[med-svn] [mesquite] 01/02: Imported Upstream version 3.04+dfsg

Andreas Tille tille at debian.org
Thu Mar 24 22:04:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository mesquite.

commit 00d77de5067935e712b62a52016c2ebad542768e
Author: Andreas Tille <tille at debian.org>
Date:   Thu Mar 24 23:00:19 2016 +0100

    Imported Upstream version 3.04+dfsg
---
 .classpath                                         |   17 +
 .gitignore                                         |   38 +
 .project                                           |   17 +
 Additional Files/classpaths.xml                    |    4 +
 Additional Files/jarFileMaking.txt                 |    3 +
 Additional Files/menuSquares.txt                   |    2 +
 Additional Files/preparingMesquite.html            |   54 +
 Additional Files/receipts.xml                      |   18 +
 LICENSE                                            |  165 +
 LibrarySource/JSci/GlobalSettings.java             |   16 +
 LibrarySource/JSci/Version.java                    |   87 +
 LibrarySource/JSci/maths/AbstractMath.java         |   13 +
 LibrarySource/JSci/maths/ExtraMath.java            |  107 +
 LibrarySource/JSci/maths/NumericalConstants.java   |   31 +
 LibrarySource/JSci/maths/SpecialMath.java          | 1535 +++++
 .../JSci/maths/statistics/BetaDistribution.java    |   68 +
 .../maths/statistics/BinomialDistribution.java     |   82 +
 .../JSci/maths/statistics/CauchyDistribution.java  |   67 +
 .../JSci/maths/statistics/ChiSqrDistribution.java  |   58 +
 .../maths/statistics/ExponentialDistribution.java  |   81 +
 .../JSci/maths/statistics/FDistribution.java       |   80 +
 .../JSci/maths/statistics/GammaDistribution.java   |   79 +
 .../maths/statistics/GeometricDistribution.java    |   69 +
 .../maths/statistics/LognormalDistribution.java    |   62 +
 .../JSci/maths/statistics/NormalDistribution.java  |  105 +
 .../JSci/maths/statistics/OutOfRangeException.java |   22 +
 .../JSci/maths/statistics/ParetoDistribution.java  |   78 +
 .../JSci/maths/statistics/PoissonDistribution.java |   72 +
 .../maths/statistics/ProbabilityDistribution.java  |   81 +
 .../JSci/maths/statistics/TDistribution.java       |   63 +
 .../JSci/maths/statistics/WeibullDistribution.java |   70 +
 LibrarySource/Jama/CholeskyDecomposition.java      |  199 +
 LibrarySource/Jama/EigenvalueDecomposition.java    |  956 +++
 LibrarySource/Jama/LUDecomposition.java            |  312 +
 LibrarySource/Jama/Matrix.java                     | 1046 ++++
 LibrarySource/Jama/QRDecomposition.java            |  219 +
 LibrarySource/Jama/SingularValueDecomposition.java |  540 ++
 .../Jama/examples/MagicSquareExample.java          |  164 +
 LibrarySource/Jama/test/TestMatrix.java            |  944 +++
 LibrarySource/Jama/util/Maths.java                 |   21 +
 LibrarySource/com/lowagie/text/Anchor.java         |  366 ++
 LibrarySource/com/lowagie/text/Annotation.java     |  727 +++
 .../com/lowagie/text/BadElementException.java      |   89 +
 LibrarySource/com/lowagie/text/Cell.java           | 1006 ++++
 LibrarySource/com/lowagie/text/Chapter.java        |  156 +
 LibrarySource/com/lowagie/text/Chunk.java          |  788 +++
 LibrarySource/com/lowagie/text/DocListener.java    |  182 +
 LibrarySource/com/lowagie/text/DocWriter.java      |  510 ++
 LibrarySource/com/lowagie/text/Document.java       |  916 +++
 .../com/lowagie/text/DocumentException.java        |  186 +
 LibrarySource/com/lowagie/text/Element.java        |  319 +
 .../com/lowagie/text/ElementListener.java          |   75 +
 LibrarySource/com/lowagie/text/ElementTags.java    |  461 ++
 LibrarySource/com/lowagie/text/Entities.java       |  388 ++
 .../com/lowagie/text/ExceptionConverter.java       |  135 +
 LibrarySource/com/lowagie/text/Font.java           |  752 +++
 LibrarySource/com/lowagie/text/FontFactory.java    |  661 +++
 LibrarySource/com/lowagie/text/Graphic.java        |  277 +
 LibrarySource/com/lowagie/text/GreekList.java      |  141 +
 LibrarySource/com/lowagie/text/Header.java         |   98 +
 LibrarySource/com/lowagie/text/HeaderFooter.java   |  206 +
 LibrarySource/com/lowagie/text/Image.java          | 1892 ++++++
 LibrarySource/com/lowagie/text/ImgCCITT.java       |  146 +
 LibrarySource/com/lowagie/text/ImgPostscript.java  |  220 +
 LibrarySource/com/lowagie/text/ImgRaw.java         |   97 +
 LibrarySource/com/lowagie/text/ImgTemplate.java    |   91 +
 LibrarySource/com/lowagie/text/ImgWMF.java         |  190 +
 LibrarySource/com/lowagie/text/Jpeg.java           |  350 ++
 LibrarySource/com/lowagie/text/List.java           |  549 ++
 LibrarySource/com/lowagie/text/ListItem.java       |  292 +
 .../com/lowagie/text/MarkupAttributes.java         |  102 +
 LibrarySource/com/lowagie/text/Meta.java           |  263 +
 LibrarySource/com/lowagie/text/PageSize.java       |  153 +
 LibrarySource/com/lowagie/text/Paragraph.java      |  517 ++
 LibrarySource/com/lowagie/text/Phrase.java         |  595 ++
 LibrarySource/com/lowagie/text/Rectangle.java      |  869 +++
 LibrarySource/com/lowagie/text/RomanList.java      |  291 +
 LibrarySource/com/lowagie/text/Row.java            |  470 ++
 LibrarySource/com/lowagie/text/Section.java        |  660 +++
 LibrarySource/com/lowagie/text/SpecialSymbol.java  |  214 +
 LibrarySource/com/lowagie/text/SplitCharacter.java |   99 +
 LibrarySource/com/lowagie/text/StringCompare.java  |   77 +
 LibrarySource/com/lowagie/text/Table.java          | 1952 +++++++
 .../com/lowagie/text/TextElementArray.java         |   75 +
 LibrarySource/com/lowagie/text/Watermark.java      |  123 +
 .../com/lowagie/text/ZapfDingbatsList.java         |  119 +
 .../com/lowagie/text/ZapfDingbatsNumberList.java   |  132 +
 .../com/lowagie/text/html/HtmlEncoder.java         |  211 +
 LibrarySource/com/lowagie/text/html/HtmlTags.java  |  331 ++
 .../com/lowagie/text/html/HtmlWriter.java          | 1084 ++++
 .../text/html/simpleparser/ChainedProperties.java  |  127 +
 .../text/html/simpleparser/FactoryProperties.java  |  174 +
 .../lowagie/text/html/simpleparser/HTMLWorker.java |  500 ++
 .../lowagie/text/html/simpleparser/IncCell.java    |  124 +
 .../lowagie/text/html/simpleparser/IncTable.java   |  122 +
 .../lowagie/text/html/simpleparser/StyleSheet.java |  112 +
 .../com/lowagie/text/markup/MarkupParser.java      |  567 ++
 .../com/lowagie/text/markup/MarkupTags.java        |  233 +
 .../com/lowagie/text/pdf/ArabicLigaturizer.java    |  772 +++
 .../com/lowagie/text/pdf/AsianFontMapper.java      |  104 +
 .../lowagie/text/pdf/BadPdfFormatException.java    |   86 +
 LibrarySource/com/lowagie/text/pdf/BaseField.java  |  686 +++
 LibrarySource/com/lowagie/text/pdf/BaseFont.java   | 1094 ++++
 LibrarySource/com/lowagie/text/pdf/BidiLine.java   |  915 +++
 LibrarySource/com/lowagie/text/pdf/BidiOrder.java  | 1241 ++++
 LibrarySource/com/lowagie/text/pdf/ByteBuffer.java |  597 ++
 LibrarySource/com/lowagie/text/pdf/CFFFont.java    | 1184 ++++
 .../com/lowagie/text/pdf/CFFFontSubset.java        | 1633 ++++++
 LibrarySource/com/lowagie/text/pdf/CJKFont.java    |  626 ++
 LibrarySource/com/lowagie/text/pdf/CMYKColor.java  |  118 +
 .../com/lowagie/text/pdf/ColorDetails.java         |  102 +
 LibrarySource/com/lowagie/text/pdf/ColumnText.java | 1420 +++++
 .../com/lowagie/text/pdf/DefaultFontMapper.java    |  309 +
 .../com/lowagie/text/pdf/DocumentFont.java         |  413 ++
 .../com/lowagie/text/pdf/EnumerateTTC.java         |  119 +
 .../com/lowagie/text/pdf/ExtendedColor.java        |  122 +
 .../com/lowagie/text/pdf/ExtraEncoding.java        |   74 +
 LibrarySource/com/lowagie/text/pdf/FdfReader.java  |  214 +
 .../com/lowagie/text/pdf/FontDetails.java          |  279 +
 LibrarySource/com/lowagie/text/pdf/FontMapper.java |   81 +
 .../com/lowagie/text/pdf/FontSelector.java         |  124 +
 LibrarySource/com/lowagie/text/pdf/GlyphList.java  | 2200 +++++++
 LibrarySource/com/lowagie/text/pdf/GrayColor.java  |   75 +
 .../com/lowagie/text/pdf/HyphenationAuto.java      |  126 +
 .../com/lowagie/text/pdf/HyphenationEvent.java     |   79 +
 .../com/lowagie/text/pdf/IntHashtable.java         |  339 ++
 LibrarySource/com/lowagie/text/pdf/LZWDecoder.java |  232 +
 .../com/lowagie/text/pdf/MultiColumnText.java      |  504 ++
 .../com/lowagie/text/pdf/OutputStreamCounter.java  |  170 +
 .../com/lowagie/text/pdf/PRIndirectReference.java  |  103 +
 LibrarySource/com/lowagie/text/pdf/PRStream.java   |  229 +
 .../com/lowagie/text/pdf/PRTokeniser.java          |  587 ++
 .../com/lowagie/text/pdf/PageResources.java        |  175 +
 .../com/lowagie/text/pdf/PatternColor.java         |   71 +
 .../com/lowagie/text/pdf/PdfAcroForm.java          |  744 +++
 LibrarySource/com/lowagie/text/pdf/PdfAction.java  |  558 ++
 .../com/lowagie/text/pdf/PdfAnnotation.java        |  741 +++
 .../com/lowagie/text/pdf/PdfAppearance.java        |  151 +
 LibrarySource/com/lowagie/text/pdf/PdfArray.java   |  223 +
 LibrarySource/com/lowagie/text/pdf/PdfBoolean.java |  130 +
 .../com/lowagie/text/pdf/PdfBorderArray.java       |   82 +
 .../com/lowagie/text/pdf/PdfBorderDictionary.java  |  100 +
 LibrarySource/com/lowagie/text/pdf/PdfCell.java    |  883 +++
 LibrarySource/com/lowagie/text/pdf/PdfChunk.java   |  782 +++
 LibrarySource/com/lowagie/text/pdf/PdfColor.java   |   80 +
 .../com/lowagie/text/pdf/PdfContentByte.java       | 2728 +++++++++
 .../com/lowagie/text/pdf/PdfContents.java          |  147 +
 .../com/lowagie/text/pdf/PdfDashPattern.java       |  144 +
 LibrarySource/com/lowagie/text/pdf/PdfDate.java    |  190 +
 .../com/lowagie/text/pdf/PdfDestination.java       |  221 +
 .../com/lowagie/text/pdf/PdfDictionary.java        |  315 +
 .../com/lowagie/text/pdf/PdfDocument.java          | 2972 ++++++++++
 .../com/lowagie/text/pdf/PdfEncodings.java         |  717 +++
 .../com/lowagie/text/pdf/PdfEncryption.java        |  363 ++
 .../com/lowagie/text/pdf/PdfEncryptionStream.java  |   85 +
 .../com/lowagie/text/pdf/PdfException.java         |   86 +
 .../com/lowagie/text/pdf/PdfFileSpecification.java |  188 +
 LibrarySource/com/lowagie/text/pdf/PdfFont.java    |  189 +
 .../com/lowagie/text/pdf/PdfFormField.java         |  353 ++
 .../com/lowagie/text/pdf/PdfFormXObject.java       |  105 +
 .../com/lowagie/text/pdf/PdfFunction.java          |  143 +
 LibrarySource/com/lowagie/text/pdf/PdfGState.java  |  144 +
 .../com/lowagie/text/pdf/PdfGraphics2D.java        | 1423 +++++
 .../com/lowagie/text/pdf/PdfICCBased.java          |   88 +
 LibrarySource/com/lowagie/text/pdf/PdfImage.java   |  281 +
 .../com/lowagie/text/pdf/PdfImportedPage.java      |  150 +
 .../com/lowagie/text/pdf/PdfIndirectObject.java    |  171 +
 .../com/lowagie/text/pdf/PdfIndirectReference.java |  129 +
 LibrarySource/com/lowagie/text/pdf/PdfLayer.java   |  302 +
 .../com/lowagie/text/pdf/PdfLayerMembership.java   |  140 +
 LibrarySource/com/lowagie/text/pdf/PdfLine.java    |  476 ++
 LibrarySource/com/lowagie/text/pdf/PdfLister.java  |  187 +
 LibrarySource/com/lowagie/text/pdf/PdfLiteral.java |  111 +
 .../com/lowagie/text/pdf/PdfMediaClipData.java     |   64 +
 LibrarySource/com/lowagie/text/pdf/PdfName.java    | 1093 ++++
 .../com/lowagie/text/pdf/PdfNameTree.java          |  165 +
 LibrarySource/com/lowagie/text/pdf/PdfNull.java    |   83 +
 LibrarySource/com/lowagie/text/pdf/PdfNumber.java  |  159 +
 LibrarySource/com/lowagie/text/pdf/PdfOCG.java     |   67 +
 .../com/lowagie/text/pdf/PdfOCProperties.java      |   59 +
 LibrarySource/com/lowagie/text/pdf/PdfObject.java  |  371 ++
 LibrarySource/com/lowagie/text/pdf/PdfOutline.java |  542 ++
 LibrarySource/com/lowagie/text/pdf/PdfPCell.java   |  697 +++
 .../com/lowagie/text/pdf/PdfPCellEvent.java        |   74 +
 LibrarySource/com/lowagie/text/pdf/PdfPRow.java    |  530 ++
 .../com/lowagie/text/pdf/PdfPSXObject.java         |   99 +
 LibrarySource/com/lowagie/text/pdf/PdfPTable.java  | 1014 ++++
 .../com/lowagie/text/pdf/PdfPTableEvent.java       |   95 +
 LibrarySource/com/lowagie/text/pdf/PdfPage.java    |  198 +
 .../com/lowagie/text/pdf/PdfPageElement.java       |   78 +
 .../com/lowagie/text/pdf/PdfPageEvent.java         |  191 +
 .../com/lowagie/text/pdf/PdfPageEventHelper.java   |  203 +
 .../com/lowagie/text/pdf/PdfPageLabels.java        |  192 +
 LibrarySource/com/lowagie/text/pdf/PdfPages.java   |  206 +
 LibrarySource/com/lowagie/text/pdf/PdfPattern.java |   84 +
 .../com/lowagie/text/pdf/PdfPatternPainter.java    |  391 ++
 .../com/lowagie/text/pdf/PdfPrinterGraphics2D.java |   73 +
 LibrarySource/com/lowagie/text/pdf/PdfReader.java  | 3052 ++++++++++
 .../com/lowagie/text/pdf/PdfReaderInstance.java    |  183 +
 .../com/lowagie/text/pdf/PdfRectangle.java         |  277 +
 .../com/lowagie/text/pdf/PdfRendition.java         |   62 +
 .../com/lowagie/text/pdf/PdfResources.java         |   91 +
 LibrarySource/com/lowagie/text/pdf/PdfShading.java |  262 +
 .../com/lowagie/text/pdf/PdfShadingPattern.java    |  120 +
 .../com/lowagie/text/pdf/PdfSpotColor.java         |  132 +
 LibrarySource/com/lowagie/text/pdf/PdfStream.java  |  287 +
 LibrarySource/com/lowagie/text/pdf/PdfString.java  |  236 +
 LibrarySource/com/lowagie/text/pdf/PdfTable.java   |  316 +
 .../com/lowagie/text/pdf/PdfTemplate.java          |  267 +
 .../com/lowagie/text/pdf/PdfTextArray.java         |   99 +
 .../com/lowagie/text/pdf/PdfTransition.java        |  253 +
 .../com/lowagie/text/pdf/PdfTransparencyGroup.java |   85 +
 LibrarySource/com/lowagie/text/pdf/PdfWriter.java  | 2542 ++++++++
 .../lowagie/text/pdf/PdfXConformanceException.java |   70 +
 LibrarySource/com/lowagie/text/pdf/Pfm2afm.java    |  774 +++
 .../com/lowagie/text/pdf/PushbuttonField.java      |  602 ++
 .../com/lowagie/text/pdf/RadioCheckField.java      |  416 ++
 .../lowagie/text/pdf/RandomAccessFileOrArray.java  |  594 ++
 .../com/lowagie/text/pdf/SequenceList.java         |  316 +
 .../com/lowagie/text/pdf/ShadingColor.java         |   75 +
 .../com/lowagie/text/pdf/SimpleBookmark.java       |  745 +++
 .../lowagie/text/pdf/SimpleNamedDestination.java   |  335 ++
 .../com/lowagie/text/pdf/SimpleXMLDocHandler.java  |   80 +
 .../text/pdf/SimpleXMLDocHandlerComment.java       |   59 +
 .../com/lowagie/text/pdf/SimpleXMLParser.java      | 1177 ++++
 LibrarySource/com/lowagie/text/pdf/SpotColor.java  |   84 +
 LibrarySource/com/lowagie/text/pdf/TextField.java  |  556 ++
 .../com/lowagie/text/pdf/TrueTypeFont.java         | 1300 +++++
 .../com/lowagie/text/pdf/TrueTypeFontSubSet.java   |  421 ++
 .../com/lowagie/text/pdf/TrueTypeFontUnicode.java  |  473 ++
 LibrarySource/com/lowagie/text/pdf/Type1Font.java  |  808 +++
 .../com/lowagie/text/pdf/VerticalText.java         |  350 ++
 LibrarySource/com/lowagie/text/pdf/XfdfReader.java |  208 +
 .../com/lowagie/text/pdf/codec/BmpImage.java       | 1307 +++++
 .../com/lowagie/text/pdf/codec/CCITTG4Encoder.java |  509 ++
 .../com/lowagie/text/pdf/codec/GifImage.java       |  592 ++
 .../com/lowagie/text/pdf/codec/PngImage.java       |  989 ++++
 .../com/lowagie/text/pdf/codec/TIFFConstants.java  |  297 +
 .../com/lowagie/text/pdf/codec/TIFFDirectory.java  |  657 +++
 .../com/lowagie/text/pdf/codec/TIFFFaxDecoder.java | 1480 +++++
 .../com/lowagie/text/pdf/codec/TIFFField.java      |  472 ++
 .../com/lowagie/text/pdf/codec/TIFFLZWDecoder.java |  255 +
 .../com/lowagie/text/pdf/codec/TiffImage.java      |  477 ++
 .../text/pdf/codec/postscript/JavaCharStream.java  |  548 ++
 .../text/pdf/codec/postscript/MetaDoPS.java        |   98 +
 .../text/pdf/codec/postscript/PACommand.java       |   22 +
 .../text/pdf/codec/postscript/PAContext.java       | 2053 +++++++
 .../text/pdf/codec/postscript/PAEngine.java        |  144 +
 .../text/pdf/codec/postscript/PAParser.java        |  305 +
 .../pdf/codec/postscript/PAParserConstants.java    |   49 +
 .../pdf/codec/postscript/PAParserTokenManager.java |  803 +++
 .../text/pdf/codec/postscript/PAPencil.java        |  401 ++
 .../lowagie/text/pdf/codec/postscript/PAToken.java |   70 +
 .../pdf/codec/postscript/PainterException.java     |   23 +
 .../text/pdf/codec/postscript/ParseException.java  |  193 +
 .../lowagie/text/pdf/codec/postscript/Token.java   |   82 +
 .../text/pdf/codec/postscript/TokenMgrError.java   |  134 +
 .../lowagie/text/pdf/codec/postscript/paparser.jj  |  290 +
 .../com/lowagie/text/pdf/codec/wmf/InputMeta.java  |  114 +
 .../com/lowagie/text/pdf/codec/wmf/MetaBrush.java  |   95 +
 .../com/lowagie/text/pdf/codec/wmf/MetaDo.java     |  760 +++
 .../com/lowagie/text/pdf/codec/wmf/MetaFont.java   |  206 +
 .../com/lowagie/text/pdf/codec/wmf/MetaObject.java |   72 +
 .../com/lowagie/text/pdf/codec/wmf/MetaPen.java    |   92 +
 .../com/lowagie/text/pdf/codec/wmf/MetaState.java  |  367 ++
 .../com/lowagie/text/pdf/fonts/Courier-Bold.afm    |  343 ++
 .../lowagie/text/pdf/fonts/Courier-BoldOblique.afm |  343 ++
 .../com/lowagie/text/pdf/fonts/Courier-Oblique.afm |  343 ++
 .../com/lowagie/text/pdf/fonts/Courier.afm         |  343 ++
 .../text/pdf/fonts/FontsResourceAnchor.java        |   62 +
 .../com/lowagie/text/pdf/fonts/Helvetica-Bold.afm  | 2828 +++++++++
 .../text/pdf/fonts/Helvetica-BoldOblique.afm       | 2828 +++++++++
 .../lowagie/text/pdf/fonts/Helvetica-Oblique.afm   | 3052 ++++++++++
 .../com/lowagie/text/pdf/fonts/Helvetica.afm       | 3052 ++++++++++
 .../com/lowagie/text/pdf/fonts/Symbol.afm          |  214 +
 .../com/lowagie/text/pdf/fonts/Times-Bold.afm      | 2589 +++++++++
 .../lowagie/text/pdf/fonts/Times-BoldItalic.afm    | 2385 ++++++++
 .../com/lowagie/text/pdf/fonts/Times-Italic.afm    | 2668 +++++++++
 .../com/lowagie/text/pdf/fonts/Times-Roman.afm     | 2420 ++++++++
 .../com/lowagie/text/pdf/fonts/ZapfDingbats.afm    |  226 +
 .../lowagie/text/pdf/hyphenation/ByteVector.java   |  125 +
 .../lowagie/text/pdf/hyphenation/CharVector.java   |  135 +
 .../com/lowagie/text/pdf/hyphenation/Hyphen.java   |   69 +
 .../lowagie/text/pdf/hyphenation/Hyphenation.java  |   84 +
 .../text/pdf/hyphenation/HyphenationException.java |   29 +
 .../text/pdf/hyphenation/HyphenationTree.java      |  462 ++
 .../lowagie/text/pdf/hyphenation/Hyphenator.java   |  186 +
 .../text/pdf/hyphenation/PatternConsumer.java      |   56 +
 .../text/pdf/hyphenation/SimplePatternParser.java  |  278 +
 .../lowagie/text/pdf/hyphenation/TernaryTree.java  |  668 +++
 LibrarySource/pal/alignment/AbstractAlignment.java |  177 +
 LibrarySource/pal/alignment/Alignment.java         |   77 +
 .../pal/alignment/AlignmentParseException.java     |   26 +
 LibrarySource/pal/alignment/AlignmentUtils.java    |  610 ++
 .../pal/alignment/AminoAcidAlignment.java          |  102 +
 .../pal/alignment/BootstrappedAlignment.java       |   75 +
 LibrarySource/pal/alignment/CodonAlignment.java    |  103 +
 .../pal/alignment/ConcatenatedAlignment.java       |   89 +
 .../pal/alignment/GapBalancedAlignment.java        |  230 +
 LibrarySource/pal/alignment/JumbledAlignment.java  |   78 +
 LibrarySource/pal/alignment/ReadAlignment.java     |  410 ++
 LibrarySource/pal/alignment/SimpleAlignment.java   |  181 +
 LibrarySource/pal/alignment/SitePattern.java       |  253 +
 LibrarySource/pal/alignment/StrippedAlignment.java |  213 +
 LibrarySource/pal/alignment/makefile               |   42 +
 LibrarySource/pal/alignment/package.html           |    8 +
 .../pal/coalescent/CoalescentException.java        |   34 +
 .../pal/coalescent/CoalescentIntervals.java        |  405 ++
 .../pal/coalescent/CoalescentSimulator.java        |   49 +
 LibrarySource/pal/coalescent/CoalescentTree.java   |   23 +
 LibrarySource/pal/coalescent/ConstExpGrowth.java   |  416 ++
 .../pal/coalescent/ConstantPopulation.java         |  236 +
 .../pal/coalescent/DemographicClockTree.java       |  110 +
 LibrarySource/pal/coalescent/DemographicModel.java |  189 +
 LibrarySource/pal/coalescent/DemographicTree.java  |   27 +
 .../pal/coalescent/ExpandingPopulation.java        |  287 +
 .../pal/coalescent/ExponentialGrowth.java          |  285 +
 .../pal/coalescent/IntervalsExtractor.java         |  237 +
 LibrarySource/pal/coalescent/SkylinePlot.java      |  415 ++
 LibrarySource/pal/coalescent/makefile              |   42 +
 LibrarySource/pal/coalescent/package.html          |    5 +
 LibrarySource/pal/datatype/AminoAcids.java         |  164 +
 LibrarySource/pal/datatype/CodonTable.java         |   56 +
 LibrarySource/pal/datatype/CodonTableFactory.java  |  271 +
 LibrarySource/pal/datatype/CodonTableUtils.java    |   76 +
 LibrarySource/pal/datatype/Codons.java             |   73 +
 LibrarySource/pal/datatype/DataType.java           |  103 +
 LibrarySource/pal/datatype/DataTypeUtils.java      |   81 +
 LibrarySource/pal/datatype/GeneralizedCodons.java  |  223 +
 LibrarySource/pal/datatype/IUPACNucleotides.java   |  148 +
 LibrarySource/pal/datatype/IUPACPenaltyTable.java  |   67 +
 LibrarySource/pal/datatype/Nucleotides.java        |  151 +
 LibrarySource/pal/datatype/SimpleDataType.java     |   60 +
 LibrarySource/pal/datatype/StateRemover.java       |   91 +
 .../pal/datatype/TransitionPenaltyTable.java       |   25 +
 LibrarySource/pal/datatype/TwoStates.java          |   83 +
 LibrarySource/pal/datatype/makefile                |   42 +
 LibrarySource/pal/datatype/package.html            |    6 +
 .../pal/distance/AlignmentDistanceMatrix.java      |  109 +
 LibrarySource/pal/distance/DistanceMatrix.java     |  286 +
 .../pal/distance/DistanceMatrixUtils.java          |  121 +
 .../pal/distance/DistanceParseException.java       |   26 +
 .../pal/distance/JukesCantorDistanceMatrix.java    |  130 +
 LibrarySource/pal/distance/PairwiseDistance.java   |  213 +
 LibrarySource/pal/distance/ReadDistanceMatrix.java |   88 +
 .../pal/distance/SUPGMADistanceMatrix.java         |   48 +
 .../pal/distance/SequencePairLikelihood.java       |  168 +
 LibrarySource/pal/distance/makefile                |   42 +
 LibrarySource/pal/distance/package.html            |    8 +
 LibrarySource/pal/eval/ChiSquareValue.java         |  196 +
 .../pal/eval/DemographicLikelihoodValue.java       |   58 +
 LibrarySource/pal/eval/DemographicValue.java       |  178 +
 LibrarySource/pal/eval/LikelihoodValue.java        | 1358 +++++
 LibrarySource/pal/eval/ModelParameters.java        |  236 +
 LibrarySource/pal/eval/makefile                    |   42 +
 LibrarySource/pal/eval/package.html                |    7 +
 LibrarySource/pal/gui/CircularGraphics.java        |  213 +
 LibrarySource/pal/gui/Painter.java                 |   26 +
 LibrarySource/pal/gui/PositionedNode.java          |   80 +
 LibrarySource/pal/gui/TreeComponent.java           |  152 +
 LibrarySource/pal/gui/TreePainter.java             |  247 +
 LibrarySource/pal/gui/TreePainterCircular.java     |  142 +
 LibrarySource/pal/gui/TreePainterNormal.java       |  168 +
 LibrarySource/pal/gui/makefile                     |   42 +
 LibrarySource/pal/gui/package.html                 |    5 +
 LibrarySource/pal/io/FormattedInput.java           |  362 ++
 LibrarySource/pal/io/FormattedOutput.java          |  312 +
 LibrarySource/pal/io/InputSource.java              |   81 +
 LibrarySource/pal/io/OutputTarget.java             |  102 +
 LibrarySource/pal/io/makefile                      |   42 +
 LibrarySource/pal/io/package.html                  |    7 +
 LibrarySource/pal/makefile                         |   52 +
 LibrarySource/pal/math/Binomial.java               |   81 +
 LibrarySource/pal/math/BoundsCheckedFunction.java  |   96 +
 .../pal/math/ConjugateDirectionSearch.java         |  953 +++
 .../pal/math/ConjugateGradientSearch.java          |  492 ++
 LibrarySource/pal/math/DifferentialEvolution.java  |  371 ++
 LibrarySource/pal/math/ErrorFunction.java          |  104 +
 LibrarySource/pal/math/GammaFunction.java          |  205 +
 LibrarySource/pal/math/GeneralizedDEOptimizer.java |   51 +
 LibrarySource/pal/math/LineFunction.java           |  295 +
 LibrarySource/pal/math/MFWithGradient.java         |   39 +
 LibrarySource/pal/math/MachineAccuracy.java        |   45 +
 LibrarySource/pal/math/MathUtils.java              |   67 +
 LibrarySource/pal/math/MersenneTwisterFast.java    |  771 +++
 LibrarySource/pal/math/MultivariateFunction.java   |   54 +
 LibrarySource/pal/math/MultivariateMinimum.java    |  218 +
 LibrarySource/pal/math/NumericalDerivative.java    |  138 +
 LibrarySource/pal/math/OrthogonalLineFunction.java |  102 +
 LibrarySource/pal/math/OrthogonalSearch.java       |   80 +
 LibrarySource/pal/math/UnivariateFunction.java     |   42 +
 LibrarySource/pal/math/UnivariateMinimum.java      |  479 ++
 LibrarySource/pal/math/UrnModel.java               |  121 +
 LibrarySource/pal/math/makefile                    |   42 +
 LibrarySource/pal/math/package.html                |    7 +
 LibrarySource/pal/mep/ConstantMutationRate.java    |  198 +
 LibrarySource/pal/mep/MutationRateModel.java       |  113 +
 LibrarySource/pal/mep/SteppedMutationRate.java     |  374 ++
 LibrarySource/pal/mep/WindowedMutationRate.java    |  310 +
 LibrarySource/pal/mep/makefile                     |   42 +
 LibrarySource/pal/mep/package.html                 |    6 +
 LibrarySource/pal/misc/BranchLimits.java           |   40 +
 LibrarySource/pal/misc/GeneralFunction.java        |   22 +
 LibrarySource/pal/misc/IdGenerator.java            |   42 +
 LibrarySource/pal/misc/IdGroup.java                |   41 +
 LibrarySource/pal/misc/Identifier.java             |   67 +
 LibrarySource/pal/misc/Nameable.java               |   35 +
 LibrarySource/pal/misc/Parameterized.java          |   85 +
 LibrarySource/pal/misc/ParameterizedDouble.java    |  144 +
 LibrarySource/pal/misc/Product.java                |   32 +
 LibrarySource/pal/misc/ReleaseInfo.java            |   31 +
 LibrarySource/pal/misc/Report.java                 |   30 +
 LibrarySource/pal/misc/SimpleIdGroup.java          |  169 +
 LibrarySource/pal/misc/SimpleSummarizable.java     |   56 +
 LibrarySource/pal/misc/Sum.java                    |   33 +
 LibrarySource/pal/misc/SumToOneWeighting.java      |  198 +
 LibrarySource/pal/misc/Summarizable.java           |   23 +
 LibrarySource/pal/misc/TimeOrderCharacterData.java |  387 ++
 LibrarySource/pal/misc/TimeStamp.java              |   66 +
 LibrarySource/pal/misc/UniformWeighting.java       |  124 +
 LibrarySource/pal/misc/Units.java                  |   24 +
 LibrarySource/pal/misc/Utils.java                  |  118 +
 LibrarySource/pal/misc/WeightedFunction.java       |   51 +
 LibrarySource/pal/misc/Weighting.java              |   26 +
 LibrarySource/pal/misc/makefile                    |   42 +
 LibrarySource/pal/misc/package.html                |    5 +
 .../pal/statistics/BootstrapStatistics.java        |  172 +
 .../pal/statistics/ChiSquareDistribution.java      |   97 +
 LibrarySource/pal/statistics/ChiSquareTest.java    |  103 +
 .../pal/statistics/DiscreteStatistics.java         |  234 +
 .../pal/statistics/ExponentialDistribution.java    |  100 +
 .../pal/statistics/GammaDistribution.java          |  180 +
 .../pal/statistics/KishinoHasegawaTest.java        |  202 +
 .../pal/statistics/LikelihoodRatioTest.java        |   41 +
 LibrarySource/pal/statistics/ModelSupport.java     |  341 ++
 .../pal/statistics/NormalDistribution.java         |   99 +
 .../pal/statistics/ParetoDistribution.java         |  122 +
 .../pal/statistics/PenalizedLikelihood.java        |   71 +
 .../pal/statistics/ShimodairaHasegawaTest.java     |  262 +
 LibrarySource/pal/statistics/makefile              |   42 +
 LibrarySource/pal/statistics/package.html          |    8 +
 .../pal/substmodel/AbstractRateMatrix.java         |  278 +
 LibrarySource/pal/substmodel/AminoAcidModel.java   |  192 +
 LibrarySource/pal/substmodel/AminoAcidModelID.java |   36 +
 LibrarySource/pal/substmodel/BLOSUM62.java         |  195 +
 LibrarySource/pal/substmodel/CPREV.java            |  210 +
 LibrarySource/pal/substmodel/CodonModel.java       |   89 +
 LibrarySource/pal/substmodel/Dayhoff.java          |  198 +
 LibrarySource/pal/substmodel/F81.java              |  104 +
 LibrarySource/pal/substmodel/F84.java              |  168 +
 LibrarySource/pal/substmodel/GTR.java              |  227 +
 LibrarySource/pal/substmodel/GammaRates.java       |  133 +
 LibrarySource/pal/substmodel/HKY.java              |  140 +
 LibrarySource/pal/substmodel/InvariableSites.java  |  126 +
 LibrarySource/pal/substmodel/JTT.java              |  197 +
 LibrarySource/pal/substmodel/MTREV24.java          |  196 +
 .../pal/substmodel/MatrixExponential.java          |  894 +++
 LibrarySource/pal/substmodel/NucleotideModel.java  |  132 +
 .../pal/substmodel/NucleotideModelID.java          |   34 +
 LibrarySource/pal/substmodel/RateDistribution.java |   92 +
 LibrarySource/pal/substmodel/RateMatrix.java       |   86 +
 LibrarySource/pal/substmodel/RateMatrixUtils.java  |   64 +
 .../pal/substmodel/SubstitutionModel.java          |  288 +
 LibrarySource/pal/substmodel/TN.java               |  183 +
 .../pal/substmodel/TransitionProbability.java      |   48 +
 LibrarySource/pal/substmodel/TwoStateModel.java    |  115 +
 LibrarySource/pal/substmodel/UniformRate.java      |   84 +
 LibrarySource/pal/substmodel/VT.java               |  210 +
 LibrarySource/pal/substmodel/WAG.java              |  210 +
 LibrarySource/pal/substmodel/YangCodonModel.java   |  276 +
 LibrarySource/pal/substmodel/makefile              |   42 +
 LibrarySource/pal/substmodel/package.html          |    9 +
 LibrarySource/pal/tree/ClockTree.java              |  143 +
 LibrarySource/pal/tree/DatedTipsClockTree.java     |  446 ++
 LibrarySource/pal/tree/LogParameterizedTree.java   |  100 +
 LibrarySource/pal/tree/MutationRateModelTree.java  |  175 +
 LibrarySource/pal/tree/NeighborJoiningTree.java    |  209 +
 LibrarySource/pal/tree/Node.java                   |  138 +
 LibrarySource/pal/tree/NodeFactory.java            |   40 +
 LibrarySource/pal/tree/NodeUtils.java              |  629 ++
 LibrarySource/pal/tree/ParameterizedTree.java      |  112 +
 LibrarySource/pal/tree/ReadTree.java               |  157 +
 LibrarySource/pal/tree/SUPGMATree.java             |  102 +
 LibrarySource/pal/tree/SimpleNode.java             |  448 ++
 LibrarySource/pal/tree/SimpleTree.java             |  274 +
 LibrarySource/pal/tree/SimulatedAlignment.java     |  211 +
 LibrarySource/pal/tree/SplitSystem.java            |  127 +
 LibrarySource/pal/tree/SplitUtils.java             |  169 +
 LibrarySource/pal/tree/Tree.java                   |   72 +
 LibrarySource/pal/tree/TreeDistanceMatrix.java     |  135 +
 LibrarySource/pal/tree/TreeParseException.java     |   26 +
 LibrarySource/pal/tree/TreeUtils.java              | 1042 ++++
 LibrarySource/pal/tree/UPGMATree.java              |  201 +
 LibrarySource/pal/tree/UnconstrainedTree.java      |  110 +
 LibrarySource/pal/tree/makefile                    |   42 +
 LibrarySource/pal/tree/package.html                |    8 +
 LibrarySource/pal/util/Comparable.java             |   36 +
 LibrarySource/pal/util/ComparableDouble.java       |   50 +
 LibrarySource/pal/util/Comparator.java             |   37 +
 LibrarySource/pal/util/HeapSort.java               |  411 ++
 LibrarySource/pal/util/Log.java                    |   55 +
 LibrarySource/pal/util/Logger.java                 |   25 +
 LibrarySource/pal/util/ThreeNumberSort.java        |  237 +
 LibrarySource/pal/util/makefile                    |   42 +
 LibrarySource/pal/util/package.html                |    5 +
 README.md                                          |    4 +
 Resources/Mesquite_Start_Script.bat                |    1 +
 Resources/Mesquite_Start_Script.command            |    4 +
 Resources/documentation.html                       |   17 +
 .../examples/Ancestral_States/01-DataMatrix.nex    |  418 ++
 .../examples/Ancestral_States/02-TreeWindow.nex    |  440 ++
 .../examples/Ancestral_States/03-TraceCharPars.nex |  475 ++
 .../examples/Ancestral_States/03b-LiveUpdate.nex   |  545 ++
 .../examples/Ancestral_States/04-Equivocal.nex     |  474 ++
 .../examples/Ancestral_States/05-TreeForm.nex      |  477 ++
 .../Ancestral_States/06-ParsimonyModels.nex        |  512 ++
 .../Ancestral_States/07-EditingParsModels.nex      |  547 ++
 .../Ancestral_States/08-ParsimonyMacClade.nex      |  495 ++
 .../examples/Ancestral_States/09-Continuous.nex    |  465 ++
 .../examples/Ancestral_States/10-PlotTree.nex      |  449 ++
 .../examples/Ancestral_States/11-TraceCharMLE.nex  |  297 +
 .../examples/Ancestral_States/11b-TextView.nex     |  298 +
 .../examples/Ancestral_States/12-Mk1Likelihood.nex |  439 ++
 .../Ancestral_States/13-AsymmLikelihood.nex        |  453 ++
 .../Ancestral_States/14-AsymmEstLikelihood.nex     |  485 ++
 .../Ancestral_States/15-Mk1AsymmCompare.nex        |  527 ++
 .../Ancestral_States/15a-estimatingParameters.nex  |  228 +
 .../Ancestral_States/15aa-xiphLikelihood.nex       |  343 ++
 .../Ancestral_States/15ab-xiphStochCharMap.nex     |  329 ++
 .../Ancestral_States/15b-estimatingParameters.nex  |  288 +
 .../Ancestral_States/15b1-estimatingParameters.nex |  270 +
 .../Ancestral_States/15b2-estimatingParameters.nex |  347 ++
 .../Ancestral_States/16b-BranchLengths.nex         |  406 ++
 .../Ancestral_States/16c-TraceAllChars.nex         |  402 ++
 .../Ancestral_States/17-TraceOverTrees.nex         |  674 +++
 .../Ancestral_States/17a-TraceOverTrees.nex        | 1339 +++++
 .../Ancestral_States/18-TraceOverResolutions.nex   |  479 ++
 .../examples/Ancestral_States/19-likelihoodTot.nex |  400 ++
 .../examples/Ancestral_States/20-likelihoodToT.nex |  422 ++
 .../examples/Ancestral_States/21-likelihoodTot.nex |  426 ++
 .../Basic_Examples/basic_operation/01-basics.nex   |  129 +
 .../basic_operation/02-standardMenus.nex           |  129 +
 .../basic_operation/03-characterMatrices.nex       |  205 +
 .../basic_operation/04-treeWindow.nex              |  227 +
 .../basic_operation/04a-windowTabs.nex             |  320 +
 .../basic_operation/05-windowModes.nex             |  486 ++
 .../Basic_Examples/basic_operation/06-helpMenu.nex |  226 +
 .../Basic_Examples/basic_operation/07-moreHelp.nex |  226 +
 .../Basic_Examples/basic_operation/08-logFile.nex  |  136 +
 .../basic_operation/09-windowFonts.nex             |  209 +
 .../basic_operation/10-scripting.nex               |  402 ++
 .../Basic_Examples/basic_operation/11-newFile.nex  |   46 +
 .../basic_operation/12-fileFormats.nex             |   46 +
 .../basic_operation/13-blockOfTaxa.nex             |  198 +
 .../Basic_Examples/basic_operation/13-matrix.nex   |   40 +
 .../Basic_Examples/basic_operation/13-trees.nex    |   25 +
 .../Basic_Examples/basic_operation/14-included.nex |  254 +
 .../basic_operation/15-annotations.nex             |  225 +
 .../Basic_Examples/basic_operation/16-webLinks.nex |   47 +
 .../fubonidianImages/fubonidiaGizmoid.gif          |  Bin 0 -> 13799 bytes
 .../fubonidianImages/fubonidiaKnobble.gif          |  Bin 0 -> 44357 bytes
 .../fubonidianImages/fubonidiaZibinator.gif        |  Bin 0 -> 18117 bytes
 .../fubonidianImages/quidnubiaGizmoid.gif          |  Bin 0 -> 15117 bytes
 .../fubonidianImages/quidnubiaKnobble.gif          |  Bin 0 -> 21844 bytes
 .../fubonidianImages/quidnubiaZibinator.gif        |  Bin 0 -> 25102 bytes
 .../fubonidianImages/snorolopaGizmoid.gif          |  Bin 0 -> 15148 bytes
 .../fubonidianImages/snorolopaKnobble.gif          |  Bin 0 -> 31130 bytes
 .../fubonidianImages/snorolopaZibinator.gif        |  Bin 0 -> 18673 bytes
 .../fubonidianImages/zorabynyxGizmoid.gif          |  Bin 0 -> 16823 bytes
 .../fubonidianImages/zorabynyxKnobble.gif          |  Bin 0 -> 19467 bytes
 .../fubonidianImages/zorabynyxZibinator.gif        |  Bin 0 -> 18135 bytes
 .../Basic_Examples/characters/01-characters.nex    |  403 ++
 .../Basic_Examples/characters/02-newMatrix.nex     |   84 +
 .../Basic_Examples/characters/03-newMatrix.nex     |   92 +
 .../characters/04-characterLists.nex               |  315 +
 .../Basic_Examples/characters/05-dataEditing.nex   |  199 +
 .../examples/Basic_Examples/characters/06-fill.nex |  200 +
 .../Basic_Examples/characters/07-dataEditing.nex   |  199 +
 .../Basic_Examples/characters/08-addDelete.nex     |  200 +
 .../Basic_Examples/characters/09-copyPaste.nex     |  294 +
 .../Basic_Examples/characters/10-names.nex         |  245 +
 .../Basic_Examples/characters/11-viewingStyles.nex |  415 ++
 .../Basic_Examples/characters/11a-annotations.nex  |  229 +
 .../Basic_Examples/characters/12-continuous.nex    |  176 +
 .../characters/13-continuousItems.nex              |  156 +
 .../Basic_Examples/characters/14-partitions.nex    |  298 +
 .../Basic_Examples/characters/15-selecting.nex     |  306 +
 .../Basic_Examples/characters/16-charSources.nex   |  263 +
 .../Basic_Examples/characters/17-charSources.nex   |  287 +
 .../fubonidianImages/fubonidiaGizmoid.gif          |  Bin 0 -> 13799 bytes
 .../fubonidianImages/fubonidiaKnobble.gif          |  Bin 0 -> 44357 bytes
 .../fubonidianImages/fubonidiaZibinator.gif        |  Bin 0 -> 18117 bytes
 .../fubonidianImages/quidnubiaGizmoid.gif          |  Bin 0 -> 15117 bytes
 .../fubonidianImages/quidnubiaKnobble.gif          |  Bin 0 -> 21844 bytes
 .../fubonidianImages/quidnubiaZibinator.gif        |  Bin 0 -> 25102 bytes
 .../fubonidianImages/snorolopaGizmoid.gif          |  Bin 0 -> 15148 bytes
 .../fubonidianImages/snorolopaKnobble.gif          |  Bin 0 -> 31130 bytes
 .../fubonidianImages/snorolopaZibinator.gif        |  Bin 0 -> 18673 bytes
 .../fubonidianImages/zorabynyxGizmoid.gif          |  Bin 0 -> 16823 bytes
 .../fubonidianImages/zorabynyxKnobble.gif          |  Bin 0 -> 19467 bytes
 .../fubonidianImages/zorabynyxZibinator.gif        |  Bin 0 -> 18135 bytes
 .../examples/Basic_Examples/charts/01-charts.nex   |  307 +
 .../Basic_Examples/charts/02-histogram.nex         |  252 +
 .../Basic_Examples/charts/03-scattergram.nex       |  297 +
 .../Basic_Examples/charts/04-scattergram.nex       |  567 ++
 .../continuous/01-editContinuous.nex               |  170 +
 .../Basic_Examples/continuous/03-trace.nex         |  359 ++
 .../Basic_Examples/continuous/04-branchLengths.nex |  363 ++
 .../Basic_Examples/continuous/05-treeSearch.nex    |  322 ++
 .../examples/Basic_Examples/continuous/06-sim.nex  |  283 +
 .../Basic_Examples/continuous/07-mirrorTree.nex    |  371 ++
 .../Basic_Examples/continuous/08-plotTree.nex      |  310 +
 .../Basic_Examples/continuous/09-plotTreeSim.nex   |  332 ++
 Resources/examples/Basic_Examples/introduction.nex |   69 +
 Resources/examples/Basic_Examples/taxa/01-taxa.nex |  166 +
 .../Basic_Examples/taxa/02-addingDeleting.nex      |  166 +
 .../examples/Basic_Examples/taxa/03-partitions.nex |  178 +
 .../examples/Basic_Examples/taxa/04-partitions.nex |  348 ++
 .../examples/Basic_Examples/taxa/05-selecting.nex  |  375 ++
 .../examples/Basic_Examples/taxa/06-selecting.nex  |  392 ++
 .../examples/Basic_Examples/taxa/07-selecting.nex  |  387 ++
 .../Basic_Examples/taxa/08-multipleBlocks.nex      |  402 ++
 .../tree_manipulation/01-editingTrees.nex          |  239 +
 .../tree_manipulation/02-editingTrees.nex          |  230 +
 .../tree_manipulation/03-editingTrees.nex          |  230 +
 .../tree_manipulation/04-branchLengths.nex         |  232 +
 .../tree_manipulation/05-branchColorNames.nex      |  231 +
 .../tree_manipulation/06-branchSelection.nex       |  234 +
 .../tree_manipulation/07-storedTrees.nex           |  281 +
 .../tree_manipulation/08-listOfTrees.nex           |  160 +
 .../tree_manipulation/09-treeBlocks.nex            |  272 +
 .../tree_manipulation/10-externalTrees.nex         |  283 +
 .../tree_manipulation/10-treeFile.nex              |   30 +
 .../tree_manipulation/11-treeSources.nex           |  347 ++
 .../tree_manipulation/12-treeSources.nex           |  321 +
 .../tree_manipulation/13-instability.nex           | 1080 ++++
 .../Basic_Examples/tree_viewing/01-treeWindow.nex  |  229 +
 .../Basic_Examples/tree_viewing/02-treeForm.nex    |  231 +
 .../Basic_Examples/tree_viewing/03-drawingSize.nex |  233 +
 .../tree_viewing/04-moreTreeForms.nex              |  367 ++
 .../tree_viewing/05-moreTreeForms.nex              |  494 ++
 .../tree_viewing/06-printingTrees.nex              |  261 +
 .../tree_viewing/07-dependentWindow.nex            |  409 ++
 .../Basic_Examples/tree_viewing/08-mirrorTree.nex  |  398 ++
 .../Basic_Examples/tree_viewing/09-multiTrees.nex  |  240 +
 .../Basic_Examples/tree_viewing/10-multiTrees.nex  |  305 +
 .../Character_Simulations/00-introduction.nex      |   40 +
 .../Character_Simulations/01-modelTree.nex         |  559 ++
 .../Character_Simulations/02-gammaTest.nex         |  569 ++
 .../03-TestingTreeStructure.nex                    |  588 ++
 .../templates/GIGTRTest.template                   |   10 +
 .../templates/GTRTest.template                     |   10 +
 .../templates/GammaInvarTest.template              |   10 +
 .../templates/GammaTest.template                   |   10 +
 .../templates/TiTvTest.template                    |   10 +
 Resources/examples/Coalescence/00-introduction.nex |   53 +
 Resources/examples/Coalescence/01-coalescence.nex  |  231 +
 Resources/examples/Coalescence/02-coalescence2.nex |  215 +
 .../examples/Coalescence/03-coalescenceDepth.nex   |  180 +
 Resources/examples/Coalescence/04-associations.nex |  476 ++
 .../examples/Coalescence/05-twoPopulations.nex     |  409 ++
 .../examples/Coalescence/06-twoPopulations2.nex    |  339 ++
 Resources/examples/Coalescence/08-fluctuating.nex  |  313 +
 .../examples/Coalescence/09-genesInSpecies.nex     |  455 ++
 .../examples/Coalescence/10-speciesTreeSearch.nex  |  270 +
 .../examples/Coalescence/11-geneInSpecies2.nex     |  465 ++
 .../Coalescence/outOfAfrica/01-outOfAfrica.nex     |  232 +
 .../Coalescence/outOfAfrica/02-outOfAfrica.nex     |  419 ++
 .../Coalescence/outOfAfrica/03-outOfAfrica.nex     |  570 ++
 .../Coalescence/outOfAfrica/04-outOfAfrica.nex     |  401 ++
 .../Coalescence/tutorial/01-associationsHow1.nex   |  474 ++
 .../Coalescence/tutorial/02-associationsHow2.nex   |  152 +
 .../Coalescence/tutorial/02b-associationsHow2.nex  |  165 +
 .../Coalescence/tutorial/03-associationsHow3.nex   |  405 ++
 .../Coalescence/tutorial/04-associationsHow4.nex   |  526 ++
 Resources/examples/Correlation/00-introduction.nex |   46 +
 .../Correlation/00a-FelsensteinsContrasts.nex      |  431 ++
 .../examples/Correlation/00b-pagel94Hominids.nex   |  395 ++
 .../examples/Correlation/00c-pairwiseIntro.nex     |   47 +
 Resources/examples/Correlation/01-pairwise.nex     |  467 ++
 .../examples/Correlation/02-pairwiseFig2(1).nex    |  347 ++
 .../examples/Correlation/03-pairwiseFig2(2).nex    |  350 ++
 .../examples/Correlation/04-pairwiseFig2(3).nex    |  350 ++
 .../examples/Correlation/05-pairwiseFig3-6(1).nex  |  318 +
 .../examples/Correlation/06-pairwiseFig3-6(2).nex  |  318 +
 .../examples/Correlation/07-pairwiseFig3-6(3).nex  |  249 +
 .../examples/Diversification/00-introduction.nex   |   46 +
 .../Diversification/01-lineagesThroughTime.nex     |  371 ++
 .../02-speciationExtinctionRates.nex               |  353 ++
 .../Diversification/03-sisterDiversification.nex   |  386 ++
 .../examples/Diversification/04-BiSSEViewer.nex    |  414 ++
 .../examples/Diversification/05-BiSSENetViewer.nex |  411 ++
 .../examples/Diversification/06-BiSSEtrees.nex     |  415 ++
 .../examples/Diversification/07-contTreeSim.nex    |  507 ++
 .../examples/Diversification/08-binaryTreeSim.nex  |  599 ++
 Resources/examples/Introduction.nex                |   52 +
 Resources/examples/Molecular/00-introduction.nex   |   54 +
 Resources/examples/Molecular/01-gcContentChart.nex |  571 ++
 .../examples/Molecular/02-gcContentMatrix.nex      |  516 ++
 .../examples/Molecular/03-gcContentBirdsEye.nex    |  515 ++
 Resources/examples/Molecular/03a-cytochromeB.nex   |  387 ++
 Resources/examples/Molecular/04-gcContentTaxa.nex  |  664 +++
 .../examples/Molecular/05-gcContentTaxaExons.nex   |  581 ++
 Resources/examples/Molecular/06-cytochromeB.nex    |  541 ++
 .../examples/Molecular/07-cytochromeBHydro.nex     |  433 ++
 .../examples/Molecular/08-cytochromeBlinked.nex    |  438 ++
 .../examples/Molecular/09-cytochromeBscatter.nex   |  453 ++
 .../Multivariate_Continuous/00-introduction.nex    |   52 +
 .../Multivariate_Continuous/01-wingsPlot.nex       |  327 ++
 .../Multivariate_Continuous/02-wingsPCA.nex        |  372 ++
 .../Multivariate_Continuous/03-wingsCVA.nex        |  371 ++
 .../examples/Multivariate_Continuous/04-anoles.nex |  448 ++
 .../examples/Multivariate_Continuous/05-anoles.nex |  489 ++
 .../examples/Multivariate_Continuous/06-anoles.nex |  517 ++
 .../examples/Multivariate_Continuous/07-anoles.nex |  529 ++
 .../examples/Multivariate_Continuous/08-anoles.nex |  536 ++
 .../examples/Multivariate_Continuous/09-pcaSim.nex |  397 ++
 .../Multivariate_Continuous/10-pcaLiveSim.nex      |  290 +
 .../Multivariate_Continuous/11-cvaLiveSim.nex      |  306 +
 .../examples/Multivariate_Continuous/12-epca.nex   |  604 ++
 .../examples/Multivariate_Continuous/13-epca.nex   |  711 +++
 .../examples/Multivariate_Continuous/14-epca.nex   |  729 +++
 .../examples/Multivariate_Continuous/15-epca.nex   |  741 +++
 .../Multivariate_Continuous/16-epcaLiveSim.nex     |  452 ++
 .../Multivariate_Continuous/17-landmarks.nex       |  386 ++
 .../Multivariate_Continuous/18-landmarks.nex       |  152 +
 .../Multivariate_Continuous/19-landmarks.nex       |  152 +
 .../Multivariate_Continuous/20-landmarks.nex       |  279 +
 .../Multivariate_Continuous/epca/Image1.gif        |  Bin 0 -> 3033 bytes
 .../Multivariate_Continuous/epca/Image2.gif        |  Bin 0 -> 2973 bytes
 .../examples/Multivariate_Continuous/fish/blue.gif |  Bin 0 -> 3046 bytes
 .../examples/Multivariate_Continuous/fish/one.gif  |  Bin 0 -> 3226 bytes
 .../examples/Multivariate_Continuous/fish/red.gif  |  Bin 0 -> 3418 bytes
 .../examples/Multivariate_Continuous/fish/two.gif  |  Bin 0 -> 2573 bytes
 .../01.concatenatingMatrices.nex                   |  337 ++
 .../02.concatenatingMatrices.nex                   |  509 ++
 .../03.concatenatingMatrices.nex                   |  530 ++
 .../04.concatenatingMatrices.nex                   |  534 ++
 .../05.concatenatingMatrices.nex                   |  557 ++
 .../06.concatenatingMatrices.nex                   |  563 ++
 .../TaxonNamesAreDifferent/07.mergedMatrix.nex     |  332 ++
 .../TaxonNamesAreDifferent/otherGeneMatrix.nex     |  258 +
 Resources/images/32arrow.gif                       |  Bin 0 -> 105 bytes
 Resources/images/32bucket.gif                      |  Bin 0 -> 130 bytes
 Resources/images/32disabled.gif                    |  Bin 0 -> 900 bytes
 Resources/images/32dropper.gif                     |  Bin 0 -> 111 bytes
 Resources/images/32ibeam.gif                       |  Bin 0 -> 109 bytes
 Resources/images/32info.gif                        |  Bin 0 -> 917 bytes
 Resources/images/32notesTool.gif                   |  Bin 0 -> 924 bytes
 Resources/images/32pointer.gif                     |  Bin 0 -> 893 bytes
 Resources/images/32revSort.gif                     |  Bin 0 -> 904 bytes
 Resources/images/32sort.gif                        |  Bin 0 -> 905 bytes
 Resources/images/32wand.gif                        |  Bin 0 -> 118 bytes
 Resources/images/32wandMinus.gif                   |  Bin 0 -> 124 bytes
 Resources/images/32wandPlus.gif                    |  Bin 0 -> 129 bytes
 Resources/images/32zoomIn.gif                      |  Bin 0 -> 909 bytes
 Resources/images/32zoomOut.gif                     |  Bin 0 -> 910 bytes
 Resources/images/64arrow.gif                       |  Bin 0 -> 147 bytes
 Resources/images/64bucket.gif                      |  Bin 0 -> 177 bytes
 Resources/images/64disabled.gif                    |  Bin 0 -> 952 bytes
 Resources/images/64dropper.gif                     |  Bin 0 -> 152 bytes
 Resources/images/64ibeam.gif                       |  Bin 0 -> 151 bytes
 Resources/images/64info.gif                        |  Bin 0 -> 970 bytes
 Resources/images/64notesTool.gif                   |  Bin 0 -> 973 bytes
 Resources/images/64pointer.gif                     |  Bin 0 -> 945 bytes
 Resources/images/64revSort.gif                     |  Bin 0 -> 956 bytes
 Resources/images/64sort.gif                        |  Bin 0 -> 958 bytes
 Resources/images/64wand.gif                        |  Bin 0 -> 161 bytes
 Resources/images/64wandMinus.gif                   |  Bin 0 -> 170 bytes
 Resources/images/64wandPlus.gif                    |  Bin 0 -> 176 bytes
 Resources/images/64zoomIn.gif                      |  Bin 0 -> 965 bytes
 Resources/images/64zoomOut.gif                     |  Bin 0 -> 964 bytes
 Resources/images/add.gif                           |  Bin 0 -> 899 bytes
 Resources/images/addGray.gif                       |  Bin 0 -> 163 bytes
 Resources/images/addRemote.gif                     |  Bin 0 -> 133 bytes
 Resources/images/and.gif                           |  Bin 0 -> 87 bytes
 Resources/images/annot.gif                         |  Bin 0 -> 87 bytes
 Resources/images/ant_logo_large.gif                |  Bin 0 -> 5360 bytes
 Resources/images/arrow.gif                         |  Bin 0 -> 84 bytes
 Resources/images/back.gif                          |  Bin 0 -> 109 bytes
 Resources/images/backDim.gif                       |  Bin 0 -> 148 bytes
 Resources/images/banner.gif                        |  Bin 0 -> 1122 bytes
 Resources/images/bannerBeta.gif                    |  Bin 0 -> 1439 bytes
 Resources/images/blackPixel.gif                    |  Bin 0 -> 807 bytes
 Resources/images/blackPixel3.gif                   |  Bin 0 -> 810 bytes
 Resources/images/blank-off.gif                     |  Bin 0 -> 167 bytes
 Resources/images/blank-off22.gif                   |  Bin 0 -> 153 bytes
 Resources/images/blank-on.gif                      |  Bin 0 -> 167 bytes
 Resources/images/blank-on22.gif                    |  Bin 0 -> 151 bytes
 Resources/images/blue-ball-small.gif               |  Bin 0 -> 255 bytes
 Resources/images/bucket.gif                        |  Bin 0 -> 100 bytes
 Resources/images/buttons.gif                       |  Bin 0 -> 117 bytes
 Resources/images/checkMark.gif                     |  Bin 0 -> 89 bytes
 Resources/images/closeTriangleUp.gif               |  Bin 0 -> 80 bytes
 Resources/images/colorLegend.gif                   |  Bin 0 -> 102 bytes
 Resources/images/colors/0                          |    6 +
 Resources/images/colors/0blank-off.gif             |  Bin 0 -> 180 bytes
 Resources/images/colors/0blank-on copy.gif         |  Bin 0 -> 132 bytes
 Resources/images/colors/0blank-on.gif              |  Bin 0 -> 132 bytes
 Resources/images/colors/0citationsTab.gif          |  Bin 0 -> 216 bytes
 Resources/images/colors/0graphicsTab.gif           |  Bin 0 -> 209 bytes
 Resources/images/colors/0infoBarBase.gif           |  Bin 0 -> 567 bytes
 Resources/images/colors/0modulesTab.gif            |  Bin 0 -> 206 bytes
 Resources/images/colors/0parametersTab.gif         |  Bin 0 -> 237 bytes
 Resources/images/colors/0textTab.gif               |  Bin 0 -> 170 bytes
 Resources/images/colors/1                          |    7 +
 Resources/images/colors/1blank-off.gif             |  Bin 0 -> 178 bytes
 Resources/images/colors/1blank-on.gif              |  Bin 0 -> 132 bytes
 Resources/images/colors/1citationsTab.gif          |  Bin 0 -> 251 bytes
 Resources/images/colors/1graphicsTab.gif           |  Bin 0 -> 242 bytes
 Resources/images/colors/1infoBarBase.gif           |  Bin 0 -> 567 bytes
 Resources/images/colors/1modulesTab.gif            |  Bin 0 -> 245 bytes
 Resources/images/colors/1parametersTab.gif         |  Bin 0 -> 271 bytes
 Resources/images/colors/1textTab.gif               |  Bin 0 -> 209 bytes
 Resources/images/colors/2                          |   22 +
 Resources/images/colors/2blank-off.gif             |  Bin 0 -> 149 bytes
 Resources/images/colors/2blank-on.gif              |  Bin 0 -> 118 bytes
 Resources/images/colors/2citationsTab.gif          |  Bin 0 -> 223 bytes
 Resources/images/colors/2graphicsTab.gif           |  Bin 0 -> 218 bytes
 Resources/images/colors/2infoBarBase.gif           |  Bin 0 -> 567 bytes
 Resources/images/colors/2modulesTab.gif            |  Bin 0 -> 216 bytes
 Resources/images/colors/2parametersTab.gif         |  Bin 0 -> 241 bytes
 Resources/images/colors/2textTab.gif               |  Bin 0 -> 181 bytes
 Resources/images/colors/3                          |    6 +
 Resources/images/colors/3blank-off.gif             |  Bin 0 -> 177 bytes
 Resources/images/colors/3blank-on.gif              |  Bin 0 -> 132 bytes
 Resources/images/colors/3citationsTab.gif          |  Bin 0 -> 251 bytes
 Resources/images/colors/3graphicsTab.gif           |  Bin 0 -> 245 bytes
 Resources/images/colors/3infoBarBase.gif           |  Bin 0 -> 567 bytes
 Resources/images/colors/3modulesTab.gif            |  Bin 0 -> 244 bytes
 Resources/images/colors/3parametersTab.gif         |  Bin 0 -> 269 bytes
 Resources/images/colors/3textTab.gif               |  Bin 0 -> 209 bytes
 Resources/images/colors/blank-off.gif              |  Bin 0 -> 133 bytes
 Resources/images/colors/blank-offBordered.gif      |  Bin 0 -> 144 bytes
 Resources/images/colors/blank-offClear.gif         |  Bin 0 -> 142 bytes
 Resources/images/colors/infoBarBase copy 2.gif     |  Bin 0 -> 557 bytes
 Resources/images/colors/infoBarBase copy.gif       |  Bin 0 -> 557 bytes
 Resources/images/colors/infoBarBase.gif            |  Bin 0 -> 558 bytes
 Resources/images/compactTransparent.gif            |  Bin 0 -> 90 bytes
 Resources/images/construction.gif                  |  Bin 0 -> 240 bytes
 Resources/images/dataSearch.gif                    |  Bin 0 -> 89 bytes
 Resources/images/decompactTransparent.gif          |  Bin 0 -> 92 bytes
 Resources/images/decrease.gif                      |  Bin 0 -> 902 bytes
 Resources/images/disabled.gif                      |  Bin 0 -> 866 bytes
 Resources/images/downarrow-blue.gif                |  Bin 0 -> 163 bytes
 Resources/images/downarrow-green.gif               |  Bin 0 -> 127 bytes
 Resources/images/downarrow-red.gif                 |  Bin 0 -> 132 bytes
 Resources/images/downarrow.gif                     |  Bin 0 -> 156 bytes
 Resources/images/downarrowDisabled.gif             |  Bin 0 -> 114 bytes
 Resources/images/downarrowPressed.gif              |  Bin 0 -> 163 bytes
 Resources/images/download.gif                      |  Bin 0 -> 106 bytes
 Resources/images/dropper.gif                       |  Bin 0 -> 90 bytes
 Resources/images/empty.gif                         |  Bin 0 -> 55 bytes
 Resources/images/enterHoriz.gif                    |  Bin 0 -> 150 bytes
 Resources/images/enterHorizDisabled.gif            |  Bin 0 -> 150 bytes
 Resources/images/enterHorizPressed.gif             |  Bin 0 -> 156 bytes
 Resources/images/enterVert.gif                     |  Bin 0 -> 151 bytes
 Resources/images/enterVertDisabled.gif             |  Bin 0 -> 150 bytes
 Resources/images/enterVertPressed.gif              |  Bin 0 -> 158 bytes
 Resources/images/equilstatestab.gif                |  Bin 0 -> 365 bytes
 Resources/images/equilstatestabOff.gif             |  Bin 0 -> 336 bytes
 Resources/images/equivocal.gif                     |  Bin 0 -> 845 bytes
 Resources/images/explanationMinus.gif              |  Bin 0 -> 874 bytes
 Resources/images/explanationMinusOff.gif           |  Bin 0 -> 874 bytes
 Resources/images/explanationPlus.gif               |  Bin 0 -> 878 bytes
 Resources/images/functionIcons/charSource.gif      |  Bin 0 -> 148 bytes
 Resources/images/functionIcons/characterNumber.gif |  Bin 0 -> 163 bytes
 Resources/images/functionIcons/chart.gif           |  Bin 0 -> 138 bytes
 Resources/images/functionIcons/fileInterpret.gif   |  Bin 0 -> 132 bytes
 Resources/images/functionIcons/matrixEditor.gif    |  Bin 0 -> 143 bytes
 .../images/functionIcons/matrixEditorUtil.gif      |  Bin 0 -> 208 bytes
 Resources/images/functionIcons/matrixNumber.gif    |  Bin 0 -> 175 bytes
 Resources/images/functionIcons/matrixSource.gif    |  Bin 0 -> 172 bytes
 Resources/images/functionIcons/simulate.gif        |  Bin 0 -> 174 bytes
 Resources/images/functionIcons/treeCharNumber.gif  |  Bin 0 -> 185 bytes
 Resources/images/functionIcons/treeNumber.gif      |  Bin 0 -> 146 bytes
 Resources/images/functionIcons/treeSource.gif      |  Bin 0 -> 153 bytes
 Resources/images/functionIcons/treeWindow.gif      |  Bin 0 -> 130 bytes
 Resources/images/functionIcons/treeWindowUtil.gif  |  Bin 0 -> 226 bytes
 Resources/images/goaway.gif                        |  Bin 0 -> 127 bytes
 Resources/images/goawayTransparent.gif             |  Bin 0 -> 97 bytes
 Resources/images/green-ball-small.gif              |  Bin 0 -> 102 bytes
 Resources/images/help.gif                          |  Bin 0 -> 1447 bytes
 Resources/images/helpPressed.gif                   |  Bin 0 -> 1440 bytes
 Resources/images/how.gif                           |  Bin 0 -> 135 bytes
 Resources/images/ibeam.gif                         |  Bin 0 -> 87 bytes
 Resources/images/increase.gif                      |  Bin 0 -> 905 bytes
 Resources/images/info.gif                          |  Bin 0 -> 880 bytes
 Resources/images/infoBarBase.gif                   |  Bin 0 -> 517 bytes
 Resources/images/infoBarIcons.gif                  |  Bin 0 -> 513 bytes
 Resources/images/infoBarTriangle.gif               |  Bin 0 -> 94 bytes
 Resources/images/leftarrow-blue.gif                |  Bin 0 -> 158 bytes
 Resources/images/leftarrow-gray.gif                |  Bin 0 -> 902 bytes
 Resources/images/leftarrow-green.gif               |  Bin 0 -> 125 bytes
 Resources/images/leftarrow-red.gif                 |  Bin 0 -> 129 bytes
 Resources/images/leftarrow.gif                     |  Bin 0 -> 152 bytes
 Resources/images/leftarrowDisabled.gif             |  Bin 0 -> 111 bytes
 Resources/images/leftarrowPressed.gif              |  Bin 0 -> 158 bytes
 Resources/images/link.gif                          |  Bin 0 -> 904 bytes
 Resources/images/list.gif                          |  Bin 0 -> 81 bytes
 Resources/images/listC.gif                         |  Bin 0 -> 113 bytes
 Resources/images/listP.GIF                         |  Bin 0 -> 881 bytes
 Resources/images/listS.gif                         |  Bin 0 -> 123 bytes
 Resources/images/listT.gif                         |  Bin 0 -> 113 bytes
 Resources/images/manual.gif                        |  Bin 0 -> 380 bytes
 Resources/images/manualPressed.gif                 |  Bin 0 -> 372 bytes
 Resources/images/matrix.gif                        |  Bin 0 -> 85 bytes
 Resources/images/maximizeTransparent.gif           |  Bin 0 -> 97 bytes
 Resources/images/mediumizeTransparent.gif          |  Bin 0 -> 93 bytes
 Resources/images/menuDropArrow.gif                 |  Bin 0 -> 75 bytes
 Resources/images/menus.gif                         |  Bin 0 -> 91 bytes
 Resources/images/mesquite.gif                      |  Bin 0 -> 6891 bytes
 Resources/images/mesquiteBeta.gif                  |  Bin 0 -> 7558 bytes
 Resources/images/mesquiteIcon.gif                  |  Bin 0 -> 204 bytes
 Resources/images/mesquiteIcon128.gif               |  Bin 0 -> 5500 bytes
 Resources/images/mesquiteIcon16.gif                |  Bin 0 -> 588 bytes
 Resources/images/mesquiteIcon48.gif                |  Bin 0 -> 278 bytes
 Resources/images/mesquitePlain.gif                 |  Bin 0 -> 9904 bytes
 Resources/images/mesquitesmall.gif                 |  Bin 0 -> 5999 bytes
 Resources/images/miniScroll.jpg                    |  Bin 0 -> 1397 bytes
 Resources/images/minimize.gif                      |  Bin 0 -> 118 bytes
 Resources/images/minimizeTransparent.gif           |  Bin 0 -> 90 bytes
 Resources/images/miniscrollHoriz.gif               |  Bin 0 -> 354 bytes
 Resources/images/miniscrollVert.gif                |  Bin 0 -> 387 bytes
 Resources/images/new.gif                           |  Bin 0 -> 892 bytes
 Resources/images/notesTool.gif                     |  Bin 0 -> 889 bytes
 Resources/images/ok.gif                            |  Bin 0 -> 133 bytes
 Resources/images/or.gif                            |  Bin 0 -> 82 bytes
 Resources/images/pause.gif                         |  Bin 0 -> 96 bytes
 Resources/images/play.gif                          |  Bin 0 -> 99 bytes
 Resources/images/pointer.gif                       |  Bin 0 -> 861 bytes
 Resources/images/prerelease.gif                    |  Bin 0 -> 128 bytes
 Resources/images/queryGray.gif                     |  Bin 0 -> 158 bytes
 Resources/images/ratematrixtab.gif                 |  Bin 0 -> 313 bytes
 Resources/images/ratematrixtabOff.gif              |  Bin 0 -> 276 bytes
 Resources/images/release.gif                       |  Bin 0 -> 111 bytes
 Resources/images/replaceLeft.gif                   |  Bin 0 -> 902 bytes
 Resources/images/revSort.gif                       |  Bin 0 -> 89 bytes
 Resources/images/rightarrow-blue.gif               |  Bin 0 -> 158 bytes
 Resources/images/rightarrow-green.gif              |  Bin 0 -> 123 bytes
 Resources/images/rightarrow-red.gif                |  Bin 0 -> 127 bytes
 Resources/images/rightarrow.gif                    |  Bin 0 -> 151 bytes
 Resources/images/rightarrowDisabled.gif            |  Bin 0 -> 112 bytes
 Resources/images/rightarrowPressed.gif             |  Bin 0 -> 157 bytes
 Resources/images/rootstatestab.gif                 |  Bin 0 -> 316 bytes
 Resources/images/rootstatestabOff.gif              |  Bin 0 -> 281 bytes
 Resources/images/search.gif                        |  Bin 0 -> 945 bytes
 Resources/images/showInfo.gif                      |  Bin 0 -> 171 bytes
 Resources/images/showInfoOld.gif                   |  Bin 0 -> 96 bytes
 Resources/images/showTransparent.gif               |  Bin 0 -> 93 bytes
 Resources/images/simplification/blueRing.gif       |  Bin 0 -> 330 bytes
 Resources/images/simplification/load.gif           |  Bin 0 -> 1672 bytes
 Resources/images/simplification/power.gif          |  Bin 0 -> 105 bytes
 Resources/images/simplification/redRing.gif        |  Bin 0 -> 347 bytes
 Resources/images/simplification/simple.gif         |  Bin 0 -> 97 bytes
 Resources/images/sitetositetab.gif                 |  Bin 0 -> 305 bytes
 Resources/images/sitetositetabOff.gif              |  Bin 0 -> 273 bytes
 Resources/images/sliderHoriz.gif                   |  Bin 0 -> 94 bytes
 Resources/images/sliderVert.gif                    |  Bin 0 -> 97 bytes
 Resources/images/small.top.arrow.gif               |  Bin 0 -> 977 bytes
 Resources/images/sort.gif                          |  Bin 0 -> 873 bytes
 Resources/images/spot.gif                          |  Bin 0 -> 880 bytes
 Resources/images/spotgreen.gif                     |  Bin 0 -> 888 bytes
 Resources/images/substantiveBug.gif                |  Bin 0 -> 156 bytes
 Resources/images/subtract.gif                      |  Bin 0 -> 891 bytes
 Resources/images/subtractGray.gif                  |  Bin 0 -> 156 bytes
 Resources/images/tabLeft.gif                       |  Bin 0 -> 255 bytes
 Resources/images/tabOff.gif                        |  Bin 0 -> 266 bytes
 Resources/images/tabOn.gif                         |  Bin 0 -> 266 bytes
 Resources/images/tabRight.gif                      |  Bin 0 -> 255 bytes
 Resources/images/taxon.gif                         |  Bin 0 -> 900 bytes
 Resources/images/trashcan.gif                      |  Bin 0 -> 906 bytes
 Resources/images/triangleDown.gif                  |  Bin 0 -> 859 bytes
 Resources/images/triangleDownOff.gif               |  Bin 0 -> 857 bytes
 Resources/images/triangleDownOn.gif                |  Bin 0 -> 855 bytes
 Resources/images/triangleRightOff.gif              |  Bin 0 -> 859 bytes
 Resources/images/triangleRightOn.gif               |  Bin 0 -> 856 bytes
 Resources/images/triangleUpOn.gif                  |  Bin 0 -> 843 bytes
 Resources/images/uparrow-blue.gif                  |  Bin 0 -> 161 bytes
 Resources/images/uparrow-green.gif                 |  Bin 0 -> 130 bytes
 Resources/images/uparrow-red.gif                   |  Bin 0 -> 131 bytes
 Resources/images/uparrow.gif                       |  Bin 0 -> 154 bytes
 Resources/images/uparrowDisabled.gif               |  Bin 0 -> 115 bytes
 Resources/images/uparrowPressed.gif                |  Bin 0 -> 158 bytes
 Resources/images/wand.gif                          |  Bin 0 -> 95 bytes
 Resources/images/wandMinus.gif                     |  Bin 0 -> 97 bytes
 Resources/images/wandPlus.gif                      |  Bin 0 -> 103 bytes
 Resources/images/windowIcons/goAway old.gif        |  Bin 0 -> 107 bytes
 Resources/images/windowIcons/goAway.gif            |  Bin 0 -> 954 bytes
 Resources/images/windowIcons/listC.gif             |  Bin 0 -> 137 bytes
 Resources/images/windowIcons/listT.gif             |  Bin 0 -> 142 bytes
 Resources/images/windowIcons/matrix.gif            |  Bin 0 -> 99 bytes
 Resources/images/windowIcons/matrixSequence.gif    |  Bin 0 -> 137 bytes
 Resources/images/windowIcons/tree.gif              |  Bin 0 -> 102 bytes
 Resources/images/zoomIn.gif                        |  Bin 0 -> 94 bytes
 Resources/images/zoomOut.gif                       |  Bin 0 -> 878 bytes
 Resources/lesser.txt                               |  504 ++
 Resources/mesquite.sh                              |   64 +
 Resources/startingMesquiteAndMemoryAllocation.txt  |   76 +
 Source/corejava/Format.java                        |  565 ++
 Source/edu/stanford/ejalbert/BrowserLauncher.java  |  583 ++
 Source/mesquite/Mesquite.java                      | 2564 ++++++++
 .../align/AlignDNAToProtein/AlignDNAToProtein.java |  180 +
 .../AlignScoreForTaxon/AlignScoreForTaxon.java     |   59 +
 .../AlignScoreForTaxonRC/AlignScoreForTaxonRC.java |   80 +
 .../align/AlignSequences/AlignSequences.java       |  231 +
 .../align/AlignToDropped/32alignToDropped.gif      |  Bin 0 -> 143 bytes
 .../align/AlignToDropped/64alignToDropped.gif      |  Bin 0 -> 188 bytes
 .../align/AlignToDropped/AlignToDropped.java       |  369 ++
 .../align/AlignToDropped/alignToDropped.gif        |  Bin 0 -> 116 bytes
 .../mesquite/align/ClustalAlign/ClustalAlign.java  |  133 +
 .../align/ColorForAlignment/ColorForAlignment.java |  141 +
 .../ColorGapsInCodingSequence.java                 |  139 +
 .../align/ColorMisaligned/ColorMisaligned.java     |  293 +
 Source/mesquite/align/MAFFTAlign/MAFFTAlign.java   |  268 +
 .../align/MultiBlockSplitter/32CrossHair.gif       |  Bin 0 -> 309 bytes
 .../MultiBlockSplitter/32MultiBlockSplitter.gif    |  Bin 0 -> 149 bytes
 .../32MultiBlockSplitterOption.gif                 |  Bin 0 -> 925 bytes
 .../align/MultiBlockSplitter/64CrossHair.gif       |  Bin 0 -> 357 bytes
 .../MultiBlockSplitter/64MultiBlockSplitter.gif    |  Bin 0 -> 197 bytes
 .../64MultiBlockSplitterOption.gif                 |  Bin 0 -> 981 bytes
 .../align/MultiBlockSplitter/CrossHair.gif         |  Bin 0 -> 88 bytes
 .../MultiBlockSplitter/MultiBlockSplitter.gif      |  Bin 0 -> 100 bytes
 .../MultiBlockSplitter/MultiBlockSplitter.java     |  473 ++
 .../MultiBlockSplitterOption.gif                   |  Bin 0 -> 101 bytes
 Source/mesquite/align/MuscleAlign/MuscleAlign.java |  126 +
 Source/mesquite/align/Notes/Align Notes            |   46 +
 Source/mesquite/align/Notes/align.nex              |  172 +
 .../align/Notes/bugs/bug.PairwiseAligner.nex       |  171 +
 Source/mesquite/align/Notes/clustal Option List    |   71 +
 Source/mesquite/align/Notes/coiLong.nex            |  200 +
 Source/mesquite/align/Notes/prot.nex               |  153 +
 .../align/RemoveAllGaps/RemoveAllGaps.java         |   92 +
 .../mesquite/align/ScrollToData/32scrollerLeft.gif |  Bin 0 -> 143 bytes
 .../align/ScrollToData/32scrollerRight.gif         |  Bin 0 -> 143 bytes
 .../mesquite/align/ScrollToData/64scrollerLeft.gif |  Bin 0 -> 189 bytes
 .../align/ScrollToData/64scrollerRight.gif         |  Bin 0 -> 977 bytes
 .../mesquite/align/ScrollToData/ScrollToData.java  |  117 +
 .../mesquite/align/ScrollToData/scrollerLeft.gif   |  Bin 0 -> 117 bytes
 .../mesquite/align/ScrollToData/scrollerRight.gif  |  Bin 0 -> 118 bytes
 .../align/SelectedBlockMover/32CrossHair.gif       |  Bin 0 -> 309 bytes
 .../SelectedBlockMover/32SelectedBlockMover.gif    |  Bin 0 -> 181 bytes
 .../align/SelectedBlockMover/64CrossHair.gif       |  Bin 0 -> 357 bytes
 .../SelectedBlockMover/64SelectedBlockMover.gif    |  Bin 0 -> 233 bytes
 .../align/SelectedBlockMover/CrossHair.gif         |  Bin 0 -> 88 bytes
 .../SelectedBlockMover/SelectedBlockMover.gif      |  Bin 0 -> 125 bytes
 .../SelectedBlockMover/SelectedBlockMover.java     |  318 +
 .../align/ShiftOtherToMatch/ShiftOtherToMatch.java |  217 +
 .../ShiftToMinimizeStops/ShiftToMinimizeStops.java |  155 +
 Source/mesquite/align/SidePusher/32leftGrab.gif    |  Bin 0 -> 965 bytes
 Source/mesquite/align/SidePusher/32rightGrab.gif   |  Bin 0 -> 964 bytes
 .../mesquite/align/SidePusher/32splitBlockLeft.gif |  Bin 0 -> 130 bytes
 .../align/SidePusher/32splitBlockRight.gif         |  Bin 0 -> 128 bytes
 Source/mesquite/align/SidePusher/64leftGrab.gif    |  Bin 0 -> 1021 bytes
 Source/mesquite/align/SidePusher/64rightGrab.gif   |  Bin 0 -> 1019 bytes
 .../mesquite/align/SidePusher/64splitBlockLeft.gif |  Bin 0 -> 172 bytes
 .../align/SidePusher/64splitBlockRight.gif         |  Bin 0 -> 172 bytes
 Source/mesquite/align/SidePusher/SidePusher.java   |  109 +
 Source/mesquite/align/SidePusher/leftGrab.gif      |  Bin 0 -> 911 bytes
 Source/mesquite/align/SidePusher/rightGrab.gif     |  Bin 0 -> 907 bytes
 .../mesquite/align/SidePusher/splitBlockLeft.gif   |  Bin 0 -> 108 bytes
 .../mesquite/align/SidePusher/splitBlockRight.gif  |  Bin 0 -> 104 bytes
 .../align/SimpleBlockMover/32BlockMover.gif        |  Bin 0 -> 941 bytes
 Source/mesquite/align/SimpleBlockMover/32Hand.gif  |  Bin 0 -> 941 bytes
 .../align/SimpleBlockMover/32splitBlock.gif        |  Bin 0 -> 158 bytes
 .../align/SimpleBlockMover/64BlockMover.gif        |  Bin 0 -> 996 bytes
 Source/mesquite/align/SimpleBlockMover/64Hand.gif  |  Bin 0 -> 996 bytes
 .../align/SimpleBlockMover/64splitBlock.gif        |  Bin 0 -> 205 bytes
 .../mesquite/align/SimpleBlockMover/BlockMover.gif |  Bin 0 -> 902 bytes
 Source/mesquite/align/SimpleBlockMover/Hand.gif    |  Bin 0 -> 884 bytes
 .../align/SimpleBlockMover/SimpleBlockMover.java   |  142 +
 .../mesquite/align/SimpleBlockMover/splitBlock.gif |  Bin 0 -> 132 bytes
 Source/mesquite/align/ZapGaps/ZapGaps.java         |   98 +
 .../mesquite/align/ZapGapsRight/ZapGapsRight.java  |   98 +
 .../align/aAlignIntro/Templates/standard.dwt       |   59 +
 .../align/aAlignIntro/_notes/2col_leftNav.css.mno  |    4 +
 Source/mesquite/align/aAlignIntro/aAlignIntro.java |   81 +
 .../align/aAlignIntro/acknowledgements.html        |   61 +
 Source/mesquite/align/aAlignIntro/additions.html   |   53 +
 Source/mesquite/align/aAlignIntro/automated.html   |  118 +
 Source/mesquite/align/aAlignIntro/citation.html    |   65 +
 .../mesquite/align/aAlignIntro/colorMisaligned.jpg |  Bin 0 -> 66630 bytes
 Source/mesquite/align/aAlignIntro/faq.html         |   66 +
 Source/mesquite/align/aAlignIntro/future.html      |   69 +
 .../align/aAlignIntro/images/BlockMover.gif        |  Bin 0 -> 126 bytes
 .../align/aAlignIntro/images/MAFFT Dialog Box.png  |  Bin 0 -> 52790 bytes
 .../align/aAlignIntro/images/alignToDropped.gif    |  Bin 0 -> 116 bytes
 Source/mesquite/align/aAlignIntro/images/email.jpg |  Bin 0 -> 2639 bytes
 .../mesquite/align/aAlignIntro/images/leftGrab.gif |  Bin 0 -> 911 bytes
 .../align/aAlignIntro/images/mesquiteIcon.gif      |  Bin 0 -> 196 bytes
 .../align/aAlignIntro/images/multiBlockSpitter.gif |  Bin 0 -> 93 bytes
 .../aAlignIntro/images/multiBlockSplitterOther.gif |  Bin 0 -> 98 bytes
 .../align/aAlignIntro/images/multiSplitBefore.gif  |  Bin 0 -> 5645 bytes
 .../align/aAlignIntro/images/multisplitAfter.gif   |  Bin 0 -> 5547 bytes
 .../align/aAlignIntro/images/rightGrab.gif         |  Bin 0 -> 907 bytes
 .../align/aAlignIntro/images/scrollToData.gif      |  Bin 0 -> 124 bytes
 .../aAlignIntro/images/selectedBlockMover.gif      |  Bin 0 -> 153 bytes
 .../align/aAlignIntro/manualAlignment.html         |  127 +
 Source/mesquite/align/aAlignIntro/overview.html    |   82 +
 Source/mesquite/align/aAlignIntro/sourceCode.html  |   61 +
 Source/mesquite/align/aAlignIntro/splash.gif       |  Bin 0 -> 4225 bytes
 Source/mesquite/align/aAlignIntro/statistics.html  |   64 +
 .../align/aAlignIntro/styles/mesquitePackage.css   |  302 +
 .../mesquite/align/aAlignIntro/visualization.html  |   82 +
 Source/mesquite/align/lib/AlignMatch.java          |  171 +
 .../mesquite/align/lib/AlignScoreForTaxonGen.java  |  197 +
 Source/mesquite/align/lib/AlignTool.java           |   53 +
 Source/mesquite/align/lib/AlignUtil.java           |  576 ++
 Source/mesquite/align/lib/AlignmentHelper.java     |  105 +
 .../align/lib/AlignmentHelperLinearSpace.java      |  411 ++
 .../align/lib/AlignmentHelperQuadraticSpace.java   |  217 +
 Source/mesquite/align/lib/BlockMover.java          |  454 ++
 .../align/lib/ExternalSequenceAligner.java         |  448 ++
 Source/mesquite/align/lib/MultiBlockMoveBase.java  |  360 ++
 .../align/lib/MultipleSequenceAligner.java         |  101 +
 Source/mesquite/align/lib/PairwiseAligner.java     |  514 ++
 Source/mesquite/align/lib/TwoSequenceAligner.java  |  117 +
 .../mesquite/align/lib/TwoSequenceAlignerGaps.java |   86 +
 .../AncestralStatesAll/AncestralStatesAll.java     |  128 +
 .../ancstates/ExportAncRec/ExportAncRec.java       |  198 +
 .../LabelStatesOnTree/LabelStatesOnTree.java       |  134 +
 .../RecAncestralStates/RecAncestralStates.java     |  313 +
 .../ShadeStatesOnTree/ShadeStatesOnTree.java       |  251 +
 .../SummarizeChanges/SummarizeChanges.java         |  761 +++
 .../SummarizeChgOnBranches.java                    |  101 +
 .../SummarizeChgOverTrees.java                     |  105 +
 .../TraceAllCharacters/TraceAllCharacters.java     |  507 ++
 .../TraceCharOverTrees/TraceCharOverTrees.java     | 1492 +++++
 .../TraceCharacterHistory.java                     |  984 ++++
 .../TraceCharacterOperator.java                    |  809 +++
 .../UnambigChangesAtNodes.java                     |  107 +
 .../ancstates/aAncStatesIntro/aAncStatesIntro.java |   58 +
 .../mesquite/ancstates/aAncStatesIntro/index.html  |  124 +
 .../mesquite/ancstates/aAncStatesIntro/splash.gif  |  Bin 0 -> 1045 bytes
 Source/mesquite/ancstates/explanation.txt          |    2 +
 .../ancstates/lib/ChgSummarizerMultTrees.java      |   48 +
 .../ContainedAssociates/ContainedAssociates.java   | 1722 ++++++
 .../assoc/DepContTreeWindow/DepContTreeWindow.java |  156 +
 .../ManageAssociations/ManageAssociations.java     |  745 +++
 .../ManageDistributionBlock.java                   |  196 +
 .../PartitionFromAssociation.java                  |  115 +
 .../StoredAssociations/StoredAssociations.java     |  198 +
 Source/mesquite/assoc/TaxaAssociationSpecs.txt     |   97 +
 .../assoc/TaxonListAssoc/TaxonListAssoc.java       |  687 +++
 Source/mesquite/assoc/aAssocIntro/aAssocIntro.java |   63 +
 Source/mesquite/assoc/explanation.txt              |    2 +
 Source/mesquite/assoc/lib/AssociationHistory.java  |  662 +++
 Source/mesquite/assoc/lib/AssociationSource.java   |   87 +
 Source/mesquite/assoc/lib/AssociationsManager.java |   50 +
 .../mesquite/assoc/lib/NumberForAssocAndTree.java  |   70 +
 .../mesquite/assoc/lib/NumberForAssociation.java   |   79 +
 .../mesquite/assoc/lib/ReconstructAssociation.java |   38 +
 Source/mesquite/assoc/lib/SimpleTaxaList.java      |  272 +
 Source/mesquite/assoc/lib/TaxaAssociation.java     |  706 +++
 Source/mesquite/assoc/macros/setupAssocMacro       |   38 +
 .../basic/AddToTaxonNames/AddToTaxonNames.java     |  102 +
 .../basic/AssignTaxonNames/AssignTaxonNames.java   |   80 +
 .../basic/AuthorDefaults/AuthorDefaults.java       |  233 +
 .../basic/BasicParametersExplorer/32centre.gif     |  Bin 0 -> 895 bytes
 .../basic/BasicParametersExplorer/64centre.gif     |  Bin 0 -> 945 bytes
 .../BasicParametersExplorer.java                   |  611 ++
 .../basic/BasicParametersExplorer/centre.gif       |  Bin 0 -> 81 bytes
 .../BasicStringMatcher/BasicStringMatcher.java     |   56 +
 .../CondenseTaxonNames/CondenseTaxonNames.java     |  132 +
 .../CurrentTaxaPartition/CurrentTaxaPartition.java |   89 +
 .../DeleteTaxonFootnotes/DeleteTaxonFootnotes.java |   69 +
 .../basic/DuplicateTaxa/DuplicateTaxa.java         |  118 +
 .../basic/ExamplesNavigator/ExamplesNavigator.java |  742 +++
 Source/mesquite/basic/GoToWebPage/GoToWebPage.java |  228 +
 .../ManageArchivedTaxonNames.java                  |  302 +
 .../basic/ManageAuthors/ManageAuthors.java         |  279 +
 .../ManageFileComments/ManageFileComments.java     |  308 +
 .../basic/ManageLabelsBlock/ManageLabelsBlock.java |  169 +
 .../basic/ManageNotesBlock/ManageNotesBlock.java   |  228 +
 .../basic/ManageSetsBlock/ManageSetsBlock.java     |  153 +
 .../ManageTaxaPartitions/ManageTaxaPartitions.java |  542 ++
 .../basic/ManageTaxaSets/ManageTaxaSets.java       |  294 +
 Source/mesquite/basic/MergeTaxa/MergeTaxa.java     |  239 +
 Source/mesquite/basic/NextProject/NextProject.java |  251 +
 .../PrefixTaxonNameWithGroup.java                  |  101 +
 .../PrefixedStringMatcher.java                     |   84 +
 .../RawNexusBlockEditor/RawNexusBlockEditor.java   |  102 +
 .../RemoveFromTaxonNames/RemoveFromTaxonNames.java |  107 +
 .../RemoveTokensTaxonNames.java                    |  184 +
 .../ReplaceInTaxonNames/ReplaceInTaxonNames.java   |  101 +
 .../SearchNameTaxonSelector.java                   |  121 +
 Source/mesquite/basic/ShowText/ShowText.java       |  155 +
 .../basic/StoredTaxonPairs/StoredTaxonPairs.java   |  197 +
 .../basic/SuffixTaxonNames/SuffixTaxonNames.java   |   77 +
 .../TaxaSelCoordinator/TaxaSelCoordinator.java     |  144 +
 .../basic/TextWindowMaker/TextWindowMaker.java     |  152 +
 .../basic/TruncTaxonNames/TruncTaxonNames.java     |  103 +
 .../VoucherInfoCoordinator.java                    |    1 +
 .../VoucherInfoFromFlexTable.java                  |    1 +
 Source/mesquite/basic/aBasicIntro/aBasicIntro.java |   67 +
 Source/mesquite/basic/explanation.txt              |    2 +
 .../zTokenizeTaxonNames/zTokenizeTaxonNames.java   |   68 +
 .../zzDetokenizeTaxonNames.java                    |   67 +
 .../BatchTemplateManager/BatchTemplateManager.java | 1173 ++++
 .../batchArch/BatchTemplateManager/manual.html     |   27 +
 .../BatchTemplateManager/templates/NONA.template   |    8 +
 .../templates/aPAUPTestConstPars.template          |   10 +
 .../templates/basicPAUP.template                   |    8 +
 .../BatchTemplateManager/templates/simple.template |    6 +
 .../ChartFromInstructions.java                     |  810 +++
 .../ExportMatricesBatch/ExportMatricesBatch.java   |  457 ++
 .../batchArch/aBatchArchIntro/aBatchArchIntro.java |   60 +
 .../batchArch/aBatchArchIntro/batchtemplate.gif    |  Bin 0 -> 36108 bytes
 .../batchArch/aBatchArchIntro/batchtemplates.html  |  107 +
 Source/mesquite/batchArch/aBatchArchIntro/emb1.gif |  Bin 0 -> 26605 bytes
 .../mesquite/batchArch/aBatchArchIntro/index.html  |  166 +
 .../batchArch/aBatchArchIntro/instructions.html    |  131 +
 .../mesquite/batchArch/aBatchArchIntro/oneGear.psd |  Bin 0 -> 32593 bytes
 .../batchArch/aBatchArchIntro/snippetNeeded.gif    |  Bin 0 -> 5113 bytes
 .../mesquite/batchArch/aBatchArchIntro/splash.gif  |  Bin 0 -> 4752 bytes
 .../batchArch/aBatchArchIntro/templateManager.gif  |  Bin 0 -> 20214 bytes
 .../batchArch/aBatchArchIntro/templateeg.gif       |  Bin 0 -> 10201 bytes
 .../batchArch/aBatchArchIntro/treeNeeded.gif       |  Bin 0 -> 3419 bytes
 Source/mesquite/batchArch/lib/TemplateManager.java |   41 +
 Source/mesquite/batchArch/lib/TemplateRecord.java  |  462 ++
 .../categ/AmbiguityToPolym/AmbiguityToPolym.java   |   82 +
 .../categ/CategVariable/CategVariable.java         |   67 +
 .../ConsensusSequenceStrip.java                    |  452 ++
 .../categ/ConsensusSequenceStrip/consensus.gif     |  Bin 0 -> 16459 bytes
 .../ConsensusStateForChar.java                     |  172 +
 .../ManageCategoricalChars.java                    |  708 +++
 .../categ/ManageDNARNAChars/ManageDNARNAChars.java |  344 ++
 .../ManageProteinChars/ManageProteinChars.java     |  306 +
 .../MultistateToMissing/MultistateToMissing.java   |   76 +
 .../categ/PolymToAmbiguity/PolymToAmbiguity.java   |   78 +
 .../ProportionUniqueStates.java                    |  204 +
 .../categ/RemoveInvariant/RemoveInvariant.java     |   97 +
 .../ResolveStateAmbiguity.java                     |   93 +
 .../SmallStateNamesEditor.java                     |  409 ++
 .../StateConsistencyInWindowStrip.java             |  473 ++
 .../StateConsistencyStrip.java                     |  391 ++
 .../categ/StateFrequency/StateFrequency.java       |  173 +
 .../categ/StateNamesEditor/StateNamesEditor.java   | 1281 ++++
 .../mesquite/categ/StateNamesEditor/transpose.gif  |  Bin 0 -> 857 bytes
 .../categ/StateNamesStrip/StateNamesStrip.java     |  168 +
 Source/mesquite/categ/aCategIntro/aCategIntro.java |   63 +
 Source/mesquite/categ/explanation.txt              |    2 +
 Source/mesquite/categ/lib/CategColorTable.java     |   28 +
 Source/mesquite/categ/lib/CategDataAlterer.java    |   38 +
 Source/mesquite/categ/lib/CategDataEditorInit.java |   43 +
 .../mesquite/categ/lib/CategDataEditorInitD.java   |   38 +
 Source/mesquite/categ/lib/CategDataMatcher.java    |   86 +
 Source/mesquite/categ/lib/CategDataSearcher.java   |   38 +
 Source/mesquite/categ/lib/CategDataUtility.java    |   38 +
 Source/mesquite/categ/lib/CategInternodeEvent.java |   58 +
 Source/mesquite/categ/lib/CategMatrixManager.java  |  149 +
 Source/mesquite/categ/lib/CategStateChanges.java   |  386 ++
 .../mesquite/categ/lib/CategStateForCharacter.java |   46 +
 Source/mesquite/categ/lib/CategTModel.java         |   48 +
 .../mesquite/categ/lib/CategTModelEditWindow.java  |  376 ++
 .../mesquite/categ/lib/CategoricalAdjustable.java  |  133 +
 Source/mesquite/categ/lib/CategoricalData.java     | 2589 +++++++++
 .../categ/lib/CategoricalDistribution.java         |  241 +
 Source/mesquite/categ/lib/CategoricalEmbedded.java |   59 +
 Source/mesquite/categ/lib/CategoricalHistory.java  |  549 ++
 Source/mesquite/categ/lib/CategoricalState.java    | 1085 ++++
 Source/mesquite/categ/lib/CategoricalStates.java   |  467 ++
 .../mesquite/categ/lib/DNACharacterAdjustable.java |  125 +
 Source/mesquite/categ/lib/DNACharacterHistory.java |  209 +
 Source/mesquite/categ/lib/DNAColorTable.java       |   49 +
 Source/mesquite/categ/lib/DNAData.java             | 1540 +++++
 Source/mesquite/categ/lib/DNADataAlterer.java      |   40 +
 Source/mesquite/categ/lib/DNADataAltererCon.java   |   29 +
 Source/mesquite/categ/lib/DNADataSearcher.java     |   40 +
 Source/mesquite/categ/lib/DNADataUtility.java      |   39 +
 Source/mesquite/categ/lib/DNAEmbedded.java         |   81 +
 Source/mesquite/categ/lib/DNAState.java            |  470 ++
 .../mesquite/categ/lib/MCategoricalAdjustable.java |  137 +
 .../categ/lib/MCategoricalDistribution.java        |   68 +
 .../mesquite/categ/lib/MCategoricalEmbedded.java   |   52 +
 Source/mesquite/categ/lib/MCategoricalHistory.java |   83 +
 Source/mesquite/categ/lib/MCategoricalStates.java  |  252 +
 Source/mesquite/categ/lib/MDNAAdjustable.java      |  108 +
 Source/mesquite/categ/lib/MDNAEmbedded.java        |   91 +
 Source/mesquite/categ/lib/MDNAHistory.java         |   93 +
 Source/mesquite/categ/lib/MProteinAdjustable.java  |  107 +
 Source/mesquite/categ/lib/MProteinEmbedded.java    |   74 +
 Source/mesquite/categ/lib/MProteinHistory.java     |   93 +
 Source/mesquite/categ/lib/MesquiteSequence.java    |   36 +
 Source/mesquite/categ/lib/MolecDataEditorInit.java |   43 +
 Source/mesquite/categ/lib/MolecularData.java       |  561 ++
 .../mesquite/categ/lib/MolecularDataAlterer.java   |   40 +
 Source/mesquite/categ/lib/MolecularDataUtil.java   |  401 ++
 Source/mesquite/categ/lib/MolecularState.java      |   34 +
 .../mesquite/categ/lib/OffersCategoricalData.java  |   46 +
 Source/mesquite/categ/lib/OffersDNAData.java       |   50 +
 Source/mesquite/categ/lib/OffersProteinData.java   |   45 +
 Source/mesquite/categ/lib/ProteinAdjustable.java   |  126 +
 .../categ/lib/ProteinCharacterHistory.java         |  175 +
 Source/mesquite/categ/lib/ProteinColorTable.java   |   49 +
 Source/mesquite/categ/lib/ProteinData.java         |  417 ++
 Source/mesquite/categ/lib/ProteinEmbedded.java     |   80 +
 Source/mesquite/categ/lib/ProteinState.java        |  208 +
 .../mesquite/categ/lib/RNACharacterAdjustable.java |   95 +
 Source/mesquite/categ/lib/RNACharacterHistory.java |   96 +
 Source/mesquite/categ/lib/RNAData.java             |  102 +
 Source/mesquite/categ/lib/RNAState.java            |  196 +
 .../categ/lib/RequiresAnyCategoricalData.java      |   47 +
 Source/mesquite/categ/lib/RequiresAnyDNAData.java  |   50 +
 .../categ/lib/RequiresAnyMolecularData.java        |   47 +
 .../categ/lib/RequiresExactlyCategoricalData.java  |   46 +
 Source/mesquite/categ/lib/RequiresProteinData.java |   45 +
 .../AddCharsFromSource/AddCharsFromSource.java     |  109 +
 .../charMatrices/AddDeleteData/32addChars.gif      |  Bin 0 -> 139 bytes
 .../charMatrices/AddDeleteData/32addTaxa.gif       |  Bin 0 -> 126 bytes
 .../charMatrices/AddDeleteData/64addChars.gif      |  Bin 0 -> 187 bytes
 .../charMatrices/AddDeleteData/64addTaxa.gif       |  Bin 0 -> 170 bytes
 .../charMatrices/AddDeleteData/AddDeleteData.java  |  382 ++
 .../charMatrices/AddDeleteData/addChars.gif        |  Bin 0 -> 110 bytes
 .../charMatrices/AddDeleteData/addTaxa.gif         |  Bin 0 -> 99 bytes
 .../AlterAllMatrices/AlterAllMatrices.java         |  140 +
 .../mesquite/charMatrices/AlterData/AlterData.java |  127 +
 .../charMatrices/AnnotPanel/AnnotPanel.java        |  538 ++
 Source/mesquite/charMatrices/AnnotPanel/annot.gif  |  Bin 0 -> 101 bytes
 .../BasicDataWindowCoord/BasicDataWindowCoord.java |  273 +
 .../BasicDataWindowMaker/32colorWand.gif           |  Bin 0 -> 926 bytes
 .../BasicDataWindowMaker/64colorWand.gif           |  Bin 0 -> 981 bytes
 .../BasicDataWindowMaker/BasicDataWindowMaker.java | 5743 ++++++++++++++++++
 .../charMatrices/BasicDataWindowMaker/birdsEye.gif |  Bin 0 -> 151 bytes
 .../BasicDataWindowMaker/colorWand.gif             |  Bin 0 -> 891 bytes
 .../BooleanForCharInfoStrip.java                   |  220 +
 .../BootstrapResample/BootstrapResample.java       |   68 +
 .../CharGroupColor/CharGroupColor.java             |   98 +
 .../CharMatrixCoordIndep/CharMatrixCoordIndep.java |  228 +
 .../CharMatrixCoordObed/CharMatrixCoordObed.java   |  227 +
 .../CharReferenceStrip/CharReferenceStrip.java     |  296 +
 .../CharSelCoordinator/CharSelCoordinator.java     |  146 +
 .../CharSrcCoordIndep/CharSrcCoordIndep.java       |  188 +
 .../CharSrcCoordObed/CharSrcCoordObed.java         |  225 +
 .../ColorByCharValue/ColorByCharValue.java         |  333 ++
 .../ColorByExcluded/ColorByExcluded.java           |  104 +
 .../ColorByFootnote/ColorByFootnote.java           |  117 +
 .../ColorByMatchToFirstTaxon.java                  |  135 +
 .../charMatrices/ColorByState/ColorByState.java    |  168 +
 .../ColorByTaxonValue/ColorByTaxonValue.java       |  320 +
 .../mesquite/charMatrices/ColorCells/32color.gif   |  Bin 0 -> 137 bytes
 .../mesquite/charMatrices/ColorCells/64color.gif   |  Bin 0 -> 179 bytes
 .../charMatrices/ColorCells/ColorCells.java        |  272 +
 Source/mesquite/charMatrices/ColorCells/color.gif  |  Bin 0 -> 115 bytes
 .../charMatrices/ColorTInfo/ColorTInfo.java        |  126 +
 .../CompareMatrices/CompareMatrices.java           |  151 +
 .../ConcatRespMatrices/ConcatRespMatrices.java     |  168 +
 .../ConcatenateMatrices/ConcatenateMatrices.java   |  281 +
 .../CondensedPatternMatrix.java                    |  203 +
 .../charMatrices/DataPainter/DataPainter.java      |  257 +
 .../DataUtilityFileProcessor.java                  |  133 +
 .../DifferenceInNumsForChar.java                   |  165 +
 Source/mesquite/charMatrices/Fill/Fill.java        |   89 +
 .../IncludedCharBoolean/IncludedCharBoolean.java   |   67 +
 .../ManageAssumptionsBlock.java                    |  158 +
 .../ManageCharInclusion/ManageCharInclusion.java   |  150 +
 .../ManageCharModels/ManageCharModels.java         |  431 ++
 .../ManageCharPartitions/ManageCharPartitions.java |  366 ++
 .../ManageCharWeights/ManageCharWeights.java       |  165 +
 .../ManageCharacters/ManageCharacters.java         | 2175 +++++++
 .../ManageCharsets/ManageCharsets.java             |  154 +
 .../ManageCodonPositions/ManageCodonPositions.java |  253 +
 .../ManageCodonsBlock/ManageCodonsBlock.java       |  153 +
 .../ManageDATAblock/ManageDATAblock.java           |  196 +
 .../MatrixFromClipboard/MatrixFromClipboard.java   |  231 +
 .../charMatrices/MatrixInfoTool/32matrixInfo.gif   |  Bin 0 -> 229 bytes
 .../charMatrices/MatrixInfoTool/64matrixInfo.gif   |  Bin 0 -> 278 bytes
 .../MatrixInfoTool/MatrixInfoTool.java             |  146 +
 .../charMatrices/MatrixInfoTool/matrixInfo.gif     |  Bin 0 -> 199 bytes
 .../MatrixSelection/MatrixSelection.java           |  123 +
 Source/mesquite/charMatrices/NoColor/NoColor.java  |   77 +
 .../NumApplicableNonMissing.java                   |   79 +
 .../NumApplicableNonMissingMatrix.java             |   59 +
 .../NumForCharWithChar/NumForCharWithChar.java     |  248 +
 .../NumIncludedMatrix/NumIncludedMatrix.java       |   76 +
 .../NumTaxaWithDataInMatrix.java                   |   77 +
 .../charMatrices/PercentGaps/PercentGaps.java      |   75 +
 .../PercentMissing/PercentMissing.java             |   73 +
 .../QuickKeySelector/32quickKeyDown.gif            |  Bin 0 -> 940 bytes
 .../QuickKeySelector/32quickKeyLeft.gif            |  Bin 0 -> 944 bytes
 .../QuickKeySelector/32quickKeyRight.gif           |  Bin 0 -> 941 bytes
 .../QuickKeySelector/32quickKeySelector copy.gif   |  Bin 0 -> 175 bytes
 .../QuickKeySelector/32quickKeySelector.gif        |  Bin 0 -> 945 bytes
 .../QuickKeySelector/64quickKeyDown.gif            |  Bin 0 -> 995 bytes
 .../QuickKeySelector/64quickKeyLeft.gif            |  Bin 0 -> 997 bytes
 .../QuickKeySelector/64quickKeyRight.gif           |  Bin 0 -> 992 bytes
 .../QuickKeySelector/64quickKeySelector copy.gif   |  Bin 0 -> 221 bytes
 .../QuickKeySelector/64quickKeySelector.gif        |  Bin 0 -> 997 bytes
 .../QuickKeySelector/QuickKeySelector.java         |  252 +
 .../charMatrices/QuickKeySelector/quickKeyDown.gif |  Bin 0 -> 907 bytes
 .../charMatrices/QuickKeySelector/quickKeyLeft.gif |  Bin 0 -> 131 bytes
 .../QuickKeySelector/quickKeyRight.gif             |  Bin 0 -> 907 bytes
 .../QuickKeySelector/quickKeySelector copy.gif     |  Bin 0 -> 140 bytes
 .../QuickKeySelector/quickKeySelector.gif          |  Bin 0 -> 909 bytes
 .../RandomFillCateg/RandomFillCateg.java           |  146 +
 .../RandomFillWithMissing.java                     |  111 +
 .../RandomModRespMatrices.java                     |  205 +
 .../RandomModifMatrix/RandomModifMatrix.java       |  197 +
 .../charMatrices/RarefyMatrix/RarefyMatrix.java    |  123 +
 .../charMatrices/RecodeCateg/RecodeCateg.java      |  332 ++
 .../ReshuffleCharacter/ReshuffleCharacter.java     |  259 +
 .../ReshuffleMatrix/ReshuffleMatrix.java           |   72 +
 .../ReshuffleMatrixByPart.java                     |  123 +
 .../ReshuffleWTaxaByPart/ReshuffleWTaxaByPart.java |  171 +
 .../ReshuffleWithinTaxa/ReshuffleWithinTaxa.java   |   87 +
 .../SaveMatrixCopies/SaveMatrixCopies.java         |  318 +
 .../charMatrices/SearchData/SearchData.java        |   93 +
 .../charMatrices/SearchSelect/SearchSelect.java    |  107 +
 .../SelSummaryStrip/SelSummaryStrip.java           |  267 +
 .../SelectCharacterRanges.java                     |  147 +
 .../SelectCharsWithProbP/SelectCharsWithProbP.java |   64 +
 .../SelectDiffering/SelectDiffering.java           |  123 +
 .../SelectMatchingTaxa/SelectMatchingTaxa.java     |  149 +
 .../SelectRndCharacters/SelectRndCharacters.java   |   76 +
 .../charMatrices/SelectSame/SelectSame.java        |  164 +
 .../SelectSameVert/SelectSameVert.java             |  166 +
 .../SelectVariableCharacters.java                  |   83 +
 .../charMatrices/ShuffleStates/ShuffleStates.java  |  133 +
 .../mesquite/charMatrices/SortChar/32charSort.gif  |  Bin 0 -> 111 bytes
 .../charMatrices/SortChar/32revCharSort.gif        |  Bin 0 -> 111 bytes
 .../mesquite/charMatrices/SortChar/64charSort.gif  |  Bin 0 -> 152 bytes
 .../charMatrices/SortChar/64revCharSort.gif        |  Bin 0 -> 155 bytes
 .../mesquite/charMatrices/SortChar/SortChar.java   |  157 +
 Source/mesquite/charMatrices/SortChar/charSort.gif |  Bin 0 -> 90 bytes
 .../mesquite/charMatrices/SortChar/revCharSort.gif |  Bin 0 -> 89 bytes
 .../charMatrices/SortTaxa/32revTaxaSort.gif        |  Bin 0 -> 112 bytes
 .../mesquite/charMatrices/SortTaxa/32taxaSort.gif  |  Bin 0 -> 113 bytes
 .../charMatrices/SortTaxa/64revTaxaSort.gif        |  Bin 0 -> 153 bytes
 .../mesquite/charMatrices/SortTaxa/64taxaSort.gif  |  Bin 0 -> 154 bytes
 .../mesquite/charMatrices/SortTaxa/SortTaxa.java   |  137 +
 .../mesquite/charMatrices/SortTaxa/revTaxaSort.gif |  Bin 0 -> 873 bytes
 Source/mesquite/charMatrices/SortTaxa/taxaSort.gif |  Bin 0 -> 873 bytes
 .../SortsInCharList/SortsInCharList.java           |  162 +
 .../SortsManagerChar/SortsManagerChar.java         |  164 +
 .../SprinkleMissing/SprinkleMissing.java           |  109 +
 .../StoredCharacters/StoredCharacters.java         |  689 +++
 .../StoredMatrices/StoredMatrices.java             |  425 ++
 .../TaxonGroupColor/TaxonGroupColor.java           |   98 +
 Source/mesquite/charMatrices/Wand/32magicWand.gif  |  Bin 0 -> 117 bytes
 Source/mesquite/charMatrices/Wand/64magicWand.gif  |  Bin 0 -> 160 bytes
 Source/mesquite/charMatrices/Wand/Wand.java        |  381 ++
 Source/mesquite/charMatrices/Wand/magicWand.gif    |  Bin 0 -> 73 bytes
 .../mesquite/charMatrices/WandChar/32charWand.gif  |  Bin 0 -> 133 bytes
 .../mesquite/charMatrices/WandChar/64charWand.gif  |  Bin 0 -> 180 bytes
 .../mesquite/charMatrices/WandChar/WandChar.java   |  251 +
 Source/mesquite/charMatrices/WandChar/charWand.gif |  Bin 0 -> 106 bytes
 .../mesquite/charMatrices/WandTaxon/32taxaWand.gif |  Bin 0 -> 129 bytes
 .../mesquite/charMatrices/WandTaxon/64taxaWand.gif |  Bin 0 -> 175 bytes
 .../mesquite/charMatrices/WandTaxon/WandTaxon.java |  209 +
 .../mesquite/charMatrices/WandTaxon/taxaWand.gif   |  Bin 0 -> 103 bytes
 .../aCharMatricesIntro/aCharMatricesIntro.java     |   67 +
 Source/mesquite/charMatrices/explanation.txt       |    2 +
 Source/mesquite/charMatrices/lib/DataWindow.java   |   91 +
 .../charMatrices/lib/MatrixInfoExtraPanel.java     |   62 +
 .../charMatrices/lib/RandomMatrixModifier.java     |   35 +
 .../lib/SourceModRespectiveMatrix.java             |   83 +
 .../charMatrices/lib/SourceModifiedMatrix.java     |   79 +
 .../CharacterValuesChart/CharacterValuesChart.java |  242 +
 .../charts/CharsScattergram/CharsScattergram.java  |  374 ++
 Source/mesquite/charts/Histogram/Histogram.java    | 2518 ++++++++
 .../charts/ItemValuesChart/ItemValuesChart.java    | 1190 ++++
 .../mesquite/charts/ItemsBiplot/ItemsBiplot.java   | 1193 ++++
 .../MatrixValuesChart/MatrixValuesChart.java       |  231 +
 .../charts/NodesScattergram/NodesScattergram.java  |  754 +++
 Source/mesquite/charts/Notes/Chart Notes.txt       |    8 +
 .../mesquite/charts/Scattergram/Scattergram.java   | 1723 ++++++
 Source/mesquite/charts/ShowMean/ShowMean.java      |  302 +
 Source/mesquite/charts/ShowPercentile/001.gif      |  Bin 0 -> 6508 bytes
 Source/mesquite/charts/ShowPercentile/01.gif       |  Bin 0 -> 6508 bytes
 Source/mesquite/charts/ShowPercentile/05.gif       |  Bin 0 -> 6508 bytes
 .../charts/ShowPercentile/ShowPercentile.java      |  691 +++
 Source/mesquite/charts/ShowPercentile/manual.html  |   48 +
 .../mesquite/charts/ShowYEqualsX/ShowYEqualsX.java |  111 +
 .../charts/TaxaScattergram/TaxaScattergram.java    |  329 ++
 .../TaxonPairValuesChart/TaxonPairValuesChart.java |  247 +
 .../TaxonPairsScattergram.java                     |  351 ++
 .../charts/TaxonValuesChart/TaxonValuesChart.java  |  245 +
 .../charts/TreeBlockValues/TreeBlockValues.java    |  260 +
 .../charts/TreeValuesChart/TreeValuesChart.java    |  280 +
 .../charts/TreesScattergram/TreesScattergram.java  |  342 ++
 .../mesquite/charts/aChartsIntro/aChartsIntro.java |   63 +
 Source/mesquite/charts/explanation.txt             |    2 +
 .../AverageTreeDepth/AverageTreeDepth.java         |  103 +
 .../CoalescenceWMigration.java                     |  580 ++
 .../coalesce/CoalescentTrees/CoalescentTrees.java  |  114 +
 .../ContainedCoalescSim/ContainedCoalescSim.java   |  234 +
 .../ContainedCoalescence/ContainedCoalescence.java |  210 +
 .../DeepCoalMultLoci/DeepCoalMultLoci.java         |  263 +
 .../DeepCoalescencesG/DeepCoalescencesG.java       |   59 +
 .../DeepCoalescencesSp/DeepCoalescencesSp.java     |   58 +
 .../DuplicationsExtinctionsG.java                  |  128 +
 .../DuplicationsExtinctionsSp.java                 |  128 +
 .../mesquite/coalesce/InsertNode/32insertNode.gif  |  Bin 0 -> 130 bytes
 .../mesquite/coalesce/InsertNode/64insertNode.gif  |  Bin 0 -> 174 bytes
 .../mesquite/coalesce/InsertNode/InsertNode.java   |  126 +
 Source/mesquite/coalesce/InsertNode/insertNode.gif |  Bin 0 -> 878 bytes
 .../coalesce/LineageWidth/32adjustWidths.gif       |  Bin 0 -> 120 bytes
 .../coalesce/LineageWidth/64adjustWidths.gif       |  Bin 0 -> 164 bytes
 .../coalesce/LineageWidth/LineageWidth.java        |  234 +
 .../coalesce/LineageWidth/adjustWidths.gif         |  Bin 0 -> 94 bytes
 .../NeutralCoalescence/NeutralCoalescence.java     |  392 ++
 .../RecCoalescenceHistory.java                     |  355 ++
 .../SlatkinMaddisonS/SlatkinMaddisonS.java         |  141 +
 Source/mesquite/coalesce/TreeDepth/TreeDepth.java  |   85 +
 .../aCoalescencePkgIntro/aCoalescencePkgIntro.java |   73 +
 .../coalesce/aCoalescencePkgIntro/index.html       |  134 +
 .../coalesce/aCoalescencePkgIntro/splash.gif       |  Bin 0 -> 2484 bytes
 .../coalesce/aCoalescencePkgIntro/splash.gif copy  |  Bin 0 -> 2458 bytes
 .../coalesce/aCoalescencePkgIntro/splashSmall.gif  |  Bin 0 -> 1516 bytes
 Source/mesquite/coalesce/explanation.txt           |    3 +
 Source/mesquite/coalesce/lib/CoalescedNode.java    |  165 +
 Source/mesquite/coalesce/lib/Coalescer.java        |   35 +
 Source/mesquite/coalesce/lib/CoalescerObed.java    |   26 +
 Source/mesquite/coalesce/lib/ContainedTreeSim.java |   35 +
 Source/mesquite/coalesce/lib/GeneTreeFit.java      |   87 +
 .../coalesce/lib/NumForGeneTInSpeciesT.java        |  118 +
 Source/mesquite/coalesce/lib/SpeciesTreeFit.java   |  256 +
 Source/mesquite/coalesce/macros/s_by_depth         |  102 +
 .../consensus/ConsensusTree/ConsensusTree.java     |  317 +
 .../consensus/MajRuleTree/MajRuleTree.java         |  167 +
 Source/mesquite/consensus/Notes/Consensus Notes    |   38 +
 .../consensus/Notes/Examples/BembidionWithTrees    |  986 ++++
 .../SemistrictConsensusTree.java                   |   66 +
 .../StrictConsensusTree/StrictConsensusTree.java   |   65 +
 .../consensus/aConsensusIntro/aConsensusIntro.java |   63 +
 .../mesquite/consensus/lib/BasicTreeConsenser.java |  181 +
 Source/mesquite/consensus/lib/Bipartition.java     |  137 +
 .../mesquite/consensus/lib/BipartitionVector.java  |  587 ++
 Source/mesquite/consensus/lib/StrictConsenser.java |   42 +
 .../mesquite/cont/AddCharacter/AddCharacter.java   |  103 +
 Source/mesquite/cont/AddItem/AddItem.java          |   71 +
 Source/mesquite/cont/AddNoise/AddNoise.java        |   71 +
 Source/mesquite/cont/AddToStates/AddToStates.java  |   80 +
 .../cont/ArcSineTransform/ArcSineTransform.java    |   83 +
 .../ContCharFrTaxonValue/ContCharFrTaxonValue.java |  137 +
 .../cont/ContinuousStatesT/ContinuousStatesT.java  |  292 +
 .../DiscretizeContinuousCharacters.java            |  196 +
 .../cont/InverseContState/InverseContState.java    |   86 +
 .../cont/ItemValueInTaxon/ItemValueInTaxon.java    |  193 +
 .../ItemsEditorForInfoPanel.java                   |  344 ++
 .../mesquite/cont/LogTransform/LogTransform.java   |   83 +
 .../cont/ManageContChars/ManageContChars.java      |   32 +
 .../cont/ManageGeogChars/ManageGeogChars.java      |   77 +
 .../mesquite/cont/MapContinuous/MapContinuous.java |  301 +
 Source/mesquite/cont/MeanValue/MeanValue.java      |  174 +
 .../MultiplyByCharacter/MultiplyByCharacter.java   |   99 +
 .../cont/MultiplyStates/MultiplyStates.java        |   81 +
 .../cont/NodeLocs2DPlot/NodeLocs2DPlot.java        |  679 +++
 Source/mesquite/cont/PlotTree/PlotTree.java        |  457 ++
 .../cont/RandomFillCont/RandomFillCont.java        |   80 +
 .../cont/RandomFillUniform/RandomFillUniform.java  |   89 +
 Source/mesquite/cont/RemoveItem/RemoveItem.java    |   73 +
 Source/mesquite/cont/RenameItem/RenameItem.java    |   75 +
 .../SquareRootTransform/SquareRootTransform.java   |   83 +
 Source/mesquite/cont/Standardize/Standardize.java  |  138 +
 .../cont/XYMatrixToItems/XYMatrixToItems.java      |  157 +
 Source/mesquite/cont/aContIntro/aContIntro.java    |   63 +
 Source/mesquite/cont/explanation.txt               |    2 +
 Source/mesquite/cont/lib/BasicStatPak.java         |  484 ++
 Source/mesquite/cont/lib/ContColorTable.java       |   35 +
 Source/mesquite/cont/lib/ContDataAlterer.java      |   39 +
 Source/mesquite/cont/lib/ContDataSearcher.java     |   38 +
 Source/mesquite/cont/lib/ContDataUtility.java      |   40 +
 Source/mesquite/cont/lib/ContinuousAdjustable.java |  288 +
 Source/mesquite/cont/lib/ContinuousData.java       | 1139 ++++
 .../mesquite/cont/lib/ContinuousDistribution.java  |  148 +
 Source/mesquite/cont/lib/ContinuousEmbedded.java   |   77 +
 Source/mesquite/cont/lib/ContinuousHistory.java    |  420 ++
 Source/mesquite/cont/lib/ContinuousState.java      |  450 ++
 Source/mesquite/cont/lib/ContinuousStateTest.java  |   44 +
 Source/mesquite/cont/lib/ContinuousStates.java     |  163 +
 Source/mesquite/cont/lib/EigenAnalysis.java        |  119 +
 Source/mesquite/cont/lib/GeogDataSearcher.java     |   38 +
 Source/mesquite/cont/lib/GeogDataUtility.java      |   40 +
 Source/mesquite/cont/lib/GeographicAdjustable.java |   33 +
 Source/mesquite/cont/lib/GeographicData.java       |  193 +
 Source/mesquite/cont/lib/GeographicState.java      |   42 +
 Source/mesquite/cont/lib/GeographicStateTest.java  |   44 +
 Source/mesquite/cont/lib/GeographicStates.java     |   48 +
 Source/mesquite/cont/lib/ItemContainer.java        |   46 +
 .../mesquite/cont/lib/MContinuousAdjustable.java   |  345 ++
 .../mesquite/cont/lib/MContinuousDistribution.java |   72 +
 Source/mesquite/cont/lib/MContinuousEmbedded.java  |   72 +
 Source/mesquite/cont/lib/MContinuousHistory.java   |   81 +
 Source/mesquite/cont/lib/MContinuousStates.java    |  136 +
 Source/mesquite/cont/lib/MGeographicStates.java    |   49 +
 Source/mesquite/cont/lib/ManageContCharsA.java     |  337 ++
 Source/mesquite/cont/lib/SquaredReconstructor.java |  430 ++
 .../CorrelationViewer/CorrelationViewer.java       |  450 ++
 Source/mesquite/correl/Pagel94/Pagel94.java        |  704 +++
 .../aCorrelPackageIntro/aCorrelPackageIntro.java   |   77 +
 .../mesquite/correl/aCorrelPackageIntro/splash.gif |  Bin 0 -> 1602 bytes
 Source/mesquite/correl/lib/CLogger.java            |   20 +
 Source/mesquite/correl/lib/ComplexMatrix.java      |  268 +
 .../correl/lib/MultipleProbCategCharModel.java     |  252 +
 .../correl/lib/MultipleProbabilityModel.java       |  127 +
 Source/mesquite/correl/lib/Pagel94Calculator.java  |   37 +
 Source/mesquite/correl/lib/PagelMatrixModel.java   | 1909 ++++++
 Source/mesquite/correl/notes/PEM Notes             |    1 +
 Source/mesquite/correl/notes/Pagel94Hominids.nex   |  313 +
 Source/mesquite/correl/notes/Pagel94test.nex       |  314 +
 Source/mesquite/correl/notes/Pagel94test.ppy       |   30 +
 Source/mesquite/correl/notes/Putzer method         | 1897 ++++++
 Source/mesquite/correl/notes/disc2.nex             |  317 +
 Source/mesquite/correl/notes/disc2.ppy             |   42 +
 Source/mesquite/correl/notes/omphalina.nex         |  341 ++
 Source/mesquite/correl/notes/omphalina.ppy         |   67 +
 .../AbsoluteDistance/AbsoluteDistance.java         |  151 +
 .../AverageOfDistances/AverageOfDistances.java     |  154 +
 .../distance/ClusterAnalysis/ClusterAnalysis.java  |  163 +
 .../DistanceContainedTaxa.java                     |  286 +
 .../ExportTaxaDistances/ExportTaxaDistances.java   |  224 +
 .../mesquite/distance/F81Distance/F81Distance.java |  126 +
 .../mesquite/distance/F84Distance/F84Distance.java |  156 +
 .../JukesCantorDistance/JukesCantorDistance.java   |  103 +
 .../mesquite/distance/K2PDistance/K2PDistance.java |  110 +
 .../distance/NodeCountDist/NodeCountDist.java      |  181 +
 Source/mesquite/distance/Notes/Distance Notes      |   12 +
 Source/mesquite/distance/PDistance/PDistance.java  |  187 +
 .../PatristicDistance/PatristicDistance.java       |  160 +
 .../SharedHistoryDistance.java                     |  166 +
 .../SharedProportionalDistance.java                |  186 +
 .../distance/ShowDistance/ShowDistance.java        |   84 +
 .../distance/SingleLinkage/SingleLinkage.java      |   64 +
 .../TaxaDistFromMatrixSrc.java                     |  227 +
 .../distance/TaxonDistance/TaxonDistance.java      |  123 +
 .../TaxonPairDistance/TaxonPairDistance.java       |  201 +
 Source/mesquite/distance/UPGMA/UPGMA.java          |   74 +
 .../UncorrectedDistance/UncorrectedDistance.java   |  152 +
 .../distance/aDistanceIntro/aDistanceIntro.java    |   63 +
 Source/mesquite/distance/explanation.txt           |    4 +
 .../distance/lib/DNATaxaDistFromMatrix.java        |  108 +
 .../distance/lib/DNATaxaDistFromMatrixFreq.java    |   72 +
 Source/mesquite/distance/lib/DNATaxaDistance.java  |   38 +
 .../distance/lib/GeoTaxaDistFromMatrix.java        |   41 +
 Source/mesquite/distance/lib/GeoTaxaDistance.java  |   41 +
 .../distance/lib/IncTaxaDistanceSource.java        |   33 +
 .../distance/lib/MolecularTaxaDistance.java        |  286 +
 Source/mesquite/distance/lib/PairsWindow.java      |  145 +
 .../mesquite/distance/lib/TaxaDistFromMatrix.java  |   83 +
 Source/mesquite/distance/lib/TaxaDistance.java     |   72 +
 .../mesquite/distance/lib/TaxaDistanceSource.java  |   43 +
 Source/mesquite/distance/lib/TreeClusterer.java    |  318 +
 .../diverse/BiSSELikelihood/BiSSELikelihood.java   |  281 +
 .../BiSSELikelihoodCalculator.java                 | 1325 +++++
 .../BiSSELikelihoodRatio/BiSSELikelihoodRatio.java |  157 +
 .../diverse/BiSSETreeCharSim/BiSSETreeCharSim.java |  757 +++
 .../diverse/BirthDeathTrees/BirthDeathTrees.java   |  279 +
 .../CharAssocDivViewer/CharAssocDivViewer.java     |  326 ++
 .../CharIndepDivViewer/CharIndepDivViewer.java     |  243 +
 .../ContCharSpeciation/ContCharSpeciation.java     |  210 +
 .../DivCategCharMLCalculator.java                  | 1297 +++++
 .../DiversCategCharLikelihood.java                 |  204 +
 .../EvolveTreesDiversChars.java                    |  199 +
 .../LineagesThroughTime/LineagesThroughTime.java   |  355 ++
 .../SisterDiversification.java                     |  152 +
 .../SpecExtincLikelihood/SpecExtincLikelihood.java |  186 +
 .../SpecExtincMLCalculator.java                    |  578 ++
 .../diverse/aDiverseIntro/aDiverseIntro.java       |   77 +
 Source/mesquite/diverse/aDiverseIntro/splash.gif   |  Bin 0 -> 3120 bytes
 Source/mesquite/diverse/lib/DEQNumSolver.java      |   26 +
 Source/mesquite/diverse/lib/DESystem.java          |   22 +
 .../diverse/lib/NumForCharAndTreeDivers.java       |   42 +
 .../mesquite/diverse/lib/NumberForTreeDivers.java  |   42 +
 Source/mesquite/diverse/lib/RK4Solver.java         |  153 +
 Source/mesquite/diverse/lib/RKF45Solver.java       |  211 +
 Source/mesquite/diverse/lib/TreeCharSimulate.java  |   36 +
 .../dmanager/FuseTMSequences/FuseTMSequences.java  |   85 +
 .../FuseTaxaMatrices/FuseTaxaMatrices.java         |   84 +
 .../InterchTaxonPrefixSuffix.java                  |  116 +
 .../KeepTaxonPrefixSuffix.java                     |  104 +
 .../mesquite/dmanager/ProcessFile/ProcessFile.java |   87 +
 .../RandomizeTaxonOrder/RandomizeTaxonOrder.java   |   84 +
 .../TaxaListImportSource/TaxaListImportSource.java |   91 +
 .../TaxonNameFromSampleNamesFile.java              |  336 ++
 .../dmanager/aDmanagerIntro/aDmanagerIntro.java    |   63 +
 .../CodePosRatesCurator/CodePosRatesCurator.java   |   82 +
 .../genesis/EvolveDNAChars/EvolveDNAChars.java     |  398 ++
 .../genesis/GammaCurator/GammaCurator.java         |   72 +
 .../GammaInvarCurator/GammaInvarCurator.java       |   72 +
 .../genesis/InitDNASubmodels/InitDNASubmodels.java |   72 +
 .../genesis/InvarCurator/InvarCurator.java         |   78 +
 .../RateMatrixGTRCurator/RateMatrixGTRCurator.java |   80 +
 .../RateMatrixTiTvCurator.java                     |   78 +
 .../SimDNAModelCurator/SimDNAModelCurator.java     |  129 +
 .../StateFreqDNAEmpCurator.java                    |   85 +
 .../StateFreqUserDNACurator.java                   |   74 +
 .../genesis/aGenesisIntro/aGenesisIntro.java       |   70 +
 .../mesquite/genesis/aGenesisIntro/composite.gif   |  Bin 0 -> 37148 bytes
 Source/mesquite/genesis/aGenesisIntro/gamma.gif    |  Bin 0 -> 13481 bytes
 .../genesis/aGenesisIntro/genesisTest.html         |  188 +
 Source/mesquite/genesis/aGenesisIntro/gtr.gif      |  Bin 0 -> 13523 bytes
 Source/mesquite/genesis/aGenesisIntro/index.html   |  229 +
 Source/mesquite/genesis/aGenesisIntro/splash.gif   |  Bin 0 -> 5927 bytes
 .../mesquite/genesis/aGenesisIntro/splashSmall.gif |  Bin 0 -> 636 bytes
 .../genesis/aGenesisIntro/testimages/gamma.gif     |  Bin 0 -> 9187 bytes
 .../genesis/aGenesisIntro/testimages/gtrra.gif     |  Bin 0 -> 8707 bytes
 .../genesis/aGenesisIntro/testimages/gtrrb.gif     |  Bin 0 -> 10895 bytes
 .../genesis/aGenesisIntro/testimages/gtrrc.gif     |  Bin 0 -> 11433 bytes
 .../genesis/aGenesisIntro/testimages/gtrrd.gif     |  Bin 0 -> 8210 bytes
 .../genesis/aGenesisIntro/testimages/gtrre.gif     |  Bin 0 -> 11514 bytes
 .../genesis/aGenesisIntro/testimages/titv.gif      |  Bin 0 -> 9422 bytes
 .../genesis/aGenesisIntro/testimages/tree.gif      |  Bin 0 -> 6716 bytes
 Source/mesquite/genesis/explanation.txt            |    2 +
 .../genesis/lib/CharRateMatrixModelSet.java        |   42 +
 Source/mesquite/genesis/lib/CharRatesCodePos.java  |  281 +
 Source/mesquite/genesis/lib/CharRatesCurator.java  |   34 +
 Source/mesquite/genesis/lib/CharRatesEqual.java    |   82 +
 Source/mesquite/genesis/lib/CharRatesGamma.java    |  244 +
 .../mesquite/genesis/lib/CharRatesGammaInvar.java  |  281 +
 Source/mesquite/genesis/lib/CharRatesInvar.java    |  150 +
 Source/mesquite/genesis/lib/CharRatesModel.java    |   93 +
 .../mesquite/genesis/lib/CharRatesModelInfo.java   |   28 +
 Source/mesquite/genesis/lib/CharRatesModelSet.java |   42 +
 .../genesis/lib/CompositProbCategModel.java        |  643 +++
 Source/mesquite/genesis/lib/ProbSubModel.java      |  110 +
 .../mesquite/genesis/lib/ProbSubModelCurator.java  |  106 +
 .../mesquite/genesis/lib/ProbabilityDNAModel.java  |   59 +
 .../mesquite/genesis/lib/RateMatrixCatModel.java   |  239 +
 .../genesis/lib/RateMatrixCatModelInfo.java        |   28 +
 Source/mesquite/genesis/lib/RateMatrixCurator.java |   33 +
 .../mesquite/genesis/lib/RateMatrixDNAModel.java   |   92 +
 .../genesis/lib/RateMatrixEqualDNAModel.java       |   90 +
 .../mesquite/genesis/lib/RateMatrixGTRModel.java   |  274 +
 .../mesquite/genesis/lib/RateMatrixTiTvModel.java  |  240 +
 .../mesquite/genesis/lib/SimulationDNAModel.java   |  539 ++
 Source/mesquite/genesis/lib/StateFreqCurator.java  |   34 +
 Source/mesquite/genesis/lib/StateFreqDNAEmpir.java |  188 +
 Source/mesquite/genesis/lib/StateFreqDNAEqual.java |   90 +
 Source/mesquite/genesis/lib/StateFreqDNAModel.java |   37 +
 .../mesquite/genesis/lib/StateFreqDNASpecif.java   |  101 +
 Source/mesquite/genesis/lib/StateFreqModel.java    |  183 +
 Source/mesquite/genesis/lib/StateFreqModelSet.java |   42 +
 .../mesquite/genesis/lib/StateFreqUserCurator.java |   81 +
 .../genesis/lib/StateFreqUserDNAModel.java         |   86 +
 .../mesquite/genesis/lib/StateFreqUserModel.java   |  209 +
 Source/mesquite/genesis/lib/SubmodelInfo.java      |   61 +
 Source/mesquite/iText/aiTextIntro/aiTextIntro.java |   75 +
 Source/mesquite/iText/aiTextIntro/index.html       |   39 +
 Source/mesquite/iText/aiTextIntro/splash.ai        | 1848 ++++++
 Source/mesquite/iText/aiTextIntro/splash.gif       |  Bin 0 -> 4255 bytes
 Source/mesquite/iText/explanation.txt              |    2 +
 .../ExportCharStateInfo/ExportCharStateInfo.java   |  218 +
 .../ExportFusedMatrixNEXUS.java                    |  513 ++
 .../io/ExportFusedPhylip/ExportFusedPhylip.java    |  181 +
 .../ExportNEXUSTreeFile/ExportNEXUSTreeFile.java   |  163 +
 .../ExportPartitionFinderDNA.java                  |   69 +
 .../ExportPartitionFinderProtein.java              |   69 +
 .../ExportTreeSourceToNEXUS.java                   |  295 +
 .../InterpretClustalDNA/InterpretClustalDNA.java   |   58 +
 .../InterpretClustalProtein.java                   |   56 +
 .../io/InterpretFastaDNA/InterpretFastaDNA.java    |   90 +
 .../InterpretFastaProtein.java                     |   83 +
 .../InterpretGenBankDNA/InterpretGenBankDNA.java   |   66 +
 .../InterpretGenBankProt/InterpretGenBankProt.java |   62 +
 .../io/InterpretNBRFDNA/InterpretNBRFDNA.java      |   83 +
 .../InterpretNBRFProtein/InterpretNBRFProtein.java |   82 +
 .../InterpretNonaHennig/InterpretNonaHennig.java   |   57 +
 .../io/InterpretPOYDNA/InterpretPOYDNA.java        |  135 +
 .../io/InterpretPhylipCat/InterpretPhylipCat.java  |  103 +
 .../io/InterpretPhylipDNA/InterpretPhylipDNA.java  |   93 +
 .../InterpretPhylipProtein.java                    |   95 +
 .../InterpretPhylipTreesBasic.java                 |   53 +
 .../io/InterpretSimpleCat/InterpretSimpleCat.java  |   64 +
 .../InterpretSimpleCont/InterpretSimpleCont.java   |   71 +
 .../io/InterpretSimpleDNA/InterpretSimpleDNA.java  |   74 +
 .../InterpretSimpleGeog/InterpretSimpleGeog.java   |   71 +
 .../InterpretSimpleProtein.java                    |   68 +
 Source/mesquite/io/InterpretTNT/InterpretTNT.java  |   50 +
 .../io/InterpretTabbedCat/InterpretTabbedCat.java  |  167 +
 .../InterpretTabbedConts/InterpretTabbedConts.java |  212 +
 Source/mesquite/io/aIOIntro/aIOIntro.java          |   70 +
 Source/mesquite/io/explanation.txt                 |    2 +
 Source/mesquite/io/lib/ExportPartitionFinder.java  |  408 ++
 Source/mesquite/io/lib/IOUtil.java                 |  273 +
 Source/mesquite/io/lib/InterpretClustal.java       |  198 +
 Source/mesquite/io/lib/InterpretFasta.java         |  627 ++
 Source/mesquite/io/lib/InterpretGenBank.java       |  306 +
 Source/mesquite/io/lib/InterpretHennig86Base.java  | 1684 ++++++
 Source/mesquite/io/lib/InterpretNBRF.java          |  358 ++
 Source/mesquite/io/lib/InterpretPhylip.java        |  606 ++
 Source/mesquite/io/lib/InterpretPhylipTrees.java   |  109 +
 Source/mesquite/io/lib/InterpretSimple.java        |  254 +
 Source/mesquite/io/lib/PartitionFinderDialog.java  |   89 +
 Source/mesquite/io/lib/PhylipExporterDialog.java   |   35 +
 .../xExportConservativeNexus.java                  |  117 +
 .../xExportPartitionsNEXUS.java                    |  189 +
 .../io/xExportSimpleNexus/xExportSimpleNexus.java  |  185 +
 Source/mesquite/jama/aJamaIntro/aJamaIntro.java    |   66 +
 Source/mesquite/jama/aJamaIntro/index.html         |   40 +
 Source/mesquite/jama/aJamaIntro/splash.gif         |  Bin 0 -> 2522 bytes
 Source/mesquite/jama/explanation.txt               |    2 +
 Source/mesquite/jsci/aJSciIntro/aJSciIntro.java    |   65 +
 Source/mesquite/jsci/aJSciIntro/index.html         |   50 +
 Source/mesquite/jsci/aJSciIntro/splash.gif         |  Bin 0 -> 2866 bytes
 Source/mesquite/jsci/explanation.txt               |    2 +
 Source/mesquite/lib/Abortable.java                 |   26 +
 Source/mesquite/lib/AdjustableTree.java            |   99 +
 Source/mesquite/lib/AlertDialog.java               |  153 +
 Source/mesquite/lib/AnnotPanelOwner.java           |   26 +
 Source/mesquite/lib/Annotatable.java               |   25 +
 Source/mesquite/lib/AnnotationsPanel.java          | 1608 ++++++
 Source/mesquite/lib/Arguments.java                 |  133 +
 Source/mesquite/lib/Associable.java                | 1706 ++++++
 Source/mesquite/lib/AssociableWithSpecs.java       |  355 ++
 Source/mesquite/lib/Attachable.java                |  268 +
 Source/mesquite/lib/AttachedNote.java              |  619 ++
 Source/mesquite/lib/AttachedNotesVector.java       |  274 +
 Source/mesquite/lib/Author.java                    |   65 +
 Source/mesquite/lib/BayesianAnalysis.java          |    5 +
 Source/mesquite/lib/Binomial.java                  |   95 +
 Source/mesquite/lib/Bits.java                      |  955 +++
 Source/mesquite/lib/BitsSpecsSet.java              |  208 +
 Source/mesquite/lib/BooleanUtil.java               |   47 +
 Source/mesquite/lib/CanRetrieveTreeBlock.java      |   21 +
 Source/mesquite/lib/CardPanel.java                 |   45 +
 Source/mesquite/lib/ChangeAuthority.java           |   39 +
 Source/mesquite/lib/ChangeEvent.java               |   82 +
 Source/mesquite/lib/ChangeHistory.java             |  205 +
 Source/mesquite/lib/ChartBkgdExtra.java            |   27 +
 Source/mesquite/lib/ChartExtra.java                |  124 +
 Source/mesquite/lib/ChartField.java                |  117 +
 Source/mesquite/lib/ChartListener.java             |   24 +
 Source/mesquite/lib/ChartTool.java                 |   59 +
 Source/mesquite/lib/ChartWindow.java               |  180 +
 Source/mesquite/lib/Charter.java                   |  306 +
 Source/mesquite/lib/ChecklistDialog.java           |  265 +
 Source/mesquite/lib/CircleSymbol.java              |  112 +
 Source/mesquite/lib/Clade.java                     |   55 +
 Source/mesquite/lib/Clades.java                    |   93 +
 Source/mesquite/lib/ClassVector.java               |  107 +
 Source/mesquite/lib/CleanUpJob.java                |   25 +
 Source/mesquite/lib/ClockPanel.java                |   64 +
 Source/mesquite/lib/ClosablePanel.java             |  242 +
 Source/mesquite/lib/ClosablePanelContainer.java    |   21 +
 Source/mesquite/lib/ColorDialog.java               |  101 +
 Source/mesquite/lib/ColorDistribution.java         |  424 ++
 Source/mesquite/lib/ColorEvent.java                |   42 +
 Source/mesquite/lib/ColorEventVector.java          |   42 +
 Source/mesquite/lib/ColorPickerPanel.java          |  248 +
 Source/mesquite/lib/ColorRecord.java               |   36 +
 Source/mesquite/lib/ColorTheme.java                |  381 ++
 Source/mesquite/lib/Colorable.java                 |   29 +
 Source/mesquite/lib/CommandChecker.java            | 1036 ++++
 Source/mesquite/lib/CommandCommunicator.java       |  592 ++
 Source/mesquite/lib/CommandRecord.java             |  389 ++
 Source/mesquite/lib/CommandRecordHolder.java       |   23 +
 Source/mesquite/lib/CommandThread.java             |  164 +
 Source/mesquite/lib/Commandable.java               |   34 +
 Source/mesquite/lib/CommandableOwner.java          |   35 +
 Source/mesquite/lib/CompatibilityChecker.java      |   26 +
 Source/mesquite/lib/CompatibilityTest.java         |   37 +
 Source/mesquite/lib/ConsoleThread.java             |   92 +
 Source/mesquite/lib/ConsoleWindow.java             |   98 +
 Source/mesquite/lib/ContentArea.java               |  415 ++
 Source/mesquite/lib/Context.java                   |   25 +
 Source/mesquite/lib/DatabaseURLSource.java         |   68 +
 Source/mesquite/lib/Debugg.java                    |   74 +
 Source/mesquite/lib/DialogGraphicsPanel.java       |   41 +
 Source/mesquite/lib/DialogListener.java            |   20 +
 Source/mesquite/lib/DistanceAnalysis.java          |    5 +
 Source/mesquite/lib/Doomable.java                  |   22 +
 Source/mesquite/lib/Double2DArray.java             |  436 ++
 Source/mesquite/lib/DoubleArray.java               |  432 ++
 Source/mesquite/lib/DoubleClickList.java           |   99 +
 Source/mesquite/lib/DoubleClickListener.java       |   24 +
 Source/mesquite/lib/DoubleField.java               |  125 +
 Source/mesquite/lib/DoubleMiniScroll.java          |  103 +
 Source/mesquite/lib/DoubleSliderWindow.java        |  197 +
 Source/mesquite/lib/DoubleSqMatrixFields.java      |  174 +
 Source/mesquite/lib/DragRectangle.java             |   88 +
 Source/mesquite/lib/ETContentArea.java             |   62 +
 Source/mesquite/lib/EmployeeNeed.java              |  139 +
 Source/mesquite/lib/EmployeeVector.java            |   43 +
 Source/mesquite/lib/EmployerEmployee.java          | 2076 +++++++
 .../mesquite/lib/EnglishDecimalFormatSymbols.java  |   15 +
 Source/mesquite/lib/EnterButton.java               |  119 +
 Source/mesquite/lib/Evaluator.java                 |   22 +
 Source/mesquite/lib/Explainable.java               |   24 +
 Source/mesquite/lib/ExplanationArea.java           |  507 ++
 Source/mesquite/lib/ExponentialDistribution.java   |   36 +
 Source/mesquite/lib/ExporterDialog.java            |  103 +
 Source/mesquite/lib/ExtensibleDialog.java          | 2125 +++++++
 Source/mesquite/lib/ExtensibleExplDialog.java      |   52 +
 Source/mesquite/lib/ExtensibleListDialog.java      |  378 ++
 Source/mesquite/lib/FileBlock.java                 |  182 +
 Source/mesquite/lib/FileDirtier.java               |   27 +
 Source/mesquite/lib/FileElement.java               |  646 +++
 Source/mesquite/lib/FillableMesquiteSymbol.java    |  205 +
 Source/mesquite/lib/Fittable.java                  |   29 +
 Source/mesquite/lib/FunctionExplainable.java       |   28 +
 Source/mesquite/lib/FunctionExplanation.java       |   65 +
 Source/mesquite/lib/GraphicsUtil.java              |  463 ++
 Source/mesquite/lib/GroupLabel.java                |  108 +
 Source/mesquite/lib/HNode.java                     |   38 +
 Source/mesquite/lib/HPanel.java                    |   34 +
 Source/mesquite/lib/HTMLDescribable.java           |   25 +
 Source/mesquite/lib/HTMLSidePanel.java             |   80 +
 Source/mesquite/lib/HelpSearchManager.java         | 1053 ++++
 Source/mesquite/lib/HelpSearchStrip.java           |  173 +
 Source/mesquite/lib/HorizontalLine.java            |   51 +
 Source/mesquite/lib/Hyperlink.java                 |   36 +
 Source/mesquite/lib/Identifiable.java              |   24 +
 Source/mesquite/lib/Illustratable.java             |   29 +
 Source/mesquite/lib/ImageLabel.java                |  200 +
 Source/mesquite/lib/ImageOwner.java                |   24 +
 Source/mesquite/lib/ImagePanel.java                |  126 +
 Source/mesquite/lib/ImagePanelListener.java        |   24 +
 Source/mesquite/lib/Incrementable.java             |   30 +
 Source/mesquite/lib/InfoBar.java                   |  725 +++
 Source/mesquite/lib/Integer2DArray.java            |  316 +
 Source/mesquite/lib/IntegerArray.java              |  578 ++
 Source/mesquite/lib/IntegerField.java              |  112 +
 Source/mesquite/lib/IntegerSqMatrixFields.java     |  174 +
 Source/mesquite/lib/InterContentArea.java          |   43 +
 Source/mesquite/lib/Journal.java                   |   94 +
 Source/mesquite/lib/KeyAdapterToConsumeKeys.java   |   35 +
 Source/mesquite/lib/LabelsAtNodes.java             |   44 +
 Source/mesquite/lib/LeakFinder.java                |   21 +
 Source/mesquite/lib/Legend.java                    |  231 +
 Source/mesquite/lib/LegendHolder.java              |   22 +
 Source/mesquite/lib/LightLabel.java                |  275 +
 Source/mesquite/lib/LightLabelsAtNodes.java        |  191 +
 Source/mesquite/lib/LikelihoodAnalysis.java        |    5 +
 Source/mesquite/lib/LinearValueToPixel.java        |   94 +
 Source/mesquite/lib/ListDialog.java                |  831 +++
 Source/mesquite/lib/Listable.java                  |   24 +
 Source/mesquite/lib/ListableVector.java            |  851 +++
 Source/mesquite/lib/Listenable.java                |   40 +
 Source/mesquite/lib/Listened.java                  |  355 ++
 Source/mesquite/lib/LogValueToPixel.java           |   44 +
 Source/mesquite/lib/LogWindow.java                 |  141 +
 Source/mesquite/lib/Logger.java                    |   26 +
 Source/mesquite/lib/Long2DArray.java               |  339 ++
 Source/mesquite/lib/LongArray.java                 |  382 ++
 Source/mesquite/lib/LongField.java                 |   57 +
 Source/mesquite/lib/LowLevelListener.java          |   27 +
 Source/mesquite/lib/MRPopup.java                   |   38 +
 Source/mesquite/lib/MainThread.java                |  162 +
 Source/mesquite/lib/MarchingAnts.java              |  115 +
 Source/mesquite/lib/MenuItemsSpecsVector.java      |   43 +
 Source/mesquite/lib/MenuOwner.java                 | 2761 +++++++++
 Source/mesquite/lib/MenuVisibility.java            |   71 +
 Source/mesquite/lib/MesqJEditorPane.java           |   52 +
 Source/mesquite/lib/Mesquite3DIntPoint.java        |   29 +
 Source/mesquite/lib/MesquiteBoolean.java           |  229 +
 Source/mesquite/lib/MesquiteButton.java            |  411 ++
 Source/mesquite/lib/MesquiteCMenuItemSpec.java     |   64 +
 Source/mesquite/lib/MesquiteChart.java             | 1255 ++++
 Source/mesquite/lib/MesquiteCheckMenuItem.java     |  287 +
 Source/mesquite/lib/MesquiteCollator.java          |   78 +
 Source/mesquite/lib/MesquiteColorTable.java        |  493 ++
 Source/mesquite/lib/MesquiteCommand.java           |  356 ++
 Source/mesquite/lib/MesquiteCursor.java            |   95 +
 Source/mesquite/lib/MesquiteDialog.java            |  934 +++
 Source/mesquite/lib/MesquiteDialogParent.java      |  506 ++
 Source/mesquite/lib/MesquiteDouble.java            | 1299 +++++
 Source/mesquite/lib/MesquiteDropListener.java      |   25 +
 Source/mesquite/lib/MesquiteDropManager.java       |  133 +
 .../mesquite/lib/MesquiteDroppedFileHandler.java   |   25 +
 Source/mesquite/lib/MesquiteEvent.java             |   69 +
 Source/mesquite/lib/MesquiteException.java         |   32 +
 Source/mesquite/lib/MesquiteExternalProcess.java   |  100 +
 Source/mesquite/lib/MesquiteFile.java              | 3279 +++++++++++
 Source/mesquite/lib/MesquiteFileDialog.java        |  355 ++
 Source/mesquite/lib/MesquiteFileUtil.java          |   75 +
 Source/mesquite/lib/MesquiteFrame.java             | 2197 +++++++
 Source/mesquite/lib/MesquiteHTMLWindow.java        |  233 +
 Source/mesquite/lib/MesquiteImage.java             |  244 +
 Source/mesquite/lib/MesquiteInteger.java           |  717 +++
 Source/mesquite/lib/MesquiteLabel.java             |  251 +
 Source/mesquite/lib/MesquiteListTable.java         |  107 +
 Source/mesquite/lib/MesquiteListWindow.java        |   79 +
 Source/mesquite/lib/MesquiteListener.java          |  102 +
 Source/mesquite/lib/MesquiteLong.java              |  423 ++
 Source/mesquite/lib/MesquiteMacro.java             |  193 +
 Source/mesquite/lib/MesquiteMenu.java              |  216 +
 Source/mesquite/lib/MesquiteMenuBar.java           |   68 +
 Source/mesquite/lib/MesquiteMenuItem.java          |  265 +
 Source/mesquite/lib/MesquiteMenuItemSpec.java      |  214 +
 Source/mesquite/lib/MesquiteMenuSpec.java          |   72 +
 Source/mesquite/lib/MesquiteMessage.java           |   90 +
 Source/mesquite/lib/MesquiteModule.java            | 2696 +++++++++
 Source/mesquite/lib/MesquiteModuleInfo.java        |  492 ++
 Source/mesquite/lib/MesquiteNumber.java            | 1294 +++++
 Source/mesquite/lib/MesquitePDFFile.java           |  476 ++
 Source/mesquite/lib/MesquitePackageRecord.java     |   77 +
 Source/mesquite/lib/MesquitePanel.java             |  209 +
 Source/mesquite/lib/MesquiteParameter.java         |  237 +
 Source/mesquite/lib/MesquitePasswordField.java     |   77 +
 Source/mesquite/lib/MesquitePath2DFloat.java       |   63 +
 Source/mesquite/lib/MesquitePopup.java             |  101 +
 Source/mesquite/lib/MesquitePrintJob.java          |  306 +
 Source/mesquite/lib/MesquiteProject.java           | 2282 ++++++++
 Source/mesquite/lib/MesquiteScrollbar.java         |   44 +
 Source/mesquite/lib/MesquiteSet.java               |  210 +
 Source/mesquite/lib/MesquiteString.java            |  196 +
 Source/mesquite/lib/MesquiteSubmenu.java           |  295 +
 Source/mesquite/lib/MesquiteSubmenuSpec.java       |   68 +
 Source/mesquite/lib/MesquiteSymbol.java            |  116 +
 Source/mesquite/lib/MesquiteTabbedPane.java        |   55 +
 Source/mesquite/lib/MesquiteTabbedPanel.java       |   58 +
 Source/mesquite/lib/MesquiteTextCanvas.java        |   83 +
 Source/mesquite/lib/MesquiteTextWindow.java        |  234 +
 Source/mesquite/lib/MesquiteThread.java            |  635 ++
 Source/mesquite/lib/MesquiteTimer.java             |  157 +
 Source/mesquite/lib/MesquiteTool.java              |  346 ++
 Source/mesquite/lib/MesquiteTree.java              | 6101 ++++++++++++++++++++
 Source/mesquite/lib/MesquiteTrunk.java             |  560 ++
 Source/mesquite/lib/MesquiteWindow.java            | 3229 +++++++++++
 .../mesquite/lib/MesquiteXMLPreferencesModule.java |  126 +
 Source/mesquite/lib/MesquiteXMLUtilities.java      |  121 +
 Source/mesquite/lib/MessagePanel.java              |   63 +
 Source/mesquite/lib/MiniControl.java               |   26 +
 Source/mesquite/lib/MiniNumberEditor.java          |   45 +
 Source/mesquite/lib/MiniScroll.java                |  467 ++
 Source/mesquite/lib/MiniScrollButton.java          |  265 +
 Source/mesquite/lib/MiniSlider.java                |  364 ++
 Source/mesquite/lib/MiniSliderWithText.java        |  346 ++
 Source/mesquite/lib/MiniStringEditor.java          |   79 +
 Source/mesquite/lib/ModuleInfoWindow.java          |   73 +
 Source/mesquite/lib/ModulesInfoVector.java         |  588 ++
 Source/mesquite/lib/MousePanel.java                |  733 +++
 Source/mesquite/lib/NameHolder.java                |   27 +
 Source/mesquite/lib/NameReference.java             |  101 +
 Source/mesquite/lib/NexusBlock.java                |  375 ++
 Source/mesquite/lib/NexusBlockEditableRaw.java     |   44 +
 Source/mesquite/lib/NexusBlockTest.java            |   30 +
 Source/mesquite/lib/NexusCommandTest.java          |   26 +
 Source/mesquite/lib/NexusWritable.java             |   29 +
 Source/mesquite/lib/Notification.java              |  155 +
 Source/mesquite/lib/NumSpecsSet.java               |  177 +
 Source/mesquite/lib/Number2DArray.java             |  501 ++
 Source/mesquite/lib/NumberArray.java               | 1137 ++++
 Source/mesquite/lib/OTUIDCodeInfoCoord.java        |    1 +
 Source/mesquite/lib/OTUIDCodeInfoSource.java       |    1 +
 Source/mesquite/lib/Object2DArray.java             |  181 +
 Source/mesquite/lib/ObjectArray.java               |  222 +
 Source/mesquite/lib/ObjectContainer.java           |   56 +
 Source/mesquite/lib/ObjectSpecsSet.java            |  208 +
 Source/mesquite/lib/Optimizer.java                 | 1491 +++++
 Source/mesquite/lib/OtherAnalysis.java             |    5 +
 Source/mesquite/lib/OuterContentArea.java          |  141 +
 Source/mesquite/lib/OutputFilePathModifier.java    |    7 +
 Source/mesquite/lib/OutputFileProcessor.java       |   23 +
 Source/mesquite/lib/OwnedByModule.java             |   24 +
 Source/mesquite/lib/PanelOfCards.java              |  159 +
 Source/mesquite/lib/PanelsAtNodes.java             |  235 +
 Source/mesquite/lib/ParametersDialog.java          |  215 +
 Source/mesquite/lib/ParametersExplorable.java      |   30 +
 Source/mesquite/lib/ParseUtil.java                 |  662 +++
 Source/mesquite/lib/Parser.java                    | 1533 +++++
 Source/mesquite/lib/ParsimonyAnalysis.java         |    5 +
 Source/mesquite/lib/PathHolder.java                |   26 +
 Source/mesquite/lib/PendingCommand.java            |  337 ++
 Source/mesquite/lib/PhoneHomeRecord.java           |  124 +
 Source/mesquite/lib/PhoneHomeUtil.java             |  680 +++
 Source/mesquite/lib/PopUpPanelOfCards.java         |   75 +
 Source/mesquite/lib/Prioritizable.java             |   24 +
 Source/mesquite/lib/Priority.java                  |   24 +
 Source/mesquite/lib/ProgressIndicator.java         |  398 ++
 Source/mesquite/lib/ProgressPanel.java             |  507 ++
 Source/mesquite/lib/ProgressWindow.java            |  296 +
 Source/mesquite/lib/ProjPanelCommand.java          |   37 +
 Source/mesquite/lib/ProjPanelPanel.java            |  436 ++
 Source/mesquite/lib/ProjectRead.java               |  265 +
 Source/mesquite/lib/ProjectReadThread.java         |   70 +
 Source/mesquite/lib/Projects.java                  |  169 +
 Source/mesquite/lib/PropertyNamesProvider.java     |   18 +
 Source/mesquite/lib/PuppetThread.java              |   63 +
 Source/mesquite/lib/Puppeteer.java                 | 1408 +++++
 Source/mesquite/lib/QueryDialogs.java              |  277 +
 Source/mesquite/lib/RadioButtons.java              |  132 +
 Source/mesquite/lib/RandomBetween.java             |  117 +
 Source/mesquite/lib/Reconnectable.java             |   22 +
 Source/mesquite/lib/Renamable.java                 |   24 +
 Source/mesquite/lib/ResizableLegend.java           |  148 +
 Source/mesquite/lib/RotatedRectangle.java          |  162 +
 Source/mesquite/lib/ScrollTextField.java           |   48 +
 Source/mesquite/lib/SelectionRectangle.java        |   71 +
 Source/mesquite/lib/Selectionable.java             |   45 +
 Source/mesquite/lib/ShellScriptRunner.java         |  172 +
 Source/mesquite/lib/ShellScriptUtil.java           |  325 ++
 Source/mesquite/lib/ShellScriptWatcher.java        |   20 +
 Source/mesquite/lib/Short2DArray.java              |  293 +
 Source/mesquite/lib/ShortArray.java                |  357 ++
 Source/mesquite/lib/Showable.java                  |   26 +
 Source/mesquite/lib/SimpleIntegerField.java        |   57 +
 Source/mesquite/lib/SimpleTaxonNamer.java          |  101 +
 Source/mesquite/lib/SingleLineTextArea.java        |   61 +
 Source/mesquite/lib/SingleLineTextField.java       |   86 +
 Source/mesquite/lib/SliderWindow.java              |  197 +
 Source/mesquite/lib/Snapshot.java                  |  302 +
 Source/mesquite/lib/SpecialListName.java           |   27 +
 Source/mesquite/lib/SpecsSet.java                  |   81 +
 Source/mesquite/lib/SpecsSetVector.java            |  108 +
 Source/mesquite/lib/StringArray.java               |  494 ++
 Source/mesquite/lib/StringInABox.java              |  561 ++
 Source/mesquite/lib/StringIntegerDialog.java       |  127 +
 Source/mesquite/lib/StringIntegerListDlog.java     |   85 +
 Source/mesquite/lib/StringLister.java              |   28 +
 Source/mesquite/lib/StringUtil.java                |  Bin 0 -> 128568 bytes
 Source/mesquite/lib/SymbolGraphicsPanel.java       |   41 +
 Source/mesquite/lib/SymbolsVector.java             |   25 +
 Source/mesquite/lib/SystemWindow.java              |   24 +
 Source/mesquite/lib/TDLegendWithColors.java        |  237 +
 Source/mesquite/lib/Taxa.java                      | 1355 +++++
 Source/mesquite/lib/TaxaBitsSet.java               |   75 +
 Source/mesquite/lib/TaxaBlock.java                 |   59 +
 Source/mesquite/lib/TaxaDisplay.java               |  249 +
 Source/mesquite/lib/TaxaDisplayActive.java         |   27 +
 Source/mesquite/lib/TaxaDisplayBkgdExtra.java      |   27 +
 Source/mesquite/lib/TaxaDisplayDrawnExtra.java     |   27 +
 Source/mesquite/lib/TaxaDisplayExtra.java          |  164 +
 Source/mesquite/lib/TaxaDrawing.java               |  166 +
 Source/mesquite/lib/TaxaGroup.java                 |   69 +
 Source/mesquite/lib/TaxaGroupVector.java           |   29 +
 Source/mesquite/lib/TaxaInclusionSet.java          |   56 +
 Source/mesquite/lib/TaxaPartition.java             |  165 +
 Source/mesquite/lib/TaxaSelectionSet.java          |   41 +
 Source/mesquite/lib/TaxaSpecsSet.java              |   38 +
 Source/mesquite/lib/TaxaStringsSet.java            |   82 +
 Source/mesquite/lib/TaxaTool.java                  |  210 +
 Source/mesquite/lib/TaxaTreeDisplay.java           |  284 +
 Source/mesquite/lib/Taxon.java                     |  147 +
 Source/mesquite/lib/TaxonNamer.java                |   32 +
 Source/mesquite/lib/TaxonPair.java                 |   55 +
 Source/mesquite/lib/TextCanvasWithButtons.java     |   52 +
 Source/mesquite/lib/TextContentArea.java           |   57 +
 Source/mesquite/lib/TextRotator.java               |  168 +
 Source/mesquite/lib/TextTree.java                  |  267 +
 Source/mesquite/lib/ThermoPanel.java               |  175 +
 Source/mesquite/lib/ToolKeyListener.java           |   25 +
 Source/mesquite/lib/ToolPalette.java               |  433 ++
 Source/mesquite/lib/TranslationTable.java          |  167 +
 Source/mesquite/lib/Tree.java                      |  322 ++
 Source/mesquite/lib/TreeContext.java               |   32 +
 Source/mesquite/lib/TreeContextListener.java       |   26 +
 Source/mesquite/lib/TreeDecorator.java             |   60 +
 Source/mesquite/lib/TreeDisplay.java               |  559 ++
 Source/mesquite/lib/TreeDisplayActive.java         |   27 +
 Source/mesquite/lib/TreeDisplayBkgdExtra.java      |   27 +
 Source/mesquite/lib/TreeDisplayDrawnExtra.java     |   27 +
 Source/mesquite/lib/TreeDisplayExtra.java          |  263 +
 Source/mesquite/lib/TreeDisplayLegend.java         |  140 +
 Source/mesquite/lib/TreeDrawing.java               |  411 ++
 Source/mesquite/lib/TreeReference.java             |   69 +
 Source/mesquite/lib/TreeTool.java                  |   78 +
 Source/mesquite/lib/TreeUtil.java                  |  120 +
 Source/mesquite/lib/TreeVector.java                |  628 ++
 Source/mesquite/lib/Trees.java                     |   32 +
 Source/mesquite/lib/TwoIntegersDialog.java         |  126 +
 Source/mesquite/lib/TwoStringsDialog.java          |   72 +
 Source/mesquite/lib/UndoInstructions.java          |  514 ++
 Source/mesquite/lib/UndoReference.java             |  139 +
 Source/mesquite/lib/Undoer.java                    |   28 +
 Source/mesquite/lib/UserNamePasswordDialog.java    |   68 +
 Source/mesquite/lib/ValueToPixel.java              |  115 +
 Source/mesquite/lib/VoucherInfoFromOTUIDDB.java    |    1 +
 Source/mesquite/lib/WindowButton.java              |   54 +
 Source/mesquite/lib/WithStringDetails.java         |   24 +
 Source/mesquite/lib/XMLPreferencesProcessor.java   |   23 +
 Source/mesquite/lib/XMLUtil.java                   |  268 +
 Source/mesquite/lib/ZipUtil.java                   |  158 +
 .../lib/characters/AdjustableDistribution.java     |   48 +
 .../lib/characters/AlteredDataParameters.java      |   26 +
 .../lib/characters/CLikelihoodCalculator.java      |   26 +
 .../mesquite/lib/characters/CModelEstimator.java   |   27 +
 Source/mesquite/lib/characters/CellBlock.java      |  610 ++
 .../lib/characters/CentralModelListener.java       |   87 +
 Source/mesquite/lib/characters/CharBitsSet.java    |   38 +
 .../lib/characters/CharHistoryContainer.java       |   28 +
 .../mesquite/lib/characters/CharInclusionSet.java  |   57 +
 Source/mesquite/lib/characters/CharNumSet.java     |   37 +
 .../lib/characters/CharObjectSpecsSet.java         |   38 +
 .../mesquite/lib/characters/CharSelectionSet.java  |   43 +
 Source/mesquite/lib/characters/CharSort.java       |   46 +
 Source/mesquite/lib/characters/CharSpecsSet.java   |   41 +
 Source/mesquite/lib/characters/CharWeightSet.java  |   50 +
 Source/mesquite/lib/characters/CharacterData.java  | 3782 ++++++++++++
 .../lib/characters/CharacterDistribution.java      |   53 +
 .../mesquite/lib/characters/CharacterHistory.java  |   74 +
 Source/mesquite/lib/characters/CharacterModel.java |  390 ++
 .../lib/characters/CharacterPartition.java         |  107 +
 Source/mesquite/lib/characters/CharacterState.java |  152 +
 .../lib/characters/CharacterStateTest.java         |   31 +
 .../mesquite/lib/characters/CharacterStates.java   |  166 +
 .../lib/characters/CharacterStatesHolder.java      |   85 +
 .../mesquite/lib/characters/CharacterSubmodel.java |   30 +
 .../mesquite/lib/characters/CharactersBlock.java   |   79 +
 .../mesquite/lib/characters/CharactersGroup.java   |   54 +
 .../lib/characters/CharactersGroupVector.java      |   43 +
 .../mesquite/lib/characters/CodonPositionsSet.java |  143 +
 .../mesquite/lib/characters/DefaultReference.java  |   39 +
 .../lib/characters/MAdjustableDistribution.java    |   44 +
 .../lib/characters/MCharactersDistribution.java    |   44 +
 .../lib/characters/MCharactersHistory.java         |   30 +
 .../mesquite/lib/characters/MCharactersStates.java |  118 +
 .../lib/characters/MCharactersStatesHolder.java    |   55 +
 .../lib/characters/ModelCompatibilityInfo.java     |   40 +
 Source/mesquite/lib/characters/ModelSet.java       |   91 +
 Source/mesquite/lib/characters/ModelVector.java    |   68 +
 .../mesquite/lib/characters/ProbabilityModel.java  |  126 +
 .../lib/characters/ProbabilityModelSet.java        |   61 +
 .../lib/characters/SlicedCharacterHistory.java     |   33 +
 .../lib/characters/StoredCharacterHistory.java     |   44 +
 Source/mesquite/lib/characters/TaxaInfo.java       |   41 +
 .../lib/characters/WholeCharacterModel.java        |   30 +
 Source/mesquite/lib/duties/AnalyticalDrawTree.java |   44 +
 .../mesquite/lib/duties/BooleanForCharacter.java   |   82 +
 Source/mesquite/lib/duties/BooleanForItem.java     |   37 +
 Source/mesquite/lib/duties/BooleanForTaxon.java    |   69 +
 Source/mesquite/lib/duties/BooleanForTree.java     |   63 +
 Source/mesquite/lib/duties/BooleanForTreeIncr.java |   35 +
 Source/mesquite/lib/duties/BooleanForTreeM.java    |   40 +
 .../mesquite/lib/duties/BranchLengthsAlterer.java  |   38 +
 .../lib/duties/BranchLengthsAltererMult.java       |   38 +
 Source/mesquite/lib/duties/BranchNamesAlterer.java |   37 +
 .../lib/duties/BranchNamesAltererMult.java         |   37 +
 Source/mesquite/lib/duties/BrowseHierarchy.java    |   41 +
 Source/mesquite/lib/duties/CellColorer.java        |   33 +
 .../mesquite/lib/duties/CellColorerCharacters.java |   25 +
 Source/mesquite/lib/duties/CellColorerMatrix.java  |   25 +
 Source/mesquite/lib/duties/CellColorerTaxa.java    |   25 +
 Source/mesquite/lib/duties/CharHistorySource.java  |  115 +
 Source/mesquite/lib/duties/CharMapper.java         |   61 +
 Source/mesquite/lib/duties/CharMatrixFiller.java   |  108 +
 Source/mesquite/lib/duties/CharMatrixManager.java  |  488 ++
 .../mesquite/lib/duties/CharMatrixObedSource.java  |   77 +
 .../mesquite/lib/duties/CharMatrixOneSource.java   |   36 +
 Source/mesquite/lib/duties/CharMatrixSource.java   |   50 +
 Source/mesquite/lib/duties/CharModelCurator.java   |  219 +
 .../mesquite/lib/duties/CharSelectCoordinator.java |   35 +
 Source/mesquite/lib/duties/CharSourceCoord.java    |   75 +
 .../mesquite/lib/duties/CharSourceCoordObed.java   |  154 +
 .../mesquite/lib/duties/CharSpecsSetManager.java   |  321 +
 Source/mesquite/lib/duties/CharStatesForNodes.java |   67 +
 .../mesquite/lib/duties/CharSubmodelCurator.java   |   33 +
 .../mesquite/lib/duties/CharTableAssistantI.java   |   43 +
 .../mesquite/lib/duties/CharacterModelSource.java  |   49 +
 .../mesquite/lib/duties/CharacterObedSource.java   |  150 +
 Source/mesquite/lib/duties/CharacterOneSource.java |   39 +
 Source/mesquite/lib/duties/CharacterSelector.java  |   47 +
 Source/mesquite/lib/duties/CharacterSimulator.java |   57 +
 Source/mesquite/lib/duties/CharacterSource.java    |   44 +
 Source/mesquite/lib/duties/CharactersManager.java  |   59 +
 .../mesquite/lib/duties/CharsStatesForNodes.java   |   39 +
 Source/mesquite/lib/duties/ChartAssistant.java     |   40 +
 Source/mesquite/lib/duties/Consenser.java          |   36 +
 .../mesquite/lib/duties/CuratorWithSettings.java   |   30 +
 Source/mesquite/lib/duties/DataAlterer.java        |  146 +
 Source/mesquite/lib/duties/DataAltererCon.java     |   93 +
 .../lib/duties/DataColumnNamesAssistant.java       |  127 +
 Source/mesquite/lib/duties/DataMatcher.java        |   95 +
 Source/mesquite/lib/duties/DataSearcher.java       |  112 +
 Source/mesquite/lib/duties/DataUtility.java        |   50 +
 .../lib/duties/DataWSelectionAssistant.java        |   47 +
 .../mesquite/lib/duties/DataWindowAssistant.java   |   69 +
 .../mesquite/lib/duties/DataWindowAssistantA.java  |   35 +
 .../mesquite/lib/duties/DataWindowAssistantI.java  |   42 +
 .../mesquite/lib/duties/DataWindowAssistantID.java |   42 +
 Source/mesquite/lib/duties/DataWindowMaker.java    |   51 +
 Source/mesquite/lib/duties/DefaultsAssistant.java  |   50 +
 .../lib/duties/DisplayCharsStsAtNodes.java         |   41 +
 .../mesquite/lib/duties/DisplayNumbersAtNodes.java |   80 +
 .../mesquite/lib/duties/DisplayStatesAtNodes.java  |   45 +
 .../mesquite/lib/duties/DistanceBetween2Trees.java |   39 +
 Source/mesquite/lib/duties/DrawChart.java          |   47 +
 .../mesquite/lib/duties/DrawNamesTaxaDisplay.java  |   54 +
 .../mesquite/lib/duties/DrawNamesTreeDisplay.java  |   59 +
 Source/mesquite/lib/duties/DrawTaxa.java           |   48 +
 .../mesquite/lib/duties/DrawTaxaCoordinator.java   |   75 +
 Source/mesquite/lib/duties/DrawTree.java           |   63 +
 .../mesquite/lib/duties/DrawTreeCoordinator.java   |   84 +
 Source/mesquite/lib/duties/EditRawNexusBlock.java  |   40 +
 Source/mesquite/lib/duties/EditingCurator.java     |   29 +
 Source/mesquite/lib/duties/ElementManager.java     |   39 +
 Source/mesquite/lib/duties/EmployeeTree.java       |   41 +
 .../mesquite/lib/duties/ExternalTreeSearcher.java  |   38 +
 Source/mesquite/lib/duties/FileAssistant.java      |   36 +
 Source/mesquite/lib/duties/FileAssistantA.java     |   33 +
 Source/mesquite/lib/duties/FileAssistantC.java     |   36 +
 Source/mesquite/lib/duties/FileAssistantCH.java    |   35 +
 Source/mesquite/lib/duties/FileAssistantCP.java    |   33 +
 Source/mesquite/lib/duties/FileAssistantCS.java    |   45 +
 Source/mesquite/lib/duties/FileAssistantM.java     |   33 +
 Source/mesquite/lib/duties/FileAssistantN.java     |   33 +
 Source/mesquite/lib/duties/FileAssistantT.java     |   33 +
 Source/mesquite/lib/duties/FileCoordinator.java    |  117 +
 Source/mesquite/lib/duties/FileElementManager.java |   55 +
 Source/mesquite/lib/duties/FileInit.java           |   41 +
 Source/mesquite/lib/duties/FileInitEarlyLoad.java  |   28 +
 Source/mesquite/lib/duties/FileInterpreter.java    |  379 ++
 Source/mesquite/lib/duties/FileInterpreterI.java   |   43 +
 .../mesquite/lib/duties/FileInterpreterITree.java  |   33 +
 Source/mesquite/lib/duties/FileProcessor.java      |   59 +
 Source/mesquite/lib/duties/GeneralFileMaker.java   |   40 +
 .../mesquite/lib/duties/HistogramAssistantA.java   |   34 +
 .../mesquite/lib/duties/IncrementalConsenser.java  |   38 +
 Source/mesquite/lib/duties/ItemsBiplotter.java     |   65 +
 Source/mesquite/lib/duties/ItemsCharter.java       |   63 +
 Source/mesquite/lib/duties/ItemsSource.java        |   59 +
 Source/mesquite/lib/duties/ManageModelSet.java     |  112 +
 Source/mesquite/lib/duties/ManagerAssistant.java   |   40 +
 Source/mesquite/lib/duties/MatrixCharter.java      |   40 +
 .../lib/duties/MatrixInfoPanelAssistant.java       |   37 +
 .../lib/duties/MatrixInfoPanelAssistantI.java      |   36 +
 Source/mesquite/lib/duties/MatrixSourceCoord.java  |   70 +
 .../mesquite/lib/duties/MatrixSourceCoordObed.java |  118 +
 Source/mesquite/lib/duties/MesquiteInit.java       |   37 +
 .../mesquite/lib/duties/NexusFileInterpreter.java  |   39 +
 Source/mesquite/lib/duties/NodeChooser.java        |   36 +
 Source/mesquite/lib/duties/NodeLocs.java           |   61 +
 Source/mesquite/lib/duties/NodeLocsCircle.java     |   44 +
 Source/mesquite/lib/duties/NodeLocsFree.java       |   34 +
 Source/mesquite/lib/duties/NodeLocsPlot.java       |   36 +
 Source/mesquite/lib/duties/NodeLocsVH.java         |   40 +
 .../lib/duties/NumFor2CharHistAndTree.java         |   43 +
 .../mesquite/lib/duties/NumForCharHistAndTree.java |   43 +
 Source/mesquite/lib/duties/NumForCharTreeDep.java  |   21 +
 .../mesquite/lib/duties/NumForCharTreeIndep.java   |   22 +
 .../mesquite/lib/duties/NumberArrayForMatrix.java  |   73 +
 .../mesquite/lib/duties/NumberFor2CharAndTree.java |   43 +
 .../mesquite/lib/duties/NumberFor2Characters.java  |   42 +
 Source/mesquite/lib/duties/NumberFor2Taxa.java     |   73 +
 Source/mesquite/lib/duties/NumberFor2TaxaIncr.java |   35 +
 Source/mesquite/lib/duties/NumberFor2Trees.java    |   48 +
 .../mesquite/lib/duties/NumberForCharAndTaxon.java |   47 +
 .../mesquite/lib/duties/NumberForCharAndTree.java  |   80 +
 .../mesquite/lib/duties/NumberForCharAndTreeM.java |   42 +
 Source/mesquite/lib/duties/NumberForCharacter.java |   78 +
 .../lib/duties/NumberForCharacterIncr.java         |   24 +
 Source/mesquite/lib/duties/NumberForItem.java      |   39 +
 Source/mesquite/lib/duties/NumberForMatrix.java    |   69 +
 .../lib/duties/NumberForMatrixAndTree.java         |   76 +
 Source/mesquite/lib/duties/NumberForNode.java      |   38 +
 Source/mesquite/lib/duties/NumberForTaxaBlock.java |   63 +
 Source/mesquite/lib/duties/NumberForTaxon.java     |   68 +
 Source/mesquite/lib/duties/NumberForTaxonIncr.java |   35 +
 Source/mesquite/lib/duties/NumberForTree.java      |   87 +
 Source/mesquite/lib/duties/NumberForTreeBlock.java |   62 +
 Source/mesquite/lib/duties/NumberForTreeIncr.java  |   35 +
 Source/mesquite/lib/duties/NumberForTreeM.java     |   43 +
 .../mesquite/lib/duties/NumberForTreeWContext.java |   42 +
 Source/mesquite/lib/duties/NumbersForNodes.java    |   55 +
 .../lib/duties/NumbersForNodesAndChar.java         |   42 +
 .../lib/duties/NumbersForNodesAndHistory.java      |   42 +
 .../lib/duties/NumbersForNodesAndMatrix.java       |   42 +
 .../mesquite/lib/duties/NumbersForNodesIncr.java   |   33 +
 .../lib/duties/NumbersForNodesWith2Char.java       |  223 +
 Source/mesquite/lib/duties/OneTreeSource.java      |   51 +
 Source/mesquite/lib/duties/PackageIntro.java       |  173 +
 .../mesquite/lib/duties/PackageIntroInterface.java |   65 +
 Source/mesquite/lib/duties/ParametersExplorer.java |   38 +
 Source/mesquite/lib/duties/ReadFileFromString.java |   25 +
 .../mesquite/lib/duties/ScattergramAssistantA.java |   34 +
 Source/mesquite/lib/duties/ScriptingManager.java   |   38 +
 Source/mesquite/lib/duties/SpecsSetManager.java    |   77 +
 Source/mesquite/lib/duties/StringMatcher.java      |   33 +
 Source/mesquite/lib/duties/TWindowMaker.java       |   38 +
 .../mesquite/lib/duties/TaxaDisplayAssistant.java  |   35 +
 .../mesquite/lib/duties/TaxaDisplayAssistantA.java |   33 +
 .../lib/duties/TaxaDisplayAssistantAD.java         |   25 +
 .../mesquite/lib/duties/TaxaDisplayAssistantD.java |   37 +
 .../lib/duties/TaxaDisplayAssistantDI.java         |   35 +
 .../mesquite/lib/duties/TaxaDisplayAssistantI.java |   33 +
 .../lib/duties/TaxaDisplayAssistantMA.java         |   38 +
 Source/mesquite/lib/duties/TaxaManager.java        |   49 +
 .../mesquite/lib/duties/TaxaPartitionSource.java   |   41 +
 .../mesquite/lib/duties/TaxaSelectCoordinator.java |   35 +
 Source/mesquite/lib/duties/TaxaSource.java         |   45 +
 .../mesquite/lib/duties/TaxaTableAssistantI.java   |   39 +
 .../mesquite/lib/duties/TaxaWindowAssistant.java   |   39 +
 .../mesquite/lib/duties/TaxaWindowAssistantC.java  |   56 +
 .../mesquite/lib/duties/TaxaWindowAssistantI.java  |   36 +
 .../mesquite/lib/duties/TaxaWindowAssistantN.java  |   36 +
 Source/mesquite/lib/duties/TaxaWindowMaker.java    |   41 +
 Source/mesquite/lib/duties/TaxonNameAlterer.java   |  101 +
 Source/mesquite/lib/duties/TaxonPairSource.java    |   99 +
 Source/mesquite/lib/duties/TaxonSelector.java      |   49 +
 Source/mesquite/lib/duties/TaxonSource.java        |  113 +
 Source/mesquite/lib/duties/TaxonUtility.java       |   40 +
 Source/mesquite/lib/duties/TextDisplayer.java      |   53 +
 Source/mesquite/lib/duties/TraceCharacterInit.java |   38 +
 Source/mesquite/lib/duties/TreeAlterer.java        |   34 +
 Source/mesquite/lib/duties/TreeAltererMult.java    |   34 +
 Source/mesquite/lib/duties/TreeBlockFiller.java    |  141 +
 Source/mesquite/lib/duties/TreeBlockSource.java    |  131 +
 .../mesquite/lib/duties/TreeDisplayAssistant.java  |   44 +
 .../mesquite/lib/duties/TreeDisplayAssistantA.java |   36 +
 .../lib/duties/TreeDisplayAssistantAD.java         |   22 +
 .../lib/duties/TreeDisplayAssistantAO.java         |   37 +
 .../mesquite/lib/duties/TreeDisplayAssistantD.java |   37 +
 .../lib/duties/TreeDisplayAssistantDI.java         |   35 +
 .../mesquite/lib/duties/TreeDisplayAssistantI.java |   34 +
 .../lib/duties/TreeDisplayAssistantMA.java         |   36 +
 Source/mesquite/lib/duties/TreeInferer.java        |  191 +
 .../lib/duties/TreeInfoPanelAssistant.java         |   38 +
 Source/mesquite/lib/duties/TreeSearcher.java       |   86 +
 Source/mesquite/lib/duties/TreeSimulate.java       |   44 +
 Source/mesquite/lib/duties/TreeSource.java         |  142 +
 Source/mesquite/lib/duties/TreeSourceDefinite.java |  106 +
 Source/mesquite/lib/duties/TreeSwapper.java        |   48 +
 Source/mesquite/lib/duties/TreeTransformer.java    |   53 +
 .../mesquite/lib/duties/TreeTransformerMult.java   |   29 +
 Source/mesquite/lib/duties/TreeUtility.java        |   45 +
 Source/mesquite/lib/duties/TreeWDIAssistant.java   |   52 +
 .../mesquite/lib/duties/TreeWindowAssistant.java   |   44 +
 .../mesquite/lib/duties/TreeWindowAssistantA.java  |   36 +
 .../mesquite/lib/duties/TreeWindowAssistantC.java  |   56 +
 .../mesquite/lib/duties/TreeWindowAssistantI.java  |   36 +
 .../mesquite/lib/duties/TreeWindowAssistantN.java  |   36 +
 .../mesquite/lib/duties/TreeWindowAssistantOA.java |   36 +
 Source/mesquite/lib/duties/TreeWindowMaker.java    |   46 +
 Source/mesquite/lib/duties/TreesManager.java       |   60 +
 Source/mesquite/lib/duties/UtilitiesAssistant.java |   37 +
 .../mesquite/lib/duties/WholeCharModelCurator.java |   33 +
 Source/mesquite/lib/duties/WindowHolder.java       |   40 +
 .../mesquite/lib/simplicity/InterfaceManager.java  |  431 ++
 .../lib/simplicity/SimplicityManagerModule.java    |   38 +
 .../mesquite/lib/simplicity/SimplicityStrip.java   |  135 +
 Source/mesquite/lib/system/SystemUtil.java         |   31 +
 Source/mesquite/lib/table/AutoScrollThread.java    |   95 +
 Source/mesquite/lib/table/CMTable.java             |   33 +
 Source/mesquite/lib/table/ColumnNamesPanel.java    |  933 +++
 Source/mesquite/lib/table/CornerPanel.java         |  208 +
 Source/mesquite/lib/table/EditorPanel.java         |  553 ++
 Source/mesquite/lib/table/EditorTextField.java     |  283 +
 Source/mesquite/lib/table/MatrixPanel.java         |  742 +++
 Source/mesquite/lib/table/MesquiteTable.java       | 5826 +++++++++++++++++++
 Source/mesquite/lib/table/RowNamesPanel.java       |  547 ++
 Source/mesquite/lib/table/TableMarchingAnts.java   |   60 +
 Source/mesquite/lib/table/TableTool.java           |  211 +
 Source/mesquite/lib/table/TableWindow.java         |  312 +
 .../BooleanForCharList/BooleanForCharList.java     |  221 +
 .../BooleanForTaxaList/BooleanForTaxaList.java     |  224 +
 .../BooleanForTreeList/BooleanForTreeList.java     |  206 +
 .../lists/CharGroupList/CharGroupList.java         |  317 +
 .../CharGroupListColor/CharGroupListColor.java     |  207 +
 .../lists/CharInclSetList/CharInclSetList.java     |   97 +
 .../CharInclSetListNum/CharInclSetListNum.java     |   98 +
 .../CharListAnnotPanel/CharListAnnotPanel.java     |  239 +
 .../lists/CharListCodonPos/CharListCodonPos.java   |  263 +
 .../lists/CharListInclusion/CharListInclusion.java |  248 +
 .../lists/CharListPartition/CharListPartition.java |  356 ++
 .../lists/CharListUniqueID/CharListUniqueID.java   |  140 +
 .../lists/CharListWeights/CharListWeights.java     |  193 +
 .../lists/CharNumForList/CharNumForList.java       |  311 +
 .../lists/CharPartitionList/CharPartitionList.java |   82 +
 Source/mesquite/lists/CharSetList/CharSetList.java |   97 +
 .../lists/CharSetListNum/CharSetListNum.java       |  101 +
 .../lists/CharacterList/CharacterList.java         |  586 ++
 .../lists/CharacterStats/CharacterStats.java       |  117 +
 .../lists/CodePosSetsList/CodePosSetsList.java     |   63 +
 Source/mesquite/lists/ColorTaxon/32color.gif       |  Bin 0 -> 137 bytes
 Source/mesquite/lists/ColorTaxon/64color.gif       |  Bin 0 -> 179 bytes
 Source/mesquite/lists/ColorTaxon/ColorTaxon.java   |  153 +
 Source/mesquite/lists/ColorTaxon/color.gif         |  Bin 0 -> 115 bytes
 Source/mesquite/lists/DatasetList/DatasetList.java |  194 +
 .../lists/DatasetsListClass/DatasetsListClass.java |  113 +
 .../DatasetsListConcatenate.java                   |  183 +
 .../DatasetsListDuplicate.java                     |  104 +
 .../DatasetsListNumChars/DatasetsListNumChars.java |   95 +
 .../lists/DatasetsListTaxa/DatasetsListTaxa.java   |  119 +
 .../lists/DefaultCharOrder/DefaultCharOrder.java   |  104 +
 .../lists/DefaultTaxaOrder/DefaultTaxaOrder.java   |   88 +
 .../lists/MarkTaxonInList/MarkTaxonInList.java     |  355 ++
 .../lists/MatrixListVisible/MatrixListVisible.java |  140 +
 Source/mesquite/lists/ModelsList/ModelsList.java   |  301 +
 .../ModelsListDatatype/ModelsListDatatype.java     |   97 +
 .../ModelsListParadigm/ModelsListParadigm.java     |   98 +
 .../lists/ModelsListType/ModelsListType.java       |   97 +
 .../lists/ModelsListWhole/ModelsListWhole.java     |  107 +
 .../lists/NexusBlockList/NexusBlockList.java       |  107 +
 .../NumForCharMatrixList/NumForCharMatrixList.java |  178 +
 .../lists/NumForTaxaList/NumForTaxaList.java       |  307 +
 .../lists/NumForTreeList/NumForTreeList.java       |  198 +
 .../NumForTreeblockList/NumForTreeblockList.java   |  178 +
 .../lists/TaxaListUniqueID/TaxaListUniqueID.java   |  154 +
 .../TaxaPartListNumGroups.java                     |  100 +
 .../lists/TaxaPartitionList/TaxaPartitionList.java |   99 +
 .../lists/TaxaSetListNum/TaxaSetListNum.java       |   96 +
 .../lists/TaxablockList/TaxablockList.java         |  150 +
 .../TaxablockListNumber/TaxablockListNumber.java   |   96 +
 .../lists/TaxonGroupList/TaxonGroupList.java       |  353 ++
 .../TaxonGroupListColor/TaxonGroupListColor.java   |  222 +
 .../TaxonGroupListSymbol/TaxonGroupListSymbol.java |  256 +
 .../TaxonGroupListSymbolSize.java                  |  214 +
 .../TaxonGroupListVisibility.java                  |  153 +
 Source/mesquite/lists/TaxonList/TaxonList.java     |  546 ++
 .../TaxonListAnnotPanel/TaxonListAnnotPanel.java   |  234 +
 .../TaxonListArchivedName.java                     |  303 +
 .../TaxonListCurrPartition.java                    |  349 ++
 .../TaxonListShowAllHasData.java                   |   47 +
 .../TaxonListVoucherCode/TaxonListVoucherCode.java |    1 +
 .../TaxonListVoucherDB/TaxonListVoucherDB.java     |    1 +
 .../mesquite/lists/TaxonSetList/TaxonSetList.java  |   94 +
 .../TreeListAttachment/TreeListAttachment.java     |  138 +
 .../TreeListPolyAssumption.java                    |   89 +
 .../lists/TreeListPolys/TreeListPolys.java         |   87 +
 .../lists/TreeListRooted/TreeListRooted.java       |   87 +
 .../lists/TreeblockList/TreeblockList.java         |  167 +
 .../TreeblocksListNumber/TreeblocksListNumber.java |   96 +
 .../TreeblocksListTaxa/TreeblocksListTaxa.java     |  119 +
 Source/mesquite/lists/TreesList/TreesList.java     |  426 ++
 .../lists/WeightSetList/WeightSetList.java         |   87 +
 Source/mesquite/lists/aListsIntro/aListsIntro.java |   63 +
 Source/mesquite/lists/explanation.txt              |    2 +
 .../lists/lib/ArchivedTaxonNamesListAssistant.java |   13 +
 .../mesquite/lists/lib/CharGroupListAssistant.java |   15 +
 Source/mesquite/lists/lib/CharInclSetListAsst.java |   36 +
 Source/mesquite/lists/lib/CharListAssistant.java   |   59 +
 Source/mesquite/lists/lib/CharListAssistantI.java  |   46 +
 Source/mesquite/lists/lib/CharListModel.java       |  194 +
 .../mesquite/lists/lib/CharListPartitionUtil.java  |  129 +
 .../mesquite/lists/lib/CharMatricesListWindow.java |   35 +
 Source/mesquite/lists/lib/CharSetListAsst.java     |   36 +
 .../mesquite/lists/lib/DataSetsListAssistant.java  |   50 +
 Source/mesquite/lists/lib/DataSpecsListWindow.java |  145 +
 Source/mesquite/lists/lib/DataSpecssetList.java    |  260 +
 Source/mesquite/lists/lib/DatasetsListUtility.java |   43 +
 Source/mesquite/lists/lib/GroupDialog.java         |  156 +
 Source/mesquite/lists/lib/GroupSymbolsDialog.java  |  117 +
 Source/mesquite/lists/lib/ListAssistant.java       |  100 +
 Source/mesquite/lists/lib/ListLVModule.java        |   83 +
 Source/mesquite/lists/lib/ListModule.java          |  202 +
 Source/mesquite/lists/lib/ListTable.java           |  534 ++
 Source/mesquite/lists/lib/ListWindow.java          | 1027 ++++
 .../mesquite/lists/lib/ListableVectorWindow.java   |  131 +
 Source/mesquite/lists/lib/ModelSetListAsst.java    |   36 +
 Source/mesquite/lists/lib/ModelsListAssistant.java |   36 +
 .../lists/lib/TaxaBlocksListAssistant.java         |   35 +
 .../mesquite/lists/lib/TaxaBlocksListUtility.java  |   40 +
 Source/mesquite/lists/lib/TaxaListAssistantI.java  |   41 +
 .../mesquite/lists/lib/TaxaListPartitionUtil.java  |   43 +
 .../mesquite/lists/lib/TaxaPartListAssistant.java  |   35 +
 .../mesquite/lists/lib/TaxaSetListAssistant.java   |   35 +
 Source/mesquite/lists/lib/TaxaSpecsListWindow.java |  136 +
 Source/mesquite/lists/lib/TaxaSpecssetList.java    |  247 +
 .../lists/lib/TaxonGroupListAssistant.java         |   15 +
 Source/mesquite/lists/lib/TaxonListAssistant.java  |   52 +
 .../mesquite/lists/lib/TreeBlockListUtility.java   |   39 +
 Source/mesquite/lists/lib/TreeListAssistant.java   |   52 +
 Source/mesquite/lists/lib/TreeListInit.java        |   36 +
 Source/mesquite/lists/lib/TreeListUtility.java     |   41 +
 .../lists/lib/TreeblocksListAssistant.java         |   36 +
 .../mesquite/mb/BestBayesTree/BestBayesTree.java   |  177 +
 .../mb/ExportForMrBayes/ExportForMrBayes.java      |   68 +
 Source/mesquite/mb/MrBayesScore/MrBayesScore.java  |   80 +
 .../mb/SimplifyTaxonNames/SimplifyTaxonNames.java  |   86 +
 .../mb/TreesFromMrBayes/TreesFromMrBayes.java      |  334 ++
 Source/mesquite/mb/aMBIntro/aMBIntro.java          |   63 +
 Source/mesquite/mb/lib/ExportForMrBayesLib.java    |  312 +
 .../InitMeristicParsimony.java                     |   55 +
 .../ManageMeristicChars/ManageMeristicChars.java   |  351 ++
 .../MerItemsEditInfo/MerItemsEditInfo.java         |  338 ++
 .../ParsimonyMeristicLinear.java                   |  365 ++
 .../RandomFillMeristic/RandomFillMeristic.java     |   90 +
 .../meristic/aMeristicIntro/aMeristicIntro.java    |   63 +
 .../mesquite/meristic/lib/MMeristicAdjustable.java |  336 ++
 .../meristic/lib/MMeristicDistribution.java        |   72 +
 .../mesquite/meristic/lib/MMeristicEmbedded.java   |   72 +
 Source/mesquite/meristic/lib/MMeristicHistory.java |   81 +
 Source/mesquite/meristic/lib/MMeristicStates.java  |  137 +
 .../mesquite/meristic/lib/MeristicAdjustable.java  |  289 +
 Source/mesquite/meristic/lib/MeristicData.java     | 1174 ++++
 .../mesquite/meristic/lib/MeristicDataAlterer.java |   29 +
 .../meristic/lib/MeristicDistribution.java         |  148 +
 Source/mesquite/meristic/lib/MeristicEmbedded.java |   77 +
 Source/mesquite/meristic/lib/MeristicHistory.java  |  278 +
 .../meristic/lib/MeristicLinearParsModel.java      |   36 +
 .../meristic/lib/MeristicParsimonyModel.java       |   27 +
 Source/mesquite/meristic/lib/MeristicState.java    |  475 ++
 .../mesquite/meristic/lib/MeristicStateTest.java   |   44 +
 Source/mesquite/meristic/lib/MeristicStates.java   |  160 +
 .../meristic/lib/RequiresAnyMeristicData.java      |   44 +
 .../meristic/lib/RequiresExactlyMeristicData.java  |   42 +
 .../BasicFileCoordinator/BasicFileCoordinator.java | 2128 +++++++
 .../BasicFileCoordinator/ProjectWindow.java        | 1860 ++++++
 .../minimal/BasicFileCoordinator/index.html        |   28 +
 .../BasicFileCoordinator/projectHTML/base.html     |   13 +
 .../projectHTML/baseMatrix.html                    |   33 +
 .../projectHTML/baseTaxaBlock.html                 |   46 +
 .../projectHTML/baseTreesBlock.html                |   33 +
 .../projectHTML/charModelSmall.gif                 |  Bin 0 -> 145 bytes
 .../BasicFileCoordinator/projectHTML/chart.gif     |  Bin 0 -> 519 bytes
 .../BasicFileCoordinator/projectHTML/delete.gif    |  Bin 0 -> 301 bytes
 .../projectHTML/fileInclude.gif                    |  Bin 0 -> 244 bytes
 .../projectHTML/fileIncludeBasic.gif               |  Bin 0 -> 191 bytes
 .../projectHTML/fileIncludeTrees.gif               |  Bin 0 -> 256 bytes
 .../BasicFileCoordinator/projectHTML/fileLink.gif  |  Bin 0 -> 258 bytes
 .../projectHTML/fileLinkTrees.gif                  |  Bin 0 -> 271 bytes
 .../projectHTML/fileLinkedSmall.gif                |  Bin 0 -> 139 bytes
 .../projectHTML/fileMergeTM.gif                    |  Bin 0 -> 237 bytes
 .../BasicFileCoordinator/projectHTML/fileSmall.gif |  Bin 0 -> 96 bytes
 .../BasicFileCoordinator/projectHTML/list.gif      |  Bin 0 -> 1108 bytes
 .../projectHTML/matrixCateg.gif                    |  Bin 0 -> 325 bytes
 .../projectHTML/matrixCategSmall.gif               |  Bin 0 -> 151 bytes
 .../projectHTML/matrixCategSmallINREPOSITORY.gif   |  Bin 0 -> 223 bytes
 .../projectHTML/matrixCategSmallUNCOMMITTED.gif    |  Bin 0 -> 174 bytes
 .../projectHTML/matrixCont.gif                     |  Bin 0 -> 1226 bytes
 .../projectHTML/matrixContSmall.gif                |  Bin 0 -> 162 bytes
 .../projectHTML/matrixContSmallINREPOSITORY.gif    |  Bin 0 -> 236 bytes
 .../projectHTML/matrixContSmallUNCOMMITTED.gif     |  Bin 0 -> 239 bytes
 .../projectHTML/matrixMeristic.gif                 |  Bin 0 -> 343 bytes
 .../projectHTML/matrixMeristicSmall.gif            |  Bin 0 -> 152 bytes
 .../matrixMeristicSmallINREPOSITORY.gif            |  Bin 0 -> 226 bytes
 .../projectHTML/matrixMeristicSmallUNCOMMITTED.gif |  Bin 0 -> 173 bytes
 .../projectHTML/matrixMolec.gif                    |  Bin 0 -> 421 bytes
 .../projectHTML/matrixMolecSmall.gif               |  Bin 0 -> 156 bytes
 .../projectHTML/matrixMolecSmallINREPOSITORY.gif   |  Bin 0 -> 233 bytes
 .../projectHTML/matrixMolecSmallUNCOMMITTED.gif    |  Bin 0 -> 237 bytes
 .../BasicFileCoordinator/projectHTML/project.html  |  138 +
 .../projectHTML/projectPanel.jpg                   |  Bin 0 -> 56968 bytes
 .../projectHTML/projectSimple.html                 |  117 +
 .../BasicFileCoordinator/projectHTML/queryGray.gif |  Bin 0 -> 152 bytes
 .../BasicFileCoordinator/projectHTML/rename.gif    |  Bin 0 -> 346 bytes
 .../projectHTML/taxaAssocSmall.gif                 |  Bin 0 -> 132 bytes
 .../projectHTML/taxaAssocSmallINREPOSITORY.gif     |  Bin 0 -> 236 bytes
 .../projectHTML/taxaAssocSmallUNCOMMITTED.gif      |  Bin 0 -> 180 bytes
 .../BasicFileCoordinator/projectHTML/taxaBlock.gif |  Bin 0 -> 1077 bytes
 .../projectHTML/taxaBlockSmall.gif                 |  Bin 0 -> 872 bytes
 .../projectHTML/taxaBlockSmallINREPOSITORY.gif     |  Bin 0 -> 215 bytes
 .../projectHTML/taxaBlockSmallUNCOMMITTED.gif      |  Bin 0 -> 161 bytes
 .../BasicFileCoordinator/projectHTML/treeView.gif  |  Bin 0 -> 308 bytes
 .../BasicFileCoordinator/projectHTML/trees.gif     |  Bin 0 -> 1080 bytes
 .../projectHTML/treesSmall.gif                     |  Bin 0 -> 109 bytes
 .../projectHTML/treesSmallINREPOSITORY.gif         |  Bin 0 -> 214 bytes
 .../projectHTML/treesSmallUNCOMMITTED.gif          |  Bin 0 -> 163 bytes
 .../minimal/BasicFileCoordinator/splash.gif        |  Bin 0 -> 1019 bytes
 .../minimal/BasicFileCoordinator/splash.gif copy   |  Bin 0 -> 968 bytes
 .../minimal/BasicFileCoordinator/splashSmall.gif   |  Bin 0 -> 460 bytes
 Source/mesquite/minimal/Defaults/Defaults.java     |  574 ++
 .../minimal/DrawHierarchy/DrawHierarchy.java       |  584 ++
 .../mesquite/minimal/IDsDefaults/IDsDefaults.java  |  125 +
 Source/mesquite/minimal/Installer/Installer.java   |  662 +++
 .../NoticesAndInstallationExplanation.xml          |  197 +
 .../mesquite/minimal/Installer/installExample.xml  |   29 +
 .../mesquite/minimal/Installer/noticeExample.xml   |   17 +
 .../mesquite/minimal/Installer/updateExample.xml   |   42 +
 .../minimal/InterpretNEXUS/InterpretNEXUS.java     |  692 +++
 .../ManageForeignBlocks/ManageForeignBlocks.java   |  218 +
 .../ManageMesquiteBlock/ManageMesquiteBlock.java   |  346 ++
 Source/mesquite/minimal/ManageTaxa/ManageTaxa.java | 1342 +++++
 .../minimal/NEXUSDefaults/NEXUSDefaults.java       |  103 +
 Source/mesquite/minimal/OpenURL/OpenURL.java       |  109 +
 .../minimal/ShowEmployeeTree/ShowEmployeeTree.java |  110 +
 Source/mesquite/minimal/Simplicity/Simplicity.java |  530 ++
 .../minimal/Simplicity/SimplifyControlWindow.java  |  894 +++
 .../mesquite/minimal/Simplicity/instructions.html  |   21 +
 .../minimal/Simplicity/simplification.html         |   15 +
 .../Simplicity/simplifications/abMacclade.xml      |  168 +
 .../Simplicity/simplifications/acBasicPopGen.xml   |  407 ++
 .../Simplicity/simplifications/adMorphPhyl.xml     |   76 +
 .../Simplicity/simplifications/zaNoneHidden.xml    |   12 +
 .../Simplicity/simplifications/zzMinimal.xml       |  672 +++
 Source/mesquite/minimal/StoredTaxa/StoredTaxa.java |  163 +
 Source/mesquite/minimal/Utilities/Utilities.java   |   48 +
 .../minimal/WindowBabysitter/WindowBabysitter.java |   57 +
 Source/mesquite/minimal/explanation.txt            |    2 +
 .../molec/AAHydrophobicity/AAHydrophobicity.java   |   71 +
 Source/mesquite/molec/AASize/AASize.java           |   65 +
 .../AminoAcidProperties/AminoAcidProperties.java   |  126 +
 .../molec/AssignGeneticCode/AssignGeneticCode.java |  106 +
 .../AvgSequenceLengthMatrix.java                   |   75 +
 Source/mesquite/molec/BLASTSearch/BLASTSearch.java |  117 +
 .../molec/CGBiasOfTaxon/CGBiasOfTaxon.java         |  160 +
 .../CharListGenCodeModels.java                     |  262 +
 .../molec/CharacterGCBias/CharacterGCBias.java     |  174 +
 .../molec/CleanUpMatrix/CleanUpMatrix.java         |  185 +
 Source/mesquite/molec/CodesetList/CodesetList.java |  103 +
 .../molec/CollapseEdges/CollapseEdges.java         |   78 +
 Source/mesquite/molec/ColorByAA/ColorByAA.java     |  194 +
 .../molec/ColorByNumber/ColorByNumber.java         |  340 ++
 Source/mesquite/molec/ColorOddAAs/ColorOddAAs.java |  200 +
 .../CompareBasesWithTaxon.java                     |  114 +
 Source/mesquite/molec/ConvertToRY/ConvertToRY.java |   93 +
 .../CurrentGenCodeModels/CurrentGenCodeModels.java |  307 +
 .../mesquite/molec/FetchGenBank/FetchGenBank.java  |  132 +
 .../molec/FillCharSelection/FillCharSelection.java |   80 +
 Source/mesquite/molec/FindMissing/FindMissing.java |   81 +
 .../FindPartialTriplet/FindPartialTriplet.java     |  100 +
 .../mesquite/molec/FindSequence/FindSequence.java  |  188 +
 .../molec/GBLOCKSSelector/GBLOCKSSelector.java     |  110 +
 Source/mesquite/molec/GCAsNumber/GCAsNumber.java   |   73 +
 .../molec/GapsToMissing/GapsToMissing.java         |   75 +
 .../molec/GenBankNumber/GenBankNumber.java         |  217 +
 .../molec/InitializeGenCode/InitializeGenCode.java |  106 +
 .../molec/LowercaseEnds/LowercaseEnds.java         |  142 +
 .../molec/MaintainClipMatch/MaintainClipMatch.java |   85 +
 .../molec/ManageCodeSets/ManageCodeSets.java       |  150 +
 .../molec/MatchingSequence/MatchingSequence.java   |  221 +
 .../molec/MeanValueLinked/MeanValueLinked.java     |  183 +
 .../molec/MissingToGaps/MissingToGaps.java         |   76 +
 Source/mesquite/molec/NCBIBlaster/NCBIBlaster.java |   72 +
 .../NucleotideComplement/NucleotideComplement.java |   73 +
 .../NumInternalGapsMatrix.java                     |   78 +
 .../mesquite/molec/NumLowerCase/NumLowerCase.java  |   73 +
 .../NumStopCodonsMatrix/NumStopCodonsMatrix.java   |   73 +
 .../molec/NumberPolyInTaxon/NumberPolyInTaxon.java |  140 +
 .../NumberStopsInTaxon/NumberStopsInTaxon.java     |  146 +
 .../PercentGapsInTaxon/PercentGapsInTaxon.java     |  192 +
 .../molec/PercentLowerCase/PercentLowerCase.java   |  134 +
 .../PercentMissingInTaxon.java                     |  148 +
 .../PercentPolymorphic/PercentPolymorphic.java     |   85 +
 .../molec/PropInternalGaps/PropInternalGaps.java   |  125 +
 .../molec/PropTerminalGaps/PropTerminalGaps.java   |  121 +
 .../molec/PropUnambigSites/PropUnambigSites.java   |  166 +
 .../molec/ReverseComplement/ReverseComplement.java |   62 +
 .../molec/ReverseSequence/ReverseSequence.java     |   82 +
 .../SequenceInfoEditor/SequenceInfoEditor.java     |  283 +
 .../molec/SequenceLength/SequenceLength.java       |  166 +
 .../mesquite/molec/SiteProperty/SiteProperty.java  |  169 +
 .../StoredGenCodeModel/StoredGenCodeModel.java     |  219 +
 .../molec/TargetSeqMatch/TargetSeqMatch.java       |   78 +
 .../molec/TaxaListHasData/TaxaListHasData.java     |  683 +++
 Source/mesquite/molec/TaxonGCBias/TaxonGCBias.java |  271 +
 .../molec/TermGapsToMissing/TermGapsToMissing.java |  115 +
 .../molec/TermMissingToGaps/TermMissingToGaps.java |  114 +
 Source/mesquite/molec/ToLowerCase/ToLowerCase.java |   81 +
 Source/mesquite/molec/ToUpperCase/ToUpperCase.java |   83 +
 .../molec/TopBlastMatches/TopBlastMatches.java     |  422 ++
 .../TranslateToProtein/TranslateToProtein.java     |  134 +
 .../TrimTermPartTriplets/TrimTermPartTriplets.java |  117 +
 Source/mesquite/molec/aMolecIntro/aMolecIntro.java |   63 +
 Source/mesquite/molec/amino acid properties        |  831 +++
 Source/mesquite/molec/explanation.txt              |    2 +
 Source/mesquite/molec/lib/AAProperty.java          |   44 +
 Source/mesquite/molec/lib/BLASTResults.java        |  319 +
 Source/mesquite/molec/lib/Blaster.java             |  112 +
 .../mesquite/molec/lib/DNADatabaseURLSource.java   |   53 +
 .../mesquite/molec/lib/FindSequenceCriterion.java  |   41 +
 .../mesquite/molec/lib/FindSequenceCriterionG.java |   50 +
 Source/mesquite/molec/lib/GBLOCKSCalculator.java   |  509 ++
 Source/mesquite/molec/lib/GenCodeBacteria.java     |   41 +
 Source/mesquite/molec/lib/GenCodeCiliate.java      |   43 +
 Source/mesquite/molec/lib/GenCodeEchino.java       |   44 +
 Source/mesquite/molec/lib/GenCodeEuplotid.java     |   42 +
 Source/mesquite/molec/lib/GenCodeInvertMito.java   |   45 +
 Source/mesquite/molec/lib/GenCodeModel.java        |   70 +
 .../mesquite/molec/lib/GenCodeModelBacteria.java   |   29 +
 Source/mesquite/molec/lib/GenCodeModelCiliate.java |   29 +
 Source/mesquite/molec/lib/GenCodeModelEchino.java  |   29 +
 .../mesquite/molec/lib/GenCodeModelEuplotid.java   |   29 +
 .../mesquite/molec/lib/GenCodeModelInvertMito.java |   29 +
 .../molec/lib/GenCodeModelMoldProtMito.java        |   29 +
 Source/mesquite/molec/lib/GenCodeModelSet.java     |   65 +
 Source/mesquite/molec/lib/GenCodeModelSource.java  |   41 +
 .../mesquite/molec/lib/GenCodeModelStandard.java   |   31 +
 .../mesquite/molec/lib/GenCodeModelVertMito.java   |   31 +
 .../mesquite/molec/lib/GenCodeModelYeastMito.java  |   29 +
 Source/mesquite/molec/lib/GenCodeMoldProtMito.java |   41 +
 Source/mesquite/molec/lib/GenCodeStandard.java     |   41 +
 Source/mesquite/molec/lib/GenCodeVertMito.java     |   45 +
 Source/mesquite/molec/lib/GenCodeYeastMito.java    |   50 +
 Source/mesquite/molec/lib/GeneticCode.java         |  303 +
 .../mesquite/molec/lib/MaintainSequenceMatch.java  |  417 ++
 Source/mesquite/molec/lib/NCBIUtil.java            | 1063 ++++
 Source/mesquite/molec/lib/SeqLedge.java            |   30 +
 .../ornamental/BranchNotes/32asteriskTool.gif      |  Bin 0 -> 147 bytes
 .../ornamental/BranchNotes/64asteriskTool.gif      |  Bin 0 -> 192 bytes
 .../ornamental/BranchNotes/BranchNotes.java        |  273 +
 .../ornamental/BranchNotes/asteriskBIGTool.gif     |  Bin 0 -> 131 bytes
 .../ornamental/BranchNotes/asteriskTool.gif        |  Bin 0 -> 122 bytes
 .../ornamental/CircularTree/CircularTree.java      |  576 ++
 .../ColorTreeByPartition/ColorTreeByPartition.java |  292 +
 .../ornamental/Constellation/Constellation.java    |  382 ++
 .../DrawTreeAssocDoubles/DrawTreeAssocDoubles.java |  489 ++
 .../DrawTreeAssocStrings/DrawTreeAssocStrings.java |  405 ++
 .../ManageAttachedNotes/ManageAttachedNotes.java   |  666 +++
 .../ManageHyperlinks/ManageHyperlinks.java         |  216 +
 .../ornamental/ManagePictures/ManagePictures.java  |  263 +
 .../NodeLocsCircular/NodeLocsCircular.java         |  457 ++
 .../ornamental/NodeLocsOval/NodeLocsOval.java      |  430 ++
 .../ornamental/NodeNumbers/NodeNumbers.java        |  141 +
 .../NodePositionAdjust/32adjustPosition.gif        |  Bin 0 -> 158 bytes
 .../NodePositionAdjust/64adjustPosition.gif        |  Bin 0 -> 206 bytes
 .../NodePositionAdjust/NodePositionAdjust.java     |  306 +
 .../NodePositionAdjust/adjustPosition.gif          |  Bin 0 -> 909 bytes
 .../PictureWindowMaker/PictureWindowMaker.java     |  203 +
 .../mesquite/ornamental/Projector/32projector.gif  |  Bin 0 -> 976 bytes
 .../mesquite/ornamental/Projector/64projector.gif  |  Bin 0 -> 1032 bytes
 .../mesquite/ornamental/Projector/Projector.java   |  393 ++
 Source/mesquite/ornamental/Projector/projector.gif |  Bin 0 -> 934 bytes
 Source/mesquite/ornamental/TaxonLink/32link.gif    |  Bin 0 -> 169 bytes
 Source/mesquite/ornamental/TaxonLink/64link.gif    |  Bin 0 -> 213 bytes
 .../mesquite/ornamental/TaxonLink/TaxonLink.java   |  363 ++
 Source/mesquite/ornamental/TaxonLink/link.gif      |  Bin 0 -> 145 bytes
 .../aOrnamentalIntro/aOrnamentalIntro.java         |   63 +
 Source/mesquite/ornamental/explanation.txt         |    2 +
 .../pairwise/PairsNoChars/PairsNoChars.java        |  461 ++
 .../pairwise/PairsOneChar/PairsOneChar.java        |  550 ++
 .../pairwise/PairsTwoChars/PairsTwoChars.java      |  755 +++
 .../PairwiseComparison/PairwiseComparison.java     | 1026 ++++
 .../pairwise/aPairwiseIntro/aPairwiseIntro.java    |   68 +
 Source/mesquite/pairwise/aPairwiseIntro/index.html |   57 +
 Source/mesquite/pairwise/explanation.txt           |    2 +
 Source/mesquite/pairwise/lib/PairMaker.java        |  104 +
 Source/mesquite/pairwise/lib/PairMakerChars.java   |   38 +
 Source/mesquite/pairwise/lib/TaxaPairer.java       |   37 +
 Source/mesquite/pairwise/lib/TaxaPairerChars.java  |   29 +
 Source/mesquite/pairwise/lib/TaxaPairing.java      |   74 +
 Source/mesquite/pairwise/lib/TaxaPath.java         |   64 +
 Source/mesquite/pal/aPALIntro/aPALIntro.java       |   66 +
 Source/mesquite/pal/aPALIntro/index.html           |   43 +
 Source/mesquite/pal/aPALIntro/splash.gif           |  Bin 0 -> 1619 bytes
 Source/mesquite/pal/explanation.txt                |    2 +
 .../CharListParsModels/CharListParsModels.java     |  207 +
 .../CharStepsDifference/CharStepsDifference.java   |  211 +
 .../ConsistIndexChar/ConsistIndexChar.java         |  119 +
 .../ConsistIndexMatrix/ConsistIndexMatrix.java     |  111 +
 .../CurrentParsModels/CurrentParsModels.java       |  299 +
 .../InitCategParsimony/InitCategParsimony.java     |   64 +
 .../InitContParsimony/InitContParsimony.java       |   59 +
 .../InitializeParsimony/InitializeParsimony.java   |   64 +
 .../parsimony/ManageTypesets/ManageTypesets.java   |  133 +
 .../ParsAncestralStates/ParsAncestralStates.java   |  286 +
 .../parsimony/ParsCharSteps/ParsCharSteps.java     |  173 +
 .../ParsimonyCostMatrix/ParsimonyCostMatrix.java   |  440 ++
 .../parsimony/ParsimonyLinear/ParsimonyLinear.java |  362 ++
 .../ParsimonyOrdered/ParsimonyOrdered.java         |  588 ++
 .../ParsimonySquared/ParsimonySquared.java         |  213 +
 .../ParsimonyUnordered/ParsimonyUnordered.java     |  479 ++
 .../RetentionIndexChar/RetentionIndexChar.java     |  126 +
 .../RetentionIndexMatrix/RetentionIndexMatrix.java |  117 +
 .../StepMatrixCurator/StepMatrixCurator.java       |  499 ++
 .../StepsInCharacter/StepsInCharacter.java         |  241 +
 .../parsimony/StoredParsModel/StoredParsModel.java |  210 +
 .../mesquite/parsimony/Treelength/Treelength.java  |  134 +
 .../TreelengthForMatrix/TreelengthForMatrix.java   |  121 +
 .../parsimony/TypesetList/TypesetList.java         |   92 +
 .../parsimony/aParsimonyIntro/aParsimonyIntro.java |   65 +
 Source/mesquite/parsimony/explanation.txt          |    2 +
 .../parsimony/lib/CategParsimonyModel.java         |   28 +
 Source/mesquite/parsimony/lib/CharacterSteps.java  |   34 +
 .../mesquite/parsimony/lib/ContParsimonyModel.java |   29 +
 Source/mesquite/parsimony/lib/CostMatrixModel.java |   45 +
 Source/mesquite/parsimony/lib/DolloModel.java      |   39 +
 .../mesquite/parsimony/lib/IrreversibleModel.java  |   39 +
 Source/mesquite/parsimony/lib/LinearModel.java     |   36 +
 Source/mesquite/parsimony/lib/MPRProcessor.java    |  274 +
 Source/mesquite/parsimony/lib/OrderedModel.java    |   39 +
 .../parsimony/lib/ParsAncStatesForModel.java       |   57 +
 Source/mesquite/parsimony/lib/ParsModelSource.java |   41 +
 Source/mesquite/parsimony/lib/ParsimonyModel.java  |   42 +
 .../mesquite/parsimony/lib/ParsimonyModelSet.java  |   44 +
 Source/mesquite/parsimony/lib/SquaredModel.java    |   36 +
 Source/mesquite/parsimony/lib/UnorderedModel.java  |   43 +
 .../CanonicalVariates/CanonicalVariates.java       |   84 +
 .../CharFromOrdinations/CharFromOrdinations.java   |  353 ++
 .../rhetenor/CharLoadings/CharLoadings.java        |  109 +
 .../CharsFromMatrices/CharsFromMatrices.java       |  384 ++
 .../rhetenor/EvolutionaryPCA/EvolutionaryPCA.java  |   81 +
 .../rhetenor/LandmarkDrawings/32landmark.gif       |  Bin 0 -> 157 bytes
 .../rhetenor/LandmarkDrawings/64landmark.gif       |  Bin 0 -> 205 bytes
 .../LandmarkDrawings/LandmarkDrawings.java         |  831 +++
 .../rhetenor/LandmarkDrawings/landmark.gif         |  Bin 0 -> 123 bytes
 .../MatricesFromOrdinations.java                   |  298 +
 .../rhetenor/NodeLocs3DPlot/NodeLocs3DPlot.java    | 1267 ++++
 .../mesquite/rhetenor/PlotTree3D/PlotTree3D.java   |  519 ++
 .../PrincipalComponents/PrincipalComponents.java   |   67 +
 .../ShowCharLoadings/ShowCharLoadings.java         |  181 +
 Source/mesquite/rhetenor/aPCA/aPCA.java            |   77 +
 .../rhetenor/aRhetenorIntro/aRhetenorIntro.java    |   71 +
 Source/mesquite/rhetenor/aRhetenorIntro/index.html |   67 +
 Source/mesquite/rhetenor/aRhetenorIntro/splash.gif |  Bin 0 -> 1431 bytes
 .../rhetenor/aRhetenorIntro/splash.gif copy        |  Bin 0 -> 1369 bytes
 .../rhetenor/aRhetenorIntro/splashSmall.gif        |  Bin 0 -> 912 bytes
 Source/mesquite/rhetenor/explanation.txt           |    2 +
 Source/mesquite/rhetenor/lib/CVAOrdination.java    |   39 +
 .../mesquite/rhetenor/lib/CharacterLoadings.java   |   42 +
 .../rhetenor/lib/CharsFromMatrixSource.java        |   39 +
 Source/mesquite/rhetenor/lib/EPCAOrdination.java   |   92 +
 Source/mesquite/rhetenor/lib/MatrixUtil.java       | 1098 ++++
 Source/mesquite/rhetenor/lib/NodeLocsPlot3D.java   |   40 +
 Source/mesquite/rhetenor/lib/Ordination.java       |   89 +
 .../mesquite/rhetenor/lib/OrdinationAssistant.java |   38 +
 Source/mesquite/rhetenor/lib/Ordinator.java        |   41 +
 .../mesquite/rhetenor/lib/PCACorrelOrdination.java |   36 +
 Source/mesquite/rhetenor/lib/PCAOrdination.java    |   37 +
 Source/mesquite/rhetenor/lib/aPCAOrdination.java   |   36 +
 Source/mesquite/rhetenor/lib/wPCAOrdination.java   |   36 +
 Source/mesquite/rhetenor/wPCA/wPCA.java            |   86 +
 .../search/AddAndRearrange/AddAndRearrange.java    |  349 ++
 .../DistanceTreeSearch/DistanceTreeSearch.java     |   39 +
 .../LikelihoodTreeSearch/LikelihoodTreeSearch.java |   34 +
 .../search/NNIRearranger/NNIRearranger.java        |  126 +
 .../OldStyleTreeSearch/OldStyleTreeSearch.java     |   58 +
 .../search/OtherTreeSearch/OtherTreeSearch.java    |   58 +
 .../ParsimonyTreeSearch/ParsimonyTreeSearch.java   |   35 +
 .../search/SPRRearranger/SPRRearranger.java        |  205 +
 .../mesquite/search/aSearchIntro/aSearchIntro.java |   58 +
 Source/mesquite/search/explanation.txt             |    2 +
 Source/mesquite/search/lib/TreeSearch.java         |  195 +
 .../stochchar/AsymmMkExplorer/AsymmMkExplorer.java |  238 +
 .../AsymmModelCurator/AsymmModelCurator.java       |  275 +
 .../stochchar/AsymmetryLR/AsymmetryLR.java         |  158 +
 Source/mesquite/stochchar/Brownian/Brownian.java   |  123 +
 .../stochchar/CharLikelihood/CharLikelihood.java   |  206 +
 .../CharListProbModels/CharListProbModels.java     |  215 +
 .../CurrentProbModels/CurrentProbModels.java       |  302 +
 .../EvolveCategChars/EvolveCategChars.java         |  338 ++
 .../EvolveContinuous/EvolveContinuous.java         |  310 +
 .../stochchar/GainLossRates/GainLossRates.java     |  173 +
 .../InterpretPagelFormat/InterpretPagelFormat.java |  237 +
 .../InterpretPagelFormatM.java                     |  261 +
 .../LikelihoodInCharacter.java                     |  225 +
 .../ManageCharModelsBlock.java                     |  155 +
 .../ManageProbModelSets/ManageProbModelSets.java   |  127 +
 .../MargProbAncStates/MargProbAncStates.java       |  248 +
 Source/mesquite/stochchar/Mk1Rate/Mk1Rate.java     |  127 +
 .../stochchar/MkModelCurator/MkModelCurator.java   |  165 +
 .../ProbModelSetList/ProbModelSetList.java         |   96 +
 .../SimAncestralStates/SimAncestralStates.java     |  230 +
 .../stochchar/SimCharsOnTrees/SimCharsOnTrees.java |  317 +
 .../SimMatricesOnTrees/SimMatricesOnTrees.java     |  374 ++
 .../SimulatedCharacters/SimulatedCharacters.java   |  264 +
 .../stochchar/SimulatedMatrix/SimulatedMatrix.java |  392 ++
 .../stochchar/StochCharMapper/StochCharMapper.java |  549 ++
 .../stochchar/StoredProbModel/StoredProbModel.java |  214 +
 .../StoredProbModelSim/StoredProbModelSim.java     |  239 +
 .../stochchar/aStochCharIntro/aStochCharIntro.java |   63 +
 Source/mesquite/stochchar/explanation.txt          |    2 +
 Source/mesquite/stochchar/lib/AsymmModel.java      |  883 +++
 .../stochchar/lib/BrownianMotionModel.java         |  120 +
 .../stochchar/lib/CategProbModelCurator.java       |   40 +
 .../stochchar/lib/CharacterLikelihood.java         |   34 +
 .../stochchar/lib/JointLikeAncStForModel.java      |   47 +
 .../stochchar/lib/MargLikeAncStCLForModel.java     |   43 +
 .../stochchar/lib/MargLikeAncStForModel.java       |   40 +
 .../stochchar/lib/MargLikelihoodForModel.java      |   46 +
 Source/mesquite/stochchar/lib/MkModel.java         |  316 +
 Source/mesquite/stochchar/lib/PagNodeRecord.java   |   40 +
 Source/mesquite/stochchar/lib/PagelFormatI.java    |  288 +
 Source/mesquite/stochchar/lib/ProbModelSource.java |   40 +
 .../stochchar/lib/ProbModelSourceLike.java         |   38 +
 .../mesquite/stochchar/lib/ProbModelSourceSim.java |   38 +
 .../stochchar/lib/ProbPhenCategCharModel.java      |   61 +
 .../stochchar/lib/ProbabilityCategCharModel.java   |  218 +
 .../stochchar/lib/ProbabilityContCharModel.java    |   55 +
 .../mesquite/stochchar/lib/SimModelCompatInfo.java |   36 +
 .../stochchar/lib/TreeDataModelBundle.java         |   59 +
 .../stochchar/zMargLikeCateg/zMargLikeCateg.java   |  894 +++
 .../CatalogueOfLifeURLServer.java                  |   36 +
 .../GenBankTaxonURLServer.java                     |   35 +
 Source/mesquite/tol/GetToLTree/GetToLTree.java     |  104 +
 Source/mesquite/tol/SearchToLTaxon/32ToL.gif       |  Bin 0 -> 932 bytes
 Source/mesquite/tol/SearchToLTaxon/64ToL.gif       |  Bin 0 -> 987 bytes
 .../tol/SearchToLTaxon/SearchToLTaxon.java         |   76 +
 Source/mesquite/tol/SearchToLTaxon/ToL.gif         |  Bin 0 -> 899 bytes
 Source/mesquite/tol/TaxonOnWebDB/32TaxonOnWeb.gif  |  Bin 0 -> 184 bytes
 Source/mesquite/tol/TaxonOnWebDB/64TaxonOnWeb.gif  |  Bin 0 -> 237 bytes
 Source/mesquite/tol/TaxonOnWebDB/TaxonOnWeb.gif    |  Bin 0 -> 159 bytes
 Source/mesquite/tol/TaxonOnWebDB/TaxonOnWebDB.java |  195 +
 Source/mesquite/tol/ToLURLServer/ToLURLServer.java |   35 +
 .../tol/TreeBaseURLServer/TreeBaseURLServer.java   |   37 +
 Source/mesquite/tol/aTolIntro/aTolIntro.java       |   63 +
 .../tol/iSpeciesURLServer/iSpeciesURLServer.java   |   36 +
 Source/mesquite/tol/lib/BaseHttpRequestMaker.java  |  422 ++
 Source/mesquite/tol/lib/BaseSearchToLTaxon.java    |   64 +
 .../tol/lib/BaseSearchToLToolTaxonExtra.java       |  129 +
 .../mesquite/tol/lib/MesquiteXMLToLUtilities.java  |   50 +
 Source/mesquite/tol/lib/TaxonOnWebServer.java      |   49 +
 Source/mesquite/tol/lib/ToLProjectOpener.java      |  189 +
 Source/mesquite/tol/lib/ToLRequestParameters.java  |   91 +
 Source/mesquite/tol/lib/ToLUtil.java               |  207 +
 Source/mesquite/tol/lib/XMLConstants.java          |  399 ++
 .../mesquite/tol/uBioURLServer/uBioURLServer.java  |   36 +
 .../AddSelectedTaxaToTree.java                     |   71 +
 .../treefarm/AllRerootings/AllRerootings.java      |   83 +
 Source/mesquite/treefarm/AllTrees/AllTrees.java    |  209 +
 .../AugmentTreeRandomly/AugmentTreeRandomly.java   |  256 +
 .../AverageNodeAssociatedDifference.java           |  317 +
 .../AvgTaxonValueAmgTrees.java                     |  165 +
 .../BLfromDivergenceTimes.java                     |  122 +
 .../BlockDirectlyFromFile.java                     |   60 +
 .../mesquite/treefarm/CladeInTree/CladeInTree.java |   95 +
 .../mesquite/treefarm/CladeMatch/CladeMatch.java   |  165 +
 .../CollessImbalance/CollessImbalance.java         |   85 +
 .../CompareOtherTree/CompareOtherTree.java         |  151 +
 .../CompareOtherTrees/CompareOtherTrees.java       |  148 +
 .../Concat2TreeSources/Concat2TreeSources.java     |  332 ++
 .../ConcatMultTreeSources.java                     |  320 +
 .../ConcatTreeBlocks/ConcatTreeBlocks.java         |   99 +
 .../CondensedTreeSource/CondensedTreeSource.java   |  214 +
 .../ConsensusTreesFromBlocks.java                  |  230 +
 .../treefarm/ConvexInTree/ConvexInTree.java        |   94 +
 .../Correlation2Trees/Correlation2Trees.java       |  152 +
 .../mesquite/treefarm/CurrentTree/CurrentTree.java |  121 +
 .../treefarm/CutSelectedTaxa/CutSelectedTaxa.java  |  103 +
 .../DeleteReticulations/DeleteReticulations.java   |   61 +
 .../treefarm/DetermModifTree/DetermModifTree.java  |  131 +
 .../DuplicateTreeBlocks/DuplicateTreeBlocks.java   |   73 +
 Source/mesquite/treefarm/EmailTree/EmailTree.java  |   79 +
 .../EqualRatesSpSampled/EqualRatesSpSampled.java   |  349 ++
 .../ExtractTreeBlock/ExtractTreeBlock.java         |   95 +
 .../treefarm/FAFillTreeBlock/FAFillTreeBlock.java  |  130 +
 .../FilterTreesOtherSrc/FilterTreesOtherSrc.java   |  180 +
 .../FractionCladesShared2Trees.java                |  155 +
 Source/mesquite/treefarm/GraftTree/GraftTree.java  |  133 +
 .../mesquite/treefarm/MRPMatrices/MRPMatrices.java |  259 +
 .../treefarm/MakeRerootings/32allRerootings.gif    |  Bin 0 -> 129 bytes
 .../treefarm/MakeRerootings/64allRerootings.gif    |  Bin 0 -> 174 bytes
 .../treefarm/MakeRerootings/MakeRerootings.java    |  100 +
 .../treefarm/MakeRerootings/allRerootings.gif      |  Bin 0 -> 101 bytes
 .../ModTreesOtherSource/ModTreesOtherSource.java   |  253 +
 .../treefarm/NNAssocValues/NNAssocValues.java      |   97 +
 Source/mesquite/treefarm/NodeDepth/NodeDepth.java  |   77 +
 .../NoiseToBranchLengths/NoiseToBranchLengths.java |  122 +
 .../NumTopologyCongruent/NumTopologyCongruent.java |  141 +
 .../NumTreesMatchingCriterion.java                 |   99 +
 .../treefarm/OutgroupRoot/OutgroupRoot.java        |  130 +
 .../ProbRndTreeModifier/ProbRndTreeModifier.java   |  131 +
 .../RandomBranchMoves/RandomBranchMoves.java       |  124 +
 .../treefarm/RandomModifTree/RandomModifTree.java  |  178 +
 .../treefarm/RandomResolve/RandomResolve.java      |  113 +
 .../RandomlyModifiedTrees.java                     |  202 +
 .../mesquite/treefarm/RarefyTree/RarefyTree.java   |  138 +
 .../treefarm/RearrangedTree/RearrangedTree.java    |  105 +
 .../ReinterpretBranchLabels.java                   |  138 +
 .../RemoveAllBranchLabels.java                     |   66 +
 .../treefarm/ReshuffleTaxa/ReshuffleTaxa.java      |   74 +
 .../SharedClades2Trees/SharedClades2Trees.java     |  101 +
 .../SharedPartitions2Trees.java                    |  246 +
 .../treefarm/SortTaxaByTree/SortTaxaByTree.java    |   86 +
 .../SplitFrequencies/SplitFrequencies.java         |  270 +
 .../TaxonValueFromTree/TaxonValueFromTree.java     |  222 +
 .../TerminalInstability/TerminalInstability.java   |  241 +
 .../TopologyCongruent/TopologyCongruent.java       |  147 +
 .../TreeSatisfiesValue/TreeSatisfiesValue.java     |  213 +
 .../TreeTotalPathLength/TreeTotalPathLength.java   |   90 +
 .../treefarm/aTreeFarmIntro/aTreeFarmIntro.java    |  112 +
 Source/mesquite/treefarm/aTreeFarmIntro/splash.gif |  Bin 0 -> 4848 bytes
 Source/mesquite/treefarm/aTreeFarmIntro/splash.psd |  Bin 0 -> 43978 bytes
 Source/mesquite/treefarm/explanation.txt           |    2 +
 .../mesquite/treefarm/lib/BlockFromTreeSource.java |  155 +
 Source/mesquite/treefarm/lib/DetTreeModifier.java  |   34 +
 Source/mesquite/treefarm/lib/LiveTreeBlocks.java   |  263 +
 .../mesquite/treefarm/lib/NForTaxonWithTree.java   |   39 +
 .../mesquite/treefarm/lib/NForTaxonWithTrees.java  |  237 +
 .../mesquite/treefarm/lib/PatristicDistances.java  |   93 +
 Source/mesquite/treefarm/lib/RndTreeModifier.java  |   33 +
 .../treefarm/lib/SourceFromTreeSource.java         |   80 +
 .../mesquite/treefarm/lib/SourceModifiedTree.java  |   90 +
 .../trees/AddTaxaToTree/AddTaxaToTree.java         |   79 +
 .../AllBranchLengthsOne/AllBranchLengthsOne.java   |   61 +
 .../AllUnassignBrLengths1.java                     |   60 +
 .../mesquite/trees/AlterLengths/AlterLengths.java  |  106 +
 Source/mesquite/trees/AlterTrees/AlterTrees.java   |  104 +
 Source/mesquite/trees/ArcTree/ArcTree.java         |  552 ++
 .../trees/AverageTreeValue/AverageTreeValue.java   |  126 +
 .../BLFromNodeAgeConstraints.java                  |  138 +
 .../mesquite/trees/BallsNSticks/BallsNSticks.java  |  789 +++
 .../BasicDrawTaxonNames/BasicDrawTaxonNames.java   |  996 ++++
 .../BasicTreeDrawCoordinator.java                  | 1080 ++++
 .../BasicTreeWindowCoord/BasicTreeWindowCoord.java |  233 +
 .../trees/BasicTreeWindowMaker/32collapse.gif      |  Bin 0 -> 118 bytes
 .../BasicTreeWindowMaker/32collapseAllBelow.gif    |  Bin 0 -> 118 bytes
 .../trees/BasicTreeWindowMaker/32collapseall.gif   |  Bin 0 -> 119 bytes
 .../trees/BasicTreeWindowMaker/32interchange.gif   |  Bin 0 -> 122 bytes
 .../trees/BasicTreeWindowMaker/32ladderize.gif     |  Bin 0 -> 119 bytes
 .../trees/BasicTreeWindowMaker/32magnify.gif       |  Bin 0 -> 115 bytes
 .../trees/BasicTreeWindowMaker/32reroot.gif        |  Bin 0 -> 108 bytes
 .../BasicTreeWindowMaker/32reverseLadderize.gif    |  Bin 0 -> 122 bytes
 .../trees/BasicTreeWindowMaker/32scissors.gif      |  Bin 0 -> 116 bytes
 .../trees/BasicTreeWindowMaker/32triangle.gif      |  Bin 0 -> 101 bytes
 .../mesquite/trees/BasicTreeWindowMaker/32zoom.gif |  Bin 0 -> 909 bytes
 .../trees/BasicTreeWindowMaker/32zoomOut.gif       |  Bin 0 -> 910 bytes
 .../trees/BasicTreeWindowMaker/64collapse.gif      |  Bin 0 -> 160 bytes
 .../BasicTreeWindowMaker/64collapseAllBelow.gif    |  Bin 0 -> 165 bytes
 .../trees/BasicTreeWindowMaker/64collapseall.gif   |  Bin 0 -> 162 bytes
 .../trees/BasicTreeWindowMaker/64interchange.gif   |  Bin 0 -> 164 bytes
 .../trees/BasicTreeWindowMaker/64ladderize.gif     |  Bin 0 -> 163 bytes
 .../trees/BasicTreeWindowMaker/64magnify.gif       |  Bin 0 -> 159 bytes
 .../trees/BasicTreeWindowMaker/64reroot.gif        |  Bin 0 -> 150 bytes
 .../BasicTreeWindowMaker/64reverseLadderize.gif    |  Bin 0 -> 166 bytes
 .../trees/BasicTreeWindowMaker/64scissors.gif      |  Bin 0 -> 159 bytes
 .../trees/BasicTreeWindowMaker/64triangle.gif      |  Bin 0 -> 141 bytes
 .../mesquite/trees/BasicTreeWindowMaker/64zoom.gif |  Bin 0 -> 965 bytes
 .../trees/BasicTreeWindowMaker/64zoomOut.gif       |  Bin 0 -> 964 bytes
 .../BasicTreeWindowMaker/BasicTreeWindowMaker.java | 5847 +++++++++++++++++++
 .../trees/BasicTreeWindowMaker/collapse.gif        |  Bin 0 -> 92 bytes
 .../BasicTreeWindowMaker/collapseAllBelow.gif      |  Bin 0 -> 90 bytes
 .../trees/BasicTreeWindowMaker/collapseall.gif     |  Bin 0 -> 95 bytes
 .../trees/BasicTreeWindowMaker/interchange.gif     |  Bin 0 -> 96 bytes
 .../trees/BasicTreeWindowMaker/ladderize.gif       |  Bin 0 -> 93 bytes
 .../trees/BasicTreeWindowMaker/magnify.gif         |  Bin 0 -> 90 bytes
 .../trees/BasicTreeWindowMaker/recent/recent0.gif  |  Bin 0 -> 902 bytes
 .../trees/BasicTreeWindowMaker/recent/recent1.gif  |  Bin 0 -> 911 bytes
 .../trees/BasicTreeWindowMaker/recent/recent10.gif |  Bin 0 -> 931 bytes
 .../trees/BasicTreeWindowMaker/recent/recent2.gif  |  Bin 0 -> 917 bytes
 .../trees/BasicTreeWindowMaker/recent/recent3.gif  |  Bin 0 -> 922 bytes
 .../trees/BasicTreeWindowMaker/recent/recent4.gif  |  Bin 0 -> 924 bytes
 .../trees/BasicTreeWindowMaker/recent/recent5.gif  |  Bin 0 -> 926 bytes
 .../trees/BasicTreeWindowMaker/recent/recent6.gif  |  Bin 0 -> 929 bytes
 .../trees/BasicTreeWindowMaker/recent/recent7.gif  |  Bin 0 -> 927 bytes
 .../trees/BasicTreeWindowMaker/recent/recent8.gif  |  Bin 0 -> 928 bytes
 .../trees/BasicTreeWindowMaker/recent/recent9.gif  |  Bin 0 -> 931 bytes
 .../mesquite/trees/BasicTreeWindowMaker/reroot.gif |  Bin 0 -> 85 bytes
 .../BasicTreeWindowMaker/reverseLadderize.gif      |  Bin 0 -> 95 bytes
 .../trees/BasicTreeWindowMaker/scissors.gif        |  Bin 0 -> 91 bytes
 .../trees/BasicTreeWindowMaker/triangle.gif        |  Bin 0 -> 79 bytes
 .../mesquite/trees/BasicTreeWindowMaker/zoom.gif   |  Bin 0 -> 94 bytes
 .../trees/BasicTreeWindowMaker/zoomOut.gif         |  Bin 0 -> 878 bytes
 .../trees/BooleanTreeValue/BooleanTreeValue.java   |  131 +
 Source/mesquite/trees/BranchInfo/32branchInfo.gif  |  Bin 0 -> 123 bytes
 Source/mesquite/trees/BranchInfo/64branchInfo.gif  |  Bin 0 -> 165 bytes
 Source/mesquite/trees/BranchInfo/BranchInfo.java   |  281 +
 Source/mesquite/trees/BranchInfo/branchInfo.gif    |  Bin 0 -> 97 bytes
 .../BranchLengthFromRoot/BranchLengthFromRoot.java |   76 +
 .../trees/BranchLengthsAdjust/32adjustLengths.gif  |  Bin 0 -> 125 bytes
 .../trees/BranchLengthsAdjust/32dragLengths.gif    |  Bin 0 -> 126 bytes
 .../trees/BranchLengthsAdjust/64adjustLengths.gif  |  Bin 0 -> 168 bytes
 .../trees/BranchLengthsAdjust/64dragLengths.gif    |  Bin 0 -> 172 bytes
 .../BranchLengthsAdjust/BranchLengthsAdjust.java   |  480 ++
 .../trees/BranchLengthsAdjust/adjustLengths.gif    |  Bin 0 -> 100 bytes
 .../trees/BranchLengthsAdjust/dragLengths.gif      |  Bin 0 -> 103 bytes
 .../trees/ClearBranchNames/ClearBranchNames.java   |   68 +
 .../CollapseZeroToPolys/CollapseZeroToPolys.java   |   63 +
 Source/mesquite/trees/ColorBranches/32color.gif    |  Bin 0 -> 137 bytes
 Source/mesquite/trees/ColorBranches/64color.gif    |  Bin 0 -> 179 bytes
 .../trees/ColorBranches/ColorBranches.java         |  300 +
 Source/mesquite/trees/ColorBranches/color.gif      |  Bin 0 -> 115 bytes
 .../trees/ConstrainNodeAge/32anchorTool.gif        |  Bin 0 -> 124 bytes
 .../trees/ConstrainNodeAge/64anchorTool.gif        |  Bin 0 -> 168 bytes
 .../trees/ConstrainNodeAge/ConstrainNodeAge.java   |  299 +
 Source/mesquite/trees/ConstrainNodeAge/anchor.gif  |  Bin 0 -> 94 bytes
 .../mesquite/trees/ConstrainNodeAge/anchorTool.gif |  Bin 0 -> 97 bytes
 .../mesquite/trees/ConstrainNodeAge/anchorWide.gif |  Bin 0 -> 111 bytes
 .../DeassignBranchLengths.java                     |   57 +
 .../mesquite/trees/DefaultTrees/DefaultTrees.java  |  153 +
 .../DefiniteTreeSource/DefiniteTreeSource.java     |  259 +
 .../DependentTreeWindow/DependentTreeWindow.java   |  567 ++
 .../trees/DiagonalDrawTree/DiagonalDrawTree.java   | 1222 ++++
 .../DifferenceInNumsForTree.java                   |  167 +
 .../EqualRatesMarkovSp/EqualRatesMarkovSp.java     |  154 +
 .../trees/EquiprobableTrees/EquiprobableTrees.java |   84 +
 .../LabelBranchLengths/LabelBranchLengths.java     |  265 +
 .../trees/ListedTreeBlocks/ListedTreeBlocks.java   |  214 +
 Source/mesquite/trees/ManageTrees/ManageTrees.java | 1989 +++++++
 .../trees/ManyTreesFromFile/ManyTreesFromFile.java |   49 +
 .../MirrorTreeWindowMaker.java                     |  557 ++
 .../MultiTreeWindowMaker/MultiTreeWindowMaker.java |  630 ++
 .../trees/NegativeToZeroBL/NegativeToZeroBL.java   |   64 +
 .../mesquite/trees/NodeLocsStandard/32expand.gif   |  Bin 0 -> 101 bytes
 .../mesquite/trees/NodeLocsStandard/64expand.gif   |  Bin 0 -> 142 bytes
 .../trees/NodeLocsStandard/NodeLocsStandard.java   | 1586 +++++
 Source/mesquite/trees/NodeLocsStandard/expand.gif  |  Bin 0 -> 79 bytes
 Source/mesquite/trees/NodeNamer/32nodeNamer.gif    |  Bin 0 -> 153 bytes
 Source/mesquite/trees/NodeNamer/64nodeNamer.gif    |  Bin 0 -> 199 bytes
 Source/mesquite/trees/NodeNamer/NodeNamer.java     |  248 +
 Source/mesquite/trees/NodeNamer/nodeNamer.gif      |  Bin 0 -> 896 bytes
 .../trees/NumAttachedToTree/NumAttachedToTree.java |  167 +
 .../NumFor2CharCurrentTree.java                    |  180 +
 .../NumForCharCurrentTree.java                     |  192 +
 .../trees/NumForCharOnTree/NumForCharOnTree.java   |  226 +
 .../NumForCharRespTree/NumForCharRespTree.java     |  174 +
 .../NumForMatCurrentTree/NumForMatCurrentTree.java |  187 +
 .../NumForNodesWithChar/NumForNodesWithChar.java   |  198 +
 .../NumForNodesWithCharHist.java                   |  123 +
 .../NumForNodesWithMat/NumForNodesWithMat.java     |  161 +
 .../NumForTreeCladeValue/NumForTreeCladeValue.java |  198 +
 .../NumForTreeSelNodeValue.java                    |  217 +
 .../NumForTreeWith2Chars/NumForTreeWith2Chars.java |  298 +
 .../NumForTreeWithChar/NumForTreeWithChar.java     |  297 +
 .../mesquite/trees/NumberOfTaxa/NumberOfTaxa.java  |   68 +
 .../NumsForNodesBrLengths.java                     |  103 +
 .../ObedientTreeWindow/ObedientTreeWindow.java     |   93 +
 .../trees/OtherTreeBlocks/OtherTreeBlocks.java     |  176 +
 .../ResolvePolytomiesToZero.java                   |   75 +
 .../SampleManyTreesFromFile.java                   |  137 +
 .../ScaleBranchLengths/ScaleBranchLengths.java     |   74 +
 .../ScaleSelBranchLengths.java                     |   71 +
 .../SearchForBetterTree/SearchForBetterTree.java   |  143 +
 .../trees/SearchTreeToolAssistant/32searchTree.gif |  Bin 0 -> 126 bytes
 .../trees/SearchTreeToolAssistant/64searchTree.gif |  Bin 0 -> 172 bytes
 .../SearchTreeToolAssistant.java                   |  243 +
 .../trees/SearchTreeToolAssistant/searchTree.gif   |  Bin 0 -> 111 bytes
 Source/mesquite/trees/SelectBranches/32select.gif  |  Bin 0 -> 123 bytes
 .../trees/SelectBranches/32selectClade.gif         |  Bin 0 -> 111 bytes
 Source/mesquite/trees/SelectBranches/64select.gif  |  Bin 0 -> 167 bytes
 .../trees/SelectBranches/64selectClade.gif         |  Bin 0 -> 153 bytes
 .../trees/SelectBranches/SelectBranches.java       |  427 ++
 Source/mesquite/trees/SelectBranches/select.gif    |  Bin 0 -> 96 bytes
 .../mesquite/trees/SelectBranches/selectClade.gif  |  Bin 0 -> 88 bytes
 .../trees/SelectTaxaInClade/32selectTaxa.gif       |  Bin 0 -> 909 bytes
 .../SelectTaxaInClade/32selectTaxaInClade.gif      |  Bin 0 -> 122 bytes
 .../trees/SelectTaxaInClade/64selectTaxa.gif       |  Bin 0 -> 963 bytes
 .../SelectTaxaInClade/64selectTaxaInClade.gif      |  Bin 0 -> 166 bytes
 .../trees/SelectTaxaInClade/SelectTaxaInClade.java |  263 +
 .../trees/SelectTaxaInClade/selectTaxa.gif         |  Bin 0 -> 875 bytes
 .../trees/SelectTaxaInClade/selectTaxaInClade.gif  |  Bin 0 -> 98 bytes
 .../SetAssumptionDefault/SetAssumptionDefault.java |   56 +
 .../trees/SetAssumptionHard/SetAssumptionHard.java |   55 +
 .../trees/SetAssumptionSoft/SetAssumptionSoft.java |   56 +
 .../trees/SetBranchLengths/SetBranchLengths.java   |   73 +
 .../SetBranchLengthsFromNames.java                 |   79 +
 .../SetBranchLengthsIfLessThan.java                |   73 +
 .../SetSelBranchLengths/SetSelBranchLengths.java   |   72 +
 .../SetToArbitrarySymmetrical.java                 |   82 +
 .../trees/SetToLadderized/SetToLadderized.java     |   61 +
 Source/mesquite/trees/SetToRooted/SetToRooted.java |   54 +
 .../trees/SetToUnrooted/SetToUnrooted.java         |   55 +
 .../trees/SetTreeDefaults/SetTreeDefaults.java     |  154 +
 .../ShadeNumbersOnTree/ShadeNumbersOnTree.java     |  299 +
 .../mesquite/trees/ShowTreeInList/32showTree.gif   |  Bin 0 -> 920 bytes
 .../mesquite/trees/ShowTreeInList/64showTree.gif   |  Bin 0 -> 974 bytes
 .../trees/ShowTreeInList/ShowTreeInList.java       |  114 +
 Source/mesquite/trees/ShowTreeInList/showTree.gif  |  Bin 0 -> 113 bytes
 .../mesquite/trees/SimulateTree/SimulateTree.java  |  286 +
 .../SimulatedTreeBlocks/SimulatedTreeBlocks.java   |  247 +
 .../trees/SquareLineTree/SquareLineTree.java       |  671 +++
 Source/mesquite/trees/SquareTree/SquareTree.java   | 1402 +++++
 .../trees/StoredTreeBlocks/StoredTreeBlocks.java   |  166 +
 Source/mesquite/trees/StoredTrees/StoredTrees.java |  751 +++
 .../trees/TreeInfoValues/TreeInfoValues.java       |  388 ++
 .../trees/TreeLegendMaker/TreeLegendMaker.java     |  737 +++
 .../trees/TreeNotesMaker/TreeNotesMaker.java       |  419 ++
 .../trees/TreeOfContext/TreeOfContext.java         |  354 ++
 .../TreeValueUsingMatrix/TreeValueUsingMatrix.java |  135 +
 .../trees/Ultrametricize/Ultrametricize.java       |   94 +
 .../UtilityCoordinator/UtilityCoordinator.java     |   69 +
 .../trees/ValuesAtNodes/ValuesAtNodes.java         |  486 ++
 Source/mesquite/trees/aTreesIntro/aTreesIntro.java |   67 +
 Source/mesquite/trees/explanation.txt              |    2 +
 Source/mesquite/trees/lib/DrawTreeUtil.java        |  883 +++
 .../mesquite/trees/lib/ManyTreesFromFileLib.java   | 1064 ++++
 Source/mesquite/trees/lib/SimpleTreeWindow.java    |  477 ++
 .../mesquite/trees/lib/SimpleTreeWindowMaker.java  |  215 +
 Source/mesquite/trees/lib/TaxonPolygon.java        |   41 +
 Source/mesquite/trees/lib/TreeInfoExtraPanel.java  |   54 +
 Source/mesquite/trees/lib/TreeOptimizer.java       |  467 ++
 Source/mesquite/trunk/AboutPanel.java              |   61 +
 Source/mesquite/trunk/AboutWindow.java             |  273 +
 Source/mesquite/trunk/ClassPathHacker.java         |   41 +
 Source/mesquite/trunk/ClockWatcherThread.java      |  151 +
 Source/mesquite/trunk/ConfigFileRecord.java        |   36 +
 Source/mesquite/trunk/DirectInit.java              |   73 +
 Source/mesquite/trunk/EAWTHandler.java             |  132 +
 Source/mesquite/trunk/FileOpener.java              |   24 +
 Source/mesquite/trunk/ModuleLoader.java            |  687 +++
 Source/mesquite/trunk/PhoneHomeThread.java         |  118 +
 Source/mesquite/trunk/ProjectTreeWindow.java       |  116 +
 Source/mesquite/trunk/WelcomeDialog.java           |   68 +
 Source/org/apache/hivemind/util/ClassAdaptor.java  |  215 +
 .../org/apache/hivemind/util/PropertyAdaptor.java  |  184 +
 Source/org/apache/hivemind/util/PropertyUtils.java |  206 +
 distributionBuildFiles/Windows XP.properties       |    1 +
 distributionBuildFiles/build.properties            |    2 +
 distributionBuildFiles/build.xml                   |  291 +
 distributionBuildFiles/buildInstructions.html      |  188 +
 .../serverinfo.properties.sample                   |    5 +
 3252 files changed, 640824 insertions(+)

diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..8494d01
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry exported="true" kind="lib" path="jars/AppleJavaExtensions.jar"/>
+	<classpathentry exported="true" kind="lib" path="jars/iText.jar"/>
+	<classpathentry exported="true" kind="lib" path="jars/Jama-1.0.1.zip"/>
+	<classpathentry exported="true" kind="lib" path="jars/JSci.zip"/>
+	<classpathentry exported="true" kind="lib" path="jars/MRJToolkitStubs.zip"/>
+	<classpathentry exported="true" kind="lib" path="jars/pal.zip"/>
+	<classpathentry exported="true" kind="lib" path="jars/commons-httpclient-3.1.jar"/>
+	<classpathentry exported="true" kind="lib" path="jars/dom4j-1.6.1.jar"/>
+	<classpathentry exported="true" kind="lib" path="jars/commons-lang-2.3.jar"/>
+	<classpathentry excluding="docs/mesquite/BeanTree/" kind="src" path="Resources"/>
+	<classpathentry kind="src" path="Source"/>
+	<classpathentry kind="lib" path="jars/commons-codec-1.6.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="Mesquite_Folder"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9c5e51e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+Mesquite_Folder/
+# Compiled source #
+###################
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+
+# OS generated files #
+######################
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
diff --git a/.project b/.project
new file mode 100644
index 0000000..ff3370d
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>MesquiteCore</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/Additional Files/classpaths.xml b/Additional Files/classpaths.xml
new file mode 100644
index 0000000..88da20c
--- /dev/null
+++ b/Additional Files/classpaths.xml	
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<mesquite>
+	<classpath>../../Cartographer/Mesquite_Folder</classpath>
+</mesquite>
\ No newline at end of file
diff --git a/Additional Files/jarFileMaking.txt b/Additional Files/jarFileMaking.txt
new file mode 100644
index 0000000..8d7ccf8
--- /dev/null
+++ b/Additional Files/jarFileMaking.txt	
@@ -0,0 +1,3 @@
+jar cvfm mesquite.jar manifest.txt mesquite org com
+
+jar cvfm mesquite.jar manifest.txt start
diff --git a/Additional Files/menuSquares.txt b/Additional Files/menuSquares.txt
new file mode 100644
index 0000000..4ec0ff6
--- /dev/null
+++ b/Additional Files/menuSquares.txt	
@@ -0,0 +1,2 @@
+◼ ◻  ❑  ⬒  ▣
+◀ ▶ ◢ ◣ ◥ ◤ ◇ ◆ ◈  ◊ 
\ No newline at end of file
diff --git a/Additional Files/preparingMesquite.html b/Additional Files/preparingMesquite.html
new file mode 100644
index 0000000..e9ae3cc
--- /dev/null
+++ b/Additional Files/preparingMesquite.html	
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Preparing a Copy of Mesquite</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body>
+<p>Taking a development copy of Mesquite and preparing a copy that can
+  be moved onto another machine</p>
+<p>(Note: step 1 is optional, but recommended.)</p>
+<ol>
+	<li>Open up Eclipse and update all of the projects (to update projects, select
+    them in the Package Explorer, right click (or control-click) and, in the popup menu, select Team>Update).</li>
+  <li>Quit Eclipse, and find the Eclipse workspace on your hard disk. In the workspace, you should find several folders.  One is called Mesquite Project; this is the core of Mesquite.  The other 
+  folders are for other Mesquite packages.  </li>
+  <li>In Mesquite Project, you will find a "Mesquite_Folder".
+      Copy that entire folder to another location on your hard disk.  This is the Mesquite_Folder that will be able to be moved to another machine.  That copy will henceforth be referred to as 
+  the Mesquite_Folder Copy</li>
+  <li>Also in the workspace are the folders for project for other packages.
+      For example, one is Chromaseq. To add Chromaseq to Mesquite_Folder Copy, open the Chromaseq folder. Inside that you will find a "Mesquite_Folder";
+      open that, then "mesquite". In there you will find a folder called "chromaseq".
+  Copy that folder into the "mesquite" folder within Mesquite_Folder Copy.</li>
+  <li>Repeat #3 for any of the other projects you wish to incorporate.</li>
+  <li>Go into the copy of the Mesquite_Folder Copy you made in step 2, and
+  delete any files whose names start with "classpath". </li>
+	<li>Open up Mesquite_Folder Copy and start up the copy of Mesquite in there.
+	  If it starts up without errors, you should be fine. If, however, there
+	  are errors, then it might be because the "jars" folder is not fully
+	  set up (this is a problem we haven't managed to get a regular fix for),
+	  or the Mac executibles have been damaged. You should then try the
+	  following:
+	  <ul>
+	    <li>go into Mesquite Project/Additional Files and copy from there the jars.zip
+	      file into Mesquite Project/Mesquite_Folder</li>
+        <li>delete the jars folder present in Mesquite Project/Mesquite_Folder</li>
+	    <li>unzip the jars.zip folder in Mesquite Project/Mesquite_Folder</li>
+        <li>On MacOS X, for reasons that we don't understand
+            yet, Eclipse seems to damage the executable files that are needed
+            to launch Mesquite in the standard way. If on a Mac you find Mesquite
+            does not launch appropriately, then open unzip the file executables.zip
+            that is contained in the Additional Files folder, and move its contents
+        into Mesquite_Folder, replacing the existing files of the same name.</li>
+        <li>Start up Mesquite again to see if the problems are now fixed; if
+          there are still problems, please contact David Maddison.</li>
+      </ul>
+  </li>
+    <li>If all is well, then zip the Mesquite_Folder copy and you can now move
+      it onto another machine.</li>
+</ol>
+<p> </p>
+</body>
+</html>
+
diff --git a/Additional Files/receipts.xml b/Additional Files/receipts.xml
new file mode 100644
index 0000000..fa0374e
--- /dev/null
+++ b/Additional Files/receipts.xml	
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mesquite>
+		<version>1</version>
+		<installationReceipt>
+			<identity>silk</identity>
+			<packageName>SILK version 1.1</packageName>
+			<explanation>SILK provides functions to display images integrated into a character matrix editor</explanation>
+			<uniqueLocation>mesquite/silk</uniqueLocation>
+			<version>110</version>
+		</installationReceipt>
+		<installationReceipt>
+			<identity>pdap</identity>
+			<packageName>PDAP version 1.1</packageName>
+			<explanation>PDAP provides functions for comparative analyses with continuous data</explanation>
+			<uniqueLocation>mesquite/pdap</uniqueLocation>
+			<version>110</version>
+		</installationReceipt>
+</mesquite>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6600f1c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/LibrarySource/JSci/GlobalSettings.java b/LibrarySource/JSci/GlobalSettings.java
new file mode 100644
index 0000000..1a58682
--- /dev/null
+++ b/LibrarySource/JSci/GlobalSettings.java
@@ -0,0 +1,16 @@
+package JSci;
+
+/**
+* The GlobalSettings class controls numeric behaviour.
+* @version 1.0
+* @author Mark Hale
+*/
+public final class GlobalSettings extends Object {
+        /**
+        * Zero tolerance.
+        */
+        public static double ZERO_TOL=0.0;
+        private GlobalSettings() {}
+}
+
+
diff --git a/LibrarySource/JSci/Version.java b/LibrarySource/JSci/Version.java
new file mode 100644
index 0000000..8f98868
--- /dev/null
+++ b/LibrarySource/JSci/Version.java
@@ -0,0 +1,87 @@
+package JSci;
+
+import java.io.*;
+import java.net.*;
+import java.util.ResourceBundle;
+
+/**
+* The Version class contains information about the current and latest release.
+* @version 1.3
+* @author Mark Hale
+*/
+public final class Version extends Object implements Serializable {
+        /**
+        * Major version number.
+        */
+        public final int major;
+        /**
+        * Minor version number.
+        */
+        public final int minor;
+        /**
+        * Java platform required.
+        */
+        public final String platform;
+        /**
+        * The URL for the home of this version.
+        */
+        public final String home;
+        /**
+        * Gets the current version.
+        */
+        public static Version getCurrent() {
+                ResourceBundle bundle = ResourceBundle.getBundle("JSci.Bundle");
+                int major = Integer.parseInt(bundle.getString("version.major"));
+                int minor = Integer.parseInt(bundle.getString("version.minor"));
+                String platform = bundle.getString("version.platform");
+                String home = bundle.getString("version.home");
+                return new Version(major, minor, home, platform);
+        }
+        /**
+        * Retrieves the latest version from the home URL.
+        */
+        public static Version getLatest() throws IOException {
+                Version latest = null;
+                try {
+                        URL serurl = new URL(getCurrent().home+"version118.ser");
+                        ObjectInputStream in = new ObjectInputStream(serurl.openStream());
+                        latest = (Version) in.readObject();
+                        in.close();
+                } catch(MalformedURLException murle) {
+                } catch(ClassNotFoundException cnfe) {}
+                return latest;
+        }
+        /**
+        * Constructs a version object.
+        */
+        private Version(int major, int minor, String home, String platform) {
+                this.major = major;
+                this.minor = minor;
+                this.home = home;
+                this.platform = platform;
+        }
+        /**
+        * Compares two versions for equality.
+        */
+        public boolean equals(Object o) {
+                if(!(o instanceof Version))
+                        return false;
+                Version ver = (Version) o;
+                return (major == ver.major) && (minor == ver.minor) && platform.equals(ver.platform);
+        }
+        /**
+        * Returns the version number as a string.
+        */
+        public String toString() {
+                return new StringBuffer().append(major).append('.').append(minor).toString();
+        }
+        /**
+        * Returns true if this is later than another version.
+        */
+        public boolean isLater(Version ver) {
+                return (major>ver.major) ||
+                        (major == ver.major && minor>ver.minor);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/AbstractMath.java b/LibrarySource/JSci/maths/AbstractMath.java
new file mode 100644
index 0000000..0e400cc
--- /dev/null
+++ b/LibrarySource/JSci/maths/AbstractMath.java
@@ -0,0 +1,13 @@
+package JSci.maths;
+
+/**
+* The AbstractMath superclass provides an abstract encapsulation of maths.
+* All classes with a postfix of Math should extend this class.
+* @version 1.0
+* @author Mark Hale
+*/
+public abstract class AbstractMath extends Object {
+        protected AbstractMath() {}
+}
+
+
diff --git a/LibrarySource/JSci/maths/ExtraMath.java b/LibrarySource/JSci/maths/ExtraMath.java
new file mode 100644
index 0000000..ab96ba0
--- /dev/null
+++ b/LibrarySource/JSci/maths/ExtraMath.java
@@ -0,0 +1,107 @@
+package JSci.maths;
+
+/**
+* The extra math library.
+* Provides extra functions not in java.lang.Math class.
+* This class cannot be subclassed or instantiated because all methods are static.
+* @version 1.1
+* @author Mark Hale
+*/
+public final class ExtraMath extends AbstractMath {
+        private ExtraMath() {}
+
+        /**
+        * Returns sqrt(x<sup>2</sup>+y<sup>2</sup>).
+        */
+        public static double hypot(final double x,final double y) {
+                final double xAbs=Math.abs(x);
+                final double yAbs=Math.abs(y);
+                if(xAbs==0.0 && yAbs==0.0)
+                        return 0.0;
+                else if(xAbs<yAbs)
+                        return yAbs*Math.sqrt(1.0+(x/y)*(x/y));
+                else
+                        return xAbs*Math.sqrt(1.0+(y/x)*(y/x));
+        }
+        /**
+        * Returns a<sup>b</sup>.
+        */
+        public static int pow(int a,int b) {
+                for(int i=0;i<b;i++)
+                        a*=a;
+                return a;
+        }
+        /**
+        * Returns the factorial.
+        * (Wrapper for the gamma function).
+        * @see SpecialMath#gamma
+        * @param x a double.
+        */
+        public static double factorial(double x) {
+                return SpecialMath.gamma(x+1.0);
+        }
+        /**
+        * Returns the natural logarithm of the factorial.
+        * (Wrapper for the log gamma function).
+        * @see SpecialMath#logGamma
+        * @param x a double.
+        */
+        public static double logFactorial(double x) {
+                return SpecialMath.logGamma(x+1.0);
+        }
+        /**
+        * Returns the binomial coefficient (n k).
+        * @param n a double.
+        * @param k a double.
+        */
+        public static double binomial(double n,double k) {
+                return Math.exp(SpecialMath.logGamma(n+1.0)-SpecialMath.logGamma(k+1.0)-SpecialMath.logGamma(n-k+1.0));
+        }
+        /**
+        * Returns the hyperbolic sine of a double.
+        * @param x a double.
+        */
+        public static double sinh(double x) {
+                return (Math.exp(x)-Math.exp(-x))/2.0;
+        }
+        /**
+        * Returns the hyperbolic cosine of a double.
+        * @param x a double.
+        */
+        public static double cosh(double x) {
+                return (Math.exp(x)+Math.exp(-x))/2.0;
+        }
+        /**
+        * Returns the hyperbolic tangent of a double.
+        * @param x a double.
+        */
+        public static double tanh(double x) {
+                return sinh(x)/cosh(x);
+        }
+        /**
+        * Returns the arc hyperbolic sine of a double,
+        * in the range of -<img border=0 alt="infinity" src="doc-files/infinity.gif"> through <img border=0 alt="infinity" src="doc-files/infinity.gif">.
+        * @param x a double.
+        */
+        public static double asinh(double x) {
+                return Math.log(x+Math.sqrt(x*x+1.0));
+        }
+        /**
+        * Returns the arc hyperbolic cosine of a double,
+        * in the range of 0.0 through <img border=0 alt="infinity" src="doc-files/infinity.gif">.
+        * @param x a double.
+        */
+        public static double acosh(double x) {
+                return Math.log(x+Math.sqrt(x*x-1.0));
+        }
+        /**
+        * Returns the arc hyperbolic tangent of a double,
+        * in the range of -<img border=0 alt="infinity" src="doc-files/infinity.gif"> through <img border=0 alt="infinity" src="doc-files/infinity.gif">.
+        * @param x a double.
+        */
+        public static double atanh(double x) {
+                return Math.log((1.0+x)/(1.0-x))/2.0;
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/NumericalConstants.java b/LibrarySource/JSci/maths/NumericalConstants.java
new file mode 100644
index 0000000..486ffb2
--- /dev/null
+++ b/LibrarySource/JSci/maths/NumericalConstants.java
@@ -0,0 +1,31 @@
+package JSci.maths;
+
+/**
+* A collection of useful numbers (stored to maximum precision).
+* @version 1.0
+* @author Mark Hale
+*/
+public interface NumericalConstants {
+        /**
+        * Square root of 2.
+        */
+        double SQRT2=1.4142135623730950488016887242096980785696718753769;
+        /**
+        * Two times <img border=0 alt="pi" src="doc-files/pi.gif">.
+        */
+        double TWO_PI=6.2831853071795864769252867665590057683943387987502;
+        /**
+        * Square root of 2<img border=0 alt="pi" src="doc-files/pi.gif">.
+        */
+        double SQRT2PI=2.5066282746310005024157652848110452530069867406099;
+        /**
+        * Euler's gamma constant.
+        */
+        double GAMMA=0.57721566490153286060651209008240243104215933593992;
+        /**
+        * Golden ratio.
+        */
+        double GOLDEN_RATIO=1.6180339887498948482045868343656381177203091798058;
+}
+
+
diff --git a/LibrarySource/JSci/maths/SpecialMath.java b/LibrarySource/JSci/maths/SpecialMath.java
new file mode 100644
index 0000000..1131f50
--- /dev/null
+++ b/LibrarySource/JSci/maths/SpecialMath.java
@@ -0,0 +1,1535 @@
+package JSci.maths;
+
+/**
+* The special function math library.
+* This class cannot be subclassed or instantiated because all methods are static.
+* @version 1.0
+* @author Mark Hale
+*/
+public final class SpecialMath extends AbstractMath implements NumericalConstants {
+        private SpecialMath() {}
+
+// Some IEEE machine constants
+        /**
+        * Relative machine precision.
+        */
+        private final static double EPS=2.22e-16;
+        /**
+        * The smallest positive floating-point number such that 1/xminin is machine representable.
+        */
+        private final static double XMININ=2.23e-308;
+
+
+// CHEBYSHEV SERIES
+
+// series for ai0        on the interval  1.25000d-01 to  3.33333d-01
+//                                        with weighted error   7.87e-17
+//                                         log weighted error  16.10
+//                               significant figures required  14.69
+//                                    decimal places required  16.76
+
+        private final static double ai0cs[]={
+                0.07575994494023796,
+                0.00759138081082334,
+                0.00041531313389237,
+                0.00001070076463439,
+                -0.00000790117997921,
+                -0.00000078261435014,
+                0.00000027838499429,
+                0.00000000825247260,
+                -0.00000001204463945,
+                0.00000000155964859,
+                0.00000000022925563,
+                -0.00000000011916228,
+                0.00000000001757854,
+                0.00000000000112822,
+                -0.00000000000114684,
+                0.00000000000027155,
+                -0.00000000000002415,
+                -0.00000000000000608,
+                0.00000000000000314,
+                -0.00000000000000071,
+                0.00000000000000007};
+
+// series for ai02       on the interval  0.          to  1.25000d-01
+//                                        with weighted error   3.79e-17
+//                                         log weighted error  16.42
+//                               significant figures required  14.86
+//                                    decimal places required  17.09
+        private final static double ai02cs[]={
+                0.05449041101410882,
+                0.00336911647825569,
+                0.00006889758346918,
+                0.00000289137052082,
+                0.00000020489185893,
+                0.00000002266668991,
+                0.00000000339623203,
+                0.00000000049406022,
+                0.00000000001188914,
+                -0.00000000003149915,
+                -0.00000000001321580,
+                -0.00000000000179419,
+                0.00000000000071801,
+                0.00000000000038529,
+                0.00000000000001539,
+                -0.00000000000004151,
+                -0.00000000000000954,
+                0.00000000000000382,
+                0.00000000000000176,
+                -0.00000000000000034,
+                -0.00000000000000027,
+                0.00000000000000003};
+
+// series for ai1        on the interval  1.25000d-01 to  3.33333d-01
+//                                        with weighted error   6.98e-17
+//                                         log weighted error  16.16
+//                               significant figures required  14.53
+//                                    decimal places required  16.82
+
+        private final static double ai1cs[]={
+                -0.02846744181881479,
+                -0.01922953231443221,
+                -0.00061151858579437,
+                -0.00002069971253350,
+                0.00000858561914581,
+                0.00000104949824671,
+                -0.00000029183389184,
+                -0.00000001559378146,
+                0.00000001318012367,
+                -0.00000000144842341,
+                -0.00000000029085122,
+                0.00000000012663889,
+                -0.00000000001664947,
+                -0.00000000000166665,
+                0.00000000000124260,
+                -0.00000000000027315,
+                0.00000000000002023,
+                0.00000000000000730,
+                -0.00000000000000333,
+                0.00000000000000071,
+                -0.00000000000000006};
+
+// series for ai12       on the interval  0.          to  1.25000d-01
+//                                        with weighted error   3.55e-17
+//                                         log weighted error  16.45
+//                               significant figures required  14.69
+//                                    decimal places required  17.12
+
+        private final static double ai12cs[]={
+                0.02857623501828014,
+                -0.00976109749136147,
+                -0.00011058893876263,
+                -0.00000388256480887,
+                -0.00000025122362377,
+                -0.00000002631468847,
+                -0.00000000383538039,
+                -0.00000000055897433,
+                -0.00000000001897495,
+                0.00000000003252602,
+                0.00000000001412580,
+                0.00000000000203564,
+                -0.00000000000071985,
+                -0.00000000000040836,
+                -0.00000000000002101,
+                0.00000000000004273,
+                0.00000000000001041,
+                -0.00000000000000382,
+                -0.00000000000000186,
+                0.00000000000000033,
+                0.00000000000000028,
+                -0.00000000000000003};
+
+// series for aif        on the interval -1.00000d+00 to  1.00000d+00
+//                                        with weighted error   1.09e-19
+//                                         log weighted error  18.96
+//                               significant figures required  17.76
+//                                    decimal places required  19.44
+
+        private final static double aifcs[]={
+                -0.03797135849666999750,
+                0.05919188853726363857,
+                0.00098629280577279975,
+                0.00000684884381907656,
+                0.00000002594202596219,
+                0.00000000006176612774,
+                0.00000000000010092454,
+                0.00000000000000012014,
+                0.00000000000000000010};
+
+// series for aig        on the interval -1.00000d+00 to  1.00000d+00
+//                                        with weighted error   1.51e-17
+//                                         log weighted error  16.82
+//                               significant figures required  15.19
+//                                    decimal places required  17.27
+
+        private final static double aigcs[]={
+                0.01815236558116127,
+                0.02157256316601076,
+                0.00025678356987483,
+                0.00000142652141197,
+                0.00000000457211492,
+                0.00000000000952517,
+                0.00000000000001392,
+                0.00000000000000001};
+
+// series for aip        on the interval  0.          to  1.00000d+00
+//                                        with weighted error   5.10e-17
+//                                         log weighted error  16.29
+//                               significant figures required  14.41
+//                                    decimal places required  17.06
+
+        private final static double aipcs[]={
+                -0.0187519297793868,
+                -0.0091443848250055,
+                0.0009010457337825,
+                -0.0001394184127221,
+                0.0000273815815785,
+                -0.0000062750421119,
+                0.0000016064844184,
+                -0.0000004476392158,
+                0.0000001334635874,
+                -0.0000000420735334,
+                0.0000000139021990,
+                -0.0000000047831848,
+                0.0000000017047897,
+                -0.0000000006268389,
+                0.0000000002369824,
+                -0.0000000000918641,
+                0.0000000000364278,
+                -0.0000000000147475,
+                0.0000000000060851,
+                -0.0000000000025552,
+                0.0000000000010906,
+                -0.0000000000004725,
+                0.0000000000002076,
+                -0.0000000000000924,
+                0.0000000000000417,
+                -0.0000000000000190,
+                0.0000000000000087,
+                -0.0000000000000040,
+                0.0000000000000019,
+                -0.0000000000000009,
+                0.0000000000000004,
+                -0.0000000000000002,
+                0.0000000000000001,
+                -0.0000000000000000};
+
+// series for am21       on the interval -1.25000d-01 to  0.
+//                                        with weighted error   2.89e-17
+//                                         log weighted error  16.54
+//                               significant figures required  14.15
+//                                    decimal places required  17.34
+
+        private final static double am21cs[]={
+                0.0065809191761485,
+                0.0023675984685722,
+                0.0001324741670371,
+                0.0000157600904043,
+                0.0000027529702663,
+                0.0000006102679017,
+                0.0000001595088468,
+                0.0000000471033947,
+                0.0000000152933871,
+                0.0000000053590722,
+                0.0000000020000910,
+                0.0000000007872292,
+                0.0000000003243103,
+                0.0000000001390106,
+                0.0000000000617011,
+                0.0000000000282491,
+                0.0000000000132979,
+                0.0000000000064188,
+                0.0000000000031697,
+                0.0000000000015981,
+                0.0000000000008213,
+                0.0000000000004296,
+                0.0000000000002284,
+                0.0000000000001232,
+                0.0000000000000675,
+                0.0000000000000374,
+                0.0000000000000210,
+                0.0000000000000119,
+                0.0000000000000068,
+                0.0000000000000039,
+                0.0000000000000023,
+                0.0000000000000013,
+                0.0000000000000008,
+                0.0000000000000005,
+                0.0000000000000003,
+                0.0000000000000001,
+                0.0000000000000001,
+                0.0000000000000000,
+                0.0000000000000000,
+                0.0000000000000000};
+
+// series for ath1       on the interval -1.25000d-01 to  0.
+//                                        with weighted error   2.53e-17
+//                                         log weighted error  16.60
+//                               significant figures required  15.15
+//                                    decimal places required  17.38
+
+        private final static double ath1cs[]={
+                -0.07125837815669365,
+                -0.00590471979831451,
+                -0.00012114544069499,
+                -0.00000988608542270,
+                -0.00000138084097352,
+                -0.00000026142640172,
+                -0.00000006050432589,
+                -0.00000001618436223,
+                -0.00000000483464911,
+                -0.00000000157655272,
+                -0.00000000055231518,
+                -0.00000000020545441,
+                -0.00000000008043412,
+                -0.00000000003291252,
+                -0.00000000001399875,
+                -0.00000000000616151,
+                -0.00000000000279614,
+                -0.00000000000130428,
+                -0.00000000000062373,
+                -0.00000000000030512,
+                -0.00000000000015239,
+                -0.00000000000007758,
+                -0.00000000000004020,
+                -0.00000000000002117,
+                -0.00000000000001132,
+                -0.00000000000000614,
+                -0.00000000000000337,
+                -0.00000000000000188,
+                -0.00000000000000105,
+                -0.00000000000000060,
+                -0.00000000000000034,
+                -0.00000000000000020,
+                -0.00000000000000011,
+                -0.00000000000000007,
+                -0.00000000000000004,
+                -0.00000000000000002};
+
+// series for am22       on the interval -1.00000d+00 to -1.25000d-01
+//                                        with weighted error   2.99e-17
+//                                         log weighted error  16.52
+//                               significant figures required  14.57
+//                                    decimal places required  17.28
+
+        private final static double am22cs[]={
+                -0.01562844480625341,
+                0.00778336445239681,
+                0.00086705777047718,
+                0.00015696627315611,
+                0.00003563962571432,
+                0.00000924598335425,
+                0.00000262110161850,
+                0.00000079188221651,
+                0.00000025104152792,
+                0.00000008265223206,
+                0.00000002805711662,
+                0.00000000976821090,
+                0.00000000347407923,
+                0.00000000125828132,
+                0.00000000046298826,
+                0.00000000017272825,
+                0.00000000006523192,
+                0.00000000002490471,
+                0.00000000000960156,
+                0.00000000000373448,
+                0.00000000000146417,
+                0.00000000000057826,
+                0.00000000000022991,
+                0.00000000000009197,
+                0.00000000000003700,
+                0.00000000000001496,
+                0.00000000000000608,
+                0.00000000000000248,
+                0.00000000000000101,
+                0.00000000000000041,
+                0.00000000000000017,
+                0.00000000000000007,
+                0.00000000000000002};
+
+// series for ath2       on the interval -1.00000d+00 to -1.25000d-01
+//                                        with weighted error   2.57e-17
+//                                         log weighted error  16.59
+//                               significant figures required  15.07
+//                                    decimal places required  17.34
+
+        private final static double ath2cs[]={
+                0.00440527345871877,
+                -0.03042919452318455,
+                -0.00138565328377179,
+                -0.00018044439089549,
+                -0.00003380847108327,
+                -0.00000767818353522,
+                -0.00000196783944371,
+                -0.00000054837271158,
+                -0.00000016254615505,
+                -0.00000005053049981,
+                -0.00000001631580701,
+                -0.00000000543420411,
+                -0.00000000185739855,
+                -0.00000000064895120,
+                -0.00000000023105948,
+                -0.00000000008363282,
+                -0.00000000003071196,
+                -0.00000000001142367,
+                -0.00000000000429811,
+                -0.00000000000163389,
+                -0.00000000000062693,
+                -0.00000000000024260,
+                -0.00000000000009461,
+                -0.00000000000003716,
+                -0.00000000000001469,
+                -0.00000000000000584,
+                -0.00000000000000233,
+                -0.00000000000000093,
+                -0.00000000000000037,
+                -0.00000000000000015,
+                -0.00000000000000006,
+                -0.00000000000000002};
+
+// series for bi0        on the interval  0.          to  9.00000d+00
+//                                        with weighted error   2.46e-18
+//                                         log weighted error  17.61
+//                               significant figures required  17.90
+//                                    decimal places required  18.15
+
+        private final static double bi0cs[]={
+                -0.07660547252839144951,
+                1.927337953993808270,
+                0.2282644586920301339,
+                0.01304891466707290428,
+                0.00043442709008164874,
+                0.00000942265768600193,
+                0.00000014340062895106,
+                0.00000000161384906966,
+                0.00000000001396650044,
+                0.00000000000009579451,
+                0.00000000000000053339,
+                0.00000000000000000245};
+
+// series for bj0        on the interval  0.          to  1.60000d+01
+//                                        with weighted error   7.47e-18
+//                                         log weighted error  17.13
+//                               significant figures required  16.98
+//                                    decimal places required  17.68
+
+        private final static double bj0cs[]={
+                0.100254161968939137,
+                -0.665223007764405132,
+                0.248983703498281314,
+                -0.0332527231700357697,
+                0.0023114179304694015,
+                -0.0000991127741995080,
+                0.0000028916708643998,
+                -0.0000000612108586630,
+                0.0000000009838650793,
+                -0.0000000000124235515,
+                0.0000000000001265433,
+                -0.0000000000000010619,
+                0.0000000000000000074};
+
+// series for bm0        on the interval  0.          to  6.25000d-02
+//                                        with weighted error   4.98e-17
+//                                         log weighted error  16.30
+//                               significant figures required  14.97
+//                                    decimal places required  16.96
+
+        private final static double bm0cs[]={
+                0.09284961637381644,
+                -0.00142987707403484,
+                0.00002830579271257,
+                -0.00000143300611424,
+                0.00000012028628046,
+                -0.00000001397113013,
+                0.00000000204076188,
+                -0.00000000035399669,
+                0.00000000007024759,
+                -0.00000000001554107,
+                0.00000000000376226,
+                -0.00000000000098282,
+                0.00000000000027408,
+                -0.00000000000008091,
+                0.00000000000002511,
+                -0.00000000000000814,
+                0.00000000000000275,
+                -0.00000000000000096,
+                0.00000000000000034,
+                -0.00000000000000012,
+                0.00000000000000004};
+
+// series for bth0       on the interval  0.          to  6.25000d-02
+//                                        with weighted error   3.67e-17
+//                                         log weighted error  16.44
+//                               significant figures required  15.53
+//                                    decimal places required  17.13
+
+        private final static double bth0cs[]={
+                -0.24639163774300119,
+                0.001737098307508963,
+                -0.000062183633402968,
+                0.000004368050165742,
+                -0.000000456093019869,
+                0.000000062197400101,
+                -0.000000010300442889,
+                0.000000001979526776,
+                -0.000000000428198396,
+                0.000000000102035840,
+                -0.000000000026363898,
+                0.000000000007297935,
+                -0.000000000002144188,
+                0.000000000000663693,
+                -0.000000000000215126,
+                0.000000000000072659,
+                -0.000000000000025465,
+                0.000000000000009229,
+                -0.000000000000003448,
+                0.000000000000001325,
+                -0.000000000000000522,
+                0.000000000000000210,
+                -0.000000000000000087,
+                0.000000000000000036};
+
+// series for by0        on the interval  0.          to  1.60000d+01
+//                                        with weighted error   1.20e-17
+//                                         log weighted error  16.92
+//                               significant figures required  16.15
+//                                    decimal places required  17.48
+
+        private final static double by0cs[]={
+                -0.011277839392865573,
+                -0.12834523756042035,
+                -0.10437884799794249,
+                0.023662749183969695,
+                -0.002090391647700486,
+                0.000103975453939057,
+                -0.000003369747162423,
+                0.000000077293842676,
+                -0.000000001324976772,
+                0.000000000017648232,
+                -0.000000000000188105,
+                0.000000000000001641,
+                -0.000000000000000011};
+
+// series for bi1        on the interval  0.          to  9.00000d+00
+//                                        with weighted error   2.40e-17
+//                                         log weighted error  16.62
+//                               significant figures required  16.23
+//                                    decimal places required  17.14
+
+        private final static double bi1cs[]={
+                -0.001971713261099859,
+                0.40734887667546481,
+                0.034838994299959456,
+                0.001545394556300123,
+                0.000041888521098377,
+                0.000000764902676483,
+                0.000000010042493924,
+                0.000000000099322077,
+                0.000000000000766380,
+                0.000000000000004741,
+                0.000000000000000024};
+
+// series for bj1        on the interval  0.          to  1.60000d+01
+//                                        with weighted error   4.48e-17
+//                                         log weighted error  16.35
+//                               significant figures required  15.77
+//                                    decimal places required  16.89
+
+        private final static double bj1cs[]={
+                -0.11726141513332787,
+                -0.25361521830790640,
+                0.050127080984469569,
+                -0.004631514809625081,
+                0.000247996229415914,
+                -0.000008678948686278,
+                0.000000214293917143,
+                -0.000000003936093079,
+                0.000000000055911823,
+                -0.000000000000632761,
+                0.000000000000005840,
+                -0.000000000000000044};
+
+// series for bm1        on the interval  0.          to  6.25000d-02
+//                                        with weighted error   5.61e-17
+//                                         log weighted error  16.25
+//                               significant figures required  14.97
+//                                    decimal places required  16.91
+
+        private final static double bm1cs[]={
+                0.1047362510931285,
+                0.00442443893702345,
+                -0.00005661639504035,
+                0.00000231349417339,
+                -0.00000017377182007,
+                0.00000001893209930,
+                -0.00000000265416023,
+                0.00000000044740209,
+                -0.00000000008691795,
+                0.00000000001891492,
+                -0.00000000000451884,
+                0.00000000000116765,
+                -0.00000000000032265,
+                0.00000000000009450,
+                -0.00000000000002913,
+                0.00000000000000939,
+                -0.00000000000000315,
+                0.00000000000000109,
+                -0.00000000000000039,
+                0.00000000000000014,
+                -0.00000000000000005};
+
+// series for bth1       on the interval  0.          to  6.25000d-02
+//                                        with weighted error   4.10e-17
+//                                         log weighted error  16.39
+//                               significant figures required  15.96
+//                                    decimal places required  17.08
+
+        private final static double bth1cs[]={
+                0.74060141026313850,
+                -0.004571755659637690,
+                0.000119818510964326,
+                -0.000006964561891648,
+                0.000000655495621447,
+                -0.000000084066228945,
+                0.000000013376886564,
+                -0.000000002499565654,
+                0.000000000529495100,
+                -0.000000000124135944,
+                0.000000000031656485,
+                -0.000000000008668640,
+                0.000000000002523758,
+                -0.000000000000775085,
+                0.000000000000249527,
+                -0.000000000000083773,
+                0.000000000000029205,
+                -0.000000000000010534,
+                0.000000000000003919,
+                -0.000000000000001500,
+                0.000000000000000589,
+                -0.000000000000000237,
+                0.000000000000000097,
+                -0.000000000000000040};
+
+// series for by1        on the interval  0.          to  1.60000d+01
+//                                        with weighted error   1.87e-18
+//                                         log weighted error  17.73
+//                               significant figures required  17.83
+//                                    decimal places required  18.30
+
+        private final static double by1cs[]={
+                0.03208047100611908629,
+                1.262707897433500450,
+                0.00649996189992317500,
+                -0.08936164528860504117,
+                0.01325088122175709545,
+                -0.00089790591196483523,
+                0.00003647361487958306,
+                -0.00000100137438166600,
+                0.00000001994539657390,
+                -0.00000000030230656018,
+                0.00000000000360987815,
+                -0.00000000000003487488,
+                0.00000000000000027838,
+                -0.00000000000000000186};
+
+
+
+        /**
+        * Evaluates a Chebyshev series.
+        * @param x value at which to evaluate series
+        * @param series the coefficients of the series
+        */
+        public static double chebyshev(double x, double series[]) {
+                double twox,b0=0.0,b1=0.0,b2=0.0;
+                twox=2*x;
+                for(int i=series.length-1;i>-1;i--) {
+                        b2=b1;
+                        b1=b0;
+                        b0=twox*b1-b2+series[i];
+                }
+                return 0.5*(b0-b2);
+        }
+        /**
+        * Airy function.
+        * Based on the NETLIB Fortran function ai written by W. Fullerton.
+        */
+        public static double airy(double x) {
+                if(x<-1.0) {
+                        double mp[]=airyModPhase(x);
+                        return mp[0]*Math.cos(mp[1]);
+                } else if(x>1.0)
+                        return expAiry(x)*Math.exp(-2.0*x*Math.sqrt(x)/3.0);
+                else {
+                        final double z=x*x*x;
+                        return 0.375+(chebyshev(z,aifcs)-x*(0.25+chebyshev(z,aigcs)));
+                }
+        }
+        /**
+        * Airy modulus and phase.
+        * Based on the NETLIB Fortran subroutine r9aimp written by W. Fullerton.
+        * @return an array with [0] containing the modulus and [1] containing the phase.
+        */
+        private static double[] airyModPhase(double x) {
+                double z,mp[]=new double[2];
+                if(x<-2.0) {
+                        z=16.0/(x*x*x)+1.0;
+                        mp[0]=0.3125+chebyshev(z,am21cs);
+                        mp[1] =-0.625+chebyshev(z,ath1cs);
+                } else {
+                        z=(16.0/(x*x*x)+9.0)/7.0;
+                        mp[0]=0.3125+chebyshev(z,am22cs);
+                        mp[1]=-0.625+chebyshev(z,ath2cs);
+                }
+                final double sqrtx=Math.sqrt(-x);
+                mp[0]=Math.sqrt(mp[0]/sqrtx);
+                mp[1]=Math.PI/4.0-x*sqrtx*mp[1];
+                return mp;
+        }
+        /**
+        * Exponential scaled Airy function.
+        * Based on the NETLIB Fortran function aie written by W. Fullerton.
+        */
+        private static double expAiry(double x) {
+                if(x<-1.0) {
+                        double mp[]=airyModPhase(x);
+                        return mp[0]*Math.cos(mp[1]);
+                } else if(x<=1.0) {
+                        final double z=x*x*x;
+                        return 0.375+(chebyshev(z,aifcs)-x*(0.25+chebyshev(z,aigcs)))*Math.exp(2.0*x*Math.sqrt(x)/3.0);
+                } else {
+                        final double sqrtx=Math.sqrt(x);
+                        final double z=2.0/(x*sqrtx)-1.0;
+                        return (0.28125+chebyshev(z,aipcs))/Math.sqrt(sqrtx);
+                }
+        }
+        /**
+        * Bessel function of first kind, order zero.
+        * Based on the NETLIB Fortran function besj0 written by W. Fullerton.
+        */
+        public static double besselFirstZero(double x) {
+                double y=Math.abs(x);
+                if(y>4.0) {
+                        final double z=32/(y*y)-1;
+                        final double amplitude=(0.75+chebyshev(z,bm0cs))/Math.sqrt(y);
+                        final double theta=y-Math.PI/4.0+chebyshev(z,bth0cs)/y;
+                        return amplitude*Math.cos(theta);
+                } else if(y==0.0)
+                        return 1.0;
+                else
+                        return chebyshev(0.125*y*y-1,bj0cs);
+        }
+        /**
+        * Modified Bessel function of first kind, order zero.
+        * Based on the NETLIB Fortran function besi0 written by W. Fullerton.
+        */
+        public static double modBesselFirstZero(double x) {
+                double y=Math.abs(x);
+                if(y>3.0)
+                        return Math.exp(y)*expModBesselFirstZero(x);
+                else
+                        return 2.75+chebyshev(y*y/4.5-1.0,bi0cs);
+        }
+        /**
+        * Exponential scaled modified Bessel function of first kind, order zero.
+        * Based on the NETLIB Fortran function besi0e written by W. Fullerton.
+        */
+        private static double expModBesselFirstZero(double x) {
+                final double y=Math.abs(x);
+                if(y>3.0) {
+                        if(y>8.0)
+                                return (0.375+chebyshev(16.0/y-1.0,ai02cs))/Math.sqrt(y);
+                        else
+                                return (0.375+chebyshev((48.0/y-11.0)/5.0,ai0cs))/Math.sqrt(y);
+                } else
+                        return Math.exp(-y)*(2.75+chebyshev(y*y/4.5-1.0,bi0cs));
+        }
+        /**
+        * Bessel function of first kind, order one.
+        * Based on the NETLIB Fortran function besj1 written by W. Fullerton.
+        */
+        public static double besselFirstOne(double x) {
+                double y=Math.abs(x);
+                if(y>4.0) {
+                        final double z=32.0/(y*y)-1.0;
+                        final double amplitude=(0.75+chebyshev(z,bm1cs))/Math.sqrt(y);
+                        final double theta=y-3.0*Math.PI/4.0+chebyshev(z,bth1cs)/y;
+                        return Math.abs(amplitude)*x*Math.cos(theta)/Math.abs(x);
+                } else if(y==0.0)
+                        return 0.0;
+                else
+                        return x*(0.25+chebyshev(0.125*y*y-1.0,bj1cs));
+        }
+        /**
+        * Modified Bessel function of first kind, order one.
+        * Based on the NETLIB Fortran function besi1 written by W. Fullerton.
+        */
+        public static double modBesselFirstOne(double x) {
+                final double y=Math.abs(x);
+                if(y>3.0)
+                        return Math.exp(y)*expModBesselFirstOne(x);
+                else if(y==0.0)
+                        return 0.0;
+                else
+                        return x*(0.875+chebyshev(y*y/4.5-1.0,bi1cs));
+        }
+        /**
+        * Exponential scaled modified Bessel function of first kind, order one.
+        * Based on the NETLIB Fortran function besi1e written by W. Fullerton.
+        */
+        private static double expModBesselFirstOne(double x) {
+                final double y=Math.abs(x);
+                if(y>3.0) {
+                        if(y>8.0)
+                                return x/y*(0.375+chebyshev(16.0/y-1.0,ai12cs))/Math.sqrt(y);
+                        else
+                                return x/y*(0.375+chebyshev((48.0/y-11.0)/5.0,ai1cs))/Math.sqrt(y);
+                } else if(y==0.0)
+                        return 0.0;
+                else
+                        return Math.exp(-y)*x*(0.875+chebyshev(y*y/4.5-1.0,bi1cs));
+        }
+        /**
+        * Bessel function of second kind, order zero.
+        * Based on the NETLIB Fortran function besy0 written by W. Fullerton.
+        */
+        public static double besselSecondZero(double x) {
+                if(x>4.0) {
+                        final double z=32.0/(x*x)-1.0;
+                        final double amplitude=(0.75+chebyshev(z,bm0cs))/Math.sqrt(x);
+                        final double theta=x-Math.PI/4+chebyshev(z,bth0cs)/x;
+                        return amplitude*Math.sin(theta);
+                } else
+                        return (Math.log(0.5)+Math.log(x))*besselFirstZero(x)+0.375+chebyshev(0.125*x*x-1.0,by0cs)*2.0/Math.PI;
+        }
+        /**
+        * Bessel function of second kind, order one.
+        * Based on the NETLIB Fortran function besy1 written by W. Fullerton.
+        */
+        public static double besselSecondOne(double x) {
+                if(x>4.0) {
+                        final double z=32.0/(x*x)-1.0;
+                        final double amplitude=(0.75+chebyshev(z,bm1cs))/Math.sqrt(x);
+                        final double theta=x-3.0*Math.PI/4.0+chebyshev(z,bth1cs)/x;
+                        return amplitude*Math.sin(theta);
+                } else
+                        return 2.0*Math.log(0.5*x)*besselFirstOne(x)/Math.PI+(0.5+chebyshev(0.125*x*x-1.0,by1cs))/x;
+        }
+
+        private final static double LOGSQRT2PI=Math.log(SQRT2PI);
+
+        /**
+        * Gamma function.
+        * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz<BR>
+        * Applied Mathematics Division<BR>
+        * Argonne National Laboratory<BR>
+        * Argonne, IL 60439<BR>
+        * <P>
+        * References:
+        * <OL>
+        * <LI>"An Overview of Software Development for Special Functions", W. J. Cody, Lecture Notes in Mathematics, 506, Numerical Analysis Dundee, 1975, G. A. Watson (ed.), Springer Verlag, Berlin, 1976.
+        * <LI>Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968.
+        * </OL></P><P>
+        * From the original documentation:
+        * </P><P>
+        * This routine calculates the GAMMA function for a real argument X. 
+	* Computation is based on an algorithm outlined in reference 1. 
+	* The program uses rational functions that approximate the GAMMA 
+	* function to at least 20 significant decimal digits.  Coefficients 
+	* for the approximation over the interval (1,2) are unpublished. 
+	* Those for the approximation for X .GE. 12 are from reference 2. 
+	* The accuracy achieved depends on the arithmetic system, the 
+	* compiler, the intrinsic functions, and proper selection of the 
+	* machine-dependent constants. 
+        * </P><P>
+	* Error returns:<BR>
+	* The program returns the value XINF for singularities or when overflow would occur.
+        * The computation is believed to be free of underflow and overflow.
+	* </P>
+        * @return Double.MAX_VALUE if overflow would occur, i.e. if abs(x) > 171.624
+        * @author Jaco van Kooten
+	*/
+        public static double gamma(double x) {
+// Gamma function related constants
+                final double g_p[] = { -1.71618513886549492533811,
+                        24.7656508055759199108314,-379.804256470945635097577,
+                        629.331155312818442661052,866.966202790413211295064,
+                        -31451.2729688483675254357,-36144.4134186911729807069,
+                        66456.1438202405440627855 };
+                final double g_q[] = { -30.8402300119738975254353,
+                        315.350626979604161529144,-1015.15636749021914166146,
+                        -3107.77167157231109440444,22538.1184209801510330112,
+                        4755.84627752788110767815,-134659.959864969306392456,
+                        -115132.259675553483497211 };
+                final double g_c[] = { -.001910444077728,8.4171387781295e-4,
+                        -5.952379913043012e-4,7.93650793500350248e-4,
+                        -.002777777777777681622553,.08333333333333333331554247,
+                        .0057083835261 };
+                final double g_xbig = 171.624;
+
+                double fact=1.0, xden, xnum;
+                int i, n=0;
+                double y=x, z, y1;
+                boolean parity=false;
+                double res, sum, ysq;
+
+                if (y <= 0.0) {
+// ----------------------------------------------------------------------
+//  Argument is negative
+// ----------------------------------------------------------------------
+                        y = -(x);
+                        y1 = (int)y;
+                        res = y - y1;
+                        if (res != 0.0) {
+                                if (y1 != (((int)(y1*0.5)) * 2.0))
+                                        parity = true;
+                                fact = -Math.PI/ Math.sin(Math.PI * res);
+                                y++;
+                        } else 
+                                return Double.MAX_VALUE;
+                }
+// ----------------------------------------------------------------------
+//  Argument is positive
+// ----------------------------------------------------------------------
+                if (y < EPS) {
+// ----------------------------------------------------------------------
+//  Argument .LT. EPS
+// ----------------------------------------------------------------------
+                        if (y >= XMININ) 
+                                res = 1.0 / y;
+                        else 
+                                return Double.MAX_VALUE;
+                } else if (y < 12.0) {
+                        y1 = y;
+                        if (y < 1.0) {
+// ----------------------------------------------------------------------
+//  0.0 .LT. argument .LT. 1.0
+// ----------------------------------------------------------------------
+                                z = y;
+                                y++;
+                        } else {
+// ----------------------------------------------------------------------
+//  1.0 .LT. argument .LT. 12.0, reduce argument if necessary
+// ----------------------------------------------------------------------
+                                n = (int)y - 1;
+                                y -= (double) n;
+                                z = y - 1.0;
+                        }
+// ----------------------------------------------------------------------
+//  Evaluate approximation for 1.0 .LT. argument .LT. 2.0
+// ----------------------------------------------------------------------
+                        xnum = 0.0;
+                        xden = 1.0;
+                        for (i = 0; i < 8; ++i) {
+                                xnum = (xnum + g_p[i]) * z;
+                                xden = xden * z + g_q[i];
+                        }
+                        res = xnum / xden + 1.0;
+                        if (y1 < y) 
+// ----------------------------------------------------------------------
+//  Adjust result for case  0.0 .LT. argument .LT. 1.0
+// ----------------------------------------------------------------------
+                                res /= y1;
+                        else if (y1 > y) {
+// ----------------------------------------------------------------------
+//  Adjust result for case  2.0 .LT. argument .LT. 12.0
+// ----------------------------------------------------------------------
+                                for (i = 0; i < n; ++i) {
+                                        res *= y;
+                                        y++;
+                                }
+                        }
+                } else {
+// ----------------------------------------------------------------------
+//  Evaluate for argument .GE. 12.0
+// ----------------------------------------------------------------------
+                        if (y <= g_xbig) {
+                                ysq = y * y;
+                                sum = g_c[6];
+                                for (i = 0; i < 6; ++i)
+                                        sum = sum / ysq + g_c[i];
+                                sum = sum / y - y + LOGSQRT2PI;
+                                sum += (y - 0.5) * Math.log(y);
+                                res = Math.exp(sum);
+                        } else 
+                                return Double.MAX_VALUE;
+                }
+// ----------------------------------------------------------------------
+//  Final adjustments and return
+// ----------------------------------------------------------------------
+                if (parity)
+                        res = -res;
+                if (fact != 1.0)
+                        res = fact / res;
+                return res;
+        } 
+
+        /**
+        * The largest argument for which logGamma(x) is representable in the machine.
+        */
+        private final static double logGamma_xBig=2.55e305;
+
+// Function cache for logGamma
+        private static double logGammaCache_res=0.0;
+        private static double logGammaCache_x=0.0;
+
+	/**
+        * The natural logarithm of the gamma function.
+        * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz<BR>
+        * Applied Mathematics Division<BR>
+        * Argonne National Laboratory<BR>
+        * Argonne, IL 60439<BR>
+        * <P>
+        * References:
+        * <OL>
+        * <LI>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.
+        * <LI>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.
+        * <LI>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.
+        * </OL></P><P>
+        * From the original documentation:
+        * </P><P>
+        * This routine calculates the LOG(GAMMA) function for a positive real argument X.
+        * Computation is based on an algorithm outlined in references 1 and 2.
+        * The program uses rational functions that theoretically approximate LOG(GAMMA)
+        * to at least 18 significant decimal digits.  The approximation for X > 12 is from reference 3,
+        * while approximations for X < 12.0 are similar to those in reference 1, but are unpublished.
+        * The accuracy achieved depends on the arithmetic system, the compiler, the intrinsic functions,
+        * and proper selection of the machine-dependent constants.
+        * </P><P>
+        * Error returns:<BR>
+        * The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
+        * The computation is believed to be free of underflow and overflow.
+        * </P>
+        * @return Double.MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
+        * @author Jaco van Kooten
+	*/
+        public static double logGamma(double x) {
+// Log Gamma related constants
+                final double lg_d1 = -.5772156649015328605195174,
+                        lg_d2 = .4227843350984671393993777,
+         		lg_d4 = 1.791759469228055000094023;
+                final double lg_p1[] = { 4.945235359296727046734888,
+                        201.8112620856775083915565,2290.838373831346393026739,
+                        11319.67205903380828685045,28557.24635671635335736389,
+                        38484.96228443793359990269,26377.48787624195437963534,
+                        7225.813979700288197698961 };
+                final double lg_q1[] = { 67.48212550303777196073036,
+                        1113.332393857199323513008,7738.757056935398733233834,
+                        27639.87074403340708898585,54993.10206226157329794414,
+                        61611.22180066002127833352,36351.27591501940507276287,
+                        8785.536302431013170870835 };
+                final double lg_p2[] = { 4.974607845568932035012064,
+                        542.4138599891070494101986,15506.93864978364947665077,
+                        184793.2904445632425417223,1088204.76946882876749847,
+                        3338152.967987029735917223,5106661.678927352456275255,
+                        3074109.054850539556250927 };
+                final double lg_q2[] = { 183.0328399370592604055942,
+                        7765.049321445005871323047,133190.3827966074194402448,
+                        1136705.821321969608938755,5267964.117437946917577538,
+                        13467014.54311101692290052,17827365.30353274213975932,
+                        9533095.591844353613395747 };
+                final double lg_p4[] = { 14745.02166059939948905062,
+                        2426813.369486704502836312,121475557.4045093227939592,
+                        2663432449.630976949898078,29403789566.34553899906876,
+                        170266573776.5398868392998,492612579337.743088758812,
+                        560625185622.3951465078242 };
+                final double lg_q4[] = { 2690.530175870899333379843,
+                        639388.5654300092398984238,41355999.30241388052042842,
+                        1120872109.61614794137657,14886137286.78813811542398,
+                        101680358627.2438228077304,341747634550.7377132798597,
+                        446315818741.9713286462081 };
+                final double lg_c[] = { -0.001910444077728,8.4171387781295e-4,
+                        -5.952379913043012e-4,7.93650793500350248e-4,
+                        -0.002777777777777681622553,0.08333333333333333331554247,
+                        0.0057083835261 };
+//       Rough estimate of the fourth root of logGamma_xBig
+                final double lg_frtbig = 2.25e76;
+
+                final double pnt68 = 0.6796875;
+
+                double xden, corr, xnum;
+                int i;
+                double y, xm1, xm2, xm4, res, ysq;
+
+                if (x==logGammaCache_x)
+                        return logGammaCache_res;
+                y = x;
+                if (y > 0.0 && y <= logGamma_xBig) {
+                        if (y <= EPS) {
+                                res = -Math.log(y);
+                        } else if (y <= 1.5) {
+// ----------------------------------------------------------------------
+//  EPS .LT. X .LE. 1.5
+// ----------------------------------------------------------------------
+                                if (y < pnt68) {
+                                        corr = -Math.log(y);
+                                        xm1 = y;
+                                } else {
+                                        corr = 0.0;
+                                        xm1 = y - 1.0;
+                                }
+                                if (y <= 0.5 || y >= pnt68) {
+                                        xden = 1.0;
+                                        xnum = 0.0;
+                                        for (i = 0; i < 8; i++) {
+                                                xnum = xnum * xm1 + lg_p1[i];
+                                                xden = xden * xm1 + lg_q1[i];
+                                        }
+                                        res = corr + xm1 * (lg_d1 + xm1 * (xnum / xden));
+                                } else {
+                                        xm2 = y - 1.0;
+                                        xden = 1.0;
+                                        xnum = 0.0;
+                                        for (i = 0; i < 8; i++) {
+                                                xnum = xnum * xm2 + lg_p2[i];
+                                                xden = xden * xm2 + lg_q2[i];
+                                        }
+                                        res = corr + xm2 * (lg_d2 + xm2 * (xnum / xden));
+                                }
+                        } else if (y <= 4.0) {
+// ----------------------------------------------------------------------
+//  1.5 .LT. X .LE. 4.0
+// ----------------------------------------------------------------------
+                                xm2 = y - 2.0;
+                                xden = 1.0;
+                                xnum = 0.0;
+                                for (i = 0; i < 8; i++) {
+                                        xnum = xnum * xm2 + lg_p2[i];
+                                        xden = xden * xm2 + lg_q2[i];
+                                }
+                                res = xm2 * (lg_d2 + xm2 * (xnum / xden));
+                        } else if (y <= 12.0) {
+// ----------------------------------------------------------------------
+//  4.0 .LT. X .LE. 12.0
+// ----------------------------------------------------------------------
+                                xm4 = y - 4.0;
+                                xden = -1.0;
+                                xnum = 0.0;
+                                for (i = 0; i < 8; i++) {
+                                        xnum = xnum * xm4 + lg_p4[i];
+                                        xden = xden * xm4 + lg_q4[i];
+                                }
+                                res = lg_d4 + xm4 * (xnum / xden);
+                        } else {
+// ----------------------------------------------------------------------
+//  Evaluate for argument .GE. 12.0
+// ----------------------------------------------------------------------
+                                res = 0.0;
+                                if (y <= lg_frtbig) {
+                			res = lg_c[6];
+                			ysq = y * y;
+                			for (i = 0; i < 6; i++)
+                        		    	res = res / ysq + lg_c[i];
+                                }
+                                res /= y;
+                                corr = Math.log(y);
+                                res = res + LOGSQRT2PI - 0.5 * corr;
+                                res += y * (corr - 1.0);
+                        }
+                } else {
+// ----------------------------------------------------------------------
+//  Return for bad arguments
+// ----------------------------------------------------------------------
+                        res = Double.MAX_VALUE;
+                }
+// ----------------------------------------------------------------------
+//  Final adjustments and return
+// ----------------------------------------------------------------------
+                logGammaCache_x = x;
+                logGammaCache_res = res;
+                return res;
+        }
+
+        private final static int MAX_ITERATIONS = 150;
+        private final static double PRECISION = 4.0*EPS;
+
+        /**
+        * Incomplete gamma function.
+        * The computation is based on approximations presented in Numerical Recipes, Chapter 6.2 (W.H. Press et al, 1992).
+        * @param a require a>=0
+        * @param x require x>=0
+        * @return 0 if x<0, a<=0 or a>2.55E305 to avoid errors and over/underflow
+        * @author Jaco van Kooten
+        */
+        public static double incompleteGamma(double a, double x) {
+                if (x <= 0.0 || a <= 0.0 || a > logGamma_xBig)
+                        return 0.0;
+                if (x < (a+1.0))
+                        return gammaSeriesExpansion(a,x);
+                else 
+                        return 1.0-gammaFraction(a,x);
+        }
+        /**
+        * @author Jaco van Kooten
+        */
+        private static double gammaSeriesExpansion(double a, double x) {
+                double ap=a;
+                double del=1.0/a;
+                double sum = del;
+                for (int n=1; n < MAX_ITERATIONS; n++) {
+                        ++ap;
+                        del *= x/ap;
+                        sum += del;
+                        if (del < sum*PRECISION)
+                                return sum*Math.exp(-x + a*Math.log(x) - logGamma(a));
+                }
+                return 0.0;
+        }
+        /**
+        * @author Jaco van Kooten
+        */
+        private static double gammaFraction(double a, double x) {
+                double b=x+1.0-a;
+                double c=1.0/XMININ;
+                double d=1.0/b;
+                double h=d;
+                double del=0.0;
+                double an; 
+                for (int i=1; i<MAX_ITERATIONS && Math.abs(del-1.0)>PRECISION; i++) {
+                        an = -i*(i-a);
+                        b += 2.0;
+                        d=an*d+b;
+                        c=b+an/c;
+                        if (Math.abs(c) < XMININ)
+                                c=XMININ;
+                        if (Math.abs(d) < XMININ)
+                                c=XMININ;
+                        d=1.0/d;
+                        del=d*c;
+                        h *= del;
+                }
+                return Math.exp(-x + a*Math.log(x) - logGamma(a))*h;
+        }
+        /**
+        * Beta function.
+        * @param p require p>0
+        * @param q require q>0
+        * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
+        * @author Jaco van Kooten
+        */
+        public static double beta(double p, double q) {
+                if (p <= 0.0 || q <= 0.0 || (p+q) > logGamma_xBig)
+                        return 0.0;
+                else
+                        return Math.exp(logBeta(p,q));
+	}
+
+// Function cache for logBeta
+        private static double logBetaCache_res=0.0;
+        private static double logBetaCache_p=0.0;
+        private static double logBetaCache_q=0.0;
+
+        /**
+        * The natural logarithm of the beta function.
+        * @param p require p>0
+        * @param q require q>0
+        * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
+        * @author Jaco van Kooten
+        */
+        public static double logBeta(double p, double q) {
+                if (p != logBetaCache_p || q != logBetaCache_q) {
+                        logBetaCache_p = p;
+                        logBetaCache_q = q;
+                        if (p <= 0.0 || q <= 0.0 || (p+q) > logGamma_xBig)
+                                logBetaCache_res = 0.0;
+                        else
+                                logBetaCache_res = logGamma(p)+logGamma(q)-logGamma(p+q);
+                }
+                return logBetaCache_res;
+        }
+        /**
+        * Incomplete beta function.
+        * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
+        * @param x require 0<=x<=1
+        * @param p require p>0
+        * @param q require q>0
+        * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow
+        * @author Jaco van Kooten
+        */
+	public static double incompleteBeta(double x, double p, double q) {
+                if (x <= 0.0) 
+        		return 0.0;
+                else if (x >= 1.0)
+                        return 1.0;
+                else if (p <= 0.0 || q <= 0.0 || (p+q) > logGamma_xBig)
+        		return 0.0;
+                else {
+                        final double beta_gam=Math.exp(-logBeta(p,q) + p*Math.log(x) + q*Math.log(1.0-x));
+                        if (x < (p+1.0)/(p+q+2.0))
+                                return beta_gam*betaFraction(x,p,q)/p;
+        		else
+        			return 1.0-(beta_gam*betaFraction(1.0-x,q,p)/q);
+                }
+        }
+        /**
+	* Evaluates of continued fraction part of incomplete beta function.
+        * Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
+        * @author Jaco van Kooten
+        */
+	private static double betaFraction(double x, double p, double q) {
+        	int m, m2;
+        	double sum_pq, p_plus, p_minus, c =1.0 , d, delta, h, frac;
+        	sum_pq  = p + q;
+        	p_plus  = p + 1.0;
+        	p_minus = p - 1.0;
+        	h=1.0-sum_pq*x/p_plus;
+        	if (Math.abs(h) < XMININ)
+                        h=XMININ;
+        	h=1.0/h;
+                frac = h;
+        	m=1;
+        	delta = 0.0;
+        	while (m <= MAX_ITERATIONS && Math.abs(delta-1.0) > PRECISION ) {
+                        m2=2*m;
+                // even index for d 
+        		d=m*(q-m)*x/((p_minus+m2)*(p+m2));
+        		h=1.0+d*h;
+        		if (Math.abs(h) < XMININ)
+                                h=XMININ;
+        		h=1.0/h;
+        		c=1.0+d/c;
+        		if (Math.abs(c) < XMININ)
+                                c=XMININ;
+        		frac *= h*c;
+                // odd index for d
+        		d = -(p+m)*(sum_pq+m)*x/((p+m2)*(p_plus+m2));
+        		h=1.0+d*h;
+        		if (Math.abs(h) < XMININ)
+                                h=XMININ;
+        		h=1.0/h;
+        		c=1.0+d/c;
+        		if (Math.abs(c) < XMININ)
+                                c=XMININ;
+                        delta=h*c;
+                        frac *= delta;
+                        m++;
+                }
+                return frac;
+        }
+
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice 
+// is preserved.
+// ====================================================
+//
+//			     x
+//		      2      |\
+//     erf(x)  =  ---------  | exp(-t*t)dt
+//	 	   sqrt(pi) \| 
+//			     0
+//
+//     erfc(x) =  1-erf(x)
+//  Note that 
+//		erf(-x) = -erf(x)
+//		erfc(-x) = 2 - erfc(x)
+//
+// Method:
+//	1. For |x| in [0, 0.84375]
+//	    erf(x)  = x + x*R(x^2)
+//          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+//                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+//	   where R = P/Q where P is an odd poly of degree 8 and
+//	   Q is an odd poly of degree 10.
+//						 -57.90
+//			| R - (erf(x)-x)/x | <= 2
+//	
+//
+//	   Remark. The formula is derived by noting
+//          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+//	   and that
+//          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+//	   is close to one. The interval is chosen because the fix
+//	   point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+//	   near 0.6174), and by some experiment, 0.84375 is chosen to
+// 	   guarantee the error is less than one ulp for erf.
+//
+//      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+//         c = 0.84506291151 rounded to single (24 bits)
+//         	erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+//         	erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+//			  1+(c+P1(s)/Q1(s))    if x < 0
+//         	|P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+//	   Remark: here we use the taylor series expansion at x=1.
+//		erf(1+s) = erf(1) + s*Poly(s)
+//			 = 0.845.. + P1(s)/Q1(s)
+//	   That is, we use rational approximation to approximate
+//			erf(1+s) - (c = (single)0.84506291151)
+//	   Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+//	   where 
+//		P1(s) = degree 6 poly in s
+//		Q1(s) = degree 6 poly in s
+//
+//      3. For x in [1.25,1/0.35(~2.857143)], 
+//         	erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+//         	erf(x)  = 1 - erfc(x)
+//	   where 
+//		R1(z) = degree 7 poly in z, (z=1/x^2)
+//		S1(z) = degree 8 poly in z
+//
+//      4. For x in [1/0.35,28]
+//         	erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+//			= 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+//			= 2.0 - tiny		(if x <= -6)
+//         	erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
+//         	erf(x)  = sign(x)*(1.0 - tiny)
+//	   where
+//		R2(z) = degree 6 poly in z, (z=1/x^2)
+//		S2(z) = degree 7 poly in z
+//
+//      Note1:
+//	   To compute exp(-x*x-0.5625+R/S), let s be a single
+//	   precision number and s := x; then
+//		-x*x = -s*s + (s-x)*(s+x)
+//	        exp(-x*x-0.5626+R/S) = 
+//			exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+//      Note2:
+//	   Here 4 and 5 make use of the asymptotic series
+//			  exp(-x*x)
+//		erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+//			  x*sqrt(pi)
+//	   We use rational approximation to approximate
+//      	g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+//	   Here is the error bound for R1/S1 and R2/S2
+//      	|R1/S1 - f(x)|  < 2**(-62.57)
+//      	|R2/S2 - f(x)|  < 2**(-61.52)
+//
+//      5. For inf > x >= 28
+//         	erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+//         	erfc(x) = tiny*tiny (raise underflow) if x > 0
+//			= 2 - tiny if x<0
+//
+//      7. Special case:
+//         	erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+//         	erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, 
+//	   	erfc/erf(NaN) is NaN
+//
+
+	/**
+        * Error function.
+        * Based on C-code for the error function developed at Sun Microsystems.
+        * @author Jaco van Kooten
+	*/
+        public static double error(double x) {
+// Coefficients for approximation to  erf on [0,0.84375]
+                final double e_efx=1.28379167095512586316e-01;
+	  	//double efx8=1.02703333676410069053e00;
+	  	final double ePp[]={
+                        1.28379167095512558561e-01,
+                        -3.25042107247001499370e-01,
+                        -2.84817495755985104766e-02,
+                        -5.77027029648944159157e-03,
+                        -2.37630166566501626084e-05};
+                final double eQq[]={
+                        3.97917223959155352819e-01,
+                        6.50222499887672944485e-02,
+                        5.08130628187576562776e-03,
+                        1.32494738004321644526e-04,
+                        -3.96022827877536812320e-06};
+// Coefficients for approximation to  erf  in [0.84375,1.25] 
+                final double ePa[]={
+                        -2.36211856075265944077e-03,
+                        4.14856118683748331666e-01,
+                        -3.72207876035701323847e-01,
+                        3.18346619901161753674e-01,
+                        -1.10894694282396677476e-01,
+                        3.54783043256182359371e-02,
+                        -2.16637559486879084300e-03};
+                final double eQa[]={
+                        1.06420880400844228286e-01,
+                        5.40397917702171048937e-01,
+                        7.18286544141962662868e-02,
+                        1.26171219808761642112e-01,
+                        1.36370839120290507362e-02,
+                        1.19844998467991074170e-02};
+ 	  	final double e_erx=8.45062911510467529297e-01;
+
+        	double P,Q,s,retval;
+        	final double abs_x = (x >= 0.0 ? x : -x);
+                if ( abs_x < 0.84375 ) {                               // 0 < |x| < 0.84375
+                        if (abs_x < 3.7252902984619141e-9 )     // |x| < 2**-28
+                                retval = abs_x + abs_x*e_efx;
+                        else {
+        			s = x*x;
+         			P = ePp[0]+s*(ePp[1]+s*(ePp[2]+s*(ePp[3]+s*ePp[4])));
+        			Q = 1.0+s*(eQq[0]+s*(eQq[1]+s*(eQq[2]+s*(eQq[3]+s*eQq[4]))));
+        			retval = abs_x + abs_x*(P/Q);
+           		}
+        	} else if (abs_x < 1.25) {                             // 0.84375 < |x| < 1.25
+        		s = abs_x-1.0;
+                        P = ePa[0]+s*(ePa[1]+s*(ePa[2]+s*(ePa[3]+s*(ePa[4]+s*(ePa[5]+s*ePa[6])))));
+                        Q = 1.0+s*(eQa[0]+s*(eQa[1]+s*(eQa[2]+s*(eQa[3]+s*(eQa[4]+s*eQa[5])))));
+                        retval = e_erx + P/Q;
+	       } else if (abs_x >= 6.0) 
+                        retval = 1.0;
+                else                                                    // 1.25 < |x| < 6.0 
+                        retval = 1.0-complementaryError(abs_x);
+                return (x >= 0.0) ? retval : -retval;
+        }
+	/**
+        * Complementary error function.
+        * Based on C-code for the error function developed at Sun Microsystems.
+        * @author Jaco van Kooten
+	*/
+	public static double complementaryError(double x) {
+// Coefficients for approximation to  erfc in [1.25,1/.35]
+                final double eRa[]={
+                        -9.86494403484714822705e-03,
+                        -6.93858572707181764372e-01,
+                        -1.05586262253232909814e01, 
+                        -6.23753324503260060396e01, 
+                        -1.62396669462573470355e02, 
+                        -1.84605092906711035994e02, 
+                        -8.12874355063065934246e01, 
+                        -9.81432934416914548592e00};
+                final double eSa[]={
+                        1.96512716674392571292e01, 
+                        1.37657754143519042600e02,
+                        4.34565877475229228821e02,
+                        6.45387271733267880336e02,
+                        4.29008140027567833386e02,
+                        1.08635005541779435134e02,
+                        6.57024977031928170135e00,
+                        -6.04244152148580987438e-02};
+// Coefficients for approximation to  erfc in [1/.35,28]
+                final double eRb[]={
+                        -9.86494292470009928597e-03, 
+                        -7.99283237680523006574e-01, 
+                        -1.77579549177547519889e01, 
+                        -1.60636384855821916062e02, 
+                        -6.37566443368389627722e02, 
+                        -1.02509513161107724954e03, 
+                        -4.83519191608651397019e02};
+                final double eSb[]={
+                        3.03380607434824582924e01, 
+                        3.25792512996573918826e02, 
+                        1.53672958608443695994e03,
+                        3.19985821950859553908e03,
+                        2.55305040643316442583e03,
+                        4.74528541206955367215e02,
+                        -2.24409524465858183362e01};
+
+          	double s,retval,R,S;
+                final double abs_x =(x>=0.0 ? x : -x);
+                if (abs_x < 1.25)
+        		retval = 1.0-error(abs_x);
+                else if (abs_x > 28.0)
+                        retval=0.0;
+                else {						// 1.25 < |x| < 28 
+                        s = 1.0/(abs_x*abs_x);
+                        if (abs_x < 2.8571428) {                // ( |x| < 1/0.35 ) 
+                                R=eRa[0]+s*(eRa[1]+s*(eRa[2]+s*(eRa[3]+s*(eRa[4]+s*(eRa[5]+s*(eRa[6]+s*eRa[7]))))));
+        	    		S=1.0+s*(eSa[0]+s*(eSa[1]+s*(eSa[2]+s*(eSa[3]+s*(eSa[4]+s*(eSa[5]+s*(eSa[6]+s*eSa[7])))))));
+        		} else {	  				// ( |x| > 1/0.35 )
+                                R=eRb[0]+s*(eRb[1]+s*(eRb[2]+s*(eRb[3]+s*(eRb[4]+s*(eRb[5]+s*eRb[6])))));
+        	    		S=1.0+s*(eSb[0]+s*(eSb[1]+s*(eSb[2]+s*(eSb[3]+s*(eSb[4]+s*(eSb[5]+s*eSb[6]))))));
+ 			}
+                        retval =  Math.exp(-x*x - 0.5625 + R/S)/abs_x;
+                }
+                return (x >= 0.0) ? retval : 2.0-retval;
+	}
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/BetaDistribution.java b/LibrarySource/JSci/maths/statistics/BetaDistribution.java
new file mode 100644
index 0000000..6a83cbb
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/BetaDistribution.java
@@ -0,0 +1,68 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The BetaDistribution class provides an object for encapsulating beta distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public final class BetaDistribution extends ProbabilityDistribution {
+        private double p,q;
+
+        /**
+        * Constructs a beta distribution.
+        * @param dgrP degrees of freedom p.
+        * @param dgrQ degrees of freedom q.
+        */
+        public BetaDistribution(double dgrP,double dgrQ) {
+                if(dgrP<=0 || dgrQ<=0)
+                        throw new OutOfRangeException("The degrees of freedom must be greater than zero.");
+                p=dgrP;
+                q=dgrQ;
+        }
+        /**
+        * Returns the degrees of freedom p.
+        */
+        public double getDegreesOfFreedomP() {
+                return p;
+        }
+        /**
+        * Returns the degrees of freedom q.
+        */
+        public double getDegreesOfFreedomQ() {
+                return q;
+        }
+        /**
+        * Probability density function of a beta distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X);
+                if(X==0.0 || X==1.0)
+                        return 0.0;
+                return Math.exp(-SpecialMath.logBeta(p,q)+(p-1.0)*Math.log(X)+(q-1.0)*Math.log(1.0-X));
+        }
+        /**
+        * Cumulative beta distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X);
+                return SpecialMath.incompleteBeta(X,p,q);
+        }
+        /**
+	* Inverse of the cumulative beta distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                if(probability==0.0)
+                        return 0.0;
+                if(probability==1.0)
+                        return 1.0;
+                return findRoot(probability, 0.5, 0.0, 1.0);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/BinomialDistribution.java b/LibrarySource/JSci/maths/statistics/BinomialDistribution.java
new file mode 100644
index 0000000..7f33498
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/BinomialDistribution.java
@@ -0,0 +1,82 @@
+package JSci.maths.statistics;
+
+import JSci.maths.ExtraMath;
+
+/**
+* The BinomialDistribution class provides an object for encapsulating binomial distributions.
+* @version 0.1
+* @author Mark Hale
+*/
+public final class BinomialDistribution extends ProbabilityDistribution {
+        private int n;
+        private double p;
+
+        /**
+        * Constructs a binomial distribution.
+        * @param trials the number of trials.
+        * @param prob the probability.
+        */
+        public BinomialDistribution(int trials,double prob) {
+                if(trials<=0)
+                        throw new OutOfRangeException("The number of trials should be (strictly) positive.");
+                n=trials;
+                if(prob<0.0 || prob>1.0)
+                        throw new OutOfRangeException("The probability should be between 0 and 1.");
+                p=prob;
+        }
+        /**
+        * Returns the number of trials.
+        */
+        public int getTrialsParameter() {
+                return n;
+        }
+        /**
+        * Returns the probability.
+        */
+        public double getProbabilityParameter() {
+                return p;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return n*p;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return n*p*(1.0-p);
+        }
+        /**
+        * Probability density function of a binomial distribution.
+        * @param X should be integer-valued.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,n);
+                return ExtraMath.binomial(n,X)*Math.pow(p,X)*Math.pow(1.0-p,n-X);
+        }
+        /**
+        * Cumulative binomial distribution function.
+        * @param X should be integer-valued.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,n);
+                double sum=0.0;
+                for(double i=0.0;i<=X;i++)
+                        sum+=probability(i);
+                return sum;
+        }
+        /**
+	* Inverse of the cumulative binomial distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return Math.floor(findRoot(probability,n/2.0,0.0,n));
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/CauchyDistribution.java b/LibrarySource/JSci/maths/statistics/CauchyDistribution.java
new file mode 100644
index 0000000..214a154
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/CauchyDistribution.java
@@ -0,0 +1,67 @@
+package JSci.maths.statistics;
+
+/**
+* The CauchyDistribution class provides an object for encapsulating Cauchy distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class CauchyDistribution extends ProbabilityDistribution {
+        private double alpha;
+        private double gamma;
+
+        /**
+        * Constructs the standard Cauchy distribution.
+        */
+        public CauchyDistribution() {
+                this(0.0,1.0);
+        }
+        /**
+        * Constructs a Cauchy distribution.
+        * @param location the location parameter.
+        * @param scale the scale parameter.
+        */
+        public CauchyDistribution(double location,double scale) {
+                if(scale<0.0)
+                        throw new OutOfRangeException("The scale parameter should be positive.");
+                alpha=location;
+                gamma=scale;
+        }
+        /**
+        * Returns the location parameter.
+        */
+        public double getLocationParameter() {
+                return alpha;
+        }
+        /**
+        * Returns the scale parameter.
+        */
+        public double getScaleParameter() {
+                return gamma;
+        }
+        /**
+        * Probability density function of a Cauchy distribution.
+        * P(X) = <img border=0 alt="Gamma" src="../doc-files/ugamma.gif">/(<img border=0 alt="pi" src="../doc-files/pi.gif">(<img border=0 alt="Gamma" src="../doc-files/ugamma.gif"><sup>2</sup>+(X-<img border=0 alt="alpha" src="../doc-files/alpha.gif">)<sup>2</sup>)).
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                final double y=X-alpha;
+                return gamma/(Math.PI*(gamma*gamma+y*y));
+        }
+        /**
+        * Cumulative Cauchy distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                return 0.5+Math.atan((X-alpha)/gamma)/Math.PI;
+        }
+        /**
+	* Inverse of the cumulative Cauchy distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return alpha-gamma/Math.tan(Math.PI*probability);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/ChiSqrDistribution.java b/LibrarySource/JSci/maths/statistics/ChiSqrDistribution.java
new file mode 100644
index 0000000..5767f62
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/ChiSqrDistribution.java
@@ -0,0 +1,58 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The ChiSqrDistribution class provides an object for encapsulating chi-squared distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public final class ChiSqrDistribution extends ProbabilityDistribution {
+        private double r;
+// The ChiSqr and Gamma distributions are closely related.
+        private GammaDistribution gamma;
+
+        /**
+        * Constructs a chi-squared distribution.
+        * @param dgr degrees of freedom.
+        */
+        public ChiSqrDistribution(double dgr) {
+                if(dgr<=0.0)
+                        throw new OutOfRangeException("The degrees of freedom must be greater than zero.");
+                r=dgr;
+                gamma=new GammaDistribution(0.5*r);
+        }
+        /**
+        * Returns the degrees of freedom.
+        */
+        public double getDegreesOfFreedom() {
+                return r;
+        }
+        /**
+        * Probability density function of a chi-squared distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                return 0.5*gamma.probability(0.5*X);
+        }
+        /**
+        * Cumulative chi-squared distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return SpecialMath.incompleteGamma(0.5*r,0.5*X);
+        }
+        /**
+	* Inverse of the cumulative chi-squared distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                if(probability==1.0)
+                        return Double.MAX_VALUE;
+                else
+                        return 2.0*gamma.inverse(probability);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/ExponentialDistribution.java b/LibrarySource/JSci/maths/statistics/ExponentialDistribution.java
new file mode 100644
index 0000000..fd6cddb
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/ExponentialDistribution.java
@@ -0,0 +1,81 @@
+package JSci.maths.statistics;
+
+/**
+* The ExponentialDistribution class provides an object for encapsulating exponential distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class ExponentialDistribution extends ProbabilityDistribution {
+        private double lambda;
+
+        /**
+        * Constructs the standard exponential distribution.
+        */
+        public ExponentialDistribution() {
+                this(1.0);
+        }
+        /**
+        * Constructs an exponential distribution.
+        * @param decay the scale parameter.
+        */
+        public ExponentialDistribution(double decay) {
+                if(decay<0.0)
+                        throw new OutOfRangeException("The scale parameter should be positive.");
+                lambda=decay;
+        }
+        /**
+        * Constructs an exponential distribution from a data set.
+        * @param array a sample.
+        */
+        public ExponentialDistribution(double array[]) {
+                double sumX=array[0];
+                for(int i=1;i<array.length;i++)
+                        sumX+=array[i];
+                lambda=sumX/array.length;
+        }
+        /**
+        * Returns the scale parameter.
+        */
+        public double getScaleParameter() {
+                return lambda;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return lambda;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return lambda*lambda;
+        }
+        /**
+        * Probability density function of an exponential distribution.
+        * P(X) = <img border=0 alt="lambda" src="../doc-files/lambda.gif">e<sup>-<img border=0 alt="lambda" src="../doc-files/lambda.gif">X</sup>.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return lambda*Math.exp(-lambda*X);
+        }
+        /**
+        * Cumulative exponential distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return 1.0-Math.exp(-lambda*X);
+        }
+        /**
+	* Inverse of the cumulative exponential distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return -Math.log(1.0-probability)/lambda;
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/FDistribution.java b/LibrarySource/JSci/maths/statistics/FDistribution.java
new file mode 100644
index 0000000..278ef57
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/FDistribution.java
@@ -0,0 +1,80 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The FDistribution class provides an object for encapsulating F-distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public final class FDistribution extends ProbabilityDistribution {
+        private double p,q;
+
+        /**
+        * Constructs an F-distribution.
+        * @param dgrP degrees of freedom p.
+        * @param dgrQ degrees of freedom q.
+        */
+        public FDistribution(double dgrP, double dgrQ) {
+                if(dgrP<=0.0 || dgrQ<=0.0)
+                        throw new OutOfRangeException("The degrees of freedom must be greater than zero.");
+                p=dgrP;
+                q=dgrQ;
+        }
+
+        /**
+        * Returns the degrees of freedom p.
+        */
+        public double getDegreesOfFreedomP() {
+                return p;
+        }
+        /**
+        * Returns the degrees of freedom q.
+        */
+        public double getDegreesOfFreedomQ() {
+                return q;
+        }
+        /**
+        * Probability density function of an F-distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+// We make use of the fact that when x has an F-distibution then
+// y = q/(q+p*x) has a beta distribution with parameters p/2 and q/2.
+                checkRange(X,0.0,Double.MAX_VALUE);
+                double y=q/(q+(p*X));
+                BetaDistribution beta=new BetaDistribution(p/2.0,q/2.0);
+                return beta.probability(y)*y*y*p/q;
+        }
+        /**
+        * Cumulative F-distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+// We make use of the fact that when x has an F-distibution then
+// y = q/(q+p*x) has a beta distribution with parameters p/2 and q/2.
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return SpecialMath.incompleteBeta(1.0/(1.0+q/(p*X)),p/2.0,q/2.0);
+        }
+        /**
+	* Inverse of the cumulative F-distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+// We make use of the fact that when x has an F-distibution then
+// y = q/(q+p*x) has a beta distribution with parameters p/2 and q/2.
+                checkRange(probability);
+                if(probability==0.0)
+                        return 0.0;
+                if(probability==1.0)
+                        return Double.MAX_VALUE;
+                BetaDistribution beta=new BetaDistribution(p/2.0,q/2.0);
+                double y=beta.inverse(1.0-probability);
+                if(y<2.23e-308) //avoid overflow
+                        return Double.MAX_VALUE;
+                else
+                        return (p/q)*(1.0/y-1.0);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/GammaDistribution.java b/LibrarySource/JSci/maths/statistics/GammaDistribution.java
new file mode 100644
index 0000000..b92250e
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/GammaDistribution.java
@@ -0,0 +1,79 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The GammaDistribution class provides an object for encapsulating gamma distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public final class GammaDistribution extends ProbabilityDistribution {
+        private double shape;
+
+        /**
+        * Constructs a gamma distribution.
+        * @param s the shape parameter.
+        */
+        public GammaDistribution(double s) {
+                if(s<=0.0)
+                        throw new OutOfRangeException("The shape parameter should be (strictly) positive.");
+                shape=s;
+        }
+        /**
+        * Returns the shape parameter.
+        */
+        public double getShapeParameter() {
+                return shape;
+        }
+        /**
+        * Returns the shape parameter.
+        */
+        public void setShapeParameter(double s) {
+                 shape = s;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return shape;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return shape;
+        }
+        /**
+        * Probability density function of a gamma distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                if(X==0.0)
+                        return 0.0;
+                else
+                        return Math.exp(-SpecialMath.logGamma(shape)-X+(shape-1)*Math.log(X));
+        }
+        /**
+        * Cumulative gamma distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return SpecialMath.incompleteGamma(shape,X);
+        }
+        /**
+	* Inverse of the cumulative gamma distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                if(probability==0.0)
+                        return 0.0;
+                if(probability==1.0)
+                        return Double.MAX_VALUE;
+                return findRoot(probability, shape, 0.0, Double.MAX_VALUE);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/GeometricDistribution.java b/LibrarySource/JSci/maths/statistics/GeometricDistribution.java
new file mode 100644
index 0000000..607705e
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/GeometricDistribution.java
@@ -0,0 +1,69 @@
+package JSci.maths.statistics;
+
+/**
+* The GeometricDistribution class provides an object for encapsulating geometric distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class GeometricDistribution extends ProbabilityDistribution {
+        private double success;
+        private double failure;
+
+        /**
+        * Constructs a geometric distribution.
+        * @param prob the probability of success.
+        */
+        public GeometricDistribution(double prob) {
+                if(prob<0.0 || prob>1.0)
+                        throw new OutOfRangeException("The probability should be between 0.0 and 1.0.");
+                success=prob;
+                failure=1.0-prob;
+        }
+        /**
+        * Returns the success parameter.
+        */
+        public double getSuccessParameter() {
+                return success;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return 1.0/success;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return failure/(success*success);
+        }
+        /**
+        * Probability density function of a geometric distribution.
+        * P(X) = p (1-p)<sup>X-1</sup>.
+        * @param X should be integer-valued.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return success*Math.pow(failure,X-1);
+        }
+        /**
+        * Cumulative geometric distribution function.
+        * @param X should be integer-valued.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return 1.0-Math.pow(failure,X);
+        }
+        /**
+	* Inverse of the cumulative geometric distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return Math.log(1.0-probability)/Math.log(failure);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/LognormalDistribution.java b/LibrarySource/JSci/maths/statistics/LognormalDistribution.java
new file mode 100644
index 0000000..0b9faa1
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/LognormalDistribution.java
@@ -0,0 +1,62 @@
+package JSci.maths.statistics;
+
+/**
+* The LognormalDistribution class provides an object for encapsulating lognormal distributions.
+* @version 0.1
+* @author Mark Hale
+*/
+public final class LognormalDistribution extends ProbabilityDistribution {
+        private NormalDistribution normal;
+
+        /**
+        * Constructs a standard lognormal distribution.
+        */
+        public LognormalDistribution() {
+                this(0.0,1.0);
+        }
+        /**
+        * Constructs a lognormal distribution.
+        * @param mu the mu parameter.
+        * @param sigma the sigma parameter.
+        */
+        public LognormalDistribution(double mu,double sigma) {
+                normal=new NormalDistribution(mu,sigma*sigma);
+        }
+        /**
+        * Returns the mu parameter.
+        */
+        public double getMuParameter() {
+                return normal.getMean();
+        }
+        /**
+        * Returns the sigma parameter.
+        */
+        public double getSigmaParameter() {
+                return Math.sqrt(normal.getVariance());
+        }
+        /**
+        * Probability density function of a lognormal distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return normal.probability(Math.log(X))/X;
+        }
+        /**
+        * Cumulative lognormal distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return normal.cumulative(Math.log(X));
+        }
+        /**
+	* Inverse of the cumulative lognormal distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                return Math.exp(normal.inverse(probability));
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/NormalDistribution.java b/LibrarySource/JSci/maths/statistics/NormalDistribution.java
new file mode 100644
index 0000000..6d8632c
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/NormalDistribution.java
@@ -0,0 +1,105 @@
+package JSci.maths.statistics;
+
+import JSci.maths.*;
+
+/**
+* The NormalDistribution class provides an object for encapsulating normal distributions.
+* @version 1.1
+* @author Jaco van Kooten
+*/
+public final class NormalDistribution extends ProbabilityDistribution implements NumericalConstants {
+        private double mean,variance;
+        private double pdfDenominator,cdfDenominator;
+
+        /**
+        * Constructs the standard normal distribution (zero mean and unity variance).
+        */
+        public NormalDistribution() {
+                this(0.0,1.0);
+        }
+        /**
+        * Constructs a normal distribution.
+        * @param mu the mean.
+        * @param var the variance.
+        */
+        public NormalDistribution(double mu,double var) {
+                mean=mu;
+                if(var<=0.0) 
+                        throw new OutOfRangeException("The variance should be (strictly) positive.");
+                variance=var;
+                pdfDenominator=SQRT2PI*Math.sqrt(variance);
+                cdfDenominator=SQRT2*Math.sqrt(variance);
+        }
+        /**
+        * Constructs a normal distribution from a data set.
+        * @param array a sample.
+        * @author Mark Hale
+        */
+        public NormalDistribution(double array[]) {
+                double sumX=array[0];
+                double sumX2=array[0]*array[0];
+                for(int i=1;i<array.length;i++) {
+                        sumX+=array[i];
+                        sumX2+=array[i]*array[i];
+                }
+                mean=sumX/array.length;
+                variance=mean*mean-sumX2/(array.length*array.length);
+                pdfDenominator=SQRT2PI*Math.sqrt(variance);
+                cdfDenominator=SQRT2*Math.sqrt(variance);
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return mean;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return variance;
+        }
+        /**
+        * Probability density function of a normal (Gaussian) distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                return Math.exp(-(X-mean)*(X-mean)/(2*variance))/pdfDenominator;
+        }
+        /**
+        * Cumulative normal distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                return SpecialMath.complementaryError(-(X-mean)/cdfDenominator)/2;
+        }
+        /**
+	* Inverse of the cumulative normal distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                if(probability==0.0)
+                        return -Double.MAX_VALUE;
+                if(probability==1.0)
+                        return Double.MAX_VALUE;
+                if(probability==0.5)
+                        return mean;
+// To ensure numerical stability we need to rescale the distribution
+                double meanSave=mean,varSave=variance;
+                double pdfDSave=pdfDenominator,cdfDSave=cdfDenominator;
+                mean=0.0;
+                variance=1.0;
+                pdfDenominator=Math.sqrt(TWO_PI);
+                cdfDenominator=SQRT2;
+                double X=findRoot(probability, 0.0, -100.0, 100.0);
+// Scale back
+                mean=meanSave;
+                variance=varSave;
+                pdfDenominator=pdfDSave;
+                cdfDenominator=cdfDSave;
+                return X*Math.sqrt(variance)+mean;
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/OutOfRangeException.java b/LibrarySource/JSci/maths/statistics/OutOfRangeException.java
new file mode 100644
index 0000000..c182b43
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/OutOfRangeException.java
@@ -0,0 +1,22 @@
+package JSci.maths.statistics; 
+
+/**
+* This exception occurs if an argument in a statistics function is out-of-range.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public class OutOfRangeException extends IllegalArgumentException {
+        /**
+        * Constructs an OutOfRangeException with no detail message.
+        */
+        public OutOfRangeException() {
+        }
+        /**
+        * Constructs an OutOfRangeException with the specified detail message.
+        */
+        public OutOfRangeException(String s) {
+                super(s);
+        }
+}
+	
+
diff --git a/LibrarySource/JSci/maths/statistics/ParetoDistribution.java b/LibrarySource/JSci/maths/statistics/ParetoDistribution.java
new file mode 100644
index 0000000..d13537a
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/ParetoDistribution.java
@@ -0,0 +1,78 @@
+package JSci.maths.statistics;
+
+/**
+* The ParetoDistribution class provides an object for encapsulating Pareto distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class ParetoDistribution extends ProbabilityDistribution {
+        private double shape;
+        private double scale;
+
+        /**
+        * Constructs a Pareto distribution.
+        * @param sh the shape.
+        * @param sc the scale.
+        */
+        public ParetoDistribution(double sh,double sc) {
+                if(sh<0.0)
+                        throw new OutOfRangeException("The shape parameter should be positive.");
+                shape=sh;
+                if(sc<0.0)
+                        throw new OutOfRangeException("The scale paremeter should be positive.");
+                scale=sc;
+        }
+        /**
+        * Returns the shape parameter.
+        */
+        public double getShapeParameter() {
+                return shape;
+        }
+        /**
+        * Returns the scale parameter.
+        */
+        public double getScaleParameter() {
+                return scale;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return shape*scale/(shape-1.0);
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return shape*scale*scale/((shape-2.0)*(shape-1.0)*(shape-1.0));
+        }
+        /**
+        * Probability density function of a Pareto distribution.
+        * P(X) = (a/X) (s/X)<sup>a</sup>.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                if(X<scale)
+                        throw new OutOfRangeException("X should be greater than or equal to the scale.");
+                return shape*Math.pow(scale/X,shape)/X;
+        }
+        /**
+        * Cumulative Pareto distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                if(X<scale)
+                        throw new OutOfRangeException("X should be greater than or equal to the scale.");
+                return 1.0-Math.pow(scale/X,shape);
+        }
+        /**
+	* Inverse of the cumulative Pareto distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return scale/Math.pow(1.0-probability,1.0/shape);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/PoissonDistribution.java b/LibrarySource/JSci/maths/statistics/PoissonDistribution.java
new file mode 100644
index 0000000..5667091
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/PoissonDistribution.java
@@ -0,0 +1,72 @@
+package JSci.maths.statistics;
+
+import JSci.maths.ExtraMath;
+
+/**
+* The PoissonDistribution class provides an object for encapsulating Poisson distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class PoissonDistribution extends ProbabilityDistribution {
+        private double lambda;
+
+        /**
+        * Constructs a Poisson distribution.
+        * @param interval the interval.
+        */
+        public PoissonDistribution(double interval) {
+                if(interval<=0.0)
+                        throw new OutOfRangeException("The interval should be (strictly) positive.");
+                lambda=interval;
+        }
+        /**
+        * Returns the interval parameter.
+        */
+        public double getIntervalParameter() {
+                return lambda;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return lambda;
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return lambda;
+        }
+        /**
+        * Probability density function of a Poisson distribution.
+        * P(X) = <img border=0 alt="lambda" src="../doc-files/lambda.gif"><sup>X</sup>e<sup>-<img border=0 alt="lambda" src="../doc-files/lambda.gif"></sup>/X!.
+        * @param X should be integer-valued.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return Math.exp(X*Math.log(lambda)-lambda-ExtraMath.logFactorial(X));
+        }
+        /**
+        * Cumulative Poisson distribution function.
+        * @param X should be integer-valued.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                double sum=0.0;
+                for(double i=0.0;i<=X;i++)
+                        sum+=probability(i);
+                return sum;
+        }
+        /**
+	* Inverse of the cumulative Poisson distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return Math.floor(findRoot(probability,lambda,0.0,Double.MAX_VALUE));
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/ProbabilityDistribution.java b/LibrarySource/JSci/maths/statistics/ProbabilityDistribution.java
new file mode 100644
index 0000000..ddfed4e
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/ProbabilityDistribution.java
@@ -0,0 +1,81 @@
+package JSci.maths.statistics;
+
+/**
+* The ProbabilityDistribution superclass provides an object for encapsulating probability distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public abstract class ProbabilityDistribution extends Object {
+        /**
+        * Constructs a probability distribution.
+        */
+        public ProbabilityDistribution() {}
+        /**
+        * Probability density function.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public abstract double probability(double X);
+        /**
+        * Cumulative distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public abstract double cumulative(double X);
+        /**
+	* Inverse of the cumulative distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public abstract double inverse(double probability);
+        /**
+	* Check if the range of the argument of the distribution method is between lo and hi.
+        */
+        protected void checkRange(double x, double lo, double hi) {
+                if(x<lo || x>hi)
+                        throw new OutOfRangeException("The argument of the distribution method should be between "+lo+" and "+hi+".");
+        }
+        /**
+	* Check if the range of the argument of the distribution method is between 0 and 1.
+        */
+        protected void checkRange(double x) {
+        	if(x<0.0 || x>1.0)
+        		throw new OutOfRangeException("The argument of the distribution method should be between 0 and 1.");
+        }
+        /**
+        * This method approximates the value of X for which P(x<X)=<I>prob</I>.
+        * It applies a combination of a Newton-Raphson procedure and bisection method
+        * with the value <I>guess</I> as a starting point. Furthermore, to ensure convergency
+        * and stability, one should supply an inverval [<I>xLo</I>,<I>xHi</I>] in which the probalility
+        * distribution reaches the value <I>prob</I>. The method does no checking, it will produce
+        * bad results if wrong values for the parameters are supplied - use it with care.
+        */
+        protected double findRoot(double prob,double guess,double xLo,double xHi) {
+                final double accuracy=1.0e-10;
+                final int maxIteration=150;
+                double x=guess,xNew=guess;
+                double error,pdf,dx=1000.0;
+                int i=0;
+                while(Math.abs(dx)>accuracy && i++<maxIteration) {
+// Apply Newton-Raphson step
+                        error=cumulative(x)-prob;
+                        if(error<0.0)
+                                xLo=x;
+                        else
+                                xHi=x;
+                        pdf=probability(x);
+                        if(pdf!=0.0) {          // Avoid division by zero
+                                dx=error/pdf;
+                                xNew=x-dx;
+                        }
+// If the NR fails to converge (which for example may be the
+// case if the initial guess is to rough) we apply a bisection
+// step to determine a more narrow interval around the root.
+                        if(xNew<xLo || xNew>xHi || pdf==0.0) {
+                                xNew=(xLo+xHi)/2.0;
+                                dx=xNew-x;
+                        }
+                        x=xNew;
+                }
+                return x;
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/TDistribution.java b/LibrarySource/JSci/maths/statistics/TDistribution.java
new file mode 100644
index 0000000..dbb7492
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/TDistribution.java
@@ -0,0 +1,63 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The TDistribution class provides an object for encapsulating student's t-distributions.
+* @version 1.0
+* @author Jaco van Kooten
+*/
+public final class TDistribution extends ProbabilityDistribution {
+        private int dgrFreedom;
+        private double logPdfFreedom;
+
+        /**
+        * Constructor for student's t-distribution.
+        * @param r degrees of freedom.
+        */
+        public TDistribution(int r) {
+                if(r<=0)
+                        throw new OutOfRangeException("The degrees of freedom must be greater than zero.");
+                dgrFreedom=r;
+                logPdfFreedom=-SpecialMath.logBeta(0.5*dgrFreedom,0.5)-0.5*Math.log(dgrFreedom);
+        }
+        /**
+        * Returns the degrees of freedom.
+        */
+        public int getDegreesOfFreedom() {
+                return dgrFreedom;
+        }
+        /**
+        * Probability density function of a student's t-distribution.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                double logPdf=logPdfFreedom;
+                logPdf-=(0.5*(dgrFreedom+1))*Math.log(1.0+(X*X)/dgrFreedom);
+                return Math.exp(logPdf);
+        }
+        /**
+        * Cumulative student's t-distribution function.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                double A=0.5*SpecialMath.incompleteBeta((dgrFreedom)/(dgrFreedom+X*X),0.5*dgrFreedom,0.5);
+                return X>0 ? 1-A : A;
+        }
+        /**
+	* Inverse of the cumulative student's t-distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                if(probability==0.0)
+                        return -Double.MAX_VALUE;
+                if(probability==1.0)
+                        return Double.MAX_VALUE;
+                if(probability==0.5)
+                        return 0.0;
+                return findRoot(probability, 0.0, -0.5*Double.MAX_VALUE, 0.5*Double.MAX_VALUE);
+        }
+}
+
+
diff --git a/LibrarySource/JSci/maths/statistics/WeibullDistribution.java b/LibrarySource/JSci/maths/statistics/WeibullDistribution.java
new file mode 100644
index 0000000..a13639b
--- /dev/null
+++ b/LibrarySource/JSci/maths/statistics/WeibullDistribution.java
@@ -0,0 +1,70 @@
+package JSci.maths.statistics;
+
+import JSci.maths.SpecialMath;
+
+/**
+* The WeibullDistribution class provides an object for encapsulating Weibull distributions.
+* @version 0.2
+* @author Mark Hale
+*/
+public final class WeibullDistribution extends ProbabilityDistribution {
+        private double shape;
+
+        /**
+        * Constructs a Weibull distribution.
+        * @param sh the shape.
+        */
+        public WeibullDistribution(double sh) {
+                if(sh<=0.0)
+                        throw new OutOfRangeException("The shape parameter should be positive.");
+                shape=sh;
+        }
+        /**
+        * Returns the shape parameter.
+        */
+        public double getShapeParameter() {
+                return shape;
+        }
+        /**
+        * Returns the mean.
+        */
+        public double getMean() {
+                return SpecialMath.gamma(1.0+1.0/shape);
+        }
+        /**
+        * Returns the variance.
+        */
+        public double getVariance() {
+                return SpecialMath.gamma(1.0+2.0/shape)-getMean()*getMean();
+        }
+        /**
+        * Probability density function of a Weibull distribution.
+        * P(X) = s X<sup>s-1</sup> exp(-X<sup>s</sup>).
+        * @param X should be integer-valued.
+        * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
+        */
+        public double probability(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                final double XpowShape=Math.pow(X,shape);
+                return shape*XpowShape/X*Math.exp(-XpowShape);
+        }
+        /**
+        * Cumulative Weibull distribution function.
+        * @param X should be integer-valued.
+	* @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
+        */
+        public double cumulative(double X) {
+                checkRange(X,0.0,Double.MAX_VALUE);
+                return 1.0-Math.exp(-Math.pow(X,shape));
+        }
+        /**
+	* Inverse of the cumulative Weibull distribution function.
+        * @return the value X for which P(x<X).
+        */
+        public double inverse(double probability) {
+                checkRange(probability);
+                return Math.pow(-Math.log(1.0-probability),1.0/shape);
+        }
+}
+
+
diff --git a/LibrarySource/Jama/CholeskyDecomposition.java b/LibrarySource/Jama/CholeskyDecomposition.java
new file mode 100644
index 0000000..058dc95
--- /dev/null
+++ b/LibrarySource/Jama/CholeskyDecomposition.java
@@ -0,0 +1,199 @@
+package Jama;
+
+   /** Cholesky Decomposition.
+   <P>
+   For a symmetric, positive definite matrix A, the Cholesky decomposition
+   is an lower triangular matrix L so that A = L*L'.
+   <P>
+   If the matrix is not symmetric or positive definite, the constructor
+   returns a partial decomposition and sets an internal flag that may
+   be queried by the isSPD() method.
+   */
+
+public class CholeskyDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   private double[][] L;
+
+   /** Row and column dimension (square matrix).
+   @serial matrix dimension.
+   */
+   private int n;
+
+   /** Symmetric and positive definite flag.
+   @serial is symmetric and positive definite flag.
+   */
+   private boolean isspd;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** Cholesky algorithm for symmetric and positive definite matrix.
+   @param  A   Square, symmetric matrix.
+   @return     Structure to access L and isspd flag.
+   */
+
+   public CholeskyDecomposition (Matrix Arg) {
+      // Initialize.
+      double[][] A = Arg.getArray();
+      n = Arg.getRowDimension();
+      L = new double[n][n];
+      isspd = (Arg.getColumnDimension() == n);
+      // Main loop.
+      for (int j = 0; j < n; j++) {
+         double[] Lrowj = L[j];
+         double d = 0.0;
+         for (int k = 0; k < j; k++) {
+            double[] Lrowk = L[k];
+            double s = 0.0;
+            for (int i = 0; i < k; i++) {
+               s += Lrowk[i]*Lrowj[i];
+            }
+            Lrowj[k] = s = (A[j][k] - s)/L[k][k];
+            d = d + s*s;
+            isspd = isspd & (A[k][j] == A[j][k]); 
+         }
+         d = A[j][j] - d;
+         isspd = isspd & (d > 0.0);
+         L[j][j] = Math.sqrt(Math.max(d,0.0));
+         for (int k = j+1; k < n; k++) {
+            L[j][k] = 0.0;
+         }
+      }
+   }
+
+/* ------------------------
+   Temporary, experimental code.
+ * ------------------------ *\
+
+   \** Right Triangular Cholesky Decomposition.
+   <P>
+   For a symmetric, positive definite matrix A, the Right Cholesky
+   decomposition is an upper triangular matrix R so that A = R'*R.
+   This constructor computes R with the Fortran inspired column oriented
+   algorithm used in LINPACK and MATLAB.  In Java, we suspect a row oriented,
+   lower triangular decomposition is faster.  We have temporarily included
+   this constructor here until timing experiments confirm this suspicion.
+   *\
+
+   \** Array for internal storage of right triangular decomposition. **\
+   private transient double[][] R;
+
+   \** Cholesky algorithm for symmetric and positive definite matrix.
+   @param  A           Square, symmetric matrix.
+   @param  rightflag   Actual value ignored.
+   @return             Structure to access R and isspd flag.
+   *\
+
+   public CholeskyDecomposition (Matrix Arg, int rightflag) {
+      // Initialize.
+      double[][] A = Arg.getArray();
+      n = Arg.getColumnDimension();
+      R = new double[n][n];
+      isspd = (Arg.getColumnDimension() == n);
+      // Main loop.
+      for (int j = 0; j < n; j++) {
+         double d = 0.0;
+         for (int k = 0; k < j; k++) {
+            double s = A[k][j];
+            for (int i = 0; i < k; i++) {
+               s = s - R[i][k]*R[i][j];
+            }
+            R[k][j] = s = s/R[k][k];
+            d = d + s*s;
+            isspd = isspd & (A[k][j] == A[j][k]); 
+         }
+         d = A[j][j] - d;
+         isspd = isspd & (d > 0.0);
+         R[j][j] = Math.sqrt(Math.max(d,0.0));
+         for (int k = j+1; k < n; k++) {
+            R[k][j] = 0.0;
+         }
+      }
+   }
+
+   \** Return upper triangular factor.
+   @return     R
+   *\
+
+   public Matrix getR () {
+      return new Matrix(R,n,n);
+   }
+
+\* ------------------------
+   End of temporary code.
+ * ------------------------ */
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Is the matrix symmetric and positive definite?
+   @return     true if A is symmetric and positive definite.
+   */
+
+   public boolean isSPD () {
+      return isspd;
+   }
+
+   /** Return triangular factor.
+   @return     L
+   */
+
+   public Matrix getL () {
+      return new Matrix(L,n,n);
+   }
+
+   /** Solve A*X = B
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     X so that L*L'*X = B
+   @exception  IllegalArgumentException  Matrix row dimensions must agree.
+   @exception  RuntimeException  Matrix is not symmetric positive definite.
+   */
+
+   public Matrix solve (Matrix B) {
+      if (B.getRowDimension() != n) {
+         throw new IllegalArgumentException("Matrix row dimensions must agree.");
+      }
+      if (!isspd) {
+         throw new RuntimeException("Matrix is not symmetric positive definite.");
+      }
+
+      // Copy right hand side.
+      double[][] X = B.getArrayCopy();
+      int nx = B.getColumnDimension();
+
+      // Solve L*Y = B;
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*L[i][k];
+            }
+         }
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= L[k][k];
+         }
+      }
+
+      // Solve L'*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= L[k][k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*L[k][i];
+            }
+         }
+      }
+      return new Matrix(X,n,nx);
+   }
+}
+
diff --git a/LibrarySource/Jama/EigenvalueDecomposition.java b/LibrarySource/Jama/EigenvalueDecomposition.java
new file mode 100644
index 0000000..d711471
--- /dev/null
+++ b/LibrarySource/Jama/EigenvalueDecomposition.java
@@ -0,0 +1,956 @@
+package Jama;
+import Jama.util.*;
+
+/** Eigenvalues and eigenvectors of a real matrix. 
+<P>
+    If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
+    diagonal and the eigenvector matrix V is orthogonal.
+    I.e. A = V.times(D.times(V.transpose())) and 
+    V.times(V.transpose()) equals the identity matrix.
+<P>
+    If A is not symmetric, then the eigenvalue matrix D is block diagonal
+    with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
+    lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The
+    columns of V represent the eigenvectors in the sense that A*V = V*D,
+    i.e. A.times(V) equals V.times(D).  The matrix V may be badly
+    conditioned, or even singular, so the validity of the equation
+    A = V*D*inverse(V) depends upon V.cond().
+**/
+
+public class EigenvalueDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Row and column dimension (square matrix).
+   @serial matrix dimension.
+   */
+   private int n;
+
+   /** Symmetry flag.
+   @serial internal symmetry flag.
+   */
+   private boolean issymmetric;
+
+   /** Arrays for internal storage of eigenvalues.
+   @serial internal storage of eigenvalues.
+   */
+   private double[] d, e;
+
+   /** Array for internal storage of eigenvectors.
+   @serial internal storage of eigenvectors.
+   */
+   private double[][] V;
+
+   /** Array for internal storage of nonsymmetric Hessenberg form.
+   @serial internal storage of nonsymmetric Hessenberg form.
+   */
+   private double[][] H;
+
+   /** Working storage for nonsymmetric algorithm.
+   @serial working storage for nonsymmetric algorithm.
+   */
+   private double[] ort;
+
+/* ------------------------
+   Private Methods
+ * ------------------------ */
+
+   // Symmetric Householder reduction to tridiagonal form.
+
+   private void tred2 () {
+
+   //  This is derived from the Algol procedures tred2 by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+      }
+
+      // Householder reduction to tridiagonal form.
+   
+      for (int i = n-1; i > 0; i--) {
+   
+         // Scale to avoid under/overflow.
+   
+         double scale = 0.0;
+         double h = 0.0;
+         for (int k = 0; k < i; k++) {
+            scale = scale + Math.abs(d[k]);
+         }
+         if (scale == 0.0) {
+            e[i] = d[i-1];
+            for (int j = 0; j < i; j++) {
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+               V[j][i] = 0.0;
+            }
+         } else {
+   
+            // Generate Householder vector.
+   
+            for (int k = 0; k < i; k++) {
+               d[k] /= scale;
+               h += d[k] * d[k];
+            }
+            double f = d[i-1];
+            double g = Math.sqrt(h);
+            if (f > 0) {
+               g = -g;
+            }
+            e[i] = scale * g;
+            h = h - f * g;
+            d[i-1] = f - g;
+            for (int j = 0; j < i; j++) {
+               e[j] = 0.0;
+            }
+   
+            // Apply similarity transformation to remaining columns.
+   
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               V[j][i] = f;
+               g = e[j] + V[j][j] * f;
+               for (int k = j+1; k <= i-1; k++) {
+                  g += V[k][j] * d[k];
+                  e[k] += V[k][j] * f;
+               }
+               e[j] = g;
+            }
+            f = 0.0;
+            for (int j = 0; j < i; j++) {
+               e[j] /= h;
+               f += e[j] * d[j];
+            }
+            double hh = f / (h + h);
+            for (int j = 0; j < i; j++) {
+               e[j] -= hh * d[j];
+            }
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               g = e[j];
+               for (int k = j; k <= i-1; k++) {
+                  V[k][j] -= (f * e[k] + g * d[k]);
+               }
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+            }
+         }
+         d[i] = h;
+      }
+   
+      // Accumulate transformations.
+   
+      for (int i = 0; i < n-1; i++) {
+         V[n-1][i] = V[i][i];
+         V[i][i] = 1.0;
+         double h = d[i+1];
+         if (h != 0.0) {
+            for (int k = 0; k <= i; k++) {
+               d[k] = V[k][i+1] / h;
+            }
+            for (int j = 0; j <= i; j++) {
+               double g = 0.0;
+               for (int k = 0; k <= i; k++) {
+                  g += V[k][i+1] * V[k][j];
+               }
+               for (int k = 0; k <= i; k++) {
+                  V[k][j] -= g * d[k];
+               }
+            }
+         }
+         for (int k = 0; k <= i; k++) {
+            V[k][i+1] = 0.0;
+         }
+      }
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+         V[n-1][j] = 0.0;
+      }
+      V[n-1][n-1] = 1.0;
+      e[0] = 0.0;
+   } 
+
+   // Symmetric tridiagonal QL algorithm.
+   
+   private void tql2 () {
+
+   //  This is derived from the Algol procedures tql2, by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+   
+      for (int i = 1; i < n; i++) {
+         e[i-1] = e[i];
+      }
+      e[n-1] = 0.0;
+   
+      double f = 0.0;
+      double tst1 = 0.0;
+      double eps = Math.pow(2.0,-52.0);
+      for (int l = 0; l < n; l++) {
+
+         // Find small subdiagonal element
+   
+         tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
+         int m = l;
+         while (m < n) {
+            if (Math.abs(e[m]) <= eps*tst1) {
+               break;
+            }
+            m++;
+         }
+   
+         // If m == l, d[l] is an eigenvalue,
+         // otherwise, iterate.
+   
+         if (m > l) {
+            int iter = 0;
+            do {
+               iter = iter + 1;  // (Could check iteration count here.)
+   
+               // Compute implicit shift
+   
+               double g = d[l];
+               double p = (d[l+1] - g) / (2.0 * e[l]);
+               double r = Maths.hypot(p,1.0);
+               if (p < 0) {
+                  r = -r;
+               }
+               d[l] = e[l] / (p + r);
+               d[l+1] = e[l] * (p + r);
+               double dl1 = d[l+1];
+               double h = g - d[l];
+               for (int i = l+2; i < n; i++) {
+                  d[i] -= h;
+               }
+               f = f + h;
+   
+               // Implicit QL transformation.
+   
+               p = d[m];
+               double c = 1.0;
+               double c2 = c;
+               double c3 = c;
+               double el1 = e[l+1];
+               double s = 0.0;
+               double s2 = 0.0;
+               for (int i = m-1; i >= l; i--) {
+                  c3 = c2;
+                  c2 = c;
+                  s2 = s;
+                  g = c * e[i];
+                  h = c * p;
+                  r = Maths.hypot(p,e[i]);
+                  e[i+1] = s * r;
+                  s = e[i] / r;
+                  c = p / r;
+                  p = c * d[i] - s * g;
+                  d[i+1] = h + s * (c * g + s * d[i]);
+   
+                  // Accumulate transformation.
+   
+                  for (int k = 0; k < n; k++) {
+                     h = V[k][i+1];
+                     V[k][i+1] = s * V[k][i] + c * h;
+                     V[k][i] = c * V[k][i] - s * h;
+                  }
+               }
+               p = -s * s2 * c3 * el1 * e[l] / dl1;
+               e[l] = s * p;
+               d[l] = c * p;
+   
+               // Check for convergence.
+   
+            } while (Math.abs(e[l]) > eps*tst1);
+         }
+         d[l] = d[l] + f;
+         e[l] = 0.0;
+      }
+     
+      // Sort eigenvalues and corresponding vectors.
+   
+      for (int i = 0; i < n-1; i++) {
+         int k = i;
+         double p = d[i];
+         for (int j = i+1; j < n; j++) {
+            if (d[j] < p) {
+               k = j;
+               p = d[j];
+            }
+         }
+         if (k != i) {
+            d[k] = d[i];
+            d[i] = p;
+            for (int j = 0; j < n; j++) {
+               p = V[j][i];
+               V[j][i] = V[j][k];
+               V[j][k] = p;
+            }
+         }
+      }
+   }
+
+   // Nonsymmetric reduction to Hessenberg form.
+
+   private void orthes () {
+   
+      //  This is derived from the Algol procedures orthes and ortran,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutines in EISPACK.
+   
+      int low = 0;
+      int high = n-1;
+   
+      for (int m = low+1; m <= high-1; m++) {
+   
+         // Scale column.
+   
+         double scale = 0.0;
+         for (int i = m; i <= high; i++) {
+            scale = scale + Math.abs(H[i][m-1]);
+         }
+         if (scale != 0.0) {
+   
+            // Compute Householder transformation.
+   
+            double h = 0.0;
+            for (int i = high; i >= m; i--) {
+               ort[i] = H[i][m-1]/scale;
+               h += ort[i] * ort[i];
+            }
+            double g = Math.sqrt(h);
+            if (ort[m] > 0) {
+               g = -g;
+            }
+            h = h - ort[m] * g;
+            ort[m] = ort[m] - g;
+   
+            // Apply Householder similarity transformation
+            // H = (I-u*u'/h)*H*(I-u*u')/h)
+   
+            for (int j = m; j < n; j++) {
+               double f = 0.0;
+               for (int i = high; i >= m; i--) {
+                  f += ort[i]*H[i][j];
+               }
+               f = f/h;
+               for (int i = m; i <= high; i++) {
+                  H[i][j] -= f*ort[i];
+               }
+           }
+   
+           for (int i = 0; i <= high; i++) {
+               double f = 0.0;
+               for (int j = high; j >= m; j--) {
+                  f += ort[j]*H[i][j];
+               }
+               f = f/h;
+               for (int j = m; j <= high; j++) {
+                  H[i][j] -= f*ort[j];
+               }
+            }
+            ort[m] = scale*ort[m];
+            H[m][m-1] = scale*g;
+         }
+      }
+   
+      // Accumulate transformations (Algol's ortran).
+
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            V[i][j] = (i == j ? 1.0 : 0.0);
+         }
+      }
+
+      for (int m = high-1; m >= low+1; m--) {
+         if (H[m][m-1] != 0.0) {
+            for (int i = m+1; i <= high; i++) {
+               ort[i] = H[i][m-1];
+            }
+            for (int j = m; j <= high; j++) {
+               double g = 0.0;
+               for (int i = m; i <= high; i++) {
+                  g += ort[i] * V[i][j];
+               }
+               // Double division avoids possible underflow
+               g = (g / ort[m]) / H[m][m-1];
+               for (int i = m; i <= high; i++) {
+                  V[i][j] += g * ort[i];
+               }
+            }
+         }
+      }
+   }
+
+
+   // Complex scalar division.
+
+   private transient double cdivr, cdivi;
+   private void cdiv(double xr, double xi, double yr, double yi) {
+      double r,d;
+      if (Math.abs(yr) > Math.abs(yi)) {
+         r = yi/yr;
+         d = yr + r*yi;
+         cdivr = (xr + r*xi)/d;
+         cdivi = (xi - r*xr)/d;
+      } else {
+         r = yr/yi;
+         d = yi + r*yr;
+         cdivr = (r*xr + xi)/d;
+         cdivi = (r*xi - xr)/d;
+      }
+   }
+
+
+   // Nonsymmetric reduction from Hessenberg to real Schur form.
+
+   private void hqr2 () {
+   
+      //  This is derived from the Algol procedure hqr2,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutine in EISPACK.
+   
+      // Initialize
+   
+      int nn = this.n;
+      int n = nn-1;
+      int low = 0;
+      int high = nn-1;
+      double eps = Math.pow(2.0,-52.0);
+      double exshift = 0.0;
+      double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+   
+      // Store roots isolated by balanc and compute matrix norm
+   
+      double norm = 0.0;
+      for (int i = 0; i < nn; i++) {
+         if (i < low | i > high) {
+            d[i] = H[i][i];
+            e[i] = 0.0;
+         }
+         for (int j = Math.max(i-1,0); j < nn; j++) {
+            norm = norm + Math.abs(H[i][j]);
+         }
+      }
+   
+      // Outer loop over eigenvalue index
+   
+      int iter = 0;
+      while (n >= low) {
+   
+         // Look for single small sub-diagonal element
+   
+         int l = n;
+         while (l > low) {
+            s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);
+            if (s == 0.0) {
+               s = norm;
+            }
+            if (Math.abs(H[l][l-1]) < eps * s) {
+               break;
+            }
+            l--;
+         }
+       
+         // Check for convergence
+         // One root found
+   
+         if (l == n) {
+            H[n][n] = H[n][n] + exshift;
+            d[n] = H[n][n];
+            e[n] = 0.0;
+            n--;
+            iter = 0;
+   
+         // Two roots found
+   
+         } else if (l == n-1) {
+            w = H[n][n-1] * H[n-1][n];
+            p = (H[n-1][n-1] - H[n][n]) / 2.0;
+            q = p * p + w;
+            z = Math.sqrt(Math.abs(q));
+            H[n][n] = H[n][n] + exshift;
+            H[n-1][n-1] = H[n-1][n-1] + exshift;
+            x = H[n][n];
+   
+            // Real pair
+   
+            if (q >= 0) {
+               if (p >= 0) {
+                  z = p + z;
+               } else {
+                  z = p - z;
+               }
+               d[n-1] = x + z;
+               d[n] = d[n-1];
+               if (z != 0.0) {
+                  d[n] = x - w / z;
+               }
+               e[n-1] = 0.0;
+               e[n] = 0.0;
+               x = H[n][n-1];
+               s = Math.abs(x) + Math.abs(z);
+               p = x / s;
+               q = z / s;
+               r = Math.sqrt(p * p+q * q);
+               p = p / r;
+               q = q / r;
+   
+               // Row modification
+   
+               for (int j = n-1; j < nn; j++) {
+                  z = H[n-1][j];
+                  H[n-1][j] = q * z + p * H[n][j];
+                  H[n][j] = q * H[n][j] - p * z;
+               }
+   
+               // Column modification
+   
+               for (int i = 0; i <= n; i++) {
+                  z = H[i][n-1];
+                  H[i][n-1] = q * z + p * H[i][n];
+                  H[i][n] = q * H[i][n] - p * z;
+               }
+   
+               // Accumulate transformations
+   
+               for (int i = low; i <= high; i++) {
+                  z = V[i][n-1];
+                  V[i][n-1] = q * z + p * V[i][n];
+                  V[i][n] = q * V[i][n] - p * z;
+               }
+   
+            // Complex pair
+   
+            } else {
+               d[n-1] = x + p;
+               d[n] = x + p;
+               e[n-1] = z;
+               e[n] = -z;
+            }
+            n = n - 2;
+            iter = 0;
+   
+         // No convergence yet
+   
+         } else {
+   
+            // Form shift
+   
+            x = H[n][n];
+            y = 0.0;
+            w = 0.0;
+            if (l < n) {
+               y = H[n-1][n-1];
+               w = H[n][n-1] * H[n-1][n];
+            }
+   
+            // Wilkinson's original ad hoc shift
+   
+            if (iter == 10) {
+               exshift += x;
+               for (int i = low; i <= n; i++) {
+                  H[i][i] -= x;
+               }
+               s = Math.abs(H[n][n-1]) + Math.abs(H[n-1][n-2]);
+               x = y = 0.75 * s;
+               w = -0.4375 * s * s;
+            }
+
+            // MATLAB's new ad hoc shift
+
+            if (iter == 30) {
+                s = (y - x) / 2.0;
+                s = s * s + w;
+                if (s > 0) {
+                    s = Math.sqrt(s);
+                    if (y < x) {
+                       s = -s;
+                    }
+                    s = x - w / ((y - x) / 2.0 + s);
+                    for (int i = low; i <= n; i++) {
+                       H[i][i] -= s;
+                    }
+                    exshift += s;
+                    x = y = w = 0.964;
+                }
+            }
+   
+            iter = iter + 1;   // (Could check iteration count here.)
+   
+            // Look for two consecutive small sub-diagonal elements
+   
+            int m = n-2;
+            while (m >= l) {
+               z = H[m][m];
+               r = x - z;
+               s = y - z;
+               p = (r * s - w) / H[m+1][m] + H[m][m+1];
+               q = H[m+1][m+1] - z - r - s;
+               r = H[m+2][m+1];
+               s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+               p = p / s;
+               q = q / s;
+               r = r / s;
+               if (m == l) {
+                  break;
+               }
+               if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
+                  eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
+                  Math.abs(H[m+1][m+1])))) {
+                     break;
+               }
+               m--;
+            }
+   
+            for (int i = m+2; i <= n; i++) {
+               H[i][i-2] = 0.0;
+               if (i > m+2) {
+                  H[i][i-3] = 0.0;
+               }
+            }
+   
+            // Double QR step involving rows l:n and columns m:n
+   
+            for (int k = m; k <= n-1; k++) {
+               boolean notlast = (k != n-1);
+               if (k != m) {
+                  p = H[k][k-1];
+                  q = H[k+1][k-1];
+                  r = (notlast ? H[k+2][k-1] : 0.0);
+                  x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+                  if (x != 0.0) {
+                     p = p / x;
+                     q = q / x;
+                     r = r / x;
+                  }
+               }
+               if (x == 0.0) {
+                  break;
+               }
+               s = Math.sqrt(p * p + q * q + r * r);
+               if (p < 0) {
+                  s = -s;
+               }
+               if (s != 0) {
+                  if (k != m) {
+                     H[k][k-1] = -s * x;
+                  } else if (l != m) {
+                     H[k][k-1] = -H[k][k-1];
+                  }
+                  p = p + s;
+                  x = p / s;
+                  y = q / s;
+                  z = r / s;
+                  q = q / p;
+                  r = r / p;
+   
+                  // Row modification
+   
+                  for (int j = k; j < nn; j++) {
+                     p = H[k][j] + q * H[k+1][j];
+                     if (notlast) {
+                        p = p + r * H[k+2][j];
+                        H[k+2][j] = H[k+2][j] - p * z;
+                     }
+                     H[k][j] = H[k][j] - p * x;
+                     H[k+1][j] = H[k+1][j] - p * y;
+                  }
+   
+                  // Column modification
+   
+                  for (int i = 0; i <= Math.min(n,k+3); i++) {
+                     p = x * H[i][k] + y * H[i][k+1];
+                     if (notlast) {
+                        p = p + z * H[i][k+2];
+                        H[i][k+2] = H[i][k+2] - p * r;
+                     }
+                     H[i][k] = H[i][k] - p;
+                     H[i][k+1] = H[i][k+1] - p * q;
+                  }
+   
+                  // Accumulate transformations
+   
+                  for (int i = low; i <= high; i++) {
+                     p = x * V[i][k] + y * V[i][k+1];
+                     if (notlast) {
+                        p = p + z * V[i][k+2];
+                        V[i][k+2] = V[i][k+2] - p * r;
+                     }
+                     V[i][k] = V[i][k] - p;
+                     V[i][k+1] = V[i][k+1] - p * q;
+                  }
+               }  // (s != 0)
+            }  // k loop
+         }  // check convergence
+      }  // while (n >= low)
+      
+      // Backsubstitute to find vectors of upper triangular form
+
+      if (norm == 0.0) {
+         return;
+      }
+   
+      for (n = nn-1; n >= 0; n--) {
+         p = d[n];
+         q = e[n];
+   
+         // Real vector
+   
+         if (q == 0) {
+            int l = n;
+            H[n][n] = 1.0;
+            for (int i = n-1; i >= 0; i--) {
+               w = H[i][i] - p;
+               r = 0.0;
+               for (int j = l; j <= n; j++) {
+                  r = r + H[i][j] * H[j][n];
+               }
+               if (e[i] < 0.0) {
+                  z = w;
+                  s = r;
+               } else {
+                  l = i;
+                  if (e[i] == 0.0) {
+                     if (w != 0.0) {
+                        H[i][n] = -r / w;
+                     } else {
+                        H[i][n] = -r / (eps * norm);
+                     }
+   
+                  // Solve real equations
+   
+                  } else {
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+                     t = (x * s - z * r) / q;
+                     H[i][n] = t;
+                     if (Math.abs(x) > Math.abs(z)) {
+                        H[i+1][n] = (-r - w * t) / x;
+                     } else {
+                        H[i+1][n] = (-s - y * t) / z;
+                     }
+                  }
+   
+                  // Overflow control
+   
+                  t = Math.abs(H[i][n]);
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+   
+         // Complex vector
+   
+         } else if (q < 0) {
+            int l = n-1;
+
+            // Last vector component imaginary so matrix is triangular
+   
+            if (Math.abs(H[n][n-1]) > Math.abs(H[n-1][n])) {
+               H[n-1][n-1] = q / H[n][n-1];
+               H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
+            } else {
+               cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
+               H[n-1][n-1] = cdivr;
+               H[n-1][n] = cdivi;
+            }
+            H[n][n-1] = 0.0;
+            H[n][n] = 1.0;
+            for (int i = n-2; i >= 0; i--) {
+               double ra,sa,vr,vi;
+               ra = 0.0;
+               sa = 0.0;
+               for (int j = l; j <= n; j++) {
+                  ra = ra + H[i][j] * H[j][n-1];
+                  sa = sa + H[i][j] * H[j][n];
+               }
+               w = H[i][i] - p;
+   
+               if (e[i] < 0.0) {
+                  z = w;
+                  r = ra;
+                  s = sa;
+               } else {
+                  l = i;
+                  if (e[i] == 0) {
+                     cdiv(-ra,-sa,w,q);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                  } else {
+   
+                     // Solve complex equations
+   
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+                     vi = (d[i] - p) * 2.0 * q;
+                     if (vr == 0.0 & vi == 0.0) {
+                        vr = eps * norm * (Math.abs(w) + Math.abs(q) +
+                        Math.abs(x) + Math.abs(y) + Math.abs(z));
+                     }
+                     cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                     if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
+                        H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
+                        H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
+                     } else {
+                        cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
+                        H[i+1][n-1] = cdivr;
+                        H[i+1][n] = cdivi;
+                     }
+                  }
+   
+                  // Overflow control
+
+                  t = Math.max(Math.abs(H[i][n-1]),Math.abs(H[i][n]));
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n-1] = H[j][n-1] / t;
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+         }
+      }
+   
+      // Vectors of isolated roots
+   
+      for (int i = 0; i < nn; i++) {
+         if (i < low | i > high) {
+            for (int j = i; j < nn; j++) {
+               V[i][j] = H[i][j];
+            }
+         }
+      }
+   
+      // Back transformation to get eigenvectors of original matrix
+   
+      for (int j = nn-1; j >= low; j--) {
+         for (int i = low; i <= high; i++) {
+            z = 0.0;
+            for (int k = low; k <= Math.min(j,high); k++) {
+               z = z + V[i][k] * H[k][j];
+            }
+            V[i][j] = z;
+         }
+      }
+   }
+
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** Check for symmetry, then construct the eigenvalue decomposition
+   @param A    Square matrix
+   @return     Structure to access D and V.
+   */
+
+   public EigenvalueDecomposition (Matrix Arg) {
+      double[][] A = Arg.getArray();
+      n = Arg.getColumnDimension();
+      V = new double[n][n];
+      d = new double[n];
+      e = new double[n];
+
+      issymmetric = true;
+      for (int j = 0; (j < n) & issymmetric; j++) {
+         for (int i = 0; (i < n) & issymmetric; i++) {
+            issymmetric = (A[i][j] == A[j][i]);
+         }
+      }
+
+      if (issymmetric) {
+         for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+               V[i][j] = A[i][j];
+            }
+         }
+   
+         // Tridiagonalize.
+         tred2();
+   
+         // Diagonalize.
+         tql2();
+
+      } else {
+         H = new double[n][n];
+         ort = new double[n];
+         
+         for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+               H[i][j] = A[i][j];
+            }
+         }
+   
+         // Reduce to Hessenberg form.
+         orthes();
+   
+         // Reduce Hessenberg to real Schur form.
+         hqr2();
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Return the eigenvector matrix
+   @return     V
+   */
+
+   public Matrix getV () {
+      return new Matrix(V,n,n);
+   }
+
+   /** Return the real parts of the eigenvalues
+   @return     real(diag(D))
+   */
+
+   public double[] getRealEigenvalues () {
+      return d;
+   }
+
+   /** Return the imaginary parts of the eigenvalues
+   @return     imag(diag(D))
+   */
+
+   public double[] getImagEigenvalues () {
+      return e;
+   }
+
+   /** Return the block diagonal eigenvalue matrix
+   @return     D
+   */
+
+   public Matrix getD () {
+      Matrix X = new Matrix(n,n);
+      double[][] D = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            D[i][j] = 0.0;
+         }
+         D[i][i] = d[i];
+         if (e[i] > 0) {
+            D[i][i+1] = e[i];
+         } else if (e[i] < 0) {
+            D[i][i-1] = e[i];
+         }
+      }
+      return X;
+   }
+}
+
diff --git a/LibrarySource/Jama/LUDecomposition.java b/LibrarySource/Jama/LUDecomposition.java
new file mode 100644
index 0000000..113eba1
--- /dev/null
+++ b/LibrarySource/Jama/LUDecomposition.java
@@ -0,0 +1,312 @@
+package Jama;
+
+   /** LU Decomposition.
+   <P>
+   For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
+   unit lower triangular matrix L, an n-by-n upper triangular matrix U,
+   and a permutation vector piv of length m so that A(piv,:) = L*U.
+   If m < n, then L is m-by-m and U is m-by-n.
+   <P>
+   The LU decompostion with pivoting always exists, even if the matrix is
+   singular, so the constructor will never fail.  The primary use of the
+   LU decomposition is in the solution of square systems of simultaneous
+   linear equations.  This will fail if isNonsingular() returns false.
+   */
+
+public class LUDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   private double[][] LU;
+
+   /** Row and column dimensions, and pivot sign.
+   @serial column dimension.
+   @serial row dimension.
+   @serial pivot sign.
+   */
+   private int m, n, pivsign; 
+
+   /** Internal storage of pivot vector.
+   @serial pivot vector.
+   */
+   private int[] piv;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** LU Decomposition
+   @param  A   Rectangular matrix
+   @return     Structure to access L, U and piv.
+   */
+
+   public LUDecomposition (Matrix A) {
+
+   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
+
+      LU = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      piv = new int[m];
+      for (int i = 0; i < m; i++) {
+         piv[i] = i;
+      }
+      pivsign = 1;
+      double[] LUrowi;
+      double[] LUcolj = new double[m];
+
+      // Outer loop.
+
+      for (int j = 0; j < n; j++) {
+
+         // Make a copy of the j-th column to localize references.
+
+         for (int i = 0; i < m; i++) {
+            LUcolj[i] = LU[i][j];
+         }
+
+         // Apply previous transformations.
+
+         for (int i = 0; i < m; i++) {
+            LUrowi = LU[i];
+
+            // Most of the time is spent in the following dot product.
+
+            int kmax = Math.min(i,j);
+            double s = 0.0;
+            for (int k = 0; k < kmax; k++) {
+               s += LUrowi[k]*LUcolj[k];
+            }
+
+            LUrowi[j] = LUcolj[i] -= s;
+         }
+   
+         // Find pivot and exchange if necessary.
+
+         int p = j;
+         for (int i = j+1; i < m; i++) {
+            if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
+               p = i;
+            }
+         }
+         if (p != j) {
+            for (int k = 0; k < n; k++) {
+               double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t;
+            }
+            int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
+            pivsign = -pivsign;
+         }
+
+         // Compute multipliers.
+         
+         if (j < m & LU[j][j] != 0.0) {
+            for (int i = j+1; i < m; i++) {
+               LU[i][j] /= LU[j][j];
+            }
+         }
+      }
+   }
+
+/* ------------------------
+   Temporary, experimental code.
+   ------------------------ *\
+
+   \** LU Decomposition, computed by Gaussian elimination.
+   <P>
+   This constructor computes L and U with the "daxpy"-based elimination
+   algorithm used in LINPACK and MATLAB.  In Java, we suspect the dot-product,
+   Crout algorithm will be faster.  We have temporarily included this
+   constructor until timing experiments confirm this suspicion.
+   <P>
+   @param  A             Rectangular matrix
+   @param  linpackflag   Use Gaussian elimination.  Actual value ignored.
+   @return               Structure to access L, U and piv.
+   *\
+
+   public LUDecomposition (Matrix A, int linpackflag) {
+      // Initialize.
+      LU = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      piv = new int[m];
+      for (int i = 0; i < m; i++) {
+         piv[i] = i;
+      }
+      pivsign = 1;
+      // Main loop.
+      for (int k = 0; k < n; k++) {
+         // Find pivot.
+         int p = k;
+         for (int i = k+1; i < m; i++) {
+            if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
+               p = i;
+            }
+         }
+         // Exchange if necessary.
+         if (p != k) {
+            for (int j = 0; j < n; j++) {
+               double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
+            }
+            int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
+            pivsign = -pivsign;
+         }
+         // Compute multipliers and eliminate k-th column.
+         if (LU[k][k] != 0.0) {
+            for (int i = k+1; i < m; i++) {
+               LU[i][k] /= LU[k][k];
+               for (int j = k+1; j < n; j++) {
+                  LU[i][j] -= LU[i][k]*LU[k][j];
+               }
+            }
+         }
+      }
+   }
+
+\* ------------------------
+   End of temporary code.
+ * ------------------------ */
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Is the matrix nonsingular?
+   @return     true if U, and hence A, is nonsingular.
+   */
+
+   public boolean isNonsingular () {
+      for (int j = 0; j < n; j++) {
+         if (LU[j][j] == 0)
+            return false;
+      }
+      return true;
+   }
+
+   /** Return lower triangular factor
+   @return     L
+   */
+
+   public Matrix getL () {
+      Matrix X = new Matrix(m,n);
+      double[][] L = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i > j) {
+               L[i][j] = LU[i][j];
+            } else if (i == j) {
+               L[i][j] = 1.0;
+            } else {
+               L[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return upper triangular factor
+   @return     U
+   */
+
+   public Matrix getU () {
+      Matrix X = new Matrix(n,n);
+      double[][] U = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i <= j) {
+               U[i][j] = LU[i][j];
+            } else {
+               U[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return pivot permutation vector
+   @return     piv
+   */
+
+   public int[] getPivot () {
+      int[] p = new int[m];
+      for (int i = 0; i < m; i++) {
+         p[i] = piv[i];
+      }
+      return p;
+   }
+
+   /** Return pivot permutation vector as a one-dimensional double array
+   @return     (double) piv
+   */
+
+   public double[] getDoublePivot () {
+      double[] vals = new double[m];
+      for (int i = 0; i < m; i++) {
+         vals[i] = (double) piv[i];
+      }
+      return vals;
+   }
+
+   /** Determinant
+   @return     det(A)
+   @exception  IllegalArgumentException  Matrix must be square
+   */
+
+   public double det () {
+      if (m != n) {
+         throw new IllegalArgumentException("Matrix must be square.");
+      }
+      double d = (double) pivsign;
+      for (int j = 0; j < n; j++) {
+         d *= LU[j][j];
+      }
+      return d;
+   }
+
+   /** Solve A*X = B
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     X so that L*U*X = B(piv,:)
+   @exception  IllegalArgumentException Matrix row dimensions must agree.
+   @exception  RuntimeException  Matrix is singular.
+   */
+
+   public Matrix solve (Matrix B) {
+      if (B.getRowDimension() != m) {
+         throw new IllegalArgumentException("Matrix row dimensions must agree.");
+      }
+      if (!this.isNonsingular()) {
+         throw new RuntimeException("Matrix is singular.");
+      }
+
+      // Copy right hand side with pivoting
+      int nx = B.getColumnDimension();
+      Matrix Xmat = B.getMatrix(piv,0,nx-1);
+      double[][] X = Xmat.getArray();
+
+      // Solve L*Y = B(piv,:)
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU[i][k];
+            }
+         }
+      }
+      // Solve U*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= LU[k][k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU[i][k];
+            }
+         }
+      }
+      return Xmat;
+   }
+}
+
diff --git a/LibrarySource/Jama/Matrix.java b/LibrarySource/Jama/Matrix.java
new file mode 100644
index 0000000..0b82a88
--- /dev/null
+++ b/LibrarySource/Jama/Matrix.java
@@ -0,0 +1,1046 @@
+package Jama;
+
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+import java.text.FieldPosition;
+import java.io.PrintWriter;
+import java.io.BufferedReader;
+import java.io.StreamTokenizer;
+import Jama.util.*;
+
+/**
+   Jama = Java Matrix class.
+<P>
+   The Java Matrix Class provides the fundamental operations of numerical
+   linear algebra.  Various constructors create Matrices from two dimensional
+   arrays of double precision floating point numbers.  Various "gets" and
+   "sets" provide access to submatrices and matrix elements.  Several methods 
+   implement basic matrix arithmetic, including matrix addition and
+   multiplication, matrix norms, and element-by-element array operations.
+   Methods for reading and printing matrices are also included.  All the
+   operations in this version of the Matrix Class involve real matrices.
+   Complex matrices may be handled in a future version.
+<P>
+   Five fundamental matrix decompositions, which consist of pairs or triples
+   of matrices, permutation vectors, and the like, produce results in five
+   decomposition classes.  These decompositions are accessed by the Matrix
+   class to compute solutions of simultaneous linear equations, determinants,
+   inverses and other matrix functions.  The five decompositions are:
+<P><UL>
+   <LI>Cholesky Decomposition of symmetric, positive definite matrices.
+   <LI>LU Decomposition of rectangular matrices.
+   <LI>QR Decomposition of rectangular matrices.
+   <LI>Singular Value Decomposition of rectangular matrices.
+   <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square matrices.
+</UL>
+<DL>
+<DT><B>Example of use:</B></DT>
+<P>
+<DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||.
+<P><PRE>
+      double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
+      Matrix A = new Matrix(vals);
+      Matrix b = Matrix.random(3,1);
+      Matrix x = A.solve(b);
+      Matrix r = A.times(x).minus(b);
+      double rnorm = r.normInf();
+</PRE></DD>
+</DL>
+
+ at author The MathWorks, Inc. and the National Institute of Standards and Technology.
+ at version 5 August 1998
+*/
+
+public class Matrix implements Cloneable, java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of elements.
+   @serial internal array storage.
+   */
+   private double[][] A;
+
+   /** Row and column dimensions.
+   @serial row dimension.
+   @serial column dimension.
+   */
+   private int m, n;
+
+/* ------------------------
+   Constructors
+ * ------------------------ */
+
+   /** Construct an m-by-n matrix of zeros. 
+   @param m    Number of rows.
+   @param n    Number of colums.
+   */
+
+   public Matrix (int m, int n) {
+      this.m = m;
+      this.n = n;
+      A = new double[m][n];
+   }
+
+   /** Construct an m-by-n constant matrix.
+   @param m    Number of rows.
+   @param n    Number of colums.
+   @param s    Fill the matrix with this scalar value.
+   */
+
+   public Matrix (int m, int n, double s) {
+      this.m = m;
+      this.n = n;
+      A = new double[m][n];
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = s;
+         }
+      }
+   }
+
+   /** Construct a matrix from a 2-D array.
+   @param A    Two-dimensional array of doubles.
+   @exception  IllegalArgumentException All rows must have the same length
+   @see        #constructWithCopy
+   */
+
+   public Matrix (double[][] A) {
+      m = A.length;
+      n = A[0].length;
+      for (int i = 0; i < m; i++) {
+         if (A[i].length != n) {
+            throw new IllegalArgumentException("All rows must have the same length.");
+         }
+      }
+      this.A = A;
+   }
+
+   /** Construct a matrix quickly without checking arguments.
+   @param A    Two-dimensional array of doubles.
+   @param m    Number of rows.
+   @param n    Number of colums.
+   */
+
+   public Matrix (double[][] A, int m, int n) {
+      this.A = A;
+      this.m = m;
+      this.n = n;
+   }
+
+   /** Construct a matrix from a one-dimensional packed array
+   @param vals One-dimensional array of doubles, packed by columns (ala Fortran).
+   @param m    Number of rows.
+   @exception  IllegalArgumentException Array length must be a multiple of m.
+   */
+
+   public Matrix (double vals[], int m) {
+      this.m = m;
+      n = (m != 0 ? vals.length/m : 0);
+      if (m*n != vals.length) {
+         throw new IllegalArgumentException("Array length must be a multiple of m.");
+      }
+      A = new double[m][n];
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = vals[i+j*m];
+         }
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Construct a matrix from a copy of a 2-D array.
+   @param A    Two-dimensional array of doubles.
+   @exception  IllegalArgumentException All rows must have the same length
+   */
+
+   public static Matrix constructWithCopy(double[][] A) {
+      int m = A.length;
+      int n = A[0].length;
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         if (A[i].length != n) {
+            throw new IllegalArgumentException
+               ("All rows must have the same length.");
+         }
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Make a deep copy of a matrix
+   */
+
+   public Matrix copy () {
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Clone the Matrix object.
+   */
+
+   public Object clone () {
+      return this.copy();
+   }
+
+   /** Access the internal two-dimensional array.
+   @return     Pointer to the two-dimensional array of matrix elements.
+   */
+
+   public double[][] getArray () {
+      return A;
+   }
+
+   /** Copy the internal two-dimensional array.
+   @return     Two-dimensional array copy of matrix elements.
+   */
+
+   public double[][] getArrayCopy () {
+      double[][] C = new double[m][n];
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j];
+         }
+      }
+      return C;
+   }
+
+   /** Make a one-dimensional column packed copy of the internal array.
+   @return     Matrix elements packed in a one-dimensional array by columns.
+   */
+
+   public double[] getColumnPackedCopy () {
+      double[] vals = new double[m*n];
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            vals[i+j*m] = A[i][j];
+         }
+      }
+      return vals;
+   }
+
+   /** Make a one-dimensional row packed copy of the internal array.
+   @return     Matrix elements packed in a one-dimensional array by rows.
+   */
+
+   public double[] getRowPackedCopy () {
+      double[] vals = new double[m*n];
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            vals[i*n+j] = A[i][j];
+         }
+      }
+      return vals;
+   }
+
+   /** Get row dimension.
+   @return     m, the number of rows.
+   */
+
+   public int getRowDimension () {
+      return m;
+   }
+
+   /** Get column dimension.
+   @return     n, the number of columns.
+   */
+
+   public int getColumnDimension () {
+      return n;
+   }
+
+   /** Get a single element.
+   @param i    Row index.
+   @param j    Column index.
+   @return     A(i,j)
+   @exception  ArrayIndexOutOfBoundsException
+   */
+
+   public double get (int i, int j) {
+      return A[i][j];
+   }
+
+   /** Get a submatrix.
+   @param i0   Initial row index
+   @param i1   Final row index
+   @param j0   Initial column index
+   @param j1   Final column index
+   @return     A(i0:i1,j0:j1)
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public Matrix getMatrix (int i0, int i1, int j0, int j1) {
+      Matrix X = new Matrix(i1-i0+1,j1-j0+1);
+      double[][] B = X.getArray();
+      try {
+         for (int i = i0; i <= i1; i++) {
+            for (int j = j0; j <= j1; j++) {
+               B[i-i0][j-j0] = A[i][j];
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+      return X;
+   }
+
+   /** Get a submatrix.
+   @param r    Array of row indices.
+   @param c    Array of column indices.
+   @return     A(r(:),c(:))
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public Matrix getMatrix (int[] r, int[] c) {
+      Matrix X = new Matrix(r.length,c.length);
+      double[][] B = X.getArray();
+      try {
+         for (int i = 0; i < r.length; i++) {
+            for (int j = 0; j < c.length; j++) {
+               B[i][j] = A[r[i]][c[j]];
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+      return X;
+   }
+
+   /** Get a submatrix.
+   @param i0   Initial row index
+   @param i1   Final row index
+   @param c    Array of column indices.
+   @return     A(i0:i1,c(:))
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public Matrix getMatrix (int i0, int i1, int[] c) {
+      Matrix X = new Matrix(i1-i0+1,c.length);
+      double[][] B = X.getArray();
+      try {
+         for (int i = i0; i <= i1; i++) {
+            for (int j = 0; j < c.length; j++) {
+               B[i-i0][j] = A[i][c[j]];
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+      return X;
+   }
+
+   /** Get a submatrix.
+   @param r    Array of row indices.
+   @param i0   Initial column index
+   @param i1   Final column index
+   @return     A(r(:),j0:j1)
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public Matrix getMatrix (int[] r, int j0, int j1) {
+      Matrix X = new Matrix(r.length,j1-j0+1);
+      double[][] B = X.getArray();
+      try {
+         for (int i = 0; i < r.length; i++) {
+            for (int j = j0; j <= j1; j++) {
+               B[i][j-j0] = A[r[i]][j];
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+      return X;
+   }
+
+   /** Set a single element.
+   @param i    Row index.
+   @param j    Column index.
+   @param s    A(i,j).
+   @exception  ArrayIndexOutOfBoundsException
+   */
+
+   public void set (int i, int j, double s) {
+      A[i][j] = s;
+   }
+
+   /** Set a submatrix.
+   @param i0   Initial row index
+   @param i1   Final row index
+   @param j0   Initial column index
+   @param j1   Final column index
+   @param X    A(i0:i1,j0:j1)
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public void setMatrix (int i0, int i1, int j0, int j1, Matrix X) {
+      try {
+         for (int i = i0; i <= i1; i++) {
+            for (int j = j0; j <= j1; j++) {
+               A[i][j] = X.get(i-i0,j-j0);
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+   }
+
+   /** Set a submatrix.
+   @param r    Array of row indices.
+   @param c    Array of column indices.
+   @param X    A(r(:),c(:))
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public void setMatrix (int[] r, int[] c, Matrix X) {
+      try {
+         for (int i = 0; i < r.length; i++) {
+            for (int j = 0; j < c.length; j++) {
+               A[r[i]][c[j]] = X.get(i,j);
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+   }
+
+   /** Set a submatrix.
+   @param r    Array of row indices.
+   @param j0   Initial column index
+   @param j1   Final column index
+   @param X    A(r(:),j0:j1)
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public void setMatrix (int[] r, int j0, int j1, Matrix X) {
+      try {
+         for (int i = 0; i < r.length; i++) {
+            for (int j = j0; j <= j1; j++) {
+               A[r[i]][j] = X.get(i,j-j0);
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+   }
+
+   /** Set a submatrix.
+   @param i0   Initial row index
+   @param i1   Final row index
+   @param c    Array of column indices.
+   @param X    A(i0:i1,c(:))
+   @exception  ArrayIndexOutOfBoundsException Submatrix indices
+   */
+
+   public void setMatrix (int i0, int i1, int[] c, Matrix X) {
+      try {
+         for (int i = i0; i <= i1; i++) {
+            for (int j = 0; j < c.length; j++) {
+               A[i][c[j]] = X.get(i-i0,j);
+            }
+         }
+      } catch(ArrayIndexOutOfBoundsException e) {
+         throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+      }
+   }
+
+   /** Matrix transpose.
+   @return    A'
+   */
+
+   public Matrix transpose () {
+      Matrix X = new Matrix(n,m);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[j][i] = A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** One norm
+   @return    maximum column sum.
+   */
+
+   public double norm1 () {
+      double f = 0;
+      for (int j = 0; j < n; j++) {
+         double s = 0;
+         for (int i = 0; i < m; i++) {
+            s += Math.abs(A[i][j]);
+         }
+         f = Math.max(f,s);
+      }
+      return f;
+   }
+
+   /** Two norm
+   @return    maximum singular value.
+   */
+
+   public double norm2 () {
+      return (new SingularValueDecomposition(this).norm2());
+   }
+
+   /** Infinity norm
+   @return    maximum row sum.
+   */
+
+   public double normInf () {
+      double f = 0;
+      for (int i = 0; i < m; i++) {
+         double s = 0;
+         for (int j = 0; j < n; j++) {
+            s += Math.abs(A[i][j]);
+         }
+         f = Math.max(f,s);
+      }
+      return f;
+   }
+
+   /** Frobenius norm
+   @return    sqrt of sum of squares of all elements.
+   */
+
+   public double normF () {
+      double f = 0;
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            f = Maths.hypot(f,A[i][j]);
+         }
+      }
+      return f;
+   }
+
+   /**  Unary minus
+   @return    -A
+   */
+
+   public Matrix uminus () {
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = -A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** C = A + B
+   @param B    another matrix
+   @return     A + B
+   */
+
+   public Matrix plus (Matrix B) {
+      checkMatrixDimensions(B);
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j] + B.A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** A = A + B
+   @param B    another matrix
+   @return     A + B
+   */
+
+   public Matrix plusEquals (Matrix B) {
+      checkMatrixDimensions(B);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = A[i][j] + B.A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** C = A - B
+   @param B    another matrix
+   @return     A - B
+   */
+
+   public Matrix minus (Matrix B) {
+      checkMatrixDimensions(B);
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j] - B.A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** A = A - B
+   @param B    another matrix
+   @return     A - B
+   */
+
+   public Matrix minusEquals (Matrix B) {
+      checkMatrixDimensions(B);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = A[i][j] - B.A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** Element-by-element multiplication, C = A.*B
+   @param B    another matrix
+   @return     A.*B
+   */
+
+   public Matrix arrayTimes (Matrix B) {
+      checkMatrixDimensions(B);
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j] * B.A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Element-by-element multiplication in place, A = A.*B
+   @param B    another matrix
+   @return     A.*B
+   */
+
+   public Matrix arrayTimesEquals (Matrix B) {
+      checkMatrixDimensions(B);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = A[i][j] * B.A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** Element-by-element right division, C = A./B
+   @param B    another matrix
+   @return     A./B
+   */
+
+   public Matrix arrayRightDivide (Matrix B) {
+      checkMatrixDimensions(B);
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = A[i][j] / B.A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Element-by-element right division in place, A = A./B
+   @param B    another matrix
+   @return     A./B
+   */
+
+   public Matrix arrayRightDivideEquals (Matrix B) {
+      checkMatrixDimensions(B);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = A[i][j] / B.A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** Element-by-element left division, C = A.\B
+   @param B    another matrix
+   @return     A.\B
+   */
+
+   public Matrix arrayLeftDivide (Matrix B) {
+      checkMatrixDimensions(B);
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = B.A[i][j] / A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Element-by-element left division in place, A = A.\B
+   @param B    another matrix
+   @return     A.\B
+   */
+
+   public Matrix arrayLeftDivideEquals (Matrix B) {
+      checkMatrixDimensions(B);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = B.A[i][j] / A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** Multiply a matrix by a scalar, C = s*A
+   @param s    scalar
+   @return     s*A
+   */
+
+   public Matrix times (double s) {
+      Matrix X = new Matrix(m,n);
+      double[][] C = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            C[i][j] = s*A[i][j];
+         }
+      }
+      return X;
+   }
+
+   /** Multiply a matrix by a scalar in place, A = s*A
+   @param s    scalar
+   @return     replace A by s*A
+   */
+
+   public Matrix timesEquals (double s) {
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = s*A[i][j];
+         }
+      }
+      return this;
+   }
+
+   /** Linear algebraic matrix multiplication, A * B
+   @param B    another matrix
+   @return     Matrix product, A * B
+   @exception  IllegalArgumentException Matrix inner dimensions must agree.
+   */
+
+   public Matrix times (Matrix B) {
+      if (B.m != n) {
+         throw new IllegalArgumentException("Matrix inner dimensions must agree.");
+      }
+      Matrix X = new Matrix(m,B.n);
+      double[][] C = X.getArray();
+      double[] Bcolj = new double[n];
+      for (int j = 0; j < B.n; j++) {
+         for (int k = 0; k < n; k++) {
+            Bcolj[k] = B.A[k][j];
+         }
+         for (int i = 0; i < m; i++) {
+            double[] Arowi = A[i];
+            double s = 0;
+            for (int k = 0; k < n; k++) {
+               s += Arowi[k]*Bcolj[k];
+            }
+            C[i][j] = s;
+         }
+      }
+      return X;
+   }
+
+   /** LU Decomposition
+   @return     LUDecomposition
+   @see LUDecomposition
+   */
+
+   public LUDecomposition lu () {
+      return new LUDecomposition(this);
+   }
+
+   /** QR Decomposition
+   @return     QRDecomposition
+   @see QRDecomposition
+   */
+
+   public QRDecomposition qr () {
+      return new QRDecomposition(this);
+   }
+
+   /** Cholesky Decomposition
+   @return     CholeskyDecomposition
+   @see CholeskyDecomposition
+   */
+
+   public CholeskyDecomposition chol () {
+      return new CholeskyDecomposition(this);
+   }
+
+   /** Singular Value Decomposition
+   @return     SingularValueDecomposition
+   @see SingularValueDecomposition
+   */
+
+   public SingularValueDecomposition svd () {
+      return new SingularValueDecomposition(this);
+   }
+
+   /** Eigenvalue Decomposition
+   @return     EigenvalueDecomposition
+   @see EigenvalueDecomposition
+   */
+
+   public EigenvalueDecomposition eig () {
+      return new EigenvalueDecomposition(this);
+   }
+
+   /** Solve A*X = B
+   @param B    right hand side
+   @return     solution if A is square, least squares solution otherwise
+   */
+
+   public Matrix solve (Matrix B) {
+      return (m == n ? (new LUDecomposition(this)).solve(B) :
+                       (new QRDecomposition(this)).solve(B));
+   }
+
+   /** Solve X*A = B, which is also A'*X' = B'
+   @param B    right hand side
+   @return     solution if A is square, least squares solution otherwise.
+   */
+
+   public Matrix solveTranspose (Matrix B) {
+      return transpose().solve(B.transpose());
+   }
+
+   /** Matrix inverse or pseudoinverse
+   @return     inverse(A) if A is square, pseudoinverse otherwise.
+   */
+
+   public Matrix inverse () {
+      return solve(identity(m,m));
+   }
+
+   /** Matrix determinant
+   @return     determinant
+   */
+
+   public double det () {
+      return new LUDecomposition(this).det();
+   }
+
+   /** Matrix rank
+   @return     effective numerical rank, obtained from SVD.
+   */
+
+   public int rank () {
+      return new SingularValueDecomposition(this).rank();
+   }
+
+   /** Matrix condition (2 norm)
+   @return     ratio of largest to smallest singular value.
+   */
+
+   public double cond () {
+      return new SingularValueDecomposition(this).cond();
+   }
+
+   /** Matrix trace.
+   @return     sum of the diagonal elements.
+   */
+
+   public double trace () {
+      double t = 0;
+      for (int i = 0; i < Math.min(m,n); i++) {
+         t += A[i][i];
+      }
+      return t;
+   }
+
+   /** Generate matrix with random elements
+   @param m    Number of rows.
+   @param n    Number of colums.
+   @return     An m-by-n matrix with uniformly distributed random elements.
+   */
+
+   public static Matrix random (int m, int n) {
+      Matrix A = new Matrix(m,n);
+      double[][] X = A.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            X[i][j] = Math.random();
+         }
+      }
+      return A;
+   }
+
+   /** Generate identity matrix
+   @param m    Number of rows.
+   @param n    Number of colums.
+   @return     An m-by-n matrix with ones on the diagonal and zeros elsewhere.
+   */
+
+   public static Matrix identity (int m, int n) {
+      Matrix A = new Matrix(m,n);
+      double[][] X = A.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            X[i][j] = (i == j ? 1.0 : 0.0);
+         }
+      }
+      return A;
+   }
+
+
+   /** Print the matrix to stdout.   Line the elements up in columns
+     * with a Fortran-like 'Fw.d' style format.
+   @param w    Column width.
+   @param d    Number of digits after the decimal.
+   */
+
+   public void print (int w, int d) {
+      print(new PrintWriter(System.out,true),w,d); }
+
+   /** Print the matrix to the output stream.   Line the elements up in
+     * columns with a Fortran-like 'Fw.d' style format.
+   @param output Output stream.
+   @param w      Column width.
+   @param d      Number of digits after the decimal.
+   */
+
+   public void print (PrintWriter output, int w, int d) {
+      DecimalFormat format = new DecimalFormat();
+      format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
+      format.setMinimumIntegerDigits(1);
+      format.setMaximumFractionDigits(d);
+      format.setMinimumFractionDigits(d);
+      format.setGroupingUsed(false);
+      print(output,format,w+2);
+   }
+
+   /** Print the matrix to stdout.  Line the elements up in columns.
+     * Use the format object, and right justify within columns of width
+     * characters.
+     * Note that is the matrix is to be read back in, you probably will want
+     * to use a NumberFormat that is set to US Locale.
+   @param format A  Formatting object for individual elements.
+   @param width     Field width for each column.
+   @see java.text.DecimalFormat#setDecimalFormatSymbols
+   */
+
+   public void print (NumberFormat format, int width) {
+      print(new PrintWriter(System.out,true),format,width); }
+
+   // DecimalFormat is a little disappointing coming from Fortran or C's printf.
+   // Since it doesn't pad on the left, the elements will come out different
+   // widths.  Consequently, we'll pass the desired column width in as an
+   // argument and do the extra padding ourselves.
+
+   /** Print the matrix to the output stream.  Line the elements up in columns.
+     * Use the format object, and right justify within columns of width
+     * characters.
+     * Note that is the matrix is to be read back in, you probably will want
+     * to use a NumberFormat that is set to US Locale.
+   @param output the output stream.
+   @param format A formatting object to format the matrix elements 
+   @param width  Column width.
+   @see java.text.DecimalFormat#setDecimalFormatSymbols
+   */
+
+   public void print (PrintWriter output, NumberFormat format, int width) {
+      output.println();  // start on new line.
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            String s = format.format(A[i][j]); // format the number
+            int padding = Math.max(1,width-s.length()); // At _least_ 1 space
+            for (int k = 0; k < padding; k++)
+               output.print(' ');
+            output.print(s);
+         }
+         output.println();
+      }
+      output.println();   // end with blank line.
+   }
+
+   /** Read a matrix from a stream.  The format is the same the print method,
+     * so printed matrices can be read back in (provided they were printed using
+     * US Locale).  Elements are separated by
+     * whitespace, all the elements for each row appear on a single line,
+     * the last row is followed by a blank line.
+   @param input the input stream.
+   */
+
+   public static Matrix read (BufferedReader input) throws java.io.IOException {
+      StreamTokenizer tokenizer= new StreamTokenizer(input);
+
+      // Although StreamTokenizer will parse numbers, it doesn't recognize
+      // scientific notation (E or D); however, Double.valueOf does.
+      // The strategy here is to disable StreamTokenizer's number parsing.
+      // We'll only get whitespace delimited words, EOL's and EOF's.
+      // These words should all be numbers, for Double.valueOf to parse.
+
+      tokenizer.resetSyntax();
+      tokenizer.wordChars(0,255);
+      tokenizer.whitespaceChars(0, ' ');
+      tokenizer.eolIsSignificant(true);
+      java.util.Vector v = new java.util.Vector();
+
+      // Ignore initial empty lines
+      while (tokenizer.nextToken() == StreamTokenizer.TT_EOL);
+      if (tokenizer.ttype == StreamTokenizer.TT_EOF)
+	throw new java.io.IOException("Unexpected EOF on matrix read.");
+      do {
+         v.addElement(Double.valueOf(tokenizer.sval)); // Read & store 1st row.
+      } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
+
+      int n = v.size();  // Now we've got the number of columns!
+      double row[] = new double[n];
+      for (int j=0; j<n; j++)  // extract the elements of the 1st row.
+         row[j]=((Double)v.elementAt(j)).doubleValue();
+      v.removeAllElements();
+      v.addElement(row);  // Start storing rows instead of columns.
+      while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
+         // While non-empty lines
+         v.addElement(row = new double[n]);
+         int j = 0;
+         do {
+            if (j >= n) throw new java.io.IOException
+               ("Row " + v.size() + " is too long.");
+            row[j++] = Double.valueOf(tokenizer.sval).doubleValue();
+         } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
+         if (j < n) throw new java.io.IOException
+            ("Row " + v.size() + " is too short.");
+      }
+      int m = v.size();  // Now we've got the number of rows.
+      double[][] A = new double[m][];
+      v.copyInto(A);  // copy the rows out of the vector
+      return new Matrix(A);
+   }
+
+
+/* ------------------------
+   Private Methods
+ * ------------------------ */
+
+   /** Check if size(A) == size(B) **/
+
+   private void checkMatrixDimensions (Matrix B) {
+      if (B.m != m || B.n != n) {
+         throw new IllegalArgumentException("Matrix dimensions must agree.");
+      }
+   }
+
+}
+
diff --git a/LibrarySource/Jama/QRDecomposition.java b/LibrarySource/Jama/QRDecomposition.java
new file mode 100644
index 0000000..1189f35
--- /dev/null
+++ b/LibrarySource/Jama/QRDecomposition.java
@@ -0,0 +1,219 @@
+package Jama;
+import Jama.util.*;
+
+/** QR Decomposition.
+<P>
+   For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
+   orthogonal matrix Q and an n-by-n upper triangular matrix R so that
+   A = Q*R.
+<P>
+   The QR decompostion always exists, even if the matrix does not have
+   full rank, so the constructor will never fail.  The primary use of the
+   QR decomposition is in the least squares solution of nonsquare systems
+   of simultaneous linear equations.  This will fail if isFullRank()
+   returns false.
+*/
+
+public class QRDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   private double[][] QR;
+
+   /** Row and column dimensions.
+   @serial column dimension.
+   @serial row dimension.
+   */
+   private int m, n;
+
+   /** Array for internal storage of diagonal of R.
+   @serial diagonal of R.
+   */
+   private double[] Rdiag;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** QR Decomposition, computed by Householder reflections.
+   @param A    Rectangular matrix
+   @return     Structure to access R and the Householder vectors and compute Q.
+   */
+
+   public QRDecomposition (Matrix A) {
+      // Initialize.
+      QR = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      Rdiag = new double[n];
+
+      // Main loop.
+      for (int k = 0; k < n; k++) {
+         // Compute 2-norm of k-th column without under/overflow.
+         double nrm = 0;
+         for (int i = k; i < m; i++) {
+            nrm = Maths.hypot(nrm,QR[i][k]);
+         }
+
+         if (nrm != 0.0) {
+            // Form k-th Householder vector.
+            if (QR[k][k] < 0) {
+               nrm = -nrm;
+            }
+            for (int i = k; i < m; i++) {
+               QR[i][k] /= nrm;
+            }
+            QR[k][k] += 1.0;
+
+            // Apply transformation to remaining columns.
+            for (int j = k+1; j < n; j++) {
+               double s = 0.0; 
+               for (int i = k; i < m; i++) {
+                  s += QR[i][k]*QR[i][j];
+               }
+               s = -s/QR[k][k];
+               for (int i = k; i < m; i++) {
+                  QR[i][j] += s*QR[i][k];
+               }
+            }
+         }
+         Rdiag[k] = -nrm;
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Is the matrix full rank?
+   @return     true if R, and hence A, has full rank.
+   */
+
+   public boolean isFullRank () {
+      for (int j = 0; j < n; j++) {
+         if (Rdiag[j] == 0)
+            return false;
+      }
+      return true;
+   }
+
+   /** Return the Householder vectors
+   @return     Lower trapezoidal matrix whose columns define the reflections
+   */
+
+   public Matrix getH () {
+      Matrix X = new Matrix(m,n);
+      double[][] H = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i >= j) {
+               H[i][j] = QR[i][j];
+            } else {
+               H[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return the upper triangular factor
+   @return     R
+   */
+
+   public Matrix getR () {
+      Matrix X = new Matrix(n,n);
+      double[][] R = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i < j) {
+               R[i][j] = QR[i][j];
+            } else if (i == j) {
+               R[i][j] = Rdiag[i];
+            } else {
+               R[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Generate and return the (economy-sized) orthogonal factor
+   @return     Q
+   */
+
+   public Matrix getQ () {
+      Matrix X = new Matrix(m,n);
+      double[][] Q = X.getArray();
+      for (int k = n-1; k >= 0; k--) {
+         for (int i = 0; i < m; i++) {
+            Q[i][k] = 0.0;
+         }
+         Q[k][k] = 1.0;
+         for (int j = k; j < n; j++) {
+            if (QR[k][k] != 0) {
+               double s = 0.0;
+               for (int i = k; i < m; i++) {
+                  s += QR[i][k]*Q[i][j];
+               }
+               s = -s/QR[k][k];
+               for (int i = k; i < m; i++) {
+                  Q[i][j] += s*QR[i][k];
+               }
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Least squares solution of A*X = B
+   @param B    A Matrix with as many rows as A and any number of columns.
+   @return     X that minimizes the two norm of Q*R*X-B.
+   @exception  IllegalArgumentException  Matrix row dimensions must agree.
+   @exception  RuntimeException  Matrix is rank deficient.
+   */
+
+   public Matrix solve (Matrix B) {
+      if (B.getRowDimension() != m) {
+         throw new IllegalArgumentException("Matrix row dimensions must agree.");
+      }
+      if (!this.isFullRank()) {
+         throw new RuntimeException("Matrix is rank deficient.");
+      }
+      
+      // Copy right hand side
+      int nx = B.getColumnDimension();
+      double[][] X = B.getArrayCopy();
+
+      // Compute Y = transpose(Q)*B
+      for (int k = 0; k < n; k++) {
+         for (int j = 0; j < nx; j++) {
+            double s = 0.0; 
+            for (int i = k; i < m; i++) {
+               s += QR[i][k]*X[i][j];
+            }
+            s = -s/QR[k][k];
+            for (int i = k; i < m; i++) {
+               X[i][j] += s*QR[i][k];
+            }
+         }
+      }
+      // Solve R*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= Rdiag[k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*QR[i][k];
+            }
+         }
+      }
+      return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1));
+   }
+}
+
diff --git a/LibrarySource/Jama/SingularValueDecomposition.java b/LibrarySource/Jama/SingularValueDecomposition.java
new file mode 100644
index 0000000..28cf197
--- /dev/null
+++ b/LibrarySource/Jama/SingularValueDecomposition.java
@@ -0,0 +1,540 @@
+package Jama;
+import Jama.util.*;
+
+   /** Singular Value Decomposition.
+   <P>
+   For an m-by-n matrix A with m >= n, the singular value decomposition is
+   an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
+   an n-by-n orthogonal matrix V so that A = U*S*V'.
+   <P>
+   The singular values, sigma[k] = S[k][k], are ordered so that
+   sigma[0] >= sigma[1] >= ... >= sigma[n-1].
+   <P>
+   The singular value decompostion always exists, so the constructor will
+   never fail.  The matrix condition number and the effective numerical
+   rank can be computed from this decomposition.
+   */
+
+public class SingularValueDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Arrays for internal storage of U and V.
+   @serial internal storage of U.
+   @serial internal storage of V.
+   */
+   private double[][] U, V;
+
+   /** Array for internal storage of singular values.
+   @serial internal storage of singular values.
+   */
+   private double[] s;
+
+   /** Row and column dimensions.
+   @serial row dimension.
+   @serial column dimension.
+   */
+   private int m, n;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** Construct the singular value decomposition
+   @param A    Rectangular matrix
+   @return     Structure to access U, S and V.
+   */
+
+   public SingularValueDecomposition (Matrix Arg) {
+
+      // Derived from LINPACK code.
+      // Initialize.
+      double[][] A = Arg.getArrayCopy();
+      m = Arg.getRowDimension();
+      n = Arg.getColumnDimension();
+      int nu = Math.min(m,n);
+      s = new double [Math.min(m+1,n)];
+      U = new double [m][nu];
+      V = new double [n][n];
+      double[] e = new double [n];
+      double[] work = new double [m];
+      boolean wantu = true;
+      boolean wantv = true;
+
+      // Reduce A to bidiagonal form, storing the diagonal elements
+      // in s and the super-diagonal elements in e.
+
+      int nct = Math.min(m-1,n);
+      int nrt = Math.max(0,Math.min(n-2,m));
+      for (int k = 0; k < Math.max(nct,nrt); k++) {
+         if (k < nct) {
+
+            // Compute the transformation for the k-th column and
+            // place the k-th diagonal in s[k].
+            // Compute 2-norm of k-th column without under/overflow.
+            s[k] = 0;
+            for (int i = k; i < m; i++) {
+               s[k] = Maths.hypot(s[k],A[i][k]);
+            }
+            if (s[k] != 0.0) {
+               if (A[k][k] < 0.0) {
+                  s[k] = -s[k];
+               }
+               for (int i = k; i < m; i++) {
+                  A[i][k] /= s[k];
+               }
+               A[k][k] += 1.0;
+            }
+            s[k] = -s[k];
+         }
+         for (int j = k+1; j < n; j++) {
+            if ((k < nct) & (s[k] != 0.0))  {
+
+            // Apply the transformation.
+
+               double t = 0;
+               for (int i = k; i < m; i++) {
+                  t += A[i][k]*A[i][j];
+               }
+               t = -t/A[k][k];
+               for (int i = k; i < m; i++) {
+                  A[i][j] += t*A[i][k];
+               }
+            }
+
+            // Place the k-th row of A into e for the
+            // subsequent calculation of the row transformation.
+
+            e[j] = A[k][j];
+         }
+         if (wantu & (k < nct)) {
+
+            // Place the transformation in U for subsequent back
+            // multiplication.
+
+            for (int i = k; i < m; i++) {
+               U[i][k] = A[i][k];
+            }
+         }
+         if (k < nrt) {
+
+            // Compute the k-th row transformation and place the
+            // k-th super-diagonal in e[k].
+            // Compute 2-norm without under/overflow.
+            e[k] = 0;
+            for (int i = k+1; i < n; i++) {
+               e[k] = Maths.hypot(e[k],e[i]);
+            }
+            if (e[k] != 0.0) {
+               if (e[k+1] < 0.0) {
+                  e[k] = -e[k];
+               }
+               for (int i = k+1; i < n; i++) {
+                  e[i] /= e[k];
+               }
+               e[k+1] += 1.0;
+            }
+            e[k] = -e[k];
+            if ((k+1 < m) & (e[k] != 0.0)) {
+
+            // Apply the transformation.
+
+               for (int i = k+1; i < m; i++) {
+                  work[i] = 0.0;
+               }
+               for (int j = k+1; j < n; j++) {
+                  for (int i = k+1; i < m; i++) {
+                     work[i] += e[j]*A[i][j];
+                  }
+               }
+               for (int j = k+1; j < n; j++) {
+                  double t = -e[j]/e[k+1];
+                  for (int i = k+1; i < m; i++) {
+                     A[i][j] += t*work[i];
+                  }
+               }
+            }
+            if (wantv) {
+
+            // Place the transformation in V for subsequent
+            // back multiplication.
+
+               for (int i = k+1; i < n; i++) {
+                  V[i][k] = e[i];
+               }
+            }
+         }
+      }
+
+      // Set up the final bidiagonal matrix or order p.
+
+      int p = Math.min(n,m+1);
+      if (nct < n) {
+         s[nct] = A[nct][nct];
+      }
+      if (m < p) {
+         s[p-1] = 0.0;
+      }
+      if (nrt+1 < p) {
+         e[nrt] = A[nrt][p-1];
+      }
+      e[p-1] = 0.0;
+
+      // If required, generate U.
+
+      if (wantu) {
+         for (int j = nct; j < nu; j++) {
+            for (int i = 0; i < m; i++) {
+               U[i][j] = 0.0;
+            }
+            U[j][j] = 1.0;
+         }
+         for (int k = nct-1; k >= 0; k--) {
+            if (s[k] != 0.0) {
+               for (int j = k+1; j < nu; j++) {
+                  double t = 0;
+                  for (int i = k; i < m; i++) {
+                     t += U[i][k]*U[i][j];
+                  }
+                  t = -t/U[k][k];
+                  for (int i = k; i < m; i++) {
+                     U[i][j] += t*U[i][k];
+                  }
+               }
+               for (int i = k; i < m; i++ ) {
+                  U[i][k] = -U[i][k];
+               }
+               U[k][k] = 1.0 + U[k][k];
+               for (int i = 0; i < k-1; i++) {
+                  U[i][k] = 0.0;
+               }
+            } else {
+               for (int i = 0; i < m; i++) {
+                  U[i][k] = 0.0;
+               }
+               U[k][k] = 1.0;
+            }
+         }
+      }
+
+      // If required, generate V.
+
+      if (wantv) {
+         for (int k = n-1; k >= 0; k--) {
+            if ((k < nrt) & (e[k] != 0.0)) {
+               for (int j = k+1; j < nu; j++) {
+                  double t = 0;
+                  for (int i = k+1; i < n; i++) {
+                     t += V[i][k]*V[i][j];
+                  }
+                  t = -t/V[k+1][k];
+                  for (int i = k+1; i < n; i++) {
+                     V[i][j] += t*V[i][k];
+                  }
+               }
+            }
+            for (int i = 0; i < n; i++) {
+               V[i][k] = 0.0;
+            }
+            V[k][k] = 1.0;
+         }
+      }
+
+      // Main iteration loop for the singular values.
+
+      int pp = p-1;
+      int iter = 0;
+      double eps = Math.pow(2.0,-52.0);
+      while (p > 0) {
+         int k,kase;
+
+         // Here is where a test for too many iterations would go.
+
+         // This section of the program inspects for
+         // negligible elements in the s and e arrays.  On
+         // completion the variables kase and k are set as follows.
+
+         // kase = 1     if s(p) and e[k-1] are negligible and k<p
+         // kase = 2     if s(k) is negligible and k<p
+         // kase = 3     if e[k-1] is negligible, k<p, and
+         //              s(k), ..., s(p) are not negligible (qr step).
+         // kase = 4     if e(p-1) is negligible (convergence).
+
+         for (k = p-2; k >= -1; k--) {
+            if (k == -1) {
+               break;
+            }
+            if (Math.abs(e[k]) <= eps*(Math.abs(s[k]) + Math.abs(s[k+1]))) {
+               e[k] = 0.0;
+               break;
+            }
+         }
+         if (k == p-2) {
+            kase = 4;
+         } else {
+            int ks;
+            for (ks = p-1; ks >= k; ks--) {
+               if (ks == k) {
+                  break;
+               }
+               double t = (ks != p ? Math.abs(e[ks]) : 0.) + 
+                          (ks != k+1 ? Math.abs(e[ks-1]) : 0.);
+               if (Math.abs(s[ks]) <= eps*t)  {
+                  s[ks] = 0.0;
+                  break;
+               }
+            }
+            if (ks == k) {
+               kase = 3;
+            } else if (ks == p-1) {
+               kase = 1;
+            } else {
+               kase = 2;
+               k = ks;
+            }
+         }
+         k++;
+
+         // Perform the task indicated by kase.
+
+         switch (kase) {
+
+            // Deflate negligible s(p).
+
+            case 1: {
+               double f = e[p-2];
+               e[p-2] = 0.0;
+               for (int j = p-2; j >= k; j--) {
+                  double t = Maths.hypot(s[j],f);
+                  double cs = s[j]/t;
+                  double sn = f/t;
+                  s[j] = t;
+                  if (j != k) {
+                     f = -sn*e[j-1];
+                     e[j-1] = cs*e[j-1];
+                  }
+                  if (wantv) {
+                     for (int i = 0; i < n; i++) {
+                        t = cs*V[i][j] + sn*V[i][p-1];
+                        V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1];
+                        V[i][j] = t;
+                     }
+                  }
+               }
+            }
+            break;
+
+            // Split at negligible s(k).
+
+            case 2: {
+               double f = e[k-1];
+               e[k-1] = 0.0;
+               for (int j = k; j < p; j++) {
+                  double t = Maths.hypot(s[j],f);
+                  double cs = s[j]/t;
+                  double sn = f/t;
+                  s[j] = t;
+                  f = -sn*e[j];
+                  e[j] = cs*e[j];
+                  if (wantu) {
+                     for (int i = 0; i < m; i++) {
+                        t = cs*U[i][j] + sn*U[i][k-1];
+                        U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1];
+                        U[i][j] = t;
+                     }
+                  }
+               }
+            }
+            break;
+
+            // Perform one qr step.
+
+            case 3: {
+
+               // Calculate the shift.
+   
+               double scale = Math.max(Math.max(Math.max(Math.max(
+                       Math.abs(s[p-1]),Math.abs(s[p-2])),Math.abs(e[p-2])), 
+                       Math.abs(s[k])),Math.abs(e[k]));
+               double sp = s[p-1]/scale;
+               double spm1 = s[p-2]/scale;
+               double epm1 = e[p-2]/scale;
+               double sk = s[k]/scale;
+               double ek = e[k]/scale;
+               double b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
+               double c = (sp*epm1)*(sp*epm1);
+               double shift = 0.0;
+               if ((b != 0.0) | (c != 0.0)) {
+                  shift = Math.sqrt(b*b + c);
+                  if (b < 0.0) {
+                     shift = -shift;
+                  }
+                  shift = c/(b + shift);
+               }
+               double f = (sk + sp)*(sk - sp) + shift;
+               double g = sk*ek;
+   
+               // Chase zeros.
+   
+               for (int j = k; j < p-1; j++) {
+                  double t = Maths.hypot(f,g);
+                  double cs = f/t;
+                  double sn = g/t;
+                  if (j != k) {
+                     e[j-1] = t;
+                  }
+                  f = cs*s[j] + sn*e[j];
+                  e[j] = cs*e[j] - sn*s[j];
+                  g = sn*s[j+1];
+                  s[j+1] = cs*s[j+1];
+                  if (wantv) {
+                     for (int i = 0; i < n; i++) {
+                        t = cs*V[i][j] + sn*V[i][j+1];
+                        V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1];
+                        V[i][j] = t;
+                     }
+                  }
+                  t = Maths.hypot(f,g);
+                  cs = f/t;
+                  sn = g/t;
+                  s[j] = t;
+                  f = cs*e[j] + sn*s[j+1];
+                  s[j+1] = -sn*e[j] + cs*s[j+1];
+                  g = sn*e[j+1];
+                  e[j+1] = cs*e[j+1];
+                  if (wantu && (j < m-1)) {
+                     for (int i = 0; i < m; i++) {
+                        t = cs*U[i][j] + sn*U[i][j+1];
+                        U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1];
+                        U[i][j] = t;
+                     }
+                  }
+               }
+               e[p-2] = f;
+               iter = iter + 1;
+            }
+            break;
+
+            // Convergence.
+
+            case 4: {
+
+               // Make the singular values positive.
+   
+               if (s[k] <= 0.0) {
+                  s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
+                  if (wantv) {
+                     for (int i = 0; i <= pp; i++) {
+                        V[i][k] = -V[i][k];
+                     }
+                  }
+               }
+   
+               // Order the singular values.
+   
+               while (k < pp) {
+                  if (s[k] >= s[k+1]) {
+                     break;
+                  }
+                  double t = s[k];
+                  s[k] = s[k+1];
+                  s[k+1] = t;
+                  if (wantv && (k < n-1)) {
+                     for (int i = 0; i < n; i++) {
+                        t = V[i][k+1]; V[i][k+1] = V[i][k]; V[i][k] = t;
+                     }
+                  }
+                  if (wantu && (k < m-1)) {
+                     for (int i = 0; i < m; i++) {
+                        t = U[i][k+1]; U[i][k+1] = U[i][k]; U[i][k] = t;
+                     }
+                  }
+                  k++;
+               }
+               iter = 0;
+               p--;
+            }
+            break;
+         }
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Return the left singular vectors
+   @return     U
+   */
+
+   public Matrix getU () {
+      return new Matrix(U,m,Math.min(m+1,n));
+   }
+
+   /** Return the right singular vectors
+   @return     V
+   */
+
+   public Matrix getV () {
+      return new Matrix(V,n,n);
+   }
+
+   /** Return the one-dimensional array of singular values
+   @return     diagonal of S.
+   */
+
+   public double[] getSingularValues () {
+      return s;
+   }
+
+   /** Return the diagonal matrix of singular values
+   @return     S
+   */
+
+   public Matrix getS () {
+      Matrix X = new Matrix(n,n);
+      double[][] S = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            S[i][j] = 0.0;
+         }
+         S[i][i] = this.s[i];
+      }
+      return X;
+   }
+
+   /** Two norm
+   @return     max(S)
+   */
+
+   public double norm2 () {
+      return s[0];
+   }
+
+   /** Two norm condition number
+   @return     max(S)/min(S)
+   */
+
+   public double cond () {
+      return s[0]/s[Math.min(m,n)-1];
+   }
+
+   /** Effective numerical matrix rank
+   @return     Number of nonnegligible singular values.
+   */
+
+   public int rank () {
+      double eps = Math.pow(2.0,-52.0);
+      double tol = Math.max(m,n)*s[0]*eps;
+      int r = 0;
+      for (int i = 0; i < s.length; i++) {
+         if (s[i] > tol) {
+            r++;
+         }
+      }
+      return r;
+   }
+}
+
diff --git a/LibrarySource/Jama/examples/MagicSquareExample.java b/LibrarySource/Jama/examples/MagicSquareExample.java
new file mode 100644
index 0000000..f470351
--- /dev/null
+++ b/LibrarySource/Jama/examples/MagicSquareExample.java
@@ -0,0 +1,164 @@
+package Jama.examples;
+import Jama.*; 
+import java.util.Date;
+
+/** Example of use of Matrix Class, featuring magic squares. **/
+
+public class MagicSquareExample {
+
+   /** Generate magic square test matrix. **/
+
+   public static Matrix magic (int n) {
+
+      double[][] M = new double[n][n];
+
+      // Odd order
+
+      if ((n % 2) == 1) {
+         int a = (n+1)/2;
+         int b = (n+1);
+         for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+               M[i][j] = n*((i+j+a) % n) + ((i+2*j+b) % n) + 1;
+            }
+         }
+
+      // Doubly Even Order
+
+      } else if ((n % 4) == 0) {
+         for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+               if (((i+1)/2)%2 == ((j+1)/2)%2) {
+                  M[i][j] = n*n-n*i-j;
+               } else {
+                  M[i][j] = n*i+j+1;
+               }
+            }
+         }
+
+      // Singly Even Order
+
+      } else {
+         int p = n/2;
+         int k = (n-2)/4;
+         Matrix A = magic(p);
+         for (int j = 0; j < p; j++) {
+            for (int i = 0; i < p; i++) {
+               double aij = A.get(i,j);
+               M[i][j] = aij;
+               M[i][j+p] = aij + 2*p*p;
+               M[i+p][j] = aij + 3*p*p;
+               M[i+p][j+p] = aij + p*p;
+            }
+         }
+         for (int i = 0; i < p; i++) {
+            for (int j = 0; j < k; j++) {
+               double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
+            }
+            for (int j = n-k+1; j < n; j++) {
+               double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
+            }
+         }
+         double t = M[k][0]; M[k][0] = M[k+p][0]; M[k+p][0] = t;
+         t = M[k][k]; M[k][k] = M[k+p][k]; M[k+p][k] = t;
+      }
+      return new Matrix(M);
+   }
+
+   /** Shorten spelling of print. **/
+
+   private static void print (String s) {
+      System.out.print(s);
+   }
+   
+   /** Format double with Fw.d. **/
+
+   public static String fixedWidthDoubletoString (double x, int w, int d) {
+      java.text.DecimalFormat fmt = new java.text.DecimalFormat();
+      fmt.setMaximumFractionDigits(d);
+      fmt.setMinimumFractionDigits(d);
+      fmt.setGroupingUsed(false);
+      String s = fmt.format(x);
+      while (s.length() < w) {
+         s = " " + s;
+      }
+      return s;
+   }
+
+   /** Format integer with Iw. **/
+
+   public static String fixedWidthIntegertoString (int n, int w) {
+      String s = Integer.toString(n);
+      while (s.length() < w) {
+         s = " " + s;
+      }
+      return s;
+   }
+
+
+   public static void main (String argv[]) {
+
+   /* 
+    | Tests LU, QR, SVD and symmetric Eig decompositions.
+    |
+    |   n       = order of magic square.
+    |   trace   = diagonal sum, should be the magic sum, (n^3 + n)/2.
+    |   max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
+    |   rank    = linear algebraic rank,
+    |             should equal n if n is odd, be less than n if n is even.
+    |   cond    = L_2 condition number, ratio of singular values.
+    |   lu_res  = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
+    |   qr_res  = test of QR factorization, norm1(Q*R-A)/(n*eps).
+    */
+
+      print("\n    Test of Matrix Class, using magic squares.\n");
+      print("    See MagicSquareExample.main() for an explanation.\n");
+      print("\n      n     trace       max_eig   rank        cond      lu_res      qr_res\n\n");
+ 
+      Date start_time = new Date();
+      double eps = Math.pow(2.0,-52.0);
+      for (int n = 3; n <= 32; n++) {
+         print(fixedWidthIntegertoString(n,7));
+
+         Matrix M = magic(n);
+
+         int t = (int) M.trace();
+         print(fixedWidthIntegertoString(t,10));
+
+         EigenvalueDecomposition E =
+            new EigenvalueDecomposition(M.plus(M.transpose()).times(0.5));
+         double[] d = E.getRealEigenvalues();
+         print(fixedWidthDoubletoString(d[n-1],14,3));
+
+         int r = M.rank();
+         print(fixedWidthIntegertoString(r,7));
+
+         double c = M.cond();
+         print(c < 1/eps ? fixedWidthDoubletoString(c,12,3) :
+            "         Inf");
+
+         LUDecomposition LU = new LUDecomposition(M);
+         Matrix L = LU.getL();
+         Matrix U = LU.getU();
+         int[] p = LU.getPivot();
+         Matrix R = L.times(U).minus(M.getMatrix(p,0,n-1));
+         double res = R.norm1()/(n*eps);
+         print(fixedWidthDoubletoString(res,12,3));
+
+         QRDecomposition QR = new QRDecomposition(M);
+         Matrix Q = QR.getQ();
+         R = QR.getR();
+         R = Q.times(R).minus(M);
+         res = R.norm1()/(n*eps);
+         print(fixedWidthDoubletoString(res,12,3));
+
+         print("\n");
+      }
+      Date stop_time = new Date();
+      double etime = (stop_time.getTime() - start_time.getTime())/1000.;
+      print("\nElapsed Time = " + 
+         fixedWidthDoubletoString(etime,12,3) + " seconds\n");
+      print("Adios\n");
+   }
+}
+
diff --git a/LibrarySource/Jama/test/TestMatrix.java b/LibrarySource/Jama/test/TestMatrix.java
new file mode 100644
index 0000000..a5c25de
--- /dev/null
+++ b/LibrarySource/Jama/test/TestMatrix.java
@@ -0,0 +1,944 @@
+package Jama.test;
+import Jama.*;
+import java.io.*;
+import java.util.zip.GZIPInputStream;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+/** TestMatrix tests the functionality of the Jama Matrix class and associated decompositions.
+<P>
+Run the test from the command line using
+<BLOCKQUOTE><PRE><CODE>
+ java Jama.test.TestMatrix 
+</CODE></PRE></BLOCKQUOTE>
+Detailed output is provided indicating the functionality being tested
+and whether the functionality is correctly implemented.   Exception handling
+is also tested.  
+<P>
+The test is designed to run to completion and give a summary of any implementation errors
+encountered. The final output should be:
+<BLOCKQUOTE><PRE><CODE>
+      TestMatrix completed.
+      Total errors reported: n1
+      Total warning reported: n2
+</CODE></PRE></BLOCKQUOTE>
+If the test does not run to completion, this indicates that there is a 
+substantial problem within the implementation that was not anticipated in the test design.  
+The stopping point should give an indication of where the problem exists.
+**/
+public class TestMatrix {
+   public static void main (String argv[]) {
+      Matrix A,B,C,Z,O,I,R,S,X,SUB,M,T,SQ,DEF,SOL;
+      // Uncomment this to test IO in a different locale.
+      // Locale.setDefault(Locale.GERMAN);
+      int errorCount=0;
+      int warningCount=0;
+      double tmp, s;
+      double[] columnwise = {1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.};
+      double[] rowwise = {1.,4.,7.,10.,2.,5.,8.,11.,3.,6.,9.,12.};
+      double[][] avals = {{1.,4.,7.,10.},{2.,5.,8.,11.},{3.,6.,9.,12.}};
+      double[][] rankdef = avals;
+      double[][] tvals =  {{1.,2.,3.},{4.,5.,6.},{7.,8.,9.},{10.,11.,12.}};
+      double[][] subavals = {{5.,8.,11.},{6.,9.,12.}};
+      double[][] rvals = {{1.,4.,7.},{2.,5.,8.,11.},{3.,6.,9.,12.}};
+      double[][] pvals = {{1.,1.,1.},{1.,2.,3.},{1.,3.,6.}};
+      double[][] ivals = {{1.,0.,0.,0.},{0.,1.,0.,0.},{0.,0.,1.,0.}};
+      double[][] evals = 
+         {{0.,1.,0.,0.},{1.,0.,2.e-7,0.},{0.,-2.e-7,0.,1.},{0.,0.,1.,0.}};
+      double[][] square = {{166.,188.,210.},{188.,214.,240.},{210.,240.,270.}};
+      double[][] sqSolution = {{13.},{15.}};
+      double[][] condmat = {{1.,3.},{7.,9.}};
+      int rows=3,cols=4;
+      int invalidld=5;/* should trigger bad shape for construction with val */
+      int raggedr=0; /* (raggedr,raggedc) should be out of bounds in ragged array */
+      int raggedc=4; 
+      int validld=3; /* leading dimension of intended test Matrices */
+      int nonconformld=4; /* leading dimension which is valid, but nonconforming */
+      int ib=1,ie=2,jb=1,je=3; /* index ranges for sub Matrix */
+      int[] rowindexset = {1,2}; 
+      int[] badrowindexset = {1,3}; 
+      int[] columnindexset = {1,2,3};
+      int[] badcolumnindexset = {1,2,4};
+      double columnsummax = 33.;
+      double rowsummax = 30.;
+      double sumofdiagonals = 15;
+      double sumofsquares = 650;
+
+/** 
+      Constructors and constructor-like methods:
+         double[], int
+         double[][]  
+         int, int
+         int, int, double
+         int, int, double[][]
+         constructWithCopy(double[][])
+         random(int,int)
+         identity(int)
+**/
+
+      print("\nTesting constructors and constructor-like methods...\n");
+      try{  
+         /** check that exception is thrown in packed constructor with invalid length **/
+         A = new Matrix(columnwise,invalidld);
+         errorCount = try_failure(errorCount,"Catch invalid length in packed constructor... ",
+                     "exception not thrown for invalid input");
+      } catch ( IllegalArgumentException e ) {
+         try_success("Catch invalid length in packed constructor... ",
+                     e.getMessage());
+      }
+      try{ 
+         /** check that exception is thrown in default constructor
+             if input array is 'ragged' **/
+         A = new Matrix(rvals);
+         tmp = A.get(raggedr,raggedc);
+      } catch ( IllegalArgumentException e ) {
+         try_success("Catch ragged input to default constructor... ",
+                      e.getMessage());
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"Catch ragged input to constructor... ",
+                     "exception not thrown in construction...ArrayIndexOutOfBoundsException thrown later");
+      }
+      try{ 
+         /** check that exception is thrown in constructWithCopy
+             if input array is 'ragged' **/
+         A = Matrix.constructWithCopy(rvals);
+         tmp = A.get(raggedr,raggedc);
+      } catch ( IllegalArgumentException e ) {
+         try_success("Catch ragged input to constructWithCopy... ",e.getMessage());
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"Catch ragged input to constructWithCopy... ","exception not thrown in construction...ArrayIndexOutOfBoundsException thrown later");
+      }
+
+      A = new Matrix(columnwise,validld);
+      B = new Matrix(avals);
+      tmp = B.get(0,0);
+      avals[0][0] = 0.0;
+      C = B.minus(A);
+      avals[0][0] = tmp;
+      B = Matrix.constructWithCopy(avals);
+      tmp = B.get(0,0);
+      avals[0][0] = 0.0;
+      if ( ( tmp - B.get(0,0) ) != 0.0 ) {
+        /** check that constructWithCopy behaves properly **/
+        errorCount = try_failure(errorCount,"constructWithCopy... ","copy not effected... data visible outside");
+      } else {
+        try_success("constructWithCopy... ","");
+      }
+      avals[0][0] = columnwise[0]; 
+      I = new Matrix(ivals);
+      try {
+        check(I,Matrix.identity(3,4));
+        try_success("identity... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"identity... ","identity Matrix not successfully created");
+      }   
+
+/**   
+      Access Methods:
+         getColumnDimension()
+         getRowDimension()
+         getArray()
+         getArrayCopy()
+         getColumnPackedCopy()
+         getRowPackedCopy()
+         get(int,int)
+         getMatrix(int,int,int,int)
+         getMatrix(int,int,int[])
+         getMatrix(int[],int,int)
+         getMatrix(int[],int[])
+         set(int,int,double)
+         setMatrix(int,int,int,int,Matrix)
+         setMatrix(int,int,int[],Matrix)
+         setMatrix(int[],int,int,Matrix)
+         setMatrix(int[],int[],Matrix)
+**/
+
+      print("\nTesting access methods...\n");
+
+/**
+      Various get methods:
+**/
+
+      B = new Matrix(avals);
+      if (B.getRowDimension() != rows) {
+         errorCount = try_failure(errorCount,"getRowDimension... ","");
+      } else {
+         try_success("getRowDimension... ","");
+      }
+      if (B.getColumnDimension() != cols) {
+         errorCount = try_failure(errorCount,"getColumnDimension... ","");
+      } else {
+         try_success("getColumnDimension... ","");
+      }
+      B = new Matrix(avals);
+      double[][] barray = B.getArray();
+      if ( barray != avals ) {
+         errorCount = try_failure(errorCount,"getArray... ","");
+      } else {
+         try_success("getArray... ","");
+      }
+      barray = B.getArrayCopy();
+      if ( barray == avals ) {
+         errorCount = try_failure(errorCount,"getArrayCopy... ","data not (deep) copied");
+      }
+      try {
+         check(barray,avals);
+         try_success("getArrayCopy... ","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"getArrayCopy... ","data not successfully (deep) copied");
+      }
+      double[] bpacked = B.getColumnPackedCopy();
+      try {
+         check(bpacked,columnwise);
+         try_success("getColumnPackedCopy... ","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"getColumnPackedCopy... ","data not successfully (deep) copied by columns");
+      }
+      bpacked = B.getRowPackedCopy();
+      try {
+         check(bpacked,rowwise);
+         try_success("getRowPackedCopy... ","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"getRowPackedCopy... ","data not successfully (deep) copied by rows");
+      }
+      try {
+         tmp = B.get(B.getRowDimension(),B.getColumnDimension()-1);
+         errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            tmp = B.get(B.getRowDimension()-1,B.getColumnDimension());
+            errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("get(int,int)... OutofBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown");
+      }
+      try {
+         if (B.get(B.getRowDimension()-1,B.getColumnDimension()-1) != 
+             avals[B.getRowDimension()-1][B.getColumnDimension()-1] ) {
+            errorCount = try_failure(errorCount,"get(int,int)... ","Matrix entry (i,j) not successfully retreived");
+         } else {
+            try_success("get(int,int)... ","");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"get(int,int)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      SUB = new Matrix(subavals);
+      try {
+         M = B.getMatrix(ib,ie+B.getRowDimension()+1,jb,je);
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            M = B.getMatrix(ib,ie,jb,je+B.getColumnDimension()+1);
+            errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("getMatrix(int,int,int,int)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      }
+      try {
+         M = B.getMatrix(ib,ie,jb,je);
+         try {
+            check(SUB,M);
+            try_success("getMatrix(int,int,int,int)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","submatrix not successfully retreived");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      
+      try {
+         M = B.getMatrix(ib,ie,badcolumnindexset);
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            M = B.getMatrix(ib,ie+B.getRowDimension()+1,columnindexset);
+            errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("getMatrix(int,int,int[])... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } 
+      try {
+         M = B.getMatrix(ib,ie,columnindexset);
+         try {
+            check(SUB,M);
+            try_success("getMatrix(int,int,int[])... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","submatrix not successfully retreived");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      try {
+         M = B.getMatrix(badrowindexset,jb,je);
+         errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            M = B.getMatrix(rowindexset,jb,je+B.getColumnDimension()+1);
+            errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("getMatrix(int[],int,int)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } 
+      try {
+         M = B.getMatrix(rowindexset,jb,je);
+         try {
+            check(SUB,M);
+            try_success("getMatrix(int[],int,int)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","submatrix not successfully retreived");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      try {
+         M = B.getMatrix(badrowindexset,columnindexset);
+         errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            M = B.getMatrix(rowindexset,badcolumnindexset);
+            errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("getMatrix(int[],int[])... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } 
+      try {
+         M = B.getMatrix(rowindexset,columnindexset);
+         try {
+            check(SUB,M);
+            try_success("getMatrix(int[],int[])... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","submatrix not successfully retreived");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+
+/**
+      Various set methods:
+**/
+
+      try {
+         B.set(B.getRowDimension(),B.getColumnDimension()-1,0.);
+         errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            B.set(B.getRowDimension()-1,B.getColumnDimension(),0.);
+            errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("set(int,int,double)... OutofBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown");
+      }
+      try {
+         B.set(ib,jb,0.);
+         tmp = B.get(ib,jb);
+         try {
+            check(tmp,0.);
+            try_success("set(int,int,double)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"set(int,int,double)... ","Matrix element not successfully set");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e1) {
+         errorCount = try_failure(errorCount,"set(int,int,double)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      M = new Matrix(2,3,0.);
+      try {
+         B.setMatrix(ib,ie+B.getRowDimension()+1,jb,je,M);
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            B.setMatrix(ib,ie,jb,je+B.getColumnDimension()+1,M);
+            errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("setMatrix(int,int,int,int,Matrix)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      }
+      try {
+         B.setMatrix(ib,ie,jb,je,M);
+         try {
+            check(M.minus(B.getMatrix(ib,ie,jb,je)),M);
+            try_success("setMatrix(int,int,int,int,Matrix)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","submatrix not successfully set");
+         }
+         B.setMatrix(ib,ie,jb,je,SUB);
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      try {
+         B.setMatrix(ib,ie+B.getRowDimension()+1,columnindexset,M);
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            B.setMatrix(ib,ie,badcolumnindexset,M);
+            errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("setMatrix(int,int,int[],Matrix)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      }
+      try {
+         B.setMatrix(ib,ie,columnindexset,M);
+         try {
+            check(M.minus(B.getMatrix(ib,ie,columnindexset)),M);
+            try_success("setMatrix(int,int,int[],Matrix)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","submatrix not successfully set");
+         }
+         B.setMatrix(ib,ie,jb,je,SUB);
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      try {
+         B.setMatrix(rowindexset,jb,je+B.getColumnDimension()+1,M);
+         errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            B.setMatrix(badrowindexset,jb,je,M);
+            errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("setMatrix(int[],int,int,Matrix)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      }
+      try {
+         B.setMatrix(rowindexset,jb,je,M);
+         try {
+            check(M.minus(B.getMatrix(rowindexset,jb,je)),M);
+            try_success("setMatrix(int[],int,int,Matrix)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","submatrix not successfully set");
+         }
+         B.setMatrix(ib,ie,jb,je,SUB);
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+      try {
+         B.setMatrix(rowindexset,badcolumnindexset,M);
+         errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e ) {
+         try {
+            B.setMatrix(badrowindexset,columnindexset,M);
+            errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+         } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+            try_success("setMatrix(int[],int[],Matrix)... ArrayIndexOutOfBoundsException... ","");
+         }
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown");
+      }
+      try {
+         B.setMatrix(rowindexset,columnindexset,M);
+         try {
+            check(M.minus(B.getMatrix(rowindexset,columnindexset)),M);
+            try_success("setMatrix(int[],int[],Matrix)... ","");
+         } catch ( java.lang.RuntimeException e ) {
+            errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","submatrix not successfully set");
+         }
+      } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) {
+         errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","Unexpected ArrayIndexOutOfBoundsException");
+      }
+
+/** 
+      Array-like methods:
+         minus
+         minusEquals
+         plus
+         plusEquals
+         arrayLeftDivide
+         arrayLeftDivideEquals
+         arrayRightDivide
+         arrayRightDivideEquals
+         arrayTimes
+         arrayTimesEquals
+         uminus
+**/
+
+      print("\nTesting array-like methods...\n");
+      S = new Matrix(columnwise,nonconformld);
+      R = Matrix.random(A.getRowDimension(),A.getColumnDimension());
+      A = R;
+      try {
+        S = A.minus(S);
+        errorCount = try_failure(errorCount,"minus conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("minus conformance check... ","");
+      }
+      if (A.minus(R).norm1() != 0.) {
+        errorCount = try_failure(errorCount,"minus... ","(difference of identical Matrices is nonzero,\nSubsequent use of minus should be suspect)");
+      } else {
+        try_success("minus... ","");
+      }
+      A = R.copy();
+      A.minusEquals(R);
+      Z = new Matrix(A.getRowDimension(),A.getColumnDimension());
+      try {
+        A.minusEquals(S);
+        errorCount = try_failure(errorCount,"minusEquals conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("minusEquals conformance check... ","");
+      }
+      if (A.minus(Z).norm1() != 0.) {
+        errorCount = try_failure(errorCount,"minusEquals... ","(difference of identical Matrices is nonzero,\nSubsequent use of minus should be suspect)");
+      } else {
+        try_success("minusEquals... ","");
+      }
+
+      A = R.copy();
+      B = Matrix.random(A.getRowDimension(),A.getColumnDimension());
+      C = A.minus(B); 
+      try {
+        S = A.plus(S);
+        errorCount = try_failure(errorCount,"plus conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("plus conformance check... ","");
+      }
+      try {
+        check(C.plus(B),A);
+        try_success("plus... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"plus... ","(C = A - B, but C + B != A)");
+      }
+      C = A.minus(B);
+      C.plusEquals(B);
+      try {
+        A.plusEquals(S);
+        errorCount = try_failure(errorCount,"plusEquals conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("plusEquals conformance check... ","");
+      }
+      try {
+        check(C,A);
+        try_success("plusEquals... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"plusEquals... ","(C = A - B, but C = C + B != A)");
+      }
+      A = R.uminus();
+      try {
+        check(A.plus(R),Z);
+        try_success("uminus... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"uminus... ","(-A + A != zeros)");
+      }
+      A = R.copy();
+      O = new Matrix(A.getRowDimension(),A.getColumnDimension(),1.0);
+      C = A.arrayLeftDivide(R);
+      try {
+        S = A.arrayLeftDivide(S);
+        errorCount = try_failure(errorCount,"arrayLeftDivide conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayLeftDivide conformance check... ","");
+      }
+      try {
+        check(C,O);
+        try_success("arrayLeftDivide... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayLeftDivide... ","(M.\\M != ones)");
+      }
+      try {
+        A.arrayLeftDivideEquals(S);
+        errorCount = try_failure(errorCount,"arrayLeftDivideEquals conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayLeftDivideEquals conformance check... ","");
+      }
+      A.arrayLeftDivideEquals(R);
+      try {
+        check(A,O);
+        try_success("arrayLeftDivideEquals... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayLeftDivideEquals... ","(M.\\M != ones)");
+      }
+      A = R.copy();
+      try {
+        A.arrayRightDivide(S);
+        errorCount = try_failure(errorCount,"arrayRightDivide conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayRightDivide conformance check... ","");
+      }
+      C = A.arrayRightDivide(R);
+      try {
+        check(C,O);
+        try_success("arrayRightDivide... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayRightDivide... ","(M./M != ones)");
+      }
+      try {
+        A.arrayRightDivideEquals(S);
+        errorCount = try_failure(errorCount,"arrayRightDivideEquals conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayRightDivideEquals conformance check... ","");
+      }
+      A.arrayRightDivideEquals(R);
+      try {
+        check(A,O);
+        try_success("arrayRightDivideEquals... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayRightDivideEquals... ","(M./M != ones)");
+      }
+      A = R.copy();
+      B = Matrix.random(A.getRowDimension(),A.getColumnDimension());
+      try {
+        S = A.arrayTimes(S);
+        errorCount = try_failure(errorCount,"arrayTimes conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayTimes conformance check... ","");
+      }
+      C = A.arrayTimes(B);
+      try {
+        check(C.arrayRightDivideEquals(B),A);
+        try_success("arrayTimes... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayTimes... ","(A = R, C = A.*B, but C./B != A)");
+      }
+      try {
+        A.arrayTimesEquals(S);
+        errorCount = try_failure(errorCount,"arrayTimesEquals conformance check... ","nonconformance not raised");
+      } catch ( IllegalArgumentException e ) {
+        try_success("arrayTimesEquals conformance check... ","");
+      }
+      A.arrayTimesEquals(B);
+      try {
+        check(A.arrayRightDivideEquals(B),R);
+        try_success("arrayTimesEquals... ","");
+      } catch ( java.lang.RuntimeException e ) {
+        errorCount = try_failure(errorCount,"arrayTimesEquals... ","(A = R, A = A.*B, but A./B != R)");
+      }
+
+/**   
+      I/O methods:
+         read
+         print
+         serializable:
+           writeObject
+           readObject
+**/
+      print("\nTesting I/O methods...\n");
+         try {
+            DecimalFormat fmt = new DecimalFormat("0.0000E00");
+	    fmt.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
+
+            PrintWriter FILE = new PrintWriter(new FileOutputStream("JamaTestMatrix.out"));
+            A.print(FILE,fmt,10);
+            FILE.close();
+            R = Matrix.read(new BufferedReader(new FileReader("JamaTestMatrix.out")));
+            if (A.minus(R).norm1() < .001 ) {
+               try_success("print()/read()...","");
+            } else {
+               errorCount = try_failure(errorCount,"print()/read()...","Matrix read from file does not match Matrix printed to file");
+            }
+         } catch ( java.io.IOException ioe ) {
+           warningCount = try_warning(warningCount,"print()/read()...","unexpected I/O error, unable to run print/read test;  check write permission in current directory and retry");
+         } catch(Exception e) {
+            try {
+               e.printStackTrace(System.out);
+               warningCount = try_warning(warningCount,"print()/read()...","Formatting error... will try JDK1.1 reformulation...");
+               DecimalFormat fmt = new DecimalFormat("0.0000");
+               PrintWriter FILE = new PrintWriter(new FileOutputStream("JamaTestMatrix.out"));
+               A.print(FILE,fmt,10);
+               FILE.close();
+               R = Matrix.read(new BufferedReader(new FileReader("JamaTestMatrix.out")));
+               if (A.minus(R).norm1() < .001 ) {
+                  try_success("print()/read()...","");
+               } else {
+                  errorCount = try_failure(errorCount,"print()/read() (2nd attempt) ...","Matrix read from file does not match Matrix printed to file");
+               }
+            } catch ( java.io.IOException ioe ) {
+              warningCount = try_warning(warningCount,"print()/read()...","unexpected I/O error, unable to run print/read test;  check write permission in current directory and retry");
+         }
+      }
+
+      R = Matrix.random(A.getRowDimension(),A.getColumnDimension());
+      String tmpname = "TMPMATRIX.serial";
+      try {
+         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(tmpname));
+         out.writeObject(R);
+         ObjectInputStream sin = new ObjectInputStream(new FileInputStream(tmpname));
+         A = (Matrix) sin.readObject();
+ 
+         try {
+            check(A,R);
+            try_success("writeObject(Matrix)/readObject(Matrix)...","");
+         } catch ( java.lang.RuntimeException e ) {
+           errorCount = try_failure(errorCount,"writeObject(Matrix)/readObject(Matrix)...","Matrix not serialized correctly");
+         }
+      } catch ( java.io.IOException ioe ) {
+         warningCount = try_warning(warningCount,"writeObject()/readObject()...","unexpected I/O error, unable to run serialization test;  check write permission in current directory and retry");
+      } catch(Exception e) {
+         errorCount = try_failure(errorCount,"writeObject(Matrix)/readObject(Matrix)...","unexpected error in serialization test");
+      }
+
+/**
+      LA methods:
+         transpose
+         times
+         cond
+         rank
+         det
+         trace
+         norm1
+         norm2
+         normF
+         normInf
+         solve
+         solveTranspose
+         inverse
+         chol
+         eig
+         lu
+         qr
+         svd 
+**/
+
+      print("\nTesting linear algebra methods...\n");
+      A = new Matrix(columnwise,3);
+      T = new Matrix(tvals);
+      T = A.transpose();
+      try {
+         check(A.transpose(),T);
+         try_success("transpose...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"transpose()...","transpose unsuccessful");
+      }
+      A.transpose();
+      try {
+         check(A.norm1(),columnsummax);
+         try_success("norm1...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"norm1()...","incorrect norm calculation");
+      }
+      try {
+         check(A.normInf(),rowsummax);
+         try_success("normInf()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"normInf()...","incorrect norm calculation");
+      }
+      try {
+         check(A.normF(),Math.sqrt(sumofsquares));
+         try_success("normF...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"normF()...","incorrect norm calculation");
+      }
+      try {
+         check(A.trace(),sumofdiagonals);
+         try_success("trace()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"trace()...","incorrect trace calculation");
+      }
+      try {
+         check(A.getMatrix(0,A.getRowDimension()-1,0,A.getRowDimension()-1).det(),0.);
+         try_success("det()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"det()...","incorrect determinant calculation");
+      }
+      SQ = new Matrix(square);
+      try {
+         check(A.times(A.transpose()),SQ);
+         try_success("times(Matrix)...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"times(Matrix)...","incorrect Matrix-Matrix product calculation");
+      }
+      try {
+         check(A.times(0.),Z);
+         try_success("times(double)...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"times(double)...","incorrect Matrix-scalar product calculation");
+      }
+
+      A = new Matrix(columnwise,4);
+      QRDecomposition QR = A.qr();
+      R = QR.getR();
+      try {
+         check(A,QR.getQ().times(R));
+         try_success("QRDecomposition...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"QRDecomposition...","incorrect QR decomposition calculation");
+      }
+      SingularValueDecomposition SVD = A.svd();
+      try {
+         check(A,SVD.getU().times(SVD.getS().times(SVD.getV().transpose())));
+         try_success("SingularValueDecomposition...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation");
+      }
+      DEF = new Matrix(rankdef);
+      try {
+         check(DEF.rank(),Math.min(DEF.getRowDimension(),DEF.getColumnDimension())-1);
+         try_success("rank()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"rank()...","incorrect rank calculation");
+      }
+      B = new Matrix(condmat);
+      SVD = B.svd(); 
+      double [] singularvalues = SVD.getSingularValues();
+      try {
+         check(B.cond(),singularvalues[0]/singularvalues[Math.min(B.getRowDimension(),B.getColumnDimension())-1]);
+         try_success("cond()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"cond()...","incorrect condition number calculation");
+      }
+      int n = A.getColumnDimension();
+      A = A.getMatrix(0,n-1,0,n-1);
+      A.set(0,0,0.);
+      LUDecomposition LU = A.lu();
+      try {
+         check(A.getMatrix(LU.getPivot(),0,n-1),LU.getL().times(LU.getU()));
+         try_success("LUDecomposition...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"LUDecomposition...","incorrect LU decomposition calculation");
+      }
+      X = A.inverse();
+      try {
+         check(A.times(X),Matrix.identity(3,3));
+         try_success("inverse()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"inverse()...","incorrect inverse calculation");
+      }
+      O = new Matrix(SUB.getRowDimension(),1,1.0);
+      SOL = new Matrix(sqSolution);
+      SQ = SUB.getMatrix(0,SUB.getRowDimension()-1,0,SUB.getRowDimension()-1);
+      try {
+         check(SQ.solve(SOL),O); 
+         try_success("solve()...","");
+      } catch ( java.lang.IllegalArgumentException e1 ) {
+         errorCount = try_failure(errorCount,"solve()...",e1.getMessage());
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"solve()...",e.getMessage());
+      }
+      A = new Matrix(pvals);
+      CholeskyDecomposition Chol = A.chol(); 
+      Matrix L = Chol.getL();
+      try {
+         check(A,L.times(L.transpose()));
+         try_success("CholeskyDecomposition...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation");
+      }
+      X = Chol.solve(Matrix.identity(3,3));
+      try {
+         check(A.times(X),Matrix.identity(3,3));
+         try_success("CholeskyDecomposition solve()...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation");
+      }
+      EigenvalueDecomposition Eig = A.eig();
+      Matrix D = Eig.getD();
+      Matrix V = Eig.getV();
+      try {
+         check(A.times(V),V.times(D));
+         try_success("EigenvalueDecomposition (symmetric)...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation");
+      }
+      A = new Matrix(evals);
+      Eig = A.eig();
+      D = Eig.getD();
+      V = Eig.getV();
+      try {
+         check(A.times(V),V.times(D));
+         try_success("EigenvalueDecomposition (nonsymmetric)...","");
+      } catch ( java.lang.RuntimeException e ) {
+         errorCount = try_failure(errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation");
+      }
+
+      print("\nTestMatrix completed.\n");
+      print("Total errors reported: " + Integer.toString(errorCount) + "\n");
+      print("Total warnings reported: " + Integer.toString(warningCount) + "\n");
+   }
+
+   /** private utility routines **/
+
+   /** Check magnitude of difference of scalars. **/
+
+   private static void check(double x, double y) {
+      double eps = Math.pow(2.0,-52.0);
+      if (x == 0 & Math.abs(y) < 10*eps) return;
+      if (y == 0 & Math.abs(x) < 10*eps) return;
+      if (Math.abs(x-y) > 10*eps*Math.max(Math.abs(x),Math.abs(y))) {
+         throw new RuntimeException("The difference x-y is too large: x = " + Double.toString(x) + "  y = " + Double.toString(y));
+      }
+   }
+
+   /** Check norm of difference of "vectors". **/
+
+   private static void check(double[] x, double[] y) {
+      if (x.length == y.length ) {
+         for (int i=0;i<x.length;i++) {
+            check(x[i],y[i]);
+         } 
+      } else {
+         throw new RuntimeException("Attempt to compare vectors of different lengths");
+      }
+   }
+
+   /** Check norm of difference of arrays. **/
+
+   private static void check(double[][] x, double[][] y) {
+      Matrix A = new Matrix(x);
+      Matrix B = new Matrix(y);
+      check(A,B);
+   }
+
+   /** Check norm of difference of Matrices. **/
+
+   private static void check(Matrix X, Matrix Y) {
+      double eps = Math.pow(2.0,-52.0);
+      if (X.norm1() == 0. & Y.norm1() < 10*eps) return;
+      if (Y.norm1() == 0. & X.norm1() < 10*eps) return;
+      if (X.minus(Y).norm1() > 1000*eps*Math.max(X.norm1(),Y.norm1())) {
+         throw new RuntimeException("The norm of (X-Y) is too large: " +  Double.toString(X.minus(Y).norm1()));
+      }
+   }
+
+   /** Shorten spelling of print. **/
+
+   private static void print (String s) {
+      System.out.print(s);
+   }
+
+  /** Print appropriate messages for successful outcome try **/
+
+   private static void try_success (String s,String e) {
+      print(">    " + s + "success\n");
+      if ( e != "" ) {
+        print(">      Message: " + e + "\n");
+      }
+   }
+  /** Print appropriate messages for unsuccessful outcome try **/
+
+   private static int try_failure (int count, String s,String e) {
+      print(">    " + s + "*** failure ***\n>      Message: " + e + "\n");
+      return ++count;
+   }
+
+  /** Print appropriate messages for unsuccessful outcome try **/
+
+   private static int try_warning (int count, String s,String e) {
+      print(">    " + s + "*** warning ***\n>      Message: " + e + "\n");
+      return ++count;
+   }
+
+   /** Print a row vector. **/
+
+   private static void print(double[] x, int w, int d) {
+      // Use format Fw.d for all elements.
+      System.out.print("\n");
+      new Matrix(x,1).print(w,d);
+      print("\n");
+   }
+
+}
diff --git a/LibrarySource/Jama/util/Maths.java b/LibrarySource/Jama/util/Maths.java
new file mode 100644
index 0000000..2fb6ff5
--- /dev/null
+++ b/LibrarySource/Jama/util/Maths.java
@@ -0,0 +1,21 @@
+package Jama.util;
+
+public class Maths {
+
+   /** sqrt(a^2 + b^2) without under/overflow. **/
+
+   public static double hypot(double a, double b) {
+      double r;
+      if (Math.abs(a) > Math.abs(b)) {
+         r = b/a;
+         r = Math.abs(a)*Math.sqrt(1+r*r);
+      } else if (b != 0) {
+         r = a/b;
+         r = Math.abs(b)*Math.sqrt(1+r*r);
+      } else {
+         r = 0.0;
+      }
+      return r;
+   }
+}
+
diff --git a/LibrarySource/com/lowagie/text/Anchor.java b/LibrarySource/com/lowagie/text/Anchor.java
new file mode 100644
index 0000000..2248358
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Anchor.java
@@ -0,0 +1,366 @@
+/*
+ * $Id: Anchor.java,v 1.84 2005/05/03 13:03:49 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * An <CODE>Anchor</CODE> can be a reference or a destination of a reference.
+ * <P>
+ * An <CODE>Anchor</CODE> is a special kind of <CODE>Phrase</CODE>.
+ * It is constructed in the same way.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>Anchor anchor = new Anchor("this is a link");</STRONG>
+ * <STRONG>anchor.setName("LINK");</STRONG>
+ * <STRONG>anchor.setReference("http://www.lowagie.com");</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * @see		Element
+ * @see		Phrase
+ */
+
+public class Anchor extends Phrase implements TextElementArray, MarkupAttributes {
+    
+    // membervariables
+    
+/** This is the anchor tag. */
+    public static final String ANCHOR = "anchor";
+    
+/** This is the name of the <CODE>Anchor</CODE>. */
+    protected String name = null;
+    
+/** This is the reference of the <CODE>Anchor</CODE>. */
+    protected String reference = null;
+    
+    // constructors
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> without specifying a leading.
+ */
+    
+    public Anchor() {
+        super(16);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain leading.
+ *
+ * @param	leading		the leading
+ */
+    
+    public Anchor(float leading) {
+        super(leading);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain <CODE>Chunk</CODE>.
+ *
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Anchor(Chunk chunk) {
+        super(chunk);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain <CODE>String</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Anchor(String string) {
+        super(string);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain <CODE>String</CODE>
+ * and a certain <CODE>Font</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Anchor(String string, Font font) {
+        super(string, font);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain <CODE>Chunk</CODE>
+ * and a certain leading.
+ *
+ * @param	leading		the leading
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Anchor(float leading, Chunk chunk) {
+        super(leading, chunk);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain leading
+ * and a certain <CODE>String</CODE>.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Anchor(float leading, String string) {
+        super(leading, string);
+    }
+    
+/**
+ * Constructs an <CODE>Anchor</CODE> with a certain leading,
+ * a certain <CODE>String</CODE> and a certain <CODE>Font</CODE>.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Anchor(float leading, String string, Font font) {
+        super(leading, string, font);
+    }
+    
+/**
+ * Returns an <CODE>Anchor</CODE> that has been constructed taking in account
+ * the value of some <VAR>attributes</VAR>.
+ *
+ * @param	attributes		Some attributes
+ */
+    
+    public Anchor(Properties attributes) {
+        this("", FontFactory.getFont(attributes));
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+            Chunk chunk = new Chunk(value);
+            if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+                chunk.setGenericTag(value);
+            }
+            add(chunk);
+        }
+        if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+            setLeading(Float.valueOf(value + "f").floatValue());
+        }
+        else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+            setLeading(MarkupParser.parseLength(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.NAME)) != null) {
+            setName(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.REFERENCE)) != null) {
+            setReference(value);
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            Chunk chunk;
+            Iterator i = getChunks().iterator();
+            boolean localDestination = (reference != null && reference.startsWith("#"));
+            boolean notGotoOK = true;
+            while (i.hasNext()) {
+                chunk = (Chunk) i.next();
+                if (name != null && notGotoOK && !chunk.isEmpty()) {
+                    chunk.setLocalDestination(name);
+                    notGotoOK = false;
+                }
+                if (localDestination) {
+                    chunk.setLocalGoto(reference.substring(1));
+                }
+                listener.add(chunk);
+            }
+            return true;
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        ArrayList tmp = new ArrayList();
+        Chunk chunk;
+        Iterator i = iterator();
+        boolean localDestination = (reference != null && reference.startsWith("#"));
+        boolean notGotoOK = true;
+        while (i.hasNext()) {
+            chunk = (Chunk) i.next();
+            if (name != null && notGotoOK && !chunk.isEmpty()) {
+                chunk.setLocalDestination(name);
+                notGotoOK = false;
+            }
+            if (localDestination) {
+                chunk.setLocalGoto(reference.substring(1));
+            }
+            else if (reference != null)
+                chunk.setAnchor(reference);
+            tmp.add(chunk);
+        }
+        return tmp;
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.ANCHOR;
+    }
+    
+    // methods
+    
+/**
+ * Gets an iterator of <CODE>Element</CODE>s.
+ *
+ * @return	an <CODE>Iterator</CODE>
+ */
+    
+    // suggestion by by Curt Thompson
+    public Iterator getElements() {
+        return this.iterator();
+    }
+    
+/**
+ * Sets the name of this <CODE>Anchor</CODE>.
+ *
+ * @param	name		a new name
+ */
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+/**
+ * Sets the reference of this <CODE>Anchor</CODE>.
+ *
+ * @param	reference		a new reference
+ */
+    
+    public void setReference(String reference) {
+        this.reference = reference;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns the name of this <CODE>Anchor</CODE>.
+ *
+ * @return	a name
+ */
+    
+    public String name() {
+        return name;
+    }
+    
+/**
+ * Gets the reference of this <CODE>Anchor</CODE>.
+ *
+ * @return	a reference
+ */
+    
+    public String reference() {
+        return reference;
+    }
+    
+/**
+ * Gets the reference of this <CODE>Anchor</CODE>.
+ *
+ * @return	an <CODE>URL</CODE>
+ */
+    
+    public URL url() {
+        try {
+            return new URL(reference);
+        }
+        catch(MalformedURLException mue) {
+            return null;
+        }
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.ANCHOR.equals(tag);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/Annotation.java b/LibrarySource/com/lowagie/text/Annotation.java
new file mode 100644
index 0000000..557a8be
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Annotation.java
@@ -0,0 +1,727 @@
+/*
+ * $Id: Annotation.java,v 1.70 2005/04/13 09:17:09 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * An <CODE>Annotation</CODE> is a little note that can be added to a page on
+ * a document.
+ * 
+ * @see Element
+ * @see Anchor
+ */
+
+public class Annotation implements Element, MarkupAttributes {
+
+	// membervariables
+
+	/** This is a possible annotation type. */
+	public static final int TEXT = 0;
+
+	/** This is a possible annotation type. */
+	public static final int URL_NET = 1;
+
+	/** This is a possible annotation type. */
+	public static final int URL_AS_STRING = 2;
+
+	/** This is a possible annotation type. */
+	public static final int FILE_DEST = 3;
+
+	/** This is a possible annotation type. */
+	public static final int FILE_PAGE = 4;
+
+	/** This is a possible annotation type. */
+	public static final int NAMED_DEST = 5;
+
+	/** This is a possible annotation type. */
+	public static final int LAUNCH = 6;
+
+	/** This is a possible annotation type. */
+	public static final int SCREEN = 7;
+
+	/** This is a possible attribute. */
+	public static String TITLE = "title";
+
+	/** This is a possible attribute. */
+	public static String CONTENT = "content";
+
+	/** This is a possible attribute. */
+	public static String URL = "url";
+
+	/** This is a possible attribute. */
+	public static String FILE = "file";
+
+	/** This is a possible attribute. */
+	public static String DESTINATION = "destination";
+
+	/** This is a possible attribute. */
+	public static String PAGE = "page";
+
+	/** This is a possible attribute. */
+	public static String NAMED = "named";
+
+	/** This is a possible attribute. */
+	public static String APPLICATION = "application";
+
+	/** This is a possible attribute. */
+	public static String PARAMETERS = "parameters";
+
+	/** This is a possible attribute. */
+	public static String OPERATION = "operation";
+
+	/** This is a possible attribute. */
+	public static String DEFAULTDIR = "defaultdir";
+
+	/** This is a possible attribute. */
+	public static String LLX = "llx";
+
+	/** This is a possible attribute. */
+	public static String LLY = "lly";
+
+	/** This is a possible attribute. */
+	public static String URX = "urx";
+
+	/** This is a possible attribute. */
+	public static String URY = "ury";
+
+	/** This is a possible attribute. */
+	public static String MIMETYPE = "mime";
+
+	/** This is the type of annotation. */
+	protected int annotationtype;
+
+	/** This is the title of the <CODE>Annotation</CODE>. */
+	protected HashMap annotationAttributes = new HashMap();
+
+	/** Contains extra markupAttributes */
+	protected Properties markupAttributes = null;
+
+	/** This is the lower left x-value */
+	protected float llx = Float.NaN;
+
+	/** This is the lower left y-value */
+	protected float lly = Float.NaN;
+
+	/** This is the upper right x-value */
+	protected float urx = Float.NaN;
+
+	/** This is the upper right y-value */
+	protected float ury = Float.NaN;
+
+	// constructors
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE> with a certain title and some
+	 * text.
+	 * 
+	 * @param llx
+	 *            lower left x coordinate
+	 * @param lly
+	 *            lower left y coordinate
+	 * @param urx
+	 *            upper right x coordinate
+	 * @param ury
+	 *            upper right y coordinate
+	 */
+
+	private Annotation(float llx, float lly, float urx, float ury) {
+		this.llx = llx;
+		this.lly = lly;
+		this.urx = urx;
+		this.ury = ury;
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE> with a certain title and some
+	 * text.
+	 * 
+	 * @param title
+	 *            the title of the annotation
+	 * @param text
+	 *            the content of the annotation
+	 */
+
+	public Annotation(String title, String text) {
+		annotationtype = TEXT;
+		annotationAttributes.put(TITLE, title);
+		annotationAttributes.put(CONTENT, text);
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE> with a certain title and some
+	 * text.
+	 * 
+	 * @param title
+	 *            the title of the annotation
+	 * @param text
+	 *            the content of the annotation
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 */
+
+	public Annotation(String title, String text, float llx, float lly,
+			float urx, float ury) {
+		this(llx, lly, urx, ury);
+		annotationtype = TEXT;
+		annotationAttributes.put(TITLE, title);
+		annotationAttributes.put(CONTENT, text);
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param url
+	 *            the external reference
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury, URL url) {
+		this(llx, lly, urx, ury);
+		annotationtype = URL_NET;
+		annotationAttributes.put(URL, url);
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param url
+	 *            the external reference
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury, String url) {
+		this(llx, lly, urx, ury);
+		annotationtype = URL_AS_STRING;
+		annotationAttributes.put(FILE, url);
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param file
+	 *            an external PDF file
+	 * @param dest
+	 *            the destination in this file
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury, String file,
+			String dest) {
+		this(llx, lly, urx, ury);
+		annotationtype = FILE_DEST;
+		annotationAttributes.put(FILE, file);
+		annotationAttributes.put(DESTINATION, dest);
+	}
+
+	/**
+	 * Creates a Screen anotation to embed media clips
+	 * 
+	 * @param llx
+	 * @param lly
+	 * @param urx
+	 * @param ury
+	 * @param moviePath
+	 *            path to the media clip file
+	 * @param mimeType
+	 *            mime type of the media
+	 * @param showOnDisplay
+	 *            if true play on display of the page
+	 */
+	public Annotation(float llx, float lly, float urx, float ury,
+			String moviePath, String mimeType, boolean showOnDisplay) {
+		this(llx, lly, urx, ury);
+		annotationtype = SCREEN;
+		annotationAttributes.put(FILE, moviePath);
+		annotationAttributes.put(MIMETYPE, mimeType);
+		annotationAttributes.put(PARAMETERS, new boolean[] {
+				false /* embedded */, showOnDisplay });
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param file
+	 *            an external PDF file
+	 * @param page
+	 *            a page number in this file
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury, String file,
+			int page) {
+		this(llx, lly, urx, ury);
+		annotationtype = FILE_PAGE;
+		annotationAttributes.put(FILE, file);
+		annotationAttributes.put(PAGE, new Integer(page));
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param named
+	 *            a named destination in this file
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury, int named) {
+		this(llx, lly, urx, ury);
+		annotationtype = NAMED_DEST;
+		annotationAttributes.put(NAMED, new Integer(named));
+	}
+
+	/**
+	 * Constructs an <CODE>Annotation</CODE>.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 * @param application
+	 *            an external application
+	 * @param parameters
+	 *            parameters to pass to this application
+	 * @param operation
+	 *            the operation to pass to this application
+	 * @param defaultdir
+	 *            the default directory to run this application in
+	 */
+
+	public Annotation(float llx, float lly, float urx, float ury,
+			String application, String parameters, String operation,
+			String defaultdir) {
+		this(llx, lly, urx, ury);
+		annotationtype = LAUNCH;
+		annotationAttributes.put(APPLICATION, application);
+		annotationAttributes.put(PARAMETERS, parameters);
+		annotationAttributes.put(OPERATION, operation);
+		annotationAttributes.put(DEFAULTDIR, defaultdir);
+	}
+
+	/**
+	 * Returns an <CODE>Annotation</CODE> that has been constructed taking in
+	 * account the value of some <VAR>attributes </VAR>.
+	 * 
+	 * @param attributes
+	 *            Some attributes
+	 */
+
+	public Annotation(Properties attributes) {
+		String value = (String) attributes.remove(ElementTags.LLX);
+		if (value != null) {
+			llx = Float.valueOf(value + "f").floatValue();
+		}
+		value = (String) attributes.remove(ElementTags.LLY);
+		if (value != null) {
+			lly = Float.valueOf(value + "f").floatValue();
+		}
+		value = (String) attributes.remove(ElementTags.URX);
+		if (value != null) {
+			urx = Float.valueOf(value + "f").floatValue();
+		}
+		value = (String) attributes.remove(ElementTags.URY);
+		if (value != null) {
+			ury = Float.valueOf(value + "f").floatValue();
+		}
+		String title = (String) attributes.remove(ElementTags.TITLE);
+		String text = (String) attributes.remove(ElementTags.CONTENT);
+		if (title != null || text != null) {
+			annotationtype = TEXT;
+		} else if ((value = (String) attributes.remove(ElementTags.URL)) != null) {
+			annotationtype = URL_AS_STRING;
+			annotationAttributes.put(FILE, value);
+		} else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
+			annotationtype = NAMED_DEST;
+			annotationAttributes.put(NAMED, Integer.valueOf(value));
+		} else {
+			String file = (String) attributes.remove(ElementTags.FILE);
+			String destination = (String) attributes
+					.remove(ElementTags.DESTINATION);
+			String page = (String) attributes.remove(ElementTags.PAGE);
+			if (file != null) {
+				annotationAttributes.put(FILE, file);
+				if (destination != null) {
+					annotationtype = FILE_DEST;
+					annotationAttributes.put(DESTINATION, destination);
+				} else if (page != null) {
+					annotationtype = FILE_PAGE;
+					annotationAttributes.put(FILE, file);
+					annotationAttributes.put(PAGE, Integer.valueOf(page));
+				}
+			} else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
+				annotationtype = LAUNCH;
+				annotationAttributes.put(APPLICATION, value);
+				annotationAttributes.put(PARAMETERS, (String) attributes
+						.remove(ElementTags.PARAMETERS));
+				annotationAttributes.put(OPERATION, (String) attributes
+						.remove(ElementTags.OPERATION));
+				annotationAttributes.put(DEFAULTDIR, (String) attributes
+						.remove(ElementTags.DEFAULTDIR));
+			}
+		}
+		if (annotationtype == TEXT) {
+			if (title == null)
+				title = "";
+			if (text == null)
+				text = "";
+			annotationAttributes.put(TITLE, title);
+			annotationAttributes.put(CONTENT, text);
+		}
+		if (attributes.size() > 0)
+			setMarkupAttributes(attributes);
+	}
+
+	// implementation of the Element-methods
+
+	/**
+	 * Gets the type of the text element.
+	 * 
+	 * @return a type
+	 */
+
+	public int type() {
+		return Element.ANNOTATION;
+	}
+
+	// methods
+
+	/**
+	 * Processes the element by adding it (or the different parts) to an <CODE>
+	 * ElementListener</CODE>.
+	 * 
+	 * @param listener
+	 *            an <CODE>ElementListener</CODE>
+	 * @return <CODE>true</CODE> if the element was processed successfully
+	 */
+
+	public boolean process(ElementListener listener) {
+		try {
+			return listener.add(this);
+		} catch (DocumentException de) {
+			return false;
+		}
+	}
+
+	/**
+	 * Gets all the chunks in this element.
+	 * 
+	 * @return an <CODE>ArrayList</CODE>
+	 */
+
+	public ArrayList getChunks() {
+		return new ArrayList();
+	}
+
+	// methods
+
+	/**
+	 * Sets the dimensions of this annotation.
+	 * 
+	 * @param llx
+	 *            the lower left x-value
+	 * @param lly
+	 *            the lower left y-value
+	 * @param urx
+	 *            the upper right x-value
+	 * @param ury
+	 *            the upper right y-value
+	 */
+
+	public void setDimensions(float llx, float lly, float urx, float ury) {
+		this.llx = llx;
+		this.lly = lly;
+		this.urx = urx;
+		this.ury = ury;
+	}
+
+	// methods to retrieve information
+
+	/**
+	 * Returns the lower left x-value.
+	 * 
+	 * @return a value
+	 */
+
+	public float llx() {
+		return llx;
+	}
+
+	/**
+	 * Returns the lower left y-value.
+	 * 
+	 * @return a value
+	 */
+
+	public float lly() {
+		return lly;
+	}
+
+	/**
+	 * Returns the uppper right x-value.
+	 * 
+	 * @return a value
+	 */
+
+	public float urx() {
+		return urx;
+	}
+
+	/**
+	 * Returns the uppper right y-value.
+	 * 
+	 * @return a value
+	 */
+
+	public float ury() {
+		return ury;
+	}
+
+	/**
+	 * Returns the lower left x-value.
+	 * 
+	 * @param def
+	 *            the default value
+	 * @return a value
+	 */
+
+	public float llx(float def) {
+		if (Float.isNaN(llx))
+			return def;
+		return llx;
+	}
+
+	/**
+	 * Returns the lower left y-value.
+	 * 
+	 * @param def
+	 *            the default value
+	 * @return a value
+	 */
+
+	public float lly(float def) {
+		if (Float.isNaN(lly))
+			return def;
+		return lly;
+	}
+
+	/**
+	 * Returns the upper right x-value.
+	 * 
+	 * @param def
+	 *            the default value
+	 * @return a value
+	 */
+
+	public float urx(float def) {
+		if (Float.isNaN(urx))
+			return def;
+		return urx;
+	}
+
+	/**
+	 * Returns the upper right y-value.
+	 * 
+	 * @param def
+	 *            the default value
+	 * @return a value
+	 */
+
+	public float ury(float def) {
+		if (Float.isNaN(ury))
+			return def;
+		return ury;
+	}
+
+	/**
+	 * Returns the type of this <CODE>Annotation</CODE>.
+	 * 
+	 * @return a type
+	 */
+
+	public int annotationType() {
+		return annotationtype;
+	}
+
+	/**
+	 * Returns the title of this <CODE>Annotation</CODE>.
+	 * 
+	 * @return a name
+	 */
+
+	public String title() {
+		String s = (String) annotationAttributes.get(TITLE);
+		if (s == null)
+			s = "";
+		return s;
+	}
+
+	/**
+	 * Gets the content of this <CODE>Annotation</CODE>.
+	 * 
+	 * @return a reference
+	 */
+
+	public String content() {
+		String s = (String) annotationAttributes.get(CONTENT);
+		if (s == null)
+			s = "";
+		return s;
+	}
+
+	/**
+	 * Gets the content of this <CODE>Annotation</CODE>.
+	 * 
+	 * @return a reference
+	 */
+
+	public HashMap attributes() {
+		return annotationAttributes;
+	}
+
+	/**
+	 * Checks if a given tag corresponds with this object.
+	 * 
+	 * @param tag
+	 *            the given tag
+	 * @return true if the tag corresponds
+	 */
+
+	public static boolean isTag(String tag) {
+		return ElementTags.ANNOTATION.equals(tag);
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
+	 *      java.lang.String)
+	 */
+	public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+		markupAttributes.put(name, value);
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+	 */
+	public void setMarkupAttributes(Properties markupAttributes) {
+		this.markupAttributes = markupAttributes;
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+	 */
+	public String getMarkupAttribute(String name) {
+		return (markupAttributes == null) ? null : String
+				.valueOf(markupAttributes.get(name));
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+	 */
+	public Set getMarkupAttributeNames() {
+		return Chunk.getKeySet(markupAttributes);
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+	 */
+	public Properties getMarkupAttributes() {
+		return markupAttributes;
+	}
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/BadElementException.java b/LibrarySource/com/lowagie/text/BadElementException.java
new file mode 100644
index 0000000..a8dec67
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/BadElementException.java
@@ -0,0 +1,89 @@
+/*
+ * $Id: BadElementException.java,v 1.50 2004/12/14 11:33:49 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * Signals an attempt to create an <CODE>Element</CODE> that hasn't got the right form.
+ *
+ * @see		DocumentException
+ * @see		Cell
+ * @see		Table
+ */
+
+public class BadElementException extends DocumentException {
+    
+    // constructors
+    /**
+     * Constructs a BadElementException
+     * @param ex an Exception object that has to be turned into a BadElementException
+     */
+    public BadElementException(Exception ex) {
+        super(ex);
+    }
+    
+/**
+ * Constructs a <CODE>BadElementException</CODE> whithout a message.
+ */
+    
+    BadElementException() {
+        super();
+    }
+    
+/**
+ * Constructs a <code>BadElementException</code> with a message.
+ *
+ * @param		message			a message describing the exception
+ */
+    
+    public BadElementException(String message) {
+        super(message);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/Cell.java b/LibrarySource/com/lowagie/text/Cell.java
new file mode 100644
index 0000000..3306f36
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Cell.java
@@ -0,0 +1,1006 @@
+/*
+ * $Id: Cell.java,v 1.101 2005/04/28 13:20:11 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+
+import com.lowagie.text.markup.*;
+import com.lowagie.text.pdf.PdfPCell;
+
+/**
+ * A <CODE>Cell</CODE> is a <CODE>Rectangle</CODE> containing other
+ * <CODE>Element</CODE>s.
+ * <P>
+ * A <CODE>Cell</CODE> must be added to a <CODE>Table</CODE>.
+ * The <CODE>Table</CODE> will place the <CODE>Cell</CODE> in
+ * a <CODE>Row</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * Table table = new Table(3);
+ * table.setBorderWidth(1);
+ * table.setBorderColor(new Color(0, 0, 255));
+ * table.setCellpadding(5);
+ * table.setCellspacing(5);
+ * <STRONG>Cell cell = new Cell("header");</STRONG>
+ * <STRONG>cell.setHeader(true);</STRONG>
+ * <STRONG>cell.setColspan(3);</STRONG>
+ * table.addCell(cell);
+ * <STRONG>cell = new Cell("example cell with colspan 1 and rowspan 2");</STRONG>
+ * <STRONG>cell.setRowspan(2);</STRONG>
+ * <STRONG>cell.setBorderColor(new Color(255, 0, 0));</STRONG>
+ * table.addCell(cell);
+ * table.addCell("1.1");
+ * table.addCell("2.1");
+ * table.addCell("1.2");
+ * table.addCell("2.2");
+ * </PRE></BLOCKQUOTE>
+ *
+ * @see		Rectangle
+ * @see		Element
+ * @see		Table
+ * @see		Row
+ */
+
+public class Cell extends Rectangle implements TextElementArray {
+
+	// static final membervariable
+
+    // This accessor replaces the dangerous static member DUMMY_CELL
+    /**
+     * Get dummy cell used when merging inner tables. 
+     * @return a cell with colspan 3 and no border
+     */
+    public static Cell getDummyCell() {
+        Cell cell = new Cell(true);
+        cell.setColspan(3);
+        cell.setBorder(NO_BORDER);
+        return cell;
+	}
+
+	// membervariables
+
+/** This is the <CODE>ArrayList</CODE> of <CODE>Element</CODE>s. */
+	protected ArrayList arrayList = null;
+
+/** This is the horizontal alignment. */
+	protected int horizontalAlignment = Element.ALIGN_UNDEFINED;
+
+/** This is the vertical alignment. */
+	protected int verticalAlignment = Element.ALIGN_UNDEFINED;
+
+/** This is the vertical alignment. */
+	protected String width;
+
+/** This is the colspan. */
+	protected int colspan = 1;
+
+/** This is the rowspan. */
+	protected int rowspan = 1;
+
+/** This is the leading. */
+	float leading = Float.NaN;
+
+/** Is this <CODE>Cell</CODE> a header? */
+	protected boolean header;
+
+    /** Indicates that the largest ascender height should be used to determine the
+     * height of the first line.  Note that this only has an effect when rendered
+     * to PDF.  Setting this to true can help with vertical alignment problems. */
+    protected boolean useAscender = false;
+
+    /** Indicates that the largest descender height should be added to the height of
+     * the last line (so characters like y don't dip into the border).   Note that
+     * this only has an effect when rendered to PDF. */
+    protected boolean useDescender = false;
+
+    /**
+     * Adjusts the cell contents to compensate for border widths.  Note that
+     * this only has an effect when rendered to PDF.
+     */
+    protected boolean useBorderPadding;
+
+	// constructors
+
+/**
+ * Constructs an empty <CODE>Cell</CODE>.
+ */
+
+	public Cell() {
+		// creates a Rectangle with BY DEFAULT a border of 0.5
+		super(0, 0, 0, 0);
+		setBorder(UNDEFINED);
+		setBorderWidth(0.5f);
+
+		// initializes the arraylist and adds an element
+		arrayList = new ArrayList();
+	}
+
+/**
+ * Constructs an empty <CODE>Cell</CODE> (for internal use only).
+ *
+ * @param   dummy   a dummy value
+ */
+
+	public Cell(boolean dummy) {
+		this();
+		arrayList.add(new Paragraph(0));
+	}
+
+/**
+ * Constructs a <CODE>Cell</CODE> with a certain content.
+ * <P>
+ * The <CODE>String</CODE> will be converted into a <CODE>Paragraph</CODE>.
+ *
+ * @param	content		a <CODE>String</CODE>
+ */
+
+	public Cell(String content) {
+		// creates a Rectangle with BY DEFAULT a border of 0.5
+		super(0, 0, 0, 0);
+		setBorder(UNDEFINED);
+		setBorderWidth(0.5f);
+
+		// initializes the arraylist and adds an element
+		arrayList = new ArrayList();
+		try {
+			addElement(new Paragraph(content));
+		}
+		catch(BadElementException bee) {
+		}
+	}
+
+/**
+ * Constructs a <CODE>Cell</CODE> with a certain <CODE>Element</CODE>.
+ * <P>
+ * if the element is a <CODE>ListItem</CODE>, <CODE>Row</CODE> or
+ * <CODE>Cell</CODE>, an exception will be thrown.
+ *
+ * @param	element		the element
+ * @throws	BadElementException when the creator was called with a <CODE>ListItem</CODE>, <CODE>Row</CODE> or <CODE>Cell</CODE>
+ */
+
+	public Cell(Element element) throws BadElementException {
+		// creates a Rectangle with BY DEFAULT a border of 0.5
+		super(0, 0, 0, 0);
+		setBorder(UNDEFINED);
+		setBorderWidth(0.5f);
+
+ 		// Update by Benoit WIART <b.wiart at proxiad.com>
+ 		if(element instanceof Phrase) {
+			Phrase p = (Phrase)element;
+			leading = p.leading();
+		}
+
+		// initializes the arraylist and adds an element
+		arrayList = new ArrayList();
+		addElement(element);
+	}
+
+/**
+ * Returns a <CODE>Cell</CODE> that has been constructed taking in account
+ * the value of some <VAR>attributes</VAR>.
+ *
+ * @param	attributes		Some attributes
+ */
+
+	public Cell(Properties attributes) {
+		this();
+		String value;
+		if ((value = (String)attributes.remove(ElementTags.HORIZONTALALIGN)) != null) {
+			setHorizontalAlignment(value);
+		}
+		if ((value = (String)attributes.remove(ElementTags.VERTICALALIGN)) != null) {
+			setVerticalAlignment(value);
+		}
+		if ((value = (String)attributes.remove(ElementTags.WIDTH)) != null) {
+			setWidth(value);
+		}
+		if ((value = (String)attributes.remove(ElementTags.COLSPAN)) != null) {
+			setColspan(Integer.parseInt(value));
+		}
+		if ((value = (String)attributes.remove(ElementTags.ROWSPAN)) != null) {
+			setRowspan(Integer.parseInt(value));
+		}
+		if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+			setLeading(Float.valueOf(value + "f").floatValue());
+		}
+		if ((value = (String)attributes.remove(ElementTags.HEADER)) != null) {
+			setHeader(new Boolean(value).booleanValue());
+		}
+		if ((value = (String)attributes.remove(ElementTags.NOWRAP)) != null) {
+			setNoWrap(new Boolean(value).booleanValue());
+		}
+		if ((value = (String)attributes.remove(ElementTags.BORDERWIDTH)) != null) {
+			setBorderWidth(Float.valueOf(value + "f").floatValue());
+		}
+		int border = 0;
+		if ((value = (String)attributes.remove(ElementTags.LEFT)) != null) {
+			if (new Boolean(value).booleanValue()) border |= Rectangle.LEFT;
+		}
+		if ((value = (String)attributes.remove(ElementTags.RIGHT)) != null) {
+			if (new Boolean(value).booleanValue()) border |= Rectangle.RIGHT;
+		}
+		if ((value = (String)attributes.remove(ElementTags.TOP)) != null) {
+			if (new Boolean(value).booleanValue()) border |= Rectangle.TOP;
+		}
+		if ((value = (String)attributes.remove(ElementTags.BOTTOM)) != null) {
+			if (new Boolean(value).booleanValue()) border |= Rectangle.BOTTOM;
+		}
+		setBorder(border);
+		String r = (String)attributes.remove(ElementTags.RED);
+		String g = (String)attributes.remove(ElementTags.GREEN);
+		String b = (String)attributes.remove(ElementTags.BLUE);
+		if (r != null || g != null || b != null) {
+			int red = 0;
+			int green = 0;
+			int blue = 0;
+			if (r != null) red = Integer.parseInt(r);
+			if (g != null) green = Integer.parseInt(g);
+			if (b != null) blue = Integer.parseInt(b);
+			setBorderColor(new Color(red, green, blue));
+		}
+		else if ((value = (String)attributes.remove(ElementTags.BORDERCOLOR)) != null) {
+			setBorderColor(MarkupParser.decodeColor(value));
+		}
+		r = (String)attributes.remove(ElementTags.BGRED);
+		g = (String)attributes.remove(ElementTags.BGGREEN);
+		b = (String)attributes.remove(ElementTags.BGBLUE);
+		if (r != null || g != null || b != null) {
+			int red = 0;
+			int green = 0;
+			int blue = 0;
+			if (r != null) red = Integer.parseInt(r);
+			if (g != null) green = Integer.parseInt(g);
+			if (b != null) blue = Integer.parseInt(b);
+			setBackgroundColor(new Color(red, green, blue));
+		}
+		else if ((value = (String)attributes.remove(ElementTags.BACKGROUNDCOLOR)) != null) {
+			setBackgroundColor(MarkupParser.decodeColor(value));
+		}
+		if ((value = (String)attributes.remove(ElementTags.GRAYFILL)) != null) {
+			setGrayFill(Float.valueOf(value + "f").floatValue());
+		}
+		if (attributes.size() > 0) setMarkupAttributes(attributes);
+	}
+
+	// implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+
+	public boolean process(ElementListener listener) {
+		try {
+			return listener.add(this);
+		}
+		catch(DocumentException de) {
+			return false;
+		}
+	}
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+
+	public int type() {
+		return Element.CELL;
+	}
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+
+	public ArrayList getChunks() {
+		ArrayList tmp = new ArrayList();
+		for (Iterator i = arrayList.iterator(); i.hasNext(); ) {
+			tmp.addAll(((Element) i.next()).getChunks());
+		}
+		return tmp;
+	}
+
+	// methods to set the membervariables
+
+/**
+ * Adds an element to this <CODE>Cell</CODE>.
+ * <P>
+ * Remark: you can't add <CODE>ListItem</CODE>s, <CODE>Row</CODE>s, <CODE>Cell</CODE>s,
+ * <CODE>JPEG</CODE>s, <CODE>GIF</CODE>s or <CODE>PNG</CODE>s to a <CODE>Cell</CODE>.
+ *
+ * @param element The <CODE>Element</CODE> to add
+ * @throws BadElementException if the method was called with a <CODE>ListItem</CODE>, <CODE>Row</CODE> or <CODE>Cell</CODE>
+ */
+
+	public void addElement(Element element) throws BadElementException {
+		if (isTable()) {
+			Table table = (Table) arrayList.get(0);
+			Cell tmp = new Cell(element);
+			tmp.setBorder(NO_BORDER);
+			tmp.setColspan(table.columns());
+			table.addCell(tmp);
+			return;
+		}
+		switch(element.type()) {
+			case Element.LISTITEM:
+			case Element.ROW:
+			case Element.CELL:
+				throw new BadElementException("You can't add listitems, rows or cells to a cell.");
+			case Element.LIST:
+				if (Float.isNaN(leading)) {
+					leading = ((List) element).leading();
+				}
+				if (((List) element).size() == 0) return;
+				arrayList.add(element);
+				return;
+			case Element.ANCHOR:
+			case Element.PARAGRAPH:
+			case Element.PHRASE:
+				if (Float.isNaN(leading)) {
+					leading = ((Phrase) element).leading();
+				}
+				if (((Phrase) element).isEmpty()) return;
+				arrayList.add(element);
+				return;
+			case Element.CHUNK:
+				if (((Chunk) element).isEmpty()) return;
+				arrayList.add(element);
+				return;
+			case Element.TABLE:
+				Table table = new Table(3);
+				float[] widths = new float[3];
+				widths[1] = ((Table)element).widthPercentage();
+
+				switch(((Table)element).alignment()) {
+					case Element.ALIGN_LEFT:
+						widths[0] = 0f;
+						widths[2] = 100f - widths[1];
+						break;
+					case Element.ALIGN_CENTER:
+						widths[0] = (100f - widths[1]) / 2f;
+						widths[2] = widths[0];
+						break;
+					case Element.ALIGN_RIGHT:
+						widths[0] = 100f - widths[1];
+						widths[2] = 0f;
+				}
+				table.setWidths(widths);
+				Cell tmp;
+				if (arrayList.size() == 0) {
+					table.addCell(getDummyCell());
+				}
+				else {
+					tmp = new Cell();
+					tmp.setBorder(NO_BORDER);
+					tmp.setColspan(3);
+					for (Iterator i = arrayList.iterator(); i.hasNext(); ) {
+						tmp.add((Element) i.next());
+					}
+					table.addCell(tmp);
+				}
+				tmp = new Cell();
+				tmp.setBorder(NO_BORDER);
+				table.addCell(tmp);
+				table.insertTable((Table)element);
+				table.addCell(tmp);
+				table.addCell(getDummyCell());
+				clear();
+				arrayList.add(table);
+				return;
+				default:
+					arrayList.add(element);
+		}
+	}
+
+/**
+ * Add an <CODE>Object</CODE> to this cell.
+ *
+ * @param o the object to add
+ * @return always <CODE>true</CODE>
+ */
+
+	public boolean add(Object o) {
+		try {
+			this.addElement((Element) o);
+			return true;
+		}
+		catch(ClassCastException cce) {
+			throw new ClassCastException("You can only add objects that implement the Element interface.");
+		}
+		catch(BadElementException bee) {
+			throw new ClassCastException(bee.getMessage());
+		}
+	}
+
+/**
+ * Sets the leading.
+ *
+ * @param	value	the new value
+ */
+
+	public void setLeading(float value) {
+		leading = value;
+	}
+
+/**
+ * Sets the horizontal alignment.
+ *
+ * @param	value	the new value
+ */
+
+	public void setHorizontalAlignment(int value) {
+		horizontalAlignment = value;
+	}
+
+/**
+ * Sets the alignment of this cell.
+ *
+ * @param	alignment		the new alignment as a <CODE>String</CODE>
+ */
+
+	public void setHorizontalAlignment(String alignment) {
+		if (ElementTags.ALIGN_CENTER.equalsIgnoreCase(alignment)) {
+			this.horizontalAlignment = Element.ALIGN_CENTER;
+			return;
+		}
+		if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(alignment)) {
+			this.horizontalAlignment = Element.ALIGN_RIGHT;
+			return;
+		}
+		if (ElementTags.ALIGN_JUSTIFIED.equalsIgnoreCase(alignment)) {
+			this.horizontalAlignment = Element.ALIGN_JUSTIFIED;
+			return;
+		}
+		if (ElementTags.ALIGN_JUSTIFIED_ALL.equalsIgnoreCase(alignment)) {
+			this.horizontalAlignment = Element.ALIGN_JUSTIFIED_ALL;
+			return;
+		}
+		this.horizontalAlignment = Element.ALIGN_LEFT;
+	}
+
+/**
+ * Sets the vertical alignment.
+ *
+ * @param	value	the new value
+ */
+
+	public void setVerticalAlignment(int value) {
+		verticalAlignment = value;
+	}
+
+/**
+ * Sets the alignment of this paragraph.
+ *
+ * @param	alignment		the new alignment as a <CODE>String</CODE>
+ */
+
+	public void setVerticalAlignment(String alignment) {
+		if (ElementTags.ALIGN_MIDDLE.equalsIgnoreCase(alignment)) {
+			this.verticalAlignment = Element.ALIGN_MIDDLE;
+			return;
+		}
+		if (ElementTags.ALIGN_BOTTOM.equalsIgnoreCase(alignment)) {
+			this.verticalAlignment = Element.ALIGN_BOTTOM;
+			return;
+		}
+		if (ElementTags.ALIGN_BASELINE.equalsIgnoreCase(alignment)) {
+			this.verticalAlignment = Element.ALIGN_BASELINE;
+			return;
+		}
+		this.verticalAlignment = Element.ALIGN_TOP;
+	}
+
+/**
+ * Sets the width.
+ *
+ * @param	value	the new value
+ */
+
+	public void setWidth(String value) {
+		width = value;
+	}
+
+/**
+ * Sets the colspan.
+ *
+ * @param	value	the new value
+ */
+
+	public void setColspan(int value) {
+		colspan = value;
+	}
+
+/**
+ * Sets the rowspan.
+ *
+ * @param	value	the new value
+ */
+
+	public void setRowspan(int value) {
+		rowspan = value;
+	}
+
+/**
+ * Sets header.
+ *
+ * @param	value	the new value
+ */
+
+	public void setHeader(boolean value) {
+		header = value;
+	}
+
+/**
+ * Set nowrap.
+ *
+ * @param	value	the new value
+ */
+
+	public void setNoWrap(boolean value) {
+		maxLines = 1;
+	}
+
+	// methods to retrieve information
+
+/**
+ * Gets the number of <CODE>Element</CODE>s in the Cell.
+ *
+ * @return	a <CODE>size</CODE>.
+ */
+
+	public int size() {
+		return arrayList.size();
+	}
+
+/**
+ * Checks if the <CODE>Cell</CODE> is empty.
+ *
+ * @return	<CODE>false</CODE> if there are non-empty <CODE>Element</CODE>s in the <CODE>Cell</CODE>.
+ */
+
+	public boolean isEmpty() {
+		switch(size()) {
+			case 0:
+				return true;
+			case 1:
+				Element element = (Element) arrayList.get(0);
+				switch (element.type()) {
+					case Element.CHUNK:
+						return ((Chunk) element).isEmpty();
+					case Element.ANCHOR:
+					case Element.PHRASE:
+					case Element.PARAGRAPH:
+						return ((Phrase) element).isEmpty();
+					case Element.LIST:
+						return ((List) element).size() == 0;
+				}
+				return false;
+				default:
+					return false;
+		}
+	}
+
+/**
+ * Makes sure there is at least 1 object in the Cell.
+ *
+ * Otherwise it might not be shown in the table.
+ */
+
+	void fill() {
+		if (size() == 0) arrayList.add(new Paragraph(0));
+	}
+
+/**
+ * Checks if the <CODE>Cell</CODE> is empty.
+ *
+ * @return	<CODE>false</CODE> if there are non-empty <CODE>Element</CODE>s in the <CODE>Cell</CODE>.
+ */
+
+	public boolean isTable() {
+		return (size() == 1) && (((Element)arrayList.get(0)).type() == Element.TABLE);
+	}
+
+/**
+ * Gets an iterator of <CODE>Element</CODE>s.
+ *
+ * @return	an <CODE>Iterator</CODE>.
+ */
+
+	public Iterator getElements() {
+		return arrayList.iterator();
+	}
+
+/**
+ * Gets the horizontal alignment.
+ *
+ * @return	a value
+ */
+
+	public int horizontalAlignment() {
+		return horizontalAlignment;
+	}
+
+/**
+ * Gets the vertical alignment.
+ *
+ * @return	a value
+ */
+
+	public int verticalAlignment() {
+		return verticalAlignment;
+	}
+
+/**
+ * Gets the width.
+ *
+ * @return	a value
+ */
+
+	public String cellWidth() {
+		return width;
+	}
+
+/**
+ * Gets the colspan.
+ *
+ * @return	a value
+ */
+
+	public int colspan() {
+		return colspan;
+	}
+
+/**
+ * Gets the rowspan.
+ *
+ * @return	a value
+ */
+
+	public int rowspan() {
+		return rowspan;
+	}
+
+/**
+ * Gets the leading.
+ *
+ * @return	a value
+ */
+
+	public float leading() {
+		if (Float.isNaN(leading)) {
+			return 16;
+		}
+		return leading;
+	}
+
+/**
+ * Is this <CODE>Cell</CODE> a header?
+ *
+ * @return	a value
+ */
+
+	public boolean header() {
+		return header;
+	}
+
+/**
+ * Get nowrap.
+ *
+ * @return	a value
+ */
+
+	public boolean noWrap() {
+		return maxLines == 1;
+	}
+
+/**
+ * Clears all the <CODE>Element</CODE>s of this <CODE>Cell</CODE>.
+ */
+	public void clear() {
+		arrayList.clear();
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @return NA
+ */
+	public float top() {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @return NA
+ */
+	public float bottom() {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @return NA
+ */
+	public float left() {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @return NA
+ */
+	public float right() {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param margin
+ * @return NA
+ */
+	public float top(int margin) {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param margin
+ * @return NA
+ */
+	public float bottom(int margin) {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param margin
+ * @return NA
+ */
+	public float left(int margin) {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param margin NA
+ * @return NA
+ */
+	public float right(int margin) {
+		throw new UnsupportedOperationException("Dimensions of a Cell can't be calculated. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param value NA
+ */
+	public void setTop(int value) {
+		throw new UnsupportedOperationException("Dimensions of a Cell are attributed automagically. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param value NA
+ */
+	public void setBottom(int value) {
+		throw new UnsupportedOperationException("Dimensions of a Cell are attributed automagically. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param value NA
+ */
+	public void setLeft(int value) {
+		throw new UnsupportedOperationException("Dimensions of a Cell are attributed automagically. See the FAQ.");
+	}
+
+/**
+ * This method throws an <CODE>UnsupportedOperationException</CODE>.
+ * @param value NA
+ */
+	public void setRight(int value) {
+		throw new UnsupportedOperationException("Dimensions of a Cell are attributed automagically. See the FAQ.");
+	}
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+
+	public static boolean isTag(String tag) {
+		return ElementTags.CELL.equals(tag);
+	}
+
+/** Does this <CODE>Cell</CODE> force a group change? */
+	protected boolean groupChange = true;
+
+/**
+ * Does this <CODE>Cell</CODE> force a group change?
+ *
+ * @return	a value
+ */
+
+	public boolean getGroupChange() {
+		return groupChange;
+	}
+
+/**
+ * Sets group change.
+ *
+ * @param	value	the new value
+ */
+
+	public void setGroupChange(boolean value) {
+		groupChange = value;
+	}
+	
+	/**
+	 * Getter for {@link #maxLines}
+	 * @return the maxLines value
+	 */
+	public int getMaxLines() {
+		return maxLines;
+	}
+	/**
+	 * Setter for {@link #maxLines}
+	 * @param value the maximum number of lines
+	 */
+	public void setMaxLines(int value) {
+		maxLines = value;
+	}
+	/**
+	 * Maximum number of lines allowed in the cell.  
+	 * The default value of this property is not to limit the maximum number of lines
+	 * (contributed by dperezcar at fcc.es)
+	 */
+	protected int maxLines = Integer.MAX_VALUE;
+	/**Setter for {@link #showTruncation}
+	 * @param value	Can be null for avoiding marking the truncation.*/
+	public void setShowTruncation(String value) {
+		showTruncation = value;
+	}
+	/**
+	 * Getter for {@link #showTruncation}
+	 * @return the showTruncation value
+	 */
+	public String getShowTruncation() {
+		return showTruncation;
+	}
+	/**
+	 * If a truncation happens due to the {@link #maxLines} property, then this text will 
+	 * be added to indicate a truncation has happened.
+	 * Default value is null, and means avoiding marking the truncation.  
+	 * A useful value of this property could be e.g. "..."
+	 * (contributed by dperezcar at fcc.es)
+	 */
+	String showTruncation;
+
+
+    /**
+     * Sets the value of {@link #useAscender}.
+     * @param use use ascender height if true
+     */
+    public void setUseAscender(boolean use) {
+        useAscender = use;
+    }
+
+    /**
+     * Gets the value of {@link #useAscender}
+     * @return useAscender
+     */
+    public boolean isUseAscender() {
+        return useAscender;
+    }
+
+    /**
+     * Sets the value of {@link #useDescender}.
+     * @param use use descender height if true
+     */
+    public void setUseDescender(boolean use) {
+        useDescender = use;
+    }
+
+    /**
+     * gets the value of {@link #useDescender }
+     * @return useDescender
+     */
+    public boolean isUseDescender() {
+        return useDescender;
+    }
+
+    /**
+     * Sets the value of {@link #useBorderPadding}.
+     * @param use adjust layour for borders if true
+     */
+    public void setUseBorderPadding(boolean use) {
+        useBorderPadding = use;
+    }
+
+    /**
+     * Gets the value of {@link #useBorderPadding}.
+     * @return useBorderPadding
+     */
+    public boolean isUseBorderPadding() {
+        return useBorderPadding;
+    }
+
+	/**
+	 * Creates a PdfPCell based on this Cell object.
+	 * @return a PdfPCell
+	 * @throws BadElementException
+	 */
+	public PdfPCell createPdfPCell() throws BadElementException {
+		if (rowspan > 1) throw new BadElementException("PdfPCells can't have a rowspan > 1");
+		if (isTable()) return new PdfPCell(((Table)arrayList.get(0)).createPdfPTable());
+		PdfPCell cell = new PdfPCell();
+		cell.setVerticalAlignment(verticalAlignment);
+		cell.setHorizontalAlignment(horizontalAlignment);
+		cell.setColspan(colspan);
+		cell.setUseBorderPadding(useBorderPadding);
+		cell.setUseDescender(useDescender);
+		cell.setLeading(leading(), 0);
+		cell.cloneNonPositionParameters(this);
+		for (Iterator i = getElements(); i.hasNext(); ) {
+			cell.addElement((Element)i.next());
+		}
+		return cell;
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/Chapter.java b/LibrarySource/com/lowagie/text/Chapter.java
new file mode 100644
index 0000000..80afae9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Chapter.java
@@ -0,0 +1,156 @@
+/*
+ * $Id: Chapter.java,v 1.69 2005/04/13 09:51:14 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Properties;
+
+/**
+ * A <CODE>Chapter</CODE> is a special <CODE>Section</CODE>.
+ * <P>
+ * A chapter number has to be created using a <CODE>Paragraph</CODE> as title
+ * and an <CODE>int</CODE> as chapter number. The chapter number is shown be
+ * default. If you don't want to see the chapter number, you have to set the
+ * numberdepth to <VAR>0</VAR>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * Paragraph title2 = new Paragraph("This is Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
+ * <STRONG>Chapter chapter2 = new Chapter(title2, 2);</STRONG>
+ * <STRONG>chapter2.setNumberDepth(0);</STRONG>
+ * Paragraph someText = new Paragraph("This is some text");
+ * <STRONG>chapter2.add(someText);</STRONG>
+ * Paragraph title21 = new Paragraph("This is Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
+ * Section section1 = <STRONG>chapter2.addSection(title21);</STRONG>
+ * Paragraph someSectionText = new Paragraph("This is some silly paragraph in a chapter and/or section. It contains some text to test the functionality of Chapters and Section.");
+ * section1.add(someSectionText);
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class Chapter extends Section implements TextElementArray {
+    
+    // constructors
+    
+	/**
+	 * Constructs a new <CODE>Chapter</CODE>.
+	 *
+	 * @param	title		the Chapter title (as a <CODE>Paragraph</CODE>)
+	 * @param	number		the Chapter number
+     */
+    
+    public Chapter(Paragraph title, int number) {
+        super(title, 1);
+        numbers = new ArrayList();
+        numbers.add(new Integer(number));
+    }
+    
+/**
+ * Constructs a new <CODE>Chapter</CODE>.
+ *
+ * @param	title		the Chapter title (as a <CODE>String</CODE>)
+ * @param	number		the Chapter number
+ */
+    
+    public Chapter(String title, int number) {
+        this(new Paragraph(title), number);
+    }
+    
+/**
+ * Creates a new <CODE>Chapter</CODE> following a set of attributes.
+ *
+ * @param	attributes	the attributes
+ * @param number a userdefined Chapter number
+ */
+    
+    public Chapter(Properties attributes, int number) {
+        this(new Paragraph(""), number);
+        
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.NUMBERDEPTH)) != null) {
+            setNumberDepth(Integer.parseInt(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENT)) != null) {
+            setIndentation(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+            setIndentationLeft(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+            setIndentationRight(Float.valueOf(value + "f").floatValue());
+        }
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.CHAPTER;
+    }
+    
+    // methods
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.CHAPTER.equals(tag);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/Chunk.java b/LibrarySource/com/lowagie/text/Chunk.java
new file mode 100644
index 0000000..93cd221
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Chunk.java
@@ -0,0 +1,788 @@
+/*
+ * $Id: Chunk.java,v 1.111 2005/05/03 13:03:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Set;
+import java.net.URL;
+
+import com.lowagie.text.pdf.PdfAction;
+import com.lowagie.text.pdf.PdfAnnotation;
+import com.lowagie.text.pdf.HyphenationEvent;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * This is the smallest significant part of text that can be added to a document.
+ * <P>
+ * Most elements can be divided in one or more <CODE>Chunk</CODE>s.
+ * A chunk is a <CODE>String</CODE> with a certain <CODE>Font</CODE>.
+ * all other layoutparameters should be defined in the object to which
+ * this chunk of text is added.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>Chunk chunk = new Chunk("Hello world", FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));</STRONG>
+ * document.add(chunk);
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class Chunk implements Element, MarkupAttributes {
+
+// public static membervariables
+    
+    /**
+     * The character stand in for an image.
+     */    
+    public static final String OBJECT_REPLACEMENT_CHARACTER = "\ufffc";
+
+/** This is a Chunk containing a newline. */
+    public static final Chunk NEWLINE = new Chunk("\n");
+
+/** This is a Chunk containing a newpage. */
+    public static final Chunk NEXTPAGE = new Chunk("");
+    static {
+    	NEXTPAGE.setNewPage();
+    }
+/** Key for sub/superscript. */
+    public static final String SUBSUPSCRIPT = "SUBSUPSCRIPT";
+
+/** Key for underline. */
+    public static final String UNDERLINE = "UNDERLINE";
+
+/** Key for color. */
+    public static final String COLOR = "COLOR";
+
+/** Key for encoding. */
+    public static final String ENCODING = "ENCODING";
+
+/** Key for remote goto. */
+    public static final String REMOTEGOTO = "REMOTEGOTO";
+
+/** Key for local goto. */
+    public static final String LOCALGOTO = "LOCALGOTO";
+
+/** Key for local destination. */
+    public static final String LOCALDESTINATION = "LOCALDESTINATION";
+
+/** Key for image. */
+    public static final String IMAGE = "IMAGE";
+
+/** Key for generic tag. */
+    public static final String GENERICTAG = "GENERICTAG";
+
+/** Key for newpage. */
+    public static final String NEWPAGE = "NEWPAGE";
+
+/** Key for split character. */
+    public static final String SPLITCHARACTER = "SPLITCHARACTER";
+
+/** Key for Action. */
+    public static final String ACTION = "ACTION";
+
+/** Key for background. */
+    public static final String BACKGROUND = "BACKGROUND";
+
+/** Key for annotation. */
+    public static final String PDFANNOTATION = "PDFANNOTATION";
+
+/** Key for hyphenation. */
+    public static final String HYPHENATION = "HYPHENATION";
+
+/** Key for text rendering mode. */
+    public static final String TEXTRENDERMODE = "TEXTRENDERMODE";
+
+/** Key for text skewing. */
+    public static final String SKEW = "SKEW";
+
+/** Key for text horizontal scaling. */
+    public static final String HSCALE = "HSCALE";
+
+// member variables
+
+/** This is the content of this chunk of text. */
+    protected StringBuffer content = null;
+
+/** This is the <CODE>Font</CODE> of this chunk of text. */
+    protected Font font = null;
+
+/** Contains some of the attributes for this Chunk. */
+    protected HashMap attributes = null;
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes = null;
+
+// constructors
+
+/**
+ * Empty constructor.
+ */
+    protected Chunk() {
+    }
+
+/**
+ * Constructs a chunk of text with a certain content and a certain <CODE>Font</CODE>.
+ *
+ * @param	content		the content
+ * @param	font		the font
+ */
+
+    public Chunk(String content, Font font) {
+        this.content = new StringBuffer(content);
+        this.font = font;
+    }
+
+/**
+ * Constructs a chunk of text with a certain content, without specifying a <CODE>Font</CODE>.
+ *
+ * @param	content		the content
+ */
+    public Chunk(String content) {
+        this(content, new Font());
+    }
+    
+/**
+ * Constructs a chunk of text with a char and a certain <CODE>Font</CODE>.
+ *
+ * @param	c		the content
+ * @param	font		the font
+ */
+    public Chunk(char c, Font font) {
+        this.content = new StringBuffer();
+        this.content.append(c);
+        this.font = font;
+    }
+    
+/**
+ * Constructs a chunk of text with a char, without specifying a <CODE>Font</CODE>.
+ *
+ * @param	c		the content
+ */
+    public Chunk(char c) {
+        this(c, new Font());
+    }
+
+/**
+ * Constructs a chunk containing an <CODE>Image</CODE>.
+ *
+ * @param image the image
+ * @param offsetX the image offset in the x direction
+ * @param offsetY the image offset in the y direction
+ */
+
+    public Chunk(Image image, float offsetX, float offsetY) {
+        this(OBJECT_REPLACEMENT_CHARACTER, new Font());
+        Image copyImage = Image.getInstance(image);
+        copyImage.setAbsolutePosition(Float.NaN, Float.NaN);
+        setAttribute(IMAGE, new Object[]{copyImage, new Float(offsetX), new Float(offsetY), new Boolean(false)});
+    }
+
+/**
+ * Constructs a chunk containing an <CODE>Image</CODE>.
+ *
+ * @param image         the image
+ * @param offsetX       the image offset in the x direction
+ * @param offsetY       the image offset in the y direction
+ * @param changeLeading true if the leading has to be adapted to the image
+ */
+
+    public Chunk(Image image, float offsetX, float offsetY, boolean changeLeading) {
+        this(OBJECT_REPLACEMENT_CHARACTER, new Font());
+        setAttribute(IMAGE, new Object[]{image, new Float(offsetX), new Float(offsetY), new Boolean(changeLeading)});
+    }
+
+/**
+ * Returns a <CODE>Chunk</CODE> that has been constructed taking in account
+ * the value of some <VAR>attributes</VAR>.
+ *
+ * @param	attributes		Some attributes
+ */
+
+    public Chunk(Properties attributes) {
+        this("", FontFactory.getFont(attributes));
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+            append(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.LOCALGOTO)) != null) {
+            setLocalGoto(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.REMOTEGOTO)) != null) {
+            String destination = (String) attributes.remove(ElementTags.DESTINATION);
+            String page = (String) attributes.remove(ElementTags.PAGE);
+            if (page != null) {
+                setRemoteGoto(value, Integer.valueOf(page).intValue());
+            }
+            else if (destination != null) {
+                setRemoteGoto(value, destination);
+            }
+        }
+        if ((value = (String)attributes.remove(ElementTags.LOCALDESTINATION)) != null) {
+            setLocalDestination(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.SUBSUPSCRIPT)) != null) {
+            setTextRise(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_VERTICALALIGN)) != null && value.endsWith("%")) {
+            float p = Float.valueOf(value.substring(0, value.length() - 1) + "f").floatValue() / 100f;
+            setTextRise(p * font.size());
+        }
+        if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+            setGenericTag(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.BACKGROUNDCOLOR)) != null) {
+            setBackground(MarkupParser.decodeColor(value));
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+
+    // implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+
+    public int type() {
+        return Element.CHUNK;
+    }
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+
+    public ArrayList getChunks() {
+        ArrayList tmp = new ArrayList();
+        tmp.add(this);
+        return tmp;
+    }
+
+    // methods
+
+/**
+ * appends some text to this <CODE>Chunk</CODE>.
+ *
+ * @param	string <CODE>String</CODE>
+ * @return	a <CODE>StringBuffer</CODE>
+ */
+
+    public StringBuffer append(String string) {
+        return content.append(string);
+    }
+
+    // methods to retrieve information
+
+/**
+ * Gets the font of this <CODE>Chunk</CODE>.
+ *
+ * @return	a <CODE>Font</CODE>
+ */
+
+    public Font font() {
+        return font;
+    }
+
+/**
+ * Sets the font of this <CODE>Chunk</CODE>.
+ *
+ * @param	font a <CODE>Font</CODE>
+ */
+
+    public void setFont(Font font) {
+        this.font = font;
+    }
+
+/**
+ * Returns the content of this <CODE>Chunk</CODE>.
+ *
+ * @return	a <CODE>String</CODE>
+ */
+
+    public String content() {
+        return content.toString();
+    }
+
+/**
+ * Checks is this <CODE>Chunk</CODE> is empty.
+ *
+ * @return	<CODE>false</CODE> if the Chunk contains other characters than space.
+ */
+
+    public boolean isEmpty() {
+        return (content.toString().trim().length() == 0) && (content.toString().indexOf("\n") == -1) && (attributes == null);
+    }
+
+/**
+ * Gets the width of the Chunk in points.
+ * @return a width in points
+ */
+    public float getWidthPoint() {
+        if (getImage() != null) {
+            return getImage().scaledWidth();
+        }
+    	return font.getCalculatedBaseFont(true).getWidthPoint(content(), font.getCalculatedSize()) * getHorizontalScaling();
+    }
+    
+/**
+ * Sets the text displacement relative to the baseline. Positive values rise the text,
+ * negative values lower the text.
+ * <P>
+ * It can be used to implement sub/superscript.
+ * @param rise the displacement in points
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setTextRise(float rise) {
+        return setAttribute(SUBSUPSCRIPT, new Float(rise));
+    }
+    
+    /**
+     * Gets the text displacement relatiev to the baseline.
+     * @return a displacement in points
+     */
+    public float getTextRise() {
+    	if (attributes.containsKey(SUBSUPSCRIPT)) {
+    		Float f = (Float)attributes.get(SUBSUPSCRIPT);
+    		return f.floatValue();
+    	}
+    	return 0.0f;
+    }
+
+    /** Sets the text rendering mode. It can outline text, simulate bold and make
+     * text invisible.
+     * @param mode the text rendering mode. It can be <CODE>PdfContentByte.TEXT_RENDER_MODE_FILL</CODE>,
+     * <CODE>PdfContentByte.TEXT_RENDER_MODE_STROKE</CODE>, <CODE>PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE</CODE>
+     * and <CODE>PdfContentByte.TEXT_RENDER_MODE_INVISIBLE</CODE>.
+     * @param strokeWidth the stroke line width for the modes <CODE>PdfContentByte.TEXT_RENDER_MODE_STROKE</CODE> and
+     * <CODE>PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE</CODE>.
+     * @param strokeColor the stroke color or <CODE>null</CODE> to follow the text color
+     * @return this <CODE>Chunk</CODE>
+     */    
+    public Chunk setTextRenderMode(int mode, float strokeWidth, Color strokeColor) {
+        return setAttribute(TEXTRENDERMODE, new Object[]{new Integer(mode), new Float(strokeWidth), strokeColor});
+    }
+
+    /**
+     * Skews the text to simulate italic and other effects.
+     * Try <CODE>alpha=0</CODE> and <CODE>beta=12</CODE>.
+     * @param alpha the first angle in degrees
+     * @param beta the second angle in degrees
+     * @return this <CODE>Chunk</CODE>
+     */    
+    public Chunk setSkew(float alpha, float beta) {
+        alpha = (float)Math.tan(alpha * Math.PI / 180);
+        beta = (float)Math.tan(beta * Math.PI / 180);
+        return setAttribute(SKEW, new float[]{alpha, beta});
+    }
+
+    /**
+     * Sets the text horizontal scaling. A value of 1 is normal and a value of 0.5f
+     * shrinks the text to half it's width.
+     * @param scale the horizontal scaling factor
+     * @return this <CODE>Chunk</CODE>
+     */    
+    public Chunk setHorizontalScaling(float scale) {
+        return setAttribute(HSCALE, new Float(scale));
+    }
+    
+    /**
+     * Gets the horizontal scaling.
+     * @return a percentage in float
+     */
+    public float getHorizontalScaling() {
+    	if (attributes == null) return 1f;
+    	Float f = (Float)attributes.get(HSCALE);
+    	if (f == null) return 1f;
+    	return f.floatValue();
+    }
+    
+/**
+ * Sets an action for this <CODE>Chunk</CODE>.
+ *
+ * @param action the action
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setAction(PdfAction action) {
+        return setAttribute(ACTION, action);
+    }
+
+/**
+ * Sets an anchor for this <CODE>Chunk</CODE>.
+ *
+ * @param url the <CODE>URL</CODE> to link to
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setAnchor(URL url) {
+        return setAttribute(ACTION, new PdfAction(url.toExternalForm()));
+    }
+
+/**
+ * Sets an anchor for this <CODE>Chunk</CODE>.
+ *
+ * @param url the url to link to
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setAnchor(String url) {
+        return setAttribute(ACTION, new PdfAction(url));
+    }
+
+/**
+ * Sets a local goto for this <CODE>Chunk</CODE>.
+ * <P>
+ * There must be a local destination matching the name.
+ * @param name the name of the destination to go to
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setLocalGoto(String name) {
+        return setAttribute(LOCALGOTO, name);
+    }
+
+/**
+ * Sets the color of the background <CODE>Chunk</CODE>.
+ * @param color the color of the background
+ * @return this <CODE>Chunk</CODE>
+ */
+    public Chunk setBackground(Color color) {
+        return setBackground(color, 0, 0, 0, 0);
+    }
+
+    /** Sets the color and the size of the background <CODE>Chunk</CODE>.
+     * @param color the color of the background
+     * @param extraLeft increase the size of the rectangle in the left
+     * @param extraBottom increase the size of the rectangle in the bottom
+     * @param extraRight increase the size of the rectangle in the right
+     * @param extraTop increase the size of the rectangle in the top
+     * @return this <CODE>Chunk</CODE>
+     */
+    public Chunk setBackground(Color color, float extraLeft, float extraBottom, float extraRight, float extraTop) {
+        return setAttribute(BACKGROUND, new Object[]{color, new float[]{extraLeft, extraBottom, extraRight, extraTop}});
+    }
+
+    /**
+     * Sets an horizontal line that can be an underline or a strikethrough.
+     * Actually, the line can be anywhere vertically and has always the
+     * <CODE>Chunk</CODE> width. Multiple call to this method will
+     * produce multiple lines.
+     * @param thickness the absolute thickness of the line
+     * @param yPosition the absolute y position relative to the baseline
+     * @return this <CODE>Chunk</CODE>
+     */    
+    public Chunk setUnderline(float thickness, float yPosition) {
+        return setUnderline(null, thickness, 0f, yPosition, 0f, PdfContentByte.LINE_CAP_BUTT);
+    }
+
+    /**
+     * Sets an horizontal line that can be an underline or a strikethrough.
+     * Actually, the line can be anywhere vertically and has always the
+     * <CODE>Chunk</CODE> width. Multiple call to this method will
+     * produce multiple lines.
+     * @param color the color of the line or <CODE>null</CODE> to follow
+     * the text color
+     * @param thickness the absolute thickness of the line
+     * @param thicknessMul the thickness multiplication factor with the font size
+     * @param yPosition the absolute y position relative to the baseline
+     * @param yPositionMul the position multiplication factor with the font size
+     * @param cap the end line cap. Allowed values are
+     * PdfContentByte.LINE_CAP_BUTT, PdfContentByte.LINE_CAP_ROUND and
+     * PdfContentByte.LINE_CAP_PROJECTING_SQUARE
+     * @return this <CODE>Chunk</CODE>
+     */    
+    public Chunk setUnderline(Color color, float thickness, float thicknessMul, float yPosition, float yPositionMul, int cap) {
+        if (attributes == null)
+            attributes = new HashMap();
+        Object obj[] = {color, new float[]{thickness, thicknessMul, yPosition, yPositionMul, (float)cap}};
+        Object unders[][] = addToArray((Object[][])attributes.get(UNDERLINE), obj);
+        return setAttribute(UNDERLINE, unders);
+    }
+    
+    /**
+     * Utility method to extend an array.
+     * @param original the original array or <CODE>null</CODE>
+     * @param item the item to be added to the array
+     * @return a new array with the item appended
+     */    
+    public static Object[][] addToArray(Object original[][], Object item[]) {
+        if (original == null) {
+            original = new Object[1][];
+            original[0] = item;
+            return original;
+        }
+        else {
+            Object original2[][] = new Object[original.length + 1][];
+            System.arraycopy(original, 0, original2, 0, original.length);
+            original2[original.length] = item;
+            return original2;
+        }
+    }
+    
+/**
+ * Sets a generic annotation to this <CODE>Chunk</CODE>.
+ * @param annotation the annotation
+ * @return this <CODE>Chunk</CODE>
+ */
+    public Chunk setAnnotation(PdfAnnotation annotation) {
+        return setAttribute(PDFANNOTATION, annotation);
+    }
+
+/** sets the hyphenation engine to this <CODE>Chunk</CODE>.
+ * @param hyphenation the hyphenation engine
+ * @return this <CODE>Chunk</CODE>
+ */
+    public Chunk setHyphenation(HyphenationEvent hyphenation) {
+        return setAttribute(HYPHENATION, hyphenation);
+    }
+
+    /**
+     * Sets a goto for a remote destination for this <CODE>Chunk</CODE>.
+     * @param filename the file name of the destination document
+     * @param name the name of the destination to go to
+     * @return this <CODE>Chunk</CODE>
+     */
+
+    public Chunk setRemoteGoto(String filename, String name) {
+        return setAttribute(REMOTEGOTO, new Object[]{filename, name});
+    }
+
+/**
+ * Sets a goto for a remote destination for this <CODE>Chunk</CODE>.
+ *
+ * @param filename the file name of the destination document
+ * @param page the page of the destination to go to. First page is 1
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setRemoteGoto(String filename, int page) {
+        return setAttribute(REMOTEGOTO, new Object[]{filename, new Integer(page)});
+    }
+
+/**
+ * Sets a local destination for this <CODE>Chunk</CODE>.
+ *
+ * @param name the name for this destination
+ * @return this <CODE>Chunk</CODE>
+ */
+    public Chunk setLocalDestination(String name) {
+        return setAttribute(LOCALDESTINATION, name);
+    }
+
+/**
+ * Sets the generic tag <CODE>Chunk</CODE>.
+ * <P>
+ * The text for this tag can be retrieved with <CODE>PdfPageEvent</CODE>.
+ *
+ * @param text the text for the tag
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setGenericTag(String text) {
+        return setAttribute(GENERICTAG, text);
+    }
+
+/**
+ * Sets the split characters.
+ *
+ * @param splitCharacter the <CODE>SplitCharacter</CODE> interface
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setSplitCharacter(SplitCharacter splitCharacter) {
+        return setAttribute(SPLITCHARACTER, splitCharacter);
+    }
+
+/**
+ * Sets a new page tag..
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    public Chunk setNewPage() {
+        return setAttribute(NEWPAGE, null);
+    }
+
+/**
+ * Sets an arbitrary attribute.
+ *
+ * @param name the key for the attribute
+ * @param obj the value of the attribute
+ * @return this <CODE>Chunk</CODE>
+ */
+
+    private Chunk setAttribute(String name, Object obj) {
+        if (attributes == null)
+            attributes = new HashMap();
+        attributes.put(name, obj);
+        return this;
+    }
+
+/**
+ * Gets the attributes for this <CODE>Chunk</CODE>.
+ * <P>
+ * It may be null.
+ *
+ * @return the attributes for this <CODE>Chunk</CODE>
+ */
+
+    public HashMap getAttributes() {
+        return attributes;
+    }
+
+/**
+ * Checks the attributes of this <CODE>Chunk</CODE>.
+ *
+ * @return false if there aren't any.
+ */
+
+    public boolean hasAttributes() {
+        return attributes != null;
+    }
+
+    /**
+     * Returns the image.
+     * @return the image
+     */
+
+    public Image getImage() {
+        if (attributes == null) return null;
+        Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
+        if (obj == null)
+            return null;
+        else {
+            return (Image)obj[0];
+        }
+    }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+
+    public static boolean isTag(String tag) {
+        return ElementTags.CHUNK.equals(tag);
+    }
+
+
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return getKeySet(markupAttributes);
+    }
+
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+
+    /**
+     * Gets the keys of a Hashtable
+     * @param table a Hashtable
+     * @return the keyset of a Hashtable (or an empty set if table is null)
+     */
+    public static Set getKeySet(Hashtable table) {
+        return (table == null) ? Collections.EMPTY_SET : table.keySet();
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/DocListener.java b/LibrarySource/com/lowagie/text/DocListener.java
new file mode 100644
index 0000000..5228f2d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/DocListener.java
@@ -0,0 +1,182 @@
+/*
+ * $Id: DocListener.java,v 1.52 2004/12/14 11:52:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * A class that implements <CODE>DocListener</CODE> will perform some
+ * actions when some actions are performed on a <CODE>Document</CODE>.
+ *
+ * @see		ElementListener
+ * @see		Document
+ * @see		DocWriter
+ */
+
+public interface DocListener extends ElementListener {
+    
+    // methods
+    
+/**
+ * Signals that the <CODE>Document</CODE> has been opened and that
+ * <CODE>Elements</CODE> can be added.
+ */
+    
+    public void open();
+    
+/**
+ * Sets the pagesize.
+ *
+ * @param	pageSize	the new pagesize
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean setPageSize(Rectangle pageSize);
+    
+/**
+ * Signals that a <CODE>Watermark</CODE> was added to the <CODE>Document</CODE>.
+ * 
+ * @param watermark the Watermark object
+ * @return	<CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
+ */
+    
+    public boolean add(Watermark watermark);
+    
+/**
+ * Signals that a <CODE>Watermark</CODE> was removed from the <CODE>Document</CODE>.
+ */
+    
+    public void removeWatermark();
+    
+/**
+ * Sets the margins.
+ *
+ * @param	marginLeft		the margin on the left
+ * @param	marginRight		the margin on the right
+ * @param	marginTop		the margin on the top
+ * @param	marginBottom	the margin on the bottom
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom);
+    
+    /**
+     * Parameter that allows you to do margin mirroring (odd/even pages)
+     * @param marginMirroring
+     * @return true if succesfull
+     */
+    public boolean setMarginMirroring(boolean marginMirroring);
+    
+/**
+ * Signals that an new page has to be started.
+ *
+ * @return	<CODE>true</CODE> if the page was added, <CODE>false</CODE> if not.
+ * @throws	DocumentException	when a document isn't open yet, or has been closed
+ */
+    
+    public boolean newPage() throws DocumentException;
+    
+/**
+ * Changes the header of this document.
+ *
+ * @param	header		the new header
+ */
+    
+    public void setHeader(HeaderFooter header);
+    
+/**
+ * Resets the header of this document.
+ */
+    
+    public void resetHeader();
+    
+/**
+ * Changes the footer of this document.
+ *
+ * @param	footer		the new footer
+ */
+    
+    public void setFooter(HeaderFooter footer);
+    
+/**
+ * Resets the footer of this document.
+ */
+    
+    public void resetFooter();
+    
+/**
+ * Sets the page number to 0.
+ */
+    
+    public void resetPageCount();
+    
+/**
+ * Sets the page number.
+ *
+ * @param	pageN		the new page number
+ */
+    
+    public void setPageCount(int pageN);
+    
+/**
+ * Clears text wrapping around images (if applicable).
+ * Method suggested by Pelikan Stephan
+ * @throws DocumentException
+ */
+	public void clearTextWrap() throws DocumentException;
+    
+/**
+ * Signals that the <CODE>Document</CODE> was closed and that no other
+ * <CODE>Elements</CODE> will be added.
+ * <P>
+ * The outputstream of every writer implementing <CODE>DocListener</CODE> will be closed.
+ */
+    
+    public void close();
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/DocWriter.java b/LibrarySource/com/lowagie/text/DocWriter.java
new file mode 100644
index 0000000..0d05b32
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/DocWriter.java
@@ -0,0 +1,510 @@
+/*
+ * $Id: DocWriter.java,v 1.70 2004/12/14 11:52:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import com.lowagie.text.pdf.OutputStreamCounter;
+
+/**
+ * An abstract <CODE>Writer</CODE> class for documents.
+ * <P>
+ * <CODE>DocWriter</CODE> is the abstract class of several writers such
+ * as <CODE>PdfWriter</CODE> and <CODE>HtmlWriter</CODE>.
+ * A <CODE>DocWriter</CODE> can be added as a <CODE>DocListener</CODE>
+ * to a certain <CODE>Document</CODE> by getting an instance (see method
+ * <CODE>getInstance()</CODE> in the specific writer-classes).
+ * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE>
+ * will be written to the <CODE>OutputStream</CODE> of the listening
+ * <CODE>DocWriter</CODE>.
+ *
+ * @see   Document
+ * @see   DocListener
+ */
+
+public abstract class DocWriter implements DocListener {
+
+/** This is some byte that is often used. */
+    public static final byte NEWLINE = (byte)'\n';
+
+/** This is some byte that is often used. */
+    public static final byte TAB = (byte)'\t';
+
+/** This is some byte that is often used. */
+    public static final byte LT = (byte)'<';
+
+/** This is some byte that is often used. */
+    public static final byte SPACE = (byte)' ';
+
+/** This is some byte that is often used. */
+    public static final byte EQUALS = (byte)'=';
+
+/** This is some byte that is often used. */
+    public static final byte QUOTE = (byte)'\"';
+
+/** This is some byte that is often used. */
+    public static final byte GT = (byte)'>';
+
+/** This is some byte that is often used. */
+    public static final byte FORWARD = (byte)'/';
+
+    // membervariables
+
+/** The pageSize. */
+    protected Rectangle pageSize;
+
+/** This is the document that has to be written. */
+    protected Document document;
+
+/** The outputstream of this writer. */
+    protected OutputStreamCounter os;
+
+/** Is the writer open for writing? */
+    protected boolean open = false;
+
+/** Do we have to pause all writing actions? */
+    protected boolean pause = false;
+    
+/** Closes the stream on document close */
+    protected boolean closeStream = true;
+
+    // constructor
+    
+    protected DocWriter()  {
+    }
+
+/**
+ * Constructs a <CODE>DocWriter</CODE>.
+ *
+ * @param document  The <CODE>Document</CODE> that has to be written
+ * @param os  The <CODE>OutputStream</CODE> the writer has to write to.
+ */
+
+    protected DocWriter(Document document, OutputStream os)  {
+        this.document = document;
+        this.os = new OutputStreamCounter(new BufferedOutputStream(os));
+    }
+
+    // implementation of the DocListener methods
+
+/**
+ * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class.
+ * 
+ * @param element A high level object to add
+ * @return  <CODE>false</CODE>
+ * @throws  DocumentException when a document isn't open yet, or has been closed
+ */
+
+    public boolean add(Element element) throws DocumentException {
+        return false;
+    }
+
+/**
+ * Signals that the <CODE>Document</CODE> was opened.
+ */
+
+    public void open() {
+        open = true;
+    }
+
+/**
+ * Sets the pagesize.
+ *
+ * @param pageSize  the new pagesize
+ * @return  a <CODE>boolean</CODE>
+ */
+
+    public boolean setPageSize(Rectangle pageSize) {
+        this.pageSize = pageSize;
+        return true;
+    }
+
+/**
+ * Sets the <CODE>Watermark</CODE>.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * a <CODE>Watermark</CODE>.
+ * 
+ * @param watermark A watermark object
+ * @return  <CODE>false</CODE> (because watermarks aren't supported by default).
+ */
+
+    public boolean add(Watermark watermark) {
+        return false;
+    }
+
+/**
+ * Removes the <CODE>Watermark</CODE> (if there is one).
+ */
+
+    public void removeWatermark() {
+    }
+
+/**
+ * Sets the margins.
+ * <P>
+ * This does nothing. Has to be overridden if needed.
+ *
+ * @param marginLeft    the margin on the left
+ * @param marginRight   the margin on the right
+ * @param marginTop   the margin on the top
+ * @param marginBottom  the margin on the bottom
+ * @return  <CODE>false</CODE>
+ */
+
+    public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+        return false;
+    }
+
+/**
+ * Signals that an new page has to be started.
+ * <P>
+ * This does nothing. Has to be overridden if needed.
+ *
+ * @return  <CODE>true</CODE> if the page was added, <CODE>false</CODE> if not.
+ * @throws  DocumentException when a document isn't open yet, or has been closed
+ */
+
+    public boolean newPage() throws DocumentException {
+        if (!open) {
+            return false;
+        }
+        return true;
+    }
+
+/**
+ * Changes the header of this document.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * headers.
+ *
+ * @param header    the new header
+ */
+
+    public void setHeader(HeaderFooter header) {
+    }
+
+/**
+ * Resets the header of this document.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * headers.
+ */
+
+    public void resetHeader() {
+    }
+
+/**
+ * Changes the footer of this document.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * footers.
+ *
+ * @param footer    the new footer
+ */
+
+    public void setFooter(HeaderFooter footer) {
+    }
+
+/**
+ * Resets the footer of this document.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * footers.
+ */
+
+    public void resetFooter() {
+    }
+
+/**
+ * Sets the page number to 0.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * pagenumbers.
+ */
+
+    public void resetPageCount() {
+    }
+
+/**
+ * Sets the page number.
+ * <P>
+ * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
+ * derived from this abstract class if they actually support the use of
+ * pagenumbers.
+ *
+ * @param pageN   the new page number
+ */
+
+    public void setPageCount(int pageN) {
+    }
+
+/**
+ * Signals that the <CODE>Document</CODE> was closed and that no other
+ * <CODE>Elements</CODE> will be added.
+ */
+
+    public void close() {
+        open = false;
+        try {
+            os.flush();
+            if (closeStream)
+                os.close();
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+
+    // methods
+
+/** Converts a <CODE>String</CODE> into a <CODE>Byte</CODE> array
+ * according to the ISO-8859-1 codepage.
+ * @param text the text to be converted
+ * @return the conversion result
+ */
+
+    public static final byte[] getISOBytes(String text)
+    {
+        if (text == null)
+            return null;
+        int len = text.length();
+        byte b[] = new byte[len];
+        for (int k = 0; k < len; ++k)
+            b[k] = (byte)text.charAt(k);
+        return b;
+    }
+
+/**
+ * Let the writer know that all writing has to be paused.
+ */
+
+    public void pause() {
+        pause = true;
+    }
+
+/**
+ * Let the writer know that writing may be resumed.
+ */
+
+    public void resume() {
+        pause = false;
+    }
+
+/**
+ * Flushes the <CODE>BufferedOutputStream</CODE>.
+ */
+
+    public void flush() {
+        try {
+            os.flush();
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+
+/**
+ * Writes a <CODE>String</CODE> to the <CODE>OutputStream</CODE>.
+ *
+ * @param string    the <CODE>String</CODE> to write
+ * @throws IOException
+ */
+
+    protected void write(String string) throws IOException {
+        os.write(getISOBytes(string));
+    }
+
+/**
+ * Writes a number of tabs.
+ *
+ * @param   indent  the number of tabs to add
+ * @throws IOException
+ */
+
+    protected void addTabs(int indent) throws IOException {
+        os.write(NEWLINE);
+        for (int i = 0; i < indent; i++) {
+            os.write(TAB);
+        }
+    }
+
+/**
+ * Writes a key-value pair to the outputstream.
+ *
+ * @param   key     the name of an attribute
+ * @param   value   the value of an attribute
+ * @throws IOException
+ */
+
+    protected void write(String key, String value)
+    throws IOException {
+        os.write(SPACE);
+        write(key);
+        os.write(EQUALS);
+        os.write(QUOTE);
+        write(value);
+        os.write(QUOTE);
+    }
+
+/**
+ * Writes a starttag to the outputstream.
+ *
+ * @param   tag     the name of the tag
+ * @throws IOException
+ */
+
+    protected void writeStart(String tag)
+    throws IOException {
+        os.write(LT);
+        write(tag);
+    }
+
+/**
+ * Writes an endtag to the outputstream.
+ *
+ * @param   tag     the name of the tag
+ * @throws IOException
+ */
+
+    protected void writeEnd(String tag)
+    throws IOException {
+        os.write(LT);
+        os.write(FORWARD);
+        write(tag);
+        os.write(GT);
+    }
+
+/**
+ * Writes an endtag to the outputstream.
+ * @throws IOException
+ */
+
+    protected void writeEnd()
+    throws IOException {
+        os.write(SPACE);
+        os.write(FORWARD);
+        os.write(GT);
+    }
+
+/**
+ * Writes the markup attributes of the specified <CODE>MarkupAttributes</CODE>
+ * object to the <CODE>OutputStream</CODE>.
+ * @param mAtt   the <CODE>MarkupAttributes</CODE> to write.
+ * @return true, if writing the markup attributes succeeded
+ * @throws IOException
+ */
+    protected boolean writeMarkupAttributes(MarkupAttributes mAtt)
+     throws IOException
+    {
+      Iterator attributeIterator = mAtt.getMarkupAttributeNames().iterator();
+      boolean result = attributeIterator.hasNext();
+      while (attributeIterator.hasNext()) {
+        String name = String.valueOf(attributeIterator.next());
+        write(name, mAtt.getMarkupAttribute(name));
+      }
+      return result;
+    }
+
+
+/**
+ * Returns <CODE>true</CODE> if the specified <CODE>Element</CODE> implements
+ * <CODE>MarkupAttributes</CODE> and has one or more attributes to write.
+ * @param element   the <CODE>Element</CODE> to check.
+ * @return <CODE>boolean</CODE>.
+ */
+    protected static boolean hasMarkupAttributes(Element element) {
+      return (element instanceof MarkupAttributes &&
+       !(((MarkupAttributes)element).getMarkupAttributeNames().isEmpty()));
+    }
+
+    /** Checks if the stream is to be closed on document close
+     * @return true if the stream is closed on documnt close
+     *
+     */
+    public boolean isCloseStream() {
+        return closeStream;
+    }
+    
+    /** Sets the close state of the stream after document close
+     * @param closeStream true if the stream is closed on document close
+     *
+     */
+    public void setCloseStream(boolean closeStream) {
+        this.closeStream = closeStream;
+    }
+    
+    
+	/**
+	 * @see com.lowagie.text.DocListener#clearTextWrap()
+	 */
+	public void clearTextWrap() throws DocumentException {
+		// do nothing
+	}
+    /**
+     * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
+     */
+    public boolean setMarginMirroring(boolean MarginMirroring) {
+        return false;
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/Document.java b/LibrarySource/com/lowagie/text/Document.java
new file mode 100644
index 0000000..2603ea2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Document.java
@@ -0,0 +1,916 @@
+/*
+ * $Id: Document.java,v 1.82 2004/12/14 10:32:59 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.util.Date;
+
+/**
+ * A generic Document class.
+ * <P>
+ * All kinds of Text-elements can be added to a <CODE>HTMLDocument</CODE>.
+ * The <CODE>Document</CODE> signals all the listeners when an element has
+ * been added.
+ * <P>
+ * Remark:
+ * <OL>
+ *     <LI>Once a document is created you can add some meta information.
+ *     <LI>You can also set the headers/footers.
+ *     <LI>You have to open the document before you can write content.
+ * <LI>You can only write content (no more meta-formation!) once a document is
+ * opened.
+ * <LI>When you change the header/footer on a certain page, this will be
+ * effective starting on the next page.
+ * <LI>Ater closing the document, every listener (as well as its <CODE>
+ * OutputStream</CODE>) is closed too.
+ * </OL>
+ * Example: <BLOCKQUOTE>
+ *
+ * <PRE>// creation of the document with a certain size and certain margins
+ * <STRONG>Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * </STRONG> try { // creation of the different writers HtmlWriter.getInstance(
+ * <STRONG>document </STRONG>, System.out); PdfWriter.getInstance(
+ * <STRONG>document </STRONG>, new FileOutputStream("text.pdf"));
+ *    // we add some meta information to the document
+ * <STRONG>document.addAuthor("Bruno Lowagie"); </STRONG>
+ * <STRONG>document.addSubject("This is the result of a Test."); </STRONG>
+ *  // we define a header and a footer HeaderFooter header = new
+ * HeaderFooter(new Phrase("This is a header."), false); HeaderFooter footer =
+ * new HeaderFooter(new Phrase("This is page "), new Phrase("."));
+ *    footer.setAlignment(Element.ALIGN_CENTER);
+ * <STRONG>document.setHeader(header); </STRONG>
+ * <STRONG>document.setFooter(footer); </STRONG>// we open the document for
+ * writing <STRONG>document.open(); </STRONG> <STRONG>document.add(new
+ * Paragraph("Hello world")); </STRONG>} catch(DocumentException de) {
+ * System.err.println(de.getMessage()); } <STRONG>document.close(); </STRONG>
+ * </CODE>
+ * </PRE>
+ * 
+ * </BLOCKQUOTE>
+ */
+
+public class Document implements DocListener {
+    
+    // membervariables
+    
+	/** This constant may only be changed by Paulo Soares and/or Bruno Lowagie. */
+	private static final String ITEXT_VERSION = "itext-paulo-154 (itextpdf.sf.net-lowagie.com)";
+    
+	/**
+	 * Allows the pdf documents to be produced without compression for debugging
+	 * purposes.
+	 */
+    public static boolean compress = true; 
+    
+	/** The DocListener. */
+    private ArrayList listeners = new ArrayList();
+    
+	/** Is the document open or not? */
+    protected boolean open;
+    
+	/** Has the document already been closed? */
+    protected boolean close;
+    
+    // membervariables concerning the layout
+    
+	/** The size of the page. */
+    protected Rectangle pageSize;
+    
+	/** The watermark on the pages. */
+    protected Watermark watermark = null;
+    
+	/** margin in x direction starting from the left */
+    protected float marginLeft = 0;
+    
+	/** margin in x direction starting from the right */
+    protected float marginRight = 0;
+    
+	/** margin in y direction starting from the top */
+    protected float marginTop = 0;
+    
+	/** margin in y direction starting from the bottom */
+    protected float marginBottom = 0;
+    
+    protected boolean marginMirroring = false;
+    
+	/** Content of JavaScript onLoad function */
+    protected String javaScript_onLoad = null;
+
+	/** Content of JavaScript onUnLoad function */
+    protected String javaScript_onUnLoad = null;
+
+	/** Style class in HTML body tag */
+    protected String htmlStyleClass = null;
+
+    // headers, footers
+    
+	/** Current pagenumber */
+    protected int pageN = 0;
+    
+	/** This is the textual part of a Page; it can contain a header */
+    protected HeaderFooter header = null;
+    
+	/** This is the textual part of the footer */
+    protected HeaderFooter footer = null;
+    
+    // constructor
+    
+	/**
+	 * Constructs a new <CODE>Document</CODE> -object.
+ */
+    
+    public Document() {
+        this(PageSize.A4);
+    }
+    
+	/**
+	 * Constructs a new <CODE>Document</CODE> -object.
+ *
+	 * @param pageSize
+	 *            the pageSize
+ */
+    
+    public Document(Rectangle pageSize) {
+        this(pageSize, 36, 36, 36, 36);
+    }
+    
+	/**
+	 * Constructs a new <CODE>Document</CODE> -object.
+ *
+	 * @param pageSize
+	 *            the pageSize
+	 * @param marginLeft
+	 *            the margin on the left
+	 * @param marginRight
+	 *            the margin on the right
+	 * @param marginTop
+	 *            the margin on the top
+	 * @param marginBottom
+	 *            the margin on the bottom
+ */
+    
+	public Document(Rectangle pageSize, float marginLeft, float marginRight,
+			float marginTop, float marginBottom) {
+        this.pageSize = pageSize;
+        this.marginLeft = marginLeft;
+        this.marginRight = marginRight;
+        this.marginTop = marginTop;
+        this.marginBottom = marginBottom;
+    }
+    
+    // listener methods
+    
+	/**
+ * Adds a <CODE>DocListener</CODE> to the <CODE>Document</CODE>.
+ *
+	 * @param listener
+	 *            the new DocListener.
+ */
+    
+    public void addDocListener(DocListener listener) {
+        listeners.add(listener);
+    }
+    
+	/**
+ * Removes a <CODE>DocListener</CODE> from the <CODE>Document</CODE>.
+ *
+	 * @param listener
+	 *            the DocListener that has to be removed.
+ */
+    
+    public void removeDocListener(DocListener listener) {
+        listeners.remove(listener);
+    }
+    
+    // methods implementing the DocListener interface
+    
+	/**
+	 * Adds an <CODE>Element</CODE> to the <CODE>Document</CODE>.
+ *
+	 * @param element
+	 *            the <CODE>Element</CODE> to add
+	 * @return <CODE>true</CODE> if the element was added, <CODE>false
+	 *         </CODE> if not
+	 * @throws DocumentException
+	 *             when a document isn't open yet, or has been closed
+ */
+    
+    public boolean add(Element element) throws DocumentException {
+        if (close) {
+			throw new DocumentException(
+					"The document has been closed. You can't add any Elements.");
+        }
+        int type = element.type();
+        if (open) {
+			if (!(type == Element.CHUNK || type == Element.PHRASE
+					|| type == Element.PARAGRAPH || type == Element.TABLE
+					|| type == Element.PTABLE
+					|| type == Element.MULTI_COLUMN_TEXT
+					|| type == Element.ANCHOR || type == Element.ANNOTATION
+					|| type == Element.CHAPTER || type == Element.SECTION
+					|| type == Element.LIST || type == Element.LISTITEM
+					|| type == Element.RECTANGLE || type == Element.JPEG
+					|| type == Element.IMGRAW || type == Element.IMGTEMPLATE || type == Element.GRAPHIC)) {
+				throw new DocumentException(
+						"The document is open; you can only add Elements with content.");
+			}
+		} else {
+			if (!(type == Element.HEADER || type == Element.TITLE
+					|| type == Element.SUBJECT || type == Element.KEYWORDS
+					|| type == Element.AUTHOR || type == Element.PRODUCER
+					|| type == Element.CREATOR || type == Element.CREATIONDATE)) {
+				throw new DocumentException(
+						"The document is not open yet; you can only add Meta information.");
+            }
+        }
+        boolean success = false;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            success |= listener.add(element);
+        }
+        return success;
+    }
+    
+	/**
+ * Opens the document.
+ * <P>
+	 * Once the document is opened, you can't write any Header- or
+	 * Meta-information anymore. You have to open the document before you can
+	 * begin to add content to the body of the document.
+ */
+    
+    public void open() {
+		if (!close) {
+            open = true;
+        }
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setPageSize(pageSize);
+			listener.setMargins(marginLeft, marginRight, marginTop,
+					marginBottom);
+            listener.open();
+        }
+    }
+    
+	/**
+ * Sets the pagesize.
+ *
+	 * @param pageSize
+	 *            the new pagesize
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean setPageSize(Rectangle pageSize) {
+        this.pageSize = pageSize;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setPageSize(pageSize);
+        }
+        return true;
+    }
+    
+	/**
+ * Sets the <CODE>Watermark</CODE>.
+ *
+	 * @param watermark
+	 *            the watermark to add
+	 * @return <CODE>true</CODE> if the element was added, <CODE>false
+	 *         </CODE> if not.
+ */
+    
+    public boolean add(Watermark watermark) {
+        this.watermark = watermark;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.add(watermark);
+        }
+        return true;
+    }
+    
+	/**
+ * Removes the <CODE>Watermark</CODE>.
+ */
+    
+    public void removeWatermark() {
+        this.watermark = null;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.removeWatermark();
+        }
+    }
+    
+	/**
+ * Sets the margins.
+ *
+	 * @param marginLeft
+	 *            the margin on the left
+	 * @param marginRight
+	 *            the margin on the right
+	 * @param marginTop
+	 *            the margin on the top
+	 * @param marginBottom
+	 *            the margin on the bottom
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+	public boolean setMargins(float marginLeft, float marginRight,
+			float marginTop, float marginBottom) {
+        this.marginLeft = marginLeft;
+        this.marginRight = marginRight;
+        this.marginTop = marginTop;
+        this.marginBottom = marginBottom;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+			listener.setMargins(marginLeft, marginRight, marginTop,
+					marginBottom);
+        }
+        return true;
+    }
+    
+	/**
+ * Signals that an new page has to be started.
+ *
+	 * @return <CODE>true</CODE> if the page was added, <CODE>false</CODE>
+	 *         if not.
+	 * @throws DocumentException
+	 *             when a document isn't open yet, or has been closed
+ */
+    
+    public boolean newPage() throws DocumentException {
+        if (!open || close) {
+            return false;
+        }
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.newPage();
+        }
+        return true;
+    }
+    
+	/**
+ * Changes the header of this document.
+ *
+	 * @param header
+	 *            the new header
+ */
+    
+    public void setHeader(HeaderFooter header) {
+        this.header = header;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setHeader(header);
+        }
+    }
+    
+	/**
+ * Resets the header of this document.
+ */
+    
+    public void resetHeader() {
+        this.header = null;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.resetHeader();
+        }
+    }
+    
+	/**
+ * Changes the footer of this document.
+ *
+	 * @param footer
+	 *            the new footer
+ */
+    
+    public void setFooter(HeaderFooter footer) {
+        this.footer = footer;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setFooter(footer);
+        }
+    }
+    
+	/**
+ * Resets the footer of this document.
+ */
+    
+    public void resetFooter() {
+        this.footer = null;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.resetFooter();
+        }
+    }
+    
+	/**
+ * Sets the page number to 0.
+ */
+    
+    public void resetPageCount() {
+        pageN = 0;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.resetPageCount();
+        }
+    }
+    
+	/**
+ * Sets the page number.
+ *
+	 * @param pageN
+	 *            the new page number
+ */
+    
+    public void setPageCount(int pageN) {
+        this.pageN = pageN;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setPageCount(pageN);
+        }
+    }
+    
+	/**
+ * Returns the current page number.
+ *
+ * @return the current page number
+ */
+    
+    public int getPageNumber() {
+        return this.pageN;
+    }
+    
+	/**
+ * Closes the document.
+ * <P>
+	 * Once all the content has been written in the body, you have to close the
+	 * body. After that nothing can be written to the body anymore.
+ */
+    
+    public void close() {
+		if (!close) {
+            open = false;
+            close = true;
+        }
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.close();
+        }
+    }
+    
+    // methods concerning the header or some meta information
+    
+	/**
+ * Adds a user defined header to the document.
+ *
+	 * @param name
+	 *            the name of the header
+	 * @param content
+	 *            the content of the header
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addHeader(String name, String content) {
+        try {
+            return add(new Header(name, content));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the title to a Document.
+ *
+	 * @param title
+	 *            the title
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addTitle(String title) {
+        try {
+            return add(new Meta(Element.TITLE, title));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the subject to a Document.
+ *
+	 * @param subject
+	 *            the subject
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addSubject(String subject) {
+        try {
+            return add(new Meta(Element.SUBJECT, subject));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the keywords to a Document.
+ *
+	 * @param keywords
+	 *            adds the keywords to the document
+ * @return <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addKeywords(String keywords) {
+        try {
+            return add(new Meta(Element.KEYWORDS, keywords));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the author to a Document.
+ *
+	 * @param author
+	 *            the name of the author
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addAuthor(String author) {
+        try {
+            return add(new Meta(Element.AUTHOR, author));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the creator to a Document.
+ *
+	 * @param creator
+	 *            the name of the creator
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addCreator(String creator) {
+        try {
+            return add(new Meta(Element.CREATOR, creator));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the producer to a Document.
+ *
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addProducer() {
+        try {
+            return add(new Meta(Element.PRODUCER, "iText by lowagie.com"));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+	/**
+ * Adds the current date and time to a Document.
+ *
+ * @return	<CODE>true</CODE> if successful, <CODE>false</CODE> otherwise
+ */
+    
+    public boolean addCreationDate() {
+        try {
+			/* bugfix by 'taqua' (Thomas) */
+			final SimpleDateFormat sdf = new SimpleDateFormat(
+					"EEE MMM dd HH:mm:ss zzz yyyy");
+			return add(new Meta(Element.CREATIONDATE, sdf.format(new Date())));
+		} catch (DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+    // methods to get the layout of the document.
+    
+	/**
+ * Returns the left margin.
+ *
+ * @return	the left margin
+ */
+    
+    public float leftMargin() {
+        return marginLeft;
+    }
+    
+	/**
+ * Return the right margin.
+ *
+ * @return	the right margin
+ */
+    
+    public float rightMargin() {
+        return marginRight;
+    }
+    
+	/**
+ * Returns the top margin.
+ *
+ * @return	the top margin
+ */
+    
+    public float topMargin() {
+        return marginTop;
+    }
+    
+	/**
+ * Returns the bottom margin.
+ *
+ * @return	the bottom margin
+ */
+    
+    public float bottomMargin() {
+        return marginBottom;
+    }
+    
+	/**
+ * Returns the lower left x-coordinate.
+ *
+ * @return	the lower left x-coordinate
+ */
+    
+    public float left() {
+        return pageSize.left(marginLeft);
+    }
+    
+	/**
+ * Returns the upper right x-coordinate.
+ *
+ * @return	the upper right x-coordinate
+ */
+    
+    public float right() {
+        return pageSize.right(marginRight);
+    }
+    
+	/**
+ * Returns the upper right y-coordinate.
+ *
+ * @return	the upper right y-coordinate
+ */
+    
+    public float top() {
+        return pageSize.top(marginTop);
+    }
+    
+	/**
+ * Returns the lower left y-coordinate.
+ *
+ * @return	the lower left y-coordinate
+ */
+    
+    public float bottom() {
+        return pageSize.bottom(marginBottom);
+    }
+    
+	/**
+ * Returns the lower left x-coordinate considering a given margin.
+ *
+	 * @param margin
+	 *            a margin
+ * @return	the lower left x-coordinate
+ */
+    
+    public float left(float margin) {
+        return pageSize.left(marginLeft + margin);
+    }
+    
+	/**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+	 * @param margin
+	 *            a margin
+ * @return	the upper right x-coordinate
+ */
+    
+    public float right(float margin) {
+        return pageSize.right(marginRight + margin);
+    }
+    
+	/**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+	 * @param margin
+	 *            a margin
+ * @return	the upper right y-coordinate
+ */
+    
+    public float top(float margin) {
+        return pageSize.top(marginTop + margin);
+    }
+    
+	/**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+	 * @param margin
+	 *            a margin
+ * @return	the lower left y-coordinate
+ */
+    
+    public float bottom(float margin) {
+        return pageSize.bottom(marginBottom + margin);
+    }
+    
+	/**
+ * Gets the pagesize.
+	 * 
+ * @return the page size
+ */
+    
+	public Rectangle getPageSize() {
+        return this.pageSize;
+    }
+    
+	/**
+	 * Checks if the document is open.
+	 * 
+     * @return <CODE>true</CODE> if the document is open
+     */    
+    public boolean isOpen() {
+        return open;
+    }
+    
+	/**
+	 * Gets the iText version.
+	 * 
+     * @return iText version
+     */    
+    public static String getVersion() {
+        return ITEXT_VERSION;
+    }
+
+	/**
+ * Adds a JavaScript onLoad function to the HTML body tag
+ *
+	 * @param code
+	 *            the JavaScript code to be executed on load of the HTML page
+ */
+    
+    public void setJavaScript_onLoad(String code) {
+        this.javaScript_onLoad = code;
+    }
+
+	/**
+ * Gets the JavaScript onLoad command.
+	 * 
+ * @return the JavaScript onLoad command
+ */
+
+    public String getJavaScript_onLoad() {
+        return this.javaScript_onLoad;
+    }
+
+	/**
+ * Adds a JavaScript onUnLoad function to the HTML body tag
+ *
+	 * @param code
+	 *            the JavaScript code to be executed on unload of the HTML page
+ */
+    
+    public void setJavaScript_onUnLoad(String code) {
+        this.javaScript_onUnLoad = code;
+    }
+
+	/**
+ * Gets the JavaScript onUnLoad command.
+	 * 
+ * @return the JavaScript onUnLoad command
+ */
+
+    public String getJavaScript_onUnLoad() {
+        return this.javaScript_onUnLoad;
+    }
+
+	/**
+ * Adds a style class to the HTML body tag
+ *
+	 * @param htmlStyleClass
+	 *            the style class for the HTML body tag
+ */
+    
+    public void setHtmlStyleClass(String htmlStyleClass) {
+        this.htmlStyleClass = htmlStyleClass;
+    }
+
+	/**
+ * Gets the style class of the HTML body tag
+ *
+ * @return		the style class of the HTML body tag
+ */
+    
+    public String getHtmlStyleClass() {
+        return this.htmlStyleClass;
+    }
+
+	/**
+ 	 * @see com.lowagie.text.DocListener#clearTextWrap()
+     */
+	public void clearTextWrap() throws DocumentException {
+		if (open && !close) {
+			DocListener listener;
+			for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+				listener = (DocListener) iterator.next();
+				listener.clearTextWrap();
+			}
+		}
+	}
+    
+    /**
+     * Set the margin mirroring. It will mirror margins for odd/even pages.
+     * <p>
+     * Note: it will not work with {@link Table}.
+	 * 
+	 * @param marginMirroring
+	 *            <CODE>true</CODE> to mirror the margins
+     * @return always <CODE>true</CODE>
+     */    
+    public boolean setMarginMirroring(boolean marginMirroring) {
+        this.marginMirroring = marginMirroring;
+        DocListener listener;
+		for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            listener = (DocListener) iterator.next();
+            listener.setMarginMirroring(marginMirroring);
+        }
+        return true;
+    }
+    
+    /**
+     * Gets the margin mirroring flag.
+	 * 
+     * @return the margin mirroring flag
+     */    
+    public boolean isMarginMirroring() {
+        return marginMirroring;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/DocumentException.java b/LibrarySource/com/lowagie/text/DocumentException.java
new file mode 100644
index 0000000..00e098e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/DocumentException.java
@@ -0,0 +1,186 @@
+/*
+ * $Id: DocumentException.java,v 1.50 2004/12/14 11:52:46 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ */
+
+package com.lowagie.text;
+
+/**
+ * Signals that an error has occurred in a <CODE>Document</CODE>.
+ *
+ * @see		BadElementException
+ * @see		Document
+ * @see		DocWriter
+ * @see		DocListener
+ */
+
+public class DocumentException extends Exception {
+    private Exception ex;
+
+    /**
+     * Creates a Document exception.
+     * @param ex an exception that has to be turned into a DocumentException
+     */
+    public DocumentException(Exception ex) {
+        this.ex = ex;
+    }
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>DocumentException</CODE> whithout a message.
+ */
+    
+    public DocumentException() {
+        super();
+    }
+    
+/**
+ * Constructs a <code>DocumentException</code> with a message.
+ *
+ * @param		message			a message describing the exception
+ */
+    
+    public DocumentException(String message) {
+        super(message);
+    }
+
+    /**
+     * We print the message of the checked exception 
+     * @return the error message
+     */
+    public String getMessage() {
+        if (ex == null)
+            return super.getMessage();
+        else
+            return ex.getMessage();
+    }
+
+    /**
+     * and make sure we also produce a localized version 
+     * @return a localized message
+     */
+    public String getLocalizedMessage() {
+        if (ex == null)
+            return super.getLocalizedMessage();
+        else
+            return ex.getLocalizedMessage();
+    }
+
+    /**
+     * The toString() is changed to be prefixed with ExceptionConverter 
+     * @return the String version of the exception
+     */
+    public String toString() {
+        if (ex == null)
+            return super.toString();
+        else
+            return split(getClass().getName()) + ": " + ex;
+    }
+
+    /** we have to override this as well */
+    public void printStackTrace() {
+        printStackTrace(System.err);
+    }
+
+    /**
+     * here we prefix, with s.print(), not s.println(), the stack
+     * trace with "ExceptionConverter:" 
+     * @param s a printstream object
+     */
+    public void printStackTrace(java.io.PrintStream s) {
+        if (ex == null)
+            super.printStackTrace(s);
+        else {
+            synchronized (s) {
+                s.print(split(getClass().getName()) + ": ");
+                ex.printStackTrace(s);
+            }
+        }
+    }
+
+    /**
+     * Again, we prefix the stack trace with "ExceptionConverter:" 
+     * @param s A PrintWriter object
+     */
+    public void printStackTrace(java.io.PrintWriter s) {
+        if (ex == null)
+            super.printStackTrace(s);
+        else {
+            synchronized (s) {
+                s.print(split(getClass().getName()) + ": ");
+                ex.printStackTrace(s);
+            }
+        }
+    }
+
+    /**
+     * Removes everything in a String that comes before a '.'
+     * @param s the original string
+     * @return the part that comes after the dot
+     */
+    private static String split(String s) {
+        int i = s.lastIndexOf('.');
+        if (i < 0)
+            return s;
+        else
+            return s.substring(i + 1);
+    }
+    
+    /** requests to fill in the stack trace we will have to ignore.
+     * We can't throw an exception here, because this method
+     * is called by the constructor of Throwable */
+//    public Throwable fillInStackTrace() {
+//        if (ex == null)
+//            return super.fillInStackTrace();
+//        else
+//            return this;
+//    }
+
+}
diff --git a/LibrarySource/com/lowagie/text/Element.java b/LibrarySource/com/lowagie/text/Element.java
new file mode 100644
index 0000000..a5a448f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Element.java
@@ -0,0 +1,319 @@
+/*
+ * $Id: Element.java,v 1.31 2002/06/20 13:30:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+
+/**
+ * Interface for a text element.
+ * <P>
+ * Remark: I looked at the interface javax.swing.text.Element, but
+ * I decided to write my own text-classes for two reasons:
+ * <OL>
+ * <LI>The javax.swing.text-classes may be very generic, I think
+ * they are overkill: they are to heavy for what they have to do.
+ * <LI>A lot of people using iText (formerly known as rugPdf), still use JDK1.1.x.
+ * I try to keep the Java2 requirements limited to the Collection classes
+ * (I think they're really great). However, if I use the javax.swing.text
+ * classes, it will become very difficult to downgrade rugPdf.
+ * </OL>
+ *
+ * @see		Anchor
+ * @see		Cell
+ * @see		Chapter
+ * @see		Chunk
+ * @see		Graphic
+ * @see		Header
+ * @see		Image
+ * @see		Jpeg
+ * @see		List
+ * @see		ListItem
+ * @see		Meta
+ * @see		Paragraph
+ * @see		Phrase
+ * @see		Rectangle
+ * @see		Row
+ * @see		Section
+ * @see		Table
+ */
+
+public interface Element {
+    
+    // static membervariables (meta information)
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int	HEADER = 0;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int TITLE = 1;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int SUBJECT = 2;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int KEYWORDS = 3;
+    
+/** This is a possible type of <CODE>Element</CIDE>. */
+    public static final int AUTHOR = 4;
+    
+/** This is a possible type of <CODE>Element</CIDE>. */
+    public static final int PRODUCER = 5;
+    
+/** This is a possible type of <CODE>Element</CIDE>. */
+    public static final int CREATIONDATE = 6;
+    
+/** This is a possible type of <CODE>Element</CIDE>. */
+    public static final int CREATOR = 7;
+    
+    // static membervariables (content)
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int CHUNK = 10;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int PHRASE = 11;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int PARAGRAPH = 12;
+    
+/** This is a possible type of <CODE>Element</CODE> */
+    public static final int SECTION = 13;
+    
+/** This is a possible type of <CODE>Element</CODE> */
+    public static final int LIST = 14;
+    
+/** This is a possible type of <CODE>Element</CODE> */
+    public static final int LISTITEM = 15;
+    
+/** This is a possible type of <CODE>Element</CODE> */
+    public static final int CHAPTER = 16;
+    
+/** This is a possible type of <CODE>Element</CODE> */
+    public static final int ANCHOR = 17;
+    
+    // static membervariables (tables)
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int CELL = 20;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int ROW = 21;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int TABLE = 22;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int PTABLE = 23;
+    
+    // static membervariables (annotations)
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int ANNOTATION = 29;
+    
+    // static membervariables (geometric figures)
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int RECTANGLE = 30;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int JPEG = 32;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int IMGRAW = 34;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int IMGTEMPLATE = 35;
+    
+/** This is a possible type of <CODE>Element</CODE>. */
+    public static final int GRAPHIC = 39;
+    
+   /** This is a possible type of <CODE>Element</CODE>. */
+    public static final int MULTI_COLUMN_TEXT = 40;
+
+    // static membervariables (alignment)
+       
+/**
+ * A possible value for paragraph alignment.  This
+ * specifies that the text is aligned to the left
+ * indent and extra whitespace should be placed on
+ * the right.
+ */
+    public static final int ALIGN_UNDEFINED = -1;
+    
+/**
+ * A possible value for paragraph alignment.  This
+ * specifies that the text is aligned to the left
+ * indent and extra whitespace should be placed on
+ * the right.
+ */
+    public static final int ALIGN_LEFT = 0;
+    
+/**
+ * A possible value for paragraph alignment.  This
+ * specifies that the text is aligned to the center
+ * and extra whitespace should be placed equally on
+ * the left and right.
+ */
+    public static final int ALIGN_CENTER = 1;
+    
+/**
+ * A possible value for paragraph alignment.  This
+ * specifies that the text is aligned to the right
+ * indent and extra whitespace should be placed on
+ * the left.
+ */
+    public static final int ALIGN_RIGHT = 2;
+    
+/**
+ * A possible value for paragraph alignment.  This
+ * specifies that extra whitespace should be spread
+ * out through the rows of the paragraph with the
+ * text lined up with the left and right indent
+ * except on the last line which should be aligned
+ * to the left.
+ */
+    public static final int ALIGN_JUSTIFIED = 3;
+    
+/**
+ * A possible value for vertical alignment.
+ */
+    
+    public static final int ALIGN_TOP = 4;
+    
+/**
+ * A possible value for vertical alignment.
+ */
+    
+    public static final int ALIGN_MIDDLE = 5;
+    
+/**
+ * A possible value for vertical alignment.
+ */
+    
+    public static final int ALIGN_BOTTOM = 6;
+    
+/**
+ * A possible value for vertical alignment.
+ */
+    public static final int ALIGN_BASELINE = 7;
+
+/**
+ * Does the same as ALIGN_JUSTIFIED but the last line is also spread out.
+ */
+    public static final int ALIGN_JUSTIFIED_ALL = 8;
+
+    // static member variables for CCITT compression
+    
+    /** Pure two-dimensional encoding (Group 4)
+     */    
+    public static final int CCITTG4 = 0x100;
+    /** Pure one-dimensional encoding (Group 3, 1-D)
+     */    
+    public static final int CCITTG3_1D = 0x101;
+    /** Mixed one- and two-dimensional encoding (Group 3, 2-D)
+     */    
+    public static final int CCITTG3_2D = 0x102;    
+    /** A flag indicating whether 1-bits are to be interpreted as black pixels
+     *  and 0-bits as white pixels,
+     */    
+    public static final int CCITT_BLACKIS1 = 1;
+    /** A flag indicating whether the filter expects extra 0-bits before each
+     *  encoded line so that the line begins on a byte boundary.
+     */
+    public static final int CCITT_ENCODEDBYTEALIGN = 2;
+    /** A flag indicating whether end-of-line bit patterns are required to be
+     *  present in the encoding.
+     */    
+    public static final int CCITT_ENDOFLINE = 4;
+    /** A flag indicating whether the filter expects the encoded data to be
+     *  terminated by an end-of-block pattern, overriding the Rows
+     *  parameter. The use of this flag will set the key /EndOfBlock to false.
+     */    
+    public static final int CCITT_ENDOFBLOCK = 8;
+    
+    
+    // methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener);
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type();
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks();
+    
+/**
+ * Gets the content of the text element.
+ *
+ * @return	a type
+ */
+    
+    public String toString();
+}
+
diff --git a/LibrarySource/com/lowagie/text/ElementListener.java b/LibrarySource/com/lowagie/text/ElementListener.java
new file mode 100644
index 0000000..5e9a8cf
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ElementListener.java
@@ -0,0 +1,75 @@
+/*
+ * $Id: ElementListener.java,v 1.48 2004/12/14 11:52:46 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.EventListener;
+
+/**
+ * A class that implements <CODE>ElementListener</CODE> will perform some
+ * actions when an <CODE>Element</CODE> is added.
+ *
+ * @see		DocListener
+ */
+
+public interface ElementListener extends EventListener {
+    
+    // methods
+    
+/**
+ * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
+ * 
+ * @param element a high level object
+ * @return	<CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
+ * @throws	DocumentException	when a document isn't open yet, or has been closed
+ */
+    
+    public boolean add(Element element) throws DocumentException;
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/ElementTags.java b/LibrarySource/com/lowagie/text/ElementTags.java
new file mode 100644
index 0000000..8ecca0f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ElementTags.java
@@ -0,0 +1,461 @@
+/*
+ * $Id: ElementTags.java,v 1.84 2005/04/06 07:01:18 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright (c) 2001, 2002 Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class ElementTags {
+    
+/** the root tag. */
+    public static final String ITEXT = "itext";
+    
+/** attribute of the root and annotation tag (also a special tag within a chapter or section) */
+    public static final String TITLE = "title";
+    
+/** attribute of the root tag */
+    public static final String SUBJECT = "subject";
+    
+/** attribute of the root tag */
+    public static final String KEYWORDS = "keywords";
+    
+/** attribute of the root tag */
+    public static final String AUTHOR = "author";
+    
+/** attribute of the root tag */
+    public static final String CREATIONDATE = "creationdate";
+    
+/** attribute of the root tag */
+    public static final String PRODUCER = "producer";
+    
+    // Chapters and Sections
+    
+/** the chapter tag */
+    public static final String CHAPTER = "chapter";
+    
+/** the section tag */
+    public static final String SECTION = "section";
+    
+/** attribute of section/chapter tag */
+    public static final String NUMBERDEPTH = "numberdepth";
+    
+/** attribute of section/chapter tag */
+    public static final String DEPTH = "depth";
+    
+/** attribute of section/chapter tag */
+    public static final String NUMBER = "number";
+    
+/** attribute of section/chapter tag */
+    public static final String INDENT = "indent";
+    
+/** attribute of chapter/section/paragraph/table/cell tag */
+    public static final String LEFT = "left";
+    
+/** attribute of chapter/section/paragraph/table/cell tag */
+    public static final String RIGHT = "right";
+    
+    // Phrases, Anchors, Lists and Paragraphs
+    
+/** the phrase tag */
+    public static final String PHRASE = "phrase";
+    
+/** the anchor tag */
+    public static final String ANCHOR = "anchor";
+    
+/** the list tag */
+    public static final String LIST = "list";
+    
+/** the listitem tag */
+    public static final String LISTITEM = "listitem";
+    
+/** the paragraph tag */
+    public static final String PARAGRAPH = "paragraph";
+    
+/** attribute of phrase/paragraph/cell tag */
+    public static final String LEADING = "leading";
+    
+/** attribute of paragraph/image/table tag */
+    public static final String ALIGN = "align";
+    
+/** attribute of paragraph */
+    public static final String KEEPTOGETHER = "keeptogether";
+    
+/** attribute of anchor tag */
+    public static final String NAME = "name";
+    
+/** attribute of anchor tag */
+    public static final String REFERENCE = "reference";
+    
+/** attribute of list tag */
+    public static final String LISTSYMBOL = "listsymbol";
+    
+/** attribute of list tag */
+    public static final String NUMBERED = "numbered";
+    
+/** attribute of the list tag */
+    public static final String LETTERED = "lettered";
+
+/** attribute of list tag */
+    public static final String FIRST = "first";
+    
+/** attribute of list tag */
+    public static final String SYMBOLINDENT = "symbolindent";
+    
+/** attribute of list tag */
+    public static final String INDENTATIONLEFT = "indentationleft";
+    
+/** attribute of list tag */
+    public static final String INDENTATIONRIGHT = "indentationright";
+    
+    // Chunks
+    
+/** the chunk tag */
+    public static final String IGNORE = "ignore";
+    
+/** the chunk tag */
+    public static final String ENTITY = "entity";
+    
+/** the chunk tag */
+    public static final String ID = "id";
+    
+/** the chunk tag */
+    public static final String CHUNK = "chunk";
+    
+/** attribute of the chunk tag */
+    public static final String ENCODING = "encoding";
+    
+/** attribute of the chunk tag */
+    public static final String EMBEDDED = "embedded";
+    
+/** attribute of the chunk/table/cell tag */
+    public static final String COLOR = "color";
+    
+/** attribute of the chunk/table/cell tag */
+    public static final String RED = "red";
+    
+/** attribute of the chunk/table/cell tag */
+    public static final String GREEN = "green";
+    
+/** attribute of the chunk/table/cell tag */
+    public static final String BLUE = "blue";
+    
+/** attribute of the chunk tag */
+    public static final String SUBSUPSCRIPT = Chunk.SUBSUPSCRIPT.toLowerCase();
+    
+/** attribute of the chunk tag */
+    public static final String LOCALGOTO = Chunk.LOCALGOTO.toLowerCase();
+    
+/** attribute of the chunk tag */
+    public static final String REMOTEGOTO = Chunk.REMOTEGOTO.toLowerCase();
+    
+/** attribute of the chunk tag */
+    public static final String LOCALDESTINATION = Chunk.LOCALDESTINATION.toLowerCase();
+    
+/** attribute of the chunk tag */
+    public static final String GENERICTAG = Chunk.GENERICTAG.toLowerCase();
+    
+    // tables/cells
+    
+/** the table tag */
+    public static final String TABLE = "table";
+    
+/** the cell tag */
+    public static final String ROW = "row";
+    
+/** the cell tag */
+    public static final String CELL = "cell";
+    
+/** attribute of the table tag */
+    public static final String COLUMNS = "columns";
+    
+/** attribute of the table tag */
+    public static final String LASTHEADERROW = "lastHeaderRow";
+    
+/** attribute of the table tag */
+    public static final String CELLPADDING = "cellpadding";
+    
+/** attribute of the table tag */
+    public static final String CELLSPACING = "cellspacing";
+    
+/** attribute of the table tag */
+    public static final String OFFSET = "offset";
+    
+/** attribute of the table tag */
+    public static final String WIDTHS = "widths";
+    
+/** attribute of the table tag */
+    public static final String TABLEFITSPAGE = "tablefitspage";
+    
+/** attribute of the table tag */
+    public static final String CELLSFITPAGE = "cellsfitpage";
+    
+/** attribute of the cell tag */
+    public static final String HORIZONTALALIGN = "horizontalalign";
+    
+/** attribute of the cell tag */
+    public static final String VERTICALALIGN = "verticalalign";
+    
+/** attribute of the cell tag */
+    public static final String COLSPAN = "colspan";
+    
+/** attribute of the cell tag */
+    public static final String ROWSPAN = "rowspan";
+    
+/** attribute of the cell tag */
+    public static final String HEADER = "header";
+    
+/** attribute of the cell tag */
+    public static final String NOWRAP = "nowrap";
+    
+/** attribute of the table/cell tag */
+    public static final String BORDERWIDTH = "borderwidth";
+    
+/** attribute of the table/cell tag */
+    public static final String TOP = "top";
+    
+/** attribute of the table/cell tag */
+    public static final String BOTTOM = "bottom";
+    
+/** attribute of the table/cell tag */
+    public static final String WIDTH = "width";
+    
+/** attribute of the table/cell tag */
+    public static final String BORDERCOLOR = "bordercolor";
+    
+/** attribute of the table/cell tag */
+    public static final String BACKGROUNDCOLOR = "backgroundcolor";
+    
+/** attribute of the table/cell tag */
+    public static final String BGRED = "bgred";
+    
+/** attribute of the table/cell tag */
+    public static final String BGGREEN = "bggreen";
+    
+/** attribute of the table/cell tag */
+    public static final String BGBLUE = "bgblue";
+    
+/** attribute of the table/cell tag */
+    public static final String GRAYFILL = "grayfill";
+    
+    // Misc
+    
+/** the image tag */
+    public static final String IMAGE = "image";
+    
+/** attribute of the image and annotation tag */
+    public static final String URL = "url";
+    
+/** attribute of the image tag */
+    public static final String UNDERLYING = "underlying";
+    
+/** attribute of the image tag */
+    public static final String TEXTWRAP = "textwrap";
+    
+/** attribute of the image tag */
+    public static final String ALT = "alt";
+    
+/** attribute of the image tag */
+    public static final String ABSOLUTEX = "absolutex";
+    
+/** attribute of the image tag */
+    public static final String ABSOLUTEY = "absolutey";
+    
+/** attribute of the image tag */
+    public static final String PLAINWIDTH = "plainwidth";
+    
+/** attribute of the image tag */
+    public static final String PLAINHEIGHT = "plainheight";
+    
+/** attribute of the image tag */
+    public static final String SCALEDWIDTH = "scaledwidth";
+    
+/** attribute of the image tag */
+    public static final String SCALEDHEIGHT = "scaledheight";
+    
+/** attribute of the image tag */
+    public static final String  ROTATION = "rotation";
+    
+/** the newpage tag */
+    public static final String NEWPAGE = "newpage";
+    
+/** the newpage tag */
+    public static final String NEWLINE = "newline";
+    
+/** the annotation tag */
+    public static final String ANNOTATION = "annotation";
+    
+/** attribute of the annotation tag */
+    public static String FILE = "file";
+    
+/** attribute of the annotation tag */
+    public static String DESTINATION = "destination";
+    
+/** attribute of the annotation tag */
+    public static String PAGE = "page";
+    
+/** attribute of the annotation tag */
+    public static String NAMED = "named";
+    
+/** attribute of the annotation tag */
+    public static String APPLICATION = "application";
+    
+/** attribute of the annotation tag */
+    public static String PARAMETERS = "parameters";
+    
+/** attribute of the annotation tag */
+    public static String OPERATION = "operation";
+    
+/** attribute of the annotation tag */
+    public static String DEFAULTDIR = "defaultdir";
+    
+/** attribute of the annotation tag */
+    public static String LLX = "llx";
+    
+/** attribute of the annotation tag */
+    public static String LLY = "lly";
+    
+/** attribute of the annotation tag */
+    public static String URX = "urx";
+    
+/** attribute of the annotation tag */
+    public static String URY = "ury";
+    
+/** attribute of the annotation tag */
+    public static final String CONTENT = "content";
+    
+    // alignment attribute values
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_LEFT = "Left";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_CENTER = "Center";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_RIGHT = "Right";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_JUSTIFIED = "Justify";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_JUSTIFIED_ALL = "JustifyAll";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_TOP = "Top";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_MIDDLE = "Middle";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_BOTTOM = "Bottom";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_BASELINE = "Baseline";
+    
+/** the possible value of an alignment attribute */
+    public static final String DEFAULT = "Default";
+    
+/** the possible value of an alignment attribute */
+    public static final String UNKNOWN = "unknown";
+    
+/** the possible value of an alignment attribute */
+    public static final String FONT = "font";
+    
+/** the possible value of an alignment attribute */
+    public static final String SIZE = "size";
+    
+/** the possible value of an alignment attribute */
+    public static final String STYLE = "fontstyle";
+    
+/** the possible value of a tag */
+    public static final String HORIZONTALRULE = "horizontalrule";
+
+    /** the possible value of a tag */
+    public static final String PAGE_SIZE  = "pagesize";
+
+    /** the possible value of a tag */
+    public static final String ORIENTATION  = "orientation";
+    
+    // methods
+    
+/**
+ * Translates the alignment value.
+ *
+ * @param   alignment   the alignment value
+ * @return  the translated value
+ */
+    
+    public static String getAlignment(int alignment) {
+        switch(alignment) {
+            case Element.ALIGN_LEFT:
+                return ALIGN_LEFT;
+            case Element.ALIGN_CENTER:
+                return ALIGN_CENTER;
+            case Element.ALIGN_RIGHT:
+                return ALIGN_RIGHT;
+            case Element.ALIGN_JUSTIFIED:
+            case Element.ALIGN_JUSTIFIED_ALL:
+                return ALIGN_JUSTIFIED;
+            case Element.ALIGN_TOP:
+                return ALIGN_TOP;
+            case Element.ALIGN_MIDDLE:
+                return ALIGN_MIDDLE;
+            case Element.ALIGN_BOTTOM:
+                return ALIGN_BOTTOM;
+            case Element.ALIGN_BASELINE:
+                return ALIGN_BASELINE;
+                default:
+                    return DEFAULT;
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/Entities.java b/LibrarySource/com/lowagie/text/Entities.java
new file mode 100644
index 0000000..1f1b596
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Entities.java
@@ -0,0 +1,388 @@
+/*
+ * $Id: Entities.java,v 1.43 2004/12/14 11:52:46 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.HashMap;
+
+/**
+ * This class contains entities that can be used in an entity tag.
+ */
+
+public class Entities {
+    
+    /** This is a map that contains all possible id values of the entity tag. */
+    public static final HashMap map;
+    
+    static {
+        map = new HashMap();
+        map.put("169", new Integer(227));
+        map.put("172", new Integer(216));
+        map.put("174", new Integer(210));
+        map.put("177", new Integer(177));
+        map.put("215", new Integer(180));
+        map.put("247", new Integer(184));
+        map.put("8230", new Integer(188));
+        map.put("8242", new Integer(162));
+        map.put("8243", new Integer(178));
+        map.put("8260", new Integer(164));
+        map.put("8364", new Integer(240));
+        map.put("8465", new Integer(193));
+        map.put("8472", new Integer(195));
+        map.put("8476", new Integer(194));
+        map.put("8482", new Integer(212));
+        map.put("8501", new Integer(192));
+        map.put("8592", new Integer(172));
+        map.put("8593", new Integer(173));
+        map.put("8594", new Integer(174));
+        map.put("8595", new Integer(175));
+        map.put("8596", new Integer(171));
+        map.put("8629", new Integer(191));
+        map.put("8656", new Integer(220));
+        map.put("8657", new Integer(221));
+        map.put("8658", new Integer(222));
+        map.put("8659", new Integer(223));
+        map.put("8660", new Integer(219));
+        map.put("8704", new Integer(34));
+        map.put("8706", new Integer(182));
+        map.put("8707", new Integer(36));
+        map.put("8709", new Integer(198));
+        map.put("8711", new Integer(209));
+        map.put("8712", new Integer(206));
+        map.put("8713", new Integer(207));
+        map.put("8717", new Integer(39));
+        map.put("8719", new Integer(213));
+        map.put("8721", new Integer(229));
+        map.put("8722", new Integer(45));
+        map.put("8727", new Integer(42));
+        map.put("8729", new Integer(183));
+        map.put("8730", new Integer(214));
+        map.put("8733", new Integer(181));
+        map.put("8734", new Integer(165));
+        map.put("8736", new Integer(208));
+        map.put("8743", new Integer(217));
+        map.put("8744", new Integer(218));
+        map.put("8745", new Integer(199));
+        map.put("8746", new Integer(200));
+        map.put("8747", new Integer(242));
+        map.put("8756", new Integer(92));
+        map.put("8764", new Integer(126));
+        map.put("8773", new Integer(64));
+        map.put("8776", new Integer(187));
+        map.put("8800", new Integer(185));
+        map.put("8801", new Integer(186));
+        map.put("8804", new Integer(163));
+        map.put("8805", new Integer(179));
+        map.put("8834", new Integer(204));
+        map.put("8835", new Integer(201));
+        map.put("8836", new Integer(203));
+        map.put("8838", new Integer(205));
+        map.put("8839", new Integer(202));
+        map.put("8853", new Integer(197));
+        map.put("8855", new Integer(196));
+        map.put("8869", new Integer(94));
+        map.put("8901", new Integer(215));
+        map.put("8992", new Integer(243));
+        map.put("8993", new Integer(245));
+        map.put("9001", new Integer(225));
+        map.put("9002", new Integer(241));
+        map.put("913", new Integer(65));
+        map.put("914", new Integer(66));
+        map.put("915", new Integer(71));
+        map.put("916", new Integer(68));
+        map.put("917", new Integer(69));
+        map.put("918", new Integer(90));
+        map.put("919", new Integer(72));
+        map.put("920", new Integer(81));
+        map.put("921", new Integer(73));
+        map.put("922", new Integer(75));
+        map.put("923", new Integer(76));
+        map.put("924", new Integer(77));
+        map.put("925", new Integer(78));
+        map.put("926", new Integer(88));
+        map.put("927", new Integer(79));
+        map.put("928", new Integer(80));
+        map.put("929", new Integer(82));
+        map.put("931", new Integer(83));
+        map.put("932", new Integer(84));
+        map.put("933", new Integer(85));
+        map.put("934", new Integer(70));
+        map.put("935", new Integer(67));
+        map.put("936", new Integer(89));
+        map.put("937", new Integer(87));
+        map.put("945", new Integer(97));
+        map.put("946", new Integer(98));
+        map.put("947", new Integer(103));
+        map.put("948", new Integer(100));
+        map.put("949", new Integer(101));
+        map.put("950", new Integer(122));
+        map.put("951", new Integer(104));
+        map.put("952", new Integer(113));
+        map.put("953", new Integer(105));
+        map.put("954", new Integer(107));
+        map.put("955", new Integer(108));
+        map.put("956", new Integer(109));
+        map.put("957", new Integer(110));
+        map.put("958", new Integer(120));
+        map.put("959", new Integer(111));
+        map.put("960", new Integer(112));
+        map.put("961", new Integer(114));
+        map.put("962", new Integer(86));
+        map.put("963", new Integer(115));
+        map.put("964", new Integer(116));
+        map.put("965", new Integer(117));
+        map.put("966", new Integer(102));
+        map.put("967", new Integer(99));
+        map.put("9674", new Integer(224));
+        map.put("968", new Integer(121));
+        map.put("969", new Integer(119));
+        map.put("977", new Integer(74));
+        map.put("978", new Integer(161));
+        map.put("981", new Integer(106));
+        map.put("982", new Integer(118));
+        map.put("9824", new Integer(170));
+        map.put("9827", new Integer(167));
+        map.put("9829", new Integer(169));
+        map.put("9830", new Integer(168));
+        map.put("Alpha", new Integer(65));
+        map.put("Beta", new Integer(66));
+        map.put("Chi", new Integer(67));
+        map.put("Delta", new Integer(68));
+        map.put("Epsilon", new Integer(69));
+        map.put("Eta", new Integer(72));
+        map.put("Gamma", new Integer(71));
+        map.put("Iota", new Integer(73));
+        map.put("Kappa", new Integer(75));
+        map.put("Lambda", new Integer(76));
+        map.put("Mu", new Integer(77));
+        map.put("Nu", new Integer(78));
+        map.put("Omega", new Integer(87));
+        map.put("Omicron", new Integer(79));
+        map.put("Phi", new Integer(70));
+        map.put("Pi", new Integer(80));
+        map.put("Prime", new Integer(178));
+        map.put("Psi", new Integer(89));
+        map.put("Rho", new Integer(82));
+        map.put("Sigma", new Integer(83));
+        map.put("Tau", new Integer(84));
+        map.put("Theta", new Integer(81));
+        map.put("Upsilon", new Integer(85));
+        map.put("Xi", new Integer(88));
+        map.put("Zeta", new Integer(90));
+        map.put("alefsym", new Integer(192));
+        map.put("alpha", new Integer(97));
+        map.put("and", new Integer(217));
+        map.put("ang", new Integer(208));
+        map.put("asymp", new Integer(187));
+        map.put("beta", new Integer(98));
+        map.put("cap", new Integer(199));
+        map.put("chi", new Integer(99));
+        map.put("clubs", new Integer(167));
+        map.put("cong", new Integer(64));
+        map.put("copy", new Integer(211));
+        map.put("crarr", new Integer(191));
+        map.put("cup", new Integer(200));
+        map.put("dArr", new Integer(223));
+        map.put("darr", new Integer(175));
+        map.put("delta", new Integer(100));
+        map.put("diams", new Integer(168));
+        map.put("divide", new Integer(184));
+        map.put("empty", new Integer(198));
+        map.put("epsilon", new Integer(101));
+        map.put("equiv", new Integer(186));
+        map.put("eta", new Integer(104));
+        map.put("euro", new Integer(240));
+        map.put("exist", new Integer(36));
+        map.put("forall", new Integer(34));
+        map.put("frasl", new Integer(164));
+        map.put("gamma", new Integer(103));
+        map.put("ge", new Integer(179));
+        map.put("hArr", new Integer(219));
+        map.put("harr", new Integer(171));
+        map.put("hearts", new Integer(169));
+        map.put("hellip", new Integer(188));
+        map.put("horizontal arrow extender", new Integer(190));
+        map.put("image", new Integer(193));
+        map.put("infin", new Integer(165));
+        map.put("int", new Integer(242));
+        map.put("iota", new Integer(105));
+        map.put("isin", new Integer(206));
+        map.put("kappa", new Integer(107));
+        map.put("lArr", new Integer(220));
+        map.put("lambda", new Integer(108));
+        map.put("lang", new Integer(225));
+        map.put("large brace extender", new Integer(239));
+        map.put("large integral extender", new Integer(244));
+        map.put("large left brace (bottom)", new Integer(238));
+        map.put("large left brace (middle)", new Integer(237));
+        map.put("large left brace (top)", new Integer(236));
+        map.put("large left bracket (bottom)", new Integer(235));
+        map.put("large left bracket (extender)", new Integer(234));
+        map.put("large left bracket (top)", new Integer(233));
+        map.put("large left parenthesis (bottom)", new Integer(232));
+        map.put("large left parenthesis (extender)", new Integer(231));
+        map.put("large left parenthesis (top)", new Integer(230));
+        map.put("large right brace (bottom)", new Integer(254));
+        map.put("large right brace (middle)", new Integer(253));
+        map.put("large right brace (top)", new Integer(252));
+        map.put("large right bracket (bottom)", new Integer(251));
+        map.put("large right bracket (extender)", new Integer(250));
+        map.put("large right bracket (top)", new Integer(249));
+        map.put("large right parenthesis (bottom)", new Integer(248));
+        map.put("large right parenthesis (extender)", new Integer(247));
+        map.put("large right parenthesis (top)", new Integer(246));
+        map.put("larr", new Integer(172));
+        map.put("le", new Integer(163));
+        map.put("lowast", new Integer(42));
+        map.put("loz", new Integer(224));
+        map.put("minus", new Integer(45));
+        map.put("mu", new Integer(109));
+        map.put("nabla", new Integer(209));
+        map.put("ne", new Integer(185));
+        map.put("not", new Integer(216));
+        map.put("notin", new Integer(207));
+        map.put("nsub", new Integer(203));
+        map.put("nu", new Integer(110));
+        map.put("omega", new Integer(119));
+        map.put("omicron", new Integer(111));
+        map.put("oplus", new Integer(197));
+        map.put("or", new Integer(218));
+        map.put("otimes", new Integer(196));
+        map.put("part", new Integer(182));
+        map.put("perp", new Integer(94));
+        map.put("phi", new Integer(102));
+        map.put("pi", new Integer(112));
+        map.put("piv", new Integer(118));
+        map.put("plusmn", new Integer(177));
+        map.put("prime", new Integer(162));
+        map.put("prod", new Integer(213));
+        map.put("prop", new Integer(181));
+        map.put("psi", new Integer(121));
+        map.put("rArr", new Integer(222));
+        map.put("radic", new Integer(214));
+        map.put("radical extender", new Integer(96));
+        map.put("rang", new Integer(241));
+        map.put("rarr", new Integer(174));
+        map.put("real", new Integer(194));
+        map.put("reg", new Integer(210));
+        map.put("rho", new Integer(114));
+        map.put("sdot", new Integer(215));
+        map.put("sigma", new Integer(115));
+        map.put("sigmaf", new Integer(86));
+        map.put("sim", new Integer(126));
+        map.put("spades", new Integer(170));
+        map.put("sub", new Integer(204));
+        map.put("sube", new Integer(205));
+        map.put("sum", new Integer(229));
+        map.put("sup", new Integer(201));
+        map.put("supe", new Integer(202));
+        map.put("tau", new Integer(116));
+        map.put("there4", new Integer(92));
+        map.put("theta", new Integer(113));
+        map.put("thetasym", new Integer(74));
+        map.put("times", new Integer(180));
+        map.put("trade", new Integer(212));
+        map.put("uArr", new Integer(221));
+        map.put("uarr", new Integer(173));
+        map.put("upsih", new Integer(161));
+        map.put("upsilon", new Integer(117));
+        map.put("vertical arrow extender", new Integer(189));
+        map.put("weierp", new Integer(195));
+        map.put("xi", new Integer(120));
+        map.put("zeta", new Integer(122));
+    }
+    
+ /**
+  * Gets a chunk with a symbol character.
+  * @param e a symbol value (see Entities class: alfa is greek alfa,...)
+  * @param font the font if the symbol isn't found (otherwise Font.SYMBIL)
+  * @return a Chunk
+  */
+    
+    public static Chunk get(String e, Font font) {
+        int s = getCorrespondingSymbol(e);
+        if (s == -1) {
+            try {
+                return new Chunk(String.valueOf((char)Integer.parseInt(e)), font);
+            }
+            catch(Exception exception) {
+                return new Chunk(e, font);
+            }
+        }
+        Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+        return new Chunk(String.valueOf((char)s), symbol);
+    }
+    
+/**
+ * Looks for the corresponding symbol in the font Symbol.
+ *
+ * @param	c	the original ASCII-char
+ * @return	the corresponding symbol in font Symbol
+ */
+    
+    public static int getCorrespondingSymbol(String c) {
+        Integer integer = (Integer) map.get(c);
+        if (integer == null) {
+            return -1;
+        }
+        return integer.intValue();
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.ENTITY.equals(tag);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ExceptionConverter.java b/LibrarySource/com/lowagie/text/ExceptionConverter.java
new file mode 100644
index 0000000..3715a47
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ExceptionConverter.java
@@ -0,0 +1,135 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text;
+
+/**
+ * The ExceptionConverter changes a checked exception into an
+ * unchecked exception.
+ */
+public class ExceptionConverter extends RuntimeException {
+    /** we keep a handle to the wrapped exception */
+    private Exception ex;
+    /** prefix for the exception */
+    private String prefix;
+
+    /**
+     * Construct a RuntimeException based on another Exception
+     * @param ex the exception that has to be turned into a RuntimeException
+     */
+    public ExceptionConverter(Exception ex) {
+        this.ex = ex;
+        prefix = (ex instanceof RuntimeException) ? "" : "ExceptionConverter: ";
+    }
+
+    /**
+     * and allow the user of ExceptionConverter to get a handle to it. 
+     * @return the original exception
+     */
+    public Exception getException() {
+        return ex;
+    }
+
+    /**
+     * We print the message of the checked exception 
+     * @return message of the original exception
+     */
+    public String getMessage() {
+        return ex.getMessage();
+    }
+
+    /**
+     * and make sure we also produce a localized version
+     * @return localized version of the message
+     */
+    public String getLocalizedMessage() {
+        return ex.getLocalizedMessage();
+    }
+
+    /**
+     * The toString() is changed to be prefixed with ExceptionConverter 
+     * @return Stringversion of the exception
+     */
+    public String toString() {
+        return prefix + ex;
+    }
+
+    /** we have to override this as well */
+    public void printStackTrace() {
+        printStackTrace(System.err);
+    }
+
+    /**
+     * here we prefix, with s.print(), not s.println(), the stack
+     * trace with "ExceptionConverter:" 
+     * @param s
+     */
+    public void printStackTrace(java.io.PrintStream s) {
+        synchronized (s) {
+            s.print(prefix);
+            ex.printStackTrace(s);
+        }
+    }
+
+    /**
+     * Again, we prefix the stack trace with "ExceptionConverter:" 
+     * @param s
+     */
+    public void printStackTrace(java.io.PrintWriter s) {
+        synchronized (s) {
+            s.print(prefix);
+            ex.printStackTrace(s);
+        }
+    }
+
+    /**
+     * requests to fill in the stack trace we will have to ignore.
+     * We can't throw an exception here, because this method
+     * is called by the constructor of Throwable 
+     * @return a Throwable
+     */
+    public Throwable fillInStackTrace() {
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/Font.java b/LibrarySource/com/lowagie/text/Font.java
new file mode 100644
index 0000000..07eb07b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Font.java
@@ -0,0 +1,752 @@
+/*
+ * $Id: Font.java,v 1.92 2005/05/03 13:03:51 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.markup.MarkupTags;
+
+/**
+ * Contains all the specifications of a font: fontfamily, size, style and color.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * Paragraph p = new Paragraph("This is a paragraph",
+ *               <STRONG>new Font(Font.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255))</STRONG>);
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class Font implements Comparable {
+    
+// static membervariables for the different families
+    
+/** a possible value of a font family. */
+    public static final int COURIER = 0;
+    
+/** a possible value of a font family. */
+    public static final int HELVETICA = 1;
+    
+/** a possible value of a font family. */
+    public static final int TIMES_ROMAN = 2;
+    
+/** a possible value of a font family. */
+    public static final int SYMBOL = 3;
+    
+/** a possible value of a font family. */
+    public static final int ZAPFDINGBATS = 4;
+    
+// static membervariables for the different styles
+    
+/** this is a possible style. */
+    public static final int NORMAL		= 0;
+    
+/** this is a possible style. */
+    public static final int BOLD		= 1;
+    
+/** this is a possible style. */
+    public static final int ITALIC		= 2;
+    
+/** this is a possible style. */
+    public static final int UNDERLINE	= 4;
+    
+/** this is a possible style. */
+    public static final int STRIKETHRU	= 8;
+    
+/** this is a possible style. */
+    public static final int BOLDITALIC	= BOLD | ITALIC;
+    
+// static membervariables
+    
+/** the value of an undefined attribute. */
+    public static final int UNDEFINED = -1;
+    
+/** the value of the default size. */
+    public static final int DEFAULTSIZE = 12;
+    
+// membervariables
+    
+/** the value of the fontfamily. */
+    private int family = UNDEFINED;
+    
+/** the value of the fontsize. */
+    private float size = UNDEFINED;
+    
+/** the value of the style. */
+    private int style = UNDEFINED;
+    
+/** the value of the color. */
+    private Color color = null;
+    
+/** the external font */
+    private BaseFont baseFont = null;
+    
+// constructors
+ 
+    /**
+     * Copy constructor of a Font
+     * @param other the font that has to be copied
+     */
+    public Font(Font other) {
+        this.color = other.color;
+        this.family = other.family;
+        this.size = other.size;
+        this.style = other.style;
+        this.baseFont = other.baseFont;
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	family	the family to which this font belongs
+ * @param	size	the size of this font
+ * @param	style	the style of this font
+ * @param	color	the <CODE>Color</CODE> of this font.
+ */
+    
+    public Font(int family, float size, int style, Color color) {
+        this.family = family;
+        this.size = size;
+        this.style = style;
+        this.color = color;
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	bf	    the external font
+ * @param	size	the size of this font
+ * @param	style	the style of this font
+ * @param	color	the <CODE>Color</CODE> of this font.
+ */
+    
+    public Font(BaseFont bf, float size, int style, Color color) {
+        this.baseFont = bf;
+        this.size = size;
+        this.style = style;
+        this.color = color;
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	bf	    the external font
+ * @param	size	the size of this font
+ * @param	style	the style of this font
+ */
+    public Font(BaseFont bf, float size, int style) {
+        this(bf, size, style, null);
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	bf	    the external font
+ * @param	size	the size of this font
+ */
+    public Font(BaseFont bf, float size) {
+        this(bf, size, UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	bf	    the external font
+ */
+    public Font(BaseFont bf) {
+        this(bf, UNDEFINED, UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	family	the family to which this font belongs
+ * @param	size	the size of this font
+ * @param	style	the style of this font
+ */
+    
+    public Font(int family, float size, int style) {
+        this(family, size, style, null);
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	family	the family to which this font belongs
+ * @param	size	the size of this font
+ */
+    
+    public Font(int family, float size) {
+        this(family, size, UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a Font.
+ *
+ * @param	family	the family to which this font belongs
+ */
+    
+    public Font(int family) {
+        this(family, UNDEFINED, UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a Font.
+ */
+    
+    public Font() {
+        this(UNDEFINED, UNDEFINED, UNDEFINED, null);
+    }
+    
+    // implementation of the Comparable interface
+    
+/**
+ * Compares this <CODE>Font</CODE> with another
+ *
+ * @param	object	the other <CODE>Font</CODE>
+ * @return	a value
+ */
+    
+    public int compareTo(Object object) {
+        if (object == null) {
+            return -1;
+        }
+        Font font;
+        try {
+            font = (Font) object;
+            if (baseFont != null && !baseFont.equals(font.getBaseFont())) {
+                return -2;
+            }
+            if (this.family != font.family()) {
+                return 1;
+            }
+            if (this.size != font.size()) {
+                return 2;
+            }
+            if (this.style != font.style()) {
+                return 3;
+            }
+            if (this.color == null) {
+                if (font.color == null) {
+                    return 0;
+                }
+                return 4;
+            }
+            if (font.color == null) {
+                return 4;
+            }
+            if (this.color.equals(font.color())) {
+                return 0;
+            }
+            return 4;
+        }
+        catch(ClassCastException cce) {
+            return -3;
+        }
+    }
+    
+    // methods
+    
+/**
+ * Sets the family using a <CODE>String</CODE> ("Courier",
+ * "Helvetica", "Times New Roman", "Symbol" or "ZapfDingbats").
+ *
+ * @param	family		A <CODE>String</CODE> representing a certain font-family.
+ */
+    
+    public void setFamily(String family) {
+        this.family = getFamilyIndex(family);
+    }
+    
+/**
+ * Translates a <CODE>String</CODE>-value of a certain family
+ * into the index that is used for this family in this class.
+ *
+ * @param	family		A <CODE>String</CODE> representing a certain font-family
+ * @return	the corresponding index
+ */
+    
+    public static int getFamilyIndex(String family) {
+        if (family.equalsIgnoreCase(FontFactory.COURIER)) {
+            return COURIER;
+        }
+        if (family.equalsIgnoreCase(FontFactory.HELVETICA)) {
+            return HELVETICA;
+        }
+        if (family.equalsIgnoreCase(FontFactory.TIMES_ROMAN)) {
+            return TIMES_ROMAN;
+        }
+        if (family.equalsIgnoreCase(FontFactory.SYMBOL)) {
+            return SYMBOL;
+        }
+        if (family.equalsIgnoreCase(FontFactory.ZAPFDINGBATS)) {
+            return ZAPFDINGBATS;
+        }
+        return UNDEFINED;
+    }
+    
+/**
+ * Gets the familyname as a String.
+ *
+ * @return  the familyname
+ */
+    
+    public String getFamilyname() {
+        String tmp = "unknown";
+        switch(family()) {
+            case Font.COURIER:
+                return FontFactory.COURIER;
+            case Font.HELVETICA:
+                return FontFactory.HELVETICA;
+            case Font.TIMES_ROMAN:
+                return FontFactory.TIMES_ROMAN;
+            case Font.SYMBOL:
+                return FontFactory.SYMBOL;
+            case Font.ZAPFDINGBATS:
+                return FontFactory.ZAPFDINGBATS;
+            default:
+                if (baseFont != null) {
+                    String[][] names = baseFont.getFamilyFontName();
+                    for (int i = 0; i < names.length; i++) {
+                        if ("0".equals(names[i][2])) {
+                            return names[i][3];
+                        }
+                        if ("1033".equals(names[i][2])) {
+                            tmp = names[i][3];
+                        }
+                        if ("".equals(names[i][2])) {
+                            tmp = names[i][3];
+                        }
+                    }
+                }
+        }
+        return tmp;
+    }
+    
+/**
+ * Sets the size.
+ *
+ * @param	size		The new size of the font.
+ */
+    
+    public void setSize(float size) {
+        this.size = size;
+    }
+    
+/**
+ * Sets the style using a <CODE>String</CODE> containing one of
+ * more of the following values: normal, bold, italic, underline, strike.
+ *
+ * @param	style	A <CODE>String</CODE> representing a certain style.
+ */
+    
+    public void setStyle(String style) {
+        if (this.style == UNDEFINED) this.style = NORMAL;
+        this.style |= getStyleValue(style);
+    }
+    
+/**
+ * Sets the style.
+ * @param	style	the style.
+ */
+    
+    public void setStyle(int style) {
+        if (this.style == UNDEFINED) this.style = NORMAL;
+        this.style |= style;
+    }
+    
+/**
+ * Translates a <CODE>String</CODE>-value of a certain style
+ * into the index value is used for this style in this class.
+ *
+ * @param	style			A <CODE>String</CODE>
+ * @return	the corresponding value
+ */
+    
+    public static int getStyleValue(String style) {
+        int s = 0;
+        if (style.indexOf(MarkupTags.CSS_VALUE_NORMAL) != -1) {
+            s |= NORMAL;
+        }
+        if (style.indexOf(MarkupTags.CSS_VALUE_BOLD) != -1) {
+            s |= BOLD;
+        }
+        if (style.indexOf(MarkupTags.CSS_VALUE_ITALIC) != -1) {
+            s |= ITALIC;
+        }
+        if (style.indexOf(MarkupTags.CSS_VALUE_OBLIQUE) != -1) {
+            s |= ITALIC;
+        }
+        if (style.indexOf(MarkupTags.CSS_VALUE_UNDERLINE) != -1) {
+            s |= UNDERLINE;
+        }
+        if (style.indexOf(MarkupTags.CSS_VALUE_LINETHROUGH) != -1) {
+            s |= STRIKETHRU;
+        }
+        return s;
+    }
+    
+/**
+ * Sets the color.
+ *
+ * @param	color		the new color of the font
+ */
+    
+    public void setColor(Color color) {
+        this.color = color;
+    }
+    
+/**
+ * Sets the color.
+ *
+ * @param	red			the red-value of the new color
+ * @param	green		the green-value of the new color
+ * @param	blue		the blue-value of the new color
+ */
+    
+    public void setColor(int red, int green, int blue) {
+        this.color = new Color(red, green, blue);
+    }
+    
+/**
+ * Gets the leading that can be used with this font.
+ *
+ * @param	linespacing		a certain linespacing
+ * @return	the height of a line
+ */
+    
+    public float leading(float linespacing) {
+        if (size == UNDEFINED) {
+            return linespacing * DEFAULTSIZE;
+        }
+        return linespacing * size;
+    }
+    
+/**
+ * Checks if the properties of this font are undefined or null.
+ * <P>
+ * If so, the standard should be used.
+ *
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean isStandardFont() {
+        return (family == UNDEFINED
+        && size == UNDEFINED
+        && style == UNDEFINED
+        && color == null
+        && baseFont == null);
+    }
+    
+/**
+ * Replaces the attributes that are equal to <VAR>null</VAR> with
+ * the attributes of a given font.
+ *
+ * @param	font	the font of a bigger element class
+ * @return	a <CODE>Font</CODE>
+ */
+    
+    public Font difference(Font font) {
+        // size
+        float dSize = font.size;
+        if (dSize == UNDEFINED) {
+            dSize = this.size;
+        }
+        // style
+        int dStyle = UNDEFINED;
+        int style1 = this.style;
+        int style2 = font.style();
+        if (style1 != UNDEFINED || style2 != UNDEFINED) {
+            if (style1 == UNDEFINED) style1 = 0;
+            if (style2 == UNDEFINED) style2 = 0;
+            dStyle = style1 | style2;
+        }
+        // color
+        Color dColor = font.color;
+        if (dColor == null) {
+            dColor = this.color;
+        }
+        // family
+        if (font.baseFont != null) {
+            return new Font(font.baseFont, dSize, dStyle, dColor);
+        }
+        if (font.family() != UNDEFINED) {
+            return new Font(font.family, dSize, dStyle, dColor);
+        }
+        if (this.baseFont != null) {
+            if (dStyle == style1) {
+                return new Font(this.baseFont, dSize, dStyle, dColor);
+            }
+            else {
+                return FontFactory.getFont(this.getFamilyname(), dSize, dStyle, dColor);
+            }
+        }
+        return new Font(this.family, dSize, dStyle, dColor);
+    }
+    
+    // methods to retrieve the membervariables
+    
+/**
+ * Gets the family of this font.
+ *
+ * @return	the value of the family
+ */
+    
+    public int family() {
+        return family;
+    }
+    
+/**
+ * Gets the size of this font.
+ *
+ * @return	a size
+ */
+    
+    public float size() {
+        return size;
+    }
+    
+/**
+ * Gets the style of this font.
+ *
+ * @return	a size
+ */
+    
+    public int style() {
+        return style;
+    }
+    
+/**
+ * checks if this font is Bold.
+ *
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean isBold() {
+        if (style == UNDEFINED) {
+            return false;
+        }
+        return (style &	BOLD) == BOLD;
+    }
+    
+/**
+ * checks if this font is Bold.
+ *
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean isItalic() {
+        if (style == UNDEFINED) {
+            return false;
+        }
+        return (style &	ITALIC) == ITALIC;
+    }
+    
+/**
+ * checks if this font is underlined.
+ *
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean isUnderlined() {
+        if (style == UNDEFINED) {
+            return false;
+        }
+        return (style &	UNDERLINE) == UNDERLINE;
+    }
+    
+/**
+ * checks if the style of this font is STRIKETHRU.
+ *
+ * @return	a <CODE>boolean</CODE>
+ */
+    
+    public boolean isStrikethru() {
+        if (style == UNDEFINED) {
+            return false;
+        }
+        return (style &	STRIKETHRU) == STRIKETHRU;
+    }
+    
+/**
+ * Gets the color of this font.
+ *
+ * @return	a color
+ */
+    
+    public Color color() {
+        return color;
+    }
+    
+ /** Gets the <CODE>BaseFont</CODE> inside this object.
+  * @return the <CODE>BaseFont</CODE>
+  */
+    
+    public BaseFont getBaseFont() {
+        return baseFont;
+    }
+
+    /** Gets the <CODE>BaseFont</CODE> this class represents.
+     * For the built-in fonts a <CODE>BaseFont</CODE> is calculated.
+     * @param specialEncoding <CODE>true</CODE> to use the special encoding for Symbol and ZapfDingbats,
+     * <CODE>false</CODE> to always use <CODE>Cp1252</CODE>
+     * @return the <CODE>BaseFont</CODE> this class represents
+     */    
+    public BaseFont getCalculatedBaseFont(boolean specialEncoding) {
+        if (baseFont != null)
+            return baseFont;
+        int style = this.style;
+        if (style == UNDEFINED) {
+            style = NORMAL;
+        }
+        String fontName = BaseFont.HELVETICA;
+        String encoding = BaseFont.WINANSI;
+        BaseFont cfont = null;
+        switch(family) {
+            case COURIER:
+                switch(style & BOLDITALIC) {
+                    case BOLD:
+                        fontName = BaseFont.COURIER_BOLD;
+                        break;
+                    case ITALIC:
+                        fontName = BaseFont.COURIER_OBLIQUE;
+                        break;
+                    case BOLDITALIC:
+                        fontName = BaseFont.COURIER_BOLDOBLIQUE;
+                        break;
+                    default:
+                    //case NORMAL:
+                        fontName = BaseFont.COURIER;
+                        break;
+                }
+                break;
+            case TIMES_ROMAN:
+                switch(style & BOLDITALIC) {
+                    case BOLD:
+                        fontName = BaseFont.TIMES_BOLD;
+                        break;
+                    case ITALIC:
+                        fontName = BaseFont.TIMES_ITALIC;
+                        break;
+                    case BOLDITALIC:
+                        fontName = BaseFont.TIMES_BOLDITALIC;
+                        break;
+                        default:
+                    case NORMAL:
+                        fontName = BaseFont.TIMES_ROMAN;
+                        break;
+                }
+                break;
+            case SYMBOL:
+                fontName = BaseFont.SYMBOL;
+                if (specialEncoding)
+                    encoding = BaseFont.SYMBOL;
+                break;
+            case ZAPFDINGBATS:
+                fontName = BaseFont.ZAPFDINGBATS;
+                if (specialEncoding)
+                    encoding = BaseFont.ZAPFDINGBATS;
+                break;
+            default:
+            //case Font.HELVETICA:
+                switch(style & BOLDITALIC) {
+                    case BOLD:
+                        fontName = BaseFont.HELVETICA_BOLD;
+                        break;
+                    case ITALIC:
+                        fontName = BaseFont.HELVETICA_OBLIQUE;
+                        break;
+                    case BOLDITALIC:
+                        fontName = BaseFont.HELVETICA_BOLDOBLIQUE;
+                        break;
+                        default:
+                    case NORMAL:
+                        fontName = BaseFont.HELVETICA;
+                        break;
+                }
+                break;
+        }
+        try {
+            cfont = BaseFont.createFont(fontName, encoding, false);
+        }
+        catch (Exception ee) {
+            throw new ExceptionConverter(ee);
+        }
+        return cfont;
+    }
+    
+    /** Gets the style that can be used with the calculated <CODE>BaseFont</CODE>.
+     * @return the style that can be used with the calculated <CODE>BaseFont</CODE>
+     */    
+    public int getCalculatedStyle() {
+        int style = this.style;
+        if (style == UNDEFINED) {
+            style = NORMAL;
+        }
+        if (baseFont != null)
+            return style;
+        if (family == SYMBOL || family == ZAPFDINGBATS)
+            return style;
+        else
+            return style & (~BOLDITALIC);
+    }
+    
+    /** Gets the size that can be used with the calculated <CODE>BaseFont</CODE>.
+     * @return the size that can be used with the calculated <CODE>BaseFont</CODE>
+     */    
+    public float getCalculatedSize() {
+        float s = this.size;
+        if (s == UNDEFINED) {
+            s = DEFAULTSIZE;
+        }
+        return s;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/FontFactory.java b/LibrarySource/com/lowagie/text/FontFactory.java
new file mode 100644
index 0000000..7ab657e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/FontFactory.java
@@ -0,0 +1,661 @@
+/*
+ * $Id: FontFactory.java,v 1.65 2005/05/03 13:03:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Enumeration;
+import java.io.File;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * If you are using True Type fonts, you can declare the paths of the different ttf- and ttc-files
+ * to this static class first and then create fonts in your code using one of the static getFont-method
+ * without having to enter a path as parameter.
+ *
+ * @author  Bruno Lowagie
+ */
+
+public class FontFactory extends java.lang.Object {
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER = BaseFont.COURIER;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_BOLD = BaseFont.COURIER_BOLD;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_OBLIQUE = BaseFont.COURIER_OBLIQUE;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_BOLDOBLIQUE = BaseFont.COURIER_BOLDOBLIQUE;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA = BaseFont.HELVETICA;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_BOLD = BaseFont.HELVETICA_BOLD;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_OBLIQUE = BaseFont.HELVETICA_OBLIQUE;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_BOLDOBLIQUE = BaseFont.HELVETICA_BOLDOBLIQUE;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String SYMBOL = BaseFont.SYMBOL;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES = "Times";
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_ROMAN = BaseFont.TIMES_ROMAN;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_BOLD = BaseFont.TIMES_BOLD;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_ITALIC = BaseFont.TIMES_ITALIC;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_BOLDITALIC = BaseFont.TIMES_BOLDITALIC;
+    
+/** This is a possible value of a base 14 type 1 font */
+    public static final String ZAPFDINGBATS = BaseFont.ZAPFDINGBATS;
+    
+/** This is a map of postscriptfontnames of True Type fonts and the path of their ttf- or ttc-file. */
+    private static Properties trueTypeFonts = new Properties();
+    
+    static {
+        trueTypeFonts.setProperty(COURIER, COURIER);
+        trueTypeFonts.setProperty(COURIER_BOLD, COURIER_BOLD);
+        trueTypeFonts.setProperty(COURIER_OBLIQUE, COURIER_OBLIQUE);
+        trueTypeFonts.setProperty(COURIER_BOLDOBLIQUE, COURIER_BOLDOBLIQUE);
+        trueTypeFonts.setProperty(HELVETICA, HELVETICA);
+        trueTypeFonts.setProperty(HELVETICA_BOLD, HELVETICA_BOLD);
+        trueTypeFonts.setProperty(HELVETICA_OBLIQUE, HELVETICA_OBLIQUE);
+        trueTypeFonts.setProperty(HELVETICA_BOLDOBLIQUE, HELVETICA_BOLDOBLIQUE);
+        trueTypeFonts.setProperty(SYMBOL, SYMBOL);
+        trueTypeFonts.setProperty(TIMES_ROMAN, TIMES_ROMAN);
+        trueTypeFonts.setProperty(TIMES_BOLD, TIMES_BOLD);
+        trueTypeFonts.setProperty(TIMES_ITALIC, TIMES_ITALIC);
+        trueTypeFonts.setProperty(TIMES_BOLDITALIC, TIMES_BOLDITALIC);
+        trueTypeFonts.setProperty(ZAPFDINGBATS, ZAPFDINGBATS);
+    }
+    
+/** This is a map of fontfamilies. */
+    private static Hashtable fontFamilies = new Hashtable();
+    
+    static {
+        HashSet tmp;
+        tmp = new HashSet();
+        tmp.add(COURIER);
+        tmp.add(COURIER_BOLD);
+        tmp.add(COURIER_OBLIQUE);
+        tmp.add(COURIER_BOLDOBLIQUE);
+        fontFamilies.put(COURIER, tmp);
+        tmp = new HashSet();
+        tmp.add(HELVETICA);
+        tmp.add(HELVETICA_BOLD);
+        tmp.add(HELVETICA_OBLIQUE);
+        tmp.add(HELVETICA_BOLDOBLIQUE);
+        fontFamilies.put(HELVETICA, tmp);
+        tmp = new HashSet();
+        tmp.add(SYMBOL);
+        fontFamilies.put(SYMBOL, tmp);
+        tmp = new HashSet();
+        tmp.add(TIMES_ROMAN);
+        tmp.add(TIMES_BOLD);
+        tmp.add(TIMES_ITALIC);
+        tmp.add(TIMES_BOLDITALIC);
+        fontFamilies.put(TIMES, tmp);
+        fontFamilies.put(TIMES_ROMAN, tmp);
+        tmp = new HashSet();
+        tmp.add(ZAPFDINGBATS);
+        fontFamilies.put(ZAPFDINGBATS, tmp);
+    }
+    
+    
+/** This is the default encoding to use. */
+    public static String defaultEncoding = BaseFont.WINANSI;
+    
+/** This is the default value of the <VAR>embedded</VAR> variable. */
+    public static boolean defaultEmbedding = BaseFont.NOT_EMBEDDED;
+    
+/** Creates new FontFactory */
+    private FontFactory() {
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param       embedded    true if the font is to be embedded in the PDF
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @param	color	    the <CODE>Color</CODE> of this font.
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) {
+        if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
+        HashSet tmp = (HashSet) fontFamilies.get(fontname);
+        if (tmp != null) {
+            // some bugs were fixed here by Daniel Marczisovszky
+            String lowercasefontname = fontname.toLowerCase();
+            int s = style == Font.UNDEFINED ? Font.NORMAL : style;
+            int fs = Font.NORMAL;
+            boolean found = false;
+            for (Iterator i = tmp.iterator(); i.hasNext(); ) {
+                String f = (String) i.next();
+                String lcf = f.toLowerCase();
+                fs = Font.NORMAL;
+                if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD;
+                if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC;
+                if ((s & Font.BOLDITALIC) == fs) {
+                    fontname = f;
+                    found = true;
+                    break;
+                }
+            }
+            if (style != Font.UNDEFINED && found) {
+                style &= ~fs;
+            }
+        }
+        BaseFont basefont = null;
+        try {
+            try {
+                // the font is a type 1 font or CJK font
+                basefont = BaseFont.createFont(fontname, encoding, embedded);
+            }
+            catch(DocumentException de) {
+                // the font is a true type font or an unknown font
+                fontname = trueTypeFonts.getProperty(fontname);
+                // the font is not registered as truetype font
+                if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
+                // the font is registered as truetype font
+                basefont = BaseFont.createFont(fontname, encoding, embedded);
+            }
+        }
+        catch(DocumentException de) {
+            // this shouldn't happen
+            throw new ExceptionConverter(de);
+        }
+        catch(IOException ioe) {
+            // the font is registered as a true type font, but the path was wrong
+            return new Font(Font.UNDEFINED, size, style, color);
+        }
+        catch(NullPointerException npe) {
+            // null was entered as fontname and/or encoding
+            return new Font(Font.UNDEFINED, size, style, color);
+        }
+        return new Font(basefont, size, style, color);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param   attributes  the attributes of a <CODE>Font</CODE> object.
+ * @return the Font constructed based on the attributes
+ */
+    
+    public static Font getFont(Properties attributes) {
+        String fontname = null;
+        String encoding = defaultEncoding;
+        boolean embedded = defaultEmbedding;
+        float size = Font.UNDEFINED;
+        int style = Font.NORMAL;
+        Color color = null;
+        String value = (String) attributes.remove(MarkupTags.HTML_ATTR_STYLE);
+        if (value != null && value.length() > 0) {
+            Properties styleAttributes = MarkupParser.parseAttributes(value);
+            if (styleAttributes.size() == 0) {
+                attributes.put(MarkupTags.HTML_ATTR_STYLE, value);
+            }
+            else {
+                fontname = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTFAMILY);
+                if (fontname != null) {
+                    String tmp;
+                    while (fontname.indexOf(",") != -1) {
+                        tmp = fontname.substring(0, fontname.indexOf(","));
+                        if (isRegistered(tmp)) {
+                            fontname = tmp;
+                        }
+                        else {
+                            fontname = fontname.substring(fontname.indexOf(",") + 1);
+                        }
+                    }
+                }
+                if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
+                    size = MarkupParser.parseLength(value);
+                }
+                if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
+                    style |= Font.getStyleValue(value);
+                }
+                if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
+                    style |= Font.getStyleValue(value);
+                }
+                if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_COLOR)) != null) {
+                    color = MarkupParser.decodeColor(value);
+                }
+                attributes.putAll(styleAttributes);
+                for (Enumeration e = styleAttributes.keys(); e.hasMoreElements();) {
+                    Object o = e.nextElement();
+                    attributes.put(o, styleAttributes.get(o));
+                }
+            }
+        }
+        if ((value = (String)attributes.remove(ElementTags.ENCODING)) != null) {
+            encoding = value;
+        }
+        if ("true".equals((String) attributes.remove(ElementTags.EMBEDDED))) {
+            embedded = true;
+        }
+        if ((value = (String)attributes.remove(ElementTags.FONT)) != null) {
+            fontname = value;
+        }
+        if ((value = (String)attributes.remove(ElementTags.SIZE)) != null) {
+            size = Float.valueOf(value + "f").floatValue();
+        }
+        if ((value = (String)attributes.remove(MarkupTags.HTML_ATTR_STYLE)) != null) {
+            style |= Font.getStyleValue(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.STYLE)) != null) {
+            style |= Font.getStyleValue(value);
+        }
+        String r = (String)attributes.remove(ElementTags.RED);
+        String g = (String)attributes.remove(ElementTags.GREEN);
+        String b = (String)attributes.remove(ElementTags.BLUE);
+        if (r != null || g != null || b != null) {
+            int red = 0;
+            int green = 0;
+            int blue = 0;
+            if (r != null) red = Integer.parseInt(r);
+            if (g != null) green = Integer.parseInt(g);
+            if (b != null) blue = Integer.parseInt(b);
+            color = new Color(red, green, blue);
+        }
+        else if ((value = (String)attributes.remove(ElementTags.COLOR)) != null) {
+            color = MarkupParser.decodeColor(value);
+        }
+        if (fontname == null) {
+            return getFont(null, encoding, embedded, size, style, color);
+        }
+        return getFont(fontname, encoding, embedded, size, style, color);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param       embedded    true if the font is to be embedded in the PDF
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style) {
+        return getFont(fontname, encoding, embedded, size, style, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param       embedded    true if the font is to be embedded in the PDF
+ * @param	size	    the size of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, boolean embedded, float size) {
+        return getFont(fontname, encoding, embedded, size, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param       embedded    true if the font is to be embedded in the PDF
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, boolean embedded) {
+        return getFont(fontname, encoding, embedded, Font.UNDEFINED, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @param	color	    the <CODE>Color</CODE> of this font.
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, float size, int style, Color color) {
+        return getFont(fontname, encoding, defaultEmbedding, size, style, color);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, float size, int style) {
+        return getFont(fontname, encoding, defaultEmbedding, size, style, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @param	size	    the size of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding, float size) {
+        return getFont(fontname, encoding, defaultEmbedding, size, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	encoding    the encoding of the font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, String encoding) {
+        return getFont(fontname, encoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @param	color	    the <CODE>Color</CODE> of this font.
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, float size, int style, Color color) {
+        return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, color);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	size	    the size of this font
+ * @param	style	    the style of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, float size, int style) {
+        return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @param	size	    the size of this font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname, float size) {
+        return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Constructs a <CODE>Font</CODE>-object.
+ *
+ * @param	fontname    the name of the font
+ * @return the Font constructed based on the parameters
+ */
+    
+    public static Font getFont(String fontname) {
+        return getFont(fontname, defaultEncoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
+    }
+    
+/**
+ * Register a ttf- or a ttc-file.
+ *
+ * @param   path    the path to a ttf- or ttc-file
+ */
+    
+    public static void register(String path) {
+        register(path, null);
+    }
+    
+/**
+ * Register a font file and use an alias for the font contained in it.
+ *
+ * @param   path    the path to a font file
+ * @param   alias   the alias you want to use for the font
+ */
+    
+    public static void register(String path, String alias) {
+        try {
+            if (path.toLowerCase().endsWith(".ttf") || path.toLowerCase().endsWith(".otf") || path.toLowerCase().indexOf(".ttc,") > 0) {
+                Object allNames[] = BaseFont.getAllFontNames(path, BaseFont.WINANSI, null);
+                trueTypeFonts.setProperty((String)allNames[0], path);
+                if (alias != null) {
+                    trueTypeFonts.setProperty(alias, path);
+                }
+                String fullName = null;
+                String familyName = null;
+                String[][] names = (String[][])allNames[2];
+                for (int i = 0; i < names.length; i++) {
+                    if ("0".equals(names[i][2])) {
+                        fullName = names[i][3];
+                        break;
+                    }
+                }
+                // register all the font names with all the locales
+                for (int i = 0; i < names.length; i++) {
+                    trueTypeFonts.setProperty(names[i][3], path);
+                }
+                if (fullName != null) {
+                    names = (String[][])allNames[1];
+                    for (int i = 0; i < names.length; i++) {
+                        if ("0".equals(names[i][2])) {
+                            familyName = names[i][3];
+                            HashSet tmp = (HashSet) fontFamilies.get(familyName);
+                            if (tmp == null) {
+                                tmp = new HashSet();
+                            }
+                            tmp.add(fullName);
+                            fontFamilies.put(familyName, tmp);
+                            break;
+                        }
+                    }
+                }
+            }
+            else if (path.toLowerCase().endsWith(".ttc")) {
+                if (alias != null)
+                    System.err.println("class FontFactory: You can't define an alias for a true type collection.");
+                String[] names = BaseFont.enumerateTTCNames(path);
+                for (int i = 0; i < names.length; i++) {
+                    register(path + "," + i);
+                }
+            }
+            else if (path.toLowerCase().endsWith(".afm")) {
+                BaseFont bf = BaseFont.createFont(path, BaseFont.CP1252, false);
+                trueTypeFonts.setProperty(bf.getPostscriptFontName(), path);
+                trueTypeFonts.setProperty(bf.getFullFontName()[0][3], path);
+            }
+        }
+        catch(DocumentException de) {
+            // this shouldn't happen
+            throw new ExceptionConverter(de);
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+
+    /** Register all the fonts in a directory.
+     * @param dir the directory
+     * @return the number of fonts registered
+     */    
+    public static int registerDirectory(String dir) {
+        int count = 0;
+        try {
+            File file = new File(dir);
+            if (!file.exists() || !file.isDirectory())
+                return 0;
+            String files[] = file.list();
+            if (files == null)
+                return 0;
+            for (int k = 0; k < files.length; ++k) {
+                try {
+                    file = new File(dir, files[k]);
+                    String name = file.getPath().toLowerCase();
+                    if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm") || name.endsWith(".ttc")) {
+                        register(file.getPath(), null);
+                        ++count;
+                    }
+                }
+                catch (Exception e) {
+                    //empty on purpose
+                }
+            }
+        }
+        catch (Exception e) {
+            //empty on purpose
+        }
+        return count;
+    }
+
+    /** Register fonts in some probable directories. It usually works in Windows,
+     * Linux and Solaris.
+     * @return the number of fonts registered
+     */    
+    public static int registerDirectories() {
+        int count = 0;
+        count += registerDirectory("c:/windows/fonts");
+        count += registerDirectory("c:/winnt/fonts");
+        count += registerDirectory("d:/windows/fonts");
+        count += registerDirectory("d:/winnt/fonts");
+        count += registerDirectory("/usr/X/lib/X11/fonts/TrueType");
+        count += registerDirectory("/usr/openwin/lib/X11/fonts/TrueType");
+        count += registerDirectory("/usr/share/fonts/default/TrueType");
+        count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf");
+        return count;
+    }
+
+/**
+ * Gets a set of registered fontnames.
+ * @return a set of registered fonts
+ */
+    
+    public static Set getRegisteredFonts() {
+        return Chunk.getKeySet(trueTypeFonts);
+    }
+    
+/**
+ * Gets a set of registered fontnames.
+ * @return a set of registered font families
+ */
+    
+    public static Set getRegisteredFamilies() {
+        return Chunk.getKeySet(fontFamilies);
+    }
+    
+/**
+ * Gets a set of registered fontnames.
+ * @param fontname of a font that may or may not be registered
+ * @return true if a given font is registered
+ */
+    
+    public static boolean contains(String fontname) {
+        return trueTypeFonts.containsKey(fontname);
+    }
+    
+/**
+ * Checks if a certain font is registered.
+ *
+ * @param   fontname    the name of the font that has to be checked.
+ * @return  true if the font is found
+ */
+    
+    public static boolean isRegistered(String fontname) {
+        String tmp;
+        for (Enumeration e = trueTypeFonts.propertyNames(); e.hasMoreElements(); ) {
+            tmp = (String) e.nextElement();
+            if (fontname.equalsIgnoreCase(tmp)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/Graphic.java b/LibrarySource/com/lowagie/text/Graphic.java
new file mode 100644
index 0000000..ac401af
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Graphic.java
@@ -0,0 +1,277 @@
+/*
+ * $Id: Graphic.java,v 1.57 2004/12/14 12:33:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+import com.lowagie.text.pdf.PdfContentByte;
+
+/**
+ * A <CODE>Graphic</CODE> element can contain several geometric figures (curves, lines,...).
+ * <P>
+ * If you want to use this <CODE>Element</CODE>, please read the Sections 8.4 and 8.5 of
+ * the PDF Reference Manual version 1.3 first.
+ *
+ * @see		Element
+ */
+
+public class Graphic extends PdfContentByte implements Element {
+    
+/** This is a type of Graphic. */
+    public static final String HORIZONTAL_LINE = "HORIZONTAL";
+    
+/** This is a type of Graphic. */
+    public static final String BORDER = "BORDER";
+    
+/** Contains some of the attributes for this Graphic. */
+    private HashMap attributes;
+    
+    // constructor
+    
+/**
+ * Constructs a <CODE>Graphic</CODE>-object.
+ */
+    
+    public Graphic() {
+        super(null);
+    }
+    
+    // implementation of the Element interface
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * <CODE>true</CODE> if the element was processed successfully
+ * @return true if processing this object succeeded
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.GRAPHIC;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+    /**
+     * Orders this graphic to draw a horizontal, centered line.
+     * @param linewidth the line width
+     * @param percentage the percentage horizontal width in relation to the margins or if negative, an absolute value
+     */
+    
+    public void setHorizontalLine(float linewidth, float percentage) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(HORIZONTAL_LINE, new Object[]{new Float(linewidth), new Float(percentage), Color.black, new Integer(Element.ALIGN_CENTER)});
+    }
+    
+    /**
+     * Orders this graphic to draw a horizontal line with some alignment.
+     * @param linewidth the line width
+     * @param percentage the percentage horizontal width in relation to the margins or if negative, an absolute value
+     * @param align the line alignment
+     */
+    public void setHorizontalLine(float linewidth, float percentage, int align) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(HORIZONTAL_LINE, new Object[]{new Float(linewidth), new Float(percentage), Color.black, new Integer(align)});
+    }
+    
+    /**
+     * Orders this graphic to draw a horizontal, centered line.
+     * @param linewidth the line width
+     * @param percentage the percentage horizontal width in relation to the margins or if negative, an absolute value
+     * @param color the color of the line
+     */
+    
+    public void setHorizontalLine(float linewidth, float percentage, Color color) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(HORIZONTAL_LINE, new Object[]{new Float(linewidth), new Float(percentage), color, new Integer(Element.ALIGN_CENTER)});
+    }
+    
+    /**
+     * Orders this graphic to draw a horizontal, centered line.
+     * @param linewidth the line width
+     * @param percentage the percentage horizontal width in relation to the margins or if negative, an absolute value
+     * @param color the color of the line
+     * @param align the line alignment
+     */
+    public void setHorizontalLine(float linewidth, float percentage, Color color, int align) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(HORIZONTAL_LINE, new Object[]{new Float(linewidth), new Float(percentage), color, new Integer(align)});
+    }
+    
+/**
+ * draws a horizontal line.
+ * @param lineWidth width of the line
+ * @param color color of the line
+ * @param x1 start position of the line
+ * @param x2 end position of the line
+ * @param y y-coordinate of the line
+ */
+    
+    public void drawHorizontalLine(float lineWidth, Color color, float x1, float x2, float y) {
+        setLineWidth(lineWidth);
+        setColorStroke(color);
+        moveTo(x1, y);
+        lineTo(x2, y);
+        stroke();
+        resetRGBColorStroke();
+    }
+    
+/**
+ * Orders this graphic to draw a horizontal line.
+ * @param linewidth linewidth of the border
+ * @param extraSpace extraspace needed as marging on the page
+ */
+    
+    public void setBorder(float linewidth, float extraSpace) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(BORDER, new Object[]{new Float(linewidth), new Float(extraSpace), new Color(0, 0, 0)});
+    }
+    
+/**
+ * Orders this graphic to draw a horizontal line.
+ * @param linewidth linewidth of the border
+ * @param extraSpace extraspace needed as marging on the page
+ * @param color color of the borderbox
+ */
+    
+    public void setBorder(float linewidth, float extraSpace, Color color) {
+        if (attributes == null) attributes = new HashMap();
+        attributes.put(BORDER, new Object[]{new Float(linewidth), new Float(extraSpace), color});
+    }
+    
+/**
+ * Draws a border
+ * @param lineWidth linewidth of the border
+ * @param color color of the borderbox
+ * @param llx lower left x coordinate
+ * @param lly lower left y coordinate
+ * @param urx upper right x coordinate
+ * @param ury upper right y coordinate
+ */
+    public void drawBorder(float lineWidth, Color color, float llx, float lly, float urx, float ury) {
+        setLineWidth(lineWidth);
+        setColorStroke(color);
+        rectangle(llx, lly, urx - llx, ury - lly);
+        stroke();
+        resetRGBColorStroke();
+    }
+    
+/**
+ * Processes the attributes of this object.
+ * @param llx lower left x coordinate
+ * @param lly lower left y coordinate
+ * @param urx upper right x coordinate
+ * @param ury upper right y coordinate
+ * @param y
+ */
+    
+    public void processAttributes(float llx, float lly, float urx, float ury, float y) {
+        if (attributes == null) return;
+        String attribute;
+        Object[] o;
+        for (Iterator i = attributes.keySet().iterator(); i.hasNext(); ) {
+            attribute = (String) i.next();
+            o = (Object[]) attributes.get(attribute);
+            if (HORIZONTAL_LINE.equals(attribute)) {
+                float p = ((Float)o[1]).floatValue();
+                float w;
+                if (p < 0)
+                    w = -p;
+                else
+                    w = (urx - llx) * p / 100.0f;
+                int align = ((Integer)o[3]).intValue();
+                float s;
+                switch (align) {
+                    case Element.ALIGN_LEFT:
+                        s = 0;
+                        break;
+                    case Element.ALIGN_RIGHT:
+                        s = urx - llx - w;
+                        break;
+                    default:
+                        s = (urx - llx - w) / 2;
+                }
+                drawHorizontalLine(((Float)o[0]).floatValue(), (Color)o[2], s + llx, s + w + llx, y);
+            }
+            if (BORDER.equals(attribute)) {
+                float extra = ((Float)o[1]).floatValue();
+                drawBorder(((Float)o[0]).floatValue(), (Color)o[2], llx - extra, lly - extra, urx + extra, ury + extra);
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/GreekList.java b/LibrarySource/com/lowagie/text/GreekList.java
new file mode 100644
index 0000000..d87a1d0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/GreekList.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2003 by Michael Niedermair.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text;
+
+/**
+ * 
+ * A special-version of <CODE>LIST</CODE> whitch use greek-letters.
+ * 
+ * @see com.lowagie.text.List
+ * @version 2003-06-22
+ * @author Michael Niedermair
+ */
+
+public class GreekList extends List {
+
+	/**
+	 * UpperCase or LowerCase
+	 */
+	protected boolean greeklower;
+
+	/**
+	 * Initialisierung
+	 * 
+	 * @param symbolIndent	indent
+	 */
+	public GreekList(int symbolIndent) {
+		super(true, symbolIndent);
+		setGreekFont();
+	}
+
+	/**
+	 * Initialisierung 
+	 * @param	greeklower		greek-char in lowercase   
+	 * @param 	symbolIndent	indent
+	 */
+	public GreekList(boolean greeklower, int symbolIndent) {
+		super(true, symbolIndent);
+		this.greeklower = greeklower;
+		setGreekFont();
+	}
+
+	/**
+	 * change the font to SYMBOL
+	 */
+	protected void setGreekFont() {
+		float fontsize = symbol.font().size();
+		symbol.setFont(FontFactory.getFont(FontFactory.SYMBOL, fontsize, Font.NORMAL));
+	}
+
+	/**
+	 * set the greek-letters to lowercase otherwise to uppercase
+	 * 
+	 * @param greeklower
+	 */
+	public void setGreekLower(boolean greeklower) {
+		this.greeklower = greeklower;
+	}
+
+	/**
+	 * Checks if the list is greek-letter with lowercase
+	 *
+	 * @return	<CODE>true</CODE> if the greek-letter is lowercase, <CODE>false</CODE> otherwise.
+	 */
+	public boolean isGreekLower() {
+		return greeklower;
+	}
+
+	/**
+	 * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
+	 *
+	 * @param	o	the object to add.
+	 * @return true if adding the object succeeded
+	 */
+	public boolean add(Object o) {
+		if (o instanceof ListItem) {
+			ListItem item = (ListItem) o;
+			Chunk chunk;
+			if (greeklower)
+				chunk = new Chunk((char) (first + list.size() + 96), symbol.font());
+			else
+				chunk = new Chunk((char) (first + list.size() + 64), symbol.font());
+			chunk.append(".");
+			item.setListSymbol(chunk);
+			item.setIndentationLeft(symbolIndent);
+			item.setIndentationRight(0);
+			list.add(item);
+		} else if (o instanceof List) {
+			List nested = (List) o;
+			nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+			first--;
+			return list.add(nested);
+		} else if (o instanceof String) {
+			return this.add(new ListItem((String) o));
+		}
+		return false;
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/Header.java b/LibrarySource/com/lowagie/text/Header.java
new file mode 100644
index 0000000..5634acb
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Header.java
@@ -0,0 +1,98 @@
+/*
+ * $Id: Header.java,v 1.29 2002/07/09 10:41:33 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * This is an <CODE>Element</CODE> that contains
+ * some userdefined meta information about the document.
+ * <P>
+ * <B>Example:</B>
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>Header header = new Header("inspired by", "William Shakespeare");</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * @see		Element
+ * @see		Meta
+ */
+
+public class Header extends Meta implements Element {
+    
+    // membervariables
+    
+/** This is the content of this chunk of text. */
+    private StringBuffer name;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>Meta</CODE>.
+ *
+ * @param	name		the name of the meta-information
+ * @param	content		the content
+ */
+    
+    public Header(String name, String content) {
+        super(Element.HEADER, content);
+        this.name = new StringBuffer(name);
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns the name of the meta information.
+ *
+ * @return	a <CODE>String</CODE>
+ */
+    
+    public String name() {
+        return name.toString();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/HeaderFooter.java b/LibrarySource/com/lowagie/text/HeaderFooter.java
new file mode 100644
index 0000000..a4427d6
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/HeaderFooter.java
@@ -0,0 +1,206 @@
+/*
+ * $Id: HeaderFooter.java,v 1.44 2003/04/29 07:45:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+
+/**
+ * A <CODE>HeaderFooter</CODE>-object is a <CODE>Rectangle</CODe> with text
+ * that can be put above and/or below every page.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>HeaderFooter header = new HeaderFooter(new Phrase("This is a header."), false);</STRONG>
+ * <STRONG>HeaderFooter footer = new HeaderFooter(new Phrase("This is page "), new Phrase("."));</STRONG>
+ * document.setHeader(header);
+ * document.setFooter(footer);
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class HeaderFooter extends Rectangle implements MarkupAttributes {
+    
+    // membervariables
+    
+/** Does the page contain a pagenumber? */
+    private boolean numbered;
+    
+/** This is the <CODE>Phrase</CODE> that comes before the pagenumber. */
+    private Phrase before = null;
+    
+/** This is number of the page. */
+    private int pageN;
+    
+/** This is the <CODE>Phrase</CODE> that comes after the pagenumber. */
+    private Phrase after = null;
+    
+/** This is alignment of the header/footer. */
+    private int alignment;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>HeaderFooter</CODE>-object.
+ *
+ * @param	before		the <CODE>Phrase</CODE> before the pagenumber
+ * @param	after		the <CODE>Phrase</CODE> before the pagenumber
+ */
+    
+    public HeaderFooter(Phrase before, Phrase after) {
+        super(0, 0, 0, 0);
+        setBorder(TOP + BOTTOM);
+        setBorderWidth(1);
+        
+        numbered = true;
+        this.before = before;
+        this.after = after;
+    }
+    
+/**
+ * Constructs a <CODE>Header</CODE>-object with a pagenumber at the end.
+ *
+ * @param	before		the <CODE>Phrase</CODE> before the pagenumber
+ * @param	numbered	<CODE>true</CODE> if the page has to be numbered
+ */
+    
+    public HeaderFooter(Phrase before, boolean numbered) {
+        super(0, 0, 0, 0);
+        setBorder(TOP + BOTTOM);
+        setBorderWidth(1);
+        
+        this.numbered = numbered;
+        this.before = before;
+    }
+    
+    // methods
+    
+/**
+ * Checks if the HeaderFooter contains a page number.
+ *
+ * @return  true if the page has to be numbered
+ */
+    
+    public boolean isNumbered() {
+        return numbered;
+    }
+    
+/**
+ * Gets the part that comes before the pageNumber.
+ *
+ * @return  a Phrase
+ */
+    
+    public Phrase getBefore() {
+        return before;
+    }
+    
+/**
+ * Gets the part that comes after the pageNumber.
+ *
+ * @return  a Phrase
+ */
+    
+    public Phrase getAfter() {
+        return after;
+    }
+    
+/**
+ * Sets the page number.
+ *
+ * @param		pageN		the new page number
+ */
+    
+    public void setPageNumber(int pageN) {
+        this.pageN = pageN;
+    }
+    
+/**
+ * Sets the alignment.
+ *
+ * @param		alignment	the new alignment
+ */
+    
+    public void setAlignment(int alignment) {
+        this.alignment = alignment;
+    }
+
+    // methods to retrieve the membervariables
+    
+/**
+ * Gets the <CODE>Paragraph</CODE> that can be used as header or footer.
+ *
+ * @return		a <CODE>Paragraph</CODE>
+ */
+    
+    public Paragraph paragraph() {
+        Paragraph paragraph = new Paragraph(before.leading());
+        paragraph.add(before);
+        if (numbered) {
+            paragraph.addSpecial(new Chunk(String.valueOf(pageN), before.font()));
+        }
+        if (after != null) {
+            paragraph.addSpecial(after);
+        }
+        paragraph.setAlignment(alignment);
+        return paragraph;
+    }
+
+    /**
+     * Gets the alignment of this HeaderFooter.
+     *
+     * @return	alignment
+     */
+
+        public int alignment() {
+            return alignment;
+        }
+
+}
diff --git a/LibrarySource/com/lowagie/text/Image.java b/LibrarySource/com/lowagie/text/Image.java
new file mode 100644
index 0000000..870a27b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Image.java
@@ -0,0 +1,1892 @@
+/*
+ * $Id: Image.java,v 1.102 2005/04/13 09:17:15 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Properties;
+import java.util.Set;
+import headless.awt.color.ICC_Profile;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.codec.CCITTG4Encoder;
+import java.lang.reflect.Constructor;
+import com.lowagie.text.pdf.RandomAccessFileOrArray;
+import com.lowagie.text.pdf.PdfDictionary;
+import com.lowagie.text.pdf.codec.GifImage;
+import com.lowagie.text.pdf.codec.PngImage;
+import com.lowagie.text.pdf.codec.TiffImage;
+import com.lowagie.text.pdf.codec.BmpImage;
+import com.lowagie.text.pdf.PdfOCG;
+
+/**
+ * An <CODE>Image</CODE> is the representation of a graphic element (JPEG, PNG
+ * or GIF) that has to be inserted into the document
+ * 
+ * @see Element
+ * @see Rectangle
+ */
+
+public abstract class Image extends Rectangle implements Element,
+		MarkupAttributes {
+
+	// static membervariables
+
+	/** this is a kind of image alignment. */
+	public static final int DEFAULT = 0;
+
+	/** this is a kind of image alignment. */
+	public static final int RIGHT = 2;
+
+	/** this is a kind of image alignment. */
+	public static final int LEFT = 0;
+
+	/** this is a kind of image alignment. */
+	public static final int MIDDLE = 1;
+
+	/** this is a kind of image alignment. */
+	public static final int TEXTWRAP = 4;
+
+	/** this is a kind of image alignment. */
+	public static final int UNDERLYING = 8;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int AX = 0;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int AY = 1;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int BX = 2;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int BY = 3;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int CX = 4;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int CY = 5;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int DX = 6;
+
+	/** This represents a coordinate in the transformation matrix. */
+	public static final int DY = 7;
+
+	/** type of image */
+	public static final int ORIGINAL_NONE = 0;
+
+	/** type of image */
+	public static final int ORIGINAL_JPEG = 1;
+
+	/** type of image */
+	public static final int ORIGINAL_PNG = 2;
+
+	/** type of image */
+	public static final int ORIGINAL_GIF = 3;
+
+	/** type of image */
+	public static final int ORIGINAL_BMP = 4;
+
+	/** type of image */
+	public static final int ORIGINAL_TIFF = 5;
+
+	/** type of image */
+	public static final int ORIGINAL_WMF = 6;
+
+	/** type of image */
+    public static final int ORIGINAL_PS = 7;
+
+	/** Image color inversion */
+	protected boolean invert = false;
+
+	/** The imagetype. */
+	protected int type;
+
+	/** The URL of the image. */
+	protected URL url;
+
+	/** The raw data of the image. */
+	protected byte rawData[];
+
+	/** The template to be treated as an image. */
+	protected PdfTemplate template[] = new PdfTemplate[1];
+
+	/** The alignment of the Image. */
+	protected int alignment;
+
+	/** Text that can be shown instead of the image. */
+	protected String alt;
+
+	/** This is the absolute X-position of the image. */
+	protected float absoluteX = Float.NaN;
+
+	/** This is the absolute Y-position of the image. */
+	protected float absoluteY = Float.NaN;
+
+	/** This is the width of the image without rotation. */
+	protected float plainWidth;
+
+	/** This is the width of the image without rotation. */
+	protected float plainHeight;
+
+	/** This is the scaled width of the image taking rotation into account. */
+	protected float scaledWidth;
+
+	/** This is the original height of the image taking rotation into account. */
+	protected float scaledHeight;
+
+	/** This is the rotation of the image. */
+	protected float rotation;
+
+	/** this is the colorspace of a jpeg-image. */
+	protected int colorspace = -1;
+
+	/**
+	 * this is the bits per component of the raw image. It also flags a CCITT
+	 * image.
+	 */
+	protected int bpc = 1;
+
+	/** this is the transparency information of the raw image */
+	protected int transparency[];
+
+	// for the moment these variables are only used for Images in class Table
+	// code contributed by Pelikan Stephan
+	/** the indentation to the left. */
+	protected float indentationLeft = 0;
+
+	/** the indentation to the right. */
+	protected float indentationRight = 0;
+
+	// serial stamping
+
+	protected Long mySerialId = getSerialId();
+
+	static long serialId = 0;
+
+	/** Holds value of property dpiX. */
+	protected int dpiX = 0;
+
+	/** Holds value of property dpiY. */
+	protected int dpiY = 0;
+
+	protected boolean mask = false;
+
+	protected Image imageMask;
+
+	/** Holds value of property interpolation. */
+	protected boolean interpolation;
+
+	/** if the annotation is not null the image will be clickable. */
+	protected Annotation annotation = null;
+
+	/** Contains extra markupAttributes */
+	protected Properties markupAttributes;
+
+	/** ICC Profile attached */
+	protected ICC_Profile profile = null;
+
+	/** Holds value of property deflated. */
+	protected boolean deflated = false;
+
+	private PdfDictionary additional = null;
+
+	/** Holds value of property smask. */
+	private boolean smask;
+
+	/** Holds value of property XYRatio. */
+	private float XYRatio = 0;
+
+	/** Holds value of property originalType. */
+	protected int originalType = ORIGINAL_NONE;
+
+	/** Holds value of property originalData. */
+	protected byte[] originalData;
+
+	/** The spacing before the image. */
+	protected float spacingBefore;
+
+	/** The spacing after the image. */
+	protected float spacingAfter;
+
+	/**
+	 * Holds value of property widthPercentage.
+	 */
+	private float widthPercentage = 100;
+
+	protected PdfOCG layer;
+
+	// constructors
+
+	/**
+	 * Constructs an <CODE>Image</CODE> -object, using an <VAR>url </VAR>.
+	 * 
+	 * @param url
+	 *            the <CODE>URL</CODE> where the image can be found.
+	 */
+
+	public Image(URL url) {
+		super(0, 0);
+		this.url = url;
+		this.alignment = DEFAULT;
+		rotation = 0;
+	}
+
+	/**
+	 * Constructs an <CODE>Image</CODE> -object, using an <VAR>url </VAR>.
+	 * 
+	 * @param image
+	 *            another Image object.
+	 */
+
+	protected Image(Image image) {
+		super(image);
+		this.type = image.type;
+		this.url = image.url;
+		this.alignment = image.alignment;
+		this.alt = image.alt;
+		this.absoluteX = image.absoluteX;
+		this.absoluteY = image.absoluteY;
+		this.plainWidth = image.plainWidth;
+		this.plainHeight = image.plainHeight;
+		this.scaledWidth = image.scaledWidth;
+		this.scaledHeight = image.scaledHeight;
+		this.rotation = image.rotation;
+		this.colorspace = image.colorspace;
+		this.rawData = image.rawData;
+		this.template = image.template;
+		this.bpc = image.bpc;
+		this.transparency = image.transparency;
+		this.mySerialId = image.mySerialId;
+		this.invert = image.invert;
+		this.dpiX = image.dpiX;
+		this.dpiY = image.dpiY;
+		this.mask = image.mask;
+		this.imageMask = image.imageMask;
+		this.interpolation = image.interpolation;
+		this.annotation = image.annotation;
+		this.markupAttributes = image.markupAttributes;
+		this.profile = image.profile;
+		this.deflated = image.deflated;
+		this.additional = image.additional;
+		this.smask = image.smask;
+		this.XYRatio = image.XYRatio;
+		this.originalData = image.originalData;
+		this.originalType = image.originalType;
+		this.spacingAfter = image.spacingAfter;
+		this.spacingBefore = image.spacingBefore;
+		this.widthPercentage = image.widthPercentage;
+		this.layer = image.layer;
+	}
+
+	/**
+	 * gets an instance of an Image
+	 * 
+	 * @param image
+	 *            an Image object
+	 * @return a new Image object
+	 */
+
+	public static Image getInstance(Image image) {
+		if (image == null)
+			return null;
+		try {
+			Class cs = image.getClass();
+			Constructor constructor = cs
+					.getDeclaredConstructor(new Class[] { Image.class });
+			return (Image) constructor.newInstance(new Object[] { image });
+		} catch (Exception e) {
+			throw new ExceptionConverter(e);
+		}
+	}
+
+	/**
+	 * Gets an instance of an Image.
+	 * 
+	 * @param url
+	 *            an URL
+	 * @return an Image
+	 * @throws BadElementException
+	 * @throws MalformedURLException
+	 * @throws IOException
+	 */
+
+	public static Image getInstance(URL url) throws BadElementException,
+			MalformedURLException, IOException {
+		InputStream is = null;
+		try {
+			is = url.openStream();
+			int c1 = is.read();
+			int c2 = is.read();
+			int c3 = is.read();
+			int c4 = is.read();
+			is.close();
+
+			is = null;
+			if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
+				GifImage gif = new GifImage(url);
+				Image img = gif.getImage(1);
+				return img;
+			}
+			if (c1 == 0xFF && c2 == 0xD8) {
+				return new Jpeg(url);
+			}
+			if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
+					&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
+				return PngImage.getImage(url);
+			}
+            if (c1 == '%' && c2 == '!' && c3 == 'P' && c4 == 'S') {
+               return new ImgPostscript(url);
+            }
+			if (c1 == 0xD7 && c2 == 0xCD) {
+				return new ImgWMF(url);
+			}
+			if (c1 == 'B' && c2 == 'M') {
+				return  BmpImage.getImage(url);
+			}
+			if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
+					|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
+				RandomAccessFileOrArray ra = null;
+				try {
+					if (url.getProtocol().equals("file")) {
+						String file = url.getFile();
+						ra = new RandomAccessFileOrArray(file);
+					} else
+						ra = new RandomAccessFileOrArray(url);
+					Image img = TiffImage.getTiffImage(ra, 1);
+					img.url = url;
+					return img;
+				} finally {
+					if (ra != null)
+						ra.close();
+				}
+
+			}
+			throw new IOException(url.toString()
+					+ " is not a recognized imageformat.");
+		} finally {
+			if (is != null) {
+				is.close();
+			}
+		}
+	}
+
+	/**
+	 * gets an instance of an Image
+	 * 
+	 * @param imgb
+	 *            raw image date
+	 * @return an Image object
+	 * @throws BadElementException
+	 * @throws MalformedURLException
+	 * @throws IOException
+	 */
+	public static Image getInstance(byte imgb[]) throws BadElementException,
+			MalformedURLException, IOException {
+		InputStream is = null;
+		try {
+			is = new java.io.ByteArrayInputStream(imgb);
+			int c1 = is.read();
+			int c2 = is.read();
+			int c3 = is.read();
+			int c4 = is.read();
+			is.close();
+
+			is = null;
+			if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
+				GifImage gif = new GifImage(imgb);
+				return gif.getImage(1);
+			}
+			if (c1 == 0xFF && c2 == 0xD8) {
+				return new Jpeg(imgb);
+			}
+			if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
+					&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
+				return PngImage.getImage(imgb);
+			}
+            if (c1 == '%' && c2 == '!' && c3 == 'P' && c4 == 'S') {
+               return new ImgPostscript(imgb);
+            }
+			if (c1 == 0xD7 && c2 == 0xCD) {
+				return new ImgWMF(imgb);
+			}
+			if (c1 == 'B' && c2 == 'M') {
+				return BmpImage.getImage(imgb);
+			}
+			if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
+					|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
+				RandomAccessFileOrArray ra = null;
+				try {
+					ra = new RandomAccessFileOrArray(imgb);
+					Image img = TiffImage.getTiffImage(ra, 1);
+					img.setOriginalData(imgb);
+					return img;
+				} finally {
+					if (ra != null)
+						ra.close();
+				}
+
+			}
+			throw new IOException(
+					"The byte array is not a recognized imageformat.");
+		} finally {
+			if (is != null) {
+				is.close();
+			}
+		}
+	}
+
+	/**
+	 * Gets an instance of an Image from a java.awt.Image.
+	 * 
+	 * @param image
+	 *            the <CODE>java.awt.Image</CODE> to convert
+	 * @param color
+	 *            if different from <CODE>null</CODE> the transparency pixels
+	 *            are replaced by this color
+	 * @param forceBW
+	 *            if <CODE>true</CODE> the image is treated as black and white
+	 * @return an object of type <CODE>ImgRaw</CODE>
+	 * @throws BadElementException
+	 *             on error
+	 * @throws IOException
+	 *             on error
+	 */
+
+	public static Image getInstance(java.awt.Image image, java.awt.Color color,
+			boolean forceBW) throws BadElementException, IOException {
+		java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(image,
+				0, 0, -1, -1, true);
+		try {
+			pg.grabPixels();
+		} catch (InterruptedException e) {
+			throw new IOException(
+					"java.awt.Image Interrupted waiting for pixels!");
+		}
+		if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) {
+			throw new IOException("java.awt.Image fetch aborted or errored");
+		}
+		int w = pg.getWidth();
+		int h = pg.getHeight();
+		int[] pixels = (int[]) pg.getPixels();
+		if (forceBW) {
+			int byteWidth = (w / 8) + ((w & 7) != 0 ? 1 : 0);
+			byte[] pixelsByte = new byte[byteWidth * h];
+
+			int index = 0;
+			int size = h * w;
+			int transColor = 1;
+			if (color != null) {
+				transColor = (color.getRed() + color.getGreen()
+						+ color.getBlue() < 384) ? 0 : 1;
+			}
+			int transparency[] = null;
+			int cbyte = 0x80;
+			int wMarker = 0;
+			int currByte = 0;
+			if (color != null) {
+				for (int j = 0; j < size; j++) {
+					int alpha = (pixels[j] >> 24) & 0xff;
+					if (alpha < 250) {
+						if (transColor == 1)
+							currByte |= cbyte;
+					} else {
+						if ((pixels[j] & 0x888) != 0)
+							currByte |= cbyte;
+					}
+					cbyte >>= 1;
+					if (cbyte == 0 || wMarker + 1 >= w) {
+						pixelsByte[index++] = (byte) currByte;
+						cbyte = 0x80;
+						currByte = 0;
+					}
+					++wMarker;
+					if (wMarker >= w)
+						wMarker = 0;
+				}
+			} else {
+				for (int j = 0; j < size; j++) {
+					if (transparency == null) {
+						int alpha = (pixels[j] >> 24) & 0xff;
+						if (alpha == 0) {
+							transparency = new int[2];
+							transparency[0] = transparency[1] = ((pixels[j] & 0x888) != 0) ? 1
+									: 0;
+						}
+					}
+					if ((pixels[j] & 0x888) != 0)
+						currByte |= cbyte;
+					cbyte >>= 1;
+					if (cbyte == 0 || wMarker + 1 >= w) {
+						pixelsByte[index++] = (byte) currByte;
+						cbyte = 0x80;
+						currByte = 0;
+					}
+					++wMarker;
+					if (wMarker >= w)
+						wMarker = 0;
+				}
+			}
+			return Image.getInstance(w, h, 1, 1, pixelsByte, transparency);
+		} else {
+			byte[] pixelsByte = new byte[w * h * 3];
+			byte[] smask = null;
+
+			int index = 0;
+			int size = h * w;
+			int red = 255;
+			int green = 255;
+			int blue = 255;
+			if (color != null) {
+				red = color.getRed();
+				green = color.getGreen();
+				blue = color.getBlue();
+			}
+			int transparency[] = null;
+			if (color != null) {
+				for (int j = 0; j < size; j++) {
+					int alpha = (pixels[j] >> 24) & 0xff;
+					if (alpha < 250) {
+						pixelsByte[index++] = (byte) red;
+						pixelsByte[index++] = (byte) green;
+						pixelsByte[index++] = (byte) blue;
+					} else {
+						pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
+						pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
+						pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
+					}
+				}
+			} else {
+				int transparentPixel = 0;
+				smask = new byte[w * h];
+				boolean shades = false;
+				for (int j = 0; j < size; j++) {
+					byte alpha = smask[j] = (byte) ((pixels[j] >> 24) & 0xff);
+					/* bugfix by Chris Nokleberg */
+					if (!shades) {
+						if (alpha != 0 && alpha != -1) {
+							shades = true;
+						} else if (transparency == null) {
+							if (alpha == 0) {
+								transparentPixel = pixels[j] & 0xffffff;
+								transparency = new int[6];
+								transparency[0] = transparency[1] = (transparentPixel >> 16) & 0xff;
+								transparency[2] = transparency[3] = (transparentPixel >> 8) & 0xff;
+								transparency[4] = transparency[5] = transparentPixel & 0xff;
+							}
+						} else if ((pixels[j] & 0xffffff) != transparentPixel) {
+							shades = true;
+						}
+					}
+					pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
+					pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
+					pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
+				}
+				if (shades)
+					transparency = null;
+				else
+					smask = null;
+			}
+			Image img = Image.getInstance(w, h, 3, 8, pixelsByte, transparency);
+			if (smask != null) {
+				Image sm = Image.getInstance(w, h, 1, 8, smask);
+				try {
+					sm.makeMask();
+					img.setImageMask(sm);
+				} catch (DocumentException de) {
+					throw new ExceptionConverter(de);
+				}
+			}
+			return img;
+		}
+	}
+
+	/**
+	 * Gets an instance of an Image from a java.awt.Image.
+	 * 
+	 * @param image
+	 *            the <CODE>java.awt.Image</CODE> to convert
+	 * @param color
+	 *            if different from <CODE>null</CODE> the transparency pixels
+	 *            are replaced by this color
+	 * @return an object of type <CODE>ImgRaw</CODE>
+	 * @throws BadElementException
+	 *             on error
+	 * @throws IOException
+	 *             on error
+	 */
+	public static Image getInstance(java.awt.Image image, java.awt.Color color)
+			throws BadElementException, IOException {
+		return Image.getInstance(image, color, false);
+	}
+
+	/**
+	 * Gets an instance of an Image.
+	 * 
+	 * @param filename
+	 *            a filename
+	 * @return an object of type <CODE>Gif</CODE>,<CODE>Jpeg</CODE> or
+	 *         <CODE>Png</CODE>
+	 * @throws BadElementException
+	 * @throws MalformedURLException
+	 * @throws IOException
+	 */
+
+	public static Image getInstance(String filename)
+			throws BadElementException, MalformedURLException, IOException {
+		return getInstance(toURL(filename));
+	}
+
+	/**
+	 * Gets an instance of an Image in raw mode.
+	 * 
+	 * @param width
+	 *            the width of the image in pixels
+	 * @param height
+	 *            the height of the image in pixels
+	 * @param components
+	 *            1,3 or 4 for GrayScale, RGB and CMYK
+	 * @param data
+	 *            the image data
+	 * @param bpc
+	 *            bits per component
+	 * @return an object of type <CODE>ImgRaw</CODE>
+	 * @throws BadElementException
+	 *             on error
+	 */
+
+	public static Image getInstance(int width, int height, int components,
+			int bpc, byte data[]) throws BadElementException {
+		return Image.getInstance(width, height, components, bpc, data, null);
+	}
+
+	/**
+	 * gets an instance of an Image
+	 * 
+	 * @param template
+	 *            a PdfTemplate that has to be wrapped in an Image object
+	 * @return an Image object
+	 * @throws BadElementException
+	 */
+	public static Image getInstance(PdfTemplate template)
+			throws BadElementException {
+		return new ImgTemplate(template);
+	}
+
+	/**
+	 * Creates an Image with CCITT G3 or G4 compression. It assumes that the
+	 * data bytes are already compressed.
+	 * 
+	 * @param width
+	 *            the exact width of the image
+	 * @param height
+	 *            the exact height of the image
+	 * @param reverseBits
+	 *            reverses the bits in <code>data</code>. Bit 0 is swapped
+	 *            with bit 7 and so on
+	 * @param typeCCITT
+	 *            the type of compression in <code>data</code>. It can be
+	 *            CCITTG4, CCITTG31D, CCITTG32D
+	 * @param parameters
+	 *            parameters associated with this stream. Possible values are
+	 *            CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
+	 *            CCITT_ENDOFBLOCK or a combination of them
+	 * @param data
+	 *            the image data
+	 * @return an Image object
+	 * @throws BadElementException
+	 *             on error
+	 */
+	public static Image getInstance(int width, int height, boolean reverseBits,
+			int typeCCITT, int parameters, byte[] data)
+			throws BadElementException {
+		return Image.getInstance(width, height, reverseBits, typeCCITT,
+				parameters, data, null);
+	}
+
+	/**
+	 * Creates an Image with CCITT G3 or G4 compression. It assumes that the
+	 * data bytes are already compressed.
+	 * 
+	 * @param width
+	 *            the exact width of the image
+	 * @param height
+	 *            the exact height of the image
+	 * @param reverseBits
+	 *            reverses the bits in <code>data</code>. Bit 0 is swapped
+	 *            with bit 7 and so on
+	 * @param typeCCITT
+	 *            the type of compression in <code>data</code>. It can be
+	 *            CCITTG4, CCITTG31D, CCITTG32D
+	 * @param parameters
+	 *            parameters associated with this stream. Possible values are
+	 *            CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
+	 *            CCITT_ENDOFBLOCK or a combination of them
+	 * @param data
+	 *            the image data
+	 * @param transparency
+	 *            transparency information in the Mask format of the image
+	 *            dictionary
+	 * @return an Image object
+	 * @throws BadElementException
+	 *             on error
+	 */
+	public static Image getInstance(int width, int height, boolean reverseBits,
+			int typeCCITT, int parameters, byte[] data, int transparency[])
+			throws BadElementException {
+		if (transparency != null && transparency.length != 2)
+			throw new BadElementException(
+					"Transparency length must be equal to 2 with CCITT images");
+		Image img = new ImgCCITT(width, height, reverseBits, typeCCITT,
+				parameters, data);
+		img.transparency = transparency;
+		return img;
+	}
+
+	/**
+	 * Gets an instance of an Image in raw mode.
+	 * 
+	 * @param width
+	 *            the width of the image in pixels
+	 * @param height
+	 *            the height of the image in pixels
+	 * @param components
+	 *            1,3 or 4 for GrayScale, RGB and CMYK
+	 * @param data
+	 *            the image data
+	 * @param bpc
+	 *            bits per component
+	 * @param transparency
+	 *            transparency information in the Mask format of the image
+	 *            dictionary
+	 * @return an object of type <CODE>ImgRaw</CODE>
+	 * @throws BadElementException
+	 *             on error
+	 */
+
+	public static Image getInstance(int width, int height, int components,
+			int bpc, byte data[], int transparency[])
+			throws BadElementException {
+		if (transparency != null && transparency.length != components * 2)
+			throw new BadElementException(
+					"Transparency length must be equal to (componentes * 2)");
+		if (components == 1 && bpc == 1) {
+			byte g4[] = CCITTG4Encoder.compress(data, width, height);
+			return Image.getInstance(width, height, false, Image.CCITTG4,
+					Image.CCITT_BLACKIS1, g4, transparency);
+		}
+		Image img = new ImgRaw(width, height, components, bpc, data);
+		img.transparency = transparency;
+		return img;
+	}
+
+	/**
+	 * Returns an <CODE>Image</CODE> that has been constructed taking in
+	 * account the value of some <VAR>attributes </VAR>.
+	 * 
+	 * @param attributes
+	 *            Some attributes
+	 * @return an <CODE>Image</CODE>
+	 * @throws BadElementException
+	 * @throws MalformedURLException
+	 * @throws IOException
+	 */
+
+	public static Image getInstance(Properties attributes)
+			throws BadElementException, MalformedURLException, IOException {
+		String value = (String) attributes.remove(ElementTags.URL);
+		if (value == null)
+			throw new MalformedURLException("The URL of the image is missing.");
+		Image image = Image.getInstance(value);
+		int align = 0;
+		if ((value = (String) attributes.remove(ElementTags.ALIGN)) != null) {
+			if (ElementTags.ALIGN_LEFT.equalsIgnoreCase(value))
+				align |= Image.LEFT;
+			else if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(value))
+				align |= Image.RIGHT;
+			else if (ElementTags.ALIGN_MIDDLE.equalsIgnoreCase(value))
+				align |= Image.MIDDLE;
+		}
+		if ((value = (String) attributes.remove(ElementTags.UNDERLYING)) != null) {
+			if (new Boolean(value).booleanValue())
+				align |= Image.UNDERLYING;
+		}
+		if ((value = (String) attributes.remove(ElementTags.TEXTWRAP)) != null) {
+			if (new Boolean(value).booleanValue())
+				align |= Image.TEXTWRAP;
+		}
+		image.setAlignment(align);
+		if ((value = (String) attributes.remove(ElementTags.ALT)) != null) {
+			image.setAlt(value);
+		}
+		String x;
+		String y;
+		if (((x = (String) attributes.remove(ElementTags.ABSOLUTEX)) != null)
+				&& ((y = (String) attributes.remove(ElementTags.ABSOLUTEY)) != null)) {
+			image.setAbsolutePosition(Float.valueOf(x + "f").floatValue(),
+					Float.valueOf(y + "f").floatValue());
+		}
+		if ((value = (String) attributes.remove(ElementTags.PLAINWIDTH)) != null) {
+			image.scaleAbsoluteWidth(Float.valueOf(value + "f").floatValue());
+		}
+		if ((value = (String) attributes.remove(ElementTags.PLAINHEIGHT)) != null) {
+			image.scaleAbsoluteHeight(Float.valueOf(value + "f").floatValue());
+		}
+		if ((value = (String) attributes.remove(ElementTags.ROTATION)) != null) {
+			image.setRotation(Float.valueOf(value + "f").floatValue());
+		}
+		if (attributes.size() > 0)
+			image.setMarkupAttributes(attributes);
+		return image;
+	}
+
+	// methods to set information
+
+	/**
+	 * Sets the alignment for the image.
+	 * 
+	 * @param alignment
+	 *            the alignment
+	 */
+
+	public void setAlignment(int alignment) {
+		this.alignment = alignment;
+	}
+
+	/**
+	 * Sets the alternative information for the image.
+	 * 
+	 * @param alt
+	 *            the alternative information
+	 */
+
+	public void setAlt(String alt) {
+		this.alt = alt;
+	}
+
+	/**
+	 * Sets the absolute position of the <CODE>Image</CODE>.
+	 * 
+	 * @param absoluteX
+	 * @param absoluteY
+	 */
+
+	public void setAbsolutePosition(float absoluteX, float absoluteY) {
+		this.absoluteX = absoluteX;
+		this.absoluteY = absoluteY;
+	}
+
+	/**
+	 * Scale the image to an absolute width and an absolute height.
+	 * 
+	 * @param newWidth
+	 *            the new width
+	 * @param newHeight
+	 *            the new height
+	 */
+
+	public void scaleAbsolute(float newWidth, float newHeight) {
+		plainWidth = newWidth;
+		plainHeight = newHeight;
+		float[] matrix = matrix();
+		scaledWidth = matrix[DX] - matrix[CX];
+		scaledHeight = matrix[DY] - matrix[CY];
+	}
+
+	/**
+	 * Scale the image to an absolute width.
+	 * 
+	 * @param newWidth
+	 *            the new width
+	 */
+
+	public void scaleAbsoluteWidth(float newWidth) {
+		plainWidth = newWidth;
+		float[] matrix = matrix();
+		scaledWidth = matrix[DX] - matrix[CX];
+		scaledHeight = matrix[DY] - matrix[CY];
+	}
+
+	/**
+	 * Scale the image to an absolute height.
+	 * 
+	 * @param newHeight
+	 *            the new height
+	 */
+
+	public void scaleAbsoluteHeight(float newHeight) {
+		plainHeight = newHeight;
+		float[] matrix = matrix();
+		scaledWidth = matrix[DX] - matrix[CX];
+		scaledHeight = matrix[DY] - matrix[CY];
+	}
+
+	/**
+	 * Scale the image to a certain percentage.
+	 * 
+	 * @param percent
+	 *            the scaling percentage
+	 */
+
+	public void scalePercent(float percent) {
+		scalePercent(percent, percent);
+	}
+
+	/**
+	 * Scale the width and height of an image to a certain percentage.
+	 * 
+	 * @param percentX
+	 *            the scaling percentage of the width
+	 * @param percentY
+	 *            the scaling percentage of the height
+	 */
+
+	public void scalePercent(float percentX, float percentY) {
+		plainWidth = (width() * percentX) / 100f;
+		plainHeight = (height() * percentY) / 100f;
+		float[] matrix = matrix();
+		scaledWidth = matrix[DX] - matrix[CX];
+		scaledHeight = matrix[DY] - matrix[CY];
+	}
+
+	/**
+	 * Scales the image so that it fits a certain width and height.
+	 * 
+	 * @param fitWidth
+	 *            the width to fit
+	 * @param fitHeight
+	 *            the height to fit
+	 */
+
+	public void scaleToFit(float fitWidth, float fitHeight) {
+		float percentX = (fitWidth * 100) / width();
+		float percentY = (fitHeight * 100) / height();
+		scalePercent(percentX < percentY ? percentX : percentY);
+	}
+
+	/**
+	 * Sets the rotation of the image in radians.
+	 * 
+	 * @param r
+	 *            rotation in radians
+	 */
+
+	public void setRotation(float r) {
+		double d = Math.PI; //__IDS__
+		rotation = (float) (r % (2.0 * d)); //__IDS__
+		if (rotation < 0) {
+			rotation += 2.0 * d; //__IDS__
+		}
+		float[] matrix = matrix();
+		scaledWidth = matrix[DX] - matrix[CX];
+		scaledHeight = matrix[DY] - matrix[CY];
+	}
+
+	/**
+	 * Sets the rotation of the image in degrees.
+	 * 
+	 * @param deg
+	 *            rotation in degrees
+	 */
+
+	public void setRotationDegrees(float deg) {
+		double d = Math.PI; //__IDS__
+		setRotation(deg / 180 * (float) d); //__IDS__
+	}
+
+	/**
+	 * Sets the annotation of this Image.
+	 * 
+	 * @param annotation
+	 *            the annotation
+	 */
+
+	public void setAnnotation(Annotation annotation) {
+		this.annotation = annotation;
+	}
+
+	/**
+	 * Gets the annotation.
+	 * 
+	 * @return the annotation that is linked to this image
+	 */
+
+	public Annotation annotation() {
+		return annotation;
+	}
+
+	// methods to retrieve information
+
+	/**
+	 * Gets the bpc for the image.
+	 * <P>
+	 * Remark: this only makes sense for Images of the type <CODE>RawImage
+	 * </CODE>.
+	 * 
+	 * @return a bpc value
+	 */
+
+	public int bpc() {
+		return bpc;
+	}
+
+	/**
+	 * Gets the raw data for the image.
+	 * <P>
+	 * Remark: this only makes sense for Images of the type <CODE>RawImage
+	 * </CODE>.
+	 * 
+	 * @return the raw data
+	 */
+
+	public byte[] rawData() {
+		return rawData;
+	}
+
+	/**
+	 * Gets the template to be used as an image.
+	 * <P>
+	 * Remark: this only makes sense for Images of the type <CODE>ImgTemplate
+	 * </CODE>.
+	 * 
+	 * @return the template
+	 */
+
+	public PdfTemplate templateData() {
+		return template[0];
+	}
+
+	/**
+	 * Sets data from a PdfTemplate
+	 * 
+	 * @param template
+	 *            the template with the content
+	 */
+	public void setTemplateData(PdfTemplate template) {
+		this.template[0] = template;
+	}
+
+	/**
+	 * Checks if the <CODE>Images</CODE> has to be added at an absolute
+	 * position.
+	 * 
+	 * @return a boolean
+	 */
+
+	public boolean hasAbsolutePosition() {
+		return !Float.isNaN(absoluteY);
+	}
+
+	/**
+	 * Checks if the <CODE>Images</CODE> has to be added at an absolute X
+	 * position.
+	 * 
+	 * @return a boolean
+	 */
+
+	public boolean hasAbsoluteX() {
+		return !Float.isNaN(absoluteX);
+	}
+
+	/**
+	 * Returns the absolute X position.
+	 * 
+	 * @return a position
+	 */
+
+	public float absoluteX() {
+		return absoluteX;
+	}
+
+	/**
+	 * Returns the absolute Y position.
+	 * 
+	 * @return a position
+	 */
+
+	public float absoluteY() {
+		return absoluteY;
+	}
+
+	/**
+	 * Returns the type.
+	 * 
+	 * @return a type
+	 */
+
+	public int type() {
+		return type;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if the image is a <CODE>Jpeg</CODE>
+	 * -object.
+	 * 
+	 * @return a <CODE>boolean</CODE>
+	 */
+
+	public boolean isJpeg() {
+		return type == JPEG;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if the image is a <CODE>ImgRaw</CODE>
+	 * -object.
+	 * 
+	 * @return a <CODE>boolean</CODE>
+	 */
+
+	public boolean isImgRaw() {
+		return type == IMGRAW;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if the image is an <CODE>ImgTemplate</CODE>
+	 * -object.
+	 * 
+	 * @return a <CODE>boolean</CODE>
+	 */
+
+	public boolean isImgTemplate() {
+		return type == IMGTEMPLATE;
+	}
+
+	/**
+	 * Gets the <CODE>String</CODE> -representation of the reference to the
+	 * image.
+	 * 
+	 * @return a <CODE>String</CODE>
+	 */
+
+	public URL url() {
+		return url;
+	}
+
+	/**
+	 * Gets the alignment for the image.
+	 * 
+	 * @return a value
+	 */
+
+	public int alignment() {
+		return alignment;
+	}
+
+	/**
+	 * Gets the alternative text for the image.
+	 * 
+	 * @return a <CODE>String</CODE>
+	 */
+
+	public String alt() {
+		return alt;
+	}
+
+	/**
+	 * Gets the scaled width of the image.
+	 * 
+	 * @return a value
+	 */
+
+	public float scaledWidth() {
+		return scaledWidth;
+	}
+
+	/**
+	 * Gets the scaled height of the image.
+	 * 
+	 * @return a value
+	 */
+
+	public float scaledHeight() {
+		return scaledHeight;
+	}
+
+	/**
+	 * Gets the colorspace for the image.
+	 * <P>
+	 * Remark: this only makes sense for Images of the type <CODE>Jpeg</CODE>.
+	 * 
+	 * @return a colorspace value
+	 */
+
+	public int colorspace() {
+		return colorspace;
+	}
+
+	/**
+	 * Returns the transformation matrix of the image.
+	 * 
+	 * @return an array [AX, AY, BX, BY, CX, CY, DX, DY]
+	 */
+
+	public float[] matrix() {
+		float[] matrix = new float[8];
+		float cosX = (float) Math.cos(rotation);
+		float sinX = (float) Math.sin(rotation);
+		matrix[AX] = plainWidth * cosX;
+		matrix[AY] = plainWidth * sinX;
+		matrix[BX] = (-plainHeight) * sinX;
+		matrix[BY] = plainHeight * cosX;
+		if (rotation < Math.PI / 2f) {
+			matrix[CX] = matrix[BX];
+			matrix[CY] = 0;
+			matrix[DX] = matrix[AX];
+			matrix[DY] = matrix[AY] + matrix[BY];
+		} else if (rotation < Math.PI) {
+			matrix[CX] = matrix[AX] + matrix[BX];
+			matrix[CY] = matrix[BY];
+			matrix[DX] = 0;
+			matrix[DY] = matrix[AY];
+		} else if (rotation < Math.PI * 1.5f) {
+			matrix[CX] = matrix[AX];
+			matrix[CY] = matrix[AY] + matrix[BY];
+			matrix[DX] = matrix[BX];
+			matrix[DY] = 0;
+		} else {
+			matrix[CX] = 0;
+			matrix[CY] = matrix[AY];
+			matrix[DX] = matrix[AX] + matrix[BX];
+			matrix[DY] = matrix[BY];
+		}
+		return matrix;
+	}
+
+	/**
+	 * This method is an alternative for the <CODE>InputStream.skip()</CODE>
+	 * -method that doesn't seem to work properly for big values of <CODE>size
+	 * </CODE>.
+	 * 
+	 * @param is
+	 *            the <CODE>InputStream</CODE>
+	 * @param size
+	 *            the number of bytes to skip
+	 * @throws IOException
+	 */
+
+	static public void skip(InputStream is, int size) throws IOException {
+		while (size > 0) {
+			size -= is.skip(size);
+		}
+	}
+
+	/**
+	 * This method makes a valid URL from a given filename.
+	 * <P>
+	 * This method makes the conversion of this library from the JAVA 2 platform
+	 * to a JDK1.1.x-version easier.
+	 * 
+	 * @param filename
+	 *            a given filename
+	 * @return a valid URL
+	 * @throws MalformedURLException
+	 */
+
+	public static URL toURL(String filename) throws MalformedURLException {
+		if (filename.startsWith("file:/") || filename.startsWith("http://")
+				|| filename.startsWith("https://")
+				|| filename.startsWith("jar:")) {
+			return new URL(filename);
+		}
+		File f = new File(filename);
+		String path = f.getAbsolutePath();
+		if (File.separatorChar != '/') {
+			path = path.replace(File.separatorChar, '/');
+		}
+		if (!path.startsWith("/")) {
+			path = "/" + path;
+		}
+		if (!path.endsWith("/") && f.isDirectory()) {
+			path = path + "/";
+		}
+		return new URL("file", "", path);
+	}
+
+	/**
+	 * Returns the transparency.
+	 * 
+	 * @return the transparency values
+	 */
+
+	public int[] getTransparency() {
+		return transparency;
+	}
+
+	/**
+	 * Sets the transparency values
+	 * 
+	 * @param transparency
+	 *            the transparency values
+	 */
+	public void setTransparency(int transparency[]) {
+		this.transparency = transparency;
+	}
+
+	/**
+	 * Checks if a given tag corresponds with this object.
+	 * 
+	 * @param tag
+	 *            the given tag
+	 * @return true if the tag corresponds
+	 */
+
+	public static boolean isTag(String tag) {
+		return ElementTags.IMAGE.equals(tag);
+	}
+
+	/**
+	 * Gets the plain width of the image.
+	 * 
+	 * @return a value
+	 */
+
+	public float plainWidth() {
+		return plainWidth;
+	}
+
+	/**
+	 * Gets the plain height of the image.
+	 * 
+	 * @return a value
+	 */
+
+	public float plainHeight() {
+		return plainHeight;
+	}
+
+	static protected synchronized Long getSerialId() {
+		++serialId;
+		return new Long(serialId);
+	}
+
+	/**
+	 * Returns a serial id for the Image (reuse the same image more than once)
+	 * 
+	 * @return a serialId
+	 */
+	public Long getMySerialId() {
+		return mySerialId;
+	}
+
+	/**
+	 * Gets the dots-per-inch in the X direction. Returns 0 if not available.
+	 * 
+	 * @return the dots-per-inch in the X direction
+	 */
+	public int getDpiX() {
+		return dpiX;
+	}
+
+	/**
+	 * Gets the dots-per-inch in the Y direction. Returns 0 if not available.
+	 * 
+	 * @return the dots-per-inch in the Y direction
+	 */
+	public int getDpiY() {
+		return dpiY;
+	}
+
+	/**
+	 * Sets the dots per inch value
+	 * 
+	 * @param dpiX
+	 *            dpi for x coordinates
+	 * @param dpiY
+	 *            dpi for y coordinates
+	 */
+	public void setDpi(int dpiX, int dpiY) {
+		this.dpiX = dpiX;
+		this.dpiY = dpiY;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if this <CODE>Image</CODE> has the
+	 * requisites to be a mask.
+	 * 
+	 * @return <CODE>true</CODE> if this <CODE>Image</CODE> can be a mask
+	 */
+	public boolean isMaskCandidate() {
+		if (type == IMGRAW) {
+			if (bpc > 0xff)
+				return true;
+		}
+		return colorspace == 1;
+	}
+
+	/**
+	 * Make this <CODE>Image</CODE> a mask.
+	 * 
+	 * @throws DocumentException
+	 *             if this <CODE>Image</CODE> can not be a mask
+	 */
+	public void makeMask() throws DocumentException {
+		if (!isMaskCandidate())
+			throw new DocumentException("This image can not be an image mask.");
+		mask = true;
+	}
+
+	/**
+	 * Sets the explicit masking.
+	 * 
+	 * @param mask
+	 *            the mask to be applied
+	 * @throws DocumentException
+	 *             on error
+	 */
+	public void setImageMask(Image mask) throws DocumentException {
+		if (this.mask)
+			throw new DocumentException(
+					"An image mask cannot contain another image mask.");
+		if (!mask.mask)
+			throw new DocumentException(
+					"The image mask is not a mask. Did you do makeMask()?");
+		imageMask = mask;
+		smask = (mask.bpc > 1 && mask.bpc <= 8);
+	}
+
+	/**
+	 * Gets the explicit masking.
+	 * 
+	 * @return the explicit masking
+	 */
+	public Image getImageMask() {
+		return imageMask;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if this <CODE>Image</CODE> is a mask.
+	 * 
+	 * @return <CODE>true</CODE> if this <CODE>Image</CODE> is a mask
+	 */
+	public boolean isMask() {
+		return mask;
+	}
+
+	/**
+	 * Inverts the meaning of the bits of a mask.
+	 * 
+	 * @param invert
+	 *            <CODE>true</CODE> to invert the meaning of the bits of a
+	 *            mask
+	 */
+	public void setInvertMask(boolean invert) {
+		this.invert = invert;
+	}
+
+	/**
+	 * Returns <CODE>true</CODE> if the bits are to be inverted in the mask.
+	 * 
+	 * @return <CODE>true</CODE> if the bits are to be inverted in the mask
+	 */
+	public boolean isInvertMask() {
+		return invert;
+	}
+
+	/**
+	 * Getter for the inverted value
+	 * 
+	 * @return true if the image is inverted
+	 */
+	public boolean isInverted() {
+		return invert;
+	}
+
+	/**
+	 * Sets inverted true or false
+	 * 
+	 * @param invert
+	 *            true or false
+	 */
+	public void setInverted(boolean invert) {
+		this.invert = invert;
+	}
+
+	/**
+	 * Getter for property interpolation.
+	 * 
+	 * @return Value of property interpolation.
+	 */
+	public boolean isInterpolation() {
+		return interpolation;
+	}
+
+	/**
+	 * Sets the image interpolation. Image interpolation attempts to produce a
+	 * smooth transition between adjacent sample values.
+	 * 
+	 * @param interpolation
+	 *            New value of property interpolation.
+	 */
+	public void setInterpolation(boolean interpolation) {
+		this.interpolation = interpolation;
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
+	 *      java.lang.String)
+	 */
+	public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+		markupAttributes.put(name, value);
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+	 */
+	public void setMarkupAttributes(Properties markupAttributes) {
+		this.markupAttributes = markupAttributes;
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+	 */
+	public String getMarkupAttribute(String name) {
+		return (markupAttributes == null) ? null : String
+				.valueOf(markupAttributes.get(name));
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+	 */
+	public Set getMarkupAttributeNames() {
+		return Chunk.getKeySet(markupAttributes);
+	}
+
+	/**
+	 * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+	 */
+	public Properties getMarkupAttributes() {
+		return markupAttributes;
+	}
+
+	/**
+	 * Tags this image with an ICC profile.
+	 * 
+	 * @param profile
+	 *            the profile
+	 */
+	public void tagICC(ICC_Profile profile) {
+		this.profile = profile;
+	}
+
+	/**
+	 * Checks is the image has an ICC profile.
+	 * 
+	 * @return the ICC profile or <CODE>null</CODE>
+	 */
+	public boolean hasICCProfile() {
+		return (this.profile != null);
+	}
+
+	/**
+	 * Gets the images ICC profile.
+	 * 
+	 * @return the ICC profile
+	 */
+	public ICC_Profile getICCProfile() {
+		return profile;
+	}
+
+	/**
+	 * Getter for property deflated.
+	 * 
+	 * @return Value of property deflated.
+	 *  
+	 */
+	public boolean isDeflated() {
+		return this.deflated;
+	}
+
+	/**
+	 * Setter for property deflated.
+	 * 
+	 * @param deflated
+	 *            New value of property deflated.
+	 *  
+	 */
+	public void setDeflated(boolean deflated) {
+		this.deflated = deflated;
+	}
+
+	/**
+	 * Getter for property indexed.
+	 * 
+	 * @return Value of property indexed.
+	 *  
+	 */
+	public PdfDictionary getAdditional() {
+		return this.additional;
+	}
+
+	/**
+	 * Sets the /Colorspace key.
+	 * 
+	 * @param additional
+	 *            New value of property indexed.
+	 */
+	public void setAdditional(PdfDictionary additional) {
+		this.additional = additional;
+	}
+
+	/**
+	 * Getter for property smask.
+	 * 
+	 * @return Value of property smask.
+	 *  
+	 */
+	public boolean isSmask() {
+		return this.smask;
+	}
+
+	/**
+	 * Setter for property smask.
+	 * 
+	 * @param smask
+	 *            New value of property smask.
+	 *  
+	 */
+	public void setSmask(boolean smask) {
+		this.smask = smask;
+	}
+
+	/**
+	 * Gets the X/Y pixel dimensionless aspect ratio.
+	 * 
+	 * @return the X/Y pixel dimensionless aspect ratio
+	 */
+	public float getXYRatio() {
+		return this.XYRatio;
+	}
+
+	/**
+	 * Sets the X/Y pixel dimensionless aspect ratio.
+	 * 
+	 * @param XYRatio
+	 *            the X/Y pixel dimensionless aspect ratio
+	 */
+	public void setXYRatio(float XYRatio) {
+		this.XYRatio = XYRatio;
+	}
+
+	/**
+	 * Gets the left indentation.
+	 * 
+	 * @return the left indentation
+	 */
+	public float indentationLeft() {
+		return indentationLeft;
+	}
+
+	/**
+	 * Gets the right indentation.
+	 * 
+	 * @return the right indentation
+	 */
+	public float indentationRight() {
+		return indentationRight;
+	}
+
+	/**
+	 * Sets the left indentation.
+	 * 
+	 * @param f
+	 */
+	public void setIndentationLeft(float f) {
+		indentationLeft = f;
+	}
+
+	/**
+	 * Sets the right indentation.
+	 * 
+	 * @param f
+	 */
+	public void setIndentationRight(float f) {
+		indentationRight = f;
+	}
+
+	/**
+	 * Getter for property originalType.
+	 * 
+	 * @return Value of property originalType.
+	 *  
+	 */
+	public int getOriginalType() {
+		return this.originalType;
+	}
+
+	/**
+	 * Setter for property originalType.
+	 * 
+	 * @param originalType
+	 *            New value of property originalType.
+	 *  
+	 */
+	public void setOriginalType(int originalType) {
+		this.originalType = originalType;
+	}
+
+	/**
+	 * Getter for property originalData.
+	 * 
+	 * @return Value of property originalData.
+	 *  
+	 */
+	public byte[] getOriginalData() {
+		return this.originalData;
+	}
+
+	/**
+	 * Setter for property originalData.
+	 * 
+	 * @param originalData
+	 *            New value of property originalData.
+	 *  
+	 */
+	public void setOriginalData(byte[] originalData) {
+		this.originalData = originalData;
+	}
+
+	/**
+	 * Sets the url of the image
+	 * 
+	 * @param url
+	 *            the url of the image
+	 */
+	public void setUrl(URL url) {
+		this.url = url;
+	}
+
+	/**
+	 * Sets the spacing before this image.
+	 * 
+	 * @param spacing
+	 *            the new spacing
+	 */
+
+	public void setSpacingBefore(float spacing) {
+		this.spacingBefore = spacing;
+	}
+
+	/**
+	 * Sets the spacing after this image.
+	 * 
+	 * @param spacing
+	 *            the new spacing
+	 */
+
+	public void setSpacingAfter(float spacing) {
+		this.spacingAfter = spacing;
+	}
+
+	/**
+	 * Gets the spacing before this image.
+	 * 
+	 * @return the spacing
+	 */
+
+	public float spacingBefore() {
+		return spacingBefore;
+	}
+
+	/**
+	 * Gets the spacing before this image.
+	 * 
+	 * @return the spacing
+	 */
+
+	public float spacingAfter() {
+		return spacingAfter;
+	}
+
+	/**
+	 * Getter for property widthPercentage.
+	 * 
+	 * @return Value of property widthPercentage.
+	 */
+	public float getWidthPercentage() {
+		return this.widthPercentage;
+	}
+
+	/**
+	 * Setter for property widthPercentage.
+	 * 
+	 * @param widthPercentage
+	 *            New value of property widthPercentage.
+	 */
+	public void setWidthPercentage(float widthPercentage) {
+		this.widthPercentage = widthPercentage;
+	}
+
+	/**
+	 * Gets the layer this image belongs to.
+	 * 
+	 * @return the layer this image belongs to or <code>null</code> for no
+	 *         layer defined
+	 */
+	public PdfOCG getLayer() {
+		return layer;
+	}
+
+	/**
+	 * Sets the layer this image belongs to.
+	 * 
+	 * @param layer
+	 *            the layer this image belongs to
+	 */
+	public void setLayer(PdfOCG layer) {
+		this.layer = layer;
+	}
+
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/ImgCCITT.java b/LibrarySource/com/lowagie/text/ImgCCITT.java
new file mode 100644
index 0000000..9ef99f0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ImgCCITT.java
@@ -0,0 +1,146 @@
+/*
+ * $Id: ImgCCITT.java,v 1.14 2002/08/23 08:59:32 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.URL;
+
+/**
+ * CCITT Image data that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ *
+ * @author  Paulo Soares
+ */
+
+public class ImgCCITT extends Image implements Element {
+    /** A table to do fast bit reversal.
+     */    
+    static final byte bitReversal[] = {
+        (byte)0x00, (byte)0x80, (byte)0x40, (byte)0xc0, (byte)0x20, (byte)0xa0, (byte)0x60, (byte)0xe0,
+        (byte)0x10, (byte)0x90, (byte)0x50, (byte)0xd0, (byte)0x30, (byte)0xb0, (byte)0x70, (byte)0xf0,
+        (byte)0x08, (byte)0x88, (byte)0x48, (byte)0xc8, (byte)0x28, (byte)0xa8, (byte)0x68, (byte)0xe8,
+        (byte)0x18, (byte)0x98, (byte)0x58, (byte)0xd8, (byte)0x38, (byte)0xb8, (byte)0x78, (byte)0xf8,
+        (byte)0x04, (byte)0x84, (byte)0x44, (byte)0xc4, (byte)0x24, (byte)0xa4, (byte)0x64, (byte)0xe4,
+        (byte)0x14, (byte)0x94, (byte)0x54, (byte)0xd4, (byte)0x34, (byte)0xb4, (byte)0x74, (byte)0xf4,
+        (byte)0x0c, (byte)0x8c, (byte)0x4c, (byte)0xcc, (byte)0x2c, (byte)0xac, (byte)0x6c, (byte)0xec,
+        (byte)0x1c, (byte)0x9c, (byte)0x5c, (byte)0xdc, (byte)0x3c, (byte)0xbc, (byte)0x7c, (byte)0xfc,
+        (byte)0x02, (byte)0x82, (byte)0x42, (byte)0xc2, (byte)0x22, (byte)0xa2, (byte)0x62, (byte)0xe2,
+        (byte)0x12, (byte)0x92, (byte)0x52, (byte)0xd2, (byte)0x32, (byte)0xb2, (byte)0x72, (byte)0xf2,
+        (byte)0x0a, (byte)0x8a, (byte)0x4a, (byte)0xca, (byte)0x2a, (byte)0xaa, (byte)0x6a, (byte)0xea,
+        (byte)0x1a, (byte)0x9a, (byte)0x5a, (byte)0xda, (byte)0x3a, (byte)0xba, (byte)0x7a, (byte)0xfa,
+        (byte)0x06, (byte)0x86, (byte)0x46, (byte)0xc6, (byte)0x26, (byte)0xa6, (byte)0x66, (byte)0xe6,
+        (byte)0x16, (byte)0x96, (byte)0x56, (byte)0xd6, (byte)0x36, (byte)0xb6, (byte)0x76, (byte)0xf6,
+        (byte)0x0e, (byte)0x8e, (byte)0x4e, (byte)0xce, (byte)0x2e, (byte)0xae, (byte)0x6e, (byte)0xee,
+        (byte)0x1e, (byte)0x9e, (byte)0x5e, (byte)0xde, (byte)0x3e, (byte)0xbe, (byte)0x7e, (byte)0xfe,
+        (byte)0x01, (byte)0x81, (byte)0x41, (byte)0xc1, (byte)0x21, (byte)0xa1, (byte)0x61, (byte)0xe1,
+        (byte)0x11, (byte)0x91, (byte)0x51, (byte)0xd1, (byte)0x31, (byte)0xb1, (byte)0x71, (byte)0xf1,
+        (byte)0x09, (byte)0x89, (byte)0x49, (byte)0xc9, (byte)0x29, (byte)0xa9, (byte)0x69, (byte)0xe9,
+        (byte)0x19, (byte)0x99, (byte)0x59, (byte)0xd9, (byte)0x39, (byte)0xb9, (byte)0x79, (byte)0xf9,
+        (byte)0x05, (byte)0x85, (byte)0x45, (byte)0xc5, (byte)0x25, (byte)0xa5, (byte)0x65, (byte)0xe5,
+        (byte)0x15, (byte)0x95, (byte)0x55, (byte)0xd5, (byte)0x35, (byte)0xb5, (byte)0x75, (byte)0xf5,
+        (byte)0x0d, (byte)0x8d, (byte)0x4d, (byte)0xcd, (byte)0x2d, (byte)0xad, (byte)0x6d, (byte)0xed,
+        (byte)0x1d, (byte)0x9d, (byte)0x5d, (byte)0xdd, (byte)0x3d, (byte)0xbd, (byte)0x7d, (byte)0xfd,
+        (byte)0x03, (byte)0x83, (byte)0x43, (byte)0xc3, (byte)0x23, (byte)0xa3, (byte)0x63, (byte)0xe3,
+        (byte)0x13, (byte)0x93, (byte)0x53, (byte)0xd3, (byte)0x33, (byte)0xb3, (byte)0x73, (byte)0xf3,
+        (byte)0x0b, (byte)0x8b, (byte)0x4b, (byte)0xcb, (byte)0x2b, (byte)0xab, (byte)0x6b, (byte)0xeb,
+        (byte)0x1b, (byte)0x9b, (byte)0x5b, (byte)0xdb, (byte)0x3b, (byte)0xbb, (byte)0x7b, (byte)0xfb,
+        (byte)0x07, (byte)0x87, (byte)0x47, (byte)0xc7, (byte)0x27, (byte)0xa7, (byte)0x67, (byte)0xe7,
+        (byte)0x17, (byte)0x97, (byte)0x57, (byte)0xd7, (byte)0x37, (byte)0xb7, (byte)0x77, (byte)0xf7,
+        (byte)0x0f, (byte)0x8f, (byte)0x4f, (byte)0xcf, (byte)0x2f, (byte)0xaf, (byte)0x6f, (byte)0xef,
+        (byte)0x1f, (byte)0x9f, (byte)0x5f, (byte)0xdf, (byte)0x3f, (byte)0xbf, (byte)0x7f, (byte)0xff
+    };
+        
+    /** Reverses the bits in the array.
+     * @param data data to reverse bits
+     */    
+    public static void ReverseBits(byte data[]) {
+        for (int k = 0; k < data.length; ++k)
+            data[k] = bitReversal[(int)data[k] & 0xff];
+    }
+
+    ImgCCITT(Image image) {
+        super(image);
+    }
+
+    /** Creates an Image with CCITT compression.
+     *
+     * @param width the exact width of the image
+     * @param height the exact height of the image
+     * @param reverseBits reverses the bits in <code>data</code>.
+     *  Bit 0 is swapped with bit 7 and so on
+     * @param typeCCITT the type of compression in <code>data</code>. It can be
+     * CCITTG4, CCITTG31D, CCITTG32D
+     * @param parameters parameters associated with this stream. Possible values are
+     * CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and CCITT_ENDOFBLOCK or a
+     * combination of them
+     * @param data the image data
+     * @throws BadElementException on error
+     */
+
+    public ImgCCITT(int width, int height, boolean reverseBits, int typeCCITT, int parameters, byte[] data) throws BadElementException{
+        super((URL)null);
+        if (typeCCITT != CCITTG4 && typeCCITT != CCITTG3_1D && typeCCITT != CCITTG3_2D)
+            throw new BadElementException("The CCITT compression type must be CCITTG4, CCITTG3_1D or CCITTG3_2D");
+        if (reverseBits)
+            ReverseBits(data);
+        type = IMGRAW;
+        scaledHeight = height;
+        setTop(scaledHeight);
+        scaledWidth = width;
+        setRight(scaledWidth);
+        colorspace = parameters;
+        bpc = typeCCITT;
+        rawData = data;
+        plainWidth = width();
+        plainHeight = height();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ImgPostscript.java b/LibrarySource/com/lowagie/text/ImgPostscript.java
new file mode 100644
index 0000000..a2f173c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ImgPostscript.java
@@ -0,0 +1,220 @@
+/*
+ * $Id: ImgWMF.java,v 1.45 2004/12/14 12:14:31 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.io.*;
+import java.net.*;
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.pdf.codec.postscript.*;
+import java.util.StringTokenizer;
+
+/**
+ * An <CODE>ImgPostscript</CODE> is the representation of an EPS
+ * that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ */
+
+public class ImgPostscript
+extends Image
+implements Element {
+    
+    // Constructors
+    
+    ImgPostscript(Image image) {
+        super(image);
+    }
+    
+    /**
+     * Constructs an <CODE>ImgPostscript</CODE>-object, using an <VAR>url</VAR>.
+     *
+     * @param url the <CODE>URL</CODE> where the image can be found
+     * @throws BadElementException on error
+     * @throws IOException on error
+     */
+    
+    public ImgPostscript(URL url) throws BadElementException, IOException {
+        super(url);
+        processParameters();
+    }
+    
+    /**
+     * Constructs an <CODE>ImgPostscript</CODE>-object, using a <VAR>filename</VAR>.
+     *
+     * @param filename a <CODE>String</CODE>-representation of the file that contains the image.
+     * @throws BadElementException on error
+     * @throws MalformedURLException on error
+     * @throws IOException on error
+     */
+    
+    public ImgPostscript(String filename) throws BadElementException,
+    MalformedURLException, IOException {
+        this(Image.toURL(filename));
+    }
+    
+    /**
+     * Constructs an <CODE>ImgPostscript</CODE>-object from memory.
+     *
+     * @param img the memory image
+     * @throws BadElementException on error
+     * @throws IOException on error
+     */
+    
+    public ImgPostscript(byte[] img) throws BadElementException, IOException {
+        super( (URL)null);
+        rawData = img;
+        originalData = img;
+        processParameters();
+    }
+    
+    /**
+     * This method checks if the image is a valid Postscript and processes some parameters.
+     * @throws BadElementException
+     * @throws IOException
+     */
+    
+    private void processParameters() throws BadElementException, IOException {
+        type = IMGTEMPLATE;
+        originalType = ORIGINAL_PS;
+        InputStream is = null;
+        try {
+            String errorID;
+            if (rawData == null) {
+                is = url.openStream();
+                errorID = url.toString();
+            }
+            else {
+                is = new java.io.ByteArrayInputStream(rawData);
+                errorID = "Byte array";
+            }
+            String boundingbox=null;
+            Reader r = new BufferedReader(new InputStreamReader(is));
+            //  StreamTokenizer st = new StreamTokenizer(r);
+            while (r.ready()) {
+                char c;
+                StringBuffer sb = new StringBuffer();
+                while ( (c = ( (char) r.read())) != '\n') {
+                    sb.append(c);
+                }
+                //System.out.println("<<" + sb.toString() + ">>");
+                if (sb.toString().startsWith("%%BoundingBox:")) {
+                    boundingbox = sb.toString();
+                    
+                }
+                if (sb.toString().startsWith("%%TemplateBox:")) {
+                    boundingbox = sb.toString();
+                }
+                if (sb.toString().startsWith("%%EndComments")) {
+                    break;
+                }
+                
+            }
+            if(boundingbox==null)return;
+            StringTokenizer st=new StringTokenizer(boundingbox,": \r\n");
+            st.nextElement();
+            String xx1=st.nextToken();
+            String yy1=st.nextToken();
+            String xx2=st.nextToken();
+            String yy2=st.nextToken();
+            
+            int left = Integer.parseInt(xx1);
+            int top = Integer.parseInt(yy1);
+            int right = Integer.parseInt(xx2);
+            int bottom = Integer.parseInt(yy2);
+            int inch = 1;
+            dpiX = 72;
+            dpiY = 72;
+            scaledHeight = (float) (bottom - top) / inch *1f;
+            scaledHeight=800;
+            setTop(scaledHeight);
+            scaledWidth = (float) (right - left) / inch * 1f;
+            scaledWidth=800;
+            setRight(scaledWidth);
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+            plainWidth = width();
+            plainHeight = height();
+        }
+    }
+    
+    /** Reads the Postscript into a template.
+     * @param template the template to read to
+     * @throws IOException on error
+     * @throws DocumentException on error
+     */
+    public void readPostscript(PdfTemplate template) throws IOException,
+    DocumentException {
+        setTemplateData(template);
+        template.setWidth(width());
+        template.setHeight(height());
+        InputStream is = null;
+        try {
+            if (rawData == null) {
+                is = url.openStream();
+            }
+            else {
+                is = new java.io.ByteArrayInputStream(rawData);
+            }
+            MetaDoPS meta = new MetaDoPS(is, template);
+            meta.readAll();
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/ImgRaw.java b/LibrarySource/com/lowagie/text/ImgRaw.java
new file mode 100644
index 0000000..5332b6f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ImgRaw.java
@@ -0,0 +1,97 @@
+/*
+ * $Id: ImgRaw.java,v 1.29 2002/08/23 08:59:32 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.URL;
+
+/**
+ * Raw Image data that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ *
+ * @author  Paulo Soares
+ */
+
+public class ImgRaw extends Image implements Element {
+
+    ImgRaw(Image image) {
+        super(image);
+    }
+
+/** Creats an Image in raw mode.
+ *
+ * @param width the exact width of the image
+ * @param height the exact height of the image
+ * @param components 1,3 or 4 for GrayScale, RGB and CMYK
+ * @param bpc bits per component. Must be 1,2,4 or 8
+ * @param data the image data
+ * @throws BadElementException on error
+ */
+    
+    public ImgRaw(int width, int height, int components, int bpc, byte[] data) throws BadElementException{
+        super((URL)null);
+        type = IMGRAW;
+        scaledHeight = height;
+        setTop(scaledHeight);
+        scaledWidth = width;
+        setRight(scaledWidth);
+        if (components != 1 && components != 3 && components != 4)
+            throw new BadElementException("Components must be 1, 3, or 4.");
+        if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8)
+            throw new BadElementException("Bits-per-component must be 1, 2, 4, or 8.");
+        colorspace = components;
+        this.bpc = bpc;
+        rawData = data;
+        plainWidth = width();
+        plainHeight = height();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ImgTemplate.java b/LibrarySource/com/lowagie/text/ImgTemplate.java
new file mode 100644
index 0000000..222b883
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ImgTemplate.java
@@ -0,0 +1,91 @@
+/*
+ * $Id: ImgTemplate.java,v 1.20 2002/08/23 08:59:32 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.URL;
+import com.lowagie.text.pdf.PdfTemplate;
+
+/**
+ * PdfTemplate that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ *
+ * @author  Paulo Soares
+ */
+
+public class ImgTemplate extends Image implements Element {
+    
+    ImgTemplate(Image image) {
+        super(image);
+    }
+    
+    /** Creats an Image from a PdfTemplate.
+     *
+     * @param template the PdfTemplate
+     * @throws BadElementException on error
+     */
+    public ImgTemplate(PdfTemplate template) throws BadElementException{
+        super((URL)null);
+        if (template == null)
+            throw new BadElementException("The template can not be null.");
+        if (template.getType() == PdfTemplate.TYPE_PATTERN)
+            throw new BadElementException("A pattern can not be used as a template to create an image.");
+        type = IMGTEMPLATE;
+        scaledHeight = template.getHeight();
+        setTop(scaledHeight);
+        scaledWidth = template.getWidth();
+        setRight(scaledWidth);
+        setTemplateData(template);
+        plainWidth = width();
+        plainHeight = height();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ImgWMF.java b/LibrarySource/com/lowagie/text/ImgWMF.java
new file mode 100644
index 0000000..438776b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ImgWMF.java
@@ -0,0 +1,190 @@
+/*
+ * $Id: ImgWMF.java,v 1.45 2004/12/14 12:14:31 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import com.lowagie.text.pdf.codec.wmf.InputMeta;
+import com.lowagie.text.pdf.codec.wmf.MetaDo;
+import com.lowagie.text.pdf.*;
+
+/**
+ * An <CODE>ImgWMF</CODE> is the representation of a windows metafile
+ * that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ */
+
+public class ImgWMF extends Image implements Element {
+    
+    // Constructors
+    
+    ImgWMF(Image image) {
+        super(image);
+    }
+    
+    /**
+     * Constructs an <CODE>ImgWMF</CODE>-object, using an <VAR>url</VAR>.
+     *
+     * @param url the <CODE>URL</CODE> where the image can be found
+     * @throws BadElementException on error
+     * @throws IOException on error
+     */
+    
+    public ImgWMF(URL url) throws BadElementException, IOException {
+        super(url);
+        processParameters();
+    }
+    
+    /**
+     * Constructs an <CODE>ImgWMF</CODE>-object, using a <VAR>filename</VAR>.
+     *
+     * @param filename a <CODE>String</CODE>-representation of the file that contains the image.
+     * @throws BadElementException on error
+     * @throws MalformedURLException on error
+     * @throws IOException on error
+     */
+    
+    public ImgWMF(String filename) throws BadElementException, MalformedURLException, IOException {
+        this(Image.toURL(filename));
+    }
+    
+    /**
+     * Constructs an <CODE>ImgWMF</CODE>-object from memory.
+     *
+     * @param img the memory image
+     * @throws BadElementException on error
+     * @throws IOException on error
+     */
+    
+    public ImgWMF(byte[] img) throws BadElementException, IOException {
+        super((URL)null);
+        rawData = img;
+        originalData = img;
+        processParameters();
+    }
+    
+/**
+ * This method checks if the image is a valid WMF and processes some parameters.
+ * @throws BadElementException
+ * @throws IOException
+ */
+    
+    private void processParameters() throws BadElementException, IOException {
+        type = IMGTEMPLATE;
+        originalType = ORIGINAL_WMF;
+        InputStream is = null;
+        try {
+            String errorID;
+            if (rawData == null){
+                is = url.openStream();
+                errorID = url.toString();
+            }
+            else{
+                is = new java.io.ByteArrayInputStream(rawData);
+                errorID = "Byte array";
+            }
+            InputMeta in = new InputMeta(is);
+            if (in.readInt() != 0x9AC6CDD7)	{
+                throw new BadElementException(errorID + " is not a valid placeable windows metafile.");
+            }
+            in.readWord();
+            int left = in.readShort();
+            int top = in.readShort();
+            int right = in.readShort();
+            int bottom = in.readShort();
+            int inch = in.readWord();
+            dpiX = 72;
+            dpiY = 72;
+            scaledHeight = (float)(bottom - top) / inch * 72f;
+            setTop(scaledHeight);
+            scaledWidth = (float)(right - left) / inch * 72f;
+            setRight(scaledWidth);
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+            plainWidth = width();
+            plainHeight = height();
+        }
+    }
+    
+    /** Reads the WMF into a template.
+     * @param template the template to read to
+     * @throws IOException on error
+     * @throws DocumentException on error
+     */    
+    public void readWMF(PdfTemplate template) throws IOException, DocumentException {
+        setTemplateData(template);
+        template.setWidth(width());
+        template.setHeight(height());
+        InputStream is = null;
+        try {
+            if (rawData == null){
+                is = url.openStream();
+            }
+            else{
+                is = new java.io.ByteArrayInputStream(rawData);
+            }
+            MetaDo meta = new MetaDo(is, template);
+            meta.readAll();
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/Jpeg.java b/LibrarySource/com/lowagie/text/Jpeg.java
new file mode 100644
index 0000000..f5485c8
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Jpeg.java
@@ -0,0 +1,350 @@
+/*
+ * $Id: Jpeg.java,v 1.59 2004/12/14 12:33:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * An <CODE>Jpeg</CODE> is the representation of a graphic element (JPEG)
+ * that has to be inserted into the document
+ *
+ * @see		Element
+ * @see		Image
+ */
+
+public class Jpeg extends Image implements Element {
+    
+    // public static final membervariables
+    
+    /** This is a type of marker. */
+    public static final int NOT_A_MARKER = -1;
+    
+    /** This is a type of marker. */
+    public static final int VALID_MARKER = 0;
+    
+    /** Acceptable Jpeg markers. */
+    public static final int[] VALID_MARKERS = {0xC0, 0xC1, 0xC2};
+    
+    /** This is a type of marker. */
+    public static final int UNSUPPORTED_MARKER = 1;
+    
+    /** Unsupported Jpeg markers. */
+    public static final int[] UNSUPPORTED_MARKERS = {0xC3, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF};
+    
+    /** This is a type of marker. */
+    public static final int NOPARAM_MARKER = 2;
+    
+    /** Jpeg markers without additional parameters. */
+    public static final int[] NOPARAM_MARKERS = {0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0x01};
+    
+    /** Marker value */
+    public static final int M_APP0 = 0xE0;
+    /** Marker value */
+    public static final int M_APPE = 0xEE;
+    
+    /** sequence that is used in all Jpeg files */
+    public static final byte JFIF_ID[] = {0x4A, 0x46, 0x49, 0x46, 0x00};
+    // Constructors
+    
+    Jpeg(Image image) {
+        super(image);
+    }
+
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object, using an <VAR>url</VAR>.
+     *
+     * @param		url			the <CODE>URL</CODE> where the image can be found
+     * @throws BadElementException
+     * @throws IOException
+     */
+    
+    public Jpeg(URL url) throws BadElementException, IOException {
+        super(url);
+        processParameters();
+    }
+    
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object, using an <VAR>url</VAR>.
+     *
+     * @param		url			the <CODE>URL</CODE> where the image can be found.
+     * @param width new width of the Jpeg
+     * @param height new height of the Jpeg
+     * @throws BadElementException
+     * @throws IOException
+     * @deprecated	use Image.getInstance(...) to create an Image
+     */
+    
+    public Jpeg(URL url, float width, float height) throws BadElementException, IOException {
+        this(url);
+        scaledWidth = width;
+        scaledHeight = height;
+    }
+    
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object, using a <VAR>filename</VAR>.
+     *
+     * @param		filename	a <CODE>String</CODE>-representation of the file that contains the Image.
+     * @throws BadElementException
+     * @throws MalformedURLException
+     * @throws IOException
+     * @deprecated	use Image.getInstance(...) to create an Image
+     */
+    
+    public Jpeg(String filename) throws BadElementException, MalformedURLException, IOException {
+        this(Image.toURL(filename));
+    }
+    
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object, using a <VAR>filename</VAR>.
+     *
+     * @param		filename	a <CODE>String</CODE>-representation of the file that contains the Image.
+     * @param width new width of the Jpeg
+     * @param height new height of the Jpeg
+     * @throws BadElementException
+     * @throws MalformedURLException
+     * @throws IOException
+     * @deprecated	use Image.getInstance(...) to create an Image
+     */
+    
+    public Jpeg(String filename, float width, float height) throws BadElementException, MalformedURLException, IOException {
+        this(Image.toURL(filename), width, height);
+    }
+    
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object from memory.
+     *
+     * @param		img		the memory image
+     * @throws BadElementException
+     * @throws IOException
+     */
+    
+    public Jpeg(byte[] img) throws BadElementException, IOException {
+        super((URL)null);
+        rawData = img;
+        originalData = img;
+        processParameters();
+    }
+    
+    /**
+     * Constructs a <CODE>Jpeg</CODE>-object from memory.
+     *
+     * @param		img			the memory image.
+     * @param		width		the width you want the image to have
+     * @param		height		the height you want the image to have
+     * @throws BadElementException
+     * @throws IOException
+     */
+    
+    public Jpeg(byte[] img, float width, float height) throws BadElementException, IOException {
+        this(img);
+        scaledWidth = width;
+        scaledHeight = height;
+    }
+    
+    // private static methods
+    
+    /**
+     * Reads a short from the <CODE>InputStream</CODE>.
+     *
+     * @param	is		the <CODE>InputStream</CODE>
+     * @return	an int
+     * @throws IOException
+     */
+    
+    private static final int getShort(InputStream is) throws IOException {
+        return (is.read() << 8) + is.read();
+    }
+    
+    /**
+     * Returns a type of marker.
+     *
+     * @param	marker      an int
+     * @return	a type: <VAR>VALID_MARKER</CODE>, <VAR>UNSUPPORTED_MARKER</VAR> or <VAR>NOPARAM_MARKER</VAR>
+     */
+    
+    private static final int marker(int marker) {
+        for (int i = 0; i < VALID_MARKERS.length; i++) {
+            if (marker == VALID_MARKERS[i]) {
+                return VALID_MARKER;
+            }
+        }
+        for (int i = 0; i < NOPARAM_MARKERS.length; i++) {
+            if (marker == NOPARAM_MARKERS[i]) {
+                return NOPARAM_MARKER;
+            }
+        }
+        for (int i = 0; i < UNSUPPORTED_MARKERS.length; i++) {
+            if (marker == UNSUPPORTED_MARKERS[i]) {
+                return UNSUPPORTED_MARKER;
+            }
+        }
+        return NOT_A_MARKER;
+    }
+    
+    // private methods
+    
+    /**
+     * This method checks if the image is a valid JPEG and processes some parameters.
+     * @throws BadElementException
+     * @throws IOException
+     */
+    
+    private void processParameters() throws BadElementException, IOException {
+        type = JPEG;
+        originalType = ORIGINAL_JPEG;
+        InputStream is = null;
+        try {
+            String errorID;
+            if (rawData == null){
+                is = url.openStream();
+                errorID = url.toString();
+            }
+            else{
+                is = new java.io.ByteArrayInputStream(rawData);
+                errorID = "Byte array";
+            }
+            if (is.read() != 0xFF || is.read() != 0xD8)	{
+                throw new BadElementException(errorID + " is not a valid JPEG-file.");
+            }
+            boolean firstPass = true;
+            int len;
+            while (true) {
+                int v = is.read();
+                if (v < 0)
+                    throw new IOException("Premature EOF while reading JPG.");
+                if (v == 0xFF) {
+                    int marker = is.read();
+                    if (firstPass && marker == M_APP0) {
+                        firstPass = false;
+                        len = getShort(is);
+                        if (len < 16) {
+                            skip(is, len - 2);
+                            continue;
+                        }
+                        byte bcomp[] = new byte[JFIF_ID.length];
+                        int r = is.read(bcomp);
+                        if (r != bcomp.length)
+                            throw new BadElementException(errorID + " corrupted JFIF marker.");
+                        boolean found = true;
+                        for (int k = 0; k < bcomp.length; ++k) {
+                            if (bcomp[k] != JFIF_ID[k]) {
+                                found = false;
+                                break;
+                            }
+                        }
+                        if (!found) {
+                            skip(is, len - 2 - bcomp.length);
+                            continue;
+                        }
+                        skip(is, 2);
+                        int units = is.read();
+                        int dx = getShort(is);
+                        int dy = getShort(is);
+                        if (units == 1) {
+                            dpiX = dx;
+                            dpiY = dy;
+                        }
+                        else if (units == 2) {
+                            dpiX = (int)((float)dx * 2.54f + 0.5f);
+                            dpiY = (int)((float)dy * 2.54f + 0.5f);
+                        }
+                        skip(is, len - 2 - bcomp.length - 7);
+                        continue;
+                    }
+                    if (marker == M_APPE) {
+                        len = getShort(is);
+                        byte[] byteappe = new byte[len];
+                        for (int k = 0; k < len; ++k) {
+                            byteappe[k] = (byte)is.read();
+                        }
+                        if (byteappe.length > 12) {
+                            String appe = new String(byteappe, 0, 5, "ISO-8859-1");
+                            if (appe.equals("Adobe")) {
+                                invert = true;
+                            }
+                        }
+                    }
+                    firstPass = false;
+                    int markertype = marker(marker);
+                    if (markertype == VALID_MARKER) {
+                        skip(is, 2);
+                        if (is.read() != 0x08) {
+                            throw new BadElementException(errorID + " must have 8 bits per component.");
+                        }
+                        scaledHeight = getShort(is);
+                        setTop(scaledHeight);
+                        scaledWidth = getShort(is);
+                        setRight(scaledWidth);
+                        colorspace = is.read();
+                        bpc = 8;
+                        break;
+                    }
+                    else if (markertype == UNSUPPORTED_MARKER) {
+                        throw new BadElementException(errorID + ": unsupported JPEG marker: " + marker);
+                    }
+                    else if (markertype != NOPARAM_MARKER) {
+                        skip(is, getShort(is) - 2);
+                    }
+                }
+            }
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+            plainWidth = width();
+            plainHeight = height();
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/List.java b/LibrarySource/com/lowagie/text/List.java
new file mode 100644
index 0000000..e4cf8b2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/List.java
@@ -0,0 +1,549 @@
+/*
+ * $Id: List.java,v 1.74 2005/04/13 09:17:14 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A <CODE>List</CODE> contains several <CODE>ListItem</CODE>s.
+ * <P>
+ * <B>Example 1:</B>
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>List list = new List(true, 20);</STRONG>
+ * <STRONG>list.add(new ListItem("First line"));</STRONG>
+ * <STRONG>list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));</STRONG>
+ * <STRONG>list.add(new ListItem("Third line"));</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * The result of this code looks like this:
+ *	<OL>
+ *		<LI>
+ *			First line
+ *		</LI>
+ *		<LI>
+ *			The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
+ *		</LI>
+ *		<LI>
+ *			Third line
+ *		</LI>
+ *	</OL>
+ *
+ * <B>Example 2:</B>
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>List overview = new List(false, 10);</STRONG>
+ * <STRONG>overview.add(new ListItem("This is an item"));</STRONG>
+ * <STRONG>overview.add("This is another item");</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * The result of this code looks like this:
+ *	<UL>
+ *		<LI>
+ *			This is an item
+ *		</LI>
+ *		<LI>
+ *			This is another item
+ *		</LI>
+ *	</UL>
+ *
+ * @see		Element
+ * @see		ListItem
+ */
+
+public class List implements TextElementArray, MarkupAttributes {
+    
+    // membervariables
+    
+/** This is the <CODE>ArrayList</CODE> containing the different <CODE>ListItem</CODE>s. */
+    protected ArrayList list = new ArrayList();
+    
+/** This variable indicates if the list has to be numbered. */
+    protected boolean numbered;
+    protected boolean lettered;
+    
+/** This variable indicates the first number of a numbered list. */
+    protected int first = 1;
+    protected char firstCh = 'A';
+    protected char lastCh  = 'Z';
+    
+/** This is the listsymbol of a list that is not numbered. */
+    protected Chunk symbol = new Chunk("-");
+    
+/** The indentation of this list on the left side. */
+    protected float indentationLeft = 0;
+    
+/** The indentation of this list on the right side. */
+    protected float indentationRight = 0;
+    
+/** The indentation of the listitems. */
+    protected float symbolIndent;
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>List</CODE>.
+ * <P>
+ * Remark: the parameter <VAR>symbolIndent</VAR> is important for instance when
+ * generating PDF-documents; it indicates the indentation of the listsymbol.
+ * It is not important for HTML-documents.
+ *
+ * @param	numbered		a boolean
+ * @param	symbolIndent	the indentation that has to be used for the listsymbol
+ */
+    
+    public List(boolean numbered, float symbolIndent) {
+        this.numbered = numbered;
+        this.lettered = false;
+        this.symbolIndent = symbolIndent;
+    }
+    
+    /**
+     * Creates a list
+     * @param numbered has the list to be numbered?
+     * @param lettered has the list to be 'numbered' with letters
+     * @param symbolIndent the indentation of the symbol
+     */
+    public List(boolean numbered, boolean lettered, float symbolIndent ) {
+        this.numbered = numbered;
+        this.lettered = lettered;
+        this.symbolIndent = symbolIndent;
+    }
+    
+        /**
+         * Returns a <CODE>List</CODE> that has been constructed taking in account
+         * the value of some <VAR>attributes</VAR>.
+         *
+         * @param	attributes		Some attributes
+         */
+    
+    public List(Properties attributes) {
+        String value= (String)attributes.remove(ElementTags.LISTSYMBOL);
+        if (value == null) {
+            value = "-";
+        }
+        symbol = new Chunk(value, FontFactory.getFont(attributes));
+        
+        this.numbered = false;
+        if ((value = (String)attributes.remove(ElementTags.NUMBERED)) != null) {
+            this.numbered = new Boolean(value).booleanValue();
+            if ( this.lettered && this.numbered )
+                this.lettered = false;
+        }
+        if ((value = (String)attributes.remove(ElementTags.LETTERED)) != null) {
+            this.lettered = new Boolean(value).booleanValue();
+            if ( this.numbered && this.lettered )
+                this.numbered = false;
+        }
+        this.symbolIndent = 0;
+        if ((value = (String)attributes.remove(ElementTags.SYMBOLINDENT)) != null) {
+            this.symbolIndent = Integer.parseInt(value);
+        }
+        
+        if ((value = (String)attributes.remove(ElementTags.FIRST)) != null) {
+            char khar = value.charAt(0);
+            if ( Character.isLetter( khar ) ) {
+                setFirst( khar );
+            }
+            else {
+                setFirst(Integer.parseInt(value));
+            }
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+            setIndentationLeft(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+            setIndentationRight(Float.valueOf(value + "f").floatValue());
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            for (Iterator i = list.iterator(); i.hasNext(); ) {
+                listener.add((Element) i.next());
+            }
+            return true;
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.LIST;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        ArrayList tmp = new ArrayList();
+        for (Iterator i = list.iterator(); i.hasNext(); ) {
+            tmp.addAll(((Element) i.next()).getChunks());
+        }
+        return tmp;
+    }
+    
+    // methods to set the membervariables
+    
+/**
+ * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
+ *
+ * @param	o		the object to add.
+ * @return true if adding the object succeeded
+ */
+    
+    public boolean add(Object o) {
+        if (o instanceof ListItem) {
+            ListItem item = (ListItem) o;
+            if (numbered || lettered) {
+                Chunk chunk;
+                if ( numbered )
+                    chunk = new Chunk(String.valueOf(first + list.size()), symbol.font());
+                else
+                    chunk = new Chunk(nextLetter(), symbol.font());
+                chunk.append(".");
+                item.setListSymbol(chunk);
+            }
+            else {
+                item.setListSymbol(symbol);
+            }
+            item.setIndentationLeft(symbolIndent);
+            item.setIndentationRight(0);
+            list.add(item);
+        }
+        else if (o instanceof List) {
+            List nested = (List) o;
+            nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+            first--;
+            return list.add(nested);
+        }
+        else if (o instanceof String) {
+            return this.add(new ListItem((String) o));
+        }
+        return false;
+    }
+    
+/**
+ * Sets the indentation of this paragraph on the left side.
+ *
+ * @param	indentation		the new indentation
+ */
+    
+    public void setIndentationLeft(float indentation) {
+        this.indentationLeft = indentation;
+    }
+    
+/**
+ * Sets the indentation of this paragraph on the right side.
+ *
+ * @param	indentation		the new indentation
+ */
+    
+    public void setIndentationRight(float indentation) {
+        this.indentationRight = indentation;
+    }
+    
+/**
+ * Sets the number that has to come first in the list.
+ *
+ * @param	first		a number
+ */
+    
+    public void setFirst(int first) {
+        this.first = first;
+    }
+    
+    
+/**
+ * Sets the Letter that has to come first in the list.
+ *
+ * @param	first		a letter
+ */
+    
+    public void setFirst(char first) {
+        this.firstCh = first;
+        if ( Character.isLowerCase( this.firstCh )) {
+            this.lastCh = 'z';
+        }
+        else {
+            this.lastCh = 'Z';
+        }
+    }
+    
+/**
+ * Sets the listsymbol.
+ *
+ * @param	symbol		a <CODE>Chunk</CODE>
+ */
+    
+    public void setListSymbol(Chunk symbol) {
+        this.symbol = symbol;
+    }
+    
+/**
+ * Sets the listsymbol.
+ * <P>
+ * This is a shortcut for <CODE>setListSymbol(Chunk symbol)</CODE>.
+ *
+ * @param	symbol		a <CODE>String</CODE>
+ */
+    
+    public void setListSymbol(String symbol) {
+        this.symbol = new Chunk(symbol);
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Gets all the items in the list.
+ *
+ * @return	an <CODE>ArrayList</CODE> containing <CODE>ListItem</CODE>s.
+ */
+    
+    public ArrayList getItems() {
+        return list;
+    }
+    
+/**
+ * Gets the size of the list.
+ *
+ * @return	a <CODE>size</CODE>
+ */
+    
+    public int size() {
+        return list.size();
+    }
+    
+/**
+ * Gets the leading of the first listitem.
+ *
+ * @return	a <CODE>leading</CODE>
+ */
+    
+    public float leading() {
+        if (list.size() < 1) {
+            return -1;
+        }
+        ListItem item = (ListItem) list.get(0);
+        return item.leading();
+    }
+    
+/**
+ * Checks if the list is numbered.
+ *
+ * @return	<CODE>true</CODE> if the list is numbered, <CODE>false</CODE> otherwise.
+ */
+    
+    public boolean isNumbered() {
+        return numbered;
+    }
+    
+/**
+ * Gets the symbol indentation.
+ * @return the symbol indentation
+ */
+    
+    public float symbolIndent() {
+        return symbolIndent;
+    }
+    
+/**
+ * Gets the Chunk containing the symbol.
+ * @return a Chunk with a symbol
+ */
+    
+    public Chunk symbol() {
+        return symbol;
+    }
+    
+/**
+ * Gets the first number        .
+ * @return a number
+ */
+    
+    public int first() {
+        return first;
+    }
+    
+/**
+ * Gets the indentation of this paragraph on the left side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationLeft() {
+        return indentationLeft;
+    }
+    
+/**
+ * Gets the indentation of this paragraph on the right side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationRight() {
+        return indentationRight;
+    }
+    
+/**
+ * Checks if a given tag corresponds with the listsymbol tag of this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isSymbol(String tag) {
+        return ElementTags.LISTSYMBOL.equals(tag);
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.LIST.equals(tag);
+    }
+
+/**
+ * Retrieves the next letter in the sequence
+ *
+ * @return  String contains the next character (A-Z or a-z)
+ */
+    private String nextLetter() {
+        int num_in_list = listItemsInList(); //list.size();
+        int max_ival = (lastCh + 0);
+        int ival = (firstCh + num_in_list);
+        while ( ival > max_ival ) {
+            ival -= 26;
+        }
+        char[] new_char = new char[1];
+        new_char[0] = (char) ival;
+        String ret = new String( new_char );
+        return ret;
+    }
+    
+    /**
+     * Counts the number of ListItems in the list ommiting nested lists
+     *
+     * @return  Integer number of ListItems in the list
+     */
+    private int listItemsInList() {
+        int result = 0;
+        for (Iterator i = list.iterator(); i.hasNext(); ) {
+            if (!(i.next() instanceof List)) result++;
+        }
+        return result;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return Chunk.getKeySet(markupAttributes);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ListItem.java b/LibrarySource/com/lowagie/text/ListItem.java
new file mode 100644
index 0000000..474aeb9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ListItem.java
@@ -0,0 +1,292 @@
+/*
+ * $Id: ListItem.java,v 1.78 2005/05/03 13:03:48 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.Properties;
+
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A <CODE>ListItem</CODE> is a <CODE>Paragraph</CODE>
+ * that can be added to a <CODE>List</CODE>.
+ * <P>
+ * <B>Example 1:</B>
+ * <BLOCKQUOTE><PRE>
+ * List list = new List(true, 20);
+ * list.add(<STRONG>new ListItem("First line")</STRONG>);
+ * list.add(<STRONG>new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?")</STRONG>);
+ * list.add(<STRONG>new ListItem("Third line")</STRONG>);
+ * </PRE></BLOCKQUOTE>
+ *
+ * The result of this code looks like this:
+ *	<OL>
+ *		<LI>
+ *			First line
+ *		</LI>
+ *		<LI>
+ *			The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
+ *		</LI>
+ *		<LI>
+ *			Third line
+ *		</LI>
+ *	</OL>
+ *
+ * <B>Example 2:</B>
+ * <BLOCKQUOTE><PRE>
+ * List overview = new List(false, 10);
+ * overview.add(<STRONG>new ListItem("This is an item")</STRONG>);
+ * overview.add("This is another item");
+ * </PRE></BLOCKQUOTE>
+ *
+ * The result of this code looks like this:
+ *	<UL>
+ *		<LI>
+ *			This is an item
+ *		</LI>
+ *		<LI>
+ *			This is another item
+ *		</LI>
+ *	</UL>
+ *
+ * @see	Element
+ * @see List
+ * @see	Paragraph
+ */
+
+public class ListItem extends Paragraph implements TextElementArray, MarkupAttributes {
+    
+    // membervariables
+    
+/** this is the symbol that wil proceed the listitem. */
+    private Chunk symbol;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>ListItem</CODE>.
+ */
+    
+    public ListItem() {
+        super();
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain leading.
+ *
+ * @param	leading		the leading
+ */
+    
+    public ListItem(float leading) {
+        super(leading);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>Chunk</CODE>.
+ *
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public ListItem(Chunk chunk) {
+        super(chunk);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>String</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public ListItem(String string) {
+        super(string);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>String</CODE>
+ * and a certain <CODE>Font</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>String</CODE>
+ */
+    
+    public ListItem(String string, Font font) {
+        super(string, font);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>Chunk</CODE>
+ * and a certain leading.
+ *
+ * @param	leading		the leading
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public ListItem(float leading, Chunk chunk) {
+        super(leading, chunk);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>String</CODE>
+ * and a certain leading.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public ListItem(float leading, String string) {
+        super(leading, string);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain leading, <CODE>String</CODE>
+ * and <CODE>Font</CODE>.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public ListItem(float leading, String string, Font font) {
+        super(leading, string, font);
+    }
+    
+/**
+ * Constructs a <CODE>ListItem</CODE> with a certain <CODE>Phrase</CODE>.
+ *
+ * @param	phrase		a <CODE>Phrase</CODE>
+ */
+    
+    public ListItem(Phrase phrase) {
+        super(phrase);
+    }
+    
+        /**
+         * Returns a <CODE>ListItem</CODE> that has been constructed taking in account
+         * the value of some <VAR>attributes</VAR>.
+         *
+         * @param	attributes		Some attributes
+         */
+    
+    public ListItem(Properties attributes) {
+        super("", FontFactory.getFont(attributes));
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+            add(new Chunk(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+            setLeading(Float.valueOf(value + "f").floatValue());
+        }
+        else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+            setLeading(MarkupParser.parseLength(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+            setIndentationLeft(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+            setIndentationRight(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
+            setAlignment(value);
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.LISTITEM;
+    }
+    
+    // methods
+    
+/**
+ * Sets the listsymbol.
+ *
+ * @param	symbol	a <CODE>Chunk</CODE>
+ */
+    
+    public void setListSymbol(Chunk symbol) {
+        this.symbol = symbol;
+        if (this.symbol.font().isStandardFont()) {
+            this.symbol.setFont(font);
+        }
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns the listsymbol.
+ *
+ * @return	a <CODE>Chunk</CODE>
+ */
+    
+    public Chunk listSymbol() {
+        return symbol;
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.LISTITEM.equals(tag);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/MarkupAttributes.java b/LibrarySource/com/lowagie/text/MarkupAttributes.java
new file mode 100644
index 0000000..0c0ec4d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/MarkupAttributes.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002 by Matt Benson.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+
+import java.util.Set;
+import java.util.Properties;
+
+
+/**
+ * Defines the interface for an <CODE>Element</CODE> with markup attributes--
+ * that is, random String-to-String properties for representation in markup
+ * languages such as HTML and XML.
+ *
+ * @author <a href="mailto:orangeherbert at users.sourceforge.net">Matt Benson</a>
+ */
+public interface MarkupAttributes extends com.lowagie.text.Element {
+    
+/**
+ * Sets the specified attribute.
+ *
+ * @param name    <CODE>String</CODE> attribute name.
+ * @param value   <CODE>String</CODE> attribute value.
+ */
+    public void setMarkupAttribute(String name, String value);
+    
+/**
+ * Sets the markupAttributes.
+ *
+ * @param   markupAttributes    a <CODE>Properties</CODE>-object containing markupattributes 
+ */
+    public void setMarkupAttributes(Properties markupAttributes);
+    
+/**
+ * Returns the value of the specified attribute.
+ *
+ * @param name   <CODE>String</CODE> attribute name.
+ * @return <CODE>String</CODE>.
+ */
+    public String getMarkupAttribute(String name);
+    
+/**
+ * Returns a <CODE>Set</CODE> of <CODE>String</CODE> attribute names for the
+ * <CODE>MarkupAttributes</CODE> implementor.
+ *
+ * @return <CODE>Set</CODE>.
+ */
+    public Set getMarkupAttributeNames();
+    
+/**
+ * Return a <CODE>Properties</CODE>-object containing all the markupAttributes.
+ *
+ * @return <CODE>Properties</CODE>
+ */
+    public Properties getMarkupAttributes();
+    
+}
diff --git a/LibrarySource/com/lowagie/text/Meta.java b/LibrarySource/com/lowagie/text/Meta.java
new file mode 100644
index 0000000..5b1a1bd
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Meta.java
@@ -0,0 +1,263 @@
+/*
+ * $Id: Meta.java,v 1.65 2005/04/13 09:17:11 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * This is an <CODE>Element</CODE> that contains
+ * some meta information about the document.
+ * <P>
+ * An object of type <CODE>Meta</CODE> can not be constructed by the user.
+ * Userdefined meta information should be placed in a <CODE>Header</CODE>-object.
+ * <CODE>Meta</CODE> is reserved for: Subject, Keywords, Author, Title, Producer
+ * and Creationdate information.
+ *
+ * @see		Element
+ * @see		Header
+ */
+
+public class Meta implements Element, MarkupAttributes {
+    
+    // membervariables
+    
+/** This is the type of Meta-information this object contains. */
+    private int type;
+    
+/** This is the content of the Meta-information. */
+    private StringBuffer content;
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>Meta</CODE>.
+ *
+ * @param	type		the type of meta-information
+ * @param	content		the content
+ */
+    
+    Meta(int type, String content) {
+        this.type = type;
+        this.content = new StringBuffer(content);
+    }
+    
+/**
+ * Constructs a <CODE>Meta</CODE>.
+ *
+ * @param	tag		    the tagname of the meta-information
+ * @param	content		the content
+ */
+    
+    public Meta(String tag, String content) {
+        this.type = Meta.getType(tag);
+        this.content = new StringBuffer(content);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to a
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener		the <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return type;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+    // methods
+    
+/**
+ * appends some text to this <CODE>Meta</CODE>.
+ *
+ * @param	string      a <CODE>String</CODE>
+ * @return	a <CODE>StringBuffer</CODE>
+ */
+    
+    public StringBuffer append(String string) {
+        return content.append(string);
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns the content of the meta information.
+ *
+ * @return	a <CODE>String</CODE>
+ */
+    
+    public String content() {
+        return content.toString();
+    }
+    
+/**
+ * Returns the name of the meta information.
+ *
+ * @return	a <CODE>String</CODE>
+ */
+    
+    public String name() {
+        switch (type) {
+            case Element.SUBJECT:
+                return ElementTags.SUBJECT;
+            case Element.KEYWORDS:
+                return ElementTags.KEYWORDS;
+            case Element.AUTHOR:
+                return ElementTags.AUTHOR;
+            case Element.TITLE:
+                return ElementTags.TITLE;
+            case Element.PRODUCER:
+                return ElementTags.PRODUCER;
+            case Element.CREATIONDATE:
+                return ElementTags.CREATIONDATE;
+                default:
+                    return ElementTags.UNKNOWN;
+        }
+    }
+    
+/**
+ * Returns the name of the meta information.
+ * 
+ * @param tag iText tag for meta information
+ * @return	the Element value corresponding with the given tag
+ */
+    
+    public static int getType(String tag) {
+        if (ElementTags.SUBJECT.equals(tag)) {
+            return Element.SUBJECT;
+        }
+        if (ElementTags.KEYWORDS.equals(tag)) {
+            return Element.KEYWORDS;
+        }
+        if (ElementTags.AUTHOR.equals(tag)) {
+            return Element.AUTHOR;
+        }
+        if (ElementTags.TITLE.equals(tag)) {
+            return Element.TITLE;
+        }
+        if (ElementTags.PRODUCER.equals(tag)) {
+            return Element.PRODUCER;
+        }
+        if (ElementTags.CREATIONDATE.equals(tag)) {
+            return Element.CREATIONDATE;
+        }
+        return Element.HEADER;
+    }
+    
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return Chunk.getKeySet(markupAttributes);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/PageSize.java b/LibrarySource/com/lowagie/text/PageSize.java
new file mode 100644
index 0000000..4c7ca52
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/PageSize.java
@@ -0,0 +1,153 @@
+/*
+ * $Id: PageSize.java,v 1.26 2002/06/20 13:30:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * The <CODE>PageSize</CODE>-object contains a number of rectangles representing the most common papersizes.
+ *
+ * @see		Rectangle
+ */
+
+public class PageSize {
+    
+    // membervariables
+    
+/** This is the letter format */
+    public static final Rectangle LETTER = new Rectangle(612,792);
+    
+/** This is the note format */
+    public static final Rectangle NOTE = new Rectangle(540,720);
+    
+/** This is the legal format */
+    public static final Rectangle LEGAL = new Rectangle(612,1008);
+    
+/** This is the a0 format */
+    public static final Rectangle A0 = new Rectangle(2384,3370);
+    
+/** This is the a1 format */
+    public static final Rectangle A1 = new Rectangle(1684,2384);
+    
+/** This is the a2 format */
+    public static final Rectangle A2 = new Rectangle(1190,1684);
+    
+/** This is the a3 format */
+    public static final Rectangle A3 = new Rectangle(842,1190);
+    
+/** This is the a4 format */
+    public static final Rectangle A4 = new Rectangle(595,842);
+    
+/** This is the a5 format */
+    public static final Rectangle A5 = new Rectangle(421,595);
+    
+/** This is the a6 format */
+    public static final Rectangle A6 = new Rectangle(297,421);
+    
+/** This is the a7 format */
+    public static final Rectangle A7 = new Rectangle(210,297);
+    
+/** This is the a8 format */
+    public static final Rectangle A8 = new Rectangle(148,210);
+    
+/** This is the a9 format */
+    public static final Rectangle A9 = new Rectangle(105,148);
+    
+/** This is the a10 format */
+    public static final Rectangle A10 = new Rectangle(74,105);
+    
+/** This is the b0 format */
+    public static final Rectangle B0 = new Rectangle(2836,4008);
+    
+/** This is the b1 format */
+    public static final Rectangle B1 = new Rectangle(2004,2836);
+    
+/** This is the b2 format */
+    public static final Rectangle B2 = new Rectangle(1418,2004);
+    
+/** This is the b3 format */
+    public static final Rectangle B3 = new Rectangle(1002,1418);
+    
+/** This is the b4 format */
+    public static final Rectangle B4 = new Rectangle(709,1002);
+    
+/** This is the b5 format */
+    public static final Rectangle B5 = new Rectangle(501,709);
+    
+/** This is the archE format */
+    public static final Rectangle ARCH_E = new Rectangle(2592,3456);
+    
+/** This is the archD format */
+    public static final Rectangle ARCH_D = new Rectangle(1728,2592);
+    
+/** This is the archC format */
+    public static final Rectangle ARCH_C = new Rectangle(1296,1728);
+    
+/** This is the archB format */
+    public static final Rectangle ARCH_B = new Rectangle(864,1296);
+    
+/** This is the archA format */
+    public static final Rectangle ARCH_A = new Rectangle(648,864);
+    
+/** This is the flsa format */
+    public static final Rectangle FLSA = new Rectangle(612,936);
+    
+/** This is the flse format */
+    public static final Rectangle FLSE = new Rectangle(612,936);
+    
+/** This is the halfletter format */
+    public static final Rectangle HALFLETTER = new Rectangle(396,612);
+    
+/** This is the 11x17 format */
+    public static final Rectangle _11X17 = new Rectangle(792,1224);
+    
+/** This is the ledger format */
+    public static final Rectangle LEDGER = new Rectangle(1224,792);
+}
+
diff --git a/LibrarySource/com/lowagie/text/Paragraph.java b/LibrarySource/com/lowagie/text/Paragraph.java
new file mode 100644
index 0000000..19c0fe0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Paragraph.java
@@ -0,0 +1,517 @@
+/*
+ * $Id: Paragraph.java,v 1.83 2005/05/03 13:03:48 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.Properties;
+
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A <CODE>Paragraph</CODE> is a series of <CODE>Chunk</CODE>s and/or <CODE>Phrases</CODE>.
+ * <P>
+ * A <CODE>Paragraph</CODE> has the same qualities of a <CODE>Phrase</CODE>, but also
+ * some additional layout-parameters:
+ * <UL>
+ * <LI>the indentation
+ * <LI>the alignment of the text
+ * </UL>
+ *
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * <STRONG>Paragraph p = new Paragraph("This is a paragraph",
+ *               FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * @see		Element
+ * @see		Phrase
+ * @see		ListItem
+ */
+
+public class Paragraph extends Phrase implements TextElementArray, MarkupAttributes {
+    
+    // membervariables
+    
+/** The alignment of the text. */
+    protected int alignment = Element.ALIGN_UNDEFINED;
+    
+/** The indentation of this paragraph on the left side. */
+    protected float indentationLeft;
+    
+/** The indentation of this paragraph on the right side. */
+    protected float indentationRight;
+    
+/** The spacing before the paragraph. */
+    protected float spacingBefore;
+    
+/** The spacing after the paragraph. */
+    protected float spacingAfter;
+    
+/** Does the paragraph has to be kept together on 1 page. */
+    protected boolean keeptogether = false;
+    
+    /** The text leading that is multiplied by the biggest font size in the line. */
+    protected float multipliedLeading = 0;
+    
+    /**
+     * Holds value of property firstLineIndent.
+     */
+    private float firstLineIndent = 0;
+    
+    /**
+     * Holds value of property extraParagraphSpace.
+     */
+    private float extraParagraphSpace = 0;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE>.
+ */
+    
+    public Paragraph() {
+        super();
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain leading.
+ *
+ * @param	leading		the leading
+ */
+    
+    public Paragraph(float leading) {
+        super(leading);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Chunk</CODE>.
+ *
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Paragraph(Chunk chunk) {
+        super(chunk);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Chunk</CODE>
+ * and a certain leading.
+ *
+ * @param	leading		the leading
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Paragraph(float leading, Chunk chunk) {
+        super(leading, chunk);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Paragraph(String string) {
+        super(string);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>
+ * and a certain <CODE>Font</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Paragraph(String string, Font font) {
+        super(string, font);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>
+ * and a certain leading.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Paragraph(float leading, String string) {
+        super(leading, string);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain leading, <CODE>String</CODE>
+ * and <CODE>Font</CODE>.
+ *
+ * @param	leading		the leading
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Paragraph(float leading, String string, Font font) {
+        super(leading, string, font);
+    }
+    
+/**
+ * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Phrase</CODE>.
+ *
+ * @param	phrase		a <CODE>Phrase</CODE>
+ */
+    
+    public Paragraph(Phrase phrase) {
+        super(phrase.leading, "", phrase.font());
+        super.add(phrase);
+    }
+    
+/**
+ * Returns a <CODE>Paragraph</CODE> that has been constructed taking in account
+ * the value of some <VAR>attributes</VAR>.
+ *
+ * @param	attributes		Some attributes
+ */
+    
+    public Paragraph(Properties attributes) {
+        this("", FontFactory.getFont(attributes));
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+            Chunk chunk = new Chunk(value);
+            if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+                chunk.setGenericTag(value);
+            }
+            add(chunk);
+        }
+        if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
+            setAlignment(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+            setLeading(Float.valueOf(value + "f").floatValue());
+        }
+        else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+            setLeading(MarkupParser.parseLength(value));
+        }
+        else {
+            setLeading(16);
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+            setIndentationLeft(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+            setIndentationRight(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.KEEPTOGETHER)) != null) {
+            keeptogether = new Boolean(value).booleanValue();
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.PARAGRAPH;
+    }
+    
+    // methods
+    
+/**
+ * Adds an <CODE>Object</CODE> to the <CODE>Paragraph</CODE>.
+ *
+ * @param	o   object		the object to add.
+ * @return true is adding the object succeeded
+ */
+    
+    public boolean add(Object o) {
+        if (o instanceof List) {
+            List list = (List) o;
+            list.setIndentationLeft(list.indentationLeft() + indentationLeft);
+            list.setIndentationRight(indentationRight);
+            return super.add(list);
+        }
+        else if (o instanceof Image) {
+            super.addSpecial((Image) o);
+            return true;
+        }
+        else if (o instanceof Paragraph) {
+            super.add(o);
+            super.add(Chunk.NEWLINE);
+            return true;
+        }
+        return super.add(o);
+    }
+    
+    // setting the membervariables
+    
+/**
+ * Sets the alignment of this paragraph.
+ *
+ * @param	alignment		the new alignment
+ */
+    
+    public void setAlignment(int alignment) {
+        this.alignment = alignment;
+    }
+    
+/**
+ * Sets the alignment of this paragraph.
+ *
+ * @param	alignment		the new alignment as a <CODE>String</CODE>
+ */
+    
+    public void setAlignment(String alignment) {
+        if (ElementTags.ALIGN_CENTER.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_CENTER;
+            return;
+        }
+        if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_RIGHT;
+            return;
+        }
+        if (ElementTags.ALIGN_JUSTIFIED.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_JUSTIFIED;
+            return;
+        }
+        if (ElementTags.ALIGN_JUSTIFIED_ALL.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_JUSTIFIED_ALL;
+            return;
+        }
+        this.alignment = Element.ALIGN_LEFT;
+    }
+    
+/**
+ * Sets the indentation of this paragraph on the left side.
+ *
+ * @param	indentation		the new indentation
+ */
+    
+    public void setIndentationLeft(float indentation) {
+        this.indentationLeft = indentation;
+    }
+    
+/**
+ * Sets the indentation of this paragraph on the right side.
+ *
+ * @param	indentation		the new indentation
+ */
+    
+    public void setIndentationRight(float indentation) {
+        this.indentationRight = indentation;
+    }
+    
+/**
+ * Sets the spacing before this paragraph.
+ *
+ * @param	spacing		the new spacing
+ */
+    
+    public void setSpacingBefore(float spacing) {
+        this.spacingBefore = spacing;
+    }
+    
+/**
+ * Sets the spacing after this paragraph.
+ *
+ * @param	spacing		the new spacing
+ */
+    
+    public void setSpacingAfter(float spacing) {
+        this.spacingAfter = spacing;
+    }
+    
+/**
+ * Indicates that the paragraph has to be kept together on one page.
+ *
+ * @param   keeptogether    true of the paragraph may not be split over 2 pages
+ */
+    
+    public void setKeepTogether(boolean keeptogether) {
+        this.keeptogether = keeptogether;
+    }
+    
+/**
+ * Checks if this paragraph has to be kept together on one page.
+ *
+ * @return  true if the paragraph may not be split over 2 pages.
+ */
+    
+    public boolean getKeepTogether() {
+        return keeptogether;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Gets the alignment of this paragraph.
+ *
+ * @return	alignment
+ */
+    
+    public int alignment() {
+        return alignment;
+    }
+    
+/**
+ * Gets the indentation of this paragraph on the left side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationLeft() {
+        return indentationLeft;
+    }
+    
+/**
+ * Gets the indentation of this paragraph on the right side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationRight() {
+        return indentationRight;
+    }
+    
+/**
+ * Gets the spacing before this paragraph.
+ *
+ * @return	the spacing
+ */
+    
+    public float spacingBefore() {
+        return spacingBefore;
+    }
+    
+/**
+ * Gets the spacing before this paragraph.
+ *
+ * @return	the spacing
+ */
+    
+    public float spacingAfter() {
+        return spacingAfter;
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.PARAGRAPH.equals(tag);
+    }
+    
+    /**
+     * Sets the leading fixed and variable. The resultant leading will be
+     * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
+     * size of the bigest font in the line.
+     * @param fixedLeading the fixed leading
+     * @param multipliedLeading the variable leading
+     */
+    public void setLeading(float fixedLeading, float multipliedLeading) {
+        this.leading = fixedLeading;
+        this.multipliedLeading = multipliedLeading;
+    }
+    
+    /**
+     * @see com.lowagie.text.Phrase#setLeading(float)
+     */
+    public void setLeading(float fixedLeading) {
+        this.leading = fixedLeading;
+        this.multipliedLeading = 0;
+    }
+    
+    /**
+     * Gets the variable leading
+     * @return the leading
+     */
+    public float getMultipliedLeading() {
+        return multipliedLeading;
+    }
+    
+    /**
+     * Getter for property firstLineIndent.
+     * @return Value of property firstLineIndent.
+     */
+    public float getFirstLineIndent() {
+        return this.firstLineIndent;
+    }
+    
+    /**
+     * Setter for property firstLineIndent.
+     * @param firstLineIndent New value of property firstLineIndent.
+     */
+    public void setFirstLineIndent(float firstLineIndent) {
+        this.firstLineIndent = firstLineIndent;
+    }
+    
+    /**
+     * Getter for property extraParagraphSpace.
+     * @return Value of property extraParagraphSpace.
+     */
+    public float getExtraParagraphSpace() {
+        return this.extraParagraphSpace;
+    }
+    
+    /**
+     * Setter for property extraParagraphSpace.
+     * @param extraParagraphSpace New value of property extraParagraphSpace.
+     */
+    public void setExtraParagraphSpace(float extraParagraphSpace) {
+        this.extraParagraphSpace = extraParagraphSpace;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/Phrase.java b/LibrarySource/com/lowagie/text/Phrase.java
new file mode 100644
index 0000000..c00e3c2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Phrase.java
@@ -0,0 +1,595 @@
+/*
+ * $Id: Phrase.java,v 1.99 2005/04/13 09:17:10 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import com.lowagie.text.markup.MarkupTags;
+import com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A <CODE>Phrase</CODE> is a series of <CODE>Chunk</CODE>s.
+ * <P>
+ * A <CODE>Phrase</CODE> has a main <CODE>Font</CODE>, but some chunks
+ * within the phrase can have a <CODE>Font</CODE> that differs from the
+ * main <CODE>Font</CODE>. All the <CODE>Chunk</CODE>s in a <CODE>Phrase</CODE>
+ * have the same <CODE>leading</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * // When no parameters are passed, the default leading = 16
+ * <STRONG>Phrase phrase0 = new Phrase();</STRONG>
+ * <STRONG>Phrase phrase1 = new Phrase("this is a phrase");</STRONG>
+ * // In this example the leading is passed as a parameter
+ * <STRONG>Phrase phrase2 = new Phrase(16, "this is a phrase with leading 16");</STRONG>
+ * // When a Font is passed (explicitely or embedded in a chunk), the default leading = 1.5 * size of the font
+ * <STRONG>Phrase phrase3 = new Phrase("this is a phrase with a red, normal font Courier, size 12", FontFactory.getFont(FontFactory.COURIER, 12, Font.NORMAL, new Color(255, 0, 0)));</STRONG>
+ * <STRONG>Phrase phrase4 = new Phrase(new Chunk("this is a phrase"));</STRONG>
+ * <STRONG>Phrase phrase5 = new Phrase(18, new Chunk("this is a phrase", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));</STRONG>
+ * </PRE></BLOCKQUOTE>
+ *
+ * @see		Element
+ * @see		Chunk
+ * @see		Paragraph
+ * @see		Anchor
+ */
+
+public class Phrase extends ArrayList implements TextElementArray, MarkupAttributes {
+    
+    // membervariables
+    
+/** This is the leading of this phrase. */
+    protected float leading = Float.NaN;
+    
+/** This is the font of this phrase. */
+    protected Font font = new Font();
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes;
+    
+    // constructors
+    
+/**
+ * Constructs a Phrase that can be used in the static getInstance() method.
+ * @param	dummy	a dummy parameter
+ */
+    private Phrase(boolean dummy) {
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> without specifying a leading.
+ */
+    
+    public Phrase() {
+        this(16);
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain leading.
+ *
+ * @param	leading		the leading
+ */
+    
+    public Phrase(float leading) {
+        this.leading = leading;
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain <CODE>Chunk</CODE>.
+ *
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Phrase(Chunk chunk) {
+        super.add(chunk);
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain <CODE>Chunk</CODE>
+ * and a certain leading.
+ *
+ * @param	leading	the leading
+ * @param	chunk		a <CODE>Chunk</CODE>
+ */
+    
+    public Phrase(float leading, Chunk chunk) {
+        this(leading);
+        super.add(chunk);
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain <CODE>String</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Phrase(String string) {
+        this(Float.NaN, string, new Font());
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain <CODE>String</CODE> and a certain <CODE>Font</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Phrase(String string, Font font) {
+        this(Float.NaN, string, font);
+        this.font = font;
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain leading and a certain <CODE>String</CODE>.
+ *
+ * @param	leading	the leading
+ * @param	string		a <CODE>String</CODE>
+ */
+    
+    public Phrase(float leading, String string) {
+        this(leading, string, new Font());
+    }
+    
+/**
+ * Constructs a <CODE>Phrase</CODE> with a certain leading, a certain <CODE>String</CODE>
+ * and a certain <CODE>Font</CODE>.
+ *
+ * @param	leading	the leading
+ * @param	string		a <CODE>String</CODE>
+ * @param	font		a <CODE>Font</CODE>
+ */
+    
+    public Phrase(float leading, String string, Font font) {
+        this(leading);
+        this.font = font;
+    	/* bugfix by August Detlefsen */
+        if (string != null && string.length() != 0) {
+            super.add(new Chunk(string, font));
+        }
+    }
+    
+    /**
+     * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+     * @param string
+     * @return a newly constructed Phrase
+     */
+    public static final Phrase getInstance(String string) {
+    	return getInstance(16, string, new Font());
+    }
+    
+    /**
+     * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+     * @param leading
+     * @param string
+     * @return a newly constructed Phrase
+     */
+    public static final Phrase getInstance(int leading, String string) {
+    	return getInstance(leading, string, new Font());
+    }
+    
+    /**
+     * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+     * @param leading
+     * @param string
+     * @param font
+     * @return a newly constructed Phrase
+     */
+    public static final Phrase getInstance(int leading, String string, Font font) {
+    	Phrase p = new Phrase(true);
+    	p.setLeading(leading);
+    	p.font = font;
+    	if (font.family() != Font.SYMBOL && font.family() != Font.ZAPFDINGBATS && font.getBaseFont() == null) {
+            int index;
+            while((index = SpecialSymbol.index(string)) > -1) {
+                if (index > 0) {
+                    String firstPart = string.substring(0, index);
+                    /* bugfix [ #461272 ] CODE CHANGE REQUIRED IN Phrase.java
+                       by Arekh Nambiar */
+                    ((ArrayList)p).add(new Chunk(firstPart, font));
+                    string = string.substring(index);
+                }
+                Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+                StringBuffer buf = new StringBuffer();
+                buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
+                string = string.substring(1);
+                while (SpecialSymbol.index(string) == 0) {
+                    buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
+                    string = string.substring(1);
+                }
+                ((ArrayList)p).add(new Chunk(buf.toString(), symbol));
+            }
+        }
+    	/* bugfix by August Detlefsen */
+        if (string != null && string.length() != 0) {
+        	((ArrayList)p).add(new Chunk(string, font));
+        }
+    	return p;
+    }    
+    
+/**
+ * Returns a <CODE>Phrase</CODE> that has been constructed taking in account
+ * the value of some <VAR>attributes</VAR>.
+ *
+ * @param	attributes		Some attributes
+ */
+    
+    public Phrase(Properties attributes) {
+        this("", FontFactory.getFont(attributes));
+        clear();
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+            setLeading(Float.valueOf(value + "f").floatValue());
+        }
+        else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+            setLeading(MarkupParser.parseLength(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+            Chunk chunk = new Chunk(value);
+            if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+                chunk.setGenericTag(value);
+            }
+            add(chunk);
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            for (Iterator i = iterator(); i.hasNext(); ) {
+                listener.add((Element) i.next());
+            }
+            return true;
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.PHRASE;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        ArrayList tmp = new ArrayList();
+        for (Iterator i = iterator(); i.hasNext(); ) {
+            tmp.addAll(((Element) i.next()).getChunks());
+        }
+        return tmp;
+    }
+    
+    // overriding some of the ArrayList-methods
+    
+/**
+ * Adds a <CODE>Chunk</CODE>, an <CODE>Anchor</CODE> or another <CODE>Phrase</CODE>
+ * to this <CODE>Phrase</CODE>.
+ *
+ * @param	index	index at which the specified element is to be inserted
+ * @param	o   	an object of type <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or <CODE>Phrase</CODE>
+ * @throws	ClassCastException	when you try to add something that isn't a <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or <CODE>Phrase</CODE>
+ */
+    
+    public void add(int index, Object o) {
+        try {
+            Element element = (Element) o;
+            if (element.type() == Element.CHUNK) {
+                Chunk chunk = (Chunk) element;
+                if (!font.isStandardFont()) {
+                    chunk.setFont(font.difference(chunk.font()));
+                }
+                super.add(index, chunk);
+            }
+            else if (element.type() == Element.PHRASE ||
+            element.type() == Element.ANCHOR ||
+            element.type() == Element.ANNOTATION ||
+            element.type() == Element.TABLE || // line added by David Freels
+            element.type() == Element.GRAPHIC) {
+                super.add(index, element);
+            }
+            else {
+                throw new ClassCastException(String.valueOf(element.type()));
+            }
+        }
+        catch(ClassCastException cce) {
+            throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+        }
+    }
+    
+/**
+ * Adds a <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or another <CODE>Phrase</CODE>
+ * to this <CODE>Phrase</CODE>.
+ *
+ * @param	o	an object of type <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or <CODE>Phrase</CODE>
+ * @return	a boolean
+ * @throws	ClassCastException	when you try to add something that isn't a <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or <CODE>Phrase</CODE>
+ */
+    
+    public boolean add(Object o) {
+        if (o instanceof String) {
+            return super.add(new Chunk((String) o, font));
+        }
+        try {
+            Element element = (Element) o;
+            switch(element.type()) {
+                case Element.CHUNK:
+                    return addChunk((Chunk) o);
+                case Element.PHRASE:
+                case Element.PARAGRAPH:
+                    Phrase phrase = (Phrase) o;
+                    boolean success = true;
+                    Element e;
+                    for (Iterator i = phrase.iterator(); i.hasNext(); ) {
+                        e = (Element) i.next();
+                        if (e instanceof Chunk) {
+                            success &= addChunk((Chunk)e);
+                        }
+                        else {
+                            success &= this.add(e);
+                        }
+                    }
+                    return success;
+                case Element.ANCHOR:
+                    return super.add((Anchor) o);
+                case Element.ANNOTATION:
+                    return super.add((Annotation) o);
+                case Element.TABLE: // case added by David Freels
+                    return super.add((Table) o);
+                case Element.LIST:
+                    return super.add((List) o);
+                case Element.GRAPHIC: // suggested by Steven Balthazor
+                	return super.add((Graphic) o);
+                    default:
+                        throw new ClassCastException(String.valueOf(element.type()));
+            }
+        }
+        catch(ClassCastException cce) {
+            throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+        }
+    }
+    
+/**
+ * Adds a Chunk.
+ * <p>
+ * This method is a hack to solve a problem I had with phrases that were split between chunks
+ * in the wrong place.
+ * @param chunk a Chunk to add to the Phrase
+ * @return true if adding the Chunk succeeded
+ */
+    
+    private synchronized boolean addChunk(Chunk chunk) {
+        if (!font.isStandardFont()) {
+            chunk.setFont(font.difference(chunk.font()));
+        }
+        if (size() > 0 && !chunk.hasAttributes()) {
+            try {
+                Chunk previous = (Chunk) get(size() - 1);
+                if (!previous.hasAttributes() && previous.font().compareTo(chunk.font()) == 0 && !"".equals(previous.content().trim()) && !"".equals(chunk.content().trim())) {
+                    previous.append(chunk.content());
+                    return true;
+                }
+            }
+            catch(ClassCastException cce) {
+            }
+        }
+        return super.add(chunk);
+    }
+    
+/**
+ * Adds a collection of <CODE>Chunk</CODE>s
+ * to this <CODE>Phrase</CODE>.
+ *
+ * @param	collection	a collection of <CODE>Chunk</CODE>s, <CODE>Anchor</CODE>s and <CODE>Phrase</CODE>s.
+ * @return	<CODE>true</CODE> if the action succeeded, <CODE>false</CODE> if not.
+ * @throws	ClassCastException	when you try to add something that isn't a <CODE>Chunk</CODE>, <CODE>Anchor</CODE> or <CODE>Phrase</CODE>
+ */
+    
+    public boolean addAll(Collection collection) {
+        for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
+            this.add(iterator.next());
+        }
+        return true;
+    }
+    
+/**
+ * Adds a <CODE>Object</CODE> to the <CODE>Paragraph</CODE>.
+ *
+ * @param	object		the object to add.
+ */
+    
+    protected void addSpecial(Object object) {
+        super.add(object);
+    }
+    
+    // methods
+    
+/**
+ * Sets the leading of this phrase.
+ *
+ * @param	leading		the new leading
+ */
+    
+    public void setLeading(float leading) {
+        this.leading = leading;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Checks is this <CODE>Phrase</CODE> contains no or 1 empty <CODE>Chunk</CODE>.
+ *
+ * @return	<CODE>false</CODE> if the <CODE>Phrase</CODE>
+ * contains more than one or more non-empty<CODE>Chunk</CODE>s.
+ */
+    
+    public boolean isEmpty() {
+        switch(size()) {
+            case 0:
+                return true;
+            case 1:
+                Element element = (Element) get(0);
+                if (element.type() == Element.CHUNK && ((Chunk) element).isEmpty()) {
+                    return true;
+                }
+                return false;
+                default:
+                    return false;
+        }
+    }
+    
+/**
+ * Checks you if the leading of this phrase is defined.
+ *
+ * @return	true if the leading is defined
+ */
+    
+    public boolean leadingDefined() {
+        if (Float.isNaN(leading)) {
+            return false;
+        }
+        return true;
+    }
+    
+/**
+ * Gets the leading of this phrase.
+ *
+ * @return	the linespacing
+ */
+    
+    public float leading() {
+        if (Float.isNaN(leading)) {
+            return font.leading(1.5f);
+        }
+        return leading;
+    }
+    
+/**
+ * Gets the font of the first <CODE>Chunk</CODE> that appears in this <CODE>Phrase</CODE>.
+ *
+ * @return	a <CODE>Font</CODE>
+ */
+    
+    public Font font() {
+        return font;
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.PHRASE.equals(tag);
+    }
+    
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return Chunk.getKeySet(markupAttributes);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/Rectangle.java b/LibrarySource/com/lowagie/text/Rectangle.java
new file mode 100644
index 0000000..7f34133
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Rectangle.java
@@ -0,0 +1,869 @@
+/*
+ * $Id: Rectangle.java,v 1.66 2005/04/13 09:17:14 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A <CODE>Rectangle</CODE> is the representation of a geometric figure.
+ *
+ * Rectangles support constant width borders using {@link #setBorderWidth(float)}
+ * and {@link #setBorder(int)}.  They also support borders that vary in
+ * width/color on each side using methods like {@link #setBorderWidthLeft(float)}
+ * or {@link #setBorderColorLeft(java.awt.Color)}.
+ *
+ * @see		Element
+ * @see		Table
+ * @see		Cell
+ * @see		HeaderFooter
+ */
+
+public class Rectangle implements Element, MarkupAttributes {
+    
+    // static membervariables (concerning the presence of borders)
+    
+/** This is the value that will be used as <VAR>undefined</VAR>. */
+    public static final int UNDEFINED = -1;
+    
+/** This represents one side of the border of the <CODE>Rectangle</CODE>. */
+    public static final int TOP = 1;
+    
+/** This represents one side of the border of the <CODE>Rectangle</CODE>. */
+    public static final int BOTTOM = 2;
+    
+/** This represents one side of the border of the <CODE>Rectangle</CODE>. */
+    public static final int LEFT = 4;
+    
+/** This represents one side of the border of the <CODE>Rectangle</CODE>. */
+    public static final int RIGHT = 8;
+    
+/** This represents a rectangle without borders. */
+    public static final int NO_BORDER = 0;
+    
+/** This represents a type of border. */
+    public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
+    
+    // membervariables
+    
+/** the lower left x-coordinate. */
+    protected float llx;
+    
+/** the lower left y-coordinate. */
+    protected float lly;
+    
+/** the upper right x-coordinate. */
+    protected float urx;
+    
+/** the upper right y-coordinate. */
+    protected float ury;
+    
+/** This represents the status of the 4 sides of the rectangle. */
+    protected int border = UNDEFINED;
+    
+/** This is the width of the border around this rectangle. */
+    protected float borderWidth = UNDEFINED;
+    
+/** The color of the border of this rectangle. */
+    protected Color color = null;
+
+/** The color of the left border of this rectangle. */
+    protected Color borderColorLeft = null;
+
+/** The color of the right border of this rectangle. */
+    protected Color borderColorRight = null;
+
+/** The color of the top border of this rectangle. */
+    protected Color borderColorTop = null;
+
+/** The color of the bottom border of this rectangle. */
+    protected Color borderColorBottom = null;
+
+
+/** The width of the left border of this rectangle. */
+    protected float borderWidthLeft = UNDEFINED;
+
+/** The width of the right border of this rectangle. */
+    protected float borderWidthRight = UNDEFINED;
+
+/** The width of the top border of this rectangle. */
+    protected float borderWidthTop = UNDEFINED;
+
+/** The width of the bottom border of this rectangle. */
+    protected float borderWidthBottom = UNDEFINED;
+
+/** Whether variable width borders are used. */
+    protected boolean useVariableBorders = false;
+
+/** This is the color of the background of this rectangle. */
+    protected Color background = null;
+    
+/** This is the grayscale value of the background of this rectangle. */
+    protected float grayFill = 0;
+    
+    protected int rotation = 0;
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes;
+
+    // constructors
+    
+/**
+ * Constructs a <CODE>Rectangle</CODE>-object.
+ *
+ * @param		llx			lower left x
+ * @param		lly			lower left y
+ * @param		urx			upper right x
+ * @param		ury			upper right y
+ */
+
+    public Rectangle(float llx, float lly, float urx, float ury) {
+        this.llx = llx;
+        this.lly = lly;
+        this.urx = urx;
+        this.ury = ury;
+    }
+    
+/**
+ * Constructs a <CODE>Rectangle</CODE>-object starting from the origin (0, 0).
+ *
+ * @param		urx			upper right x
+ * @param		ury			upper right y
+ */
+
+    public Rectangle(float urx, float ury) {
+        this(0, 0, urx, ury);
+    }
+    
+/**
+ * Constructs a <CODE>Rectangle</CODE>-object.
+ *
+ * @param		rect	another <CODE>Rectangle</CODE>
+ */
+    
+    public Rectangle(Rectangle rect) {
+        this(rect.llx, rect.lly, rect.urx, rect.ury);
+        cloneNonPositionParameters(rect);
+    }
+
+/**
+ * Copies all of the parameters from a <CODE>Rectangle</CODE>
+ * object except the position.
+ *
+ * @param		rect	<CODE>Rectangle</CODE> to copy from
+ */
+
+    public void cloneNonPositionParameters(Rectangle rect) {
+       this.rotation = rect.rotation;
+       this.border = rect.border;
+       this.borderWidth = rect.borderWidth;
+       this.color = rect.color;
+       this.background = rect.background;
+       this.grayFill = rect.grayFill;
+       this.borderColorLeft = rect.borderColorLeft;
+       this.borderColorRight = rect.borderColorRight;
+       this.borderColorTop = rect.borderColorTop;
+       this.borderColorBottom = rect.borderColorBottom;
+       this.borderWidthLeft = rect.borderWidthLeft;
+       this.borderWidthRight = rect.borderWidthRight;
+       this.borderWidthTop = rect.borderWidthTop;
+       this.borderWidthBottom = rect.borderWidthBottom;
+       this.useVariableBorders = rect.useVariableBorders;
+    }
+
+    // implementation of the Element interface
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener	an <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.RECTANGLE;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+    // methods
+    
+    /**
+     * Switches lowerleft with upperright
+     */
+    public void normalize() {
+        if (llx > urx) {
+            float a = llx;
+            llx = urx;
+            urx = a;
+        }
+        if (lly > ury) {
+            float a = lly;
+            lly = ury;
+            ury = a;
+        }
+    }
+    
+/**
+ * Gets a Rectangle that is altered to fit on the page.
+ *
+ * @param	top		the top position
+ * @param	bottom	the bottom position
+ * @return	a <CODE>Rectangle</CODE>
+ */
+    
+    public Rectangle rectangle(float top, float bottom) {
+        Rectangle tmp = new Rectangle(this);
+        if (top() > top) {
+            tmp.setTop(top);
+            tmp.setBorder(border - (border & TOP));
+        }
+        if (bottom() < bottom) {
+            tmp.setBottom(bottom);
+            tmp.setBorder(border - (border & BOTTOM));
+        }
+        return tmp;
+    }
+
+/**
+ * Swaps the values of urx and ury and of lly and llx in order to rotate the rectangle.
+ *
+ * @return		a <CODE>Rectangle</CODE>
+ */
+    
+    public Rectangle rotate() {
+        Rectangle rect = new Rectangle(lly, llx, ury, urx);
+        rect.rotation = rotation + 90;
+        rect.rotation %= 360;
+        return rect;
+    }
+    
+    // methods to set the membervariables
+    
+/**
+ * Sets the lower left x-coordinate.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setLeft(float value) {
+        llx = value;
+    }
+    
+/**
+ * Sets the upper right x-coordinate.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setRight(float value) {
+        urx = value;
+    }
+    
+/**
+ * Sets the upper right y-coordinate.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setTop(float value) {
+        ury = value;
+    }
+    
+/**
+ * Sets the lower left y-coordinate.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setBottom(float value) {
+        lly = value;
+    }
+    
+/**
+ * Enables/Disables the border on the specified sides.  The border is specified
+ * as an integer bitwise combination of the constants:
+ * <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>.
+ * @see #enableBorderSide(int)
+ * @see #disableBorderSide(int)
+ * @param	value	the new value
+ */
+    
+    public void setBorder(int value) {
+        border = value;
+    }
+
+/**
+* Enables the border on the specified side.
+*
+* @param	side the side to enable. One of <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>
+*/
+    public void enableBorderSide(int side) {
+        if (border == UNDEFINED) {
+            border = 0;
+        }
+        border |= side;
+    }
+
+/**
+* Disables the border on the specified side.
+*
+* @param	side the side to disable. One of <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>
+*/
+    public void disableBorderSide(int side) {
+        if (border == UNDEFINED) {
+            border = 0;
+        }
+        border &= ~side;
+    }
+
+/**
+ * Sets the borderwidth of the table.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setBorderWidth(float value) {
+        borderWidth = value;
+    }
+
+
+
+ /**
+ * Sets the color of the border.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setBorderColor(Color value) {
+        color = value;
+    }
+
+/**
+ * Sets the value of the border color
+ * @param value a color value
+ */
+public void setBorderColorRight(Color value)
+   {
+      borderColorRight = value;
+   }
+
+/**
+ * Sets the value of the border color
+ * @param value a color value
+ */
+   public void setBorderColorLeft(Color value)
+   {
+      borderColorLeft = value;
+   }
+
+   /**
+    * Sets the value of the border color
+    * @param value a color value
+    */
+   public void setBorderColorTop(Color value)
+   {
+      borderColorTop = value;
+   }
+
+   /**
+    * Sets the value of the border color
+    * @param value a color value
+    */
+   public void setBorderColorBottom(Color value)
+   {
+      borderColorBottom = value;
+   }
+
+
+/**
+ * Sets the backgroundcolor of the rectangle.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setBackgroundColor(Color value) {
+        background = value;
+    }
+    
+/**
+ * Sets the grayscale of the rectangle.
+ *
+ * @param	value	the new value
+ */
+    
+    public void setGrayFill(float value) {
+        if (value >= 0 && value <= 1.0) {
+            grayFill = value;
+        }
+    }
+    
+    // methods to get the membervariables
+    
+/**
+ * Returns the lower left x-coordinate.
+ *
+ * @return		the lower left x-coordinate
+ */
+    
+    public float left() {
+        return llx;
+    }
+    
+/**
+ * Returns the upper right x-coordinate.
+ *
+ * @return		the upper right x-coordinate
+ */
+    
+    public float right() {
+        return urx;
+    }
+    
+/**
+ * Returns the upper right y-coordinate.
+ *
+ * @return		the upper right y-coordinate
+ */
+    
+    public float top() {
+        return ury;
+    }
+    
+/**
+ * Returns the lower left y-coordinate.
+ *
+ * @return		the lower left y-coordinate
+ */
+    
+    public float bottom() {
+        return lly;
+    }
+    
+/**
+ * Returns the lower left x-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the lower left x-coordinate
+ */
+    
+    public float left(float margin) {
+        return llx + margin;
+    }
+    
+/**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the upper right x-coordinate
+ */
+    
+    public float right(float margin) {
+        return urx - margin;
+    }
+    
+/**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the upper right y-coordinate
+ */
+    
+    public float top(float margin) {
+        return ury - margin;
+    }
+    
+/**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the lower left y-coordinate
+ */
+    
+    public float bottom(float margin) {
+        return lly + margin;
+    }
+    
+/**
+ * Returns the width of the rectangle.
+ *
+ * @return		a width
+ */
+    
+    public float width() {
+        return urx - llx;
+    }
+    
+/**
+ * Returns the height of the rectangle.
+ *
+ * @return		a height
+ */
+    
+    public float height() {
+        return ury - lly;
+    }
+    
+/**
+ * Indicates if the table has borders.
+ *
+ * @return	a boolean
+ */
+    
+    public boolean hasBorders() {
+        return (border > 0) &&
+              ((borderWidth > 0)      ||
+               (borderWidthLeft > 0)  ||
+               (borderWidthRight > 0) ||
+               (borderWidthTop > 0)   ||
+               (borderWidthBottom > 0));
+    }
+    
+/**
+ * Indicates if the table has a some type of border.
+ *
+ * @param	type    the type of border
+ * @return	a boolean
+ */
+    
+    public boolean hasBorder(int type) {
+        return border != UNDEFINED && (border & type) == type;
+    }
+    
+/**
+ * Returns the exact type of the border.
+ *
+ * @return	a value
+ */
+    
+    public int border() {
+        return border;
+    }
+    
+/**
+ * Gets the borderwidth.
+ *
+ * @return	a value
+ */
+    
+    public float borderWidth() {
+        return borderWidth;
+    }
+    
+/**
+ * Gets the color of the border.
+ *
+ * @return	a value
+ */
+    
+    public Color borderColor() {
+        return color;
+    }
+    
+/**
+ * Gets the backgroundcolor.
+ *
+ * @return	a value
+ */
+    
+    public Color backgroundColor() {
+        return background;
+    }
+
+/**
+ * Gets the grayscale.
+ *
+ * @return	a value
+ */
+
+    public float grayFill() {
+        return grayFill;
+    }
+    
+    /**
+     * Gets the rotation of the rectangle
+     * @return a rotation value
+     */
+    public int getRotation() {
+        return rotation;
+    }
+    
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+		if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return Chunk.getKeySet(markupAttributes);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+
+/**
+ * Gets the color of a border.
+ * @return a color value
+ */
+public Color getBorderColorLeft()
+   {
+      return borderColorLeft;
+   }
+
+/**
+ * Gets the color of a border.
+ * @return a color value
+ */
+   public Color getBorderColorRight()
+   {
+      return borderColorRight;
+   }
+
+   /**
+    * Gets the color of a border.
+    * @return a color value
+    */
+   public Color getBorderColorTop()
+   {
+      return borderColorTop;
+   }
+
+   /**
+    * Gets the color of a border.
+    * @return a color value
+    */
+   public Color getBorderColorBottom()
+   {
+      return borderColorBottom;
+   }
+
+   /**
+    * Gets the width of a border.
+    * @return a width
+    */
+   public float getBorderWidthLeft()
+   {
+      return getVariableBorderWidth( borderWidthLeft, LEFT );
+   }
+   
+/**
+ * Sets the width of a border
+ * @param borderWidthLeft a width
+ */
+public void setBorderWidthLeft( float borderWidthLeft )
+   {
+      this.borderWidthLeft = borderWidthLeft;
+      updateBorderBasedOnWidth(borderWidthLeft, LEFT);
+   }
+
+   /**
+    * Gets the width of a border.
+    * @return a width
+    */
+   public float getBorderWidthRight()
+   {
+      return getVariableBorderWidth( borderWidthRight, RIGHT );
+   }
+
+/**
+ * Sets the width of a border
+ * @param borderWidthRight a width
+ */
+   public void setBorderWidthRight( float borderWidthRight )
+   {
+      this.borderWidthRight = borderWidthRight;
+      updateBorderBasedOnWidth(borderWidthRight, RIGHT);
+   }
+
+   /**
+    * Gets the width of a border.
+    * @return a width
+    */
+   public float getBorderWidthTop()
+   {
+      return getVariableBorderWidth( borderWidthTop, TOP );
+   }
+   
+/**
+ * Sets the width of a border
+ * @param borderWidthTop a width
+ */
+   public void setBorderWidthTop( float borderWidthTop )
+   {
+      this.borderWidthTop = borderWidthTop;
+      updateBorderBasedOnWidth(borderWidthTop, TOP);
+   }
+
+   /**
+    * Gets the width of a border.
+    * @return a width
+    */
+   public float getBorderWidthBottom()
+   {
+      return getVariableBorderWidth( borderWidthBottom, BOTTOM );
+   }
+   
+/**
+ * Sets the width of a border
+ * @param borderWidthBottom a width
+ */
+   public void setBorderWidthBottom( float borderWidthBottom )
+   {
+      this.borderWidthBottom = borderWidthBottom;
+      updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
+   }
+
+/**
+ * Updates the border flag for a side based on the specified
+ * width.  A width of 0 will disable the border on that side.
+ * Any other width enables it.
+ * @param width  width of border
+ * @param side   border side constant
+ */
+
+   private void updateBorderBasedOnWidth(float width, int side)
+   {
+      useVariableBorders = true;
+      if (width > 0)
+      {
+         enableBorderSide(side);
+      }
+      else
+      {
+         disableBorderSide(side);
+      }
+   }
+
+   private float getVariableBorderWidth( float variableWidthValue, int side )
+   {
+      if ((border & side) != 0)
+      {
+         return  variableWidthValue != UNDEFINED ? variableWidthValue : borderWidth;
+      }
+      else
+      {
+         return 0;
+      }
+   }
+
+/**
+ * Indicates whether variable width borders are being used.
+ * Returns true if <CODE>setBorderWidthLeft, setBorderWidthRight,
+ * setBorderWidthTop, or setBorderWidthBottom</CODE> has been called.
+ *
+ * @return true if variable width borders are in use
+ *
+ */
+   public boolean isUseVariableBorders()
+   {
+      return useVariableBorders;
+   }
+
+/**
+ * Sets a parameter indicating if the rectangle has variable borders
+ * @param useVariableBorders indication if the rectangle has variable borders
+ */
+public void setUseVariableBorders(boolean useVariableBorders)
+   {
+      this.useVariableBorders = useVariableBorders;
+   }
+
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/RomanList.java b/LibrarySource/com/lowagie/text/RomanList.java
new file mode 100644
index 0000000..98ab0f8
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/RomanList.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2003 by Michael Niedermair.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text;
+
+/**
+ * 
+ * A special-version of <CODE>LIST</CODE> which use roman-letters.
+ * 
+ * @see com.lowagie.text.List
+ * @version 2003-06-22
+ * @author Michael Niedermair
+ */
+
+public class RomanList extends List {
+
+	/**
+	 * UpperCase or LowerCase
+	 */
+	protected boolean romanlower;
+
+	/**
+	 * Initialization
+	 * 
+	 * @param symbolIndent	indent
+	 */
+	public RomanList(int symbolIndent) {
+		super(true, symbolIndent);
+	}
+
+	/**
+	 * Initialization 
+	 * @param	romanlower		roman-char in lowercase   
+	 * @param 	symbolIndent	indent
+	 */
+	public RomanList(boolean romanlower, int symbolIndent) {
+		super(true, symbolIndent);
+		this.romanlower = romanlower;
+	}
+
+	/**
+	 * set the roman-letters to lowercase otherwise to uppercase
+	 * 
+	 * @param romanlower
+	 */
+	public void setRomanLower(boolean romanlower) {
+		this.romanlower = romanlower;
+	}
+
+	/**
+	 * Checks if the list is roman-letter with lowercase
+	 *
+	 * @return	<CODE>true</CODE> if the roman-letter is lowercase, <CODE>false</CODE> otherwise.
+	 */
+	public boolean isRomanLower() {
+		return romanlower;
+	}
+
+	/**
+	 * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
+	 *
+	 * @param	o	the object to add.
+	 * @return true if adding the object succeeded
+	 */
+	public boolean add(Object o) {
+		if (o instanceof ListItem) {
+			ListItem item = (ListItem) o;
+			Chunk chunk;
+			if (romanlower)
+				chunk = new Chunk(toRomanLowerCase(first + list.size()), symbol.font());
+			else
+				chunk = new Chunk(toRomanUppercase(first + list.size()), symbol.font());
+			chunk.append(".");
+			item.setListSymbol(chunk);
+			item.setIndentationLeft(symbolIndent);
+			item.setIndentationRight(0);
+			list.add(item);
+		} else if (o instanceof List) {
+			List nested = (List) o;
+			nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+			first--;
+			return list.add(nested);
+		} else if (o instanceof String) {
+			return this.add(new ListItem((String) o));
+		}
+		return false;
+	}
+
+	// ****************************************************************************************
+
+	/*
+	 * Wandelt eine Integer-Zahl in r�mische Schreibweise um
+	 *
+	 * Regeln: http://de.wikipedia.org/wiki/R%F6mische_Ziffern
+	 *  
+	 * 1. Die Ziffern werden addiert, wobei sie von gro� nach klein sortiert sind:
+	 *
+	 *  XVII = 10+5+1+1=17 
+	 *
+	 * 2. Eine kleinere Ziffer, die links von einer gr��eren steht, wird abgezogen:
+	 * 
+	 *  IV = 5-1=4 
+	 *  CM = 1000-100=900 
+	 *
+	 * 3. Maximal drei gleiche Ziffern stehen nebeneinander (Ausnahme: IIII auf Zifferblaettern von Uhren):
+	 * 
+	 *  XL = 40 (und nicht XXXX) 
+	 *  IX = 9 (und nicht VIIII) 
+	 *  Diese "Subtraktionsschreibweise" ist erst im Mittelalter allgemein gebr�uchlich geworden. 
+	 *  Vorher wurde oft "IIII" f�r "4" geshrieben. 
+	 *
+	 * 4. Bei mehreren m�glichen Schreibweisen wird in der Regel der k�rzesten der Vorzug gegeben:
+	 *
+	 *  IC = 99 (auch LXLIX) 
+	 *  IL = 49 (auch XLIX oder sogar XLVIV) 
+	 *  Andererseits gibt es die Vorschrift, nach der ein Symbol, das einen Wert von 10n darstellt, 
+	 *  nicht einem Symbol, das einen Wert von 10(n+1) darstellt, direkt voranstehen darf. 
+	 *  Nach dieser Regel w�re die Schreibweise "XCIX" f�r "99" der Schreibweise "IC" vorzuziehen. 
+	 *
+	 * 5. Die r�mischen Zahlen V, L und D k�nnen nicht gr��eren Zahlen voran gestellt werden:
+	 *
+	 *  XCV = 95 (nicht VC) 
+	 * 
+	 *  Zahlen �ber 3000 werden dargestellt durch Einkastung der Tausender: |IX|LIV=9054
+	 * 
+	 *
+	 * Zahlen gr��er als 3.000.000 werden durch Doppelstrich etc. dargestellt.
+	 */
+
+	/**
+	 * Array with Roman digits.
+	 */
+	private static final RomanDigit[] roman =
+		{
+			new RomanDigit('m', 1000, false),
+			new RomanDigit('d', 500, false),
+			new RomanDigit('c', 100, true),
+			new RomanDigit('l', 50, false),
+			new RomanDigit('x', 10, true),
+			new RomanDigit('v', 5, false),
+			new RomanDigit('i', 1, true)};
+
+	/** 
+	 * changes an int into a lower case roman number.
+	 * @param number the original number
+	 * @return the roman number (lower case)
+	 */
+	public static String toRoman(int number) {
+		return toRomanLowerCase(number);
+	}
+
+	/** 
+	 * Changes an int into an upper case roman number.
+	 * @param number the original number
+	 * @return the roman number (upper case)
+	 */
+	public static String toRomanUppercase(int number) {
+		return toRomanLowerCase(number).toUpperCase();
+	}
+
+	/** 
+	 * Changes an int into a lower case roman number.
+	 * @param number the original number
+	 * @return the roman number (lower case)
+	 */
+	public static String toRomanLowerCase(int number) {
+
+		// Buffer
+		StringBuffer buf = new StringBuffer();
+
+		// kleiner 0 ? Vorzeichen festlegen
+		if (number < 0) {
+			buf.append('-');
+			number = -number;
+		}
+
+		// gr��er 3000
+		if (number > 3000) {
+			// rekursiver Aufruf (ohne tausender-Bereich)
+			buf.append('|');
+			buf.append(toRomanLowerCase(number / 1000));
+			buf.append('|');
+			// tausender-Bereich 
+			number = number - (number / 1000) * 1000;
+		}
+
+		// Schleife
+		int pos = 0;
+		while (true) {
+			// roman-array durchlaufen
+			RomanDigit dig = roman[pos];
+
+			// solange Zahl gr��er roman-Wert
+			while (number >= dig.value) {
+				// Zeichen hinzuf�gen
+				buf.append(dig.digit);
+				// Wert des Zeichens abziehen
+				number -= dig.value;
+			}
+
+			// Abbruch
+			if (number <= 0) {
+				break;
+			}
+			// pre=false suchen (ab Stelle pos)
+			int j = pos;
+			while (!roman[++j].pre);
+
+			// neuer Wert gr��er
+			if (number + roman[j].value >= dig.value) {
+				// hinzuf�gen
+				buf.append(roman[j].digit).append(dig.digit);
+				// Wert vom Rest abziehen
+				number -= dig.value - roman[j].value;
+			}
+			pos++;
+		}
+		return buf.toString();
+	}
+
+	/**
+	 * Helper class for Roman Digits
+	 */
+	private static class RomanDigit {
+
+		/** part of a roman number */
+		public char digit;
+
+		/** value of the roman digit */
+		public int value;
+
+		/** can the digit be used as a prefix */
+		public boolean pre;
+
+		/**
+		 * Constructs a roman digit
+		 * @param digit the roman digit
+		 * @param value the value
+		 * @param pre can it be used as a prefix
+		 */
+		RomanDigit(char digit, int value, boolean pre) {
+			this.digit = digit;
+			this.value = value;
+			this.pre = pre;
+		}
+	}
+
+}
diff --git a/LibrarySource/com/lowagie/text/Row.java b/LibrarySource/com/lowagie/text/Row.java
new file mode 100644
index 0000000..08308b1
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Row.java
@@ -0,0 +1,470 @@
+/*
+ * $Id: Row.java,v 1.63 2005/04/13 09:17:11 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A <CODE>Row</CODE> is part of a <CODE>Table</CODE>
+ * and contains some <CODE>Cells</CODE>.
+ * <P>
+ * All <CODE>Row</CODE>s are constructed by a <CODE>Table</CODE>-object.
+ * You don't have to construct any <CODE>Row</CODE> yourself.
+ * In fact you can't construct a <CODE>Row</CODE> outside the package.
+ * <P>
+ * Since a <CODE>Cell</CODE> can span several rows and/or columns
+ * a row can contain reserved space without any content.
+ *
+ * @see   Element
+ * @see   Cell
+ * @see   Table
+ */
+
+public class Row implements Element, MarkupAttributes {
+    
+    // membervariables
+    
+/** id of a null element in a Row*/
+    public static final int NULL = 0;
+    
+/** id of the Cell element in a Row*/
+    public static final int CELL = 1;
+    
+/** id of the Table element in a Row*/
+    public static final int TABLE = 2;
+    
+/** This is the number of columns in the <CODE>Row</CODE>. */
+    protected int columns;
+    
+/** This is a valid position the <CODE>Row</CODE>. */
+    protected int currentColumn;
+    
+/** This is the array that keeps track of reserved cells. */
+    protected boolean[] reserved;
+    
+/** This is the array of Objects (<CODE>Cell</CODE> or <CODE>Table</CODE>). */
+    protected Object[] cells;
+    
+/** This is the vertical alignment. */
+    protected int horizontalAlignment;
+    
+/** This is the vertical alignment. */
+    protected int verticalAlignment;
+
+/** Contains extra markupAttributes */
+    protected Properties markupAttributes;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>Row</CODE> with a certain number of <VAR>columns</VAR>.
+ *
+ * @param columns   a number of columns
+ */
+ 
+    protected Row(int columns) {
+        this.columns = columns;
+        reserved = new boolean[columns];
+        cells = new Object[columns];
+        currentColumn = 0;
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to a
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param listener  an <CODE>ElementListener</CODE>
+ * @return  <CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return  a type
+ */
+    
+    public int type() {
+        return Element.ROW;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return  an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+/**
+ * Returns a <CODE>Row</CODE> that is a copy of this <CODE>Row</CODE>
+ * in which a certain column has been deleted.
+ *
+ * @param column  the number of the column to delete
+ */
+    
+    void deleteColumn(int column) {
+        if ((column >= columns) || (column < 0)) {
+            throw new IndexOutOfBoundsException("getCell at illegal index : " + column);
+        }
+        columns--;
+        boolean newReserved[] = new boolean[columns];
+        Object newCells[] = new Cell[columns];
+        
+        for (int i = 0; i < column; i++) {
+            newReserved[i] = reserved[i];
+            newCells[i] = cells[i];
+            if (newCells[i] != null && (i + ((Cell) newCells[i]).colspan() > column)) {
+                ((Cell) newCells[i]).setColspan(((Cell) cells[i]).colspan() - 1);
+            }
+        }
+        for (int i = column; i < columns; i++) {
+            newReserved[i] = reserved[i + 1];
+            newCells[i] = cells[i + 1];
+        }
+        if (cells[column] != null && ((Cell) cells[column]).colspan() > 1) {
+            newCells[column] = cells[column];
+            ((Cell) newCells[column]).setColspan(((Cell) newCells[column]).colspan() - 1);
+        }
+        reserved = newReserved;
+        cells = newCells;
+    }
+    
+    // methods
+    
+/**
+ * Adds a <CODE>Cell</CODE> to the <CODE>Row</CODE>.
+ *
+ * @param       element the element to add (currently only Cells and Tables supported)
+ * @return      the column position the <CODE>Cell</CODE> was added,
+ *                      or <CODE>-1</CODE> if the <CODE>element</CODE> couldn't be added.
+ */
+    
+    int addElement(Object element) {
+        return addElement(element, currentColumn);
+    }
+    
+/**
+ * Adds an element to the <CODE>Row</CODE> at the position given.
+ *
+ * @param       element the element to add. (currently only Cells and Tables supported
+ * @param       column  the position where to add the cell.
+ * @return      the column position the <CODE>Cell</CODE> was added,
+ *                      or <CODE>-1</CODE> if the <CODE>Cell</CODE> couldn't be added.
+ */
+    
+    int addElement(Object element, int column) {
+        if (element == null) throw new NullPointerException("addCell - null argument");
+        if ((column < 0) || (column > columns)) throw new IndexOutOfBoundsException("addCell - illegal column argument");
+        if ( !((getObjectID(element) == CELL) || (getObjectID(element) == TABLE)) ) throw new IllegalArgumentException("addCell - only Cells or Tables allowed");
+        
+        int lColspan = ( (Cell.class.isInstance(element)) ? ((Cell) element).colspan() : 1);
+        
+        if ( reserve(column, lColspan) == false ) {
+            return -1;
+        }
+        
+        cells[column] = element;
+        currentColumn += lColspan - 1;
+        
+        return column;
+    }
+    
+/**
+ * Puts <CODE>Cell</CODE> to the <CODE>Row</CODE> at the position given, doesn't reserve colspan.
+ *
+ * @param   aElement    the cell to add.
+ * @param   column  the position where to add the cell.
+ */
+    
+    void setElement(Object aElement, int column) {
+        if (reserved[column] == true) throw new IllegalArgumentException("setElement - position already taken");
+        
+        cells[column] = aElement;
+        if (aElement != null) {
+            reserved[column] = true;
+        }
+    }
+    
+/**
+ * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>.
+ *
+ * @param   column  the column that has to be reserved.
+ * @return  <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
+ */
+    
+    boolean reserve(int column) {
+        return reserve(column, 1);
+    }
+    
+    
+/**
+ * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>.
+ *
+ * @param   column  the column that has to be reserved.
+ * @param   size    the number of columns
+ * @return  <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
+ */
+    
+    boolean reserve(int column, int size) {
+        if ((column < 0) || ((column + size) > columns)) throw new IndexOutOfBoundsException("reserve - incorrect column/size");
+        
+        for(int i=column; i < column + size; i++)
+        {
+            if (reserved[i] == true) {
+                // undo reserve
+                for(int j=i; j >= column; j--) {
+                    reserved[i] = false;
+                }
+                return false;
+            }
+            reserved[i] = true;
+        }
+        return true;
+    }
+    
+/**
+ * Sets the horizontal alignment.
+ *
+ * @param value the new value
+ */
+    
+    public void setHorizontalAlignment(int value) {
+        horizontalAlignment = value;
+    }
+    
+/**
+ * Sets the vertical alignment.
+ *
+ * @param value the new value
+ */
+    
+    public void setVerticalAlignment(int value) {
+        verticalAlignment = value;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns true/false when this position in the <CODE>Row</CODE> has been reserved, either filled or through a colspan of an Element.
+ *
+ * @param       column  the column.
+ * @return      <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
+ */
+    
+    boolean isReserved(int column) {
+        return reserved[column];
+    }
+    
+/**
+ * Returns the type-id of the element in a Row.
+ *
+ * @param       column  the column of which you'd like to know the type
+ * @return the type-id of the element in the row
+ */
+    
+    int getElementID(int column) {
+        if (cells[column] == null) return NULL;
+        else if (Cell.class.isInstance(cells[column])) return CELL;
+        else if (Table.class.isInstance(cells[column])) return TABLE;
+        
+        return -1;
+    }
+    
+    
+/**
+ * Returns the type-id of an Object.
+ *
+ * @param       element the object of which you'd like to know the type-id, -1 if invalid
+ * @return the type-id of an object
+ */
+    
+    int getObjectID(Object element) {
+        if (element == null) return NULL;
+        else if (Cell.class.isInstance(element)) return CELL;
+        else if (Table.class.isInstance(element)) return TABLE;
+        
+        return -1;
+    }
+    
+    
+/**
+ * Gets a <CODE>Cell</CODE> or <CODE>Table</CODE> from a certain column.
+ *
+ * @param   column  the column the <CODE>Cell/Table</CODE> is in.
+ * @return  the <CODE>Cell</CODE>,<CODE>Table</CODE> or <VAR>Object</VAR> if the column was
+ *                  reserved or null if empty.
+ */
+    
+    public Object getCell(int column) {
+        if ((column < 0) || (column > columns)) {
+            throw new IndexOutOfBoundsException("getCell at illegal index :" + column + " max is " + columns);
+        }
+        return cells[column];
+    }
+    
+/**
+ * Checks if the row is empty.
+ *
+ * @return  <CODE>true</CODE> if none of the columns is reserved.
+ */
+    
+    public boolean isEmpty() {
+        for (int i = 0; i < columns; i++) {
+            if (cells[i] != null) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+/**
+ * Gets the index of the current, valid position
+ *
+ * @return  a value
+ */
+    
+    int validPosition() {
+        return currentColumn;
+    }
+    
+/**
+ * Gets the number of columns.
+ *
+ * @return  a value
+ */
+    
+    public int columns() {
+        return columns;
+    }
+    
+/**
+ * Gets the horizontal alignment.
+ *
+ * @return  a value
+ */
+    
+    public int horizontalAlignment() {
+        return horizontalAlignment;
+    }
+    
+/**
+ * Gets the vertical alignment.
+ *
+ * @return  a value
+ */
+    
+    public int verticalAlignment() {
+        return verticalAlignment;
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.ROW.equals(tag);
+    }
+    
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+    public void setMarkupAttribute(String name, String value) {
+        if (markupAttributes == null) markupAttributes = new Properties();
+        markupAttributes.put(name, value);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+    public void setMarkupAttributes(Properties markupAttributes) {
+        this.markupAttributes = markupAttributes;
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+    public String getMarkupAttribute(String name) {
+        return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+    public Set getMarkupAttributeNames() {
+        return Chunk.getKeySet(markupAttributes);
+    }
+    
+/**
+ * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+    public Properties getMarkupAttributes() {
+        return markupAttributes;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/Section.java b/LibrarySource/com/lowagie/text/Section.java
new file mode 100644
index 0000000..9ab0753
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Section.java
@@ -0,0 +1,660 @@
+/*
+ * $Id: Section.java,v 1.78 2004/12/14 11:52:50 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+/**
+ * A <CODE>Section</CODE> is a part of a <CODE>Document</CODE> containing
+ * other <CODE>Section</CODE>s, <CODE>Paragraph</CODE>s, <CODE>List</CODE>
+ * and/or <CODE>Table</CODE>s.
+ * <P>
+ * Remark: you can not construct a <CODE>Section</CODE> yourself.
+ * You will have to ask an instance of <CODE>Section</CODE> to the
+ * <CODE>Chapter</CODE> or <CODE>Section</CODE> to which you want to
+ * add the new <CODE>Section</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * Paragraph title2 = new Paragraph("This is Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
+ * Chapter chapter2 = new Chapter(title2, 2);
+ * Paragraph someText = new Paragraph("This is some text");
+ * chapter2.add(someText);
+ * Paragraph title21 = new Paragraph("This is Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
+ * <STRONG>Section section1 = chapter2.addSection(title21);</STRONG>
+ * Paragraph someSectionText = new Paragraph("This is some silly paragraph in a chapter and/or section. It contains some text to test the functionality of Chapters and Section.");
+ * <STRONG>section1.add(someSectionText);</STRONG>
+ * Paragraph title211 = new Paragraph("This is SubSection 1 in Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 14, Font.BOLD, new Color(255, 0, 0)));
+ * <STRONG>Section section11 = section1.addSection(40, title211, 2);</STRONG>
+ * <STRONG>section11.add(someSectionText);</STRONG>
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class Section extends ArrayList implements TextElementArray {
+    
+    // membervariables
+    
+/** This is the title of this section. */
+    protected Paragraph title;
+    
+/** This is the number of sectionnumbers that has to be shown before the section title. */
+    protected int numberDepth;
+    
+/** The indentation of this section on the left side. */
+    protected float indentationLeft;
+    
+/** The indentation of this section on the right side. */
+    protected float indentationRight;
+    
+/** The additional indentation of the content of this section. */
+    protected float sectionIndent;
+    
+/** This is the number of subsections. */
+    protected int subsections = 0;
+    
+/** This is the complete list of sectionnumbers of this section and the parents of this section. */
+    protected ArrayList numbers = null;
+    
+    /** false if the bookmark children are not visible */
+    protected boolean bookmarkOpen = true;
+    
+    /** The bookmark title if different from the content title */
+    protected String bookmarkTitle;
+    // constructors
+    
+/**
+ * Constructs a new <CODE>Section</CODE>.
+ */
+    
+    protected Section() {
+        title = new Paragraph();
+        numberDepth = 1;
+    }
+    
+/**
+ * Constructs a new <CODE>Section</CODE>.
+ *
+ * @param	title			a <CODE>Paragraph</CODE>
+ * @param	numberDepth		the numberDepth
+ */
+    
+    Section(Paragraph title, int numberDepth) {
+        this.numberDepth = numberDepth;
+        this.title = title;
+    }
+    
+    // private methods
+    
+/**
+ * Sets the number of this section.
+ *
+ * @param	number		the number of this section
+ * @param	numbers		an <CODE>ArrayList</CODE>, containing the numbers of the Parent
+ */
+    
+    private void setNumbers(int number, ArrayList numbers) {
+        this.numbers = new ArrayList();
+        this.numbers.add(new Integer(number));
+        this.numbers.addAll(numbers);
+    }
+    
+    // implementation of the Element-methods
+    
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * <CODE>ElementListener</CODE>.
+ *
+ * @param	listener		the <CODE>ElementListener</CODE>
+ * @return	<CODE>true</CODE> if the element was processed successfully
+ */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            for (Iterator i = iterator(); i.hasNext(); ) {
+                listener.add((Element) i.next());
+            }
+            return true;
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return Element.SECTION;
+    }
+    
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return	an <CODE>ArrayList</CODE>
+ */
+    
+    public ArrayList getChunks() {
+        ArrayList tmp = new ArrayList();
+        for (Iterator i = iterator(); i.hasNext(); ) {
+            tmp.addAll(((Element) i.next()).getChunks());
+        }
+        return tmp;
+    }
+    
+    // overriding some of the ArrayList-methods
+    
+/**
+ * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
+ * to this <CODE>Section</CODE>.
+ *
+ * @param	index	index at which the specified element is to be inserted
+ * @param	o   	an object of type <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>=
+ * @throws	ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
+ */
+    
+    public void add(int index, Object o) {
+        try {
+            Element element = (Element) o;
+            if (element.type() == Element.PARAGRAPH ||
+            element.type() == Element.LIST ||
+            element.type() == Element.CHUNK ||
+            element.type() == Element.PHRASE ||
+            element.type() == Element.ANCHOR ||
+            element.type() == Element.ANNOTATION ||
+            element.type() == Element.TABLE ||
+            element.type() == Element.PTABLE ||
+            element.type() == Element.IMGTEMPLATE ||
+            element.type() == Element.JPEG ||
+            element.type() == Element.IMGRAW) {
+                super.add(index, element);
+            }
+            else {
+                throw new ClassCastException(String.valueOf(element.type()));
+            }
+        }
+        catch(ClassCastException cce) {
+            throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+        }
+    }
+    
+/**
+ * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
+ * to this <CODE>Section</CODE>.
+ *
+ * @param	o   	an object of type <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
+ * @return	a boolean
+ * @throws	ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or <CODE>Section</CODE>
+ */
+    
+    public boolean add(Object o) {
+        try {
+            Element element = (Element) o;
+            if (element.type() == Element.PARAGRAPH ||
+            element.type() == Element.LIST ||
+            element.type() == Element.CHUNK ||
+            element.type() == Element.PHRASE ||
+            element.type() == Element.ANCHOR ||
+            element.type() == Element.ANNOTATION ||
+            element.type() == Element.TABLE ||
+            element.type() == Element.IMGTEMPLATE ||
+            element.type() == Element.PTABLE ||
+            element.type() == Element.JPEG ||
+            element.type() == Element.IMGRAW) {
+                return super.add(o);
+            }
+            else if (element.type() == Element.SECTION) {
+                Section section = (Section) o;
+                section.setNumbers(++subsections, numbers);
+                return super.add(section);
+            }
+            else {
+                throw new ClassCastException(String.valueOf(element.type()));
+            }
+        }
+        catch(ClassCastException cce) {
+            throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+        }
+    }
+    
+/**
+ * Adds a collection of <CODE>Element</CODE>s
+ * to this <CODE>Section</CODE>.
+ *
+ * @param	collection	a collection of <CODE>Paragraph</CODE>s, <CODE>List</CODE>s and/or <CODE>Table</CODE>s
+ * @return	<CODE>true</CODE> if the action succeeded, <CODE>false</CODE> if not.
+ * @throws	ClassCastException if one of the objects isn't a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE>
+ */
+    
+    public boolean addAll(Collection collection) {
+        for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
+            this.add(iterator.next());
+        }
+        return true;
+    }
+    
+    // methods that return a Section
+    
+/**
+ * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	indentation	the indentation of the new section
+ * @param	title		the title of the new section
+ * @param	numberDepth	the numberDepth of the section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(float indentation, Paragraph title, int numberDepth) {
+        Section section = new Section(title, numberDepth);
+        section.setIndentation(indentation);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	indentation	the indentation of the new section
+ * @param	title		the title of the new section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(float indentation, Paragraph title) {
+        Section section = new Section(title, 1);
+        section.setIndentation(indentation);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Creates a <CODE>Section</CODE>, add it to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	title		the title of the new section
+ * @param	numberDepth	the numberDepth of the section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(Paragraph title, int numberDepth) {
+        Section section = new Section(title, numberDepth);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	title		the title of the new section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(Paragraph title) {
+        Section section = new Section(title, 1);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	indentation	the indentation of the new section
+ * @param	title		the title of the new section
+ * @param	numberDepth	the numberDepth of the section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(float indentation, String title, int numberDepth) {
+        Section section = new Section(new Paragraph(title), numberDepth);
+        section.setIndentation(indentation);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	title		the title of the new section
+ * @param	numberDepth	the numberDepth of the section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(String title, int numberDepth) {
+        Section section = new Section(new Paragraph(title), numberDepth);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	indentation	the indentation of the new section
+ * @param	title		the title of the new section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(float indentation, String title) {
+        Section section = new Section(new Paragraph(title), 1);
+        section.setIndentation(indentation);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
+ *
+ * @param	title		the title of the new section
+ * @return  a new Section object
+ */
+    
+    public Section addSection(String title) {
+        Section section = new Section(new Paragraph(title), 1);
+        add(section);
+        return section;
+    }
+    
+/**
+ * Creates a given <CODE>Section</CODE> following a set of attributes and adds it to this one.
+ *
+ * @param	attributes	the attributes
+ * @return      a Section
+ */
+    
+    public Section addSection(Properties attributes) {
+        Section section = new Section(new Paragraph(""), 1);
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.NUMBER)) != null) {
+            subsections = Integer.parseInt(value) - 1;
+        }
+        section.set(attributes);
+        add(section);
+        return section;
+    }
+    
+    
+    // public methods
+    
+/**
+ * Alters the attributes of this <CODE>Section</CODE>.
+ *
+ * @param	attributes	the attributes
+ */
+    
+    public void set(Properties attributes) {
+        String value;
+        if ((value = (String)attributes.remove(ElementTags.NUMBERDEPTH)) != null) {
+            setNumberDepth(Integer.parseInt(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENT)) != null) {
+            setIndentation(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+            setIndentationLeft(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+            setIndentationRight(Float.valueOf(value + "f").floatValue());
+        }
+    }
+    
+/**
+ * Sets the title of this section.
+ *
+ * @param	title	the new title
+ */
+    
+    public void setTitle(Paragraph title) {
+        this.title = title;
+    }
+    
+/**
+ * Sets the depth of the sectionnumbers that will be shown preceding the title.
+ * <P>
+ * If the numberdepth is 0, the sections will not be numbered. If the numberdepth
+ * is 1, the section will be numbered with their own number. If the numberdepth is
+ * higher (for instance x > 1), the numbers of x - 1 parents will be shown.
+ *
+ * @param	numberDepth		the new numberDepth
+ */
+    
+    public void setNumberDepth(int numberDepth) {
+        this.numberDepth = numberDepth;
+    }
+    
+/**
+ * Sets the indentation of this <CODE>Section</CODE> on the left side.
+ *
+ * @param	indentation		the indentation
+ */
+    
+    public void setIndentationLeft(float indentation) {
+        indentationLeft = indentation;
+    }
+    
+/**
+ * Sets the indentation of this <CODE>Section</CODE> on the right side.
+ *
+ * @param	indentation		the indentation
+ */
+    
+    public void setIndentationRight(float indentation) {
+        indentationRight = indentation;
+    }
+    
+/**
+ * Sets the indentation of the content of this <CODE>Section</CODE>.
+ *
+ * @param	indentation		the indentation
+ */
+    
+    public void setIndentation(float indentation) {
+        sectionIndent = indentation;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Checks if this object is a <CODE>Chapter</CODE>.
+ *
+ * @return	<CODE>true</CODE> if it is a <CODE>Chapter</CODE>,
+ *			<CODE>false</CODE> if it is a <CODE>Section</CODE>.
+ */
+    
+    public boolean isChapter() {
+        return type() == Element.CHAPTER;
+    }
+    
+/**
+ * Checks if this object is a <CODE>Section</CODE>.
+ *
+ * @return	<CODE>true</CODE> if it is a <CODE>Section</CODE>,
+ *			<CODE>false</CODE> if it is a <CODE>Chapter</CODE>.
+ */
+    
+    public boolean isSection() {
+        return type() == Element.SECTION;
+    }
+    
+/**
+ * Returns the numberdepth of this <CODE>Section</CODE>.
+ *
+ * @return	the numberdepth
+ */
+    
+    public int numberDepth() {
+        return numberDepth;
+    }
+    
+/**
+ * Returns the indentation of this <CODE>Section</CODE> on the left side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationLeft() {
+        return indentationLeft;
+    }
+    
+/**
+ * Returns the indentation of this <CODE>Section</CODE> on the right side.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentationRight() {
+        return indentationRight;
+    }
+    
+/**
+ * Returns the indentation of the content of this <CODE>Section</CODE>.
+ *
+ * @return	the indentation
+ */
+    
+    public float indentation() {
+        return sectionIndent;
+    }
+    
+/**
+ * Returns the depth of this section.
+ *
+ * @return	the depth
+ */
+    
+    public int depth() {
+        return numbers.size();
+    }
+    
+/**
+ * Returns the title, preceeded by a certain number of sectionnumbers.
+ *
+ * @return	a <CODE>Paragraph</CODE>
+ */
+    
+    public Paragraph title() {
+        if (title == null) {
+            return null;
+        }
+        int depth = Math.min(numbers.size(), numberDepth);
+        if (depth < 1) {
+            return title;
+        }
+        StringBuffer buf = new StringBuffer(" ");
+        for (int i = 0; i < depth; i++) {
+            buf.insert(0, ".");
+            buf.insert(0, ((Integer) numbers.get(i)).intValue());
+        }
+        Paragraph result = new Paragraph(title);
+        result.setMarkupAttributes(title.getMarkupAttributes());
+        result.add(0, new Chunk(buf.toString(), title.font()));
+        return result;
+    }
+    
+/**
+ * Checks if a given tag corresponds with a title tag for this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTitle(String tag) {
+        return ElementTags.TITLE.equals(tag);
+    }
+    
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param   tag     the given tag
+ * @return  true if the tag corresponds
+ */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.SECTION.equals(tag);
+    }
+    
+    /** Getter for property bookmarkOpen.
+     * @return Value of property bookmarkOpen.
+     */
+    public boolean isBookmarkOpen() {
+        return bookmarkOpen;
+    }
+    
+    /** Setter for property bookmarkOpen.
+     * @param bookmarkOpen false if the bookmark children are not
+     * visible.
+     */
+    public void setBookmarkOpen(boolean bookmarkOpen) {
+        this.bookmarkOpen = bookmarkOpen;
+    }
+    
+    /**
+     * Gets the bookmark title.
+     * @return the bookmark title
+     */    
+    public Paragraph getBookmarkTitle() {
+        if (bookmarkTitle == null)
+            return title();
+        else
+            return new Paragraph(bookmarkTitle);
+    }
+    
+    /**
+     * Sets the bookmark title. The bookmark title is the same as the section title but
+     * can be changed with this method.
+     * @param bookmarkTitle the bookmark title
+     */    
+    public void setBookmarkTitle(String bookmarkTitle) {
+        this.bookmarkTitle = bookmarkTitle;
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/SpecialSymbol.java b/LibrarySource/com/lowagie/text/SpecialSymbol.java
new file mode 100644
index 0000000..7d32101
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/SpecialSymbol.java
@@ -0,0 +1,214 @@
+/*
+ * $Id: SpecialSymbol.java,v 1.1 2004/12/23 09:14:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * This class contains the symbols that correspond with special symbols.
+ * <P>
+ * When you construct a <CODE>Phrase</CODE> with Phrase.getInstance using a <CODE>String</CODE>,
+ * this <CODE>String</CODE> can contain special Symbols. These are characters with an int value
+ * between 913 and 937 (except 930) and between 945 and 969. With this class the value of the
+ * corresponding character of the Font Symbol, can be retrieved.
+ *
+ * @see		Phrase
+ *
+ * @author  Bruno Lowagie
+ * @author  Evelyne De Cordier
+ */
+
+public class SpecialSymbol {
+    
+/**
+ * Returns the first occurrence of a special symbol in a <CODE>String</CODE>.
+ *
+ * @param	string		a <CODE>String</CODE>
+ * @return	an index of -1 if no special symbol was found
+ */
+    
+    public static int index(String string) {
+        int length = string.length();
+        for (int i = 0; i < length; i++) {
+            if (getCorrespondingSymbol(string.charAt(i)) != ' ') {
+                return i;
+            }
+        }
+        return -1;
+    }
+    
+/**
+ * Gets a chunk with a symbol character.
+ * @param c a character that has to be changed into a symbol
+ * @param font Font if there is no SYMBOL character corresponding with c
+ * @return a SYMBOL version of a character
+ */
+    
+    public static Chunk get(char c, Font font) {
+        char greek = SpecialSymbol.getCorrespondingSymbol(c);
+        if (greek == ' ') {
+            return new Chunk(String.valueOf(c), font);
+        }
+        Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+        String s = String.valueOf(greek);
+        return new Chunk(s, symbol);
+    }
+    
+/**
+ * Looks for the corresponding symbol in the font Symbol.
+ *
+ * @param	c	the original ASCII-char
+ * @return	the corresponding symbol in font Symbol
+ */
+    
+    public static char getCorrespondingSymbol(char c) {
+        switch(c) {
+            case 913:
+                return 'A'; // ALFA
+            case 914:
+                return 'B'; // BETA
+            case 915:
+                return 'G'; // GAMMA
+            case 916:
+                return 'D'; // DELTA
+            case 917:
+                return 'E'; // EPSILON
+            case 918:
+                return 'Z'; // ZETA
+            case 919:
+                return 'H'; // ETA
+            case 920:
+                return 'Q'; // THETA
+            case 921:
+                return 'I'; // IOTA
+            case 922:
+                return 'K'; // KAPPA
+            case 923:
+                return 'L'; // LAMBDA
+            case 924:
+                return 'M'; // MU
+            case 925:
+                return 'N'; // NU
+            case 926:
+                return 'X'; // XI
+            case 927:
+                return 'O'; // OMICRON
+            case 928:
+                return 'P'; // PI
+            case 929:
+                return 'R'; // RHO
+            case 931:
+                return 'S'; // SIGMA
+            case 932:
+                return 'T'; // TAU
+            case 933:
+                return 'U'; // UPSILON
+            case 934:
+                return 'J'; // PHI
+            case 935:
+                return 'C'; // CHI
+            case 936:
+                return 'Y'; // PSI
+            case 937:
+                return 'W'; // OMEGA
+            case 945:
+                return 'a'; // alfa
+            case 946:
+                return 'b'; // beta
+            case 947:
+                return 'g'; // gamma
+            case 948:
+                return 'd'; // delta
+            case 949:
+                return 'e'; // epsilon
+            case 950:
+                return 'z'; // zeta
+            case 951:
+                return 'h'; // eta
+            case 952:
+                return 'q'; // theta
+            case 953:
+                return 'i'; // iota
+            case 954:
+                return 'k'; // kappa
+            case 955:
+                return 'l'; // lambda
+            case 956:
+                return 'm'; // mu
+            case 957:
+                return 'n'; // nu
+            case 958:
+                return 'x'; // xi
+            case 959:
+                return 'o'; // omicron
+            case 960:
+                return 'p'; // pi
+            case 961:
+                return 'r'; // rho
+            case 962:
+                return 's'; // sigma
+            case 963:
+                return 's'; // sigma
+            case 964:
+                return 't'; // tau
+            case 965:
+                return 'u'; // upsilon
+            case 966:
+                return 'j'; // phi
+            case 967:
+                return 'c'; // chi
+            case 968:
+                return 'y'; // psi
+            case 969:
+                return 'w'; // omega
+                default:
+                    return ' ';
+        }
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/SplitCharacter.java b/LibrarySource/com/lowagie/text/SplitCharacter.java
new file mode 100644
index 0000000..b40753d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/SplitCharacter.java
@@ -0,0 +1,99 @@
+/*
+ * $Id: SplitCharacter.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import com.lowagie.text.pdf.PdfChunk;
+
+/** Interface for customizing the split character.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public interface SplitCharacter {
+    
+    /**
+     * Returns <CODE>true</CODE> if the character can split a line. The splitting implementation
+     * is free to look ahead or look behind characters to make a decision.
+     * <p>
+     * The default implementation is:
+     * <p>
+     * <pre>
+     * public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+     *    char c;
+     *    if (ck == null)
+     *        c = cc[current];
+     *    else
+     *        c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
+     *    if (c <= ' ' || c == '-') {
+     *        return true;
+     *    }
+     *    if (c < 0x2e80)
+     *        return false;
+     *    return ((c >= 0x2e80 && c < 0xd7a0)
+     *    || (c >= 0xf900 && c < 0xfb00)
+     *    || (c >= 0xfe30 && c < 0xfe50)
+     *    || (c >= 0xff61 && c < 0xffa0));
+     * }
+     * </pre>
+     * @param start the lower limit of <CODE>cc</CODE> inclusive
+     * @param current the pointer to the character in <CODE>cc</CODE>
+     * @param end the upper limit of <CODE>cc</CODE> exclusive
+     * @param cc an array of characters at least <CODE>end</CODE> sized
+     * @param ck an array of <CODE>PdfChunk</CODE>. The main use is to be able to call
+     * {@link PdfChunk#getUnicodeEquivalent(char)}. It may be <CODE>null</CODE>
+     * or shorter than <CODE>end</CODE>. If <CODE>null</CODE> no convertion takes place.
+     * If shorter than <CODE>end</CODE> the last element is used
+     * @return <CODE>true</CODE> if the character(s) can split a line
+     */
+    
+    public boolean isSplitCharacter(int start, int current, int end, char cc[], PdfChunk ck[]);
+}
+
diff --git a/LibrarySource/com/lowagie/text/StringCompare.java b/LibrarySource/com/lowagie/text/StringCompare.java
new file mode 100644
index 0000000..f98811c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/StringCompare.java
@@ -0,0 +1,77 @@
+/*
+ * $Id: StringCompare.java,v 1.22 2002/07/09 10:41:40 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * Copyright (c) 2000 Volker Richert
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.util.Comparator;
+
+/**
+ * This class was used in the 1.1-version of iText (by Volker Richert).
+ * Paulo Soares suggested I should add it to the original library, so
+ * that in the future it would be easier to port it to the JDK1.1.x.
+ */
+
+public class StringCompare implements Comparator {
+    
+/**
+ * Compares 2 objects.
+ *
+ * @param   o1  a first object
+ * @param   o2  a second object
+ * @return  a value
+ * @throws  ClassCastException  if the objects aren't Strings
+ */
+    
+    public int compare(Object o1, Object o2) {
+        return ((String)o1).compareTo((String)o2);
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/Table.java b/LibrarySource/com/lowagie/text/Table.java
new file mode 100644
index 0000000..00ab697
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Table.java
@@ -0,0 +1,1952 @@
+/*
+ * $Id: Table.java,v 1.132 2005/05/03 11:58:52 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ * Some methods in this class were contributed by Geert Poels, Kris Jespers and
+ * Steve Ogryzek. Check the CVS repository.
+ */
+
+package com.lowagie.text;
+
+import headless.awt.Color;
+import headless.awt.Dimension;
+import headless.awt.Point;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import com.lowagie.text.markup.*;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfPTableEvent;
+
+import java.text.DecimalFormat;
+/**
+ * A <CODE>Table</CODE> is a <CODE>Rectangle</CODE> that contains <CODE>Cell</CODE>s,
+ * ordered in some kind of matrix.
+ * <P>
+ * Tables that span multiple pages are cut into different parts automatically.
+ * If you want a table header to be repeated on every page, you may not forget to
+ * mark the end of the header section by using the method <CODE>endHeaders()</CODE>.
+ * <P>
+ * The matrix of a table is not necessarily an m x n-matrix. It can contain holes
+ * or cells that are bigger than the unit. Believe me or not, but it took some serious
+ * thinking to make this as userfriendly as possible. I hope you wil find the result
+ * quite simple (I love simple solutions, especially for complex problems).
+ * I didn't want it to be something as complex as the Java <CODE>GridBagLayout</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * // Remark: You MUST know the number of columns when constructing a Table.
+ * //         The number of rows is not important.
+ * <STRONG>Table table = new Table(3);</STRONG>
+ * <STRONG>table.setBorderWidth(1);</STRONG>
+ * <STRONG>table.setBorderColor(new Color(0, 0, 255));</STRONG>
+ * <STRONG>table.setPadding(5);</STRONG>
+ * <STRONG>table.setSpacing(5);</STRONG>
+ * Cell cell = new Cell("header");
+ * cell.setHeader(true);
+ * cell.setColspan(3);
+ * <STRONG>table.addCell(cell);</STRONG>
+ * <STRONG>table.endHeaders();</STRONG>
+ * cell = new Cell("example cell with colspan 1 and rowspan 2");
+ * cell.setRowspan(2);
+ * cell.setBorderColor(new Color(255, 0, 0));
+ * <STRONG>table.addCell(cell);</STRONG>
+ * <STRONG>table.addCell("1.1");</STRONG>
+ * <STRONG>table.addCell("2.1");</STRONG>
+ * <STRONG>table.addCell("1.2");</STRONG>
+ * <STRONG>table.addCell("2.2");</STRONG>
+ * <STRONG>table.addCell("cell test1");</STRONG>
+ * cell = new Cell("big cell");
+ * cell.setRowspan(2);
+ * cell.setColspan(2);
+ * <STRONG>table.addCell(cell);</STRONG>
+ * <STRONG>table.addCell("cell test2");</STRONG>
+ * </PRE></BLOCKQUOTE>
+ * The result of this code is a table:
+ *      <TABLE ALIGN="Center" BORDER="1" BORDERCOLOR="#0000ff" CELLPADDING="5" CELLSPACING="5">
+ *              <TR ALIGN="Left" VALIGN="Left">
+ *                      <TH ALIGN="Left" COLSPAN="3" VALIGN="Left">
+ *                              header
+ *                      </TH>
+ *              </TR>
+ *              <TR ALIGN="Left" VALIGN="Left">
+ *                      <TD ALIGN="Left" BORDERCOLOR="#ff0000" ROWSPAN="2" VALIGN="Left">
+ *                              example cell with colspan 1 and rowspan 2
+ *                      </TD>
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              1.1
+ *                      </TD>
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              2.1
+ *                      </TD>
+ *              </TR>
+ *              <TR ALIGN="Left" VALIGN="Left">
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              1.2
+ *                      </TD>
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              2.2
+ *                      </TD>
+ *              </TR>
+ *              <TR ALIGN="Left" VALIGN="Left">
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              cell test1
+ *                      </TD>
+ *                      <TD ALIGN="Left" COLSPAN="2" ROWSPAN="2" VALIGN="Left">
+ *                              big cell
+ *                      </TD>
+ *              </TR>
+ *              <TR ALIGN="Left" VALIGN="Left">
+ *                      <TD ALIGN="Left" VALIGN="Left">
+ *                              cell test2
+ *                      </TD>
+ *              </TR>
+ *      </TABLE>
+ *
+ * @see         Rectangle
+ * @see         Element
+ * @see         Row
+ * @see         Cell
+ */
+
+public class Table extends Rectangle implements Element, MarkupAttributes {
+    
+    // membervariables
+    
+    // these variables contain the data of the table
+    
+    /** This is the number of columns in the <CODE>Table</CODE>. */
+    private int columns;
+    
+    // this is the current Position in the table
+    private Point curPosition = new Point(0, 0);
+    
+    /** This is the list of <CODE>Row</CODE>s. */
+    private ArrayList rows = new ArrayList();
+    
+    // these variables contain the layout of the table
+    
+    /** This Empty Cell contains the DEFAULT layout of each Cell added with the method addCell(String content). */
+    private Cell defaultLayout = new Cell(true);
+    
+    /** This is the number of the last row of the table headers. */
+    private int lastHeaderRow = -1;
+    
+    /** This is the horizontal alignment. */
+    private int alignment = Element.ALIGN_CENTER;
+    
+    /** This is cellpadding. */
+    private float cellpadding;
+    
+    /** This is cellspacing. */
+    private float cellspacing;
+    
+    /** This is the width of the table (in percent of the available space). */
+    private float widthPercentage = 80;
+    
+    // member variable added by Evelyne De Cordier
+    /** This is the width of the table (in pixels). */
+    private String absWidth = "";
+    
+    /** This is an array containing the widths (in percentages) of every column. */
+    private float[] widths;
+    
+    /** Boolean to track errors (some checks will be performed) */
+    boolean mDebug = false;
+    
+    /** Boolean to track if a table was inserted (to avoid unnecessary computations afterwards) */
+    boolean mTableInserted = false;
+    
+    /**
+     * Boolean to automatically fill empty cells before a table is rendered
+     *  (takes CPU so may be set to false in case of certainty)
+     */
+    boolean mAutoFillEmptyCells = false;
+    
+    /** If true this table may not be split over two pages. */
+    boolean tableFitsPage = false;
+    
+    /** If true cells may not be split over two pages. */
+    boolean cellsFitPage = false;
+    
+    /** This is the offset of the table. */
+    float offset = Float.NaN;
+    
+    /** contains the attributes that are added to each odd (or even) row */
+    protected Hashtable alternatingRowAttributes = null;
+    
+    /** if you want to generate tables the old way, set this value to false. */
+    protected boolean convert2pdfptable = false;
+    
+    // constructors
+    
+    /**
+     * Constructs a <CODE>Table</CODE> with a certain number of columns.
+     *
+     * @param       columns         The number of columns in the table
+     * @throws      BadElementException if the creator was called with less than 1 column
+     */
+    
+    public Table(int columns) throws BadElementException {
+        this(columns, 1);
+    }
+    
+    /**
+     * Constructs a <CODE>Table</CODE> with a certain number of columns
+     * and a certain number of <CODE>Row</CODE>s.
+     *
+     * @param       columns         The number of columns in the table
+     * @param       rows            The number of rows
+     * @throws      BadElementException if the creator was called with less than 1 column
+     */
+    
+    public Table(int columns, int rows) throws BadElementException {
+        // a Rectangle is create with BY DEFAULT a border with a width of 1
+        super(0, 0, 0, 0);
+        setBorder(BOX);
+        setBorderWidth(1);
+        defaultLayout.setBorder(BOX);
+        
+        // a table should have at least 1 column
+        if (columns <= 0) {
+            throw new BadElementException("A table should have at least 1 column.");
+        }
+        this.columns = columns;
+        
+        // a certain number of rows are created
+        for (int i = 0; i < rows; i++) {
+            this.rows.add(new Row(columns));
+        }
+        curPosition = new Point(0, 0);
+        
+        // the DEFAULT widths are calculated
+        widths = new float[columns];
+        float width = 100f / columns;
+        for (int i = 0; i < columns; i++) {
+            widths[i] = width;
+        }
+    }
+    
+    /**
+     * Returns a <CODE>Table</CODE> that has been constructed taking in account
+     * the value of some <VAR>attributes</VAR>.
+     *
+     * @param    attributes        Some attributes
+     */
+    
+    public Table(Properties attributes) {
+        // a Rectangle is create with BY DEFAULT a border with a width of 1
+        super(0, 0, 0, 0);
+        setBorder(BOX);
+        setBorderWidth(1);
+        defaultLayout.setBorder(BOX);
+        
+        String value = (String)attributes.remove(ElementTags.COLUMNS);
+        if (value == null) {
+            columns = 1;
+        }
+        else {
+            columns = Integer.parseInt(value);
+            if (columns <= 0) {
+                columns = 1;
+            }
+        }
+        
+        rows.add(new Row(columns));
+        curPosition.setLocation(0, curPosition.y);
+        
+        if ((value = (String)attributes.remove(ElementTags.LASTHEADERROW)) != null) {
+            setLastHeaderRow(Integer.parseInt(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
+            setAlignment(value);
+        }
+        if ((value = (String)attributes.remove(ElementTags.CELLSPACING)) != null) {
+            setSpacing(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.CELLPADDING)) != null) {
+            setPadding(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.OFFSET)) != null) {
+            setOffset(Float.valueOf(value + "f").floatValue());
+        }
+        if ((value = (String)attributes.remove(ElementTags.WIDTH)) != null) {
+            if (value.endsWith("%"))
+                setWidth(Float.valueOf(value.substring(0, value.length() - 1) + "f").floatValue());
+            else
+                setAbsWidth(value);
+        }
+        widths = new float[columns];
+        for (int i = 0; i < columns; i++) {
+            widths[i] = 0;
+        }
+        if ((value = (String)attributes.remove(ElementTags.WIDTHS)) != null) {
+            StringTokenizer widthTokens = new StringTokenizer(value, ";");
+            int i = 0;
+            while (widthTokens.hasMoreTokens()) {
+                value = (String) widthTokens.nextToken();
+                widths[i] = Float.valueOf(value + "f").floatValue();
+                i++;
+            }
+            columns = i;
+        }
+        if ((value = (String)attributes.remove(ElementTags.TABLEFITSPAGE)) != null) {
+            tableFitsPage = new Boolean(value).booleanValue();
+        }
+        if ((value = (String)attributes.remove(ElementTags.CELLSFITPAGE)) != null) {
+            cellsFitPage = new Boolean(value).booleanValue();
+        }
+        if ((value = (String)attributes.remove(ElementTags.BORDERWIDTH)) != null) {
+            setBorderWidth(Float.valueOf(value + "f").floatValue());
+        }
+        int border = 0;
+        if ((value = (String)attributes.remove(ElementTags.LEFT)) != null) {
+            if (new Boolean(value).booleanValue()) border |= Rectangle.LEFT;
+        }
+        if ((value = (String)attributes.remove(ElementTags.RIGHT)) != null) {
+            if (new Boolean(value).booleanValue()) border |= Rectangle.RIGHT;
+        }
+        if ((value = (String)attributes.remove(ElementTags.TOP)) != null) {
+            if (new Boolean(value).booleanValue()) border |= Rectangle.TOP;
+        }
+        if ((value = (String)attributes.remove(ElementTags.BOTTOM)) != null) {
+            if (new Boolean(value).booleanValue()) border |= Rectangle.BOTTOM;
+        }
+        setBorder(border);
+        String r = (String)attributes.remove(ElementTags.RED);
+        String g = (String)attributes.remove(ElementTags.GREEN);
+        String b = (String)attributes.remove(ElementTags.BLUE);
+        if (r != null || g != null || b != null) {
+            int red = 0;
+            int green = 0;
+            int blue = 0;
+            if (r != null) red = Integer.parseInt(r);
+            if (g != null) green = Integer.parseInt(g);
+            if (b != null) blue = Integer.parseInt(b);
+            setBorderColor(new Color(red, green, blue));
+        }
+        else if ((value = attributes.getProperty(ElementTags.BORDERCOLOR)) != null) {
+            setBorderColor(MarkupParser.decodeColor(value));
+        }
+        r = (String)attributes.remove(ElementTags.BGRED);
+        g = (String)attributes.remove(ElementTags.BGGREEN);
+        b = (String)attributes.remove(ElementTags.BGBLUE);
+        if (r != null || g != null || b != null) {
+            int red = 0;
+            int green = 0;
+            int blue = 0;
+            if (r != null) red = Integer.parseInt(r);
+            if (g != null) green = Integer.parseInt(g);
+            if (b != null) blue = Integer.parseInt(b);
+            setBackgroundColor(new Color(red, green, blue));
+        }
+        else if ((value = (String)attributes.remove(ElementTags.BACKGROUNDCOLOR)) != null) {
+            setBackgroundColor(MarkupParser.decodeColor(value));
+        }
+        if ((value = (String)attributes.remove(ElementTags.GRAYFILL)) != null) {
+            setGrayFill(Float.valueOf(value + "f").floatValue());
+        }
+        if (attributes.size() > 0) setMarkupAttributes(attributes);
+    }
+    
+    // implementation of the Element-methods
+    
+    /**
+     * Processes the element by adding it (or the different parts) to an
+     * <CODE>ElementListener</CODE>.
+     *
+     * @param       listener        an <CODE>ElementListener</CODE>
+     * @return <CODE>true</CODE> if the element was processed successfully
+     */
+    
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+    /**
+     * Performs extra checks when executing table code (currently only when cells are added).
+     * @param aDebug
+     */
+    public void setDebug(boolean aDebug) {
+        mDebug = aDebug;
+    }
+    
+    /**
+     * Sets the default layout of the Table to
+     * the provided Cell
+     * @param value a cell with all the defaults
+     */
+    public void setDefaultLayout(Cell value) {
+        defaultLayout = value;
+    }
+    
+    /**
+     * Enables/disables automatic insertion of empty cells before table is rendered. (default = false)
+     * As some people may want to create a table, fill only a couple of the cells and don't bother with
+     * investigating which empty ones need to be added, this default behaviour may be very welcome.
+     * Disabling is recommended to increase speed. (empty cells should be added through extra code then)
+     *
+     * @param       aDoAutoFill   enable/disable autofill
+     */
+    
+    public void setAutoFillEmptyCells(boolean aDoAutoFill) {
+        mAutoFillEmptyCells = aDoAutoFill;
+    }
+    
+    /**
+     * Allows you to control when a page break occurs.
+     * <P>
+     * When a table doesn't fit a page, it is split in two parts.
+     * If you want to avoid this, you should set the <VAR>tableFitsPage</VAR> value to true.
+     *
+     * @param   fitPage    enter true if you don't want to split cells
+     */
+    
+    public void setTableFitsPage(boolean fitPage) {
+        this.tableFitsPage = fitPage;
+        if (fitPage) setCellsFitPage(true);
+    }
+    
+    /**
+     * Allows you to control when a page break occurs.
+     * <P>
+     * When a cell doesn't fit a page, it is split in two parts.
+     * If you want to avoid this, you should set the <VAR>cellsFitPage</VAR> value to true.
+     *
+     * @param   fitPage    enter true if you don't want to split cells
+     */
+    
+    public void setCellsFitPage(boolean fitPage) {
+        this.cellsFitPage = fitPage;
+    }
+    
+    /**
+     * Checks if this <CODE>Table</CODE> has to fit a page.
+     *
+     * @return  true if the table may not be split
+     */
+    
+    public boolean hasToFitPageTable() {
+        return tableFitsPage;
+    }
+    
+    /**
+     * Checks if the cells of this <CODE>Table</CODE> have to fit a page.
+     *
+     * @return  true if the cells may not be split
+     */
+    
+    public boolean hasToFitPageCells() {
+        return cellsFitPage;
+    }
+    
+    /**
+     * Sets the offset of this table.
+     *
+     * Normally a newline is added before you add a Table object.
+     * This newline uses the current leading.
+     * If you want to control the space between the table and the previous
+     * element yourself, you have to set the offset of this table.
+     *
+     * @param   offset  the space between this table and the previous object.
+     */
+    
+    public void setOffset(float offset) {
+        this.offset = offset;
+    }
+    
+    /**
+     * Gets the offset of this table.
+     *
+     * @return  the space between this table and the previous element.
+     */
+    
+    public float getOffset() {
+        return offset;
+    }
+    
+    /**
+     * Gets the type of the text element.
+     *
+     * @return  a type
+     */
+    
+    public int type() {
+        return Element.TABLE;
+    }
+    
+    /**
+     * Gets all the chunks in this element.
+     *
+     * @return  an <CODE>ArrayList</CODE>
+     */
+    
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+    // methods to add content to the table
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain row and column.
+     *
+     * @param       aCell    The <CODE>Cell</CODE> to add
+     * @param       row     The row where the <CODE>Cell</CODE> will be added
+     * @param       column  The column where the <CODE>Cell</CODE> will be added
+     * @throws BadElementException
+     */
+    
+    public void addCell(Cell aCell, int row, int column) throws BadElementException {
+        addCell(aCell, new Point(row,column));
+    }
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain location.
+     *
+     * @param       aCell        The <CODE>Cell</CODE> to add
+     * @param       aLocation    The location where the <CODE>Cell</CODE> will be added
+     * @throws BadElementException
+     */
+    
+    public void addCell(Cell aCell, Point aLocation) throws BadElementException {
+        if (aCell == null) throw new NullPointerException("addCell - cell has null-value");
+        if (aLocation == null) throw new NullPointerException("addCell - point has null-value");
+        if (aCell.isTable()) insertTable((Table)aCell.getElements().next(), aLocation);
+        if (mDebug == true) {
+            if (aLocation.x < 0) throw new BadElementException("row coordinate of location must be >= 0");
+            if ((aLocation.y <= 0) && (aLocation.y > columns)) throw new BadElementException("column coordinate of location must be >= 0 and < nr of columns");
+            if (!isValidLocation(aCell, aLocation)) throw new BadElementException("Adding a cell at the location (" + aLocation.x + "," + aLocation.y + ") with a colspan of " + aCell.colspan() + " and a rowspan of " + aCell.rowspan() + " is illegal (beyond boundaries/overlapping).");
+        }
+        if (aCell.border() == UNDEFINED) aCell.setBorder(defaultLayout.border());
+        aCell.fill();
+        placeCell(rows, aCell, aLocation);
+        setCurrentLocationToNextValidPosition(aLocation);
+    }
+    
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
+     *
+     * @param       cell         a <CODE>Cell</CODE>
+     */
+    
+    public void addCell(Cell cell) {
+        try {
+            addCell(cell, curPosition);
+        }
+        catch(BadElementException bee) {
+            // don't add the cell
+        }
+    }
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
+     * <P>
+     * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
+     * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
+     *
+     * @param       content         a <CODE>Phrase</CODE>
+     * @throws      BadElementException this should never happen
+     */
+    
+    public void addCell(Phrase content) throws BadElementException {
+        addCell(content, curPosition);
+    }
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
+     * <P>
+     * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
+     * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
+     *
+     * @param       content         a <CODE>Phrase</CODE>
+     * @param       location        a <CODE>Point</CODE>
+     * @throws      BadElementException this should never happen
+     */
+    
+    public void addCell(Phrase content, Point location) throws BadElementException {
+        Cell cell = new Cell(content);
+        cell.setBorder(defaultLayout.border());
+        cell.setBorderWidth(defaultLayout.borderWidth());
+        cell.setBorderColor(defaultLayout.borderColor());
+        cell.setBackgroundColor(defaultLayout.backgroundColor());
+        cell.setGrayFill(defaultLayout.grayFill());
+        cell.setHorizontalAlignment(defaultLayout.horizontalAlignment());
+        cell.setVerticalAlignment(defaultLayout.verticalAlignment());
+        cell.setColspan(defaultLayout.colspan());
+        cell.setRowspan(defaultLayout.rowspan());
+        addCell(cell, location);
+    }
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
+     * <P>
+     * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
+     * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
+     *
+     * @param       content         a <CODE>String</CODE>
+     * @throws      BadElementException this should never happen
+     */
+    
+    public void addCell(String content) throws BadElementException {
+        addCell(new Phrase(content), curPosition);
+    }
+    
+    /**
+     * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
+     * <P>
+     * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
+     * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
+     *
+     * @param       content         a <CODE>String</CODE>
+     * @param       location        a <CODE>Point</CODE>
+     * @throws      BadElementException this should never happen
+     */
+    
+    public void addCell(String content, Point location) throws BadElementException {
+        addCell(new Phrase(content), location);
+    }
+    
+    /**
+     * To put a table within the existing table at the current position
+     * generateTable will of course re-arrange the widths of the columns.
+     *
+     * @param   aTable      the table you want to insert
+     */
+    
+    public void insertTable(Table aTable) {
+        if (aTable == null) throw new NullPointerException("insertTable - table has null-value");
+        insertTable(aTable, curPosition);
+    }
+    
+    /**
+     * To put a table within the existing table at the given position
+     * generateTable will of course re-arrange the widths of the columns.
+     *
+     * @param       aTable  The <CODE>Table</CODE> to add
+     * @param       row     The row where the <CODE>Cell</CODE> will be added
+     * @param       column  The column where the <CODE>Cell</CODE> will be added
+     */
+    
+    public void insertTable(Table aTable, int row, int column) {
+        if (aTable == null) throw new NullPointerException("insertTable - table has null-value");
+        insertTable(aTable, new Point(row, column));
+    }
+    
+    /**
+     * To put a table within the existing table at the given position
+     * generateTable will of course re-arrange the widths of the columns.
+     *
+     * @param   aTable      the table you want to insert
+     * @param   aLocation   a <CODE>Point</CODE>
+     */
+    public void insertTable(Table aTable, Point aLocation) {
+        
+        if (aTable == null) throw new NullPointerException("insertTable - table has null-value");
+        if (aLocation == null) throw new NullPointerException("insertTable - point has null-value");
+        mTableInserted = true;
+        aTable.complete();
+        if (mDebug == true) {
+            if (aLocation.y > columns) System.err.println("insertTable -- wrong columnposition("+ aLocation.y + ") of location; max =" + columns);
+        }
+        int rowCount = aLocation.x + 1 - rows.size();
+        int i = 0;
+        if ( rowCount > 0 ) {   //create new rows ?
+            for (; i < rowCount; i++) {
+                rows.add(new Row(columns));
+            }
+        }
+        
+        ((Row) rows.get(aLocation.x)).setElement(aTable,aLocation.y);
+        
+        setCurrentLocationToNextValidPosition(aLocation);
+    }
+    
+/**
+ * Will fill empty cells with valid blank <CODE>Cell</CODE>s
+ */
+    
+    public void complete() {
+        if (mTableInserted == true) {
+            mergeInsertedTables();  // integrate tables in the table
+            mTableInserted = false;
+        }
+        if (mAutoFillEmptyCells == true) {
+            fillEmptyMatrixCells();
+        }
+        if (alternatingRowAttributes != null) {
+            Properties even = new Properties();
+            Properties odd = new Properties();
+            String name;
+            String[] value;
+            for (Iterator iterator = alternatingRowAttributes.keySet().iterator(); iterator.hasNext(); ) {
+                name = String.valueOf(iterator.next());
+                value = (String[])alternatingRowAttributes.get(name);
+                even.setProperty(name, value[0]);
+                odd.setProperty(name, value[1]);
+            }
+            Row row;
+            for (int i = lastHeaderRow + 1; i < rows.size(); i++) {
+                row = (Row)rows.get(i);
+                row.setMarkupAttributes(i % 2 == 0 ? even : odd);
+            }
+        }
+    }
+    
+    /**
+     * Changes the border in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new border value
+     */
+    
+    public void setDefaultCellBorder(int value) {
+        defaultLayout.setBorder(value);
+    }
+    
+    /**
+     * Changes the width of the borders in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new width
+     */
+    
+    public void setDefaultCellBorderWidth(float value) {
+        defaultLayout.setBorderWidth(value);
+    }
+    
+    /**
+     * Changes the bordercolor in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       color   the new color
+     */
+    
+    public void setDefaultCellBorderColor(Color color) {
+        defaultLayout.setBorderColor(color);
+    }
+    
+    /**
+     * Changes the backgroundcolor in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       color   the new color
+     */
+    
+    public void setDefaultCellBackgroundColor(Color color) {
+        defaultLayout.setBackgroundColor(color);
+    }
+    
+    /**
+     * Changes the grayfill in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setDefaultCellGrayFill(float value) {
+        if (value >= 0 && value <= 1) {
+            defaultLayout.setGrayFill(value);
+        }
+    }
+    
+    /**
+     * Changes the horizontalAlignment in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new alignment value
+     */
+    
+    public void setDefaultHorizontalAlignment(int value) {
+        defaultLayout.setHorizontalAlignment(value);
+    }
+    
+    /**
+     * Changes the verticalAlignment in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new alignment value
+     */
+    
+    public void setDefaultVerticalAlignment(int value) {
+        defaultLayout.setVerticalAlignment(value);
+    }
+    
+    /**
+     * Changes the rowspan in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new rowspan value
+     */
+    
+    public void setDefaultRowspan(int value) {
+        defaultLayout.setRowspan(value);
+    }
+    
+    /**
+     * Changes the colspan in the default layout of the <CODE>Cell</CODE>s
+     * added with method <CODE>addCell(String content)</CODE>.
+     *
+     * @param       value   the new colspan value
+     */
+    
+    public void setDefaultColspan(int value) {
+        defaultLayout.setColspan(value);
+    }
+    
+    // methods
+    
+    /**
+     * Sets the unset cell properties to be the table defaults.
+     *
+     * @param aCell The cell to set to table defaults as necessary.
+     */
+    
+    private void assumeTableDefaults(Cell aCell) {
+        
+        if (aCell.border() == Rectangle.UNDEFINED) {
+            aCell.setBorder(defaultLayout.border());
+        }
+        if (aCell.borderWidth() == Rectangle.UNDEFINED) {
+            aCell.setBorderWidth(defaultLayout.borderWidth());
+        }
+        if (aCell.borderColor() == null) {
+            aCell.setBorderColor(defaultLayout.borderColor());
+        }
+        if (aCell.backgroundColor() == null) {
+            aCell.setBackgroundColor(defaultLayout.backgroundColor());
+        }
+        if (aCell.grayFill() == Rectangle.UNDEFINED) {
+            aCell.setGrayFill(defaultLayout.grayFill());
+        }
+        if (aCell.horizontalAlignment() == Element.ALIGN_UNDEFINED) {
+            aCell.setHorizontalAlignment(defaultLayout.horizontalAlignment());
+        }
+        if (aCell.verticalAlignment() == Element.ALIGN_UNDEFINED) {
+            aCell.setVerticalAlignment(defaultLayout.verticalAlignment());
+        }
+    }
+    
+    /**
+     * Deletes a column in this table.
+     *
+     * @param       column  the number of the column that has to be deleted
+     * @throws BadElementException
+     */
+    
+    public void deleteColumn(int column) throws BadElementException {
+        float newWidths[] = new float[--columns];
+        for (int i = 0; i < column; i++) {
+            newWidths[i] = widths[i];
+        }
+        for (int i = column; i < columns; i++) {
+            newWidths[i] = widths[i + 1];
+        }
+        setWidths(newWidths);
+        for (int i = 0; i < columns; i++) {
+            newWidths[i] = widths[i];
+        }
+        widths = newWidths;
+        Row row;
+        int size = rows.size();
+        for (int i = 0; i < size; i++) {
+            row = (Row) rows.get(i);
+            row.deleteColumn(column);
+            rows.set(i, row);
+        }
+        if (column == columns) {
+            curPosition.setLocation(curPosition.x+1, 0);
+        }
+    }
+
+	/**
+     * Deletes a row.
+     *
+     * @param       row             the number of the row to delete
+     * @return      boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
+     */
+    
+    public boolean deleteRow(int row) {
+        if (row < 0 || row >= rows.size()) {
+            return false;
+        }
+        rows.remove(row);
+        curPosition.setLocation(curPosition.x-1, curPosition.y);
+        return true;
+    }
+    
+    /**
+     * Deletes all rows in this table.
+	 * (contributed by dperezcar at fcc.es)
+     */
+    
+    public void deleteAllRows() {
+        rows.clear();
+        rows.add(new Row(columns));
+        curPosition.setLocation(0, 0);
+        lastHeaderRow = -1;
+    }
+    
+    /**
+     * Deletes the last row in this table.
+     *
+     * @return      boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
+     */
+    
+    public boolean deleteLastRow() {
+        return deleteRow(rows.size() - 1);
+    }
+    
+    /**
+     * Marks the last row of the table headers.
+     *
+     * @return      the number of the last row of the table headers
+     */
+    
+    public int endHeaders() {
+        /* patch sep 8 2001 Francesco De Milato */
+        lastHeaderRow = curPosition.x - 1;
+        return lastHeaderRow;
+    }
+    
+    // methods to set the membervariables
+    
+    /**
+     * Sets the horizontal alignment.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setLastHeaderRow(int value) {
+        lastHeaderRow = value;
+    }
+    
+    /**
+     * Sets the horizontal alignment.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setAlignment(int value) {
+        alignment = value;
+    }
+    
+    /**
+     * Sets the alignment of this paragraph.
+     *
+     * @param    alignment        the new alignment as a <CODE>String</CODE>
+     */
+    
+    public void setAlignment(String alignment) {
+        if (ElementTags.ALIGN_LEFT.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_LEFT;
+            return;
+        }
+        if (ElementTags.RIGHT.equalsIgnoreCase(alignment)) {
+            this.alignment = Element.ALIGN_RIGHT;
+            return;
+        }
+        this.alignment = Element.ALIGN_CENTER;
+    }
+    
+    /**
+     * Sets the cellpadding.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setSpaceInsideCell(float value) {
+        cellpadding = value;
+    }
+    
+    /**
+     * Sets the cellspacing.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setSpaceBetweenCells(float value) {
+        cellspacing = value;
+    }
+    
+    /**
+     * Sets the cellpadding.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setPadding(float value) {
+        cellpadding = value;
+    }
+    
+    /**
+     * Sets the cellspacing.
+     *
+     * @param       value   the new value
+     */
+    
+    public void setSpacing(float value) {
+        cellspacing = value;
+    }
+    
+    /**
+     * Sets the cellspacing (the meaning of cellpadding and cellspacing was inverted by mistake).
+     *
+     * @param       value   the new value
+     * @deprecated  use setSpacing instead
+     */
+    
+    public void setCellpadding(float value) {
+        cellspacing = value;
+    }
+    
+    /**
+     * Sets the cellpadding (the meaning of cellpadding and cellspacing was inverted by mistake).
+     *
+     * @param       value   the new value
+     * @deprecated  use setPadding instead
+     */
+    
+    public void setCellspacing(float value) {
+        cellpadding = value;
+    }
+    
+    /**
+     * Sets the width of this table (in percentage of the available space).
+     *
+     * @param       width           the width
+     */
+    
+    public void setWidth(float width) {
+        this.widthPercentage = width;
+    }
+    
+    /**
+     * Sets the width of this table (in percentage of the available space).
+     *
+     * @param   width           the width
+     */
+    
+    public void setAbsWidth(String width) {
+        this.absWidth = width;
+    }
+    
+    /**
+     * Sets the widths of the different columns (percentages).
+     * <P>
+     * You can give up relative values of borderwidths.
+     * The sum of these values will be considered 100%.
+     * The values will be recalculated as percentages of this sum.
+     * <P>
+     * example:
+     * <BLOCKQUOTE><PRE>
+     * float[] widths = {2, 1, 1};
+     * <STRONG>table.setWidths(widths)</STRONG>
+     * </PRE></BLOCKQUOTE>
+     * The widths will be: a width of 50% for the first column,
+     * 25% for the second and third column.
+     *
+     * @param       widths  an array with values
+     * @throws BadElementException
+     */
+    
+    public void setWidths(float[] widths) throws BadElementException {
+        if (widths.length != columns) {
+            throw new BadElementException("Wrong number of columns.");
+        }
+        
+        // The sum of all values is 100%
+        float hundredPercent = 0;
+        for (int i = 0; i < columns; i++) {
+            hundredPercent += widths[i];
+        }
+        
+        // The different percentages are calculated
+        float width;
+        this.widths[columns - 1] = 100;
+        for (int i = 0; i < columns - 1; i++) {
+            width = (100.0f * widths[i]) / hundredPercent;
+            this.widths[i] = width;
+            this.widths[columns - 1] -= width;
+        }
+    }
+    
+    /**
+     * Sets the widths of the different columns (percentages).
+     * <P>
+     * You can give up relative values of borderwidths.
+     * The sum of these values will be considered 100%.
+     * The values will be recalculated as percentages of this sum.
+     *
+     * @param       widths  an array with values
+     * @throws DocumentException
+     */
+    
+    public void setWidths(int[] widths) throws DocumentException {
+        float tb[] = new float[widths.length];
+        for (int k = 0; k < widths.length; ++k)
+            tb[k] = widths[k];
+        setWidths(tb);
+    }
+    // methods to retrieve the membervariables
+    
+    /**
+     * Gets the number of columns.
+     *
+     * @return    a value
+     */
+    
+    public int columns() {
+        return columns;
+    }
+    
+    /**
+     * Gets the number of rows in this <CODE>Table</CODE>.
+     *
+     * @return      the number of rows in this <CODE>Table</CODE>
+     */
+    
+    public int size() {
+        return rows.size();
+    }
+    
+    /**
+     * Gets the proportional widths of the columns in this <CODE>Table</CODE>.
+     *
+     * @return      the proportional widths of the columns in this <CODE>Table</CODE>
+     */
+    
+    public float[] getProportionalWidths() {
+        return widths;
+    }
+    
+    /**
+     * Gets an <CODE>Iterator</CODE> of all the <CODE>Row</CODE>s.
+     *
+     * @return      an <CODE>Iterator</CODE>
+     */
+    
+    public Iterator iterator() {
+        return rows.iterator();
+    }
+    
+    /**
+     * Gets the horizontal alignment.
+     *
+     * @return  a value
+     */
+    
+    public int alignment() {
+        return alignment;
+    }
+    
+    /**
+     * Gets the cellpadding.
+     *
+     * @return  a value
+     */
+    
+    public float cellpadding() {
+        return cellpadding;
+    }
+    
+    /**
+     * Gets the cellspacing.
+     *
+     * @return  a value
+     */
+    
+    public float cellspacing() {
+        return cellspacing;
+    }
+    
+    /**
+     * Gets the table width (a percentage).
+     *
+     * @return      the table width
+     */
+    
+    public float widthPercentage() {
+        return widthPercentage;
+    }
+    
+    /**
+     * Gets the table width (in pixels).
+     *
+     * @return  the table width
+     */
+    
+    public String absWidth() {
+        return absWidth;
+    }
+    
+    /**
+     * Gets the first number of the row that doesn't contain headers.
+     *
+     * @return      a rownumber
+     */
+    
+    public int firstDataRow() {
+        return lastHeaderRow + 1;
+    }
+    
+    /**
+     * Gets the last number of the rows that contain headers.
+     *  
+     * @return a rownumber
+     */
+    public int lastHeaderRow() {
+        return this.lastHeaderRow;
+    }
+    
+    /**
+     * Gets the dimension of this table
+     *
+     * @return  dimension
+     */
+    
+    public Dimension getDimension() {
+        return new Dimension(columns, rows.size());
+    }
+    
+    /**
+     * returns the element at the position row, column
+     *          (Cast to Cell or Table)
+     * 
+     * @param row
+     * @param column
+     * @return  dimension
+     */
+    
+    public Object getElement(int row, int column) {
+        return ((Row) rows.get(row)).getCell(column);
+    }
+    
+    /**
+     * Integrates all added tables and recalculates column widths.
+     */
+    
+    private void mergeInsertedTables() {
+        int i=0, j=0;
+        float [] lNewWidths = null;
+        int [] lDummyWidths = new int[columns];     // to keep track in how many new cols this one will be split
+        float[][] lDummyColumnWidths = new float[columns][]; // bugfix Tony Copping
+        int [] lDummyHeights = new int[rows.size()]; // to keep track in how many new rows this one will be split
+        ArrayList newRows = null;
+        boolean isTable=false;
+        int lTotalRows  = 0, lTotalColumns      = 0;
+        int lNewMaxRows = 0, lNewMaxColumns     = 0;
+        
+        Table lDummyTable = null;
+        
+        // first we'll add new columns when needed
+        // check one column at a time, find maximum needed nr of cols
+        // Search internal tables and find one with max columns
+        for (j=0; j < columns; j++) {
+            lNewMaxColumns = 1; // value to hold in how many columns the current one will be split
+            float [] tmpWidths = null;
+            for (i=0; i < rows.size(); i++) {
+                if ( Table.class.isInstance(((Row) rows.get(i)).getCell(j)) ) {
+                    isTable=true;
+                    lDummyTable = ((Table) ((Row) rows.get(i)).getCell(j));
+                    if( tmpWidths == null) {
+                        tmpWidths = lDummyTable.widths;
+                        lNewMaxColumns=tmpWidths.length;
+                    }
+                    else {
+                        int cols = lDummyTable.getDimension().width;
+                        float [] tmpWidthsN = new float[ cols * tmpWidths.length];
+                        float tpW=0, btW=0, totW=0;
+                        int tpI=0, btI=0, totI=0;
+                        tpW+=tmpWidths[0];
+                        btW+=lDummyTable.widths[0];
+                        while( tpI<tmpWidths.length && btI<cols) {
+                            if( btW>tpW) {
+                                tmpWidthsN[totI] = tpW-totW;
+                                tpI++;
+                                if(tpI<tmpWidths.length) {
+                                    tpW+=tmpWidths[tpI];
+                                }
+                            }
+                            else {
+                                tmpWidthsN[totI] = btW-totW;
+                                btI++;
+                                if( btW == tpW) {
+                                    tpI++;
+                                    if(tpI<tmpWidths.length) {
+                                        tpW+=tmpWidths[tpI];
+                                    }
+                                }
+                                if(btI<cols) {
+                                    btW+=lDummyTable.widths[btI];
+                                }
+                            }
+                            totW+=tmpWidthsN[totI];
+                            totI++;
+                        }
+                       /*if( tpI<tmpWidths.length)
+                       {
+                           System.arraycopy(tmpWidths, tpI, tmpWidthsN, totI, tmpWidths.length-tpI);
+                           totI +=tmpWidths.length-tpI;
+                       }
+                       else if(btI<cols)
+                       {
+                           System.arraycopy(lDummyTable.widths, btI, tmpWidthsN, totI, lDummyTable.widths.length-btI);
+                           totI +=lDummyTable.widths.length-btI;                                                  }*/
+                        tmpWidths = new float[totI];
+                        System.arraycopy(tmpWidthsN, 0, tmpWidths, 0, totI);
+                        lNewMaxColumns=totI;
+                    }
+                                     /*if ( lDummyTable.getDimension().width > lNewMaxColumns )
+                   {
+                       lNewMaxColumns = lDummyTable.getDimension().width;
+                       lDummyColumnWidths[j] = lDummyTable.widths; // bugfix Tony Copping
+                   }*/
+                }
+            }
+            lDummyColumnWidths[j] = tmpWidths;
+            lTotalColumns += lNewMaxColumns;
+            lDummyWidths [j] = lNewMaxColumns;
+        }
+        
+        // next we'll add new rows when needed
+        for (i=0; i < rows.size(); i++) {
+            lNewMaxRows = 1;    // holds value in how many rows the current one will be split
+            for (j=0; j < columns; j++) {
+                if ( Table.class.isInstance(((Row) rows.get(i)).getCell(j)) ) {
+                    isTable=true;
+                    lDummyTable = (Table) ((Row) rows.get(i)).getCell(j);
+                    if ( lDummyTable.getDimension().height > lNewMaxRows ) {
+                        lNewMaxRows = lDummyTable.getDimension().height;
+                    }
+                }
+            }
+            lTotalRows += lNewMaxRows;
+            lDummyHeights [i] = lNewMaxRows;
+        }
+        
+        if ( (lTotalColumns != columns) || (lTotalRows != rows.size()) || isTable)    // NO ADJUSTMENT
+        {
+            // ** WIDTH
+            // set correct width for new columns
+            // divide width over new nr of columns
+            // Take new max columns of internal table and work out widths for each col
+            lNewWidths = new float [lTotalColumns];
+            int lDummy = 0;
+            for (int tel=0; tel < widths.length;tel++) {
+                if ( lDummyWidths[tel] != 1) {
+                    // divide
+                    for (int tel2 = 0; tel2 < lDummyWidths[tel]; tel2++) {
+                        // lNewWidths[lDummy] = widths[tel] / lDummyWidths[tel];
+                        lNewWidths[lDummy] = widths[tel] * lDummyColumnWidths[tel][tel2] / 100f; // bugfix Tony Copping
+                        lDummy++;
+                    }
+                }
+                else {
+                    lNewWidths[lDummy] = widths[tel];
+                    lDummy++;
+                }
+            }
+            
+            // ** FILL OUR NEW TABLE
+            // generate new table
+            // set new widths
+            // copy old values
+            newRows = new ArrayList(lTotalRows);
+            for (i = 0; i < lTotalRows; i++) {
+                newRows.add(new Row(lTotalColumns));
+            }
+            int lDummyRow = 0, lDummyColumn = 0;        // to remember where we are in the new, larger table
+            Object lDummyElement = null;
+            for (i=0; i < rows.size(); i++) {
+                lDummyColumn = 0;
+                lNewMaxRows = 1;
+                for (j=0; j < columns; j++) {
+                    if ( Table.class.isInstance(((Row) rows.get(i)).getCell(j)) )       // copy values from embedded table
+                    {
+                        lDummyTable = (Table) ((Row) rows.get(i)).getCell(j);
+                        
+                        // Work out where columns in table table correspond to columns in current table
+                        int colMap[] = new int[lDummyTable.widths.length+1];
+                        int cb=0, ct=0;
+                        
+                        for( ; cb<lDummyTable.widths.length;cb++) {
+                            colMap[cb] = lDummyColumn+ct;
+                            
+                            float wb;
+                            wb = lDummyTable.widths[cb];
+                            
+                            float wt=0;
+                            while( ct<lDummyWidths[j]) {
+                                wt+=lDummyColumnWidths[j][ct++];
+                                if(convertWidth(wb)==convertWidth(wt)) break;
+                            }
+                            
+                            /* if(convertWidth(wb)==convertWidth(wt) == false) {
+                                System.out.println( "error w !=w2");
+                            } */
+                        }
+                        colMap[cb] = lDummyColumn+ct;
+                        
+                        // need to change this to work out how many cols to span
+                        for (int k=0; k < lDummyTable.getDimension().height; k++) {
+                            for (int l=0; l < lDummyTable.getDimension().width; l++) {
+                                int yy=l;
+                                lDummyElement = lDummyTable.getElement(k,l);
+                                if (lDummyElement != null) {
+                                    int col=lDummyColumn+l;
+                                    
+                                    if ( Cell.class.isInstance(lDummyElement) ) {
+                                        Cell lDummyC = (Cell)lDummyElement;
+                                        // Find col to add cell in and set col span
+                                        col = colMap[l];
+                                        int ot = colMap[l+lDummyC.colspan()];
+                                        
+                                        lDummyC.setColspan(ot-col);
+                                    }
+                                    
+                                    ((Row) newRows.get(k + lDummyRow)).addElement(lDummyElement,col);  // use addElement to set reserved status ok in row
+                                }
+                            }
+                        }
+                    }
+                    else        // copy others values
+                    {
+                        Object aElement = getElement(i,j);
+                        
+                        if ( Cell.class.isInstance(aElement) ) {
+                            
+                            // adjust spans for cell
+                            ((Cell) aElement).setRowspan(((Cell) ((Row) rows.get(i)).getCell(j)).rowspan() + lDummyHeights[i] - 1);
+                            ((Cell) aElement).setColspan(((Cell) ((Row) rows.get(i)).getCell(j)).colspan() + lDummyWidths[j] - 1);
+                            
+                            // most likely this cell covers a larger area because of the row/cols splits : define not-to-be-filled cells
+                            placeCell(newRows,((Cell) aElement), new Point(lDummyRow,lDummyColumn));
+                        }
+                    }
+                    lDummyColumn += lDummyWidths[j];
+                }
+                lDummyRow += lDummyHeights[i];
+            }
+            
+            // Set our new matrix
+            columns     = lTotalColumns;
+            rows = newRows;
+            this.widths = lNewWidths;
+        }
+    }
+    
+    /**
+     * adds new<CODE>Cell</CODE>'s to empty/null spaces.
+     */
+    
+    private void fillEmptyMatrixCells() {
+        try {
+            for (int i=0; i < rows.size(); i++) {
+                for (int j=0; j < columns; j++) {
+                    if ( ((Row) rows.get(i)).isReserved(j) == false) {
+                        addCell(defaultLayout, new Point(i, j));
+                    }
+                }
+            }
+        }
+        catch(BadElementException bee) {
+            throw new ExceptionConverter(bee);
+        }
+    }
+    
+    /**
+     * check if <CODE>Cell</CODE> 'fits' the table.
+     * <P>
+     * <UL><LI>rowspan/colspan not beyond borders
+     *     <LI>spanned cell don't overlap existing cells</UL>
+     *
+     * @param   aCell       the cell that has to be checked
+     * @param   aLocation   the location where the cell has to be placed
+     * @return true if the location was valid
+     */
+    private boolean isValidLocation(Cell aCell, Point aLocation) {
+        // rowspan not beyond last column
+        if ( aLocation.x < rows.size() )        // if false : new location is already at new, not-yet-created area so no check
+        {
+            if ((aLocation.y + aCell.colspan()) > columns) {
+                return false;
+            }
+            
+            int difx = ((rows.size() - aLocation.x) >  aCell.rowspan()) ? aCell.rowspan() : rows.size() - aLocation.x;
+            int dify = ((columns - aLocation.y) >  aCell.colspan()) ? aCell.colspan() : columns - aLocation.y;
+            // no other content at cells targetted by rowspan/colspan
+            for (int i=aLocation.x; i < (aLocation.x + difx); i++) {
+                for (int j=aLocation.y; j < (aLocation.y + dify); j++) {
+                    if ( ((Row) rows.get(i)).isReserved(j) == true ) {
+                        return false;
+                    }
+                }
+            }
+        }
+        else {
+            if ((aLocation.y + aCell.colspan()) > columns) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Inserts a Cell in a cell-array and reserves cells defined by row-/colspan.
+     *
+     * @param   someRows    some rows
+     * @param   aCell       the cell that has to be inserted
+     * @param   aPosition   the position where the cell has to be placed
+     */
+    
+    private void placeCell(ArrayList someRows, Cell aCell, Point aPosition) {
+        int i;
+        Row row = null;
+        int lColumns = ((Row) someRows.get(0)).columns();
+        int rowCount = aPosition.x + aCell.rowspan() - someRows.size();
+        assumeTableDefaults(aCell);
+        if ( (aPosition.x + aCell.rowspan()) > someRows.size() )        //create new rows ?
+        {
+            for (i = 0; i < rowCount; i++) {
+                row = new Row(lColumns);
+                someRows.add(row);
+            }
+        }
+        
+        // reserve cell in rows below
+        for (i = aPosition.x + 1; i < (aPosition.x  + aCell.rowspan()); i++) {
+            if ( !((Row) someRows.get(i)).reserve(aPosition.y, aCell.colspan())) {
+                
+                // should be impossible to come here :-)
+                throw new RuntimeException("addCell - error in reserve");
+            }
+        }
+        row = (Row) someRows.get(aPosition.x);
+        row.addElement(aCell, aPosition.y);
+        
+    }
+    
+    /**
+     * Gives you the posibility to add columns.
+     *
+     * @param   aColumns    the number of columns to add
+     */
+    
+    public void addColumns(int aColumns) {
+        ArrayList newRows = new ArrayList(rows.size());
+        
+        int newColumns = columns + aColumns;
+        Row row;
+        for (int i = 0; i < rows.size(); i++) {
+            row = new Row(newColumns);
+            for (int j = 0; j < columns; j++) {
+                row.setElement(((Row) rows.get(i)).getCell(j) ,j);
+            }
+            for (int j = columns; j < newColumns && i < curPosition.x; j++) {
+                row.setElement(defaultLayout, j);
+            }
+            newRows.add(row);
+        }
+        
+        // applied 1 column-fix; last column needs to have a width of 0
+        float [] newWidths = new float[newColumns];
+        for (int j = 0; j < columns; j++) {
+            newWidths[j] = widths[j];
+        }
+        for (int j = columns; j < newColumns ; j++) {
+            newWidths[j] = 0;
+        }
+        columns = newColumns;
+        widths = newWidths;
+        rows = newRows;
+    }
+    
+    /**
+     * Gets an array with the positions of the borders between every column.
+     * <P>
+     * This method translates the widths expressed in percentages into the
+     * x-coordinate of the borders of the columns on a real document.
+     *
+     * @param       left            this is the position of the first border at the left (cellpadding not included)
+     * @param       totalWidth      this is the space between the first border at the left
+     *                                              and the last border at the right (cellpadding not included)
+     * @return      an array with borderpositions
+     */
+    
+    public float[] getWidths(float left, float totalWidth) {
+        // for x columns, there are x+1 borders
+        float[] w = new float[columns + 1];
+        // the border at the left is calculated
+        switch(alignment) {
+            case Element.ALIGN_LEFT:
+                w[0] = left;
+                break;
+            case Element.ALIGN_RIGHT:
+                w[0] = left + (totalWidth * (100 - widthPercentage)) / 100;
+                break;
+            case Element.ALIGN_CENTER:
+            default:
+                w[0] = left + (totalWidth * (100 - widthPercentage)) / 200;
+        }
+        // the total available width is changed
+        totalWidth = (totalWidth * widthPercentage) / 100;
+        // the inner borders are calculated
+        for (int i = 1; i < columns; i++) {
+            w[i] = w[i - 1] + (widths[i - 1] * totalWidth / 100);
+        }
+        // the border at the right is calculated
+        w[columns] = w[0] + totalWidth;
+        return w;
+    }
+    
+    /**
+     *  Sets current col/row to valid(empty) pos after addCell/Table
+     * @param aLocation a location in the Table
+     */
+    private void setCurrentLocationToNextValidPosition(Point aLocation)    {
+        // set latest location to next valid position
+        int i, j;
+        i = aLocation.x;
+        j = aLocation.y;
+        do {
+            if ( (j + 1)  == columns ) {    // goto next row
+                i++;
+                j = 0;
+            }
+            else {
+                j++;
+            }
+        }
+        while (
+        (i < rows.size()) && (j < columns) && (((Row) rows.get(i)).isReserved(j) == true)
+        );
+        curPosition = new Point(i, j);
+    }
+    
+    
+    
+    /**
+     * Checks if a given tag corresponds with this object.
+     *
+     * @param   tag     the given tag
+     * @return  true if the tag corresponds
+     */
+    
+    public static boolean isTag(String tag) {
+        return ElementTags.TABLE.equals(tag);
+    }
+    
+    /**
+     * Allows clients to set up alternating attributes for each Row in the Table.
+     * <P>
+     * This code was contributed by Matt Benson.
+     *
+     * @param   name    the name of the attribute
+     * @param   value0  the value of the attribute for even rows
+     * @param   value1  the value of the attribute for odd rows
+     */
+    public void setAlternatingRowAttribute(String name, String value0, String value1) {
+        if (value0 == null || value1 == null) {
+            throw new NullPointerException("MarkupTable#setAlternatingRowAttribute(): null values are not permitted.");
+        }
+        if (alternatingRowAttributes == null) alternatingRowAttributes = new Hashtable();
+        
+        // we could always use new Arrays but this is big enough
+        String[] value = (String[])(alternatingRowAttributes.get(name));
+        if (value == null) value = new String[2];
+        value[0] = value0;
+        value[1] = value1;
+        alternatingRowAttributes.put(name, value);
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @return NA
+     */
+    public float top() {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @return NA
+     */
+    public float bottom() {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @return NA
+     */
+    public float left() {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @return NA
+     */
+    public float right() {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param margin NA
+     * @return NA
+     */
+    public float top(int margin) {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param margin NA
+     * @return NA
+     */
+    public float bottom(int margin) {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param margin NA
+     * @return NA
+     */
+    public float left(int margin) {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param margin NA
+     * @return NA
+     */
+    public float right(int margin) {
+        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param value NA
+     */
+    public void setTop(int value) {
+        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param value NA
+     */
+    public void setBottom(int value) {
+        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param value NA
+     */
+    public void setLeft(int value) {
+        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
+    }
+    
+    /**
+     * This method throws an <CODE>UnsupportedOperationException</CODE>.
+     * @param value NA
+     */
+    public void setRight(int value) {
+        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
+    }
+    
+    /**
+     * Returns the next row 0-based index where a new cell would be added.
+	 * (contributed by dperezcar at fcc.es)
+     * @return x coordinate for the next row
+     */
+    public int getNextRow() {
+        return curPosition.x;
+    }
+    
+    /**
+     * Returns the next column 0-based index where a new cell would be added.
+	 * (contributed by dperezcar at fcc.es)
+     * @return y coordinate for the next row
+     */
+    public int getNextColumn() {
+        return curPosition.y;
+    }
+    
+    private static final double convertWidth( double val) {
+        if( val == 0) {
+            return 0;
+        }
+        try {
+            String tmp = widthFormat.format( val);
+            Number result = widthFormat.parse( tmp);
+            
+            return result.doubleValue();
+        }
+        catch( java.text.ParseException pe) {
+            throw new RuntimeException( "Could not convert double to width for val:" + val);
+        }
+    }
+    
+    private static DecimalFormat widthFormat = new DecimalFormat( "0.00");
+
+    /**
+     * Create a PdfPTable based on this Table object.
+     * @return a PdfPTable object
+     * @throws BadElementException
+     */
+    public PdfPTable createPdfPTable() throws BadElementException {
+    	if (!convert2pdfptable) {
+    		throw new BadElementException("No error, just an old style table");
+    	}
+        setAutoFillEmptyCells(true);
+    	complete();
+    	PdfPTable pdfptable = new PdfPTable(widths);
+    	pdfptable.setTableEvent(new BorderEvent(this));
+    	pdfptable.setHeaderRows(lastHeaderRow + 1);
+    	pdfptable.setSplitLate(cellsFitPage);
+    	if (!Float.isNaN(offset)) {
+    		pdfptable.setSpacingBefore(offset);
+    	}
+    	pdfptable.setHorizontalAlignment(alignment);
+    	if (absWidth.length() > 0) {
+    		try {
+    			pdfptable.setTotalWidth(Float.parseFloat(absWidth));
+    		}
+    		catch(Exception e1) {
+    			try {
+    				pdfptable.setTotalWidth((float)Integer.parseInt(absWidth));
+    			}
+    			catch(Exception e2) {
+    				pdfptable.setWidthPercentage(widthPercentage);
+    			}
+    		}
+    	}
+    	else {
+    		pdfptable.setWidthPercentage(widthPercentage);
+    	}
+    	Row row;
+        for (Iterator iterator = iterator(); iterator.hasNext(); ) {
+            row = (Row) iterator.next();
+            Element cell;
+            PdfPCell pcell;
+            for (int i = 0; i < row.columns(); i++) {
+                if ((cell = (Element)row.getCell(i)) != null) {
+                	if (cell instanceof Table) {
+                		pcell = new PdfPCell(((Table)cell).createPdfPTable());
+                	}
+                	else if (cell instanceof Cell) {
+                		pcell = ((Cell)cell).createPdfPCell();
+                		pcell.setPadding(cellpadding);
+                	}
+                	else {
+                		pcell = new PdfPCell();
+                	}
+                	pdfptable.addCell(pcell);
+                }
+            }
+        }
+    	return pdfptable;
+    }
+    
+	/**
+	 * Method to check if the Table should be converted to a PdfPTable or not.
+	 * @return false if the table should be handled the oldfashioned way.
+	 */
+	public boolean isConvert2pdfptable() {
+		return convert2pdfptable;
+	}
+	/**
+	 * If set to true, iText will try to convert the Table to a PdfPTable.
+	 * @param convert2pdfptable true if you want iText to try to convert the Table to a PdfPTable
+	 */
+	public void setConvert2pdfptable(boolean convert2pdfptable) {
+		this.convert2pdfptable = convert2pdfptable;
+	}
+
+	/**
+	 * Event class to draw the Border of a Table when converted to a PdfPTable.
+	 */
+	public class BorderEvent implements PdfPTableEvent {
+		private Rectangle rectangle;
+		/**
+		 * The Table that has to get a Border.
+		 * @param table
+		 */
+		public BorderEvent(Table table) {
+			this.rectangle = table;
+		}
+    	/**
+	     * @see com.lowagie.text.pdf.PdfPTableEvent#tableLayout(com.lowagie.text.pdf.PdfPTable, float[][], float[], int, int, com.lowagie.text.pdf.PdfContentByte[])
+	 	 */
+		public void tableLayout(PdfPTable table, float[][] widths, float[] heights, int headerRows, int rowStart, PdfContentByte[] canvases) {
+			float[] width = widths[0];
+			Rectangle rect = new Rectangle(width[0], heights[heights.length - 1], width[width.length - 1], heights[0]);
+			rect.cloneNonPositionParameters(rectangle);
+			canvases[PdfPTable.BACKGROUNDCANVAS].rectangle(rect);
+			rect.setBackgroundColor(null);
+			canvases[PdfPTable.LINECANVAS].rectangle(rect);
+		}
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/TextElementArray.java b/LibrarySource/com/lowagie/text/TextElementArray.java
new file mode 100644
index 0000000..6b8560c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/TextElementArray.java
@@ -0,0 +1,75 @@
+/*
+ * $Id: TextElementArray.java,v 1.27 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+/**
+ * Interface for a text element to which other objects can be added.
+ *
+ * @see		Phrase
+ * @see		Paragraph
+ * @see		Section
+ * @see		ListItem
+ * @see		Chapter
+ * @see		Anchor
+ * @see		Cell
+ */
+
+public interface TextElementArray extends Element {
+    
+  /**
+   * Adds an object to the <CODE>TextElementArray</CODE>.
+   *
+   * @param	o			an object that has to be added
+   * @return	<CODE>true</CODE> if the addition succeeded; <CODE>false</CODE> otherwise
+   */
+    
+    public boolean add(Object o);
+}
diff --git a/LibrarySource/com/lowagie/text/Watermark.java b/LibrarySource/com/lowagie/text/Watermark.java
new file mode 100644
index 0000000..bda93fa
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/Watermark.java
@@ -0,0 +1,123 @@
+/*
+ * $Id: Watermark.java,v 1.52 2004/12/14 11:52:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text;
+
+import java.net.MalformedURLException;
+
+/**
+ * A <CODE>Watermark</CODE> is a graphic element (GIF or JPEG)
+ * that is shown on a certain position on each page.
+ *
+ * @see		Element
+ * @see		Jpeg
+ */
+
+public class Watermark extends Image implements Element {
+    
+    // membervariables
+    
+/** This is the offset in x-direction of the Watermark. */
+    private float offsetX = 0;
+    
+/** This is the offset in y-direction of the Watermark. */
+    private float offsetY = 0;
+    
+    // Constructors
+    
+/**
+ * Constructs a <CODE>Watermark</CODE>-object, using an <CODE>Image</CODE>.
+ *
+ * @param		image		an <CODE>Image</CODE>-object
+ * @param		offsetX		the offset in x-direction
+ * @param		offsetY		the offset in y-direction
+ * @throws MalformedURLException
+ */
+    
+    public Watermark(Image image, float offsetX, float offsetY) throws MalformedURLException {
+        super(image);
+        this.offsetX = offsetX;
+        this.offsetY = offsetY;
+    }
+    
+    // implementation of the Element interface
+    
+/**
+ * Gets the type of the text element.
+ *
+ * @return	a type
+ */
+    
+    public int type() {
+        return type;
+    }
+    
+    // methods to retrieve information
+    
+/**
+ * Returns the offset in x direction.
+ *
+ * @return		an offset
+ */
+    
+    public float offsetX() {
+        return offsetX;
+    }
+    
+/**
+ * Returns the offset in y direction.
+ *
+ * @return		an offset
+ */
+    
+    public float offsetY() {
+        return offsetY;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/ZapfDingbatsList.java b/LibrarySource/com/lowagie/text/ZapfDingbatsList.java
new file mode 100644
index 0000000..033a0c7
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ZapfDingbatsList.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2003 by Michael Niedermair.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text;
+
+/**
+ * 
+ * A special-version of <CODE>LIST</CODE> whitch use zapfdingbats-letters.
+ * 
+ * @see com.lowagie.text.List
+ * @version 2003-06-22
+ * @author Michael Niedermair
+ */
+
+public class ZapfDingbatsList extends List {
+
+	/**
+	 * char-number in zapfdingbats
+	 */
+	protected int zn;
+
+	/**
+	 * Creates a ZapfDingbatsList
+	 * 
+	 * @param zn a char-number
+	 * @param symbolIndent	indent
+	 */
+	public ZapfDingbatsList(int zn, int symbolIndent) {
+		super(true, symbolIndent);
+		this.zn = zn;
+		float fontsize = symbol.font().size();
+		symbol.setFont(FontFactory.getFont(FontFactory.ZAPFDINGBATS, fontsize, Font.NORMAL));
+	}
+
+	/**
+	 * set the char-number 
+	 * @param zn a char-number
+	 */
+	public void setCharNumber(int zn) {
+		this.zn = zn;
+	}
+
+	/**
+	 * get the char-number
+	 *
+	 * @return	char-number
+	 */
+	public int getCharNumber() {
+		return zn;
+	}
+
+	/**
+	 * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
+	 *
+	 * @param	o	the object to add.
+	 * @return true if adding the object succeeded
+	 */
+	public boolean add(Object o) {
+		if (o instanceof ListItem) {
+			ListItem item = (ListItem) o;
+			Chunk chunk = new Chunk((char)zn, symbol.font());
+			item.setListSymbol(chunk);
+			item.setIndentationLeft(symbolIndent);
+			item.setIndentationRight(0);
+			list.add(item);
+		} else if (o instanceof List) {
+			List nested = (List) o;
+			nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+			first--;
+			return list.add(nested);
+		} else if (o instanceof String) {
+			return this.add(new ListItem((String) o));
+		}
+		return false;
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/ZapfDingbatsNumberList.java b/LibrarySource/com/lowagie/text/ZapfDingbatsNumberList.java
new file mode 100644
index 0000000..7ca1b06
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/ZapfDingbatsNumberList.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2003 by Michael Niedermair.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text;
+
+/**
+ * 
+ * A special-version of <CODE>LIST</CODE> whitch use zapfdingbats-numbers (1..10).
+ * 
+ * @see com.lowagie.text.List
+ * @version 2003-06-22
+ * @author Michael Niedermair
+ */
+
+public class ZapfDingbatsNumberList extends List {
+
+	/**
+	 * which type
+	 */
+	protected int type;
+
+	/**
+	 * Creates a ZapdDingbatsNumberList
+	 * @param type the type of list
+	 * @param symbolIndent	indent
+	 */
+	public ZapfDingbatsNumberList(int type, int symbolIndent) {
+		super(true, symbolIndent);
+		this.type = type;
+		float fontsize = symbol.font().size();
+		symbol.setFont(FontFactory.getFont(FontFactory.ZAPFDINGBATS, fontsize, Font.NORMAL));
+	}
+
+	/**
+	 * set the type 
+	 * 
+	 * @param type
+	 */
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	/**
+	 * get the type
+	 *
+	 * @return	char-number
+	 */
+	public int getType() {
+		return type;
+	}
+
+	/**
+	 * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
+	 *
+	 * @param	o	the object to add.
+	 * @return true if adding the object succeeded
+	 */
+	public boolean add(Object o) {
+		if (o instanceof ListItem) {
+			ListItem item = (ListItem) o;
+			Chunk chunk;
+			switch (type ) {
+				case 0:
+					chunk = new Chunk((char)(first + list.size() + 171), symbol.font());
+					break;
+				case 1:
+					chunk = new Chunk((char)(first + list.size() + 181), symbol.font());
+					break;
+				case 2:
+					chunk = new Chunk((char)(first + list.size() + 191), symbol.font());
+					break;
+				default:
+					chunk = new Chunk((char)(first + list.size() + 201), symbol.font());
+			}
+			item.setListSymbol(chunk);
+			item.setIndentationLeft(symbolIndent);
+			item.setIndentationRight(0);
+			list.add(item);
+		} else if (o instanceof List) {
+			List nested = (List) o;
+			nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+			first--;
+			return list.add(nested);
+		} else if (o instanceof String) {
+			return this.add(new ListItem((String) o));
+		}
+		return false;
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/html/HtmlEncoder.java b/LibrarySource/com/lowagie/text/html/HtmlEncoder.java
new file mode 100644
index 0000000..994b270
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/HtmlEncoder.java
@@ -0,0 +1,211 @@
+/*
+ * $Id: HtmlEncoder.java,v 1.24 2002/08/27 11:07:11 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html;
+
+import headless.awt.Color;
+
+import com.lowagie.text.Element;
+
+/**
+ * This class converts a <CODE>String</CODE> to the HTML-format of a String.
+ * <P>
+ * To convert the <CODE>String</CODE>, each character is examined:
+ * <UL>
+ * <LI>ASCII-characters from 000 till 031 are represented as &#xxx;<BR>
+ *     (with xxx = the value of the character)
+ * <LI>ASCII-characters from 032 t/m 127 are represented by the character itself, except for:
+ *     <UL>
+ *     <LI>'\n'	becomes <BR>\n
+ *     <LI>" becomes &quot;
+ *     <LI>& becomes &amp;
+ *     <LI>< becomes &lt;
+ *     <LI>> becomes &gt;
+ *     </UL>
+ * <LI>ASCII-characters from 128 till 255 are represented as &#xxx;<BR>
+ *     (with xxx = the value of the character)
+ * </UL>
+ * <P>
+ * Example:
+ * <P><BLOCKQUOTE><PRE>
+ *    String htmlPresentation = HtmlEncoder.encode("Marie-Thérèse Sørensen");
+ * </PRE></BLOCKQUOTE><P>
+ * for more info: see O'Reilly; "HTML: The Definitive Guide" (page 164)
+ *
+ * @author  mario.maccarini at rug.ac.be
+ */
+
+public class HtmlEncoder {
+    
+    // membervariables
+    
+/** List with the HTML translation of all the characters. */
+    private static final String[] htmlCode = new String[256];
+    
+    static {
+        for (int i = 0; i < 10; i++) {
+            htmlCode[i] = "&#00" + i + ";";
+        }
+        
+        for (int i = 10; i < 32; i++) {
+            htmlCode[i] = "&#0" + i + ";";
+        }
+        
+        for (int i = 32; i < 128; i++) {
+            htmlCode[i] = String.valueOf((char)i);
+        }
+        
+        // Special characters
+        htmlCode['\t'] = "\t";
+        htmlCode['\n'] = "<" + HtmlTags.NEWLINE + " />\n";
+        htmlCode['\"'] = """; // double quote
+        htmlCode['&'] = "&"; // ampersand
+        htmlCode['<'] = "<"; // lower than
+        htmlCode['>'] = ">"; // greater than
+        
+        for (int i = 128; i < 256; i++) {
+            htmlCode[i] = "&#" + i + ";";
+        }
+    }
+    
+    
+    // constructors
+    
+/**
+ * This class will never be constructed.
+ * <P>
+ * HtmlEncoder only contains static methods.
+ */
+    
+    private HtmlEncoder () { }
+    
+    // methods
+    
+/**
+ * Converts a <CODE>String</CODE> to the HTML-format of this <CODE>String</CODE>.
+ *
+ * @param	string	The <CODE>String</CODE> to convert
+ * @return	a <CODE>String</CODE>
+ */
+    
+    public static String encode(String string) {
+        int n = string.length();
+        char character;
+        StringBuffer buffer = new StringBuffer();
+        // loop over all the characters of the String.
+        for (int i = 0; i < n; i++) {
+            character = string.charAt(i);
+            // the Htmlcode of these characters are added to a StringBuffer one by one
+            if (character < 256) {
+                buffer.append(htmlCode[character]);
+            }
+            else {
+                // Improvement posted by Joachim Eyrich
+                buffer.append("&#").append((int)character).append(";");
+            }
+        }
+        return buffer.toString().trim();
+    }
+    
+/**
+ * Converts a <CODE>Color</CODE> into a HTML representation of this <CODE>Color</CODE>.
+ *
+ * @param	color	the <CODE>Color</CODE> that has to be converted.
+ * @return	the HTML representation of this <COLOR>Color</COLOR>
+ */
+    
+    public static String encode(Color color) {
+        StringBuffer buffer = new StringBuffer("#");
+        if (color.getRed() < 16) {
+            buffer.append('0');
+        }
+        buffer.append(Integer.toString(color.getRed(), 16));
+        if (color.getGreen() < 16) {
+            buffer.append('0');
+        }
+        buffer.append(Integer.toString(color.getGreen(), 16));
+        if (color.getBlue() < 16) {
+            buffer.append('0');
+        }
+        buffer.append(Integer.toString(color.getBlue(), 16));
+        return buffer.toString();
+    }
+    
+/**
+ * Translates the alignment value.
+ *
+ * @param   alignment   the alignment value
+ * @return  the translated value
+ */
+    
+    public static String getAlignment(int alignment) {
+        switch(alignment) {
+            case Element.ALIGN_LEFT:
+                return HtmlTags.ALIGN_LEFT;
+            case Element.ALIGN_CENTER:
+                return HtmlTags.ALIGN_CENTER;
+            case Element.ALIGN_RIGHT:
+                return HtmlTags.ALIGN_RIGHT;
+            case Element.ALIGN_JUSTIFIED:
+            case Element.ALIGN_JUSTIFIED_ALL:
+                return HtmlTags.ALIGN_JUSTIFIED;
+            case Element.ALIGN_TOP:
+                return HtmlTags.ALIGN_TOP;
+            case Element.ALIGN_MIDDLE:
+                return HtmlTags.ALIGN_MIDDLE;
+            case Element.ALIGN_BOTTOM:
+                return HtmlTags.ALIGN_BOTTOM;
+            case Element.ALIGN_BASELINE:
+                return HtmlTags.ALIGN_BASELINE;
+                default:
+                    return "";
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/html/HtmlTags.java b/LibrarySource/com/lowagie/text/html/HtmlTags.java
new file mode 100644
index 0000000..4ff2f91
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/HtmlTags.java
@@ -0,0 +1,331 @@
+/*
+ * $Id: HtmlTags.java,v 1.69 2005/05/03 14:43:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class HtmlTags {
+    
+/** the root tag. */
+    public static final String HTML = "html";
+    
+/** the head tag */
+    public static final String HEAD = "head";
+    
+/** This is a possible HTML attribute for the HEAD tag. */
+    public static final String CONTENT = "content";
+    
+/** the meta tag */
+    public static final String META = "meta";
+    
+/** attribute of the root tag */
+    public static final String SUBJECT = "subject";
+    
+/** attribute of the root tag */
+    public static final String KEYWORDS = "keywords";
+    
+/** attribute of the root tag */
+    public static final String AUTHOR = "author";
+    
+/** the title tag. */
+    public static final String TITLE = "title";
+    
+/** the script tag. */
+    public static final String SCRIPT = "script";
+
+/** This is a possible HTML attribute for the SCRIPT tag. */
+    public static final String LANGUAGE = "language";
+
+/** This is a possible value for the LANGUAGE attribute. */
+    public static final String JAVASCRIPT = "JavaScript";
+
+/** the body tag. */
+    public static final String BODY = "body";
+    
+/** This is a possible HTML attribute for the BODY tag */
+    public static final String JAVASCRIPT_ONLOAD = "onLoad";
+
+/** This is a possible HTML attribute for the BODY tag */
+    public static final String JAVASCRIPT_ONUNLOAD = "onUnLoad";
+
+/** This is a possible HTML attribute for the BODY tag. */
+    public static final String TOPMARGIN = "topmargin";
+    
+/** This is a possible HTML attribute for the BODY tag. */
+    public static final String BOTTOMMARGIN = "bottommargin";
+    
+/** This is a possible HTML attribute for the BODY tag. */
+    public static final String LEFTMARGIN = "leftmargin";
+    
+/** This is a possible HTML attribute for the BODY tag. */
+    public static final String RIGHTMARGIN = "rightmargin";
+    
+    // Phrases, Anchors, Lists and Paragraphs
+    
+/** the chunk tag */
+    public static final String CHUNK = "font";
+    
+/** the phrase tag */
+    public static final String CODE = "code";
+    
+/** the phrase tag */
+    public static final String VAR = "var";
+    
+/** the anchor tag */
+    public static final String ANCHOR = "a";
+    
+/** the list tag */
+    public static final String ORDEREDLIST = "ol";
+    
+/** the list tag */
+    public static final String UNORDEREDLIST = "ul";
+    
+/** the listitem tag */
+    public static final String LISTITEM = "li";
+    
+/** the paragraph tag */
+    public static final String PARAGRAPH = "p";
+    
+/** attribute of anchor tag */
+    public static final String NAME = "name";
+    
+/** attribute of anchor tag */
+    public static final String REFERENCE = "href";
+    
+/** attribute of anchor tag */
+    public static final String[] H = new String[6];
+    static {
+        H[0] = "h1";
+        H[1] = "h2";
+        H[2] = "h3";
+        H[3] = "h4";
+        H[4] = "h5";
+        H[5] = "h6";
+    }
+    
+    // Chunks
+    
+/** attribute of the chunk tag */
+    public static final String FONT = "face";
+    
+/** attribute of the chunk tag */
+    public static final String SIZE = "point-size";
+    
+/** attribute of the chunk/table/cell tag */
+    public static final String COLOR = "color";
+    
+/** some phrase tag */
+    public static final String EM = "em";
+    
+/** some phrase tag */
+    public static final String I = "i";
+    
+/** some phrase tag */
+    public static final String STRONG = "strong";
+    
+/** some phrase tag */
+    public static final String B = "b";
+    
+/** some phrase tag */
+    public static final String S = "s";
+    
+/** some phrase tag */
+    public static final String U = "u";
+    
+/** some phrase tag */
+    public static final String SUB = "sub";
+    
+/** some phrase tag */
+    public static final String SUP = "sup";
+    
+/** the possible value of a tag */
+    public static final String HORIZONTALRULE = "hr";
+    
+    // tables/cells
+    
+/** the table tag */
+    public static final String TABLE = "table";
+    
+/** the cell tag */
+    public static final String ROW = "tr";
+    
+/** the cell tag */
+    public static final String CELL = "td";
+    
+/** attribute of the cell tag */
+    public static final String HEADERCELL = "th";
+    
+/** attribute of the table tag */
+    public static final String COLUMNS = "cols";
+    
+/** attribute of the table tag */
+    public static final String CELLPADDING = "cellpadding";
+    
+/** attribute of the table tag */
+    public static final String CELLSPACING = "cellspacing";
+    
+/** attribute of the cell tag */
+    public static final String COLSPAN = "colspan";
+    
+/** attribute of the cell tag */
+    public static final String ROWSPAN = "rowspan";
+    
+/** attribute of the cell tag */
+    public static final String NOWRAP = "nowrap";
+    
+/** attribute of the table/cell tag */
+    public static final String BORDERWIDTH = "border";
+    
+/** attribute of the table/cell tag */
+    public static final String WIDTH = "width";
+    
+/** attribute of the table/cell tag */
+    public static final String BACKGROUNDCOLOR = "bgcolor";
+    
+/** attribute of the table/cell tag */
+    public static final String BORDERCOLOR = "bordercolor";
+    
+/** attribute of paragraph/image/table tag */
+    public static final String ALIGN = "align";
+    
+/** attribute of chapter/section/paragraph/table/cell tag */
+    public static final String LEFT = "left";
+    
+/** attribute of chapter/section/paragraph/table/cell tag */
+    public static final String RIGHT = "right";
+    
+/** attribute of the cell tag */
+    public static final String HORIZONTALALIGN = "align";
+    
+/** attribute of the cell tag */
+    public static final String VERTICALALIGN = "valign";
+    
+/** attribute of the table/cell tag */
+    public static final String TOP = "top";
+    
+/** attribute of the table/cell tag */
+    public static final String BOTTOM = "bottom";
+    
+    // Misc
+    
+/** the image tag */
+    public static final String IMAGE = "img";
+    
+/** attribute of the image tag */
+    public static final String URL = "src";
+    
+/** attribute of the image tag */
+    public static final String ALT = "alt";
+    
+/** attribute of the image tag */
+    public static final String PLAINWIDTH = "width";
+    
+/** attribute of the image tag */
+    public static final String PLAINHEIGHT = "height";
+    
+/** the newpage tag */
+    public static final String NEWLINE = "br";
+    
+    // alignment attribute values
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_LEFT = "Left";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_CENTER = "Center";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_RIGHT = "Right";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_JUSTIFIED = "Justify";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_TOP = "Top";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_MIDDLE = "Middle";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_BOTTOM = "Bottom";
+    
+/** the possible value of an alignment attribute */
+    public static final String ALIGN_BASELINE = "Baseline";
+    
+/** the possible value of an alignment attribute */
+    public static final String DEFAULT = "Default";
+	
+	/** The DIV tag. */
+	public static final String DIV = "div";
+
+	/** The SPAN tag. */
+	public static final String SPAN = "span";
+	/** The LINK tag. */
+	public static final String LINK = "link";
+	
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String TEXT_CSS = "text/css";
+
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String REL = "rel";
+
+	/** This is used for inline css style information */
+	public static final String STYLE = "style";
+
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String TYPE = "type";
+
+	/** This is a possible HTML attribute. */
+	public static final String STYLESHEET = "stylesheet";
+
+}
diff --git a/LibrarySource/com/lowagie/text/html/HtmlWriter.java b/LibrarySource/com/lowagie/text/html/HtmlWriter.java
new file mode 100644
index 0000000..7df77dc
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/HtmlWriter.java
@@ -0,0 +1,1084 @@
+/*
+ * $Id: HtmlWriter.java,v 1.104 2005/05/03 14:43:59 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Stack;
+import java.util.EmptyStackException;
+
+import com.lowagie.text.*;
+import com.lowagie.text.markup.MarkupTags;
+
+/**
+ * A <CODE>DocWriter</CODE> class for HTML.
+ * <P>
+ * An <CODE>HtmlWriter</CODE> can be added as a <CODE>DocListener</CODE>
+ * to a certain <CODE>Document</CODE> by getting an instance.
+ * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE>
+ * will be written to the <CODE>OutputStream</CODE> of this <CODE>HtmlWriter</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * // creation of the document with a certain size and certain margins
+ * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * try {
+ *    // this will write HTML to the Standard OutputStream
+ *    <STRONG>HtmlWriter.getInstance(document, System.out);</STRONG>
+ *    // this will write HTML to a file called text.html
+ *    <STRONG>HtmlWriter.getInstance(document, new FileOutputStream("text.html"));</STRONG>
+ *    // this will write HTML to for instance the OutputStream of a HttpServletResponse-object
+ *    <STRONG>HtmlWriter.getInstance(document, response.getOutputStream());</STRONG>
+ * }
+ * catch(DocumentException de) {
+ *    System.err.println(de.getMessage());
+ * }
+ * // this will close the document and all the OutputStreams listening to it
+ * <STRONG>document.close();</CODE>
+ * </PRE></BLOCKQUOTE>
+ */
+
+public class HtmlWriter extends DocWriter implements DocListener {
+    
+    // static membervariables (tags)
+    
+/** This is a possible HTML-tag. */
+    public static final byte[] BEGINCOMMENT = getISOBytes("<!-- ");
+    
+/** This is a possible HTML-tag. */
+    public static final byte[] ENDCOMMENT = getISOBytes(" -->");
+    
+/** This is a possible HTML-tag. */
+    public static final String NBSP = " ";
+    
+    // membervariables
+    
+/** This is the current font of the HTML. */
+    protected Stack currentfont = new Stack();
+    
+/** This is the standard font of the HTML. */
+    protected Font standardfont = new Font();
+    
+/** This is a path for images. */
+    protected String imagepath = null;
+    
+/** Stores the page number. */
+    protected int pageN = 0;
+    
+/** This is the textual part of a header */
+    protected HeaderFooter header = null;
+    
+/** This is the textual part of the footer */
+    protected HeaderFooter footer = null;
+    
+    // constructor
+    
+/**
+ * Constructs a <CODE>HtmlWriter</CODE>.
+ *
+ * @param doc     The <CODE>Document</CODE> that has to be written as HTML
+ * @param os      The <CODE>OutputStream</CODE> the writer has to write to.
+ */
+    
+    protected HtmlWriter(Document doc, OutputStream os) {
+        super(doc, os);
+        
+        document.addDocListener(this);
+        this.pageN = document.getPageNumber();
+        try {
+            os.write(LT);
+            os.write(getISOBytes(HtmlTags.HTML));
+            os.write(GT);
+            os.write(NEWLINE);
+            os.write(TAB);
+            os.write(LT);
+            os.write(getISOBytes(HtmlTags.HEAD));
+            os.write(GT);
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+    // get an instance of the HtmlWriter
+    
+/**
+ * Gets an instance of the <CODE>HtmlWriter</CODE>.
+ *
+ * @param document  The <CODE>Document</CODE> that has to be written
+ * @param os  The <CODE>OutputStream</CODE> the writer has to write to.
+ * @return  a new <CODE>HtmlWriter</CODE>
+ */
+    
+    public static HtmlWriter getInstance(Document document, OutputStream os) {
+        return new HtmlWriter(document, os);
+    }
+    
+    // implementation of the DocListener methods
+    
+/**
+ * Signals that an new page has to be started.
+ *
+ * @return  <CODE>true</CODE> if this action succeeded, <CODE>false</CODE> if not.
+ * @throws  DocumentException when a document isn't open yet, or has been closed
+ */
+    
+    public boolean newPage() throws DocumentException {
+        try {
+            writeStart(HtmlTags.DIV);
+            write(" ");
+            write(HtmlTags.STYLE);
+            write("=\"");
+            writeCssProperty(MarkupTags.CSS_KEY_PAGE_BREAK_BEFORE, MarkupTags.CSS_VALUE_ALWAYS);
+            write("\" /");
+            os.write(GT);
+        }
+        catch(IOException ioe) {
+            throw new DocumentException(ioe);
+        }
+        return true;
+    }
+    
+/**
+ * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
+ * 
+ * @param element a high level object that has to be translated to HTML
+ * @return  <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
+ * @throws  DocumentException when a document isn't open yet, or has been closed
+ */
+    
+    public boolean add(Element element) throws DocumentException {
+        if (pause) {
+            return false;
+        }
+        try {
+            
+            switch(element.type()) {
+                case Element.HEADER:
+                    try {
+                        Header h = (Header) element;
+                        if (HtmlTags.STYLESHEET.equals(h.name())) {
+                            writeLink(h);
+                        }
+                        else if (HtmlTags.JAVASCRIPT.equals(h.name())) {
+                            writeJavaScript(h);
+                        }
+                        else {
+                            writeHeader(h);
+                        }
+                    }
+                    catch(ClassCastException cce) {
+                    }
+                    return true;
+                case Element.SUBJECT:
+                case Element.KEYWORDS:
+                case Element.AUTHOR:
+                    Meta meta = (Meta) element;
+                    writeHeader(meta);
+                    return true;
+                case Element.TITLE:
+                    addTabs(2);
+                    writeStart(HtmlTags.TITLE);
+                    os.write(GT);
+                    addTabs(3);
+                    write(HtmlEncoder.encode(((Meta)element).content()));
+                    addTabs(2);
+                    writeEnd(HtmlTags.TITLE);
+                    return true;
+                case Element.CREATOR:
+                    writeComment("Creator: " + HtmlEncoder.encode(((Meta)element).content()));
+                    return true;
+                case Element.PRODUCER:
+                    writeComment("Producer: " + HtmlEncoder.encode(((Meta)element).content()));
+                    return true;
+                case Element.CREATIONDATE:
+                    writeComment("Creationdate: " + HtmlEncoder.encode(((Meta)element).content()));
+                    return true;
+                    default:
+                        write(element, 2);
+                        return true;
+            }
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+/**
+ * Signals that the <CODE>Document</CODE> has been opened and that
+ * <CODE>Elements</CODE> can be added.
+ * <P>
+ * The <CODE>HEAD</CODE>-section of the HTML-document is written.
+ */
+    
+    public void open() {
+        super.open();
+        try {
+            writeComment("Producer: iTextXML by lowagie.com");
+            writeComment("CreationDate: " + new Date().toString());
+            addTabs(1);
+            writeEnd(HtmlTags.HEAD);
+            addTabs(1);
+            writeStart(HtmlTags.BODY);
+            if (document.leftMargin() > 0) {
+                write(HtmlTags.LEFTMARGIN, String.valueOf(document.leftMargin()));
+            }
+            if (document.rightMargin() > 0) {
+                write(HtmlTags.RIGHTMARGIN, String.valueOf(document.rightMargin()));
+            }
+            if (document.topMargin() > 0) {
+                write(HtmlTags.TOPMARGIN, String.valueOf(document.topMargin()));
+            }
+            if (document.bottomMargin() > 0) {
+                write(HtmlTags.BOTTOMMARGIN, String.valueOf(document.bottomMargin()));
+            }
+            if (pageSize.backgroundColor() != null) {
+                write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(pageSize.backgroundColor()));
+            }
+            if (document.getJavaScript_onLoad() != null) {
+                write(HtmlTags.JAVASCRIPT_ONLOAD, HtmlEncoder.encode(document.getJavaScript_onLoad()));
+            }
+            if (document.getJavaScript_onUnLoad() != null) {
+                write(HtmlTags.JAVASCRIPT_ONUNLOAD, HtmlEncoder.encode(document.getJavaScript_onUnLoad()));
+            }
+            if (document.getHtmlStyleClass() != null) {
+                write(MarkupTags.HTML_ATTR_CSS_CLASS, document.getHtmlStyleClass());
+            }
+            os.write(GT);
+            initHeader(); // line added by David Freels
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+/**
+ * Signals that the <CODE>Document</CODE> was closed and that no other
+ * <CODE>Elements</CODE> will be added.
+ */
+    
+    public void close() {
+        try {
+            initFooter(); // line added by David Freels
+            addTabs(1);
+            writeEnd(HtmlTags.BODY);
+            os.write(NEWLINE);
+            writeEnd(HtmlTags.HTML);
+            super.close();
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+    // some protected methods
+    
+/**
+ * Adds the header to the top of the </CODE>Document</CODE>
+ */
+    
+    protected void initHeader() {
+        if (header != null) {
+            try {
+                add(header.paragraph());
+            }
+            catch(Exception e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+    }
+    
+/**
+ *  Adds the header to the top of the </CODE>Document</CODE>
+ */
+    
+    protected void initFooter() {
+        if (footer != null) {
+            try {
+                // Set the page number. HTML has no notion of a page, so it should always
+                // add up to 1
+                footer.setPageNumber(pageN + 1);
+                add(footer.paragraph());
+            }
+            catch(Exception e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+    }
+    
+/**
+ * Writes a Metatag in the header.
+ *
+ * @param   meta   the element that has to be written
+ * @throws  IOException
+ */
+    
+    protected void writeHeader(Meta meta) throws IOException {
+        addTabs(2);
+        writeStart(HtmlTags.META);
+        switch(meta.type()) {
+            case Element.HEADER:
+                write(HtmlTags.NAME, ((Header) meta).name());
+                break;
+            case Element.SUBJECT:
+                write(HtmlTags.NAME, HtmlTags.SUBJECT);
+                break;
+            case Element.KEYWORDS:
+                write(HtmlTags.NAME, HtmlTags.KEYWORDS);
+                break;
+            case Element.AUTHOR:
+                write(HtmlTags.NAME, HtmlTags.AUTHOR);
+                break;
+        }
+        write(HtmlTags.CONTENT, HtmlEncoder.encode(meta.content()));
+        writeEnd();
+    }
+    
+/**
+ * Writes a link in the header.
+ *
+ * @param   header   the element that has to be written
+ * @throws  IOException
+ */
+    
+    protected void writeLink(Header header) throws IOException {
+        addTabs(2);
+        writeStart(HtmlTags.LINK);
+        write(HtmlTags.REL, header.name());
+        write(HtmlTags.TYPE, HtmlTags.TEXT_CSS);
+        write(HtmlTags.REFERENCE, header.content());
+        writeEnd();
+    }
+    
+/**
+ * Writes a JavaScript section or, if the markup attribute HtmlTags.URL is set, a JavaScript reference in the header.
+ *
+ * @param   header   the element that has to be written
+ * @throws  IOException
+ */
+    
+    protected void writeJavaScript(Header header) throws IOException {
+        addTabs(2);
+        writeStart(HtmlTags.SCRIPT);
+        write(HtmlTags.LANGUAGE, HtmlTags.JAVASCRIPT);
+        if (header.getMarkupAttribute(HtmlTags.URL) != null) {
+          /* JavaScript reference example:
+           *
+           * <script language="JavaScript" src="/myPath/MyFunctions.js"/>
+           */ 
+          write(HtmlTags.URL, header.getMarkupAttribute(HtmlTags.URL));
+          os.write(GT);
+          writeEnd(HtmlTags.SCRIPT);
+        }
+        else {
+          /* JavaScript coding convention:
+           *
+           * <script language="JavaScript" type="text/javascript">
+           * <!--
+           * // ... JavaScript methods ...
+           * //-->
+           * </script>
+           */ 
+          write(HtmlTags.TYPE, MarkupTags.HTML_VALUE_JAVASCRIPT);
+          os.write(GT);
+          addTabs(2);
+          write(new String(BEGINCOMMENT) + "\n");
+          write(header.content());
+          addTabs(2);
+          write("//" + new String(ENDCOMMENT));
+          addTabs(2);
+          writeEnd(HtmlTags.SCRIPT);
+        }
+    }
+    
+/**
+ * Writes some comment.
+ * <P>
+ * This method writes some comment.
+ *
+ * @param comment   the comment that has to be written
+ * @throws  IOException
+ */
+    
+    protected void writeComment(String comment) throws IOException {
+        addTabs(2);
+        os.write(BEGINCOMMENT);
+        write(comment);
+        os.write(ENDCOMMENT);
+    }
+    
+    // public methods
+    
+/**
+ * Changes the standardfont.
+ *
+ * @param standardfont  The font
+ */
+    
+    public void setStandardFont(Font standardfont) {
+        this.standardfont = standardfont;
+    }
+    
+/**
+ * Checks if a given font is the same as the font that was last used.
+ *
+ * @param   font    the font of an object
+ * @return  true if the font differs
+ */
+    
+    public boolean isOtherFont(Font font) {
+        try {
+            Font cFont = (Font) currentfont.peek();
+            if (cFont.compareTo(font) == 0) return false;
+            return true;
+        }
+        catch(EmptyStackException ese) {
+            if (standardfont.compareTo(font) == 0) return false;
+            return true;
+        }
+    }
+    
+/**
+ * Sets the basepath for images.
+ * <P>
+ * This is especially useful if you add images using a file,
+ * rather than an URL. In PDF there is no problem, since
+ * the images are added inline, but in HTML it is sometimes
+ * necessary to use a relative path or a special path to some
+ * images directory.
+ *
+ * @param imagepath the new imagepath
+ */
+    
+    public void setImagepath(String imagepath) {
+        this.imagepath = imagepath;
+    }
+    
+/**
+ * Resets the imagepath.
+ */
+    
+    public void resetImagepath() {
+        imagepath = null;
+    }
+    
+/**
+ * Changes the header of this document.
+ *
+ * @param header    the new header
+ */
+    
+    public void setHeader(HeaderFooter header) {
+        this.header = header;
+    }
+    
+/**
+ * Changes the footer of this document.
+ *
+ * @param footer    the new footer
+ */
+    
+    public void setFooter(HeaderFooter footer) {
+        this.footer = footer;
+    }
+    
+/**
+ * Signals that a <CODE>String</CODE> was added to the <CODE>Document</CODE>.
+ * 
+ * @param string a String to add to the HTML
+ * @return  <CODE>true</CODE> if the string was added, <CODE>false</CODE> if not.
+ * @throws  DocumentException when a document isn't open yet, or has been closed
+ */
+    
+    public boolean add(String string) throws DocumentException{
+        if (pause) {
+            return false;
+        }
+        try
+        {
+            write(string);
+            return true;
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+/**
+ * Writes the HTML representation of an element.
+ *
+ * @param   element     the element
+ * @param   indent      the indentation
+ * @throws IOException
+ */
+    
+    protected void write(Element element, int indent) throws IOException {
+        Properties styleAttributes = null;
+        switch(element.type()) {
+            case Element.CHUNK:
+            {
+                Chunk chunk = (Chunk) element;
+                // if the chunk contains an image, return the image representation
+                Image image = chunk.getImage();
+                if (image != null) {
+                    write(image, indent);
+                    return;
+                }
+                
+                if (chunk.isEmpty()) return;
+                HashMap attributes = chunk.getAttributes();
+                if (attributes != null && attributes.get(Chunk.NEWPAGE) != null) {
+                    return;
+                }
+                // This doesn't seem to work:
+                //if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) {
+                //    float p = (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() * 100f) / chunk.font().size();
+                //    styleAttributes = new Properties();
+                //    styleAttributes.setProperty(MarkupTags.CSS_VERTICALALIGN, "" + p + "%");
+                //}
+                boolean tag = isOtherFont(chunk.font()) || hasMarkupAttributes(chunk) || styleAttributes != null;
+                if (tag) {
+                    // start span tag
+                    addTabs(indent);
+                    writeStart(HtmlTags.SPAN);
+                    if (isOtherFont(chunk.font())) {
+                        write(chunk.font(), styleAttributes);
+                    }
+                    if (hasMarkupAttributes(chunk)) {
+                        writeMarkupAttributes((MarkupAttributes)chunk);
+                    }
+                    os.write(GT);
+                }
+                if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) {
+                    // start sup or sub tag
+                    if (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() > 0) {
+                        writeStart(HtmlTags.SUP);
+                    }
+                    else {
+                        writeStart(HtmlTags.SUB);
+                    }
+                    os.write(GT);
+                }
+                // contents
+                write(HtmlEncoder.encode(chunk.content()));
+                if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) {
+                    // end sup or sub tag
+                    os.write(LT);
+                    os.write(FORWARD);
+                    if (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() > 0) {
+                        write(HtmlTags.SUP);
+                    }
+                    else {
+                        write(HtmlTags.SUB);
+                    }
+                    os.write(GT);
+                }
+                if (tag) {
+                    // end tag
+                    writeEnd(MarkupTags.HTML_TAG_SPAN);
+                }
+                return;
+            }
+            case Element.PHRASE:
+            {
+                Phrase phrase = (Phrase) element;
+                styleAttributes = new Properties();
+                if (phrase.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(phrase.leading()) + "pt");
+                
+                // start tag
+                addTabs(indent);
+                writeStart(MarkupTags.HTML_TAG_SPAN);
+                if (hasMarkupAttributes(phrase)) {
+                    writeMarkupAttributes((MarkupAttributes)phrase);
+                }
+                write(phrase.font(), styleAttributes);
+                os.write(GT);
+                currentfont.push(phrase.font());
+                // contents
+                for (Iterator i = phrase.iterator(); i.hasNext(); ) {
+                    write((Element) i.next(), indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(MarkupTags.HTML_TAG_SPAN);
+                currentfont.pop();
+                return;
+            }
+            case Element.ANCHOR:
+            {
+                Anchor anchor = (Anchor) element;
+                styleAttributes = new Properties();
+                if (anchor.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(anchor.leading()) + "pt");
+                
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.ANCHOR);
+                if (anchor.name() != null) {
+                    write(HtmlTags.NAME, anchor.name());
+                }
+                if (anchor.reference() != null) {
+                    write(HtmlTags.REFERENCE, anchor.reference());
+                }
+                if (hasMarkupAttributes(anchor)) {
+                    writeMarkupAttributes((MarkupAttributes)anchor);
+                }
+                write(anchor.font(), styleAttributes);
+                os.write(GT);
+                currentfont.push(anchor.font());
+                // contents
+                for (Iterator i = anchor.iterator(); i.hasNext(); ) {
+                    write((Element) i.next(), indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(HtmlTags.ANCHOR);
+                currentfont.pop();
+                return;
+            }
+            case Element.PARAGRAPH:
+            {
+                Paragraph paragraph = (Paragraph) element;
+                styleAttributes = new Properties();
+                if (paragraph.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(paragraph.leading()) + "pt");
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.DIV);
+                if (hasMarkupAttributes(paragraph)) {
+                    writeMarkupAttributes((MarkupAttributes)paragraph);
+                }
+                String alignment = HtmlEncoder.getAlignment(paragraph.alignment());
+                if (!"".equals(alignment)) {
+                    write(HtmlTags.ALIGN, alignment);
+                }
+                write(paragraph.font(), styleAttributes);
+                os.write(GT);
+                currentfont.push(paragraph.font());
+                // contents
+                for (Iterator i = paragraph.iterator(); i.hasNext(); ) {
+                    write((Element) i.next(), indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(HtmlTags.DIV);
+                currentfont.pop();
+                return;
+            }
+            case Element.SECTION:
+            case Element.CHAPTER:
+            {
+                // part of the start tag + contents
+                writeSection((Section) element, indent);
+                return;
+            }
+            case Element.LIST:
+            {
+                List list = (List) element;
+                // start tag
+                addTabs(indent);
+                if (list.isNumbered()) {
+                    writeStart(HtmlTags.ORDEREDLIST);
+                }
+                else {
+                    writeStart(HtmlTags.UNORDEREDLIST);
+                }
+                if (hasMarkupAttributes(list)) {
+                    writeMarkupAttributes((MarkupAttributes)list);
+                }
+                os.write(GT);
+                // contents
+                for (Iterator i = list.getItems().iterator(); i.hasNext(); ) {
+                    write((Element) i.next(), indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                if (list.isNumbered()) {
+                    writeEnd(HtmlTags.ORDEREDLIST);
+                }
+                else {
+                    writeEnd(HtmlTags.UNORDEREDLIST);
+                }
+                return;
+            }
+            case Element.LISTITEM:
+            {
+                ListItem listItem = (ListItem) element;
+                styleAttributes = new Properties();
+                if (listItem.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(listItem.leading()) + "pt");
+                
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.LISTITEM);
+                if (hasMarkupAttributes(listItem)) {
+                    writeMarkupAttributes((MarkupAttributes)listItem);
+                }
+                write(listItem.font(), styleAttributes);
+                os.write(GT);
+                currentfont.push(listItem.font());
+                // contents
+                for (Iterator i = listItem.iterator(); i.hasNext(); ) {
+                    write((Element) i.next(), indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(HtmlTags.LISTITEM);
+                currentfont.pop();
+                return;
+            }
+            case Element.CELL:
+            {
+                Cell cell = (Cell) element;
+                
+                // start tag
+                addTabs(indent);
+                if (cell.header()) {
+                    writeStart(HtmlTags.HEADERCELL);
+                }
+                else {
+                    writeStart(HtmlTags.CELL);
+                }
+                if (hasMarkupAttributes(cell)) {
+                    writeMarkupAttributes((MarkupAttributes)cell);
+                }
+                if (cell.borderWidth() != Rectangle.UNDEFINED) {
+                    write(HtmlTags.BORDERWIDTH, String.valueOf(cell.borderWidth()));
+                }
+                if (cell.borderColor() != null) {
+                    write(HtmlTags.BORDERCOLOR, HtmlEncoder.encode(cell.borderColor()));
+                }
+                if (cell.backgroundColor() != null) {
+                    write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(cell.backgroundColor()));
+                }
+                String alignment = HtmlEncoder.getAlignment(cell.horizontalAlignment());
+                if (!"".equals(alignment)) {
+                    write(HtmlTags.HORIZONTALALIGN, alignment);
+                }
+                alignment = HtmlEncoder.getAlignment(cell.verticalAlignment());
+                if (!"".equals(alignment)) {
+                    write(HtmlTags.VERTICALALIGN, alignment);
+                }
+                if (cell.cellWidth() != null) {
+                    write(HtmlTags.WIDTH, cell.cellWidth());
+                }
+                if (cell.colspan() != 1) {
+                    write(HtmlTags.COLSPAN, String.valueOf(cell.colspan()));
+                }
+                if (cell.rowspan() != 1) {
+                    write(HtmlTags.ROWSPAN, String.valueOf(cell.rowspan()));
+                }
+                if (cell.noWrap()) {
+                    write(HtmlTags.NOWRAP, String.valueOf(true));
+                }
+                os.write(GT);
+                // contents
+                if (cell.isEmpty()) {
+                    write(NBSP);
+                } else {
+                    for (Iterator i = cell.getElements(); i.hasNext(); ) {
+                        write((Element) i.next(), indent + 1);
+                    }
+                }
+                // end tag
+                addTabs(indent);
+                if (cell.header()) {
+                    writeEnd(HtmlTags.HEADERCELL);
+                }
+                else {
+                    writeEnd(HtmlTags.CELL);
+                }
+                return;
+            }
+            case Element.ROW:
+            {
+                Row row = (Row) element;
+                
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.ROW);
+                if (hasMarkupAttributes(row)) {
+                    writeMarkupAttributes((MarkupAttributes)row);
+                }
+                os.write(GT);
+                // contents
+                Element cell;
+                for (int i = 0; i < row.columns(); i++) {
+                    if ((cell = (Element)row.getCell(i)) != null) {
+                        write(cell, indent + 1);
+                    }
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(HtmlTags.ROW);
+                return;
+            }
+            case Element.TABLE:
+            {
+                Table table = (Table) element;
+                table.complete();
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.TABLE);
+                if (hasMarkupAttributes(table)) {
+                    writeMarkupAttributes((MarkupAttributes)table);
+                }
+                os.write(SPACE);
+                write(HtmlTags.WIDTH);
+                os.write(EQUALS);
+                os.write(QUOTE);
+                if (! "".equals(table.absWidth())){
+                    write(table.absWidth());
+                }
+                else{
+                    write(String.valueOf(table.widthPercentage()));
+                    write("%");
+                }
+                os.write(QUOTE);
+                String alignment = HtmlEncoder.getAlignment(table.alignment());
+                if (!"".equals(alignment)) {
+                    write(HtmlTags.ALIGN, alignment);
+                }
+                write(HtmlTags.CELLPADDING, String.valueOf(table.cellpadding()));
+                write(HtmlTags.CELLSPACING, String.valueOf(table.cellspacing()));
+                if (table.borderWidth() != Rectangle.UNDEFINED) {
+                    write(HtmlTags.BORDERWIDTH, String.valueOf(table.borderWidth()));
+                }
+                if (table.borderColor() != null) {
+                    write(HtmlTags.BORDERCOLOR, HtmlEncoder.encode(table.borderColor()));
+                }
+                if (table.backgroundColor() != null) {
+                    write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(table.backgroundColor()));
+                }
+                os.write(GT);
+                // contents
+                Row row;
+                for (Iterator iterator = table.iterator(); iterator.hasNext(); ) {
+                    row = (Row) iterator.next();
+                    write(row, indent + 1);
+                }
+                // end tag
+                addTabs(indent);
+                writeEnd(HtmlTags.TABLE);
+                return;
+            }
+            case Element.ANNOTATION:
+            {
+                Annotation annotation = (Annotation) element;
+                writeComment(annotation.title() + ": " + annotation.content());
+                if (hasMarkupAttributes(annotation)) {
+                    os.write(BEGINCOMMENT);
+                    writeMarkupAttributes((MarkupAttributes)annotation);
+                    os.write(ENDCOMMENT);
+                }
+                return;
+            }
+            case Element.IMGRAW:
+            case Element.JPEG:
+            case Element.IMGTEMPLATE:
+            {
+                Image image = (Image) element;
+                if (image.url() == null) {
+                    return;
+                }
+                
+                // start tag
+                addTabs(indent);
+                writeStart(HtmlTags.IMAGE);
+                String path = image.url().toString();
+                if (imagepath != null) {
+                    if (path.indexOf("/") > 0) {
+                        path = imagepath + path.substring(path.lastIndexOf("/") + 1);
+                    }
+                    else {
+                        path = imagepath + path;
+                    }
+                }
+                write(HtmlTags.URL, path);
+                if ((image.alignment() & Image.LEFT) > 0) {
+                    write(HtmlTags.ALIGN, HtmlTags.ALIGN_LEFT);
+                }
+                else if ((image.alignment() & Image.RIGHT) > 0) {
+                    write(HtmlTags.ALIGN, HtmlTags.ALIGN_RIGHT);
+                }
+                else if ((image.alignment() & Image.MIDDLE) > 0) {
+                    write(HtmlTags.ALIGN, HtmlTags.ALIGN_MIDDLE);
+                }
+                if (image.alt() != null) {
+                    write(HtmlTags.ALT, image.alt());
+                }
+                write(HtmlTags.PLAINWIDTH, String.valueOf(image.scaledWidth()));
+                write(HtmlTags.PLAINHEIGHT, String.valueOf(image.scaledHeight()));
+                if (hasMarkupAttributes(image)){
+                    writeMarkupAttributes((MarkupAttributes)image);
+                }
+                writeEnd();
+                return;
+            }
+            
+            default:
+                return;
+        }
+    }
+    
+/**
+ * Writes the HTML representation of a section.
+ *
+ * @param   section     the section to write
+ * @param   indent      the indentation
+ * @throws IOException
+ */
+    
+    protected void writeSection(Section section, int indent) throws IOException {
+        if (section.title() != null) {
+            int depth = section.depth() - 1;
+            if (depth > 5) {
+                depth = 5;
+            }
+            Properties styleAttributes = new Properties();
+            if (section.title().leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(section.title().leading()) + "pt");
+            // start tag
+            addTabs(indent);
+            writeStart(HtmlTags.H[depth]);
+            write(section.title().font(), styleAttributes);
+            String alignment = HtmlEncoder.getAlignment(section.title().alignment());
+            if (!"".equals(alignment)) {
+                write(HtmlTags.ALIGN, alignment);
+            }
+            if (hasMarkupAttributes(section.title())) {
+                writeMarkupAttributes((MarkupAttributes)section.title());
+            }
+            os.write(GT);
+            currentfont.push(section.title().font());
+            // contents
+            for (Iterator i = section.title().iterator(); i.hasNext(); ) {
+                write((Element)i.next(), indent + 1);
+            }
+            // end tag
+            addTabs(indent);
+            writeEnd(HtmlTags.H[depth]);
+            currentfont.pop();
+        }
+        for (Iterator i = section.iterator(); i.hasNext(); ) {
+            write((Element) i.next(), indent);
+        }
+    }
+    
+    /**
+     * Writes the representation of a <CODE>Font</CODE>.
+     *
+     * @param font              a <CODE>Font</CODE>
+     * @param styleAttributes   the style of the font
+     * @throws IOException
+     */
+    
+    protected void write(Font font, Properties styleAttributes) throws IOException {
+        if (font == null || !isOtherFont(font) /* || styleAttributes == null*/) return;
+        write(" ");
+        write(HtmlTags.STYLE);
+        write("=\"");
+        if (styleAttributes != null) {
+            String key;
+            for (Enumeration e = styleAttributes.propertyNames(); e.hasMoreElements(); ) {
+                key = (String)e.nextElement();
+                writeCssProperty(key, styleAttributes.getProperty(key));
+            }
+        }
+        if (isOtherFont(font)) {
+            writeCssProperty(MarkupTags.CSS_KEY_FONTFAMILY, font.getFamilyname());
+            
+            if (font.size() != Font.UNDEFINED) {
+                writeCssProperty(MarkupTags.CSS_KEY_FONTSIZE, String.valueOf(font.size()) + "pt");
+            }
+            if (font.color() != null) {
+                writeCssProperty(MarkupTags.CSS_KEY_COLOR, HtmlEncoder.encode(font.color()));
+            }
+            
+            int fontstyle = font.style();
+            if (fontstyle != Font.UNDEFINED && fontstyle != Font.NORMAL) {
+                switch (fontstyle & Font.BOLDITALIC) {
+                    case Font.BOLD:
+                        writeCssProperty(MarkupTags.CSS_KEY_FONTWEIGHT, MarkupTags.CSS_VALUE_BOLD);
+                        break;
+                    case Font.ITALIC:
+                        writeCssProperty(MarkupTags.CSS_KEY_FONTSTYLE, MarkupTags.CSS_VALUE_ITALIC);
+                        break;
+                    case Font.BOLDITALIC:
+                        writeCssProperty(MarkupTags.CSS_KEY_FONTWEIGHT, MarkupTags.CSS_VALUE_BOLD);
+                        writeCssProperty(MarkupTags.CSS_KEY_FONTSTYLE, MarkupTags.CSS_VALUE_ITALIC);
+                        break;
+                }
+                
+                // CSS only supports one decoration tag so if both are specified
+                // only one of the two will display
+                if ((fontstyle & Font.UNDERLINE) > 0) {
+                    writeCssProperty(MarkupTags.CSS_KEY_TEXTDECORATION, MarkupTags.CSS_VALUE_UNDERLINE);
+                }
+                if ((fontstyle & Font.STRIKETHRU) > 0) {
+                    writeCssProperty(MarkupTags.CSS_KEY_TEXTDECORATION, MarkupTags.CSS_VALUE_LINETHROUGH);
+                }
+            }
+        }
+        write("\"");
+    }
+    
+    /**
+     * Writes out a CSS property.
+     * @param prop a CSS property
+     * @param value the value of the CSS property
+     * @throws IOException
+     */
+    protected void writeCssProperty(String prop, String value) throws IOException {
+        write(new StringBuffer(prop).append(": ").append(value).append("; ").toString());
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/ChainedProperties.java b/LibrarySource/com/lowagie/text/html/simpleparser/ChainedProperties.java
new file mode 100644
index 0000000..eb5097a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/ChainedProperties.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ChainedProperties {
+    
+    public final static int fontSizes[] = {8, 10, 12, 14, 18, 24, 36};
+    public ArrayList chain = new ArrayList();
+    
+    /** Creates a new instance of ChainedProperties */
+    public ChainedProperties() {
+    }
+    
+    public String getProperty(String key) {
+        for (int k = chain.size() - 1; k >= 0; --k) {
+            Object obj[] = (Object[])chain.get(k);
+            HashMap prop = (HashMap)obj[1];
+            String ret = (String)prop.get(key);
+            if (ret != null)
+                return ret;
+        }
+        return null;
+    }
+    
+    public boolean hasProperty(String key) {
+        for (int k = chain.size() - 1; k >= 0; --k) {
+            Object obj[] = (Object[])chain.get(k);
+            HashMap prop = (HashMap)obj[1];
+            if (prop.containsKey(key))
+                return true;
+        }
+        return false;
+    }
+    
+    public void addToChain(String key, HashMap prop) {
+        // adjust the font size
+        String value = (String)prop.get("size");
+        if (value != null) {
+            if (value.endsWith("px")) {
+                prop.put("size", value.substring(0, value.length() - 2));
+            }
+            else {
+                int s = 0;
+                if (value.startsWith("+") || value.startsWith("-")) {
+                    String old = getProperty("basefontsize");
+                    if (old == null)
+                        old = "12";
+                    float f = Float.valueOf(old).floatValue();
+                    int c = (int)f;
+                    for (int k = fontSizes.length - 1; k >= 0; --k) {
+                        if (c >= fontSizes[k]) {
+                            s = k;
+                            break;
+                        }
+                    }
+                    int inc = Integer.parseInt(value.startsWith("+") ? value.substring(1) : value);
+                    s += inc;
+                }
+                else
+                    s = Integer.parseInt(value) - 1;
+                if (s < 0)
+                    s = 0;
+                else if (s >= fontSizes.length)
+                    s = fontSizes.length - 1;
+                prop.put("size", Integer.toString(fontSizes[s]));
+            }
+        }
+        chain.add(new Object[]{key, prop});
+    }
+    
+    public void removeChain(String key) {
+        for (int k = chain.size() - 1; k >= 0; --k) {
+            if (key.equals(((Object[])chain.get(k))[0])) {
+                chain.remove(k);
+                return;
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/FactoryProperties.java b/LibrarySource/com/lowagie/text/html/simpleparser/FactoryProperties.java
new file mode 100644
index 0000000..c375c1c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/FactoryProperties.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import headless.awt.Color;
+
+/**
+ *
+ * @author  psoares
+ */
+public class FactoryProperties {
+    
+    /** Creates a new instance of FactoryProperties */
+    public FactoryProperties() {
+    }
+    
+    public static Chunk createChunk(String text, ChainedProperties props) {
+        Chunk ck = new Chunk(text, getFont(props));
+        if (props.hasProperty("sub"))
+            ck.setTextRise(-6);
+        else if (props.hasProperty("sup"))
+            ck.setTextRise(6);
+        return ck;
+    }
+    
+    public static Paragraph createParagraph(HashMap props) {
+        Paragraph p = new Paragraph();
+        String value = (String)props.get("align");
+        if (value != null) {
+            if (value.equalsIgnoreCase("center"))
+                p.setAlignment(Element.ALIGN_CENTER);
+            else if (value.equalsIgnoreCase("right"))
+                p.setAlignment(Element.ALIGN_RIGHT);
+            else if (value.equalsIgnoreCase("justify"))
+                p.setAlignment(Element.ALIGN_JUSTIFIED);
+        }
+        p.setLeading(0, 1.5f);
+        return p;
+    }
+    
+    public static Paragraph createParagraph(ChainedProperties props) {
+        Paragraph p = new Paragraph();
+        String value = props.getProperty("align");
+        if (value != null) {
+            if (value.equalsIgnoreCase("center"))
+                p.setAlignment(Element.ALIGN_CENTER);
+            else if (value.equalsIgnoreCase("right"))
+                p.setAlignment(Element.ALIGN_RIGHT);
+            else if (value.equalsIgnoreCase("justify"))
+                p.setAlignment(Element.ALIGN_JUSTIFIED);
+        }
+        p.setLeading(0, 1.5f);
+        return p;
+    }
+    
+    public static Font getFont(ChainedProperties props) {
+        String face = props.getProperty("face");
+        if (face != null) {
+            StringTokenizer tok = new StringTokenizer(face, ",");
+            while (tok.hasMoreTokens()) {
+                face = tok.nextToken().trim();
+                if (FontFactory.isRegistered(face))
+                    break;
+            }
+        }
+        int style = 0;
+        if (props.hasProperty("i"))
+            style |= Font.ITALIC;
+        if (props.hasProperty("b"))
+            style |= Font.BOLD;
+        if (props.hasProperty("u"))
+            style |= Font.UNDERLINE;
+        String value = props.getProperty("size");
+        float size = 12;
+        if (value != null)
+            size = Float.valueOf(value).floatValue();
+        Color color = decodeColor(props.getProperty("color"));
+        return FontFactory.getFont(face, BaseFont.WINANSI, true, size, style, color);
+    }
+    
+    public static Color decodeColor(String s) {
+        if (s == null)
+            return null;
+        s = s.toLowerCase().trim();
+        Color c = (Color)colorTable.get(s);
+        if (c != null)
+            return c;
+        try {
+            if (s.startsWith("#"))
+                return new Color(Integer.parseInt(s.substring(1), 16));
+        }
+        catch (Exception e) {
+        }
+        return null;
+    }
+    
+    public static HashMap colorTable = new HashMap();
+    public static HashMap followTags = new HashMap();
+    static {
+        followTags.put("i", "i");
+        followTags.put("b", "b");
+        followTags.put("u", "u");
+        followTags.put("sub", "sub");
+        followTags.put("sup", "sup");
+        followTags.put("em", "i");
+        followTags.put("strong", "b");
+        
+        colorTable.put("black", new Color(0x000000));
+        colorTable.put("green", new Color(0x008000));
+        colorTable.put("silver", new Color(0xC0C0C0));
+        colorTable.put("lime", new Color(0x00FF00));
+        colorTable.put("gray", new Color(0x808080));
+        colorTable.put("olive", new Color(0x808000));
+        colorTable.put("white", new Color(0xFFFFFF));
+        colorTable.put("yellow", new Color(0xFFFF00));
+        colorTable.put("maroon", new Color(0x800000));
+        colorTable.put("navy", new Color(0x000080));
+        colorTable.put("red", new Color(0xFF0000));
+        colorTable.put("blue", new Color(0x0000FF));
+        colorTable.put("purple", new Color(0x800080));
+        colorTable.put("teal", new Color(0x008080));
+        colorTable.put("fuchsia", new Color(0xFF00FF));
+        colorTable.put("aqua", new Color(0x00FFFF));
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/HTMLWorker.java b/LibrarySource/com/lowagie/text/html/simpleparser/HTMLWorker.java
new file mode 100644
index 0000000..f5a0f07
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/HTMLWorker.java
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.Stack;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.Reader;
+
+public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
+    
+    public ArrayList objectList;
+    public DocListener document;
+    public Paragraph currentParagraph;
+    public ChainedProperties cprops = new ChainedProperties();
+    public Stack stack = new Stack();
+    public boolean pendingP = false;
+    public boolean pendingTR = false;
+    public boolean pendingTD = false;
+    public boolean pendingLI = false;
+    public StyleSheet style = new StyleSheet();
+    public boolean isPRE = false;
+    public Stack tableState = new Stack();
+    public boolean skipText = false;
+    
+    /** Creates a new instance of HTMLWorker */
+    public HTMLWorker(DocListener document) {
+        this.document = document;
+    }
+    
+    public void setStyleSheet(StyleSheet style) {
+        this.style = style;
+    }
+    
+    public void parse(Reader reader) throws IOException {
+        SimpleXMLParser.parse(this, null, reader, true);
+    }
+    
+    public static ArrayList parseToList(Reader reader, StyleSheet style) throws IOException {
+        HTMLWorker worker = new HTMLWorker(null);
+        if (style != null)
+            worker.style = style;
+        worker.document = worker;
+        worker.objectList = new ArrayList();
+        worker.parse(reader);
+        return worker.objectList;
+    }
+    
+    public void endDocument() {
+        try {
+            for (int k = 0; k < stack.size(); ++k)
+                document.add((Element)stack.elementAt(k));
+            if (currentParagraph != null)
+                document.add(currentParagraph);
+            currentParagraph = null;
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    public void startDocument() {
+        HashMap h = new HashMap();
+        style.applyStyle("body", h);
+        cprops.addToChain("body", h);
+    }
+    
+    public void startElement(String tag, HashMap h) {
+        if (!tagsSupported.containsKey(tag))
+            return;
+        style.applyStyle(tag, h);
+        String follow = (String)FactoryProperties.followTags.get(tag);
+        if (follow != null) {
+            HashMap prop = new HashMap();
+            prop.put(follow, null);
+            cprops.addToChain(follow, prop);
+            return;
+        }
+        if (tag.equals("a")) {
+            cprops.addToChain(tag, h);
+            if (currentParagraph == null)
+                currentParagraph = new Paragraph();
+            stack.push(currentParagraph);
+            currentParagraph = new Paragraph();
+            return;
+        }
+        if (tag.equals("br")) {
+            if (currentParagraph == null)
+                currentParagraph = new Paragraph();
+            currentParagraph.add(FactoryProperties.createChunk("\n", cprops));
+            return;
+        }
+        if (tag.equals("font") || tag.equals("span")) {
+            cprops.addToChain(tag, h);
+            return;
+        }
+        endElement("p");
+        if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
+            if (!h.containsKey("size"))
+                h.put("size", tag.substring(1));
+            cprops.addToChain(tag, h);
+            return;
+        }
+        if (tag.equals("ul")) {
+            if (pendingLI)
+                endElement("li");
+            skipText = true;
+            cprops.addToChain(tag, h);
+            com.lowagie.text.List list = new com.lowagie.text.List(false, 10);
+            list.setListSymbol("\u2022");
+            stack.push(list);
+            return;
+        }
+        if (tag.equals("ol")) {
+            if (pendingLI)
+                endElement("li");
+            skipText = true;
+            cprops.addToChain(tag, h);
+            com.lowagie.text.List list = new com.lowagie.text.List(true, 10);
+            stack.push(list);
+            return;
+        }
+        if (tag.equals("li")) {
+            if (pendingLI)
+                endElement("li");
+            skipText = false;
+            pendingLI = true;
+            cprops.addToChain(tag, h);
+            stack.push(new com.lowagie.text.ListItem());
+            return;
+        }
+        if (tag.equals("div") || tag.equals("body")) {
+            cprops.addToChain(tag, h);
+            return;
+        }
+        if (tag.equals("pre")) {
+            if (!h.containsKey("face")) {
+                h.put("face", "Courier");
+            }
+            cprops.addToChain(tag, h);
+            isPRE = true;
+            return;
+        }
+        if (tag.equals("p")) {
+            cprops.addToChain(tag, h);
+            currentParagraph = FactoryProperties.createParagraph(h);
+            return;
+        }
+        if (tag.equals("tr")) {
+            if (pendingTR)
+                endElement("tr");
+            skipText = true;
+            pendingTR = true;
+            cprops.addToChain("tr", h);
+            return;
+        }
+        if (tag.equals("td") || tag.equals("th")) {
+            if (pendingTD)
+                endElement(tag);
+            skipText = false;
+            pendingTD = true;
+            cprops.addToChain("td", h);
+            stack.push(new IncCell(tag, cprops));
+            return;
+        }
+        if (tag.equals("table")) {
+            cprops.addToChain("table", h);
+            IncTable table = new IncTable(h);
+            stack.push(table);
+            tableState.push(new boolean[]{pendingTR, pendingTD});
+            pendingTR = pendingTD = false;
+            skipText = true;
+            return;
+        }
+    }
+    
+    public void endElement(String tag) {
+        if (!tagsSupported.containsKey(tag))
+            return;
+        try {
+            String follow = (String)FactoryProperties.followTags.get(tag);
+            if (follow != null) {
+                cprops.removeChain(follow);
+                return;
+            }
+            if (tag.equals("font") || tag.equals("span")) {
+                cprops.removeChain(tag);
+                return;
+            }
+            if (tag.equals("a")) {
+                String href = cprops.getProperty("href");
+                if (currentParagraph == null)
+                    currentParagraph = new Paragraph();
+                if (href != null) {
+                    ArrayList chunks = currentParagraph.getChunks();
+                    for (int k = 0; k < chunks.size(); ++k) {
+                        Chunk ck = (Chunk)chunks.get(k);
+                        ck.setAnchor(href);
+                    }
+                }
+                Paragraph tmp = (Paragraph)stack.pop();
+                Phrase tmp2 = new Phrase();
+                tmp2.add(currentParagraph);
+                tmp.add(tmp2);
+                currentParagraph = tmp;
+                cprops.removeChain("a");
+                return;
+            }
+            if (tag.equals("br")) {
+                return;
+            }
+            if (currentParagraph != null) {
+                if (stack.empty())
+                    document.add(currentParagraph);
+                else {
+                    Object obj = stack.pop();
+                    if (obj instanceof TextElementArray) {
+                        TextElementArray current = (TextElementArray)obj;
+                        current.add(currentParagraph);
+                    }
+                    stack.push(obj);
+                }
+            }
+            currentParagraph = null;
+            if (tag.equals("ul") || tag.equals("ol")) {
+                if (pendingLI)
+                    endElement("li");
+                skipText = false;
+                cprops.removeChain(tag);
+                if (stack.empty())
+                    return;
+                Object obj = stack.pop();
+                if (!(obj instanceof com.lowagie.text.List)) {
+                    stack.push(obj);
+                    return;
+                }
+                if (stack.empty())
+                    document.add((Element)obj);
+                else
+                    ((TextElementArray)stack.peek()).add(obj);
+                return;
+            }
+            if (tag.equals("li")) {
+                pendingLI = false;
+                skipText = true;
+                cprops.removeChain(tag);
+                if (stack.empty())
+                    return;
+                Object obj = stack.pop();
+                if (!(obj instanceof ListItem)) {
+                    stack.push(obj);
+                    return;
+                }
+                if (stack.empty()) {
+                    document.add((Element)obj);
+                    return;
+                }
+                Object list = stack.pop();
+                if (!(list instanceof com.lowagie.text.List)) {
+                    stack.push(list);
+                    return;
+                }
+                ListItem item = (ListItem)obj;
+                ((com.lowagie.text.List)list).add(item);
+                ArrayList cks = item.getChunks();
+                if (cks.size() > 0)
+                    item.listSymbol().setFont(((Chunk)cks.get(0)).font());
+                stack.push(list);
+                return;
+            }
+            if (tag.equals("div") || tag.equals("body")) {
+                cprops.removeChain(tag);
+                return;
+            }
+            if (tag.equals("pre")) {
+                cprops.removeChain(tag);
+                isPRE = false;
+                return;
+            }
+            if (tag.equals("p")) {
+                cprops.removeChain(tag);
+                pendingP = false;
+                return;
+            }
+            if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
+                cprops.removeChain(tag);
+                return;
+            }
+            if (tag.equals("table")) {
+                if (pendingTR)
+                    endElement("tr");
+                cprops.removeChain("table");
+                IncTable table = (IncTable) stack.pop();
+                PdfPTable tb = table.buildTable();
+                tb.setSplitRows(true);
+                if (stack.empty())
+                    document.add(tb);
+                else
+                    ((TextElementArray)stack.peek()).add(tb);
+                boolean state[] = (boolean[])tableState.pop();
+                pendingTR = state[0];
+                pendingTD = state[1];
+                skipText = false;
+                return;
+            }
+            if (tag.equals("tr")) {
+                if (pendingTD)
+                    endElement("td");
+                pendingTR = false;
+                cprops.removeChain("tr");
+                ArrayList cells = new ArrayList();
+                IncTable table = null;
+                while (true) {
+                    Object obj = stack.pop();
+                    if (obj instanceof IncCell) {
+                        cells.add(((IncCell)obj).getCell());
+                    }
+                    if (obj instanceof IncTable) {
+                        table = (IncTable)obj;
+                        break;
+                    }
+                }
+                table.addCols(cells);
+                table.endRow();
+                stack.push(table);
+                skipText = true;
+                return;
+            }
+            if (tag.equals("td") || tag.equals("th")) {
+                pendingTD = false;
+                cprops.removeChain("td");
+                skipText = true;
+                return;
+            }
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    public void text(String str) {
+        if (skipText)
+            return;
+        String content = str;
+        if (isPRE) {
+            if (currentParagraph == null)
+                currentParagraph = new Paragraph();
+            currentParagraph.add(FactoryProperties.createChunk(content, cprops));
+            return;
+        }
+        if (content.trim().length() == 0 && content.indexOf(' ') < 0) {
+            return;
+        }
+        
+        StringBuffer buf = new StringBuffer();
+        int len = content.length();
+        char character;
+        boolean newline = false;
+        for (int i = 0; i < len; i++) {
+            switch(character = content.charAt(i)) {
+                case ' ':
+                    if (!newline) {
+                        buf.append(character);
+                    }
+                    break;
+                case '\n':
+                    if (i > 0) {
+                        newline = true;
+                        buf.append(' ');
+                    }
+                    break;
+                case '\r':
+                    break;
+                case '\t':
+                    break;
+                    default:
+                        newline = false;
+                        buf.append(character);
+            }
+        }
+        if (currentParagraph == null)
+            currentParagraph = FactoryProperties.createParagraph(cprops);
+        currentParagraph.add(FactoryProperties.createChunk(buf.toString(), cprops));
+    }
+    
+    public boolean add(Element element) throws DocumentException {
+        objectList.add(element);
+        return true;
+    }
+    
+    public boolean add(Watermark watermark) {
+        return true;
+    }
+    
+    public void clearTextWrap() throws DocumentException {
+    }
+    
+    public void close() {
+    }
+    
+    public boolean newPage() throws DocumentException {
+        return true;
+    }
+    
+    public void open() {
+    }
+    
+    public void removeWatermark() {
+    }
+    
+    public void resetFooter() {
+    }
+    
+    public void resetHeader() {
+    }
+    
+    public void resetPageCount() {
+    }
+    
+    public void setFooter(HeaderFooter footer) {
+    }
+    
+    public void setHeader(HeaderFooter header) {
+    }
+    
+    public boolean setMarginMirroring(boolean marginMirroring) {
+        return true;
+    }
+    
+    public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+        return true;
+    }
+    
+    public void setPageCount(int pageN) {
+    }
+    
+    public boolean setPageSize(Rectangle pageSize) {
+        return true;
+    }
+    
+    public static final String tagsSupportedString = "ol ul li a pre font span br p div body table td th tr i b u sub sup em strong"
+        + " h1 h2 h3 h4 h5 h6";
+    
+    public static final HashMap tagsSupported = new HashMap();
+    
+    static {
+        StringTokenizer tok = new StringTokenizer(tagsSupportedString);
+        while (tok.hasMoreTokens())
+            tagsSupported.put(tok.nextToken(), null);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/IncCell.java b/LibrarySource/com/lowagie/text/html/simpleparser/IncCell.java
new file mode 100644
index 0000000..8c67264
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/IncCell.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.ArrayList;
+/**
+ *
+ * @author  psoares
+ */
+public class IncCell implements TextElementArray {
+    
+    public ArrayList chunks = new ArrayList();
+    public PdfPCell cell;
+    
+    /** Creates a new instance of IncCell */
+    public IncCell(String tag, ChainedProperties props) {
+        cell = new PdfPCell((Phrase)null);
+        String value = props.getProperty("colspan");
+        if (value != null)
+            cell.setColspan(Integer.parseInt(value));
+        value = props.getProperty("align");
+        if (tag.equals("th"))
+            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+        if (value != null) {
+            if ("center".equalsIgnoreCase(value))
+                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+            else if ("right".equalsIgnoreCase(value))
+                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
+            else if ("left".equalsIgnoreCase(value))
+                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
+            else if ("justify".equalsIgnoreCase(value))
+                cell.setHorizontalAlignment(Element.ALIGN_JUSTIFIED);
+        }
+        value = props.getProperty("valign");
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        if (value != null) {
+            if ("top".equalsIgnoreCase(value))
+                cell.setVerticalAlignment(Element.ALIGN_TOP);
+            else if ("bottom".equalsIgnoreCase(value))
+                cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
+        }
+        value = props.getProperty("border");
+        float border = 0;
+        if (value != null)
+            border = Float.valueOf(value).floatValue();
+        cell.setBorderWidth(border);
+        value = props.getProperty("cellpadding");
+        if (value != null)
+            cell.setPadding(Float.valueOf(value).floatValue());
+        cell.setUseDescender(true);
+        value = props.getProperty("bgcolor");
+        cell.setBackgroundColor(FactoryProperties.decodeColor(value));
+    }
+    
+    public boolean add(Object o) {
+        if (!(o instanceof Element))
+            return false;
+        cell.addElement((Element)o);
+        return true;
+    }
+    
+    public ArrayList getChunks() {
+        return chunks;
+    }
+    
+    public boolean process(ElementListener listener) {
+        return true;
+    }
+    
+    public int type() {
+        return 0;
+    }
+    
+    public PdfPCell getCell() {
+        return cell;
+    }    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/IncTable.java b/LibrarySource/com/lowagie/text/html/simpleparser/IncTable.java
new file mode 100644
index 0000000..757f499
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/IncTable.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import com.lowagie.text.pdf.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ *
+ * @author  psoares
+ */
+public class IncTable {
+    public HashMap props = new HashMap();
+    public ArrayList rows = new ArrayList();
+    public ArrayList cols;
+    /** Creates a new instance of IncTable */
+    public IncTable(HashMap props) {
+        this.props.putAll(props);
+    }
+    
+    public void addCol(PdfPCell cell) {
+        if (cols == null)
+            cols = new ArrayList();
+        cols.add(cell);
+    }
+    
+    public void addCols(ArrayList ncols) {
+        if (cols == null)
+            cols = new ArrayList(ncols);
+        else
+            cols.addAll(ncols);
+    }
+    
+    public void endRow() {
+        if (cols != null) {
+            Collections.reverse(cols);
+            rows.add(cols);
+            cols = null;
+        }
+    }
+    
+    public ArrayList getRows() {
+        return rows;
+    }
+    
+    public PdfPTable buildTable() {
+        if (rows.size() == 0)
+            return new PdfPTable(1);
+        int ncol = 0;
+        ArrayList c0 = (ArrayList)rows.get(0);
+        for (int k = 0; k < c0.size(); ++k) {
+            ncol += ((PdfPCell)c0.get(k)).getColspan();
+        }
+        PdfPTable table = new PdfPTable(ncol);
+        String width = (String)props.get("width");
+        if (width == null)
+            table.setWidthPercentage(100);
+        else {
+            if (width.endsWith("%"))
+                table.setWidthPercentage(Float.valueOf(width.substring(0, width.length() - 1)).floatValue());
+            else {
+                table.setTotalWidth(Float.valueOf(width).floatValue());
+                table.setLockedWidth(true);
+            }
+        }
+        for (int row = 0; row < rows.size(); ++row) {
+            ArrayList col = (ArrayList)rows.get(row);
+            for (int k = 0; k < col.size(); ++k) {
+                table.addCell((PdfPCell)col.get(k));
+            }
+        }
+        return table;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/html/simpleparser/StyleSheet.java b/LibrarySource/com/lowagie/text/html/simpleparser/StyleSheet.java
new file mode 100644
index 0000000..1b84b12
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/html/simpleparser/StyleSheet.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.html.simpleparser;
+
+import java.util.HashMap;
+
+public class StyleSheet {
+    
+    public HashMap classMap = new HashMap();
+    public HashMap tagMap = new HashMap();
+    
+    /** Creates a new instance of StyleSheet */
+    public StyleSheet() {
+    }
+    
+    public void applyStyle(String tag, HashMap props) {
+        HashMap map = (HashMap)tagMap.get(tag.toLowerCase());
+        if (map != null) {
+            HashMap temp = new HashMap(map);
+            temp.putAll(props);
+            props.putAll(temp);
+        }
+        String cm = (String)props.get("class");
+        if (cm == null)
+            return;
+        map = (HashMap)classMap.get(cm.toLowerCase());
+        if (map == null)
+            return;
+        props.remove("class");
+        HashMap temp = new HashMap(map);
+        temp.putAll(props);
+        props.putAll(temp);
+    }
+    
+    private void applyMap(HashMap map, HashMap props) {
+        
+    }
+    
+    public void loadStyle(String style, HashMap props) {
+        classMap.put(style.toLowerCase(), props);
+    }
+
+    public void loadStyle(String style, String key, String value) {
+        style = style.toLowerCase();
+        HashMap props = (HashMap)classMap.get(style);
+        if (props == null) {
+            props = new HashMap();
+            classMap.put(style, props);
+        }
+        props.put(key, value);
+    }
+    
+    public void loadTagStyle(String tag, HashMap props) {
+        tagMap.put(tag.toLowerCase(), props);
+    }
+
+    public void loadTagStyle(String tag, String key, String value) {
+        tag = tag.toLowerCase();
+        HashMap props = (HashMap)tagMap.get(tag);
+        if (props == null) {
+            props = new HashMap();
+            tagMap.put(tag, props);
+        }
+        props.put(key, value);
+    }
+
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/markup/MarkupParser.java b/LibrarySource/com/lowagie/text/markup/MarkupParser.java
new file mode 100644
index 0000000..e7b7e3d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/markup/MarkupParser.java
@@ -0,0 +1,567 @@
+/*
+ * $Id: MarkupParser.java,v 1.50 2005/05/03 13:04:18 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.markup;
+
+import headless.awt.Color;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.FontFactory;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+
+/**
+ * This class is a HashMap that contains selectors (String) and styles (a Properties object).
+ * Given a tag and its attributes (id/class), this class can return an iText object with the according style.
+ * 
+ * @author blowagie
+ */
+public class MarkupParser extends HashMap {
+	/**
+	 * HashMap with styles for each known combination of tag/id/class.
+	 * The key is a String-combination, the value a Properties object.
+	 */
+	protected HashMap stylecache = new HashMap();
+	/**
+	 * HashMap with fonts for each known combination of tag/id/class.
+	 * The key is the same String-combination used for the stylecache.
+	 */
+	protected HashMap fontcache = new HashMap();
+	
+// processing CSS
+	
+	/**
+	 * Creates new MarkupParser
+	 * @param file the path to a CSS file.
+	 */
+	 
+	 // the toString() addition in the rethrow in this constructor was added 4 May 2005
+	 // to allow compilation by Code Warrior.  Peter E. Midford peteremidford at yahoo.com
+	public MarkupParser(String file) {
+		super();
+		try {
+			FileReader reader = new FileReader(file);
+			BufferedReader br = new BufferedReader(reader);
+			StringBuffer buf = new StringBuffer();
+			String line;
+			while ((line = br.readLine()) != null) {
+				buf.append(line.trim()); 
+			}
+			String string = buf.toString();
+			string = removeComment(string, "/*", "*/");
+			StringTokenizer tokenizer = new StringTokenizer(string, "}");
+			String tmp;
+			int pos;
+			String selector;
+			String attributes;
+			while (tokenizer.hasMoreTokens()) {
+				tmp = tokenizer.nextToken();
+				pos = tmp.indexOf("{");
+				if (pos > 0) {
+					selector = tmp.substring(0, pos).trim();
+					attributes = tmp.substring(pos + 1).trim();
+					if (attributes.endsWith("}")) attributes = attributes.substring(0, attributes.length() - 1);
+					put(selector, parseAttributes(attributes));
+				}
+			}
+		}
+		catch(Exception e) {
+			throw new RuntimeException(e.toString());   //toString() added to allow compilation
+		}
+	}
+
+	/**
+	 * Removes the comments sections of  a String.
+	 * @param string the original String
+	 * @param startComment the String that marks the start of a Comment section
+	 * @param endComment the String that marks the end of a Comment section.
+	 * @return the String stripped of its comment section
+	 */
+	public static String removeComment(String string, String startComment,
+			String endComment) {
+		StringBuffer result = new StringBuffer();
+		int pos = 0;
+		int end = endComment.length();
+		int start = string.indexOf(startComment, pos);
+		while (start > -1) {
+			result.append(string.substring(pos, start));
+			pos = string.indexOf(endComment, start) + end;
+			start = string.indexOf(startComment, pos);
+		}
+		result.append(string.substring(pos));
+		return result.toString();
+	}
+
+	/**
+	 * This method parses a String with attributes and returns a Properties
+	 * object.
+	 * 
+	 * @param string
+	 *            a String of this form: 'key1="value1"; key2="value2";...
+	 *            keyN="valueN" '
+	 * @return a Properties object
+	 */
+	public static Properties parseAttributes(String string) {
+		Properties result = new Properties();
+		if (string == null)
+			return result;
+		StringTokenizer keyValuePairs = new StringTokenizer(string, ";");
+		StringTokenizer keyValuePair;
+		String key;
+		String value;
+		while (keyValuePairs.hasMoreTokens()) {
+			keyValuePair = new StringTokenizer(keyValuePairs.nextToken(), ":");
+			if (keyValuePair.hasMoreTokens())
+				key = keyValuePair.nextToken().trim();
+			else
+				continue;
+			if (keyValuePair.hasMoreTokens())
+				value = keyValuePair.nextToken().trim();
+			else
+				continue;
+			if (value.startsWith("\""))
+				value = value.substring(1);
+			if (value.endsWith("\""))
+				value = value.substring(0, value.length() - 1);
+			result.setProperty(key, value);
+		}
+		return result;
+	}
+
+// reading attributevalues
+
+	/**
+	 * Parses a length.
+	 * 
+	 * @param string
+	 *            a length in the form of an optional + or -, followed by a
+	 *            number and a unit.
+	 * @return a float
+	 */
+
+	public static float parseLength(String string) {
+		int pos = 0;
+		int length = string.length();
+		boolean ok = true;
+		while (ok && pos < length) {
+			switch (string.charAt(pos)) {
+			case '+':
+			case '-':
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+			case '.':
+				pos++;
+				break;
+			default:
+				ok = false;
+			}
+		}
+		if (pos == 0)
+			return 0f;
+		if (pos == length)
+			return Float.valueOf(string + "f").floatValue();
+		float f = Float.valueOf(string.substring(0, pos) + "f").floatValue();
+		string = string.substring(pos);
+		// inches
+		if (string.startsWith("in")) {
+			return f * 72f;
+		}
+		// centimeters
+		if (string.startsWith("cm")) {
+			return (f / 2.54f) * 72f;
+		}
+		// millimeters
+		if (string.startsWith("mm")) {
+			return (f / 25.4f) * 72f;
+		}
+		// picas
+		if (string.startsWith("pc")) {
+			return f * 12f;
+		}
+		// default: we assume the length was measured in points
+		return f;
+	}
+
+	/**
+	 * Converts a <CODE>Color</CODE> into a HTML representation of this <CODE>
+	 * Color</CODE>.
+	 * 
+	 * @param color
+	 *            the <CODE>Color</CODE> that has to be converted.
+	 * @return the HTML representation of this <COLOR>Color </COLOR>
+	 */
+
+	public static Color decodeColor(String color) {
+		int red = 0;
+		int green = 0;
+		int blue = 0;
+		try {
+			red = Integer.parseInt(color.substring(1, 3), 16);
+			green = Integer.parseInt(color.substring(3, 5), 16);
+			blue = Integer.parseInt(color.substring(5), 16);
+		} catch (Exception sioobe) {
+			// empty on purpose
+		}
+		return new Color(red, green, blue);
+	}
+
+// helper methods
+	
+	/**
+	 * Generates a key for an tag/id/class combination and adds the style attributes to the stylecache.
+	 * @param attributes a Properties object with the tagname and the attributes of the tag.
+	 * @return a key 
+	 */
+	private String getKey(Properties attributes) {
+		String tag = attributes.getProperty(MarkupTags.ITEXT_TAG);
+		String id = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_ID);
+		String cl = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_CLASS);
+		if (id == null) {
+			id = "";
+		}
+		else {
+			id = "#" + id;
+		}
+		if (cl == null) {
+			cl = "";
+		}
+		else {
+			cl = "." + cl;
+		}
+		String key = tag + id + cl;
+		if (!stylecache.containsKey(key) && key.length() > 0) {
+			Properties props = new Properties();
+			Properties tagprops = (Properties)get(tag);
+			Properties idprops = (Properties)get(id);
+			Properties clprops = (Properties)get(cl);
+			Properties tagidprops = (Properties)get(tag + id);
+			Properties tagclprops = (Properties)get(tag + cl);
+			if (tagprops != null) props.putAll(tagprops);
+			if (idprops != null) props.putAll(idprops);
+			if (clprops != null) props.putAll(clprops);
+			if (tagidprops != null) props.putAll(tagidprops);
+			if (tagclprops != null) props.putAll(tagclprops);
+			stylecache.put(key, props);
+		}
+		return key;
+	}
+	
+// getting the objects based on the tag and its attributes
+
+	/** Returns pagebreak information. 
+	 * @param attributes
+	 * @return true if a page break is needed before the tag
+	 */
+	public boolean getPageBreakBefore(Properties attributes) {
+		String key = getKey(attributes);
+		Properties styleattributes = (Properties)stylecache.get(key);
+		if (styleattributes != null && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes.getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_BEFORE))) {
+			return true;
+		}
+		return false;
+	}
+	
+	/** Returns pagebreak information. 
+	 * @param attributes
+	 * @return true if a page break is needed after the tag
+	 */
+	public boolean getPageBreakAfter(Properties attributes) {
+		String key = getKey(attributes);
+		Properties styleattributes = (Properties)stylecache.get(key);
+		if (styleattributes != null && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes.getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_AFTER))) {
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns an object based on a tag and its attributes.
+	 * @param attributes a Properties object with the tagname and the attributes of the tag.
+	 * @return an iText object
+	 */
+	public Element getObject(Properties attributes) {
+		String key = getKey(attributes);
+		Properties styleattributes = (Properties)stylecache.get(key);
+		if (styleattributes != null && MarkupTags.CSS_VALUE_HIDDEN.equals(styleattributes.get(MarkupTags.CSS_KEY_VISIBILITY))) {
+			return null;
+		}
+		String display = styleattributes.getProperty(MarkupTags.CSS_KEY_DISPLAY);
+		Element element = null;
+		if (MarkupTags.CSS_VALUE_INLINE.equals(display)) {
+			element = retrievePhrase(getFont(attributes), styleattributes);
+		}
+		else if (MarkupTags.CSS_VALUE_BLOCK.equals(display)) {
+			element = retrieveParagraph(getFont(attributes), styleattributes);
+		}
+		else if (MarkupTags.CSS_VALUE_LISTITEM.equals(display)) {
+			element = retrieveListItem(getFont(attributes), styleattributes);
+		}
+		else if (MarkupTags.CSS_VALUE_TABLECELL.equals(display)) {
+			element = retrieveTableCell(getFont(attributes), styleattributes);
+		}
+		else if (MarkupTags.CSS_VALUE_TABLE.equals(display)) {
+			element = retrieveTable(styleattributes);
+		}
+		return element;
+	}
+
+	/**
+	 * Returns a font based on the ID and CLASS attributes of a tag.
+	 * @param attributes a Properties object with the tagname and the attributes of the tag.
+	 * @return an iText Font;
+	 */
+	public Font getFont(Properties attributes) {
+		String key = getKey(attributes);
+		Font f = (Font)fontcache.get(key);
+		if (f != null) {
+			return f;
+		}
+		else {
+			Properties styleattributes = (Properties)stylecache.get(key);
+			f = retrieveFont(styleattributes);
+			fontcache.put(key, f);
+		}
+		return f;
+	}
+
+	/**
+	 * Returns a rectangle based on the width and height attributes of a tag,
+	 * can be overridden by the ID and CLASS attributes.
+	 * @param attrs the attributes that came with the tag
+	 * @return an iText Rectangle object
+	 */
+	public Rectangle getRectangle(Properties attrs) {
+		String width = null;
+		String height = null;
+		String key = getKey(attrs);
+		Properties styleattributes = (Properties)stylecache.get(key);
+		if (styleattributes != null) {
+			width = styleattributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+			height = styleattributes.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
+		}
+		if (width == null) width = attrs.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+		if (height == null) height = attrs.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
+		if (width == null || height == null) return null;
+		return new Rectangle(parseLength(width), parseLength(height));
+	}
+	
+// retrieving objects based on the styleAttributes
+	
+	/**
+	 * Retrieves a Phrase based on some style attributes.
+	 * @param font
+	 * @param styleattributes a Properties object containing keys and values
+	 * @return an iText Phrase object
+	 */
+	public Element retrievePhrase(Font font, Properties styleattributes) {
+		Phrase p = new Phrase("", font);
+		if (styleattributes == null) return p;
+		String leading = styleattributes.getProperty(MarkupTags.CSS_KEY_LINEHEIGHT);
+		if (leading != null) {
+			if (leading.endsWith("%")) {
+				p.setLeading(p.font().size() * (parseLength(leading) / 100f));
+			}
+			else {
+				p.setLeading(parseLength(leading));
+			}
+		}
+		return p;
+	}
+
+	/**
+	 * Retrieves a Paragraph based on some style attributes.
+	 * @param font
+	 * @param styleattributes a Properties object containing keys and values
+	 * @return an iText Paragraph object
+	 */
+	public Element retrieveParagraph(Font font, Properties styleattributes) {
+		Paragraph p = new Paragraph((Phrase)retrievePhrase(font, styleattributes));
+		if (styleattributes == null) return p;
+		String margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGIN);
+		float f;
+		if (margin != null) {
+			f = parseLength(margin);
+			p.setIndentationLeft(f);
+			p.setIndentationRight(f);
+			p.setSpacingBefore(f);
+			p.setSpacingAfter(f);
+		}
+		margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINLEFT);
+		if (margin != null) {
+			f = parseLength(margin);
+			p.setIndentationLeft(f);
+		}
+		margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINRIGHT);
+		if (margin != null) {
+			f = parseLength(margin);
+			p.setIndentationRight(f);
+		}
+		margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINTOP);
+		if (margin != null) {
+			f = parseLength(margin);
+			p.setSpacingBefore(f);
+		}
+		margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINBOTTOM);
+		if (margin != null) {
+			f = parseLength(margin);
+			p.setSpacingAfter(f);
+		}
+		String align = styleattributes.getProperty(MarkupTags.CSS_KEY_TEXTALIGN);
+		if (MarkupTags.CSS_VALUE_TEXTALIGNLEFT.equals(align)) {
+			p.setAlignment(Element.ALIGN_LEFT);
+		}
+		else if (MarkupTags.CSS_VALUE_TEXTALIGNRIGHT.equals(align)) {
+			p.setAlignment(Element.ALIGN_RIGHT);
+		}
+		else if (MarkupTags.CSS_VALUE_TEXTALIGNCENTER.equals(align)) {
+			p.setAlignment(Element.ALIGN_CENTER);
+		}
+		else if (MarkupTags.CSS_VALUE_TEXTALIGNJUSTIFY.equals(align)) {
+			p.setAlignment(Element.ALIGN_JUSTIFIED);
+		}
+		return p;
+	}
+	
+	/**
+	 * Gets a table based on the styleattributes.
+	 * @param styleattributes
+	 * @return an iText Table
+	 */
+	private Element retrieveTable(Properties styleattributes) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/**
+	 * Returns a Cell based on the styleattributes.
+	 * @param font
+	 * @param styleattributes
+	 * @return an iText Cell
+	 */
+	private Element retrieveTableCell(Font font, Properties styleattributes) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/**
+	 * Returns a ListItem based on the styleattributes.
+	 * @param font
+	 * @param styleattributes
+	 * @return an iText ListItem
+	 */
+	private Element retrieveListItem(Font font, Properties styleattributes) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+	/**
+	 * Retrieves a font from the FontFactory based on some style attributes.
+	 * Looks for the font-family, font-size, font-weight, font-style and color.
+	 * Takes the default encoding and embedded value.
+	 * @param styleAttributes a Properties object containing keys and values
+	 * @return an iText Font object
+	 */
+	    
+	public Font retrieveFont(Properties styleAttributes) {
+	    String fontname = null;
+	    String encoding = FontFactory.defaultEncoding;
+	    boolean embedded = FontFactory.defaultEmbedding;
+	    float size = Font.UNDEFINED;
+	    int style = Font.NORMAL;
+	    Color color = null;
+	    String value = (String)styleAttributes.get(MarkupTags.CSS_KEY_FONTFAMILY);
+	    if (value != null) {
+	    	if (value.indexOf(",") == -1) {
+	    		fontname = value.trim();
+	    	}
+	        else {
+	        	String tmp;
+	        	while (value.indexOf(",") != -1) {
+	        		tmp = value.substring(0, value.indexOf(",")).trim();
+	        		if (FontFactory.isRegistered(tmp)) {
+	        			fontname = tmp;
+	        			break;
+	        		}
+	        		else {
+	        			value = value.substring(value.indexOf(",") + 1);
+	        		}
+	        	}
+	        }
+	    }
+	    if ((value = (String)styleAttributes.get(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
+	         size = MarkupParser.parseLength(value);
+	    }
+	    if ((value = (String)styleAttributes.get(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
+	        style |= Font.getStyleValue(value);
+	    }
+	    if ((value = (String)styleAttributes.get(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
+	        style |= Font.getStyleValue(value);
+	    }
+	    if ((value = (String)styleAttributes.get(MarkupTags.CSS_KEY_COLOR)) != null) {
+	        color = MarkupParser.decodeColor(value);
+	    }
+	    return FontFactory.getFont(fontname, encoding, embedded, size, style, color);
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/markup/MarkupTags.java b/LibrarySource/com/lowagie/text/markup/MarkupTags.java
new file mode 100644
index 0000000..fd1b193
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/markup/MarkupTags.java
@@ -0,0 +1,233 @@
+/*
+ * $Id: MarkupTags.java,v 1.50 2005/05/03 14:44:38 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.markup;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class MarkupTags {
+	
+	// iText specific
+	
+	/** the key for any tag */
+	public static final String ITEXT_TAG = "tag";
+
+	// HTML tags
+
+	/** the markup for the body part of a file */
+	public static final String HTML_TAG_BODY = "body";
+	
+	/** The DIV tag. */
+	public static final String HTML_TAG_DIV = "div";
+
+	/** This is a possible HTML-tag. */
+	public static final String HTML_TAG_LINK = "link";
+
+	/** The SPAN tag. */
+	public static final String HTML_TAG_SPAN = "span";
+
+	// HTML attributes
+
+	/** the height attribute. */
+	public static final String HTML_ATTR_HEIGHT = "height";
+
+	/** the hyperlink reference attribute. */
+	public static final String HTML_ATTR_HREF = "href";
+
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String HTML_ATTR_REL = "rel";
+
+	/** This is used for inline css style information */
+	public static final String HTML_ATTR_STYLE = "style";
+
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String HTML_ATTR_TYPE = "type";
+
+	/** This is a possible HTML attribute. */
+	public static final String HTML_ATTR_STYLESHEET = "stylesheet";
+
+	/** the width attribute. */
+	public static final String HTML_ATTR_WIDTH = "width";
+
+	/** attribute for specifying externally defined CSS class */
+	public static final String HTML_ATTR_CSS_CLASS = "class";
+
+	/** The ID attribute. */
+	public static final String HTML_ATTR_CSS_ID = "id";
+
+	// HTML values
+	
+	/** This is a possible value for the language attribute (SCRIPT tag). */
+	public static final String HTML_VALUE_JAVASCRIPT = "text/javascript";
+	
+	/** This is a possible HTML attribute for the LINK tag. */
+	public static final String HTML_VALUE_CSS = "text/css";
+
+	// CSS keys
+
+	/** the CSS tag for background color */
+	public static final String CSS_KEY_BGCOLOR = "background-color";
+
+	/** the CSS tag for text color */
+	public static final String CSS_KEY_COLOR = "color";
+
+	/** CSS key that indicate the way something has to be displayed */
+	public static final String CSS_KEY_DISPLAY = "display";
+
+	/** the CSS tag for the font family */
+	public static final String CSS_KEY_FONTFAMILY = "font-family";
+
+	/** the CSS tag for the font size */
+	public static final String CSS_KEY_FONTSIZE = "font-size";
+
+	/** the CSS tag for the font style */
+	public static final String CSS_KEY_FONTSTYLE = "font-style";
+
+	/** the CSS tag for the font weight */
+	public static final String CSS_KEY_FONTWEIGHT = "font-weight";
+
+	/** the CSS tag for text decorations */
+	public static final String CSS_KEY_LINEHEIGHT = "line-height";
+
+	/** the CSS tag for the margin of an object */
+	public static final String CSS_KEY_MARGIN = "margin";
+
+	/** the CSS tag for the margin of an object */
+	public static final String CSS_KEY_MARGINLEFT = "margin-left";
+
+	/** the CSS tag for the margin of an object */
+	public static final String CSS_KEY_MARGINRIGHT = "margin-right";
+
+	/** the CSS tag for the margin of an object */
+	public static final String CSS_KEY_MARGINTOP = "margin-top";
+
+	/** the CSS tag for the margin of an object */
+	public static final String CSS_KEY_MARGINBOTTOM = "margin-bottom";
+
+	/** the CSS tag for adding a page break when the document is printed */
+	public static final String CSS_KEY_PAGE_BREAK_AFTER = "page-break-after";
+
+	/** the CSS tag for adding a page break when the document is printed */
+	public static final String CSS_KEY_PAGE_BREAK_BEFORE = "page-break-before";
+
+	/** the CSS tag for the horizontal alignment of an object */
+	public static final String CSS_KEY_TEXTALIGN = "text-align";
+
+	/** the CSS tag for text decorations */
+	public static final String CSS_KEY_TEXTDECORATION = "text-decoration";
+
+	/** the CSS tag for text decorations */
+	public static final String CSS_KEY_VERTICALALIGN = "vertical-align";
+
+	/** the CSS tag for the visibility of objects */
+	public static final String CSS_KEY_VISIBILITY = "visibility";
+
+	// CSS values
+
+	/** value for the CSS tag for adding a page break when the document is printed */
+	public static final String CSS_VALUE_ALWAYS = "always";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_BLOCK = "block";
+
+	/** a CSS value for text font weight */
+	public static final String CSS_VALUE_BOLD = "bold";
+
+	/** the value if you want to hide objects. */
+	public static final String CSS_VALUE_HIDDEN = "hidden";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_INLINE = "inline";
+	
+	/** a CSS value for text font style */
+	public static final String CSS_VALUE_ITALIC = "italic";
+
+	/** a CSS value for text decoration */
+	public static final String CSS_VALUE_LINETHROUGH = "line-through";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_LISTITEM = "list-item";
+	
+	/** a CSS value */
+	public static final String CSS_VALUE_NONE = "none";
+
+	/** a CSS value */
+	public static final String CSS_VALUE_NORMAL = "normal";
+
+	/** a CSS value for text font style */
+	public static final String CSS_VALUE_OBLIQUE = "oblique";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_TABLE = "table";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_TABLEROW = "table-row";
+
+	/** A possible value for the DISPLAY key */
+	public static final String CSS_VALUE_TABLECELL = "table-cell";
+
+	/** the CSS value for a horizontal alignment of an object */
+	public static final String CSS_VALUE_TEXTALIGNLEFT = "left";
+
+	/** the CSS value for a horizontal alignment of an object */
+	public static final String CSS_VALUE_TEXTALIGNRIGHT = "right";
+
+	/** the CSS value for a horizontal alignment of an object */
+	public static final String CSS_VALUE_TEXTALIGNCENTER = "center";
+
+	/** the CSS value for a horizontal alignment of an object */
+	public static final String CSS_VALUE_TEXTALIGNJUSTIFY = "justify";
+
+	/** a CSS value for text decoration */
+	public static final String CSS_VALUE_UNDERLINE = "underline";
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/ArabicLigaturizer.java b/LibrarySource/com/lowagie/text/pdf/ArabicLigaturizer.java
new file mode 100644
index 0000000..acf451b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ArabicLigaturizer.java
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/** Shape arabic characters. This code was converted from a C version
+ * at www.pango.org.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class ArabicLigaturizer {
+    
+    static boolean isVowel(char s) {
+        return ((s >= 0x064B) && (s <= 0x0655)) || (s == 0x0670);
+    }
+
+    static char charshape(char s, int which)
+    /* which 0=isolated 1=final 2=initial 3=medial */
+    {
+        int l, r, m;
+        if ((s >= 0x0621) && (s <= 0x06D3)) {
+            l = 0;
+            r = chartable.length - 1;
+            while (l <= r) {
+                m = (l + r) / 2;
+                if (s == chartable[m][0]) {
+                    return chartable[m][which + 1];
+                }
+                else if (s < chartable[m][0]) {
+                    r = m - 1;
+                }
+                else {
+                    l = m + 1;
+                }
+            }
+        }
+        else if (s >= 0xfef5 && s <= 0xfefb)
+            return (char)(s + which);
+        return s;
+    }
+
+    static int shapecount(char s) {
+        int l, r, m;
+        if ((s >= 0x0621) && (s <= 0x06D3) && !isVowel(s)) {
+            l = 0;
+            r = chartable.length - 1;
+            while (l <= r) {
+                m = (l + r) / 2;
+                if (s == chartable[m][0]) {
+                    return chartable[m].length - 1;
+                }
+                else if (s < chartable[m][0]) {
+                    r = m - 1;
+                }
+                else {
+                    l = m + 1;
+                }
+            }
+        }
+        else if (s == ZWJ) {
+            return 4;
+        }
+        return 1;
+    }
+    
+    static int ligature(char newchar, charstruct oldchar) {
+    /* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
+        int retval = 0;
+        
+        if (oldchar.basechar == 0)
+            return 0;
+        if (isVowel(newchar)) {
+            retval = 1;
+            if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
+                retval = 2;           /* we eliminate the old vowel .. */
+            }
+            switch (newchar) {
+                case SHADDA:
+                    if (oldchar.mark1 == 0) {
+                        oldchar.mark1 = SHADDA;
+                    }
+                    else {
+                        return 0;         /* no ligature possible */
+                    }
+                    break;
+                case HAMZABELOW:
+                    switch (oldchar.basechar) {
+                        case ALEF:
+                            oldchar.basechar = ALEFHAMZABELOW;
+                            retval = 2;
+                            break;
+                        case LAM_ALEF:
+                            oldchar.basechar = LAM_ALEFHAMZABELOW;
+                            retval = 2;
+                            break;
+                        default:
+                            oldchar.mark1 = HAMZABELOW;
+                            break;
+                    }
+                    break;
+                case HAMZAABOVE:
+                    switch (oldchar.basechar) {
+                        case ALEF:
+                            oldchar.basechar = ALEFHAMZA;
+                            retval = 2;
+                            break;
+                        case LAM_ALEF:
+                            oldchar.basechar = LAM_ALEFHAMZA;
+                            retval = 2;
+                            break;
+                        case WAW:
+                            oldchar.basechar = WAWHAMZA;
+                            retval = 2;
+                            break;
+                        case YEH:
+                        case ALEFMAKSURA:
+                        case FARSIYEH:
+                            oldchar.basechar = YEHHAMZA;
+                            retval = 2;
+                            break;
+                        default:           /* whatever sense this may make .. */
+                            oldchar.mark1 = HAMZAABOVE;
+                            break;
+                    }
+                    break;
+                case MADDA:
+                    switch (oldchar.basechar) {
+                        case ALEF:
+                            oldchar.basechar = ALEFMADDA;
+                            retval = 2;
+                            break;
+                    }
+                    break;
+                default:
+                    oldchar.vowel = newchar;
+                    break;
+            }
+            if (retval == 1) {
+                oldchar.lignum++;
+            }
+            return retval;
+        }
+        if (oldchar.vowel != 0) {  /* if we already joined a vowel, we can't join a Hamza */
+            return 0;
+        }
+        
+        switch (oldchar.basechar) {
+            case LAM:
+                switch (newchar) {
+                    case ALEF:
+                        oldchar.basechar = LAM_ALEF;
+                        oldchar.numshapes = 2;
+                        retval = 3;
+                        break;
+                    case ALEFHAMZA:
+                        oldchar.basechar = LAM_ALEFHAMZA;
+                        oldchar.numshapes = 2;
+                        retval = 3;
+                        break;
+                    case ALEFHAMZABELOW:
+                        oldchar.basechar = LAM_ALEFHAMZABELOW;
+                        oldchar.numshapes = 2;
+                        retval = 3;
+                        break;
+                    case ALEFMADDA:
+                        oldchar.basechar = LAM_ALEFMADDA;
+                        oldchar.numshapes = 2;
+                        retval = 3;
+                        break;
+                }
+                break;
+            case 0:
+                oldchar.basechar = newchar;
+                oldchar.numshapes = shapecount(newchar);
+                retval = 1;
+                break;
+        }
+        return retval;
+    }
+    
+    static void copycstostring(StringBuffer string, charstruct s, int level) {
+    /* s is a shaped charstruct; i is the index into the string */
+        if (s.basechar == 0)
+            return;
+        
+        string.append(s.basechar);
+        s.lignum--;
+        if (s.mark1 != 0) {
+            if ((level & ar_novowel) == 0) {
+                string.append(s.mark1);
+                s.lignum--;
+            }
+            else {
+                s.lignum--;
+            }
+        }
+        if (s.vowel != 0) {
+            if ((level & ar_novowel) == 0) {
+                string.append(s.vowel);
+                s.lignum--;
+            }
+            else {                       /* vowel elimination */
+                s.lignum--;
+            }
+        }
+//        while (s.lignum > 0) {                           /* NULL-insertion for Langbox-font */
+//            string[i] = 0;
+//            i++;
+//            (s.lignum)--;
+//        }
+//        return i;
+    }
+
+    // return len
+    static void doublelig(StringBuffer string, int level)
+    /* Ok. We have presentation ligatures in our font. */
+    {
+        int len;
+        int olen = len = string.length();
+        int j = 0, si = 1;
+        char lapresult;
+        
+        while (si < olen) {
+            lapresult = 0;
+            if ((level & ar_composedtashkeel) != 0) {
+                switch (string.charAt(j)) {
+                    case SHADDA:
+                        switch (string.charAt(si)) {
+                            case KASRA:
+                                lapresult = 0xFC62;
+                                break;
+                            case FATHA:
+                                lapresult = 0xFC60;
+                                break;
+                            case DAMMA:
+                                lapresult = 0xFC61;
+                                break;
+                            case 0x064C:
+                                lapresult = 0xFC5E;
+                                break;
+                            case 0x064D:
+                                lapresult = 0xFC5F;
+                                break;
+                        }
+                        break;
+                    case KASRA:
+                        if (string.charAt(si) == SHADDA)
+                            lapresult = 0xFC62;
+                        break;
+                    case FATHA:
+                        if (string.charAt(si) == SHADDA)
+                            lapresult = 0xFC60;
+                        break;
+                    case DAMMA:
+                        if (string.charAt(si) == SHADDA)
+                            lapresult = 0xFC61;
+                        break;
+                }
+            }
+            
+            if ((level & ar_lig) != 0) {
+                switch (string.charAt(j)) {
+                    case 0xFEDF:       /* LAM initial */
+                        switch (string.charAt(si)) {
+                            case 0xFE9E:
+                                lapresult = 0xFC3F;
+                                break;        /* JEEM final */
+                            case 0xFEA0:
+                                lapresult = 0xFCC9;
+                                break;        /* JEEM medial */
+                            case 0xFEA2:
+                                lapresult = 0xFC40;
+                                break;        /* HAH final */
+                            case 0xFEA4:
+                                lapresult = 0xFCCA;
+                                break;        /* HAH medial */
+                            case 0xFEA6:
+                                lapresult = 0xFC41;
+                                break;        /* KHAH final */
+                            case 0xFEA8:
+                                lapresult = 0xFCCB;
+                                break;        /* KHAH medial */
+                            case 0xFEE2:
+                                lapresult = 0xFC42;
+                                break;        /* MEEM final */
+                            case 0xFEE4:
+                                lapresult = 0xFCCC;
+                                break;        /* MEEM medial */
+                        }
+                        break;
+                    case 0xFE97:       /* TEH inital */
+                        switch (string.charAt(si)) {
+                            case 0xFEA0:
+                                lapresult = 0xFCA1;
+                                break;        /* JEEM medial */
+                            case 0xFEA4:
+                                lapresult = 0xFCA2;
+                                break;        /* HAH medial */
+                            case 0xFEA8:
+                                lapresult = 0xFCA3;
+                                break;        /* KHAH medial */
+                        }
+                        break;
+                    case 0xFE91:       /* BEH inital */
+                        switch (string.charAt(si)) {
+                            case 0xFEA0:
+                                lapresult = 0xFC9C;
+                                break;        /* JEEM medial */
+                            case 0xFEA4:
+                                lapresult = 0xFC9D;
+                                break;        /* HAH medial */
+                            case 0xFEA8:
+                                lapresult = 0xFC9E;
+                                break;        /* KHAH medial */
+                        }
+                        break;
+                    case 0xFEE7:       /* NOON inital */
+                        switch (string.charAt(si)) {
+                            case 0xFEA0:
+                                lapresult = 0xFCD2;
+                                break;        /* JEEM initial */
+                            case 0xFEA4:
+                                lapresult = 0xFCD3;
+                                break;        /* HAH medial */
+                            case 0xFEA8:
+                                lapresult = 0xFCD4;
+                                break;        /* KHAH medial */
+                        }
+                        break;
+                        
+                    case 0xFEE8:       /* NOON medial */
+                        switch (string.charAt(si)) {
+                            case 0xFEAE:
+                                lapresult = 0xFC8A;
+                                break;        /* REH final  */
+                            case 0xFEB0:
+                                lapresult = 0xFC8B;
+                                break;        /* ZAIN final */
+                        }
+                        break;
+                    case 0xFEE3:       /* MEEM initial */
+                        switch (string.charAt(si)) {
+                            case 0xFEA0:
+                                lapresult = 0xFCCE;
+                                break;        /* JEEM medial */
+                            case 0xFEA4:
+                                lapresult = 0xFCCF;
+                                break;        /* HAH medial */
+                            case 0xFEA8:
+                                lapresult = 0xFCD0;
+                                break;        /* KHAH medial */
+                            case 0xFEE4:
+                                lapresult = 0xFCD1;
+                                break;        /* MEEM medial */
+                        }
+                        break;
+                        
+                    case 0xFED3:       /* FEH initial */
+                        switch (string.charAt(si)) {
+                            case 0xFEF2:
+                                lapresult = 0xFC32;
+                                break;        /* YEH final */
+                        }
+                        break;
+                        
+                    default:
+                        break;
+                }                   /* end switch string[si] */
+            }
+            if (lapresult != 0) {
+                string.setCharAt(j, lapresult);
+                len--;
+                si++;                 /* jump over one character */
+                /* we'll have to change this, too. */
+            }
+            else {
+                j++;
+                string.setCharAt(j, string.charAt(si));
+                si++;
+            }
+        }
+        string.setLength(len);
+    }
+
+    static boolean connects_to_left(charstruct a) {
+        return a.numshapes > 2;
+    }
+    
+    static void shape(char text[], StringBuffer string, int level) {
+  /* string is assumed to be empty and big enough.
+   * text is the original text.
+   * This routine does the basic arabic reshaping.
+   * *len the number of non-null characters.
+   *
+   * Note: We have to unshape each character first!
+   */
+        int j = 0;
+        int join;
+        int which;
+        char nextletter;
+        
+        int p = 0;                     /* initialize for output */
+        charstruct oldchar = new charstruct();
+        charstruct curchar = new charstruct();
+        while (p < text.length) {
+            nextletter = text[p++];
+            //nextletter = unshape (nextletter);
+            
+            join = ligature(nextletter, curchar);
+            if (join == 0) {                       /* shape curchar */
+                int nc = shapecount(nextletter);
+                //(*len)++;
+                if (nc == 1) {
+                    which = 0;        /* final or isolated */
+                }
+                else {
+                    which = 2;        /* medial or initial */
+                }
+                if (connects_to_left(oldchar)) {
+                    which++;
+                }
+                
+                which = which % (curchar.numshapes);
+                curchar.basechar = charshape(curchar.basechar, which);
+                
+                /* get rid of oldchar */
+                copycstostring(string, oldchar, level);
+                oldchar = curchar;    /* new values in oldchar */
+                
+                /* init new curchar */
+                curchar = new charstruct();
+                curchar.basechar = nextletter;
+                curchar.numshapes = nc;
+                curchar.lignum++;
+                //          (*len) += unligature (&curchar, level);
+            }
+            else if (join == 1) {
+            }
+            //      else
+            //        {
+            //          (*len) += unligature (&curchar, level);
+            //        }
+            //      p = g_utf8_next_char (p);
+        }
+        
+        /* Handle last char */
+        if (connects_to_left(oldchar))
+            which = 1;
+        else
+            which = 0;
+        which = which % (curchar.numshapes);
+        curchar.basechar = charshape(curchar.basechar, which);
+        
+        /* get rid of oldchar */
+        copycstostring(string, oldchar, level);
+        copycstostring(string, curchar, level);
+    }
+
+    static int arabic_shape(char src[], int srcoffset, int srclength, char dest[], int destoffset, int destlength, int level) {
+        char str[] = new char[srclength];
+        for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
+            str[k - srcoffset] = src[k];
+        StringBuffer string = new StringBuffer(srclength);
+        shape(str, string, level);
+        if ((level & (ar_composedtashkeel | ar_lig)) != 0)
+            doublelig(string, level);
+//        string.reverse();
+        System.arraycopy(string.toString().toCharArray(), 0, dest, destoffset, string.length());
+        return string.length();
+    }
+
+    static void processNumbers(char text[], int offset, int length, int options) {
+        int limit = offset + length;
+        if ((options & DIGITS_MASK) != 0) {
+            char digitBase = '\u0030'; // European digits
+            switch (options & DIGIT_TYPE_MASK) {
+                case DIGIT_TYPE_AN:
+                    digitBase = '\u0660';  // Arabic-Indic digits
+                    break;
+                    
+                case DIGIT_TYPE_AN_EXTENDED:
+                    digitBase = '\u06f0';  // Eastern Arabic-Indic digits (Persian and Urdu)
+                    break;
+                    
+                default:
+                    break;
+            }
+            
+            switch (options & DIGITS_MASK) {
+                case DIGITS_EN2AN: {
+                    int digitDelta = digitBase - '\u0030';
+                    for (int i = offset; i < limit; ++i) {
+                        char ch = text[i];
+                        if (ch <= '\u0039' && ch >= '\u0030') {
+                            text[i] += digitDelta;
+                        }
+                    }
+                }
+                break;
+                
+                case DIGITS_AN2EN: {
+                    char digitTop = (char)(digitBase + 9);
+                    int digitDelta = '\u0030' - digitBase;
+                    for (int i = offset; i < limit; ++i) {
+                        char ch = text[i];
+                        if (ch <= digitTop && ch >= digitBase) {
+                            text[i] += digitDelta;
+                        }
+                    }
+                }
+                break;
+                
+                case DIGITS_EN2AN_INIT_LR:
+                    shapeToArabicDigitsWithContext(text, 0, length, digitBase, false);
+                    break;
+                    
+                case DIGITS_EN2AN_INIT_AL:
+                    shapeToArabicDigitsWithContext(text, 0, length, digitBase, true);
+                    break;
+                    
+                default:
+                    break;
+            }
+        }
+    }
+    
+    static void shapeToArabicDigitsWithContext(char[] dest, int start, int length, char digitBase,  boolean lastStrongWasAL) {
+        digitBase -= '0'; // move common adjustment out of loop
+ 
+        int limit = start + length;
+        for(int i = start; i < limit; ++i) {
+            char ch = dest[i];
+            switch (BidiOrder.getDirection(ch)) {
+            case BidiOrder.L:
+            case BidiOrder.R:
+                lastStrongWasAL = false;
+                break;
+            case BidiOrder.AL:
+                lastStrongWasAL = true;
+                break;
+            case BidiOrder.EN:
+                if (lastStrongWasAL && ch <= '\u0039') {
+                    dest[i] = (char)(ch + digitBase);
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    private static final char ALEF = 0x0627;
+    private static final char ALEFHAMZA = 0x0623;
+    private static final char ALEFHAMZABELOW = 0x0625;
+    private static final char ALEFMADDA = 0x0622;
+    private static final char LAM = 0x0644;
+    private static final char HAMZA = 0x0621;
+    private static final char TATWEEL = 0x0640;
+    private static final char ZWJ = 0x200D;
+
+    private static final char HAMZAABOVE = 0x0654;
+    private static final char HAMZABELOW = 0x0655;
+
+    private static final char WAWHAMZA = 0x0624;
+    private static final char YEHHAMZA = 0x0626;
+    private static final char WAW = 0x0648;
+    private static final char ALEFMAKSURA = 0x0649;
+    private static final char YEH = 0x064A;
+    private static final char FARSIYEH = 0x06CC;
+
+    private static final char SHADDA = 0x0651;
+    private static final char KASRA = 0x0650;
+    private static final char FATHA = 0x064E;
+    private static final char DAMMA = 0x064F;
+    private static final char MADDA = 0x0653;
+
+    private static final char LAM_ALEF = 0xFEFB;
+    private static final char LAM_ALEFHAMZA = 0xFEF7;
+    private static final char LAM_ALEFHAMZABELOW = 0xFEF9;
+    private static final char LAM_ALEFMADDA = 0xFEF5;
+
+    private static final char chartable[][] = {
+        {0x0621, 0xFE80}, /* HAMZA */
+        {0x0622, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE */
+        {0x0623, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE */
+        {0x0624, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE */
+        {0x0625, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW */
+        {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE */
+        {0x0627, 0xFE8D, 0xFE8E}, /* ALEF */
+        {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH */
+        {0x0629, 0xFE93, 0xFE94}, /* TEH MARBUTA */
+        {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH */
+        {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH */
+        {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM */
+        {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH */
+        {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH */
+        {0x062F, 0xFEA9, 0xFEAA}, /* DAL */
+        {0x0630, 0xFEAB, 0xFEAC}, /* THAL */
+        {0x0631, 0xFEAD, 0xFEAE}, /* REH */
+        {0x0632, 0xFEAF, 0xFEB0}, /* ZAIN */
+        {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN */
+        {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN */
+        {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD */
+        {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD */
+        {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH */
+        {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH */
+        {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN */
+        {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN */
+        {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, /* TATWEEL */
+        {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FEH */
+        {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF */
+        {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF */
+        {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM */
+        {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM */
+        {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON */
+        {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH */
+        {0x0648, 0xFEED, 0xFEEE}, /* WAW */
+        {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA */
+        {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH */
+        {0x0671, 0xFB50, 0xFB51}, /* ALEF WASLA */
+        {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69}, /* TTEH */
+        {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* TTEHEH */
+        {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* BEEH */
+        {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* PEH */
+        {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* TEHEH */
+        {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* BEHEH */
+        {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* NYEH */
+        {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* DYEH */
+        {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* TCHEH */
+        {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* TCHEHEH */
+        {0x0688, 0xFB88, 0xFB89}, /* DDAL */
+        {0x068C, 0xFB84, 0xFB85}, /* DAHAL */
+        {0x068D, 0xFB82, 0xFB83}, /* DDAHAL */
+        {0x068E, 0xFB86, 0xFB87}, /* DUL */
+        {0x0691, 0xFB8C, 0xFB8D}, /* RREH */
+        {0x0698, 0xFB8A, 0xFB8B}, /* JEH */
+        {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* VEH */
+        {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* PEHEH */
+        {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* KEHEH */
+        {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* NG */
+        {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* GAF */
+        {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* NGOEH */
+        {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* GUEH */
+        {0x06BA, 0xFB9E, 0xFB9F}, /* NOON GHUNNA */
+        {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* RNOON */
+        {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* HEH DOACHASHMEE */
+        {0x06C0, 0xFBA4, 0xFBA5}, /* HEH WITH YEH ABOVE */
+        {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* HEH GOAL */
+        {0x06C5, 0xFBE0, 0xFBE1}, /* KIRGHIZ OE */
+        {0x06C6, 0xFBD9, 0xFBDA}, /* OE */
+        {0x06C7, 0xFBD7, 0xFBD8}, /* U */
+        {0x06C8, 0xFBDB, 0xFBDC}, /* YU */
+        {0x06C9, 0xFBE2, 0xFBE3}, /* KIRGHIZ YU */
+        {0x06CB, 0xFBDE, 0xFBDF}, /* VE */
+        {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* FARSI YEH */
+        {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
+        {0x06D2, 0xFBAE, 0xFBAF}, /* YEH BARREE */
+        {0x06D3, 0xFBB0, 0xFBB1} /* YEH BARREE WITH HAMZA ABOVE */
+        };
+
+        public static final int ar_nothing  = 0x0;
+        public static final int ar_novowel = 0x1;
+        public static final int ar_composedtashkeel = 0x4;
+        public static final int ar_lig = 0x8;
+        /**
+         * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
+         */
+        public static final int DIGITS_EN2AN = 0x20;
+        
+        /**
+         * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
+         */
+        public static final int DIGITS_AN2EN = 0x40;
+        
+        /**
+         * Digit shaping option:
+         * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+         * if the most recent strongly directional character
+         * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+         * The initial state at the start of the text is assumed to be not an Arabic,
+         * letter, so European digits at the start of the text will not change.
+         * Compare to DIGITS_ALEN2AN_INIT_AL.
+         */
+        public static final int DIGITS_EN2AN_INIT_LR = 0x60;
+        
+        /**
+         * Digit shaping option:
+         * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+         * if the most recent strongly directional character
+         * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+         * The initial state at the start of the text is assumed to be an Arabic,
+         * letter, so European digits at the start of the text will change.
+         * Compare to DIGITS_ALEN2AN_INT_LR.
+         */
+        public static final int DIGITS_EN2AN_INIT_AL = 0x80;
+        
+        /** Not a valid option value. */
+        private static final int DIGITS_RESERVED = 0xa0;
+        
+        /**
+         * Bit mask for digit shaping options.
+         */
+        public static final int DIGITS_MASK = 0xe0;
+        
+        /**
+         * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
+         */
+        public static final int DIGIT_TYPE_AN = 0;
+        
+        /**
+         * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
+         */
+        public static final int DIGIT_TYPE_AN_EXTENDED = 0x100;
+
+        /**
+         * Bit mask for digit type options.
+         */
+        public static final int DIGIT_TYPE_MASK = 0x0100; // 0x3f00?
+
+        static class charstruct {
+            char basechar;
+            char mark1;               /* has to be initialized to zero */
+            char vowel;
+            int lignum;           /* is a ligature with lignum aditional characters */
+            int numshapes = 1;
+        };
+
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/AsianFontMapper.java b/LibrarySource/com/lowagie/text/pdf/AsianFontMapper.java
new file mode 100644
index 0000000..b86c6de
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/AsianFontMapper.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2004 by Takenori.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import headless.awt.Font;
+
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.DefaultFontMapper;
+
+public class AsianFontMapper extends DefaultFontMapper {
+	
+	public static String ChineseSimplifiedFont = "STSong-Light";
+	public static String ChineseSimplifiedEncoding_H = "UniGB-UCS2-H";
+	public static String ChineseSimplifiedEncoding_V = "UniGB-UCS2-V";
+	
+	public static String ChineseTraditionalFont_MHei = "MHei-Medium";
+	public static String ChineseTraditionalFont_MSung = "MSung-Light";
+	public static String ChineseTraditionalEncoding_H = "UniCNS-UCS2-H";
+	public static String ChineseTraditionalEncoding_V = "UniCNS-UCS2-V";
+	
+	public static String JapaneseFont_Go = "HeiseiKakuGo-W5";
+	public static String JapaneseFont_Min = "HeiseiMin-W3";
+	public static String JapaneseEncoding_H = "UniJIS-UCS2-H";
+	public static String JapaneseEncoding_V = "UniJIS-UCS2-V";
+	public static String JapaneseEncoding_HW_H = "UniJIS-UCS2-HW-H";
+	public static String JapaneseEncoding_HW_V = "UniJIS-UCS2-HW-V";
+	
+	public static String KoreanFont_GoThic = "HYGoThic-Medium";
+	public static String KoreanFont_SMyeongJo = "HYSMyeongJo-Medium";
+	public static String KoreanEncoding_H = "UniKS-UCS2-H";
+	public static String KoreanEncoding_V = "UniKS-UCS2-V";
+	
+	private String defaultFont;
+	private String encoding;
+
+	public AsianFontMapper(String font, String encoding) {
+		super();
+		
+		this.defaultFont = font;
+		this.encoding = encoding;
+	}
+
+	public BaseFont awtToPdf(Font font) {
+		try {
+			BaseFontParameters p = getBaseFontParameters(font.getFontName());
+			if (p != null){
+				return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
+			}else{
+				return BaseFont.createFont(defaultFont, encoding, true);
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+
+	}
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/BadPdfFormatException.java b/LibrarySource/com/lowagie/text/pdf/BadPdfFormatException.java
new file mode 100644
index 0000000..39a7250
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/BadPdfFormatException.java
@@ -0,0 +1,86 @@
+/*
+ * $Id: BadPdfFormatException.java,v 1.22 2002/06/18 13:59:39 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * Signals that a bad PDF format has been used to construct a <CODE>PdfObject</CODE>.
+ *
+ * @see		PdfException
+ * @see		PdfBoolean
+ * @see		PdfNumber
+ * @see		PdfString
+ * @see		PdfName
+ * @see		PdfDictionary
+ * @see		PdfFont
+ */
+
+public class BadPdfFormatException extends PdfException {
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>BadPdfFormatException</CODE> whithout a message.
+ */
+    
+    BadPdfFormatException() {
+        super();
+    }
+    
+/**
+ * Constructs a <code>BadPdfFormatException</code> with a message.
+ *
+ * @param		message			a message describing the exception
+ */
+    
+    BadPdfFormatException(String message) {
+        super(message);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/BaseField.java b/LibrarySource/com/lowagie/text/pdf/BaseField.java
new file mode 100644
index 0000000..fbe2593
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/BaseField.java
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ * Mesquite specific changes/deletions copyright 2005 Peter E. Midford
+ * peteremidford at yahoo.com.  Mesquite itself is copyright 1997-2005 by W. and D.
+ * Maddison and licensed under the LGPL.
+ * 
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import com.lowagie.text.Element;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Rectangle;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/** Common field variables.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public abstract class BaseField {
+    
+    /** A thin border with 1 point width. */    
+    public static final float BORDER_WIDTH_THIN = 1;
+    /** A medium border with 2 point width. */    
+    public static final float BORDER_WIDTH_MEDIUM = 2;
+    /** A thick border with 3 point width. */    
+    public static final float BORDER_WIDTH_THICK = 3;
+    /** The field is visible. */    
+    public static final int VISIBLE = 0;
+    /** The field is hidden. */    
+    public static final int HIDDEN = 1;
+    /** The field is visible but does not print. */    
+    public static final int VISIBLE_BUT_DOES_NOT_PRINT = 2;
+    /** The field is hidden but is printable. */    
+    public static final int HIDDEN_BUT_PRINTABLE = 3;
+    /** The user may not change the value of the field. */    
+    public static final int READ_ONLY = 1;
+    /** The field must have a value at the time it is exported by a submit-form
+     * action.
+     */    
+    public static final int REQUIRED = 2;
+    /** The field may contain multiple lines of text.
+     * This flag is only meaningful with text fields.
+     */    
+    public static final int MULTILINE = 4;
+    /** The field will not scroll (horizontally for single-line
+     * fields, vertically for multiple-line fields) to accommodate more text
+     * than will fit within its annotation rectangle. Once the field is full, no
+     * further text will be accepted.
+     */    
+    public static final int DO_NOT_SCROLL = 8;
+    /** The field is intended for entering a secure password that should
+     * not be echoed visibly to the screen.
+     */    
+    public static final int PASSWORD = 16;
+    /** The text entered in the field represents the pathname of
+     * a file whose contents are to be submitted as the value of the field.
+     */    
+    public static final int FILE_SELECTION = 32;
+    /** The text entered in the field will not be spell-checked.
+     * This flag is meaningful only in text fields and in combo
+     * fields with the <CODE>EDIT</CODE> flag set.
+     */    
+    public static final int DO_NOT_SPELL_CHECK = 64;
+    /** If set the combo box includes an editable text box as well as a drop list; if
+     * clear, it includes only a drop list.
+     * This flag is only meaningful with combo fields.
+     */    
+    public static final int EDIT = 128;
+
+    /**
+     * combo box flag.
+     */
+    public static final int COMB = 256;
+
+    protected float borderWidth = BORDER_WIDTH_THIN;
+    protected int borderStyle = PdfBorderDictionary.STYLE_SOLID;
+    protected Color borderColor;
+    protected Color backgroundColor;
+    protected Color textColor;
+    protected BaseFont font;
+    protected float fontSize = 0;
+    protected int alignment = Element.ALIGN_LEFT;
+    protected PdfWriter writer;
+    protected String text;
+    protected Rectangle box;
+    
+    /** Holds value of property rotation. */
+    protected int rotation = 0;
+    
+    /** Holds value of property visibility. */
+    protected int visibility;
+    
+    /** Holds value of property fieldName. */
+    protected String fieldName;
+    
+    /** Holds value of property options. */
+    protected int options;
+    
+    /** Holds value of property maxCharacterLength. */
+    protected int maxCharacterLength;
+    
+    private final static HashMap fieldKeys = new HashMap();
+ 
+    static {
+        Integer one = new Integer(1);
+        fieldKeys.put(PdfName.AA, one);
+        fieldKeys.put(PdfName.FT, one);
+        fieldKeys.put(PdfName.TU, one);
+        fieldKeys.put(PdfName.TM, one);
+        fieldKeys.put(PdfName.FF, one);
+        fieldKeys.put(PdfName.V, one);
+        fieldKeys.put(PdfName.DV, one);
+        fieldKeys.put(PdfName.DS, one);
+        fieldKeys.put(PdfName.RV, one);
+        fieldKeys.put(PdfName.OPT, one);
+        fieldKeys.put(PdfName.MAXLEN, one);
+        fieldKeys.put(PdfName.TI, one);
+        fieldKeys.put(PdfName.I, one);
+        fieldKeys.put(PdfName.LOCK, one);
+        fieldKeys.put(PdfName.SV, one);
+		//fieldKeys.putAll(PdfCopyFieldsImp.fieldKeys);  // removed for Mesquite support 25 September 2005 P. E. Midford
+        fieldKeys.put(PdfName.T, one);
+    }
+    /** Creates a new <CODE>TextField</CODE>.
+     * @param writer the document <CODE>PdfWriter</CODE>
+     * @param box the field location and dimensions
+     * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
+     * will be included in the field allowing it to be used as a kid field.
+     */
+    public BaseField(PdfWriter writer, Rectangle box, String fieldName) {
+        this.writer = writer;
+        this.box = box;
+        this.fieldName = fieldName;
+    }
+    
+    protected BaseFont getRealFont() throws IOException, DocumentException {
+        if (font == null)
+            return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
+        else
+            return font;
+    }
+    
+    protected PdfAppearance getBorderAppearance() throws IOException, DocumentException {
+        PdfAppearance app = writer.getDirectContent().createAppearance(box.width(), box.height());
+        switch (rotation) {
+            case 90:
+                app.setMatrix(0, 1, -1, 0, box.height(), 0);
+                break;
+            case 180:
+                app.setMatrix(-1, 0, 0, -1, box.width(), box.height());
+                break;
+            case 270:
+                app.setMatrix(0, -1, 1, 0, 0, box.width());
+                break;
+        }
+        // background
+        if (backgroundColor != null) {
+            app.setColorFill(backgroundColor);
+            app.rectangle(0, 0, box.width(), box.height());
+            app.fill();
+        }
+        // border
+        if (borderStyle == PdfBorderDictionary.STYLE_UNDERLINE) {
+            if (borderWidth != 0 && borderColor != null) {
+                app.setColorStroke(borderColor);
+                app.setLineWidth(borderWidth);
+                app.moveTo(0, borderWidth / 2);
+                app.lineTo(box.width(), borderWidth / 2);
+                app.stroke();
+            }
+        }
+        else if (borderStyle == PdfBorderDictionary.STYLE_BEVELED) {
+            if (borderWidth != 0 && borderColor != null) {
+                app.setColorStroke(borderColor);
+                app.setLineWidth(borderWidth);
+                app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+                app.stroke();
+            }
+            // beveled
+            Color actual = backgroundColor;
+            if (actual == null)
+                actual = Color.white;
+            app.setGrayFill(1);
+            drawTopFrame(app);
+            app.setColorFill(actual.darker());
+            drawBottomFrame(app);
+        }
+        else if (borderStyle == PdfBorderDictionary.STYLE_INSET) {
+            if (borderWidth != 0 && borderColor != null) {
+                app.setColorStroke(borderColor);
+                app.setLineWidth(borderWidth);
+                app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+                app.stroke();
+            }
+            // inset
+            app.setGrayFill(0.5f);
+            drawTopFrame(app);
+            app.setGrayFill(0.75f);
+            drawBottomFrame(app);
+        }
+        else {
+            if (borderWidth != 0 && borderColor != null) {
+                if (borderStyle == PdfBorderDictionary.STYLE_DASHED)
+                    app.setLineDash(3, 0);
+                app.setColorStroke(borderColor);
+                app.setLineWidth(borderWidth);
+                app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+                app.stroke();
+                if ((options & COMB) != 0 && maxCharacterLength > 1) {
+                    float step = box.width() / maxCharacterLength;
+                    float yb = borderWidth / 2;
+                    float yt = box.height() - borderWidth / 2;
+                    for (int k = 1; k < maxCharacterLength; ++k) {
+                        float x = step * k;
+                        app.moveTo(x, yb);
+                        app.lineTo(x, yt);
+                    }
+                    app.stroke();
+                }
+            }
+        }
+        return app;
+    }
+    
+    protected static ArrayList getHardBreaks(String text) {
+        ArrayList arr = new ArrayList();
+        char cs[] = text.toCharArray();
+        int len = cs.length;
+        StringBuffer buf = new StringBuffer();
+        for (int k = 0; k < len; ++k) {
+            char c = cs[k];
+            if (c == '\r') {
+                if (k + 1 < len && cs[k + 1] == '\n')
+                    ++k;
+                arr.add(buf.toString());
+                buf = new StringBuffer();
+            }
+            else if (c == '\n') {
+                arr.add(buf.toString());
+                buf = new StringBuffer();
+            }
+            else
+                buf.append(c);
+        }
+        arr.add(buf.toString());
+        return arr;
+    }
+    
+    protected static void trimRight(StringBuffer buf) {
+        int len = buf.length();
+        while (true) {
+            if (len == 0)
+                return;
+            if (buf.charAt(--len) != ' ')
+                return;
+            buf.setLength(len);
+        }
+    }
+    
+    protected static ArrayList breakLines(ArrayList breaks, BaseFont font, float fontSize, float width) {
+        ArrayList lines = new ArrayList();
+        StringBuffer buf = new StringBuffer();
+        for (int ck = 0; ck < breaks.size(); ++ck) {
+            buf.setLength(0);
+            float w = 0;
+            char cs[] = ((String)breaks.get(ck)).toCharArray();
+            int len = cs.length;
+            // 0 inline first, 1 inline, 2 spaces
+            int state = 0;
+            int lastspace = -1;
+            char c = 0;
+            int refk = 0;
+            for (int k = 0; k < len; ++k) {
+                c = cs[k];
+                switch (state) {
+                    case 0:
+                        w += font.getWidthPoint(c, fontSize);
+                        buf.append(c);
+                        if (w > width) {
+                            w = 0;
+                            if (buf.length() > 1) {
+                                --k;
+                                buf.setLength(buf.length() - 1);
+                            }
+                            lines.add(buf.toString());
+                            buf.setLength(0);
+                            refk = k;
+                            if (c == ' ')
+                                state = 2;
+                            else
+                                state = 1;
+                        }
+                        else {
+                            if (c != ' ')
+                                state = 1;
+                        }
+                        break;
+                    case 1:
+                        w += font.getWidthPoint(c, fontSize);
+                        buf.append(c);
+                        if (c == ' ')
+                            lastspace = k;
+                        if (w > width) {
+                            w = 0;
+                            if (lastspace >= 0) {
+                                k = lastspace;
+                                buf.setLength(lastspace - refk);
+                                trimRight(buf);
+                                lines.add(buf.toString());
+                                buf.setLength(0);
+                                refk = k;
+                                lastspace = -1;
+                                state = 2;
+                            }
+                            else {
+                                if (buf.length() > 1) {
+                                    --k;
+                                    buf.setLength(buf.length() - 1);
+                                }
+                                lines.add(buf.toString());
+                                buf.setLength(0);
+                                refk = k;
+                                if (c == ' ')
+                                    state = 2;
+                            }
+                        }
+                        break;
+                    case 2:
+                        if (c != ' ') {
+                            w = 0;
+                            --k;
+                            state = 1;
+                        }
+                        break;
+                }
+            }
+            trimRight(buf);
+            lines.add(buf.toString());
+        }
+        return lines;
+    }
+        
+    private void drawTopFrame(PdfAppearance app) {
+        app.moveTo(borderWidth, borderWidth);
+        app.lineTo(borderWidth, box.height() - borderWidth);
+        app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
+        app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
+        app.lineTo(2 * borderWidth, box.height() - 2 * borderWidth);
+        app.lineTo(2 * borderWidth, 2 * borderWidth);
+        app.lineTo(borderWidth, borderWidth);
+        app.fill();
+    }
+    
+    private void drawBottomFrame(PdfAppearance app) {
+        app.moveTo(borderWidth, borderWidth);
+        app.lineTo(box.width() - borderWidth, borderWidth);
+        app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
+        app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
+        app.lineTo(box.width() - 2 * borderWidth, 2 * borderWidth);
+        app.lineTo(2 * borderWidth, 2 * borderWidth);
+        app.lineTo(borderWidth, borderWidth);
+        app.fill();
+    }
+    /** Gets the border width in points.
+     * @return the border width in points
+     */
+    public float getBorderWidth() {
+        return this.borderWidth;
+    }
+    
+    /** Sets the border width in points. To eliminate the border
+     * set the border color to <CODE>null</CODE>.
+     * @param borderWidth the border width in points
+     */
+    public void setBorderWidth(float borderWidth) {
+        this.borderWidth = borderWidth;
+    }
+    
+    /** Gets the border style.
+     * @return the border style
+     */
+    public int getBorderStyle() {
+        return this.borderStyle;
+    }
+    
+    /** Sets the border style. The styles are found in <CODE>PdfBorderDictionary</CODE>
+     * and can be <CODE>STYLE_SOLID</CODE>, <CODE>STYLE_DASHED</CODE>,
+     * <CODE>STYLE_BEVELED</CODE>, <CODE>STYLE_INSET</CODE> and
+     * <CODE>STYLE_UNDERLINE</CODE>.
+     * @param borderStyle the border style
+     */
+    public void setBorderStyle(int borderStyle) {
+        this.borderStyle = borderStyle;
+    }
+    
+    /** Gets the border color.
+     * @return the border color
+     */
+    public Color getBorderColor() {
+        return this.borderColor;
+    }
+    
+    /** Sets the border color. Set to <CODE>null</CODE> to remove
+     * the border.
+     * @param borderColor the border color
+     */
+    public void setBorderColor(Color borderColor) {
+        this.borderColor = borderColor;
+    }
+    
+    /** Gets the background color.
+     * @return the background color
+     */
+    public Color getBackgroundColor() {
+        return this.backgroundColor;
+    }
+    
+    /** Sets the background color. Set to <CODE>null</CODE> for
+     * transparent background.
+     * @param backgroundColor the background color
+     */
+    public void setBackgroundColor(Color backgroundColor) {
+        this.backgroundColor = backgroundColor;
+    }
+    
+    /** Gets the text color.
+     * @return the text color
+     */
+    public Color getTextColor() {
+        return this.textColor;
+    }
+    
+    /** Sets the text color. If <CODE>null</CODE> the color used
+     * will be black.
+     * @param textColor the text color
+     */
+    public void setTextColor(Color textColor) {
+        this.textColor = textColor;
+    }
+    
+    /** Gets the text font.
+     * @return the text font
+     */
+    public BaseFont getFont() {
+        return this.font;
+    }
+    
+    /** Sets the text font. If <CODE>null</CODE> then Helvetica
+     * will be used.
+     * @param font the text font
+     */
+    public void setFont(BaseFont font) {
+        this.font = font;
+    }
+    
+    /** Gets the font size.
+     * @return the font size
+     */
+    public float getFontSize() {
+        return this.fontSize;
+    }
+    
+    /** Sets the font size. If 0 then auto-sizing will be used but
+     * only for text fields.
+     * @param fontSize the font size
+     */
+    public void setFontSize(float fontSize) {
+        this.fontSize = fontSize;
+    }
+    
+    /** Gets the text horizontal alignment.
+     * @return the text horizontal alignment
+     */
+    public int getAlignment() {
+        return this.alignment;
+    }
+    
+    /** Sets the text horizontal alignment. It can be <CODE>Element.ALIGN_LEFT</CODE>,
+     * <CODE>Element.ALIGN_CENTER</CODE> and <CODE>Element.ALIGN_RIGHT</CODE>.
+     * @param alignment the text horizontal alignment
+     */
+    public void setAlignment(int alignment) {
+        this.alignment = alignment;
+    }
+    
+    /** Gets the text.
+     * @return the text
+     */
+    public String getText() {
+        return this.text;
+    }
+    
+    /** Sets the text for text fields.
+     * @param text the text
+     */
+    public void setText(String text) {
+        this.text = text;
+    }
+    
+    /** Gets the field dimension and position.
+     * @return the field dimension and position
+     */
+    public Rectangle getBox() {
+        return this.box;
+    }
+    
+    /** Sets the field dimension and position.
+     * @param box the field dimension and position
+     */
+    public void setBox(Rectangle box) {
+        this.box = box;
+    }
+    
+    /** Gets the field rotation.
+     * @return the field rotation
+     */
+    public int getRotation() {
+        return this.rotation;
+    }
+    
+    /** Sets the field rotation. This value should be the same as
+     * the page rotation where the field will be shown.
+     * @param rotation the field rotation
+     */
+    public void setRotation(int rotation) {
+        if (rotation % 90 != 0)
+            throw new IllegalArgumentException("Rotation must be a multiple of 90.");
+        rotation %= 360;
+        if (rotation < 0)
+            rotation += 360;
+        this.rotation = rotation;
+    }
+    
+    /** Convenience method to set the field rotation the same as the
+     * page rotation.
+     * @param page the page
+     */    
+    public void setRotationFromPage(Rectangle page) {
+        setRotation(page.getRotation());
+    }
+    
+    /** Gets the field visibility flag.
+     * @return the field visibility flag
+     */
+    public int getVisibility() {
+        return this.visibility;
+    }
+    
+    /** Sets the field visibility flag. This flags can be one of
+     * <CODE>VISIBLE</CODE>, <CODE>HIDDEN</CODE>, <CODE>VISIBLE_BUT_DOES_NOT_PRINT</CODE>
+     * and <CODE>HIDDEN_BUT_PRINTABLE</CODE>.
+     * @param visibility field visibility flag
+     */
+    public void setVisibility(int visibility) {
+        this.visibility = visibility;
+    }
+    
+    /** Gets the field name.
+     * @return the field name
+     */
+    public String getFieldName() {
+        return this.fieldName;
+    }
+    
+    /** Sets the field name.
+     * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
+     * will be included in the field allowing it to be used as a kid field.
+     */
+    public void setFieldName(String fieldName) {
+        this.fieldName = fieldName;
+    }
+    
+    /** Gets the option flags.
+     * @return the option flags
+     */
+    public int getOptions() {
+        return this.options;
+    }
+    
+    /** Sets the option flags. The option flags can be a combination by oring of
+     * <CODE>READ_ONLY</CODE>, <CODE>REQUIRED</CODE>,
+     * <CODE>MULTILINE</CODE>, <CODE>DO_NOT_SCROLL</CODE>,
+     * <CODE>PASSWORD</CODE>, <CODE>FILE_SELECTION</CODE>,
+     * <CODE>DO_NOT_SPELL_CHECK</CODE> and <CODE>EDIT</CODE>.
+     * @param options the option flags
+     */
+    public void setOptions(int options) {
+        this.options = options;
+    }
+    
+    /** Gets the maximum length of the field�s text, in characters.
+     * @return the maximum length of the field�s text, in characters.
+     */
+    public int getMaxCharacterLength() {
+        return this.maxCharacterLength;
+    }
+    
+    /** Sets the maximum length of the field�s text, in characters.
+     * It is only meaningful for text fields.
+     * @param maxCharacterLength the maximum length of the field�s text, in characters
+     */
+    public void setMaxCharacterLength(int maxCharacterLength) {
+        this.maxCharacterLength = maxCharacterLength;
+    }
+    
+    /**
+     * Getter for property writer.
+     * @return Value of property writer.
+     */
+    public PdfWriter getWriter() {
+        return writer;
+    }
+    
+    /**
+     * Setter for property writer.
+     * @param writer New value of property writer.
+     */
+    public void setWriter(PdfWriter writer) {
+        this.writer = writer;
+    }
+    
+    /**
+     * Moves the field keys from <CODE>from</CODE> to <CODE>to</CODE>. The moved keys
+     * are removed from <CODE>from</CODE>.
+     * @param from the source
+     * @param to the destination. It may be <CODE>null</CODE>
+     */    
+    public static void moveFields(PdfDictionary from, PdfDictionary to) {
+        for (Iterator i = from.getKeys().iterator(); i.hasNext();) {
+            PdfName key = (PdfName)i.next();
+            if (fieldKeys.containsKey(key)) {
+                if (to != null)
+                    to.put(key, from.get(key));
+                i.remove();
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/BaseFont.java b/LibrarySource/com/lowagie/text/pdf/BaseFont.java
new file mode 100644
index 0000000..ddedefe
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/BaseFont.java
@@ -0,0 +1,1094 @@
+/*
+ * $Id: BaseFont.java,v 1.65 2005/04/05 12:48:09 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.*;
+import com.lowagie.text.DocumentException;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Base class for the several font types supported
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public abstract class BaseFont {
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER = "Courier";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_BOLD = "Courier-Bold";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_OBLIQUE = "Courier-Oblique";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String COURIER_BOLDOBLIQUE = "Courier-BoldOblique";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA = "Helvetica";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_BOLD = "Helvetica-Bold";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_OBLIQUE = "Helvetica-Oblique";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String HELVETICA_BOLDOBLIQUE = "Helvetica-BoldOblique";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String SYMBOL = "Symbol";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_ROMAN = "Times-Roman";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_BOLD = "Times-Bold";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_ITALIC = "Times-Italic";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String TIMES_BOLDITALIC = "Times-BoldItalic";
+    
+    /** This is a possible value of a base 14 type 1 font */
+    public static final String ZAPFDINGBATS = "ZapfDingbats";
+    
+    /** The maximum height above the baseline reached by glyphs in this
+     * font, excluding the height of glyphs for accented characters.
+     */    
+    public static final int ASCENT = 1;    
+    /** The y coordinate of the top of flat capital letters, measured from
+     * the baseline.
+     */    
+    public static final int CAPHEIGHT = 2;
+    /** The maximum depth below the baseline reached by glyphs in this
+     * font. The value is a negative number.
+     */    
+    public static final int DESCENT = 3;
+    /** The angle, expressed in degrees counterclockwise from the vertical,
+     * of the dominant vertical strokes of the font. The value is
+     * negative for fonts that slope to the right, as almost all italic fonts do.
+     */    
+    public static final int ITALICANGLE = 4;
+    /** The lower left x glyph coordinate.
+     */    
+    public static final int BBOXLLX = 5;
+    /** The lower left y glyph coordinate.
+     */    
+    public static final int BBOXLLY = 6;
+    /** The upper right x glyph coordinate.
+     */    
+    public static final int BBOXURX = 7;
+    /** The upper right y glyph coordinate.
+     */    
+    public static final int BBOXURY = 8;
+    
+    /** java.awt.Font property */
+    public static final int AWT_ASCENT = 9;
+    /** java.awt.Font property */
+    public static final int AWT_DESCENT = 10;
+    /** java.awt.Font property */
+    public static final int AWT_LEADING = 11;
+    /** java.awt.Font property */
+    public static final int AWT_MAXADVANCE = 12;
+    
+    /** The font is Type 1.
+     */    
+    public static final int FONT_TYPE_T1 = 0;
+    /** The font is True Type with a standard encoding.
+     */    
+    public static final int FONT_TYPE_TT = 1;
+    /** The font is CJK.
+     */    
+    public static final int FONT_TYPE_CJK = 2;
+    /** The font is True Type with a Unicode encoding.
+     */    
+    public static final int FONT_TYPE_TTUNI = 3;
+    /** A font already inside the document.
+     */    
+    public static final int FONT_TYPE_DOCUMENT = 4;
+    /** The Unicode encoding with horizontal writing.
+     */    
+    public static final String IDENTITY_H = "Identity-H";
+    /** The Unicode encoding with vertical writing.
+     */    
+    public static final String IDENTITY_V = "Identity-V";
+    
+    /** A possible encoding. */    
+    public static final String CP1250 = "Cp1250";
+    
+    /** A possible encoding. */    
+    public static final String CP1252 = "Cp1252";
+    
+    /** A possible encoding. */    
+    public static final String CP1257 = "Cp1257";
+    
+    /** A possible encoding. */    
+    public static final String WINANSI = "Cp1252";
+    
+    /** A possible encoding. */    
+    public static final String MACROMAN = "MacRoman";
+    
+    
+/** if the font has to be embedded */
+    public static final boolean EMBEDDED = true;
+    
+/** if the font doesn't have to be embedded */
+    public static final boolean NOT_EMBEDDED = false;
+/** if the font has to be cached */
+    public static final boolean CACHED = true;
+/** if the font doesn't have to be cached */
+    public static final boolean NOT_CACHED = false;
+    
+    /** The path to the font resources. */    
+    public static final String RESOURCE_PATH = "com/lowagie/text/pdf/fonts/";
+    /** The fake CID code that represents a newline. */    
+    public static final char CID_NEWLINE = '\u7fff';
+    
+    /** The font type.
+     */    
+    int fontType;
+/** a not defined character in a custom PDF encoding */
+    public static final String notdef = ".notdef";
+    
+/** table of characters widths for this encoding */
+    protected int widths[] = new int[256];
+    
+/** encoding names */
+    protected String differences[] = new String[256];
+/** same as differences but with the unicode codes */
+    protected char unicodeDifferences[] = new char[256];
+    
+    protected int charBBoxes[][] = new int[256][];
+/** encoding used with this font */
+    protected String encoding;
+    
+/** true if the font is to be embedded in the PDF */
+    protected boolean embedded;
+    
+/**
+ * true if the font must use it's built in encoding. In that case the
+ * <CODE>encoding</CODE> is only used to map a char to the position inside
+ * the font, not to the expected char name.
+ */
+    protected boolean fontSpecific = true;
+    
+/** cache for the fonts already used. */
+    protected static HashMap fontCache = new HashMap();
+    
+/** list of the 14 built in fonts. */
+    protected static final HashMap BuiltinFonts14 = new HashMap();
+    
+    /** Forces the output of the width array. Only matters for the 14
+     * built-in fonts.
+     */
+    protected boolean forceWidthsOutput = false;
+    
+    /** Converts <CODE>char</CODE> directly to <CODE>byte</CODE>
+     * by casting.
+     */
+    protected boolean directTextToByte = false;
+    
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document.
+     */
+    protected boolean subset = true;
+    
+    protected boolean fastWinansi = false;
+    
+    static {
+        BuiltinFonts14.put(COURIER, PdfName.COURIER);
+        BuiltinFonts14.put(COURIER_BOLD, PdfName.COURIER_BOLD);
+        BuiltinFonts14.put(COURIER_BOLDOBLIQUE, PdfName.COURIER_BOLDOBLIQUE);
+        BuiltinFonts14.put(COURIER_OBLIQUE, PdfName.COURIER_OBLIQUE);
+        BuiltinFonts14.put(HELVETICA, PdfName.HELVETICA);
+        BuiltinFonts14.put(HELVETICA_BOLD, PdfName.HELVETICA_BOLD);
+        BuiltinFonts14.put(HELVETICA_BOLDOBLIQUE, PdfName.HELVETICA_BOLDOBLIQUE);
+        BuiltinFonts14.put(HELVETICA_OBLIQUE, PdfName.HELVETICA_OBLIQUE);
+        BuiltinFonts14.put(SYMBOL, PdfName.SYMBOL);
+        BuiltinFonts14.put(TIMES_ROMAN, PdfName.TIMES_ROMAN);
+        BuiltinFonts14.put(TIMES_BOLD, PdfName.TIMES_BOLD);
+        BuiltinFonts14.put(TIMES_BOLDITALIC, PdfName.TIMES_BOLDITALIC);
+        BuiltinFonts14.put(TIMES_ITALIC, PdfName.TIMES_ITALIC);
+        BuiltinFonts14.put(ZAPFDINGBATS, PdfName.ZAPFDINGBATS);
+    }
+    
+    /** Generates the PDF stream with the Type1 and Truetype fonts returning
+     * a PdfStream.
+     */
+    static class StreamFont extends PdfStream {
+        
+        /** Generates the PDF stream with the Type1 and Truetype fonts returning
+         * a PdfStream.
+         * @param contents the content of the stream
+         * @param lengths an array of int that describes the several lengths of each part of the font
+         * @throws DocumentException error in the stream compression
+         */
+        public StreamFont(byte contents[], int lengths[]) throws DocumentException {
+            try {
+                bytes = contents;
+                put(PdfName.LENGTH, new PdfNumber(bytes.length));
+                for (int k = 0; k < lengths.length; ++k) {
+                    put(new PdfName("Length" + (k + 1)), new PdfNumber(lengths[k]));
+                }
+                flateCompress();
+            }
+            catch (Exception e) {
+                throw new DocumentException(e);
+            }
+        }
+        
+        /**
+         * Generates the PDF stream for a font.
+         * @param contents the content of a stream
+         * @param subType the subtype of the font.
+         * @throws DocumentException
+         */
+        public StreamFont(byte contents[], String subType) throws DocumentException {
+            try {
+                bytes = contents;
+                put(PdfName.LENGTH, new PdfNumber(bytes.length));
+                if (subType != null)
+                    put(PdfName.SUBTYPE, new PdfName(subType));
+                flateCompress();
+            }
+            catch (Exception e) {
+                throw new DocumentException(e);
+            }
+        }
+    }
+    
+    /**
+     *Creates new BaseFont
+     */
+    protected BaseFont() {
+    }
+    
+    /** Creates a new font. This font can be one of the 14 built in types,
+     * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
+     * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
+     * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
+     * example would be "STSong-Light,Bold". Note that this modifiers do not work if
+     * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
+     * This would get the second font (indexes start at 0), in this case "MS PGothic".
+     * <P>
+     * The fonts are cached and if they already exist they are extracted from the cache,
+     * not parsed again.
+     * <P>
+     * This method calls:<br>
+     * <PRE>
+     * createFont(name, encoding, embedded, true, null, null);
+     * </PRE>
+     * @param name the name of the font or it's location on file
+     * @param encoding the encoding to be applied to this font
+     * @param embedded true if the font is to be embedded in the PDF
+     * @return returns a new font. This font may come from the cache
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    public static BaseFont createFont(String name, String encoding, boolean embedded) throws DocumentException, IOException {
+        return createFont(name, encoding, embedded, true, null, null);
+    }
+    
+    /** Creates a new font. This font can be one of the 14 built in types,
+     * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
+     * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
+     * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
+     * example would be "STSong-Light,Bold". Note that this modifiers do not work if
+     * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
+     * This would get the second font (indexes start at 0), in this case "MS PGothic".
+     * <P>
+     * The fonts may or may not be cached depending on the flag <CODE>cached</CODE>.
+     * If the <CODE>byte</CODE> arrays are present the font will be
+     * read from them instead of the name. The name is still required to identify
+     * the font type.
+     * @param name the name of the font or it's location on file
+     * @param encoding the encoding to be applied to this font
+     * @param embedded true if the font is to be embedded in the PDF
+     * @param cached true if the font comes from the cache or is added to
+     * the cache if new, false if the font is always created new
+     * @param ttfAfm the true type font or the afm in a byte array
+     * @param pfb the pfb in a byte array
+     * @return returns a new font. This font may come from the cache but only if cached
+     * is true, otherwise it will always be created new
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    public static BaseFont createFont(String name, String encoding, boolean embedded, boolean cached, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException {
+        String nameBase = getBaseName(name);
+        encoding = normalizeEncoding(encoding);
+        boolean isBuiltinFonts14 = BuiltinFonts14.containsKey(name);
+        boolean isCJKFont = isBuiltinFonts14 ? false : CJKFont.isCJKFont(nameBase, encoding);
+        if (isBuiltinFonts14 || isCJKFont)
+            embedded = false;
+        else if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
+            embedded = true;
+        BaseFont fontFound = null;
+        BaseFont fontBuilt = null;
+        String key = name + "\n" + encoding + "\n" + embedded;
+        if (cached) {
+            synchronized (fontCache) {
+                fontFound = (BaseFont)fontCache.get(key);
+            }
+            if (fontFound != null)
+                return fontFound;
+        }
+        if (isBuiltinFonts14 || name.toLowerCase().endsWith(".afm") || name.toLowerCase().endsWith(".pfm")) {
+            fontBuilt = new Type1Font(name, encoding, embedded, ttfAfm, pfb);
+            fontBuilt.fastWinansi = encoding.equals(CP1252);
+        }
+        else if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0) {
+            if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
+                fontBuilt = new TrueTypeFontUnicode(name, encoding, embedded, ttfAfm);
+            else {
+                fontBuilt = new TrueTypeFont(name, encoding, embedded, ttfAfm);
+                fontBuilt.fastWinansi = encoding.equals(CP1252);
+            }
+        }
+        else if (isCJKFont)
+            fontBuilt = new CJKFont(name, encoding, embedded);
+        else
+            throw new DocumentException("Font '" + name + "' with '" + encoding + "' is not recognized.");
+        if (cached) {
+            synchronized (fontCache) {
+                fontFound = (BaseFont)fontCache.get(key);
+                if (fontFound != null)
+                    return fontFound;
+                fontCache.put(key, fontBuilt);
+            }
+        }
+        return fontBuilt;
+    }
+    
+    /**
+     * Creates a font based on an existing document font. The created font font may not
+     * behave as expected, depending on the encoding or subset.
+     * @param fontRef the reference to the document font
+     * @return the font
+     */    
+    public static BaseFont createFont(PRIndirectReference fontRef) {
+        return new DocumentFont(fontRef);
+    }
+    
+    /**
+     * Gets the name without the modifiers Bold, Italic or BoldItalic.
+     * @param name the full name of the font
+     * @return the name without the modifiers Bold, Italic or BoldItalic
+     */
+    protected static String getBaseName(String name) {
+        if (name.endsWith(",Bold"))
+            return name.substring(0, name.length() - 5);
+        else if (name.endsWith(",Italic"))
+            return name.substring(0, name.length() - 7);
+        else if (name.endsWith(",BoldItalic"))
+            return name.substring(0, name.length() - 11);
+        else
+            return name;
+    }
+    
+    /**
+     * Normalize the encoding names. "winansi" is changed to "Cp1252" and
+     * "macroman" is changed to "MacRoman".
+     * @param enc the encoding to be normalized
+     * @return the normalized encoding
+     */
+    protected static String normalizeEncoding(String enc) {
+        if (enc.equals("winansi") || enc.equals(""))
+            return CP1252;
+        else if (enc.equals("macroman"))
+            return MACROMAN;
+        else
+            return enc;
+    }
+    
+    /**
+     * Creates the <CODE>widths</CODE> and the <CODE>differences</CODE> arrays
+     */
+    protected void createEncoding() {
+        if (fontSpecific) {
+            for (int k = 0; k < 256; ++k) {
+                widths[k] = getRawWidth(k, null);
+                charBBoxes[k] = getRawCharBBox(k, null);
+            }
+        }
+        else {
+            String s;
+            String name;
+            char c;
+            byte b[] = new byte[1];
+            for (int k = 0; k < 256; ++k) {
+                b[0] = (byte)k;
+                s = PdfEncodings.convertToString(b, encoding);
+                if (s.length() > 0) {
+                    c = s.charAt(0);
+                }
+                else {
+                    c = '?';
+                }
+                name = GlyphList.unicodeToName((int)c);
+                if (name == null)
+                    name = notdef;
+                differences[k] = name;
+                unicodeDifferences[k] = c;
+                widths[k] = getRawWidth((int)c, name);
+                charBBoxes[k] = getRawCharBBox((int)c, name);
+            }
+        }
+    }
+    
+    /**
+     * Gets the width from the font according to the Unicode char <CODE>c</CODE>
+     * or the <CODE>name</CODE>. If the <CODE>name</CODE> is null it's a symbolic font.
+     * @param c the unicode char
+     * @param name the glyph name
+     * @return the width of the char
+     */
+    abstract int getRawWidth(int c, String name);
+    
+    /**
+     * Gets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @return the kerning to be applied in normalized 1000 units
+     */
+    public abstract int getKerning(char char1, char char2);
+
+    /**
+     * Sets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @param kern the kerning to apply in normalized 1000 units
+     * @return <code>true</code> if the kerning was applied, <code>false</code> otherwise
+     */
+    public abstract boolean setKerning(char char1, char char2, int kern);
+    
+    /**
+     * Gets the width of a <CODE>char</CODE> in normalized 1000 units.
+     * @param char1 the unicode <CODE>char</CODE> to get the width of
+     * @return the width in normalized 1000 units
+     */
+    public int getWidth(char char1) {
+        if (fastWinansi) {
+            if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+                return widths[char1];
+            return widths[PdfEncodings.winansi.get(char1)];
+        }
+        return getWidth(new String(new char[]{char1}));
+    }
+    
+    /**
+     * Gets the width of a <CODE>String</CODE> in normalized 1000 units.
+     * @param text the <CODE>String</CODE> to get the witdth of
+     * @return the width in normalized 1000 units
+     */
+    public int getWidth(String text) {
+        int total = 0;
+        if (fastWinansi) {
+            int len = text.length();
+            for (int k = 0; k < len; ++k) {
+                char char1 = text.charAt(k);
+                if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+                    total += widths[char1];
+                else
+                    total += widths[PdfEncodings.winansi.get(char1)];
+            }
+            return total;
+        }
+        else {
+            byte mbytes[] = convertToBytes(text);
+            for (int k = 0; k < mbytes.length; ++k)
+                total += widths[0xff & mbytes[k]];
+        }
+        return total;
+    }
+    
+/**
+ * Gets the descent of a <CODE>String</CODE> in normalized 1000 units. The descent will always be
+ * less than or equal to zero even if all the characters have an higher descent.
+ * @param text the <CODE>String</CODE> to get the descent of
+ * @return the dexcent in normalized 1000 units
+ */
+    public int getDescent(String text) {
+        int min = 0;
+        char chars[] = text.toCharArray();
+        for (int k = 0; k < chars.length; ++k) {
+            int bbox[] = getCharBBox(chars[k]);
+            if (bbox != null && bbox[1] < min)
+                min = bbox[1];
+        }
+        return min;
+    }
+    
+/**
+ * Gets the ascent of a <CODE>String</CODE> in normalized 1000 units. The ascent will always be
+ * greater than or equal to zero even if all the characters have a lower ascent.
+ * @param text the <CODE>String</CODE> to get the ascent of
+ * @return the ascent in normalized 1000 units
+ */
+    public int getAscent(String text) {
+        int max = 0;
+        char chars[] = text.toCharArray();
+        for (int k = 0; k < chars.length; ++k) {
+            int bbox[] = getCharBBox(chars[k]);
+            if (bbox != null && bbox[3] > max)
+                max = bbox[3];
+        }
+        return max;
+    }
+
+/**
+ * Gets the descent of a <CODE>String</CODE> in points. The descent will always be
+ * less than or equal to zero even if all the characters have an higher descent.
+ * @param text the <CODE>String</CODE> to get the descent of
+ * @param fontSize the size of the font
+ * @return the dexcent in points
+ */
+    public float getDescentPoint(String text, float fontSize)
+    {
+        return (float)getDescent(text) * 0.001f * fontSize;
+    }
+    
+/**
+ * Gets the ascent of a <CODE>String</CODE> in points. The ascent will always be
+ * greater than or equal to zero even if all the characters have a lower ascent.
+ * @param text the <CODE>String</CODE> to get the ascent of
+ * @param fontSize the size of the font
+ * @return the ascent in points
+ */
+    public float getAscentPoint(String text, float fontSize)
+    {
+        return (float)getAscent(text) * 0.001f * fontSize;
+    }
+// ia>    
+    
+    /**
+     * Gets the width of a <CODE>String</CODE> in points taking kerning
+     * into account.
+     * @param text the <CODE>String</CODE> to get the witdth of
+     * @param fontSize the font size
+     * @return the width in points
+     */
+    public float getWidthPointKerned(String text, float fontSize) {
+        float size = (float)getWidth(text) * 0.001f * fontSize;
+        if (!hasKernPairs())
+            return size;
+        int len = text.length() - 1;
+        int kern = 0;
+        char c[] = text.toCharArray();
+        for (int k = 0; k < len; ++k) {
+            kern += getKerning(c[k], c[k + 1]);
+        }
+        return size + kern * 0.001f * fontSize;
+    }
+    
+    /**
+     * Gets the width of a <CODE>String</CODE> in points.
+     * @param text the <CODE>String</CODE> to get the witdth of
+     * @param fontSize the font size
+     * @return the width in points
+     */
+    public float getWidthPoint(String text, float fontSize) {
+        return (float)getWidth(text) * 0.001f * fontSize;
+    }
+    
+    /**
+     * Gets the width of a <CODE>char</CODE> in points.
+     * @param char1 the <CODE>char</CODE> to get the witdth of
+     * @param fontSize the font size
+     * @return the width in points
+     */
+    public float getWidthPoint(char char1, float fontSize) {
+        return getWidth(char1) * 0.001f * fontSize;
+    }
+    
+    /**
+     * Converts a <CODE>String</CODE> to a </CODE>byte</CODE> array according
+     * to the font's encoding.
+     * @param text the <CODE>String</CODE> to be converted
+     * @return an array of <CODE>byte</CODE> representing the conversion according to the font's encoding
+     */
+    byte[] convertToBytes(String text) {
+        if (directTextToByte)
+            return PdfEncodings.convertToBytes(text, null);
+        return PdfEncodings.convertToBytes(text, encoding);
+    }
+    
+    /** Outputs to the writer the font dictionaries and streams.
+     * @param writer the writer for this document
+     * @param ref the font indirect reference
+     * @param params several parameters that depend on the font type
+     * @throws IOException on error
+     * @throws DocumentException error in generating the object
+     */
+    abstract void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException;
+    
+    /** Gets the encoding used to convert <CODE>String</CODE> into <CODE>byte[]</CODE>.
+     * @return the encoding name
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+    
+    /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
+     * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>AWT_ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, 
+     * <CODE>DESCENT</CODE>, <CODE>AWT_DESCENT</CODE>,
+     * <CODE>ITALICANGLE</CODE>, <CODE>BBOXLLX</CODE>, <CODE>BBOXLLY</CODE>, <CODE>BBOXURX</CODE>
+     * and <CODE>BBOXURY</CODE>.
+     * @param key the parameter to be extracted
+     * @param fontSize the font size in points
+     * @return the parameter in points
+     */
+    public abstract float getFontDescriptor(int key, float fontSize);
+    
+    /** Gets the font type. The font types can be: FONT_TYPE_T1,
+     * FONT_TYPE_TT, FONT_TYPE_CJK and FONT_TYPE_TTUNI.
+     * @return the font type
+     */
+    public int getFontType() {
+        return fontType;
+    }
+    
+    /** Gets the embedded flag.
+     * @return <CODE>true</CODE> if the font is embedded.
+     */
+    public boolean isEmbedded() {
+        return embedded;
+    }
+    
+    /** Gets the symbolic flag of the font.
+     * @return <CODE>true</CODE> if the font is symbolic
+     */
+    public boolean isFontSpecific() {
+        return fontSpecific;
+    }
+    
+    /** Creates a unique subset prefix to be added to the font name when the font is embedded and subset.
+     * @return the subset prefix
+     */
+    public static String createSubsetPrefix() {
+        String s = "";
+        for (int k = 0; k < 6; ++k)
+            s += (char)(Math.random() * 26 + 'A');
+        return s + "+";
+    }
+    
+    /** Gets the Unicode character corresponding to the byte output to the pdf stream.
+     * @param index the byte index
+     * @return the Unicode character
+     */
+    char getUnicodeDifferences(int index) {
+        return unicodeDifferences[index];
+    }
+    
+    /** Gets the postscript font name.
+     * @return the postscript font name
+     */
+    public abstract String getPostscriptFontName();
+    
+    /**
+     * Sets the font name that will appear in the pdf font dictionary.
+     * Use with care as it can easily make a font unreadable if not embedded.
+     * @param name the new font name
+     */    
+    public abstract void setPostscriptFontName(String name);
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the full name of the font
+     */
+    public abstract String[][] getFullFontName();
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @param name the name of the font
+     * @param encoding the encoding of the font
+     * @param ttfAfm the true type font or the afm in a byte array
+     * @throws DocumentException on error
+     * @throws IOException on error
+     * @return the full name of the font
+     */    
+    public static String[][] getFullFontName(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
+        String nameBase = getBaseName(name);
+        BaseFont fontBuilt = null;
+        if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
+            fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
+        else
+            fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
+        return fontBuilt.getFullFontName();
+    }
+    
+    /** Gets all the names from the font. Only the required tables are read.
+     * @param name the name of the font
+     * @param encoding the encoding of the font
+     * @param ttfAfm the true type font or the afm in a byte array
+     * @throws DocumentException on error
+     * @throws IOException on error
+     * @return an array of Object[] built with {getPostscriptFontName(), getFamilyFontName(), getFullFontName()}
+     */    
+    public static Object[] getAllFontNames(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
+        String nameBase = getBaseName(name);
+        BaseFont fontBuilt = null;
+        if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
+            fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
+        else
+            fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
+        return new Object[]{fontBuilt.getPostscriptFontName(), fontBuilt.getFamilyFontName(), fontBuilt.getFullFontName()};
+    }
+    
+    /** Gets the family name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the family name of the font
+     */
+    public abstract String[][] getFamilyFontName();
+    
+    /** Gets the code pages supported by the font. This has only meaning
+     * with True Type fonts.
+     * @return the code pages supported by the font
+     */
+    public String[] getCodePagesSupported() {
+        return new String[0];
+    }
+    
+    /** Enumerates the postscript font names present inside a
+     * True Type Collection.
+     * @param ttcFile the file name of the font
+     * @throws DocumentException on error
+     * @throws IOException on error
+     * @return the postscript font names
+     */    
+    public static String[] enumerateTTCNames(String ttcFile) throws DocumentException, IOException {
+        return new EnumerateTTC(ttcFile).getNames();
+    }
+
+    /** Enumerates the postscript font names present inside a
+     * True Type Collection.
+     * @param ttcArray the font as a <CODE>byte</CODE> array
+     * @throws DocumentException on error
+     * @throws IOException on error
+     * @return the postscript font names
+     */    
+    public static String[] enumerateTTCNames(byte ttcArray[]) throws DocumentException, IOException {
+        return new EnumerateTTC(ttcArray).getNames();
+    }
+    
+    /** Gets the font width array.
+     * @return the font width array
+     */    
+    public int[] getWidths() {
+        return widths;
+    }
+
+    /** Gets the array with the names of the characters.
+     * @return the array with the names of the characters
+     */    
+    public String[] getDifferences() {
+        return differences;
+    }
+
+    /** Gets the array with the unicode characters.
+     * @return the array with the unicode characters
+     */    
+    public char[] getUnicodeDifferences() {
+        return unicodeDifferences;
+    }
+    
+    /** Gets the state of the property.
+     * @return value of property forceWidthsOutput
+     */
+    public boolean isForceWidthsOutput() {
+        return forceWidthsOutput;
+    }
+    
+    /** Set to <CODE>true</CODE> to force the generation of the
+     * widths array.
+     * @param forceWidthsOutput <CODE>true</CODE> to force the generation of the
+     * widths array
+     */
+    public void setForceWidthsOutput(boolean forceWidthsOutput) {
+        this.forceWidthsOutput = forceWidthsOutput;
+    }
+    
+    /** Gets the direct conversion of <CODE>char</CODE> to <CODE>byte</CODE>.
+     * @return value of property directTextToByte.
+     * @see #setDirectTextToByte(boolean directTextToByte)
+     */
+    public boolean isDirectTextToByte() {
+        return directTextToByte;
+    }
+    
+    /** Sets the conversion of <CODE>char</CODE> directly to <CODE>byte</CODE>
+     * by casting. This is a low level feature to put the bytes directly in
+     * the content stream without passing through String.getBytes().
+     * @param directTextToByte New value of property directTextToByte.
+     */
+    public void setDirectTextToByte(boolean directTextToByte) {
+        this.directTextToByte = directTextToByte;
+    }
+    
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document.
+     * @return <CODE>false</CODE> to include all the glyphs and widths.
+     */
+    public boolean isSubset() {
+        return subset;
+    }
+    
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document. Set to <CODE>false</CODE>
+     * to include all.
+     * @param subset new value of property subset
+     */
+    public void setSubset(boolean subset) {
+        this.subset = subset;
+    }
+
+    /** Gets the font resources.
+     * @param key the full name of the resource
+     * @return the <CODE>InputStream</CODE> to get the resource or
+     * <CODE>null</CODE> if not found
+     */    
+    public static InputStream getResourceStream(String key) {
+        return getResourceStream(key, null);
+    }
+    
+    /** Gets the font resources.
+     * @param key the full name of the resource
+     * @param loader the ClassLoader to load the resource or null to try the ones available
+     * @return the <CODE>InputStream</CODE> to get the resource or
+     * <CODE>null</CODE> if not found
+     */    
+    public static InputStream getResourceStream(String key, ClassLoader loader) {
+        if (key.startsWith("/"))
+            key = key.substring(1);
+        InputStream is = null;
+        if (loader != null) {
+            is = loader.getResourceAsStream(key);
+            if (is != null)
+                return is;
+        }
+        // Try to use Context Class Loader to load the properties file.
+        try {
+            java.lang.reflect.Method getCCL =
+                Thread.class.getMethod("getContextClassLoader", new Class[0]);
+            if (getCCL != null) {
+                ClassLoader contextClassLoader =
+                    (ClassLoader)getCCL.invoke(Thread.currentThread(),
+                                               new Object[0]);
+                if (contextClassLoader != null)
+                    is = contextClassLoader.getResourceAsStream(key);
+            }
+        } catch (Throwable e) {}
+
+        if (is == null) {
+            is = BaseFont.class.getResourceAsStream("/" + key);
+        }
+        if (is == null) {
+            is = ClassLoader.getSystemResourceAsStream(key);
+        }
+        return is;
+    }
+    
+    /** Gets the Unicode equivalent to a CID.
+     * The (inexistent) CID <FF00> is translated as '\n'. 
+     * It has only meaning with CJK fonts with Identity encoding.
+     * @param c the CID code
+     * @return the Unicode equivalent
+     */    
+    public char getUnicodeEquivalent(char c) {
+        return c;
+    }
+    
+    /** Gets the CID code given an Unicode.
+     * It has only meaning with CJK fonts.
+     * @param c the Unicode
+     * @return the CID equivalent
+     */    
+    public char getCidCode(char c) {
+        return c;
+    }
+
+    /** Checks if the font has any kerning pairs.
+     * @return <CODE>true</CODE> if the font has any kerning pairs
+     */    
+    public abstract boolean hasKernPairs();
+    
+    /**
+     * Checks if a character exists in this font.
+     * @param c the character to check
+     * @return <CODE>true</CODE> if the character has a glyph,
+     * <CODE>false</CODE> otherwise
+     */    
+    public boolean charExists(char c) {
+        byte b[] = convertToBytes(new String(new char[]{c}));
+        return b.length > 0;
+    }
+    
+    /**
+     * Sets the character advance.
+     * @param c the character
+     * @param advance the character advance normalized to 1000 units
+     * @return <CODE>true</CODE> if the advance was set,
+     * <CODE>false</CODE> otherwise
+     */    
+    public boolean setCharAdvance(char c, int advance) {
+        byte b[] = convertToBytes(new String(new char[]{c}));
+        if (b.length == 0)
+            return false;
+        widths[0xff & b[0]] = advance;
+        return true;
+    }
+    
+    private static void addFont(PRIndirectReference fontRef, IntHashtable hits, ArrayList fonts) {
+        PdfObject obj = PdfReader.getPdfObject(fontRef);
+        if (!obj.isDictionary())
+            return;
+        PdfDictionary font = (PdfDictionary)obj;
+        PdfName subtype = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
+        if (!PdfName.TYPE1.equals(subtype) && !PdfName.TRUETYPE.equals(subtype))
+            return;
+        PdfName name = (PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT));
+        fonts.add(new Object[]{PdfName.decodeName(name.toString()), fontRef});
+        hits.put(fontRef.getNumber(), 1);
+    }
+    
+    private static void recourseFonts(PdfDictionary page, IntHashtable hits, ArrayList fonts, int level) {
+        ++level;
+        if (level > 50) // in case we have an endless loop
+            return;
+        PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(page.get(PdfName.RESOURCES));
+        if (resources == null)
+            return;
+        PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.FONT));
+        if (font != null) {
+            for (Iterator it = font.getKeys().iterator(); it.hasNext();) {
+                PdfObject ft = font.get((PdfName)it.next());        
+                if (ft == null || !ft.isIndirect())
+                    continue;
+                int hit = ((PRIndirectReference)ft).getNumber();
+                if (hits.containsKey(hit))
+                    continue;
+                addFont((PRIndirectReference)ft, hits, fonts);
+            }
+        }
+        PdfDictionary xobj = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.XOBJECT));
+        if (xobj != null) {
+            for (Iterator it = xobj.getKeys().iterator(); it.hasNext();) {
+                recourseFonts((PdfDictionary)PdfReader.getPdfObject(xobj.get((PdfName)it.next())), hits, fonts, level);
+            }
+        }
+    }
+    
+    /**
+     * Gets a list of all document fonts. Each element of the <CODE>ArrayList</CODE>
+     * contains a <CODE>Object[]{String,PRIndirectReference}</CODE> with the font name
+     * and the indirect reference to it.
+     * @param reader the document where the fonts are to be listed from
+     * @return the list of fonts and references
+     */    
+    public static ArrayList getDocumentFonts(PdfReader reader) {
+        IntHashtable hits = new IntHashtable();
+        ArrayList fonts = new ArrayList();
+        int npages = reader.getNumberOfPages();
+        for (int k = 1; k <= npages; ++k)
+            recourseFonts(reader.getPageN(k), hits, fonts, 1);
+        return fonts;
+    }
+    
+    /**
+     * Gets a list of the document fonts in a particular page. Each element of the <CODE>ArrayList</CODE>
+     * contains a <CODE>Object[]{String,PRIndirectReference}</CODE> with the font name
+     * and the indirect reference to it.
+     * @param reader the document where the fonts are to be listed from
+     * @param page the page to list the fonts from
+     * @return the list of fonts and references
+     */    
+    public static ArrayList getDocumentFonts(PdfReader reader, int page) {
+        IntHashtable hits = new IntHashtable();
+        ArrayList fonts = new ArrayList();
+        recourseFonts(reader.getPageN(page), hits, fonts, 1);
+        return fonts;
+    }
+    
+    /**
+     * Gets the smallest box enclosing the character contours. It will return
+     * <CODE>null</CODE> if the font has not the information or the character has no
+     * contours, as in the case of the space, for example. Characters with no contours may
+     * also return [0,0,0,0].
+     * @param c the character to get the contour bounding box from
+     * @return an array of four floats with the bounding box in the format [llx,lly,urx,ury] or
+     * <code>null</code>
+     */    
+    public int[] getCharBBox(char c) {
+        byte b[] = convertToBytes(new String(new char[]{c}));
+        if (b.length == 0)
+            return null;
+        else
+            return charBBoxes[b[0] & 0xff];
+    }
+    
+    protected abstract int[] getRawCharBBox(int c, String name);
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/BidiLine.java b/LibrarySource/com/lowagie/text/pdf/BidiLine.java
new file mode 100644
index 0000000..cc35844
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/BidiLine.java
@@ -0,0 +1,915 @@
+/*
+ *
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+
+import com.lowagie.text.Chunk;
+
+/** Does all the line bidirectional processing with PdfChunk assembly.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class BidiLine {
+    
+    protected int runDirection;
+    protected int pieceSize = 2048;
+    protected char text[] = new char[pieceSize];
+    protected PdfChunk detailChunks[] = new PdfChunk[pieceSize];
+    protected int totalTextLength = 0;
+    
+    protected byte orderLevels[] = new byte[pieceSize];
+    protected int indexChars[] = new int[pieceSize];
+    
+    protected ArrayList chunks = new ArrayList();
+    protected int indexChunk = 0;
+    protected int indexChunkChar = 0;
+    protected int currentChar = 0;
+    
+    protected int storedRunDirection;
+    protected char storedText[] = new char[0];
+    protected PdfChunk storedDetailChunks[] = new PdfChunk[0];
+    protected int storedTotalTextLength = 0;
+    
+    protected byte storedOrderLevels[] = new byte[0];
+    protected int storedIndexChars[] = new int[0];
+    
+    protected int storedIndexChunk = 0;
+    protected int storedIndexChunkChar = 0;
+    protected int storedCurrentChar = 0;
+    
+    protected boolean shortStore;
+//    protected ArabicShaping arabic = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK | ArabicShaping.TEXT_DIRECTION_LOGICAL);
+    protected static final IntHashtable mirrorChars = new IntHashtable();
+    protected int arabicOptions;
+
+    /** Creates new BidiLine */
+    public BidiLine() {
+    }
+    
+    public BidiLine(BidiLine org) {
+        runDirection = org.runDirection;
+        pieceSize = org.pieceSize;
+        text = (char[])org.text.clone();
+        detailChunks = (PdfChunk[])org.detailChunks.clone();
+        totalTextLength = org.totalTextLength;
+
+        orderLevels = (byte[])org.orderLevels.clone();
+        indexChars = (int[])org.indexChars.clone();
+
+        chunks = new ArrayList(org.chunks);
+        indexChunk = org.indexChunk;
+        indexChunkChar = org.indexChunkChar;
+        currentChar = org.currentChar;
+
+        storedRunDirection = org.storedRunDirection;
+        storedText = (char[])org.storedText.clone();
+        storedDetailChunks = (PdfChunk[])org.storedDetailChunks.clone();
+        storedTotalTextLength = org.storedTotalTextLength;
+
+        storedOrderLevels = (byte[])org.storedOrderLevels.clone();
+        storedIndexChars = (int[])org.storedIndexChars.clone();
+
+        storedIndexChunk = org.storedIndexChunk;
+        storedIndexChunkChar = org.storedIndexChunkChar;
+        storedCurrentChar = org.storedCurrentChar;
+
+        shortStore = org.shortStore;
+        arabicOptions = org.arabicOptions;
+    }
+    
+    public boolean isEmpty() {
+        return (currentChar >= totalTextLength && indexChunk >= chunks.size());
+    }
+    
+    public void clearChunks() {
+        chunks.clear();
+        totalTextLength = 0;
+        currentChar = 0;
+    }
+
+    public boolean getParagraph(int runDirection) {
+        this.runDirection = runDirection;
+        currentChar = 0;
+        totalTextLength = 0;
+        boolean hasText = false;
+        char c;
+        char uniC;
+        BaseFont bf;
+        for (; indexChunk < chunks.size(); ++indexChunk) {
+            PdfChunk ck = (PdfChunk)chunks.get(indexChunk);
+            bf = ck.font().getFont();
+            String s = ck.toString();
+            int len = s.length();
+            for (; indexChunkChar < len; ++indexChunkChar) {
+                c = s.charAt(indexChunkChar);
+                uniC = bf.getUnicodeEquivalent(c);
+                if (uniC == '\r' || uniC == '\n') {
+                    // next condition is never true for CID
+                    if (uniC == '\r' && indexChunkChar + 1 < len && s.charAt(indexChunkChar + 1) == '\n')
+                        ++indexChunkChar;
+                    ++indexChunkChar;
+                    if (indexChunkChar >= len) {
+                        indexChunkChar = 0;
+                        ++indexChunk;
+                    }
+                    hasText = true;
+                    if (totalTextLength == 0)
+                        detailChunks[0] = ck;
+                    break;
+                }
+                addPiece(c, ck);
+            }
+            if (hasText)
+                break;
+            indexChunkChar = 0;
+        }
+        if (totalTextLength == 0)
+            return hasText;
+
+        // remove trailing WS
+        totalTextLength = trimRight(0, totalTextLength - 1) + 1;
+        if (totalTextLength == 0)
+            return true;
+        
+        if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+            if (orderLevels.length < totalTextLength) {
+                orderLevels = new byte[pieceSize];
+                indexChars = new int[pieceSize];
+            }
+            ArabicLigaturizer.processNumbers(text, 0, totalTextLength, arabicOptions);
+            BidiOrder order = new BidiOrder(text, 0, totalTextLength, (byte)(runDirection == PdfWriter.RUN_DIRECTION_RTL ? 1 : 0));
+            byte od[] = order.getLevels();
+            for (int k = 0; k < totalTextLength; ++k) {
+                orderLevels[k] = od[k];
+                indexChars[k] = k;
+            }
+            doArabicShapping();
+            mirrorGlyphs();
+        }
+        totalTextLength = trimRightEx(0, totalTextLength - 1) + 1;
+        return true;
+    }
+    
+    public void addChunk(PdfChunk chunk) {
+        chunks.add(chunk);
+    }
+    
+    public void addChunks(ArrayList chunks) {
+        this.chunks.addAll(chunks);
+    }
+    
+    public void addPiece(char c, PdfChunk chunk) {
+        if (totalTextLength >= pieceSize) {
+            char tempText[] = text;
+            PdfChunk tempDetailChunks[] = detailChunks;
+            pieceSize *= 2;
+            text = new char[pieceSize];
+            detailChunks = new PdfChunk[pieceSize];
+            System.arraycopy(tempText, 0, text, 0, totalTextLength);
+            System.arraycopy(tempDetailChunks, 0, detailChunks, 0, totalTextLength);
+        }
+        text[totalTextLength] = c;
+        detailChunks[totalTextLength++] = chunk;
+    }
+    
+    public void save() {
+        if (indexChunk > 0) {
+            if (indexChunk >= chunks.size())
+                chunks.clear();
+            else {
+                for (--indexChunk; indexChunk >= 0; --indexChunk)
+                    chunks.remove(indexChunk);
+            }
+            indexChunk = 0;
+        }
+        storedRunDirection = runDirection;
+        storedTotalTextLength = totalTextLength;
+        storedIndexChunk = indexChunk;
+        storedIndexChunkChar = indexChunkChar;
+        storedCurrentChar = currentChar;
+        shortStore = (currentChar < totalTextLength);
+        if (!shortStore) {
+            // long save
+            if (storedText.length < totalTextLength) {
+                storedText = new char[totalTextLength];
+                storedDetailChunks = new PdfChunk[totalTextLength];
+            }
+            System.arraycopy(text, 0, storedText, 0, totalTextLength);
+            System.arraycopy(detailChunks, 0, storedDetailChunks, 0, totalTextLength);
+        }
+        if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+            if (storedOrderLevels.length < totalTextLength) {
+                storedOrderLevels = new byte[totalTextLength];
+                storedIndexChars = new int[totalTextLength];
+            }
+            System.arraycopy(orderLevels, currentChar, storedOrderLevels, currentChar, totalTextLength - currentChar);
+            System.arraycopy(indexChars, currentChar, storedIndexChars, currentChar, totalTextLength - currentChar);
+        }
+    }
+    
+    public void restore() {
+        runDirection = storedRunDirection;
+        totalTextLength = storedTotalTextLength;
+        indexChunk = storedIndexChunk;
+        indexChunkChar = storedIndexChunkChar;
+        currentChar = storedCurrentChar;
+        if (!shortStore) {
+            // long restore
+            System.arraycopy(storedText, 0, text, 0, totalTextLength);
+            System.arraycopy(storedDetailChunks, 0, detailChunks, 0, totalTextLength);
+        }
+        if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+            System.arraycopy(storedOrderLevels, currentChar, orderLevels, currentChar, totalTextLength - currentChar);
+            System.arraycopy(storedIndexChars, currentChar, indexChars, currentChar, totalTextLength - currentChar);
+        }
+    }
+    
+    public void mirrorGlyphs() {
+        for (int k = 0; k < totalTextLength; ++k) {
+            if ((orderLevels[k] & 1) == 1) {
+                int mirror = mirrorChars.get(text[k]);
+                if (mirror != 0)
+                    text[k] = (char)mirror;
+            }
+        }
+    }
+    
+    public void doArabicShapping() {
+        int src = 0;
+        int dest = 0;
+        for (;;) {
+            while (src < totalTextLength) {
+                char c = text[src];
+                if (c >= 0x0600 && c <= 0x06ff)
+                    break;
+                if (src != dest) {
+                    text[dest] = text[src];
+                    detailChunks[dest] = detailChunks[src];
+                    orderLevels[dest] = orderLevels[src];
+                }
+                ++src;
+                ++dest;
+            }
+            if (src >= totalTextLength) {
+                totalTextLength = dest;
+                return;
+            }
+            int startArabicIdx = src;
+            ++src;
+            while (src < totalTextLength) {
+                char c = text[src];
+                if (c < 0x0600 || c > 0x06ff)
+                    break;
+                ++src;
+            }
+            int arabicWordSize = src - startArabicIdx;
+            int size = ArabicLigaturizer.arabic_shape(text, startArabicIdx, arabicWordSize, text, dest, arabicWordSize, arabicOptions /*PangoArabicShapping.ar_novowel PangoArabicShapping.ar_lig | PangoArabicShapping.ar_composedtashkeel*/);
+            if (startArabicIdx != dest) {
+                for (int k = 0; k < size; ++k) {
+                    detailChunks[dest] = detailChunks[startArabicIdx];
+                    orderLevels[dest++] = orderLevels[startArabicIdx++];
+                }
+            }
+            else
+                dest += size;
+        }
+    }
+       
+    public PdfLine processLine(float width, int alignment, int runDirection, int arabicOptions) {
+        this.arabicOptions = arabicOptions;
+        save();
+        boolean isRTL = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
+        if (currentChar >= totalTextLength) {
+            boolean hasText = getParagraph(runDirection);
+            if (!hasText)
+                return null;
+            if (totalTextLength == 0) {
+                ArrayList ar = new ArrayList();
+                PdfChunk ck = new PdfChunk("", detailChunks[0]);
+                ar.add(ck);
+                return new PdfLine(0, 0, alignment, true, ar, isRTL);
+            }
+        }
+        float originalWidth = width;
+        int lastSplit = -1;
+        if (currentChar != 0)
+            currentChar = trimLeftEx(currentChar, totalTextLength - 1);
+        int oldCurrentChar = currentChar;
+        char c = 0;
+        char uniC = 0;
+        PdfChunk ck = null;
+        float charWidth = 0;
+        PdfChunk lastValidChunk = null;
+        for (; currentChar < totalTextLength; ++currentChar) {
+            c = text[currentChar];
+            ck = detailChunks[currentChar];
+            uniC = ck.getUnicodeEquivalent(c);
+            if (PdfChunk.noPrint(uniC))
+                continue;
+            charWidth = ck.getCharWidth(c);
+            if (ck.isExtSplitCharacter(oldCurrentChar, currentChar, totalTextLength, text, detailChunks))
+                lastSplit = currentChar;
+            if (width - charWidth < 0)
+                break;
+            width -= charWidth;
+            lastValidChunk = ck;
+        }
+        if (lastValidChunk == null) {
+            // not even a single char fit; must output the first char
+            ++currentChar;
+            return new PdfLine(0, 0, alignment, false, createArrayOfPdfChunks(currentChar - 1, currentChar - 1), isRTL);
+        }
+        if (currentChar >= totalTextLength) {
+            // there was more line than text
+            return new PdfLine(0, width, alignment, true, createArrayOfPdfChunks(oldCurrentChar, totalTextLength - 1), isRTL);
+        }
+        int newCurrentChar = trimRightEx(oldCurrentChar, currentChar - 1);
+        if (newCurrentChar < oldCurrentChar) {
+            // only WS
+            return new PdfLine(0, width, alignment, false, createArrayOfPdfChunks(oldCurrentChar, currentChar - 1), isRTL);
+        }
+        if (newCurrentChar == currentChar - 1) { // middle of word
+            HyphenationEvent he = (HyphenationEvent)lastValidChunk.getAttribute(Chunk.HYPHENATION);
+            if (he != null) {
+                int word[] = getWord(oldCurrentChar, newCurrentChar);
+                if (word != null) {
+                    float testWidth = width + getWidth(word[0], currentChar - 1);
+                    String pre = he.getHyphenatedWordPre(new String(text, word[0], word[1] - word[0]), lastValidChunk.font().getFont(), lastValidChunk.font().size(), testWidth);
+                    String post = he.getHyphenatedWordPost();
+                    if (pre.length() > 0) {
+                        PdfChunk extra = new PdfChunk(pre, lastValidChunk);
+                        currentChar = word[1] - post.length();
+                        return new PdfLine(0, testWidth - lastValidChunk.font().width(pre), alignment, false, createArrayOfPdfChunks(oldCurrentChar, word[0] - 1, extra), isRTL);
+                    }
+                }
+            }
+        }
+        if (lastSplit == -1 || lastSplit >= newCurrentChar) {
+            // no split point or split point ahead of end
+            return new PdfLine(0, width + getWidth(newCurrentChar + 1, currentChar - 1), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
+        }
+        // standard split
+        currentChar = lastSplit + 1;
+        newCurrentChar = trimRightEx(oldCurrentChar, lastSplit);
+        if (newCurrentChar < oldCurrentChar) {
+            // only WS again
+            newCurrentChar = currentChar - 1;
+        }
+        return new PdfLine(0, originalWidth - getWidth(oldCurrentChar, newCurrentChar), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
+    }
+    
+    /** Gets the width of a range of characters.
+     * @param startIdx the first index to calculate
+     * @param lastIdx the last inclusive index to calculate
+     * @return the sum of all widths
+     */    
+    public float getWidth(int startIdx, int lastIdx) {
+        char c = 0;
+        char uniC;
+        PdfChunk ck = null;
+        float width = 0;
+        for (; startIdx <= lastIdx; ++startIdx) {
+            c = text[startIdx];
+            ck = detailChunks[startIdx];
+            uniC = ck.getUnicodeEquivalent(c);
+            if (PdfChunk.noPrint(uniC))
+                continue;
+            width += detailChunks[startIdx].getCharWidth(c);
+        }
+        return width;
+    }
+    
+    public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx) {
+        return createArrayOfPdfChunks(startIdx, endIdx, null);
+    }
+    
+    public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx, PdfChunk extraPdfChunk) {
+        boolean bidi = (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL);
+        if (bidi)
+            reorder(startIdx, endIdx);
+        ArrayList ar = new ArrayList();
+        PdfChunk refCk = detailChunks[startIdx];
+        PdfChunk ck = null;
+        StringBuffer buf = new StringBuffer();
+        char c;
+        int idx = 0;
+        for (; startIdx <= endIdx; ++startIdx) {
+            idx = bidi ? indexChars[startIdx] : startIdx;
+            c = text[idx];
+            ck = detailChunks[idx];
+            if (PdfChunk.noPrint(ck.getUnicodeEquivalent(c)))
+                continue;
+            if (ck.isImage()) {
+                if (buf.length() > 0) {
+                    ar.add(new PdfChunk(buf.toString(), refCk));
+                    buf = new StringBuffer();
+                }
+                ar.add(ck);
+            }
+            else if (ck == refCk) {
+                buf.append(c);
+            }
+            else {
+                if (buf.length() > 0) {
+                    ar.add(new PdfChunk(buf.toString(), refCk));
+                    buf = new StringBuffer();
+                }
+                if (!ck.isImage())
+                    buf.append(c);
+                refCk = ck;
+            }
+        }
+        if (buf.length() > 0) {
+            ar.add(new PdfChunk(buf.toString(), refCk));
+        }
+        if (extraPdfChunk != null)
+            ar.add(extraPdfChunk);
+        return ar;
+    }
+    
+    public int[] getWord(int startIdx, int idx) {
+        int last = idx;
+        int first = idx;
+        // forward
+        for (; last < totalTextLength; ++last) {
+            if (!Character.isLetter(text[last]))
+                break;            
+        }
+        if (last == idx)
+            return null;
+        // backward
+        for (; first >= startIdx; --first) {
+            if (!Character.isLetter(text[first]))
+                break;            
+        }
+        ++first;
+        return new int[]{first, last};
+    }
+    
+    public int trimRight(int startIdx, int endIdx) {
+        int idx = endIdx;
+        char c;
+        for (; idx >= startIdx; --idx) {
+            c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+            if (!isWS(c))
+                break;
+        }
+        return idx;
+    }
+    
+    public int trimLeft(int startIdx, int endIdx) {
+        int idx = startIdx;
+        char c;
+        for (; idx <= endIdx; ++idx) {
+            c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+            if (!isWS(c))
+                break;
+        }
+        return idx;
+    }
+    
+    public int trimRightEx(int startIdx, int endIdx) {
+        int idx = endIdx;
+        char c = 0;
+        for (; idx >= startIdx; --idx) {
+            c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+            if (!isWS(c) && !PdfChunk.noPrint(c))
+                break;
+        }
+        return idx;
+    }
+    
+    public int trimLeftEx(int startIdx, int endIdx) {
+        int idx = startIdx;
+        char c = 0;
+        for (; idx <= endIdx; ++idx) {
+            c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+            if (!isWS(c) && !PdfChunk.noPrint(c))
+                break;
+        }
+        return idx;
+    }
+    
+    public void reorder(int start, int end) {
+        byte maxLevel = orderLevels[start];
+        byte minLevel = maxLevel;
+        byte onlyOddLevels = maxLevel;
+        byte onlyEvenLevels = maxLevel;
+        for (int k = start + 1; k <= end; ++k) {
+            byte b = orderLevels[k];
+            if (b > maxLevel)
+                maxLevel = b;
+            else if (b < minLevel)
+                minLevel = b;
+            onlyOddLevels &= b;
+            onlyEvenLevels |= b;
+        }
+        if ((onlyEvenLevels & 1) == 0) // nothing to do
+            return;
+        if ((onlyOddLevels & 1) == 1) { // single inversion
+            flip(start, end + 1);
+            return;
+        }
+        minLevel |= 1;
+        for (; maxLevel >= minLevel; --maxLevel) {
+            int pstart = start;
+            for (;;) {
+                for (;pstart <= end; ++pstart) {
+                    if (orderLevels[pstart] >= maxLevel)
+                        break;
+                }
+                if (pstart > end)
+                    break;
+                int pend = pstart + 1;
+                for (; pend <= end; ++pend) {
+                    if (orderLevels[pend] < maxLevel)
+                        break;
+                }
+                flip(pstart, pend);
+                pstart = pend + 1;
+            }
+        }
+    }
+    
+    public void flip(int start, int end) {
+        int mid = (start + end) / 2;
+        --end;
+        for (; start < mid; ++start, --end) {
+            int temp = indexChars[start];
+            indexChars[start] = indexChars[end];
+            indexChars[end] = temp;
+        }
+    }
+    
+    public static boolean isWS(char c) {
+        return (c <= ' ');
+    }
+
+    static {
+        mirrorChars.put(0x0028, 0x0029); // LEFT PARENTHESIS
+        mirrorChars.put(0x0029, 0x0028); // RIGHT PARENTHESIS
+        mirrorChars.put(0x003C, 0x003E); // LESS-THAN SIGN
+        mirrorChars.put(0x003E, 0x003C); // GREATER-THAN SIGN
+        mirrorChars.put(0x005B, 0x005D); // LEFT SQUARE BRACKET
+        mirrorChars.put(0x005D, 0x005B); // RIGHT SQUARE BRACKET
+        mirrorChars.put(0x007B, 0x007D); // LEFT CURLY BRACKET
+        mirrorChars.put(0x007D, 0x007B); // RIGHT CURLY BRACKET
+        mirrorChars.put(0x00AB, 0x00BB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        mirrorChars.put(0x00BB, 0x00AB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        mirrorChars.put(0x2039, 0x203A); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+        mirrorChars.put(0x203A, 0x2039); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+        mirrorChars.put(0x2045, 0x2046); // LEFT SQUARE BRACKET WITH QUILL
+        mirrorChars.put(0x2046, 0x2045); // RIGHT SQUARE BRACKET WITH QUILL
+        mirrorChars.put(0x207D, 0x207E); // SUPERSCRIPT LEFT PARENTHESIS
+        mirrorChars.put(0x207E, 0x207D); // SUPERSCRIPT RIGHT PARENTHESIS
+        mirrorChars.put(0x208D, 0x208E); // SUBSCRIPT LEFT PARENTHESIS
+        mirrorChars.put(0x208E, 0x208D); // SUBSCRIPT RIGHT PARENTHESIS
+        mirrorChars.put(0x2208, 0x220B); // ELEMENT OF
+        mirrorChars.put(0x2209, 0x220C); // NOT AN ELEMENT OF
+        mirrorChars.put(0x220A, 0x220D); // SMALL ELEMENT OF
+        mirrorChars.put(0x220B, 0x2208); // CONTAINS AS MEMBER
+        mirrorChars.put(0x220C, 0x2209); // DOES NOT CONTAIN AS MEMBER
+        mirrorChars.put(0x220D, 0x220A); // SMALL CONTAINS AS MEMBER
+        mirrorChars.put(0x2215, 0x29F5); // DIVISION SLASH
+        mirrorChars.put(0x223C, 0x223D); // TILDE OPERATOR
+        mirrorChars.put(0x223D, 0x223C); // REVERSED TILDE
+        mirrorChars.put(0x2243, 0x22CD); // ASYMPTOTICALLY EQUAL TO
+        mirrorChars.put(0x2252, 0x2253); // APPROXIMATELY EQUAL TO OR THE IMAGE OF
+        mirrorChars.put(0x2253, 0x2252); // IMAGE OF OR APPROXIMATELY EQUAL TO
+        mirrorChars.put(0x2254, 0x2255); // COLON EQUALS
+        mirrorChars.put(0x2255, 0x2254); // EQUALS COLON
+        mirrorChars.put(0x2264, 0x2265); // LESS-THAN OR EQUAL TO
+        mirrorChars.put(0x2265, 0x2264); // GREATER-THAN OR EQUAL TO
+        mirrorChars.put(0x2266, 0x2267); // LESS-THAN OVER EQUAL TO
+        mirrorChars.put(0x2267, 0x2266); // GREATER-THAN OVER EQUAL TO
+        mirrorChars.put(0x2268, 0x2269); // [BEST FIT] LESS-THAN BUT NOT EQUAL TO
+        mirrorChars.put(0x2269, 0x2268); // [BEST FIT] GREATER-THAN BUT NOT EQUAL TO
+        mirrorChars.put(0x226A, 0x226B); // MUCH LESS-THAN
+        mirrorChars.put(0x226B, 0x226A); // MUCH GREATER-THAN
+        mirrorChars.put(0x226E, 0x226F); // [BEST FIT] NOT LESS-THAN
+        mirrorChars.put(0x226F, 0x226E); // [BEST FIT] NOT GREATER-THAN
+        mirrorChars.put(0x2270, 0x2271); // [BEST FIT] NEITHER LESS-THAN NOR EQUAL TO
+        mirrorChars.put(0x2271, 0x2270); // [BEST FIT] NEITHER GREATER-THAN NOR EQUAL TO
+        mirrorChars.put(0x2272, 0x2273); // [BEST FIT] LESS-THAN OR EQUIVALENT TO
+        mirrorChars.put(0x2273, 0x2272); // [BEST FIT] GREATER-THAN OR EQUIVALENT TO
+        mirrorChars.put(0x2274, 0x2275); // [BEST FIT] NEITHER LESS-THAN NOR EQUIVALENT TO
+        mirrorChars.put(0x2275, 0x2274); // [BEST FIT] NEITHER GREATER-THAN NOR EQUIVALENT TO
+        mirrorChars.put(0x2276, 0x2277); // LESS-THAN OR GREATER-THAN
+        mirrorChars.put(0x2277, 0x2276); // GREATER-THAN OR LESS-THAN
+        mirrorChars.put(0x2278, 0x2279); // NEITHER LESS-THAN NOR GREATER-THAN
+        mirrorChars.put(0x2279, 0x2278); // NEITHER GREATER-THAN NOR LESS-THAN
+        mirrorChars.put(0x227A, 0x227B); // PRECEDES
+        mirrorChars.put(0x227B, 0x227A); // SUCCEEDS
+        mirrorChars.put(0x227C, 0x227D); // PRECEDES OR EQUAL TO
+        mirrorChars.put(0x227D, 0x227C); // SUCCEEDS OR EQUAL TO
+        mirrorChars.put(0x227E, 0x227F); // [BEST FIT] PRECEDES OR EQUIVALENT TO
+        mirrorChars.put(0x227F, 0x227E); // [BEST FIT] SUCCEEDS OR EQUIVALENT TO
+        mirrorChars.put(0x2280, 0x2281); // [BEST FIT] DOES NOT PRECEDE
+        mirrorChars.put(0x2281, 0x2280); // [BEST FIT] DOES NOT SUCCEED
+        mirrorChars.put(0x2282, 0x2283); // SUBSET OF
+        mirrorChars.put(0x2283, 0x2282); // SUPERSET OF
+        mirrorChars.put(0x2284, 0x2285); // [BEST FIT] NOT A SUBSET OF
+        mirrorChars.put(0x2285, 0x2284); // [BEST FIT] NOT A SUPERSET OF
+        mirrorChars.put(0x2286, 0x2287); // SUBSET OF OR EQUAL TO
+        mirrorChars.put(0x2287, 0x2286); // SUPERSET OF OR EQUAL TO
+        mirrorChars.put(0x2288, 0x2289); // [BEST FIT] NEITHER A SUBSET OF NOR EQUAL TO
+        mirrorChars.put(0x2289, 0x2288); // [BEST FIT] NEITHER A SUPERSET OF NOR EQUAL TO
+        mirrorChars.put(0x228A, 0x228B); // [BEST FIT] SUBSET OF WITH NOT EQUAL TO
+        mirrorChars.put(0x228B, 0x228A); // [BEST FIT] SUPERSET OF WITH NOT EQUAL TO
+        mirrorChars.put(0x228F, 0x2290); // SQUARE IMAGE OF
+        mirrorChars.put(0x2290, 0x228F); // SQUARE ORIGINAL OF
+        mirrorChars.put(0x2291, 0x2292); // SQUARE IMAGE OF OR EQUAL TO
+        mirrorChars.put(0x2292, 0x2291); // SQUARE ORIGINAL OF OR EQUAL TO
+        mirrorChars.put(0x2298, 0x29B8); // CIRCLED DIVISION SLASH
+        mirrorChars.put(0x22A2, 0x22A3); // RIGHT TACK
+        mirrorChars.put(0x22A3, 0x22A2); // LEFT TACK
+        mirrorChars.put(0x22A6, 0x2ADE); // ASSERTION
+        mirrorChars.put(0x22A8, 0x2AE4); // TRUE
+        mirrorChars.put(0x22A9, 0x2AE3); // FORCES
+        mirrorChars.put(0x22AB, 0x2AE5); // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+        mirrorChars.put(0x22B0, 0x22B1); // PRECEDES UNDER RELATION
+        mirrorChars.put(0x22B1, 0x22B0); // SUCCEEDS UNDER RELATION
+        mirrorChars.put(0x22B2, 0x22B3); // NORMAL SUBGROUP OF
+        mirrorChars.put(0x22B3, 0x22B2); // CONTAINS AS NORMAL SUBGROUP
+        mirrorChars.put(0x22B4, 0x22B5); // NORMAL SUBGROUP OF OR EQUAL TO
+        mirrorChars.put(0x22B5, 0x22B4); // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+        mirrorChars.put(0x22B6, 0x22B7); // ORIGINAL OF
+        mirrorChars.put(0x22B7, 0x22B6); // IMAGE OF
+        mirrorChars.put(0x22C9, 0x22CA); // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+        mirrorChars.put(0x22CA, 0x22C9); // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+        mirrorChars.put(0x22CB, 0x22CC); // LEFT SEMIDIRECT PRODUCT
+        mirrorChars.put(0x22CC, 0x22CB); // RIGHT SEMIDIRECT PRODUCT
+        mirrorChars.put(0x22CD, 0x2243); // REVERSED TILDE EQUALS
+        mirrorChars.put(0x22D0, 0x22D1); // DOUBLE SUBSET
+        mirrorChars.put(0x22D1, 0x22D0); // DOUBLE SUPERSET
+        mirrorChars.put(0x22D6, 0x22D7); // LESS-THAN WITH DOT
+        mirrorChars.put(0x22D7, 0x22D6); // GREATER-THAN WITH DOT
+        mirrorChars.put(0x22D8, 0x22D9); // VERY MUCH LESS-THAN
+        mirrorChars.put(0x22D9, 0x22D8); // VERY MUCH GREATER-THAN
+        mirrorChars.put(0x22DA, 0x22DB); // LESS-THAN EQUAL TO OR GREATER-THAN
+        mirrorChars.put(0x22DB, 0x22DA); // GREATER-THAN EQUAL TO OR LESS-THAN
+        mirrorChars.put(0x22DC, 0x22DD); // EQUAL TO OR LESS-THAN
+        mirrorChars.put(0x22DD, 0x22DC); // EQUAL TO OR GREATER-THAN
+        mirrorChars.put(0x22DE, 0x22DF); // EQUAL TO OR PRECEDES
+        mirrorChars.put(0x22DF, 0x22DE); // EQUAL TO OR SUCCEEDS
+        mirrorChars.put(0x22E0, 0x22E1); // [BEST FIT] DOES NOT PRECEDE OR EQUAL
+        mirrorChars.put(0x22E1, 0x22E0); // [BEST FIT] DOES NOT SUCCEED OR EQUAL
+        mirrorChars.put(0x22E2, 0x22E3); // [BEST FIT] NOT SQUARE IMAGE OF OR EQUAL TO
+        mirrorChars.put(0x22E3, 0x22E2); // [BEST FIT] NOT SQUARE ORIGINAL OF OR EQUAL TO
+        mirrorChars.put(0x22E4, 0x22E5); // [BEST FIT] SQUARE IMAGE OF OR NOT EQUAL TO
+        mirrorChars.put(0x22E5, 0x22E4); // [BEST FIT] SQUARE ORIGINAL OF OR NOT EQUAL TO
+        mirrorChars.put(0x22E6, 0x22E7); // [BEST FIT] LESS-THAN BUT NOT EQUIVALENT TO
+        mirrorChars.put(0x22E7, 0x22E6); // [BEST FIT] GREATER-THAN BUT NOT EQUIVALENT TO
+        mirrorChars.put(0x22E8, 0x22E9); // [BEST FIT] PRECEDES BUT NOT EQUIVALENT TO
+        mirrorChars.put(0x22E9, 0x22E8); // [BEST FIT] SUCCEEDS BUT NOT EQUIVALENT TO
+        mirrorChars.put(0x22EA, 0x22EB); // [BEST FIT] NOT NORMAL SUBGROUP OF
+        mirrorChars.put(0x22EB, 0x22EA); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP
+        mirrorChars.put(0x22EC, 0x22ED); // [BEST FIT] NOT NORMAL SUBGROUP OF OR EQUAL TO
+        mirrorChars.put(0x22ED, 0x22EC); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+        mirrorChars.put(0x22F0, 0x22F1); // UP RIGHT DIAGONAL ELLIPSIS
+        mirrorChars.put(0x22F1, 0x22F0); // DOWN RIGHT DIAGONAL ELLIPSIS
+        mirrorChars.put(0x22F2, 0x22FA); // ELEMENT OF WITH LONG HORIZONTAL STROKE
+        mirrorChars.put(0x22F3, 0x22FB); // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+        mirrorChars.put(0x22F4, 0x22FC); // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+        mirrorChars.put(0x22F6, 0x22FD); // ELEMENT OF WITH OVERBAR
+        mirrorChars.put(0x22F7, 0x22FE); // SMALL ELEMENT OF WITH OVERBAR
+        mirrorChars.put(0x22FA, 0x22F2); // CONTAINS WITH LONG HORIZONTAL STROKE
+        mirrorChars.put(0x22FB, 0x22F3); // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+        mirrorChars.put(0x22FC, 0x22F4); // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+        mirrorChars.put(0x22FD, 0x22F6); // CONTAINS WITH OVERBAR
+        mirrorChars.put(0x22FE, 0x22F7); // SMALL CONTAINS WITH OVERBAR
+        mirrorChars.put(0x2308, 0x2309); // LEFT CEILING
+        mirrorChars.put(0x2309, 0x2308); // RIGHT CEILING
+        mirrorChars.put(0x230A, 0x230B); // LEFT FLOOR
+        mirrorChars.put(0x230B, 0x230A); // RIGHT FLOOR
+        mirrorChars.put(0x2329, 0x232A); // LEFT-POINTING ANGLE BRACKET
+        mirrorChars.put(0x232A, 0x2329); // RIGHT-POINTING ANGLE BRACKET
+        mirrorChars.put(0x2768, 0x2769); // MEDIUM LEFT PARENTHESIS ORNAMENT
+        mirrorChars.put(0x2769, 0x2768); // MEDIUM RIGHT PARENTHESIS ORNAMENT
+        mirrorChars.put(0x276A, 0x276B); // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+        mirrorChars.put(0x276B, 0x276A); // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+        mirrorChars.put(0x276C, 0x276D); // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+        mirrorChars.put(0x276D, 0x276C); // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+        mirrorChars.put(0x276E, 0x276F); // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+        mirrorChars.put(0x276F, 0x276E); // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+        mirrorChars.put(0x2770, 0x2771); // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+        mirrorChars.put(0x2771, 0x2770); // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+        mirrorChars.put(0x2772, 0x2773); // LIGHT LEFT TORTOISE SHELL BRACKET
+        mirrorChars.put(0x2773, 0x2772); // LIGHT RIGHT TORTOISE SHELL BRACKET
+        mirrorChars.put(0x2774, 0x2775); // MEDIUM LEFT CURLY BRACKET ORNAMENT
+        mirrorChars.put(0x2775, 0x2774); // MEDIUM RIGHT CURLY BRACKET ORNAMENT
+        mirrorChars.put(0x27D5, 0x27D6); // LEFT OUTER JOIN
+        mirrorChars.put(0x27D6, 0x27D5); // RIGHT OUTER JOIN
+        mirrorChars.put(0x27DD, 0x27DE); // LONG RIGHT TACK
+        mirrorChars.put(0x27DE, 0x27DD); // LONG LEFT TACK
+        mirrorChars.put(0x27E2, 0x27E3); // WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
+        mirrorChars.put(0x27E3, 0x27E2); // WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
+        mirrorChars.put(0x27E4, 0x27E5); // WHITE SQUARE WITH LEFTWARDS TICK
+        mirrorChars.put(0x27E5, 0x27E4); // WHITE SQUARE WITH RIGHTWARDS TICK
+        mirrorChars.put(0x27E6, 0x27E7); // MATHEMATICAL LEFT WHITE SQUARE BRACKET
+        mirrorChars.put(0x27E7, 0x27E6); // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+        mirrorChars.put(0x27E8, 0x27E9); // MATHEMATICAL LEFT ANGLE BRACKET
+        mirrorChars.put(0x27E9, 0x27E8); // MATHEMATICAL RIGHT ANGLE BRACKET
+        mirrorChars.put(0x27EA, 0x27EB); // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+        mirrorChars.put(0x27EB, 0x27EA); // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+        mirrorChars.put(0x2983, 0x2984); // LEFT WHITE CURLY BRACKET
+        mirrorChars.put(0x2984, 0x2983); // RIGHT WHITE CURLY BRACKET
+        mirrorChars.put(0x2985, 0x2986); // LEFT WHITE PARENTHESIS
+        mirrorChars.put(0x2986, 0x2985); // RIGHT WHITE PARENTHESIS
+        mirrorChars.put(0x2987, 0x2988); // Z NOTATION LEFT IMAGE BRACKET
+        mirrorChars.put(0x2988, 0x2987); // Z NOTATION RIGHT IMAGE BRACKET
+        mirrorChars.put(0x2989, 0x298A); // Z NOTATION LEFT BINDING BRACKET
+        mirrorChars.put(0x298A, 0x2989); // Z NOTATION RIGHT BINDING BRACKET
+        mirrorChars.put(0x298B, 0x298C); // LEFT SQUARE BRACKET WITH UNDERBAR
+        mirrorChars.put(0x298C, 0x298B); // RIGHT SQUARE BRACKET WITH UNDERBAR
+        mirrorChars.put(0x298D, 0x2990); // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+        mirrorChars.put(0x298E, 0x298F); // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+        mirrorChars.put(0x298F, 0x298E); // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+        mirrorChars.put(0x2990, 0x298D); // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+        mirrorChars.put(0x2991, 0x2992); // LEFT ANGLE BRACKET WITH DOT
+        mirrorChars.put(0x2992, 0x2991); // RIGHT ANGLE BRACKET WITH DOT
+        mirrorChars.put(0x2993, 0x2994); // LEFT ARC LESS-THAN BRACKET
+        mirrorChars.put(0x2994, 0x2993); // RIGHT ARC GREATER-THAN BRACKET
+        mirrorChars.put(0x2995, 0x2996); // DOUBLE LEFT ARC GREATER-THAN BRACKET
+        mirrorChars.put(0x2996, 0x2995); // DOUBLE RIGHT ARC LESS-THAN BRACKET
+        mirrorChars.put(0x2997, 0x2998); // LEFT BLACK TORTOISE SHELL BRACKET
+        mirrorChars.put(0x2998, 0x2997); // RIGHT BLACK TORTOISE SHELL BRACKET
+        mirrorChars.put(0x29B8, 0x2298); // CIRCLED REVERSE SOLIDUS
+        mirrorChars.put(0x29C0, 0x29C1); // CIRCLED LESS-THAN
+        mirrorChars.put(0x29C1, 0x29C0); // CIRCLED GREATER-THAN
+        mirrorChars.put(0x29C4, 0x29C5); // SQUARED RISING DIAGONAL SLASH
+        mirrorChars.put(0x29C5, 0x29C4); // SQUARED FALLING DIAGONAL SLASH
+        mirrorChars.put(0x29CF, 0x29D0); // LEFT TRIANGLE BESIDE VERTICAL BAR
+        mirrorChars.put(0x29D0, 0x29CF); // VERTICAL BAR BESIDE RIGHT TRIANGLE
+        mirrorChars.put(0x29D1, 0x29D2); // BOWTIE WITH LEFT HALF BLACK
+        mirrorChars.put(0x29D2, 0x29D1); // BOWTIE WITH RIGHT HALF BLACK
+        mirrorChars.put(0x29D4, 0x29D5); // TIMES WITH LEFT HALF BLACK
+        mirrorChars.put(0x29D5, 0x29D4); // TIMES WITH RIGHT HALF BLACK
+        mirrorChars.put(0x29D8, 0x29D9); // LEFT WIGGLY FENCE
+        mirrorChars.put(0x29D9, 0x29D8); // RIGHT WIGGLY FENCE
+        mirrorChars.put(0x29DA, 0x29DB); // LEFT DOUBLE WIGGLY FENCE
+        mirrorChars.put(0x29DB, 0x29DA); // RIGHT DOUBLE WIGGLY FENCE
+        mirrorChars.put(0x29F5, 0x2215); // REVERSE SOLIDUS OPERATOR
+        mirrorChars.put(0x29F8, 0x29F9); // BIG SOLIDUS
+        mirrorChars.put(0x29F9, 0x29F8); // BIG REVERSE SOLIDUS
+        mirrorChars.put(0x29FC, 0x29FD); // LEFT-POINTING CURVED ANGLE BRACKET
+        mirrorChars.put(0x29FD, 0x29FC); // RIGHT-POINTING CURVED ANGLE BRACKET
+        mirrorChars.put(0x2A2B, 0x2A2C); // MINUS SIGN WITH FALLING DOTS
+        mirrorChars.put(0x2A2C, 0x2A2B); // MINUS SIGN WITH RISING DOTS
+        mirrorChars.put(0x2A2D, 0x2A2C); // PLUS SIGN IN LEFT HALF CIRCLE
+        mirrorChars.put(0x2A2E, 0x2A2D); // PLUS SIGN IN RIGHT HALF CIRCLE
+        mirrorChars.put(0x2A34, 0x2A35); // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
+        mirrorChars.put(0x2A35, 0x2A34); // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
+        mirrorChars.put(0x2A3C, 0x2A3D); // INTERIOR PRODUCT
+        mirrorChars.put(0x2A3D, 0x2A3C); // RIGHTHAND INTERIOR PRODUCT
+        mirrorChars.put(0x2A64, 0x2A65); // Z NOTATION DOMAIN ANTIRESTRICTION
+        mirrorChars.put(0x2A65, 0x2A64); // Z NOTATION RANGE ANTIRESTRICTION
+        mirrorChars.put(0x2A79, 0x2A7A); // LESS-THAN WITH CIRCLE INSIDE
+        mirrorChars.put(0x2A7A, 0x2A79); // GREATER-THAN WITH CIRCLE INSIDE
+        mirrorChars.put(0x2A7D, 0x2A7E); // LESS-THAN OR SLANTED EQUAL TO
+        mirrorChars.put(0x2A7E, 0x2A7D); // GREATER-THAN OR SLANTED EQUAL TO
+        mirrorChars.put(0x2A7F, 0x2A80); // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+        mirrorChars.put(0x2A80, 0x2A7F); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+        mirrorChars.put(0x2A81, 0x2A82); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+        mirrorChars.put(0x2A82, 0x2A81); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+        mirrorChars.put(0x2A83, 0x2A84); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
+        mirrorChars.put(0x2A84, 0x2A83); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
+        mirrorChars.put(0x2A8B, 0x2A8C); // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+        mirrorChars.put(0x2A8C, 0x2A8B); // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+        mirrorChars.put(0x2A91, 0x2A92); // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
+        mirrorChars.put(0x2A92, 0x2A91); // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
+        mirrorChars.put(0x2A93, 0x2A94); // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
+        mirrorChars.put(0x2A94, 0x2A93); // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
+        mirrorChars.put(0x2A95, 0x2A96); // SLANTED EQUAL TO OR LESS-THAN
+        mirrorChars.put(0x2A96, 0x2A95); // SLANTED EQUAL TO OR GREATER-THAN
+        mirrorChars.put(0x2A97, 0x2A98); // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
+        mirrorChars.put(0x2A98, 0x2A97); // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
+        mirrorChars.put(0x2A99, 0x2A9A); // DOUBLE-LINE EQUAL TO OR LESS-THAN
+        mirrorChars.put(0x2A9A, 0x2A99); // DOUBLE-LINE EQUAL TO OR GREATER-THAN
+        mirrorChars.put(0x2A9B, 0x2A9C); // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
+        mirrorChars.put(0x2A9C, 0x2A9B); // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
+        mirrorChars.put(0x2AA1, 0x2AA2); // DOUBLE NESTED LESS-THAN
+        mirrorChars.put(0x2AA2, 0x2AA1); // DOUBLE NESTED GREATER-THAN
+        mirrorChars.put(0x2AA6, 0x2AA7); // LESS-THAN CLOSED BY CURVE
+        mirrorChars.put(0x2AA7, 0x2AA6); // GREATER-THAN CLOSED BY CURVE
+        mirrorChars.put(0x2AA8, 0x2AA9); // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+        mirrorChars.put(0x2AA9, 0x2AA8); // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+        mirrorChars.put(0x2AAA, 0x2AAB); // SMALLER THAN
+        mirrorChars.put(0x2AAB, 0x2AAA); // LARGER THAN
+        mirrorChars.put(0x2AAC, 0x2AAD); // SMALLER THAN OR EQUAL TO
+        mirrorChars.put(0x2AAD, 0x2AAC); // LARGER THAN OR EQUAL TO
+        mirrorChars.put(0x2AAF, 0x2AB0); // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+        mirrorChars.put(0x2AB0, 0x2AAF); // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+        mirrorChars.put(0x2AB3, 0x2AB4); // PRECEDES ABOVE EQUALS SIGN
+        mirrorChars.put(0x2AB4, 0x2AB3); // SUCCEEDS ABOVE EQUALS SIGN
+        mirrorChars.put(0x2ABB, 0x2ABC); // DOUBLE PRECEDES
+        mirrorChars.put(0x2ABC, 0x2ABB); // DOUBLE SUCCEEDS
+        mirrorChars.put(0x2ABD, 0x2ABE); // SUBSET WITH DOT
+        mirrorChars.put(0x2ABE, 0x2ABD); // SUPERSET WITH DOT
+        mirrorChars.put(0x2ABF, 0x2AC0); // SUBSET WITH PLUS SIGN BELOW
+        mirrorChars.put(0x2AC0, 0x2ABF); // SUPERSET WITH PLUS SIGN BELOW
+        mirrorChars.put(0x2AC1, 0x2AC2); // SUBSET WITH MULTIPLICATION SIGN BELOW
+        mirrorChars.put(0x2AC2, 0x2AC1); // SUPERSET WITH MULTIPLICATION SIGN BELOW
+        mirrorChars.put(0x2AC3, 0x2AC4); // SUBSET OF OR EQUAL TO WITH DOT ABOVE
+        mirrorChars.put(0x2AC4, 0x2AC3); // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
+        mirrorChars.put(0x2AC5, 0x2AC6); // SUBSET OF ABOVE EQUALS SIGN
+        mirrorChars.put(0x2AC6, 0x2AC5); // SUPERSET OF ABOVE EQUALS SIGN
+        mirrorChars.put(0x2ACD, 0x2ACE); // SQUARE LEFT OPEN BOX OPERATOR
+        mirrorChars.put(0x2ACE, 0x2ACD); // SQUARE RIGHT OPEN BOX OPERATOR
+        mirrorChars.put(0x2ACF, 0x2AD0); // CLOSED SUBSET
+        mirrorChars.put(0x2AD0, 0x2ACF); // CLOSED SUPERSET
+        mirrorChars.put(0x2AD1, 0x2AD2); // CLOSED SUBSET OR EQUAL TO
+        mirrorChars.put(0x2AD2, 0x2AD1); // CLOSED SUPERSET OR EQUAL TO
+        mirrorChars.put(0x2AD3, 0x2AD4); // SUBSET ABOVE SUPERSET
+        mirrorChars.put(0x2AD4, 0x2AD3); // SUPERSET ABOVE SUBSET
+        mirrorChars.put(0x2AD5, 0x2AD6); // SUBSET ABOVE SUBSET
+        mirrorChars.put(0x2AD6, 0x2AD5); // SUPERSET ABOVE SUPERSET
+        mirrorChars.put(0x2ADE, 0x22A6); // SHORT LEFT TACK
+        mirrorChars.put(0x2AE3, 0x22A9); // DOUBLE VERTICAL BAR LEFT TURNSTILE
+        mirrorChars.put(0x2AE4, 0x22A8); // VERTICAL BAR DOUBLE LEFT TURNSTILE
+        mirrorChars.put(0x2AE5, 0x22AB); // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
+        mirrorChars.put(0x2AEC, 0x2AED); // DOUBLE STROKE NOT SIGN
+        mirrorChars.put(0x2AED, 0x2AEC); // REVERSED DOUBLE STROKE NOT SIGN
+        mirrorChars.put(0x2AF7, 0x2AF8); // TRIPLE NESTED LESS-THAN
+        mirrorChars.put(0x2AF8, 0x2AF7); // TRIPLE NESTED GREATER-THAN
+        mirrorChars.put(0x2AF9, 0x2AFA); // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
+        mirrorChars.put(0x2AFA, 0x2AF9); // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
+        mirrorChars.put(0x3008, 0x3009); // LEFT ANGLE BRACKET
+        mirrorChars.put(0x3009, 0x3008); // RIGHT ANGLE BRACKET
+        mirrorChars.put(0x300A, 0x300B); // LEFT DOUBLE ANGLE BRACKET
+        mirrorChars.put(0x300B, 0x300A); // RIGHT DOUBLE ANGLE BRACKET
+        mirrorChars.put(0x300C, 0x300D); // [BEST FIT] LEFT CORNER BRACKET
+        mirrorChars.put(0x300D, 0x300C); // [BEST FIT] RIGHT CORNER BRACKET
+        mirrorChars.put(0x300E, 0x300F); // [BEST FIT] LEFT WHITE CORNER BRACKET
+        mirrorChars.put(0x300F, 0x300E); // [BEST FIT] RIGHT WHITE CORNER BRACKET
+        mirrorChars.put(0x3010, 0x3011); // LEFT BLACK LENTICULAR BRACKET
+        mirrorChars.put(0x3011, 0x3010); // RIGHT BLACK LENTICULAR BRACKET
+        mirrorChars.put(0x3014, 0x3015); // LEFT TORTOISE SHELL BRACKET
+        mirrorChars.put(0x3015, 0x3014); // RIGHT TORTOISE SHELL BRACKET
+        mirrorChars.put(0x3016, 0x3017); // LEFT WHITE LENTICULAR BRACKET
+        mirrorChars.put(0x3017, 0x3016); // RIGHT WHITE LENTICULAR BRACKET
+        mirrorChars.put(0x3018, 0x3019); // LEFT WHITE TORTOISE SHELL BRACKET
+        mirrorChars.put(0x3019, 0x3018); // RIGHT WHITE TORTOISE SHELL BRACKET
+        mirrorChars.put(0x301A, 0x301B); // LEFT WHITE SQUARE BRACKET
+        mirrorChars.put(0x301B, 0x301A); // RIGHT WHITE SQUARE BRACKET
+        mirrorChars.put(0xFF08, 0xFF09); // FULLWIDTH LEFT PARENTHESIS
+        mirrorChars.put(0xFF09, 0xFF08); // FULLWIDTH RIGHT PARENTHESIS
+        mirrorChars.put(0xFF1C, 0xFF1E); // FULLWIDTH LESS-THAN SIGN
+        mirrorChars.put(0xFF1E, 0xFF1C); // FULLWIDTH GREATER-THAN SIGN
+        mirrorChars.put(0xFF3B, 0xFF3D); // FULLWIDTH LEFT SQUARE BRACKET
+        mirrorChars.put(0xFF3D, 0xFF3B); // FULLWIDTH RIGHT SQUARE BRACKET
+        mirrorChars.put(0xFF5B, 0xFF5D); // FULLWIDTH LEFT CURLY BRACKET
+        mirrorChars.put(0xFF5D, 0xFF5B); // FULLWIDTH RIGHT CURLY BRACKET
+        mirrorChars.put(0xFF5F, 0xFF60); // FULLWIDTH LEFT WHITE PARENTHESIS
+        mirrorChars.put(0xFF60, 0xFF5F); // FULLWIDTH RIGHT WHITE PARENTHESIS
+        mirrorChars.put(0xFF62, 0xFF63); // [BEST FIT] HALFWIDTH LEFT CORNER BRACKET
+        mirrorChars.put(0xFF63, 0xFF62); // [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/BidiOrder.java b/LibrarySource/com/lowagie/text/pdf/BidiOrder.java
new file mode 100644
index 0000000..93dd829
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/BidiOrder.java
@@ -0,0 +1,1241 @@
+package com.lowagie.text.pdf;
+
+/*
+ *
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+/*
+ * (C) Copyright IBM Corp. 1999, All Rights Reserved
+ *
+ * version 1.1
+ */
+
+/**
+ * Reference implementation of the Unicode 3.0 Bidi algorithm.
+ *
+ * <p>
+ * This implementation is not optimized for performance.  It is intended
+ * as a reference implementation that closely follows the specification
+ * of the Bidirectional Algorithm in The Unicode Standard version 3.0.
+ * <p>
+ * <b>Input:</b><br>
+ * There are two levels of input to the algorithm, since clients may prefer
+ * to supply some information from out-of-band sources rather than relying on
+ * the default behavior.
+ * <ol>
+ * <li>unicode type array
+ * <li>unicode type array, with externally supplied base line direction
+ * </ol>
+ * <p><b>Output:</b><br>
+ * Output is separated into several stages as well, to better enable clients
+ * to evaluate various aspects of implementation conformance.
+ * <ol>
+ * <li>levels array over entire paragraph
+ * <li>reordering array over entire paragraph
+ * <li>levels array over line
+ * <li>reordering array over line
+ * </ol>
+ * Note that for conformance, algorithms are only required to generate correct
+ * reordering and character directionality (odd or even levels) over a line.
+ * Generating identical level arrays over a line is not required.  Bidi
+ * explicit format codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned
+ * arbitrary levels and positions as long as the other text matches.
+ * <p>
+ * As the algorithm is defined to operate on a single paragraph at a time,
+ * this implementation is written to handle single paragraphs.  Thus
+ * rule P1 is presumed by this implementation-- the data provided to the
+ * implementation is assumed to be a single paragraph, and either contains no
+ * 'B' codes, or a single 'B' code at the end of the input.  'B' is allowed
+ * as input to illustrate how the algorithm assigns it a level.
+ * <p>
+ * Also note that rules L3 and L4 depend on the rendering engine that uses
+ * the result of the bidi algorithm.  This implementation assumes that the
+ * rendering engine expects combining marks in visual order (e.g. to the
+ * left of their base character in RTL runs) and that it adjust the glyphs
+ * used to render mirrored characters that are in RTL runs so that they
+ * render appropriately.
+ *
+ * @author Doug Felt
+ */
+
+public final class BidiOrder {
+    private byte[] initialTypes;
+    private byte[] embeddings; // generated from processing format codes
+    private byte paragraphEmbeddingLevel = -1; // undefined
+    
+    private int textLength; // for convenience
+    private byte[] resultTypes; // for paragraph, not lines
+    private byte[] resultLevels; // for paragraph, not lines
+    
+    // The bidi types
+    
+    /** Left-to-right*/
+    public static final byte L = 0;
+    
+    /** Left-to-Right Embedding */
+    public static final byte LRE = 1;
+    
+    /** Left-to-Right Override */
+    public static final byte LRO = 2;
+    
+    /** Right-to-Left */
+    public static final byte R = 3;
+    
+    /** Right-to-Left Arabic */
+    public static final byte AL = 4;
+    
+    /** Right-to-Left Embedding */
+    public static final byte RLE = 5;
+    
+    /** Right-to-Left Override */
+    public static final byte RLO = 6;
+    
+    /** Pop Directional Format */
+    public static final byte PDF = 7;
+    
+    /** European Number */
+    public static final byte EN = 8;
+    
+    /** European Number Separator */
+    public static final byte ES = 9;
+    
+    /** European Number Terminator */
+    public static final byte ET = 10;
+    
+    /** Arabic Number */
+    public static final byte AN = 11;
+    
+    /** Common Number Separator */
+    public static final byte CS = 12;
+    
+    /** Non-Spacing Mark */
+    public static final byte NSM = 13;
+    
+    /** Boundary Neutral */
+    public static final byte BN = 14;
+    
+    /** Paragraph Separator */
+    public static final byte B = 15;
+    
+    /** Segment Separator */
+    public static final byte S = 16;
+    
+    /** Whitespace */
+    public static final byte WS = 17;
+    
+    /** Other Neutrals */
+    public static final byte ON = 18;
+    
+    /** Minimum bidi type value. */
+    public static final byte TYPE_MIN = 0;
+    
+    /** Maximum bidi type value. */
+    public static final byte TYPE_MAX = 18;
+    
+    //
+    // Input
+    //
+    
+    /**
+     * Initialize using an array of direction types.  Types range from TYPE_MIN to TYPE_MAX inclusive
+     * and represent the direction codes of the characters in the text.
+     *
+     * @param types the types array
+     */
+    public BidiOrder(byte[] types) {
+        validateTypes(types);
+        
+        this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
+        
+        runAlgorithm();
+    }
+    
+    /**
+     * Initialize using an array of direction types and an externally supplied paragraph embedding level.
+     * The embedding level may be -1, 0, or 1.  -1 means to apply the default algorithm (rules P2 and P3),
+     * 0 is for LTR paragraphs, and 1 is for RTL paragraphs.
+     *
+     * @param types the types array
+     * @param paragraphEmbeddingLevel the externally supplied paragraph embedding level.
+     */
+    public BidiOrder(byte[] types, byte paragraphEmbeddingLevel) {
+        validateTypes(types);
+        validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
+        
+        this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
+        this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
+        
+        runAlgorithm();
+    }
+    
+    public BidiOrder(char text[], int offset, int length, byte paragraphEmbeddingLevel) {
+        initialTypes = new byte[length];
+        for (int k = 0; k < length; ++k) {
+            initialTypes[k] = rtypes[text[offset + k]];
+        }
+        validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
+        
+        this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
+        
+        runAlgorithm();
+    }
+    
+    public final static byte getDirection(char c) {
+        return rtypes[c];
+    }
+    
+    /**
+     * The algorithm.
+     * Does not include line-based processing (Rules L1, L2).
+     * These are applied later in the line-based phase of the algorithm.
+     */
+    private void runAlgorithm() {
+        textLength = initialTypes.length;
+        
+        // Initialize output types.
+        // Result types initialized to input types.
+        resultTypes = (byte[])initialTypes.clone();
+        
+        
+        // 1) determining the paragraph level
+        // Rule P1 is the requirement for entering this algorithm.
+        // Rules P2, P3.
+        // If no externally supplied paragraph embedding level, use default.
+        if (paragraphEmbeddingLevel == -1) {
+            determineParagraphEmbeddingLevel();
+        }
+        
+        // Initialize result levels to paragraph embedding level.
+        resultLevels = new byte[textLength];
+        setLevels(0, textLength, paragraphEmbeddingLevel);
+        
+        // 2) Explicit levels and directions
+        // Rules X1-X8.
+        determineExplicitEmbeddingLevels();
+        
+        // Rule X9.
+        textLength = removeExplicitCodes();
+        
+        // Rule X10.
+        // Run remainder of algorithm one level run at a time
+        byte prevLevel = paragraphEmbeddingLevel;
+        int start = 0;
+        while (start < textLength) {
+            byte level = resultLevels[start];
+            byte prevType = typeForLevel(Math.max(prevLevel, level));
+            
+            int limit = start + 1;
+            while (limit < textLength && resultLevels[limit] == level) {
+                ++limit;
+            }
+            
+            byte succLevel = limit < textLength ? resultLevels[limit] : paragraphEmbeddingLevel;
+            byte succType = typeForLevel(Math.max(succLevel, level));
+            
+            // 3) resolving weak types
+            // Rules W1-W7.
+            resolveWeakTypes(start, limit, level, prevType, succType);
+            
+            // 4) resolving neutral types
+            // Rules N1-N3.
+            resolveNeutralTypes(start, limit, level, prevType, succType);
+            
+            // 5) resolving implicit embedding levels
+            // Rules I1, I2.
+            resolveImplicitLevels(start, limit, level, prevType, succType);
+            
+            prevLevel = level;
+            start = limit;
+        }
+        
+        // Reinsert explicit codes and assign appropriate levels to 'hide' them.
+        // This is for convenience, so the resulting level array maps 1-1
+        // with the initial array.
+        // See the implementation suggestions section of TR#9 for guidelines on
+        // how to implement the algorithm without removing and reinserting the codes.
+        textLength = reinsertExplicitCodes(textLength);
+    }
+    
+    /**
+     * 1) determining the paragraph level.
+     * <p>
+     * Rules P2, P3.
+     * <p>
+     * At the end of this function, the member variable paragraphEmbeddingLevel is set to either 0 or 1.
+     */
+    private void determineParagraphEmbeddingLevel() {
+        byte strongType = -1; // unknown
+        
+        // Rule P2.
+        for (int i = 0; i < textLength; ++i) {
+            byte t = resultTypes[i];
+            if (t == L || t == AL || t == R) {
+                strongType = t;
+                break;
+            }
+        }
+        
+        // Rule P3.
+        if (strongType == -1) { // none found
+            // default embedding level when no strong types found is 0.
+            paragraphEmbeddingLevel = 0;
+        } else if (strongType == L) {
+            paragraphEmbeddingLevel = 0;
+        } else { // AL, R
+            paragraphEmbeddingLevel = 1;
+        }
+    }
+    
+    /**
+     * Process embedding format codes.
+     * <p>
+     * Calls processEmbeddings to generate an embedding array from the explicit format codes.  The
+     * embedding overrides in the array are then applied to the result types, and the result levels are
+     * initialized.
+     * @see #processEmbeddings
+     */
+    private void determineExplicitEmbeddingLevels() {
+        embeddings = processEmbeddings(resultTypes, paragraphEmbeddingLevel);
+        
+        for (int i = 0; i < textLength; ++i) {
+            byte level = embeddings[i];
+            if ((level & 0x80) != 0) {
+                level &= 0x7f;
+                resultTypes[i] = typeForLevel(level);
+            }
+            resultLevels[i] = level;
+        }
+    }
+    
+    /**
+     * Rules X9.
+     * Remove explicit codes so that they may be ignored during the remainder
+     * of the main portion of the algorithm.  The length of the resulting text
+     * is returned.
+     * @return the length of the data excluding explicit codes and BN.
+     */
+    private int removeExplicitCodes() {
+        int w = 0;
+        for (int i = 0; i < textLength; ++i) {
+            byte t = initialTypes[i];
+            if (!(t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN)) {
+                embeddings[w] = embeddings[i];
+                resultTypes[w] = resultTypes[i];
+                resultLevels[w] = resultLevels[i];
+                w++;
+            }
+        }
+        return w; // new textLength while explicit levels are removed
+    }
+    
+    /**
+     * Reinsert levels information for explicit codes.
+     * This is for ease of relating the level information
+     * to the original input data.  Note that the levels
+     * assigned to these codes are arbitrary, they're
+     * chosen so as to avoid breaking level runs.
+     * @param textLength the length of the data after compression
+     * @return the length of the data (original length of
+     * types array supplied to constructor)
+     */
+    private int reinsertExplicitCodes(int textLength) {
+        int r = textLength;
+        for (int i = initialTypes.length; --i >= 0;) {
+            byte t = initialTypes[i];
+            if (t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN) {
+                embeddings[i] = 0;
+                resultTypes[i] = t;
+                resultLevels[i] = -1;
+            } else {
+                --textLength;
+                embeddings[i] = embeddings[textLength];
+                resultTypes[i] = resultTypes[textLength];
+                resultLevels[i] = resultLevels[textLength];
+            }
+        }
+        
+        // now propagate forward the levels information (could have
+        // propagated backward, the main thing is not to introduce a level
+        // break where one doesn't already exist).
+        
+        if (resultLevels[0] == -1) {
+            resultLevels[0] = paragraphEmbeddingLevel;
+        }
+        for (int i = 1; i < initialTypes.length; ++i) {
+            if (resultLevels[i] == -1) {
+                resultLevels[i] = resultLevels[i-1];
+            }
+        }
+        
+        // Embedding information is for informational purposes only
+        // so need not be adjusted.
+        
+        return initialTypes.length;
+    }
+    
+    /**
+     * 2) determining explicit levels
+     * Rules X1 - X8
+     *
+     * The interaction of these rules makes handling them a bit complex.
+     * This examines resultTypes but does not modify it.  It returns embedding and
+     * override information in the result array.  The low 7 bits are the level, the high
+     * bit is set if the level is an override, and clear if it is an embedding.
+     */
+    private static byte[] processEmbeddings(byte[] resultTypes, byte paragraphEmbeddingLevel) {
+        final int EXPLICIT_LEVEL_LIMIT = 62;
+        
+        int textLength = resultTypes.length;
+        byte[] embeddings = new byte[textLength];
+        
+        // This stack will store the embedding levels and override status in a single byte
+        // as described above.
+        byte[] embeddingValueStack = new byte[EXPLICIT_LEVEL_LIMIT];
+        int stackCounter = 0;
+        
+        // An LRE or LRO at level 60 is invalid, since the new level 62 is invalid.  But
+        // an RLE at level 60 is valid, since the new level 61 is valid.  The current wording
+        // of the rules requires that the RLE remain valid even if a previous LRE is invalid.
+        // This keeps track of ignored LRE or LRO codes at level 60, so that the matching PDFs
+        // will not try to pop the stack.
+        int overflowAlmostCounter = 0;
+        
+        // This keeps track of ignored pushes at level 61 or higher, so that matching PDFs will
+        // not try to pop the stack.
+        int overflowCounter = 0;
+        
+        // Rule X1.
+        
+        // Keep the level separate from the value (level | override status flag) for ease of access.
+        byte currentEmbeddingLevel = paragraphEmbeddingLevel;
+        byte currentEmbeddingValue = paragraphEmbeddingLevel;
+        
+        // Loop through types, handling all remaining rules
+        for (int i = 0; i < textLength; ++i) {
+            
+            embeddings[i] = currentEmbeddingValue;
+            
+            byte t = resultTypes[i];
+            
+            // Rules X2, X3, X4, X5
+            switch (t) {
+                case RLE:
+                case LRE:
+                case RLO:
+                case LRO:
+                    // Only need to compute new level if current level is valid
+                    if (overflowCounter == 0) {
+                        byte newLevel;
+                        if (t == RLE || t == RLO) {
+                            newLevel = (byte)((currentEmbeddingLevel + 1) | 1); // least greater odd
+                        } else { // t == LRE || t == LRO
+                            newLevel = (byte)((currentEmbeddingLevel + 2) & ~1); // least greater even
+                        }
+                        
+                        // If the new level is valid, push old embedding level and override status
+                        // No check for valid stack counter, since the level check suffices.
+                        if (newLevel < EXPLICIT_LEVEL_LIMIT) {
+                            embeddingValueStack[stackCounter] = currentEmbeddingValue;
+                            stackCounter++;
+                            
+                            currentEmbeddingLevel = newLevel;
+                            if (t == LRO || t == RLO) { // override
+                                currentEmbeddingValue = (byte)(newLevel | 0x80);
+                            } else {
+                                currentEmbeddingValue = newLevel;
+                            }
+                            
+                            // Adjust level of format mark (for expositional purposes only, this gets
+                            // removed later).
+                            embeddings[i] = currentEmbeddingValue;
+                            break;
+                        }
+                        
+                        // Otherwise new level is invalid, but a valid level can still be achieved if this
+                        // level is 60 and we encounter an RLE or RLO further on.  So record that we
+                        // 'almost' overflowed.
+                        if (currentEmbeddingLevel == 60) {
+                            overflowAlmostCounter++;
+                            break;
+                        }
+                    }
+                    
+                    // Otherwise old or new level is invalid.
+                    overflowCounter++;
+                    break;
+                    
+                case PDF:
+                    // The only case where this did not actually overflow but may have almost overflowed
+                    // is when there was an RLE or RLO on level 60, which would result in level 61.  So we
+                    // only test the almost overflow condition in that case.
+                    //
+                    // Also note that there may be a PDF without any pushes at all.
+                    
+                    if (overflowCounter > 0) {
+                        --overflowCounter;
+                    } else if (overflowAlmostCounter > 0 && currentEmbeddingLevel != 61) {
+                        --overflowAlmostCounter;
+                    } else if (stackCounter > 0) {
+                        --stackCounter;
+                        currentEmbeddingValue = embeddingValueStack[stackCounter];
+                        currentEmbeddingLevel = (byte)(currentEmbeddingValue & 0x7f);
+                    }
+                    break;
+                    
+                case B:
+                    // Rule X8.
+                    
+                    // These values are reset for clarity, in this implementation B can only
+                    // occur as the last code in the array.
+                    stackCounter = 0;
+                    overflowCounter = 0;
+                    overflowAlmostCounter = 0;
+                    currentEmbeddingLevel = paragraphEmbeddingLevel;
+                    currentEmbeddingValue = paragraphEmbeddingLevel;
+                    
+                    embeddings[i] = paragraphEmbeddingLevel;
+                    break;
+                    
+                default:
+                    break;
+            }
+        }
+        
+        return embeddings;
+    }
+    
+    
+    /**
+     * 3) resolving weak types
+     * Rules W1-W7.
+     *
+     * Note that some weak types (EN, AN) remain after this processing is complete.
+     */
+    private void resolveWeakTypes(int start, int limit, byte level, byte sor, byte eor) {
+        
+        // Rule W1.
+        // Changes all NSMs.
+        byte preceedingCharacterType = sor;
+        for (int i = start; i < limit; ++i) {
+            byte t = resultTypes[i];
+            if (t == NSM) {
+                resultTypes[i] = preceedingCharacterType;
+            } else {
+                preceedingCharacterType = t;
+            }
+        }
+        
+        // Rule W2.
+        // EN does not change at the start of the run, because sor != AL.
+        for (int i = start; i < limit; ++i) {
+            if (resultTypes[i] == EN) {
+                for (int j = i - 1; j >= start; --j) {
+                    byte t = resultTypes[j];
+                    if (t == L || t == R || t == AL) {
+                        if (t == AL) {
+                            resultTypes[i] = AN;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        
+        // Rule W3.
+        for (int i = start; i < limit; ++i) {
+            if (resultTypes[i] == AL) {
+                resultTypes[i] = R;
+            }
+        }
+        
+        // Rule W4.
+        // Since there must be values on both sides for this rule to have an
+        // effect, the scan skips the first and last value.
+        //
+        // Although the scan proceeds left to right, and changes the type values
+        // in a way that would appear to affect the computations later in the scan,
+        // there is actually no problem.  A change in the current value can only
+        // affect the value to its immediate right, and only affect it if it is
+        // ES or CS.  But the current value can only change if the value to its
+        // right is not ES or CS.  Thus either the current value will not change,
+        // or its change will have no effect on the remainder of the analysis.
+        
+        for (int i = start + 1; i < limit - 1; ++i) {
+            if (resultTypes[i] == ES || resultTypes[i] == CS) {
+                byte prevSepType = resultTypes[i-1];
+                byte succSepType = resultTypes[i+1];
+                if (prevSepType == EN && succSepType == EN) {
+                    resultTypes[i] = EN;
+                } else if (resultTypes[i] == CS && prevSepType == AN && succSepType == AN) {
+                    resultTypes[i] = AN;
+                }
+            }
+        }
+        
+        // Rule W5.
+        for (int i = start; i < limit; ++i) {
+            if (resultTypes[i] == ET) {
+                // locate end of sequence
+                int runstart = i;
+                int runlimit = findRunLimit(runstart, limit, new byte[] { ET });
+                
+                // check values at ends of sequence
+                byte t = runstart == start ? sor : resultTypes[runstart - 1];
+                
+                if (t != EN) {
+                    t = runlimit == limit ? eor : resultTypes[runlimit];
+                }
+                
+                if (t == EN) {
+                    setTypes(runstart, runlimit, EN);
+                }
+                
+                // continue at end of sequence
+                i = runlimit;
+            }
+        }
+        
+        // Rule W6.
+        for (int i = start; i < limit; ++i) {
+            byte t = resultTypes[i];
+            if (t == ES || t == ET || t == CS) {
+                resultTypes[i] = ON;
+            }
+        }
+        
+        // Rule W7.
+        for (int i = start; i < limit; ++i) {
+            if (resultTypes[i] == EN) {
+                // set default if we reach start of run
+                byte prevStrongType = sor;
+                for (int j = i - 1; j >= start; --j) {
+                    byte t = resultTypes[j];
+                    if (t == L || t == R) { // AL's have been removed
+                        prevStrongType = t;
+                        break;
+                    }
+                }
+                if (prevStrongType == L) {
+                    resultTypes[i] = L;
+                }
+            }
+        }
+    }
+    
+    /**
+     * 6) resolving neutral types
+     * Rules N1-N2.
+     */
+    private void resolveNeutralTypes(int start, int limit, byte level, byte sor, byte eor) {
+        
+        for (int i = start; i < limit; ++i) {
+            byte t = resultTypes[i];
+            if (t == WS || t == ON || t == B || t == S) {
+                // find bounds of run of neutrals
+                int runstart = i;
+                int runlimit = findRunLimit(runstart, limit, new byte[] {B, S, WS, ON});
+                
+                // determine effective types at ends of run
+                byte leadingType;
+                byte trailingType;
+                
+                if (runstart == start) {
+                    leadingType = sor;
+                } else {
+                    leadingType = resultTypes[runstart - 1];
+                    if (leadingType == L || leadingType == R) {
+                        // found the strong type
+                    } else if (leadingType == AN) {
+                        leadingType = R;
+                    } else if (leadingType == EN) {
+                        // Since EN's with previous strong L types have been changed
+                        // to L in W7, the leadingType must be R.
+                        leadingType = R;
+                    }
+                }
+                
+                if (runlimit == limit) {
+                    trailingType = eor;
+                } else {
+                    trailingType = resultTypes[runlimit];
+                    if (trailingType == L || trailingType == R) {
+                        // found the strong type
+                    } else if (trailingType == AN) {
+                        trailingType = R;
+                    } else if (trailingType == EN) {
+                        trailingType = R;
+                    }
+                }
+                
+                byte resolvedType;
+                if (leadingType == trailingType) {
+                    // Rule N1.
+                    resolvedType = leadingType;
+                } else {
+                    // Rule N2.
+                    // Notice the embedding level of the run is used, not
+                    // the paragraph embedding level.
+                    resolvedType = typeForLevel(level);
+                }
+                
+                setTypes(runstart, runlimit, resolvedType);
+                
+                // skip over run of (former) neutrals
+                i = runlimit;
+            }
+        }
+    }
+    
+    /**
+     * 7) resolving implicit embedding levels
+     * Rules I1, I2.
+     */
+    private void resolveImplicitLevels(int start, int limit, byte level, byte sor, byte eor) {
+        if ((level & 1) == 0) { // even level
+            for (int i = start; i < limit; ++i) {
+                byte t = resultTypes[i];
+                // Rule I1.
+                if (t == L ) {
+                    // no change
+                } else if (t == R) {
+                    resultLevels[i] += 1;
+                } else { // t == AN || t == EN
+                    resultLevels[i] += 2;
+                }
+            }
+        } else { // odd level
+            for (int i = start; i < limit; ++i) {
+                byte t = resultTypes[i];
+                // Rule I2.
+                if (t == R) {
+                    // no change
+                } else { // t == L || t == AN || t == EN
+                    resultLevels[i] += 1;
+                }
+            }
+        }
+    }
+    
+    //
+    // Output
+    //
+    
+    public byte[] getLevels() {
+        return getLevels(new int[]{textLength});
+    }
+    
+    /**
+     * Return levels array breaking lines at offsets in linebreaks. <br>
+     * Rule L1.
+     * <p>
+     * The returned levels array contains the resolved level for each
+     * bidi code passed to the constructor.
+     * <p>
+     * The linebreaks array must include at least one value.
+     * The values must be in strictly increasing order (no duplicates)
+     * between 1 and the length of the text, inclusive.  The last value
+     * must be the length of the text.
+     *
+     * @param linebreaks the offsets at which to break the paragraph
+     * @return the resolved levels of the text
+     */
+    public byte[] getLevels(int[] linebreaks) {
+        
+        // Note that since the previous processing has removed all
+        // P, S, and WS values from resultTypes, the values referred to
+        // in these rules are the initial types, before any processing
+        // has been applied (including processing of overrides).
+        //
+        // This example implementation has reinserted explicit format codes
+        // and BN, in order that the levels array correspond to the
+        // initial text.  Their final placement is not normative.
+        // These codes are treated like WS in this implementation,
+        // so they don't interrupt sequences of WS.
+        
+        validateLineBreaks(linebreaks, textLength);
+        
+        byte[] result = (byte[])resultLevels.clone(); // will be returned to caller
+        
+        // don't worry about linebreaks since if there is a break within
+        // a series of WS values preceeding S, the linebreak itself
+        // causes the reset.
+        for (int i = 0; i < result.length; ++i) {
+            byte t = initialTypes[i];
+            if (t == B || t == S) {
+                // Rule L1, clauses one and two.
+                result[i] = paragraphEmbeddingLevel;
+                
+                // Rule L1, clause three.
+                for (int j = i - 1; j >= 0; --j) {
+                    if (isWhitespace(initialTypes[j])) { // including format codes
+                        result[j] = paragraphEmbeddingLevel;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+        
+        // Rule L1, clause four.
+        int start = 0;
+        for (int i = 0; i < linebreaks.length; ++i) {
+            int limit = linebreaks[i];
+            for (int j = limit - 1; j >= start; --j) {
+                if (isWhitespace(initialTypes[j])) { // including format codes
+                    result[j] = paragraphEmbeddingLevel;
+                } else {
+                    break;
+                }
+            }
+            
+            start = limit;
+        }
+        
+        return result;
+    }
+    
+    /**
+     * Return reordering array breaking lines at offsets in linebreaks.
+     * <p>
+     * The reordering array maps from a visual index to a logical index.
+     * Lines are concatenated from left to right.  So for example, the
+     * fifth character from the left on the third line is
+     * <pre> getReordering(linebreaks)[linebreaks[1] + 4]</pre>
+     * (linebreaks[1] is the position after the last character of the
+     * second line, which is also the index of the first character on the
+     * third line, and adding four gets the fifth character from the left).
+     * <p>
+     * The linebreaks array must include at least one value.
+     * The values must be in strictly increasing order (no duplicates)
+     * between 1 and the length of the text, inclusive.  The last value
+     * must be the length of the text.
+     *
+     * @param linebreaks the offsets at which to break the paragraph.
+     */
+    public int[] getReordering(int[] linebreaks) {
+        validateLineBreaks(linebreaks, textLength);
+        
+        byte[] levels = getLevels(linebreaks);
+        
+        return computeMultilineReordering(levels, linebreaks);
+    }
+    
+    /**
+     * Return multiline reordering array for a given level array.
+     * Reordering does not occur across a line break.
+     */
+    private static int[] computeMultilineReordering(byte[] levels, int[] linebreaks) {
+        int[] result = new int[levels.length];
+        
+        int start = 0;
+        for (int i = 0; i < linebreaks.length; ++i) {
+            int limit = linebreaks[i];
+            
+            byte[] templevels = new byte[limit - start];
+            System.arraycopy(levels, start, templevels, 0, templevels.length);
+            
+            int[] temporder = computeReordering(templevels);
+            for (int j = 0; j < temporder.length; ++j) {
+                result[start + j] = temporder[j] + start;
+            }
+            
+            start = limit;
+        }
+        
+        return result;
+    }
+    
+    /**
+     * Return reordering array for a given level array.  This reorders a single line.
+     * The reordering is a visual to logical map.  For example,
+     * the leftmost char is string.charAt(order[0]).
+     * Rule L2.
+     */
+    private static int[] computeReordering(byte[] levels) {
+        int lineLength = levels.length;
+        
+        int[] result = new int[lineLength];
+        
+        // initialize order
+        for (int i = 0; i < lineLength; ++i) {
+            result[i] = i;
+        }
+        
+        // locate highest level found on line.
+        // Note the rules say text, but no reordering across line bounds is performed,
+        // so this is sufficient.
+        byte highestLevel = 0;
+        byte lowestOddLevel = 63;
+        for (int i = 0; i < lineLength; ++i) {
+            byte level = levels[i];
+            if (level > highestLevel) {
+                highestLevel = level;
+            }
+            if (((level & 1) != 0) && level < lowestOddLevel) {
+                lowestOddLevel = level;
+            }
+        }
+        
+        for (int level = highestLevel; level >= lowestOddLevel; --level) {
+            for (int i = 0; i < lineLength; ++i) {
+                if (levels[i] >= level) {
+                    // find range of text at or above this level
+                    int start = i;
+                    int limit = i + 1;
+                    while (limit < lineLength && levels[limit] >= level) {
+                        ++limit;
+                    }
+                    
+                    // reverse run
+                    for (int j = start, k = limit - 1; j < k; ++j, --k) {
+                        int temp = result[j];
+                        result[j] = result[k];
+                        result[k] = temp;
+                    }
+                    
+                    // skip to end of level run
+                    i = limit;
+                }
+            }
+        }
+        
+        return result;
+    }
+    
+    /**
+     * Return the base level of the paragraph.
+     */
+    public byte getBaseLevel() {
+        return paragraphEmbeddingLevel;
+    }
+    
+    // --- internal utilities -------------------------------------------------
+    
+    /**
+     * Return true if the type is considered a whitespace type for the line break rules.
+     */
+    private static boolean isWhitespace(byte biditype) {
+        switch (biditype) {
+            case LRE:
+            case RLE:
+            case LRO:
+            case RLO:
+            case PDF:
+            case BN:
+            case WS:
+                return true;
+            default:
+                return false;
+        }
+    }
+    
+    /**
+     * Return the strong type (L or R) corresponding to the level.
+     */
+    private static byte typeForLevel(int level) {
+        return ((level & 0x1) == 0) ? L : R;
+    }
+    
+    /**
+     * Return the limit of the run starting at index that includes only resultTypes in validSet.
+     * This checks the value at index, and will return index if that value is not in validSet.
+     */
+    private int findRunLimit(int index, int limit, byte[] validSet) {
+        --index;
+        loop:
+            while (++index < limit) {
+                byte t = resultTypes[index];
+                for (int i = 0; i < validSet.length; ++i) {
+                    if (t == validSet[i]) {
+                        continue loop;
+                    }
+                }
+                // didn't find a match in validSet
+                return index;
+            }
+            return limit;
+    }
+    
+    /**
+     * Return the start of the run including index that includes only resultTypes in validSet.
+     * This assumes the value at index is valid, and does not check it.
+     */
+    private int findRunStart(int index, byte[] validSet) {
+        loop:
+            while (--index >= 0) {
+                byte t = resultTypes[index];
+                for (int i = 0; i < validSet.length; ++i) {
+                    if (t == validSet[i]) {
+                        continue loop;
+                    }
+                }
+                return index + 1;
+            }
+            return 0;
+    }
+    
+    /**
+     * Set resultTypes from start up to (but not including) limit to newType.
+     */
+    private void setTypes(int start, int limit, byte newType) {
+        for (int i = start; i < limit; ++i) {
+            resultTypes[i] = newType;
+        }
+    }
+    
+    /**
+     * Set resultLevels from start up to (but not including) limit to newLevel.
+     */
+    private void setLevels(int start, int limit, byte newLevel) {
+        for (int i = start; i < limit; ++i) {
+            resultLevels[i] = newLevel;
+        }
+    }
+    
+    // --- input validation ---------------------------------------------------
+    
+    /**
+     * Throw exception if type array is invalid.
+     */
+    private static void validateTypes(byte[] types) {
+        if (types == null) {
+            throw new IllegalArgumentException("types is null");
+        }
+        for (int i = 0; i < types.length; ++i) {
+            if (types[i] < TYPE_MIN || types[i] > TYPE_MAX) {
+                throw new IllegalArgumentException("illegal type value at " + i + ": " + types[i]);
+            }
+        }
+        for (int i = 0; i < types.length - 1; ++i) {
+            if (types[i] == B) {
+                throw new IllegalArgumentException("B type before end of paragraph at index: " + i);
+            }
+        }
+    }
+    
+    /**
+     * Throw exception if paragraph embedding level is invalid. Special allowance for -1 so that
+     * default processing can still be performed when using this API.
+     */
+    private static void validateParagraphEmbeddingLevel(byte paragraphEmbeddingLevel) {
+        if (paragraphEmbeddingLevel != -1 &&
+        paragraphEmbeddingLevel != 0 &&
+        paragraphEmbeddingLevel != 1) {
+            throw new IllegalArgumentException("illegal paragraph embedding level: " + paragraphEmbeddingLevel);
+        }
+    }
+    
+    /**
+     * Throw exception if line breaks array is invalid.
+     */
+    private static void validateLineBreaks(int[] linebreaks, int textLength) {
+        int prev = 0;
+        for (int i = 0; i < linebreaks.length; ++i) {
+            int next = linebreaks[i];
+            if (next <= prev) {
+                throw new IllegalArgumentException("bad linebreak: " + next + " at index: " + i);
+            }
+            prev = next;
+        }
+        if (prev != textLength) {
+            throw new IllegalArgumentException("last linebreak must be at " + textLength);
+        }
+    }
+    
+    private static final byte rtypes[] = new byte[0x10000];
+    
+    private static char baseTypes[] = {
+        0, 8, (char)BN, 9, 9, (char)S, 10, 10, (char)B, 11, 11, (char)S, 12, 12, (char)WS, 13, 13, (char)B,
+        14, 27, (char)BN, 28, 30, (char)B, 31, 31, (char)S, 32, 32, (char)WS, 33, 34, (char)ON, 35, 37, (char)ET,
+        38, 42, (char)ON, 43, 43, (char)ET, 44, 44, (char)CS, 45, 45, (char)ET, 46, 46, (char)CS, 47, 47, (char)ES,
+        48, 57, (char)EN, 58, 58, (char)CS, 59, 64, (char)ON, 65, 90, (char)L, 91, 96, (char)ON, 97, 122, (char)L,
+        123, 126, (char)ON, 127, 132, (char)BN, 133, 133, (char)B, 134, 159, (char)BN, 160, 160, (char)CS,
+        161, 161, (char)ON, 162, 165, (char)ET, 166, 169, (char)ON, 170, 170, (char)L, 171, 175, (char)ON,
+        176, 177, (char)ET, 178, 179, (char)EN, 180, 180, (char)ON, 181, 181, (char)L, 182, 184, (char)ON,
+        185, 185, (char)EN, 186, 186, (char)L, 187, 191, (char)ON, 192, 214, (char)L, 215, 215, (char)ON,
+        216, 246, (char)L, 247, 247, (char)ON, 248, 696, (char)L, 697, 698, (char)ON, 699, 705, (char)L,
+        706, 719, (char)ON, 720, 721, (char)L, 722, 735, (char)ON, 736, 740, (char)L, 741, 749, (char)ON,
+        750, 750, (char)L, 751, 767, (char)ON, 768, 855, (char)NSM, 856, 860, (char)L, 861, 879, (char)NSM,
+        880, 883, (char)L, 884, 885, (char)ON, 886, 893, (char)L, 894, 894, (char)ON, 895, 899, (char)L,
+        900, 901, (char)ON, 902, 902, (char)L, 903, 903, (char)ON, 904, 1013, (char)L, 1014, 1014, (char)ON,
+        1015, 1154, (char)L, 1155, 1158, (char)NSM, 1159, 1159, (char)L, 1160, 1161, (char)NSM,
+        1162, 1417, (char)L, 1418, 1418, (char)ON, 1419, 1424, (char)L, 1425, 1441, (char)NSM,
+        1442, 1442, (char)L, 1443, 1465, (char)NSM, 1466, 1466, (char)L, 1467, 1469, (char)NSM,
+        1470, 1470, (char)R, 1471, 1471, (char)NSM, 1472, 1472, (char)R, 1473, 1474, (char)NSM,
+        1475, 1475, (char)R, 1476, 1476, (char)NSM, 1477, 1487, (char)L, 1488, 1514, (char)R,
+        1515, 1519, (char)L, 1520, 1524, (char)R, 1525, 1535, (char)L, 1536, 1539, (char)AL,
+        1540, 1547, (char)L, 1548, 1548, (char)CS, 1549, 1549, (char)AL, 1550, 1551, (char)ON,
+        1552, 1557, (char)NSM, 1558, 1562, (char)L, 1563, 1563, (char)AL, 1564, 1566, (char)L,
+        1567, 1567, (char)AL, 1568, 1568, (char)L, 1569, 1594, (char)AL, 1595, 1599, (char)L,
+        1600, 1610, (char)AL, 1611, 1624, (char)NSM, 1625, 1631, (char)L, 1632, 1641, (char)AN,
+        1642, 1642, (char)ET, 1643, 1644, (char)AN, 1645, 1647, (char)AL, 1648, 1648, (char)NSM,
+        1649, 1749, (char)AL, 1750, 1756, (char)NSM, 1757, 1757, (char)AL, 1758, 1764, (char)NSM,
+        1765, 1766, (char)AL, 1767, 1768, (char)NSM, 1769, 1769, (char)ON, 1770, 1773, (char)NSM,
+        1774, 1775, (char)AL, 1776, 1785, (char)EN, 1786, 1805, (char)AL, 1806, 1806, (char)L,
+        1807, 1807, (char)BN, 1808, 1808, (char)AL, 1809, 1809, (char)NSM, 1810, 1839, (char)AL,
+        1840, 1866, (char)NSM, 1867, 1868, (char)L, 1869, 1871, (char)AL, 1872, 1919, (char)L,
+        1920, 1957, (char)AL, 1958, 1968, (char)NSM, 1969, 1969, (char)AL, 1970, 2304, (char)L,
+        2305, 2306, (char)NSM, 2307, 2363, (char)L, 2364, 2364, (char)NSM, 2365, 2368, (char)L,
+        2369, 2376, (char)NSM, 2377, 2380, (char)L, 2381, 2381, (char)NSM, 2382, 2384, (char)L,
+        2385, 2388, (char)NSM, 2389, 2401, (char)L, 2402, 2403, (char)NSM, 2404, 2432, (char)L,
+        2433, 2433, (char)NSM, 2434, 2491, (char)L, 2492, 2492, (char)NSM, 2493, 2496, (char)L,
+        2497, 2500, (char)NSM, 2501, 2508, (char)L, 2509, 2509, (char)NSM, 2510, 2529, (char)L,
+        2530, 2531, (char)NSM, 2532, 2545, (char)L, 2546, 2547, (char)ET, 2548, 2560, (char)L,
+        2561, 2562, (char)NSM, 2563, 2619, (char)L, 2620, 2620, (char)NSM, 2621, 2624, (char)L,
+        2625, 2626, (char)NSM, 2627, 2630, (char)L, 2631, 2632, (char)NSM, 2633, 2634, (char)L,
+        2635, 2637, (char)NSM, 2638, 2671, (char)L, 2672, 2673, (char)NSM, 2674, 2688, (char)L,
+        2689, 2690, (char)NSM, 2691, 2747, (char)L, 2748, 2748, (char)NSM, 2749, 2752, (char)L,
+        2753, 2757, (char)NSM, 2758, 2758, (char)L, 2759, 2760, (char)NSM, 2761, 2764, (char)L,
+        2765, 2765, (char)NSM, 2766, 2785, (char)L, 2786, 2787, (char)NSM, 2788, 2800, (char)L,
+        2801, 2801, (char)ET, 2802, 2816, (char)L, 2817, 2817, (char)NSM, 2818, 2875, (char)L,
+        2876, 2876, (char)NSM, 2877, 2878, (char)L, 2879, 2879, (char)NSM, 2880, 2880, (char)L,
+        2881, 2883, (char)NSM, 2884, 2892, (char)L, 2893, 2893, (char)NSM, 2894, 2901, (char)L,
+        2902, 2902, (char)NSM, 2903, 2945, (char)L, 2946, 2946, (char)NSM, 2947, 3007, (char)L,
+        3008, 3008, (char)NSM, 3009, 3020, (char)L, 3021, 3021, (char)NSM, 3022, 3058, (char)L,
+        3059, 3064, (char)ON, 3065, 3065, (char)ET, 3066, 3066, (char)ON, 3067, 3133, (char)L,
+        3134, 3136, (char)NSM, 3137, 3141, (char)L, 3142, 3144, (char)NSM, 3145, 3145, (char)L,
+        3146, 3149, (char)NSM, 3150, 3156, (char)L, 3157, 3158, (char)NSM, 3159, 3259, (char)L,
+        3260, 3260, (char)NSM, 3261, 3275, (char)L, 3276, 3277, (char)NSM, 3278, 3392, (char)L,
+        3393, 3395, (char)NSM, 3396, 3404, (char)L, 3405, 3405, (char)NSM, 3406, 3529, (char)L,
+        3530, 3530, (char)NSM, 3531, 3537, (char)L, 3538, 3540, (char)NSM, 3541, 3541, (char)L,
+        3542, 3542, (char)NSM, 3543, 3632, (char)L, 3633, 3633, (char)NSM, 3634, 3635, (char)L,
+        3636, 3642, (char)NSM, 3643, 3646, (char)L, 3647, 3647, (char)ET, 3648, 3654, (char)L,
+        3655, 3662, (char)NSM, 3663, 3760, (char)L, 3761, 3761, (char)NSM, 3762, 3763, (char)L,
+        3764, 3769, (char)NSM, 3770, 3770, (char)L, 3771, 3772, (char)NSM, 3773, 3783, (char)L,
+        3784, 3789, (char)NSM, 3790, 3863, (char)L, 3864, 3865, (char)NSM, 3866, 3892, (char)L,
+        3893, 3893, (char)NSM, 3894, 3894, (char)L, 3895, 3895, (char)NSM, 3896, 3896, (char)L,
+        3897, 3897, (char)NSM, 3898, 3901, (char)ON, 3902, 3952, (char)L, 3953, 3966, (char)NSM,
+        3967, 3967, (char)L, 3968, 3972, (char)NSM, 3973, 3973, (char)L, 3974, 3975, (char)NSM,
+        3976, 3983, (char)L, 3984, 3991, (char)NSM, 3992, 3992, (char)L, 3993, 4028, (char)NSM,
+        4029, 4037, (char)L, 4038, 4038, (char)NSM, 4039, 4140, (char)L, 4141, 4144, (char)NSM,
+        4145, 4145, (char)L, 4146, 4146, (char)NSM, 4147, 4149, (char)L, 4150, 4151, (char)NSM,
+        4152, 4152, (char)L, 4153, 4153, (char)NSM, 4154, 4183, (char)L, 4184, 4185, (char)NSM,
+        4186, 5759, (char)L, 5760, 5760, (char)WS, 5761, 5786, (char)L, 5787, 5788, (char)ON,
+        5789, 5905, (char)L, 5906, 5908, (char)NSM, 5909, 5937, (char)L, 5938, 5940, (char)NSM,
+        5941, 5969, (char)L, 5970, 5971, (char)NSM, 5972, 6001, (char)L, 6002, 6003, (char)NSM,
+        6004, 6070, (char)L, 6071, 6077, (char)NSM, 6078, 6085, (char)L, 6086, 6086, (char)NSM,
+        6087, 6088, (char)L, 6089, 6099, (char)NSM, 6100, 6106, (char)L, 6107, 6107, (char)ET,
+        6108, 6108, (char)L, 6109, 6109, (char)NSM, 6110, 6127, (char)L, 6128, 6137, (char)ON,
+        6138, 6143, (char)L, 6144, 6154, (char)ON, 6155, 6157, (char)NSM, 6158, 6158, (char)WS,
+        6159, 6312, (char)L, 6313, 6313, (char)NSM, 6314, 6431, (char)L, 6432, 6434, (char)NSM,
+        6435, 6438, (char)L, 6439, 6443, (char)NSM, 6444, 6449, (char)L, 6450, 6450, (char)NSM,
+        6451, 6456, (char)L, 6457, 6459, (char)NSM, 6460, 6463, (char)L, 6464, 6464, (char)ON,
+        6465, 6467, (char)L, 6468, 6469, (char)ON, 6470, 6623, (char)L, 6624, 6655, (char)ON,
+        6656, 8124, (char)L, 8125, 8125, (char)ON, 8126, 8126, (char)L, 8127, 8129, (char)ON,
+        8130, 8140, (char)L, 8141, 8143, (char)ON, 8144, 8156, (char)L, 8157, 8159, (char)ON,
+        8160, 8172, (char)L, 8173, 8175, (char)ON, 8176, 8188, (char)L, 8189, 8190, (char)ON,
+        8191, 8191, (char)L, 8192, 8202, (char)WS, 8203, 8205, (char)BN, 8206, 8206, (char)L,
+        8207, 8207, (char)R, 8208, 8231, (char)ON, 8232, 8232, (char)WS, 8233, 8233, (char)B,
+        8234, 8234, (char)LRE, 8235, 8235, (char)RLE, 8236, 8236, (char)PDF, 8237, 8237, (char)LRO,
+        8238, 8238, (char)RLO, 8239, 8239, (char)WS, 8240, 8244, (char)ET, 8245, 8276, (char)ON,
+        8277, 8278, (char)L, 8279, 8279, (char)ON, 8280, 8286, (char)L, 8287, 8287, (char)WS,
+        8288, 8291, (char)BN, 8292, 8297, (char)L, 8298, 8303, (char)BN, 8304, 8304, (char)EN,
+        8305, 8307, (char)L, 8308, 8313, (char)EN, 8314, 8315, (char)ET, 8316, 8318, (char)ON,
+        8319, 8319, (char)L, 8320, 8329, (char)EN, 8330, 8331, (char)ET, 8332, 8334, (char)ON,
+        8335, 8351, (char)L, 8352, 8369, (char)ET, 8370, 8399, (char)L, 8400, 8426, (char)NSM,
+        8427, 8447, (char)L, 8448, 8449, (char)ON, 8450, 8450, (char)L, 8451, 8454, (char)ON,
+        8455, 8455, (char)L, 8456, 8457, (char)ON, 8458, 8467, (char)L, 8468, 8468, (char)ON,
+        8469, 8469, (char)L, 8470, 8472, (char)ON, 8473, 8477, (char)L, 8478, 8483, (char)ON,
+        8484, 8484, (char)L, 8485, 8485, (char)ON, 8486, 8486, (char)L, 8487, 8487, (char)ON,
+        8488, 8488, (char)L, 8489, 8489, (char)ON, 8490, 8493, (char)L, 8494, 8494, (char)ET,
+        8495, 8497, (char)L, 8498, 8498, (char)ON, 8499, 8505, (char)L, 8506, 8507, (char)ON,
+        8508, 8511, (char)L, 8512, 8516, (char)ON, 8517, 8521, (char)L, 8522, 8523, (char)ON,
+        8524, 8530, (char)L, 8531, 8543, (char)ON, 8544, 8591, (char)L, 8592, 8721, (char)ON,
+        8722, 8723, (char)ET, 8724, 9013, (char)ON, 9014, 9082, (char)L, 9083, 9108, (char)ON,
+        9109, 9109, (char)L, 9110, 9168, (char)ON, 9169, 9215, (char)L, 9216, 9254, (char)ON,
+        9255, 9279, (char)L, 9280, 9290, (char)ON, 9291, 9311, (char)L, 9312, 9371, (char)EN,
+        9372, 9449, (char)L, 9450, 9450, (char)EN, 9451, 9751, (char)ON, 9752, 9752, (char)L,
+        9753, 9853, (char)ON, 9854, 9855, (char)L, 9856, 9873, (char)ON, 9874, 9887, (char)L,
+        9888, 9889, (char)ON, 9890, 9984, (char)L, 9985, 9988, (char)ON, 9989, 9989, (char)L,
+        9990, 9993, (char)ON, 9994, 9995, (char)L, 9996, 10023, (char)ON, 10024, 10024, (char)L,
+        10025, 10059, (char)ON, 10060, 10060, (char)L, 10061, 10061, (char)ON, 10062, 10062, (char)L,
+        10063, 10066, (char)ON, 10067, 10069, (char)L, 10070, 10070, (char)ON, 10071, 10071, (char)L,
+        10072, 10078, (char)ON, 10079, 10080, (char)L, 10081, 10132, (char)ON, 10133, 10135, (char)L,
+        10136, 10159, (char)ON, 10160, 10160, (char)L, 10161, 10174, (char)ON, 10175, 10191, (char)L,
+        10192, 10219, (char)ON, 10220, 10223, (char)L, 10224, 11021, (char)ON, 11022, 11903, (char)L,
+        11904, 11929, (char)ON, 11930, 11930, (char)L, 11931, 12019, (char)ON, 12020, 12031, (char)L,
+        12032, 12245, (char)ON, 12246, 12271, (char)L, 12272, 12283, (char)ON, 12284, 12287, (char)L,
+        12288, 12288, (char)WS, 12289, 12292, (char)ON, 12293, 12295, (char)L, 12296, 12320, (char)ON,
+        12321, 12329, (char)L, 12330, 12335, (char)NSM, 12336, 12336, (char)ON, 12337, 12341, (char)L,
+        12342, 12343, (char)ON, 12344, 12348, (char)L, 12349, 12351, (char)ON, 12352, 12440, (char)L,
+        12441, 12442, (char)NSM, 12443, 12444, (char)ON, 12445, 12447, (char)L, 12448, 12448, (char)ON,
+        12449, 12538, (char)L, 12539, 12539, (char)ON, 12540, 12828, (char)L, 12829, 12830, (char)ON,
+        12831, 12879, (char)L, 12880, 12895, (char)ON, 12896, 12923, (char)L, 12924, 12925, (char)ON,
+        12926, 12976, (char)L, 12977, 12991, (char)ON, 12992, 13003, (char)L, 13004, 13007, (char)ON,
+        13008, 13174, (char)L, 13175, 13178, (char)ON, 13179, 13277, (char)L, 13278, 13279, (char)ON,
+        13280, 13310, (char)L, 13311, 13311, (char)ON, 13312, 19903, (char)L, 19904, 19967, (char)ON,
+        19968, 42127, (char)L, 42128, 42182, (char)ON, 42183, 64284, (char)L, 64285, 64285, (char)R,
+        64286, 64286, (char)NSM, 64287, 64296, (char)R, 64297, 64297, (char)ET, 64298, 64310, (char)R,
+        64311, 64311, (char)L, 64312, 64316, (char)R, 64317, 64317, (char)L, 64318, 64318, (char)R,
+        64319, 64319, (char)L, 64320, 64321, (char)R, 64322, 64322, (char)L, 64323, 64324, (char)R,
+        64325, 64325, (char)L, 64326, 64335, (char)R, 64336, 64433, (char)AL, 64434, 64466, (char)L,
+        64467, 64829, (char)AL, 64830, 64831, (char)ON, 64832, 64847, (char)L, 64848, 64911, (char)AL,
+        64912, 64913, (char)L, 64914, 64967, (char)AL, 64968, 65007, (char)L, 65008, 65020, (char)AL,
+        65021, 65021, (char)ON, 65022, 65023, (char)L, 65024, 65039, (char)NSM, 65040, 65055, (char)L,
+        65056, 65059, (char)NSM, 65060, 65071, (char)L, 65072, 65103, (char)ON, 65104, 65104, (char)CS,
+        65105, 65105, (char)ON, 65106, 65106, (char)CS, 65107, 65107, (char)L, 65108, 65108, (char)ON,
+        65109, 65109, (char)CS, 65110, 65118, (char)ON, 65119, 65119, (char)ET, 65120, 65121, (char)ON,
+        65122, 65123, (char)ET, 65124, 65126, (char)ON, 65127, 65127, (char)L, 65128, 65128, (char)ON,
+        65129, 65130, (char)ET, 65131, 65131, (char)ON, 65132, 65135, (char)L, 65136, 65140, (char)AL,
+        65141, 65141, (char)L, 65142, 65276, (char)AL, 65277, 65278, (char)L, 65279, 65279, (char)BN,
+        65280, 65280, (char)L, 65281, 65282, (char)ON, 65283, 65285, (char)ET, 65286, 65290, (char)ON,
+        65291, 65291, (char)ET, 65292, 65292, (char)CS, 65293, 65293, (char)ET, 65294, 65294, (char)CS,
+        65295, 65295, (char)ES, 65296, 65305, (char)EN, 65306, 65306, (char)CS, 65307, 65312, (char)ON,
+        65313, 65338, (char)L, 65339, 65344, (char)ON, 65345, 65370, (char)L, 65371, 65381, (char)ON,
+        65382, 65503, (char)L, 65504, 65505, (char)ET, 65506, 65508, (char)ON, 65509, 65510, (char)ET,
+        65511, 65511, (char)L, 65512, 65518, (char)ON, 65519, 65528, (char)L, 65529, 65531, (char)BN,
+        65532, 65533, (char)ON, 65534, 65535, (char)L};
+        
+    static {
+        for (int k = 0; k < baseTypes.length; ++k) {
+            int start = baseTypes[k];
+            int end = baseTypes[++k];
+            byte b = (byte)baseTypes[++k];
+            while (start <= end)
+                rtypes[start++] = b;
+        }
+    }        
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/ByteBuffer.java b/LibrarySource/com/lowagie/text/pdf/ByteBuffer.java
new file mode 100644
index 0000000..3232da1
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ByteBuffer.java
@@ -0,0 +1,597 @@
+/*
+ * $Id: ByteBuffer.java,v 1.34 2002/06/18 13:59:39 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.UnsupportedEncodingException;
+import java.io.OutputStream;
+import java.io.IOException;
+import com.lowagie.text.DocWriter;
+
+/**
+ * Acts like a <CODE>StringBuffer</CODE> but works with <CODE>byte</CODE> arrays.
+ * Floating point is converted to a format suitable to the PDF.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class ByteBuffer extends OutputStream {
+    /** The count of bytes in the buffer. */
+    protected int count;
+    
+    /** The buffer where the bytes are stored. */
+    protected byte buf[];
+    
+    private static int byteCacheSize = 0;
+    
+    private static byte[][] byteCache = new byte[byteCacheSize][];
+    public static byte ZERO = (byte)'0';
+    private static final char[] chars = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+    private static final byte[] bytes = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
+    
+    /** Creates new ByteBuffer with capacity 128 */
+    public ByteBuffer() {
+        this(128);
+    }
+    
+    /**
+     * Creates a byte buffer with a certain capacity.
+     * @param size the initial capacity
+     */
+    public ByteBuffer(int size) {
+        if (size < 1)
+            size = 128;
+        buf = new byte[size];
+    }
+    
+    /**
+     * Sets the cache size.
+     * <P>
+     * This can only be used to increment the size.
+     * If the size that is passed through is smaller than the current size, nothing happens.
+     *
+     * @param   size    the size of the cache
+     */
+    
+    public static void setCacheSize(int size) {
+        if (size > 3276700) size = 3276700;
+        if (size <= byteCacheSize) return;
+        byte[][] tmpCache = new byte[size][];
+        for (int i = 0; i < byteCacheSize; i++) {
+            tmpCache[i] = byteCache[i];
+        }
+        byteCache = tmpCache;
+        byteCacheSize = size;
+    }
+    
+    /**
+     * You can fill the cache in advance if you want to.
+     *
+     * @param   decimals
+     */
+    
+    public static void fillCache(int decimals) {
+        int step = 1;
+        switch(decimals) {
+            case 0:
+                step = 100;
+                break;
+            case 1:
+                step = 10;
+                break;
+        }
+        for (int i = 1; i < byteCacheSize; i += step) {
+            if (byteCache[i] != null) continue;
+            byteCache[i] = convertToBytes(i);
+        }
+    }
+    
+    /**
+     * Converts an double (multiplied by 100 and cast to an int) into an array of bytes.
+     *
+     * @param   i   the int
+     * @return  a bytearray
+     */
+    
+    private static byte[] convertToBytes(int i) {
+        int size = (int)Math.floor(Math.log(i) / Math.log(10));
+        if (i % 100 != 0) {
+            size += 2;
+        }
+        if (i % 10 != 0) {
+            size++;
+        }
+        if (i < 100) {
+            size++;
+            if (i < 10) {
+                size++;
+            }
+        }
+        size--;
+        byte[] cache = new byte[size];
+        size --;
+        if (i < 100) {
+            cache[0] = (byte)'0';
+        }
+        if (i % 10 != 0) {
+            cache[size--] = bytes[i % 10];
+        }
+        if (i % 100 != 0) {
+            cache[size--] = bytes[(i / 10) % 10];
+            cache[size--] = (byte)'.';
+        }
+        size = (int)Math.floor(Math.log(i) / Math.log(10)) - 1;
+        int add = 0;
+        while (add < size) {
+            cache[add] = bytes[(i / (int)Math.pow(10, size - add + 1)) % 10];
+            add++;
+        }
+        return cache;
+    }
+    
+    /**
+     * Appends an <CODE>int</CODE>. The size of the array will grow by one.
+     * @param b the int to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append_i(int b) {
+        int newcount = count + 1;
+        if (newcount > buf.length) {
+            byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
+            System.arraycopy(buf, 0, newbuf, 0, count);
+            buf = newbuf;
+        }
+        buf[count] = (byte)b;
+        count = newcount;
+        return this;
+    }
+    
+    /**
+     * Appends the subarray of the <CODE>byte</CODE> array. The buffer will grow by
+     * <CODE>len</CODE> bytes.
+     * @param b the array to be appended
+     * @param off the offset to the start of the array
+     * @param len the length of bytes to append
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(byte b[], int off, int len) {
+        if ((off < 0) || (off > b.length) || (len < 0) ||
+        ((off + len) > b.length) || ((off + len) < 0) || len == 0)
+            return this;
+        int newcount = count + len;
+        if (newcount > buf.length) {
+            byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
+            System.arraycopy(buf, 0, newbuf, 0, count);
+            buf = newbuf;
+        }
+        System.arraycopy(b, off, buf, count, len);
+        count = newcount;
+        return this;
+    }
+    
+    /**
+     * Appends an array of bytes.
+     * @param b the array to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(byte b[]) {
+        return append(b, 0, b.length);
+    }
+    
+    /**
+     * Appends a <CODE>String</CODE> to the buffer. The <CODE>String</CODE> is
+     * converted according to the encoding ISO-8859-1.
+     * @param str the <CODE>String</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(String str) {
+        if (str != null)
+            return append(DocWriter.getISOBytes(str));
+        return this;
+    }
+    
+    /**
+     * Appends a <CODE>char</CODE> to the buffer. The <CODE>char</CODE> is
+     * converted according to the encoding ISO-8859-1.
+     * @param c the <CODE>char</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(char c) {
+        return append_i(c);
+    }
+    
+    /**
+     * Appends another <CODE>ByteBuffer</CODE> to this buffer.
+     * @param buf the <CODE>ByteBuffer</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(ByteBuffer buf) {
+        return append(buf.buf, 0, buf.count);
+    }
+    
+    /**
+     * Appends the string representation of an <CODE>int</CODE>.
+     * @param i the <CODE>int</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(int i) {
+        return append((double)i);
+    }
+    
+    public ByteBuffer append(byte b) {
+        return append_i(b);
+    }
+    
+    public ByteBuffer appendHex(byte b) {
+        append(bytes[(b >> 4) & 0x0f]);
+        return append(bytes[b & 0x0f]);
+    }
+    
+    /**
+     * Appends a string representation of a <CODE>float</CODE> according
+     * to the Pdf conventions.
+     * @param i the <CODE>float</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(float i) {
+        return append((double)i);
+    }
+    
+    /**
+     * Appends a string representation of a <CODE>double</CODE> according
+     * to the Pdf conventions.
+     * @param d the <CODE>double</CODE> to be appended
+     * @return a reference to this <CODE>ByteBuffer</CODE> object
+     */
+    public ByteBuffer append(double d) {
+        append(formatDouble(d, this));
+        return this;
+    }
+    
+    /**
+     * Outputs a <CODE>double</CODE> into a format suitable for the PDF.
+     * @param d a double
+     * @return the <CODE>String</CODE> representation of the <CODE>double</CODE>
+     */
+    public static String formatDouble(double d) {
+        return formatDouble(d, null);
+    }
+    
+    /**
+     * Outputs a <CODE>double</CODE> into a format suitable for the PDF.
+     * @param d a double
+     * @return the <CODE>String</CODE> representation of the <CODE>double</CODE> if
+     * <CODE>d</CODE> is <CODE>null</CODE>. If <CODE>d</CODE> is <B>not</B> <CODE>null</CODE>,
+     * then the double is appended directly to the buffer and this methods returns <CODE>null</CODE>.
+     */
+    public static String formatDouble(double d, ByteBuffer buf) {
+        boolean negative = false;
+        if (Math.abs(d) < 0.000015) {
+            if (buf != null) {
+                buf.append((byte)ZERO);
+                return null;
+            } else {
+                return "0";
+            }
+        }
+        if (d < 0) {
+            negative = true;
+            d = -d;
+        }
+        if (d < 1.0) {
+            d += 0.000005;
+            if (d >= 1) {
+                if (negative) {
+                    if (buf != null) {
+                        buf.append((byte)'-');
+                        buf.append((byte)'1');
+                        return null;
+                    } else {
+                        return "-1";
+                    }
+                } else {
+                    if (buf != null) {
+                        buf.append((byte)'1');
+                        return null;
+                    } else {
+                        return "1";
+                    }
+                }
+            }
+            if (buf != null) {
+                int v = (int) (d * 100000);
+                
+                if (negative) buf.append((byte)'-');
+                buf.append((byte)'0');
+                buf.append((byte)'.');
+                
+                buf.append( (byte)(v / 10000 + ZERO) );
+                if (v % 10000 != 0) {
+                    buf.append( (byte)((v / 1000) % 10 + ZERO) );
+                    if (v % 1000 != 0) {
+                        buf.append( (byte)((v / 100) % 10 + ZERO) );
+                        if (v % 100 != 0) {
+                            buf.append((byte)((v / 10) % 10 + ZERO) );
+                            if (v % 10 != 0) {
+                                buf.append((byte)((v) % 10 + ZERO) );
+                            }
+                        }
+                    }
+                }
+                return null;
+            } else {
+                int x = 100000;
+                int v = (int) (d * x);
+                
+                StringBuffer res = new StringBuffer();
+                if (negative) res.append('-');
+                res.append("0.");
+                
+                while( v < x/10 ) {
+                    res.append('0');
+                    x /= 10;
+                }
+                res.append(v);
+                int cut = res.length() - 1;
+                while (res.charAt(cut) == '0') {
+                    --cut;
+                }
+                res.setLength(cut + 1);
+                return res.toString();
+            }
+        } else if (d <= 32767) {
+            d += 0.005;
+            int v = (int) (d * 100);
+            
+            if (v < byteCacheSize && byteCache[v] != null) {
+                if (buf != null) {
+                    if (negative) buf.append((byte)'-');
+                    buf.append(byteCache[v]);
+                    return null;
+                } else {
+                    String tmp = PdfEncodings.convertToString(byteCache[v], null);
+                    if (negative) tmp = "-" + tmp;
+                    return tmp;
+                }
+            }
+            if (buf != null) {
+                if (v < byteCacheSize) {
+                    //create the cachebyte[]
+                    byte[] cache;
+                    int size = 0;
+                    if (v >= 1000000) {
+                        //the original number is >=10000, we need 5 more bytes
+                        size += 5;
+                    } else if (v >= 100000) {
+                        //the original number is >=1000, we need 4 more bytes
+                        size += 4;
+                    } else if (v >= 10000) {
+                        //the original number is >=100, we need 3 more bytes
+                        size += 3;
+                    } else if (v >= 1000) {
+                        //the original number is >=10, we need 2 more bytes
+                        size += 2;
+                    } else if (v >= 100) {
+                        //the original number is >=1, we need 1 more bytes
+                        size += 1;
+                    }
+                    
+                    //now we must check if we have a decimal number
+                    if (v % 100 != 0) {
+                        //yes, do not forget the "."
+                        size += 2;
+                    }
+                    if (v % 10 != 0) {
+                        size++;
+                    }
+                    cache = new byte[size];
+                    int add = 0;
+                    if (v >= 1000000) {
+                        cache[add++] = bytes[(v / 1000000)];
+                    }
+                    if (v >= 100000) {
+                        cache[add++] = bytes[(v / 100000) % 10];
+                    }
+                    if (v >= 10000) {
+                        cache[add++] = bytes[(v / 10000) % 10];
+                    }
+                    if (v >= 1000) {
+                        cache[add++] = bytes[(v / 1000) % 10];
+                    }
+                    if (v >= 100) {
+                        cache[add++] = bytes[(v / 100) % 10];
+                    }
+                    
+                    if (v % 100 != 0) {
+                        cache[add++] = (byte)'.';
+                        cache[add++] = bytes[(v / 10) % 10];
+                        if (v % 10 != 0) {
+                            cache[add++] = bytes[v % 10];
+                        }
+                    }
+                    byteCache[v] = cache;
+                }
+                
+                if (negative) buf.append((byte)'-');
+                if (v >= 1000000) {
+                    buf.append( bytes[(v / 1000000)] );
+                }
+                if (v >= 100000) {
+                    buf.append( bytes[(v / 100000) % 10] );
+                }
+                if (v >= 10000) {
+                    buf.append( bytes[(v / 10000) % 10] );
+                }
+                if (v >= 1000) {
+                    buf.append( bytes[(v / 1000) % 10] );
+                }
+                if (v >= 100) {
+                    buf.append( bytes[(v / 100) % 10] );
+                }
+                
+                if (v % 100 != 0) {
+                    buf.append((byte)'.');
+                    buf.append( bytes[(v / 10) % 10] );
+                    if (v % 10 != 0) {
+                        buf.append( bytes[v % 10] );
+                    }
+                }
+                return null;
+            } else {
+                StringBuffer res = new StringBuffer();
+                if (negative) res.append((char)'-');
+                if (v >= 1000000) {
+                    res.append( chars[(v / 1000000)] );
+                }
+                if (v >= 100000) {
+                    res.append( chars[(v / 100000) % 10] );
+                }
+                if (v >= 10000) {
+                    res.append( chars[(v / 10000) % 10] );
+                }
+                if (v >= 1000) {
+                    res.append( chars[(v / 1000) % 10] );
+                }
+                if (v >= 100) {
+                    res.append( chars[(v / 100) % 10] );
+                }
+                
+                if (v % 100 != 0) {
+                    res.append((char)'.');
+                    res.append( chars[(v / 10) % 10] );
+                    if (v % 10 != 0) {
+                        res.append( chars[v % 10] );
+                    }
+                }
+                return res.toString();
+            }
+        } else {
+            StringBuffer res = new StringBuffer();
+            if (negative) res.append('-');
+            d += 0.5;
+            long v = (long) d;
+            return res.append(v).toString();
+        }
+    }
+    
+    /**
+     * Sets the size to zero.
+     */
+    public void reset() {
+        count = 0;
+    }
+    
+    /**
+     * Creates a newly allocated byte array. Its size is the current
+     * size of this output stream and the valid contents of the buffer
+     * have been copied into it.
+     *
+     * @return  the current contents of this output stream, as a byte array.
+     */
+    public byte[] toByteArray() {
+        byte newbuf[] = new byte[count];
+        System.arraycopy(buf, 0, newbuf, 0, count);
+        return newbuf;
+    }
+    
+    /**
+     * Returns the current size of the buffer.
+     *
+     * @return the value of the <code>count</code> field, which is the number of valid bytes in this byte buffer.
+     */
+    public int size() {
+        return count;
+    }
+    
+    /**
+     * Converts the buffer's contents into a string, translating bytes into
+     * characters according to the platform's default character encoding.
+     *
+     * @return String translated from the buffer's contents.
+     */
+    public String toString() {
+        return new String(buf, 0, count);
+    }
+    
+    /**
+     * Converts the buffer's contents into a string, translating bytes into
+     * characters according to the specified character encoding.
+     *
+     * @param   enc  a character-encoding name.
+     * @return String translated from the buffer's contents.
+     * @throws UnsupportedEncodingException
+     *         If the named encoding is not supported.
+     */
+    public String toString(String enc) throws UnsupportedEncodingException {
+        return new String(buf, 0, count, enc);
+    }
+    
+    /**
+     * Writes the complete contents of this byte buffer output to
+     * the specified output stream argument, as if by calling the output
+     * stream's write method using <code>out.write(buf, 0, count)</code>.
+     *
+     * @param      out   the output stream to which to write the data.
+     * @exception  IOException  if an I/O error occurs.
+     */
+    public void writeTo(OutputStream out) throws IOException {
+        out.write(buf, 0, count);
+    }
+    
+    public void write(int b) throws IOException {
+        append((byte)b);
+    }
+    
+    public void write(byte[] b, int off, int len) {
+        append(b, off, len);
+    }
+    
+    public byte[] getBuffer() {
+        return buf;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/CFFFont.java b/LibrarySource/com/lowagie/text/pdf/CFFFont.java
new file mode 100644
index 0000000..ac337c0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/CFFFont.java
@@ -0,0 +1,1184 @@
+/*
+ *
+ * Copyright 2003 Sivan Toledo
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ */
+
+/*
+ * Comments by Sivan Toledo:
+ * I created this class in order to add to iText the ability to utilize
+ * OpenType fonts with CFF glyphs (these usually have an .otf extension).
+ * The CFF font within the CFF table of the OT font might be either a CID
+ * or a Type1 font. (CFF fonts may also contain multiple fonts; I do not
+ * know if this is allowed in an OT table). The PDF spec, however, only
+ * allow a CID font with an Identity-H or Identity-V encoding. Otherwise,
+ * you are limited to an 8-bit encoding.
+ * Adobe fonts come in both flavors. That is, the OTFs sometimes have
+ * a CID CFF inside (for Japanese fonts), and sometimes a Type1 CFF
+ * (virtually all the others, Latin/Greek/Cyrillic). So to easily use
+ * all the glyphs in the latter, without creating multiple 8-bit encoding,
+ * I wrote this class, whose main purpose is to convert a Type1 font inside
+ * a CFF container (which might include other fonts) into a CID CFF font
+ * that can be directly embeded in the PDF.
+ *
+ * Limitations of the current version:
+ * 1. It does not extract a single CID font from a CFF that contains that
+ *    particular CID along with other fonts. The Adobe Japanese OTF's that
+ *    I have only have one font in the CFF table, so these can be
+ *    embeded in the PDF as is.
+ * 2. It does not yet subset fonts.
+ * 3. It may or may not work on CFF fonts that are not within OTF's.
+ *    I didn't try that. In any case, that would probably only be
+ *    useful for subsetting CID fonts, not for CFF Type1 fonts (I don't
+ *    think there are any available.
+ * I plan to extend the class to support these three features at some
+ * future time.
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * @author stoledo
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.lowagie.text.ExceptionConverter;
+
+public class CFFFont {
+    
+    static final String operatorNames[] = {
+        "version", "Notice", "FullName", "FamilyName",
+        "Weight", "FontBBox", "BlueValues", "OtherBlues",
+        "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW",
+        "UNKNOWN_12", "UniqueID", "XUID", "charset",
+        "Encoding", "CharStrings", "Private", "Subrs",
+        "defaultWidthX", "nominalWidthX", "UNKNOWN_22", "UNKNOWN_23",
+        "UNKNOWN_24", "UNKNOWN_25", "UNKNOWN_26", "UNKNOWN_27",
+        "UNKNOWN_28", "UNKNOWN_29", "UNKNOWN_30", "UNKNOWN_31",
+        "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition",
+        "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix",
+        "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz",
+        "StemSnapH", "StemSnapV", "ForceBold", "UNKNOWN_12_15",
+        "UNKNOWN_12_16", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
+        "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend",
+        "UNKNOWN_12_24", "UNKNOWN_12_25", "UNKNOWN_12_26", "UNKNOWN_12_27",
+        "UNKNOWN_12_28", "UNKNOWN_12_29", "ROS", "CIDFontVersion",
+        "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase",
+        "FDArray", "FDSelect", "FontName"
+    };
+    
+    static final String standardStrings[] = {
+        // Automatically generated from Appendix A of the CFF specification; do
+        // not edit. Size should be 391.
+        ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
+        "percent", "ampersand", "quoteright", "parenleft", "parenright",
+        "asterisk", "plus", "comma", "hyphen", "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", "exclamdown", "cent", "sterling", "fraction", "yen",
+        "florin", "section", "currency", "quotesingle", "quotedblleft",
+        "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash",
+        "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet",
+        "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+        "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex",
+        "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
+        "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash",
+        "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe",
+        "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+        "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar",
+        "degree", "thorn", "threequarters", "twosuperior", "registered", "minus",
+        "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex",
+        "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute",
+        "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+        "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve",
+        "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave",
+        "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis",
+        "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex",
+        "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+        "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde",
+        "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute",
+        "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall",
+        "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
+        "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+        "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
+        "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
+        "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+        "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+        "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
+        "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior",
+        "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+        "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
+        "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
+        "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
+        "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+        "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
+        "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
+        "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
+        "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+        "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
+        "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
+        "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior",
+        "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
+        "ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
+        "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
+        "seveninferior", "eightinferior", "nineinferior", "centinferior",
+        "dollarinferior", "periodinferior", "commainferior", "Agravesmall",
+        "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
+        "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
+        "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
+        "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
+        "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
+        "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
+        "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
+        "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black",
+        "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
+    };
+    
+    //private String[] strings;
+    public String getString(char sid) {
+        if (sid < standardStrings.length) return standardStrings[sid];
+        if (sid >= standardStrings.length+(stringOffsets.length-1)) return null;
+        int j = sid - standardStrings.length;
+        //java.lang.System.err.println("going for "+j);
+        int p = getPosition();
+        seek(stringOffsets[j]);
+        StringBuffer s = new StringBuffer();
+        for (int k=stringOffsets[j]; k<stringOffsets[j+1]; k++) {
+            s.append(getCard8());
+        }
+        seek(p);
+        return s.toString();
+    }
+    
+    char getCard8() {
+        try {
+            byte i = buf.readByte();
+            return (char)(i & 0xff);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    char getCard16() {
+        try {
+            return buf.readChar();
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    int getOffset(int offSize) {
+        int offset = 0;
+        for (int i=0; i<offSize; i++) {
+            offset *= 256;
+            offset += getCard8();
+        }
+        return offset;
+    }
+    
+    void seek(int offset) {
+        try {
+            buf.seek(offset);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    short getShort() {
+        try {
+            return buf.readShort();
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    int getInt() {
+        try {
+            return buf.readInt();
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    int getPosition() {
+        try {
+            return buf.getFilePointer();
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    int nextIndexOffset;
+    // read the offsets in the next index
+    // data structure, convert to global
+    // offsets, and return them.
+    // Sets the nextIndexOffset.
+    int[] getIndex(int nextIndexOffset) {
+        int count, indexOffSize;
+        
+        seek(nextIndexOffset);
+        count = getCard16();
+        int[] offsets = new int[count+1];
+        
+        if (count==0) {
+            offsets[0] = -1;
+            nextIndexOffset += 2;
+            return offsets;
+        }
+        
+        indexOffSize = getCard8();
+        
+        for (int j=0; j<=count; j++) {
+        	//nextIndexOffset = ofset to relative segment
+            offsets[j] = nextIndexOffset
+			//2-> count in the index header. 1->offset size in index header
+            + 2+1
+			//offset array size * offset size 
+            + (count+1)*indexOffSize
+			//???zero <-> one base
+            - 1
+			// read object offset relative to object array base 
+            + getOffset(indexOffSize);
+        }
+        //nextIndexOffset = offsets[count];
+        return offsets;
+    }
+    
+    protected String   key;
+    protected Object[] args      = new Object[48];
+    protected int      arg_count = 0;
+    
+    protected void getDictItem() {
+        for (int i=0; i<arg_count; i++) args[i]=null;
+        arg_count = 0;
+        key = null;
+        boolean gotKey = false;
+        
+        while (!gotKey) {
+            char b0 = getCard8();
+            if (b0 == 29) {
+                int item = getInt();
+                args[arg_count] = new Integer(item);
+                arg_count++;
+                //System.err.println(item+" ");
+                continue;
+            }
+            if (b0 == 28) {
+                short item = getShort();
+                args[arg_count] = new Integer(item);
+                arg_count++;
+                //System.err.println(item+" ");
+                continue;
+            }
+            if (b0 >= 32 && b0 <= 246) {
+                byte item = (byte) (b0-139);
+                args[arg_count] = new Integer(item);
+                arg_count++;
+                //System.err.println(item+" ");
+                continue;
+            }
+            if (b0 >= 247 && b0 <= 250) {
+                char b1 = getCard8();
+                short item = (short) ((b0-247)*256+b1+108);
+                args[arg_count] = new Integer(item);
+                arg_count++;
+                //System.err.println(item+" ");
+                continue;
+            }
+            if (b0 >= 251 && b0 <= 254) {
+                char b1 = getCard8();
+                short item = (short) (-(b0-251)*256-b1-108);
+                args[arg_count] = new Integer(item);
+                arg_count++;
+                //System.err.println(item+" ");
+                continue;
+            }
+            if (b0 == 30) {
+                String item = "";
+                boolean done = false;
+                char buffer = 0;
+                byte avail = 0;
+                int  nibble = 0;
+                while (!done) {
+                    // get a nibble
+                    if (avail==0) { buffer = getCard8(); avail=2; }
+                    if (avail==1) { nibble = (buffer / 16); avail--; }
+                    if (avail==2) { nibble = (buffer % 16); avail--; }
+                    switch (nibble) {
+                        case 0xa: item += "." ; break;
+                        case 0xb: item += "E" ; break;
+                        case 0xc: item += "E-"; break;
+                        case 0xe: item += "-" ; break;
+                        case 0xf: done=true   ; break;
+                        default:
+                            if (nibble >= 0 && nibble <= 9)
+                                item += String.valueOf(nibble);
+                            else {
+                                item += "<NIBBLE ERROR: "+String.valueOf(nibble)+">";
+                                done = true;
+                            }
+                            break;
+                    }
+                }
+                args[arg_count] = item;
+                arg_count++;
+                //System.err.println(" real=["+item+"]");
+                continue;
+            }
+            if (b0 <= 21) {
+                gotKey=true;
+                if (b0 != 12) key = operatorNames[b0];
+                else key = operatorNames[32 + getCard8()];
+                //for (int i=0; i<arg_count; i++)
+                //  System.err.print(args[i].toString()+" ");
+                //System.err.println(key+" ;");
+                continue;
+            }
+        }
+    }
+    
+    /** List items for the linked list that builds the new CID font.
+     */
+    
+    protected static abstract class Item {
+        protected int myOffset = -1;
+        /** remember the current offset and increment by item's size in bytes. */
+        public void increment(int[] currentOffset) {
+            myOffset = currentOffset[0];
+        }
+        /** Emit the byte stream for this item. */
+        public void emit(byte[] buffer) {}
+        /** Fix up cross references to this item (applies only to markers). */
+        public void xref() {}
+    }
+    
+    protected static abstract class OffsetItem extends Item {
+        public int value;
+        /** set the value of an offset item that was initially unknown.
+         * It will be fixed up latex by a call to xref on some marker.
+         */
+        public void set(int offset) { this.value = offset; }
+    }
+    
+    
+    /** A range item.
+     */
+    
+    protected static final class RangeItem extends Item {
+        public int offset, length;
+        private RandomAccessFileOrArray buf;
+        public RangeItem(RandomAccessFileOrArray buf, int offset, int length) {
+            this.offset = offset;
+            this.length = length;
+            this.buf = buf;
+        }
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += length;
+        }
+        public void emit(byte[] buffer) {
+            //System.err.println("range emit offset "+offset+" size="+length);
+            try {
+                buf.seek(offset);
+                for (int i=myOffset; i<myOffset+length; i++)
+                    buffer[i] = buf.readByte();
+            }
+            catch (Exception e) {
+                throw new ExceptionConverter(e);
+            }
+            //System.err.println("finished range emit");
+        }
+    }
+    
+    /** An index-offset item for the list.
+     * The size denotes the required size in the CFF. A positive
+     * value means that we need a specific size in bytes (for offset arrays)
+     * and a negative value means that this is a dict item that uses a
+     * variable-size representation.
+     */
+    static protected final class IndexOffsetItem extends OffsetItem {
+        public final int size;
+        public IndexOffsetItem(int size, int value) {this.size=size; this.value=value;}
+        public IndexOffsetItem(int size) {this.size=size; }
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += size;
+        }
+        public void emit(byte[] buffer) {
+            int i=0;
+            switch (size) {
+                case 4:
+                    buffer[myOffset+i] = (byte) ((value >>> 24) & 0xff);
+                    i++;
+                case 3:
+                    buffer[myOffset+i] = (byte) ((value >>> 16) & 0xff);
+                    i++;
+                case 2:
+                    buffer[myOffset+i] = (byte) ((value >>>  8) & 0xff);
+                    i++;
+                case 1:
+                    buffer[myOffset+i] = (byte) ((value >>>  0) & 0xff);
+                    i++;
+            }
+            /*
+            int mask = 0xff;
+            for (int i=size-1; i>=0; i--) {
+                buffer[myOffset+i] = (byte) (value & mask);
+                mask <<= 8;
+            }
+             */
+        }
+    }
+    
+    static protected final class IndexBaseItem extends Item {
+        public IndexBaseItem() {}
+    }
+    
+    static protected final class IndexMarkerItem extends Item {
+        private OffsetItem offItem;
+        private IndexBaseItem indexBase;
+        public IndexMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
+            this.offItem   = offItem;
+            this.indexBase = indexBase;
+        }
+        public void xref() {
+            //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
+            offItem.set(this.myOffset-indexBase.myOffset+1);
+        }
+    }
+    /**
+     * 
+     * @author orly manor
+     *
+     * TODO To change the template for this generated type comment go to
+     * Window - Preferences - Java - Code Generation - Code and Comments
+     */
+    static protected final class SubrMarkerItem extends Item {
+        private OffsetItem offItem;
+        private IndexBaseItem indexBase;
+        public SubrMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
+            this.offItem   = offItem;
+            this.indexBase = indexBase;
+        }
+        public void xref() {
+            //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
+            offItem.set(this.myOffset-indexBase.myOffset);
+        }
+    }
+    
+    
+    /** an unknown offset in a dictionary for the list.
+     * We will fix up the offset later; for now, assume it's large.
+     */
+    static protected final class DictOffsetItem extends OffsetItem {
+        public final int size;
+        public DictOffsetItem() {this.size=5; }
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += size;
+        }
+        // this is incomplete!
+        public void emit(byte[] buffer) {
+            if (size==5) {
+                buffer[myOffset]   = 29;
+                buffer[myOffset+1] = (byte) ((value >>> 24) & 0xff);
+                buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
+                buffer[myOffset+3] = (byte) ((value >>>  8) & 0xff);
+                buffer[myOffset+4] = (byte) ((value >>>  0) & 0xff);
+            }
+        }
+    }
+    
+	/** Card24 item.
+     */
+    
+    static protected final class UInt24Item extends Item {
+        public int value;
+        public UInt24Item(int value) {this.value=value;}
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += 3;
+        }
+        // this is incomplete!
+        public void emit(byte[] buffer) {
+        	buffer[myOffset+0] = (byte) ((value >>> 16) & 0xff);
+            buffer[myOffset+1] = (byte) ((value >>> 8) & 0xff);
+            buffer[myOffset+2] = (byte) ((value >>> 0) & 0xff);
+        }
+    }
+    
+    /** Card32 item.
+     */
+    
+    static protected final class UInt32Item extends Item {
+        public int value;
+        public UInt32Item(int value) {this.value=value;}
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += 4;
+        }
+        // this is incomplete!
+        public void emit(byte[] buffer) {
+        	buffer[myOffset+0] = (byte) ((value >>> 24) & 0xff);
+        	buffer[myOffset+1] = (byte) ((value >>> 16) & 0xff);
+            buffer[myOffset+2] = (byte) ((value >>> 8) & 0xff);
+            buffer[myOffset+3] = (byte) ((value >>> 0) & 0xff);
+        }
+    }
+
+    /** A SID or Card16 item.
+     */
+    
+    static protected final class UInt16Item extends Item {
+        public char value;
+        public UInt16Item(char value) {this.value=value;}
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += 2;
+        }
+        // this is incomplete!
+        public void emit(byte[] buffer) {
+            buffer[myOffset+0] = (byte) ((value >>> 8) & 0xff);
+            buffer[myOffset+1] = (byte) ((value >>> 0) & 0xff);
+        }
+    }
+    
+    /** A Card8 item.
+     */
+    
+    static protected final class UInt8Item extends Item {
+        public char value;
+        public UInt8Item(char value) {this.value=value;}
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += 1;
+        }
+        // this is incomplete!
+        public void emit(byte[] buffer) {
+            buffer[myOffset+0] = (byte) ((value >>> 0) & 0xff);
+        }
+    }
+    
+    static protected final class StringItem extends Item {
+        public String s;
+        public StringItem(String s) {this.s=s;}
+        
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += s.length();
+        }
+        public void emit(byte[] buffer) {
+            for (int i=0; i<s.length(); i++)
+                buffer[myOffset+i] = (byte) (s.charAt(i) & 0xff);
+        }
+    }
+    
+    
+    /** A dictionary number on the list.
+     * This implementation is inefficient: it doesn't use the variable-length
+     * representation.
+     */
+    
+    static protected final class DictNumberItem extends Item {
+        public final int value;
+        public int size = 5;
+        public DictNumberItem(int value) {this.value=value;}
+        public void increment(int[] currentOffset) {
+            super.increment(currentOffset);
+            currentOffset[0] += size;
+        }
+        // this is imcomplete!
+        public void emit(byte[] buffer) {
+            if (size==5) {
+                buffer[myOffset]   = 29;
+                buffer[myOffset+1] = (byte) ((value >>> 24) & 0xff);
+                buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
+                buffer[myOffset+3] = (byte) ((value >>>  8) & 0xff);
+                buffer[myOffset+4] = (byte) ((value >>>  0) & 0xff);
+            }
+        }
+    }
+    
+    /** An offset-marker item for the list.
+     * It is used to mark an offset and to set the offset list item.
+     */
+    
+    static protected final class MarkerItem extends Item {
+        OffsetItem p;
+        public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
+        public void xref() {
+            p.set(this.myOffset);
+        }
+    }
+    
+    /** a utility that creates a range item for an entire index
+     *
+     * @param indexOffset where the index is
+     * @return a range item representing the entire index
+     */
+    
+    protected RangeItem getEntireIndexRange(int indexOffset) {
+        seek(indexOffset);
+        int count = getCard16();
+        if (count==0) {
+            return new RangeItem(buf,indexOffset,2);
+        } else {
+            int indexOffSize = getCard8();
+            seek(indexOffset+2+1+count*indexOffSize);
+            int size = getOffset(indexOffSize)-1;
+            return new RangeItem(buf,indexOffset,
+            2+1+(count+1)*indexOffSize+size);
+        }
+    }
+    
+    
+    /** get a single CID font. The PDF architecture (1.4)
+     * supports 16-bit strings only with CID CFF fonts, not
+     * in Type-1 CFF fonts, so we convert the font to CID if
+     * it is in the Type-1 format.
+     * Two other tasks that we need to do are to select
+     * only a single font from the CFF package (this again is
+     * a PDF restriction) and to subset the CharStrings glyph
+     * description.
+     */
+    
+    
+    public byte[] getCID(String fontName)
+    //throws java.io.FileNotFoundException
+    {
+        int j;
+        for (j=0; j<fonts.length; j++)
+            if (fontName.equals(fonts[j].name)) break;
+        if (j==fonts.length) return null;
+        
+        LinkedList l = new LinkedList();
+        
+        // copy the header
+        
+        seek(0);
+        
+        int major = getCard8();
+        int minor = getCard8();
+        int hdrSize = getCard8();
+        int offSize = getCard8();
+        nextIndexOffset = hdrSize;
+        
+        l.addLast(new RangeItem(buf,0,hdrSize));
+        
+        int nglyphs=-1, nstrings=-1;
+        if ( ! fonts[j].isCID ) {
+            // count the glyphs
+            seek(fonts[j].charstringsOffset);
+            nglyphs = getCard16();
+            seek(stringIndexOffset);
+            nstrings = getCard16()+standardStrings.length;
+            //System.err.println("number of glyphs = "+nglyphs);
+        }
+        
+        // create a name index
+        
+        l.addLast(new UInt16Item((char)1)); // count
+        l.addLast(new UInt8Item((char)1)); // offSize
+        l.addLast(new UInt8Item((char)1)); // first offset
+        l.addLast(new UInt8Item((char)( 1+fonts[j].name.length() )));
+        l.addLast(new StringItem(fonts[j].name));
+        
+        // create the topdict Index
+        
+        
+        l.addLast(new UInt16Item((char)1)); // count
+        l.addLast(new UInt8Item((char)2)); // offSize
+        l.addLast(new UInt16Item((char)1)); // first offset
+        OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
+        l.addLast(topdictIndex1Ref);
+        IndexBaseItem topdictBase = new IndexBaseItem();
+        l.addLast(topdictBase);
+        
+        /*
+        int maxTopdictLen = (topdictOffsets[j+1]-topdictOffsets[j])
+                            + 9*2 // at most 9 new keys
+                            + 8*5 // 8 new integer arguments
+                            + 3*2;// 3 new SID arguments
+         */
+        
+        //int    topdictNext = 0;
+        //byte[] topdict = new byte[maxTopdictLen];
+        
+        OffsetItem charsetRef     = new DictOffsetItem();
+        OffsetItem charstringsRef = new DictOffsetItem();
+        OffsetItem fdarrayRef     = new DictOffsetItem();
+        OffsetItem fdselectRef    = new DictOffsetItem();
+        
+        if ( !fonts[j].isCID ) {
+            // create a ROS key
+            l.addLast(new DictNumberItem(nstrings));
+            l.addLast(new DictNumberItem(nstrings+1));
+            l.addLast(new DictNumberItem(0));
+            l.addLast(new UInt8Item((char)12));
+            l.addLast(new UInt8Item((char)30));
+            // create a CIDCount key
+            l.addLast(new DictNumberItem(nglyphs));
+            l.addLast(new UInt8Item((char)12));
+            l.addLast(new UInt8Item((char)34));
+            // What about UIDBase (12,35)? Don't know what is it.
+            // I don't think we need FontName; the font I looked at didn't have it.
+        }
+        
+        // create an FDArray key
+        l.addLast(fdarrayRef);
+        l.addLast(new UInt8Item((char)12));
+        l.addLast(new UInt8Item((char)36));
+        // create an FDSelect key
+        l.addLast(fdselectRef);
+        l.addLast(new UInt8Item((char)12));
+        l.addLast(new UInt8Item((char)37));
+        // create an charset key
+        l.addLast(charsetRef);
+        l.addLast(new UInt8Item((char)15));
+        // create a CharStrings key
+        l.addLast(charstringsRef);
+        l.addLast(new UInt8Item((char)17));
+        
+        seek(topdictOffsets[j]);
+        while (getPosition() < topdictOffsets[j+1]) {
+            int p1 = getPosition();
+            getDictItem();
+            int p2 = getPosition();
+            if (key=="Encoding"
+            || key=="Private"
+            || key=="FDSelect"
+            || key=="FDArray"
+            || key=="charset"
+            || key=="CharStrings"
+            ) {
+                // just drop them
+            } else {
+                l.add(new RangeItem(buf,p1,p2-p1));
+            }
+        }
+        
+        l.addLast(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
+        
+        // Copy the string index and append new strings.
+        // We need 3 more strings: Registry, Ordering, and a FontName for one FD.
+        // The total length is at most "Adobe"+"Identity"+63 = 76
+        
+        if (fonts[j].isCID) {
+            l.addLast(getEntireIndexRange(stringIndexOffset));
+        } else {
+            String fdFontName = fonts[j].name+"-OneRange";
+            if (fdFontName.length() > 127)
+                fdFontName = fdFontName.substring(0,127);
+            String extraStrings = "Adobe"+"Identity"+fdFontName;
+            
+            int origStringsLen = stringOffsets[stringOffsets.length-1]
+            - stringOffsets[0];
+            int stringsBaseOffset = stringOffsets[0]-1;
+            
+            byte stringsIndexOffSize;
+            if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
+            else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
+            else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
+            else stringsIndexOffSize = 4;
+            
+            l.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
+            l.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
+            for (int i=0; i<stringOffsets.length; i++)
+                l.addLast(new IndexOffsetItem(stringsIndexOffSize,
+                stringOffsets[i]-stringsBaseOffset));
+            int currentStringsOffset = stringOffsets[stringOffsets.length-1]
+            - stringsBaseOffset;
+            //l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+            currentStringsOffset += ("Adobe").length();
+            l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+            currentStringsOffset += ("Identity").length();
+            l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+            currentStringsOffset += fdFontName.length();
+            l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+            
+            l.addLast(new RangeItem(buf,stringOffsets[0],origStringsLen));
+            l.addLast(new StringItem(extraStrings));
+        }
+        
+        // copy the global subroutine index
+        
+        l.addLast(getEntireIndexRange(gsubrIndexOffset));
+        
+        // deal with fdarray, fdselect, and the font descriptors
+        
+        if (fonts[j].isCID) {
+            // copy the FDArray, FDSelect, charset
+        } else {
+            // create FDSelect
+            l.addLast(new MarkerItem(fdselectRef));
+            l.addLast(new UInt8Item((char)3)); // format identifier
+            l.addLast(new UInt16Item((char)1)); // nRanges
+            
+            l.addLast(new UInt16Item((char)0)); // Range[0].firstGlyph
+            l.addLast(new UInt8Item((char)0)); // Range[0].fd
+            
+            l.addLast(new UInt16Item((char)nglyphs)); // sentinel
+            
+            // recreate a new charset
+            // This format is suitable only for fonts without subsetting
+            
+            l.addLast(new MarkerItem(charsetRef));
+            l.addLast(new UInt8Item((char)2)); // format identifier
+            
+            l.addLast(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
+            l.addLast(new UInt16Item((char)(nglyphs-1))); // nLeft
+            // now all are covered, the data structure is complete.
+            
+            // create a font dict index (fdarray)
+            
+            l.addLast(new MarkerItem(fdarrayRef));
+            l.addLast(new UInt16Item((char)1));
+            l.addLast(new UInt8Item((char)1)); // offSize
+            l.addLast(new UInt8Item((char)1)); // first offset
+            
+            OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
+            l.addLast(privateIndex1Ref);
+            IndexBaseItem privateBase = new IndexBaseItem();
+            l.addLast(privateBase);
+            
+            // looking at the PS that acrobat generates from a PDF with
+            // a CFF opentype font embeded with an identity-H encoding,
+            // it seems that it does not need a FontName.
+            //l.addLast(new DictNumberItem((standardStrings.length+(stringOffsets.length-1)+2)));
+            //l.addLast(new UInt8Item((char)12));
+            //l.addLast(new UInt8Item((char)38)); // FontName
+            
+            l.addLast(new DictNumberItem(fonts[j].privateLength));
+            OffsetItem privateRef = new DictOffsetItem();
+            l.addLast(privateRef);
+            l.addLast(new UInt8Item((char)18)); // Private
+            
+            l.addLast(new IndexMarkerItem(privateIndex1Ref,privateBase));
+            
+            // copy the private index & local subroutines
+            
+            l.addLast(new MarkerItem(privateRef));
+            // copy the private dict and the local subroutines.
+            // the length of the private dict seems to NOT include
+            // the local subroutines.
+            l.addLast(new RangeItem(buf,fonts[j].privateOffset,fonts[j].privateLength));
+            if (fonts[j].privateSubrs >= 0) {
+                //System.err.println("has subrs="+fonts[j].privateSubrs+" ,len="+fonts[j].privateLength);
+                l.addLast(getEntireIndexRange(fonts[j].privateSubrs));
+            }
+        }
+        
+        // copy the charstring index
+        
+        l.addLast(new MarkerItem(charstringsRef));
+        l.addLast(getEntireIndexRange(fonts[j].charstringsOffset));
+        
+        // now create the new CFF font
+        
+        int[] currentOffset = new int[1];
+        currentOffset[0] = 0;
+        
+        Iterator listIter = l.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.increment(currentOffset);
+        }
+        
+        listIter = l.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.xref();
+        }
+        
+        int size = currentOffset[0];
+        byte[] b = new byte[size];
+        
+        listIter = l.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.emit(b);
+        }
+        
+        return b;
+    }
+    
+    
+    public boolean isCID(String fontName) {
+        int j;
+        for (j=0; j<fonts.length; j++)
+            if (fontName.equals(fonts[j].name)) return fonts[j].isCID;
+        return false;
+    }
+    
+    public boolean exists(String fontName) {
+        int j;
+        for (j=0; j<fonts.length; j++)
+            if (fontName.equals(fonts[j].name)) return true;
+        return false;
+    }
+    
+    
+    public String[] getNames() {
+        String[] names = new String[ fonts.length ];
+        for (int i=0; i<fonts.length; i++)
+            names[i] = fonts[i].name;
+        return names;
+    }
+    /**
+     * A random Access File or an array
+     * (contributed by orly manor)
+     */
+    protected RandomAccessFileOrArray buf;
+    private int offSize;
+    
+    protected int nameIndexOffset;
+    protected int topdictIndexOffset;
+    protected int stringIndexOffset;
+    protected int gsubrIndexOffset;
+    protected int[] nameOffsets;
+    protected int[] topdictOffsets;
+    protected int[] stringOffsets;
+    protected int[] gsubrOffsets;
+    
+    /**
+     * @author orly manor
+     * TODO Changed from private to protected by Ygal&Oren
+     */
+    protected final class Font {
+        public String    name;
+        public String    fullName;
+        public boolean   isCID = false;
+        public int       privateOffset     = -1; // only if not CID
+        public int       privateLength     = -1; // only if not CID
+        public int       privateSubrs      = -1;
+        public int       charstringsOffset = -1;
+        public int       encodingOffset    = -1;
+        public int       charsetOffset     = -1;
+        public int       fdarrayOffset     = -1; // only if CID
+        public int       fdselectOffset    = -1; // only if CID
+        public int[]     fdprivateOffsets;
+        public int[]     fdprivateLengths;
+        public int[]     fdprivateSubrs;
+        
+        // Added by Oren & Ygal
+        public int nglyphs;
+        public int nstrings;
+        public int CharsetLength;
+        public int[]    charstringsOffsets;
+        public int[]    charset;
+        public int[] 	FDSelect;
+        public int FDSelectLength;
+        public int FDSelectFormat;
+        public int 		CharstringType = 2;
+        public int FDArrayCount;
+        public int FDArrayOffsize;
+        public int[] FDArrayOffsets;
+        public int[] PrivateSubrsOffset;
+        public int[][] PrivateSubrsOffsetsArray;
+        public int[]       SubrsOffsets;
+    }
+    // Changed from private to protected by Ygal&Oren
+    protected Font[] fonts;
+    
+    public CFFFont(RandomAccessFileOrArray inputbuffer) {
+        
+        //System.err.println("CFF: nStdString = "+standardStrings.length);
+        buf = inputbuffer;
+        seek(0);
+        
+        int major, minor;
+        major = getCard8();
+        minor = getCard8();
+        
+        //System.err.println("CFF Major-Minor = "+major+"-"+minor);
+        
+        int hdrSize = getCard8();
+        
+        offSize = getCard8();
+        
+        //System.err.println("offSize = "+offSize);
+        
+        //int count, indexOffSize, indexOffset, nextOffset;
+        
+        nameIndexOffset    = hdrSize;
+        nameOffsets        = getIndex(nameIndexOffset);
+        topdictIndexOffset = nameOffsets[nameOffsets.length-1];
+        topdictOffsets     = getIndex(topdictIndexOffset);
+        stringIndexOffset  = topdictOffsets[topdictOffsets.length-1];
+        stringOffsets      = getIndex(stringIndexOffset);
+        gsubrIndexOffset   = stringOffsets[stringOffsets.length-1];
+        gsubrOffsets       = getIndex(gsubrIndexOffset);
+        
+        fonts = new Font[nameOffsets.length-1];
+        
+        // now get the name index
+        
+        /*
+        names             = new String[nfonts];
+        privateOffset     = new int[nfonts];
+        charsetOffset     = new int[nfonts];
+        encodingOffset    = new int[nfonts];
+        charstringsOffset = new int[nfonts];
+        fdarrayOffset     = new int[nfonts];
+        fdselectOffset    = new int[nfonts];
+         */
+        
+        for (int j=0; j<nameOffsets.length-1; j++) {
+            fonts[j] = new Font();
+            seek(nameOffsets[j]);
+            fonts[j].name = "";
+            for (int k=nameOffsets[j]; k<nameOffsets[j+1]; k++) {
+                fonts[j].name += (char)getCard8();
+            }
+            //System.err.println("name["+j+"]=<"+fonts[j].name+">");
+        }
+        
+        // string index
+        
+        //strings = new String[stringOffsets.length-1];
+        /*
+        System.err.println("std strings = "+standardStrings.length);
+        System.err.println("fnt strings = "+(stringOffsets.length-1));
+        for (char j=0; j<standardStrings.length+(stringOffsets.length-1); j++) {
+            //seek(stringOffsets[j]);
+            //strings[j] = "";
+            //for (int k=stringOffsets[j]; k<stringOffsets[j+1]; k++) {
+            //	strings[j] += (char)getCard8();
+            //}
+            System.err.println("j="+(int)j+" <? "+(standardStrings.length+(stringOffsets.length-1)));
+            System.err.println("strings["+(int)j+"]=<"+getString(j)+">");
+        }
+         */
+        
+        // top dict
+        
+        for (int j=0; j<topdictOffsets.length-1; j++) {
+            seek(topdictOffsets[j]);
+            while (getPosition() < topdictOffsets[j+1]) {            	
+                getDictItem();
+                if (key=="FullName") {
+                    //System.err.println("getting fullname sid = "+((Integer)args[0]).intValue());
+                    fonts[j].fullName = getString((char)((Integer)args[0]).intValue());
+                    //System.err.println("got it");
+                } else if (key=="ROS")
+                    fonts[j].isCID = true;
+                else if (key=="Private") {
+                    fonts[j].privateLength  = ((Integer)args[0]).intValue();
+                    fonts[j].privateOffset  = ((Integer)args[1]).intValue();
+                }
+                else if (key=="charset"){
+                    fonts[j].charsetOffset = ((Integer)args[0]).intValue();
+                    
+                }
+                else if (key=="Encoding"){
+                    fonts[j].encodingOffset = ((Integer)args[0]).intValue();
+                    ReadEncoding(fonts[j].encodingOffset);
+                }
+                else if (key=="CharStrings") {
+                    fonts[j].charstringsOffset = ((Integer)args[0]).intValue();
+                    //System.err.println("charstrings "+fonts[j].charstringsOffset);
+                    // Added by Oren & Ygal
+                    int p = getPosition();
+                    fonts[j].charstringsOffsets = getIndex(fonts[j].charstringsOffset);
+                    seek(p);
+                } else if (key=="FDArray")
+                    fonts[j].fdarrayOffset = ((Integer)args[0]).intValue();
+                else if (key=="FDSelect")
+                    fonts[j].fdselectOffset = ((Integer)args[0]).intValue();
+                else if (key=="CharstringType")
+                	fonts[j].CharstringType = ((Integer)args[0]).intValue();
+            }
+            
+            // private dict
+            if (fonts[j].privateOffset >= 0) {
+                //System.err.println("PRIVATE::");
+                seek(fonts[j].privateOffset);
+                while (getPosition() < fonts[j].privateOffset+fonts[j].privateLength) {
+                    getDictItem();
+                    if (key=="Subrs")
+                    	//Add the private offset to the lsubrs since the offset is 
+                    	// relative to the begining of the PrivateDict
+                        fonts[j].privateSubrs = ((Integer)args[0]).intValue()+fonts[j].privateOffset;
+                }
+            }
+            
+            // fdarray index
+            if (fonts[j].fdarrayOffset >= 0) {
+                int[] fdarrayOffsets = getIndex(fonts[j].fdarrayOffset);
+                
+                fonts[j].fdprivateOffsets = new int[fdarrayOffsets.length-1];
+                fonts[j].fdprivateLengths = new int[fdarrayOffsets.length-1];
+                
+                //System.err.println("FD Font::");
+                
+                for (int k=0; k<fdarrayOffsets.length-1; k++) {
+                    seek(fdarrayOffsets[k]);
+                    while (getPosition() < fdarrayOffsets[k+1])
+                        getDictItem();
+                    if (key=="Private") {
+                        fonts[j].fdprivateLengths[k]  = ((Integer)args[0]).intValue();
+                        fonts[j].fdprivateOffsets[k]  = ((Integer)args[1]).intValue();
+                    }
+                    
+                }
+            }
+        }
+        //System.err.println("CFF: done");
+    }
+    
+    // ADDED BY Oren & Ygal
+    
+    void ReadEncoding(int nextIndexOffset){
+    	int format;
+    	seek(nextIndexOffset);
+    	format = getCard8();
+    }    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/CFFFontSubset.java b/LibrarySource/com/lowagie/text/pdf/CFFFontSubset.java
new file mode 100644
index 0000000..fdc8aec
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/CFFFontSubset.java
@@ -0,0 +1,1633 @@
+/*
+ * $Id: CFFFontSubset.java,v 1.3 2005/02/17 09:20:54 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2004 Oren Manor and Ygal Blum
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ArrayList;
+import java.io.*;
+
+/**
+ * This Class subsets a CFF Type Font. The subset is preformed for CID fonts and NON CID fonts.
+ * The Charstring is subseted for both types. For CID fonts only the FDArray which are used are embedded. 
+ * The Lsubroutines of the FDArrays used are subsetted as well. The Subroutine subset supports both Type1 and Type2
+ * formatting altough only tested on Type2 Format.
+ * For Non CID the Lsubroutines are subsetted. On both types the Gsubroutines is subsetted. 
+ * A font which was not of CID type is transformed into CID as a part of the subset process. 
+ * The CID synthetic creation was written by Sivan Toledo <sivan at math.tau.ac.il> 
+ * @author Oren Manor <manorore at post.tau.ac.il> & Ygal Blum <blumygal at post.tau.ac.il>
+ */
+public class CFFFontSubset extends CFFFont {
+	
+	/**
+	 *  The Strings in this array represent Type1/Type2 operator names
+	 */
+	static final String SubrsFunctions[] = {
+			"RESERVED_0","hstem","RESERVED_2","vstem","vmoveto","rlineto","hlineto","vlineto",
+			"rrcurveto","RESERVED_9","callsubr","return","escape","RESERVED_13",
+			"endchar","RESERVED_15","RESERVED_16","RESERVED_17","hstemhm","hintmask",
+			"cntrmask","rmoveto","hmoveto","vstemhm","rcurveline","rlinecurve","vvcurveto",
+			"hhcurveto","shortint","callgsubr","vhcurveto","hvcurveto"
+			};
+	/**
+	 * The Strings in this array represent Type1/Type2 escape operator names
+	 */
+	static final String SubrsEscapeFuncs[] = {
+			"RESERVED_0","RESERVED_1","RESERVED_2","and","or","not","RESERVED_6",
+			"RESERVED_7","RESERVED_8","abs","add","sub","div","RESERVED_13","neg",
+			"eq","RESERVED_16","RESERVED_17","drop","RESERVED_19","put","get","ifelse",
+			"random","mul","RESERVED_25","sqrt","dup","exch","index","roll","RESERVED_31",
+			"RESERVED_32","RESERVED_33","hflex","flex","hflex1","flex1","RESERVED_REST"
+	};
+	
+	/**
+	 * A HashMap containing the glyphs used in the text after being converted
+	 * to glyph number by the CMap 
+	 */
+	HashMap GlyphsUsed;
+	/**
+	 * The GlyphsUsed keys as an ArrayList
+	 */
+	ArrayList glyphsInList;
+	/**
+	 * A HashMap for keeping the FDArrays being used by the font
+	 */
+	HashMap FDArrayUsed = new HashMap();
+	/**
+	 * A HashMaps array for keeping the subroutines used in each FontDict
+	 */
+	HashMap[] hSubrsUsed;
+	/**
+	 * The SubroutinesUsed HashMaps as ArrayLists
+	 */
+	ArrayList[] lSubrsUsed;
+	/**
+	 * A HashMap for keeping the Global subroutines used in the font
+	 */
+	HashMap hGSubrsUsed  = new HashMap();
+	/**
+	 * The Global SubroutinesUsed HashMaps as ArrayLists
+	 */
+	ArrayList lGSubrsUsed = new ArrayList();
+	/**
+	 * A HashMap for keeping the subroutines used in a non-cid font
+	 */
+	HashMap hSubrsUsedNonCID  = new HashMap();
+	/**
+	 * The SubroutinesUsed HashMap as ArrayList
+	 */
+	ArrayList lSubrsUsedNonCID = new ArrayList();
+	/**
+	 * An array of the new Indexs for the local Subr. One index for each FontDict
+	 */
+	byte[][] NewLSubrsIndex;
+	/**
+	 * The new subroutines index for a non-cid font
+	 */
+	byte[] NewSubrsIndexNonCID;
+	/**
+	 * The new global subroutines index of the font
+	 */
+	byte[] NewGSubrsIndex;
+	/**
+	 * The new CharString of the font
+	 */
+	byte[] NewCharStringsIndex;
+	
+	/**
+	 * The bias for the global subroutines
+	 */
+	int GBias = 0;
+	
+	/**
+	 * The linked list for generating the new font stream
+	 */
+	LinkedList OutputList;
+	
+	/**
+	 * Number of arguments to the stem operators in a subroutine calculated recursivly
+	 */
+	int NumOfHints=0;
+
+	
+	/**	 
+	 * C'tor for CFFFontSubset
+	 * @param rf - The font file
+	 * @param GlyphsUsed - a HashMap that contains the glyph used in the subset 
+	 */
+    public CFFFontSubset(RandomAccessFileOrArray rf,HashMap GlyphsUsed){
+		// Use CFFFont c'tor in order to parse the font file.
+    	super(rf);
+		this.GlyphsUsed = GlyphsUsed;
+		//Put the glyphs into a list
+		glyphsInList = new ArrayList(GlyphsUsed.keySet());
+		
+		
+		for (int i=0;i<fonts.length;++i)
+		{
+			// Read the number of glyphs in the font
+			seek(fonts[i].charstringsOffset);
+	        fonts[i].nglyphs = getCard16();
+	        
+	    	// Jump to the count field of the String Index
+	        seek(stringIndexOffset);
+	        fonts[i].nstrings = getCard16()+standardStrings.length;
+	        
+	        // For each font save the offset array of the charstring
+			fonts[i].charstringsOffsets = getIndex(fonts[i].charstringsOffset);
+			
+			// Proces the FDSelect if exist 
+			if (fonts[i].fdselectOffset>=0)
+			{
+				// Proces the FDSelect
+	            readFDSelect(i);
+	            // Build the FDArrayUsed hashmap
+            	BuildFDArrayUsed(i);
+			}
+			if (fonts[i].isCID)
+				// Build the FD Array used Hash Map
+				ReadFDArray(i);
+			// compute the charset length 
+			fonts[i].CharsetLength = CountCharset(fonts[i].charsetOffset,fonts[i].nglyphs);
+		}
+	}
+
+    /**
+     * Calculates the length of the charset according to its format
+     * @param Offset The Charset Offset
+     * @param NumofGlyphs Number of glyphs in the font
+     * @return the length of the Charset
+     */
+    int CountCharset(int Offset,int NumofGlyphs){
+    	int format;
+    	int Length=0;
+    	seek(Offset);
+    	// Read the format
+    	format = getCard8();
+    	// Calc according to format
+    	switch (format){
+    		case 0:
+    			Length = 1+2*NumofGlyphs;
+    			break;
+    		case 1:
+    			Length = 1+3*CountRange(NumofGlyphs,1);
+    			break;
+    		case 2:
+    			Length = 1+4*CountRange(NumofGlyphs,2);
+    			break;
+    		default:
+    			break;
+    	}
+    	return Length;
+    }
+    
+    /**
+     * Function calculates the number of ranges in the Charset
+     * @param NumofGlyphs The number of glyphs in the font
+     * @param Type The format of the Charset
+     * @return The number of ranges in the Charset data structure
+     */
+    int CountRange(int NumofGlyphs,int Type){
+    	int num=0;
+    	char Sid;
+    	int i=1,nLeft,Places;
+    	while (i<NumofGlyphs){
+    		num++;
+    		Sid = getCard16();
+    		if (Type==1)
+    			nLeft = getCard8();
+    		else
+    			nLeft = getCard16();
+    		i += nLeft+1;
+    	}
+    	return num;
+    }
+
+
+	/**
+	 * Read the FDSelect of the font and compute the array and its length
+	 * @param Font The index of the font being processed
+	 * @return The Processed FDSelect of the font
+	 */
+	protected void readFDSelect(int Font)
+	{
+		// Restore the number of glyphs
+		int NumOfGlyphs = fonts[Font].nglyphs;
+		int[] FDSelect = new int[NumOfGlyphs];
+		// Go to the beginning of the FDSelect
+		seek(fonts[Font].fdselectOffset);
+		// Read the FDSelect's format
+		fonts[Font].FDSelectFormat = getCard8();
+		
+		switch(fonts[Font].FDSelectFormat){
+			// Format==0 means each glyph has an entry that indicated
+			// its FD.
+			case 0:
+				for (int i=0;i<NumOfGlyphs;i++)
+				{
+					FDSelect[i] = getCard8();
+				}
+				// The FDSelect's Length is one for each glyph + the format
+				// for later use
+				fonts[Font].FDSelectLength = fonts[Font].nglyphs+1;
+				break;
+			case 3:
+				// Format==3 means the ranges version
+				// The number of ranges
+				int nRanges = getCard16();
+				int l=0;
+				// Read the first in the first range
+				int first = getCard16();
+				for (int i=0;i<nRanges;i++)
+				{
+					// Read the FD index
+					int fd = getCard8();
+					// Read the first of the next range
+					int last = getCard16();
+					// Calc the steps and write to the array
+					int steps = last-first;
+					for (int k=0;k<steps;k++)
+					{
+						FDSelect[l] = fd;
+						l++;
+					}
+					// The last from this iteration is the first of the next
+					first = last;
+				}
+				// Store the length for later use
+				fonts[Font].FDSelectLength = 1+2+nRanges*3+2;
+				break;
+			default:
+				break;
+		}
+		// Save the FDSelect of the font 
+		fonts[Font].FDSelect = FDSelect; 
+	}
+	
+	/**
+	 * Function reads the FDSelect and builds the FDArrayUsed HashMap According to the glyphs used
+	 * @param Font the Number of font being processed
+	 */
+	protected void BuildFDArrayUsed(int Font)
+	{
+		int[] FDSelect = fonts[Font].FDSelect;
+		// For each glyph used
+		for (int i=0;i<glyphsInList.size();i++)
+		{
+			// Pop the glyphs index
+			int glyph = ((Integer)glyphsInList.get(i)).intValue();
+			// Pop the glyph's FD
+			int FD = FDSelect[glyph];
+			// Put the FD index into the FDArrayUsed HashMap
+			FDArrayUsed.put(new Integer(FD),null);
+		}
+	}
+
+	/**
+	 * Read the FDArray count, offsize and Offset array
+	 * @param Font
+	 */
+	protected void ReadFDArray(int Font)
+	{
+		seek(fonts[Font].fdarrayOffset);
+		fonts[Font].FDArrayCount = getCard16();
+		fonts[Font].FDArrayOffsize = getCard8();
+		// Since we will change values inside the FDArray objects
+		// We increase its offsize to prevent errors 
+		if (fonts[Font].FDArrayOffsize < 4)
+			fonts[Font].FDArrayOffsize++;
+		fonts[Font].FDArrayOffsets = getIndex(fonts[Font].fdarrayOffset);
+	}
+
+    
+	/**
+	 * The Process function extracts one font out of the CFF file and returns a
+	 * subset version of the original.
+	 * @param fontName - The name of the font to be taken out of the CFF
+	 * @return The new font stream
+	 * @throws IOException
+	 */
+	public byte[] Process(String fontName)throws IOException{
+		try
+		{	
+			// Verify that the file is open
+			buf.reOpen();
+			// Find the Font that we will be dealing with
+			int j;
+	        for (j=0; j<fonts.length; j++)
+	            if (fontName.equals(fonts[j].name)) break;
+	        if (j==fonts.length) return null;
+	        
+			// Calc the bias for the global subrs
+			if (gsubrIndexOffset >= 0)
+				GBias = CalcBias(gsubrIndexOffset,j);
+
+	        // Prepare the new CharStrings Index
+			BuildNewCharString(j);
+			 // Prepare the new Global and Local Subrs Indices
+			BuildNewLGSubrs(j);
+			// Build the new file 
+			byte[] Ret = BuildNewFile(j);
+			return Ret;
+		}
+		finally {
+            try {
+                buf.close();
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }
+		}
+	}
+
+	/**
+	 * Function calcs bias according to the CharString type and the count
+	 * of the subrs
+	 * @param Offset The offset to the relevent subrs index
+	 * @param Font the font
+	 * @return The calculated Bias
+	 */
+	protected int CalcBias(int Offset,int Font)
+	{
+		seek(Offset);
+		int nSubrs = getCard16();
+		// If type==1 -> bias=0 
+		if (fonts[Font].CharstringType == 1)
+			return 0;
+		// else calc according to the count
+		else if (nSubrs < 1240)
+			return 107;
+		else if (nSubrs < 33900)
+			return 1131;
+		else
+			return 32768;
+	}
+
+	/**
+	 *Function uses BuildNewIndex to create the new index of the subset charstrings
+	 * @param FontIndex the font
+	 * @throws IOException
+	 */
+	protected void BuildNewCharString(int FontIndex) throws IOException 
+	{
+		NewCharStringsIndex = BuildNewIndex(fonts[FontIndex].charstringsOffsets,GlyphsUsed);
+	}
+	
+	/**
+	 * Function builds the new local & global subsrs indices. IF CID then All of 
+	 * the FD Array lsubrs will be subsetted. 
+	 * @param Font the font
+	 * @throws IOException
+	 */
+	protected void BuildNewLGSubrs(int Font)throws IOException
+	{
+		// If the font is CID then the lsubrs are divided into FontDicts.
+		// for each FD array the lsubrs will be subsetted.
+		if(fonts[Font].isCID)
+		{
+			// Init the hasmap-array and the arraylist-array to hold the subrs used
+			// in each private dict.
+			hSubrsUsed = new HashMap[fonts[Font].fdprivateOffsets.length];
+			lSubrsUsed = new ArrayList[fonts[Font].fdprivateOffsets.length];
+			// A [][] which will store the byte array for each new FD Array lsubs index
+			NewLSubrsIndex = new byte[fonts[Font].fdprivateOffsets.length][];
+			// An array to hold the offset for each Lsubr index 
+			fonts[Font].PrivateSubrsOffset = new int[fonts[Font].fdprivateOffsets.length];
+			// A [][] which will store the offset array for each lsubr index			
+			fonts[Font].PrivateSubrsOffsetsArray = new int[fonts[Font].fdprivateOffsets.length][];
+			
+			// Put the FDarrayUsed into a list
+			ArrayList FDInList = new ArrayList(FDArrayUsed.keySet());
+			// For each FD array which is used subset the lsubr 
+			for (int j=0;j<FDInList.size();j++)
+			{
+				// The FDArray index, Hash Map, Arrat List to work on
+				int FD = ((Integer)FDInList.get(j)).intValue();
+				hSubrsUsed[FD] = new HashMap();
+				lSubrsUsed[FD] = new ArrayList();
+				//Reads the private dicts looking for the subr operator and 
+				// store both the offest for the index and its offset array
+				BuildFDSubrsOffsets(Font,FD);
+				// Verify that FDPrivate has a LSubrs index
+				if(fonts[Font].PrivateSubrsOffset[FD]>=0)
+				{
+					//Scans the Charsting data storing the used Local and Global subroutines 
+					// by the glyphs. Scans the Subrs recursivley. 
+					BuildSubrUsed(Font,FD,fonts[Font].PrivateSubrsOffset[FD],fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD],lSubrsUsed[FD]);
+					// Builds the New Local Subrs index
+					NewLSubrsIndex[FD] = BuildNewIndex(fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD]);
+				}
+			}
+		}
+		// If the font is not CID && the Private Subr exists then subset:
+		else if (fonts[Font].privateSubrs>=0)
+		{
+			// Build the subrs offsets;
+			fonts[Font].SubrsOffsets = getIndex(fonts[Font].privateSubrs);
+			//Scans the Charsting data storing the used Local and Global subroutines 
+			// by the glyphs. Scans the Subrs recursivley.
+			BuildSubrUsed(Font,-1,fonts[Font].privateSubrs,fonts[Font].SubrsOffsets,hSubrsUsedNonCID,lSubrsUsedNonCID);
+		}
+		// For all fonts susbset the Global Subroutines
+		// Scan the Global Subr Hashmap recursivly on the Gsubrs
+		BuildGSubrsUsed(Font);
+		if (fonts[Font].privateSubrs>=0)
+			// Builds the New Local Subrs index
+			NewSubrsIndexNonCID = BuildNewIndex(fonts[Font].SubrsOffsets,hSubrsUsedNonCID);
+		//Builds the New Global Subrs index
+		NewGSubrsIndex = BuildNewIndex(gsubrOffsets,hGSubrsUsed);
+	}
+
+	/**
+	 * The function finds for the FD array processed the local subr offset and its 
+	 * offset array.  
+	 * @param Font the font
+	 * @param FD The FDARRAY processed
+	 */
+	protected void BuildFDSubrsOffsets(int Font,int FD)
+	{
+		// Initiate to -1 to indicate lsubr operator present
+		fonts[Font].PrivateSubrsOffset[FD] = -1;
+		// Goto begining of objects
+        seek(fonts[Font].fdprivateOffsets[FD]);
+        // While in the same object:
+        while (getPosition() < fonts[Font].fdprivateOffsets[FD]+fonts[Font].fdprivateLengths[FD])
+        {
+        	getDictItem();
+        	// If the dictItem is the "Subrs" then find and store offset, 
+        	if (key=="Subrs")
+        		fonts[Font].PrivateSubrsOffset[FD] = ((Integer)args[0]).intValue()+fonts[Font].fdprivateOffsets[FD];
+        }
+        //Read the lsub index if the lsubr was found
+        if (fonts[Font].PrivateSubrsOffset[FD] >= 0)
+        	fonts[Font].PrivateSubrsOffsetsArray[FD] = getIndex(fonts[Font].PrivateSubrsOffset[FD]); 
+	}
+
+	/**
+	 * Function uses ReadAsubr on the glyph used to build the LSubr & Gsubr HashMap.
+	 * The HashMap (of the lsub only) is then scaned recursivly for Lsubr & Gsubrs
+	 * calls.  
+	 * @param Font the font
+	 * @param FD FD array processed. 0 indicates function was called by non CID font
+	 * @param SubrOffset the offset to the subr index to calc the bias
+	 * @param SubrsOffsets the offset array of the subr index
+	 * @param hSubr HashMap of the subrs used
+	 * @param lSubr ArrayList of the subrs used
+	 */
+	protected void BuildSubrUsed(int Font,int FD,int SubrOffset,int[] SubrsOffsets,HashMap hSubr,ArrayList lSubr)
+	{
+
+		// Calc the Bias for the subr index
+		int LBias = CalcBias(SubrOffset,Font);
+		
+		// For each glyph used find its GID, start & end pos
+		for (int i=0;i<glyphsInList.size();i++)
+		{
+			int glyph = ((Integer)glyphsInList.get(i)).intValue();
+			int Start = fonts[Font].charstringsOffsets[glyph];
+			int End = fonts[Font].charstringsOffsets[glyph+1];
+			
+			// IF CID:
+			if (FD >= 0)
+			{
+				EmptyStack();
+				NumOfHints=0;
+				// Using FDSELECT find the FD Array the glyph belongs to.
+				int GlyphFD = fonts[Font].FDSelect[glyph];
+				// If the Glyph is part of the FD being processed 
+				if (GlyphFD == FD)
+					// Find the Subrs called by the glyph and insert to hash:
+					ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+			}
+			else
+				// If the font is not CID 
+				//Find the Subrs called by the glyph and insert to hash:
+				ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+		}
+		// For all Lsubrs used, check recusrivly for Lsubr & Gsubr used
+		for (int i=0;i<lSubr.size();i++)
+		{
+			// Pop the subr value from the hash
+			int Subr = ((Integer)lSubr.get(i)).intValue();
+			// Ensure the Lsubr call is valid
+			if (Subr < SubrsOffsets.length-1 && Subr>=0)
+			{
+				// Read and process the subr
+				int Start = SubrsOffsets[Subr];
+				int End = SubrsOffsets[Subr+1];
+				ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+			}
+		}
+	}
+	
+	/**
+	 * Function scans the Glsubr used ArrayList to find recursive calls 
+	 * to Gsubrs and adds to Hashmap & ArrayList
+	 * @param Font the font
+	 */
+	protected void BuildGSubrsUsed(int Font)
+	{
+		int LBias = 0;
+		int SizeOfNonCIDSubrsUsed = 0;
+		if (fonts[Font].privateSubrs>=0)
+		{
+			LBias = CalcBias(fonts[Font].privateSubrs,Font);
+			SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
+		}
+		
+		// For each global subr used 
+		for (int i=0;i<lGSubrsUsed.size();i++)
+		{
+			//Pop the value + check valid 
+			int Subr = ((Integer)lGSubrsUsed.get(i)).intValue();
+			if (Subr < gsubrOffsets.length-1 && Subr>=0)
+			{
+				// Read the subr and process
+				int Start = gsubrOffsets[Subr];
+				int End = gsubrOffsets[Subr+1];
+				
+				if (fonts[Font].isCID)
+					ReadASubr(Start,End,GBias,0,hGSubrsUsed,lGSubrsUsed,null);
+				else
+				{
+					ReadASubr(Start,End,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
+					if (SizeOfNonCIDSubrsUsed < lSubrsUsedNonCID.size())
+					{
+						for (int j=SizeOfNonCIDSubrsUsed;j<lSubrsUsedNonCID.size();j++)
+						{
+							//Pop the value + check valid 
+							int LSubr = ((Integer)lSubrsUsedNonCID.get(j)).intValue();
+							if (LSubr < fonts[Font].SubrsOffsets.length-1 && LSubr>=0)
+							{
+								// Read the subr and process
+								int LStart = fonts[Font].SubrsOffsets[LSubr];
+								int LEnd = fonts[Font].SubrsOffsets[LSubr+1];
+								ReadASubr(LStart,LEnd,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
+							}
+						}
+						SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * The function reads a subrs (glyph info) between begin and end.
+	 * Adds calls to a Lsubr to the hSubr and lSubrs.
+	 * Adds calls to a Gsubr to the hGSubr and lGSubrs.
+	 * @param begin the start point of the subr
+	 * @param end the end point of the subr
+	 * @param GBias the bias of the Global Subrs
+	 * @param LBias the bias of the Local Subrs
+	 * @param hSubr the HashMap for the lSubrs
+	 * @param lSubr the ArrayList for the lSubrs
+	 */
+	protected void ReadASubr(int begin,int end,int GBias,int LBias,HashMap hSubr,ArrayList lSubr,int[] LSubrsOffsets)
+	{
+		// Clear the stack for the subrs
+		EmptyStack();
+		NumOfHints = 0;
+		// Goto begining of the subr
+        seek(begin);
+        while (getPosition() < end)
+        {
+        	// Read the next command
+        	ReadCommand();
+        	int pos = getPosition();
+        	Object TopElement=null;
+        	if (arg_count > 0)
+        		TopElement = args[arg_count-1];
+        	int NumOfArgs = arg_count;
+        	// Check the modification needed on the Argument Stack according to key;
+        	HandelStack();
+        	// a call to a Lsubr
+        	if (key=="callsubr") 
+        	{
+        		// Verify that arguments are passed 
+        		if (NumOfArgs > 0)
+        		{
+            		// Calc the index of the Subrs
+            		int Subr = ((Integer)TopElement).intValue() + LBias;
+            		// If the subr isn't in the HashMap -> Put in
+        			if (!hSubr.containsKey(new Integer (Subr)))
+            		{
+            			hSubr.put(new Integer(Subr),null);
+            			lSubr.add(new Integer(Subr));
+            		}
+        			CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+        			seek(pos);
+        		}        		
+        	}
+        	// a call to a Gsubr
+        	else if (key=="callgsubr")
+        	{
+        		// Verify that arguments are passed 
+        		if (NumOfArgs > 0)
+        		{
+	        		// Calc the index of the Subrs
+	        		int Subr = ((Integer)TopElement).intValue() + GBias;
+	        		// If the subr isn't in the HashMap -> Put in
+	        		if (!hGSubrsUsed.containsKey(new Integer (Subr)))
+	        		{
+	        			hGSubrsUsed.put(new Integer(Subr),null);
+	        			lGSubrsUsed.add(new Integer(Subr));
+	        		}
+	        		CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+	        		seek(pos);
+        		}
+        	}
+        	// A call to "stem"
+        	else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
+        		// Increment the NumOfHints by the number couples of of arguments
+        		NumOfHints += NumOfArgs/2;
+        	// A call to "mask"
+        	else if (key == "hintmask" || key == "cntrmask")
+        	{
+        		// Compute the size of the mask
+        		int SizeOfMask = NumOfHints/8;
+        		if (NumOfHints%8 != 0 || SizeOfMask == 0)
+        			SizeOfMask++;
+        		// Continue the pointer in SizeOfMask steps
+        		for (int i=0;i<SizeOfMask;i++)
+        			getCard8();
+        	}
+        }
+	}
+
+	/**
+	 * Function Checks how the current operator effects the run time stack after being run 
+	 * An operator may increase or decrease the stack size
+	 */
+	protected void HandelStack()
+	{
+    	// Findout what the operator does to the stack
+    	int StackHandel = StackOpp();
+    	if (StackHandel < 2)
+    	{
+    		// The operators that enlarge the stack by one
+    		if (StackHandel==1)
+    			PushStack();
+    		// The operators that pop the stack
+    		else
+    		{
+    			// Abs value for the for loop
+    			StackHandel *= -1;
+    			for (int i=0;i<StackHandel;i++)
+    				PopStack();
+    		}
+    		
+    	}
+    	// All other flush the stack
+    	else
+    		EmptyStack();		
+	}
+	
+	/**
+	 * Function checks the key and return the change to the stack after the operator
+	 * @return The change in the stack. 2-> flush the stack
+	 */
+	protected int StackOpp()
+	{
+		if (key == "ifelse")
+			return -3;
+		if (key == "roll" || key == "put")
+			return -2;
+		if (key == "callsubr" || key == "callgsubr" || key == "add" || key == "sub" ||
+			key == "div" || key == "mul" || key == "drop" || key == "and" || 
+			key == "or" || key == "eq")
+			return -1;
+		if (key == "abs" || key == "neg" || key == "sqrt" || key == "exch" || 
+			key == "index" || key == "get" || key == "not" || key == "return")
+			return 0;
+		if (key == "random" || key == "dup")
+			return 1;
+		return 2;
+	}
+	
+	/**
+	 * Empty the Type2 Stack
+	 *
+	 */
+	protected void EmptyStack()
+	{
+		// Null the arguments
+    	for (int i=0; i<arg_count; i++) args[i]=null;
+        arg_count = 0;		
+	}
+	
+	/**
+	 * Pop one element from the stack 
+	 *
+	 */
+	protected void PopStack()
+	{
+		if (arg_count>0)
+		{
+			args[arg_count-1]=null;
+			arg_count--;
+		}
+	}
+	
+	/**
+	 * Add an item to the stack
+	 *
+	 */
+	protected void PushStack()
+	{
+		arg_count++;
+	}
+	
+	/**
+	 * The function reads the next command after the file pointer is set
+	 */
+	protected void ReadCommand()
+	{
+        key = null;
+        boolean gotKey = false;
+        // Until a key is found
+        while (!gotKey) {
+        	// Read the first Char
+            char b0 = getCard8();
+            // decode according to the type1/type2 format
+            if (b0 == 28) // the two next bytes represent a short int;
+            {
+            	int first = getCard8();
+            	int second = getCard8();
+            	args[arg_count] = new Integer(first<<8 | second);
+            	arg_count++;
+            	continue;
+            }
+            if (b0 >= 32 && b0 <= 246) // The byte read is the byte;
+            {
+            	args[arg_count] = new Integer(b0 - 139);
+            	arg_count++;
+            	continue;
+            }
+            if (b0 >= 247 && b0 <= 250) // The byte read and the next byte constetute a short int
+            {
+            	int w = getCard8();
+            	args[arg_count] = new Integer((b0-247)*256 + w + 108);
+            	arg_count++;
+            	continue;
+            }
+            if (b0 >= 251 && b0 <= 254)// Same as above except negative
+            {
+            	int w = getCard8();
+            	args[arg_count] = new Integer(-(b0-251)*256 - w - 108);
+            	arg_count++;
+            	continue;
+            }
+            if (b0 == 255)// The next for bytes represent a double.
+            {
+            	int first = getCard8();
+            	int second = getCard8();
+            	int third = getCard8();
+            	int fourth = getCard8();
+            	args[arg_count] = new Integer(first<<24 | second<<16 | third<<8 | fourth);
+            	arg_count++;
+            	continue;
+            }
+            if (b0<=31 && b0 != 28) // An operator was found.. Set Key.
+            {
+            	gotKey=true;
+            	// 12 is an escape command therefor the next byte is a part
+            	// of this command
+            	if (b0 == 12)
+            	{
+            		int b1 = getCard8();
+            		if (b1>SubrsEscapeFuncs.length-1)
+            			b1 = SubrsEscapeFuncs.length-1;
+            		key = SubrsEscapeFuncs[b1];
+            	}
+            	else
+            		key = SubrsFunctions[b0];
+                continue;
+            }
+        }		
+	}
+	
+	/**
+	 * The function reads the subroutine and returns the number of the hint in it.
+	 * If a call to another subroutine is found the function calls recursively.
+	 * @param begin the start point of the subr
+	 * @param end the end point of the subr
+	 * @param LBias the bias of the Local Subrs
+	 * @param GBias the bias of the Global Subrs
+	 * @param LSubrsOffsets The Offsets array of the subroutines
+	 * @return The number of hints in the subroutine read.
+	 */
+	protected int CalcHints(int begin,int end,int LBias,int GBias,int[] LSubrsOffsets)
+	{
+		// Goto begining of the subr
+        seek(begin);
+        while (getPosition() < end)
+        {
+        	// Read the next command
+        	ReadCommand();
+        	int pos = getPosition();
+        	Object TopElement = null;
+        	if (arg_count>0)
+        		TopElement = args[arg_count-1];
+        	int NumOfArgs = arg_count;
+            //Check the modification needed on the Argument Stack according to key;
+        	HandelStack();
+        	// a call to a Lsubr
+        	if (key=="callsubr") 
+        	{
+        		if (NumOfArgs>0)
+        		{
+            		int Subr = ((Integer)TopElement).intValue() + LBias;
+            		CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+            		seek(pos);        			
+        		}
+        	}
+        	// a call to a Gsubr
+        	else if (key=="callgsubr")
+        	{
+        		if (NumOfArgs>0)
+        		{
+            		int Subr = ((Integer)TopElement).intValue() + GBias;
+            		CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+            		seek(pos);        			
+        		}
+        	}
+        	// A call to "stem"
+        	else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
+        		// Increment the NumOfHints by the number couples of of arguments
+        		NumOfHints += NumOfArgs/2;
+        	// A call to "mask"
+        	else if (key == "hintmask" || key == "cntrmask")
+        	{
+        		// Compute the size of the mask
+        		int SizeOfMask = NumOfHints/8;
+        		if (NumOfHints%8 != 0 || SizeOfMask == 0)
+        			SizeOfMask++;
+        		// Continue the pointer in SizeOfMask steps
+        		for (int i=0;i<SizeOfMask;i++)
+        			getCard8();
+        	}
+        }
+        return NumOfHints;
+	}
+
+
+	/**
+	 * Function builds the new offset array, object array and assembles the index.
+	 * used for creating the glyph and subrs subsetted index 
+	 * @param Offsets the offset array of the original index  
+	 * @param Used the hashmap of the used objects
+	 * @return the new index subset version 
+	 * @throws IOException
+	 */
+	protected byte[] BuildNewIndex(int[] Offsets,HashMap Used) throws IOException 
+	{
+		int Offset=0;
+		int[] NewOffsets = new int[Offsets.length];
+		// Build the Offsets Array for the Subset
+		for (int i=0;i<Offsets.length;++i)
+		{
+			NewOffsets[i] = Offset;
+			// If the object in the offset is also present in the used
+			// HashMap then increment the offset var by its size
+			if (Used.containsKey(new Integer(i)))
+				Offset += Offsets[i+1] - Offsets[i];
+				// Else the same offset is kept in i+1.
+		}
+		// Offset var determines the size of the object array
+		byte[] NewObjects = new byte[Offset];
+		// Build the new Object array
+		for (int i=0;i<Offsets.length-1;++i)
+		{
+			int start = NewOffsets[i];
+			int end = NewOffsets[i+1];
+			// If start != End then the Object is used
+			// So, we will copy the object data from the font file
+			if (start != end)
+			{
+				// All offsets are Global Offsets relative to the begining of the font file.
+				// Jump the file pointer to the start address to read from.
+				buf.seek(Offsets[i]);
+				// Read from the buffer and write into the array at start.  
+                buf.readFully(NewObjects, start, end-start);
+			}
+		}
+		// Use AssembleIndex to build the index from the offset & object arrays
+		return AssembleIndex(NewOffsets,NewObjects);
+	}
+
+	/**
+	 * Function creates the new index, inserting the count,offsetsize,offset array
+	 * and object array.
+	 * @param NewOffsets the subsetted offset array
+	 * @param NewObjects the subsetted object array
+	 * @return the new index created
+	 */
+	protected byte[] AssembleIndex(int[] NewOffsets,byte[] NewObjects)
+	{
+		// Calc the index' count field
+		char Count = (char)(NewOffsets.length-1);
+		// Calc the size of the object array
+		int Size = NewOffsets[NewOffsets.length-1];
+		// Calc the Offsize
+		byte Offsize;
+        if (Size <= 0xff) Offsize = 1;
+        else if (Size <= 0xffff) Offsize = 2;
+        else if (Size <= 0xffffff) Offsize = 3;
+        else Offsize = 4;
+        // The byte array for the new index. The size is calc by
+        // Count=2, Offsize=1, OffsetArray = Offsize*(Count+1), The object array
+        byte[] NewIndex = new byte[2+1+Offsize*(Count+1)+NewObjects.length];
+        // The counter for writing
+        int Place = 0;
+        // Write the count field
+        NewIndex[Place++] = (byte) ((Count >>> 8) & 0xff);
+        NewIndex[Place++] = (byte) ((Count >>> 0) & 0xff);
+        // Write the offsize field
+        NewIndex[Place++] = Offsize;
+        // Write the offset array according to the offsize
+        for (int i=0;i<NewOffsets.length;i++)
+        {
+        	// The value to be written
+        	int Num = NewOffsets[i]-NewOffsets[0]+1;
+        	// Write in bytes according to the offsize
+        	switch (Offsize) {
+                case 4:
+                	NewIndex[Place++] = (byte) ((Num >>> 24) & 0xff);
+                case 3:
+                	NewIndex[Place++] = (byte) ((Num >>> 16) & 0xff);
+                case 2:
+                	NewIndex[Place++] = (byte) ((Num >>>  8) & 0xff);
+                case 1:
+                	NewIndex[Place++] = (byte) ((Num >>>  0) & 0xff);
+        	}                	
+        }
+        // Write the new object array one by one
+        for (int i=0;i<NewObjects.length;i++)
+        {
+        	NewIndex[Place++] = NewObjects[i];
+        }
+        // Return the new index
+        return NewIndex;
+	}
+	
+	/**
+	 * The function builds the new output stream according to the subset process
+	 * @param Font the font
+	 * @return the subseted font stream
+	 * @throws IOException
+	 */
+	protected byte[] BuildNewFile(int Font)throws IOException
+    {
+		// Prepare linked list for new font components
+		OutputList = new LinkedList();
+
+        // copy the header of the font
+        CopyHeader();
+                
+        // create a name index
+        BuildIndexHeader(1,1,1);
+        OutputList.addLast(new UInt8Item((char)( 1+fonts[Font].name.length() )));
+        OutputList.addLast(new StringItem(fonts[Font].name));
+        
+        // create the topdict Index
+        BuildIndexHeader(1,2,1);
+        OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
+        OutputList.addLast(topdictIndex1Ref);
+        IndexBaseItem topdictBase = new IndexBaseItem();
+        OutputList.addLast(topdictBase);
+                
+        // Initialise the Dict Items for later use
+        OffsetItem charsetRef     = new DictOffsetItem();
+        OffsetItem charstringsRef = new DictOffsetItem();
+        OffsetItem fdarrayRef     = new DictOffsetItem();
+        OffsetItem fdselectRef    = new DictOffsetItem();
+        OffsetItem privateRef     = new DictOffsetItem();
+        
+        // If the font is not CID create the following keys
+        if ( !fonts[Font].isCID ) {
+            // create a ROS key
+        	OutputList.addLast(new DictNumberItem(fonts[Font].nstrings));
+        	OutputList.addLast(new DictNumberItem(fonts[Font].nstrings+1));
+        	OutputList.addLast(new DictNumberItem(0));
+        	OutputList.addLast(new UInt8Item((char)12));
+        	OutputList.addLast(new UInt8Item((char)30));
+            // create a CIDCount key
+        	OutputList.addLast(new DictNumberItem(fonts[Font].nglyphs));
+        	OutputList.addLast(new UInt8Item((char)12));
+            OutputList.addLast(new UInt8Item((char)34));
+            // Sivan's comments
+            // What about UIDBase (12,35)? Don't know what is it.
+            // I don't think we need FontName; the font I looked at didn't have it.
+        }
+        // Go to the TopDict of the font being processed
+        seek(topdictOffsets[Font]);
+        // Run untill the end of the TopDict
+        while (getPosition() < topdictOffsets[Font+1]) {
+            int p1 = getPosition();
+            getDictItem();
+            int p2 = getPosition();
+            // The encoding key is disregarded since CID has no encoding
+            if (key=="Encoding"
+            // These keys will be added manualy by the process.
+            || key=="Private" 
+            || key=="FDSelect"
+            || key=="FDArray" 
+            || key=="charset" 
+            || key=="CharStrings"
+            ) {
+            }else {
+            //OtherWise copy key "as is" to the output list
+                OutputList.add(new RangeItem(buf,p1,p2-p1));
+            }
+        }
+        // Create the FDArray, FDSelect, Charset and CharStrings Keys
+        CreateKeys(fdarrayRef,fdselectRef,charsetRef,charstringsRef);
+        
+        // Mark the end of the top dict area
+        OutputList.addLast(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
+        
+        // Copy the string index
+
+        if (fonts[Font].isCID) 
+            OutputList.addLast(getEntireIndexRange(stringIndexOffset));
+        // If the font is not CID we need to append new strings.
+        // We need 3 more strings: Registry, Ordering, and a FontName for one FD.
+        // The total length is at most "Adobe"+"Identity"+63 = 76
+        else
+        	CreateNewStringIndex(Font);
+        
+        // copy the new subsetted global subroutine index       
+        OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewGSubrsIndex),0,NewGSubrsIndex.length));
+        
+        // deal with fdarray, fdselect, and the font descriptors
+        // If the font is CID:
+        if (fonts[Font].isCID) {
+            // copy the FDArray, FDSelect, charset
+       
+            // Copy FDSelect
+        	// Mark the beginning
+            OutputList.addLast(new MarkerItem(fdselectRef));
+            // If an FDSelect exists copy it
+            if (fonts[Font].fdselectOffset>=0)
+        		OutputList.addLast(new RangeItem(buf,fonts[Font].fdselectOffset,fonts[Font].FDSelectLength));
+            // Else create a new one
+            else
+            	CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
+            	           
+          	// Copy the Charset
+            // Mark the beginning and copy entirly 
+            OutputList.addLast(new MarkerItem(charsetRef));
+            OutputList.addLast(new RangeItem(buf,fonts[Font].charsetOffset,fonts[Font].CharsetLength));
+            
+            // Copy the FDArray
+            // If an FDArray exists
+            if (fonts[Font].fdarrayOffset>=0)
+            {
+                // Mark the beginning
+	            OutputList.addLast(new MarkerItem(fdarrayRef));
+	            // Build a new FDArray with its private dicts and their LSubrs
+	            Reconstruct(Font);
+            }
+            else
+            	// Else create a new one
+            	CreateFDArray(fdarrayRef,privateRef,Font);
+           
+        }
+        // If the font is not CID
+        else 
+        {
+            // create FDSelect
+        	CreateFDSelect(fdselectRef,fonts[Font].nglyphs);            
+            // recreate a new charset
+        	CreateCharset(charsetRef,fonts[Font].nglyphs);            
+            // create a font dict index (fdarray)
+        	CreateFDArray(fdarrayRef,privateRef,Font);            
+        }
+        
+        // if a private dict exists insert its subsetted version
+        if (fonts[Font].privateOffset>=0)
+        {
+        	// Mark the beginning of the private dict
+        	IndexBaseItem PrivateBase = new IndexBaseItem();
+	        OutputList.addLast(PrivateBase);
+        	OutputList.addLast(new MarkerItem(privateRef));
+
+        	OffsetItem Subr = new DictOffsetItem();
+        	// Build and copy the new private dict
+        	CreateNonCIDPrivate(Font,Subr);
+        	// Copy the new LSubrs index
+        	CreateNonCIDSubrs(Font,PrivateBase,Subr);
+        }
+        
+        // copy the charstring index
+        OutputList.addLast(new MarkerItem(charstringsRef));
+
+        // Add the subsetted charstring
+        OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewCharStringsIndex),0,NewCharStringsIndex.length));
+        
+        // now create the new CFF font        
+        int[] currentOffset = new int[1];
+        currentOffset[0] = 0;
+        // Count and save the offset for each item
+        Iterator listIter = OutputList.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.increment(currentOffset);
+        }
+        // Compute the Xref for each of the offset items
+        listIter = OutputList.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.xref();
+        }
+        
+        int size = currentOffset[0];
+        byte[] b = new byte[size];
+        
+        // Emit all the items into the new byte array
+        listIter = OutputList.iterator();
+        while ( listIter.hasNext() ) {
+            Item item = (Item) listIter.next();
+            item.emit(b);
+        }
+        // Return the new stream
+        return b;
+    }
+
+	/**
+	 * Function Copies the header from the original fileto the output list
+	 */
+	protected void CopyHeader()
+	{
+		seek(0);
+        int major = getCard8();
+        int minor = getCard8();
+        int hdrSize = getCard8();
+        int offSize = getCard8();
+        nextIndexOffset = hdrSize;
+        OutputList.addLast(new RangeItem(buf,0,hdrSize));
+	}
+
+	/**
+	 * Function Build the header of an index
+	 * @param Count the count field of the index
+	 * @param Offsize the offsize field of the index
+	 * @param First the first offset of the index
+	 */
+	protected void BuildIndexHeader(int Count,int Offsize,int First)
+	{
+		// Add the count field
+		OutputList.addLast(new UInt16Item((char)Count)); // count
+		// Add the offsize field
+		OutputList.addLast(new UInt8Item((char)Offsize)); // offSize
+		// Add the first offset according to the offsize
+        switch(Offsize){
+        	case 1:
+        		OutputList.addLast(new UInt8Item((char)First)); // first offset
+        		break;
+        	case 2:
+        		OutputList.addLast(new UInt16Item((char)First)); // first offset
+        		break;
+        	case 3:
+        		OutputList.addLast(new UInt24Item((char)First)); // first offset
+        		break;
+        	case 4:
+        		OutputList.addLast(new UInt32Item((char)First)); // first offset
+        		break;
+    		default:
+    			break;	
+        }
+	}
+	
+	/**
+	 * Function adds the keys into the TopDict
+	 * @param fdarrayRef OffsetItem for the FDArray
+	 * @param fdselectRef OffsetItem for the FDSelect
+	 * @param charsetRef OffsetItem for the CharSet
+	 * @param charstringsRef OffsetItem for the CharString
+	 */
+	protected void CreateKeys(OffsetItem fdarrayRef,OffsetItem fdselectRef,OffsetItem charsetRef,OffsetItem charstringsRef)
+	{
+	    // create an FDArray key
+        OutputList.addLast(fdarrayRef);
+        OutputList.addLast(new UInt8Item((char)12));
+        OutputList.addLast(new UInt8Item((char)36));
+        // create an FDSelect key
+        OutputList.addLast(fdselectRef);
+        OutputList.addLast(new UInt8Item((char)12));
+        OutputList.addLast(new UInt8Item((char)37));
+        // create an charset key
+        OutputList.addLast(charsetRef);
+        OutputList.addLast(new UInt8Item((char)15));
+        // create a CharStrings key
+        OutputList.addLast(charstringsRef);
+        OutputList.addLast(new UInt8Item((char)17));
+	}
+	
+	/**
+	 * Function takes the original string item and adds the new strings
+	 * to accomodate the CID rules
+	 * @param Font the font
+	 */
+	protected void CreateNewStringIndex(int Font)
+	{
+        String fdFontName = fonts[Font].name+"-OneRange";
+        if (fdFontName.length() > 127)
+            fdFontName = fdFontName.substring(0,127);
+        String extraStrings = "Adobe"+"Identity"+fdFontName;
+        
+        int origStringsLen = stringOffsets[stringOffsets.length-1]
+        - stringOffsets[0];
+        int stringsBaseOffset = stringOffsets[0]-1;
+        
+        byte stringsIndexOffSize;
+        if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
+        else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
+        else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
+        else stringsIndexOffSize = 4;
+        
+        OutputList.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
+        OutputList.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
+        for (int i=0; i<stringOffsets.length; i++)
+            OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
+            stringOffsets[i]-stringsBaseOffset));
+        int currentStringsOffset = stringOffsets[stringOffsets.length-1]
+        - stringsBaseOffset;
+        //l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+        currentStringsOffset += ("Adobe").length();
+        OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+        currentStringsOffset += ("Identity").length();
+        OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+        currentStringsOffset += fdFontName.length();
+        OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
+        
+        OutputList.addLast(new RangeItem(buf,stringOffsets[0],origStringsLen));
+        OutputList.addLast(new StringItem(extraStrings));
+    }
+     
+	/**
+	 * Function creates new FDSelect for non-CID fonts.
+	 * The FDSelect built uses a single range for all glyphs
+	 * @param fdselectRef OffsetItem for the FDSelect
+	 * @param nglyphs the number of glyphs in the font
+	 */
+	protected void CreateFDSelect(OffsetItem fdselectRef,int nglyphs)
+	{
+		OutputList.addLast(new MarkerItem(fdselectRef));
+	    OutputList.addLast(new UInt8Item((char)3)); // format identifier
+	    OutputList.addLast(new UInt16Item((char)1)); // nRanges
+	    
+	    OutputList.addLast(new UInt16Item((char)0)); // Range[0].firstGlyph
+	    OutputList.addLast(new UInt8Item((char)0)); // Range[0].fd
+	    
+	    OutputList.addLast(new UInt16Item((char)nglyphs)); // sentinel
+	}
+
+	/**
+	 * Function creates new CharSet for non-CID fonts.
+	 * The CharSet built uses a single range for all glyphs
+	 * @param charsetRef OffsetItem for the CharSet
+	 * @param nglyphs the number of glyphs in the font
+	 */
+	protected void CreateCharset(OffsetItem charsetRef,int nglyphs)
+	{
+		OutputList.addLast(new MarkerItem(charsetRef));
+	    OutputList.addLast(new UInt8Item((char)2)); // format identifier
+	    OutputList.addLast(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
+	    OutputList.addLast(new UInt16Item((char)(nglyphs-1))); // nLeft
+	}
+    
+	/**
+	 * Function creates new FDArray for non-CID fonts.
+	 * The FDArray built has only the "Private" operator that points to the font's
+	 * original private dict 
+	 * @param fdarrayRef OffsetItem for the FDArray
+	 * @param privateRef OffsetItem for the Private Dict
+	 * @param Font the font
+	 */
+	protected void CreateFDArray(OffsetItem fdarrayRef,OffsetItem privateRef,int Font)
+	{
+		OutputList.addLast(new MarkerItem(fdarrayRef));
+		// Build the header (count=offsize=first=1)
+		BuildIndexHeader(1,1,1);
+	    
+		// Mark
+	    OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
+	    OutputList.addLast(privateIndex1Ref);
+	    IndexBaseItem privateBase = new IndexBaseItem();
+	    // Insert the private operands and operator
+	    OutputList.addLast(privateBase);
+	    // Calc the new size of the private after subsetting
+	    // Origianl size
+	    int NewSize = fonts[Font].privateLength;
+	    // Calc the original size of the Subr offset in the private
+		int OrgSubrsOffsetSize = CalcSubrOffsetSize(fonts[Font].privateOffset,fonts[Font].privateLength);
+		// Increase the ptivate's size
+		if (OrgSubrsOffsetSize != 0)
+			NewSize += 5-OrgSubrsOffsetSize;
+	    OutputList.addLast(new DictNumberItem(NewSize));
+	    OutputList.addLast(privateRef);
+	    OutputList.addLast(new UInt8Item((char)18)); // Private
+	    
+	    OutputList.addLast(new IndexMarkerItem(privateIndex1Ref,privateBase));
+	}
+    
+	/**
+	 * Function reconstructs the FDArray, PrivateDict and LSubr for CID fonts
+	 * @param Font the font
+	 * @throws IOException
+	 */
+	void Reconstruct(int Font)throws IOException
+	{
+		// Init for later use
+		OffsetItem[] fdPrivate = new DictOffsetItem[fonts[Font].FDArrayOffsets.length-1];
+		IndexBaseItem[] fdPrivateBase = new IndexBaseItem[fonts[Font].fdprivateOffsets.length]; 
+		OffsetItem[] fdSubrs = new DictOffsetItem[fonts[Font].fdprivateOffsets.length];
+		// Reconstruct each type
+		ReconstructFDArray(Font,fdPrivate);
+		ReconstructPrivateDict(Font,fdPrivate,fdPrivateBase,fdSubrs);
+		ReconstructPrivateSubrs(Font,fdPrivateBase,fdSubrs);
+	}
+
+	/**
+	 * Function subsets the FDArray and builds the new one with new offsets
+	 * @param Font The font
+	 * @param fdPrivate OffsetItem Array (one for each FDArray)
+	 * @throws IOException
+	 */
+	void ReconstructFDArray(int Font,OffsetItem[] fdPrivate)throws IOException
+	{
+		// Build the header of the index
+		BuildIndexHeader(fonts[Font].FDArrayCount,fonts[Font].FDArrayOffsize,1);
+
+		// For each offset create an Offset Item
+		OffsetItem[] fdOffsets = new IndexOffsetItem[fonts[Font].FDArrayOffsets.length-1];
+		for (int i=0;i<fonts[Font].FDArrayOffsets.length-1;i++)
+		{
+			fdOffsets[i] = new IndexOffsetItem(fonts[Font].FDArrayOffsize);
+			OutputList.addLast(fdOffsets[i]);
+		}
+		
+		// Declare beginning of the object array
+		IndexBaseItem fdArrayBase = new IndexBaseItem();
+	    OutputList.addLast(fdArrayBase);
+	    
+		// For each object check if that FD is used.
+	    // if is used build a new one by changing the private object
+	    // Else do nothing
+	    // At the end of each object mark its ending (Even if wasn't written)
+		for (int k=0; k<fonts[Font].FDArrayOffsets.length-1; k++) {
+			if (FDArrayUsed.containsKey(new Integer (k)))
+			{
+				// Goto begining of objects
+	            seek(fonts[Font].FDArrayOffsets[k]);
+	            while (getPosition() < fonts[Font].FDArrayOffsets[k+1])
+	            {
+	            	int p1 = getPosition();
+	            	getDictItem();
+	            	int p2 = getPosition();
+	            	// If the dictItem is the "Private" then compute and copy length, 
+	            	// use marker for offset and write operator number
+	            	if (key=="Private") {
+	            		// Save the original length of the private dict
+	            		int NewSize = ((Integer)args[0]).intValue();
+	            		// Save the size of the offset to the subrs in that private
+	            		int OrgSubrsOffsetSize = CalcSubrOffsetSize(fonts[Font].fdprivateOffsets[k],fonts[Font].fdprivateLengths[k]);
+	            		// Increase the private's length accordingly
+	            		if (OrgSubrsOffsetSize != 0)
+	            			NewSize += 5-OrgSubrsOffsetSize;
+	            		// Insert the new size, OffsetItem and operator key number
+	            		OutputList.addLast(new DictNumberItem(NewSize));
+	            		fdPrivate[k] = new DictOffsetItem();
+	            		OutputList.addLast(fdPrivate[k]);
+	            	    OutputList.addLast(new UInt8Item((char)18)); // Private
+	            	    // Go back to place 
+	            	    seek(p2);
+	            	}
+	            	// Else copy the entire range
+	            	else  // other than private
+	            		OutputList.addLast(new RangeItem(buf,p1,p2-p1));
+	            }
+			}
+            // Mark the ending of the object (even if wasn't written)
+            OutputList.addLast(new IndexMarkerItem(fdOffsets[k],fdArrayBase));
+        }
+	}
+	/**
+	 * Function Adds the new private dicts (only for the FDs used) to the list
+	 * @param Font the font
+	 * @param fdPrivate OffsetItem array one element for each private
+	 * @param fdPrivateBase IndexBaseItem array one element for each private
+	 * @param fdSubrs OffsetItem array one element for each private
+	 * @throws IOException
+	 */
+	void ReconstructPrivateDict(int Font,OffsetItem[] fdPrivate,IndexBaseItem[] fdPrivateBase,
+			OffsetItem[] fdSubrs)throws IOException
+	{
+		
+		// For each fdarray private dict check if that FD is used.
+	    // if is used build a new one by changing the subrs offset
+	    // Else do nothing
+		for (int i=0;i<fonts[Font].fdprivateOffsets.length;i++)
+		{
+			if (FDArrayUsed.containsKey(new Integer (i)))
+			{
+				// Mark beginning
+		        OutputList.addLast(new MarkerItem(fdPrivate[i]));
+		        fdPrivateBase[i] = new IndexBaseItem();
+		        OutputList.addLast(fdPrivateBase[i]);
+				// Goto begining of objects
+	            seek(fonts[Font].fdprivateOffsets[i]);
+	            while (getPosition() < fonts[Font].fdprivateOffsets[i]+fonts[Font].fdprivateLengths[i])
+	            {
+	            	int p1 = getPosition();
+	            	getDictItem();
+	            	int p2 = getPosition();
+	            	// If the dictItem is the "Subrs" then, 
+	            	// use marker for offset and write operator number
+	            	if (key=="Subrs") {
+	            		fdSubrs[i] = new DictOffsetItem();
+	            		OutputList.addLast(fdSubrs[i]);
+	            	    OutputList.addLast(new UInt8Item((char)19)); // Subrs
+	            	}
+	            	// Else copy the entire range
+	            	else
+	            		OutputList.addLast(new RangeItem(buf,p1,p2-p1));
+	            }
+			}
+		}
+	}
+	
+	/**
+	 * Function Adds the new LSubrs dicts (only for the FDs used) to the list
+	 * @param Font  The index of the font
+	 * @param fdPrivateBase The IndexBaseItem array for the linked list
+	 * @param fdSubrs OffsetItem array for the linked list
+	 * @throws IOException
+	 */
+	
+	void ReconstructPrivateSubrs(int Font,IndexBaseItem[] fdPrivateBase,
+			OffsetItem[] fdSubrs)throws IOException
+	{
+		// For each private dict
+        for (int i=0;i<fonts[Font].fdprivateLengths.length;i++)
+        {
+        	// If that private dict's Subrs are used insert the new LSubrs
+        	// computed earlier
+        	if (fdSubrs[i]!= null && fonts[Font].PrivateSubrsOffset[i] >= 0)
+        	{        		
+        		OutputList.addLast(new SubrMarkerItem(fdSubrs[i],fdPrivateBase[i]));
+        		OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewLSubrsIndex[i]),0,NewLSubrsIndex[i].length));
+        	}
+        }
+    }
+
+	/**
+	 * Calculates how many byte it took to write the offset for the subrs in a specific
+	 * private dict.
+	 * @param Offset The Offset for the private dict
+	 * @param Size The size of the private dict
+	 * @return The size of the offset of the subrs in the private dict
+	 */
+	int CalcSubrOffsetSize(int Offset,int Size)
+	{
+		// Set the size to 0
+		int OffsetSize = 0;
+		// Go to the beginning of the private dict
+		seek(Offset);
+		// Go until the end of the private dict 
+		while (getPosition() < Offset+Size)
+        {
+        	int p1 = getPosition();
+        	getDictItem();
+        	int p2 = getPosition();
+        	// When reached to the subrs offset
+        	if (key=="Subrs") {
+        		// The Offsize (minus the subrs key)
+        		OffsetSize = p2-p1-1;
+        	}
+        	// All other keys are ignored
+        }
+		// return the size
+		return OffsetSize;
+	}
+	
+	/**
+	 * Function computes the size of an index
+	 * @param indexOffset The offset for the computed index
+	 * @return The size of the index
+	 */
+	protected int countEntireIndexRange(int indexOffset) 
+	{
+		// Go to the beginning of the index 
+	    seek(indexOffset);
+	    // Read the count field
+	    int count = getCard16();
+	    // If count==0 -> size=2
+	    if (count==0) 
+	        return 2;
+	    else 
+	    {
+	    	// Read the offsize field
+	        int indexOffSize = getCard8();
+	        // Go to the last element of the offset array
+	        seek(indexOffset+2+1+count*indexOffSize);
+	        // The size of the object array is the value of the last element-1
+	        int size = getOffset(indexOffSize)-1;
+	        // Return the size of the entire index
+	        return 2+1+(count+1)*indexOffSize+size;
+	    }
+	}
+	
+	/**
+	 * The function creates a private dict for a font that was not CID
+	 * All the keys are copied as is except for the subrs key 
+	 * @param Font the font
+	 * @param Subr The OffsetItem for the subrs of the private 
+	 */
+	void CreateNonCIDPrivate(int Font,OffsetItem Subr)
+	{
+		// Go to the beginning of the private dict and read untill the end
+		seek(fonts[Font].privateOffset);
+        while (getPosition() < fonts[Font].privateOffset+fonts[Font].privateLength)
+        {
+        	int p1 = getPosition();
+        	getDictItem();
+        	int p2 = getPosition();
+        	// If the dictItem is the "Subrs" then, 
+        	// use marker for offset and write operator number
+        	if (key=="Subrs") {
+        		OutputList.addLast(Subr);
+        	    OutputList.addLast(new UInt8Item((char)19)); // Subrs
+        	}
+        	// Else copy the entire range
+        	else
+        		OutputList.addLast(new RangeItem(buf,p1,p2-p1));
+        }
+	}
+	
+	/**
+	 * the function marks the beginning of the subrs index and adds the subsetted subrs
+	 * index to the output list. 
+	 * @param Font the font
+	 * @param PrivateBase IndexBaseItem for the private that's referencing to the subrs
+	 * @param Subrs OffsetItem for the subrs
+	 * @throws IOException
+	 */
+	void CreateNonCIDSubrs(int Font,IndexBaseItem PrivateBase,OffsetItem Subrs)throws IOException
+	{
+		// Mark the beginning of the Subrs index
+		OutputList.addLast(new SubrMarkerItem(Subrs,PrivateBase));
+		// Put the subsetted new subrs index
+		OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewSubrsIndexNonCID),0,NewSubrsIndexNonCID.length));
+    }	
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/CJKFont.java b/LibrarySource/com/lowagie/text/pdf/CJKFont.java
new file mode 100644
index 0000000..1f8d335
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/CJKFont.java
@@ -0,0 +1,626 @@
+/*
+ * $Id: CJKFont.java,v 1.29 2002/07/09 11:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.DocumentException;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Enumeration;
+
+/**
+ * Creates a CJK font compatible with the fonts in the Adobe Asian font Pack.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+
+class CJKFont extends BaseFont {
+    /** The encoding used in the PDF document for CJK fonts
+     */
+    static final String CJK_ENCODING = "UnicodeBigUnmarked";
+    private static final int FIRST = 0;
+    private static final int BRACKET = 1;
+    private static final int SERIAL = 2;
+    private static final int V1Y = 880;
+        
+    static Properties cjkFonts = new Properties();
+    static Properties cjkEncodings = new Properties();
+    static Hashtable allCMaps = new Hashtable();
+    static Hashtable allFonts = new Hashtable();
+    private static boolean propertiesLoaded = false;
+    
+    /** The font name */
+    private String fontName;
+    /** The style modifier */
+    private String style = "";
+    /** The CMap name associated with this font */
+    private String CMap;
+    
+    private boolean cidDirect = false;
+    
+    private char[] translationMap;
+    private IntHashtable vMetrics;
+    private IntHashtable hMetrics;
+    private HashMap fontDesc;
+    private boolean vertical = false;
+    
+    private static void loadProperties() {
+        if (propertiesLoaded)
+            return;
+        synchronized (allFonts) {
+            if (propertiesLoaded)
+                return;
+            try {
+                InputStream is = getResourceStream(RESOURCE_PATH + "cjkfonts.properties");
+                cjkFonts.load(is);
+                is.close();
+                is = getResourceStream(RESOURCE_PATH + "cjkencodings.properties");
+                cjkEncodings.load(is);
+                is.close();
+            }
+            catch (Exception e) {
+                cjkFonts = new Properties();
+                cjkEncodings = new Properties();
+            }
+            propertiesLoaded = true;
+        }
+    }
+    
+    /** Creates a CJK font.
+     * @param fontName the name of the font
+     * @param enc the encoding of the font
+     * @param emb always <CODE>false</CODE>. CJK font and not embedded
+     * @throws DocumentException on error
+     * @throws IOException on error
+     */
+    CJKFont(String fontName, String enc, boolean emb) throws DocumentException, IOException {
+        loadProperties();
+        fontType = FONT_TYPE_CJK;
+        String nameBase = getBaseName(fontName);
+        if (!isCJKFont(nameBase, enc))
+            throw new DocumentException("Font '" + fontName + "' with '" + enc + "' encoding is not a CJK font.");
+        if (nameBase.length() < fontName.length()) {
+            style = fontName.substring(nameBase.length());
+            fontName = nameBase;
+        }
+        this.fontName = fontName;
+        encoding = CJK_ENCODING;
+        vertical = enc.endsWith("V");
+        CMap = enc;
+        if (enc.startsWith("Identity-")) {
+            cidDirect = true;
+            String s = cjkFonts.getProperty(fontName);
+            s = s.substring(0, s.indexOf('_'));
+            char c[] = (char[])allCMaps.get(s);
+            if (c == null) {
+                c = readCMap(s);
+                if (c == null)
+                    throw new DocumentException("The cmap " + s + " does not exist as a resource.");
+                c[CID_NEWLINE] = '\n';
+                allCMaps.put(s, c);
+            }
+            translationMap = c;
+        }
+        else {
+            char c[] = (char[])allCMaps.get(enc);
+            if (c == null) {
+                String s = cjkEncodings.getProperty(enc);
+                if (s == null)
+                    throw new DocumentException("The resource cjkencodings.properties does not contain the encoding " + enc);
+                StringTokenizer tk = new StringTokenizer(s);
+                String nt = tk.nextToken();
+                c = (char[])allCMaps.get(nt);
+                if (c == null) {
+                    c = readCMap(nt);
+                    allCMaps.put(nt, c);
+                }
+                if (tk.hasMoreTokens()) {
+                    String nt2 = tk.nextToken();
+                    char m2[] = readCMap(nt2);
+                    for (int k = 0; k < 0x10000; ++k) {
+                        if (m2[k] == 0)
+                            m2[k] = c[k];
+                    }
+                    allCMaps.put(enc, m2);
+                    c = m2;
+                }
+            }
+            translationMap = c;
+        }
+        fontDesc = (HashMap)allFonts.get(fontName);
+        if (fontDesc == null) {
+            fontDesc = readFontProperties(fontName);
+            allFonts.put(fontName, fontDesc);
+        }
+        hMetrics = (IntHashtable)fontDesc.get("W");
+        vMetrics = (IntHashtable)fontDesc.get("W2");
+    }
+    
+    /** Checks if its a valid CJK font.
+     * @param fontName the font name
+     * @param enc the encoding
+     * @return <CODE>true</CODE> if it is CJK font
+     */
+    public static boolean isCJKFont(String fontName, String enc) {
+        loadProperties();
+        String encodings = cjkFonts.getProperty(fontName);
+        return (encodings != null && (enc.equals("Identity-H") || enc.equals("Identity-V") || encodings.indexOf("_" + enc + "_") >= 0));
+    }
+        
+    public int getWidth(String text) {
+        int total = 0;
+        for (int k = 0; k < text.length(); ++k) {
+            int c = text.charAt(k);
+            if (!cidDirect)
+                c = translationMap[c];
+            int v;
+            if (vertical)
+                v = vMetrics.get(c);
+            else
+                v = hMetrics.get(c);
+            if (v > 0)
+                total += v;
+            else
+                total += 1000;
+        }
+        return total;
+    }
+    
+    int getRawWidth(int c, String name) {
+        return 0;
+    }
+  
+    public int getKerning(char char1, char char2) {
+        return 0;
+    }
+
+    private PdfDictionary getFontDescriptor() {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+        dic.put(PdfName.ASCENT, new PdfLiteral((String)fontDesc.get("Ascent")));
+        dic.put(PdfName.CAPHEIGHT, new PdfLiteral((String)fontDesc.get("CapHeight")));
+        dic.put(PdfName.DESCENT, new PdfLiteral((String)fontDesc.get("Descent")));
+        dic.put(PdfName.FLAGS, new PdfLiteral((String)fontDesc.get("Flags")));
+        dic.put(PdfName.FONTBBOX, new PdfLiteral((String)fontDesc.get("FontBBox")));
+        dic.put(PdfName.FONTNAME, new PdfName(fontName + style));
+        dic.put(PdfName.ITALICANGLE, new PdfLiteral((String)fontDesc.get("ItalicAngle")));
+        dic.put(PdfName.STEMV, new PdfLiteral((String)fontDesc.get("StemV")));
+        PdfDictionary pdic = new PdfDictionary();
+        pdic.put(PdfName.PANOSE, new PdfString((String)fontDesc.get("Panose"), null));
+        dic.put(PdfName.STYLE, pdic);
+        return dic;
+    }
+    
+    private PdfDictionary getCIDFont(PdfIndirectReference fontDescriptor, IntHashtable cjkTag) {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+        dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
+        dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
+        dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+        int keys[] = cjkTag.toOrderedKeys();
+        String w = convertToHCIDMetrics(keys, hMetrics);
+        if (w != null)
+            dic.put(PdfName.W, new PdfLiteral(w));
+        if (vertical) {
+            w = convertToVCIDMetrics(keys, vMetrics, hMetrics);;
+            if (w != null)
+                dic.put(PdfName.W2, new PdfLiteral(w));
+        }
+        else
+            dic.put(PdfName.DW, new PdfNumber(1000));
+        PdfDictionary cdic = new PdfDictionary();
+        cdic.put(PdfName.REGISTRY, new PdfString((String)fontDesc.get("Registry"), null));
+        cdic.put(PdfName.ORDERING, new PdfString((String)fontDesc.get("Ordering"), null));
+        cdic.put(PdfName.SUPPLEMENT, new PdfLiteral((String)fontDesc.get("Supplement")));
+        dic.put(PdfName.CIDSYSTEMINFO, cdic);
+        return dic;
+    }
+    
+    private PdfDictionary getFontBaseType(PdfIndirectReference CIDFont) {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+        dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
+        String name = fontName;
+        if (style.length() > 0)
+            name += "-" + style.substring(1);
+        name += "-" + CMap;
+        dic.put(PdfName.BASEFONT, new PdfName(name));
+        dic.put(PdfName.ENCODING, new PdfName(CMap));
+        dic.put(PdfName.DESCENDANTFONTS, new PdfArray(CIDFont));
+        return dic;
+    }
+    
+    void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+        IntHashtable cjkTag = (IntHashtable)params[0];
+        PdfIndirectReference ind_font = null;
+        PdfObject pobj = null;
+        PdfIndirectObject obj = null;
+        pobj = getFontDescriptor();
+        if (pobj != null){
+            obj = writer.addToBody(pobj);
+            ind_font = obj.getIndirectReference();
+        }
+        pobj = getCIDFont(ind_font, cjkTag);
+        if (pobj != null){
+            obj = writer.addToBody(pobj);
+            ind_font = obj.getIndirectReference();
+        }
+        pobj = getFontBaseType(ind_font);
+        writer.addToBody(pobj, ref);
+    }
+    
+    private float getDescNumber(String name) {
+        return Integer.parseInt((String)fontDesc.get(name));
+    }
+    
+    private float getBBox(int idx) {
+        String s = (String)fontDesc.get("FontBBox");
+        StringTokenizer tk = new StringTokenizer(s, " []\r\n\t\f");
+        String ret = tk.nextToken();
+        for (int k = 0; k < idx; ++k)
+            ret = tk.nextToken();
+        return Integer.parseInt(ret);
+    }
+    
+    /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
+     * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>
+     * and <CODE>ITALICANGLE</CODE>.
+     * @param key the parameter to be extracted
+     * @param fontSize the font size in points
+     * @return the parameter in points
+     */
+    public float getFontDescriptor(int key, float fontSize) {
+        switch (key) {
+            case AWT_ASCENT:
+            case ASCENT:
+                return getDescNumber("Ascent") * fontSize / 1000;
+            case CAPHEIGHT:
+                return getDescNumber("CapHeight") * fontSize / 1000;
+            case AWT_DESCENT:
+            case DESCENT:
+                return getDescNumber("Descent") * fontSize / 1000;
+            case ITALICANGLE:
+                return getDescNumber("ItalicAngle");
+            case BBOXLLX:
+                return fontSize * getBBox(0) / 1000;
+            case BBOXLLY:
+                return fontSize * getBBox(1) / 1000;
+            case BBOXURX:
+                return fontSize * getBBox(2) / 1000;
+            case BBOXURY:
+                return fontSize * getBBox(3) / 1000;
+            case AWT_LEADING:
+                return 0;
+            case AWT_MAXADVANCE:
+                return fontSize * (getBBox(2) - getBBox(0)) / 1000;
+        }
+        return 0;
+    }
+    
+    public String getPostscriptFontName() {
+        return fontName;
+    }
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the full name of the font
+     */
+    public String[][] getFullFontName() {
+        return new String[][]{{"", "", "", fontName}};
+    }
+    
+    /** Gets the family name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the family name of the font
+     */
+    public String[][] getFamilyFontName() {
+        return getFullFontName();
+    }
+    
+    static char[] readCMap(String name) {
+        try {
+            name = name + ".cmap";
+            InputStream is = getResourceStream(RESOURCE_PATH + name);
+            char c[] = new char[0x10000];
+            for (int k = 0; k < 0x10000; ++k)
+                c[k] = (char)((is.read() << 8) + is.read());
+            return c;
+        }
+        catch (Exception e) {
+            // empty on purpose
+        }
+        return null;
+    }
+    
+    static IntHashtable createMetric(String s) {
+        IntHashtable h = new IntHashtable();
+        StringTokenizer tk = new StringTokenizer(s);
+        while (tk.hasMoreTokens()) {
+            int n1 = Integer.parseInt(tk.nextToken());
+            h.put(n1, Integer.parseInt(tk.nextToken()));
+        }
+        return h;
+    }
+    
+    static String convertToHCIDMetrics(int keys[], IntHashtable h) {
+        if (keys.length == 0)
+            return null;
+        int lastCid = 0;
+        int lastValue = 0;
+        int start;
+        for (start = 0; start < keys.length; ++start) {
+            lastCid = keys[start];
+            lastValue = h.get(lastCid);
+            if (lastValue != 0) {
+                ++start;
+                break;
+            }
+        }
+        if (lastValue == 0)
+            return null;
+        StringBuffer buf = new StringBuffer();
+        buf.append('[');
+        buf.append(lastCid);
+        int state = FIRST;
+        for (int k = start; k < keys.length; ++k) {
+            int cid = keys[k];
+            int value = h.get(cid);
+            if (value == 0)
+                continue;
+            switch (state) {
+                case FIRST: {
+                    if (cid == lastCid + 1 && value == lastValue) {
+                        state = SERIAL;
+                    }
+                    else if (cid == lastCid + 1) {
+                        state = BRACKET;
+                        buf.append('[').append(lastValue);
+                    }
+                    else {
+                        buf.append('[').append(lastValue).append(']').append(cid);
+                    }
+                    break;
+                }
+                case BRACKET: {
+                    if (cid == lastCid + 1 && value == lastValue) {
+                        state = SERIAL;
+                        buf.append(']').append(lastCid);
+                    }
+                    else if (cid == lastCid + 1) {
+                        buf.append(' ').append(lastValue);
+                    }
+                    else {
+                        state = FIRST;
+                        buf.append(' ').append(lastValue).append(']').append(cid);
+                    }
+                    break;
+                }
+                case SERIAL: {
+                    if (cid != lastCid + 1 || value != lastValue) {
+                        buf.append(' ').append(lastCid).append(' ').append(lastValue).append(' ').append(cid);
+                        state = FIRST;
+                    }
+                    break;
+                }
+            }
+            lastValue = value;
+            lastCid = cid;
+        }
+        switch (state) {
+            case FIRST: {
+                buf.append('[').append(lastValue).append("]]");
+                break;
+            }
+            case BRACKET: {
+                buf.append(' ').append(lastValue).append("]]");
+                break;
+            }
+            case SERIAL: {
+                buf.append(' ').append(lastCid).append(' ').append(lastValue).append(']');
+                break;
+            }
+        }
+        return buf.toString();
+    }
+    
+    static String convertToVCIDMetrics(int keys[], IntHashtable v, IntHashtable h) {
+        if (keys.length == 0)
+            return null;
+        int lastCid = 0;
+        int lastValue = 0;
+        int lastHValue = 0;
+        int start;
+        for (start = 0; start < keys.length; ++start) {
+            lastCid = keys[start];
+            lastValue = v.get(lastCid);
+            if (lastValue != 0) {
+                ++start;
+                break;
+            }
+            else
+                lastHValue = h.get(lastCid);
+        }
+        if (lastValue == 0)
+            return null;
+        if (lastHValue == 0)
+            lastHValue = 1000;
+        StringBuffer buf = new StringBuffer();
+        buf.append('[');
+        buf.append(lastCid);
+        int state = FIRST;
+        for (int k = start; k < keys.length; ++k) {
+            int cid = keys[k];
+            int value = v.get(cid);
+            if (value == 0)
+                continue;
+            int hValue = h.get(lastCid);
+            if (hValue == 0)
+                hValue = 1000;
+            switch (state) {
+                case FIRST: {
+                    if (cid == lastCid + 1 && value == lastValue && hValue == lastHValue) {
+                        state = SERIAL;
+                    }
+                    else {
+                        buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
+                    }
+                    break;
+                }
+                case SERIAL: {
+                    if (cid != lastCid + 1 || value != lastValue || hValue != lastHValue) {
+                        buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
+                        state = FIRST;
+                    }
+                    break;
+                }
+            }
+            lastValue = value;
+            lastCid = cid;
+            lastHValue = hValue;
+        }
+        buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(" ]");
+        return buf.toString();
+    }
+    
+    static HashMap readFontProperties(String name) {
+        try {
+            name += ".properties";
+            InputStream is = getResourceStream(RESOURCE_PATH + name);
+            Properties p = new Properties();
+            p.load(is);
+            is.close();
+            IntHashtable W = createMetric(p.getProperty("W"));
+            p.remove("W");
+            IntHashtable W2 = createMetric(p.getProperty("W2"));
+            p.remove("W2");
+            HashMap map = new HashMap();
+            for (Enumeration e = p.keys(); e.hasMoreElements();) {
+                Object obj = e.nextElement();
+                map.put(obj, p.getProperty((String)obj));
+            }
+            map.put("W", W);
+            map.put("W2", W2);
+            return map;
+        }
+        catch (Exception e) {
+            // empty on purpose
+        }
+        return null;
+    }
+
+    public char getUnicodeEquivalent(char c) {
+        if (cidDirect)
+            return translationMap[c];
+        return c;
+    }
+    
+    public char getCidCode(char c) {
+        if (cidDirect)
+            return c;
+        return translationMap[c];
+    }
+    
+    /** Checks if the font has any kerning pairs.
+     * @return always <CODE>false</CODE>
+     */    
+    public boolean hasKernPairs() {
+        return false;
+    }
+    
+    /**
+     * Checks if a character exists in this font.
+     * @param c the character to check
+     * @return <CODE>true</CODE> if the character has a glyph,
+     * <CODE>false</CODE> otherwise
+     */
+    public boolean charExists(char c) {
+        return translationMap[c] != 0;
+    }
+    
+    /**
+     * Sets the character advance.
+     * @param c the character
+     * @param advance the character advance normalized to 1000 units
+     * @return <CODE>true</CODE> if the advance was set,
+     * <CODE>false</CODE> otherwise. Will always return <CODE>false</CODE>
+     */
+    public boolean setCharAdvance(char c, int advance) {
+        return false;
+    }
+    
+    /**
+     * Sets the font name that will appear in the pdf font dictionary.
+     * Use with care as it can easily make a font unreadable if not embedded.
+     * @param name the new font name
+     */    
+    public void setPostscriptFontName(String name) {
+        fontName = name;
+    }   
+    
+    public boolean setKerning(char char1, char char2, int kern) {
+        return false;
+    }
+    
+    public int[] getCharBBox(char c) {
+        return null;
+    }
+    
+    protected int[] getRawCharBBox(int c, String name) {
+        return null;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/CMYKColor.java b/LibrarySource/com/lowagie/text/pdf/CMYKColor.java
new file mode 100644
index 0000000..5b57346
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/CMYKColor.java
@@ -0,0 +1,118 @@
+/*
+ * $Id: CMYKColor.java,v 1.43 2005/05/02 11:12:44 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class CMYKColor extends ExtendedColor {
+
+    float cyan;
+    float magenta;
+    float yellow;
+    float black;
+
+    /**
+     * Constructs a CMYK Color beased on 4 colorvalues (values are integers from 0 to 255).
+     * @param intCyan
+     * @param intMagenta
+     * @param intYellow
+     * @param intBlack
+     */
+    public CMYKColor(int intCyan, int intMagenta, int intYellow, int intBlack) {
+        this((float)intCyan / 255f, (float)intMagenta / 255f, (float)intYellow / 255f, (float)intBlack / 255f);
+    }
+
+    /**
+     * Construct a CMYK Color.
+     * @param floatCyan
+     * @param floatMagenta
+     * @param floatYellow
+     * @param floatBlack
+     */
+    public CMYKColor(float floatCyan, float floatMagenta, float floatYellow, float floatBlack) {
+        super(TYPE_CMYK, 1f - floatCyan - floatBlack, 1f - floatMagenta - floatBlack, 1f - floatYellow - floatBlack);
+        cyan = normalize(floatCyan);
+        magenta = normalize(floatMagenta);
+        yellow = normalize(floatYellow);
+        black = normalize(floatBlack);
+    }
+    
+    /**
+     * @return the cyan value
+     */
+    public float getCyan() {
+        return cyan;
+    }
+
+    /**
+     * @return the magenta value
+     */
+    public float getMagenta() {
+        return magenta;
+    }
+
+    /**
+     * @return the yellow value
+     */
+    public float getYellow() {
+        return yellow;
+    }
+
+    /**
+     * @return the black value
+     */
+    public float getBlack() {
+        return black;
+    }
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/ColorDetails.java b/LibrarySource/com/lowagie/text/pdf/ColorDetails.java
new file mode 100644
index 0000000..affcd34
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ColorDetails.java
@@ -0,0 +1,102 @@
+/*
+ * $Id: ColorDetails.java,v 1.11 2002/06/20 13:06:47 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+/** Each spotcolor in the document will have an instance of this class
+ *
+ * @author Phillip Pan (phillip at formstar.com)
+ */
+class ColorDetails {
+
+    /** The indirect reference to this color
+     */
+    PdfIndirectReference indirectReference;
+    /** The color name that appears in the document body stream
+     */
+    PdfName colorName;
+    /** The color
+     */
+    PdfSpotColor spotcolor;
+
+    /** Each spot color used in a document has an instance of this class.
+     * @param colorName the color name
+     * @param indirectReference the indirect reference to the font
+     * @param scolor the <CODE>PDfSpotColor</CODE>
+     */
+    ColorDetails(PdfName colorName, PdfIndirectReference indirectReference, PdfSpotColor scolor) {
+        this.colorName = colorName;
+        this.indirectReference = indirectReference;
+        this.spotcolor = scolor;
+    }
+
+    /** Gets the indirect reference to this color.
+     * @return the indirect reference to this color
+     */
+    PdfIndirectReference getIndirectReference() {
+        return indirectReference;
+    }
+
+    /** Gets the color name as it appears in the document body.
+     * @return the color name
+     */
+    PdfName getColorName() {
+        return colorName;
+    }
+
+    /** Gets the <CODE>SpotColor</CODE> object.
+     * @return the <CODE>PdfSpotColor</CODE>
+     */
+    PdfObject getSpotColor(PdfWriter writer) throws IOException {
+        return spotcolor.getSpotObject(writer);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/ColumnText.java b/LibrarySource/com/lowagie/text/pdf/ColumnText.java
new file mode 100644
index 0000000..ff48eea
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ColumnText.java
@@ -0,0 +1,1420 @@
+/*
+ * $Id: ColumnText.java,v 1.58 2005/01/11 14:14:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Stack;
+import java.util.Iterator;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Graphic;
+import com.lowagie.text.ListItem;
+import com.lowagie.text.Element;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Image;
+
+/**
+ * Formats text in a columnwise form. The text is bound
+ * on the left and on the right by a sequence of lines. This allows the column
+ * to have any shape, not only rectangular.
+ * <P>
+ * Several parameters can be set like the first paragraph line indent and
+ * extra space between paragraphs.
+ * <P>
+ * A call to the method <CODE>go</CODE> will return one of the following
+ * situations: the column ended or the text ended.
+ * <P>
+ * I the column ended, a new column definition can be loaded with the method
+ * <CODE>setColumns</CODE> and the method <CODE>go</CODE> can be called again.
+ * <P>
+ * If the text ended, more text can be loaded with <CODE>addText</CODE>
+ * and the method <CODE>go</CODE> can be called again.<BR>
+ * The only limitation is that one or more complete paragraphs must be loaded
+ * each time.
+ * <P>
+ * Full bidirectional reordering is supported. If the run direction is
+ * <CODE>PdfWriter.RUN_DIRECTION_RTL</CODE> the meaning of the horizontal
+ * alignments and margins is mirrored.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class ColumnText {
+    /** Eliminate the arabic vowels */    
+    public static final int AR_NOVOWEL = ArabicLigaturizer.ar_novowel;
+    /** Compose the tashkeel in the ligatures. */    
+    public static final int AR_COMPOSEDTASHKEEL = ArabicLigaturizer.ar_composedtashkeel;
+    /** Do some extra double ligatures. */    
+    public static final int AR_LIG = ArabicLigaturizer.ar_lig;
+    /**
+     * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
+     */
+    public static final int DIGITS_EN2AN = ArabicLigaturizer.DIGITS_EN2AN;
+    
+    /**
+     * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
+     */
+    public static final int DIGITS_AN2EN = ArabicLigaturizer.DIGITS_AN2EN;
+    
+    /**
+     * Digit shaping option:
+     * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+     * if the most recent strongly directional character
+     * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+     * The initial state at the start of the text is assumed to be not an Arabic,
+     * letter, so European digits at the start of the text will not change.
+     * Compare to DIGITS_ALEN2AN_INIT_AL.
+     */
+    public static final int DIGITS_EN2AN_INIT_LR = ArabicLigaturizer.DIGITS_EN2AN_INIT_LR;
+    
+    /**
+     * Digit shaping option:
+     * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+     * if the most recent strongly directional character
+     * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+     * The initial state at the start of the text is assumed to be an Arabic,
+     * letter, so European digits at the start of the text will change.
+     * Compare to DIGITS_ALEN2AN_INT_LR.
+     */
+    public static final int DIGITS_EN2AN_INIT_AL = ArabicLigaturizer.DIGITS_EN2AN_INIT_AL;
+    
+    /**
+     * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
+     */
+    public static final int DIGIT_TYPE_AN = ArabicLigaturizer.DIGIT_TYPE_AN;
+    
+    /**
+     * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
+     */
+    public static final int DIGIT_TYPE_AN_EXTENDED = ArabicLigaturizer.DIGIT_TYPE_AN_EXTENDED;
+    
+    protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
+    
+    /** the space char ratio */
+    public static final float GLOBAL_SPACE_CHAR_RATIO = 0;
+    
+    /** Signals that there is no more text available. */
+    public static final int NO_MORE_TEXT = 1;
+    
+    /** Signals that there is no more column. */
+    public static final int NO_MORE_COLUMN = 2;
+    
+    /** The column is valid. */
+    protected static final int LINE_STATUS_OK = 0;
+    
+    /** The line is out the column limits. */
+    protected static final int LINE_STATUS_OFFLIMITS = 1;
+    
+    /** The line cannot fit this column position. */
+    protected static final int LINE_STATUS_NOLINE = 2;
+    
+    /** Upper bound of the column. */
+    protected float maxY;
+    
+    /** Lower bound of the column. */
+    protected float minY;
+    
+    protected float leftX;
+    
+    protected float rightX;
+    
+    /** The column alignment. Default is left alignment. */
+    protected int alignment = Element.ALIGN_LEFT;
+    
+    /** The left column bound. */
+    protected ArrayList leftWall;
+    
+    /** The right column bound. */
+    protected ArrayList rightWall;
+    
+    /** The chunks that form the text. */
+//    protected ArrayList chunks = new ArrayList();
+    protected BidiLine bidiLine;
+    
+    /** The current y line location. Text will be written at this line minus the leading. */
+    protected float yLine;
+    
+    /** The leading for the current line. */
+    protected float currentLeading = 16;
+    
+    /** The fixed text leading. */
+    protected float fixedLeading = 16;
+    
+    /** The text leading that is multiplied by the biggest font size in the line. */
+    protected float multipliedLeading = 0;
+    
+    /** The <CODE>PdfContent</CODE> where the text will be written to. */
+    protected PdfContentByte canvas;
+    
+    /** The line status when trying to fit a line to a column. */
+    protected int lineStatus;
+    
+    /** The first paragraph line indent. */
+    protected float indent = 0;
+    
+    /** The following paragraph lines indent. */
+    protected float followingIndent = 0;
+    
+    /** The right paragraph lines indent. */
+    protected float rightIndent = 0;
+    
+    /** The extra space between paragraphs. */
+    protected float extraParagraphSpace = 0;
+    
+    /** The width of the line when the column is defined as a simple rectangle. */
+    protected float rectangularWidth = -1;
+    
+    protected boolean rectangularMode = false;
+    /** Holds value of property spaceCharRatio. */
+    private float spaceCharRatio = GLOBAL_SPACE_CHAR_RATIO;
+
+    private boolean lastWasNewline = true;
+    
+    /** Holds value of property linesWritten. */
+    private int linesWritten;
+    
+    private float firstLineY;
+    private boolean firstLineYDone = false;
+    
+    /** Holds value of property arabicOptions. */
+    private int arabicOptions = 0;
+    
+    protected float descender;
+    
+    protected boolean composite = false;
+    
+    protected ColumnText compositeColumn;
+    
+    protected LinkedList compositeElements;
+    
+    protected int listIdx = 0;
+    
+    private boolean splittedRow;
+    
+    protected Phrase waitPhrase;
+    
+    /** if true, first line height is adjusted so that the max ascender touches the top */
+    private boolean useAscender = false;
+
+    /**
+     * Creates a <CODE>ColumnText</CODE>.
+     * @param canvas the place where the text will be written to. Can
+     * be a template.
+     */
+    public ColumnText(PdfContentByte canvas) {
+        this.canvas = canvas;
+    }
+    
+    /** Creates an independent duplicated of the instance <CODE>org</CODE>.
+     * @param org the original <CODE>ColumnText</CODE>
+     * @return the duplicated
+     */    
+    public static ColumnText duplicate(ColumnText org) {
+        ColumnText ct = new ColumnText(null);
+        ct.setACopy(org);
+        return ct;
+    }
+    
+    /** Makes this instance an independent copy of <CODE>org</CODE>.
+     * @param org the original <CODE>ColumnText</CODE>
+     * @return itself
+     */    
+    public ColumnText setACopy(ColumnText org) {
+        setSimpleVars(org);
+        if (org.bidiLine != null)
+            bidiLine = new BidiLine(org.bidiLine);
+        return this;
+    }
+    
+    protected void setSimpleVars(ColumnText org) {
+        maxY = org.maxY;
+        minY = org.minY;
+        alignment = org.alignment;
+        leftWall = null;
+        if (org.leftWall != null)
+            leftWall = new ArrayList(org.leftWall);
+        rightWall = null;
+        if (org.rightWall != null)
+            rightWall = new ArrayList(org.rightWall);
+        yLine = org.yLine;
+        currentLeading = org.currentLeading;
+        fixedLeading = org.fixedLeading;
+        multipliedLeading = org.multipliedLeading;
+        canvas = org.canvas;
+        lineStatus = org.lineStatus;
+        indent = org.indent;
+        followingIndent = org.followingIndent;
+        rightIndent = org.rightIndent;
+        extraParagraphSpace = org.extraParagraphSpace;
+        rectangularWidth = org.rectangularWidth;
+        rectangularMode = org.rectangularMode;
+        spaceCharRatio = org.spaceCharRatio;
+        lastWasNewline = org.lastWasNewline;
+        linesWritten = org.linesWritten;
+        arabicOptions = org.arabicOptions;
+        runDirection = org.runDirection;
+        descender = org.descender;
+        composite = org.composite;
+        splittedRow = org.splittedRow;
+        if (org.composite) {
+            compositeElements = new LinkedList(org.compositeElements);
+            if (splittedRow) {
+                PdfPTable table = (PdfPTable)compositeElements.getFirst();
+                compositeElements.set(0, new PdfPTable(table));
+            }
+            if (org.compositeColumn != null)
+                compositeColumn = duplicate(org.compositeColumn);
+        }
+        listIdx = org.listIdx;
+        firstLineY = org.firstLineY;
+        leftX = org.leftX;
+        rightX = org.rightX;
+        firstLineYDone = org.firstLineYDone;
+        waitPhrase = org.waitPhrase;
+        useAscender = org.useAscender;
+    }
+    
+    private void addWaitingPhrase() {
+        if (bidiLine == null && waitPhrase != null) {
+            bidiLine = new BidiLine();
+            for (Iterator j = waitPhrase.getChunks().iterator(); j.hasNext();) {
+                bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
+            }
+            waitPhrase = null;
+        }
+    }
+    
+    /**
+     * Adds a <CODE>Phrase</CODE> to the current text array.
+     * Will not have any effect if addElement() was called before.
+     * @param phrase the text
+     */
+    public void addText(Phrase phrase) {
+        if (phrase == null || composite)
+            return;
+        addWaitingPhrase();
+        if (bidiLine == null) {
+            waitPhrase = phrase;
+            return;
+        }
+        for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
+            bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
+        }
+    }
+    
+    /**
+     * Replaces the current text array with this <CODE>Phrase</CODE>.
+     * Anything added previously with addElement() is lost.
+     * @param phrase the text
+     */
+    public void setText(Phrase phrase) {
+        bidiLine = null;
+        composite = false;
+        compositeColumn = null;
+        compositeElements = null;
+        listIdx = 0;
+        splittedRow = false;
+        waitPhrase = phrase;
+    }
+    
+    /**
+     * Adds a <CODE>Chunk</CODE> to the current text array.
+     * Will not have any effect if addElement() was called before.
+     * @param chunk the text
+     */
+    public void addText(Chunk chunk) {
+        if (chunk == null || composite)
+            return;
+        addText(new Phrase(chunk));
+    }
+    
+    /**
+     * Adds an element. Elements supported are <CODE>Paragraph</CODE>,
+     * <CODE>List</CODE>, <CODE>PdfPTable</CODE>, <CODE>Image</CODE> and
+     * <CODE>Graphic</CODE>.
+     * <p>
+     * It removes all the text placed with <CODE>addText()</CODE>.
+     * @param element the <CODE>Element</CODE>
+     */    
+    public void addElement(Element element) {
+        if (element == null)
+            return;
+        if (element instanceof Image) {
+            Image img = (Image)element;
+            PdfPTable t = new PdfPTable(1);
+            float w = img.getWidthPercentage();
+            if (w == 0) {
+                t.setTotalWidth(img.scaledWidth());
+                t.setLockedWidth(true);
+            }
+            else
+                t.setWidthPercentage(w);
+            t.setSpacingAfter(img.spacingAfter());
+            t.setSpacingBefore(img.spacingBefore());
+            PdfPCell c = new PdfPCell(img, true);
+            c.setPadding(0);
+            c.setBorder(img.border());
+            c.setBorderColor(img.borderColor());
+            c.setBorderWidth(img.borderWidth());
+            c.setBackgroundColor(img.backgroundColor());
+            c.setGrayFill(img.grayFill());
+            t.addCell(c);
+            element = t;
+        }
+        if (element.type() == Element.CHUNK) {
+        	element = new Paragraph((Chunk)element);
+        }
+        else if (element.type() == Element.PHRASE) {
+        	element = new Paragraph((Phrase)element);
+        }
+        if (element.type() != Element.PARAGRAPH && element.type() != Element.LIST && element.type() != Element.PTABLE && element.type() != Element.GRAPHIC)
+            throw new IllegalArgumentException("Element not allowed.");
+        if (!composite) {
+            composite = true;
+            compositeElements = new LinkedList();
+            bidiLine = null;
+            waitPhrase = null;
+        }
+        compositeElements.add(element);
+    }
+    
+    /**
+     * Converts a sequence of lines representing one of the column bounds into
+     * an internal format.
+     * <p>
+     * Each array element will contain a <CODE>float[4]</CODE> representing
+     * the line x = ax + b.
+     * @param cLine the column array
+     * @return the converted array
+     */
+    protected ArrayList convertColumn(float cLine[]) {
+        if (cLine.length < 4)
+            throw new RuntimeException("No valid column line found.");
+        ArrayList cc = new ArrayList();
+        for (int k = 0; k < cLine.length - 2; k += 2) {
+            float x1 = cLine[k];
+            float y1 = cLine[k + 1];
+            float x2 = cLine[k + 2];
+            float y2 = cLine[k + 3];
+            if (y1 == y2)
+                continue;
+            // x = ay + b
+            float a = (x1 - x2) / (y1 - y2);
+            float b = x1 - a * y1;
+            float r[] = new float[4];
+            r[0] = Math.min(y1, y2);
+            r[1] = Math.max(y1, y2);
+            r[2] = a;
+            r[3] = b;
+            cc.add(r);
+            maxY = Math.max(maxY, r[1]);
+            minY = Math.min(minY, r[0]);
+        }
+        if (cc.size() == 0)
+            throw new RuntimeException("No valid column line found.");
+        return cc;
+    }
+    
+    /**
+     * Finds the intersection between the <CODE>yLine</CODE> and the column. It will
+     * set the <CODE>lineStatus</CODE> apropriatly.
+     * @param wall the column to intersect
+     * @return the x coordinate of the intersection
+     */
+    protected float findLimitsPoint(ArrayList wall) {
+        lineStatus = LINE_STATUS_OK;
+        if (yLine < minY || yLine > maxY) {
+            lineStatus = LINE_STATUS_OFFLIMITS;
+            return 0;
+        }
+        for (int k = 0; k < wall.size(); ++k) {
+            float r[] = (float[])wall.get(k);
+            if (yLine < r[0] || yLine > r[1])
+                continue;
+            return r[2] * yLine + r[3];
+        }
+        lineStatus = LINE_STATUS_NOLINE;
+        return 0;
+    }
+    
+    /**
+     * Finds the intersection between the <CODE>yLine</CODE> and the two
+     * column bounds. It will set the <CODE>lineStatus</CODE> apropriatly.
+     * @return a <CODE>float[2]</CODE>with the x coordinates of the intersection
+     */
+    protected float[] findLimitsOneLine() {
+        float x1 = findLimitsPoint(leftWall);
+        if (lineStatus == LINE_STATUS_OFFLIMITS || lineStatus == LINE_STATUS_NOLINE)
+            return null;
+        float x2 = findLimitsPoint(rightWall);
+        if (lineStatus == LINE_STATUS_NOLINE)
+            return null;
+        return new float[]{x1, x2};
+    }
+    
+    /**
+     * Finds the intersection between the <CODE>yLine</CODE>,
+     * the <CODE>yLine-leading</CODE>and the two
+     * column bounds. It will set the <CODE>lineStatus</CODE> apropriatly.
+     * @return a <CODE>float[4]</CODE>with the x coordinates of the intersection
+     */
+    protected float[] findLimitsTwoLines() {
+        boolean repeat = false;
+        for (;;) {
+            if (repeat && currentLeading == 0)
+                return null;
+            repeat = true;
+            float x1[] = findLimitsOneLine();
+            if (lineStatus == LINE_STATUS_OFFLIMITS)
+                return null;
+            yLine -= currentLeading;
+            if (lineStatus == LINE_STATUS_NOLINE) {
+                continue;
+            }
+            float x2[] = findLimitsOneLine();
+            if (lineStatus == LINE_STATUS_OFFLIMITS)
+                return null;
+            if (lineStatus == LINE_STATUS_NOLINE) {
+                yLine -= currentLeading;
+                continue;
+            }
+            if (x1[0] >= x2[1] || x2[0] >= x1[1])
+                continue;
+            return new float[]{x1[0], x1[1], x2[0], x2[1]};
+        }
+    }
+    
+    /**
+     * Sets the columns bounds. Each column bound is described by a
+     * <CODE>float[]</CODE> with the line points [x1,y1,x2,y2,...].
+     * The array must have at least 4 elements.
+     * @param leftLine the left column bound
+     * @param rightLine the right column bound
+     */
+    public void setColumns(float leftLine[], float rightLine[]) {
+        maxY = -10e20f;
+        minY = 10e20f;
+        rightWall = convertColumn(rightLine);
+        leftWall = convertColumn(leftLine);
+        rectangularWidth = -1;
+        rectangularMode = false;
+    }
+    
+    /**
+     * Simplified method for rectangular columns.
+     * @param phrase a <CODE>Phrase</CODE>
+     * @param llx the lower left x corner
+     * @param lly the lower left y corner
+     * @param urx the upper right x corner
+     * @param ury the upper right y corner
+     * @param leading the leading
+     * @param alignment the column alignment
+     */
+    public void setSimpleColumn(Phrase phrase, float llx, float lly, float urx, float ury, float leading, int alignment) {
+        addText(phrase);
+        setSimpleColumn(llx, lly, urx, ury, leading, alignment);
+    }
+    
+    /**
+     * Simplified method for rectangular columns.
+     * @param llx the lower left x corner
+     * @param lly the lower left y corner
+     * @param urx the upper right x corner
+     * @param ury the upper right y corner
+     * @param leading the leading
+     * @param alignment the column alignment
+     */
+    public void setSimpleColumn(float llx, float lly, float urx, float ury, float leading, int alignment) {
+        setLeading(leading);
+        this.alignment = alignment;
+        setSimpleColumn(llx, lly, urx, ury);
+    }
+    
+    /**
+     * Simplified method for rectangular columns.
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void setSimpleColumn(float llx, float lly, float urx, float ury) {
+        leftX = Math.min(llx, urx);
+        maxY = Math.max(lly, ury);
+        minY = Math.min(lly, ury);
+        rightX = Math.max(llx, urx);
+        yLine = maxY;
+        rectangularWidth = rightX - leftX;
+        if (rectangularWidth < 0)
+            rectangularWidth = 0;
+        rectangularMode = true;
+    }
+    /**
+     * Sets the leading to fixed
+     * @param leading the leading
+     */
+    public void setLeading(float leading) {
+        fixedLeading = leading;
+        multipliedLeading = 0;
+    }
+    
+    /**
+     * Sets the leading fixed and variable. The resultant leading will be
+     * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
+     * size of the bigest font in the line.
+     * @param fixedLeading the fixed leading
+     * @param multipliedLeading the variable leading
+     */
+    public void setLeading(float fixedLeading, float multipliedLeading) {
+        this.fixedLeading = fixedLeading;
+        this.multipliedLeading = multipliedLeading;
+    }
+    
+    /**
+     * Gets the fixed leading
+     * @return the leading
+     */
+    public float getLeading() {
+        return fixedLeading;
+    }
+    
+    /**
+     * Gets the variable leading
+     * @return the leading
+     */
+    public float getMultipliedLeading() {
+        return multipliedLeading;
+    }
+    
+    /**
+     * Sets the yLine. The line will be written to yLine-leading.
+     * @param yLine the yLine
+     */
+    public void setYLine(float yLine) {
+        this.yLine = yLine;
+    }
+    
+    /**
+     * Gets the yLine.
+     * @return the yLine
+     */
+    public float getYLine() {
+        return yLine;
+    }
+    
+    /**
+     * Sets the alignment.
+     * @param alignment the alignment
+     */
+    public void setAlignment(int alignment) {
+        this.alignment = alignment;
+    }
+    
+    /**
+     * Gets the alignment.
+     * @return the alignment
+     */
+    public int getAlignment() {
+        return alignment;
+    }
+    
+    /**
+     * Sets the first paragraph line indent.
+     * @param indent the indent
+     */
+    public void setIndent(float indent) {
+        this.indent = indent;
+        lastWasNewline = true;
+    }
+    
+    /**
+     * Gets the first paragraph line indent.
+     * @return the indent
+     */
+    public float getIndent() {
+        return indent;
+    }
+    
+    /**
+     * Sets the following paragraph lines indent.
+     * @param indent the indent
+     */
+    public void setFollowingIndent(float indent) {
+        this.followingIndent = indent;
+        lastWasNewline = true;
+    }
+    
+    /**
+     * Gets the following paragraph lines indent.
+     * @return the indent
+     */
+    public float getFollowingIndent() {
+        return followingIndent;
+    }
+    
+    /**
+     * Sets the right paragraph lines indent.
+     * @param indent the indent
+     */
+    public void setRightIndent(float indent) {
+        this.rightIndent = indent;
+        lastWasNewline = true;
+    }
+    
+    /**
+     * Gets the right paragraph lines indent.
+     * @return the indent
+     */
+    public float getRightIndent() {
+        return rightIndent;
+    }
+    
+    /**
+     * Outputs the lines to the document. It is equivalent to <CODE>go(false)</CODE>.
+     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
+     * and/or <CODE>NO_MORE_COLUMN</CODE>
+     * @throws DocumentException on error
+     */
+    public int go() throws DocumentException {
+        return go(false);
+    }
+    
+    /**
+     * Outputs the lines to the document. The output can be simulated.
+     * @param simulate <CODE>true</CODE> to simulate the writting to the document
+     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
+     * and/or <CODE>NO_MORE_COLUMN</CODE>
+     * @throws DocumentException on error
+     */
+    public int go(boolean simulate) throws DocumentException {
+        if (composite)
+            return goComposite(simulate);
+        addWaitingPhrase();
+        if (bidiLine == null)
+            return NO_MORE_TEXT;
+        descender = 0;
+        linesWritten = 0;
+        boolean dirty = false;
+        float ratio = spaceCharRatio;
+        Object currentValues[] = new Object[2];
+        PdfFont currentFont = null;
+        Float lastBaseFactor = new Float(0);
+        currentValues[1] = lastBaseFactor;
+        PdfDocument pdf = null;
+        PdfContentByte graphics = null;
+        PdfContentByte text = null;
+        firstLineY = Float.NaN;
+        int localRunDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
+        if (runDirection != PdfWriter.RUN_DIRECTION_DEFAULT)
+            localRunDirection = runDirection;
+        if (canvas != null) {
+            graphics = canvas;
+            pdf = canvas.getPdfDocument();
+            text = canvas.getDuplicate();
+        }
+        else if (!simulate)
+            throw new NullPointerException("ColumnText.go with simulate==false and text==null.");
+        if (!simulate) {
+            if (ratio == GLOBAL_SPACE_CHAR_RATIO)
+                ratio = text.getPdfWriter().getSpaceCharRatio();
+            else if (ratio < 0.001f)
+                ratio = 0.001f;
+        }
+        float firstIndent = 0;
+        
+        int status = 0;
+        if (rectangularMode) {
+            for (;;) {
+                firstIndent = (lastWasNewline ? indent : followingIndent);
+                if (rectangularWidth <= firstIndent + rightIndent) {
+                    status = NO_MORE_COLUMN;
+                    if (bidiLine.isEmpty())
+                        status |= NO_MORE_TEXT;
+                    break;
+                }
+                if (bidiLine.isEmpty()) {
+                    status = NO_MORE_TEXT;
+                    break;
+                }
+                PdfLine line = bidiLine.processLine(rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
+                if (line == null) {
+                    status = NO_MORE_TEXT;
+                    break;
+                }
+                float maxSize = line.getMaxSizeSimple();
+                if (isUseAscender() && Float.isNaN(firstLineY)) {
+                    currentLeading = line.getAscender();
+                }
+                else {
+                    currentLeading = fixedLeading + maxSize * multipliedLeading;
+                }
+                if (yLine > maxY || yLine - currentLeading < minY ) {
+                    status = NO_MORE_COLUMN;
+                    bidiLine.restore();
+                    break;
+                }
+                yLine -= currentLeading;
+                if (!simulate && !dirty) {
+                    text.beginText();
+                    dirty = true;
+                }
+                if (Float.isNaN(firstLineY)) {
+                    firstLineY = yLine;
+                }
+                if (!simulate) {
+                    currentValues[0] = currentFont;
+                    text.setTextMatrix(leftX + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
+                    pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
+                    currentFont = (PdfFont)currentValues[0];
+                }
+                lastWasNewline = line.isNewlineSplit();
+                yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
+                ++linesWritten;
+                descender = line.getDescender();
+            }
+        }
+        else {
+            currentLeading = fixedLeading;
+            for (;;) {
+                firstIndent = (lastWasNewline ? indent : followingIndent);
+                float yTemp = yLine;
+                float xx[] = findLimitsTwoLines();
+                if (xx == null) {
+                    status = NO_MORE_COLUMN;
+                    if (bidiLine.isEmpty())
+                        status |= NO_MORE_TEXT;
+                    yLine = yTemp;
+                    break;
+                }
+                if (bidiLine.isEmpty()) {
+                    status = NO_MORE_TEXT;
+                    yLine = yTemp;
+                    break;
+                }
+                float x1 = Math.max(xx[0], xx[2]);
+                float x2 = Math.min(xx[1], xx[3]);
+                if (x2 - x1 <= firstIndent + rightIndent)
+                    continue;
+                if (!simulate && !dirty) {
+                    text.beginText();
+                    dirty = true;
+                }
+                PdfLine line = bidiLine.processLine(x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
+                if (line == null) {
+                    status = NO_MORE_TEXT;
+                    yLine = yTemp;
+                    break;
+                }
+                if (!simulate) {
+                    currentValues[0] = currentFont;
+                    text.setTextMatrix(x1 + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
+                    pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
+                    currentFont = (PdfFont)currentValues[0];
+                }
+                lastWasNewline = line.isNewlineSplit();
+                yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
+                ++linesWritten;
+                descender = line.getDescender();
+            }
+        }
+        if (dirty) {
+            text.endText();
+            canvas.add(text);
+        }
+        return status;
+    }
+    
+    /**
+     * Sets the extra space between paragraphs.
+     * @return the extra space between paragraphs
+     */
+    public float getExtraParagraphSpace() {
+        return extraParagraphSpace;
+    }
+    
+    /**
+     * Sets the extra space between paragraphs.
+     * @param extraParagraphSpace the extra space between paragraphs
+     */
+    public void setExtraParagraphSpace(float extraParagraphSpace) {
+        this.extraParagraphSpace = extraParagraphSpace;
+    }
+    
+    /**
+     * Clears the chunk array. A call to <CODE>go()</CODE> will always return
+     * NO_MORE_TEXT.
+     */
+    public void clearChunks() {
+        if (bidiLine != null)
+            bidiLine.clearChunks();
+    }
+    
+    /** Gets the space/character extra spacing ratio for
+     * fully justified text.
+     * @return the space/character extra spacing ratio
+     */    
+    public float getSpaceCharRatio() {
+        return spaceCharRatio;
+    }
+    
+    /** Sets the ratio between the extra word spacing and the extra character spacing
+     * when the text is fully justified.
+     * Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing.
+     * If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing
+     * will be zero.
+     * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
+     */
+    public void setSpaceCharRatio(float spaceCharRatio) {
+        this.spaceCharRatio = spaceCharRatio;
+    }
+
+    /** Sets the run direction. 
+     * @param runDirection the run direction
+     */    
+    public void setRunDirection(int runDirection) {
+        if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
+            throw new RuntimeException("Invalid run direction: " + runDirection);
+        this.runDirection = runDirection;
+    }
+    
+    /** Gets the run direction.
+     * @return the run direction
+     */    
+    public int getRunDirection() {
+        return runDirection;
+    }
+    
+    /** Gets the number of lines written.
+     * @return the number of lines written
+     */
+    public int getLinesWritten() {
+        return this.linesWritten;
+    }
+    
+    /** Gets the arabic shaping options.
+     * @return the arabic shaping options
+     */
+    public int getArabicOptions() {
+        return this.arabicOptions;
+    }
+    
+    /** Sets the arabic shaping options. The option can be AR_NOVOWEL,
+     * AR_COMPOSEDTASHKEEL and AR_LIG.
+     * @param arabicOptions the arabic shaping options
+     */
+    public void setArabicOptions(int arabicOptions) {
+        this.arabicOptions = arabicOptions;
+    }
+    
+    /** Gets the biggest descender value of the last line written.
+     * @return the biggest descender value of the last line written
+     */    
+    public float getDescender() {
+        return descender;
+    }
+    
+    /** Gets the width that the line will occupy after writing.
+     * Only the width of the first line is returned.
+     * @param phrase the <CODE>Phrase</CODE> containing the line
+     * @param runDirection the run direction
+     * @param arabicOptions the options for the arabic shaping
+     * @return the width of the line
+     */    
+    public static float getWidth(Phrase phrase, int runDirection, int arabicOptions) {
+        ColumnText ct = new ColumnText(null);
+        ct.addText(phrase);
+        ct.addWaitingPhrase();
+        PdfLine line = ct.bidiLine.processLine(20000, Element.ALIGN_LEFT, runDirection, arabicOptions);
+        if (line == null)
+            return 0;
+        else
+            return 20000 - line.widthLeft();
+    }
+    
+    /** Gets the width that the line will occupy after writing.
+     * Only the width of the first line is returned.
+     * @param phrase the <CODE>Phrase</CODE> containing the line
+     * @return the width of the line
+     */    
+    public static float getWidth(Phrase phrase) {
+        return getWidth(phrase, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
+    }
+    
+    /** Shows a line of text. Only the first line is written.
+     * @param canvas where the text is to be written to
+     * @param alignment the alignment. It is not influenced by the run direction
+     * @param phrase the <CODE>Phrase</CODE> with the text
+     * @param x the x reference position
+     * @param y the y reference position
+     * @param rotation the rotation to be applied in degrees counterclockwise
+     * @param runDirection the run direction
+     * @param arabicOptions the options for the arabic shaping
+     */    
+    public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation, int runDirection, int arabicOptions) {
+        if (alignment != Element.ALIGN_LEFT && alignment != Element.ALIGN_CENTER
+            && alignment != Element.ALIGN_RIGHT)
+            alignment = Element.ALIGN_LEFT;
+        canvas.saveState();
+        ColumnText ct = new ColumnText(canvas);
+        if (rotation == 0) {
+            if (alignment == Element.ALIGN_LEFT)
+                ct.setSimpleColumn(phrase, x, y - 1, 20000 + x, y + 2, 2, alignment);
+            else if (alignment == Element.ALIGN_RIGHT)
+                ct.setSimpleColumn(phrase, x-20000, y-1, x, y+2, 2, alignment);
+            else
+                ct.setSimpleColumn(phrase, x-20000, y-1, x+20000, y+2, 2, alignment);
+        }
+        else {
+            double alpha = rotation * Math.PI / 180.0;
+            float cos = (float)Math.cos(alpha);
+            float sin = (float)Math.sin(alpha);
+            canvas.concatCTM(cos, sin, -sin, cos, x, y);
+            if (alignment == Element.ALIGN_LEFT)
+                ct.setSimpleColumn(phrase, 0, -1, 20000, 2, 2, alignment);
+            else if (alignment == Element.ALIGN_RIGHT)
+                ct.setSimpleColumn(phrase, -20000, -1, 0, 2, 2, alignment);
+            else
+                ct.setSimpleColumn(phrase, -20000, -1, 20000, 2, 2, alignment);
+        }
+        if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+            if (alignment == Element.ALIGN_LEFT)
+                alignment = Element.ALIGN_RIGHT;
+            else if (alignment == Element.ALIGN_RIGHT)
+                alignment = Element.ALIGN_LEFT;
+        }
+        ct.setAlignment(alignment);
+        ct.setArabicOptions(arabicOptions);
+        ct.setRunDirection(runDirection);
+        try {
+            ct.go();
+        }
+        catch (DocumentException e) {
+            throw new ExceptionConverter(e);
+        }
+        canvas.restoreState();
+    }
+
+    /** Shows a line of text. Only the first line is written.
+     * @param canvas where the text is to be written to
+     * @param alignment the alignment
+     * @param phrase the <CODE>Phrase</CODE> with the text
+     * @param x the x reference position
+     * @param y the y reference position
+     * @param rotation the rotation to be applied in degrees counterclockwise
+     */    
+    public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation) {
+        showTextAligned(canvas, alignment, phrase, x, y, rotation, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
+    }
+
+    protected int goComposite(boolean simulate) throws DocumentException {
+        if (!rectangularMode)
+            throw new DocumentException("Irregular columns are not supported in composite mode.");
+        linesWritten = 0;
+        descender = 0;
+        boolean firstPass = true;
+        main_loop:
+        while (true) {
+            if (compositeElements.isEmpty())
+                return NO_MORE_TEXT;
+            Element element = (Element)compositeElements.getFirst();
+            if (element.type() == Element.PARAGRAPH) {
+                Paragraph para = (Paragraph)element;
+                int status = 0;
+                for (int keep = 0; keep < 2; ++keep) {
+                    float lastY = yLine;
+                    boolean createHere = false;
+                    if (compositeColumn == null) {
+                        compositeColumn = new ColumnText(canvas);
+                        compositeColumn.setUseAscender(firstPass ? useAscender : false);
+                        compositeColumn.setAlignment(para.alignment());
+                        compositeColumn.setIndent(para.indentationLeft() + para.getFirstLineIndent());
+                        compositeColumn.setExtraParagraphSpace(para.getExtraParagraphSpace());
+                        compositeColumn.setFollowingIndent(para.indentationLeft());
+                        compositeColumn.setRightIndent(para.indentationRight());
+                        compositeColumn.setLeading(para.leading(), para.getMultipliedLeading());
+                        compositeColumn.setRunDirection(runDirection);
+                        compositeColumn.setArabicOptions(arabicOptions);
+                        compositeColumn.setSpaceCharRatio(spaceCharRatio);
+                        compositeColumn.addText(para);
+                        if (!firstPass) {
+                            yLine -= para.spacingBefore();
+                        }
+                        createHere = true;
+                    }
+                    compositeColumn.leftX = leftX;
+                    compositeColumn.rightX = rightX;
+                    compositeColumn.yLine = yLine;
+                    compositeColumn.rectangularWidth = rectangularWidth;
+                    compositeColumn.rectangularMode = rectangularMode;
+                    compositeColumn.minY = minY;
+                    compositeColumn.maxY = maxY;
+                    boolean keepCandidate = (para.getKeepTogether() && createHere && !firstPass);
+                    status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
+                    if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
+                        compositeColumn = null;
+                        yLine = lastY;
+                        return NO_MORE_COLUMN;
+                    }
+                    if (simulate || !keepCandidate)
+                        break;
+                    if (keep == 0) {
+                        compositeColumn = null;
+                        yLine = lastY;
+                    }
+                }
+                firstPass = false;
+                yLine = compositeColumn.yLine;
+                linesWritten += compositeColumn.linesWritten;
+                descender = compositeColumn.descender;
+                if ((status & NO_MORE_TEXT) != 0) {
+                    compositeColumn = null;
+                    compositeElements.removeFirst();
+                    yLine -= para.spacingAfter();
+                }
+                if ((status & NO_MORE_COLUMN) != 0) {
+                    return NO_MORE_COLUMN;
+                }
+            }
+            else if (element.type() == Element.LIST) {
+                com.lowagie.text.List list = (com.lowagie.text.List)element;
+                ArrayList items = list.getItems();
+                ListItem item = null;
+                float listIndentation = list.indentationLeft();
+                int count = 0;
+                Stack stack = new Stack();
+                for (int k = 0; k < items.size(); ++k) {
+                    Object obj = items.get(k);
+                    if (obj instanceof ListItem) {
+                        if (count == listIdx) {
+                            item = (ListItem)obj;
+                            break;
+                        }
+                        else ++count;
+                    }
+                    else if (obj instanceof com.lowagie.text.List) {
+                        stack.push(new Object[]{list, new Integer(k), new Float(listIndentation)});
+                        list = (com.lowagie.text.List)obj;
+                        items = list.getItems();
+                        listIndentation += list.indentationLeft();
+                        k = -1;
+                        continue;
+                    }
+                    if (k == items.size() - 1) {
+                        if (!stack.isEmpty()) {
+                            Object objs[] = (Object[])stack.pop();
+                            list = (com.lowagie.text.List)objs[0];
+                            items = list.getItems();
+                            k = ((Integer)objs[1]).intValue();
+                            listIndentation = ((Float)objs[2]).floatValue();
+                        }
+                    }
+                }
+                int status = 0;
+                for (int keep = 0; keep < 2; ++keep) {
+                    float lastY = yLine;
+                    boolean createHere = false;
+                    if (compositeColumn == null) {
+                        if (item == null) {
+                            listIdx = 0;
+                            compositeElements.removeFirst();
+                            continue main_loop;
+                        }
+                        compositeColumn = new ColumnText(canvas);
+                        compositeColumn.setUseAscender(firstPass ? useAscender : false);
+                        compositeColumn.setAlignment(item.alignment());
+                        compositeColumn.setIndent(item.indentationLeft() + listIndentation + item.getFirstLineIndent());
+                        compositeColumn.setExtraParagraphSpace(item.getExtraParagraphSpace());
+                        compositeColumn.setFollowingIndent(compositeColumn.getIndent());
+                        compositeColumn.setRightIndent(item.indentationRight() + list.indentationRight());
+                        compositeColumn.setLeading(item.leading(), item.getMultipliedLeading());
+                        compositeColumn.setRunDirection(runDirection);
+                        compositeColumn.setArabicOptions(arabicOptions);
+                        compositeColumn.setSpaceCharRatio(spaceCharRatio);
+                        compositeColumn.addText(item);
+                        if (!firstPass) {
+                            yLine -= item.spacingBefore();
+                        }
+                        createHere = true;
+                    }
+                    compositeColumn.leftX = leftX;
+                    compositeColumn.rightX = rightX;
+                    compositeColumn.yLine = yLine;
+                    compositeColumn.rectangularWidth = rectangularWidth;
+                    compositeColumn.rectangularMode = rectangularMode;
+                    compositeColumn.minY = minY;
+                    compositeColumn.maxY = maxY;
+                    boolean keepCandidate = (item.getKeepTogether() && createHere && !firstPass);
+                    status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
+                    if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
+                        compositeColumn = null;
+                        yLine = lastY;
+                        return NO_MORE_COLUMN;
+                    }
+                    if (simulate || !keepCandidate)
+                        break;
+                    if (keep == 0) {
+                        compositeColumn = null;
+                        yLine = lastY;
+                    }
+                }
+                firstPass = false;
+                yLine = compositeColumn.yLine;
+                linesWritten += compositeColumn.linesWritten;
+                descender = compositeColumn.descender;
+                if (!Float.isNaN(compositeColumn.firstLineY) && !compositeColumn.firstLineYDone) {
+                    if (!simulate)
+                        showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(item.listSymbol()), compositeColumn.leftX + listIndentation, compositeColumn.firstLineY, 0);
+                    compositeColumn.firstLineYDone = true;
+                }
+                if ((status & NO_MORE_TEXT) != 0) {
+                    compositeColumn = null;
+                    ++listIdx;
+                    yLine -= item.spacingAfter();
+                }
+                if ((status & NO_MORE_COLUMN) != 0) {
+                    return NO_MORE_COLUMN;
+                }
+            }
+            else if (element.type() == Element.PTABLE) {
+                if (yLine < minY || yLine > maxY)
+                    return NO_MORE_COLUMN;
+                PdfPTable table = (PdfPTable)element;
+                if (table.size() <= table.getHeaderRows()) {
+                    compositeElements.removeFirst();
+                    continue;
+                }
+                float yTemp = yLine;
+                float yLineWrite = yLine;
+                if (!firstPass && listIdx == 0) {
+                    yTemp -= table.spacingBefore();
+                    yLineWrite = yTemp;
+                }
+                currentLeading = 0;
+                if (yTemp < minY || yTemp > maxY)
+                    return NO_MORE_COLUMN;
+                float x1 = leftX;
+                float tableWidth;
+                if (table.isLockedWidth())
+                    tableWidth = table.getTotalWidth();
+                else {
+                    tableWidth = rectangularWidth * table.getWidthPercentage() / 100f;
+                    table.setTotalWidth(tableWidth);
+                }
+                int k;
+                boolean skipHeader = (!firstPass && table.isSkipFirstHeader() && listIdx <= table.getHeaderRows());
+                if (!skipHeader) {
+                    yTemp -= table.getHeaderHeight();
+                    if (yTemp < minY || yTemp > maxY) {
+                        if (firstPass) {
+                            compositeElements.removeFirst();
+                            continue;
+                        }
+                        return NO_MORE_COLUMN;
+                    }
+                }
+                if (listIdx < table.getHeaderRows())
+                    listIdx = table.getHeaderRows();
+                for (k = listIdx; k < table.size(); ++k) {
+                    float rowHeight = table.getRowHeight(k);
+                    if (yTemp - rowHeight < minY)
+                        break;
+                    yTemp -= rowHeight;
+                }
+                if (k < table.size()) {
+                    if (table.isSplitRows() && (!table.isSplitLate() || (k == listIdx && firstPass))) {
+                        if (!splittedRow) {
+                            splittedRow = true;
+                            table = new PdfPTable(table);
+                            compositeElements.set(0, table);
+                            ArrayList rows = table.getRows();
+                            for (int i = table.getHeaderRows(); i < listIdx; ++i)
+                                rows.set(i, null);
+                        }
+                        float h = yTemp - minY;
+                        PdfPRow newRow = table.getRow(k).splitRow(h);
+                        if (newRow == null) {
+                            if (k == listIdx)
+                                return NO_MORE_COLUMN;
+                        }
+                        else {
+                            yTemp = minY;
+                            table.getRows().add(++k, newRow);
+                        }
+                    }
+                    else if (!table.isSplitRows() && k == listIdx && firstPass) {
+                        compositeElements.removeFirst();
+                        splittedRow = false;
+                        continue;
+                    }
+                    else if (k == listIdx && !firstPass && (!table.isSplitRows() || table.isSplitLate())) {
+                            return NO_MORE_COLUMN;
+                    }
+                }
+                firstPass = false;
+                if (!simulate) {
+                    switch (table.getHorizontalAlignment()) {
+                        case Element.ALIGN_LEFT:
+                            break;
+                        case Element.ALIGN_RIGHT:
+                            x1 += rectangularWidth - tableWidth;
+                            break;
+                        default:
+                            x1 += (rectangularWidth - tableWidth) / 2f;
+                    }
+                    PdfPTable nt = PdfPTable.shallowCopy(table);
+                    ArrayList rows = table.getRows();
+                    ArrayList sub = nt.getRows();
+                    if (!skipHeader) {
+                        for (int j = 0; j < table.getHeaderRows(); ++j)
+                            sub.add(rows.get(j));
+                    }
+                    else
+                        nt.setHeaderRows(0);
+                    for (int j = listIdx; j < k; ++j)
+                        sub.add(rows.get(j));
+                    float rowHeight = 0;
+                    if (table.isExtendLastRow()) {
+                        PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
+                        rowHeight = last.getMaxHeights();
+                        last.setMaxHeights(yTemp - minY + rowHeight);
+                        yTemp = minY;
+                    }
+                    nt.writeSelectedRows(0, -1, x1, yLineWrite, canvas);
+                    if (table.isExtendLastRow()) {
+                        PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
+                        last.setMaxHeights(rowHeight);
+                    }
+                }
+                else if (table.isExtendLastRow() && minY > PdfPRow.BOTTOM_LIMIT)
+                    yTemp = minY;
+                yLine = yTemp;
+                if (k >= table.size()) {
+                    yLine -= table.spacingAfter();
+                    compositeElements.removeFirst();
+                    splittedRow = false;
+                    listIdx = 0;
+                }
+                else {
+                    if (splittedRow) {
+                        ArrayList rows = table.getRows();
+                        for (int i = listIdx; i < k; ++i)
+                            rows.set(i, null);
+                    }
+                    listIdx = k;
+                    return NO_MORE_COLUMN;
+                }
+            }
+            else if (element.type() == Element.GRAPHIC) {
+                if (!simulate) {
+                    Graphic gr = (Graphic)element;
+                    ByteBuffer bf = gr.getInternalBuffer();
+                    ByteBuffer store = null;
+                    if (bf.size() > 0) {
+                        store = new ByteBuffer();
+                        store.append(bf);
+                        bf.reset();
+                    }
+                    gr.processAttributes(leftX, minY, rightX, maxY, yLine);
+                    canvas.add(gr);
+                    bf.reset();
+                    if (store != null) {
+                        bf.append(store);
+                    }
+                }
+                compositeElements.removeFirst();
+            }
+            else
+                compositeElements.removeFirst();
+        }
+    }
+    
+    /**
+     * Gets the canvas.
+     * @return a PdfContentByte.
+     */
+    public PdfContentByte getCanvas() {
+        return canvas;
+    }
+    
+    /**
+     * Sets the canvas.
+     * @param canvas
+     */
+    public void setCanvas(PdfContentByte canvas) {
+        this.canvas = canvas;
+        if (compositeColumn != null)
+            compositeColumn.setCanvas(canvas);
+    }
+    
+    /**
+     * Checks if the element has a height of 0.
+     * @return true or false
+     */
+    public boolean zeroHeightElement() {
+        return composite == true && compositeElements.size() > 0 && ((Element)compositeElements.getFirst()).type() == Element.GRAPHIC;
+    }
+
+    /**
+     * Checks if UseAscender is enabled/disabled.
+     * @return true is the adjustment of the first line height is based on max ascender.
+     */
+    public boolean isUseAscender() {
+        return useAscender;
+    }
+
+    /**
+     * Enables/Disables adjustment of first line height based on max ascender.
+     * @param use enable adjustment if true
+     */
+    public void setUseAscender(boolean use) {
+        useAscender = use;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/DefaultFontMapper.java b/LibrarySource/com/lowagie/text/pdf/DefaultFontMapper.java
new file mode 100644
index 0000000..363a0b3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/DefaultFontMapper.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import headless.awt.Font;
+import com.lowagie.text.ExceptionConverter;
+import java.util.HashMap;
+import java.io.File;
+/** Default class to map awt fonts to BaseFont.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class DefaultFontMapper implements FontMapper {
+    
+    /** A representation of BaseFont parameters.
+     */    
+    public static class BaseFontParameters {
+        /** The font name.
+         */        
+        public String fontName;
+        /** The encoding for that font.
+         */        
+        public String encoding;
+        /** The embedding for that font.
+         */        
+        public boolean embedded;
+        /** Whether the font is cached of not.
+         */        
+        public boolean cached;
+        /** The font bytes for ttf and afm.
+         */        
+        public byte ttfAfm[];
+        /** The font bytes for pfb.
+         */        
+        public byte pfb[];
+        
+        /** Constructs default BaseFont parameters.
+         * @param fontName the font name or location
+         */        
+        public BaseFontParameters(String fontName) {
+            this.fontName = fontName;
+            encoding = BaseFont.CP1252;
+            embedded = BaseFont.EMBEDDED;
+            cached = BaseFont.CACHED;
+        }
+    }
+    
+    /** Maps aliases to names.
+     */    
+    private HashMap aliases = new HashMap();
+    /** Maps names to BaseFont parameters.
+     */    
+    private HashMap mapper = new HashMap();
+    /**
+     * Returns a BaseFont which can be used to represent the given AWT Font
+     *
+     * @param	font		the font to be converted
+     * @return	a BaseFont which has similar properties to the provided Font
+     */
+    
+    public BaseFont awtToPdf(Font font) {
+        try {
+            BaseFontParameters p = getBaseFontParameters(font.getFontName());
+            if (p != null)
+                return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
+            String fontKey = null;
+            String logicalName = font.getName();
+
+            if (logicalName.equalsIgnoreCase("DialogInput") || logicalName.equalsIgnoreCase("Monospaced") || logicalName.equalsIgnoreCase("Courier")) {
+
+                if (font.isItalic()) {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.COURIER_BOLDOBLIQUE;
+
+                    } else {
+                        fontKey = BaseFont.COURIER_OBLIQUE;
+                    }
+
+                } else {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.COURIER_BOLD;
+
+                    } else {
+                        fontKey = BaseFont.COURIER;
+                    }
+                }
+
+            } else if (logicalName.equalsIgnoreCase("Serif") || logicalName.equalsIgnoreCase("TimesRoman")) {
+
+                if (font.isItalic()) {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.TIMES_BOLDITALIC;
+
+                    } else {
+                        fontKey = BaseFont.TIMES_ITALIC;
+                    }
+
+                } else {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.TIMES_BOLD;
+
+                    } else {
+                        fontKey = BaseFont.TIMES_ROMAN;
+                    }
+                }
+
+            } else {  // default, this catches Dialog and SansSerif
+
+                if (font.isItalic()) {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.HELVETICA_BOLDOBLIQUE;
+
+                    } else {
+                        fontKey = BaseFont.HELVETICA_OBLIQUE;
+                    }
+
+                } else {
+                    if (font.isBold()) {
+                        fontKey = BaseFont.HELVETICA_BOLD;
+                    } else {
+                        fontKey = BaseFont.HELVETICA;
+                    }
+                }
+            }
+            return BaseFont.createFont(fontKey, BaseFont.CP1252, false);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /**
+     * Returns an AWT Font which can be used to represent the given BaseFont
+     *
+     * @param	font		the font to be converted
+     * @param	size		the desired point size of the resulting font
+     * @return	a Font which has similar properties to the provided BaseFont
+     */
+    
+    public Font pdfToAwt(BaseFont font, int size) {
+        String names[][] = font.getFullFontName();
+        if (names.length == 1)
+            return new Font(names[0][3], 0, size);
+        String name10 = null;
+        String name3x = null;
+        for (int k = 0; k < names.length; ++k) {
+            String name[] = names[k];
+            if (name[0].equals("1") && name[1].equals("0"))
+                name10 = name[3];
+            else if (name[2].equals("1033")) {
+                name3x = name[3];
+                break;
+            }
+        }
+        String finalName = name3x;
+        if (finalName == null)
+            finalName = name10;
+        if (finalName == null)
+            finalName = names[0][3];
+        return new Font(finalName, 0, size);
+    }
+    
+    /** Maps a name to a BaseFont parameter.
+     * @param awtName the name
+     * @param parameters the BaseFont parameter
+     */    
+    public void putName(String awtName, BaseFontParameters parameters) {
+        mapper.put(awtName, parameters);
+    }
+    
+    /** Maps an alias to a name.
+     * @param alias the alias
+     * @param awtName the name
+     */    
+    public void putAlias(String alias, String awtName) {
+        aliases.put(alias, awtName);
+    }
+    
+    /** Looks for a BaseFont parameter associated with a name.
+     * @param name the name
+     * @return the BaseFont parameter or <CODE>null</CODE> if not found.
+     */    
+    public BaseFontParameters getBaseFontParameters(String name) {
+        String alias = (String)aliases.get(name);
+        if (alias == null)
+            return (BaseFontParameters)mapper.get(name);
+        BaseFontParameters p = (BaseFontParameters)mapper.get(alias);
+        if (p == null)
+            return (BaseFontParameters)mapper.get(name);
+        else
+            return p;
+    }
+    
+    /**
+     * Inserts the names in this map.
+     * @param allNames the returned value of calling {@link BaseFont#getAllFontNames(String, String, byte[])}
+     * @param path the full path to the font
+     */    
+    public void insertNames(Object allNames[], String path) {
+        String names[][] = (String[][])allNames[2];
+        String main = null;
+        for (int k = 0; k < names.length; ++k) {
+            String name[] = names[k];
+            if (name[2].equals("1033")) {
+                main = name[3];
+                break;
+            }
+        }
+        if (main == null)
+            main = names[0][3];
+        BaseFontParameters p = new BaseFontParameters(path);
+        mapper.put(main, p);
+        for (int k = 0; k < names.length; ++k) {
+            aliases.put(names[k][3], main);
+        }
+        aliases.put((String)allNames[0], main);
+    }
+    
+    /** Inserts all the fonts recognized by iText in the
+     * <CODE>directory</CODE> into the map. The encoding
+     * will be <CODE>BaseFont.CP1252</CODE> but can be
+     * changed later.
+     * @param dir the directory to scan
+     * @return the number of files processed
+     */    
+    public int insertDirectory(String dir) {
+        File file = new File(dir);
+        if (!file.exists() || !file.isDirectory())
+            return 0;
+        File files[] = file.listFiles();
+        int count = 0;
+        for (int k = 0; k < files.length; ++k) {
+            file = files[k];
+            String name = file.getPath().toLowerCase();
+            try {
+                if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm")) {
+                    Object allNames[] = BaseFont.getAllFontNames(file.getPath(), BaseFont.CP1252, null);
+                    insertNames(allNames, file.getPath());
+                    ++count;
+                }
+                else if (name.endsWith(".ttc")) {
+                    String ttcs[] = BaseFont.enumerateTTCNames(file.getPath());
+                    for (int j = 0; j < ttcs.length; ++j) {
+                        String nt = file.getPath() + "," + j;
+                        Object allNames[] = BaseFont.getAllFontNames(nt, BaseFont.CP1252, null);
+                        insertNames(allNames, nt);
+                    }
+                    ++count;
+                }
+            }
+            catch (Exception e) {
+            }
+        }
+        return count;
+    }
+    
+    public HashMap getMapper() {
+        return mapper;
+    }
+    
+    public HashMap getAliases() {
+        return aliases;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/DocumentFont.java b/LibrarySource/com/lowagie/text/pdf/DocumentFont.java
new file mode 100644
index 0000000..23de88d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/DocumentFont.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ *
+ * @author  psoares
+ */
+public class DocumentFont extends BaseFont {
+    
+    String fontName;
+    PRIndirectReference refFont;
+    PdfDictionary font;
+    IntHashtable uni2byte = new IntHashtable();
+    float Ascender = 800;
+    float CapHeight = 700;
+    float Descender = -200;
+    float ItalicAngle = 0;
+    float llx = -50;
+    float lly = -200;
+    float urx = 100;
+    float ury = 900;
+    
+    BaseFont cjkMirror;
+    
+    String cjkNames[] = {"HeiseiMin-W3", "HeiseiKakuGo-W5", "STSong-Light", "MHei-Medium",
+        "MSung-Light", "HYGoThic-Medium", "HYSMyeongJo-Medium", "MSungStd-Light", "STSongStd-Light",
+        "HYSMyeongJoStd-Medium", "KozMinPro-Regular"};
+        
+    String cjkEncs[] = {"UniJIS-UCS2-H", "UniJIS-UCS2-H", "UniGB-UCS2-H", "UniCNS-UCS2-H",
+        "UniCNS-UCS2-H", "UniKS-UCS2-H", "UniKS-UCS2-H", "UniCNS-UCS2-H", "UniGB-UCS2-H",
+        "UniKS-UCS2-H", "UniJIS-UCS2-H"};
+        
+    static final int stdEnc[] = {
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+        32,33,34,35,36,37,38,8217,40,41,42,43,44,45,46,47,
+        48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+        64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+        80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+        8216,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
+        112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,0,
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+        0,161,162,163,8260,165,402,167,164,39,8220,171,8249,8250,64257,64258,
+        0,8211,8224,8225,183,0,182,8226,8218,8222,8221,187,8230,8240,0,191,
+        0,96,180,710,732,175,728,729,168,0,730,184,0,733,731,711,
+        8212,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+        0,198,0,170,0,0,0,0,321,216,338,186,0,0,0,0,
+        0,230,0,0,0,305,0,0,322,248,339,223,0,0,0,0};
+
+    /** Creates a new instance of DocumentFont */
+    DocumentFont(PRIndirectReference refFont) {
+        encoding = "";
+        fontSpecific = false;
+        this.refFont = refFont;
+        fontType = FONT_TYPE_DOCUMENT;
+        font = (PdfDictionary)PdfReader.getPdfObject(refFont);
+        fontName = PdfName.decodeName(((PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT))).toString());
+        PdfName subType = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
+        if (PdfName.TYPE1.equals(subType) || PdfName.TRUETYPE.equals(subType))
+            doType1TT();
+        else {
+            for (int k = 0; k < cjkNames.length; ++k) {
+                if (fontName.startsWith(cjkNames[k])) {
+                    fontName = cjkNames[k];
+                    try {
+                        cjkMirror = BaseFont.createFont(fontName, cjkEncs[k], false);
+                    }
+                    catch (Exception e) {
+                        throw new ExceptionConverter(e);
+                    }
+                    return;
+                }
+            }
+        }
+    }
+    
+    public void doType1TT() {
+        PdfObject enc = PdfReader.getPdfObject(font.get(PdfName.ENCODING));
+        if (enc == null)
+            fillEncoding(null);
+        else {
+            if (enc.isName())
+                fillEncoding((PdfName)enc);
+            else {
+                PdfDictionary encDic = (PdfDictionary)enc;
+                enc = PdfReader.getPdfObject(encDic.get(PdfName.BASEENCODING));
+                if (enc == null)
+                    fillEncoding(null);
+                else
+                    fillEncoding((PdfName)enc);
+                PdfArray diffs = (PdfArray)PdfReader.getPdfObject(encDic.get(PdfName.DIFFERENCES));
+                if (diffs != null) {
+                    ArrayList dif = diffs.getArrayList();
+                    int currentNumber = 0;
+                    for (int k = 0; k < dif.size(); ++k) {
+                        PdfObject obj = (PdfObject)dif.get(k);
+                        if (obj.isNumber())
+                            currentNumber = ((PdfNumber)obj).intValue();
+                        else {
+                            int c[] = GlyphList.nameToUnicode(PdfName.decodeName(((PdfName)obj).toString()));
+                            if (c != null && c.length > 0)
+                                uni2byte.put(c[0], currentNumber);
+                            ++currentNumber;
+                        }
+                    }
+                }
+            }
+        }
+        PdfArray newWidths = (PdfArray)PdfReader.getPdfObject(font.get(PdfName.WIDTHS));
+        PdfNumber first = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.FIRSTCHAR));
+        PdfNumber last = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.LASTCHAR));
+        if (BuiltinFonts14.containsKey(fontName)) {
+            BaseFont bf;
+            try {
+                bf = BaseFont.createFont(fontName, WINANSI, false);
+            }
+            catch (Exception e) {
+                throw new ExceptionConverter(e);
+            }
+            int e[] = uni2byte.toOrderedKeys();
+            for (int k = 0; k < e.length; ++k) {
+                int n = uni2byte.get(e[k]);
+                widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k]));
+            }
+            Ascender = bf.getFontDescriptor(ASCENT, 1000);
+            CapHeight = bf.getFontDescriptor(CAPHEIGHT, 1000);
+            Descender = bf.getFontDescriptor(DESCENT, 1000);
+            ItalicAngle = bf.getFontDescriptor(ITALICANGLE, 1000);
+            llx = bf.getFontDescriptor(BBOXLLX, 1000);
+            lly = bf.getFontDescriptor(BBOXLLY, 1000);
+            urx = bf.getFontDescriptor(BBOXURX, 1000);
+            ury = bf.getFontDescriptor(BBOXURY, 1000);
+        }
+        if (first != null && last != null && newWidths != null) {
+            int f = ((PdfNumber)first).intValue();
+            ArrayList ar = ((PdfArray)newWidths).getArrayList();
+            for (int k = 0; k < ar.size(); ++k) {
+                widths[f + k] = ((PdfNumber)ar.get(k)).intValue();
+            }
+        }
+        fillFontDesc();
+    }
+    
+    void fillFontDesc() {
+        PdfDictionary fontDesc = (PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONTDESCRIPTOR));
+        if (fontDesc == null)
+            return;
+        PdfNumber v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ASCENT));
+        if (v != null)
+            Ascender = v.floatValue();
+        v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.CAPHEIGHT));
+        if (v != null)
+            CapHeight = v.floatValue();
+        v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.DESCENT));
+        if (v != null)
+            Descender = v.floatValue();
+        v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ITALICANGLE));
+        if (v != null)
+            ItalicAngle = v.floatValue();
+        PdfArray bbox = (PdfArray)PdfReader.getPdfObject(fontDesc.get(PdfName.FONTBBOX));
+        if (bbox != null) {
+            ArrayList ar = bbox.getArrayList();
+            llx = ((PdfNumber)ar.get(0)).floatValue();
+            lly = ((PdfNumber)ar.get(1)).floatValue();
+            urx = ((PdfNumber)ar.get(2)).floatValue();
+            ury = ((PdfNumber)ar.get(3)).floatValue();
+            if (llx > urx) {
+                float t = llx;
+                llx = urx;
+                urx = t;
+            }
+            if (lly > ury) {
+                float t = lly;
+                lly = ury;
+                ury = t;
+            }
+        }
+    }
+    
+    void fillEncoding(PdfName encoding) {
+        if (PdfName.MAC_ROMAN_ENCODING.equals(encoding) || PdfName.WIN_ANSI_ENCODING.equals(encoding)) {
+            byte b[] = new byte[256];
+            for (int k = 0; k < 256; ++k)
+                b[k] = (byte)k;
+            String enc = WINANSI;
+            if (PdfName.MAC_ROMAN_ENCODING.equals(encoding))
+                enc = MACROMAN;
+            String cv = PdfEncodings.convertToString(b, enc);
+            char arr[] = cv.toCharArray();
+            for (int k = 0; k < 256; ++k)
+                uni2byte.put(arr[k], k);
+        }
+        else {
+            for (int k = 0; k < 256; ++k)
+                uni2byte.put(stdEnc[k], k);
+        }
+    }
+    
+    /** Gets the family name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the family name of the font
+     *
+     */
+    public String[][] getFamilyFontName() {
+        return null;
+    }
+    
+    /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
+     * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>,
+     * <CODE>ITALICANGLE</CODE>, <CODE>BBOXLLX</CODE>, <CODE>BBOXLLY</CODE>, <CODE>BBOXURX</CODE>
+     * and <CODE>BBOXURY</CODE>.
+     * @param key the parameter to be extracted
+     * @param fontSize the font size in points
+     * @return the parameter in points
+     *
+     */
+    public float getFontDescriptor(int key, float fontSize) {
+        if (cjkMirror != null)
+            return cjkMirror.getFontDescriptor(key, fontSize);
+        switch (key) {
+            case AWT_ASCENT:
+            case ASCENT:
+                return Ascender * fontSize / 1000;
+            case CAPHEIGHT:
+                return CapHeight * fontSize / 1000;
+            case AWT_DESCENT:
+            case DESCENT:
+                return Descender * fontSize / 1000;
+            case ITALICANGLE:
+                return ItalicAngle;
+            case BBOXLLX:
+                return llx * fontSize / 1000;
+            case BBOXLLY:
+                return lly * fontSize / 1000;
+            case BBOXURX:
+                return urx * fontSize / 1000;
+            case BBOXURY:
+                return ury * fontSize / 1000;
+            case AWT_LEADING:
+                return 0;
+            case AWT_MAXADVANCE:
+                return (urx - llx) * fontSize / 1000;
+        }
+        return 0;
+    }
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the full name of the font
+     *
+     */
+    public String[][] getFullFontName() {
+        return null;
+    }
+    
+    /** Gets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @return the kerning to be applied
+     *
+     */
+    public int getKerning(char char1, char char2) {
+        return 0;
+    }
+    
+    /** Gets the postscript font name.
+     * @return the postscript font name
+     *
+     */
+    public String getPostscriptFontName() {
+        return fontName;
+    }
+    
+    /** Gets the width from the font according to the Unicode char <CODE>c</CODE>
+     * or the <CODE>name</CODE>. If the <CODE>name</CODE> is null it's a symbolic font.
+     * @param c the unicode char
+     * @param name the glyph name
+     * @return the width of the char
+     *
+     */
+    int getRawWidth(int c, String name) {
+        return 0;
+    }
+    
+    /** Checks if the font has any kerning pairs.
+     * @return <CODE>true</CODE> if the font has any kerning pairs
+     *
+     */
+    public boolean hasKernPairs() {
+        return false;
+    }
+    
+    /** Outputs to the writer the font dictionaries and streams.
+     * @param writer the writer for this document
+     * @param ref the font indirect reference
+     * @param params several parameters that depend on the font type
+     * @throws IOException on error
+     * @throws DocumentException error in generating the object
+     *
+     */
+    void writeFont(PdfWriter writer, PdfIndirectReference ref, Object[] params) throws DocumentException, IOException {
+    }
+
+    public int getWidth(String text) {
+        if (cjkMirror != null)
+            return cjkMirror.getWidth(text);
+        else
+            return super.getWidth(text);
+    }
+    
+    byte[] convertToBytes(String text) {
+        if (cjkMirror != null)
+            return PdfEncodings.convertToBytes(text, CJKFont.CJK_ENCODING);
+        else {
+            char cc[] = text.toCharArray();
+            byte b[] = new byte[cc.length];
+            for (int k = 0; k < cc.length; ++k)
+                b[k] = (byte)uni2byte.get(cc[k]);
+            return b;
+        }
+    }
+    
+    PdfIndirectReference getIndirectReference() {
+        return refFont;
+    }
+    
+    public boolean charExists(char c) {
+        if (cjkMirror != null)
+            return cjkMirror.charExists(c);
+        else
+            return super.charExists(c);
+    }
+    
+    /**
+     * Sets the font name that will appear in the pdf font dictionary.
+     * It does nothing in this case as the font is already in the document.
+     * @param name the new font name
+     */    
+    public void setPostscriptFontName(String name) {
+    }
+    
+    public boolean setKerning(char char1, char char2, int kern) {
+        return false;
+    }
+    
+    public int[] getCharBBox(char c) {
+        return null;
+    }
+    
+    protected int[] getRawCharBBox(int c, String name) {
+        return null;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/EnumerateTTC.java b/LibrarySource/com/lowagie/text/pdf/EnumerateTTC.java
new file mode 100644
index 0000000..517fe23
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/EnumerateTTC.java
@@ -0,0 +1,119 @@
+/*
+ * $Id: EnumerateTTC.java,v 1.13 2002/06/20 13:04:40 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import com.lowagie.text.DocumentException;
+/** Enumerates all the fonts inside a True Type Collection.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+class EnumerateTTC extends TrueTypeFont{
+
+    protected String[] names;
+
+    EnumerateTTC(String ttcFile) throws DocumentException, IOException {
+        fileName = ttcFile;
+        rf = new RandomAccessFileOrArray(ttcFile);
+        findNames();
+    }
+
+    EnumerateTTC(byte ttcArray[]) throws DocumentException, IOException {
+        fileName = "Byte array TTC";
+        rf = new RandomAccessFileOrArray(ttcArray);
+        findNames();
+    }
+    
+    void findNames() throws DocumentException, IOException {
+        tables = new HashMap();
+        
+        try {
+            String mainTag = readStandardString(4);
+            if (!mainTag.equals("ttcf"))
+                throw new DocumentException(fileName + " is not a valid TTC file.");
+            rf.skipBytes(4);
+            int dirCount = rf.readInt();
+            names = new String[dirCount];
+            int dirPos = rf.getFilePointer();
+            for (int dirIdx = 0; dirIdx < dirCount; ++dirIdx) {
+                tables.clear();
+                rf.seek(dirPos);
+                rf.skipBytes(dirIdx * 4);
+                directoryOffset = rf.readInt();
+                rf.seek(directoryOffset);
+                if (rf.readInt() != 0x00010000)
+                    throw new DocumentException(fileName + " is not a valid TTF file.");
+                int num_tables = rf.readUnsignedShort();
+                rf.skipBytes(6);
+                for (int k = 0; k < num_tables; ++k) {
+                    String tag = readStandardString(4);
+                    rf.skipBytes(4);
+                    int table_location[] = new int[2];
+                    table_location[0] = rf.readInt();
+                    table_location[1] = rf.readInt();
+                    tables.put(tag, table_location);
+                }
+                names[dirIdx] = getBaseFont();
+            }
+        }
+        finally {
+            if (rf != null)
+                rf.close();
+        }
+    }
+    
+    String[] getNames() {
+        return names;
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/ExtendedColor.java b/LibrarySource/com/lowagie/text/pdf/ExtendedColor.java
new file mode 100644
index 0000000..2e4fc57
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ExtendedColor.java
@@ -0,0 +1,122 @@
+/*
+ * $Id: ExtendedColor.java,v 1.43 2005/03/29 14:08:15 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+/**
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class ExtendedColor extends Color{
+    
+	/** a type of extended color. */
+    public static final int TYPE_RGB = 0;
+    /** a type of extended color. */
+    public static final int TYPE_GRAY = 1;
+    /** a type of extended color. */
+    public static final int TYPE_CMYK = 2;
+    /** a type of extended color. */
+    public static final int TYPE_SEPARATION = 3;
+    /** a type of extended color. */
+    public static final int TYPE_PATTERN = 4;
+    /** a type of extended color. */
+    public static final int TYPE_SHADING = 5;
+    
+    protected int type;
+
+    /**
+     * Constructs an extended color of a certain type.
+     * @param type
+     */
+    public ExtendedColor(int type) {
+        super(0, 0, 0);
+        this.type = type;
+    }
+    
+    /**
+     * Constructs an extended color of a certain type and a certain color.
+     * @param type
+     * @param red
+     * @param green
+     * @param blue
+     */
+    public ExtendedColor(int type, float red, float green, float blue) {
+        super(normalize(red), normalize(green), normalize(blue));
+        this.type = type;
+    }
+    
+    /**
+     * Gets the type of this color.
+     * @return one of the types (see constants)
+     */
+    public int getType() {
+        return type;
+    }
+    
+    /**
+     * Gets the type of a given color.
+     * @param color
+     * @return one of the types (see constants)
+     */
+    public static int getType(Color color) {
+        if (color instanceof ExtendedColor)
+            return ((ExtendedColor)color).getType();
+        return TYPE_RGB;
+    }
+
+    static final float normalize(float value) {
+        if (value < 0)
+            return 0;
+        if (value > 1)
+            return 1;
+        return value;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/ExtraEncoding.java b/LibrarySource/com/lowagie/text/pdf/ExtraEncoding.java
new file mode 100644
index 0000000..cbdb4b6
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ExtraEncoding.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * Classes implementing this interface can create custom encodings or
+ * replace existing ones. It is used in the context of <code>PdfEncoding</code>.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface ExtraEncoding {
+    
+    /**
+     * Converts an Unicode string to a byte array according to some encoding.
+     * @param text the Unicode string
+     * @param encoding the requested encoding. It's mainly of use if the same class
+     * supports more than one encoding.
+     * @return the conversion or <CODE>null</CODE> if no conversion is supported
+     */    
+    public byte[] charToByte(String text, String encoding);
+    
+    /**
+     * Converts a byte array to an Unicode string according to some encoding.
+     * @param b the input byte array
+     * @param encoding the requested encoding. It's mainly of use if the same class
+     * supports more than one encoding.
+     * @return the conversion or <CODE>null</CODE> if no conversion is supported
+     */
+    public String byteToChar(byte b[], String encoding);   
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/FdfReader.java b/LibrarySource/com/lowagie/text/pdf/FdfReader.java
new file mode 100644
index 0000000..f97129a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/FdfReader.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.net.URL;
+/** Reads an FDF form and makes the fields available
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class FdfReader extends PdfReader {
+    
+    HashMap fields;
+    String fileSpec;
+    PdfName encoding;
+    
+    /** Reads an FDF form.
+     * @param filename the file name of the form
+     * @throws IOException on error
+     */    
+    public FdfReader(String filename) throws IOException {
+        super(filename);
+    }
+    
+    /** Reads an FDF form.
+     * @param pdfIn the byte array with the form
+     * @throws IOException on error
+     */    
+    public FdfReader(byte pdfIn[]) throws IOException {
+        super(pdfIn);
+    }
+    
+    /** Reads an FDF form.
+     * @param url the URL of the document
+     * @throws IOException on error
+     */    
+    public FdfReader(URL url) throws IOException {
+        super(url);
+    }
+    
+    /** Reads an FDF form.
+     * @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
+     * end but is not closed
+     * @throws IOException on error
+     */    
+    public FdfReader(InputStream is) throws IOException {
+        super(is);
+    }
+    
+    protected void readPdf() throws IOException {
+        fields = new HashMap();
+        try {
+            tokens.checkFdfHeader();
+            rebuildXref();
+            readDocObj();
+        }
+        finally {
+            try {
+                tokens.close();
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }
+        }
+        readFields();
+    }
+    
+    protected void kidNode(PdfDictionary merged, String name) {
+        PdfArray kids = (PdfArray)getPdfObject(merged.get(PdfName.KIDS));
+        if (kids == null || kids.getArrayList().size() == 0) {
+            if (name.length() > 0)
+                name = name.substring(1);
+            fields.put(name, merged);
+        }
+        else {
+            merged.remove(PdfName.KIDS);
+            ArrayList ar = kids.getArrayList();
+            for (int k = 0; k < ar.size(); ++k) {
+                PdfDictionary dic = new PdfDictionary();
+                dic.merge(merged);
+                PdfDictionary newDic = (PdfDictionary)getPdfObject((PdfObject)ar.get(k));
+                PdfString t = (PdfString)getPdfObject(newDic.get(PdfName.T));
+                String newName = name;
+                if (t != null)
+                    newName += "." + t.toUnicodeString();
+                dic.merge(newDic);
+                dic.remove(PdfName.T);
+                kidNode(dic, newName);
+            }
+        }
+    }
+    
+    protected void readFields() throws IOException {
+        catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
+        PdfDictionary fdf = (PdfDictionary)getPdfObject(catalog.get(PdfName.FDF));
+        PdfString fs = (PdfString)getPdfObject(fdf.get(PdfName.F));
+        if (fs != null)
+            fileSpec = fs.toUnicodeString();
+        PdfArray fld = (PdfArray)getPdfObject(fdf.get(PdfName.FIELDS));
+        if (fld == null)
+            return;
+        encoding = (PdfName)getPdfObject(fdf.get(PdfName.ENCODING));
+        PdfDictionary merged = new PdfDictionary();
+        merged.put(PdfName.KIDS, fld);
+        kidNode(merged, "");
+    }
+
+    /** Gets all the fields. The map is keyed by the fully qualified
+     * field name and the value is a merged <CODE>PdfDictionary</CODE>
+     * with the field content.
+     * @return all the fields
+     */    
+    public HashMap getFields() {
+        return fields;
+    }
+    
+    /** Gets the field dictionary.
+     * @param name the fully qualified field name
+     * @return the field dictionary
+     */    
+    public PdfDictionary getField(String name) {
+        return (PdfDictionary)fields.get(name);
+    }
+    
+    /** Gets the field value or <CODE>null</CODE> if the field does not
+     * exist or has no value defined.
+     * @param name the fully qualified field name
+     * @return the field value or <CODE>null</CODE>
+     */    
+    public String getFieldValue(String name) {
+        PdfDictionary field = (PdfDictionary)fields.get(name);
+        if (field == null)
+            return null;
+        PdfObject v = getPdfObject(field.get(PdfName.V));
+        if (v == null)
+            return null;
+        if (v.isName())
+            return PdfName.decodeName(((PdfName)v).toString());
+        else if (v.isString()) {
+            PdfString vs = (PdfString)v;
+            if (encoding == null || vs.getEncoding() != null)
+                return vs.toUnicodeString();
+            byte b[] = vs.getBytes();
+            if (b.length >= 2 && b[0] == (byte)254 && b[1] == (byte)255)
+                return vs.toUnicodeString();
+            try {
+                if (encoding.equals(PdfName.SHIFT_JIS))
+                    return new String(b, "SJIS");
+                else if (encoding.equals(PdfName.UHC))
+                    return new String(b, "MS949");
+                else if (encoding.equals(PdfName.GBK))
+                    return new String(b, "GBK");
+                else if (encoding.equals(PdfName.BIGFIVE))
+                    return new String(b, "Big5");
+            }
+            catch (Exception e) {
+            }
+            return vs.toUnicodeString();
+        }
+        return null;
+    }
+    
+    /** Gets the PDF file specification contained in the FDF.
+     * @return the PDF file specification contained in the FDF
+     */    
+    public String getFileSpec() {
+        return fileSpec;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/FontDetails.java b/LibrarySource/com/lowagie/text/pdf/FontDetails.java
new file mode 100644
index 0000000..39dc804
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/FontDetails.java
@@ -0,0 +1,279 @@
+/*
+ * $Id: FontDetails.java,v 1.12 2002/06/18 13:59:40 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+import java.util.HashMap;
+import java.io.UnsupportedEncodingException;
+/** Each font in the document will have an instance of this class
+ * where the characters used will be represented.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+class FontDetails {
+    
+    /** The indirect reference to this font
+     */    
+    PdfIndirectReference indirectReference;
+    /** The font name that appears in the document body stream
+     */    
+    PdfName fontName;
+    /** The font
+     */    
+    BaseFont baseFont;
+    /** The font if its an instance of <CODE>TrueTypeFontUnicode</CODE>
+     */    
+    TrueTypeFontUnicode ttu;
+
+    CJKFont cjkFont;
+    /** The array used with single byte encodings
+     */    
+    byte shortTag[];
+    /** The map used with double byte encodings. The key is Integer(glyph) and the
+     * value is int[]{glyph, width, Unicode code}
+     */    
+    HashMap longTag;
+    
+    IntHashtable cjkTag;
+    /** The font type
+     */    
+    int fontType;
+    /** <CODE>true</CODE> if the font is symbolic
+     */    
+    boolean symbolic;
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document.
+     */
+    protected boolean subset = true;
+    /** Each font used in a document has an instance of this class.
+     * This class stores the characters used in the document and other
+     * specifics unique to the current working document.
+     * @param fontName the font name
+     * @param indirectReference the indirect reference to the font
+     * @param baseFont the <CODE>BaseFont</CODE>
+     */
+    FontDetails(PdfName fontName, PdfIndirectReference indirectReference, BaseFont baseFont) {
+        this.fontName = fontName;
+        this.indirectReference = indirectReference;
+        this.baseFont = baseFont;
+        fontType = baseFont.getFontType();
+        switch (fontType) {
+            case BaseFont.FONT_TYPE_T1:
+            case BaseFont.FONT_TYPE_TT:
+                shortTag = new byte[256];
+                break;
+            case BaseFont.FONT_TYPE_CJK:
+                cjkTag = new IntHashtable();
+                cjkFont = (CJKFont)baseFont;
+                break;
+            case BaseFont.FONT_TYPE_TTUNI:
+                longTag = new HashMap();
+                ttu = (TrueTypeFontUnicode)baseFont;
+                symbolic = baseFont.isFontSpecific();
+                break;
+        }
+    }
+    
+    /** Gets the indirect reference to this font.
+     * @return the indirect reference to this font
+     */    
+    PdfIndirectReference getIndirectReference() {
+        return indirectReference;
+    }
+    
+    /** Gets the font name as it appears in the document body.
+     * @return the font name
+     */    
+    PdfName getFontName() {
+        return fontName;
+    }
+    
+    /** Gets the <CODE>BaseFont</CODE> of this font.
+     * @return the <CODE>BaseFont</CODE> of this font
+     */    
+    BaseFont getBaseFont() {
+        return baseFont;
+    }
+    
+    /** Converts the text into bytes to be placed in the document.
+     * The conversion is done according to the font and the encoding and the characters
+     * used are stored.
+     * @param text the text to convert
+     * @return the conversion
+     */    
+    byte[] convertToBytes(String text) {
+        byte b[] = null;
+        switch (fontType) {
+            case BaseFont.FONT_TYPE_T1:
+            case BaseFont.FONT_TYPE_TT: {
+                b = baseFont.convertToBytes(text);
+                int len = b.length;
+                for (int k = 0; k < len; ++k)
+                    shortTag[((int)b[k]) & 0xff] = 1;
+                break;
+            }
+            case BaseFont.FONT_TYPE_CJK: {
+                int len = text.length();
+                for (int k = 0; k < len; ++k)
+                    cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
+                b = baseFont.convertToBytes(text);
+                break;
+            }
+            case BaseFont.FONT_TYPE_DOCUMENT: {
+                b = baseFont.convertToBytes(text);
+                break;
+            }
+            case BaseFont.FONT_TYPE_TTUNI: {
+                try {
+                    int len = text.length();
+                    int metrics[] = null;
+                    char glyph[] = new char[len];
+                    int i = 0;
+                    if (symbolic) {
+                        b = PdfEncodings.convertToBytes(text, "symboltt");
+                        len = b.length;
+                        for (int k = 0; k < len; ++k) {
+                            metrics = ttu.getMetricsTT(b[k] & 0xff);
+                            if (metrics == null)
+                                continue;
+                            longTag.put(new Integer(metrics[0]), new int[]{metrics[0], metrics[1], ttu.getUnicodeDifferences(b[k] & 0xff)});
+                            glyph[i++] = (char)metrics[0];
+                        }
+                    }
+                    else {
+                        for (int k = 0; k < len; ++k) {
+                            char c = text.charAt(k);
+                            metrics = ttu.getMetricsTT(c);
+                            if (metrics == null)
+                                continue;
+                            int m0 = metrics[0];
+                            Integer gl = new Integer(m0);
+                            if (!longTag.containsKey(gl))
+                                longTag.put(gl, new int[]{m0, metrics[1], c});
+                            glyph[i++] = (char)m0;
+                        }
+                    }
+                    String s = new String(glyph, 0, i);
+                    b = s.getBytes(CJKFont.CJK_ENCODING);
+                }
+                catch (UnsupportedEncodingException e) {
+                    throw new ExceptionConverter(e);
+                }
+                break;
+            }
+        }
+        return b;
+    }
+    
+    /** Writes the font definition to the document.
+     * @param writer the <CODE>PdfWriter</CODE> of this document
+     */    
+    void writeFont(PdfWriter writer) {
+        try {
+            switch (fontType) {
+                case BaseFont.FONT_TYPE_T1:
+                case BaseFont.FONT_TYPE_TT: {
+                    int firstChar;
+                    int lastChar;
+                    if (subset) {
+                        for (firstChar = 0; firstChar < 256; ++firstChar) {
+                            if (shortTag[firstChar] != 0)
+                                break;
+                        }
+                        for (lastChar = 255; lastChar >= firstChar; --lastChar) {
+                            if (shortTag[lastChar] != 0)
+                                break;
+                        }
+                        if (firstChar > 255) {
+                            firstChar = 255;
+                            lastChar = 255;
+                        }
+                    }
+                    else {
+                        for (int k = 0; k < shortTag.length; ++k)
+                            shortTag[k] = 1;
+                        firstChar = 0;
+                        lastChar = shortTag.length - 1;
+                    }
+                    baseFont.writeFont(writer, indirectReference, new Object[]{new Integer(firstChar), new Integer(lastChar), shortTag});
+                    break;
+                }
+                case BaseFont.FONT_TYPE_CJK:
+                    baseFont.writeFont(writer, indirectReference, new Object[]{cjkTag});
+                    break;
+                case BaseFont.FONT_TYPE_TTUNI:
+                    baseFont.writeFont(writer, indirectReference, new Object[]{longTag});
+                    break;
+            }
+        }
+        catch(Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document.
+     * @return <CODE>false</CODE> to include all the glyphs and widths.
+     */
+    public boolean isSubset() {
+        return subset;
+    }
+    
+    /** Indicates if all the glyphs and widths for that particular
+     * encoding should be included in the document. Set to <CODE>false</CODE>
+     * to include all.
+     * @param subset new value of property subset
+     */
+    public void setSubset(boolean subset) {
+        this.subset = subset;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/FontMapper.java b/LibrarySource/com/lowagie/text/pdf/FontMapper.java
new file mode 100644
index 0000000..2d6b197
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/FontMapper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002 by Jeremy Bowman <bowmanjm at attbi.com>.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Font;
+
+/**
+ * A FontMapper implementation handles mappings between AWT Fonts and PDF
+ * fonts. An interface is used instead of a fixed class because there isn't
+ * an exact correlation between the font types, so each application is free
+ * to define a mapping which is appropriate for it.
+ */
+
+public interface FontMapper {
+
+    /**
+     * Returns a BaseFont which can be used to represent the given AWT Font
+     *
+     * @param	font		the font to be converted
+     * @return	a BaseFont which has similar properties to the provided Font
+     */
+
+    public BaseFont awtToPdf(Font font);
+
+    /**
+     * Returns an AWT Font which can be used to represent the given BaseFont
+     *
+     * @param	font		the font to be converted
+     * @param	size		the desired point size of the resulting font
+     * @return	a Font which has similar properties to the provided BaseFont
+     */
+
+    public Font pdfToAwt(BaseFont font, int size);
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/FontSelector.java b/LibrarySource/com/lowagie/text/pdf/FontSelector.java
new file mode 100644
index 0000000..f10215f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/FontSelector.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import com.lowagie.text.*;
+
+/** Selects the appropriate fonts that contain the glyphs needed to
+ * render text correctly. The fonts are checked in order until the 
+ * character is found.
+ * <p>
+ * The built in fonts "Symbol" and "ZapfDingbats", if used, have a special encoding
+ * to allow the characters to be referred by Unicode.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class FontSelector {
+    
+    protected ArrayList fonts = new ArrayList();
+
+    /**
+     * Adds a <CODE>Font</CODE> to be searched for valid characters.
+     * @param font the <CODE>Font</CODE>
+     */    
+    public void addFont(Font font) {
+        if (font.getBaseFont() != null) {
+            fonts.add(font);
+            return;
+        }
+        BaseFont bf = font.getCalculatedBaseFont(true);
+        Font f2 = new Font(bf, font.size(), font.getCalculatedStyle(), font.color());
+        fonts.add(f2);
+    }
+    
+    /**
+     * Process the text so that it will render with a combination of fonts
+     * if needed.
+     * @param text the text
+     * @return a <CODE>Phrase</CODE> with one or more chunks
+     */    
+    public Phrase process(String text) {
+        int fsize = fonts.size();
+        if (fsize == 0)
+            throw new IndexOutOfBoundsException("No font is defined.");
+        char cc[] = text.toCharArray();
+        int len = cc.length;
+        StringBuffer sb = new StringBuffer();
+        Font font = null;
+        int lastidx = -1;
+        Phrase ret = new Phrase();
+        for (int k = 0; k < len; ++k) {
+            char c = cc[k];
+            if (c == '\n' || c == '\r') {
+                sb.append(c);
+                continue;
+            }
+            for (int f = 0; f < fsize; ++f) {
+                font = (Font)fonts.get(f);
+                if (font.getBaseFont().charExists(c)) {
+                    if (lastidx == f)
+                        sb.append(c);
+                    else {
+                        if (sb.length() > 0 && lastidx != -1) {
+                            Chunk ck = new Chunk(sb.toString(), (Font)fonts.get(lastidx));
+                            ret.add(ck);
+                            sb = new StringBuffer();
+                        }
+                        sb.append(c);
+                        lastidx = f;
+                    }
+                    break;
+                }
+            }
+        }
+        if (sb.length() > 0) {
+            Chunk ck = new Chunk(sb.toString(), (Font)fonts.get(lastidx));
+            ret.add(ck);
+        }
+        return ret;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/GlyphList.java b/LibrarySource/com/lowagie/text/pdf/GlyphList.java
new file mode 100644
index 0000000..2f76917
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/GlyphList.java
@@ -0,0 +1,2200 @@
+/*
+ * $Id: GlyphList.java,v 1.20 2002/06/18 13:59:40 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+
+public class GlyphList
+{
+    private static HashMap unicode2names = new HashMap();
+    private static HashMap names2unicode = new HashMap();
+    
+    private static final int unicode[] =
+    {
+        0x0041,
+        0x00C6,
+        0x01FC,
+        0xF7E6,
+        0x00C1,
+        0xF7E1,
+        0x0102,
+        0x00C2,
+        0xF7E2,
+        0xF6C9,
+        0xF7B4,
+        0x00C4,
+        0xF7E4,
+        0x00C0,
+        0xF7E0,
+        0x0391,
+        0x0386,
+        0x0100,
+        0x0104,
+        0x00C5,
+        0x01FA,
+        0xF7E5,
+        0xF761,
+        0x00C3,
+        0xF7E3,
+        0x0042,
+        0x0392,
+        0xF6F4,
+        0xF762,
+        0x0043,
+        0x0106,
+        0xF6CA,
+        0xF6F5,
+        0x010C,
+        0x00C7,
+        0xF7E7,
+        0x0108,
+        0x010A,
+        0xF7B8,
+        0x03A7,
+        0xF6F6,
+        0xF763,
+        0x0044,
+        0x010E,
+        0x0110,
+        0x2206,
+        0x0394,
+        0xF6CB,
+        0xF6CC,
+        0xF6CD,
+        0xF7A8,
+        0xF6F7,
+        0xF764,
+        0x0045,
+        0x00C9,
+        0xF7E9,
+        0x0114,
+        0x011A,
+        0x00CA,
+        0xF7EA,
+        0x00CB,
+        0xF7EB,
+        0x0116,
+        0x00C8,
+        0xF7E8,
+        0x0112,
+        0x014A,
+        0x0118,
+        0x0395,
+        0x0388,
+        0xF765,
+        0x0397,
+        0x0389,
+        0x00D0,
+        0xF7F0,
+        0x20AC,
+        0x0046,
+        0xF766,
+        0x0047,
+        0x0393,
+        0x011E,
+        0x01E6,
+        0x011C,
+        0x0122,
+        0x0120,
+        0xF6CE,
+        0xF760,
+        0xF767,
+        0x0048,
+        0x25CF,
+        0x25AA,
+        0x25AB,
+        0x25A1,
+        0x0126,
+        0x0124,
+        0xF768,
+        0xF6CF,
+        0xF6F8,
+        0x0049,
+        0x0132,
+        0x00CD,
+        0xF7ED,
+        0x012C,
+        0x00CE,
+        0xF7EE,
+        0x00CF,
+        0xF7EF,
+        0x0130,
+        0x2111,
+        0x00CC,
+        0xF7EC,
+        0x012A,
+        0x012E,
+        0x0399,
+        0x03AA,
+        0x038A,
+        0xF769,
+        0x0128,
+        0x004A,
+        0x0134,
+        0xF76A,
+        0x004B,
+        0x039A,
+        0x0136,
+        0xF76B,
+        0x004C,
+        0xF6BF,
+        0x0139,
+        0x039B,
+        0x013D,
+        0x013B,
+        0x013F,
+        0x0141,
+        0xF6F9,
+        0xF76C,
+        0x004D,
+        0xF6D0,
+        0xF7AF,
+        0xF76D,
+        0x039C,
+        0x004E,
+        0x0143,
+        0x0147,
+        0x0145,
+        0xF76E,
+        0x00D1,
+        0xF7F1,
+        0x039D,
+        0x004F,
+        0x0152,
+        0xF6FA,
+        0x00D3,
+        0xF7F3,
+        0x014E,
+        0x00D4,
+        0xF7F4,
+        0x00D6,
+        0xF7F6,
+        0xF6FB,
+        0x00D2,
+        0xF7F2,
+        0x01A0,
+        0x0150,
+        0x014C,
+        0x2126,
+        0x03A9,
+        0x038F,
+        0x039F,
+        0x038C,
+        0x00D8,
+        0x01FE,
+        0xF7F8,
+        0xF76F,
+        0x00D5,
+        0xF7F5,
+        0x0050,
+        0x03A6,
+        0x03A0,
+        0x03A8,
+        0xF770,
+        0x0051,
+        0xF771,
+        0x0052,
+        0x0154,
+        0x0158,
+        0x0156,
+        0x211C,
+        0x03A1,
+        0xF6FC,
+        0xF772,
+        0x0053,
+        0x250C,
+        0x2514,
+        0x2510,
+        0x2518,
+        0x253C,
+        0x252C,
+        0x2534,
+        0x251C,
+        0x2524,
+        0x2500,
+        0x2502,
+        0x2561,
+        0x2562,
+        0x2556,
+        0x2555,
+        0x2563,
+        0x2551,
+        0x2557,
+        0x255D,
+        0x255C,
+        0x255B,
+        0x255E,
+        0x255F,
+        0x255A,
+        0x2554,
+        0x2569,
+        0x2566,
+        0x2560,
+        0x2550,
+        0x256C,
+        0x2567,
+        0x2568,
+        0x2564,
+        0x2565,
+        0x2559,
+        0x2558,
+        0x2552,
+        0x2553,
+        0x256B,
+        0x256A,
+        0x015A,
+        0x0160,
+        0xF6FD,
+        0x015E,
+        0xF6C1,
+        0x015C,
+        0x0218,
+        0x03A3,
+        0xF773,
+        0x0054,
+        0x03A4,
+        0x0166,
+        0x0164,
+        0x0162,
+        0x021A,
+        0x0398,
+        0x00DE,
+        0xF7FE,
+        0xF6FE,
+        0xF774,
+        0x0055,
+        0x00DA,
+        0xF7FA,
+        0x016C,
+        0x00DB,
+        0xF7FB,
+        0x00DC,
+        0xF7FC,
+        0x00D9,
+        0xF7F9,
+        0x01AF,
+        0x0170,
+        0x016A,
+        0x0172,
+        0x03A5,
+        0x03D2,
+        0x03AB,
+        0x038E,
+        0x016E,
+        0xF775,
+        0x0168,
+        0x0056,
+        0xF776,
+        0x0057,
+        0x1E82,
+        0x0174,
+        0x1E84,
+        0x1E80,
+        0xF777,
+        0x0058,
+        0x039E,
+        0xF778,
+        0x0059,
+        0x00DD,
+        0xF7FD,
+        0x0176,
+        0x0178,
+        0xF7FF,
+        0x1EF2,
+        0xF779,
+        0x005A,
+        0x0179,
+        0x017D,
+        0xF6FF,
+        0x017B,
+        0x0396,
+        0xF77A,
+        0x0061,
+        0x00E1,
+        0x0103,
+        0x00E2,
+        0x00B4,
+        0x0301,
+        0x00E4,
+        0x00E6,
+        0x01FD,
+        0x2015,
+        0x0410,
+        0x0411,
+        0x0412,
+        0x0413,
+        0x0414,
+        0x0415,
+        0x0401,
+        0x0416,
+        0x0417,
+        0x0418,
+        0x0419,
+        0x041A,
+        0x041B,
+        0x041C,
+        0x041D,
+        0x041E,
+        0x041F,
+        0x0420,
+        0x0421,
+        0x0422,
+        0x0423,
+        0x0424,
+        0x0425,
+        0x0426,
+        0x0427,
+        0x0428,
+        0x0429,
+        0x042A,
+        0x042B,
+        0x042C,
+        0x042D,
+        0x042E,
+        0x042F,
+        0x0490,
+        0x0402,
+        0x0403,
+        0x0404,
+        0x0405,
+        0x0406,
+        0x0407,
+        0x0408,
+        0x0409,
+        0x040A,
+        0x040B,
+        0x040C,
+        0x040E,
+        0xF6C4,
+        0xF6C5,
+        0x0430,
+        0x0431,
+        0x0432,
+        0x0433,
+        0x0434,
+        0x0435,
+        0x0451,
+        0x0436,
+        0x0437,
+        0x0438,
+        0x0439,
+        0x043A,
+        0x043B,
+        0x043C,
+        0x043D,
+        0x043E,
+        0x043F,
+        0x0440,
+        0x0441,
+        0x0442,
+        0x0443,
+        0x0444,
+        0x0445,
+        0x0446,
+        0x0447,
+        0x0448,
+        0x0449,
+        0x044A,
+        0x044B,
+        0x044C,
+        0x044D,
+        0x044E,
+        0x044F,
+        0x0491,
+        0x0452,
+        0x0453,
+        0x0454,
+        0x0455,
+        0x0456,
+        0x0457,
+        0x0458,
+        0x0459,
+        0x045A,
+        0x045B,
+        0x045C,
+        0x045E,
+        0x040F,
+        0x0462,
+        0x0472,
+        0x0474,
+        0xF6C6,
+        0x045F,
+        0x0463,
+        0x0473,
+        0x0475,
+        0xF6C7,
+        0xF6C8,
+        0x04D9,
+        0x200E,
+        0x200F,
+        0x200D,
+        0x066A,
+        0x060C,
+        0x0660,
+        0x0661,
+        0x0662,
+        0x0663,
+        0x0664,
+        0x0665,
+        0x0666,
+        0x0667,
+        0x0668,
+        0x0669,
+        0x061B,
+        0x061F,
+        0x0621,
+        0x0622,
+        0x0623,
+        0x0624,
+        0x0625,
+        0x0626,
+        0x0627,
+        0x0628,
+        0x0629,
+        0x062A,
+        0x062B,
+        0x062C,
+        0x062D,
+        0x062E,
+        0x062F,
+        0x0630,
+        0x0631,
+        0x0632,
+        0x0633,
+        0x0634,
+        0x0635,
+        0x0636,
+        0x0637,
+        0x0638,
+        0x0639,
+        0x063A,
+        0x0640,
+        0x0641,
+        0x0642,
+        0x0643,
+        0x0644,
+        0x0645,
+        0x0646,
+        0x0648,
+        0x0649,
+        0x064A,
+        0x064B,
+        0x064C,
+        0x064D,
+        0x064E,
+        0x064F,
+        0x0650,
+        0x0651,
+        0x0652,
+        0x0647,
+        0x06A4,
+        0x067E,
+        0x0686,
+        0x0698,
+        0x06AF,
+        0x0679,
+        0x0688,
+        0x0691,
+        0x06BA,
+        0x06D2,
+        0x06D5,
+        0x20AA,
+        0x05BE,
+        0x05C3,
+        0x05D0,
+        0x05D1,
+        0x05D2,
+        0x05D3,
+        0x05D4,
+        0x05D5,
+        0x05D6,
+        0x05D7,
+        0x05D8,
+        0x05D9,
+        0x05DA,
+        0x05DB,
+        0x05DC,
+        0x05DD,
+        0x05DE,
+        0x05DF,
+        0x05E0,
+        0x05E1,
+        0x05E2,
+        0x05E3,
+        0x05E4,
+        0x05E5,
+        0x05E6,
+        0x05E7,
+        0x05E8,
+        0x05E9,
+        0x05EA,
+        0xFB2A,
+        0xFB2B,
+        0xFB4B,
+        0xFB1F,
+        0x05F0,
+        0x05F1,
+        0x05F2,
+        0xFB35,
+        0x05B4,
+        0x05B5,
+        0x05B6,
+        0x05BB,
+        0x05B8,
+        0x05B7,
+        0x05B0,
+        0x05B2,
+        0x05B1,
+        0x05B3,
+        0x05C2,
+        0x05C1,
+        0x05B9,
+        0x05BC,
+        0x05BD,
+        0x05BF,
+        0x05C0,
+        0x02BC,
+        0x2105,
+        0x2113,
+        0x2116,
+        0x202C,
+        0x202D,
+        0x202E,
+        0x200C,
+        0x066D,
+        0x02BD,
+        0x00E0,
+        0x2135,
+        0x03B1,
+        0x03AC,
+        0x0101,
+        0x0026,
+        0xF726,
+        0x2220,
+        0x2329,
+        0x232A,
+        0x0387,
+        0x0105,
+        0x2248,
+        0x00E5,
+        0x01FB,
+        0x2194,
+        0x21D4,
+        0x21D3,
+        0x21D0,
+        0x21D2,
+        0x21D1,
+        0x2193,
+        0xF8E7,
+        0x2190,
+        0x2192,
+        0x2191,
+        0x2195,
+        0x21A8,
+        0xF8E6,
+        0x005E,
+        0x007E,
+        0x002A,
+        0x2217,
+        0xF6E9,
+        0x0040,
+        0x00E3,
+        0x0062,
+        0x005C,
+        0x007C,
+        0x03B2,
+        0x2588,
+        0xF8F4,
+        0x007B,
+        0xF8F3,
+        0xF8F2,
+        0xF8F1,
+        0x007D,
+        0xF8FE,
+        0xF8FD,
+        0xF8FC,
+        0x005B,
+        0xF8F0,
+        0xF8EF,
+        0xF8EE,
+        0x005D,
+        0xF8FB,
+        0xF8FA,
+        0xF8F9,
+        0x02D8,
+        0x00A6,
+        0xF6EA,
+        0x2022,
+        0x0063,
+        0x0107,
+        0x02C7,
+        0x21B5,
+        0x010D,
+        0x00E7,
+        0x0109,
+        0x010B,
+        0x00B8,
+        0x00A2,
+        0xF6DF,
+        0xF7A2,
+        0xF6E0,
+        0x03C7,
+        0x25CB,
+        0x2297,
+        0x2295,
+        0x02C6,
+        0x2663,
+        0x003A,
+        0x20A1,
+        0x002C,
+        0xF6C3,
+        0xF6E1,
+        0xF6E2,
+        0x2245,
+        0x00A9,
+        0xF8E9,
+        0xF6D9,
+        0x00A4,
+        0xF6D1,
+        0xF6D2,
+        0xF6D4,
+        0xF6D5,
+        0x0064,
+        0x2020,
+        0x2021,
+        0xF6D3,
+        0xF6D6,
+        0x010F,
+        0x0111,
+        0x00B0,
+        0x03B4,
+        0x2666,
+        0x00A8,
+        0xF6D7,
+        0xF6D8,
+        0x0385,
+        0x00F7,
+        0x2593,
+        0x2584,
+        0x0024,
+        0xF6E3,
+        0xF724,
+        0xF6E4,
+        0x20AB,
+        0x02D9,
+        0x0323,
+        0x0131,
+        0xF6BE,
+        0x22C5,
+        0xF6EB,
+        0x0065,
+        0x00E9,
+        0x0115,
+        0x011B,
+        0x00EA,
+        0x00EB,
+        0x0117,
+        0x00E8,
+        0x0038,
+        0x2088,
+        0xF738,
+        0x2078,
+        0x2208,
+        0x2026,
+        0x0113,
+        0x2014,
+        0x2205,
+        0x2013,
+        0x014B,
+        0x0119,
+        0x03B5,
+        0x03AD,
+        0x003D,
+        0x2261,
+        0x212E,
+        0xF6EC,
+        0x03B7,
+        0x03AE,
+        0x00F0,
+        0x0021,
+        0x203C,
+        0x00A1,
+        0xF7A1,
+        0xF721,
+        0x2203,
+        0x0066,
+        0x2640,
+        0xFB00,
+        0xFB03,
+        0xFB04,
+        0xFB01,
+        0x2012,
+        0x25A0,
+        0x25AC,
+        0x0035,
+        0x215D,
+        0x2085,
+        0xF735,
+        0x2075,
+        0xFB02,
+        0x0192,
+        0x0034,
+        0x2084,
+        0xF734,
+        0x2074,
+        0x2044,
+        0x2215,
+        0x20A3,
+        0x0067,
+        0x03B3,
+        0x011F,
+        0x01E7,
+        0x011D,
+        0x0123,
+        0x0121,
+        0x00DF,
+        0x2207,
+        0x0060,
+        0x0300,
+        0x003E,
+        0x2265,
+        0x00AB,
+        0x00BB,
+        0x2039,
+        0x203A,
+        0x0068,
+        0x0127,
+        0x0125,
+        0x2665,
+        0x0309,
+        0x2302,
+        0x02DD,
+        0x002D,
+        0x00AD,
+        0xF6E5,
+        0xF6E6,
+        0x0069,
+        0x00ED,
+        0x012D,
+        0x00EE,
+        0x00EF,
+        0x00EC,
+        0x0133,
+        0x012B,
+        0x221E,
+        0x222B,
+        0x2321,
+        0xF8F5,
+        0x2320,
+        0x2229,
+        0x25D8,
+        0x25D9,
+        0x263B,
+        0x012F,
+        0x03B9,
+        0x03CA,
+        0x0390,
+        0x03AF,
+        0xF6ED,
+        0x0129,
+        0x006A,
+        0x0135,
+        0x006B,
+        0x03BA,
+        0x0137,
+        0x0138,
+        0x006C,
+        0x013A,
+        0x03BB,
+        0x013E,
+        0x013C,
+        0x0140,
+        0x003C,
+        0x2264,
+        0x258C,
+        0x20A4,
+        0xF6C0,
+        0x2227,
+        0x00AC,
+        0x2228,
+        0x017F,
+        0x25CA,
+        0x0142,
+        0xF6EE,
+        0x2591,
+        0x006D,
+        0x00AF,
+        0x02C9,
+        0x2642,
+        0x2212,
+        0x2032,
+        0xF6EF,
+        0x00B5,
+        0x03BC,
+        0x00D7,
+        0x266A,
+        0x266B,
+        0x006E,
+        0x0144,
+        0x0149,
+        0x0148,
+        0x0146,
+        0x0039,
+        0x2089,
+        0xF739,
+        0x2079,
+        0x2209,
+        0x2260,
+        0x2284,
+        0x207F,
+        0x00F1,
+        0x03BD,
+        0x0023,
+        0x006F,
+        0x00F3,
+        0x014F,
+        0x00F4,
+        0x00F6,
+        0x0153,
+        0x02DB,
+        0x00F2,
+        0x01A1,
+        0x0151,
+        0x014D,
+        0x03C9,
+        0x03D6,
+        0x03CE,
+        0x03BF,
+        0x03CC,
+        0x0031,
+        0x2024,
+        0x215B,
+        0xF6DC,
+        0x00BD,
+        0x2081,
+        0xF731,
+        0x00BC,
+        0x00B9,
+        0x2153,
+        0x25E6,
+        0x00AA,
+        0x00BA,
+        0x221F,
+        0x00F8,
+        0x01FF,
+        0xF6F0,
+        0x00F5,
+        0x0070,
+        0x00B6,
+        0x0028,
+        0xF8ED,
+        0xF8EC,
+        0x208D,
+        0x207D,
+        0xF8EB,
+        0x0029,
+        0xF8F8,
+        0xF8F7,
+        0x208E,
+        0x207E,
+        0xF8F6,
+        0x2202,
+        0x0025,
+        0x002E,
+        0x00B7,
+        0x2219,
+        0xF6E7,
+        0xF6E8,
+        0x22A5,
+        0x2030,
+        0x20A7,
+        0x03C6,
+        0x03D5,
+        0x03C0,
+        0x002B,
+        0x00B1,
+        0x211E,
+        0x220F,
+        0x2282,
+        0x2283,
+        0x221D,
+        0x03C8,
+        0x0071,
+        0x003F,
+        0x00BF,
+        0xF7BF,
+        0xF73F,
+        0x0022,
+        0x201E,
+        0x201C,
+        0x201D,
+        0x2018,
+        0x201B,
+        0x2019,
+        0x201A,
+        0x0027,
+        0x0072,
+        0x0155,
+        0x221A,
+        0xF8E5,
+        0x0159,
+        0x0157,
+        0x2286,
+        0x2287,
+        0x00AE,
+        0xF8E8,
+        0xF6DA,
+        0x2310,
+        0x03C1,
+        0x02DA,
+        0xF6F1,
+        0x2590,
+        0xF6DD,
+        0x0073,
+        0x015B,
+        0x0161,
+        0x015F,
+        0xF6C2,
+        0x015D,
+        0x0219,
+        0x2033,
+        0x00A7,
+        0x003B,
+        0x0037,
+        0x215E,
+        0x2087,
+        0xF737,
+        0x2077,
+        0x2592,
+        0x03C3,
+        0x03C2,
+        0x223C,
+        0x0036,
+        0x2086,
+        0xF736,
+        0x2076,
+        0x002F,
+        0x263A,
+        0x0020,
+        0x00A0,
+        0x2660,
+        0xF6F2,
+        0x00A3,
+        0x220B,
+        0x2211,
+        0x263C,
+        0x0074,
+        0x03C4,
+        0x0167,
+        0x0165,
+        0x0163,
+        0x021B,
+        0x2234,
+        0x03B8,
+        0x03D1,
+        0x00FE,
+        0x0033,
+        0x215C,
+        0x2083,
+        0xF733,
+        0x00BE,
+        0xF6DE,
+        0x00B3,
+        0x02DC,
+        0x0303,
+        0x0384,
+        0x2122,
+        0xF8EA,
+        0xF6DB,
+        0x25BC,
+        0x25C4,
+        0x25BA,
+        0x25B2,
+        0xF6F3,
+        0x0032,
+        0x2025,
+        0x2082,
+        0xF732,
+        0x00B2,
+        0x2154,
+        0x0075,
+        0x00FA,
+        0x016D,
+        0x00FB,
+        0x00FC,
+        0x00F9,
+        0x01B0,
+        0x0171,
+        0x016B,
+        0x005F,
+        0x2017,
+        0x222A,
+        0x2200,
+        0x0173,
+        0x2580,
+        0x03C5,
+        0x03CB,
+        0x03B0,
+        0x03CD,
+        0x016F,
+        0x0169,
+        0x0076,
+        0x0077,
+        0x1E83,
+        0x0175,
+        0x1E85,
+        0x2118,
+        0x1E81,
+        0x0078,
+        0x03BE,
+        0x0079,
+        0x00FD,
+        0x0177,
+        0x00FF,
+        0x00A5,
+        0x1EF3,
+        0x007A,
+        0x017A,
+        0x017E,
+        0x017C,
+        0x0030,
+        0x2080,
+        0xF730,
+        0x2070,
+        0x03B6
+    };
+    
+    private static final String names[] =
+    {
+        "A",
+        "AE",
+        "AEacute",
+        "AEsmall",
+        "Aacute",
+        "Aacutesmall",
+        "Abreve",
+        "Acircumflex",
+        "Acircumflexsmall",
+        "Acute",
+        "Acutesmall",
+        "Adieresis",
+        "Adieresissmall",
+        "Agrave",
+        "Agravesmall",
+        "Alpha",
+        "Alphatonos",
+        "Amacron",
+        "Aogonek",
+        "Aring",
+        "Aringacute",
+        "Aringsmall",
+        "Asmall",
+        "Atilde",
+        "Atildesmall",
+        "B",
+        "Beta",
+        "Brevesmall",
+        "Bsmall",
+        "C",
+        "Cacute",
+        "Caron",
+        "Caronsmall",
+        "Ccaron",
+        "Ccedilla",
+        "Ccedillasmall",
+        "Ccircumflex",
+        "Cdotaccent",
+        "Cedillasmall",
+        "Chi",
+        "Circumflexsmall",
+        "Csmall",
+        "D",
+        "Dcaron",
+        "Dcroat",
+        "Delta",
+        "Delta",
+        "Dieresis",
+        "DieresisAcute",
+        "DieresisGrave",
+        "Dieresissmall",
+        "Dotaccentsmall",
+        "Dsmall",
+        "E",
+        "Eacute",
+        "Eacutesmall",
+        "Ebreve",
+        "Ecaron",
+        "Ecircumflex",
+        "Ecircumflexsmall",
+        "Edieresis",
+        "Edieresissmall",
+        "Edotaccent",
+        "Egrave",
+        "Egravesmall",
+        "Emacron",
+        "Eng",
+        "Eogonek",
+        "Epsilon",
+        "Epsilontonos",
+        "Esmall",
+        "Eta",
+        "Etatonos",
+        "Eth",
+        "Ethsmall",
+        "Euro",
+        "F",
+        "Fsmall",
+        "G",
+        "Gamma",
+        "Gbreve",
+        "Gcaron",
+        "Gcircumflex",
+        "Gcommaaccent",
+        "Gdotaccent",
+        "Grave",
+        "Gravesmall",
+        "Gsmall",
+        "H",
+        "H18533",
+        "H18543",
+        "H18551",
+        "H22073",
+        "Hbar",
+        "Hcircumflex",
+        "Hsmall",
+        "Hungarumlaut",
+        "Hungarumlautsmall",
+        "I",
+        "IJ",
+        "Iacute",
+        "Iacutesmall",
+        "Ibreve",
+        "Icircumflex",
+        "Icircumflexsmall",
+        "Idieresis",
+        "Idieresissmall",
+        "Idotaccent",
+        "Ifraktur",
+        "Igrave",
+        "Igravesmall",
+        "Imacron",
+        "Iogonek",
+        "Iota",
+        "Iotadieresis",
+        "Iotatonos",
+        "Ismall",
+        "Itilde",
+        "J",
+        "Jcircumflex",
+        "Jsmall",
+        "K",
+        "Kappa",
+        "Kcommaaccent",
+        "Ksmall",
+        "L",
+        "LL",
+        "Lacute",
+        "Lambda",
+        "Lcaron",
+        "Lcommaaccent",
+        "Ldot",
+        "Lslash",
+        "Lslashsmall",
+        "Lsmall",
+        "M",
+        "Macron",
+        "Macronsmall",
+        "Msmall",
+        "Mu",
+        "N",
+        "Nacute",
+        "Ncaron",
+        "Ncommaaccent",
+        "Nsmall",
+        "Ntilde",
+        "Ntildesmall",
+        "Nu",
+        "O",
+        "OE",
+        "OEsmall",
+        "Oacute",
+        "Oacutesmall",
+        "Obreve",
+        "Ocircumflex",
+        "Ocircumflexsmall",
+        "Odieresis",
+        "Odieresissmall",
+        "Ogoneksmall",
+        "Ograve",
+        "Ogravesmall",
+        "Ohorn",
+        "Ohungarumlaut",
+        "Omacron",
+        "Omega",
+        "Omega",
+        "Omegatonos",
+        "Omicron",
+        "Omicrontonos",
+        "Oslash",
+        "Oslashacute",
+        "Oslashsmall",
+        "Osmall",
+        "Otilde",
+        "Otildesmall",
+        "P",
+        "Phi",
+        "Pi",
+        "Psi",
+        "Psmall",
+        "Q",
+        "Qsmall",
+        "R",
+        "Racute",
+        "Rcaron",
+        "Rcommaaccent",
+        "Rfraktur",
+        "Rho",
+        "Ringsmall",
+        "Rsmall",
+        "S",
+        "SF010000",
+        "SF020000",
+        "SF030000",
+        "SF040000",
+        "SF050000",
+        "SF060000",
+        "SF070000",
+        "SF080000",
+        "SF090000",
+        "SF100000",
+        "SF110000",
+        "SF190000",
+        "SF200000",
+        "SF210000",
+        "SF220000",
+        "SF230000",
+        "SF240000",
+        "SF250000",
+        "SF260000",
+        "SF270000",
+        "SF280000",
+        "SF360000",
+        "SF370000",
+        "SF380000",
+        "SF390000",
+        "SF400000",
+        "SF410000",
+        "SF420000",
+        "SF430000",
+        "SF440000",
+        "SF450000",
+        "SF460000",
+        "SF470000",
+        "SF480000",
+        "SF490000",
+        "SF500000",
+        "SF510000",
+        "SF520000",
+        "SF530000",
+        "SF540000",
+        "Sacute",
+        "Scaron",
+        "Scaronsmall",
+        "Scedilla",
+        "Scedilla",
+        "Scircumflex",
+        "Scommaaccent",
+        "Sigma",
+        "Ssmall",
+        "T",
+        "Tau",
+        "Tbar",
+        "Tcaron",
+        "Tcommaaccent",
+        "Tcommaaccent",
+        "Theta",
+        "Thorn",
+        "Thornsmall",
+        "Tildesmall",
+        "Tsmall",
+        "U",
+        "Uacute",
+        "Uacutesmall",
+        "Ubreve",
+        "Ucircumflex",
+        "Ucircumflexsmall",
+        "Udieresis",
+        "Udieresissmall",
+        "Ugrave",
+        "Ugravesmall",
+        "Uhorn",
+        "Uhungarumlaut",
+        "Umacron",
+        "Uogonek",
+        "Upsilon",
+        "Upsilon1",
+        "Upsilondieresis",
+        "Upsilontonos",
+        "Uring",
+        "Usmall",
+        "Utilde",
+        "V",
+        "Vsmall",
+        "W",
+        "Wacute",
+        "Wcircumflex",
+        "Wdieresis",
+        "Wgrave",
+        "Wsmall",
+        "X",
+        "Xi",
+        "Xsmall",
+        "Y",
+        "Yacute",
+        "Yacutesmall",
+        "Ycircumflex",
+        "Ydieresis",
+        "Ydieresissmall",
+        "Ygrave",
+        "Ysmall",
+        "Z",
+        "Zacute",
+        "Zcaron",
+        "Zcaronsmall",
+        "Zdotaccent",
+        "Zeta",
+        "Zsmall",
+        "a",
+        "aacute",
+        "abreve",
+        "acircumflex",
+        "acute",
+        "acutecomb",
+        "adieresis",
+        "ae",
+        "aeacute",
+        "afii00208",
+        "afii10017",
+        "afii10018",
+        "afii10019",
+        "afii10020",
+        "afii10021",
+        "afii10022",
+        "afii10023",
+        "afii10024",
+        "afii10025",
+        "afii10026",
+        "afii10027",
+        "afii10028",
+        "afii10029",
+        "afii10030",
+        "afii10031",
+        "afii10032",
+        "afii10033",
+        "afii10034",
+        "afii10035",
+        "afii10036",
+        "afii10037",
+        "afii10038",
+        "afii10039",
+        "afii10040",
+        "afii10041",
+        "afii10042",
+        "afii10043",
+        "afii10044",
+        "afii10045",
+        "afii10046",
+        "afii10047",
+        "afii10048",
+        "afii10049",
+        "afii10050",
+        "afii10051",
+        "afii10052",
+        "afii10053",
+        "afii10054",
+        "afii10055",
+        "afii10056",
+        "afii10057",
+        "afii10058",
+        "afii10059",
+        "afii10060",
+        "afii10061",
+        "afii10062",
+        "afii10063",
+        "afii10064",
+        "afii10065",
+        "afii10066",
+        "afii10067",
+        "afii10068",
+        "afii10069",
+        "afii10070",
+        "afii10071",
+        "afii10072",
+        "afii10073",
+        "afii10074",
+        "afii10075",
+        "afii10076",
+        "afii10077",
+        "afii10078",
+        "afii10079",
+        "afii10080",
+        "afii10081",
+        "afii10082",
+        "afii10083",
+        "afii10084",
+        "afii10085",
+        "afii10086",
+        "afii10087",
+        "afii10088",
+        "afii10089",
+        "afii10090",
+        "afii10091",
+        "afii10092",
+        "afii10093",
+        "afii10094",
+        "afii10095",
+        "afii10096",
+        "afii10097",
+        "afii10098",
+        "afii10099",
+        "afii10100",
+        "afii10101",
+        "afii10102",
+        "afii10103",
+        "afii10104",
+        "afii10105",
+        "afii10106",
+        "afii10107",
+        "afii10108",
+        "afii10109",
+        "afii10110",
+        "afii10145",
+        "afii10146",
+        "afii10147",
+        "afii10148",
+        "afii10192",
+        "afii10193",
+        "afii10194",
+        "afii10195",
+        "afii10196",
+        "afii10831",
+        "afii10832",
+        "afii10846",
+        "afii299",
+        "afii300",
+        "afii301",
+        "afii57381",
+        "afii57388",
+        "afii57392",
+        "afii57393",
+        "afii57394",
+        "afii57395",
+        "afii57396",
+        "afii57397",
+        "afii57398",
+        "afii57399",
+        "afii57400",
+        "afii57401",
+        "afii57403",
+        "afii57407",
+        "afii57409",
+        "afii57410",
+        "afii57411",
+        "afii57412",
+        "afii57413",
+        "afii57414",
+        "afii57415",
+        "afii57416",
+        "afii57417",
+        "afii57418",
+        "afii57419",
+        "afii57420",
+        "afii57421",
+        "afii57422",
+        "afii57423",
+        "afii57424",
+        "afii57425",
+        "afii57426",
+        "afii57427",
+        "afii57428",
+        "afii57429",
+        "afii57430",
+        "afii57431",
+        "afii57432",
+        "afii57433",
+        "afii57434",
+        "afii57440",
+        "afii57441",
+        "afii57442",
+        "afii57443",
+        "afii57444",
+        "afii57445",
+        "afii57446",
+        "afii57448",
+        "afii57449",
+        "afii57450",
+        "afii57451",
+        "afii57452",
+        "afii57453",
+        "afii57454",
+        "afii57455",
+        "afii57456",
+        "afii57457",
+        "afii57458",
+        "afii57470",
+        "afii57505",
+        "afii57506",
+        "afii57507",
+        "afii57508",
+        "afii57509",
+        "afii57511",
+        "afii57512",
+        "afii57513",
+        "afii57514",
+        "afii57519",
+        "afii57534",
+        "afii57636",
+        "afii57645",
+        "afii57658",
+        "afii57664",
+        "afii57665",
+        "afii57666",
+        "afii57667",
+        "afii57668",
+        "afii57669",
+        "afii57670",
+        "afii57671",
+        "afii57672",
+        "afii57673",
+        "afii57674",
+        "afii57675",
+        "afii57676",
+        "afii57677",
+        "afii57678",
+        "afii57679",
+        "afii57680",
+        "afii57681",
+        "afii57682",
+        "afii57683",
+        "afii57684",
+        "afii57685",
+        "afii57686",
+        "afii57687",
+        "afii57688",
+        "afii57689",
+        "afii57690",
+        "afii57694",
+        "afii57695",
+        "afii57700",
+        "afii57705",
+        "afii57716",
+        "afii57717",
+        "afii57718",
+        "afii57723",
+        "afii57793",
+        "afii57794",
+        "afii57795",
+        "afii57796",
+        "afii57797",
+        "afii57798",
+        "afii57799",
+        "afii57800",
+        "afii57801",
+        "afii57802",
+        "afii57803",
+        "afii57804",
+        "afii57806",
+        "afii57807",
+        "afii57839",
+        "afii57841",
+        "afii57842",
+        "afii57929",
+        "afii61248",
+        "afii61289",
+        "afii61352",
+        "afii61573",
+        "afii61574",
+        "afii61575",
+        "afii61664",
+        "afii63167",
+        "afii64937",
+        "agrave",
+        "aleph",
+        "alpha",
+        "alphatonos",
+        "amacron",
+        "ampersand",
+        "ampersandsmall",
+        "angle",
+        "angleleft",
+        "angleright",
+        "anoteleia",
+        "aogonek",
+        "approxequal",
+        "aring",
+        "aringacute",
+        "arrowboth",
+        "arrowdblboth",
+        "arrowdbldown",
+        "arrowdblleft",
+        "arrowdblright",
+        "arrowdblup",
+        "arrowdown",
+        "arrowhorizex",
+        "arrowleft",
+        "arrowright",
+        "arrowup",
+        "arrowupdn",
+        "arrowupdnbse",
+        "arrowvertex",
+        "asciicircum",
+        "asciitilde",
+        "asterisk",
+        "asteriskmath",
+        "asuperior",
+        "at",
+        "atilde",
+        "b",
+        "backslash",
+        "bar",
+        "beta",
+        "block",
+        "braceex",
+        "braceleft",
+        "braceleftbt",
+        "braceleftmid",
+        "bracelefttp",
+        "braceright",
+        "bracerightbt",
+        "bracerightmid",
+        "bracerighttp",
+        "bracketleft",
+        "bracketleftbt",
+        "bracketleftex",
+        "bracketlefttp",
+        "bracketright",
+        "bracketrightbt",
+        "bracketrightex",
+        "bracketrighttp",
+        "breve",
+        "brokenbar",
+        "bsuperior",
+        "bullet",
+        "c",
+        "cacute",
+        "caron",
+        "carriagereturn",
+        "ccaron",
+        "ccedilla",
+        "ccircumflex",
+        "cdotaccent",
+        "cedilla",
+        "cent",
+        "centinferior",
+        "centoldstyle",
+        "centsuperior",
+        "chi",
+        "circle",
+        "circlemultiply",
+        "circleplus",
+        "circumflex",
+        "club",
+        "colon",
+        "colonmonetary",
+        "comma",
+        "commaaccent",
+        "commainferior",
+        "commasuperior",
+        "congruent",
+        "copyright",
+        "copyrightsans",
+        "copyrightserif",
+        "currency",
+        "cyrBreve",
+        "cyrFlex",
+        "cyrbreve",
+        "cyrflex",
+        "d",
+        "dagger",
+        "daggerdbl",
+        "dblGrave",
+        "dblgrave",
+        "dcaron",
+        "dcroat",
+        "degree",
+        "delta",
+        "diamond",
+        "dieresis",
+        "dieresisacute",
+        "dieresisgrave",
+        "dieresistonos",
+        "divide",
+        "dkshade",
+        "dnblock",
+        "dollar",
+        "dollarinferior",
+        "dollaroldstyle",
+        "dollarsuperior",
+        "dong",
+        "dotaccent",
+        "dotbelowcomb",
+        "dotlessi",
+        "dotlessj",
+        "dotmath",
+        "dsuperior",
+        "e",
+        "eacute",
+        "ebreve",
+        "ecaron",
+        "ecircumflex",
+        "edieresis",
+        "edotaccent",
+        "egrave",
+        "eight",
+        "eightinferior",
+        "eightoldstyle",
+        "eightsuperior",
+        "element",
+        "ellipsis",
+        "emacron",
+        "emdash",
+        "emptyset",
+        "endash",
+        "eng",
+        "eogonek",
+        "epsilon",
+        "epsilontonos",
+        "equal",
+        "equivalence",
+        "estimated",
+        "esuperior",
+        "eta",
+        "etatonos",
+        "eth",
+        "exclam",
+        "exclamdbl",
+        "exclamdown",
+        "exclamdownsmall",
+        "exclamsmall",
+        "existential",
+        "f",
+        "female",
+        "ff",
+        "ffi",
+        "ffl",
+        "fi",
+        "figuredash",
+        "filledbox",
+        "filledrect",
+        "five",
+        "fiveeighths",
+        "fiveinferior",
+        "fiveoldstyle",
+        "fivesuperior",
+        "fl",
+        "florin",
+        "four",
+        "fourinferior",
+        "fouroldstyle",
+        "foursuperior",
+        "fraction",
+        "fraction",
+        "franc",
+        "g",
+        "gamma",
+        "gbreve",
+        "gcaron",
+        "gcircumflex",
+        "gcommaaccent",
+        "gdotaccent",
+        "germandbls",
+        "gradient",
+        "grave",
+        "gravecomb",
+        "greater",
+        "greaterequal",
+        "guillemotleft",
+        "guillemotright",
+        "guilsinglleft",
+        "guilsinglright",
+        "h",
+        "hbar",
+        "hcircumflex",
+        "heart",
+        "hookabovecomb",
+        "house",
+        "hungarumlaut",
+        "hyphen",
+        "hyphen",
+        "hypheninferior",
+        "hyphensuperior",
+        "i",
+        "iacute",
+        "ibreve",
+        "icircumflex",
+        "idieresis",
+        "igrave",
+        "ij",
+        "imacron",
+        "infinity",
+        "integral",
+        "integralbt",
+        "integralex",
+        "integraltp",
+        "intersection",
+        "invbullet",
+        "invcircle",
+        "invsmileface",
+        "iogonek",
+        "iota",
+        "iotadieresis",
+        "iotadieresistonos",
+        "iotatonos",
+        "isuperior",
+        "itilde",
+        "j",
+        "jcircumflex",
+        "k",
+        "kappa",
+        "kcommaaccent",
+        "kgreenlandic",
+        "l",
+        "lacute",
+        "lambda",
+        "lcaron",
+        "lcommaaccent",
+        "ldot",
+        "less",
+        "lessequal",
+        "lfblock",
+        "lira",
+        "ll",
+        "logicaland",
+        "logicalnot",
+        "logicalor",
+        "longs",
+        "lozenge",
+        "lslash",
+        "lsuperior",
+        "ltshade",
+        "m",
+        "macron",
+        "macron",
+        "male",
+        "minus",
+        "minute",
+        "msuperior",
+        "mu",
+        "mu",
+        "multiply",
+        "musicalnote",
+        "musicalnotedbl",
+        "n",
+        "nacute",
+        "napostrophe",
+        "ncaron",
+        "ncommaaccent",
+        "nine",
+        "nineinferior",
+        "nineoldstyle",
+        "ninesuperior",
+        "notelement",
+        "notequal",
+        "notsubset",
+        "nsuperior",
+        "ntilde",
+        "nu",
+        "numbersign",
+        "o",
+        "oacute",
+        "obreve",
+        "ocircumflex",
+        "odieresis",
+        "oe",
+        "ogonek",
+        "ograve",
+        "ohorn",
+        "ohungarumlaut",
+        "omacron",
+        "omega",
+        "omega1",
+        "omegatonos",
+        "omicron",
+        "omicrontonos",
+        "one",
+        "onedotenleader",
+        "oneeighth",
+        "onefitted",
+        "onehalf",
+        "oneinferior",
+        "oneoldstyle",
+        "onequarter",
+        "onesuperior",
+        "onethird",
+        "openbullet",
+        "ordfeminine",
+        "ordmasculine",
+        "orthogonal",
+        "oslash",
+        "oslashacute",
+        "osuperior",
+        "otilde",
+        "p",
+        "paragraph",
+        "parenleft",
+        "parenleftbt",
+        "parenleftex",
+        "parenleftinferior",
+        "parenleftsuperior",
+        "parenlefttp",
+        "parenright",
+        "parenrightbt",
+        "parenrightex",
+        "parenrightinferior",
+        "parenrightsuperior",
+        "parenrighttp",
+        "partialdiff",
+        "percent",
+        "period",
+        "periodcentered",
+        "periodcentered",
+        "periodinferior",
+        "periodsuperior",
+        "perpendicular",
+        "perthousand",
+        "peseta",
+        "phi",
+        "phi1",
+        "pi",
+        "plus",
+        "plusminus",
+        "prescription",
+        "product",
+        "propersubset",
+        "propersuperset",
+        "proportional",
+        "psi",
+        "q",
+        "question",
+        "questiondown",
+        "questiondownsmall",
+        "questionsmall",
+        "quotedbl",
+        "quotedblbase",
+        "quotedblleft",
+        "quotedblright",
+        "quoteleft",
+        "quotereversed",
+        "quoteright",
+        "quotesinglbase",
+        "quotesingle",
+        "r",
+        "racute",
+        "radical",
+        "radicalex",
+        "rcaron",
+        "rcommaaccent",
+        "reflexsubset",
+        "reflexsuperset",
+        "registered",
+        "registersans",
+        "registerserif",
+        "revlogicalnot",
+        "rho",
+        "ring",
+        "rsuperior",
+        "rtblock",
+        "rupiah",
+        "s",
+        "sacute",
+        "scaron",
+        "scedilla",
+        "scedilla",
+        "scircumflex",
+        "scommaaccent",
+        "second",
+        "section",
+        "semicolon",
+        "seven",
+        "seveneighths",
+        "seveninferior",
+        "sevenoldstyle",
+        "sevensuperior",
+        "shade",
+        "sigma",
+        "sigma1",
+        "similar",
+        "six",
+        "sixinferior",
+        "sixoldstyle",
+        "sixsuperior",
+        "slash",
+        "smileface",
+        "space",
+        "space",
+        "spade",
+        "ssuperior",
+        "sterling",
+        "suchthat",
+        "summation",
+        "sun",
+        "t",
+        "tau",
+        "tbar",
+        "tcaron",
+        "tcommaaccent",
+        "tcommaaccent",
+        "therefore",
+        "theta",
+        "theta1",
+        "thorn",
+        "three",
+        "threeeighths",
+        "threeinferior",
+        "threeoldstyle",
+        "threequarters",
+        "threequartersemdash",
+        "threesuperior",
+        "tilde",
+        "tildecomb",
+        "tonos",
+        "trademark",
+        "trademarksans",
+        "trademarkserif",
+        "triagdn",
+        "triaglf",
+        "triagrt",
+        "triagup",
+        "tsuperior",
+        "two",
+        "twodotenleader",
+        "twoinferior",
+        "twooldstyle",
+        "twosuperior",
+        "twothirds",
+        "u",
+        "uacute",
+        "ubreve",
+        "ucircumflex",
+        "udieresis",
+        "ugrave",
+        "uhorn",
+        "uhungarumlaut",
+        "umacron",
+        "underscore",
+        "underscoredbl",
+        "union",
+        "universal",
+        "uogonek",
+        "upblock",
+        "upsilon",
+        "upsilondieresis",
+        "upsilondieresistonos",
+        "upsilontonos",
+        "uring",
+        "utilde",
+        "v",
+        "w",
+        "wacute",
+        "wcircumflex",
+        "wdieresis",
+        "weierstrass",
+        "wgrave",
+        "x",
+        "xi",
+        "y",
+        "yacute",
+        "ycircumflex",
+        "ydieresis",
+        "yen",
+        "ygrave",
+        "z",
+        "zacute",
+        "zcaron",
+        "zdotaccent",
+        "zero",
+        "zeroinferior",
+        "zerooldstyle",
+        "zerosuperior",
+        "zeta"
+    };
+    
+    static
+    {
+        for (int k = 0; k < unicode.length; ++k)
+        {
+            Integer num = new Integer(unicode[k]);
+            unicode2names.put(num, names[k]);
+            int code[] = (int[])names2unicode.get(names[k]);
+            if (code == null)
+            {
+                names2unicode.put(names[k], new int[]{unicode[k]});
+            }
+            else
+            {
+                int code2[] = new int[code.length + 1];
+                System.arraycopy(code, 0, code2, 0, code.length);
+                code2[code.length] = unicode[k];
+                names2unicode.put(names[k], code2);
+            }
+        }
+    }
+    
+    public static int[] nameToUnicode(String name)
+    {
+        return (int[])names2unicode.get(name);
+    }
+    
+    public static String unicodeToName(int num)
+    {
+        return (String)unicode2names.get(new Integer(num));
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/GrayColor.java b/LibrarySource/com/lowagie/text/pdf/GrayColor.java
new file mode 100644
index 0000000..d94493d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/GrayColor.java
@@ -0,0 +1,75 @@
+/*
+ * $Id: GrayColor.java,v 1.10 2002/06/18 13:59:40 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class GrayColor extends ExtendedColor {
+
+    float gray;
+
+    public GrayColor(int intGray) {
+        this((float)intGray / 255f);
+    }
+
+    public GrayColor(float floatGray) {
+        super(TYPE_GRAY, floatGray, floatGray, floatGray);
+        gray = normalize(floatGray);
+    }
+    
+    public float getGray() {
+        return gray;
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/HyphenationAuto.java b/LibrarySource/com/lowagie/text/pdf/HyphenationAuto.java
new file mode 100644
index 0000000..7b4507e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/HyphenationAuto.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.pdf.hyphenation.Hyphenator;
+import com.lowagie.text.pdf.hyphenation.Hyphenation;
+
+/** Hyphenates words automatically accordingly to the language and country.
+ * The hyphenator engine was taken from FOP and uses the TEX patterns. If a language
+ * is not provided and a TEX pattern for it exists, it can be easily adapted.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class HyphenationAuto implements HyphenationEvent {
+
+    /** The hyphenator engine.
+     */    
+    protected Hyphenator hyphenator;
+    /** The second part of the hyphenated word.
+     */    
+    protected String post;
+    
+    /** Creates a new hyphenation instance usable in <CODE>Chunk</CODE>.
+     * @param lang the language ("en" for english, for example)
+     * @param country the country ("GB" for Great-Britain or "none" for no country, for example)
+     * @param leftMin the minimun number of letters before the hyphen
+     * @param rightMin the minimun number of letters after the hyphen
+     */    
+    public HyphenationAuto(String lang, String country, int leftMin, int rightMin) {
+        hyphenator = new Hyphenator(lang, country, leftMin, rightMin);
+    }
+
+    /** Gets the hyphen symbol.
+     * @return the hyphen symbol
+     */    
+    public String getHyphenSymbol() {
+        return "-";
+    }
+    
+    /** Hyphenates a word and returns the first part of it. To get
+     * the second part of the hyphenated word call <CODE>getHyphenatedWordPost()</CODE>.
+     * @param word the word to hyphenate
+     * @param font the font used by this word
+     * @param fontSize the font size used by this word
+     * @param remainingWidth the width available to fit this word in
+     * @return the first part of the hyphenated word including
+     * the hyphen symbol, if any
+     */    
+    public String getHyphenatedWordPre(String word, BaseFont font, float fontSize, float remainingWidth) {
+        post = word;
+        String hyphen = getHyphenSymbol();
+        float hyphenWidth = font.getWidthPoint(hyphen, fontSize);
+        if (hyphenWidth > remainingWidth)
+            return "";
+        Hyphenation hyphenation = hyphenator.hyphenate(word);
+        if (hyphenation == null) {
+            return "";
+        }
+        int len = hyphenation.length();
+        int k;
+        for (k = 0; k < len; ++k) {
+            if (font.getWidthPoint(hyphenation.getPreHyphenText(k), fontSize) + hyphenWidth > remainingWidth)
+                break;
+        }
+        --k;
+        if (k < 0)
+            return "";
+        post = hyphenation.getPostHyphenText(k);
+        return hyphenation.getPreHyphenText(k) + hyphen;
+    }
+    
+    /** Gets the second part of the hyphenated word. Must be called
+     * after <CODE>getHyphenatedWordPre()</CODE>.
+     * @return the second part of the hyphenated word
+     */    
+    public String getHyphenatedWordPost() {
+        return post;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/HyphenationEvent.java b/LibrarySource/com/lowagie/text/pdf/HyphenationEvent.java
new file mode 100644
index 0000000..68bf40d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/HyphenationEvent.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/** Called by <code>Chunk</code> to hyphenate a word.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface HyphenationEvent {
+
+    /** Gets the hyphen symbol.
+     * @return the hyphen symbol
+     */    
+    public String getHyphenSymbol();
+    
+    /** Hyphenates a word and returns the first part of it. To get
+     * the second part of the hyphenated word call <CODE>getHyphenatedWordPost()</CODE>.
+     * @param word the word to hyphenate
+     * @param font the font used by this word
+     * @param fontSize the font size used by this word
+     * @param remainingWidth the width available to fit this word in
+     * @return the first part of the hyphenated word including
+     * the hyphen symbol, if any
+     */    
+    public String getHyphenatedWordPre(String word, BaseFont font, float fontSize, float remainingWidth);
+    
+    /** Gets the second part of the hyphenated word. Must be called
+     * after <CODE>getHyphenatedWordPre()</CODE>.
+     * @return the second part of the hyphenated word
+     */    
+    public String getHyphenatedWordPost();
+}
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/IntHashtable.java b/LibrarySource/com/lowagie/text/pdf/IntHashtable.java
new file mode 100644
index 0000000..66d720a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/IntHashtable.java
@@ -0,0 +1,339 @@
+// IntHashtable - a Hashtable that uses ints as the keys
+//
+// This is 90% based on JavaSoft's java.util.Hashtable.
+//
+// Visit the ACME Labs Java page for up-to-date versions of this and other
+// fine Java utilities: http://www.acme.com/java/
+
+package com.lowagie.text.pdf;
+
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import java.util.Iterator;
+
+/// A Hashtable that uses ints as the keys.
+// <P>
+// Use just like java.util.Hashtable, except that the keys must be ints.
+// This is much faster than creating a new Integer for each access.
+// <P>
+// <A HREF="/resources/classes/Acme/IntHashtable.java">Fetch the software.</A><BR>
+// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
+// <P>
+// @see java.util.Hashtable
+
+public class IntHashtable implements Cloneable {
+    /// The hash table data.
+    private IntHashtableEntry table[];
+    
+    /// The total number of entries in the hash table.
+    private int count;
+    
+    /// Rehashes the table when count exceeds this threshold.
+    private int threshold;
+    
+    /// The load factor for the hashtable.
+    private float loadFactor;
+    
+    /// Constructs a new, empty hashtable with the specified initial
+    // capacity and the specified load factor.
+    // @param initialCapacity the initial number of buckets
+    // @param loadFactor a number between 0.0 and 1.0, it defines
+    //		the threshold for rehashing the hashtable into
+    //		a bigger one.
+    // @exception IllegalArgumentException If the initial capacity
+    // is less than or equal to zero.
+    // @exception IllegalArgumentException If the load factor is
+    // less than or equal to zero.
+    public IntHashtable( int initialCapacity, float loadFactor ) {
+        if ( initialCapacity <= 0 || loadFactor <= 0.0 )
+            throw new IllegalArgumentException();
+        this.loadFactor = loadFactor;
+        table = new IntHashtableEntry[initialCapacity];
+        threshold = (int) ( initialCapacity * loadFactor );
+    }
+    
+    /// Constructs a new, empty hashtable with the specified initial
+    // capacity.
+    // @param initialCapacity the initial number of buckets
+    public IntHashtable( int initialCapacity ) {
+        this( initialCapacity, 0.75f );
+    }
+    
+    /// Constructs a new, empty hashtable. A default capacity and load factor
+    // is used. Note that the hashtable will automatically grow when it gets
+    // full.
+    public IntHashtable() {
+        this( 101, 0.75f );
+    }
+    
+    /// Returns the number of elements contained in the hashtable.
+    public int size() {
+        return count;
+    }
+    
+    /// Returns true if the hashtable contains no elements.
+    public boolean isEmpty() {
+        return count == 0;
+    }
+    
+    /// Returns true if the specified object is an element of the hashtable.
+    // This operation is more expensive than the containsKey() method.
+    // @param value the value that we are looking for
+    // @exception NullPointerException If the value being searched
+    // for is equal to null.
+    // @see IntHashtable#containsKey
+    public boolean contains( int value ) {
+        IntHashtableEntry tab[] = table;
+        for ( int i = tab.length ; i-- > 0 ; ) {
+            for ( IntHashtableEntry e = tab[i] ; e != null ; e = e.next ) {
+                if ( e.value == value )
+                    return true;
+            }
+        }
+        return false;
+    }
+    
+    /// Returns true if the collection contains an element for the key.
+    // @param key the key that we are looking for
+    // @see IntHashtable#contains
+    public boolean containsKey( int key ) {
+        IntHashtableEntry tab[] = table;
+        int hash = key;
+        int index = ( hash & 0x7FFFFFFF ) % tab.length;
+        for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
+            if ( e.hash == hash && e.key == key )
+                return true;
+        }
+        return false;
+    }
+    
+    /// Gets the object associated with the specified key in the
+    // hashtable.
+    // @param key the specified key
+    // @returns the element for the key or null if the key
+    // 		is not defined in the hash table.
+    // @see IntHashtable#put
+    public int get( int key ) {
+        IntHashtableEntry tab[] = table;
+        int hash = key;
+        int index = ( hash & 0x7FFFFFFF ) % tab.length;
+        for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
+            if ( e.hash == hash && e.key == key )
+                return e.value;
+        }
+        return 0;
+    }
+    
+    /// Rehashes the content of the table into a bigger table.
+    // This method is called automatically when the hashtable's
+    // size exceeds the threshold.
+    protected void rehash() {
+        int oldCapacity = table.length;
+        IntHashtableEntry oldTable[] = table;
+        
+        int newCapacity = oldCapacity * 2 + 1;
+        IntHashtableEntry newTable[] = new IntHashtableEntry[newCapacity];
+        
+        threshold = (int) ( newCapacity * loadFactor );
+        table = newTable;
+        
+        for ( int i = oldCapacity ; i-- > 0 ; ) {
+            for ( IntHashtableEntry old = oldTable[i] ; old != null ; ) {
+                IntHashtableEntry e = old;
+                old = old.next;
+                
+                int index = ( e.hash & 0x7FFFFFFF ) % newCapacity;
+                e.next = newTable[index];
+                newTable[index] = e;
+            }
+        }
+    }
+    
+    /// Puts the specified element into the hashtable, using the specified
+    // key.  The element may be retrieved by doing a get() with the same key.
+    // The key and the element cannot be null.
+    // @param key the specified key in the hashtable
+    // @param value the specified element
+    // @exception NullPointerException If the value of the element
+    // is equal to null.
+    // @see IntHashtable#get
+    // @return the old value of the key, or null if it did not have one.
+    public int put( int key, int value ) {
+        // Makes sure the key is not already in the hashtable.
+        IntHashtableEntry tab[] = table;
+        int hash = key;
+        int index = ( hash & 0x7FFFFFFF ) % tab.length;
+        for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
+            if ( e.hash == hash && e.key == key ) {
+                int old = e.value;
+                e.value = value;
+                return old;
+            }
+        }
+        
+        if ( count >= threshold ) {
+            // Rehash the table if the threshold is exceeded.
+            rehash();
+            return put( key, value );
+        }
+        
+        // Creates the new entry.
+        IntHashtableEntry e = new IntHashtableEntry();
+        e.hash = hash;
+        e.key = key;
+        e.value = value;
+        e.next = tab[index];
+        tab[index] = e;
+        ++count;
+        return 0;
+    }
+    
+    /// Removes the element corresponding to the key. Does nothing if the
+    // key is not present.
+    // @param key the key that needs to be removed
+    // @return the value of key, or null if the key was not found.
+    public int remove( int key ) {
+        IntHashtableEntry tab[] = table;
+        int hash = key;
+        int index = ( hash & 0x7FFFFFFF ) % tab.length;
+        for ( IntHashtableEntry e = tab[index], prev = null ; e != null ; prev = e, e = e.next ) {
+            if ( e.hash == hash && e.key == key ) {
+                if ( prev != null )
+                    prev.next = e.next;
+                else
+                    tab[index] = e.next;
+                --count;
+                return e.value;
+            }
+        }
+        return 0;
+    }
+    
+    /// Clears the hash table so that it has no more elements in it.
+    public void clear() {
+        IntHashtableEntry tab[] = table;
+        for ( int index = tab.length; --index >= 0; )
+            tab[index] = null;
+        count = 0;
+    }
+    
+    public Object clone() {
+        try {
+            IntHashtable t = (IntHashtable)super.clone();
+            t.table = new IntHashtableEntry[table.length];
+            for (int i = table.length ; i-- > 0 ; ) {
+                t.table[i] = (table[i] != null)
+                ? (IntHashtableEntry)table[i].clone() : null;
+            }
+            return t;
+        } catch (CloneNotSupportedException e) {
+            // this shouldn't happen, since we are Cloneable
+            throw new InternalError();
+        }
+    }
+
+    public int[] toOrderedKeys() {
+        int res[] = getKeys();
+        Arrays.sort(res);
+        return res;
+    }
+    
+    public int[] getKeys() {
+        int res[] = new int[count];
+        int ptr = 0;
+        int index = table.length;
+        IntHashtableEntry entry = null;
+        while (true) {
+            if (entry == null)
+                while ((index-- > 0) && ((entry = table[index]) == null));
+            if (entry == null)
+                break;
+            IntHashtableEntry e = entry;
+            entry = e.next;
+            res[ptr++] = e.key;
+        }
+        return res;
+    }
+    
+    public int getOneKey() {
+        if (count == 0)
+            return 0;
+        int index = table.length;
+        IntHashtableEntry entry = null;
+        while ((index-- > 0) && ((entry = table[index]) == null));
+        if (entry == null)
+            return 0;
+        return entry.key;
+    }
+    
+    static class IntHashtableEntry {
+        int hash;
+        int key;
+        int value;
+        IntHashtableEntry next;
+        
+        public int getKey() {
+            return key;
+        }
+        
+        public int getValue() {
+            return value;
+        }
+        
+        protected Object clone() {
+            IntHashtableEntry entry = new IntHashtableEntry();
+            entry.hash = hash;
+            entry.key = key;
+            entry.value = value;
+            entry.next = (next != null) ? (IntHashtableEntry)next.clone() : null;
+            return entry;
+        }
+    }    
+
+    public Iterator getEntryIterator() {
+        return new IntHashtableIterator(table);
+    }
+    
+    static class IntHashtableIterator implements Iterator {
+        //    boolean keys;
+        int index;
+        IntHashtableEntry table[];
+        IntHashtableEntry entry;
+        
+        IntHashtableIterator(IntHashtableEntry table[] /* , boolean keys */) {
+            this.table = table;
+            //	this.keys = keys;
+            this.index = table.length;
+        }
+        
+        public boolean hasNext() {
+            if (entry != null) {
+                return true;
+            }
+            while (index-- > 0) {
+                if ((entry = table[index]) != null) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        public Object next() {
+            if (entry == null) {
+                while ((index-- > 0) && ((entry = table[index]) == null));
+            }
+            if (entry != null) {
+                IntHashtableEntry e = entry;
+                entry = e.next;
+                return entry;
+            }
+            throw new NoSuchElementException("IntHashtableIterator");
+        }
+        
+        public void remove() {
+            throw new UnsupportedOperationException("remove() not supported.");
+        }
+        
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/LZWDecoder.java b/LibrarySource/com/lowagie/text/pdf/LZWDecoder.java
new file mode 100644
index 0000000..aaffad3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/LZWDecoder.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ *
+ * Adapted from the JAI codecs TIFFLZWDecoder.
+ */
+package com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+import com.lowagie.text.ExceptionConverter;
+/**
+ * A class for performing LZW decoding.
+ *
+ *
+ */
+public class LZWDecoder {
+    
+    byte stringTable[][];
+    byte data[] = null;
+    OutputStream uncompData;
+    int tableIndex, bitsToGet = 9;
+    int bytePointer, bitPointer;
+    int nextData = 0;
+    int nextBits = 0;
+    
+    int andTable[] = {
+        511,
+        1023,
+        2047,
+        4095
+    };
+    
+    public LZWDecoder() {
+    }
+    
+    /**
+     * Method to decode LZW compressed data.
+     *
+     * @param data            The compressed data.
+     * @param uncompData      Array to return the uncompressed data in.
+     */
+    public void decode(byte data[], OutputStream uncompData) {
+        
+        if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
+            throw new RuntimeException("LZW flavour not supported.");
+        }
+        
+        initializeStringTable();
+        
+        this.data = data;
+        this.uncompData = uncompData;
+        
+        // Initialize pointers
+        bytePointer = 0;
+        bitPointer = 0;
+        
+        nextData = 0;
+        nextBits = 0;
+        
+        int code, oldCode = 0;
+        byte string[];
+        
+        while ((code = getNextCode()) != 257) {
+            
+            if (code == 256) {
+                
+                initializeStringTable();
+                code = getNextCode();
+                
+                if (code == 257) {
+                    break;
+                }
+                
+                writeString(stringTable[code]);
+                oldCode = code;
+                
+            } else {
+                
+                if (code < tableIndex) {
+                    
+                    string = stringTable[code];
+                    
+                    writeString(string);
+                    addStringToTable(stringTable[oldCode], string[0]);
+                    oldCode = code;
+                    
+                } else {
+                    
+                    string = stringTable[oldCode];
+                    string = composeString(string, string[0]);
+                    writeString(string);
+                    addStringToTable(string);
+                    oldCode = code;
+                }
+            }
+        }
+    }
+    
+    
+    /**
+     * Initialize the string table.
+     */
+    public void initializeStringTable() {
+        
+        stringTable = new byte[8192][];
+        
+        for (int i=0; i<256; i++) {
+            stringTable[i] = new byte[1];
+            stringTable[i][0] = (byte)i;
+        }
+        
+        tableIndex = 258;
+        bitsToGet = 9;
+    }
+    
+    /**
+     * Write out the string just uncompressed.
+     */
+    public void writeString(byte string[]) {
+        try {
+            uncompData.write(string);
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /**
+     * Add a new string to the string table.
+     */
+    public void addStringToTable(byte oldString[], byte newString) {
+        int length = oldString.length;
+        byte string[] = new byte[length + 1];
+        System.arraycopy(oldString, 0, string, 0, length);
+        string[length] = newString;
+        
+        // Add this new String to the table
+        stringTable[tableIndex++] = string;
+        
+        if (tableIndex == 511) {
+            bitsToGet = 10;
+        } else if (tableIndex == 1023) {
+            bitsToGet = 11;
+        } else if (tableIndex == 2047) {
+            bitsToGet = 12;
+        }
+    }
+    
+    /**
+     * Add a new string to the string table.
+     */
+    public void addStringToTable(byte string[]) {
+        
+        // Add this new String to the table
+        stringTable[tableIndex++] = string;
+        
+        if (tableIndex == 511) {
+            bitsToGet = 10;
+        } else if (tableIndex == 1023) {
+            bitsToGet = 11;
+        } else if (tableIndex == 2047) {
+            bitsToGet = 12;
+        }
+    }
+    
+    /**
+     * Append <code>newString</code> to the end of <code>oldString</code>.
+     */
+    public byte[] composeString(byte oldString[], byte newString) {
+        int length = oldString.length;
+        byte string[] = new byte[length + 1];
+        System.arraycopy(oldString, 0, string, 0, length);
+        string[length] = newString;
+        
+        return string;
+    }
+    
+    // Returns the next 9, 10, 11 or 12 bits
+    public int getNextCode() {
+        // Attempt to get the next code. The exception is caught to make
+        // this robust to cases wherein the EndOfInformation code has been
+        // omitted from a strip. Examples of such cases have been observed
+        // in practice.
+        try {
+            nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+            nextBits += 8;
+            
+            if (nextBits < bitsToGet) {
+                nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+                nextBits += 8;
+            }
+            
+            int code =
+            (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
+            nextBits -= bitsToGet;
+            
+            return code;
+        } catch(ArrayIndexOutOfBoundsException e) {
+            // Strip not terminated as expected: return EndOfInformation code.
+            return 257;
+        }
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/MultiColumnText.java b/LibrarySource/com/lowagie/text/pdf/MultiColumnText.java
new file mode 100644
index 0000000..6b3c38b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/MultiColumnText.java
@@ -0,0 +1,504 @@
+/*
+ * $Id: MultiColumnText.java,v 1.12 2005/04/06 08:54:17 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2004 Steve Appling
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.*;
+
+import java.util.ArrayList;
+
+/**
+ * Formats content into one or more columns bounded by a
+ * rectangle.  The columns may be simple rectangles or
+ * more complicated shapes. Add all of the columns before
+ * adding content. Column continuation is supported. A MultiColumnText object may be added to
+ * a document using <CODE>Document.add</CODE>.
+ * @author Steve Appling
+ */
+public class MultiColumnText implements Element {
+
+    /** special constant for automatic calculation of height */
+    public static final float AUTOMATIC = -1f;
+
+    /**
+     * total desiredHeight of columns.  If <CODE>AUTOMATIC</CODE>, this means fill pages until done.
+     * This may be larger than one page
+     */
+    private float desiredHeight;
+
+    /**
+     * total height of element written out so far
+     */
+    private float totalHeight;
+
+    /**
+     * true if all the text could not be written out due to height restriction
+     */
+    private boolean overflow;
+
+    /**
+     * Top of the columns - y position on starting page.
+     * If <CODE>AUTOMATIC</CODE>, it means current y position when added to document
+     */
+    private float top;
+
+    /**
+     * used to store the y position of the bottom of the page
+     */
+    private float pageBottom;
+
+    /**
+     * ColumnText object used to do all the real work.  This same object is used for all columns
+     */
+    private ColumnText columnText;
+
+    /**
+     * Array of <CODE>ColumnDef</CODE> objects used to define the columns
+     */
+    private ArrayList columnDefs;
+
+    /**
+     * true if all columns are simple (rectangular)
+     */
+    private boolean simple = true;
+
+    private int currentColumn = 0;
+    
+    private float nextY = AUTOMATIC;
+    
+    private boolean columnsRightToLeft = false;
+    
+    private PdfDocument document;
+    /**
+     * Default constructor.  Sets height to <CODE>AUTOMATIC</CODE>.
+     * Columns will repeat on each page as necessary to accomodate content length.
+     */
+    public MultiColumnText() {
+        this(AUTOMATIC);
+    }
+
+    /**
+     * Construct a MultiColumnText container of the specified height.
+     * If height is <CODE>AUTOMATIC</CODE>, fill complete pages until done.
+     * If a specific height is used, it may span one or more pages.
+     *
+     * @param height
+     */
+    public MultiColumnText(float height) {
+        columnDefs = new ArrayList();
+        desiredHeight = height;
+        top = AUTOMATIC;
+        // canvas will be set later
+        columnText = new ColumnText(null);
+        totalHeight = 0f;
+    }
+
+    /**
+     * Indicates that all of the text did not fit in the
+     * specified height. Note that isOverflow will return
+     * false before the MultiColumnText object has been
+     * added to the document.  It will always be false if
+     * the height is AUTOMATIC.
+     *
+     * @return true if there is still space left in the column
+     */
+    public boolean isOverflow() {
+        return overflow;
+    }
+
+    /**
+     * Copy the parameters from the specified ColumnText to use
+     * when rendering.  Parameters like <CODE>setArabicOptions</CODE>
+     * must be set in this way.
+     *
+     * @param sourceColumn
+     */
+    public void useColumnParams(ColumnText sourceColumn) {
+        // note that canvas will be overwritten later
+        columnText.setSimpleVars(sourceColumn);
+    }
+
+    /**
+     * Add a new column.  The parameters are limits for each column
+     * wall in the format of a sequence of points (x1,y1,x2,y2,...).
+     *
+     * @param left  limits for left column
+     * @param right limits for right column
+     */
+    public void addColumn(float[] left, float[] right) {
+        ColumnDef nextDef = new ColumnDef(left, right);
+        simple = nextDef.isSimple();
+        columnDefs.add(nextDef);
+    }
+
+    /**
+     * Add a simple rectangular column with specified left
+     * and right x position boundaries.
+     *
+     * @param left  left boundary
+     * @param right right boundary
+     */
+    public void addSimpleColumn(float left, float right) {
+        ColumnDef newCol = new ColumnDef(left, right);
+        columnDefs.add(newCol);
+    }
+
+    /**
+     * Add the specified number of evenly spaced rectangular columns.
+     * Columns will be seperated by the specified gutterWidth.
+     *
+     * @param left        left boundary of first column
+     * @param right       right boundary of last column
+     * @param gutterWidth width of gutter spacing between columns
+     * @param numColumns  number of columns to add
+     */
+    public void addRegularColumns(float left, float right, float gutterWidth, int numColumns) {
+        float currX = left;
+        float width = right - left;
+        float colWidth = (width - (gutterWidth * (numColumns - 1))) / numColumns;
+        for (int i = 0; i < numColumns; i++) {
+            addSimpleColumn(currX, currX + colWidth);
+            currX += colWidth + gutterWidth;
+        }
+    }
+
+    /**
+     * Add an element to be rendered in a column.
+     * Note that you can only add a <CODE>Phrase</CODE>
+     * or a <CODE>Chunk</CODE> if the columns are
+     * not all simple.  This is an underlying restriction in
+     * {@link com.lowagie.text.pdf.ColumnText}
+     *
+     * @param element element to add
+     * @throws DocumentException if element can't be added
+     */
+    public void addElement(Element element) throws DocumentException {
+        if (simple) {
+            columnText.addElement(element);
+        } else if (element instanceof Phrase) {
+            columnText.addText((Phrase) element);
+        } else if (element instanceof Chunk) {
+            columnText.addText((Chunk) element);
+        } else {
+            throw new DocumentException("Can't add " + element.getClass() + " to MultiColumnText with complex columns");
+        }
+    }
+
+
+    /**
+     * Write out the columns.  After writing, use
+     * {@link #isOverflow()} to see if all text was written.
+     * @param canvas PdfContentByte to write with
+     * @param document document to write to (only used to get page limit info)
+     * @param documentY starting y position to begin writing at
+     * @return the current height (y position) after writing the columns
+     * @throws DocumentException on error
+     */
+    public float write(PdfContentByte canvas, PdfDocument document, float documentY) throws DocumentException {
+        this.document = document;
+        columnText.setCanvas(canvas);
+        if (columnDefs.size() == 0) {
+            throw new DocumentException("MultiColumnText has no columns");
+        }
+        overflow = false;
+        pageBottom = document.bottom();
+        float currentHeight = 0;
+        boolean done = false;
+        try {
+            while (!done) {
+                if (nextY == AUTOMATIC) {
+                    nextY = documentY;
+                }
+                if (top == AUTOMATIC) {
+                    top = documentY;  // shouldn't I be able to get this from the document?
+                }
+
+                ColumnDef currentDef = (ColumnDef) columnDefs.get(getCurrentColumn());
+                columnText.setYLine(top);
+
+                float[] left = currentDef.resolvePositions(Rectangle.LEFT);
+                float[] right = currentDef.resolvePositions(Rectangle.RIGHT);
+                currentHeight = Math.max(currentHeight, getHeight(left, right));
+
+                if (currentDef.isSimple()) {
+                    columnText.setSimpleColumn(left[2], left[3], right[0], right[1]);
+                } else {
+                    columnText.setColumns(left, right);
+                }
+
+                int result = columnText.go();
+                if ((result & ColumnText.NO_MORE_TEXT) != 0) {
+                    done = true;
+                    top = columnText.getYLine();
+                } else if (shiftCurrentColumn()) {
+                    top = nextY;
+                } else {  // check if we are done because of height
+                    totalHeight += currentHeight;
+
+                    if ((desiredHeight != AUTOMATIC) && (totalHeight >= desiredHeight)) {
+                        overflow = true;
+                        break;
+                    } else {  // need to start new page and reset the columns
+                        newPage();
+                        currentHeight = 0;
+                    }
+                }
+            }
+        } catch (DocumentException ex) {
+            ex.printStackTrace();
+            throw ex;
+        }
+        return currentHeight;
+    }
+
+    private void newPage() throws DocumentException {
+        resetCurrentColumn();
+        top = nextY = AUTOMATIC;
+        if (document != null) {
+            document.newPage();
+        }
+    }
+    
+    /**
+     * Figure out the height of a column from the border extents
+     *
+     * @param left  left border
+     * @param right right border
+     * @return height
+     */
+    private float getHeight(float[] left, float[] right) {
+        float max = Float.MIN_VALUE;
+        float min = Float.MAX_VALUE;
+        for (int i = 0; i < left.length; i += 2) {
+            min = Math.min(min, left[i + 1]);
+            max = Math.max(max, left[i + 1]);
+        }
+        for (int i = 0; i < right.length; i += 2) {
+            min = Math.min(min, right[i + 1]);
+            max = Math.max(max, right[i + 1]);
+        }
+        return max - min;
+    }
+
+
+    /**
+     * Processes the element by adding it to an
+     * <CODE>ElementListener</CODE>.
+     *
+     * @param	listener	an <CODE>ElementListener</CODE>
+     * @return	<CODE>true</CODE> if the element was processed successfully
+     */
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        } catch (DocumentException de) {
+            return false;
+        }
+    }
+
+    /**
+     * Gets the type of the text element.
+     *
+     * @return	a type
+     */
+
+    public int type() {
+        return Element.MULTI_COLUMN_TEXT;
+    }
+
+    /**
+     * Returns null - not used
+     *
+     * @return	null
+     */
+
+    public ArrayList getChunks() {
+        return null;
+    }
+
+    /**
+     * Calculates the appropriate y position for the bottom
+     * of the columns on this page.
+     *
+     * @return the y position of the bottom of the columns
+     */
+    private float getColumnBottom() {
+        if (desiredHeight == AUTOMATIC) {
+            return pageBottom;
+        } else {
+            return Math.max(top - (desiredHeight - totalHeight), pageBottom);
+        }
+    }
+
+    /**
+     * Moves the text insertion point to the beginning of the next column, issuing a page break if
+     * needed.
+     * @throws DocumentException on error
+     */    
+    public void nextColumn() throws DocumentException {
+        currentColumn = (currentColumn + 1) % columnDefs.size();
+        top = nextY;
+        if (currentColumn == 0) {
+            newPage();
+        }
+    }
+
+    /**
+     * Gets the current column.
+     * @return the current column
+     */
+    public int getCurrentColumn() {
+    	if (columnsRightToLeft) {
+    		return (columnDefs.size() - currentColumn - 1);
+    	} 
+        return currentColumn;
+    }
+    
+    /**
+     * Resets the current column.
+     */
+    public void resetCurrentColumn() {
+    	currentColumn = 0;
+    }
+    
+    /**
+     * Shifts the current column.
+     * @return true if the currentcolumn has changed
+     */
+    public boolean shiftCurrentColumn() {
+    	if (currentColumn + 1 < columnDefs.size()) {
+            currentColumn++;
+            return true;
+    	}
+    	return false;
+    }
+    
+    /**
+     * Sets the direction of the columns.
+     * @param direction true = right2left; false = left2right
+     */
+    public void setColumnsRightToLeft(boolean direction) {
+    	columnsRightToLeft = direction;
+    }
+    
+    /**
+     * Inner class used to define a column
+     */
+    private class ColumnDef {
+        private float[] left;
+        private float[] right;
+
+        ColumnDef(float[] newLeft, float[] newRight) {
+            left = newLeft;
+            right = newRight;
+        }
+
+        ColumnDef(float leftPosition, float rightPosition) {
+            left = new float[4];
+            left[0] = leftPosition; // x1
+            left[1] = top;          // y1
+            left[2] = leftPosition; // x2
+            if (desiredHeight == AUTOMATIC || top == AUTOMATIC) {
+                left[3] = AUTOMATIC;
+            } else {
+                left[3] = top - desiredHeight;
+            }
+
+            right = new float[4];
+            right[0] = rightPosition; // x1
+            right[1] = top;           // y1
+            right[2] = rightPosition; // x2
+            if (desiredHeight == AUTOMATIC || top == AUTOMATIC) {
+                right[3] = AUTOMATIC;
+            } else {
+                right[3] = top - desiredHeight;
+            }
+        }
+
+        /**
+         * Resolves the positions for the specified side of the column
+         * into real numbers once the top of the column is known.
+         *
+         * @param side either <CODE>Rectangle.LEFT</CODE>
+         *             or <CODE>Rectangle.RIGHT</CODE>
+         * @return the array of floats for the side
+         */
+        float[] resolvePositions(int side) {
+            if (side == Rectangle.LEFT) {
+                return resolvePositions(left);
+            } else {
+                return resolvePositions(right);
+            }
+        }
+
+        private float[] resolvePositions(float[] positions) {
+            if (!isSimple()) {
+                return positions;
+            }
+            if (top == AUTOMATIC) {
+                // this is bad - must be programmer error
+                throw new RuntimeException("resolvePositions called with top=AUTOMATIC (-1).  " +
+                        "Top position must be set befure lines can be resolved");
+            }
+            positions[1] = top;
+            positions[3] = getColumnBottom();
+            return positions;
+        }
+
+        /**
+         * Checks if column definition is a simple rectangle
+         * @return true if it is a simple column 
+         */
+        private boolean isSimple() {
+            return (left.length == 4 && right.length == 4) && (left[0] == left[2] && right[0] == right[2]);
+        }
+
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/OutputStreamCounter.java b/LibrarySource/com/lowagie/text/pdf/OutputStreamCounter.java
new file mode 100644
index 0000000..74f8188
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/OutputStreamCounter.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author  psoares
+ */
+public class OutputStreamCounter extends OutputStream {
+    
+    protected OutputStream out;
+    protected int counter = 0;
+    
+    /** Creates a new instance of OutputStreamCounter */
+    public OutputStreamCounter(OutputStream out) {
+        this.out = out;
+    }
+    
+    /** Closes this output stream and releases any system resources
+     * associated with this stream. The general contract of <code>close</code>
+     * is that it closes the output stream. A closed stream cannot perform
+     * output operations and cannot be reopened.
+     * <p>
+     * The <code>close</code> method of <code>OutputStream</code> does nothing.
+     *
+     * @exception  IOException  if an I/O error occurs.
+     *
+     */
+    public void close() throws IOException {
+        out.close();
+    }
+    
+    /** Flushes this output stream and forces any buffered output bytes
+     * to be written out. The general contract of <code>flush</code> is
+     * that calling it is an indication that, if any bytes previously
+     * written have been buffered by the implementation of the output
+     * stream, such bytes should immediately be written to their
+     * intended destination.
+     * <p>
+     * The <code>flush</code> method of <code>OutputStream</code> does nothing.
+     *
+     * @exception  IOException  if an I/O error occurs.
+     *
+     */
+    public void flush() throws IOException {
+        out.flush();
+    }
+    
+    /** Writes <code>b.length</code> bytes from the specified byte array
+     * to this output stream. The general contract for <code>write(b)</code>
+     * is that it should have exactly the same effect as the call
+     * <code>write(b, 0, b.length)</code>.
+     *
+     * @param      b   the data.
+     * @exception  IOException  if an I/O error occurs.
+     * @see        java.io.OutputStream#write(byte[], int, int)
+     *
+     */
+    public void write(byte[] b) throws IOException {
+        counter += b.length;
+        out.write(b);
+    }
+    
+    /** Writes the specified byte to this output stream. The general
+     * contract for <code>write</code> is that one byte is written
+     * to the output stream. The byte to be written is the eight
+     * low-order bits of the argument <code>b</code>. The 24
+     * high-order bits of <code>b</code> are ignored.
+     * <p>
+     * Subclasses of <code>OutputStream</code> must provide an
+     * implementation for this method.
+     *
+     * @param      b   the <code>byte</code>.
+     * @exception  IOException  if an I/O error occurs. In particular,
+     *             an <code>IOException</code> may be thrown if the
+     *             output stream has been closed.
+     *
+     */
+    public void write(int b) throws IOException {
+        ++counter;
+        out.write(b);
+    }
+    
+    /** Writes <code>len</code> bytes from the specified byte array
+     * starting at offset <code>off</code> to this output stream.
+     * The general contract for <code>write(b, off, len)</code> is that
+     * some of the bytes in the array <code>b</code> are written to the
+     * output stream in order; element <code>b[off]</code> is the first
+     * byte written and <code>b[off+len-1]</code> is the last byte written
+     * by this operation.
+     * <p>
+     * The <code>write</code> method of <code>OutputStream</code> calls
+     * the write method of one argument on each of the bytes to be
+     * written out. Subclasses are encouraged to override this method and
+     * provide a more efficient implementation.
+     * <p>
+     * If <code>b</code> is <code>null</code>, a
+     * <code>NullPointerException</code> is thrown.
+     * <p>
+     * If <code>off</code> is negative, or <code>len</code> is negative, or
+     * <code>off+len</code> is greater than the length of the array
+     * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
+     *
+     * @param      b     the data.
+     * @param      off   the start offset in the data.
+     * @param      len   the number of bytes to write.
+     * @exception  IOException  if an I/O error occurs. In particular,
+     *             an <code>IOException</code> is thrown if the output
+     *             stream is closed.
+     *
+     */
+    public void write(byte[] b, int off, int len) throws IOException {
+        counter += len;
+        out.write(b, off, len);
+    }
+    
+    public int getCounter() {
+        return counter;
+    }
+    
+    public void resetCounter() {
+        counter = 0;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PRIndirectReference.java b/LibrarySource/com/lowagie/text/pdf/PRIndirectReference.java
new file mode 100644
index 0000000..89f4365
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PRIndirectReference.java
@@ -0,0 +1,103 @@
+/*
+ * $Id: PRIndirectReference.java,v 1.12 2002/07/09 11:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class PRIndirectReference extends PdfIndirectReference {
+    
+    protected PdfReader reader;
+    // membervariables
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfIndirectReference</CODE>.
+ *
+ * @param		reader			a <CODE>PdfReader</CODE>
+ * @param		number			the object number.
+ * @param		generation		the generation number.
+ */
+    
+    PRIndirectReference(PdfReader reader, int number, int generation) {
+        type = INDIRECT;
+        this.number = number;
+        this.generation = generation;
+        this.reader = reader;
+    }
+    
+/**
+ * Constructs a <CODE>PdfIndirectReference</CODE>.
+ *
+ * @param		reader			a <CODE>PdfReader</CODE>
+ * @param		number			the object number.
+ */
+    
+    PRIndirectReference(PdfReader reader, int number) {
+        this(reader, number, 0);
+    }
+    
+    // methods
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        int n = writer.getNewObjectNumber(reader, number, generation);
+        os.write(PdfEncodings.convertToBytes(new StringBuffer().append(n).append(" 0 R").toString(), null));
+    }
+
+    public PdfReader getReader() {
+        return reader;
+    }
+    
+    public void setNumber(int number, int generation) {
+        this.number = number;
+        this.generation = generation;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PRStream.java b/LibrarySource/com/lowagie/text/pdf/PRStream.java
new file mode 100644
index 0000000..2514d99
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PRStream.java
@@ -0,0 +1,229 @@
+/*
+ * $Id: PRStream.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import com.lowagie.text.ExceptionConverter;
+import java.util.zip.DeflaterOutputStream;
+import com.lowagie.text.Document;
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class PRStream extends PdfStream {
+    
+    protected PdfReader reader;
+    protected int offset;
+    protected int length;
+    
+    //added by ujihara for decryption
+    protected int objNum = 0;
+    protected int objGen = 0;
+    
+    public PRStream(PRStream stream, PdfDictionary newDic) {
+        reader = stream.reader;
+        offset = stream.offset;
+        length = stream.length;
+        compressed = stream.compressed;
+        streamBytes = stream.streamBytes;
+        bytes = stream.bytes;
+        objNum = stream.objNum;
+        objGen = stream.objGen;
+        if (newDic != null)
+            putAll(newDic);
+        else
+            hashMap.putAll(stream.hashMap);
+    }
+
+    public PRStream(PRStream stream, PdfDictionary newDic, PdfReader reader) {
+        this(stream, newDic);
+        this.reader = reader;
+    }
+
+    public PRStream(PdfReader reader, int offset) {
+        this.reader = reader;
+        this.offset = offset;
+    }
+    
+    public PRStream(PdfReader reader, byte conts[]) {
+        this.reader = reader;
+        this.offset = -1;
+        if (Document.compress) {
+            try {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                DeflaterOutputStream zip = new DeflaterOutputStream(stream);
+                zip.write(conts);
+                zip.close();
+                bytes = stream.toByteArray();
+            }
+            catch (IOException ioe) {
+                throw new ExceptionConverter(ioe);
+            }
+            put(PdfName.FILTER, PdfName.FLATEDECODE);
+        }
+        else
+            bytes = conts;
+        setLength(bytes.length);
+    }
+    
+    /**Sets the data associated with the stream
+     * @param data raw data, decrypted and uncompressed.
+     */
+    public void setData(byte[] data) {
+        remove(PdfName.FILTER);
+        this.offset = -1;
+        if (Document.compress) {
+            try {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                DeflaterOutputStream zip = new DeflaterOutputStream(stream);
+                zip.write(data);
+                zip.close();
+                bytes = stream.toByteArray();
+            }
+            catch (IOException ioe) {
+                throw new ExceptionConverter(ioe);
+            }
+            put(PdfName.FILTER, PdfName.FLATEDECODE);
+        }
+        else
+            bytes = data;
+        setLength(bytes.length);
+    }
+
+    public void setLength(int length) {
+        this.length = length;
+        put(PdfName.LENGTH, new PdfNumber(length));
+    }
+    
+    public int getOffset() {
+        return offset;
+    }
+    
+    public int getLength() {
+        return length;
+    }
+    
+    public PdfReader getReader() {
+        return reader;
+    }
+    
+    public byte[] getBytes() {
+        return bytes;
+    }
+    
+    public void setObjNum(int objNum, int objGen) {
+        this.objNum = objNum;
+        this.objGen = objGen;
+    }
+    
+    int getObjNum() {
+        return objNum;
+    }
+    
+    int getObjGen() {
+        return objGen;
+    }
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        superToPdf(writer, os);
+        os.write(STARTSTREAM);
+        if (length > 0) {
+            PdfEncryption crypto = null;
+            if (writer != null)
+                crypto = writer.getEncryption();
+            if (offset < 0) {
+                if (crypto == null)
+                    os.write(bytes);
+                else {
+                    crypto.prepareKey();
+                    byte buf[] = new byte[length];
+                    System.arraycopy(bytes, 0, buf, 0, length);
+                    crypto.encryptRC4(buf);
+                    os.write(buf);
+                }
+            }
+            else {
+                byte buf[] = new byte[Math.min(length, 4092)];
+                RandomAccessFileOrArray file = writer.getReaderFile(reader);
+                boolean isOpen = file.isOpen();
+                try {
+                    file.seek(offset);
+                    int size = length;
+
+                    //added by ujihara for decryption
+                    PdfEncryption decrypt = reader.getDecrypt();
+                    if (decrypt != null) {
+                        decrypt.setHashKey(objNum, objGen);
+                        decrypt.prepareKey();
+                    }
+
+                    if (crypto != null)
+                        crypto.prepareKey();
+                    while (size > 0) {
+                        int r = file.read(buf, 0, Math.min(size, buf.length));
+                        size -= r;
+
+                        if (decrypt != null)
+                            decrypt.encryptRC4(buf, 0, r); //added by ujihara for decryption
+
+                        if (crypto != null)
+                            crypto.encryptRC4(buf, 0, r);
+                        os.write(buf, 0, r);
+                    }
+                }
+                finally {
+                    if (!isOpen)
+                        try{file.close();}catch(Exception e){}
+                }
+            }
+        }
+        os.write(ENDSTREAM);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PRTokeniser.java b/LibrarySource/com/lowagie/text/pdf/PRTokeniser.java
new file mode 100644
index 0000000..67d7141
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PRTokeniser.java
@@ -0,0 +1,587 @@
+/*
+ * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+/**
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class PRTokeniser {
+    
+    public static final int TK_NUMBER = 1;
+    public static final int TK_STRING = 2;
+    public static final int TK_NAME = 3;
+    public static final int TK_COMMENT = 4;
+    public static final int TK_START_ARRAY = 5;
+    public static final int TK_END_ARRAY = 6;
+    public static final int TK_START_DIC = 7;
+    public static final int TK_END_DIC = 8;
+    public static final int TK_REF = 9;
+    public static final int TK_OTHER = 10;
+    public static final boolean delims[] = {
+        true,  true,  false, false, false, false, false, false, false, false,
+        true,  true,  false, true,  true,  false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, true,  false, false, false, false, true,  false,
+        false, true,  true,  false, false, false, false, false, true,  false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, true,  false, true,  false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, true,  false, true,  false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false, false, false, false,
+        false, false, false, false, false, false, false};
+    
+    static final String EMPTY = "";
+
+    
+    protected RandomAccessFileOrArray file;
+    protected int type;
+    protected String stringValue;
+    protected int reference;
+    protected int generation;
+    protected boolean hexString;
+    
+    private static final int LINE_SEGMENT_SIZE = 256;
+    
+    public PRTokeniser(String filename) throws IOException {
+        file = new RandomAccessFileOrArray(filename);
+    }
+
+    public PRTokeniser(byte pdfIn[]) {
+        file = new RandomAccessFileOrArray(pdfIn);
+    }
+    
+    public PRTokeniser(RandomAccessFileOrArray file) {
+        this.file = file;
+    }
+    
+    public void seek(int pos) throws IOException {
+        file.seek(pos);
+    }
+    
+    public int getFilePointer() throws IOException {
+        return file.getFilePointer();
+    }
+
+    public void close() throws IOException {
+        file.close();
+    }
+    
+    public int length() throws IOException {
+        return file.length();
+    }
+
+    public int read() throws IOException {
+        return file.read();
+    }
+    
+    public RandomAccessFileOrArray getSafeFile() {
+        return new RandomAccessFileOrArray(file);
+    }
+    
+    public RandomAccessFileOrArray getFile() {
+        return file;
+    }
+    
+    public String readString(int size) throws IOException {
+        StringBuffer buf = new StringBuffer();
+        int ch;
+        while ((size--) > 0) {
+            ch = file.read();
+            if (ch == -1)
+                break;
+            buf.append((char)ch);
+        }
+        return buf.toString();
+    }
+
+    public static final boolean isWhitespace(int ch) {
+        return (ch == 0 || ch == 9 || ch == 10 || ch == 12 || ch == 13 || ch == 32);
+    }
+    
+    public static final boolean isDelimiter(int ch) {
+        return (ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '/' || ch == '%');
+    }
+
+    public static final boolean isDelimiterWhitespace(int ch) {
+        return delims[ch + 1];
+    }
+
+    public int getTokenType() {
+        return type;
+    }
+    
+    public String getStringValue() {
+        return stringValue;
+    }
+    
+    public int getReference() {
+        return reference;
+    }
+    
+    public int getGeneration() {
+        return generation;
+    }
+    
+    public void backOnePosition(int ch) throws IOException {
+        if (ch != -1)
+            file.pushBack((byte)ch);
+    }
+    
+    public void throwError(String error) throws IOException {
+        throw new IOException(error + " at file pointer " + file.getFilePointer());
+    }
+    
+    public char checkPdfHeader() throws IOException {
+        file.setStartOffset(0);
+        String str = readString(1024);
+        int idx = str.indexOf("%PDF-1.");
+        if (idx < 0)
+            throw new IOException("PDF header signature not found.");
+        file.setStartOffset(idx);
+        return str.charAt(idx + 7);
+    }
+    
+    public void checkFdfHeader() throws IOException {
+        file.setStartOffset(0);
+        String str = readString(1024);
+        int idx = str.indexOf("%FDF-1.2");
+        if (idx < 0)
+            throw new IOException("FDF header signature not found.");
+        file.setStartOffset(idx);
+    }
+
+    public int getStartxref() throws IOException {
+        int size = Math.min(1024, file.length());
+        int pos = file.length() - size;
+        file.seek(pos);
+        String str = readString(1024);
+        int idx = str.lastIndexOf("startxref");
+        if (idx < 0)
+            throw new IOException("PDF startxref not found.");
+        return pos + idx;
+    }
+
+    public static int getHex(int v) {
+        if (v >= '0' && v <= '9')
+            return v - '0';
+        if (v >= 'A' && v <= 'F')
+            return v - 'A' + 10;
+        if (v >= 'a' && v <= 'f')
+            return v - 'a' + 10;
+        return -1;
+    }
+    
+    public void nextValidToken() throws IOException {
+        int level = 0;
+        String n1 = null;
+        String n2 = null;
+        int ptr = 0;
+        while (nextToken()) {
+            if (type == TK_COMMENT)
+                continue;
+            switch (level) {
+                case 0:
+                {
+                    if (type != TK_NUMBER)
+                        return;
+                    ptr = file.getFilePointer();
+                    n1 = stringValue;
+                    ++level;
+                    break;
+                }
+                case 1:
+                {
+                    if (type != TK_NUMBER) {
+                        file.seek(ptr);
+                        type = TK_NUMBER;
+                        stringValue = n1;
+                        return;
+                    }
+                    n2 = stringValue;
+                    ++level;
+                    break;
+                }
+                default:
+                {
+                    if (type != TK_OTHER || !stringValue.equals("R")) {
+                        file.seek(ptr);
+                        type = TK_NUMBER;
+                        stringValue = n1;
+                        return;
+                    }
+                    type = TK_REF;
+                    reference = Integer.valueOf(n1).intValue();
+                    generation = Integer.valueOf(n2).intValue();
+                    return;
+                }
+            }
+        }
+        throwError("Unexpected end of file");
+    }
+    
+    public boolean nextToken() throws IOException {
+        StringBuffer outBuf = null;
+        stringValue = EMPTY;
+        int ch = 0;
+        do {
+            ch = file.read();
+        } while (ch != -1 && isWhitespace(ch));
+        if (ch == -1)
+            return false;
+        switch (ch) {
+            case '[':
+                type = TK_START_ARRAY;
+                break;
+            case ']':
+                type = TK_END_ARRAY;
+                break;
+            case '/':
+            {
+                outBuf = new StringBuffer();
+                type = TK_NAME;
+                while (true) {
+                    ch = file.read();
+                    if (delims[ch + 1])
+                        break;
+                    if (ch == '#') {
+                        ch = (getHex(file.read()) << 4) + getHex(file.read());
+                    }
+                    outBuf.append((char)ch);
+                }
+                backOnePosition(ch);
+                break;
+            }
+            case '>':
+                ch = file.read();
+                if (ch != '>')
+                    throwError("'>' not expected");
+                type = TK_END_DIC;
+                break;
+            case '<':
+            {
+                int v1 = file.read();
+                if (v1 == '<') {
+                    type = TK_START_DIC;
+                    break;
+                }
+                outBuf = new StringBuffer();
+                type = TK_STRING;
+                hexString = true;
+                int v2 = 0;
+                while (true) {
+                    while (isWhitespace(v1))
+                        v1 = file.read();
+                    if (v1 == '>')
+                        break;
+                    v1 = getHex(v1);
+                    if (v1 < 0)
+                        break;
+                    v2 = file.read();
+                    while (isWhitespace(v2))
+                        v2 = file.read();
+                    if (v2 == '>') {
+                        ch = v1 << 4;
+                        outBuf.append((char)ch);
+                        break;
+                    }
+                    v2 = getHex(v2);
+                    if (v2 < 0)
+                        break;
+                    ch = (v1 << 4) + v2;
+                    outBuf.append((char)ch);
+                    v1 = file.read();
+                }
+                if (v1 < 0 || v2 < 0)
+                    throwError("Error reading string");
+                break;
+            }
+            case '%':
+                type = TK_COMMENT;
+                do {
+                    ch = file.read();
+                } while (ch != -1 && ch != '\r' && ch != '\n');
+                break;
+            case '(':
+            {
+                outBuf = new StringBuffer();
+                type = TK_STRING;
+                hexString = false;
+                int nesting = 0;
+                while (true) {
+                    ch = file.read();
+                    if (ch == -1)
+                        break;
+                    if (ch == '(') {
+                        ++nesting;
+                    }
+                    else if (ch == ')') {
+                        --nesting;
+                    }
+                    else if (ch == '\\') {
+                        boolean lineBreak = false;
+                        ch = file.read();
+                        switch (ch) {
+                            case 'n':
+                                ch = '\n';
+                                break;
+                            case 'r':
+                                ch = '\r';
+                                break;
+                            case 't':
+                                ch = '\t';
+                                break;
+                            case 'b':
+                                ch = '\b';
+                                break;
+                            case 'f':
+                                ch = '\f';
+                                break;
+                            case '(':
+                            case ')':
+                            case '\\':
+                                break;
+                            case '\r':
+                                lineBreak = true;
+                                ch = file.read();
+                                if (ch != '\n')
+                                    backOnePosition(ch);
+                                break;
+                            case '\n':
+                                lineBreak = true;
+                                break;
+                            default:
+                            {
+                                if (ch < '0' || ch > '7') {
+                                    break;
+                                }
+                                int octal = ch - '0';
+                                ch = file.read();
+                                if (ch < '0' || ch > '7') {
+                                    backOnePosition(ch);
+                                    ch = octal;
+                                    break;
+                                }
+                                octal = (octal << 3) + ch - '0';
+                                ch = file.read();
+                                if (ch < '0' || ch > '7') {
+                                    backOnePosition(ch);
+                                    ch = octal;
+                                    break;
+                                }
+                                octal = (octal << 3) + ch - '0';
+                                ch = octal & 0xff;
+                                break;
+                            }
+                        }
+                        if (lineBreak)
+                            continue;
+                        if (ch < 0)
+                            break;
+                    }
+                    else if (ch == '\r') {
+                        ch = file.read();
+                        if (ch < 0)
+                            break;
+                        if (ch != '\n') {
+                            backOnePosition(ch);
+                            ch = '\n';
+                        }
+                    }
+                    if (nesting == -1)
+                        break;
+                    outBuf.append((char)ch);
+                }
+                if (ch == -1)
+                    throwError("Error reading string");
+                break;
+            }
+            default:
+            {
+                outBuf = new StringBuffer();
+                if (ch == '-' || ch == '+' || ch == '.' || (ch >= '0' && ch <= '9')) {
+                    type = TK_NUMBER;
+                    do {
+                        outBuf.append((char)ch);
+                        ch = file.read();
+                    } while (ch != -1 && ((ch >= '0' && ch <= '9') || ch == '.'));
+                }
+                else {
+                    type = TK_OTHER;
+                    do {
+                        outBuf.append((char)ch);
+                        ch = file.read();
+                    } while (!delims[ch + 1]);
+                }
+                backOnePosition(ch);
+                break;
+            }
+        }
+        if (outBuf != null)
+            stringValue = outBuf.toString();
+        return true;
+    }
+    
+    public int intValue() {
+        return Integer.valueOf(stringValue).intValue();
+    }
+    
+    public boolean readLineSegment(byte input[]) throws IOException {
+        int c = -1;
+        boolean eol = false;
+        int ptr = 0;
+        int len = input.length;
+	// ssteward, pdftk-1.10, 040922: 
+	// skip initial whitespace; added this because PdfReader.rebuildXref()
+	// assumes that line provided by readLineSegment does not have init. whitespace;
+	if ( ptr < len ) {
+	    while ( isWhitespace( (c = read()) ) );
+	}
+	while ( !eol && ptr < len ) {
+	    switch (c) {
+                case -1:
+                case '\n':
+                    eol = true;
+                    break;
+                case '\r':
+                    eol = true;
+                    int cur = getFilePointer();
+                    if ((read()) != '\n') {
+                        seek(cur);
+                    }
+                    break;
+                default:
+                    input[ptr++] = (byte)c;
+                    break;
+            }
+
+	    // break loop? do it before we read() again
+	    if( eol || len <= ptr ) {
+		break;
+	    }
+	    else {
+		c = read();
+	    }
+        }
+        if (ptr >= len) {
+            eol = false;
+            while (!eol) {
+                switch (c = read()) {
+                    case -1:
+                    case '\n':
+                        eol = true;
+                        break;
+                    case '\r':
+                        eol = true;
+                        int cur = getFilePointer();
+                        if ((read()) != '\n') {
+                            seek(cur);
+                        }
+                        break;
+                }
+            }
+        }
+        
+        if ((c == -1) && (ptr == 0)) {
+            return false;
+        }
+        if (ptr + 2 <= len) {
+            input[ptr++] = (byte)' ';
+            input[ptr] = (byte)'X';
+        }
+        return true;
+    }
+    
+    public static int[] checkObjectStart(byte line[]) {
+        try {
+            PRTokeniser tk = new PRTokeniser(line);
+            int num = 0;
+            int gen = 0;
+            if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
+                return null;
+            num = tk.intValue();
+            if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
+                return null;
+            gen = tk.intValue();
+            if (!tk.nextToken())
+                return null;
+            if (!tk.getStringValue().equals("obj"))
+                return null;
+            return new int[]{num, gen};
+        }
+        catch (Exception ioe) {
+            // empty on purpose
+        }
+        return null;
+    }
+    
+    public boolean isHexString() {
+        return this.hexString;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PageResources.java b/LibrarySource/com/lowagie/text/pdf/PageResources.java
new file mode 100644
index 0000000..2583220
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PageResources.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+class PageResources {
+    
+    protected PdfDictionary fontDictionary = new PdfDictionary();
+    protected PdfDictionary xObjectDictionary = new PdfDictionary();
+    protected PdfDictionary colorDictionary = new PdfDictionary();
+    protected PdfDictionary patternDictionary = new PdfDictionary();
+    protected PdfDictionary shadingDictionary = new PdfDictionary();
+    protected PdfDictionary extGStateDictionary = new PdfDictionary();
+    protected PdfDictionary LayerDictionary = new PdfDictionary();
+    protected HashMap forbiddenNames;
+    protected PdfDictionary originalResources;
+    protected int namePtr[] = {0};
+    protected HashMap usedNames;
+
+    PageResources() {
+    }
+    
+    void setOriginalResources(PdfDictionary resources, int newNamePtr[]) {
+        if (newNamePtr != null)
+            namePtr = newNamePtr;
+        originalResources = resources;
+        forbiddenNames = new HashMap();
+        usedNames = new HashMap();
+        if (resources == null)
+            return;
+        for (Iterator i = resources.getKeys().iterator(); i.hasNext();) {
+            PdfObject sub = PdfReader.getPdfObject(resources.get((PdfName)i.next()));
+            if (sub.isDictionary()) {
+                PdfDictionary dic = (PdfDictionary)sub;
+                for (Iterator j = dic.getKeys().iterator(); j.hasNext();) {
+                    forbiddenNames.put(j.next(), null);
+                }
+            }
+        }
+    }
+    
+    PdfName translateName(PdfName name) {
+        PdfName translated = name;
+        if (forbiddenNames != null) {
+            translated = (PdfName)usedNames.get(name);
+            if (translated == null) {
+                while (true) {
+                    translated = new PdfName("Xi" + (namePtr[0]++));
+                    if (!forbiddenNames.containsKey(translated))
+                        break;
+                }
+                usedNames.put(name, translated);
+            }
+        }
+        return translated;
+    }
+    
+    PdfName addFont(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        fontDictionary.put(name, reference);
+        return name;
+    }
+
+    PdfName addXObject(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        xObjectDictionary.put(name, reference);
+        return name;
+    }
+
+    PdfName addColor(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        colorDictionary.put(name, reference);
+        return name;
+    }
+
+    void addDefaultColor(PdfName name, PdfObject obj) {
+        if (obj == null || obj.isNull())
+            colorDictionary.remove(name);
+        else
+            colorDictionary.put(name, obj);
+    }
+
+    void addDefaultColor(PdfDictionary dic) {
+        colorDictionary.merge(dic);
+    }
+
+    void addDefaultColorDiff(PdfDictionary dic) {
+        colorDictionary.mergeDifferent(dic);
+    }
+
+    PdfName addShading(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        shadingDictionary.put(name, reference);
+        return name;
+    }
+    
+    PdfName addPattern(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        patternDictionary.put(name, reference);
+        return name;
+    }
+
+    PdfName addExtGState(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        extGStateDictionary.put(name, reference);
+        return name;
+    }
+
+    PdfName addLayer(PdfName name, PdfIndirectReference reference) {
+        name = translateName(name);
+        LayerDictionary.put(name, reference);
+        return name;
+    }
+
+    PdfDictionary getResources() {
+       PdfResources resources = new PdfResources();
+        if (originalResources != null)
+            resources.putAll(originalResources);
+        resources.put(PdfName.PROCSET, new PdfLiteral("[/PDF /Text /ImageB /ImageC /ImageI]"));
+        resources.add(PdfName.FONT, fontDictionary);
+        resources.add(PdfName.XOBJECT, xObjectDictionary);
+        resources.add(PdfName.COLORSPACE, colorDictionary);
+        resources.add(PdfName.PATTERN, patternDictionary);
+        resources.add(PdfName.SHADING, shadingDictionary);
+        resources.add(PdfName.EXTGSTATE, extGStateDictionary);
+        resources.add(PdfName.PROPERTIES, LayerDictionary);
+        return resources;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PatternColor.java b/LibrarySource/com/lowagie/text/pdf/PatternColor.java
new file mode 100644
index 0000000..9db2624
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PatternColor.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/** Represents a pattern. Can be used in high-level constructs (Paragraph, Cell, etc.).
+ */
+public class PatternColor extends ExtendedColor {
+    /**
+     * The actual pattern.
+     */    
+    PdfPatternPainter painter;
+    
+    /** Creates a color representing a pattern.
+     * @param painter the actual pattern
+     */    
+    public PatternColor(PdfPatternPainter painter) {
+        super(TYPE_PATTERN, .5f, .5f, .5f);
+        this.painter = painter;
+    }
+    
+    /** Gets the pattern.
+     * @return the pattern
+     */    
+    public PdfPatternPainter getPainter() {
+        return this.painter;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfAcroForm.java b/LibrarySource/com/lowagie/text/pdf/PdfAcroForm.java
new file mode 100644
index 0000000..071b600
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfAcroForm.java
@@ -0,0 +1,744 @@
+/*
+ * $Id: PdfAcroForm.java,v 1.44 2005/03/30 10:10:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.Iterator;
+import java.util.HashMap;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * Each PDF document can contain maximum 1 AcroForm.
+ */
+
+public class PdfAcroForm extends PdfDictionary {
+
+    private PdfWriter writer;
+
+
+    /** This is a map containing FieldTemplates. */
+    private HashMap fieldTemplates = new HashMap();
+
+    /** This is an array containing DocumentFields. */
+    private PdfArray documentFields = new PdfArray();
+
+    /** This is an array containing the calculationorder of the fields. */
+    private PdfArray calculationOrder = new PdfArray();
+
+    /** Contains the signature flags. */
+    private int sigFlags = 0;
+
+    /** Creates new PdfAcroForm 
+     * @param writer*/
+    PdfAcroForm(PdfWriter writer) {
+        super();
+        this.writer = writer;
+    }
+
+    /**
+     * Adds fieldTemplates.
+     * @param ft
+     */
+
+    void addFieldTemplates(HashMap ft) {
+        fieldTemplates.putAll(ft);
+    }
+
+    /**
+     * Adds documentFields.
+     * @param ref
+     */
+
+    void addDocumentField(PdfIndirectReference ref) {
+        documentFields.add(ref);
+    }
+
+    /**
+     * Checks if the Acroform is valid
+     * @return true if the Acroform is valid
+     */
+
+    boolean isValid() {
+        if (documentFields.size() == 0) return false;
+        put(PdfName.FIELDS, documentFields);
+        if (sigFlags != 0)
+            put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
+        if (calculationOrder.size() > 0)
+            put(PdfName.CO, calculationOrder);
+        if (fieldTemplates.size() == 0) return true;
+        PdfDictionary dic = new PdfDictionary();
+        for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
+            PdfTemplate template = (PdfTemplate)it.next();
+            PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources());
+        }
+        put(PdfName.DR, dic);
+        PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT);
+        if (fonts != null) {
+            put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
+            writer.eliminateFontSubset(fonts);
+        }
+        return true;
+    }
+
+    /**
+     * Adds an object to the calculationOrder.
+     * @param formField
+     */
+
+    public void addCalculationOrder(PdfFormField formField) {
+        calculationOrder.add(formField.getIndirectReference());
+    }
+
+    /**
+     * Sets the signature flags.
+     * @param f
+     */
+
+    public void setSigFlags(int f) {
+        sigFlags |= f;
+    }
+
+    /**
+     * Adds a formfield to the AcroForm.
+     * @param formField
+     */
+
+    public void addFormField(PdfFormField formField) {
+        writer.addAnnotation(formField);
+    }
+
+    /**
+     * @param name
+     * @param caption
+     * @param value
+     * @param url
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT);
+        PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+        setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
+        drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
+        addFormField(button);
+	return button;
+    }
+
+    /**
+     * @param name
+     * @param caption
+     * @param value
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfAction action = PdfAction.createResetForm(null, 0);
+        PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+        setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
+        drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
+        addFormField(button);
+        return button;
+    }
+
+    /**
+     * @param name
+     * @param value
+     * @param url
+     * @param appearance
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) {
+        PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES);
+        PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+        setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null);
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
+        pa.add(appearance);
+        button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
+        addFormField(button);
+        return button;
+    }
+
+    /**
+     * @param button
+     * @param characteristics
+     * @param name
+     * @param value
+     */
+    public void setButtonParams(PdfFormField button, int characteristics, String name, String value) {
+        button.setButton(characteristics);
+        button.setFlags(PdfAnnotation.FLAGS_PRINT);
+        button.setPage();
+        button.setFieldName(name);
+        if (value != null) button.setValueAsString(value);
+    }
+
+    /**
+     * @param button
+     * @param caption
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
+        pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize);
+        button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
+    }
+
+    /**
+     * @param name
+     * @param value
+     * @return a PdfFormField
+     */
+    public PdfFormField addHiddenField(String name, String value) {
+        PdfFormField hidden = PdfFormField.createEmpty(writer);
+        hidden.setFieldName(name);
+        hidden.setValueAsName(value);
+        addFormField(hidden);
+        return hidden;
+    }
+
+    /**
+     * @param name
+     * @param text
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0);
+        setTextFieldParams(field, text, name, llx, lly, urx, ury);
+        drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+        addFormField(field);
+        return field;
+    }
+
+    /**
+     * @param name
+     * @param text
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0);
+        setTextFieldParams(field, text, name, llx, lly, urx, ury);
+        drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+        addFormField(field);
+        return field;
+    }
+
+    /**
+     * @param name
+     * @param text
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return PdfFormField
+     */
+    public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0);
+        setTextFieldParams(field, text, name, llx, lly, urx, ury);
+        drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+        addFormField(field);
+        return field;
+    }
+
+    /**
+     * @param field
+     * @param text
+     * @param name
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) {
+        field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+        field.setValueAsString(text);
+        field.setDefaultValueAsString(text);
+        field.setFieldName(name);
+        field.setFlags(PdfAnnotation.FLAGS_PRINT);
+        field.setPage();
+    }
+
+    /**
+     * @param field
+     * @param text
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+        PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
+        tp2.setFontAndSize(font, fontSize);
+        tp2.resetRGBColorFill();
+        field.setDefaultAppearanceString(tp2);
+        tp.drawTextField(0f, 0f, urx - llx, ury - lly);
+        tp.beginVariableText();
+        tp.saveState();
+        tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
+        tp.clip();
+        tp.newPath();
+        tp.beginText();
+        tp.setFontAndSize(font, fontSize);
+        tp.resetRGBColorFill();
+        tp.setTextMatrix(4, (ury - lly) / 2 - (fontSize * 0.3f));
+        tp.showText(text);
+        tp.endText();
+        tp.restoreState();
+        tp.endVariableText();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+    }
+
+    /**
+     * @param field
+     * @param text
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+        PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
+        tp2.setFontAndSize(font, fontSize);
+        tp2.resetRGBColorFill();
+        field.setDefaultAppearanceString(tp2);
+        tp.drawTextField(0f, 0f, urx - llx, ury - lly);
+        tp.beginVariableText();
+        tp.saveState();
+        tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
+        tp.clip();
+        tp.newPath();
+        tp.beginText();
+        tp.setFontAndSize(font, fontSize);
+        tp.resetRGBColorFill();
+        tp.setTextMatrix(4, 5);
+        java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n");
+        float yPos = ury - lly;
+        while (tokenizer.hasMoreTokens()) {
+            yPos -= fontSize * 1.2f;
+            tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0);
+        }
+        tp.endText();
+        tp.restoreState();
+        tp.endVariableText();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+    }
+
+    /**
+     * @param name
+     * @param value
+     * @param status
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) {
+        PdfFormField field = PdfFormField.createCheckBox(writer);
+        setCheckBoxParams(field, name, value, status, llx, lly, urx, ury);
+        drawCheckBoxAppearences(field, value, llx, lly, urx, ury);
+        addFormField(field);
+        return field;
+    }
+
+    /**
+     * @param field
+     * @param name
+     * @param value
+     * @param status
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) {
+        field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
+        field.setFieldName(name);
+        if (status) {
+            field.setValueAsName(value);
+            field.setAppearanceState(value);
+        }
+        else {
+            field.setValueAsName("Off");
+            field.setAppearanceState("Off");
+        }
+        field.setFlags(PdfAnnotation.FLAGS_PRINT);
+        field.setPage();
+        field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
+    }
+
+    /**
+     * @param field
+     * @param value
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
+        BaseFont font = null;
+        try {
+            font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
+        }
+        catch(Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        float size = (ury - lly);
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
+        PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate();
+        tp2.setFontAndSize(font, size);
+        tp2.resetRGBColorFill();
+        field.setDefaultAppearanceString(tp2);
+        tpOn.drawTextField(0f, 0f, urx - llx, ury - lly);
+        tpOn.saveState();
+        tpOn.resetRGBColorFill();
+        tpOn.beginText();
+        tpOn.setFontAndSize(font, size);
+        tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - (size * 0.3f), 0);
+        tpOn.endText();
+        tpOn.restoreState();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
+        PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
+        tpOff.drawTextField(0f, 0f, urx - llx, ury - lly);
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
+    }
+
+    /**
+     * @param name
+     * @param defaultValue
+     * @param noToggleToOff
+     * @return a PdfFormField
+     */
+    public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) {
+        PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff);
+        radio.setFieldName(name);
+        radio.setValueAsName(defaultValue);
+        return radio;
+    }
+
+    /**
+     * @param radiogroup
+     */
+    public void addRadioGroup(PdfFormField radiogroup) {
+        addFormField(radiogroup);
+    }
+
+    /**
+     * @param radiogroup
+     * @param value
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) {
+        PdfFormField radio = PdfFormField.createEmpty(writer);
+        radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
+        String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1);
+        if (name.equals(value)) {
+            radio.setAppearanceState(value);
+        }
+        else {
+            radio.setAppearanceState("Off");
+        }
+        drawRadioAppearences(radio, value, llx, lly, urx, ury);
+        radiogroup.addKid(radio);
+        return radio;
+    }
+
+    /**
+     * @param field
+     * @param value
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
+        tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true);
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
+        PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
+        tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false);
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
+    }
+
+    /**
+     * @param name
+     * @param options
+     * @param defaultValue
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField choice = PdfFormField.createList(writer, options, 0);
+        setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+        StringBuffer text = new StringBuffer();
+        for (int i = 0; i < options.length; i++) {
+            text.append(options[i]).append("\n");
+        }
+        drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
+        addFormField(choice);
+        return choice;
+    }
+
+    /**
+     * @param name
+     * @param options
+     * @param defaultValue
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField choice = PdfFormField.createList(writer, options, 0);
+        setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+        StringBuffer text = new StringBuffer();
+        for (int i = 0; i < options.length; i++) {
+            text.append(options[i][1]).append("\n");
+        }
+        drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
+        addFormField(choice);
+        return choice;
+    }
+
+    /**
+     * @param name
+     * @param options
+     * @param defaultValue
+     * @param editable
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
+        setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+        if (defaultValue == null) {
+            defaultValue = options[0];
+        }
+        drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury);
+        addFormField(choice);
+        return choice;
+    }
+
+    /**
+     * @param name
+     * @param options
+     * @param defaultValue
+     * @param editable
+     * @param font
+     * @param fontSize
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+        PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
+        setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+        String value = null;
+        for (int i = 0; i < options.length; i++) {
+            if (options[i][0].equals(defaultValue)) {
+                value = options[i][1];
+                break;
+            }
+        }
+        if (value == null) {
+            value = options[0][1];
+        }
+        drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury);
+        addFormField(choice);
+        return choice;
+    }
+
+    /**
+     * @param field
+     * @param name
+     * @param defaultValue
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) {
+        field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+        if (defaultValue != null) {
+            field.setValueAsString(defaultValue);
+            field.setDefaultValueAsString(defaultValue);
+        }
+        field.setFieldName(name);
+        field.setFlags(PdfAnnotation.FLAGS_PRINT);
+        field.setPage();
+        field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID));
+    }
+
+    /**
+     * @param name
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @return a PdfFormField
+     */
+    public PdfFormField addSignature(String name, 
+                    float llx, float lly, float urx, float ury) {
+        PdfFormField signature = PdfFormField.createSignature(writer);
+        setSignatureParams(signature, name, llx, lly, urx, ury);
+        drawSignatureAppearences(signature, llx, lly, urx, ury);
+        addFormField(signature);
+        return signature;
+    }
+    
+    /**
+     * @param field
+     * @param name
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void setSignatureParams(PdfFormField field, String name,
+                    float llx, float lly, float urx, float ury) {
+        field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+        field.setFieldName(name);
+        field.setFlags(PdfAnnotation.FLAGS_PRINT);
+        field.setPage();
+        field.setMKBorderColor(java.awt.Color.black);
+        field.setMKBackgroundColor(java.awt.Color.white);
+    }
+
+    /**
+     * @param field
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */
+    public void drawSignatureAppearences(PdfFormField field, 
+                    float llx, float lly, float urx, float ury) {
+        PdfContentByte cb = writer.getDirectContent();
+        PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+        tp.setGrayFill(1.0f);
+        tp.rectangle(0, 0, urx - llx, ury - lly);
+        tp.fill();
+        tp.setGrayStroke(0);
+        tp.setLineWidth(1);
+        tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f);
+        tp.closePathStroke();
+        tp.saveState();
+        tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2);
+        tp.clip();
+        tp.newPath();
+        tp.restoreState();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfAction.java b/LibrarySource/com/lowagie/text/pdf/PdfAction.java
new file mode 100644
index 0000000..8442abc
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfAction.java
@@ -0,0 +1,558 @@
+/*
+ * $Id: PdfAction.java,v 1.64 2005/01/06 09:40:10 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.net.URL;
+import com.lowagie.text.ExceptionConverter;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * A <CODE>PdfAction</CODE> defines an action that can be triggered from a PDF file.
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfAction extends PdfDictionary {
+    
+    /** A named action to go to the first page.
+     */
+    public static final int FIRSTPAGE = 1;
+    /** A named action to go to the previous page.
+     */
+    public static final int PREVPAGE = 2;
+    /** A named action to go to the next page.
+     */
+    public static final int NEXTPAGE = 3;
+    /** A named action to go to the last page.
+     */
+    public static final int LASTPAGE = 4;
+
+    /** A named action to open a print dialog.
+     */
+    public static final int PRINTDIALOG = 5;
+
+    /** a possible submitvalue */
+    public static final int SUBMIT_EXCLUDE = 1;
+    /** a possible submitvalue */
+    public static final int SUBMIT_INCLUDE_NO_VALUE_FIELDS = 2;
+    /** a possible submitvalue */
+    public static final int SUBMIT_HTML_FORMAT = 4;
+    /** a possible submitvalue */
+    public static final int SUBMIT_HTML_GET = 8;
+    /** a possible submitvalue */
+    public static final int SUBMIT_COORDINATES = 16;
+    /** a possible submitvalue */
+    public static final int SUBMIT_XFDF = 32;
+    /** a possible submitvalue */
+    public static final int SUBMIT_INCLUDE_APPEND_SAVES = 64;
+    /** a possible submitvalue */
+    public static final int SUBMIT_INCLUDE_ANNOTATIONS = 128;
+    /** a possible submitvalue */
+    public static final int SUBMIT_PDF = 256;
+    /** a possible submitvalue */
+    public static final int SUBMIT_CANONICAL_FORMAT = 512;
+    /** a possible submitvalue */
+    public static final int SUBMIT_EXCL_NON_USER_ANNOTS = 1024;
+    /** a possible submitvalue */
+    public static final int SUBMIT_EXCL_F_KEY = 2048;
+    /** a possible submitvalue */
+    public static final int SUBMIT_EMBED_FORM = 8196;
+    /** a possible submitvalue */
+    public static final int RESET_EXCLUDE = 1;
+
+    // constructors
+    
+    /** Create an empty action.
+     */    
+    public PdfAction() {
+    }
+    
+    /**
+     * Constructs a new <CODE>PdfAction</CODE> of Subtype URI.
+     *
+     * @param url the Url to go to
+     */
+    
+    public PdfAction(URL url) {
+        this(url.toExternalForm());
+    }
+    
+    /**
+     * Construct a new <CODE>PdfAction</CODE> of Subtype URI that accepts the x and y coordinate of the position that was clicked.
+     * @param url
+     * @param isMap
+     */
+    public PdfAction(URL url, boolean isMap) {
+        this(url.toExternalForm(), isMap);
+    }
+    
+    /**
+     * Constructs a new <CODE>PdfAction</CODE> of Subtype URI.
+     *
+     * @param url the url to go to
+     */
+    
+    public PdfAction(String url) {
+        this(url, false);
+    }
+    
+    /**
+     * Construct a new <CODE>PdfAction</CODE> of Subtype URI that accepts the x and y coordinate of the position that was clicked.
+     * @param url
+     * @param isMap
+     */
+    
+    public PdfAction(String url, boolean isMap) {
+        put(PdfName.S, PdfName.URI);
+        put(PdfName.URI, new PdfString(url));
+        if (isMap)
+            put(PdfName.ISMAP, PdfBoolean.PDFTRUE);
+    }
+    
+    /**
+     * Constructs a new <CODE>PdfAction</CODE> of Subtype GoTo.
+     * @param destination the destination to go to
+     */
+    
+    PdfAction(PdfIndirectReference destination) {
+        put(PdfName.S, PdfName.GOTO);
+        put(PdfName.D, destination);
+    }
+    
+    /**
+     * Constructs a new <CODE>PdfAction</CODE> of Subtype GoToR.
+     * @param filename the file name to go to
+     * @param name the named destination to go to
+     */
+    
+    public PdfAction(String filename, String name) {
+        put(PdfName.S, PdfName.GOTOR);
+        put(PdfName.F, new PdfString(filename));
+        put(PdfName.D, new PdfString(name));
+    }
+    
+    /**
+     * Constructs a new <CODE>PdfAction</CODE> of Subtype GoToR.
+     * @param filename the file name to go to
+     * @param page the page destination to go to
+     */
+    
+    public PdfAction(String filename, int page) {
+        put(PdfName.S, PdfName.GOTOR);
+        put(PdfName.F, new PdfString(filename));
+        put(PdfName.D, new PdfLiteral("[" + (page - 1) + " /FitH 10000]"));
+    }
+    
+    /** Implements name actions. The action can be FIRSTPAGE, LASTPAGE,
+     * NEXTPAGE, PREVPAGE and PRINTDIALOG.
+     * @param named the named action
+     */
+    public PdfAction(int named) {
+        put(PdfName.S, PdfName.NAMED);
+        switch (named) {
+            case FIRSTPAGE:
+                put(PdfName.N, PdfName.FIRSTPAGE);
+                break;
+            case LASTPAGE:
+                put(PdfName.N, PdfName.LASTPAGE);
+                break;
+            case NEXTPAGE:
+                put(PdfName.N, PdfName.NEXTPAGE);
+                break;
+            case PREVPAGE:
+                put(PdfName.N, PdfName.PREVPAGE);
+                break;
+            case PRINTDIALOG:
+                put(PdfName.S, PdfName.JAVASCRIPT);
+                put(PdfName.JS, new PdfString("this.print(true);\r"));
+                break;
+            default:
+                throw new RuntimeException("Invalid named action.");
+        }
+    }
+    
+    /** Launchs an application or a document.
+     * @param application the application to be launched or the document to be opened or printed.
+     * @param parameters (Windows-specific) A parameter string to be passed to the application.
+     * It can be <CODE>null</CODE>.
+     * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
+     * "print" - Print a document.
+     * It can be <CODE>null</CODE>.
+     * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
+     * It can be <CODE>null</CODE>.
+     */
+    public PdfAction(String application, String parameters, String operation, String defaultDir) {
+        put(PdfName.S, PdfName.LAUNCH);
+        if (parameters == null && operation == null && defaultDir == null)
+            put(PdfName.F, new PdfString(application));
+        else {
+            PdfDictionary dic = new PdfDictionary();
+            dic.put(PdfName.F, new PdfString(application));
+            if (parameters != null)
+                dic.put(PdfName.P, new PdfString(parameters));
+            if (operation != null)
+                dic.put(PdfName.O, new PdfString(operation));
+            if (defaultDir != null)
+                dic.put(PdfName.D, new PdfString(defaultDir));
+            put(PdfName.WIN, dic);
+        }
+    }
+    
+    /** Launchs an application or a document.
+     * @param application the application to be launched or the document to be opened or printed.
+     * @param parameters (Windows-specific) A parameter string to be passed to the application.
+     * It can be <CODE>null</CODE>.
+     * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
+     * "print" - Print a document.
+     * It can be <CODE>null</CODE>.
+     * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
+     * It can be <CODE>null</CODE>.
+     * @return a Launch action
+     */
+    public static PdfAction createLaunch(String application, String parameters, String operation, String defaultDir) {
+        return new PdfAction(application, parameters, operation, defaultDir);
+    }
+    
+     /**Creates a Rendition action
+     * @param file
+     * @param fs
+     * @param mimeType
+     * @param ref
+     * @return a Media Clip action
+     * @throws IOException
+     */
+    public static PdfAction rendition(String file, PdfFileSpecification fs, String mimeType, PdfIndirectReference ref) throws IOException {
+        PdfAction js = new PdfAction();
+        js.put(PdfName.S, PdfName.RENDITION);
+        js.put(PdfName.R, new PdfRendition(file, fs, mimeType));
+        js.put(new PdfName("OP"), new PdfNumber(0));
+        js.put(new PdfName("AN"), ref);
+        return js;
+     }
+  
+    /** Creates a JavaScript action. If the JavaScript is smaller than
+     * 50 characters it will be placed as a string, otherwise it will
+     * be placed as a compressed stream.
+     * @param code the JavaScript code
+     * @param writer the writer for this action
+     * @param unicode select JavaScript unicode. Note that the internal
+     * Acrobat JavaScript engine does not support unicode,
+     * so this may or may not work for you
+     * @return the JavaScript action
+     */    
+    public static PdfAction javaScript(String code, PdfWriter writer, boolean unicode) {
+        PdfAction js = new PdfAction();
+        js.put(PdfName.S, PdfName.JAVASCRIPT);
+        if (unicode && code.length() < 50) {
+                js.put(PdfName.JS, new PdfString(code, PdfObject.TEXT_UNICODE));
+        }
+        else if (!unicode && code.length() < 100) {
+                js.put(PdfName.JS, new PdfString(code));
+        }
+        else {
+            try {
+                byte b[] = PdfEncodings.convertToBytes(code, unicode ? PdfObject.TEXT_UNICODE : PdfObject.TEXT_PDFDOCENCODING);
+                PdfStream stream = new PdfStream(b);
+                stream.flateCompress();
+                js.put(PdfName.JS, writer.addToBody(stream).getIndirectReference());
+            }
+            catch (Exception e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+        return js;
+    }
+
+    /** Creates a JavaScript action. If the JavaScript is smaller than
+     * 50 characters it will be place as a string, otherwise it will
+     * be placed as a compressed stream.
+     * @param code the JavaScript code
+     * @param writer the writer for this action
+     * @return the JavaScript action
+     */    
+    public static PdfAction javaScript(String code, PdfWriter writer) {
+        return javaScript(code, writer, false);
+    }
+    
+    /**
+     * A Hide action hides or shows an object.
+     * @param obj object to hide or show
+     * @param hide true is hide, false is show
+     * @return a Hide Action
+     */
+    static PdfAction createHide(PdfObject obj, boolean hide) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.HIDE);
+        action.put(PdfName.T, obj);
+        if (!hide)
+            action.put(PdfName.H, PdfBoolean.PDFFALSE);
+        return action;
+    }
+    
+    /**
+     * A Hide action hides or shows an annotation.
+     * @param annot
+     * @param hide
+     * @return A Hide Action
+     */
+    public static PdfAction createHide(PdfAnnotation annot, boolean hide) {
+        return createHide(annot.getIndirectReference(), hide);
+    }
+    
+    /**
+     * A Hide action hides or shows an annotation.
+     * @param name
+     * @param hide
+     * @return A Hide Action
+     */
+    public static PdfAction createHide(String name, boolean hide) {
+        return createHide(new PdfString(name), hide);
+    }
+    
+    static PdfArray buildArray(Object names[]) {
+        PdfArray array = new PdfArray();
+        for (int k = 0; k < names.length; ++k) {
+            Object obj = names[k];
+            if (obj instanceof String)
+                array.add(new PdfString((String)obj));
+            else if (obj instanceof PdfAnnotation)
+                array.add(((PdfAnnotation)obj).getIndirectReference());
+            else
+                throw new RuntimeException("The array must contain String or PdfAnnotation.");
+        }
+        return array;
+    }
+    
+    /**
+     * A Hide action hides or shows objects.
+     * @param names
+     * @param hide
+     * @return A Hide Action
+     */
+    public static PdfAction createHide(Object names[], boolean hide) {
+        return createHide(buildArray(names), hide);
+    }
+    
+    /**
+     * Creates a submit form.
+     * @param file	the URI to submit the form to
+     * @param names	the objects to submit
+     * @param flags	submit properties
+     * @return A PdfAction
+     */
+    public static PdfAction createSubmitForm(String file, Object names[], int flags) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.SUBMITFORM);
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.F, new PdfString(file));
+        dic.put(PdfName.FS, PdfName.URL);
+        action.put(PdfName.F, dic);
+        if (names != null)
+            action.put(PdfName.FIELDS, buildArray(names));
+        action.put(PdfName.FLAGS, new PdfNumber(flags));
+        return action;
+    }
+    
+    /**
+     * Creates a resetform.
+     * @param names	the objects to reset
+     * @param flags	submit properties
+     * @return A PdfAction
+     */
+    public static PdfAction createResetForm(Object names[], int flags) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.RESETFORM);
+        if (names != null)
+            action.put(PdfName.FIELDS, buildArray(names));
+        action.put(PdfName.FLAGS, new PdfNumber(flags));
+        return action;
+    }
+    
+    /**
+     * Creates an Import field.
+     * @param file
+     * @return A PdfAction
+     */
+    public static PdfAction createImportData(String file) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.IMPORTDATA);
+        action.put(PdfName.F, new PdfString(file));
+        return action;
+    }
+    
+    /** Add a chained action.
+     * @param na the next action
+     */    
+    public void next(PdfAction na) {
+        PdfObject nextAction = get(PdfName.NEXT);
+        if (nextAction == null)
+            put(PdfName.NEXT, na);
+        else if (nextAction.isDictionary()) {
+            PdfArray array = new PdfArray(nextAction);
+            array.add(na);
+            put(PdfName.NEXT, array);
+        }
+        else {
+            ((PdfArray)nextAction).add(na);
+        }
+    }
+    
+    /** Creates a GoTo action to an internal page.
+     * @param page the page to go. First page is 1
+     * @param dest the destination for the page
+     * @param writer the writer for this action
+     * @return a GoTo action
+     */    
+    public static PdfAction gotoLocalPage(int page, PdfDestination dest, PdfWriter writer) {
+        PdfIndirectReference ref = writer.getPageReference(page);
+        dest.addPage(ref);
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.GOTO);
+        action.put(PdfName.D, dest);
+        return action;
+    }
+
+    /**
+     * Creates a GoTo action to a named destination.
+     * @param dest the named destination
+     * @param isName if true sets the destination as a name, if false sets it as a String
+     * @return a GoToR action
+     */
+    public static PdfAction gotoLocalPage(String dest, boolean isName) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.GOTO);
+        if (isName)
+            action.put(PdfName.D, new PdfName(dest));
+        else
+            action.put(PdfName.D, new PdfString(dest, null));
+        return action;
+    }
+
+    /**
+     * Creates a GoToR action to a named destination.
+     * @param filename the file name to go to
+     * @param dest the destination name
+     * @param isName if true sets the destination as a name, if false sets it as a String
+     * @param newWindow open the document in a new window if <CODE>true</CODE>, if false the current document is replaced by the new document.
+     * @return a GoToR action
+     */
+    public static PdfAction gotoRemotePage(String filename, String dest, boolean isName, boolean newWindow) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.F, new PdfString(filename));
+        action.put(PdfName.S, PdfName.GOTOR);
+        if (isName)
+            action.put(PdfName.D, new PdfName(dest));
+        else
+            action.put(PdfName.D, new PdfString(dest, null));
+        if (newWindow)
+            action.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
+        return action;
+    }
+
+    /**
+     * A set-OCG-state action (PDF 1.5) sets the state of one or more optional content
+     * groups.
+     * @param state an array consisting of any number of sequences beginning with a <CODE>PdfName</CODE>
+     * or <CODE>String</CODE> (ON, OFF, or Toggle) followed by one or more optional content group dictionaries
+     * <CODE>PdfLayer</CODE> or a <CODE>PdfIndirectReference</CODE> to a <CODE>PdfLayer</CODE>.<br>
+     * The array elements are processed from left to right; each name is applied
+     * to the subsequent groups until the next name is encountered:
+     * <ul>
+     * <li>ON sets the state of subsequent groups to ON</li>
+     * <li>OFF sets the state of subsequent groups to OFF</li>
+     * <li>Toggle reverses the state of subsequent groups</li>
+     * </ul>
+     * @param preserveRB if <CODE>true</CODE>, indicates that radio-button state relationships between optional
+     * content groups (as specified by the RBGroups entry in the current configuration
+     * dictionary) should be preserved when the states in the
+     * <CODE>state</CODE> array are applied. That is, if a group is set to ON (either by ON or Toggle) during
+     * processing of the <CODE>state</CODE> array, any other groups belong to the same radio-button
+     * group are turned OFF. If a group is set to OFF, there is no effect on other groups.<br>
+     * If <CODE>false</CODE>, radio-button state relationships, if any, are ignored
+     * @return the action
+     */    
+    public static PdfAction setOCGstate(ArrayList state, boolean preserveRB) {
+        PdfAction action = new PdfAction();
+        action.put(PdfName.S, PdfName.SETOCGSTATE);
+        PdfArray a = new PdfArray();
+        for (int k = 0; k < state.size(); ++k) {
+            Object o = state.get(k);
+            if (o == null)
+                continue;
+            if (o instanceof PdfIndirectReference)
+                a.add((PdfIndirectReference)o);
+            else if (o instanceof PdfLayer)
+                a.add(((PdfLayer)o).getRef());
+            else if (o instanceof PdfName)
+                a.add((PdfName)o);
+            else if (o instanceof String) {
+                PdfName name = null;
+                String s = (String)o;
+                if (s.equalsIgnoreCase("on"))
+                    name = PdfName.ON;
+                else if (s.equalsIgnoreCase("off"))
+                    name = PdfName.OFF;
+                else if (s.equalsIgnoreCase("toggle"))
+                    name = PdfName.TOGGLE;
+                else
+                    throw new IllegalArgumentException("A string '" + s + " was passed in state. Only 'ON', 'OFF' and 'Toggle' are allowed.");
+                a.add(name);
+            }
+            else
+                throw new IllegalArgumentException("Invalid type was passed in state: " + o.getClass().getName());
+        }
+        action.put(PdfName.STATE, a);
+        if (!preserveRB)
+            action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE);
+        return action;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfAnnotation.java b/LibrarySource/com/lowagie/text/pdf/PdfAnnotation.java
new file mode 100644
index 0000000..661aa3e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfAnnotation.java
@@ -0,0 +1,741 @@
+/*
+ * $Id: PdfAnnotation.java,v 1.57 2005/01/06 13:42:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Rectangle;
+import java.util.HashMap;
+import headless.awt.Color;
+import java.io.*;
+/**
+ * A <CODE>PdfAnnotation</CODE> is a note that is associated with a page.
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfAnnotation extends PdfDictionary {
+    /** highlight attributename */
+    public static final PdfName HIGHLIGHT_NONE = PdfName.N;
+    /** highlight attributename */
+    public static final PdfName HIGHLIGHT_INVERT = PdfName.I;
+    /** highlight attributename */
+    public static final PdfName HIGHLIGHT_OUTLINE = PdfName.O;
+    /** highlight attributename */
+    public static final PdfName HIGHLIGHT_PUSH = PdfName.P;
+    /** highlight attributename */
+    public static final PdfName HIGHLIGHT_TOGGLE = PdfName.T;
+    /** flagvalue */
+    public static final int FLAGS_INVISIBLE = 1;
+    /** flagvalue */
+    public static final int FLAGS_HIDDEN = 2;
+    /** flagvalue */
+    public static final int FLAGS_PRINT = 4;
+    /** flagvalue */
+    public static final int FLAGS_NOZOOM = 8;
+    /** flagvalue */
+    public static final int FLAGS_NOROTATE = 16;
+    /** flagvalue */
+    public static final int FLAGS_NOVIEW = 32;
+    /** flagvalue */
+    public static final int FLAGS_READONLY = 64;
+    /** flagvalue */
+    public static final int FLAGS_LOCKED = 128;
+    /** flagvalue */
+    public static final int FLAGS_TOGGLENOVIEW = 256;
+    /** appearance attributename */
+    public static final PdfName APPEARANCE_NORMAL = PdfName.N;
+    /** appearance attributename */
+    public static final PdfName APPEARANCE_ROLLOVER = PdfName.R;
+    /** appearance attributename */
+    public static final PdfName APPEARANCE_DOWN = PdfName.D;
+    /** attributevalue */
+    public static final PdfName AA_ENTER = PdfName.E;
+    /** attributevalue */
+    public static final PdfName AA_EXIT = PdfName.X;
+    /** attributevalue */
+    public static final PdfName AA_DOWN = PdfName.D;
+    /** attributevalue */
+    public static final PdfName AA_UP = PdfName.U;
+    /** attributevalue */
+    public static final PdfName AA_FOCUS = PdfName.FO;
+    /** attributevalue */
+    public static final PdfName AA_BLUR = PdfName.BL;
+    /** attributevalue */
+    public static final PdfName AA_JS_KEY = PdfName.K;
+    /** attributevalue */
+    public static final PdfName AA_JS_FORMAT = PdfName.F;
+    /** attributevalue */
+    public static final PdfName AA_JS_CHANGE = PdfName.V;
+    /** attributevalue */
+    public static final PdfName AA_JS_OTHER_CHANGE = PdfName.C;
+    /** attributevalue */
+    public static final int MARKUP_HIGHLIGHT = 0;
+    /** attributevalue */
+    public static final int MARKUP_UNDERLINE = 1;
+    /** attributevalue */
+    public static final int MARKUP_STRIKEOUT = 2;
+    
+    protected PdfWriter writer;
+    protected PdfIndirectReference reference;
+    protected HashMap templates;
+    protected boolean form = false;
+    protected boolean annotation = true;
+    
+    /** Holds value of property used. */
+    protected boolean used = false;
+    
+    /** Holds value of property placeInPage. */
+    private int placeInPage = -1;
+    
+    // constructors
+    protected PdfAnnotation(PdfWriter writer, Rectangle rect) {
+        this.writer = writer;
+        if (rect != null)
+            put(PdfName.RECT, new PdfRectangle(rect));
+    }
+    
+/**
+ * Constructs a new <CODE>PdfAnnotation</CODE> of subtype text.
+ * @param writer
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param title
+ * @param content
+ */
+    
+    PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfString title, PdfString content) {
+        this.writer = writer;
+        put(PdfName.SUBTYPE, PdfName.TEXT);
+        put(PdfName.T, title);
+        put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
+        put(PdfName.CONTENTS, content);
+    }
+    
+/**
+ * Constructs a new <CODE>PdfAnnotation</CODE> of subtype link (Action).
+ * @param writer
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param action
+ */
+    
+    public PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
+        this.writer = writer;
+        put(PdfName.SUBTYPE, PdfName.LINK);
+        put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
+        put(PdfName.A, action);
+        put(PdfName.BORDER, new PdfBorderArray(0, 0, 0));
+        put(PdfName.C, new PdfColor(0x00, 0x00, 0xFF));
+    }
+
+    /**
+     * Creates a screen PdfAnnotation
+     * @param writer
+     * @param rect
+     * @param clipTitle
+     * @param fs
+     * @param mimeType
+     * @param playOnDisplay
+     * @return a screen PdfAnnotation
+     * @throws IOException
+     */
+    public static PdfAnnotation createScreen(PdfWriter writer, Rectangle rect, String clipTitle, PdfFileSpecification fs,
+                                             String mimeType, boolean playOnDisplay) throws IOException {
+        PdfAnnotation ann = new PdfAnnotation(writer, rect);
+        ann.put(PdfName.SUBTYPE, PdfName.SCREEN);
+        ann.put (PdfName.F, new PdfNumber(FLAGS_PRINT));
+        ann.put(PdfName.TYPE, PdfName.ANNOT);
+        ann.setPage();
+        PdfIndirectReference ref = ann.getIndirectReference();
+        PdfAction action = PdfAction.rendition(clipTitle,fs,mimeType, ref);
+        PdfIndirectReference actionRef = writer.addToBody(action).getIndirectReference();
+        // for play on display add trigger event
+        if (playOnDisplay)
+        {
+            PdfDictionary aa = new PdfDictionary();
+            aa.put(new PdfName("PV"), actionRef);
+            ann.put(PdfName.AA, aa);
+        }
+        ann.put(PdfName.A, actionRef);
+        return ann;
+    }
+
+    PdfIndirectReference getIndirectReference() {
+        if (reference == null) {
+            reference = writer.getPdfIndirectReference();
+        }
+        return reference;
+    }
+    
+    /**
+     * @param writer
+     * @param rect
+     * @param title
+     * @param contents
+     * @param open
+     * @param icon
+     * @return a PdfAnnotation
+     */
+    public static PdfAnnotation createText(PdfWriter writer, Rectangle rect, String title, String contents, boolean open, String icon) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.TEXT);
+        if (title != null)
+            annot.put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
+        if (contents != null)
+            annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        if (open)
+            annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
+        if (icon != null) {
+            annot.put(PdfName.NAME, new PdfName(icon));
+        }
+        return annot;
+    }
+    
+    /**
+     * Creates a link.
+     * @param writer
+     * @param rect
+     * @param highlight
+     * @return A PdfAnnotation
+     */
+    protected static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.LINK);
+        if (!highlight.equals(HIGHLIGHT_INVERT))
+            annot.put(PdfName.H, highlight);
+        return annot;
+    }
+    
+    /**
+     * Creates an Annotation with an Action.
+     * @param writer
+     * @param rect
+     * @param highlight
+     * @param action
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, PdfAction action) {
+        PdfAnnotation annot = createLink(writer, rect, highlight);
+        annot.putEx(PdfName.A, action);
+        return annot;
+    }
+
+    /**
+     * Creates an Annotation with an local destination.
+     * @param writer
+     * @param rect
+     * @param highlight
+     * @param namedDestination
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, String namedDestination) {
+        PdfAnnotation annot = createLink(writer, rect, highlight);
+        annot.put(PdfName.DEST, new PdfString(namedDestination));
+        return annot;
+    }
+
+    /**
+     * Creates an Annotation with a PdfDestination.
+     * @param writer
+     * @param rect
+     * @param highlight
+     * @param page
+     * @param dest
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, int page, PdfDestination dest) {
+        PdfAnnotation annot = createLink(writer, rect, highlight);
+        PdfIndirectReference ref = writer.getPageReference(page);
+        dest.addPage(ref);
+        annot.put(PdfName.DEST, dest);
+        return annot;
+    }
+    
+    /**
+     * Add some free text to the document.
+     * @param writer
+     * @param rect
+     * @param contents
+     * @param defaultAppearance
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createFreeText(PdfWriter writer, Rectangle rect, String contents, PdfContentByte defaultAppearance) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.FREETEXT);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        annot.setDefaultAppearanceString(defaultAppearance);
+        return annot;
+    }
+
+    /**
+     * Adds a line to the document. Move over the line and a tooltip is shown.
+     * @param writer
+     * @param rect
+     * @param contents
+     * @param x1
+     * @param y1
+     * @param x2
+     * @param y2
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createLine(PdfWriter writer, Rectangle rect, String contents, float x1, float y1, float x2, float y2) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.LINE);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        PdfArray array = new PdfArray(new PdfNumber(x1));
+        array.add(new PdfNumber(y1));
+        array.add(new PdfNumber(x2));
+        array.add(new PdfNumber(y2));
+        annot.put(PdfName.L, array);
+        return annot;
+    }
+
+    /**
+     * Adds a circle or a square that shows a tooltip when you pass over it.
+     * @param writer
+     * @param rect
+     * @param contents The tooltip
+     * @param square true if you want a square, false if you want a circle
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createSquareCircle(PdfWriter writer, Rectangle rect, String contents, boolean square) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        if (square)
+            annot.put(PdfName.SUBTYPE, PdfName.SQUARE);
+        else
+            annot.put(PdfName.SUBTYPE, PdfName.CIRCLE);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        return annot;
+    }
+
+    public static PdfAnnotation createMarkup(PdfWriter writer, Rectangle rect, String contents, int type, float quadPoints[]) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        PdfName name = PdfName.HIGHLIGHT;
+        switch (type) {
+            case MARKUP_UNDERLINE:
+                name = PdfName.UNDERLINE;
+                break;
+            case MARKUP_STRIKEOUT:
+                name = PdfName.STRIKEOUT;
+                break;
+        }
+        annot.put(PdfName.SUBTYPE, name);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        PdfArray array = new PdfArray();
+        for (int k = 0; k < quadPoints.length; ++k)
+            array.add(new PdfNumber(quadPoints[k]));
+        annot.put(PdfName.QUADPOINTS, array);
+        return annot;
+    }
+
+    /**
+     * Adds a Stamp to your document. Move over the stamp and a tooltip is shown
+     * @param writer
+     * @param rect
+     * @param contents
+     * @param name
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createStamp(PdfWriter writer, Rectangle rect, String contents, String name) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.STAMP);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        annot.put(PdfName.NAME, new PdfName(name));
+        return annot;
+    }
+
+    public static PdfAnnotation createInk(PdfWriter writer, Rectangle rect, String contents, float inkList[][]) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.INK);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        PdfArray outer = new PdfArray();
+        for (int k = 0; k < inkList.length; ++k) {
+            PdfArray inner = new PdfArray();
+            float deep[] = inkList[k];
+            for (int j = 0; j < deep.length; ++j)
+                inner.add(new PdfNumber(deep[j]));
+            outer.add(inner);
+        }
+        annot.put(PdfName.INKLIST, outer);
+        return annot;
+    }
+
+    /** Creates a file attachment annotation.
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @param rect the dimensions in the page of the annotation
+     * @param contents the file description
+     * @param fileStore an array with the file. If it's <CODE>null</CODE>
+     * the file will be read from the disk
+     * @param file the path to the file. It will only be used if
+     * <CODE>fileStore</CODE> is not <CODE>null</CODE>
+     * @param fileDisplay the actual file name stored in the pdf
+     * @throws IOException on error
+     * @return the annotation
+     */    
+    public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, byte fileStore[], String file, String fileDisplay) throws IOException {
+        return createFileAttachment(writer, rect, contents, PdfFileSpecification.fileEmbedded(writer, file, fileDisplay, fileStore));
+    }
+
+    /** Creates a file attachment annotation
+     * @param writer
+     * @param rect
+     * @param contents
+     * @param fs
+     * @return the annotation
+     * @throws IOException
+     */
+    public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, PdfFileSpecification fs) throws IOException {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.FILEATTACHMENT);
+        annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        annot.put(PdfName.FS, fs.getReference());
+        return annot;
+    }
+    
+    /**
+     * Adds a popup to your document.
+     * @param writer
+     * @param rect
+     * @param contents
+     * @param open
+     * @return A PdfAnnotation
+     */
+    public static PdfAnnotation createPopup(PdfWriter writer, Rectangle rect, String contents, boolean open) {
+        PdfAnnotation annot = new PdfAnnotation(writer, rect);
+        annot.put(PdfName.SUBTYPE, PdfName.POPUP);
+        if (contents != null)
+            annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+        if (open)
+            annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
+        return annot;
+    }
+
+    public void setDefaultAppearanceString(PdfContentByte cb) {
+        byte b[] = cb.getInternalBuffer().toByteArray();
+        int len = b.length;
+        for (int k = 0; k < len; ++k) {
+            if (b[k] == '\n')
+                b[k] = 32;
+        }
+        put(PdfName.DA, new PdfString(b));
+    }
+    
+    public void setFlags(int flags) {
+        if (flags == 0)
+            remove(PdfName.F);
+        else
+            put(PdfName.F, new PdfNumber(flags));
+    }
+    
+    public void setBorder(PdfBorderArray border) {
+        putDel(PdfName.BORDER, border);
+    }
+
+    public void setBorderStyle(PdfBorderDictionary border) {
+        putDel(PdfName.BS, border);
+    }
+    
+    /**
+     * Sets the annotation's highlighting mode. The values can be
+     * <CODE>HIGHLIGHT_NONE</CODE>, <CODE>HIGHLIGHT_INVERT</CODE>,
+     * <CODE>HIGHLIGHT_OUTLINE</CODE> and <CODE>HIGHLIGHT_PUSH</CODE>;
+     * @param highlight the annotation's highlighting mode
+     */    
+    public void setHighlighting(PdfName highlight) {
+        if (highlight.equals(HIGHLIGHT_INVERT))
+            remove(PdfName.H);
+        else
+            put(PdfName.H, highlight);
+    }
+    
+    public void setAppearance(PdfName ap, PdfTemplate template) {
+        PdfDictionary dic = (PdfDictionary)get(PdfName.AP);
+        if (dic == null)
+            dic = new PdfDictionary();
+        dic.put(ap, template.getIndirectReference());
+        put(PdfName.AP, dic);
+        if (!form)
+            return;
+        if (templates == null)
+            templates = new HashMap();
+        templates.put(template, null);
+    }
+
+    public void setAppearance(PdfName ap, String state, PdfTemplate template) {
+        PdfDictionary dicAp = (PdfDictionary)get(PdfName.AP);
+        if (dicAp == null)
+            dicAp = new PdfDictionary();
+
+        PdfDictionary dic;
+        PdfObject obj = dicAp.get(ap);
+        if (obj != null && obj.isDictionary())
+            dic = (PdfDictionary)obj;
+        else
+            dic = new PdfDictionary();
+        dic.put(new PdfName(state), template.getIndirectReference());
+        dicAp.put(ap, dic);
+        put(PdfName.AP, dicAp);
+        if (!form)
+            return;
+        if (templates == null)
+            templates = new HashMap();
+        templates.put(template, null);
+    }
+    
+    public void setAppearanceState(String state) {
+        if (state == null) {
+            remove(PdfName.AS);
+            return;
+        }
+        put(PdfName.AS, new PdfName(state));
+    }
+    
+    public void setColor(Color color) {
+        putDel(PdfName.C, new PdfColor(color));
+    }
+    
+    public void setTitle(String title) {
+        if (title == null) {
+            remove(PdfName.T);
+            return;
+        }
+        put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setPopup(PdfAnnotation popup) {
+        put(PdfName.POPUP, popup.getIndirectReference());
+        popup.put(PdfName.PARENT, getIndirectReference());
+    }
+    
+    public void setAction(PdfAction action) {
+        putDel(PdfName.A, action);
+    }
+    
+    public void setAdditionalActions(PdfName key, PdfAction action) {
+        PdfDictionary dic;
+        PdfObject obj = get(PdfName.AA);
+        if (obj != null && obj.isDictionary())
+            dic = (PdfDictionary)obj;
+        else
+            dic = new PdfDictionary();
+        dic.put(key, action);
+        put(PdfName.AA, dic);
+    }
+    
+    /** Getter for property used.
+     * @return Value of property used.
+     */
+    public boolean isUsed() {
+        return used;
+    }
+    
+    /** Setter for property used.
+     */
+    void setUsed() {
+        used = true;
+    }
+    
+    HashMap getTemplates() {
+        return templates;
+    }
+    
+    /** Getter for property form.
+     * @return Value of property form.
+     */
+    public boolean isForm() {
+        return form;
+    }
+    
+    /** Getter for property annotation.
+     * @return Value of property annotation.
+     */
+    public boolean isAnnotation() {
+        return annotation;
+    }
+    
+    public void setPage(int page) {
+        put(PdfName.P, writer.getPageReference(page));
+    }
+    
+    public void setPage() {
+        put(PdfName.P, writer.getCurrentPage());
+    }
+    
+    /** Getter for property placeInPage.
+     * @return Value of property placeInPage.
+     */
+    public int getPlaceInPage() {
+        return placeInPage;
+    }
+    
+    /** Places the annotation in a specified page that must be greater
+     * or equal to the current one. With <code>PdfStamper</code> the page
+     * can be any. The first page is 1.
+     * @param placeInPage New value of property placeInPage.
+     */
+    public void setPlaceInPage(int placeInPage) {
+        this.placeInPage = placeInPage;
+    }
+    
+    public void setRotate(int v) {
+        put(PdfName.ROTATE, new PdfNumber(v));
+    }
+    
+    PdfDictionary getMK() {
+        PdfDictionary mk = (PdfDictionary)get(PdfName.MK);
+        if (mk == null) {
+            mk = new PdfDictionary();
+            put(PdfName.MK, mk);
+        }
+        return mk;
+    }
+    
+    public void setMKRotation(int rotation) {
+        getMK().put(PdfName.R, new PdfNumber(rotation));
+    }
+    
+    public static PdfArray getMKColor(Color color) {
+        PdfArray array = new PdfArray();
+        int type = ExtendedColor.getType(color);
+        switch (type) {
+            case ExtendedColor.TYPE_GRAY: {
+                array.add(new PdfNumber(((GrayColor)color).getGray()));
+                break;
+            }
+            case ExtendedColor.TYPE_CMYK: {
+                CMYKColor cmyk = (CMYKColor)color;
+                array.add(new PdfNumber(cmyk.getCyan()));
+                array.add(new PdfNumber(cmyk.getMagenta()));
+                array.add(new PdfNumber(cmyk.getYellow()));
+                array.add(new PdfNumber(cmyk.getBlack()));
+                break;
+            }
+            case ExtendedColor.TYPE_SEPARATION:
+            case ExtendedColor.TYPE_PATTERN:
+            case ExtendedColor.TYPE_SHADING:
+                throw new RuntimeException("Separations, patterns and shadings are not allowed in MK dictionary.");
+            default:
+                array.add(new PdfNumber(color.getRed() / 255f));
+                array.add(new PdfNumber(color.getGreen() / 255f));
+                array.add(new PdfNumber(color.getBlue() / 255f));
+        }
+        return array;
+    }
+    
+    public void setMKBorderColor(Color color) {
+        if (color == null)
+            getMK().remove(PdfName.BC);
+        else
+            getMK().put(PdfName.BC, getMKColor(color));
+    }
+    
+    public void setMKBackgroundColor(Color color) {
+        if (color == null)
+            getMK().remove(PdfName.BG);
+        else
+            getMK().put(PdfName.BG, getMKColor(color));
+    }
+    
+    public void setMKNormalCaption(String caption) {
+        getMK().put(PdfName.CA, new PdfString(caption, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setMKRolloverCaption(String caption) {
+        getMK().put(PdfName.RC, new PdfString(caption, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setMKAlternateCaption(String caption) {
+        getMK().put(PdfName.AC, new PdfString(caption, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setMKNormalIcon(PdfTemplate template) {
+        getMK().put(PdfName.I, template.getIndirectReference());
+    }
+    
+    public void setMKRolloverIcon(PdfTemplate template) {
+        getMK().put(PdfName.RI, template.getIndirectReference());
+    }
+    
+    public void setMKAlternateIcon(PdfTemplate template) {
+        getMK().put(PdfName.IX, template.getIndirectReference());
+    }
+    
+    public void setMKIconFit(PdfName scale, PdfName scalingType, float leftoverLeft, float leftoverBottom, boolean fitInBounds) {
+        PdfDictionary dic = new PdfDictionary();
+        if (!scale.equals(PdfName.A))
+            dic.put(PdfName.SW, scale);
+        if (!scalingType.equals(PdfName.P))
+            dic.put(PdfName.S, scalingType);
+        if (leftoverLeft != 0.5f || leftoverBottom != 0.5f) {
+            PdfArray array = new PdfArray(new PdfNumber(leftoverLeft));
+            array.add(new PdfNumber(leftoverBottom));
+            dic.put(PdfName.A, array);
+        }
+        if (fitInBounds)
+            dic.put(PdfName.FB, PdfBoolean.PDFTRUE);
+        getMK().put(PdfName.IF, dic);
+    }
+    
+    public void setMKTextPosition(int tp) {
+        getMK().put(PdfName.TP, new PdfNumber(tp));
+    }
+    
+    /**
+     * Sets the layer this annotation belongs to.
+     * @param layer the layer this annotation belongs to
+     */    
+    public void setLayer(PdfOCG layer) {
+        put(PdfName.OC, layer.getRef());
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfAppearance.java b/LibrarySource/com/lowagie/text/pdf/PdfAppearance.java
new file mode 100644
index 0000000..1625b61
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfAppearance.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.Rectangle;
+import java.util.HashMap;
+
+/**
+ * Implements the appearance stream to be used with form fields..
+ */
+
+public class PdfAppearance extends PdfTemplate {
+    
+    public static final HashMap stdFieldFontNames = new HashMap();
+    static {
+        stdFieldFontNames.put("Courier-BoldOblique", new PdfName("CoBO"));
+        stdFieldFontNames.put("Courier-Bold", new PdfName("CoBo"));
+        stdFieldFontNames.put("Courier-Oblique", new PdfName("CoOb"));
+        stdFieldFontNames.put("Courier", new PdfName("Cour"));
+        stdFieldFontNames.put("Helvetica-BoldOblique", new PdfName("HeBO"));
+        stdFieldFontNames.put("Helvetica-Bold", new PdfName("HeBo"));
+        stdFieldFontNames.put("Helvetica-Oblique", new PdfName("HeOb"));
+        stdFieldFontNames.put("Helvetica", new PdfName("Helv"));
+        stdFieldFontNames.put("Symbol", new PdfName("Symb"));
+        stdFieldFontNames.put("Times-BoldItalic", new PdfName("TiBI"));
+        stdFieldFontNames.put("Times-Bold", new PdfName("TiBo"));
+        stdFieldFontNames.put("Times-Italic", new PdfName("TiIt"));
+        stdFieldFontNames.put("Times-Roman", new PdfName("TiRo"));
+        stdFieldFontNames.put("ZapfDingbats", new PdfName("ZaDb"));
+        stdFieldFontNames.put("HYSMyeongJo-Medium", new PdfName("HySm"));
+        stdFieldFontNames.put("HYGoThic-Medium", new PdfName("HyGo"));
+        stdFieldFontNames.put("HeiseiKakuGo-W5", new PdfName("KaGo"));
+        stdFieldFontNames.put("HeiseiMin-W3", new PdfName("KaMi"));
+        stdFieldFontNames.put("MHei-Medium", new PdfName("MHei"));
+        stdFieldFontNames.put("MSung-Light", new PdfName("MSun"));
+        stdFieldFontNames.put("STSong-Light", new PdfName("STSo"));
+        stdFieldFontNames.put("MSungStd-Light", new PdfName("MSun"));
+        stdFieldFontNames.put("STSongStd-Light", new PdfName("STSo"));
+        stdFieldFontNames.put("HYSMyeongJoStd-Medium", new PdfName("HySm"));
+        stdFieldFontNames.put("KozMinPro-Regular", new PdfName("KaMi"));
+    }
+    
+    /**
+     *Creates a <CODE>PdfAppearance</CODE>.
+     */
+    
+    PdfAppearance() {
+        super();
+        separator = ' ';
+    }
+    
+    PdfAppearance(PdfIndirectReference iref) {
+        thisReference = iref;
+    }
+    
+    /**
+     * Creates new PdfTemplate
+     *
+     * @param wr the <CODE>PdfWriter</CODE>
+     */
+    
+    PdfAppearance(PdfWriter wr) {
+        super(wr);
+        separator = ' ';
+    }
+    
+    /**
+     * Set the font and the size for the subsequent text writing.
+     *
+     * @param bf the font
+     * @param size the font size in points
+     */
+    public void setFontAndSize(BaseFont bf, float size) {
+        checkWriter();
+        state.size = size;
+        if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
+            state.fontDetails = new FontDetails(null, ((DocumentFont)bf).getIndirectReference(), bf);
+        }
+        else
+            state.fontDetails = writer.addSimple(bf);
+        PdfName psn = (PdfName)stdFieldFontNames.get(bf.getPostscriptFontName());
+        if (psn == null) {
+            psn = new PdfName(bf.getPostscriptFontName());
+            bf.setSubset(false);
+        }
+        PageResources prs = getPageResources();
+//        PdfName name = state.fontDetails.getFontName();
+        prs.addFont(psn, state.fontDetails.getIndirectReference());
+        content.append(psn.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
+    }
+
+    public PdfContentByte getDuplicate() {
+        PdfAppearance tpl = new PdfAppearance();
+        tpl.writer = writer;
+        tpl.pdf = pdf;
+        tpl.thisReference = thisReference;
+        tpl.pageResources = pageResources;
+        tpl.bBox = new Rectangle(bBox);
+        tpl.group = group;
+        tpl.layer = layer;
+        if (matrix != null) {
+            tpl.matrix = new PdfArray(matrix);
+        }
+        tpl.separator = separator;
+        return tpl;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfArray.java b/LibrarySource/com/lowagie/text/pdf/PdfArray.java
new file mode 100644
index 0000000..f00f468
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfArray.java
@@ -0,0 +1,223 @@
+/*
+ * $Id: PdfArray.java,v 1.37 2003/05/02 09:01:13 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * <CODE>PdfArray</CODE> is the PDF Array object.
+ * <P>
+ * An array is a sequence of PDF objects. An array may contain a mixture of object types.
+ * An array is written as a left square bracket ([), followed by a sequence of objects,
+ * followed by a right square bracket (]).<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.6 (page 40).
+ *
+ * @see		PdfObject
+ */
+
+public class PdfArray extends PdfObject {
+    
+    // membervariables
+    
+/** this is the actual array of PdfObjects */
+    protected ArrayList arrayList;
+    
+    // constructors
+    
+/**
+ * Constructs an empty <CODE>PdfArray</CODE>-object.
+ */
+    
+    public PdfArray() {
+        super(ARRAY);
+        arrayList = new ArrayList();
+    }
+    
+/**
+ * Constructs an <CODE>PdfArray</CODE>-object, containing 1 <CODE>PdfObject</CODE>.
+ *
+ * @param	object		a <CODE>PdfObject</CODE> that has to be added to the array
+ */
+    
+    public PdfArray(PdfObject object) {
+        super(ARRAY);
+        arrayList = new ArrayList();
+        arrayList.add(object);
+    }
+    
+    public PdfArray(float values[]) {
+        super(ARRAY);
+        arrayList = new ArrayList();
+        add(values);
+    }
+    
+    public PdfArray(int values[]) {
+        super(ARRAY);
+        arrayList = new ArrayList();
+        add(values);
+    }
+    
+/**
+ * Constructs an <CODE>PdfArray</CODE>-object, containing all the <CODE>PdfObject</CODE>s in a given <CODE>PdfArray</CODE>.
+ *
+ * @param	array		a <CODE>PdfArray</CODE> that has to be added to the array
+ */
+    
+    public PdfArray(PdfArray array) {
+        super(ARRAY);
+        arrayList = new ArrayList(array.getArrayList());
+    }
+    
+    // methods overriding some methods in PdfObject
+    
+/**
+ * Returns the PDF representation of this <CODE>PdfArray</CODE>.
+ *
+ * @return		an array of <CODE>byte</CODE>s
+ */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        os.write('[');
+
+        Iterator i = arrayList.iterator();
+        PdfObject object;
+        int type = 0;
+        if (i.hasNext()) {
+            object = (PdfObject) i.next();
+            object.toPdf(writer, os);
+        }
+        while (i.hasNext()) {
+            object = (PdfObject) i.next();
+            type = object.type();
+            if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+                os.write(' ');
+            object.toPdf(writer, os);
+        }
+        os.write(']');
+    }
+    
+    // methods concerning the ArrayList-membervalue
+    
+/**
+ * Returns an ArrayList containing <CODE>PdfObject</CODE>s.
+ *
+ * @return		an ArrayList
+ */
+    
+    public ArrayList getArrayList() {
+        return arrayList;
+    }
+    
+/**
+ * Returns the number of entries in the array.
+ *
+ * @return		the size of the ArrayList
+ */
+    
+    public int size() {
+        return arrayList.size();
+    }
+    
+/**
+ * Adds a <CODE>PdfObject</CODE> to the <CODE>PdfArray</CODE>.
+ *
+ * @param		object			<CODE>PdfObject</CODE> to add
+ * @return		<CODE>true</CODE>
+ */
+    
+    public boolean add(PdfObject object) {
+        return arrayList.add(object);
+    }
+    
+    public boolean add(float values[]) {
+        for (int k = 0; k < values.length; ++k)
+            arrayList.add(new PdfNumber(values[k]));
+        return true;
+    }
+    
+    public boolean add(int values[]) {
+        for (int k = 0; k < values.length; ++k)
+            arrayList.add(new PdfNumber(values[k]));
+        return true;
+    }
+    
+/**
+ * Adds a <CODE>PdfObject</CODE> to the <CODE>PdfArray</CODE>.
+ * <P>
+ * The newly added object will be the first element in the <CODE>ArrayList</CODE>.
+ *
+ * @param		object			<CODE>PdfObject</CODE> to add
+ */
+    
+    public void addFirst(PdfObject object) {
+        arrayList.add(0, object);
+    }
+    
+/**
+ * Checks if the <CODE>PdfArray</CODE> already contains a certain <CODE>PdfObject</CODE>.
+ *
+ * @param		object			<CODE>PdfObject</CODE> to check
+ * @return		<CODE>true</CODE>
+ */
+    
+    public boolean contains(PdfObject object) {
+        return arrayList.contains(object);
+    }
+    
+    public ListIterator listIterator() {
+        return arrayList.listIterator();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfBoolean.java b/LibrarySource/com/lowagie/text/pdf/PdfBoolean.java
new file mode 100644
index 0000000..3e7f207
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfBoolean.java
@@ -0,0 +1,130 @@
+/*
+ * $Id: PdfBoolean.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfBoolean</CODE> is the boolean object represented by the keywords <VAR>true</VAR> or <VAR>false</VAR>.
+ * <P>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.2 (page 37).
+ *
+ * @see		PdfObject
+ * @see		BadPdfFormatException
+ */
+
+public class PdfBoolean extends PdfObject {
+    
+    // static membervariables (possible values of a boolean object)
+    public static final PdfBoolean PDFTRUE = new PdfBoolean(true);
+    public static final PdfBoolean PDFFALSE = new PdfBoolean(false);
+/** A possible value of <CODE>PdfBoolean</CODE> */
+    public static final String TRUE = "true";
+    
+/** A possible value of <CODE>PdfBoolean</CODE> */
+    public static final String FALSE = "false";
+    
+    // membervariables
+    
+/** the boolean value of this object */
+    private boolean value;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfBoolean</CODE>-object.
+ *
+ * @param		value			the value of the new <CODE>PdfObject</CODE>
+ */
+    
+    public PdfBoolean(boolean value) {
+        super(BOOLEAN);
+        if (value) {
+            setContent(TRUE);
+        }
+        else {
+            setContent(FALSE);
+        }
+        this.value = value;
+    }
+    
+/**
+ * Constructs a <CODE>PdfBoolean</CODE>-object.
+ *
+ * @param		value			the value of the new <CODE>PdfObject</CODE>, represented as a <CODE>String</CODE>
+ *
+ * @throws		BadPdfFormatException	thrown if the <VAR>value</VAR> isn't '<CODE>true</CODE>' or '<CODE>false</CODE>'
+ */
+    
+    public PdfBoolean(String value) throws BadPdfFormatException {
+        super(BOOLEAN, value);
+        if (value.equals(TRUE)) {
+            this.value = true;
+        }
+        else if (value.equals(FALSE)) {
+            this.value = false;
+        }
+        else {
+            throw new BadPdfFormatException("The value has to be 'true' of 'false', instead of '" + value + "'.");
+        }
+    }
+    
+    // methods returning the value of this object
+    
+/**
+ * Returns the primitive value of the <CODE>PdfBoolean</CODE>-object.
+ *
+ * @return		the actual value of the object.
+ */
+    
+    public boolean booleanValue() {
+        return value;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfBorderArray.java b/LibrarySource/com/lowagie/text/pdf/PdfBorderArray.java
new file mode 100644
index 0000000..adfbfcf
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfBorderArray.java
@@ -0,0 +1,82 @@
+/*
+ * $Id: PdfBorderArray.java,v 1.23 2002/07/09 11:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * A <CODE>PdfBorderArray</CODE> defines the border of a <CODE>PdfAnnotation</CODE>.
+ *
+ * @see		PdfArray
+ */
+
+public class PdfBorderArray extends PdfArray {
+    
+    // constructors
+    
+/**
+ * Constructs a new <CODE>PdfBorderArray</CODE>.
+ */
+    
+    public PdfBorderArray(float hRadius, float vRadius, float width) {
+        this(hRadius, vRadius, width, null);
+    }
+    
+/**
+ * Constructs a new <CODE>PdfBorderArray</CODE>.
+ */
+    
+    public PdfBorderArray(float hRadius, float vRadius, float width, PdfDashPattern dash) {
+        super(new PdfNumber(hRadius));
+        add(new PdfNumber(vRadius));
+        add(new PdfNumber(width));
+        if (dash != null)
+            add(dash);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfBorderDictionary.java b/LibrarySource/com/lowagie/text/pdf/PdfBorderDictionary.java
new file mode 100644
index 0000000..a7299de
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfBorderDictionary.java
@@ -0,0 +1,100 @@
+/*
+ * $Id: PdfBorderDictionary.java,v 1.22 2002/06/20 13:28:20 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * A <CODE>PdfBorderDictionary</CODE> define the appearance of a Border (Annotations).
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfBorderDictionary extends PdfDictionary {
+    
+    public static final int STYLE_SOLID = 0;
+    public static final int STYLE_DASHED = 1;
+    public static final int STYLE_BEVELED = 2;
+    public static final int STYLE_INSET = 3;
+    public static final int STYLE_UNDERLINE = 4;
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfBorderDictionary</CODE>.
+ */
+    
+    public PdfBorderDictionary(float borderWidth, int borderStyle, PdfDashPattern dashes) {
+        put(PdfName.W, new PdfNumber(borderWidth));
+        switch (borderStyle) {
+            case STYLE_SOLID:
+                put(PdfName.S, PdfName.S);
+                break;
+            case STYLE_DASHED:
+                if (dashes != null)
+                    put(PdfName.D, dashes);
+                put(PdfName.S, PdfName.D);
+                break;
+            case STYLE_BEVELED:
+                put(PdfName.S, PdfName.B);
+                break;
+            case STYLE_INSET:
+                put(PdfName.S, PdfName.I);
+                break;
+            case STYLE_UNDERLINE:
+                put(PdfName.S, PdfName.U);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid border style.");
+        }
+    }
+    
+    public PdfBorderDictionary(float borderWidth, int borderStyle) {
+        this(borderWidth, borderStyle, null);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfCell.java b/LibrarySource/com/lowagie/text/pdf/PdfCell.java
new file mode 100644
index 0000000..9a6bf34
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfCell.java
@@ -0,0 +1,883 @@
+/*
+ * $Id: PdfCell.java,v 1.83 2004/11/15 17:39:15 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.lowagie.text.*;
+
+/**
+ * A <CODE>PdfCell</CODE> is the PDF translation of a <CODE>Cell</CODE>.
+ * <P>
+ * A <CODE>PdfCell</CODE> is an <CODE>ArrayList</CODE> of <CODE>PdfLine</CODE>s.
+ * <P>
+ * When using variable borders ({@link com.lowagie.text.Rectangle#isUseVariableBorders isUseVariableBorders()} == true),
+ * the borders are drawn completely inside the cell Rectangle
+ * so that adjacent cell borders will not overlap.
+ * Otherwise, the borders are drawn on top of the edges of the
+ * cell Rectangle and will overlap the borders of adjacent
+ * cells.
+ *
+ * @see		com.lowagie.text.Rectangle
+ * @see		com.lowagie.text.Cell
+ * @see		PdfLine
+ * @see		PdfTable
+ */
+
+public class PdfCell extends Rectangle {
+
+    // membervariables
+    
+    /**
+     * These are the PdfLines in the Cell.
+     */
+    private ArrayList lines;
+
+    /**
+     * These are the PdfLines in the Cell.
+     */
+    private PdfLine line;
+
+    /**
+     * These are the Images in the Cell.
+     */
+    private ArrayList images;
+
+    /**
+     * This is the leading of the lines.
+     */
+    private float leading;
+
+    /**
+     * This is the number of the row the cell is in.
+     */
+    private int rownumber;
+
+    /**
+     * This is the rowspan of the cell.
+     */
+    private int rowspan;
+
+    /**
+     * This is the cellspacing of the cell.
+     */
+    private float cellspacing;
+
+    /**
+     * This is the cellpadding of the cell.
+     */
+    private float cellpadding;
+
+    /**
+     * Indicates if this cell belongs to the header of a <CODE>PdfTable</CODE>
+     */
+    private boolean header = false;
+
+    /**
+     * This is the total height of the content of the cell.  Note that the actual cell
+     * height may be larger due to another cell on the row *
+     */
+    private float contentHeight = 0.0f;
+
+    /**
+     * Indicates that the largest ascender height should be used to
+     * determine the height of the first line. Setting this to true can help
+     * with vertical alignment problems. */
+    private boolean useAscender;
+
+    /**
+     * Indicates that the largest descender height should be added to the height of
+     * the last line (so characters like y don't dip into the border). */
+    private boolean useDescender;
+
+    /**
+     * Adjusts the cell contents to compensate for border widths.
+     */
+    private boolean useBorderPadding;
+
+    private int verticalAlignment;
+
+    private PdfLine firstLine;
+    private PdfLine lastLine;
+
+    // constructors
+    
+    /**
+     * Constructs a <CODE>PdfCell</CODE>-object.
+     *
+     * @param	cell		the original <CODE>Cell</CODE>
+     * @param	rownumber	the number of the <CODE>Row</CODE> the <CODE>Cell</CODE> was in.
+     * @param	left		the left border of the <CODE>PdfCell</CODE>
+     * @param	right		the right border of the <CODE>PdfCell</CODE>
+     * @param	top			the top border of the <CODE>PdfCell</CODE>
+     * @param	cellspacing	the cellspacing of the <CODE>Table</CODE>
+     * @param	cellpadding	the cellpadding	of the <CODE>Table</CODE>
+     */
+
+    public PdfCell(Cell cell, int rownumber, float left, float right, float top, float cellspacing, float cellpadding) {
+        // constructs a Rectangle (the bottomvalue will be changed afterwards)
+        super(left, top, right, top);
+        // copying the other Rectangle attributes from class Cell
+        cloneNonPositionParameters(cell);
+        this.cellpadding = cellpadding;
+        this.cellspacing = cellspacing;
+        this.verticalAlignment = cell.verticalAlignment();
+        this.useAscender = cell.isUseAscender();
+        this.useDescender = cell.isUseDescender();
+        this.useBorderPadding = cell.isUseBorderPadding();
+
+        // initialisation of some parameters
+        PdfChunk chunk;
+        Element element;
+        PdfChunk overflow;
+        lines = new ArrayList();
+        images = new ArrayList();
+        leading = cell.leading();
+        int alignment = cell.horizontalAlignment();
+        left += cellspacing + cellpadding;
+        right -= cellspacing + cellpadding;
+
+        left += getBorderWidthInside(LEFT);
+        right -= getBorderWidthInside(RIGHT);
+
+
+        contentHeight = 0;
+
+        rowspan = cell.rowspan();
+
+        ArrayList allActions;
+        int aCounter;
+        // we loop over all the elements of the cell
+        for (Iterator i = cell.getElements(); i.hasNext();) {
+            element = (Element) i.next();
+            switch (element.type()) {
+                case Element.JPEG:
+                case Element.IMGRAW:
+                case Element.IMGTEMPLATE:
+                    addImage((Image) element, left, right, 0.4f * leading, alignment); //
+                    break;
+                    // if the element is a list
+                case Element.LIST:
+                    if (line != null && line.size() > 0) {
+                        line.resetAlignment();
+                        addLine(line);
+                    }
+                    allActions = new ArrayList();
+                    processActions(element, null, allActions);
+                    aCounter = 0;
+                    ListItem item;
+                    // we loop over all the listitems
+                    for (Iterator items = ((List) element).getItems().iterator(); items.hasNext();) {
+                        item = (ListItem) items.next();
+                        line = new PdfLine(left + item.indentationLeft(), right, alignment, item.leading());
+                        line.setListItem(item);
+                        for (Iterator j = item.getChunks().iterator(); j.hasNext();) {
+                            chunk = new PdfChunk((Chunk) j.next(), (PdfAction) (allActions.get(aCounter++)));
+                            while ((overflow = line.add(chunk)) != null) {
+                                addLine(line);
+                                line = new PdfLine(left + item.indentationLeft(), right, alignment, item.leading());
+                                chunk = overflow;
+                            }
+                            line.resetAlignment();
+                            addLine(line);
+                            line = new PdfLine(left + item.indentationLeft(), right, alignment, leading);
+                        }
+                    }
+                    line = new PdfLine(left, right, alignment, leading);
+                    break;
+                    // if the element is something else
+                default:
+                    allActions = new ArrayList();
+                    processActions(element, null, allActions);
+                    aCounter = 0;
+
+                    float currentLineLeading = leading;
+                    float currentLeft = left;
+                    float currentRight = right;
+                    if (element instanceof Phrase) {
+                        currentLineLeading = ((Phrase) element).leading();
+                    }
+                    if (element instanceof Paragraph) {
+                        Paragraph p = (Paragraph) element;
+                        currentLeft += p.indentationLeft();
+                        currentRight -= p.indentationRight();
+                    }
+                    if (line == null) {
+                        line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
+                    }
+                    // we loop over the chunks
+                    ArrayList chunks = element.getChunks();
+                    if (chunks.isEmpty()) {
+                       addLine(line); // add empty line - all cells need some lines even if they are empty
+                       line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
+                    }
+                    else {
+                        for (Iterator j = chunks.iterator(); j.hasNext();) {
+                            Chunk c = (Chunk) j.next();
+                            chunk = new PdfChunk(c, (PdfAction) (allActions.get(aCounter++)));
+                            while ((overflow = line.add(chunk)) != null) {
+                                addLine(line);
+                                line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
+                                chunk = overflow;
+                            }
+                        }
+                    }
+                    // if the element is a paragraph, section or chapter, we reset the alignment and add the line
+                    switch (element.type()) {
+                        case Element.PARAGRAPH:
+                        case Element.SECTION:
+                        case Element.CHAPTER:
+                            line.resetAlignment();
+                            flushCurrentLine();
+                    }
+            }
+        }
+        flushCurrentLine();
+        if (lines.size() > cell.getMaxLines()) {
+            while (lines.size() > cell.getMaxLines()) {
+                removeLine(lines.size() - 1);
+            }
+            if (cell.getMaxLines() > 0) {
+                String more = cell.getShowTruncation();
+                if (more != null && more.length() > 0) {
+                    // Denote that the content has been truncated
+                    lastLine = (PdfLine) lines.get(lines.size() - 1);
+                    if (lastLine.size() >= 0) {
+                        PdfChunk lastChunk = lastLine.getChunk(lastLine.size() - 1);
+                        float moreWidth = new PdfChunk(more, lastChunk).width();
+                        while (lastChunk.toString().length() > 0 && lastChunk.width() + moreWidth > right - left) {
+                            // Remove characters to leave room for the 'more' indicator
+                            lastChunk.setValue(lastChunk.toString().substring(0, lastChunk.length() - 1));
+                        }
+                        lastChunk.setValue(lastChunk.toString() + more);
+                    } else {
+                        lastLine.add(new PdfChunk(new Chunk(more), null));
+                    }
+                }
+            }
+        }
+        // we set some additional parameters
+        if (useDescender && lastLine != null) {
+            contentHeight -= lastLine.getDescender();
+        }
+
+        // adjust first line height so that it touches the top
+        if (lines.size() > 0) {
+            firstLine = (PdfLine) lines.get(0);
+            float firstLineRealHeight = firstLineRealHeight();
+            contentHeight -= firstLine.height();
+            firstLine.height = firstLineRealHeight;
+            contentHeight += firstLineRealHeight;
+        }
+
+        float newBottom = top - contentHeight - (2f * cellpadding()) - (2f * cellspacing());
+        newBottom -= getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM);
+        setBottom(newBottom);
+
+        this.rownumber = rownumber;
+    }
+
+
+
+
+    // overriding of the Rectangle methods
+
+
+    /**
+     * Sets the bottom of the Rectangle and determines the proper {link #verticalOffset}
+     * to appropriately align the contents vertically.
+     */
+    public void setBottom(float value) {
+        super.setBottom(value);
+        float firstLineRealHeight = firstLineRealHeight();
+
+        float totalHeight = ury - value; // can't use top (already compensates for cellspacing)
+        float nonContentHeight = (cellpadding() * 2f) + (cellspacing() * 2f);
+        nonContentHeight += getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM);
+
+        float interiorHeight = totalHeight - nonContentHeight;
+        float extraHeight = 0.0f;
+
+        switch (verticalAlignment) {
+            case Element.ALIGN_BOTTOM:
+                extraHeight = interiorHeight - contentHeight;
+                break;
+            case Element.ALIGN_MIDDLE:
+                extraHeight = (interiorHeight - contentHeight) / 2.0f;
+                break;
+            default:    // ALIGN_TOP
+                extraHeight = 0f;
+        }
+
+        extraHeight += cellpadding() + cellspacing();
+        extraHeight += getBorderWidthInside(TOP);
+        if (firstLine != null) {
+            firstLine.height = firstLineRealHeight + extraHeight;
+        }
+    }
+
+    /**
+     * Returns the lower left x-coordinaat.
+     *
+     * @return		the lower left x-coordinaat
+     */
+
+    public float left() {
+        return super.left(cellspacing);
+    }
+
+    /**
+     * Returns the upper right x-coordinate.
+     *
+     * @return		the upper right x-coordinate
+     */
+
+    public float right() {
+        return super.right(cellspacing);
+    }
+
+    /**
+     * Returns the upper right y-coordinate.
+     *
+     * @return		the upper right y-coordinate
+     */
+
+    public float top() {
+        return super.top(cellspacing);
+    }
+
+    /**
+     * Returns the lower left y-coordinate.
+     *
+     * @return		the lower left y-coordinate
+     */
+
+    public float bottom() {
+        return super.bottom(cellspacing);
+    }
+    
+    // methods
+
+    private void addLine(PdfLine line) {
+        lines.add(line);
+        contentHeight += line.height();
+        lastLine = line;
+        this.line = null;
+    }
+
+    private PdfLine removeLine(int index) {
+        PdfLine oldLine = (PdfLine) lines.remove(index);
+        contentHeight -= oldLine.height();
+        if (index == 0) {
+            if (lines.size() > 0) {
+                firstLine = (PdfLine) lines.get(0);
+                float firstLineRealHeight = firstLineRealHeight();
+                contentHeight -= firstLine.height();
+                firstLine.height = firstLineRealHeight;
+                contentHeight += firstLineRealHeight;
+            }
+        }
+        return oldLine;
+    }
+
+    private void flushCurrentLine() {
+        if (line != null && line.size() > 0) {
+            addLine(line);
+        }
+    }
+
+    /**
+     * Calculates what the height of the first line should be so that the content will be
+     * flush with the top.  For text, this is the height of the ascender.  For an image,
+     * it is the actual height of the image.
+     */
+    private float firstLineRealHeight() {
+        float firstLineRealHeight = 0f;
+        if (firstLine != null) {
+            PdfChunk chunk = firstLine.getChunk(0);
+            if (chunk != null) {
+                Image image = chunk.getImage();
+                if (image != null) {
+                    firstLineRealHeight = firstLine.getChunk(0).getImage().scaledHeight();
+                } else {
+                    firstLineRealHeight = useAscender ? firstLine.getAscender() : leading;
+                }
+            }
+        }
+        return firstLineRealHeight;
+    }
+
+    /**
+     * Gets the amount of the border for the specified side that is inside the Rectangle.
+     * For non-variable width borders this is only 1/2 the border width on that side.  This
+     * always returns 0 if {@link #useBorderPadding} is false;
+     * @param side the side to check.  One of the side constants in {@link com.lowagie.text.Rectangle}
+     */
+    private float getBorderWidthInside(int side) {
+        float width = 0f;
+        if (useBorderPadding) {
+            switch (side) {
+                case Rectangle.LEFT:
+                    width = getBorderWidthLeft();
+                    break;
+
+                case Rectangle.RIGHT:
+                    width = getBorderWidthRight();
+                    break;
+
+                case Rectangle.TOP:
+                    width = getBorderWidthTop();
+                    break;
+
+                default:    // default and BOTTOM
+                    width = getBorderWidthBottom();
+                    break;
+            }
+            // non-variable (original style) borders overlap the rectangle (only 1/2 counts)
+            if (!isUseVariableBorders()) {
+                width = width / 2f;
+            }
+        }
+        return width;
+    }
+
+
+    /**
+     * Adds an image to this Cell.
+     *
+     * @param i           the image to add
+     * @param left        the left border
+     * @param right       the right border
+     * @param extraHeight extra height to add above image
+     * @param alignment   horizontal alignment (constant from Element class)
+     */
+
+    private float addImage(Image i, float left, float right, float extraHeight, int alignment) {
+        Image image = Image.getInstance(i);
+        if (image.scaledWidth() > right - left) {
+            image.scaleToFit(right - left, Float.MAX_VALUE);
+        }
+        flushCurrentLine();
+        if (line == null) {
+            line = new PdfLine(left, right, alignment, leading);
+        }
+        PdfLine imageLine = line;
+
+        // left and right in chunk is relative to the start of the line
+        right = right - left;
+        left = 0f;
+
+        if ((image.alignment() & Image.RIGHT) == Image.RIGHT) { // fix Uwe Zimmerman
+            left = right - image.scaledWidth();
+        } else if ((image.alignment() & Image.MIDDLE) == Image.MIDDLE) {
+            left = left + ((right - left - image.scaledWidth()) / 2f);
+        }
+        Chunk imageChunk = new Chunk(image, left, 0);
+        imageLine.add(new PdfChunk(imageChunk, null));
+        addLine(imageLine);
+        return imageLine.height();
+    }
+
+    /**
+     * Gets the lines of a cell that can be drawn between certain limits.
+     * <P>
+     * Remark: all the lines that can be drawn are removed from the object!
+     *
+     * @param	top		the top of the part of the table that can be drawn
+     * @param	bottom	the bottom of the part of the table that can be drawn
+     * @return	an <CODE>ArrayList</CODE> of <CODE>PdfLine</CODE>s
+     */
+
+    public ArrayList getLines(float top, float bottom) {
+        float lineHeight;
+        float currentPosition = Math.min(top(), top);
+        setTop(currentPosition + cellspacing);
+        ArrayList result = new ArrayList();
+
+        // if the bottom of the page is higher than the top of the cell: do nothing
+        if (top() < bottom) {
+            return result;
+        }
+        
+        // we loop over the lines
+        int size = lines.size();
+        boolean aboveBottom = true;
+        for (int i = 0; i < size && aboveBottom; i++) {
+            line = (PdfLine) lines.get(i);
+            lineHeight = line.height();
+            currentPosition -= lineHeight;
+            // if the currentPosition is higher than the bottom, we add the line to the result
+            if (currentPosition > (bottom + cellpadding + getBorderWidthInside(BOTTOM))) { // bugfix by Tom Ring and Veerendra Namineni
+                result.add(line);
+            } else {
+                aboveBottom = false;
+            }
+        }
+        // if the bottom of the cell is higher than the bottom of the page, the cell is written, so we can remove all lines
+        float difference = 0f;
+        if (!header) {
+            if (aboveBottom) {
+                lines = new ArrayList();
+                contentHeight = 0f;
+            } else {
+                size = result.size();
+                for (int i = 0; i < size; i++) {
+                    line = (PdfLine) removeLine(0);
+                    difference += line.height();
+                }
+            }
+        }
+        if (difference > 0) {
+            Image image;
+            for (Iterator i = images.iterator(); i.hasNext();) {
+                image = (Image) i.next();
+                image.setAbsolutePosition(image.absoluteX(), image.absoluteY() - difference - leading);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Gets the images of a cell that can be drawn between certain limits.
+     * <P>
+     * Remark: all the lines that can be drawn are removed from the object!
+     *
+     * @param	top		the top of the part of the table that can be drawn
+     * @param	bottom	the bottom of the part of the table that can be drawn
+     * @return	an <CODE>ArrayList</CODE> of <CODE>Image</CODE>s
+     */
+
+    public ArrayList getImages(float top, float bottom) {
+
+        // if the bottom of the page is higher than the top of the cell: do nothing
+        if (top() < bottom) {
+            return new ArrayList();
+        }
+        top = Math.min(top(), top);
+        // initialisations
+        Image image;
+        float height;
+        ArrayList result = new ArrayList();
+        // we loop over the images
+        for (Iterator i = images.iterator(); i.hasNext() && !header;) {
+            image = (Image) i.next();
+            height = image.absoluteY();
+            // if the currentPosition is higher than the bottom, we add the line to the result
+            if (top - height > (bottom + cellpadding)) {
+                image.setAbsolutePosition(image.absoluteX(), top - height);
+                result.add(image);
+                i.remove();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks if this cell belongs to the header of a <CODE>PdfTable</CODE>.
+     *
+     * @return	<CODE>void</CODE>
+     */
+
+    boolean isHeader() {
+        return header;
+    }
+
+    /**
+     * Indicates that this cell belongs to the header of a <CODE>PdfTable</CODE>.
+     */
+
+    void setHeader() {
+        header = true;
+    }
+
+    /**
+     * Checks if the cell may be removed.
+     * <P>
+     * Headers may allways be removed, even if they are drawn only partially:
+     * they will be repeated on each following page anyway!
+     *
+     * @return	<CODE>true</CODE> if all the lines are allready drawn; <CODE>false</CODE> otherwise.
+     */
+
+    boolean mayBeRemoved() {
+        return (header || (lines.size() == 0 && images.size() == 0));
+    }
+
+    /**
+     * Returns the number of lines in the cell.
+     *
+     * @return	a value
+     */
+
+    public int size() {
+        return lines.size();
+    }
+
+    /**
+     * Returns the number of lines in the cell that are not empty.
+     *
+     * @return	a value
+     */
+
+    public int remainingLines() {
+        if (lines.size() == 0) return 0;
+        int result = 0;
+        int size = lines.size();
+        PdfLine line;
+        for (int i = 0; i < size; i++) {
+            line = (PdfLine) lines.get(i);
+            if (line.size() > 0) result++;
+        }
+        return result;
+    }
+
+    /**
+     * Returns the height needed to draw the remaining text.
+     *
+     * @return a height
+     */
+
+    public float remainingHeight() {
+        float result = 0f;
+        for (Iterator i = images.iterator(); i.hasNext();) {
+            Image image = (Image) i.next();
+            result += image.scaledHeight();
+        }
+        return remainingLines() * leading + 2 * cellpadding + cellspacing + result + leading / 2.5f;
+    }
+    
+    // methods to retrieve membervariables
+    
+    /**
+     * Gets the leading of a cell.
+     *
+     * @return	the leading of the lines is the cell.
+     */
+
+    public float leading() {
+        return leading;
+    }
+
+    /**
+     * Gets the number of the row this cell is in..
+     *
+     * @return	a number
+     */
+
+    public int rownumber() {
+        return rownumber;
+    }
+
+    /**
+     * Gets the rowspan of a cell.
+     *
+     * @return	the rowspan of the cell
+     */
+
+    public int rowspan() {
+        return rowspan;
+    }
+
+    /**
+     * Gets the cellspacing of a cell.
+     *
+     * @return	a value
+     */
+
+    public float cellspacing() {
+        return cellspacing;
+    }
+
+    /**
+     * Gets the cellpadding of a cell..
+     *
+     * @return	a value
+     */
+
+    public float cellpadding() {
+        return cellpadding;
+    }
+
+    /**
+     * Processes all actions contained in the cell.
+     */
+
+    protected void processActions(Element element, PdfAction action, ArrayList allActions) {
+        if (element.type() == Element.ANCHOR) {
+            String url = ((Anchor) element).reference();
+            if (url != null) {
+                action = new PdfAction(url);
+            }
+        }
+        Iterator i;
+        switch (element.type()) {
+            case Element.PHRASE:
+            case Element.SECTION:
+            case Element.ANCHOR:
+            case Element.CHAPTER:
+            case Element.LISTITEM:
+            case Element.PARAGRAPH:
+                for (i = ((ArrayList) element).iterator(); i.hasNext();) {
+                    processActions((Element) i.next(), action, allActions);
+                }
+                break;
+            case Element.CHUNK:
+                allActions.add(action);
+                break;
+            case Element.LIST:
+                for (i = ((List) element).getItems().iterator(); i.hasNext();) {
+                    processActions((Element) i.next(), action, allActions);
+                }
+                break;
+            default:
+                ArrayList tmp = element.getChunks();
+                int n = element.getChunks().size();
+                while (n-- > 0)
+                    allActions.add(action);
+                break;
+        }
+    }
+
+    /**
+     * This is the number of the group the cell is in.
+     */
+    private int groupNumber;
+
+    /**
+     * Gets the number of the group this cell is in..
+     *
+     * @return	a number
+     */
+
+    public int getGroupNumber() {
+        return groupNumber;
+    }
+
+    /**
+     * Sets the group number.
+     */
+
+    void setGroupNumber(int number) {
+        groupNumber = number;
+    }
+
+    /**
+     * Gets a Rectangle that is altered to fit on the page.
+     *
+     * @param	top		the top position
+     * @param	bottom	the bottom position
+     * @return	a <CODE>Rectangle</CODE>
+     */
+
+    public Rectangle rectangle(float top, float bottom) {
+        Rectangle tmp = new Rectangle(left(), bottom(), right(), top());
+        tmp.cloneNonPositionParameters(this);
+        if (top() > top) {
+            tmp.setTop(top);
+            tmp.setBorder(border - (border & TOP));
+        }
+        if (bottom() < bottom) {
+            tmp.setBottom(bottom);
+            tmp.setBorder(border - (border & BOTTOM));
+        }
+        return tmp;
+    }
+
+    /**
+     * Sets the value of {@link #useAscender}.
+     * @param use use ascender height if true
+     */
+    public void setUseAscender(boolean use) {
+        useAscender = use;
+    }
+
+    /**
+     * Gets the value of {@link #useAscender}
+     * @return useAscender
+     */
+    public boolean isUseAscender() {
+        return useAscender;
+    }
+
+    /**
+     * Sets the value of {@link #useDescender}.
+     * @param use use descender height if true
+     */
+    public void setUseDescender(boolean use) {
+        useDescender = use;
+    }
+
+    /**
+     * gets the value of {@link #useDescender }
+     * @return useDescender
+     */
+    public boolean isUseDescender() {
+        return useDescender;
+    }
+
+    /**
+     * Sets the value of {@link #useBorderPadding}.
+     * @param use adjust layour for borders if true
+     */
+    public void setUseBorderPadding(boolean use) {
+        useBorderPadding = use;
+    }
+
+    /**
+     * Gets the value of {@link #useBorderPadding}.
+     * @return useBorderPadding
+     */
+    public boolean isUseBorderPadding() {
+        return useBorderPadding;
+    }
+
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfChunk.java b/LibrarySource/com/lowagie/text/pdf/PdfChunk.java
new file mode 100644
index 0000000..d8316f7
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfChunk.java
@@ -0,0 +1,782 @@
+/*
+ * $Id: PdfChunk.java,v 1.70 2004/12/20 11:39:08 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Font;
+import com.lowagie.text.Image;
+import com.lowagie.text.SplitCharacter;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A <CODE>PdfChunk</CODE> is the PDF translation of a <CODE>Chunk</CODE>.
+ * <P>
+ * A <CODE>PdfChunk</CODE> is a <CODE>PdfString</CODE> in a certain
+ * <CODE>PdfFont</CODE> and <CODE>Color</CODE>.
+ *
+ * @see		PdfString
+ * @see		PdfFont
+ * @see		com.lowagie.text.Chunk
+ * @see		com.lowagie.text.Font
+ */
+
+public class PdfChunk implements SplitCharacter{
+
+    private static final char singleSpace[] = {' '};
+    private static final PdfChunk thisChunk[] = new PdfChunk[1];
+    private static final float ITALIC_ANGLE = 0.21256f;
+/** The allowed attributes in variable <CODE>attributes</CODE>. */
+    private static final HashMap keysAttributes = new HashMap();
+    
+/** The allowed attributes in variable <CODE>noStroke</CODE>. */
+    private static final HashMap keysNoStroke = new HashMap();
+    
+    static {
+        keysAttributes.put(Chunk.ACTION, null);
+        keysAttributes.put(Chunk.UNDERLINE, null);
+        keysAttributes.put(Chunk.REMOTEGOTO, null);
+        keysAttributes.put(Chunk.LOCALGOTO, null);
+        keysAttributes.put(Chunk.LOCALDESTINATION, null);
+        keysAttributes.put(Chunk.GENERICTAG, null);
+        keysAttributes.put(Chunk.NEWPAGE, null);
+        keysAttributes.put(Chunk.IMAGE, null);
+        keysAttributes.put(Chunk.BACKGROUND, null);
+        keysAttributes.put(Chunk.PDFANNOTATION, null);
+        keysAttributes.put(Chunk.SKEW, null);
+        keysAttributes.put(Chunk.HSCALE, null);
+        keysNoStroke.put(Chunk.SUBSUPSCRIPT, null);
+        keysNoStroke.put(Chunk.SPLITCHARACTER, null);
+        keysNoStroke.put(Chunk.HYPHENATION, null);
+        keysNoStroke.put(Chunk.TEXTRENDERMODE, null);
+    }
+    
+    // membervariables
+
+    /** The value of this object. */
+    protected String value = PdfObject.NOTHING;
+    
+    /** The encoding. */
+    protected String encoding = BaseFont.WINANSI;
+    
+    
+/** The font for this <CODE>PdfChunk</CODE>. */
+    protected PdfFont font;
+    
+    protected BaseFont baseFont;
+    
+    protected SplitCharacter splitCharacter;
+/**
+ * Metric attributes.
+ * <P>
+ * This attributes require the mesurement of characters widths when rendering
+ * such as underline.
+ */
+    protected HashMap attributes = new HashMap();
+    
+/**
+ * Non metric attributes.
+ * <P>
+ * This attributes do not require the mesurement of characters widths when rendering
+ * such as Color.
+ */
+    protected HashMap noStroke = new HashMap();
+    
+/** <CODE>true</CODE> if the chunk split was cause by a newline. */
+    protected boolean newlineSplit;
+    
+/** The image in this <CODE>PdfChunk</CODE>, if it has one */
+    protected Image image;
+    
+/** The offset in the x direction for the image */
+    protected float offsetX;
+    
+/** The offset in the y direction for the image */
+    protected float offsetY;
+
+/** Indicates if the height and offset of the Image has to be taken into account */
+    protected boolean changeLeading = false;
+
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfChunk</CODE>-object.
+ *
+ * @param string the content of the <CODE>PdfChunk</CODE>-object
+ * @param other Chunk with the same style you want for the new Chunk
+ */
+    
+    PdfChunk(String string, PdfChunk other) {
+        thisChunk[0] = this;
+        value = string;
+        this.font = other.font;
+        this.attributes = other.attributes;
+        this.noStroke = other.noStroke;
+        this.baseFont = other.baseFont;
+        Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
+        if (obj == null)
+            image = null;
+        else {
+            image = (Image)obj[0];
+            offsetX = ((Float)obj[1]).floatValue();
+            offsetY = ((Float)obj[2]).floatValue();
+            changeLeading = ((Boolean)obj[3]).booleanValue();
+        }
+        encoding = font.getFont().getEncoding();
+        splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
+        if (splitCharacter == null)
+            splitCharacter = this;
+    }
+    
+/**
+ * Constructs a <CODE>PdfChunk</CODE>-object.
+ *
+ * @param chunk the original <CODE>Chunk</CODE>-object
+ * @param action the <CODE>PdfAction</CODE> if the <CODE>Chunk</CODE> comes from an <CODE>Anchor</CODE>
+ */
+    
+    PdfChunk(Chunk chunk, PdfAction action) {
+        thisChunk[0] = this;
+        value = chunk.content();
+        
+        Font f = chunk.font();
+        float size = f.size();
+        if (size == Font.UNDEFINED)
+            size = 12;
+        baseFont = f.getBaseFont();
+        int style = f.style();
+        if (style == Font.UNDEFINED) {
+            style = Font.NORMAL;
+        }
+        if (baseFont == null) {
+            // translation of the font-family to a PDF font-family
+            baseFont = f.getCalculatedBaseFont(false);
+        }
+        else {
+            // bold simulation
+            if ((style & Font.BOLD) != 0)
+                attributes.put(Chunk.TEXTRENDERMODE, new Object[]{new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null});
+            // italic simulation
+            if ((style & Font.ITALIC) != 0)
+                attributes.put(Chunk.SKEW, new float[]{0, ITALIC_ANGLE});
+        }
+        font = new PdfFont(baseFont, size);
+        // other style possibilities
+        HashMap attr = chunk.getAttributes();
+        if (attr != null) {
+            for (Iterator i = attr.keySet().iterator(); i.hasNext();) {
+                Object name = i.next();
+                if (keysAttributes.containsKey(name)) {
+                    attributes.put(name, attr.get(name));
+                }
+                else if (keysNoStroke.containsKey(name)) {
+                    noStroke.put(name, attr.get(name));
+                }
+            }
+            if ("".equals(attr.get(Chunk.GENERICTAG))) {
+                attributes.put(Chunk.GENERICTAG, chunk.content());
+            }
+        }
+        if (f.isUnderlined()) {
+            Object obj[] = {null, new float[]{0, 1f / 15, 0, -1f / 3, 0}};
+            Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
+            attributes.put(Chunk.UNDERLINE, unders);
+        }
+        if (f.isStrikethru()) {
+            Object obj[] = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}};
+            Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
+            attributes.put(Chunk.UNDERLINE, unders);
+        }
+        if (action != null)
+            attributes.put(Chunk.ACTION, action);
+        // the color can't be stored in a PdfFont
+        noStroke.put(Chunk.COLOR, f.color());
+        noStroke.put(Chunk.ENCODING, font.getFont().getEncoding());
+        Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
+        if (obj == null) {
+            image = null;
+        }
+        else {
+            attributes.remove(Chunk.HSCALE); // images are scaled in other ways
+            image = (Image)obj[0];
+            offsetX = ((Float)obj[1]).floatValue();
+            offsetY = ((Float)obj[2]).floatValue();
+            changeLeading = ((Boolean)obj[3]).booleanValue();
+        }
+        font.setImage(image);
+        Float hs = (Float)attributes.get(Chunk.HSCALE);
+        if (hs != null)
+            font.setHorizontalScaling(hs.floatValue());
+        encoding = font.getFont().getEncoding();
+        splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
+        if (splitCharacter == null)
+            splitCharacter = this;
+    }
+    
+    // methods
+    
+    /** Gets the Unicode equivalent to a CID.
+     * The (inexistent) CID <FF00> is translated as '\n'. 
+     * It has only meaning with CJK fonts with Identity encoding.
+     * @param c the CID code
+     * @return the Unicode equivalent
+     */    
+    public char getUnicodeEquivalent(char c) {
+        return baseFont.getUnicodeEquivalent(c);
+    }
+
+    protected int getWord(String text, int start) {
+        int len = text.length();
+        while (start < len) {
+            if (!Character.isLetter(text.charAt(start)))
+                break;
+            ++start;
+        }
+        return start;
+    }
+    
+/**
+ * Splits this <CODE>PdfChunk</CODE> if it's too long for the given width.
+ * <P>
+ * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
+ *
+ * @param		width		a given width
+ * @return		the <CODE>PdfChunk</CODE> that doesn't fit into the width.
+ */
+    
+    PdfChunk split(float width) {
+        newlineSplit = false;
+        if (image != null) {
+            if (image.scaledWidth() > width) {
+                PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
+                value = "";
+                attributes = new HashMap();
+                image = null;
+                font = PdfFont.getDefaultFont();
+                return pc;
+            }
+            else
+                return null;
+        }
+        HyphenationEvent hyphenationEvent = (HyphenationEvent)noStroke.get(Chunk.HYPHENATION);
+        int currentPosition = 0;
+        int splitPosition = -1;
+        float currentWidth = 0;
+        
+        // loop over all the characters of a string
+        // or until the totalWidth is reached
+        int lastSpace = -1;
+        float lastSpaceWidth = 0;
+        int length = value.length();
+        char valueArray[] = value.toCharArray();
+        char character = 0;
+        BaseFont ft = font.getFont();
+        if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+            while (currentPosition < length) {
+                // the width of every character is added to the currentWidth
+                char cidChar = valueArray[currentPosition];
+                character = ft.getUnicodeEquivalent(cidChar);
+                // if a newLine or carriageReturn is encountered
+                if (character == '\n') {
+                    newlineSplit = true;
+                    String returnValue = value.substring(currentPosition + 1);
+                    value = value.substring(0, currentPosition);
+                    if (value.length() < 1) {
+                        value = "\u0001";
+                    }
+                    PdfChunk pc = new PdfChunk(returnValue, this);
+                    return pc;
+                }
+                currentWidth += font.width(cidChar);
+                if (character == ' ') {
+                    lastSpace = currentPosition + 1;
+                    lastSpaceWidth = currentWidth;
+                }
+                if (currentWidth > width)
+                    break;
+                // if a split-character is encountered, the splitPosition is altered
+                if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
+                    splitPosition = currentPosition + 1;
+                currentPosition++;
+            }
+        }
+        else {
+            while (currentPosition < length) {
+                // the width of every character is added to the currentWidth
+                character = valueArray[currentPosition];
+                // if a newLine or carriageReturn is encountered
+                if (character == '\r' || character == '\n') {
+                    newlineSplit = true;
+                    int inc = 1;
+                    if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n')
+                        inc = 2;
+                    String returnValue = value.substring(currentPosition + inc);
+                    value = value.substring(0, currentPosition);
+                    if (value.length() < 1) {
+                        value = " ";
+                    }
+                    PdfChunk pc = new PdfChunk(returnValue, this);
+                    return pc;
+                }
+                currentWidth += font.width(character);
+                if (character == ' ') {
+                    lastSpace = currentPosition + 1;
+                    lastSpaceWidth = currentWidth;
+                }
+                if (currentWidth > width)
+                    break;
+                // if a split-character is encountered, the splitPosition is altered
+                if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null))
+                    splitPosition = currentPosition + 1;
+                currentPosition++;
+            }
+        }
+        
+        // if all the characters fit in the total width, null is returned (there is no overflow)
+        if (currentPosition == length) {
+            return null;
+        }
+        // otherwise, the string has to be truncated
+        if (splitPosition < 0) {
+            String returnValue = value;
+            value = "";
+            PdfChunk pc = new PdfChunk(returnValue, this);
+            return pc;
+        }
+        if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null))
+            splitPosition = lastSpace;
+        if (hyphenationEvent != null && lastSpace < currentPosition) {
+            int wordIdx = getWord(value, lastSpace);
+            if (wordIdx > lastSpace) {
+                String pre = hyphenationEvent.getHyphenatedWordPre(value.substring(lastSpace, wordIdx), font.getFont(), font.size(), width - lastSpaceWidth);
+                String post = hyphenationEvent.getHyphenatedWordPost();
+                if (pre.length() > 0) {
+                    String returnValue = post + value.substring(wordIdx);
+                    value = trim(value.substring(0, lastSpace) + pre);
+                    PdfChunk pc = new PdfChunk(returnValue, this);
+                    return pc;
+                }
+            }
+        }
+        String returnValue = value.substring(splitPosition);
+        value = trim(value.substring(0, splitPosition));
+        PdfChunk pc = new PdfChunk(returnValue, this);
+        return pc;
+    }
+    
+/**
+ * Truncates this <CODE>PdfChunk</CODE> if it's too long for the given width.
+ * <P>
+ * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
+ *
+ * @param		width		a given width
+ * @return		the <CODE>PdfChunk</CODE> that doesn't fit into the width.
+ */
+    
+    PdfChunk truncate(float width) {
+        if (image != null) {
+            if (image.scaledWidth() > width) {
+                PdfChunk pc = new PdfChunk("", this);
+                value = "";
+                attributes.remove(Chunk.IMAGE);
+                image = null;
+                font = PdfFont.getDefaultFont();
+                return pc;
+            }
+            else
+                return null;
+        }
+        
+        int currentPosition = 0;
+        float currentWidth = 0;
+        
+        // it's no use trying to split if there isn't even enough place for a space
+        if (width < font.width()) {
+            String returnValue = value.substring(1);
+            value = value.substring(0, 1);
+            PdfChunk pc = new PdfChunk(returnValue, this);
+            return pc;
+        }
+        
+        // loop over all the characters of a string
+        // or until the totalWidth is reached
+        int length = value.length();
+        char character;
+        while (currentPosition < length) {
+            // the width of every character is added to the currentWidth
+            character = value.charAt(currentPosition);
+            currentWidth += font.width(character);
+            if (currentWidth > width)
+                break;
+            currentPosition++;
+        }
+        
+        // if all the characters fit in the total width, null is returned (there is no overflow)
+        if (currentPosition == length) {
+            return null;
+        }
+        
+        // otherwise, the string has to be truncated
+        //currentPosition -= 2;
+        // we have to chop off minimum 1 character from the chunk
+        if (currentPosition == 0) {
+            currentPosition = 1;
+        }
+        String returnValue = value.substring(currentPosition);
+        value = value.substring(0, currentPosition);
+        PdfChunk pc = new PdfChunk(returnValue, this);
+        return pc;
+    }
+    
+    // methods to retrieve the membervariables
+    
+/**
+ * Returns the font of this <CODE>Chunk</CODE>.
+ *
+ * @return	a <CODE>PdfFont</CODE>
+ */
+    
+    PdfFont font() {
+        return font;
+    }
+    
+/**
+ * Returns the color of this <CODE>Chunk</CODE>.
+ *
+ * @return	a <CODE>Color</CODE>
+ */
+    
+    Color color() {
+        return (Color)noStroke.get(Chunk.COLOR);
+    }
+    
+/**
+ * Returns the width of this <CODE>PdfChunk</CODE>.
+ *
+ * @return	a width
+ */
+    
+    float width() {
+        return font.width(value);
+    }
+    
+/**
+ * Checks if the <CODE>PdfChunk</CODE> split was caused by a newline.
+ * @return <CODE>true</CODE> if the <CODE>PdfChunk</CODE> split was caused by a newline.
+ */
+    
+    public boolean isNewlineSplit()
+    {
+        return newlineSplit;
+    }
+    
+/**
+ * Gets the width of the <CODE>PdfChunk</CODE> taking into account the
+ * extra character and word spacing.
+ * @param charSpacing the extra character spacing
+ * @param wordSpacing the extra word spacing
+ * @return the calculated width
+ */
+    
+    public float getWidthCorrected(float charSpacing, float wordSpacing)
+    {
+        if (image != null) {
+            return image.scaledWidth() + charSpacing;
+        }
+        int numberOfSpaces = 0;
+        int idx = -1;
+        while ((idx = value.indexOf(' ', idx + 1)) >= 0)
+            ++numberOfSpaces;
+        return width() + (value.length() * charSpacing + numberOfSpaces * wordSpacing);
+    }
+    
+    /**
+     * Gets the text displacement relatiev to the baseline.
+     * @return a displacement in points
+     */
+    public float getTextRise() {
+    	Float f = (Float) getAttribute(Chunk.SUBSUPSCRIPT);
+    	if (f != null) {
+    		return f.floatValue();
+    	}
+    	return 0.0f;
+    }
+    
+/**
+ * Trims the last space.
+ * @return the width of the space trimmed, otherwise 0
+ */
+    
+    public float trimLastSpace()
+    {
+        BaseFont ft = font.getFont();
+        if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+            if (value.length() > 1 && value.endsWith("\u0001")) {
+                value = value.substring(0, value.length() - 1);
+                return font.width('\u0001');
+            }
+        }
+        else {
+            if (value.length() > 1 && value.endsWith(" ")) {
+                value = value.substring(0, value.length() - 1);
+                return font.width(' ');
+            }
+        }
+        return 0;
+    }
+    
+/**
+ * Gets an attribute. The search is made in <CODE>attributes</CODE>
+ * and <CODE>noStroke</CODE>.
+ * @param name the attribute key
+ * @return the attribute value or null if not found
+ */
+    
+    Object getAttribute(String name)
+    {
+        if (attributes.containsKey(name))
+            return attributes.get(name);
+        return noStroke.get(name);
+    }
+    
+/**
+ *Checks if the attribute exists.
+ * @param name the attribute key
+ * @return <CODE>true</CODE> if the attribute exists
+ */
+    
+    boolean isAttribute(String name)
+    {
+        if (attributes.containsKey(name))
+            return true;
+        return noStroke.containsKey(name);
+    }
+    
+/**
+ * Checks if this <CODE>PdfChunk</CODE> needs some special metrics handling.
+ * @return <CODE>true</CODE> if this <CODE>PdfChunk</CODE> needs some special metrics handling.
+ */
+    
+    boolean isStroked()
+    {
+        return (attributes.size() > 0);
+    }
+    
+/**
+ * Checks if there is an image in the <CODE>PdfChunk</CODE>.
+ * @return <CODE>true</CODE> if an image is present
+ */
+    
+    boolean isImage()
+    {
+        return image != null;
+    }
+    
+/**
+ * Gets the image in the <CODE>PdfChunk</CODE>.
+ * @return the image or <CODE>null</CODE>
+ */
+    
+    Image getImage()
+    {
+        return image;
+    }
+    
+/**
+ * Sets the image offset in the x direction
+ * @param  offsetX the image offset in the x direction
+ */
+    
+    void setImageOffsetX(float offsetX)
+    {
+        this.offsetX = offsetX;
+    }
+    
+/**
+ * Gets the image offset in the x direction
+ * @return the image offset in the x direction
+ */
+    
+    float getImageOffsetX()
+    {
+        return offsetX;
+    }
+    
+/**
+ * Sets the image offset in the y direction
+ * @param  offsetY the image offset in the y direction
+ */
+    
+    void setImageOffsetY(float offsetY)
+    {
+        this.offsetY = offsetY;
+    }
+    
+/**
+ * Gets the image offset in the y direction
+ * @return Gets the image offset in the y direction
+ */
+    
+    float getImageOffsetY()
+    {
+        return offsetY;
+    }
+    
+/**
+ * sets the value.
+ * @param value content of the Chunk
+ */
+    
+    void setValue(String value)
+    {
+        this.value = value;
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return value;
+    }
+
+    /**
+     * Tells you if this string is in Chinese, Japanese, Korean or Identity-H.
+     * @return true if the Chunk has a special encoding
+     */
+    
+    boolean isSpecialEncoding() {
+        return encoding.equals(CJKFont.CJK_ENCODING) || encoding.equals(BaseFont.IDENTITY_H);
+    }
+    
+    /**
+     * Gets the encoding of this string.
+     *
+     * @return		a <CODE>String</CODE>
+     */
+    
+    String getEncoding() {
+        return encoding;
+    }
+
+    int length() {
+        return value.length();
+    }
+/**
+ * Checks if a character can be used to split a <CODE>PdfString</CODE>.
+ * <P>
+ * for the moment every character less than or equal to SPACE and the character '-' are 'splitCharacters'.
+ * 
+ * @param start start position in the array
+ * @param current current position in the array
+ * @param end end position in the array
+ * @param	cc		the character array that has to be checked
+ * @param ck chunk array
+ * @return	<CODE>true</CODE> if the character can be used to split a string, <CODE>false</CODE> otherwise
+ */
+    public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+        char c;
+        if (ck == null)
+            c = cc[current];
+        else
+            c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
+        if (c <= ' ' || c == '-') {
+            return true;
+        }
+        if (c < 0x2e80)
+            return false;
+        return ((c >= 0x2e80 && c < 0xd7a0)
+        || (c >= 0xf900 && c < 0xfb00)
+        || (c >= 0xfe30 && c < 0xfe50)
+        || (c >= 0xff61 && c < 0xffa0));
+    }
+    
+    boolean isExtSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+        return splitCharacter.isSplitCharacter(start, current, end, cc, ck);
+    }
+    
+/**
+ * Removes all the <VAR>' '</VAR> and <VAR>'-'</VAR>-characters on the right of a <CODE>String</CODE>.
+ * <P>
+ * @param	string		the <CODE>String<CODE> that has to be trimmed.
+ * @return	the trimmed <CODE>String</CODE>
+ */    
+    String trim(String string) {
+        BaseFont ft = font.getFont();
+        if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+            while (string.endsWith("\u0001")) {
+                string = string.substring(0, string.length() - 1);
+            }
+        }
+        else {
+            while (string.endsWith(" ") || string.endsWith("\t")) {
+                string = string.substring(0, string.length() - 1);
+            }
+        }
+        return string;
+    }
+
+    public boolean changeLeading() {
+        return changeLeading;
+    }
+    
+    float getCharWidth(char c) {
+        if (noPrint(c))
+            return 0;
+        return font.width(c);
+    }
+    
+    public static boolean noPrint(char c) {
+        return ((c >= 0x200b && c <= 0x200f) || (c >= 0x202a && c <= 0x202e));
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfColor.java b/LibrarySource/com/lowagie/text/pdf/PdfColor.java
new file mode 100644
index 0000000..5332630
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfColor.java
@@ -0,0 +1,80 @@
+/*
+ * $Id: PdfColor.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import headless.awt.Color;
+/**
+ * A <CODE>PdfColor</CODE> defines a Color (it's a <CODE>PdfArray</CODE> containing 3 values).
+ *
+ * @see		PdfDictionary
+ */
+
+class PdfColor extends PdfArray {
+    
+    // constructors
+    
+/**
+ * Constructs a new <CODE>PdfColor</CODE>.
+ *
+ * @param		red			a value between 0 and 255
+ * @param		green		a value between 0 and 255
+ * @param		blue		a value between 0 and 255
+ */
+    
+    PdfColor(int red, int green, int blue) {
+        super(new PdfNumber((double)(red & 0xFF) / 0xFF));
+        add(new PdfNumber((double)(green & 0xFF) / 0xFF));
+        add(new PdfNumber((double)(blue & 0xFF) / 0xFF));
+    }
+    
+    PdfColor(Color color) {
+        this(color.getRed(), color.getGreen(), color.getBlue());
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfContentByte.java b/LibrarySource/com/lowagie/text/pdf/PdfContentByte.java
new file mode 100644
index 0000000..61689f1
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfContentByte.java
@@ -0,0 +1,2728 @@
+/*
+ * $Id: PdfContentByte.java,v 1.84 2005/03/29 11:07:53 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import headless.awt.Color;
+import java.util.ArrayList;
+import headless.awt.geom.AffineTransform;
+import headless.awt.print.PrinterJob;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Image;
+import com.lowagie.text.Rectangle;
+
+/**
+ * <CODE>PdfContentByte</CODE> is an object containing the user positioned
+ * text and graphic contents of a page. It knows how to apply the proper
+ * font encoding.
+ */
+
+public class PdfContentByte {
+    
+    /**
+     * This class keeps the graphic state of the current page
+     */
+    
+    static class GraphicState {
+        
+        /** This is the font in use */
+        FontDetails fontDetails;
+        
+        /** This is the color in use */
+        ColorDetails colorDetails;
+        
+        /** This is the font size in use */
+        float size;
+        
+        /** The x position of the text line matrix. */
+        protected float xTLM = 0;
+        /** The y position of the text line matrix. */
+        protected float yTLM = 0;
+        
+        /** The current text leading. */
+        protected float leading = 0;
+    }
+    
+    /** The alignement is center */
+    public static final int ALIGN_CENTER = Element.ALIGN_CENTER;
+    
+    /** The alignement is left */
+    public static final int ALIGN_LEFT = Element.ALIGN_LEFT;
+    
+    /** The alignement is right */
+    public static final int ALIGN_RIGHT = Element.ALIGN_RIGHT;
+
+    /** A possible line cap value */
+    public static final int LINE_CAP_BUTT = 0;
+    /** A possible line cap value */
+    public static final int LINE_CAP_ROUND = 1;
+    /** A possible line cap value */
+    public static final int LINE_CAP_PROJECTING_SQUARE = 2;
+
+    /** A possible line join value */
+    public static final int LINE_JOIN_MITER = 0;
+    /** A possible line join value */
+    public static final int LINE_JOIN_ROUND = 1;
+    /** A possible line join value */
+    public static final int LINE_JOIN_BEVEL = 2;
+
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_FILL = 0;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_STROKE = 1;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_FILL_STROKE = 2;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_INVISIBLE = 3;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_FILL_CLIP = 4;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_STROKE_CLIP = 5;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_FILL_STROKE_CLIP = 6;
+    /** A possible text rendering value */
+    public static final int TEXT_RENDER_MODE_CLIP = 7;
+    
+    // membervariables
+    
+    /** This is the actual content */
+    protected ByteBuffer content = new ByteBuffer();
+    
+    /** This is the writer */
+    protected PdfWriter writer;
+    
+    /** This is the PdfDocument */
+    protected PdfDocument pdf;
+    
+    /** This is the GraphicState in use */
+    protected GraphicState state = new GraphicState();
+    
+    /** The list were we save/restore the state */
+    protected ArrayList stateList = new ArrayList();
+    
+    /** The list were we save/restore the layer depth */
+    protected ArrayList layerDepth;
+    
+    /** The separator between commands.
+     */
+    protected int separator = '\n';
+    
+    // constructors
+    
+    /**
+     * Constructs a new <CODE>PdfContentByte</CODE>-object.
+     *
+     * @param wr the writer associated to this content
+     */
+    
+    public PdfContentByte(PdfWriter wr) {
+        if (wr != null) {
+            writer = wr;
+            pdf = writer.getPdfDocument();
+        }
+    }
+    
+    // methods to get the content of this object
+    
+    /**
+     * Returns the <CODE>String</CODE> representation of this <CODE>PdfContentByte</CODE>-object.
+     *
+     * @return		a <CODE>String</CODE>
+     */
+    
+    public String toString() {
+        return content.toString();
+    }
+    
+    /**
+     * Gets the internal buffer.
+     * @return the internal buffer
+     */
+    public ByteBuffer getInternalBuffer() {
+        return content;
+    }
+    
+    /** Returns the PDF representation of this <CODE>PdfContentByte</CODE>-object.
+     *
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @return a <CODE>byte</CODE> array with the representation
+     */
+    
+    public byte[] toPdf(PdfWriter writer) {
+        return content.toByteArray();
+    }
+    
+    // methods to add graphical content
+    
+    /**
+     * Adds the content of another <CODE>PdfContent</CODE>-object to this object.
+     *
+     * @param		other		another <CODE>PdfByteContent</CODE>-object
+     */
+    
+    public void add(PdfContentByte other) {
+        if (other.writer != null && writer != other.writer)
+            throw new RuntimeException("Inconsistent writers. Are you mixing two documents?");
+        content.append(other.content);
+    }
+    
+    /**
+     * Gets the x position of the text line matrix.
+     *
+     * @return the x position of the text line matrix
+     */
+    public float getXTLM() {
+        return state.xTLM;
+    }
+    
+    /**
+     * Gets the y position of the text line matrix.
+     *
+     * @return the y position of the text line matrix
+     */
+    public float getYTLM() {
+        return state.yTLM;
+    }
+    
+    /**
+     * Gets the current text leading.
+     *
+     * @return the current text leading
+     */
+    public float getLeading() {
+        return state.leading;
+    }
+    
+    /**
+     * Changes the <VAR>Flatness</VAR>.
+     * <P>
+     * <VAR>Flatness</VAR> sets the maximum permitted distance in device pixels between the
+     * mathematically correct path and an approximation constructed from straight line segments.<BR>
+     *
+     * @param		flatness		a value
+     */
+    
+    public void setFlatness(float flatness) {
+        if (flatness >= 0 && flatness <= 100) {
+            content.append(flatness).append(" i").append_i(separator);
+        }
+    }
+    
+    /**
+     * Changes the <VAR>Line cap style</VAR>.
+     * <P>
+     * The <VAR>line cap style</VAR> specifies the shape to be used at the end of open subpaths
+     * when they are stroked.<BR>
+     * Allowed values are LINE_CAP_BUTT, LINE_CAP_ROUND and LINE_CAP_PROJECTING_SQUARE.<BR>
+     *
+     * @param		style		a value
+     */
+    
+    public void setLineCap(int style) {
+        if (style >= 0 && style <= 2) {
+            content.append(style).append(" J").append_i(separator);
+        }
+    }
+    
+    /**
+     * Changes the value of the <VAR>line dash pattern</VAR>.
+     * <P>
+     * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+     * It is specified by an <I>array</I> and a <I>phase</I>. The array specifies the length
+     * of the alternating dashes and gaps. The phase specifies the distance into the dash
+     * pattern to start the dash.<BR>
+     *
+     * @param		phase		the value of the phase
+     */
+    
+    public void setLineDash(float phase) {
+        content.append("[] ").append(phase).append(" d").append_i(separator);
+    }
+    
+    /**
+     * Changes the value of the <VAR>line dash pattern</VAR>.
+     * <P>
+     * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+     * It is specified by an <I>array</I> and a <I>phase</I>. The array specifies the length
+     * of the alternating dashes and gaps. The phase specifies the distance into the dash
+     * pattern to start the dash.<BR>
+     *
+     * @param		phase		the value of the phase
+     * @param		unitsOn		the number of units that must be 'on' (equals the number of units that must be 'off').
+     */
+    
+    public void setLineDash(float unitsOn, float phase) {
+        content.append("[").append(unitsOn).append("] ").append(phase).append(" d").append_i(separator);
+    }
+    
+    /**
+     * Changes the value of the <VAR>line dash pattern</VAR>.
+     * <P>
+     * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+     * It is specified by an <I>array</I> and a <I>phase</I>. The array specifies the length
+     * of the alternating dashes and gaps. The phase specifies the distance into the dash
+     * pattern to start the dash.<BR>
+     *
+     * @param		phase		the value of the phase
+     * @param		unitsOn		the number of units that must be 'on'
+     * @param		unitsOff	the number of units that must be 'off'
+     */
+    
+    public void setLineDash(float unitsOn, float unitsOff, float phase) {
+        content.append("[").append(unitsOn).append(' ').append(unitsOff).append("] ").append(phase).append(" d").append_i(separator);
+    }
+    
+    /**
+     * Changes the value of the <VAR>line dash pattern</VAR>.
+     * <P>
+     * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+     * It is specified by an <I>array</I> and a <I>phase</I>. The array specifies the length
+     * of the alternating dashes and gaps. The phase specifies the distance into the dash
+     * pattern to start the dash.<BR>
+     *
+     * @param		array		length of the alternating dashes and gaps
+     * @param		phase		the value of the phase
+     */
+    
+    public final void setLineDash(float[] array, float phase) {
+        content.append("[");
+        for (int i = 0; i < array.length; i++) {
+            content.append(array[i]);
+            if (i < array.length - 1) content.append(' ');
+        }
+        content.append("] ").append(phase).append(" d").append_i(separator);
+    }
+
+    /**
+     * Changes the <VAR>Line join style</VAR>.
+     * <P>
+     * The <VAR>line join style</VAR> specifies the shape to be used at the corners of paths
+     * that are stroked.<BR>
+     * Allowed values are LINE_JOIN_MITER (Miter joins), LINE_JOIN_ROUND (Round joins) and LINE_JOIN_BEVEL (Bevel joins).<BR>
+     *
+     * @param		style		a value
+     */
+    
+    public void setLineJoin(int style) {
+        if (style >= 0 && style <= 2) {
+            content.append(style).append(" j").append_i(separator);
+        }
+    }
+    
+    /**
+     * Changes the <VAR>line width</VAR>.
+     * <P>
+     * The line width specifies the thickness of the line used to stroke a path and is measured
+     * in used space units.<BR>
+     *
+     * @param		w			a width
+     */
+    
+    public void setLineWidth(float w) {
+        content.append(w).append(" w").append_i(separator);
+    }
+    
+    /**
+     * Changes the <VAR>Miter limit</VAR>.
+     * <P>
+     * When two line segments meet at a sharp angle and mitered joins have been specified as the
+     * line join style, it is possible for the miter to extend far beyond the thickness of the line
+     * stroking path. The miter limit imposes a maximum on the ratio of the miter length to the line
+     * witdh. When the limit is exceeded, the join is converted from a miter to a bevel.<BR>
+     *
+     * @param		miterLimit		a miter limit
+     */
+    
+    public void setMiterLimit(float miterLimit) {
+        if (miterLimit > 1) {
+            content.append(miterLimit).append(" M").append_i(separator);
+        }
+    }
+    
+    /**
+     * Modify the current clipping path by intersecting it with the current path, using the
+     * nonzero winding number rule to determine which regions lie inside the clipping
+     * path.
+     */
+    
+    public void clip() {
+        content.append("W").append_i(separator);
+    }
+    
+    /**
+     * Modify the current clipping path by intersecting it with the current path, using the
+     * even-odd rule to determine which regions lie inside the clipping path.
+     */
+    
+    public void eoClip() {
+        content.append("W*").append_i(separator);
+    }
+    
+    /**
+     * Changes the currentgray tint for filling paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceGray</B> (or the <B>DefaultGray</B> color space),
+     * and sets the gray tint to use for filling paths.</P>
+     *
+     * @param	gray	a value between 0 (black) and 1 (white)
+     */
+    
+    public void setGrayFill(float gray) {
+        content.append(gray).append(" g").append_i(separator);
+    }
+    
+    /**
+     * Changes the current gray tint for filling paths to black.
+     */
+    
+    public void resetGrayFill() {
+        content.append("0 g").append_i(separator);
+    }
+    
+    /**
+     * Changes the currentgray tint for stroking paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceGray</B> (or the <B>DefaultGray</B> color space),
+     * and sets the gray tint to use for stroking paths.</P>
+     *
+     * @param	gray	a value between 0 (black) and 1 (white)
+     */
+    
+    public void setGrayStroke(float gray) {
+        content.append(gray).append(" G").append_i(separator);
+    }
+    
+    /**
+     * Changes the current gray tint for stroking paths to black.
+     */
+    
+    public void resetGrayStroke() {
+        content.append("0 G").append_i(separator);
+    }
+    
+    /**
+     * Helper to validate and write the RGB color components
+     * @param	red		the intensity of red. A value between 0 and 1
+     * @param	green	the intensity of green. A value between 0 and 1
+     * @param	blue	the intensity of blue. A value between 0 and 1
+     */
+    private void HelperRGB(float red, float green, float blue) {
+        PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_RGB, null);
+        if (red < 0)
+            red = 0.0f;
+        else if (red > 1.0f)
+            red = 1.0f;
+        if (green < 0)
+            green = 0.0f;
+        else if (green > 1.0f)
+            green = 1.0f;
+        if (blue < 0)
+            blue = 0.0f;
+        else if (blue > 1.0f)
+            blue = 1.0f;
+        content.append(red).append(' ').append(green).append(' ').append(blue);
+    }
+    
+    /**
+     * Changes the current color for filling paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceRGB</B> (or the <B>DefaultRGB</B> color space),
+     * and sets the color to use for filling paths.</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (minimum intensity) and
+     * 1 (maximum intensity).</P>
+     *
+     * @param	red		the intensity of red. A value between 0 and 1
+     * @param	green	the intensity of green. A value between 0 and 1
+     * @param	blue	the intensity of blue. A value between 0 and 1
+     */
+    
+    public void setRGBColorFillF(float red, float green, float blue) {
+        HelperRGB(red, green, blue);
+        content.append(" rg").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for filling paths to black.
+     */
+    
+    public void resetRGBColorFill() {
+        content.append("0 g").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for stroking paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceRGB</B> (or the <B>DefaultRGB</B> color space),
+     * and sets the color to use for stroking paths.</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+     * 1 (maximum intensity).
+     *
+     * @param	red		the intensity of red. A value between 0 and 1
+     * @param	green	the intensity of green. A value between 0 and 1
+     * @param	blue	the intensity of blue. A value between 0 and 1
+     */
+    
+    public void setRGBColorStrokeF(float red, float green, float blue) {
+        HelperRGB(red, green, blue);
+        content.append(" RG").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for stroking paths to black.
+     *
+     */
+    
+    public void resetRGBColorStroke() {
+        content.append("0 G").append_i(separator);
+    }
+    
+    /**
+     * Helper to validate and write the CMYK color components.
+     *
+     * @param	cyan	the intensity of cyan. A value between 0 and 1
+     * @param	magenta	the intensity of magenta. A value between 0 and 1
+     * @param	yellow	the intensity of yellow. A value between 0 and 1
+     * @param	black	the intensity of black. A value between 0 and 1
+     */
+    private void HelperCMYK(float cyan, float magenta, float yellow, float black) {
+        if (cyan < 0)
+            cyan = 0.0f;
+        else if (cyan > 1.0f)
+            cyan = 1.0f;
+        if (magenta < 0)
+            magenta = 0.0f;
+        else if (magenta > 1.0f)
+            magenta = 1.0f;
+        if (yellow < 0)
+            yellow = 0.0f;
+        else if (yellow > 1.0f)
+            yellow = 1.0f;
+        if (black < 0)
+            black = 0.0f;
+        else if (black > 1.0f)
+            black = 1.0f;
+        content.append(cyan).append(' ').append(magenta).append(' ').append(yellow).append(' ').append(black);
+    }
+    
+    /**
+     * Changes the current color for filling paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceCMYK</B> (or the <B>DefaultCMYK</B> color space),
+     * and sets the color to use for filling paths.</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (no ink) and
+     * 1 (maximum ink).</P>
+     *
+     * @param	cyan	the intensity of cyan. A value between 0 and 1
+     * @param	magenta	the intensity of magenta. A value between 0 and 1
+     * @param	yellow	the intensity of yellow. A value between 0 and 1
+     * @param	black	the intensity of black. A value between 0 and 1
+     */
+    
+    public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
+        HelperCMYK(cyan, magenta, yellow, black);
+        content.append(" k").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for filling paths to black.
+     *
+     */
+    
+    public void resetCMYKColorFill() {
+        content.append("0 0 0 1 k").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for stroking paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceCMYK</B> (or the <B>DefaultCMYK</B> color space),
+     * and sets the color to use for stroking paths.</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+     * 1 (maximum intensity).
+     *
+     * @param	cyan	the intensity of cyan. A value between 0 and 1
+     * @param	magenta	the intensity of magenta. A value between 0 and 1
+     * @param	yellow	the intensity of yellow. A value between 0 and 1
+     * @param	black	the intensity of black. A value between 0 and 1
+     */
+    
+    public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
+        HelperCMYK(cyan, magenta, yellow, black);
+        content.append(" K").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for stroking paths to black.
+     *
+     */
+    
+    public void resetCMYKColorStroke() {
+        content.append("0 0 0 1 K").append_i(separator);
+    }
+    
+    /**
+     * Move the current point <I>(x, y)</I>, omitting any connecting line segment.
+     *
+     * @param		x				new x-coordinate
+     * @param		y				new y-coordinate
+     */
+    
+    public void moveTo(float x, float y) {
+        content.append(x).append(' ').append(y).append(" m").append_i(separator);
+    }
+    
+    /**
+     * Appends a straight line segment from the current point <I>(x, y)</I>. The new current
+     * point is <I>(x, y)</I>.
+     *
+     * @param		x				new x-coordinate
+     * @param		y				new y-coordinate
+     */
+    
+    public void lineTo(float x, float y) {
+        content.append(x).append(' ').append(y).append(" l").append_i(separator);
+    }
+    
+    /**
+     * Appends a B�zier curve to the path, starting from the current point.
+     *
+     * @param		x1		x-coordinate of the first control point
+     * @param		y1		y-coordinate of the first control point
+     * @param		x2		x-coordinate of the second control point
+     * @param		y2		y-coordinate of the second control point
+     * @param		x3		x-coordinaat of the ending point (= new current point)
+     * @param		y3		y-coordinaat of the ending point (= new current point)
+     */
+    
+    public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) {
+        content.append(x1).append(' ').append(y1).append(' ').append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" c").append_i(separator);
+    }
+    
+    /**
+     * Appends a B�zier curve to the path, starting from the current point.
+     *
+     * @param		x2		x-coordinate of the second control point
+     * @param		y2		y-coordinate of the second control point
+     * @param		x3		x-coordinaat of the ending point (= new current point)
+     * @param		y3		y-coordinaat of the ending point (= new current point)
+     */
+    
+    public void curveTo(float x2, float y2, float x3, float y3) {
+        content.append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" v").append_i(separator);
+    }
+    
+    /**
+     * Appends a B�zier curve to the path, starting from the current point.
+     *
+     * @param		x1		x-coordinate of the first control point
+     * @param		y1		y-coordinate of the first control point
+     * @param		x3		x-coordinaat of the ending point (= new current point)
+     * @param		y3		y-coordinaat of the ending point (= new current point)
+     */
+    
+    public void curveFromTo(float x1, float y1, float x3, float y3) {
+        content.append(x1).append(' ').append(y1).append(' ').append(x3).append(' ').append(y3).append(" y").append_i(separator);
+    }
+    
+    /** Draws a circle. The endpoint will (x+r, y).
+     *
+     * @param x x center of circle
+     * @param y y center of circle
+     * @param r radius of circle
+     */
+    public void circle(float x, float y, float r) {
+        float b = 0.5523f;
+        moveTo(x + r, y);
+        curveTo(x + r, y + r * b, x + r * b, y + r, x, y + r);
+        curveTo(x - r * b, y + r, x - r, y + r * b, x - r, y);
+        curveTo(x - r, y - r * b, x - r * b, y - r, x, y - r);
+        curveTo(x + r * b, y - r, x + r, y - r * b, x + r, y);
+    }
+    
+    
+    
+    /**
+     * Adds a rectangle to the current path.
+     *
+     * @param		x		x-coordinate of the starting point
+     * @param		y		y-coordinate of the starting point
+     * @param		w		width
+     * @param		h		height
+     */
+    
+    public void rectangle(float x, float y, float w, float h) {
+        content.append(x).append(' ').append(y).append(' ').append(w).append(' ').append(h).append(" re").append_i(separator);
+    }
+    
+
+    // Contribution by Barry Richards and Prabhakar Chaganti
+    /**
+     * Adds a variable width border to the current path.
+     * Only use if {@link com.lowagie.text.Rectangle#isUseVariableBorders() Rectangle.isUseVariableBorders}
+     * = true.
+     * @param		rect		a <CODE>Rectangle</CODE>
+     */
+    public void variableRectangle(Rectangle rect) {
+        float limit = 0f;
+        float startX = rect.left();
+        float startY = rect.bottom();
+        
+        // start at the origin
+        // draw bottom
+        if (rect.getBorderWidthBottom() > limit) {
+            moveTo(startX, startY);
+            if (rect.getBorderColorBottom() == null)
+                resetRGBColorFill();
+            else
+                setColorFill(rect.getBorderColorBottom());
+            // DRAW BOTTOM EDGE.
+            lineTo(startX + rect.width(), startY);
+            // DRAW RIGHT EDGE.
+            lineTo((startX + rect.width()) - rect.getBorderWidthRight(), startY + rect.getBorderWidthBottom());
+            //DRAW TOP EDGE.
+            lineTo((startX + rect.getBorderWidthLeft()), startY + rect.getBorderWidthBottom());
+            lineTo(startX, startY);
+            fill();
+        }
+
+        // Draw left
+        if (rect.getBorderWidthLeft() > limit) {
+            moveTo(startX, startY);
+            if (rect.getBorderColorLeft() == null)
+                resetRGBColorFill();
+            else
+                setColorFill(rect.getBorderColorLeft());
+            // DRAW BOTTOM EDGE.
+            lineTo(startX, startY + rect.height());
+            // DRAW RIGHT EDGE.
+            lineTo(startX + rect.getBorderWidthLeft(), (startY + rect.height()) - rect.getBorderWidthTop());
+            //DRAW TOP EDGE.
+            lineTo(startX + rect.getBorderWidthLeft(), startY + rect.getBorderWidthBottom());
+
+            lineTo(startX, startY);
+            fill();
+        }
+
+
+        startX = startX + rect.width();
+        startY = startY + rect.height();
+
+        // Draw top
+        if (rect.getBorderWidthTop() > limit) {
+            moveTo(startX, startY);
+            if (rect.getBorderColorTop() == null)
+                resetRGBColorFill();
+            else
+                setColorFill(rect.getBorderColorTop());
+            // DRAW LONG EDGE.
+            lineTo(startX - rect.width(), startY);
+            // DRAW LEFT EDGE.
+            lineTo(startX - rect.width() + rect.getBorderWidthLeft(), startY - rect.getBorderWidthTop());
+            //DRAW SHORT EDGE.
+            lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
+
+            lineTo(startX, startY);
+            fill();
+        }
+
+        // Draw Right
+        if (rect.getBorderWidthRight() > limit) {
+            moveTo(startX, startY);
+            if (rect.getBorderColorRight() == null)
+                resetRGBColorFill();
+            else
+                setColorFill(rect.getBorderColorRight());
+            // DRAW LONG EDGE.
+            lineTo(startX, startY - rect.height());
+            // DRAW LEFT EDGE.
+            lineTo(startX - rect.getBorderWidthRight(), startY - rect.height() + rect.getBorderWidthBottom());
+            //DRAW SHORT EDGE.
+            lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
+
+            lineTo(startX, startY);
+            fill();
+        }
+        resetRGBColorFill();
+    }
+
+    /**
+     * Adds a border (complete or partially) to the current path..
+     *
+     * @param		rectangle		a <CODE>Rectangle</CODE>
+     */
+    
+    public void rectangle(Rectangle rectangle) {
+        // the coordinates of the border are retrieved
+        float x1 = rectangle.left();
+        float y1 = rectangle.bottom();
+        float x2 = rectangle.right();
+        float y2 = rectangle.top();
+
+        // the backgroundcolor is set
+        Color background = rectangle.backgroundColor();
+        if (background != null) {
+            setColorFill(background);
+            rectangle(x1, y1, x2 - x1, y2 - y1);
+            fill();
+            resetRGBColorFill();
+        }
+        else if (rectangle.grayFill() > 0.0) {
+            setGrayFill((float)rectangle.grayFill());
+            rectangle(x1, y1, x2 - x1, y2 - y1);
+            fill();
+            resetGrayFill();
+        }
+
+
+        // if the element hasn't got any borders, nothing is added
+        if (! rectangle.hasBorders()) {
+            return;
+        }
+
+        // if any of the individual border colors are set
+        // we draw the borders all around using the
+        // different colors
+        if (rectangle.isUseVariableBorders()) {
+            variableRectangle(rectangle);
+        }
+        else {
+            // the width is set to the width of the element
+            if (rectangle.borderWidth() != Rectangle.UNDEFINED) {
+                setLineWidth((float)rectangle.borderWidth());
+            }
+
+            // the color is set to the color of the element
+            Color color = rectangle.borderColor();
+            if (color != null) {
+                setColorStroke(color);
+            }
+
+            // if the box is a rectangle, it is added as a rectangle
+            if (rectangle.hasBorder(Rectangle.BOX)) {
+               rectangle(x1, y1, x2 - x1, y2 - y1);
+            }
+            // if the border isn't a rectangle, the different sides are added apart
+            else {
+                if (rectangle.hasBorder(Rectangle.RIGHT)) {
+                    moveTo(x2, y1);
+                    lineTo(x2, y2);
+                }
+                if (rectangle.hasBorder(Rectangle.LEFT)) {
+                    moveTo(x1, y1);
+                    lineTo(x1, y2);
+                }
+                if (rectangle.hasBorder(Rectangle.BOTTOM)) {
+                    moveTo(x1, y1);
+                    lineTo(x2, y1);
+                }
+                if (rectangle.hasBorder(Rectangle.TOP)) {
+                    moveTo(x1, y2);
+                    lineTo(x2, y2);
+                }
+            }
+
+            stroke();
+
+            if (color != null) {
+                resetRGBColorStroke();
+            }
+        }
+    }
+
+    /**
+     * Closes the current subpath by appending a straight line segment from the current point
+     * to the starting point of the subpath.
+     */
+    
+    public void closePath() {
+        content.append("h").append_i(separator);
+    }
+    
+    /**
+     * Ends the path without filling or stroking it.
+     */
+    
+    public void newPath() {
+        content.append("n").append_i(separator);
+    }
+    
+    /**
+     * Strokes the path.
+     */
+    
+    public void stroke() {
+        content.append("S").append_i(separator);
+    }
+    
+    /**
+     * Closes the path and strokes it.
+     */
+    
+    public void closePathStroke() {
+        content.append("s").append_i(separator);
+    }
+    
+    /**
+     * Fills the path, using the non-zero winding number rule to determine the region to fill.
+     */
+    
+    public void fill() {
+        content.append("f").append_i(separator);
+    }
+    
+    /**
+     * Fills the path, using the even-odd rule to determine the region to fill.
+     */
+    
+    public void eoFill() {
+        content.append("f*").append_i(separator);
+    }
+    
+    /**
+     * Fills the path using the non-zero winding number rule to determine the region to fill and strokes it.
+     */
+    
+    public void fillStroke() {
+        content.append("B").append_i(separator);
+    }
+    
+    /**
+     * Closes the path, fills it using the non-zero winding number rule to determine the region to fill and strokes it.
+     */
+    
+    public void closePathFillStroke() {
+        content.append("b").append_i(separator);
+    }
+    
+    /**
+     * Fills the path, using the even-odd rule to determine the region to fill and strokes it.
+     */
+    
+    public void eoFillStroke() {
+        content.append("B*").append_i(separator);
+    }
+    
+    /**
+     * Closes the path, fills it using the even-odd rule to determine the region to fill and strokes it.
+     */
+    
+    public void closePathEoFillStroke() {
+        content.append("b*").append_i(separator);
+    }
+    
+    /**
+     * Adds an <CODE>Image</CODE> to the page. The <CODE>Image</CODE> must have
+     * absolute positioning.
+     * @param image the <CODE>Image</CODE> object
+     * @throws DocumentException if the <CODE>Image</CODE> does not have absolute positioning
+     */
+    public void addImage(Image image) throws DocumentException {
+        if (!image.hasAbsolutePosition())
+            throw new DocumentException("The image must have absolute positioning.");
+        float matrix[] = image.matrix();
+        matrix[Image.CX] = image.absoluteX() - matrix[Image.CX];
+        matrix[Image.CY] = image.absoluteY() - matrix[Image.CY];
+        addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+    }
+    
+    /**
+     * Adds an <CODE>Image</CODE> to the page. The positioning of the <CODE>Image</CODE>
+     * is done with the transformation matrix. To position an <CODE>image</CODE> at (x,y)
+     * use addImage(image, image_width, 0, 0, image_height, x, y).
+     * @param image the <CODE>Image</CODE> object
+     * @param a an element of the transformation matrix
+     * @param b an element of the transformation matrix
+     * @param c an element of the transformation matrix
+     * @param d an element of the transformation matrix
+     * @param e an element of the transformation matrix
+     * @param f an element of the transformation matrix
+     * @throws DocumentException on error
+     */
+    public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+        try {
+            
+            if (image.isImgTemplate()) {
+                writer.addDirectImageSimple(image);
+                PdfTemplate template = image.templateData();
+                float w = template.getWidth();
+                float h = template.getHeight();
+                if (image.getLayer() != null)
+                    beginLayer(image.getLayer());
+                addTemplate(template, a / w, b / w, c / h, d / h, e, f);
+                if (image.getLayer() != null)
+                    endLayer();
+            }
+            else {
+                PdfName name;
+                PageResources prs = getPageResources();
+                Image maskImage = image.getImageMask();
+                if (maskImage != null) {
+                    name = writer.addDirectImageSimple(maskImage);
+                    prs.addXObject(name, writer.getImageReference(name));
+                }
+                name = writer.addDirectImageSimple(image);
+                name = prs.addXObject(name, writer.getImageReference(name));
+                content.append("q ");
+                content.append(a).append(' ');
+                content.append(b).append(' ');
+                content.append(c).append(' ');
+                content.append(d).append(' ');
+                content.append(e).append(' ');
+                content.append(f).append(" cm ");
+                content.append(name.getBytes()).append(" Do Q").append_i(separator);
+            }
+        }
+        catch (Exception ee) {
+            throw new DocumentException(ee);
+        }
+    }
+    
+    /**
+     * Makes this <CODE>PdfContentByte</CODE> empty.
+     */
+    public void reset() {
+        content.reset();
+        stateList.clear();
+        state = new GraphicState();
+    }
+    
+    /**
+     * Starts the writing of text.
+     */
+    public void beginText() {
+        state.xTLM = 0;
+        state.yTLM = 0;
+        content.append("BT").append_i(separator);
+    }
+    
+    /**
+     * Ends the writing of text and makes the current font invalid.
+     */
+    public void endText() {
+        content.append("ET").append_i(separator);
+    }
+    
+    /**
+     * Saves the graphic state. <CODE>saveState</CODE> and
+     * <CODE>restoreState</CODE> must be balanced.
+     */
+    public void saveState() {
+        content.append("q").append_i(separator);
+        stateList.add(state);
+    }
+    
+    /**
+     * Restores the graphic state. <CODE>saveState</CODE> and
+     * <CODE>restoreState</CODE> must be balanced.
+     */
+    public void restoreState() {
+        content.append("Q").append_i(separator);
+        int idx = stateList.size() - 1;
+        if (idx < 0)
+            throw new RuntimeException("Unbalanced save/restore state operators.");
+        state = (GraphicState)stateList.get(idx);
+        stateList.remove(idx);
+    }
+    
+    /**
+     * Sets the character spacing parameter.
+     *
+     * @param		charSpace			a parameter
+     */
+    public void setCharacterSpacing(float charSpace) {
+        content.append(charSpace).append(" Tc").append_i(separator);
+    }
+    
+    /**
+     * Sets the word spacing parameter.
+     *
+     * @param		wordSpace			a parameter
+     */
+    public void setWordSpacing(float wordSpace) {
+        content.append(wordSpace).append(" Tw").append_i(separator);
+    }
+    
+    /**
+     * Sets the horizontal scaling parameter.
+     *
+     * @param		scale				a parameter
+     */
+    public void setHorizontalScaling(float scale) {
+        content.append(scale).append(" Tz").append_i(separator);
+    }
+    
+    /**
+     * Sets the text leading parameter.
+     * <P>
+     * The leading parameter is measured in text space units. It specifies the vertical distance
+     * between the baselines of adjacent lines of text.</P>
+     *
+     * @param		leading			the new leading
+     */
+    public void setLeading(float leading) {
+        state.leading = leading;
+        content.append(leading).append(" TL").append_i(separator);
+    }
+    
+    /**
+     * Set the font and the size for the subsequent text writing.
+     *
+     * @param bf the font
+     * @param size the font size in points
+     */
+    public void setFontAndSize(BaseFont bf, float size) {
+        checkWriter();
+        state.size = size;
+        state.fontDetails = writer.addSimple(bf);
+        PageResources prs = getPageResources();
+        PdfName name = state.fontDetails.getFontName();
+        name = prs.addFont(name, state.fontDetails.getIndirectReference());
+        content.append(name.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
+    }
+    
+    /**
+     * Sets the text rendering parameter.
+     *
+     * @param		rendering				a parameter
+     */
+    public void setTextRenderingMode(int rendering) {
+        content.append(rendering).append(" Tr").append_i(separator);
+    }
+    
+    /**
+     * Sets the text rise parameter.
+     * <P>
+     * This allows to write text in subscript or superscript mode.</P>
+     *
+     * @param		rise				a parameter
+     */
+    public void setTextRise(float rise) {
+        content.append(rise).append(" Ts").append_i(separator);
+    }
+    
+    /**
+     * A helper to insert into the content stream the <CODE>text</CODE>
+     * converted to bytes according to the font's encoding.
+     *
+     * @param text the text to write
+     */
+    private void showText2(String text) {
+        if (state.fontDetails == null)
+            throw new NullPointerException("Font and size must be set before writing any text");
+        byte b[] = state.fontDetails.convertToBytes(text);
+        escapeString(b, content);
+    }
+    
+    /**
+     * Shows the <CODE>text</CODE>.
+     *
+     * @param text the text to write
+     */
+    public void showText(String text) {
+        showText2(text);
+        content.append("Tj").append_i(separator);
+    }
+    
+    /**
+     * Constructs a kern array for a text in a certain font
+     * @param text the text
+     * @param font the font
+     * @return a PdfTextArray
+     */
+    public static PdfTextArray getKernArray(String text, BaseFont font) {
+        PdfTextArray pa = new PdfTextArray();
+        StringBuffer acc = new StringBuffer();
+        int len = text.length() - 1;
+        char c[] = text.toCharArray();
+        if (len >= 0)
+            acc.append(c, 0, 1);
+        for (int k = 0; k < len; ++k) {
+            char c2 = c[k + 1];
+            int kern = font.getKerning(c[k], c2);
+            if (kern == 0) {
+                acc.append(c2);
+            }
+            else {
+                pa.add(acc.toString());
+                acc.setLength(0);
+                acc.append(c, k + 1, 1);
+                pa.add(-kern);
+            }
+        }
+        pa.add(acc.toString());
+        return pa;
+    }
+    
+    /**
+     * Shows the <CODE>text</CODE> kerned.
+     *
+     * @param text the text to write
+     */
+    public void showTextKerned(String text) {
+        if (state.fontDetails == null)
+            throw new NullPointerException("Font and size must be set before writing any text");
+        BaseFont bf = state.fontDetails.getBaseFont();
+        if (bf.hasKernPairs())
+            showText(getKernArray(text, bf));
+        else
+            showText(text);
+    }
+    
+    /**
+     * Moves to the next line and shows <CODE>text</CODE>.
+     *
+     * @param text the text to write
+     */
+    public void newlineShowText(String text) {
+        state.yTLM -= state.leading;
+        showText2(text);
+        content.append("'").append_i(separator);
+    }
+    
+    /**
+     * Moves to the next line and shows text string, using the given values of the character and word spacing parameters.
+     *
+     * @param		wordSpacing		a parameter
+     * @param		charSpacing		a parameter
+     * @param text the text to write
+     */
+    public void newlineShowText(float wordSpacing, float charSpacing, String text) {
+        state.yTLM -= state.leading;
+        content.append(wordSpacing).append(' ').append(charSpacing);
+        showText2(text);
+        content.append("\"").append_i(separator);
+    }
+    
+    /**
+     * Changes the text matrix.
+     * <P>
+     * Remark: this operation also initializes the current point position.</P>
+     *
+     * @param		a			operand 1,1 in the matrix
+     * @param		b			operand 1,2 in the matrix
+     * @param		c			operand 2,1 in the matrix
+     * @param		d			operand 2,2 in the matrix
+     * @param		x			operand 3,1 in the matrix
+     * @param		y			operand 3,2 in the matrix
+     */
+    public void setTextMatrix(float a, float b, float c, float d, float x, float y) {
+        state.xTLM = x;
+        state.yTLM = y;
+        content.append(a).append(' ').append(b).append_i(' ')
+        .append(c).append_i(' ').append(d).append_i(' ')
+        .append(x).append_i(' ').append(y).append(" Tm").append_i(separator);
+    }
+    
+    /**
+     * Changes the text matrix. The first four parameters are {1,0,0,1}.
+     * <P>
+     * Remark: this operation also initializes the current point position.</P>
+     *
+     * @param		x			operand 3,1 in the matrix
+     * @param		y			operand 3,2 in the matrix
+     */
+    public void setTextMatrix(float x, float y) {
+        setTextMatrix(1, 0, 0, 1, x, y);
+    }
+    
+    /**
+     * Moves to the start of the next line, offset from the start of the current line.
+     *
+     * @param		x			x-coordinate of the new current point
+     * @param		y			y-coordinate of the new current point
+     */
+    public void moveText(float x, float y) {
+        state.xTLM += x;
+        state.yTLM += y;
+        content.append(x).append(' ').append(y).append(" Td").append_i(separator);
+    }
+    
+    /**
+     * Moves to the start of the next line, offset from the start of the current line.
+     * <P>
+     * As a side effect, this sets the leading parameter in the text state.</P>
+     *
+     * @param		x			offset of the new current point
+     * @param		y			y-coordinate of the new current point
+     */
+    public void moveTextWithLeading(float x, float y) {
+        state.xTLM += x;
+        state.yTLM += y;
+        state.leading = -y;
+        content.append(x).append(' ').append(y).append(" TD").append_i(separator);
+    }
+    
+    /**
+     * Moves to the start of the next line.
+     */
+    public void newlineText() {
+        state.yTLM -= state.leading;
+        content.append("T*").append_i(separator);
+    }
+    
+    /**
+     * Gets the size of this content.
+     *
+     * @return the size of the content
+     */
+    int size() {
+        return content.size();
+    }
+    
+    /**
+     * Escapes a <CODE>byte</CODE> array according to the PDF conventions.
+     *
+     * @param b the <CODE>byte</CODE> array to escape
+     * @return an escaped <CODE>byte</CODE> array
+     */
+    static byte[] escapeString(byte b[]) {
+        ByteBuffer content = new ByteBuffer();
+        escapeString(b, content);
+        return content.toByteArray();
+    }
+    
+    /**
+     * Escapes a <CODE>byte</CODE> array according to the PDF conventions.
+     *
+     * @param b the <CODE>byte</CODE> array to escape
+     * @param content the content
+     */
+    static void escapeString(byte b[], ByteBuffer content) {
+        content.append_i('(');
+        for (int k = 0; k < b.length; ++k) {
+            byte c = b[k];
+            switch ((int)c) {
+                case '\r':
+                    content.append("\\r");
+                    break;
+                case '\n':
+                    content.append("\\n");
+                    break;
+                case '\t':
+                    content.append("\\t");
+                    break;
+                case '\b':
+                    content.append("\\b");
+                    break;
+                case '\f':
+                    content.append("\\f");
+                    break;
+                case '(':
+                case ')':
+                case '\\':
+                    content.append_i('\\').append_i(c);
+                    break;
+                default:
+                    content.append_i(c);
+            }
+        }
+        content.append(")");
+    }
+    
+    /**
+     * Adds an outline to the document.
+     *
+     * @param outline the outline
+     * @deprecated not needed anymore. The outlines are extracted
+     * from the root outline
+     */
+    public void addOutline(PdfOutline outline) {
+        // for compatibility
+    }
+    /**
+     * Adds a named outline to the document.
+     *
+     * @param outline the outline
+     * @param name the name for the local destination
+     */
+    public void addOutline(PdfOutline outline, String name) {
+        checkWriter();
+        pdf.addOutline(outline, name);
+    }
+    /**
+     * Gets the root outline.
+     *
+     * @return the root outline
+     */
+    public PdfOutline getRootOutline() {
+        checkWriter();
+        return pdf.getRootOutline();
+    }
+    
+    /**
+     * Shows text right, left or center aligned with rotation.
+     * @param alignment the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
+     * @param text the text to show
+     * @param x the x pivot position
+     * @param y the y pivot position
+     * @param rotation the rotation to be applied in degrees counterclockwise
+     */
+    public void showTextAligned(int alignment, String text, float x, float y, float rotation) {
+        if (state.fontDetails == null)
+            throw new NullPointerException("Font and size must be set before writing any text");
+        BaseFont bf = state.fontDetails.getBaseFont();
+        if (rotation == 0) {
+            switch (alignment) {
+                case ALIGN_CENTER:
+                    x -= bf.getWidthPoint(text, state.size) / 2;
+                    break;
+                case ALIGN_RIGHT:
+                    x -= bf.getWidthPoint(text, state.size);
+                    break;
+            }
+            setTextMatrix(x, y);
+            showText(text);
+        }
+        else {
+            double alpha = rotation * Math.PI / 180.0;
+            float cos = (float)Math.cos(alpha);
+            float sin = (float)Math.sin(alpha);
+            float len;
+            switch (alignment) {
+                case ALIGN_CENTER:
+                    len = bf.getWidthPoint(text, state.size) / 2;
+                    x -=  len * cos;
+                    y -=  len * sin;
+                    break;
+                case ALIGN_RIGHT:
+                    len = bf.getWidthPoint(text, state.size);
+                    x -=  len * cos;
+                    y -=  len * sin;
+                    break;
+            }
+            setTextMatrix(cos, sin, -sin, cos, x, y);
+            showText(text);
+            setTextMatrix(0f, 0f);
+        }
+    }
+    
+    /**
+     * Shows text kerned right, left or center aligned with rotation.
+     * @param alignement the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
+     * @param text the text to show
+     * @param x the x pivot position
+     * @param y the y pivot position
+     * @param rotation the rotation to be applied in degrees counterclockwise
+     */
+    public void showTextAlignedKerned(int alignement, String text, float x, float y, float rotation) {
+        if (state.fontDetails == null)
+            throw new NullPointerException("Font and size must be set before writing any text");
+        BaseFont bf = state.fontDetails.getBaseFont();
+        if (rotation == 0) {
+            switch (alignement) {
+                case ALIGN_CENTER:
+                    x -= bf.getWidthPointKerned(text, state.size) / 2;
+                    break;
+                case ALIGN_RIGHT:
+                    x -= bf.getWidthPointKerned(text, state.size);
+                    break;
+            }
+            setTextMatrix(x, y);
+            showTextKerned(text);
+        }
+        else {
+            double alpha = rotation * Math.PI / 180.0;
+            float cos = (float)Math.cos(alpha);
+            float sin = (float)Math.sin(alpha);
+            float len;
+            switch (alignement) {
+                case ALIGN_CENTER:
+                    len = bf.getWidthPointKerned(text, state.size) / 2;
+                    x -=  len * cos;
+                    y -=  len * sin;
+                    break;
+                case ALIGN_RIGHT:
+                    len = bf.getWidthPointKerned(text, state.size);
+                    x -=  len * cos;
+                    y -=  len * sin;
+                    break;
+            }
+            setTextMatrix(cos, sin, -sin, cos, x, y);
+            showTextKerned(text);
+            setTextMatrix(0f, 0f);
+        }
+    }
+    
+    /**
+     * Concatenate a matrix to the current transformation matrix.
+     * @param a an element of the transformation matrix
+     * @param b an element of the transformation matrix
+     * @param c an element of the transformation matrix
+     * @param d an element of the transformation matrix
+     * @param e an element of the transformation matrix
+     * @param f an element of the transformation matrix
+     **/
+    public void concatCTM(float a, float b, float c, float d, float e, float f) {
+        content.append(a).append(' ').append(b).append(' ').append(c).append(' ');
+        content.append(d).append(' ').append(e).append(' ').append(f).append(" cm").append_i(separator);
+    }
+    
+    /**
+     * Generates an array of bezier curves to draw an arc.
+     * <P>
+     * (x1, y1) and (x2, y2) are the corners of the enclosing rectangle.
+     * Angles, measured in degrees, start with 0 to the right (the positive X
+     * axis) and increase counter-clockwise.  The arc extends from startAng
+     * to startAng+extent.  I.e. startAng=0 and extent=180 yields an openside-down
+     * semi-circle.
+     * <P>
+     * The resulting coordinates are of the form float[]{x1,y1,x2,y2,x3,y3, x4,y4}
+     * such that the curve goes from (x1, y1) to (x4, y4) with (x2, y2) and
+     * (x3, y3) as their respective Bezier control points.
+     * <P>
+     * Note: this code was taken from ReportLab (www.reportlab.com), an excelent
+     * PDF generator for Python.
+     *
+     * @param x1 a corner of the enclosing rectangle
+     * @param y1 a corner of the enclosing rectangle
+     * @param x2 a corner of the enclosing rectangle
+     * @param y2 a corner of the enclosing rectangle
+     * @param startAng starting angle in degrees
+     * @param extent angle extent in degrees
+     * @return a list of float[] with the bezier curves
+     */
+    public static ArrayList bezierArc(float x1, float y1, float x2, float y2, float startAng, float extent) {
+        float tmp;
+        if (x1 > x2) {
+            tmp = x1;
+            x1 = x2;
+            x2 = tmp;
+        }
+        if (y2 > y1) {
+            tmp = y1;
+            y1 = y2;
+            y2 = tmp;
+        }
+        
+        float fragAngle;
+        int Nfrag;
+        if (Math.abs(extent) <= 90f) {
+            fragAngle = extent;
+            Nfrag = 1;
+        }
+        else {
+            Nfrag = (int)(Math.ceil(Math.abs(extent)/90f));
+            fragAngle = extent / Nfrag;
+        }
+        float x_cen = (x1+x2)/2f;
+        float y_cen = (y1+y2)/2f;
+        float rx = (x2-x1)/2f;
+        float ry = (y2-y1)/2f;
+        float halfAng = (float)(fragAngle * Math.PI / 360.);
+        float kappa = (float)(Math.abs(4. / 3. * (1. - Math.cos(halfAng)) / Math.sin(halfAng)));
+        ArrayList pointList = new ArrayList();
+        for (int i = 0; i < Nfrag; ++i) {
+            float theta0 = (float)((startAng + i*fragAngle) * Math.PI / 180.);
+            float theta1 = (float)((startAng + (i+1)*fragAngle) * Math.PI / 180.);
+            float cos0 = (float)Math.cos(theta0);
+            float cos1 = (float)Math.cos(theta1);
+            float sin0 = (float)Math.sin(theta0);
+            float sin1 = (float)Math.sin(theta1);
+            if (fragAngle > 0f) {
+                pointList.add(new float[]{x_cen + rx * cos0,
+                y_cen - ry * sin0,
+                x_cen + rx * (cos0 - kappa * sin0),
+                y_cen - ry * (sin0 + kappa * cos0),
+                x_cen + rx * (cos1 + kappa * sin1),
+                y_cen - ry * (sin1 - kappa * cos1),
+                x_cen + rx * cos1,
+                y_cen - ry * sin1});
+            }
+            else {
+                pointList.add(new float[]{x_cen + rx * cos0,
+                y_cen - ry * sin0,
+                x_cen + rx * (cos0 + kappa * sin0),
+                y_cen - ry * (sin0 - kappa * cos0),
+                x_cen + rx * (cos1 - kappa * sin1),
+                y_cen - ry * (sin1 + kappa * cos1),
+                x_cen + rx * cos1,
+                y_cen - ry * sin1});
+            }
+        }
+        return pointList;
+    }
+    
+    /**
+     * Draws a partial ellipse inscribed within the rectangle x1,y1,x2,y2,
+     * starting at startAng degrees and covering extent degrees. Angles
+     * start with 0 to the right (+x) and increase counter-clockwise.
+     *
+     * @param x1 a corner of the enclosing rectangle
+     * @param y1 a corner of the enclosing rectangle
+     * @param x2 a corner of the enclosing rectangle
+     * @param y2 a corner of the enclosing rectangle
+     * @param startAng starting angle in degrees
+     * @param extent angle extent in degrees
+     */
+    public void arc(float x1, float y1, float x2, float y2, float startAng, float extent) {
+        ArrayList ar = bezierArc(x1, y1, x2, y2, startAng, extent);
+        if (ar.size() == 0)
+            return;
+        float pt[] = (float [])ar.get(0);
+        moveTo(pt[0], pt[1]);
+        for (int k = 0; k < ar.size(); ++k) {
+            pt = (float [])ar.get(k);
+            curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]);
+        }
+    }
+    
+    /**
+     * Draws an ellipse inscribed within the rectangle x1,y1,x2,y2.
+     *
+     * @param x1 a corner of the enclosing rectangle
+     * @param y1 a corner of the enclosing rectangle
+     * @param x2 a corner of the enclosing rectangle
+     * @param y2 a corner of the enclosing rectangle
+     */
+    public void ellipse(float x1, float y1, float x2, float y2) {
+        arc(x1, y1, x2, y2, 0f, 360f);
+    }
+    
+    /**
+     * Create a new colored tiling pattern.
+     *
+     * @param width the width of the pattern
+     * @param height the height of the pattern
+     * @param xstep the desired horizontal spacing between pattern cells.
+     * May be either positive or negative, but not zero.
+     * @param ystep the desired vertical spacing between pattern cells.
+     * May be either positive or negative, but not zero.
+     * @return the <CODE>PdfPatternPainter</CODE> where the pattern will be created
+     */
+    public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep) {
+        checkWriter();
+        if ( xstep == 0.0f || ystep == 0.0f )
+            throw new RuntimeException("XStep or YStep can not be ZERO.");
+        PdfPatternPainter painter = new PdfPatternPainter(writer);
+        painter.setWidth(width);
+        painter.setHeight(height);
+        painter.setXStep(xstep);
+        painter.setYStep(ystep);
+        writer.addSimplePattern(painter);
+        return painter;
+    }
+    
+    /**
+     * Create a new colored tiling pattern. Variables xstep and ystep are set to the same values
+     * of width and height.
+     * @param width the width of the pattern
+     * @param height the height of the pattern
+     * @return the <CODE>PdfPatternPainter</CODE> where the pattern will be created
+     */
+    public PdfPatternPainter createPattern(float width, float height) {
+        return createPattern(width, height, width, height);
+    }
+    
+    /**
+     * Create a new uncolored tiling pattern.
+     *
+     * @param width the width of the pattern
+     * @param height the height of the pattern
+     * @param xstep the desired horizontal spacing between pattern cells.
+     * May be either positive or negative, but not zero.
+     * @param ystep the desired vertical spacing between pattern cells.
+     * May be either positive or negative, but not zero.
+     * @param color the default color. Can be <CODE>null</CODE>
+     * @return the <CODE>PdfPatternPainter</CODE> where the pattern will be created
+     */
+    public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep, Color color) {
+        checkWriter();
+        if ( xstep == 0.0f || ystep == 0.0f )
+            throw new RuntimeException("XStep or YStep can not be ZERO.");
+        PdfPatternPainter painter = new PdfPatternPainter(writer, color);
+        painter.setWidth(width);
+        painter.setHeight(height);
+        painter.setXStep(xstep);
+        painter.setYStep(ystep);
+        writer.addSimplePattern(painter);
+        return painter;
+    }
+    
+    /**
+     * Create a new uncolored tiling pattern.
+     * Variables xstep and ystep are set to the same values
+     * of width and height.
+     * @param width the width of the pattern
+     * @param height the height of the pattern
+     * @param color the default color. Can be <CODE>null</CODE>
+     * @return the <CODE>PdfPatternPainter</CODE> where the pattern will be created
+     */
+    public PdfPatternPainter createPattern(float width, float height, Color color) {
+        return createPattern(width, height, width, height, color);
+    }
+    
+    /**
+     * Creates a new template.
+     * <P>
+     * Creates a new template that is nothing more than a form XObject. This template can be included
+     * in this <CODE>PdfContentByte</CODE> or in another template. Templates are only written
+     * to the output when the document is closed permitting things like showing text in the first page
+     * that is only defined in the last page.
+     *
+     * @param width the bounding box width
+     * @param height the bounding box height
+     * @return the templated created
+     */
+    public PdfTemplate createTemplate(float width, float height) {
+        return createTemplate(width, height, null);
+    }
+    
+    PdfTemplate createTemplate(float width, float height, PdfName forcedName) {
+        checkWriter();
+        PdfTemplate template = new PdfTemplate(writer);
+        template.setWidth(width);
+        template.setHeight(height);
+        writer.addDirectTemplateSimple(template, forcedName);
+        return template;
+    }
+    
+    /**
+     * Creates a new appearance to be used with form fields.
+     *
+     * @param width the bounding box width
+     * @param height the bounding box height
+     * @return the appearance created
+     */
+    public PdfAppearance createAppearance(float width, float height) {
+        return createAppearance(width, height, null);
+    }
+    
+    PdfAppearance createAppearance(float width, float height, PdfName forcedName) {
+        checkWriter();
+        PdfAppearance template = new PdfAppearance(writer);
+        template.setWidth(width);
+        template.setHeight(height);
+        writer.addDirectTemplateSimple(template, forcedName);
+        return template;
+    }
+    
+    /**
+     * Adds a PostScript XObject to this content.
+     *
+     * @param psobject the object
+     */
+    public void addPSXObject(PdfPSXObject psobject) {
+        checkWriter();
+        PdfName name = writer.addDirectTemplateSimple(psobject, null);
+        PageResources prs = getPageResources();
+        name = prs.addXObject(name, psobject.getIndirectReference());
+        content.append(name.getBytes()).append(" Do").append_i(separator);
+    }
+    
+    /**
+     * Adds a template to this content.
+     *
+     * @param template the template
+     * @param a an element of the transformation matrix
+     * @param b an element of the transformation matrix
+     * @param c an element of the transformation matrix
+     * @param d an element of the transformation matrix
+     * @param e an element of the transformation matrix
+     * @param f an element of the transformation matrix
+     */
+    public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
+        checkWriter();
+        checkNoPattern(template);
+        PdfName name = writer.addDirectTemplateSimple(template, null);
+        PageResources prs = getPageResources();
+        name = prs.addXObject(name, template.getIndirectReference());
+        content.append("q ");
+        content.append(a).append(' ');
+        content.append(b).append(' ');
+        content.append(c).append(' ');
+        content.append(d).append(' ');
+        content.append(e).append(' ');
+        content.append(f).append(" cm ");
+        content.append(name.getBytes()).append(" Do Q").append_i(separator);
+    }
+    
+    /**
+     * Adds a template to this content.
+     *
+     * @param template the template
+     * @param x the x location of this template
+     * @param y the y location of this template
+     */
+    public void addTemplate(PdfTemplate template, float x, float y) {
+        addTemplate(template, 1, 0, 0, 1, x, y);
+    }
+    
+    /**
+     * Changes the current color for filling paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceCMYK</B> (or the <B>DefaultCMYK</B> color space),
+     * and sets the color to use for filling paths.</P>
+     * <P>
+     * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 8.5.2.1 (page 331).</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (no ink) and
+     * 1 (maximum ink). This method however accepts only integers between 0x00 and 0xFF.</P>
+     *
+     * @param cyan the intensity of cyan
+     * @param magenta the intensity of magenta
+     * @param yellow the intensity of yellow
+     * @param black the intensity of black
+     */
+    
+    public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
+        content.append((float)(cyan & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(magenta & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(yellow & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(black & 0xFF) / 0xFF);
+        content.append(" k").append_i(separator);
+    }
+    /**
+     * Changes the current color for stroking paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceCMYK</B> (or the <B>DefaultCMYK</B> color space),
+     * and sets the color to use for stroking paths.</P>
+     * <P>
+     * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 8.5.2.1 (page 331).</P>
+     * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+     * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
+     *
+     * @param cyan the intensity of red
+     * @param magenta the intensity of green
+     * @param yellow the intensity of blue
+     * @param black the intensity of black
+     */
+    
+    public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
+        content.append((float)(cyan & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(magenta & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(yellow & 0xFF) / 0xFF);
+        content.append(' ');
+        content.append((float)(black & 0xFF) / 0xFF);
+        content.append(" K").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for filling paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceRGB</B> (or the <B>DefaultRGB</B> color space),
+     * and sets the color to use for filling paths.</P>
+     * <P>
+     * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 8.5.2.1 (page 331).</P>
+     * <P>
+     * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+     * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.</P>
+     *
+     * @param red the intensity of red
+     * @param green the intensity of green
+     * @param blue the intensity of blue
+     */
+    
+    public void setRGBColorFill(int red, int green, int blue) {
+        HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
+        content.append(" rg").append_i(separator);
+    }
+    
+    /**
+     * Changes the current color for stroking paths (device dependent colors!).
+     * <P>
+     * Sets the color space to <B>DeviceRGB</B> (or the <B>DefaultRGB</B> color space),
+     * and sets the color to use for stroking paths.</P>
+     * <P>
+     * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 8.5.2.1 (page 331).</P>
+     * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+     * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
+     *
+     * @param red the intensity of red
+     * @param green the intensity of green
+     * @param blue the intensity of blue
+     */
+    
+    public void setRGBColorStroke(int red, int green, int blue) {
+        HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
+        content.append(" RG").append_i(separator);
+    }
+    
+    /** Sets the stroke color. <CODE>color</CODE> can be an
+     * <CODE>ExtendedColor</CODE>.
+     * @param color the color
+     */
+    public void setColorStroke(Color color) {
+        PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+        int type = ExtendedColor.getType(color);
+        switch (type) {
+            case ExtendedColor.TYPE_GRAY: {
+                setGrayStroke(((GrayColor)color).getGray());
+                break;
+            }
+            case ExtendedColor.TYPE_CMYK: {
+                CMYKColor cmyk = (CMYKColor)color;
+                setCMYKColorStrokeF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
+                break;
+            }
+            case ExtendedColor.TYPE_SEPARATION: {
+                SpotColor spot = (SpotColor)color;
+                setColorStroke(spot.getPdfSpotColor(), spot.getTint());
+                break;
+            }
+            case ExtendedColor.TYPE_PATTERN: {
+                PatternColor pat = (PatternColor) color;
+                setPatternStroke(pat.getPainter());
+                break;
+            }
+            case ExtendedColor.TYPE_SHADING: {
+                ShadingColor shading = (ShadingColor) color;
+                setShadingStroke(shading.getPdfShadingPattern());
+                break;
+            }
+            default:
+                setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue());
+        }
+    }
+    
+    /** Sets the fill color. <CODE>color</CODE> can be an
+     * <CODE>ExtendedColor</CODE>.
+     * @param color the color
+     */
+    public void setColorFill(Color color) {
+        PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+        int type = ExtendedColor.getType(color);
+        switch (type) {
+            case ExtendedColor.TYPE_GRAY: {
+                setGrayFill(((GrayColor)color).getGray());
+                break;
+            }
+            case ExtendedColor.TYPE_CMYK: {
+                CMYKColor cmyk = (CMYKColor)color;
+                setCMYKColorFillF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
+                break;
+            }
+            case ExtendedColor.TYPE_SEPARATION: {
+                SpotColor spot = (SpotColor)color;
+                setColorFill(spot.getPdfSpotColor(), spot.getTint());
+                break;
+            }
+            case ExtendedColor.TYPE_PATTERN: {
+                PatternColor pat = (PatternColor) color;
+                setPatternFill(pat.getPainter());
+                break;
+            }
+            case ExtendedColor.TYPE_SHADING: {
+                ShadingColor shading = (ShadingColor) color;
+                setShadingFill(shading.getPdfShadingPattern());
+                break;
+            }
+            default:
+                setRGBColorFill(color.getRed(), color.getGreen(), color.getBlue());
+        }
+    }
+    
+    /** Sets the fill color to a spot color.
+     * @param sp the spot color
+     * @param tint the tint for the spot color. 0 is no color and 1
+     * is 100% color
+     */
+    public void setColorFill(PdfSpotColor sp, float tint) {
+        checkWriter();
+        state.colorDetails = writer.addSimple(sp);
+        PageResources prs = getPageResources();
+        PdfName name = state.colorDetails.getColorName();
+        name = prs.addColor(name, state.colorDetails.getIndirectReference());
+        content.append(name.getBytes()).append(" cs ").append(tint).append(" scn").append_i(separator);
+    }
+    
+    /** Sets the stroke color to a spot color.
+     * @param sp the spot color
+     * @param tint the tint for the spot color. 0 is no color and 1
+     * is 100% color
+     */
+    public void setColorStroke(PdfSpotColor sp, float tint) {
+        checkWriter();
+        state.colorDetails = writer.addSimple(sp);
+        PageResources prs = getPageResources();
+        PdfName name = state.colorDetails.getColorName();
+        name = prs.addColor(name, state.colorDetails.getIndirectReference());
+        content.append(name.getBytes()).append(" CS ").append(tint).append(" SCN").append_i(separator);
+    }
+    
+    /** Sets the fill color to a pattern. The pattern can be
+     * colored or uncolored.
+     * @param p the pattern
+     */
+    public void setPatternFill(PdfPatternPainter p) {
+        if (p.isStencil()) {
+            setPatternFill(p, p.getDefaultColor());
+            return;
+        }
+        checkWriter();
+        PageResources prs = getPageResources();
+        PdfName name = writer.addSimplePattern(p);
+        name = prs.addPattern(name, p.getIndirectReference());
+        content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
+    }
+    
+    /** Outputs the color values to the content.
+     * @param color The color
+     * @param tint the tint if it is a spot color, ignored otherwise
+     */
+    void outputColorNumbers(Color color, float tint) {
+        PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+        int type = ExtendedColor.getType(color);
+        switch (type) {
+            case ExtendedColor.TYPE_RGB:
+                content.append((float)(color.getRed()) / 0xFF);
+                content.append(' ');
+                content.append((float)(color.getGreen()) / 0xFF);
+                content.append(' ');
+                content.append((float)(color.getBlue()) / 0xFF);
+                break;
+            case ExtendedColor.TYPE_GRAY:
+                content.append(((GrayColor)color).getGray());
+                break;
+            case ExtendedColor.TYPE_CMYK: {
+                CMYKColor cmyk = (CMYKColor)color;
+                content.append(cmyk.getCyan()).append(' ').append(cmyk.getMagenta());
+                content.append(' ').append(cmyk.getYellow()).append(' ').append(cmyk.getBlack());
+                break;
+            }
+            case ExtendedColor.TYPE_SEPARATION:
+                content.append(tint);
+                break;
+            default:
+                throw new RuntimeException("Invalid color type.");
+        }
+    }
+    
+    /** Sets the fill color to an uncolored pattern.
+     * @param p the pattern
+     * @param color the color of the pattern
+     */
+    public void setPatternFill(PdfPatternPainter p, Color color) {
+        if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
+            setPatternFill(p, color, ((SpotColor)color).getTint());
+        else
+            setPatternFill(p, color, 0);
+    }
+    
+    /** Sets the fill color to an uncolored pattern.
+     * @param p the pattern
+     * @param color the color of the pattern
+     * @param tint the tint if the color is a spot color, ignored otherwise
+     */
+    public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
+        checkWriter();
+        if (!p.isStencil())
+            throw new RuntimeException("An uncolored pattern was expected.");
+        PageResources prs = getPageResources();
+        PdfName name = writer.addSimplePattern(p);
+        name = prs.addPattern(name, p.getIndirectReference());
+        ColorDetails csDetail = writer.addSimplePatternColorspace(color);
+        PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
+        content.append(cName.getBytes()).append(" cs").append_i(separator);
+        outputColorNumbers(color, tint);
+        content.append(' ').append(name.getBytes()).append(" scn").append_i(separator);
+    }
+    
+    /** Sets the stroke color to an uncolored pattern.
+     * @param p the pattern
+     * @param color the color of the pattern
+     */
+    public void setPatternStroke(PdfPatternPainter p, Color color) {
+        if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
+            setPatternStroke(p, color, ((SpotColor)color).getTint());
+        else
+            setPatternStroke(p, color, 0);
+    }
+    
+    /** Sets the stroke color to an uncolored pattern.
+     * @param p the pattern
+     * @param color the color of the pattern
+     * @param tint the tint if the color is a spot color, ignored otherwise
+     */
+    public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
+        checkWriter();
+        if (!p.isStencil())
+            throw new RuntimeException("An uncolored pattern was expected.");
+        PageResources prs = getPageResources();
+        PdfName name = writer.addSimplePattern(p);
+        name = prs.addPattern(name, p.getIndirectReference());
+        ColorDetails csDetail = writer.addSimplePatternColorspace(color);
+        PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
+        content.append(cName.getBytes()).append(" CS").append_i(separator);
+        outputColorNumbers(color, tint);
+        content.append(' ').append(name.getBytes()).append(" SCN").append_i(separator);
+    }
+    
+    /** Sets the stroke color to a pattern. The pattern can be
+     * colored or uncolored.
+     * @param p the pattern
+     */
+    public void setPatternStroke(PdfPatternPainter p) {
+        if (p.isStencil()) {
+            setPatternStroke(p, p.getDefaultColor());
+            return;
+        }
+        checkWriter();
+        PageResources prs = getPageResources();
+        PdfName name = writer.addSimplePattern(p);
+        name = prs.addPattern(name, p.getIndirectReference());
+        content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
+    }
+    
+    /**
+     * Paints using a shading object. 
+     * @param shading the shading object
+     */
+    public void paintShading(PdfShading shading) {
+        writer.addSimpleShading(shading);
+        PageResources prs = getPageResources();
+        PdfName name = prs.addShading(shading.getShadingName(), shading.getShadingReference());
+        content.append(name.getBytes()).append(" sh").append_i(separator);
+        ColorDetails details = shading.getColorDetails();
+        if (details != null)
+            prs.addColor(details.getColorName(), details.getIndirectReference());
+    }
+    
+    /**
+     * Paints using a shading pattern. 
+     * @param shading the shading pattern
+     */
+    public void paintShading(PdfShadingPattern shading) {
+        paintShading(shading.getShading());
+    }
+    
+    /**
+     * Sets the shading fill pattern.
+     * @param shading the shading pattern
+     */
+    public void setShadingFill(PdfShadingPattern shading) {
+        writer.addSimpleShadingPattern(shading);
+        PageResources prs = getPageResources();
+        PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
+        content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
+        ColorDetails details = shading.getColorDetails();
+        if (details != null)
+            prs.addColor(details.getColorName(), details.getIndirectReference());
+    }
+    
+    /**
+     * Sets the shading stroke pattern
+     * @param shading the shading pattern
+     */
+    public void setShadingStroke(PdfShadingPattern shading) {
+        writer.addSimpleShadingPattern(shading);
+        PageResources prs = getPageResources();
+        PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
+        content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
+        ColorDetails details = shading.getColorDetails();
+        if (details != null)
+            prs.addColor(details.getColorName(), details.getIndirectReference());
+    }
+    
+    /** Check if we have a valid PdfWriter.
+     *
+     */
+    protected void checkWriter() {
+        if (writer == null)
+            throw new NullPointerException("The writer in PdfContentByte is null.");
+    }
+    
+    /**
+     * Show an array of text.
+     * @param text array of text
+     */
+    public void showText(PdfTextArray text) {
+        if (state.fontDetails == null)
+            throw new NullPointerException("Font and size must be set before writing any text");
+        content.append("[");
+        ArrayList arrayList = text.getArrayList();
+        boolean lastWasNumber = false;
+        for (int k = 0; k < arrayList.size(); ++k) {
+            Object obj = arrayList.get(k);
+            if (obj instanceof String) {
+                showText2((String)obj);
+                lastWasNumber = false;
+            }
+            else {
+                if (lastWasNumber)
+                    content.append(' ');
+                else
+                    lastWasNumber = true;
+                content.append(((Float)obj).floatValue());
+            }
+        }
+        content.append("]TJ").append_i(separator);
+    }
+    
+    /**
+     * Gets the <CODE>PdfWriter</CODE> in use by this object.
+     * @return the <CODE>PdfWriter</CODE> in use by this object
+     */
+    public PdfWriter getPdfWriter() {
+        return writer;
+    }
+    
+    /**
+     * Gets the <CODE>PdfDocument</CODE> in use by this object.
+     * @return the <CODE>PdfDocument</CODE> in use by this object
+     */
+    public PdfDocument getPdfDocument() {
+        return pdf;
+    }
+    
+    /**
+     * Implements a link to other part of the document. The jump will
+     * be made to a local destination with the same name, that must exist.
+     * @param name the name for this link
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    public void localGoto(String name, float llx, float lly, float urx, float ury) {
+        pdf.localGoto(name, llx, lly, urx, ury);
+    }
+    
+    /**
+     * The local destination to where a local goto with the same
+     * name will jump.
+     * @param name the name of this local destination
+     * @param destination the <CODE>PdfDestination</CODE> with the jump coordinates
+     * @return <CODE>true</CODE> if the local destination was added,
+     * <CODE>false</CODE> if a local destination with the same name
+     * already exists
+     */
+    public boolean localDestination(String name, PdfDestination destination) {
+        return pdf.localDestination(name, destination);
+    }
+    
+    /**
+     * Gets a duplicate of this <CODE>PdfContentByte</CODE>. All
+     * the members are copied by reference but the buffer stays different.
+     *
+     * @return a copy of this <CODE>PdfContentByte</CODE>
+     */
+    public PdfContentByte getDuplicate() {
+        return new PdfContentByte(writer);
+    }
+    
+    /**
+     * Implements a link to another document.
+     * @param filename the filename for the remote document
+     * @param name the name to jump to
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    public void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
+        pdf.remoteGoto(filename, name, llx, lly, urx, ury);
+    }
+    
+    /**
+     * Implements a link to another document.
+     * @param filename the filename for the remote document
+     * @param page the page to jump to
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    public void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
+        pdf.remoteGoto(filename, page, llx, lly, urx, ury);
+    }
+    /**
+     * Adds a round rectangle to the current path.
+     *
+     * @param x x-coordinate of the starting point
+     * @param y y-coordinate of the starting point
+     * @param w width
+     * @param h height
+     * @param r radius of the arc corner
+     */
+    public void roundRectangle(float x, float y, float w, float h, float r) {
+        if (w < 0) {
+            x += w;
+            w = -w;
+        }
+        if (h < 0) {
+            y += h;
+            h = -h;
+        }
+        if (r < 0)
+            r = -r;
+        float b = 0.4477f;
+        moveTo(x + r, y);
+        lineTo(x + w - r, y);
+        curveTo(x + w - r * b, y, x + w, y + r * b, x + w, y + r);
+        lineTo(x + w, y + h - r);
+        curveTo(x + w, y + h - r * b, x + w - r * b, y + h, x + w - r, y + h);
+        lineTo(x + r, y + h);
+        curveTo(x + r * b, y + h, x, y + h - r * b, x, y + h - r);
+        lineTo(x, y + r);
+        curveTo(x, y + r * b, x + r * b, y, x + r, y);
+    }
+    
+    /** Implements an action in an area.
+     * @param action the <CODE>PdfAction</CODE>
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    public void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
+        pdf.setAction(action, llx, lly, urx, ury);
+    }
+    
+    /** Outputs a <CODE>String</CODE> directly to the content.
+     * @param s the <CODE>String</CODE>
+     */
+    public void setLiteral(String s) {
+        content.append(s);
+    }
+    
+    /** Outputs a <CODE>char</CODE> directly to the content.
+     * @param c the <CODE>char</CODE>
+     */
+    public void setLiteral(char c) {
+        content.append(c);
+    }
+    
+    /** Outputs a <CODE>float</CODE> directly to the content.
+     * @param n the <CODE>float</CODE>
+     */
+    public void setLiteral(float n) {
+        content.append(n);
+    }
+    
+    /** Throws an error if it is a pattern.
+     * @param t the object to check
+     */
+    void checkNoPattern(PdfTemplate t) {
+        if (t.getType() == PdfTemplate.TYPE_PATTERN)
+            throw new RuntimeException("Invalid use of a pattern. A template was expected.");
+    }
+    
+    /**
+     * Draws a TextField.
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @param on
+     */
+    public void drawRadioField(float llx, float lly, float urx, float ury, boolean on) {
+        if (llx > urx) { float x = llx; llx = urx; urx = x; }
+        if (lly > ury) { float y = lly; lly = ury; ury = y; }
+        // silver circle
+        setLineWidth(1);
+        setLineCap(1);
+        setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+        arc(llx + 1f, lly + 1f, urx - 1f, ury - 1f, 0f, 360f);
+        stroke();
+        // gray circle-segment
+        setLineWidth(1);
+        setLineCap(1);
+        setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+        arc(llx + 0.5f, lly + 0.5f, urx - 0.5f, ury - 0.5f, 45, 180);
+        stroke();
+        // black circle-segment
+        setLineWidth(1);
+        setLineCap(1);
+        setColorStroke(new Color(0x00, 0x00, 0x00));
+        arc(llx + 1.5f, lly + 1.5f, urx - 1.5f, ury - 1.5f, 45, 180);
+        stroke();
+        if (on) {
+            // gray circle
+            setLineWidth(1);
+            setLineCap(1);
+            setColorFill(new Color(0x00, 0x00, 0x00));
+            arc(llx + 4f, lly + 4f, urx - 4f, ury - 4f, 0, 360);
+            fill();
+        }
+    }
+    
+    /**
+     * Draws a TextField.
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     */   
+    public void drawTextField(float llx, float lly, float urx, float ury) {
+        if (llx > urx) { float x = llx; llx = urx; urx = x; }
+        if (lly > ury) { float y = lly; lly = ury; ury = y; }
+        // silver rectangle not filled
+        setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+        setLineWidth(1);
+        setLineCap(0);
+        rectangle(llx, lly, urx - llx, ury - lly);
+        stroke();
+        // white rectangle filled
+        setLineWidth(1);
+        setLineCap(0);
+        setColorFill(new Color(0xFF, 0xFF, 0xFF));
+        rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
+        fill();
+        // silver lines
+        setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+        setLineWidth(1);
+        setLineCap(0);
+        moveTo(llx + 1f, lly + 1.5f);
+        lineTo(urx - 1.5f, lly + 1.5f);
+        lineTo(urx - 1.5f, ury - 1f);
+        stroke();
+        // gray lines
+        setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+        setLineWidth(1);
+        setLineCap(0);
+        moveTo(llx + 1f, lly + 1);
+        lineTo(llx + 1f, ury - 1f);
+        lineTo(urx - 1f, ury - 1f);
+        stroke();
+        // black lines
+        setColorStroke(new Color(0x00, 0x00, 0x00));
+        setLineWidth(1);
+        setLineCap(0);
+        moveTo(llx + 2f, lly + 2f);
+        lineTo(llx + 2f, ury - 2f);
+        lineTo(urx - 2f, ury - 2f);
+        stroke();
+    }
+    
+    /**
+     * Draws a button.
+     * @param llx
+     * @param lly
+     * @param urx
+     * @param ury
+     * @param text
+     * @param bf
+     * @param size
+     */
+    public void drawButton(float llx, float lly, float urx, float ury, String text, BaseFont bf, float size) {
+        if (llx > urx) { float x = llx; llx = urx; urx = x; }
+        if (lly > ury) { float y = lly; lly = ury; ury = y; }
+        // black rectangle not filled
+        setColorStroke(new Color(0x00, 0x00, 0x00));
+        setLineWidth(1);
+        setLineCap(0);
+        rectangle(llx, lly, urx - llx, ury - lly);
+        stroke();
+        // silver rectangle filled
+        setLineWidth(1);
+        setLineCap(0);
+        setColorFill(new Color(0xC0, 0xC0, 0xC0));
+        rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
+        fill();
+        // white lines
+        setColorStroke(new Color(0xFF, 0xFF, 0xFF));
+        setLineWidth(1);
+        setLineCap(0);
+        moveTo(llx + 1f, lly + 1f);
+        lineTo(llx + 1f, ury - 1f);
+        lineTo(urx - 1f, ury - 1f);
+        stroke();
+        // dark grey lines
+        setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+        setLineWidth(1);
+        setLineCap(0);
+        moveTo(llx + 1f, lly + 1f);
+        lineTo(urx - 1f, lly + 1f);
+        lineTo(urx - 1f, ury - 1f);
+        stroke();
+        // text
+        resetRGBColorFill();
+        beginText();
+        setFontAndSize(bf, size);
+        showTextAligned(PdfContentByte.ALIGN_CENTER, text, llx + (urx - llx) / 2, lly + (ury - lly - size) / 2, 0);
+        endText();
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to write on. The graphics
+     * are translated to PDF commands as shapes. No PDF fonts will appear.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createGraphicsShapes(float width, float height) {
+        return new PdfGraphics2D(this, width, height, null, true, false, 0);
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands as shapes. No PDF fonts will appear.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param printerJob a printer job
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, null, true, false, 0, printerJob);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to write on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createGraphics(float width, float height) {
+        return new PdfGraphics2D(this, width, height, null, false, false, 0);
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param printerJob
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createPrinterGraphics(float width, float height, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, null, false, false, 0, printerJob);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to write on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param convertImagesToJPEG
+     * @param quality
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createGraphics(float width, float height, boolean convertImagesToJPEG, float quality) {
+        return new PdfGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param convertImagesToJPEG
+     * @param quality
+     * @param printerJob
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createPrinterGraphics(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality, printerJob);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width
+     * @param height
+     * @param convertImagesToJPEG
+     * @param quality
+     * @return A Graphics2D object
+     */
+    public java.awt.Graphics2D createGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality) {
+        return new PdfGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width
+     * @param height
+     * @param convertImagesToJPEG
+     * @param quality
+     * @param printerJob
+     * @return a Graphics2D object
+     */
+    public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality, printerJob);
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to write on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param fontMapper the mapping from awt fonts to <CODE>BaseFont</CODE>
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper) {
+        return new PdfGraphics2D(this, width, height, fontMapper, false, false, 0);
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param fontMapper the mapping from awt fonts to <CODE>BaseFont</CODE>
+     * @param printerJob a printer job
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, false, 0, printerJob);
+    }
+    
+    /** Gets a <CODE>Graphics2D</CODE> to write on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param fontMapper the mapping from awt fonts to <CODE>BaseFont</CODE>
+     * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
+     * @param quality the quality of the jpeg
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality) {
+        return new PdfGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality);
+    }
+
+    /** Gets a <CODE>Graphics2D</CODE> to print on. The graphics
+     * are translated to PDF commands.
+     * @param width the width of the panel
+     * @param height the height of the panel
+     * @param fontMapper the mapping from awt fonts to <CODE>BaseFont</CODE>
+     * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
+     * @param quality the quality of the jpeg
+     * @param printerJob a printer job
+     * @return a <CODE>Graphics2D</CODE>
+     */
+    public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+        return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality, printerJob);
+    }
+
+    PageResources getPageResources() {
+        return pdf.getPageResources();
+    }
+    
+    /** Sets the graphic state
+     * @param gstate the graphic state
+     */    
+    public void setGState(PdfGState gstate) {
+        PdfObject obj[] = writer.addSimpleExtGState(gstate);
+        PageResources prs = getPageResources();
+        PdfName name = prs.addExtGState((PdfName)obj[0], (PdfIndirectReference)obj[1]);
+        content.append(name.getBytes()).append(" gs").append_i(separator);
+    }
+    
+    /**
+     * Begins a graphic block whose visibility is controled by the <CODE>layer</CODE>.
+     * Blocks can be nested. Each block must be terminated by an {@link #endLayer()}.<p>
+     * Note that nested layers with {@link PdfLayer#addChild(PdfLayer)} only require a single
+     * call to this method and a single call to {@link #endLayer()}; all the nesting control
+     * is built in.
+     * @param layer the layer
+     */    
+    public void beginLayer(PdfOCG layer) {
+        if ((layer instanceof PdfLayer) && ((PdfLayer)layer).getTitle() != null)
+            throw new IllegalArgumentException("A title is not a layer");
+        if (layerDepth == null)
+            layerDepth = new ArrayList();
+        if (layer instanceof PdfLayerMembership) {
+            layerDepth.add(new Integer(1));
+            beginLayer2(layer);
+            return;
+        }
+        int n = 0;
+        PdfLayer la = (PdfLayer)layer;
+        while (la != null) {
+            if (la.getTitle() == null) {
+                beginLayer2(la);
+                ++n;
+            }
+            la = la.getParent();
+        }
+        layerDepth.add(new Integer(n));
+    }
+    
+    private void beginLayer2(PdfOCG layer) {
+        PdfName name = writer.addSimpleLayer(layer);
+        PageResources prs = getPageResources();
+        name = prs.addLayer(name, layer.getRef());
+        content.append("/OC ").append(name.getBytes()).append(" BDC").append_i(separator);
+    }
+    
+    /**
+     * Ends a layer controled graphic block. It will end the most recent open block.
+     */    
+    public void endLayer() {
+        int n = 1;
+        if (layerDepth != null && layerDepth.size() > 0) {
+            n = ((Integer)layerDepth.get(layerDepth.size() - 1)).intValue();
+            layerDepth.remove(layerDepth.size() - 1);
+        }
+        while (n-- > 0)
+            content.append("EMC").append_i(separator);
+    }
+    
+    /** Concatenates a transformation to the current transformation
+     * matrix.
+     * @param af the transformation
+     */    
+    public void transform(AffineTransform af) {
+        double arr[] = new double[6];
+        af.getMatrix(arr);
+        content.append(arr[0]).append(' ').append(arr[1]).append(' ').append(arr[2]).append(' ');
+        content.append(arr[3]).append(' ').append(arr[4]).append(' ').append(arr[5]).append(" cm").append_i(separator);
+    }
+    
+    void addAnnotation(PdfAnnotation annot) {
+        writer.addAnnotation(annot);
+    }
+    
+    /**
+     * Sets the default colorspace.
+     * @param name the name of the colorspace. It can be <CODE>PdfName.DEFAULTGRAY</CODE>, <CODE>PdfName.DEFAULTRGB</CODE>
+     * or <CODE>PdfName.DEFAULTCMYK</CODE>
+     * @param obj the colorspace. A <CODE>null</CODE> or <CODE>PdfNull</CODE> removes any colorspace with the same name
+     */    
+    public void setDefaultColorspace(PdfName name, PdfObject obj) {
+        PageResources prs = getPageResources();
+        prs.addDefaultColor(name, obj);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfContents.java b/LibrarySource/com/lowagie/text/pdf/PdfContents.java
new file mode 100644
index 0000000..fb031cf
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfContents.java
@@ -0,0 +1,147 @@
+/*
+ * $Id: PdfContents.java,v 1.26 2002/06/20 13:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.DocWriter;
+import com.lowagie.text.Document;
+import com.lowagie.text.Rectangle;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.zip.DeflaterOutputStream;
+
+/**
+ * <CODE>PdfContents</CODE> is a <CODE>PdfStream</CODE> containing the contents (text + graphics) of a <CODE>PdfPage</CODE>.
+ */
+
+class PdfContents extends PdfStream {
+    
+    static final byte SAVESTATE[] = DocWriter.getISOBytes("q\n");
+    static final byte RESTORESTATE[] = DocWriter.getISOBytes("Q\n");
+    static final byte ROTATE90[] = DocWriter.getISOBytes("0 1 -1 0 ");
+    static final byte ROTATE180[] = DocWriter.getISOBytes("-1 0 0 -1 ");
+    static final byte ROTATE270[] = DocWriter.getISOBytes("0 -1 1 0 ");
+    static final byte ROTATEFINAL[] = DocWriter.getISOBytes(" cm\n");
+    // constructor
+    
+/**
+ * Constructs a <CODE>PdfContents</CODE>-object, containing text and general graphics.
+ *
+ * @param under the direct content that is under all others
+ * @param content the graphics in a page
+ * @param text the text in a page
+ * @param secondContent the direct content that is over all others
+ * @throws BadPdfFormatException on error
+ */
+    
+    PdfContents(PdfContentByte under, PdfContentByte content, PdfContentByte text, PdfContentByte secondContent, Rectangle page) throws BadPdfFormatException {
+        super();
+        try {
+            OutputStream out = null;
+            streamBytes = new ByteArrayOutputStream();
+            if (Document.compress)
+            {
+                compressed = true;
+                out = new DeflaterOutputStream(streamBytes);
+            }
+            else
+                out = streamBytes;
+            int rotation = page.getRotation();
+            switch (rotation) {
+                case 90:
+                    out.write(ROTATE90);
+                    out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
+                    out.write(' ');
+                    out.write('0');
+                    out.write(ROTATEFINAL);
+                    break;
+                case 180:
+                    out.write(ROTATE180);
+                    out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
+                    out.write(' ');
+                    out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
+                    out.write(ROTATEFINAL);
+                    break;
+                case 270:
+                    out.write(ROTATE270);
+                    out.write('0');
+                    out.write(' ');
+                    out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
+                    out.write(ROTATEFINAL);
+                    break;
+            }
+            if (under.size() > 0) {
+                out.write(SAVESTATE);
+                under.getInternalBuffer().writeTo(out);
+                out.write(RESTORESTATE);
+            }
+            if (content.size() > 0) {
+                out.write(SAVESTATE);
+                content.getInternalBuffer().writeTo(out);
+                out.write(RESTORESTATE);
+            }
+            if (text != null) {
+                out.write(SAVESTATE);
+                text.getInternalBuffer().writeTo(out);
+                out.write(RESTORESTATE);
+            }
+            if (secondContent.size() > 0) {
+                secondContent.getInternalBuffer().writeTo(out);
+            }
+            out.close();
+        }
+        catch (Exception e) {
+            throw new BadPdfFormatException(e.getMessage());
+        }
+        put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
+        if (compressed)
+            put(PdfName.FILTER, PdfName.FLATEDECODE);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfDashPattern.java b/LibrarySource/com/lowagie/text/pdf/PdfDashPattern.java
new file mode 100644
index 0000000..bd252f4
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfDashPattern.java
@@ -0,0 +1,144 @@
+/*
+ * $Id: PdfDashPattern.java,v 1.33 2003/05/02 09:01:18 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A <CODE>PdfDashPattern</CODE> defines a dash pattern as described in
+ * the PDF Reference Manual version 1.3 p 325 (section 8.4.3).
+ *
+ * @see		PdfArray
+ */
+
+public class PdfDashPattern extends PdfArray {
+    
+    // membervariables
+    
+/** This is the length of a dash. */
+    private float dash = -1;
+    
+/** This is the length of a gap. */
+    private float gap = -1;
+    
+/** This is the phase. */
+    private float phase = -1;
+    
+    // constructors
+    
+/**
+ * Constructs a new <CODE>PdfDashPattern</CODE>.
+ */
+    
+    public PdfDashPattern() {
+        super();
+    }
+    
+/**
+ * Constructs a new <CODE>PdfDashPattern</CODE>.
+ */
+    
+    public PdfDashPattern(float dash) {
+        super(new PdfNumber(dash));
+        this.dash = dash;
+    }
+    
+/**
+ * Constructs a new <CODE>PdfDashPattern</CODE>.
+ */
+    
+    public PdfDashPattern(float dash, float gap) {
+        super(new PdfNumber(dash));
+        add(new PdfNumber(gap));
+        this.dash = dash;
+        this.gap = gap;
+    }
+    
+/**
+ * Constructs a new <CODE>PdfDashPattern</CODE>.
+ */
+    
+    public PdfDashPattern(float dash, float gap, float phase) {
+        super(new PdfNumber(dash));
+        add(new PdfNumber(gap));
+        this.dash = dash;
+        this.gap = gap;
+        this.phase = phase;
+    }
+    
+    public void add(float n) {
+        add(new PdfNumber(n));
+    }
+    
+/**
+ * Returns the PDF representation of this <CODE>PdfArray</CODE>.
+ *
+ * @return		an array of <CODE>byte</CODE>s
+ */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        os.write('[');
+
+        if (dash >= 0) {
+            new PdfNumber(dash).toPdf(writer, os);
+            if (gap >= 0) {
+                os.write(' ');
+                new PdfNumber(gap).toPdf(writer, os);
+            }
+        }
+        os.write(']');
+        if (phase >=0) {
+            os.write(' ');
+            new PdfNumber(phase).toPdf(writer, os);
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfDate.java b/LibrarySource/com/lowagie/text/pdf/PdfDate.java
new file mode 100644
index 0000000..df14a24
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfDate.java
@@ -0,0 +1,190 @@
+/*
+ * $Id: PdfDate.java,v 1.23 2002/07/09 11:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.GregorianCalendar;
+import java.util.Calendar;
+import java.util.SimpleTimeZone;
+
+/**
+ * <CODE>PdfDate</CODE> is the PDF date object.
+ * <P>
+ * PDF defines a standard date format. The PDF date format closely follows the format
+ * defined by the international standard ASN.1 (Abstract Syntax Notation One, defined
+ * in CCITT X.208 or ISO/IEC 8824). A date is a <CODE>PdfString</CODE> of the form:
+ * <P><BLOCKQUOTE>
+ * (D: YYYYMMDDHHmmSSOHH'mm')
+ * </BLOCKQUOTE><P>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.2 (page 183-184)
+ *
+ * @see		PdfString
+ * @see		java.util.GregorianCalendar
+ */
+
+public class PdfDate extends PdfString {
+    
+    private static final int dateSpace[] = {Calendar.YEAR, 4, 0, Calendar.MONTH, 2, -1, Calendar.DAY_OF_MONTH, 2, 0,
+        Calendar.HOUR_OF_DAY, 2, 0, Calendar.MINUTE, 2, 0, Calendar.SECOND, 2, 0};
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfDate</CODE>-object.
+ *
+ * @param		d			the date that has to be turned into a <CODE>PdfDate</CODE>-object
+ */
+    
+    public PdfDate(Calendar d) {
+        super();
+        StringBuffer date = new StringBuffer("D:");
+        date.append(setLength(d.get(Calendar.YEAR), 4));
+        date.append(setLength(d.get(Calendar.MONTH) + 1, 2));
+        date.append(setLength(d.get(Calendar.DATE), 2));
+        date.append(setLength(d.get(Calendar.HOUR_OF_DAY), 2));
+        date.append(setLength(d.get(Calendar.MINUTE), 2));
+        date.append(setLength(d.get(Calendar.SECOND), 2));
+        int timezone = d.get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000);
+        if (timezone == 0) {
+            date.append("Z");
+        }
+        else if (timezone < 0) {
+            date.append("-");
+            timezone = -timezone;
+        }
+        else {
+            date.append("+");
+        }
+        if (timezone != 0) {
+            date.append(setLength(timezone, 2)).append("'");
+            int zone = Math.abs(d.get(Calendar.ZONE_OFFSET) / (60 * 1000)) - (timezone * 60);
+            date.append(setLength(zone, 2)).append("'");
+        }
+        value = date.toString();
+    }
+    
+/**
+ * Constructs a <CODE>PdfDate</CODE>-object, representing the current day and time.
+ */
+    
+    public PdfDate() {
+        this(new GregorianCalendar());
+    }
+    
+/**
+ * Adds a number of leading zeros to a given <CODE>String</CODE> in order to get a <CODE>String</CODE>
+ * of a certain length.
+ *
+ * @param		i   		a given number
+ * @param		length		the length of the resulting <CODE>String</CODE>
+ * @return		the resulting <CODE>String</CODE>
+ */
+    
+    private String setLength(int i, int length) { // 1.3-1.4 problem fixed by Finn Bock
+        StringBuffer tmp = new StringBuffer();
+        tmp.append(i);
+        while (tmp.length() < length) {
+            tmp.insert(0, "0");
+        }
+        tmp.setLength(length);
+        return tmp.toString();
+    }
+    
+    /**
+     * Converts a PDF string representing a date into a Calendar.
+     * @param s the PDF string representing a date
+     * @return a <CODE>Calendar</CODE> representing the date or <CODE>null</CODE> if the string
+     * was not a date
+     */    
+    public static Calendar decode(String s) {
+        try {
+            if (s.startsWith("D:"))
+                s = s.substring(2);
+            GregorianCalendar calendar;
+            int slen = s.length();
+            int idx = s.indexOf('Z');
+            if (idx >= 0) {
+                slen = idx;
+                calendar = new GregorianCalendar(new SimpleTimeZone(0, "ZPDF"));
+            }
+            else {
+                int sign = 1;
+                idx = s.indexOf('+');
+                if (idx < 0) {
+                    idx = s.indexOf('-');
+                    if (idx >= 0)
+                        sign = -1;
+                }
+                if (idx < 0)
+                    calendar = new GregorianCalendar();
+                else {
+                    int offset = Integer.parseInt(s.substring(idx + 1, idx + 3)) * 60;
+                    if (idx + 5 < s.length())
+                        offset += Integer.parseInt(s.substring(idx + 4, idx + 6));
+                    calendar = new GregorianCalendar(new SimpleTimeZone(offset * sign * 60000, "ZPDF"));
+                    slen = idx;
+                }
+            }
+            calendar.clear();
+            idx = 0;
+            for (int k = 0; k < dateSpace.length; k += 3) {
+                if (idx >= slen)
+                    break;
+                calendar.set(dateSpace[k], Integer.parseInt(s.substring(idx, idx + dateSpace[k + 1])) + dateSpace[k + 2]);
+                idx += dateSpace[k + 1];
+            }
+            return calendar;
+        }
+        catch (Exception e) {
+            return null;
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfDestination.java b/LibrarySource/com/lowagie/text/pdf/PdfDestination.java
new file mode 100644
index 0000000..36c49ba
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfDestination.java
@@ -0,0 +1,221 @@
+/*
+ * $Id: PdfDestination.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * A <CODE>PdfColor</CODE> defines a Color (it's a <CODE>PdfArray</CODE> containing 3 values).
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfDestination extends PdfArray {
+    
+    // public static final member-variables
+    
+/** This is a possible destination type */
+    public static final int XYZ = 0;
+    
+/** This is a possible destination type */
+    public static final int FIT = 1;
+    
+/** This is a possible destination type */
+    public static final int FITH = 2;
+    
+/** This is a possible destination type */
+    public static final int FITV = 3;
+    
+/** This is a possible destination type */
+    public static final int FITR = 4;
+    
+/** This is a possible destination type */
+    public static final int FITB = 5;
+    
+/** This is a possible destination type */
+    public static final int FITBH = 6;
+    
+/** This is a possible destination type */
+    public static final int FITBV = 7;
+    
+    // member variables
+    
+/** Is the indirect reference to a page already added? */
+    private boolean status = false;
+    
+    // constructors
+    
+/**
+ * Constructs a new <CODE>PdfDestination</CODE>.
+ * <P>
+ * If <VAR>type</VAR> equals <VAR>FITB</VAR>, the bounding box of a page
+ * will fit the window of the Reader. Otherwise the type will be set to
+ * <VAR>FIT</VAR> so that the entire page will fit to the window.
+ *
+ * @param		type		The destination type
+ */
+    
+    public PdfDestination(int type) {
+        super();
+        if (type == FITB) {
+            add(PdfName.FITB);
+        }
+        else {
+            add(PdfName.FIT);
+        }
+    }
+    
+/**
+ * Constructs a new <CODE>PdfDestination</CODE>.
+ * <P>
+ * If <VAR>type</VAR> equals <VAR>FITBH</VAR> / <VAR>FITBV</VAR>,
+ * the width / height of the bounding box of a page will fit the window
+ * of the Reader. The parameter will specify the y / x coordinate of the
+ * top / left edge of the window. If the <VAR>type</VAR> equals <VAR>FITH</VAR>
+ * or <VAR>FITV</VAR> the width / height of the entire page will fit
+ * the window and the parameter will specify the y / x coordinate of the
+ * top / left edge. In all other cases the type will be set to <VAR>FITH</VAR>.
+ *
+ * @param		type		the destination type
+ * @param		parameter	a parameter to combined with the destination type
+ */
+    
+    public PdfDestination(int type, float parameter) {
+        super(new PdfNumber(parameter));
+        switch(type) {
+            default:
+                addFirst(PdfName.FITH);
+                break;
+            case FITV:
+                addFirst(PdfName.FITV);
+                break;
+            case FITBH:
+                addFirst(PdfName.FITBH);
+                break;
+            case FITBV:
+                addFirst(PdfName.FITBV);
+        }
+    }
+    
+/** Constructs a new <CODE>PdfDestination</CODE>.
+ * <P>
+ * Display the page, with the coordinates (left, top) positioned
+ * at the top-left corner of the window and the contents of the page magnified
+ * by the factor zoom. A negative value for any of the parameters left or top, or a
+ * zoom value of 0 specifies that the current value of that parameter is to be retained unchanged.
+ * @param type must be a <VAR>PdfDestination.XYZ</VAR>
+ * @param left the left value. Negative to place a null
+ * @param top the top value. Negative to place a null
+ * @param zoom The zoom factor. A value of 0 keeps the current value
+ */
+    
+    public PdfDestination(int type, float left, float top, float zoom) {
+        super(PdfName.XYZ);
+        if (left < 0)
+            add(PdfNull.PDFNULL);
+        else
+            add(new PdfNumber(left));
+        if (top < 0)
+            add(PdfNull.PDFNULL);
+        else
+            add(new PdfNumber(top));
+        add(new PdfNumber(zoom));
+    }
+    
+/** Constructs a new <CODE>PdfDestination</CODE>.
+ * <P>
+ * Display the page, with its contents magnified just enough
+ * to fit the rectangle specified by the coordinates left, bottom, right, and top
+ * entirely within the window both horizontally and vertically. If the required
+ * horizontal and vertical magnification factors are different, use the smaller of
+ * the two, centering the rectangle within the window in the other dimension.
+ *
+ * @param type must be PdfDestination.FITR
+ * @param left a parameter
+ * @param bottom a parameter
+ * @param right a parameter
+ * @param top a parameter
+ * @since iText0.38
+ */
+    
+    public PdfDestination(int type, float left, float bottom, float right, float top) {
+        super(PdfName.FITR);
+        add(new PdfNumber(left));
+        add(new PdfNumber(bottom));
+        add(new PdfNumber(right));
+        add(new PdfNumber(top));
+    }
+    
+    // methods
+    
+/**
+ * Checks if an indirect reference to a page has been added.
+ *
+ * @return	<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean hasPage() {
+        return status;
+    }
+    
+/** Adds the indirect reference of the destination page.
+ *
+ * @param page	an indirect reference
+ * @return true if the page reference was added
+ */
+    
+    public boolean addPage(PdfIndirectReference page) {
+        if (!status) {
+            addFirst(page);
+            status = true;
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfDictionary.java b/LibrarySource/com/lowagie/text/pdf/PdfDictionary.java
new file mode 100644
index 0000000..4af1471
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfDictionary.java
@@ -0,0 +1,315 @@
+/*
+ * $Id: PdfDictionary.java,v 1.27 2002/07/09 11:28:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * <CODE>PdfDictionary</CODE> is the Pdf dictionary object.
+ * <P>
+ * A dictionary is an associative table containing pairs of objects. The first element
+ * of each pair is called the <I>key</I> and the second element is called the <I>value</I>.
+ * Unlike dictionaries in the PostScript language, a key must be a <CODE>PdfName</CODE>.
+ * A value can be any kind of <CODE>PdfObject</CODE>, including a dictionary. A dictionary is
+ * generally used to collect and tie together the attributes of a complex object, with each
+ * key-value pair specifying the name and value of an attribute.<BR>
+ * A dictionary is represented by two left angle brackets (<<), followed by a sequence of
+ * key-value pairs, followed by two right angle brackets (>>).<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.7 (page 40-41).
+ * <P>
+ *
+ * @see		PdfObject
+ * @see		PdfName
+ * @see		BadPdfFormatException
+ */
+
+public class PdfDictionary extends PdfObject {
+    
+    // static membervariables (types of dictionary's)
+    
+/** This is a possible type of dictionary */
+    public static final PdfName FONT = PdfName.FONT;
+    
+/** This is a possible type of dictionary */
+    public static final PdfName OUTLINES = PdfName.OUTLINES;
+    
+/** This is a possible type of dictionary */
+    public static final PdfName PAGE = PdfName.PAGE;
+    
+/** This is a possible type of dictionary */
+    public static final PdfName PAGES = PdfName.PAGES;
+    
+/** This is a possible type of dictionary */
+    public static final PdfName CATALOG = PdfName.CATALOG;
+    
+    // membervariables
+    
+/** This is the type of this dictionary */
+    private PdfName dictionaryType = null;
+    
+/** This is the hashmap that contains all the values and keys of the dictionary */
+    protected HashMap hashMap;
+    
+    // constructors
+    
+/**
+ * Constructs an empty <CODE>PdfDictionary</CODE>-object.
+ */
+    
+    public PdfDictionary() {
+        super(DICTIONARY);
+        hashMap = new HashMap();
+    }
+    
+/**
+ * Constructs a <CODE>PdfDictionary</CODE>-object of a certain type.
+ *
+ * @param		type	a <CODE>PdfName</CODE>
+ */
+    
+    public PdfDictionary(PdfName type) {
+        this();
+        dictionaryType = type;
+        put(PdfName.TYPE, dictionaryType);
+    }
+    
+    // methods overriding some methods in PdfObject
+    
+/**
+ * Returns the PDF representation of this <CODE>PdfDictionary</CODE>.
+ *
+ * @return		an array of <CODE>byte</CODE>
+ */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        os.write('<');
+        os.write('<');
+
+        // loop over all the object-pairs in the HashMap
+        PdfName key;
+        PdfObject value;
+        int type = 0;
+        for (Iterator i = hashMap.keySet().iterator(); i.hasNext(); ) {
+            key = (PdfName) i.next();
+            value = (PdfObject) hashMap.get(key);
+            key.toPdf(writer, os);
+            type = value.type();
+            if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+                os.write(' ');
+            value.toPdf(writer, os);
+        }
+        os.write('>');
+        os.write('>');
+    }
+    
+    // methods concerning the HashMap member value
+    
+/**
+ * Adds a <CODE>PdfObject</CODE> and its key to the <CODE>PdfDictionary</CODE>.
+ *
+ * @param		key		key of the entry (a <CODE>PdfName</CODE>)
+ * @param		value	value of the entry (a <CODE>PdfObject</CODE>)
+ * @return		the previous </CODE>PdfObject</CODE> corresponding with the <VAR>key</VAR>
+ */
+    
+    public PdfObject put(PdfName key, PdfObject value) {
+        return (PdfObject) hashMap.put(key, value);
+    }
+    
+/**
+ * Adds a <CODE>PdfObject</CODE> and its key to the <CODE>PdfDictionary</CODE>.
+ * If the value is null it does nothing.
+ *
+ * @param		key		key of the entry (a <CODE>PdfName</CODE>)
+ * @param		value	value of the entry (a <CODE>PdfObject</CODE>)
+ * @return		the previous </CODE>PdfObject</CODE> corresponding with the <VAR>key</VAR>
+ */
+    public PdfObject putEx(PdfName key, PdfObject value) {
+        if (value == null)
+            return null;
+        return (PdfObject) hashMap.put(key, value);
+    }
+    
+/**
+ * Adds a <CODE>PdfObject</CODE> and its key to the <CODE>PdfDictionary</CODE>.
+ * If the value is null the key is deleted.
+ *
+ * @param		key		key of the entry (a <CODE>PdfName</CODE>)
+ * @param		value	value of the entry (a <CODE>PdfObject</CODE>)
+ * @return		the previous </CODE>PdfObject</CODE> corresponding with the <VAR>key</VAR>
+ */
+    public PdfObject putDel(PdfName key, PdfObject value) {
+        if (value == null)
+            return (PdfObject) hashMap.remove(key);;
+        return (PdfObject) hashMap.put(key, value);
+    }
+    
+/**
+ * Removes a <CODE>PdfObject</CODE> and its key from the <CODE>PdfDictionary</CODE>.
+ *
+ * @param		key		key of the entry (a <CODE>PdfName</CODE>)
+ * @return		the previous </CODE>PdfObject</CODE> corresponding with the <VAR>key</VAR>
+ */
+    
+    public PdfObject remove(PdfName key) {
+        return (PdfObject) hashMap.remove(key);
+    }
+    
+/**
+ * Gets a <CODE>PdfObject</CODE> with a certain key from the <CODE>PdfDictionary</CODE>.
+ *
+ * @param		key		key of the entry (a <CODE>PdfName</CODE>)
+ * @return		the previous </CODE>PdfObject</CODE> corresponding with the <VAR>key</VAR>
+ */
+    
+    public PdfObject get(PdfName key) {
+        return (PdfObject) hashMap.get(key);
+    }
+    
+    // methods concerning the type of Dictionary
+    
+/**
+ * Checks if a <CODE>PdfDictionary</CODE> is of a certain type.
+ *
+ * @param		type	a type of dictionary
+ * @return		<CODE>true</CODE> of <CODE>false</CODE>
+ *
+ * @deprecated
+ */
+    
+    public boolean isDictionaryType(PdfName type) {
+        return dictionaryType.compareTo(type) == 0;
+    }
+    
+/**
+ *  Checks if a <CODE>Dictionary</CODE> is of the type FONT.
+ *
+ * @return		<CODE>true</CODE> if it is, <CODE>false</CODE> if it isn't.
+ */
+    
+    public boolean isFont() {
+        return dictionaryType.compareTo(FONT) == 0;
+    }
+    
+/**
+ *  Checks if a <CODE>Dictionary</CODE> is of the type PAGE.
+ *
+ * @return		<CODE>true</CODE> if it is, <CODE>false</CODE> if it isn't.
+ */
+    
+    public boolean isPage() {
+        return dictionaryType.compareTo(PAGE) == 0;
+    }
+    
+/**
+ *  Checks if a <CODE>Dictionary</CODE> is of the type PAGES.
+ *
+ * @return		<CODE>true</CODE> if it is, <CODE>false</CODE> if it isn't.
+ */
+    
+    public boolean isPages() {
+        return dictionaryType.compareTo(PAGES) == 0;
+    }
+    
+/**
+ *  Checks if a <CODE>Dictionary</CODE> is of the type CATALOG.
+ *
+ * @return		<CODE>true</CODE> if it is, <CODE>false</CODE> if it isn't.
+ */
+    
+    public boolean isCatalog() {
+        return dictionaryType.compareTo(CATALOG) == 0;
+    }
+    
+/**
+ *  Checks if a <CODE>Dictionary</CODE> is of the type OUTLINES.
+ *
+ * @return		<CODE>true</CODE> if it is, <CODE>false</CODE> if it isn't.
+ */
+    
+    public boolean isOutlineTree() {
+        return dictionaryType.compareTo(OUTLINES) == 0;
+    }
+    
+    public void merge(PdfDictionary other) {
+        hashMap.putAll(other.hashMap);
+    }
+    
+    public void mergeDifferent(PdfDictionary other) {
+        for (Iterator i = other.hashMap.keySet().iterator(); i.hasNext();) {
+            Object key = i.next();
+            if (!hashMap.containsKey(key)) {
+                hashMap.put(key, other.hashMap.get(key));
+            }
+        }
+    }
+    
+    public Set getKeys() {
+        return hashMap.keySet();
+    }
+
+    public void putAll(PdfDictionary dic) {
+        hashMap.putAll(dic.hashMap);
+    }
+    
+    public int size() {
+        return hashMap.size();
+    }
+    
+    public boolean contains(PdfName key) {
+        return hashMap.containsKey(key);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfDocument.java b/LibrarySource/com/lowagie/text/pdf/PdfDocument.java
new file mode 100644
index 0000000..e45e4ea
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfDocument.java
@@ -0,0 +1,2972 @@
+/*
+ * $Name:  $
+ * $Id: PdfDocument.java,v 1.199 2005/05/03 09:05:50 blowagie Exp $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.TreeMap;
+
+import com.lowagie.text.Anchor;
+import com.lowagie.text.Annotation;
+import com.lowagie.text.BadElementException;
+import com.lowagie.text.Cell;
+import com.lowagie.text.Chunk;
+import com.lowagie.text.DocListener;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Graphic;
+import com.lowagie.text.HeaderFooter;
+import com.lowagie.text.Image;
+import com.lowagie.text.List;
+import com.lowagie.text.ListItem;
+import com.lowagie.text.Meta;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Section;
+import com.lowagie.text.StringCompare;
+import com.lowagie.text.Table;
+import com.lowagie.text.Watermark;
+
+/**
+ * <CODE>PdfDocument</CODE> is the class that is used by <CODE>PdfWriter</CODE>
+ * to translate a <CODE>Document</CODE> into a PDF with different pages.
+ * <P>
+ * A <CODE>PdfDocument</CODE> always listens to a <CODE>Document</CODE>
+ * and adds the Pdf representation of every <CODE>Element</CODE> that is
+ * added to the <CODE>Document</CODE>.
+ *
+ * @see		com.lowagie.text.Document
+ * @see		com.lowagie.text.DocListener
+ * @see		PdfWriter
+ */
+
+class PdfDocument extends Document implements DocListener {
+    
+    /**
+     * <CODE>PdfInfo</CODE> is the PDF InfoDictionary.
+     * <P>
+     * A document's trailer may contain a reference to an Info dictionary that provides information
+     * about the document. This optional dictionary may contain one or more keys, whose values
+     * should be strings.<BR>
+     * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 6.10 (page 120-121)
+     */
+    
+    public static class PdfInfo extends PdfDictionary {
+        
+        // constructors
+        
+        /**
+         * Construct a <CODE>PdfInfo</CODE>-object.
+         */
+        
+        PdfInfo() {
+            super();
+            addProducer();
+            addCreationDate();
+        }
+        
+        /**
+         * Constructs a <CODE>PdfInfo</CODE>-object.
+         *
+         * @param		author		name of the author of the document
+         * @param		title		title of the document
+         * @param		subject		subject of the document
+         */
+        
+        PdfInfo(String author, String title, String subject) {
+            this();
+            addTitle(title);
+            addSubject(subject);
+            addAuthor(author);
+        }
+        
+        /**
+         * Adds the title of the document.
+         *
+         * @param	title		the title of the document
+         */
+        
+        void addTitle(String title) {
+            put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
+        }
+        
+        /**
+         * Adds the subject to the document.
+         *
+         * @param	subject		the subject of the document
+         */
+        
+        void addSubject(String subject) {
+            put(PdfName.SUBJECT, new PdfString(subject, PdfObject.TEXT_UNICODE));
+        }
+        
+        /**
+         * Adds some keywords to the document.
+         *
+         * @param	keywords		the keywords of the document
+         */
+        
+        void addKeywords(String keywords) {
+            put(PdfName.KEYWORDS, new PdfString(keywords, PdfObject.TEXT_UNICODE));
+        }
+        
+        /**
+         * Adds the name of the author to the document.
+         *
+         * @param	author		the name of the author
+         */
+        
+        void addAuthor(String author) {
+            put(PdfName.AUTHOR, new PdfString(author, PdfObject.TEXT_UNICODE));
+        }
+        
+        /**
+         * Adds the name of the creator to the document.
+         *
+         * @param	creator		the name of the creator
+         */
+        
+        void addCreator(String creator) {
+            put(PdfName.CREATOR, new PdfString(creator, PdfObject.TEXT_UNICODE));
+        }
+        
+        /**
+         * Adds the name of the producer to the document.
+         */
+        
+        void addProducer() {
+            // This line may only be changed by Bruno Lowagie or Paulo Soares
+            put(PdfName.PRODUCER, new PdfString(getVersion()));
+            // Do not edit the line above!
+        }
+        
+        /**
+         * Adds the date of creation to the document.
+         */
+        
+        void addCreationDate() {
+            PdfString date = new PdfDate();
+            put(PdfName.CREATIONDATE, date);
+            put(PdfName.MODDATE, date);
+        }
+        
+        void addkey(String key, String value) {
+            if (key.equals("Producer") || key.equals("CreationDate"))
+                return;
+            put(new PdfName(key), new PdfString(value, PdfObject.TEXT_UNICODE));
+        }
+    }
+    
+    /**
+     * <CODE>PdfCatalog</CODE> is the PDF Catalog-object.
+     * <P>
+     * The Catalog is a dictionary that is the root node of the document. It contains a reference
+     * to the tree of pages contained in the document, a reference to the tree of objects representing
+     * the document's outline, a reference to the document's article threads, and the list of named
+     * destinations. In addition, the Catalog indicates whether the document's outline or thumbnail
+     * page images should be displayed automatically when the document is viewed and wether some location
+     * other than the first page should be shown when the document is opened.<BR>
+     * In this class however, only the reference to the tree of pages is implemented.<BR>
+     * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 6.2 (page 67-71)
+     */
+    
+    static class PdfCatalog extends PdfDictionary {
+        
+        PdfWriter writer;
+        // constructors
+        
+        /**
+         * Constructs a <CODE>PdfCatalog</CODE>.
+         *
+         * @param		pages		an indirect reference to the root of the document's Pages tree.
+         * @param writer the writer the catalog applies to
+         */
+        
+        PdfCatalog(PdfIndirectReference pages, PdfWriter writer) {
+            super(CATALOG);
+            this.writer = writer;
+            put(PdfName.PAGES, pages);
+        }
+        
+        /**
+         * Constructs a <CODE>PdfCatalog</CODE>.
+         *
+         * @param		pages		an indirect reference to the root of the document's Pages tree.
+         * @param		outlines	an indirect reference to the outline tree.
+         * @param writer the writer the catalog applies to
+         */
+        
+        PdfCatalog(PdfIndirectReference pages, PdfIndirectReference outlines, PdfWriter writer) {
+            super(CATALOG);
+            this.writer = writer;
+            put(PdfName.PAGES, pages);
+            put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
+            put(PdfName.OUTLINES, outlines);
+        }
+        
+        /**
+         * Adds the names of the named destinations to the catalog.
+         * @param localDestinations the local destinations
+         * @param documentJavaScript the javascript used in the document
+         * @param writer the writer the catalog applies to
+         */
+        void addNames(TreeMap localDestinations, ArrayList documentJavaScript, PdfWriter writer) {
+            if (localDestinations.size() == 0 && documentJavaScript.size() == 0)
+                return;
+            try {
+                PdfDictionary names = new PdfDictionary();
+                if (localDestinations.size() > 0) {
+                    PdfArray ar = new PdfArray();
+                    for (Iterator i = localDestinations.keySet().iterator(); i.hasNext();) {
+                        String name = (String)i.next();
+                        Object obj[] = (Object[])localDestinations.get(name);
+                        PdfIndirectReference ref = (PdfIndirectReference)obj[1];
+                        ar.add(new PdfString(name));
+                        ar.add(ref);
+                    }
+                    PdfDictionary dests = new PdfDictionary();
+                    dests.put(PdfName.NAMES, ar);
+                    names.put(PdfName.DESTS, writer.addToBody(dests).getIndirectReference());
+                }
+                if (documentJavaScript.size() > 0) {
+                    String s[] = new String[documentJavaScript.size()];
+                    for (int k = 0; k < s.length; ++k)
+                        s[k] = Integer.toHexString(k);
+                    Arrays.sort(s, new StringCompare());
+                    PdfArray ar = new PdfArray();
+                    for (int k = 0; k < s.length; ++k) {
+                        ar.add(new PdfString(s[k]));
+                        ar.add((PdfIndirectReference)documentJavaScript.get(k));
+                    }
+                    PdfDictionary js = new PdfDictionary();
+                    js.put(PdfName.NAMES, ar);
+                    names.put(PdfName.JAVASCRIPT, writer.addToBody(js).getIndirectReference());
+                }
+                put(PdfName.NAMES, writer.addToBody(names).getIndirectReference());
+            }
+            catch (IOException e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+        
+        /** Sets the viewer preferences as the sum of several constants.
+         * @param preferences the viewer preferences
+         * @see PdfWriter#setViewerPreferences
+         */
+        
+        void setViewerPreferences(int preferences) {
+            PdfReader.setViewerPreferences(preferences, this);
+        }
+        
+        void setOpenAction(PdfAction action) {
+            put(PdfName.OPENACTION, action);
+        }
+        
+        
+        /** Sets the document level additional actions.
+         * @param actions   dictionary of actions
+         */
+        void setAdditionalActions(PdfDictionary actions) {
+            try {
+                put(PdfName.AA, writer.addToBody(actions).getIndirectReference());
+            } catch (Exception e) {
+                new ExceptionConverter(e);
+            }
+        }
+        
+        
+        void setPageLabels(PdfPageLabels pageLabels) {
+            put(PdfName.PAGELABELS, pageLabels.getDictionary());
+        }
+        
+        void setAcroForm(PdfObject fields) {
+            put(PdfName.ACROFORM, fields);
+        }
+    }
+    
+    // membervariables
+    private PdfIndirectReference thumb;
+    
+    /** The characters to be applied the hanging ponctuation. */
+    static final String hangingPunctuation = ".,;:'";
+    
+    /** The <CODE>PdfWriter</CODE>. */
+    private PdfWriter writer;
+    
+    /** some meta information about the Document. */
+    private PdfInfo info = new PdfInfo();
+    
+    /** Signals that OnOpenDocument should be called. */
+    private boolean firstPageEvent = true;
+    
+    /** Signals that onParagraph is valid. */
+    private boolean isParagraph = true;
+    
+    // Horizontal line
+    
+    /** The line that is currently being written. */
+    private PdfLine line = null;
+    
+    /** This represents the current indentation of the PDF Elements on the left side. */
+    private float indentLeft = 0;
+    
+    /** This represents the current indentation of the PDF Elements on the right side. */
+    private float indentRight = 0;
+    
+    /** This represents the current indentation of the PDF Elements on the left side. */
+    private float listIndentLeft = 0;
+    
+    /** This represents the current alignment of the PDF Elements. */
+    private int alignment = Element.ALIGN_LEFT;
+    
+    // Vertical lines
+    
+    /** This is the PdfContentByte object, containing the text. */
+    private PdfContentByte text;
+    
+    /** This is the PdfContentByte object, containing the borders and other Graphics. */
+    private PdfContentByte graphics;
+    
+    /** The lines that are written until now. */
+    private ArrayList lines = new ArrayList();
+    
+    /** This represents the leading of the lines. */
+    private float leading = 0;
+    
+    /** This is the current height of the document. */
+    private float currentHeight = 0;
+    
+    /** This represents the current indentation of the PDF Elements on the top side. */
+    private float indentTop = 0;
+    
+    /** This represents the current indentation of the PDF Elements on the bottom side. */
+    private float indentBottom = 0;
+    
+    /** This checks if the page is empty. */
+    private boolean pageEmpty = true;
+    
+    private int textEmptySize;
+    // resources
+    
+    /** This is the size of the next page. */
+    protected Rectangle nextPageSize = null;
+    
+    /** This is the size of the several boxes of the current Page. */
+    protected HashMap thisBoxSize = new HashMap();
+    
+    /** This is the size of the several boxes that will be used in
+     * the next page. */
+    protected HashMap boxSize = new HashMap();
+    
+    /** This are the page resources of the current Page. */
+    protected PageResources pageResources;
+    
+    // images
+    
+    /** This is the image that could not be shown on a previous page. */
+    private Image imageWait = null;
+    
+    /** This is the position where the image ends. */
+    private float imageEnd = -1;
+    
+    /** This is the indentation caused by an image on the left. */
+    private float imageIndentLeft = 0;
+    
+    /** This is the indentation caused by an image on the right. */
+    private float imageIndentRight = 0;
+    
+    // annotations and outlines
+    
+    /** This is the array containing the references to the annotations. */
+    private ArrayList annotations;
+    
+    /** This is an array containg references to some delayed annotations. */
+    private ArrayList delayedAnnotations = new ArrayList();
+    
+    /** This is the AcroForm object. */
+    PdfAcroForm acroForm;
+    
+    /** This is the root outline of the document. */
+    private PdfOutline rootOutline;
+    
+    /** This is the current <CODE>PdfOutline</CODE> in the hierarchy of outlines. */
+    private PdfOutline currentOutline;
+    
+    /** The current active <CODE>PdfAction</CODE> when processing an <CODE>Anchor</CODE>. */
+    private PdfAction currentAction = null;
+    
+    /**
+     * Stores the destinations keyed by name. Value is
+     * <CODE>Object[]{PdfAction,PdfIndirectReference,PdfDestintion}</CODE>.
+     */
+    private TreeMap localDestinations = new TreeMap(new StringCompare());
+    
+    private ArrayList documentJavaScript = new ArrayList();
+    
+    /** these are the viewerpreferences of the document */
+    private int viewerPreferences = 0;
+    
+    private String openActionName;
+    private PdfAction openActionAction;
+    private PdfDictionary additionalActions;
+    private PdfPageLabels pageLabels;
+    
+    //add by Jin-Hsia Yang
+    private boolean isNewpage = false;
+    
+    private float paraIndent = 0;
+    //end add by Jin-Hsia Yang
+    
+    /** margin in x direction starting from the left. Will be valid in the next page */
+    protected float nextMarginLeft;
+    
+    /** margin in x direction starting from the right. Will be valid in the next page */
+    protected float nextMarginRight;
+    
+    /** margin in y direction starting from the top. Will be valid in the next page */
+    protected float nextMarginTop;
+    
+    /** margin in y direction starting from the bottom. Will be valid in the next page */
+    protected float nextMarginBottom;
+    
+/** The duration of the page */
+    protected int duration=-1; // negative values will indicate no duration
+    
+/** The page transition */
+    protected PdfTransition transition=null; 
+    
+    protected PdfDictionary pageAA = null;
+    
+    /** Holds value of property strictImageSequence. */
+    private boolean strictImageSequence = false;    
+
+    /** Holds the type of the last element, that has been added to the document. */
+    private int lastElementType = -1;    
+    
+    
+    // constructors
+    
+    /**
+     * Constructs a new PDF document.
+     * @throws DocumentException on error
+     */
+    
+    public PdfDocument() throws DocumentException {
+        super();
+        addProducer();
+        addCreationDate();
+    }
+    
+    // listener methods
+    
+    /**
+     * Adds a <CODE>PdfWriter</CODE> to the <CODE>PdfDocument</CODE>.
+     *
+     * @param writer the <CODE>PdfWriter</CODE> that writes everything
+     *                     what is added to this document to an outputstream.
+     * @throws DocumentException on error
+     */
+    
+    public void addWriter(PdfWriter writer) throws DocumentException {
+        if (this.writer == null) {
+            this.writer = writer;
+            acroForm = new PdfAcroForm(writer);
+            return;
+        }
+        throw new DocumentException("You can only add a writer to a PdfDocument once.");
+    }
+    
+    /**
+     * Sets the pagesize.
+     *
+     * @param pageSize the new pagesize
+     * @return <CODE>true</CODE> if the page size was set
+     */
+    
+    public boolean setPageSize(Rectangle pageSize) {
+        if (writer != null && writer.isPaused()) {
+            return false;
+        }
+        nextPageSize = new Rectangle(pageSize);
+        return true;
+    }
+    
+    /**
+     * Changes the header of this document.
+     *
+     * @param header the new header
+     */
+    
+    public void setHeader(HeaderFooter header) {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.setHeader(header);
+    }
+    
+    /**
+     * Resets the header of this document.
+     */
+    
+    public void resetHeader() {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.resetHeader();
+    }
+    
+    /**
+     * Changes the footer of this document.
+     *
+     * @param	footer		the new footer
+     */
+    
+    public void setFooter(HeaderFooter footer) {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.setFooter(footer);
+    }
+    
+    /**
+     * Resets the footer of this document.
+     */
+    
+    public void resetFooter() {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.resetFooter();
+    }
+    
+    /**
+     * Sets the page number to 0.
+     */
+    
+    public void resetPageCount() {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.resetPageCount();
+    }
+    
+    /**
+     * Sets the page number.
+     *
+     * @param	pageN		the new page number
+     */
+    
+    public void setPageCount(int pageN) {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        super.setPageCount(pageN);
+    }
+    
+    /**
+     * Sets the <CODE>Watermark</CODE>.
+     *
+     * @param watermark the watermark to add
+     * @return <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
+     */
+    
+    public boolean add(Watermark watermark) {
+        if (writer != null && writer.isPaused()) {
+            return false;
+        }
+        this.watermark = watermark;
+        return true;
+    }
+    
+    /**
+     * Removes the <CODE>Watermark</CODE>.
+     */
+    
+    public void removeWatermark() {
+        if (writer != null && writer.isPaused()) {
+            return;
+        }
+        this.watermark = null;
+    }
+    
+    /**
+     * Sets the margins.
+     *
+     * @param	marginLeft		the margin on the left
+     * @param	marginRight		the margin on the right
+     * @param	marginTop		the margin on the top
+     * @param	marginBottom	the margin on the bottom
+     * @return	a <CODE>boolean</CODE>
+     */
+    
+    public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+        if (writer != null && writer.isPaused()) {
+            return false;
+        }
+        nextMarginLeft = marginLeft;
+        nextMarginRight = marginRight;
+        nextMarginTop = marginTop;
+        nextMarginBottom = marginBottom;
+        return true;
+    }
+    
+    protected PdfArray rotateAnnotations() {
+        PdfArray array = new PdfArray();
+        int rotation = pageSize.getRotation() % 360;
+        int currentPage = writer.getCurrentPageNumber();
+        for (int k = 0; k < annotations.size(); ++k) {
+            PdfAnnotation dic = (PdfAnnotation)annotations.get(k);
+            int page = dic.getPlaceInPage();
+            if (page > currentPage) {
+                delayedAnnotations.add(dic);
+                continue;
+            }
+            if (dic.isForm()) {
+                if (!dic.isUsed()) {
+                    HashMap templates = dic.getTemplates();
+                    if (templates != null)
+                        acroForm.addFieldTemplates(templates);
+                }
+                PdfFormField field = (PdfFormField)dic;
+                if (field.getParent() == null)
+                    acroForm.addDocumentField(field.getIndirectReference());
+            }
+            if (dic.isAnnotation()) {
+                array.add(dic.getIndirectReference());
+                if (!dic.isUsed()) {
+                    PdfRectangle rect = (PdfRectangle)dic.get(PdfName.RECT);
+                    switch (rotation) {
+                        case 90:
+                            dic.put(PdfName.RECT, new PdfRectangle(
+                            pageSize.top() - rect.bottom(),
+                            rect.left(),
+                            pageSize.top() - rect.top(),
+                            rect.right()));
+                            break;
+                        case 180:
+                            dic.put(PdfName.RECT, new PdfRectangle(
+                            pageSize.right() - rect.left(),
+                            pageSize.top() - rect.bottom(),
+                            pageSize.right() - rect.right(),
+                            pageSize.top() - rect.top()));
+                            break;
+                        case 270:
+                            dic.put(PdfName.RECT, new PdfRectangle(
+                            rect.bottom(),
+                            pageSize.right() - rect.left(),
+                            rect.top(),
+                            pageSize.right() - rect.right()));
+                            break;
+                    }
+                }
+            }
+            if (!dic.isUsed()) {
+                dic.setUsed();
+                try {
+                    writer.addToBody(dic, dic.getIndirectReference());
+                }
+                catch (IOException e) {
+                    throw new ExceptionConverter(e);
+                }
+            }
+        }
+        return array;
+    }
+    
+    /**
+     * Makes a new page and sends it to the <CODE>PdfWriter</CODE>.
+     *
+     * @return a <CODE>boolean</CODE>
+     * @throws DocumentException on error
+     */
+    
+    public boolean newPage() throws DocumentException {
+        lastElementType = -1;
+        //add by Jin-Hsia Yang
+        isNewpage = true;
+        //end add by Jin-Hsia Yang
+        if (writer.getDirectContent().size() == 0 && writer.getDirectContentUnder().size() == 0 && (pageEmpty || (writer != null && writer.isPaused()))) {
+            return false;
+        }
+        PdfPageEvent pageEvent = writer.getPageEvent();
+        if (pageEvent != null)
+            pageEvent.onEndPage(writer, this);
+        
+        //Added to inform any listeners that we are moving to a new page (added by David Freels)
+        super.newPage();
+        
+        // the following 2 lines were added by Pelikan Stephan
+        imageIndentLeft = 0;
+        imageIndentRight = 0;
+        
+        // we flush the arraylist with recently written lines
+        flushLines();
+        // we assemble the resources of this pages
+        pageResources.addDefaultColorDiff(writer.getDefaultColorspace());        
+        PdfDictionary resources = pageResources.getResources();
+        // we make a new page and add it to the document
+        if (writer.getPDFXConformance() != PdfWriter.PDFXNONE) {
+            if (thisBoxSize.containsKey("art") && thisBoxSize.containsKey("trim"))
+                throw new PdfXConformanceException("Only one of ArtBox or TrimBox can exist in the page.");
+            if (!thisBoxSize.containsKey("art") && !thisBoxSize.containsKey("trim")) {
+                if (thisBoxSize.containsKey("crop"))
+                    thisBoxSize.put("trim", thisBoxSize.get("crop"));
+                else
+                    thisBoxSize.put("trim", new PdfRectangle(pageSize, pageSize.getRotation()));
+            }
+        }
+        PdfPage page;
+        int rotation = pageSize.getRotation();
+        page = new PdfPage(new PdfRectangle(pageSize, rotation), thisBoxSize, resources, rotation);
+        // we add the transitions
+        if (this.transition!=null) {
+            page.put(PdfName.TRANS, this.transition.getTransitionDictionary());
+            transition = null;
+        }
+        if (this.duration>0) {
+            page.put(PdfName.DUR,new PdfNumber(this.duration));
+            duration = 0;
+        }
+        // we add the page object additional actions
+        if (pageAA != null) {
+            try {
+                page.put(PdfName.AA, writer.addToBody(pageAA).getIndirectReference());
+            }
+            catch (IOException ioe) {
+                throw new ExceptionConverter(ioe);
+            }
+            pageAA = null;
+        }
+        // we add the annotations
+        if (annotations.size() > 0) {
+            PdfArray array = rotateAnnotations();
+            if (array.size() != 0)
+                page.put(PdfName.ANNOTS, array);
+        }
+        // we add the thumbs
+        if (thumb != null) {
+            page.put(PdfName.THUMB, thumb);
+            thumb = null;
+        }
+        if (!open || close) {
+            throw new PdfException("The document isn't open.");
+        }
+        if (text.size() > textEmptySize)
+            text.endText();
+        else
+            text = null;
+        PdfIndirectReference pageReference = writer.add(page, new PdfContents(writer.getDirectContentUnder(), graphics, text, writer.getDirectContent(), pageSize));
+        // we initialize the new page
+        initPage();
+        
+        //add by Jin-Hsia Yang
+        isNewpage = false;
+        //end add by Jin-Hsia Yang
+        
+        return true;
+    }
+    
+    // methods to open and close a document
+    
+    /**
+     * Opens the document.
+     * <P>
+     * You have to open the document before you can begin to add content
+     * to the body of the document.
+     */
+    
+    public void open() {
+        if (!open) {
+            super.open();
+            writer.open();
+            rootOutline = new PdfOutline(writer);
+            currentOutline = rootOutline;
+        }
+        try {
+            initPage();
+        }
+        catch(DocumentException de) {
+            throw new ExceptionConverter(de);
+        }
+    }
+    
+    void outlineTree(PdfOutline outline) throws IOException {
+        outline.setIndirectReference(writer.getPdfIndirectReference());
+        if (outline.parent() != null)
+            outline.put(PdfName.PARENT, outline.parent().indirectReference());
+        ArrayList kids = outline.getKids();
+        int size = kids.size();
+        for (int k = 0; k < size; ++k)
+            outlineTree((PdfOutline)kids.get(k));
+        for (int k = 0; k < size; ++k) {
+            if (k > 0)
+                ((PdfOutline)kids.get(k)).put(PdfName.PREV, ((PdfOutline)kids.get(k - 1)).indirectReference());
+            if (k < size - 1)
+                ((PdfOutline)kids.get(k)).put(PdfName.NEXT, ((PdfOutline)kids.get(k + 1)).indirectReference());
+        }
+        if (size > 0) {
+            outline.put(PdfName.FIRST, ((PdfOutline)kids.get(0)).indirectReference());
+            outline.put(PdfName.LAST, ((PdfOutline)kids.get(size - 1)).indirectReference());
+        }
+        for (int k = 0; k < size; ++k) {
+            PdfOutline kid = (PdfOutline)kids.get(k);
+            writer.addToBody(kid, kid.indirectReference());
+        }
+    }
+    
+    void writeOutlines() throws IOException {
+        if (rootOutline.getKids().size() == 0)
+            return;
+        outlineTree(rootOutline);
+        writer.addToBody(rootOutline, rootOutline.indirectReference());
+    }
+    
+    void traverseOutlineCount(PdfOutline outline) {
+        ArrayList kids = outline.getKids();
+        PdfOutline parent = outline.parent();
+        if (kids.size() == 0) {
+            if (parent != null) {
+                parent.setCount(parent.getCount() + 1);
+            }
+        }
+        else {
+            for (int k = 0; k < kids.size(); ++k) {
+                traverseOutlineCount((PdfOutline)kids.get(k));
+            }
+            if (parent != null) {
+                if (outline.isOpen()) {
+                    parent.setCount(outline.getCount() + parent.getCount() + 1);
+                }
+                else {
+                    parent.setCount(parent.getCount() + 1);
+                    outline.setCount(-outline.getCount());
+                }
+            }
+        }
+    }
+    
+    void calculateOutlineCount() {
+        if (rootOutline.getKids().size() == 0)
+            return;
+        traverseOutlineCount(rootOutline);
+    }
+    /**
+     * Closes the document.
+     * <B>
+     * Once all the content has been written in the body, you have to close
+     * the body. After that nothing can be written to the body anymore.
+     */
+    
+    public void close() {
+        if (close) {
+            return;
+        }
+        try {
+            newPage();
+            if (imageWait != null) newPage();
+            if (annotations.size() > 0)
+                throw new RuntimeException(annotations.size() + " annotations had invalid placement pages.");
+            PdfPageEvent pageEvent = writer.getPageEvent();
+            if (pageEvent != null)
+                pageEvent.onCloseDocument(writer, this);
+            super.close();
+            
+            writer.addLocalDestinations(localDestinations);
+            calculateOutlineCount();
+            writeOutlines();
+        }
+        catch(Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        
+        writer.close();
+    }
+
+    PageResources getPageResources() {
+        return pageResources;
+    }
+    
+    /** Adds a <CODE>PdfPTable</CODE> to the document.
+     * @param ptable the <CODE>PdfPTable</CODE> to be added to the document.
+     * @throws DocumentException on error
+     */
+    void addPTable(PdfPTable ptable) throws DocumentException {
+        ColumnText ct = new ColumnText(writer.getDirectContent());
+        if (currentHeight > 0) {
+            Paragraph p = new Paragraph();
+            p.setLeading(0);
+            ct.addElement(p);
+        }
+        ct.addElement(ptable);
+        boolean he = ptable.isHeadersInEvent();
+        ptable.setHeadersInEvent(true);
+        int loop = 0;
+        while (true) {
+            ct.setSimpleColumn(indentLeft(), indentBottom(), indentRight(), indentTop() - currentHeight);
+            int status = ct.go();
+            if ((status & ColumnText.NO_MORE_TEXT) != 0) {
+                text.moveText(0, ct.getYLine() - indentTop() + currentHeight);
+                currentHeight = indentTop() - ct.getYLine();
+                break;
+            }
+            if (indentTop() - currentHeight == ct.getYLine())
+                ++loop;
+            else
+                loop = 0;
+            if (loop == 3) {
+                add(new Paragraph("ERROR: Infinite table loop"));
+                break;
+            }
+            newPage();
+        }
+        ptable.setHeadersInEvent(he);
+    }
+    
+	/**
+	 * Gets a PdfTable object
+	 * (contributed by dperezcar at fcc.es)
+	 * @param table a high level table object
+	 * @param supportRowAdditions
+	 * @return returns a PdfTable object
+	 * @see PdfWriter#getPdfTable(Table)
+	 */
+
+	PdfTable getPdfTable(Table table, boolean supportRowAdditions) {
+        return new PdfTable(table, indentLeft(), indentRight(), indentTop() - currentHeight, supportRowAdditions);
+	}
+
+	/**
+	 * @see PdfWriter#breakTableIfDoesntFit(PdfTable)
+	 * (contributed by dperezcar at fcc.es)
+	 * @param table				Table to add
+	 * @return true if the table will be broken
+	 * @throws DocumentException
+	 */
+	
+	boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
+		table.updateRowAdditions();
+		// Do we have any full page available?
+		if (!table.hasToFitPageTable() && table.bottom() <= indentBottom) {
+			// Then output that page
+			add(table, true);
+			return true;
+		}
+		return false;
+	}
+    
+	/**
+	 * Adds a new table to 
+	 * @param table				Table to add.  Rendered rows will be deleted after processing.
+	 * @param onlyFirstPage		Render only the first full page
+	 * @throws DocumentException
+	 */
+	
+    private void add(PdfTable table, boolean onlyFirstPage) throws DocumentException {
+        // before every table, we flush all lines
+        flushLines();
+
+		// initialisation of parameters
+		float pagetop = indentTop();
+		float oldHeight = currentHeight;
+		float cellDisplacement;
+		PdfCell cell;
+		PdfContentByte cellGraphics = new PdfContentByte(writer);
+	                    
+		boolean tableHasToFit =
+			table.hasToFitPageTable() ? table.bottom() < indentBottom() : false;
+		if (pageEmpty)
+			tableHasToFit = false;
+		boolean cellsHaveToFit = table.hasToFitPageCells();
+                    
+		// drawing the table
+		ArrayList cells = table.getCells();
+		ArrayList headercells = table.getHeaderCells();
+		// Check if we have removed header cells in a previous call
+		if (headercells.size() > 0 && (cells.size() == 0 || cells.get(0) != headercells.get(0))) {
+			ArrayList allCells = new ArrayList(cells.size()+headercells.size());
+			allCells.addAll(headercells);
+			allCells.addAll(cells);
+			cells = allCells;
+		}
+		while (!cells.isEmpty()) {
+			// initialisation of some extra parameters;
+			float lostTableBottom = 0;
+                        
+			// loop over the cells
+			boolean cellsShown = false;
+			int currentGroupNumber = 0;
+			boolean headerChecked = false;
+			for (ListIterator iterator = cells.listIterator(); iterator.hasNext() && !tableHasToFit;) {
+				cell = (PdfCell) iterator.next();
+				if( cellsHaveToFit ) {
+					if( !cell.isHeader() ) {
+						if (cell.getGroupNumber() != currentGroupNumber) {
+							boolean cellsFit = true;
+							currentGroupNumber = cell.getGroupNumber();
+							int cellCount = 0;
+							while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
+								if (cell.bottom() < indentBottom()) {
+									cellsFit = false;
+								}
+								cell = (PdfCell) iterator.next();
+								cellCount++;
+							}
+							if (!cellsFit) {
+								break;
+							}
+							for (int i = cellCount; i >= 0; i--) {
+								cell = (PdfCell) iterator.previous();
+							}
+						}
+					}
+					else {
+						if( !headerChecked ) {
+							headerChecked = true;
+							boolean cellsFit = true;
+							int cellCount = 0;
+							float firstTop = cell.top();
+							while (cell.isHeader() && cellsFit && iterator.hasNext()) {
+								if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom()) {
+									cellsFit = false;
+								}
+								cell = (PdfCell) iterator.next();
+								cellCount++;
+							}
+							currentGroupNumber = cell.getGroupNumber();
+							while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
+								if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom() - 10.0) {
+									cellsFit = false;
+								}
+								cell = (PdfCell) iterator.next();
+								cellCount++;
+							}
+							for (int i = cellCount; i >= 0; i--) {
+								cell = (PdfCell) iterator.previous();
+							}
+							if (!cellsFit) {
+								while( cell.isHeader() ) {
+									iterator.remove();
+									cell = (PdfCell) iterator.next();
+								}
+								break;
+							}
+						}
+					}
+				}
+				lines = cell.getLines(pagetop, indentBottom());
+				// if there are lines to add, add them
+				if (lines != null && lines.size() > 0) {
+					// we paint the borders of the cells
+					cellsShown = true;
+					cellGraphics.rectangle(cell.rectangle(pagetop, indentBottom()));
+					lostTableBottom = Math.max(cell.bottom(), indentBottom());
+                                
+					// we write the text
+					float cellTop = cell.top(pagetop - oldHeight);
+					text.moveText(0, cellTop);
+					cellDisplacement = flushLines() - cellTop;
+					text.moveText(0, cellDisplacement);
+					if (oldHeight + cellDisplacement > currentHeight) {
+						currentHeight = oldHeight + cellDisplacement;
+					}
+				}
+				ArrayList images = cell.getImages(pagetop, indentBottom());
+				for (Iterator i = images.iterator(); i.hasNext();) {
+					cellsShown = true;
+					Image image = (Image) i.next();
+					addImage(graphics, image, 0, 0, 0, 0, 0, 0);
+				}
+				// if a cell is allready added completely, remove it
+				if (cell.mayBeRemoved()) {
+					iterator.remove();
+				}
+			}
+			tableHasToFit = false;
+			// we paint the graphics of the table after looping through all the cells
+			if (cellsShown) {
+				Rectangle tablerec = new Rectangle(table);
+				tablerec.setBorder(table.border());
+				tablerec.setBorderWidth(table.borderWidth());
+				tablerec.setBorderColor(table.borderColor());
+				tablerec.setBackgroundColor(table.backgroundColor());
+				tablerec.setGrayFill(table.grayFill());
+				PdfContentByte under = writer.getDirectContentUnder();
+				under.rectangle(tablerec.rectangle(top(), indentBottom()));
+				under.add(cellGraphics);
+				// bugfix by Gerald Fehringer: now again add the border for the table
+				// since it might have been covered by cell backgrounds
+				tablerec.setGrayFill(0);
+				tablerec.setBackgroundColor(null);
+				under.rectangle(tablerec.rectangle(top(), indentBottom()));
+				// end bugfix
+			}
+			cellGraphics = new PdfContentByte(null);
+			// if the table continues on the next page
+			if (!cells.isEmpty()) {
+				graphics.setLineWidth(table.borderWidth());
+				if (cellsShown && (table.border() & Rectangle.BOTTOM) == Rectangle.BOTTOM) {
+					// Draw the bottom line
+                                
+					// the color is set to the color of the element
+					Color tColor = table.borderColor();
+					if (tColor != null) {
+						graphics.setColorStroke(tColor);
+					}
+					graphics.moveTo(table.left(), Math.max(table.bottom(), indentBottom()));
+					graphics.lineTo(table.right(), Math.max(table.bottom(), indentBottom()));
+					graphics.stroke();
+					if (tColor != null) {
+						graphics.resetRGBColorStroke();
+					}
+				}
+                            
+				// old page
+				pageEmpty = false;
+				float difference = lostTableBottom;
+                            
+				// new page
+				newPage();
+				// G.F.: if something added in page event i.e. currentHeight > 0
+				float heightCorrection = 0;
+				boolean somethingAdded = false;
+				if (currentHeight > 0) {
+					heightCorrection = 6;
+					currentHeight += heightCorrection;
+					somethingAdded = true;
+					newLine();
+					flushLines();
+					indentTop = currentHeight - leading;
+					currentHeight = 0;
+				}
+				else {
+					flushLines();
+				}
+                            
+				// this part repeats the table headers (if any)
+				int size = headercells.size();
+				if (size > 0) {
+					// this is the top of the headersection
+					cell = (PdfCell) headercells.get(0);
+					float oldTop = cell.top(0);
+					// loop over all the cells of the table header
+					for (int i = 0; i < size; i++) {
+						cell = (PdfCell) headercells.get(i);
+						// calculation of the new cellpositions
+						cell.setTop(indentTop() - oldTop + cell.top(0));
+						cell.setBottom(indentTop() - oldTop + cell.bottom(0));
+						pagetop = cell.bottom();
+						// we paint the borders of the cell
+						cellGraphics.rectangle(cell.rectangle(indentTop(), indentBottom()));
+						// we write the text of the cell
+						ArrayList images = cell.getImages(indentTop(), indentBottom());
+						for (Iterator im = images.iterator(); im.hasNext();) {
+							cellsShown = true;
+							Image image = (Image) im.next();
+							addImage(graphics, image, 0, 0, 0, 0, 0, 0);
+						}
+						lines = cell.getLines(indentTop(), indentBottom());
+						float cellTop = cell.top(indentTop());
+						text.moveText(0, cellTop-heightCorrection);
+						cellDisplacement = flushLines() - cellTop+heightCorrection;
+						text.moveText(0, cellDisplacement);
+					}           
+					currentHeight = indentTop() - pagetop + table.cellspacing();
+					text.moveText(0, pagetop - indentTop() - currentHeight);
+				}
+				else {
+					if (somethingAdded) {
+						pagetop = indentTop();
+						text.moveText(0, -table.cellspacing());
+					}
+				}
+				oldHeight = currentHeight - heightCorrection;
+                            
+				// calculating the new positions of the table and the cells
+				size = Math.min(cells.size(), table.columns());
+				int i = 0;
+				while (i < size) {
+					cell = (PdfCell) cells.get(i);
+					if (cell.top(-table.cellspacing()) > lostTableBottom) {
+						float newBottom = pagetop - difference + cell.bottom();
+						float neededHeight = cell.remainingHeight();
+						if (newBottom > pagetop - neededHeight) {
+							difference += newBottom - (pagetop - neededHeight);
+						}
+					}
+					i++;
+				}
+				size = cells.size();
+				table.setTop(indentTop());
+				table.setBottom(pagetop - difference + table.bottom(table.cellspacing()));
+				for (i = 0; i < size; i++) {
+					cell = (PdfCell) cells.get(i);
+					float newBottom = pagetop - difference + cell.bottom();
+					float newTop = pagetop - difference + cell.top(-table.cellspacing());
+					if (newTop > indentTop() - currentHeight) {
+						newTop = indentTop() - currentHeight;
+					}
+					//float newBottom = newTop - cell.height();
+					cell.setTop(newTop );
+					cell.setBottom(newBottom );
+				}
+				if (onlyFirstPage) {
+					break;
+				}
+			}
+		}
+                    
+        float tableHeight = table.top() - table.bottom();
+        currentHeight = oldHeight + tableHeight;
+        text.moveText(0, -tableHeight );
+        pageEmpty = false;
+    }
+
+    /**
+     * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
+     *
+     * @param element the element to add
+     * @return <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
+     * @throws DocumentException when a document isn't open yet, or has been closed
+     */
+    
+    public boolean add(Element element) throws DocumentException {
+        if (writer != null && writer.isPaused()) {
+            return false;
+        }
+        try {
+            
+            switch(element.type()) {
+                
+                // Information (headers)
+                case Element.HEADER:
+                    info.addkey(((Meta)element).name(), ((Meta)element).content());
+                    break;
+                case Element.TITLE:
+                    info.addTitle(((Meta)element).content());
+                    break;
+                case Element.SUBJECT:
+                    info.addSubject(((Meta)element).content());
+                    break;
+                case Element.KEYWORDS:
+                    info.addKeywords(((Meta)element).content());
+                    break;
+                case Element.AUTHOR:
+                    info.addAuthor(((Meta)element).content());
+                    break;
+                case Element.CREATOR:
+                    info.addCreator(((Meta)element).content());
+                    break;
+                case Element.PRODUCER:
+                    // you can not change the name of the producer
+                    info.addProducer();
+                    break;
+                case Element.CREATIONDATE:
+                    // you can not set the creation date, only reset it
+                    info.addCreationDate();
+                    break;
+                    
+                    // content (text)
+                case Element.CHUNK: {
+                    // if there isn't a current line available, we make one
+                    if (line == null) {
+                        carriageReturn();
+                    }
+                    
+                    // we cast the element to a chunk
+                    PdfChunk chunk = new PdfChunk((Chunk) element, currentAction);
+                    // we try to add the chunk to the line, until we succeed
+                    {
+                        PdfChunk overflow;
+                        while ((overflow = line.add(chunk)) != null) {
+                            carriageReturn();
+                            chunk = overflow;
+                        }
+                    }
+                    pageEmpty = false;
+                    if (chunk.isAttribute(Chunk.NEWPAGE)) {
+                        newPage();
+                    }
+                    break;
+                }
+                case Element.ANCHOR: {
+                    Anchor anchor = (Anchor) element;
+                    String url = anchor.reference();
+                    leading = anchor.leading();
+                    if (url != null) {
+                        currentAction = new PdfAction(url);
+                    }
+                    
+                    // we process the element
+                    element.process(this);
+                    currentAction = null;
+                    break;
+                }
+                case Element.ANNOTATION: {
+                    if (line == null) {
+                        carriageReturn();
+                    }
+                    Annotation annot = (Annotation) element;
+                    switch(annot.annotationType()) {
+                        case Annotation.URL_NET:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((URL) annot.attributes().get(Annotation.URL))));
+                            break;
+                        case Annotation.URL_AS_STRING:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE))));
+                            break;
+                        case Annotation.FILE_DEST:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), (String) annot.attributes().get(Annotation.DESTINATION))));
+                            break;
+                        case Annotation.SCREEN:
+                            boolean sparams[] = (boolean[])annot.attributes().get(Annotation.PARAMETERS);
+                            String fname = (String) annot.attributes().get(Annotation.FILE);
+                            String mimetype = (String) annot.attributes().get(Annotation.MIMETYPE);
+                            PdfFileSpecification fs;
+                            if (sparams[0])
+                                fs = PdfFileSpecification.fileEmbedded(writer, fname, fname, null);
+                            else
+                                fs = PdfFileSpecification.fileExtern(writer, fname);
+                            PdfAnnotation ann = PdfAnnotation.createScreen(writer, new Rectangle(annot.llx(), annot.lly(), annot.urx(), annot.ury()),
+                                    fname, fs, mimetype, sparams[1]);
+                            annotations.add(ann);
+                            break;
+                        case Annotation.FILE_PAGE:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), ((Integer) annot.attributes().get(Annotation.PAGE)).intValue())));
+                            break;
+                        case Annotation.NAMED_DEST:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction(((Integer) annot.attributes().get(Annotation.NAMED)).intValue())));
+                            break;
+                        case Annotation.LAUNCH:
+                            annotations.add(new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.APPLICATION),(String) annot.attributes().get(Annotation.PARAMETERS),(String) annot.attributes().get(Annotation.OPERATION),(String) annot.attributes().get(Annotation.DEFAULTDIR))));
+                            break;
+                        default:
+                            PdfAnnotation an = new PdfAnnotation(writer, annot.llx(indentRight() - line.widthLeft()), annot.lly(indentTop() - currentHeight), annot.urx(indentRight() - line.widthLeft() + 20), annot.ury(indentTop() - currentHeight - 20), new PdfString(annot.title()), new PdfString(annot.content()));
+                            //PdfAnnotation pop = PdfAnnotation.createPopup(writer, new Rectangle(annot.llx(indentRight() - line.widthLeft()), annot.lly(indentTop() - currentHeight), annot.urx(indentRight() - line.widthLeft() + 20), annot.ury(indentTop() - currentHeight - 20)), null, true);
+                            //an.setPopup(pop);
+                            annotations.add(an);
+                            //annotations.add(pop);
+                    }
+                    pageEmpty = false;
+                    break;
+                }
+                case Element.PHRASE: {
+                    // we cast the element to a phrase and set the leading of the document
+                    leading = ((Phrase) element).leading();
+                    // we process the element
+                    element.process(this);
+                    break;
+                }
+                case Element.PARAGRAPH: {
+                    // we cast the element to a paragraph
+                    Paragraph paragraph = (Paragraph) element;
+                    
+                    float spacingBefore = paragraph.spacingBefore();
+                    if (spacingBefore != 0) {
+                        leading = spacingBefore;
+                        carriageReturn();
+                        if (!pageEmpty) {
+                            /*
+                             * Don't add spacing before a paragraph if it's the first
+                             * on the page
+                             */
+                            Chunk space = new Chunk(" ");
+                            space.process(this);
+                            carriageReturn();
+                        }
+                    }
+                    
+                    // we adjust the parameters of the document
+                    alignment = paragraph.alignment();
+                    leading = paragraph.leading();
+                    
+                    carriageReturn();
+                    // we don't want to make orphans/widows
+                    if (currentHeight + line.height() + leading > indentTop() - indentBottom()) {
+                        newPage();
+                    }
+
+                    // Begin added: Bonf (Marc Schneider) 2003-07-29
+                    //carriageReturn();
+                    // End added: Bonf (Marc Schneider) 2003-07-29
+
+                    indentLeft += paragraph.indentationLeft();
+                    indentRight += paragraph.indentationRight();
+                    
+                    // Begin removed: Bonf (Marc Schneider) 2003-07-29
+                    carriageReturn();
+                    // End removed: Bonf (Marc Schneider) 2003-07-29
+
+                    
+                    //add by Jin-Hsia Yang
+                    
+                    paraIndent += paragraph.indentationLeft();
+                    //end add by Jin-Hsia Yang
+                    
+                    PdfPageEvent pageEvent = writer.getPageEvent();
+                    if (pageEvent != null && isParagraph)
+                        pageEvent.onParagraph(writer, this, indentTop() - currentHeight);
+                    
+                    // if a paragraph has to be kept together, we wrap it in a table object
+                    if (paragraph.getKeepTogether()) {
+                        Table table = new Table(1, 1);
+                        table.setOffset(0f);
+                        table.setBorder(Table.NO_BORDER);
+                        table.setWidth(100f);
+                        table.setTableFitsPage(true);
+                        Cell cell = new Cell(paragraph);
+                        cell.setBorder(Table.NO_BORDER);
+                        //patch by Matt Benson 11/01/2002 - 14:32:00
+                        cell.setHorizontalAlignment(paragraph.alignment());
+                        //end patch by Matt Benson
+                        table.addCell(cell);
+                        this.add(table);
+                        break;
+                    }
+                    else
+                        // we process the paragraph
+                        element.process(this);
+                    
+                    //add by Jin-Hsia Yang and blowagie
+                    paraIndent -= paragraph.indentationLeft();
+                    //end add by Jin-Hsia Yang and blowagie
+                    
+                    // Begin removed: Bonf (Marc Schneider) 2003-07-29
+                    //       carriageReturn();
+                    // End removed: Bonf (Marc Schneider) 2003-07-29
+                    
+                    float spacingAfter = paragraph.spacingAfter();
+                    if (spacingAfter != 0) {
+                        leading = spacingAfter;
+                        carriageReturn();
+                        if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+                            /*
+                             * Only add spacing after a paragraph if the extra
+                             * spacing fits on the page.
+                             */
+                            Chunk space = new Chunk(" ");
+                            space.process(this);
+                            carriageReturn();
+                        }
+                        leading = paragraph.leading();      // restore original leading
+                    }
+
+                    if (pageEvent != null && isParagraph)
+                        pageEvent.onParagraphEnd(writer, this, indentTop() - currentHeight);
+                    
+                    alignment = Element.ALIGN_LEFT;
+                    indentLeft -= paragraph.indentationLeft();
+                    indentRight -= paragraph.indentationRight();
+                    
+                    // Begin added: Bonf (Marc Schneider) 2003-07-29
+                    carriageReturn();
+                    // End added: Bonf (Marc Schneider) 2003-07-29
+
+                    //add by Jin-Hsia Yang
+                    
+                    //end add by Jin-Hsia Yang
+                    
+                    break;
+                }
+                case Element.SECTION:
+                case Element.CHAPTER: {
+                    // Chapters and Sections only differ in their constructor
+                    // so we cast both to a Section
+                    Section section = (Section) element;
+                    
+                    boolean hasTitle = section.title() != null;
+                    
+                    // if the section is a chapter, we begin a new page
+                    if (section.isChapter()) {
+                        newPage();
+                    }
+                    // otherwise, we begin a new line
+                    else {
+                        newLine();
+                    }
+
+                    if (hasTitle) {
+                    float fith = indentTop() - currentHeight;
+                    int rotation = pageSize.getRotation();
+                    if (rotation == 90 || rotation == 180)
+                        fith = pageSize.height() - fith;
+                    PdfDestination destination = new PdfDestination(PdfDestination.FITH, fith);
+                    while (currentOutline.level() >= section.depth()) {
+                        currentOutline = currentOutline.parent();
+                    }
+                    PdfOutline outline = new PdfOutline(currentOutline, destination, section.getBookmarkTitle(), section.isBookmarkOpen());
+                    currentOutline = outline;
+                    }
+                    
+                    // some values are set
+                    carriageReturn();
+                    indentLeft += section.indentationLeft();
+                    indentRight += section.indentationRight();
+                    
+                    PdfPageEvent pageEvent = writer.getPageEvent();
+                    if (pageEvent != null)
+                        if (element.type() == Element.CHAPTER)
+                            pageEvent.onChapter(writer, this, indentTop() - currentHeight, section.title());
+                        else
+                            pageEvent.onSection(writer, this, indentTop() - currentHeight, section.depth(), section.title());
+                    
+                    // the title of the section (if any has to be printed)
+                    if (hasTitle) {
+                        isParagraph = false;
+                        add(section.title());
+                        isParagraph = true;
+                    }
+                    indentLeft += section.indentation();
+                    // we process the section
+                    element.process(this);
+                    // some parameters are set back to normal again
+                    indentLeft -= section.indentationLeft() + section.indentation();
+                    indentRight -= section.indentationRight();
+                    
+                    if (pageEvent != null)
+                        if (element.type() == Element.CHAPTER)
+                            pageEvent.onChapterEnd(writer, this, indentTop() - currentHeight);
+                        else
+                            pageEvent.onSectionEnd(writer, this, indentTop() - currentHeight);
+                    
+                    break;
+                }
+                case Element.LIST: {
+                    // we cast the element to a List
+                    List list = (List) element;
+                    // we adjust the document
+                    listIndentLeft += list.indentationLeft();
+                    indentRight += list.indentationRight();
+                    // we process the items in the list
+                    element.process(this);
+                    // some parameters are set back to normal again
+                    listIndentLeft -= list.indentationLeft();
+                    indentRight -= list.indentationRight();
+                    break;
+                }
+                case Element.LISTITEM: {
+                    // we cast the element to a ListItem
+                    ListItem listItem = (ListItem) element;
+                   
+                    float spacingBefore = listItem.spacingBefore();
+                    if (spacingBefore != 0) {
+                        leading = spacingBefore;
+                        carriageReturn();
+                        if (!pageEmpty) {
+                            /*
+                             * Don't add spacing before a paragraph if it's the first
+                             * on the page
+                             */
+                            Chunk space = new Chunk(" ");
+                            space.process(this);
+                            carriageReturn();
+                        }
+                    }
+                   
+                    // we adjust the document
+                    alignment = listItem.alignment();
+                    listIndentLeft += listItem.indentationLeft();
+                    indentRight += listItem.indentationRight();
+                    leading = listItem.leading();
+                    carriageReturn();
+                    // we prepare the current line to be able to show us the listsymbol
+                    line.setListItem(listItem);
+                    // we process the item
+                    element.process(this);
+
+                    float spacingAfter = listItem.spacingAfter();
+                    if (spacingAfter != 0) {
+                        leading = spacingAfter;
+                        carriageReturn();
+                        if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+                            /*
+                             * Only add spacing after a paragraph if the extra
+                             * spacing fits on the page.
+                             */
+                            Chunk space = new Chunk(" ");
+                            space.process(this);
+                            carriageReturn();
+                        }
+                        leading = listItem.leading();      // restore original leading
+                    }
+                   
+                    // if the last line is justified, it should be aligned to the left
+                    //                          if (line.hasToBeJustified()) {
+                    //                                  line.resetAlignment();
+                    //                          }
+                    // some parameters are set back to normal again
+                    carriageReturn();
+                    listIndentLeft -= listItem.indentationLeft();
+                    indentRight -= listItem.indentationRight();
+                    break;
+                }
+                case Element.RECTANGLE: {
+                    Rectangle rectangle = (Rectangle) element;
+                    graphics.rectangle(rectangle);
+                    pageEmpty = false;
+                    break;
+                }
+                case Element.PTABLE: {
+                    PdfPTable ptable = (PdfPTable)element;
+                    if (ptable.size() <= ptable.getHeaderRows())
+                        break; //nothing to do
+
+                    // before every table, we add a new line and flush all lines
+                    ensureNewLine();
+                    flushLines();
+                    addPTable(ptable);                    
+                    pageEmpty = false;
+                    break;
+                }
+                case Element.MULTI_COLUMN_TEXT: {
+                    ensureNewLine();
+                    flushLines();
+                    MultiColumnText multiText = (MultiColumnText) element;
+                    float height = multiText.write(writer.getDirectContent(), this, indentTop() - currentHeight);
+                    currentHeight += height;
+                    text.moveText(0, -1f* height);
+                    pageEmpty = false;
+                    break;
+                }
+                case Element.TABLE : {
+                    
+                    /**
+                     * This is a list of people who worked on the Table functionality.
+                     * To see who did what, please check the CVS repository:
+                     *
+                     * Leslie Baski
+                     * Matt Benson
+                     * Francesco De Milato
+                     * David Freels
+                     * Bruno Lowagie
+                     * Veerendra Namineni
+                     * Geert Poels
+                     * Tom Ring
+                     * Paulo Soares
+                     * Gerald Fehringer
+                     * Steve Appling
+                     */
+	                    
+					PdfTable table;
+                    if (element instanceof PdfTable) {
+                    	// Already pre-rendered
+                    	table = (PdfTable)element;
+						table.updateRowAdditions();
+                    } else if (element instanceof Table) {
+
+                    	try {
+                    		PdfPTable ptable = ((Table)element).createPdfPTable();
+                    		if (ptable.size() <= ptable.getHeaderRows())
+                                break; //nothing to do
+                    		
+                            // before every table, we add a new line and flush all lines
+                            ensureNewLine();
+                            flushLines();
+                            addPTable(ptable);                    
+                            pageEmpty = false;
+                            break;
+                    	}
+                    	catch(BadElementException bee) {
+                    		// constructing the PdfTable
+                            // Before the table, add a blank line using offset or default leading
+                            float offset = ((Table)element).getOffset();
+                            if (Float.isNaN(offset))
+                                offset = leading;
+                            carriageReturn();
+                            lines.add(new PdfLine(indentLeft(), indentRight(), alignment, offset));
+                            currentHeight += offset;
+    	                    table = getPdfTable((Table)element, false);
+                    	}
+					} else {
+						return false;
+					}
+                    add(table, false);
+                    break;
+                }
+                case Element.JPEG:
+                case Element.IMGRAW:
+                case Element.IMGTEMPLATE: {
+                    //carriageReturn(); suggestion by Marc Campforts
+                    add((Image) element);
+                    break;
+                }
+                case Element.GRAPHIC: {
+                    Graphic graphic = (Graphic) element;
+                    graphic.processAttributes(indentLeft(), indentBottom(), indentRight(), indentTop(), indentTop() - currentHeight);
+                    graphics.add(graphic);
+                    pageEmpty = false;
+                    break;
+                }
+                default:
+                    return false;
+            }
+            lastElementType = element.type();
+            return true;
+        }
+        catch(Exception e) {
+            throw new DocumentException(e);
+        }
+    }
+    
+    // methods to add Content
+        
+    /**
+     * Adds an image to the Graphics object.
+     * 
+     * @param graphics the PdfContentByte holding the graphics layer of this PdfDocument
+     * @param image the image
+     * @param a an element of the transformation matrix
+     * @param b an element of the transformation matrix
+     * @param c an element of the transformation matrix
+     * @param d an element of the transformation matrix
+     * @param e an element of the transformation matrix
+     * @param f an element of the transformation matrix
+     * @throws DocumentException
+     */
+    
+    private void addImage(PdfContentByte graphics, Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+        Annotation annotation = image.annotation();
+        if (image.hasAbsolutePosition()) {
+            graphics.addImage(image);
+            if (annotation != null) {
+                annotation.setDimensions(image.absoluteX(), image.absoluteY(), image.absoluteX() + image.scaledWidth(), image.absoluteY() + image.scaledHeight());
+                add(annotation);
+            }
+        }
+        else {
+            graphics.addImage(image, a, b, c, d, e, f);
+            if (annotation != null) {
+                annotation.setDimensions(e, f, e + image.scaledWidth(), f + image.scaledHeight());
+                add(annotation);
+            }
+        }
+    }
+    
+    /**
+     * Adds an image to the document.
+     * @param image the <CODE>Image</CODE> to add
+     * @throws PdfException on error
+     * @throws DocumentException on error
+     */
+    
+    private void add(Image image) throws PdfException, DocumentException {
+        
+        if (image.hasAbsolutePosition()) {
+            addImage(graphics, image, 0, 0, 0, 0, 0, 0);
+            pageEmpty = false;
+            return;
+        }
+        
+        // if there isn't enough room for the image on this page, save it for the next page
+        if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
+            if (!strictImageSequence && imageWait == null) {
+                imageWait = image;
+                return;
+            }
+            newPage();
+            if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
+                imageWait = image;
+                return;
+            }
+        }
+        pageEmpty = false;
+        // avoid endless loops
+        if (image == imageWait)
+            imageWait = null;
+        boolean textwrap = (image.alignment() & Image.TEXTWRAP) == Image.TEXTWRAP
+        && !((image.alignment() & Image.MIDDLE) == Image.MIDDLE);
+        boolean underlying = (image.alignment() & Image.UNDERLYING) == Image.UNDERLYING;
+        float diff = leading / 2;
+        if (textwrap) {
+            diff += leading;
+        }
+        float lowerleft = indentTop() - currentHeight - image.scaledHeight() -diff;
+        float mt[] = image.matrix();
+        float startPosition = indentLeft() - mt[4];
+        if ((image.alignment() & Image.RIGHT) == Image.RIGHT) startPosition = indentRight() - image.scaledWidth() - mt[4];
+        if ((image.alignment() & Image.MIDDLE) == Image.MIDDLE) startPosition = indentLeft() + ((indentRight() - indentLeft() - image.scaledWidth()) / 2) - mt[4];
+        if (image.hasAbsoluteX()) startPosition = image.absoluteX();
+        addImage(graphics, image, mt[0], mt[1], mt[2], mt[3], startPosition, lowerleft - mt[5]);
+        if (textwrap) {
+            if (imageEnd < 0 || imageEnd < currentHeight + image.scaledHeight() + diff) {
+                imageEnd = currentHeight + image.scaledHeight() + diff;
+            }
+            if ((image.alignment() & Image.RIGHT) == Image.RIGHT) {
+            	// indentation suggested by Pelikan Stephan
+                imageIndentRight += image.scaledWidth() + image.indentationLeft();
+            }
+            else {
+            	// indentation suggested by Pelikan Stephan
+                imageIndentLeft += image.scaledWidth() + image.indentationRight();
+            }
+        }
+        if (!(textwrap || underlying)) {
+            currentHeight += image.scaledHeight() + diff;
+            flushLines();
+            text.moveText(0, - (image.scaledHeight() + diff));
+            newLine();
+        }
+    }
+    
+    /**
+     * Initializes a page.
+     * <P>
+     * If the footer/header is set, it is printed.
+     * @throws DocumentException on error
+     */
+    
+    private void initPage() throws DocumentException {
+        
+        // initialisation of some page objects
+        annotations = delayedAnnotations;
+        delayedAnnotations = new ArrayList();
+        pageResources = new PageResources();
+        writer.resetContent();
+        
+        // the pagenumber is incremented
+        pageN++;
+        
+        // graphics and text are initialized
+        float oldleading = leading;
+        int oldAlignment = alignment;
+        
+        if (marginMirroring && (getPageNumber() & 1) == 0) {
+            marginRight = nextMarginLeft;
+            marginLeft = nextMarginRight;
+        }
+        else {
+            marginLeft = nextMarginLeft;
+            marginRight = nextMarginRight;
+        }
+        marginTop = nextMarginTop;
+        marginBottom = nextMarginBottom;
+        imageEnd = -1;
+        imageIndentRight = 0;
+        imageIndentLeft = 0;
+        graphics = new PdfContentByte(writer);
+        text = new PdfContentByte(writer);
+        text.beginText();
+        text.moveText(left(), top());
+        textEmptySize = text.size();
+        text.reset();
+        text.beginText();
+        leading = 16;
+        indentBottom = 0;
+        indentTop = 0;
+        currentHeight = 0;
+        
+        // backgroundcolors, etc...
+        pageSize = nextPageSize;
+        thisBoxSize = new HashMap(boxSize);
+        if (pageSize.backgroundColor() != null
+        || pageSize.hasBorders()
+        || pageSize.borderColor() != null
+        || pageSize.grayFill() > 0) {
+            add(pageSize);
+        }
+        
+        // if there is a watermark, the watermark is added
+        if (watermark != null) {
+            float mt[] = watermark.matrix();
+            addImage(graphics, watermark, mt[0], mt[1], mt[2], mt[3], watermark.offsetX() - mt[4], watermark.offsetY() - mt[5]);
+        }
+        
+        // if there is a footer, the footer is added
+        if (footer != null) {
+			/*
+				Added by Edgar Leonardo Prieto Perilla
+			*/
+			// Avoid footer identation
+			float tmpIndentLeft = indentLeft;
+			float tmpIndentRight = indentRight;
+                        // Begin added: Bonf (Marc Schneider) 2003-07-29
+                        float tmpListIndentLeft = listIndentLeft;
+                        float tmpImageIndentLeft = imageIndentLeft;
+                        float tmpImageIndentRight = imageIndentRight;
+                        // End added: Bonf (Marc Schneider) 2003-07-29
+
+			indentLeft = indentRight = 0;
+                        // Begin added: Bonf (Marc Schneider) 2003-07-29
+                        listIndentLeft = 0;
+                        imageIndentLeft = 0;
+                        imageIndentRight = 0;
+                        // End added: Bonf (Marc Schneider) 2003-07-29
+			/*
+				End Added by Edgar Leonardo Prieto Perilla
+			*/
+
+			footer.setPageNumber(pageN);
+            leading = footer.paragraph().leading();
+            add(footer.paragraph());
+            // adding the footer limits the height
+            indentBottom = currentHeight;
+            text.moveText(left(), indentBottom());
+            flushLines();
+            text.moveText(-left(), -bottom());
+            footer.setTop(bottom(currentHeight));
+            footer.setBottom(bottom() - (0.75f * leading));
+            footer.setLeft(left());
+            footer.setRight(right());
+            graphics.rectangle(footer);
+            indentBottom = currentHeight + leading * 2;
+            currentHeight = 0;
+
+			/*
+				Added by Edgar Leonardo Prieto Perilla
+			*/
+			indentLeft = tmpIndentLeft;
+			indentRight = tmpIndentRight;
+                        // Begin added: Bonf (Marc Schneider) 2003-07-29
+                        listIndentLeft = tmpListIndentLeft;
+                        imageIndentLeft = tmpImageIndentLeft;
+                        imageIndentRight = tmpImageIndentRight;
+                        // End added: Bonf (Marc Schneider) 2003-07-29
+			/*
+				End Added by Edgar Leonardo Prieto Perilla
+			*/
+        }
+        
+        // we move to the left/top position of the page
+        text.moveText(left(), top());
+        
+        // if there is a header, the header = added
+        if (header != null) {
+			/*
+				Added by Edgar Leonardo Prieto Perilla
+			*/
+			// Avoid header identation
+			float tmpIndentLeft = indentLeft;
+			float tmpIndentRight = indentRight;
+                        // Begin added: Bonf (Marc Schneider) 2003-07-29
+                        float tmpListIndentLeft = listIndentLeft;
+                        float tmpImageIndentLeft = imageIndentLeft;
+                        float tmpImageIndentRight = imageIndentRight;
+                        // End added: Bonf (Marc Schneider) 2003-07-29
+
+			indentLeft = indentRight = 0;
+                        //  Added: Bonf
+                        listIndentLeft = 0;
+                        imageIndentLeft = 0;
+                        imageIndentRight = 0;
+                        // End added: Bonf
+			/*
+				End Added by Edgar Leonardo Prieto Perilla
+			*/
+			
+			header.setPageNumber(pageN);
+            leading = header.paragraph().leading();
+            text.moveText(0, leading);
+            add(header.paragraph());
+            newLine();
+            indentTop = currentHeight - leading;
+            header.setTop(top() + leading);
+            header.setBottom(indentTop() + leading * 2 / 3);
+            header.setLeft(left());
+            header.setRight(right());
+            graphics.rectangle(header);
+            flushLines();
+            currentHeight = 0;
+
+			/*
+				Added by Edgar Leonardo Prieto Perilla
+			*/
+			// Restore identation
+			indentLeft = tmpIndentLeft;
+			indentRight = tmpIndentRight;
+                        // Begin added: Bonf (Marc Schneider) 2003-07-29
+                        listIndentLeft = tmpListIndentLeft;
+                        imageIndentLeft = tmpImageIndentLeft;
+                        imageIndentRight = tmpImageIndentRight;
+                        // End added: Bonf (Marc Schneider) 2003-07-29
+			/*
+				End Added by Edgar Leonardo Prieto Perilla
+			*/
+        }
+        
+        pageEmpty = true;
+        
+        // if there is an image waiting to be drawn, draw it
+        try {
+            if (imageWait != null) {
+                add(imageWait);
+                imageWait = null;
+            }
+        }
+        catch(Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        
+        leading = oldleading;
+        alignment = oldAlignment;
+        carriageReturn();
+        PdfPageEvent pageEvent = writer.getPageEvent();
+        if (pageEvent != null) {
+            if (firstPageEvent) {
+                pageEvent.onOpenDocument(writer, this);
+            }
+            pageEvent.onStartPage(writer, this);
+        }
+        firstPageEvent = false;
+    }
+    
+    /**
+     * If the current line is not empty or null, it is added to the arraylist
+     * of lines and a new empty line is added.
+     * @throws DocumentException on error
+     */
+    
+    private void carriageReturn() throws DocumentException {
+        // the arraylist with lines may not be null
+        if (lines == null) {
+            lines = new ArrayList();
+        }
+        // If the current line is not null
+        if (line != null) {
+            // we check if the end of the page is reached (bugfix by Francois Gravel)
+            if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+                // if so nonempty lines are added and the heigt is augmented
+                if (line.size() > 0) {
+                    currentHeight += line.height();
+                    lines.add(line);
+                    pageEmpty = false;
+                }
+            }
+            // if the end of the line is reached, we start a new page
+            else {
+                newPage();
+            }
+        }
+        if (imageEnd > -1 && currentHeight > imageEnd) {
+            imageEnd = -1;
+            imageIndentRight = 0;
+            imageIndentLeft = 0;
+        }
+        // a new current line is constructed
+        line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+    }
+    
+    /**
+     * Adds the current line to the list of lines and also adds an empty line.
+     * @throws DocumentException on error
+     */
+    
+    private void newLine() throws DocumentException {
+        lastElementType = -1;
+        carriageReturn();
+        if (lines != null && lines.size() > 0) {
+            lines.add(line);
+            currentHeight += line.height();
+        }
+        line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+    }
+    
+    /**
+     * Writes all the lines to the text-object.
+     *
+     * @return the displacement that was caused
+     * @throws DocumentException on error
+     */
+    
+    private float flushLines() throws DocumentException {
+        
+        // checks if the ArrayList with the lines is not null
+        if (lines == null) {
+            return 0;
+        }
+        
+        //add by Jin-Hsia Yang
+        boolean newline=false;
+        //end add by Jin-Hsia Yang
+        
+        // checks if a new Line has to be made.
+        if (line != null && line.size() > 0) {
+            lines.add(line);
+            line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+            
+            //add by Jin-Hsia Yang
+            newline=true;
+            //end add by Jin-Hsia Yang
+            
+        }
+        
+        // checks if the ArrayList with the lines is empty
+        if (lines.size() == 0) {
+            return 0;
+        }
+        
+        // initialisation of some parameters
+        Object currentValues[] = new Object[2];
+        PdfFont currentFont = null;
+        float displacement = 0;
+        PdfLine l;
+        PdfChunk chunk;
+        Float lastBaseFactor = new Float(0);
+        currentValues[1] = lastBaseFactor;
+        // looping over all the lines
+        for (Iterator i = lines.iterator(); i.hasNext(); ) {
+            
+            // this is a line in the loop
+            l = (PdfLine) i.next();
+            
+            if(isNewpage && newline) { // fix Ken at PDI
+                newline=false;
+                text.moveText(l.indentLeft() - indentLeft() + listIndentLeft + paraIndent,-l.height());
+            }
+            else {
+                text.moveText(l.indentLeft() - indentLeft() + listIndentLeft, -l.height());
+            }
+            
+            // is the line preceeded by a symbol?
+            if (l.listSymbol() != null) {
+                chunk = l.listSymbol();
+                text.moveText(- l.listIndent(), 0);
+                if (chunk.font().compareTo(currentFont) != 0) {
+                    currentFont = chunk.font();
+                    text.setFontAndSize(currentFont.getFont(), currentFont.size());
+                }
+                if (chunk.color() != null) {
+                    Color color = chunk.color();
+                    text.setColorFill(color);
+                    text.showText(chunk.toString());
+                    text.resetRGBColorFill();
+                }
+                else if (chunk.isImage()) {
+                    Image image = chunk.getImage();
+                    float matrix[] = image.matrix();
+                    float xMarker = text.getXTLM();
+                    float yMarker = text.getYTLM();
+                    matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
+                    matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
+                    addImage(graphics, image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+                }
+                else {
+                    text.showText(chunk.toString());
+                }
+                text.moveText(l.listIndent(), 0);
+            }
+            
+            currentValues[0] = currentFont;
+            
+            writeLineToContent(l, text, graphics, currentValues, writer.getSpaceCharRatio());
+            
+            currentFont = (PdfFont)currentValues[0];
+            
+            displacement += l.height();
+            if (indentLeft() - listIndentLeft != l.indentLeft()) {
+                text.moveText(indentLeft() - l.indentLeft() - listIndentLeft, 0);
+            }
+            
+        }
+        lines = new ArrayList();
+        return displacement;
+    }
+    
+    // methods to retrieve information
+    
+    /**
+     * Gets the <CODE>PdfInfo</CODE>-object.
+     *
+     * @return	<CODE>PdfInfo</COPE>
+     */
+    
+    PdfInfo getInfo() {
+        return info;
+    }
+    
+    /**
+     * Gets the <CODE>PdfCatalog</CODE>-object.
+     *
+     * @param pages an indirect reference to this document pages
+     * @return <CODE>PdfCatalog</CODE>
+     */
+    
+    PdfCatalog getCatalog(PdfIndirectReference pages) {
+        PdfCatalog catalog;
+        if (rootOutline.getKids().size() > 0) {
+            catalog = new PdfCatalog(pages, rootOutline.indirectReference(), writer);
+        }
+        else
+            catalog = new PdfCatalog(pages, writer);
+        if (openActionName != null) {
+            PdfAction action = getLocalGotoAction(openActionName);
+            catalog.setOpenAction(action);
+        }
+        else if (openActionAction != null)
+            catalog.setOpenAction(openActionAction);
+        
+        if (additionalActions != null)   {
+            catalog.setAdditionalActions(additionalActions);
+        }
+        
+        if (pageLabels != null)
+            catalog.setPageLabels(pageLabels);
+        catalog.addNames(localDestinations, documentJavaScript, writer);
+        catalog.setViewerPreferences(viewerPreferences);
+        if (acroForm.isValid()) {
+            try {
+                catalog.setAcroForm(writer.addToBody(acroForm).getIndirectReference());
+            }
+            catch (IOException e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+        return catalog;
+    }
+    
+    // methods concerning the layout
+    
+    /**
+     * Returns the bottomvalue of a <CODE>Table</CODE> if it were added to this document.
+     *
+     * @param	table	the table that may or may not be added to this document
+     * @return	a bottom value
+     */
+    
+    float bottom(Table table) {
+        // where will the table begin?
+        float h = (currentHeight > 0) ? indentTop() - currentHeight - 2f * leading : indentTop();
+        // constructing a PdfTable
+        PdfTable tmp = getPdfTable(table, false);
+        return tmp.bottom();
+    }
+    
+    /**
+     * Checks if a <CODE>PdfPTable</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
+     *
+     * @param	table	the table that has to be checked
+     * @param	margin	a certain margin
+     * @return	<CODE>true</CODE> if the <CODE>PdfPTable</CODE> fits the page, <CODE>false</CODE> otherwise.
+     */
+    
+    boolean fitsPage(PdfPTable table, float margin) {
+            if (!table.isLockedWidth()) {
+                float totalWidth = (indentRight() - indentLeft()) * table.getWidthPercentage() / 100;
+                table.setTotalWidth(totalWidth);
+            }
+        // ensuring that a new line has been started.
+        ensureNewLine();
+            return table.getTotalHeight() <= indentTop() - currentHeight - indentBottom() - margin;
+        }
+    
+    
+    /**
+     * Gets the current vertical page position.
+     * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects 
+     *   for elements that do not terminate the lines they've started because those lines will get
+     *   terminated. 
+     * @return The current vertical page position.
+     */
+    public float getVerticalPosition(boolean ensureNewLine) {
+        // ensuring that a new line has been started.
+        if (ensureNewLine) {
+          ensureNewLine();
+        }
+        return top() -  currentHeight - indentTop;
+    }
+    
+    /**
+     * Ensures that a new line has been started. 
+     */
+    private void ensureNewLine() {
+      try {
+        if ((lastElementType == Element.PHRASE) || 
+            (lastElementType == Element.CHUNK)) {
+          newLine();
+          flushLines();
+        }
+      } catch (DocumentException ex) {
+        throw new ExceptionConverter(ex);
+        }
+    }
+    
+    /**
+     * Gets the indentation on the left side.
+     *
+     * @return	a margin
+     */
+    
+    private float indentLeft() {
+        return left(indentLeft + listIndentLeft + imageIndentLeft);
+    }
+    
+    /**
+     * Gets the indentation on the right side.
+     *
+     * @return	a margin
+     */
+    
+    private float indentRight() {
+        return right(indentRight + imageIndentRight);
+    }
+    
+    /**
+     * Gets the indentation on the top side.
+     *
+     * @return	a margin
+     */
+    
+    private float indentTop() {
+        return top(indentTop);
+    }
+    
+    /**
+     * Gets the indentation on the bottom side.
+     *
+     * @return	a margin
+     */
+    
+    float indentBottom() {
+        return bottom(indentBottom);
+    }
+    
+    /**
+     * Adds a named outline to the document .
+     * @param outline the outline to be added
+     * @param name the name of this local destination
+     */
+    void addOutline(PdfOutline outline, String name) {
+        localDestination(name, outline.getPdfDestination());
+    }
+    
+    /**
+     * Gets the AcroForm object.
+     * @return the PdfAcroform object of the PdfDocument
+     */
+    
+    public PdfAcroForm getAcroForm() {
+        return acroForm;
+    }
+    
+    /**
+     * Gets the root outline. All the outlines must be created with a parent.
+     * The first level is created with this outline.
+     * @return the root outline
+     */
+    public PdfOutline getRootOutline() {
+        return rootOutline;
+    }
+        
+    /**
+     * Writes a text line to the document. It takes care of all the attributes.
+     * <P>
+     * Before entering the line position must have been established and the
+     * <CODE>text</CODE> argument must be in text object scope (<CODE>beginText()</CODE>).
+     * @param line the line to be written
+     * @param text the <CODE>PdfContentByte</CODE> where the text will be written to
+     * @param graphics the <CODE>PdfContentByte</CODE> where the graphics will be written to
+     * @param currentValues the current font and extra spacing values
+     * @param ratio
+     * @throws DocumentException on error
+     */
+    void writeLineToContent(PdfLine line, PdfContentByte text, PdfContentByte graphics, Object currentValues[], float ratio)  throws DocumentException {
+        PdfFont currentFont = (PdfFont)(currentValues[0]);
+        float lastBaseFactor = ((Float)(currentValues[1])).floatValue();
+        PdfChunk chunk;
+        int numberOfSpaces;
+        int lineLen;
+        boolean isJustified;
+        float hangingCorrection = 0;
+        float hScale = 1;
+        float lastHScale = Float.NaN;
+        float baseWordSpacing = 0;
+        float baseCharacterSpacing = 0;
+        
+        numberOfSpaces = line.numberOfSpaces();
+        lineLen = line.toString().length();
+        // does the line need to be justified?
+        isJustified = line.hasToBeJustified() && (numberOfSpaces != 0 || lineLen > 1);
+        if (isJustified) {
+            if (line.isNewlineSplit() && line.widthLeft() >= (lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1))) {
+                if (line.isRTL()) {
+                    text.moveText(line.widthLeft() - lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1), 0);
+                }
+                baseWordSpacing = ratio * lastBaseFactor;
+                baseCharacterSpacing = lastBaseFactor;
+            }
+            else {
+                float width = line.widthLeft();
+                PdfChunk last = line.getChunk(line.size() - 1);
+                if (last != null) {
+                    String s = last.toString();
+                    char c;
+                    if (s.length() > 0 && hangingPunctuation.indexOf((c = s.charAt(s.length() - 1))) >= 0) {
+                        float oldWidth = width;
+                        width += last.font().width(c) * 0.4f;
+                        hangingCorrection = width - oldWidth;
+                    }
+                }
+                float baseFactor = width / (ratio * numberOfSpaces + lineLen - 1);
+                baseWordSpacing = ratio * baseFactor;
+                baseCharacterSpacing = baseFactor;
+                lastBaseFactor = baseFactor;
+            }
+        }
+        
+        int lastChunkStroke = line.getLastStrokeChunk();
+        int chunkStrokeIdx = 0;
+        float xMarker = text.getXTLM();
+        float baseXMarker = xMarker;
+        float yMarker = text.getYTLM();
+        boolean adjustMatrix = false;
+        
+        // looping over all the chunks in 1 line
+        for (Iterator j = line.iterator(); j.hasNext(); ) {
+            chunk = (PdfChunk) j.next();
+            Color color = chunk.color();
+            hScale = 1;
+            
+            if (chunkStrokeIdx <= lastChunkStroke) {
+                float width;
+                if (isJustified) {
+                    width = chunk.getWidthCorrected(baseCharacterSpacing, baseWordSpacing);
+                }
+                else
+                    width = chunk.width();
+                if (chunk.isStroked()) {
+                    PdfChunk nextChunk = line.getChunk(chunkStrokeIdx + 1);
+                    if (chunk.isAttribute(Chunk.UNDERLINE)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.UNDERLINE))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        Object unders[][] = (Object[][])chunk.getAttribute(Chunk.UNDERLINE);
+                        Color scolor = null;
+                        int cap = 0;
+                        for (int k = 0; k < unders.length; ++k) {
+                            Object obj[] = unders[k];
+                            scolor = (Color)obj[0];
+                            float ps[] = (float[])obj[1];
+                            if (scolor == null)
+                                scolor = color;
+                            if (scolor != null)
+                                graphics.setColorStroke(scolor);
+                            float fsize = chunk.font().size();
+                            graphics.setLineWidth(ps[0] + fsize * ps[1]);
+                            float shift = ps[2] + fsize * ps[3];
+                            int cap2 = (int)ps[4];
+                            if (cap2 != 0)
+                                graphics.setLineCap(cap2);
+                            graphics.moveTo(xMarker, yMarker + shift);
+                            graphics.lineTo(xMarker + width - subtract, yMarker + shift);
+                            graphics.stroke();
+                            if (scolor != null)
+                                graphics.resetGrayStroke();
+                            if (cap2 != 0)
+                                graphics.setLineCap(0);
+                        }
+                        graphics.setLineWidth(1);
+                    }
+                    if (chunk.isAttribute(Chunk.ACTION)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.ACTION))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        text.addAnnotation(new PdfAnnotation(writer, xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size(), (PdfAction)chunk.getAttribute(Chunk.ACTION)));
+                    }
+                    if (chunk.isAttribute(Chunk.REMOTEGOTO)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.REMOTEGOTO))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        Object obj[] = (Object[])chunk.getAttribute(Chunk.REMOTEGOTO);
+                        String filename = (String)obj[0];
+                        if (obj[1] instanceof String)
+                            remoteGoto(filename, (String)obj[1], xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+                        else
+                            remoteGoto(filename, ((Integer)obj[1]).intValue(), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+                    }
+                    if (chunk.isAttribute(Chunk.LOCALGOTO)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        localGoto((String)chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+                    }
+                    if (chunk.isAttribute(Chunk.LOCALDESTINATION)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALDESTINATION))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        localDestination((String)chunk.getAttribute(Chunk.LOCALDESTINATION), new PdfDestination(PdfDestination.XYZ, xMarker, yMarker + chunk.font().size(), 0));
+                    }
+                    if (chunk.isAttribute(Chunk.GENERICTAG)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.GENERICTAG))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        Rectangle rect = new Rectangle(xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+                        PdfPageEvent pev = writer.getPageEvent();
+                        if (pev != null)
+                            pev.onGenericTag(writer, this, rect, (String)chunk.getAttribute(Chunk.GENERICTAG));
+                    }
+                    if (chunk.isAttribute(Chunk.BACKGROUND)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.BACKGROUND))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        float fontSize = chunk.font().size();
+                        float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
+                        float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
+                        Object bgr[] = (Object[])chunk.getAttribute(Chunk.BACKGROUND);
+                        graphics.setColorFill((Color)bgr[0]);
+                        float extra[] = (float[])bgr[1];
+                        graphics.rectangle(xMarker - extra[0],
+                            yMarker + descender - extra[1] + chunk.getTextRise(),
+                            width - subtract + extra[0] + extra[2],
+                            ascender - descender + extra[1] + extra[3]);
+                        graphics.fill();
+                        graphics.setGrayFill(0);
+                    }
+                    if (chunk.isAttribute(Chunk.PDFANNOTATION)) {
+                        float subtract = lastBaseFactor;
+                        if (nextChunk != null && nextChunk.isAttribute(Chunk.PDFANNOTATION))
+                            subtract = 0;
+                        if (nextChunk == null)
+                            subtract += hangingCorrection;
+                        float fontSize = chunk.font().size();
+                        float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
+                        float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
+                        PdfAnnotation annot = PdfFormField.shallowDuplicate((PdfAnnotation)chunk.getAttribute(Chunk.PDFANNOTATION));
+                        annot.put(PdfName.RECT, new PdfRectangle(xMarker, yMarker + descender, xMarker + width - subtract, yMarker + ascender));
+                        text.addAnnotation(annot);
+                    }
+                    float params[] = (float[])chunk.getAttribute(Chunk.SKEW);
+                    Float hs = (Float)chunk.getAttribute(Chunk.HSCALE);
+                    if (params != null || hs != null) {
+                        float a = 1, b = 0, c = 0;
+                        if (params != null) {
+                            b = params[0];
+                            c = params[1];
+                        }
+                        if (hs != null)
+                            hScale = hs.floatValue();
+                        text.setTextMatrix(hScale, b, c, 1, xMarker, yMarker);
+                    }
+                    if (chunk.isImage()) {
+                        Image image = chunk.getImage();
+                        float matrix[] = image.matrix();
+                        matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
+                        matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
+                        addImage(graphics, image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+                        text.moveText(xMarker + lastBaseFactor + image.scaledWidth() - text.getXTLM(), 0);
+                    }
+                }
+                xMarker += width;
+                ++chunkStrokeIdx;
+            }
+
+            if (chunk.font().compareTo(currentFont) != 0) {
+                currentFont = chunk.font();
+                text.setFontAndSize(currentFont.getFont(), currentFont.size());
+            }
+            float rise = 0;
+            Object textRender[] = (Object[])chunk.getAttribute(Chunk.TEXTRENDERMODE);
+            int tr = 0;
+            float strokeWidth = 1;
+            Color strokeColor = null;
+            Float fr = (Float)chunk.getAttribute(Chunk.SUBSUPSCRIPT);
+            if (textRender != null) {
+                tr = ((Integer)textRender[0]).intValue() & 3;
+                if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
+                    text.setTextRenderingMode(tr);
+                if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) {
+                    strokeWidth = ((Float)textRender[1]).floatValue();
+                    if (strokeWidth != 1)
+                        text.setLineWidth(strokeWidth);
+                    strokeColor = (Color)textRender[2];
+                    if (strokeColor == null)
+                        strokeColor = color;
+                    if (strokeColor != null)
+                        text.setColorStroke(strokeColor);
+                }
+            }
+            if (fr != null)
+                rise = fr.floatValue();
+            if (color != null)
+                text.setColorFill(color);
+            if (rise != 0)
+                text.setTextRise(rise);
+            if (chunk.isImage()) {
+                adjustMatrix = true;
+            }
+            // If it is a CJK chunk or Unicode TTF we will have to simulate the
+            // space adjustment.
+            else if (isJustified && numberOfSpaces > 0 && chunk.isSpecialEncoding()) {
+                if (hScale != lastHScale) {
+                    lastHScale = hScale;
+                    text.setWordSpacing(baseWordSpacing / hScale);
+                    text.setCharacterSpacing(baseCharacterSpacing / hScale);
+                }
+                String s = chunk.toString();
+                int idx = s.indexOf(' ');
+                if (idx < 0)
+                    text.showText(chunk.toString());
+                else {
+                    float spaceCorrection = - baseWordSpacing * 1000f / chunk.font.size() / hScale;
+                    PdfTextArray textArray = new PdfTextArray(s.substring(0, idx));
+                    int lastIdx = idx;
+                    while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) {
+                        textArray.add(spaceCorrection);
+                        textArray.add(s.substring(lastIdx, idx));
+                        lastIdx = idx;
+                    }
+                    textArray.add(spaceCorrection);
+                    textArray.add(s.substring(lastIdx));
+                    text.showText(textArray);
+                }
+            }
+            else {
+                if (isJustified && hScale != lastHScale) {
+                    lastHScale = hScale;
+                    text.setWordSpacing(baseWordSpacing / hScale);
+                    text.setCharacterSpacing(baseCharacterSpacing / hScale);
+                }
+                text.showText(chunk.toString());
+            }
+            
+            if (rise != 0)
+                text.setTextRise(0);
+            if (color != null)
+                text.resetRGBColorFill();
+            if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
+                text.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
+            if (strokeColor != null)
+                text.resetRGBColorStroke();
+            if (strokeWidth != 1)
+                text.setLineWidth(1);            
+            if (chunk.isAttribute(Chunk.SKEW) || chunk.isAttribute(Chunk.HSCALE)) {
+                adjustMatrix = true;
+                text.setTextMatrix(xMarker, yMarker);
+            }
+        }
+        if (isJustified) {
+            text.setWordSpacing(0);
+            text.setCharacterSpacing(0);
+            if (line.isNewlineSplit())
+                lastBaseFactor = 0;
+        }
+        if (adjustMatrix)
+            text.moveText(baseXMarker - text.getXTLM(), 0);
+        currentValues[0] = currentFont;
+        currentValues[1] = new Float(lastBaseFactor);
+    }
+    
+    /**
+     * Implements a link to other part of the document. The jump will
+     * be made to a local destination with the same name, that must exist.
+     * @param name the name for this link
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    void localGoto(String name, float llx, float lly, float urx, float ury) {
+        PdfAction action = getLocalGotoAction(name);
+        annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, action));
+    }
+    
+    PdfAction getLocalGotoAction(String name) {
+        PdfAction action;
+        Object obj[] = (Object[])localDestinations.get(name);
+        if (obj == null)
+            obj = new Object[3];
+        if (obj[0] == null) {
+            if (obj[1] == null) {
+                obj[1] = writer.getPdfIndirectReference();
+            }
+            action = new PdfAction((PdfIndirectReference)obj[1]);
+            obj[0] = action;
+            localDestinations.put(name, obj);
+        }
+        else {
+            action = (PdfAction)obj[0];
+        }
+        return action;
+    }
+    
+    /**
+     * The local destination to where a local goto with the same
+     * name will jump to.
+     * @param name the name of this local destination
+     * @param destination the <CODE>PdfDestination</CODE> with the jump coordinates
+     * @return <CODE>true</CODE> if the local destination was added,
+     * <CODE>false</CODE> if a local destination with the same name
+     * already existed
+     */
+    boolean localDestination(String name, PdfDestination destination) {
+        Object obj[] = (Object[])localDestinations.get(name);
+        if (obj == null)
+            obj = new Object[3];
+        if (obj[2] != null)
+            return false;
+        obj[2] = destination;
+        localDestinations.put(name, obj);
+        destination.addPage(writer.getCurrentPage());
+        return true;
+    }
+    
+    /**
+     * Implements a link to another document.
+     * @param filename the filename for the remote document
+     * @param name the name to jump to
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
+        annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, name)));
+    }
+    
+    /**
+     * Implements a link to another document.
+     * @param filename the filename for the remote document
+     * @param page the page to jump to
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
+        writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, page)));
+    }
+    
+    /** Sets the viewer preferences as the sum of several constants.
+     * @param preferences the viewer preferences
+     * @see PdfWriter#setViewerPreferences
+     */
+    
+    public void setViewerPreferences(int preferences) {
+        viewerPreferences |= preferences;
+    }
+    
+    /** Implements an action in an area.
+     * @param action the <CODE>PdfAction</CODE>
+     * @param llx the lower left x corner of the activation area
+     * @param lly the lower left y corner of the activation area
+     * @param urx the upper right x corner of the activation area
+     * @param ury the upper right y corner of the activation area
+     */
+    void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
+        writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action));
+    }
+    
+    void setOpenAction(String name) {
+        openActionName = name;
+        openActionAction = null;
+    }
+    
+    void setOpenAction(PdfAction action) {
+        openActionAction = action;
+        openActionName = null;
+    }
+    
+    void addAdditionalAction(PdfName actionType, PdfAction action)  {
+        if (additionalActions == null)  {
+            additionalActions = new PdfDictionary();
+        }
+        if (action == null)
+            additionalActions.remove(actionType);
+        else
+            additionalActions.put(actionType, action);
+        if (additionalActions.size() == 0)
+            additionalActions = null;
+    }
+    
+    void setPageLabels(PdfPageLabels pageLabels) {
+        this.pageLabels = pageLabels;
+    }
+    
+    void addJavaScript(PdfAction js) {
+        if (js.get(PdfName.JS) == null)
+            throw new RuntimeException("Only JavaScript actions are allowed.");
+        try {
+            documentJavaScript.add(writer.addToBody(js).getIndirectReference());
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    void setCropBoxSize(Rectangle crop) {
+        setBoxSize("crop", crop);
+    }
+    
+    void setBoxSize(String boxName, Rectangle size) {
+        if (size == null)
+            boxSize.remove(boxName);
+        else
+            boxSize.put(boxName, new PdfRectangle(size));
+    }
+    
+    void addCalculationOrder(PdfFormField formField) {
+        acroForm.addCalculationOrder(formField);
+    }
+    
+    void setSigFlags(int f) {
+        acroForm.setSigFlags(f);
+    }
+    
+    void addFormFieldRaw(PdfFormField field) {
+        annotations.add(field);
+        ArrayList kids = field.getKids();
+        if (kids != null) {
+            for (int k = 0; k < kids.size(); ++k)
+                addFormFieldRaw((PdfFormField)kids.get(k));
+        }
+    }
+    
+    void addAnnotation(PdfAnnotation annot) {
+        pageEmpty = false;
+        if (annot.isForm()) {
+            PdfFormField field = (PdfFormField)annot;
+            if (field.getParent() == null)
+                addFormFieldRaw(field);
+        }
+        else
+            annotations.add(annot);
+    }
+    
+    /**
+     * Sets the display duration for the page (for presentations)
+     * @param seconds   the number of seconds to display the page
+     */
+    void setDuration(int seconds) {
+        if (seconds > 0)
+            this.duration=seconds;
+        else
+            this.duration=-1;
+    }
+    
+    /**
+     * Sets the transition for the page
+     * @param transition   the PdfTransition object
+     */
+    void setTransition(PdfTransition transition) {
+        this.transition=transition;
+    }
+
+    void setPageAction(PdfName actionType, PdfAction action) {
+        if (pageAA == null) {
+            pageAA = new PdfDictionary();
+        }
+        pageAA.put(actionType, action);
+    }
+    
+    /** Getter for property strictImageSequence.
+     * @return Value of property strictImageSequence.
+     *
+     */
+    boolean isStrictImageSequence() {
+        return this.strictImageSequence;
+    }
+    
+    /** Setter for property strictImageSequence.
+     * @param strictImageSequence New value of property strictImageSequence.
+     *
+     */
+    void setStrictImageSequence(boolean strictImageSequence) {
+        this.strictImageSequence = strictImageSequence;
+    }
+ 
+    void setPageEmpty(boolean pageEmpty) {
+        this.pageEmpty = pageEmpty;
+    }
+	/**
+	 * Method added by Pelikan Stephan
+	 * @see com.lowagie.text.DocListener#clearTextWrap()
+	 */
+	public void clearTextWrap() throws DocumentException {
+		super.clearTextWrap();
+		float tmpHeight = imageEnd - currentHeight;
+		if (line != null) {
+			tmpHeight += line.height();
+		}
+		if ((imageEnd > -1) && (tmpHeight > 0)) {
+			carriageReturn();
+			currentHeight += tmpHeight;
+		}
+	}
+    
+    ArrayList getDocumentJavaScript() {
+        return documentJavaScript;
+    }
+
+    /**
+     * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
+     */
+    public boolean setMarginMirroring(boolean MarginMirroring) {
+        if (writer != null && writer.isPaused()) {
+            return false;
+        }
+        return super.setMarginMirroring(MarginMirroring);
+    }
+    
+    void setThumbnail(Image image) throws PdfException, DocumentException {
+        thumb = writer.getImageReference(writer.addDirectImageSimple(image));
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfEncodings.java b/LibrarySource/com/lowagie/text/pdf/PdfEncodings.java
new file mode 100644
index 0000000..3bd2b30
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfEncodings.java
@@ -0,0 +1,717 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.ExceptionConverter;
+import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+/** Supports fast encodings for winansi and PDFDocEncoding.
+ * Supports conversions from CJK encodings to CID.
+ * Supports custom encodings.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfEncodings {
+    protected static final int CIDNONE = 0;
+    protected static final int CIDRANGE = 1;
+    protected static final int CIDCHAR = 2;
+
+    static final char winansiByteToChar[] = {
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
+        16, 17, 18, 19, 20, 21, 22, 23, 24, 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, 56, 57, 58, 59, 60, 61, 62, 63, 
+        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 
+        80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 
+        96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
+        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 
+        8364, 65533, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 65533, 381, 65533, 
+        65533, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 65533, 382, 376, 
+        160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 
+        176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 
+        192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 
+        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 
+        224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 
+        240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
+        
+    static final char pdfEncodingByteToChar[] = {
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
+        16, 17, 18, 19, 20, 21, 22, 23, 24, 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, 56, 57, 58, 59, 60, 61, 62, 63, 
+        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 
+        80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 
+        96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
+        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 
+        0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
+        0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 65533,
+        0x20ac, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 
+        176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 
+        192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 
+        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 
+        224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 
+        240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
+        
+    static final IntHashtable winansi = new IntHashtable();
+    
+    static final IntHashtable pdfEncoding = new IntHashtable();
+    
+    static final HashMap extraEncodings = new HashMap();
+    
+    static {        
+        for (int k = 128; k < 160; ++k) {
+            char c = winansiByteToChar[k];
+            if (c != 65533)
+                winansi.put(c, k);
+        }
+
+        for (int k = 128; k < 161; ++k) {
+            char c = pdfEncodingByteToChar[k];
+            if (c != 65533)
+                pdfEncoding.put(c, k);
+        }
+        
+        addExtraEncoding("Wingdings", new WingdingsConversion());
+        addExtraEncoding("Symbol", new SymbolConversion(true));
+        addExtraEncoding("ZapfDingbats", new SymbolConversion(false));
+        addExtraEncoding("SymbolTT", new SymbolTTConversion());
+        addExtraEncoding("Cp437", new Cp437Conversion());
+    }
+
+    /** Converts a <CODE>String</CODE> to a </CODE>byte</CODE> array according
+     * to the font's encoding.
+     * @return an array of <CODE>byte</CODE> representing the conversion according to the font's encoding
+     * @param encoding the encoding
+     * @param text the <CODE>String</CODE> to be converted
+     */
+    public static final byte[] convertToBytes(String text, String encoding) {
+        if (text == null)
+            return new byte[0];
+        if (encoding == null || encoding.length() == 0) {
+            int len = text.length();
+            byte b[] = new byte[len];
+            for (int k = 0; k < len; ++k)
+                b[k] = (byte)text.charAt(k);
+            return b;
+        }
+        ExtraEncoding extra = null;
+        synchronized (extraEncodings) {
+            extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
+        }
+        if (extra != null) {
+            byte b[] = extra.charToByte(text, encoding);
+            if (b != null)
+                return b;
+        }
+        IntHashtable hash = null;
+        if (encoding.equals(BaseFont.WINANSI))
+            hash = winansi;
+        else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
+            hash = pdfEncoding;
+        if (hash != null) {
+            char cc[] = text.toCharArray();
+            int len = cc.length;
+            int ptr = 0;
+            byte b[] = new byte[len];
+            int c = 0;
+            for (int k = 0; k < len; ++k) {
+                char char1 = cc[k];
+                if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+                    c = char1;
+                else
+                    c = hash.get(char1);
+                if (c != 0)
+                    b[ptr++] = (byte)c;
+            }
+            if (ptr == len)
+                return b;
+            byte b2[] = new byte[ptr];
+            System.arraycopy(b, 0, b2, 0, ptr);
+            return b2;
+        }
+        if (encoding.equals(PdfObject.TEXT_UNICODE)) {
+            // workaround for jdk 1.2.2 bug
+            char cc[] = text.toCharArray();
+            int len = cc.length;
+            byte b[] = new byte[cc.length * 2 + 2];
+            b[0] = -2;
+            b[1] = -1;
+            int bptr = 2;
+            for (int k = 0; k < len; ++k) {
+                char c = cc[k];
+                b[bptr++] = (byte)(c >> 8);
+                b[bptr++] = (byte)(c & 0xff);
+            }
+            return b;
+        }
+        try {
+            return text.getBytes(encoding);
+        }
+        catch (UnsupportedEncodingException e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /** Converts a </CODE>byte</CODE> array to a <CODE>String</CODE> according
+     * to the some encoding.
+     * @param bytes the bytes to convert
+     * @param encoding the encoding
+     * @return the converted <CODE>String</CODE>
+     */    
+    public static final String convertToString(byte bytes[], String encoding) {
+        if (bytes == null)
+            return PdfObject.NOTHING;
+        if (encoding == null || encoding.length() == 0) {
+            char c[] = new char[bytes.length];
+            for (int k = 0; k < bytes.length; ++k)
+                c[k] = (char)(bytes[k] & 0xff);
+            return new String(c);
+        }
+        ExtraEncoding extra = null;
+        synchronized (extraEncodings) {
+            extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
+        }
+        if (extra != null) {
+            String text = extra.byteToChar(bytes, encoding);
+            if (text != null)
+                return text;
+        }
+        char ch[] = null;
+        if (encoding.equals(BaseFont.WINANSI))
+            ch = winansiByteToChar;
+        else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
+            ch = pdfEncodingByteToChar;
+        if (ch != null) {
+            int len = bytes.length;
+            char c[] = new char[len];
+            for (int k = 0; k < len; ++k) {
+                c[k] = ch[bytes[k] & 0xff];
+            }
+            return new String(c);
+        }
+        try {
+            return new String(bytes, encoding);
+        }
+        catch (UnsupportedEncodingException e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /** Checks is <CODE>text</CODE> only has PdfDocEncoding characters.
+     * @param text the <CODE>String</CODE> to test
+     * @return <CODE>true</CODE> if only PdfDocEncoding characters are present
+     */    
+    public static boolean isPdfDocEncoding(String text) {
+        if (text == null)
+            return true;
+        int len = text.length();
+        for (int k = 0; k < len; ++k) {
+            char char1 = text.charAt(k);
+            if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+                continue;
+            if (!pdfEncoding.containsKey(char1))
+                return false;
+        }
+        return true;
+    }
+    
+    static final HashMap cmaps = new HashMap();
+    /** Assumes that '\\n' and '\\r\\n' are the newline sequences. It may not work for
+     * all CJK encodings. To be used with loadCmap().
+     */    
+    public static final byte CRLF_CID_NEWLINE[][] = new byte[][]{{(byte)'\n'}, {(byte)'\r', (byte)'\n'}};
+
+    /** Clears the CJK cmaps from the cache. If <CODE>name</CODE> is the
+     * empty string then all the cache is cleared. Calling this method
+     * has no consequences other than the need to reload the cmap
+     * if needed.
+     * @param name the name of the cmap to clear or all the cmaps if the empty string
+     */    
+    public static void clearCmap(String name) {
+        synchronized (cmaps) {
+            if (name.length() == 0)
+                cmaps.clear();
+            else
+                cmaps.remove(name);
+        }
+    }
+    
+    /** Loads a CJK cmap to the cache with the option of associating
+     * sequences to the newline.
+     * @param name the CJK cmap name
+     * @param newline the sequences to be replaced bi a newline in the resulting CID. See <CODE>CRLF_CID_NEWLINE</CODE>
+     */    
+    public static void loadCmap(String name, byte newline[][]) {
+        try {
+            char planes[][] = null;
+            synchronized (cmaps) {
+                planes = (char[][])cmaps.get(name);
+            }
+            if (planes == null) {
+                planes = readCmap(name, (byte[][])newline);
+                synchronized (cmaps) {
+                    cmaps.put(name, planes);
+                }
+            }
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }        
+    }
+    
+    /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
+     * to a CID string. This is needed to reach some CJK characters
+     * that don't exist in 16 bit Unicode.</p>
+     * The font to use this result must use the encoding "Identity-H"
+     * or "Identity-V".</p>
+     * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
+     * @param name the CJK encoding name
+     * @param seq the <CODE>byte</CODE> array to be decoded
+     * @return the CID string
+     */    
+    public static String convertCmap(String name, byte seq[]) {
+        return convertCmap(name, seq, 0, seq.length);
+    }
+    
+    /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
+     * to a CID string. This is needed to reach some CJK characters
+     * that don't exist in 16 bit Unicode.</p>
+     * The font to use this result must use the encoding "Identity-H"
+     * or "Identity-V".</p>
+     * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
+     * @param name the CJK encoding name
+     * @param start the start offset in the data
+     * @param length the number of bytes to convert
+     * @param seq the <CODE>byte</CODE> array to be decoded
+     * @return the CID string
+     */    
+    public static String convertCmap(String name, byte seq[], int start, int length) {
+        try {
+            char planes[][] = null;
+            synchronized (cmaps) {
+                planes = (char[][])cmaps.get(name);
+            }
+            if (planes == null) {
+                planes = readCmap(name, (byte[][])null);
+                synchronized (cmaps) {
+                    cmaps.put(name, planes);
+                }
+            }
+            return decodeSequence(seq, start, length, planes);
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }        
+    }
+    
+    static String decodeSequence(byte seq[], int start, int length, char planes[][]) {
+        StringBuffer buf = new StringBuffer();
+        int end = start + length;
+        int currentPlane = 0;
+        for (int k = start; k < end; ++k) {
+            int one = (int)seq[k] & 0xff;
+            char plane[] = planes[currentPlane];
+            int cid = plane[one];
+            if ((cid & 0x8000) == 0) {
+                buf.append((char)cid);
+                currentPlane = 0;
+            }
+            else
+                currentPlane = cid & 0x7fff;
+        }
+        return buf.toString();
+    }
+
+    static char[][] readCmap(String name, byte newline[][]) throws IOException {
+        ArrayList planes = new ArrayList();
+        planes.add(new char[256]);
+        readCmap(name, planes);
+        if (newline != null) {
+            for (int k = 0; k < newline.length; ++k)
+                encodeSequence(newline[k].length, newline[k], BaseFont.CID_NEWLINE, planes);
+        }
+        char ret[][] = new char[planes.size()][];
+        return (char[][])planes.toArray(ret);
+    }
+    
+    static void readCmap(String name, ArrayList planes) throws IOException {
+        String fullName = BaseFont.RESOURCE_PATH + "cmaps/" + name;
+        InputStream in = BaseFont.getResourceStream(fullName);
+        if (in == null)
+            throw new IOException("The Cmap " + name + " was not found.");
+        encodeStream(in, planes);
+        in.close();
+    }
+    
+    static void encodeStream(InputStream in, ArrayList planes) throws IOException {
+        BufferedReader rd = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));
+        String line = null;
+        int state = CIDNONE;
+        byte seqs[] = new byte[7];
+        while ((line = rd.readLine()) != null) {
+            if (line.length() < 6)
+                continue;
+            switch (state) {
+                case CIDNONE: {
+                    if (line.indexOf("begincidrange") >= 0)
+                        state = CIDRANGE;
+                    else if (line.indexOf("begincidchar") >= 0)
+                        state = CIDCHAR;
+                    else if (line.indexOf("usecmap") >= 0) {
+                        StringTokenizer tk = new StringTokenizer(line);
+                        String t = tk.nextToken();
+                        readCmap(t.substring(1), planes);
+                    }
+                    break;
+                }
+                case CIDRANGE: {
+                    if (line.indexOf("endcidrange") >= 0) {
+                        state = CIDNONE;
+                        break;
+                    }
+                    StringTokenizer tk = new StringTokenizer(line);
+                    String t = tk.nextToken();
+                    int size = t.length() / 2 - 1;
+                    long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
+                    t = tk.nextToken();
+                    long end = Long.parseLong(t.substring(1, t.length() - 1), 16);
+                    t = tk.nextToken();
+                    int cid = Integer.parseInt(t);
+                    for (long k = start; k <= end; ++k) {
+                        breakLong(k, size, seqs);
+                        encodeSequence(size, seqs, (char)cid, planes);
+                        ++cid;
+                    }
+                    break;
+                }
+                case CIDCHAR: {
+                    if (line.indexOf("endcidchar") >= 0) {
+                        state = CIDNONE;
+                        break;
+                    }
+                    StringTokenizer tk = new StringTokenizer(line);
+                    String t = tk.nextToken();
+                    int size = t.length() / 2 - 1;
+                    long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
+                    t = tk.nextToken();
+                    int cid = Integer.parseInt(t);
+                    breakLong(start, size, seqs);
+                    encodeSequence(size, seqs, (char)cid, planes);
+                    break;
+                }
+            }
+        }
+    }
+    
+    static void breakLong(long n, int size, byte seqs[]) {
+        for (int k = 0; k < size; ++k) {
+            seqs[k] = (byte)(n >> ((size - 1 - k) * 8));
+        }
+    }
+
+    static void encodeSequence(int size, byte seqs[], char cid, ArrayList planes) {
+        --size;
+        int nextPlane = 0;
+        for (int idx = 0; idx < size; ++idx) {
+            char plane[] = (char[])planes.get(nextPlane);
+            int one = (int)seqs[idx] & 0xff;
+            char c = plane[one];
+            if (c != 0 && (c & 0x8000) == 0)
+                throw new RuntimeException("Inconsistent mapping.");
+            if (c == 0) {
+                planes.add(new char[256]);
+                c = (char)((planes.size() - 1) | 0x8000);
+                plane[one] = c;
+            }
+            nextPlane = c & 0x7fff;
+        }
+        char plane[] = (char[])planes.get(nextPlane);
+        int one = (int)seqs[size] & 0xff;
+        char c = plane[one];
+        if ((c & 0x8000) != 0)
+            throw new RuntimeException("Inconsistent mapping.");
+        plane[one] = cid;
+    }
+
+    /** Adds an extra encoding.
+     * @param name the name of the encoding. The encoding recognition is case insensitive
+     * @param enc the conversion class
+     */    
+    public static void addExtraEncoding(String name, ExtraEncoding enc) {
+        synchronized (extraEncodings) {
+            extraEncodings.put(name.toLowerCase(), enc);
+        }
+    }
+
+    private static class WingdingsConversion implements ExtraEncoding {
+        
+        public byte[] charToByte(String text, String encoding) {
+            char cc[] = text.toCharArray();
+            byte b[] = new byte[cc.length];
+            int ptr = 0;
+            int len = cc.length;
+            for (int k = 0; k < len; ++k) {
+                char c = cc[k];
+                if (c == ' ')
+                    b[ptr++] = (byte)c;
+                else if (c >= '\u2701' && c <= '\u27BE') {
+                    byte v = table[c - 0x2700];
+                    if (v != 0)
+                        b[ptr++] = v;
+                }
+            }
+            if (ptr == len)
+                return b;
+            byte b2[] = new byte[ptr];
+            System.arraycopy(b, 0, b2, 0, ptr);
+            return b2;
+        }
+        
+        public String byteToChar(byte[] b, String encoding) {
+            return null;
+        }
+
+        private final static byte table[] = {
+            0, 35, 34, 0, 0, 0, 41, 62, 81, 42, 
+            0, 0, 65, 63, 0, 0, 0, 0, 0, -4, 
+            0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 
+            86, 0, 88, 89, 0, 0, 0, 0, 0, 0, 
+            0, 0, -75, 0, 0, 0, 0, 0, -74, 0, 
+            0, 0, -83, -81, -84, 0, 0, 0, 0, 0, 
+            0, 0, 0, 124, 123, 0, 0, 0, 84, 0, 
+            0, 0, 0, 0, 0, 0, 0, -90, 0, 0, 
+            0, 113, 114, 0, 0, 0, 117, 0, 0, 0, 
+            0, 0, 0, 125, 126, 0, 0, 0, 0, 0, 
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+            0, 0, 0, 0, 0, 0, 0, 0, -116, -115, 
+            -114, -113, -112, -111, -110, -109, -108, -107, -127, -126, 
+            -125, -124, -123, -122, -121, -120, -119, -118, -116, -115, 
+            -114, -113, -112, -111, -110, -109, -108, -107, -24, 0, 
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+            0, -24, -40, 0, 0, -60, -58, 0, 0, -16, 
+            0, 0, 0, 0, 0, 0, 0, 0, 0, -36, 
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+            0
+        };
+    }
+
+    private static class Cp437Conversion implements ExtraEncoding {
+        private static IntHashtable c2b = new IntHashtable();
+        
+        public byte[] charToByte(String text, String encoding) {
+            char cc[] = text.toCharArray();
+            byte b[] = new byte[cc.length];
+            int ptr = 0;
+            int len = cc.length;
+            for (int k = 0; k < len; ++k) {
+                char c = cc[k];
+                if (c < ' ')
+                    continue;
+                if (c < 128)
+                    b[ptr++] = (byte)c;
+                else {
+                    byte v = (byte)c2b.get(c);
+                    if (v != 0)
+                        b[ptr++] = v;
+                }
+            }
+            if (ptr == len)
+                return b;
+            byte b2[] = new byte[ptr];
+            System.arraycopy(b, 0, b2, 0, ptr);
+            return b2;
+        }
+        
+        public String byteToChar(byte[] b, String encoding) {
+            int len = b.length;
+            char cc[] = new char[len];
+            int ptr = 0;
+            for (int k = 0; k < len; ++k) {
+                int c = b[k] & 0xff;
+                if (c < ' ')
+                    continue;
+                if (c < 128)
+                    cc[ptr++] = (char)c;
+                else {
+                    char v = table[c - 128];
+                    cc[ptr++] = v;
+                }
+            }
+            return new String(cc, 0, ptr);
+        }
+        
+        private final static char table[] = {
+            '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
+            '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
+            '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
+            '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
+            '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
+            '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
+            '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
+            '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0'
+        };
+        
+        static {
+            for (int k = 0; k < table.length; ++k)
+                c2b.put(table[k], k + 128);
+        }
+    }
+    
+    private static class SymbolConversion implements ExtraEncoding {
+        
+        private static final IntHashtable t1 = new IntHashtable();
+        private static final IntHashtable t2 = new IntHashtable();
+        private IntHashtable translation;
+        
+        SymbolConversion(boolean symbol) {
+            if (symbol)
+                translation = t1;
+            else
+                translation = t2;
+        }
+        
+        public byte[] charToByte(String text, String encoding) {
+            char cc[] = text.toCharArray();
+            byte b[] = new byte[cc.length];
+            int ptr = 0;
+            int len = cc.length;
+            for (int k = 0; k < len; ++k) {
+                char c = cc[k];
+                byte v = (byte)translation.get((int)c);
+                if (v != 0)
+                    b[ptr++] = v;
+            }
+            if (ptr == len)
+                return b;
+            byte b2[] = new byte[ptr];
+            System.arraycopy(b, 0, b2, 0, ptr);
+            return b2;
+        }
+        
+        public String byteToChar(byte[] b, String encoding) {
+            return null;
+        }
+
+        private final static char table1[] = {
+            ' ','!','\u2200','#','\u2203','%','&','\u220b','(',')','*','+',',','-','.','/',
+            '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
+            '\u2245','\u0391','\u0392','\u03a7','\u0394','\u0395','\u03a6','\u0393','\u0397','\u0399','\u03d1','\u039a','\u039b','\u039c','\u039d','\u039f',
+            '\u03a0','\u0398','\u03a1','\u03a3','\u03a4','\u03a5','\u03c2','\u03a9','\u039e','\u03a8','\u0396','[','\u2234',']','\u22a5','_',
+            '\u0305','\u03b1','\u03b2','\u03c7','\u03b4','\u03b5','\u03d5','\u03b3','\u03b7','\u03b9','\u03c6','\u03ba','\u03bb','\u03bc','\u03bd','\u03bf',
+            '\u03c0','\u03b8','\u03c1','\u03c3','\u03c4','\u03c5','\u03d6','\u03c9','\u03be','\u03c8','\u03b6','{','|','}','~','\0',
+            '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+            '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+            '\u20ac','\u03d2','\u2032','\u2264','\u2044','\u221e','\u0192','\u2663','\u2666','\u2665','\u2660','\u2194','\u2190','\u2191','\u2192','\u2193',
+            '\u00b0','\u00b1','\u2033','\u2265','\u00d7','\u221d','\u2202','\u2022','\u00f7','\u2260','\u2261','\u2248','\u2026','\u2502','\u2500','\u21b5',
+            '\u2135','\u2111','\u211c','\u2118','\u2297','\u2295','\u2205','\u2229','\u222a','\u2283','\u2287','\u2284','\u2282','\u2286','\u2208','\u2209',
+            '\u2220','\u2207','\u00ae','\u00a9','\u2122','\u220f','\u221a','\u2022','\u00ac','\u2227','\u2228','\u21d4','\u21d0','\u21d1','\u21d2','\u21d3',
+            '\u25ca','\u2329','\0','\0','\0','\u2211','\u239b','\u239c','\u239d','\u23a1','\u23a2','\u23a3','\u23a7','\u23a8','\u23a9','\u23aa',
+            '\0','\u232a','\u222b','\u2320','\u23ae','\u2321','\u239e','\u239f','\u23a0','\u23a4','\u23a5','\u23a6','\u23ab','\u23ac','\u23ad','\0'
+        };
+
+        private final static char table2[] = {
+            '\u0020','\u2701','\u2702','\u2703','\u2704','\u260e','\u2706','\u2707','\u2708','\u2709','\u261b','\u261e','\u270C','\u270D','\u270E','\u270F',
+            '\u2710','\u2711','\u2712','\u2713','\u2714','\u2715','\u2716','\u2717','\u2718','\u2719','\u271A','\u271B','\u271C','\u271D','\u271E','\u271F',
+            '\u2720','\u2721','\u2722','\u2723','\u2724','\u2725','\u2726','\u2727','\u2605','\u2729','\u272A','\u272B','\u272C','\u272D','\u272E','\u272F',
+            '\u2730','\u2731','\u2732','\u2733','\u2734','\u2735','\u2736','\u2737','\u2738','\u2739','\u273A','\u273B','\u273C','\u273D','\u273E','\u273F',
+            '\u2740','\u2741','\u2742','\u2743','\u2744','\u2745','\u2746','\u2747','\u2748','\u2749','\u274A','\u274B','\u25cf','\u274D','\u25a0','\u274F',
+            '\u2750','\u2751','\u2752','\u25b2','\u25bc','\u25c6','\u2756','\u25d7','\u2758','\u2759','\u275A','\u275B','\u275C','\u275D','\u275E','\u0000',
+            '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+            '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+            '\u0000','\u2761','\u2762','\u2763','\u2764','\u2765','\u2766','\u2767','\u2663','\u2666','\u2665','\u2660','\u2460','\u2461','\u2462','\u2463',
+            '\u2464','\u2465','\u2466','\u2467','\u2468','\u2469','\u2776','\u2777','\u2778','\u2779','\u277A','\u277B','\u277C','\u277D','\u277E','\u277F',
+            '\u2780','\u2781','\u2782','\u2783','\u2784','\u2785','\u2786','\u2787','\u2788','\u2789','\u278A','\u278B','\u278C','\u278D','\u278E','\u278F',
+            '\u2790','\u2791','\u2792','\u2793','\u2794','\u2192','\u2194','\u2195','\u2798','\u2799','\u279A','\u279B','\u279C','\u279D','\u279E','\u279F',
+            '\u27A0','\u27A1','\u27A2','\u27A3','\u27A4','\u27A5','\u27A6','\u27A7','\u27A8','\u27A9','\u27AA','\u27AB','\u27AC','\u27AD','\u27AE','\u27AF',
+            '\u0000','\u27B1','\u27B2','\u27B3','\u27B4','\u27B5','\u27B6','\u27B7','\u27B8','\u27B9','\u27BA','\u27BB','\u27BC','\u27BD','\u27BE','\u0000'
+        };
+
+        static {
+            for (int k = 0; k < table1.length; ++k) {
+                int v = (int)table1[k];
+                if (v != 0)
+                    t1.put(v, k + 32);
+            }
+            for (int k = 0; k < table2.length; ++k) {
+                int v = (int)table2[k];
+                if (v != 0)
+                    t2.put(v, k + 32);
+            }
+        }
+    }
+    
+    private static class SymbolTTConversion implements ExtraEncoding {
+        
+        public byte[] charToByte(String text, String encoding) {
+            char ch[] = text.toCharArray();
+            byte b[] = new byte[ch.length];
+            int ptr = 0;
+            int len = ch.length;
+            for (int k = 0; k < len; ++k) {
+                char c = ch[k];
+                if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+                    b[ptr++] = (byte)c;
+            }
+            if (ptr == len)
+                return b;
+            byte b2[] = new byte[ptr];
+            System.arraycopy(b, 0, b2, 0, ptr);
+            return b2;
+        }
+        
+        public String byteToChar(byte[] b, String encoding) {
+            return null;
+        }
+        
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfEncryption.java b/LibrarySource/com/lowagie/text/pdf/PdfEncryption.java
new file mode 100644
index 0000000..86653f9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfEncryption.java
@@ -0,0 +1,363 @@
+/*
+ * $Id: PdfEncryption.java,v 1.20 2003/03/11 09:33:34 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.security.MessageDigest;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ * @author Kazuya Ujihara
+ */
+public class PdfEncryption {
+    
+    static final byte pad[] = {
+        (byte)0x28, (byte)0xBF, (byte)0x4E, (byte)0x5E, (byte)0x4E, (byte)0x75,
+        (byte)0x8A, (byte)0x41, (byte)0x64, (byte)0x00, (byte)0x4E, (byte)0x56,
+        (byte)0xFF, (byte)0xFA, (byte)0x01, (byte)0x08, (byte)0x2E, (byte)0x2E,
+        (byte)0x00, (byte)0xB6, (byte)0xD0, (byte)0x68, (byte)0x3E, (byte)0x80,
+        (byte)0x2F, (byte)0x0C, (byte)0xA9, (byte)0xFE, (byte)0x64, (byte)0x53,
+        (byte)0x69, (byte)0x7A};
+        
+    byte state[] = new byte[256];
+    int x;
+    int y;
+    /** The encryption key for a particular object/generation */
+    byte key[];
+    /** The encryption key length for a particular object/generation */
+    int keySize;
+    /** The global encryption key */
+    byte mkey[];
+    /** Work area to prepare the object/generation bytes */
+    byte extra[] = new byte[5];
+    /** The message digest algorithm MD5 */
+    MessageDigest md5;
+    /** The encryption key for the owner */
+    byte ownerKey[] = new byte[32];
+    /** The encryption key for the user */
+    byte userKey[] = new byte[32];
+    int permissions;
+    byte documentID[];
+    static long seq = System.currentTimeMillis();
+
+    public PdfEncryption() {
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+
+    public PdfEncryption(PdfEncryption enc) {
+        super();
+        mkey = (byte[])enc.mkey.clone();
+        ownerKey = (byte[])enc.ownerKey.clone();
+        userKey = (byte[])enc.userKey.clone();
+        permissions = enc.permissions;
+        if (enc.documentID != null)
+            documentID = (byte[])enc.documentID.clone();
+    }
+    
+    /**
+     */
+    private byte[] padPassword(byte userPassword[]) {
+        byte userPad[] = new byte[32];
+        if (userPassword == null) {
+            System.arraycopy(pad, 0, userPad, 0, 32);
+        }
+        else {
+            System.arraycopy(userPassword, 0, userPad, 0, Math.min(userPassword.length, 32));
+            if (userPassword.length < 32)
+                System.arraycopy(pad, 0, userPad, userPassword.length, 32 - userPassword.length);
+        }
+
+        return userPad;
+    }
+
+    /**
+     */
+    private byte[] computeOwnerKey(byte userPad[], byte ownerPad[], boolean strength128Bits) {
+        byte ownerKey[] = new byte[32];
+
+        byte digest[] = md5.digest(ownerPad);
+        if (strength128Bits) {
+            byte mkey[] = new byte[16];
+            for (int k = 0; k < 50; ++k)
+                digest = md5.digest(digest);
+            System.arraycopy(userPad, 0, ownerKey, 0, 32);
+            for (int i = 0; i < 20; ++i) {
+                for (int j = 0; j < mkey.length ; ++j)
+                    mkey[j] = (byte)(digest[j] ^ i);
+                prepareRC4Key(mkey);
+                encryptRC4(ownerKey);
+            }
+        }
+        else {
+            prepareRC4Key(digest, 0, 5);
+            encryptRC4(userPad, ownerKey);
+        }
+
+        return ownerKey;
+    }
+
+    /**
+     *
+     * ownerKey, documentID must be setuped
+     */
+    private void setupGlobalEncryptionKey(byte[] documentID, byte userPad[], byte ownerKey[], int permissions, boolean strength128Bits) {
+        this.documentID = documentID;
+        this.ownerKey = ownerKey;
+        this.permissions = permissions;
+        mkey = new byte[strength128Bits ? 16 : 5];
+
+        //fixed by ujihara in order to follow PDF refrence
+        md5.reset();
+        md5.update(userPad);
+        md5.update(ownerKey);
+
+        byte ext[] = new byte[4];
+        ext[0] = (byte)permissions;
+        ext[1] = (byte)(permissions >> 8);
+        ext[2] = (byte)(permissions >> 16);
+        ext[3] = (byte)(permissions >> 24);
+        md5.update(ext, 0, 4);
+        if (documentID != null) md5.update(documentID);
+
+        byte digest[] = md5.digest();
+
+        if (mkey.length == 16) {
+            for (int k = 0; k < 50; ++k)
+                digest = md5.digest(digest);
+        }
+
+        System.arraycopy(digest, 0, mkey, 0, mkey.length);
+    }
+
+    /**
+     *
+     * mkey must be setuped
+     */
+    private void setupUserKey() {
+        if (mkey.length == 16) {
+            md5.update(pad);
+            byte digest[] = md5.digest(documentID);
+            System.arraycopy(digest, 0, userKey, 0, 16);
+            for (int k = 16; k < 32; ++k)
+                userKey[k] = 0;
+            for (int i = 0; i < 20; ++i) {
+                for (int j = 0; j < mkey.length; ++j)
+                    digest[j] = (byte)(mkey[j] ^ i);
+                prepareRC4Key(digest, 0, mkey.length);
+                encryptRC4(userKey, 0, 16);
+            }
+        }
+        else {
+            prepareRC4Key(mkey);
+            encryptRC4(pad, userKey);
+        }
+    }
+
+    public void setupAllKeys(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) {
+        if (ownerPassword == null || ownerPassword.length == 0)
+            ownerPassword = md5.digest(createDocumentId());
+        permissions |= strength128Bits ? 0xfffff0c0 : 0xffffffc0;
+        permissions &= 0xfffffffc;
+        //PDF refrence 3.5.2 Standard Security Handler, Algorithum 3.3-1
+        //If there is no owner password, use the user password instead.
+        byte userPad[] = padPassword(userPassword);
+        byte ownerPad[] = padPassword(ownerPassword);
+
+        this.ownerKey = computeOwnerKey(userPad, ownerPad, strength128Bits);
+        documentID = createDocumentId();
+        setupByUserPad(this.documentID, userPad, this.ownerKey, permissions, strength128Bits);
+    }
+
+    public static byte[] createDocumentId() {
+        MessageDigest md5;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+        }
+        catch (Exception e) {
+             throw new ExceptionConverter(e);
+       }
+        long time = System.currentTimeMillis();
+        long mem = Runtime.getRuntime().freeMemory();
+        String s = time + "+" + mem + "+" + (seq++);
+        return md5.digest(s.getBytes());
+    }
+
+    /**
+     */
+    public void setupByUserPassword(byte[] documentID, byte userPassword[], byte ownerKey[], int permissions, boolean strength128Bits) {
+        setupByUserPad(documentID, padPassword(userPassword), ownerKey, permissions, strength128Bits);
+    }
+
+    /**
+     */
+    private void setupByUserPad(byte[] documentID, byte userPad[], byte ownerKey[], int permissions, boolean strength128Bits) {
+        setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions, strength128Bits);
+        setupUserKey();
+    }
+
+    /**
+     */
+    public void setupByOwnerPassword(byte[] documentID, byte ownerPassword[], byte userKey[], byte ownerKey[], int permissions, boolean strength128Bits) {
+        setupByOwnerPad(documentID, padPassword(ownerPassword), userKey, ownerKey, permissions, strength128Bits);
+    }
+
+    private void setupByOwnerPad(byte[] documentID, byte ownerPad[], byte userKey[], byte ownerKey[], int permissions, boolean strength128Bits) {
+        byte userPad[] = computeOwnerKey(ownerKey, ownerPad, strength128Bits);	//userPad will be set in this.ownerKey
+        setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions, strength128Bits); //step 3
+        setupUserKey();
+    }
+
+    public void prepareKey() {
+        prepareRC4Key(key, 0, keySize);
+    }
+
+    public void setHashKey(int number, int generation) {
+        md5.reset();	//added by ujihara
+        extra[0] = (byte)number;
+        extra[1] = (byte)(number >> 8);
+        extra[2] = (byte)(number >> 16);
+        extra[3] = (byte)generation;
+        extra[4] = (byte)(generation >> 8);
+        md5.update(mkey);
+        key = md5.digest(extra);
+        keySize = mkey.length + 5;
+        if (keySize > 16)
+            keySize = 16;
+    }
+
+    public static PdfObject createInfoId(byte id[]) {
+        ByteBuffer buf = new ByteBuffer(90);
+        buf.append('[').append('<');
+        for (int k = 0; k < 16; ++k)
+            buf.appendHex(id[k]);
+        buf.append('>').append('<');
+        for (int k = 0; k < 16; ++k)
+            buf.appendHex(id[k]);
+        buf.append('>').append(']');
+        return new PdfLiteral(buf.toByteArray());
+    }
+
+    public PdfDictionary getEncryptionDictionary() {
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.FILTER, PdfName.STANDARD);
+        dic.put(PdfName.O, new PdfLiteral(PdfContentByte.escapeString(ownerKey)));
+        dic.put(PdfName.U, new PdfLiteral(PdfContentByte.escapeString(userKey)));
+        dic.put(PdfName.P, new PdfNumber(permissions));
+        if (mkey.length > 5) {
+            dic.put(PdfName.V, new PdfNumber(2));
+            dic.put(PdfName.R, new PdfNumber(3));
+            dic.put(PdfName.LENGTH, new PdfNumber(128));
+        }
+        else {
+            dic.put(PdfName.V, new PdfNumber(1));
+            dic.put(PdfName.R, new PdfNumber(2));
+        }
+        return dic;
+    }
+
+    public void prepareRC4Key(byte key[]) {
+        prepareRC4Key(key, 0, key.length);
+    }
+
+    public void prepareRC4Key(byte key[], int off, int len) {
+        int index1 = 0;
+        int index2 = 0;
+        for (int k = 0; k < 256; ++k)
+            state[k] = (byte)k;
+        x = 0;
+        y = 0;
+        byte tmp;
+        for (int k = 0; k < 256; ++k) {
+            index2 = (key[index1 + off] + state[k] + index2) & 255;
+            tmp = state[k];
+            state[k] = state[index2];
+            state[index2] = tmp;
+            index1 = (index1 + 1) % len;
+        }
+    }
+
+    public void encryptRC4(byte dataIn[], int off, int len, byte dataOut[]) {
+        int length = len + off;
+        byte tmp;
+        for (int k = off; k < length; ++k) {
+            x = (x + 1) & 255;
+            y = (state[x] + y) & 255;
+            tmp = state[x];
+            state[x] = state[y];
+            state[y] = tmp;
+            dataOut[k] = (byte)(dataIn[k] ^ state[(state[x] + state[y]) & 255]);
+        }
+    }
+
+    public void encryptRC4(byte data[], int off, int len) {
+        encryptRC4(data, off, len, data);
+    }
+
+    public void encryptRC4(byte dataIn[], byte dataOut[]) {
+        encryptRC4(dataIn, 0, dataIn.length, dataOut);
+    }
+
+    public void encryptRC4(byte data[]) {
+        encryptRC4(data, 0, data.length, data);
+    }
+    
+    public PdfObject getFileID() {
+        return createInfoId(documentID);
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfEncryptionStream.java b/LibrarySource/com/lowagie/text/pdf/PdfEncryptionStream.java
new file mode 100644
index 0000000..30c2be4
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfEncryptionStream.java
@@ -0,0 +1,85 @@
+/*
+ * $Id: PdfEncryptionStream.java,v 1.3 2005/02/17 09:20:54 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class PdfEncryptionStream extends FilterOutputStream {
+    
+    protected PdfEncryption enc;
+    private byte buf[] = new byte[1];
+    
+    public PdfEncryptionStream(OutputStream out, PdfEncryption enc) {
+        super(out);
+        this.enc = enc;
+    }
+    
+    public void write(byte[] b, int off, int len) throws IOException {
+        if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
+            throw new IndexOutOfBoundsException();
+        enc.encryptRC4(b, off, len);
+        out.write(b, off, len);
+    }
+    
+    public void close() throws IOException {
+    }
+    
+    public void write(int b) throws IOException {
+        buf[0] = (byte)b;
+        write(buf);
+    }
+    
+    public void flush() throws IOException {
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfException.java b/LibrarySource/com/lowagie/text/pdf/PdfException.java
new file mode 100644
index 0000000..6fa0581
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfException.java
@@ -0,0 +1,86 @@
+/*
+ * $Id: PdfException.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.DocumentException;
+
+/**
+ * Signals that an unspecified problem while constructing a PDF document.
+ *
+ * @see		BadPdfFormatException
+ */
+
+public class PdfException extends DocumentException {
+    
+    // constructors
+    
+    public PdfException(Exception ex) {
+        super(ex);
+    }
+
+ /**
+ * Constructs a <CODE>PdfException</CODE> whithout a message.
+ */
+    
+    PdfException() {
+        super();
+    }
+    
+/**
+ * Constructs a <code>PdfException</code> with a message.
+ *
+ * @param		message			a message describing the exception
+ */
+    
+    PdfException(String message) {
+        super(message);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfFileSpecification.java b/LibrarySource/com/lowagie/text/pdf/PdfFileSpecification.java
new file mode 100644
index 0000000..c951df9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfFileSpecification.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.net.URL;
+/** Specifies a file or an URL. The file can be extern or embedded.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfFileSpecification extends PdfDictionary {
+    protected PdfWriter writer;
+    protected PdfIndirectReference ref;
+    
+    /** Creates a new instance of PdfFileSpecification. The static methods are preferred. */
+    public PdfFileSpecification() {
+        super(PdfName.FILESPEC);
+    }
+    
+    /**
+     * Creates a file specification of type URL.
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @param url the URL
+     * @return the file specification
+     */    
+    public static PdfFileSpecification url(PdfWriter writer, String url) {
+        PdfFileSpecification fs = new PdfFileSpecification();
+        fs.writer = writer;
+        fs.put(PdfName.FS, PdfName.URL);
+        fs.put(PdfName.F, new PdfString(url));
+        return fs;
+    }
+
+    /**
+     * Creates a file specification with the file embedded. The file may
+     * come from the file system or from a byte array. The data is flate compressed.
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @param filePath the file path
+     * @param fileDisplay the file information that is presented to the user
+     * @param fileStore the byte array with the file. If it is not <CODE>null</CODE>
+     * it takes precedence over <CODE>filePath</CODE>
+     * @throws IOException on error
+     * @return the file specification
+     */    
+    public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[]) throws IOException {
+        return fileEmbedded(writer, filePath, fileDisplay, fileStore, true);
+    }
+    
+    
+    /**
+     * Creates a file specification with the file embedded. The file may
+     * come from the file system or from a byte array.
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @param filePath the file path
+     * @param fileDisplay the file information that is presented to the user
+     * @param fileStore the byte array with the file. If it is not <CODE>null</CODE>
+     * it takes precedence over <CODE>filePath</CODE>
+     * @param compress sets the compression on the data. Multimedia content will benefit little
+     * from compression
+     * @throws IOException on error
+     * @return the file specification
+     */    
+    public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[], boolean compress) throws IOException {
+        PdfFileSpecification fs = new PdfFileSpecification();
+        fs.writer = writer;
+        fs.put(PdfName.F, new PdfString(fileDisplay));
+        PdfStream stream;
+        InputStream in = null;
+        PdfIndirectReference ref;
+        try {
+            if (fileStore == null) {
+                File file = new File(filePath);
+                if (file.canRead()) {
+                    in = new FileInputStream(filePath);
+                }
+                else {
+                    if (filePath.startsWith("file:/") || filePath.startsWith("http://") || filePath.startsWith("https://") || filePath.startsWith("jar:")) {
+                        in = new URL(filePath).openStream();
+                    }
+                    else {
+                        in = BaseFont.getResourceStream(filePath);
+                        if (in == null)
+                            throw new IOException(filePath + " not found as file or resource.");
+                    }
+                }
+                stream = new PdfStream(in, writer);
+            }
+            else
+                stream = new PdfStream(fileStore);
+            stream.put(PdfName.TYPE, PdfName.EMBEDDEDFILE);
+            if (compress)
+                stream.flateCompress();
+            ref = writer.addToBody(stream).getIndirectReference();
+            if (fileStore == null) {
+                stream.writeLength();
+            }
+        }
+        finally {
+            if (in != null)
+                try{in.close();}catch(Exception e){}
+        }
+        PdfDictionary f = new PdfDictionary();
+        f.put(PdfName.F, ref);
+        fs.put(PdfName.EF, f);
+        return fs;
+    }
+    
+    /**
+     * Creates a file specification for an external file.
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @param filePath the file path
+     * @return the file specification
+     */
+    public static PdfFileSpecification fileExtern(PdfWriter writer, String filePath) {
+        PdfFileSpecification fs = new PdfFileSpecification();
+        fs.writer = writer;
+        fs.put(PdfName.F, new PdfString(filePath));
+        return fs;
+    }
+    
+    /**
+     * Gets the indirect reference to this file specification.
+     * Multiple invocations will retrieve the same value.
+     * @throws IOException on error
+     * @return the indirect reference
+     */    
+    public PdfIndirectReference getReference() throws IOException {
+        if (ref != null)
+            return ref;
+        ref = writer.addToBody(this).getIndirectReference();
+        return ref;
+    }
+    
+    /**
+     * Sets the file name (the key /F) string as an hex representation
+     * to support multi byte file names. The name must heve th slash and
+     * backslash escaped according to the file specification rules
+     * @param fileName the file name as a byte array
+     */    
+    public void setMultiByteFileName(byte fileName[]) {
+        put(PdfName.F, new PdfString(fileName).setHexWriting(true));
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfFont.java b/LibrarySource/com/lowagie/text/pdf/PdfFont.java
new file mode 100644
index 0000000..298f8c7
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfFont.java
@@ -0,0 +1,189 @@
+/*
+ * $Id: PdfFont.java,v 1.30 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Image;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * <CODE>PdfFont</CODE> is the Pdf Font object.
+ * <P>
+ * Limitation: in this class only base 14 Type 1 fonts (courier, courier bold, courier oblique,
+ * courier boldoblique, helvetica, helvetica bold, helvetica oblique, helvetica boldoblique,
+ * symbol, times roman, times bold, times italic, times bolditalic, zapfdingbats) and their
+ * standard encoding (standard, MacRoman, (MacExpert,) WinAnsi) are supported.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.7 (page 198-203).
+ *
+ * @see		PdfName
+ * @see		PdfDictionary
+ * @see		BadPdfFormatException
+ */
+
+class PdfFont implements Comparable {
+    
+    
+    /** the font metrics. */
+    private BaseFont font;
+    
+    /** the size. */
+    private float size;
+    
+    /** an image. */
+    protected Image image;
+    
+    protected float hScale = 1;
+    
+    // constructors
+    
+    PdfFont(BaseFont bf, float size) {
+        this.size = size;
+        font = bf;
+    }
+    
+    // methods
+    
+    /**
+     * Compares this <CODE>PdfFont</CODE> with another
+     *
+     * @param	object	the other <CODE>PdfFont</CODE>
+     * @return	a value
+     */
+    
+    public int compareTo(Object object) {
+        if (image != null)
+            return 0;
+        if (object == null) {
+            return -1;
+        }
+        PdfFont pdfFont;
+        try {
+            pdfFont = (PdfFont) object;
+            if (font != pdfFont.font) {
+                return 1;
+            }
+            if (this.size() != pdfFont.size()) {
+                return 2;
+            }
+            return 0;
+        }
+        catch(ClassCastException cce) {
+            return -2;
+        }
+    }
+    
+    /**
+     * Returns the size of this font.
+     *
+     * @return		a size
+     */
+    
+    float size() {
+        if (image == null)
+            return size;
+        else {
+            return image.scaledHeight();
+        }
+    }
+    
+    /**
+     * Returns the approximative width of 1 character of this font.
+     *
+     * @return		a width in Text Space
+     */
+    
+    float width() {
+        return width(' ');
+    }
+    
+    /**
+     * Returns the width of a certain character of this font.
+     *
+     * @param		character	a certain character
+     * @return		a width in Text Space
+     */
+    
+    float width(char character) {
+        if (image == null)
+            return font.getWidthPoint(character, size) * hScale;
+        else
+            return image.scaledWidth();
+    }
+    
+    float width(String s) {
+        if (image == null)
+            return font.getWidthPoint(s, size) * hScale;
+        else
+            return image.scaledWidth();
+    }
+    
+    BaseFont getFont() {
+        return font;
+    }
+    
+    void setImage(Image image) {
+        this.image = image;
+    }
+    
+    static PdfFont getDefaultFont() {
+        try {
+            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
+            return new PdfFont(bf, 12);
+        }
+        catch (Exception ee) {
+            throw new ExceptionConverter(ee);
+        }
+    }
+    void setHorizontalScaling(float hScale) {
+        this.hScale = hScale;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfFormField.java b/LibrarySource/com/lowagie/text/pdf/PdfFormField.java
new file mode 100644
index 0000000..b552ee8
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfFormField.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ * 
+ * Mesquite specific changes/deletions copyright 2005 Peter E. Midford
+ * peteremidford at yahoo.com.  Mesquite itself is copyright 1997-2005 by W. and D.
+ * Maddison and licensed under the LGPL.
+ *  
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.Rectangle;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/** Implements form fields.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfFormField extends PdfAnnotation {
+
+    public static final int FF_READ_ONLY = 1;
+    public static final int FF_REQUIRED = 2;
+    public static final int FF_NO_EXPORT = 4;
+    public static final int FF_NO_TOGGLE_TO_OFF = 16384;
+    public static final int FF_RADIO = 32768;
+    public static final int FF_PUSHBUTTON = 65536;
+    public static final int FF_MULTILINE = 4096;
+    public static final int FF_PASSWORD = 8192;
+    public static final int FF_COMBO = 131072;
+    public static final int FF_EDIT = 262144;
+    public static final int FF_FILESELECT = 1048576;
+    public static final int FF_MULTISELECT = 2097152;
+    public static final int FF_DONOTSPELLCHECK = 4194304;
+    public static final int FF_DONOTSCROLL = 8388608;
+    public static final int FF_COMB = 16777216;
+    public static final int FF_RADIOSINUNISON = 1 << 25;
+    public static final int Q_LEFT = 0;
+    public static final int Q_CENTER = 1;
+    public static final int Q_RIGHT = 2;
+    public static final int MK_NO_ICON = 0;
+    public static final int MK_NO_CAPTION = 1;
+    public static final int MK_CAPTION_BELOW = 2;
+    public static final int MK_CAPTION_ABOVE = 3;
+    public static final int MK_CAPTION_RIGHT = 4;
+    public static final int MK_CAPTION_LEFT = 5;
+    public static final int MK_CAPTION_OVERLAID = 6;
+    public static final PdfName IF_SCALE_ALWAYS = PdfName.A;
+    public static final PdfName IF_SCALE_BIGGER = PdfName.B;
+    public static final PdfName IF_SCALE_SMALLER = PdfName.S;
+    public static final PdfName IF_SCALE_NEVER = PdfName.N;
+    public static final PdfName IF_SCALE_ANAMORPHIC = PdfName.A;
+    public static final PdfName IF_SCALE_PROPORTIONAL = PdfName.P;
+    public static final boolean MULTILINE = true;
+    public static final boolean SINGLELINE = false;
+    public static final boolean PLAINTEXT = false;
+    public static final boolean PASSWORD = true;
+    static PdfName mergeTarget[] = {PdfName.FONT, PdfName.XOBJECT, PdfName.COLORSPACE, PdfName.PATTERN};
+    
+    /** Holds value of property parent. */
+    protected PdfFormField parent;
+    
+    protected ArrayList kids;
+    
+/**
+ * Constructs a new <CODE>PdfAnnotation</CODE> of subtype link (Action).
+ */
+    
+    public PdfFormField(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
+        super(writer, llx, lly, urx, ury, action);
+        put(PdfName.TYPE, PdfName.ANNOT);
+        put(PdfName.SUBTYPE, PdfName.WIDGET);
+        annotation = true;
+    }
+
+    /** Creates new PdfFormField */
+    protected PdfFormField(PdfWriter writer) {
+        super(writer, null);
+        form = true;
+        annotation = false;
+    }
+    
+    public void setWidget(Rectangle rect, PdfName highlight) {
+        put(PdfName.TYPE, PdfName.ANNOT);
+        put(PdfName.SUBTYPE, PdfName.WIDGET);
+        put(PdfName.RECT, new PdfRectangle(rect));
+        annotation = true;
+        if (highlight != null && !highlight.equals(HIGHLIGHT_INVERT))
+            put(PdfName.H, highlight);
+    }
+    
+    public static PdfFormField createEmpty(PdfWriter writer) {
+        PdfFormField field = new PdfFormField(writer);
+        return field;
+    }
+    
+    public void setButton(int flags) {
+        put(PdfName.FT, PdfName.BTN);
+        if (flags != 0)
+            put(PdfName.FF, new PdfNumber(flags));
+    }
+    
+    protected static PdfFormField createButton(PdfWriter writer, int flags) {
+        PdfFormField field = new PdfFormField(writer);
+        field.setButton(flags);
+        return field;
+    }
+    
+    public static PdfFormField createPushButton(PdfWriter writer) {
+        return createButton(writer, FF_PUSHBUTTON);
+    }
+
+    public static PdfFormField createCheckBox(PdfWriter writer) {
+        return createButton(writer, 0);
+    }
+
+    public static PdfFormField createRadioButton(PdfWriter writer, boolean noToggleToOff) {
+        return createButton(writer, FF_RADIO + (noToggleToOff ? FF_NO_TOGGLE_TO_OFF : 0));
+    }
+    
+    public static PdfFormField createTextField(PdfWriter writer, boolean multiline, boolean password, int maxLen) {
+        PdfFormField field = new PdfFormField(writer);
+        field.put(PdfName.FT, PdfName.TX);
+        int flags = (multiline ? FF_MULTILINE : 0);
+        flags += (password ? FF_PASSWORD : 0);
+        field.put(PdfName.FF, new PdfNumber(flags));
+        if (maxLen > 0)
+            field.put(PdfName.MAXLEN, new PdfNumber(maxLen));
+        return field;
+    }
+    
+    protected static PdfFormField createChoice(PdfWriter writer, int flags, PdfArray options, int topIndex) {
+        PdfFormField field = new PdfFormField(writer);
+        field.put(PdfName.FT, PdfName.CH);
+        field.put(PdfName.FF, new PdfNumber(flags));
+        field.put(PdfName.OPT, options);
+        if (topIndex > 0)
+            field.put(PdfName.TI, new PdfNumber(topIndex));
+        return field;
+    }
+    
+    public static PdfFormField createList(PdfWriter writer, String options[], int topIndex) {
+        return createChoice(writer, 0, processOptions(options), topIndex);
+    }
+
+    public static PdfFormField createList(PdfWriter writer, String options[][], int topIndex) {
+        return createChoice(writer, 0, processOptions(options), topIndex);
+    }
+
+    public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[], int topIndex) {
+        return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
+    }
+    
+    public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[][], int topIndex) {
+        return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
+    }
+    
+    protected static PdfArray processOptions(String options[]) {
+        PdfArray array = new PdfArray();
+        for (int k = 0; k < options.length; ++k) {
+            array.add(new PdfString(options[k], PdfObject.TEXT_UNICODE));
+        }
+        return array;
+    }
+    
+    protected static PdfArray processOptions(String options[][]) {
+        PdfArray array = new PdfArray();
+        for (int k = 0; k < options.length; ++k) {
+            String subOption[] = options[k];
+            PdfArray ar2 = new PdfArray(new PdfString(subOption[0], PdfObject.TEXT_UNICODE));
+            ar2.add(new PdfString(subOption[1], PdfObject.TEXT_UNICODE));
+            array.add(ar2);
+        }
+        return array;
+    }
+    
+    public static PdfFormField createSignature(PdfWriter writer) {
+        PdfFormField field = new PdfFormField(writer);
+        field.put(PdfName.FT, PdfName.SIG);
+        return field;
+    }
+    
+    /** Getter for property parent.
+     * @return Value of property parent.
+     */
+    public PdfFormField getParent() {
+        return parent;
+    }
+    
+    public void addKid(PdfFormField field) {
+        field.parent = this;
+        if (kids == null)
+            kids = new ArrayList();
+        kids.add(field);
+    }
+    
+    ArrayList getKids() {
+        return kids;
+    }
+    
+    public int setFieldFlags(int flags) {
+        PdfNumber obj = (PdfNumber)get(PdfName.FF);
+        int old;
+        if (obj == null)
+            old = 0;
+        else
+            old = obj.intValue();
+        int v = old | flags;
+        put(PdfName.FF, new PdfNumber(v));
+        return old;
+    }
+    
+    public void setValueAsString(String s) {
+        put(PdfName.V, new PdfString(s, PdfObject.TEXT_UNICODE));
+    }
+
+    public void setValueAsName(String s) {
+        put(PdfName.V, new PdfName(s));
+    }
+
+	// Removed for mesquite support 25 September 2005 P. E. Midford
+//    public void setValue(PdfSignature sig) {
+//        put(PdfName.V, sig);
+//    }
+
+    public void setDefaultValueAsString(String s) {
+        put(PdfName.DV, new PdfString(s, PdfObject.TEXT_UNICODE));
+    }
+
+    public void setDefaultValueAsName(String s) {
+        put(PdfName.DV, new PdfName(s));
+    }
+    
+    public void setFieldName(String s) {
+        put(PdfName.T, new PdfString(s, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setUserName(String s) {
+        put(PdfName.TU, new PdfString(s, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setMappingName(String s) {
+        put(PdfName.TM, new PdfString(s, PdfObject.TEXT_UNICODE));
+    }
+    
+    public void setQuadding(int v) {
+        put(PdfName.Q, new PdfNumber(v));
+    }
+    
+    static void mergeResources(PdfDictionary result, PdfDictionary source, Object writer) {
+        PdfDictionary dic = null;
+        PdfDictionary res = null;
+        PdfName target = null;
+        for (int k = 0; k < mergeTarget.length; ++k) {
+            target = mergeTarget[k];
+            PdfDictionary pdfDict = (PdfDictionary)PdfReader.getPdfObject(source.get(target));
+            if ((dic = pdfDict) != null) {
+                if ((res = (PdfDictionary)PdfReader.getPdfObject(result.get(target), result)) == null) {
+                    res = new PdfDictionary();
+                }
+                res.mergeDifferent(dic);
+                result.put(target, res);
+              //  if (writer != null)
+              //      writer.markUsed(res);
+            }
+        }
+    }
+
+    static void mergeResources(PdfDictionary result, PdfDictionary source) {
+        mergeResources(result, source, null);
+    }
+
+    void setUsed() {
+        used = true;
+        if (parent != null)
+            put(PdfName.PARENT, parent.getIndirectReference());
+        if (kids != null) {
+            PdfArray array = new PdfArray();
+            for (int k = 0; k < kids.size(); ++k)
+                array.add(((PdfFormField)kids.get(k)).getIndirectReference());
+            put(PdfName.KIDS, array);
+        }
+        if (templates == null)
+            return;
+        PdfDictionary dic = new PdfDictionary();
+        for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
+            PdfTemplate template = (PdfTemplate)it.next();
+            mergeResources(dic, (PdfDictionary)template.getResources());
+        }
+        put(PdfName.DR, dic);
+    }
+
+    public static PdfAnnotation shallowDuplicate(PdfAnnotation annot) {
+        PdfAnnotation dup;
+        if (annot.isForm()) {
+            dup = new PdfFormField(annot.writer);
+            PdfFormField dupField = (PdfFormField)dup;
+            PdfFormField srcField = (PdfFormField)annot;
+            dupField.parent = srcField.parent;
+            dupField.kids = srcField.kids;
+        }
+        else
+            dup = new PdfAnnotation(annot.writer, null);
+        dup.merge(annot);
+        dup.form = annot.form;
+        dup.annotation = annot.annotation;
+        dup.templates = annot.templates;
+        return dup;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfFormXObject.java b/LibrarySource/com/lowagie/text/pdf/PdfFormXObject.java
new file mode 100644
index 0000000..a05a946
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfFormXObject.java
@@ -0,0 +1,105 @@
+/*
+ * $Id: PdfFormXObject.java,v 1.25 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+/**
+ * <CODE>PdfFormObject</CODE> is a type of XObject containing a template-object.
+ */
+
+public class PdfFormXObject extends PdfStream {
+    
+    // public static final variables
+    
+/** This is a PdfNumber representing 0. */
+    public static final PdfNumber ZERO = new PdfNumber(0);
+    
+/** This is a PdfNumber representing 1. */
+    public static final PdfNumber ONE = new PdfNumber(1);
+    
+/** This is the 1 - matrix. */
+    public static final PdfLiteral MATRIX = new PdfLiteral("[1 0 0 1 0 0]");
+    
+    // membervariables
+    
+    
+    // constructor
+    
+/**
+ * Constructs a <CODE>PdfFormXObject</CODE>-object.
+ *
+ * @param		template		the template
+ */
+    
+    PdfFormXObject(PdfTemplate template) // throws BadPdfFormatException
+    {
+        super();
+        put(PdfName.TYPE, PdfName.XOBJECT);
+        put(PdfName.SUBTYPE, PdfName.FORM);
+        put(PdfName.RESOURCES, template.getResources());
+        put(PdfName.BBOX, new PdfRectangle(template.getBoundingBox()));
+        put(PdfName.FORMTYPE, ONE);
+        if (template.getLayer() != null)
+            put(PdfName.OC, template.getLayer().getRef());
+        if (template.getGroup() != null)
+            put(PdfName.GROUP, template.getGroup());
+        PdfArray matrix = template.getMatrix();
+        if (matrix == null)
+            put(PdfName.MATRIX, MATRIX);
+        else
+            put(PdfName.MATRIX, matrix);
+        bytes = template.toPdf(null);
+        put(PdfName.LENGTH, new PdfNumber(bytes.length));
+        flateCompress();
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfFunction.java b/LibrarySource/com/lowagie/text/pdf/PdfFunction.java
new file mode 100644
index 0000000..5956801
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfFunction.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+import java.io.IOException;
+/** Implements PDF functions.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfFunction {
+    
+    protected PdfWriter writer;
+    
+    protected PdfIndirectReference reference;
+    
+    protected PdfDictionary dictionary;
+    
+    /** Creates new PdfFunction */
+    protected PdfFunction(PdfWriter writer) {
+        this.writer = writer;
+    }
+    
+    PdfIndirectReference getReference() {
+        try {
+            if (reference == null) {
+                reference = writer.addToBody(dictionary).getIndirectReference();
+            }
+        }
+        catch (IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+        return reference;
+    }
+        
+    public static PdfFunction type0(PdfWriter writer, float domain[], float range[], int size[],
+        int bitsPerSample, int order, float encode[], float decode[], byte stream[]) {
+        PdfFunction func = new PdfFunction(writer);
+        func.dictionary = new PdfStream(stream);
+        ((PdfStream)func.dictionary).flateCompress();
+        func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(0));
+        func.dictionary.put(PdfName.DOMAIN, new PdfArray(domain));
+        func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+        func.dictionary.put(PdfName.SIZE, new PdfArray(size));
+        func.dictionary.put(PdfName.BITSPERSAMPLE, new PdfNumber(bitsPerSample));
+        if (order != 1)
+            func.dictionary.put(PdfName.ORDER, new PdfNumber(order));
+        if (encode != null)
+            func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
+        if (decode != null)
+            func.dictionary.put(PdfName.DECODE, new PdfArray(decode));
+        return func;
+    }
+
+    public static PdfFunction type2(PdfWriter writer, float domain[], float range[], float c0[], float c1[], float n) {
+        PdfFunction func = new PdfFunction(writer);
+        func.dictionary = new PdfDictionary();
+        func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(2));
+        func.dictionary.put(PdfName.DOMAIN, new PdfArray(domain));
+        if (range != null)
+            func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+        if (c0 != null)
+            func.dictionary.put(PdfName.C0, new PdfArray(c0));
+        if (c1 != null)
+            func.dictionary.put(PdfName.C1, new PdfArray(c1));
+        func.dictionary.put(PdfName.N, new PdfNumber(n));
+        return func;
+    }
+
+    public static PdfFunction type3(PdfWriter writer, float domain[], float range[], PdfFunction functions[], float bounds[], float encode[]) {
+        PdfFunction func = new PdfFunction(writer);
+        func.dictionary = new PdfDictionary();
+        func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(3));
+        func.dictionary.put(PdfName.DOMAIN, new PdfArray(domain));
+        if (range != null)
+            func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+        PdfArray array = new PdfArray();
+        for (int k = 0; k < functions.length; ++k)
+            array.add(functions[k].getReference());
+        func.dictionary.put(PdfName.FUNCTIONS, array);
+        func.dictionary.put(PdfName.BOUNDS, new PdfArray(bounds));
+        func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
+        return func;
+    }
+    
+    public static PdfFunction type4(PdfWriter writer, float domain[], float range[], String postscript) {
+        byte b[] = new byte[postscript.length()];
+        for (int k = 0; k < b.length; ++k)
+            b[k] = (byte)postscript.charAt(k);
+        PdfFunction func = new PdfFunction(writer);
+        func.dictionary = new PdfStream(b);
+        ((PdfStream)func.dictionary).flateCompress();
+        func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(4));
+        func.dictionary.put(PdfName.DOMAIN, new PdfArray(domain));
+        func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+        return func;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfGState.java b/LibrarySource/com/lowagie/text/pdf/PdfGState.java
new file mode 100644
index 0000000..fe629aa
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfGState.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/** The graphic state dictionary.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfGState extends PdfDictionary {
+    /** A possible blend mode */
+    public static final PdfName BM_NORMAL = new PdfName("Normal");
+    /** A possible blend mode */
+    public static final PdfName BM_COMPATIBLE = new PdfName("Compatible");
+    /** A possible blend mode */
+    public static final PdfName BM_MULTIPLY = new PdfName("Multiply");
+    /** A possible blend mode */
+    public static final PdfName BM_SCREEN = new PdfName("Screen");
+    /** A possible blend mode */
+    public static final PdfName BM_OVERLAY = new PdfName("Overlay");
+    /** A possible blend mode */
+    public static final PdfName BM_DARKEN = new PdfName("Darken");
+    /** A possible blend mode */
+    public static final PdfName BM_LIGHTEN = new PdfName("Lighten");
+    /** A possible blend mode */
+    public static final PdfName BM_COLORDODGE = new PdfName("ColorDodge");
+    /** A possible blend mode */
+    public static final PdfName BM_COLORBURN = new PdfName("ColorBurn");
+    /** A possible blend mode */
+    public static final PdfName BM_HARDLIGHT = new PdfName("HardLight");
+    /** A possible blend mode */
+    public static final PdfName BM_SOFTLIGHT = new PdfName("SoftLight");
+    /** A possible blend mode */
+    public static final PdfName BM_DIFFERENCE = new PdfName("Difference");
+    /** A possible blend mode */
+    public static final PdfName BM_EXCLUSION = new PdfName("Exclusion");
+    
+    /**
+     * Sets the flag whether to apply overprint for stroking.
+     * @param ov
+     */
+    public void setOverPrintStroking(boolean ov) {
+        put(PdfName.OP, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+    }
+
+    /**
+     * Sets the flag whether to apply overprint for non stroking painting operations.
+     * @param ov
+     */
+    public void setOverPrintNonStroking(boolean ov) {
+        put(PdfName.op, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+    }
+    
+    /**
+     * Sets the current stroking alpha constant, specifying the constant shape or
+     * constant opacity value to be used for stroking operations in the transparent
+     * imaging model.
+     * @param n
+     */
+    public void setStrokeOpacity(float n) {
+        put(PdfName.CA, new PdfNumber(n));
+    }
+    
+    /**
+     * Sets the current stroking alpha constant, specifying the constant shape or
+     * constant opacity value to be used for nonstroking operations in the transparent
+     * imaging model.
+     * @param n
+     */
+    public void setFillOpacity(float n) {
+        put(PdfName.ca, new PdfNumber(n));
+    }
+    
+    /**
+     * The alpha source flag specifying whether the current soft mask
+     * and alpha constant are to be interpreted as shape values (true)
+     * or opacity values (false). 
+     * @param v
+     */
+    public void setAlphaIsShape(boolean v) {
+        put(PdfName.AIS, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+    }
+    
+    /**
+     * Determines the behaviour of overlapping glyphs within a text object
+     * in the transparent imaging model.
+     * @param v
+     */
+    public void setTextKnockout(boolean v) {
+        put(PdfName.TK, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+    }
+    
+    /**
+     * The current blend mode to be used in the transparent imaging model.
+     * @param bm
+     */
+    public void setBlendMode(PdfName bm) {
+        put(PdfName.BM, bm);
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfGraphics2D.java b/LibrarySource/com/lowagie/text/pdf/PdfGraphics2D.java
new file mode 100644
index 0000000..ed25e2b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfGraphics2D.java
@@ -0,0 +1,1423 @@
+/*
+ * Copyright 2002 by Jim Moore <jim at scolamoore.com>.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.BasicStroke;
+import headless.awt.Color;
+import headless.awt.Component;
+import headless.awt.Composite;
+import headless.awt.Font;
+import headless.awt.FontMetrics;
+import headless.awt.Graphics;
+import headless.awt.Graphics2D;
+import headless.awt.GraphicsConfiguration;
+import headless.awt.Image;
+import headless.awt.Paint;
+import headless.awt.GradientPaint;
+import headless.awt.TexturePaint;
+import headless.awt.MediaTracker;
+import headless.awt.Polygon;
+import headless.awt.Rectangle;
+import headless.awt.RenderingHints;
+import headless.awt.Shape;
+import headless.awt.Stroke;
+import headless.awt.Transparency;
+import headless.awt.font.FontRenderContext;
+import headless.awt.font.GlyphVector;
+import headless.awt.font.TextLayout;
+import headless.awt.geom.AffineTransform;
+import headless.awt.geom.Arc2D;
+import headless.awt.geom.Area;
+import headless.awt.geom.Ellipse2D;
+import headless.awt.geom.Line2D;
+import headless.awt.geom.PathIterator;
+import headless.awt.geom.Rectangle2D;
+import headless.awt.geom.RoundRectangle2D;
+import headless.awt.image.BufferedImage;
+import headless.awt.image.BufferedImageOp;
+import headless.awt.image.ColorModel;
+import headless.awt.image.ImageObserver;
+import headless.awt.image.RenderedImage;
+import headless.awt.image.WritableRaster;
+import headless.awt.image.renderable.RenderableImage;
+import headless.awt.RenderingHints.Key;
+import headless.awt.geom.NoninvertibleTransformException;
+import headless.awt.geom.Point2D;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.ArrayList;
+import java.io.ByteArrayOutputStream;
+//
+import java.util.Set;
+import java.util.Iterator;
+import headless.awt.font.TextAttribute;
+
+public class PdfGraphics2D extends Graphics2D {
+    
+    private static final int FILL = 1;
+    private static final int STROKE = 2;
+    private static final int CLIP = 3;
+    private BasicStroke strokeOne = new BasicStroke(1);
+    
+    private static AffineTransform IDENTITY = new AffineTransform();
+    
+    private Font font;
+    private BaseFont baseFont;
+    private float fontSize;
+    private AffineTransform transform;
+    private Paint paint;
+    private Color background;
+    private float width;
+    private float height;
+    
+    private Area clip;
+    
+    private RenderingHints rhints = new RenderingHints(null);
+    
+    private Stroke stroke;
+    private Stroke originalStroke;
+    
+    private PdfContentByte cb;
+    
+    /** Storage for BaseFont objects created. */
+    private HashMap baseFonts;
+    
+    private boolean disposeCalled = false;
+    
+    private FontMapper fontMapper;
+    
+    private ArrayList kids;
+    
+    private boolean kid = false;
+    
+    private Graphics dg2 = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB).getGraphics();
+    
+    private boolean onlyShapes = false;
+    
+    private Stroke oldStroke;
+    private Paint paintFill;
+    private Paint paintStroke;
+    
+    private MediaTracker mediaTracker;
+
+    // Added by Jurij Bilas
+    protected boolean underline;          // indicates if the font style is underlined
+    
+    protected PdfGState fillGState[] = new PdfGState[256];
+    protected PdfGState strokeGState[] = new PdfGState[256];
+    protected int currentFillGState = 255;
+    protected int currentStrokeGState = 255;
+    
+    public static int AFM_DIVISOR = 1000; // used to calculate coordinates
+
+    private boolean convertImagesToJPEG = false;
+    private float jpegQuality = .95f;
+
+    private PdfGraphics2D() {
+    }
+    
+    /**
+     * Constructor for PDFGraphics2D.
+     *
+     */
+    PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper, boolean onlyShapes, boolean convertImagesToJPEG, float quality) {
+        super();
+        try {
+            Class.forName("com.sun.image.codec.jpeg.JPEGCodec");
+        }
+        catch (Throwable t) {
+            convertImagesToJPEG = false;
+        }
+        this.convertImagesToJPEG = convertImagesToJPEG;
+        this.jpegQuality = quality;
+        this.onlyShapes = onlyShapes;
+        this.transform = new AffineTransform();
+        this.baseFonts = new HashMap();
+        if (!onlyShapes) {
+            this.fontMapper = fontMapper;
+            if (this.fontMapper == null)
+                this.fontMapper = new DefaultFontMapper();
+        }
+        this.kids = new ArrayList();
+        paint = Color.black;
+        background = Color.white;
+        setFont(new Font("sanserif", Font.PLAIN, 12));
+        this.cb = cb;
+        cb.saveState();
+        this.width = width;
+        this.height = height;
+        clip = new Area(new Rectangle2D.Float(0, 0, width, height));
+        clip(clip);
+        originalStroke = stroke = oldStroke = strokeOne;
+        setStrokeDiff(stroke, null);
+        cb.saveState();
+    }
+    
+    /**
+     * @see Graphics2D#draw(Shape)
+     */
+    public void draw(Shape s) {
+        followPath(s, STROKE);
+    }
+    
+    /**
+     * @see Graphics2D#drawImage(Image, AffineTransform, ImageObserver)
+     */
+    public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
+        return drawImage(img, null, xform, null, obs);
+    }
+    
+    /**
+     * @see Graphics2D#drawImage(BufferedImage, BufferedImageOp, int, int)
+     */
+    public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
+        BufferedImage result = op.createCompatibleDestImage(img, img.getColorModel());
+        result = op.filter(img, result);
+        drawImage(result, x, y, null);
+    }
+    
+    /**
+     * @see Graphics2D#drawRenderedImage(RenderedImage, AffineTransform)
+     */
+    public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+        BufferedImage image = null;
+        if (img instanceof BufferedImage) {
+            image = (BufferedImage)img;
+        } else {
+            ColorModel cm = img.getColorModel();
+            int width = img.getWidth();
+            int height = img.getHeight();
+            WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
+            boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
+            Hashtable properties = new Hashtable();
+            String[] keys = img.getPropertyNames();
+            if (keys!=null) {
+                for (int i = 0; i < keys.length; i++) {
+                    properties.put(keys[i], img.getProperty(keys[i]));
+                }
+            }
+            BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
+            img.copyData(raster);
+            image=result;
+        }
+        drawImage(image, xform, null);
+    }
+    
+    /**
+     * @see Graphics2D#drawRenderableImage(RenderableImage, AffineTransform)
+     */
+    public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+        drawRenderedImage(img.createDefaultRendering(), xform);
+    }
+    
+    /**
+     * @see Graphics#drawString(String, int, int)
+     */
+    public void drawString(String s, int x, int y) {
+        drawString(s, (float)x, (float)y);
+    }
+    
+    /**
+     * Calculates position and/or stroke thickness depending on the font size
+     * @param d value to be converted
+     * @param i font size
+     * @return position and/or stroke thickness depending on the font size
+     */
+    public static double asPoints(double d, int i) {
+        return (d * (double)i) / (double)AFM_DIVISOR;
+    }
+    /**
+     * This routine goes through the attributes and sets the font
+     * before calling the actual string drawing routine
+     * @param iter
+     */
+    protected void doAttributes(AttributedCharacterIterator iter) {
+        underline = false;
+        Set set = iter.getAttributes().keySet();
+        for(Iterator iterator = set.iterator(); iterator.hasNext();) {
+            TextAttribute textattribute = (TextAttribute)iterator.next();
+            if(textattribute.equals(TextAttribute.FONT)) {
+                Font font = (Font)iter.getAttributes().get(textattribute);
+                setFont(font);
+            }
+            else if(textattribute.equals(TextAttribute.UNDERLINE)) {
+                if(iter.getAttributes().get(textattribute) == TextAttribute.UNDERLINE_ON)
+                    underline = true;
+            }
+            else if(textattribute.equals(TextAttribute.SUPERSCRIPT)) {
+                /*
+                iter.getAttributes().get(textattribute);
+                Integer _tmp = TextAttribute.SUPERSCRIPT_SUPER;
+                subscript = true;
+                 */
+            }
+            else if(textattribute.equals(TextAttribute.SIZE)) {
+                Object obj = iter.getAttributes().get(textattribute);
+                Font font1 = null;
+                if(obj instanceof Integer) {
+                    int i = ((Integer)obj).intValue();
+                    font1 = getFont().deriveFont(getFont().getStyle(), i);
+                }
+                else if(obj instanceof Float) {
+                    float f = ((Float)obj).floatValue();
+                    font1 = getFont().deriveFont(getFont().getStyle(), f);
+                }
+                else {
+                    //System.out.println("Unknown type for attribute SIZE");
+                    return;
+                }
+                setFont(font1);
+            }
+            else {
+                String s = "only FONT/SIZE/UNDERLINE/SUPERSCRIPT supported";
+                throw new RuntimeException(s);
+            }
+        }
+    }
+
+    /**
+     * @see Graphics2D#drawString(String, float, float)
+     */
+    public void drawString(String s, float x, float y) {
+        if (s.length() == 0)
+            return;
+        setFillPaint();
+        if (onlyShapes) {
+            TextLayout tl = new TextLayout(s, this.font, new FontRenderContext(new AffineTransform(), false, true));
+            tl.draw(this, x, y);
+        }
+        else {
+            AffineTransform at = getTransform();
+            AffineTransform at2 = getTransform();
+            at2.translate(x, y);
+            at2.concatenate(font.getTransform());
+            setTransform(at2);
+            AffineTransform inverse = this.normalizeMatrix();
+            AffineTransform flipper = AffineTransform.getScaleInstance(1,-1);
+            inverse.concatenate(flipper);
+            double[] mx = new double[6];
+            inverse.getMatrix(mx);
+            cb.beginText();
+            cb.setFontAndSize(baseFont, fontSize);
+            cb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]);
+            double width = font.deriveFont(IDENTITY).getStringBounds(s, getFontRenderContext()).getWidth();
+            if (s.length() > 1) {
+                float adv = ((float)width - baseFont.getWidthPoint(s, fontSize)) / (s.length() - 1);
+                cb.setCharacterSpacing(adv);
+            }
+            cb.showText(s);
+            if (s.length() > 1) {
+                cb.setCharacterSpacing(0);
+            }
+            cb.endText();
+            setTransform(at);
+            if(underline)
+            {
+                // These two are supposed to be taken from the .AFM file
+                int UnderlinePosition = -100;
+                int UnderlineThickness = 50;
+                //
+                double d = asPoints((double)UnderlineThickness, (int)fontSize);
+                setStroke(new BasicStroke((float)d));
+                y = (float)((double)(y) + asPoints((double)(-UnderlineThickness), (int)fontSize));
+                Line2D line = new Line2D.Double((double)x, (double)y, (double)(width+x), (double)y);
+                draw(line);
+            }
+        }
+    }
+
+    /**
+     * @see Graphics#drawString(AttributedCharacterIterator, int, int)
+     */
+    public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+        drawString(iterator, (float)x, (float)y);
+    }
+    
+    /**
+     * @see Graphics2D#drawString(AttributedCharacterIterator, float, float)
+     */
+    public void drawString(AttributedCharacterIterator iter, float x, float y) {
+/*
+        StringBuffer sb = new StringBuffer();
+        for(char c = iter.first(); c != AttributedCharacterIterator.DONE; c = iter.next()) {
+            sb.append(c);
+        }
+        drawString(sb.toString(),x,y);
+*/
+        StringBuffer stringbuffer = new StringBuffer(iter.getEndIndex());
+        for(char c = iter.first(); c != '\uFFFF'; c = iter.next())
+        {
+            if(iter.getIndex() == iter.getRunStart())
+            {
+                if(stringbuffer.length() > 0)
+                {
+                    drawString(stringbuffer.toString(), x, y);
+                    FontMetrics fontmetrics = getFontMetrics();
+                    x = (float)((double)x + fontmetrics.getStringBounds(stringbuffer.toString(), this).getWidth());
+                    stringbuffer.delete(0, stringbuffer.length());
+                }
+                doAttributes(iter);
+            }
+            stringbuffer.append(c);
+        }
+        
+        drawString(stringbuffer.toString(), x, y);
+        underline = false;
+    }
+    
+    /**
+     * @see Graphics2D#drawGlyphVector(GlyphVector, float, float)
+     */
+    public void drawGlyphVector(GlyphVector g, float x, float y) {
+        Shape s = g.getOutline(x, y);
+        fill(s);
+    }
+    
+    /**
+     * @see Graphics2D#fill(Shape)
+     */
+    public void fill(Shape s) {
+        followPath(s, FILL);
+    }
+    
+    /**
+     * @see Graphics2D#hit(Rectangle, Shape, boolean)
+     */
+    public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
+        if (onStroke) {
+            s = stroke.createStrokedShape(s);
+        }
+        s = transform.createTransformedShape(s);
+        Area area = new Area(s);
+        if (clip != null)
+            area.intersect(clip);
+        return area.intersects(rect.x, rect.y, rect.width, rect.height);
+    }
+    
+    /**
+     * @see Graphics2D#getDeviceConfiguration()
+     */
+    public GraphicsConfiguration getDeviceConfiguration() {
+        return ((Graphics2D)dg2).getDeviceConfiguration();
+    }
+    
+    /**
+     * @see Graphics2D#setComposite(Composite)
+     */
+    public void setComposite(Composite comp) {
+        
+    }
+    
+    /**
+     * @see Graphics2D#setPaint(Paint)
+     */
+    public void setPaint(Paint paint) {
+        if (paint == null)
+            return;
+        this.paint = paint;
+//        setPaint(paint, false, 0, 0);
+    }
+
+    private Stroke transformStroke(Stroke stroke) {
+        if (!(stroke instanceof BasicStroke))
+            return stroke;
+        BasicStroke st = (BasicStroke)stroke;
+        float scale = (float)Math.sqrt(Math.abs(transform.getDeterminant()));
+        float dash[] = st.getDashArray();
+        if (dash != null) {
+            for (int k = 0; k < dash.length; ++k)
+                dash[k] *= scale;
+        }
+        return new BasicStroke(st.getLineWidth() * scale, st.getEndCap(), st.getLineJoin(), st.getMiterLimit(), dash, st.getDashPhase() * scale);
+    }
+    
+    private void setStrokeDiff(Stroke newStroke, Stroke oldStroke) {
+        if (newStroke == oldStroke)
+            return;
+        if (!(newStroke instanceof BasicStroke))
+            return;
+        BasicStroke nStroke = (BasicStroke)newStroke;
+        boolean oldOk = (oldStroke instanceof BasicStroke);
+        BasicStroke oStroke = null;
+        if (oldOk)
+            oStroke = (BasicStroke)oldStroke;
+        if (!oldOk || nStroke.getLineWidth() != oStroke.getLineWidth())
+            cb.setLineWidth(nStroke.getLineWidth());
+        if (!oldOk || nStroke.getEndCap() != oStroke.getEndCap()) {
+            switch (nStroke.getEndCap()) {
+            case BasicStroke.CAP_BUTT:
+                cb.setLineCap(0);
+                break;
+            case BasicStroke.CAP_SQUARE:
+                cb.setLineCap(2);
+                break;
+            default:
+                cb.setLineCap(1);
+            }
+        }
+        if (!oldOk || nStroke.getLineJoin() != oStroke.getLineJoin()) {
+            switch (nStroke.getLineJoin()) {
+            case BasicStroke.JOIN_MITER:
+                cb.setLineJoin(0);
+                break;
+            case BasicStroke.JOIN_BEVEL:
+                cb.setLineJoin(2);
+                break;
+            default:
+                cb.setLineJoin(1);
+            }
+        }
+        if (!oldOk || nStroke.getMiterLimit() != oStroke.getMiterLimit())
+            cb.setMiterLimit(nStroke.getMiterLimit());
+        boolean makeDash;
+        if (oldOk) {
+            if (nStroke.getDashArray() != null) {
+                if (nStroke.getDashPhase() != oStroke.getDashPhase()) {
+                    makeDash = true;
+                }
+                else if (!java.util.Arrays.equals(nStroke.getDashArray(), oStroke.getDashArray())) {
+                    makeDash = true;
+                }
+                else
+                    makeDash = false;
+            }
+            else if (oStroke.getDashArray() != null) {
+                makeDash = true;
+            }
+            else
+                makeDash = false;
+        }
+        else {
+            makeDash = true;
+        }
+        if (makeDash) {
+            float dash[] = nStroke.getDashArray();
+            if (dash == null)
+                cb.setLiteral("[]0 d\n");
+            else {
+                cb.setLiteral('[');
+                int lim = dash.length;
+                for (int k = 0; k < lim; ++k) {
+                    cb.setLiteral(dash[k]);
+                    cb.setLiteral(' ');
+                }
+                cb.setLiteral(']');
+                cb.setLiteral(nStroke.getDashPhase());
+                cb.setLiteral(" d\n");
+            }
+        }
+    }
+    
+    /**
+     * @see Graphics2D#setStroke(Stroke)
+     */
+    public void setStroke(Stroke s) {
+        originalStroke = s;
+        this.stroke = transformStroke(s);
+    }
+    
+    
+    /**
+     * Sets a rendering hint
+     * @param arg0
+     * @param arg1
+     */
+    public void setRenderingHint(Key arg0, Object arg1) {
+        rhints.put(arg0, arg1);
+    }
+    
+    /**
+     * @param arg0 a key
+     * @return the rendering hint
+     */
+    public Object getRenderingHint(Key arg0) {
+        return rhints.get(arg0);
+    }
+    
+    /**
+     * @see Graphics2D#setRenderingHints(Map)
+     */
+    public void setRenderingHints(Map hints) {
+        rhints.clear();
+        rhints.putAll(hints);
+    }
+    
+    /**
+     * @see Graphics2D#addRenderingHints(Map)
+     */
+    public void addRenderingHints(Map hints) {
+        rhints.putAll(hints);
+    }
+    
+    /**
+     * @see Graphics2D#getRenderingHints()
+     */
+    public RenderingHints getRenderingHints() {
+        return rhints;
+    }
+    
+    /**
+     * @see Graphics#translate(int, int)
+     */
+    public void translate(int x, int y) {
+        translate((double)x, (double)y);
+    }
+    
+    /**
+     * @see Graphics2D#translate(double, double)
+     */
+    public void translate(double tx, double ty) {
+        transform.translate(tx,ty);
+    }
+    
+    /**
+     * @see Graphics2D#rotate(double)
+     */
+    public void rotate(double theta) {
+        transform.rotate(theta);
+    }
+    
+    /**
+     * @see Graphics2D#rotate(double, double, double)
+     */
+    public void rotate(double theta, double x, double y) {
+        transform.rotate(theta, x, y);
+    }
+    
+    /**
+     * @see Graphics2D#scale(double, double)
+     */
+    public void scale(double sx, double sy) {
+        transform.scale(sx, sy);
+        this.stroke = transformStroke(originalStroke);
+    }
+    
+    /**
+     * @see Graphics2D#shear(double, double)
+     */
+    public void shear(double shx, double shy) {
+        transform.shear(shx, shy);
+    }
+    
+    /**
+     * @see Graphics2D#transform(AffineTransform)
+     */
+    public void transform(AffineTransform tx) {
+        transform.concatenate(tx);
+        this.stroke = transformStroke(originalStroke);
+    }
+    
+    /**
+     * @see Graphics2D#setTransform(AffineTransform)
+     */
+    public void setTransform(AffineTransform t) {
+        transform = new AffineTransform(t);
+        this.stroke = transformStroke(originalStroke);
+    }
+    
+    /**
+     * @see Graphics2D#getTransform()
+     */
+    public AffineTransform getTransform() {
+        return new AffineTransform(transform);
+    }
+    
+    /**
+     * @see Graphics2D#getPaint()
+     */
+    public Paint getPaint() {
+        return paint;
+    }
+    
+    /**
+     * @see Graphics2D#getComposite()
+     */
+    public Composite getComposite() {
+        return null;
+    }
+    
+    /**
+     * @see Graphics2D#setBackground(Color)
+     */
+    public void setBackground(Color color) {
+        background = color;
+    }
+    
+    /**
+     * @see Graphics2D#getBackground()
+     */
+    public Color getBackground() {
+        return background;
+    }
+    
+    /**
+     * @see Graphics2D#getStroke()
+     */
+    public Stroke getStroke() {
+        return originalStroke;
+    }
+    
+    
+    /**
+     * @see Graphics2D#getFontRenderContext()
+     */
+    public FontRenderContext getFontRenderContext() {
+        return new FontRenderContext(null, true, true);
+    }
+    
+    /**
+     * @see Graphics#create()
+     */
+    public Graphics create() {
+        PdfGraphics2D g2 = new PdfGraphics2D();
+        g2.onlyShapes = this.onlyShapes;
+        g2.transform = new AffineTransform(this.transform);
+        g2.baseFonts = this.baseFonts;
+        g2.fontMapper = this.fontMapper;
+        g2.kids = this.kids;
+        g2.paint = this.paint;
+        g2.fillGState = this.fillGState;
+        g2.strokeGState = this.strokeGState;
+        g2.background = this.background;
+        g2.mediaTracker = this.mediaTracker;
+        g2.convertImagesToJPEG = this.convertImagesToJPEG;
+        g2.jpegQuality = this.jpegQuality;
+        g2.setFont(this.font);
+        g2.cb = this.cb.getDuplicate();
+        g2.cb.saveState();
+        g2.width = this.width;
+        g2.height = this.height;
+        g2.followPath(new Area(new Rectangle2D.Float(0, 0, width, height)), CLIP);
+        if (this.clip != null)
+            g2.clip = new Area(this.clip);
+        g2.stroke = stroke;
+        g2.originalStroke = originalStroke;
+        g2.strokeOne = (BasicStroke)g2.transformStroke(g2.strokeOne);
+        g2.oldStroke = g2.strokeOne;
+        g2.setStrokeDiff(g2.oldStroke, null);
+        g2.cb.saveState();
+        if (g2.clip != null)
+            g2.followPath(g2.clip, CLIP);
+        g2.kid = true;
+        synchronized (kids) {
+            kids.add(g2);
+        }
+        return g2;
+    }
+    
+    public PdfContentByte getContent() {
+        return this.cb;
+    }
+    /**
+     * @see Graphics#getColor()
+     */
+    public Color getColor() {
+        if (paint instanceof Color) {
+            return (Color)paint;
+        } else {
+            return Color.black;
+        }
+    }
+    
+    /**
+     * @see Graphics#setColor(Color)
+     */
+    public void setColor(Color color) {
+        setPaint(color);
+    }
+    
+    /**
+     * @see Graphics#setPaintMode()
+     */
+    public void setPaintMode() {}
+    
+    /**
+     * @see Graphics#setXORMode(Color)
+     */
+    public void setXORMode(Color c1) {
+        
+    }
+    
+    /**
+     * @see Graphics#getFont()
+     */
+    public Font getFont() {
+        return font;
+    }
+    
+    /**
+     * @see Graphics#setFont(Font)
+     */
+    /**
+     * Sets the current font.
+     */
+    public void setFont(Font f) {
+        if (f == null)
+            return;
+        if (onlyShapes) {
+            font = f;
+            return;
+        }
+        if (f == font)
+            return;
+        font = f;
+        fontSize = f.getSize2D();
+        baseFont = getCachedBaseFont(f);
+    }
+    
+    private BaseFont getCachedBaseFont(Font f) {
+        synchronized (baseFonts) {
+            BaseFont bf = (BaseFont)baseFonts.get(f.getFontName());
+            if (bf == null) {
+                bf = fontMapper.awtToPdf(f);
+                baseFonts.put(f.getFontName(), bf);
+            }
+            return bf;
+        }
+    }
+    
+    /**
+     * @see Graphics#getFontMetrics(Font)
+     */
+    public FontMetrics getFontMetrics(Font f) {
+        return dg2.getFontMetrics(f);
+    }
+    
+    /**
+     * @see Graphics#getClipBounds()
+     */
+    public Rectangle getClipBounds() {
+        if (clip == null)
+            return null;
+        return getClip().getBounds();
+    }
+    
+    /**
+     * @see Graphics#clipRect(int, int, int, int)
+     */
+    public void clipRect(int x, int y, int width, int height) {
+        Rectangle2D rect = new Rectangle2D.Double(x,y,width,height);
+        clip(rect);
+    }
+    
+    /**
+     * @see Graphics#setClip(int, int, int, int)
+     */
+    public void setClip(int x, int y, int width, int height) {
+        Rectangle2D rect = new Rectangle2D.Double(x,y,width,height);
+        setClip(rect);
+    }
+    
+    /**
+     * @see Graphics2D#clip(Shape)
+     */
+    public void clip(Shape s) {
+        if (s != null)
+            s = transform.createTransformedShape(s);
+        if (clip == null)
+            clip = new Area(s);
+        else
+            clip.intersect(new Area(s));
+        followPath(s, CLIP);
+    }
+    
+    /**
+     * @see Graphics#getClip()
+     */
+    public Shape getClip() {
+        try {
+            return transform.createInverse().createTransformedShape(clip);
+        }
+        catch (NoninvertibleTransformException e) {
+            return null;
+        }
+    }
+    
+    /**
+     * @see Graphics#setClip(Shape)
+     */
+    public void setClip(Shape s) {
+        cb.restoreState();
+        cb.saveState();
+        if (s != null)
+            s = transform.createTransformedShape(s);
+        if (s == null) {
+            clip = null;
+        }
+        else {
+            clip = new Area(s);
+            followPath(s, CLIP);
+        }
+        paintFill = paintStroke = null;
+        currentFillGState = currentStrokeGState = 255;
+        oldStroke = strokeOne;
+    }
+    
+    /**
+     * @see Graphics#copyArea(int, int, int, int, int, int)
+     */
+    public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+        
+    }
+    
+    /**
+     * @see Graphics#drawLine(int, int, int, int)
+     */
+    public void drawLine(int x1, int y1, int x2, int y2) {
+        Line2D line = new Line2D.Double((double)x1, (double)y1, (double)x2, (double)y2);
+        draw(line);
+    }
+    
+    /**
+     * @see Graphics#fillRect(int, int, int, int)
+     */
+    public void drawRect(int x, int y, int width, int height) {
+        draw(new Rectangle(x, y, width, height));
+    }
+    
+    /**
+     * @see Graphics#fillRect(int, int, int, int)
+     */
+    public void fillRect(int x, int y, int width, int height) {
+        fill(new Rectangle(x,y,width,height));
+    }
+    
+    /**
+     * @see Graphics#clearRect(int, int, int, int)
+     */
+    public void clearRect(int x, int y, int width, int height) {
+        Paint temp = paint;
+        setPaint(background);
+        fillRect(x,y,width,height);
+        setPaint(temp);
+    }
+    
+    /**
+     * @see Graphics#drawRoundRect(int, int, int, int, int, int)
+     */
+    public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+        RoundRectangle2D rect = new RoundRectangle2D.Double(x,y,width,height,arcWidth, arcHeight);
+        draw(rect);
+    }
+    
+    /**
+     * @see Graphics#fillRoundRect(int, int, int, int, int, int)
+     */
+    public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+        RoundRectangle2D rect = new RoundRectangle2D.Double(x,y,width,height,arcWidth, arcHeight);
+        fill(rect);
+    }
+    
+    /**
+     * @see Graphics#drawOval(int, int, int, int)
+     */
+    public void drawOval(int x, int y, int width, int height) {
+        Ellipse2D oval = new Ellipse2D.Float((float)x, (float)y, (float)width, (float)height);
+        draw(oval);
+    }
+    
+    /**
+     * @see Graphics#fillOval(int, int, int, int)
+     */
+    public void fillOval(int x, int y, int width, int height) {
+        Ellipse2D oval = new Ellipse2D.Float((float)x, (float)y, (float)width, (float)height);
+        fill(oval);
+    }
+    
+    /**
+     * @see Graphics#drawArc(int, int, int, int, int, int)
+     */
+    public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+        Arc2D arc = new Arc2D.Double(x,y,width,height,startAngle, arcAngle, Arc2D.OPEN);
+        draw(arc);
+
+    }
+    
+    /**
+     * @see Graphics#fillArc(int, int, int, int, int, int)
+     */
+    public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+        Arc2D arc = new Arc2D.Double(x,y,width,height,startAngle, arcAngle, Arc2D.PIE);
+        fill(arc);
+    }
+    
+    /**
+     * @see Graphics#drawPolyline(int[], int[], int)
+     */
+    public void drawPolyline(int[] x, int[] y, int nPoints) {
+        Line2D line = new Line2D.Double(x[0],y[0],x[0],y[0]);
+        for (int i = 1; i < nPoints; i++) {
+            line.setLine(line.getX2(), line.getY2(), x[i], y[i]);
+            draw(line);
+        }
+    }
+    
+    /**
+     * @see Graphics#drawPolygon(int[], int[], int)
+     */
+    public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+        Polygon poly = new Polygon();
+        for (int i = 0; i < nPoints; i++) {
+            poly.addPoint(xPoints[i], yPoints[i]);
+        }
+        draw(poly);
+    }
+    
+    /**
+     * @see Graphics#fillPolygon(int[], int[], int)
+     */
+    public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+        Polygon poly = new Polygon();
+        for (int i = 0; i < nPoints; i++) {
+            poly.addPoint(xPoints[i], yPoints[i]);
+        }
+        fill(poly);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, ImageObserver)
+     */
+    public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+        return drawImage(img, x, y, null, observer);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
+     */
+    public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+        return drawImage(img, x, y, width, height, null, observer);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
+     */
+    public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+        waitForImage(img);
+        return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), bgcolor, observer);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
+     */
+    public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+        waitForImage(img);
+        double scalex = width/(double)img.getWidth(observer);
+        double scaley = height/(double)img.getHeight(observer);
+        AffineTransform tx = AffineTransform.getTranslateInstance(x,y);
+        tx.scale(scalex,scaley);
+        return drawImage(img, null, tx, bgcolor, observer);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver)
+     */
+    public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+        return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
+    }
+    
+    /**
+     * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver)
+     */
+    public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
+        waitForImage(img);
+        double dwidth = (double)dx2-dx1;
+        double dheight = (double)dy2-dy1;
+        double swidth = (double)sx2-sx1;
+        double sheight = (double)sy2-sy1;
+        
+        //if either width or height is 0, then there is nothing to draw
+        if (dwidth == 0 || dheight == 0 || swidth == 0 || sheight == 0) return true;
+        
+        double scalex = dwidth/swidth;
+        double scaley = dheight/sheight;
+        
+        double transx = sx1*scalex;
+        double transy = sy1*scaley;
+        AffineTransform tx = AffineTransform.getTranslateInstance(dx1-transx,dy1-transy);
+        tx.scale(scalex,scaley);
+        
+        BufferedImage mask = new BufferedImage(img.getWidth(observer), img.getHeight(observer), BufferedImage.TYPE_BYTE_BINARY);
+        Graphics g = mask.getGraphics();
+        g.fillRect(sx1,sy1, (int)swidth, (int)sheight);
+        drawImage(img, mask, tx, null, observer);
+        return true;
+    }
+    
+    /**
+     * @see Graphics#dispose()
+     */
+    public void dispose() {
+        if (kid)
+            return;
+        if (!disposeCalled) {
+            disposeCalled = true;
+            cb.restoreState();
+            cb.restoreState();
+            for (int k = 0; k < kids.size(); ++k) {
+                PdfGraphics2D g2 = (PdfGraphics2D)kids.get(k);
+                g2.cb.restoreState();
+                g2.cb.restoreState();
+                cb.add(g2.cb);
+            }
+        }
+    }
+    
+    ///////////////////////////////////////////////
+    //
+    //
+    //		implementation specific methods
+    //
+    //
+    
+    
+    private void followPath(Shape s, int drawType) {
+        if (s==null) return;
+        if (drawType==STROKE) {
+            if (!(stroke instanceof BasicStroke)) {
+                s = stroke.createStrokedShape(s);
+                followPath(s, FILL);
+                return;
+            }
+        }
+        if (drawType==STROKE) {
+            setStrokeDiff(stroke, oldStroke);
+            oldStroke = stroke;
+            setStrokePaint();
+        }
+        else if (drawType==FILL)
+            setFillPaint();
+        PathIterator points;
+        if (drawType == CLIP)
+            points = s.getPathIterator(IDENTITY);
+        else
+            points = s.getPathIterator(transform);
+        float[] coords = new float[6];
+        int traces = 0;
+        while(!points.isDone()) {
+            ++traces;
+            int segtype = points.currentSegment(coords);
+            normalizeY(coords);
+            switch(segtype) {
+                case PathIterator.SEG_CLOSE:
+                    cb.closePath();
+                    break;
+                    
+                case PathIterator.SEG_CUBICTO:
+                    cb.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
+                    break;
+                    
+                case PathIterator.SEG_LINETO:
+                    cb.lineTo(coords[0], coords[1]);
+                    break;
+                    
+                case PathIterator.SEG_MOVETO:
+                    cb.moveTo(coords[0], coords[1]);
+                    break;
+                    
+                case PathIterator.SEG_QUADTO:
+                    cb.curveTo(coords[0], coords[1], coords[2], coords[3]);
+                    break;
+            }
+            points.next();
+        }
+        
+        switch (drawType) {
+        case FILL:
+            if (traces > 0) {
+                if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD)
+                    cb.eoFill();
+                else
+                    cb.fill();
+            }
+            break;
+        case STROKE:
+            if (traces > 0)
+                cb.stroke();
+            break;
+        default: //drawType==CLIP
+            if (traces == 0)
+                cb.rectangle(0, 0, 0, 0);
+            if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD)
+                cb.eoClip();
+            else
+                cb.clip();
+            cb.newPath();
+        }
+    }
+    
+    private float normalizeY(float y) {
+        return this.height - y;
+    }
+    
+    private void normalizeY(float[] coords) {
+        coords[1] = normalizeY(coords[1]);
+        coords[3] = normalizeY(coords[3]);
+        coords[5] = normalizeY(coords[5]);
+    }
+    
+    private AffineTransform normalizeMatrix() {
+        double[] mx = new double[6];
+        AffineTransform result = AffineTransform.getTranslateInstance(0,0);
+        result.getMatrix(mx);
+        mx[3]=-1;
+        mx[5]=height;
+        result = new AffineTransform(mx);
+        result.concatenate(transform);
+        return result;
+    }
+    
+    private boolean drawImage(Image img, Image mask, AffineTransform xform, Color bgColor, ImageObserver obs) {
+        if (xform==null) return true;
+        
+        xform.translate(0, img.getHeight(obs));
+        xform.scale(img.getWidth(obs), img.getHeight(obs));
+        
+        AffineTransform inverse = this.normalizeMatrix();
+        AffineTransform flipper = AffineTransform.getScaleInstance(1,-1);
+        inverse.concatenate(xform);
+        inverse.concatenate(flipper);
+        
+        double[] mx = new double[6];
+        inverse.getMatrix(mx);
+        if (currentFillGState != 255) {
+            PdfGState gs = fillGState[255];
+            if (gs == null) {
+                gs = new PdfGState();
+                gs.setFillOpacity(1);
+                fillGState[255] = gs;
+            }
+            cb.setGState(gs);
+        }
+        
+        try {
+            com.lowagie.text.Image image = null;
+            if(!convertImagesToJPEG){
+                image = com.lowagie.text.Image.getInstance(img, bgColor);
+            }
+            else{
+                BufferedImage scaled = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
+                Graphics2D g3 = scaled.createGraphics();
+                g3.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null);
+                g3.dispose();
+                
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                com.sun.image.codec.jpeg.JPEGImageEncoder encoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(baos);
+                com.sun.image.codec.jpeg.JPEGEncodeParam param = com.sun.image.codec.jpeg.JPEGCodec.getDefaultJPEGEncodeParam(scaled);
+                param.setQuality(jpegQuality, true);
+                encoder.encode(scaled, param);
+                scaled.flush();
+                scaled = null;
+                image = com.lowagie.text.Image.getInstance(baos.toByteArray());
+                
+            }
+            if (mask!=null) {
+                com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true);
+                msk.makeMask();
+                msk.setInvertMask(true);
+                image.setImageMask(msk);
+            }
+            cb.addImage(image, (float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]);
+        } catch (Exception ex) {
+            throw new IllegalArgumentException();
+        }
+        if (currentFillGState != 255) {
+            PdfGState gs = fillGState[currentFillGState];
+            cb.setGState(gs);
+        }        
+        return true;
+    }
+    
+    private boolean checkNewPaint(Paint oldPaint) {
+        if (paint == oldPaint)
+            return false;
+        return !((paint instanceof Color) && paint.equals(oldPaint));
+    }
+    
+    private void setFillPaint() {
+        if (checkNewPaint(paintFill)) {
+            paintFill = paint;
+            setPaint(false, 0, 0, true);
+        }
+    }
+    
+    private void setStrokePaint() {
+        if (checkNewPaint(paintStroke)) {
+            paintStroke = paint;
+            setPaint(false, 0, 0, false);
+        }
+    }
+    
+    private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill) {
+        if (paint instanceof Color) {
+            Color color = (Color)paint;
+            int alpha = color.getAlpha();
+            if (fill) {
+                if (alpha != currentFillGState) {
+                    currentFillGState = alpha;
+                    PdfGState gs = fillGState[alpha];
+                    if (gs == null) {
+                        gs = new PdfGState();
+                        gs.setFillOpacity((float)alpha / 255f);
+                        fillGState[alpha] = gs;
+                    }
+                    cb.setGState(gs);
+                }
+                cb.setColorFill(color);
+            }
+            else {
+                if (alpha != currentStrokeGState) {
+                    currentStrokeGState = alpha;
+                    PdfGState gs = strokeGState[alpha];
+                    if (gs == null) {
+                        gs = new PdfGState();
+                        gs.setStrokeOpacity((float)alpha / 255f);
+                        strokeGState[alpha] = gs;
+                    }
+                    cb.setGState(gs);
+                }
+                cb.setColorStroke(color);
+            }
+        }
+        else if (paint instanceof GradientPaint) {
+            GradientPaint gp = (GradientPaint)paint;
+            Point2D p1 = gp.getPoint1();
+            transform.transform(p1, p1);
+            Point2D p2 = gp.getPoint2();
+            transform.transform(p2, p2);
+            Color c1 = gp.getColor1();
+            Color c2 = gp.getColor2();
+            PdfShading shading = PdfShading.simpleAxial(cb.getPdfWriter(), (float)p1.getX(), normalizeY((float)p1.getY()), (float)p2.getX(), normalizeY((float)p2.getY()), c1, c2);
+            PdfShadingPattern pat = new PdfShadingPattern(shading);
+            if (fill)
+                cb.setShadingFill(pat);
+            else
+                cb.setShadingStroke(pat);
+        }
+        else if (paint instanceof TexturePaint) {
+            try {
+                TexturePaint tp = (TexturePaint)paint;
+                BufferedImage img = tp.getImage();
+                Rectangle2D rect = tp.getAnchorRect();
+                com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null);
+                PdfPatternPainter pattern = cb.createPattern(image.width(), image.height());
+                AffineTransform inverse = this.normalizeMatrix();
+                inverse.translate(rect.getX(), rect.getY());
+                inverse.scale(rect.getWidth() / image.width(), -rect.getHeight() / image.height());
+                double[] mx = new double[6];
+                inverse.getMatrix(mx);
+                pattern.setPatternMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]) ;
+                image.setAbsolutePosition(0,0);
+                pattern.addImage(image);
+                if (fill)
+                    cb.setPatternFill(pattern);
+                else
+                    cb.setPatternStroke(pattern);
+            } catch (Exception ex) {
+                if (fill)
+                    cb.setColorFill(Color.gray);
+                else
+                    cb.setColorStroke(Color.gray);
+            }
+        }
+        else {
+            try {
+                BufferedImage img = null;
+                int type = BufferedImage.TYPE_4BYTE_ABGR;
+                if (paint.getTransparency() == Transparency.OPAQUE) {
+                    type = BufferedImage.TYPE_3BYTE_BGR;
+                }
+                img = new BufferedImage((int)width, (int)height, type);
+                Graphics2D g = (Graphics2D)img.getGraphics();
+                g.transform(transform);
+                AffineTransform inv = transform.createInverse();
+                Shape fillRect = new Rectangle2D.Double(0,0,img.getWidth(),img.getHeight());
+                fillRect = inv.createTransformedShape(fillRect);
+                g.setPaint(paint);
+                g.fill(fillRect);
+                if (invert) {
+                    AffineTransform tx = new AffineTransform();
+                    tx.scale(1,-1);
+                    tx.translate(-xoffset,-yoffset);
+                    g.drawImage(img,tx,null);
+                }
+                com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null);
+                PdfPatternPainter pattern = cb.createPattern(width, height);
+                image.setAbsolutePosition(0,0);
+                pattern.addImage(image);
+                if (fill)
+                    cb.setPatternFill(pattern);
+                else
+                    cb.setPatternStroke(pattern);
+            } catch (Exception ex) {
+                if (fill)
+                    cb.setColorFill(Color.gray);
+                else
+                    cb.setColorStroke(Color.gray);
+            }
+        }
+    }
+    
+    private synchronized void waitForImage(java.awt.Image image) {
+        if (mediaTracker == null)
+            mediaTracker = new MediaTracker(new PdfGraphics2D.fakeComponent());
+        mediaTracker.addImage(image, 0);
+        try {
+            mediaTracker.waitForID(0);
+        }
+        catch (InterruptedException e) {
+            // empty on purpose
+        }
+        mediaTracker.removeImage(image);
+    }
+        
+    static private class fakeComponent extends Component {
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfICCBased.java b/LibrarySource/com/lowagie/text/pdf/PdfICCBased.java
new file mode 100644
index 0000000..c59e106
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfICCBased.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import headless.awt.color.ICC_Profile;
+
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * A <CODE>PdfICCBased</CODE> defines a ColorSpace
+ *
+ * @see		PdfStream
+ */
+
+class PdfICCBased extends PdfStream {
+    
+    protected int NumberOfComponents;
+    
+    PdfICCBased(ICC_Profile profile) {
+        super();
+        try {
+            NumberOfComponents = profile.getNumComponents();
+            PdfNumber pNumber = new PdfNumber(NumberOfComponents);
+            switch (NumberOfComponents) {
+                case 1:
+                    put(PdfName.ALTERNATE, PdfName.DEVICEGRAY);
+                    break;
+                case 3:
+                    put(PdfName.ALTERNATE, PdfName.DEVICERGB);
+                    break;
+                case 4:
+                    put(PdfName.ALTERNATE, PdfName.DEVICECMYK);
+                    break;
+                default:
+                    throw new PdfException(NumberOfComponents + " component(s) is not supported in PDF1.4");
+            }
+            put(PdfName.N, new PdfNumber(NumberOfComponents));
+            bytes = profile.getData();
+            flateCompress();
+        } catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfImage.java b/LibrarySource/com/lowagie/text/pdf/PdfImage.java
new file mode 100644
index 0000000..0a2e0cb
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfImage.java
@@ -0,0 +1,281 @@
+/*
+ * $Id: PdfImage.java,v 1.58 2004/11/29 14:07:00 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ * REMARK:
+ * LZW/GIF is covered by a software patent which is owned by Unisys Corporation.
+ * Unisys refuses to license this patent for PDF-related use in software
+ * even when this software is released for free and may be freely distributed.
+ * HOWEVER:
+ * This library doesn't compress or decompress data using the LZW
+ * algorithm, nor does it create or visualize GIF-images in any way;
+ * it only copies parts of an existing GIF file into a PDF file.
+ *
+ * More information about the GIF format can be found in the following documents:
+ * * GRAPHICS INTERCHANGE FORMAT(sm) Version 89a
+ *   (c)1987,1988,1989,1990 Copyright CompuServe Incorporated. Columbus, Ohio
+ * * LZW and GIF explained
+ *   Steve Blackstock
+ * * http://mistress.informatik.unibw-muenchen.de/
+ *   very special thanks to klee at informatik.unibw-muenchen.de for the algorithm
+ *   to extract the LZW data from a GIF.
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Image;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * <CODE>PdfImage</CODE> is a <CODE>PdfStream</CODE> containing an image-<CODE>Dictionary</CODE> and -stream.
+ */
+
+class PdfImage extends PdfStream {
+    
+    static final int TRANSFERSIZE = 4096;
+    // membervariables
+    
+    /** This is the <CODE>PdfName</CODE> of the image. */
+    protected PdfName name = null;
+    
+    // constructor
+    
+    /**
+     * Constructs a <CODE>PdfImage</CODE>-object.
+     *
+     * @param image the <CODE>Image</CODE>-object
+     * @param name the <CODE>PdfName</CODE> for this image
+     * @throws BadPdfFormatException on error
+     */
+    
+    public PdfImage(Image image, String name, PdfIndirectReference maskRef) throws BadPdfFormatException {
+        super();
+        this.name = new PdfName(name);
+        put(PdfName.TYPE, PdfName.XOBJECT);
+        put(PdfName.SUBTYPE, PdfName.IMAGE);
+        put(PdfName.WIDTH, new PdfNumber(image.width()));
+        put(PdfName.HEIGHT, new PdfNumber(image.height()));
+        if (image.getLayer() != null)
+            put(PdfName.OC, image.getLayer().getRef());
+        if (image.isMask() && (image.bpc() == 1 || image.bpc() > 0xff))
+            put(PdfName.IMAGEMASK, PdfBoolean.PDFTRUE);
+        if (maskRef != null) {
+            if (image.isSmask())
+                put(PdfName.SMASK, maskRef);
+            else
+                put(PdfName.MASK, maskRef);
+        }
+        if (image.isMask() && image.isInvertMask())
+            put(PdfName.DECODE, new PdfLiteral("[1 0]"));
+        if (image.isInterpolation())
+            put(PdfName.INTERPOLATE, PdfBoolean.PDFTRUE);
+        InputStream is = null;
+        try {
+            
+            // Raw Image data
+            if (image.isImgRaw()) {
+                // will also have the CCITT parameters
+                int colorspace = image.colorspace();
+                int transparency[] = image.getTransparency();
+                if (transparency != null && !image.isMask() && maskRef == null) {
+                    String s = "[";
+                    for (int k = 0; k < transparency.length; ++k)
+                        s += transparency[k] + " ";
+                    s += "]";
+                    put(PdfName.MASK, new PdfLiteral(s));
+                }
+                bytes = image.rawData();
+                put(PdfName.LENGTH, new PdfNumber(bytes.length));
+                int bpc = image.bpc();
+                if (bpc > 0xff) {
+                    if (!image.isMask())
+                        put(PdfName.COLORSPACE, PdfName.DEVICEGRAY);
+                    put(PdfName.BITSPERCOMPONENT, new PdfNumber(1));
+                    put(PdfName.FILTER, PdfName.CCITTFAXDECODE);
+                    int k = bpc - Image.CCITTG3_1D;
+                    PdfDictionary decodeparms = new PdfDictionary();
+                    if (k != 0)
+                        decodeparms.put(PdfName.K, new PdfNumber(k));
+                    if ((colorspace & Image.CCITT_BLACKIS1) != 0)
+                        decodeparms.put(PdfName.BLACKIS1, PdfBoolean.PDFTRUE);
+                    if ((colorspace & Image.CCITT_ENCODEDBYTEALIGN) != 0)
+                        decodeparms.put(PdfName.ENCODEDBYTEALIGN, PdfBoolean.PDFTRUE);
+                    if ((colorspace & Image.CCITT_ENDOFLINE) != 0)
+                        decodeparms.put(PdfName.ENDOFLINE, PdfBoolean.PDFTRUE);
+                    if ((colorspace & Image.CCITT_ENDOFBLOCK) != 0)
+                        decodeparms.put(PdfName.ENDOFBLOCK, PdfBoolean.PDFFALSE);
+                    decodeparms.put(PdfName.COLUMNS, new PdfNumber(image.width()));
+                    decodeparms.put(PdfName.ROWS, new PdfNumber(image.height()));
+                    put(PdfName.DECODEPARMS, decodeparms);
+                }
+                else {
+                    switch(colorspace) {
+                        case 1:
+                            put(PdfName.COLORSPACE, PdfName.DEVICEGRAY);
+                            if (image.isInverted())
+                                put(PdfName.DECODE, new PdfLiteral("[1 0]"));
+                            break;
+                        case 3:
+                            put(PdfName.COLORSPACE, PdfName.DEVICERGB);
+                            if (image.isInverted())
+                                put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0]"));
+                            break;
+                        case 4:
+                        default:
+                            put(PdfName.COLORSPACE, PdfName.DEVICECMYK);
+                            if (image.isInverted())
+                                put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0 1 0]"));
+                    }
+                    PdfDictionary additional = image.getAdditional();
+                    if (additional != null)
+                        putAll(additional);
+                    if (image.isMask() && (image.bpc() == 1 || image.bpc() > 8))
+                        remove(PdfName.COLORSPACE);
+                    put(PdfName.BITSPERCOMPONENT, new PdfNumber(image.bpc()));
+                    if (image.isDeflated())
+                        put(PdfName.FILTER, PdfName.FLATEDECODE);
+                    else {
+                        flateCompress();
+                    }
+                }
+                return;
+            }
+            
+            // GIF, JPEG or PNG
+            String errorID;
+            if (image.rawData() == null){
+                is = image.url().openStream();
+                errorID = image.url().toString();
+            }
+            else{
+                is = new java.io.ByteArrayInputStream(image.rawData());
+                errorID = "Byte array";
+            }
+            int i = 0;
+            switch(image.type()) {
+                case Image.JPEG:
+                    put(PdfName.FILTER, PdfName.DCTDECODE);
+                    switch(image.colorspace()) {
+                        case 1:
+                            put(PdfName.COLORSPACE, PdfName.DEVICEGRAY);
+                            break;
+                        case 3:
+                            put(PdfName.COLORSPACE, PdfName.DEVICERGB);
+                            break;
+                        default:
+                            put(PdfName.COLORSPACE, PdfName.DEVICECMYK);
+                            if (image.isInverted()) {
+                                put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0 1 0]"));
+                            }
+                    }
+                    put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
+                    if (image.rawData() != null){
+                        bytes = image.rawData();
+                        put(PdfName.LENGTH, new PdfNumber(bytes.length));
+                        return;
+                    }
+                    streamBytes = new ByteArrayOutputStream();
+                    transferBytes(is, streamBytes, -1);
+                    break;
+                default:
+                    throw new BadPdfFormatException(errorID + " is an unknown Image format.");
+            }
+            put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
+        }
+        catch(IOException ioe) {
+            throw new BadPdfFormatException(ioe.getMessage());
+        }
+        finally {
+            if (is != null) {
+                try{
+                    is.close();
+                }
+                catch (Exception ee) {
+                    // empty on purpose
+                }
+            }
+        }
+    }
+    
+    /**
+     * Returns the <CODE>PdfName</CODE> of the image.
+     *
+     * @return		the name
+     */
+    
+    public PdfName name() {
+        return name;
+    }
+    
+    static void transferBytes(InputStream in, OutputStream out, int len) throws IOException {
+        byte buffer[] = new byte[TRANSFERSIZE];
+        if (len < 0)
+            len = 0x7ffffff;
+        int size;
+        while (len != 0) {
+            size = in.read(buffer, 0, Math.min(len, TRANSFERSIZE));
+            if (size < 0)
+                return;
+            out.write(buffer, 0, size);
+            len -= size;
+        }
+    }
+    
+    protected void importAll(PdfImage dup) {
+        name = dup.name;
+        compressed = dup.compressed;
+        streamBytes = dup.streamBytes;
+        bytes = dup.bytes;
+        hashMap = dup.hashMap;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfImportedPage.java b/LibrarySource/com/lowagie/text/pdf/PdfImportedPage.java
new file mode 100644
index 0000000..feb51fd
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfImportedPage.java
@@ -0,0 +1,150 @@
+/*
+ * $Id: PdfImportedPage.java,v 1.14 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Image;
+import java.io.IOException;
+
+/** Represents an imported page.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfImportedPage extends com.lowagie.text.pdf.PdfTemplate {
+
+    PdfReaderInstance readerInstance;
+    int pageNumber;
+    
+    PdfImportedPage(PdfReaderInstance readerInstance, PdfWriter writer, int pageNumber) {
+        this.readerInstance = readerInstance;
+        this.pageNumber = pageNumber;
+        thisReference = writer.getPdfIndirectReference();
+        bBox = readerInstance.getReader().getPageSize(pageNumber);
+        type = TYPE_IMPORTED;
+    }
+
+    /** Reads the content from this <CODE>PdfImportedPage</CODE>-object from a reader.
+     *
+     * @return self
+     *
+     */
+    public PdfImportedPage getFromReader() {
+      return this;
+    }
+
+    public int getPageNumber() {
+        return pageNumber;
+    }
+
+
+    /** Always throws an error. This operation is not allowed.
+     * @param image dummy
+     * @param a dummy
+     * @param b dummy
+     * @param c dummy
+     * @param d dummy
+     * @param e dummy
+     * @param f dummy
+     * @throws DocumentException  dummy */    
+    public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+        throwError();
+    }
+    
+    /** Always throws an error. This operation is not allowed.
+     * @param template dummy
+     * @param a dummy
+     * @param b dummy
+     * @param c dummy
+     * @param d dummy
+     * @param e dummy
+     * @param f  dummy */    
+    public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
+        throwError();
+    }
+    
+    /** Always throws an error. This operation is not allowed.
+     * @return  dummy */    
+    public PdfContentByte getDuplicate() {
+        throwError();
+        return null;
+    }
+    
+    PdfStream getFormXObject() throws IOException {
+         return readerInstance.getFormXObject(pageNumber);
+    }
+    
+    public void setColorFill(PdfSpotColor sp, float tint) {
+        throwError();
+    }
+    
+    public void setColorStroke(PdfSpotColor sp, float tint) {
+        throwError();
+    }
+    
+    PdfObject getResources() {
+        return readerInstance.getResources(pageNumber);
+    }
+    
+    /** Always throws an error. This operation is not allowed.
+     * @param bf dummy
+     * @param size dummy */    
+    public void setFontAndSize(BaseFont bf, float size) {
+        throwError();
+    }
+    
+    void throwError() {
+        throw new RuntimeException("Content can not be added to a PdfImportedPage.");
+    }
+    
+    PdfReaderInstance getPdfReaderInstance() {
+        return readerInstance;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfIndirectObject.java b/LibrarySource/com/lowagie/text/pdf/PdfIndirectObject.java
new file mode 100644
index 0000000..3880a7c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfIndirectObject.java
@@ -0,0 +1,171 @@
+/*
+ * $Id: PdfIndirectObject.java,v 1.35 2003/05/02 09:01:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import com.lowagie.text.DocWriter;
+
+/**
+ * <CODE>PdfIndirectObject</CODE> is the Pdf indirect object.
+ * <P>
+ * An <I>indirect object</I> is an object that has been labeled so that it can be referenced by
+ * other objects. Any type of <CODE>PdfObject</CODE> may be labeled as an indirect object.<BR>
+ * An indirect object consists of an object identifier, a direct object, and the <B>endobj</B>
+ * keyword. The <I>object identifier</I> consists of an integer <I>object number</I>, an integer
+ * <I>generation number</I>, and the <B>obj</B> keyword.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.10 (page 53).
+ *
+ * @see		PdfObject
+ * @see		PdfIndirectReference
+ */
+
+public class PdfIndirectObject {
+    
+    // membervariables
+    
+/** The object number */
+    protected int number;
+    
+/** the generation number */
+    protected int generation = 0;
+    
+    static final byte STARTOBJ[] = DocWriter.getISOBytes(" obj");
+    static final byte ENDOBJ[] = DocWriter.getISOBytes("\nendobj\n");
+    static final int SIZEOBJ = STARTOBJ.length + ENDOBJ.length;
+    PdfObject object;
+    PdfWriter writer;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfIndirectObject</CODE>.
+ *
+ * @param		number			the object number
+ * @param		object			the direct object
+ */
+    
+    PdfIndirectObject(int number, PdfObject object, PdfWriter writer) {
+        this(number, 0, object, writer);
+    }
+    
+    PdfIndirectObject(PdfIndirectReference ref, PdfObject object, PdfWriter writer) {
+        this(ref.getNumber(),ref.getGeneration(),object,writer);
+    }
+/**
+ * Constructs a <CODE>PdfIndirectObject</CODE>.
+ *
+ * @param		number			the object number
+ * @param		generation		the generation number
+ * @param		object			the direct object
+ */
+    
+    PdfIndirectObject(int number, int generation, PdfObject object, PdfWriter writer) {
+        this.writer = writer;
+        this.number = number;
+        this.generation = generation;
+        this.object = object;
+        PdfEncryption crypto = null;
+        if (writer != null)
+            crypto = writer.getEncryption();
+        if (crypto != null) {
+            crypto.setHashKey(number, generation);
+        }
+    }
+    
+    // methods
+    
+/**
+ * Return the length of this <CODE>PdfIndirectObject</CODE>.
+ *
+ * @return		the length of the PDF-representation of this indirect object.
+ */
+    
+//    public int length() {
+//        if (isStream)
+//            return bytes.size() + SIZEOBJ + stream.getStreamLength(writer);
+//        else
+//            return bytes.size();
+//    }
+    
+    
+/**
+ * Returns a <CODE>PdfIndirectReference</CODE> to this <CODE>PdfIndirectObject</CODE>.
+ *
+ * @return		a <CODE>PdfIndirectReference</CODE>
+ */
+    
+    public PdfIndirectReference getIndirectReference() {
+        return new PdfIndirectReference(object.type(), number, generation);
+    }
+    
+/**
+ * Writes eficiently to a stream
+ *
+ * @param os the stream to write to
+ * @throws IOException on write error
+ */
+    void writeTo(OutputStream os) throws IOException
+    {
+        os.write(DocWriter.getISOBytes(String.valueOf(number)));
+        os.write(' ');
+        os.write(DocWriter.getISOBytes(String.valueOf(generation)));
+        os.write(STARTOBJ);
+        int type = object.type();
+        if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+            os.write(' ');
+        object.toPdf(writer, os);
+        os.write(ENDOBJ);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfIndirectReference.java b/LibrarySource/com/lowagie/text/pdf/PdfIndirectReference.java
new file mode 100644
index 0000000..b3436ad
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfIndirectReference.java
@@ -0,0 +1,129 @@
+/*
+ * $Id: PdfIndirectReference.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfIndirectReference</CODE> contains a reference to a <CODE>PdfIndirectObject</CODE>.
+ * <P>
+ * Any object used as an element of an array or as a value in a dictionary may be specified
+ * by either a direct object of an indirect reference. An <I>indirect reference</I> is a reference
+ * to an indirect object, and consists of the indirect object's object number, generation number
+ * and the <B>R</B> keyword.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.11 (page 54).
+ *
+ * @see		PdfObject
+ * @see		PdfIndirectObject
+ */
+
+public class PdfIndirectReference extends PdfObject {
+    
+    // membervariables
+    
+/** the object number */
+    protected int number;
+    
+/** the generation number */
+    protected int generation = 0;
+    
+    // constructors
+    
+    protected PdfIndirectReference() {
+        super(0);
+    }
+    
+/**
+ * Constructs a <CODE>PdfIndirectReference</CODE>.
+ *
+ * @param		type			the type of the <CODE>PdfObject</CODE> that is referenced to
+ * @param		number			the object number.
+ * @param		generation		the generation number.
+ */
+    
+    PdfIndirectReference(int type, int number, int generation) {
+        super(0, new StringBuffer().append(number).append(" ").append(generation).append(" R").toString());
+        this.number = number;
+        this.generation = generation;
+    }
+    
+/**
+ * Constructs a <CODE>PdfIndirectReference</CODE>.
+ *
+ * @param		type			the type of the <CODE>PdfObject</CODE> that is referenced to
+ * @param		number			the object number.
+ */
+    
+    PdfIndirectReference(int type, int number) {
+        this(type, number, 0);
+    }
+    
+    // methods
+    
+/**
+ * Returns the number of the object.
+ *
+ * @return		a number.
+ */
+    
+    public int getNumber() {
+        return number;
+    }
+    
+/**
+ * Returns the generation of the object.
+ *
+ * @return		a number.
+ */
+    
+    public int getGeneration() {
+        return generation;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfLayer.java b/LibrarySource/com/lowagie/text/pdf/PdfLayer.java
new file mode 100644
index 0000000..6a835cf
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfLayer.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+/**
+ * An optional content group is a dictionary representing a collection of graphics
+ * that can be made visible or invisible dynamically by users of viewer applications.
+ * In iText they are referenced as layers.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfLayer extends PdfDictionary implements PdfOCG {
+    protected PdfIndirectReference ref;
+    protected ArrayList children;
+    protected PdfLayer parent;
+    protected String title;
+
+    /**
+     * Holds value of property on.
+     */
+    private boolean on = true;
+    
+    /**
+     * Holds value of property onPanel.
+     */
+    private boolean onPanel = true;
+    
+    PdfLayer(String title) {
+        this.title = title;
+    }
+    
+    /**
+     * Creates a title layer. A title layer is not really a layer but a collection of layers
+     * under the same title heading.
+     * @param title the title text
+     * @param writer the <CODE>PdfWriter</CODE>
+     * @return the title layer
+     */    
+    public static PdfLayer createTitle(String title, PdfWriter writer) {
+        if (title == null)
+            throw new NullPointerException("Title cannot be null.");
+        PdfLayer layer = new PdfLayer(title);
+        writer.registerLayer(layer);
+        return layer;
+    }
+    /**
+     * Creates a new layer.
+     * @param name the name of the layer
+     * @param writer the writer
+     */    
+    public PdfLayer(String name, PdfWriter writer) {
+        super(PdfName.OCG);
+        setName(name);
+        ref = writer.getPdfIndirectReference();
+        writer.registerLayer(this);
+    }
+    
+    String getTitle() {
+        return title;
+    }
+    
+    /**
+     * Adds a child layer. Nested layers can only have one parent.
+     * @param child the child layer
+     */    
+    public void addChild(PdfLayer child) {
+        if (child.parent != null)
+            throw new IllegalArgumentException("The layer '" + ((PdfString)child.get(PdfName.NAME)).toUnicodeString() + "' already has a parent.");
+        child.parent = this;
+        if (children == null)
+            children = new ArrayList();
+        children.add(child);
+    }
+
+    
+    /**
+     * Gets the parent layer.
+     * @return the parent layer or <CODE>null</CODE> if the layer has no parent
+     */    
+    public PdfLayer getParent() {
+        return parent;
+    }
+    
+    /**
+     * Gets the children layers.
+     * @return the children layers or <CODE>null</CODE> if the layer has no children
+     */    
+    public ArrayList getChildren() {
+        return children;
+    }
+    
+    /**
+     * Gets the <CODE>PdfIndirectReference</CODE> that represents this layer.
+     * @return the <CODE>PdfIndirectReference</CODE> that represents this layer
+     */    
+    public PdfIndirectReference getRef() {
+        return ref;
+    }
+    
+    /**
+     * Sets the name of this layer.
+     * @param name the name of this layer
+     */    
+    public void setName(String name) {
+        put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
+    }
+    
+    /**
+     * Gets the dictionary representing the layer. It just returns <CODE>this</CODE>.
+     * @return the dictionary representing the layer
+     */    
+    public PdfObject getPdfObject() {
+        return this;
+    }
+    
+    /**
+     * Gets the initial visibility of the layer.
+     * @return the initial visibility of the layer
+     */
+    public boolean isOn() {
+        return this.on;
+    }
+    
+    /**
+     * Sets the initial visibility of the layer.
+     * @param on the initial visibility of the layer
+     */
+    public void setOn(boolean on) {
+        this.on = on;
+    }
+    
+    private PdfDictionary getUsage() {
+        PdfDictionary usage = (PdfDictionary)get(PdfName.USAGE);
+        if (usage == null) {
+            usage = new PdfDictionary();
+            put(PdfName.USAGE, usage);
+        }
+        return usage;
+    }
+    
+    /**
+     * Used by the creating application to store application-specific
+     * data associated with this optional content group.
+     * @param creator a text string specifying the application that created the group
+     * @param subtype a string defining the type of content controlled by the group. Suggested
+     * values include but are not limited to <B>Artwork</B>, for graphic-design or publishing
+     * applications, and <B>Technical</B>, for technical designs such as building plans or
+     * schematics
+     */    
+    public void setCreatorInfo(String creator, String subtype) {
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.CREATOR, new PdfString(creator, PdfObject.TEXT_UNICODE));
+        dic.put(PdfName.SUBTYPE, new PdfName(subtype));
+        usage.put(PdfName.CREATORINFO, dic);
+    }
+    
+    /**
+     * Specifies the language of the content controlled by this
+     * optional content group
+     * @param lang a language string which specifies a language and possibly a locale
+     * (for example, <B>es-MX</B> represents Mexican Spanish)
+     * @param preferred used by viewer applications when there is a partial match but no exact
+     * match between the system language and the language strings in all usage dictionaries
+     */    
+    public void setLanguage(String lang, boolean preferred) {
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.LANG, new PdfString(lang, PdfObject.TEXT_UNICODE));
+        if (preferred)
+            dic.put(PdfName.PREFERRED, PdfName.ON);
+        usage.put(PdfName.LANGUAGE, dic);
+    }
+    
+    /**
+     * Specifies the recommended state for content in this
+     * group when the document (or part of it) is saved by a viewer application to a format
+     * that does not support optional content (for example, an earlier version of
+     * PDF or a raster image format).
+     * @param export the export state
+     */    
+    public void setExport(boolean export) {
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.EXPORTSTATE, export ? PdfName.ON : PdfName.OFF);
+        usage.put(PdfName.EXPORT, dic);
+    }
+    
+    /**
+     * Specifies a range of magnifications at which the content
+     * in this optional content group is best viewed.
+     * @param min the minimum recommended magnification factors at which the group
+     * should be ON. A negative value will set the default to 0
+     * @param max the maximum recommended magnification factor at which the group
+     * should be ON. A negative value will set the largest possible magnification supported by the
+     * viewer application
+     */    
+    public void setZoom(float min, float max) {
+        if (min <= 0 && max < 0)
+            return;
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        if (min > 0)
+            dic.put(PdfName.MIN, new PdfNumber(min));
+        if (max >= 0)
+            dic.put(PdfName.MAX, new PdfNumber(max));
+        usage.put(PdfName.ZOOM, dic);
+    }
+
+    /**
+     * Specifies that the content in this group is intended for
+     * use in printing
+     * @param subtype a name specifying the kind of content controlled by the group;
+     * for example, <B>Trapping</B>, <B>PrintersMarks</B> and <B>Watermark</B>
+     * @param printstate indicates that the group should be
+     * set to that state when the document is printed from a viewer application
+     */    
+    public void setPrint(String subtype, boolean printstate) {
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.SUBTYPE, new PdfName(subtype));
+        dic.put(PdfName.PRINTSTATE, printstate ? PdfName.ON : PdfName.OFF);
+        usage.put(PdfName.PRINT, dic);
+    }
+
+    /**
+     * Indicates that the group should be set to that state when the
+     * document is opened in a viewer application.
+     * @param view the view state
+     */    
+    public void setView(boolean view) {
+        PdfDictionary usage = getUsage();
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(PdfName.VIEWSTATE, view ? PdfName.ON : PdfName.OFF);
+        usage.put(PdfName.VIEW, dic);
+    }
+    
+    /**
+     * Gets the layer visibility in Acrobat's layer panel
+     * @return the layer visibility in Acrobat's layer panel
+     */
+    public boolean isOnPanel() {
+        return this.onPanel;
+    }
+    
+    /**
+     * Sets the visibility of the layer in Acrobat's layer panel. If <CODE>false</CODE>
+     * the layer cannot be directly manipulated by the user. Note that any children layers will
+     * also be absent from the panel.
+     * @param onPanel the visibility of the layer in Acrobat's layer panel
+     */
+    public void setOnPanel(boolean onPanel) {
+        this.onPanel = onPanel;
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfLayerMembership.java b/LibrarySource/com/lowagie/text/pdf/PdfLayerMembership.java
new file mode 100644
index 0000000..c899134
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfLayerMembership.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Collection;
+
+/**
+ * Content typically belongs to a single optional content group,
+ * and is visible when the group is <B>ON</B> and invisible when it is <B>OFF</B>. To express more
+ * complex visibility policies, content should not declare itself to belong to an optional
+ * content group directly, but rather to an optional content membership dictionary
+ * represented by this class.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfLayerMembership extends PdfDictionary implements PdfOCG {
+    
+    /**
+     * Visible only if all of the entries are <B>ON</B>.
+     */    
+    public static PdfName ALLON = new PdfName("AllOn");
+    /**
+     * Visible if any of the entries are <B>ON</B>.
+     */    
+    public static PdfName ANYON = new PdfName("AnyOn");
+    /**
+     * Visible if any of the entries are <B>OFF</B>.
+     */    
+    public static PdfName ANYOFF = new PdfName("AnyOff");
+    /**
+     * Visible only if all of the entries are <B>OFF</B>.
+     */    
+    public static PdfName ALLOFF = new PdfName("AllOff");
+
+    PdfIndirectReference ref;
+    PdfArray members = new PdfArray();
+    HashSet layers = new HashSet();
+    
+    /**
+     * Creates a new, empty, membership layer.
+     * @param writer the writer
+     */    
+    public PdfLayerMembership(PdfWriter writer) {
+        super(PdfName.OCMD);
+        put(PdfName.OCGS, members);
+        ref = writer.getPdfIndirectReference();
+    }
+    
+    /**
+     * Gets the <CODE>PdfIndirectReference</CODE> that represents this membership layer.
+     * @return the <CODE>PdfIndirectReference</CODE> that represents this layer
+     */    
+    public PdfIndirectReference getRef() {
+        return ref;
+    }
+    
+    /**
+     * Adds a new member to the layer.
+     * @param layer the new member to the layer
+     */    
+    public void addMember(PdfLayer layer) {
+        if (!layers.contains(layer)) {
+            members.add(layer.getRef());
+            layers.add(layer);
+        }
+    }
+    
+    /**
+     * Gets the member layers.
+     * @return the member layers
+     */    
+    public Collection getLayers() {
+        return layers;
+    }
+    
+    /**
+     * Sets the visibility policy for content belonging to this
+     * membership dictionary. Possible values are ALLON, ANYON, ANYOFF and ALLOFF.
+     * The default value is ANYON.
+     * @param type the visibility policy
+     */    
+    public void setVisibilityPolicy(PdfName type) {
+        put(PdfName.P, type);
+    }
+    
+    /**
+     * Gets the dictionary representing the membership layer. It just returns <CODE>this</CODE>.
+     * @return the dictionary representing the layer
+     */    
+    public PdfObject getPdfObject() {
+        return this;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfLine.java b/LibrarySource/com/lowagie/text/pdf/PdfLine.java
new file mode 100644
index 0000000..60f8b62
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfLine.java
@@ -0,0 +1,476 @@
+/*
+ * $Id: PdfLine.java,v 1.65 2005/04/08 07:33:22 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.lowagie.text.Element;
+import com.lowagie.text.ListItem;
+
+/**
+ * <CODE>PdfLine</CODE> defines an array with <CODE>PdfChunk</CODE>-objects
+ * that fit into 1 line.
+ */
+
+public class PdfLine {
+    
+    // membervariables
+    
+    /** The arraylist containing the chunks. */
+    protected ArrayList line;
+    
+    /** The left indentation of the line. */
+    protected float left;
+    
+    /** The width of the line. */
+    protected float width;
+    
+    /** The alignment of the line. */
+    protected int alignment;
+    
+    /** The heigth of the line. */
+    protected float height;
+    
+    /** The listsymbol (if necessary). */
+    protected PdfChunk listSymbol = null;
+    
+    /** The listsymbol (if necessary). */
+    protected float symbolIndent;
+    
+    /** <CODE>true</CODE> if the chunk splitting was caused by a newline. */
+    protected boolean newlineSplit = false;
+    
+    /** The original width. */
+    protected float originalWidth;
+    
+    protected boolean isRTL = false;
+    
+    // constructors
+    
+    /**
+     * Constructs a new <CODE>PdfLine</CODE>-object.
+     *
+     * @param	left		the limit of the line at the left
+     * @param	right		the limit of the line at the right
+     * @param	alignment	the alignment of the line
+     * @param	height		the height of the line
+     */
+    
+    PdfLine(float left, float right, int alignment, float height) {
+        this.left = left;
+        this.width = right - left;
+        this.originalWidth = this.width;
+        this.alignment = alignment;
+        this.height = height;
+        this.line = new ArrayList();
+    }
+    
+    PdfLine(float left, float remainingWidth, int alignment, boolean newlineSplit, ArrayList line, boolean isRTL) {
+        this.left = left;
+        this.width = remainingWidth;
+        this.alignment = alignment;
+        this.line = line;
+        this.newlineSplit = newlineSplit;
+        this.isRTL = isRTL;
+    }
+    
+    // methods
+    
+    /**
+     * Adds a <CODE>PdfChunk</CODE> to the <CODE>PdfLine</CODE>.
+     *
+     * @param		chunk		the <CODE>PdfChunk</CODE> to add
+     * @return		<CODE>null</CODE> if the chunk could be added completely; if not
+     *				a <CODE>PdfChunk</CODE> containing the part of the chunk that could
+     *				not be added is returned
+     */
+    
+    PdfChunk add(PdfChunk chunk) {
+        // nothing happens if the chunk is null.
+        if (chunk == null || chunk.toString().equals("")) {
+            return null;
+        }
+        
+        // we split the chunk to be added
+        PdfChunk overflow = chunk.split(width);
+        newlineSplit = (chunk.isNewlineSplit() || overflow == null);
+        //        if (chunk.isNewlineSplit() && alignment == Element.ALIGN_JUSTIFIED)
+        //            alignment = Element.ALIGN_LEFT;
+        
+        
+        // if the length of the chunk > 0 we add it to the line
+        if (chunk.length() > 0) {
+            if (overflow != null)
+                chunk.trimLastSpace();
+            width -= chunk.width();
+            line.add(chunk);
+        }
+        
+        // if the length == 0 and there were no other chunks added to the line yet,
+        // we risk to end up in an endless loop trying endlessly to add the same chunk
+        else if (line.size() < 1) {
+            chunk = overflow;
+            overflow = chunk.truncate(width);
+            width -= chunk.width();
+            if (chunk.length() > 0) {
+                line.add(chunk);
+                return overflow;
+            }
+            // if the chunck couldn't even be truncated, we add everything, so be it
+            else {
+                if (overflow != null)
+                    line.add(overflow);
+                return null;
+            }
+        }
+        else {
+            width += ((PdfChunk)(line.get(line.size() - 1))).trimLastSpace();
+        }
+        return overflow;
+    }
+    
+    // methods to retrieve information
+    
+    /**
+     * Returns the number of chunks in the line.
+     *
+     * @return	a value
+     */
+    
+    public int size() {
+        return line.size();
+    }
+    
+    /**
+     * Returns an iterator of <CODE>PdfChunk</CODE>s.
+     *
+     * @return	an <CODE>Iterator</CODE>
+     */
+    
+    public Iterator iterator() {
+        return line.iterator();
+    }
+    
+    /**
+     * Returns the height of the line.
+     *
+     * @return	a value
+     */
+    
+    float height() {
+        return height;
+    }
+    
+    /**
+     * Returns the left indentation of the line taking the alignment of the line into account.
+     *
+     * @return	a value
+     */
+    
+    float indentLeft() {
+        if (isRTL) {
+            switch (alignment) {
+                case Element.ALIGN_LEFT:
+                    return left + width;
+                case Element.ALIGN_CENTER:
+                    return left + (width / 2f);
+                default:
+                    return left;
+            }
+        }
+        else {
+            switch (alignment) {
+                case Element.ALIGN_RIGHT:
+                    return left + width;
+                case Element.ALIGN_CENTER:
+                    return left + (width / 2f);
+                default:
+                    return left;
+            }
+        }
+    }
+    
+    /**
+     * Checks if this line has to be justified.
+     *
+     * @return	<CODE>true</CODE> if the alignment equals <VAR>ALIGN_JUSTIFIED</VAR> and there is some width left.
+     */
+    
+    public boolean hasToBeJustified() {
+        return ((alignment == Element.ALIGN_JUSTIFIED || alignment == Element.ALIGN_JUSTIFIED_ALL) && width != 0);
+    }
+    
+    /**
+     * Resets the alignment of this line.
+     * <P>
+     * The alignment of the last line of for instance a <CODE>Paragraph</CODE>
+     * that has to be justified, has to be reset to <VAR>ALIGN_LEFT</VAR>.
+     */
+    
+    public void resetAlignment() {
+        if (alignment == Element.ALIGN_JUSTIFIED) {
+            alignment = Element.ALIGN_LEFT;
+        }
+    }
+    
+    /**
+     * Returns the width that is left, after a maximum of characters is added to the line.
+     *
+     * @return	a value
+     */
+    
+    float widthLeft() {
+        return width;
+    }
+    
+    /**
+     * Returns the number of space-characters in this line.
+     *
+     * @return	a value
+     */
+    
+    int numberOfSpaces() {
+        String string = toString();
+        int length = string.length();
+        int numberOfSpaces = 0;
+        for (int i = 0; i < length; i++) {
+            if (string.charAt(i) == ' ') {
+                numberOfSpaces++;
+            }
+        }
+        return numberOfSpaces;
+    }
+    
+    /**
+     * Sets the listsymbol of this line.
+     * <P>
+     * This is only necessary for the first line of a <CODE>ListItem</CODE>.
+     *
+     * @param listItem the list symbol
+     */
+    
+    public void setListItem(ListItem listItem) {
+        this.listSymbol = new PdfChunk(listItem.listSymbol(), null);
+        this.symbolIndent = listItem.indentationLeft();
+    }
+    
+    /**
+     * Returns the listsymbol of this line.
+     *
+     * @return	a <CODE>PdfChunk</CODE> if the line has a listsymbol; <CODE>null</CODE> otherwise
+     */
+    
+    public PdfChunk listSymbol() {
+        return listSymbol;
+    }
+    
+    /**
+     * Return the indentation needed to show the listsymbol.
+     *
+     * @return	a value
+     */
+    
+    public float listIndent() {
+        return symbolIndent;
+    }
+    
+    /**
+     * Get the string representation of what is in this line.
+     *
+     * @return	a <CODE>String</CODE>
+     */
+    
+    public String toString() {
+        StringBuffer tmp = new StringBuffer();
+        for (Iterator i = line.iterator(); i.hasNext(); ) {
+            tmp.append(((PdfChunk) i.next()).toString());
+        }
+        return tmp.toString();
+    }
+    
+    /**
+     * Checks if a newline caused the line split.
+     * @return <CODE>true</CODE> if a newline caused the line split
+     */
+    public boolean isNewlineSplit() {
+        return newlineSplit && (alignment != Element.ALIGN_JUSTIFIED_ALL);
+    }
+    
+    /**
+     * Gets the index of the last <CODE>PdfChunk</CODE> with metric attributes
+     * @return the last <CODE>PdfChunk</CODE> with metric attributes
+     */
+    public int getLastStrokeChunk() {
+        int lastIdx = line.size() - 1;
+        for (; lastIdx >= 0; --lastIdx) {
+            PdfChunk chunk = (PdfChunk)line.get(lastIdx);
+            if (chunk.isStroked())
+                break;
+        }
+        return lastIdx;
+    }
+    
+    /**
+     * Gets a <CODE>PdfChunk</CODE> by index.
+     * @param idx the index
+     * @return the <CODE>PdfChunk</CODE> or null if beyond the array
+     */
+    public PdfChunk getChunk(int idx) {
+        if (idx < 0 || idx >= line.size())
+            return null;
+        return (PdfChunk)line.get(idx);
+    }
+    
+    /**
+     * Gets the original width of the line.
+     * @return the original width of the line
+     */
+    public float getOriginalWidth() {
+        return originalWidth;
+    }
+    
+    /**
+     * Gets the maximum size of all the fonts used in this line
+     * including images (if there are images in the line and if
+     * the leading has to be changed).
+     * @return maximum size of all the fonts used in this line
+     */
+    float getMaxSize() {
+        float maxSize = 0;
+        for (int k = 0; k < line.size(); ++k) {
+            PdfChunk chunk = (PdfChunk)line.get(k);
+            if (!chunk.isImage() || !chunk.changeLeading()) {
+                maxSize = Math.max(chunk.font().size(), maxSize);
+            }
+            else {
+                maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
+            }
+        }
+        return maxSize;
+    }
+    
+    /**
+     * Gets the maximum size of all the fonts used in this line
+     * including images.
+     * @return maximum size of all the fonts used in this line
+     */
+    float getMaxSizeSimple() {
+        float maxSize = 0;
+        for (int k = 0; k < line.size(); ++k) {
+            PdfChunk chunk = (PdfChunk)line.get(k);
+            if (!chunk.isImage()) {
+                maxSize = Math.max(chunk.font().size(), maxSize);
+            }
+            else {
+                maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
+            }
+        }
+        return maxSize;
+    }
+    
+    boolean isRTL() {
+        return isRTL;
+    }
+    
+    /**
+     * Gets a width corrected with a charSpacing and wordSpacing.
+     * @param charSpacing
+     * @param wordSpacing
+     * @return a corrected width
+     */
+    public float getWidthCorrected(float charSpacing, float wordSpacing) {
+        float total = 0;
+        for (int k = 0; k < line.size(); ++k) {
+            PdfChunk ck = (PdfChunk)line.get(k);
+            total += ck.getWidthCorrected(charSpacing, wordSpacing);
+        }
+        return total;
+    }
+    
+/**
+ * Gets the maximum size of the ascender for all the fonts used
+ * in this line.
+ * @return maximum size of all the ascenders used in this line
+ */
+   public float getAscender() {
+       float ascender = 0;
+       for (int k = 0; k < line.size(); ++k) {
+           PdfChunk ck = (PdfChunk)line.get(k);
+           if (ck.isImage())
+               ascender = Math.max(ascender, ck.getImage().scaledHeight() + ck.getImageOffsetY());
+           else {
+               PdfFont font = ck.font();
+               ascender = Math.max(ascender, font.getFont().getFontDescriptor(BaseFont.ASCENT, font.size()));
+           }
+       }
+       return ascender;
+   }
+
+/**
+ * Gets the biggest descender for all the fonts used 
+ * in this line.  Note that this is a negative number.
+ * @return maximum size of all the ascenders used in this line
+ */
+    public float getDescender() {
+        float descender = 0;
+        for (int k = 0; k < line.size(); ++k) {
+            PdfChunk ck = (PdfChunk)line.get(k);
+            if (ck.isImage())
+                descender = Math.min(descender, ck.getImageOffsetY());
+            else {
+                PdfFont font = ck.font();
+                descender = Math.min(descender, font.getFont().getFontDescriptor(BaseFont.DESCENT, font.size()));
+            }
+        }
+        return descender;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfLister.java b/LibrarySource/com/lowagie/text/pdf/PdfLister.java
new file mode 100644
index 0000000..fc6932f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfLister.java
@@ -0,0 +1,187 @@
+/*
+ * $Id: PdfLister.java,v 1.33 2005/02/01 14:30:50 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * This class by Mark Thompson. Copyright (C) 2002 Mark Thompson
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+ package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.Iterator;
+/**
+ * List a PDF file in human-readable form (for debugging reasons mostly)
+ * @author Mark Thompson
+ */
+
+public class PdfLister {
+
+	/** the printStream you want to write the output to. */
+    PrintStream out;
+
+    /**
+     * Create a new lister object.
+     * @param out
+     */
+    public PdfLister(PrintStream out) {
+        this.out = out;
+    }
+
+    /**
+     * Visualizes a PDF object.
+     * @param object	a com.lowagie.text.pdf object
+     */
+    public void listAnyObject(PdfObject object)
+    {
+        switch (object.type()) {
+        case PdfObject.ARRAY:
+            listArray((PdfArray)object);
+            break;
+        case PdfObject.DICTIONARY:
+            listDict((PdfDictionary) object);
+            break;
+        case PdfObject.STRING:
+            out.println("(" + object.toString() + ")");
+            break;
+        default:
+            out.println(object.toString());
+            break;
+        }
+    }
+    /**
+     * Visualizes a PdfDictionary object.
+     * @param dictionary	a com.lowagie.text.pdf.PdfDictionary object
+     */
+    public void listDict(PdfDictionary dictionary)
+    {
+        out.println("<<");
+        PdfName key;
+        PdfObject value;
+        for (Iterator i = dictionary.getKeys().iterator(); i.hasNext(); ) {
+            key = (PdfName) i.next();
+            value = (PdfObject) dictionary.get(key);
+            out.print(key.toString());
+            out.print(' ');
+            listAnyObject(value);
+        }
+        out.println(">>");
+    }
+
+    /**
+     * Visualizes a PdfArray object.
+     * @param array	a com.lowagie.text.pdf.PdfArray object
+     */
+    public void listArray(PdfArray array)
+    {
+        out.println('[');
+        for (Iterator i = array.getArrayList().iterator(); i.hasNext(); ) {
+            PdfObject item = (PdfObject)i.next();
+            listAnyObject(item);
+        }
+        out.println(']');
+    }
+    /**
+     * Visualizes a Stream.
+     * @param stream
+     * @param reader
+     */
+    public void listStream(PRStream stream, PdfReaderInstance reader)
+    {
+        try {
+            listDict(stream);
+            out.println("startstream");
+            byte[] b = PdfReader.getStreamBytes(stream);
+//                  byte buf[] = new byte[Math.min(stream.getLength(), 4096)];
+//                  int r = 0;
+//                  stream.openStream(reader);
+//                  for (;;) {
+//                      r = stream.readStream(buf, 0, buf.length);
+//                      if (r == 0) break;
+//                      out.write(buf, 0, r);
+//                  }
+//                  stream.closeStream();
+            int len = b.length - 1;
+            for (int k = 0; k < len; ++k) {
+                if (b[k] == '\r' && b[k + 1] != '\n')
+                    b[k] = (byte)'\n';
+            }
+            out.println(new String(b));
+            out.println("endstream");
+        } catch (IOException e) {
+            System.err.println("I/O exception: " + e);
+//          } catch (java.util.zip.DataFormatException e) {
+//              System.err.println("Data Format Exception: " + e);
+        }
+    }
+    /**
+     * Visualizes an imported page
+     * @param iPage
+     */
+    public void listPage(PdfImportedPage iPage)
+    {
+        int pageNum = iPage.getPageNumber();
+        PdfReaderInstance readerInst = iPage.getPdfReaderInstance();
+        PdfReader reader = readerInst.getReader();
+
+        PdfDictionary page = reader.getPageN(pageNum);
+        listDict(page);
+        PdfObject obj = PdfReader.getPdfObject(page.get(PdfName.CONTENTS));
+        switch (obj.type) {
+        case PdfObject.STREAM:
+            listStream((PRStream)obj, readerInst);
+            break;
+        case PdfObject.ARRAY:
+            for (Iterator i = ((PdfArray)obj).getArrayList().iterator(); i.hasNext();) {
+                PdfObject o = PdfReader.getPdfObject((PdfObject)i.next());
+                listStream((PRStream)o, readerInst);
+                out.println("-----------");
+            }
+            break;
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfLiteral.java b/LibrarySource/com/lowagie/text/pdf/PdfLiteral.java
new file mode 100644
index 0000000..b64a823
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfLiteral.java
@@ -0,0 +1,111 @@
+/*
+ * $Id: PdfLiteral.java,v 1.21 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * a Literal
+ */
+
+public class PdfLiteral extends PdfObject {
+    
+    /**
+     * Holds value of property position.
+     */
+    private int position;
+        
+    public PdfLiteral(String text) {
+        super(0, text);
+    }
+    
+    public PdfLiteral(byte b[]) {
+        super(0, b);
+    }
+
+    public PdfLiteral(int size) {
+        super(0, (byte[])null);
+        bytes = new byte[size];
+        java.util.Arrays.fill(bytes, (byte)32);
+    }
+
+    public PdfLiteral(int type, String text) {
+        super(type, text);
+    }
+    
+    public PdfLiteral(int type, byte b[]) {
+        super(type, b);
+    }
+    
+    public void toPdf(PdfWriter writer, java.io.OutputStream os) throws java.io.IOException {
+        if (os instanceof OutputStreamCounter)
+            position = ((OutputStreamCounter)os).getCounter();
+        super.toPdf(writer, os);
+    }
+    
+    /**
+     * Getter for property position.
+     * @return Value of property position.
+     */
+    public int getPosition() {
+        return this.position;
+    }
+    
+    /**
+     * Getter for property posLength.
+     * @return Value of property posLength.
+     */
+    public int getPosLength() {
+        if (bytes != null)
+            return bytes.length;
+        else
+            return 0;
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfMediaClipData.java b/LibrarySource/com/lowagie/text/pdf/PdfMediaClipData.java
new file mode 100644
index 0000000..8fbd689
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfMediaClipData.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2003 Galo Gimenez
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+public class PdfMediaClipData extends PdfDictionary {
+    
+    PdfMediaClipData(String file, PdfFileSpecification fs, String mimeType) throws IOException {
+        put(PdfName.TYPE,new PdfName("MediaClip"));
+        put(PdfName.S, new PdfName("MCD"));
+        put(PdfName.N, new PdfString("Media clip for "+file));
+        put(new PdfName("CT"), new PdfString(mimeType));
+        PdfDictionary dic = new PdfDictionary();
+        dic.put(new PdfName("TF"), new PdfString("TEMPACCESS"));
+        put(new PdfName("P"), dic);
+        put(PdfName.D, fs.getReference());
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfName.java b/LibrarySource/com/lowagie/text/pdf/PdfName.java
new file mode 100644
index 0000000..c4cbb40
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfName.java
@@ -0,0 +1,1093 @@
+/*
+ * $Id: PdfName.java,v 1.34 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfName</CODE> is an object that can be used as a name in a PDF-file.
+ * <P>
+ * A name, like a string, is a sequence of characters. It must begin with a slash
+ * followed by a sequence of ASCII characters in the range 32 through 136 except
+ * %, (, ), [, ], <, >, {, }, / and #. Any character except 0x00 may be included
+ * in a name by writing its twocharacter hex code, preceded by #. The maximum number
+ * of characters in a name is 127.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.5 (page 39-40).
+ * <P>
+ *
+ * @see		PdfObject
+ * @see		PdfDictionary
+ * @see		BadPdfFormatException
+ */
+
+public class PdfName extends PdfObject implements Comparable{
+    
+    // static membervariables (a variety of standard names used in PDF)
+    
+    /** A name */
+    public static final PdfName A = new PdfName("A");    
+    /** A name */
+    public static final PdfName AA = new PdfName("AA");
+    /** A name */
+    public static final PdfName ABSOLUTECALORIMETRIC = new PdfName("AbsoluteColorimetric");
+    /** A name */
+    public static final PdfName AC = new PdfName("AC");
+    /** A name */
+    public static final PdfName ACROFORM = new PdfName("AcroForm");
+    /** A name */
+    public static final PdfName ACTION = new PdfName("Action");
+    /** A name */
+    public static final PdfName ADBE_PKCS7_DETACHED = new PdfName("adbe.pkcs7.detached");
+    /** A name */
+    public static final PdfName ADBE_PKCS7_SHA1 = new PdfName("adbe.pkcs7.sha1");
+    /** A name */
+    public static final PdfName ADBE_X509_RSA_SHA1 = new PdfName("adbe.x509.rsa_sha1");
+    /** A name */
+    public static final PdfName ADOBE_PPKLITE = new PdfName("Adobe.PPKLite");
+    /** A name */
+    public static final PdfName ADOBE_PPKMS = new PdfName("Adobe.PPKMS");
+    /** A name */
+    public static final PdfName AIS = new PdfName("AIS");
+    /** A name */
+    public static final PdfName ALLPAGES = new PdfName("AllPages");
+    /** A name */
+    public static final PdfName ALTERNATE = new PdfName("Alternate");
+    /** A name */
+    public static final PdfName ANNOT = new PdfName("Annot");
+    /** A name */
+    public static final PdfName ANTIALIAS = new PdfName("AntiAlias");
+    /** A name */
+    public static final PdfName ANNOTS = new PdfName("Annots");
+    /** A name */
+    public static final PdfName AP = new PdfName("AP");
+    /** A name */
+    public static final PdfName ARTBOX = new PdfName("ArtBox");
+    /** A name */
+    public static final PdfName ASCENT = new PdfName("Ascent");
+    /** A name */
+    public static final PdfName AS = new PdfName("AS");
+    /** A name */
+    public static final PdfName ASCII85DECODE = new PdfName("ASCII85Decode");
+    /** A name */
+    public static final PdfName ASCIIHEXDECODE = new PdfName("ASCIIHexDecode");
+    /** A name */
+    public static final PdfName AUTHOR = new PdfName("Author");
+    /** A name */
+    public static final PdfName B = new PdfName("B");
+    /** A name */
+    public static final PdfName BASEENCODING = new PdfName("BaseEncoding");
+    /** A name */
+    public static final PdfName BASEFONT = new PdfName("BaseFont");
+    /** A name */
+    public static final PdfName BBOX = new PdfName("BBox");
+    /** A name */
+    public static final PdfName BC = new PdfName("BC");
+    /** A name */
+    public static final PdfName BG = new PdfName("BG");
+    /** A name */
+    public static final PdfName BIGFIVE = new PdfName("BigFive");
+    /** A name */
+    public static final PdfName BITSPERCOMPONENT = new PdfName("BitsPerComponent");
+    /** A name */
+    public static final PdfName BITSPERSAMPLE = new PdfName("BitsPerSample");
+    /** A name */
+    public static final PdfName BL = new PdfName("Bl");
+    /** A name */
+    public static final PdfName BLACKIS1 = new PdfName("BlackIs1");
+    /** A name */
+    public static final PdfName BLACKPOINT = new PdfName("BlackPoint");
+    /** A name */
+    public static final PdfName BLEEDBOX = new PdfName("BleedBox");
+    /** A name */
+    public static final PdfName BLINDS = new PdfName("Blinds");
+    /** A name */
+    public static final PdfName BM = new PdfName("BM");
+    /** A name */
+    public static final PdfName BORDER = new PdfName("Border");
+    /** A name */
+    public static final PdfName BOUNDS = new PdfName("Bounds");
+    /** A name */
+    public static final PdfName BOX = new PdfName("Box");
+    /** A name */
+    public static final PdfName BS = new PdfName("BS");
+    /** A name */
+    public static final PdfName BTN = new PdfName("Btn");
+    /** A name */
+    public static final PdfName BYTERANGE = new PdfName("ByteRange");
+    /** A name */
+    public static final PdfName C = new PdfName("C");
+    /** A name */
+    public static final PdfName C0 = new PdfName("C0");
+    /** A name */
+    public static final PdfName C1 = new PdfName("C1");
+    /** A name */
+    public static final PdfName CA = new PdfName("CA");
+    /** A name */
+    public static final PdfName ca = new PdfName("ca");
+    /** A name */
+    public static final PdfName CALGRAY = new PdfName("CalGray");
+    /** A name */
+    public static final PdfName CALRGB = new PdfName("CalRGB");
+    /** A name */
+    public static final PdfName CAPHEIGHT = new PdfName("CapHeight");
+    /** A name */
+    public static final PdfName CATALOG = new PdfName("Catalog");
+    /** A name */
+    public static final PdfName CATEGORY = new PdfName("Category");
+    /** A name */
+    public static final PdfName CCITTFAXDECODE = new PdfName("CCITTFaxDecode");
+    /** A name */
+    public static final PdfName CENTERWINDOW = new PdfName("CenterWindow");
+    /** A name */
+    public static final PdfName CERT = new PdfName("Cert");
+    /** A name */
+    public static final PdfName CH = new PdfName("Ch");
+    /** A name */
+    public static final PdfName CIDFONTTYPE0 = new PdfName("CIDFontType0");
+    /** A name */
+    public static final PdfName CIDFONTTYPE2 = new PdfName("CIDFontType2");
+    /** A name */
+    public static final PdfName CIDSYSTEMINFO = new PdfName("CIDSystemInfo");
+    /** A name */
+    public static final PdfName CIDTOGIDMAP = new PdfName("CIDToGIDMap");
+    /** A name */
+    public static final PdfName CIRCLE = new PdfName("Circle");
+    /** A name */
+    public static final PdfName CO = new PdfName("CO");
+    /** A name */
+    public static final PdfName COLORS = new PdfName("Colors");
+    /** A name */
+    public static final PdfName COLORSPACE = new PdfName("ColorSpace");
+    /** A name */
+    public static final PdfName COLUMNS = new PdfName("Columns");
+    /** A name */
+    public static final PdfName CONTACTINFO = new PdfName("ContactInfo");
+    /** A name */
+    public static final PdfName CONTENT = new PdfName("Content");
+    /** A name */
+    public static final PdfName CONTENTS = new PdfName("Contents");
+    /** A name */
+    public static final PdfName COORDS = new PdfName("Coords");
+    /** A name */
+    public static final PdfName COUNT = new PdfName("Count");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName COURIER = new PdfName("Courier");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName COURIER_BOLD = new PdfName("Courier-Bold");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName COURIER_OBLIQUE = new PdfName("Courier-Oblique");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName COURIER_BOLDOBLIQUE = new PdfName("Courier-BoldOblique");
+    /** A name */
+    public static final PdfName CREATIONDATE = new PdfName("CreationDate");
+    /** A name */
+    public static final PdfName CREATOR = new PdfName("Creator");
+    /** A name */
+    public static final PdfName CREATORINFO = new PdfName("CreatorInfo");
+    /** A name */
+    public static final PdfName CROPBOX = new PdfName("CropBox");
+    /** A name */
+    public static final PdfName CS = new PdfName("CS");
+    /** A name */
+    public static final PdfName D = new PdfName("D");
+    /** A name */
+    public static final PdfName DA = new PdfName("DA");
+    /** A name */
+    public static final PdfName DC = new PdfName("DC");
+    /** A name */
+    public static final PdfName DCTDECODE = new PdfName("DCTDecode");
+    /** A name */
+    public static final PdfName DECODE = new PdfName("Decode");
+    /** A name */
+    public static final PdfName DECODEPARMS = new PdfName("DecodeParms");
+    /** A name */
+    public static final PdfName DEFAULTCMYK = new PdfName("DefaultCMYK");
+    /** A name */
+    public static final PdfName DEFAULTGRAY = new PdfName("DefaultGray");
+    /** A name */
+    public static final PdfName DEFAULTRGB = new PdfName("DefaultRGB");
+    /** A name */
+    public static final PdfName DESCENDANTFONTS = new PdfName("DescendantFonts");
+    /** A name */
+    public static final PdfName DESCENT = new PdfName("Descent");
+    /** A name */
+    public static final PdfName DEST = new PdfName("Dest");
+    /** A name */
+    public static final PdfName DESTOUTPUTPROFILE = new PdfName("DestOutputProfile");
+    /** A name */
+    public static final PdfName DESTS = new PdfName("Dests");
+    /** A name */
+    public static final PdfName DEVICEGRAY = new PdfName("DeviceGray");
+    /** A name */
+    public static final PdfName DEVICERGB = new PdfName("DeviceRGB");
+    /** A name */
+    public static final PdfName DEVICECMYK = new PdfName("DeviceCMYK");
+    /** A name */
+    public static final PdfName DI = new PdfName("Di");
+    /** A name */
+    public static final PdfName DIFFERENCES = new PdfName("Differences");
+    /** A name */
+    public static final PdfName DISSOLVE = new PdfName("Dissolve");
+    /** A name */
+    public static final PdfName DIRECTION = new PdfName("Direction");
+    /** A name */
+    public static final PdfName DISPLAYDOCTITLE = new PdfName("DisplayDocTitle");
+    /** A name */
+    public static final PdfName DM = new PdfName("Dm");
+    /** A name */
+    public static final PdfName DOMAIN = new PdfName("Domain");
+    /** A name */
+    public static final PdfName DP = new PdfName("DP");
+    /** A name */
+    public static final PdfName DR = new PdfName("DR");
+    /** A name */
+    public static final PdfName DS = new PdfName("DS");
+    /** A name */
+    public static final PdfName DUR = new PdfName("Dur");
+    /** A name */
+    public static final PdfName DV = new PdfName("DV");
+    /** A name */
+    public static final PdfName DW = new PdfName("DW");
+    /** A name */
+    public static final PdfName E = new PdfName("E");
+    /** A name */
+    public static final PdfName EARLYCHANGE = new PdfName("EarlyChange");
+    /** A name */
+    public static final PdfName EF = new PdfName("EF");
+    /** A name */
+    public static final PdfName EMBEDDEDFILE = new PdfName("EmbeddedFile");
+    /** A name */
+    public static final PdfName ENCODE = new PdfName("Encode");
+    /** A name */
+    public static final PdfName ENCODEDBYTEALIGN = new PdfName("EncodedByteAlign");
+    /** A name */
+    public static final PdfName ENCODING = new PdfName("Encoding");
+    /** A name */
+    public static final PdfName ENCRYPT = new PdfName("Encrypt");
+    /** A name */
+    public static final PdfName ENDOFBLOCK = new PdfName("EndOfBlock");
+    /** A name */
+    public static final PdfName ENDOFLINE = new PdfName("EndOfLine");
+    /** A name */
+    public static final PdfName EXTEND = new PdfName("Extend");
+    /** A name */
+    public static final PdfName EXTGSTATE = new PdfName("ExtGState");
+    /** A name */
+    public static final PdfName EXPORT = new PdfName("Export");
+    /** A name */
+    public static final PdfName EXPORTSTATE = new PdfName("ExportState");
+    /** A name */
+    public static final PdfName EVENT = new PdfName("Event");
+    /** A name */
+    public static final PdfName F = new PdfName("F");
+    /** A name */
+    public static final PdfName FB = new PdfName("FB");
+    /** A name */
+    public static final PdfName FDECODEPARMS = new PdfName("FDecodeParms");
+    /** A name */
+    public static final PdfName FDF = new PdfName("FDF");
+    /** A name */
+    public static final PdfName FF = new PdfName("Ff");
+    /** A name */
+    public static final PdfName FFILTER = new PdfName("FFilter");
+    /** A name */
+    public static final PdfName FIELDS = new PdfName("Fields");
+    /** A name */
+    public static final PdfName FILEATTACHMENT = new PdfName("FileAttachment");
+    /** A name */
+    public static final PdfName FILESPEC = new PdfName("Filespec");
+    /** A name */
+    public static final PdfName FILTER = new PdfName("Filter");
+    /** A name */
+    public static final PdfName FIRST = new PdfName("First");
+    /** A name */
+    public static final PdfName FIRSTCHAR = new PdfName("FirstChar");
+    /** A name */
+    public static final PdfName FIRSTPAGE = new PdfName("FirstPage");
+    /** A name */
+    public static final PdfName FIT = new PdfName("Fit");
+    /** A name */
+    public static final PdfName FITH = new PdfName("FitH");
+    /** A name */
+    public static final PdfName FITV = new PdfName("FitV");
+    /** A name */
+    public static final PdfName FITR = new PdfName("FitR");
+    /** A name */
+    public static final PdfName FITB = new PdfName("FitB");
+    /** A name */
+    public static final PdfName FITBH = new PdfName("FitBH");
+    /** A name */
+    public static final PdfName FITBV = new PdfName("FitBV");
+    /** A name */
+    public static final PdfName FITWINDOW = new PdfName("FitWindow");
+    /** A name */
+    public static final PdfName FLAGS = new PdfName("Flags");
+    /** A name */
+    public static final PdfName FLATEDECODE = new PdfName("FlateDecode");
+    /** A name */
+    public static final PdfName FO = new PdfName("Fo");
+    /** A name */
+    public static final PdfName FONT = new PdfName("Font");
+    /** A name */
+    public static final PdfName FONTBBOX = new PdfName("FontBBox");
+    /** A name */
+    public static final PdfName FONTDESCRIPTOR = new PdfName("FontDescriptor");
+    /** A name */
+    public static final PdfName FONTFILE = new PdfName("FontFile");
+    /** A name */
+    public static final PdfName FONTFILE2 = new PdfName("FontFile2");
+    /** A name */
+    public static final PdfName FONTFILE3 = new PdfName("FontFile3");
+    /** A name */
+    public static final PdfName FONTNAME = new PdfName("FontName");
+    /** A name */
+    public static final PdfName FORM = new PdfName("Form");
+    /** A name */
+    public static final PdfName FORMTYPE = new PdfName("FormType");
+    /** A name */
+    public static final PdfName FREETEXT = new PdfName("FreeText");
+    /** A name */
+    public static final PdfName FRM = new PdfName("FRM");
+    /** A name */
+    public static final PdfName FS = new PdfName("FS");
+    /** A name */
+    public static final PdfName FT = new PdfName("FT");
+    /** A name */
+    public static final PdfName FULLSCREEN = new PdfName("FullScreen");
+    /** A name */
+    public static final PdfName FUNCTION = new PdfName("Function");
+    /** A name */
+    public static final PdfName FUNCTIONS = new PdfName("Functions");
+    /** A name */
+    public static final PdfName FUNCTIONTYPE = new PdfName("FunctionType");
+    /** A name of an attribute. */
+    public static final PdfName GAMMA = new PdfName("Gamma");
+    /** A name of an attribute. */
+    public static final PdfName GBK = new PdfName("GBK");
+    /** A name of an attribute. */
+    public static final PdfName GLITTER = new PdfName("Glitter");
+    /** A name of an attribute. */
+    public static final PdfName GOTO = new PdfName("GoTo");
+    /** A name of an attribute. */
+    public static final PdfName GOTOR = new PdfName("GoToR");
+    /** A name of an attribute. */
+    public static final PdfName GROUP = new PdfName("Group");
+    /** A name of an attribute. */
+    public static final PdfName GTS_PDFX = new PdfName("GTS_PDFX");
+    /** A name of an attribute. */
+    public static final PdfName GTS_PDFXVERSION = new PdfName("GTS_PDFXVersion");
+    /** A name of an attribute. */
+    public static final PdfName H = new PdfName("H");
+    /** A name of an attribute. */
+    public static final PdfName HEIGHT = new PdfName("Height");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName HELVETICA = new PdfName("Helvetica");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName HELVETICA_BOLD = new PdfName("Helvetica-Bold");
+    /** This is a static PdfName PdfName of a base 14 type 1 font */
+    public static final PdfName HELVETICA_OBLIQUE = new PdfName("Helvetica-Oblique");
+    /** This is a static PdfName PdfName of a base 14 type 1 font */
+    public static final PdfName HELVETICA_BOLDOBLIQUE = new PdfName("Helvetica-BoldOblique");
+    /** A name */
+    public static final PdfName HID = new PdfName("Hid");
+    /** A name */
+    public static final PdfName HIDE = new PdfName("Hide");
+    /** A name */
+    public static final PdfName HIDEMENUBAR = new PdfName("HideMenubar");
+    /** A name */
+    public static final PdfName HIDETOOLBAR = new PdfName("HideToolbar");
+    /** A name */
+    public static final PdfName HIDEWINDOWUI = new PdfName("HideWindowUI");
+    /** A name */
+    public static final PdfName HIGHLIGHT = new PdfName("Highlight");
+    /** A name */
+    public static final PdfName I = new PdfName("I");
+    /** A name */
+    public static final PdfName ICCBASED = new PdfName("ICCBased");
+    /** A name */
+    public static final PdfName ID = new PdfName("ID");
+    /** A name */
+    public static final PdfName IDENTITY = new PdfName("Identity");
+    /** A name */
+    public static final PdfName IF = new PdfName("IF");
+    /** A name */
+    public static final PdfName IMAGE = new PdfName("Image");
+    /** A name */
+    public static final PdfName IMAGEB = new PdfName("ImageB");
+    /** A name */
+    public static final PdfName IMAGEC = new PdfName("ImageC");
+    /** A name */
+    public static final PdfName IMAGEI = new PdfName("ImageI");
+    /** A name */
+    public static final PdfName IMAGEMASK = new PdfName("ImageMask");
+    /** A name */
+    public static final PdfName INDEX = new PdfName("Index");
+    /** A name */
+    public static final PdfName INDEXED = new PdfName("Indexed");
+    /** A name */
+    public static final PdfName INFO = new PdfName("Info");
+    /** A name */
+    public static final PdfName INK = new PdfName("Ink");
+    /** A name */
+    public static final PdfName INKLIST = new PdfName("InkList");
+    /** A name */
+    public static final PdfName IMPORTDATA = new PdfName("ImportData");
+    /** A name */
+    public static final PdfName INTENT = new PdfName("Intent");
+    /** A name */
+    public static final PdfName INTERPOLATE = new PdfName("Interpolate");
+    /** A name */
+    public static final PdfName ISMAP = new PdfName("IsMap");
+    /** A name */
+    public static final PdfName IRT = new PdfName("IRT");
+    /** A name */
+    public static final PdfName ITALICANGLE = new PdfName("ItalicAngle");
+    /** A name */
+    public static final PdfName IX = new PdfName("IX");
+    /** A name */
+    public static final PdfName JAVASCRIPT = new PdfName("JavaScript");
+    /** A name */
+    public static final PdfName JS = new PdfName("JS");
+    /** A name */
+    public static final PdfName K = new PdfName("K");
+    /** A name */
+    public static final PdfName KEYWORDS = new PdfName("Keywords");
+    /** A name */
+    public static final PdfName KIDS = new PdfName("Kids");
+    /** A name */
+    public static final PdfName L = new PdfName("L");
+    /** A name */
+    public static final PdfName L2R = new PdfName("L2R");
+    /** A name */
+    public static final PdfName LANG = new PdfName("Lang");
+    /** A name */
+    public static final PdfName LANGUAGE = new PdfName("Language");
+    /** A name */
+    public static final PdfName LAST = new PdfName("Last");
+    /** A name */
+    public static final PdfName LASTCHAR = new PdfName("LastChar");
+    /** A name */
+    public static final PdfName LASTPAGE = new PdfName("LastPage");
+    /** A name */
+    public static final PdfName LAUNCH = new PdfName("Launch");
+    /** A name */
+    public static final PdfName LENGTH = new PdfName("Length");
+    /** A name */
+    public static final PdfName LENGTH1 = new PdfName("Length1");
+    /** A name */
+    public static final PdfName LIMITS = new PdfName("Limits");
+    /** A name */
+    public static final PdfName LINE = new PdfName("Line");
+    /** A name */
+    public static final PdfName LINK = new PdfName("Link");
+    /** A name */
+    public static final PdfName LISTMODE = new PdfName("ListMode");
+    /** A name */
+    public static final PdfName LOCATION = new PdfName("Location");
+    /** A name */
+    public static final PdfName LOCK = new PdfName("Lock");
+    /** A name */
+    public static final PdfName LZWDECODE = new PdfName("LZWDecode");
+    /** A name */
+    public static final PdfName M = new PdfName("M");
+    /** A name */
+    public static final PdfName MATRIX = new PdfName("Matrix");
+    /** A name of an encoding */
+    public static final PdfName MAC_EXPERT_ENCODING = new PdfName("MacExpertEncoding");
+    /** A name of an encoding */
+    public static final PdfName MAC_ROMAN_ENCODING = new PdfName("MacRomanEncoding");
+    /** A name */
+    public static final PdfName MASK = new PdfName("Mask");
+    /** A name */
+    public static final PdfName MAX = new PdfName("max");
+    /** A name */
+    public static final PdfName MAXLEN = new PdfName("MaxLen");
+    /** A name */
+    public static final PdfName MEDIABOX = new PdfName("MediaBox");
+    /** A name */
+    public static final PdfName METADATA = new PdfName("Metadata");
+    /** A name */
+    public static final PdfName MIN = new PdfName("min");
+    /** A name */
+    public static final PdfName MK = new PdfName("MK");
+    /** A name */
+    public static final PdfName MMTYPE1 = new PdfName("MMType1");
+    /** A name */
+    public static final PdfName MODDATE = new PdfName("ModDate");
+    /** A name */
+    public static final PdfName N = new PdfName("N");
+    /** A name */
+    public static final PdfName N0 = new PdfName("n0");
+    /** A name */
+    public static final PdfName N1 = new PdfName("n1");
+    /** A name */
+    public static final PdfName N2 = new PdfName("n2");
+    /** A name */
+    public static final PdfName N3 = new PdfName("n3");
+    /** A name */
+    public static final PdfName N4 = new PdfName("n4");
+    /** A name */
+    public static final PdfName NAME = new PdfName("Name");
+    /** A name */
+    public static final PdfName NAMED = new PdfName("Named");
+    /** A name */
+    public static final PdfName NAMES = new PdfName("Names");
+    /** A name */
+    public static final PdfName NEEDAPPEARANCES = new PdfName("NeedAppearances");
+    /** A name */
+    public static final PdfName NEWWINDOW = new PdfName("NewWindow");
+    /** A name */
+    public static final PdfName NEXT = new PdfName("Next");
+    /** A name */
+    public static final PdfName NEXTPAGE = new PdfName("NextPage");
+    /** A name */
+    public static final PdfName NM = new PdfName("NM");
+    /** A name */
+    public static final PdfName NONE = new PdfName("None");
+    /** A name */
+    public static final PdfName NONFULLSCREENPAGEMODE = new PdfName("NonFullScreenPageMode");
+    /** A name */
+    public static final PdfName NUMS = new PdfName("Nums");
+    /** A name */
+    public static final PdfName O = new PdfName("O");
+    /** A name */
+    public static final PdfName OBJSTM = new PdfName("ObjStm");
+    /** A name */
+    public static final PdfName OC = new PdfName("OC");
+    /** A name */
+    public static final PdfName OCG = new PdfName("OCG");
+    /** A name */
+    public static final PdfName OCGS = new PdfName("OCGs");
+    /** A name */
+    public static final PdfName OCMD = new PdfName("OCMD");
+    /** A name */
+    public static final PdfName OCPROPERTIES = new PdfName("OCProperties");
+    /** A name */
+    public static final PdfName Off = new PdfName("Off");
+    /** A name */
+    public static final PdfName OFF = new PdfName("OFF");
+    /** A name */
+    public static final PdfName ON = new PdfName("ON");
+    /** A name */
+    public static final PdfName ONECOLUMN = new PdfName("OneColumn");
+    /** A name */
+    public static final PdfName OPEN = new PdfName("Open");
+    /** A name */
+    public static final PdfName OPENACTION = new PdfName("OpenAction");
+    /** A name */
+    public static final PdfName OP = new PdfName("OP");
+    /** A name */
+    public static final PdfName op = new PdfName("op");
+    /** A name */
+    public static final PdfName OPM = new PdfName("OPM");
+    /** A name */
+    public static final PdfName OPT = new PdfName("Opt");
+    /** A name */
+    public static final PdfName ORDER = new PdfName("Order");
+    /** A name */
+    public static final PdfName ORDERING = new PdfName("Ordering");
+    /** A name */
+    public static final PdfName OUTLINES = new PdfName("Outlines");
+    /** A name */
+    public static final PdfName OUTPUTCONDITION = new PdfName("OutputCondition");
+    /** A name */
+    public static final PdfName OUTPUTCONDITIONIDENTIFIER = new PdfName("OutputConditionIdentifier");
+    /** A name */
+    public static final PdfName OUTPUTINTENT = new PdfName("OutputIntent");
+    /** A name */
+    public static final PdfName OUTPUTINTENTS = new PdfName("OutputIntents");
+    /** A name */
+    public static final PdfName P = new PdfName("P");
+    /** A name */
+    public static final PdfName PAGE = new PdfName("Page");
+    /** A name */
+    public static final PdfName PAGELABELS = new PdfName("PageLabels");
+    /** A name */
+    public static final PdfName PAGELAYOUT = new PdfName("PageLayout");
+    /** A name */
+    public static final PdfName PAGEMODE = new PdfName("PageMode");
+    /** A name */
+    public static final PdfName PAGES = new PdfName("Pages");
+    /** A name */
+    public static final PdfName PAINTTYPE = new PdfName("PaintType");
+    /** A name */
+    public static final PdfName PANOSE = new PdfName("Panose");
+    /** A name */
+    public static final PdfName PARENT = new PdfName("Parent");
+    /** A name */
+    public static final PdfName PATTERN = new PdfName("Pattern");
+    /** A name */
+    public static final PdfName PATTERNTYPE = new PdfName("PatternType");
+    /** A name */
+    public static final PdfName PDF = new PdfName("PDF");
+    /** A name */
+    public static final PdfName PERCEPTUAL = new PdfName("Perceptual");
+    /** A name */
+    public static final PdfName POPUP = new PdfName("Popup");
+    /** A name */
+    public static final PdfName PREDICTOR = new PdfName("Predictor");
+    /** A name */
+    public static final PdfName PREFERRED = new PdfName("Preferred");
+    /** A name */
+    public static final PdfName PRESERVERB = new PdfName("PreserveRB");
+    /** A name */
+    public static final PdfName PREV = new PdfName("Prev");
+    /** A name */
+    public static final PdfName PREVPAGE = new PdfName("PrevPage");
+    /** A name */
+    public static final PdfName PRINT = new PdfName("Print");
+    /** A name */
+    public static final PdfName PRINTSCALING = new PdfName("PrintScaling");
+    /** A name */
+    public static final PdfName PRINTSTATE = new PdfName("PrintState");
+    /** A name */
+    public static final PdfName PROCSET = new PdfName("ProcSet");
+    /** A name */
+    public static final PdfName PRODUCER = new PdfName("Producer");
+    /** A name */
+    public static final PdfName PROPERTIES = new PdfName("Properties");
+    /** A name */
+    public static final PdfName PS = new PdfName("PS");
+    /** A name */
+    public static final PdfName Q = new PdfName("Q");
+    /** A name */
+    public static final PdfName QUADPOINTS = new PdfName("QuadPoints");
+    /** A name */
+    public static final PdfName R = new PdfName("R");
+    /** A name */
+    public static final PdfName R2L = new PdfName("R2L");
+    /** A name */
+    public static final PdfName RANGE = new PdfName("Range");
+    /** A name */
+    public static final PdfName RC = new PdfName("RC");
+    /** A name */
+    public static final PdfName RBGROUPS = new PdfName("RBGroups");
+    /** A name */
+    public static final PdfName REASON = new PdfName("Reason");
+    /** A name */
+    public static final PdfName RECT = new PdfName("Rect");
+    /** A name */
+    public static final PdfName REGISTRY = new PdfName("Registry");
+    /** A name */
+    public static final PdfName REGISTRYNAME = new PdfName("RegistryName");
+    /** A name */
+    public static final PdfName RELATIVECALORIMETRIC = new PdfName("RelativeColorimetric");
+    /** A name */
+    public static final PdfName RENDITION = new PdfName("Rendition");
+    /** A name */
+    public static final PdfName RESETFORM = new PdfName("ResetForm");
+    /** A name */
+    public static final PdfName RESOURCES = new PdfName("Resources");
+    /** A name */
+    public static final PdfName RI = new PdfName("RI");
+    /** A name */
+    public static final PdfName ROOT = new PdfName("Root");
+    /** A name */
+    public static final PdfName ROTATE = new PdfName("Rotate");
+    /** A name */
+    public static final PdfName ROWS = new PdfName("Rows");
+    /** A name */
+    public static final PdfName RUNLENGTHDECODE = new PdfName("RunLengthDecode");
+    /** A name */
+    public static final PdfName RV = new PdfName("RV");
+    /** A name */
+    public static final PdfName S = new PdfName("S");
+    /** A name */
+    public static final PdfName SATURATION = new PdfName("Saturation");
+    /** A name */
+    public static final PdfName SCREEN = new PdfName("Screen");
+    /** A name */
+    public static final PdfName SEPARATION = new PdfName("Separation");
+    /** A name */
+    public static final PdfName SETOCGSTATE = new PdfName("SetOCGState");
+    /** A name */
+    public static final PdfName SHADING = new PdfName("Shading");
+    /** A name */
+    public static final PdfName SHADINGTYPE = new PdfName("ShadingType");
+    /** A name */
+    public static final PdfName SHIFT_JIS = new PdfName("Shift?JIS");
+    /** A name */
+    public static final PdfName SIG = new PdfName("Sig");
+    /** A name */
+    public static final PdfName SIGFLAGS = new PdfName("SigFlags");
+    /** A name */
+    public static final PdfName SINGLEPAGE = new PdfName("SinglePage");
+    /** A name */
+    public static final PdfName SIZE = new PdfName("Size");
+    /** A name */
+    public static final PdfName SMASK = new PdfName("SMask");
+    /** A name */
+    public static final PdfName SPLIT = new PdfName("Split");
+    /** A name */
+    public static final PdfName SQUARE = new PdfName("Square");
+    /** A name */
+    public static final PdfName ST = new PdfName("St");
+    /** A name */
+    public static final PdfName STAMP = new PdfName("Stamp");
+    /** A name */
+    public static final PdfName STANDARD = new PdfName("Standard");
+    /** A name */
+    public static final PdfName STATE = new PdfName("State");
+    /** A name */
+    public static final PdfName STRIKEOUT = new PdfName("StrikeOut");
+    /** A name */
+    public static final PdfName STRUCTPARENT = new PdfName("StructParent");
+    /** A name */
+    public static final PdfName STYLE = new PdfName("Style");
+    /** A name */
+    public static final PdfName STEMV = new PdfName("StemV");
+    /** A name */
+    public static final PdfName SUBFILTER = new PdfName("SubFilter");
+    /** A name */
+    public static final PdfName SUBJECT = new PdfName("Subject");
+    /** A name */
+    public static final PdfName SUBMITFORM = new PdfName("SubmitForm");
+    /** A name */
+    public static final PdfName SUBTYPE = new PdfName("Subtype");
+    /** A name */
+    public static final PdfName SUPPLEMENT = new PdfName("Supplement");
+    /** A name */
+    public static final PdfName SV = new PdfName("SV");
+    /** A name */
+    public static final PdfName SW = new PdfName("SW");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName SYMBOL = new PdfName("Symbol");
+    /** A name */
+    public static final PdfName T = new PdfName("T");
+    /** A name */
+    public static final PdfName TEXT = new PdfName("Text");
+    /** A name */
+    public static final PdfName THUMB = new PdfName("Thumb");
+    /** A name */
+    public static final PdfName THREADS = new PdfName("Threads");
+    /** A name */
+    public static final PdfName TI = new PdfName("TI");
+    /** A name */
+    public static final PdfName TILINGTYPE = new PdfName("TilingType");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName TIMES_ROMAN = new PdfName("Times-Roman");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName TIMES_BOLD = new PdfName("Times-Bold");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName TIMES_ITALIC = new PdfName("Times-Italic");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName TIMES_BOLDITALIC = new PdfName("Times-BoldItalic");
+    /** A name */
+    public static final PdfName TITLE = new PdfName("Title");
+    /** A name */
+    public static final PdfName TK = new PdfName("TK");
+    /** A name */
+    public static final PdfName TM = new PdfName("TM");
+    /** A name */
+    public static final PdfName TOGGLE = new PdfName("Toggle");
+    /** A name */
+    public static final PdfName TOUNICODE = new PdfName("ToUnicode");
+    /** A name */
+    public static final PdfName TP = new PdfName("TP");
+    /** A name */
+    public static final PdfName TRANS = new PdfName("Trans");
+    /** A name */
+    public static final PdfName TRANSPARENCY = new PdfName("Transparency");
+    /** A name */
+    public static final PdfName TRAPPED = new PdfName("Trapped");
+    /** A name */
+    public static final PdfName TRIMBOX = new PdfName("TrimBox");
+    /** A name */
+    public static final PdfName TRUETYPE = new PdfName("TrueType");
+    /** A name */
+    public static final PdfName TU = new PdfName("TU");
+    /** A name */
+    public static final PdfName TWOCOLUMNLEFT = new PdfName("TwoColumnLeft");
+    /** A name */
+    public static final PdfName TWOCOLUMNRIGHT = new PdfName("TwoColumnRight");
+    /** A name */
+    public static final PdfName TX = new PdfName("Tx");
+    /** A name */
+    public static final PdfName TYPE = new PdfName("Type");
+    /** A name */
+    public static final PdfName TYPE0 = new PdfName("Type0");
+    /** A name */
+    public static final PdfName TYPE1 = new PdfName("Type1");
+    /** A name of an attribute. */
+    public static final PdfName U = new PdfName("U");
+    /** A name of an attribute. */
+    public static final PdfName UHC = new PdfName("UHC");
+    /** A name of an attribute. */
+    public static final PdfName UNDERLINE = new PdfName("Underline");
+    /** A name */
+    public static final PdfName URI = new PdfName("URI");
+    /** A name */
+    public static final PdfName URL = new PdfName("URL");
+    /** A name */
+    public static final PdfName USAGE = new PdfName("Usage");
+    /** A name */
+    public static final PdfName USENONE = new PdfName("UseNone");
+    /** A name */
+    public static final PdfName USEOC = new PdfName("UseOC");
+    /** A name */
+    public static final PdfName USEOUTLINES = new PdfName("UseOutlines");
+    /** A name */
+    public static final PdfName USER = new PdfName("User");
+    /** A name */
+    public static final PdfName USETHUMBS = new PdfName("UseThumbs");
+    /** A name */
+    public static final PdfName V = new PdfName("V");
+    /** A name */
+    public static final PdfName VERISIGN_PPKVS = new PdfName("VeriSign.PPKVS");
+    /** A name */
+    public static final PdfName VIEW = new PdfName("View");
+    /** A name */
+    public static final PdfName VIEWERPREFERENCES = new PdfName("ViewerPreferences");
+    /** A name */
+    public static final PdfName VIEWSTATE = new PdfName("ViewState");
+    /** A name */
+    public static final PdfName VISIBLEPAGES = new PdfName("VisiblePages");
+    /** A name of an attribute. */
+    public static final PdfName W = new PdfName("W");
+    /** A name of an attribute. */
+    public static final PdfName W2 = new PdfName("W2");
+    /** A name of an attribute. */
+    public static final PdfName WC = new PdfName("WC");
+    /** A name of an attribute. */
+    public static final PdfName WIDGET = new PdfName("Widget");
+    /** A name of an attribute. */
+    public static final PdfName WIDTH = new PdfName("Width");
+    /** A name */
+    public static final PdfName WIDTHS = new PdfName("Widths");
+    /** A name of an encoding */
+    public static final PdfName WIN = new PdfName("Win");
+    /** A name of an encoding */
+    public static final PdfName WIN_ANSI_ENCODING = new PdfName("WinAnsiEncoding");
+    /** A name of an encoding */
+    public static final PdfName WIPE = new PdfName("Wipe");
+    /** A name */
+    public static final PdfName WHITEPOINT = new PdfName("WhitePoint");
+    /** A name */
+    public static final PdfName WP = new PdfName("WP");
+    /** A name of an encoding */
+    public static final PdfName WS = new PdfName("WS");
+    /** A name */
+    public static final PdfName X = new PdfName("X");
+    /** A name */
+    public static final PdfName XOBJECT = new PdfName("XObject");
+    /** A name */
+    public static final PdfName XSTEP = new PdfName("XStep");
+    /** A name */
+    public static final PdfName XREF = new PdfName("XRef");
+    /** A name */
+    public static final PdfName XREFSTM = new PdfName("XRefStm");
+    /** A name */
+    public static final PdfName XYZ = new PdfName("XYZ");
+    /** A name */
+    public static final PdfName YSTEP = new PdfName("YStep");
+    /** A name of a base 14 type 1 font */
+    public static final PdfName ZAPFDINGBATS = new PdfName("ZapfDingbats");
+    /** A name */
+    public static final PdfName ZOOM = new PdfName("Zoom");
+    
+    private int hash = 0;
+    
+    // constructors
+    
+    /**
+     * Constructs a <CODE>PdfName</CODE>-object.
+     *
+     * @param		name		the new Name.
+     */
+    
+    public PdfName(String name) {
+        super(PdfObject.NAME);
+        // The minimum number of characters in a name is 0, the maximum is 127 (the '/' not included)
+        int length = name.length();
+        if (length > 127) {
+            throw new IllegalArgumentException("The name '" + name + "' is too long (" + length + " characters).");
+        }
+        // The name has to be checked for illegal characters
+        // every special character has to be substituted
+        ByteBuffer pdfName = new ByteBuffer(length + 20);
+        pdfName.append('/');
+        char character;
+        char chars[] = name.toCharArray();
+        // loop over all the characters
+        for (int index = 0; index < length; index++) {
+            character = (char)(chars[index] & 0xff);
+            // special characters are escaped (reference manual p.39)
+            switch (character) {
+                case ' ':
+                case '%':
+                case '(':
+                case ')':
+                case '<':
+                case '>':
+                case '[':
+                case ']':
+                case '{':
+                case '}':
+                case '/':
+                case '#':
+                    pdfName.append('#');
+                    pdfName.append(Integer.toString((int) character, 16));
+                    break;
+                default:
+                    if (character > 126 || character < 32) {
+                        pdfName.append('#');
+                        if (character < 16)
+                            pdfName.append('0');
+                        pdfName.append(Integer.toString((int) character, 16));
+                    }
+                    else
+                        pdfName.append(character);
+                    break;
+            }
+        }
+        bytes = pdfName.toByteArray();
+    }
+    
+    /**
+     * Constructs a PdfName.
+     * @param bytes
+     */
+    public PdfName(byte bytes[]) {
+        super(PdfObject.NAME, bytes);
+    }
+    // methods
+    
+    /**
+     * Compares this object with the specified object for order.  Returns a
+     * negative integer, zero, or a positive integer as this object is less
+     * than, equal to, or greater than the specified object.<p>
+     *
+     *
+     * @param   object the Object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+     *
+     * @throws ClassCastException if the specified object's type prevents it
+     *         from being compared to this Object.
+     */
+    public int compareTo(Object object) {
+        PdfName name = (PdfName) object;
+        
+        byte myBytes[] = bytes;
+        byte objBytes[] = name.bytes;
+        int len = Math.min(myBytes.length, objBytes.length);
+        for(int i=0; i<len; i++) {
+            if(myBytes[i] > objBytes[i])
+                return 1;
+            
+            if(myBytes[i] < objBytes[i])
+                return -1;
+        }
+        if (myBytes.length < objBytes.length)
+            return -1;
+        if (myBytes.length > objBytes.length)
+            return 1;
+        return 0;
+    }
+    
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     *
+     * @param   obj   the reference object with which to compare.
+     * @return  <code>true</code> if this object is the same as the obj
+     *          argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj instanceof PdfName)
+            return compareTo(obj) == 0;
+        return false;
+    }
+    
+    /**
+     * Returns a hash code value for the object. This method is
+     * supported for the benefit of hashtables such as those provided by
+     * <code>java.util.Hashtable</code>.
+     *
+     * @return  a hash code value for this object.
+     */
+    public int hashCode() {
+        int h = hash;
+        if (h == 0) {
+            int ptr = 0;
+            int len = bytes.length;
+            
+            for (int i = 0; i < len; i++)
+                h = 31*h + (bytes[ptr++] & 0xff);
+            hash = h;
+        }
+        return h;
+    }
+    
+    /** Decodes an escaped name in the form "/AB#20CD" into "AB CD".
+     * @param name the name to decode
+     * @return the decoded name
+     */
+    public static String decodeName(String name) {
+        StringBuffer buf = new StringBuffer();
+        try {
+            int len = name.length();
+            for (int k = 1; k < len; ++k) {
+                char c = name.charAt(k);
+                if (c == '#') {
+                    c = (char)((PRTokeniser.getHex(name.charAt(k + 1)) << 4) + PRTokeniser.getHex(name.charAt(k + 2)));
+                    k += 2;
+                }
+                buf.append(c);
+            }
+        }
+        catch (IndexOutOfBoundsException e) {
+            // empty on purpose
+        }
+        return buf.toString();
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfNameTree.java b/LibrarySource/com/lowagie/text/pdf/PdfNameTree.java
new file mode 100644
index 0000000..9227c57
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfNameTree.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.io.IOException;
+import com.lowagie.text.StringCompare;
+
+/**
+ * Creates a name tree.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfNameTree {
+    
+    private static final int leafSize = 64;
+    private static final StringCompare stringCompare = new StringCompare();
+    
+    /**
+     * Creates a name tree.
+     * @param items the item of the name tree. The key is a <CODE>String</CODE>
+     * and the value is a <CODE>PdfIndirectReference</CODE>. Note that although the
+     * keys are strings only the lower byte is used and no check is made for chars
+     * with the same lower byte and different upper byte. This will generate a wrong
+     * tree name.
+     * @param writer the writer
+     * @throws IOException on error
+     * @return the dictionary with the name tree. This dictionary is the one
+     * generally pointed to by the key /Dests
+     */    
+    public static PdfDictionary writeTree(HashMap items, PdfWriter writer) throws IOException {
+        if (items.size() == 0)
+            return null;
+        String names[] = new String[items.size()];
+        names = (String[])items.keySet().toArray(names);
+        Arrays.sort(names, stringCompare);
+        if (names.length <= leafSize) {
+            PdfDictionary dic = new PdfDictionary();
+            PdfArray ar = new PdfArray();
+            for (int k = 0; k < names.length; ++k) {
+                ar.add(new PdfString(names[k], null));
+                ar.add((PdfIndirectReference)items.get(names[k]));
+            }
+            dic.put(PdfName.NAMES, ar);
+            return dic;
+        }
+        int skip = leafSize;
+        PdfIndirectReference kids[] = new PdfIndirectReference[(names.length + leafSize - 1) / leafSize];
+        for (int k = 0; k < kids.length; ++k) {
+            int offset = k * leafSize;
+            int end = Math.min(offset + leafSize, names.length);
+            PdfDictionary dic = new PdfDictionary();
+            PdfArray arr = new PdfArray();
+            arr.add(new PdfString(names[offset], null));
+            arr.add(new PdfString(names[end - 1], null));
+            dic.put(PdfName.LIMITS, arr);
+            arr = new PdfArray();
+            for (; offset < end; ++offset) {
+                arr.add(new PdfString(names[offset], null));
+                arr.add((PdfIndirectReference)items.get(names[offset]));
+            }
+            dic.put(PdfName.NAMES, arr);
+            kids[k] = writer.addToBody(dic).getIndirectReference();
+        }
+        int top = kids.length;
+        while (true) {
+            if (top <= leafSize) {
+                PdfArray arr = new PdfArray();
+                for (int k = 0; k < top; ++k)
+                    arr.add(kids[k]);
+                PdfDictionary dic = new PdfDictionary();
+                dic.put(PdfName.KIDS, arr);
+                return dic;
+            }
+            skip *= leafSize;
+            int tt = (names.length + skip - 1 )/ skip;
+            for (int k = 0; k < tt; ++k) {
+                int offset = k * leafSize;
+                int end = Math.min(offset + leafSize, top);
+                PdfDictionary dic = new PdfDictionary();
+                PdfArray arr = new PdfArray();
+                arr.add(new PdfString(names[k * skip], null));
+                arr.add(new PdfString(names[Math.min((k + 1) * skip, names.length) - 1], null));
+                dic.put(PdfName.LIMITS, arr);
+                arr = new PdfArray();
+                for (; offset < end; ++offset) {
+                    arr.add(kids[offset]);
+                }
+                dic.put(PdfName.KIDS, arr);
+                kids[k] = writer.addToBody(dic).getIndirectReference();
+            }
+            top = tt;
+        }
+    }
+    
+    private static void iterateItems(PdfDictionary dic, HashMap items) {
+        PdfArray nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.NAMES));
+        if (nn != null) {
+            ArrayList arr = nn.getArrayList();
+            for (int k = 0; k < arr.size(); ++k) {
+                PdfString s = (PdfString)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k++));
+                items.put(s.toString(), arr.get(k));
+            }
+        }
+        else if ((nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.KIDS))) != null) {
+            ArrayList arr = nn.getArrayList();
+            for (int k = 0; k < arr.size(); ++k) {
+                PdfDictionary kid = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k));
+                iterateItems(kid, items);
+            }
+        }
+    }
+    
+    public static HashMap readTree(PdfDictionary dic) {
+        HashMap items = new HashMap();
+        if (dic != null)
+            iterateItems(dic, items);
+        return items;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfNull.java b/LibrarySource/com/lowagie/text/pdf/PdfNull.java
new file mode 100644
index 0000000..24a536d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfNull.java
@@ -0,0 +1,83 @@
+/*
+ * $Id: PdfNull.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfNull</CODE> is the Null object represented by the keyword <VAR>null</VAR>.
+ * <P>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.9 (page 53).
+ *
+ * @see		PdfObject
+ */
+
+public class PdfNull extends PdfObject {
+    
+    // static membervariables
+    
+/** This is an instance of the <CODE>PdfNull</CODE>-object. */
+    public static final PdfNull	PDFNULL = new PdfNull();
+    
+/** This is the content of a <CODE>PdfNull</CODE>-object. */
+    private static final String CONTENT = "null";
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfNull</CODE>-object.
+ * <P>
+ * You never need to do this yourself, you can always use the static final object <VAR>PDFNULL</VAR>.
+ */
+    
+    public PdfNull() {
+        super(NULL, CONTENT);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfNumber.java b/LibrarySource/com/lowagie/text/pdf/PdfNumber.java
new file mode 100644
index 0000000..5276f9d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfNumber.java
@@ -0,0 +1,159 @@
+/*
+ * $Id: PdfNumber.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfNumber</CODE> provides two types of numbers, integer and real.
+ * <P>
+ * Integers may be specified by signed or unsigned constants. Reals may only be
+ * in decimal format.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.3 (page 37).
+ *
+ * @see		PdfObject
+ * @see		BadPdfFormatException
+ */
+
+public class PdfNumber extends PdfObject {
+    
+/** actual value of this <CODE>PdfNumber</CODE>, represented as a <CODE>double</CODE> */
+    private double value;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfNumber</CODE>-object.
+ *
+ * @param		content			value of the new <CODE>PdfNumber</CODE>-object
+ */
+    
+    public PdfNumber(String content) {
+        super(NUMBER);
+        try {
+            value = Double.valueOf(content.trim()).doubleValue();
+            setContent(content);
+        }
+        catch (NumberFormatException nfe){
+            throw new RuntimeException(content + " is not a valid number - " + nfe.toString());
+        }
+    }
+    
+/**
+ * Constructs a new INTEGER <CODE>PdfNumber</CODE>-object.
+ *
+ * @param		value				value of the new <CODE>PdfNumber</CODE>-object
+ */
+    
+    public PdfNumber(int value) {
+        super(NUMBER);
+        this.value = value;
+        setContent(String.valueOf(value));
+    }
+    
+/**
+ * Constructs a new REAL <CODE>PdfNumber</CODE>-object.
+ *
+ * @param		value				value of the new <CODE>PdfNumber</CODE>-object
+ */
+    
+    public PdfNumber(double value) {
+        super(NUMBER);
+        this.value = value;
+        setContent(ByteBuffer.formatDouble(value));
+    }
+    
+/**
+ * Constructs a new REAL <CODE>PdfNumber</CODE>-object.
+ *
+ * @param		value				value of the new <CODE>PdfNumber</CODE>-object
+ */
+    
+    public PdfNumber(float value) {
+        this((double)value);
+    }
+    
+    // methods returning the value of this object
+    
+/**
+ * Returns the primitive <CODE>int</CODE> value of this object.
+ *
+ * @return		a value
+ */
+    
+    public int intValue() {
+        return (int) value;
+    }
+    
+/**
+ * Returns the primitive <CODE>double</CODE> value of this object.
+ *
+ * @return		a value
+ */
+    
+    public double doubleValue() {
+        return value;
+    }
+    
+    public float floatValue() {
+        return (float)value;
+    }
+    
+    // other methods
+    
+/**
+ * Increments the value of the <CODE>PdfNumber</CODE>-object with 1.
+ */
+    
+    public void increment() {
+        value += 1.0;
+        setContent(ByteBuffer.formatDouble(value));
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfOCG.java b/LibrarySource/com/lowagie/text/pdf/PdfOCG.java
new file mode 100644
index 0000000..bf0b078
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfOCG.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/**
+ * The interface common to all layer types.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface PdfOCG {
+
+    /**
+     * Gets the <CODE>PdfIndirectReference</CODE> that represents this layer.
+     * @return the <CODE>PdfIndirectReference</CODE> that represents this layer
+     */    
+    public PdfIndirectReference getRef();
+    
+    /**
+     * Gets the object representing the layer.
+     * @return the object representing the layer
+     */    
+    public PdfObject getPdfObject();
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfOCProperties.java b/LibrarySource/com/lowagie/text/pdf/PdfOCProperties.java
new file mode 100644
index 0000000..41bbd36
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfOCProperties.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/**
+ * This class represents the /OCProperties entry in the document catalog
+ * and holds the optional content properties dictionary, which contains
+ * a list of all the optional content groups in the document, as well as information
+ * about the default and alternate configurations for optional content.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfOCProperties extends PdfDictionary {
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfObject.java b/LibrarySource/com/lowagie/text/pdf/PdfObject.java
new file mode 100644
index 0000000..d55894c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfObject.java
@@ -0,0 +1,371 @@
+/*
+ * $Id: PdfObject.java,v 1.26 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * <CODE>PdfObject</CODE> is the abstract superclass of all PDF objects.
+ * <P>
+ * PDF supports seven basic types of objects: Booleans, numbers, strings, names,
+ * arrays, dictionaries and streams. In addition, PDF provides a null object.
+ * Objects may be labeled so that they can be referred to by other objects.<BR>
+ * All these basic PDF objects are described in the 'Portable Document Format
+ * Reference Manual version 1.3' Chapter 4 (pages 37-54).
+ *
+ * @see		PdfNull
+ * @see		PdfBoolean
+ * @see		PdfNumber
+ * @see		PdfString
+ * @see		PdfName
+ * @see		PdfArray
+ * @see		PdfDictionary
+ * @see		PdfStream
+ * @see		PdfIndirectReference
+ */
+
+public abstract class PdfObject {
+    
+    // static membervariables (all the possible types of a PdfObject)
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int BOOLEAN = 1;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int NUMBER = 2;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int STRING = 3;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int NAME = 4;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int ARRAY = 5;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int DICTIONARY = 6;
+    
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int STREAM = 7;
+
+/** a possible type of <CODE>PdfObject</CODE> */
+    public static final int NULL = 8;
+    
+    /** a possible type of <CODE>PdfObject</CODE> */
+    public static final int INDIRECT = 10;    
+
+/** This is an empty string used for the <CODE>PdfNull</CODE>-object and for an empty <CODE>PdfString</CODE>-object. */
+    public static final String NOTHING = "";
+    
+/** This is the default encoding to be used for converting Strings into bytes and vice versa.
+ * The default encoding is PdfDocEncoding.
+ */
+    public static final String TEXT_PDFDOCENCODING = "PDF";
+    
+/** This is the encoding to be used to output text in Unicode. */
+    public static final String TEXT_UNICODE = "UnicodeBig";
+    
+    // membervariables
+    
+/** the content of this <CODE>PdfObject</CODE> */
+    protected byte[] bytes;
+    
+/** the type of this <CODE>PdfObject</CODE> */
+    protected int type;
+    
+    /**
+     * Holds value of property indRef.
+     */
+    protected PRIndirectReference indRef;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR> without any <VAR>content</VAR>.
+ *
+ * @param		type			type of the new <CODE>PdfObject</CODE>
+ */
+    
+    protected PdfObject(int type) {
+        this.type = type;
+    }
+    
+/**
+ * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR> with a certain <VAR>content</VAR>.
+ *
+ * @param		type			type of the new <CODE>PdfObject</CODE>
+ * @param		content			content of the new <CODE>PdfObject</CODE> as a <CODE>String</CODE>.
+ */
+    
+    protected PdfObject(int type, String content) {
+        this.type = type;
+        bytes = PdfEncodings.convertToBytes(content, null);
+    }
+    
+/**
+ * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR> with a certain <VAR>content</VAR>.
+ *
+ * @param		type			type of the new <CODE>PdfObject</CODE>
+ * @param		bytes			content of the new <CODE>PdfObject</CODE> as an array of <CODE>byte</CODE>.
+ */
+    
+    protected PdfObject(int type, byte[] bytes) {
+        this.bytes = bytes;
+        this.type = type;
+    }
+    
+    // methods dealing with the content of this object
+    
+/**
+ * Writes the PDF representation of this <CODE>PdfObject</CODE> as an array of <CODE>byte</CODE>s to the writer.
+ * @param writer for backwards compatibility
+ * @param os the outputstream to write the bytes to.
+ * @throws IOException
+ */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        if (bytes != null)
+            os.write(bytes);
+    }
+    
+    /**
+     * Gets the presentation of this object in a byte array
+     * @return a byte array
+     */
+    public byte[] getBytes() {
+        return bytes;
+    }
+
+    /**
+     * Can this object be in an object stream?
+     * @return true if this object can be in an object stream.
+     */
+    public boolean canBeInObjStm() {
+        return (type >= 1 && type <= 6) || type == 8;
+    }
+    
+/**
+ * Returns the length of the PDF representation of the <CODE>PdfObject</CODE>.
+ * <P>
+ * In some cases, namely for <CODE>PdfString</CODE> and <CODE>PdfStream</CODE>,
+ * this method differs from the method <CODE>length</CODE> because <CODE>length</CODE>
+ * returns the length of the actual content of the <CODE>PdfObject</CODE>.</P>
+ * <P>
+ * Remark: the actual content of an object is in most cases identical to its representation.
+ * The following statement is always true: length() >= pdfLength().</P>
+ *
+ * @return		a length
+ */
+    
+//    public int pdfLength() {
+//        return toPdf(null).length;
+//    }
+    
+/**
+ * Returns the <CODE>String</CODE>-representation of this <CODE>PdfObject</CODE>.
+ *
+ * @return		a <CODE>String</CODE>
+ */
+    
+    public String toString() {
+        if (bytes == null)
+            return super.toString();
+        else
+            return PdfEncodings.convertToString(bytes, null);
+    }
+    
+/**
+ * Returns the length of the actual content of the <CODE>PdfObject</CODE>.
+ * <P>
+ * In some cases, namely for <CODE>PdfString</CODE> and <CODE>PdfStream</CODE>,
+ * this method differs from the method <CODE>pdfLength</CODE> because <CODE>pdfLength</CODE>
+ * returns the length of the PDF representation of the object, not of the actual content
+ * as does the method <CODE>length</CODE>.</P>
+ * <P>
+ * Remark: the actual content of an object is in some cases identical to its representation.
+ * The following statement is always true: length() >= pdfLength().</P>
+ *
+ * @return		a length
+ */
+    
+    public int length() {
+        return toString().length();
+    }
+    
+/**
+ * Changes the content of this <CODE>PdfObject</CODE>.
+ *
+ * @param		content			the new content of this <CODE>PdfObject</CODE>
+ */
+    
+    protected void setContent(String content) {
+        bytes = PdfEncodings.convertToBytes(content, null);
+    }
+    
+    // methods dealing with the type of this object
+    
+/**
+ * Returns the type of this <CODE>PdfObject</CODE>.
+ *
+ * @return		a type
+ */
+    
+    public int type() {
+        return type;
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfNull</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isNull() {
+        return (this.type == NULL);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfBoolean</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isBoolean() {
+        return (this.type == BOOLEAN);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfNumber</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isNumber() {
+        return (this.type == NUMBER);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfString</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isString() {
+        return (this.type == STRING);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfName</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isName() {
+        return (this.type == NAME);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfArray</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isArray() {
+        return (this.type == ARRAY);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfDictionary</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isDictionary() {
+        return (this.type == DICTIONARY);
+    }
+    
+/**
+ * Checks if this <CODE>PdfObject</CODE> is of the type <CODE>PdfStream</CODE>.
+ *
+ * @return		<CODE>true</CODE> or <CODE>false</CODE>
+ */
+    
+    public boolean isStream() {
+        return (this.type == STREAM);
+    }
+
+    /**
+     * Checks if this is an indirect object.
+     * @return true if this is an indirect object
+     */
+    public boolean isIndirect() {
+        return (this.type == INDIRECT);
+    }
+    
+    /**
+     * Getter for property indRef.
+     * @return Value of property indRef.
+     */
+    public PRIndirectReference getIndRef() {
+        return this.indRef;
+    }
+    
+    /**
+     * Setter for property indRef.
+     * @param indRef New value of property indRef.
+     */
+    public void setIndRef(PRIndirectReference indRef) {
+        this.indRef = indRef;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfOutline.java b/LibrarySource/com/lowagie/text/pdf/PdfOutline.java
new file mode 100644
index 0000000..18f76b3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfOutline.java
@@ -0,0 +1,542 @@
+/*
+ * $Id: PdfOutline.java,v 1.51 2005/01/05 10:05:20 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.Iterator;
+
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Paragraph;
+import java.util.ArrayList;
+import headless.awt.Color;
+import com.lowagie.text.Font;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * <CODE>PdfOutline</CODE> is an object that represents a PDF outline entry.
+ * <P>
+ * An outline allows a user to access views of a document by name.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.7 (page 104-106)
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfOutline extends PdfDictionary {
+    
+    // membervariables
+    
+    /** the <CODE>PdfIndirectReference</CODE> of this object */
+    private PdfIndirectReference reference;
+    
+    /** value of the <B>Count</B>-key */
+    private int count = 0;
+    
+    /** value of the <B>Parent</B>-key */
+    private PdfOutline parent;
+    
+    /** value of the <B>Destination</B>-key */
+    private PdfDestination destination;
+    
+    /** The <CODE>PdfAction</CODE> for this outline.
+     */
+    private PdfAction action;
+       
+    protected ArrayList kids = new ArrayList();
+    
+    protected PdfWriter writer;
+    
+    /** Holds value of property tag. */
+    private String tag;
+    
+    /** Holds value of property open. */
+    private boolean open;
+    
+    /** Holds value of property color. */
+    private Color color;
+    
+    /** Holds value of property style. */
+    private int style = 0;
+    
+    // constructors
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for the <CODE>outlines object</CODE>.
+     * 
+     * @param writer The PdfWriter you are adding the outline to
+     */
+    
+    PdfOutline(PdfWriter writer) {
+        super(OUTLINES);
+        open = true;
+        parent = null;
+        this.writer = writer;
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     */
+    
+    public PdfOutline(PdfOutline parent, PdfAction action, String title) {
+        this(parent, action, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfAction action, String title, boolean open) {
+        super();
+        this.action = action;
+        initOutline(parent, title, open);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     */
+    
+    public PdfOutline(PdfOutline parent, PdfDestination destination, String title) {
+        this(parent, destination, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfDestination destination, String title, boolean open) {
+        super();
+        this.destination = destination;
+        initOutline(parent, title, open);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     */
+    public PdfOutline(PdfOutline parent, PdfAction action, PdfString title) {
+        this(parent, action, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfAction action, PdfString title, boolean open) {
+        this(parent, action, title.toString(), true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     */
+    
+    public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title) {
+        this(parent, destination, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title, boolean open) {
+        this(parent, destination, title.toString(), true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     */
+    
+    public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title) {
+        this(parent, action, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param action the <CODE>PdfAction</CODE> for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title, boolean open) {
+        super();
+        StringBuffer buf = new StringBuffer();
+        for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
+            Chunk chunk = (Chunk) i.next();
+            buf.append(chunk.content());
+        }
+        this.action = action;
+        initOutline(parent, buf.toString(), open);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
+     * <CODE>true</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     */
+    
+    public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title) {
+        this(parent, destination, title, true);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfOutline</CODE>.
+     * <P>
+     * This is the constructor for an <CODE>outline entry</CODE>.
+     *
+     * @param parent the parent of this outline item
+     * @param destination the destination for this outline item
+     * @param title the title of this outline item
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title, boolean open) {
+        super();
+        StringBuffer buf = new StringBuffer();
+        for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
+            Chunk chunk = (Chunk) i.next();
+            buf.append(chunk.content());
+        }
+        this.destination = destination;
+        initOutline(parent, buf.toString(), open);
+    }
+    
+    
+    // methods
+    
+    /** Helper for the constructors.
+     * @param parent the parent outline
+     * @param title the title for this outline
+     * @param open <CODE>true</CODE> if the children are visible
+     */
+    void initOutline(PdfOutline parent, String title, boolean open) {
+        this.open = open;
+        this.parent = parent;
+        writer = parent.writer;
+        put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
+        parent.addKid(this);
+        if (destination != null && !destination.hasPage()) // bugfix Finn Bock
+            setDestinationPage(writer.getCurrentPage());
+    }
+    
+    /**
+     * Sets the indirect reference of this <CODE>PdfOutline</CODE>.
+     *
+     * @param reference the <CODE>PdfIndirectReference</CODE> to this outline.
+     */
+    
+    public void setIndirectReference(PdfIndirectReference reference) {
+        this.reference = reference;
+    }
+    
+    /**
+     * Gets the indirect reference of this <CODE>PdfOutline</CODE>.
+     *
+     * @return		the <CODE>PdfIndirectReference</CODE> to this outline.
+     */
+    
+    public PdfIndirectReference indirectReference() {
+        return reference;
+    }
+    
+    /**
+     * Gets the parent of this <CODE>PdfOutline</CODE>.
+     *
+     * @return		the <CODE>PdfOutline</CODE> that is the parent of this outline.
+     */
+    
+    public PdfOutline parent() {
+        return parent;
+    }
+    
+    /**
+     * Set the page of the <CODE>PdfDestination</CODE>-object.
+     *
+     * @param pageReference indirect reference to the page
+     * @return <CODE>true</CODE> if this page was set as the <CODE>PdfDestination</CODE>-page.
+     */
+    
+    public boolean setDestinationPage(PdfIndirectReference pageReference) {
+        if (destination == null) {
+            return false;
+        }
+        return destination.addPage(pageReference);
+    }
+    
+    /**
+     * Gets the destination for this outline.
+     * @return the destination
+     */
+    public PdfDestination getPdfDestination() {
+        return destination;
+    }
+    
+    int getCount() {
+        return count;
+    }
+
+    void setCount(int count) {
+        this.count = count;
+    }
+    
+    /**
+     * returns the level of this outline.
+     *
+     * @return		a level
+     */
+    
+    public int level() {
+        if (parent == null) {
+            return 0;
+        }
+        return (parent.level() + 1);
+    }
+    
+    /**
+     * Returns the PDF representation of this <CODE>PdfOutline</CODE>.
+     *
+     * @param writer the encryption information
+     * @param os
+     * @throws IOException
+     */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        if (color != null && !color.equals(Color.black)) {
+            put(PdfName.C, new PdfArray(new float[]{color.getRed()/255f,color.getGreen()/255f,color.getBlue()/255f}));
+        }
+        int flag = 0;
+        if ((style & Font.BOLD) != 0)
+            flag |= 2;
+        if ((style & Font.ITALIC) != 0)
+            flag |= 1;
+        if (flag != 0)
+            put(PdfName.F, new PdfNumber(flag));
+        if (parent != null) {
+            put(PdfName.PARENT, parent.indirectReference());
+        }
+        if (destination != null && destination.hasPage()) {
+            put(PdfName.DEST, destination);
+        }
+        if (action != null)
+            put(PdfName.A, action);
+        if (count != 0) {
+            put(PdfName.COUNT, new PdfNumber(count));
+        }
+        super.toPdf(writer, os);
+    }
+    
+    /**
+     * Adds a kid to the outline
+     * @param outline
+     */
+    public void addKid(PdfOutline outline) {
+        kids.add(outline);
+    }
+    
+    /**
+     * Returns the kids of this outline
+     * @return an ArrayList with PdfOutlines
+     */
+    public ArrayList getKids() {
+        return kids;
+    }
+    
+    /**
+     * Sets the kids of this outline
+     * @param kids
+     */
+    public void setKids(ArrayList kids) {
+        this.kids = kids;
+    }
+    
+    /** Getter for property tag.
+     * @return Value of property tag.
+     */
+    public String getTag() {
+        return tag;
+    }
+    
+    /** Setter for property tag.
+     * @param tag New value of property tag.
+     */
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+    
+    /**
+     * Gets the title of this outline
+     * @return the title as a String
+     */
+    public String getTitle() {
+        PdfString title = (PdfString)get(PdfName.TITLE);
+        return title.toString();
+    }
+    
+    /**
+     * Sets the title of this outline
+     * @param title
+     */
+    public void setTitle(String title) {
+        put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
+    }
+    
+    /** Getter for property open.
+     * @return Value of property open.
+     */
+    public boolean isOpen() {
+        return open;
+    }
+    
+    /** Setter for property open.
+     * @param open New value of property open.
+     */
+    public void setOpen(boolean open) {
+        this.open = open;
+    }
+    
+    /** Getter for property color.
+     * @return Value of property color.
+     *
+     */
+    public Color getColor() {
+        return this.color;
+    }
+    
+    /** Setter for property color.
+     * @param color New value of property color.
+     *
+     */
+    public void setColor(Color color) {
+        this.color = color;
+    }
+    
+    /** Getter for property style.
+     * @return Value of property style.
+     *
+     */
+    public int getStyle() {
+        return this.style;
+    }
+    
+    /** Setter for property style.
+     * @param style New value of property style.
+     *
+     */
+    public void setStyle(int style) {
+        this.style = style;
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPCell.java b/LibrarySource/com/lowagie/text/pdf/PdfPCell.java
new file mode 100644
index 0000000..05811be
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPCell.java
@@ -0,0 +1,697 @@
+/*
+ * $Id: PdfPCell.java,v 1.56 2005/01/12 13:59:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Element;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Image;
+import com.lowagie.text.Chunk;
+
+/** A cell in a PdfPTable.
+ */
+
+public class PdfPCell extends Rectangle{
+    
+    private ColumnText column = new ColumnText(null);
+    
+    /** Holds value of property verticalAlignment. */
+    private int verticalAlignment = Element.ALIGN_TOP;
+    
+    /** Holds value of property paddingLeft. */
+    private float paddingLeft = 2;
+    
+    /** Holds value of property paddingLeft. */
+    private float paddingRight = 2;
+    
+    /** Holds value of property paddingTop. */
+    private float paddingTop = 2;
+    
+    /** Holds value of property paddingBottom. */
+    private float paddingBottom = 2;
+    
+    /** Holds value of property fixedHeight. */
+    private float fixedHeight = 0;
+    
+    /** Holds value of property noWrap. */
+    private boolean noWrap = false;
+    
+    /** Holds value of property table. */
+    private PdfPTable table;
+    
+    /** Holds value of property minimumHeight. */
+    private float minimumHeight;
+    
+    /** Holds value of property colspan. */
+    private int colspan = 1;
+    
+    /** Holds value of property image. */
+    private Image image;
+    
+    /** Holds value of property cellEvent. */
+    private PdfPCellEvent cellEvent;
+
+    /** Holds value of property useDescender. */
+    private boolean useDescender;
+
+    /** Increases padding to include border if true */
+    private boolean useBorderPadding = false;
+
+
+    /** The text in the cell. */
+    protected Phrase phrase;
+
+    /** Constructs an empty <CODE>PdfPCell</CODE>.
+     * The default padding is 2.
+     */
+    public PdfPCell() {
+        super(0, 0, 0, 0);
+        borderWidth = 0.5f;
+        border = BOX;
+        column.setLeading(0, 1);
+    }
+
+    /** Constructs a <CODE>PdfPCell</CODE> with a <CODE>Phrase</CODE>.
+     * The default padding is 2.
+     * @param phrase the text
+     */
+    public PdfPCell(Phrase phrase) {
+        super(0, 0, 0, 0);
+        borderWidth = 0.5f;
+        border = BOX;
+        column.addText(this.phrase = phrase);
+        column.setLeading(0, 1);
+    }
+    
+    /** Constructs a <CODE>PdfPCell</CODE> with an <CODE>Image</CODE>.
+     * The default padding is 0.
+     * @param image the <CODE>Image</CODE>
+     */
+    public PdfPCell(Image image) {
+        super(0, 0, 0, 0);
+        borderWidth = 0.5f;
+        border = BOX;
+        column.addText(this.phrase = new Phrase(new Chunk(image, 0, 0)));
+        column.setLeading(0, 1);
+        setPadding(0);
+    }
+    
+    /** Constructs a <CODE>PdfPCell</CODE> with an <CODE>Image</CODE>.
+     * The default padding is 0.25 for a border width of 0.5.
+     * @param image the <CODE>Image</CODE>
+     * @param fit <CODE>true</CODE> to fit the image to the cell
+     */
+    public PdfPCell(Image image, boolean fit) {
+        super(0, 0, 0, 0);
+        if (fit) {
+            borderWidth = 0.5f;
+            border = BOX;
+            this.image = image;
+            column.setLeading(0, 1);
+            setPadding(borderWidth / 2);
+        }
+        else {
+            borderWidth = 0.5f;
+            border = BOX;
+            column.addText(this.phrase = new Phrase(new Chunk(image, 0, 0)));
+            column.setLeading(0, 1);
+            setPadding(0);
+        }
+    }
+    
+    /** Constructs a <CODE>PdfPCell</CODE> with a <CODE>PdfPtable</CODE>.
+     * This constructor allows nested tables.
+     * The default padding is 0.
+     * @param table The <CODE>PdfPTable</CODE>
+     */
+    public PdfPCell(PdfPTable table) {
+        super(0, 0, 0, 0);
+        borderWidth = 0.5f;
+        border = BOX;
+        column.setLeading(0, 1);
+        setPadding(0);
+        this.table = table;
+        table.setWidthPercentage(100);
+        table.setExtendLastRow(true);
+        column.addElement(table);
+    }
+    
+    /** Constructs a deep copy of a <CODE>PdfPCell</CODE>.
+     * @param cell the <CODE>PdfPCell</CODE> to duplicate
+     */
+    public PdfPCell(PdfPCell cell) {
+        super(cell.llx, cell.lly, cell.urx, cell.ury);
+        cloneNonPositionParameters(cell);
+        verticalAlignment = cell.verticalAlignment;
+        paddingLeft = cell.paddingLeft;
+        paddingRight = cell.paddingRight;
+        paddingTop = cell.paddingTop;
+        paddingBottom = cell.paddingBottom;
+        phrase = cell.phrase;
+        fixedHeight = cell.fixedHeight;
+        minimumHeight = cell.minimumHeight;
+        noWrap = cell.noWrap;
+        colspan = cell.colspan;
+        if (cell.table != null)
+            table = new PdfPTable(cell.table);
+        image = Image.getInstance(cell.image);
+        cellEvent = cell.cellEvent;
+        useDescender = cell.useDescender;
+        column = ColumnText.duplicate(cell.column);
+        useBorderPadding = cell.useBorderPadding;
+    }
+    
+    /**
+     * Adds an iText element to the cell.
+     * @param element
+     */
+    public void addElement(Element element) {
+        if (table != null) {
+            table = null;
+            column.setText(null);
+        }
+        column.addElement(element);
+    }
+    
+    /** Gets the <CODE>Phrase</CODE> from this cell.
+     * @return the <CODE>Phrase</CODE>
+     */
+    public Phrase getPhrase() {
+        return phrase;
+    }
+    
+    /** Sets the <CODE>Phrase</CODE> for this cell.
+     * @param phrase the <CODE>Phrase</CODE>
+     */
+    public void setPhrase(Phrase phrase) {
+        table = null;
+        image = null;
+        column.setText(this.phrase = phrase);
+    }
+    
+    /** Gets the horizontal alignment for the cell.
+     * @return the horizontal alignment for the cell
+     */
+    public int getHorizontalAlignment() {
+        return column.getAlignment();
+    }
+    
+    /** Sets the horizontal alignment for the cell. It could be
+     * <CODE>Element.ALIGN_CENTER</CODE> for example.
+     * @param horizontalAlignment The horizontal alignment
+     */
+    public void setHorizontalAlignment(int horizontalAlignment) {
+        column.setAlignment(horizontalAlignment);
+    }
+    
+    /** Gets the vertical alignment for the cell.
+     * @return the vertical alignment for the cell
+     */
+    public int getVerticalAlignment() {
+        return verticalAlignment;
+    }
+    
+    /** Sets the vertical alignment for the cell. It could be
+     * <CODE>Element.ALIGN_MIDDLE</CODE> for example.
+     * @param verticalAlignment The vertical alignment
+     */
+    public void setVerticalAlignment(int verticalAlignment) {
+        if (table != null)
+            table.setExtendLastRow(verticalAlignment == Element.ALIGN_TOP);
+        this.verticalAlignment = verticalAlignment;
+    }
+    
+    /** Gets the effective left padding.  This will include
+     *  the left border width if {@link #isUseBorderPadding()} is true.
+     * @return effective value of property paddingLeft.
+     */
+    public float getEffectivePaddingLeft() {
+        return paddingLeft + (isUseBorderPadding() ? (getBorderWidthLeft()/(isUseVariableBorders()?1f:2f)) : 0);
+    }
+    
+    /**
+     * @return Value of property paddingLeft.
+     */
+    public float getPaddingLeft() {
+        return paddingLeft;
+    }
+
+    /**
+     * Setter for property paddingLeft.
+     * @param paddingLeft New value of property paddingLeft.
+     */
+    public void setPaddingLeft(float paddingLeft) {
+        this.paddingLeft = paddingLeft;
+    }
+    
+    /** Gets the effective right padding.  This will include
+     *  the right border width if {@link #isUseBorderPadding()} is true.
+     * @return effective value of property paddingRight.
+     */
+    public float getEffectivePaddingRight() {
+        return paddingRight + (isUseBorderPadding() ? (getBorderWidthRight()/(isUseVariableBorders()?1f:2f)) : 0);
+    }
+    
+    /**
+     * Getter for property paddingRight.
+     * @return Value of property paddingRight.
+     */
+    public float getPaddingRight() {
+        return paddingRight;
+    }
+
+    /**
+     * Setter for property paddingRight.
+     * @param paddingRight New value of property paddingRight.
+     */
+    public void setPaddingRight(float paddingRight) {
+        this.paddingRight = paddingRight;
+    }
+    
+    /** Gets the effective top padding.  This will include
+     *  the top border width if {@link #isUseBorderPadding()} is true.
+     * @return effective value of property paddingTop.
+     */
+    public float getEffectivePaddingTop() {
+        return paddingTop + (isUseBorderPadding() ? (getBorderWidthTop()/(isUseVariableBorders()?1f:2f)) : 0);
+    }
+    
+    /**
+     * Getter for property paddingTop.
+     * @return Value of property paddingTop.
+     */
+    public float getPaddingTop() {
+        return paddingTop;
+    }
+
+    /**
+     * Setter for property paddingTop.
+     * @param paddingTop New value of property paddingTop.
+     */
+    public void setPaddingTop(float paddingTop) {
+        this.paddingTop = paddingTop;
+    }
+    
+    /** Gets the effective bottom padding.  This will include
+     *  the bottom border width if {@link #isUseBorderPadding()} is true.
+     * @return effective value of property paddingBottom.
+     */
+    public float getEffectivePaddingBottom() {
+        return paddingBottom + (isUseBorderPadding() ? (getBorderWidthBottom()/(isUseVariableBorders()?1f:2f)) : 0);
+    }
+    
+    /**
+     * Getter for property paddingBottom.
+     * @return Value of property paddingBottom.
+     */
+    public float getPaddingBottom() {
+        return paddingBottom;
+    }
+
+    /**
+     * Setter for property paddingBottom.
+     * @param paddingBottom New value of property paddingBottom.
+     */
+    public void setPaddingBottom(float paddingBottom) {
+        this.paddingBottom = paddingBottom;
+    }
+    
+    /**
+     * Sets the padding of the contents in the cell (space between content and border).
+     * @param padding
+     */
+    public void setPadding(float padding) {
+        paddingBottom = padding;
+        paddingTop = padding;
+        paddingLeft = padding;
+        paddingRight = padding;
+    }
+
+    /**
+     * If true, then effective padding will include border widths
+     * @return true if effective padding includes border widths
+     */
+    public boolean isUseBorderPadding() {
+        return useBorderPadding;
+    }
+
+    /**
+     * Adjusts effective padding to include border widths.
+     * @param use adjust effective padding if true
+     */
+    public void setUseBorderPadding(boolean use) {
+        useBorderPadding = use;
+    }
+
+    /**
+     * Sets the leading fixed and variable. The resultant leading will be
+     * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
+     * size of the bigest font in the line.
+     * @param fixedLeading the fixed leading
+     * @param multipliedLeading the variable leading
+     */
+    public void setLeading(float fixedLeading, float multipliedLeading) {
+        column.setLeading(fixedLeading, multipliedLeading);
+    }
+    
+    /**
+     * Gets the fixed leading
+     * @return the leading
+     */
+    public float getLeading() {
+        return column.getLeading();
+    }
+    
+    /**
+     * Gets the variable leading
+     * @return the leading
+     */
+    public float getMultipliedLeading() {
+        return column.getMultipliedLeading();
+    }
+    
+    /**
+     * Sets the first paragraph line indent.
+     * @param indent the indent
+     */
+    public void setIndent(float indent) {
+        column.setIndent(indent);
+    }
+    
+    /**
+     * Gets the first paragraph line indent.
+     * @return the indent
+     */
+    public float getIndent() {
+        return column.getIndent();
+    }
+    
+    /**
+     * Gets the extra space between paragraphs.
+     * @return the extra space between paragraphs
+     */
+    public float getExtraParagraphSpace() {
+        return column.getExtraParagraphSpace();
+    }
+    
+    /**
+     * Sets the extra space between paragraphs.
+     * @param extraParagraphSpace the extra space between paragraphs
+     */
+    public void setExtraParagraphSpace(float extraParagraphSpace) {
+        column.setExtraParagraphSpace(extraParagraphSpace);
+    }
+    
+    /**
+     * Getter for property fixedHeight.
+     * @return Value of property fixedHeight.
+     */
+    public float getFixedHeight() {
+        return fixedHeight;
+    }
+    
+    /**
+     * Setter for property fixedHeight.
+     * @param fixedHeight New value of property fixedHeight.
+     */
+    public void setFixedHeight(float fixedHeight) {
+        this.fixedHeight = fixedHeight;
+        minimumHeight = 0;
+    }
+    
+    /**
+     * Getter for property noWrap.
+     * @return Value of property noWrap.
+     */
+    public boolean isNoWrap() {
+        return noWrap;
+    }
+    
+    /**
+     * Setter for property noWrap.
+     * @param noWrap New value of property noWrap.
+     */
+    public void setNoWrap(boolean noWrap) {
+        this.noWrap = noWrap;
+    }
+    
+    /**
+     * Getter for property table.
+     * @return Value of property table.
+     */
+    PdfPTable getTable() {
+        return table;
+    }
+    
+    void setTable(PdfPTable table) {
+        this.table = table;
+        column.setText(null);
+        image = null;
+        if (table != null) {
+            table.setExtendLastRow(verticalAlignment == Element.ALIGN_TOP);
+            column.addElement(table);
+            table.setWidthPercentage(100);
+        }
+    }
+    
+    /** Getter for property minimumHeight.
+     * @return Value of property minimumHeight.
+     */
+    public float getMinimumHeight() {
+        return minimumHeight;
+    }
+    
+    /** Setter for property minimumHeight.
+     * @param minimumHeight New value of property minimumHeight.
+     */
+    public void setMinimumHeight(float minimumHeight) {
+        this.minimumHeight = minimumHeight;
+        fixedHeight = 0;
+    }
+    
+    /** Getter for property colspan.
+     * @return Value of property colspan.
+     */
+    public int getColspan() {
+        return colspan;
+    }
+    
+    /** Setter for property colspan.
+     * @param colspan New value of property colspan.
+     */
+    public void setColspan(int colspan) {
+        this.colspan = colspan;
+    }
+    
+    /**
+     * Sets the following paragraph lines indent.
+     * @param indent the indent
+     */
+    public void setFollowingIndent(float indent) {
+        column.setFollowingIndent(indent);
+    }
+    
+    /**
+     * Gets the following paragraph lines indent.
+     * @return the indent
+     */
+    public float getFollowingIndent() {
+        return column.getFollowingIndent();
+    }
+    
+    /**
+     * Sets the right paragraph lines indent.
+     * @param indent the indent
+     */
+    public void setRightIndent(float indent) {
+        column.setRightIndent(indent);
+    }
+    
+    /**
+     * Gets the right paragraph lines indent.
+     * @return the indent
+     */
+    public float getRightIndent() {
+        return column.getRightIndent();
+    }
+    
+    /** Gets the space/character extra spacing ratio for
+     * fully justified text.
+     * @return the space/character extra spacing ratio
+     */
+    public float getSpaceCharRatio() {
+        return column.getSpaceCharRatio();
+    }
+    
+    /** Sets the ratio between the extra word spacing and the extra character spacing
+     * when the text is fully justified.
+     * Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing.
+     * If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing
+     * will be zero.
+     * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
+     */
+    public void setSpaceCharRatio(float spaceCharRatio) {
+        column.setSpaceCharRatio(spaceCharRatio);
+    }
+    
+    /**
+     * Sets the run direction of the text content in the cell (PdfWriter.RUN_DIRECTION_DEFAULT, PdfWriter.RUN_DIRECTION_NO_BIDI, PdfWriter.RUN_DIRECTION_LTR or PdfWriter.RUN_DIRECTION_RTL).
+     * @param runDirection
+     */
+    public void setRunDirection(int runDirection) {
+        column.setRunDirection(runDirection);
+    }
+    
+    /**
+     * Gets the run direction of the text content in the cell
+     * @return One of the following values: PdfWriter.RUN_DIRECTION_DEFAULT, PdfWriter.RUN_DIRECTION_NO_BIDI, PdfWriter.RUN_DIRECTION_LTR or PdfWriter.RUN_DIRECTION_RTL.
+     */
+    public int getRunDirection() {
+        return column.getRunDirection();
+    }
+    
+    /** Getter for property image.
+     * @return Value of property image.
+     *
+     */
+    public Image getImage() {
+        return this.image;
+    }
+    
+    /** Setter for property image.
+     * @param image New value of property image.
+     *
+     */
+    public void setImage(Image image) {
+        column.setText(null);
+        table = null;
+        this.image = image;
+    }
+    
+    /** Gets the cell event for this cell.
+     * @return the cell event
+     *
+     */
+    public PdfPCellEvent getCellEvent() {
+        return this.cellEvent;
+    }
+    
+    /** Sets the cell event for this cell.
+     * @param cellEvent the cell event
+     *
+     */
+    public void setCellEvent(PdfPCellEvent cellEvent) {
+        this.cellEvent = cellEvent;
+    }
+    
+    /** Gets the arabic shaping options.
+     * @return the arabic shaping options
+     */
+    public int getArabicOptions() {
+        return column.getArabicOptions();
+    }
+    
+    /** Sets the arabic shaping options. The option can be AR_NOVOWEL,
+     * AR_COMPOSEDTASHKEEL and AR_LIG.
+     * @param arabicOptions the arabic shaping options
+     */
+    public void setArabicOptions(int arabicOptions) {
+        column.setArabicOptions(arabicOptions);
+    }
+
+    /** Gets state of first line height based on max ascender
+     * @return true if an ascender is to be used.
+     */
+    public boolean isUseAscender() {
+        return column.isUseAscender();
+    }
+
+    /** Enables/ Disables adjustment of first line height based on max ascender.
+     *
+     * @param use adjust height if true
+     */
+    public void setUseAscender(boolean use) {
+        column.setUseAscender(use);
+    }
+
+
+    /** Getter for property useDescender.
+     * @return Value of property useDescender.
+     *
+     */
+    public boolean isUseDescender() {
+        return this.useDescender;
+    }
+
+    /** Setter for property useDescender.
+     * @param useDescender New value of property useDescender.
+     *
+     */
+    public void setUseDescender(boolean useDescender) {
+        this.useDescender = useDescender;
+    }
+
+    /**
+     * Gets the ColumnText with the content of the cell.
+     * @return a columntext object
+     */
+    public ColumnText getColumn() {
+        return column;
+    }
+    
+    /**
+     * Sets the columntext in the cell.
+     * @param column
+     */
+    public void setColumn(ColumnText column) {
+        this.column = column;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPCellEvent.java b/LibrarySource/com/lowagie/text/pdf/PdfPCellEvent.java
new file mode 100644
index 0000000..f1d2f8c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPCellEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Rectangle;
+
+/** An event called for a single cell.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface PdfPCellEvent {
+    /** This method is called at the end of the cell rendering. The text or graphics are added to
+     * one of the 4 <CODE>PdfContentByte</CODE> contained in
+     * <CODE>canvases</CODE>.<br>
+     * The indexes to <CODE>canvases</CODE> are:<p>
+     * <ul>
+     * <li><CODE>PdfPTable.BASECANVAS</CODE> - the original <CODE>PdfContentByte</CODE>. Anything placed here
+     * will be under the cell.
+     * <li><CODE>PdfPTable.BACKGROUNDCANVAS</CODE> - the layer where the background goes to.
+     * <li><CODE>PdfPTable.LINECANVAS</CODE> - the layer where the lines go to.
+     * <li><CODE>PdfPTable.TEXTCANVAS</CODE> - the layer where the text go to. Anything placed here
+     * will be over the cell.
+     * </ul>
+     * The layers are placed in sequence on top of each other.
+     * <p>
+     * @param cell the cell
+     * @param position the coordinates of the cell
+     * @param canvases an array of <CODE>PdfContentByte</CODE>
+     */    
+    public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases);
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPRow.java b/LibrarySource/com/lowagie/text/pdf/PdfPRow.java
new file mode 100644
index 0000000..e1f9bc6
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPRow.java
@@ -0,0 +1,530 @@
+/*
+ * $Id: PdfPRow.java,v 1.63 2005/01/11 13:59:21 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Image;
+import com.lowagie.text.Rectangle;
+import headless.awt.Color;
+
+/**
+ * A row in a PdfPTable.
+ * 
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class PdfPRow {
+
+	/** the bottom limit (bottom right y) */
+	public static final float BOTTOM_LIMIT = -(1 << 30);
+
+	protected PdfPCell cells[];
+
+	protected float widths[];
+
+	protected float maxHeight = 0;
+
+	protected boolean calculated = false;
+
+	/**
+	 * Constructs a new PdfPRow with the cells in the array that was passed as a parameter.
+	 * @param cells
+	 */
+	public PdfPRow(PdfPCell cells[]) {
+		this.cells = cells;
+		widths = new float[cells.length];
+	}
+
+	/**
+	 * Makes a copy of an existing row.
+	 * @param row
+	 */
+	public PdfPRow(PdfPRow row) {
+		maxHeight = row.maxHeight;
+		calculated = row.calculated;
+		cells = new PdfPCell[row.cells.length];
+		for (int k = 0; k < cells.length; ++k) {
+			if (row.cells[k] != null)
+				cells[k] = new PdfPCell(row.cells[k]);
+		}
+		widths = new float[cells.length];
+		System.arraycopy(row.widths, 0, widths, 0, cells.length);
+	}
+
+	/**
+	 * Sets the widths of the columns in the row.
+	 * @param widths
+	 * @return true if everything went right
+	 */
+	public boolean setWidths(float widths[]) {
+		if (widths.length != cells.length)
+			return false;
+		System.arraycopy(widths, 0, this.widths, 0, cells.length);
+		float total = 0;
+		calculated = false;
+		for (int k = 0; k < widths.length; ++k) {
+			PdfPCell cell = cells[k];
+			cell.setLeft(total);
+			int last = k + cell.getColspan();
+			for (; k < last; ++k)
+				total += widths[k];
+			--k;
+			cell.setRight(total);
+			cell.setTop(0);
+		}
+		return true;
+	}
+
+	/**
+	 * Calculates the heights of each cell in the row.
+	 * @return the maximum height of the row.
+	 */
+	public float calculateHeights() {
+		maxHeight = 0;
+		for (int k = 0; k < cells.length; ++k) {
+			PdfPCell cell = cells[k];
+			if (cell == null)
+				continue;
+			Image img = cell.getImage();
+			if (img != null) {
+				img.scalePercent(100);
+				float scale = (cell.right() - cell.getEffectivePaddingRight()
+						- cell.getEffectivePaddingLeft() - cell.left())
+						/ img.scaledWidth();
+				img.scalePercent(scale * 100);
+				cell
+						.setBottom(cell.top() - cell.getEffectivePaddingTop()
+								- cell.getEffectivePaddingBottom()
+								- img.scaledHeight());
+			} else {
+				float rightLimit = cell.isNoWrap() ? 20000 : cell.right()
+						- cell.getEffectivePaddingRight();
+				float bry = (cell.getFixedHeight() > 0) ? cell.top()
+						- cell.getEffectivePaddingTop()
+						+ cell.getEffectivePaddingBottom()
+						- cell.getFixedHeight() : BOTTOM_LIMIT;
+				ColumnText ct = ColumnText.duplicate(cell.getColumn());
+				ct.setSimpleColumn(
+						cell.left() + cell.getEffectivePaddingLeft(), bry,
+						rightLimit, cell.top() - cell.getEffectivePaddingTop());
+				try {
+					ct.go(true);
+				} catch (DocumentException e) {
+					throw new ExceptionConverter(e);
+				}
+				float yLine = ct.getYLine();
+				if (cell.isUseDescender())
+					yLine += ct.getDescender();
+				cell.setBottom(yLine - cell.getEffectivePaddingBottom());
+			}
+			float height = cell.getFixedHeight();
+			if (height <= 0)
+				height = cell.height();
+			if (height < cell.getFixedHeight())
+				height = cell.getFixedHeight();
+			else if (height < cell.getMinimumHeight())
+				height = cell.getMinimumHeight();
+			if (height > maxHeight)
+				maxHeight = height;
+		}
+		calculated = true;
+		return maxHeight;
+	}
+
+	/**
+	 * Writes the border and background of one cell in the row.
+	 * @param xPos
+	 * @param yPos
+	 * @param cell
+	 * @param canvases
+	 */
+	public void writeBorderAndBackground(float xPos, float yPos, PdfPCell cell,
+			PdfContentByte[] canvases) {
+		PdfContentByte lines = canvases[PdfPTable.LINECANVAS];
+		PdfContentByte backgr = canvases[PdfPTable.BACKGROUNDCANVAS];
+		// the coordinates of the border are retrieved
+		float x1 = cell.left() + xPos;
+		float y2 = cell.top() + yPos;
+		float x2 = cell.right() + xPos;
+		float y1 = y2 - maxHeight;
+
+		// the backgroundcolor is set
+		Color background = cell.backgroundColor();
+		if (background != null) {
+			backgr.setColorFill(background);
+			backgr.rectangle(x1, y1, x2 - x1, y2 - y1);
+			backgr.fill();
+		} else if (cell.grayFill() > 0) {
+			backgr.setGrayFill(cell.grayFill());
+			backgr.rectangle(x1, y1, x2 - x1, y2 - y1);
+			backgr.fill();
+		}
+		// if the element hasn't got any borders, nothing is added
+		if (cell.hasBorders()) {
+			if (cell.isUseVariableBorders()) {
+				Rectangle borderRect = new Rectangle(cell.left() + xPos, cell
+						.top()
+						- maxHeight + yPos, cell.right() + xPos, cell.top()
+						+ yPos);
+				borderRect.cloneNonPositionParameters(cell);
+				lines.rectangle(borderRect);
+			} else {
+				// the width is set to the width of the element
+				if (cell.borderWidth() != Rectangle.UNDEFINED) {
+					lines.setLineWidth(cell.borderWidth());
+				}
+				// the color is set to the color of the element
+				Color color = cell.borderColor();
+				if (color != null) {
+					lines.setColorStroke(color);
+				}
+
+				// if the box is a rectangle, it is added as a rectangle
+				if (cell.hasBorder(Rectangle.BOX)) {
+					lines.rectangle(x1, y1, x2 - x1, y2 - y1);
+				}
+				// if the border isn't a rectangle, the different sides are
+				// added apart
+				else {
+					if (cell.hasBorder(Rectangle.RIGHT)) {
+						lines.moveTo(x2, y1);
+						lines.lineTo(x2, y2);
+					}
+					if (cell.hasBorder(Rectangle.LEFT)) {
+						lines.moveTo(x1, y1);
+						lines.lineTo(x1, y2);
+					}
+					if (cell.hasBorder(Rectangle.BOTTOM)) {
+						lines.moveTo(x1, y1);
+						lines.lineTo(x2, y1);
+					}
+					if (cell.hasBorder(Rectangle.TOP)) {
+						lines.moveTo(x1, y2);
+						lines.lineTo(x2, y2);
+					}
+				}
+				lines.stroke();
+				if (color != null) {
+					lines.resetRGBColorStroke();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Writes a number of cells (not necessarily all cells).
+	 * @param colStart
+	 * @param colEnd
+	 * @param xPos
+	 * @param yPos
+	 * @param canvases
+	 */
+	public void writeCells(int colStart, int colEnd, float xPos, float yPos,
+			PdfContentByte[] canvases) {
+		if (!calculated)
+			calculateHeights();
+		if (colEnd < 0)
+			colEnd = cells.length;
+		colEnd = Math.min(colEnd, cells.length);
+		if (colStart < 0)
+			colStart = 0;
+		if (colStart >= colEnd)
+			return;
+		int newStart;
+		for (newStart = colStart; newStart >= 0; --newStart) {
+			if (cells[newStart] != null)
+				break;
+			xPos -= widths[newStart - 1];
+		}
+		xPos -= cells[newStart].left();
+		for (int k = newStart; k < colEnd; ++k) {
+			PdfPCell cell = cells[k];
+			if (cell == null)
+				continue;
+			writeBorderAndBackground(xPos, yPos, cell, canvases);
+			PdfPTable table = cell.getTable();
+			Image img = cell.getImage();
+			float tly = 0;
+			boolean alignTop = false;
+			switch (cell.getVerticalAlignment()) {
+			case Element.ALIGN_BOTTOM:
+				tly = cell.top() + yPos - maxHeight + cell.height()
+						- cell.getEffectivePaddingTop();
+				break;
+			case Element.ALIGN_MIDDLE:
+				tly = cell.top() + yPos + (cell.height() - maxHeight) / 2
+						- cell.getEffectivePaddingTop();
+				break;
+			default:
+				alignTop = true;
+				tly = cell.top() + yPos - cell.getEffectivePaddingTop();
+				break;
+			}
+			if (img != null) {
+				boolean vf = false;
+				if (cell.height() > maxHeight) {
+					img.scalePercent(100);
+					float scale = (maxHeight - cell.getEffectivePaddingTop() - cell
+							.getEffectivePaddingBottom())
+							/ img.scaledHeight();
+					img.scalePercent(scale * 100);
+					vf = true;
+				}
+				float left = cell.left() + xPos
+						+ cell.getEffectivePaddingLeft();
+				if (vf) {
+					switch (cell.getHorizontalAlignment()) {
+					case Element.ALIGN_CENTER:
+						left = xPos
+								+ (cell.left() + cell.getEffectivePaddingLeft()
+										+ cell.right()
+										- cell.getEffectivePaddingRight() - img
+										.scaledWidth()) / 2;
+						break;
+					case Element.ALIGN_RIGHT:
+						left = xPos + cell.right()
+								- cell.getEffectivePaddingRight()
+								- img.scaledWidth();
+						break;
+					default:
+						break;
+					}
+					tly = cell.top() + yPos - cell.getEffectivePaddingTop();
+				}
+				img.setAbsolutePosition(left, tly - img.scaledHeight());
+				try {
+					canvases[PdfPTable.TEXTCANVAS].addImage(img);
+				} catch (DocumentException e) {
+					throw new ExceptionConverter(e);
+				}
+			} else {
+				float fixedHeight = cell.getFixedHeight();
+				float rightLimit = cell.right() + xPos
+						- cell.getEffectivePaddingRight();
+				float leftLimit = cell.left() + xPos
+						+ cell.getEffectivePaddingLeft();
+				if (cell.isNoWrap()) {
+					switch (cell.getHorizontalAlignment()) {
+					case Element.ALIGN_CENTER:
+						rightLimit += 10000;
+						leftLimit -= 10000;
+						break;
+					case Element.ALIGN_RIGHT:
+						leftLimit -= 20000;
+						break;
+					default:
+						rightLimit += 20000;
+						break;
+					}
+				}
+				ColumnText ct = ColumnText.duplicate(cell.getColumn());
+				ct.setCanvas(canvases[PdfPTable.TEXTCANVAS]);
+				float bry = tly
+						- (maxHeight /* cell.height() */
+								- cell.getEffectivePaddingTop() - cell
+								.getEffectivePaddingBottom());
+				if (fixedHeight > 0) {
+					if (cell.height() > maxHeight) {
+						tly = cell.top() + yPos - cell.getEffectivePaddingTop();
+						bry = cell.top() + yPos - maxHeight
+								+ cell.getEffectivePaddingBottom();
+					}
+				}
+				if (tly > bry || ct.zeroHeightElement()) {
+					ct
+							.setSimpleColumn(leftLimit, bry - 0.001f,
+									rightLimit, tly);
+					try {
+						ct.go();
+					} catch (DocumentException e) {
+						throw new ExceptionConverter(e);
+					}
+				}
+			}
+			PdfPCellEvent evt = cell.getCellEvent();
+			if (evt != null) {
+				Rectangle rect = new Rectangle(cell.left() + xPos, cell.top()
+						+ yPos - maxHeight, cell.right() + xPos, cell.top()
+						+ yPos);
+				evt.cellLayout(cell, rect, canvases);
+			}
+		}
+	}
+
+	/**
+	 * Checks if the dimensions of the columns were calculated.
+	 * @return true if the dimensions of the columns were calculated
+	 */
+	public boolean isCalculated() {
+		return calculated;
+	}
+
+	/**
+	 * Gets the maximum height of the row (i.e. of the 'highest' cell).
+	 * @return the maximum height of the row
+	 */
+	public float getMaxHeights() {
+		if (calculated)
+			return maxHeight;
+		else
+			return calculateHeights();
+	}
+
+	/**
+	 * Changes the maximum height of the row (to make it higher).
+	 * (added by Jin-Hsia Yang)
+	 * @param maxHeight the new maximum height
+	 */
+	public void setMaxHeights(float maxHeight) {
+		this.maxHeight = maxHeight;
+	}
+
+	//end add
+
+	float[] getEventWidth(float xPos) {
+		int n = 0;
+		for (int k = 0; k < cells.length; ++k) {
+			if (cells[k] != null)
+				++n;
+		}
+		float width[] = new float[n + 1];
+		n = 0;
+		width[n++] = xPos;
+		for (int k = 0; k < cells.length; ++k) {
+			if (cells[k] != null) {
+				width[n] = width[n - 1] + cells[k].width();
+				++n;
+			}
+		}
+		return width;
+	}
+
+	/**
+	 * Splits a row to newHeight. The returned row is the remainder. It will
+	 * return null if the newHeight was so small that only an empty row would
+	 * result.
+	 * 
+	 * @param newHeight
+	 *            the new height
+	 * @return the remainder row or null if the newHeight was so small that only
+	 *         an empty row would result
+	 */
+	public PdfPRow splitRow(float newHeight) {
+		PdfPCell newCells[] = new PdfPCell[cells.length];
+		float fh[] = new float[cells.length * 2];
+		boolean allEmpty = true;
+		for (int k = 0; k < cells.length; ++k) {
+			PdfPCell cell = cells[k];
+			if (cell == null)
+				continue;
+			fh[k * 2] = cell.getFixedHeight();
+			fh[k * 2 + 1] = cell.getMinimumHeight();
+			Image img = cell.getImage();
+			PdfPCell c2 = new PdfPCell(cell);
+			if (img != null) {
+				if (newHeight > cell.getEffectivePaddingBottom()
+						+ cell.getEffectivePaddingTop() + 2) {
+					c2.setPhrase(null);
+					allEmpty = false;
+				}
+			} else {
+				float rightLimit = cell.isNoWrap() ? 20000 : cell.right()
+						- cell.getEffectivePaddingRight();
+				ColumnText ct = ColumnText.duplicate(cell.getColumn());
+				float y1 = cell.top() - newHeight
+						+ cell.getEffectivePaddingBottom();
+				float y2 = cell.top() - cell.getEffectivePaddingTop();
+				float y = Math.max(y1, y2);
+				int status;
+				ct.setSimpleColumn(
+						cell.left() + cell.getEffectivePaddingLeft(), y1,
+						rightLimit, y2);
+				try {
+					status = ct.go(true);
+				} catch (DocumentException e) {
+					throw new ExceptionConverter(e);
+				}
+				boolean thisEmpty = (ct.getYLine() == y);
+				if (thisEmpty)
+					ct = ColumnText.duplicate(cell.getColumn());
+				allEmpty = (allEmpty && thisEmpty);
+				if ((status & ColumnText.NO_MORE_TEXT) == 0 || thisEmpty) {
+					c2.setColumn(ct);
+				} else {
+					c2.setPhrase(null);
+				}
+			}
+			newCells[k] = c2;
+			cell.setFixedHeight(newHeight);
+		}
+		if (allEmpty) {
+			for (int k = 0; k < cells.length; ++k) {
+				PdfPCell cell = cells[k];
+				if (cell == null)
+					continue;
+				float f = fh[k * 2];
+				float m = fh[k * 2 + 1];
+				if (f <= 0)
+					cell.setMinimumHeight(m);
+				else
+					cell.setFixedHeight(f);
+			}
+			return null;
+		}
+		calculateHeights();
+		PdfPRow split = new PdfPRow(newCells);
+		split.widths = (float[]) widths.clone();
+		split.calculateHeights();
+		return split;
+	}
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPSXObject.java b/LibrarySource/com/lowagie/text/pdf/PdfPSXObject.java
new file mode 100644
index 0000000..42f1ee9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPSXObject.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2005 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+/**
+ * Implements the PostScript XObject.
+ */
+public class PdfPSXObject extends PdfTemplate {
+    
+    /** Creates a new instance of PdfPSXObject */
+    protected PdfPSXObject() {
+        super();
+    }
+    
+    /**
+     * Constructs a PSXObject
+     * @param wr
+     */
+    public PdfPSXObject(PdfWriter wr) {
+        super(wr);
+    }
+
+    /**
+     * Gets the stream representing this object.
+     *
+     * @return the stream representing this object
+     * @throws IOException
+     */
+    
+    PdfStream getFormXObject() throws IOException {
+        PdfStream s = new PdfStream(content.toByteArray());
+        s.put(PdfName.TYPE, PdfName.XOBJECT);
+        s.put(PdfName.SUBTYPE, PdfName.PS);
+        s.flateCompress();
+        return s;
+    }
+        
+    /**
+     * Gets a duplicate of this <CODE>PdfPSXObject</CODE>. All
+     * the members are copied by reference but the buffer stays different.
+     * @return a copy of this <CODE>PdfPSXObject</CODE>
+     */
+    
+    public PdfContentByte getDuplicate() {
+        PdfPSXObject tpl = new PdfPSXObject();
+        tpl.writer = writer;
+        tpl.pdf = pdf;
+        tpl.thisReference = thisReference;
+        tpl.pageResources = pageResources;
+        tpl.separator = separator;
+        return tpl;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPTable.java b/LibrarySource/com/lowagie/text/pdf/PdfPTable.java
new file mode 100644
index 0000000..3d4cd28
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPTable.java
@@ -0,0 +1,1014 @@
+/*
+ * $Id: PdfPTable.java,v 1.58 2005/01/10 15:35:57 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Element;
+import com.lowagie.text.Image;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.ElementListener;
+import com.lowagie.text.DocumentException;
+
+/** This is a table that can be put at an absolute position but can also
+ * be added to the document as the class <CODE>Table</CODE>.
+ * In the last case when crossing pages the table always break at full rows; if a
+ * row is bigger than the page it is dropped silently to avoid infinite loops.
+ * <P>
+ * A PdfPTableEvent can be associated to the table to do custom drawing
+ * when the table is rendered.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class PdfPTable implements Element{
+    
+    /** The index of the original <CODE>PdfcontentByte</CODE>.
+     */    
+    public static final int BASECANVAS = 0;
+    /** The index of the duplicate <CODE>PdfContentByte</CODE> where the background will be drawn.
+     */    
+    public static final int BACKGROUNDCANVAS = 1;
+    /** The index of the duplicate <CODE>PdfContentByte</CODE> where the border lines will be drawn.
+     */    
+    public static final int LINECANVAS = 2;
+    /** The index of the duplicate <CODE>PdfContentByte</CODE> where the text will be drawn.
+     */    
+    public static final int TEXTCANVAS = 3;
+    
+    protected ArrayList rows = new ArrayList();
+    protected float totalHeight = 0;
+    protected PdfPCell currentRow[];
+    protected int currentRowIdx = 0;
+    protected PdfPCell defaultCell = new PdfPCell((Phrase)null);
+    protected float totalWidth = 0;
+    protected float relativeWidths[];
+    protected float absoluteWidths[];
+    protected PdfPTableEvent tableEvent;
+    
+/** Holds value of property headerRows. */
+    protected int headerRows;
+    
+/** Holds value of property widthPercentage. */
+    protected float widthPercentage = 80;
+    
+/** Holds value of property horizontalAlignment. */
+    private int horizontalAlignment = Element.ALIGN_CENTER;
+    
+/** Holds value of property skipFirstHeader. */
+    private boolean skipFirstHeader = false;
+
+    protected boolean isColspan = false;
+    
+    protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
+
+    /**
+     * Holds value of property lockedWidth.
+     */
+    private boolean lockedWidth = false;
+    
+    /**
+     * Holds value of property splitRows.
+     */
+    private boolean splitRows = true;
+    
+/** The spacing before the table. */
+    protected float spacingBefore;
+    
+/** The spacing after the table. */
+    protected float spacingAfter;
+    
+    /**
+     * Holds value of property extendLastRow.
+     */
+    private boolean extendLastRow;
+    
+    /**
+     * Holds value of property headersInEvent.
+     */
+    private boolean headersInEvent;
+    
+    /**
+     * Holds value of property splitLate.
+     */
+    private boolean splitLate = true;
+    
+    protected PdfPTable() {
+    }
+    
+    /** Constructs a <CODE>PdfPTable</CODE> with the relative column widths.
+     * @param relativeWidths the relative column widths
+     */    
+    public PdfPTable(float relativeWidths[]) {
+        if (relativeWidths == null)
+            throw new NullPointerException("The widths array in PdfPTable constructor can not be null.");
+        if (relativeWidths.length == 0)
+            throw new IllegalArgumentException("The widths array in PdfPTable constructor can not have zero length.");
+        this.relativeWidths = new float[relativeWidths.length];
+        System.arraycopy(relativeWidths, 0, this.relativeWidths, 0, relativeWidths.length);
+        absoluteWidths = new float[relativeWidths.length];
+        calculateWidths();
+        currentRow = new PdfPCell[absoluteWidths.length];
+    }
+    
+    /** Constructs a <CODE>PdfPTable</CODE> with <CODE>numColumns</CODE> columns.
+     * @param numColumns the number of columns
+     */    
+    public PdfPTable(int numColumns) {
+        if (numColumns <= 0)
+            throw new IllegalArgumentException("The number of columns in PdfPTable constructor must be greater than zero.");
+        relativeWidths = new float[numColumns];
+        for (int k = 0; k < numColumns; ++k)
+            relativeWidths[k] = 1;
+        absoluteWidths = new float[relativeWidths.length];
+        calculateWidths();
+        currentRow = new PdfPCell[absoluteWidths.length];
+    }
+    
+    /** Constructs a copy of a <CODE>PdfPTable</CODE>.
+     * @param table the <CODE>PdfPTable</CODE> to be copied
+     */    
+    public PdfPTable(PdfPTable table) {
+        copyFormat(table);
+        for (int k = 0; k < currentRow.length; ++k) {
+            if (table.currentRow[k] == null)
+                break;
+            currentRow[k] = new PdfPCell(table.currentRow[k]);
+        }
+        for (int k = 0; k < table.rows.size(); ++k) {
+            PdfPRow row = (PdfPRow)(table.rows.get(k));
+            if (row != null)
+                row = new PdfPRow(row);
+            rows.add(row);
+        }
+    }
+    
+    /**
+     * Makes a shallow copy of a table (format without content).
+     * @param table
+     * @return a shallow copy of the table
+     */
+    public static PdfPTable shallowCopy(PdfPTable table) {
+        PdfPTable nt = new PdfPTable();
+        nt.copyFormat(table);
+        return nt;
+    }
+
+    /**
+     * Copies the format of the sourceTable without copying the content. 
+     * @param sourceTable
+     */
+    private void copyFormat(PdfPTable sourceTable) {
+        relativeWidths = new float[sourceTable.relativeWidths.length];
+        absoluteWidths = new float[sourceTable.relativeWidths.length];
+        System.arraycopy(sourceTable.relativeWidths, 0, relativeWidths, 0, relativeWidths.length);
+        System.arraycopy(sourceTable.absoluteWidths, 0, absoluteWidths, 0, relativeWidths.length);
+        totalWidth = sourceTable.totalWidth;
+        totalHeight = sourceTable.totalHeight;
+        currentRowIdx = 0;
+        tableEvent = sourceTable.tableEvent;
+        runDirection = sourceTable.runDirection;
+        defaultCell = new PdfPCell(sourceTable.defaultCell);
+        currentRow = new PdfPCell[sourceTable.currentRow.length];
+        isColspan = sourceTable.isColspan;
+        splitRows = sourceTable.splitRows;
+        spacingAfter = sourceTable.spacingAfter;
+        spacingBefore = sourceTable.spacingBefore;
+        headerRows = sourceTable.headerRows;
+        lockedWidth = sourceTable.lockedWidth;
+        extendLastRow = sourceTable.extendLastRow;
+        headersInEvent = sourceTable.headersInEvent;
+        widthPercentage = sourceTable.widthPercentage;
+        splitLate = sourceTable.splitLate;
+        skipFirstHeader = sourceTable.skipFirstHeader;
+        horizontalAlignment = sourceTable.horizontalAlignment;
+    }
+
+    /** Sets the relative widths of the table.
+     * @param relativeWidths the relative widths of the table.
+     * @throws DocumentException if the number of widths is different than the number
+     * of columns
+     */    
+    public void setWidths(float relativeWidths[]) throws DocumentException {
+        if (relativeWidths.length != this.relativeWidths.length)
+            throw new DocumentException("Wrong number of columns.");
+        this.relativeWidths = new float[relativeWidths.length];
+        System.arraycopy(relativeWidths, 0, this.relativeWidths, 0, relativeWidths.length);
+        absoluteWidths = new float[relativeWidths.length];
+        totalHeight = 0;
+        calculateWidths();
+        calculateHeights();
+    }
+
+    /** Sets the relative widths of the table.
+     * @param relativeWidths the relative widths of the table.
+     * @throws DocumentException if the number of widths is different than the number
+     * of columns
+     */    
+    public void setWidths(int relativeWidths[]) throws DocumentException {
+        float tb[] = new float[relativeWidths.length];
+        for (int k = 0; k < relativeWidths.length; ++k)
+            tb[k] = relativeWidths[k];
+        setWidths(tb);
+    }
+
+    private void calculateWidths() {
+        if (totalWidth <= 0)
+            return;
+        float total = 0;
+        for (int k = 0; k < absoluteWidths.length; ++k) {
+            total += relativeWidths[k];
+        }
+        for (int k = 0; k < absoluteWidths.length; ++k) {
+            absoluteWidths[k] = totalWidth * relativeWidths[k] / total;
+        }
+    }
+    
+    /** Sets the full width of the table.
+     * @param totalWidth the full width of the table.
+     */    
+    public void setTotalWidth(float totalWidth) {
+        if (this.totalWidth == totalWidth)
+            return;
+        this.totalWidth = totalWidth;
+        totalHeight = 0;
+        calculateWidths();
+        calculateHeights();
+    }
+
+    /** Sets the full width of the table from the absolute column width.
+     * @param columnWidth the absolute width of each column
+     * @throws DocumentException if the number of widths is different than the number
+     * of columns
+     */    
+    public void setTotalWidth(float columnWidth[]) throws DocumentException {
+        if (columnWidth.length != this.relativeWidths.length)
+            throw new DocumentException("Wrong number of columns.");
+        totalWidth = 0;
+        for (int k = 0; k < columnWidth.length; ++k)
+            totalWidth += columnWidth[k];
+        setWidths(columnWidth);
+    }
+
+    /** Sets the percentage width of the table from the absolute column width.
+     * @param columnWidth the absolute width of each column
+     * @param pageSize the page size
+     * @throws DocumentException
+     */    
+    public void setWidthPercentage(float columnWidth[], Rectangle pageSize) throws DocumentException {
+        if (columnWidth.length != this.relativeWidths.length)
+            throw new IllegalArgumentException("Wrong number of columns.");
+        float totalWidth = 0;
+        for (int k = 0; k < columnWidth.length; ++k)
+            totalWidth += columnWidth[k];
+        widthPercentage = totalWidth / (pageSize.right() - pageSize.left()) * 100f;
+        setWidths(columnWidth);
+    }
+
+    /** Gets the full width of the table.
+     * @return the full width of the table
+     */    
+    public float getTotalWidth() {
+        return totalWidth;
+    }
+
+    void calculateHeights() {
+        if (totalWidth <= 0)
+            return;
+        totalHeight = 0;
+        for (int k = 0; k < rows.size(); ++k) {
+            PdfPRow row = (PdfPRow)rows.get(k);
+            if (row != null) {
+                row.setWidths(absoluteWidths);
+                totalHeight += row.getMaxHeights();
+            }
+        }
+    }
+    
+    /**
+     * Calculates the heights of the table.
+     */
+    public void calculateHeightsFast() {
+        if (totalWidth <= 0)
+            return;
+        totalHeight = 0;
+        for (int k = 0; k < rows.size(); ++k) {
+            PdfPRow row = (PdfPRow)rows.get(k);
+            if (row != null)
+                totalHeight += row.getMaxHeights();
+        }
+    }
+    
+    /** Gets the default <CODE>PdfPCell</CODE> that will be used as
+     * reference for all the <CODE>addCell</CODE> methods except
+     * <CODE>addCell(PdfPCell)</CODE>.
+     * @return default <CODE>PdfPCell</CODE>
+     */    
+    public PdfPCell getDefaultCell() {
+        return defaultCell;
+    }
+    
+    /** Adds a cell element.
+     * @param cell the cell element
+     */    
+    public void addCell(PdfPCell cell) {
+        PdfPCell ncell = new PdfPCell(cell);
+        int colspan = ncell.getColspan();
+        colspan = Math.max(colspan, 1);
+        colspan = Math.min(colspan, currentRow.length - currentRowIdx);
+        ncell.setColspan(colspan);
+        if (colspan != 1)
+            isColspan = true;
+        int rdir = ncell.getRunDirection();
+        if (rdir == PdfWriter.RUN_DIRECTION_DEFAULT)
+            ncell.setRunDirection(runDirection);
+        currentRow[currentRowIdx] = ncell;
+        currentRowIdx += colspan;
+        if (currentRowIdx >= currentRow.length) {
+            if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+                PdfPCell rtlRow[] = new PdfPCell[absoluteWidths.length];
+                int rev = currentRow.length;
+                for (int k = 0; k < currentRow.length; ++k) {
+                    PdfPCell rcell = currentRow[k];
+                    int cspan = rcell.getColspan();
+                    rev -= cspan;
+                    rtlRow[rev] = rcell;
+                    k += cspan - 1;
+                }
+                currentRow = rtlRow;
+            }
+            PdfPRow row = new PdfPRow(currentRow);
+            if (totalWidth > 0) {
+                row.setWidths(absoluteWidths);
+                totalHeight += row.getMaxHeights();
+            }
+            rows.add(row);
+            currentRow = new PdfPCell[absoluteWidths.length];
+            currentRowIdx = 0;
+        }
+    }
+    
+    /** Adds a cell element.
+     * @param text the text for the cell
+     */    
+    public void addCell(String text) {
+        addCell(new Phrase(text));
+    }
+    
+    /**
+     * Adds a nested table.
+     * @param table the table to be added to the cell
+     */    
+    public void addCell(PdfPTable table) {
+        defaultCell.setTable(table);
+        addCell(defaultCell);
+        defaultCell.setTable(null);
+    }
+    
+    /**
+     * Adds an Image as Cell.
+     * @param image the <CODE>Image</CODE> to add to the table. This image will fit in the cell
+     */    
+    public void addCell(Image image) {
+        defaultCell.setImage(image);
+        addCell(defaultCell);
+        defaultCell.setImage(null);
+    }
+    
+    /**
+     * Adds a cell element.
+     * @param phrase the <CODE>Phrase</CODE> to be added to the cell
+     */    
+    public void addCell(Phrase phrase) {
+        defaultCell.setPhrase(phrase);
+        addCell(defaultCell);
+        defaultCell.setPhrase(null);
+    }
+    
+    /**
+     * Writes the selected rows to the document.
+     * <P>
+     * <CODE>canvases</CODE> is obtained from <CODE>beginWritingRows()</CODE>.
+     * @param rowStart the first row to be written, zero index
+     * @param rowEnd the last row to be written + 1. If it is -1 all the
+     * rows to the end are written
+     * @param xPos the x write coodinate
+     * @param yPos the y write coodinate
+     * @param canvases an array of 4 <CODE>PdfContentByte</CODE> obtained from
+     * <CODE>beginWrittingRows()</CODE>
+     * @return the y coordinate position of the bottom of the last row
+     * @see #beginWritingRows(com.lowagie.text.pdf.PdfContentByte)
+     */    
+    public float writeSelectedRows(int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte[] canvases) {
+        return writeSelectedRows(0, -1, rowStart, rowEnd, xPos, yPos, canvases);
+    }
+    
+    /** Writes the selected rows and columns to the document.
+     * This method does not clip the columns; this is only important
+     * if there are columns with colspan at boundaries.
+     * <P>
+     * <CODE>canvases</CODE> is obtained from <CODE>beginWritingRows()</CODE>.
+     * <P>
+     * The table event is only fired for complete rows.
+     * @param colStart the first column to be written, zero index
+     * @param colEnd the last column to be written + 1. If it is -1 all the
+     * columns to the end are written
+     * @param rowStart the first row to be written, zero index
+     * @param rowEnd the last row to be written + 1. If it is -1 all the
+     * rows to the end are written
+     * @param xPos the x write coodinate
+     * @param yPos the y write coodinate
+     * @param canvases an array of 4 <CODE>PdfContentByte</CODE> obtained from
+     * <CODE>beginWrittingRows()</CODE>
+     * @return the y coordinate position of the bottom of the last row
+     * @see #beginWritingRows(com.lowagie.text.pdf.PdfContentByte)
+     */    
+    public float writeSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte[] canvases) {
+        if (totalWidth <= 0)
+            throw new RuntimeException("The table width must be greater than zero.");
+        int size = rows.size();
+        if (rowEnd < 0)
+            rowEnd = size;
+        rowEnd = Math.min(rowEnd, size);
+        if (rowStart < 0)
+            rowStart = 0;
+        if (rowStart >= rowEnd)
+            return yPos;
+        if (colEnd < 0)
+            colEnd = absoluteWidths.length;
+        colEnd = Math.min(colEnd, absoluteWidths.length);
+        if (colStart < 0)
+            colStart = 0;
+        colStart = Math.min(colStart, absoluteWidths.length);
+        float yPosStart = yPos;
+        for (int k = rowStart; k < rowEnd; ++k) {
+            PdfPRow row = (PdfPRow)rows.get(k);
+            if (row != null) {
+                row.writeCells(colStart, colEnd, xPos, yPos, canvases);
+                yPos -= row.getMaxHeights();
+            }
+        }
+        if (tableEvent != null && colStart == 0 && colEnd == absoluteWidths.length) {
+            float heights[] = new float[rowEnd - rowStart + 1];
+            heights[0] = yPosStart;
+            for (int k = rowStart; k < rowEnd; ++k) {
+                PdfPRow row = (PdfPRow)rows.get(k);
+                float hr = 0;
+                if (row != null)
+                    hr = row.getMaxHeights();
+                heights[k - rowStart + 1] = heights[k - rowStart] - hr;
+            }
+            tableEvent.tableLayout(this, getEventWidths(xPos, rowStart, rowEnd, headersInEvent), heights, headersInEvent ? headerRows : 0, rowStart, canvases);
+        }
+        return yPos;
+    }
+    
+    /**
+     * Writes the selected rows to the document.
+     * 
+     * @param rowStart the first row to be written, zero index
+     * @param rowEnd the last row to be written + 1. If it is -1 all the
+     * rows to the end are written
+     * @param xPos the x write coodinate
+     * @param yPos the y write coodinate
+     * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
+     * be written to
+     * @return the y coordinate position of the bottom of the last row
+     */    
+    public float writeSelectedRows(int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas) {
+        return writeSelectedRows(0, -1, rowStart, rowEnd, xPos, yPos, canvas);
+    }
+    
+    /**
+     * Writes the selected rows to the document.
+     * This method clips the columns; this is only important
+     * if there are columns with colspan at boundaries.
+     * <P>
+     * The table event is only fired for complete rows.
+     * 
+     * @param colStart the first column to be written, zero index
+     * @param colEnd the last column to be written + 1. If it is -1 all the
+     * @param rowStart the first row to be written, zero index
+     * @param rowEnd the last row to be written + 1. If it is -1 all the
+     * rows to the end are written
+     * @param xPos the x write coodinate
+     * @param yPos the y write coodinate
+     * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
+     * be written to
+     * @return the y coordinate position of the bottom of the last row
+     */    
+    public float writeSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas) {
+        if (colEnd < 0)
+            colEnd = absoluteWidths.length;
+        colEnd = Math.min(colEnd, absoluteWidths.length);
+        if (colStart < 0)
+            colStart = 0;
+        colStart = Math.min(colStart, absoluteWidths.length);
+        if (colStart != 0 || colEnd != absoluteWidths.length) {
+            float w = 0;
+            for (int k = colStart; k < colEnd; ++k)
+                w += absoluteWidths[k];
+            canvas.saveState();
+            float lx = 0;
+            float rx = 0;
+            if (colStart == 0)
+                lx = 10000;
+            if (colEnd == absoluteWidths.length)
+                rx = 10000;
+            canvas.rectangle(xPos - lx, -10000, w + lx + rx, 20000);
+            canvas.clip();
+            canvas.newPath();
+        }
+        PdfContentByte[] canvases = beginWritingRows(canvas);
+        float y = writeSelectedRows(colStart, colEnd, rowStart, rowEnd, xPos, yPos, canvases);
+        endWritingRows(canvases);
+        if (colStart != 0 || colEnd != absoluteWidths.length)
+            canvas.restoreState();
+        return y;
+    }
+    
+    /** Gets and initializes the 4 layers where the table is written to. The text or graphics are added to
+     * one of the 4 <CODE>PdfContentByte</CODE> returned with the following order:<p>
+     * <ul>
+     * <li><CODE>PdfPtable.BASECANVAS</CODE> - the original <CODE>PdfContentByte</CODE>. Anything placed here
+     * will be under the table.
+     * <li><CODE>PdfPtable.BACKGROUNDCANVAS</CODE> - the layer where the background goes to.
+     * <li><CODE>PdfPtable.LINECANVAS</CODE> - the layer where the lines go to.
+     * <li><CODE>PdfPtable.TEXTCANVAS</CODE> - the layer where the text go to. Anything placed here
+     * will be over the table.
+     * </ul><p>
+     * The layers are placed in sequence on top of each other.
+     * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
+     * be written to
+     * @return an array of 4 <CODE>PdfContentByte</CODE>
+     * @see #writeSelectedRows(int, int, float, float, PdfContentByte[])
+     */    
+    public static PdfContentByte[] beginWritingRows(PdfContentByte canvas) {
+        return new PdfContentByte[]{
+            canvas,
+            canvas.getDuplicate(),
+            canvas.getDuplicate(),
+            canvas.getDuplicate(),
+        };
+    }
+    
+    /** Finishes writing the table.
+     * @param canvases the array returned by <CODE>beginWritingRows()</CODE>
+     */    
+    public static void endWritingRows(PdfContentByte[] canvases) {
+        PdfContentByte canvas = canvases[BASECANVAS];
+        canvas.saveState();
+        canvas.add(canvases[BACKGROUNDCANVAS]);
+        canvas.restoreState();
+        canvas.saveState();
+        canvas.setLineCap(2);
+        canvas.resetRGBColorStroke();
+        canvas.add(canvases[LINECANVAS]);
+        canvas.restoreState();
+        canvas.add(canvases[TEXTCANVAS]);
+    }
+    
+    /** Gets the number of rows in this table.
+     * @return the number of rows in this table
+     */    
+    public int size() {
+        return rows.size();
+    }
+    
+    /** Gets the total height of the table.
+     * @return the total height of the table
+     */    
+    public float getTotalHeight() {
+        return totalHeight;
+    }
+    
+    /** Gets the height of a particular row.
+     * @param idx the row index (starts at 0)
+     * @return the height of a particular row
+     */    
+    public float getRowHeight(int idx) {
+        if (totalWidth <= 0 || idx < 0 || idx >= rows.size())
+            return 0;
+        PdfPRow row = (PdfPRow)rows.get(idx);
+        if (row == null)
+            return 0;
+        return row.getMaxHeights();
+    }
+    
+    /** Gets the height of the rows that constitute the header as defined by
+     * <CODE>setHeaderRows()</CODE>.
+     * @return the height of the rows that constitute the header
+     */    
+    public float getHeaderHeight() {
+        float total = 0;
+        int size = Math.min(rows.size(), headerRows);
+        for (int k = 0; k < size; ++k) {
+            PdfPRow row = (PdfPRow)rows.get(k);
+            if (row != null)
+                total += row.getMaxHeights();
+        }
+        return total;
+    }
+    
+    /** Deletes a row from the table.
+     * @param rowNumber the row to be deleted
+     * @return <CODE>true</CODE> if the row was deleted
+     */    
+    public boolean deleteRow(int rowNumber) {
+        if (rowNumber < 0 || rowNumber >= rows.size()) {
+            return false;
+        }
+        if (totalWidth > 0) {
+            PdfPRow row = (PdfPRow)rows.get(rowNumber);
+            if (row != null)
+                totalHeight -= row.getMaxHeights();
+        }
+        rows.remove(rowNumber);
+        return true;
+    }
+    
+    /** Deletes the last row in the table.
+     * @return <CODE>true</CODE> if the last row was deleted
+     */    
+    public boolean deleteLastRow() {
+        return deleteRow(rows.size() - 1);
+    }
+    
+    /**
+     * Removes all of the rows except headers
+     */
+    public void deleteBodyRows() {
+        ArrayList rows2 = new ArrayList();
+        for (int k = 0; k < headerRows; ++k)
+            rows2.add(rows.get(k));
+        rows = rows2;
+        totalHeight = 0;
+        if (totalWidth > 0)
+            totalHeight = getHeaderHeight();
+    }
+
+    /** Gets the number of the rows that constitute the header.
+     * @return the number of the rows that constitute the header
+     */
+    public int getHeaderRows() {
+        return headerRows;
+    }
+    
+    /** Sets the number of the top rows that constitute the header.
+     * This header has only meaning if the table is added to <CODE>Document</CODE>
+     * and the table crosses pages.
+     * @param headerRows the number of the top rows that constitute the header
+     */
+    public void setHeaderRows(int headerRows) {
+        if (headerRows < 0)
+            headerRows = 0;
+        this.headerRows = headerRows;
+    }
+    
+    /**
+     * Gets all the chunks in this element.
+     *
+     * @return	an <CODE>ArrayList</CODE>
+     */
+    public ArrayList getChunks() {
+        return new ArrayList();
+    }
+    
+    /**
+     * Gets the type of the text element.
+     *
+     * @return	a type
+     */
+    public int type() {
+        return Element.PTABLE;
+    }
+    
+    /**
+     * Processes the element by adding it (or the different parts) to an
+     * <CODE>ElementListener</CODE>.
+     *
+     * @param	listener	an <CODE>ElementListener</CODE>
+     * @return	<CODE>true</CODE> if the element was processed successfully
+     */
+    public boolean process(ElementListener listener) {
+        try {
+            return listener.add(this);
+        }
+        catch(DocumentException de) {
+            return false;
+        }
+    }
+    
+    /** Gets the width percentage that the table will occupy in the page.
+     * @return the width percentage that the table will occupy in the page
+     */
+    public float getWidthPercentage() {
+        return widthPercentage;
+    }
+    
+    /** Sets the width percentage that the table will occupy in the page.
+     * @param widthPercentage the width percentage that the table will occupy in the page
+     */
+    public void setWidthPercentage(float widthPercentage) {
+        this.widthPercentage = widthPercentage;
+    }
+    
+    /** Gets the horizontal alignment of the table relative to the page.
+     * @return the horizontal alignment of the table relative to the page
+     */
+    public int getHorizontalAlignment() {
+        return horizontalAlignment;
+    }
+    
+    /** Sets the horizontal alignment of the table relative to the page.
+     * It only has meaning if the width percentage is less than
+     * 100%.
+     * @param horizontalAlignment the horizontal alignment of the table relative to the page
+     */
+    public void setHorizontalAlignment(int horizontalAlignment) {
+        this.horizontalAlignment = horizontalAlignment;
+    }
+    
+    /**
+     * Gets a row with a given index
+     * (added by Jin-Hsia Yang).
+     * @param idx
+     * @return the row at position idx
+     */
+    public PdfPRow getRow(int idx) {
+        return (PdfPRow)rows.get(idx);
+    }
+
+    /**
+     * Gets an arraylist with all the rows in the table.
+     * @return an arraylist
+     */
+    public ArrayList getRows() {
+        return rows;
+    }
+
+    /** Sets the table event for this table.
+     * @param event the table event for this table
+     */    
+    public void setTableEvent(PdfPTableEvent event) {
+        tableEvent = event;
+    }
+    
+    /** Gets the table event for this page.
+     * @return the table event for this page
+     */    
+    public PdfPTableEvent getTableEvent() {
+        return tableEvent;
+    }
+    
+    /** Gets the absolute sizes of each column width.
+     * @return he absolute sizes of each column width
+     */    
+    public float[] getAbsoluteWidths() {
+        return absoluteWidths;
+    }
+    
+    float [][] getEventWidths(float xPos, int firstRow, int lastRow, boolean includeHeaders) {
+        if (includeHeaders) {
+            firstRow = Math.max(firstRow, headerRows);
+            lastRow = Math.max(lastRow, headerRows);
+        }
+        float widths[][] = new float[(includeHeaders ? headerRows : 0) + lastRow - firstRow][];
+        if (isColspan) {
+            int n = 0;
+            if (includeHeaders) {
+                for (int k = 0; k < headerRows; ++k) {
+                    PdfPRow row = (PdfPRow)rows.get(k);
+                    if (row == null)
+                        ++n;
+                    else
+                        widths[n++] = row.getEventWidth(xPos);
+                }
+            }
+            for (; firstRow < lastRow; ++firstRow) {
+                    PdfPRow row = (PdfPRow)rows.get(firstRow);
+                    if (row == null)
+                        ++n;
+                    else
+                        widths[n++] = row.getEventWidth(xPos);
+            }
+        }
+        else {
+            float width[] = new float[absoluteWidths.length + 1];
+            width[0] = xPos;
+            for (int k = 0; k < absoluteWidths.length; ++k)
+                width[k + 1] = width[k] + absoluteWidths[k];
+            for (int k = 0; k < widths.length; ++k)
+                widths[k] = width;
+        }
+        return widths;
+    }
+
+
+    /** Getter for property skipFirstHeader.
+     * @return Value of property skipFirstHeader.
+     */
+    public boolean isSkipFirstHeader() {
+        return skipFirstHeader;
+    }
+    
+    /** Skips the printing of the first header. Used when printing
+     * tables in succession belonging to the same printed table aspect.
+     * @param skipFirstHeader New value of property skipFirstHeader.
+     */
+    public void setSkipFirstHeader(boolean skipFirstHeader) {
+        this.skipFirstHeader = skipFirstHeader;
+    }
+
+    /**
+     * Sets the run direction of the contents of the table.
+     * @param runDirection
+     */
+    public void setRunDirection(int runDirection) {
+        if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
+            throw new RuntimeException("Invalid run direction: " + runDirection);
+        this.runDirection = runDirection;
+    }
+    
+    /**
+     * Returns the run direction of the contents in the table.
+     * @return One of the following values: PdfWriter.RUN_DIRECTION_DEFAULT, PdfWriter.RUN_DIRECTION_NO_BIDI, PdfWriter.RUN_DIRECTION_LTR or PdfWriter.RUN_DIRECTION_RTL.
+     */
+    public int getRunDirection() {
+        return runDirection;
+    }
+    
+    /**
+     * Getter for property lockedWidth.
+     * @return Value of property lockedWidth.
+     */
+    public boolean isLockedWidth() {
+        return this.lockedWidth;
+    }
+    
+    /**
+     * Uses the value in <CODE>setTotalWidth()</CODE> in <CODE>Document.add()</CODE>.
+     * @param lockedWidth <CODE>true</CODE> to use the value in <CODE>setTotalWidth()</CODE> in <CODE>Document.add()</CODE>
+     */
+    public void setLockedWidth(boolean lockedWidth) {
+        this.lockedWidth = lockedWidth;
+    }
+    
+    /**
+     * Gets the split value.
+     * @return true to split; false otherwise
+     */
+    public boolean isSplitRows() {
+        return this.splitRows;
+    }
+    
+    /**
+     * When set the rows that won't fit in the page will be split. 
+     * Note that it takes at least twice the memory to handle a split table row
+     * than a normal table. <CODE>true</CODE> by default.
+     * @param splitRows true to split; false otherwise
+     */
+    public void setSplitRows(boolean splitRows) {
+        this.splitRows = splitRows;
+    }
+    
+/**
+ * Sets the spacing before this table.
+ *
+ * @param	spacing		the new spacing
+ */
+    
+    public void setSpacingBefore(float spacing) {
+        this.spacingBefore = spacing;
+    }
+    
+/**
+ * Sets the spacing after this table.
+ *
+ * @param	spacing		the new spacing
+ */
+    
+    public void setSpacingAfter(float spacing) {
+        this.spacingAfter = spacing;
+    }    
+
+/**
+ * Gets the spacing before this table.
+ *
+ * @return	the spacing
+ */
+    
+    public float spacingBefore() {
+        return spacingBefore;
+    }
+    
+/**
+ * Gets the spacing before this table.
+ *
+ * @return	the spacing
+ */
+    
+    public float spacingAfter() {
+        return spacingAfter;
+    }    
+    
+    /**
+     *  Gets the value of the last row extension.
+     * @return true if the last row will extend; false otherwise
+     */
+    public boolean isExtendLastRow() {
+        return this.extendLastRow;
+    }
+    
+    /**
+     * When set the last row will be extended to fill all the remaining space to the
+     * bottom boundary.
+     * @param extendLastRow true to extend the last row; false otherwise
+     */
+    public void setExtendLastRow(boolean extendLastRow) {
+        this.extendLastRow = extendLastRow;
+    }
+    
+    /**
+     * Gets the header status inclusion in PdfPTableEvent.
+     * @return true if the headers are included; false otherwise
+     */
+    public boolean isHeadersInEvent() {
+        return this.headersInEvent;
+    }
+    
+    /**
+     * When set the PdfPTableEvent will include the headers.
+     * @param headersInEvent true to include the headers; false otherwise
+     */
+    public void setHeadersInEvent(boolean headersInEvent) {
+        this.headersInEvent = headersInEvent;
+    }
+    
+    /**
+     * Gets the property splitLate.
+     * @return the property splitLate
+     */
+    public boolean isSplitLate() {
+        return this.splitLate;
+    }
+    
+    /**
+     * If true the row will only split if it's the first one in an empty page.
+     * It's true by default.
+     *<p>
+     * It's only meaningful if setSplitRows(true).
+     * @param splitLate the property value
+     */
+    public void setSplitLate(boolean splitLate) {
+        this.splitLate = splitLate;
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPTableEvent.java b/LibrarySource/com/lowagie/text/pdf/PdfPTableEvent.java
new file mode 100644
index 0000000..90f4f64
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPTableEvent.java
@@ -0,0 +1,95 @@
+/*
+ * $Id: PdfPTableEvent.java,v 1.13 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/** An interface that can be used to retrieve the position of cells in <CODE>PdfPTable</CODE>.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface PdfPTableEvent {
+    
+    /** This method is called at the end of the table rendering. The text or graphics are added to
+     * one of the 4 <CODE>PdfContentByte</CODE> contained in
+     * <CODE>canvases</CODE>.<br>
+     * The indexes to <CODE>canvases</CODE> are:<p>
+     * <ul>
+     * <li><CODE>PdfPTable.BASECANVAS</CODE> - the original <CODE>PdfContentByte</CODE>. Anything placed here
+     * will be under the table.
+     * <li><CODE>PdfPTable.BACKGROUNDCANVAS</CODE> - the layer where the background goes to.
+     * <li><CODE>PdfPTable.LINECANVAS</CODE> - the layer where the lines go to.
+     * <li><CODE>PdfPTable.TEXTCANVAS</CODE> - the layer where the text go to. Anything placed here
+     * will be over the table.
+     * </ul>
+     * The layers are placed in sequence on top of each other.
+     * <p>
+     * The <CODE>widths</CODE> and <CODE>heights</CODE> have the coordinates of the cells.<br>
+     * The size of the <CODE>widths</CODE> array is the number of rows.
+     * Each sub-array in <CODE>widths</CODE> corresponds to the x column border positions where
+     * the first element is the x coordinate of the left table border and the last
+     * element is the x coordinate of the right table border. 
+     * If colspan is not used all the sub-arrays in <CODE>widths</CODE>
+     * are the same.<br>
+     * For the <CODE>heights</CODE> the first element is the y coordinate of the top table border and the last
+     * element is the y coordinate of the bottom table border.
+     * @param table the <CODE>PdfPTable</CODE> in use
+     * @param widths an array of arrays with the cells' x positions. It has the length of the number
+     * of rows
+     * @param heights an array with the cells' y positions. It has a length of the number
+     * of rows + 1
+     * @param headerRows the number of rows defined for the header.
+     * @param rowStart the first row number after the header
+     * @param canvases an array of <CODE>PdfContentByte</CODE>
+     */    
+    public void tableLayout(PdfPTable table, float widths[][], float heights[], int headerRows, int rowStart, PdfContentByte[] canvases);
+
+}
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPage.java b/LibrarySource/com/lowagie/text/pdf/PdfPage.java
new file mode 100644
index 0000000..1b84750
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPage.java
@@ -0,0 +1,198 @@
+/*
+ * $Id: PdfPage.java,v 1.47 2004/11/29 14:07:03 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.util.HashMap;
+/**
+ * <CODE>PdfPage</CODE> is the PDF Page-object.
+ * <P>
+ * A Page object is a dictionary whose keys describe a single page containing text,
+ * graphics, and images. A Page onjects is a leaf of the Pages tree.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.4 (page 73-81)
+ *
+ * @see		PdfPageElement
+ * @see		PdfPages
+ */
+
+public class PdfPage extends PdfDictionary {
+
+    private static final String boxStrings[] = {"crop", "trim", "art", "bleed"};
+    private static final PdfName boxNames[] = {PdfName.CROPBOX, PdfName.TRIMBOX, PdfName.ARTBOX, PdfName.BLEEDBOX};
+    // membervariables
+    
+/** value of the <B>Rotate</B> key for a page in PORTRAIT */
+    public static final PdfNumber PORTRAIT = new PdfNumber(0);
+    
+/** value of the <B>Rotate</B> key for a page in LANDSCAPE */
+    public static final PdfNumber LANDSCAPE = new PdfNumber(90);
+    
+/** value of the <B>Rotate</B> key for a page in INVERTEDPORTRAIT */
+    public static final PdfNumber INVERTEDPORTRAIT = new PdfNumber(180);
+    
+/**	value of the <B>Rotate</B> key for a page in SEASCAPE */
+    public static final PdfNumber SEASCAPE = new PdfNumber(270);
+    
+/** value of the <B>MediaBox</B> key */
+    PdfRectangle mediaBox;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfPage</CODE>.
+ *
+ * @param		mediaBox		a value for the <B>MediaBox</B> key
+ * @param		resources		an indirect reference to a <CODE>PdfResources</CODE>-object
+ * @param		rotate			a value for the <B>Rotate</B> key
+ */
+    
+//    PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources, PdfNumber rotate) {
+//        super(PAGE);
+//        this.mediaBox = mediaBox;
+//        put(PdfName.MEDIABOX, mediaBox);
+//        put(PdfName.RESOURCES, resources);
+//        if (rotate != null) {
+//            put(PdfName.ROTATE, rotate);
+//        }
+//        if (cropBox != null)
+//            put(PdfName.CROPBOX, new PdfRectangle(cropBox));
+//    }
+    
+/**
+ * Constructs a <CODE>PdfPage</CODE>.
+ *
+ * @param		mediaBox		a value for the <B>MediaBox</B> key
+ * @param		resources		an indirect reference to a <CODE>PdfResources</CODE>-object
+ * @param		rotate			a value for the <B>Rotate</B> key
+ */
+    
+    PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources, int rotate) {
+        super(PAGE);
+        this.mediaBox = mediaBox;
+        put(PdfName.MEDIABOX, mediaBox);
+        put(PdfName.RESOURCES, resources);
+        if (rotate != 0) {
+            put(PdfName.ROTATE, new PdfNumber(rotate));
+        }
+        for (int k = 0; k < boxStrings.length; ++k) {
+            PdfObject rect = (PdfObject)boxSize.get(boxStrings[k]);
+            if (rect != null)
+                put(boxNames[k], rect);
+        }
+    }
+    
+/**
+ * Constructs a <CODE>PdfPage</CODE>.
+ *
+ * @param		mediaBox		a value for the <B>MediaBox</B> key
+ * @param		resources		an indirect reference to a <CODE>PdfResources</CODE>-object
+ */
+    
+//    PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources) {
+//        this(mediaBox, cropBox, resources, null);
+//    }
+    
+/**
+ * Constructs a <CODE>PdfPage</CODE>.
+ *
+ * @param		mediaBox		a value for the <B>MediaBox</B> key
+ * @param		resources		an indirect reference to a <CODE>PdfResources</CODE>-object
+ */
+    
+    PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources) {
+        this(mediaBox, boxSize, resources, 0);
+    }
+    
+/**
+ * Checks if this page element is a tree of pages.
+ * <P>
+ * This method allways returns <CODE>false</CODE>.
+ *
+ * @return	<CODE>false</CODE> because this is a single page
+ */
+    
+    public boolean isParent() {
+        return false;
+    }
+    
+    // methods
+    
+/**
+ * Adds an indirect reference pointing to a <CODE>PdfContents</CODE>-object.
+ *
+ * @param		contents		an indirect reference to a <CODE>PdfContents</CODE>-object
+ */
+    
+    void add(PdfIndirectReference contents) {
+        put(PdfName.CONTENTS, contents);
+    }
+    
+/**
+ * Rotates the mediabox, but not the text in it.
+ *
+ * @return		a <CODE>PdfRectangle</CODE>
+ */
+    
+    PdfRectangle rotateMediaBox() {
+        this.mediaBox =  mediaBox.rotate();
+        put(PdfName.MEDIABOX, this.mediaBox);
+        return this.mediaBox;
+    }
+    
+/**
+ * Returns the MediaBox of this Page.
+ *
+ * @return		a <CODE>PdfRectangle</CODE>
+ */
+    
+    PdfRectangle getMediaBox() {
+        return mediaBox;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPageElement.java b/LibrarySource/com/lowagie/text/pdf/PdfPageElement.java
new file mode 100644
index 0000000..6799854
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPageElement.java
@@ -0,0 +1,78 @@
+/*
+ * $Id: PdfPageElement.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * The <CODE>PdfPageElement</CODE> interface has to be implemented by <CODE>PdfPage</CODE> and <CODE>PdfPages</CODE>.
+ *
+ * @see		PdfPage
+ * @see		PdfPages
+ */
+
+interface PdfPageElement {
+    
+/**
+ * Set the value for the <B>Parent</B> key in the Page or Pages Dictionary.
+ *
+ * @param	reference			an indirect reference to a <CODE>PdfPages</CODE>-object
+ */
+    
+    public void setParent(PdfIndirectReference reference);
+    
+/**
+ * Checks if this page element is a tree of pages.
+ *
+ * @return	<CODE>true</CODE> if it's a tree of pages;
+ *			<CODE>false</CODE> if it's a single page
+ */
+    
+    public boolean isParent();
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPageEvent.java b/LibrarySource/com/lowagie/text/pdf/PdfPageEvent.java
new file mode 100644
index 0000000..e76bf5b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPageEvent.java
@@ -0,0 +1,191 @@
+/*
+ * $Id: PdfPageEvent.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.Document;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Paragraph;
+
+/**
+ * Allows a class to catch several document events.
+ *<p>
+ * Note: do not use Document.add() inside a page event.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+
+public interface PdfPageEvent {
+    
+/**
+ * Called when the document is opened.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onOpenDocument(PdfWriter writer, Document document);
+    
+/**
+ * Called when a page is initialized.
+ * <P>
+ * Note that if even if a page is not written this method is still
+ * called. It is preferable to use <CODE>onEndPage</CODE> to avoid
+ * infinite loops.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onStartPage(PdfWriter writer, Document document);
+    
+/**
+ * Called when a page is finished, just before being written to the document.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onEndPage(PdfWriter writer, Document document);
+    
+/**
+ * Called when the document is closed.
+ * <P>
+ * Note that this method is called with the page number equal
+ * to the last page plus one.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onCloseDocument(PdfWriter writer, Document document);
+    
+/**
+ * Called when a Paragraph is written.
+ * <P>
+ * <CODE>paragraphPosition</CODE> will hold the height at which the
+ * paragraph will be written to. This is useful to insert bookmarks with
+ * more control.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param paragraphPosition the position the paragraph will be written to
+ */
+    public void onParagraph(PdfWriter writer, Document document, float paragraphPosition);
+    
+/**
+ * Called when a Paragraph is written.
+ * <P>
+ * <CODE>paragraphPosition</CODE> will hold the height of the end of the paragraph.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param paragraphPosition the position of the end of the paragraph
+ */
+    public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition);
+    
+/**
+ * Called when a Chapter is written.
+ * <P>
+ * <CODE>position</CODE> will hold the height at which the
+ * chapter will be written to.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the chapter will be written to
+ * @param title             the title of the Chapter
+ */
+    public void onChapter(PdfWriter writer,Document document,float paragraphPosition, Paragraph title);
+    
+/**
+ * Called when the end of a Chapter is reached.
+ * <P>
+ * <CODE>position</CODE> will hold the height of the end of the chapter.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the chapter will be written to
+ */
+    public void onChapterEnd(PdfWriter writer,Document document,float paragraphPosition);
+    
+/**
+ * Called when a Section is written.
+ * <P>
+ * <CODE>position</CODE> will hold the height at which the
+ * section will be written to.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the section will be written to
+ * @param depth				the number depth of the section
+ * @param title             the title of the section
+ */
+    public void onSection(PdfWriter writer,Document document,float paragraphPosition, int depth, Paragraph title);
+    
+/**
+ * Called when the end of a Section is reached.
+ * <P>
+ * <CODE>position</CODE> will hold the height of the section end.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the section will be written to
+ */
+    public void onSectionEnd(PdfWriter writer,Document document,float paragraphPosition);
+    
+/**
+ * Called when a <CODE>Chunk</CODE> with a generic tag is written.
+ * <P>
+ * It is usefull to pinpoint the <CODE>Chunk</CODE> location to generate
+ * bookmarks, for example.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param rect the <CODE>Rectangle</CODE> containing the <CODE>Chunk</CODE>
+ * @param text the text of the tag
+ */
+    public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text);
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPageEventHelper.java b/LibrarySource/com/lowagie/text/pdf/PdfPageEventHelper.java
new file mode 100644
index 0000000..ab99717
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPageEventHelper.java
@@ -0,0 +1,203 @@
+/*
+ * $Id: PdfPageEventHelper.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import com.lowagie.text.Document;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Paragraph;
+
+/**
+ * Helps the use of <CODE>PdfPageEvent</CODE> by implementing all the interface methods.
+ * A class can extend <CODE>PdfPageEventHelper</CODE> and only implement the
+ * needed methods.
+ *<p>
+ * Note: do not use Document.add() inside a page event.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+
+public class PdfPageEventHelper implements PdfPageEvent {
+    
+/**
+ * Called when the document is opened.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onOpenDocument(PdfWriter writer,Document document) {
+    }
+    
+/**
+ * Called when a page is initialized.
+ * <P>
+ * Note that if even if a page is not written this method is still
+ * called. It is preferable to use <CODE>onEndPage</CODE> to avoid
+ * infinite loops.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onStartPage(PdfWriter writer,Document document) {
+    }
+    
+/**
+ * Called when a page is finished, just before being written to the document.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onEndPage(PdfWriter writer,Document document) {
+    }
+    
+/**
+ * Called when the document is closed.
+ * <P>
+ * Note that this method is called with the page number equal
+ * to the last page plus one.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ */
+    public void onCloseDocument(PdfWriter writer,Document document) {
+    }
+    
+/**
+ * Called when a Paragraph is written.
+ * <P>
+ * <CODE>paragraphPosition</CODE> will hold the height at which the
+ * paragraph will be written to. This is useful to insert bookmarks with
+ * more control.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param paragraphPosition the position the paragraph will be written to
+ */
+    public void onParagraph(PdfWriter writer,Document document,float paragraphPosition) {
+    }
+    
+/**
+ * Called when a Paragraph is written.
+ * <P>
+ * <CODE>paragraphPosition</CODE> will hold the height of the end of the paragraph.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param paragraphPosition the position of the end of the paragraph
+ */
+    public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition) {
+    }
+    
+/**
+ * Called when a Chapter is written.
+ * <P>
+ * <CODE>position</CODE> will hold the height at which the
+ * chapter will be written to.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the chapter will be written to
+ * @param title             the title of the Chapter
+ */
+    public void onChapter(PdfWriter writer,Document document,float paragraphPosition,Paragraph title) {
+    }
+    
+/**
+ * Called when the end of a Chapter is reached.
+ * <P>
+ * <CODE>position</CODE> will hold the height of the end of the chapter.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param position the position of the end of the chapter.
+ */
+    public void onChapterEnd(PdfWriter writer,Document document,float position) {
+    }
+    
+/**
+ * Called when a Section is written.
+ * <P>
+ * <CODE>position</CODE> will hold the height at which the
+ * section will be written to.
+ *
+ * @param writer            the <CODE>PdfWriter</CODE> for this document
+ * @param document          the document
+ * @param paragraphPosition the position the section will be written to
+ * @param depth				the number depth of the Section
+ * @param title             the title of the section
+ */
+    public void onSection(PdfWriter writer,Document document,float paragraphPosition,int depth,Paragraph title) {
+    }
+    
+/**
+ * Called when the end of a Section is reached.
+ * <P>
+ * <CODE>position</CODE> will hold the height of the section end.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param position the position of the end of the section
+ */
+    public void onSectionEnd(PdfWriter writer,Document document,float position) {
+    }
+    
+/**
+ * Called when a <CODE>Chunk</CODE> with a generic tag is written.
+ * <P>
+ * It is usefull to pinpoint the <CODE>Chunk</CODE> location to generate
+ * bookmarks, for example.
+ *
+ * @param writer the <CODE>PdfWriter</CODE> for this document
+ * @param document the document
+ * @param rect the <CODE>Rectangle</CODE> containing the <CODE>Chunk</CODE>
+ * @param text the text of the tag
+ */
+    public void onGenericTag(PdfWriter writer,Document document,Rectangle rect,String text) {
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPageLabels.java b/LibrarySource/com/lowagie/text/pdf/PdfPageLabels.java
new file mode 100644
index 0000000..4c60f8a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPageLabels.java
@@ -0,0 +1,192 @@
+/*
+ * $Id: PdfPageLabels.java,v 1.14 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.Comparator;
+import java.util.TreeMap;
+import java.util.Iterator;
+
+/** Page labels are used to identify each
+ * page visually on the screen or in print.
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfPageLabels implements Comparator {
+
+    /** Logical pages will have the form 1,2,3,...
+     */    
+    public static int DECIMAL_ARABIC_NUMERALS = 0;
+    /** Logical pages will have the form I,II,III,IV,...
+     */    
+    public static int UPPERCASE_ROMAN_NUMERALS = 1;
+    /** Logical pages will have the form i,ii,iii,iv,...
+     */    
+    public static int LOWERCASE_ROMAN_NUMERALS = 2;
+    /** Logical pages will have the form of uppercase letters
+     * (A to Z for the first 26 pages, AA to ZZ for the next 26, and so on)
+     */    
+    public static int UPPERCASE_LETTERS = 3;
+    /** Logical pages will have the form of uppercase letters
+     * (a to z for the first 26 pages, aa to zz for the next 26, and so on)
+     */    
+    public static int LOWERCASE_LETTERS = 4;
+    /** No logical page numbers are generated but fixed text may
+     * still exist
+     */    
+    public static int EMPTY = 5;
+    /** Dictionary values to set the logical page styles
+     */    
+    static PdfName numberingStyle[] = new PdfName[]{PdfName.D, PdfName.R,
+                new PdfName("r"), PdfName.A, new PdfName("a")};
+    /** The sequence of logical pages. Will contain at least a value for page 1
+     */    
+    TreeMap map;
+    
+    /** Creates a new PdfPageLabel with a default logical page 1
+     */
+    public PdfPageLabels() {
+        map = new TreeMap(this);
+        addPageLabel(1, DECIMAL_ARABIC_NUMERALS, null, 1);
+    }
+
+    /** Compares two <CODE>Integer</CODE>.
+     * @param obj the first <CODE>Integer</CODE>
+     * @param obj1 the second <CODE>Integer</CODE>
+     * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second
+     */    
+    public int compare(Object obj, Object obj1) {
+        int v1 = ((Integer)obj).intValue();
+        int v2 = ((Integer)obj1).intValue();
+        if (v1 < v2)
+            return -1;
+        if (v1 == v2)
+            return 0;
+        return 1;
+    }
+    
+    /** Not used
+     * @param obj not used
+     * @return always <CODE>true</CODE>
+     */    
+    public boolean equals(Object obj) {
+        return true;
+    }
+    
+    /** Adds or replaces a page label.
+     * @param page the real page to start the numbering. First page is 1
+     * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+     * @param text the text to prefix the number. Can be <CODE>null</CODE> or empty
+     * @param firstPage the first logical page number
+     */    
+    public void addPageLabel(int page, int numberStyle, String text, int firstPage) {
+        if (page < 1 || firstPage < 1)
+            throw new IllegalArgumentException("In a page label the page numbers must be greater or equal to 1.");
+        PdfName pdfName = null;
+        if (numberStyle >= 0 && numberStyle < numberingStyle.length)
+            pdfName = numberingStyle[numberStyle];
+        Integer iPage = new Integer(page);
+        Object obj = new Object[]{iPage, pdfName, text, new Integer(firstPage)};
+        map.put(iPage, obj);
+    }
+
+    /** Adds or replaces a page label. The first logical page has the default
+     * of 1.
+     * @param page the real page to start the numbering. First page is 1
+     * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+     * @param text the text to prefix the number. Can be <CODE>null</CODE> or empty
+     */    
+    public void addPageLabel(int page, int numberStyle, String text) {
+        addPageLabel(page, numberStyle, text, 1);
+    }
+    
+    /** Adds or replaces a page label. There is no text prefix and the first
+     * logical page has the default of 1.
+     * @param page the real page to start the numbering. First page is 1
+     * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+     */    
+    public void addPageLabel(int page, int numberStyle) {
+        addPageLabel(page, numberStyle, null, 1);
+    }
+    
+    /** Removes a page label. The first page label can not be removed, only changed.
+     * @param page the real page to remove
+     */    
+    public void removePageLabel(int page) {
+        if (page <= 1)
+            return;
+        map.remove(new Integer(page));
+    }
+
+    /** Gets the page label dictionary to insert into the document.
+     * @return the page label dictionary
+     */    
+    PdfDictionary getDictionary() {
+        PdfDictionary dic = new PdfDictionary();
+        PdfArray array = new PdfArray();
+        for (Iterator it = map.values().iterator(); it.hasNext();) {
+            Object obj[] = (Object[])it.next();
+            PdfDictionary subDic = new PdfDictionary();
+            PdfName pName = (PdfName)obj[1];
+            if (pName != null)
+                subDic.put(PdfName.S, pName);
+            String text = (String)obj[2];
+            if (text != null)
+                subDic.put(PdfName.P, new PdfString(text, PdfObject.TEXT_UNICODE));
+            int st = ((Integer)obj[3]).intValue();
+            if (st != 1)
+                subDic.put(PdfName.ST, new PdfNumber(st));
+            array.add(new PdfNumber(((Integer)obj[0]).intValue() - 1));
+            array.add(subDic);
+        }
+        dic.put(PdfName.NUMS, array);
+        return dic;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPages.java b/LibrarySource/com/lowagie/text/pdf/PdfPages.java
new file mode 100644
index 0000000..ccb57e9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPages.java
@@ -0,0 +1,206 @@
+/*
+ * $Id: PdfPages.java,v 1.33 2003/05/02 09:01:26 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * <CODE>PdfPages</CODE> is the PDF Pages-object.
+ * <P>
+ * The Pages of a document are accessible through a tree of nodes known as the Pages tree.
+ * This tree defines the ordering of the pages in the document.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.3 (page 71-73)
+ *
+ * @see		PdfPageElement
+ * @see		PdfPage
+ */
+
+public class PdfPages {
+    
+    private ArrayList pages = new ArrayList();
+    private ArrayList parents = new ArrayList();
+    private int leafSize = 10;
+    private PdfWriter writer;
+    private PdfIndirectReference topParent;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfPages</CODE>-object.
+ */
+    
+    PdfPages(PdfWriter writer) {
+        this.writer = writer;
+    }
+    
+    void addPage(PdfDictionary page) {
+        try {
+            if ((pages.size() % leafSize) == 0)
+                parents.add(writer.getPdfIndirectReference());
+            PdfIndirectReference parent = (PdfIndirectReference)parents.get(parents.size() - 1);
+            page.put(PdfName.PARENT, parent);
+            PdfIndirectReference current = writer.getCurrentPage();
+            writer.addToBody(page, current);
+            pages.add(current);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    PdfIndirectReference addPageRef(PdfIndirectReference pageRef) {
+        try {
+            if ((pages.size() % leafSize) == 0)
+                parents.add(writer.getPdfIndirectReference());
+            pages.add(pageRef);
+            return (PdfIndirectReference)parents.get(parents.size() - 1);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    // returns the top parent to include in the catalog
+    PdfIndirectReference writePageTree() throws IOException {
+        if (pages.size() == 0)
+            throw new IOException("The document has no pages.");
+        int leaf = 1;
+        ArrayList tParents = parents;
+        ArrayList tPages = pages;
+        ArrayList nextParents = new ArrayList();
+        while (true) {
+            leaf *= leafSize;
+            int stdCount = leafSize;
+            int rightCount = tPages.size() % leafSize;
+            if (rightCount == 0)
+                rightCount = leafSize;
+            for (int p = 0; p < tParents.size(); ++p) {
+                int count;
+                int thisLeaf = leaf;
+                if (p == tParents.size() - 1) {
+                    count = rightCount;
+                    thisLeaf = pages.size() % leaf;
+                    if (thisLeaf == 0)
+                        thisLeaf = leaf;
+                }
+                else
+                    count = stdCount;
+                PdfDictionary top = new PdfDictionary(PdfName.PAGES);
+                top.put(PdfName.COUNT, new PdfNumber(thisLeaf));
+                PdfArray kids = new PdfArray();
+                ArrayList internal = kids.getArrayList();
+                internal.addAll(tPages.subList(p * stdCount, p * stdCount + count));
+                top.put(PdfName.KIDS, kids);
+                if (tParents.size() > 1) {
+                    if ((p % leafSize) == 0)
+                        nextParents.add(writer.getPdfIndirectReference());
+                    top.put(PdfName.PARENT, (PdfIndirectReference)nextParents.get(p / leafSize));
+                }
+                writer.addToBody(top, (PdfIndirectReference)tParents.get(p));
+            }
+            if (tParents.size() == 1) {
+                topParent = (PdfIndirectReference)tParents.get(0);
+                return topParent;
+            }
+            tPages = tParents;
+            tParents = nextParents;
+            nextParents = new ArrayList();
+        }
+    }
+    
+    PdfIndirectReference getTopParent() {
+        return topParent;
+    }
+    
+    void setLinearMode(PdfIndirectReference topParent) {
+        if (parents.size() > 1)
+            throw new RuntimeException("Linear page mode can only be called with a single parent.");
+        if (topParent != null) {
+            this.topParent = topParent;
+            parents.clear();
+            parents.add(topParent);
+        }
+        leafSize = 10000000;
+    }
+
+    void addPage(PdfIndirectReference page) {
+        pages.add(page);
+    }
+
+    int reorderPages(int order[]) throws DocumentException {
+        if (order == null)
+            return pages.size();
+        if (parents.size() > 1)
+            throw new DocumentException("Page reordering requires a single parent in the page tree. Call PdfWriter.setLinearMode() after open.");
+        if (order.length != pages.size())
+            throw new DocumentException("Page reordering requires an array with the same size as the number of pages.");
+        int max = pages.size();
+        boolean temp[] = new boolean[max];
+        for (int k = 0; k < max; ++k) {
+            int p = order[k];
+            if (p < 1 || p > max)
+                throw new DocumentException("Page reordering requires pages between 1 and " + max + ". Found " + p + ".");
+            if (temp[p - 1])
+                throw new DocumentException("Page reordering requires no page repetition. Page " + p + " is repeated.");
+            temp[p - 1] = true;
+        }
+        Object copy[] = pages.toArray();
+        for (int k = 0; k < max; ++k) {
+            pages.set(k, copy[order[k] - 1]);
+        }
+        return max;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPattern.java b/LibrarySource/com/lowagie/text/pdf/PdfPattern.java
new file mode 100644
index 0000000..488bfde
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPattern.java
@@ -0,0 +1,84 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * A <CODE>PdfPattern</CODE> defines a ColorSpace
+ *
+ * @see		PdfStream
+ */
+
+public class PdfPattern extends PdfStream {
+    
+    PdfPattern(PdfPatternPainter painter) {
+        super();
+        PdfNumber one = new PdfNumber(1);
+        PdfArray matrix = painter.getMatrix();
+        if ( matrix != null ) {
+            put(PdfName.MATRIX, matrix);
+        }
+        put(PdfName.TYPE, PdfName.PATTERN);
+        put(PdfName.BBOX, new PdfRectangle(painter.getBoundingBox()));
+        put(PdfName.RESOURCES, painter.getResources());
+        put(PdfName.TILINGTYPE, one);
+        put(PdfName.PATTERNTYPE, one);
+        if (painter.isStencil())
+            put(PdfName.PAINTTYPE, new PdfNumber(2));
+        else
+            put(PdfName.PAINTTYPE, one);
+        put(PdfName.XSTEP, new PdfNumber(painter.getXStep()));
+        put(PdfName.YSTEP, new PdfNumber(painter.getYStep()));
+        bytes = painter.toPdf(null);
+        put(PdfName.LENGTH, new PdfNumber(bytes.length));
+        try {
+            flateCompress();
+        } catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPatternPainter.java b/LibrarySource/com/lowagie/text/pdf/PdfPatternPainter.java
new file mode 100644
index 0000000..7221eac
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPatternPainter.java
@@ -0,0 +1,391 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Image;
+import com.lowagie.text.Rectangle;
+import headless.awt.Color;
+
+/**
+ * Implements the pattern.
+ */
+
+public class PdfPatternPainter extends PdfTemplate {
+    
+    protected float xstep, ystep;
+    protected boolean stencil = false;
+    protected Color defaultColor;
+    
+    /**
+     *Creates a <CODE>PdfPattern</CODE>.
+     */
+    
+    private PdfPatternPainter() {
+        super(null);
+        type = TYPE_PATTERN;
+    }
+    
+    /**
+     * Creates new PdfPattern
+     *
+     * @param wr the <CODE>PdfWriter</CODE>
+     */
+    
+    PdfPatternPainter(PdfWriter wr) {
+        super(wr);
+        type = TYPE_PATTERN;
+    }
+    
+    PdfPatternPainter(PdfWriter wr, Color defaultColor) {
+        this(wr);
+        stencil = true;
+        if (defaultColor == null)
+            this.defaultColor = Color.gray;
+        else
+            this.defaultColor = defaultColor;
+    }
+    
+    /**
+     * Sets the horizontal interval of this pattern.
+     *
+     * @param xstep the xstep in horizontal painting
+     */
+    
+    public void setXStep(float xstep) {
+        this.xstep = xstep;
+    }
+    
+    /**
+     * Sets the vertical interval of this pattern.
+     *
+     * @param ystep in vertical painting
+     */
+    
+    public void setYStep(float ystep) {
+        this.ystep = ystep;
+    }
+    
+    /**
+     * Returns the horizontal interval when repeating the pattern.
+     * @return a value
+     */
+    public float getXStep() {
+        return this.xstep;
+    }
+    
+    /**
+     * Returns the vertical interval when repeating the pattern.
+     * @return a value
+     */
+    public float getYStep() {
+        return this.ystep;
+    }
+    
+    /**
+     * Tells you if this pattern is colored/uncolored (stencil = uncolored, you need to set a default color).
+     * @return true if the pattern is an uncolored tiling pattern (stencil).
+     */
+    public boolean isStencil() {
+        return stencil;
+    }
+    
+    /**
+     * Sets the transformation matrix for the pattern.
+     * @param a
+     * @param b
+     * @param c
+     * @param d
+     * @param e
+     * @param f
+     */
+    public void setPatternMatrix(float a, float b, float c, float d, float e, float f) {
+        setMatrix(a, b, c, d, e, f);
+    }
+    /**
+     * Gets the stream representing this pattern
+     *
+     * @return the stream representing this pattern
+     */
+    
+    PdfPattern getPattern() {
+        return new PdfPattern(this);
+    }
+    
+    /**
+     * Gets a duplicate of this <CODE>PdfPatternPainter</CODE>. All
+     * the members are copied by reference but the buffer stays different.
+     * @return a copy of this <CODE>PdfPatternPainter</CODE>
+     */
+    
+    public PdfContentByte getDuplicate() {
+        PdfPatternPainter tpl = new PdfPatternPainter();
+        tpl.writer = writer;
+        tpl.pdf = pdf;
+        tpl.thisReference = thisReference;
+        tpl.pageResources = pageResources;
+        tpl.bBox = new Rectangle(bBox);
+        tpl.xstep = xstep;
+        tpl.ystep = ystep;
+        tpl.matrix = matrix;
+        tpl.stencil = stencil;
+        tpl.defaultColor = defaultColor;
+        return tpl;
+    }
+    
+    /**
+     * Returns the default color of the pattern.
+     * @return a Color
+     */
+    public Color getDefaultColor() {
+        return defaultColor;
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setGrayFill(float)
+     */
+    public void setGrayFill(float gray) {
+        checkNoColor();
+        super.setGrayFill(gray);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetGrayFill()
+     */
+    public void resetGrayFill() {
+        checkNoColor();
+        super.resetGrayFill();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setGrayStroke(float)
+     */
+    public void setGrayStroke(float gray) {
+        checkNoColor();
+        super.setGrayStroke(gray);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetGrayStroke()
+     */
+    public void resetGrayStroke() {
+        checkNoColor();
+        super.resetGrayStroke();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorFillF(float, float, float)
+     */
+    public void setRGBColorFillF(float red, float green, float blue) {
+        checkNoColor();
+        super.setRGBColorFillF(red, green, blue);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetRGBColorFill()
+     */
+    public void resetRGBColorFill() {
+        checkNoColor();
+        super.resetRGBColorFill();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorStrokeF(float, float, float)
+     */
+    public void setRGBColorStrokeF(float red, float green, float blue) {
+        checkNoColor();
+        super.setRGBColorStrokeF(red, green, blue);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetRGBColorStroke()
+     */
+    public void resetRGBColorStroke() {
+        checkNoColor();
+        super.resetRGBColorStroke();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorFillF(float, float, float, float)
+     */
+    public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
+        checkNoColor();
+        super.setCMYKColorFillF(cyan, magenta, yellow, black);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetCMYKColorFill()
+     */
+    public void resetCMYKColorFill() {
+        checkNoColor();
+        super.resetCMYKColorFill();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorStrokeF(float, float, float, float)
+     */
+    public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
+        checkNoColor();
+        super.setCMYKColorStrokeF(cyan, magenta, yellow, black);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#resetCMYKColorStroke()
+     */
+    public void resetCMYKColorStroke() {
+        checkNoColor();
+        super.resetCMYKColorStroke();
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#addImage(com.lowagie.text.Image, float, float, float, float, float, float)
+     */
+    public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+        if (stencil && !image.isMask())
+            checkNoColor();
+        super.addImage(image, a, b, c, d, e, f);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorFill(int, int, int, int)
+     */
+    public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
+        checkNoColor();
+        super.setCMYKColorFill(cyan, magenta, yellow, black);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorStroke(int, int, int, int)
+     */
+    public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
+        checkNoColor();
+        super.setCMYKColorStroke(cyan, magenta, yellow, black);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorFill(int, int, int)
+     */
+    public void setRGBColorFill(int red, int green, int blue) {
+        checkNoColor();
+        super.setRGBColorFill(red, green, blue);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorStroke(int, int, int)
+     */
+    public void setRGBColorStroke(int red, int green, int blue) {
+        checkNoColor();
+        super.setRGBColorStroke(red, green, blue);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setColorStroke(java.awt.Color)
+     */
+    public void setColorStroke(Color color) {
+        checkNoColor();
+        super.setColorStroke(color);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setColorFill(java.awt.Color)
+     */
+    public void setColorFill(Color color) {
+        checkNoColor();
+        super.setColorFill(color);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setColorFill(com.lowagie.text.pdf.PdfSpotColor, float)
+     */
+    public void setColorFill(PdfSpotColor sp, float tint) {
+        checkNoColor();
+        super.setColorFill(sp, tint);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setColorStroke(com.lowagie.text.pdf.PdfSpotColor, float)
+     */
+    public void setColorStroke(PdfSpotColor sp, float tint) {
+        checkNoColor();
+        super.setColorStroke(sp, tint);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setPatternFill(com.lowagie.text.pdf.PdfPatternPainter)
+     */
+    public void setPatternFill(PdfPatternPainter p) {
+        checkNoColor();
+        super.setPatternFill(p);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setPatternFill(com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
+     */
+    public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
+        checkNoColor();
+        super.setPatternFill(p, color, tint);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setPatternStroke(com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
+     */
+    public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
+        checkNoColor();
+        super.setPatternStroke(p, color, tint);
+    }
+    
+    /**
+     * @see com.lowagie.text.pdf.PdfContentByte#setPatternStroke(com.lowagie.text.pdf.PdfPatternPainter)
+     */
+    public void setPatternStroke(PdfPatternPainter p) {
+        checkNoColor();
+        super.setPatternStroke(p);
+    }
+    
+    void checkNoColor() {
+        if (stencil)
+            throw new RuntimeException("Colors are not allowed in uncolored tile patterns.");
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfPrinterGraphics2D.java b/LibrarySource/com/lowagie/text/pdf/PdfPrinterGraphics2D.java
new file mode 100644
index 0000000..4bc4624
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfPrinterGraphics2D.java
@@ -0,0 +1,73 @@
+/*
+ * $Id: PdfPrinterGraphics2D.java,v 1.3 2005/02/17 09:20:53 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2004 Paulo Soares and Alexandru Carstoiu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.print.PrinterGraphics;
+import headless.awt.print.PrinterJob;
+
+/**
+ * This is an extension class for the sole purpose of implementing the
+ * {@link java.awt.print.PrinterGraphics PrinterGraphics} interface.
+ */
+public class PdfPrinterGraphics2D extends PdfGraphics2D implements PrinterGraphics
+{
+	private PrinterJob printerJob;
+	
+	public PdfPrinterGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper,
+			boolean onlyShapes, boolean convertImagesToJPEG, float quality, PrinterJob printerJob)	{
+		super(cb, width, height, fontMapper, onlyShapes, convertImagesToJPEG, quality);
+		this.printerJob = printerJob;
+	}
+
+	public PrinterJob getPrinterJob()	{
+		return printerJob;
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfReader.java b/LibrarySource/com/lowagie/text/pdf/PdfReader.java
new file mode 100644
index 0000000..442880c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfReader.java
@@ -0,0 +1,3052 @@
+/*
+ * $Id: PdfReader.java,v 1.31 2003/05/02 09:01:26 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ * Mesquite specific changes/deletions copyright 2005 Peter E. Midford
+ * peteremidford at yahoo.com.  Mesquite itself is copyright 1997-2005 by W. and D.
+ * Maddison and licensed under the LGPL.
+ * 
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.zip.InflaterInputStream;
+import java.util.Arrays;
+import java.util.Collections;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.StringCompare;
+import com.lowagie.text.ExceptionConverter;
+
+/** Reads a PDF document.
+ * @author Paulo Soares (psoares at consiste.pt)
+ * @author Kazuya Ujihara
+ */
+public class PdfReader {
+    
+    static final PdfName pageInhCandidates[] = {
+        PdfName.MEDIABOX, PdfName.ROTATE, PdfName.RESOURCES, PdfName.CROPBOX
+    };
+
+    static final PdfName vpnames[] = {PdfName.HIDETOOLBAR, PdfName.HIDEMENUBAR,
+        PdfName.HIDEWINDOWUI, PdfName.FITWINDOW, PdfName.CENTERWINDOW, PdfName.DISPLAYDOCTITLE};
+    static final int vpints[] = {PdfWriter.HideToolbar, PdfWriter.HideMenubar,
+        PdfWriter.HideWindowUI, PdfWriter.FitWindow, PdfWriter.CenterWindow, PdfWriter.DisplayDocTitle};
+
+    static final byte endstream[] = PdfEncodings.convertToBytes("endstream", null);
+    static final byte endobj[] = PdfEncodings.convertToBytes("endobj", null);
+    protected PRTokeniser tokens;
+    // Each xref pair is a position
+    // type 0 -> -1, 0
+    // type 1 -> offset, 0
+    // type 2 -> index, obj num
+    protected int xref[];
+    protected HashMap objStmMark;
+    protected IntHashtable objStmToOffset;
+    protected boolean newXrefType;
+    private ArrayList xrefObj;
+    PdfDictionary rootPages;
+    protected PdfDictionary trailer;
+    //protected ArrayList pages;
+    protected PdfDictionary catalog;
+    protected PageRefs pageRefs;
+   // protected PRAcroForm acroForm = null;   //removed for Mesquite support 25 September 2005
+    protected boolean acroFormParsed = false;
+    protected ArrayList pageInh;
+    protected boolean encrypted = false;
+    protected boolean rebuilt = false;
+    protected int freeXref;
+    protected boolean tampered = false;
+    protected int lastXref;
+    protected int eofPos;
+    protected char pdfVersion;
+    protected PdfEncryption decrypt;
+    protected byte password[] = null; //added by ujihara for decryption
+    protected ArrayList strings = new ArrayList();
+    protected boolean sharedStreams = true;
+    protected boolean consolidateNamedDestinations = false;
+    protected int rValue;
+    protected int pValue;
+    private int objNum;
+    private int objGen;
+    private boolean visited[];
+    private IntHashtable newHits;
+    private int fileLength;
+    private boolean hybridXref;
+    private int lastXrefPartial = -1;
+    private boolean partial;
+    
+    /**
+     * Holds value of property appendable.
+     */
+    private boolean appendable;
+    
+    protected PdfReader() {
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param filename the file name of the document
+     * @throws IOException on error
+     */
+    public PdfReader(String filename) throws IOException {
+        this(filename, null);
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param filename the file name of the document
+     * @param ownerPassword the password to read the document
+     * @throws IOException on error
+     */    
+    public PdfReader(String filename, byte ownerPassword[]) throws IOException {
+        password = ownerPassword;
+        tokens = new PRTokeniser(filename);
+        readPdf();
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param pdfIn the byte array with the document
+     * @throws IOException on error
+     */
+    public PdfReader(byte pdfIn[]) throws IOException {
+        this(pdfIn, null);
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param pdfIn the byte array with the document
+     * @param ownerPassword the password to read the document
+     * @throws IOException on error
+     */
+    public PdfReader(byte pdfIn[], byte ownerPassword[]) throws IOException {
+        password = ownerPassword;
+        tokens = new PRTokeniser(pdfIn);
+        readPdf();
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param url the URL of the document
+     * @throws IOException on error
+     */
+    public PdfReader(URL url) throws IOException {
+        this(url, null);
+    }
+    
+    /** Reads and parses a PDF document.
+     * @param url the URL of the document
+     * @param ownerPassword the password to read the document
+     * @throws IOException on error
+     */
+    public PdfReader(URL url, byte ownerPassword[]) throws IOException {
+        password = ownerPassword;
+        tokens = new PRTokeniser(new RandomAccessFileOrArray(url));
+        readPdf();
+    }
+    
+    /**
+     * Reads and parses a PDF document.
+     * @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
+     * end but is not closed
+     * @param ownerPassword the password to read the document
+     * @throws IOException on error
+     */
+    public PdfReader(InputStream is, byte ownerPassword[]) throws IOException {
+        password = ownerPassword;
+        tokens = new PRTokeniser(new RandomAccessFileOrArray(is));
+        readPdf();
+    }
+    
+    /**
+     * Reads and parses a PDF document.
+     * @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
+     * end but is not closed
+     * @throws IOException on error
+     */
+    public PdfReader(InputStream is) throws IOException {
+        this(is, null);
+    }
+    
+    /**
+     * Reads and parses a pdf document. Contrary to the other constructors only the xref is read
+     * into memory. The reader is said to be working in "partial" mode as only parts of the pdf
+     * are read as needed. The pdf is left open but may be closed at any time with
+     * <CODE>PdfReader.close()</CODE>, reopen is automatic.
+     * @param raf the document location
+     * @param ownerPassword the password or <CODE>null</CODE> for no password
+     * @throws IOException on error
+     */    
+    public PdfReader(RandomAccessFileOrArray raf, byte ownerPassword[]) throws IOException {
+        password = ownerPassword;
+        partial = true;
+        tokens = new PRTokeniser(raf);
+        readPdfPartial();
+    }
+    
+    /** Creates an independent duplicate.
+     * @param reader the <CODE>PdfReader</CODE> to duplicate
+     */    
+    public PdfReader(PdfReader reader) {
+        this.appendable = reader.appendable;
+        this.consolidateNamedDestinations = reader.consolidateNamedDestinations;
+        this.encrypted = reader.encrypted;
+        this.rebuilt = reader.rebuilt;
+        this.sharedStreams = reader.sharedStreams;
+        this.tampered = reader.tampered;
+        this.password = reader.password;
+        this.pdfVersion = reader.pdfVersion;
+        this.eofPos = reader.eofPos;
+        this.freeXref = reader.freeXref;
+        this.lastXref = reader.lastXref;
+        this.tokens = new PRTokeniser(reader.tokens.getSafeFile());
+        if (reader.decrypt != null)
+            this.decrypt = new PdfEncryption(reader.decrypt);
+        this.pValue = reader.pValue;
+        this.rValue = reader.rValue;
+        this.xrefObj = new ArrayList(reader.xrefObj);
+        for (int k = 0; k < reader.xrefObj.size(); ++k) {
+            this.xrefObj.set(k, duplicatePdfObject((PdfObject)reader.xrefObj.get(k), this));
+        }
+        this.pageRefs = new PageRefs(reader.pageRefs, this);
+        this.trailer = (PdfDictionary)duplicatePdfObject(reader.trailer, this);
+        this.catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
+        this.rootPages = (PdfDictionary)getPdfObject(catalog.get(PdfName.PAGES));
+        this.fileLength = reader.fileLength;
+        this.partial = reader.partial;
+        this.hybridXref = reader.hybridXref;
+        this.objStmToOffset = reader.objStmToOffset;
+        this.xref = reader.xref;
+    }
+    
+    /** Gets a new file instance of the original PDF
+     * document.
+     * @return a new file instance of the original PDF document
+     */
+    public RandomAccessFileOrArray getSafeFile() {
+        return tokens.getSafeFile();
+    }
+    
+    protected PdfReaderInstance getPdfReaderInstance(PdfWriter writer) {
+        return new PdfReaderInstance(this, writer);
+    }
+    
+    /** Gets the number of pages in the document.
+     * @return the number of pages in the document
+     */
+    public int getNumberOfPages() {
+        return pageRefs.size();
+    }
+    
+    /** Returns the document's catalog. This dictionary is not a copy,
+     * any changes will be reflected in the catalog.
+     * @return the document's catalog
+     */
+    public PdfDictionary getCatalog() {
+        return catalog;
+    }
+    
+    /** Returns the document's acroform, if it has one.
+     * @return the document's acroform
+     * removed for Mesquite support 25 September 2005 P. E. Midford
+     */
+//    public PRAcroForm getAcroForm() {
+//        if (!acroFormParsed) {
+//            acroFormParsed = true;
+//            PdfObject form = catalog.get(PdfName.ACROFORM);
+//            if (form != null) {
+//                try {
+//                    acroForm = new PRAcroForm(this);
+//                    acroForm.readAcroForm((PdfDictionary)getPdfObject(form));
+//                }
+//                catch (Exception e) {
+//                    acroForm = null;
+//                }
+//            }
+//       }
+//        return acroForm;
+//    }
+    /**
+     * Gets the page rotation. This value can be 0, 90, 180 or 270.
+     * @param index the page number. The first page is 1
+     * @return the page rotation
+     */
+    public int getPageRotation(int index) {
+        return getPageRotation(pageRefs.getPageNRelease(index));
+    }
+    
+    int getPageRotation(PdfDictionary page) {
+        PdfNumber rotate = (PdfNumber)getPdfObject(page.get(PdfName.ROTATE));
+        if (rotate == null)
+            return 0;
+        else {
+            int n = rotate.intValue();
+            n %= 360;
+            return n < 0 ? n + 360 : n;
+        }
+    }
+    /** Gets the page size, taking rotation into account. This
+     * is a <CODE>Rectangle</CODE> with the value of the /MediaBox and the /Rotate key.
+     * @param index the page number. The first page is 1
+     * @return a <CODE>Rectangle</CODE>
+     */
+    public Rectangle getPageSizeWithRotation(int index) {
+        return getPageSizeWithRotation(pageRefs.getPageNRelease(index));
+    }
+    
+    /**
+     * Gets the rotated page from a page dictionary.
+     * @param page the page dictionary
+     * @return the rotated page
+     */    
+    public Rectangle getPageSizeWithRotation(PdfDictionary page) {
+        Rectangle rect = getPageSize(page);
+        int rotation = getPageRotation(page);
+        while (rotation > 0) {
+            rect = rect.rotate();
+            rotation -= 90;
+        }
+        return rect;
+    }
+    
+    /** Gets the page size without taking rotation into account. This
+     * is the value of the /MediaBox key.
+     * @param index the page number. The first page is 1
+     * @return the page size
+     */
+    public Rectangle getPageSize(int index) {
+        return getPageSize(pageRefs.getPageNRelease(index));
+    }
+    
+    /**
+     * Gets the page from a page dictionary
+     * @param page the page dictionary
+     * @return the page
+     */    
+    public Rectangle getPageSize(PdfDictionary page) {
+        PdfArray mediaBox = (PdfArray)getPdfObject(page.get(PdfName.MEDIABOX));
+        return getNormalizedRectangle(mediaBox);
+    }
+    
+    /** Gets the crop box without taking rotation into account. This
+     * is the value of the /CropBox key. The crop box is the part
+     * of the document to be displayed or printed. It usually is the same
+     * as the media box but may be smaller. If the page doesn't have a crop
+     * box the page size will be returned.
+     * @param index the page number. The first page is 1
+     * @return the crop box
+     */
+    public Rectangle getCropBox(int index) {
+        PdfDictionary page = pageRefs.getPageNRelease(index);
+        PdfArray cropBox = (PdfArray)getPdfObjectRelease(page.get(PdfName.CROPBOX));
+        if (cropBox == null)
+            return getPageSize(page);
+        return getNormalizedRectangle(cropBox);
+    }
+    
+    /** Gets the box size. Allowed names are: "crop", "trim", "art", "bleed" and "media".
+     * @param index the page number. The first page is 1
+     * @param boxName the box name
+     * @return the box rectangle or null
+     */
+    public Rectangle getBoxSize(int index, String boxName) {
+        PdfDictionary page = pageRefs.getPageNRelease(index);
+        PdfArray box = null;
+        if (boxName.equals("trim"))
+            box = (PdfArray)getPdfObjectRelease(page.get(PdfName.TRIMBOX));
+        else if (boxName.equals("art"))
+            box = (PdfArray)getPdfObjectRelease(page.get(PdfName.ARTBOX));
+        else if (boxName.equals("bleed"))
+            box = (PdfArray)getPdfObjectRelease(page.get(PdfName.BLEEDBOX));
+        else if (boxName.equals("crop"))
+            box = (PdfArray)getPdfObjectRelease(page.get(PdfName.CROPBOX));
+        else if (boxName.equals("media"))
+            box = (PdfArray)getPdfObjectRelease(page.get(PdfName.MEDIABOX));
+        if (box == null)
+            return null;
+        return getNormalizedRectangle(box);
+    }
+    
+    /** Returns the content of the document information dictionary as a <CODE>HashMap</CODE>
+     * of <CODE>String</CODE>.
+     * @return content of the document information dictionary
+     */
+    public HashMap getInfo() {
+        HashMap map = new HashMap();
+        PdfDictionary info = (PdfDictionary)getPdfObject(trailer.get(PdfName.INFO));
+        if (info == null)
+            return map;
+        for (Iterator it = info.getKeys().iterator(); it.hasNext();) {
+            PdfName key = (PdfName)it.next();
+            PdfObject obj = (PdfObject)getPdfObject(info.get(key));
+            if (obj == null)
+                continue;
+            String value = obj.toString();
+            switch (obj.type()) {
+                case PdfObject.STRING: {
+                    value = ((PdfString)obj).toUnicodeString();
+                    break;
+                }
+                case PdfObject.NAME: {
+                    value = PdfName.decodeName(value);
+                    break;
+                }
+            }
+            map.put(PdfName.decodeName(key.toString()), value);
+        }
+        return map;
+    }
+    
+    /** Normalizes a <CODE>Rectangle</CODE> so that llx and lly are smaller than urx and ury.
+     * @param box the original rectangle
+     * @return a normalized <CODE>Rectangle</CODE>
+     */    
+    public static Rectangle getNormalizedRectangle(PdfArray box) {
+        ArrayList rect = box.getArrayList();
+        float llx = ((PdfNumber)rect.get(0)).floatValue();
+        float lly = ((PdfNumber)rect.get(1)).floatValue();
+        float urx = ((PdfNumber)rect.get(2)).floatValue();
+        float ury = ((PdfNumber)rect.get(3)).floatValue();
+        return new Rectangle(Math.min(llx, urx), Math.min(lly, ury),
+        Math.max(llx, urx), Math.max(lly, ury));
+    }
+    
+    protected void readPdf() throws IOException {
+        try {
+            fileLength = tokens.getFile().length();
+            pdfVersion = tokens.checkPdfHeader();
+            try {
+                readXref();
+            }
+            catch (Exception e) {
+                try {
+                    rebuilt = true;
+                    rebuildXref();
+                    lastXref = -1;
+                }
+                catch (Exception ne) {
+                    throw new IOException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
+                }
+            }
+            try {
+                readDocObj();
+            }
+            catch (IOException ne) {
+                if (rebuilt)
+                    throw ne;
+                rebuilt = true;
+                encrypted = false;
+                rebuildXref();
+                lastXref = -1;
+                readDocObj();
+            }
+            
+            strings.clear();
+            readPages();
+            eliminateSharedStreams();
+            removeUnusedObjects();
+        }
+        finally {
+            try {
+                tokens.close();
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }
+        }
+    }
+    
+    protected void readPdfPartial() throws IOException {
+        try {
+            fileLength = tokens.getFile().length();
+            pdfVersion = tokens.checkPdfHeader();
+            try {
+                readXref();
+            }
+            catch (Exception e) {
+                try {
+                    rebuilt = true;
+                    rebuildXref();
+                    lastXref = -1;
+                }
+                catch (Exception ne) {
+                    throw new IOException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
+                }
+            }
+            readDocObjPartial();
+            readPages();
+        }
+        catch (IOException e) {
+            try{tokens.close();}catch(Exception ee){}
+            throw e;
+        }
+    }
+    
+    private boolean equalsArray(byte ar1[], byte ar2[], int size) {
+        for (int k = 0; k < size; ++k) {
+            if (ar1[k] != ar2[k])
+                return false;
+        }
+        return true;
+    }
+    
+    /**
+     */
+    private void readDecryptedDocObj() throws IOException {
+        if (encrypted)
+            return;
+        PdfObject encDic = trailer.get(PdfName.ENCRYPT);
+        if (encDic == null || encDic.toString().equals("null"))
+            return;
+        encrypted = true;
+        PdfDictionary enc = (PdfDictionary)getPdfObject(encDic);
+        
+        String s;
+        PdfObject o;
+        
+        PdfArray documentIDs = (PdfArray)getPdfObject(trailer.get(PdfName.ID));
+        byte documentID[] = null;
+        if (documentIDs != null) {
+            o = (PdfObject)documentIDs.getArrayList().get(0);
+            s = o.toString();
+            documentID = com.lowagie.text.DocWriter.getISOBytes(s);
+        }
+        
+        s = enc.get(PdfName.U).toString();
+        byte uValue[] = com.lowagie.text.DocWriter.getISOBytes(s);
+        s = enc.get(PdfName.O).toString();
+        byte oValue[] = com.lowagie.text.DocWriter.getISOBytes(s);
+        
+        o = enc.get(PdfName.R);
+        if (!o.isNumber()) throw new IOException("Illegal R value.");
+        rValue = ((PdfNumber)o).intValue();
+        if (rValue != 2 && rValue != 3) throw new IOException("Unknown encryption type (" + rValue + ")");
+        
+        o = enc.get(PdfName.P);
+        if (!o.isNumber()) throw new IOException("Illegal P value.");
+        pValue = ((PdfNumber)o).intValue();
+        
+        decrypt = new PdfEncryption();
+        
+        //check by user password
+        decrypt.setupByUserPassword(documentID, password, oValue, pValue, rValue == 3);
+        if (!equalsArray(uValue, decrypt.userKey, rValue == 3 ? 16 : 32)) {
+            //check by owner password
+            decrypt.setupByOwnerPassword(documentID, password, uValue, oValue, pValue, rValue == 3);
+            if (!equalsArray(uValue, decrypt.userKey, rValue == 3 ? 16 : 32)) {
+                throw new IOException("Bad user password");
+            }
+        }
+        for (int k = 0; k < strings.size(); ++k) {
+            PdfString str = (PdfString)strings.get(k);
+            str.decrypt(this);
+        }
+        if (encDic.isIndirect())
+            xrefObj.set(((PRIndirectReference)encDic).getNumber(), null);
+    }
+    
+    public static PdfObject getPdfObjectRelease(PdfObject obj) {
+        PdfObject obj2 = getPdfObject(obj);
+        releaseLastXrefPartial(obj);
+        return obj2;
+    }
+
+    
+    /**
+     * Reads a <CODE>PdfObject</CODE> resolving an indirect reference
+     * if needed.
+     * @param obj the <CODE>PdfObject</CODE> to read
+     * @return the resolved <CODE>PdfObject</CODE>
+     */    
+    public static PdfObject getPdfObject(PdfObject obj) {
+        if (obj == null)
+            return null;
+        if (!obj.isIndirect())
+            return obj;
+        try {
+            PRIndirectReference ref = (PRIndirectReference)obj;
+            int idx = ref.getNumber();
+            boolean appendable = ref.getReader().appendable;
+            obj = ref.getReader().getPdfObject(idx);
+            if (obj == null) {
+                if (appendable) {
+                    obj = new PdfNull();
+                    obj.setIndRef(ref);
+                    return obj;
+                }
+                else
+                    return PdfNull.PDFNULL;
+            }
+            else {
+                if (appendable) {
+                    switch (obj.type()) {
+                        case PdfObject.NULL:
+                            obj = new PdfNull();
+                            break;
+                        case PdfObject.BOOLEAN:
+                            obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
+                            break;
+                        case PdfObject.NAME:
+                            obj = new PdfName(obj.getBytes());
+                            break;
+                    }
+                    obj.setIndRef(ref);
+                }
+                return obj;
+            }
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /**
+     * Reads a <CODE>PdfObject</CODE> resolving an indirect reference
+     * if needed. If the reader was opened in partial mode the object will be released
+     * to save memory.
+     * @param obj the <CODE>PdfObject</CODE> to read
+     * @param parent
+     * @return
+     */    
+    public static PdfObject getPdfObjectRelease(PdfObject obj, PdfObject parent) {
+        PdfObject obj2 = getPdfObject(obj, parent);
+        releaseLastXrefPartial(obj);
+        return obj2;
+    }
+    
+    public static PdfObject getPdfObject(PdfObject obj, PdfObject parent) {
+        if (obj == null)
+            return null;
+        if (!obj.isIndirect()) {
+            PRIndirectReference ref = null;
+            if (parent != null && (ref = parent.getIndRef()) != null && ref.getReader().isAppendable()) {
+                switch (obj.type()) {
+                    case PdfObject.NULL:
+                        obj = new PdfNull();
+                        break;
+                    case PdfObject.BOOLEAN:
+                        obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
+                        break;
+                    case PdfObject.NAME:
+                        obj = new PdfName(obj.getBytes());
+                        break;
+                }
+                obj.setIndRef(ref);
+            }
+            return obj;
+        }
+        return getPdfObject(obj);
+    }
+    
+    public PdfObject getPdfObjectRelease(int idx) {
+        PdfObject obj = getPdfObject(idx);
+        releaseLastXrefPartial();
+        return obj;
+    }
+    
+    public PdfObject getPdfObject(int idx) {
+        try {
+            lastXrefPartial = -1;
+            if (idx < 0 || idx >= xrefObj.size())
+                return null;
+            PdfObject obj = (PdfObject)xrefObj.get(idx);
+            if (!partial || obj != null)
+                return obj;
+            if (idx * 2 >= xref.length)
+                return null;
+            obj = readSingleObject(idx);
+            lastXrefPartial = -1;
+            if (obj != null)
+                lastXrefPartial = idx;
+            return obj;
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+
+    public void resetLastXrefPartial() {
+        lastXrefPartial = -1;
+    }
+    
+    public void releaseLastXrefPartial() {
+        if (partial && lastXrefPartial != -1) {
+            xrefObj.set(lastXrefPartial, null);
+            lastXrefPartial = -1;
+        }
+    }
+
+    public static void releaseLastXrefPartial(PdfObject obj) {
+        if (obj == null)
+            return;
+        if (!obj.isIndirect())
+            return;
+        PRIndirectReference ref = (PRIndirectReference)obj;
+        PdfReader reader = ref.getReader();
+        if (reader.partial && reader.lastXrefPartial != -1 && reader.lastXrefPartial == ref.getNumber()) {
+            reader.xrefObj.set(reader.lastXrefPartial, null);
+        }
+        reader.lastXrefPartial = -1;
+    }
+
+    private void setXrefPartialObject(int idx, PdfObject obj) {
+        if (!partial || idx < 0)
+            return;
+        xrefObj.set(idx, obj);
+    }
+    
+    public PRIndirectReference addPdfObject(PdfObject obj) {
+        xrefObj.add(obj);
+        return new PRIndirectReference(this, xrefObj.size() - 1);
+    }
+    
+    protected void readPages() throws IOException {
+        pageInh = new ArrayList();
+        catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
+        rootPages = (PdfDictionary)getPdfObject(catalog.get(PdfName.PAGES));
+        pageRefs = new PageRefs(this);
+    }
+    
+    protected PRIndirectReference getSinglePage(int n) throws IOException {
+        PdfDictionary acc = new PdfDictionary();
+        PdfDictionary top = rootPages;
+        int base = 0;
+        while (true) {
+            break;
+        }
+        return null;
+    }
+    
+    protected void PRSimpleRecursive(PdfObject obj) throws IOException {
+        switch (obj.type()) {
+            case PdfObject.DICTIONARY:
+            case PdfObject.STREAM:
+                PdfDictionary dic = (PdfDictionary)obj;
+                for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+                    PdfName key = (PdfName)it.next();
+                    PRSimpleRecursive(dic.get(key));
+                }
+                break;
+            case PdfObject.ARRAY:
+                ArrayList list = ((PdfArray)obj).getArrayList();
+                for (int k = 0; k < list.size(); ++k) {
+                    PRSimpleRecursive((PdfObject)list.get(k));
+                }
+                break;
+            case PdfObject.INDIRECT:
+                PRIndirectReference ref = (PRIndirectReference)obj;
+                int num = ref.getNumber();
+                if (!visited[num]) {
+                    visited[num] = true;
+                    newHits.put(num, 1);
+                }
+                break;
+        }
+    }
+        
+    protected void readDocObjPartial() throws IOException {
+        xrefObj = new ArrayList(xref.length / 2);
+        xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
+        readDecryptedDocObj();
+        if (objStmToOffset != null) {
+            int keys[] = objStmToOffset.getKeys();
+            for (int k = 0; k < keys.length; ++k) {
+                int n = keys[k];
+                objStmToOffset.put(n, xref[n * 2]);
+                xref[n * 2] = -1;
+            }
+        }
+    }
+
+    protected PdfObject readSingleObject(int k) throws IOException {
+        strings.clear();
+        int k2 = k * 2;
+        int pos = xref[k2];
+        if (pos < 0)
+            return null;
+        if (xref[k2 + 1] > 0)
+            pos = objStmToOffset.get(xref[k2 + 1]);
+        tokens.seek(pos);
+        tokens.nextValidToken();
+        if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+            tokens.throwError("Invalid object number.");
+        objNum = tokens.intValue();
+        tokens.nextValidToken();
+        if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+            tokens.throwError("Invalid generation number.");
+        objGen = tokens.intValue();
+        tokens.nextValidToken();
+        if (!tokens.getStringValue().equals("obj"))
+            tokens.throwError("Token 'obj' expected.");
+        PdfObject obj;
+        try {
+            obj = readPRObject();
+            for (int j = 0; j < strings.size(); ++j) {
+                PdfString str = (PdfString)strings.get(j);
+                str.decrypt(this);
+            }
+            if (obj.isStream()) {
+                checkPRStreamLength((PRStream)obj);
+            }
+        }
+        catch (Exception e) {
+            obj = null;
+        }
+        if (xref[k2 + 1] > 0) {
+            obj = readOneObjStm((PRStream)obj, xref[k2]);
+        }
+        xrefObj.set(k, obj);
+        return obj;
+    }
+    
+    protected PdfObject readOneObjStm(PRStream stream, int idx) throws IOException {
+        int first = ((PdfNumber)getPdfObject(stream.get(PdfName.FIRST))).intValue();
+        int n = ((PdfNumber)getPdfObject(stream.get(PdfName.N))).intValue();
+        byte b[] = getStreamBytes(stream, tokens.getFile());
+        PRTokeniser saveTokens = tokens;
+        tokens = new PRTokeniser(b);
+        try {
+            int address = 0;
+            int objNumber = 0;
+            boolean ok = true;
+            ++idx;
+            for (int k = 0; k < idx; ++k) {
+                ok = tokens.nextToken();
+                if (!ok)
+                    break;
+                if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+                    ok = false;
+                    break;
+                }
+                objNumber = tokens.intValue();
+                ok = tokens.nextToken();
+                if (!ok)
+                    break;
+                if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+                    ok = false;
+                    break;
+                }
+                address = tokens.intValue() + first;
+            }
+            if (!ok)
+                throw new IOException("Error reading ObjStm");
+            tokens.seek(address);
+            return readPRObject();
+        }
+        finally {
+            tokens = saveTokens;
+        }
+    }
+
+    public double dumpPerc() {
+        int total = 0;
+        for (int k = 0; k < xrefObj.size(); ++k) {
+            if (xrefObj.get(k) != null)
+                ++total;
+        }
+        return (total * 100.0 / xrefObj.size());
+    }
+    
+    protected void readDocObj() throws IOException {
+        ArrayList streams = new ArrayList();
+        xrefObj = new ArrayList(xref.length / 2);
+        xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
+        for (int k = 2; k < xref.length; k += 2) {
+            int pos = xref[k];
+            if (pos <= 0 || xref[k + 1] > 0)
+                continue;
+            tokens.seek(pos);
+            tokens.nextValidToken();
+            if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+                tokens.throwError("Invalid object number.");
+            objNum = tokens.intValue();
+            tokens.nextValidToken();
+            if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+                tokens.throwError("Invalid generation number.");
+            objGen = tokens.intValue();
+            tokens.nextValidToken();
+            if (!tokens.getStringValue().equals("obj"))
+                tokens.throwError("Token 'obj' expected.");
+            PdfObject obj;
+            try {
+                obj = readPRObject();
+                if (obj.isStream()) {
+                    streams.add(obj);
+                }
+            }
+            catch (Exception e) {
+                obj = null;
+            }
+            xrefObj.set(k / 2, obj);
+        }
+        int fileLength = tokens.length();
+        byte tline[] = new byte[16];
+        for (int k = 0; k < streams.size(); ++k) {
+            checkPRStreamLength((PRStream)streams.get(k));
+        }
+        readDecryptedDocObj();
+        if (objStmMark != null) {
+            for (Iterator i = objStmMark.entrySet().iterator(); i.hasNext();) {
+                Map.Entry entry = (Map.Entry)i.next();
+                int n = ((Integer)entry.getKey()).intValue();
+                IntHashtable h = (IntHashtable)entry.getValue();
+                readObjStm((PRStream)xrefObj.get(n), h);
+                xrefObj.set(n, null);
+            }
+            objStmMark = null;
+        }
+        xref = null;
+    }
+    
+    private void checkPRStreamLength(PRStream stream) throws IOException {
+        int fileLength = tokens.length();
+        int start = stream.getOffset();
+        boolean calc = false;
+        int streamLength = 0;
+        PdfObject obj = getPdfObjectRelease(stream.get(PdfName.LENGTH));
+        if (obj != null && obj.type() == PdfObject.NUMBER) {
+            streamLength = ((PdfNumber)obj).intValue();
+            if (streamLength + start > fileLength - 20)
+                calc = true;
+            else {
+                tokens.seek(start + streamLength);
+                String line = tokens.readString(20);
+                if (!line.startsWith("\nendstream") &&
+                !line.startsWith("\r\nendstream") &&
+                !line.startsWith("\rendstream") &&
+                !line.startsWith("endstream"))
+                    calc = true;
+            }
+        }
+        else
+            calc = true;
+        if (calc) {
+            byte tline[] = new byte[16];
+            tokens.seek(start);
+            while (true) {
+                int pos = tokens.getFilePointer();
+                if (!tokens.readLineSegment(tline))
+                    break;
+                if (equalsn(tline, endstream)) {
+                    streamLength = pos - start;
+                    break;
+                }
+                if (equalsn(tline, endobj)) {
+                    tokens.seek(pos - 16);
+                    String s = tokens.readString(16);
+                    int index = s.indexOf("endstream");
+                    if (index >= 0)
+                        pos = pos - 16 + index;
+                    streamLength = pos - start;
+                    break;
+                }
+            }
+        }
+        stream.setLength(streamLength);
+    }
+    
+    protected void readObjStm(PRStream stream, IntHashtable map) throws IOException {
+        int first = ((PdfNumber)getPdfObject(stream.get(PdfName.FIRST))).intValue();
+        int n = ((PdfNumber)getPdfObject(stream.get(PdfName.N))).intValue();
+        byte b[] = getStreamBytes(stream, tokens.getFile());
+        PRTokeniser saveTokens = tokens;
+        tokens = new PRTokeniser(b);
+        try {
+            int address[] = new int[n];
+            int objNumber[] = new int[n];
+            boolean ok = true;
+            for (int k = 0; k < n; ++k) {
+                ok = tokens.nextToken();
+                if (!ok)
+                    break;
+                if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+                    ok = false;
+                    break;
+                }
+                objNumber[k] = tokens.intValue();
+                ok = tokens.nextToken();
+                if (!ok)
+                    break;
+                if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+                    ok = false;
+                    break;
+                }
+                address[k] = tokens.intValue() + first;
+            }
+            if (!ok)
+                throw new IOException("Error reading ObjStm");
+            for (int k = 0; k < n; ++k) {
+                if (map.containsKey(k)) {
+                    tokens.seek(address[k]);
+                    PdfObject obj = readPRObject();
+                    xrefObj.set(objNumber[k], obj);
+                }
+            }            
+        }
+        finally {
+            tokens = saveTokens;
+        }
+    }
+    
+    static PdfObject killIndirect(PdfObject obj) {
+        if (obj == null || obj.isNull())
+            return null;
+        PdfObject ret = getPdfObjectRelease(obj);
+        if (obj.isIndirect()) {
+            PRIndirectReference ref = (PRIndirectReference)obj;
+            PdfReader reader = ref.getReader();
+            int n = ref.getNumber();
+            reader.xrefObj.set(n, null);
+            if (reader.partial)
+                reader.xref[n * 2] = -1;
+        }
+        return ret;
+    }
+    
+    private void ensureXrefSize(int size) {
+        if (size == 0)
+            return;
+        if (xref == null)
+            xref = new int[size];
+        else {
+            if (xref.length < size) {
+                int xref2[] = new int[size];
+                System.arraycopy(xref, 0, xref2, 0, xref.length);
+                xref = xref2;
+            }
+        }
+    }
+    
+    protected void readXref() throws IOException {
+        hybridXref = false;
+        newXrefType = false;
+        tokens.seek(tokens.getStartxref());
+        tokens.nextToken();
+        if (!tokens.getStringValue().equals("startxref"))
+            throw new IOException("startxref not found.");
+        tokens.nextToken();
+        if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+            throw new IOException("startxref is not followed by a number.");
+        int startxref = tokens.intValue();
+        lastXref = startxref;
+        eofPos = tokens.getFilePointer();
+        try {
+            if (readXRefStream(startxref)) {
+                newXrefType = true;
+                return;
+            }
+        }
+        catch (Exception e) {}
+        xref = null;
+        tokens.seek(startxref);
+        trailer = readXrefSection();
+        PdfDictionary trailer2 = trailer;
+        while (true) {
+            PdfNumber prev = (PdfNumber)trailer2.get(PdfName.PREV);
+            if (prev == null)
+                break;
+            tokens.seek(prev.intValue());
+            trailer2 = readXrefSection();
+        }
+    }
+    
+    protected PdfDictionary readXrefSection() throws IOException {
+        tokens.nextValidToken();
+        if (!tokens.getStringValue().equals("xref"))
+            tokens.throwError("xref subsection not found");
+        int start = 0;
+        int end = 0;
+        int pos = 0;
+        int gen = 0;
+        while (true) {
+            tokens.nextValidToken();
+            if (tokens.getStringValue().equals("trailer"))
+                break;
+            if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+                tokens.throwError("Object number of the first object in this xref subsection not found");
+            start = tokens.intValue();
+            tokens.nextValidToken();
+            if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+                tokens.throwError("Number of entries in this xref subsection not found");
+            end = tokens.intValue() + start;
+            if (start == 1) { // fix incorrect start number
+                int back = tokens.getFilePointer();
+                tokens.nextValidToken();
+                pos = tokens.intValue();
+                tokens.nextValidToken();
+                gen = tokens.intValue();
+                if (pos == 0 && gen == 65535) {
+                    --start;
+                    --end;
+                }
+                tokens.seek(back);
+            }
+            ensureXrefSize(end * 2);
+            for (int k = start; k < end; ++k) {
+                tokens.nextValidToken();
+                pos = tokens.intValue();
+                tokens.nextValidToken();
+                gen = tokens.intValue();
+                tokens.nextValidToken();
+                int p = k * 2;
+                if (tokens.getStringValue().equals("n")) {
+                    if (xref[p] == 0 && xref[p + 1] == 0) {
+//                        if (pos == 0)
+//                            tokens.throwError("File position 0 cross-reference entry in this xref subsection");
+                        xref[p] = pos;
+                    }
+                }
+                else if (tokens.getStringValue().equals("f")) {
+                    if (xref[p] == 0 && xref[p + 1] == 0)
+                        xref[p] = -1;
+                }
+                else
+                    tokens.throwError("Invalid cross-reference entry in this xref subsection");
+            }
+        }
+        PdfDictionary trailer = (PdfDictionary)readPRObject();
+        PdfNumber xrefSize = (PdfNumber)trailer.get(PdfName.SIZE);
+        ensureXrefSize(xrefSize.intValue() * 2);
+        PdfObject xrs = trailer.get(PdfName.XREFSTM);
+        if (xrs != null && xrs.isNumber()) {
+            int loc = ((PdfNumber)xrs).intValue();
+            try {
+                readXRefStream(loc);
+                newXrefType = true;
+                hybridXref = true;
+            }
+            catch (IOException e) {
+                xref = null;
+                throw e;
+            }
+        }
+        return trailer;
+    }
+    
+    protected boolean readXRefStream(int ptr) throws IOException {
+        tokens.seek(ptr);
+        int thisStream = 0;
+        if (!tokens.nextToken())
+            return false;
+        if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+            return false;
+        thisStream = tokens.intValue();
+        if (!tokens.nextToken() || tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+            return false;
+        if (!tokens.nextToken() || !tokens.getStringValue().equals("obj"))
+            return false;
+        PdfObject object = readPRObject();
+        PRStream stm = null;
+        if (object.isStream()) {
+            stm = (PRStream)object;
+            if (!PdfName.XREF.equals(stm.get(PdfName.TYPE)))
+                return false;
+        }
+        if (trailer == null) {
+            trailer = new PdfDictionary();
+            trailer.putAll(stm);
+        }
+        stm.setLength(((PdfNumber)stm.get(PdfName.LENGTH)).intValue());
+        int size = ((PdfNumber)stm.get(PdfName.SIZE)).intValue();
+        PdfArray index;
+        PdfObject obj = stm.get(PdfName.INDEX);
+        if (obj == null) {
+            index = new PdfArray();
+            index.add(new int[]{0, size});
+        }
+        else
+            index = (PdfArray)obj;
+        PdfArray w = (PdfArray)stm.get(PdfName.W);
+        int prev = -1;
+        obj = stm.get(PdfName.PREV);
+        if (obj != null)
+            prev = ((PdfNumber)obj).intValue();
+        // Each xref pair is a position
+        // type 0 -> -1, 0
+        // type 1 -> offset, 0
+        // type 2 -> index, obj num
+        ensureXrefSize(size * 2);
+        if (objStmMark == null && !partial)
+            objStmMark = new HashMap();
+        if (objStmToOffset == null && partial)
+            objStmToOffset = new IntHashtable();
+        byte b[] = getStreamBytes(stm, tokens.getFile());
+        int bptr = 0;
+        ArrayList wa = w.getArrayList();
+        int wc[] = new int[3];
+        for (int k = 0; k < 3; ++k)
+            wc[k] = ((PdfNumber)wa.get(k)).intValue();
+        ArrayList sections = index.getArrayList();
+        for (int idx = 0; idx < sections.size(); idx += 2) {
+            int start = ((PdfNumber)sections.get(idx)).intValue();
+            int length = ((PdfNumber)sections.get(idx + 1)).intValue();
+            ensureXrefSize((start + length) * 2);
+            while (length-- > 0) {
+                int total = 0;
+                int type = 1;
+                if (wc[0] > 0) {
+                    type = 0;
+                    for (int k = 0; k < wc[0]; ++k)
+                        type = (type << 8) + (b[bptr++] & 0xff);
+                }
+                int field2 = 0;
+                for (int k = 0; k < wc[1]; ++k)
+                    field2 = (field2 << 8) + (b[bptr++] & 0xff);
+                int field3 = 0;
+                for (int k = 0; k < wc[2]; ++k)
+                    field3 = (field3 << 8) + (b[bptr++] & 0xff);
+                int base = start * 2;
+                if (xref[base] == 0 && xref[base + 1] == 0) {
+                    switch (type) {
+                        case 0:
+                            xref[base] = -1;
+                            break;
+                        case 1:
+                            xref[base] = field2;
+                            break;
+                        case 2:
+                            xref[base] = field3;
+                            xref[base + 1] = field2;
+                            if (partial) {
+                                objStmToOffset.put(field2, 0);
+                            }
+                            else {
+                                Integer on = new Integer(field2);
+                                IntHashtable seq = (IntHashtable)objStmMark.get(on);
+                                if (seq == null) {
+                                    seq = new IntHashtable();
+                                    seq.put(field3, 1);
+                                    objStmMark.put(on, seq);
+                                }
+                                else
+                                    seq.put(field3, 1);
+                            }
+                            break;
+                    }
+                }
+                ++start;
+            }
+        }
+        thisStream *= 2;
+        if (thisStream < xref.length)
+            xref[thisStream] = -1;
+            
+        if (prev == -1)
+            return true;
+        return readXRefStream(prev);
+    }
+    
+    protected void rebuildXref() throws IOException {
+        hybridXref = false;
+        newXrefType = false;
+        tokens.seek(0);
+        int xr[][] = new int[1024][];
+        int top = 0;
+        trailer = null;
+        byte line[] = new byte[64];
+        for (;;) {
+            int pos = tokens.getFilePointer();
+            if (!tokens.readLineSegment(line))
+                break;
+            if (line[0] == 't') {
+                if (!PdfEncodings.convertToString(line, null).startsWith("trailer"))
+                    continue;
+                pos = tokens.getFilePointer();
+                try {
+                    PdfDictionary dic = (PdfDictionary)readPRObject();
+                    if (dic.get(PdfName.ROOT) != null)
+                        trailer = dic;
+                    else
+                        tokens.seek(pos);
+                }
+                catch (Exception e) {
+                    tokens.seek(pos);
+                }
+            }
+            else if (line[0] >= '0' && line[0] <= '9') {
+                int obj[] = PRTokeniser.checkObjectStart(line);
+                if (obj == null)
+                    continue;
+                int num = obj[0];
+                int gen = obj[1];
+                if (num >= xr.length) {
+                    int newLength = num * 2;
+                    int xr2[][] = new int[newLength][];
+                    System.arraycopy(xr, 0, xr2, 0, top);
+                    xr = xr2;
+                }
+                if (num >= top)
+                    top = num + 1;
+                if (xr[num] == null || gen >= xr[num][1]) {
+                    obj[0] = pos;
+                    xr[num] = obj;
+                }
+            }
+        }
+        if (trailer == null)
+            throw new IOException("trailer not found.");
+        xref = new int[top * 2];
+        for (int k = 0; k < top; ++k) {
+            int obj[] = xr[k];
+            if (obj != null)
+                xref[k * 2] = obj[0];
+        }
+    }
+    
+    protected PdfDictionary readDictionary() throws IOException {
+        PdfDictionary dic = new PdfDictionary();
+        while (true) {
+            tokens.nextValidToken();
+            if (tokens.getTokenType() == PRTokeniser.TK_END_DIC)
+                break;
+            if (tokens.getTokenType() != PRTokeniser.TK_NAME)
+                tokens.throwError("Dictionary key is not a name.");
+            PdfName name = new PdfName(tokens.getStringValue());
+            PdfObject obj = readPRObject();
+            int type = obj.type();
+            if (-type == PRTokeniser.TK_END_DIC)
+                tokens.throwError("Unexpected '>>'");
+            if (-type == PRTokeniser.TK_END_ARRAY)
+                tokens.throwError("Unexpected ']'");
+            dic.put(name, obj);
+        }
+        return dic;
+    }
+    
+    protected PdfArray readArray() throws IOException {
+        PdfArray array = new PdfArray();
+        while (true) {
+            PdfObject obj = readPRObject();
+            int type = obj.type();
+            if (-type == PRTokeniser.TK_END_ARRAY)
+                break;
+            if (-type == PRTokeniser.TK_END_DIC)
+                tokens.throwError("Unexpected '>>'");
+            array.add(obj);
+        }
+        return array;
+    }
+    
+    protected PdfObject readPRObject() throws IOException {
+        tokens.nextValidToken();
+        int type = tokens.getTokenType();
+        switch (type) {
+            case PRTokeniser.TK_START_DIC: {
+                PdfDictionary dic = readDictionary();
+                int pos = tokens.getFilePointer();
+                // be careful in the trailer. May not be a "next" token.
+                if (tokens.nextToken() && tokens.getStringValue().equals("stream")) {
+                    int ch = tokens.read();
+                    if (ch != '\n')
+                        ch = tokens.read();
+                    if (ch != '\n')
+                        tokens.backOnePosition(ch);
+                    PRStream stream = new PRStream(this, tokens.getFilePointer());
+                    stream.putAll(dic);
+                    stream.setObjNum(objNum, objGen);
+                    return stream;
+                }
+                else {
+                    tokens.seek(pos);
+                    return dic;
+                }
+            }
+            case PRTokeniser.TK_START_ARRAY:
+                return readArray();
+            case PRTokeniser.TK_NUMBER:
+                return new PdfNumber(tokens.getStringValue());
+            case PRTokeniser.TK_STRING:
+                PdfString str = new PdfString(tokens.getStringValue(), null).setHexWriting(tokens.isHexString());
+                str.setObjNum(objNum, objGen);
+                if (strings != null)
+                    strings.add(str);
+                return str;
+            case PRTokeniser.TK_NAME:
+                return new PdfName(tokens.getStringValue());
+            case PRTokeniser.TK_REF:
+                int num = tokens.getReference();
+                PRIndirectReference ref = new PRIndirectReference(this, num, tokens.getGeneration());
+                if (visited != null && !visited[num]) {
+                    visited[num] = true;
+                    newHits.put(num, 1);
+                }
+                return ref;
+            default:
+                return new PdfLiteral(-type, tokens.getStringValue());
+        }
+    }
+    
+    /** Decodes a stream that has the FlateDecode filter.
+     * @param in the input data
+     * @return the decoded data
+     */    
+    public static byte[] FlateDecode(byte in[]) {
+        byte b[] = FlateDecode(in, true);
+        if (b == null)
+            return FlateDecode(in, false);
+        return b;
+    }
+    
+    public static byte[] decodePredictor(byte in[], PdfObject dicPar) {
+        if (dicPar == null || !dicPar.isDictionary())
+            return in;
+        PdfDictionary dic = (PdfDictionary)dicPar;
+        PdfObject obj = getPdfObject(dic.get(PdfName.PREDICTOR));
+        if (obj == null || !obj.isNumber())
+            return in;
+        int predictor = ((PdfNumber)obj).intValue();
+        if (predictor < 10)
+            return in;
+        int width = 1;
+        obj = getPdfObject(dic.get(PdfName.COLUMNS));
+        if (obj != null && obj.isNumber())
+            width = ((PdfNumber)obj).intValue();
+        int colors = 1;
+        obj = getPdfObject(dic.get(PdfName.COLORS));
+        if (obj != null && obj.isNumber())
+            colors = ((PdfNumber)obj).intValue();
+        int bpc = 8;
+        obj = getPdfObject(dic.get(PdfName.BITSPERCOMPONENT));
+        if (obj != null && obj.isNumber())
+            bpc = ((PdfNumber)obj).intValue();
+        DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(in));
+        ByteArrayOutputStream fout = new ByteArrayOutputStream(in.length);
+        int bytesPerPixel = colors * bpc / 8;
+        int bytesPerRow = (colors*width*bpc + 7)/8;
+        byte[] curr = new byte[bytesPerRow];
+        byte[] prior = new byte[bytesPerRow];
+        
+        // Decode the (sub)image row-by-row
+        while (true) {
+            // Read the filter type byte and a row of data
+            int filter = 0;
+            try {
+                filter = dataStream.read();
+                if (filter < 0) {
+                    return fout.toByteArray();
+                }
+                dataStream.readFully(curr, 0, bytesPerRow);
+            } catch (Exception e) {
+                return fout.toByteArray();
+            }
+            
+            switch (filter) {
+                case 0: //PNG_FILTER_NONE
+                    break;
+                case 1: //PNG_FILTER_SUB
+                    for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+                        curr[i] += curr[i - bytesPerPixel];
+                    }
+                    break;
+                case 2: //PNG_FILTER_UP
+                    for (int i = 0; i < bytesPerRow; i++) {
+                        curr[i] += prior[i];
+                    }
+                    break;
+                case 3: //PNG_FILTER_AVERAGE
+                    for (int i = 0; i < bytesPerPixel; i++) {
+                        curr[i] += prior[i] / 2;
+                    }
+                    for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+                        curr[i] += ((curr[i - bytesPerPixel] & 0xff) + (prior[i] & 0xff))/2;
+                    }
+                    break;
+                case 4: //PNG_FILTER_PAETH
+                    for (int i = 0; i < bytesPerPixel; i++) {
+                        curr[i] += prior[i];
+                    }
+
+                    for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+                        int a = curr[i - bytesPerPixel] & 0xff;
+                        int b = prior[i] & 0xff;
+                        int c = prior[i - bytesPerPixel] & 0xff;
+
+                        int p = a + b - c;
+                        int pa = Math.abs(p - a);
+                        int pb = Math.abs(p - b);
+                        int pc = Math.abs(p - c);
+
+                        int ret;
+
+                        if ((pa <= pb) && (pa <= pc)) {
+                            ret = a;
+                        } else if (pb <= pc) {
+                            ret = b;
+                        } else {
+                            ret = c;
+                        }
+                        curr[i] += (byte)(ret);
+                    }
+                    break;
+                default:
+                    // Error -- uknown filter type
+                    throw new RuntimeException("PNG filter unknown.");
+            }
+            try {
+                fout.write(curr);
+            }
+            catch (IOException ioe) {
+                // Never happens
+            }
+            
+            // Swap curr and prior
+            byte[] tmp = prior;
+            prior = curr;
+            curr = tmp;
+        }        
+    }
+    
+    /** A helper to FlateDecode.
+     * @param in the input data
+     * @param strict <CODE>true</CODE> to read a correct stream. <CODE>false</CODE>
+     * to try to read a corrupted stream
+     * @return the decoded data
+     */    
+    public static byte[] FlateDecode(byte in[], boolean strict) {
+        ByteArrayInputStream stream = new ByteArrayInputStream(in);
+        InflaterInputStream zip = new InflaterInputStream(stream);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        byte b[] = new byte[strict ? 4092 : 1];
+        try {
+            int n;
+            while ((n = zip.read(b)) >= 0) {
+                out.write(b, 0, n);
+            }
+            zip.close();
+            out.close();
+            return out.toByteArray();
+        }
+        catch (Exception e) {
+            if (strict)
+                return null;
+            return out.toByteArray();
+        }
+    }
+    
+    /** Decodes a stream that has the ASCIIHexDecode filter.
+     * @param in the input data
+     * @return the decoded data
+     */    
+    public static byte[] ASCIIHexDecode(byte in[]) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        boolean first = true;
+        int n1 = 0;
+        for (int k = 0; k < in.length; ++k) {
+            int ch = in[k] & 0xff;
+            if (ch == '>')
+                break;
+            if (PRTokeniser.isWhitespace(ch))
+                continue;
+            int n = PRTokeniser.getHex(ch);
+            if (n == -1)
+                throw new RuntimeException("Illegal character in ASCIIHexDecode.");
+            if (first)
+                n1 = n;
+            else
+                out.write((byte)((n1 << 4) + n));
+            first = !first;
+        }
+        if (!first)
+            out.write((byte)(n1 << 4));
+        return out.toByteArray();
+    }
+    
+    /** Decodes a stream that has the ASCII85Decode filter.
+     * @param in the input data
+     * @return the decoded data
+     */    
+    public static byte[] ASCII85Decode(byte in[]) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int state = 0;
+        int chn[] = new int[5];
+        for (int k = 0; k < in.length; ++k) {
+            int ch = in[k] & 0xff;
+            if (ch == '~')
+                break;
+            if (PRTokeniser.isWhitespace(ch))
+                continue;
+            if (ch == 'z' && state == 0) {
+                out.write(0);
+                out.write(0);
+                out.write(0);
+                out.write(0);
+                continue;
+            }
+            if (ch < '!' || ch > 'u')
+                throw new RuntimeException("Illegal character in ASCII85Decode.");
+            chn[state] = ch - '!';
+            ++state;
+            if (state == 5) {
+                state = 0;
+                int r = 0;
+                for (int j = 0; j < 5; ++j)
+                    r = r * 85 + chn[j];
+                out.write((byte)(r >> 24));
+                out.write((byte)(r >> 16));
+                out.write((byte)(r >> 8));
+                out.write((byte)r);
+            }
+        }
+        int r = 0;
+        if (state == 1)
+            throw new RuntimeException("Illegal length in ASCII85Decode.");
+        if (state == 2) {
+            r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85;
+            out.write((byte)(r >> 24));
+        }
+        else if (state == 3) {
+            r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85  + chn[2] * 85 * 85;
+            out.write((byte)(r >> 24));
+            out.write((byte)(r >> 16));
+        }
+        else if (state == 4) {
+            r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85  + chn[2] * 85 * 85  + chn[3] * 85 ;
+            out.write((byte)(r >> 24));
+            out.write((byte)(r >> 16));
+            out.write((byte)(r >> 8));
+        }
+        return out.toByteArray();
+    }
+    
+    /** Decodes a stream that has the LZWDecode filter.
+     * @param in the input data
+     * @return the decoded data
+     */    
+    public static byte[] LZWDecode(byte in[]) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        LZWDecoder lzw = new LZWDecoder();
+        lzw.decode(in, out);
+        return out.toByteArray();
+    }
+    
+    /** Checks if the document had errors and was rebuilt.
+     * @return true if rebuilt.
+     *
+     */
+    public boolean isRebuilt() {
+        return this.rebuilt;
+    }
+    
+    /** Gets the dictionary that represents a page.
+     * @param pageNum the page number. 1 is the first
+     * @return the page dictionary
+     */    
+    public PdfDictionary getPageN(int pageNum) {
+        PdfDictionary dic = pageRefs.getPageN(pageNum);
+        if (dic == null)
+            return null;
+        if (appendable)
+            dic.setIndRef(pageRefs.getPageOrigRef(pageNum));
+        return dic;
+    }
+    
+    public PdfDictionary getPageNRelease(int pageNum) {
+        PdfDictionary dic = getPageN(pageNum);
+        pageRefs.releasePage(pageNum);
+        return dic;
+    }
+    
+    public void releasePage(int pageNum) {
+        pageRefs.releasePage(pageNum);
+    }
+    
+    public void resetReleasePage() {
+        pageRefs.resetReleasePage();
+    }
+
+    /** Gets the page reference to this page.
+     * @param pageNum the page number. 1 is the first
+     * @return the page reference
+     */    
+    public PRIndirectReference getPageOrigRef(int pageNum) {
+        return pageRefs.getPageOrigRef(pageNum);
+    }
+    
+    /** Gets the contents of the page.
+     * @param pageNum the page number. 1 is the first
+     * @param file the location of the PDF document
+     * @throws IOException on error
+     * @return the content
+     */    
+    public byte[] getPageContent(int pageNum, RandomAccessFileOrArray file) throws IOException{
+        PdfDictionary page = getPageNRelease(pageNum);
+        if (page == null)
+            return null;
+        PdfObject contents = getPdfObjectRelease(page.get(PdfName.CONTENTS));
+        if (contents == null)
+            return new byte[0];
+        ByteArrayOutputStream bout = null;
+        if (contents.isStream()) {
+            return getStreamBytes((PRStream)contents, file);
+        }
+        else if (contents.isArray()) {
+            PdfArray array = (PdfArray)contents;
+            ArrayList list = array.getArrayList();
+            bout = new ByteArrayOutputStream();
+            for (int k = 0; k < list.size(); ++k) {
+                PdfObject item = getPdfObjectRelease((PdfObject)list.get(k));
+                if (item == null || !item.isStream())
+                    continue;
+                byte[] b = getStreamBytes((PRStream)item, file);
+                bout.write(b);
+                if (k != list.size() - 1)
+                    bout.write('\n');
+            }
+            return bout.toByteArray();
+        }
+        else
+            return new byte[0];
+    }
+    
+    /** Gets the contents of the page.
+     * @param pageNum the page number. 1 is the first
+     * @throws IOException on error
+     * @return the content
+     */    
+    public byte[] getPageContent(int pageNum) throws IOException{
+        RandomAccessFileOrArray rf = getSafeFile();
+        try {
+            rf.reOpen();
+            return getPageContent(pageNum, rf);
+        }
+        finally {
+            try{rf.close();}catch(Exception e){}
+        }
+    }
+    
+    protected void killXref(PdfObject obj) {
+        if (obj == null)
+            return;
+        if ((obj instanceof PdfIndirectReference) && !obj.isIndirect())
+            return;
+        switch (obj.type()) {
+            case PdfObject.INDIRECT: {
+                int xr = ((PRIndirectReference)obj).getNumber();
+                obj = (PdfObject)xrefObj.get(xr);
+                xrefObj.set(xr, null);
+                freeXref = xr;
+                killXref(obj);
+                break;
+            }
+            case PdfObject.ARRAY: {
+                ArrayList t = ((PdfArray)obj).getArrayList();
+                for (int i = 0; i < t.size(); ++i)
+                    killXref((PdfObject)t.get(i));
+                break;
+            }
+            case PdfObject.STREAM:
+            case PdfObject.DICTIONARY: {
+                PdfDictionary dic = (PdfDictionary)obj;
+                for (Iterator i = dic.getKeys().iterator(); i.hasNext();){
+                    killXref(dic.get((PdfName)i.next()));
+                }
+                break;
+            }
+        }
+    }
+    
+    /** Sets the contents of the page.
+     * @param content the new page content
+     * @param pageNum the page number. 1 is the first
+     * @throws IOException on error
+     */    
+    public void setPageContent(int pageNum, byte content[]) throws IOException{
+        PdfDictionary page = getPageN(pageNum);
+        if (page == null)
+            return;
+        PdfObject contents = page.get(PdfName.CONTENTS);
+        freeXref = -1;
+        killXref(contents);
+        if (freeXref == -1) {
+            xrefObj.add(null);
+            freeXref = xrefObj.size() - 1;
+        }
+        page.put(PdfName.CONTENTS, new PRIndirectReference(this, freeXref));
+        xrefObj.set(freeXref, new PRStream(this, content));
+    }
+    
+    /** Get the content from a stream.
+     * @param stream the stream
+     * @param file the location where the stream is
+     * @throws IOException on error
+     * @return the stream content
+     */    
+    public static byte[] getStreamBytes(PRStream stream, RandomAccessFileOrArray file) throws IOException {
+        PdfReader reader = stream.getReader();
+        PdfObject filter = getPdfObjectRelease(stream.get(PdfName.FILTER));
+        byte b[];
+        if (stream.getOffset() < 0)
+            b = stream.getBytes();
+        else {
+            b = new byte[stream.getLength()];
+            file.seek(stream.getOffset());
+            file.readFully(b);
+            PdfEncryption decrypt = reader.getDecrypt();
+            if (decrypt != null) {
+                decrypt.setHashKey(stream.getObjNum(), stream.getObjGen());
+                decrypt.prepareKey();
+                decrypt.encryptRC4(b);
+            }
+        }
+        ArrayList filters = new ArrayList();
+        if (filter != null) {
+            if (filter.isName())
+                filters.add(filter);
+            else if (filter.isArray())
+                filters = ((PdfArray)filter).getArrayList();
+        }
+        ArrayList dp = new ArrayList();
+        PdfObject dpo = getPdfObjectRelease(stream.get(PdfName.DECODEPARMS));
+        if (dpo == null || (!dpo.isDictionary() && !dpo.isArray()))
+            dpo = getPdfObjectRelease(stream.get(PdfName.DP));
+        if (dpo != null) {
+            if (dpo.isDictionary())
+                dp.add(dpo);
+            else if (dpo.isArray())
+                dp = ((PdfArray)dpo).getArrayList();
+        }
+        String name;
+        for (int j = 0; j < filters.size(); ++j) {
+            name = ((PdfName)PdfReader.getPdfObjectRelease((PdfObject)filters.get(j))).toString();
+            if (name.equals("/FlateDecode") || name.equals("/Fl")) {
+                b = PdfReader.FlateDecode(b);
+                PdfObject dicParam = null;
+                if (j < dp.size()) {
+                    dicParam = (PdfObject)dp.get(j);
+                    b = decodePredictor(b, dicParam);
+                }
+            }
+            else if (name.equals("/ASCIIHexDecode") || name.equals("/AHx"))
+                b = PdfReader.ASCIIHexDecode(b);
+            else if (name.equals("/ASCII85Decode") || name.equals("/A85"))
+                b = PdfReader.ASCII85Decode(b);
+            else if (name.equals("/LZWDecode")) {
+                b = PdfReader.LZWDecode(b);
+                PdfObject dicParam = null;
+                if (j < dp.size()) {
+                    dicParam = (PdfObject)dp.get(j);
+                    b = decodePredictor(b, dicParam);
+                }
+            }
+            else
+                throw new IOException("The filter " + name + " is not supported.");
+        }
+        return b;
+    }
+    
+    /** Get the content from a stream.
+     * @param stream the stream
+     * @throws IOException on error
+     * @return the stream content
+     */    
+    public static byte[] getStreamBytes(PRStream stream) throws IOException {
+        RandomAccessFileOrArray rf = stream.getReader().getSafeFile();
+        try {
+            rf.reOpen();
+            return PdfReader.getStreamBytes(stream, rf);
+        }
+        finally {
+            try{rf.close();}catch(Exception e){}
+        }
+    }
+    
+    /** Eliminates shared streams if they exist. */    
+    public void eliminateSharedStreams() {
+        if (!sharedStreams)
+            return;
+        sharedStreams = false;
+        if (pageRefs.size() == 1)
+            return;
+        ArrayList newRefs = new ArrayList();
+        ArrayList newStreams = new ArrayList();
+        IntHashtable visited = new IntHashtable();
+        for (int k = 1; k <= pageRefs.size(); ++k) {
+            PdfDictionary page = pageRefs.getPageN(k);
+            if (page == null)
+                continue;
+            PdfObject contents = getPdfObject(page.get(PdfName.CONTENTS));
+            if (contents == null)
+                continue;
+            if (contents.isStream()) {
+                PRIndirectReference ref = (PRIndirectReference)page.get(PdfName.CONTENTS);
+                if (visited.containsKey(ref.getNumber())) {
+                    // need to duplicate
+                    newRefs.add(ref);
+                    newStreams.add(new PRStream((PRStream)contents, null));
+                }
+                else
+                    visited.put(ref.getNumber(), 1);
+            }
+            else {
+                PdfArray array = (PdfArray)contents;
+                ArrayList list = array.getArrayList();
+                for (int j = 0; j < list.size(); ++j) {
+                    PRIndirectReference ref = (PRIndirectReference)list.get(j);
+                    if (visited.containsKey(ref.getNumber())) {
+                        // need to duplicate
+                        newRefs.add(ref);
+                        newStreams.add(new PRStream((PRStream)getPdfObject(ref), null));
+                    }
+                    else
+                        visited.put(ref.getNumber(), 1);
+                }
+            }
+        }
+        if (newStreams.size() == 0)
+            return;
+        for (int k = 0; k < newStreams.size(); ++k) {
+            xrefObj.add(newStreams.get(k));
+            PRIndirectReference ref = (PRIndirectReference)newRefs.get(k);
+            ref.setNumber(xrefObj.size() - 1, 0);
+        }
+    }
+    
+    /** Checks if the document was changed.
+     * @return <CODE>true</CODE> if the document was changed,
+     * <CODE>false</CODE> otherwise
+     */    
+    public boolean isTampered() {
+        return tampered;
+    }
+    
+    /**
+     * Sets the tampered state. A tampered PdfReader cannot be reused in PdfStamper.
+     * @param tampered the tampered state
+     */    
+    public void setTampered(boolean tampered) {
+        this.tampered = tampered;
+    }
+    
+    /** Gets the XML metadata.
+     * @throws IOException on error
+     * @return the XML metadata
+     */
+    public byte[] getMetadata() throws IOException {
+        PdfObject obj = getPdfObject(catalog.get(PdfName.METADATA));
+        if (!(obj instanceof PRStream))
+            return null;
+        RandomAccessFileOrArray rf = getSafeFile();
+        byte b[] = null;
+        try {
+            rf.reOpen();
+            b = getStreamBytes((PRStream)obj, rf);
+        }
+        finally {
+            try {
+                rf.close();
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }
+        }
+        return b;
+    }
+    
+    /**
+     * Gets the byte address of the last xref table.
+     * @return the byte address of the last xref table
+     */    
+    public int getLastXref() {
+        return lastXref;
+    }
+    
+    /**
+     * Gets the number of xref objects.
+     * @return the number of xref objects
+     */    
+    public int getXrefSize() {
+        return xrefObj.size();
+    }
+    
+    /**
+     * Gets the byte address of the %%EOF marker.
+     * @return the byte address of the %%EOF marker
+     */    
+    public int getEofPos() {
+        return eofPos;
+    }
+    
+    /**
+     * Gets the PDF version. Only the last version char is returned. For example
+     * version 1.4 is returned as '4'.
+     * @return the PDF version
+     */    
+    public char getPdfVersion() {
+        return pdfVersion;
+    }
+    
+    /**
+     * Returns <CODE>true</CODE> if the PDF is encrypted.
+     * @return <CODE>true</CODE> if the PDF is encrypted
+     */    
+    public boolean isEncrypted() {
+        return encrypted;
+    }
+    
+    /**
+     * Gets the encryption permissions. It can be used directly in
+     * <CODE>PdfWriter.setEncryption()</CODE>.
+     * @return the encryption permissions
+     */    
+    public int getPermissions() {
+        return pValue;
+    }
+    
+    /**
+     * Returns <CODE>true</CODE> if the PDF has a 128 bit key encryption.
+     * @return <CODE>true</CODE> if the PDF has a 128 bit key encryption
+     */    
+    public boolean is128Key() {
+        return rValue == 3;
+    }
+    
+    /**
+     * Gets the trailer dictionary
+     * @return the trailer dictionary
+     */    
+    public PdfDictionary getTrailer() {
+        return trailer;
+    }
+    
+    PdfEncryption getDecrypt() {
+        return decrypt;
+    }
+    
+    static boolean equalsn(byte a1[], byte a2[]) {
+        int length = a2.length;
+        for (int k = 0; k < length; ++k) {
+            if (a1[k] != a2[k])
+                return false;
+        }
+        return true;
+    }
+    
+    static boolean existsName(PdfDictionary dic, PdfName key, PdfName value) {
+        PdfObject type = getPdfObjectRelease(dic.get(key));
+        if (type == null || !type.isName())
+            return false;
+        PdfName name = (PdfName)type;
+        return name.equals(value);
+    }
+    
+    static String getFontName(PdfDictionary dic) {
+        PdfObject type = getPdfObjectRelease(dic.get(PdfName.BASEFONT));
+        if (type == null || !type.isName())
+            return null;
+        return PdfName.decodeName(type.toString());
+    }
+    
+    static String getSubsetPrefix(PdfDictionary dic) {
+        String s = getFontName(dic);
+        if (s == null)
+            return null;
+        if (s.length() < 8 || s.charAt(6) != '+')
+            return null;
+        for (int k = 0; k < 6; ++k) {
+            char c = s.charAt(k);
+            if (c < 'A' || c > 'Z')
+                return null;
+        }
+        return s;
+    }
+    
+    /** Finds all the font subsets and changes the prefixes to some
+     * random values.
+     * @return the number of font subsets altered
+     */    
+    public int shuffleSubsetNames() {
+        int total = 0;
+        for (int k = 1; k < xrefObj.size(); ++k) {
+            PdfObject obj = getPdfObjectRelease(k);
+            if (obj == null || !obj.isDictionary())
+                continue;
+            PdfDictionary dic = (PdfDictionary)obj;
+            if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
+                continue;
+            if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
+                || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
+                || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
+                String s = getSubsetPrefix(dic);
+                if (s == null)
+                    continue;
+                String ns = BaseFont.createSubsetPrefix() + s.substring(7);
+                PdfName newName = new PdfName(ns);
+                dic.put(PdfName.BASEFONT, newName);
+                setXrefPartialObject(k, dic);
+                ++total;
+                PdfDictionary fd = (PdfDictionary)getPdfObject(dic.get(PdfName.FONTDESCRIPTOR));
+                if (fd == null)
+                    continue;
+                fd.put(PdfName.FONTNAME, newName);
+            }
+            else if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE0)) {
+                String s = getSubsetPrefix(dic);
+                PdfArray arr = (PdfArray)getPdfObject(dic.get(PdfName.DESCENDANTFONTS));
+                if (arr == null)
+                    continue;
+                ArrayList list = arr.getArrayList();
+                if (list.size() == 0)
+                    continue;
+                PdfDictionary desc = (PdfDictionary)getPdfObject((PdfObject)list.get(0));
+                String sde = getSubsetPrefix(desc);
+                if (sde == null)
+                    continue;
+                String ns = BaseFont.createSubsetPrefix();
+                if (s != null)
+                    dic.put(PdfName.BASEFONT, new PdfName(ns + s.substring(7)));
+                setXrefPartialObject(k, dic);
+                PdfName newName = new PdfName(ns + sde.substring(7));
+                desc.put(PdfName.BASEFONT, newName);
+                ++total;
+                PdfDictionary fd = (PdfDictionary)getPdfObject(desc.get(PdfName.FONTDESCRIPTOR));
+                if (fd == null)
+                    continue;
+                fd.put(PdfName.FONTNAME, newName);
+            }
+        }
+        return total;
+    }
+    
+    /** Finds all the fonts not subset but embedded and marks them as subset.
+     * @return the number of fonts altered
+     */    
+    public int createFakeFontSubsets() {
+        int total = 0;
+        for (int k = 1; k < xrefObj.size(); ++k) {
+            PdfObject obj = getPdfObjectRelease(k);
+            if (obj == null || !obj.isDictionary())
+                continue;
+            PdfDictionary dic = (PdfDictionary)obj;
+            if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
+                continue;
+            if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
+                || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
+                || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
+                String s = getSubsetPrefix(dic);
+                if (s != null)
+                    continue;
+                s = getFontName(dic);
+                if (s == null)
+                    continue;
+                String ns = BaseFont.createSubsetPrefix() + s;
+                PdfDictionary fd = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.FONTDESCRIPTOR));
+                if (fd == null)
+                    continue;
+                if (fd.get(PdfName.FONTFILE) == null && fd.get(PdfName.FONTFILE2) == null
+                    && fd.get(PdfName.FONTFILE3) == null)
+                    continue;
+                fd = (PdfDictionary)getPdfObject(dic.get(PdfName.FONTDESCRIPTOR));
+                PdfName newName = new PdfName(ns);
+                dic.put(PdfName.BASEFONT, newName);
+                fd.put(PdfName.FONTNAME, newName);
+                setXrefPartialObject(k, dic);
+                ++total;
+            }
+        }
+        return total;
+    }
+    
+    private static PdfArray getNameArray(PdfObject obj) {
+        if (obj == null)
+            return null;
+        obj = getPdfObjectRelease(obj);
+        if (obj.isArray())
+            return (PdfArray)obj;
+        else if (obj.isDictionary()) {
+            PdfObject arr2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.D));
+            if (arr2 != null && arr2.isArray())
+                return (PdfArray)arr2;
+        }
+        return null;
+    }
+
+    /**
+     * Gets all the named destinations as an <CODE>HashMap</CODE>. The key is the name
+     * and the value is the destinations array.
+     * @return gets all the named destinations
+     */    
+    public HashMap getNamedDestination() {
+        HashMap names = getNamedDestinationFromNames();
+        names.putAll(getNamedDestinationFromStrings());
+        return names;
+    }
+    
+    /**
+     * Gets the named destinations from the /Dests key in the catalog as an <CODE>HashMap</CODE>. The key is the name
+     * and the value is the destinations array.
+     * @return gets the named destinations
+     */    
+    public HashMap getNamedDestinationFromNames() {
+        HashMap names = new HashMap();
+        if (catalog.get(PdfName.DESTS) != null) {
+            PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.DESTS));
+            Set keys = dic.getKeys();
+            for (Iterator it = keys.iterator(); it.hasNext();) {
+                PdfName key = (PdfName)it.next();
+                String name = PdfName.decodeName(key.toString());
+                PdfArray arr = getNameArray(dic.get(key));
+                if (arr != null)
+                    names.put(name, arr);
+            }
+        }
+        return names;
+    }
+
+    /**
+     * Gets the named destinations from the /Names key in the catalog as an <CODE>HashMap</CODE>. The key is the name
+     * and the value is the destinations array.
+     * @return gets the named destinations
+     */    
+    public HashMap getNamedDestinationFromStrings() {
+        if (catalog.get(PdfName.NAMES) != null) {
+            PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
+            dic = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.DESTS));
+            if (dic != null) {
+                HashMap names = PdfNameTree.readTree(dic);
+                for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+                    Map.Entry entry = (Map.Entry)it.next();
+                    PdfArray arr = getNameArray((PdfObject)entry.getValue());
+                    if (arr != null)
+                        entry.setValue(arr);
+                    else
+                        it.remove();
+                }
+                return names;
+            }
+        }
+        return new HashMap();
+    }
+    
+    private boolean replaceNamedDestination(PdfObject obj, HashMap names) {
+        obj = getPdfObject(obj);
+        int objIdx = lastXrefPartial;
+        releaseLastXrefPartial();
+        if (obj != null && obj.isDictionary()) {
+            PdfObject ob2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.DEST));
+            String name = null;
+            if (ob2 != null) {
+                if (ob2.isName())
+                    name = PdfName.decodeName(ob2.toString());
+                else if (ob2.isString())
+                    name = ob2.toString();
+                PdfArray dest = (PdfArray)names.get(name);
+                if (dest != null) {
+                    ((PdfDictionary)obj).put(PdfName.DEST, dest);
+                    setXrefPartialObject(objIdx, obj);
+                    return true;
+                }
+            }
+            else if ((ob2 = getPdfObject(((PdfDictionary)obj).get(PdfName.A))) != null) {
+                int obj2Idx = lastXrefPartial;
+                releaseLastXrefPartial();
+                PdfDictionary dic = (PdfDictionary)ob2;
+                PdfName type = (PdfName)getPdfObjectRelease(dic.get(PdfName.S));
+                if (PdfName.GOTO.equals(type)) {
+                    PdfObject ob3 = getPdfObjectRelease(dic.get(PdfName.D));
+                    if (ob3.isName())
+                        name = PdfName.decodeName(ob3.toString());
+                    else if (ob3.isString())
+                        name = ob3.toString();
+                    PdfArray dest = (PdfArray)names.get(name);
+                    if (dest != null) {
+                        dic.put(PdfName.D, dest);
+                        setXrefPartialObject(obj2Idx, ob2);
+                        setXrefPartialObject(objIdx, obj);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Removes all the fields from the document.
+     */    
+    public void removeFields() {
+        pageRefs.resetReleasePage();
+        for (int k = 1; k <= pageRefs.size(); ++k) {
+            PdfDictionary page = pageRefs.getPageN(k);
+            PdfArray annots = (PdfArray)getPdfObject(page.get(PdfName.ANNOTS));
+            if (annots == null) {
+                pageRefs.releasePage(k);
+                continue;
+            }
+            ArrayList arr = annots.getArrayList();
+            int startSize = arr.size();
+            for (int j = 0; j < arr.size(); ++j) {
+                PdfDictionary annot = (PdfDictionary)getPdfObjectRelease((PdfObject)arr.get(j));
+                if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE)))
+                    arr.remove(j--);
+            }
+            if (arr.isEmpty())
+                page.remove(PdfName.ANNOTS);
+            else
+                pageRefs.releasePage(k);
+        }
+        catalog.remove(PdfName.ACROFORM);
+        pageRefs.resetReleasePage();
+    }
+    
+    /**
+     * Removes all the annotations and fields from the document.
+     */    
+    public void removeAnnotations() {
+        pageRefs.resetReleasePage();
+        for (int k = 1; k <= pageRefs.size(); ++k) {
+            PdfDictionary page = pageRefs.getPageN(k);
+            if (page.get(PdfName.ANNOTS) == null)
+                pageRefs.releasePage(k);
+            else
+                page.remove(PdfName.ANNOTS);
+        }
+        catalog.remove(PdfName.ACROFORM);
+        pageRefs.resetReleasePage();
+    }
+    
+    private void iterateBookmarks(PdfObject outlineRef, HashMap names) {
+        while (outlineRef != null) {
+            replaceNamedDestination(outlineRef, names);
+            PdfDictionary outline = (PdfDictionary)getPdfObjectRelease(outlineRef);
+            PdfObject first = outline.get(PdfName.FIRST);
+            if (first != null) {
+                iterateBookmarks(first, names);
+            }
+            outlineRef = outline.get(PdfName.NEXT);
+        }
+    }
+    
+    /** Replaces all the local named links with the actual destinations. */    
+    public void consolidateNamedDestinations() {
+        if (consolidateNamedDestinations)
+            return;
+        consolidateNamedDestinations = true;
+        HashMap names = getNamedDestination();
+        if (names.size() == 0)
+            return;
+        for (int k = 1; k <= pageRefs.size(); ++k) {
+            PdfDictionary page = pageRefs.getPageN(k);
+            PdfObject annotsRef;
+            PdfArray annots = (PdfArray)getPdfObject(annotsRef = page.get(PdfName.ANNOTS));
+            int annotIdx = lastXrefPartial;
+            releaseLastXrefPartial();
+            if (annots == null) {
+                pageRefs.releasePage(k);
+                continue;
+            }
+            ArrayList list = annots.getArrayList();
+            boolean commitAnnots = false;
+            for (int an = 0; an < list.size(); ++an) {
+                PdfObject objRef = (PdfObject)list.get(an);
+                if (replaceNamedDestination(objRef, names) && !objRef.isIndirect())
+                    commitAnnots = true;
+            }
+            if (commitAnnots)
+                setXrefPartialObject(annotIdx,  annots);
+            if (!commitAnnots || annotsRef.isIndirect())
+                pageRefs.releasePage(k);
+        }
+        PdfDictionary outlines = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
+        if (outlines == null)
+            return;
+        iterateBookmarks(outlines.get(PdfName.FIRST), names);
+    }
+    
+    protected static PdfDictionary duplicatePdfDictionary(PdfDictionary original, PdfDictionary copy, PdfReader newReader) {
+        if (copy == null)
+            copy = new PdfDictionary();
+        for (Iterator it = original.getKeys().iterator(); it.hasNext();) {
+            PdfName key = (PdfName)it.next();
+            copy.put(key, duplicatePdfObject(original.get(key), newReader));
+        }
+        return copy;
+    }
+    
+    protected static PdfObject duplicatePdfObject(PdfObject original, PdfReader newReader) {
+        if (original == null)
+            return null;
+        switch (original.type()) {
+            case PdfObject.DICTIONARY: {
+                return duplicatePdfDictionary((PdfDictionary)original, null, newReader);
+            }
+            case PdfObject.STREAM: {
+                PRStream org = (PRStream)original;
+                PRStream stream = new PRStream(org, null, newReader);
+                duplicatePdfDictionary(org, stream, newReader);
+                return stream;
+            }
+            case PdfObject.ARRAY: {
+                ArrayList list = ((PdfArray)original).getArrayList();
+                PdfArray arr = new PdfArray();
+                for (Iterator it = list.iterator(); it.hasNext();) {
+                    arr.add(duplicatePdfObject((PdfObject)it.next(), newReader));
+                }
+                return arr;
+            }
+            case PdfObject.INDIRECT: {
+                PRIndirectReference org = (PRIndirectReference)original;
+                return new PRIndirectReference(newReader, org.getNumber(), org.getGeneration());
+            }
+            default:
+                return original;
+        }
+    }
+    
+    public void close() {
+        if (!partial)
+            return;
+        try {
+            tokens.close();
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    protected void removeUnusedNode(PdfObject obj, boolean hits[]) {
+        if (obj == null)
+            return;
+        switch (obj.type()) {
+            case PdfObject.DICTIONARY: 
+            case PdfObject.STREAM: {
+                PdfDictionary dic = (PdfDictionary)obj;
+                for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+                    PdfName key = (PdfName)it.next();
+                    PdfObject v = dic.get(key);
+                    if (v.isIndirect()) {
+                        int num = ((PRIndirectReference)v).getNumber();
+                        if (num >= xrefObj.size() || xrefObj.get(num) == null) {
+                            dic.put(key, PdfNull.PDFNULL);
+                            continue;
+                        }
+                    }
+                    removeUnusedNode(v, hits);
+                }
+                break;
+            }
+            case PdfObject.ARRAY: {
+                ArrayList list = ((PdfArray)obj).getArrayList();
+                for (int k = 0; k < list.size(); ++k) {
+                    PdfObject v = (PdfObject)list.get(k);
+                    if (v.isIndirect()) {
+                        int num = ((PRIndirectReference)v).getNumber();
+                        if (xrefObj.get(num) == null) {
+                            list.set(k, PdfNull.PDFNULL);
+                            continue;
+                        }
+                    }
+                    removeUnusedNode(v, hits);
+                }
+                break;
+            }
+            case PdfObject.INDIRECT: {
+                PRIndirectReference ref = (PRIndirectReference)obj;
+                int num = ref.getNumber();
+                if (!hits[num]) {
+                    hits[num] = true;
+                    removeUnusedNode(getPdfObjectRelease(ref), hits);
+                }
+            }
+        }
+    }
+    
+    /** Removes all the unreachable objects.
+     * @return the number of indirect objects removed
+     */    
+    public int removeUnusedObjects() {
+        boolean hits[] = new boolean[xrefObj.size()];
+        removeUnusedNode(trailer, hits);
+        int total = 0;
+        if (partial) {
+            for (int k = 1; k < hits.length; ++k) {
+                if (!hits[k]) {
+                    xref[k * 2] = -1;
+                    xref[k * 2 + 1] = 0;
+                    xrefObj.set(k, null);
+                    ++total;
+                }
+            }
+        }
+        else {
+            for (int k = 1; k < hits.length; ++k) {
+                if (!hits[k]) {
+                    xrefObj.set(k, null);
+                    ++total;
+                }
+            }
+        }
+        return total;
+    }
+    
+    /** Gets a read-only version of <CODE>AcroFields</CODE>.
+     * @return a read-only version of <CODE>AcroFields</CODE>
+	 * Removed for Mesquite Support 25 September 2005 P. E. Midford
+     */    
+//    public AcroFields getAcroFields() {
+//        return new AcroFields(this, null);
+//    }
+    
+    /**
+     * Gets the global document JavaScript.
+     * @param file the document file
+     * @throws IOException on error
+     * @return the global document JavaScript
+     */    
+    public String getJavaScript(RandomAccessFileOrArray file) throws IOException {
+        PdfDictionary names = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
+        if (names == null)
+            return null;
+        PdfDictionary js = (PdfDictionary)getPdfObjectRelease(names.get(PdfName.JAVASCRIPT));
+        if (js == null)
+            return null;
+        HashMap jscript = PdfNameTree.readTree(js);
+        String sortedNames[] = new String[jscript.size()];
+        sortedNames = (String[])jscript.keySet().toArray(sortedNames);
+        Arrays.sort(sortedNames, new StringCompare());
+        StringBuffer buf = new StringBuffer();
+        for (int k = 0; k < sortedNames.length; ++k) {
+            PdfDictionary j = (PdfDictionary)getPdfObjectRelease((PdfIndirectReference)jscript.get(sortedNames[k]));
+            if (j == null)
+                continue;
+            PdfObject obj = getPdfObjectRelease(j.get(PdfName.JS));
+            if (obj.isString())
+                buf.append(((PdfString)obj).toUnicodeString()).append('\n');
+            else if (obj.isStream()) {
+                byte bytes[] = getStreamBytes((PRStream)obj, file);
+                if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255)
+                    buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE));
+                else
+                    buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING));
+                buf.append('\n');    
+            }            
+        }
+        return buf.toString();
+    }
+    
+    /**
+     * Gets the global document JavaScript.
+     * @throws IOException on error
+     * @return the global document JavaScript
+     */    
+    public String getJavaScript() throws IOException {
+        RandomAccessFileOrArray rf = getSafeFile();
+        try {
+            rf.reOpen();
+            return getJavaScript(rf);
+        }
+        finally {
+            try{rf.close();}catch(Exception e){}
+        }
+    }
+    
+    /**
+     * Selects the pages to keep in the document. The pages are described as
+     * ranges. The page ordering can be changed but
+     * no page repetitions are allowed.
+     * @param ranges the comma separated ranges as described in {@link SequenceList}
+     */    
+    public void selectPages(String ranges) {
+        selectPages(SequenceList.expand(ranges, getNumberOfPages()));
+    }
+    
+    /**
+     * Selects the pages to keep in the document. The pages are described as a
+     * <CODE>List</CODE> of <CODE>Integer</CODE>. The page ordering can be changed but
+     * no page repetitions are allowed.
+     * @param pagesToKeep the pages to keep in the document
+     */    
+    public void selectPages(List pagesToKeep) {
+        throw new UnsupportedOperationException("Later.");
+/*
+        IntHashtable pg = new IntHashtable();
+        ArrayList finalPages = new ArrayList();
+        for (Iterator it = pagesToKeep.iterator(); it.hasNext();) {
+            Integer pi = (Integer)it.next();
+            int p = pi.intValue();
+            if (p >= 1 && p <= pages.size() && pg.put(p, 1) == 0)
+                finalPages.add(pi);
+        }
+        PRIndirectReference parent = (PRIndirectReference)catalog.get(PdfName.PAGES);
+        PdfDictionary topPages = (PdfDictionary)getPdfObject(parent);
+        PRIndirectReference newPageRefs[] = new PRIndirectReference[finalPages.size()];
+        PdfDictionary newPages[] = new PdfDictionary[finalPages.size()];
+        topPages.put(PdfName.COUNT, new PdfNumber(finalPages.size()));
+        PdfArray kids = new PdfArray();
+        for (int k = 0; k < finalPages.size(); ++k) {
+            int p = ((Integer)finalPages.get(k)).intValue() - 1;
+            kids.add(newPageRefs[k] = (PRIndirectReference)pageRefs.get(p));
+            newPages[k] = (PdfDictionary)pages.get(p);
+            newPages[k].put(PdfName.PARENT, parent);
+            pageRefs.set(p, null);
+        }
+        topPages.put(PdfName.KIDS, kids);
+        AcroFields af = getAcroFields();
+        for (int k = 0; k < pageRefs.size(); ++k) {
+            PRIndirectReference ref = (PRIndirectReference)pageRefs.get(k);
+            if (ref != null) {
+                af.removeFieldsFromPage(k + 1);
+                xrefObj.set(ref.getNumber(), null);
+            }
+        }
+        pages = new ArrayList(Arrays.asList(newPages));
+        pageRefs = new ArrayList(Arrays.asList(newPageRefs));
+        removeUnusedObjects();*/
+    }
+
+    public static void setViewerPreferences(int preferences, PdfDictionary catalog) {
+        catalog.remove(PdfName.PAGELAYOUT);
+        catalog.remove(PdfName.PAGEMODE);
+        catalog.remove(PdfName.VIEWERPREFERENCES);
+        if ((preferences & PdfWriter.PageLayoutSinglePage) != 0)
+            catalog.put(PdfName.PAGELAYOUT, PdfName.SINGLEPAGE);
+        else if ((preferences & PdfWriter.PageLayoutOneColumn) != 0)
+            catalog.put(PdfName.PAGELAYOUT, PdfName.ONECOLUMN);
+        else if ((preferences & PdfWriter.PageLayoutTwoColumnLeft) != 0)
+            catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNLEFT);
+        else if ((preferences & PdfWriter.PageLayoutTwoColumnRight) != 0)
+            catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNRIGHT);
+        if ((preferences & PdfWriter.PageModeUseNone) != 0)
+            catalog.put(PdfName.PAGEMODE, PdfName.USENONE);
+        else if ((preferences & PdfWriter.PageModeUseOutlines) != 0)
+            catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
+        else if ((preferences & PdfWriter.PageModeUseThumbs) != 0)
+            catalog.put(PdfName.PAGEMODE, PdfName.USETHUMBS);
+        else if ((preferences & PdfWriter.PageModeFullScreen) != 0)
+            catalog.put(PdfName.PAGEMODE, PdfName.FULLSCREEN);
+        else if ((preferences & PdfWriter.PageModeUseOC) != 0)
+            catalog.put(PdfName.PAGEMODE, PdfName.USEOC);
+        if ((preferences & PdfWriter.ViewerPreferencesMask) == 0)
+            return;
+        PdfDictionary vp = new PdfDictionary();
+        if ((preferences & PdfWriter.HideToolbar) != 0)
+            vp.put(PdfName.HIDETOOLBAR, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.HideMenubar) != 0)
+            vp.put(PdfName.HIDEMENUBAR, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.HideWindowUI) != 0)
+            vp.put(PdfName.HIDEWINDOWUI, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.FitWindow) != 0)
+            vp.put(PdfName.FITWINDOW, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.CenterWindow) != 0)
+            vp.put(PdfName.CENTERWINDOW, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.DisplayDocTitle) != 0)
+            vp.put(PdfName.DISPLAYDOCTITLE, PdfBoolean.PDFTRUE);
+        if ((preferences & PdfWriter.NonFullScreenPageModeUseNone) != 0)
+            vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USENONE);
+        else if ((preferences & PdfWriter.NonFullScreenPageModeUseOutlines) != 0)
+            vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOUTLINES);
+        else if ((preferences & PdfWriter.NonFullScreenPageModeUseThumbs) != 0)
+            vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USETHUMBS);
+        else if ((preferences & PdfWriter.NonFullScreenPageModeUseOC) != 0)
+            vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOC);
+        if ((preferences & PdfWriter.DirectionL2R) != 0)
+            vp.put(PdfName.DIRECTION, PdfName.L2R);
+        else if ((preferences & PdfWriter.DirectionR2L) != 0)
+            vp.put(PdfName.DIRECTION, PdfName.R2L);
+        if ((preferences & PdfWriter.PrintScalingNone) != 0)
+            vp.put(PdfName.PRINTSCALING, PdfName.NONE);
+        catalog.put(PdfName.VIEWERPREFERENCES, vp);
+    }
+
+    public void setViewerPreferences(int preferences) {
+        setViewerPreferences(preferences, catalog);
+    }
+    
+    public int getViewerPreferences() {
+        int prefs = 0;
+        PdfName name = null;
+        PdfObject obj = getPdfObjectRelease(catalog.get(PdfName.PAGELAYOUT));
+        if (obj != null && obj.isName()) {
+            name = (PdfName)obj;
+            if (name.equals(PdfName.SINGLEPAGE))
+                prefs |= PdfWriter.PageLayoutSinglePage;
+            else if (name.equals(PdfName.ONECOLUMN))
+                prefs |= PdfWriter.PageLayoutOneColumn;
+            else if (name.equals(PdfName.TWOCOLUMNLEFT))
+                prefs |= PdfWriter.PageLayoutTwoColumnLeft;
+            else if (name.equals(PdfName.TWOCOLUMNRIGHT))
+                prefs |= PdfWriter.PageLayoutTwoColumnRight;
+        }
+        obj = getPdfObjectRelease(catalog.get(PdfName.PAGEMODE));
+        if (obj != null && obj.isName()) {
+            name = (PdfName)obj;
+            if (name.equals(PdfName.USENONE))
+                prefs |= PdfWriter.PageModeUseNone;
+            else if (name.equals(PdfName.USEOUTLINES))
+                prefs |= PdfWriter.PageModeUseOutlines;
+            else if (name.equals(PdfName.USETHUMBS))
+                prefs |= PdfWriter.PageModeUseThumbs;
+            else if (name.equals(PdfName.USEOC))
+                prefs |= PdfWriter.PageModeUseOC;
+        }
+        obj = getPdfObjectRelease(catalog.get(PdfName.VIEWERPREFERENCES));
+        if (obj == null || !obj.isDictionary())
+            return prefs;
+        PdfDictionary vp = (PdfDictionary)obj;
+        for (int k = 0; k < vpnames.length; ++k) {
+            obj = getPdfObject(vp.get(vpnames[k]));
+            if (obj != null && "true".equals(obj.toString()))
+                prefs |= vpints[k];
+        }
+        obj = getPdfObjectRelease(vp.get(PdfName.PRINTSCALING));
+        if (PdfName.NONE.equals(obj))
+            prefs |= PdfWriter.PrintScalingNone;
+        obj = getPdfObjectRelease(vp.get(PdfName.NONFULLSCREENPAGEMODE));
+        if (obj != null && obj.isName()) {
+            name = (PdfName)obj;
+            if (name.equals(PdfName.USENONE))
+                prefs |= PdfWriter.NonFullScreenPageModeUseNone;
+            else if (name.equals(PdfName.USEOUTLINES))
+                prefs |= PdfWriter.NonFullScreenPageModeUseOutlines;
+            else if (name.equals(PdfName.USETHUMBS))
+                prefs |= PdfWriter.NonFullScreenPageModeUseThumbs;
+            else if (name.equals(PdfName.USEOC))
+                prefs |= PdfWriter.NonFullScreenPageModeUseOC;
+        }
+        obj = getPdfObjectRelease(vp.get(PdfName.DIRECTION));
+        if (obj != null && obj.isName()) {
+            name = (PdfName)obj;
+            if (name.equals(PdfName.L2R))
+                prefs |= PdfWriter.DirectionL2R;
+            else if (name.equals(PdfName.R2L))
+                prefs |= PdfWriter.DirectionR2L;
+        }
+        return prefs;
+    }
+    
+    /**
+     * Getter for property appendable.
+     * @return Value of property appendable.
+     */
+    public boolean isAppendable() {
+        return this.appendable;
+    }
+    
+    /**
+     * Setter for property appendable.
+     * @param appendable New value of property appendable.
+     */
+    public void setAppendable(boolean appendable) {
+        this.appendable = appendable;
+        if (appendable)
+            getPdfObject(trailer.get(PdfName.ROOT));
+    }
+    
+    /**
+     * Getter for property newXrefType.
+     * @return Value of property newXrefType.
+     */
+    public boolean isNewXrefType() {
+        return newXrefType;
+    }    
+    
+    /**
+     * Getter for property fileLength.
+     * @return Value of property fileLength.
+     */
+    public int getFileLength() {
+        return fileLength;
+    }
+    
+    /**
+     * Getter for property hybridXref.
+     * @return Value of property hybridXref.
+     */
+    public boolean isHybridXref() {
+        return hybridXref;
+    }
+    
+    static class PageRefs {
+        private PdfReader reader;
+        private IntHashtable refsp;
+        private ArrayList refsn;
+        private ArrayList pageInh;
+        private int lastPageRead = -1;
+        private int sizep;
+        
+        private PageRefs(PdfReader reader) throws IOException {
+            this.reader = reader;
+            if (reader.partial) {
+                refsp = new IntHashtable();
+                PdfNumber npages = (PdfNumber)PdfReader.getPdfObjectRelease(reader.rootPages.get(PdfName.COUNT));
+                sizep = npages.intValue();
+            }
+            else {
+                readPages();
+            }
+        }
+        
+        PageRefs(PageRefs other, PdfReader reader) {
+            this.reader = reader;
+            this.sizep = other.sizep;
+            if (refsn != null) {
+                refsn = new ArrayList(other.refsn);
+                for (int k = 0; k < refsn.size(); ++k) {
+                    refsn.set(k, duplicatePdfObject((PdfObject)refsn.get(k), reader));
+                }
+            }
+            else
+                this.refsp = (IntHashtable)other.refsp.clone();
+        }
+        
+        int size() {
+            if (refsn != null)
+                return refsn.size();
+            else
+                return sizep;
+        }
+        
+        void readPages() throws IOException {
+            if (refsn != null)
+                return;
+            refsp = null;
+            refsn = new ArrayList();
+            pageInh = new ArrayList();
+            iteratePages((PRIndirectReference)reader.catalog.get(PdfName.PAGES));
+            pageInh = null;
+            reader.rootPages.put(PdfName.COUNT, new PdfNumber(refsn.size()));
+        }
+        
+        void reReadPages() throws IOException {
+            refsn = null;
+            readPages();
+        }
+        
+        /** Gets the dictionary that represents a page.
+         * @param pageNum the page number. 1 is the first
+         * @return the page dictionary
+         */    
+        public PdfDictionary getPageN(int pageNum) {
+            PRIndirectReference ref = getPageOrigRef(pageNum);
+            return (PdfDictionary)PdfReader.getPdfObject(ref);
+        }
+
+        public PdfDictionary getPageNRelease(int pageNum) {
+            PdfDictionary page = getPageN(pageNum);
+            releasePage(pageNum);
+            return page;
+        }
+
+        public PRIndirectReference getPageOrigRefRelease(int pageNum) {
+            PRIndirectReference ref = getPageOrigRef(pageNum);
+            releasePage(pageNum);
+            return ref;
+        }
+        
+        /** Gets the page reference to this page.
+         * @param pageNum the page number. 1 is the first
+         * @return the page reference
+         */    
+        public PRIndirectReference getPageOrigRef(int pageNum) {
+            try {
+                --pageNum;
+                if (pageNum < 0 || pageNum >= size())
+                    return null;
+                if (refsn != null)
+                    return (PRIndirectReference)refsn.get(pageNum);
+                else {
+                    int n = refsp.get(pageNum);
+                    if (n == 0) {
+                        PRIndirectReference ref = getSinglePage(pageNum);
+                        if (reader.lastXrefPartial == -1)
+                            lastPageRead = -1;
+                        else
+                            lastPageRead = pageNum;
+                        reader.lastXrefPartial = -1;
+                        refsp.put(pageNum, ref.getNumber());
+                        return ref;
+                    }
+                    else {
+                        if (lastPageRead != pageNum)
+                            lastPageRead = -1;
+                        return new PRIndirectReference(reader, n);
+                    }
+                }
+            }
+            catch (Exception e) {
+                throw new ExceptionConverter(e);
+            }
+        }
+        
+        public void releasePage(int pageNum) {
+            if (refsp == null)
+                return;
+            --pageNum;
+            if (pageNum < 0 || pageNum >= size())
+                return;
+            if (pageNum != lastPageRead)
+                return;
+            lastPageRead = -1;
+            reader.lastXrefPartial = refsp.get(pageNum);
+            reader.releaseLastXrefPartial();
+            refsp.remove(pageNum);
+        }
+        
+        public void resetReleasePage() {
+            if (refsp == null)
+                return;
+            lastPageRead = -1;
+        }
+        
+        void insertPage(int pageNum, PRIndirectReference ref) {
+            --pageNum;
+            if (refsn != null) {
+                if (pageNum >= refsn.size())
+                    refsn.add(ref);
+                else
+                    refsn.add(pageNum, ref);
+            }
+            else {
+                ++sizep;
+                lastPageRead = -1;
+                if (pageNum >= size()) {
+                    refsp.put(size(), ref.getNumber());
+                }
+                else {
+                    IntHashtable refs2 = new IntHashtable((refsp.size() + 1) * 2);
+                    for (Iterator it = refsp.getEntryIterator(); it.hasNext();) {
+                        IntHashtable.IntHashtableEntry entry = (IntHashtable.IntHashtableEntry)it.next();
+                        int p = entry.getKey();
+                        refs2.put(p >= pageNum ? p + 1 : p, entry.getValue());
+                    }
+                    refs2.put(pageNum, ref.getNumber());
+                    refsp = refs2;
+                }
+            }
+        }
+        
+        private void pushPageAttributes(PdfDictionary nodePages) {
+            PdfDictionary dic = new PdfDictionary();
+            if (pageInh.size() != 0) {
+                dic.putAll((PdfDictionary)pageInh.get(pageInh.size() - 1));
+            }
+            for (int k = 0; k < pageInhCandidates.length; ++k) {
+                PdfObject obj = nodePages.get(pageInhCandidates[k]);
+                if (obj != null)
+                    dic.put(pageInhCandidates[k], obj);
+            }
+            pageInh.add(dic);
+        }
+
+        private void popPageAttributes() {
+            pageInh.remove(pageInh.size() - 1);
+        }
+
+        private void iteratePages(PRIndirectReference rpage) throws IOException {
+            PdfDictionary page = (PdfDictionary)getPdfObject(rpage);
+            PdfArray kidsPR = (PdfArray)getPdfObject(page.get(PdfName.KIDS));
+            if (kidsPR == null) {
+                page.put(PdfName.TYPE, PdfName.PAGE);
+                PdfDictionary dic = (PdfDictionary)pageInh.get(pageInh.size() - 1);
+                PdfName key;
+                for (Iterator i = dic.getKeys().iterator(); i.hasNext();) {
+                    key = (PdfName)i.next();
+                    if (page.get(key) == null)
+                        page.put(key, dic.get(key));
+                }
+                if (page.get(PdfName.MEDIABOX) == null) {
+                    PdfArray arr = new PdfArray(new float[]{0,0,PageSize.LETTER.right(),PageSize.LETTER.top()});
+                    page.put(PdfName.MEDIABOX, arr);
+                }
+                refsn.add(rpage);
+            }
+            else {
+                page.put(PdfName.TYPE, PdfName.PAGES);
+                pushPageAttributes(page);
+                ArrayList kids = kidsPR.getArrayList();
+                for (int k = 0; k < kids.size(); ++k){
+                    iteratePages((PRIndirectReference)kids.get(k));
+                }
+                popPageAttributes();
+            }
+        }
+        
+        protected PRIndirectReference getSinglePage(int n) throws IOException {
+            PdfDictionary acc = new PdfDictionary();
+            PdfDictionary top = reader.rootPages;
+            int base = 0;
+            while (true) {
+                for (int k = 0; k < pageInhCandidates.length; ++k) {
+                    PdfObject obj = top.get(pageInhCandidates[k]);
+                    if (obj != null)
+                        acc.put(pageInhCandidates[k], obj);
+                }
+                PdfArray kids = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.KIDS));
+                for (Iterator it = kids.listIterator(); it.hasNext();) {
+                    PRIndirectReference ref = (PRIndirectReference)it.next();
+                    PdfDictionary dic = (PdfDictionary)getPdfObject(ref);
+                    int last = reader.lastXrefPartial;
+                    PdfObject count = getPdfObjectRelease(dic.get(PdfName.COUNT));
+                    reader.lastXrefPartial = last;
+                    int acn = 1;
+                    if (count != null && count.type() == PdfObject.NUMBER)
+                        acn = ((PdfNumber)count).intValue();
+                    if (n < base + acn) {
+                        if (count == null) {
+                            dic.mergeDifferent(acc);
+                            return ref;
+                        }
+                        reader.releaseLastXrefPartial();
+                        top = dic;
+                        break;
+                    }
+                    reader.releaseLastXrefPartial();
+                    base += acn;
+                }
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfReaderInstance.java b/LibrarySource/com/lowagie/text/pdf/PdfReaderInstance.java
new file mode 100644
index 0000000..ec0326d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfReaderInstance.java
@@ -0,0 +1,183 @@
+/*
+ * $Id: PdfReaderInstance.java,v 1.27 2003/05/02 09:01:27 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.*;
+/**
+ * Instance of PdfReader in each output document.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+class PdfReaderInstance {
+    static final PdfLiteral IDENTITYMATRIX = new PdfLiteral("[1 0 0 1 0 0]");
+    static final PdfNumber ONE = new PdfNumber(1);
+    int myXref[];
+    PdfReader reader;
+    RandomAccessFileOrArray file;
+    HashMap importedPages = new HashMap();
+    PdfWriter writer;
+    HashMap visited = new HashMap();
+    ArrayList nextRound = new ArrayList();
+    
+    PdfReaderInstance(PdfReader reader, PdfWriter writer) {
+        this.reader = reader;
+        this.writer = writer;
+        file = reader.getSafeFile();
+        myXref = new int[reader.getXrefSize()];
+    }
+    
+    PdfReader getReader() {
+        return reader;
+    }
+    
+    PdfImportedPage getImportedPage(int pageNumber) {
+        if (pageNumber < 1 || pageNumber > reader.getNumberOfPages())
+            throw new IllegalArgumentException("Invalid page number");
+        Integer i = new Integer(pageNumber);
+        PdfImportedPage pageT = (PdfImportedPage)importedPages.get(i);
+        if (pageT == null) {
+            pageT = new PdfImportedPage(this, writer, pageNumber);
+            importedPages.put(i, pageT);
+        }
+        return pageT;
+    }
+    
+    int getNewObjectNumber(int number, int generation) {
+        if (myXref[number] == 0) {
+            myXref[number] = writer.getIndirectReferenceNumber();
+            nextRound.add(new Integer(number));
+        }
+        return myXref[number];
+    }
+    
+    RandomAccessFileOrArray getReaderFile() {
+        return file;
+    }
+    
+    PdfObject getResources(int pageNumber) {
+        PdfObject obj = PdfReader.getPdfObjectRelease(reader.getPageNRelease(pageNumber).get(PdfName.RESOURCES));
+        return obj;
+    }
+    
+    
+    PdfStream getFormXObject(int pageNumber) throws IOException {
+        PdfDictionary page = reader.getPageNRelease(pageNumber);
+        PdfObject contents = PdfReader.getPdfObjectRelease(page.get(PdfName.CONTENTS));
+        PdfDictionary dic = new PdfDictionary();
+        byte bout[] = null;
+        ArrayList filters = null;
+        if (contents != null) {
+            if (contents.isStream())
+                dic.putAll((PRStream)contents);
+            else
+                bout = reader.getPageContent(pageNumber, file);
+        }
+        else
+            bout = new byte[0];
+        dic.put(PdfName.RESOURCES, PdfReader.getPdfObjectRelease(page.get(PdfName.RESOURCES)));
+        dic.put(PdfName.TYPE, PdfName.XOBJECT);
+        dic.put(PdfName.SUBTYPE, PdfName.FORM);
+        PdfImportedPage impPage = (PdfImportedPage)importedPages.get(new Integer(pageNumber));
+        dic.put(PdfName.BBOX, new PdfRectangle(impPage.getBoundingBox()));
+        PdfArray matrix = impPage.getMatrix();
+        if (matrix == null)
+            dic.put(PdfName.MATRIX, IDENTITYMATRIX);
+        else
+            dic.put(PdfName.MATRIX, matrix);
+        dic.put(PdfName.FORMTYPE, ONE);
+        PRStream stream;
+        if (bout == null) {
+            stream = new PRStream((PRStream)contents, dic);
+        }
+        else {
+            stream = new PRStream(reader, bout);
+            stream.putAll(dic);
+        }
+        return stream;
+    }
+    
+    void writeAllVisited() throws IOException {
+        while (nextRound.size() > 0) {
+            ArrayList vec = nextRound;
+            nextRound = new ArrayList();
+            for (int k = 0; k < vec.size(); ++k) {
+                Integer i = (Integer)vec.get(k);
+                if (!visited.containsKey(i)) {
+                    visited.put(i, null);
+                    int n = i.intValue();
+                    writer.addToBody(reader.getPdfObjectRelease(n), myXref[n]);
+                }
+            }
+        }
+    }
+    
+    void writeAllPages() throws IOException {
+        try {
+            file.reOpen();
+            for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
+                PdfImportedPage ip = (PdfImportedPage)it.next();
+                writer.addToBody(ip.getFormXObject(), ip.getIndirectReference());
+            }
+            writeAllVisited();
+        }
+        finally {
+            try {
+                reader.close();
+                file.close();
+            }
+            catch (Exception e) {
+                //Empty on purpose
+            }
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfRectangle.java b/LibrarySource/com/lowagie/text/pdf/PdfRectangle.java
new file mode 100644
index 0000000..3b0bade
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfRectangle.java
@@ -0,0 +1,277 @@
+/*
+ * $Id: PdfRectangle.java,v 1.26 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Rectangle;
+
+/**
+ * <CODE>PdfRectangle</CODE> is the PDF Rectangle object.
+ * <P>
+ * Rectangles are used to describe locations on the page and bounding boxes for several
+ * objects in PDF, such as fonts. A rectangle is represented as an <CODE>array</CODE> of
+ * four numbers, specifying the lower lef <I>x</I>, lower left <I>y</I>, upper right <I>x</I>,
+ * and upper right <I>y</I> coordinates of the rectangle, in that order.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.1 (page 183).
+ *
+ * @see		com.lowagie.text.Rectangle
+ * @see		PdfArray
+ */
+
+public class PdfRectangle extends PdfArray {
+    
+    // membervariables
+    
+/** lower left x */
+    private float llx = 0;
+    
+/** lower left y */
+    private float lly = 0;
+    
+/** upper right x */
+    private float urx = 0;
+    
+/** upper right y */
+    private float ury = 0;
+    
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfRectangle</CODE>-object.
+ *
+ * @param		llx			lower left x
+ * @param		lly			lower left y
+ * @param		urx			upper right x
+ * @param		ury			upper right y
+ *
+ * @since		rugPdf0.10
+ */
+    
+    public PdfRectangle(float llx, float lly, float urx, float ury, int rotation) {
+        super();
+        if (rotation == 90 || rotation == 270) {
+            this.llx = lly;
+            this.lly = llx;
+            this.urx = ury;
+            this.ury = urx;
+        }
+        else {
+            this.llx = llx;
+            this.lly = lly;
+            this.urx = urx;
+            this.ury = ury;
+        }
+        super.add(new PdfNumber(this.llx));
+        super.add(new PdfNumber(this.lly));
+        super.add(new PdfNumber(this.urx));
+        super.add(new PdfNumber(this.ury));
+    }
+
+    public PdfRectangle(float llx, float lly, float urx, float ury) {
+        this(llx, lly, urx, ury, 0);
+    }
+
+/**
+ * Constructs a <CODE>PdfRectangle</CODE>-object starting from the origin (0, 0).
+ *
+ * @param		urx			upper right x
+ * @param		ury			upper right y
+ */
+    
+    public PdfRectangle(float urx, float ury, int rotation) {
+        this(0, 0, urx, ury, rotation);
+    }
+
+    public PdfRectangle(float urx, float ury) {
+        this(0, 0, urx, ury, 0);
+    }
+    
+/**
+ * Constructs a <CODE>PdfRectangle</CODE>-object with a <CODE>Rectangle</CODE>-object.
+ *
+ * @param	rectangle	a <CODE>Rectangle</CODE>
+ */
+    
+    public PdfRectangle(Rectangle rectangle, int rotation) {
+        this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), rotation);
+    }
+    
+    public PdfRectangle(Rectangle rectangle) {
+        this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), 0);
+    }
+    
+    // methods
+    
+/**
+ * Overrides the <CODE>add</CODE>-method in <CODE>PdfArray</CODE> in order to prevent the adding of extra object to the array.
+ *
+ * @param		object			<CODE>PdfObject</CODE> to add (will not be added here)
+ * @return		<CODE>false</CODE>
+ */
+    
+    public boolean add(PdfObject object) {
+        return false;
+    }
+    
+/**
+ * Returns the lower left x-coordinate.
+ *
+ * @return		the lower left x-coordinaat
+ */
+    
+    public float left() {
+        return llx;
+    }
+    
+/**
+ * Returns the upper right x-coordinate.
+ *
+ * @return		the upper right x-coordinate
+ */
+    
+    public float right() {
+        return urx;
+    }
+    
+/**
+ * Returns the upper right y-coordinate.
+ *
+ * @return		the upper right y-coordinate
+ */
+    
+    public float top() {
+        return ury;
+    }
+    
+/**
+ * Returns the lower left y-coordinate.
+ *
+ * @return		the lower left y-coordinate
+ */
+    
+    public float bottom() {
+        return lly;
+    }
+    
+/**
+ * Returns the lower left x-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the lower left x-coordinate
+ */
+    
+    public float left(int margin) {
+        return llx + margin;
+    }
+    
+/**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the upper right x-coordinate
+ */
+    
+    public float right(int margin) {
+        return urx - margin;
+    }
+    
+/**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the upper right y-coordinate
+ */
+    
+    public float top(int margin) {
+        return ury - margin;
+    }
+    
+/**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param		margin		a margin
+ * @return		the lower left y-coordinate
+ */
+    
+    public float bottom(int margin) {
+        return lly + margin;
+    }
+    
+/**
+ * Returns the width of the rectangle.
+ *
+ * @return		a width
+ */
+    
+    public float width() {
+        return urx - llx;
+    }
+    
+/**
+ * Returns the height of the rectangle.
+ *
+ * @return		a height
+ */
+    
+    public float height() {
+        return ury - lly;
+    }
+    
+/**
+ * Swaps the values of urx and ury and of lly and llx in order to rotate the rectangle.
+ *
+ * @return		a <CODE>PdfRectangle</CODE>
+ */
+    
+    public PdfRectangle rotate() {
+        return new PdfRectangle(lly, llx, ury, urx, 0);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfRendition.java b/LibrarySource/com/lowagie/text/pdf/PdfRendition.java
new file mode 100644
index 0000000..f3acd02
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfRendition.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2003 Galo Gimenez
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+/**
+ * A Rendition dictionary (pdf spec 1.5)
+ */
+public class PdfRendition extends PdfDictionary {
+     PdfRendition(String file, PdfFileSpecification fs, String mimeType) throws IOException{
+         put(PdfName.S, new PdfName("MR"));
+         put(PdfName.N, new PdfString("Rendition for "+file));
+         put(PdfName.C, new PdfMediaClipData(file, fs, mimeType));
+     }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfResources.java b/LibrarySource/com/lowagie/text/pdf/PdfResources.java
new file mode 100644
index 0000000..65001de
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfResources.java
@@ -0,0 +1,91 @@
+/*
+ * $Id: PdfResources.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ * <CODE>PdfResources</CODE> is the PDF Resources-object.
+ * <P>
+ * The marking operations for drawing a page are stored in a stream that is the value of the
+ * <B>Contents</B> key in the Page object's dictionary. Each marking context includes a list
+ * of the named resources it uses. This resource list is stored as a dictionary that is the
+ * value of the context's <B>Resources</B> key, and it serves two functions: it enumerates
+ * the named resources in the contents stream, and it established the mapping from the names
+ * to the objects used by the marking operations.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.5 (page 195-197).
+ *
+ * @see		PdfPage
+ */
+
+class PdfResources extends PdfDictionary {
+    
+    // constructor
+    
+/**
+ * Constructs a PDF ResourcesDictionary.
+ */
+    
+    PdfResources() {
+        super();
+    }
+    
+    // methods
+    
+    void add(PdfName key, PdfDictionary resource) {
+        if (resource.size() == 0)
+            return;
+        PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObject(get(key));
+        if (dic == null)
+            put(key, resource);
+        else
+            dic.putAll(resource);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfShading.java b/LibrarySource/com/lowagie/text/pdf/PdfShading.java
new file mode 100644
index 0000000..5ce9f80
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfShading.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import java.io.IOException;
+/** Implements the shading dictionary (or stream).
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfShading {
+
+    protected PdfDictionary shading;
+    
+    protected PdfWriter writer;
+    
+    protected int shadingType;
+    
+    protected ColorDetails colorDetails;
+    
+    protected PdfName shadingName;
+    
+    protected PdfIndirectReference shadingReference;
+    
+    private Color cspace;
+    
+    /** Holds value of property bBox. */
+    protected float[] bBox;
+    
+    /** Holds value of property antiAlias. */
+    protected boolean antiAlias = false;
+    
+    /** Creates new PdfShading */
+    protected PdfShading(PdfWriter writer) {
+        this.writer = writer;
+    }
+    
+    protected void setColorSpace(Color color) {
+        cspace = color;
+        int type = ExtendedColor.getType(color);
+        PdfObject colorSpace = null;
+        switch (type) {
+            case ExtendedColor.TYPE_GRAY: {
+                colorSpace = PdfName.DEVICEGRAY;
+                break;
+            }
+            case ExtendedColor.TYPE_CMYK: {
+                colorSpace = PdfName.DEVICECMYK;
+                break;
+            }
+            case ExtendedColor.TYPE_SEPARATION: {
+                SpotColor spot = (SpotColor)color;
+                colorDetails = writer.addSimple(spot.getPdfSpotColor());
+                colorSpace = colorDetails.getIndirectReference();
+                break;
+            }
+            case ExtendedColor.TYPE_PATTERN:
+            case ExtendedColor.TYPE_SHADING: {
+                throwColorSpaceError();
+            }
+            default:
+                colorSpace = PdfName.DEVICERGB;
+                break;
+        }
+        shading.put(PdfName.COLORSPACE, colorSpace);
+    }
+    
+    Color getColorSpace() {
+        return cspace;
+    }
+    
+    public static void throwColorSpaceError() {
+        throw new IllegalArgumentException("A tiling or shading pattern cannot be used as a color space in a shading pattern");
+    }
+    
+    public static void checkCompatibleColors(Color c1, Color c2) {
+        int type1 = ExtendedColor.getType(c1);
+        int type2 = ExtendedColor.getType(c2);
+        if (type1 != type2)
+            throw new IllegalArgumentException("Both colors must be of the same type.");
+        if (type1 == ExtendedColor.TYPE_SEPARATION && ((SpotColor)c1).getPdfSpotColor() != ((SpotColor)c2).getPdfSpotColor())
+            throw new IllegalArgumentException("The spot color must be the same, only the tint can vary.");
+        if (type1 == ExtendedColor.TYPE_PATTERN || type1 == ExtendedColor.TYPE_SHADING)
+            throwColorSpaceError();
+    }
+    
+    public static float[] getColorArray(Color color) {
+        int type = ExtendedColor.getType(color);
+        switch (type) {
+            case ExtendedColor.TYPE_GRAY: {
+                return new float[]{((GrayColor)color).getGray()};
+            }
+            case ExtendedColor.TYPE_CMYK: {
+                CMYKColor cmyk = (CMYKColor)color;
+                return new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()};
+            }
+            case ExtendedColor.TYPE_SEPARATION: {
+                return new float[]{((SpotColor)color).getTint()};
+            }
+            case ExtendedColor.TYPE_RGB: {
+                return new float[]{color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f};
+            }
+        }
+        throwColorSpaceError();
+        return null;
+    }
+
+    public static PdfShading type1(PdfWriter writer, Color colorSpace, float domain[], float tMatrix[], PdfFunction function) {
+        PdfShading sp = new PdfShading(writer);
+        sp.shading = new PdfDictionary();
+        sp.shadingType = 1;
+        sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+        sp.setColorSpace(colorSpace);
+        if (domain != null)
+            sp.shading.put(PdfName.DOMAIN, new PdfArray(domain));
+        if (tMatrix != null)
+            sp.shading.put(PdfName.MATRIX, new PdfArray(tMatrix));
+        sp.shading.put(PdfName.FUNCTION, function.getReference());
+        return sp;
+    }
+    
+    public static PdfShading type2(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
+        PdfShading sp = new PdfShading(writer);
+        sp.shading = new PdfDictionary();
+        sp.shadingType = 2;
+        sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+        sp.setColorSpace(colorSpace);
+        sp.shading.put(PdfName.COORDS, new PdfArray(coords));
+        if (domain != null)
+            sp.shading.put(PdfName.DOMAIN, new PdfArray(domain));
+        sp.shading.put(PdfName.FUNCTION, function.getReference());
+        if (extend != null && (extend[0] || extend[1])) {
+            PdfArray array = new PdfArray(extend[0] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+            array.add(extend[1] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+            sp.shading.put(PdfName.EXTEND, array);
+        }
+        return sp;
+    }
+
+    public static PdfShading type3(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
+        PdfShading sp = type2(writer, colorSpace, coords, domain, function, extend);
+        sp.shadingType = 3;
+        sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+        return sp;
+    }
+    
+    public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
+        checkCompatibleColors(startColor, endColor);
+        PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
+            getColorArray(endColor), 1);
+        return type2(writer, startColor, new float[]{x0, y0, x1, y1}, null, function, new boolean[]{extendStart, extendEnd});
+    }
+    
+    public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor) {
+        return simpleAxial(writer, x0, y0, x1, y1, startColor, endColor, true, true);
+    }
+    
+    public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
+        checkCompatibleColors(startColor, endColor);
+        PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
+            getColorArray(endColor), 1);
+        return type3(writer, startColor, new float[]{x0, y0, r0, x1, y1, r1}, null, function, new boolean[]{extendStart, extendEnd});
+    }
+
+    public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor) {
+        return simpleRadial(writer, x0, y0, r0, x1, y1, r1, startColor, endColor, true, true);
+    }
+
+    PdfName getShadingName() {
+        return shadingName;
+    }
+    
+    PdfIndirectReference getShadingReference() {
+        if (shadingReference == null)
+            shadingReference = writer.getPdfIndirectReference();
+        return shadingReference;
+    }
+    
+    void setName(int number) {
+        shadingName = new PdfName("Sh" + number);
+    }
+    
+    void addToBody() throws IOException {
+        if (bBox != null)
+            shading.put(PdfName.BBOX, new PdfArray(bBox));
+        if (antiAlias)
+            shading.put(PdfName.ANTIALIAS, PdfBoolean.PDFTRUE);
+        writer.addToBody(shading, getShadingReference());
+    }
+    
+    PdfWriter getWriter() {
+        return writer;
+    }
+    
+    ColorDetails getColorDetails() {
+        return colorDetails;
+    }
+    
+    public float[] getBBox() {
+        return bBox;
+    }
+    
+    public void setBBox(float[] bBox) {
+        if (bBox.length != 4)
+            throw new IllegalArgumentException("BBox must be a 4 element array.");
+        this.bBox = bBox;
+    }
+    
+    public boolean isAntiAlias() {
+        return antiAlias;
+    }
+    
+    public void setAntiAlias(boolean antiAlias) {
+        this.antiAlias = antiAlias;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfShadingPattern.java b/LibrarySource/com/lowagie/text/pdf/PdfShadingPattern.java
new file mode 100644
index 0000000..8713101
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfShadingPattern.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+/** Implements the shading pattern dictionary.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfShadingPattern extends PdfDictionary {
+
+    protected PdfShading shading;
+    
+    protected PdfWriter writer;
+    
+    protected float matrix[] = {1, 0, 0, 1, 0, 0};
+    
+    protected PdfName patternName;
+
+    protected PdfIndirectReference patternReference;
+
+    /** Creates new PdfShadingPattern */
+    public PdfShadingPattern(PdfShading shading) {
+        writer = shading.getWriter();
+        put(PdfName.PATTERNTYPE, new PdfNumber(2));
+        this.shading = shading;
+    }
+        
+    PdfName getPatternName() {
+        return patternName;
+    }
+
+    PdfName getShadingName() {
+        return shading.getShadingName();
+    }
+    
+    PdfIndirectReference getPatternReference() {
+        if (patternReference == null)
+            patternReference = writer.getPdfIndirectReference();
+        return patternReference;
+    }
+    
+    PdfIndirectReference getShadingReference() {
+        return shading.getShadingReference();
+    }
+    
+    void setName(int number) {
+        patternName = new PdfName("P" + number);
+    }
+    
+    void addToBody() throws IOException {
+        put(PdfName.SHADING, getShadingReference());
+        put(PdfName.MATRIX, new PdfArray(matrix));
+        writer.addToBody(this, getPatternReference());
+    }
+    
+    public void setMatrix(float matrix[]) {
+        if (matrix.length != 6)
+            throw new RuntimeException("The matrix size must be 6.");
+        this.matrix = matrix;
+    }
+    
+    public float[] getMatrix() {
+        return matrix;
+    }
+    
+    PdfShading getShading() {
+        return shading;
+    }
+    
+    ColorDetails getColorDetails() {
+        return shading.getColorDetails();
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfSpotColor.java b/LibrarySource/com/lowagie/text/pdf/PdfSpotColor.java
new file mode 100644
index 0000000..2befdcb
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfSpotColor.java
@@ -0,0 +1,132 @@
+/*
+ * $Id: PdfSpotColor.java,v 1.45 2005/03/24 12:38:19 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import java.io.IOException;
+/**
+ * A <CODE>PdfSpotColor</CODE> defines a ColorSpace
+ *
+ * @see		PdfDictionary
+ */
+
+public class PdfSpotColor{
+    
+/*	The tint value */
+    protected float tint;
+    
+/**	The color name */
+    public PdfName name;
+    
+/** The alternative color space */
+    public Color altcs;
+    // constructors
+    
+    /**
+     * Constructs a new <CODE>PdfSpotColor</CODE>.
+     *
+     * @param		name		a String value
+     * @param		tint		a tint value between 0 and 1
+     * @param		altcs		a altnative colorspace value
+     */
+    
+    public PdfSpotColor(String name, float tint, Color altcs) {
+        this.name = new PdfName(name);
+        this.tint = tint;
+        this.altcs = altcs;
+    }
+    
+    /**
+     * Gets the tint of the SpotColor.
+     * @return a float
+     */
+    public float getTint() {
+        return tint;
+    }
+    
+    /**
+     * Gets the alternative ColorSpace.
+     * @return a Colot
+     */
+    public Color getAlternativeCS() {
+        return altcs;
+    }
+    
+    protected PdfObject getSpotObject(PdfWriter writer) throws IOException {
+        PdfArray array = new PdfArray(PdfName.SEPARATION);
+        array.add(name);
+        PdfFunction func = null;
+        if (altcs instanceof ExtendedColor) {
+            int type = ((ExtendedColor)altcs).type;
+            switch (type) {
+                case ExtendedColor.TYPE_GRAY:
+                    array.add(PdfName.DEVICEGRAY);
+                    func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0}, new float[]{((GrayColor)altcs).getGray()}, 1);
+                    break;
+                case ExtendedColor.TYPE_CMYK:
+                    array.add(PdfName.DEVICECMYK);
+                    CMYKColor cmyk = (CMYKColor)altcs;
+                    func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0, 0, 0, 0},
+                        new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()}, 1);
+                    break;
+                default:
+                    throw new RuntimeException("Only RGB, Gray and CMYK are supported as alternative color spaces.");
+            }
+        }
+        else {
+            array.add(PdfName.DEVICERGB);
+            func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0, 0, 0},
+                new float[]{(float)altcs.getRed() / 255, (float)altcs.getGreen() / 255, (float)altcs.getBlue() / 255}, 1);
+        }
+        array.add(func.getReference());
+        return array;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfStream.java b/LibrarySource/com/lowagie/text/pdf/PdfStream.java
new file mode 100644
index 0000000..f8a915c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfStream.java
@@ -0,0 +1,287 @@
+/*
+ * $Id: PdfStream.java,v 1.53 2004/12/14 15:15:59 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Deflater;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocWriter;
+import com.lowagie.text.ExceptionConverter;
+
+/**
+ * <CODE>PdfStream</CODE> is the Pdf stream object.
+ * <P>
+ * A stream, like a string, is a sequence of characters. However, an application can
+ * read a small portion of a stream at a time, while a string must be read in its entirety.
+ * For this reason, objects with potentially large amounts of data, such as images and
+ * page descriptions, are represented as streams.<BR>
+ * A stream consists of a dictionary that describes a sequence of characters, followed by
+ * the keyword <B>stream</B>, followed by zero or more lines of characters, followed by
+ * the keyword <B>endstream</B>.<BR>
+ * All streams must be <CODE>PdfIndirectObject</CODE>s. The stream dictionary must be a direct
+ * object. The keyword <B>stream</B> that follows the stream dictionary should be followed by
+ * a carriage return and linefeed or just a linefeed.<BR>
+ * Remark: In this version only the FLATEDECODE-filter is supported.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.8 (page 41-53).<BR>
+ *
+ * @see		PdfObject
+ * @see		PdfDictionary
+ */
+
+public class PdfStream extends PdfDictionary {
+    
+    // membervariables
+    
+/** is the stream compressed? */
+    protected boolean compressed = false;
+    
+    protected ByteArrayOutputStream streamBytes = null;
+    protected InputStream inputStream;
+    protected PdfIndirectReference ref;
+    protected int inputStreamLength = -1;
+    protected PdfWriter writer;
+        
+    static final byte STARTSTREAM[] = DocWriter.getISOBytes("stream\n");
+    static final byte ENDSTREAM[] = DocWriter.getISOBytes("\nendstream");
+    static final int SIZESTREAM = STARTSTREAM.length + ENDSTREAM.length;
+
+    // constructors
+    
+/**
+ * Constructs a <CODE>PdfStream</CODE>-object.
+ *
+ * @param		bytes			content of the new <CODE>PdfObject</CODE> as an array of <CODE>byte</CODE>.
+ */
+ 
+    public PdfStream(byte[] bytes) {
+        super();
+        type = STREAM;
+        this.bytes = bytes;
+        put(PdfName.LENGTH, new PdfNumber(bytes.length));
+    }
+  
+    /**
+     * Creates an efficient stream. No temporary array is ever created. The <CODE>InputStream</CODE>
+     * is totally consumed but is not closed. The general usage is:
+     * <p>
+     * <pre>
+     * InputStream in = ...;
+     * PdfStream stream = new PdfStream(in, writer);
+     * stream.flateCompress();
+     * writer.addToBody(stream);
+     * stream.writeLength();
+     * in.close();
+     * </pre>
+     * @param inputStream the data to write to this stream
+     * @param writer the <CODE>PdfWriter</CODE> for this stream
+     */    
+    public PdfStream(InputStream inputStream, PdfWriter writer) {
+        super();
+        type = STREAM;
+        this.inputStream = inputStream;
+        this.writer = writer;
+        ref = writer.getPdfIndirectReference();
+        put(PdfName.LENGTH, ref);
+    }
+  
+/**
+ * Constructs a <CODE>PdfStream</CODE>-object.
+ */
+    
+    protected PdfStream() {
+        super();
+        type = STREAM;
+    }
+    
+    /**
+     * Writes the stream length to the <CODE>PdfWriter</CODE>.
+     * <p>
+     * This method must be called and can only be called if the contructor {@link #PdfStream(InputStream,PdfWriter)}
+     * is used to create the stream.
+     * @throws IOException on error
+     * @see #PdfStream(InputStream,PdfWriter)
+     */
+    public void writeLength() throws IOException {
+        if (inputStream == null)
+            throw new UnsupportedOperationException("writeLength() can only be called in a contructed PdfStream(InputStream,PdfWriter).");
+        if (inputStreamLength == -1)
+            throw new IOException("writeLength() can only be called after output of the stream body.");
+        writer.addToBody(new PdfNumber(inputStreamLength), ref, false);
+    }
+    
+    /**
+     * Compresses the stream.
+     */
+    
+    public void flateCompress() {
+        if (!Document.compress)
+            return;
+        // check if the flateCompress-method has already been
+        if (compressed) {
+            return;
+        }
+        if (inputStream != null) {
+            compressed = true;
+            return;
+        }
+        // check if a filter already exists
+        PdfObject filter = get(PdfName.FILTER);
+        if (filter != null) {
+            if (filter.isName() && ((PdfName) filter).compareTo(PdfName.FLATEDECODE) == 0) {
+                return;
+            }
+            else if (filter.isArray() && ((PdfArray) filter).contains(PdfName.FLATEDECODE)) {
+                return;
+            }
+            else {
+                throw new RuntimeException("Stream could not be compressed: filter is not a name or array.");
+            }
+        }
+        try {
+            // compress
+            ByteArrayOutputStream stream = new ByteArrayOutputStream();
+            DeflaterOutputStream zip = new DeflaterOutputStream(stream);
+            if (streamBytes != null)
+                streamBytes.writeTo(zip);
+            else
+                zip.write(bytes);
+            zip.close();
+            // update the object
+            streamBytes = stream;
+            bytes = null;
+            put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
+            if (filter == null) {
+                put(PdfName.FILTER, PdfName.FLATEDECODE);
+            }
+            else {
+                PdfArray filters = new PdfArray(filter);
+                filters.add(PdfName.FLATEDECODE);
+                put(PdfName.FILTER, filters);
+            }
+            compressed = true;
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+
+//    public int getStreamLength(PdfWriter writer) {
+//        if (dicBytes == null)
+//            toPdf(writer);
+//        if (streamBytes != null)
+//            return streamBytes.size() + dicBytes.length + SIZESTREAM;
+//        else
+//            return bytes.length + dicBytes.length + SIZESTREAM;
+//    }
+    
+    protected void superToPdf(PdfWriter writer, OutputStream os) throws IOException {
+        super.toPdf(writer, os);
+    }
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        if (inputStream != null && compressed)
+            put(PdfName.FILTER, PdfName.FLATEDECODE);
+        superToPdf(writer, os);
+        os.write(STARTSTREAM);
+        PdfEncryption crypto = null;
+        if (writer != null)
+            crypto = writer.getEncryption();
+        if (crypto != null)
+            crypto.prepareKey();
+        if (inputStream != null) {
+            DeflaterOutputStream def = null;
+            PdfEncryptionStream encs = null;
+            OutputStreamCounter osc = new OutputStreamCounter(os);
+            OutputStream fout = osc;
+            if (crypto != null)
+                fout = encs = new PdfEncryptionStream(fout, crypto);
+            if (compressed)    
+                fout = def = new DeflaterOutputStream(fout, new Deflater(Deflater.BEST_COMPRESSION), 0x8000);
+            
+            byte buf[] = new byte[0x10000];
+            while (true) {
+                int n = inputStream.read(buf);
+                if (n <= 0)
+                    break;
+                fout.write(buf, 0, n);
+            }
+            if (def != null)
+                def.finish();
+            inputStreamLength = osc.getCounter();
+        }
+        else {
+            if (crypto == null) {
+                if (streamBytes != null)
+                    streamBytes.writeTo(os);
+                else
+                    os.write(bytes);
+            }
+            else {
+                byte b[];
+                if (streamBytes != null) {
+                    b = streamBytes.toByteArray();
+                    crypto.encryptRC4(b);
+                }
+                else {
+                    b = new byte[bytes.length];
+                    crypto.encryptRC4(bytes, b);
+                }
+                os.write(b);
+            }
+        }
+        os.write(ENDSTREAM);
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfString.java b/LibrarySource/com/lowagie/text/pdf/PdfString.java
new file mode 100644
index 0000000..ec521f4
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfString.java
@@ -0,0 +1,236 @@
+/*
+ * $Id: PdfString.java,v 1.26 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * A <CODE>PdfString</CODE>-class is the PDF-equivalent of a JAVA-<CODE>String</CODE>-object.
+ * <P>
+ * A string is a sequence of characters delimited by parenthesis. If a string is too long
+ * to be conveniently placed on a single line, it may be split across multiple lines by using
+ * the backslash character (\) at the end of a line to indicate that the string continues
+ * on the following line. Within a string, the backslash character is used as an escape to
+ * specify unbalanced parenthesis, non-printing ASCII characters, and the backslash character
+ * itself. Use of the \<I>ddd</I> escape sequence is the preferred way to represent characters
+ * outside the printable ASCII character set.<BR>
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.4 (page 37-39).
+ *
+ * @see		PdfObject
+ * @see		BadPdfFormatException
+ */
+
+public class PdfString extends PdfObject {
+    
+    // membervariables
+    
+    /** The value of this object. */
+    protected String value = NOTHING;
+    protected String originalValue = null;
+    
+    /** The encoding. */
+    protected String encoding = TEXT_PDFDOCENCODING;
+    protected int objNum = 0;
+    protected int objGen = 0;
+    protected boolean hexWriting = false;
+
+    // constructors
+    
+    /**
+     * Constructs an empty <CODE>PdfString</CODE>-object.
+     */
+    
+    public PdfString() {
+        super(STRING);
+    }
+    
+    /**
+     * Constructs a <CODE>PdfString</CODE>-object.
+     *
+     * @param		value		the content of the string
+     */
+    
+    public PdfString(String value) {
+        super(STRING);
+        this.value = value;
+    }
+    
+    /**
+     * Constructs a <CODE>PdfString</CODE>-object.
+     *
+     * @param		value		the content of the string
+     * @param		encoding	an encoding
+     */
+    
+    public PdfString(String value, String encoding) {
+        super(STRING);
+        this.value = value;
+        this.encoding = encoding;
+    }
+    
+    /**
+     * Constructs a <CODE>PdfString</CODE>-object.
+     *
+     * @param		bytes	an array of <CODE>byte</CODE>
+     */
+    
+    public PdfString(byte[] bytes) {
+        super(STRING);
+        value = PdfEncodings.convertToString(bytes, null);
+        encoding = NOTHING;
+    }
+    
+    // methods overriding some methods in PdfObject
+    
+    /**
+     * Returns the PDF representation of this <CODE>PdfString</CODE>.
+     *
+     * @return		an array of <CODE>byte</CODE>s
+     */
+    
+    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+        byte b[] = getBytes();
+        PdfEncryption crypto = null;
+        if (writer != null)
+            crypto = writer.getEncryption();
+        if (crypto != null) {
+            b = (byte[])bytes.clone();
+            crypto.prepareKey();
+            crypto.encryptRC4(b);
+        }
+        if (hexWriting) {
+            ByteBuffer buf = new ByteBuffer();
+            buf.append('<');
+            int len = b.length;
+            for (int k = 0; k < len; ++k)
+                buf.appendHex(b[k]);
+            buf.append('>');
+            os.write(buf.toByteArray());
+        }
+        else
+            os.write(PdfContentByte.escapeString(b));
+    }
+    
+    /**
+     * Returns the <CODE>String</CODE> value of the <CODE>PdfString</CODE>-object.
+     *
+     * @return		a <CODE>String</CODE>
+     */
+    
+    public String toString() {
+        return value;
+    }
+    
+    // other methods
+    
+    /**
+     * Gets the encoding of this string.
+     *
+     * @return		a <CODE>String</CODE>
+     */
+    
+    public String getEncoding() {
+        return encoding;
+    }
+    
+    public String toUnicodeString() {
+        if (encoding != null && encoding.length() != 0)
+            return value;
+        getBytes();
+        if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255)
+            return PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE);
+        else
+            return PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING);
+    }
+    
+    void setObjNum(int objNum, int objGen) {
+        this.objNum = objNum;
+        this.objGen = objGen;
+    }
+    
+    void decrypt(PdfReader reader) {
+        PdfEncryption decrypt = reader.getDecrypt();
+        if (decrypt != null) {
+            originalValue = value;
+            decrypt.setHashKey(objNum, objGen);
+            decrypt.prepareKey();
+            bytes = PdfEncodings.convertToBytes(value, null);
+            decrypt.encryptRC4(bytes);
+            value = PdfEncodings.convertToString(bytes, null);
+        }
+    }
+   
+    public byte[] getBytes() {
+        if (bytes == null) {
+            if (encoding != null && encoding.equals(TEXT_UNICODE) && PdfEncodings.isPdfDocEncoding(value))
+                bytes = PdfEncodings.convertToBytes(value, TEXT_PDFDOCENCODING);
+            else
+                bytes = PdfEncodings.convertToBytes(value, encoding);
+        }
+        return bytes;
+    }
+    
+    public byte[] getOriginalBytes() {
+        if (originalValue == null)
+            return getBytes();
+        return PdfEncodings.convertToBytes(originalValue, null);
+    }
+    
+    public PdfString setHexWriting(boolean hexWriting) {
+        this.hexWriting = hexWriting;
+        return this;
+    }
+    
+    public boolean isHexWriting() {
+        return hexWriting;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfTable.java b/LibrarySource/com/lowagie/text/pdf/PdfTable.java
new file mode 100644
index 0000000..b8333a3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfTable.java
@@ -0,0 +1,316 @@
+/*
+ * $Id: PdfTable.java,v 1.51 2004/02/07 10:28:45 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.lowagie.text.Element;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Cell;
+import com.lowagie.text.Row;
+import com.lowagie.text.Table;
+
+/**
+ * <CODE>PdfTable</CODE> is an object that contains the graphics and text of a table.
+ *
+ * @see		com.lowagie.text.Table
+ * @see		com.lowagie.text.Row
+ * @see		com.lowagie.text.Cell
+ * @see		PdfCell
+ */
+
+public class PdfTable extends Rectangle {
+    
+	// membervariables
+    
+	/** this is the number of columns in the table. */
+	private int columns;
+    
+	/** this is the ArrayList with all the cell of the table header. */
+	private ArrayList headercells;
+    
+	/** this is the ArrayList with all the cells in the table. */
+	private ArrayList cells;
+    
+	/** Original table used to build this object*/
+	protected Table table;
+	
+	/** Cached column widths. */
+	protected float[] positions;
+
+	// constructors
+
+	/**
+	 * Constructs a <CODE>PdfTable</CODE>-object.
+	 *
+	 * @param	table	a <CODE>Table</CODE>
+	 * @param	left	the left border on the page
+	 * @param	right	the right border on the page
+	 * @param	top		the start position of the top of the table
+	 * @param	supportUpdateRowAdditions	
+	 * 					if true, table rows will be deleted after building the PdfTable table, 
+	 * 					in order to preserve memory and detect future row additions
+	 */
+    
+	PdfTable(Table table, float left, float right, float top, boolean supportUpdateRowAdditions) {
+		// constructs a Rectangle (the bottomvalue will be changed afterwards)
+		super(left, top, right, top);
+		this.table = table;
+        table.complete();
+
+		// copying the attributes from class Table
+        cloneNonPositionParameters(table);
+
+		this.columns = table.columns();
+		positions = table.getWidths(left, right - left);
+        
+		// initialisation of some parameters
+		setLeft(positions[0]);
+		setRight(positions[positions.length - 1]);
+		
+		headercells = new ArrayList();
+		cells = new ArrayList();
+
+		updateRowAdditionsInternal();
+		if (supportUpdateRowAdditions) {
+			table.deleteAllRows();
+		}
+	}
+
+	// methods
+
+	/**
+	 * Updates the table row additions in the underlying table object and deletes all table rows, 
+	 * in order to preserve memory and detect future row additions.
+	 * <p><b>Pre-requisite</b>: the object must have been built with the parameter <code>supportUpdateRowAdditions</code> equals to true.
+	 */
+	
+	void updateRowAdditions() {
+        table.complete();
+		updateRowAdditionsInternal();
+		table.deleteAllRows();
+	}
+	
+	/**
+	 * Updates the table row additions in the underlying table object
+	 */
+	
+	private void updateRowAdditionsInternal() {
+		// correct table : fill empty cells/ parse table in table
+		Row row;
+		int prevRows = rows();
+		int rowNumber = 0;
+		int groupNumber = 0;
+		boolean groupChange;
+		int firstDataRow = table.firstDataRow();
+		Cell cell;
+		PdfCell currentCell;
+		ArrayList newCells = new ArrayList();
+		int rows = table.size() + 1;
+		float[] offsets = new float[rows];
+		for (int i = 0; i < rows; i++) {
+			offsets[i] = bottom();
+		}
+        
+		// loop over all the rows
+		for (Iterator rowIterator = table.iterator(); rowIterator.hasNext(); ) {
+			groupChange = false;
+			row = (Row) rowIterator.next();
+			if (row.isEmpty()) {
+				if (rowNumber < rows - 1 && offsets[rowNumber + 1] > offsets[rowNumber]) offsets[rowNumber + 1] = offsets[rowNumber];
+			}
+			else {
+				for(int i = 0; i < row.columns(); i++) {
+					cell = (Cell) row.getCell(i);
+					if (cell != null) {
+						currentCell = new PdfCell(cell, rowNumber+prevRows, positions[i], positions[i + cell.colspan()], offsets[rowNumber], cellspacing(), cellpadding());
+						try {
+                     if (offsets[rowNumber] - currentCell.height() - cellpadding() < offsets[rowNumber + currentCell.rowspan()]) {
+                        offsets[rowNumber + currentCell.rowspan()] = offsets[rowNumber] - currentCell.height() - cellpadding();
+							}
+						}
+						catch(ArrayIndexOutOfBoundsException aioobe) {
+							if (offsets[rowNumber] - currentCell.height() < offsets[rows - 1]) {
+								offsets[rows - 1] = offsets[rowNumber] - currentCell.height();
+							}
+						}
+						if (rowNumber < firstDataRow) {
+							currentCell.setHeader();
+							headercells.add(currentCell);
+						}
+						currentCell.setGroupNumber(groupNumber);
+						groupChange |= cell.getGroupChange();
+						newCells.add(currentCell);
+					}
+				}
+			}
+			rowNumber++;
+			if( groupChange ) groupNumber++;
+		}
+        
+		// loop over all the cells
+		int n = newCells.size();
+		for (int i = 0; i < n; i++) {
+			currentCell = (PdfCell) newCells.get(i);
+			try {
+				currentCell.setBottom(offsets[currentCell.rownumber()-prevRows + currentCell.rowspan()]);
+			}
+			catch(ArrayIndexOutOfBoundsException aioobe) {
+				currentCell.setBottom(offsets[rows - 1]);
+			}
+		}
+		cells.addAll(newCells);
+		setBottom(offsets[rows - 1]);
+	}
+
+	/**
+	 * Get the number of rows
+	 */
+	
+	int rows() {
+		return cells.size() == 0 ? 0 : ((PdfCell)cells.get(cells.size()-1)).rownumber()+1; 
+	}
+
+	/** @see com.lowagie.text.Element#type() */
+	public int type() {
+		return Element.TABLE;
+	}
+    
+	/**
+	 * Returns the arraylist with the cells of the table header.
+	 *
+	 * @return	an <CODE>ArrayList</CODE>
+	 */
+    
+	ArrayList getHeaderCells() {
+		return headercells;
+	}
+    
+	/**
+	 * Checks if there is a table header.
+	 *
+	 * @return	an <CODE>ArrayList</CODE>
+	 */
+    
+	boolean hasHeader() {
+		return headercells.size() > 0;
+	}
+    
+	/**
+	 * Returns the arraylist with the cells of the table.
+	 *
+	 * @return	an <CODE>ArrayList</CODE>
+	 */
+    
+	ArrayList getCells() {
+		return cells;
+	}
+    
+	/**
+	 * Returns the number of columns of the table.
+	 *
+	 * @return	the number of columns
+	 */
+    
+	int columns() {
+		return columns;
+	}
+    
+	/**
+	 * Returns the cellpadding of the table.
+	 *
+	 * @return	the cellpadding
+	 */
+    
+	final float cellpadding() {
+		return table.cellpadding();
+	}
+    
+	/**
+	 * Returns the cellspacing of the table.
+	 *
+	 * @return	the cellspacing
+	 */
+    
+	final float cellspacing() {
+		return table.cellspacing();
+	}
+	
+	/**
+	 * Checks if this <CODE>Table</CODE> has to fit a page.
+	 *
+	 * @return  true if the table may not be split
+	 */
+
+	public final boolean hasToFitPageTable() {
+		return table.hasToFitPageTable();
+	}
+
+	/**
+	 * Checks if the cells of this <CODE>Table</CODE> have to fit a page.
+	 *
+	 * @return  true if the cells may not be split
+	 */
+	
+	public final boolean hasToFitPageCells() {
+		return table.hasToFitPageCells();
+	}
+
+	/**
+	 * Gets the offset of this table.
+	 *
+	 * @return  the space between this table and the previous element.
+	 */
+	public float getOffset() {
+		return table.getOffset();
+	}
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfTemplate.java b/LibrarySource/com/lowagie/text/pdf/PdfTemplate.java
new file mode 100644
index 0000000..d22aa60
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfTemplate.java
@@ -0,0 +1,267 @@
+/*
+ * $Id: PdfTemplate.java,v 1.36 2003/05/02 09:01:28 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+import java.io.IOException;
+
+import com.lowagie.text.Rectangle;
+
+/**
+ * Implements the form XObject.
+ */
+
+public class PdfTemplate extends PdfContentByte {
+    public static final int TYPE_TEMPLATE = 1;
+    public static final int TYPE_IMPORTED = 2;
+    public static final int TYPE_PATTERN = 3;
+    protected int type;
+    /** The indirect reference to this template */
+    protected PdfIndirectReference thisReference;
+    
+    /** The resources used by this template */
+    protected PageResources pageResources;
+    
+    
+    /** The bounding box of this template */
+    protected Rectangle bBox = new Rectangle(0, 0);
+    
+    protected PdfArray matrix;
+    
+    protected PdfTransparencyGroup group;
+    
+    protected PdfOCG layer;
+    
+    /**
+     *Creates a <CODE>PdfTemplate</CODE>.
+     */
+    
+    protected PdfTemplate() {
+        super(null);
+        type = TYPE_TEMPLATE;
+    }
+    
+    /**
+     * Creates new PdfTemplate
+     *
+     * @param wr the <CODE>PdfWriter</CODE>
+     */
+    
+    PdfTemplate(PdfWriter wr) {
+        super(wr);
+        type = TYPE_TEMPLATE;
+        pageResources = new PageResources();
+        pageResources.addDefaultColor(wr.getDefaultColorspace());
+        thisReference = writer.getPdfIndirectReference();
+    }
+    
+    /**
+     * Sets the bounding width of this template.
+     *
+     * @param width the bounding width
+     */
+    
+    public void setWidth(float width) {
+        bBox.setLeft(0);
+        bBox.setRight(width);
+    }
+    
+    /**
+     * Sets the bounding heigth of this template.
+     *
+     * @param height the bounding height
+     */
+    
+    public void setHeight(float height) {
+        bBox.setBottom(0);
+        bBox.setTop(height);
+    }
+    
+    /**
+     * Gets the bounding width of this template.
+     *
+     * @return width the bounding width
+     */
+    public float getWidth() {
+        return bBox.width();
+    }
+    
+    /**
+     * Gets the bounding heigth of this template.
+     *
+     * @return heigth the bounding height
+     */
+    
+    public float getHeight() {
+        return bBox.height();
+    }
+    
+    public Rectangle getBoundingBox() {
+        return bBox;
+    }
+    
+    public void setBoundingBox(Rectangle bBox) {
+        this.bBox = bBox;
+    }
+    
+    /**
+     * Sets the layer this template belongs to.
+     * @param layer the layer this template belongs to
+     */    
+    public void setLayer(PdfOCG layer) {
+        this.layer = layer;
+    }
+    
+    /**
+     * Gets the layer this template belongs to.
+     * @return the layer this template belongs to or <code>null</code> for no layer defined
+     */
+    public PdfOCG getLayer() {
+        return layer;
+    }
+
+    public void setMatrix(float a, float b, float c, float d, float e, float f) {
+		matrix = new PdfArray();
+		matrix.add(new PdfNumber(a));
+		matrix.add(new PdfNumber(b));
+		matrix.add(new PdfNumber(c));
+		matrix.add(new PdfNumber(d));
+		matrix.add(new PdfNumber(e));
+		matrix.add(new PdfNumber(f));
+	}
+
+	PdfArray getMatrix() {
+		return matrix;
+	}
+    
+    /**
+     * Gets the indirect reference to this template.
+     *
+     * @return the indirect reference to this template
+     */
+    
+    PdfIndirectReference getIndirectReference() {
+        return thisReference;
+    }
+        
+    public void beginVariableText() {
+        content.append("/Tx BMC ");
+    }
+    
+    public void endVariableText() {
+        content.append("EMC ");
+    }
+    
+    /**
+     * Constructs the resources used by this template.
+     *
+     * @return the resources used by this template
+     */
+    
+    PdfObject getResources() {
+        return getPageResources().getResources();
+    }
+    
+    /**
+     * Gets the stream representing this template.
+     *
+     * @return the stream representing this template
+     */
+    
+    PdfStream getFormXObject() throws IOException {
+        return new PdfFormXObject(this);
+    }
+        
+    /**
+     * Gets a duplicate of this <CODE>PdfTemplate</CODE>. All
+     * the members are copied by reference but the buffer stays different.
+     * @return a copy of this <CODE>PdfTemplate</CODE>
+     */
+    
+    public PdfContentByte getDuplicate() {
+        PdfTemplate tpl = new PdfTemplate();
+        tpl.writer = writer;
+        tpl.pdf = pdf;
+        tpl.thisReference = thisReference;
+        tpl.pageResources = pageResources;
+        tpl.bBox = new Rectangle(bBox);
+        tpl.group = group;
+        tpl.layer = layer;
+        if (matrix != null) {
+            tpl.matrix = new PdfArray(matrix);
+        }
+        tpl.separator = separator;
+        return tpl;
+    }
+    
+    public int getType() {
+        return type;
+    }
+    
+    PageResources getPageResources() {
+        return pageResources;
+    }
+    
+    /** Getter for property group.
+     * @return Value of property group.
+     *
+     */
+    public PdfTransparencyGroup getGroup() {
+        return this.group;
+    }
+    
+    /** Setter for property group.
+     * @param group New value of property group.
+     *
+     */
+    public void setGroup(PdfTransparencyGroup group) {
+        this.group = group;
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfTextArray.java b/LibrarySource/com/lowagie/text/pdf/PdfTextArray.java
new file mode 100644
index 0000000..9abd927
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfTextArray.java
@@ -0,0 +1,99 @@
+/*
+ * $Id: PdfTextArray.java,v 1.24 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+
+/**
+ * <CODE>PdfTextArray</CODE> defines an array with displacements and <CODE>PdfString</CODE>-objects.
+ * <P>
+ * A <CODE>TextArray</CODE> is used with the operator <VAR>TJ</VAR> in <CODE>PdfText</CODE>.
+ * The first object in this array has to be a <CODE>PdfString</CODE>;
+ * see reference manual version 1.3 section 8.7.5, pages 346-347.
+ */
+
+public class PdfTextArray{
+    ArrayList arrayList = new ArrayList();
+    // constructors
+    
+    
+    public PdfTextArray(String str) {
+        arrayList.add(str);
+    }
+    
+    public PdfTextArray() {
+    }
+    
+/**
+ * Adds a <CODE>PdfNumber</CODE> to the <CODE>PdfArray</CODE>.
+ *
+ * @param		number			displacement of the string
+ */
+    
+    public void add(PdfNumber number)
+    {
+        arrayList.add(new Float(number.doubleValue()));
+    }
+    
+    public void add(float number)
+    {
+        arrayList.add(new Float(number));
+    }
+    
+    public void add(String str)
+    {
+        arrayList.add(str);
+    }
+    
+    ArrayList getArrayList() {
+        return arrayList;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfTransition.java b/LibrarySource/com/lowagie/text/pdf/PdfTransition.java
new file mode 100644
index 0000000..057ccac
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfTransition.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2002 by Josselin PUJO.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+public class PdfTransition {
+    /**
+     *  Out Vertical Split
+     */
+    public static final int SPLITVOUT      = 1;
+    /**
+     *  Out Horizontal Split
+     */
+    public static final int SPLITHOUT      = 2;
+    /**
+     *  In Vertical Split
+     */
+    public static final int SPLITVIN      = 3;
+    /**
+     *  IN Horizontal Split
+     */
+    public static final int SPLITHIN      = 4;
+    /**
+     *  Vertical Blinds
+     */
+    public static final int BLINDV      = 5;
+    /**
+     *  Vertical Blinds
+     */
+    public static final int BLINDH      = 6;
+    /**
+     *  Inward Box
+     */
+    public static final int INBOX       = 7;
+    /**
+     *  Outward Box
+     */
+    public static final int OUTBOX      = 8;
+    /**
+     *  Left-Right Wipe
+     */
+    public static final int LRWIPE      = 9;
+    /**
+     *  Right-Left Wipe
+     */
+    public static final int RLWIPE     = 10;
+    /**
+     *  Bottom-Top Wipe
+     */
+    public static final int BTWIPE     = 11;
+    /**
+     *  Top-Bottom Wipe
+     */
+    public static final int TBWIPE     = 12;
+    /**
+     *  Dissolve
+     */
+    public static final int DISSOLVE    = 13;
+    /**
+     *  Left-Right Glitter
+     */
+    public static final int LRGLITTER   = 14;
+    /**
+     *  Top-Bottom Glitter
+     */
+    public static final int TBGLITTER  = 15;
+    /**
+     *  Diagonal Glitter
+     */
+    public static final int DGLITTER  = 16;
+    
+    /**
+     *  duration of the transition effect
+     */
+    protected int duration;
+    /**
+     *  type of the transition effect
+     */
+    protected int type;
+    
+    /**
+     *  Constructs a <CODE>Transition</CODE>.
+     *
+     */
+    public PdfTransition() {
+        this(BLINDH);
+    }
+    
+    /**
+     *  Constructs a <CODE>Transition</CODE>.
+     *
+     *@param  type      type of the transition effect
+     */
+    public PdfTransition(int type) {
+        this(type,1);
+    }
+    
+    /**
+     *  Constructs a <CODE>Transition</CODE>.
+     *
+     *@param  type      type of the transition effect
+     *@param  duration  duration of the transition effect
+     */
+    public PdfTransition(int type, int duration) {
+        this.duration = duration;
+        this.type = type;
+    }
+    
+    
+    public int getDuration() {
+        return duration;
+    }
+    
+    
+    public int getType() {
+        return type;
+    }
+    
+    public PdfDictionary getTransitionDictionary() {
+        PdfDictionary trans = new PdfDictionary(PdfName.TRANS);
+        switch (type) {
+            case SPLITVOUT:
+                trans.put(PdfName.S,PdfName.SPLIT);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.V);
+                trans.put(PdfName.M,PdfName.O);
+                break;
+            case SPLITHOUT:
+                trans.put(PdfName.S,PdfName.SPLIT);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.H);
+                trans.put(PdfName.M,PdfName.O);
+                break;
+            case SPLITVIN:
+                trans.put(PdfName.S,PdfName.SPLIT);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.V);
+                trans.put(PdfName.M,PdfName.I);
+                break;
+            case SPLITHIN:
+                trans.put(PdfName.S,PdfName.SPLIT);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.H);
+                trans.put(PdfName.M,PdfName.I);
+                break;
+            case BLINDV:
+                trans.put(PdfName.S,PdfName.BLINDS);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.V);
+                break;
+            case BLINDH:
+                trans.put(PdfName.S,PdfName.BLINDS);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DM,PdfName.H);
+                break;
+            case INBOX:
+                trans.put(PdfName.S,PdfName.BOX);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.M,PdfName.I);
+                break;
+            case OUTBOX:
+                trans.put(PdfName.S,PdfName.BOX);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.M,PdfName.O);
+                break;
+            case LRWIPE:
+                trans.put(PdfName.S,PdfName.WIPE);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(0));
+                break;
+            case RLWIPE:
+                trans.put(PdfName.S,PdfName.WIPE);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(180));
+                break;
+            case BTWIPE:
+                trans.put(PdfName.S,PdfName.WIPE);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(90));
+                break;
+            case TBWIPE:
+                trans.put(PdfName.S,PdfName.WIPE);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(270));
+                break;
+            case DISSOLVE:
+                trans.put(PdfName.S,PdfName.DISSOLVE);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                break;
+            case LRGLITTER:
+                trans.put(PdfName.S,PdfName.GLITTER);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(0));
+                break;
+            case TBGLITTER:
+                trans.put(PdfName.S,PdfName.GLITTER);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(270));
+                break;
+            case DGLITTER:
+                trans.put(PdfName.S,PdfName.GLITTER);
+                trans.put(PdfName.D,new PdfNumber(duration));
+                trans.put(PdfName.DI,new PdfNumber(315));
+                break;
+        }
+        return trans;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfTransparencyGroup.java b/LibrarySource/com/lowagie/text/pdf/PdfTransparencyGroup.java
new file mode 100644
index 0000000..7890cc3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfTransparencyGroup.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/** The transparency group dictionary.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PdfTransparencyGroup extends PdfDictionary {
+    
+    /**
+     * Constructs a transparencyGroup.
+     */
+    public PdfTransparencyGroup() {
+        super();
+        put(PdfName.S, PdfName.TRANSPARENCY);
+    }
+ 
+    /**
+     * Determining the initial backdrop against which its stack is composited.
+     * @param isolated
+     */
+    public void setIsolated(boolean isolated) {
+        if (isolated)
+            put(PdfName.I, PdfBoolean.PDFTRUE);
+        else
+            remove(PdfName.I);
+    }
+    
+    /**
+     * Determining whether the objects within the stack are composited with one another or only with the group's backdrop.
+     * @param knockout
+     */
+    public void setKnockout(boolean knockout) {
+        if (knockout)
+            put(PdfName.K, PdfBoolean.PDFTRUE);
+        else
+            remove(PdfName.K);
+    }
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfWriter.java b/LibrarySource/com/lowagie/text/pdf/PdfWriter.java
new file mode 100644
index 0000000..dca2b22
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfWriter.java
@@ -0,0 +1,2542 @@
+/*
+ * $Id: PdfWriter.java,v 1.87 2004/12/14 15:16:01 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.HashSet;
+
+import com.lowagie.text.DocListener;
+import com.lowagie.text.DocWriter;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Image;
+import com.lowagie.text.ImgWMF;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Table;
+import com.lowagie.text.ImgPostscript;
+
+/**
+ * A <CODE>DocWriter</CODE> class for PDF.
+ * <P>
+ * When this <CODE>PdfWriter</CODE> is added
+ * to a certain <CODE>PdfDocument</CODE>, the PDF representation of every Element
+ * added to this Document will be written to the outputstream.</P>
+ */
+
+public class PdfWriter extends DocWriter {
+    
+    // inner classes
+    
+    /**
+     * This class generates the structure of a PDF document.
+     * <P>
+     * This class covers the third section of Chapter 5 in the 'Portable Document Format
+     * Reference Manual version 1.3' (page 55-60). It contains the body of a PDF document
+     * (section 5.14) and it can also generate a Cross-reference Table (section 5.15).
+     *
+     * @see		PdfWriter
+     * @see		PdfObject
+     * @see		PdfIndirectObject
+     */
+    
+    public static class PdfBody {
+        
+        // inner classes
+        
+        /**
+         * <CODE>PdfCrossReference</CODE> is an entry in the PDF Cross-Reference table.
+         */
+        
+        static class PdfCrossReference implements Comparable {
+            
+            // membervariables
+            private int type;
+            
+            /**	Byte offset in the PDF file. */
+            private int offset;
+            
+            private int refnum;
+            /**	generation of the object. */
+            private int generation;
+            
+            // constructors
+            /**
+             * Constructs a cross-reference element for a PdfIndirectObject.
+             * @param refnum
+             * @param	offset		byte offset of the object
+             * @param	generation	generationnumber of the object
+             */
+            
+            PdfCrossReference(int refnum, int offset, int generation) {
+                type = 0;
+                this.offset = offset;
+                this.refnum = refnum;
+                this.generation = generation;
+            }
+            
+            /**
+             * Constructs a cross-reference element for a PdfIndirectObject.
+             * @param refnum
+             * @param	offset		byte offset of the object
+             */
+            
+            PdfCrossReference(int refnum, int offset) {
+                type = 1;
+                this.offset = offset;
+                this.refnum = refnum;
+                this.generation = 0;
+            }
+            
+            PdfCrossReference(int type, int refnum, int offset, int generation) {
+                this.type = type;
+                this.offset = offset;
+                this.refnum = refnum;
+                this.generation = generation;
+            }
+            
+            int getRefnum() {
+                return refnum;
+            }
+            
+            /**
+             * Returns the PDF representation of this <CODE>PdfObject</CODE>.
+             * @param os
+             * @throws IOException
+             */
+            
+            public void toPdf(OutputStream os) throws IOException {
+                // This code makes it more difficult to port the lib to JDK1.1.x:
+                // StringBuffer off = new StringBuffer("0000000000").append(offset);
+                // off.delete(0, off.length() - 10);
+                // StringBuffer gen = new StringBuffer("00000").append(generation);
+                // gen.delete(0, gen.length() - 5);
+                // so it was changed into this:
+                String s = "0000000000" + offset;
+                StringBuffer off = new StringBuffer(s.substring(s.length() - 10));
+                s = "00000" + generation;
+                String gen = s.substring(s.length() - 5);
+                if (generation == 65535) {
+                    os.write(getISOBytes(off.append(' ').append(gen).append(" f \n").toString()));
+                }
+                else
+                    os.write(getISOBytes(off.append(' ').append(gen).append(" n \n").toString()));
+            }
+            
+            /**
+             * Writes PDF syntax to the OutputStream
+             * @param midSize
+             * @param os
+             * @throws IOException
+             */
+            public void toPdf(int midSize, OutputStream os) throws IOException {
+                os.write((byte)type);
+                while (--midSize >= 0)
+                    os.write((byte)((offset >>> (8 * midSize)) & 0xff));
+                os.write((byte)((generation >>> 8) & 0xff));
+                os.write((byte)(generation & 0xff));
+            }
+            
+            /**
+             * @see java.lang.Comparable#compareTo(java.lang.Object)
+             */
+            public int compareTo(Object o) {
+                PdfCrossReference other = (PdfCrossReference)o;
+                return (refnum < other.refnum ? -1 : (refnum==other.refnum ? 0 : 1));
+            }
+            
+            /**
+             * @see java.lang.Object#equals(java.lang.Object)
+             */
+            public boolean equals(Object obj) {
+                if (obj instanceof PdfCrossReference) {
+                    PdfCrossReference other = (PdfCrossReference)obj;
+                    return (refnum == other.refnum);
+                }
+                else
+                    return false;
+            }
+            
+        }
+        
+        // membervariables
+        
+        /** array containing the cross-reference table of the normal objects. */
+        private TreeSet xrefs;
+        private int refnum;
+        /** the current byteposition in the body. */
+        private int position;
+        private PdfWriter writer;
+        // constructors
+        
+        /**
+         * Constructs a new <CODE>PdfBody</CODE>.
+         * @param writer
+         */
+        PdfBody(PdfWriter writer) {
+            xrefs = new TreeSet();
+            xrefs.add(new PdfCrossReference(0, 0, 65535));
+            position = writer.getOs().getCounter();
+            refnum = 1;
+            this.writer = writer;
+        }
+        
+        void setRefnum(int refnum) {
+            this.refnum = refnum;
+        }
+        
+        // methods
+        
+        private static final int OBJSINSTREAM = 200;
+        
+        private ByteBuffer index;
+        private ByteBuffer streamObjects;
+        private int currentObjNum;
+        private int numObj = 0;
+        
+        private PdfWriter.PdfBody.PdfCrossReference addToObjStm(PdfObject obj, int nObj) throws IOException {
+            if (numObj >= OBJSINSTREAM)
+                flushObjStm();
+            if (index == null) {
+                index = new ByteBuffer();
+                streamObjects = new ByteBuffer();
+                currentObjNum = getIndirectReferenceNumber();
+                numObj = 0;
+            }
+            int p = streamObjects.size();
+            int idx = numObj++;
+            PdfEncryption enc = writer.crypto;
+            writer.crypto = null;
+            obj.toPdf(writer, streamObjects);
+            writer.crypto = enc;
+            streamObjects.append(' ');
+            index.append(nObj).append(' ').append(p).append(' ');
+            return new PdfWriter.PdfBody.PdfCrossReference(2, nObj, currentObjNum, idx);
+        }
+        
+        private void flushObjStm() throws IOException {
+            if (numObj == 0)
+                return;
+            int first = index.size();
+            index.append(streamObjects);
+            PdfStream stream = new PdfStream(index.toByteArray());
+            stream.flateCompress();
+            stream.put(PdfName.TYPE, PdfName.OBJSTM);
+            stream.put(PdfName.N, new PdfNumber(numObj));
+            stream.put(PdfName.FIRST, new PdfNumber(first));
+            add(stream, currentObjNum);
+            index = null;
+            streamObjects = null;
+            numObj = 0;
+        }
+        
+        /**
+         * Adds a <CODE>PdfObject</CODE> to the body.
+         * <P>
+         * This methods creates a <CODE>PdfIndirectObject</CODE> with a
+         * certain number, containing the given <CODE>PdfObject</CODE>.
+         * It also adds a <CODE>PdfCrossReference</CODE> for this object
+         * to an <CODE>ArrayList</CODE> that will be used to build the
+         * Cross-reference Table.
+         *
+         * @param		object			a <CODE>PdfObject</CODE>
+         * @return		a <CODE>PdfIndirectObject</CODE>
+         * @throws IOException
+         */
+        
+        PdfIndirectObject add(PdfObject object) throws IOException {
+            return add(object, getIndirectReferenceNumber());
+        }
+        
+        PdfIndirectObject add(PdfObject object, boolean inObjStm) throws IOException {
+            return add(object, getIndirectReferenceNumber(), inObjStm);
+        }
+        
+        /**
+         * Gets a PdfIndirectReference for an object that will be created in the future.
+         * @return a PdfIndirectReference
+         */
+        
+        PdfIndirectReference getPdfIndirectReference() {
+            return new PdfIndirectReference(0, getIndirectReferenceNumber());
+        }
+        
+        int getIndirectReferenceNumber() {
+            int n = refnum++;
+            xrefs.add(new PdfCrossReference(n, 0, 65536));
+            return n;
+        }
+        
+        /**
+         * Adds a <CODE>PdfObject</CODE> to the body given an already existing
+         * PdfIndirectReference.
+         * <P>
+         * This methods creates a <CODE>PdfIndirectObject</CODE> with the number given by
+         * <CODE>ref</CODE>, containing the given <CODE>PdfObject</CODE>.
+         * It also adds a <CODE>PdfCrossReference</CODE> for this object
+         * to an <CODE>ArrayList</CODE> that will be used to build the
+         * Cross-reference Table.
+         *
+         * @param		object			a <CODE>PdfObject</CODE>
+         * @param		ref		        a <CODE>PdfIndirectReference</CODE>
+         * @return		a <CODE>PdfIndirectObject</CODE>
+         * @throws IOException
+         */
+        
+        PdfIndirectObject add(PdfObject object, PdfIndirectReference ref) throws IOException {
+            return add(object, ref.getNumber());
+        }
+        
+        PdfIndirectObject add(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
+            return add(object, ref.getNumber(), inObjStm);
+        }
+        
+        PdfIndirectObject add(PdfObject object, int refNumber) throws IOException {
+            return add(object, refNumber, true); // to false
+        }
+        
+        PdfIndirectObject add(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
+            if (inObjStm && object.canBeInObjStm() && writer.isFullCompression()) {
+                PdfCrossReference pxref = addToObjStm(object, refNumber);
+                PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
+                if (!xrefs.add(pxref)) {
+                    xrefs.remove(pxref);
+                    xrefs.add(pxref);
+                }
+                return indirect;
+            }
+            else {
+                PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
+                PdfCrossReference pxref = new PdfCrossReference(refNumber, position);
+                if (!xrefs.add(pxref)) {
+                    xrefs.remove(pxref);
+                    xrefs.add(pxref);
+                }
+                indirect.writeTo(writer.getOs());
+                position = writer.getOs().getCounter();
+                return indirect;
+            }
+        }
+        
+        /**
+         * Adds a <CODE>PdfResources</CODE> object to the body.
+         *
+         * @param		object			the <CODE>PdfResources</CODE>
+         * @return		a <CODE>PdfIndirectObject</CODE>
+         */
+        
+//        PdfIndirectObject add(PdfResources object) {
+//            return add(object);
+//        }
+        
+        /**
+         * Adds a <CODE>PdfPages</CODE> object to the body.
+         *
+         * @param		object			the root of the document
+         * @return		a <CODE>PdfIndirectObject</CODE>
+         */
+        
+//        PdfIndirectObject add(PdfPages object) throws IOException {
+//            PdfIndirectObject indirect = new PdfIndirectObject(PdfWriter.ROOT, object, writer);
+//            rootOffset = position;
+//            indirect.writeTo(writer.getOs());
+//            position = writer.getOs().getCounter();
+//            return indirect;
+//        }
+        
+        /**
+         * Returns the offset of the Cross-Reference table.
+         *
+         * @return		an offset
+         */
+        
+        int offset() {
+            return position;
+        }
+        
+        /**
+         * Returns the total number of objects contained in the CrossReferenceTable of this <CODE>Body</CODE>.
+         *
+         * @return	a number of objects
+         */
+        
+        int size() {
+            return Math.max(((PdfCrossReference)xrefs.last()).getRefnum() + 1, refnum);
+        }
+        
+        /**
+         * Returns the CrossReferenceTable of the <CODE>Body</CODE>.
+         * @param os
+         * @param root
+         * @param info
+         * @param encryption
+         * @param fileID
+         * @param prevxref
+         * @throws IOException
+         */
+        
+        void writeCrossReferenceTable(OutputStream os, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) throws IOException {
+            int refNumber = 0;
+            if (writer.isFullCompression()) {
+                flushObjStm();
+                refNumber = getIndirectReferenceNumber();
+                xrefs.add(new PdfCrossReference(refNumber, position));
+            }
+            PdfCrossReference entry = (PdfCrossReference)xrefs.first();
+            int first = entry.getRefnum();
+            int len = 0;
+            ArrayList sections = new ArrayList();
+            for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
+                entry = (PdfCrossReference)i.next();
+                if (first + len == entry.getRefnum())
+                    ++len;
+                else {
+                    sections.add(new Integer(first));
+                    sections.add(new Integer(len));
+                    first = entry.getRefnum();
+                    len = 1;
+                }
+            }
+            sections.add(new Integer(first));
+            sections.add(new Integer(len));
+            if (writer.isFullCompression()) {
+                int mid = 4;
+                int mask = 0xff000000;
+                for (; mid > 1; --mid) {
+                    if ((mask & position) != 0)
+                        break;
+                    mask >>>= 8;
+                }
+                ByteBuffer buf = new ByteBuffer();
+                
+                for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
+                    entry = (PdfCrossReference) i.next();
+                    entry.toPdf(mid, buf);
+                }
+                PdfStream xr = new PdfStream(buf.toByteArray());
+                buf = null;
+                xr.flateCompress();
+                xr.put(PdfName.SIZE, new PdfNumber(size()));
+                xr.put(PdfName.ROOT, root);
+                if (info != null) {
+                    xr.put(PdfName.INFO, info);
+                }
+                if (encryption != null)
+                    xr.put(PdfName.ENCRYPT, encryption);
+                if (fileID != null)
+                    xr.put(PdfName.ID, fileID);
+                xr.put(PdfName.W, new PdfArray(new int[]{1, mid, 2}));
+                xr.put(PdfName.TYPE, PdfName.XREF);
+                PdfArray idx = new PdfArray();
+                for (int k = 0; k < sections.size(); ++k)
+                    idx.add(new PdfNumber(((Integer)sections.get(k)).intValue()));
+                xr.put(PdfName.INDEX, idx);
+                if (prevxref > 0)
+                    xr.put(PdfName.PREV, new PdfNumber(prevxref));
+                PdfEncryption enc = writer.crypto;
+                writer.crypto = null;
+                PdfIndirectObject indirect = new PdfIndirectObject(refNumber, xr, writer);
+                indirect.writeTo(writer.getOs());
+                writer.crypto = enc;
+            }
+            else {
+                os.write(getISOBytes("xref\n"));
+                Iterator i = xrefs.iterator();
+                for (int k = 0; k < sections.size(); k += 2) {
+                    first = ((Integer)sections.get(k)).intValue();
+                    len = ((Integer)sections.get(k + 1)).intValue();
+                    os.write(getISOBytes(String.valueOf(first)));
+                    os.write(getISOBytes(" "));
+                    os.write(getISOBytes(String.valueOf(len)));
+                    os.write('\n');
+                    while (len-- > 0) {
+                        entry = (PdfCrossReference) i.next();
+                        entry.toPdf(os);
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * <CODE>PdfTrailer</CODE> is the PDF Trailer object.
+     * <P>
+     * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+     * section 5.16 (page 59-60).
+     */
+    
+    static class PdfTrailer extends PdfDictionary {
+        
+        // membervariables
+        
+        int offset;
+        
+        // constructors
+        
+        /**
+         * Constructs a PDF-Trailer.
+         *
+         * @param		size		the number of entries in the <CODE>PdfCrossReferenceTable</CODE>
+         * @param		offset		offset of the <CODE>PdfCrossReferenceTable</CODE>
+         * @param		root		an indirect reference to the root of the PDF document
+         * @param		info		an indirect reference to the info object of the PDF document
+         * @param encryption
+         * @param fileID
+         * @param prevxref
+         */
+        
+        PdfTrailer(int size, int offset, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) {
+            this.offset = offset;
+            put(PdfName.SIZE, new PdfNumber(size));
+            put(PdfName.ROOT, root);
+            if (info != null) {
+                put(PdfName.INFO, info);
+            }
+            if (encryption != null)
+                put(PdfName.ENCRYPT, encryption);
+            if (fileID != null)
+                put(PdfName.ID, fileID);
+            if (prevxref > 0)
+                put(PdfName.PREV, new PdfNumber(prevxref));
+        }
+        
+        /**
+         * Returns the PDF representation of this <CODE>PdfObject</CODE>.
+         * @param writer
+         * @param os
+         * @throws IOException
+         */
+        public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+            os.write(getISOBytes("trailer\n"));
+            super.toPdf(null, os);
+            os.write(getISOBytes("\nstartxref\n"));
+            os.write(getISOBytes(String.valueOf(offset)));
+            os.write(getISOBytes("\n%%EOF\n"));
+        }
+    }
+    // static membervariables
+    
+    /** A viewer preference */
+    public static final int PageLayoutSinglePage = 1;
+    /** A viewer preference */
+    public static final int PageLayoutOneColumn = 2;
+    /** A viewer preference */
+    public static final int PageLayoutTwoColumnLeft = 4;
+    /** A viewer preference */
+    public static final int PageLayoutTwoColumnRight = 8;
+    
+    /** A viewer preference */
+    public static final int PageModeUseNone = 16;
+    /** A viewer preference */
+    public static final int PageModeUseOutlines = 32;
+    /** A viewer preference */
+    public static final int PageModeUseThumbs = 64;
+    /** A viewer preference */
+    public static final int PageModeFullScreen = 128;
+    /** A viewer preference */
+    public static final int PageModeUseOC = 1 << 20;
+    
+    /** A viewer preference */
+    public static final int HideToolbar = 256;
+    /** A viewer preference */
+    public static final int HideMenubar = 512;
+    /** A viewer preference */
+    public static final int HideWindowUI = 1024;
+    /** A viewer preference */
+    public static final int FitWindow = 2048;
+    /** A viewer preference */
+    public static final int CenterWindow = 4096;
+    
+    /** A viewer preference */
+    public static final int NonFullScreenPageModeUseNone = 8192;
+    /** A viewer preference */
+    public static final int NonFullScreenPageModeUseOutlines = 16384;
+    /** A viewer preference */
+    public static final int NonFullScreenPageModeUseThumbs = 32768;
+    /** A viewer preference */
+    public static final int NonFullScreenPageModeUseOC = 1 << 19;
+    
+    /** A viewer preference */
+    public static final int DirectionL2R = 1 << 16;
+    /** A viewer preference */
+    public static final int DirectionR2L = 1 << 17;
+    /** A viewer preference */
+    public static final int DisplayDocTitle = 1 << 18;
+    /** A viewer preference */
+    public static final int PrintScalingNone = 1 << 20;
+    /** The mask to decide if a ViewerPreferences dictionary is needed */
+    static final int ViewerPreferencesMask = 0xffff00;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowPrinting = 4 + 2048;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowModifyContents = 8;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowCopy = 16;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowModifyAnnotations = 32;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowFillIn = 256;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowScreenReaders = 512;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowAssembly = 1024;
+    /** The operation permitted when the document is opened with the user password */
+    public static final int AllowDegradedPrinting = 4;
+    /** Type of encryption */
+    public static final boolean STRENGTH40BITS = false;
+    /** Type of encryption */
+    public static final boolean STRENGTH128BITS = true;
+    /** action value */
+    public static final PdfName DOCUMENT_CLOSE = PdfName.WC;
+    /** action value */
+    public static final PdfName WILL_SAVE = PdfName.WS;
+    /** action value */
+    public static final PdfName DID_SAVE = PdfName.DS;
+    /** action value */
+    public static final PdfName WILL_PRINT = PdfName.WP;
+    /** action value */
+    public static final PdfName DID_PRINT = PdfName.DP;
+    /** action value */
+    public static final PdfName PAGE_OPEN = PdfName.O;
+    /** action value */
+    public static final PdfName PAGE_CLOSE = PdfName.C;
+
+    /** signature value */
+    public static final int SIGNATURE_EXISTS = 1;
+    /** signature value */
+    public static final int SIGNATURE_APPEND_ONLY = 2;
+    
+    /** possible PDF version */
+    public static final char VERSION_1_2 = '2';
+    /** possible PDF version */
+    public static final char VERSION_1_3 = '3';
+    /** possible PDF version */
+    public static final char VERSION_1_4 = '4';
+    /** possible PDF version */
+    public static final char VERSION_1_5 = '5';
+    /** possible PDF version */
+    public static final char VERSION_1_6 = '6';
+    
+    private static final int VPOINT = 7;
+    /** this is the header of a PDF document */
+    protected byte[] HEADER = getISOBytes("%PDF-1.4\n%\u00e2\u00e3\u00cf\u00d3\n");
+
+    protected int prevxref = 0;
+    
+    protected PdfPages root = new PdfPages(this);
+    
+    /** Dictionary, containing all the images of the PDF document */
+    protected PdfDictionary imageDictionary = new PdfDictionary();
+    
+    /** This is the list with all the images in the document. */
+    private HashMap images = new HashMap();
+    
+    /** The form XObjects in this document. The key is the xref and the value
+        is Object[]{PdfName, template}.*/
+    protected HashMap formXObjects = new HashMap();
+    
+    /** The name counter for the form XObjects name. */
+    protected int formXObjectsCounter = 1;
+    
+    /** The font number counter for the fonts in the document. */
+    protected int fontNumber = 1;
+    
+    /** The color number counter for the colors in the document. */
+    protected int colorNumber = 1;
+    
+    /** The patten number counter for the colors in the document. */
+    protected int patternNumber = 1;
+    
+    /** The direct content in this document. */
+    protected PdfContentByte directContent;
+    
+    /** The direct content under in this document. */
+    protected PdfContentByte directContentUnder;
+    
+    /** The fonts of this document */
+    protected HashMap documentFonts = new HashMap();
+    
+    /** The colors of this document */
+    protected HashMap documentColors = new HashMap();
+    
+    /** The patterns of this document */
+    protected HashMap documentPatterns = new HashMap();
+    
+    protected HashMap documentShadings = new HashMap();
+    
+    protected HashMap documentShadingPatterns = new HashMap();
+    
+    protected ColorDetails patternColorspaceRGB;
+    protected ColorDetails patternColorspaceGRAY;
+    protected ColorDetails patternColorspaceCMYK;
+    protected HashMap documentSpotPatterns = new HashMap();
+    
+    protected HashMap documentExtGState = new HashMap();
+    
+    protected HashMap documentLayers = new HashMap();
+    protected HashSet documentOCG = new HashSet();
+    protected ArrayList documentOCGorder = new ArrayList();
+    protected PdfOCProperties OCProperties;
+    protected PdfArray OCGRadioGroup = new PdfArray();
+    
+    protected PdfDictionary defaultColorspace = new PdfDictionary();
+    
+    /** PDF/X value */
+    public static final int PDFXNONE = 0;
+    /** PDF/X value */
+    public static final int PDFX1A2001 = 1;
+    /** PDF/X value */
+    public static final int PDFX32002 = 2;
+
+    private int pdfxConformance = PDFXNONE;
+    
+    static final int PDFXKEY_COLOR = 1;
+    static final int PDFXKEY_CMYK = 2;
+    static final int PDFXKEY_RGB = 3;
+    static final int PDFXKEY_FONT = 4;
+    static final int PDFXKEY_IMAGE = 5;
+    static final int PDFXKEY_GSTATE = 6;
+    static final int PDFXKEY_LAYER = 7;
+    
+    // membervariables
+    
+    /** body of the PDF document */
+    protected PdfBody body;
+    
+    /** the pdfdocument object. */
+    protected PdfDocument pdf;
+    
+    /** The <CODE>PdfPageEvent</CODE> for this document. */
+    private PdfPageEvent pageEvent;
+    
+    protected PdfEncryption crypto;
+    
+    protected HashMap importedPages = new HashMap();
+    
+    protected PdfReaderInstance currentPdfReaderInstance;
+    
+    /** The PdfIndirectReference to the pages. */
+    protected ArrayList pageReferences = new ArrayList();
+    
+    protected int currentPageNumber = 1;
+    
+    protected PdfDictionary group;
+    
+    /** The default space-char ratio. */    
+    public static final float SPACE_CHAR_RATIO_DEFAULT = 2.5f;
+    /** Disable the inter-character spacing. */    
+    public static final float NO_SPACE_CHAR_RATIO = 10000000f;
+    
+    /** Use the default run direction. */    
+    public static final int RUN_DIRECTION_DEFAULT = 0;
+    /** Do not use bidirectional reordering. */    
+    public static final int RUN_DIRECTION_NO_BIDI = 1;
+    /** Use bidirectional reordering with left-to-right
+     * preferential run direction.
+     */    
+    public static final int RUN_DIRECTION_LTR = 2;
+    /** Use bidirectional reordering with right-to-left
+     * preferential run direction.
+     */    
+    public static final int RUN_DIRECTION_RTL = 3;
+    protected int runDirection = RUN_DIRECTION_NO_BIDI;
+    /**
+     * The ratio between the extra word spacing and the extra character spacing.
+     * Extra word spacing will grow <CODE>ratio</CODE> times more than extra character spacing.
+     */
+    private float spaceCharRatio = SPACE_CHAR_RATIO_DEFAULT;
+    
+    /** Holds value of property extraCatalog. */
+    private PdfDictionary extraCatalog;
+    
+    /**
+     * Holds value of property fullCompression.
+     */
+    protected boolean fullCompression = false;
+        
+    // constructor
+    
+    protected PdfWriter() {
+    }
+    
+    /**
+     * Constructs a <CODE>PdfWriter</CODE>.
+     * <P>
+     * Remark: a PdfWriter can only be constructed by calling the method
+     * <CODE>getInstance(Document document, OutputStream os)</CODE>.
+     *
+     * @param	document	The <CODE>PdfDocument</CODE> that has to be written
+     * @param	os			The <CODE>OutputStream</CODE> the writer has to write to.
+     */
+    
+    protected PdfWriter(PdfDocument document, OutputStream os) {
+        super(document, os);
+        pdf = document;
+        directContent = new PdfContentByte(this);
+        directContentUnder = new PdfContentByte(this);
+    }
+    
+    // get an instance of the PdfWriter
+    
+    /**
+     * Gets an instance of the <CODE>PdfWriter</CODE>.
+     *
+     * @param	document	The <CODE>Document</CODE> that has to be written
+     * @param	os	The <CODE>OutputStream</CODE> the writer has to write to.
+     * @return	a new <CODE>PdfWriter</CODE>
+     *
+     * @throws	DocumentException on error
+     */
+    
+    public static PdfWriter getInstance(Document document, OutputStream os)
+    throws DocumentException {
+        PdfDocument pdf = new PdfDocument();
+        document.addDocListener(pdf);
+        PdfWriter writer = new PdfWriter(pdf, os);
+        pdf.addWriter(writer);
+        return writer;
+    }
+    
+    /** Gets an instance of the <CODE>PdfWriter</CODE>.
+     *
+     * @return a new <CODE>PdfWriter</CODE>
+     * @param document The <CODE>Document</CODE> that has to be written
+     * @param os The <CODE>OutputStream</CODE> the writer has to write to.
+     * @param listener A <CODE>DocListener</CODE> to pass to the PdfDocument.
+     * @throws DocumentException on error
+     */
+    
+    public static PdfWriter getInstance(Document document, OutputStream os, DocListener listener)
+    throws DocumentException {
+        PdfDocument pdf = new PdfDocument();
+        pdf.addDocListener(listener);
+        document.addDocListener(pdf);
+        PdfWriter writer = new PdfWriter(pdf, os);
+        pdf.addWriter(writer);
+        return writer;
+    }
+    
+    // methods to write objects to the outputstream
+    
+    /**
+     * Adds some <CODE>PdfContents</CODE> to this Writer.
+     * <P>
+     * The document has to be open before you can begin to add content
+     * to the body of the document.
+     *
+     * @return a <CODE>PdfIndirectReference</CODE>
+     * @param page the <CODE>PdfPage</CODE> to add
+     * @param contents the <CODE>PdfContents</CODE> of the page
+     * @throws PdfException on error
+     */
+    
+    PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException {
+        if (!open) {
+            throw new PdfException("The document isn't open.");
+        }
+        PdfIndirectObject object;
+        try {
+            object = addToBody(contents);
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+        page.add(object.getIndirectReference());
+        if (group != null) {
+            page.put(PdfName.GROUP, group);
+            group = null;
+        }
+        root.addPage(page);
+        currentPageNumber++;
+        return null;
+    }
+    
+    /** Adds an image to the document but not to the page resources. It is used with
+     * templates and <CODE>Document.add(Image)</CODE>.
+     * @param image the <CODE>Image</CODE> to add
+     * @return the name of the image added
+     * @throws PdfException on error
+     * @throws DocumentException on error
+     */
+    PdfName addDirectImageSimple(Image image) throws PdfException, DocumentException {
+        PdfName name;
+        // if the images is already added, just retrieve the name
+        if (images.containsKey(image.getMySerialId())) {
+            name = (PdfName) images.get(image.getMySerialId());
+        }
+        // if it's a new image, add it to the document
+        else {
+            if (image.isImgTemplate()) {
+                name = new PdfName("img" + images.size());
+                if (image.templateData() == null) {
+                    if(image instanceof ImgWMF){
+                        try {
+                            ImgWMF wmf = (ImgWMF)image;
+                            wmf.readWMF(getDirectContent().createTemplate(0, 0));
+                        }
+                        catch (Exception e) {
+                            throw new DocumentException(e);
+                        }
+                    }else{
+                        try {
+                            ((ImgPostscript)image).readPostscript(getDirectContent().createTemplate(0, 0));
+                        }
+                        catch (Exception e) {
+                            throw new DocumentException(e);
+                        }
+                        
+                    }
+                }
+            }
+            else {
+                Image maskImage = image.getImageMask();
+                PdfIndirectReference maskRef = null;
+                if (maskImage != null) {
+                    PdfName mname = (PdfName)images.get(maskImage.getMySerialId());
+                    maskRef = getImageReference(mname);
+                }
+                PdfImage i = new PdfImage(image, "img" + images.size(), maskRef);
+                if (image.hasICCProfile()) {
+                    PdfICCBased icc = new PdfICCBased(image.getICCProfile());
+                    PdfIndirectReference iccRef = add(icc);
+                    PdfArray iccArray = new PdfArray();
+                    iccArray.add(PdfName.ICCBASED);
+                    iccArray.add(iccRef);
+                    PdfObject colorspace = i.get(PdfName.COLORSPACE);
+                    if (colorspace != null && colorspace.isArray()) {
+                        ArrayList ar = ((PdfArray)colorspace).getArrayList();
+                        if (ar.size() > 1 && PdfName.INDEXED.equals(ar.get(0)))
+                            ar.set(1, iccArray);
+                        else
+                            i.put(PdfName.COLORSPACE, iccArray);
+                    }
+                    else
+                        i.put(PdfName.COLORSPACE, iccArray);
+                }
+                add(i);
+                name = i.name();
+            }
+            images.put(image.getMySerialId(), name);
+        }
+        return name;
+    }
+
+    /**
+     * Writes a <CODE>PdfImage</CODE> to the outputstream.
+     *
+     * @param pdfImage the image to be added
+     * @return a <CODE>PdfIndirectReference</CODE> to the encapsulated image
+     * @throws PdfException when a document isn't open yet, or has been closed
+     */
+    
+    PdfIndirectReference add(PdfImage pdfImage) throws PdfException {
+        if (! imageDictionary.contains(pdfImage.name())) {
+            checkPDFXConformance(this, PDFXKEY_IMAGE, pdfImage);
+            PdfIndirectObject object;
+            try {
+                object = addToBody(pdfImage);
+            }
+            catch(IOException ioe) {
+                throw new ExceptionConverter(ioe);
+            }
+            imageDictionary.put(pdfImage.name(), object.getIndirectReference());
+            return object.getIndirectReference();
+        }
+        return (PdfIndirectReference) imageDictionary.get(pdfImage.name());
+    }
+    
+    protected PdfIndirectReference add(PdfICCBased icc) throws PdfException {
+        PdfIndirectObject object;
+        try {
+            object = addToBody(icc);
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+        return object.getIndirectReference();
+    }
+    
+    /**
+     * return the <CODE>PdfIndirectReference</CODE> to the image with a given name.
+     *
+     * @param name the name of the image
+     * @return a <CODE>PdfIndirectReference</CODE>
+     */
+    
+    PdfIndirectReference getImageReference(PdfName name) {
+        return (PdfIndirectReference) imageDictionary.get(name);
+    }
+    
+    // methods to open and close the writer
+    
+    /**
+     * Signals that the <CODE>Document</CODE> has been opened and that
+     * <CODE>Elements</CODE> can be added.
+     * <P>
+     * When this method is called, the PDF-document header is
+     * written to the outputstream.
+     */
+    
+    public void open() {
+        super.open();
+        try {
+            os.write(HEADER);
+            body = new PdfBody(this);
+            if (pdfxConformance == PDFX32002) {
+                PdfDictionary sec = new PdfDictionary();
+                sec.put(PdfName.GAMMA, new PdfArray(new float[]{2.2f,2.2f,2.2f}));
+                sec.put(PdfName.MATRIX, new PdfArray(new float[]{0.4124f,0.2126f,0.0193f,0.3576f,0.7152f,0.1192f,0.1805f,0.0722f,0.9505f}));
+                sec.put(PdfName.WHITEPOINT, new PdfArray(new float[]{0.9505f,1f,1.089f}));
+                PdfArray arr = new PdfArray(PdfName.CALRGB);
+                arr.add(sec);
+                setDefaultColorspace(PdfName.DEFAULTRGB, addToBody(arr).getIndirectReference());
+            }
+        }
+        catch(IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+    }
+    
+    private static void getOCGOrder(PdfArray order, PdfLayer layer) {
+        if (!layer.isOnPanel())
+            return;
+        if (layer.getTitle() == null)
+            order.add(layer.getRef());
+        ArrayList children = layer.getChildren();
+        if (children == null)
+            return;
+        PdfArray kids = new PdfArray();
+        if (layer.getTitle() != null)
+            kids.add(new PdfString(layer.getTitle(), PdfObject.TEXT_UNICODE));
+        for (int k = 0; k < children.size(); ++k) {
+            getOCGOrder(kids, (PdfLayer)children.get(k));
+        }
+        if (kids.size() > 0)
+            order.add(kids);
+    }
+    
+    private void addASEvent(PdfName event, PdfName category) {
+        PdfArray arr = new PdfArray();
+        for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+            PdfLayer layer = (PdfLayer)it.next();
+            PdfDictionary usage = (PdfDictionary)layer.get(PdfName.USAGE);
+            if (usage != null && usage.get(category) != null)
+                arr.add(layer.getRef());
+        }
+        if (arr.size() == 0)
+            return;
+        PdfDictionary d = (PdfDictionary)OCProperties.get(PdfName.D);
+        PdfArray arras = (PdfArray)d.get(PdfName.AS);
+        if (arras == null) {
+            arras = new PdfArray();
+            d.put(PdfName.AS, arras);
+        }
+        PdfDictionary as = new PdfDictionary();
+        as.put(PdfName.EVENT, event);
+        as.put(PdfName.CATEGORY, new PdfArray(category));
+        as.put(PdfName.OCGS, arr);
+        arras.add(as);
+    }
+    
+    private void fillOCProperties(boolean erase) {
+        if (OCProperties == null)
+            OCProperties = new PdfOCProperties();
+        if (erase) {
+            OCProperties.remove(PdfName.OCGS);
+            OCProperties.remove(PdfName.D);
+        }
+        if (OCProperties.get(PdfName.OCGS) == null) {
+            PdfArray gr = new PdfArray();
+            for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+                PdfLayer layer = (PdfLayer)it.next();
+                gr.add(layer.getRef());
+            }
+            OCProperties.put(PdfName.OCGS, gr);
+        }
+        if (OCProperties.get(PdfName.D) != null)
+            return;
+        ArrayList docOrder = new ArrayList(documentOCGorder);
+        for (Iterator it = docOrder.iterator(); it.hasNext();) {
+            PdfLayer layer = (PdfLayer)it.next();
+            if (layer.getParent() != null)
+                it.remove();
+        }
+        PdfArray order = new PdfArray();
+        for (Iterator it = docOrder.iterator(); it.hasNext();) {
+            PdfLayer layer = (PdfLayer)it.next();
+            getOCGOrder(order, layer);
+        }
+        PdfDictionary d = new PdfDictionary();
+        OCProperties.put(PdfName.D, d);
+        d.put(PdfName.ORDER, order);
+        PdfArray gr = new PdfArray();
+        for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+            PdfLayer layer = (PdfLayer)it.next();
+            if (!layer.isOn())
+                gr.add(layer.getRef());
+        }
+        if (gr.size() > 0)
+            d.put(PdfName.OFF, gr);
+        if (OCGRadioGroup.size() > 0)
+            d.put(PdfName.RBGROUPS, OCGRadioGroup);
+        addASEvent(PdfName.VIEW, PdfName.ZOOM);
+        addASEvent(PdfName.VIEW, PdfName.VIEW);
+        addASEvent(PdfName.PRINT, PdfName.PRINT);
+        addASEvent(PdfName.EXPORT, PdfName.EXPORT);
+        d.put(PdfName.LISTMODE, PdfName.VISIBLEPAGES);
+    }
+    
+    protected PdfDictionary getCatalog(PdfIndirectReference rootObj)
+    {
+        PdfDictionary catalog = ((PdfDocument)document).getCatalog(rootObj);
+        if (documentOCG.size() == 0)
+            return catalog;
+        fillOCProperties(false);
+        catalog.put(PdfName.OCPROPERTIES, OCProperties);
+        return catalog;
+    }
+
+    protected void addSharedObjectsToBody() throws IOException {
+        // add the fonts
+        for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
+            FontDetails details = (FontDetails)it.next();
+            details.writeFont(this);
+        }
+        // add the form XObjects
+        for (Iterator it = formXObjects.values().iterator(); it.hasNext();) {
+            Object objs[] = (Object[])it.next();
+            PdfTemplate template = (PdfTemplate)objs[1];
+            if (template != null && template.getIndirectReference() instanceof PRIndirectReference)
+                continue;
+            if (template != null && template.getType() == PdfTemplate.TYPE_TEMPLATE) {
+                PdfIndirectObject obj = addToBody(template.getFormXObject(), template.getIndirectReference());
+            }
+        }
+        // add all the dependencies in the imported pages
+        for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
+            currentPdfReaderInstance = (PdfReaderInstance)it.next();
+            currentPdfReaderInstance.writeAllPages();
+        }
+        currentPdfReaderInstance = null;
+        // add the color
+        for (Iterator it = documentColors.values().iterator(); it.hasNext();) {
+            ColorDetails color = (ColorDetails)it.next();
+            PdfIndirectObject cobj = addToBody(color.getSpotColor(this), color.getIndirectReference());
+        }
+        // add the pattern
+        for (Iterator it = documentPatterns.keySet().iterator(); it.hasNext();) {
+            PdfPatternPainter pat = (PdfPatternPainter)it.next();
+            PdfIndirectObject pobj = addToBody(pat.getPattern(), pat.getIndirectReference());
+        }
+        // add the shading patterns
+        for (Iterator it = documentShadingPatterns.keySet().iterator(); it.hasNext();) {
+            PdfShadingPattern shadingPattern = (PdfShadingPattern)it.next();
+            shadingPattern.addToBody();
+        }
+        // add the shadings
+        for (Iterator it = documentShadings.keySet().iterator(); it.hasNext();) {
+            PdfShading shading = (PdfShading)it.next();
+            shading.addToBody();
+        }
+        // add the extgstate
+        for (Iterator it = documentExtGState.keySet().iterator(); it.hasNext();) {
+            PdfDictionary gstate = (PdfDictionary)it.next();
+            PdfObject obj[] = (PdfObject[])documentExtGState.get(gstate);
+            addToBody(gstate, (PdfIndirectReference)obj[1]);
+        }
+        // add the layers
+        for (Iterator it = documentLayers.keySet().iterator(); it.hasNext();) {
+            PdfOCG layer = (PdfOCG)it.next();
+            if (layer instanceof PdfLayerMembership)
+                addToBody(layer.getPdfObject(), layer.getRef());
+        }
+        for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+            PdfOCG layer = (PdfOCG)it.next();
+            addToBody(layer.getPdfObject(), layer.getRef());
+        }
+    }
+    
+    /**
+     * Signals that the <CODE>Document</CODE> was closed and that no other
+     * <CODE>Elements</CODE> will be added.
+     * <P>
+     * The pages-tree is built and written to the outputstream.
+     * A Catalog is constructed, as well as an Info-object,
+     * the referencetable is composed and everything is written
+     * to the outputstream embedded in a Trailer.
+     */
+    
+    public synchronized void close() {
+        if (open) {
+            if ((currentPageNumber - 1) != pageReferences.size())
+                throw new RuntimeException("The page " + pageReferences.size() +
+                " was requested but the document has only " + (currentPageNumber - 1) + " pages.");
+            pdf.close();
+            try {
+                addSharedObjectsToBody();
+                // add the root to the body
+                PdfIndirectReference rootRef = root.writePageTree();
+                // make the catalog-object and add it to the body
+                PdfDictionary catalog = getCatalog(rootRef);
+                // make pdfx conformant
+                PdfDictionary info = getInfo();
+                if (pdfxConformance != PDFXNONE) {
+                    if (info.get(PdfName.GTS_PDFXVERSION) == null) {
+                        if (pdfxConformance == PDFX1A2001) {
+                            info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-1:2001"));
+                            info.put(new PdfName("GTS_PDFXConformance"), new PdfString("PDF/X-1a:2001"));
+                        }
+                        else if (pdfxConformance == PDFX32002)
+                            info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-3:2002"));
+                    }
+                    if (info.get(PdfName.TITLE) == null) {
+                        info.put(PdfName.TITLE, new PdfString("Pdf document"));
+                    }
+                    if (info.get(PdfName.CREATOR) == null) {
+                        info.put(PdfName.CREATOR, new PdfString("Unknown"));
+                    }
+                    if (info.get(PdfName.TRAPPED) == null) {
+                        info.put(PdfName.TRAPPED, new PdfName("False"));
+                    }
+                    getExtraCatalog();
+                    if (extraCatalog.get(PdfName.OUTPUTINTENTS) == null) {
+                        PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
+                        out.put(PdfName.OUTPUTCONDITION, new PdfString("SWOP CGATS TR 001-1995"));
+                        out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("CGATS TR 001"));
+                        out.put(PdfName.REGISTRYNAME, new PdfString("http://www.color.org"));
+                        out.put(PdfName.INFO, new PdfString(""));
+                        out.put(PdfName.S, PdfName.GTS_PDFX);
+                        extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
+                    }
+                }
+                if (extraCatalog != null) {
+                    catalog.mergeDifferent(extraCatalog);
+                }
+                PdfIndirectObject indirectCatalog = addToBody(catalog, false);
+                // add the info-object to the body
+                PdfIndirectObject infoObj = addToBody(info, false);
+                PdfIndirectReference encryption = null;
+                PdfObject fileID = null;
+                body.flushObjStm();
+                if (crypto != null) {
+                    PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
+                    encryption = encryptionObject.getIndirectReference();
+                    fileID = crypto.getFileID();
+                }
+                else
+                    fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
+                
+                // write the cross-reference table of the body
+                body.writeCrossReferenceTable(os, indirectCatalog.getIndirectReference(),
+                    infoObj.getIndirectReference(), encryption,  fileID, prevxref);
+
+                // make the trailer
+                if (fullCompression) {
+                    os.write(getISOBytes("startxref\n"));
+                    os.write(getISOBytes(String.valueOf(body.offset())));
+                    os.write(getISOBytes("\n%%EOF\n"));
+                }
+                else {
+                    PdfTrailer trailer = new PdfTrailer(body.size(),
+                    body.offset(),
+                    indirectCatalog.getIndirectReference(),
+                    infoObj.getIndirectReference(),
+                    encryption,
+                    fileID, prevxref);
+                    trailer.toPdf(this, os);
+                }
+                super.close();
+            }
+            catch(IOException ioe) {
+                throw new ExceptionConverter(ioe);
+            }
+        }
+    }
+    
+    // methods
+    
+    /**
+     * Sometimes it is necessary to know where the just added <CODE>Table</CODE> ends.
+     *
+     * For instance to avoid to add another table in a page that is ending up, because
+     * the new table will be probably splitted just after the header (it is an
+     * unpleasant effect, isn't it?).
+     *
+     * Added on September 8th, 2001
+     * by Francesco De Milato
+     * francesco.demilato at tiscalinet.it
+     * @param table the <CODE>Table</CODE>
+     * @return the bottom height of the just added table
+     */
+    
+    public float getTableBottom(Table table) {
+        return pdf.bottom(table) - pdf.indentBottom();
+    }
+    
+    /**
+	 * Gets a pre-rendered table.
+	 * (Contributed by dperezcar at fcc.es) 
+	 * @param table		Contains the table definition.  Its contents are deleted, after being pre-rendered.
+     * @return a PdfTable
+	 */
+	
+	public PdfTable getPdfTable(Table table) {
+		return pdf.getPdfTable(table, true);
+	}
+
+	/**
+	 * Row additions to the original {@link Table} used to build the {@link PdfTable} are processed and pre-rendered,
+	 * and then the contents are deleted. 
+	 * If the pre-rendered table doesn't fit, then it is fully rendered and its data discarded.  
+	 * There shouldn't be any column change in the underlying {@link Table} object.
+	 * (Contributed by dperezcar at fcc.es) 
+	 *
+	 * @param	table		The pre-rendered table obtained from {@link #getPdfTable(Table)} 
+	 * @return	true if the table is rendered and emptied.
+	 * @throws DocumentException
+	 * @see #getPdfTable(Table)
+	 */
+	
+	public boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
+		return pdf.breakTableIfDoesntFit(table);
+	}
+    
+    /**
+     * Checks if a <CODE>Table</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
+     *
+     * @param	table	the table that has to be checked
+     * @param	margin	a certain margin
+     * @return	<CODE>true</CODE> if the <CODE>Table</CODE> fits the page, <CODE>false</CODE> otherwise.
+     */
+    
+    public boolean fitsPage(Table table, float margin) {
+        return pdf.bottom(table) > pdf.indentBottom() + margin;
+    }
+    
+    /**
+     * Checks if a <CODE>Table</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
+     *
+     * @param	table	the table that has to be checked
+     * @return	<CODE>true</CODE> if the <CODE>Table</CODE> fits the page, <CODE>false</CODE> otherwise.
+     */
+    
+    public boolean fitsPage(Table table) {
+        return fitsPage(table, 0);
+    }
+    
+    /**
+     * Checks if a <CODE>PdfPTable</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
+     *
+     * @param	table	the table that has to be checked
+     * @param	margin	a certain margin
+     * @return	<CODE>true</CODE> if the <CODE>PdfPTable</CODE> fits the page, <CODE>false</CODE> otherwise.
+     */
+    public boolean fitsPage(PdfPTable table, float margin) {
+        return pdf.fitsPage(table, margin);
+    }
+    
+    /**
+     * Checks if a <CODE>PdfPTable</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
+     *
+     * @param	table	the table that has to be checked
+     * @return	<CODE>true</CODE> if the <CODE>PdfPTable</CODE> fits the page, <CODE>false</CODE> otherwise.
+     */
+    public boolean fitsPage(PdfPTable table) {
+        return pdf.fitsPage(table, 0);
+    }
+    
+    /**
+     * Gets the current vertical page position.
+     * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects 
+     *   for elements that do not terminate the lines they've started because those lines will get
+     *   terminated. 
+     * @return The current vertical page position.
+     */
+    public float getVerticalPosition(boolean ensureNewLine) {
+        return pdf.getVerticalPosition(ensureNewLine);
+    }
+    
+    /**
+     * Checks if writing is paused.
+     *
+     * @return		<CODE>true</CODE> if writing temporarely has to be paused, <CODE>false</CODE> otherwise.
+     */
+    
+    boolean isPaused() {
+        return pause;
+    }
+    
+    /**
+     * Gets the direct content for this document. There is only one direct content,
+     * multiple calls to this method will allways retrieve the same.
+     * @return the direct content
+     */
+    
+    public PdfContentByte getDirectContent() {
+        if (!open)
+            throw new RuntimeException("The document is not open.");
+        return directContent;
+    }
+    
+    /**
+     * Gets the direct content under for this document. There is only one direct content,
+     * multiple calls to this method will allways retrieve the same.
+     * @return the direct content
+     */
+    
+    public PdfContentByte getDirectContentUnder() {
+        if (!open)
+            throw new RuntimeException("The document is not open.");
+        return directContentUnder;
+    }
+    
+    /**
+     * Resets all the direct contents to empty. This happens when a new page is started.
+     */
+    
+    void resetContent() {
+        directContent.reset();
+        directContentUnder.reset();
+    }
+    
+    /** Gets the AcroForm object.
+     * @return the <CODE>PdfAcroForm</CODE>
+     */
+    
+    public PdfAcroForm getAcroForm() {
+        return pdf.getAcroForm();
+    }
+    
+    /** Gets the root outline.
+     * @return the root outline
+     */
+    
+    public PdfOutline getRootOutline() {
+        return directContent.getRootOutline();
+    }
+    
+    /**
+     * Returns the outputStreamCounter.
+     * @return the outputStreamCounter
+     */
+    public OutputStreamCounter getOs() {
+        return os;
+    }
+        
+    /**
+     * Adds a <CODE>BaseFont</CODE> to the document but not to the page resources.
+     * It is used for templates.
+     * @param bf the <CODE>BaseFont</CODE> to add
+     * @return an <CODE>Object[]</CODE> where position 0 is a <CODE>PdfName</CODE>
+     * and position 1 is an <CODE>PdfIndirectReference</CODE>
+     */
+    
+    FontDetails addSimple(BaseFont bf) {
+        if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
+            return new FontDetails(new PdfName("F" + (fontNumber++)), ((DocumentFont)bf).getIndirectReference(), bf);
+        }
+        FontDetails ret = (FontDetails)documentFonts.get(bf);
+        if (ret == null) {
+            checkPDFXConformance(this, PDFXKEY_FONT, bf);
+            ret = new FontDetails(new PdfName("F" + (fontNumber++)), body.getPdfIndirectReference(), bf);
+            documentFonts.put(bf, ret);
+        }
+        return ret;
+    }
+    
+    void eliminateFontSubset(PdfDictionary fonts) {
+        for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
+            FontDetails ft = (FontDetails)it.next();
+            if (fonts.get(ft.getFontName()) != null)
+                ft.setSubset(false);
+        }
+    }
+    
+    /**
+     * Adds a <CODE>SpotColor</CODE> to the document but not to the page resources.
+     * @param spc the <CODE>SpotColor</CODE> to add
+     * @return an <CODE>Object[]</CODE> where position 0 is a <CODE>PdfName</CODE>
+     * and position 1 is an <CODE>PdfIndirectReference</CODE>
+     */
+    
+    ColorDetails addSimple(PdfSpotColor spc) {
+        ColorDetails ret = (ColorDetails)documentColors.get(spc);
+        if (ret == null) {
+            ret = new ColorDetails(new PdfName("CS" + (colorNumber++)), body.getPdfIndirectReference(), spc);
+            documentColors.put(spc, ret);
+        }
+        return ret;
+    }
+    
+    ColorDetails addSimplePatternColorspace(Color color) {
+        int type = ExtendedColor.getType(color);
+        if (type == ExtendedColor.TYPE_PATTERN || type == ExtendedColor.TYPE_SHADING)
+            throw new RuntimeException("An uncolored tile pattern can not have another pattern or shading as color.");
+        try {
+            switch (type) {
+                case ExtendedColor.TYPE_RGB:
+                    if (patternColorspaceRGB == null) {
+                        patternColorspaceRGB = new ColorDetails(new PdfName("CS" + (colorNumber++)), body.getPdfIndirectReference(), null);
+                        PdfArray array = new PdfArray(PdfName.PATTERN);
+                        array.add(PdfName.DEVICERGB);
+                        PdfIndirectObject cobj = addToBody(array, patternColorspaceRGB.getIndirectReference());
+                    }
+                    return patternColorspaceRGB;
+                case ExtendedColor.TYPE_CMYK:
+                    if (patternColorspaceCMYK == null) {
+                        patternColorspaceCMYK = new ColorDetails(new PdfName("CS" + (colorNumber++)), body.getPdfIndirectReference(), null);
+                        PdfArray array = new PdfArray(PdfName.PATTERN);
+                        array.add(PdfName.DEVICECMYK);
+                        PdfIndirectObject cobj = addToBody(array, patternColorspaceCMYK.getIndirectReference());
+                    }
+                    return patternColorspaceCMYK;
+                case ExtendedColor.TYPE_GRAY:
+                    if (patternColorspaceGRAY == null) {
+                        patternColorspaceGRAY = new ColorDetails(new PdfName("CS" + (colorNumber++)), body.getPdfIndirectReference(), null);
+                        PdfArray array = new PdfArray(PdfName.PATTERN);
+                        array.add(PdfName.DEVICEGRAY);
+                        PdfIndirectObject cobj = addToBody(array, patternColorspaceGRAY.getIndirectReference());
+                    }
+                    return patternColorspaceGRAY;
+                case ExtendedColor.TYPE_SEPARATION: {
+                    ColorDetails details = addSimple(((SpotColor)color).getPdfSpotColor());
+                    ColorDetails patternDetails = (ColorDetails)documentSpotPatterns.get(details);
+                    if (patternDetails == null) {
+                        patternDetails = new ColorDetails(new PdfName("CS" + (colorNumber++)), body.getPdfIndirectReference(), null);
+                        PdfArray array = new PdfArray(PdfName.PATTERN);
+                        array.add(details.getIndirectReference());
+                        PdfIndirectObject cobj = addToBody(array, patternDetails.getIndirectReference());
+                        documentSpotPatterns.put(details, patternDetails);
+                    }
+                    return patternDetails;
+                }
+                default:
+                    throw new RuntimeException("Invalid color type in PdfWriter.addSimplePatternColorspace().");
+            }
+        }
+        catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+    
+    void addSimpleShadingPattern(PdfShadingPattern shading) {
+        if (!documentShadingPatterns.containsKey(shading)) {
+            shading.setName(patternNumber);
+            ++patternNumber;
+            documentShadingPatterns.put(shading, null);
+            addSimpleShading(shading.getShading());
+        }
+    }
+    
+    void addSimpleShading(PdfShading shading) {
+        if (!documentShadings.containsKey(shading)) {
+            documentShadings.put(shading, null);
+            shading.setName(documentShadings.size());
+        }
+    }
+    
+    PdfObject[] addSimpleExtGState(PdfDictionary gstate) {
+        if (!documentExtGState.containsKey(gstate)) {
+            checkPDFXConformance(this, PDFXKEY_GSTATE, gstate);
+            documentExtGState.put(gstate, new PdfObject[]{new PdfName("GS" + (documentExtGState.size() + 1)), getPdfIndirectReference()});
+        }
+        return (PdfObject[])documentExtGState.get(gstate);
+    }
+    
+    void registerLayer(PdfOCG layer) {
+        checkPDFXConformance(this, PDFXKEY_LAYER, null);
+        if (layer instanceof PdfLayer) {
+            PdfLayer la = (PdfLayer)layer;
+            if (la.getTitle() == null) {
+                if (!documentOCG.contains(layer)) {
+                    documentOCG.add(layer);
+                    documentOCGorder.add(layer);
+                }
+            }
+            else {
+                documentOCGorder.add(layer);
+            }
+        }
+        else
+            throw new IllegalArgumentException("Only PdfLayer is accepted.");
+    }
+    
+    PdfName addSimpleLayer(PdfOCG layer) {
+        if (!documentLayers.containsKey(layer)) {
+            checkPDFXConformance(this, PDFXKEY_LAYER, null);
+            documentLayers.put(layer, new PdfName("OC" + (documentLayers.size() + 1)));
+        }
+        return (PdfName)documentLayers.get(layer);
+    }
+    
+    /**
+     * Gets the <CODE>PdfDocument</CODE> associated with this writer.
+     * @return the <CODE>PdfDocument</CODE>
+     */
+    
+    PdfDocument getPdfDocument() {
+        return pdf;
+    }
+    
+    /**
+     * Gets a <CODE>PdfIndirectReference</CODE> for an object that
+     * will be created in the future.
+     * @return the <CODE>PdfIndirectReference</CODE>
+     */
+    
+    public PdfIndirectReference getPdfIndirectReference() {
+        return body.getPdfIndirectReference();
+    }
+    
+    int getIndirectReferenceNumber() {
+        return body.getIndirectReferenceNumber();
+    }
+    
+    PdfName addSimplePattern(PdfPatternPainter painter) {
+        PdfName name = (PdfName)documentPatterns.get(painter);
+        try {
+            if ( name == null ) {
+                name = new PdfName("P" + patternNumber);
+                ++patternNumber;
+                documentPatterns.put(painter, name);
+            }
+        } catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        return name;
+    }
+    
+    /**
+     * Adds a template to the document but not to the page resources.
+     * @param template the template to add
+     * @param forcedName the template name, rather than a generated one. Can be null
+     * @return the <CODE>PdfName</CODE> for this template
+     */
+    
+    PdfName addDirectTemplateSimple(PdfTemplate template, PdfName forcedName) {
+        PdfIndirectReference ref = template.getIndirectReference();
+        Object obj[] = (Object[])formXObjects.get(ref);
+        PdfName name = null;
+        try {
+            if (obj == null) {
+                if (forcedName == null) {
+                    name = new PdfName("Xf" + formXObjectsCounter);
+                    ++formXObjectsCounter;
+                }
+                else
+                    name = forcedName;
+                if (template.getType() == PdfTemplate.TYPE_IMPORTED)
+                    template = null;
+                formXObjects.put(ref, new Object[]{name, template});
+            }
+            else
+                name = (PdfName)obj[0];
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        return name;
+    }
+    
+    /**
+     * Sets the <CODE>PdfPageEvent</CODE> for this document.
+     * @param pageEvent the <CODE>PdfPageEvent</CODE> for this document
+     */
+    
+    public void setPageEvent(PdfPageEvent pageEvent) {
+        this.pageEvent = pageEvent;
+    }
+    
+    /**
+     * Gets the <CODE>PdfPageEvent</CODE> for this document or <CODE>null</CODE>
+     * if none is set.
+     * @return the <CODE>PdfPageEvent</CODE> for this document or <CODE>null</CODE>
+     * if none is set
+     */
+    
+    public PdfPageEvent getPageEvent() {
+        return pageEvent;
+    }
+    
+    /**
+     * Adds the local destinations to the body of the document.
+     * @param dest the <CODE>HashMap</CODE> containing the destinations
+     * @throws IOException on error
+     */
+    
+    void addLocalDestinations(TreeMap dest) throws IOException {
+        for (Iterator i = dest.keySet().iterator(); i.hasNext();) {
+            String name = (String)i.next();
+            Object obj[] = (Object[])dest.get(name);
+            PdfDestination destination = (PdfDestination)obj[2];
+            if (destination == null)
+                throw new RuntimeException("The name '" + name + "' has no local destination.");
+            if (obj[1] == null)
+                obj[1] = getPdfIndirectReference();
+            PdfIndirectObject iob = addToBody(destination, (PdfIndirectReference)obj[1]);
+        }
+    }
+    
+    /**
+     * Gets the current pagenumber of this document.
+     *
+     * @return a page number
+     */
+    
+    public int getPageNumber() {
+        return pdf.getPageNumber();
+    }
+    
+    /**
+     * Sets the viewer preferences by ORing some constants.
+     * <p>
+     * <ul>
+     * <li>The page layout to be used when the document is opened (choose one).
+     *   <ul>
+     *   <li><b>PageLayoutSinglePage</b> - Display one page at a time. (default)
+     *   <li><b>PageLayoutOneColumn</b> - Display the pages in one column.
+     *   <li><b>PageLayoutTwoColumnLeft</b> - Display the pages in two columns, with
+     *       oddnumbered pages on the left.
+     *   <li><b>PageLayoutTwoColumnRight</b> - Display the pages in two columns, with
+     *       oddnumbered pages on the right.
+     *   </ul>
+     * <li>The page mode how the document should be displayed
+     *     when opened (choose one).
+     *   <ul>
+     *   <li><b>PageModeUseNone</b> - Neither document outline nor thumbnail images visible. (default)
+     *   <li><b>PageModeUseOutlines</b> - Document outline visible.
+     *   <li><b>PageModeUseThumbs</b> - Thumbnail images visible.
+     *   <li><b>PageModeFullScreen</b> - Full-screen mode, with no menu bar, window
+     *       controls, or any other window visible.
+     *   <li><b>PageModeUseOC</b> - Optional content group panel visible
+     *   </ul>
+     * <li><b>HideToolbar</b> - A flag specifying whether to hide the viewer application's tool
+     *     bars when the document is active.
+     * <li><b>HideMenubar</b> - A flag specifying whether to hide the viewer application's
+     *     menu bar when the document is active.
+     * <li><b>HideWindowUI</b> - A flag specifying whether to hide user interface elements in
+     *     the document's window (such as scroll bars and navigation controls),
+     *     leaving only the document's contents displayed.
+     * <li><b>FitWindow</b> - A flag specifying whether to resize the document's window to
+     *     fit the size of the first displayed page.
+     * <li><b>CenterWindow</b> - A flag specifying whether to position the document's window
+     *     in the center of the screen.
+     * <li><b>DisplayDocTitle</b> - A flag specifying whether to display the document's title
+     *     in the top bar.
+     * <li>The predominant reading order for text. This entry has no direct effect on the
+     *     document's contents or page numbering, but can be used to determine the relative
+     *     positioning of pages when displayed side by side or printed <i>n-up</i> (choose one).
+     *   <ul>
+     *   <li><b>DirectionL2R</b> - Left to right
+     *   <li><b>DirectionR2L</b> - Right to left (including vertical writing systems such as
+     *       Chinese, Japanese, and Korean)
+     *   </ul>
+     * <li>The document's page mode, specifying how to display the
+     *     document on exiting full-screen mode. It is meaningful only
+     *     if the page mode is <b>PageModeFullScreen</b> (choose one).
+     *   <ul>
+     *   <li><b>NonFullScreenPageModeUseNone</b> - Neither document outline nor thumbnail images
+     *       visible
+     *   <li><b>NonFullScreenPageModeUseOutlines</b> - Document outline visible
+     *   <li><b>NonFullScreenPageModeUseThumbs</b> - Thumbnail images visible
+     *   <li><b>NonFullScreenPageModeUseOC</b> - Optional content group panel visible
+     *   </ul>
+     * <li><b>PrintScalingNone</b> - Indicates that the print dialog should reflect no page scaling.
+     * </ul>
+     * @param preferences the viewer preferences
+     */
+    
+    public void setViewerPreferences(int preferences) {
+        pdf.setViewerPreferences(preferences);
+    }
+    
+    /** Sets the encryption options for this document. The userPassword and the
+     *  ownerPassword can be null or have zero length. In this case the ownerPassword
+     *  is replaced by a random string. The open permissions for the document can be
+     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+     *  The permissions can be combined by ORing them.
+     * @param userPassword the user password. Can be null or empty
+     * @param ownerPassword the owner password. Can be null or empty
+     * @param permissions the user permissions
+     * @param strength128Bits <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
+     * @throws DocumentException if the document is already open
+     */
+    public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
+        if (pdf.isOpen())
+            throw new DocumentException("Encryption can only be added before opening the document.");
+        crypto = new PdfEncryption();
+        crypto.setupAllKeys(userPassword, ownerPassword, permissions, strength128Bits);
+    }
+    
+    /**
+     * Sets the encryption options for this document. The userPassword and the
+     *  ownerPassword can be null or have zero length. In this case the ownerPassword
+     *  is replaced by a random string. The open permissions for the document can be
+     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+     *  The permissions can be combined by ORing them.
+     * @param strength <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
+     * @param userPassword the user password. Can be null or empty
+     * @param ownerPassword the owner password. Can be null or empty
+     * @param permissions the user permissions
+     * @throws DocumentException if the document is already open
+     */
+    public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
+        setEncryption(getISOBytes(userPassword), getISOBytes(ownerPassword), permissions, strength);
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object) throws IOException {
+        PdfIndirectObject iobj = body.add(object);
+        return iobj;
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @param inObjStm
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object, boolean inObjStm) throws IOException {
+        PdfIndirectObject iobj = body.add(object, inObjStm);
+        return iobj;
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @param ref
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref) throws IOException {
+        PdfIndirectObject iobj = body.add(object, ref);
+        return iobj;
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @param ref
+     * @param inObjStm
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
+        PdfIndirectObject iobj = body.add(object, ref, inObjStm);
+        return iobj;
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @param refNumber
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object, int refNumber) throws IOException {
+        PdfIndirectObject iobj = body.add(object, refNumber);
+        return iobj;
+    }
+    
+    /**
+     * Adds an object to the PDF body.
+     * @param object
+     * @param refNumber
+     * @param inObjStm
+     * @return a PdfIndirectObject
+     * @throws IOException
+     */
+    public PdfIndirectObject addToBody(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
+        PdfIndirectObject iobj = body.add(object, refNumber, inObjStm);
+        return iobj;
+    }
+    
+    /** When the document opens it will jump to the destination with
+     * this name.
+     * @param name the name of the destination to jump to
+     */
+    public void setOpenAction(String name) {
+        pdf.setOpenAction(name);
+    }
+    
+    /** Additional-actions defining the actions to be taken in
+     * response to various trigger events affecting the document
+     * as a whole. The actions types allowed are: <CODE>DOCUMENT_CLOSE</CODE>,
+     * <CODE>WILL_SAVE</CODE>, <CODE>DID_SAVE</CODE>, <CODE>WILL_PRINT</CODE>
+     * and <CODE>DID_PRINT</CODE>.
+     *
+     * @param actionType the action type
+     * @param action the action to execute in response to the trigger
+     * @throws PdfException on invalid action type
+     */
+    public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
+        if (!(actionType.equals(DOCUMENT_CLOSE) ||
+        actionType.equals(WILL_SAVE) ||
+        actionType.equals(DID_SAVE) ||
+        actionType.equals(WILL_PRINT) ||
+        actionType.equals(DID_PRINT))) {
+            throw new PdfException("Invalid additional action type: " + actionType.toString());
+        }
+        pdf.addAdditionalAction(actionType, action);
+    }
+    
+    /** When the document opens this <CODE>action</CODE> will be
+     * invoked.
+     * @param action the action to be invoked
+     */
+    public void setOpenAction(PdfAction action) {
+        pdf.setOpenAction(action);
+    }
+    
+    /** Sets the page labels
+     * @param pageLabels the page labels
+     */
+    public void setPageLabels(PdfPageLabels pageLabels) {
+        pdf.setPageLabels(pageLabels);
+    }
+    
+    PdfEncryption getEncryption() {
+        return crypto;
+    }
+    
+    RandomAccessFileOrArray getReaderFile(PdfReader reader) {
+        return currentPdfReaderInstance.getReaderFile();
+    }
+    
+    protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
+        return currentPdfReaderInstance.getNewObjectNumber(number, generation);
+    }
+    
+    /** Gets a page from other PDF document. The page can be used as
+     * any other PdfTemplate. Note that calling this method more than
+     * once with the same parameters will retrieve the same object.
+     * @param reader the PDF document where the page is
+     * @param pageNumber the page number. The first page is 1
+     * @return the template representing the imported page
+     */
+    public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
+        PdfReaderInstance inst = (PdfReaderInstance)importedPages.get(reader);
+        if (inst == null) {
+            inst = reader.getPdfReaderInstance(this);
+            importedPages.put(reader, inst);
+        }
+        return inst.getImportedPage(pageNumber);
+    }
+    
+    /** Adds a JavaScript action at the document level. When the document
+     * opens all this JavaScript runs.
+     * @param js The JavaScrip action
+     */
+    public void addJavaScript(PdfAction js) {
+        pdf.addJavaScript(js);
+    }
+    
+    /** Adds a JavaScript action at the document level. When the document
+     * opens all this JavaScript runs.
+     * @param code the JavaScript code
+     * @param unicode select JavaScript unicode. Note that the internal
+     * Acrobat JavaScript engine does not support unicode,
+     * so this may or may not work for you
+     */
+    public void addJavaScript(String code, boolean unicode) {
+        addJavaScript(PdfAction.javaScript(code, this, unicode));
+    }
+    
+    /** Adds a JavaScript action at the document level. When the document
+     * opens all this JavaScript runs.
+     * @param code the JavaScript code
+     */
+    public void addJavaScript(String code) {
+        addJavaScript(code, false);
+    }
+    
+    /** Sets the crop box. The crop box should not be rotated even if the
+     * page is rotated. This change only takes effect in the next
+     * page.
+     * @param crop the crop box
+     */
+    public void setCropBoxSize(Rectangle crop) {
+        pdf.setCropBoxSize(crop);
+    }
+    
+    /** Gets a reference to a page existing or not. If the page does not exist
+     * yet the reference will be created in advance. If on closing the document, a
+     * page number greater than the total number of pages was requested, an
+     * exception is thrown.
+     * @param page the page number. The first page is 1
+     * @return the reference to the page
+     */
+    public PdfIndirectReference getPageReference(int page) {
+        --page;
+        if (page < 0)
+            throw new IndexOutOfBoundsException("The page numbers start at 1.");
+        PdfIndirectReference ref;
+        if (page < pageReferences.size()) {
+            ref = (PdfIndirectReference)pageReferences.get(page);
+            if (ref == null) {
+                ref = body.getPdfIndirectReference();
+                pageReferences.set(page, ref);
+            }
+        }
+        else {
+            int empty = page - pageReferences.size();
+            for (int k = 0; k < empty; ++k)
+                pageReferences.add(null);
+            ref = body.getPdfIndirectReference();
+            pageReferences.add(ref);
+        }
+        return ref;
+    }
+    
+    PdfIndirectReference getCurrentPage() {
+        return getPageReference(currentPageNumber);
+    }
+    
+    int getCurrentPageNumber() {
+        return currentPageNumber;
+    }
+    
+    /** Adds the <CODE>PdfAnnotation</CODE> to the calculation order
+     * array.
+     * @param annot the <CODE>PdfAnnotation</CODE> to be added
+     */
+    public void addCalculationOrder(PdfFormField annot) {
+        pdf.addCalculationOrder(annot);
+    }
+    
+    /** Set the signature flags.
+     * @param f the flags. This flags are ORed with current ones
+     */
+    public void setSigFlags(int f) {
+        pdf.setSigFlags(f);
+    }
+    
+    /** Adds a <CODE>PdfAnnotation</CODE> or a <CODE>PdfFormField</CODE>
+     * to the document. Only the top parent of a <CODE>PdfFormField</CODE>
+     * needs to be added.
+     * @param annot the <CODE>PdfAnnotation</CODE> or the <CODE>PdfFormField</CODE> to add
+     */
+    public void addAnnotation(PdfAnnotation annot) {
+        pdf.addAnnotation(annot);
+    }
+    
+    void addAnnotation(PdfAnnotation annot, int page) {
+        addAnnotation(annot);
+    }
+    
+    /** Sets the PDF version. Must be used right before the document
+     * is opened. Valid options are VERSION_1_2, VERSION_1_3,
+     * VERSION_1_4, VERSION_1_5 and VERSION_1_6. VERSION_1_4 is the default.
+     * @param version the version number
+     */
+    public void setPdfVersion(char version) {
+        if (HEADER.length > VPOINT)
+            HEADER[VPOINT] = (byte)version;
+    }
+    
+    /** Reorder the pages in the document. A <CODE>null</CODE> argument value
+     * only returns the number of pages to process. It is
+     * advisable to issue a <CODE>Document.newPage()</CODE>
+     * before using this method.
+     * @return the total number of pages
+     * @param order an array with the new page sequence. It must have the
+     * same size as the number of pages.
+     * @throws DocumentException if all the pages are not present in the array
+     */
+    public int reorderPages(int order[]) throws DocumentException {
+        return root.reorderPages(order);
+    }
+    
+    /** Gets the space/character extra spacing ratio for
+     * fully justified text.
+     * @return the space/character extra spacing ratio
+     */
+    public float getSpaceCharRatio() {
+        return spaceCharRatio;
+    }
+    
+    /** Sets the ratio between the extra word spacing and the extra character spacing
+     * when the text is fully justified.
+     * Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing.
+     * If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing
+     * will be zero.
+     * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
+     */
+    public void setSpaceCharRatio(float spaceCharRatio) {
+        if (spaceCharRatio < 0.001f)
+            this.spaceCharRatio = 0.001f;
+        else
+            this.spaceCharRatio = spaceCharRatio;
+    }
+    
+    /** Sets the run direction. This is only used as a placeholder
+     * as it does not affect anything.
+     * @param runDirection the run direction
+     */    
+    public void setRunDirection(int runDirection) {
+        if (runDirection < RUN_DIRECTION_NO_BIDI || runDirection > RUN_DIRECTION_RTL)
+            throw new RuntimeException("Invalid run direction: " + runDirection);
+        this.runDirection = runDirection;
+    }
+    
+    /** Gets the run direction.
+     * @return the run direction
+     */    
+    public int getRunDirection() {
+        return runDirection;
+    }
+
+    /**
+     * Sets the display duration for the page (for presentations)
+     * @param seconds   the number of seconds to display the page
+     */
+    public void setDuration(int seconds) {
+        pdf.setDuration(seconds);
+    }
+    
+    /**
+     * Sets the transition for the page
+     * @param transition   the Transition object
+     */
+    public void setTransition(PdfTransition transition) {
+        pdf.setTransition(transition);
+    }
+    
+    /** Writes the reader to the document and frees the memory used by it.
+     * The main use is when concatenating multiple documents to keep the
+     * memory usage restricted to the current appending document.
+     * @param reader the <CODE>PdfReader</CODE> to free
+     * @throws IOException on error
+     */    
+    public void freeReader(PdfReader reader) throws IOException {
+        currentPdfReaderInstance = (PdfReaderInstance)importedPages.get(reader);
+        if (currentPdfReaderInstance == null)
+            return;
+        currentPdfReaderInstance.writeAllPages();
+        currentPdfReaderInstance = null;
+        importedPages.remove(reader);
+    }
+    
+    /** Sets the open and close page additional action.
+     * @param actionType the action type. It can be <CODE>PdfWriter.PAGE_OPEN</CODE>
+     * or <CODE>PdfWriter.PAGE_CLOSE</CODE>
+     * @param action the action to perform
+     * @throws PdfException if the action type is invalid
+     */    
+    public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
+        if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
+            throw new PdfException("Invalid page additional action type: " + actionType.toString());
+        pdf.setPageAction(actionType, action);
+    }
+    
+    /** Gets the current document size. This size only includes
+     * the data already writen to the output stream, it does not
+     * include templates or fonts. It is usefull if used with
+     * <CODE>freeReader()</CODE> when concatenating many documents
+     * and an idea of the current size is needed.
+     * @return the approximate size without fonts or templates
+     */    
+    public int getCurrentDocumentSize() {
+        return body.offset() + body.size() * 20 + 0x48;
+    }
+    
+    /** Getter for property strictImageSequence.
+     * @return value of property strictImageSequence
+     *
+     */
+    public boolean isStrictImageSequence() {
+        return pdf.isStrictImageSequence();
+    }
+    
+    /** Sets the image sequence to follow the text in strict order.
+     * @param strictImageSequence new value of property strictImageSequence
+     *
+     */
+    public void setStrictImageSequence(boolean strictImageSequence) {
+        pdf.setStrictImageSequence(strictImageSequence);
+    }
+    
+    /**
+     * If you use setPageEmpty(false), invoking newPage() after a blank page will add a newPage.
+     * @param pageEmpty the state
+     */
+    public void setPageEmpty(boolean pageEmpty) {
+        pdf.setPageEmpty(pageEmpty);
+    }
+
+    /** Gets the info dictionary for changing.
+     * @return the info dictionary
+     */    
+    public PdfDictionary getInfo() {
+        return ((PdfDocument)document).getInfo();
+    }
+    
+    /**
+     * Sets extra keys to the catalog.
+     * @return the catalog to change
+     */    
+    public PdfDictionary getExtraCatalog() {
+        if (extraCatalog == null)
+            extraCatalog = new PdfDictionary();
+        return this.extraCatalog;
+    }
+    
+    /**
+     * Sets the document in a suitable way to do page reordering.
+     */    
+     public void setLinearPageMode() {
+        root.setLinearMode(null);
+    }
+    
+    /** Getter for property group.
+     * @return Value of property group.
+     *
+     */
+    public PdfDictionary getGroup() {
+        return this.group;
+    }
+    
+    /** Setter for property group.
+     * @param group New value of property group.
+     *
+     */
+    public void setGroup(PdfDictionary group) {
+        this.group = group;
+    }
+    
+    /**
+     * Sets the PDFX conformance level. Allowed values are PDFX1A2001 and PDFX32002. It
+     * must be called before opening the document.
+     * @param pdfxConformance the conformance level
+     */    
+    public void setPDFXConformance(int pdfxConformance) {
+        if (this.pdfxConformance == pdfxConformance)
+            return;
+        if (pdf.isOpen())
+            throw new PdfXConformanceException("PDFX conformance can only be set before opening the document.");
+        if (crypto != null)
+            throw new PdfXConformanceException("A PDFX conforming document cannot be encrypted.");
+        if (pdfxConformance != PDFXNONE)
+            setPdfVersion(VERSION_1_3);
+        this.pdfxConformance = pdfxConformance;
+    }
+ 
+    /**
+     * Gets the PDFX conformance level.
+     * @return the PDFX conformance level
+     */    
+    public int getPDFXConformance() {
+        return pdfxConformance;
+    }
+    
+    static void checkPDFXConformance(PdfWriter writer, int key, Object obj1) {
+        if (writer == null || writer.pdfxConformance == PDFXNONE)
+            return;
+        int conf = writer.pdfxConformance;
+        switch (key) {
+            case PDFXKEY_COLOR:
+                switch (conf) {
+                    case PDFX1A2001:
+                        if (obj1 instanceof ExtendedColor) {
+                            ExtendedColor ec = (ExtendedColor)obj1;
+                            switch (ec.getType()) {
+                                case ExtendedColor.TYPE_CMYK:
+                                case ExtendedColor.TYPE_GRAY:
+                                    return;
+                                case ExtendedColor.TYPE_RGB:
+                                    throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+                                case ExtendedColor.TYPE_SEPARATION:
+                                    SpotColor sc = (SpotColor)ec;
+                                    checkPDFXConformance(writer, PDFXKEY_COLOR, sc.getPdfSpotColor().getAlternativeCS());
+                                    break;
+                                case ExtendedColor.TYPE_SHADING:
+                                    ShadingColor xc = (ShadingColor)ec;
+                                    checkPDFXConformance(writer, PDFXKEY_COLOR, xc.getPdfShadingPattern().getShading().getColorSpace());
+                                    break;
+                                case ExtendedColor.TYPE_PATTERN:
+                                    PatternColor pc = (PatternColor)ec;
+                                    checkPDFXConformance(writer, PDFXKEY_COLOR, pc.getPainter().getDefaultColor());
+                                    break;
+                            }
+                        }
+                        else if (obj1 instanceof Color)
+                            throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+                        break;
+                }
+                break;
+            case PDFXKEY_CMYK:
+                break;
+            case PDFXKEY_RGB:
+                if (conf == PDFX1A2001)
+                    throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+                break;
+            case PDFXKEY_FONT:
+                if (!((BaseFont)obj1).isEmbedded())
+                    throw new PdfXConformanceException("All the fonts must be embedded.");
+                break;
+            case PDFXKEY_IMAGE:
+                PdfImage image = (PdfImage)obj1;
+                if (image.get(PdfName.SMASK) != null)
+                    throw new PdfXConformanceException("The /SMask key is not allowed in images.");
+                switch (conf) {
+                    case PDFX1A2001:
+                        PdfObject cs = image.get(PdfName.COLORSPACE);
+                        if (cs == null)
+                            return;
+                        if (cs.isName()) {
+                            if (PdfName.DEVICERGB.equals(cs))
+                                throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+                        }
+                        else if (cs.isArray()) {
+                            if (PdfName.CALRGB.equals((PdfObject)((PdfArray)cs).getArrayList().get(0)))
+                                throw new PdfXConformanceException("Colorspace CalRGB is not allowed.");
+                        }
+                        break;
+                }
+                break;
+            case PDFXKEY_GSTATE:
+                PdfDictionary gs = (PdfDictionary)obj1;
+                PdfObject obj = gs.get(PdfName.BM);
+                if (obj != null && !PdfGState.BM_NORMAL.equals(obj) && !PdfGState.BM_COMPATIBLE.equals(obj))
+                    throw new PdfXConformanceException("Blend mode " + obj.toString() + " not allowed.");
+                obj = gs.get(PdfName.CA);
+                double v = 0.0;
+                if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
+                    throw new PdfXConformanceException("Transparency is not allowed: /CA = " + v);
+                obj = gs.get(PdfName.ca);
+                v = 0.0;
+                if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
+                    throw new PdfXConformanceException("Transparency is not allowed: /ca = " + v);
+                break;
+            case PDFXKEY_LAYER:
+                throw new PdfXConformanceException("Layers are not allowed.");
+        }
+    }
+    
+    /**
+     * Sets the values of the output intent dictionary. Null values are allowed to
+     * suppress any key.
+     * @param outputConditionIdentifier a value
+     * @param outputCondition a value
+     * @param registryName a value
+     * @param info a value
+     * @param destOutputProfile a value
+     * @throws IOException on error
+     */    
+    public void setOutputIntents(String outputConditionIdentifier, String outputCondition, String registryName, String info, byte destOutputProfile[]) throws IOException {
+        getExtraCatalog();
+        PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
+        if (outputCondition != null)
+            out.put(PdfName.OUTPUTCONDITION, new PdfString(outputCondition, PdfObject.TEXT_UNICODE));
+        if (outputConditionIdentifier != null)
+            out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString(outputConditionIdentifier, PdfObject.TEXT_UNICODE));
+        if (registryName != null)
+            out.put(PdfName.REGISTRYNAME, new PdfString(registryName, PdfObject.TEXT_UNICODE));
+        if (info != null)
+            out.put(PdfName.INFO, new PdfString(registryName, PdfObject.TEXT_UNICODE));
+        if (destOutputProfile != null) {
+            PdfStream stream = new PdfStream(destOutputProfile);
+            stream.flateCompress();
+            out.put(PdfName.DESTOUTPUTPROFILE, addToBody(stream).getIndirectReference());
+        }
+        out.put(PdfName.S, PdfName.GTS_PDFX);
+        extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
+    }
+    
+    private static String getNameString(PdfDictionary dic, PdfName key) {
+        PdfObject obj = PdfReader.getPdfObject(dic.get(key));
+        if (obj == null || !obj.isString())
+            return null;
+        return ((PdfString)obj).toUnicodeString();
+    }
+    
+    /**
+     * Copies the output intent dictionary from other document to this one.
+     * @param reader the other document
+     * @param checkExistence <CODE>true</CODE> to just check for the existence of a valid output intent
+     * dictionary, <CODE>false</CODE> to insert the dictionary if it exists
+     * @throws IOException on error
+     * @return <CODE>true</CODE> if the output intent dictionary exists, <CODE>false</CODE>
+     * otherwise
+     */    
+    public boolean setOutputIntents(PdfReader reader, boolean checkExistence) throws IOException {
+        PdfDictionary catalog = reader.getCatalog();
+        PdfArray outs = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.OUTPUTINTENTS));
+        if (outs == null)
+            return false;
+        ArrayList arr = outs.getArrayList();
+        if (arr.size() == 0)
+            return false;
+        PdfDictionary out = (PdfDictionary)PdfReader.getPdfObject((PdfObject)arr.get(0));
+        PdfObject obj = PdfReader.getPdfObject(out.get(PdfName.S));
+        if (obj == null || !PdfName.GTS_PDFX.equals(obj))
+            return false;
+        if (checkExistence)
+            return true;
+        PRStream stream = (PRStream)PdfReader.getPdfObject(out.get(PdfName.DESTOUTPUTPROFILE));
+        byte destProfile[] = null;
+        if (stream != null) {
+            destProfile = PdfReader.getStreamBytes(stream);
+        }
+        setOutputIntents(getNameString(out, PdfName.OUTPUTCONDITIONIDENTIFIER), getNameString(out, PdfName.OUTPUTCONDITION),
+            getNameString(out, PdfName.REGISTRYNAME), getNameString(out, PdfName.INFO), destProfile);
+        return true;
+    }
+    
+    /**
+     * Sets the page box sizes. Allowed names are: "crop", "trim", "art" and "bleed".
+     * @param boxName the box size
+     * @param size the size
+     */    
+    public void setBoxSize(String boxName, Rectangle size) {
+        pdf.setBoxSize(boxName, size);
+    }
+    
+    /**
+     * Gets the default colorspaces.
+     * @return the default colorspaces
+     */    
+    public PdfDictionary getDefaultColorspace() {
+        return defaultColorspace;
+    }
+
+    /**
+     * Sets the default colorspace that will be applied to all the document.
+     * The colorspace is only applied if another colorspace with the same name
+     * is not present in the content.
+     * <p>
+     * The colorspace is applied immediately when creating templates and at the page
+     * end for the main document content.
+     * @param key the name of the colorspace. It can be <CODE>PdfName.DEFAULTGRAY</CODE>, <CODE>PdfName.DEFAULTRGB</CODE>
+     * or <CODE>PdfName.DEFAULTCMYK</CODE>
+     * @param cs the colorspace. A <CODE>null</CODE> or <CODE>PdfNull</CODE> removes any colorspace with the same name
+     */    
+    public void setDefaultColorspace(PdfName key, PdfObject cs) {
+        if (cs == null || cs.isNull())
+            defaultColorspace.remove(key);
+        defaultColorspace.put(key, cs);
+    }
+
+    /**
+     * Gets the 1.5 compression status.
+     * @return <code>true</code> if the 1.5 compression is on
+     */
+    public boolean isFullCompression() {
+        return this.fullCompression;
+    }
+    
+    /**
+     * Sets the document's compression to the new 1.5 mode with object streams and xref
+     * streams. It can be set at any time but once set it can't be unset.
+     * <p>
+     * If set before opening the document it will also set the pdf version to 1.5.
+     */
+    public void setFullCompression() {
+        this.fullCompression = true;
+        setPdfVersion(VERSION_1_5);
+    }
+    
+    /**
+     * Gets the <B>Optional Content Properties Dictionary</B>. Each call fills the dictionary with the current layer
+     * state. It's advisable to only call this method right before close and do any modifications
+     * at that time.
+     * @return the Optional Content Properties Dictionary
+     */    
+    public PdfOCProperties getOCProperties() {
+        fillOCProperties(true);
+        return OCProperties;
+    }
+    
+    /**
+     * Sets a collection of optional content groups whose states are intended to follow
+     * a "radio button" paradigm. That is, the state of at most one optional
+     * content group in the array should be ON at a time: if one group is turned
+     * ON, all others must be turned OFF.
+     * @param group the radio group
+     */    
+    public void addOCGRadioGroup(ArrayList group) {
+        PdfArray ar = new PdfArray();
+        for (int k = 0; k < group.size(); ++k) {
+            PdfLayer layer = (PdfLayer)group.get(k);
+            if (layer.getTitle() == null)
+                ar.add(layer.getRef());
+        }
+        if (ar.size() == 0)
+            return;
+        OCGRadioGroup.add(ar);
+    }
+    
+    /**
+     * Sets the the thumbnail image for the current page.
+     * @param image the image
+     * @throws PdfException on error
+     * @throws DocumentException or error
+     */    
+    public void setThumbnail(Image image) throws PdfException, DocumentException {
+        pdf.setThumbnail(image);
+    }
+
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PdfXConformanceException.java b/LibrarySource/com/lowagie/text/pdf/PdfXConformanceException.java
new file mode 100644
index 0000000..574f229
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PdfXConformanceException.java
@@ -0,0 +1,70 @@
+/*
+ * $Id: PdfXConformanceException.java,v 1.2 2005/02/17 09:20:54 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2004 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ *
+ * @author  psoares
+ */
+public class PdfXConformanceException extends RuntimeException {
+    
+    /** Creates a new instance of PdfXConformanceException. */
+    public PdfXConformanceException() {
+    }
+    
+    /**
+     * Creates a new instance of PdfXConformanceException.
+     * @param s
+     */
+    public PdfXConformanceException(String s) {
+        super(s);
+    }    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/Pfm2afm.java b/LibrarySource/com/lowagie/text/pdf/Pfm2afm.java
new file mode 100644
index 0000000..0e24461
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/Pfm2afm.java
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+/********************************************************************
+ *                                                                  *
+ *  Title:  pfm2afm - Convert Windows .pfm files to .afm files      *
+ *                                                                  *
+ *  Author: Ken Borgendale   10/9/91  Version 1.0                   *
+ *                                                                  *
+ *  Function:                                                       *
+ *      Convert a Windows .pfm (Printer Font Metrics) file to a     *
+ *      .afm (Adobe Font Metrics) file.  The purpose of this is     *
+ *      to allow fonts put out for Windows to be used with OS/2.    *
+ *                                                                  *
+ *  Syntax:                                                         *
+ *      pfm2afm  infile  [outfile] -a                               *
+ *                                                                  *
+ *  Copyright:                                                      *
+ *      pfm2afm - Copyright (C) IBM Corp., 1991                     *
+ *                                                                  *
+ *      This code is released for public use as long as the         *
+ *      copyright remains intact.  This code is provided asis       *
+ *      without any warrenties, express or implied.                 *
+ *                                                                  *
+ *  Notes:                                                          *
+ *      1. Much of the information in the original .afm file is     *
+ *         lost when the .pfm file is created, and thus cannot be   *
+ *         reconstructed by this utility.  This is especially true  *
+ *         of data for characters not in the Windows character set. *
+ *                                                                  *
+ *      2. This module is coded to be compiled by the MSC 6.0.      *
+ *         For other compilers, be careful of the packing of the    *
+ *         PFM structure.                                           *
+ *                                                                  *
+ ********************************************************************/
+
+/********************************************************************
+ *                                                                  *
+ *  Modifications by Rod Smith, 5/22/96                             *
+ *                                                                  *
+ *  These changes look for the strings "italic", "bold", "black",   *
+ *  and "light" in the font's name and set the weight accordingly   *
+ *  and adds an ItalicAngle line with a value of "0" or "-12.00".   *
+ *  This allows OS/2 programs such as DeScribe to handle the bold   *
+ *  and italic attributes appropriately, which was not the case     *
+ *  when I used the original version on fonts from the KeyFonts     *
+ *  Pro 2002 font CD.                                               *
+ *                                                                  *
+ *  I've also increased the size of the buffer used to load the     *
+ *  .PFM file; the old size was inadequate for most of the fonts    *
+ *  from the SoftKey collection.                                    *
+ *                                                                  *
+ *  Compiled with Watcom C 10.6                                     *
+ *                                                                  *
+ ********************************************************************/
+ 
+/********************************************************************
+ *                                                                  *
+ *  Further modifications, 4/21/98, by Rod Smith                    *
+ *                                                                  *
+ *  Minor changes to get the program to compile with gcc under      *
+ *  Linux (Red Hat 5.0, to be precise).  I had to add an itoa       *
+ *  function from the net (the function was buggy, so I had to fix  *
+ *  it, too!).  I also made the program more friendly towards       *
+ *  files with mixed-case filenames.                                *
+ *                                                                  *
+ ********************************************************************/
+package com.lowagie.text.pdf;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Converts a PFM file into an AFM file.
+ */
+public class Pfm2afm {
+    private RandomAccessFileOrArray in;
+    private PrintWriter out;
+    
+    /** Creates a new instance of Pfm2afm */
+    private Pfm2afm(RandomAccessFileOrArray in, OutputStream out) throws IOException {
+        this.in = in;
+        this.out = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
+    }
+    
+    /**
+     * Converts a PFM file into an AFM file.
+     * @param in the PFM file
+     * @param out the AFM file
+     * @throws IOException on error
+     */    
+    public static void convert(RandomAccessFileOrArray in, OutputStream out) throws IOException {
+        Pfm2afm p = new Pfm2afm(in, out);
+        p.openpfm();
+        p.putheader();
+        p.putchartab();
+        p.putkerntab();
+        p.puttrailer();
+        p.out.flush();
+    }
+    
+    public static void main(String[] args) {
+        try {
+            RandomAccessFileOrArray in = new RandomAccessFileOrArray(args[0]);
+            OutputStream out = new FileOutputStream(args[1]);
+            convert(in, out);
+            in.close();
+            out.close();
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    private String readString(int n) throws IOException {
+        byte b[] = new byte[n];
+        in.readFully(b);
+        int k;
+        for (k = 0; k < b.length; ++k) {
+            if (b[k] == 0)
+                break;
+        }
+        return new String(b, 0, k, "ISO-8859-1");
+    }
+    
+    private String readString() throws IOException {
+        StringBuffer buf = new StringBuffer();
+        while (true) {
+            int c = in.read();
+            if (c <= 0)
+                break;
+            buf.append((char)c);
+        }
+        return buf.toString();
+    }
+    
+    private void outval(int n) {
+        out.print(' ');
+        out.print(n);
+    }
+    
+    /*
+     *  Output a character entry
+     */
+    private void  outchar(int code, int width, String name) {
+        out.print("C ");
+        outval(code);
+        out.print(" ; WX ");
+        outval(width);
+        if (name != null) {
+            out.print(" ; N ");
+            out.print(name);
+        }
+        out.print(" ;\n");
+    }
+    
+    private void openpfm() throws IOException {
+        in.seek(0);
+        vers = in.readShortLE();
+        h_len = in.readIntLE();
+        copyright = readString(60);
+        type = in.readShortLE();
+        points = in.readShortLE();
+        verres = in.readShortLE();
+        horres = in.readShortLE();
+        ascent = in.readShortLE();
+        intleading = in.readShortLE();
+        extleading = in.readShortLE();
+        italic = (byte)in.read();
+        uline = (byte)in.read();
+        overs = (byte)in.read();
+        weight = in.readShortLE();
+        charset = (byte)in.read();
+        pixwidth = in.readShortLE();
+        pixheight = in.readShortLE();
+        kind = (byte)in.read();
+        avgwidth = in.readShortLE();
+        maxwidth = in.readShortLE();
+        firstchar = in.read();
+        lastchar = in.read();
+        defchar = (byte)in.read();
+        brkchar = (byte)in.read();
+        widthby = in.readShortLE();
+        device = in.readIntLE();
+        face = in.readIntLE();
+        bits = in.readIntLE();
+        bitoff = in.readIntLE();
+        extlen = in.readShortLE();
+        psext = in.readIntLE();
+        chartab = in.readIntLE();
+        res1 = in.readIntLE();
+        kernpairs = in.readIntLE();
+        res2 = in.readIntLE();
+        fontname = in.readIntLE();
+        if (h_len != in.length() || extlen != 30 || fontname < 75 || fontname > 512)
+            throw new IOException("Not a valid PFM file.");
+        in.seek(psext + 14);
+        capheight = in.readShortLE();
+        xheight = in.readShortLE();
+        ascender = in.readShortLE();
+        descender = in.readShortLE();
+    }
+    
+    private void putheader() throws IOException {
+        out.print("StartFontMetrics 2.0\n");
+        if (copyright.length() > 0)
+            out.print("Comment " + copyright + '\n');
+        out.print("FontName ");
+        in.seek(fontname);
+        String fname = readString();
+        out.print(fname);
+        out.print("\nEncodingScheme ");
+        if (charset != 0)
+            out.print("FontSpecific\n");
+        else
+            out.print("AdobeStandardEncoding\n");
+        /*
+         * The .pfm is missing full name, so construct from font name by
+         * changing the hyphen to a space.  This actually works in a lot
+         * of cases.
+         */
+        out.print("FullName " + fname.replace('-', ' '));
+        if (face != 0) {
+            in.seek(face);
+            out.print("\nFamilyName " + readString());
+        }
+
+        out.print("\nWeight ");
+        if (weight > 475 || fname.toLowerCase().indexOf("bold") >= 0)
+           out.print("Bold");
+        else if ((weight < 325 && weight != 0) || fname.toLowerCase().indexOf("light") >= 0)
+            out.print("Light");
+        else if (fname.toLowerCase().indexOf("black") >= 0)
+            out.print("Black");
+        else 
+            out.print("Medium");
+
+        out.print("\nItalicAngle ");
+        if (italic != 0 || fname.toLowerCase().indexOf("italic") >= 0)
+            out.print("-12.00");
+            /* this is a typical value; something else may work better for a
+               specific font */
+        else
+            out.print("0");
+
+        /*
+         *  The mono flag in the pfm actually indicates whether there is a
+         *  table of font widths, not if they are all the same.
+         */
+        out.print("\nIsFixedPitch ");
+        if ((kind & 1) == 0 ||                  /* Flag for mono */
+            avgwidth == maxwidth ) {  /* Avg width = max width */
+            out.print("true");
+            isMono = true;
+        }
+        else {
+            out.print("false");
+            isMono = false;
+        }
+
+        /*
+         * The font bounding box is lost, but try to reconstruct it.
+         * Much of this is just guess work.  The bounding box is required in
+         * the .afm, but is not used by the PM font installer.
+         */
+        out.print("\nFontBBox");
+        if (isMono)
+            outval(-20);      /* Just guess at left bounds */
+        else 
+            outval(-100);
+        outval(-(descender+5));  /* Descender is given as positive value */
+        outval(maxwidth+10);
+        outval(ascent+5);
+
+        /*
+         * Give other metrics that were kept
+         */
+        out.print("\nCapHeight");
+        outval(capheight);
+        out.print("\nXHeight");
+        outval(xheight);
+        out.print("\nDescender");
+        outval(descender);
+        out.print("\nAscender");
+        outval(ascender);
+        out.print('\n');
+    }
+    
+    private void putchartab() throws IOException {
+        int count = lastchar - firstchar + 1;
+        int ctabs[] = new int[count];
+        in.seek(chartab);
+        for (int k = 0; k < count; ++k)
+            ctabs[k] = in.readUnsignedShortLE();
+        int back[] = new int[256];
+        if (charset == 0) {
+            for (int i = firstchar; i <= lastchar; ++i) {
+                if (Win2PSStd[i] != 0)
+                    back[Win2PSStd[i]] = i;
+            }
+        }
+        /* Put out the header */
+        out.print("StartCharMetrics");
+        outval(count);
+        out.print('\n');
+
+        /* Put out all encoded chars */
+        if (charset != 0) {
+        /*
+         * If the charset is not the Windows standard, just put out
+         * unnamed entries.
+         */
+            for (int i = firstchar; i <= lastchar; i++) {
+                if (ctabs[i - firstchar] != 0) {
+                    outchar(i, ctabs[i - firstchar], null);
+                }
+            }
+        }
+        else {
+            for (int i = 0; i < 256; i++) {
+                int j = back[i];
+                if (j != 0) {
+                    outchar(i, ctabs[j - firstchar], WinChars[j]);
+                    ctabs[j - firstchar] = 0;
+                }
+            }
+            /* Put out all non-encoded chars */
+            for (int i = firstchar; i <= lastchar; i++) {
+                if (ctabs[i - firstchar] != 0) {
+                    outchar(-1, ctabs[i - firstchar], WinChars[i]);
+                }
+            }
+        }
+        /* Put out the trailer */
+        out.print("EndCharMetrics\n");
+        
+    }
+    
+    private void putkerntab() throws IOException {
+        if (kernpairs == 0)
+            return;
+        in.seek(kernpairs);
+        int count = in.readUnsignedShortLE();
+        int nzero = 0;
+        int kerns[] = new int[count * 3];
+        for (int k = 0; k < kerns.length;) {
+            kerns[k++] = in.read();
+            kerns[k++] = in.read();
+            if ((kerns[k++] = in.readShortLE()) != 0)
+                ++nzero;
+        }
+        if (nzero == 0)
+            return;
+        out.print("StartKernData\nStartKernPairs");
+        outval(nzero);
+        out.print('\n');
+        for (int k = 0; k < kerns.length; k += 3) {
+            if (kerns[k + 2] != 0) {
+                out.print("KPX ");
+                out.print(WinChars[kerns[k]]);
+                out.print(' ');
+                out.print(WinChars[kerns[k + 1]]);
+                outval(kerns[k + 2]);
+                out.print('\n');
+            }
+        }
+        /* Put out trailer */
+        out.print("EndKernPairs\nEndKernData\n");
+    }
+    
+
+    private void  puttrailer() {
+        out.print("EndFontMetrics\n");
+    }
+
+    private short  vers;
+    private int   h_len;             /* Total length of .pfm file */
+    private String   copyright;   /* Copyright string [60]*/
+    private short  type;
+    private short  points;
+    private short  verres;
+    private short  horres;
+    private short  ascent;
+    private short  intleading;
+    private short  extleading;
+    private byte   italic;
+    private byte   uline;
+    private byte   overs;
+    private short  weight;
+    private byte   charset;         /* 0=windows, otherwise nomap */
+    private short  pixwidth;        /* Width for mono fonts */
+    private short  pixheight;
+    private byte   kind;            /* Lower bit off in mono */
+    private short  avgwidth;        /* Mono if avg=max width */
+    private short  maxwidth;        /* Use to compute bounding box */
+    private int   firstchar;       /* First char in table */
+    private int   lastchar;        /* Last char in table */
+    private byte   defchar;
+    private byte   brkchar;
+    private short  widthby;
+    private int   device;
+    private int   face;            /* Face name */
+    private int   bits;
+    private int   bitoff;
+    private short  extlen;
+    private int   psext;           /* PostScript extension */
+    private int   chartab;         /* Character width tables */
+    private int   res1;
+    private int   kernpairs;       /* Kerning pairs */
+    private int   res2;
+    private int   fontname;        /* Font name */
+
+/*
+ *  Some metrics from the PostScript extension
+ */
+    private short  capheight;       /* Cap height */
+    private short  xheight;         /* X height */
+    private short  ascender;        /* Ascender */
+    private short  descender;       /* Descender (positive) */
+
+    
+    private boolean isMono;
+/*
+ * Translate table from 1004 to psstd.  1004 is an extension of the
+ * Windows translate table used in PM.
+ */
+    private int Win2PSStd[] = {
+        0,   0,   0,   0, 197, 198, 199,   0, 202,   0, 205, 206, 207,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        32,  33,  34,  35,  36,  37,  38, 169,  40,  41,  42,  43,  44,  45,  46,  47,
+        48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
+        64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
+        80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
+        193,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+        0,   0, 184,   0, 185, 188, 178, 179,  94, 189,   0, 172, 234,   0,   0,   0,
+        0,  96,   0, 170, 186,   0, 177, 208, 126,   0,   0, 173, 250,   0,   0,   0,
+        0, 161, 162, 163, 168, 165,   0, 167, 200,   0, 227, 171,   0,   0,   0,   0,
+        0,   0,   0,   0, 194,   0, 182, 180, 203,   0, 235, 187,   0,   0,   0, 191,
+        0,   0,   0,   0,   0,   0, 225,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0, 233,   0,   0,   0,   0,   0,   0, 251,
+        0,   0,   0,   0,   0,   0, 241,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0, 249,   0,   0,   0,   0,   0,   0,   0
+    };
+    
+/*
+ *  Character class.  This is a minor attempt to overcome the problem that
+ *  in the pfm file, all unused characters are given the width of space.
+ */
+    private int WinClass[] = {
+        0, 0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0,   /* 00 */
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 10 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 20 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 30 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 40 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 50 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 60 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,   /* 70 */
+        0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,   /* 80 */
+        0, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,   /* 90 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* a0 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* b0 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* c0 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* d0 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* e0 */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1   /* f0 */
+    };
+    
+/*
+ *  Windows chararacter names.  Give a name to the usused locations
+ *  for when the all flag is specified.
+ */
+    private String WinChars[] = {
+        "W00",              /*   00    */
+        "W01",              /*   01    */
+        "W02",              /*   02    */
+        "W03",              /*   03    */
+        "macron",           /*   04    */
+        "breve",            /*   05    */
+        "dotaccent",        /*   06    */
+        "W07",              /*   07    */
+        "ring",             /*   08    */
+        "W09",              /*   09    */
+        "W0a",              /*   0a    */
+        "W0b",              /*   0b    */
+        "W0c",              /*   0c    */
+        "W0d",              /*   0d    */
+        "W0e",              /*   0e    */
+        "W0f",              /*   0f    */
+        "hungarumlaut",     /*   10    */
+        "ogonek",           /*   11    */
+        "caron",            /*   12    */
+        "W13",              /*   13    */
+        "W14",              /*   14    */
+        "W15",              /*   15    */
+        "W16",              /*   16    */
+        "W17",              /*   17    */
+        "W18",              /*   18    */
+        "W19",              /*   19    */
+        "W1a",              /*   1a    */
+        "W1b",              /*   1b    */
+        "W1c",              /*   1c    */
+        "W1d",              /*   1d    */
+        "W1e",              /*   1e    */
+        "W1f",              /*   1f    */
+        "space",            /*   20    */
+        "exclam",           /*   21    */
+        "quotedbl",         /*   22    */
+        "numbersign",       /*   23    */
+        "dollar",           /*   24    */
+        "percent",          /*   25    */
+        "ampersand",        /*   26    */
+        "quotesingle",      /*   27    */
+        "parenleft",        /*   28    */
+        "parenright",       /*   29    */
+        "asterisk",         /*   2A    */
+        "plus",             /*   2B    */
+        "comma",            /*   2C    */
+        "hyphen",           /*   2D    */
+        "period",           /*   2E    */
+        "slash",            /*   2F    */
+        "zero",             /*   30    */
+        "one",              /*   31    */
+        "two",              /*   32    */
+        "three",            /*   33    */
+        "four",             /*   34    */
+        "five",             /*   35    */
+        "six",              /*   36    */
+        "seven",            /*   37    */
+        "eight",            /*   38    */
+        "nine",             /*   39    */
+        "colon",            /*   3A    */
+        "semicolon",        /*   3B    */
+        "less",             /*   3C    */
+        "equal",            /*   3D    */
+        "greater",          /*   3E    */
+        "question",         /*   3F    */
+        "at",               /*   40    */
+        "A",                /*   41    */
+        "B",                /*   42    */
+        "C",                /*   43    */
+        "D",                /*   44    */
+        "E",                /*   45    */
+        "F",                /*   46    */
+        "G",                /*   47    */
+        "H",                /*   48    */
+        "I",                /*   49    */
+        "J",                /*   4A    */
+        "K",                /*   4B    */
+        "L",                /*   4C    */
+        "M",                /*   4D    */
+        "N",                /*   4E    */
+        "O",                /*   4F    */
+        "P",                /*   50    */
+        "Q",                /*   51    */
+        "R",                /*   52    */
+        "S",                /*   53    */
+        "T",                /*   54    */
+        "U",                /*   55    */
+        "V",                /*   56    */
+        "W",                /*   57    */
+        "X",                /*   58    */
+        "Y",                /*   59    */
+        "Z",                /*   5A    */
+        "bracketleft",      /*   5B    */
+        "backslash",        /*   5C    */
+        "bracketright",     /*   5D    */
+        "asciicircum",      /*   5E    */
+        "underscore",       /*   5F    */
+        "grave",            /*   60    */
+        "a",                /*   61    */
+        "b",                /*   62    */
+        "c",                /*   63    */
+        "d",                /*   64    */
+        "e",                /*   65    */
+        "f",                /*   66    */
+        "g",                /*   67    */
+        "h",                /*   68    */
+        "i",                /*   69    */
+        "j",                /*   6A    */
+        "k",                /*   6B    */
+        "l",                /*   6C    */
+        "m",                /*   6D    */
+        "n",                /*   6E    */
+        "o",                /*   6F    */
+        "p",                /*   70    */
+        "q",                /*   71    */
+        "r",                /*   72    */
+        "s",                /*   73    */
+        "t",                /*   74    */
+        "u",                /*   75    */
+        "v",                /*   76    */
+        "w",                /*   77    */
+        "x",                /*   78    */
+        "y",                /*   79    */
+        "z",                /*   7A    */
+        "braceleft",        /*   7B    */
+        "bar",              /*   7C    */
+        "braceright",       /*   7D    */
+        "asciitilde",       /*   7E    */
+        "W7f",              /*   7F    */
+        "W80",              /*   80    */
+        "W81",              /*   81    */
+        "quotesinglbase",   /*   82    */
+        "W83",              /*   83    */
+        "quotedblbase",     /*   84    */
+        "ellipsis",         /*   85    */
+        "dagger",           /*   86    */
+        "daggerdbl",        /*   87    */
+        "asciicircum",      /*   88    */
+        "perthousand",      /*   89    */
+        "Scaron",           /*   8A    */
+        "guilsinglleft",    /*   8B    */
+        "OE",               /*   8C    */
+        "W8d",              /*   8D    */
+        "W8e",              /*   8E    */
+        "W8f",              /*   8F    */
+        "W90",              /*   90    */
+        "quoteleft",        /*   91    */
+        "quoteright",       /*   92    */
+        "quotedblleft",     /*   93    */
+        "quotedblright",    /*   94    */
+        "bullet1",          /*   95    */
+        "endash",           /*   96    */
+        "emdash",           /*   97    */
+        "asciitilde",       /*   98    */
+        "trademark",        /*   99    */
+        "scaron",           /*   9A    */
+        "guilsinglright",   /*   9B    */
+        "oe",               /*   9C    */
+        "W9d",              /*   9D    */
+        "W9e",              /*   9E    */
+        "Ydieresis",        /*   9F    */
+        "reqspace",         /*   A0    */
+        "exclamdown",       /*   A1    */
+        "cent",             /*   A2    */
+        "sterling",         /*   A3    */
+        "currency",         /*   A4    */
+        "yen",              /*   A5    */
+        "brokenbar",        /*   A6    */
+        "section",          /*   A7    */
+        "dieresis",         /*   A8    */
+        "copyright",        /*   A9    */
+        "ordfeminine",      /*   AA    */
+        "guillemotleft",    /*   AB    */
+        "logicalnot",       /*   AC    */
+        "syllable",         /*   AD    */
+        "registered",       /*   AE    */
+        "overbar",          /*   AF    */
+        "degree",           /*   B0    */
+        "plusminus",        /*   B1    */
+        "twosuperior",      /*   B2    */
+        "threesuperior",    /*   B3    */
+        "acute",            /*   B4    */
+        "mu",               /*   B5    */
+        "paragraph",        /*   B6    */
+        "periodcentered",   /*   B7    */
+        "cedilla",          /*   B8    */
+        "onesuperior",      /*   B9    */
+        "ordmasculine",     /*   BA    */
+        "guillemotright",   /*   BB    */
+        "onequarter",       /*   BC    */
+        "onehalf",          /*   BD    */
+        "threequarters",    /*   BE    */
+        "questiondown",     /*   BF    */
+        "Agrave",           /*   C0    */
+        "Aacute",           /*   C1    */
+        "Acircumflex",      /*   C2    */
+        "Atilde",           /*   C3    */
+        "Adieresis",        /*   C4    */
+        "Aring",            /*   C5    */
+        "AE",               /*   C6    */
+        "Ccedilla",         /*   C7    */
+        "Egrave",           /*   C8    */
+        "Eacute",           /*   C9    */
+        "Ecircumflex",      /*   CA    */
+        "Edieresis",        /*   CB    */
+        "Igrave",           /*   CC    */
+        "Iacute",           /*   CD    */
+        "Icircumflex",      /*   CE    */
+        "Idieresis",        /*   CF    */
+        "Eth",              /*   D0    */
+        "Ntilde",           /*   D1    */
+        "Ograve",           /*   D2    */
+        "Oacute",           /*   D3    */
+        "Ocircumflex",      /*   D4    */
+        "Otilde",           /*   D5    */
+        "Odieresis",        /*   D6    */
+        "multiply",         /*   D7    */
+        "Oslash",           /*   D8    */
+        "Ugrave",           /*   D9    */
+        "Uacute",           /*   DA    */
+        "Ucircumflex",      /*   DB    */
+        "Udieresis",        /*   DC    */
+        "Yacute",           /*   DD    */
+        "Thorn",            /*   DE    */
+        "germandbls",       /*   DF    */
+        "agrave",           /*   E0    */
+        "aacute",           /*   E1    */
+        "acircumflex",      /*   E2    */
+        "atilde",           /*   E3    */
+        "adieresis",        /*   E4    */
+        "aring",            /*   E5    */
+        "ae",               /*   E6    */
+        "ccedilla",         /*   E7    */
+        "egrave",           /*   E8    */
+        "eacute",           /*   E9    */
+        "ecircumflex",      /*   EA    */
+        "edieresis",        /*   EB    */
+        "igrave",           /*   EC    */
+        "iacute",           /*   ED    */
+        "icircumflex",      /*   EE    */
+        "idieresis",        /*   EF    */
+        "eth",              /*   F0    */
+        "ntilde",           /*   F1    */
+        "ograve",           /*   F2    */
+        "oacute",           /*   F3    */
+        "ocircumflex",      /*   F4    */
+        "otilde",           /*   F5    */
+        "odieresis",        /*   F6    */
+        "divide",           /*   F7    */
+        "oslash",           /*   F8    */
+        "ugrave",           /*   F9    */
+        "uacute",           /*   FA    */
+        "ucircumflex",      /*   FB    */
+        "udieresis",        /*   FC    */
+        "yacute",           /*   FD    */
+        "thorn",            /*   FE    */
+        "ydieresis"        /*   FF    */
+    };
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/PushbuttonField.java b/LibrarySource/com/lowagie/text/pdf/PushbuttonField.java
new file mode 100644
index 0000000..0f8c69d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/PushbuttonField.java
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Image;
+import com.lowagie.text.DocumentException;
+import java.io.IOException;
+/**
+ * Creates a pushbutton field. It supports all the text and icon alignments.
+ * The icon may be an image or a template.
+ * <p>
+ * Example usage:
+ * <p>
+ * <PRE>
+ * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
+ * document.open();
+ * PdfContentByte cb = writer.getDirectContent();
+ * Image img = Image.getInstance("image.png");
+ * PushbuttonField bt = new PushbuttonField(writer, new Rectangle(100, 100, 200, 200), "Button1");
+ * bt.setText("My Caption");
+ * bt.setFontSize(0);
+ * bt.setImage(img);
+ * bt.setLayout(PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM);
+ * bt.setBackgroundColor(Color.cyan);
+ * bt.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
+ * bt.setBorderColor(Color.red);
+ * bt.setBorderWidth(3);
+ * PdfFormField ff = bt.getButton();
+ * PdfAction ac = PdfAction.createSubmitForm("http://www.submit-site.com", null, 0);
+ * ff.setAction(ac);
+ * writer.addAnnotation(ff);
+ * document.close();
+ * </PRE>
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class PushbuttonField extends BaseField {
+   
+    /** A layout option */    
+    public static final int LAYOUT_LABEL_ONLY = 1;
+    /** A layout option */    
+    public static final int LAYOUT_ICON_ONLY = 2;
+    /** A layout option */    
+    public static final int LAYOUT_ICON_TOP_LABEL_BOTTOM = 3;
+    /** A layout option */    
+    public static final int LAYOUT_LABEL_TOP_ICON_BOTTOM = 4;
+    /** A layout option */    
+    public static final int LAYOUT_ICON_LEFT_LABEL_RIGHT = 5;
+    /** A layout option */    
+    public static final int LAYOUT_LABEL_LEFT_ICON_RIGHT = 6;
+    /** A layout option */    
+    public static final int LAYOUT_LABEL_OVER_ICON = 7;
+    /** An icon scaling option */    
+    public static final int SCALE_ICON_ALWAYS  = 1;
+    /** An icon scaling option */    
+    public static final int SCALE_ICON_NEVER = 2;
+    /** An icon scaling option */    
+    public static final int SCALE_ICON_IS_TOO_BIG = 3;
+    /** An icon scaling option */    
+    public static final int SCALE_ICON_IS_TOO_SMALL = 4;
+
+    /**
+     * Holds value of property layout.
+     */
+    private int layout = LAYOUT_LABEL_ONLY;
+    
+    /**
+     * Holds value of property image.
+     */
+    private Image image;    
+    
+    /**
+     * Holds value of property template.
+     */
+    private PdfTemplate template;
+    
+    /**
+     * Holds value of property scaleIcon.
+     */
+    private int scaleIcon = SCALE_ICON_ALWAYS;
+    
+    /**
+     * Holds value of property proportionalIcon.
+     */
+    private boolean proportionalIcon = true;
+    
+    /**
+     * Holds value of property iconVerticalAdjustment.
+     */
+    private float iconVerticalAdjustment = 0.5f;
+    
+    /**
+     * Holds value of property iconHorizontalAdjustment.
+     */
+    private float iconHorizontalAdjustment = 0.5f;
+    
+    /**
+     * Holds value of property iconFitToBounds.
+     */
+    private boolean iconFitToBounds;
+    
+    private PdfTemplate tp;
+    
+    /**
+     * Creates a new instance of PushbuttonField
+     * @param writer the document <CODE>PdfWriter</CODE>
+     * @param box the field location and dimensions
+     * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
+     * will be included in the field allowing it to be used as a kid field.
+     */
+    public PushbuttonField(PdfWriter writer, Rectangle box, String fieldName) {
+        super(writer, box, fieldName);
+    }
+    
+    /**
+     * Getter for property layout.
+     * @return Value of property layout.
+     */
+    public int getLayout() {
+        return this.layout;
+    }
+    
+    /**
+     * Sets the icon and label layout. Possible values are <CODE>LAYOUT_LABEL_ONLY</CODE>,
+     * <CODE>LAYOUT_ICON_ONLY</CODE>, <CODE>LAYOUT_ICON_TOP_LABEL_BOTTOM</CODE>,
+     * <CODE>LAYOUT_LABEL_TOP_ICON_BOTTOM</CODE>, <CODE>LAYOUT_ICON_LEFT_LABEL_RIGHT</CODE>,
+     * <CODE>LAYOUT_LABEL_LEFT_ICON_RIGHT</CODE> and <CODE>LAYOUT_LABEL_OVER_ICON</CODE>.
+     * The default is <CODE>LAYOUT_LABEL_ONLY</CODE>.
+     * @param layout New value of property layout.
+     */
+    public void setLayout(int layout) {
+        if (layout < LAYOUT_LABEL_ONLY || layout > LAYOUT_LABEL_OVER_ICON)
+            throw new IllegalArgumentException("Layout out of bounds.");
+        this.layout = layout;
+    }
+    
+    /**
+     * Getter for property image.
+     * @return Value of property image.
+     */
+    public Image getImage() {
+        return this.image;
+    }
+    
+    /**
+     * Sets the icon as an image.
+     * @param image the image
+     */
+    public void setImage(Image image) {
+        this.image = image;
+        template = null;
+    }
+    
+    /**
+     * Getter for property template.
+     * @return Value of property template.
+     */
+    public PdfTemplate getTemplate() {
+        return this.template;
+    }
+    
+    /**
+     * Sets the icon as a template.
+     * @param template the template
+     */
+    public void setTemplate(PdfTemplate template) {
+        this.template = template;
+        image = null;
+    }
+    
+    /**
+     * Getter for property scaleIcon.
+     * @return Value of property scaleIcon.
+     */
+    public int getScaleIcon() {
+        return this.scaleIcon;
+    }
+    
+    /**
+     * Sets the way the icon will be scaled. Possible values are
+     * <CODE>SCALE_ICON_ALWAYS</CODE>, <CODE>SCALE_ICON_NEVER</CODE>,
+     * <CODE>SCALE_ICON_IS_TOO_BIG</CODE> and <CODE>SCALE_ICON_IS_TOO_SMALL</CODE>.
+     * The default is <CODE>SCALE_ICON_ALWAYS</CODE>.
+     * @param scaleIcon the way the icon will be scaled
+     */
+    public void setScaleIcon(int scaleIcon) {
+        if (scaleIcon < SCALE_ICON_ALWAYS || scaleIcon > SCALE_ICON_IS_TOO_SMALL)
+            scaleIcon = SCALE_ICON_ALWAYS;
+        this.scaleIcon = scaleIcon;
+    }
+    
+    /**
+     * Getter for property proportionalIcon.
+     * @return Value of property proportionalIcon.
+     */
+    public boolean isProportionalIcon() {
+        return this.proportionalIcon;
+    }
+    
+    /**
+     * Sets the way the icon is scaled. If <CODE>true</CODE> the icon is scaled proportionally,
+     * if <CODE>false</CODE> the scaling is done anamorphicaly.
+     * @param proportionalIcon the way the icon is scaled
+     */
+    public void setProportionalIcon(boolean proportionalIcon) {
+        this.proportionalIcon = proportionalIcon;
+    }
+    
+    /**
+     * Getter for property iconVerticalAdjustment.
+     * @return Value of property iconVerticalAdjustment.
+     */
+    public float getIconVerticalAdjustment() {
+        return this.iconVerticalAdjustment;
+    }
+    
+    /**
+     * A number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon.
+     * A value of 0 positions the icon at the bottom of the annotation rectangle.
+     * A value of 0.5 centers it within the rectangle. The default is 0.5.
+     * @param iconVerticalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon
+     */
+    public void setIconVerticalAdjustment(float iconVerticalAdjustment) {
+        if (iconVerticalAdjustment < 0)
+            iconVerticalAdjustment = 0;
+        else if (iconVerticalAdjustment > 1)
+            iconVerticalAdjustment = 1;
+        this.iconVerticalAdjustment = iconVerticalAdjustment;
+    }
+    
+    /**
+     * Getter for property iconHorizontalAdjustment.
+     * @return Value of property iconHorizontalAdjustment.
+     */
+    public float getIconHorizontalAdjustment() {
+        return this.iconHorizontalAdjustment;
+    }
+    
+    /**
+     * A number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon.
+     * A value of 0 positions the icon at the left of the annotation rectangle.
+     * A value of 0.5 centers it within the rectangle. The default is 0.5.
+     * @param iconHorizontalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon
+     */
+    public void setIconHorizontalAdjustment(float iconHorizontalAdjustment) {
+        if (iconHorizontalAdjustment < 0)
+            iconHorizontalAdjustment = 0;
+        else if (iconHorizontalAdjustment > 1)
+            iconHorizontalAdjustment = 1;
+        this.iconHorizontalAdjustment = iconHorizontalAdjustment;
+    }
+    
+    private float calculateFontSize(float w, float h) throws IOException, DocumentException {
+        BaseFont ufont = getRealFont();
+        float fsize = fontSize;
+        if (fsize == 0) {
+            float bw = ufont.getWidthPoint(text, 1);
+            if (bw == 0)
+                fsize = 12;
+            else
+                fsize = w / bw;
+            float nfsize = h / (1 - ufont.getFontDescriptor(BaseFont.DESCENT, 1));
+            fsize = Math.min(fsize, nfsize);
+            if (fsize < 4)
+                fsize = 4;
+        }
+        return fsize;
+    }
+    
+    /**
+     * Gets the button appearance.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return the button appearance
+     */    
+    protected PdfAppearance getAppearance() throws IOException, DocumentException {
+        PdfAppearance app = getBorderAppearance();
+        Rectangle box = new Rectangle(app.getBoundingBox());
+        if ((text == null || text.length() == 0) && (layout == LAYOUT_LABEL_ONLY || (image == null && template == null))) {
+            return app;
+        }
+        if (layout == LAYOUT_ICON_ONLY && image == null && template == null)
+            return app;
+        BaseFont ufont = getRealFont();
+        boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+        float h = box.height() - borderWidth * 2;
+        float bw2 = borderWidth;
+        if (borderExtra) {
+            h -= borderWidth * 2;
+            bw2 *= 2;
+        }
+        float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+        offsetX = Math.max(offsetX, 1);
+        float offX = Math.min(bw2, offsetX);
+        tp = null;
+        Rectangle bounds = null;
+        float textX = Float.NaN;
+        float textY = 0;
+        float fsize = fontSize;
+        float wt = box.width() - 2 * offX - 2;
+        float ht = box.height() - 2 * offX;
+        float adj = (iconFitToBounds ? 0 : offX + 1);
+        int nlayout = layout;
+        if (image == null && template == null)
+            nlayout = LAYOUT_LABEL_ONLY;
+        Rectangle iconBox = null;
+        while (true) {
+            switch (nlayout) {
+                case LAYOUT_LABEL_ONLY:
+                case LAYOUT_LABEL_OVER_ICON:
+                    if (text != null && text.length() > 0 && wt > 0 && ht > 0) {
+                        fsize = calculateFontSize(wt, ht);
+                        textX = (box.width() - ufont.getWidthPoint(text, fsize)) / 2;
+                        textY = (box.height() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
+                    }
+                case LAYOUT_ICON_ONLY:
+                    if (nlayout == LAYOUT_LABEL_OVER_ICON || nlayout == LAYOUT_ICON_ONLY)
+                        iconBox = new Rectangle(box.left() + adj, box.bottom() + adj, box.right() - adj, box.top() - adj);
+                    break;
+                case LAYOUT_ICON_TOP_LABEL_BOTTOM:
+                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
+                        nlayout = LAYOUT_ICON_ONLY;
+                        continue;
+                    }
+                    float nht = box.height() * 0.35f - offX;
+                    if (nht > 0)
+                        fsize = calculateFontSize(wt, nht);
+                    else
+                        fsize = 4;
+                    textX = (box.width() - ufont.getWidthPoint(text, fsize)) / 2;
+                    textY = offX - ufont.getFontDescriptor(BaseFont.DESCENT, fsize);
+                    iconBox = new Rectangle(box.left() + adj, textY + fsize, box.right() - adj, box.top() - adj);
+                    break;
+                case LAYOUT_LABEL_TOP_ICON_BOTTOM:
+                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
+                        nlayout = LAYOUT_ICON_ONLY;
+                        continue;
+                    }
+                    nht = box.height() * 0.35f - offX;
+                    if (nht > 0)
+                        fsize = calculateFontSize(wt, nht);
+                    else
+                        fsize = 4;
+                    textX = (box.width() - ufont.getWidthPoint(text, fsize)) / 2;
+                    textY = box.height() - offX - fsize;
+                    if (textY < offX)
+                        textY = offX;
+                    iconBox = new Rectangle(box.left() + adj, box.bottom() + adj, box.right() - adj, textY + ufont.getFontDescriptor(BaseFont.DESCENT, fsize));
+                    break;
+                case LAYOUT_LABEL_LEFT_ICON_RIGHT:
+                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
+                        nlayout = LAYOUT_ICON_ONLY;
+                        continue;
+                    }
+                    float nw = box.width() * 0.35f - offX;
+                    if (nw > 0)
+                        fsize = calculateFontSize(wt, nw);
+                    else
+                        fsize = 4;
+                    if (ufont.getWidthPoint(text, fsize) >= wt) {
+                        nlayout = LAYOUT_LABEL_ONLY;
+                        fsize = fontSize;
+                        continue;
+                    }
+                    textX = offX + 1;
+                    textY = (box.height() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
+                    iconBox = new Rectangle(textX + ufont.getWidthPoint(text, fsize), box.bottom() + adj, box.right() - adj, box.top() - adj);
+                    break;
+                case LAYOUT_ICON_LEFT_LABEL_RIGHT:
+                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
+                        nlayout = LAYOUT_ICON_ONLY;
+                        continue;
+                    }
+                    nw = box.width() * 0.35f - offX;
+                    if (nw > 0)
+                        fsize = calculateFontSize(wt, nw);
+                    else
+                        fsize = 4;
+                    if (ufont.getWidthPoint(text, fsize) >= wt) {
+                        nlayout = LAYOUT_LABEL_ONLY;
+                        fsize = fontSize;
+                        continue;
+                    }
+                    textX = box.width() - ufont.getWidthPoint(text, fsize) - offX - 1;
+                    textY = (box.height() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
+                    iconBox = new Rectangle(box.left() + adj, box.bottom() + adj, textX - 1, box.top() - adj);
+                    break;
+            }
+            break;
+        }
+        if (textY < box.bottom() + offX)
+            textY = box.bottom() + offX;
+        if (iconBox != null && (iconBox.width() <= 0 || iconBox.height() <= 0))
+            iconBox = null;
+        if (iconBox != null) {
+            if (image != null) {
+                tp = new PdfTemplate(writer);
+                tp.setBoundingBox(new Rectangle(image));
+                writer.addDirectTemplateSimple(tp, new PdfName("FRM"));
+                tp.addImage(image, image.width(), 0, 0, image.height(), 0, 0);
+            }
+            else if (template != null) {
+                tp = new PdfTemplate(writer);
+                tp.setBoundingBox(new Rectangle(template.getWidth(), template.getHeight()));
+                writer.addDirectTemplateSimple(tp, new PdfName("FRM"));
+                tp.addTemplate(template, template.getBoundingBox().left(), template.getBoundingBox().bottom());
+            }
+        }
+        if (tp != null) {
+            float icx = iconBox.width() / tp.getBoundingBox().width();
+            float icy = iconBox.height() / tp.getBoundingBox().height();
+            if (proportionalIcon) {
+                switch (scaleIcon) {
+                    case SCALE_ICON_IS_TOO_BIG:
+                        icx = Math.min(icx, icy);
+                        icx = Math.min(icx, 1);
+                        break;
+                    case SCALE_ICON_IS_TOO_SMALL:
+                        icx = Math.min(icx, icy);
+                        icx = Math.max(icx, 1);
+                        break;
+                    case SCALE_ICON_NEVER:
+                        icx = 1;
+                        break;
+                    default:
+                        icx = Math.min(icx, icy);
+                        break;
+                }
+                icy = icx;
+            }
+            else {
+                switch (scaleIcon) {
+                    case SCALE_ICON_IS_TOO_BIG:
+                        icx = Math.min(icx, 1);
+                        icy = Math.min(icy, 1);
+                        break;
+                    case SCALE_ICON_IS_TOO_SMALL:
+                        icx = Math.max(icx, 1);
+                        icy = Math.max(icy, 1);
+                        break;
+                    case SCALE_ICON_NEVER:
+                        icx = icy = 1;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            float xpos = iconBox.left() + (iconBox.width() - (tp.getBoundingBox().width() * icx)) * iconHorizontalAdjustment;
+            float ypos = iconBox.bottom() + (iconBox.height() - (tp.getBoundingBox().height() * icy)) * iconVerticalAdjustment;
+            app.saveState();
+            app.rectangle(iconBox.left(), iconBox.bottom(), iconBox.width(), iconBox.height());
+            app.clip();
+            app.newPath();
+            app.addTemplate(tp, icx, 0, 0, icy, xpos, ypos);
+            app.restoreState();
+        }
+        if (!Float.isNaN(textX)) {
+            app.saveState();
+            app.rectangle(offX, offX, box.width() - 2 * offX, box.height() - 2 * offX);
+            app.clip();
+            app.newPath();
+            if (textColor == null)
+                app.resetGrayFill();
+            else
+                app.setColorFill(textColor);
+            app.beginText();
+            app.setFontAndSize(ufont, fsize);
+            app.setTextMatrix(textX, textY);
+            app.showText(text);
+            app.endText();
+            app.restoreState();
+        }
+        return app;
+    }
+
+    /**
+     * Gets the pushbutton field.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return the pushbutton field
+     */    
+    public PdfFormField getField() throws IOException, DocumentException {
+        PdfFormField field = PdfFormField.createPushButton(writer);
+        field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+        if (fieldName != null) {
+            field.setFieldName(fieldName);
+            if ((options & READ_ONLY) != 0)
+                field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+            if ((options & REQUIRED) != 0)
+                field.setFieldFlags(PdfFormField.FF_REQUIRED);
+        }
+        if (text != null)
+            field.setMKNormalCaption(text);
+        if (rotation != 0)
+            field.setMKRotation(rotation);
+        field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+        PdfAppearance tpa = getAppearance();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tpa);
+        PdfAppearance da = (PdfAppearance)tpa.getDuplicate();
+        da.setFontAndSize(getRealFont(), fontSize);
+        if (textColor == null)
+            da.setGrayFill(0);
+        else
+            da.setColorFill(textColor);
+        field.setDefaultAppearanceString(da);
+        if (borderColor != null)
+            field.setMKBorderColor(borderColor);
+        if (backgroundColor != null)
+            field.setMKBackgroundColor(backgroundColor);
+        switch (visibility) {
+            case HIDDEN:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+                break;
+            case VISIBLE_BUT_DOES_NOT_PRINT:
+                break;
+            case HIDDEN_BUT_PRINTABLE:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+                break;
+            default:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT);
+                break;
+        }
+        if (tp != null)
+            field.setMKNormalIcon(tp);
+        field.setMKTextPosition(layout - 1);
+        PdfName scale = PdfName.A;
+        if (scaleIcon == SCALE_ICON_IS_TOO_BIG)
+            scale = PdfName.B;
+        else if (scaleIcon == SCALE_ICON_IS_TOO_SMALL)
+            scale = PdfName.S;
+        else if (scaleIcon == SCALE_ICON_NEVER)
+            scale = PdfName.N;
+        field.setMKIconFit(scale, proportionalIcon ? PdfName.P : PdfName.A, iconHorizontalAdjustment,
+            iconVerticalAdjustment, iconFitToBounds);
+        return field;
+    }
+    
+    /**
+     * Getter for property iconFitToBounds.
+     * @return Value of property iconFitToBounds.
+     */
+    public boolean isIconFitToBounds() {
+        return this.iconFitToBounds;
+    }
+    
+    /**
+     * If <CODE>true</CODE> the icon will be scaled to fit fully within the bounds of the annotation,
+     * if <CODE>false</CODE> the border width will be taken into account. The default
+     * is <CODE>false</CODE>.
+     * @param iconFitToBounds if <CODE>true</CODE> the icon will be scaled to fit fully within the bounds of the annotation,
+     * if <CODE>false</CODE> the border width will be taken into account
+     */
+    public void setIconFitToBounds(boolean iconFitToBounds) {
+        this.iconFitToBounds = iconFitToBounds;
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/RadioCheckField.java b/LibrarySource/com/lowagie/text/pdf/RadioCheckField.java
new file mode 100644
index 0000000..4740484
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/RadioCheckField.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.DocumentException;
+import java.io.IOException;
+
+/**
+ * Creates a radio or a check field.
+ * <p>
+ * Example usage:
+ * <p>
+ * <PRE>
+ * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
+ * document.open();
+ * PdfContentByte cb = writer.getDirectContent();
+ * RadioCheckField bt = new RadioCheckField(writer, new Rectangle(100, 100, 200, 200), "radio", "v1");
+ * bt.setCheckType(RadioCheckField.TYPE_CIRCLE);
+ * bt.setBackgroundColor(Color.CYAN);
+ * bt.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
+ * bt.setBorderColor(Color.red);
+ * bt.setTextColor(Color.yellow);
+ * bt.setBorderWidth(BaseField.BORDER_WIDTH_THICK);
+ * bt.setChecked(false);
+ * PdfFormField f1 = bt.getRadioField();
+ * bt.setOnValue("v2");
+ * bt.setChecked(true);
+ * bt.setBox(new Rectangle(100, 300, 200, 400));
+ * PdfFormField f2 = bt.getRadioField();
+ * bt.setChecked(false);
+ * PdfFormField top = bt.getRadioGroup(true, false);
+ * bt.setOnValue("v3");
+ * bt.setBox(new Rectangle(100, 500, 200, 600));
+ * PdfFormField f3 = bt.getRadioField();
+ * top.addKid(f1);
+ * top.addKid(f2);
+ * top.addKid(f3);
+ * writer.addAnnotation(top);
+ * bt = new RadioCheckField(writer, new Rectangle(300, 300, 400, 400), "check1", "Yes");
+ * bt.setCheckType(RadioCheckField.TYPE_CHECK);
+ * bt.setBorderWidth(BaseField.BORDER_WIDTH_THIN);
+ * bt.setBorderColor(Color.black);
+ * bt.setBackgroundColor(Color.white);
+ * PdfFormField ck = bt.getCheckField();
+ * writer.addAnnotation(ck);
+ * document.close();
+ * </PRE>
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class RadioCheckField extends BaseField {
+
+    /** A field with the symbol check */
+    public static final int TYPE_CHECK = 1;
+    /** A field with the symbol circle */
+    public static final int TYPE_CIRCLE = 2;
+    /** A field with the symbol cross */
+    public static final int TYPE_CROSS = 3;
+    /** A field with the symbol diamond */
+    public static final int TYPE_DIAMOND = 4;
+    /** A field with the symbol square */
+    public static final int TYPE_SQUARE = 5;
+    /** A field with the symbol star */
+    public static final int TYPE_STAR = 6;
+    
+    private static String typeChars[] = {"4", "l", "8", "u", "n", "H"};
+    
+    /**
+     * Holds value of property checkType.
+     */
+    private int checkType;
+    
+    /**
+     * Holds value of property onValue.
+     */
+    private String onValue;
+    
+    /**
+     * Holds value of property checked.
+     */
+    private boolean checked;
+    
+    /**
+     * Creates a new instance of RadioCheckField
+     * @param writer the document <CODE>PdfWriter</CODE>
+     * @param box the field location and dimensions
+     * @param fieldName the field name. It must not be <CODE>null</CODE>
+     * @param onValue the value when the field is checked
+     */
+    public RadioCheckField(PdfWriter writer, Rectangle box, String fieldName, String onValue) {
+        super(writer, box, fieldName);
+        setOnValue(onValue);
+        setCheckType(TYPE_CIRCLE);
+    }
+    
+    /**
+     * Getter for property checkType.
+     * @return Value of property checkType.
+     */
+    public int getCheckType() {
+        return this.checkType;
+    }
+    
+    /**
+     * Sets the checked symbol. It can be
+     * <CODE>TYPE_CHECK</CODE>,
+     * <CODE>TYPE_CIRCLE</CODE>,
+     * <CODE>TYPE_CROSS</CODE>,
+     * <CODE>TYPE_DIAMOND</CODE>,
+     * <CODE>TYPE_SQUARE</CODE> and
+     * <CODE>TYPE_STAR</CODE>.
+     * @param checkType the checked symbol
+     */
+    public void setCheckType(int checkType) {
+        if (checkType < TYPE_CHECK || checkType > TYPE_STAR)
+            checkType = TYPE_CIRCLE;
+        this.checkType = checkType;
+        setText(typeChars[checkType - 1]);
+        try {
+            setFont(BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, false));
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /**
+     * Getter for property onValue.
+     * @return Value of property onValue.
+     */
+    public String getOnValue() {
+        return this.onValue;
+    }
+    
+    /**
+     * Sets the value when the field is checked.
+     * @param onValue the value when the field is checked
+     */
+    public void setOnValue(String onValue) {
+        this.onValue = onValue;
+    }
+    
+    /**
+     * Getter for property checked.
+     * @return Value of property checked.
+     */
+    public boolean isChecked() {
+        return this.checked;
+    }
+    
+    /**
+     * Sets the state of the field to checked or unchecked.
+     * @param checked the state of the field, <CODE>true</CODE> for checked
+     * and <CODE>false</CODE> for unchecked
+     */
+    public void setChecked(boolean checked) {
+        this.checked = checked;
+    }
+    
+    /**
+     * Gets the field appearance.
+     * @param isRadio <CODE>true</CODE> for a radio field and <CODE>false</CODE>
+     * for a check field
+     * @param on <CODE>true</CODE> for the checked state, <CODE>false</CODE>
+     * otherwise
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return the appearance
+     */    
+    public PdfAppearance getAppearance(boolean isRadio, boolean on) throws IOException, DocumentException {
+        if (isRadio && checkType == TYPE_CIRCLE)
+            return getAppearanceRadioCircle(on);
+        PdfAppearance app = getBorderAppearance();
+        if (!on)
+            return app;
+        BaseFont ufont = getRealFont();
+        boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+        float h = box.height() - borderWidth * 2;
+        float bw2 = borderWidth;
+        if (borderExtra) {
+            h -= borderWidth * 2;
+            bw2 *= 2;
+        }
+        float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+        offsetX = Math.max(offsetX, 1);
+        float offX = Math.min(bw2, offsetX);
+        float wt = box.width() - 2 * offX;
+        float ht = box.height() - 2 * offX;
+        float fsize = fontSize;
+        if (fsize == 0) {
+            float bw = ufont.getWidthPoint(text, 1);
+            if (bw == 0)
+                fsize = 12;
+            else
+                fsize = wt / bw;
+            float nfsize = h / (ufont.getFontDescriptor(BaseFont.ASCENT, 1));
+            fsize = Math.min(fsize, nfsize);
+        }
+        app.saveState();
+        app.rectangle(offX, offX, box.width() - 2 * offX, box.height() - 2 * offX);
+        app.clip();
+        app.newPath();
+        if (textColor == null)
+            app.resetGrayFill();
+        else
+            app.setColorFill(textColor);
+        app.beginText();
+        app.setFontAndSize(ufont, fsize);
+        app.setTextMatrix((box.width() - ufont.getWidthPoint(text, fsize)) / 2, 
+            (box.height() - ufont.getAscentPoint(text, fsize)) / 2);
+        app.showText(text);
+        app.endText();
+        app.restoreState();
+        return app;
+    }
+
+    /**
+     * Gets the special field appearance for the radio circle.
+     * @param on <CODE>true</CODE> for the checked state, <CODE>false</CODE>
+     * otherwise
+     * @return the appearance
+     */    
+    public PdfAppearance getAppearanceRadioCircle(boolean on) {
+        PdfAppearance app = writer.getDirectContent().createAppearance(box.width(), box.height());
+        switch (rotation) {
+            case 90:
+                app.setMatrix(0, 1, -1, 0, box.height(), 0);
+                break;
+            case 180:
+                app.setMatrix(-1, 0, 0, -1, box.width(), box.height());
+                break;
+            case 270:
+                app.setMatrix(0, -1, 1, 0, 0, box.width());
+                break;
+        }
+        Rectangle box = new Rectangle(app.getBoundingBox());
+        float cx = box.width() / 2;
+        float cy = box.height() / 2;
+        float r = (Math.min(box.width(), box.height()) - borderWidth) / 2;
+        if (r <= 0)
+            return app;
+        if (backgroundColor != null) {
+            app.setColorFill(backgroundColor);
+            app.circle(cx, cy, r + borderWidth / 2);
+            app.fill();
+        }
+        if (borderWidth > 0 && borderColor != null) {
+            app.setLineWidth(borderWidth);
+            app.setColorStroke(borderColor);
+            app.circle(cx, cy, r);
+            app.stroke();
+        }
+        if (on) {
+            if (textColor == null)
+                app.resetGrayFill();
+            else
+                app.setColorFill(textColor);
+            app.circle(cx, cy, r / 2);
+            app.fill();
+        }
+        return app;
+    }
+    
+    /**
+     * Gets a radio group. It's composed of the field specific keys, without the widget
+     * ones. This field is to be used as a field aggregator with {@link PdfFormField#addKid(PdfFormField) addKid()}.
+     * @param noToggleToOff if <CODE>true</CODE>, exactly one radio button must be selected at all
+     * times; clicking the currently selected button has no effect.
+     * If <CODE>false</CODE>, clicking
+     * the selected button deselects it, leaving no button selected.
+     * @param radiosInUnison if <CODE>true</CODE>, a group of radio buttons within a radio button field that
+     * use the same value for the on state will turn on and off in unison; that is if
+     * one is checked, they are all checked. If <CODE>false</CODE>, the buttons are mutually exclusive
+     * (the same behavior as HTML radio buttons)
+     * @return the radio group
+     */    
+    public PdfFormField getRadioGroup(boolean noToggleToOff, boolean radiosInUnison) {
+        PdfFormField field = PdfFormField.createRadioButton(writer, noToggleToOff);
+        if (radiosInUnison)
+            field.setFieldFlags(PdfFormField.FF_RADIOSINUNISON);
+        field.setFieldName(fieldName);
+        if ((options & READ_ONLY) != 0)
+            field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+        if ((options & REQUIRED) != 0)
+            field.setFieldFlags(PdfFormField.FF_REQUIRED);
+        field.setValueAsName(checked ? onValue : "Off");
+        return field;
+    }
+    
+    /**
+     * Gets the radio field. It's only composed of the widget keys and must be used
+     * with {@link #getRadioGroup(boolean,boolean)}.
+     * @return the radio field
+     * @throws IOException on error
+     * @throws DocumentException on error
+     */    
+    public PdfFormField getRadioField() throws IOException, DocumentException {
+        return getField(true);
+    }
+    
+    /**
+     * Gets the check field.
+     * @return the check field
+     * @throws IOException on error
+     * @throws DocumentException on error
+     */    
+    public PdfFormField getCheckField() throws IOException, DocumentException {
+        return getField(false);
+    }
+    
+    /**
+     * Gets a radio or check field.
+     * @param isRadio <CODE>true</CODE> to get a radio field, <CODE>false</CODE> to get
+     * a check field
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return the field
+     */    
+    protected PdfFormField getField(boolean isRadio) throws IOException, DocumentException {
+        PdfFormField field = null;
+        if (isRadio)
+            field = PdfFormField.createEmpty(writer);
+        else
+            field = PdfFormField.createCheckBox(writer);
+        field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+        if (!isRadio) {
+            field.setFieldName(fieldName);
+            if ((options & READ_ONLY) != 0)
+                field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+            if ((options & REQUIRED) != 0)
+                field.setFieldFlags(PdfFormField.FF_REQUIRED);
+            field.setValueAsName(checked ? onValue : "Off");
+        }
+        if (text != null)
+            field.setMKNormalCaption(text);
+        if (rotation != 0)
+            field.setMKRotation(rotation);
+        field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+        PdfAppearance tpon = getAppearance(isRadio, true);
+        PdfAppearance tpoff = getAppearance(isRadio, false);
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, onValue, tpon);
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpoff);
+        field.setAppearanceState(checked ? onValue : "Off");
+        PdfAppearance da = (PdfAppearance)tpon.getDuplicate();
+        da.setFontAndSize(getRealFont(), fontSize);
+        if (textColor == null)
+            da.setGrayFill(0);
+        else
+            da.setColorFill(textColor);
+        field.setDefaultAppearanceString(da);
+        if (borderColor != null)
+            field.setMKBorderColor(borderColor);
+        if (backgroundColor != null)
+            field.setMKBackgroundColor(backgroundColor);
+        switch (visibility) {
+            case HIDDEN:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+                break;
+            case VISIBLE_BUT_DOES_NOT_PRINT:
+                break;
+            case HIDDEN_BUT_PRINTABLE:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+                break;
+            default:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT);
+                break;
+        }
+        return field;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/RandomAccessFileOrArray.java b/LibrarySource/com/lowagie/text/pdf/RandomAccessFileOrArray.java
new file mode 100644
index 0000000..908a09f
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/RandomAccessFileOrArray.java
@@ -0,0 +1,594 @@
+/*
+ * $Id: RandomAccessFileOrArray.java,v 1.11 2002/06/20 13:30:25 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.DataInputStream;
+import java.io.DataInput;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URL;
+/** An implementation of a RandomAccessFile for input only
+ * that accepts a file or a byte array as data source.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class RandomAccessFileOrArray implements DataInput {
+    
+    RandomAccessFile rf;
+    String filename;
+    byte arrayIn[];
+    int arrayInPtr;
+    byte back;
+    boolean isBack = false;
+    
+    /** Holds value of property startOffset. */
+    private int startOffset = 0;
+    
+    public RandomAccessFileOrArray(String filename) throws IOException {
+        File file = new File(filename);
+        if (!file.canRead()) {
+            if (filename.startsWith("file:/") || filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("jar:")) {
+                InputStream is = new URL(filename).openStream();
+                try {
+                    this.arrayIn = InputStreamToArray(is);
+                    return;
+                }
+                finally {
+                    try {is.close();}catch(IOException ioe){}
+                }
+            }
+            else {
+                InputStream is = BaseFont.getResourceStream(filename);
+                if (is == null)
+                    throw new IOException(filename + " not found as file or resource.");
+                try {
+                    this.arrayIn = InputStreamToArray(is);
+                    return;
+                }
+                finally {
+                    try {is.close();}catch(IOException ioe){}
+                }
+            }
+        }
+        this.filename = filename;
+        rf = new RandomAccessFile(filename, "r");
+    }
+
+    public RandomAccessFileOrArray(URL url) throws IOException {
+        InputStream is = url.openStream();
+        try {
+            this.arrayIn = InputStreamToArray(is);
+        }
+        finally {
+            try {is.close();}catch(IOException ioe){}
+        }
+    }
+
+    public RandomAccessFileOrArray(InputStream is) throws IOException {
+        this.arrayIn = InputStreamToArray(is);
+    }
+    
+    public byte[] InputStreamToArray(InputStream is) throws IOException {
+        byte b[] = new byte[8192];
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        while (true) {
+            int read = is.read(b);
+            if (read < 1)
+                break;
+            out.write(b, 0, read);
+        }
+        return out.toByteArray();
+    }
+
+    public RandomAccessFileOrArray(byte arrayIn[]) {
+        this.arrayIn = arrayIn;
+    }
+    
+    public RandomAccessFileOrArray(RandomAccessFileOrArray file) {
+        filename = file.filename;
+        arrayIn = file.arrayIn;
+        startOffset = file.startOffset;
+    }
+    
+    public void pushBack(byte b) {
+        back = b;
+        isBack = true;
+    }
+    
+    public int read() throws IOException {
+        if(isBack) {
+            isBack = false;
+            return back & 0xff;
+        }
+        if (arrayIn == null)
+            return rf.read();
+        else {
+            if (arrayInPtr >= arrayIn.length)
+                return -1;
+            return arrayIn[arrayInPtr++] & 0xff;
+        }
+    }
+    
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (len == 0)
+            return 0;
+        int n = 0;
+        if (isBack) {
+            isBack = false;
+            if (len == 1) {
+                b[off] = back;
+                return 1;
+            }
+            else {
+                n = 1;
+                b[off++] = back;
+                --len;
+            }
+        }
+        if (arrayIn == null) {
+            return rf.read(b, off, len) + n;
+        }
+        else {
+            if (arrayInPtr >= arrayIn.length)
+                return -1;
+            if (arrayInPtr + len > arrayIn.length)
+                len = arrayIn.length - arrayInPtr;
+            System.arraycopy(arrayIn, arrayInPtr, b, off, len);
+            arrayInPtr += len;
+            return len + n;
+        }
+    }
+    
+    public int read(byte b[]) throws IOException {
+        return read(b, 0, b.length);
+    }
+    
+    public void readFully(byte b[]) throws IOException {
+        readFully(b, 0, b.length);
+    }
+    
+    public void readFully(byte b[], int off, int len) throws IOException {
+        int n = 0;
+        do {
+            int count = read(b, off + n, len - n);
+            if (count < 0)
+                throw new EOFException();
+            n += count;
+        } while (n < len);
+    }
+    
+    public long skip(long n) throws IOException {
+        return skipBytes((int)n);
+    }
+    
+    public int skipBytes(int n) throws IOException {
+        if (n <= 0) {
+            return 0;
+        }
+        int adj = 0;
+        if (isBack) {
+            isBack = false;
+            if (n == 1) {
+                return 1;
+            }
+            else {
+                --n;
+                adj = 1;
+            }
+        }
+        int pos;
+        int len;
+        int newpos;
+        
+        pos = getFilePointer();
+        len = length();
+        newpos = pos + n;
+        if (newpos > len) {
+            newpos = len;
+        }
+        seek(newpos);
+        
+        /* return the actual number of bytes skipped */
+        return newpos - pos + adj;
+    }
+    
+    public void reOpen() throws IOException {
+        if (filename != null && rf == null)
+            rf = new RandomAccessFile(filename, "r");
+        seek(0);
+    }
+    
+    protected void insureOpen() throws IOException {
+        if (filename != null && rf == null) {
+            reOpen();
+        }
+    }
+    
+    public boolean isOpen() {
+        return (filename == null || rf != null);
+    }
+    
+    public void close() throws IOException {
+        isBack = false;
+        if (rf != null) {
+            rf.close();
+            rf = null;
+        }
+    }
+    
+    public int length() throws IOException {
+        if (arrayIn == null) {
+            insureOpen();
+            return (int)rf.length() - startOffset;
+        }
+        else
+            return arrayIn.length - startOffset;
+    }
+    
+    public void seek(int pos) throws IOException {
+        pos += startOffset;
+        isBack = false;
+        if (arrayIn == null) {
+            insureOpen();
+            rf.seek(pos);
+        }
+        else
+            arrayInPtr = pos;
+    }
+    
+    public void seek(long pos) throws IOException {
+        seek((int)pos);
+    }
+    
+    public int getFilePointer() throws IOException {
+        insureOpen();
+        int n = isBack ? 1 : 0;
+        if (arrayIn == null) {
+            return (int)rf.getFilePointer() - n - startOffset;
+        }
+        else
+            return arrayInPtr - n - startOffset;
+    }
+    
+    public boolean readBoolean() throws IOException {
+        int ch = this.read();
+        if (ch < 0)
+            throw new EOFException();
+        return (ch != 0);
+    }
+    
+    public byte readByte() throws IOException {
+        int ch = this.read();
+        if (ch < 0)
+            throw new EOFException();
+        return (byte)(ch);
+    }
+    
+    public int readUnsignedByte() throws IOException {
+        int ch = this.read();
+        if (ch < 0)
+            throw new EOFException();
+        return ch;
+    }
+    
+    public short readShort() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (short)((ch1 << 8) + ch2);
+    }
+    
+    /**
+     * Reads a signed 16-bit number from this stream in little-endian order.
+     * The method reads two
+     * bytes from this stream, starting at the current stream pointer.
+     * If the two bytes read, in order, are
+     * <code>b1</code> and <code>b2</code>, where each of the two values is
+     * between <code>0</code> and <code>255</code>, inclusive, then the
+     * result is equal to:
+     * <blockquote><pre>
+     *     (short)((b2 << 8) | b1)
+     * </pre></blockquote>
+     * <p>
+     * This method blocks until the two bytes are read, the end of the
+     * stream is detected, or an exception is thrown.
+     *
+     * @return     the next two bytes of this stream, interpreted as a signed
+     *             16-bit number.
+     * @exception  EOFException  if this stream reaches the end before reading
+     *               two bytes.
+     * @exception  IOException   if an I/O error occurs.
+     */
+    public final short readShortLE() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (short)((ch2 << 8) + (ch1 << 0));
+    }
+    
+    public int readUnsignedShort() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (ch1 << 8) + ch2;
+    }
+    
+    /**
+     * Reads an unsigned 16-bit number from this stream in little-endian order.
+     * This method reads
+     * two bytes from the stream, starting at the current stream pointer.
+     * If the bytes read, in order, are
+     * <code>b1</code> and <code>b2</code>, where
+     * <code>0 <= b1, b2 <= 255</code>,
+     * then the result is equal to:
+     * <blockquote><pre>
+     *     (b2 << 8) | b1
+     * </pre></blockquote>
+     * <p>
+     * This method blocks until the two bytes are read, the end of the
+     * stream is detected, or an exception is thrown.
+     *
+     * @return     the next two bytes of this stream, interpreted as an
+     *             unsigned 16-bit integer.
+     * @exception  EOFException  if this stream reaches the end before reading
+     *               two bytes.
+     * @exception  IOException   if an I/O error occurs.
+     */
+    public final int readUnsignedShortLE() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (ch2 << 8) + (ch1 << 0);
+    }
+    
+    public char readChar() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (char)((ch1 << 8) + ch2);
+    }
+    
+    /**
+     * Reads a Unicode character from this stream in little-endian order.
+     * This method reads two
+     * bytes from the stream, starting at the current stream pointer.
+     * If the bytes read, in order, are
+     * <code>b1</code> and <code>b2</code>, where
+     * <code>0 <= b1, b2 <= 255</code>,
+     * then the result is equal to:
+     * <blockquote><pre>
+     *     (char)((b2 << 8) | b1)
+     * </pre></blockquote>
+     * <p>
+     * This method blocks until the two bytes are read, the end of the
+     * stream is detected, or an exception is thrown.
+     *
+     * @return     the next two bytes of this stream as a Unicode character.
+     * @exception  EOFException  if this stream reaches the end before reading
+     *               two bytes.
+     * @exception  IOException   if an I/O error occurs.
+     */
+    public final char readCharLE() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        if ((ch1 | ch2) < 0)
+            throw new EOFException();
+        return (char)((ch2 << 8) + (ch1 << 0));
+    }
+    
+    public int readInt() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        int ch3 = this.read();
+        int ch4 = this.read();
+        if ((ch1 | ch2 | ch3 | ch4) < 0)
+            throw new EOFException();
+        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
+    }
+    
+    /**
+     * Reads a signed 32-bit integer from this stream in little-endian order.
+     * This method reads 4
+     * bytes from the stream, starting at the current stream pointer.
+     * If the bytes read, in order, are <code>b1</code>,
+     * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
+     * <code>0 <= b1, b2, b3, b4 <= 255</code>,
+     * then the result is equal to:
+     * <blockquote><pre>
+     *     (b4 << 24) | (b3 << 16) + (b2 << 8) + b1
+     * </pre></blockquote>
+     * <p>
+     * This method blocks until the four bytes are read, the end of the
+     * stream is detected, or an exception is thrown.
+     *
+     * @return     the next four bytes of this stream, interpreted as an
+     *             <code>int</code>.
+     * @exception  EOFException  if this stream reaches the end before reading
+     *               four bytes.
+     * @exception  IOException   if an I/O error occurs.
+     */
+    public final int readIntLE() throws IOException {
+        int ch1 = this.read();
+        int ch2 = this.read();
+        int ch3 = this.read();
+        int ch4 = this.read();
+        if ((ch1 | ch2 | ch3 | ch4) < 0)
+            throw new EOFException();
+        return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
+    }
+    
+    /**
+     * Reads an unsigned 32-bit integer from this stream. This method reads 4
+     * bytes from the stream, starting at the current stream pointer.
+     * If the bytes read, in order, are <code>b1</code>,
+     * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
+     * <code>0 <= b1, b2, b3, b4 <= 255</code>,
+     * then the result is equal to:
+     * <blockquote><pre>
+     *     (b1 << 24) | (b2 << 16) + (b3 << 8) + b4
+     * </pre></blockquote>
+     * <p>
+     * This method blocks until the four bytes are read, the end of the
+     * stream is detected, or an exception is thrown.
+     *
+     * @return     the next four bytes of this stream, interpreted as a
+     *             <code>long</code>.
+     * @exception  EOFException  if this stream reaches the end before reading
+     *               four bytes.
+     * @exception  IOException   if an I/O error occurs.
+     */
+    public final long readUnsignedInt() throws IOException {
+        long ch1 = this.read();
+        long ch2 = this.read();
+        long ch3 = this.read();
+        long ch4 = this.read();
+        if ((ch1 | ch2 | ch3 | ch4) < 0)
+            throw new EOFException();
+        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+    }
+    
+    public final long readUnsignedIntLE() throws IOException {
+        long ch1 = this.read();
+        long ch2 = this.read();
+        long ch3 = this.read();
+        long ch4 = this.read();
+        if ((ch1 | ch2 | ch3 | ch4) < 0)
+            throw new EOFException();
+        return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
+    }
+    
+    public long readLong() throws IOException {
+        return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
+    }
+    
+    public final long readLongLE() throws IOException {
+        int i1 = readIntLE();
+        int i2 = readIntLE();
+        return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
+    }
+    
+    public float readFloat() throws IOException {
+        return Float.intBitsToFloat(readInt());
+    }
+    
+    public final float readFloatLE() throws IOException {
+        return Float.intBitsToFloat(readIntLE());
+    }
+    
+    public double readDouble() throws IOException {
+        return Double.longBitsToDouble(readLong());
+    }
+    
+    public final double readDoubleLE() throws IOException {
+        return Double.longBitsToDouble(readLongLE());
+    }
+    
+    public String readLine() throws IOException {
+        StringBuffer input = new StringBuffer();
+        int c = -1;
+        boolean eol = false;
+        
+        while (!eol) {
+            switch (c = read()) {
+                case -1:
+                case '\n':
+                    eol = true;
+                    break;
+                case '\r':
+                    eol = true;
+                    int cur = getFilePointer();
+                    if ((read()) != '\n') {
+                        seek(cur);
+                    }
+                    break;
+                default:
+                    input.append((char)c);
+                    break;
+            }
+        }
+        
+        if ((c == -1) && (input.length() == 0)) {
+            return null;
+        }
+        return input.toString();
+    }
+    
+    public String readUTF() throws IOException {
+        return DataInputStream.readUTF(this);
+    }
+    
+    /** Getter for property startOffset.
+     * @return Value of property startOffset.
+     *
+     */
+    public int getStartOffset() {
+        return this.startOffset;
+    }
+    
+    /** Setter for property startOffset.
+     * @param startOffset New value of property startOffset.
+     *
+     */
+    public void setStartOffset(int startOffset) {
+        this.startOffset = startOffset;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/SequenceList.java b/LibrarySource/com/lowagie/text/pdf/SequenceList.java
new file mode 100644
index 0000000..c1c336d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SequenceList.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * This class expands a string into a list of numbers. The main use is to select a
+ * range of pages.
+ * <p>
+ * The general systax is:<br>
+ * [!][o][odd][e][even]start-end
+ * <p>
+ * You can have multiple ranges separated by commas ','. The '!' modifier removes the
+ * range from what is already selected. The range changes are incremental, that is,
+ * numbers are added or deleted as the range appears. The start or the end, but not both, can be ommited.
+ */
+public class SequenceList {
+    protected static final int COMMA = 1;
+    protected static final int MINUS = 2;
+    protected static final int NOT = 3;
+    protected static final int TEXT = 4;
+    protected static final int NUMBER = 5;
+    protected static final int END = 6;
+    protected static final char EOT = '\uffff';
+
+    private static final int FIRST = 0;
+    private static final int DIGIT = 1;
+    private static final int OTHER = 2;
+    private static final int DIGIT2 = 3;
+    private static final String NOT_OTHER = "-,!0123456789";
+
+    protected char text[];
+    protected int ptr;
+    protected int number;
+    protected String other;
+
+    protected int low;
+    protected int high;
+    protected boolean odd;
+    protected boolean even;
+    protected boolean inverse;
+
+    protected SequenceList(String range) {
+        ptr = 0;
+        text = range.toCharArray();
+    }
+    
+    protected char nextChar() {
+        while (true) {
+            if (ptr >= text.length)
+                return EOT;
+            char c = text[ptr++];
+            if (c > ' ')
+                return c;
+        }
+    }
+    
+    protected void putBack() {
+        --ptr;
+        if (ptr < 0)
+            ptr = 0;
+    }
+    
+    protected int getType() {
+        StringBuffer buf = new StringBuffer();
+        int state = FIRST;
+        while (true) {
+            char c = nextChar();
+            if (c == EOT) {
+                if (state == DIGIT) {
+                    number = Integer.parseInt(other = buf.toString());
+                    return NUMBER;
+                }
+                else if (state == OTHER) {
+                    other = buf.toString().toLowerCase();
+                    return TEXT;
+                }
+                return END;
+            }
+            switch (state) {
+                case FIRST:
+                    switch (c) {
+                        case '!':
+                            return NOT;
+                        case '-':
+                            return MINUS;
+                        case ',':
+                            return COMMA;
+                    }
+                    buf.append(c);
+                    if (c >= '0' && c <= '9')
+                        state = DIGIT;
+                    else
+                        state = OTHER;
+                    break;
+                case DIGIT:
+                    if (c >= '0' && c <= '9')
+                        buf.append(c);
+                    else {
+                        putBack();
+                        number = Integer.parseInt(other = buf.toString());
+                        return NUMBER;
+                    }
+                    break;
+                case OTHER:
+                    if (NOT_OTHER.indexOf(c) < 0)
+                        buf.append(c);
+                    else {
+                        putBack();
+                        other = buf.toString().toLowerCase();
+                        return TEXT;
+                    }
+                    break;
+            }
+        }
+    }
+    
+    private void otherProc() {
+        if (other.equals("odd") || other.equals("o")) {
+            odd = true;
+            even = false;
+        }
+        else if (other.equals("even") || other.equals("e")) {
+            odd = false;
+            even = true;
+        }
+    }
+    
+    protected boolean getAttributes() {
+        low = -1;
+        high = -1;
+        odd = even = inverse = false;
+        int state = OTHER;
+        while (true) {
+            int type = getType();
+            if (type == END || type == COMMA) {
+                if (state == DIGIT)
+                    high = low;
+                return (type == END);
+            }
+            switch (state) {
+                case OTHER:
+                    switch (type) {
+                        case NOT:
+                            inverse = true;
+                            break;
+                        case MINUS:
+                            state = DIGIT2;
+                            break;
+                        default:
+                            if (type == NUMBER) {
+                                low = number;
+                                state = DIGIT;
+                            }
+                            else
+                                otherProc();
+                            break;
+                    }
+                    break;
+                case DIGIT:
+                    switch (type) {
+                        case NOT:
+                            inverse = true;
+                            state = OTHER;
+                            high = low;
+                            break;
+                        case MINUS:
+                            state = DIGIT2;
+                            break;
+                        default:
+                            high = low;
+                            state = OTHER;
+                            otherProc();
+                            break;
+                    }
+                    break;
+                case DIGIT2:
+                    switch (type) {
+                        case NOT:
+                            inverse = true;
+                            state = OTHER;
+                            break;
+                        case MINUS:
+                            break;
+                        case NUMBER:
+                            high = number;
+                            state = OTHER;
+                            break;
+                        default:
+                            state = OTHER;
+                            otherProc();
+                            break;
+                    }
+                    break;
+            }
+        }
+    }
+    
+    /**
+     * Generates a list of numbers from a string.
+     * @param ranges the comma separated ranges
+     * @param maxNumber the maximum number in the range
+     * @return a list with the numbers as <CODE>Integer</CODE>
+     */    
+    public static List expand(String ranges, int maxNumber) {
+        SequenceList parse = new SequenceList(ranges);
+        LinkedList list = new LinkedList();
+        boolean sair = false;
+        while (!sair) {
+            sair = parse.getAttributes();
+            if (parse.low == -1 && parse.high == -1)
+                continue;
+            if (parse.low < 1)
+                parse.low = 1;
+            if (parse.high < 1 || parse.high > maxNumber)
+                parse.high = maxNumber;
+            if (parse.low > maxNumber)
+                parse.low = maxNumber;
+            
+            //System.out.println("low="+parse.low+",high="+parse.high+",odd="+parse.odd+",even="+parse.even+",inverse="+parse.inverse);
+            int inc = 1;
+            if (parse.inverse) {
+                if (parse.low > parse.high) {
+                    int t = parse.low;
+                    parse.low = parse.high;
+                    parse.high = t;
+                }
+                for (ListIterator it = list.listIterator(); it.hasNext();) {
+                    int n = ((Integer)it.next()).intValue();
+                    if (parse.even && (n & 1) == 1)
+                        continue;
+                    if (parse.odd && (n & 1) == 0)
+                        continue;
+                    if (n >= parse.low && n <= parse.high)
+                        it.remove();
+                }
+            }
+            else {
+                if (parse.low > parse.high) {
+                    inc = -1;
+                    if (parse.odd || parse.even) {
+                        --inc;
+                        if (parse.even)
+                            parse.low &= ~1;
+                        else
+                            parse.low -= ((parse.low & 1) == 1 ? 0 : 1);
+                    }
+                    for (int k = parse.low; k >= parse.high; k += inc)
+                        list.add(new Integer(k));
+                }
+                else {
+                    if (parse.odd || parse.even) {
+                        ++inc;
+                        if (parse.odd)
+                            parse.low |= 1;
+                        else
+                            parse.low += ((parse.low & 1) == 1 ? 1 : 0);
+                    }
+                    for (int k = parse.low; k <= parse.high; k += inc)
+                        list.add(new Integer(k));
+                }
+            }
+//            for (int k = 0; k < list.size(); ++k)
+//                System.out.print(((Integer)list.get(k)).intValue() + ",");
+//            System.out.println();
+        }
+        return list;
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/ShadingColor.java b/LibrarySource/com/lowagie/text/pdf/ShadingColor.java
new file mode 100644
index 0000000..1727c85
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/ShadingColor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/** Implements a shading pattern as a <code>Color</code>.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class ShadingColor extends ExtendedColor {
+
+    PdfShadingPattern shadingPattern;
+
+    /**
+     * Creates a shading color.
+     * @param shadingPattern
+     */
+    public ShadingColor(PdfShadingPattern shadingPattern) {
+        super(TYPE_SHADING, .5f, .5f, .5f);
+        this.shadingPattern = shadingPattern;
+    }
+
+    /**
+     * Gets the shading pattern.
+     * @return a shading pattern.
+     */
+    public PdfShadingPattern getPdfShadingPattern() {
+        return shadingPattern;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/SimpleBookmark.java b/LibrarySource/com/lowagie/text/pdf/SimpleBookmark.java
new file mode 100644
index 0000000..a8c34d0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SimpleBookmark.java
@@ -0,0 +1,745 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.Writer;
+import java.io.Reader;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.util.Stack;
+/**
+ * Bookmark processing in a simple way. It has some limitations, mainly the only
+ * action types supported are GoTo, GoToR, URI and Launch.
+ * <p>
+ * The list structure is composed by a number of HashMap, keyed by strings, one HashMap
+ * for each bookmark.
+ * The element values are all strings with the exception of the key "Kids" that has
+ * another list for the child bookmarks.
+ * <p>
+ * All the bookmarks have a "Title" with the
+ * bookmark title and optionally a "Style" that can be "bold", "italic" or a
+ * combination of both. They can also have a "Color" key with a value of three
+ * floats separated by spaces. The key "Open" can have the values "true" or "false" and
+ * signals the open status of the children. It's "true" by default.
+ * <p>
+ * The actions and the parameters can be:
+ * <ul>
+ * <li>"Action" = "GoTo" - "Page" | "Named"
+ * <ul>
+ * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
+ * <li>"Named" = "named_destination"
+ * </ul>
+ * <li>"Action" = "GoToR" - "Page" | "Named" | "NamedN", "File", ["NewWindow"]
+ * <ul>
+ * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
+ * <li>"Named" = "named_destination_as_a_string"
+ * <li>"NamedN" = "named_destination_as_a_name"
+ * <li>"File" - "the_file_to_open"
+ * <li>"NewWindow" - "true" or "false"
+ * </ul>
+ * <li>"Action" = "URI" - "URI"
+ * <ul>
+ * <li>"URI" = "http://sf.net" - URI to jump to
+ * </ul>
+ * <li>"Action" = "Launch" - "File"
+ * <ul>
+ * <li>"File" - "the_file_to_open_or_execute"
+ * </ul>
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class SimpleBookmark implements SimpleXMLDocHandler {
+    
+    private ArrayList topList;
+    private Stack attr = new Stack();
+    
+    /** Creates a new instance of SimpleBookmark */
+    private SimpleBookmark() {
+    }
+    
+    private static List bookmarkDepth(PdfReader reader, PdfDictionary outline, IntHashtable pages) {
+        ArrayList list = new ArrayList();
+        while (outline != null) {
+            HashMap map = new HashMap();
+            PdfString title = (PdfString)PdfReader.getPdfObjectRelease(outline.get(PdfName.TITLE));
+            map.put("Title", title.toUnicodeString());
+            PdfArray color = (PdfArray)PdfReader.getPdfObjectRelease(outline.get(PdfName.C));
+            if (color != null && color.getArrayList().size() == 3) {
+                ByteBuffer out = new ByteBuffer();
+                ArrayList arr = color.getArrayList();
+                out.append(((PdfNumber)arr.get(0)).floatValue()).append(' ');
+                out.append(((PdfNumber)arr.get(1)).floatValue()).append(' ');
+                out.append(((PdfNumber)arr.get(2)).floatValue());
+                map.put("Color", PdfEncodings.convertToString(out.toByteArray(), null));
+            }
+            PdfNumber style = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.F));
+            if (style != null) {
+                int f = style.intValue();
+                String s = "";
+                if ((f & 1) != 0)
+                    s += "italic ";
+                if ((f & 2) != 0)
+                    s += "bold ";
+                s = s.trim();
+                if (s.length() != 0) 
+                    map.put("Style", s);
+            }
+            PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.COUNT));
+            if (count != null && count.intValue() < 0)
+                map.put("Open", "false");
+            try {
+                PdfObject dest = PdfReader.getPdfObjectRelease(outline.get(PdfName.DEST));
+                if (dest != null) {
+                    mapGotoBookmark(map, dest, pages); //changed by ujihara 2004-06-13
+                }
+                else {
+                    PdfDictionary action = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.A));
+                    if (action != null) {
+                        if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+                            dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
+                            if (dest != null) {
+                                mapGotoBookmark(map, dest, pages);
+                            }
+                        }
+                        else if (PdfName.URI.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+                            map.put("Action", "URI");
+                            map.put("URI", ((PdfString)PdfReader.getPdfObjectRelease(action.get(PdfName.URI))).toUnicodeString());
+                        }
+                        else if (PdfName.GOTOR.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+                            dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
+                            if (dest != null) {
+                                if (dest.isString())
+                                    map.put("Named", dest.toString());
+                                else if (dest.isName())
+                                    map.put("NamedN", PdfName.decodeName(dest.toString()));
+                                else if (dest.isArray()) {
+                                    ArrayList arr = ((PdfArray)dest).getArrayList();
+                                    StringBuffer s = new StringBuffer();
+                                    s.append(arr.get(0).toString());
+                                    s.append(' ').append(arr.get(1).toString());
+                                    for (int k = 2; k < arr.size(); ++k)
+                                        s.append(' ').append(arr.get(k).toString());
+                                    map.put("Page", s.toString());
+                                }
+                            }
+                            map.put("Action", "GoToR");
+                            PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
+                            if (file != null) {
+                                if (file.isString())
+                                    map.put("File", ((PdfString)file).toUnicodeString());
+                                else if (file.isDictionary()) {
+                                    file = PdfReader.getPdfObject(((PdfDictionary)file).get(PdfName.F));
+                                    if (file.isString())
+                                        map.put("File", ((PdfString)file).toUnicodeString());
+                                }
+                            }
+                            PdfObject newWindow = PdfReader.getPdfObjectRelease(action.get(PdfName.NEWWINDOW));
+                            if (newWindow != null)
+                                map.put("NewWindow", newWindow.toString());
+                        }
+                        else if (PdfName.LAUNCH.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+                            map.put("Action", "Launch");
+                            PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
+                            if (file == null)
+                                file = PdfReader.getPdfObjectRelease(action.get(PdfName.WIN));
+                            if (file != null) {
+                                if (file.isString())
+                                    map.put("File", ((PdfString)file).toUnicodeString());
+                                else if (file.isDictionary()) {
+                                    file = PdfReader.getPdfObjectRelease(((PdfDictionary)file).get(PdfName.F));
+                                    if (file.isString())
+                                        map.put("File", ((PdfString)file).toUnicodeString());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            catch (Exception e) {
+                //empty on purpose
+            }
+            PdfDictionary first = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.FIRST));
+            if (first != null) {
+                map.put("Kids", bookmarkDepth(reader, first, pages));
+            }
+            list.add(map);
+            outline = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.NEXT));
+        }
+        return list;
+    }
+    
+	private static void mapGotoBookmark(HashMap map, PdfObject dest, IntHashtable pages) 
+	{
+		if (dest.isString())
+			map.put("Named", dest.toString());
+		else if (dest.isName())
+			map.put("Named", PdfName.decodeName(dest.toString()));
+		else if (dest.isArray()) 
+			map.put("Page", makeBookmarkParam((PdfArray)dest, pages)); //changed by ujihara 2004-06-13
+		map.put("Action", "GoTo");
+	}
+
+	private static String makeBookmarkParam(PdfArray dest, IntHashtable pages)
+	{
+		ArrayList arr = ((PdfArray)dest).getArrayList();
+		StringBuffer s = new StringBuffer();
+		s.append(pages.get(getNumber((PdfIndirectReference)arr.get(0)))); //changed by ujihara 2004-06-13
+		s.append(' ').append(arr.get(1).toString().substring(1));
+		for (int k = 2; k < arr.size(); ++k)
+			s.append(' ').append(arr.get(k).toString());
+		return s.toString();
+	}
+	
+	/**
+	 * Gets number of indirect. If type of directed indirect is PAGES, it refers PAGE object through KIDS.
+	 * (Contributed by Kazuya Ujihara)
+	 * @param indirect 
+	 * 2004-06-13
+	 */
+	private static int getNumber(PdfIndirectReference indirect)
+	{
+		PdfDictionary pdfObj = (PdfDictionary)PdfReader.getPdfObjectRelease(indirect);
+		if (pdfObj.contains(PdfName.TYPE) && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES) && pdfObj.contains(PdfName.KIDS)) 
+		{
+			PdfArray kids = (PdfArray)pdfObj.get(PdfName.KIDS);
+			indirect = (PdfIndirectReference)kids.arrayList.get(0);
+		}
+		return indirect.getNumber();
+	}
+    
+    /**
+     * Gets a <CODE>List</CODE> with the bookmarks. It returns <CODE>null</CODE> if
+     * the document doesn't have any bookmarks.
+     * @param reader the document
+     * @return a <CODE>List</CODE> with the bookmarks or <CODE>null</CODE> if the
+     * document doesn't have any
+     */    
+    public static List getBookmark(PdfReader reader) {
+        PdfDictionary catalog = reader.getCatalog();
+        PdfDictionary outlines = (PdfDictionary)PdfReader.getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
+        if (outlines == null)
+            return null;
+        IntHashtable pages = new IntHashtable();
+        int numPages = reader.getNumberOfPages();
+        for (int k = 1; k <= numPages; ++k) {
+            pages.put(reader.getPageOrigRef(k).getNumber(), k);
+            reader.releasePage(k);
+        }
+        return bookmarkDepth(reader, (PdfDictionary)PdfReader.getPdfObjectRelease(outlines.get(PdfName.FIRST)), pages);
+    }
+    
+    /**
+     * Removes the bookmark entries for a number of page ranges. The page ranges
+     * consists of a number of pairs with the start/end page range. The page numbers
+     * are inclusive.
+     * @param list the bookmarks
+     * @param pageRange the page ranges, always in pairs.
+     */    
+    public static void eliminatePages(List list, int pageRange[]) {
+        if (list == null)
+            return;
+        for (Iterator it = list.listIterator(); it.hasNext();) {
+            HashMap map = (HashMap)it.next();
+            boolean hit = false;
+            if ("GoTo".equals(map.get("Action"))) {
+                String page = (String)map.get("Page");
+                if (page != null) {
+                    page = page.trim();
+                    int idx = page.indexOf(' ');
+                    int pageNum;
+                    if (idx < 0)
+                        pageNum = Integer.parseInt(page);
+                    else
+                        pageNum = Integer.parseInt(page.substring(0, idx));
+                    int len = pageRange.length & 0xfffffffe;
+                    for (int k = 0; k < len; k += 2) {
+                        if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
+                            hit = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            List kids = (List)map.get("Kids");
+            if (kids != null) {
+                eliminatePages(kids, pageRange);
+                if (kids.size() == 0) {
+                    map.remove("Kids");
+                    kids = null;
+                }
+            }
+            if (hit) {
+                if (kids == null)
+                    it.remove();
+                else {
+                    map.remove("Action");
+                    map.remove("Page");
+                    map.remove("Named");
+                }
+            }
+        }
+    }
+    
+    /**
+     * For the pages in range add the <CODE>pageShift</CODE> to the page number.
+     * The page ranges
+     * consists of a number of pairs with the start/end page range. The page numbers
+     * are inclusive.
+     * @param list the bookmarks
+     * @param pageShift the number to add to the pages in range
+     * @param pageRange the page ranges, always in pairs. It can be <CODE>null</CODE>
+     * to include all the pages
+     */    
+    public static void shiftPageNumbers(List list, int pageShift, int pageRange[]) {
+        if (list == null)
+            return;
+        for (Iterator it = list.listIterator(); it.hasNext();) {
+            HashMap map = (HashMap)it.next();
+            if ("GoTo".equals(map.get("Action"))) {
+                String page = (String)map.get("Page");
+                if (page != null) {
+                    page = page.trim();
+                    int idx = page.indexOf(' ');
+                    int pageNum;
+                    if (idx < 0)
+                        pageNum = Integer.parseInt(page);
+                    else
+                        pageNum = Integer.parseInt(page.substring(0, idx));
+                    boolean hit = false;
+                    if (pageRange == null)
+                        hit = true;
+                    else {
+                        int len = pageRange.length & 0xfffffffe;
+                        for (int k = 0; k < len; k += 2) {
+                            if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
+                                hit = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (hit) {
+                        if (idx < 0)
+                            page = (pageNum + pageShift) + "";
+                        else
+                            page = (pageNum + pageShift) + page.substring(idx);
+                    }
+                    map.put("Page", page);
+                }
+            }
+            List kids = (List)map.get("Kids");
+            if (kids != null)
+                shiftPageNumbers(kids, pageShift, pageRange);
+        }
+    }
+    
+    static void createOutlineAction(PdfDictionary outline, HashMap map, PdfWriter writer, boolean namedAsNames) throws IOException {
+        try {
+            String action = (String)map.get("Action");
+            if ("GoTo".equals(action)) {
+                String p;
+                if ((p = (String)map.get("Named")) != null) {
+                    if (namedAsNames)
+                        outline.put(PdfName.DEST, new PdfName(p));
+                    else
+                        outline.put(PdfName.DEST, new PdfString(p, null));
+                }
+                else if ((p = (String)map.get("Page")) != null) {
+                    PdfArray ar = new PdfArray();
+                    StringTokenizer tk = new StringTokenizer(p);
+                    int n = Integer.parseInt(tk.nextToken());
+                    ar.add(writer.getPageReference(n));
+                    if (!tk.hasMoreTokens()) {
+                        ar.add(PdfName.XYZ);
+                        ar.add(new float[]{0, 10000, 0});
+                    }
+                    else {
+                        String fn = tk.nextToken();
+                        if (fn.startsWith("/"))
+                            fn = fn.substring(1);
+                        ar.add(new PdfName(fn));
+                        for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+                            fn = tk.nextToken();
+                            if (fn.equals("null"))
+                                ar.add(PdfNull.PDFNULL);
+                            else
+                                ar.add(new PdfNumber(fn));
+                        }
+                    }
+                    outline.put(PdfName.DEST, ar);
+                }
+            }
+            else if ("GoToR".equals(action)) {
+                String p;
+                PdfDictionary dic = new PdfDictionary();
+                if ((p = (String)map.get("Named")) != null)
+                    dic.put(PdfName.D, new PdfString(p, null));
+                else if ((p = (String)map.get("NamedN")) != null)
+                    dic.put(PdfName.D, new PdfName(p));
+                else if ((p = (String)map.get("Page")) != null){
+                    PdfArray ar = new PdfArray();
+                    StringTokenizer tk = new StringTokenizer(p);
+                    ar.add(new PdfNumber(tk.nextToken()));
+                    if (!tk.hasMoreTokens()) {
+                        ar.add(PdfName.XYZ);
+                        ar.add(new float[]{0, 10000, 0});
+                    }
+                    else {
+                        String fn = tk.nextToken();
+                        if (fn.startsWith("/"))
+                            fn = fn.substring(1);
+                        ar.add(new PdfName(fn));
+                        for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+                            fn = tk.nextToken();
+                            if (fn.equals("null"))
+                                ar.add(PdfNull.PDFNULL);
+                            else
+                                ar.add(new PdfNumber(fn));
+                        }
+                    }
+                    dic.put(PdfName.D, ar);
+                }
+                String file = (String)map.get("File");
+                if (dic.size() > 0 && file != null) {
+                    dic.put(PdfName.S,  PdfName.GOTOR);
+                    dic.put(PdfName.F, new PdfString(file));
+                    String nw = (String)map.get("NewWindow");
+                    if (nw != null) {
+                        if (nw.equals("true"))
+                            dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
+                        else if (nw.equals("false"))
+                            dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFFALSE);
+                    }
+                    outline.put(PdfName.A, dic);
+                }
+            }
+            else if ("URI".equals(action)) {
+                String uri = (String)map.get("URI");
+                if (uri != null) {
+                    PdfDictionary dic = new PdfDictionary();
+                    dic.put(PdfName.S, PdfName.URI);
+                    dic.put(PdfName.URI, new PdfString(uri));
+                    outline.put(PdfName.A, dic);
+                }
+            }
+            else if ("Launch".equals(action)) {
+                String file = (String)map.get("File");
+                if (file != null) {
+                    PdfDictionary dic = new PdfDictionary();
+                    dic.put(PdfName.S, PdfName.LAUNCH);
+                    dic.put(PdfName.F, new PdfString(file));
+                    outline.put(PdfName.A, dic);
+                }
+            }
+        }
+        catch (Exception e) {
+            // empty on purpose
+        }
+    }
+
+    static Object[] iterateOutlines(PdfWriter writer, PdfIndirectReference parent, List kids, boolean namedAsNames) throws IOException {
+        PdfIndirectReference refs[] = new PdfIndirectReference[kids.size()];
+        for (int k = 0; k < refs.length; ++k)
+            refs[k] = writer.getPdfIndirectReference();
+        int ptr = 0;
+        int count = 0;
+        for (Iterator it = kids.listIterator(); it.hasNext(); ++ptr) {
+            HashMap map = (HashMap)it.next();
+            Object lower[] = null;
+            List subKid = (List)map.get("Kids");
+            if (subKid != null && subKid.size() > 0)
+                lower = iterateOutlines(writer, refs[ptr], subKid, namedAsNames);
+            PdfDictionary outline = new PdfDictionary();
+            ++count;
+            if (lower != null) {
+                outline.put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
+                outline.put(PdfName.LAST, (PdfIndirectReference)lower[1]);
+                int n = ((Integer)lower[2]).intValue();
+                int tc;
+                if ("false".equals(map.get("Open"))) {
+                    outline.put(PdfName.COUNT, new PdfNumber(-n));
+                }
+                else {
+                    outline.put(PdfName.COUNT, new PdfNumber(n));
+                    count += n;
+                }
+            }
+            outline.put(PdfName.PARENT, parent);
+            if (ptr > 0)
+                outline.put(PdfName.PREV, refs[ptr - 1]);
+            if (ptr < refs.length - 1)
+                outline.put(PdfName.NEXT, refs[ptr + 1]);
+            outline.put(PdfName.TITLE, new PdfString((String)map.get("Title"), PdfObject.TEXT_UNICODE));
+            String color = (String)map.get("Color");
+            if (color != null) {
+                try {
+                    PdfArray arr = new PdfArray();
+                    StringTokenizer tk = new StringTokenizer(color);
+                    for (int k = 0; k < 3; ++k) {
+                        float f = Float.valueOf(tk.nextToken()).intValue();
+                        if (f < 0) f = 0;
+                        if (f > 1) f = 1;
+                        arr.add(new PdfNumber(f));
+                    }
+                    outline.put(PdfName.C, arr);
+                } catch(Exception e){} //in case it's malformed
+            }
+            String style = (String)map.get("Style");
+            if (style != null) {
+                style = style.toLowerCase();
+                int bits = 0;
+                if (style.indexOf("italic") >= 0)
+                    bits |= 1;
+                if (style.indexOf("bold") >= 0)
+                    bits |= 2;
+                if (bits != 0)
+                    outline.put(PdfName.F, new PdfNumber(bits));
+            }
+            createOutlineAction(outline, map, writer, namedAsNames);
+            writer.addToBody(outline, refs[ptr]);
+        }
+        return new Object[]{refs[0], refs[refs.length - 1], new Integer(count)};
+    }
+    
+    /**
+     * Exports the bookmarks to XML. Only of use if the generation is to be include in
+     * some other XML document.
+     * @param list the bookmarks
+     * @param out the export destination. The writer is not closed
+     * @param indent the indentation level. Pretty printing significant only
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>,
+     * whatever the encoding
+     * @throws IOException on error
+     */
+    public static void exportToXMLNode(List list, Writer out, int indent, boolean onlyASCII) throws IOException {
+        String dep = "";
+        for (int k = 0; k < indent; ++k)
+            dep += "  ";
+        for (Iterator it = list.iterator(); it.hasNext();) {
+            HashMap map = (HashMap)it.next();
+            String title = null;
+            out.write(dep);
+            out.write("<Title ");
+            List kids = null;
+            for (Iterator e = map.keySet().iterator(); e.hasNext();) {
+                String key = (String)e.next();
+                if (key.equals("Title")) {
+                    title = (String)map.get(key);
+                    continue;
+                }
+                else if (key.equals("Kids")) {
+                    kids = (List)map.get(key);
+                    continue;
+                }
+                else {
+                    out.write(key);
+                    out.write("=\"");
+                    String value = (String)map.get(key);
+                    if (key.equals("Named") || key.equals("NamedN"))
+                        value = SimpleNamedDestination.escapeBinaryString(value);
+                    out.write(SimpleXMLParser.escapeXML(value, onlyASCII));
+                    out.write("\" ");
+                }
+            }
+            out.write(">");
+            if (title == null)
+                title = "";
+            out.write(SimpleXMLParser.escapeXML(title, onlyASCII));
+            if (kids != null) {
+                out.write("\n");
+                exportToXMLNode(kids, out, indent + 1, onlyASCII);
+                out.write(dep);
+            }
+            out.write("</Title>\n");
+        }
+    }
+    
+    /**
+     * Exports the bookmarks to XML. The DTD for this XML is:
+     * <p>
+     * <pre>
+     * <?xml version='1.0' encoding='UTF-8'?>
+     * <!ELEMENT Title (#PCDATA|Title)*>
+     * <!ATTLIST Title
+     *    Action CDATA #IMPLIED
+     *    Open CDATA #IMPLIED
+     *    Page CDATA #IMPLIED
+     *    URI CDATA #IMPLIED
+     *    File CDATA #IMPLIED
+     *    Named CDATA #IMPLIED
+     *    NamedN CDATA #IMPLIED
+     *    NewWindow CDATA #IMPLIED
+     *    Style CDATA #IMPLIED
+     *    Color CDATA #IMPLIED
+     * >
+     * <!ELEMENT Bookmark (Title)*>
+     * </pre>
+     * @param list the bookmarks
+     * @param out the export destination. The stream is not closed
+     * @param encoding the encoding according to IANA conventions
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>,
+     * whatever the encoding
+     * @throws IOException on error
+     */    
+    public static void exportToXML(List list, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
+        String jenc = SimpleXMLParser.getJavaEncoding(encoding);
+        Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
+        exportToXML(list, wrt, encoding, onlyASCII);
+    }
+    
+    /**
+     * Exports the bookmarks to XML.
+     * @param list the bookmarks
+     * @param wrt the export destination. The writer is not closed
+     * @param encoding the encoding according to IANA conventions
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>,
+     * whatever the encoding
+     * @throws IOException on error
+     */
+    public static void exportToXML(List list, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
+        wrt.write("<?xml version=\"1.0\" encoding=\"");
+        wrt.write(SimpleXMLParser.escapeXML(encoding, onlyASCII));
+        wrt.write("\"?>\n<Bookmark>\n");
+        exportToXMLNode(list, wrt, 1, onlyASCII);
+        wrt.write("</Bookmark>\n");
+        wrt.flush();
+    }
+    
+    /**
+     * Import the bookmarks from XML.
+     * @param in the XML source. The stream is not closed
+     * @throws IOException on error
+     * @return the bookmarks
+     */    
+    public static List importFromXML(InputStream in) throws IOException {
+        SimpleBookmark book = new SimpleBookmark();
+        SimpleXMLParser.parse(book, in);
+        return book.topList;
+    }
+    
+    /**
+     * Import the bookmarks from XML.
+     * @param in the XML source. The reader is not closed
+     * @throws IOException on error
+     * @return the bookmarks
+     */
+    public static List importFromXML(Reader in) throws IOException {
+        SimpleBookmark book = new SimpleBookmark();
+        SimpleXMLParser.parse(book, in);
+        return book.topList;
+    }
+    
+    public void endDocument() {
+    }
+    
+    public void endElement(String tag) {
+        if (tag.equals("Bookmark")) {
+            if (attr.isEmpty())
+                return;
+            else
+                throw new RuntimeException("Bookmark end tag out of place.");
+        }
+        if (!tag.equals("Title"))
+            throw new RuntimeException("Invalid end tag - " + tag);
+        HashMap attributes = (HashMap)attr.pop();
+        String title = (String)attributes.get("Title");
+        attributes.put("Title",  title.trim());
+        String named = (String)attributes.get("Named");
+        if (named != null)
+            attributes.put("Named", SimpleNamedDestination.unEscapeBinaryString(named));
+        named = (String)attributes.get("NamedN");
+        if (named != null)
+            attributes.put("NamedN", SimpleNamedDestination.unEscapeBinaryString(named));
+        if (attr.isEmpty())
+            topList.add(attributes);
+        else {
+            HashMap parent = (HashMap)attr.peek();
+            List kids = (List)parent.get("Kids");
+            if (kids == null) {
+                kids = new ArrayList();
+                parent.put("Kids", kids);
+            }
+            kids.add(attributes);
+        }
+    }
+    
+    public void startDocument() {
+    }
+    
+    public void startElement(String tag, HashMap h) {
+        if (topList == null) {
+            if (tag.equals("Bookmark")) {
+                topList = new ArrayList();
+                return;
+            }
+            else
+                throw new RuntimeException("Root element is not Bookmark.");
+        }
+        if (!tag.equals("Title"))
+            throw new RuntimeException("Tag " + tag + " not allowed.");
+        HashMap attributes = new HashMap(h);
+        attributes.put("Title", "");
+        attributes.remove("Kids");
+        attr.push(attributes);
+    }
+    
+    public void text(String str) {
+        if (attr.isEmpty())
+            return;
+        HashMap attributes = (HashMap)attr.peek();
+        String title = (String)attributes.get("Title");
+        title += str;
+        attributes.put("Title", title);
+    }    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/SimpleNamedDestination.java b/LibrarySource/com/lowagie/text/pdf/SimpleNamedDestination.java
new file mode 100644
index 0000000..0bbaa38
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SimpleNamedDestination.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class SimpleNamedDestination implements SimpleXMLDocHandler {
+    
+    private HashMap xmlNames;
+    private HashMap xmlLast;
+
+    private SimpleNamedDestination() {
+    }
+    
+    public static HashMap getNamedDestination(PdfReader reader, boolean fromNames) {
+        IntHashtable pages = new IntHashtable();
+        int numPages = reader.getNumberOfPages();
+        for (int k = 1; k <= numPages; ++k)
+            pages.put(reader.getPageOrigRef(k).getNumber(), k);
+        HashMap names = fromNames ? reader.getNamedDestinationFromNames() : reader.getNamedDestinationFromStrings();
+        for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+            Map.Entry entry = (Map.Entry)it.next();
+            ArrayList arr = ((PdfArray)entry.getValue()).getArrayList();
+            StringBuffer s = new StringBuffer();
+            try {
+                s.append(pages.get(((PdfIndirectReference)arr.get(0)).getNumber()));
+                s.append(' ').append(arr.get(1).toString().substring(1));
+                for (int k = 2; k < arr.size(); ++k)
+                    s.append(' ').append(arr.get(k).toString());
+                entry.setValue(s.toString());
+            }
+            catch (Exception e) {
+                it.remove();
+            }
+        }
+        return names;
+    }
+    
+    /**
+     * Exports the bookmarks to XML. The DTD for this XML is:
+     * <p>
+     * <pre>
+     * <?xml version='1.0' encoding='UTF-8'?>
+     * <!ELEMENT Name (#PCDATA)>
+     * <!ATTLIST Name
+     *    Page CDATA #IMPLIED
+     * >
+     * <!ELEMENT Destination (Name)*>
+     * </pre>
+     * @param names the names
+     * @param out the export destination. The stream is not closed
+     * @param encoding the encoding according to IANA conventions
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>,
+     * whatever the encoding
+     * @throws IOException on error
+     */
+    public static void exportToXML(HashMap names, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
+        String jenc = SimpleXMLParser.getJavaEncoding(encoding);
+        Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
+        exportToXML(names, wrt, encoding, onlyASCII);
+    }
+    
+    /**
+     * Exports the bookmarks to XML.
+     * @param names the names
+     * @param wrt the export destination. The writer is not closed
+     * @param encoding the encoding according to IANA conventions
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>,
+     * whatever the encoding
+     * @throws IOException on error
+     */
+    public static void exportToXML(HashMap names, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
+        wrt.write("<?xml version=\"1.0\" encoding=\"");
+        wrt.write(SimpleXMLParser.escapeXML(encoding, onlyASCII));
+        wrt.write("\"?>\n<Destination>\n");
+        for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+            Map.Entry entry = (Map.Entry)it.next();
+            String key = (String)entry.getKey();
+            String value = (String)entry.getValue();
+            wrt.write("  <Name Page=\"");
+            wrt.write(SimpleXMLParser.escapeXML(value, onlyASCII));
+            wrt.write("\">");
+            wrt.write(SimpleXMLParser.escapeXML(escapeBinaryString(key), onlyASCII));
+            wrt.write("</Name>\n");
+        }
+        wrt.write("</Destination>\n");
+        wrt.flush();
+    }
+    
+    /**
+     * Import the names from XML.
+     * @param in the XML source. The stream is not closed
+     * @throws IOException on error
+     * @return the names
+     */
+    public static HashMap importFromXML(InputStream in) throws IOException {
+        SimpleNamedDestination names = new SimpleNamedDestination();
+        SimpleXMLParser.parse(names, in);
+        return names.xmlNames;
+    }
+    
+    /**
+     * Import the names from XML.
+     * @param in the XML source. The reader is not closed
+     * @throws IOException on error
+     * @return the names
+     */
+    public static HashMap importFromXML(Reader in) throws IOException {
+        SimpleNamedDestination names = new SimpleNamedDestination();
+        SimpleXMLParser.parse(names, in);
+        return names.xmlNames;
+    }
+
+    static PdfArray createDestinationArray(String value, PdfWriter writer) throws IOException {
+        PdfArray ar = new PdfArray();
+        StringTokenizer tk = new StringTokenizer(value);
+        int n = Integer.parseInt(tk.nextToken());
+        ar.add(writer.getPageReference(n));
+        if (!tk.hasMoreTokens()) {
+            ar.add(PdfName.XYZ);
+            ar.add(new float[]{0, 10000, 0});
+        }
+        else {
+            String fn = tk.nextToken();
+            if (fn.startsWith("/"))
+                fn = fn.substring(1);
+            ar.add(new PdfName(fn));
+            for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+                fn = tk.nextToken();
+                if (fn.equals("null"))
+                    ar.add(PdfNull.PDFNULL);
+                else
+                    ar.add(new PdfNumber(fn));
+            }
+        }
+        return ar;
+    }
+    
+    public static PdfDictionary outputNamedDestinationAsNames(HashMap names, PdfWriter writer) throws IOException {
+        PdfDictionary dic = new PdfDictionary();
+        for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+            Map.Entry entry = (Map.Entry)it.next();
+            try {
+                String key = (String)entry.getKey();
+                String value = (String)entry.getValue();
+                PdfArray ar = createDestinationArray(value, writer);
+                PdfName kn = new PdfName(key);
+                dic.put(kn, ar);
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }            
+        }
+        return dic;
+    }
+    
+    public static PdfDictionary outputNamedDestinationAsStrings(HashMap names, PdfWriter writer) throws IOException {
+        HashMap n2 = new HashMap(names);
+        for (Iterator it = n2.entrySet().iterator(); it.hasNext();) {
+            Map.Entry entry = (Map.Entry)it.next();
+            try {
+                String value = (String)entry.getValue();
+                PdfArray ar = createDestinationArray(value, writer);
+                entry.setValue(writer.addToBody(ar).getIndirectReference());
+            }
+            catch (Exception e) {
+                it.remove();
+            }
+        }
+        return PdfNameTree.writeTree(n2, writer);
+    }
+    
+    public static String escapeBinaryString(String s) {
+        StringBuffer buf = new StringBuffer();
+        char cc[] = s.toCharArray();
+        int len = cc.length;
+        for (int k = 0; k < len; ++k) {
+            char c = cc[k];
+            if (c < ' ') {
+                buf.append('\\');
+                String octal = "00" + Integer.toOctalString((int)c);
+                buf.append(octal.substring(octal.length() - 3));
+            }
+            else if (c == '\\')
+                buf.append("\\\\");
+            else
+                buf.append(c);
+        }
+        return buf.toString();
+    }
+    
+    public static String unEscapeBinaryString(String s) {
+        StringBuffer buf = new StringBuffer();
+        char cc[] = s.toCharArray();
+        int len = cc.length;
+        for (int k = 0; k < len; ++k) {
+            char c = cc[k];
+            if (c == '\\') {
+                if (++k >= len) {
+                    buf.append('\\');
+                    break;
+                }
+                c = cc[k];
+                if (c >= '0' && c <= '7') {
+                    int n = c - '0';
+                    ++k;
+                    for (int j = 0; j < 2 && k < len; ++j) {
+                        c = cc[k];
+                        if (c >= '0' && c <= '7') {
+                            ++k;
+                            n = n * 8 + c - '0';
+                        }
+                        else {
+                            break;
+                        }
+                    }
+                    --k;
+                    buf.append((char)n);
+                }
+                else
+                    buf.append(c);
+            }
+            else
+                buf.append(c);
+        }
+        return buf.toString();
+    }
+    
+    public void endDocument() {
+    }
+    
+    public void endElement(String tag) {
+        if (tag.equals("Destination")) {
+            if (xmlLast == null && xmlNames != null)
+                return;
+            else
+                throw new RuntimeException("Destination end tag out of place.");
+        }
+        if (!tag.equals("Name"))
+            throw new RuntimeException("Invalid end tag - " + tag);
+        if (xmlLast == null || xmlNames == null)
+            throw new RuntimeException("Name end tag out of place.");
+        if (!xmlLast.containsKey("Page"))
+            throw new RuntimeException("Page attribute missing.");
+        xmlNames.put(unEscapeBinaryString((String)xmlLast.get("Name")), xmlLast.get("Page"));
+        xmlLast = null;
+    }
+    
+    public void startDocument() {
+    }
+    
+    public void startElement(String tag, HashMap h) {
+        if (xmlNames == null) {
+            if (tag.equals("Destination")) {
+                xmlNames = new HashMap();
+                return;
+            }
+            else
+                throw new RuntimeException("Root element is not Destination.");
+        }
+        if (!tag.equals("Name"))
+            throw new RuntimeException("Tag " + tag + " not allowed.");
+        if (xmlLast != null)
+            throw new RuntimeException("Nested tags are not allowed.");
+        xmlLast = new HashMap(h);
+        xmlLast.put("Name", "");
+    }
+    
+    public void text(String str) {
+        if (xmlLast == null)
+            return;
+        String name = (String)xmlLast.get("Name");
+        name += str;
+        xmlLast.put("Name", name);
+    }    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandler.java b/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandler.java
new file mode 100644
index 0000000..9713432
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandler.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.util.HashMap;
+
+/**
+ * The handler for the events fired by <CODE>SimpleXMLParser</CODE>.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface SimpleXMLDocHandler {
+    /**
+     * Called when a start tag is found.
+     * @param tag the tag name
+     * @param h the tag's attributes
+     */    
+    public void startElement(String tag, HashMap h);
+    /**
+     * Called when an end tag is found.
+     * @param tag the tag name
+     */    
+    public void endElement(String tag);
+    /**
+     * Called when the document starts to be parsed.
+     */    
+    public void startDocument();
+    /**
+     * Called after the document is parsed.
+     */    
+    public void endDocument();
+    /**
+     * Called when a text element is found.
+     * @param str the text element, probably a fragment.
+     */    
+    public void text(String str);
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java b/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java
new file mode 100644
index 0000000..c8cc3c2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+/**
+ * The handler for the events fired by <CODE>SimpleXMLParser</CODE>.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public interface SimpleXMLDocHandlerComment {
+    /**
+     * Called when a comment is found.
+     * @param text the comment text
+     */    
+    public void comment(String text);
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/SimpleXMLParser.java b/LibrarySource/com/lowagie/text/pdf/SimpleXMLParser.java
new file mode 100644
index 0000000..7461abb
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SimpleXMLParser.java
@@ -0,0 +1,1177 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.Stack;
+import java.util.HashMap;
+
+/**
+ * A simple XML and HTML parser.  This parser is, like the SAX parser,
+ * an event based parser, but with much less functionality.
+ * <p>
+ * The parser can:
+ * <p>
+ * <ul>
+ * <li>It recognizes the encoding used
+ * <li>It recognizes all the elements' start tags and end tags
+ * <li>It lists attributes, where attribute values can be enclosed in single or double quotes
+ * <li>It recognizes the <code><[CDATA[ ... ]]></code> construct
+ * <li>It recognizes the standard entities: &amp;, &lt;, &gt;, &quot;, and &apos;, as well as numeric entities
+ * <li>It maps lines ending in <code>\r\n</code> and <code>\r</code> to <code>\n</code> on input, in accordance with the XML Specification, Section 2.11
+ * </ul>
+ * <p>
+ * The code is based on <A HREF="http://www.javaworld.com/javaworld/javatips/javatip128/">
+ * http://www.javaworld.com/javaworld/javatips/javatip128/</A> with some extra
+ * code from XERCES to recognize the encoding.
+ */
+public class SimpleXMLParser {
+    private static final HashMap fIANA2JavaMap = new HashMap();
+    private static final HashMap entityMap = new HashMap();
+    
+    private static int popMode(Stack st) {
+        if(!st.empty())
+            return ((Integer)st.pop()).intValue();
+        else
+            return PRE;
+    }
+    
+    private final static int
+    TEXT = 1,
+    ENTITY = 2,
+    OPEN_TAG = 3,
+    CLOSE_TAG = 4,
+    START_TAG = 5,
+    ATTRIBUTE_LVALUE = 6,
+    ATTRIBUTE_EQUAL = 9,
+    ATTRIBUTE_RVALUE = 10,
+    QUOTE = 7,
+    IN_TAG = 8,
+    SINGLE_TAG = 12,
+    COMMENT = 13,
+    DONE = 11,
+    DOCTYPE = 14,
+    PRE = 15,
+    CDATA = 16;
+    
+    private SimpleXMLParser() {
+    }
+    
+    /**
+     * Parses the XML document firing the events to the handler.
+     * @param doc the document handler
+     * @param in the document. The encoding is deduced from the stream. The stream is not closed
+     * @throws IOException on error
+     */    
+    public static void parse(SimpleXMLDocHandler doc, InputStream in) throws IOException {
+        byte b4[] = new byte[4];
+        int count = in.read(b4);
+        if (count != 4)
+            throw new IOException("Insufficient length.");
+        String encoding = getEncodingName(b4);
+        String decl = null;
+        if (encoding.equals("UTF-8")) {
+            StringBuffer sb = new StringBuffer();
+            int c;
+            while ((c = in.read()) != -1) {
+                if (c == '>')
+                    break;
+                sb.append((char)c);
+            }
+            decl = sb.toString();
+        }
+        else if (encoding.equals("CP037")) {
+            ByteArrayOutputStream bi = new ByteArrayOutputStream();
+            int c;
+            while ((c = in.read()) != -1) {
+                if (c == 0x6e) // that's '>' in ebcdic
+                    break;
+                bi.write(c);
+            }
+            decl = new String(bi.toByteArray(), "CP037");
+        }
+        if (decl != null) {
+            decl = getDeclaredEncoding(decl);
+            if (decl != null)
+                encoding = decl;
+        }
+        parse(doc, new InputStreamReader(in, getJavaEncoding(encoding)));
+    }
+    
+    private static String getDeclaredEncoding(String decl) {
+        if (decl == null)
+            return null;
+        int idx = decl.indexOf("encoding");
+        if (idx < 0)
+            return null;
+        int idx1 = decl.indexOf('"', idx);
+        int idx2 = decl.indexOf('\'', idx);
+        if (idx1 == idx2)
+            return null;
+        if ((idx1 < 0 && idx2 > 0) || (idx2 > 0 && idx2 < idx1)) {
+            int idx3 = decl.indexOf('\'', idx2 + 1);
+            if (idx3 < 0)
+                return null;
+            return decl.substring(idx2 + 1, idx3);
+        }
+        if ((idx2 < 0 && idx1 > 0) || (idx1 > 0 && idx1 < idx2)) {
+            int idx3 = decl.indexOf('"', idx1 + 1);
+            if (idx3 < 0)
+                return null;
+            return decl.substring(idx1 + 1, idx3);
+        }
+        return null;
+    }
+    
+    /**
+     * Gets the java encoding from the IANA encoding. If the encoding cannot be found
+     * it returns the input.
+     * @param iana the IANA encoding
+     * @return the java encoding
+     */    
+    public static String getJavaEncoding(String iana) {
+        String IANA = iana.toUpperCase();
+        String jdec = (String)fIANA2JavaMap.get(IANA);
+        if (jdec == null)
+            jdec = iana;
+        return jdec;
+    }
+    
+    public static void parse(SimpleXMLDocHandler doc,Reader r) throws IOException {
+        parse(doc, null, r, false);
+    }
+    
+    /**
+     * Parses the XML document firing the events to the handler.
+     * @param doc the document handler
+     * @param r the document. The encoding is already resolved. The reader is not closed
+     * @throws IOException on error
+     */
+    public static void parse(SimpleXMLDocHandler doc, SimpleXMLDocHandlerComment comment, Reader r, boolean html) throws IOException {
+        BufferedReader reader;
+        if (r instanceof BufferedReader)
+            reader = (BufferedReader)r;
+        else
+            reader = new BufferedReader(r);
+        Stack st = new Stack();
+        int depth = 0;
+        int mode = PRE;
+        int c = 0;
+        int quotec = '"';
+        depth = 0;
+        StringBuffer sb = new StringBuffer();
+        StringBuffer etag = new StringBuffer();
+        String tagName = null;
+        String lvalue = null;
+        String rvalue = null;
+        HashMap attrs = null;
+        st = new Stack();
+        doc.startDocument();
+        int line=1, col=0;
+        boolean eol = false;
+        if (html)
+            mode = TEXT;
+        int pushBack = -1;
+        while(true) {
+            if (pushBack != -1) {
+                c = pushBack;
+                pushBack = -1;
+            }
+            else
+                c = reader.read();
+            if (c == -1)
+                break;
+            
+            // We need to map \r, \r\n, and \n to \n
+            // See XML spec section 2.11
+            if(c == '\n' && eol) {
+                eol = false;
+                continue;
+            } else if(eol) {
+                eol = false;
+            } else if(c == '\n') {
+                line++;
+                col=0;
+            } else if(c == '\r') {
+                eol = true;
+                c = '\n';
+                line++;
+                col=0;
+            } else {
+                col++;
+            }
+            
+            if(mode == DONE) {
+                doc.endDocument();
+                return;
+                
+                // We are between tags collecting text.
+            } else if(mode == TEXT) {
+                if(c == '<') {
+                    st.push(new Integer(mode));
+                    mode = START_TAG;
+                    if(sb.length() > 0) {
+                        doc.text(sb.toString());
+                        sb.setLength(0);
+                    }
+                } else if(c == '&') {
+                    st.push(new Integer(mode));
+                    mode = ENTITY;
+                    etag.setLength(0);
+                } else
+                    sb.append((char)c);
+                
+                // we are processing a closing tag: e.g. </foo>
+            } else if(mode == CLOSE_TAG) {
+                if(c == '>') {
+                    mode = popMode(st);
+                    tagName = sb.toString();
+                    if (html)
+                        tagName = tagName.toLowerCase();
+                    sb.setLength(0);
+                    depth--;
+                    if(!html && depth==0)
+                        mode = DONE;
+                   doc.endElement(tagName);
+                } else {
+                    if (!Character.isWhitespace((char)c))
+                        sb.append((char)c);
+                }
+                
+                // we are processing CDATA
+            } else if(mode == CDATA) {
+                if(c == '>'
+                && sb.toString().endsWith("]]")) {
+                    sb.setLength(sb.length()-2);
+                    doc.text(sb.toString());
+                    sb.setLength(0);
+                    mode = popMode(st);
+                } else
+                    sb.append((char)c);
+                
+                // we are processing a comment.  We are inside
+                // the <!-- .... --> looking for the -->.
+            } else if(mode == COMMENT) {
+                if(c == '>'
+                && sb.toString().endsWith("--")) {
+                    if (comment != null) {
+                        sb.setLength(sb.length() - 2);
+                        comment.comment(sb.toString());
+                    }
+                    sb.setLength(0);
+                    mode = popMode(st);
+                } else
+                    sb.append((char)c);
+                
+                // We are outside the root tag element
+            } else if(mode == PRE) {
+                if(c == '<') {
+                    mode = TEXT;
+                    st.push(new Integer(mode));
+                    mode = START_TAG;
+                }
+                
+                // We are inside one of these <? ... ?>
+                // or one of these <!DOCTYPE ... >
+            } else if(mode == DOCTYPE) {
+                if(c == '>') {
+                    mode = popMode(st);
+                    if(mode == TEXT) mode = PRE;
+                }
+                
+                // we have just seen a < and
+                // are wondering what we are looking at
+                // <foo>, </foo>, <!-- ... --->, etc.
+            } else if(mode == START_TAG) {
+                mode = popMode(st);
+                if(c == '/') {
+                    st.push(new Integer(mode));
+                    mode = CLOSE_TAG;
+                } else if (c == '?') {
+                    mode = DOCTYPE;
+                } else {
+                    st.push(new Integer(mode));
+                    mode = OPEN_TAG;
+                    tagName = null;
+                    attrs = new HashMap();
+                    sb.append((char)c);
+                }
+                
+                // we are processing an entity, e.g. <, », etc.
+            } else if(mode == ENTITY) {
+                if(c == ';') {
+                    mode = popMode(st);
+                    String cent = etag.toString();
+                    etag.setLength(0);
+                    if(cent.startsWith("#x")) {
+                        try {
+                            char ci = (char)Integer.parseInt(cent.substring(2),16);
+                            sb.append(ci);
+                        }
+                        catch (Exception es) {
+                            sb.append('&').append(cent).append(';');
+                        }
+                    }
+                    else if(cent.startsWith("#")) {
+                        try {
+                            char ci = (char)Integer.parseInt(cent.substring(1));
+                            sb.append(ci);
+                        }
+                        catch (Exception es) {
+                            sb.append('&').append(cent).append(';');
+                        }
+                    }
+                    else {
+                        char ce = decodeEntity(cent);
+                        if (ce == '\0')
+                            sb.append('&').append(cent).append(';');
+                        else
+                        sb.append(ce);
+                    }
+                } else if ((c != '#' && (c < '0' || c > '9') && (c < 'a' || c > 'z')
+                    && (c < 'A' || c > 'Z')) || etag.length() >= 7) {
+                    mode = popMode(st);
+                    pushBack = c;
+                    sb.append('&').append(etag.toString());
+                    etag.setLength(0);
+                }
+                else {
+                    etag.append((char)c);
+                }
+                
+                // we have just seen something like this:
+                // <foo a="b"/
+                // and are looking for the final >.
+            } else if(mode == SINGLE_TAG) {
+                if(tagName == null)
+                    tagName = sb.toString();
+                if (html)
+                    tagName = tagName.toLowerCase();
+                if(c != '>')
+                    exc("Expected > for tag: <"+tagName+"/>",line,col);
+                doc.startElement(tagName,attrs);
+                doc.endElement(tagName);
+                if(!html && depth==0) {
+                    doc.endDocument();
+                    return;
+                }
+                sb.setLength(0);
+                attrs = new HashMap();
+                tagName = null;
+                mode = popMode(st);
+                
+                // we are processing something
+                // like this <foo ... >.  It could
+                // still be a <!-- ... --> or something.
+            } else if(mode == OPEN_TAG) {
+                if(c == '>') {
+                    if(tagName == null)
+                        tagName = sb.toString();
+                    if (html)
+                        tagName = tagName.toLowerCase();
+                    sb.setLength(0);
+                    depth++;
+                    doc.startElement(tagName,attrs);
+                    tagName = null;
+                    attrs = new HashMap();
+                    mode = popMode(st);
+                } else if(c == '/') {
+                    mode = SINGLE_TAG;
+                } else if(c == '-' && sb.toString().equals("!-")) {
+                    mode = COMMENT;
+                    sb.setLength(0);
+                } else if(c == '[' && sb.toString().equals("![CDATA")) {
+                    mode = CDATA;
+                    sb.setLength(0);
+                } else if(c == 'E' && sb.toString().equals("!DOCTYP")) {
+                    sb.setLength(0);
+                    mode = DOCTYPE;
+                } else if(Character.isWhitespace((char)c)) {
+                    tagName = sb.toString();
+                    if (html)
+                        tagName = tagName.toLowerCase();
+                    sb.setLength(0);
+                    mode = IN_TAG;
+                } else {
+                    sb.append((char)c);
+                }
+                
+                // We are processing the quoted right-hand side
+                // of an element's attribute.
+            } else if(mode == QUOTE) {
+                if (html && quotec == ' ' && c == '>') {
+                    rvalue = sb.toString();
+                    sb.setLength(0);
+                    attrs.put(lvalue,rvalue);
+                    mode = popMode(st);
+                    doc.startElement(tagName,attrs);
+                    depth++;
+                    tagName = null;
+                    attrs = new HashMap();
+                }
+                else if (html && quotec == ' ' && Character.isWhitespace((char)c)) {
+                    rvalue = sb.toString();
+                    sb.setLength(0);
+                    attrs.put(lvalue,rvalue);
+                    mode = IN_TAG;
+                }
+                else if (html && quotec == ' ') {
+                    sb.append((char)c);
+                }
+                else if(c == quotec) {
+                    rvalue = sb.toString();
+                    sb.setLength(0);
+                    attrs.put(lvalue,rvalue);
+                    mode = IN_TAG;
+                    // See section the XML spec, section 3.3.3
+                    // on normalization processing.
+                } else if(" \r\n\u0009".indexOf(c)>=0) {
+                    sb.append(' ');
+                } else if(c == '&') {
+                    st.push(new Integer(mode));
+                    mode = ENTITY;
+                    etag.setLength(0);
+                } else {
+                    sb.append((char)c);
+                }
+                
+            } else if(mode == ATTRIBUTE_RVALUE) {
+                if(c == '"' || c == '\'') {
+                    quotec = c;
+                    mode = QUOTE;
+                } else if(Character.isWhitespace((char)c)) {
+                    ;
+                } else if (html && c == '>') {
+                    attrs.put(lvalue,sb.toString());
+                    sb.setLength(0);
+                    mode = popMode(st);
+                    doc.startElement(tagName,attrs);
+                    depth++;
+                    tagName = null;
+                    attrs = new HashMap();
+                } else if (html) {
+                    sb.append((char)c);
+                    quotec = ' ';
+                    mode = QUOTE;
+                } else {
+                    exc("Error in attribute processing",line,col);
+                }
+                
+            } else if(mode == ATTRIBUTE_LVALUE) {
+                if(Character.isWhitespace((char)c)) {
+                    lvalue = sb.toString();
+                    if (html)
+                        lvalue = lvalue.toLowerCase();
+                    sb.setLength(0);
+                    mode = ATTRIBUTE_EQUAL;
+                } else if(c == '=') {
+                    lvalue = sb.toString();
+                    if (html)
+                        lvalue = lvalue.toLowerCase();
+                    sb.setLength(0);
+                    mode = ATTRIBUTE_RVALUE;
+                } else if (html && c == '>') {
+                    sb.setLength(0);
+                    mode = popMode(st);
+                    doc.startElement(tagName,attrs);
+                    depth++;
+                    tagName = null;
+                    attrs = new HashMap();
+                } else {
+                    sb.append((char)c);
+                }
+                
+            } else if(mode == ATTRIBUTE_EQUAL) {
+                if(c == '=') {
+                    mode = ATTRIBUTE_RVALUE;
+                } else if(Character.isWhitespace((char)c)) {
+                    ;
+                } else if (html && c == '>') {
+                    sb.setLength(0);
+                    mode = popMode(st);
+                    doc.startElement(tagName,attrs);
+                    depth++;
+                    tagName = null;
+                    attrs = new HashMap();
+                } else if (html && c == '/') {
+                    sb.setLength(0);
+                    mode = SINGLE_TAG;
+                } else if (html) {
+                    sb.setLength(0);
+                    sb.append((char)c);
+                    mode = ATTRIBUTE_LVALUE;
+                } else {
+                    exc("Error in attribute processing.",line,col);
+                }
+                
+            } else if(mode == IN_TAG) {
+                if(c == '>') {
+                    mode = popMode(st);
+                    doc.startElement(tagName,attrs);
+                    depth++;
+                    tagName = null;
+                    attrs = new HashMap();
+                } else if(c == '/') {
+                    mode = SINGLE_TAG;
+                } else if(Character.isWhitespace((char)c)) {
+                    ;
+                } else {
+                    mode = ATTRIBUTE_LVALUE;
+                    sb.append((char)c);
+                }
+            }
+        }
+        if(html || mode == DONE) {
+            if (html && mode == TEXT)
+                doc.text(sb.toString());
+            doc.endDocument();
+        }
+        else
+            exc("missing end tag",line,col);
+    }
+    private static void exc(String s,int line,int col) throws IOException {
+        throw new IOException(s+" near line "+line+", column "+col);
+    }
+    
+    /**
+     * Escapes a string with the appropriated XML codes.
+     * @param s the string to be escaped
+     * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>
+     * @return the escaped string
+     */    
+    public static String escapeXML(String s, boolean onlyASCII) {
+        char cc[] = s.toCharArray();
+        int len = cc.length;
+        StringBuffer sb = new StringBuffer();
+        for (int k = 0; k < len; ++k) {
+            int c = cc[k];
+            switch (c) {
+                case '<':
+                    sb.append("<");
+                    break;
+                case '>':
+                    sb.append(">");
+                    break;
+                case '&':
+                    sb.append("&");
+                    break;
+                case '"':
+                    sb.append(""");
+                    break;
+                case '\'':
+                    sb.append("'");
+                    break;
+                default:
+                    if (onlyASCII && c > 127)
+                        sb.append("&#").append(c).append(";");
+                    else
+                        sb.append((char)c);
+            }
+        }
+        return sb.toString();
+    }
+    
+    public static char decodeEntity(String s) {
+        Character c = (Character)entityMap.get(s);
+        if (c == null)
+            return '\0';
+        else
+            return c.charValue();
+    }
+    
+    private static String getEncodingName(byte[] b4) {
+        
+        // UTF-16, with BOM
+        int b0 = b4[0] & 0xFF;
+        int b1 = b4[1] & 0xFF;
+        if (b0 == 0xFE && b1 == 0xFF) {
+            // UTF-16, big-endian
+            return "UTF-16BE";
+        }
+        if (b0 == 0xFF && b1 == 0xFE) {
+            // UTF-16, little-endian
+            return "UTF-16LE";
+        }
+        
+        // UTF-8 with a BOM
+        int b2 = b4[2] & 0xFF;
+        if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
+            return "UTF-8";
+        }
+        
+        // other encodings
+        int b3 = b4[3] & 0xFF;
+        if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
+            // UCS-4, big endian (1234)
+            return "ISO-10646-UCS-4";
+        }
+        if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
+            // UCS-4, little endian (4321)
+            return "ISO-10646-UCS-4";
+        }
+        if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
+            // UCS-4, unusual octet order (2143)
+            // REVISIT: What should this be?
+            return "ISO-10646-UCS-4";
+        }
+        if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
+            // UCS-4, unusual octect order (3412)
+            // REVISIT: What should this be?
+            return "ISO-10646-UCS-4";
+        }
+        if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
+            // UTF-16, big-endian, no BOM
+            // (or could turn out to be UCS-2...
+            // REVISIT: What should this be?
+            return "UTF-16BE";
+        }
+        if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
+            // UTF-16, little-endian, no BOM
+            // (or could turn out to be UCS-2...
+            return "UTF-16LE";
+        }
+        if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
+            // EBCDIC
+            // a la xerces1, return CP037 instead of EBCDIC here
+            return "CP037";
+        }
+        
+        // default encoding
+        return "UTF-8";
+    }
+
+    static {        
+        // add IANA to Java encoding mappings.
+        fIANA2JavaMap.put("BIG5", "Big5");
+        fIANA2JavaMap.put("CSBIG5", "Big5");
+        fIANA2JavaMap.put("CP037", "CP037");
+        fIANA2JavaMap.put("IBM037", "CP037");
+        fIANA2JavaMap.put("CSIBM037", "CP037");
+        fIANA2JavaMap.put("EBCDIC-CP-US", "CP037");
+        fIANA2JavaMap.put("EBCDIC-CP-CA", "CP037");
+        fIANA2JavaMap.put("EBCDIC-CP-NL", "CP037");
+        fIANA2JavaMap.put("EBCDIC-CP-WT", "CP037");
+        fIANA2JavaMap.put("IBM277", "CP277");
+        fIANA2JavaMap.put("CP277", "CP277");
+        fIANA2JavaMap.put("CSIBM277", "CP277");
+        fIANA2JavaMap.put("EBCDIC-CP-DK", "CP277");
+        fIANA2JavaMap.put("EBCDIC-CP-NO", "CP277");
+        fIANA2JavaMap.put("IBM278", "CP278");
+        fIANA2JavaMap.put("CP278", "CP278");
+        fIANA2JavaMap.put("CSIBM278", "CP278");
+        fIANA2JavaMap.put("EBCDIC-CP-FI", "CP278");
+        fIANA2JavaMap.put("EBCDIC-CP-SE", "CP278");
+        fIANA2JavaMap.put("IBM280", "CP280");
+        fIANA2JavaMap.put("CP280", "CP280");
+        fIANA2JavaMap.put("CSIBM280", "CP280");
+        fIANA2JavaMap.put("EBCDIC-CP-IT", "CP280");
+        fIANA2JavaMap.put("IBM284", "CP284");
+        fIANA2JavaMap.put("CP284", "CP284");
+        fIANA2JavaMap.put("CSIBM284", "CP284");
+        fIANA2JavaMap.put("EBCDIC-CP-ES", "CP284");
+        fIANA2JavaMap.put("EBCDIC-CP-GB", "CP285");
+        fIANA2JavaMap.put("IBM285", "CP285");
+        fIANA2JavaMap.put("CP285", "CP285");
+        fIANA2JavaMap.put("CSIBM285", "CP285");
+        fIANA2JavaMap.put("EBCDIC-CP-FR", "CP297");
+        fIANA2JavaMap.put("IBM297", "CP297");
+        fIANA2JavaMap.put("CP297", "CP297");
+        fIANA2JavaMap.put("CSIBM297", "CP297");
+        fIANA2JavaMap.put("EBCDIC-CP-AR1", "CP420");
+        fIANA2JavaMap.put("IBM420", "CP420");
+        fIANA2JavaMap.put("CP420", "CP420");
+        fIANA2JavaMap.put("CSIBM420", "CP420");
+        fIANA2JavaMap.put("EBCDIC-CP-HE", "CP424");
+        fIANA2JavaMap.put("IBM424", "CP424");
+        fIANA2JavaMap.put("CP424", "CP424");
+        fIANA2JavaMap.put("CSIBM424", "CP424");
+        fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
+        fIANA2JavaMap.put("IBM500", "CP500");
+        fIANA2JavaMap.put("CP500", "CP500");
+        fIANA2JavaMap.put("CSIBM500", "CP500");
+        fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
+        fIANA2JavaMap.put("EBCDIC-CP-BE", "CP500");
+        fIANA2JavaMap.put("IBM868", "CP868");
+        fIANA2JavaMap.put("CP868", "CP868");
+        fIANA2JavaMap.put("CSIBM868", "CP868");
+        fIANA2JavaMap.put("CP-AR", "CP868");
+        fIANA2JavaMap.put("IBM869", "CP869");
+        fIANA2JavaMap.put("CP869", "CP869");
+        fIANA2JavaMap.put("CSIBM869", "CP869");
+        fIANA2JavaMap.put("CP-GR", "CP869");
+        fIANA2JavaMap.put("IBM870", "CP870");
+        fIANA2JavaMap.put("CP870", "CP870");
+        fIANA2JavaMap.put("CSIBM870", "CP870");
+        fIANA2JavaMap.put("EBCDIC-CP-ROECE", "CP870");
+        fIANA2JavaMap.put("EBCDIC-CP-YU", "CP870");
+        fIANA2JavaMap.put("IBM871", "CP871");
+        fIANA2JavaMap.put("CP871", "CP871");
+        fIANA2JavaMap.put("CSIBM871", "CP871");
+        fIANA2JavaMap.put("EBCDIC-CP-IS", "CP871");
+        fIANA2JavaMap.put("IBM918", "CP918");
+        fIANA2JavaMap.put("CP918", "CP918");
+        fIANA2JavaMap.put("CSIBM918", "CP918");
+        fIANA2JavaMap.put("EBCDIC-CP-AR2", "CP918");
+        fIANA2JavaMap.put("EUC-JP", "EUCJIS");
+        fIANA2JavaMap.put("CSEUCPkdFmtJapanese", "EUCJIS");
+        fIANA2JavaMap.put("EUC-KR", "KSC5601");
+        fIANA2JavaMap.put("GB2312", "GB2312");
+        fIANA2JavaMap.put("CSGB2312", "GB2312");
+        fIANA2JavaMap.put("ISO-2022-JP", "JIS");
+        fIANA2JavaMap.put("CSISO2022JP", "JIS");
+        fIANA2JavaMap.put("ISO-2022-KR", "ISO2022KR");
+        fIANA2JavaMap.put("CSISO2022KR", "ISO2022KR");
+        fIANA2JavaMap.put("ISO-2022-CN", "ISO2022CN");
+        
+        fIANA2JavaMap.put("X0201", "JIS0201");
+        fIANA2JavaMap.put("CSISO13JISC6220JP", "JIS0201");
+        fIANA2JavaMap.put("X0208", "JIS0208");
+        fIANA2JavaMap.put("ISO-IR-87", "JIS0208");
+        fIANA2JavaMap.put("X0208dbiJIS_X0208-1983", "JIS0208");
+        fIANA2JavaMap.put("CSISO87JISX0208", "JIS0208");
+        fIANA2JavaMap.put("X0212", "JIS0212");
+        fIANA2JavaMap.put("ISO-IR-159", "JIS0212");
+        fIANA2JavaMap.put("CSISO159JISX02121990", "JIS0212");
+        fIANA2JavaMap.put("SHIFT_JIS", "SJIS");
+        fIANA2JavaMap.put("CSSHIFT_JIS", "SJIS");
+        fIANA2JavaMap.put("MS_Kanji", "SJIS");
+        
+        // Add support for Cp1252 and its friends
+        fIANA2JavaMap.put("WINDOWS-1250", "Cp1250");
+        fIANA2JavaMap.put("WINDOWS-1251", "Cp1251");
+        fIANA2JavaMap.put("WINDOWS-1252", "Cp1252");
+        fIANA2JavaMap.put("WINDOWS-1253", "Cp1253");
+        fIANA2JavaMap.put("WINDOWS-1254", "Cp1254");
+        fIANA2JavaMap.put("WINDOWS-1255", "Cp1255");
+        fIANA2JavaMap.put("WINDOWS-1256", "Cp1256");
+        fIANA2JavaMap.put("WINDOWS-1257", "Cp1257");
+        fIANA2JavaMap.put("WINDOWS-1258", "Cp1258");
+        fIANA2JavaMap.put("TIS-620", "TIS620");
+        
+        fIANA2JavaMap.put("ISO-8859-1", "ISO8859_1");
+        fIANA2JavaMap.put("ISO-IR-100", "ISO8859_1");
+        fIANA2JavaMap.put("ISO_8859-1", "ISO8859_1");
+        fIANA2JavaMap.put("LATIN1", "ISO8859_1");
+        fIANA2JavaMap.put("CSISOLATIN1", "ISO8859_1");
+        fIANA2JavaMap.put("L1", "ISO8859_1");
+        fIANA2JavaMap.put("IBM819", "ISO8859_1");
+        fIANA2JavaMap.put("CP819", "ISO8859_1");
+        
+        fIANA2JavaMap.put("ISO-8859-2", "ISO8859_2");
+        fIANA2JavaMap.put("ISO-IR-101", "ISO8859_2");
+        fIANA2JavaMap.put("ISO_8859-2", "ISO8859_2");
+        fIANA2JavaMap.put("LATIN2", "ISO8859_2");
+        fIANA2JavaMap.put("CSISOLATIN2", "ISO8859_2");
+        fIANA2JavaMap.put("L2", "ISO8859_2");
+        
+        fIANA2JavaMap.put("ISO-8859-3", "ISO8859_3");
+        fIANA2JavaMap.put("ISO-IR-109", "ISO8859_3");
+        fIANA2JavaMap.put("ISO_8859-3", "ISO8859_3");
+        fIANA2JavaMap.put("LATIN3", "ISO8859_3");
+        fIANA2JavaMap.put("CSISOLATIN3", "ISO8859_3");
+        fIANA2JavaMap.put("L3", "ISO8859_3");
+        
+        fIANA2JavaMap.put("ISO-8859-4", "ISO8859_4");
+        fIANA2JavaMap.put("ISO-IR-110", "ISO8859_4");
+        fIANA2JavaMap.put("ISO_8859-4", "ISO8859_4");
+        fIANA2JavaMap.put("LATIN4", "ISO8859_4");
+        fIANA2JavaMap.put("CSISOLATIN4", "ISO8859_4");
+        fIANA2JavaMap.put("L4", "ISO8859_4");
+        
+        fIANA2JavaMap.put("ISO-8859-5", "ISO8859_5");
+        fIANA2JavaMap.put("ISO-IR-144", "ISO8859_5");
+        fIANA2JavaMap.put("ISO_8859-5", "ISO8859_5");
+        fIANA2JavaMap.put("CYRILLIC", "ISO8859_5");
+        fIANA2JavaMap.put("CSISOLATINCYRILLIC", "ISO8859_5");
+        
+        fIANA2JavaMap.put("ISO-8859-6", "ISO8859_6");
+        fIANA2JavaMap.put("ISO-IR-127", "ISO8859_6");
+        fIANA2JavaMap.put("ISO_8859-6", "ISO8859_6");
+        fIANA2JavaMap.put("ECMA-114", "ISO8859_6");
+        fIANA2JavaMap.put("ASMO-708", "ISO8859_6");
+        fIANA2JavaMap.put("ARABIC", "ISO8859_6");
+        fIANA2JavaMap.put("CSISOLATINARABIC", "ISO8859_6");
+        
+        fIANA2JavaMap.put("ISO-8859-7", "ISO8859_7");
+        fIANA2JavaMap.put("ISO-IR-126", "ISO8859_7");
+        fIANA2JavaMap.put("ISO_8859-7", "ISO8859_7");
+        fIANA2JavaMap.put("ELOT_928", "ISO8859_7");
+        fIANA2JavaMap.put("ECMA-118", "ISO8859_7");
+        fIANA2JavaMap.put("GREEK", "ISO8859_7");
+        fIANA2JavaMap.put("CSISOLATINGREEK", "ISO8859_7");
+        fIANA2JavaMap.put("GREEK8", "ISO8859_7");
+        
+        fIANA2JavaMap.put("ISO-8859-8", "ISO8859_8");
+        fIANA2JavaMap.put("ISO-8859-8-I", "ISO8859_8"); // added since this encoding only differs w.r.t. presentation
+        fIANA2JavaMap.put("ISO-IR-138", "ISO8859_8");
+        fIANA2JavaMap.put("ISO_8859-8", "ISO8859_8");
+        fIANA2JavaMap.put("HEBREW", "ISO8859_8");
+        fIANA2JavaMap.put("CSISOLATINHEBREW", "ISO8859_8");
+        
+        fIANA2JavaMap.put("ISO-8859-9", "ISO8859_9");
+        fIANA2JavaMap.put("ISO-IR-148", "ISO8859_9");
+        fIANA2JavaMap.put("ISO_8859-9", "ISO8859_9");
+        fIANA2JavaMap.put("LATIN5", "ISO8859_9");
+        fIANA2JavaMap.put("CSISOLATIN5", "ISO8859_9");
+        fIANA2JavaMap.put("L5", "ISO8859_9");
+        
+        fIANA2JavaMap.put("KOI8-R", "KOI8_R");
+        fIANA2JavaMap.put("CSKOI8-R", "KOI8_R");
+        fIANA2JavaMap.put("US-ASCII", "ASCII");
+        fIANA2JavaMap.put("ISO-IR-6", "ASCII");
+        fIANA2JavaMap.put("ANSI_X3.4-1986", "ASCII");
+        fIANA2JavaMap.put("ISO_646.IRV:1991", "ASCII");
+        fIANA2JavaMap.put("ASCII", "ASCII");
+        fIANA2JavaMap.put("CSASCII", "ASCII");
+        fIANA2JavaMap.put("ISO646-US", "ASCII");
+        fIANA2JavaMap.put("US", "ASCII");
+        fIANA2JavaMap.put("IBM367", "ASCII");
+        fIANA2JavaMap.put("CP367", "ASCII");
+        fIANA2JavaMap.put("UTF-8", "UTF8");
+        fIANA2JavaMap.put("UTF-16", "Unicode");
+        fIANA2JavaMap.put("UTF-16BE", "UnicodeBig");
+        fIANA2JavaMap.put("UTF-16LE", "UnicodeLittle");
+
+        entityMap.put("nbsp", new Character('\u00a0')); // no-break space = non-breaking space, U+00A0 ISOnum
+        entityMap.put("iexcl", new Character('\u00a1')); // inverted exclamation mark, U+00A1 ISOnum
+        entityMap.put("cent", new Character('\u00a2')); // cent sign, U+00A2 ISOnum
+        entityMap.put("pound", new Character('\u00a3')); // pound sign, U+00A3 ISOnum
+        entityMap.put("curren", new Character('\u00a4')); // currency sign, U+00A4 ISOnum
+        entityMap.put("yen", new Character('\u00a5')); // yen sign = yuan sign, U+00A5 ISOnum
+        entityMap.put("brvbar", new Character('\u00a6')); // broken bar = broken vertical bar, U+00A6 ISOnum
+        entityMap.put("sect", new Character('\u00a7')); // section sign, U+00A7 ISOnum
+        entityMap.put("uml", new Character('\u00a8')); // diaeresis = spacing diaeresis, U+00A8 ISOdia
+        entityMap.put("copy", new Character('\u00a9')); // copyright sign, U+00A9 ISOnum
+        entityMap.put("ordf", new Character('\u00aa')); // feminine ordinal indicator, U+00AA ISOnum
+        entityMap.put("laquo", new Character('\u00ab')); // left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum
+        entityMap.put("not", new Character('\u00ac')); // not sign, U+00AC ISOnum
+        entityMap.put("shy", new Character('\u00ad')); // soft hyphen = discretionary hyphen, U+00AD ISOnum
+        entityMap.put("reg", new Character('\u00ae')); // registered sign = registered trade mark sign, U+00AE ISOnum
+        entityMap.put("macr", new Character('\u00af')); // macron = spacing macron = overline = APL overbar, U+00AF ISOdia
+        entityMap.put("deg", new Character('\u00b0')); // degree sign, U+00B0 ISOnum
+        entityMap.put("plusmn", new Character('\u00b1')); // plus-minus sign = plus-or-minus sign, U+00B1 ISOnum
+        entityMap.put("sup2", new Character('\u00b2')); // superscript two = superscript digit two = squared, U+00B2 ISOnum
+        entityMap.put("sup3", new Character('\u00b3')); // superscript three = superscript digit three = cubed, U+00B3 ISOnum
+        entityMap.put("acute", new Character('\u00b4')); // acute accent = spacing acute, U+00B4 ISOdia
+        entityMap.put("micro", new Character('\u00b5')); // micro sign, U+00B5 ISOnum
+        entityMap.put("para", new Character('\u00b6')); // pilcrow sign = paragraph sign, U+00B6 ISOnum
+        entityMap.put("middot", new Character('\u00b7')); // middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum
+        entityMap.put("cedil", new Character('\u00b8')); // cedilla = spacing cedilla, U+00B8 ISOdia
+        entityMap.put("sup1", new Character('\u00b9')); // superscript one = superscript digit one, U+00B9 ISOnum
+        entityMap.put("ordm", new Character('\u00ba')); // masculine ordinal indicator, U+00BA ISOnum
+        entityMap.put("raquo", new Character('\u00bb')); // right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum
+        entityMap.put("frac14", new Character('\u00bc')); // vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum
+        entityMap.put("frac12", new Character('\u00bd')); // vulgar fraction one half = fraction one half, U+00BD ISOnum
+        entityMap.put("frac34", new Character('\u00be')); // vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum
+        entityMap.put("iquest", new Character('\u00bf')); // inverted question mark = turned question mark, U+00BF ISOnum
+        entityMap.put("Agrave", new Character('\u00c0')); // latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1
+        entityMap.put("Aacute", new Character('\u00c1')); // latin capital letter A with acute, U+00C1 ISOlat1
+        entityMap.put("Acirc", new Character('\u00c2')); // latin capital letter A with circumflex, U+00C2 ISOlat1
+        entityMap.put("Atilde", new Character('\u00c3')); // latin capital letter A with tilde, U+00C3 ISOlat1
+        entityMap.put("Auml", new Character('\u00c4')); // latin capital letter A with diaeresis, U+00C4 ISOlat1
+        entityMap.put("Aring", new Character('\u00c5')); // latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1
+        entityMap.put("AElig", new Character('\u00c6')); // latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
+        entityMap.put("Ccedil", new Character('\u00c7')); // latin capital letter C with cedilla, U+00C7 ISOlat1
+        entityMap.put("Egrave", new Character('\u00c8')); // latin capital letter E with grave, U+00C8 ISOlat1
+        entityMap.put("Eacute", new Character('\u00c9')); // latin capital letter E with acute, U+00C9 ISOlat1
+        entityMap.put("Ecirc", new Character('\u00ca')); // latin capital letter E with circumflex, U+00CA ISOlat1
+        entityMap.put("Euml", new Character('\u00cb')); // latin capital letter E with diaeresis, U+00CB ISOlat1
+        entityMap.put("Igrave", new Character('\u00cc')); // latin capital letter I with grave, U+00CC ISOlat1
+        entityMap.put("Iacute", new Character('\u00cd')); // latin capital letter I with acute, U+00CD ISOlat1
+        entityMap.put("Icirc", new Character('\u00ce')); // latin capital letter I with circumflex, U+00CE ISOlat1
+        entityMap.put("Iuml", new Character('\u00cf')); // latin capital letter I with diaeresis, U+00CF ISOlat1
+        entityMap.put("ETH", new Character('\u00d0')); // latin capital letter ETH, U+00D0 ISOlat1
+        entityMap.put("Ntilde", new Character('\u00d1')); // latin capital letter N with tilde, U+00D1 ISOlat1
+        entityMap.put("Ograve", new Character('\u00d2')); // latin capital letter O with grave, U+00D2 ISOlat1
+        entityMap.put("Oacute", new Character('\u00d3')); // latin capital letter O with acute, U+00D3 ISOlat1
+        entityMap.put("Ocirc", new Character('\u00d4')); // latin capital letter O with circumflex, U+00D4 ISOlat1
+        entityMap.put("Otilde", new Character('\u00d5')); // latin capital letter O with tilde, U+00D5 ISOlat1
+        entityMap.put("Ouml", new Character('\u00d6')); // latin capital letter O with diaeresis, U+00D6 ISOlat1
+        entityMap.put("times", new Character('\u00d7')); // multiplication sign, U+00D7 ISOnum
+        entityMap.put("Oslash", new Character('\u00d8')); // latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1
+        entityMap.put("Ugrave", new Character('\u00d9')); // latin capital letter U with grave, U+00D9 ISOlat1
+        entityMap.put("Uacute", new Character('\u00da')); // latin capital letter U with acute, U+00DA ISOlat1
+        entityMap.put("Ucirc", new Character('\u00db')); // latin capital letter U with circumflex, U+00DB ISOlat1
+        entityMap.put("Uuml", new Character('\u00dc')); // latin capital letter U with diaeresis, U+00DC ISOlat1
+        entityMap.put("Yacute", new Character('\u00dd')); // latin capital letter Y with acute, U+00DD ISOlat1
+        entityMap.put("THORN", new Character('\u00de')); // latin capital letter THORN, U+00DE ISOlat1
+        entityMap.put("szlig", new Character('\u00df')); // latin small letter sharp s = ess-zed, U+00DF ISOlat1
+        entityMap.put("agrave", new Character('\u00e0')); // latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1
+        entityMap.put("aacute", new Character('\u00e1')); // latin small letter a with acute, U+00E1 ISOlat1
+        entityMap.put("acirc", new Character('\u00e2')); // latin small letter a with circumflex, U+00E2 ISOlat1
+        entityMap.put("atilde", new Character('\u00e3')); // latin small letter a with tilde, U+00E3 ISOlat1
+        entityMap.put("auml", new Character('\u00e4')); // latin small letter a with diaeresis, U+00E4 ISOlat1
+        entityMap.put("aring", new Character('\u00e5')); // latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1
+        entityMap.put("aelig", new Character('\u00e6')); // latin small letter ae = latin small ligature ae, U+00E6 ISOlat1
+        entityMap.put("ccedil", new Character('\u00e7')); // latin small letter c with cedilla, U+00E7 ISOlat1
+        entityMap.put("egrave", new Character('\u00e8')); // latin small letter e with grave, U+00E8 ISOlat1
+        entityMap.put("eacute", new Character('\u00e9')); // latin small letter e with acute, U+00E9 ISOlat1
+        entityMap.put("ecirc", new Character('\u00ea')); // latin small letter e with circumflex, U+00EA ISOlat1
+        entityMap.put("euml", new Character('\u00eb')); // latin small letter e with diaeresis, U+00EB ISOlat1
+        entityMap.put("igrave", new Character('\u00ec')); // latin small letter i with grave, U+00EC ISOlat1
+        entityMap.put("iacute", new Character('\u00ed')); // latin small letter i with acute, U+00ED ISOlat1
+        entityMap.put("icirc", new Character('\u00ee')); // latin small letter i with circumflex, U+00EE ISOlat1
+        entityMap.put("iuml", new Character('\u00ef')); // latin small letter i with diaeresis, U+00EF ISOlat1
+        entityMap.put("eth", new Character('\u00f0')); // latin small letter eth, U+00F0 ISOlat1
+        entityMap.put("ntilde", new Character('\u00f1')); // latin small letter n with tilde, U+00F1 ISOlat1
+        entityMap.put("ograve", new Character('\u00f2')); // latin small letter o with grave, U+00F2 ISOlat1
+        entityMap.put("oacute", new Character('\u00f3')); // latin small letter o with acute, U+00F3 ISOlat1
+        entityMap.put("ocirc", new Character('\u00f4')); // latin small letter o with circumflex, U+00F4 ISOlat1
+        entityMap.put("otilde", new Character('\u00f5')); // latin small letter o with tilde, U+00F5 ISOlat1
+        entityMap.put("ouml", new Character('\u00f6')); // latin small letter o with diaeresis, U+00F6 ISOlat1
+        entityMap.put("divide", new Character('\u00f7')); // division sign, U+00F7 ISOnum
+        entityMap.put("oslash", new Character('\u00f8')); // latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1
+        entityMap.put("ugrave", new Character('\u00f9')); // latin small letter u with grave, U+00F9 ISOlat1
+        entityMap.put("uacute", new Character('\u00fa')); // latin small letter u with acute, U+00FA ISOlat1
+        entityMap.put("ucirc", new Character('\u00fb')); // latin small letter u with circumflex, U+00FB ISOlat1
+        entityMap.put("uuml", new Character('\u00fc')); // latin small letter u with diaeresis, U+00FC ISOlat1
+        entityMap.put("yacute", new Character('\u00fd')); // latin small letter y with acute, U+00FD ISOlat1
+        entityMap.put("thorn", new Character('\u00fe')); // latin small letter thorn, U+00FE ISOlat1
+        entityMap.put("yuml", new Character('\u00ff')); // latin small letter y with diaeresis, U+00FF ISOlat1
+        // Latin Extended-B
+        entityMap.put("fnof", new Character('\u0192')); // latin small f with hook = function = florin, U+0192 ISOtech
+        // Greek
+        entityMap.put("Alpha", new Character('\u0391')); // greek capital letter alpha, U+0391
+        entityMap.put("Beta", new Character('\u0392')); // greek capital letter beta, U+0392
+        entityMap.put("Gamma", new Character('\u0393')); // greek capital letter gamma, U+0393 ISOgrk3
+        entityMap.put("Delta", new Character('\u0394')); // greek capital letter delta, U+0394 ISOgrk3
+        entityMap.put("Epsilon", new Character('\u0395')); // greek capital letter epsilon, U+0395
+        entityMap.put("Zeta", new Character('\u0396')); // greek capital letter zeta, U+0396
+        entityMap.put("Eta", new Character('\u0397')); // greek capital letter eta, U+0397
+        entityMap.put("Theta", new Character('\u0398')); // greek capital letter theta, U+0398 ISOgrk3
+        entityMap.put("Iota", new Character('\u0399')); // greek capital letter iota, U+0399
+        entityMap.put("Kappa", new Character('\u039a')); // greek capital letter kappa, U+039A
+        entityMap.put("Lambda", new Character('\u039b')); // greek capital letter lambda, U+039B ISOgrk3
+        entityMap.put("Mu", new Character('\u039c')); // greek capital letter mu, U+039C
+        entityMap.put("Nu", new Character('\u039d')); // greek capital letter nu, U+039D
+        entityMap.put("Xi", new Character('\u039e')); // greek capital letter xi, U+039E ISOgrk3
+        entityMap.put("Omicron", new Character('\u039f')); // greek capital letter omicron, U+039F
+        entityMap.put("Pi", new Character('\u03a0')); // greek capital letter pi, U+03A0 ISOgrk3
+        entityMap.put("Rho", new Character('\u03a1')); // greek capital letter rho, U+03A1
+        // there is no Sigmaf, and no U+03A2 character either
+        entityMap.put("Sigma", new Character('\u03a3')); // greek capital letter sigma, U+03A3 ISOgrk3
+        entityMap.put("Tau", new Character('\u03a4')); // greek capital letter tau, U+03A4
+        entityMap.put("Upsilon", new Character('\u03a5')); // greek capital letter upsilon, U+03A5 ISOgrk3
+        entityMap.put("Phi", new Character('\u03a6')); // greek capital letter phi, U+03A6 ISOgrk3
+        entityMap.put("Chi", new Character('\u03a7')); // greek capital letter chi, U+03A7
+        entityMap.put("Psi", new Character('\u03a8')); // greek capital letter psi, U+03A8 ISOgrk3
+        entityMap.put("Omega", new Character('\u03a9')); // greek capital letter omega, U+03A9 ISOgrk3
+        entityMap.put("alpha", new Character('\u03b1')); // greek small letter alpha, U+03B1 ISOgrk3
+        entityMap.put("beta", new Character('\u03b2')); // greek small letter beta, U+03B2 ISOgrk3
+        entityMap.put("gamma", new Character('\u03b3')); // greek small letter gamma, U+03B3 ISOgrk3
+        entityMap.put("delta", new Character('\u03b4')); // greek small letter delta, U+03B4 ISOgrk3
+        entityMap.put("epsilon", new Character('\u03b5')); // greek small letter epsilon, U+03B5 ISOgrk3
+        entityMap.put("zeta", new Character('\u03b6')); // greek small letter zeta, U+03B6 ISOgrk3
+        entityMap.put("eta", new Character('\u03b7')); // greek small letter eta, U+03B7 ISOgrk3
+        entityMap.put("theta", new Character('\u03b8')); // greek small letter theta, U+03B8 ISOgrk3
+        entityMap.put("iota", new Character('\u03b9')); // greek small letter iota, U+03B9 ISOgrk3
+        entityMap.put("kappa", new Character('\u03ba')); // greek small letter kappa, U+03BA ISOgrk3
+        entityMap.put("lambda", new Character('\u03bb')); // greek small letter lambda, U+03BB ISOgrk3
+        entityMap.put("mu", new Character('\u03bc')); // greek small letter mu, U+03BC ISOgrk3
+        entityMap.put("nu", new Character('\u03bd')); // greek small letter nu, U+03BD ISOgrk3
+        entityMap.put("xi", new Character('\u03be')); // greek small letter xi, U+03BE ISOgrk3
+        entityMap.put("omicron", new Character('\u03bf')); // greek small letter omicron, U+03BF NEW
+        entityMap.put("pi", new Character('\u03c0')); // greek small letter pi, U+03C0 ISOgrk3
+        entityMap.put("rho", new Character('\u03c1')); // greek small letter rho, U+03C1 ISOgrk3
+        entityMap.put("sigmaf", new Character('\u03c2')); // greek small letter final sigma, U+03C2 ISOgrk3
+        entityMap.put("sigma", new Character('\u03c3')); // greek small letter sigma, U+03C3 ISOgrk3
+        entityMap.put("tau", new Character('\u03c4')); // greek small letter tau, U+03C4 ISOgrk3
+        entityMap.put("upsilon", new Character('\u03c5')); // greek small letter upsilon, U+03C5 ISOgrk3
+        entityMap.put("phi", new Character('\u03c6')); // greek small letter phi, U+03C6 ISOgrk3
+        entityMap.put("chi", new Character('\u03c7')); // greek small letter chi, U+03C7 ISOgrk3
+        entityMap.put("psi", new Character('\u03c8')); // greek small letter psi, U+03C8 ISOgrk3
+        entityMap.put("omega", new Character('\u03c9')); // greek small letter omega, U+03C9 ISOgrk3
+        entityMap.put("thetasym", new Character('\u03d1')); // greek small letter theta symbol, U+03D1 NEW
+        entityMap.put("upsih", new Character('\u03d2')); // greek upsilon with hook symbol, U+03D2 NEW
+        entityMap.put("piv", new Character('\u03d6')); // greek pi symbol, U+03D6 ISOgrk3
+        // General Punctuation
+        entityMap.put("bull", new Character('\u2022')); // bullet = black small circle, U+2022 ISOpub
+        // bullet is NOT the same as bullet operator, U+2219
+        entityMap.put("hellip", new Character('\u2026')); // horizontal ellipsis = three dot leader, U+2026 ISOpub
+        entityMap.put("prime", new Character('\u2032')); // prime = minutes = feet, U+2032 ISOtech
+        entityMap.put("Prime", new Character('\u2033')); // double prime = seconds = inches, U+2033 ISOtech
+        entityMap.put("oline", new Character('\u203e')); // overline = spacing overscore, U+203E NEW
+        entityMap.put("frasl", new Character('\u2044')); // fraction slash, U+2044 NEW
+        // Letterlike Symbols
+        entityMap.put("weierp", new Character('\u2118')); // script capital P = power set = Weierstrass p, U+2118 ISOamso
+        entityMap.put("image", new Character('\u2111')); // blackletter capital I = imaginary part, U+2111 ISOamso
+        entityMap.put("real", new Character('\u211c')); // blackletter capital R = real part symbol, U+211C ISOamso
+        entityMap.put("trade", new Character('\u2122')); // trade mark sign, U+2122 ISOnum
+        entityMap.put("alefsym", new Character('\u2135')); // alef symbol = first transfinite cardinal, U+2135 NEW
+        // alef symbol is NOT the same as hebrew letter alef,
+        // U+05D0 although the same glyph could be used to depict both characters
+        // Arrows
+        entityMap.put("larr", new Character('\u2190')); // leftwards arrow, U+2190 ISOnum
+        entityMap.put("uarr", new Character('\u2191')); // upwards arrow, U+2191 ISOnum
+        entityMap.put("rarr", new Character('\u2192')); // rightwards arrow, U+2192 ISOnum
+        entityMap.put("darr", new Character('\u2193')); // downwards arrow, U+2193 ISOnum
+        entityMap.put("harr", new Character('\u2194')); // left right arrow, U+2194 ISOamsa
+        entityMap.put("crarr", new Character('\u21b5')); // downwards arrow with corner leftwards = carriage return, U+21B5 NEW
+        entityMap.put("lArr", new Character('\u21d0')); // leftwards double arrow, U+21D0 ISOtech
+        // ISO 10646 does not say that lArr is the same as the 'is implied by' arrow
+        // but also does not have any other character for that function. So ? lArr can
+        // be used for 'is implied by' as ISOtech suggests
+        entityMap.put("uArr", new Character('\u21d1')); // upwards double arrow, U+21D1 ISOamsa
+        entityMap.put("rArr", new Character('\u21d2')); // rightwards double arrow, U+21D2 ISOtech
+        // ISO 10646 does not say this is the 'implies' character but does not have 
+        // another character with this function so ?
+        // rArr can be used for 'implies' as ISOtech suggests
+        entityMap.put("dArr", new Character('\u21d3')); // downwards double arrow, U+21D3 ISOamsa
+        entityMap.put("hArr", new Character('\u21d4')); // left right double arrow, U+21D4 ISOamsa
+        // Mathematical Operators
+        entityMap.put("forall", new Character('\u2200')); // for all, U+2200 ISOtech
+        entityMap.put("part", new Character('\u2202')); // partial differential, U+2202 ISOtech
+        entityMap.put("exist", new Character('\u2203')); // there exists, U+2203 ISOtech
+        entityMap.put("empty", new Character('\u2205')); // empty set = null set = diameter, U+2205 ISOamso
+        entityMap.put("nabla", new Character('\u2207')); // nabla = backward difference, U+2207 ISOtech
+        entityMap.put("isin", new Character('\u2208')); // element of, U+2208 ISOtech
+        entityMap.put("notin", new Character('\u2209')); // not an element of, U+2209 ISOtech
+        entityMap.put("ni", new Character('\u220b')); // contains as member, U+220B ISOtech
+        // should there be a more memorable name than 'ni'?
+        entityMap.put("prod", new Character('\u220f')); // n-ary product = product sign, U+220F ISOamsb
+        // prod is NOT the same character as U+03A0 'greek capital letter pi' though
+        // the same glyph might be used for both
+        entityMap.put("sum", new Character('\u2211')); // n-ary sumation, U+2211 ISOamsb
+        // sum is NOT the same character as U+03A3 'greek capital letter sigma'
+        // though the same glyph might be used for both
+        entityMap.put("minus", new Character('\u2212')); // minus sign, U+2212 ISOtech
+        entityMap.put("lowast", new Character('\u2217')); // asterisk operator, U+2217 ISOtech
+        entityMap.put("radic", new Character('\u221a')); // square root = radical sign, U+221A ISOtech
+        entityMap.put("prop", new Character('\u221d')); // proportional to, U+221D ISOtech
+        entityMap.put("infin", new Character('\u221e')); // infinity, U+221E ISOtech
+        entityMap.put("ang", new Character('\u2220')); // angle, U+2220 ISOamso
+        entityMap.put("and", new Character('\u2227')); // logical and = wedge, U+2227 ISOtech
+        entityMap.put("or", new Character('\u2228')); // logical or = vee, U+2228 ISOtech
+        entityMap.put("cap", new Character('\u2229')); // intersection = cap, U+2229 ISOtech
+        entityMap.put("cup", new Character('\u222a')); // union = cup, U+222A ISOtech
+        entityMap.put("int", new Character('\u222b')); // integral, U+222B ISOtech
+        entityMap.put("there4", new Character('\u2234')); // therefore, U+2234 ISOtech
+        entityMap.put("sim", new Character('\u223c')); // tilde operator = varies with = similar to, U+223C ISOtech
+        // tilde operator is NOT the same character as the tilde, U+007E,
+        // although the same glyph might be used to represent both
+        entityMap.put("cong", new Character('\u2245')); // approximately equal to, U+2245 ISOtech
+        entityMap.put("asymp", new Character('\u2248')); // almost equal to = asymptotic to, U+2248 ISOamsr
+        entityMap.put("ne", new Character('\u2260')); // not equal to, U+2260 ISOtech
+        entityMap.put("equiv", new Character('\u2261')); // identical to, U+2261 ISOtech
+        entityMap.put("le", new Character('\u2264')); // less-than or equal to, U+2264 ISOtech
+        entityMap.put("ge", new Character('\u2265')); // greater-than or equal to, U+2265 ISOtech
+        entityMap.put("sub", new Character('\u2282')); // subset of, U+2282 ISOtech
+        entityMap.put("sup", new Character('\u2283')); // superset of, U+2283 ISOtech
+        // note that nsup, 'not a superset of, U+2283' is not covered by the Symbol 
+        // font encoding and is not included. Should it be, for symmetry?
+        // It is in ISOamsn
+        entityMap.put("nsub", new Character('\u2284')); // not a subset of, U+2284 ISOamsn
+        entityMap.put("sube", new Character('\u2286')); // subset of or equal to, U+2286 ISOtech
+        entityMap.put("supe", new Character('\u2287')); // superset of or equal to, U+2287 ISOtech
+        entityMap.put("oplus", new Character('\u2295')); // circled plus = direct sum, U+2295 ISOamsb
+        entityMap.put("otimes", new Character('\u2297')); // circled times = vector product, U+2297 ISOamsb
+        entityMap.put("perp", new Character('\u22a5')); // up tack = orthogonal to = perpendicular, U+22A5 ISOtech
+        entityMap.put("sdot", new Character('\u22c5')); // dot operator, U+22C5 ISOamsb
+        // dot operator is NOT the same character as U+00B7 middle dot
+        // Miscellaneous Technical
+        entityMap.put("lceil", new Character('\u2308')); // left ceiling = apl upstile, U+2308 ISOamsc
+        entityMap.put("rceil", new Character('\u2309')); // right ceiling, U+2309 ISOamsc
+        entityMap.put("lfloor", new Character('\u230a')); // left floor = apl downstile, U+230A ISOamsc
+        entityMap.put("rfloor", new Character('\u230b')); // right floor, U+230B ISOamsc
+        entityMap.put("lang", new Character('\u2329')); // left-pointing angle bracket = bra, U+2329 ISOtech
+        // lang is NOT the same character as U+003C 'less than' 
+        // or U+2039 'single left-pointing angle quotation mark'
+        entityMap.put("rang", new Character('\u232a')); // right-pointing angle bracket = ket, U+232A ISOtech
+        // rang is NOT the same character as U+003E 'greater than' 
+        // or U+203A 'single right-pointing angle quotation mark'
+        // Geometric Shapes
+        entityMap.put("loz", new Character('\u25ca')); // lozenge, U+25CA ISOpub
+        // Miscellaneous Symbols
+        entityMap.put("spades", new Character('\u2660')); // black spade suit, U+2660 ISOpub
+        // black here seems to mean filled as opposed to hollow
+        entityMap.put("clubs", new Character('\u2663')); // black club suit = shamrock, U+2663 ISOpub
+        entityMap.put("hearts", new Character('\u2665')); // black heart suit = valentine, U+2665 ISOpub
+        entityMap.put("diams", new Character('\u2666')); // black diamond suit, U+2666 ISOpub
+        // C0 Controls and Basic Latin
+        entityMap.put("quot", new Character('\u0022')); // quotation mark = APL quote, U+0022 ISOnum
+        entityMap.put("amp", new Character('\u0026')); // ampersand, U+0026 ISOnum
+        entityMap.put("apos", new Character('\''));
+        entityMap.put("lt", new Character('\u003c')); // less-than sign, U+003C ISOnum
+        entityMap.put("gt", new Character('\u003e')); // greater-than sign, U+003E ISOnum
+        // Latin Extended-A
+        entityMap.put("OElig", new Character('\u0152')); // latin capital ligature OE, U+0152 ISOlat2
+        entityMap.put("oelig", new Character('\u0153')); // latin small ligature oe, U+0153 ISOlat2
+        // ligature is a misnomer, this is a separate character in some languages
+        entityMap.put("Scaron", new Character('\u0160')); // latin capital letter S with caron, U+0160 ISOlat2
+        entityMap.put("scaron", new Character('\u0161')); // latin small letter s with caron, U+0161 ISOlat2
+        entityMap.put("Yuml", new Character('\u0178')); // latin capital letter Y with diaeresis, U+0178 ISOlat2
+        // Spacing Modifier Letters
+        entityMap.put("circ", new Character('\u02c6')); // modifier letter circumflex accent, U+02C6 ISOpub
+        entityMap.put("tilde", new Character('\u02dc')); // small tilde, U+02DC ISOdia
+        // General Punctuation
+        entityMap.put("ensp", new Character('\u2002')); // en space, U+2002 ISOpub
+        entityMap.put("emsp", new Character('\u2003')); // em space, U+2003 ISOpub
+        entityMap.put("thinsp", new Character('\u2009')); // thin space, U+2009 ISOpub
+        entityMap.put("zwnj", new Character('\u200c')); // zero width non-joiner, U+200C NEW RFC 2070
+        entityMap.put("zwj", new Character('\u200d')); // zero width joiner, U+200D NEW RFC 2070
+        entityMap.put("lrm", new Character('\u200e')); // left-to-right mark, U+200E NEW RFC 2070
+        entityMap.put("rlm", new Character('\u200f')); // right-to-left mark, U+200F NEW RFC 2070
+        entityMap.put("ndash", new Character('\u2013')); // en dash, U+2013 ISOpub
+        entityMap.put("mdash", new Character('\u2014')); // em dash, U+2014 ISOpub
+        entityMap.put("lsquo", new Character('\u2018')); // left single quotation mark, U+2018 ISOnum
+        entityMap.put("rsquo", new Character('\u2019')); // right single quotation mark, U+2019 ISOnum
+        entityMap.put("sbquo", new Character('\u201a')); // single low-9 quotation mark, U+201A NEW
+        entityMap.put("ldquo", new Character('\u201c')); // left double quotation mark, U+201C ISOnum
+        entityMap.put("rdquo", new Character('\u201d')); // right double quotation mark, U+201D ISOnum
+        entityMap.put("bdquo", new Character('\u201e')); // double low-9 quotation mark, U+201E NEW
+        entityMap.put("dagger", new Character('\u2020')); // dagger, U+2020 ISOpub
+        entityMap.put("Dagger", new Character('\u2021')); // double dagger, U+2021 ISOpub
+        entityMap.put("permil", new Character('\u2030')); // per mille sign, U+2030 ISOtech
+        entityMap.put("lsaquo", new Character('\u2039')); // single left-pointing angle quotation mark, U+2039 ISO proposed
+        // lsaquo is proposed but not yet ISO standardized
+        entityMap.put("rsaquo", new Character('\u203a')); // single right-pointing angle quotation mark, U+203A ISO proposed
+        // rsaquo is proposed but not yet ISO standardized
+        entityMap.put("euro", new Character('\u20ac')); // euro sign, U+20AC NEW
+    
+    
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/SpotColor.java b/LibrarySource/com/lowagie/text/pdf/SpotColor.java
new file mode 100644
index 0000000..6b74fc9
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/SpotColor.java
@@ -0,0 +1,84 @@
+/*
+ * $Id: SpotColor.java,v 1.13 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+/**
+ *
+ * @author  psoares
+ */
+public class SpotColor extends ExtendedColor {
+
+    PdfSpotColor spot;
+    float tint;
+
+    public SpotColor(PdfSpotColor spot, float tint) {
+        super(TYPE_SEPARATION,
+            (float)spot.getAlternativeCS().getRed() / 255f * tint,
+            (float)spot.getAlternativeCS().getGreen() / 255f * tint,
+            (float)spot.getAlternativeCS().getBlue() / 255f * tint);
+        this.spot = spot;
+        this.tint = tint;
+    }
+    
+    public SpotColor(PdfSpotColor spot) {
+        this(spot, spot.getTint());
+    }
+    
+    public PdfSpotColor getPdfSpotColor() {
+        return spot;
+    }
+    
+    public float getTint() {
+        return tint;
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/TextField.java b/LibrarySource/com/lowagie/text/pdf/TextField.java
new file mode 100644
index 0000000..89eda88
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/TextField.java
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2003-2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import headless.awt.Color;
+import com.lowagie.text.Element;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Rectangle;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/** Supports text, combo and list fields generating the correct appearances.
+ * All the option in the Acrobat GUI are supported in an easy to use API.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class TextField extends BaseField {
+    
+    /** Holds value of property defaultText. */
+    private String defaultText;
+    
+    /** Holds value of property choices. */
+    private String[] choices;
+    
+    /** Holds value of property choiceExports. */
+    private String[] choiceExports;
+    
+    /** Holds value of property choiceSelection. */
+    private int choiceSelection;
+    
+    private int topFirst;
+    /** Creates a new <CODE>TextField</CODE>.
+     * @param writer the document <CODE>PdfWriter</CODE>
+     * @param box the field location and dimensions
+     * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
+     * will be included in the field allowing it to be used as a kid field.
+     */
+    public TextField(PdfWriter writer, Rectangle box, String fieldName) {
+        super(writer, box, fieldName);
+    }
+    
+    /**
+     * Gets the appearance for this TextField.
+     * @return the appearance object for this TextField
+     * @throws IOException
+     * @throws DocumentException
+     */
+    public PdfAppearance getAppearance() throws IOException, DocumentException {
+        PdfAppearance app = getBorderAppearance();
+        app.beginVariableText();
+        if (text == null || text.length() == 0) {
+            app.endVariableText();
+            return app;
+        }
+        BaseFont ufont = getRealFont();
+        boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+        float h = box.height() - borderWidth * 2;
+        float bw2 = borderWidth;
+        if (borderExtra) {
+            h -= borderWidth * 2;
+            bw2 *= 2;
+        }
+        float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+        offsetX = Math.max(offsetX, 1);
+        float offX = Math.min(bw2, offsetX);
+        app.saveState();
+        app.rectangle(offX, offX, box.width() - 2 * offX, box.height() - 2 * offX);
+        app.clip();
+        app.newPath();
+        if (textColor == null)
+            app.setGrayFill(0);
+        else
+            app.setColorFill(textColor);
+        app.beginText();
+        if ((options & MULTILINE) != 0) {
+            float usize = fontSize;
+            float width = box.width() - 3 * offsetX;
+            ArrayList breaks = getHardBreaks(text);
+            ArrayList lines = breaks;
+            float factor = ufont.getFontDescriptor(BaseFont.BBOXURY, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1);
+            if (usize == 0) {
+                usize = h / breaks.size() / factor;
+                if (usize > 4) {
+                    if (usize > 12)
+                        usize = 12;
+                    float step = Math.max((usize - 4) / 10, 0.2f);
+                    for (; usize > 4; usize -= step) {
+                        lines = breakLines(breaks, ufont, usize, width);
+                        if (lines.size() * usize * factor <= h)
+                            break;
+                    }
+                }
+                if (usize <= 4) {
+                    usize = 4;
+                    lines = breakLines(breaks, ufont, usize, width);
+                }
+            }
+            else
+                lines = breakLines(breaks, ufont, usize, width);
+            app.setFontAndSize(ufont, usize);
+            app.setLeading(usize * factor);
+            float offsetY = offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize);
+            String nt = (String)lines.get(0);
+            if (alignment == Element.ALIGN_RIGHT) {
+                float wd = ufont.getWidthPoint(nt, usize);
+                app.moveText(box.width() - 2 * offsetX - wd, offsetY);
+            }
+            else if (alignment == Element.ALIGN_CENTER) {
+                nt = nt.trim();
+                float wd = ufont.getWidthPoint(nt, usize);
+                app.moveText(box.width() / 2  - wd / 2, offsetY);
+            }
+            else
+                app.moveText(2 * offsetX, offsetY);
+            app.showText(nt);
+            int maxline = (int)(h / usize / factor) + 1;
+            maxline = Math.min(maxline, lines.size());
+            for (int k = 1; k < maxline; ++k) {
+                nt = (String)lines.get(k);
+                if (alignment == Element.ALIGN_RIGHT) {
+                    float wd = ufont.getWidthPoint(nt, usize);
+                    app.moveText(box.width() - 2 * offsetX - wd - app.getXTLM(), 0);
+                }
+                else if (alignment == Element.ALIGN_CENTER) {
+                    nt = nt.trim();
+                    float wd = ufont.getWidthPoint(nt, usize);
+                    app.moveText(box.width() / 2  - wd / 2 - app.getXTLM(), 0);
+                }
+                app.newlineShowText(nt);
+            }
+        }
+        else {
+            float usize = fontSize;
+            if (usize == 0) {
+                float maxCalculatedSize = h / (ufont.getFontDescriptor(BaseFont.BBOXURX, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1));
+                float wd = ufont.getWidthPoint(text, 1);
+                if (wd == 0)
+                    usize = maxCalculatedSize;
+                else
+                    usize = (box.width() - 2 * offsetX) / wd;
+                if (usize > maxCalculatedSize)
+                    usize = maxCalculatedSize;
+                if (usize < 4)
+                    usize = 4;
+            }
+            app.setFontAndSize(ufont, usize);
+            float offsetY = offX + ((box.height() - 2*offX) - ufont.getFontDescriptor(BaseFont.ASCENT, usize)) / 2;
+            if (offsetY < offX)
+                offsetY = offX;
+            if (offsetY - offX < -ufont.getFontDescriptor(BaseFont.DESCENT, usize)) {
+                float ny = -ufont.getFontDescriptor(BaseFont.DESCENT, usize) + offX;
+                float dy = box.height() - offX - ufont.getFontDescriptor(BaseFont.ASCENT, usize);
+                offsetY = Math.min(ny, Math.max(offsetY, dy));
+            }
+            if ((options & COMB) != 0 && maxCharacterLength > 0) {
+                int textLen = Math.min(maxCharacterLength, text.length());
+                int position = 0;
+                if (alignment == Element.ALIGN_RIGHT) {
+                    position = maxCharacterLength - textLen;
+                }
+                else if (alignment == Element.ALIGN_CENTER) {
+                    position = (maxCharacterLength - textLen) / 2;
+                }
+                float step = box.width() / maxCharacterLength;
+                float start = step / 2 + position * step;
+                for (int k = 0; k < textLen; ++k) {
+                    String c = text.substring(k, k + 1);
+                    float wd = ufont.getWidthPoint(c, usize);
+                    app.setTextMatrix(start - wd / 2, offsetY);
+                    app.showText(c);
+                    start += step;
+                }
+            }
+            else {
+                if (alignment == Element.ALIGN_RIGHT) {
+                    float wd = ufont.getWidthPoint(text, usize);
+                    app.moveText(box.width() - 2 * offsetX - wd, offsetY);
+                }
+                else if (alignment == Element.ALIGN_CENTER) {
+                    float wd = ufont.getWidthPoint(text, usize);
+                    app.moveText(box.width() / 2  - wd / 2, offsetY);
+                }
+                else
+                    app.moveText(2 * offsetX, offsetY);
+                app.showText(text);
+            }
+        }
+        app.endText();
+        app.restoreState();
+        app.endVariableText();
+        return app;
+    }
+
+    PdfAppearance getListAppearance() throws IOException, DocumentException {
+        PdfAppearance app = getBorderAppearance();
+        app.beginVariableText();
+        if (choices == null || choices.length == 0) {
+            app.endVariableText();
+            return app;
+        }
+        int topChoice = choiceSelection;
+        if (topChoice >= choices.length) {
+            topChoice = choices.length - 1;
+        }
+        if (topChoice < 0)
+            topChoice = 0;
+        BaseFont ufont = getRealFont();
+        float usize = fontSize;
+        if (usize == 0)
+            usize = 12;
+        boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+        float h = box.height() - borderWidth * 2;
+        if (borderExtra)
+            h -= borderWidth * 2;
+        float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+        float leading = ufont.getFontDescriptor(BaseFont.BBOXURY, usize) - ufont.getFontDescriptor(BaseFont.BBOXLLY, usize);
+        int maxFit = (int)(h / leading) + 1;
+        int first = 0;
+        int last = 0;
+        last = topChoice + maxFit / 2 + 1;
+        first = last - maxFit;
+        if (first < 0) {
+            last += first;
+            first = 0;
+        }
+//        first = topChoice;
+        last = first + maxFit;
+        if (last > choices.length)
+            last = choices.length;
+        topFirst = first;
+        app.saveState();
+        app.rectangle(offsetX, offsetX, box.width() - 2 * offsetX, box.height() - 2 * offsetX);
+        app.clip();
+        app.newPath();
+        Color mColor;
+        if (textColor == null)
+            mColor = new GrayColor(0);
+        else
+            mColor = textColor;
+        app.setColorFill(new Color(10, 36, 106));
+        app.rectangle(offsetX, offsetX + h - (topChoice - first + 1) * leading, box.width() - 2 * offsetX, leading);
+        app.fill();
+        app.beginText();
+        app.setFontAndSize(ufont, usize);
+        app.setLeading(leading);
+        app.moveText(offsetX * 2, offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize) + leading);
+        app.setColorFill(mColor);
+        for (int idx = first; idx < last; ++idx) {
+            if (idx == topChoice) {
+                app.setGrayFill(1);
+                app.newlineShowText(choices[idx]);
+                app.setColorFill(mColor);
+            }
+            else
+                app.newlineShowText(choices[idx]);
+        }
+        app.endText();
+        app.restoreState();
+        app.endVariableText();
+        return app;
+    }
+
+    /** Gets a new text field.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return a new text field
+     */    
+    public PdfFormField getTextField() throws IOException, DocumentException {
+        if (maxCharacterLength <= 0)
+            options &= ~COMB;
+        if ((options & COMB) != 0)
+            options &= ~MULTILINE;
+        PdfFormField field = PdfFormField.createTextField(writer, false, false, maxCharacterLength);
+        field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+        switch (alignment) {
+            case Element.ALIGN_CENTER:
+                field.setQuadding(PdfFormField.Q_CENTER);
+                break;
+            case Element.ALIGN_RIGHT:
+                field.setQuadding(PdfFormField.Q_RIGHT);
+                break;
+        }
+        if (rotation != 0)
+            field.setMKRotation(rotation);
+        if (fieldName != null) {
+            field.setFieldName(fieldName);
+            field.setValueAsString(text);
+            if (defaultText != null)
+                field.setDefaultValueAsString(defaultText);
+            if ((options & READ_ONLY) != 0)
+                field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+            if ((options & REQUIRED) != 0)
+                field.setFieldFlags(PdfFormField.FF_REQUIRED);
+            if ((options & MULTILINE) != 0)
+                field.setFieldFlags(PdfFormField.FF_MULTILINE);
+            if ((options & DO_NOT_SCROLL) != 0)
+                field.setFieldFlags(PdfFormField.FF_DONOTSCROLL);
+            if ((options & PASSWORD) != 0)
+                field.setFieldFlags(PdfFormField.FF_PASSWORD);
+            if ((options & FILE_SELECTION) != 0)
+                field.setFieldFlags(PdfFormField.FF_FILESELECT);
+            if ((options & DO_NOT_SPELL_CHECK) != 0)
+                field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
+            if ((options & COMB) != 0)
+                field.setFieldFlags(PdfFormField.FF_COMB);
+        }
+        field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+        PdfAppearance tp = getAppearance();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+        PdfAppearance da = (PdfAppearance)tp.getDuplicate();
+        da.setFontAndSize(getRealFont(), fontSize);
+        if (textColor == null)
+            da.setGrayFill(0);
+        else
+            da.setColorFill(textColor);
+        field.setDefaultAppearanceString(da);
+        if (borderColor != null)
+            field.setMKBorderColor(borderColor);
+        if (backgroundColor != null)
+            field.setMKBackgroundColor(backgroundColor);
+        switch (visibility) {
+            case HIDDEN:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+                break;
+            case VISIBLE_BUT_DOES_NOT_PRINT:
+                break;
+            case HIDDEN_BUT_PRINTABLE:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+                break;
+            default:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT);
+                break;
+        }
+        return field;
+    }
+    
+    /** Gets a new combo field.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return a new combo field
+     */    
+    public PdfFormField getComboField() throws IOException, DocumentException {
+        return getChoiceField(false);
+    }
+    
+    /** Gets a new list field.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return a new list field
+     */    
+    public PdfFormField getListField() throws IOException, DocumentException {
+        return getChoiceField(true);
+    }
+
+    protected PdfFormField getChoiceField(boolean isList) throws IOException, DocumentException {
+        options &= (~MULTILINE) & (~COMB);
+        String uchoices[] = choices;
+        if (uchoices == null)
+            uchoices = new String[0];
+        int topChoice = choiceSelection;
+        if (topChoice >= uchoices.length)
+            topChoice = uchoices.length - 1;
+        text = "";
+        if (topChoice >= 0)
+            text = uchoices[topChoice];
+        if (topChoice < 0)
+            topChoice = 0;
+        PdfFormField field = null;
+        String mix[][] = null;
+        if (choiceExports == null) {
+            if (isList)
+                field = PdfFormField.createList(writer, uchoices, topChoice);
+            else
+                field = PdfFormField.createCombo(writer, (options & EDIT) != 0, uchoices, topChoice);
+        }
+        else {
+            mix = new String[uchoices.length][2];
+            for (int k = 0; k < mix.length; ++k)
+                mix[k][0] = mix[k][1] = uchoices[k];
+            int top = Math.min(uchoices.length, choiceExports.length);
+            for (int k = 0; k < top; ++k) {
+                if (choiceExports[k] != null)
+                    mix[k][0] = choiceExports[k];
+            }
+            if (isList)
+                field = PdfFormField.createList(writer, mix, topChoice);
+            else
+                field = PdfFormField.createCombo(writer, (options & EDIT) != 0, mix, topChoice);
+        }
+        field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+        if (rotation != 0)
+            field.setMKRotation(rotation);
+        if (fieldName != null) {
+            field.setFieldName(fieldName);
+            if (uchoices.length > 0) {
+                if (mix != null) {
+                    field.setValueAsString(mix[topChoice][0]);
+                    field.setDefaultValueAsString(mix[topChoice][0]);
+                }
+                else {
+                    field.setValueAsString(text);
+                    field.setDefaultValueAsString(text);
+                }
+            }
+            if ((options & READ_ONLY) != 0)
+                field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+            if ((options & REQUIRED) != 0)
+                field.setFieldFlags(PdfFormField.FF_REQUIRED);
+            if ((options & DO_NOT_SPELL_CHECK) != 0)
+                field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
+        }
+        field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+        PdfAppearance tp;
+        if (isList) {
+            tp = getListAppearance();
+            if (topFirst > 0)
+                field.put(PdfName.TI, new PdfNumber(topFirst));
+        }
+        else
+            tp = getAppearance();
+        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+        PdfAppearance da = (PdfAppearance)tp.getDuplicate();
+        da.setFontAndSize(getRealFont(), fontSize);
+        if (textColor == null)
+            da.setGrayFill(0);
+        else
+            da.setColorFill(textColor);
+        field.setDefaultAppearanceString(da);
+        if (borderColor != null)
+            field.setMKBorderColor(borderColor);
+        if (backgroundColor != null)
+            field.setMKBackgroundColor(backgroundColor);
+        switch (visibility) {
+            case HIDDEN:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+                break;
+            case VISIBLE_BUT_DOES_NOT_PRINT:
+                break;
+            case HIDDEN_BUT_PRINTABLE:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+                break;
+            default:
+                field.setFlags(PdfAnnotation.FLAGS_PRINT);
+                break;
+        }
+        return field;
+    }
+    
+    /** Gets the default text.
+     * @return the default text
+     */
+    public String getDefaultText() {
+        return this.defaultText;
+    }
+    
+    /** Sets the default text. It is only meaningful for text fields.
+     * @param defaultText the default text
+     */
+    public void setDefaultText(String defaultText) {
+        this.defaultText = defaultText;
+    }
+    
+    /** Gets the choices to be presented to the user in list/combo
+     * fields.
+     * @return the choices to be presented to the user
+     */
+    public String[] getChoices() {
+        return this.choices;
+    }
+    
+    /** Sets the choices to be presented to the user in list/combo
+     * fields.
+     * @param choices the choices to be presented to the user
+     */
+    public void setChoices(String[] choices) {
+        this.choices = choices;
+    }
+    
+    /** Gets the export values in list/combo fields.
+     * @return the export values in list/combo fields
+     */
+    public String[] getChoiceExports() {
+        return this.choiceExports;
+    }
+    
+    /** Sets the export values in list/combo fields. If this array
+     * is <CODE>null</CODE> then the choice values will also be used
+     * as the export values.
+     * @param choiceExports the export values in list/combo fields
+     */
+    public void setChoiceExports(String[] choiceExports) {
+        this.choiceExports = choiceExports;
+    }
+    
+    /** Gets the zero based index of the selected item.
+     * @return the zero based index of the selected item
+     */
+    public int getChoiceSelection() {
+        return this.choiceSelection;
+    }
+    
+    /** Sets the zero based index of the selected item.
+     * @param choiceSelection the zero based index of the selected item
+     */
+    public void setChoiceSelection(int choiceSelection) {
+        this.choiceSelection = choiceSelection;
+    }
+    
+    int getTopFirst() {
+        return topFirst;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/TrueTypeFont.java b/LibrarySource/com/lowagie/text/pdf/TrueTypeFont.java
new file mode 100644
index 0000000..b774e93
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/TrueTypeFont.java
@@ -0,0 +1,1300 @@
+/*
+ * $Id: TrueTypeFont.java,v 1.55 2004/12/14 15:15:59 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+/** Reads a Truetype font
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+class TrueTypeFont extends BaseFont {
+
+    /** The code pages possible for a True Type font.
+     */    
+    static final String codePages[] = {
+        "1252 Latin 1",
+        "1250 Latin 2: Eastern Europe",
+        "1251 Cyrillic",
+        "1253 Greek",
+        "1254 Turkish",
+        "1255 Hebrew",
+        "1256 Arabic",
+        "1257 Windows Baltic",
+        "1258 Vietnamese",
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        "874 Thai",
+        "932 JIS/Japan",
+        "936 Chinese: Simplified chars--PRC and Singapore",
+        "949 Korean Wansung",
+        "950 Chinese: Traditional chars--Taiwan and Hong Kong",
+        "1361 Korean Johab",
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        "Macintosh Character Set (US Roman)",
+        "OEM Character Set",
+        "Symbol Character Set",
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        null,
+        "869 IBM Greek",
+        "866 MS-DOS Russian",
+        "865 MS-DOS Nordic",
+        "864 Arabic",
+        "863 MS-DOS Canadian French",
+        "862 Hebrew",
+        "861 MS-DOS Icelandic",
+        "860 MS-DOS Portuguese",
+        "857 IBM Turkish",
+        "855 IBM Cyrillic; primarily Russian",
+        "852 Latin 2",
+        "775 MS-DOS Baltic",
+        "737 Greek; former 437 G",
+        "708 Arabic; ASMO 708",
+        "850 WE/Latin 1",
+        "437 US"};
+ 
+    protected boolean justNames = false;
+    /** Contains the location of the several tables. The key is the name of
+     * the table and the value is an <CODE>int[2]</CODE> where position 0
+     * is the offset from the start of the file and position 1 is the length
+     * of the table.
+     */
+    protected HashMap tables;
+    /** The file in use.
+     */
+    protected RandomAccessFileOrArray rf;
+    /** The file name.
+     */
+    protected String fileName;
+    
+    protected boolean cff = false;
+    
+    protected int cffOffset;
+    
+    protected int cffLength;
+    
+    /** The offset from the start of the file to the table directory.
+     * It is 0 for TTF and may vary for TTC depending on the chosen font.
+     */    
+    protected int directoryOffset;
+    /** The index for the TTC font. It is an empty <CODE>String</CODE> for a
+     * TTF file.
+     */    
+    protected String ttcIndex;
+    /** The style modifier */
+    protected String style = "";
+    /** The content of table 'head'.
+     */
+    protected FontHeader head = new FontHeader();
+    /** The content of table 'hhea'.
+     */
+    protected HorizontalHeader hhea = new HorizontalHeader();
+    /** The content of table 'OS/2'.
+     */
+    protected WindowsMetrics os_2 = new WindowsMetrics();
+    /** The width of the glyphs. This is essentially the content of table
+     * 'hmtx' normalized to 1000 units.
+     */
+    protected int GlyphWidths[];
+    
+    protected int bboxes[][];
+    /** The map containing the code information for the table 'cmap', encoding 1.0.
+     * The key is the code and the value is an <CODE>int[2]</CODE> where position 0
+     * is the glyph number and position 1 is the glyph width normalized to 1000
+     * units.
+     */
+    protected HashMap cmap10;
+    /** The map containing the code information for the table 'cmap', encoding 3.1
+     * in Unicode.
+     * <P>
+     * The key is the code and the value is an <CODE>int</CODE>[2] where position 0
+     * is the glyph number and position 1 is the glyph width normalized to 1000
+     * units.
+     */
+    protected HashMap cmap31;
+    /** The map containing the kerning information. It represents the content of
+     * table 'kern'. The key is an <CODE>Integer</CODE> where the top 16 bits
+     * are the glyph number for the first character and the lower 16 bits are the
+     * glyph number for the second character. The value is the amount of kerning in
+     * normalized 1000 units as an <CODE>Integer</CODE>. This value is usually negative.
+     */
+    protected IntHashtable kerning = new IntHashtable();
+    /**
+     * The font name.
+     * This name is usually extracted from the table 'name' with
+     * the 'Name ID' 6.
+     */
+    protected String fontName;
+    
+    /** The full name of the font
+     */    
+    protected String fullName[][];
+
+    /** The family name of the font
+     */    
+    protected String familyName[][];
+    /** The italic angle. It is usually extracted from the 'post' table or in it's
+     * absence with the code:
+     * <P>
+     * <PRE>
+     * -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI
+     * </PRE>
+     */
+    protected double italicAngle;
+    /** <CODE>true</CODE> if all the glyphs have the same width.
+     */
+    protected boolean isFixedPitch = false;
+    
+    /** The components of table 'head'.
+     */
+    protected static class FontHeader {
+        /** A variable. */
+        int flags;
+        /** A variable. */
+        int unitsPerEm;
+        /** A variable. */
+        short xMin;
+        /** A variable. */
+        short yMin;
+        /** A variable. */
+        short xMax;
+        /** A variable. */
+        short yMax;
+        /** A variable. */
+        int macStyle;
+    }
+    
+    /** The components of table 'hhea'.
+     */
+    protected static class HorizontalHeader {
+        /** A variable. */
+        short Ascender;
+        /** A variable. */
+        short Descender;
+        /** A variable. */
+        short LineGap;
+        /** A variable. */
+        int advanceWidthMax;
+        /** A variable. */
+        short minLeftSideBearing;
+        /** A variable. */
+        short minRightSideBearing;
+        /** A variable. */
+        short xMaxExtent;
+        /** A variable. */
+        short caretSlopeRise;
+        /** A variable. */
+        short caretSlopeRun;
+        /** A variable. */
+        int numberOfHMetrics;
+    }
+    
+    /** The components of table 'OS/2'.
+     */
+    protected static class WindowsMetrics {
+        /** A variable. */
+        short xAvgCharWidth;
+        /** A variable. */
+        int usWeightClass;
+        /** A variable. */
+        int usWidthClass;
+        /** A variable. */
+        short fsType;
+        /** A variable. */
+        short ySubscriptXSize;
+        /** A variable. */
+        short ySubscriptYSize;
+        /** A variable. */
+        short ySubscriptXOffset;
+        /** A variable. */
+        short ySubscriptYOffset;
+        /** A variable. */
+        short ySuperscriptXSize;
+        /** A variable. */
+        short ySuperscriptYSize;
+        /** A variable. */
+        short ySuperscriptXOffset;
+        /** A variable. */
+        short ySuperscriptYOffset;
+        /** A variable. */
+        short yStrikeoutSize;
+        /** A variable. */
+        short yStrikeoutPosition;
+        /** A variable. */
+        short sFamilyClass;
+        /** A variable. */
+        byte panose[] = new byte[10];
+        /** A variable. */
+        byte achVendID[] = new byte[4];
+        /** A variable. */
+        int fsSelection;
+        /** A variable. */
+        int usFirstCharIndex;
+        /** A variable. */
+        int usLastCharIndex;
+        /** A variable. */
+        short sTypoAscender;
+        /** A variable. */
+        short sTypoDescender;
+        /** A variable. */
+        short sTypoLineGap;
+        /** A variable. */
+        int usWinAscent;
+        /** A variable. */
+        int usWinDescent;
+        /** A variable. */
+        int ulCodePageRange1;
+        /** A variable. */
+        int ulCodePageRange2;
+        /** A variable. */
+        int sCapHeight;
+    }
+    
+    /** This constructor is present to allow extending the class.
+     */
+    protected TrueTypeFont() {
+    }
+    
+    TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
+        this(ttFile, enc, emb, ttfAfm, false);
+    }
+    
+    /** Creates a new TrueType font.
+     * @param ttFile the location of the font on file. The file must end in '.ttf' or
+     * '.ttc' but can have modifiers after the name
+     * @param enc the encoding to be applied to this font
+     * @param emb true if the font is to be embedded in the PDF
+     * @param ttfAfm the font as a <CODE>byte</CODE> array
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[], boolean justNames) throws DocumentException, IOException {
+        this.justNames = justNames;
+        String nameBase = getBaseName(ttFile);
+        String ttcName = getTTCName(nameBase);
+        if (nameBase.length() < ttFile.length()) {
+            style = ttFile.substring(nameBase.length());
+        }
+        encoding = enc;
+        embedded = emb;
+        fileName = ttcName;
+        fontType = FONT_TYPE_TT;
+        ttcIndex = "";
+        if (ttcName.length() < nameBase.length())
+            ttcIndex = nameBase.substring(ttcName.length() + 1);
+        if (fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) {
+            process(ttfAfm);
+            if (!justNames && embedded && os_2.fsType == 2)
+                throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
+        }
+        else
+            throw new DocumentException(fileName + style + " is not a TTF, OTF or TTC font file.");
+        PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
+        createEncoding();
+    }
+    
+    /** Gets the name from a composed TTC file name.
+     * If I have for input "myfont.ttc,2" the return will
+     * be "myfont.ttc".
+     * @param name the full name
+     * @return the simple file name
+     */    
+    protected static String getTTCName(String name) {
+        int idx = name.toLowerCase().indexOf(".ttc,");
+        if (idx < 0)
+            return name;
+        else
+            return name.substring(0, idx + 4);
+    }
+    
+    
+    /**
+     * Reads the tables 'head', 'hhea', 'OS/2' and 'post' filling several variables.
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    void fillTables() throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("head");
+        if (table_location == null)
+            throw new DocumentException("Table 'head' does not exist in " + fileName + style);
+        rf.seek(table_location[0] + 16);
+        head.flags = rf.readUnsignedShort();
+        head.unitsPerEm = rf.readUnsignedShort();
+        rf.skipBytes(16);
+        head.xMin = rf.readShort();
+        head.yMin = rf.readShort();
+        head.xMax = rf.readShort();
+        head.yMax = rf.readShort();
+        head.macStyle = rf.readUnsignedShort();
+        
+        table_location = (int[])tables.get("hhea");
+        if (table_location == null)
+            throw new DocumentException("Table 'hhea' does not exist " + fileName + style);
+        rf.seek(table_location[0] + 4);
+        hhea.Ascender = rf.readShort();
+        hhea.Descender = rf.readShort();
+        hhea.LineGap = rf.readShort();
+        hhea.advanceWidthMax = rf.readUnsignedShort();
+        hhea.minLeftSideBearing = rf.readShort();
+        hhea.minRightSideBearing = rf.readShort();
+        hhea.xMaxExtent = rf.readShort();
+        hhea.caretSlopeRise = rf.readShort();
+        hhea.caretSlopeRun = rf.readShort();
+        rf.skipBytes(12);
+        hhea.numberOfHMetrics = rf.readUnsignedShort();
+        
+        table_location = (int[])tables.get("OS/2");
+        if (table_location == null)
+            throw new DocumentException("Table 'OS/2' does not exist in " + fileName + style);
+        rf.seek(table_location[0]);
+        int version = rf.readUnsignedShort();
+        os_2.xAvgCharWidth = rf.readShort();
+        os_2.usWeightClass = rf.readUnsignedShort();
+        os_2.usWidthClass = rf.readUnsignedShort();
+        os_2.fsType = rf.readShort();
+        os_2.ySubscriptXSize = rf.readShort();
+        os_2.ySubscriptYSize = rf.readShort();
+        os_2.ySubscriptXOffset = rf.readShort();
+        os_2.ySubscriptYOffset = rf.readShort();
+        os_2.ySuperscriptXSize = rf.readShort();
+        os_2.ySuperscriptYSize = rf.readShort();
+        os_2.ySuperscriptXOffset = rf.readShort();
+        os_2.ySuperscriptYOffset = rf.readShort();
+        os_2.yStrikeoutSize = rf.readShort();
+        os_2.yStrikeoutPosition = rf.readShort();
+        os_2.sFamilyClass = rf.readShort();
+        rf.readFully(os_2.panose);
+        rf.skipBytes(16);
+        rf.readFully(os_2.achVendID);
+        os_2.fsSelection = rf.readUnsignedShort();
+        os_2.usFirstCharIndex = rf.readUnsignedShort();
+        os_2.usLastCharIndex = rf.readUnsignedShort();
+        os_2.sTypoAscender = rf.readShort();
+        os_2.sTypoDescender = rf.readShort();
+        if (os_2.sTypoDescender > 0)
+            os_2.sTypoDescender = (short)(-os_2.sTypoDescender);
+        os_2.sTypoLineGap = rf.readShort();
+        os_2.usWinAscent = rf.readUnsignedShort();
+        os_2.usWinDescent = rf.readUnsignedShort();
+        os_2.ulCodePageRange1 = 0;
+        os_2.ulCodePageRange2 = 0;
+        if (version > 0) {
+            os_2.ulCodePageRange1 = rf.readInt();
+            os_2.ulCodePageRange2 = rf.readInt();
+        }
+        if (version > 1) {
+            rf.skipBytes(2);
+            os_2.sCapHeight = rf.readShort();
+        }
+        else
+            os_2.sCapHeight = (int)(0.7 * head.unitsPerEm);
+        
+        table_location = (int[])tables.get("post");
+        if (table_location == null) {
+            italicAngle = -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI;
+            return;
+        }
+        rf.seek(table_location[0] + 4);
+        short mantissa = rf.readShort();
+        int fraction = rf.readUnsignedShort();
+        italicAngle = (double)mantissa + (double)fraction / 16384.0;
+        rf.skipBytes(4);
+        isFixedPitch = rf.readInt() != 0;
+    }
+    
+    /**
+     * Gets the Postscript font name.
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     * @return the Postscript font name
+     */
+    String getBaseFont() throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("name");
+        if (table_location == null)
+            throw new DocumentException("Table 'name' does not exist in " + fileName + style);
+        rf.seek(table_location[0] + 2);
+        int numRecords = rf.readUnsignedShort();
+        int startOfStorage = rf.readUnsignedShort();
+        for (int k = 0; k < numRecords; ++k) {
+            int platformID = rf.readUnsignedShort();
+            int platformEncodingID = rf.readUnsignedShort();
+            int languageID = rf.readUnsignedShort();
+            int nameID = rf.readUnsignedShort();
+            int length = rf.readUnsignedShort();
+            int offset = rf.readUnsignedShort();
+            if (nameID == 6) {
+                rf.seek(table_location[0] + startOfStorage + offset);
+                if (platformID == 0 || platformID == 3)
+                    return readUnicodeString(length);
+                else
+                    return readStandardString(length);
+            }
+        }
+        File file = new File(fileName);
+        return file.getName().replace(' ', '-');
+    }
+    
+    /** Extracts the names of the font in all the languages available.
+     * @param id the name id to retrieve
+     * @throws DocumentException on error
+     * @throws IOException on error
+     */    
+    String[][] getNames(int id) throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("name");
+        if (table_location == null)
+            throw new DocumentException("Table 'name' does not exist in " + fileName + style);
+        rf.seek(table_location[0] + 2);
+        int numRecords = rf.readUnsignedShort();
+        int startOfStorage = rf.readUnsignedShort();
+        ArrayList names = new ArrayList();
+        for (int k = 0; k < numRecords; ++k) {
+            int platformID = rf.readUnsignedShort();
+            int platformEncodingID = rf.readUnsignedShort();
+            int languageID = rf.readUnsignedShort();
+            int nameID = rf.readUnsignedShort();
+            int length = rf.readUnsignedShort();
+            int offset = rf.readUnsignedShort();
+            if (nameID == id) {
+                int pos = rf.getFilePointer();
+                rf.seek(table_location[0] + startOfStorage + offset);
+                String name;
+                if (platformID == 0 || platformID == 3 || (platformID == 2 && platformEncodingID == 1)){
+                    name = readUnicodeString(length);
+                }
+                else {
+                    name = readStandardString(length);
+                }
+                names.add(new String[]{String.valueOf(platformID),
+                    String.valueOf(platformEncodingID), String.valueOf(languageID), name});
+                rf.seek(pos);
+            }
+        }
+        String thisName[][] = new String[names.size()][];
+        for (int k = 0; k < names.size(); ++k)
+            thisName[k] = (String[])names.get(k);
+        return thisName;
+    }
+    
+    void checkCff() throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("CFF ");
+        if (table_location != null) {
+            cff = true;
+            cffOffset = table_location[0];
+            cffLength = table_location[1];
+        }
+    }
+
+    /** Reads the font data.
+     * @param ttfAfm the font as a <CODE>byte</CODE> array, possibly <CODE>null</CODE>
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    void process(byte ttfAfm[]) throws DocumentException, IOException {
+        tables = new HashMap();
+        
+        try {
+            if (ttfAfm == null)
+                rf = new RandomAccessFileOrArray(fileName);
+            else
+                rf = new RandomAccessFileOrArray(ttfAfm);
+            if (ttcIndex.length() > 0) {
+                int dirIdx = Integer.parseInt(ttcIndex);
+                if (dirIdx < 0)
+                    throw new DocumentException("The font index for " + fileName + " must be positive.");
+                String mainTag = readStandardString(4);
+                if (!mainTag.equals("ttcf"))
+                    throw new DocumentException(fileName + " is not a valid TTC file.");
+                rf.skipBytes(4);
+                int dirCount = rf.readInt();
+                if (dirIdx >= dirCount)
+                    throw new DocumentException("The font index for " + fileName + " must be between 0 and " + (dirCount - 1) + ". It was " + dirIdx + ".");
+                rf.skipBytes(dirIdx * 4);
+                directoryOffset = rf.readInt();
+            }
+            rf.seek(directoryOffset);
+            int ttId = rf.readInt();
+            if (ttId != 0x00010000 && ttId != 0x4F54544F)
+                throw new DocumentException(fileName + " is not a valid TTF or OTF file.");
+            int num_tables = rf.readUnsignedShort();
+            rf.skipBytes(6);
+            for (int k = 0; k < num_tables; ++k) {
+                String tag = readStandardString(4);
+                rf.skipBytes(4);
+                int table_location[] = new int[2];
+                table_location[0] = rf.readInt();
+                table_location[1] = rf.readInt();
+                tables.put(tag, table_location);
+            }
+            checkCff();
+            fontName = getBaseFont();
+            fullName = getNames(4); //full name
+            familyName = getNames(1); //family name
+            if (!justNames) {
+                fillTables();
+                readGlyphWidths();
+                readCMaps();
+                readKerning();
+                readBbox();
+                GlyphWidths = null;
+            }
+        }
+        finally {
+            if (rf != null) {
+                rf.close();
+                if (!embedded)
+                    rf = null;
+            }
+        }
+    }
+    
+    /** Reads a <CODE>String</CODE> from the font file as bytes using the Cp1252
+     *  encoding.
+     * @param length the length of bytes to read
+     * @return the <CODE>String</CODE> read
+     * @throws IOException the font file could not be read
+     */
+    protected String readStandardString(int length) throws IOException {
+        byte buf[] = new byte[length];
+        rf.readFully(buf);
+        try {
+            return new String(buf, WINANSI);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    /** Reads a Unicode <CODE>String</CODE> from the font file. Each character is
+     *  represented by two bytes.
+     * @param length the length of bytes to read. The <CODE>String</CODE> will have <CODE>length</CODE>/2
+     * characters
+     * @return the <CODE>String</CODE> read
+     * @throws IOException the font file could not be read
+     */
+    protected String readUnicodeString(int length) throws IOException {
+        StringBuffer buf = new StringBuffer();
+        length /= 2;
+        for (int k = 0; k < length; ++k) {
+            buf.append(rf.readChar());
+        }
+        return buf.toString();
+    }
+    
+    /** Reads the glyphs widths. The widths are extracted from the table 'hmtx'.
+     *  The glyphs are normalized to 1000 units.
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    protected void readGlyphWidths() throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("hmtx");
+        if (table_location == null)
+            throw new DocumentException("Table 'hmtx' does not exist in " + fileName + style);
+        rf.seek(table_location[0]);
+        GlyphWidths = new int[hhea.numberOfHMetrics];
+        for (int k = 0; k < hhea.numberOfHMetrics; ++k) {
+            GlyphWidths[k] = (rf.readUnsignedShort() * 1000) / head.unitsPerEm;
+            rf.readUnsignedShort();
+        }
+    }
+    
+    /** Gets a glyph width.
+     * @param glyph the glyph to get the width of
+     * @return the width of the glyph in normalized 1000 units
+     */
+    protected int getGlyphWidth(int glyph) {
+        if (glyph >= GlyphWidths.length)
+            glyph = GlyphWidths.length - 1;
+        return GlyphWidths[glyph];
+    }
+    
+    private void readBbox() throws DocumentException, IOException {
+        int tableLocation[];
+        tableLocation = (int[])tables.get("head");
+        if (tableLocation == null)
+            throw new DocumentException("Table 'head' does not exist in " + fileName + style);
+        rf.seek(tableLocation[0] + TrueTypeFontSubSet.HEAD_LOCA_FORMAT_OFFSET);
+        boolean locaShortTable = (rf.readUnsignedShort() == 0);
+        tableLocation = (int[])tables.get("loca");
+        if (tableLocation == null)
+            return;
+        rf.seek(tableLocation[0]);
+        int locaTable[];
+        if (locaShortTable) {
+            int entries = tableLocation[1] / 2;
+            locaTable = new int[entries];
+            for (int k = 0; k < entries; ++k)
+                locaTable[k] = rf.readUnsignedShort() * 2;
+        }
+        else {
+            int entries = tableLocation[1] / 4;
+            locaTable = new int[entries];
+            for (int k = 0; k < entries; ++k)
+                locaTable[k] = rf.readInt();
+        }
+        tableLocation = (int[])tables.get("glyf");
+        if (tableLocation == null)
+            throw new DocumentException("Table 'glyf' does not exist in " + fileName + style);
+        int tableGlyphOffset = tableLocation[0];
+        bboxes = new int[locaTable.length - 1][];
+        for (int glyph = 0; glyph < locaTable.length - 1; ++glyph) {
+            int start = locaTable[glyph];
+            if (start != locaTable[glyph + 1]) {
+                rf.seek(tableGlyphOffset + start + 2);
+                bboxes[glyph] = new int[]{
+                    (rf.readShort() * 1000) / head.unitsPerEm,
+                    (rf.readShort() * 1000) / head.unitsPerEm,
+                    (rf.readShort() * 1000) / head.unitsPerEm,
+                    (rf.readShort() * 1000) / head.unitsPerEm};
+            }
+        }
+    }
+    
+    /** Reads the several maps from the table 'cmap'. The maps of interest are 1.0 for symbolic
+     *  fonts and 3.1 for all others. A symbolic font is defined as having the map 3.0.
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    void readCMaps() throws DocumentException, IOException {
+        int table_location[];
+        table_location = (int[])tables.get("cmap");
+        if (table_location == null)
+            throw new DocumentException("Table 'cmap' does not exist in " + fileName + style);
+        rf.seek(table_location[0]);
+        rf.skipBytes(2);
+        int num_tables = rf.readUnsignedShort();
+        fontSpecific = false;
+        int map10 = 0;
+        int map31 = 0;
+        int map30 = 0;
+        for (int k = 0; k < num_tables; ++k) {
+            int platId = rf.readUnsignedShort();
+            int platSpecId = rf.readUnsignedShort();
+            int offset = rf.readInt();
+            if (platId == 3 && platSpecId == 0) {
+                fontSpecific = true;
+                map30 = offset;
+            }
+            else if (platId == 3 && platSpecId == 1) {
+                map31 = offset;
+            }
+            if (platId == 1 && platSpecId == 0) {
+                map10 = offset;
+            }
+        }
+        if (map10 > 0) {
+            rf.seek(table_location[0] + map10);
+            int format = rf.readUnsignedShort();
+            switch (format) {
+                case 0:
+                    cmap10 = readFormat0();
+                    break;
+                case 4:
+                    cmap10 = readFormat4();
+                    break;
+                case 6:
+                    cmap10 = readFormat6();
+                    break;
+            }
+        }
+        if (map31 > 0) {
+            rf.seek(table_location[0] + map31);
+            int format = rf.readUnsignedShort();
+            if (format == 4) {
+                cmap31 = readFormat4();
+            }
+        }
+        if (map30 > 0) {
+            rf.seek(table_location[0] + map30);
+            int format = rf.readUnsignedShort();
+            if (format == 4) {
+                cmap10 = readFormat4();
+            }
+        }
+    }
+    
+    /** The information in the maps of the table 'cmap' is coded in several formats.
+     *  Format 0 is the Apple standard character to glyph index mapping table.
+     * @return a <CODE>HashMap</CODE> representing this map
+     * @throws IOException the font file could not be read
+     */
+    HashMap readFormat0() throws IOException {
+        HashMap h = new HashMap();
+        rf.skipBytes(4);
+        for (int k = 0; k < 256; ++k) {
+            int r[] = new int[2];
+            r[0] = rf.readUnsignedByte();
+            r[1] = getGlyphWidth(r[0]);
+            h.put(new Integer(k), r);
+        }
+        return h;
+    }
+    
+    /** The information in the maps of the table 'cmap' is coded in several formats.
+     *  Format 4 is the Microsoft standard character to glyph index mapping table.
+     * @return a <CODE>HashMap</CODE> representing this map
+     * @throws IOException the font file could not be read
+     */
+    HashMap readFormat4() throws IOException {
+        HashMap h = new HashMap();
+        int table_lenght = rf.readUnsignedShort();
+        rf.skipBytes(2);
+        int segCount = rf.readUnsignedShort() / 2;
+        rf.skipBytes(6);
+        int endCount[] = new int[segCount];
+        for (int k = 0; k < segCount; ++k) {
+            endCount[k] = rf.readUnsignedShort();
+        }
+        rf.skipBytes(2);
+        int startCount[] = new int[segCount];
+        for (int k = 0; k < segCount; ++k) {
+            startCount[k] = rf.readUnsignedShort();
+        }
+        int idDelta[] = new int[segCount];
+        for (int k = 0; k < segCount; ++k) {
+            idDelta[k] = rf.readUnsignedShort();
+        }
+        int idRO[] = new int[segCount];
+        for (int k = 0; k < segCount; ++k) {
+            idRO[k] = rf.readUnsignedShort();
+        }
+        int glyphId[] = new int[table_lenght / 2 - 8 - segCount * 4];
+        for (int k = 0; k < glyphId.length; ++k) {
+            glyphId[k] = rf.readUnsignedShort();
+        }
+        for (int k = 0; k < segCount; ++k) {
+            int glyph;
+            for (int j = startCount[k]; j <= endCount[k] && j != 0xFFFF; ++j) {
+                if (idRO[k] == 0) {
+                    glyph = (j + idDelta[k]) & 0xFFFF;
+                }
+                else {
+                    int idx = k + idRO[k] / 2 - segCount + j - startCount[k];
+                    if (idx >= glyphId.length)
+                        continue;
+                    glyph = (glyphId[idx] + idDelta[k]) & 0xFFFF;
+                }
+                int r[] = new int[2];
+                r[0] = glyph;
+                r[1] = getGlyphWidth(r[0]);
+                h.put(new Integer(fontSpecific ? ((j & 0xff00) == 0xf000 ? j & 0xff : j) : j), r);
+            }
+        }
+        return h;
+    }
+    
+    /** The information in the maps of the table 'cmap' is coded in several formats.
+     *  Format 6 is a trimmed table mapping. It is similar to format 0 but can have
+     *  less than 256 entries.
+     * @return a <CODE>HashMap</CODE> representing this map
+     * @throws IOException the font file could not be read
+     */
+    HashMap readFormat6() throws IOException {
+        HashMap h = new HashMap();
+        rf.skipBytes(4);
+        int start_code = rf.readUnsignedShort();
+        int code_count = rf.readUnsignedShort();
+        for (int k = 0; k < code_count; ++k) {
+            int r[] = new int[2];
+            r[0] = rf.readUnsignedShort();
+            r[1] = getGlyphWidth(r[0]);
+            h.put(new Integer(k + start_code), r);
+        }
+        return h;
+    }
+    
+    /** Reads the kerning information from the 'kern' table.
+     * @throws IOException the font file could not be read
+     */
+    void readKerning() throws IOException {
+        int table_location[];
+        table_location = (int[])tables.get("kern");
+        if (table_location == null)
+            return;
+        rf.seek(table_location[0] + 2);
+        int nTables = rf.readUnsignedShort();
+        int checkpoint = table_location[0] + 4;
+        int length = 0;
+        for (int k = 0; k < nTables; ++k) {
+            checkpoint += length;
+            rf.seek(checkpoint);
+            rf.skipBytes(2);
+            length = rf.readUnsignedShort();
+            int coverage = rf.readUnsignedShort();
+            if ((coverage & 0xfff7) == 0x0001) {
+                int nPairs = rf.readUnsignedShort();
+                rf.skipBytes(6);
+                for (int j = 0; j < nPairs; ++j) {
+                    int pair = rf.readInt();
+                    int value = ((int)rf.readShort() * 1000) / head.unitsPerEm;
+                    kerning.put(pair, value);
+                }
+            }
+        }
+    }
+    
+    /** Gets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @return the kerning to be applied
+     */
+    public int getKerning(char char1, char char2) {
+        int metrics[] = getMetricsTT(char1);
+        if (metrics == null)
+            return 0;
+        int c1 = metrics[0];
+        metrics = getMetricsTT(char2);
+        if (metrics == null)
+            return 0;
+        int c2 = metrics[0];
+        return kerning.get((c1 << 16) + c2);
+    }
+    
+    /** Gets the width from the font according to the unicode char <CODE>c</CODE>.
+     * If the <CODE>name</CODE> is null it's a symbolic font.
+     * @param c the unicode char
+     * @param name the glyph name
+     * @return the width of the char
+     */
+    int getRawWidth(int c, String name) {
+        HashMap map = null;
+        if (name == null || cmap31 == null)
+            map = cmap10;
+        else
+            map = cmap31;
+        if (map == null)
+            return 0;
+        int metric[] = (int[])map.get(new Integer(c));
+        if (metric == null)
+            return 0;
+        return metric[1];
+    }
+    
+    /** Generates the font descriptor for this font.
+     * @return the PdfDictionary containing the font descriptor or <CODE>null</CODE>
+     * @param subsetPrefix the subset prefix
+     * @param fontStream the indirect reference to a PdfStream containing the font or <CODE>null</CODE>
+     * @throws DocumentException if there is an error
+     */
+    protected PdfDictionary getFontDescriptor(PdfIndirectReference fontStream, String subsetPrefix) throws DocumentException {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+        dic.put(PdfName.ASCENT, new PdfNumber((int)os_2.sTypoAscender * 1000 / head.unitsPerEm));
+        dic.put(PdfName.CAPHEIGHT, new PdfNumber((int)os_2.sCapHeight * 1000 / head.unitsPerEm));
+        dic.put(PdfName.DESCENT, new PdfNumber((int)os_2.sTypoDescender * 1000 / head.unitsPerEm));
+        dic.put(PdfName.FONTBBOX, new PdfRectangle(
+        (int)head.xMin * 1000 / head.unitsPerEm,
+        (int)head.yMin * 1000 / head.unitsPerEm,
+        (int)head.xMax * 1000 / head.unitsPerEm,
+        (int)head.yMax * 1000 / head.unitsPerEm));
+        if (cff) {
+            if (encoding.startsWith("Identity-"))
+                dic.put(PdfName.FONTNAME, new PdfName(fontName+"-"+encoding));
+            else
+                dic.put(PdfName.FONTNAME, new PdfName(fontName + style));
+        }
+        else
+            dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName + style));
+        dic.put(PdfName.ITALICANGLE, new PdfNumber(italicAngle));
+        dic.put(PdfName.STEMV, new PdfNumber(80));
+        if (fontStream != null) {
+            if (cff)
+                dic.put(PdfName.FONTFILE3, fontStream);
+            else
+                dic.put(PdfName.FONTFILE2, fontStream);
+        }
+        int flags = 0;
+        if (isFixedPitch)
+            flags |= 1;
+        flags |= fontSpecific ? 4 : 32;
+        if ((head.macStyle & 2) != 0)
+            flags |= 64;
+        if ((head.macStyle & 1) != 0)
+            flags |= 262144;
+        dic.put(PdfName.FLAGS, new PdfNumber(flags));
+        
+        return dic;
+    }
+    
+    /** Generates the font dictionary for this font.
+     * @return the PdfDictionary containing the font dictionary
+     * @param subsetPrefix the subset prefx
+     * @param firstChar the first valid character
+     * @param lastChar the last valid character
+     * @param shortTag a 256 bytes long <CODE>byte</CODE> array where each unused byte is represented by 0
+     * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or <CODE>null</CODE>
+     * @throws DocumentException if there is an error
+     */
+    protected PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, String subsetPrefix, int firstChar, int lastChar, byte shortTag[]) throws DocumentException {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+        if (cff) {
+            dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
+            dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
+        }
+        else {
+            dic.put(PdfName.SUBTYPE, PdfName.TRUETYPE);
+            dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
+        }
+        dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
+        if (!fontSpecific) {
+            for (int k = firstChar; k <= lastChar; ++k) {
+                if (!differences[k].equals(notdef)) {
+                    firstChar = k;
+                    break;
+                }
+            }
+        if (encoding.equals("Cp1252") || encoding.equals("MacRoman"))
+                dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
+            else {
+                PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
+                PdfArray dif = new PdfArray();
+                boolean gap = true;                
+                for (int k = firstChar; k <= lastChar; ++k) {
+                    if (shortTag[k] != 0) {
+                        if (gap) {
+                            dif.add(new PdfNumber(k));
+                            gap = false;
+                        }
+                        dif.add(new PdfName(differences[k]));
+                    }
+                    else
+                        gap = true;
+                }
+                enc.put(PdfName.DIFFERENCES, dif);
+                dic.put(PdfName.ENCODING, enc);
+            }
+        }
+        dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
+        dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
+        PdfArray wd = new PdfArray();
+        for (int k = firstChar; k <= lastChar; ++k) {
+            if (shortTag[k] == 0)
+                wd.add(new PdfNumber(0));
+            else
+                wd.add(new PdfNumber(widths[k]));
+        }
+        dic.put(PdfName.WIDTHS, wd);
+        if (fontDescriptor != null)
+            dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+        return dic;
+    }
+    
+    private byte[] getFullFont() throws IOException {
+        RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+        rf2.reOpen();
+        byte b[] = new byte[rf2.length()];
+        rf2.readFully(b);
+        rf2.close();
+        return b;
+    }
+    
+    /** Outputs to the writer the font dictionaries and streams.
+     * @param writer the writer for this document
+     * @param ref the font indirect reference
+     * @param params several parameters that depend on the font type
+     * @throws IOException on error
+     * @throws DocumentException error in generating the object
+     */
+    void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+        int firstChar = ((Integer)params[0]).intValue();
+        int lastChar = ((Integer)params[1]).intValue();
+        byte shortTag[] = (byte[])params[2];
+        if (!subset) {
+            firstChar = 0;
+            lastChar = shortTag.length - 1;
+            for (int k = 0; k < shortTag.length; ++k)
+                shortTag[k] = 1;
+        }
+        PdfIndirectReference ind_font = null;
+        PdfObject pobj = null;
+        PdfIndirectObject obj = null;
+        String subsetPrefix = "";
+        if (embedded) {
+            if (cff) {
+                RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+                byte b[] = new byte[cffLength];
+                try {
+                    rf2.reOpen();
+                    rf2.seek(cffOffset);
+                    rf2.readFully(b);
+                }
+                finally {
+                    try {
+                        rf2.close();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                }
+                pobj = new StreamFont(b, "Type1C");
+                obj = writer.addToBody(pobj);
+                ind_font = obj.getIndirectReference();
+            }
+            else {
+                if (subset)
+                    subsetPrefix = createSubsetPrefix();
+                HashMap glyphs = new HashMap();
+                for (int k = firstChar; k <= lastChar; ++k) {
+                    if (shortTag[k] != 0) {
+                        int metrics[];
+                        if (fontSpecific)
+                            metrics = getMetricsTT(k);
+                        else
+                            metrics = getMetricsTT(unicodeDifferences[k]);
+                        if (metrics != null)
+                            glyphs.put(new Integer(metrics[0]), null);
+                    }
+                }
+                TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), glyphs, directoryOffset, true);
+                byte b[] = sb.process();
+                int lengths[] = new int[]{b.length};
+                pobj = new StreamFont(b, lengths);
+                obj = writer.addToBody(pobj);
+                ind_font = obj.getIndirectReference();
+            }
+        }
+        pobj = getFontDescriptor(ind_font, subsetPrefix);
+        if (pobj != null){
+            obj = writer.addToBody(pobj);
+            ind_font = obj.getIndirectReference();
+        }
+        pobj = getFontBaseType(ind_font, subsetPrefix, firstChar, lastChar, shortTag);
+        writer.addToBody(pobj, ref);
+    }
+    
+    /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
+     * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>
+     * and <CODE>ITALICANGLE</CODE>.
+     * @param key the parameter to be extracted
+     * @param fontSize the font size in points
+     * @return the parameter in points
+     */    
+    public float getFontDescriptor(int key, float fontSize) {
+        switch (key) {
+            case ASCENT:
+                return (float)os_2.sTypoAscender * fontSize / (float)head.unitsPerEm;
+            case CAPHEIGHT:
+                return (float)os_2.sCapHeight * fontSize / (float)head.unitsPerEm;
+            case DESCENT:
+                return (float)os_2.sTypoDescender * fontSize / (float)head.unitsPerEm;
+            case ITALICANGLE:
+                return (float)italicAngle;
+            case BBOXLLX:
+                return fontSize * (int)head.xMin / head.unitsPerEm;
+            case BBOXLLY:
+                return fontSize * (int)head.yMin / head.unitsPerEm;
+            case BBOXURX:
+                return fontSize * (int)head.xMax / head.unitsPerEm;
+            case BBOXURY:
+                return fontSize * (int)head.yMax / head.unitsPerEm;
+            case AWT_ASCENT:
+                return fontSize * (int)hhea.Ascender / head.unitsPerEm;
+            case AWT_DESCENT:
+                return fontSize * (int)hhea.Descender / head.unitsPerEm;
+            case AWT_LEADING:
+                return fontSize * (int)hhea.LineGap / head.unitsPerEm;
+            case AWT_MAXADVANCE:
+                return fontSize * (int)hhea.advanceWidthMax / head.unitsPerEm;
+        }
+        return 0;
+    }
+    
+    /** Gets the glyph index and metrics for a character.
+     * @param c the character
+     * @return an <CODE>int</CODE> array with {glyph index, width}
+     */    
+    public int[] getMetricsTT(int c) {
+        if (!fontSpecific && cmap31 != null) 
+            return (int[])cmap31.get(new Integer(c));
+        if (fontSpecific && cmap10 != null) 
+            return (int[])cmap10.get(new Integer(c));
+        if (cmap31 != null) 
+            return (int[])cmap31.get(new Integer(c));
+        if (cmap10 != null) 
+            return (int[])cmap10.get(new Integer(c));
+        return null;
+    }
+
+    /** Gets the postscript font name.
+     * @return the postscript font name
+     */
+    public String getPostscriptFontName() {
+        return fontName;
+    }
+
+    /** Gets the code pages supported by the font.
+     * @return the code pages supported by the font
+     */
+    public String[] getCodePagesSupported() {
+        long cp = (((long)os_2.ulCodePageRange2) << 32) + ((long)os_2.ulCodePageRange1 & 0xffffffffL);
+        int count = 0;
+        long bit = 1;
+        for (int k = 0; k < 64; ++k) {
+            if ((cp & bit) != 0 && codePages[k] != null)
+                ++count;
+            bit <<= 1;
+        }
+        String ret[] = new String[count];
+        count = 0;
+        bit = 1;
+        for (int k = 0; k < 64; ++k) {
+            if ((cp & bit) != 0 && codePages[k] != null)
+                ret[count++] = codePages[k];
+            bit <<= 1;
+        }
+        return ret;
+    }
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the full name of the font
+     */
+    public String[][] getFullFontName() {
+        return fullName;
+    }
+    
+    /** Gets the family name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the family name of the font
+     */
+    public String[][] getFamilyFontName() {
+        return familyName;
+    }
+    
+    /** Checks if the font has any kerning pairs.
+     * @return <CODE>true</CODE> if the font has any kerning pairs
+     */    
+    public boolean hasKernPairs() {
+        return kerning.size() > 0;
+    }    
+    
+    /**
+     * Sets the font name that will appear in the pdf font dictionary.
+     * Use with care as it can easily make a font unreadable if not embedded.
+     * @param name the new font name
+     */    
+    public void setPostscriptFontName(String name) {
+        fontName = name;
+    }
+    
+    /**
+     * Sets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @param kern the kerning to apply in normalized 1000 units
+     * @return <code>true</code> if the kerning was applied, <code>false</code> otherwise
+     */
+    public boolean setKerning(char char1, char char2, int kern) {
+        int metrics[] = getMetricsTT(char1);
+        if (metrics == null)
+            return false;
+        int c1 = metrics[0];
+        metrics = getMetricsTT(char2);
+        if (metrics == null)
+            return false;
+        int c2 = metrics[0];
+        kerning.put((c1 << 16) + c2, kern);
+        return true;
+    }
+    
+    protected int[] getRawCharBBox(int c, String name) {
+        HashMap map = null;
+        if (name == null || cmap31 == null)
+            map = cmap10;
+        else
+            map = cmap31;
+        if (map == null)
+            return null;
+        int metric[] = (int[])map.get(new Integer(c));
+        if (metric == null || bboxes == null)
+            return null;
+        return bboxes[metric[0]];
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/TrueTypeFontSubSet.java b/LibrarySource/com/lowagie/text/pdf/TrueTypeFontSubSet.java
new file mode 100644
index 0000000..9f8bc38
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/TrueTypeFontSubSet.java
@@ -0,0 +1,421 @@
+/*
+ * $Id: TrueTypeFontSubSet.java,v 1.15 2002/07/09 11:28:24 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+
+/** Subsets a True Type font by removing the unneeded glyphs from
+ * the font.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+class TrueTypeFontSubSet {
+    static final String tableNamesSimple[] = {"cvt ", "fpgm", "glyf", "head",
+        "hhea", "hmtx", "loca", "maxp", "prep"};
+    static final String tableNamesCmap[] = {"cmap", "cvt ", "fpgm", "glyf", "head",
+        "hhea", "hmtx", "loca", "maxp", "prep"};
+    static final int entrySelectors[] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4};
+    static final int TABLE_CHECKSUM = 0;
+    static final int TABLE_OFFSET = 1;
+    static final int TABLE_LENGTH = 2;
+    static final int HEAD_LOCA_FORMAT_OFFSET = 51;
+
+    static final int ARG_1_AND_2_ARE_WORDS = 1;
+    static final int WE_HAVE_A_SCALE = 8;
+    static final int MORE_COMPONENTS = 32;
+    static final int WE_HAVE_AN_X_AND_Y_SCALE = 64;
+    static final int WE_HAVE_A_TWO_BY_TWO = 128;
+    
+    
+    /** Contains the location of the several tables. The key is the name of
+     * the table and the value is an <CODE>int[3]</CODE> where position 0
+     * is the checksum, position 1 is the offset from the start of the file
+     * and position 2 is the length of the table.
+     */
+    protected HashMap tableDirectory;
+    /** The file in use.
+     */
+    protected RandomAccessFileOrArray rf;
+    /** The file name.
+     */
+    protected String fileName;
+    protected boolean includeCmap;
+    protected boolean locaShortTable;
+    protected int locaTable[];
+    protected HashMap glyphsUsed;
+    protected ArrayList glyphsInList;
+    protected int tableGlyphOffset;
+    protected int newLocaTable[];
+    protected byte newLocaTableOut[];
+    protected byte newGlyfTable[];
+    protected int glyfTableRealSize;
+    protected int locaTableRealSize;
+    protected byte outFont[];
+    protected int fontPtr;
+    protected int directoryOffset;
+
+    /** Creates a new TrueTypeFontSubSet
+     * @param directoryOffset The offset from the start of the file to the table directory
+     * @param fileName the file name of the font
+     * @param glyphsUsed the glyphs used
+     * @param includeCmap <CODE>true</CODE> if the table cmap is to be included in the generated font
+     */
+    TrueTypeFontSubSet(String fileName, RandomAccessFileOrArray rf, HashMap glyphsUsed, int directoryOffset, boolean includeCmap) {
+        this.fileName = fileName;
+        this.rf = rf;
+        this.glyphsUsed = glyphsUsed;
+        this.includeCmap = includeCmap;
+        this.directoryOffset = directoryOffset;
+        glyphsInList = new ArrayList(glyphsUsed.keySet());
+    }
+    
+    /** Does the actual work of subsetting the font.
+     * @throws IOException on error
+     * @throws DocumentException on error
+     * @return the subset font
+     */    
+    byte[] process() throws IOException, DocumentException {
+        try {
+            rf.reOpen();
+            createTableDirectory();
+            readLoca();
+            flatGlyphs();
+            createNewGlyphTables();
+            locaTobytes();
+            assembleFont();
+            return outFont;
+        }
+        finally {
+            try {
+                rf.close();
+            }
+            catch (Exception e) {
+                // empty on purpose
+            }
+        }
+    }
+    
+    protected void assembleFont() throws IOException, DocumentException {
+        int tableLocation[];
+        int fullFontSize = 0;
+        String tableNames[];
+        if (includeCmap)
+            tableNames = tableNamesCmap;
+        else
+            tableNames = tableNamesSimple;
+        int tablesUsed = 2;
+        int len = 0;
+        for (int k = 0; k < tableNames.length; ++k) {
+            String name = tableNames[k];
+            if (name.equals("glyf") || name.equals("loca"))
+                continue;
+            tableLocation = (int[])tableDirectory.get(name);
+            if (tableLocation == null)
+                continue;
+            ++tablesUsed;
+            fullFontSize += (tableLocation[TABLE_LENGTH] + 3) & (~3);
+        }
+        fullFontSize += newLocaTableOut.length;
+        fullFontSize += newGlyfTable.length;
+        int ref = 16 * tablesUsed + 12;
+        fullFontSize += ref;
+        outFont = new byte[fullFontSize];
+        fontPtr = 0;
+        writeFontInt(0x00010000);
+        writeFontShort(tablesUsed);
+        int selector = entrySelectors[tablesUsed];
+        writeFontShort((1 << selector) * 16);
+        writeFontShort(selector);
+        writeFontShort((tablesUsed - (1 << selector)) * 16);
+        for (int k = 0; k < tableNames.length; ++k) {
+            String name = tableNames[k];
+            tableLocation = (int[])tableDirectory.get(name);
+            if (tableLocation == null)
+                continue;
+            writeFontString(name);
+            if (name.equals("glyf")) {
+                writeFontInt(calculateChecksum(newGlyfTable));
+                len = glyfTableRealSize;
+            }
+            else if (name.equals("loca")) {
+                writeFontInt(calculateChecksum(newLocaTableOut));
+                len = locaTableRealSize;
+            }
+            else {
+                writeFontInt(tableLocation[TABLE_CHECKSUM]);
+                len = tableLocation[TABLE_LENGTH];
+            }
+            writeFontInt(ref);
+            writeFontInt(len);
+            ref += (len + 3) & (~3);
+        }
+        for (int k = 0; k < tableNames.length; ++k) {
+            String name = tableNames[k];
+            tableLocation = (int[])tableDirectory.get(name);
+            if (tableLocation == null)
+                continue;
+            if (name.equals("glyf")) {
+                System.arraycopy(newGlyfTable, 0, outFont, fontPtr, newGlyfTable.length);
+                fontPtr += newGlyfTable.length;
+                newGlyfTable = null;
+            }
+            else if (name.equals("loca")) {
+                System.arraycopy(newLocaTableOut, 0, outFont, fontPtr, newLocaTableOut.length);
+                fontPtr += newLocaTableOut.length;
+                newLocaTableOut = null;
+            }
+            else {
+                rf.seek(tableLocation[TABLE_OFFSET]);
+                rf.readFully(outFont, fontPtr, tableLocation[TABLE_LENGTH]);
+                fontPtr += (tableLocation[TABLE_LENGTH] + 3) & (~3);
+            }
+        }
+    }
+    
+    protected void createTableDirectory() throws IOException, DocumentException {
+        tableDirectory = new HashMap();
+        rf.seek(directoryOffset);
+        int id = rf.readInt();
+        if (id != 0x00010000)
+            throw new DocumentException(fileName + " is not a true type file.");
+        int num_tables = rf.readUnsignedShort();
+        rf.skipBytes(6);
+        for (int k = 0; k < num_tables; ++k) {
+            String tag = readStandardString(4);
+            int tableLocation[] = new int[3];
+            tableLocation[TABLE_CHECKSUM] = rf.readInt();
+            tableLocation[TABLE_OFFSET] = rf.readInt();
+            tableLocation[TABLE_LENGTH] = rf.readInt();
+            tableDirectory.put(tag, tableLocation);
+        }
+    }
+    
+    protected void readLoca() throws IOException, DocumentException {
+        int tableLocation[];
+        tableLocation = (int[])tableDirectory.get("head");
+        if (tableLocation == null)
+            throw new DocumentException("Table 'head' does not exist in " + fileName);
+        rf.seek(tableLocation[TABLE_OFFSET] + HEAD_LOCA_FORMAT_OFFSET);
+        locaShortTable = (rf.readUnsignedShort() == 0);
+        tableLocation = (int[])tableDirectory.get("loca");
+        if (tableLocation == null)
+            throw new DocumentException("Table 'loca' does not exist in " + fileName);
+        rf.seek(tableLocation[TABLE_OFFSET]);
+        if (locaShortTable) {
+            int entries = tableLocation[TABLE_LENGTH] / 2;
+            locaTable = new int[entries];
+            for (int k = 0; k < entries; ++k)
+                locaTable[k] = rf.readUnsignedShort() * 2;
+        }
+        else {
+            int entries = tableLocation[TABLE_LENGTH] / 4;
+            locaTable = new int[entries];
+            for (int k = 0; k < entries; ++k)
+                locaTable[k] = rf.readInt();
+        }
+    }
+    
+    protected void createNewGlyphTables() throws IOException {
+        newLocaTable = new int[locaTable.length];
+        int activeGlyphs[] = new int[glyphsInList.size()];
+        for (int k = 0; k < activeGlyphs.length; ++k)
+            activeGlyphs[k] = ((Integer)glyphsInList.get(k)).intValue();
+        Arrays.sort(activeGlyphs);
+        int glyfSize = 0;
+        for (int k = 0; k < activeGlyphs.length; ++k) {
+            int glyph = activeGlyphs[k];
+            glyfSize += locaTable[glyph + 1] - locaTable[glyph];
+        }
+        glyfTableRealSize = glyfSize;
+        glyfSize = (glyfSize + 3) & (~3);
+        newGlyfTable = new byte[glyfSize];
+        int glyfPtr = 0;
+        int listGlyf = 0;
+        for (int k = 0; k < newLocaTable.length; ++k) {
+            newLocaTable[k] = glyfPtr;
+            if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
+                ++listGlyf;
+                newLocaTable[k] = glyfPtr;
+                int start = locaTable[k];
+                int len = locaTable[k + 1] - start;
+                if (len > 0) {
+                    rf.seek(tableGlyphOffset + start);
+                    rf.readFully(newGlyfTable, glyfPtr, len);
+                    glyfPtr += len;
+                }
+            }
+        }
+    }
+    
+    protected void locaTobytes() {
+        if (locaShortTable)
+            locaTableRealSize = newLocaTable.length * 2;
+        else
+            locaTableRealSize = newLocaTable.length * 4;
+        newLocaTableOut = new byte[(locaTableRealSize + 3) & (~3)];
+        outFont = newLocaTableOut;
+        fontPtr = 0;
+        for (int k = 0; k < newLocaTable.length; ++k) {
+            if (locaShortTable)
+                writeFontShort(newLocaTable[k] / 2);
+            else
+                writeFontInt(newLocaTable[k]);
+        }
+        
+    }
+    
+    protected void flatGlyphs() throws IOException, DocumentException {
+        int tableLocation[];
+        tableLocation = (int[])tableDirectory.get("glyf");
+        if (tableLocation == null)
+            throw new DocumentException("Table 'glyf' does not exist in " + fileName);
+        Integer glyph0 = new Integer(0);
+        if (!glyphsUsed.containsKey(glyph0)) {
+            glyphsUsed.put(glyph0, null);
+            glyphsInList.add(glyph0);
+        }
+        tableGlyphOffset = tableLocation[TABLE_OFFSET];
+        for (int k = 0; k < glyphsInList.size(); ++k) {
+            int glyph = ((Integer)glyphsInList.get(k)).intValue();
+            checkGlyphComposite(glyph);
+        }
+    }
+
+    protected void checkGlyphComposite(int glyph) throws IOException {
+        int start = locaTable[glyph];
+        if (start == locaTable[glyph + 1]) // no contour
+            return;
+        rf.seek(tableGlyphOffset + start);
+        int numContours = rf.readShort();
+        if (numContours >= 0)
+            return;
+        rf.skipBytes(8);
+        for(;;) {
+            int flags = rf.readUnsignedShort();
+            Integer cGlyph = new Integer(rf.readUnsignedShort());
+            if (!glyphsUsed.containsKey(cGlyph)) {
+                glyphsUsed.put(cGlyph, null);
+                glyphsInList.add(cGlyph);
+            }
+            if ((flags & MORE_COMPONENTS) == 0)
+                return;
+            int skip;
+            if ((flags & ARG_1_AND_2_ARE_WORDS) != 0)
+                skip = 4;
+            else
+                skip = 2;
+            if ((flags & WE_HAVE_A_SCALE) != 0)
+                skip += 2;
+            else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
+                skip += 4;
+            if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
+                skip += 8;
+            rf.skipBytes(skip);
+        }
+    }
+    
+    /** Reads a <CODE>String</CODE> from the font file as bytes using the Cp1252
+     *  encoding.
+     * @param length the length of bytes to read
+     * @return the <CODE>String</CODE> read
+     * @throws IOException the font file could not be read
+     */
+    protected String readStandardString(int length) throws IOException {
+        byte buf[] = new byte[length];
+        rf.readFully(buf);
+        try {
+            return new String(buf, BaseFont.WINANSI);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    protected void writeFontShort(int n) {
+        outFont[fontPtr++] = (byte)(n >> 8);
+        outFont[fontPtr++] = (byte)(n);
+    }
+
+    protected void writeFontInt(int n) {
+        outFont[fontPtr++] = (byte)(n >> 24);
+        outFont[fontPtr++] = (byte)(n >> 16);
+        outFont[fontPtr++] = (byte)(n >> 8);
+        outFont[fontPtr++] = (byte)(n);
+    }
+
+    protected void writeFontString(String s) {
+        byte b[] = PdfEncodings.convertToBytes(s, BaseFont.WINANSI);
+        System.arraycopy(b, 0, outFont, fontPtr, b.length);
+        fontPtr += b.length;
+    }
+    
+    protected int calculateChecksum(byte b[]) {
+        int len = b.length / 4;
+        int v0 = 0;
+        int v1 = 0;
+        int v2 = 0;
+        int v3 = 0;
+        int ptr = 0;
+        for (int k = 0; k < len; ++k) {
+            v3 += (int)b[ptr++] & 0xff;
+            v2 += (int)b[ptr++] & 0xff;
+            v1 += (int)b[ptr++] & 0xff;
+            v0 += (int)b[ptr++] & 0xff;
+        }
+        return v0 + (v1 << 8) + (v2 << 16) + (v3 << 24);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/TrueTypeFontUnicode.java b/LibrarySource/com/lowagie/text/pdf/TrueTypeFontUnicode.java
new file mode 100644
index 0000000..51fb026
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/TrueTypeFontUnicode.java
@@ -0,0 +1,473 @@
+/*
+ * $Id: TrueTypeFontUnicode.java,v 1.3 2003/11/17 12:53:06 stoledo Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+
+import com.lowagie.text.DocumentException;
+/** Represents a True Type font with Unicode encoding. All the character
+ * in the font can be used directly by using the encoding Identity-H or
+ * Identity-V. This is the only way to represent some character sets such
+ * as Thai.
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+class TrueTypeFontUnicode extends TrueTypeFont implements Comparator{
+    
+    /** <CODE>true</CODE> if the encoding is vertical.
+     */    
+    boolean vertical = false;
+
+    /** Creates a new TrueType font addressed by Unicode characters. The font
+     * will always be embedded.
+     * @param ttFile the location of the font on file. The file must end in '.ttf'.
+     * The modifiers after the name are ignored.
+     * @param enc the encoding to be applied to this font
+     * @param emb true if the font is to be embedded in the PDF
+     * @param ttfAfm the font as a <CODE>byte</CODE> array
+     * @throws DocumentException the font is invalid
+     * @throws IOException the font file could not be read
+     */
+    TrueTypeFontUnicode(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
+        String nameBase = getBaseName(ttFile);
+        String ttcName = getTTCName(nameBase);
+        if (nameBase.length() < ttFile.length()) {
+            style = ttFile.substring(nameBase.length());
+        }
+        encoding = enc;
+        embedded = emb;
+        fileName = ttcName;
+        ttcIndex = "";
+        if (ttcName.length() < nameBase.length())
+            ttcIndex = nameBase.substring(ttcName.length() + 1);
+        fontType = FONT_TYPE_TTUNI;
+        if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)) && emb)) {
+            process(ttfAfm);
+            if (os_2.fsType == 2)
+                throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
+            // Sivan
+            if ((cmap31 == null && !fontSpecific) || (cmap10 == null && fontSpecific))
+                directTextToByte=true;
+                //throw new DocumentException(fileName + " " + style + " does not contain an usable cmap.");
+            if (fontSpecific) {
+                fontSpecific = false;
+                String tempEncoding = encoding;
+                encoding = "";
+                createEncoding();
+                encoding = tempEncoding;
+                fontSpecific = true;
+            }
+        }
+        else
+            throw new DocumentException(fileName + " " + style + " is not a TTF font file.");
+        vertical = enc.endsWith("V");
+    }
+    
+/**
+ * Gets the width of a <CODE>String</CODE> in normalized 1000 units.
+ * @param text the <CODE>String</CODE> to get the witdth of
+ * @return the width in normalized 1000 units
+ */
+    public int getWidth(String text)
+    {
+        if (vertical)
+            return text.length() * 1000;
+        int total = 0;
+        if (fontSpecific) {
+            char cc[] = text.toCharArray();
+            char ptr = 0;
+            int len = cc.length;
+            for (int k = 0; k < len; ++k) {
+                char c = cc[k];
+                if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+                    total += getRawWidth(c & 0xff, null);
+            }
+        }
+        else {
+            int len = text.length();
+            for (int k = 0; k < len; ++k)
+                total += getRawWidth(text.charAt(k), encoding);
+        }
+        return total;
+    }
+
+    /** Creates a ToUnicode CMap to allow copy and paste from Acrobat.
+     * @param metrics metrics[0] contains the glyph index and metrics[2]
+     * contains the Unicode code
+     * @throws DocumentException on error
+     * @return the stream representing this CMap or <CODE>null</CODE>
+     */    
+    private PdfStream getToUnicode(Object metrics[]) throws DocumentException {
+        if (metrics.length == 0)
+            return null;
+        StringBuffer buf = new StringBuffer(
+        "/CIDInit /ProcSet findresource begin\n" +
+        "12 dict begin\n" +
+        "begincmap\n" +
+        "/CIDSystemInfo\n" +
+        "<< /Registry (Adobe)\n" +
+        "/Ordering (UCS)\n" +
+        "/Supplement 0\n" +
+        ">> def\n" +
+        "/CMapName /Adobe-Identity-UCS def\n" +
+        "/CMapType 2 def\n" +
+        "1 begincodespacerange\n" +
+        toHex(((int[])metrics[0])[0]) + toHex(((int[])metrics[metrics.length - 1])[0]) + "\n" +
+        "endcodespacerange\n");
+        int size = 0;
+        for (int k = 0; k < metrics.length; ++k) {
+            if (size == 0) {
+                if (k != 0) {
+                    buf.append("endbfrange\n");
+                }
+                size = Math.min(100, metrics.length - k);
+                buf.append(size).append(" beginbfrange\n");
+            }
+            --size;
+            int metric[] = (int[])metrics[k];
+            String fromTo = toHex(metric[0]);
+            buf.append(fromTo).append(fromTo).append(toHex(metric[2])).append("\n");
+        }
+        buf.append(
+        "endbfrange\n" +
+        "endcmap\n" +
+        "CMapName currentdict /CMap defineresource pop\n" +
+        "end end\n");
+        String s = buf.toString();
+        PdfStream stream = new PdfStream(PdfEncodings.convertToBytes(s, null));
+        stream.flateCompress();
+        return stream;
+    }
+    
+    /** Gets an hex string in the format "<HHHH>".
+     * @param n the number
+     * @return the hex string
+     */    
+    static String toHex(int n) {
+        String s = Integer.toHexString(n);
+        return "<0000".substring(0, 5 - s.length()) + s + ">";
+    }
+    
+    /** Generates the CIDFontTyte2 dictionary.
+     * @param fontDescriptor the indirect reference to the font descriptor
+     * @param subsetPrefix the subset prefix
+     * @param metrics the horizontal width metrics
+     * @return a stream
+     */    
+    private PdfDictionary getCIDFontType2(PdfIndirectReference fontDescriptor, String subsetPrefix, Object metrics[]) {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+        // sivan; cff
+        if (cff) {
+			dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
+            dic.put(PdfName.BASEFONT, new PdfName(fontName+"-"+encoding));
+        }
+		else {
+			dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE2);
+            dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
+        }
+        dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+        if (!cff)
+          dic.put(PdfName.CIDTOGIDMAP,PdfName.IDENTITY);
+        PdfDictionary cdic = new PdfDictionary();
+        cdic.put(PdfName.REGISTRY, new PdfString("Adobe"));
+        cdic.put(PdfName.ORDERING, new PdfString("Identity"));
+        cdic.put(PdfName.SUPPLEMENT, new PdfNumber(0));
+        dic.put(PdfName.CIDSYSTEMINFO, cdic);
+        if (!vertical) {
+            dic.put(PdfName.DW, new PdfNumber(1000));
+            StringBuffer buf = new StringBuffer("[");
+            int lastNumber = -10;
+            boolean firstTime = true;
+            for (int k = 0; k < metrics.length; ++k) {
+                int metric[] = (int[])metrics[k];
+                if (metric[1] == 1000)
+                    continue;
+                int m = metric[0];
+                if (m == lastNumber + 1) {
+                    buf.append(" ").append(metric[1]);
+                }
+                else {
+                    if (!firstTime) {
+                        buf.append("]");
+                    }
+                    firstTime = false;
+                    buf.append(m).append("[").append(metric[1]);
+                }
+                lastNumber = m;
+            }
+            if (buf.length() > 1) {
+                buf.append("]]");
+                dic.put(PdfName.W, new PdfLiteral(buf.toString()));
+            }
+        }
+        return dic;
+    }
+    
+    /** Generates the font dictionary.
+     * @param descendant the descendant dictionary
+     * @param subsetPrefix the subset prefix
+     * @param toUnicode the ToUnicode stream
+     * @return the stream
+     */    
+    private PdfDictionary getFontBaseType(PdfIndirectReference descendant, String subsetPrefix, PdfIndirectReference toUnicode) {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+
+        dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
+        // The PDF Reference manual advises to add -encoding to CID font names
+		if (cff)
+		  dic.put(PdfName.BASEFONT, new PdfName(fontName+"-"+encoding));
+		  //dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName));
+		else
+		  dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
+		  //dic.put(PdfName.BASEFONT, new PdfName(fontName));
+        dic.put(PdfName.ENCODING, new PdfName(encoding));
+        dic.put(PdfName.DESCENDANTFONTS, new PdfArray(descendant));
+        if (toUnicode != null)
+            dic.put(PdfName.TOUNICODE, toUnicode);  
+        return dic;
+    }
+
+    /** The method used to sort the metrics array.
+     * @param o1 the first element
+     * @param o2 the second element
+     * @return the comparisation
+     */    
+    public int compare(Object o1, Object o2) {
+        int m1 = ((int[])o1)[0];
+        int m2 = ((int[])o2)[0];
+        if (m1 < m2)
+            return -1;
+        if (m1 == m2)
+            return 0;
+        return 1;
+    }
+
+    /** Outputs to the writer the font dictionaries and streams.
+     * @param writer the writer for this document
+     * @param ref the font indirect reference
+     * @param params several parameters that depend on the font type
+     * @throws IOException on error
+     * @throws DocumentException error in generating the object
+     */
+    void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+        HashMap longTag = (HashMap)params[0];
+        Object metrics[] = longTag.values().toArray();
+        Arrays.sort(metrics, this);
+        PdfIndirectReference ind_font = null;
+        PdfObject pobj = null;
+        PdfIndirectObject obj = null;
+        // sivan: cff
+        if (cff) {
+			RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+			byte b[] = new byte[cffLength];
+			try {
+				rf2.reOpen();
+				rf2.seek(cffOffset);
+				rf2.readFully(b);
+			} finally {
+				try {
+					rf2.close();
+				} catch (Exception e) {
+					// empty on purpose
+				}
+			}
+			/*
+			CFFFont cffFont = new CFFFont(new RandomAccessFileOrArray(b));
+			// test if we can find the font by name and if it's a type1 CFF
+			if (cffFont.exists(fontName) && !cffFont.isCID(fontName)) {
+				byte[] cid = cffFont.getCID( (cffFont.getNames())[0] );
+				if (cid != null) b=cid;
+			}
+			
+			*/
+			
+			CFFFontSubset cff = new CFFFontSubset(new RandomAccessFileOrArray(b),longTag);
+			b = cff.Process( (cff.getNames())[0] );
+			
+			// if the font is already CID, or not found by name, or 
+			// getCID returned null, we just use the data in the CFF
+			// table and hope for the best.
+		  
+				
+			// for debugging, force a reparsing
+			/*
+			java.lang.System.err.println("");
+			java.lang.System.err.println("");
+			java.lang.System.err.println("");
+			CFFFont dummy = new CFFFont(java.nio.ByteBuffer.wrap(b));	
+			java.lang.System.err.println("");
+			java.lang.System.err.println("");
+			java.lang.System.err.println("");
+			*/	
+			pobj = new StreamFont(b, "CIDFontType0C");
+			obj = writer.addToBody(pobj);
+			ind_font = obj.getIndirectReference();
+        } else {
+          TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), longTag, directoryOffset, false);
+          byte b[] = sb.process();
+          int lengths[] = new int[]{b.length};
+          pobj = new StreamFont(b, lengths);
+          obj = writer.addToBody(pobj);
+          ind_font = obj.getIndirectReference();
+        }
+        String subsetPrefix = createSubsetPrefix();
+        //if (cff) subsetPrefix = "";
+        PdfDictionary dic = getFontDescriptor(ind_font, subsetPrefix);
+        obj = writer.addToBody(dic);
+        ind_font = obj.getIndirectReference();
+
+        pobj = getCIDFontType2(ind_font, subsetPrefix, metrics);
+        obj = writer.addToBody(pobj);
+        ind_font = obj.getIndirectReference();
+
+        pobj = getToUnicode(metrics);
+        PdfIndirectReference toUnicodeRef = null;
+        
+        if (pobj != null) {
+            obj = writer.addToBody(pobj);
+            toUnicodeRef = obj.getIndirectReference();
+        }
+
+        pobj = getFontBaseType(ind_font, subsetPrefix, toUnicodeRef);
+        writer.addToBody(pobj, ref);
+    }
+
+    /** A forbidden operation. Will throw a null pointer exception.
+     * @param text the text
+     * @return always <CODE>null</CODE>
+     */    
+    byte[] convertToBytes(String text)
+    {
+        return null;
+    }
+
+    /**
+     * Checks if a character exists in this font.
+     * @param c the character to check
+     * @return <CODE>true</CODE> if the character has a glyph,
+     * <CODE>false</CODE> otherwise
+     */
+    public boolean charExists(char c) {
+        HashMap map = null;
+        if (fontSpecific)
+            map = cmap10;
+        else
+            map = cmap31;
+        if (map == null)
+            return false;
+        if (fontSpecific) {
+            if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+                return map.get(new Integer(c & 0xff)) != null;
+            else
+                return false;
+        }
+        else
+            return map.get(new Integer(c)) != null;
+    }
+    
+    /**
+     * Sets the character advance.
+     * @param c the character
+     * @param advance the character advance normalized to 1000 units
+     * @return <CODE>true</CODE> if the advance was set,
+     * <CODE>false</CODE> otherwise
+     */
+    public boolean setCharAdvance(char c, int advance) {
+        HashMap map = null;
+        if (fontSpecific)
+            map = cmap10;
+        else
+            map = cmap31;
+        if (map == null)
+            return false;
+        int m[] = null;
+        if (fontSpecific) {
+            if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+                m = (int[])map.get(new Integer(c & 0xff));
+            else
+                return false;
+        }
+        else
+            m = (int[])map.get(new Integer(c));
+        if (m == null)
+            return false;
+        else
+            m[1] = advance;
+        return true;
+    }
+    
+    public int[] getCharBBox(char c) {
+        if (bboxes == null)
+            return null;
+        HashMap map = null;
+        if (fontSpecific)
+            map = cmap10;
+        else
+            map = cmap31;
+        if (map == null)
+            return null;
+        int m[] = null;
+        if (fontSpecific) {
+            if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+                m = (int[])map.get(new Integer(c & 0xff));
+            else
+                return null;
+        }
+        else
+            m = (int[])map.get(new Integer(c));
+        if (m == null)
+            return null;
+        return bboxes[m[0]];
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/Type1Font.java b/LibrarySource/com/lowagie/text/pdf/Type1Font.java
new file mode 100644
index 0000000..fb13693
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/Type1Font.java
@@ -0,0 +1,808 @@
+/*
+ * $Id: Type1Font.java,v 1.59 2004/12/14 15:16:00 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.DocumentException;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import com.lowagie.text.pdf.fonts.FontsResourceAnchor;
+import java.io.*;
+
+/** Reads a Type1 font
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+class Type1Font extends BaseFont
+{
+    private static FontsResourceAnchor resourceAnchor;
+    
+    /** The PFB file if the input was made with a <CODE>byte</CODE> array.
+     */    
+    protected byte pfb[];
+/** The Postscript font name.
+ */
+    private String FontName;
+/** The full name of the font.
+ */
+    private String FullName;
+/** The family name of the font.
+ */
+    private String FamilyName;
+/** The weight of the font: normal, bold, etc.
+ */
+    private String Weight = "";
+/** The italic angle of the font, usually 0.0 or negative.
+ */
+    private float ItalicAngle = 0.0f;
+/** <CODE>true</CODE> if all the characters have the same
+ *  width.
+ */
+    private boolean IsFixedPitch = false;
+/** The character set of the font.
+ */
+    private String CharacterSet;
+/** The llx of the FontBox.
+ */
+    private int llx = -50;
+/** The lly of the FontBox.
+ */
+    private int lly = -200;
+/** The lurx of the FontBox.
+ */
+    private int urx = 1000;
+/** The ury of the FontBox.
+ */
+    private int ury = 900;
+/** The underline position.
+ */
+    private int UnderlinePosition = -100;
+/** The underline thickness.
+ */
+    private int UnderlineThickness = 50;
+/** The font's encoding name. This encoding is 'StandardEncoding' or
+ *  'AdobeStandardEncoding' for a font that can be totally encoded
+ *  according to the characters names. For all other names the
+ *  font is treated as symbolic.
+ */
+    private String EncodingScheme = "FontSpecific";
+/** A variable.
+ */
+    private int CapHeight = 700;
+/** A variable.
+ */
+    private int XHeight = 480;
+/** A variable.
+ */
+    private int Ascender = 800;
+/** A variable.
+ */
+    private int Descender = -200;
+/** A variable.
+ */
+    private int StdHW;
+/** A variable.
+ */
+    private int StdVW = 80;
+    
+/** Represents the section CharMetrics in the AFM file. Each
+ *  value of this array contains a <CODE>Object[4]</CODE> with an
+ *  Integer, Integer, String and int[]. This is the code, width, name and char bbox.
+ *  The key is the name of the char and also an Integer with the char number.
+ */
+    private HashMap CharMetrics = new HashMap();
+/** Represents the section KernPairs in the AFM file. The key is
+ *  the name of the first character and the value is a <CODE>Object[]</CODE>
+ *  with 2 elements for each kern pair. Position 0 is the name of
+ *  the second character and position 1 is the kerning distance. This is
+ *  repeated for all the pairs.
+ */
+    private HashMap KernPairs = new HashMap();
+/** The file in use.
+ */
+    private String fileName;
+/** <CODE>true</CODE> if this font is one of the 14 built in fonts.
+ */
+    private boolean builtinFont = false;
+/** Types of records in a PFB file. ASCII is 1 and BINARY is 2.
+ *  They have to appear in the PFB file in this sequence.
+ */
+    private static final int pfbTypes[] = {1, 2, 1};
+    
+    /** Creates a new Type1 font.
+     * @param ttfAfm the AFM file if the input is made with a <CODE>byte</CODE> array
+     * @param pfb the PFB file if the input is made with a <CODE>byte</CODE> array
+     * @param afmFile the name of one of the 14 built-in fonts or the location of an AFM file. The file must end in '.afm'
+     * @param enc the encoding to be applied to this font
+     * @param emb true if the font is to be embedded in the PDF
+     * @throws DocumentException the AFM file is invalid
+     * @throws IOException the AFM file could not be read
+     */
+    Type1Font(String afmFile, String enc, boolean emb, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException
+    {
+        if (emb && ttfAfm != null && pfb == null)
+            throw new DocumentException("Two byte arrays are needed if the Type1 font is embedded.");
+        if (emb && ttfAfm != null)
+            this.pfb = pfb;
+        encoding = enc;
+        embedded = emb;
+        fileName = afmFile;
+        fontType = FONT_TYPE_T1;
+        RandomAccessFileOrArray rf = null;
+        InputStream is = null;
+        if (BuiltinFonts14.containsKey(afmFile)) {
+            embedded = false;
+            builtinFont = true;
+            byte buf[] = new byte[1024];
+            try {
+                if (resourceAnchor == null)
+                    resourceAnchor = new FontsResourceAnchor();
+                is = getResourceStream(RESOURCE_PATH + afmFile + ".afm", resourceAnchor.getClass().getClassLoader());
+                if (is == null) {
+                    String msg = afmFile + " not found as resource. (The *.afm files must exist as resources in the package com.lowagie.text.pdf.fonts)";
+                    System.err.println(msg);
+                    throw new DocumentException(msg);
+                }
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                while (true) {
+                    int size = is.read(buf);
+                    if (size < 0)
+                        break;
+                    out.write(buf, 0, size);
+                }
+                buf = out.toByteArray();
+            }
+            finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                }
+            }
+            try {
+                rf = new RandomAccessFileOrArray(buf);
+                process(rf);
+            }
+            finally {
+                if (rf != null) {
+                    try {
+                        rf.close();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                }
+            }
+        }
+        else if (afmFile.toLowerCase().endsWith(".afm")) {
+            try {
+                if (ttfAfm == null)
+                    rf = new RandomAccessFileOrArray(afmFile);
+                else
+                    rf = new RandomAccessFileOrArray(ttfAfm);
+                process(rf);
+            }
+            finally {
+                if (rf != null) {
+                    try {
+                        rf.close();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                }
+            }
+        }
+        else if (afmFile.toLowerCase().endsWith(".pfm")) {
+            try {
+                ByteArrayOutputStream ba = new ByteArrayOutputStream();
+                if (ttfAfm == null)
+                    rf = new RandomAccessFileOrArray(afmFile);
+                else
+                    rf = new RandomAccessFileOrArray(ttfAfm);
+                Pfm2afm.convert(rf, ba);
+                rf.close();
+                rf = new RandomAccessFileOrArray(ba.toByteArray());
+                process(rf);
+            }
+            finally {
+                if (rf != null) {
+                    try {
+                        rf.close();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                }
+            }
+        }
+        else
+            throw new DocumentException(afmFile + " is not an AFM or PFM font file.");
+        try {
+            EncodingScheme = EncodingScheme.trim();
+            if (EncodingScheme.equals("AdobeStandardEncoding") || EncodingScheme.equals("StandardEncoding")) {
+                fontSpecific = false;
+            }
+            PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
+            createEncoding();
+        }
+        catch (RuntimeException re) {
+            throw re;
+        }
+        catch (Exception e) {
+            throw new DocumentException(e);
+        }
+    }
+    
+/** Gets the width from the font according to the <CODE>name</CODE> or,
+ * if the <CODE>name</CODE> is null, meaning it is a symbolic font,
+ * the char <CODE>c</CODE>.
+ * @param c the char if the font is symbolic
+ * @param name the glyph name
+ * @return the width of the char
+ */
+    int getRawWidth(int c, String name) {
+        Object metrics[];
+        if (name == null) { // font specific
+            metrics = (Object[])CharMetrics.get(new Integer(c));
+        }
+        else {
+            if (name.equals(".notdef"))
+                return 0;
+            metrics = (Object[])CharMetrics.get(name);
+        }
+        if (metrics != null)
+            return ((Integer)(metrics[1])).intValue();
+        return 0;
+    }
+    
+/** Gets the kerning between two Unicode characters. The characters
+ * are converted to names and this names are used to find the kerning
+ * pairs in the <CODE>HashMap</CODE> <CODE>KernPairs</CODE>.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @return the kerning to be applied
+ */
+    public int getKerning(char char1, char char2)
+    {
+        String first = GlyphList.unicodeToName((int)char1);
+        if (first == null)
+            return 0;
+        String second = GlyphList.unicodeToName((int)char2);
+        if (second == null)
+            return 0;
+        Object obj[] = (Object[])KernPairs.get(first);
+        if (obj == null)
+            return 0;
+        for (int k = 0; k < obj.length; k += 2) {
+            if (second.equals(obj[k]))
+                return ((Integer)obj[k + 1]).intValue();
+        }
+        return 0;
+    }
+    
+    
+    /** Reads the font metrics
+     * @param rf the AFM file
+     * @throws DocumentException the AFM file is invalid
+     * @throws IOException the AFM file could not be read
+     */
+    public void process(RandomAccessFileOrArray rf) throws DocumentException, IOException
+    {
+        String line;
+        boolean isMetrics = false;
+        while ((line = rf.readLine()) != null)
+        {
+            StringTokenizer tok = new StringTokenizer(line);
+            if (!tok.hasMoreTokens())
+                continue;
+            String ident = tok.nextToken();
+            if (ident.equals("FontName"))
+                FontName = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("FullName"))
+                FullName = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("FamilyName"))
+                FamilyName = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("Weight"))
+                Weight = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("ItalicAngle"))
+                ItalicAngle = Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("IsFixedPitch"))
+                IsFixedPitch = tok.nextToken().equals("true");
+            else if (ident.equals("CharacterSet"))
+                CharacterSet = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("FontBBox"))
+            {
+                llx = (int)Float.valueOf(tok.nextToken()).floatValue();
+                lly = (int)Float.valueOf(tok.nextToken()).floatValue();
+                urx = (int)Float.valueOf(tok.nextToken()).floatValue();
+                ury = (int)Float.valueOf(tok.nextToken()).floatValue();
+            }
+            else if (ident.equals("UnderlinePosition"))
+                UnderlinePosition = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("UnderlineThickness"))
+                UnderlineThickness = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("EncodingScheme"))
+                EncodingScheme = tok.nextToken("\u00ff").substring(1);
+            else if (ident.equals("CapHeight"))
+                CapHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("XHeight"))
+                XHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("Ascender"))
+                Ascender = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("Descender"))
+                Descender = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("StdHW"))
+                StdHW = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("StdVW"))
+                StdVW = (int)Float.valueOf(tok.nextToken()).floatValue();
+            else if (ident.equals("StartCharMetrics"))
+            {
+                isMetrics = true;
+                break;
+            }
+        }
+        if (!isMetrics)
+            throw new DocumentException("Missing StartCharMetrics in " + fileName);
+        while ((line = rf.readLine()) != null)
+        {
+            StringTokenizer tok = new StringTokenizer(line);
+            if (!tok.hasMoreTokens())
+                continue;
+            String ident = tok.nextToken();
+            if (ident.equals("EndCharMetrics"))
+            {
+                isMetrics = false;
+                break;
+            }
+            Integer C = new Integer(-1);
+            Integer WX = new Integer(250);
+            String N = "";
+            int B[] = null;
+
+            tok = new StringTokenizer(line, ";");
+            while (tok.hasMoreTokens())
+            {
+                StringTokenizer tokc = new StringTokenizer(tok.nextToken());
+                if (!tokc.hasMoreTokens())
+                    continue;
+                ident = tokc.nextToken();
+                if (ident.equals("C"))
+                    C = Integer.valueOf(tokc.nextToken());
+                else if (ident.equals("WX"))
+                    WX = new Integer(Float.valueOf(tokc.nextToken()).intValue());
+                else if (ident.equals("N"))
+                    N = tokc.nextToken();
+                else if (ident.equals("B")) {
+                    B = new int[]{Integer.parseInt(tokc.nextToken()), 
+                                         Integer.parseInt(tokc.nextToken()),
+                                         Integer.parseInt(tokc.nextToken()),
+                                         Integer.parseInt(tokc.nextToken())};
+                }
+            }
+            Object metrics[] = new Object[]{C, WX, N, B};
+            if (C.intValue() >= 0)
+                CharMetrics.put(C, metrics);
+            CharMetrics.put(N, metrics);
+        }
+        if (isMetrics)
+            throw new DocumentException("Missing EndCharMetrics in " + fileName);
+        while ((line = rf.readLine()) != null)
+        {
+            StringTokenizer tok = new StringTokenizer(line);
+            if (!tok.hasMoreTokens())
+                continue;
+            String ident = tok.nextToken();
+            if (ident.equals("EndFontMetrics"))
+                return;
+            if (ident.equals("StartKernPairs"))
+            {
+                isMetrics = true;
+                break;
+            }
+        }
+        if (!isMetrics)
+            throw new DocumentException("Missing EndFontMetrics in " + fileName);
+        while ((line = rf.readLine()) != null)
+        {
+            StringTokenizer tok = new StringTokenizer(line);
+            if (!tok.hasMoreTokens())
+                continue;
+            String ident = tok.nextToken();
+            if (ident.equals("KPX"))
+            {
+                String first = tok.nextToken();
+                String second = tok.nextToken();
+                Integer width = new Integer(Float.valueOf(tok.nextToken()).intValue());
+                Object relates[] = (Object[])KernPairs.get(first);
+                if (relates == null)
+                    KernPairs.put(first, new Object[]{second, width});
+                else
+                {
+                    int n = relates.length;
+                    Object relates2[] = new Object[n + 2];
+                    System.arraycopy(relates, 0, relates2, 0, n);
+                    relates2[n] = second;
+                    relates2[n + 1] = width;
+                    KernPairs.put(first, relates2);
+                }
+            }
+            else if (ident.equals("EndKernPairs"))
+            {
+                isMetrics = false;
+                break;
+            }
+        }
+        if (isMetrics)
+            throw new DocumentException("Missing EndKernPairs in " + fileName);
+        rf.close();
+    }
+    
+/** If the embedded flag is <CODE>false</CODE> or if the font is
+ *  one of the 14 built in types, it returns <CODE>null</CODE>,
+ * otherwise the font is read and output in a PdfStream object.
+ * @return the PdfStream containing the font or <CODE>null</CODE>
+ * @throws DocumentException if there is an error reading the font
+ */
+    private PdfStream getFontStream() throws DocumentException
+    {
+        if (builtinFont || !embedded)
+            return null;
+        RandomAccessFileOrArray rf = null;
+        try {
+            String filePfb = fileName.substring(0, fileName.length() - 3) + "pfb";
+            if (pfb == null)
+                rf = new RandomAccessFileOrArray(filePfb);
+            else
+                rf = new RandomAccessFileOrArray(pfb);
+            int fileLength = rf.length();
+            byte st[] = new byte[fileLength - 18];
+            int lengths[] = new int[3];
+            int bytePtr = 0;
+            for (int k = 0; k < 3; ++k) {
+                if (rf.read() != 0x80)
+                    throw new DocumentException("Start marker missing in " + filePfb);
+                if (rf.read() != pfbTypes[k])
+                    throw new DocumentException("Incorrect segment type in " + filePfb);
+                int size = rf.read();
+                size += rf.read() << 8;
+                size += rf.read() << 16;
+                size += rf.read() << 24;
+                lengths[k] = size;
+                while (size != 0) {
+                    int got = rf.read(st, bytePtr, size);
+                    if (got < 0)
+                        throw new DocumentException("Premature end in " + filePfb);
+                    bytePtr += got;
+                    size -= got;
+                }
+            }
+            return new StreamFont(st, lengths);
+        }
+        catch (Exception e) {
+            throw new DocumentException(e);
+        }
+        finally {
+            if (rf != null) {
+                try {
+                    rf.close();
+                }
+                catch (Exception e) {
+                    // empty on purpose
+                }
+            }
+        }
+    }
+    
+/** Generates the font descriptor for this font or <CODE>null</CODE> if it is
+ * one of the 14 built in fonts.
+ * @param fontStream the indirect reference to a PdfStream containing the font or <CODE>null</CODE>
+ * @return the PdfDictionary containing the font descriptor or <CODE>null</CODE>
+ */
+    private PdfDictionary getFontDescriptor(PdfIndirectReference fontStream)
+    {
+        if (builtinFont)
+            return null;
+        PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+        dic.put(PdfName.ASCENT, new PdfNumber(Ascender));
+        dic.put(PdfName.CAPHEIGHT, new PdfNumber(CapHeight));
+        dic.put(PdfName.DESCENT, new PdfNumber(Descender));
+        dic.put(PdfName.FONTBBOX, new PdfRectangle(llx, lly, urx, ury));
+        dic.put(PdfName.FONTNAME, new PdfName(FontName));
+        dic.put(PdfName.ITALICANGLE, new PdfNumber(ItalicAngle));
+        dic.put(PdfName.STEMV, new PdfNumber(StdVW));
+        if (fontStream != null)
+            dic.put(PdfName.FONTFILE, fontStream);
+        int flags = 0;
+        if (IsFixedPitch)
+            flags |= 1;
+        flags |= fontSpecific ? 4 : 32;
+        if (ItalicAngle < 0)
+            flags |= 64;
+        if (FontName.indexOf("Caps") >= 0 || FontName.endsWith("SC"))
+            flags |= 131072;
+        if (Weight.equals("Bold"))
+            flags |= 262144;
+        dic.put(PdfName.FLAGS, new PdfNumber(flags));
+        
+        return dic;
+    }
+    
+    /** Generates the font dictionary for this font.
+     * @return the PdfDictionary containing the font dictionary
+     * @param firstChar the first valid character
+     * @param lastChar the last valid character
+     * @param shortTag a 256 bytes long <CODE>byte</CODE> array where each unused byte is represented by 0
+     * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or <CODE>null</CODE>
+     */
+    private PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, int firstChar, int lastChar, byte shortTag[])
+    {
+        PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+        dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
+        dic.put(PdfName.BASEFONT, new PdfName(FontName));
+        boolean stdEncoding = encoding.equals("Cp1252") || encoding.equals("MacRoman");
+        if (!fontSpecific) {
+            for (int k = firstChar; k <= lastChar; ++k) {
+                if (!differences[k].equals(notdef)) {
+                    firstChar = k;
+                    break;
+                }
+            }
+            if (stdEncoding)
+                dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
+            else {
+                PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
+                PdfArray dif = new PdfArray();
+                boolean gap = true;                
+                for (int k = firstChar; k <= lastChar; ++k) {
+                    if (shortTag[k] != 0) {
+                        if (gap) {
+                            dif.add(new PdfNumber(k));
+                            gap = false;
+                        }
+                        dif.add(new PdfName(differences[k]));
+                    }
+                    else
+                        gap = true;
+                }
+                enc.put(PdfName.DIFFERENCES, dif);
+                dic.put(PdfName.ENCODING, enc);
+            }
+        }
+        if (forceWidthsOutput || !(builtinFont && (fontSpecific || stdEncoding))) {
+            dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
+            dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
+            PdfArray wd = new PdfArray();
+            for (int k = firstChar; k <= lastChar; ++k) {
+                if (shortTag[k] == 0)
+                    wd.add(new PdfNumber(0));
+                else
+                    wd.add(new PdfNumber(widths[k]));
+            }
+            dic.put(PdfName.WIDTHS, wd);
+        }
+        if (!builtinFont && fontDescriptor != null)
+            dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+        return dic;
+    }
+    
+    /** Outputs to the writer the font dictionaries and streams.
+     * @param writer the writer for this document
+     * @param ref the font indirect reference
+     * @param params several parameters that depend on the font type
+     * @throws IOException on error
+     * @throws DocumentException error in generating the object
+     */
+    void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+        int firstChar = ((Integer)params[0]).intValue();
+        int lastChar = ((Integer)params[1]).intValue();
+        byte shortTag[] = (byte[])params[2];
+        if (!subset) {
+            firstChar = 0;
+            lastChar = shortTag.length - 1;
+            for (int k = 0; k < shortTag.length; ++k)
+                shortTag[k] = 1;
+        }
+        PdfIndirectReference ind_font = null;
+        PdfObject pobj = null;
+        PdfIndirectObject obj = null;
+        pobj = getFontStream();
+        if (pobj != null){
+            obj = writer.addToBody(pobj);
+            ind_font = obj.getIndirectReference();
+        }
+        pobj = getFontDescriptor(ind_font);
+        if (pobj != null){
+            obj = writer.addToBody(pobj);
+            ind_font = obj.getIndirectReference();
+        }
+        pobj = getFontBaseType(ind_font, firstChar, lastChar, shortTag);
+        writer.addToBody(pobj, ref);
+    }
+    
+    /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
+     * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>,
+     * <CODE>ITALICANGLE</CODE>, <CODE>BBOXLLX</CODE>, <CODE>BBOXLLY</CODE>, <CODE>BBOXURX</CODE>
+     * and <CODE>BBOXURY</CODE>.
+     * @param key the parameter to be extracted
+     * @param fontSize the font size in points
+     * @return the parameter in points
+     */    
+    public float getFontDescriptor(int key, float fontSize) {
+        switch (key) {
+            case AWT_ASCENT:
+            case ASCENT:
+                return Ascender * fontSize / 1000;
+            case CAPHEIGHT:
+                return CapHeight * fontSize / 1000;
+            case AWT_DESCENT:
+            case DESCENT:
+                return Descender * fontSize / 1000;
+            case ITALICANGLE:
+                return ItalicAngle;
+            case BBOXLLX:
+                return llx * fontSize / 1000;
+            case BBOXLLY:
+                return lly * fontSize / 1000;
+            case BBOXURX:
+                return urx * fontSize / 1000;
+            case BBOXURY:
+                return ury * fontSize / 1000;
+            case AWT_LEADING:
+                return 0;
+            case AWT_MAXADVANCE:
+                return (urx - llx) * fontSize / 1000;
+        }
+        return 0;
+    }
+    
+    /** Gets the postscript font name.
+     * @return the postscript font name
+     */
+    public String getPostscriptFontName() {
+        return FontName;
+    }
+    
+    /** Gets the full name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the full name of the font
+     */
+    public String[][] getFullFontName() {
+        return new String[][]{{"", "", "", FullName}};
+    }
+    
+    /** Gets the family name of the font. If it is a True Type font
+     * each array element will have {Platform ID, Platform Encoding ID,
+     * Language ID, font name}. The interpretation of this values can be
+     * found in the Open Type specification, chapter 2, in the 'name' table.<br>
+     * For the other fonts the array has a single element with {"", "", "",
+     * font name}.
+     * @return the family name of the font
+     */
+    public String[][] getFamilyFontName() {
+        return new String[][]{{"", "", "", FamilyName}};
+    }
+    
+    /** Checks if the font has any kerning pairs.
+     * @return <CODE>true</CODE> if the font has any kerning pairs
+     */    
+    public boolean hasKernPairs() {
+        return KernPairs.size() > 0;
+    }
+    
+    /**
+     * Sets the font name that will appear in the pdf font dictionary.
+     * Use with care as it can easily make a font unreadable if not embedded.
+     * @param name the new font name
+     */    
+    public void setPostscriptFontName(String name) {
+        FontName = name;
+    }
+    
+    /**
+     * Sets the kerning between two Unicode chars.
+     * @param char1 the first char
+     * @param char2 the second char
+     * @param kern the kerning to apply in normalized 1000 units
+     * @return <code>true</code> if the kerning was applied, <code>false</code> otherwise
+     */
+    public boolean setKerning(char char1, char char2, int kern) {
+        String first = GlyphList.unicodeToName((int)char1);
+        if (first == null)
+            return false;
+        String second = GlyphList.unicodeToName((int)char2);
+        if (second == null)
+            return false;
+        Object obj[] = (Object[])KernPairs.get(first);
+        if (obj == null) {
+            obj = new Object[]{second, new Integer(kern)};
+            KernPairs.put(first, obj);
+            return true;
+        }
+        for (int k = 0; k < obj.length; k += 2) {
+            if (second.equals(obj[k])) {
+                obj[k + 1] = new Integer(kern);
+                return true;
+            }
+        }
+        int size = obj.length;
+        Object obj2[] = new Object[size + 2];
+        System.arraycopy(obj, 0, obj2, 0, size);
+        obj2[size] = second;
+        obj2[size + 1] = new Integer(kern);
+        KernPairs.put(first, obj2);
+        return true;
+    }
+    
+    protected int[] getRawCharBBox(int c, String name) {
+        Object metrics[];
+        if (name == null) { // font specific
+            metrics = (Object[])CharMetrics.get(new Integer(c));
+        }
+        else {
+            if (name.equals(".notdef"))
+                return null;
+            metrics = (Object[])CharMetrics.get(name);
+        }
+        if (metrics != null)
+            return ((int[])(metrics[3]));
+        return null;
+    }
+    
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/VerticalText.java b/LibrarySource/com/lowagie/text/pdf/VerticalText.java
new file mode 100644
index 0000000..04d5e67
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/VerticalText.java
@@ -0,0 +1,350 @@
+/*
+ *
+ * Copyright 2002 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.Iterator;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Element;
+import com.lowagie.text.DocumentException;
+import headless.awt.Color;
+
+/** Writes text vertically. Note that the naming is done according
+ * to horizontal text although it referrs to vertical text.
+ * A line with the alignment Element.LEFT_ALIGN will actually
+ * be top aligned.
+ */
+public class VerticalText {
+
+/** Signals that there are no more text available. */    
+    public static final int NO_MORE_TEXT = 1;
+	
+/** Signals that there is no more column. */    
+    public static final int NO_MORE_COLUMN = 2;
+
+/** The chunks that form the text. */    
+    protected ArrayList chunks = new ArrayList();
+
+    /** The <CODE>PdfContent</CODE> where the text will be written to. */    
+    protected PdfContentByte text;
+    
+    /** The column alignment. Default is left alignment. */
+    protected int alignment = Element.ALIGN_LEFT;
+
+    /** Marks the chunks to be eliminated when the line is written. */
+    protected int currentChunkMarker = -1;
+    
+    /** The chunk created by the splitting. */
+    protected PdfChunk currentStandbyChunk;
+    
+    /** The chunk created by the splitting. */
+    protected String splittedChunkText;
+
+    /** The leading
+     */    
+    protected float leading;
+    
+    /** The X coordinate.
+     */    
+    protected float startX;
+    
+    /** The Y coordinate.
+     */    
+    protected float startY;
+    
+    /** The maximum number of vertical lines.
+     */    
+    protected int maxLines;
+    
+    /** The height of the text.
+     */    
+    protected float height;
+    
+    /** Creates new VerticalText
+     * @param text the place where the text will be written to. Can
+     * be a template.
+     */
+    public VerticalText(PdfContentByte text) {
+        this.text = text;
+    }
+    
+    /**
+     * Adds a <CODE>Phrase</CODE> to the current text array.
+     * @param phrase the text
+     */
+    public void addText(Phrase phrase) {
+        for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
+            chunks.add(new PdfChunk((Chunk)j.next(), null));
+        }
+    }
+    
+    /**
+     * Adds a <CODE>Chunk</CODE> to the current text array.
+     * @param chunk the text
+     */
+    public void addText(Chunk chunk) {
+        chunks.add(new PdfChunk(chunk, null));
+    }
+
+    /** Sets the layout.
+     * @param startX the top right X line position
+     * @param startY the top right Y line position
+     * @param height the height of the lines
+     * @param maxLines the maximum number of lines
+     * @param leading the separation between the lines
+     */    
+    public void setVerticalLayout(float startX, float startY, float height, int maxLines, float leading) {
+        this.startX = startX;
+        this.startY = startY;
+        this.height = height;
+        this.maxLines = maxLines;
+        setLeading(leading);
+    }
+    
+    /** Sets the separation between the vertical lines.
+     * @param leading the vertical line separation
+     */    
+    public void setLeading(float leading) {
+        this.leading = leading;
+    }
+
+    /** Gets the separation between the vertical lines.
+     * @return the vertical line separation
+     */    
+    public float getLeading() {
+        return leading;
+    }
+    
+    /**
+     * Creates a line from the chunk array.
+     * @param width the width of the line
+     * @return the line or null if no more chunks
+     */
+    protected PdfLine createLine(float width) {
+        if (chunks.size() == 0)
+            return null;
+        splittedChunkText = null;
+        currentStandbyChunk = null;
+        PdfLine line = new PdfLine(0, width, alignment, 0);
+        String total;
+        for (currentChunkMarker = 0; currentChunkMarker < chunks.size(); ++currentChunkMarker) {
+            PdfChunk original = (PdfChunk)(chunks.get(currentChunkMarker));
+            total = original.toString();
+            currentStandbyChunk = line.add(original);
+            if (currentStandbyChunk != null) {
+                splittedChunkText = original.toString();
+                original.setValue(total);
+                return line;
+            }
+        }
+        return line;
+    }
+    
+    /**
+     * Normalizes the list of chunks when the line is accepted.
+     */
+    protected void shortenChunkArray() {
+        if (currentChunkMarker < 0)
+            return;
+        if (currentChunkMarker >= chunks.size()) {
+            chunks.clear();
+            return;
+        }
+        PdfChunk split = (PdfChunk)(chunks.get(currentChunkMarker));
+        split.setValue(splittedChunkText);
+        chunks.set(currentChunkMarker, currentStandbyChunk);
+        for (int j = currentChunkMarker - 1; j >= 0; --j)
+            chunks.remove(j);
+    }
+
+    /**
+     * Outputs the lines to the document. It is equivalent to <CODE>go(false)</CODE>.
+     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
+     * and/or <CODE>NO_MORE_COLUMN</CODE>
+     * @throws DocumentException on error
+     */
+    public int go() throws DocumentException {
+        return go(false);
+    }
+    
+    /**
+     * Outputs the lines to the document. The output can be simulated.
+     * @param simulate <CODE>true</CODE> to simulate the writting to the document
+     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
+     * and/or <CODE>NO_MORE_COLUMN</CODE>
+     * @throws DocumentException on error
+     */
+    public int go(boolean simulate) throws DocumentException {
+        boolean dirty = false;
+        PdfContentByte graphics = null;
+        if (text != null) {
+            graphics = text.getDuplicate();
+        }
+        else if (simulate == false)
+            throw new NullPointerException("VerticalText.go with simulate==false and text==null.");
+        int status = 0;
+        for (;;) {
+            if (maxLines <= 0) {
+                status = NO_MORE_COLUMN;
+                if (chunks.size() == 0)
+                    status |= NO_MORE_TEXT;
+                break;
+            }
+            if (chunks.size() == 0) {
+                status = NO_MORE_TEXT;
+                break;
+            }
+            PdfLine line = createLine(height);
+            if (!simulate && !dirty) {
+                text.beginText();
+                dirty = true;
+            }
+            shortenChunkArray();
+            if (!simulate) {
+                text.setTextMatrix(startX, startY - line.indentLeft());
+                writeLine(line, text, graphics);
+            }
+            --maxLines;
+            startX -= leading;
+        }
+        if (dirty) {
+            text.endText();
+            text.add(graphics);
+        }
+        return status;
+    }
+    
+    void writeLine(PdfLine line, PdfContentByte text, PdfContentByte graphics)  throws DocumentException {
+        PdfFont currentFont = null;
+        PdfChunk chunk;
+        for (Iterator j = line.iterator(); j.hasNext(); ) {
+            chunk = (PdfChunk) j.next();
+            
+            if (chunk.font().compareTo(currentFont) != 0) {
+                currentFont = chunk.font();
+                text.setFontAndSize(currentFont.getFont(), currentFont.size());
+            }
+            Color color = chunk.color();
+            if (color != null)
+                text.setColorFill(color);
+            text.showText(chunk.toString());
+            if (color != null)
+                text.resetRGBColorFill();
+        }
+    }
+    
+    /** Sets the new text origin.
+     * @param startX the X coordinate
+     * @param startY the Y coordinate
+     */    
+    public void setOrigin(float startX, float startY) {
+        this.startX = startX;
+        this.startY = startY;
+    }
+    
+    /** Gets the X coordinate where the next line will be writen. This value will change
+     * after each call to <code>go()</code>.
+     * @return  the X coordinate
+     */    
+    public float getOriginX() {
+        return startX;
+    }
+
+    /** Gets the Y coordinate where the next line will be writen.
+     * @return  the Y coordinate
+     */    
+    public float getOriginY() {
+        return startY;
+    }
+    
+    /** Gets the maximum number of available lines. This value will change
+     * after each call to <code>go()</code>.
+     * @return Value of property maxLines.
+     */
+    public int getMaxLines() {
+        return maxLines;
+    }
+    
+    /** Sets the maximum number of lines.
+     * @param maxLines the maximum number of lines
+     */
+    public void setMaxLines(int maxLines) {
+        this.maxLines = maxLines;
+    }
+    
+    /** Gets the height of the line
+     * @return the height
+     */
+    public float getHeight() {
+        return height;
+    }
+    
+    /** Sets the height of the line
+     * @param height the new height
+     */
+    public void setHeight(float height) {
+        this.height = height;
+    }
+    
+    /**
+     * Sets the alignment.
+     * @param alignment the alignment
+     */
+    public void setAlignment(int alignment) {
+        this.alignment = alignment;
+    }
+    
+    /**
+     * Gets the alignment.
+     * @return the alignment
+     */
+    public int getAlignment() {
+        return alignment;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/XfdfReader.java b/LibrarySource/com/lowagie/text/pdf/XfdfReader.java
new file mode 100644
index 0000000..9bbd42b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/XfdfReader.java
@@ -0,0 +1,208 @@
+/*
+ *
+ * Copyright 2004 by Leonard Rosenthol.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Stack;
+
+/**
+ * Reads a XFDF.
+ * @author Leonard Rosenthol (leonardr at pdfsages.com)
+ */
+public class XfdfReader implements SimpleXMLDocHandler {
+	// stuff used during parsing to handle state
+	private boolean foundRoot = false;
+    private Stack fieldNames = new Stack();
+    private Stack fieldValues = new Stack();
+
+    // storage for the field list and their values
+	HashMap	fields;
+	
+	// storage for the path to referenced PDF, if any
+	String	fileSpec;
+	
+   /** Reads an XFDF form.
+     * @param filename the file name of the form
+     * @throws IOException on error
+     */    
+    public XfdfReader(String filename) throws IOException {
+        FileInputStream fin = null;
+        try {
+            fin = new FileInputStream(filename);
+            SimpleXMLParser.parse(this, fin);
+        }
+        finally {
+            try{fin.close();}catch(Exception e){}
+        }
+    }
+    
+    /** Reads an XFDF form.
+     * @param xfdfIn the byte array with the form
+     * @throws IOException on error
+     */    
+    public XfdfReader(byte xfdfIn[]) throws IOException {
+        SimpleXMLParser.parse( this, new ByteArrayInputStream(xfdfIn));
+   }
+    
+    /** Gets all the fields. The map is keyed by the fully qualified
+     * field name and the value is a merged <CODE>PdfDictionary</CODE>
+     * with the field content.
+     * @return all the fields
+     */    
+    public HashMap getFields() {
+        return fields;
+    }
+    
+    /** Gets the field value.
+     * @param name the fully qualified field name
+     * @return the field's value
+     */    
+    public String getField(String name) {
+        return (String)fields.get(name);
+    }
+    
+    /** Gets the field value or <CODE>null</CODE> if the field does not
+     * exist or has no value defined.
+     * @param name the fully qualified field name
+     * @return the field value or <CODE>null</CODE>
+     */    
+    public String getFieldValue(String name) {
+        String field = (String)fields.get(name);
+        if (field == null)
+            return null;
+        else
+        	return field;
+    }
+    
+    /** Gets the PDF file specification contained in the FDF.
+     * @return the PDF file specification contained in the FDF
+     */    
+    public String getFileSpec() {
+        return fileSpec;
+    }
+
+    /**
+     * Called when a start tag is found.
+     * @param tag the tag name
+     * @param h the tag's attributes
+     */    
+    public void startElement(String tag, HashMap h)
+    {
+        if ( !foundRoot ) {
+            if (!tag.equals("xfdf"))
+                throw new RuntimeException("Root element is not Bookmark.");
+            else 
+            	foundRoot = true;
+        }
+
+        if ( tag.equals("xfdf") ){
+    		
+    	} else if ( tag.equals("f") ) {
+    		fileSpec = (String)h.get( "href" );
+    	} else if ( tag.equals("fields") ) {
+            fields = new HashMap();		// init it!
+    	} else if ( tag.equals("field") ) {
+    		String	fName = (String) h.get( "name" );
+    		fieldNames.push( fName );
+    	} else if ( tag.equals("value") ) {
+    		fieldValues.push( (String)"" );
+    	}
+    }
+    /**
+     * Called when an end tag is found.
+     * @param tag the tag name
+     */    
+    public void endElement(String tag) {
+        if ( tag.equals("value") ) {
+            String	fName = "";
+            for (int k = 0; k < fieldNames.size(); ++k) {
+                fName += "." + (String)fieldNames.elementAt(k);
+            }
+            if (fName.startsWith("."))
+                fName = fName.substring(1);
+            String	fVal = (String) fieldValues.pop();
+            fields.put( fName, fVal );
+        }
+        else if (tag.equals("field") ) {
+            if (!fieldNames.isEmpty())
+                fieldNames.pop();
+        }
+    }
+    
+    /**
+     * Called when the document starts to be parsed.
+     */    
+    public void startDocument()
+    {
+        fileSpec = new String("");	// and this too...
+    }
+    /**
+     * Called after the document is parsed.
+     */    
+    public void endDocument()
+	{
+    	
+	}
+    /**
+     * Called when a text element is found.
+     * @param str the text element, probably a fragment.
+     */    
+    public void text(String str)
+    {
+        if (fieldNames.isEmpty() || fieldValues.isEmpty())
+            return;
+        
+        String val = (String)fieldValues.pop();
+        val += str;
+        fieldValues.push(val);
+    }
+}
\ No newline at end of file
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/BmpImage.java b/LibrarySource/com/lowagie/text/pdf/codec/BmpImage.java
new file mode 100644
index 0000000..f3d4db6
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/BmpImage.java
@@ -0,0 +1,1307 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ *
+ * The original JAI codecs have the following license
+ *
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.*;
+import java.io.*;
+import java.util.HashMap;
+import java.net.URL;
+
+/** Reads a BMP image. All types of BMP can be read.
+ * <p>
+ * It is based in the JAI codec.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class BmpImage {
+    
+    // BMP variables
+    private InputStream inputStream;
+    private long bitmapFileSize;
+    private long bitmapOffset;
+    private long compression;
+    private long imageSize;
+    private byte palette[];
+    private int imageType;
+    private int numBands;
+    private boolean isBottomUp;
+    private int bitsPerPixel;
+    private int redMask, greenMask, blueMask, alphaMask;
+    public HashMap properties = new HashMap();    
+    private long xPelsPerMeter;
+    private long yPelsPerMeter;
+    // BMP Image types
+    private static final int VERSION_2_1_BIT = 0;
+    private static final int VERSION_2_4_BIT = 1;
+    private static final int VERSION_2_8_BIT = 2;
+    private static final int VERSION_2_24_BIT = 3;
+    
+    private static final int VERSION_3_1_BIT = 4;
+    private static final int VERSION_3_4_BIT = 5;
+    private static final int VERSION_3_8_BIT = 6;
+    private static final int VERSION_3_24_BIT = 7;
+    
+    private static final int VERSION_3_NT_16_BIT = 8;
+    private static final int VERSION_3_NT_32_BIT = 9;
+    
+    private static final int VERSION_4_1_BIT = 10;
+    private static final int VERSION_4_4_BIT = 11;
+    private static final int VERSION_4_8_BIT = 12;
+    private static final int VERSION_4_16_BIT = 13;
+    private static final int VERSION_4_24_BIT = 14;
+    private static final int VERSION_4_32_BIT = 15;
+    
+    // Color space types
+    private static final int LCS_CALIBRATED_RGB = 0;
+    private static final int LCS_sRGB = 1;
+    private static final int LCS_CMYK = 2;
+    
+    // Compression Types
+    private static final int BI_RGB = 0;
+    private static final int BI_RLE8 = 1;
+    private static final int BI_RLE4 = 2;
+    private static final int BI_BITFIELDS = 3;
+    
+    int width;
+    int height;
+    
+    BmpImage(InputStream is, boolean noHeader, int size) throws IOException {
+        bitmapFileSize = size;
+        bitmapOffset = 0;
+        process(is, noHeader);
+    }
+    
+    /** Reads a BMP from an url.
+     * @param url the url
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(URL url) throws IOException {
+        InputStream is = null;
+        try {
+            is = url.openStream();
+            Image img = getImage(is);
+            img.setUrl(url);
+            return img;
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+    
+    /** Reads a BMP from a stream. The stream is not closed.
+     * @param is the stream
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(InputStream is) throws IOException {
+        return getImage(is, false, 0);
+    }
+    
+    /** Reads a BMP from a stream. The stream is not closed.
+     * The BMP may not have a header and be considered as a plain DIB.
+     * @param is the stream
+     * @param noHeader true to process a plain DIB
+     * @param size the size of the DIB. Not used for a BMP
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(InputStream is, boolean noHeader, int size) throws IOException {
+        BmpImage bmp = new BmpImage(is, noHeader, size);
+        try {
+            Image img = bmp.getImage();
+            img.setDpi((int)((double)bmp.xPelsPerMeter * 0.0254), (int)((double)bmp.xPelsPerMeter * 0.0254));
+            img.setOriginalType(Image.ORIGINAL_BMP);
+            return img;
+        }
+        catch (BadElementException be) {
+            throw new ExceptionConverter(be);
+        }
+    }
+    
+    /** Reads a BMP from a file.
+     * @param file the file
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(String file) throws IOException {
+        return getImage(Image.toURL(file));
+    }
+    
+    /** Reads a BMP from a byte array.
+     * @param data the byte array
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(byte data[]) throws IOException {
+        InputStream is = null;
+        try {
+            is = new ByteArrayInputStream(data);
+            Image img = getImage(is);
+            img.setOriginalData(data);
+            return img;
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    
+    protected void process(InputStream stream, boolean noHeader) throws IOException {
+        if (noHeader || stream instanceof BufferedInputStream) {
+            inputStream = stream;
+        } else {
+            inputStream = new BufferedInputStream(stream);
+        }
+        if (!noHeader) {
+            // Start File Header
+            if (!(readUnsignedByte(inputStream) == 'B' &&
+            readUnsignedByte(inputStream) == 'M')) {
+                throw new
+                RuntimeException("Invalid magic value for BMP file.");
+            }
+
+            // Read file size
+            bitmapFileSize = readDWord(inputStream);
+
+            // Read the two reserved fields
+            readWord(inputStream);
+            readWord(inputStream);
+
+            // Offset to the bitmap from the beginning
+            bitmapOffset = readDWord(inputStream);
+
+            // End File Header
+        }
+        // Start BitmapCoreHeader
+        long size = readDWord(inputStream);
+        
+        if (size == 12) {
+            width = readWord(inputStream);
+            height = readWord(inputStream);
+        } else {
+            width = readLong(inputStream);
+            height = readLong(inputStream);
+        }
+        
+        int planes = readWord(inputStream);
+        bitsPerPixel = readWord(inputStream);
+        
+        properties.put("color_planes", new Integer(planes));
+        properties.put("bits_per_pixel", new Integer(bitsPerPixel));
+        
+        // As BMP always has 3 rgb bands, except for Version 5,
+        // which is bgra
+        numBands = 3;
+        if (bitmapOffset == 0)
+            bitmapOffset = size;
+        if (size == 12) {
+            // Windows 2.x and OS/2 1.x
+            properties.put("bmp_version", "BMP v. 2.x");
+            
+            // Classify the image type
+            if (bitsPerPixel == 1) {
+                imageType = VERSION_2_1_BIT;
+            } else if (bitsPerPixel == 4) {
+                imageType = VERSION_2_4_BIT;
+            } else if (bitsPerPixel == 8) {
+                imageType = VERSION_2_8_BIT;
+            } else if (bitsPerPixel == 24) {
+                imageType = VERSION_2_24_BIT;
+            }
+            
+            // Read in the palette
+            int numberOfEntries = (int)((bitmapOffset-14-size) / 3);
+            int sizeOfPalette = numberOfEntries*3;
+            if (bitmapOffset == size) {
+                switch (imageType) {
+                    case VERSION_2_1_BIT:
+                        sizeOfPalette = 2 * 3;
+                        break;
+                    case VERSION_2_4_BIT:
+                        sizeOfPalette = 16 * 3;
+                        break;
+                    case VERSION_2_8_BIT:
+                        sizeOfPalette = 256 * 3;
+                        break;
+                    case VERSION_2_24_BIT:
+                        sizeOfPalette = 0;
+                        break;
+                }
+                bitmapOffset = size + sizeOfPalette;
+            }
+            palette = new byte[sizeOfPalette];
+            inputStream.read(palette, 0, sizeOfPalette);
+            properties.put("palette", palette);
+        } else {
+            
+            compression = readDWord(inputStream);
+            imageSize = readDWord(inputStream);
+            xPelsPerMeter = readLong(inputStream);
+            yPelsPerMeter = readLong(inputStream);
+            long colorsUsed = readDWord(inputStream);
+            long colorsImportant = readDWord(inputStream);
+            
+            switch((int)compression) {
+                case BI_RGB:
+                    properties.put("compression", "BI_RGB");
+                    break;
+                    
+                case BI_RLE8:
+                    properties.put("compression", "BI_RLE8");
+                    break;
+                    
+                case BI_RLE4:
+                    properties.put("compression", "BI_RLE4");
+                    break;
+                    
+                case BI_BITFIELDS:
+                    properties.put("compression", "BI_BITFIELDS");
+                    break;
+            }
+            
+            properties.put("x_pixels_per_meter", new Long(xPelsPerMeter));
+            properties.put("y_pixels_per_meter", new Long(yPelsPerMeter));
+            properties.put("colors_used", new Long(colorsUsed));
+            properties.put("colors_important", new Long(colorsImportant));
+            
+            if (size == 40) {
+                // Windows 3.x and Windows NT
+                switch((int)compression) {
+                    
+                    case BI_RGB:  // No compression
+                    case BI_RLE8:  // 8-bit RLE compression
+                    case BI_RLE4:  // 4-bit RLE compression
+                        
+                        if (bitsPerPixel == 1) {
+                            imageType = VERSION_3_1_BIT;
+                        } else if (bitsPerPixel == 4) {
+                            imageType = VERSION_3_4_BIT;
+                        } else if (bitsPerPixel == 8) {
+                            imageType = VERSION_3_8_BIT;
+                        } else if (bitsPerPixel == 24) {
+                            imageType = VERSION_3_24_BIT;
+                        } else if (bitsPerPixel == 16) {
+                            imageType = VERSION_3_NT_16_BIT;
+                            redMask = 0x7C00;
+                            greenMask = 0x3E0;
+                            blueMask = 0x1F;
+                            properties.put("red_mask", new Integer(redMask));
+                            properties.put("green_mask", new Integer(greenMask));
+                            properties.put("blue_mask", new Integer(blueMask));
+                        } else if (bitsPerPixel == 32) {
+                            imageType = VERSION_3_NT_32_BIT;
+                            redMask   = 0x00FF0000;
+                            greenMask = 0x0000FF00;
+                            blueMask  = 0x000000FF;
+                            properties.put("red_mask", new Integer(redMask));
+                            properties.put("green_mask", new Integer(greenMask));
+                            properties.put("blue_mask", new Integer(blueMask));
+                        }
+
+                        // Read in the palette
+                        int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
+                        int sizeOfPalette = numberOfEntries*4;
+                        if (bitmapOffset == size) {
+                            switch (imageType) {
+                                case VERSION_3_1_BIT:
+                                    sizeOfPalette = (int)(colorsUsed == 0 ? 2 : colorsUsed) * 4;
+                                    break;
+                                case VERSION_3_4_BIT:
+                                    sizeOfPalette = (int)(colorsUsed == 0 ? 16 : colorsUsed) * 4;
+                                    break;
+                                case VERSION_3_8_BIT:
+                                    sizeOfPalette = (int)(colorsUsed == 0 ? 256 : colorsUsed) * 4;
+                                    break;
+                                default:
+                                    sizeOfPalette = 0;
+                                    break;
+                            }
+                            bitmapOffset = size + sizeOfPalette;
+                        }
+                        palette = new byte[sizeOfPalette];
+                        inputStream.read(palette, 0, sizeOfPalette);
+                        properties.put("palette", palette);
+                                                
+                        properties.put("bmp_version", "BMP v. 3.x");
+                        break;
+                        
+                    case BI_BITFIELDS:
+                        
+                        if (bitsPerPixel == 16) {
+                            imageType = VERSION_3_NT_16_BIT;
+                        } else if (bitsPerPixel == 32) {
+                            imageType = VERSION_3_NT_32_BIT;
+                        }
+                        
+                        // BitsField encoding
+                        redMask = (int)readDWord(inputStream);
+                        greenMask = (int)readDWord(inputStream);
+                        blueMask = (int)readDWord(inputStream);
+                        
+                        properties.put("red_mask", new Integer(redMask));
+                        properties.put("green_mask", new Integer(greenMask));
+                        properties.put("blue_mask", new Integer(blueMask));
+                        
+                        if (colorsUsed != 0) {
+                            // there is a palette
+                            sizeOfPalette = (int)colorsUsed*4;
+                            palette = new byte[sizeOfPalette];
+                            inputStream.read(palette, 0, sizeOfPalette);
+                            properties.put("palette", palette);
+                        }
+                        
+                        properties.put("bmp_version", "BMP v. 3.x NT");
+                        break;
+                        
+                    default:
+                        throw new
+                        RuntimeException("Invalid compression specified in BMP file.");
+                }
+            } else if (size == 108) {
+                // Windows 4.x BMP
+                
+                properties.put("bmp_version", "BMP v. 4.x");
+                
+                // rgb masks, valid only if comp is BI_BITFIELDS
+                redMask = (int)readDWord(inputStream);
+                greenMask = (int)readDWord(inputStream);
+                blueMask = (int)readDWord(inputStream);
+                // Only supported for 32bpp BI_RGB argb
+                alphaMask = (int)readDWord(inputStream);
+                long csType = readDWord(inputStream);
+                int redX = readLong(inputStream);
+                int redY = readLong(inputStream);
+                int redZ = readLong(inputStream);
+                int greenX = readLong(inputStream);
+                int greenY = readLong(inputStream);
+                int greenZ = readLong(inputStream);
+                int blueX = readLong(inputStream);
+                int blueY = readLong(inputStream);
+                int blueZ = readLong(inputStream);
+                long gammaRed = readDWord(inputStream);
+                long gammaGreen = readDWord(inputStream);
+                long gammaBlue = readDWord(inputStream);
+                
+                if (bitsPerPixel == 1) {
+                    imageType = VERSION_4_1_BIT;
+                } else if (bitsPerPixel == 4) {
+                    imageType = VERSION_4_4_BIT;
+                } else if (bitsPerPixel == 8) {
+                    imageType = VERSION_4_8_BIT;
+                } else if (bitsPerPixel == 16) {
+                    imageType = VERSION_4_16_BIT;
+                    if ((int)compression == BI_RGB) {
+                        redMask = 0x7C00;
+                        greenMask = 0x3E0;
+                        blueMask = 0x1F;
+                    }
+                } else if (bitsPerPixel == 24) {
+                    imageType = VERSION_4_24_BIT;
+                } else if (bitsPerPixel == 32) {
+                    imageType = VERSION_4_32_BIT;
+                    if ((int)compression == BI_RGB) {
+                        redMask   = 0x00FF0000;
+                        greenMask = 0x0000FF00;
+                        blueMask  = 0x000000FF;
+                    }
+                }
+                
+                properties.put("red_mask", new Integer(redMask));
+                properties.put("green_mask", new Integer(greenMask));
+                properties.put("blue_mask", new Integer(blueMask));
+                properties.put("alpha_mask", new Integer(alphaMask));
+
+                // Read in the palette
+                int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
+                int sizeOfPalette = numberOfEntries*4;
+                if (bitmapOffset == size) {
+                    switch (imageType) {
+                        case VERSION_4_1_BIT:
+                            sizeOfPalette = (int)(colorsUsed == 0 ? 2 : colorsUsed) * 4;
+                            break;
+                        case VERSION_4_4_BIT:
+                            sizeOfPalette = (int)(colorsUsed == 0 ? 16 : colorsUsed) * 4;
+                            break;
+                        case VERSION_4_8_BIT:
+                            sizeOfPalette = (int)(colorsUsed == 0 ? 256 : colorsUsed) * 4;
+                            break;
+                        default:
+                            sizeOfPalette = 0;
+                            break;
+                    }
+                    bitmapOffset = size + sizeOfPalette;
+                }
+                palette = new byte[sizeOfPalette];
+                inputStream.read(palette, 0, sizeOfPalette);
+                
+                if (palette != null || palette.length != 0) {
+                    properties.put("palette", palette);
+                }
+                
+                switch((int)csType) {
+                    case LCS_CALIBRATED_RGB:
+                        // All the new fields are valid only for this case
+                        properties.put("color_space", "LCS_CALIBRATED_RGB");
+                        properties.put("redX", new Integer(redX));
+                        properties.put("redY", new Integer(redY));
+                        properties.put("redZ", new Integer(redZ));
+                        properties.put("greenX", new Integer(greenX));
+                        properties.put("greenY", new Integer(greenY));
+                        properties.put("greenZ", new Integer(greenZ));
+                        properties.put("blueX", new Integer(blueX));
+                        properties.put("blueY", new Integer(blueY));
+                        properties.put("blueZ", new Integer(blueZ));
+                        properties.put("gamma_red", new Long(gammaRed));
+                        properties.put("gamma_green", new Long(gammaGreen));
+                        properties.put("gamma_blue", new Long(gammaBlue));
+                        
+                        // break;
+                        throw new
+                        RuntimeException("Not implemented yet.");
+                        
+                    case LCS_sRGB:
+                        // Default Windows color space
+                        properties.put("color_space", "LCS_sRGB");
+                        break;
+                        
+                    case LCS_CMYK:
+                        properties.put("color_space", "LCS_CMYK");
+                        //		    break;
+                        throw new
+                        RuntimeException("Not implemented yet.");
+                }
+                
+            } else {
+                properties.put("bmp_version", "BMP v. 5.x");
+                throw new
+                RuntimeException("BMP version 5 not implemented yet.");
+            }
+        }
+        
+        if (height > 0) {
+            // bottom up image
+            isBottomUp = true;
+        } else {
+            // top down image
+            isBottomUp = false;
+            height = Math.abs(height);
+        }
+        // When number of bitsPerPixel is <= 8, we use IndexColorModel.
+        if (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8) {
+            
+            numBands = 1;
+            
+            
+            // Create IndexColorModel from the palette.
+            byte r[], g[], b[];
+            int sizep;
+            if (imageType == VERSION_2_1_BIT ||
+            imageType == VERSION_2_4_BIT ||
+            imageType == VERSION_2_8_BIT) {
+                
+                sizep = palette.length/3;
+                
+                if (sizep > 256) {
+                    sizep = 256;
+                }
+                
+                int off;
+                r = new byte[sizep];
+                g = new byte[sizep];
+                b = new byte[sizep];
+                for (int i=0; i<sizep; i++) {
+                    off = 3 * i;
+                    b[i] = palette[off];
+                    g[i] = palette[off+1];
+                    r[i] = palette[off+2];
+                }
+            } else {
+                sizep = palette.length/4;
+                
+                if (sizep > 256) {
+                    sizep = 256;
+                }
+                
+                int off;
+                r = new byte[sizep];
+                g = new byte[sizep];
+                b = new byte[sizep];
+                for (int i=0; i<sizep; i++) {
+                    off = 4 * i;
+                    b[i] = palette[off];
+                    g[i] = palette[off+1];
+                    r[i] = palette[off+2];
+                }
+            }
+            
+        } else if (bitsPerPixel == 16) {
+            numBands = 3;
+        } else if (bitsPerPixel == 32) {
+            numBands = alphaMask == 0 ? 3 : 4;
+            
+            // The number of bands in the SampleModel is determined by
+            // the length of the mask array passed in.
+            int[] bitMasks = numBands == 3 ?
+            new int[] {redMask, greenMask, blueMask} :
+                new int[] {redMask, greenMask, blueMask, alphaMask};
+                
+        } else {
+            numBands = 3;
+        }
+    }
+    
+    private byte[] getPalette(int group) {
+        if (palette == null)
+            return null;
+        byte np[] = new byte[palette.length / group * 3];
+        int e = palette.length / group;
+        for (int k = 0; k < e; ++k) {
+            int src = k * group;
+            int dest = k * 3;
+            np[dest + 2] = palette[src++];
+            np[dest + 1] = palette[src++];
+            np[dest] = palette[src];
+        }
+        return np;
+    }
+    
+    private Image getImage() throws IOException, BadElementException {
+        byte bdata[] = null; // buffer for byte data
+        short sdata[] = null; // buffer for short data
+        int idata[] = null; // buffer for int data
+        
+        //	if (sampleModel.getDataType() == DataBuffer.TYPE_BYTE)
+        //	    bdata = (byte[])((DataBufferByte)tile.getDataBuffer()).getData();
+        //	else if (sampleModel.getDataType() == DataBuffer.TYPE_USHORT)
+        //	    sdata = (short[])((DataBufferUShort)tile.getDataBuffer()).getData();
+        //	else if (sampleModel.getDataType() == DataBuffer.TYPE_INT)
+        //	    idata = (int[])((DataBufferInt)tile.getDataBuffer()).getData();
+        
+        // There should only be one tile.
+        switch(imageType) {
+            
+            case VERSION_2_1_BIT:
+                // no compression
+                return read1Bit(3);
+                
+            case VERSION_2_4_BIT:
+                // no compression
+                return read4Bit(3);
+                
+            case VERSION_2_8_BIT:
+                // no compression
+                return read8Bit(3);
+                
+            case VERSION_2_24_BIT:
+                // no compression
+                bdata = new byte[width * height * 3];
+                read24Bit(bdata);
+                return new ImgRaw(width, height, 3, 8, bdata);
+                
+            case VERSION_3_1_BIT:
+                // 1-bit images cannot be compressed.
+                return read1Bit(4);
+                
+            case VERSION_3_4_BIT:
+                switch((int)compression) {
+                    case BI_RGB:
+                        return read4Bit(4);
+                        
+                    case BI_RLE4:
+                        return readRLE4();
+                        
+                    default:
+                        throw new
+                        RuntimeException("Invalid compression specified for BMP file.");
+                }
+                
+            case VERSION_3_8_BIT:
+                switch((int)compression) {
+                    case BI_RGB:
+                        return read8Bit(4);
+                        
+                    case BI_RLE8:
+                        return readRLE8();
+                        
+                    default:
+                        throw new
+                        RuntimeException("Invalid compression specified for BMP file.");
+                }
+                
+            case VERSION_3_24_BIT:
+                // 24-bit images are not compressed
+                bdata = new byte[width * height * 3];
+                read24Bit(bdata);
+                return new ImgRaw(width, height, 3, 8, bdata);
+                
+            case VERSION_3_NT_16_BIT:
+                return read1632Bit(false);
+                
+            case VERSION_3_NT_32_BIT:
+                return read1632Bit(true);
+                
+            case VERSION_4_1_BIT:
+                return read1Bit(4);
+                
+            case VERSION_4_4_BIT:
+                switch((int)compression) {
+                    
+                    case BI_RGB:
+                        return read4Bit(4);
+                        
+                    case BI_RLE4:
+                        return readRLE4();
+                        
+                    default:
+                        throw new
+                        RuntimeException("Invalid compression specified for BMP file.");
+                }
+                
+            case VERSION_4_8_BIT:
+                switch((int)compression) {
+                    
+                    case BI_RGB:
+                        return read8Bit(4);
+                        
+                    case BI_RLE8:
+                        return readRLE8();
+                        
+                    default:
+                        throw new
+                        RuntimeException("Invalid compression specified for BMP file.");
+                }
+                
+            case VERSION_4_16_BIT:
+                return read1632Bit(false);
+                
+            case VERSION_4_24_BIT:
+                bdata = new byte[width * height * 3];
+                read24Bit(bdata);
+                return new ImgRaw(width, height, 3, 8, bdata);
+                
+            case VERSION_4_32_BIT:
+                return read1632Bit(true);
+        }
+        return null;
+    }
+    
+    private Image indexedModel(byte bdata[], int bpc, int paletteEntries) throws BadElementException {
+        Image img = new ImgRaw(width, height, 1, bpc, bdata);
+        PdfArray colorspace = new PdfArray();
+        colorspace.add(PdfName.INDEXED);
+        colorspace.add(PdfName.DEVICERGB);
+        byte np[] = getPalette(paletteEntries);
+        int len = np.length;
+        colorspace.add(new PdfNumber(len / 3 - 1));
+        colorspace.add(new PdfString(np));
+        PdfDictionary ad = new PdfDictionary();
+        ad.put(PdfName.COLORSPACE, colorspace);
+        img.setAdditional(ad);
+        return img;
+    }
+    
+    // Deal with 1 Bit images using IndexColorModels
+    private Image read1Bit(int paletteEntries) throws IOException, BadElementException {
+        byte bdata[] = new byte[((width + 7) / 8) * height];
+        int padding = 0;
+        int bytesPerScanline = (int)Math.ceil((double)width/8.0);
+        
+        int remainder = bytesPerScanline % 4;
+        if (remainder != 0) {
+            padding = 4 - remainder;
+        }
+        
+        int imSize = (bytesPerScanline + padding) * height;
+        
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        int bytesRead = 0;
+        while (bytesRead < imSize) {
+            bytesRead += inputStream.read(values, bytesRead,
+            imSize - bytesRead);
+        }
+        
+        if (isBottomUp) {
+            
+            // Convert the bottom up image to a top down format by copying
+            // one scanline from the bottom to the top at a time.
+            
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                imSize - (i+1)*(bytesPerScanline + padding),
+                bdata,
+                i*bytesPerScanline, bytesPerScanline);
+            }
+        } else {
+            
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                i * (bytesPerScanline + padding),
+                bdata,
+                i * bytesPerScanline,
+                bytesPerScanline);
+            }
+        }
+        return indexedModel(bdata, 1, paletteEntries);
+    }
+    
+    // Method to read a 4 bit BMP image data
+    private Image read4Bit(int paletteEntries) throws IOException, BadElementException {
+        byte bdata[] = new byte[((width + 1) / 2) * height];
+        
+        // Padding bytes at the end of each scanline
+        int padding = 0;
+        
+        int bytesPerScanline = (int)Math.ceil((double)width/2.0);
+        int remainder = bytesPerScanline % 4;
+        if (remainder != 0) {
+            padding = 4 - remainder;
+        }
+        
+        int imSize = (bytesPerScanline + padding) * height;
+        
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        int bytesRead = 0;
+        while (bytesRead < imSize) {
+            bytesRead += inputStream.read(values, bytesRead,
+            imSize - bytesRead);
+        }
+        
+        if (isBottomUp) {
+            
+            // Convert the bottom up image to a top down format by copying
+            // one scanline from the bottom to the top at a time.
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                imSize - (i+1)*(bytesPerScanline + padding),
+                bdata,
+                i*bytesPerScanline,
+                bytesPerScanline);
+            }
+        } else {
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                i * (bytesPerScanline + padding),
+                bdata,
+                i * bytesPerScanline,
+                bytesPerScanline);
+            }
+        }
+        return indexedModel(bdata, 4, paletteEntries);
+    }
+    
+    // Method to read 8 bit BMP image data
+    private Image read8Bit(int paletteEntries) throws IOException, BadElementException {
+        byte bdata[] = new byte[width * height];
+        // Padding bytes at the end of each scanline
+        int padding = 0;
+        
+        // width * bitsPerPixel should be divisible by 32
+        int bitsPerScanline = width * 8;
+        if ( bitsPerScanline%32 != 0) {
+            padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
+            padding = (int)Math.ceil(padding/8.0);
+        }
+        
+        int imSize = (width + padding) * height;
+        
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        int bytesRead = 0;
+        while (bytesRead < imSize) {
+            bytesRead += inputStream.read(values, bytesRead, imSize - bytesRead);
+        }
+        
+        if (isBottomUp) {
+            
+            // Convert the bottom up image to a top down format by copying
+            // one scanline from the bottom to the top at a time.
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                imSize - (i+1) * (width + padding),
+                bdata,
+                i * width,
+                width);
+            }
+        } else {
+            for (int i=0; i<height; i++) {
+                System.arraycopy(values,
+                i * (width + padding),
+                bdata,
+                i * width,
+                width);
+            }
+        }
+        return indexedModel(bdata, 8, paletteEntries);
+    }
+    
+    // Method to read 24 bit BMP image data
+    private void read24Bit(byte[] bdata) {
+        // Padding bytes at the end of each scanline
+        int padding = 0;
+        
+        // width * bitsPerPixel should be divisible by 32
+        int bitsPerScanline = width * 24;
+        if ( bitsPerScanline%32 != 0) {
+            padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
+            padding = (int)Math.ceil(padding/8.0);
+        }
+        
+        
+        int imSize = ((width * 3 + 3) / 4 * 4) * height;
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        try {
+            int bytesRead = 0;
+            while (bytesRead < imSize) {
+                int r = inputStream.read(values, bytesRead,
+                imSize - bytesRead);
+                if (r < 0)
+                    break;
+                bytesRead += r;
+            }
+        } catch (IOException ioe) {
+            throw new ExceptionConverter(ioe);
+        }
+        
+        int l=0, count;
+        
+        if (isBottomUp) {
+            int max = width*height*3-1;
+            
+            count = -padding;
+            for (int i=0; i<height; i++) {
+                l = max - (i+1)*width*3 + 1;
+                count += padding;
+                for (int j=0; j<width; j++) {
+                    bdata[l + 2] = values[count++];
+                    bdata[l + 1] = values[count++];
+                    bdata[l] = values[count++];
+                    l += 3;
+                }
+            }
+        } else {
+            count = -padding;
+            for (int i=0; i<height; i++) {
+                count += padding;
+                for (int j=0; j<width; j++) {
+                    bdata[l + 2] = values[count++];
+                    bdata[l + 1] = values[count++];
+                    bdata[l] = values[count++];
+                    l += 3;
+                }
+            }
+        }
+    }
+    
+    private int findMask(int mask) {
+        int k = 0;
+        for (; k < 32; ++k) {
+            if ((mask & 1) == 1)
+                break;
+            mask >>>= 1;
+        }
+        return mask;
+    }
+    
+    private int findShift(int mask) {
+        int k = 0;
+        for (; k < 32; ++k) {
+            if ((mask & 1) == 1)
+                break;
+            mask >>>= 1;
+        }
+        return k;
+    }
+    
+    private Image read1632Bit(boolean is32) throws IOException, BadElementException {
+        
+        int red_mask = findMask(redMask);
+        int red_shift = findShift(redMask);
+        int red_factor = red_mask + 1;
+        int green_mask = findMask(greenMask);
+        int green_shift = findShift(greenMask);
+        int green_factor = green_mask + 1;
+        int blue_mask = findMask(blueMask);
+        int blue_shift = findShift(blueMask);
+        int blue_factor = blue_mask + 1;
+        byte bdata[] = new byte[width * height * 3];
+        // Padding bytes at the end of each scanline
+        int padding = 0;
+        
+        if (!is32) {
+        // width * bitsPerPixel should be divisible by 32
+            int bitsPerScanline = width * 16;
+            if ( bitsPerScanline%32 != 0) {
+                padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
+                padding = (int)Math.ceil(padding/8.0);
+            }
+        }
+        
+        int imSize = (int)imageSize;
+        if (imSize == 0) {
+            imSize = (int)(bitmapFileSize - bitmapOffset);
+        }
+        
+        int l=0;
+        int v;
+        if (isBottomUp) {
+            int max = width*height-1;
+
+            for (int i=height - 1; i >= 0; --i) {
+                l = width * 3 * i;
+                for (int j=0; j<width; j++) {
+                    if (is32)
+                        v = (int)readDWord(inputStream);
+                    else
+                        v = readWord(inputStream);
+                    bdata[l++] = (byte)(((v >>> red_shift) & red_mask) * 256 / red_factor);
+                    bdata[l++] = (byte)(((v >>> green_shift) & green_mask) * 256 / green_factor);
+                    bdata[l++] = (byte)(((v >>> blue_shift) & blue_mask) * 256 / blue_factor);
+                }
+                for (int m=0; m<padding; m++) {
+                    inputStream.read();
+                }
+            }
+        } else {
+            for (int i=0; i<height; i++) {
+                for (int j=0; j<width; j++) {
+                    if (is32)
+                        v = (int)readDWord(inputStream);
+                    else
+                        v = readWord(inputStream);
+                    bdata[l++] = (byte)(((v >>> red_shift) & red_mask) * 256 / red_factor);
+                    bdata[l++] = (byte)(((v >>> green_shift) & green_mask) * 256 / green_factor);
+                    bdata[l++] = (byte)(((v >>> blue_shift) & blue_mask) * 256 / blue_factor);
+                }
+                for (int m=0; m<padding; m++) {
+                    inputStream.read();
+                }
+            }
+        }
+        return new ImgRaw(width, height, 3, 8, bdata);
+    }
+    
+    private Image readRLE8() throws IOException, BadElementException {
+        
+        // If imageSize field is not provided, calculate it.
+        int imSize = (int)imageSize;
+        if (imSize == 0) {
+            imSize = (int)(bitmapFileSize - bitmapOffset);
+        }
+        
+        int padding = 0;
+        // If width is not 32 bit aligned, then while uncompressing each
+        // scanline will have padding bytes, calculate the amount of padding
+        int remainder = width % 4;
+        if (remainder != 0) {
+            padding = 4 - remainder;
+        }
+        
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        int bytesRead = 0;
+        while (bytesRead < imSize) {
+            bytesRead += inputStream.read(values, bytesRead,
+            imSize - bytesRead);
+        }
+        
+        // Since data is compressed, decompress it
+        byte val[] = decodeRLE(true, values);
+        
+        // Uncompressed data does not have any padding
+        imSize = width * height;
+        
+        if (isBottomUp) {
+            
+            // Convert the bottom up image to a top down format by copying
+            // one scanline from the bottom to the top at a time.
+            // int bytesPerScanline = (int)Math.ceil((double)width/8.0);
+            byte temp[] = new byte[val.length];
+            int bytesPerScanline = width;
+            for (int i=0; i<height; i++) {
+                System.arraycopy(val,
+                imSize - (i+1)*(bytesPerScanline),
+                temp,
+                i*bytesPerScanline, bytesPerScanline);
+            }
+            val = temp;
+        }
+        return indexedModel(val, 8, 4);
+    }
+    
+    private Image readRLE4() throws IOException, BadElementException {
+        
+        // If imageSize field is not specified, calculate it.
+        int imSize = (int)imageSize;
+        if (imSize == 0) {
+            imSize = (int)(bitmapFileSize - bitmapOffset);
+        }
+        
+        int padding = 0;
+        // If width is not 32 byte aligned, then while uncompressing each
+        // scanline will have padding bytes, calculate the amount of padding
+        int remainder = width % 4;
+        if (remainder != 0) {
+            padding = 4 - remainder;
+        }
+        
+        // Read till we have the whole image
+        byte values[] = new byte[imSize];
+        int bytesRead = 0;
+        while (bytesRead < imSize) {
+            bytesRead += inputStream.read(values, bytesRead,
+            imSize - bytesRead);
+        }
+        
+        // Decompress the RLE4 compressed data.
+        byte val[] = decodeRLE(false, values);
+        
+        // Invert it as it is bottom up format.
+        if (isBottomUp) {
+            
+            byte inverted[] = val;
+            val = new byte[width * height];
+            int l = 0, index, lineEnd;
+            
+            for (int i = height-1; i >= 0; i--) {
+                index = i * width;
+                lineEnd = l + width;
+                while(l != lineEnd) {
+                    val[l++] = inverted[index++];
+                }
+            }
+        }
+        int stride = ((width + 1) / 2);
+        byte bdata[] = new byte[stride * height];
+        int ptr = 0;
+        boolean flip = true;
+        int sh = 0;
+        for (int h = 0; h < height; ++h) {
+            for (int w = 0; w < width; ++w) {
+                if ((w & 1) == 0)
+                    bdata[sh + w / 2] = (byte)(val[ptr++] << 4);
+                else
+                    bdata[sh + w / 2] |= (byte)(val[ptr++] & 0x0f);
+            }
+            sh += stride;
+        }
+        return indexedModel(bdata, 4, 4);
+    }
+    
+    private byte[] decodeRLE(boolean is8, byte values[]) {
+        byte val[] = new byte[width * height];
+        try {
+            int ptr = 0;
+            int x = 0;
+            int q = 0;
+            for (int y = 0; y < height && ptr < values.length;) {
+                int count = values[ptr++] & 0xff;
+                if (count != 0) {
+                    // encoded mode
+                    int bt = values[ptr++] & 0xff;
+                    if (is8) {
+                        for (int i = count; i != 0; --i) {
+                            val[q++] = (byte)bt;
+                        }
+                    }
+                    else {
+                        for (int i = 0; i < count; ++i) {
+                            val[q++] = (byte)((i & 1) == 1 ? (bt & 0x0f) : ((bt >>> 4) & 0x0f));
+                        }
+                    }
+                    x += count;
+                }
+                else {
+                    // escape mode
+                    count = values[ptr++] & 0xff;
+                    if (count == 1)
+                        break;
+                    switch (count) {
+                        case 0:
+                            x = 0;
+                            ++y;
+                            q = y * width;
+                            break;
+                        case 2:
+                            // delta mode
+                            x += values[ptr++] & 0xff;
+                            y += values[ptr++] & 0xff;
+                            q = y * width + x;
+                            break;
+                        default:
+                            // absolute mode
+                            if (is8) {
+                                for (int i = count; i != 0; --i)
+                                    val[q++] = (byte)(values[ptr++] & 0xff);
+                            }
+                            else {
+                                int bt = 0;
+                                for (int i = 0; i < count; ++i) {
+                                    if ((i & 1) == 0)
+                                        bt = values[ptr++] & 0xff;
+                                    val[q++] = (byte)((i & 1) == 1 ? (bt & 0x0f) : ((bt >>> 4) & 0x0f));
+                                }
+                            }
+                            x += count;
+                            // read pad byte
+                            if (is8) {
+                                if ((count & 1) == 1)
+                                    ++ptr;
+                            }
+                            else {
+                                if ((count & 3) == 1 || (count & 3) == 2)
+                                    ++ptr;
+                            }
+                            break;
+                    }
+                }
+            }
+        }
+        catch (Exception e) {
+            //empty on purpose
+        }
+        
+        return val;
+    }
+    
+    // Windows defined data type reading methods - everything is little endian
+    
+    // Unsigned 8 bits
+    private int readUnsignedByte(InputStream stream) throws IOException {
+        return (stream.read() & 0xff);
+    }
+    
+    // Unsigned 2 bytes
+    private int readUnsignedShort(InputStream stream) throws IOException {
+        int b1 = readUnsignedByte(stream);
+        int b2 = readUnsignedByte(stream);
+        return ((b2 << 8) | b1) & 0xffff;
+    }
+    
+    // Signed 16 bits
+    private int readShort(InputStream stream) throws IOException {
+        int b1 = readUnsignedByte(stream);
+        int b2 = readUnsignedByte(stream);
+        return (b2 << 8) | b1;
+    }
+    
+    // Unsigned 16 bits
+    private int readWord(InputStream stream) throws IOException {
+        return readUnsignedShort(stream);
+    }
+    
+    // Unsigned 4 bytes
+    private long readUnsignedInt(InputStream stream) throws IOException {
+        int b1 = readUnsignedByte(stream);
+        int b2 = readUnsignedByte(stream);
+        int b3 = readUnsignedByte(stream);
+        int b4 = readUnsignedByte(stream);
+        long l = (long)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
+        return l & 0xffffffff;
+    }
+    
+    // Signed 4 bytes
+    private int readInt(InputStream stream) throws IOException {
+        int b1 = readUnsignedByte(stream);
+        int b2 = readUnsignedByte(stream);
+        int b3 = readUnsignedByte(stream);
+        int b4 = readUnsignedByte(stream);
+        return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
+    }
+    
+    // Unsigned 4 bytes
+    private long readDWord(InputStream stream) throws IOException {
+        return readUnsignedInt(stream);
+    }
+    
+    // 32 bit signed value
+    private int readLong(InputStream stream) throws IOException {
+        return readInt(stream);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/CCITTG4Encoder.java b/LibrarySource/com/lowagie/text/pdf/codec/CCITTG4Encoder.java
new file mode 100644
index 0000000..9fe7b94
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/CCITTG4Encoder.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ *
+ * Modified by Paulo Soares for iText.
+ */
+package com.lowagie.text.pdf.codec;
+import com.lowagie.text.pdf.*;
+
+public class CCITTG4Encoder {
+    
+    /**
+     * The CCITT numerical definition of white.
+     */
+    private static final int WHITE = 0;
+    
+    /**
+     * The CCITT numerical definition of black.
+     */
+    private static final int BLACK = 1;
+    
+    // --- Begin tables for CCITT compression ---
+    
+    private static byte[] byteTable = new byte[] {
+        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,     // 0 to 15
+        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,     // 16 to 31
+        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,     // 32 to 47
+        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,     // 48 to 63
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 64 to 79
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 80 to 95
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 96 to 111
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 112 to 127
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 128 to 143
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 144 to 159
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 160 to 175
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 176 to 191
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 192 to 207
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 208 to 223
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 224 to 239
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0      // 240 to 255
+    };
+    
+    /**
+     * Terminating codes for black runs.
+     */
+    private static int[] termCodesBlack = new int[] {
+        /*     0 0x0000 */     0x0dc0000a, 0x40000003, 0xc0000002, 0x80000002,
+        /*     4 0x0004 */     0x60000003, 0x30000004, 0x20000004, 0x18000005,
+        /*     8 0x0008 */     0x14000006, 0x10000006, 0x08000007, 0x0a000007,
+        /*    12 0x000c */     0x0e000007, 0x04000008, 0x07000008, 0x0c000009,
+        /*    16 0x0010 */     0x05c0000a, 0x0600000a, 0x0200000a, 0x0ce0000b,
+        /*    20 0x0014 */     0x0d00000b, 0x0d80000b, 0x06e0000b, 0x0500000b,
+        /*    24 0x0018 */     0x02e0000b, 0x0300000b, 0x0ca0000c, 0x0cb0000c,
+        /*    28 0x001c */     0x0cc0000c, 0x0cd0000c, 0x0680000c, 0x0690000c,
+        /*    32 0x0020 */     0x06a0000c, 0x06b0000c, 0x0d20000c, 0x0d30000c,
+        /*    36 0x0024 */     0x0d40000c, 0x0d50000c, 0x0d60000c, 0x0d70000c,
+        /*    40 0x0028 */     0x06c0000c, 0x06d0000c, 0x0da0000c, 0x0db0000c,
+        /*    44 0x002c */     0x0540000c, 0x0550000c, 0x0560000c, 0x0570000c,
+        /*    48 0x0030 */     0x0640000c, 0x0650000c, 0x0520000c, 0x0530000c,
+        /*    52 0x0034 */     0x0240000c, 0x0370000c, 0x0380000c, 0x0270000c,
+        /*    56 0x0038 */     0x0280000c, 0x0580000c, 0x0590000c, 0x02b0000c,
+        /*    60 0x003c */     0x02c0000c, 0x05a0000c, 0x0660000c, 0x0670000c
+    };
+    
+    /**
+     * Terminating codes for white runs.
+     */
+    private static int[] termCodesWhite = new int[] {
+        /*     0 0x0000 */     0x35000008, 0x1c000006, 0x70000004, 0x80000004,
+        /*     4 0x0004 */     0xb0000004, 0xc0000004, 0xe0000004, 0xf0000004,
+        /*     8 0x0008 */     0x98000005, 0xa0000005, 0x38000005, 0x40000005,
+        /*    12 0x000c */     0x20000006, 0x0c000006, 0xd0000006, 0xd4000006,
+        /*    16 0x0010 */     0xa8000006, 0xac000006, 0x4e000007, 0x18000007,
+        /*    20 0x0014 */     0x10000007, 0x2e000007, 0x06000007, 0x08000007,
+        /*    24 0x0018 */     0x50000007, 0x56000007, 0x26000007, 0x48000007,
+        /*    28 0x001c */     0x30000007, 0x02000008, 0x03000008, 0x1a000008,
+        /*    32 0x0020 */     0x1b000008, 0x12000008, 0x13000008, 0x14000008,
+        /*    36 0x0024 */     0x15000008, 0x16000008, 0x17000008, 0x28000008,
+        /*    40 0x0028 */     0x29000008, 0x2a000008, 0x2b000008, 0x2c000008,
+        /*    44 0x002c */     0x2d000008, 0x04000008, 0x05000008, 0x0a000008,
+        /*    48 0x0030 */     0x0b000008, 0x52000008, 0x53000008, 0x54000008,
+        /*    52 0x0034 */     0x55000008, 0x24000008, 0x25000008, 0x58000008,
+        /*    56 0x0038 */     0x59000008, 0x5a000008, 0x5b000008, 0x4a000008,
+        /*    60 0x003c */     0x4b000008, 0x32000008, 0x33000008, 0x34000008
+    };
+    
+    /**
+     * Make-up codes for black runs.
+     */
+    private static int[] makeupCodesBlack = new int[] {
+        /*     0 0x0000 */     0x00000000, 0x03c0000a, 0x0c80000c, 0x0c90000c,
+        /*     4 0x0004 */     0x05b0000c, 0x0330000c, 0x0340000c, 0x0350000c,
+        /*     8 0x0008 */     0x0360000d, 0x0368000d, 0x0250000d, 0x0258000d,
+        /*    12 0x000c */     0x0260000d, 0x0268000d, 0x0390000d, 0x0398000d,
+        /*    16 0x0010 */     0x03a0000d, 0x03a8000d, 0x03b0000d, 0x03b8000d,
+        /*    20 0x0014 */     0x0290000d, 0x0298000d, 0x02a0000d, 0x02a8000d,
+        /*    24 0x0018 */     0x02d0000d, 0x02d8000d, 0x0320000d, 0x0328000d,
+        /*    28 0x001c */     0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c,
+        /*    32 0x0020 */     0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c,
+        /*    36 0x0024 */     0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c,
+        /*    40 0x0028 */     0x01f0000c, 0x00000000, 0x00000000, 0x00000000,
+        /*    44 0x002c */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    48 0x0030 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    52 0x0034 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    56 0x0038 */     0x00000000, 0x00000000, 0x00000000, 0x00000000
+    };
+    
+    /**
+     * Make-up codes for white runs.
+     */
+    private static int[] makeupCodesWhite = new int[] {
+        /*     0 0x0000 */     0x00000000, 0xd8000005, 0x90000005, 0x5c000006,
+        /*     4 0x0004 */     0x6e000007, 0x36000008, 0x37000008, 0x64000008,
+        /*     8 0x0008 */     0x65000008, 0x68000008, 0x67000008, 0x66000009,
+        /*    12 0x000c */     0x66800009, 0x69000009, 0x69800009, 0x6a000009,
+        /*    16 0x0010 */     0x6a800009, 0x6b000009, 0x6b800009, 0x6c000009,
+        /*    20 0x0014 */     0x6c800009, 0x6d000009, 0x6d800009, 0x4c000009,
+        /*    24 0x0018 */     0x4c800009, 0x4d000009, 0x60000006, 0x4d800009,
+        /*    28 0x001c */     0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c,
+        /*    32 0x0020 */     0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c,
+        /*    36 0x0024 */     0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c,
+        /*    40 0x0028 */     0x01f0000c, 0x00000000, 0x00000000, 0x00000000,
+        /*    44 0x002c */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    48 0x0030 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    52 0x0034 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        /*    56 0x0038 */     0x00000000, 0x00000000, 0x00000000, 0x00000000
+    };
+    
+    /**
+     * Pass mode table.
+     */
+    private static int[] passMode = new int[] {
+        0x10000004            // 0001
+    };
+    
+    /**
+     * Vertical mode table.
+     */
+    private static int[] vertMode = new int[] {
+        0x06000007,            // 0000011
+        0x0c000006,            // 000011
+        0x60000003,            // 011
+        0x80000001,            // 1
+        0x40000003,            // 010
+        0x08000006,            // 000010
+        0x04000007            // 0000010
+    };
+    
+    /**
+     * Horizontal mode table.
+     */
+    private static int[] horzMode = new int[] {
+        0x20000003            // 001
+    };
+    
+    /**
+     * Black and white terminating code table.
+     */
+    private static int[][] termCodes =
+    new int[][] {termCodesWhite, termCodesBlack};
+    
+    /**
+     * Black and white make-up code table.
+     */
+    private static int[][] makeupCodes =
+        new int[][] {makeupCodesWhite, makeupCodesBlack};
+    
+    /**
+     * Black and white pass mode table.
+     */
+    private static int[][] pass = new int[][] {passMode, passMode};
+    
+    /**
+     * Black and white vertical mode table.
+     */
+    private static int[][] vert = new int[][] {vertMode, vertMode};
+    
+    /**
+     * Black and white horizontal mode table.
+     */
+    private static int[][] horz = new int[][] {horzMode, horzMode};
+    
+    // --- End tables for CCITT compression ---
+    
+    /**
+     * Output bit buffer.
+     */
+    private int bits;
+    
+    /**
+     * Number of bits in the output bit buffer.
+     */
+    private int ndex;
+    private ByteBuffer outBuf = new ByteBuffer(1024);
+    private int width;
+    private int lineStride;
+    byte[] refData = null;
+    
+    /**
+     * Constructs a <code>TIFFFaxEncoder</code> for CCITT bilevel encoding.
+     */
+    public CCITTG4Encoder(int width) {
+        this.width = width;
+        lineStride = (width + 7) / 8;
+        initBitBuf();
+    }
+    
+    public static byte[] compress(byte[] data, int width, int height) {
+        CCITTG4Encoder g4 = new CCITTG4Encoder(width);
+        int yPos = 0;
+        while (height-- != 0) {
+            g4.encodeT6Line(data, yPos);
+            yPos += g4.lineStride;
+        }
+        return g4.close();
+    }
+    
+    public void encodeT6Lines(byte data[], int lineAddr, int height) {
+        int yPos = lineAddr;
+        while (height-- != 0) {
+            encodeT6Line(data, yPos);
+            yPos += lineStride;
+        }
+    }
+    /**
+     * Return min of <code>maxOffset</code> or offset of first pixel
+     * different from pixel at <code>bitOffset</code>.
+     */
+    private int nextState(byte[] data,
+        int    base,
+        int    bitOffset,
+        int    maxOffset) {
+        if(data == null) {
+            return maxOffset;
+        }
+        
+        int next  = base + (bitOffset>>>3);
+        int end   = base + (maxOffset>>>3);
+        if(end == data.length) { // Prevents out of bounds exception below
+            end--;
+        }
+        if (next == data.length) // and so does this
+            --next;
+        int extra = bitOffset & 0x7;
+        
+        int  testbyte;
+        if((data[next] & (0x80 >>> extra)) != 0) {    // look for "0"
+            testbyte = ~(data[next]) & (0xff >>> extra);
+            while (next < end) {
+                if (testbyte != 0) {
+                    break;
+                }
+                testbyte = ~(data[++next]) & 0xff;
+            }
+        } else {                // look for "1"
+            if ((testbyte = (data[next] & (0xff >>> extra))) != 0) {
+                bitOffset = (next-base)*8 + byteTable[testbyte];
+                return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
+            }
+            while (next < end) {
+                if ((testbyte = data[++next]&0xff) != 0) {
+                    // "1" is in current byte
+                    bitOffset = (next-base)*8 + byteTable[testbyte];
+                    return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
+                }
+            }
+        }
+        bitOffset = (next-base)*8 + byteTable[testbyte];
+        return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
+    }
+    
+    /**
+     * Initialize bit buffer machinery.
+     */
+    private void initBitBuf() {
+        ndex = 0;
+        bits = 0x00000000;
+    }
+    
+    /**
+     * Get code for run and add to compressed bitstream.
+     */
+    private void add1DBits(
+        int    count, // #pixels in run
+        int    color) // color of run
+    {
+        int                 sixtyfours;
+        int        mask;
+        
+        if (count < 0)
+            return;
+        sixtyfours = count >>> 6;    // count / 64;
+        count = count & 0x3f;       // count % 64
+        if (sixtyfours != 0) {
+            for ( ; sixtyfours > 40; sixtyfours -= 40) {
+                mask = makeupCodes[color][40];
+                bits |= (mask & 0xfff80000) >>> ndex;
+                ndex += (int)(mask & 0x0000ffff);
+                while (ndex > 7) {
+                    outBuf.append((byte)(bits >>> 24));
+                    bits <<= 8;
+                    ndex -= 8;
+                }
+            }
+            
+            mask = makeupCodes[color][sixtyfours];
+            bits |= (mask & 0xfff80000) >>> ndex;
+            ndex += (int)(mask & 0x0000ffff);
+            while (ndex > 7) {
+                outBuf.append((byte)(bits >>> 24));
+                bits <<= 8;
+                ndex -= 8;
+            }
+        }
+        
+        mask = termCodes[color][count];
+        bits |= (mask & 0xfff80000) >>> ndex;
+        ndex += (int)(mask & 0x0000ffff);
+        while (ndex > 7) {
+            outBuf.append((byte)(bits >>> 24));
+            bits <<= 8;
+            ndex -= 8;
+        }        
+    }
+    
+    /**
+     * Place entry from mode table into compressed bitstream.
+     */
+    private void add2DBits(
+        int[][] mode,  // 2-D mode to be encoded
+        int     entry) // mode entry (0 unless vertical)
+    {
+        int        mask;
+        int                 color = 0;
+        
+        mask = mode[color][entry];
+        bits |= (mask & 0xfff80000) >>> ndex;
+        ndex += (int)(mask & 0x0000ffff);
+        while (ndex > 7) {
+            outBuf.append((byte)(bits >>> 24));
+            bits <<= 8;
+            ndex -= 8;
+        }
+    }
+    
+    /**
+     * Add an End-of-Line (EOL == 0x001) to the compressed bitstream
+     * with optional byte alignment.
+     */
+    private void addEOL(boolean is1DMode,// 1D encoding
+    boolean addFill, // byte aligned EOLs
+    boolean add1    // add1 ? EOL+1 : EOL+0
+    )
+    {
+        
+        //
+        // Add zero-valued fill bits such that the EOL is aligned as
+        //
+        //     xxxx 0000 0000 0001
+        //
+        if(addFill) {
+            //
+            // Simply increment the bit count. No need to feed bits into
+            // the output buffer at this point as there are at most 7 bits
+            // in the bit buffer, at most 7 are added here, and at most
+            // 13 below making the total 7+7+13 = 27 before the bit feed
+            // at the end of this routine.
+            //
+            ndex += ((ndex <= 4) ? 4 - ndex : 12 - ndex);
+        }
+        
+        //
+        // Write EOL into buffer
+        //
+        if(is1DMode) {
+            bits |= 0x00100000 >>> ndex;
+            ndex += 12;
+        } else {
+            bits |= (add1 ? 0x00180000 : 0x00100000) >>> ndex;
+            ndex += 13;
+        }
+        
+        while (ndex > 7) {
+            outBuf.append((byte)(bits >>> 24));
+            bits <<= 8;
+            ndex -= 8;
+        }
+    }
+    
+    /**
+     * Add an End-of-Facsimile-Block (EOFB == 0x001001) to the compressed
+     * bitstream.
+     */
+    private void addEOFB()
+    {
+        //
+        // eofb code
+        //
+        bits |= 0x00100100 >>> ndex;
+        
+        //
+        // eofb code length
+        //
+        ndex += 24;
+        
+        //
+        // flush all pending bits
+        //
+        while(ndex > 0) {
+            outBuf.append((byte)(bits >>> 24));
+            bits <<= 8;
+            ndex -= 8;
+        }
+    }
+
+    public void encodeT6Line(byte data[], int lineAddr) {
+        int a0   = 0;
+        int last = a0 + width;
+
+        int testbit = 
+        ((data[lineAddr + (a0>>>3)]&0xff) >>>
+        (7-(a0 & 0x7))) & 0x1;
+        int a1 = testbit != 0 ?
+        a0 : nextState(data, lineAddr, a0, last);
+
+        testbit = refData == null ?
+        0: ((refData[(a0>>>3)]&0xff) >>>
+        (7-(a0 & 0x7))) & 0x1;
+        int b1 = testbit != 0 ?
+        a0 : nextState(refData, 0, a0, last);
+
+        //
+        // The current color is set to WHITE at line start
+        //
+        int color = WHITE;
+
+        while(true) {
+            int b2 = nextState(refData, 0, b1, last);
+            if(b2 < a1) {          // pass mode
+                add2DBits(pass, 0);
+                a0 = b2;
+            } else {
+                int tmp = b1 - a1 + 3;
+                if((tmp <= 6) && (tmp >= 0)) { // vertical mode
+                    add2DBits(vert, tmp);
+                    a0 = a1;
+                } else {            // horizontal mode
+                    int a2 = nextState(data, lineAddr, a1, last);
+                    add2DBits(horz, 0);
+                    add1DBits(a1-a0, color);
+                    add1DBits(a2-a1, color^1);
+                    if (a2 <= a0)
+                        throw new RuntimeException("G4 encoding error.");
+                    a0 = a2;
+                }
+            }
+            if(a0 >= last) {
+                break;
+            }
+            color = ((data[lineAddr + (a0>>>3)]&0xff) >>>
+            (7-(a0 & 0x7))) & 0x1;
+            a1 = nextState(data, lineAddr, a0, last);
+            b1 = nextState(refData, 0, a0, last);
+            testbit = refData == null ?
+            0: ((refData[(b1>>>3)]&0xff) >>>
+            (7-(b1 & 0x7))) & 0x1;
+            if(testbit == color) {
+                b1 = nextState(refData, 0, b1, last);
+            }
+        }
+
+        if (refData == null)
+            refData = new byte[lineStride + 1];
+        System.arraycopy(data, lineAddr, refData, 0, lineStride);
+    }
+    
+    public byte[] close() {
+        addEOFB();
+        return outBuf.toByteArray();
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/GifImage.java b/LibrarySource/com/lowagie/text/pdf/codec/GifImage.java
new file mode 100644
index 0000000..0981417
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/GifImage.java
@@ -0,0 +1,592 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf.codec;
+
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.*;
+import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+
+/** Reads gif images of all types. All the images in a gif are read in the constructors
+ * and can be retrieved with other methods.
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class GifImage {
+    
+    protected DataInputStream in;
+    protected int width;            // full image width
+    protected int height;           // full image height
+    protected boolean gctFlag;      // global color table used
+
+    protected int bgIndex;          // background color index
+    protected int bgColor;          // background color
+    protected int pixelAspect;      // pixel aspect ratio
+
+    protected boolean lctFlag;      // local color table flag
+    protected boolean interlace;    // interlace flag
+    protected int lctSize;          // local color table size
+
+    protected int ix, iy, iw, ih;   // current image rectangle
+
+    protected byte[] block = new byte[256];  // current data block
+    protected int blockSize = 0;    // block size
+
+    // last graphic control extension info
+    protected int dispose = 0;   // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
+    protected boolean transparency = false;   // use transparent color
+    protected int delay = 0;        // delay in milliseconds
+    protected int transIndex;       // transparent color index
+
+    protected static final int MaxStackSize = 4096;   // max decoder pixel stack size
+
+    // LZW decoder working arrays
+    protected short[] prefix;
+    protected byte[] suffix;
+    protected byte[] pixelStack;
+    protected byte[] pixels;
+
+    protected byte m_out[];
+    protected int m_bpc;
+    protected int m_gbpc;
+    protected byte m_global_table[];
+    protected byte m_local_table[];
+    protected byte m_curr_table[];
+    protected int m_line_stride;
+    protected byte fromData[];
+    protected URL fromUrl;
+
+
+    protected ArrayList frames = new ArrayList();     // frames read from current file
+
+    /** Reads gif images from an URL.
+     * @param url the URL
+     * @throws IOException on error
+     */    
+    public GifImage(URL url) throws IOException {
+        fromUrl = url;
+        InputStream is = null;
+        try {
+            is = url.openStream();
+            process(is);
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+    
+    /** Reads gif images from a file.
+     * @param file the file
+     * @throws IOException on error
+     */    
+    public GifImage(String file) throws IOException {
+        this(Image.toURL(file));
+    }
+    
+    /** Reads gif images from a byte array.
+     * @param data the byte array
+     * @throws IOException on error
+     */    
+    public GifImage(byte data[]) throws IOException {
+        fromData = data;
+        InputStream is = null;
+        try {
+            is = new ByteArrayInputStream(data);
+            process(is);
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+    
+    /** Reads gif images from a stream. The stream is not closed.
+     * @param is the stream
+     * @throws IOException on error
+     */    
+    public GifImage(InputStream is) throws IOException {
+        process(is);
+    }
+    
+    /** Gets the number of frames the gif has.
+     * @return the number of frames the gif has
+     */    
+    public int getFrameCount() {
+        return frames.size();
+    }
+    
+    /** Gets the image from a frame. The first frame is 1.
+     * @param frame the frame to get the image from
+     * @return the image
+     */    
+    public Image getImage(int frame) {
+        GifFrame gf = (GifFrame)frames.get(frame - 1);
+        return gf.image;
+    }
+    
+    /** Gets the [x,y] position of the frame in reference to the
+     * logical screen.
+     * @param frame the frame
+     * @return the [x,y] position of the frame
+     */    
+    public int[] getFramePosition(int frame) {
+        GifFrame gf = (GifFrame)frames.get(frame - 1);
+        return new int[]{gf.ix, gf.iy};
+        
+    }
+    
+    /** Gets the logical screen. The images may be smaller and placed
+     * in some position in this screen to playback some animation.
+     * No image will be be bigger that this.
+     * @return the logical screen dimensions as [x,y]
+     */    
+    public int[] getLogicalScreen() {
+        return new int[]{width, height};
+    }
+    
+    void process(InputStream is) throws IOException {
+        in = new DataInputStream(new BufferedInputStream(is));
+        readHeader();
+        readContents();
+        if (frames.size() == 0)
+            throw new IOException("The file does not contain any valid image.");
+    }
+    
+    /**
+     * Reads GIF file header information.
+     */
+    protected void readHeader() throws IOException {
+        String id = "";
+        for (int i = 0; i < 6; i++)
+            id += (char)in.read();
+        if (!id.startsWith("GIF8")) {
+            throw new IOException("Gif signature nor found.");
+        }
+        
+        readLSD();
+        if (gctFlag) {
+            m_global_table = readColorTable(m_gbpc);
+        }
+    }
+
+    /**
+     * Reads Logical Screen Descriptor
+     */
+    protected void readLSD() throws IOException {
+        
+        // logical screen size
+        width = readShort();
+        height = readShort();
+        
+        // packed fields
+        int packed = in.read();
+        gctFlag = (packed & 0x80) != 0;      // 1   : global color table flag
+        m_gbpc = (packed & 7) + 1;
+        bgIndex = in.read();        // background color index
+        pixelAspect = in.read();    // pixel aspect ratio
+    }
+
+    /**
+     * Reads next 16-bit value, LSB first
+     */
+    protected int readShort() throws IOException {
+        // read 16-bit value, LSB first
+        return in.read() | (in.read() << 8);
+    }
+
+    /**
+     * Reads next variable length block from input.
+     *
+     * @return number of bytes stored in "buffer"
+     */
+    protected int readBlock() throws IOException {
+        blockSize = in.read();
+        if (blockSize <= 0)
+            return blockSize = 0;
+        for (int k = 0; k < blockSize; ++k) {
+            int v = in.read();
+            if (v < 0) {
+                return blockSize = k;
+            }
+            block[k] = (byte)v;
+        }
+        return blockSize;
+    }
+
+    protected byte[] readColorTable(int bpc) throws IOException {
+        int ncolors = 1 << bpc;
+        int nbytes = 3*ncolors;
+        bpc = newBpc(bpc);
+        byte table[] = new byte[(1 << bpc) * 3];
+        in.readFully(table, 0, nbytes);
+        return table;
+    }
+ 
+    
+    static protected int newBpc(int bpc) {
+        switch (bpc) {
+            case 1:
+            case 2:
+            case 4:
+                break;
+            case 3:
+                return 4;
+            default:
+                return 8;
+        }
+        return bpc;
+    }
+    
+    protected void readContents() throws IOException {
+        // read GIF file content blocks
+        boolean done = false;
+        while (!done) {
+            int code = in.read();
+            switch (code) {
+                
+                case 0x2C:    // image separator
+                    readImage();
+                    break;
+                    
+                case 0x21:    // extension
+                    code = in.read();
+                    switch (code) {
+                        
+                        case 0xf9:    // graphics control extension
+                            readGraphicControlExt();
+                            break;
+                            
+                        case 0xff:    // application extension
+                            readBlock();
+                            skip();        // don't care
+                            break;
+                            
+                        default:    // uninteresting extension
+                            skip();
+                    }
+                    break;
+                    
+                default:
+                    done = true;
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Reads next frame image
+     */
+    protected void readImage() throws IOException {
+        ix = readShort();    // (sub)image position & size
+        iy = readShort();
+        iw = readShort();
+        ih = readShort();
+        
+        int packed = in.read();
+        lctFlag = (packed & 0x80) != 0;     // 1 - local color table flag
+        interlace = (packed & 0x40) != 0;   // 2 - interlace flag
+        // 3 - sort flag
+        // 4-5 - reserved
+        lctSize = 2 << (packed & 7);        // 6-8 - local color table size
+        m_bpc = newBpc(m_gbpc);
+        if (lctFlag) {
+            m_curr_table = readColorTable((packed & 7) + 1);   // read table
+            m_bpc = newBpc((packed & 7) + 1);
+        }
+        else {
+            m_curr_table = m_global_table;
+        }
+        if (transparency && transIndex >= m_curr_table.length / 3)
+            transparency = false;
+        if (transparency && m_bpc == 1) { // Acrobat 5.05 doesn't like this combination
+            byte tp[] = new byte[12];
+            System.arraycopy(m_curr_table, 0, tp, 0, 6);
+            m_curr_table = tp;
+            m_bpc = 2;
+        }
+        boolean skipZero = decodeImageData();   // decode pixel data
+        if (!skipZero)
+            skip();
+        
+        Image img = null;
+        try {
+            img = new ImgRaw(iw, ih, 1, m_bpc, m_out);
+            PdfArray colorspace = new PdfArray();
+            colorspace.add(PdfName.INDEXED);
+            colorspace.add(PdfName.DEVICERGB);
+            int len = m_curr_table.length;
+            colorspace.add(new PdfNumber(len / 3 - 1));
+            colorspace.add(new PdfString(m_curr_table));
+            PdfDictionary ad = new PdfDictionary();
+            ad.put(PdfName.COLORSPACE, colorspace);
+            img.setAdditional(ad);
+            if (transparency) {
+                img.setTransparency(new int[]{transIndex, transIndex});
+            }
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        img.setOriginalType(Image.ORIGINAL_GIF);
+        img.setOriginalData(fromData);
+        img.setUrl(fromUrl);
+        GifFrame gf = new GifFrame();
+        gf.image = img;
+        gf.ix = ix;
+        gf.iy = iy;
+        frames.add(gf);   // add image to frame list
+        
+        resetFrame();
+        
+    }
+    
+    protected boolean decodeImageData() throws IOException {
+        int NullCode = -1;
+        int npix = iw * ih;
+        int available, clear, code_mask, code_size, end_of_information, in_code, old_code,
+        bits, code, count, i, datum, data_size, first, top, bi, pi;
+        boolean skipZero = false;
+        
+        if (prefix == null)
+            prefix = new short[MaxStackSize];
+        if (suffix == null)
+            suffix = new byte[MaxStackSize];
+        if (pixelStack == null)
+            pixelStack = new byte[MaxStackSize+1];
+        
+        m_line_stride = (iw * m_bpc + 7) / 8;
+        m_out = new byte[m_line_stride * ih];
+        int pass = 1;
+        int inc = interlace ? 8 : 1;
+        int line = 0;
+        int xpos = 0;
+        
+        //  Initialize GIF data stream decoder.
+        
+        data_size = in.read();
+        clear = 1 << data_size;
+        end_of_information = clear + 1;
+        available = clear + 2;
+        old_code = NullCode;
+        code_size = data_size + 1;
+        code_mask = (1 << code_size) - 1;
+        for (code = 0; code < clear; code++) {
+            prefix[code] = 0;
+            suffix[code] = (byte) code;
+        }
+        
+        //  Decode GIF pixel stream.
+        
+        datum = bits = count = first = top = pi = bi = 0;
+        
+        for (i = 0; i < npix; ) {
+            if (top == 0) {
+                if (bits < code_size) {
+                    //  Load bytes until there are enough bits for a code.
+                    if (count == 0) {
+                        // Read a new data block.
+                        count = readBlock();
+                        if (count <= 0) {
+                            skipZero = true;
+                            break;
+                        }
+                        bi = 0;
+                    }
+                    datum += (((int) block[bi]) & 0xff) << bits;
+                    bits += 8;
+                    bi++;
+                    count--;
+                    continue;
+                }
+                
+                //  Get the next code.
+                
+                code = datum & code_mask;
+                datum >>= code_size;
+                bits -= code_size;
+                
+                //  Interpret the code
+                
+                if ((code > available) || (code == end_of_information))
+                    break;
+                if (code == clear) {
+                    //  Reset decoder.
+                    code_size = data_size + 1;
+                    code_mask = (1 << code_size) - 1;
+                    available = clear + 2;
+                    old_code = NullCode;
+                    continue;
+                }
+                if (old_code == NullCode) {
+                    pixelStack[top++] = suffix[code];
+                    old_code = code;
+                    first = code;
+                    continue;
+                }
+                in_code = code;
+                if (code == available) {
+                    pixelStack[top++] = (byte) first;
+                    code = old_code;
+                }
+                while (code > clear) {
+                    pixelStack[top++] = suffix[code];
+                    code = prefix[code];
+                }
+                first = ((int) suffix[code]) & 0xff;
+                
+                //  Add a new string to the string table,
+                
+                if (available >= MaxStackSize)
+                    break;
+                pixelStack[top++] = (byte) first;
+                prefix[available] = (short) old_code;
+                suffix[available] = (byte) first;
+                available++;
+                if (((available & code_mask) == 0) && (available < MaxStackSize)) {
+                    code_size++;
+                    code_mask += available;
+                }
+                old_code = in_code;
+            }
+            
+            //  Pop a pixel off the pixel stack.
+            
+            top--;
+            i++;
+            
+            setPixel(xpos, line, pixelStack[top]);
+            ++xpos;
+            if (xpos >= iw) {
+                xpos = 0;
+                line += inc;
+                if (line >= ih) {
+                    if (interlace) {
+                        do {
+                            pass++;
+                            switch (pass) {
+                                case 2:
+                                    line = 4;
+                                    break;
+                                case 3:
+                                    line = 2;
+                                    inc = 4;
+                                    break;
+                                case 4:
+                                    line = 1;
+                                    inc = 2;
+                                    break;
+                                default: // this shouldn't happen
+                                    line = ih - 1;
+                                    inc = 0;
+                            }
+                        } while (line >= ih);
+                    }
+                    else {
+                        line = ih - 1; // this shouldn't happen
+                        inc = 0;
+                    }
+                }
+            }
+        }
+        return skipZero;
+    }
+    
+    
+    protected void setPixel(int x, int y, int v) {
+        if (m_bpc == 8) {
+            int pos = x + iw * y;
+            m_out[pos] = (byte)v;
+        }
+        else {
+            int pos = m_line_stride * y + x / (8 / m_bpc);
+            int vout = v << (8 - m_bpc * (x % (8 / m_bpc))- m_bpc);
+            m_out[pos] |= vout;
+        }
+    }
+    
+    /**
+     * Resets frame state for reading next image.
+     */
+    protected void resetFrame() {
+        boolean transparency = false;
+        int delay = 0;
+    }
+
+    /**
+     * Reads Graphics Control Extension values
+     */
+    protected void readGraphicControlExt() throws IOException {
+        in.read();    // block size
+        int packed = in.read();   // packed fields
+        dispose = (packed & 0x1c) >> 2;   // disposal method
+        if (dispose == 0)
+            dispose = 1;   // elect to keep old image if discretionary
+        transparency = (packed & 1) != 0;
+        delay = readShort() * 10;   // delay in milliseconds
+        transIndex = in.read();        // transparent color index
+        in.read();                     // block terminator
+    }
+    
+    /**
+     * Skips variable length blocks up to and including
+     * next zero length block.
+     */
+    protected void skip() throws IOException {
+        do {
+            readBlock();
+        } while (blockSize > 0);
+    }
+
+    static class GifFrame {
+        Image image;
+        int ix;
+        int iy;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/PngImage.java b/LibrarySource/com/lowagie/text/pdf/codec/PngImage.java
new file mode 100644
index 0000000..95b1a4d
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/PngImage.java
@@ -0,0 +1,989 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ *
+ * The original JAI codecs have the following license
+ *
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+
+package com.lowagie.text.pdf.codec;
+
+import headless.awt.color.ICC_Profile;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Image;
+import com.lowagie.text.ImgRaw;
+import com.lowagie.text.pdf.ByteBuffer;
+import com.lowagie.text.pdf.PdfArray;
+import com.lowagie.text.pdf.PdfDictionary;
+import com.lowagie.text.pdf.PdfLiteral;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfNumber;
+import com.lowagie.text.pdf.PdfObject;
+import com.lowagie.text.pdf.PdfReader;
+import com.lowagie.text.pdf.PdfString;
+
+/** Reads a PNG image. All types of PNG can be read.
+ * <p>
+ * It is based in part in the JAI codec.
+ *
+ * @author  Paulo Soares (psoares at consiste.pt)
+ */
+public class PngImage {
+/** Some PNG specific values. */
+    public static final int[] PNGID = {137, 80, 78, 71, 13, 10, 26, 10};
+    
+/** A PNG marker. */
+    public static final String IHDR = "IHDR";
+    
+/** A PNG marker. */
+    public static final String PLTE = "PLTE";
+    
+/** A PNG marker. */
+    public static final String IDAT = "IDAT";
+    
+/** A PNG marker. */
+    public static final String IEND = "IEND";
+    
+/** A PNG marker. */
+    public static final String tRNS = "tRNS";
+    
+/** A PNG marker. */
+    public static final String pHYs = "pHYs";
+    
+/** A PNG marker. */
+    public static final String gAMA = "gAMA";
+    
+/** A PNG marker. */
+    public static final String cHRM = "cHRM";
+    
+/** A PNG marker. */
+    public static final String sRGB = "sRGB";
+    
+/** A PNG marker. */
+    public static final String iCCP = "iCCP";
+    
+    private static final int TRANSFERSIZE = 4096;
+    private static final int PNG_FILTER_NONE = 0;
+    private static final int PNG_FILTER_SUB = 1;
+    private static final int PNG_FILTER_UP = 2;
+    private static final int PNG_FILTER_AVERAGE = 3;
+    private static final int PNG_FILTER_PAETH = 4;
+    private static final PdfName intents[] = {PdfName.PERCEPTUAL,
+        PdfName.RELATIVECALORIMETRIC,PdfName.SATURATION,PdfName.ABSOLUTECALORIMETRIC};
+    
+    InputStream is;
+    DataInputStream dataStream;
+    int width;
+    int height;
+    int bitDepth;
+    int colorType;
+    int compressionMethod;
+    int filterMethod;
+    int interlaceMethod;
+    PdfDictionary additional = new PdfDictionary();
+    byte image[];
+    byte smask[];
+    byte trans[];
+    NewByteArrayOutputStream idat = new NewByteArrayOutputStream();
+    int dpiX;
+    int dpiY;
+    float XYRatio;
+    boolean genBWMask;
+    boolean palShades;
+    int transRedGray = -1;
+    int transGreen = -1;
+    int transBlue = -1;
+    int inputBands;
+    int bytesPerPixel; // number of bytes per input pixel
+    byte colorTable[];
+    float gamma = 1f;
+    boolean hasCHRM = false;
+    float xW, yW, xR, yR, xG, yG, xB, yB;
+    PdfName intent;
+    ICC_Profile icc_profile;
+
+    
+    
+    /** Creates a new instance of PngImage */
+    PngImage(InputStream is) {
+        this.is = is;
+    }
+    
+    /** Reads a PNG from an url.
+     * @param url the url
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(URL url) throws IOException {
+        InputStream is = null;
+        try {
+            is = url.openStream();
+            Image img = getImage(is);
+            img.setUrl(url);
+            return img;
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+    
+    /** Reads a PNG from a stream.
+     * @param is the stream
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(InputStream is) throws IOException {
+        PngImage png = new PngImage(is);
+        return png.getImage();
+    }
+    
+    /** Reads a PNG from a file.
+     * @param file the file
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(String file) throws IOException {
+        return getImage(Image.toURL(file));
+    }
+    
+    /** Reads a PNG from a byte array.
+     * @param data the byte array
+     * @throws IOException on error
+     * @return the image
+     */    
+    public static Image getImage(byte data[]) throws IOException {
+        InputStream is = null;
+        try {
+            is = new ByteArrayInputStream(data);
+            Image img = getImage(is);
+            img.setOriginalData(data);
+            return img;
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+    
+    boolean checkMarker(String s) {
+        if (s.length() != 4)
+            return false;
+        for (int k = 0; k < 4; ++k) {
+            char c = s.charAt(k);
+            if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z'))
+                return false;
+        }
+        return true;
+    }
+    
+    void readPng() throws IOException {
+        for (int i = 0; i < PNGID.length; i++) {
+            if (PNGID[i] != is.read())	{
+                throw new IOException("File is not a valid PNG.");
+            }
+        }
+        byte buffer[] = new byte[TRANSFERSIZE];
+        while (true) {
+            int len = getInt(is);
+            String marker = getString(is);
+            if (len < 0 || !checkMarker(marker))
+                throw new IOException("Corrupted PNG file.");
+            if (IDAT.equals(marker)) {
+                int size;
+                while (len != 0) {
+                    size = is.read(buffer, 0, Math.min(len, TRANSFERSIZE));
+                    if (size < 0)
+                        return;
+                    idat.write(buffer, 0, size);
+                    len -= size;
+                }
+            }
+            else if (tRNS.equals(marker)) {
+                switch (colorType) {
+                    case 0:
+                        if (len >= 2) {
+                            len -= 2;
+                            int gray = getWord(is);
+                            if (bitDepth == 16)
+                                transRedGray = gray;
+                            else
+                                additional.put(PdfName.MASK, new PdfLiteral("["+gray+" "+gray+"]"));
+                        }
+                        break;
+                    case 2:
+                        if (len >= 6) {
+                            len -= 6;
+                            int red = getWord(is);
+                            int green = getWord(is);
+                            int blue = getWord(is);
+                            if (bitDepth == 16) {
+                                transRedGray = red;
+                                transGreen = green;
+                                transBlue = blue;
+                            }
+                            else
+                                additional.put(PdfName.MASK, new PdfLiteral("["+red+" "+red+" "+green+" "+green+" "+blue+" "+blue+"]"));
+                        }
+                        break;
+                    case 3:
+                        if (len > 0) {
+                            trans = new byte[len];
+                            for (int k = 0; k < len; ++k)
+                                trans[k] = (byte)is.read();
+                            len = 0;
+                        }
+                        break;
+                }
+                Image.skip(is, len);
+            }
+            else if (IHDR.equals(marker)) {
+                width = getInt(is);
+                height = getInt(is);
+                
+                bitDepth = is.read();
+                colorType = is.read();
+                compressionMethod = is.read();
+                filterMethod = is.read();
+                interlaceMethod = is.read();
+            }
+            else if (PLTE.equals(marker)) {
+                if (colorType == 3) {
+                    PdfArray colorspace = new PdfArray();
+                    colorspace.add(PdfName.INDEXED);
+                    colorspace.add(getColorspace());
+                    colorspace.add(new PdfNumber(len / 3 - 1));
+                    ByteBuffer colortable = new ByteBuffer();
+                    while ((len--) > 0) {
+                        colortable.append_i(is.read());
+                    }
+                    colorspace.add(new PdfString(colorTable = colortable.toByteArray()));
+                    additional.put(PdfName.COLORSPACE, colorspace);
+                }
+                else {
+                    Image.skip(is, len);
+                }
+            }
+            else if (pHYs.equals(marker)) {
+                int dx = getInt(is);
+                int dy = getInt(is);
+                int unit = is.read();
+                if (unit == 1) {
+                    dpiX = (int)((float)dx * 0.0254f);
+                    dpiY = (int)((float)dy * 0.0254f);
+                }
+                else {
+                    if (dy != 0)
+                        XYRatio = (float)dx / (float)dy;
+                }
+            }
+            else if (cHRM.equals(marker)) {
+                xW = (float)getInt(is) / 100000f;
+                yW = (float)getInt(is) / 100000f;
+                xR = (float)getInt(is) / 100000f;
+                yR = (float)getInt(is) / 100000f;
+                xG = (float)getInt(is) / 100000f;
+                yG = (float)getInt(is) / 100000f;
+                xB = (float)getInt(is) / 100000f;
+                yB = (float)getInt(is) / 100000f;
+                hasCHRM = !(Math.abs(xW)<0.0001f||Math.abs(yW)<0.0001f||Math.abs(xR)<0.0001f||Math.abs(yR)<0.0001f||Math.abs(xG)<0.0001f||Math.abs(yG)<0.0001f||Math.abs(xB)<0.0001f||Math.abs(yB)<0.0001f);
+            }
+            else if (sRGB.equals(marker)) {
+                int ri = is.read();
+                intent = intents[ri];
+                gamma = 2.2f;
+                xW = 0.3127f;
+                yW = 0.329f;
+                xR = 0.64f;
+                yR = 0.33f;
+                xG = 0.3f;
+                yG = 0.6f;
+                xB = 0.15f;
+                yB = 0.06f;
+                hasCHRM = true;
+            }
+            else if (gAMA.equals(marker)) {
+                int gm = getInt(is);
+                if (gm != 0) {
+                    gamma = 100000f / (float)gm;
+                    if (!hasCHRM) {
+                        xW = 0.3127f;
+                        yW = 0.329f;
+                        xR = 0.64f;
+                        yR = 0.33f;
+                        xG = 0.3f;
+                        yG = 0.6f;
+                        xB = 0.15f;
+                        yB = 0.06f;
+                        hasCHRM = true;
+                    }
+                }
+            }
+            else if (iCCP.equals(marker)) {
+                do {
+                    --len;
+                } while (is.read() != 0);
+                is.read();
+                --len;
+                byte icccom[] = new byte[len];
+                int p = 0;
+                while (len > 0) {
+                    int r = is.read(icccom, p, len);
+                    if (r < 0)
+                        throw new IOException("Premature end of file.");
+                    p += r;
+                    len -= r;
+                }
+                byte iccp[] = PdfReader.FlateDecode(icccom, true);
+                icccom = null;
+                try {
+                    icc_profile = ICC_Profile.getInstance(iccp);
+                }
+                catch (Exception e) {
+                    icc_profile = null;
+                }
+            }
+            else if (IEND.equals(marker)) {
+                break;
+            }
+            else {
+                Image.skip(is, len);
+            }
+            Image.skip(is, 4);
+        }
+    }
+    
+    PdfObject getColorspace() {
+        if (icc_profile != null) {
+            if ((colorType & 2) == 0)
+                return PdfName.DEVICEGRAY;
+            else
+                return PdfName.DEVICERGB;
+        }
+        if (gamma == 1f && !hasCHRM) {
+            if ((colorType & 2) == 0)
+                return PdfName.DEVICEGRAY;
+            else
+                return PdfName.DEVICERGB;
+        }
+        else {
+            PdfArray array = new PdfArray();
+            PdfDictionary dic = new PdfDictionary();
+            if ((colorType & 2) == 0) {
+                if (gamma == 1f)
+                    return PdfName.DEVICEGRAY;
+                array.add(PdfName.CALGRAY);
+                dic.put(PdfName.GAMMA, new PdfNumber(gamma));
+                dic.put(PdfName.WHITEPOINT, new PdfLiteral("[1 1 1]"));
+                array.add(dic);
+            }
+            else {
+                PdfObject wp = new PdfLiteral("[1 1 1]");
+                array.add(PdfName.CALRGB);
+                if (gamma != 1f) {
+                    PdfArray gm = new PdfArray();
+                    PdfNumber n = new PdfNumber(gamma);
+                    gm.add(n);
+                    gm.add(n);
+                    gm.add(n);
+                    dic.put(PdfName.GAMMA, gm);
+                }
+                if (hasCHRM) {
+                    float z = yW*((xG-xB)*yR-(xR-xB)*yG+(xR-xG)*yB);
+                    float YA = yR*((xG-xB)*yW-(xW-xB)*yG+(xW-xG)*yB)/z;
+                    float XA = YA*xR/yR;
+                    float ZA = YA*((1-xR)/yR-1);
+                    float YB = -yG*((xR-xB)*yW-(xW-xB)*yR+(xW-xR)*yB)/z;
+                    float XB = YB*xG/yG;
+                    float ZB = YB*((1-xG)/yG-1);
+                    float YC = yB*((xR-xG)*yW-(xW-xG)*yW+(xW-xR)*yG)/z;
+                    float XC = YC*xB/yB;
+                    float ZC = YC*((1-xB)/yB-1);
+                    float XW = XA+XB+XC;
+                    float YW = 1;//YA+YB+YC;
+                    float ZW = ZA+ZB+ZC;
+                    PdfArray wpa = new PdfArray();
+                    wpa.add(new PdfNumber(XW));
+                    wpa.add(new PdfNumber(YW));
+                    wpa.add(new PdfNumber(ZW));
+                    wp = wpa;
+                    PdfArray matrix = new PdfArray();
+                    matrix.add(new PdfNumber(XA));
+                    matrix.add(new PdfNumber(YA));
+                    matrix.add(new PdfNumber(ZA));
+                    matrix.add(new PdfNumber(XB));
+                    matrix.add(new PdfNumber(YB));
+                    matrix.add(new PdfNumber(ZB));
+                    matrix.add(new PdfNumber(XC));
+                    matrix.add(new PdfNumber(YC));
+                    matrix.add(new PdfNumber(ZC));
+                    dic.put(PdfName.MATRIX, matrix);
+                }
+                dic.put(PdfName.WHITEPOINT, wp);
+                array.add(dic);
+            }
+            return array;
+        }
+    }
+    
+    Image getImage() throws IOException {
+        readPng();
+        try {
+            int pal0 = 0;
+            int palIdx = 0;
+            palShades = false;
+            if (trans != null) {
+                for (int k = 0; k < trans.length; ++k) {
+                    int n = trans[k] & 0xff;
+                    if (n == 0) {
+                        ++pal0;
+                        palIdx = k;
+                    }
+                    if (n != 0 && n != 255) {
+                        palShades = true;
+                        break;
+                    }
+                }
+            }
+            if ((colorType & 4) != 0)
+                palShades = true;
+            genBWMask = (!palShades && (pal0 > 1 || transRedGray >= 0));
+            if (!palShades && !genBWMask && pal0 == 1) {
+                additional.put(PdfName.MASK, new PdfLiteral("["+palIdx+" "+palIdx+"]"));
+            }
+            boolean needDecode = (interlaceMethod == 1) || (bitDepth == 16) || ((colorType & 4) != 0) || palShades || genBWMask;
+            switch (colorType) {
+                case 0:
+                    inputBands = 1;
+                    break;
+                case 2:
+                    inputBands = 3;
+                    break;
+                case 3:
+                    inputBands = 1;
+                    break;
+                case 4:
+                    inputBands = 2;
+                    break;
+                case 6:
+                    inputBands = 4;
+                    break;
+            }
+            if (needDecode)
+                decodeIdat();
+            int components = inputBands;
+            if ((colorType & 4) != 0)
+                --components;
+            int bpc = bitDepth;
+            if (bpc == 16)
+                bpc = 8;
+            Image img;
+            if (image != null)
+                img = Image.getInstance(width, height, components, bpc, image);
+            else {
+                img = new ImgRaw(width, height, components, bpc, idat.toByteArray());
+                img.setDeflated(true);
+                PdfDictionary decodeparms = new PdfDictionary();
+                decodeparms.put(PdfName.BITSPERCOMPONENT, new PdfNumber(bitDepth));
+                decodeparms.put(PdfName.PREDICTOR, new PdfNumber(15));
+                decodeparms.put(PdfName.COLUMNS, new PdfNumber(width));
+                decodeparms.put(PdfName.COLORS, new PdfNumber((colorType == 3 || (colorType & 2) == 0) ? 1 : 3));
+                additional.put(PdfName.DECODEPARMS, decodeparms);
+            }
+            if (additional.get(PdfName.COLORSPACE) == null)
+                additional.put(PdfName.COLORSPACE, getColorspace());
+            if (intent != null)
+                additional.put(PdfName.INTENT, intent);
+            if (additional.size() > 0)
+                img.setAdditional(additional);
+            if (icc_profile != null)
+                img.tagICC(icc_profile);
+            if (palShades) {
+                Image im2 = Image.getInstance(width, height, 1, 8, smask);
+                im2.makeMask();
+                img.setImageMask(im2);
+            }
+            if (genBWMask) {
+                Image im2 = Image.getInstance(width, height, 1, 1, smask);
+                im2.makeMask();
+                img.setImageMask(im2);
+            }
+            img.setDpi(dpiX, dpiY);
+            img.setXYRatio(XYRatio);
+            img.setOriginalType(Image.ORIGINAL_PNG);
+            return img;
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    void decodeIdat() {
+        int nbitDepth = bitDepth;
+        if (nbitDepth == 16)
+            nbitDepth = 8;
+        int size = -1;
+        bytesPerPixel = (bitDepth == 16) ? 2 : 1;
+        switch (colorType) {
+            case 0:
+                size = (nbitDepth * width + 7) / 8 * height;
+                break;
+            case 2:
+                size = width * 3 * height;
+                bytesPerPixel *= 3;
+                break;
+            case 3:
+                if (interlaceMethod == 1)
+                    size = (nbitDepth * width + 7) / 8 * height;
+                bytesPerPixel = 1;
+                break;
+            case 4:
+                size = width * height;
+                bytesPerPixel *= 2;
+                break;
+            case 6:
+                size = width * 3 * height;
+                bytesPerPixel *= 4;
+                break;
+        }
+        if (size >= 0)
+            image = new byte[size];
+        if (palShades)
+            smask = new byte[width * height];
+        else if (genBWMask)
+            smask = new byte[(width + 7) / 8 * height];
+        ByteArrayInputStream bai = new ByteArrayInputStream(idat.getBuf(), 0, idat.size());
+        InputStream infStream = new InflaterInputStream(bai, new Inflater());
+        dataStream = new DataInputStream(infStream);
+        
+        if (interlaceMethod != 1) {
+            decodePass(0, 0, 1, 1, width, height);
+        }
+        else {
+            decodePass(0, 0, 8, 8, (width + 7)/8, (height + 7)/8);
+            decodePass(4, 0, 8, 8, (width + 3)/8, (height + 7)/8);
+            decodePass(0, 4, 4, 8, (width + 3)/4, (height + 3)/8);
+            decodePass(2, 0, 4, 4, (width + 1)/4, (height + 3)/4);
+            decodePass(0, 2, 2, 4, (width + 1)/2, (height + 1)/4);
+            decodePass(1, 0, 2, 2, width/2, (height + 1)/2);
+            decodePass(0, 1, 1, 2, width, height/2);
+        }
+        
+    }
+    
+    void decodePass( int xOffset, int yOffset,
+    int xStep, int yStep,
+    int passWidth, int passHeight) {
+        if ((passWidth == 0) || (passHeight == 0)) {
+            return;
+        }
+        
+        int bytesPerRow = (inputBands*passWidth*bitDepth + 7)/8;
+        byte[] curr = new byte[bytesPerRow];
+        byte[] prior = new byte[bytesPerRow];
+        
+        // Decode the (sub)image row-by-row
+        int srcY, dstY;
+        for (srcY = 0, dstY = yOffset;
+        srcY < passHeight;
+        srcY++, dstY += yStep) {
+            // Read the filter type byte and a row of data
+            int filter = 0;
+            try {
+                filter = dataStream.read();
+                dataStream.readFully(curr, 0, bytesPerRow);
+            } catch (Exception e) {
+                // empty on purpose
+            }
+            
+            switch (filter) {
+                case PNG_FILTER_NONE:
+                    break;
+                case PNG_FILTER_SUB:
+                    decodeSubFilter(curr, bytesPerRow, bytesPerPixel);
+                    break;
+                case PNG_FILTER_UP:
+                    decodeUpFilter(curr, prior, bytesPerRow);
+                    break;
+                case PNG_FILTER_AVERAGE:
+                    decodeAverageFilter(curr, prior, bytesPerRow, bytesPerPixel);
+                    break;
+                case PNG_FILTER_PAETH:
+                    decodePaethFilter(curr, prior, bytesPerRow, bytesPerPixel);
+                    break;
+                default:
+                    // Error -- uknown filter type
+                    throw new RuntimeException("PNG filter unknown.");
+            }
+            
+            processPixels(curr, xOffset, xStep, dstY, passWidth);
+            
+            // Swap curr and prior
+            byte[] tmp = prior;
+            prior = curr;
+            curr = tmp;
+        }
+    }
+    
+    void processPixels(byte curr[], int xOffset, int step, int y, int width) {
+        int srcX, dstX;
+
+        int out[] = getPixel(curr);
+        int sizes = 0;
+        switch (colorType) {
+            case 0:
+            case 3:
+            case 4:
+                sizes = 1;
+                break;
+            case 2:
+            case 6:
+                sizes = 3;
+                break;
+        }
+        if (image != null) {
+            dstX = xOffset;
+            int yStride = (sizes*this.width*(bitDepth == 16 ? 8 : bitDepth)+ 7)/8;
+            for (srcX = 0; srcX < width; srcX++) {
+                setPixel(image, out, inputBands * srcX, sizes, dstX, y, bitDepth, yStride);
+                dstX += step;
+            }
+        }
+        if (palShades) {
+            if ((colorType & 4) != 0) {
+                if (bitDepth == 16) {
+                    for (int k = 0; k < width; ++k)
+                        out[k * inputBands + sizes] >>>= 8;
+                }
+                int yStride = this.width;
+                dstX = xOffset;
+                for (srcX = 0; srcX < width; srcX++) {
+                    setPixel(smask, out, inputBands * srcX + sizes, 1, dstX, y, 8, yStride);
+                    dstX += step;
+                }
+            }
+            else { //colorType 3
+                int yStride = this.width;
+                int v[] = new int[1];
+                dstX = xOffset;
+                for (srcX = 0; srcX < width; srcX++) {
+                    int idx = out[srcX];
+                    int r = 255;
+                    if (idx < trans.length)
+                        v[0] = trans[idx];
+                    setPixel(smask, v, 0, 1, dstX, y, 8, yStride);
+                    dstX += step;
+                }
+            }
+        }
+        else if (genBWMask) {
+            switch (colorType) {
+                case 3: {
+                    int yStride = (this.width + 7) / 8;
+                    int v[] = new int[1];
+                    dstX = xOffset;
+                    for (srcX = 0; srcX < width; srcX++) {
+                        int idx = out[srcX];
+                        int r = 0;
+                        if (idx < trans.length)
+                            v[0] = (trans[idx] == 0 ? 1 : 0);
+                        setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
+                        dstX += step;
+                    }
+                    break;
+                }
+                case 0: {
+                    int yStride = (this.width + 7) / 8;
+                    int v[] = new int[1];
+                    dstX = xOffset;
+                    for (srcX = 0; srcX < width; srcX++) {
+                        int g = out[srcX];
+                        v[0] = (g == transRedGray ? 1 : 0);
+                        setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
+                        dstX += step;
+                    }
+                    break;
+                }
+                case 2: {
+                    int yStride = (this.width + 7) / 8;
+                    int v[] = new int[1];
+                    dstX = xOffset;
+                    for (srcX = 0; srcX < width; srcX++) {
+                        int markRed = inputBands * srcX;
+                        v[0] = (out[markRed] == transRedGray && out[markRed + 1] == transGreen 
+                            && out[markRed + 2] == transBlue ? 1 : 0);
+                        setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
+                        dstX += step;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    
+    static int getPixel(byte image[], int x, int y, int bitDepth, int bytesPerRow) {
+        if (bitDepth == 8) {
+            int pos = bytesPerRow * y + x;
+            return image[pos] & 0xff;
+        }
+        else {
+            int pos = bytesPerRow * y + x / (8 / bitDepth);
+            int v = image[pos] >> (8 - bitDepth * (x % (8 / bitDepth))- bitDepth);
+            return v & ((1 << bitDepth) - 1);
+        }
+    }
+    
+    static void setPixel(byte image[], int data[], int offset, int size, int x, int y, int bitDepth, int bytesPerRow) {
+        if (bitDepth == 8) {
+            int pos = bytesPerRow * y + size * x;
+            for (int k = 0; k < size; ++k)
+                image[pos + k] = (byte)data[k + offset];
+        }
+        else if (bitDepth == 16) {
+            int pos = bytesPerRow * y + size * x;
+            for (int k = 0; k < size; ++k)
+                image[pos + k] = (byte)(data[k + offset] >>> 8);
+        }
+        else {
+            int pos = bytesPerRow * y + x / (8 / bitDepth);
+            int v = data[offset] << (8 - bitDepth * (x % (8 / bitDepth))- bitDepth);
+            image[pos] |= v;
+        }
+    }
+    
+    int[] getPixel(byte curr[]) {
+        switch (bitDepth) {
+            case 8: {
+                int out[] = new int[curr.length];
+                for (int k = 0; k < out.length; ++k)
+                    out[k] = curr[k] & 0xff;
+                return out;
+            }
+            case 16: {
+                int out[] = new int[curr.length / 2];
+                for (int k = 0; k < out.length; ++k)
+                    out[k] = ((curr[k * 2] & 0xff) << 8) + (curr[k * 2 + 1] & 0xff);
+                return out;
+            }
+            default: {
+                int out[] = new int[curr.length * 8 / bitDepth];
+                int idx = 0;
+                int passes = 8 / bitDepth;
+                int mask = (1 << bitDepth) - 1;
+                for (int k = 0; k < curr.length; ++k) {
+                    for (int j = passes - 1; j >= 0; --j) {
+                        out[idx++] = (curr[k] >>> (bitDepth * j)) & mask; 
+                    }
+                }
+                return out;
+            }
+        }
+    }
+    
+    private static void decodeSubFilter(byte[] curr, int count, int bpp) {
+        for (int i = bpp; i < count; i++) {
+            int val;
+            
+            val = curr[i] & 0xff;
+            val += curr[i - bpp] & 0xff;
+            
+            curr[i] = (byte)val;
+        }
+    }
+    
+    private static void decodeUpFilter(byte[] curr, byte[] prev,
+    int count) {
+        for (int i = 0; i < count; i++) {
+            int raw = curr[i] & 0xff;
+            int prior = prev[i] & 0xff;
+            
+            curr[i] = (byte)(raw + prior);
+        }
+    }
+    
+    private static void decodeAverageFilter(byte[] curr, byte[] prev,
+    int count, int bpp) {
+        int raw, priorPixel, priorRow;
+        
+        for (int i = 0; i < bpp; i++) {
+            raw = curr[i] & 0xff;
+            priorRow = prev[i] & 0xff;
+            
+            curr[i] = (byte)(raw + priorRow/2);
+        }
+        
+        for (int i = bpp; i < count; i++) {
+            raw = curr[i] & 0xff;
+            priorPixel = curr[i - bpp] & 0xff;
+            priorRow = prev[i] & 0xff;
+            
+            curr[i] = (byte)(raw + (priorPixel + priorRow)/2);
+        }
+    }
+    
+    private static int paethPredictor(int a, int b, int c) {
+        int p = a + b - c;
+        int pa = Math.abs(p - a);
+        int pb = Math.abs(p - b);
+        int pc = Math.abs(p - c);
+        
+        if ((pa <= pb) && (pa <= pc)) {
+            return a;
+        } else if (pb <= pc) {
+            return b;
+        } else {
+            return c;
+        }
+    }
+    
+    private static void decodePaethFilter(byte[] curr, byte[] prev,
+    int count, int bpp) {
+        int raw, priorPixel, priorRow, priorRowPixel;
+        
+        for (int i = 0; i < bpp; i++) {
+            raw = curr[i] & 0xff;
+            priorRow = prev[i] & 0xff;
+            
+            curr[i] = (byte)(raw + priorRow);
+        }
+        
+        for (int i = bpp; i < count; i++) {
+            raw = curr[i] & 0xff;
+            priorPixel = curr[i - bpp] & 0xff;
+            priorRow = prev[i] & 0xff;
+            priorRowPixel = prev[i - bpp] & 0xff;
+            
+            curr[i] = (byte)(raw + paethPredictor(priorPixel,
+            priorRow,
+            priorRowPixel));
+        }
+    }
+    
+    static class NewByteArrayOutputStream extends ByteArrayOutputStream {
+        public byte[] getBuf() {
+            return buf;
+        }
+    }
+
+/**
+ * Gets an <CODE>int</CODE> from an <CODE>InputStream</CODE>.
+ *
+ * @param		is      an <CODE>InputStream</CODE>
+ * @return		the value of an <CODE>int</CODE>
+ */
+    
+    public static final int getInt(InputStream is) throws IOException {
+        return (is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read();
+    }
+    
+/**
+ * Gets a <CODE>word</CODE> from an <CODE>InputStream</CODE>.
+ *
+ * @param		is      an <CODE>InputStream</CODE>
+ * @return		the value of an <CODE>int</CODE>
+ */
+    
+    public static final int getWord(InputStream is) throws IOException {
+        return (is.read() << 8) + is.read();
+    }
+    
+/**
+ * Gets a <CODE>String</CODE> from an <CODE>InputStream</CODE>.
+ *
+ * @param		is      an <CODE>InputStream</CODE>
+ * @return		the value of an <CODE>int</CODE>
+ */
+    
+    public static final String getString(InputStream is) throws IOException {
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < 4; i++) {
+            buf.append((char)is.read());
+        }
+        return buf.toString();
+    }
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TIFFConstants.java b/LibrarySource/com/lowagie/text/pdf/codec/TIFFConstants.java
new file mode 100644
index 0000000..35bc9c2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TIFFConstants.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+
+/**
+ * A baseline TIFF reader. The reader has some functionality in addition to
+ * the baseline specifications for Bilevel images, for which the group 3 and
+ * group 4 decompression schemes have been implemented. Support for LZW
+ * decompression has also been added. Support for Horizontal differencing
+ * predictor decoding is also included, when used with LZW compression.
+ * However, this support is limited to data with bitsPerSample value of 8.
+ * When reading in RGB images, support for alpha and extraSamples being
+ * present has been added. Support for reading in images with 16 bit samples
+ * has been added. Support for the SampleFormat tag (signed samples as well
+ * as floating-point samples) has also been added. In all other cases, support
+ * is limited to Baseline specifications.
+ *
+ *
+ */
+public class TIFFConstants {
+    
+/*
+ * TIFF Tag Definitions (from tifflib).
+ */
+    public static final int TIFFTAG_SUBFILETYPE = 254;	/* subfile data descriptor */
+    public static final int     FILETYPE_REDUCEDIMAGE = 0x1;	/* reduced resolution version */
+    public static final int     FILETYPE_PAGE = 0x2;	/* one page of many */
+    public static final int     FILETYPE_MASK = 0x4;	/* transparency mask */
+    public static final int TIFFTAG_OSUBFILETYPE = 255; /* +kind of data in subfile */
+    public static final int     OFILETYPE_IMAGE = 1; /* full resolution image data */
+    public static final int     OFILETYPE_REDUCEDIMAGE = 2; /* reduced size image data */
+    public static final int     OFILETYPE_PAGE = 3; /* one page of many */
+    public static final int TIFFTAG_IMAGEWIDTH = 256; /* image width in pixels */
+    public static final int TIFFTAG_IMAGELENGTH = 257; /* image height in pixels */
+    public static final int TIFFTAG_BITSPERSAMPLE = 258; /* bits per channel (sample) */
+    public static final int TIFFTAG_COMPRESSION = 259; /* data compression technique */
+    public static final int     COMPRESSION_NONE = 1; /* dump mode */
+    public static final int     COMPRESSION_CCITTRLE = 2; /* CCITT modified Huffman RLE */
+    public static final int     COMPRESSION_CCITTFAX3 = 3;	/* CCITT Group 3 fax encoding */
+    public static final int     COMPRESSION_CCITTFAX4 = 4;	/* CCITT Group 4 fax encoding */
+    public static final int     COMPRESSION_LZW = 5;       /* Lempel-Ziv  & Welch */
+    public static final int     COMPRESSION_OJPEG = 6; /* !6.0 JPEG */
+    public static final int     COMPRESSION_JPEG = 7; /* %JPEG DCT compression */
+    public static final int     COMPRESSION_NEXT = 32766; /* NeXT 2-bit RLE */
+    public static final int     COMPRESSION_CCITTRLEW = 32771; /* #1 w/ word alignment */
+    public static final int     COMPRESSION_PACKBITS = 32773; /* Macintosh RLE */
+    public static final int     COMPRESSION_THUNDERSCAN = 32809; /* ThunderScan RLE */
+    /* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly at etsinc.com) */
+    public static final int     COMPRESSION_IT8CTPAD = 32895;   /* IT8 CT w/padding */
+    public static final int     COMPRESSION_IT8LW = 32896;   /* IT8 Linework RLE */
+    public static final int     COMPRESSION_IT8MP = 32897;   /* IT8 Monochrome picture */
+    public static final int     COMPRESSION_IT8BL = 32898;   /* IT8 Binary line art */
+    /* compression codes 32908-32911 are reserved for Pixar */
+    public static final int     COMPRESSION_PIXARFILM = 32908;   /* Pixar companded 10bit LZW */
+    public static final int     COMPRESSION_PIXARLOG = 32909;   /* Pixar companded 11bit ZIP */
+    public static final int     COMPRESSION_DEFLATE = 32946; /* Deflate compression */
+    public static final int     COMPRESSION_ADOBE_DEFLATE = 8;       /* Deflate compression, as recognized by Adobe */
+    /* compression code 32947 is reserved for Oceana Matrix <dev at oceana.com> */
+    public static final int     COMPRESSION_DCS = 32947;   /* Kodak DCS encoding */
+    public static final int     COMPRESSION_JBIG = 34661; /* ISO JBIG */
+    public static final int     COMPRESSION_SGILOG = 34676; /* SGI Log Luminance RLE */
+    public static final int     COMPRESSION_SGILOG24 = 34677;	/* SGI Log 24-bit packed */
+    public static final int TIFFTAG_PHOTOMETRIC = 262; /* photometric interpretation */
+    public static final int     PHOTOMETRIC_MINISWHITE = 0; /* min value is white */
+    public static final int     PHOTOMETRIC_MINISBLACK = 1; /* min value is black */
+    public static final int     PHOTOMETRIC_RGB = 2; /* RGB color model */
+    public static final int     PHOTOMETRIC_PALETTE = 3; /* color map indexed */
+    public static final int     PHOTOMETRIC_MASK = 4; /* $holdout mask */
+    public static final int     PHOTOMETRIC_SEPARATED = 5; /* !color separations */
+    public static final int     PHOTOMETRIC_YCBCR = 6; /* !CCIR 601 */
+    public static final int     PHOTOMETRIC_CIELAB = 8; /* !1976 CIE L*a*b* */
+    public static final int     PHOTOMETRIC_LOGL = 32844; /* CIE Log2(L) */
+    public static final int     PHOTOMETRIC_LOGLUV = 32845; /* CIE Log2(L) (u',v') */
+    public static final int TIFFTAG_THRESHHOLDING = 263; /* +thresholding used on data */
+    public static final int     THRESHHOLD_BILEVEL = 1; /* b&w art scan */
+    public static final int     THRESHHOLD_HALFTONE = 2; /* or dithered scan */
+    public static final int     THRESHHOLD_ERRORDIFFUSE = 3; /* usually floyd-steinberg */
+    public static final int TIFFTAG_CELLWIDTH = 264; /* +dithering matrix width */
+    public static final int TIFFTAG_CELLLENGTH = 265; /* +dithering matrix height */
+    public static final int TIFFTAG_FILLORDER = 266; /* data order within a byte */
+    public static final int     FILLORDER_MSB2LSB = 1; /* most significant -> least */
+    public static final int     FILLORDER_LSB2MSB = 2; /* least significant -> most */
+    public static final int TIFFTAG_DOCUMENTNAME = 269; /* name of doc. image is from */
+    public static final int TIFFTAG_IMAGEDESCRIPTION = 270; /* info about image */
+    public static final int TIFFTAG_MAKE = 271; /* scanner manufacturer name */
+    public static final int TIFFTAG_MODEL = 272; /* scanner model name/number */
+    public static final int TIFFTAG_STRIPOFFSETS = 273; /* offsets to data strips */
+    public static final int TIFFTAG_ORIENTATION = 274; /* +image orientation */
+    public static final int     ORIENTATION_TOPLEFT = 1; /* row 0 top, col 0 lhs */
+    public static final int     ORIENTATION_TOPRIGHT = 2; /* row 0 top, col 0 rhs */
+    public static final int     ORIENTATION_BOTRIGHT = 3; /* row 0 bottom, col 0 rhs */
+    public static final int     ORIENTATION_BOTLEFT = 4; /* row 0 bottom, col 0 lhs */
+    public static final int     ORIENTATION_LEFTTOP = 5; /* row 0 lhs, col 0 top */
+    public static final int     ORIENTATION_RIGHTTOP = 6; /* row 0 rhs, col 0 top */
+    public static final int     ORIENTATION_RIGHTBOT = 7; /* row 0 rhs, col 0 bottom */
+    public static final int     ORIENTATION_LEFTBOT = 8; /* row 0 lhs, col 0 bottom */
+    public static final int TIFFTAG_SAMPLESPERPIXEL = 277; /* samples per pixel */
+    public static final int TIFFTAG_ROWSPERSTRIP = 278; /* rows per strip of data */
+    public static final int TIFFTAG_STRIPBYTECOUNTS = 279; /* bytes counts for strips */
+    public static final int TIFFTAG_MINSAMPLEVALUE = 280; /* +minimum sample value */
+    public static final int TIFFTAG_MAXSAMPLEVALUE = 281; /* +maximum sample value */
+    public static final int TIFFTAG_XRESOLUTION = 282; /* pixels/resolution in x */
+    public static final int TIFFTAG_YRESOLUTION = 283; /* pixels/resolution in y */
+    public static final int TIFFTAG_PLANARCONFIG = 284; /* storage organization */
+    public static final int     PLANARCONFIG_CONTIG = 1; /* single image plane */
+    public static final int     PLANARCONFIG_SEPARATE = 2; /* separate planes of data */
+    public static final int TIFFTAG_PAGENAME = 285; /* page name image is from */
+    public static final int TIFFTAG_XPOSITION = 286; /* x page offset of image lhs */
+    public static final int TIFFTAG_YPOSITION = 287; /* y page offset of image lhs */
+    public static final int TIFFTAG_FREEOFFSETS = 288; /* +byte offset to free block */
+    public static final int TIFFTAG_FREEBYTECOUNTS = 289; /* +sizes of free blocks */
+    public static final int TIFFTAG_GRAYRESPONSEUNIT = 290; /* $gray scale curve accuracy */
+    public static final int     GRAYRESPONSEUNIT_10S = 1; /* tenths of a unit */
+    public static final int     GRAYRESPONSEUNIT_100S = 2; /* hundredths of a unit */
+    public static final int     GRAYRESPONSEUNIT_1000S = 3; /* thousandths of a unit */
+    public static final int     GRAYRESPONSEUNIT_10000S = 4; /* ten-thousandths of a unit */
+    public static final int     GRAYRESPONSEUNIT_100000S = 5; /* hundred-thousandths */
+    public static final int TIFFTAG_GRAYRESPONSECURVE = 291; /* $gray scale response curve */
+    public static final int TIFFTAG_GROUP3OPTIONS = 292; /* 32 flag bits */
+    public static final int     GROUP3OPT_2DENCODING = 0x1;	/* 2-dimensional coding */
+    public static final int     GROUP3OPT_UNCOMPRESSED = 0x2;	/* data not compressed */
+    public static final int     GROUP3OPT_FILLBITS = 0x4;	/* fill to byte boundary */
+    public static final int TIFFTAG_GROUP4OPTIONS = 293; /* 32 flag bits */
+    public static final int     GROUP4OPT_UNCOMPRESSED = 0x2;	/* data not compressed */
+    public static final int TIFFTAG_RESOLUTIONUNIT = 296; /* units of resolutions */
+    public static final int     RESUNIT_NONE = 1; /* no meaningful units */
+    public static final int     RESUNIT_INCH = 2; /* english */
+    public static final int     RESUNIT_CENTIMETER = 3;	/* metric */
+    public static final int TIFFTAG_PAGENUMBER = 297;	/* page numbers of multi-page */
+    public static final int TIFFTAG_COLORRESPONSEUNIT = 300;	/* $color curve accuracy */
+    public static final int     COLORRESPONSEUNIT_10S = 1;	/* tenths of a unit */
+    public static final int     COLORRESPONSEUNIT_100S = 2;	/* hundredths of a unit */
+    public static final int     COLORRESPONSEUNIT_1000S = 3;	/* thousandths of a unit */
+    public static final int     COLORRESPONSEUNIT_10000S = 4;	/* ten-thousandths of a unit */
+    public static final int     COLORRESPONSEUNIT_100000S = 5;	/* hundred-thousandths */
+    public static final int TIFFTAG_TRANSFERFUNCTION = 301;	/* !colorimetry info */
+    public static final int TIFFTAG_SOFTWARE = 305;	/* name & release */
+    public static final int TIFFTAG_DATETIME = 306;	/* creation date and time */
+    public static final int TIFFTAG_ARTIST = 315;	/* creator of image */
+    public static final int TIFFTAG_HOSTCOMPUTER = 316;	/* machine where created */
+    public static final int TIFFTAG_PREDICTOR = 317;	/* prediction scheme w/ LZW */
+    public static final int TIFFTAG_WHITEPOINT = 318;	/* image white point */
+    public static final int TIFFTAG_PRIMARYCHROMATICITIES = 319;	/* !primary chromaticities */
+    public static final int TIFFTAG_COLORMAP = 320;	/* RGB map for pallette image */
+    public static final int TIFFTAG_HALFTONEHINTS = 321;	/* !highlight+shadow info */
+    public static final int TIFFTAG_TILEWIDTH = 322;	/* !rows/data tile */
+    public static final int TIFFTAG_TILELENGTH = 323;	/* !cols/data tile */
+    public static final int TIFFTAG_TILEOFFSETS = 324;	/* !offsets to data tiles */
+    public static final int TIFFTAG_TILEBYTECOUNTS = 325;	/* !byte counts for tiles */
+    public static final int TIFFTAG_BADFAXLINES = 326;	/* lines w/ wrong pixel count */
+    public static final int TIFFTAG_CLEANFAXDATA = 327;	/* regenerated line info */
+    public static final int     CLEANFAXDATA_CLEAN = 0;	/* no errors detected */
+    public static final int     CLEANFAXDATA_REGENERATED = 1;	/* receiver regenerated lines */
+    public static final int     CLEANFAXDATA_UNCLEAN = 2;	/* uncorrected errors exist */
+    public static final int TIFFTAG_CONSECUTIVEBADFAXLINES = 328;	/* max consecutive bad lines */
+    public static final int TIFFTAG_SUBIFD = 330;	/* subimage descriptors */
+    public static final int TIFFTAG_INKSET = 332;	/* !inks in separated image */
+    public static final int     INKSET_CMYK = 1;	/* !cyan-magenta-yellow-black */
+    public static final int TIFFTAG_INKNAMES = 333;	/* !ascii names of inks */
+    public static final int TIFFTAG_NUMBEROFINKS = 334;	/* !number of inks */
+    public static final int TIFFTAG_DOTRANGE = 336;	/* !0% and 100% dot codes */
+    public static final int TIFFTAG_TARGETPRINTER = 337;	/* !separation target */
+    public static final int TIFFTAG_EXTRASAMPLES = 338;	/* !info about extra samples */
+    public static final int     EXTRASAMPLE_UNSPECIFIED = 0;	/* !unspecified data */
+    public static final int     EXTRASAMPLE_ASSOCALPHA = 1;	/* !associated alpha data */
+    public static final int     EXTRASAMPLE_UNASSALPHA = 2;	/* !unassociated alpha data */
+    public static final int TIFFTAG_SAMPLEFORMAT = 339;	/* !data sample format */
+    public static final int     SAMPLEFORMAT_UINT = 1;	/* !unsigned integer data */
+    public static final int     SAMPLEFORMAT_INT = 2;	/* !signed integer data */
+    public static final int     SAMPLEFORMAT_IEEEFP = 3;	/* !IEEE floating point data */
+    public static final int     SAMPLEFORMAT_VOID = 4;	/* !untyped data */
+    public static final int     SAMPLEFORMAT_COMPLEXINT = 5;	/* !complex signed int */
+    public static final int     SAMPLEFORMAT_COMPLEXIEEEFP = 6;	/* !complex ieee floating */
+    public static final int TIFFTAG_SMINSAMPLEVALUE = 340;	/* !variable MinSampleValue */
+    public static final int TIFFTAG_SMAXSAMPLEVALUE = 341;	/* !variable MaxSampleValue */
+    public static final int TIFFTAG_JPEGTABLES = 347;	/* %JPEG table stream */
+/*
+ * Tags 512-521 are obsoleted by Technical Note #2
+ * which specifies a revised JPEG-in-TIFF scheme.
+ */
+    public static final int TIFFTAG_JPEGPROC = 512;	/* !JPEG processing algorithm */
+    public static final int     JPEGPROC_BASELINE = 1;	/* !baseline sequential */
+    public static final int     JPEGPROC_LOSSLESS = 14;	/* !Huffman coded lossless */
+    public static final int TIFFTAG_JPEGIFOFFSET = 513;	/* !pointer to SOI marker */
+    public static final int TIFFTAG_JPEGIFBYTECOUNT = 514;	/* !JFIF stream length */
+    public static final int TIFFTAG_JPEGRESTARTINTERVAL = 515;	/* !restart interval length */
+    public static final int TIFFTAG_JPEGLOSSLESSPREDICTORS = 517;	/* !lossless proc predictor */
+    public static final int TIFFTAG_JPEGPOINTTRANSFORM = 518;	/* !lossless point transform */
+    public static final int TIFFTAG_JPEGQTABLES = 519;	/* !Q matrice offsets */
+    public static final int TIFFTAG_JPEGDCTABLES = 520;	/* !DCT table offsets */
+    public static final int TIFFTAG_JPEGACTABLES = 521;	/* !AC coefficient offsets */
+    public static final int TIFFTAG_YCBCRCOEFFICIENTS = 529;	/* !RGB -> YCbCr transform */
+    public static final int TIFFTAG_YCBCRSUBSAMPLING = 530;	/* !YCbCr subsampling factors */
+    public static final int TIFFTAG_YCBCRPOSITIONING = 531;	/* !subsample positioning */
+    public static final int     YCBCRPOSITION_CENTERED = 1;	/* !as in PostScript Level 2 */
+    public static final int     YCBCRPOSITION_COSITED = 2;	/* !as in CCIR 601-1 */
+    public static final int TIFFTAG_REFERENCEBLACKWHITE = 532;	/* !colorimetry info */
+    /* tags 32952-32956 are private tags registered to Island Graphics */
+    public static final int TIFFTAG_REFPTS = 32953;	/* image reference points */
+    public static final int TIFFTAG_REGIONTACKPOINT = 32954;	/* region-xform tack point */
+    public static final int TIFFTAG_REGIONWARPCORNERS = 32955;	/* warp quadrilateral */
+    public static final int TIFFTAG_REGIONAFFINE = 32956;	/* affine transformation mat */
+    /* tags 32995-32999 are private tags registered to SGI */
+    public static final int TIFFTAG_MATTEING = 32995;	/* $use ExtraSamples */
+    public static final int TIFFTAG_DATATYPE = 32996;	/* $use SampleFormat */
+    public static final int TIFFTAG_IMAGEDEPTH = 32997;	/* z depth of image */
+    public static final int TIFFTAG_TILEDEPTH = 32998;	/* z depth/data tile */
+    /* tags 33300-33309 are private tags registered to Pixar */
+/*
+ * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH
+ * are set when an image has been cropped out of a larger image.
+ * They reflect the size of the original uncropped image.
+ * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used
+ * to determine the position of the smaller image in the larger one.
+ */
+    public static final int TIFFTAG_PIXAR_IMAGEFULLWIDTH = 33300;   /* full image size in x */
+    public static final int TIFFTAG_PIXAR_IMAGEFULLLENGTH = 33301;   /* full image size in y */
+ /* Tags 33302-33306 are used to identify special image modes and data
+  * used by Pixar's texture formats.
+  */
+    public static final int TIFFTAG_PIXAR_TEXTUREFORMAT = 33302;	/* texture map format */
+    public static final int TIFFTAG_PIXAR_WRAPMODES = 33303;	/* s & t wrap modes */
+    public static final int TIFFTAG_PIXAR_FOVCOT = 33304;	/* cotan(fov) for env. maps */
+    public static final int TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN = 33305;
+    public static final int TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA = 33306;
+    /* tag 33405 is a private tag registered to Eastman Kodak */
+    public static final int TIFFTAG_WRITERSERIALNUMBER = 33405;   /* device serial number */
+    /* tag 33432 is listed in the 6.0 spec w/ unknown ownership */
+    public static final int TIFFTAG_COPYRIGHT = 33432;	/* copyright string */
+    /* IPTC TAG from RichTIFF specifications */
+    public static final int TIFFTAG_RICHTIFFIPTC = 33723;
+    /* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly at etsinc.com) */
+    public static final int TIFFTAG_IT8SITE = 34016;	/* site name */
+    public static final int TIFFTAG_IT8COLORSEQUENCE = 34017;	/* color seq. [RGB,CMYK,etc] */
+    public static final int TIFFTAG_IT8HEADER = 34018;	/* DDES Header */
+    public static final int TIFFTAG_IT8RASTERPADDING = 34019;	/* raster scanline padding */
+    public static final int TIFFTAG_IT8BITSPERRUNLENGTH = 34020;	/* # of bits in short run */
+    public static final int TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH = 34021;/* # of bits in long run */
+    public static final int TIFFTAG_IT8COLORTABLE = 34022;	/* LW colortable */
+    public static final int TIFFTAG_IT8IMAGECOLORINDICATOR = 34023;	/* BP/BL image color switch */
+    public static final int TIFFTAG_IT8BKGCOLORINDICATOR = 34024;	/* BP/BL bg color switch */
+    public static final int TIFFTAG_IT8IMAGECOLORVALUE = 34025;	/* BP/BL image color value */
+    public static final int TIFFTAG_IT8BKGCOLORVALUE = 34026;	/* BP/BL bg color value */
+    public static final int TIFFTAG_IT8PIXELINTENSITYRANGE = 34027;	/* MP pixel intensity value */
+    public static final int TIFFTAG_IT8TRANSPARENCYINDICATOR = 34028;	/* HC transparency switch */
+    public static final int TIFFTAG_IT8COLORCHARACTERIZATION = 34029;	/* color character. table */
+    /* tags 34232-34236 are private tags registered to Texas Instruments */
+    public static final int TIFFTAG_FRAMECOUNT = 34232;   /* Sequence Frame Count */
+    /* tag 34750 is a private tag registered to Adobe? */
+    public static final int TIFFTAG_ICCPROFILE = 34675;	/* ICC profile data */
+    /* tag 34377 is private tag registered to Adobe for PhotoShop */
+    public static final int TIFFTAG_PHOTOSHOP = 34377;
+    /* tag 34750 is a private tag registered to Pixel Magic */
+    public static final int TIFFTAG_JBIGOPTIONS = 34750;	/* JBIG options */
+    /* tags 34908-34914 are private tags registered to SGI */
+    public static final int TIFFTAG_FAXRECVPARAMS = 34908;	/* encoded Class 2 ses. parms */
+    public static final int TIFFTAG_FAXSUBADDRESS = 34909;	/* received SubAddr string */
+    public static final int TIFFTAG_FAXRECVTIME = 34910;	/* receive time (secs) */
+    /* tags 37439-37443 are registered to SGI <gregl at sgi.com> */
+    public static final int TIFFTAG_STONITS = 37439;	/* Sample value to Nits */
+    /* tag 34929 is a private tag registered to FedEx */
+    public static final int TIFFTAG_FEDEX_EDR = 34929;	/* unknown use */
+    /* tag 65535 is an undefined tag used by Eastman Kodak */
+    public static final int TIFFTAG_DCSHUESHIFTVALUES = 65535;   /* hue shift correction data */
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TIFFDirectory.java b/LibrarySource/com/lowagie/text/pdf/codec/TIFFDirectory.java
new file mode 100644
index 0000000..1bcbd71
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TIFFDirectory.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.ArrayList;
+import com.lowagie.text.pdf.RandomAccessFileOrArray;
+
+/**
+ * A class representing an Image File Directory (IFD) from a TIFF 6.0
+ * stream.  The TIFF file format is described in more detail in the
+ * comments for the TIFFDescriptor class.
+ *
+ * <p> A TIFF IFD consists of a set of TIFFField tags.  Methods are
+ * provided to query the set of tags and to obtain the raw field
+ * array.  In addition, convenience methods are provided for acquiring
+ * the values of tags that contain a single value that fits into a
+ * byte, int, long, float, or double.
+ *
+ * <p> Every TIFF file is made up of one or more public IFDs that are
+ * joined in a linked list, rooted in the file header.  A file may
+ * also contain so-called private IFDs that are referenced from
+ * tag data and do not appear in the main list.
+ *
+ * <p><b> This class is not a committed part of the JAI API.  It may
+ * be removed or changed in future releases of JAI.</b>
+ *
+ * @see TIFFField
+ */
+public class TIFFDirectory extends Object implements Serializable {
+    
+    /** A boolean storing the endianness of the stream. */
+    boolean isBigEndian;
+    
+    /** The number of entries in the IFD. */
+    int numEntries;
+    
+    /** An array of TIFFFields. */
+    TIFFField[] fields;
+    
+    /** A Hashtable indexing the fields by tag number. */
+    Hashtable fieldIndex = new Hashtable();
+    
+    /** The offset of this IFD. */
+    long IFDOffset = 8;
+    
+    /** The offset of the next IFD. */
+    long nextIFDOffset = 0;
+    
+    /** The default constructor. */
+    TIFFDirectory() {}
+    
+    private static boolean isValidEndianTag(int endian) {
+        return ((endian == 0x4949) || (endian == 0x4d4d));
+    }
+    
+    /**
+     * Constructs a TIFFDirectory from a SeekableStream.
+     * The directory parameter specifies which directory to read from
+     * the linked list present in the stream; directory 0 is normally
+     * read but it is possible to store multiple images in a single
+     * TIFF file by maintaing multiple directories.
+     *
+     * @param stream a SeekableStream to read from.
+     * @param directory the index of the directory to read.
+     */
+    public TIFFDirectory(RandomAccessFileOrArray stream, int directory)
+    throws IOException {
+        
+        long global_save_offset = stream.getFilePointer();
+        long ifd_offset;
+        
+        // Read the TIFF header
+        stream.seek(0L);
+        int endian = stream.readUnsignedShort();
+        if (!isValidEndianTag(endian)) {
+            throw new
+            IllegalArgumentException("Bad endianness tag (not 0x4949 or 0x4d4d).");
+        }
+        isBigEndian = (endian == 0x4d4d);
+        
+        int magic = readUnsignedShort(stream);
+        if (magic != 42) {
+            throw new
+            IllegalArgumentException("Bad magic number, should be 42.");
+        }
+        
+        // Get the initial ifd offset as an unsigned int (using a long)
+        ifd_offset = readUnsignedInt(stream);
+        
+        for (int i = 0; i < directory; i++) {
+            if (ifd_offset == 0L) {
+                throw new
+                IllegalArgumentException("Directory number too large.");
+            }
+            
+            stream.seek(ifd_offset);
+            int entries = readUnsignedShort(stream);
+            stream.skip(12*entries);
+            
+            ifd_offset = readUnsignedInt(stream);
+        }
+        
+        stream.seek(ifd_offset);
+        initialize(stream);
+        stream.seek(global_save_offset);
+    }
+    
+    /**
+     * Constructs a TIFFDirectory by reading a SeekableStream.
+     * The ifd_offset parameter specifies the stream offset from which
+     * to begin reading; this mechanism is sometimes used to store
+     * private IFDs within a TIFF file that are not part of the normal
+     * sequence of IFDs.
+     *
+     * @param stream a SeekableStream to read from.
+     * @param ifd_offset the long byte offset of the directory.
+     * @param directory the index of the directory to read beyond the
+     *        one at the current stream offset; zero indicates the IFD
+     *        at the current offset.
+     */
+    public TIFFDirectory(RandomAccessFileOrArray stream, long ifd_offset, int directory)
+    throws IOException {
+        
+        long global_save_offset = stream.getFilePointer();
+        stream.seek(0L);
+        int endian = stream.readUnsignedShort();
+        if (!isValidEndianTag(endian)) {
+            throw new
+            IllegalArgumentException("Bad endianness tag (not 0x4949 or 0x4d4d).");
+        }
+        isBigEndian = (endian == 0x4d4d);
+        
+        // Seek to the first IFD.
+        stream.seek(ifd_offset);
+        
+        // Seek to desired IFD if necessary.
+        int dirNum = 0;
+        while(dirNum < directory) {
+            // Get the number of fields in the current IFD.
+            int numEntries = readUnsignedShort(stream);
+            
+            // Skip to the next IFD offset value field.
+            stream.seek(ifd_offset + 12*numEntries);
+            
+            // Read the offset to the next IFD beyond this one.
+            ifd_offset = readUnsignedInt(stream);
+            
+            // Seek to the next IFD.
+            stream.seek(ifd_offset);
+            
+            // Increment the directory.
+            dirNum++;
+        }
+        
+        initialize(stream);
+        stream.seek(global_save_offset);
+    }
+    
+    private static final int[] sizeOfType = {
+        0, //  0 = n/a
+        1, //  1 = byte
+        1, //  2 = ascii
+        2, //  3 = short
+        4, //  4 = long
+        8, //  5 = rational
+        1, //  6 = sbyte
+        1, //  7 = undefined
+        2, //  8 = sshort
+        4, //  9 = slong
+        8, // 10 = srational
+        4, // 11 = float
+        8  // 12 = double
+    };
+    
+    private void initialize(RandomAccessFileOrArray stream) throws IOException {
+        long nextTagOffset = 0L;
+        long maxOffset = (long) stream.length();
+        int i, j;
+        
+        IFDOffset = stream.getFilePointer();
+        
+        numEntries = readUnsignedShort(stream);
+        fields = new TIFFField[numEntries];
+        
+        for (i = 0; (i < numEntries) && (nextTagOffset < maxOffset); i++) {
+            int tag = readUnsignedShort(stream);
+            int type = readUnsignedShort(stream);
+            int count = (int)(readUnsignedInt(stream));
+            int value = 0;
+            boolean processTag = true;
+            
+            // The place to return to to read the next tag
+            nextTagOffset = stream.getFilePointer() + 4;
+            
+            try {
+                // If the tag data can't fit in 4 bytes, the next 4 bytes
+                // contain the starting offset of the data
+                if (count*sizeOfType[type] > 4) {
+                    long valueOffset = readUnsignedInt(stream);
+                    
+                    // bounds check offset for EOF
+                    if (valueOffset < maxOffset) {
+                    	stream.seek(valueOffset);
+                    }
+                    else {
+                    	// bad offset pointer .. skip tag
+                    	processTag = false;
+                    }
+                }
+            } catch (ArrayIndexOutOfBoundsException ae) {
+                // if the data type is unknown we should skip this TIFF Field
+                processTag = false;
+            }
+            
+            if (processTag) {
+            fieldIndex.put(new Integer(tag), new Integer(i));
+            Object obj = null;
+            
+            switch (type) {
+                case TIFFField.TIFF_BYTE:
+                case TIFFField.TIFF_SBYTE:
+                case TIFFField.TIFF_UNDEFINED:
+                case TIFFField.TIFF_ASCII:
+                    byte[] bvalues = new byte[count];
+                    stream.readFully(bvalues, 0, count);
+                    
+                    if (type == TIFFField.TIFF_ASCII) {
+                        
+                        // Can be multiple strings
+                        int index = 0, prevIndex = 0;
+                        ArrayList v = new ArrayList();
+                        
+                        while (index < count) {
+                            
+                            while ((index < count) && (bvalues[index++] != 0));
+                            
+                            // When we encountered zero, means one string has ended
+                            v.add(new String(bvalues, prevIndex,
+                            (index - prevIndex)) );
+                            prevIndex = index;
+                        }
+                        
+                        count = v.size();
+                        String strings[] = new String[count];
+                        for (int c = 0 ; c < count; c++) {
+                            strings[c] = (String)v.get(c);
+                        }
+                        
+                        obj = strings;
+                    } else {
+                        obj = bvalues;
+                    }
+                    
+                    break;
+                    
+                case TIFFField.TIFF_SHORT:
+                    char[] cvalues = new char[count];
+                    for (j = 0; j < count; j++) {
+                        cvalues[j] = (char)(readUnsignedShort(stream));
+                    }
+                    obj = cvalues;
+                    break;
+                    
+                case TIFFField.TIFF_LONG:
+                    long[] lvalues = new long[count];
+                    for (j = 0; j < count; j++) {
+                        lvalues[j] = readUnsignedInt(stream);
+                    }
+                    obj = lvalues;
+                    break;
+                    
+                case TIFFField.TIFF_RATIONAL:
+                    long[][] llvalues = new long[count][2];
+                    for (j = 0; j < count; j++) {
+                        llvalues[j][0] = readUnsignedInt(stream);
+                        llvalues[j][1] = readUnsignedInt(stream);
+                    }
+                    obj = llvalues;
+                    break;
+                    
+                case TIFFField.TIFF_SSHORT:
+                    short[] svalues = new short[count];
+                    for (j = 0; j < count; j++) {
+                        svalues[j] = readShort(stream);
+                    }
+                    obj = svalues;
+                    break;
+                    
+                case TIFFField.TIFF_SLONG:
+                    int[] ivalues = new int[count];
+                    for (j = 0; j < count; j++) {
+                        ivalues[j] = readInt(stream);
+                    }
+                    obj = ivalues;
+                    break;
+                    
+                case TIFFField.TIFF_SRATIONAL:
+                    int[][] iivalues = new int[count][2];
+                    for (j = 0; j < count; j++) {
+                        iivalues[j][0] = readInt(stream);
+                        iivalues[j][1] = readInt(stream);
+                    }
+                    obj = iivalues;
+                    break;
+                    
+                case TIFFField.TIFF_FLOAT:
+                    float[] fvalues = new float[count];
+                    for (j = 0; j < count; j++) {
+                        fvalues[j] = readFloat(stream);
+                    }
+                    obj = fvalues;
+                    break;
+                    
+                case TIFFField.TIFF_DOUBLE:
+                    double[] dvalues = new double[count];
+                    for (j = 0; j < count; j++) {
+                        dvalues[j] = readDouble(stream);
+                    }
+                    obj = dvalues;
+                    break;
+                    
+                default:
+                    break;
+            }
+            
+            fields[i] = new TIFFField(tag, type, count, obj);
+            }
+            
+            stream.seek(nextTagOffset);
+        }
+        
+        // Read the offset of the next IFD.
+        nextIFDOffset = readUnsignedInt(stream);
+    }
+    
+    /** Returns the number of directory entries. */
+    public int getNumEntries() {
+        return numEntries;
+    }
+    
+    /**
+     * Returns the value of a given tag as a TIFFField,
+     * or null if the tag is not present.
+     */
+    public TIFFField getField(int tag) {
+        Integer i = (Integer)fieldIndex.get(new Integer(tag));
+        if (i == null) {
+            return null;
+        } else {
+            return fields[i.intValue()];
+        }
+    }
+    
+    /**
+     * Returns true if a tag appears in the directory.
+     */
+    public boolean isTagPresent(int tag) {
+        return fieldIndex.containsKey(new Integer(tag));
+    }
+    
+    /**
+     * Returns an ordered array of ints indicating the tag
+     * values.
+     */
+    public int[] getTags() {
+        int[] tags = new int[fieldIndex.size()];
+        Enumeration e = fieldIndex.keys();
+        int i = 0;
+        
+        while (e.hasMoreElements()) {
+            tags[i++] = ((Integer)e.nextElement()).intValue();
+        }
+        
+        return tags;
+    }
+    
+    /**
+     * Returns an array of TIFFFields containing all the fields
+     * in this directory.
+     */
+    public TIFFField[] getFields() {
+        return fields;
+    }
+    
+    /**
+     * Returns the value of a particular index of a given tag as a
+     * byte.  The caller is responsible for ensuring that the tag is
+     * present and has type TIFFField.TIFF_SBYTE, TIFF_BYTE, or
+     * TIFF_UNDEFINED.
+     */
+    public byte getFieldAsByte(int tag, int index) {
+        Integer i = (Integer)fieldIndex.get(new Integer(tag));
+        byte [] b = (fields[i.intValue()]).getAsBytes();
+        return b[index];
+    }
+    
+    /**
+     * Returns the value of index 0 of a given tag as a
+     * byte.  The caller is responsible for ensuring that the tag is
+     * present and has  type TIFFField.TIFF_SBYTE, TIFF_BYTE, or
+     * TIFF_UNDEFINED.
+     */
+    public byte getFieldAsByte(int tag) {
+        return getFieldAsByte(tag, 0);
+    }
+    
+    /**
+     * Returns the value of a particular index of a given tag as a
+     * long.  The caller is responsible for ensuring that the tag is
+     * present and has type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED,
+     * TIFF_SHORT, TIFF_SSHORT, TIFF_SLONG or TIFF_LONG.
+     */
+    public long getFieldAsLong(int tag, int index) {
+        Integer i = (Integer)fieldIndex.get(new Integer(tag));
+        return (fields[i.intValue()]).getAsLong(index);
+    }
+    
+    /**
+     * Returns the value of index 0 of a given tag as a
+     * long.  The caller is responsible for ensuring that the tag is
+     * present and has type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED,
+     * TIFF_SHORT, TIFF_SSHORT, TIFF_SLONG or TIFF_LONG.
+     */
+    public long getFieldAsLong(int tag) {
+        return getFieldAsLong(tag, 0);
+    }
+    
+    /**
+     * Returns the value of a particular index of a given tag as a
+     * float.  The caller is responsible for ensuring that the tag is
+     * present and has numeric type (all but TIFF_UNDEFINED and
+     * TIFF_ASCII).
+     */
+    public float getFieldAsFloat(int tag, int index) {
+        Integer i = (Integer)fieldIndex.get(new Integer(tag));
+        return fields[i.intValue()].getAsFloat(index);
+    }
+    
+    /**
+     * Returns the value of index 0 of a given tag as a float.  The
+     * caller is responsible for ensuring that the tag is present and
+     * has numeric type (all but TIFF_UNDEFINED and TIFF_ASCII).
+     */
+    public float getFieldAsFloat(int tag) {
+        return getFieldAsFloat(tag, 0);
+    }
+    
+    /**
+     * Returns the value of a particular index of a given tag as a
+     * double.  The caller is responsible for ensuring that the tag is
+     * present and has numeric type (all but TIFF_UNDEFINED and
+     * TIFF_ASCII).
+     */
+    public double getFieldAsDouble(int tag, int index) {
+        Integer i = (Integer)fieldIndex.get(new Integer(tag));
+        return fields[i.intValue()].getAsDouble(index);
+    }
+    
+    /**
+     * Returns the value of index 0 of a given tag as a double.  The
+     * caller is responsible for ensuring that the tag is present and
+     * has numeric type (all but TIFF_UNDEFINED and TIFF_ASCII).
+     */
+    public double getFieldAsDouble(int tag) {
+        return getFieldAsDouble(tag, 0);
+    }
+    
+    // Methods to read primitive data types from the stream
+    
+    private short readShort(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readShort();
+        } else {
+            return stream.readShortLE();
+        }
+    }
+    
+    private int readUnsignedShort(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readUnsignedShort();
+        } else {
+            return stream.readUnsignedShortLE();
+        }
+    }
+    
+    private int readInt(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readInt();
+        } else {
+            return stream.readIntLE();
+        }
+    }
+    
+    private long readUnsignedInt(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readUnsignedInt();
+        } else {
+            return stream.readUnsignedIntLE();
+        }
+    }
+    
+    private long readLong(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readLong();
+        } else {
+            return stream.readLongLE();
+        }
+    }
+    
+    private float readFloat(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readFloat();
+        } else {
+            return stream.readFloatLE();
+        }
+    }
+    
+    private double readDouble(RandomAccessFileOrArray stream)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readDouble();
+        } else {
+            return stream.readDoubleLE();
+        }
+    }
+    
+    private static int readUnsignedShort(RandomAccessFileOrArray stream,
+    boolean isBigEndian)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readUnsignedShort();
+        } else {
+            return stream.readUnsignedShortLE();
+        }
+    }
+    
+    private static long readUnsignedInt(RandomAccessFileOrArray stream,
+    boolean isBigEndian)
+    throws IOException {
+        if (isBigEndian) {
+            return stream.readUnsignedInt();
+        } else {
+            return stream.readUnsignedIntLE();
+        }
+    }
+    
+    // Utilities
+    
+    /**
+     * Returns the number of image directories (subimages) stored in a
+     * given TIFF file, represented by a <code>SeekableStream</code>.
+     */
+    public static int getNumDirectories(RandomAccessFileOrArray stream)
+    throws IOException{
+        long pointer = stream.getFilePointer(); // Save stream pointer
+        
+        stream.seek(0L);
+        int endian = stream.readUnsignedShort();
+        if (!isValidEndianTag(endian)) {
+            throw new
+            IllegalArgumentException("Bad endianness tag (not 0x4949 or 0x4d4d).");
+        }
+        boolean isBigEndian = (endian == 0x4d4d);
+        int magic = readUnsignedShort(stream, isBigEndian);
+        if (magic != 42) {
+            throw new
+            IllegalArgumentException("Bad magic number, should be 42.");
+        }
+        
+        stream.seek(4L);
+        long offset = readUnsignedInt(stream, isBigEndian);
+        
+        int numDirectories = 0;
+        while (offset != 0L) {
+            ++numDirectories;
+            
+            // EOFException means IFD was probably not properly terminated.
+            try {
+                stream.seek(offset);
+                int entries = readUnsignedShort(stream, isBigEndian);
+                stream.skip(12*entries);
+                offset = readUnsignedInt(stream, isBigEndian);
+            } catch(EOFException eof) {
+                numDirectories--;
+                break;
+            }
+        }
+        
+        stream.seek(pointer); // Reset stream pointer
+        return numDirectories;
+    }
+    
+    /**
+     * Returns a boolean indicating whether the byte order used in the
+     * the TIFF file is big-endian (i.e. whether the byte order is from
+     * the most significant to the least significant)
+     */
+    public boolean isBigEndian() {
+        return isBigEndian;
+    }
+    
+    /**
+     * Returns the offset of the IFD corresponding to this
+     * <code>TIFFDirectory</code>.
+     */
+    public long getIFDOffset() {
+        return IFDOffset;
+    }
+    
+    /**
+     * Returns the offset of the next IFD after the IFD corresponding to this
+     * <code>TIFFDirectory</code>.
+     */
+    public long getNextIFDOffset() {
+        return nextIFDOffset;
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java b/LibrarySource/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java
new file mode 100644
index 0000000..e124303
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java
@@ -0,0 +1,1480 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+
+public class TIFFFaxDecoder {
+    
+    private int bitPointer, bytePointer;
+    private byte[] data;
+    private int w, h;
+    private int fillOrder;
+    
+    // Data structures needed to store changing elements for the previous
+    // and the current scanline
+    private int changingElemSize = 0;
+    private int prevChangingElems[];
+    private int currChangingElems[];
+    
+    // Element at which to start search in getNextChangingElement
+    private int lastChangingElement = 0;
+    
+    private int compression = 2;
+    
+    // Variables set by T4Options
+    private int uncompressedMode = 0;
+    private int fillBits = 0;
+    private int oneD;
+    
+    static int table1[] = {
+        0x00, // 0 bits are left in first byte - SHOULD NOT HAPPEN
+        0x01, // 1 bits are left in first byte
+        0x03, // 2 bits are left in first byte
+        0x07, // 3 bits are left in first byte
+        0x0f, // 4 bits are left in first byte
+        0x1f, // 5 bits are left in first byte
+        0x3f, // 6 bits are left in first byte
+        0x7f, // 7 bits are left in first byte
+        0xff  // 8 bits are left in first byte
+    };
+    
+    static int table2[] = {
+        0x00, // 0
+        0x80, // 1
+        0xc0, // 2
+        0xe0, // 3
+        0xf0, // 4
+        0xf8, // 5
+        0xfc, // 6
+        0xfe, // 7
+        0xff  // 8
+    };
+    
+    // Table to be used when fillOrder = 2, for flipping bytes.
+    static byte flipTable[] = {
+        0,  -128,    64,   -64,    32,   -96,    96,   -32,
+        16,  -112,    80,   -48,    48,   -80,   112,   -16,
+        8,  -120,    72,   -56,    40,   -88,   104,   -24,
+        24,  -104,    88,   -40,    56,   -72,   120,    -8,
+        4,  -124,    68,   -60,    36,   -92,   100,   -28,
+        20,  -108,    84,   -44,    52,   -76,   116,   -12,
+        12,  -116,    76,   -52,    44,   -84,   108,   -20,
+        28,  -100,    92,   -36,    60,   -68,   124,    -4,
+        2,  -126,    66,   -62,    34,   -94,    98,   -30,
+        18,  -110,    82,   -46,    50,   -78,   114,   -14,
+        10,  -118,    74,   -54,    42,   -86,   106,   -22,
+        26,  -102,    90,   -38,    58,   -70,   122,    -6,
+        6,  -122,    70,   -58,    38,   -90,   102,   -26,
+        22,  -106,    86,   -42,    54,   -74,   118,   -10,
+        14,  -114,    78,   -50,    46,   -82,   110,   -18,
+        30,   -98,    94,   -34,    62,   -66,   126,    -2,
+        1,  -127,    65,   -63,    33,   -95,    97,   -31,
+        17,  -111,    81,   -47,    49,   -79,   113,   -15,
+        9,  -119,    73,   -55,    41,   -87,   105,   -23,
+        25,  -103,    89,   -39,    57,   -71,   121,    -7,
+        5,  -123,    69,   -59,    37,   -91,   101,   -27,
+        21,  -107,    85,   -43,    53,   -75,   117,   -11,
+        13,  -115,    77,   -51,    45,   -83,   109,   -19,
+        29,   -99,    93,   -35,    61,   -67,   125,    -3,
+        3,  -125,    67,   -61,    35,   -93,    99,   -29,
+        19,  -109,    83,   -45,    51,   -77,   115,   -13,
+        11,  -117,    75,   -53,    43,   -85,   107,   -21,
+        27,  -101,    91,   -37,    59,   -69,   123,    -5,
+        7,  -121,    71,   -57,    39,   -89,   103,   -25,
+        23,  -105,    87,   -41,    55,   -73,   119,    -9,
+        15,  -113,    79,   -49,    47,   -81,   111,   -17,
+        31,   -97,    95,   -33,    63,   -65,   127,    -1,
+    };
+    
+    // The main 10 bit white runs lookup table
+    static short white[] = {
+        // 0 - 7
+        6430,   6400,   6400,   6400,   3225,   3225,   3225,   3225,
+        // 8 - 15
+        944,    944,    944,    944,    976,    976,    976,    976,
+        // 16 - 23
+        1456,   1456,   1456,   1456,   1488,   1488,   1488,   1488,
+        // 24 - 31
+        718,    718,    718,    718,    718,    718,    718,    718,
+        // 32 - 39
+        750,    750,    750,    750,    750,    750,    750,    750,
+        // 40 - 47
+        1520,   1520,   1520,   1520,   1552,   1552,   1552,   1552,
+        // 48 - 55
+        428,    428,    428,    428,    428,    428,    428,    428,
+        // 56 - 63
+        428,    428,    428,    428,    428,    428,    428,    428,
+        // 64 - 71
+        654,    654,    654,    654,    654,    654,    654,    654,
+        // 72 - 79
+        1072,   1072,   1072,   1072,   1104,   1104,   1104,   1104,
+        // 80 - 87
+        1136,   1136,   1136,   1136,   1168,   1168,   1168,   1168,
+        // 88 - 95
+        1200,   1200,   1200,   1200,   1232,   1232,   1232,   1232,
+        // 96 - 103
+        622,    622,    622,    622,    622,    622,    622,    622,
+        // 104 - 111
+        1008,   1008,   1008,   1008,   1040,   1040,   1040,   1040,
+        // 112 - 119
+        44,     44,     44,     44,     44,     44,     44,     44,
+        // 120 - 127
+        44,     44,     44,     44,     44,     44,     44,     44,
+        // 128 - 135
+        396,    396,    396,    396,    396,    396,    396,    396,
+        // 136 - 143
+        396,    396,    396,    396,    396,    396,    396,    396,
+        // 144 - 151
+        1712,   1712,   1712,   1712,   1744,   1744,   1744,   1744,
+        // 152 - 159
+        846,    846,    846,    846,    846,    846,    846,    846,
+        // 160 - 167
+        1264,   1264,   1264,   1264,   1296,   1296,   1296,   1296,
+        // 168 - 175
+        1328,   1328,   1328,   1328,   1360,   1360,   1360,   1360,
+        // 176 - 183
+        1392,   1392,   1392,   1392,   1424,   1424,   1424,   1424,
+        // 184 - 191
+        686,    686,    686,    686,    686,    686,    686,    686,
+        // 192 - 199
+        910,    910,    910,    910,    910,    910,    910,    910,
+        // 200 - 207
+        1968,   1968,   1968,   1968,   2000,   2000,   2000,   2000,
+        // 208 - 215
+        2032,   2032,   2032,   2032,     16,     16,     16,     16,
+        // 216 - 223
+        10257,  10257,  10257,  10257,  12305,  12305,  12305,  12305,
+        // 224 - 231
+        330,    330,    330,    330,    330,    330,    330,    330,
+        // 232 - 239
+        330,    330,    330,    330,    330,    330,    330,    330,
+        // 240 - 247
+        330,    330,    330,    330,    330,    330,    330,    330,
+        // 248 - 255
+        330,    330,    330,    330,    330,    330,    330,    330,
+        // 256 - 263
+        362,    362,    362,    362,    362,    362,    362,    362,
+        // 264 - 271
+        362,    362,    362,    362,    362,    362,    362,    362,
+        // 272 - 279
+        362,    362,    362,    362,    362,    362,    362,    362,
+        // 280 - 287
+        362,    362,    362,    362,    362,    362,    362,    362,
+        // 288 - 295
+        878,    878,    878,    878,    878,    878,    878,    878,
+        // 296 - 303
+        1904,   1904,   1904,   1904,   1936,   1936,   1936,   1936,
+        // 304 - 311
+        -18413, -18413, -16365, -16365, -14317, -14317, -10221, -10221,
+        // 312 - 319
+        590,    590,    590,    590,    590,    590,    590,    590,
+        // 320 - 327
+        782,    782,    782,    782,    782,    782,    782,    782,
+        // 328 - 335
+        1584,   1584,   1584,   1584,   1616,   1616,   1616,   1616,
+        // 336 - 343
+        1648,   1648,   1648,   1648,   1680,   1680,   1680,   1680,
+        // 344 - 351
+        814,    814,    814,    814,    814,    814,    814,    814,
+        // 352 - 359
+        1776,   1776,   1776,   1776,   1808,   1808,   1808,   1808,
+        // 360 - 367
+        1840,   1840,   1840,   1840,   1872,   1872,   1872,   1872,
+        // 368 - 375
+        6157,   6157,   6157,   6157,   6157,   6157,   6157,   6157,
+        // 376 - 383
+        6157,   6157,   6157,   6157,   6157,   6157,   6157,   6157,
+        // 384 - 391
+        -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275,
+        // 392 - 399
+        -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275,
+        // 400 - 407
+        14353,  14353,  14353,  14353,  16401,  16401,  16401,  16401,
+        // 408 - 415
+        22547,  22547,  24595,  24595,  20497,  20497,  20497,  20497,
+        // 416 - 423
+        18449,  18449,  18449,  18449,  26643,  26643,  28691,  28691,
+        // 424 - 431
+        30739,  30739, -32749, -32749, -30701, -30701, -28653, -28653,
+        // 432 - 439
+        -26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461,
+        // 440 - 447
+        8207,   8207,   8207,   8207,   8207,   8207,   8207,   8207,
+        // 448 - 455
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 456 - 463
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 464 - 471
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 472 - 479
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 480 - 487
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 488 - 495
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 496 - 503
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 504 - 511
+        72,     72,     72,     72,     72,     72,     72,     72,
+        // 512 - 519
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 520 - 527
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 528 - 535
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 536 - 543
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 544 - 551
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 552 - 559
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 560 - 567
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 568 - 575
+        104,    104,    104,    104,    104,    104,    104,    104,
+        // 576 - 583
+        4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107,
+        // 584 - 591
+        4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107,
+        // 592 - 599
+        4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107,
+        // 600 - 607
+        4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107,
+        // 608 - 615
+        266,    266,    266,    266,    266,    266,    266,    266,
+        // 616 - 623
+        266,    266,    266,    266,    266,    266,    266,    266,
+        // 624 - 631
+        266,    266,    266,    266,    266,    266,    266,    266,
+        // 632 - 639
+        266,    266,    266,    266,    266,    266,    266,    266,
+        // 640 - 647
+        298,    298,    298,    298,    298,    298,    298,    298,
+        // 648 - 655
+        298,    298,    298,    298,    298,    298,    298,    298,
+        // 656 - 663
+        298,    298,    298,    298,    298,    298,    298,    298,
+        // 664 - 671
+        298,    298,    298,    298,    298,    298,    298,    298,
+        // 672 - 679
+        524,    524,    524,    524,    524,    524,    524,    524,
+        // 680 - 687
+        524,    524,    524,    524,    524,    524,    524,    524,
+        // 688 - 695
+        556,    556,    556,    556,    556,    556,    556,    556,
+        // 696 - 703
+        556,    556,    556,    556,    556,    556,    556,    556,
+        // 704 - 711
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 712 - 719
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 720 - 727
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 728 - 735
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 736 - 743
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 744 - 751
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 752 - 759
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 760 - 767
+        136,    136,    136,    136,    136,    136,    136,    136,
+        // 768 - 775
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 776 - 783
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 784 - 791
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 792 - 799
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 800 - 807
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 808 - 815
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 816 - 823
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 824 - 831
+        168,    168,    168,    168,    168,    168,    168,    168,
+        // 832 - 839
+        460,    460,    460,    460,    460,    460,    460,    460,
+        // 840 - 847
+        460,    460,    460,    460,    460,    460,    460,    460,
+        // 848 - 855
+        492,    492,    492,    492,    492,    492,    492,    492,
+        // 856 - 863
+        492,    492,    492,    492,    492,    492,    492,    492,
+        // 864 - 871
+        2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059,
+        // 872 - 879
+        2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059,
+        // 880 - 887
+        2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059,
+        // 888 - 895
+        2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059,
+        // 896 - 903
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 904 - 911
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 912 - 919
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 920 - 927
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 928 - 935
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 936 - 943
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 944 - 951
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 952 - 959
+        200,    200,    200,    200,    200,    200,    200,    200,
+        // 960 - 967
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 968 - 975
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 976 - 983
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 984 - 991
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 992 - 999
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 1000 - 1007
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 1008 - 1015
+        232,    232,    232,    232,    232,    232,    232,    232,
+        // 1016 - 1023
+        232,    232,    232,    232,    232,    232,    232,    232,
+    };
+    
+    // Additional make up codes for both White and Black runs
+    static short additionalMakeup[] = {
+        28679,  28679,  31752,  (short)32777,
+        (short)33801,  (short)34825,  (short)35849,  (short)36873,
+        (short)29703,  (short)29703,  (short)30727,  (short)30727,
+        (short)37897,  (short)38921,  (short)39945,  (short)40969
+    };
+    
+    // Initial black run look up table, uses the first 4 bits of a code
+    static short initBlack[] = {
+        // 0 - 7
+        3226,  6412,    200,    168,    38,     38,    134,    134,
+        // 8 - 15
+        100,    100,    100,    100,    68,     68,     68,     68
+    };
+    
+    //
+    static short twoBitBlack[] = {292, 260, 226, 226};   // 0 - 3
+    
+    // Main black run table, using the last 9 bits of possible 13 bit code
+    static short black[] = {
+        // 0 - 7
+        62,     62,     30,     30,     0,      0,      0,      0,
+        // 8 - 15
+        0,      0,      0,      0,      0,      0,      0,      0,
+        // 16 - 23
+        0,      0,      0,      0,      0,      0,      0,      0,
+        // 24 - 31
+        0,      0,      0,      0,      0,      0,      0,      0,
+        // 32 - 39
+        3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225,
+        // 40 - 47
+        3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225,
+        // 48 - 55
+        3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225,
+        // 56 - 63
+        3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225,
+        // 64 - 71
+        588,    588,    588,    588,    588,    588,    588,    588,
+        // 72 - 79
+        1680,   1680,  20499,  22547,  24595,  26643,   1776,   1776,
+        // 80 - 87
+        1808,   1808, -24557, -22509, -20461, -18413,   1904,   1904,
+        // 88 - 95
+        1936,   1936, -16365, -14317,    782,    782,    782,    782,
+        // 96 - 103
+        814,    814,    814,    814, -12269, -10221,  10257,  10257,
+        // 104 - 111
+        12305,  12305,  14353,  14353,  16403,  18451,   1712,   1712,
+        // 112 - 119
+        1744,   1744,  28691,  30739, -32749, -30701, -28653, -26605,
+        // 120 - 127
+        2061,   2061,   2061,   2061,   2061,   2061,   2061,   2061,
+        // 128 - 135
+        424,    424,    424,    424,    424,    424,    424,    424,
+        // 136 - 143
+        424,    424,    424,    424,    424,    424,    424,    424,
+        // 144 - 151
+        424,    424,    424,    424,    424,    424,    424,    424,
+        // 152 - 159
+        424,    424,    424,    424,    424,    424,    424,    424,
+        // 160 - 167
+        750,    750,    750,    750,   1616,   1616,   1648,   1648,
+        // 168 - 175
+        1424,   1424,   1456,   1456,   1488,   1488,   1520,   1520,
+        // 176 - 183
+        1840,   1840,   1872,   1872,   1968,   1968,   8209,   8209,
+        // 184 - 191
+        524,    524,    524,    524,    524,    524,    524,    524,
+        // 192 - 199
+        556,    556,    556,    556,    556,    556,    556,    556,
+        // 200 - 207
+        1552,   1552,   1584,   1584,   2000,   2000,   2032,   2032,
+        // 208 - 215
+        976,    976,   1008,   1008,   1040,   1040,   1072,   1072,
+        // 216 - 223
+        1296,   1296,   1328,   1328,    718,    718,    718,    718,
+        // 224 - 231
+        456,    456,    456,    456,    456,    456,    456,    456,
+        // 232 - 239
+        456,    456,    456,    456,    456,    456,    456,    456,
+        // 240 - 247
+        456,    456,    456,    456,    456,    456,    456,    456,
+        // 248 - 255
+        456,    456,    456,    456,    456,    456,    456,    456,
+        // 256 - 263
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 264 - 271
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 272 - 279
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 280 - 287
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 288 - 295
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 296 - 303
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 304 - 311
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 312 - 319
+        326,    326,    326,    326,    326,    326,    326,    326,
+        // 320 - 327
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 328 - 335
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 336 - 343
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 344 - 351
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 352 - 359
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 360 - 367
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 368 - 375
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 376 - 383
+        358,    358,    358,    358,    358,    358,    358,    358,
+        // 384 - 391
+        490,    490,    490,    490,    490,    490,    490,    490,
+        // 392 - 399
+        490,    490,    490,    490,    490,    490,    490,    490,
+        // 400 - 407
+        4113,   4113,   6161,   6161,    848,    848,    880,    880,
+        // 408 - 415
+        912,    912,    944,    944,    622,    622,    622,    622,
+        // 416 - 423
+        654,    654,    654,    654,   1104,   1104,   1136,   1136,
+        // 424 - 431
+        1168,   1168,   1200,   1200,   1232,   1232,   1264,   1264,
+        // 432 - 439
+        686,    686,    686,    686,   1360,   1360,   1392,   1392,
+        // 440 - 447
+        12,     12,     12,     12,     12,     12,     12,     12,
+        // 448 - 455
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 456 - 463
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 464 - 471
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 472 - 479
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 480 - 487
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 488 - 495
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 496 - 503
+        390,    390,    390,    390,    390,    390,    390,    390,
+        // 504 - 511
+        390,    390,    390,    390,    390,    390,    390,    390,
+    };
+    
+    static byte twoDCodes[] = {
+        // 0 - 7
+        80,     88,     23,     71,     30,     30,     62,     62,
+        // 8 - 15
+        4,      4,      4,      4,      4,      4,      4,      4,
+        // 16 - 23
+        11,     11,     11,     11,     11,     11,     11,     11,
+        // 24 - 31
+        11,     11,     11,     11,     11,     11,     11,     11,
+        // 32 - 39
+        35,     35,     35,     35,     35,     35,     35,     35,
+        // 40 - 47
+        35,     35,     35,     35,     35,     35,     35,     35,
+        // 48 - 55
+        51,     51,     51,     51,     51,     51,     51,     51,
+        // 56 - 63
+        51,     51,     51,     51,     51,     51,     51,     51,
+        // 64 - 71
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 72 - 79
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 80 - 87
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 88 - 95
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 96 - 103
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 104 - 111
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 112 - 119
+        41,     41,     41,     41,     41,     41,     41,     41,
+        // 120 - 127
+        41,     41,     41,     41,     41,     41,     41,     41,
+    };
+    
+    /**
+     * @param fillOrder   The fill order of the compressed data bytes.
+     * @param w
+     * @param h
+     */
+    public TIFFFaxDecoder(int fillOrder, int w, int h) {
+        this.fillOrder = fillOrder;
+        this.w = w;
+        this.h = h;
+        
+        this.bitPointer = 0;
+        this.bytePointer = 0;
+        this.prevChangingElems = new int[w];
+        this.currChangingElems = new int[w];
+    }
+    
+    // One-dimensional decoding methods
+    
+    public void decode1D(byte[] buffer, byte[] compData,
+    int startX, int height) {
+        this.data = compData;
+        
+        int lineOffset = 0;
+        int scanlineStride = (w + 7)/8;
+        
+        bitPointer = 0;
+        bytePointer = 0;
+        
+        for (int i = 0; i < height; i++) {
+            decodeNextScanline(buffer, lineOffset, startX);
+            lineOffset += scanlineStride;
+        }
+    }
+    
+    public void decodeNextScanline(byte[] buffer,
+    int lineOffset, int bitOffset) {
+        int bits = 0, code = 0, isT = 0;
+        int current, entry, twoBits;
+        boolean isWhite = true;
+        int dstEnd = 0;
+        
+        // Initialize starting of the changing elements array
+        changingElemSize = 0;
+        
+        // While scanline not complete
+        while (bitOffset < w) {
+            while (isWhite) {
+                // White run
+                current = nextNBits(10);
+                entry = white[current];
+                
+                // Get the 3 fields from the entry
+                isT = entry & 0x0001;
+                bits = (entry >>> 1) & 0x0f;
+                
+                if (bits == 12) {          // Additional Make up code
+                    // Get the next 2 bits
+                    twoBits = nextLesserThan8Bits(2);
+                    // Consolidate the 2 new bits and last 2 bits into 4 bits
+                    current = ((current << 2) & 0x000c) | twoBits;
+                    entry = additionalMakeup[current];
+                    bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
+                    code  = (entry >>> 4) & 0x0fff;  // 12 bits
+                    bitOffset += code; // Skip white run
+                    
+                    updatePointer(4 - bits);
+                } else if (bits == 0) {     // ERROR
+                    throw new RuntimeException("Invalid code encountered.");
+                } else if (bits == 15) {    // EOL
+                    throw new RuntimeException("EOL code word encountered in White run.");
+                } else {
+                    // 11 bits - 0000 0111 1111 1111 = 0x07ff
+                    code = (entry >>> 5) & 0x07ff;
+                    bitOffset += code;
+                    
+                    updatePointer(10 - bits);
+                    if (isT == 0) {
+                        isWhite = false;
+                        currChangingElems[changingElemSize++] = bitOffset;
+                    }
+                }
+            }
+            
+            // Check whether this run completed one width, if so
+            // advance to next byte boundary for compression = 2.
+            if (bitOffset == w) {
+                if (compression == 2) {
+                    advancePointer();
+                }
+                break;
+            }
+            
+            while (isWhite == false) {
+                // Black run
+                current = nextLesserThan8Bits(4);
+                entry = initBlack[current];
+                
+                // Get the 3 fields from the entry
+                isT = entry & 0x0001;
+                bits = (entry >>> 1) & 0x000f;
+                code = (entry >>> 5) & 0x07ff;
+                
+                if (code == 100) {
+                    current = nextNBits(9);
+                    entry = black[current];
+                    
+                    // Get the 3 fields from the entry
+                    isT = entry & 0x0001;
+                    bits = (entry >>> 1) & 0x000f;
+                    code = (entry >>> 5) & 0x07ff;
+                    
+                    if (bits == 12) {
+                        // Additional makeup codes
+                        updatePointer(5);
+                        current = nextLesserThan8Bits(4);
+                        entry = additionalMakeup[current];
+                        bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
+                        code  = (entry >>> 4) & 0x0fff;  // 12 bits
+                        
+                        setToBlack(buffer, lineOffset, bitOffset, code);
+                        bitOffset += code;
+                        
+                        updatePointer(4 - bits);
+                    } else if (bits == 15) {
+                        // EOL code
+                        throw new RuntimeException("EOL code word encountered in Black run.");
+                    } else {
+                        setToBlack(buffer, lineOffset, bitOffset, code);
+                        bitOffset += code;
+                        
+                        updatePointer(9 - bits);
+                        if (isT == 0) {
+                            isWhite = true;
+                            currChangingElems[changingElemSize++] = bitOffset;
+                        }
+                    }
+                } else if (code == 200) {
+                    // Is a Terminating code
+                    current = nextLesserThan8Bits(2);
+                    entry = twoBitBlack[current];
+                    code = (entry >>> 5) & 0x07ff;
+                    bits = (entry >>> 1) & 0x0f;
+                    
+                    setToBlack(buffer, lineOffset, bitOffset, code);
+                    bitOffset += code;
+                    
+                    updatePointer(2 - bits);
+                    isWhite = true;
+                    currChangingElems[changingElemSize++] = bitOffset;
+                } else {
+                    // Is a Terminating code
+                    setToBlack(buffer, lineOffset, bitOffset, code);
+                    bitOffset += code;
+                    
+                    updatePointer(4 - bits);
+                    isWhite = true;
+                    currChangingElems[changingElemSize++] = bitOffset;
+                }
+            }
+            
+            // Check whether this run completed one width
+            if (bitOffset == w) {
+                if (compression == 2) {
+                    advancePointer();
+                }
+                break;
+            }
+        }
+        
+        currChangingElems[changingElemSize++] = bitOffset;
+    }
+    
+    // Two-dimensional decoding methods
+    
+    public void decode2D(byte[] buffer,
+    byte compData[],
+    int startX,
+    int height,
+    long tiffT4Options) {
+        this.data = compData;
+        compression = 3;
+        
+        bitPointer = 0;
+        bytePointer = 0;
+        
+        int scanlineStride = (w + 7)/8;
+        
+        int a0, a1, b1, b2;
+        int[] b = new int[2];
+        int entry, code, bits, color;
+        boolean isWhite;
+        int currIndex = 0;
+        int temp[];
+        
+        // fillBits - dealt with this in readEOL
+        // 1D/2D encoding - dealt with this in readEOL
+        
+        // uncompressedMode - haven't dealt with this yet.
+        
+        
+        oneD = (int)(tiffT4Options & 0x01);
+        uncompressedMode = (int)((tiffT4Options & 0x02) >> 1);
+        fillBits = (int)((tiffT4Options & 0x04) >> 2);
+        
+        // The data must start with an EOL code
+        if (readEOL(true) != 1) {
+            throw new RuntimeException("First scanline must be 1D encoded.");
+        }
+        
+        int lineOffset = 0;
+        int bitOffset;
+        
+        // Then the 1D encoded scanline data will occur, changing elements
+        // array gets set.
+        decodeNextScanline(buffer, lineOffset, startX);
+        lineOffset += scanlineStride;
+        
+        for (int lines = 1; lines < height; lines++) {
+            
+            // Every line must begin with an EOL followed by a bit which
+            // indicates whether the following scanline is 1D or 2D encoded.
+            if (readEOL(false) == 0) {
+                // 2D encoded scanline follows
+                
+                // Initialize previous scanlines changing elements, and
+                // initialize current scanline's changing elements array
+                temp = prevChangingElems;
+                prevChangingElems = currChangingElems;
+                currChangingElems = temp;
+                currIndex = 0;
+                
+                // a0 has to be set just before the start of this scanline.
+                a0 = -1;
+                isWhite = true;
+                bitOffset = startX;
+                
+                lastChangingElement = 0;
+                
+                while (bitOffset < w) {
+                    // Get the next changing element
+                    getNextChangingElement(a0, isWhite, b);
+                    
+                    b1 = b[0];
+                    b2 = b[1];
+                    
+                    // Get the next seven bits
+                    entry = nextLesserThan8Bits(7);
+                    
+                    // Run these through the 2DCodes table
+                    entry = (int)(twoDCodes[entry] & 0xff);
+                    
+                    // Get the code and the number of bits used up
+                    code = (entry & 0x78) >>> 3;
+                    bits = entry & 0x07;
+                    
+                    if (code == 0) {
+                        if (!isWhite) {
+                            setToBlack(buffer, lineOffset, bitOffset,
+                            b2 - bitOffset);
+                        }
+                        bitOffset = a0 = b2;
+                        
+                        // Set pointer to consume the correct number of bits.
+                        updatePointer(7 - bits);
+                    } else if (code == 1) {
+                        // Horizontal
+                        updatePointer(7 - bits);
+                        
+                        // identify the next 2 codes.
+                        int number;
+                        if (isWhite) {
+                            number = decodeWhiteCodeWord();
+                            bitOffset += number;
+                            currChangingElems[currIndex++] = bitOffset;
+                            
+                            number = decodeBlackCodeWord();
+                            setToBlack(buffer, lineOffset, bitOffset, number);
+                            bitOffset += number;
+                            currChangingElems[currIndex++] = bitOffset;
+                        } else {
+                            number = decodeBlackCodeWord();
+                            setToBlack(buffer, lineOffset, bitOffset, number);
+                            bitOffset += number;
+                            currChangingElems[currIndex++] = bitOffset;
+                            
+                            number = decodeWhiteCodeWord();
+                            bitOffset += number;
+                            currChangingElems[currIndex++] = bitOffset;
+                        }
+                        
+                        a0 = bitOffset;
+                    } else if (code <= 8) {
+                        // Vertical
+                        a1 = b1 + (code - 5);
+                        
+                        currChangingElems[currIndex++] = a1;
+                        
+                        // We write the current color till a1 - 1 pos,
+                        // since a1 is where the next color starts
+                        if (!isWhite) {
+                            setToBlack(buffer, lineOffset, bitOffset,
+                            a1 - bitOffset);
+                        }
+                        bitOffset = a0 = a1;
+                        isWhite = !isWhite;
+                        
+                        updatePointer(7 - bits);
+                    } else {
+                        throw new RuntimeException("Invalid code encountered while decoding 2D group 3 compressed data.");
+                    }
+                }
+                
+                // Add the changing element beyond the current scanline for the
+                // other color too
+                currChangingElems[currIndex++] = bitOffset;
+                changingElemSize = currIndex;
+            } else {
+                // 1D encoded scanline follows
+                decodeNextScanline(buffer, lineOffset, startX);
+            }
+            
+            lineOffset += scanlineStride;
+        }
+    }
+    
+    public synchronized void decodeT6(byte[] buffer,
+    byte[] compData,
+    int startX,
+    int height,
+    long tiffT6Options) {
+        this.data = compData;
+        compression = 4;
+        
+        bitPointer = 0;
+        bytePointer = 0;
+        
+        int scanlineStride = (w + 7)/8;
+        int bufferOffset = 0;
+        
+        int a0, a1, b1, b2;
+        int entry, code, bits;
+        byte color;
+        boolean isWhite;
+        int currIndex;
+        int temp[];
+        
+        // Return values from getNextChangingElement
+        int[] b = new int[2];
+        
+        // uncompressedMode - have written some code for this, but this
+        // has not been tested due to lack of test images using this optional
+        
+        uncompressedMode = (int)((tiffT6Options & 0x02) >> 1);
+        
+        // Local cached reference
+        int[] cce = currChangingElems;
+        
+        // Assume invisible preceding row of all white pixels and insert
+        // both black and white changing elements beyond the end of this
+        // imaginary scanline.
+        changingElemSize = 0;
+        cce[changingElemSize++] = w;
+        cce[changingElemSize++] = w;
+        
+        int lineOffset = 0;
+        int bitOffset;
+        
+        for (int lines = 0; lines < height; lines++) {
+            // a0 has to be set just before the start of the scanline.
+            a0 = -1;
+            isWhite = true;
+            
+            // Assign the changing elements of the previous scanline to
+            // prevChangingElems and start putting this new scanline's
+            // changing elements into the currChangingElems.
+            temp = prevChangingElems;
+            prevChangingElems = currChangingElems;
+            cce = currChangingElems = temp;
+            currIndex = 0;
+            
+            // Start decoding the scanline at startX in the raster
+            bitOffset = startX;
+            
+            // Reset search start position for getNextChangingElement
+            lastChangingElement = 0;
+            
+            // Till one whole scanline is decoded
+            while (bitOffset < w) {
+                // Get the next changing element
+                getNextChangingElement(a0, isWhite, b);
+                b1 = b[0];
+                b2 = b[1];
+                
+                // Get the next seven bits
+                entry = nextLesserThan8Bits(7);
+                // Run these through the 2DCodes table
+                entry = (int)(twoDCodes[entry] & 0xff);
+                
+                // Get the code and the number of bits used up
+                code = (entry & 0x78) >>> 3;
+                bits = entry & 0x07;
+                
+                if (code == 0) { // Pass
+                    // We always assume WhiteIsZero format for fax.
+                    if (!isWhite) {
+                        setToBlack(buffer, lineOffset, bitOffset,
+                        b2 - bitOffset);
+                    }
+                    bitOffset = a0 = b2;
+                    
+                    // Set pointer to only consume the correct number of bits.
+                    updatePointer(7 - bits);
+                } else if (code == 1) { // Horizontal
+                    // Set pointer to only consume the correct number of bits.
+                    updatePointer(7 - bits);
+                    
+                    // identify the next 2 alternating color codes.
+                    int number;
+                    if (isWhite) {
+                        // Following are white and black runs
+                        number = decodeWhiteCodeWord();
+                        bitOffset += number;
+                        cce[currIndex++] = bitOffset;
+                        
+                        number = decodeBlackCodeWord();
+                        setToBlack(buffer, lineOffset, bitOffset, number);
+                        bitOffset += number;
+                        cce[currIndex++] = bitOffset;
+                    } else {
+                        // First a black run and then a white run follows
+                        number = decodeBlackCodeWord();
+                        setToBlack(buffer, lineOffset, bitOffset, number);
+                        bitOffset += number;
+                        cce[currIndex++] = bitOffset;
+                        
+                        number = decodeWhiteCodeWord();
+                        bitOffset += number;
+                        cce[currIndex++] = bitOffset;
+                    }
+                    
+                    a0 = bitOffset;
+                } else if (code <= 8) { // Vertical
+                    a1 = b1 + (code - 5);
+                    cce[currIndex++] = a1;
+                    
+                    // We write the current color till a1 - 1 pos,
+                    // since a1 is where the next color starts
+                    if (!isWhite) {
+                        setToBlack(buffer, lineOffset, bitOffset,
+                        a1 - bitOffset);
+                    }
+                    bitOffset = a0 = a1;
+                    isWhite = !isWhite;
+                    
+                    updatePointer(7 - bits);
+                } else if (code == 11) {
+                    if (nextLesserThan8Bits(3) != 7) {
+                        throw new RuntimeException("Invalid code encountered while decoding 2D group 4 compressed data.");
+                    }
+                    
+                    int zeros = 0;
+                    boolean exit = false;
+                    
+                    while (!exit) {
+                        while (nextLesserThan8Bits(1) != 1) {
+                            zeros++;
+                        }
+                        
+                        if (zeros > 5) {
+                            // Exit code
+                            
+                            // Zeros before exit code
+                            zeros = zeros - 6;
+                            
+                            if (!isWhite && (zeros > 0)) {
+                                cce[currIndex++] = bitOffset;
+                            }
+                            
+                            // Zeros before the exit code
+                            bitOffset += zeros;
+                            if (zeros > 0) {
+                                // Some zeros have been written
+                                isWhite = true;
+                            }
+                            
+                            // Read in the bit which specifies the color of
+                            // the following run
+                            if (nextLesserThan8Bits(1) == 0) {
+                                if (!isWhite) {
+                                    cce[currIndex++] = bitOffset;
+                                }
+                                isWhite = true;
+                            } else {
+                                if (isWhite) {
+                                    cce[currIndex++] = bitOffset;
+                                }
+                                isWhite = false;
+                            }
+                            
+                            exit = true;
+                        }
+                        
+                        if (zeros == 5) {
+                            if (!isWhite) {
+                                cce[currIndex++] = bitOffset;
+                            }
+                            bitOffset += zeros;
+                            
+                            // Last thing written was white
+                            isWhite = true;
+                        } else {
+                            bitOffset += zeros;
+                            
+                            cce[currIndex++] = bitOffset;
+                            setToBlack(buffer, lineOffset, bitOffset, 1);
+                            ++bitOffset;
+                            
+                            // Last thing written was black
+                            isWhite = false;
+                        }
+                        
+                    }
+                } else {
+                    throw new RuntimeException("Invalid code encountered while decoding 2D group 4 compressed data.");
+                }
+            }
+            
+            // Add the changing element beyond the current scanline for the
+            // other color too
+            //make sure that the index does not exceed the bounds of the array
+            if(currIndex < cce.length) 
+            cce[currIndex++] = bitOffset;
+            
+            // Number of changing elements in this scanline.
+            changingElemSize = currIndex;
+            
+            lineOffset += scanlineStride;
+        }
+    }
+    
+    private void setToBlack(byte[] buffer,
+    int lineOffset, int bitOffset,
+    int numBits) {
+        int bitNum = 8*lineOffset + bitOffset;
+        int lastBit = bitNum + numBits;
+        
+        int byteNum = bitNum >> 3;
+        
+        // Handle bits in first byte
+        int shift = bitNum & 0x7;
+        if (shift > 0) {
+            int maskVal = 1 << (7 - shift);
+            byte val = buffer[byteNum];
+            while (maskVal > 0 && bitNum < lastBit) {
+                val |= maskVal;
+                maskVal >>= 1;
+                ++bitNum;
+            }
+            buffer[byteNum] = val;
+        }
+        
+        // Fill in 8 bits at a time
+        byteNum = bitNum >> 3;
+        while (bitNum < lastBit - 7) {
+            buffer[byteNum++] = (byte)255;
+            bitNum += 8;
+        }
+        
+        // Fill in remaining bits
+        while (bitNum < lastBit) {
+            byteNum = bitNum >> 3;
+            buffer[byteNum] |= 1 << (7 - (bitNum & 0x7));
+            ++bitNum;
+        }
+    }
+    
+    // Returns run length
+    private int decodeWhiteCodeWord() {
+        int current, entry, bits, isT, twoBits, code = -1;
+        int runLength = 0;
+        boolean isWhite = true;
+        
+        while (isWhite) {
+            current = nextNBits(10);
+            entry = white[current];
+            
+            // Get the 3 fields from the entry
+            isT = entry & 0x0001;
+            bits = (entry >>> 1) & 0x0f;
+            
+            if (bits == 12) {           // Additional Make up code
+                // Get the next 2 bits
+                twoBits = nextLesserThan8Bits(2);
+                // Consolidate the 2 new bits and last 2 bits into 4 bits
+                current = ((current << 2) & 0x000c) | twoBits;
+                entry = additionalMakeup[current];
+                bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
+                code = (entry >>> 4) & 0x0fff;   // 12 bits
+                runLength += code;
+                updatePointer(4 - bits);
+            } else if (bits == 0) {     // ERROR
+                throw new RuntimeException("Invalid code encountered.");
+            } else if (bits == 15) {    // EOL
+                throw new RuntimeException("EOL code word encountered in White run.");
+            } else {
+                // 11 bits - 0000 0111 1111 1111 = 0x07ff
+                code = (entry >>> 5) & 0x07ff;
+                runLength += code;
+                updatePointer(10 - bits);
+                if (isT == 0) {
+                    isWhite = false;
+                }
+            }
+        }
+        
+        return runLength;
+    }
+    
+    // Returns run length
+    private int decodeBlackCodeWord() {
+        int current, entry, bits, isT, twoBits, code = -1;
+        int runLength = 0;
+        boolean isWhite = false;
+        
+        while (!isWhite) {
+            current = nextLesserThan8Bits(4);
+            entry = initBlack[current];
+            
+            // Get the 3 fields from the entry
+            isT = entry & 0x0001;
+            bits = (entry >>> 1) & 0x000f;
+            code = (entry >>> 5) & 0x07ff;
+            
+            if (code == 100) {
+                current = nextNBits(9);
+                entry = black[current];
+                
+                // Get the 3 fields from the entry
+                isT = entry & 0x0001;
+                bits = (entry >>> 1) & 0x000f;
+                code = (entry >>> 5) & 0x07ff;
+                
+                if (bits == 12) {
+                    // Additional makeup codes
+                    updatePointer(5);
+                    current = nextLesserThan8Bits(4);
+                    entry = additionalMakeup[current];
+                    bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
+                    code  = (entry >>> 4) & 0x0fff;  // 12 bits
+                    runLength += code;
+                    
+                    updatePointer(4 - bits);
+                } else if (bits == 15) {
+                    // EOL code
+                    throw new RuntimeException("EOL code word encountered in Black run.");
+                } else {
+                    runLength += code;
+                    updatePointer(9 - bits);
+                    if (isT == 0) {
+                        isWhite = true;
+                    }
+                }
+            } else if (code == 200) {
+                // Is a Terminating code
+                current = nextLesserThan8Bits(2);
+                entry = twoBitBlack[current];
+                code = (entry >>> 5) & 0x07ff;
+                runLength += code;
+                bits = (entry >>> 1) & 0x0f;
+                updatePointer(2 - bits);
+                isWhite = true;
+            } else {
+                // Is a Terminating code
+                runLength += code;
+                updatePointer(4 - bits);
+                isWhite = true;
+            }
+        }
+        
+        return runLength;
+    }
+    
+    private int readEOL(boolean isFirstEOL) {
+        if (fillBits == 0) {
+            int next12Bits = nextNBits(12);
+            if (isFirstEOL && next12Bits == 0) {
+                
+                // Might have the case of EOL padding being used even
+                // though it was not flagged in the T4Options field.
+                // This was observed to be the case in TIFFs produced
+                // by a well known vendor who shall remain nameless.
+                
+                if(nextNBits(4) == 1) {
+                    
+                    // EOL must be padded: reset the fillBits flag.
+                    
+                    fillBits = 1;
+                    return 1;
+                }
+            }
+            if(next12Bits != 1) {
+                throw new RuntimeException("Scanline must begin with EOL code word.");
+            }
+        } else if (fillBits == 1) {
+            
+            // First EOL code word xxxx 0000 0000 0001 will occur
+            // As many fill bits will be present as required to make
+            // the EOL code of 12 bits end on a byte boundary.
+            
+            int bitsLeft = 8 - bitPointer;
+            
+            if (nextNBits(bitsLeft) != 0) {
+                throw new RuntimeException("All fill bits preceding EOL code must be 0.");
+            }
+            
+            // If the number of bitsLeft is less than 8, then to have a 12
+            // bit EOL sequence, two more bytes are certainly going to be
+            // required. The first of them has to be all zeros, so ensure
+            // that.
+            if (bitsLeft < 4) {
+                if (nextNBits(8) != 0) {
+                    throw new RuntimeException("All fill bits preceding EOL code must be 0.");
+                }
+            }
+            
+            // There might be a random number of fill bytes with 0s, so
+            // loop till the EOL of 0000 0001 is found, as long as all
+            // the bytes preceding it are 0's.
+            int n;
+            while ((n = nextNBits(8)) != 1) {
+                
+                // If not all zeros
+                if (n != 0) {
+                    throw new RuntimeException("All fill bits preceding EOL code must be 0.");
+                }
+            }
+        }
+        
+        // If one dimensional encoding mode, then always return 1
+        if (oneD == 0) {
+            return 1;
+        } else {
+            // Otherwise for 2D encoding mode,
+            // The next one bit signifies 1D/2D encoding of next line.
+            return nextLesserThan8Bits(1);
+        }
+    }
+    
+    private void getNextChangingElement(int a0, boolean isWhite, int[] ret) {
+        // Local copies of instance variables
+        int[] pce = this.prevChangingElems;
+        int ces = this.changingElemSize;
+        
+        // If the previous match was at an odd element, we still
+        // have to search the preceeding element.
+        // int start = lastChangingElement & ~0x1;
+        int start = lastChangingElement > 0 ? lastChangingElement - 1 : 0;
+        if (isWhite) {
+            start &= ~0x1; // Search even numbered elements
+        } else {
+            start |= 0x1; // Search odd numbered elements
+        }
+        
+        int i = start;
+        for (; i < ces; i += 2) {
+            int temp = pce[i];
+            if (temp > a0) {
+                lastChangingElement = i;
+                ret[0] = temp;
+                break;
+            }
+        }
+        
+        if (i + 1 < ces) {
+            ret[1] = pce[i + 1];
+        }
+    }
+    
+    private int nextNBits(int bitsToGet) {
+        byte b, next, next2next;
+        int l = data.length - 1;
+        int bp = this.bytePointer;
+        
+        if (fillOrder == 1) {
+            b = data[bp];
+            
+            if (bp == l) {
+                next = 0x00;
+                next2next = 0x00;
+            } else if ((bp + 1) == l) {
+                next = data[bp + 1];
+                next2next = 0x00;
+            } else {
+                next = data[bp + 1];
+                next2next = data[bp + 2];
+            }
+        } else if (fillOrder == 2) {
+            b = flipTable[data[bp] & 0xff];
+            
+            if (bp == l) {
+                next = 0x00;
+                next2next = 0x00;
+            } else if ((bp + 1) == l) {
+                next = flipTable[data[bp + 1] & 0xff];
+                next2next = 0x00;
+            } else {
+                next = flipTable[data[bp + 1] & 0xff];
+                next2next = flipTable[data[bp + 2] & 0xff];
+            }
+        } else {
+            throw new RuntimeException("TIFF_FILL_ORDER tag must be either 1 or 2.");
+        }
+        
+        int bitsLeft = 8 - bitPointer;
+        int bitsFromNextByte = bitsToGet - bitsLeft;
+        int bitsFromNext2NextByte = 0;
+        if (bitsFromNextByte > 8) {
+            bitsFromNext2NextByte = bitsFromNextByte - 8;
+            bitsFromNextByte = 8;
+        }
+        
+        bytePointer++;
+        
+        int i1 = (b & table1[bitsLeft]) << (bitsToGet - bitsLeft);
+        int i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte);
+        
+        int i3 = 0;
+        if (bitsFromNext2NextByte != 0) {
+            i2 <<= bitsFromNext2NextByte;
+            i3 = (next2next & table2[bitsFromNext2NextByte]) >>>
+            (8 - bitsFromNext2NextByte);
+            i2 |= i3;
+            bytePointer++;
+            bitPointer = bitsFromNext2NextByte;
+        } else {
+            if (bitsFromNextByte == 8) {
+                bitPointer = 0;
+                bytePointer++;
+            } else {
+                bitPointer = bitsFromNextByte;
+            }
+        }
+        
+        int i = i1 | i2;
+        return i;
+    }
+    
+    private int nextLesserThan8Bits(int bitsToGet) {
+        byte b, next;
+        int l = data.length - 1;
+        int bp = this.bytePointer;
+        
+        if (fillOrder == 1) {
+            b = data[bp];
+            if (bp == l) {
+                next = 0x00;
+            } else {
+                next = data[bp + 1];
+            }
+        } else if (fillOrder == 2) {
+            b = flipTable[data[bp] & 0xff];
+            if (bp == l) {
+                next = 0x00;
+            } else {
+                next = flipTable[data[bp + 1] & 0xff];
+            }
+        } else {
+            throw new RuntimeException("TIFF_FILL_ORDER tag must be either 1 or 2.");
+        }
+        
+        int bitsLeft = 8 - bitPointer;
+        int bitsFromNextByte = bitsToGet - bitsLeft;
+        
+        int shift = bitsLeft - bitsToGet;
+        int i1, i2;
+        if (shift >= 0) {
+            i1 = (b & table1[bitsLeft]) >>> shift;
+            bitPointer += bitsToGet;
+            if (bitPointer == 8) {
+                bitPointer = 0;
+                bytePointer++;
+            }
+        } else {
+            i1 = (b & table1[bitsLeft]) << (-shift);
+            i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte);
+            
+            i1 |= i2;
+            bytePointer++;
+            bitPointer = bitsFromNextByte;
+        }
+        
+        return i1;
+    }
+    
+    // Move pointer backwards by given amount of bits
+    private void updatePointer(int bitsToMoveBack) {
+        int i = bitPointer - bitsToMoveBack;
+        
+        if (i < 0) {
+            bytePointer--;
+            bitPointer = 8 + i;
+        } else {
+            bitPointer = i;
+        }
+    }
+    
+    // Move to the next byte boundary
+    private boolean advancePointer() {
+        if (bitPointer != 0) {
+            bytePointer++;
+            bitPointer = 0;
+        }
+        
+        return true;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TIFFField.java b/LibrarySource/com/lowagie/text/pdf/codec/TIFFField.java
new file mode 100644
index 0000000..4bfbb50
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TIFFField.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * -Redistributions of source code must retain the above copyright notice, this 
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ * 
+ * You acknowledge that Software is not designed,licensed or intended for use in 
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+
+import java.io.Serializable;
+
+/**
+ * A class representing a field in a TIFF 6.0 Image File Directory.
+ *
+ * <p> The TIFF file format is described in more detail in the
+ * comments for the TIFFDescriptor class.
+ *
+ * <p> A field in a TIFF Image File Directory (IFD).  A field is defined
+ * as a sequence of values of identical data type.  TIFF 6.0 defines
+ * 12 data types, which are mapped internally onto the Java datatypes
+ * byte, int, long, float, and double.
+ *
+ * <p><b> This class is not a committed part of the JAI API.  It may
+ * be removed or changed in future releases of JAI.</b>
+ *
+ * @see TIFFDirectory
+ */
+public class TIFFField extends Object implements Comparable, Serializable {
+
+    /** Flag for 8 bit unsigned integers. */
+    public static final int TIFF_BYTE      =  1;
+
+    /** Flag for null-terminated ASCII strings. */
+    public static final int TIFF_ASCII     =  2;
+
+    /** Flag for 16 bit unsigned integers. */
+    public static final int TIFF_SHORT     =  3;
+
+    /** Flag for 32 bit unsigned integers. */
+    public static final int TIFF_LONG      =  4;
+
+    /** Flag for pairs of 32 bit unsigned integers. */
+    public static final int TIFF_RATIONAL  =  5;
+
+    /** Flag for 8 bit signed integers. */
+    public static final int TIFF_SBYTE     =  6;
+
+    /** Flag for 8 bit uninterpreted bytes. */
+    public static final int TIFF_UNDEFINED =  7;
+
+    /** Flag for 16 bit signed integers. */
+    public static final int TIFF_SSHORT    =  8;
+
+    /** Flag for 32 bit signed integers. */
+    public static final int TIFF_SLONG     =  9;
+
+    /** Flag for pairs of 32 bit signed integers. */
+    public static final int TIFF_SRATIONAL = 10;
+
+    /** Flag for 32 bit IEEE floats. */
+    public static final int TIFF_FLOAT     = 11;
+
+    /** Flag for 64 bit IEEE doubles. */
+    public static final int TIFF_DOUBLE    = 12;
+
+    /** The tag number. */
+    int tag;
+
+    /** The tag type. */
+    int type;
+
+    /** The number of data items present in the field. */
+    int count;
+
+    /** The field data. */
+    Object data;
+    
+    /** The default constructor. */
+    TIFFField() {}
+
+    /**
+     * Constructs a TIFFField with arbitrary data.  The data
+     * parameter must be an array of a Java type appropriate for the
+     * type of the TIFF field.  Since there is no available 32-bit
+     * unsigned datatype, long is used. The mapping between types is
+     * as follows:
+     *
+     * <table border=1>
+     * <tr>
+     * <th> TIFF type </th> <th> Java type </th>
+     * <tr>
+     * <td><tt>TIFF_BYTE</tt></td>      <td><tt>byte</tt></td>
+     * <tr>
+     * <td><tt>TIFF_ASCII</tt></td>     <td><tt>String</tt></td>
+     * <tr>
+     * <td><tt>TIFF_SHORT</tt></td>     <td><tt>char</tt></td>
+     * <tr>
+     * <td><tt>TIFF_LONG</tt></td>      <td><tt>long</tt></td>
+     * <tr>
+     * <td><tt>TIFF_RATIONAL</tt></td>  <td><tt>long[2]</tt></td>
+     * <tr>
+     * <td><tt>TIFF_SBYTE</tt></td>     <td><tt>byte</tt></td>
+     * <tr>
+     * <td><tt>TIFF_UNDEFINED</tt></td> <td><tt>byte</tt></td>
+     * <tr>
+     * <td><tt>TIFF_SSHORT</tt></td>    <td><tt>short</tt></td>
+     * <tr>
+     * <td><tt>TIFF_SLONG</tt></td>     <td><tt>int</tt></td>
+     * <tr>
+     * <td><tt>TIFF_SRATIONAL</tt></td> <td><tt>int[2]</tt></td>
+     * <tr>
+     * <td><tt>TIFF_FLOAT</tt></td>     <td><tt>float</tt></td>
+     * <tr>
+     * <td><tt>TIFF_DOUBLE</tt></td>    <td><tt>double</tt></td>
+     * </table>
+     */
+    public TIFFField(int tag, int type, int count, Object data) {
+        this.tag = tag;
+        this.type = type;
+        this.count = count;
+        this.data = data;
+    }
+
+    /**
+     * Returns the tag number, between 0 and 65535.
+     */
+    public int getTag() {
+        return tag;
+    }
+
+    /**
+     * Returns the type of the data stored in the IFD.
+     * For a TIFF6.0 file, the value will equal one of the
+     * TIFF_ constants defined in this class.  For future
+     * revisions of TIFF, higher values are possible.
+     *
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * Returns the number of elements in the IFD.
+     */
+    public int getCount() {
+        return count;
+    }
+
+    /**
+     * Returns the data as an uninterpreted array of bytes.
+     * The type of the field must be one of TIFF_BYTE, TIFF_SBYTE,
+     * or TIFF_UNDEFINED;
+     *
+     * <p> For data in TIFF_BYTE format, the application must take
+     * care when promoting the data to longer integral types
+     * to avoid sign extension.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_BYTE, TIFF_SBYTE, or TIFF_UNDEFINED.
+     */
+    public byte[] getAsBytes() {
+        return (byte[])data;
+    }
+
+    /**
+     * Returns TIFF_SHORT data as an array of chars (unsigned 16-bit
+     * integers).
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_SHORT.
+     */
+    public char[] getAsChars() {
+        return (char[])data;
+    }
+
+    /**
+     * Returns TIFF_SSHORT data as an array of shorts (signed 16-bit
+     * integers).
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_SSHORT.
+     */
+    public short[] getAsShorts() {
+        return (short[])data;
+    }
+
+    /**
+     * Returns TIFF_SLONG data as an array of ints (signed 32-bit
+     * integers).
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_SLONG.
+     */
+    public int[] getAsInts() {
+        return (int[])data;
+    }
+
+    /**
+     * Returns TIFF_LONG data as an array of longs (signed 64-bit
+     * integers).
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_LONG.
+     */
+    public long[] getAsLongs() {
+        return (long[])data;
+    }
+
+    /**
+     * Returns TIFF_FLOAT data as an array of floats. 
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_FLOAT.
+     */
+    public float[] getAsFloats() {
+        return (float[])data;
+    }
+
+    /**
+     * Returns TIFF_DOUBLE data as an array of doubles. 
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_DOUBLE.
+     */
+    public double[] getAsDoubles() {
+        return (double[])data;
+    }
+
+    /**
+     * Returns TIFF_SRATIONAL data as an array of 2-element arrays of ints.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_SRATIONAL.
+     */
+    public int[][] getAsSRationals() {
+        return (int[][])data;
+    }
+
+    /**
+     * Returns TIFF_RATIONAL data as an array of 2-element arrays of longs.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_RATTIONAL.
+     */
+    public long[][] getAsRationals() {
+        return (long[][])data;
+    }
+
+    /**
+     * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
+     * TIFF_SSHORT, or TIFF_SLONG format as an int.
+     *
+     * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned;
+     * that is, no sign extension will take place and the returned
+     * value will be in the range [0, 255].  TIFF_SBYTE data will
+     * be returned in the range [-128, 127].
+     *
+     * <p> A ClassCastException will be thrown if the field is not of
+     * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
+     * TIFF_SSHORT, or TIFF_SLONG.
+     */
+    public int getAsInt(int index) {
+        switch (type) {
+        case TIFF_BYTE: case TIFF_UNDEFINED:
+            return ((byte[])data)[index] & 0xff;
+        case TIFF_SBYTE:
+            return ((byte[])data)[index];
+        case TIFF_SHORT:
+            return ((char[])data)[index] & 0xffff;
+        case TIFF_SSHORT:
+            return ((short[])data)[index];
+        case TIFF_SLONG:
+            return ((int[])data)[index];
+        default:
+            throw new ClassCastException();
+        }
+    }
+
+    /**
+     * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
+     * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG format as a long.
+     *
+     * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned;
+     * that is, no sign extension will take place and the returned
+     * value will be in the range [0, 255].  TIFF_SBYTE data will
+     * be returned in the range [-128, 127].
+     *
+     * <p> A ClassCastException will be thrown if the field is not of
+     * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
+     * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG.
+     */
+    public long getAsLong(int index) {
+        switch (type) {
+        case TIFF_BYTE: case TIFF_UNDEFINED:
+            return ((byte[])data)[index] & 0xff;
+        case TIFF_SBYTE:
+            return ((byte[])data)[index];
+        case TIFF_SHORT:
+            return ((char[])data)[index] & 0xffff;
+        case TIFF_SSHORT:
+            return ((short[])data)[index];
+        case TIFF_SLONG:
+            return ((int[])data)[index];
+        case TIFF_LONG:
+            return ((long[])data)[index];
+        default:
+            throw new ClassCastException();
+        }
+    }
+    
+    /**
+     * Returns data in any numerical format as a float.  Data in
+     * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by
+     * dividing the numerator into the denominator using
+     * double-precision arithmetic and then truncating to single
+     * precision.  Data in TIFF_SLONG, TIFF_LONG, or TIFF_DOUBLE
+     * format may suffer from truncation.
+     *
+     * <p> A ClassCastException will be thrown if the field is
+     * of type TIFF_UNDEFINED or TIFF_ASCII.
+     */
+    public float getAsFloat(int index) {
+        switch (type) {
+        case TIFF_BYTE:
+            return ((byte[])data)[index] & 0xff;
+        case TIFF_SBYTE:
+            return ((byte[])data)[index];
+        case TIFF_SHORT:
+            return ((char[])data)[index] & 0xffff;
+        case TIFF_SSHORT:
+            return ((short[])data)[index];
+        case TIFF_SLONG:
+            return ((int[])data)[index];
+        case TIFF_LONG:
+            return ((long[])data)[index];
+        case TIFF_FLOAT:
+            return ((float[])data)[index];
+        case TIFF_DOUBLE:
+            return (float)((double[])data)[index];
+        case TIFF_SRATIONAL:
+            int[] ivalue = getAsSRational(index);
+            return (float)((double)ivalue[0]/ivalue[1]);
+        case TIFF_RATIONAL:
+            long[] lvalue = getAsRational(index);
+            return (float)((double)lvalue[0]/lvalue[1]);
+        default:
+            throw new ClassCastException();
+        }
+    }
+
+    /**
+     * Returns data in any numerical format as a float.  Data in
+     * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by
+     * dividing the numerator into the denominator using
+     * double-precision arithmetic.
+     *
+     * <p> A ClassCastException will be thrown if the field is of
+     * type TIFF_UNDEFINED or TIFF_ASCII.
+     */
+    public double getAsDouble(int index) {
+        switch (type) {
+        case TIFF_BYTE:
+            return ((byte[])data)[index] & 0xff;
+        case TIFF_SBYTE:
+            return ((byte[])data)[index];
+        case TIFF_SHORT:
+            return ((char[])data)[index] & 0xffff;
+        case TIFF_SSHORT:
+            return ((short[])data)[index];
+        case TIFF_SLONG:
+            return ((int[])data)[index];
+        case TIFF_LONG:
+            return ((long[])data)[index];
+        case TIFF_FLOAT:
+            return ((float[])data)[index];
+        case TIFF_DOUBLE:
+            return ((double[])data)[index];
+        case TIFF_SRATIONAL:
+            int[] ivalue = getAsSRational(index);
+            return (double)ivalue[0]/ivalue[1];
+        case TIFF_RATIONAL:
+            long[] lvalue = getAsRational(index);
+            return (double)lvalue[0]/lvalue[1];
+        default:
+            throw new ClassCastException();
+        }
+    }
+
+    /**
+     * Returns a TIFF_ASCII data item as a String.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_ASCII.
+     */
+    public String getAsString(int index) {
+        return ((String[])data)[index];
+    }
+
+    /**
+     * Returns a TIFF_SRATIONAL data item as a two-element array
+     * of ints.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_SRATIONAL.
+     */
+    public int[] getAsSRational(int index) {
+        return ((int[][])data)[index];
+    }
+
+    /**
+     * Returns a TIFF_RATIONAL data item as a two-element array
+     * of ints.
+     *
+     * <p> A ClassCastException will be thrown if the field is not
+     * of type TIFF_RATIONAL.
+     */
+    public long[] getAsRational(int index) {
+        return ((long[][])data)[index];
+    }
+
+    /**
+     * Compares this <code>TIFFField</code> with another
+     * <code>TIFFField</code> by comparing the tags.
+     *
+     * <p><b>Note: this class has a natural ordering that is inconsistent
+     * with <code>equals()</code>.</b>
+     *
+     * @throws IllegalArgumentException if the parameter is <code>null</code>.
+     * @throws ClassCastException if the parameter is not a
+     *         <code>TIFFField</code>.
+     */
+    public int compareTo(Object o) {
+        if(o == null) {
+            throw new IllegalArgumentException();
+        }
+
+        int oTag = ((TIFFField)o).getTag();
+
+        if(tag < oTag) {
+            return -1;
+        } else if(tag > oTag) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TIFFLZWDecoder.java b/LibrarySource/com/lowagie/text/pdf/codec/TIFFLZWDecoder.java
new file mode 100644
index 0000000..f3586e1
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TIFFLZWDecoder.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed,licensed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+package com.lowagie.text.pdf.codec;
+
+/**
+ * A class for performing LZW decoding.
+ *
+ *
+ */
+public class TIFFLZWDecoder {
+    
+    byte stringTable[][];
+    byte data[] = null, uncompData[];
+    int tableIndex, bitsToGet = 9;
+    int bytePointer, bitPointer;
+    int dstIndex;
+    int w, h;
+    int predictor, samplesPerPixel;
+    int nextData = 0;
+    int nextBits = 0;
+    
+    int andTable[] = {
+        511,
+        1023,
+        2047,
+        4095
+    };
+    
+    public TIFFLZWDecoder(int w, int predictor, int samplesPerPixel) {
+        this.w = w;
+        this.predictor = predictor;
+        this.samplesPerPixel = samplesPerPixel;
+    }
+    
+    /**
+     * Method to decode LZW compressed data.
+     *
+     * @param data            The compressed data.
+     * @param uncompData      Array to return the uncompressed data in.
+     * @param h               The number of rows the compressed data contains.
+     */
+    public byte[] decode(byte data[], byte uncompData[], int h) {
+        
+        if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
+            throw new UnsupportedOperationException("TIFF 5.0-style LZW codes are not supported.");
+        }
+        
+        initializeStringTable();
+        
+        this.data = data;
+        this.h = h;
+        this.uncompData = uncompData;
+        
+        // Initialize pointers
+        bytePointer = 0;
+        bitPointer = 0;
+        dstIndex = 0;
+        
+        
+        nextData = 0;
+        nextBits = 0;
+        
+        int code, oldCode = 0;
+        byte string[];
+        
+        while ( ((code = getNextCode()) != 257) &&
+        dstIndex < uncompData.length) {
+            
+            if (code == 256) {
+                
+                initializeStringTable();
+                code = getNextCode();
+                
+                if (code == 257) {
+                    break;
+                }
+                
+                writeString(stringTable[code]);
+                oldCode = code;
+                
+            } else {
+                
+                if (code < tableIndex) {
+                    
+                    string = stringTable[code];
+                    
+                    writeString(string);
+                    addStringToTable(stringTable[oldCode], string[0]);
+                    oldCode = code;
+                    
+                } else {
+                    
+                    string = stringTable[oldCode];
+                    string = composeString(string, string[0]);
+                    writeString(string);
+                    addStringToTable(string);
+                    oldCode = code;
+                }
+                
+            }
+            
+        }
+        
+        // Horizontal Differencing Predictor
+        if (predictor == 2) {
+            
+            int count;
+            for (int j = 0; j < h; j++) {
+                
+                count = samplesPerPixel * (j * w + 1);
+                
+                for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
+                    
+                    uncompData[count] += uncompData[count - samplesPerPixel];
+                    count++;
+                }
+            }
+        }
+        
+        return uncompData;
+    }
+    
+    
+    /**
+     * Initialize the string table.
+     */
+    public void initializeStringTable() {
+        
+        stringTable = new byte[4096][];
+        
+        for (int i=0; i<256; i++) {
+            stringTable[i] = new byte[1];
+            stringTable[i][0] = (byte)i;
+        }
+        
+        tableIndex = 258;
+        bitsToGet = 9;
+    }
+    
+    /**
+     * Write out the string just uncompressed.
+     */
+    public void writeString(byte string[]) {
+        
+        for (int i=0; i<string.length; i++) {
+            uncompData[dstIndex++] = string[i];
+        }
+    }
+    
+    /**
+     * Add a new string to the string table.
+     */
+    public void addStringToTable(byte oldString[], byte newString) {
+        int length = oldString.length;
+        byte string[] = new byte[length + 1];
+        System.arraycopy(oldString, 0, string, 0, length);
+        string[length] = newString;
+        
+        // Add this new String to the table
+        stringTable[tableIndex++] = string;
+        
+        if (tableIndex == 511) {
+            bitsToGet = 10;
+        } else if (tableIndex == 1023) {
+            bitsToGet = 11;
+        } else if (tableIndex == 2047) {
+            bitsToGet = 12;
+        }
+    }
+    
+    /**
+     * Add a new string to the string table.
+     */
+    public void addStringToTable(byte string[]) {
+        
+        // Add this new String to the table
+        stringTable[tableIndex++] = string;
+        
+        if (tableIndex == 511) {
+            bitsToGet = 10;
+        } else if (tableIndex == 1023) {
+            bitsToGet = 11;
+        } else if (tableIndex == 2047) {
+            bitsToGet = 12;
+        }
+    }
+    
+    /**
+     * Append <code>newString</code> to the end of <code>oldString</code>.
+     */
+    public byte[] composeString(byte oldString[], byte newString) {
+        int length = oldString.length;
+        byte string[] = new byte[length + 1];
+        System.arraycopy(oldString, 0, string, 0, length);
+        string[length] = newString;
+        
+        return string;
+    }
+    
+    // Returns the next 9, 10, 11 or 12 bits
+    public int getNextCode() {
+        // Attempt to get the next code. The exception is caught to make
+        // this robust to cases wherein the EndOfInformation code has been
+        // omitted from a strip. Examples of such cases have been observed
+        // in practice.
+        try {
+            nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+            nextBits += 8;
+            
+            if (nextBits < bitsToGet) {
+                nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+                nextBits += 8;
+            }
+            
+            int code =
+            (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
+            nextBits -= bitsToGet;
+            
+            return code;
+        } catch(ArrayIndexOutOfBoundsException e) {
+            // Strip not terminated as expected: return EndOfInformation code.
+            return 257;
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/TiffImage.java b/LibrarySource/com/lowagie/text/pdf/codec/TiffImage.java
new file mode 100644
index 0000000..5c05465
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/TiffImage.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf.codec;
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.Image;
+import com.lowagie.text.ExceptionConverter;
+import java.io.*;
+import java.util.zip.*;
+import headless.awt.color.ICC_Profile;
+
+/** Reads TIFF images
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class TiffImage {
+    
+    /** Gets the number of pages the TIFF document has.
+     * @param s the file source
+     * @return the number of pages
+     */    
+    public static int getNumberOfPages(RandomAccessFileOrArray s) {
+        try {
+            return TIFFDirectory.getNumDirectories(s);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+
+    static int getDpi(TIFFField fd, int resolutionUnit) {
+        if (fd == null)
+            return 0;
+        long res[] = fd.getAsRational(0);
+        float frac = (float)res[0] / (float)res[1];
+        int dpi = 0;
+        switch (resolutionUnit) {
+            case TIFFConstants.RESUNIT_INCH:
+            case TIFFConstants.RESUNIT_NONE:
+                dpi = (int)frac;
+                break;
+            case TIFFConstants.RESUNIT_CENTIMETER:
+                dpi = (int)(frac * 2.54);
+                break;
+        }
+        return dpi;
+    }
+    
+    /** Reads a page from a TIFF image. Direct mode is not used.
+     * @param s the file source
+     * @param page the page to get. The first page is 1
+     * @return the <CODE>Image</CODE>
+     */    
+    public static Image getTiffImage(RandomAccessFileOrArray s, int page) {
+        return getTiffImage(s, page, false);
+    }
+    
+    /** Reads a page from a TIFF image.
+     * @param s the file source
+     * @param page the page to get. The first page is 1
+     * @param direct for single strip, CCITT images, generate the image
+     * by direct byte copying. It's faster but may not work
+     * every time
+     * @return the <CODE>Image</CODE>
+     */    
+    public static Image getTiffImage(RandomAccessFileOrArray s, int page, boolean direct) {
+        if (page < 1)
+            throw new IllegalArgumentException("The page number must be >= 1.");
+        try {
+            TIFFDirectory dir = new TIFFDirectory(s, page - 1);
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_TILEWIDTH))
+                throw new IllegalArgumentException("Tiles are not supported.");
+            int compression = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
+            switch (compression) {
+                case TIFFConstants.COMPRESSION_CCITTRLEW:
+                case TIFFConstants.COMPRESSION_CCITTRLE:
+                case TIFFConstants.COMPRESSION_CCITTFAX3:
+                case TIFFConstants.COMPRESSION_CCITTFAX4:
+                    break;
+                default:
+                    return getTiffImageColor(dir, s);
+            }
+            Image img = null;
+            long tiffT4Options = 0;
+            long tiffT6Options = 0;
+            int fillOrder = 1;
+            int h = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
+            int w = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
+            int dpiX = 0;
+            int dpiY = 0;
+            float XYRatio = 0;
+            int resolutionUnit = TIFFConstants.RESUNIT_INCH;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
+                resolutionUnit = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
+            dpiX = getDpi(dir.getField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
+            dpiY = getDpi(dir.getField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
+            if (resolutionUnit == TIFFConstants.RESUNIT_NONE) {
+                if (dpiY != 0)
+                    XYRatio = (float)dpiX / (float)dpiY;
+                dpiX = 0;
+                dpiY = 0;
+            }
+            long tstrip = 0xFFFFFFFFL;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_ROWSPERSTRIP))
+                tstrip = dir.getFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
+            int rowsStrip = (int)Math.min((long)h, tstrip);
+            TIFFField field = dir.getField(TIFFConstants.TIFFTAG_STRIPOFFSETS);
+            long offset[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
+            long size[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
+            boolean reverse = false;
+            TIFFField fillOrderField =  dir.getField(TIFFConstants.TIFFTAG_FILLORDER);
+            if (fillOrderField != null)
+                fillOrder = fillOrderField.getAsInt(0);
+            reverse = (fillOrder == TIFFConstants.FILLORDER_LSB2MSB);
+            int params = 0;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_PHOTOMETRIC)) {
+                long photo = dir.getFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
+                if (photo == TIFFConstants.PHOTOMETRIC_MINISBLACK)
+                    params |= Image.CCITT_BLACKIS1;
+            }
+            int imagecomp = 0;
+            switch (compression) {
+                case TIFFConstants.COMPRESSION_CCITTRLEW:
+                case TIFFConstants.COMPRESSION_CCITTRLE:
+                    imagecomp = Image.CCITTG3_1D;
+                    params |= Image.CCITT_ENCODEDBYTEALIGN | Image.CCITT_ENDOFBLOCK;
+                    break;
+                case TIFFConstants.COMPRESSION_CCITTFAX3:
+                    imagecomp = Image.CCITTG3_1D;
+                    params |= Image.CCITT_ENDOFLINE | Image.CCITT_ENDOFBLOCK;
+                    TIFFField t4OptionsField = dir.getField(TIFFConstants.TIFFTAG_GROUP3OPTIONS);
+                    if (t4OptionsField != null) {
+                        tiffT4Options = t4OptionsField.getAsLong(0);
+                    if ((tiffT4Options & TIFFConstants.GROUP3OPT_2DENCODING) != 0)
+                        compression = Image.CCITTG3_2D;
+                    if ((tiffT4Options & TIFFConstants.GROUP3OPT_FILLBITS) != 0)
+                        params |= Image.CCITT_ENCODEDBYTEALIGN;
+                    }
+                    break;
+                case TIFFConstants.COMPRESSION_CCITTFAX4:
+                    imagecomp = Image.CCITTG4;
+                    TIFFField t6OptionsField = dir.getField(TIFFConstants.TIFFTAG_GROUP4OPTIONS);
+                    if (t6OptionsField != null)
+                        tiffT6Options = t6OptionsField.getAsLong(0);
+                    break;
+            }
+            if (direct && rowsStrip == h) { //single strip, direct
+                byte im[] = new byte[(int)size[0]];
+                s.seek(offset[0]);
+                s.readFully(im);
+                img = Image.getInstance((int) w, (int) h, reverse, imagecomp, params, im);
+                img.setInverted(true);
+            }
+            else {
+                int rowsLeft = h;
+                CCITTG4Encoder g4 = new CCITTG4Encoder((int)w);
+                for (int k = 0; k < offset.length; ++k) {
+                    byte im[] = new byte[(int)size[k]];
+                    s.seek(offset[k]);
+                    s.readFully(im);
+                    int height = Math.min(rowsStrip, rowsLeft);
+                    TIFFFaxDecoder decoder = new TIFFFaxDecoder(fillOrder, (int)w, height);
+                    byte outBuf[] = new byte[(w + 7) / 8 * height];
+                    switch (compression) {
+                        case TIFFConstants.COMPRESSION_CCITTRLEW:
+                        case TIFFConstants.COMPRESSION_CCITTRLE:
+                            decoder.decode1D(outBuf, im, 0, height);
+                            g4.encodeT6Lines(outBuf, 0, height);
+                            break;
+                        case TIFFConstants.COMPRESSION_CCITTFAX3:
+                            try {
+                                decoder.decode2D(outBuf, im, 0, height, tiffT4Options);
+                            }
+                            catch (Exception e) {
+                                // let's flip the fill bits and try again...
+                                tiffT4Options ^= TIFFConstants.GROUP3OPT_FILLBITS;
+                                try {
+                                    decoder.decode2D(outBuf, im, 0, height, tiffT4Options);
+                                }
+                                catch (Exception e2) {
+                                    throw e;
+                                }
+                            }
+                            g4.encodeT6Lines(outBuf, 0, height);
+                            break;
+                        case TIFFConstants.COMPRESSION_CCITTFAX4:
+                            decoder.decodeT6(outBuf, im, 0, height, tiffT6Options);
+                            g4.encodeT6Lines(outBuf, 0, height);
+                            break;
+                    }
+                    rowsLeft -= rowsStrip;
+                }
+                byte g4pic[] = g4.close();
+                img = Image.getInstance((int) w, (int) h, false, Image.CCITTG4, params & Image.CCITT_BLACKIS1, g4pic);
+            }
+            img.setDpi(dpiX, dpiY);
+            img.setXYRatio(XYRatio);
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE)) {
+                try {
+                    TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_ICCPROFILE);
+                    ICC_Profile icc_prof = ICC_Profile.getInstance(fd.getAsBytes());
+                    if (icc_prof.getNumComponents() == 1)
+                        img.tagICC(icc_prof);
+                }
+                catch (Exception e) {
+                    //empty
+                }
+            }
+            img.setOriginalType(Image.ORIGINAL_TIFF);
+            return img;
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    protected static Image getTiffImageColor(TIFFDirectory dir, RandomAccessFileOrArray s) {
+        try {
+            int compression = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
+            int predictor = 1;
+            TIFFLZWDecoder lzwDecoder = null;
+            switch (compression) {
+                case TIFFConstants.COMPRESSION_NONE:
+                case TIFFConstants.COMPRESSION_LZW:
+                case TIFFConstants.COMPRESSION_PACKBITS:
+                case TIFFConstants.COMPRESSION_DEFLATE:
+                    break;
+                default:
+                    throw new IllegalArgumentException("The compression " + compression + " is not supported.");
+            }
+            int photometric = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
+            switch (photometric) {
+                case TIFFConstants.PHOTOMETRIC_MINISWHITE:
+                case TIFFConstants.PHOTOMETRIC_MINISBLACK:
+                case TIFFConstants.PHOTOMETRIC_RGB:
+                case TIFFConstants.PHOTOMETRIC_SEPARATED:
+                case TIFFConstants.PHOTOMETRIC_PALETTE:
+                    break;
+                default:
+                    throw new IllegalArgumentException("The photometric " + photometric + " is not supported.");
+            }
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_PLANARCONFIG)
+                && dir.getFieldAsLong(TIFFConstants.TIFFTAG_PLANARCONFIG) == TIFFConstants.PLANARCONFIG_SEPARATE)
+                throw new IllegalArgumentException("Planar images are not supported.");
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_EXTRASAMPLES))
+                throw new IllegalArgumentException("Extra samples are not supported.");
+            int samplePerPixel = 1;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL)) // 1,3,4
+                samplePerPixel = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL);
+            int bitsPerSample = 1;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_BITSPERSAMPLE))
+                bitsPerSample = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_BITSPERSAMPLE);
+            switch (bitsPerSample) {
+                case 1:
+                case 2:
+                case 4:
+                case 8:
+                    break;
+                default:
+                    throw new IllegalArgumentException("Bits per sample " + bitsPerSample + " is not supported.");
+            }
+            Image img = null;
+
+            int h = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
+            int w = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
+            int dpiX = 0;
+            int dpiY = 0;
+            int resolutionUnit = TIFFConstants.RESUNIT_INCH;
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
+                resolutionUnit = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
+            dpiX = getDpi(dir.getField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
+            dpiY = getDpi(dir.getField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
+            int rowsStrip = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
+            long offset[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
+            long size[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
+            if (compression == TIFFConstants.COMPRESSION_LZW) {
+                TIFFField predictorField = dir.getField(TIFFConstants.TIFFTAG_PREDICTOR);
+                if (predictorField != null) {
+                    predictor = predictorField.getAsInt(0);
+                    if (predictor != 1 && predictor != 2) {
+                        throw new RuntimeException("Illegal value for Predictor in TIFF file."); 
+                    }
+                    if (predictor == 2 && bitsPerSample != 8) {
+                        throw new RuntimeException(bitsPerSample + "-bit samples are not supported for Horizontal differencing Predictor.");
+                    }
+                }
+                lzwDecoder = new TIFFLZWDecoder(w, predictor, 
+                                                samplePerPixel); 
+            }
+            int rowsLeft = h;
+            ByteArrayOutputStream stream = null;
+            DeflaterOutputStream zip = null;
+            CCITTG4Encoder g4 = null;
+            if (bitsPerSample == 1 && samplePerPixel == 1) {
+                g4 = new CCITTG4Encoder(w);
+            }
+            else {
+                stream = new ByteArrayOutputStream();
+                zip = new DeflaterOutputStream(stream);
+            }
+            for (int k = 0; k < offset.length; ++k) {
+                byte im[] = new byte[(int)size[k]];
+                s.seek(offset[k]);
+                s.readFully(im);
+                int height = Math.min(rowsStrip, rowsLeft);
+                byte outBuf[] = null;
+                if (compression != TIFFConstants.COMPRESSION_NONE)
+                    outBuf = new byte[(w * bitsPerSample * samplePerPixel + 7) / 8 * height];
+                switch (compression) {
+                    case TIFFConstants.COMPRESSION_DEFLATE:
+                        inflate(im, outBuf);
+                        break;
+                    case TIFFConstants.COMPRESSION_NONE:
+                        outBuf = im;
+                        break;
+                    case TIFFConstants.COMPRESSION_PACKBITS:
+                        decodePackbits(im,  outBuf);
+                        break;
+                    case TIFFConstants.COMPRESSION_LZW:
+                        lzwDecoder.decode(im, outBuf, height);
+                        break;
+                }
+                if (bitsPerSample == 1 && samplePerPixel == 1) {
+                    g4.encodeT6Lines(outBuf, 0, height);
+                }
+                else {
+                    zip.write(outBuf);
+                }
+                rowsLeft -= rowsStrip;
+            }
+            if (bitsPerSample == 1 && samplePerPixel == 1) {
+                img = Image.getInstance(w, h, false, Image.CCITTG4, 
+                    photometric == TIFFConstants.PHOTOMETRIC_MINISBLACK ? Image.CCITT_BLACKIS1 : 0, g4.close());
+            }
+            else {
+                zip.close();
+                img = Image.getInstance(w, h, samplePerPixel, bitsPerSample, stream.toByteArray());
+                img.setDeflated(true);
+            }
+            img.setDpi(dpiX, dpiY);
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE)) {
+                try {
+                    TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_ICCPROFILE);
+                    ICC_Profile icc_prof = ICC_Profile.getInstance(fd.getAsBytes());
+                    if (samplePerPixel == icc_prof.getNumComponents())
+                        img.tagICC(icc_prof);
+                }
+                catch (Exception e) {
+                    //empty
+                }
+            }
+            if (dir.isTagPresent(TIFFConstants.TIFFTAG_COLORMAP)) {
+                TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_COLORMAP);
+                char rgb[] = fd.getAsChars();
+                byte palette[] = new byte[rgb.length];
+                int gColor = rgb.length / 3;
+                int bColor = gColor * 2;
+                for (int k = 0; k < gColor; ++k) {
+                    palette[k * 3] = (byte)(rgb[k] >>> 8);
+                    palette[k * 3 + 1] = (byte)(rgb[k + gColor] >>> 8);
+                    palette[k * 3 + 2] = (byte)(rgb[k + bColor] >>> 8);
+                }
+                PdfArray indexed = new PdfArray();
+                indexed.add(PdfName.INDEXED);
+                indexed.add(PdfName.DEVICERGB);
+                indexed.add(new PdfNumber(gColor - 1));
+                indexed.add(new PdfString(palette));
+                PdfDictionary additional = new PdfDictionary();
+                additional.put(PdfName.COLORSPACE, indexed);
+                img.setAdditional(additional);
+            }
+            if (photometric == TIFFConstants.PHOTOMETRIC_MINISWHITE)
+                img.setInverted(true);
+            img.setOriginalType(Image.ORIGINAL_TIFF);
+            return img;
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+    }
+    
+    static long[] getArrayLongShort(TIFFDirectory dir, int tag) {
+        TIFFField field = dir.getField(tag);
+        if (field == null)
+            return null;
+        long offset[];
+        if (field.getType() == TIFFField.TIFF_LONG)
+            offset = field.getAsLongs();
+        else { // must be short
+            char temp[] = field.getAsChars();
+            offset = new long[temp.length];
+            for (int k = 0; k < temp.length; ++k)
+                offset[k] = temp[k];
+        }
+        return offset;
+    }
+    
+    // Uncompress packbits compressed image data.
+    public static void decodePackbits(byte data[], byte[] dst) {
+        int srcCount = 0, dstCount = 0;
+        byte repeat, b;
+        
+        while (dstCount < dst.length) {
+            b = data[srcCount++];
+            if (b >= 0 && b <= 127) {
+                // literal run packet
+                for (int i=0; i<(b + 1); i++) {
+                    dst[dstCount++] = data[srcCount++];
+                }
+
+            } else if (b <= -1 && b >= -127) {
+                // 2 byte encoded run packet
+                repeat = data[srcCount++];
+                for (int i=0; i<(-b + 1); i++) {
+                    dst[dstCount++] = repeat;
+                }
+            } else {
+                // no-op packet. Do nothing
+                srcCount++;
+            }
+        }
+    }
+
+    public static void inflate(byte[] deflated, byte[] inflated) {
+        Inflater inflater = new Inflater();
+        inflater.setInput(deflated);
+        try {
+            inflater.inflate(inflated);
+        }
+        catch(DataFormatException dfe) {
+            throw new ExceptionConverter(dfe);
+        }
+    }
+
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/JavaCharStream.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/JavaCharStream.java
new file mode 100644
index 0000000..2950d29
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/JavaCharStream.java
@@ -0,0 +1,548 @@
+/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 2.1 */
+package com.lowagie.text.pdf.codec.postscript;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (with java-like unicode escape processing).
+ */
+
+public final class JavaCharStream
+{
+  public static final boolean staticFlag = false;
+  static final int hexval(char c) throws java.io.IOException {
+    switch(c)
+    {
+       case '0' :
+          return 0;
+       case '1' :
+          return 1;
+       case '2' :
+          return 2;
+       case '3' :
+          return 3;
+       case '4' :
+          return 4;
+       case '5' :
+          return 5;
+       case '6' :
+          return 6;
+       case '7' :
+          return 7;
+       case '8' :
+          return 8;
+       case '9' :
+          return 9;
+
+       case 'a' :
+       case 'A' :
+          return 10;
+       case 'b' :
+       case 'B' :
+          return 11;
+       case 'c' :
+       case 'C' :
+          return 12;
+       case 'd' :
+       case 'D' :
+          return 13;
+       case 'e' :
+       case 'E' :
+          return 14;
+       case 'f' :
+       case 'F' :
+          return 15;
+    }
+
+    throw new java.io.IOException(); // Should never come here
+  }
+
+  public int bufpos = -1;
+  int bufsize;
+  int available;
+  int tokenBegin;
+  private int bufline[];
+  private int bufcolumn[];
+
+  private int column = 0;
+  private int line = 1;
+
+  private boolean prevCharIsCR = false;
+  private boolean prevCharIsLF = false;
+
+  private java.io.Reader inputStream;
+
+  private char[] nextCharBuf;
+  private char[] buffer;
+  private int maxNextCharInd = 0;
+  private int nextCharInd = -1;
+  private int inBuf = 0;
+
+  private final void ExpandBuff(boolean wrapAround)
+  {
+     char[] newbuffer = new char[bufsize + 2048];
+     int newbufline[] = new int[bufsize + 2048];
+     int newbufcolumn[] = new int[bufsize + 2048];
+
+     try
+     {
+        if (wrapAround)
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           System.arraycopy(buffer, 0, newbuffer,
+                                             bufsize - tokenBegin, bufpos);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+           bufcolumn = newbufcolumn;
+
+           bufpos += (bufsize - tokenBegin);
+        }
+        else
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           bufcolumn = newbufcolumn;
+
+           bufpos -= tokenBegin;
+        }
+     }
+     catch (Throwable t)
+     {
+        throw new Error(t.getMessage());
+     }
+
+     available = (bufsize += 2048);
+     tokenBegin = 0;
+  }
+
+  private final void FillBuff() throws java.io.IOException
+  {
+     int i;
+     if (maxNextCharInd == 4096)
+        maxNextCharInd = nextCharInd = 0;
+
+     try {
+        if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
+                                            4096 - maxNextCharInd)) == -1)
+        {
+           inputStream.close();
+           throw new java.io.IOException();
+        }
+        else
+           maxNextCharInd += i;
+        return;
+     }
+     catch(java.io.IOException e) {
+        if (bufpos != 0)
+        {
+           --bufpos;
+           backup(0);
+        }
+        else
+        {
+           bufline[bufpos] = line;
+           bufcolumn[bufpos] = column;
+        }
+        throw e;
+     }
+  }
+
+  private final char ReadByte() throws java.io.IOException
+  {
+     if (++nextCharInd >= maxNextCharInd)
+        FillBuff();
+
+     return nextCharBuf[nextCharInd];
+  }
+
+  public final char BeginToken() throws java.io.IOException
+  {
+     if (inBuf > 0)
+     {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        tokenBegin = bufpos;
+        return buffer[bufpos];
+     }
+
+     tokenBegin = 0;
+     bufpos = -1;
+
+     return readChar();
+  }
+
+  private final void AdjustBuffSize()
+  {
+     if (available == bufsize)
+     {
+        if (tokenBegin > 2048)
+        {
+           bufpos = 0;
+           available = tokenBegin;
+        }
+        else
+           ExpandBuff(false);
+     }
+     else if (available > tokenBegin)
+        available = bufsize;
+     else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+     else
+        available = tokenBegin;
+  }
+
+  private final void UpdateLineColumn(char c)
+  {
+     column++;
+
+     if (prevCharIsLF)
+     {
+        prevCharIsLF = false;
+        line += (column = 1);
+     }
+     else if (prevCharIsCR)
+     {
+        prevCharIsCR = false;
+        if (c == '\n')
+        {
+           prevCharIsLF = true;
+        }
+        else
+           line += (column = 1);
+     }
+
+     switch (c)
+     {
+        case '\r' :
+           prevCharIsCR = true;
+           break;
+        case '\n' :
+           prevCharIsLF = true;
+           break;
+        case '\t' :
+           column--;
+           column += (8 - (column & 07));
+           break;
+        default :
+           break;
+     }
+
+     bufline[bufpos] = line;
+     bufcolumn[bufpos] = column;
+  }
+
+  public final char readChar() throws java.io.IOException
+  {
+     if (inBuf > 0)
+     {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        return buffer[bufpos];
+     }
+
+     char c;
+
+     if (++bufpos == available)
+        AdjustBuffSize();
+
+     if ((buffer[bufpos] = c = ReadByte()) == '\\')
+     {
+        UpdateLineColumn(c);
+
+        int backSlashCnt = 1;
+
+        for (;;) // Read all the backslashes
+        {
+           if (++bufpos == available)
+              AdjustBuffSize();
+
+           try
+           {
+              if ((buffer[bufpos] = c = ReadByte()) != '\\')
+              {
+                 UpdateLineColumn(c);
+                 // found a non-backslash char.
+                 if ((c == 'u') && ((backSlashCnt & 1) == 1))
+                 {
+                    if (--bufpos < 0)
+                       bufpos = bufsize - 1;
+
+                    break;
+                 }
+
+                 backup(backSlashCnt);
+                 return '\\';
+              }
+           }
+           catch(java.io.IOException e)
+           {
+              if (backSlashCnt > 1)
+                 backup(backSlashCnt);
+
+              return '\\';
+           }
+
+           UpdateLineColumn(c);
+           backSlashCnt++;
+        }
+
+        // Here, we have seen an odd number of backslash's followed by a 'u'
+        try
+        {
+           while ((c = ReadByte()) == 'u')
+              ++column;
+
+           buffer[bufpos] = c = (char)(hexval(c) << 12 |
+                                       hexval(ReadByte()) << 8 |
+                                       hexval(ReadByte()) << 4 |
+                                       hexval(ReadByte()));
+
+           column += 4;
+        }
+        catch(java.io.IOException e)
+        {
+           throw new Error("Invalid escape character at line " + line +
+                                         " column " + column + ".");
+        }
+
+        if (backSlashCnt == 1)
+           return c;
+        else
+        {
+           backup(backSlashCnt - 1);
+           return '\\';
+        }
+     }
+     else
+     {
+        UpdateLineColumn(c);
+        return (c);
+     }
+  }
+
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public final int getColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public final int getLine() {
+     return bufline[bufpos];
+  }
+
+  public final int getEndColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  public final int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  public final int getBeginColumn() {
+     return bufcolumn[tokenBegin];
+  }
+
+  public final int getBeginLine() {
+     return bufline[tokenBegin];
+  }
+
+  public final void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+       bufpos += bufsize;
+  }
+
+  public JavaCharStream(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+    nextCharBuf = new char[4096];
+  }
+
+  public JavaCharStream(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public JavaCharStream(java.io.Reader dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+  public void ReInit(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+      nextCharBuf = new char[4096];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    nextCharInd = bufpos = -1;
+  }
+
+  public void ReInit(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  public void ReInit(java.io.Reader dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public JavaCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+     this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+  public JavaCharStream(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public JavaCharStream(java.io.InputStream dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+
+  public void ReInit(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+     ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+  public void ReInit(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+  public void ReInit(java.io.InputStream dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+
+  public final String GetImage()
+  {
+     if (bufpos >= tokenBegin)
+        return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+     else
+        return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                              new String(buffer, 0, bufpos + 1);
+  }
+
+  public final char[] GetSuffix(int len)
+  {
+     char[] ret = new char[len];
+
+     if ((bufpos + 1) >= len)
+        System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+     else
+     {
+        System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                          len - bufpos - 1);
+        System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+     }
+
+     return ret;
+  }
+
+  public void Done()
+  {
+     nextCharBuf = null;
+     buffer = null;
+     bufline = null;
+     bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.<BR>
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+     int start = tokenBegin;
+     int len;
+
+     if (bufpos >= tokenBegin)
+     {
+        len = bufpos - tokenBegin + inBuf + 1;
+     }
+     else
+     {
+        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+     }
+
+     int i = 0, j = 0, k = 0;
+     int nextColDiff = 0, columnDiff = 0;
+
+     while (i < len &&
+            bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+     {
+        bufline[j] = newLine;
+        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+        bufcolumn[j] = newCol + columnDiff;
+        columnDiff = nextColDiff;
+        i++;
+     }
+
+     if (i < len)
+     {
+        bufline[j] = newLine++;
+        bufcolumn[j] = newCol + columnDiff;
+
+        while (i++ < len)
+        {
+           if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+              bufline[j] = newLine++;
+           else
+              bufline[j] = newLine;
+        }
+     }
+
+     line = bufline[j];
+     column = bufcolumn[j];
+  }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/MetaDoPS.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/MetaDoPS.java
new file mode 100644
index 0000000..543ee35
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/MetaDoPS.java
@@ -0,0 +1,98 @@
+/*
+ * $Id: MetaDo.java,v 1.28 2003/05/02 09:01:33 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.io.*;
+import headless.awt.*;
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+
+public class MetaDoPS {
+
+  public PdfContentByte cb;
+  InputStream in;
+  int left;
+  int top;
+  int right;
+  int bottom;
+  int inch;
+
+  public MetaDoPS(InputStream in, PdfContentByte cb) {
+    this.cb = cb;
+    this.in = in;
+  }
+
+  public void readAll() throws IOException, DocumentException {
+
+    cb.saveState();
+    java.awt.Graphics2D g2 = cb.createGraphicsShapes(PageSize.A4.
+        width(), PageSize.A4.height());
+    try {
+      PAContext context = new PAContext( (Graphics2D) g2,
+                                        new Dimension( (int) PageSize.A4.width(),
+          (int) PageSize.A4.height()));
+      context.draw(new BufferedInputStream(in));
+      // ( (Graphics2D) backBuffer.getGraphics()).dispose();
+      in.close();
+    }
+    catch (IOException ex) {
+      ex.printStackTrace();
+    }
+    catch (PainterException ex) {
+      ex.printStackTrace();
+    }
+
+    cb.restoreState();
+
+  }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PACommand.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PACommand.java
new file mode 100644
index 0000000..6f52e4a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PACommand.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+
+public interface PACommand {
+
+    public void execute(PAContext context) throws PainterException;
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAContext.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAContext.java
new file mode 100644
index 0000000..c998fad
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAContext.java
@@ -0,0 +1,2053 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.io.*;
+import headless.awt.*;
+import headless.awt.geom.*;
+import headless.awt.color.*;
+import headless.awt.font.*;
+
+public class PAContext
+    extends Object {
+
+  public PAPencil pencil;
+  public Stack dictionaries;
+  public Stack operands;
+  public PAEngine engine;
+  PAParser poorscript = null;
+  protected Random randomNumberGenerator;
+
+  protected Object lastUnknownIdentifier;
+
+  public PAContext(Component component) {
+    this(new PAPencil(component));
+  }
+
+  public PAContext(Graphics2D g, Dimension size) {
+    this(new PAPencil(g, size));
+  }
+
+  public PAContext(PAPencil pencil) {
+    super();
+    this.pencil = pencil;
+    this.dictionaries = new Stack();
+    this.operands = new Stack();
+    this.engine = new PAEngine(this);
+    this.dictionaries.push(this.constructSystemDict());
+    this.dictionaries.push(this.constructGlobalDict());
+    this.dictionaries.push(new HashMap());
+    this.randomNumberGenerator = new Random();
+    this.lastUnknownIdentifier = null;
+  }
+
+  public void draw(InputStream inputStream) throws PainterException {
+    try {
+
+        poorscript = new PAParser(inputStream);
+
+      poorscript.parse(this);
+     // pencil.graphics.dispose();
+    }
+    catch (ParseException e) {
+      e.printStackTrace();
+      throw new PainterException(e.toString());
+    }
+  }
+
+  public Object getLastUnknownIdentifier() {
+    return this.lastUnknownIdentifier;
+  }
+
+  public double[] popNumberOperands(int n) throws PainterException {
+    double[] result = new double[n];
+    Object objectValue;
+    double doubleValue;
+
+    for (int i = n - 1; i >= 0; i--) {
+      try {
+        objectValue = this.operands.pop();
+      }
+      catch (EmptyStackException e) {
+        throw new PainterException("Operand stack is empty");
+      }
+      if (objectValue instanceof Number) {
+        doubleValue = ( (Number) objectValue).doubleValue();
+      }
+      else {
+        throw new PainterException("Number expected on operand stack");
+      }
+      result[i] = doubleValue;
+    }
+    return result;
+  }
+
+  public Object[] popOperands(int n) throws PainterException {
+    Object[] result = new Object[n];
+    Object objectValue;
+
+    for (int i = n - 1; i >= 0; i--) {
+      try {
+        objectValue = this.operands.pop();
+      }
+      catch (EmptyStackException e) {
+        throw new PainterException("Operand stack is empty");
+      }
+      result[i] = objectValue;
+    }
+    return result;
+  }
+
+  public Object peekOperand() throws PainterException {
+    Object objectValue;
+
+    try {
+      objectValue = this.operands.peek();
+    }
+    catch (EmptyStackException e) {
+      throw new PainterException("Operand stack is empty");
+    }
+    return objectValue;
+  }
+
+  public Object findIdentifier(Object identifier) {
+    Object result = null;
+    int i, n;
+
+    n = this.dictionaries.size();
+    i = n - 1;
+    while (i >= 0 && result == null) {
+      HashMap dictionary = (HashMap)this.dictionaries.elementAt(i);
+      result = dictionary.get(identifier);
+      i--;
+    }
+    if (result == null) {
+      this.lastUnknownIdentifier = identifier;
+    }
+    return result;
+  }
+
+  public Object findDictionary(Object identifier) {
+    Object result = null;
+    HashMap dictionary = null;
+    int i, n;
+
+    n = this.dictionaries.size();
+    i = n - 1;
+    while (i >= 0 && result == null) {
+      dictionary = (HashMap)this.dictionaries.elementAt(i);
+      result = dictionary.get(identifier);
+      i--;
+    }
+    if (result == null) {
+      return result;
+    }
+    else {
+      return dictionary;
+    }
+  }
+
+  public void collectArray() throws PainterException {
+    ArrayList result;
+    Object objectValue;
+    int i, n;
+    boolean found = false;
+
+    n = this.operands.size();
+    for (i = n - 1; i >= 0; i--) {
+      objectValue = this.operands.elementAt(i);
+      if (objectValue instanceof PAToken &&
+          ( (PAToken) objectValue).type == PAToken.START_ARRAY) {
+        found = true;
+        break;
+      }
+    }
+    if (!found) {
+      throw new PainterException("No array was started");
+    }
+    result = new ArrayList(n - i - 1);
+    for (int j = 0; j < n - i - 1; j++) {
+      result.add(null);
+    }
+    for (int j = n - 1; j > i; j--) {
+      try {
+        objectValue = this.operands.pop();
+      }
+      catch (EmptyStackException e) {
+        throw new PainterException("Operand stack is empty");
+      }
+      result.set(j - i - 1, objectValue);
+    }
+    try {
+      this.operands.pop(); // the start array mark itself
+    }
+    catch (EmptyStackException e) {
+      throw new PainterException("Operand stack is empty");
+    }
+    this.operands.push(result);
+  }
+
+  protected HashMap constructGlobalDict() {
+    HashMap globalDict = new HashMap();
+
+    return globalDict;
+  }
+
+  protected HashMap constructSystemDict() {
+    HashMap systemDict = new HashMap();
+
+    // newpath
+    systemDict.put("newpath", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.newpath();
+      }
+    });
+
+    // moveto
+    systemDict.put("moveto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.pencil.moveto(data[0], data[1]);
+      }
+    });
+
+    // rmoveto
+    systemDict.put("rmoveto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.pencil.rmoveto(data[0], data[1]);
+      }
+    });
+
+    // lineto
+    systemDict.put("lineto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.pencil.lineto(data[0], data[1]);
+      }
+    });
+
+    // rlineto
+    systemDict.put("rlineto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.pencil.rlineto(data[0], data[1]);
+      }
+    });
+
+    // arc
+    systemDict.put("arc", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(5);
+        context.pencil.arc(data[0], data[1], data[2], data[3], data[4]);
+      }
+    });
+
+    // arcn
+    systemDict.put("arcn", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(5);
+        context.pencil.arcn(data[0], data[1], data[2], data[3], data[4]);
+      }
+    });
+
+    // curveto
+    systemDict.put("curveto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(6);
+        context.pencil.curveto(data[0], data[1], data[2], data[3], data[4],
+                               data[5]);
+      }
+    });
+
+    // rcurveto
+    systemDict.put("rcurveto", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(6);
+        context.pencil.rcurveto(data[0], data[1], data[2], data[3], data[4],
+                                data[5]);
+      }
+    });
+
+    // closepath
+    systemDict.put("closepath", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.closepath();
+      }
+    });
+
+    // gsave
+    systemDict.put("gsave", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.gsave();
+      }
+    });
+
+    // grestore
+    systemDict.put("grestore", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.grestore();
+      }
+    });
+
+    // translate
+    systemDict.put("translate", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        if (context.peekOperand() instanceof Number) {
+          double data[];
+          AffineTransform at = new AffineTransform();
+          AffineTransform ctm = context.pencil.graphics.getTransform();
+
+          data = context.popNumberOperands(2);
+          at.translate(data[0], data[1]);
+          ctm.concatenate(at);
+          context.pencil.graphics.setTransform(ctm);
+        }
+        else {
+          Object data[];
+
+          data = context.popOperands(3);
+          if (! (data[0] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[2] instanceof ArrayList)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          ArrayList array = (ArrayList) data[2];
+
+          if (! (array.size() == 6)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          AffineTransform at = new AffineTransform();
+
+          at.translate( ( (Number) data[0]).doubleValue(),
+                       ( (Number) data[1]).doubleValue());
+
+          double[] entries = new double[6];
+
+          at.getMatrix(entries);
+
+          for (int i = 0; i < 6; i++) {
+            array.set(i, new Double(entries[i]));
+          }
+          context.operands.push(array);
+        }
+      }
+    });
+
+    // rotate
+    systemDict.put("rotate", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        if (context.peekOperand() instanceof Number) {
+          double data[];
+          AffineTransform at = new AffineTransform();
+          AffineTransform ctm = context.pencil.graphics.getTransform();
+
+          data = context.popNumberOperands(1);
+          at.rotate(data[0] * Math.PI / 180.0d);
+          ctm.concatenate(at);
+          context.pencil.graphics.setTransform(ctm);
+        }
+        else {
+          Object data[];
+          AffineTransform at = new AffineTransform();
+
+          data = context.popOperands(2);
+          if (! (data[0] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[1] instanceof ArrayList)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          ArrayList array = (ArrayList) data[1];
+
+          if (! (array.size() == 6)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          at.rotate( ( (Number) data[0]).doubleValue());
+
+          double[] entries = new double[6];
+
+          at.getMatrix(entries);
+
+          for (int i = 0; i < 6; i++) {
+            array.set(i, new Double(entries[i]));
+          }
+          context.operands.push(array);
+        }
+      }
+    });
+
+    // scale
+    systemDict.put("scale", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        if (context.peekOperand() instanceof Number) {
+          double data[];
+          AffineTransform at = new AffineTransform();
+          AffineTransform ctm = context.pencil.graphics.getTransform();
+
+          data = context.popNumberOperands(2);
+          at.scale(data[0], data[1]);
+          ctm.concatenate(at);
+          context.pencil.graphics.setTransform(ctm);
+        }
+        else {
+          Object data[];
+
+          data = context.popOperands(3);
+          if (! (data[0] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[2] instanceof ArrayList)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          ArrayList array = (ArrayList) data[2];
+
+          double[] entries = new double[6];
+
+          if (! (array.size() == 6)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          entries[0] = ( (Number) data[0]).doubleValue();
+          entries[1] = 0.0d;
+          entries[2] = 0.0d;
+          entries[3] = ( (Number) data[1]).doubleValue();
+          entries[4] = 0.0d;
+          entries[5] = 0.0d;
+
+          for (int i = 0; i < 6; i++) {
+            array.set(i, new Double(entries[i]));
+          }
+          context.operands.push(array);
+        }
+      }
+    });
+
+    // stroke
+    systemDict.put("stroke", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.stroke();
+      }
+    });
+
+    // fill
+    systemDict.put("fill", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.fill();
+      }
+    });
+
+    // eofill
+    systemDict.put("eofill", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.eofill();
+      }
+    });
+
+    // show
+    systemDict.put("show", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(1);
+        if (! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.pencil.show( (String) data[0]);
+      }
+    });
+
+    // stringwidth
+    systemDict.put("stringwidth", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        float[] result;
+        Font font;
+
+        data = context.popOperands(1);
+        if (! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        font = context.pencil.graphics.getFont();
+        Rectangle2D rect = font.getStringBounds( (String) data[0],
+                                                context.pencil.graphics.
+                                                getFontRenderContext());
+        context.operands.push(new Float(rect.getWidth()));
+        context.operands.push(new Float(rect.getHeight()));
+      }
+    });
+
+    // showpage
+    systemDict.put("showpage", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.showpage();
+      }
+    });
+
+    // findfont
+    systemDict.put("findfont", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.operands.push(context.pencil.findFont( (String) patoken.value));
+      }
+    });
+
+    // scalefont
+    systemDict.put("scalefont", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Font)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.operands.push( ( (Font) data[0]).deriveFont( ( (Number) data[1]).
+            floatValue()));
+      }
+    });
+
+    // setfont
+    systemDict.put("setfont", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(1);
+        if (! (data[0] instanceof Font)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.pencil.graphics.setFont( (Font) data[0]);
+      }
+    });
+
+    // def
+    systemDict.put("def", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(2);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        try {
+          ( (HashMap) context.dictionaries.peek()).put(patoken.value, data[1]);
+        }
+        catch (EmptyStackException e) {
+          throw new PainterException(e.toString());
+        }
+      }
+    });
+
+    // bind
+    systemDict.put("bind", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.engine.bindProcedure(patoken);
+        context.operands.push(patoken);
+      }
+    });
+
+    // mul
+    systemDict.put("mul", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.operands.push(new Double(data[0] * data[1]));
+      }
+    });
+
+    // div
+    systemDict.put("div", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.operands.push(new Double(data[0] / data[1]));
+      }
+    });
+
+    // mod
+    systemDict.put("mod", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        int a, b, m;
+        a = (int) data[0];
+        b = (int) data[1];
+        m = a % b;
+        context.operands.push(new Integer(m));
+      }
+    });
+
+    // add
+    systemDict.put("add", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.operands.push(new Double(data[0] + data[1]));
+      }
+    });
+
+    // neg
+    systemDict.put("neg", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Double( -data[0]));
+      }
+    });
+
+    // sub
+    systemDict.put("sub", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.operands.push(new Double(data[0] - data[1]));
+      }
+    });
+
+    // atan
+    systemDict.put("atan", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(2);
+        context.operands.push(new Double(Math.atan2(data[0], data[1])));
+      }
+    });
+
+    // sin
+    systemDict.put("sin", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Double(Math.sin(data[0] * Math.PI / 180.0)));
+      }
+    });
+
+    // cos
+    systemDict.put("cos", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Double(Math.cos(data[0] * Math.PI / 180.0)));
+      }
+    });
+
+    // sqrt
+    systemDict.put("sqrt", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Double(Math.sqrt(data[0])));
+      }
+    });
+
+    // exch
+    systemDict.put("exch", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        context.operands.push(data[1]);
+        context.operands.push(data[0]);
+      }
+    });
+
+    // dup
+    systemDict.put("dup", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(1);
+        context.operands.push(data[0]);
+        context.operands.push(data[0]);
+      }
+    });
+
+    // roll
+    systemDict.put("roll", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        Object rollData[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        int numberOfElements, numberOfPositions, i;
+
+        numberOfElements = ( (Number) data[0]).intValue();
+        numberOfPositions = ( (Number) data[1]).intValue();
+
+        if (numberOfPositions == 0 || numberOfElements <= 0) {
+          return;
+        }
+
+        rollData = context.popOperands(numberOfElements);
+
+        if (numberOfPositions < 0) {
+          numberOfPositions = -numberOfPositions;
+          numberOfPositions = numberOfPositions % numberOfElements;
+
+          // downward roll
+          for (i = numberOfPositions; i < numberOfElements; i++) {
+            context.operands.push(rollData[i]);
+          }
+          for (i = 0; i < numberOfPositions; i++) {
+            context.operands.push(rollData[i]);
+          }
+        }
+        else {
+          numberOfPositions = numberOfPositions % numberOfElements;
+
+          // upward roll
+          for (i = numberOfElements - numberOfPositions; i < numberOfElements;
+               i++) {
+            context.operands.push(rollData[i]);
+          }
+          for (i = 0; i < numberOfElements - numberOfPositions; i++) {
+            context.operands.push(rollData[i]);
+          }
+        }
+      }
+    });
+
+    // pop
+    systemDict.put("pop", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.popOperands(1);
+      }
+    });
+
+    // index
+    systemDict.put("index", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(1);
+        if (! (data[0] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        int index = ( (Number) data[0]).intValue();
+        try {
+          context.operands.push(context.operands.elementAt(index));
+        }
+        catch (ArrayIndexOutOfBoundsException e) {
+          throw new PainterException(e.toString());
+        }
+      }
+    });
+
+    // mark
+    systemDict.put("mark", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.operands.push(new PAToken(null, PAToken.MARK));
+      }
+    });
+
+    // cleartomark
+    systemDict.put("cleartomark", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data;
+        boolean finished = false;
+
+        while (!finished) {
+          try {
+            data = context.operands.pop();
+            if (data instanceof PAToken) {
+              if ( ( (PAToken) data).type == PAToken.MARK) {
+                finished = true;
+              }
+            }
+          }
+          catch (EmptyStackException e) {
+            throw new PainterException(e.toString());
+          }
+        }
+      }
+    });
+
+    // copy
+    systemDict.put("copy", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(2);
+
+        // decide if it's a simple copy or a composite object copy
+        if ( (data[0] instanceof PAToken) && (data[1] instanceof PAToken)) {
+          // composite object copy
+          if ( ( (PAToken) data[0]).type == ( (PAToken) data[1]).type) {
+            // our tokens are immutable so a copy is easy
+            context.operands.push(data[0]);
+            context.operands.push(data[0]);
+          }
+          else {
+            throw new PainterException(
+                "copy operation failed because composite objects on stack are not of same type");
+          }
+        }
+        else {
+          // restore first arg, we're not interested in it in this simple case
+          context.operands.push(data[0]);
+
+          if (data[1] instanceof Number) {
+            int index = ( (Number) data[1]).intValue();
+            int i, n;
+            n = context.operands.size();
+            Object[] copyData = new Object[index];
+            for (i = n - index; i < n; i++) {
+              try {
+                copyData[i - n + index] = context.operands.elementAt(i);
+              }
+              catch (ArrayIndexOutOfBoundsException e) {
+                throw new PainterException(e.toString());
+              }
+            }
+            for (i = 0; i < index; i++) {
+              context.operands.push(copyData[i]);
+            }
+          }
+          else {
+            throw new PainterException("I expect a number on stack, dude");
+          }
+        }
+      }
+    });
+
+    // setgray
+    systemDict.put("setgray", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.pencil.graphics.setPaint(new Color( (float) data[0],
+            (float) data[0], (float) data[0]));
+      }
+    });
+
+    // setrgbcolor
+    systemDict.put("setrgbcolor", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(3);
+        float[] fv = new float[3];
+        fv[0] = (float) Math.max(Math.min(data[0], 1.0d), 0.0d);
+        fv[1] = (float) Math.max(Math.min(data[1], 1.0d), 0.0d);
+        fv[2] = (float) Math.max(Math.min(data[2], 1.0d), 0.0d);
+        context.pencil.graphics.setPaint(new Color(fv[0], fv[1], fv[2]));
+      }
+    });
+
+    // PENDING(uweh): color stuff still shaky
+    // sethsbcolor
+    systemDict.put("sethsbcolor", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(3);
+        float[] fv = new float[3];
+        fv[0] = (float) Math.max(Math.min(data[0], 1.0d), 0.0d);
+        fv[1] = (float) Math.max(Math.min(data[1], 1.0d), 0.0d);
+        fv[2] = (float) Math.max(Math.min(data[2], 1.0d), 0.0d);
+        context.pencil.graphics.setPaint(new Color(fv[0], fv[1], fv[2]));
+      }
+    });
+
+    // PENDING(uweh): I have to convert these puppies myself to rgb ?
+    // setcmybcolor
+    systemDict.put("setcmybcolor", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        int rd, gr, bl;
+
+        data = context.popNumberOperands(4);
+        float[] fv = new float[4];
+        fv[0] = (float) data[0];
+        fv[1] = (float) data[1];
+        fv[2] = (float) data[2];
+        fv[3] = (float) data[3];
+        rd = (int) (255 * Math.max(0, 1 - fv[0] - fv[3]));
+        gr = (int) (255 * Math.max(0, 1 - fv[1] - fv[3]));
+        bl = (int) (255 * Math.max(0, 1 - fv[2] - fv[3]));
+        context.pencil.graphics.setPaint(new Color(rd, gr, bl));
+      }
+    });
+
+    // setlinewidth
+    systemDict.put("setlinewidth", new PACommand() {
+      private double minLineWidth(double w, AffineTransform at) {
+        double matrix[] = new double[4];
+        at.getMatrix(matrix);
+        double scale = matrix[0] * matrix[3] - matrix[1] * matrix[2];
+        double minlw = .25 / Math.sqrt(Math.abs(scale));
+        if (w < minlw) {
+          w = minlw;
+        }
+        return w;
+      }
+
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        BasicStroke newStroke;
+        Stroke oldStroke = context.pencil.graphics.getStroke();
+        data = context.popNumberOperands(1);
+        data[0] = this.minLineWidth(data[0],
+                                    context.pencil.graphics.getTransform());
+        if (oldStroke instanceof BasicStroke) {
+          newStroke = new BasicStroke( (float) data[0],
+                                      ( (BasicStroke) oldStroke).getEndCap(),
+                                      ( (BasicStroke) oldStroke).getLineJoin(),
+                                      ( (BasicStroke) oldStroke).getMiterLimit(),
+                                      ( (BasicStroke) oldStroke).getDashArray(),
+                                      ( (BasicStroke) oldStroke).getDashPhase());
+        }
+        else {
+          newStroke = new BasicStroke( (float) data[0], BasicStroke.CAP_ROUND,
+                                      BasicStroke.JOIN_ROUND);
+        }
+        context.pencil.graphics.setStroke(newStroke);
+      }
+    });
+
+    // setlinecap
+    systemDict.put("setlinecap", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        BasicStroke newStroke;
+        Stroke oldStroke = context.pencil.graphics.getStroke();
+        data = context.popNumberOperands(1);
+        if (oldStroke instanceof BasicStroke) {
+          newStroke = new BasicStroke( ( (BasicStroke) oldStroke).getLineWidth(),
+                                      (int) data[0],
+                                      ( (BasicStroke) oldStroke).getLineJoin(),
+                                      ( (BasicStroke) oldStroke).getMiterLimit(),
+                                      ( (BasicStroke) oldStroke).getDashArray(),
+                                      ( (BasicStroke) oldStroke).getDashPhase());
+        }
+        else {
+          newStroke = new BasicStroke(1.0f, (int) data[0],
+                                      BasicStroke.JOIN_ROUND);
+        }
+        context.pencil.graphics.setStroke(newStroke);
+      }
+    });
+
+    // setmiterlimit
+    systemDict.put("setmiterlimit", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        BasicStroke newStroke;
+        Stroke oldStroke = context.pencil.graphics.getStroke();
+        data = context.popNumberOperands(1);
+        if (oldStroke instanceof BasicStroke) {
+          newStroke = new BasicStroke( ( (BasicStroke) oldStroke).getLineWidth(),
+                                      ( (BasicStroke) oldStroke).getEndCap(),
+                                      ( (BasicStroke) oldStroke).getLineJoin(),
+                                      (float) data[0],
+                                      ( (BasicStroke) oldStroke).getDashArray(),
+                                      ( (BasicStroke) oldStroke).getDashPhase());
+        }
+        else {
+          newStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+                                      BasicStroke.JOIN_ROUND, (float) data[0]);
+        }
+        context.pencil.graphics.setStroke(newStroke);
+      }
+    });
+
+    // setdash
+    systemDict.put("setdash", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        BasicStroke newStroke;
+        Stroke oldStroke = context.pencil.graphics.getStroke();
+        data = context.popOperands(2);
+        if (! (data[0] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        ArrayList list = (ArrayList) data[0];
+
+        if (list.size() == 0) {
+          return;
+        }
+        float[] dashpattern = new float[list.size()];
+        for (int i = 0; i < dashpattern.length; i++) {
+          dashpattern[i] = ( (Number) list.get(i)).floatValue();
+        }
+        float dashoffset = ( (Number) data[1]).floatValue();
+        if (oldStroke instanceof BasicStroke) {
+          newStroke = new BasicStroke( ( (BasicStroke) oldStroke).getLineWidth(),
+                                      ( (BasicStroke) oldStroke).getEndCap(),
+                                      ( (BasicStroke) oldStroke).getLineJoin(),
+                                      ( (BasicStroke) oldStroke).getMiterLimit(),
+                                      dashpattern,
+                                      dashoffset);
+        }
+        else {
+          newStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+                                      BasicStroke.JOIN_ROUND, 1.0f, dashpattern,
+                                      dashoffset);
+        }
+        context.pencil.graphics.setStroke(newStroke);
+      }
+    });
+
+    // setlinejoin
+    systemDict.put("setlinejoin", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        BasicStroke newStroke;
+        Stroke oldStroke = context.pencil.graphics.getStroke();
+        data = context.popNumberOperands(1);
+        if (oldStroke instanceof BasicStroke) {
+          newStroke = new BasicStroke( ( (BasicStroke) oldStroke).getLineWidth(),
+                                      ( (BasicStroke) oldStroke).getEndCap(),
+                                      (int) data[0],
+                                      ( (BasicStroke) oldStroke).getMiterLimit(),
+                                      ( (BasicStroke) oldStroke).getDashArray(),
+                                      ( (BasicStroke) oldStroke).getDashPhase());
+        }
+        else {
+          newStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, (int) data[0]);
+        }
+        context.pencil.graphics.setStroke(newStroke);
+      }
+    });
+
+    // dumpstack
+    systemDict.put("dumpstack", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Enumeration enumx = context.operands.elements();
+        System.out.println("-------------Stack--------------");
+        while (enumx.hasMoreElements()) {
+          System.out.println(enumx.nextElement());
+        }
+        System.out.println("--------------------------------");
+      }
+    });
+
+    // for
+    systemDict.put("for", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+
+        data = context.popOperands(4);
+        if (! (data[3] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[0] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[2] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[3];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        int i0, i1, i2;
+        i0 = ( (Number) data[0]).intValue();
+        i1 = ( (Number) data[1]).intValue();
+        i2 = ( (Number) data[2]).intValue();
+
+        if (i1 > 0) {
+          for (int i = i0; i <= i2; i += i1) {
+            context.operands.push(new Integer(i));
+            context.engine.process(patoken);
+          }
+        }
+        else {
+          for (int i = i0; i >= i2; i -= i1) {
+            context.operands.push(new Integer(i));
+            context.engine.process(patoken);
+          }
+        }
+      }
+    });
+
+    // repeat
+    systemDict.put("repeat", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(2);
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[0] instanceof Number)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[1];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        int n = ( (Number) data[0]).intValue();
+        for (int i = 0; i < n; i++) {
+          context.engine.process(patoken);
+        }
+      }
+    });
+
+    // true
+    systemDict.put("true", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.operands.push(new Boolean(true));
+      }
+    });
+
+    // false
+    systemDict.put("false", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.operands.push(new Boolean(false));
+      }
+    });
+
+    // lt
+    systemDict.put("lt", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Number) && ! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof Number) {
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          double d0, d1;
+          d0 = ( (Number) data[0]).doubleValue();
+          d1 = ( (Number) data[1]).doubleValue();
+          if (d0 < d1) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+        else {
+          if (! (data[1] instanceof String)) {
+            throw new PainterException("wrong arguments");
+          }
+          String s0, s1;
+          s0 = (String) data[0];
+          s1 = (String) data[1];
+          if (s0.compareTo(s1) < 0) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+      }
+    });
+
+    // gt
+    systemDict.put("gt", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Number) && ! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof Number) {
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          double d0, d1;
+          d0 = ( (Number) data[0]).doubleValue();
+          d1 = ( (Number) data[1]).doubleValue();
+          if (d0 > d1) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+        else {
+          if (! (data[1] instanceof String)) {
+            throw new PainterException("wrong arguments");
+          }
+          String s0, s1;
+          s0 = (String) data[0];
+          s1 = (String) data[1];
+          if (s0.compareTo(s1) > 0) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+      }
+    });
+
+    // ne
+    systemDict.put("ne", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Number) && ! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof Number) {
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          double d0, d1;
+          d0 = ( (Number) data[0]).doubleValue();
+          d1 = ( (Number) data[1]).doubleValue();
+          if (d0 != d1) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+        else {
+          if (! (data[1] instanceof String)) {
+            throw new PainterException("wrong arguments");
+          }
+          String s0, s1;
+          s0 = (String) data[0];
+          s1 = (String) data[1];
+          if (s0.equals(s1)) {
+            context.operands.push(new Boolean(false));
+          }
+          else {
+            context.operands.push(new Boolean(true));
+          }
+        }
+      }
+    });
+
+    // eq
+    systemDict.put("eq", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Number) && ! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof Number) {
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          double d0, d1;
+          d0 = ( (Number) data[0]).doubleValue();
+          d1 = ( (Number) data[1]).doubleValue();
+          if (d0 == d1) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+        else {
+          if (! (data[1] instanceof String)) {
+            throw new PainterException("wrong arguments");
+          }
+          String s0, s1;
+          s0 = (String) data[0];
+          s1 = (String) data[1];
+          if (s0.compareTo(s1) == 0) {
+            context.operands.push(new Boolean(true));
+          }
+          else {
+            context.operands.push(new Boolean(false));
+          }
+        }
+      }
+    });
+
+    // if
+    systemDict.put("if", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(2);
+        if (! (data[0] instanceof Boolean)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[1];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        if ( ( (Boolean) data[0]).booleanValue()) {
+          context.engine.process(patoken);
+        }
+      }
+    });
+
+    // ifelse
+    systemDict.put("ifelse", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken1, patoken2;
+        data = context.popOperands(3);
+        if (! (data[0] instanceof Boolean)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[2] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken1 = (PAToken) data[1];
+        patoken2 = (PAToken) data[2];
+        if (! (patoken1.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (patoken2.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        if ( ( (Boolean) data[0]).booleanValue()) {
+          context.engine.process(patoken1);
+        }
+        else {
+          context.engine.process(patoken2);
+        }
+      }
+    });
+
+    // dict
+    systemDict.put("dict", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new HashMap());
+      }
+    });
+
+    // userdict
+    systemDict.put("userdict", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new HashMap());
+      }
+    });
+    // put
+    systemDict.put("put", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(3);
+        if (! (data[0] instanceof HashMap)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[1];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        ( (HashMap) data[0]).put(patoken.value, data[2]);
+      }
+    });
+
+    // get
+    systemDict.put("get", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(2);
+        if (! (data[0] instanceof HashMap) && ! (data[0] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof HashMap) {
+          if (! (data[1] instanceof PAToken)) {
+            throw new PainterException("wrong arguments");
+          }
+          patoken = (PAToken) data[1];
+          if (! (patoken.type == PAToken.KEY)) {
+            throw new PainterException("wrong arguments");
+          }
+          context.operands.push( ( (HashMap) data[0]).get(patoken.value));
+        }
+        else if (data[0] instanceof ArrayList) {
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          context.operands.push( ( (ArrayList) data[0]).get( ( (Number) data[1]).
+              intValue()));
+        }
+      }
+    });
+
+    // load
+    systemDict.put("load", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.operands.push(context.findIdentifier(patoken.value));
+      }
+    });
+
+    // length
+    systemDict.put("length", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        int size = 0;
+        data = context.popOperands(1);
+        if (data[0] instanceof PAToken) {
+          patoken = (PAToken) data[0];
+          if (! (patoken.type == PAToken.KEY)) {
+            throw new PainterException("wrong arguments");
+          }
+          size = ( (String) patoken.value).length();
+        }
+        else if (data[0] instanceof HashMap) {
+          size = ( (HashMap) data[0]).size();
+        }
+        else if (data[0] instanceof ArrayList) {
+          size = ( (ArrayList) data[0]).size();
+        }
+        else if (data[0] instanceof String) {
+          size = ( (String) data[0]).length();
+        }
+        else {
+          throw new PainterException("wrong arguments");
+        }
+
+        context.operands.push(new Integer(size));
+      }
+    });
+
+    // begin
+    systemDict.put("begin", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(1);
+        if (! (data[0] instanceof HashMap)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.dictionaries.push(data[0]);
+      }
+    });
+
+    // end
+    systemDict.put("end", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        try {
+          context.dictionaries.pop();
+        }
+        catch (EmptyStackException e) {
+          throw new PainterException("Dictionary stack is empty");
+        }
+      }
+    });
+
+    // undef
+    systemDict.put("undef", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+        data = context.popOperands(2);
+        if (! (data[0] instanceof HashMap)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[1];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        // we don't do an actual undef because we don't care
+      }
+    });
+
+    // known
+    systemDict.put("known", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[], foundObject;
+        PAToken patoken;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        foundObject = context.findIdentifier(patoken.value);
+        if (foundObject != null) {
+          context.operands.push(new Boolean(true));
+        }
+        else {
+          context.operands.push(new Boolean(false));
+        }
+      }
+    });
+
+    // where
+    systemDict.put("where", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[], foundObject;
+        PAToken patoken;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.KEY)) {
+          throw new PainterException("wrong arguments");
+        }
+        foundObject = context.findDictionary(patoken.value);
+        if (foundObject != null) {
+          context.operands.push(foundObject);
+          context.operands.push(new Boolean(true));
+        }
+        else {
+          context.operands.push(new Boolean(false));
+        }
+      }
+    });
+
+    // aload
+    systemDict.put("aload", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        ArrayList list;
+        data = context.popOperands(1);
+        if (! (data[0] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        list = (ArrayList) data[0];
+        Iterator iterator = list.iterator();
+        while (iterator.hasNext()) {
+          context.operands.push(iterator.next());
+        }
+        context.operands.push(data[0]);
+      }
+    });
+
+    // forall
+    systemDict.put("forall", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        ArrayList list;
+        PAToken patoken;
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        patoken = (PAToken) data[1];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        list = (ArrayList) data[0];
+        Iterator iterator = list.iterator();
+        while (iterator.hasNext()) {
+          context.operands.push(iterator.next());
+          context.engine.process(patoken);
+        }
+
+      }
+    });
+
+    // currentflat PENDING(uweh):placeholder for now
+    systemDict.put("currentflat", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.operands.push(new Float(1.0f));
+      }
+    });
+
+    // setflat PENDING(uweh):placeholder for now
+    systemDict.put("setflat", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+      }
+    });
+
+    // round
+    systemDict.put("round", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Long(Math.round(data[0])));
+      }
+    });
+
+    // abs
+    systemDict.put("abs", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        context.operands.push(new Double(Math.abs(data[0])));
+      }
+    });
+
+    // transform
+    systemDict.put("transform", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        if (context.peekOperand() instanceof Number) {
+          double data[];
+          double[] transformedData = new double[2];
+          data = context.popNumberOperands(2);
+          AffineTransform at = context.pencil.graphics.getTransform();
+          at.transform(data, 0, transformedData, 0, 1);
+          context.operands.push(new Double(transformedData[0]));
+          context.operands.push(new Double(transformedData[1]));
+        }
+        else {
+          Object data[];
+
+          data = context.popOperands(3);
+          if (! (data[0] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[2] instanceof ArrayList)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          ArrayList array = (ArrayList) data[2];
+
+          double[] entries = new double[6];
+
+          if (! (array.size() == 6)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          for (int i = 0; i < 6; i++) {
+            entries[i] = ( (Number) array.get(i)).doubleValue();
+          }
+
+          AffineTransform at = new AffineTransform(entries);
+
+          double numberdata[] = new double[2];
+          numberdata[0] = ( (Number) data[0]).doubleValue();
+          numberdata[1] = ( (Number) data[0]).doubleValue();
+
+          double[] transformedData = new double[2];
+
+          at.transform(numberdata, 0, transformedData, 0, 1);
+          context.operands.push(new Double(transformedData[0]));
+          context.operands.push(new Double(transformedData[1]));
+        }
+      }
+    });
+
+    // itransform
+    systemDict.put("itransform", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        if (context.peekOperand() instanceof Number) {
+          double data[];
+          double[] transformedData = new double[2];
+          data = context.popNumberOperands(2);
+          AffineTransform at = context.pencil.graphics.getTransform();
+          try {
+            at.inverseTransform(data, 0, transformedData, 0, 1);
+          }
+          catch (NoninvertibleTransformException e) {
+            throw new PainterException(e.toString());
+          }
+          context.operands.push(new Double(transformedData[0]));
+          context.operands.push(new Double(transformedData[1]));
+        }
+        else {
+          Object data[];
+
+          data = context.popOperands(3);
+          if (! (data[0] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[1] instanceof Number)) {
+            throw new PainterException("wrong arguments");
+          }
+          if (! (data[2] instanceof ArrayList)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          ArrayList array = (ArrayList) data[2];
+
+          double[] entries = new double[6];
+
+          if (! (array.size() == 6)) {
+            throw new PainterException("wrong arguments");
+          }
+
+          for (int i = 0; i < 6; i++) {
+            entries[i] = ( (Number) array.get(i)).doubleValue();
+          }
+
+          AffineTransform at = new AffineTransform(entries);
+
+          double numberdata[] = new double[2];
+          numberdata[0] = ( (Number) data[0]).doubleValue();
+          numberdata[1] = ( (Number) data[0]).doubleValue();
+
+          double[] transformedData = new double[2];
+
+          try {
+            at.inverseTransform(numberdata, 0, transformedData, 0, 1);
+          }
+          catch (NoninvertibleTransformException e) {
+            throw new PainterException(e.toString());
+          }
+          context.operands.push(new Double(transformedData[0]));
+          context.operands.push(new Double(transformedData[1]));
+        }
+      }
+    });
+
+    // currentpoint
+    // PENDING(uweh): what about CTM, same thing when you construct path
+    // this is different than ps, might not work in a few instances
+    systemDict.put("currentpoint", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Point2D currentPoint = context.pencil.state.path.getCurrentPoint();
+        context.operands.push(new Double(currentPoint.getX()));
+        context.operands.push(new Double(currentPoint.getY()));
+      }
+    });
+
+    // clippath
+    systemDict.put("clippath", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        context.pencil.clippath();
+      }
+    });
+
+    // matrix
+    systemDict.put("matrix", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        ArrayList identityMatrix = new ArrayList(6);
+
+        identityMatrix.add(new Double(1.0d));
+        identityMatrix.add(new Double(0.0d));
+        identityMatrix.add(new Double(0.0d));
+        identityMatrix.add(new Double(1.0d));
+        identityMatrix.add(new Double(0.0d));
+        identityMatrix.add(new Double(0.0d));
+        context.operands.push(identityMatrix);
+      }
+    });
+
+    // concatmatrix
+    systemDict.put("concatmatrix", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        data = context.popOperands(3);
+        if (! (data[0] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[2] instanceof ArrayList)) {
+          throw new PainterException("wrong arguments");
+        }
+        ArrayList arrayOne, arrayTwo, arrayThree;
+        AffineTransform atOne, atTwo;
+
+        arrayOne = (ArrayList) data[0];
+        arrayTwo = (ArrayList) data[1];
+        arrayThree = (ArrayList) data[2];
+
+        double[] entries = new double[6];
+
+        if (! (arrayOne.size() == 6)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (arrayTwo.size() == 6)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (arrayThree.size() == 6)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        for (int i = 0; i < 6; i++) {
+          entries[i] = ( (Number) arrayOne.get(i)).doubleValue();
+        }
+        atOne = new AffineTransform(entries);
+        for (int i = 0; i < 6; i++) {
+          entries[i] = ( (Number) arrayTwo.get(i)).doubleValue();
+        }
+        atTwo = new AffineTransform(entries);
+
+        atOne.concatenate(atTwo);
+
+        atOne.getMatrix(entries);
+        for (int i = 0; i < 6; i++) {
+          arrayThree.set(i, new Double(entries[i]));
+        }
+        context.operands.push(arrayThree);
+      }
+    });
+
+    // pathbbox
+    systemDict.put("pathbbox", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Rectangle2D pathBounds = context.pencil.state.path.getBounds2D();
+
+        context.operands.push(new Double(pathBounds.getMinX()));
+        context.operands.push(new Double(pathBounds.getMinY()));
+        context.operands.push(new Double(pathBounds.getMaxX()));
+        context.operands.push(new Double(pathBounds.getMaxY()));
+      }
+    });
+
+    // truncate
+    systemDict.put("truncate", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+        double truncated;
+
+        data = context.popNumberOperands(1);
+        if (data[0] < 0) {
+          truncated = Math.ceil(data[0]);
+        }
+        else {
+          truncated = Math.floor(data[0]);
+        }
+        context.operands.push(new Double(truncated));
+      }
+    });
+
+    // rand
+    systemDict.put("rand", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        context.operands.push(new Integer(randomNumberGenerator.nextInt(231)));
+      }
+    });
+
+    // srand
+    systemDict.put("srand", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        double data[];
+
+        data = context.popNumberOperands(1);
+        randomNumberGenerator = new Random(Math.round(data[0]));
+      }
+    });
+
+    // cvi
+    systemDict.put("cvi", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(1);
+        if (! (data[0] instanceof Number) && ! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (data[0] instanceof Number) {
+          int d;
+
+          d = ( (Number) data[0]).intValue();
+          context.operands.push(new Integer(d));
+        }
+        else {
+          String s;
+          s = (String) data[0];
+
+          context.operands.push(new Integer(s));
+        }
+      }
+    });
+
+    // usertime
+    systemDict.put("usertime", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        context.operands.push(new Long(System.currentTimeMillis()));
+      }
+    });
+// save
+    systemDict.put("save", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        // context.operands.push(new Long(System.currentTimeMillis()));
+      }
+    });
+// restore
+    systemDict.put("restore", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        //     Object data[];
+
+        //   data = context.popOperands(1);
+
+      }
+    });
+// clear
+    systemDict.put("clear", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        // Object data[];
+
+        // data = context.popOperands(1);
+
+      }
+    });
+// cleardictstack
+    systemDict.put("cleardictstack", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+
+        // Object data[];
+
+        // data = context.popOperands(1);
+
+      }
+    });
+
+    // charpath
+    systemDict.put("charpath", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+
+        data = context.popOperands(2);
+        if (! (data[0] instanceof String)) {
+          throw new PainterException("wrong arguments");
+        }
+        if (! (data[1] instanceof Boolean)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        context.pencil.charpath( (String) data[0],
+                                ( (Boolean) data[1]).booleanValue());
+      }
+    });
+
+    // PENDING(uweh): we only support procedure right now and always push false on the stack
+    // stopped
+    systemDict.put("stopped", new PACommand() {
+      public void execute(PAContext context) throws PainterException {
+        Object data[];
+        PAToken patoken;
+
+        data = context.popOperands(1);
+        if (! (data[0] instanceof PAToken)) {
+          throw new PainterException("wrong arguments");
+        }
+
+        patoken = (PAToken) data[0];
+        if (! (patoken.type == PAToken.PROCEDURE)) {
+          throw new PainterException("wrong arguments");
+        }
+        context.engine.process(patoken);
+        context.operands.push(new Boolean(false));
+      }
+    });
+
+    return systemDict;
+  }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAEngine.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAEngine.java
new file mode 100644
index 0000000..8420bef
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAEngine.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import headless.awt.*;
+import headless.awt.geom.*;
+import headless.awt.color.*;
+import headless.awt.font.*;
+
+
+public class PAEngine extends Object {
+
+    static public final int MODE_STACK = 0;
+    static public final int MODE_PROCEDURE = 1;
+    static public final int MODE_ARRAY = 2;
+
+    protected PAContext context;
+    protected int mode;
+    protected Stack procedure;
+    protected int innerProcedures;
+
+    public PAEngine(PAContext context){
+        super();
+        this.context = context;
+        this.mode = PAEngine.MODE_STACK;
+    }
+
+    public void startProcedure() throws PainterException {
+        this.procedure = new Stack();
+        this.mode = PAEngine.MODE_PROCEDURE;
+        this.innerProcedures = 0;
+    }
+
+    public void endProcedure() throws PainterException {
+        this.context.operands.push(new PAToken(this.procedure, PAToken.PROCEDURE));
+        this.mode = PAEngine.MODE_STACK;
+    }
+
+    public void bindProcedure(PAToken patoken){
+        Stack oldStack = (Stack) patoken.value;
+        Stack newStack = new Stack();
+        int i,n;
+        n = oldStack.size();
+        for(i = 0; i < n; i++){
+            Object token = oldStack.elementAt(i);
+            if((token instanceof PAToken) && ((PAToken) token).type == PAToken.IDENTIFIER){
+                Object foundToken = this.context.findIdentifier(((PAToken) token).value);
+                if(foundToken == null){
+                    newStack.push(token);
+                } else {
+                    newStack.push(foundToken);
+                }
+            } else {
+                newStack.push(token);
+            }
+        }
+        patoken.value = newStack;
+    }
+
+    public void process(Object token) throws PainterException {
+        if(token == null){
+            throw new IllegalStateException("Null token encountered; last unknown identifier was " + this.context.getLastUnknownIdentifier());
+        }
+       // System.out.println("==>"+token.toString());
+        if(token instanceof PAToken && ((PAToken) token).type == PAToken.IMMEDIATE){
+            Object foundValue = this.context.findIdentifier(((PAToken) token).value);
+            this.process(foundValue);
+            return;
+        }
+        if(this.mode == MODE_STACK){
+            if(token instanceof PACommand){
+                ((PACommand) token).execute(this.context);
+            } else if(token instanceof PAToken){
+                PAToken patoken = (PAToken) token;
+
+                switch(patoken.type){
+                case PAToken.IDENTIFIER:
+                    this.process(this.context.findIdentifier(patoken.value));
+                    break;
+                case PAToken.KEY:
+                case PAToken.MARK:
+                case PAToken.START_ARRAY:
+                    this.context.operands.push(token);
+                    break;
+                case PAToken.PROCEDURE:
+                    Enumeration enumx = ((Vector) patoken.value).elements();
+                    while(enumx.hasMoreElements()){
+                        this.process(enumx.nextElement());
+                    }
+                    break;
+                case PAToken.START_PROCEDURE:
+                    this.startProcedure();
+                    break;
+                case PAToken.END_ARRAY:
+                    this.context.collectArray();
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown token encountered" + token);
+                }
+            } else {
+                this.context.operands.push(token);
+            }
+        } else if(this.mode == MODE_PROCEDURE){
+            if(token instanceof PAToken){
+                PAToken patoken = (PAToken) token;
+
+                switch(patoken.type){
+                case PAToken.START_PROCEDURE:
+                    this.innerProcedures++;
+                    this.procedure.push(token);
+                    break;
+                case PAToken.END_PROCEDURE:
+                    if(this.innerProcedures > 0){
+                        this.innerProcedures--;
+                        this.procedure.push(token);
+                    } else {
+                        this.endProcedure();
+                    }
+                    break;
+                default:
+                    this.procedure.push(token);
+                }
+            } else {
+                this.procedure.push(token);
+            }
+        }
+    }
+
+}
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParser.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParser.java
new file mode 100644
index 0000000..2f10272
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParser.java
@@ -0,0 +1,305 @@
+/* Generated By:JavaCC: Do not edit this line. PAParser.java */
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import headless.awt.*;
+import headless.awt.geom.*;
+import headless.awt.color.*;
+import headless.awt.font.*;
+
+import java.io.*;
+import java.net.URL;
+
+public class PAParser extends Object implements PAParserConstants {
+
+  void error_skipto(int kind) throws ParseException {
+ParseException e=generateParseException();
+Token t;
+String dump="";
+do{
+if(getToken(1).kind==kind)break;
+t=getNextToken();
+dump+=t.image;
+}while(t.kind!=kind);
+System.out.println("Ignoriere >"+dump+"<");
+  }
+
+  final public void parse(PAContext context) throws ParseException {
+        Token x = null;
+    try {
+      label_1:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case INTEGER_LITERAL:
+        case FLOATING_POINT_LITERAL:
+        case STRING_LITERAL:
+        case IDENTIFIER:
+        case KEY_IDENTIFIER:
+        case IMMEDIATE_IDENTIFIER:
+        case LBRACE:
+        case RBRACE:
+        case LBRACKET:
+        case RBRACKET:
+          ;
+          break;
+        default:
+          jj_la1[0] = jj_gen;
+          break label_1;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case INTEGER_LITERAL:
+        case FLOATING_POINT_LITERAL:
+        case STRING_LITERAL:
+        case IDENTIFIER:
+        case KEY_IDENTIFIER:
+        case IMMEDIATE_IDENTIFIER:
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case INTEGER_LITERAL:
+            x = jj_consume_token(INTEGER_LITERAL);
+                                try {
+                                        context.engine.process(new Integer(x.image));
+                                } catch(NumberFormatException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          case FLOATING_POINT_LITERAL:
+            x = jj_consume_token(FLOATING_POINT_LITERAL);
+                                try {
+                                        context.engine.process(new Double(x.image));
+                                } catch(NumberFormatException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          case STRING_LITERAL:
+            x = jj_consume_token(STRING_LITERAL);
+                                try {
+                                        context.engine.process(x.image.substring(1, x.image.length() -1));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          case IDENTIFIER:
+            x = jj_consume_token(IDENTIFIER);
+                                try {
+                                        context.engine.process(new PAToken(x.image, PAToken.IDENTIFIER));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          case KEY_IDENTIFIER:
+            x = jj_consume_token(KEY_IDENTIFIER);
+                                try {
+                                        context.engine.process(new PAToken(x.image.substring(1, x.image.length()), PAToken.KEY));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          case IMMEDIATE_IDENTIFIER:
+            x = jj_consume_token(IMMEDIATE_IDENTIFIER);
+                                try {
+                                        context.engine.process(new PAToken(x.image.substring(2, x.image.length()), PAToken.IMMEDIATE));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+            break;
+          default:
+            jj_la1[1] = jj_gen;
+            jj_consume_token(-1);
+            throw new ParseException();
+          }
+          break;
+        case LBRACE:
+          jj_consume_token(LBRACE);
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.START_PROCEDURE));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+          break;
+        case RBRACE:
+          jj_consume_token(RBRACE);
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.END_PROCEDURE));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+          break;
+        case LBRACKET:
+          jj_consume_token(LBRACKET);
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.START_ARRAY));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+          break;
+        case RBRACKET:
+          jj_consume_token(RBRACKET);
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.END_ARRAY));
+                                } catch(PainterException e) {
+                                        {if (true) throw new ParseException(e.toString());}
+                                }
+          break;
+        default:
+          jj_la1[2] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      }
+    } catch (ParseException e) {
+                  //System.out.println("Fehlerhaftes Element in Spalte "+e.currentToken.beginColumn+" in Eingabedatei in Zeile="+e.currentToken.next.beginLine+" in Zeichen Nr. "+e.currentToken.next.beginColumn+". >"+e.currentToken.next.image+"< wurde hier nicht erwartet.");
+                  //System.err.println("Fehler:"+e);
+                  e.printStackTrace();
+                  error_skipto(WHITESPACE);
+    }
+  }
+
+  public PAParserTokenManager token_source;
+  JavaCharStream jj_input_stream;
+  public Token token, jj_nt;
+  private int jj_ntk;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[3];
+  final private int[] jj_la1_0 = {0x79e90,0x1e90,0x79e90,};
+
+  public PAParser(java.io.InputStream stream) {
+    jj_input_stream = new JavaCharStream(stream, 1, 1);
+    token_source = new PAParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  public void ReInit(java.io.InputStream stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  public PAParser(java.io.Reader stream) {
+    jj_input_stream = new JavaCharStream(stream, 1, 1);
+    token_source = new PAParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  public void ReInit(java.io.Reader stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  public PAParser(PAParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  public void ReInit(PAParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 3; i++) jj_la1[i] = -1;
+  }
+
+  final private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  final private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.Vector jj_expentries = new java.util.Vector();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+
+  final public ParseException generateParseException() {
+    jj_expentries.removeAllElements();
+    boolean[] la1tokens = new boolean[19];
+    for (int i = 0; i < 19; i++) {
+      la1tokens[i] = false;
+    }
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 3; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 19; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.addElement(jj_expentry);
+      }
+    }
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = (int[])jj_expentries.elementAt(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  final public void enable_tracing() {
+  }
+
+  final public void disable_tracing() {
+  }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserConstants.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserConstants.java
new file mode 100644
index 0000000..df02229
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserConstants.java
@@ -0,0 +1,49 @@
+/* Generated By:JavaCC: Do not edit this line. PAParserConstants.java */
+package com.lowagie.text.pdf.codec.postscript;
+
+public interface PAParserConstants {
+
+  int EOF = 0;
+  int WHITESPACE = 1;
+  int INTEGER_LITERAL = 4;
+  int DECIMAL_LITERAL = 5;
+  int HEX_LITERAL = 6;
+  int FLOATING_POINT_LITERAL = 7;
+  int EXPONENT = 8;
+  int STRING_LITERAL = 9;
+  int IDENTIFIER = 10;
+  int KEY_IDENTIFIER = 11;
+  int IMMEDIATE_IDENTIFIER = 12;
+  int LETTER = 13;
+  int DIGIT = 14;
+  int LBRACE = 15;
+  int RBRACE = 16;
+  int LBRACKET = 17;
+  int RBRACKET = 18;
+
+  int DEFAULT = 0;
+
+  String[] tokenImage = {
+    "<EOF>",
+    "<WHITESPACE>",
+    "<token of kind 2>",
+    "<token of kind 3>",
+    "<INTEGER_LITERAL>",
+    "<DECIMAL_LITERAL>",
+    "<HEX_LITERAL>",
+    "<FLOATING_POINT_LITERAL>",
+    "<EXPONENT>",
+    "<STRING_LITERAL>",
+    "<IDENTIFIER>",
+    "<KEY_IDENTIFIER>",
+    "<IMMEDIATE_IDENTIFIER>",
+    "<LETTER>",
+    "<DIGIT>",
+    "\"{\"",
+    "\"}\"",
+    "\"[\"",
+    "\"]\"",
+  };
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserTokenManager.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserTokenManager.java
new file mode 100644
index 0000000..6dae4f0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAParserTokenManager.java
@@ -0,0 +1,803 @@
+/* Generated By:JavaCC: Do not edit this line. PAParserTokenManager.java */
+package com.lowagie.text.pdf.codec.postscript;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import headless.awt.*;
+import headless.awt.geom.*;
+import headless.awt.color.*;
+import headless.awt.font.*;
+import java.io.*;
+import java.net.URL;
+
+public class PAParserTokenManager implements PAParserConstants
+{
+  public  java.io.PrintStream debugStream = System.out;
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private final int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private final int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+private final int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 91:
+         return jjStopAtPos(0, 17);
+      case 93:
+         return jjStopAtPos(0, 18);
+      case 123:
+         return jjStopAtPos(0, 15);
+      case 125:
+         return jjStopAtPos(0, 16);
+      default :
+         return jjMoveNfa_0(0, 0);
+   }
+}
+private final void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private final void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private final void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+private final void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+private final void jjCheckNAddStates(int start)
+{
+   jjCheckNAdd(jjnextStates[start]);
+   jjCheckNAdd(jjnextStates[start + 1]);
+}
+static final long[] jjbitVec0 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec2 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec3 = {
+   0x1ff00000fffffffeL, 0xffffffffffffc000L, 0xffffffffL, 0x600000000000000L
+};
+static final long[] jjbitVec4 = {
+   0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL
+};
+static final long[] jjbitVec5 = {
+   0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec6 = {
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffL, 0x0L
+};
+static final long[] jjbitVec7 = {
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L, 0x0L
+};
+static final long[] jjbitVec8 = {
+   0x3fffffffffffL, 0x0L, 0x0L, 0x0L
+};
+private final int jjMoveNfa_0(int startState, int curPos)
+{
+   int[] nextStates;
+   int startsAt = 0;
+   jjnewStateCnt = 70;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int j, kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x3ff000000000000L & l) != 0L)
+                  {
+                     if (kind > 4)
+                        kind = 4;
+                     jjCheckNAddStates(0, 8);
+                  }
+                  else if ((0x100003600L & l) != 0L)
+                  {
+                     if (kind > 1)
+                        kind = 1;
+                  }
+                  else if (curChar == 45)
+                     jjCheckNAddStates(9, 14);
+                  else if (curChar == 37)
+                     jjCheckNAddStates(15, 18);
+                  else if (curChar == 47)
+                     jjstateSet[jjnewStateCnt++] = 25;
+                  else if (curChar == 36)
+                  {
+                     if (kind > 10)
+                        kind = 10;
+                     jjCheckNAdd(21);
+                  }
+                  else if (curChar == 40)
+                     jjCheckNAddStates(19, 21);
+                  else if (curChar == 46)
+                     jjCheckNAdd(6);
+                  if (curChar == 47)
+                     jjstateSet[jjnewStateCnt++] = 23;
+                  else if (curChar == 48)
+                     jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 1:
+                  if (curChar == 48)
+                     jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 3:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 4)
+                     kind = 4;
+                  jjCheckNAddTwoStates(3, 4);
+                  break;
+               case 5:
+                  if (curChar == 46)
+                     jjCheckNAdd(6);
+                  break;
+               case 6:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(22, 24);
+                  break;
+               case 8:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(9);
+                  break;
+               case 9:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(9, 10);
+                  break;
+               case 11:
+                  if (curChar == 40)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 12:
+                  if ((0xfffffdffffffdbffL & l) != 0L)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 14:
+                  if ((0x28000000400L & l) != 0L)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 15:
+                  if (curChar == 41 && kind > 9)
+                     kind = 9;
+                  break;
+               case 16:
+                  if ((0xff000000000000L & l) != 0L)
+                     jjCheckNAddStates(25, 28);
+                  break;
+               case 17:
+                  if ((0xff000000000000L & l) != 0L)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 18:
+                  if ((0xf000000000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 19;
+                  break;
+               case 19:
+                  if ((0xff000000000000L & l) != 0L)
+                     jjCheckNAdd(17);
+                  break;
+               case 20:
+                  if (curChar != 36)
+                     break;
+                  if (kind > 10)
+                     kind = 10;
+                  jjCheckNAdd(21);
+                  break;
+               case 21:
+                  if ((0x3ff601000000000L & l) == 0L)
+                     break;
+                  if (kind > 10)
+                     kind = 10;
+                  jjCheckNAdd(21);
+                  break;
+               case 22:
+                  if (curChar == 47)
+                     jjstateSet[jjnewStateCnt++] = 23;
+                  break;
+               case 23:
+                  if (curChar != 36)
+                     break;
+                  if (kind > 11)
+                     kind = 11;
+                  jjCheckNAdd(24);
+                  break;
+               case 24:
+                  if ((0x3ff601000000000L & l) == 0L)
+                     break;
+                  if (kind > 11)
+                     kind = 11;
+                  jjCheckNAdd(24);
+                  break;
+               case 25:
+                  if (curChar == 47)
+                     jjstateSet[jjnewStateCnt++] = 26;
+                  break;
+               case 26:
+                  if (curChar != 36)
+                     break;
+                  if (kind > 12)
+                     kind = 12;
+                  jjCheckNAdd(27);
+                  break;
+               case 27:
+                  if ((0x3ff601000000000L & l) == 0L)
+                     break;
+                  if (kind > 12)
+                     kind = 12;
+                  jjCheckNAdd(27);
+                  break;
+               case 28:
+                  if (curChar == 47)
+                     jjstateSet[jjnewStateCnt++] = 25;
+                  break;
+               case 29:
+                  if (curChar == 37)
+                     jjCheckNAddStates(15, 18);
+                  break;
+               case 30:
+                  if ((0xfffffffffffffbffL & l) != 0L)
+                     jjCheckNAddTwoStates(30, 31);
+                  break;
+               case 31:
+                  if (curChar == 10 && kind > 2)
+                     kind = 2;
+                  break;
+               case 32:
+                  if ((0xffffffffffffdfffL & l) != 0L)
+                     jjCheckNAddTwoStates(32, 33);
+                  break;
+               case 33:
+                  if (curChar == 13 && kind > 3)
+                     kind = 3;
+                  break;
+               case 34:
+                  if (curChar == 45)
+                     jjCheckNAddStates(9, 14);
+                  break;
+               case 35:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 4)
+                     kind = 4;
+                  jjCheckNAddTwoStates(35, 4);
+                  break;
+               case 36:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(36, 37);
+                  break;
+               case 37:
+                  if (curChar != 46)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(29, 31);
+                  break;
+               case 38:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(29, 31);
+                  break;
+               case 40:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(41);
+                  break;
+               case 41:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(41, 10);
+                  break;
+               case 42:
+                  if (curChar == 46)
+                     jjCheckNAdd(43);
+                  break;
+               case 43:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(32, 34);
+                  break;
+               case 45:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(46);
+                  break;
+               case 46:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(46, 10);
+                  break;
+               case 47:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(47, 48);
+                  break;
+               case 49:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(50);
+                  break;
+               case 50:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(50, 10);
+                  break;
+               case 51:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddStates(35, 37);
+                  break;
+               case 53:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(54);
+                  break;
+               case 54:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(54, 10);
+                  break;
+               case 55:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 4)
+                     kind = 4;
+                  jjCheckNAddStates(0, 8);
+                  break;
+               case 56:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(56, 57);
+                  break;
+               case 57:
+                  if (curChar != 46)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(38, 40);
+                  break;
+               case 58:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(38, 40);
+                  break;
+               case 60:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(61);
+                  break;
+               case 61:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(61, 10);
+                  break;
+               case 62:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(62, 63);
+                  break;
+               case 64:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(65);
+                  break;
+               case 65:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddTwoStates(65, 10);
+                  break;
+               case 66:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddStates(41, 43);
+                  break;
+               case 68:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(69);
+                  break;
+               case 69:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(69, 10);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 21:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 10)
+                     kind = 10;
+                  jjCheckNAdd(21);
+                  break;
+               case 2:
+                  if ((0x100000001000000L & l) != 0L)
+                     jjCheckNAdd(3);
+                  break;
+               case 3:
+                  if ((0x7e0000007eL & l) == 0L)
+                     break;
+                  if (kind > 4)
+                     kind = 4;
+                  jjCheckNAddTwoStates(3, 4);
+                  break;
+               case 4:
+                  if ((0x100000001000L & l) != 0L && kind > 4)
+                     kind = 4;
+                  break;
+               case 7:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(44, 45);
+                  break;
+               case 10:
+                  if ((0x5000000050L & l) != 0L && kind > 7)
+                     kind = 7;
+                  break;
+               case 12:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 13:
+                  if (curChar == 92)
+                     jjAddStates(46, 48);
+                  break;
+               case 14:
+                  if ((0x14404410000000L & l) != 0L)
+                     jjCheckNAddStates(19, 21);
+                  break;
+               case 23:
+               case 24:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 11)
+                     kind = 11;
+                  jjCheckNAdd(24);
+                  break;
+               case 26:
+               case 27:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 12)
+                     kind = 12;
+                  jjCheckNAdd(27);
+                  break;
+               case 30:
+                  jjAddStates(49, 50);
+                  break;
+               case 32:
+                  jjAddStates(51, 52);
+                  break;
+               case 39:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(53, 54);
+                  break;
+               case 44:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(55, 56);
+                  break;
+               case 48:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(57, 58);
+                  break;
+               case 52:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(59, 60);
+                  break;
+               case 59:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(61, 62);
+                  break;
+               case 63:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(63, 64);
+                  break;
+               case 67:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(65, 66);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 21:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 10)
+                     kind = 10;
+                  jjCheckNAdd(21);
+                  break;
+               case 12:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjAddStates(19, 21);
+                  break;
+               case 23:
+               case 24:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 11)
+                     kind = 11;
+                  jjCheckNAdd(24);
+                  break;
+               case 26:
+               case 27:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 12)
+                     kind = 12;
+                  jjCheckNAdd(27);
+                  break;
+               case 30:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjAddStates(49, 50);
+                  break;
+               case 32:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjAddStates(51, 52);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 70 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   35, 4, 56, 57, 62, 63, 66, 67, 10, 35, 1, 36, 42, 47, 51, 30,
+   31, 32, 33, 12, 13, 15, 6, 7, 10, 12, 13, 17, 15, 38, 39, 10,
+   43, 44, 10, 51, 52, 10, 58, 59, 10, 66, 67, 10, 8, 9, 14, 16,
+   18, 30, 31, 32, 33, 40, 41, 45, 46, 49, 50, 53, 54, 60, 61, 64,
+   65, 68, 69,
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec2[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec0[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec4[i2] & l2) != 0L);
+      case 48:
+         return ((jjbitVec5[i2] & l2) != 0L);
+      case 49:
+         return ((jjbitVec6[i2] & l2) != 0L);
+      case 51:
+         return ((jjbitVec7[i2] & l2) != 0L);
+      case 61:
+         return ((jjbitVec8[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec3[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, null, null,
+null, null, "\173", "\175", "\133", "\135", };
+public static final String[] lexStateNames = {
+   "DEFAULT",
+};
+static final long[] jjtoToken = {
+   0x79e91L,
+};
+static final long[] jjtoSkip = {
+   0xeL,
+};
+private JavaCharStream input_stream;
+private final int[] jjrounds = new int[70];
+private final int[] jjstateSet = new int[140];
+protected char curChar;
+public PAParserTokenManager(JavaCharStream stream)
+{
+   if (JavaCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+public PAParserTokenManager(JavaCharStream stream, int lexState)
+{
+   this(stream);
+   SwitchTo(lexState);
+}
+public void ReInit(JavaCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private final void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 70; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+public void ReInit(JavaCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+private final Token jjFillToken()
+{
+   Token t = Token.newToken(jjmatchedKind);
+   t.kind = jjmatchedKind;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   t.image = (im == null) ? input_stream.GetImage() : im;
+   t.beginLine = input_stream.getBeginLine();
+   t.beginColumn = input_stream.getBeginColumn();
+   t.endLine = input_stream.getEndLine();
+   t.endColumn = input_stream.getEndColumn();
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+public final Token getNextToken()
+{
+  int kind;
+  Token specialToken = null;
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   jjmatchedKind = 0x7fffffff;
+   jjmatchedPos = 0;
+   curPos = jjMoveStringLiteralDfa0_0();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAPencil.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAPencil.java
new file mode 100644
index 0000000..65f9fba
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAPencil.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.util.*;
+import headless.awt.*;
+import headless.awt.font.*;
+import headless.awt.geom.*;
+
+
+public class PAPencil extends Object {
+
+    static protected class State extends Object implements Cloneable {
+        public Stroke stroke;
+        public Paint paint;
+        public AffineTransform at;
+        public Shape clipShape;
+        public Font font;
+        public Composite composite;
+        public GeneralPath path;
+
+        public State(){
+            this(null);
+        }
+
+        public State(Graphics2D g){
+            if(g == null){
+                this.stroke = new BasicStroke();
+                this.paint = Color.black;
+                this.at = new AffineTransform();
+                this.font = new Font("SansSerif", Font.PLAIN, 12);
+                this.composite = AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1.0f);
+                this.clipShape = null;
+            } else {
+                this.recordState(g);
+            }
+            this.path = new GeneralPath();
+        }
+
+        public void recordState(Graphics2D g){
+            this.stroke = g.getStroke();
+            this.paint = g.getPaint();
+            this.at = g.getTransform();
+            this.font = g.getFont();
+            this.composite = g.getComposite();
+            this.clipShape = g.getClip();
+        }
+
+        public void stampState(Graphics2D g, Dimension size){
+            g.setTransform(new AffineTransform());
+            g.setClip(new Rectangle(0, 0, size.width, size.height));
+            g.setStroke(this.stroke);
+            g.setPaint(this.paint);
+            g.setTransform(this.at);
+            g.setFont(this.font);
+            g.setComposite(this.composite);
+            if(this.clipShape != null){
+                g.clip(this.clipShape);
+            }
+        }
+
+        public Object clone(){
+            try {
+                State n = (State)super.clone();
+
+                n.at = (AffineTransform) this.at.clone();
+                n.path = new GeneralPath();
+                n.path.append(this.path, false);
+                return n;
+            } catch(CloneNotSupportedException e){
+                throw new InternalError();
+            }
+        }
+
+    }
+
+    //
+    // Class Variables
+    //
+
+    //
+    // Instance Variables
+    //
+
+    /**
+     * The canvas size.
+     */
+    protected Dimension size;
+
+    /**
+     * The current graphics state.
+     */
+    protected State state;
+
+    /**
+     * The stack of graphic states.
+     */
+    protected Stack gStack;
+
+    /**
+     * The font hashtable with postscript names as keys
+     */
+    protected HashMap fonts;
+
+    /**
+     * The current graphics device
+     */
+    public Graphics2D graphics;
+
+    //
+    // Constructors
+    //
+
+    public PAPencil(Component component){
+	this.graphics = (Graphics2D) component.getGraphics();
+	this.size = component.getSize();
+	this.initgraphics();
+    }
+
+    public PAPencil(Graphics graphics, Dimension size){
+	this.graphics = (Graphics2D) graphics;
+	this.size = size;
+	this.initgraphics();
+    }
+
+    //
+    // Graphics state management
+    //
+
+    public void gsave(){
+        this.state.recordState(this.graphics);
+	State next = (State) this.state.clone();
+
+	this.gStack.push(this.state);
+	this.state = next;
+    }
+
+    public void grestore(){
+       	if(this.gStack.empty()){
+	    this.initgraphics();
+	} else {
+	    this.state = (State) this.gStack.pop();
+            this.state.stampState(this.graphics, this.size);
+	}
+    }
+
+    public void grestoreall(){
+	this.initgraphics();
+    }
+
+    public void initgraphics(){
+       // AffineTransform at = new AffineTransform();
+
+        // turn anti-aliasing and high-quality rendering on
+	this.graphics.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
+	this.graphics.setRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
+
+        // initialize to a postscript coordinate system
+//        at.translate(0, this.size.getHeight());
+//        at.scale(1, -1);
+//        this.graphics.setTransform(at);
+        this.graphics.translate(0, this.size.getHeight());
+        this.graphics.scale(1, -1);
+
+        // state, stack and page
+	this.state = new State(this.graphics);
+	this.gStack = new Stack();
+	this.erasepage();
+    }
+
+    //
+    // Path definition
+    //
+
+    public void newpath(){
+	this.state.path.reset();
+    }
+
+    public void moveto(double x, double y){
+	this.state.path.moveTo((float) x, (float) y);
+    }
+
+    public void moveto(Point2D p) {
+	this.moveto(p.getX(), p.getY());
+    }
+
+    public void rmoveto(double dx, double dy) throws PainterException {
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+	this.state.path.moveTo((float) (currentPoint.getX() + dx) , (float) (currentPoint.getY() + dy));
+    }
+
+    public void lineto(double x, double y) throws PainterException {
+	Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+	this.state.path.lineTo((float) x, (float) y);
+    }
+
+    public void lineto(Point2D p) throws PainterException {
+	this.lineto(p.getX(), p.getY());
+    }
+
+    public void rlineto(double dx, double dy) throws PainterException {
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+        this.state.path.lineTo((float) (currentPoint.getX() + dx) , (float) (currentPoint.getY() + dy));
+    }
+
+    public void arc(double cx, double cy, double r, double ang1, double ang2){
+        Arc2D.Float arc = new Arc2D.Float((float) cx, (float) cy, (float) r, (float) r,
+                                          (float) ang1, (float) (ang2 - ang1), Arc2D.OPEN);
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+            this.state.path.append(arc, false);
+        } else {
+            this.state.path.append(arc, true);
+        }
+    }
+
+    public void arcn(double cx, double cy, double r,
+    		      double ang1, double ang2) {
+	Arc2D.Float arc = new Arc2D.Float((float) cx, (float) cy, (float) r, (float) r,
+                                          (float) ang1, (float) (ang1 - ang2), Arc2D.OPEN);
+       Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+            this.state.path.append(arc, false);
+        } else {
+            this.state.path.append(arc, true);
+        }
+    }
+
+    public void curveto(double x1, double y1, double x2, double y2,
+		         double x3, double y3) throws PainterException {
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+        this.state.path.curveTo((float) x1, (float) y1, (float) x2, (float) y2,
+                                  (float) x3, (float) y3);
+    }
+
+    public void rcurveto(double dx1, double dy1, double dx2, double dy2,
+			  double dx3, double dy3) throws PainterException {
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+	double x0 = currentPoint.getX();
+	double y0 = currentPoint.getY();
+	this.curveto(x0 + dx1, y0 + dy1, x0 + dx2, y0 + dy2, x0 + dx3,y0 + dy3);
+    }
+
+    public void closepath(){
+        this.state.path.closePath();
+    }
+
+    // PENDING(uweh): just a placeholder for now
+    public void clippath(){
+        this.rectpath(0.0d, 0.0d, 800.0d, 800.0d);
+    }
+
+    public void erasepage(){
+	this.graphics.clearRect(0, 0, 800, 800);
+    }
+
+    public void charpath(String aString, boolean adjustForStroking){
+	GlyphVector glyphVector = this.state.font.createGlyphVector(this.graphics.getFontRenderContext(), aString);
+
+        Shape glyphShape = glyphVector.getOutline();
+        this.state.path.append(glyphShape, false);
+    }
+
+    public void showpage(){
+
+    }
+
+    public void show(String string) throws PainterException {
+        Point2D currentPoint = this.state.path.getCurrentPoint();
+        AffineTransform currentTransform = this.graphics.getTransform();
+        Point2D tranformedPoint = currentTransform.transform(currentPoint, null);
+
+
+	if(currentPoint == null){
+	    throw new PainterException("no current point");
+	}
+        this.graphics.setTransform(new AffineTransform());
+        this.graphics.drawString(string, (float) tranformedPoint.getX(), (float) tranformedPoint.getY());
+        this.graphics.setTransform(currentTransform);
+    }
+
+    public void fill(){
+        this.graphics.fill(this.state.path);
+        this.newpath();
+    }
+
+    public void eofill(){
+        this.state.path.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+        this.graphics.fill(this.state.path);
+        this.state.path.setWindingRule(GeneralPath.WIND_NON_ZERO);
+        this.newpath();
+    }
+
+    public void stroke(){
+        this.graphics.draw(this.state.path);
+        this.newpath();
+    }
+
+    public void rectfill(double x, double y, double width, double height){
+	this.gsave();
+	this.rectpath(x, y, width, height);
+	this.fill();
+	this.grestore();
+    }
+
+    public void rectfill(Rectangle2D rect){
+        this.rectfill(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    public void rectstroke(double x, double y, double width, double height){
+	this.gsave();
+	this.rectpath(x, y, width, height);
+	this.stroke();
+	this.grestore();
+    }
+
+    public void rectstroke(Rectangle2D rect){
+	this.rectstroke(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    public void rectpath(double x, double y, double width, double height){
+	this.newpath();
+	this.moveto(x, y);
+	try {
+	    this.rlineto(width, 0);
+	    this.rlineto(0, height);
+	    this.rlineto(-width, 0);
+	} catch(PainterException e){
+	}
+	this.closepath();
+    }
+
+    // convenience
+
+    // this guy tries to find an appropiate font
+    // if he fails returns whatever font he wants
+    public Font findFont(String fontname){
+        Font result;
+        StringBuffer buffer = new StringBuffer(fontname);
+        int i, n;
+        n = buffer.length();
+
+        for(i = 0; i < n; i++){
+            if(buffer.charAt(i) == '-'){
+                buffer.setCharAt(i,' ');
+            }
+        }
+
+        fontname = buffer.toString();
+
+        if(this.fonts == null){
+            // construct the fonts dictionary
+            GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
+            Font[] fontArray = genv.getAllFonts();
+            this.fonts = new HashMap();
+            for(i = 0; i < fontArray.length; i++){
+                String postscriptName = fontArray[i].getPSName();
+                this.fonts.put(postscriptName, fontArray[i]);
+            }
+        }
+        result = (Font) this.fonts.get(fontname);
+        if(result == null){
+            result = new Font("SansSerif", Font.PLAIN, 12);
+        }
+        return result;
+    }
+}
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAToken.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAToken.java
new file mode 100644
index 0000000..0cb6fa3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PAToken.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import headless.awt.*;
+import headless.awt.geom.*;
+import headless.awt.color.*;
+import headless.awt.font.*;
+
+public class PAToken extends Object {
+
+    static public final int IDENTIFIER = 0;
+    static public final int KEY = 1;
+    static public final int PROCEDURE = 2;
+    static public final int MARK = 3;
+    static public final int START_PROCEDURE = 4;
+    static public final int END_PROCEDURE = 5;
+    static public final int IMMEDIATE = 6;
+    static public final int START_ARRAY = 7;
+    static public final int END_ARRAY = 8;
+
+    public Object value;
+    public int type;
+
+    public PAToken(Object value, int type){
+        super();
+        this.value = value;
+        this.type = type;
+    }
+
+    public String toString(){
+        switch(this.type){
+        case IDENTIFIER:
+            return "IDENTIFIER " + this.value.toString();
+        case KEY:
+            return "KEY " + this.value.toString();
+        case PROCEDURE:
+            return "PROCEDURE " + this.value.toString();
+        case MARK:
+            return "MARK";
+        case START_PROCEDURE:
+            return "START_PROCEDURE";
+        case END_PROCEDURE:
+            return "END_PROCEDURE";
+        case IMMEDIATE:
+            return "IMMEDIATE " + this.value.toString();
+        case START_ARRAY:
+            return "START_ARRAY";
+        case END_ARRAY:
+            return "END_ARRAY";
+        }
+        return this.value.toString();
+    }
+
+}
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/PainterException.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PainterException.java
new file mode 100644
index 0000000..6250891
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/PainterException.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ */
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+
+public class PainterException extends Exception {
+
+    public PainterException(String msg){
+        super(msg);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/ParseException.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/ParseException.java
new file mode 100644
index 0000000..c4a1c9b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/ParseException.java
@@ -0,0 +1,193 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 2.1 */
+package com.lowagie.text.pdf.codec.postscript;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.  The boolean
+   * flag "specialConstructor" is also set to true to indicate that
+   * this constructor was used to create this object.
+   * This constructor calls its super class with the empty string
+   * to force the "toString" method of parent class "Throwable" to
+   * print the error message in the form:
+   *     ParseException: <result of getMessage>
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super("");
+    specialConstructor = true;
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+    specialConstructor = false;
+  }
+
+  public ParseException(String message) {
+    super(message);
+    specialConstructor = false;
+  }
+
+  /**
+   * This variable determines which constructor was used to create
+   * this object and thereby affects the semantics of the
+   * "getMessage" method (see below).
+   */
+  protected boolean specialConstructor;
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * This method has the standard behavior when this object has been
+   * created using the standard constructors.  Otherwise, it uses
+   * "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser), then this method is called during the printing
+   * of the final stack trace, and hence the correct error message
+   * gets displayed.
+   */
+  public String getMessage() {
+    if (!specialConstructor) {
+      return super.getMessage();
+    }
+    String expected = "";
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected += tokenImage[expectedTokenSequences[i][j]] + " ";
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected += "...";
+      }
+      expected += eol + "    ";
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += add_escapes(tok.image);
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected;
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  protected String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/Token.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/Token.java
new file mode 100644
index 0000000..c45f0d3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/Token.java
@@ -0,0 +1,82 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 2.1 */
+package com.lowagie.text.pdf.codec.postscript;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token {
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /**
+   * beginLine and beginColumn describe the position of the first character
+   * of this token; endLine and endColumn describe the position of the
+   * last character of this token.
+   */
+  public int beginLine, beginColumn, endLine, endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * Returns the image.
+   */
+  public final String toString()
+  {
+     return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simlpy add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken();
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use it in your lexical actions.
+   */
+  public static final Token newToken(int ofKind)
+  {
+     switch(ofKind)
+     {
+       default : return new Token();
+     }
+  }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/TokenMgrError.java b/LibrarySource/com/lowagie/text/pdf/codec/postscript/TokenMgrError.java
new file mode 100644
index 0000000..7445bf7
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/TokenMgrError.java
@@ -0,0 +1,134 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 2.1 */
+package com.lowagie.text.pdf.codec.postscript;
+
+public class TokenMgrError extends Error
+{
+   /*
+    * Ordinals for various reasons why an Error of this type can be thrown.
+    */
+
+   /**
+    * Lexical error occured.
+    */
+   static final int LEXICAL_ERROR = 0;
+
+   /**
+    * An attempt wass made to create a second instance of a static token manager.
+    */
+   static final int STATIC_LEXER_ERROR = 1;
+
+   /**
+    * Tried to change to an invalid lexical state.
+    */
+   static final int INVALID_LEXICAL_STATE = 2;
+
+   /**
+    * Detected (and bailed out of) an infinite loop in the token manager.
+    */
+   static final int LOOP_DETECTED = 3;
+
+   /**
+    * Indicates the reason why the exception is thrown. It will have
+    * one of the above 4 values.
+    */
+   int errorCode;
+
+   /**
+    * Replaces unprintable characters by their espaced (or unicode escaped)
+    * equivalents in the given string
+    */
+   protected static final String addEscapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+   /**
+    * Returns a detailed message for the Error when it is thrown by the
+    * token manager to indicate a lexical error.
+    * Parameters :
+    *    EOFSeen     : indicates if EOF caused the lexicl error
+    *    curLexState : lexical state in which this error occured
+    *    errorLine   : line number when the error occured
+    *    errorColumn : column number when the error occured
+    *    errorAfter  : prefix that was seen before this error occured
+    *    curchar     : the offending character
+    * Note: You can customize the lexical error message by modifying this method.
+    */
+   private static final String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+      return("Lexical error at line " +
+           errorLine + ", column " +
+           errorColumn + ".  Encountered: " +
+           (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+           "after : \"" + addEscapes(errorAfter) + "\"");
+   }
+
+   /**
+    * You can also modify the body of this method to customize your error messages.
+    * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+    * of end-users concern, so you can return something like :
+    *
+    *     "Internal Error : Please file a bug report .... "
+    *
+    * from this method for such cases in the release version of your parser.
+    */
+   public String getMessage() {
+      return super.getMessage();
+   }
+
+   /*
+    * Constructors of various flavors follow.
+    */
+
+   public TokenMgrError() {
+   }
+
+   public TokenMgrError(String message, int reason) {
+      super(message);
+      errorCode = reason;
+   }
+
+   public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+      this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+   }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/postscript/paparser.jj b/LibrarySource/com/lowagie/text/pdf/codec/postscript/paparser.jj
new file mode 100644
index 0000000..8aafa1c
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/postscript/paparser.jj
@@ -0,0 +1,290 @@
+options {
+        LOOKAHEAD=1;
+	JAVA_UNICODE_ESCAPE = true;
+	STATIC = false;
+}
+
+PARSER_BEGIN(PAParser)
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.color.*;
+import java.awt.font.*;
+
+import java.io.*;
+import java.net.URL;
+
+public class PAParser extends Object {
+
+}
+
+PARSER_END(PAParser)
+
+
+/* WHITE SPACE */
+
+SKIP :
+{
+  < WHITESPACE: " " | "\t" | "\n" | "\r" | "\f" >
+|
+  < "%" ( ~["\n"] )* "\n" >
+      |
+  < "%" ( ~["\r"] )* "\r" >
+}
+
+/* LITERALS */
+
+TOKEN :
+{
+  < INTEGER_LITERAL:
+      ("-")? (  <DECIMAL_LITERAL> (["l","L"])?
+      | <HEX_LITERAL> (["l","L"])?
+       )
+  >
+|
+  < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* >
+|
+  < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
+|
+  < FLOATING_POINT_LITERAL:
+        ((["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?)
+      | ("." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?)
+      | ((["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?)
+      | ((["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"])
+      | ("-" (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?)
+      | ("-" "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?)
+      | ("-" (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?)
+      | ("-" (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"])
+  >
+|
+  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
+|
+  < STRING_LITERAL:
+      "("
+      (   (~[")","\\","\n","\r"])
+        | ("\\"
+            ( ["n","t","b","r","f","\\","'",")", "\n"]
+            | ["0"-"7"] ( ["0"-"7"] )?
+            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
+            )
+          )
+      )*
+      ")"
+  >
+}
+
+/* IDENTIFIERS */
+
+TOKEN :
+{
+  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|"-"|".")* >
+|
+  < KEY_IDENTIFIER: "/" <IDENTIFIER> >
+|
+  < IMMEDIATE_IDENTIFIER: "//" <IDENTIFIER> >
+|
+  < #LETTER:
+      [
+       "\u0024",
+       "\u0041"-"\u005a",
+       "\u005f",
+       "\u0061"-"\u007a",
+       "\u00c0"-"\u00d6",
+       "\u00d8"-"\u00f6",
+       "\u00f8"-"\u00ff",
+       "\u0100"-"\u1fff",
+       "\u3040"-"\u318f",
+       "\u3300"-"\u337f",
+       "\u3400"-"\u3d2d",
+       "\u4e00"-"\u9fff",
+       "\uf900"-"\ufaff"
+      ]
+  >
+|
+  < #DIGIT:
+      [
+       "\u0030"-"\u0039",
+       "\u0660"-"\u0669",
+       "\u06f0"-"\u06f9",
+       "\u0966"-"\u096f",
+       "\u09e6"-"\u09ef",
+       "\u0a66"-"\u0a6f",
+       "\u0ae6"-"\u0aef",
+       "\u0b66"-"\u0b6f",
+       "\u0be7"-"\u0bef",
+       "\u0c66"-"\u0c6f",
+       "\u0ce6"-"\u0cef",
+       "\u0d66"-"\u0d6f",
+       "\u0e50"-"\u0e59",
+       "\u0ed0"-"\u0ed9",
+       "\u1040"-"\u1049"
+      ]
+  >
+}
+
+/* SEPARATORS */
+
+TOKEN :
+{
+
+  < LBRACE: "{" >
+| < RBRACE: "}" >
+| < LBRACKET: "[" >
+| < RBRACKET: "]" >
+
+}
+
+JAVACODE
+void error_skipto(int kind){
+ParseException e=generateParseException();
+Token t;
+String dump="";
+do{
+if(getToken(1).kind==kind)break;
+t=getNextToken();
+dump+=t.image;
+}while(t.kind!=kind);
+System.out.println("Ignoriere >"+dump+"<");
+}
+
+
+void parse(PAContext context) :
+{
+        Token x = null;
+}
+{
+  try{
+       (
+      (
+              (  (
+                        x = <INTEGER_LITERAL>
+                        {
+                                try {
+                                        context.engine.process(new Integer(x.image));
+                                } catch(NumberFormatException e) {
+                                        throw new ParseException(e.toString());
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        x = <FLOATING_POINT_LITERAL>
+                        {
+                                try {
+                                        context.engine.process(new Double(x.image));
+                                } catch(NumberFormatException e) {
+                                        throw new ParseException(e.toString());
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        x = <STRING_LITERAL>
+                        {
+                                try {
+	  	                        context.engine.process(x.image.substring(1, x.image.length() -1));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        x = <IDENTIFIER>
+                        {
+                                try {
+	  	                        context.engine.process(new PAToken(x.image, PAToken.IDENTIFIER));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        x = <KEY_IDENTIFIER>
+                        {
+                                try {
+	  	                        context.engine.process(new PAToken(x.image.substring(1, x.image.length()), PAToken.KEY));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        x = <IMMEDIATE_IDENTIFIER>
+                        {
+                                try {
+	  	                        context.engine.process(new PAToken(x.image.substring(2, x.image.length()), PAToken.IMMEDIATE));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                ) )
+                |
+                (
+                        <LBRACE>
+                        {
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.START_PROCEDURE));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        <RBRACE>
+                        {
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.END_PROCEDURE));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        <LBRACKET>
+                        {
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.START_ARRAY));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                |
+                (
+                        <RBRACKET>
+                        {
+                                try {
+                                        context.engine.process(new PAToken(null, PAToken.END_ARRAY));
+                                } catch(PainterException e) {
+                                        throw new ParseException(e.toString());
+                                }
+                        }
+                )
+                )//{System.out.println(">>>"+token.image+"");System.out.flush();}
+        )*
+
+  }catch(ParseException e){
+                  //System.out.println("Fehlerhaftes Element in Spalte "+e.currentToken.beginColumn+" in Eingabedatei in Zeile="+e.currentToken.next.beginLine+" in Zeichen Nr. "+e.currentToken.next.beginColumn+". >"+e.currentToken.next.image+"< wurde hier nicht erwartet.");
+                  //System.err.println("Fehler:"+e);
+                  e.printStackTrace();
+                  error_skipto(WHITESPACE);
+              }
+}
+
+
+
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/InputMeta.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/InputMeta.java
new file mode 100644
index 0000000..afd9c1e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/InputMeta.java
@@ -0,0 +1,114 @@
+/*
+ * $Id: InputMeta.java,v 1.15 2002/06/18 13:59:57 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+
+import java.io.*;
+import headless.awt.Color;
+
+public class InputMeta {
+    
+    InputStream in;
+    int length;
+    
+    public InputMeta(InputStream in) {
+        this.in = in;
+    }
+
+    public int readWord() throws IOException{
+        length += 2;
+        int k1 = in.read();
+        if (k1 < 0)
+            return 0;
+        return (k1 + (in.read() << 8)) & 0xffff;
+    }
+
+    public int readShort() throws IOException{
+        int k = readWord();
+        if (k > 0x7fff)
+            k -= 0x10000;
+        return k;
+    }
+
+    public int readInt() throws IOException{
+        length += 4;
+        int k1 = in.read();
+        if (k1 < 0)
+            return 0;
+        int k2 = in.read() << 8;
+        int k3 = in.read() << 16;
+        return k1 + k2 + k3 + (in.read() << 24);
+    }
+    
+    public int readByte() throws IOException{
+        ++length;
+        return in.read() & 0xff;
+    }
+    
+    public void skip(int len) throws IOException{
+        length += len;
+        while (len > 0) {
+            len -= in.skip(len);
+        }
+    }
+    
+    public int getLength() {
+        return length;
+    }
+    
+    public Color readColor() throws IOException{
+        int red = readByte();
+        int green = readByte();
+        int blue = readByte();
+        readByte();
+        return new Color(red, green, blue);
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaBrush.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaBrush.java
new file mode 100644
index 0000000..c28ace3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaBrush.java
@@ -0,0 +1,95 @@
+/*
+ * $Id: MetaBrush.java,v 1.15 2002/06/18 13:59:57 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+import java.io.IOException;
+import headless.awt.Color;
+
+public class MetaBrush extends MetaObject {
+
+    public static final int BS_SOLID = 0;
+    public static final int BS_NULL = 1;
+    public static final int BS_HATCHED = 2;
+    public static final int BS_PATTERN = 3;
+    public static final int BS_DIBPATTERN = 5;
+    public static final int HS_HORIZONTAL = 0;
+    public static final int HS_VERTICAL = 1;
+    public static final int HS_FDIAGONAL = 2;
+    public static final int HS_BDIAGONAL = 3;
+    public static final int HS_CROSS = 4;
+    public static final int HS_DIAGCROSS = 5;
+
+    int style = BS_SOLID;
+    int hatch;
+    Color color = Color.white;
+
+    public MetaBrush() {
+        type = META_BRUSH;
+    }
+
+    public void init(InputMeta in) throws IOException {
+        style = in.readWord();
+        color = in.readColor();
+        hatch = in.readWord();
+    }
+    
+    public int getStyle() {
+        return style;
+    }
+    
+    public int getHatch() {
+        return hatch;
+    }
+    
+    public Color getColor() {
+        return color;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaDo.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaDo.java
new file mode 100644
index 0000000..d335c0b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaDo.java
@@ -0,0 +1,760 @@
+/*
+ * $Id: MetaDo.java,v 1.28 2003/05/02 09:01:33 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+import java.io.*;
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.pdf.codec.BmpImage;
+import com.lowagie.text.*;
+import headless.awt.Point;
+import headless.awt.Color;
+import java.util.ArrayList;
+
+public class MetaDo {
+    
+    public static final int META_SETBKCOLOR            = 0x0201;
+    public static final int META_SETBKMODE             = 0x0102;
+    public static final int META_SETMAPMODE            = 0x0103;
+    public static final int META_SETROP2               = 0x0104;
+    public static final int META_SETRELABS             = 0x0105;
+    public static final int META_SETPOLYFILLMODE       = 0x0106;
+    public static final int META_SETSTRETCHBLTMODE     = 0x0107;
+    public static final int META_SETTEXTCHAREXTRA      = 0x0108;
+    public static final int META_SETTEXTCOLOR          = 0x0209;
+    public static final int META_SETTEXTJUSTIFICATION  = 0x020A;
+    public static final int META_SETWINDOWORG          = 0x020B;
+    public static final int META_SETWINDOWEXT          = 0x020C;
+    public static final int META_SETVIEWPORTORG        = 0x020D;
+    public static final int META_SETVIEWPORTEXT        = 0x020E;
+    public static final int META_OFFSETWINDOWORG       = 0x020F;
+    public static final int META_SCALEWINDOWEXT        = 0x0410;
+    public static final int META_OFFSETVIEWPORTORG     = 0x0211;
+    public static final int META_SCALEVIEWPORTEXT      = 0x0412;
+    public static final int META_LINETO                = 0x0213;
+    public static final int META_MOVETO                = 0x0214;
+    public static final int META_EXCLUDECLIPRECT       = 0x0415;
+    public static final int META_INTERSECTCLIPRECT     = 0x0416;
+    public static final int META_ARC                   = 0x0817;
+    public static final int META_ELLIPSE               = 0x0418;
+    public static final int META_FLOODFILL             = 0x0419;
+    public static final int META_PIE                   = 0x081A;
+    public static final int META_RECTANGLE             = 0x041B;
+    public static final int META_ROUNDRECT             = 0x061C;
+    public static final int META_PATBLT                = 0x061D;
+    public static final int META_SAVEDC                = 0x001E;
+    public static final int META_SETPIXEL              = 0x041F;
+    public static final int META_OFFSETCLIPRGN         = 0x0220;
+    public static final int META_TEXTOUT               = 0x0521;
+    public static final int META_BITBLT                = 0x0922;
+    public static final int META_STRETCHBLT            = 0x0B23;
+    public static final int META_POLYGON               = 0x0324;
+    public static final int META_POLYLINE              = 0x0325;
+    public static final int META_ESCAPE                = 0x0626;
+    public static final int META_RESTOREDC             = 0x0127;
+    public static final int META_FILLREGION            = 0x0228;
+    public static final int META_FRAMEREGION           = 0x0429;
+    public static final int META_INVERTREGION          = 0x012A;
+    public static final int META_PAINTREGION           = 0x012B;
+    public static final int META_SELECTCLIPREGION      = 0x012C;
+    public static final int META_SELECTOBJECT          = 0x012D;
+    public static final int META_SETTEXTALIGN          = 0x012E;
+    public static final int META_CHORD                 = 0x0830;
+    public static final int META_SETMAPPERFLAGS        = 0x0231;
+    public static final int META_EXTTEXTOUT            = 0x0a32;
+    public static final int META_SETDIBTODEV           = 0x0d33;
+    public static final int META_SELECTPALETTE         = 0x0234;
+    public static final int META_REALIZEPALETTE        = 0x0035;
+    public static final int META_ANIMATEPALETTE        = 0x0436;
+    public static final int META_SETPALENTRIES         = 0x0037;
+    public static final int META_POLYPOLYGON           = 0x0538;
+    public static final int META_RESIZEPALETTE         = 0x0139;
+    public static final int META_DIBBITBLT             = 0x0940;
+    public static final int META_DIBSTRETCHBLT         = 0x0b41;
+    public static final int META_DIBCREATEPATTERNBRUSH = 0x0142;
+    public static final int META_STRETCHDIB            = 0x0f43;
+    public static final int META_EXTFLOODFILL          = 0x0548;
+    public static final int META_DELETEOBJECT          = 0x01f0;
+    public static final int META_CREATEPALETTE         = 0x00f7;
+    public static final int META_CREATEPATTERNBRUSH    = 0x01F9;
+    public static final int META_CREATEPENINDIRECT     = 0x02FA;
+    public static final int META_CREATEFONTINDIRECT    = 0x02FB;
+    public static final int META_CREATEBRUSHINDIRECT   = 0x02FC;
+    public static final int META_CREATEREGION          = 0x06FF;
+
+    public PdfContentByte cb;
+    public InputMeta in;
+    int left;
+    int top;
+    int right;
+    int bottom;
+    int inch;
+    MetaState state = new MetaState();
+
+    public MetaDo(InputStream in, PdfContentByte cb) {
+        this.cb = cb;
+        this.in = new InputMeta(in);
+    }
+    
+    public void readAll() throws IOException, DocumentException{
+        if (in.readInt() != 0x9AC6CDD7) {
+            throw new DocumentException("Not a placeable windows metafile");
+        }
+        in.readWord();
+        left = in.readShort();
+        top = in.readShort();
+        right = in.readShort();
+        bottom = in.readShort();
+        inch = in.readWord();
+        state.setScalingX((float)(right - left) / (float)inch * 72f);
+        state.setScalingY((float)(bottom - top) / (float)inch * 72f);
+        state.setOffsetWx(left);
+        state.setOffsetWy(top);
+        state.setExtentWx(right - left);
+        state.setExtentWy(bottom - top);
+        in.readInt();
+        in.readWord();
+        in.skip(18);
+        
+        int tsize;
+        int function;
+        cb.setLineCap(1);
+        cb.setLineJoin(1);
+        for (;;) {
+            int lenMarker = in.getLength();
+            tsize = in.readInt();
+            if (tsize < 3)
+                break;
+            function = in.readWord();
+            switch (function) {
+                case 0:
+                    break;
+                case META_CREATEPALETTE:
+                case META_CREATEREGION:
+                case META_DIBCREATEPATTERNBRUSH:
+                    state.addMetaObject(new MetaObject());
+                    break;
+                case META_CREATEPENINDIRECT:
+                {
+                    MetaPen pen = new MetaPen();
+                    pen.init(in);
+                    state.addMetaObject(pen);
+                    break;
+                }
+                case META_CREATEBRUSHINDIRECT:
+                {
+                    MetaBrush brush = new MetaBrush();
+                    brush.init(in);
+                    state.addMetaObject(brush);
+                    break;
+                }
+                case META_CREATEFONTINDIRECT:
+                {
+                    MetaFont font = new MetaFont();
+                    font.init(in);
+                    state.addMetaObject(font);
+                    break;
+                }
+                case META_SELECTOBJECT:
+                {
+                    int idx = in.readWord();
+                    state.selectMetaObject(idx, cb);
+                    break;
+                }
+                case META_DELETEOBJECT:
+                {
+                    int idx = in.readWord();
+                    state.deleteMetaObject(idx);
+                    break;
+                }
+                case META_SAVEDC:
+                    state.saveState(cb);
+                    break;
+                case META_RESTOREDC:
+                {
+                    int idx = in.readShort();
+                    state.restoreState(idx, cb);
+                    break;
+                }
+                case META_SETWINDOWORG:
+                    state.setOffsetWy(in.readShort());
+                    state.setOffsetWx(in.readShort());
+                    break;
+                case META_SETWINDOWEXT:
+                    state.setExtentWy(in.readShort());
+                    state.setExtentWx(in.readShort());
+                    break;
+                case META_MOVETO:
+                {
+                    int y = in.readShort();
+                    Point p = new Point(in.readShort(), y);
+                    state.setCurrentPoint(p);
+                    break;
+                }
+                case META_LINETO:
+                {
+                    int y = in.readShort();
+                    int x = in.readShort();
+                    Point p = state.getCurrentPoint();
+                    cb.moveTo(state.transformX(p.x), state.transformY(p.y));
+                    cb.lineTo(state.transformX(x), state.transformY(y));
+                    cb.stroke();
+                    state.setCurrentPoint(new Point(x, y));
+                    break;
+                }
+                case META_POLYLINE:
+                {
+                    state.setLineJoinPolygon(cb);
+                    int len = in.readWord();
+                    int x = in.readShort();
+                    int y = in.readShort();
+                    cb.moveTo(state.transformX(x), state.transformY(y));
+                    for (int k = 1; k < len; ++k) {
+                        x = in.readShort();
+                        y = in.readShort();
+                        cb.lineTo(state.transformX(x), state.transformY(y));
+                    }
+                    cb.stroke();
+                    break;
+                }
+                case META_POLYGON:
+                {
+                    if (isNullStrokeFill(false))
+                        break;
+                    int len = in.readWord();
+                    int sx = in.readShort();
+                    int sy = in.readShort();
+                    cb.moveTo(state.transformX(sx), state.transformY(sy));
+                    for (int k = 1; k < len; ++k) {
+                        int x = in.readShort();
+                        int y = in.readShort();
+                        cb.lineTo(state.transformX(x), state.transformY(y));
+                    }
+                    cb.lineTo(state.transformX(sx), state.transformY(sy));
+                    strokeAndFill();
+                    break;
+                }
+                case META_POLYPOLYGON:
+                {
+                    if (isNullStrokeFill(false))
+                        break;
+                    int numPoly = in.readWord();
+                    int lens[] = new int[numPoly];
+                    for (int k = 0; k < lens.length; ++k)
+                        lens[k] = in.readWord();
+                    for (int j = 0; j < lens.length; ++j) {
+                        int len = lens[j];
+                        int sx = in.readShort();
+                        int sy = in.readShort();
+                        cb.moveTo(state.transformX(sx), state.transformY(sy));
+                        for (int k = 1; k < len; ++k) {
+                            int x = in.readShort();
+                            int y = in.readShort();
+                            cb.lineTo(state.transformX(x), state.transformY(y));
+                        }
+                        cb.lineTo(state.transformX(sx), state.transformY(sy));
+                    }
+                    strokeAndFill();
+                    break;
+                }
+                case META_ELLIPSE:
+                {
+                    if (isNullStrokeFill(state.getLineNeutral()))
+                        break;
+                    int b = in.readShort();
+                    int r = in.readShort();
+                    int t = in.readShort();
+                    int l = in.readShort();
+                    cb.arc(state.transformX(l), state.transformY(b), state.transformX(r), state.transformY(t), 0, 360);
+                    strokeAndFill();
+                    break;
+                }
+                case META_ARC:
+                {
+                    if (isNullStrokeFill(state.getLineNeutral()))
+                        break;
+                    float yend = state.transformY(in.readShort());
+                    float xend = state.transformX(in.readShort());
+                    float ystart = state.transformY(in.readShort());
+                    float xstart = state.transformX(in.readShort());
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    float cx = (r + l) / 2;
+                    float cy = (t + b) / 2;
+                    float arc1 = getArc(cx, cy, xstart, ystart);
+                    float arc2 = getArc(cx, cy, xend, yend);
+                    arc2 -= arc1;
+                    if (arc2 <= 0)
+                        arc2 += 360;
+                    cb.arc(l, b, r, t, arc1, arc2);
+                    cb.stroke();
+                    break;
+                }
+                case META_PIE:
+                {
+                    if (isNullStrokeFill(state.getLineNeutral()))
+                        break;
+                    float yend = state.transformY(in.readShort());
+                    float xend = state.transformX(in.readShort());
+                    float ystart = state.transformY(in.readShort());
+                    float xstart = state.transformX(in.readShort());
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    float cx = (r + l) / 2;
+                    float cy = (t + b) / 2;
+                    float arc1 = getArc(cx, cy, xstart, ystart);
+                    float arc2 = getArc(cx, cy, xend, yend);
+                    arc2 -= arc1;
+                    if (arc2 <= 0)
+                        arc2 += 360;
+                    ArrayList ar = PdfContentByte.bezierArc(l, b, r, t, arc1, arc2);
+                    if (ar.size() == 0)
+                        break;
+                    float pt[] = (float [])ar.get(0);
+                    cb.moveTo(cx, cy);
+                    cb.lineTo(pt[0], pt[1]);
+                    for (int k = 0; k < ar.size(); ++k) {
+                        pt = (float [])ar.get(k);
+                        cb.curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]);
+                    }
+                    cb.lineTo(cx, cy);
+                    strokeAndFill();
+                    break;
+                }
+                case META_CHORD:
+                {
+                    if (isNullStrokeFill(state.getLineNeutral()))
+                        break;
+                    float yend = state.transformY(in.readShort());
+                    float xend = state.transformX(in.readShort());
+                    float ystart = state.transformY(in.readShort());
+                    float xstart = state.transformX(in.readShort());
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    float cx = (r + l) / 2;
+                    float cy = (t + b) / 2;
+                    float arc1 = getArc(cx, cy, xstart, ystart);
+                    float arc2 = getArc(cx, cy, xend, yend);
+                    arc2 -= arc1;
+                    if (arc2 <= 0)
+                        arc2 += 360;
+                    ArrayList ar = PdfContentByte.bezierArc(l, b, r, t, arc1, arc2);
+                    if (ar.size() == 0)
+                        break;
+                    float pt[] = (float [])ar.get(0);
+                    cx = pt[0];
+                    cy = pt[1];
+                    cb.moveTo(cx, cy);
+                    for (int k = 0; k < ar.size(); ++k) {
+                        pt = (float [])ar.get(k);
+                        cb.curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]);
+                    }
+                    cb.lineTo(cx, cy);
+                    strokeAndFill();
+                    break;
+                }
+                case META_RECTANGLE:
+                {
+                    if (isNullStrokeFill(true))
+                        break;
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    cb.rectangle(l, b, r - l, t - b);
+                    strokeAndFill();
+                    break;
+                }
+                case META_ROUNDRECT:
+                {
+                    if (isNullStrokeFill(true))
+                        break;
+                    float h = state.transformY(0) - state.transformY(in.readShort());
+                    float w = state.transformX(in.readShort()) - state.transformX(0);
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    cb.roundRectangle(l, b, r - l, t - b, (h + w) / 4);
+                    strokeAndFill();
+                    break;
+                }
+                case META_INTERSECTCLIPRECT:
+                {
+                    float b = state.transformY(in.readShort());
+                    float r = state.transformX(in.readShort());
+                    float t = state.transformY(in.readShort());
+                    float l = state.transformX(in.readShort());
+                    cb.rectangle(l, b, r - l, t - b);
+                    cb.eoClip();
+                    cb.newPath();
+                    break;
+                }
+                case META_EXTTEXTOUT:
+                {
+                    int y = in.readShort();
+                    int x = in.readShort();
+                    int count = in.readWord();
+                    int flag = in.readWord();
+                    int x1 = 0;
+                    int y1 = 0;
+                    int x2 = 0;
+                    int y2 = 0;
+                    if ((flag & (MetaFont.ETO_CLIPPED | MetaFont.ETO_OPAQUE)) != 0) {
+                        x1 = in.readShort();
+                        y1 = in.readShort();
+                        x2 = in.readShort();
+                        y2 = in.readShort();
+                    }
+                    byte text[] = new byte[count];
+                    int k;
+                    for (k = 0; k < count; ++k) {
+                        byte c = (byte)in.readByte();
+                        if (c == 0)
+                            break;
+                        text[k] = c;
+                    }
+                    String s;
+                    try {
+                        s = new String(text, 0, k, "Cp1252");
+                    }
+                    catch (UnsupportedEncodingException e) {
+                        s = new String(text, 0, k);
+                    }
+                    outputText(x, y, flag, x1, y1, x2, y2, s);
+                    break;
+                }
+                case META_TEXTOUT:
+                {
+                    int count = in.readWord();
+                    byte text[] = new byte[count];
+                    int k;
+                    for (k = 0; k < count; ++k) {
+                        byte c = (byte)in.readByte();
+                        if (c == 0)
+                            break;
+                        text[k] = c;
+                    }
+                    String s;
+                    try {
+                        s = new String(text, 0, k, "Cp1252");
+                    }
+                    catch (UnsupportedEncodingException e) {
+                        s = new String(text, 0, k);
+                    }
+                    count = (count + 1) & 0xfffe;
+                    in.skip(count - k);
+                    int y = in.readShort();
+                    int x = in.readShort();
+                    outputText(x, y, 0, 0, 0, 0, 0, s);
+                    break;
+                }
+                case META_SETBKCOLOR:
+                    state.setCurrentBackgroundColor(in.readColor());
+                    break;
+                case META_SETTEXTCOLOR:
+                    state.setCurrentTextColor(in.readColor());
+                    break;
+                case META_SETTEXTALIGN:
+                    state.setTextAlign(in.readWord());
+                    break;
+                case META_SETBKMODE:
+                    state.setBackgroundMode(in.readWord());
+                    break;
+                case META_SETPOLYFILLMODE:
+                    state.setPolyFillMode(in.readWord());
+                    break;
+                case META_SETPIXEL:
+                {
+                    Color color = in.readColor();
+                    int y = in.readShort();
+                    int x = in.readShort();
+                    cb.saveState();
+                    cb.setColorFill(color);
+                    cb.rectangle(state.transformX(x), state.transformY(y), .2f, .2f);
+                    cb.fill();
+                    cb.restoreState();
+                    break;
+                }
+                case META_DIBSTRETCHBLT:
+                case META_STRETCHDIB: {
+                    int rop = in.readInt();
+                    if (function == META_STRETCHDIB) {
+                        /*int usage = */ in.readWord();
+                    }
+                    int srcHeight = in.readShort();
+                    int srcWidth = in.readShort();
+                    int ySrc = in.readShort();
+                    int xSrc = in.readShort();
+                    float destHeight = state.transformY(in.readShort()) - state.transformY(0);
+                    float destWidth = state.transformX(in.readShort()) - state.transformX(0);
+                    float yDest = state.transformY(in.readShort());
+                    float xDest = state.transformX(in.readShort());
+                    byte b[] = new byte[(tsize * 2) - (in.getLength() - lenMarker)];
+                    for (int k = 0; k < b.length; ++k)
+                        b[k] = (byte)in.readByte();
+                    try {
+                        ByteArrayInputStream inb = new ByteArrayInputStream(b);
+                        Image bmp = BmpImage.getImage(inb, true, b.length);
+                        cb.saveState();
+                        cb.rectangle(xDest, yDest, destWidth, destHeight);
+                        cb.clip();
+                        cb.newPath();
+                        bmp.scaleAbsolute(destWidth * bmp.width() / srcWidth, -destHeight * bmp.height() / srcHeight);
+                        bmp.setAbsolutePosition(xDest - destWidth * xSrc / srcWidth, yDest + destHeight * ySrc / srcHeight - bmp.scaledHeight());
+                        cb.addImage(bmp);
+                        cb.restoreState();
+                    }
+                    catch (Exception e) {
+                        // empty on purpose
+                    }
+                    break;
+                }
+            }
+            in.skip((tsize * 2) - (in.getLength() - lenMarker));
+        }
+        
+    }
+    
+    public void outputText(int x, int y, int flag, int x1, int y1, int x2, int y2, String text) throws IOException {
+        MetaFont font = state.getCurrentFont();
+        float refX = state.transformX(x);
+        float refY = state.transformY(y);
+        float angle = state.transformAngle(font.getAngle());
+        float sin = (float)Math.sin(angle);
+        float cos = (float)Math.cos(angle);
+        float fontSize = font.getFontSize(state);
+        BaseFont bf = font.getFont();
+        int align = state.getTextAlign();
+        float textWidth = bf.getWidthPoint(text, fontSize);
+        float tx = 0;
+        float ty = 0;
+        float descender = bf.getFontDescriptor(BaseFont.DESCENT, fontSize);
+        float ury = bf.getFontDescriptor(BaseFont.BBOXURY, fontSize);
+        cb.saveState();
+        cb.concatCTM(cos, sin, -sin, cos, refX, refY);
+        if ((align & MetaState.TA_CENTER) == MetaState.TA_CENTER)
+            tx = -textWidth / 2;
+        else if ((align & MetaState.TA_RIGHT) == MetaState.TA_RIGHT)
+            tx = -textWidth;
+        if ((align & MetaState.TA_BASELINE) == MetaState.TA_BASELINE)
+            ty = 0;
+        else if ((align & MetaState.TA_BOTTOM) == MetaState.TA_BOTTOM)
+            ty = -descender;
+        else
+            ty = -ury;
+        Color textColor;
+        if (state.getBackgroundMode() == MetaState.OPAQUE) {
+            textColor = state.getCurrentBackgroundColor();
+            cb.setColorFill(textColor);
+            cb.rectangle(tx, ty + descender, textWidth, ury - descender);
+            cb.fill();
+        }
+        textColor = state.getCurrentTextColor();
+        cb.setColorFill(textColor);
+        cb.beginText();
+        cb.setFontAndSize(bf, fontSize);
+        cb.setTextMatrix(tx, ty);
+        cb.showText(text);
+        cb.endText();
+        if (font.isUnderline()) {
+            cb.rectangle(tx, ty - fontSize / 4, textWidth, fontSize / 15);
+            cb.fill();
+        }
+        if (font.isStrikeout()) {
+            cb.rectangle(tx, ty + fontSize / 3, textWidth, fontSize / 15);
+            cb.fill();
+        }
+        cb.restoreState();
+    }
+    
+    public boolean isNullStrokeFill(boolean isRectangle) {
+        MetaPen pen = state.getCurrentPen();
+        MetaBrush brush = state.getCurrentBrush();
+        boolean noPen = (pen.getStyle() == MetaPen.PS_NULL);
+        int style = brush.getStyle();
+        boolean isBrush = (style == MetaBrush.BS_SOLID || (style == MetaBrush.BS_HATCHED && state.getBackgroundMode() == MetaState.OPAQUE));
+        boolean result = noPen && !isBrush;
+        if (!noPen) {
+            if (isRectangle)
+                state.setLineJoinRectangle(cb);
+            else
+                state.setLineJoinPolygon(cb);
+        }
+        return result;
+    }
+
+    public void strokeAndFill(){
+        MetaPen pen = state.getCurrentPen();
+        MetaBrush brush = state.getCurrentBrush();
+        int penStyle = pen.getStyle();
+        int brushStyle = brush.getStyle();
+        if (penStyle == MetaPen.PS_NULL) {
+            cb.closePath();
+            if (state.getPolyFillMode() == MetaState.ALTERNATE) {
+                cb.eoFill();
+            }
+            else {
+                cb.fill();
+            }
+        }
+        else {
+            boolean isBrush = (brushStyle == MetaBrush.BS_SOLID || (brushStyle == MetaBrush.BS_HATCHED && state.getBackgroundMode() == MetaState.OPAQUE));
+            if (isBrush) {
+                if (state.getPolyFillMode() == MetaState.ALTERNATE)
+                    cb.closePathEoFillStroke();
+                else
+                    cb.closePathFillStroke();
+            }
+            else {
+                cb.closePathStroke();
+            }
+        }
+    }
+    
+    static float getArc(float xCenter, float yCenter, float xDot, float yDot) {
+        double s = Math.atan2(yDot - yCenter, xDot - xCenter);
+        if (s < 0)
+            s += Math.PI * 2;
+        return (float)(s / Math.PI * 180);
+    }
+    
+    public static byte[] wrapBMP(Image image) throws IOException {
+        if (image.getOriginalType() != Image.ORIGINAL_BMP)
+            throw new IOException("Only BMP can be wrapped in WMF.");
+        InputStream imgIn;
+        byte data[] = null;
+        if (image.getOriginalData() == null) {
+            imgIn = image.url().openStream();
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            int b = 0;
+            while ((b = imgIn.read()) != -1)
+                out.write(b);
+            imgIn.close();
+            data = out.toByteArray();
+        }
+        else
+            data = image.getOriginalData();
+        int sizeBmpWords = (data.length - 14 + 1) >>> 1;
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        // write metafile header
+        writeWord(os, 1);
+        writeWord(os, 9);
+        writeWord(os, 0x0300);
+        writeDWord(os, 9 + 4 + 5 + 5 + (13 + sizeBmpWords) + 3); // total metafile size
+        writeWord(os, 1);
+        writeDWord(os, 14 + sizeBmpWords); // max record size
+        writeWord(os, 0);
+        // write records
+        writeDWord(os, 4);
+        writeWord(os, META_SETMAPMODE);
+        writeWord(os, 8);
+
+        writeDWord(os, 5);
+        writeWord(os, META_SETWINDOWORG);
+        writeWord(os, 0);
+        writeWord(os, 0);
+
+        writeDWord(os, 5);
+        writeWord(os, META_SETWINDOWEXT);
+        writeWord(os, (int)image.height());
+        writeWord(os, (int)image.width());
+
+        writeDWord(os, 13 + sizeBmpWords);
+        writeWord(os, META_DIBSTRETCHBLT);
+        writeDWord(os, 0x00cc0020);
+        writeWord(os, (int)image.height());
+        writeWord(os, (int)image.width());
+        writeWord(os, 0);
+        writeWord(os, 0);
+        writeWord(os, (int)image.height());
+        writeWord(os, (int)image.width());
+        writeWord(os, 0);
+        writeWord(os, 0);
+        os.write(data, 14, data.length - 14);
+        if ((data.length & 1) == 1)
+            os.write(0);
+//        writeDWord(os, 14 + sizeBmpWords);
+//        writeWord(os, META_STRETCHDIB);
+//        writeDWord(os, 0x00cc0020);
+//        writeWord(os, 0);
+//        writeWord(os, (int)image.height());
+//        writeWord(os, (int)image.width());
+//        writeWord(os, 0);
+//        writeWord(os, 0);
+//        writeWord(os, (int)image.height());
+//        writeWord(os, (int)image.width());
+//        writeWord(os, 0);
+//        writeWord(os, 0);
+//        os.write(data, 14, data.length - 14);
+//        if ((data.length & 1) == 1)
+//            os.write(0);
+
+        writeDWord(os, 3);
+        writeWord(os, 0);
+        os.close();
+        return os.toByteArray();
+    }
+
+    public static void writeWord(OutputStream os, int v) throws IOException {
+        os.write(v & 0xff);
+        os.write((v >>> 8) & 0xff);
+    }
+    
+    public static void writeDWord(OutputStream os, int v) throws IOException {
+        writeWord(os, v & 0xffff);
+        writeWord(os, (v >>> 16) & 0xffff);
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaFont.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaFont.java
new file mode 100644
index 0000000..7daa762
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaFont.java
@@ -0,0 +1,206 @@
+/*
+ * $Id: MetaFont.java,v 1.20 2002/06/20 13:00:28 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.ExceptionConverter;
+
+public class MetaFont extends MetaObject {
+    static final String fontNames[] = {
+        "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
+        "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique",
+        "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
+        "Symbol", "ZapfDingbats"};
+
+    static final int MARKER_BOLD = 1;
+    static final int MARKER_ITALIC = 2;
+    static final int MARKER_COURIER = 0;
+    static final int MARKER_HELVETICA = 4;
+    static final int MARKER_TIMES = 8;
+    static final int MARKER_SYMBOL = 12;
+
+    static final int DEFAULT_PITCH = 0;
+    static final int FIXED_PITCH = 1;
+    static final int VARIABLE_PITCH = 2;
+    static final int FF_DONTCARE = 0;
+    static final int FF_ROMAN = 1;
+    static final int FF_SWISS = 2;
+    static final int FF_MODERN = 3;
+    static final int FF_SCRIPT = 4;
+    static final int FF_DECORATIVE = 5;
+    static final int BOLDTHRESHOLD = 600;    
+    static final int nameSize = 32;
+    static final int ETO_OPAQUE = 2;
+    static final int ETO_CLIPPED = 4;
+
+    int height;
+    float angle;
+    int bold;
+    int italic;
+    boolean underline;
+    boolean strikeout;
+    int charset;
+    int pitchAndFamily;
+    String faceName = "arial";
+    BaseFont font = null;
+
+    public MetaFont() {
+        type = META_FONT;
+    }
+
+    public void init(InputMeta in) throws IOException {
+        height = Math.abs(in.readShort());
+        in.skip(2);
+        angle = (float)(in.readShort() / 1800.0 * Math.PI);
+        in.skip(2);
+        bold = (in.readShort() >= BOLDTHRESHOLD ? MARKER_BOLD : 0);
+        italic = (in.readByte() != 0 ? MARKER_ITALIC : 0);
+        underline = (in.readByte() != 0);
+        strikeout = (in.readByte() != 0);
+        charset = in.readByte();
+        in.skip(3);
+        pitchAndFamily = in.readByte();
+        byte name[] = new byte[nameSize];
+        int k;
+        for (k = 0; k < nameSize; ++k) {
+            int c = in.readByte();
+            if (c == 0) {
+                break;
+            }
+            name[k] = (byte)c;
+        }
+        try {
+            faceName = new String(name, 0, k, "Cp1252");
+        }
+        catch (UnsupportedEncodingException e) {
+            faceName = new String(name, 0, k);
+        }
+        faceName = faceName.toLowerCase();
+    }
+    
+    public BaseFont getFont() {
+        if (font != null)
+            return font;
+        String fontName;
+        if (faceName.indexOf("courier") != -1 || faceName.indexOf("terminal") != -1
+            || faceName.indexOf("fixedsys") != -1) {
+            fontName = fontNames[MARKER_COURIER + italic + bold];
+        }
+        else if (faceName.indexOf("ms sans serif") != -1 || faceName.indexOf("arial") != -1
+            || faceName.indexOf("system") != -1) {
+            fontName = fontNames[MARKER_HELVETICA + italic + bold];
+        }
+        else if (faceName.indexOf("arial black") != -1) {
+            fontName = fontNames[MARKER_HELVETICA + italic + MARKER_BOLD];
+        }
+        else if (faceName.indexOf("times") != -1 || faceName.indexOf("ms serif") != -1
+            || faceName.indexOf("roman") != -1) {
+            fontName = fontNames[MARKER_TIMES + italic + bold];
+        }
+        else if (faceName.indexOf("symbol") != -1) {
+            fontName = fontNames[MARKER_SYMBOL];
+        }
+        else {
+            int pitch = pitchAndFamily & 3;
+            int family = (pitchAndFamily >> 4) & 7;
+            switch (family) {
+                case FF_MODERN:
+                    fontName = fontNames[MARKER_COURIER + italic + bold];
+                    break;
+                case FF_ROMAN:
+                    fontName = fontNames[MARKER_TIMES + italic + bold];
+                    break;
+                case FF_SWISS:
+                case FF_SCRIPT:
+                case FF_DECORATIVE:
+                    fontName = fontNames[MARKER_HELVETICA + italic + bold];
+                    break;
+                default:
+                {
+                    switch (pitch) {
+                        case FIXED_PITCH:
+                            fontName = fontNames[MARKER_COURIER + italic + bold];
+                            break;
+                        default:
+                            fontName = fontNames[MARKER_HELVETICA + italic + bold];
+                            break;
+                    }
+                }
+            }
+        }
+        try {
+            font = BaseFont.createFont(fontName, "Cp1252", false);
+        }
+        catch (Exception e) {
+            throw new ExceptionConverter(e);
+        }
+        
+        return font;
+    }
+    
+    public float getAngle() {
+        return angle;
+    }
+    
+    public boolean isUnderline() {
+        return underline;
+    }
+    
+    public boolean isStrikeout() {
+        return strikeout;
+    }
+    
+    public float getFontSize(MetaState state) {
+        return Math.abs(state.transformY(height) - state.transformY(0)) * 0.86f;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaObject.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaObject.java
new file mode 100644
index 0000000..bb0711b
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaObject.java
@@ -0,0 +1,72 @@
+/*
+ * $Id: MetaObject.java,v 1.15 2002/06/18 13:59:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+
+public class MetaObject {
+    public static final int META_NOT_SUPPORTED = 0;
+    public static final int META_PEN = 1;
+    public static final int META_BRUSH = 2;
+    public static final int META_FONT = 3;
+    public int type = META_NOT_SUPPORTED;
+
+    public MetaObject() {
+    }
+
+    public MetaObject(int type) {
+        this.type = type;
+    }
+    
+    public int getType() {
+        return type;
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaPen.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaPen.java
new file mode 100644
index 0000000..1c53f14
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaPen.java
@@ -0,0 +1,92 @@
+/*
+ * $Id: MetaPen.java,v 1.15 2002/06/18 13:59:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+import java.io.IOException;
+import headless.awt.Color;
+
+public class MetaPen extends MetaObject {
+
+    public static final int PS_SOLID = 0;
+    public static final int PS_DASH = 1;
+    public static final int PS_DOT = 2;
+    public static final int PS_DASHDOT = 3;
+    public static final int PS_DASHDOTDOT = 4;
+    public static final int PS_NULL = 5;
+    public static final int PS_INSIDEFRAME = 6;
+
+    int style = PS_SOLID;
+    int penWidth = 1;
+    Color color = Color.black;
+
+    public MetaPen() {
+        type = META_PEN;
+    }
+
+    public void init(InputMeta in) throws IOException {
+        style = in.readWord();
+        penWidth = in.readShort();
+        in.readWord();
+        color = in.readColor();
+    }
+    
+    public int getStyle() {
+        return style;
+    }
+    
+    public int getPenWidth() {
+        return penWidth;
+    }
+    
+    public Color getColor() {
+        return color;
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaState.java b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaState.java
new file mode 100644
index 0000000..b2ccd46
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/codec/wmf/MetaState.java
@@ -0,0 +1,367 @@
+/*
+ * $Id: MetaState.java,v 1.15 2002/06/18 13:59:58 blowagie Exp $
+ * $Name:  $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.codec.wmf;
+
+import java.util.ArrayList;
+import java.util.Stack;
+import headless.awt.Point;
+import headless.awt.Color;
+import com.lowagie.text.pdf.*;
+
+public class MetaState {
+    
+    public static final int TA_NOUPDATECP = 0;
+    public static final int TA_UPDATECP = 1;
+    public static final int TA_LEFT = 0;
+    public static final int TA_RIGHT = 2;
+    public static final int TA_CENTER = 6;
+    public static final int TA_TOP = 0;
+    public static final int TA_BOTTOM = 8;
+    public static final int TA_BASELINE = 24;
+    
+    public static final int TRANSPARENT = 1;
+    public static final int OPAQUE = 2;
+
+    public static final int ALTERNATE = 1;
+    public static final int WINDING = 2;
+
+    public Stack savedStates;
+    public ArrayList MetaObjects;
+    public Point currentPoint;
+    public MetaPen currentPen;
+    public MetaBrush currentBrush;
+    public MetaFont currentFont;
+    public Color currentBackgroundColor = Color.white;
+    public Color currentTextColor = Color.black;
+    public int backgroundMode = OPAQUE;
+    public int polyFillMode = ALTERNATE;
+    public int lineJoin = 1;
+    public int textAlign;
+    public int offsetWx;
+    public int offsetWy;
+    public int extentWx;
+    public int extentWy;
+    public float scalingX;
+    public float scalingY;
+    
+
+    /** Creates new MetaState */
+    public MetaState() {
+        savedStates = new Stack();
+        MetaObjects = new ArrayList();
+        currentPoint = new Point(0, 0);
+        currentPen = new MetaPen();
+        currentBrush = new MetaBrush();
+        currentFont = new MetaFont();
+    }
+
+    public MetaState(MetaState state) {
+        setMetaState(state);
+    }
+    
+    public void setMetaState(MetaState state) {
+        savedStates = state.savedStates;
+        MetaObjects = state.MetaObjects;
+        currentPoint = state.currentPoint;
+        currentPen = state.currentPen;
+        currentBrush = state.currentBrush;
+        currentFont = state.currentFont;
+        currentBackgroundColor = state.currentBackgroundColor;
+        currentTextColor = state.currentTextColor;
+        backgroundMode = state.backgroundMode;
+        polyFillMode = state.polyFillMode;
+        textAlign = state.textAlign;
+        lineJoin = state.lineJoin;
+        offsetWx = state.offsetWx;
+        offsetWy = state.offsetWy;
+        extentWx = state.extentWx;
+        extentWy = state.extentWy;
+        scalingX = state.scalingX;
+        scalingY = state.scalingY;
+    }
+
+    public void addMetaObject(MetaObject object) {
+        for (int k = 0; k < MetaObjects.size(); ++k) {
+            if (MetaObjects.get(k) == null) {
+                MetaObjects.set(k, object);
+                return;
+            }
+        }
+        MetaObjects.add(object);
+    }
+    
+    public void selectMetaObject(int index, PdfContentByte cb) {
+        MetaObject obj = (MetaObject)MetaObjects.get(index);
+        if (obj == null)
+            return;
+        int style;
+        switch (obj.getType()) {
+            case MetaObject.META_BRUSH:
+                currentBrush = (MetaBrush)obj;
+                style = currentBrush.getStyle();
+                if (style == MetaBrush.BS_SOLID) {
+                    Color color = currentBrush.getColor();
+                    cb.setColorFill(color);
+                }
+                else if (style == MetaBrush.BS_HATCHED) {
+                    Color color = currentBackgroundColor;
+                    cb.setColorFill(color);
+                }
+                break;
+            case MetaObject.META_PEN:
+            {
+                currentPen = (MetaPen)obj;
+                style = currentPen.getStyle();
+                if (style != MetaPen.PS_NULL) {
+                    Color color = currentPen.getColor();
+                    cb.setColorStroke(color);
+                    cb.setLineWidth(Math.abs((float)currentPen.getPenWidth() * scalingX / extentWx));
+                    switch (style) {
+                        case MetaPen.PS_DASH:
+                            cb.setLineDash(18, 6, 0);
+                            break;
+                        case MetaPen.PS_DASHDOT:
+                            cb.setLiteral("[9 6 3 6]0 d\n");
+                            break;
+                        case MetaPen.PS_DASHDOTDOT:
+                            cb.setLiteral("[9 3 3 3 3 3]0 d\n");
+                            break;
+                        case MetaPen.PS_DOT:
+                            cb.setLineDash(3, 0);
+                            break;
+                        default:
+                            cb.setLineDash(0);
+                            break;                            
+                    }
+                }
+                break;
+            }
+            case MetaObject.META_FONT:
+            {
+                currentFont = (MetaFont)obj;
+                break;
+            }
+        }
+    }
+    
+    public void deleteMetaObject(int index) {
+        MetaObjects.set(index, null);
+    }
+    
+    public void saveState(PdfContentByte cb) {
+        cb.saveState();
+        MetaState state = new MetaState(this);
+        savedStates.push(this);
+    }
+
+    public void restoreState(int index, PdfContentByte cb) {
+        int pops;
+        if (index < 0)
+            pops = Math.min(-index, savedStates.size());
+        else
+            pops = Math.max(savedStates.size() - index, 0);
+        if (pops == 0)
+            return;
+        MetaState state = null;
+        while (pops-- != 0) {
+            cb.restoreState();
+            state = (MetaState)savedStates.pop();
+        }
+        setMetaState(state);
+    }
+    
+    public float transformX(int x) {
+        return ((float)x - offsetWx) * scalingX / extentWx;
+    }
+
+    public float transformY(int y) {
+        return (1f - ((float)y - offsetWy) / extentWy) * scalingY;
+    }
+    
+    public void setScalingX(float scalingX) {
+        this.scalingX = scalingX;
+    }
+    
+    public void setScalingY(float scalingY) {
+        this.scalingY = scalingY;
+    }
+    
+    public void setOffsetWx(int offsetWx) {
+        this.offsetWx = offsetWx;
+    }
+    
+    public void setOffsetWy(int offsetWy) {
+        this.offsetWy = offsetWy;
+    }
+    
+    public void setExtentWx(int extentWx) {
+        this.extentWx = extentWx;
+    }
+    
+    public void setExtentWy(int extentWy) {
+        this.extentWy = extentWy;
+    }
+    
+    public float transformAngle(float angle) {
+        float ta = extentWy < 0 ? -angle : angle;
+        return extentWx < 0 ? 180 - ta : ta;
+    }
+    
+    public void setCurrentPoint(Point p) {
+        currentPoint = p;
+    }
+
+    public Point getCurrentPoint() {
+        return currentPoint;
+    }
+    
+    public MetaBrush getCurrentBrush() {
+        return currentBrush;
+    }
+
+    public MetaPen getCurrentPen() {
+        return currentPen;
+    }
+
+    public MetaFont getCurrentFont() {
+        return currentFont;
+    }
+    
+    /** Getter for property currentBackgroundColor.
+     * @return Value of property currentBackgroundColor.
+     */
+    public Color getCurrentBackgroundColor() {
+        return currentBackgroundColor;
+    }
+    
+    /** Setter for property currentBackgroundColor.
+     * @param currentBackgroundColor New value of property currentBackgroundColor.
+     */
+    public void setCurrentBackgroundColor(Color currentBackgroundColor) {
+        this.currentBackgroundColor = currentBackgroundColor;
+    }
+    
+    /** Getter for property currentTextColor.
+     * @return Value of property currentTextColor.
+     */
+    public Color getCurrentTextColor() {
+        return currentTextColor;
+    }
+    
+    /** Setter for property currentTextColor.
+     * @param currentTextColor New value of property currentTextColor.
+     */
+    public void setCurrentTextColor(Color currentTextColor) {
+        this.currentTextColor = currentTextColor;
+    }
+    
+    /** Getter for property backgroundMode.
+     * @return Value of property backgroundMode.
+     */
+    public int getBackgroundMode() {
+        return backgroundMode;
+    }
+    
+    /** Setter for property backgroundMode.
+     * @param backgroundMode New value of property backgroundMode.
+     */
+    public void setBackgroundMode(int backgroundMode) {
+        this.backgroundMode = backgroundMode;
+    }
+    
+    /** Getter for property textAlign.
+     * @return Value of property textAlign.
+     */
+    public int getTextAlign() {
+        return textAlign;
+    }
+    
+    /** Setter for property textAlign.
+     * @param textAlign New value of property textAlign.
+     */
+    public void setTextAlign(int textAlign) {
+        this.textAlign = textAlign;
+    }
+    
+    /** Getter for property polyFillMode.
+     * @return Value of property polyFillMode.
+     */
+    public int getPolyFillMode() {
+        return polyFillMode;
+    }
+    
+    /** Setter for property polyFillMode.
+     * @param polyFillMode New value of property polyFillMode.
+     */
+    public void setPolyFillMode(int polyFillMode) {
+        this.polyFillMode = polyFillMode;
+    }
+    
+    public void setLineJoinRectangle(PdfContentByte cb) {
+        if (lineJoin != 0) {
+            lineJoin = 0;
+            cb.setLineJoin(0);
+        }
+    }
+    
+    public void setLineJoinPolygon(PdfContentByte cb) {
+        if (lineJoin == 0) {
+            lineJoin = 1;
+            cb.setLineJoin(1);
+        }
+    }
+    
+    public boolean getLineNeutral() {
+        return (lineJoin == 0);
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Bold.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Bold.afm
new file mode 100644
index 0000000..a8e2309
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Bold.afm
@@ -0,0 +1,343 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Mon Jun 23 16:28:00 1997
+Comment UniqueID 43048
+Comment VMusage 41139 52164
+FontName Courier-Bold
+FullName Courier Bold
+FamilyName Courier
+Weight Bold
+ItalicAngle 0
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -113 -250 749 801 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 629
+Descender -157
+StdHW 84
+StdVW 106
+StartCharMetrics 315
+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 498 370 638 ;
+C 200 ; WX 600 ; N dieresis ; B 128 498 472 638 ;
+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 400 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 Idieresis ; B 77 0 523 761 ;
+C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N abreve ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B -1 -15 628 661 ;
+C -1 ; WX 600 ; N ecaron ; B 40 -15 563 667 ;
+C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 761 ;
+C -1 ; WX 600 ; N divide ; B 71 16 529 500 ;
+C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ;
+C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ;
+C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ;
+C -1 ; WX 600 ; N scommaaccent ; B 68 -250 535 459 ;
+C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ;
+C -1 ; WX 600 ; N Uring ; B 4 -18 596 801 ;
+C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 761 ;
+C -1 ; WX 600 ; N aogonek ; B 35 -199 586 454 ;
+C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N uogonek ; B -1 -199 585 439 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 560 761 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 594 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 205 -250 397 -57 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Emacron ; B 25 0 560 708 ;
+C -1 ; WX 600 ; N ccaron ; B 40 -15 545 667 ;
+C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 610 562 ;
+C -1 ; WX 600 ; N lacute ; B 77 0 523 801 ;
+C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 21 -250 579 562 ;
+C -1 ; WX 600 ; N Cacute ; B 22 -18 560 784 ;
+C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ;
+C -1 ; WX 600 ; N Edotaccent ; B 25 0 560 761 ;
+C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ;
+C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N lozenge ; B 66 0 534 740 ;
+C -1 ; WX 600 ; N Rcaron ; B 24 0 599 790 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 22 -250 594 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ;
+C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ;
+C -1 ; WX 600 ; N Amacron ; B -9 0 609 708 ;
+C -1 ; WX 600 ; N rcaron ; B 47 0 580 667 ;
+C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 62 0 539 761 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ;
+C -1 ; WX 600 ; N Omacron ; B 22 -18 578 708 ;
+C -1 ; WX 600 ; N Racute ; B 24 0 599 784 ;
+C -1 ; WX 600 ; N Sacute ; B 47 -22 553 784 ;
+C -1 ; WX 600 ; N dcaron ; B 20 -15 727 626 ;
+C -1 ; WX 600 ; N Umacron ; B 4 -18 596 708 ;
+C -1 ; WX 600 ; N uring ; B -1 -15 569 678 ;
+C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ;
+C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N Abreve ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ;
+C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N Tcaron ; B 21 0 579 790 ;
+C -1 ; WX 600 ; N partialdiff ; B 63 -38 537 728 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 638 ;
+C -1 ; WX 600 ; N Nacute ; B 8 -12 610 784 ;
+C -1 ; WX 600 ; N icircumflex ; B 73 0 523 657 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ;
+C -1 ; WX 600 ; N adieresis ; B 35 -15 570 638 ;
+C -1 ; WX 600 ; N edieresis ; B 40 -15 563 638 ;
+C -1 ; WX 600 ; N cacute ; B 40 -15 545 661 ;
+C -1 ; WX 600 ; N nacute ; B 18 0 592 661 ;
+C -1 ; WX 600 ; N umacron ; B -1 -15 569 585 ;
+C -1 ; WX 600 ; N Ncaron ; B 8 -12 610 790 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ;
+C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 22 -18 594 784 ;
+C -1 ; WX 600 ; N Idotaccent ; B 77 0 523 761 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N racute ; B 47 0 580 661 ;
+C -1 ; WX 600 ; N omacron ; B 30 -15 570 585 ;
+C -1 ; WX 600 ; N Zacute ; B 62 0 539 784 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ;
+C -1 ; WX 600 ; N greaterequal ; B 26 0 523 696 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 523 626 ;
+C -1 ; WX 600 ; N tcaron ; B 47 -15 532 703 ;
+C -1 ; WX 600 ; N eogonek ; B 40 -199 563 454 ;
+C -1 ; WX 600 ; N Uogonek ; B 4 -199 596 562 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 609 761 ;
+C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N zacute ; B 81 0 520 661 ;
+C -1 ; WX 600 ; N iogonek ; B 77 -199 523 658 ;
+C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N amacron ; B 35 -15 570 585 ;
+C -1 ; WX 600 ; N sacute ; B 68 -17 535 661 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 523 618 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ;
+C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
+C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ;
+C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ;
+C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 761 ;
+C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 30 -15 668 661 ;
+C -1 ; WX 600 ; N Eogonek ; B 25 -199 576 562 ;
+C -1 ; WX 600 ; N dcroat ; B 20 -15 591 626 ;
+C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ;
+C -1 ; WX 600 ; N lcaron ; B 77 0 597 626 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 599 562 ;
+C -1 ; WX 600 ; N Lacute ; B 39 0 578 784 ;
+C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 40 -15 563 638 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N Imacron ; B 77 0 523 708 ;
+C -1 ; WX 600 ; N Lcaron ; B 39 0 637 562 ;
+C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N lessequal ; B 26 0 523 696 ;
+C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 4 -18 638 784 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N emacron ; B 40 -15 563 585 ;
+C -1 ; WX 600 ; N gbreve ; B 30 -146 580 661 ;
+C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ;
+C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 47 -250 553 582 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 22 -18 628 784 ;
+C -1 ; WX 600 ; N degree ; B 86 243 474 616 ;
+C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N Ccaron ; B 22 -18 560 790 ;
+C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N radical ; B -19 -104 473 778 ;
+C -1 ; WX 600 ; N Dcaron ; B 30 0 594 790 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 580 454 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ;
+C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 599 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 578 562 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ;
+C -1 ; WX 600 ; N Aogonek ; B -9 -199 625 562 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ;
+C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ;
+C -1 ; WX 600 ; N zdotaccent ; B 81 0 520 638 ;
+C -1 ; WX 600 ; N Ecaron ; B 25 0 560 790 ;
+C -1 ; WX 600 ; N Iogonek ; B 77 -199 523 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 20 -250 585 626 ;
+C -1 ; WX 600 ; N minus ; B 71 203 529 313 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ;
+C -1 ; WX 600 ; N ncaron ; B 18 0 592 667 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 47 -250 532 562 ;
+C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ;
+C -1 ; WX 600 ; N odieresis ; B 30 -15 570 638 ;
+C -1 ; WX 600 ; N udieresis ; B -1 -15 569 638 ;
+C -1 ; WX 600 ; N notequal ; B 12 -47 537 563 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 30 -146 580 714 ;
+C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 592 454 ;
+C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ;
+C -1 ; WX 600 ; N imacron ; B 77 0 523 585 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm
new file mode 100644
index 0000000..9d2f8a2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm
@@ -0,0 +1,343 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Mon Jun 23 16:28:46 1997
+Comment UniqueID 43049
+Comment VMusage 17529 79244
+FontName Courier-BoldOblique
+FullName Courier Bold Oblique
+FamilyName Courier
+Weight Bold
+ItalicAngle -12
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -57 -250 869 801 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 629
+Descender -157
+StdHW 84
+StdVW 106
+StartCharMetrics 315
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 215 -15 495 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 211 277 585 562 ;
+C 35 ; WX 600 ; N numbersign ; B 88 -45 641 651 ;
+C 36 ; WX 600 ; N dollar ; B 87 -126 630 666 ;
+C 37 ; WX 600 ; N percent ; B 101 -15 625 616 ;
+C 38 ; WX 600 ; N ampersand ; B 61 -15 595 543 ;
+C 39 ; WX 600 ; N quoteright ; B 229 277 543 562 ;
+C 40 ; WX 600 ; N parenleft ; B 265 -102 592 616 ;
+C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ;
+C 42 ; WX 600 ; N asterisk ; B 179 219 598 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 206 -15 427 171 ;
+C 47 ; WX 600 ; N slash ; B 90 -77 626 626 ;
+C 48 ; WX 600 ; N zero ; B 135 -15 593 616 ;
+C 49 ; WX 600 ; N one ; B 93 0 562 616 ;
+C 50 ; WX 600 ; N two ; B 61 0 594 616 ;
+C 51 ; WX 600 ; N three ; B 71 -15 571 616 ;
+C 52 ; WX 600 ; N four ; B 81 0 559 616 ;
+C 53 ; WX 600 ; N five ; B 77 -15 621 601 ;
+C 54 ; WX 600 ; N six ; B 135 -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 75 -15 592 616 ;
+C 58 ; WX 600 ; N colon ; B 205 -15 480 425 ;
+C 59 ; WX 600 ; N semicolon ; B 99 -111 481 425 ;
+C 60 ; WX 600 ; N less ; B 120 15 613 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 592 580 ;
+C 64 ; WX 600 ; N at ; B 65 -15 642 616 ;
+C 65 ; WX 600 ; N A ; B -9 0 632 562 ;
+C 66 ; WX 600 ; N B ; B 30 0 630 562 ;
+C 67 ; WX 600 ; N C ; B 74 -18 675 580 ;
+C 68 ; WX 600 ; N D ; B 30 0 664 562 ;
+C 69 ; WX 600 ; N E ; B 25 0 670 562 ;
+C 70 ; WX 600 ; N F ; B 39 0 684 562 ;
+C 71 ; WX 600 ; N G ; B 74 -18 675 580 ;
+C 72 ; WX 600 ; N H ; B 20 0 700 562 ;
+C 73 ; WX 600 ; N I ; B 77 0 643 562 ;
+C 74 ; WX 600 ; N J ; B 58 -18 721 562 ;
+C 75 ; WX 600 ; N K ; B 21 0 692 562 ;
+C 76 ; WX 600 ; N L ; B 39 0 636 562 ;
+C 77 ; WX 600 ; N M ; B -2 0 722 562 ;
+C 78 ; WX 600 ; N N ; B 8 -12 730 562 ;
+C 79 ; WX 600 ; N O ; B 74 -18 645 580 ;
+C 80 ; WX 600 ; N P ; B 48 0 643 562 ;
+C 81 ; WX 600 ; N Q ; B 83 -138 636 580 ;
+C 82 ; WX 600 ; N R ; B 24 0 617 562 ;
+C 83 ; WX 600 ; N S ; B 54 -22 673 582 ;
+C 84 ; WX 600 ; N T ; B 86 0 679 562 ;
+C 85 ; WX 600 ; N U ; B 101 -18 716 562 ;
+C 86 ; WX 600 ; N V ; B 84 0 733 562 ;
+C 87 ; WX 600 ; N W ; B 79 0 738 562 ;
+C 88 ; WX 600 ; N X ; B 12 0 690 562 ;
+C 89 ; WX 600 ; N Y ; B 109 0 709 562 ;
+C 90 ; WX 600 ; N Z ; B 62 0 637 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ;
+C 92 ; WX 600 ; N backslash ; B 222 -77 496 626 ;
+C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ;
+C 94 ; WX 600 ; N asciicircum ; B 171 250 556 616 ;
+C 95 ; WX 600 ; N underscore ; B -27 -125 585 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ;
+C 97 ; WX 600 ; N a ; B 61 -15 593 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 60 -15 645 626 ;
+C 101 ; WX 600 ; N e ; B 81 -15 605 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 40 -146 674 454 ;
+C 104 ; WX 600 ; N h ; B 18 0 615 626 ;
+C 105 ; WX 600 ; N i ; B 77 0 546 658 ;
+C 106 ; WX 600 ; N j ; B 36 -146 580 658 ;
+C 107 ; WX 600 ; N k ; B 33 0 643 626 ;
+C 108 ; WX 600 ; N l ; B 77 0 546 626 ;
+C 109 ; WX 600 ; N m ; B -22 0 649 454 ;
+C 110 ; WX 600 ; N n ; B 18 0 615 454 ;
+C 111 ; WX 600 ; N o ; B 71 -15 622 454 ;
+C 112 ; WX 600 ; N p ; B -32 -142 622 454 ;
+C 113 ; WX 600 ; N q ; B 60 -142 685 454 ;
+C 114 ; WX 600 ; N r ; B 47 0 655 454 ;
+C 115 ; WX 600 ; N s ; B 66 -17 608 459 ;
+C 116 ; WX 600 ; N t ; B 118 -15 567 562 ;
+C 117 ; WX 600 ; N u ; B 70 -15 592 439 ;
+C 118 ; WX 600 ; N v ; B 70 0 695 439 ;
+C 119 ; WX 600 ; N w ; B 53 0 712 439 ;
+C 120 ; WX 600 ; N x ; B 6 0 671 439 ;
+C 121 ; WX 600 ; N y ; B -21 -142 695 439 ;
+C 122 ; WX 600 ; N z ; B 81 0 614 439 ;
+C 123 ; WX 600 ; N braceleft ; B 203 -102 595 616 ;
+C 124 ; WX 600 ; N bar ; B 201 -250 505 750 ;
+C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ;
+C 126 ; WX 600 ; N asciitilde ; B 120 153 590 356 ;
+C 161 ; WX 600 ; N exclamdown ; B 196 -146 477 449 ;
+C 162 ; WX 600 ; N cent ; B 121 -49 605 614 ;
+C 163 ; WX 600 ; N sterling ; B 106 -28 650 611 ;
+C 164 ; WX 600 ; N fraction ; B 22 -60 708 661 ;
+C 165 ; WX 600 ; N yen ; B 98 0 710 562 ;
+C 166 ; WX 600 ; N florin ; B -57 -131 702 616 ;
+C 167 ; WX 600 ; N section ; B 74 -70 620 580 ;
+C 168 ; WX 600 ; N currency ; B 77 49 644 517 ;
+C 169 ; WX 600 ; N quotesingle ; B 303 277 493 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 62 70 639 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 195 70 545 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 165 70 514 446 ;
+C 174 ; WX 600 ; N fi ; B 12 0 644 626 ;
+C 175 ; WX 600 ; N fl ; B 12 0 644 626 ;
+C 177 ; WX 600 ; N endash ; B 108 203 602 313 ;
+C 178 ; WX 600 ; N dagger ; B 175 -70 586 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 121 -70 587 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 248 165 461 351 ;
+C 182 ; WX 600 ; N paragraph ; B 61 -70 700 580 ;
+C 183 ; WX 600 ; N bullet ; B 196 132 523 430 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 144 -142 458 143 ;
+C 185 ; WX 600 ; N quotedblbase ; B 34 -142 560 143 ;
+C 186 ; WX 600 ; N quotedblright ; B 119 277 645 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 71 70 647 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 35 -15 587 116 ;
+C 189 ; WX 600 ; N perthousand ; B -45 -15 743 616 ;
+C 191 ; WX 600 ; N questiondown ; B 100 -146 509 449 ;
+C 193 ; WX 600 ; N grave ; B 272 508 503 661 ;
+C 194 ; WX 600 ; N acute ; B 312 508 609 661 ;
+C 195 ; WX 600 ; N circumflex ; B 212 483 607 657 ;
+C 196 ; WX 600 ; N tilde ; B 199 493 643 636 ;
+C 197 ; WX 600 ; N macron ; B 195 505 637 585 ;
+C 198 ; WX 600 ; N breve ; B 217 468 652 631 ;
+C 199 ; WX 600 ; N dotaccent ; B 348 498 493 638 ;
+C 200 ; WX 600 ; N dieresis ; B 246 498 595 638 ;
+C 202 ; WX 600 ; N ring ; B 319 481 528 678 ;
+C 203 ; WX 600 ; N cedilla ; B 168 -206 368 0 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 171 488 729 661 ;
+C 206 ; WX 600 ; N ogonek ; B 143 -199 367 0 ;
+C 207 ; WX 600 ; N caron ; B 238 493 633 667 ;
+C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ;
+C 225 ; WX 600 ; N AE ; B -29 0 708 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 188 196 526 580 ;
+C 232 ; WX 600 ; N Lslash ; B 39 0 636 562 ;
+C 233 ; WX 600 ; N Oslash ; B 48 -22 673 584 ;
+C 234 ; WX 600 ; N OE ; B 26 0 701 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 188 196 543 580 ;
+C 241 ; WX 600 ; N ae ; B 21 -15 652 454 ;
+C 245 ; WX 600 ; N dotlessi ; B 77 0 546 439 ;
+C 248 ; WX 600 ; N lslash ; B 77 0 587 626 ;
+C 249 ; WX 600 ; N oslash ; B 54 -24 638 463 ;
+C 250 ; WX 600 ; N oe ; B 18 -15 662 454 ;
+C 251 ; WX 600 ; N germandbls ; B 22 -15 629 626 ;
+C -1 ; WX 600 ; N Idieresis ; B 77 0 643 761 ;
+C -1 ; WX 600 ; N eacute ; B 81 -15 609 661 ;
+C -1 ; WX 600 ; N abreve ; B 61 -15 658 661 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 70 -15 769 661 ;
+C -1 ; WX 600 ; N ecaron ; B 81 -15 633 667 ;
+C -1 ; WX 600 ; N Ydieresis ; B 109 0 709 761 ;
+C -1 ; WX 600 ; N divide ; B 114 16 596 500 ;
+C -1 ; WX 600 ; N Yacute ; B 109 0 709 784 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 632 780 ;
+C -1 ; WX 600 ; N aacute ; B 61 -15 609 661 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 716 780 ;
+C -1 ; WX 600 ; N yacute ; B -21 -142 695 661 ;
+C -1 ; WX 600 ; N scommaaccent ; B 66 -250 608 459 ;
+C -1 ; WX 600 ; N ecircumflex ; B 81 -15 607 657 ;
+C -1 ; WX 600 ; N Uring ; B 101 -18 716 801 ;
+C -1 ; WX 600 ; N Udieresis ; B 101 -18 716 761 ;
+C -1 ; WX 600 ; N aogonek ; B 61 -199 593 454 ;
+C -1 ; WX 600 ; N Uacute ; B 101 -18 716 784 ;
+C -1 ; WX 600 ; N uogonek ; B 70 -199 592 439 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 670 761 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 664 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 151 -250 385 -57 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Emacron ; B 25 0 670 708 ;
+C -1 ; WX 600 ; N ccaron ; B 81 -15 633 667 ;
+C -1 ; WX 600 ; N aring ; B 61 -15 593 678 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 730 562 ;
+C -1 ; WX 600 ; N lacute ; B 77 0 639 801 ;
+C -1 ; WX 600 ; N agrave ; B 61 -15 593 661 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 86 -250 679 562 ;
+C -1 ; WX 600 ; N Cacute ; B 74 -18 675 784 ;
+C -1 ; WX 600 ; N atilde ; B 61 -15 643 636 ;
+C -1 ; WX 600 ; N Edotaccent ; B 25 0 670 761 ;
+C -1 ; WX 600 ; N scaron ; B 66 -17 633 667 ;
+C -1 ; WX 600 ; N scedilla ; B 66 -206 608 459 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 609 661 ;
+C -1 ; WX 600 ; N lozenge ; B 145 0 614 740 ;
+C -1 ; WX 600 ; N Rcaron ; B 24 0 659 790 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 74 -250 675 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 70 -15 597 657 ;
+C -1 ; WX 600 ; N acircumflex ; B 61 -15 607 657 ;
+C -1 ; WX 600 ; N Amacron ; B -9 0 633 708 ;
+C -1 ; WX 600 ; N rcaron ; B 47 0 655 667 ;
+C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 62 0 637 761 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 620 562 ;
+C -1 ; WX 600 ; N Omacron ; B 74 -18 663 708 ;
+C -1 ; WX 600 ; N Racute ; B 24 0 665 784 ;
+C -1 ; WX 600 ; N Sacute ; B 54 -22 673 784 ;
+C -1 ; WX 600 ; N dcaron ; B 60 -15 861 626 ;
+C -1 ; WX 600 ; N Umacron ; B 101 -18 716 708 ;
+C -1 ; WX 600 ; N uring ; B 70 -15 592 678 ;
+C -1 ; WX 600 ; N threesuperior ; B 193 222 526 616 ;
+C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 632 784 ;
+C -1 ; WX 600 ; N Abreve ; B -9 0 684 784 ;
+C -1 ; WX 600 ; N multiply ; B 104 39 606 478 ;
+C -1 ; WX 600 ; N uacute ; B 70 -15 599 661 ;
+C -1 ; WX 600 ; N Tcaron ; B 86 0 679 790 ;
+C -1 ; WX 600 ; N partialdiff ; B 91 -38 627 728 ;
+C -1 ; WX 600 ; N ydieresis ; B -21 -142 695 638 ;
+C -1 ; WX 600 ; N Nacute ; B 8 -12 730 784 ;
+C -1 ; WX 600 ; N icircumflex ; B 77 0 577 657 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 670 780 ;
+C -1 ; WX 600 ; N adieresis ; B 61 -15 595 638 ;
+C -1 ; WX 600 ; N edieresis ; B 81 -15 605 638 ;
+C -1 ; WX 600 ; N cacute ; B 81 -15 649 661 ;
+C -1 ; WX 600 ; N nacute ; B 18 0 639 661 ;
+C -1 ; WX 600 ; N umacron ; B 70 -15 637 585 ;
+C -1 ; WX 600 ; N Ncaron ; B 8 -12 730 790 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 643 784 ;
+C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ;
+C -1 ; WX 600 ; N brokenbar ; B 217 -175 489 675 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 74 -18 684 784 ;
+C -1 ; WX 600 ; N Idotaccent ; B 77 0 643 761 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 672 706 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 670 784 ;
+C -1 ; WX 600 ; N racute ; B 47 0 655 661 ;
+C -1 ; WX 600 ; N omacron ; B 71 -15 637 585 ;
+C -1 ; WX 600 ; N Zacute ; B 62 0 665 784 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ;
+C -1 ; WX 600 ; N greaterequal ; B 26 0 627 696 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 74 -206 675 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 546 626 ;
+C -1 ; WX 600 ; N tcaron ; B 118 -15 627 703 ;
+C -1 ; WX 600 ; N eogonek ; B 81 -199 605 454 ;
+C -1 ; WX 600 ; N Uogonek ; B 101 -199 716 562 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 655 784 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 632 761 ;
+C -1 ; WX 600 ; N egrave ; B 81 -15 605 661 ;
+C -1 ; WX 600 ; N zacute ; B 81 0 614 661 ;
+C -1 ; WX 600 ; N iogonek ; B 77 -199 546 658 ;
+C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N oacute ; B 71 -15 649 661 ;
+C -1 ; WX 600 ; N amacron ; B 61 -15 637 585 ;
+C -1 ; WX 600 ; N sacute ; B 66 -17 609 661 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 561 618 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ;
+C -1 ; WX 600 ; N Ugrave ; B 101 -18 716 784 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
+C -1 ; WX 600 ; N thorn ; B -32 -142 622 626 ;
+C -1 ; WX 600 ; N twosuperior ; B 191 230 542 616 ;
+C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 761 ;
+C -1 ; WX 600 ; N mu ; B 49 -142 592 439 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 546 661 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 71 -15 809 661 ;
+C -1 ; WX 600 ; N Eogonek ; B 25 -199 670 562 ;
+C -1 ; WX 600 ; N dcroat ; B 60 -15 712 626 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -60 699 661 ;
+C -1 ; WX 600 ; N Scedilla ; B 54 -206 673 582 ;
+C -1 ; WX 600 ; N lcaron ; B 77 0 731 626 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 692 562 ;
+C -1 ; WX 600 ; N Lacute ; B 39 0 636 784 ;
+C -1 ; WX 600 ; N trademark ; B 86 230 869 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 81 -15 605 638 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 643 784 ;
+C -1 ; WX 600 ; N Imacron ; B 77 0 663 708 ;
+C -1 ; WX 600 ; N Lcaron ; B 39 0 757 562 ;
+C -1 ; WX 600 ; N onehalf ; B 22 -60 716 661 ;
+C -1 ; WX 600 ; N lessequal ; B 26 0 671 696 ;
+C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 643 636 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 101 -18 805 784 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 670 784 ;
+C -1 ; WX 600 ; N emacron ; B 81 -15 637 585 ;
+C -1 ; WX 600 ; N gbreve ; B 40 -146 674 661 ;
+C -1 ; WX 600 ; N onequarter ; B 13 -60 707 661 ;
+C -1 ; WX 600 ; N Scaron ; B 54 -22 689 790 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 54 -250 673 582 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 74 -18 795 784 ;
+C -1 ; WX 600 ; N degree ; B 173 243 570 616 ;
+C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ;
+C -1 ; WX 600 ; N Ccaron ; B 74 -18 689 790 ;
+C -1 ; WX 600 ; N ugrave ; B 70 -15 592 661 ;
+C -1 ; WX 600 ; N radical ; B 67 -104 635 778 ;
+C -1 ; WX 600 ; N Dcaron ; B 30 0 664 790 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 655 454 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 730 759 ;
+C -1 ; WX 600 ; N otilde ; B 71 -15 643 636 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 617 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 636 562 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 669 759 ;
+C -1 ; WX 600 ; N Aogonek ; B -9 -199 632 562 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 632 801 ;
+C -1 ; WX 600 ; N Otilde ; B 74 -18 669 759 ;
+C -1 ; WX 600 ; N zdotaccent ; B 81 0 614 638 ;
+C -1 ; WX 600 ; N Ecaron ; B 25 0 670 790 ;
+C -1 ; WX 600 ; N Iogonek ; B 77 -199 643 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 33 -250 643 626 ;
+C -1 ; WX 600 ; N minus ; B 114 203 596 313 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 643 780 ;
+C -1 ; WX 600 ; N ncaron ; B 18 0 633 667 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 118 -250 567 562 ;
+C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ;
+C -1 ; WX 600 ; N odieresis ; B 71 -15 622 638 ;
+C -1 ; WX 600 ; N udieresis ; B 70 -15 595 638 ;
+C -1 ; WX 600 ; N notequal ; B 30 -47 626 563 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 40 -146 674 714 ;
+C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 643 667 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 615 454 ;
+C -1 ; WX 600 ; N onesuperior ; B 212 230 514 616 ;
+C -1 ; WX 600 ; N imacron ; B 77 0 575 585 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Oblique.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Oblique.afm
new file mode 100644
index 0000000..d7f1b78
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Courier-Oblique.afm
@@ -0,0 +1,343 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 17:37:52 1997
+Comment UniqueID 43051
+Comment VMusage 16248 75829
+FontName Courier-Oblique
+FullName Courier Oblique
+FamilyName Courier
+Weight Medium
+ItalicAngle -12
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -27 -250 849 805 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StdHW 51
+StdVW 51
+StartCharMetrics 315
+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 373 537 478 640 ;
+C 200 ; WX 600 ; N dieresis ; B 272 537 579 640 ;
+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 189 -172 377 4 ;
+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 587 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 Idieresis ; B 96 0 623 753 ;
+C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ;
+C -1 ; WX 600 ; N abreve ; B 76 -15 576 609 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 101 -15 723 672 ;
+C -1 ; WX 600 ; N ecaron ; B 106 -15 614 669 ;
+C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 753 ;
+C -1 ; WX 600 ; N divide ; B 136 48 573 467 ;
+C -1 ; WX 600 ; N Yacute ; B 133 0 695 805 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 787 ;
+C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 787 ;
+C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ;
+C -1 ; WX 600 ; N scommaaccent ; B 78 -250 584 441 ;
+C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ;
+C -1 ; WX 600 ; N Uring ; B 125 -18 702 760 ;
+C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 753 ;
+C -1 ; WX 600 ; N aogonek ; B 76 -172 569 441 ;
+C -1 ; WX 600 ; N Uacute ; B 125 -18 702 805 ;
+C -1 ; WX 600 ; N uogonek ; B 101 -172 572 426 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 660 753 ;
+C -1 ; WX 600 ; N Dcroat ; B 43 0 645 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 145 -250 323 -58 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Emacron ; B 53 0 660 698 ;
+C -1 ; WX 600 ; N ccaron ; B 106 -15 614 669 ;
+C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 712 562 ;
+C -1 ; WX 600 ; N lacute ; B 95 0 640 805 ;
+C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 108 -250 665 562 ;
+C -1 ; WX 600 ; N Cacute ; B 93 -18 655 805 ;
+C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ;
+C -1 ; WX 600 ; N Edotaccent ; B 53 0 660 753 ;
+C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ;
+C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ;
+C -1 ; WX 600 ; N lozenge ; B 94 0 519 706 ;
+C -1 ; WX 600 ; N Rcaron ; B 38 0 642 802 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 83 -250 645 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ;
+C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ;
+C -1 ; WX 600 ; N Amacron ; B 3 0 607 698 ;
+C -1 ; WX 600 ; N rcaron ; B 60 0 636 669 ;
+C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 86 0 610 753 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ;
+C -1 ; WX 600 ; N Omacron ; B 94 -18 628 698 ;
+C -1 ; WX 600 ; N Racute ; B 38 0 670 805 ;
+C -1 ; WX 600 ; N Sacute ; B 76 -20 650 805 ;
+C -1 ; WX 600 ; N dcaron ; B 85 -15 849 629 ;
+C -1 ; WX 600 ; N Umacron ; B 125 -18 702 698 ;
+C -1 ; WX 600 ; N uring ; B 101 -15 572 627 ;
+C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ;
+C -1 ; WX 600 ; N Ograve ; B 94 -18 625 805 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 607 805 ;
+C -1 ; WX 600 ; N Abreve ; B 3 0 607 732 ;
+C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ;
+C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ;
+C -1 ; WX 600 ; N Tcaron ; B 108 0 665 802 ;
+C -1 ; WX 600 ; N partialdiff ; B 45 -38 546 710 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 620 ;
+C -1 ; WX 600 ; N Nacute ; B 7 -13 712 805 ;
+C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 787 ;
+C -1 ; WX 600 ; N adieresis ; B 76 -15 575 620 ;
+C -1 ; WX 600 ; N edieresis ; B 106 -15 598 620 ;
+C -1 ; WX 600 ; N cacute ; B 106 -15 612 672 ;
+C -1 ; WX 600 ; N nacute ; B 26 0 602 672 ;
+C -1 ; WX 600 ; N umacron ; B 101 -15 600 565 ;
+C -1 ; WX 600 ; N Ncaron ; B 7 -13 712 802 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 640 805 ;
+C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ;
+C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 83 -18 645 732 ;
+C -1 ; WX 600 ; N Idotaccent ; B 96 0 623 753 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 670 706 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 660 805 ;
+C -1 ; WX 600 ; N racute ; B 60 0 636 672 ;
+C -1 ; WX 600 ; N omacron ; B 102 -15 600 565 ;
+C -1 ; WX 600 ; N Zacute ; B 86 0 670 805 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 642 802 ;
+C -1 ; WX 600 ; N greaterequal ; B 98 0 594 710 ;
+C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 515 629 ;
+C -1 ; WX 600 ; N tcaron ; B 167 -15 587 717 ;
+C -1 ; WX 600 ; N eogonek ; B 106 -172 598 441 ;
+C -1 ; WX 600 ; N Uogonek ; B 124 -172 702 562 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 660 805 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 607 753 ;
+C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ;
+C -1 ; WX 600 ; N zacute ; B 99 0 612 672 ;
+C -1 ; WX 600 ; N iogonek ; B 95 -172 515 657 ;
+C -1 ; WX 600 ; N Oacute ; B 94 -18 640 805 ;
+C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ;
+C -1 ; WX 600 ; N amacron ; B 76 -15 600 565 ;
+C -1 ; WX 600 ; N sacute ; B 78 -15 612 672 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 545 620 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 787 ;
+C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 805 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
+C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ;
+C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ;
+C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 753 ;
+C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 102 -15 723 672 ;
+C -1 ; WX 600 ; N Eogonek ; B 53 -172 660 562 ;
+C -1 ; WX 600 ; N dcroat ; B 85 -15 704 629 ;
+C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ;
+C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ;
+C -1 ; WX 600 ; N lcaron ; B 95 0 667 629 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 671 562 ;
+C -1 ; WX 600 ; N Lacute ; B 47 0 607 805 ;
+C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 106 -15 598 620 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 623 805 ;
+C -1 ; WX 600 ; N Imacron ; B 96 0 628 698 ;
+C -1 ; WX 600 ; N Lcaron ; B 47 0 632 562 ;
+C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ;
+C -1 ; WX 600 ; N lessequal ; B 98 0 645 710 ;
+C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 125 -18 761 805 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 670 805 ;
+C -1 ; WX 600 ; N emacron ; B 106 -15 600 565 ;
+C -1 ; WX 600 ; N gbreve ; B 61 -157 657 609 ;
+C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ;
+C -1 ; WX 600 ; N Scaron ; B 76 -20 672 802 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 76 -250 650 580 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 94 -18 751 805 ;
+C -1 ; WX 600 ; N degree ; B 214 269 576 622 ;
+C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ;
+C -1 ; WX 600 ; N Ccaron ; B 93 -18 672 802 ;
+C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ;
+C -1 ; WX 600 ; N radical ; B 85 -15 765 792 ;
+C -1 ; WX 600 ; N Dcaron ; B 43 0 645 802 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 636 441 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 729 ;
+C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 598 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 607 562 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 655 729 ;
+C -1 ; WX 600 ; N Aogonek ; B 3 -172 607 562 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 607 750 ;
+C -1 ; WX 600 ; N Otilde ; B 94 -18 655 729 ;
+C -1 ; WX 600 ; N zdotaccent ; B 99 0 593 620 ;
+C -1 ; WX 600 ; N Ecaron ; B 53 0 660 802 ;
+C -1 ; WX 600 ; N Iogonek ; B 96 -172 623 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 58 -250 633 629 ;
+C -1 ; WX 600 ; N minus ; B 129 232 580 283 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 787 ;
+C -1 ; WX 600 ; N ncaron ; B 26 0 614 669 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 165 -250 561 561 ;
+C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ;
+C -1 ; WX 600 ; N odieresis ; B 102 -15 588 620 ;
+C -1 ; WX 600 ; N udieresis ; B 101 -15 575 620 ;
+C -1 ; WX 600 ; N notequal ; B 43 -16 621 529 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 61 -157 657 708 ;
+C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 585 441 ;
+C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ;
+C -1 ; WX 600 ; N imacron ; B 95 0 543 565 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Courier.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Courier.afm
new file mode 100644
index 0000000..f3fe4c1
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Courier.afm
@@ -0,0 +1,343 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 17:27:09 1997
+Comment UniqueID 43050
+Comment VMusage 39754 50779
+FontName Courier
+FullName Courier
+FamilyName Courier
+Weight Medium
+ItalicAngle 0
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -23 -250 715 805 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StdHW 51
+StdVW 51
+StartCharMetrics 315
+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 537 352 640 ;
+C 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ;
+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 211 -172 407 4 ;
+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 Idieresis ; B 96 0 504 753 ;
+C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ;
+C -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ;
+C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ;
+C -1 ; WX 600 ; N divide ; B 87 48 513 467 ;
+C -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ;
+C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ;
+C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;
+C -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ;
+C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;
+C -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ;
+C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ;
+C -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ;
+C -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ;
+C -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ;
+C -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ;
+C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ;
+C -1 ; WX 600 ; N lacute ; B 95 0 505 805 ;
+C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ;
+C -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ;
+C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;
+C -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ;
+C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;
+C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ;
+C -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;
+C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;
+C -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ;
+C -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ;
+C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;
+C -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ;
+C -1 ; WX 600 ; N Racute ; B 38 0 588 805 ;
+C -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ;
+C -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ;
+C -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ;
+C -1 ; WX 600 ; N uring ; B 21 -15 562 627 ;
+C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;
+C -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ;
+C -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ;
+C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;
+C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ;
+C -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ;
+C -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ;
+C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ;
+C -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ;
+C -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ;
+C -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ;
+C -1 ; WX 600 ; N nacute ; B 26 0 575 672 ;
+C -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ;
+C -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ;
+C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;
+C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ;
+C -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ;
+C -1 ; WX 600 ; N racute ; B 60 0 559 672 ;
+C -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ;
+C -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ;
+C -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ;
+C -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ;
+C -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ;
+C -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ;
+C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N zacute ; B 99 0 502 672 ;
+C -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ;
+C -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ;
+C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ;
+C -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ;
+C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
+C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;
+C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;
+C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ;
+C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ;
+C -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ;
+C -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;
+C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;
+C -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ;
+C -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ;
+C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ;
+C -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ;
+C -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ;
+C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;
+C -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ;
+C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ;
+C -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ;
+C -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ;
+C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;
+C -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ;
+C -1 ; WX 600 ; N degree ; B 123 269 477 622 ;
+C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ;
+C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N radical ; B 3 -15 597 792 ;
+C -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ;
+C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ;
+C -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 597 750 ;
+C -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ;
+C -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ;
+C -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ;
+C -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ;
+C -1 ; WX 600 ; N minus ; B 80 232 520 283 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ;
+C -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ;
+C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;
+C -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ;
+C -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ;
+C -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ;
+C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ;
+C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;
+C -1 ; WX 600 ; N imacron ; B 95 0 505 565 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java b/LibrarySource/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java
new file mode 100644
index 0000000..37de4bc
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package com.lowagie.text.pdf.fonts;
+
+/**
+ * A class to facilitate the loading of resources
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class FontsResourceAnchor {
+    
+    /**
+     * Creates a FontsResourceAnchor
+     */
+    public FontsResourceAnchor() {
+    }
+    
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm
new file mode 100644
index 0000000..3991be4
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm
@@ -0,0 +1,2828 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:43:52 1997
+Comment UniqueID 43052
+Comment VMusage 37169 48194
+FontName Helvetica-Bold
+FullName Helvetica Bold
+FamilyName Helvetica
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -170 -228 1003 962 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StdHW 118
+StdVW 140
+StartCharMetrics 315
+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 -225 196 775 ;
+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 401 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 401 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 278 ; N Idieresis ; B -21 0 300 915 ;
+C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ;
+C -1 ; WX 556 ; N abreve ; B 29 -14 527 750 ;
+C -1 ; WX 611 ; N uhungarumlaut ; B 66 -14 625 750 ;
+C -1 ; WX 556 ; N ecaron ; B 23 -14 528 750 ;
+C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ;
+C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ;
+C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ;
+C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ;
+C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ;
+C -1 ; WX 556 ; N scommaaccent ; B 30 -228 519 546 ;
+C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ;
+C -1 ; WX 722 ; N Uring ; B 72 -19 651 962 ;
+C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ;
+C -1 ; WX 556 ; N aogonek ; B 29 -224 545 546 ;
+C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ;
+C -1 ; WX 611 ; N uogonek ; B 66 -228 545 532 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ;
+C -1 ; WX 722 ; N Dcroat ; B -5 0 685 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 64 -228 199 -50 ;
+C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ;
+C -1 ; WX 667 ; N Emacron ; B 76 0 621 864 ;
+C -1 ; WX 556 ; N ccaron ; B 34 -14 524 750 ;
+C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 654 718 ;
+C -1 ; WX 278 ; N lacute ; B 69 0 329 936 ;
+C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 14 -228 598 718 ;
+C -1 ; WX 722 ; N Cacute ; B 44 -19 684 936 ;
+C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ;
+C -1 ; WX 667 ; N Edotaccent ; B 76 0 621 915 ;
+C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ;
+C -1 ; WX 556 ; N scedilla ; B 30 -228 519 546 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 76 0 677 936 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 44 -228 713 737 ;
+C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ;
+C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ;
+C -1 ; WX 722 ; N Amacron ; B 20 0 702 864 ;
+C -1 ; WX 389 ; N rcaron ; B 18 0 373 750 ;
+C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 25 0 586 915 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ;
+C -1 ; WX 778 ; N Omacron ; B 44 -19 734 864 ;
+C -1 ; WX 722 ; N Racute ; B 76 0 677 936 ;
+C -1 ; WX 667 ; N Sacute ; B 39 -19 629 936 ;
+C -1 ; WX 743 ; N dcaron ; B 34 -14 750 718 ;
+C -1 ; WX 722 ; N Umacron ; B 72 -19 651 864 ;
+C -1 ; WX 611 ; N uring ; B 66 -14 545 776 ;
+C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ;
+C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Abreve ; B 20 0 702 936 ;
+C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ;
+C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ;
+C -1 ; WX 611 ; N Tcaron ; B 14 0 598 936 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ;
+C -1 ; WX 722 ; N Nacute ; B 69 0 654 936 ;
+C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ;
+C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ;
+C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ;
+C -1 ; WX 556 ; N cacute ; B 34 -14 524 750 ;
+C -1 ; WX 611 ; N nacute ; B 65 0 546 750 ;
+C -1 ; WX 611 ; N umacron ; B 66 -14 545 678 ;
+C -1 ; WX 722 ; N Ncaron ; B 69 0 654 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ;
+C -1 ; WX 280 ; N brokenbar ; B 84 -150 196 700 ;
+C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 44 -19 713 936 ;
+C -1 ; WX 278 ; N Idotaccent ; B 64 0 214 915 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ;
+C -1 ; WX 389 ; N racute ; B 64 0 384 750 ;
+C -1 ; WX 611 ; N omacron ; B 34 -14 578 678 ;
+C -1 ; WX 611 ; N Zacute ; B 25 0 586 936 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 69 -228 213 718 ;
+C -1 ; WX 389 ; N tcaron ; B 10 -6 421 878 ;
+C -1 ; WX 556 ; N eogonek ; B 23 -228 528 546 ;
+C -1 ; WX 722 ; N Uogonek ; B 72 -228 651 718 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ;
+C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ;
+C -1 ; WX 500 ; N zacute ; B 20 0 480 750 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -224 249 725 ;
+C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ;
+C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ;
+C -1 ; WX 556 ; N amacron ; B 29 -14 527 678 ;
+C -1 ; WX 556 ; N sacute ; B 30 -14 519 750 ;
+C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ;
+C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ;
+C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ;
+C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ;
+C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ;
+C -1 ; WX 611 ; N ohungarumlaut ; B 34 -14 625 750 ;
+C -1 ; WX 667 ; N Eogonek ; B 76 -224 639 718 ;
+C -1 ; WX 611 ; N dcroat ; B 34 -14 650 718 ;
+C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ;
+C -1 ; WX 667 ; N Scedilla ; B 39 -228 629 737 ;
+C -1 ; WX 400 ; N lcaron ; B 69 0 408 718 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 722 718 ;
+C -1 ; WX 611 ; N Lacute ; B 76 0 583 936 ;
+C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 23 -14 528 729 ;
+C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ;
+C -1 ; WX 278 ; N Imacron ; B -33 0 312 864 ;
+C -1 ; WX 611 ; N Lcaron ; B 76 0 583 718 ;
+C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 72 -19 681 936 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ;
+C -1 ; WX 556 ; N emacron ; B 23 -14 528 678 ;
+C -1 ; WX 611 ; N gbreve ; B 40 -217 553 750 ;
+C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ;
+C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 39 -228 629 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 44 -19 734 936 ;
+C -1 ; WX 400 ; N degree ; B 57 426 343 712 ;
+C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ;
+C -1 ; WX 722 ; N Ccaron ; B 44 -19 684 936 ;
+C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 76 0 685 936 ;
+C -1 ; WX 389 ; N rcommaaccent ; B 64 -228 373 546 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ;
+C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 677 718 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 583 718 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ;
+C -1 ; WX 722 ; N Aogonek ; B 20 -224 742 718 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ;
+C -1 ; WX 500 ; N zdotaccent ; B 20 0 480 729 ;
+C -1 ; WX 667 ; N Ecaron ; B 76 0 621 936 ;
+C -1 ; WX 278 ; N Iogonek ; B -11 -228 222 718 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 562 718 ;
+C -1 ; WX 584 ; N minus ; B 40 197 544 309 ;
+C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ;
+C -1 ; WX 611 ; N ncaron ; B 65 0 546 750 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 10 -228 309 676 ;
+C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ;
+C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ;
+C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 611 ; N gcommaaccent ; B 40 -217 553 850 ;
+C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ;
+C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 546 546 ;
+C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ;
+C -1 ; WX 278 ; N imacron ; B -8 0 285 678 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2481
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -50
+KPX A Gbreve -50
+KPX A Gcommaaccent -50
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -90
+KPX A Tcaron -90
+KPX A Tcommaaccent -90
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -80
+KPX A W -60
+KPX A Y -110
+KPX A Yacute -110
+KPX A Ydieresis -110
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -30
+KPX A y -30
+KPX A yacute -30
+KPX A ydieresis -30
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -50
+KPX Aacute Gbreve -50
+KPX Aacute Gcommaaccent -50
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -90
+KPX Aacute Tcaron -90
+KPX Aacute Tcommaaccent -90
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -80
+KPX Aacute W -60
+KPX Aacute Y -110
+KPX Aacute Yacute -110
+KPX Aacute Ydieresis -110
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -30
+KPX Aacute y -30
+KPX Aacute yacute -30
+KPX Aacute ydieresis -30
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -50
+KPX Abreve Gbreve -50
+KPX Abreve Gcommaaccent -50
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -90
+KPX Abreve Tcaron -90
+KPX Abreve Tcommaaccent -90
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -80
+KPX Abreve W -60
+KPX Abreve Y -110
+KPX Abreve Yacute -110
+KPX Abreve Ydieresis -110
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -30
+KPX Abreve y -30
+KPX Abreve yacute -30
+KPX Abreve ydieresis -30
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -50
+KPX Acircumflex Gbreve -50
+KPX Acircumflex Gcommaaccent -50
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -90
+KPX Acircumflex Tcaron -90
+KPX Acircumflex Tcommaaccent -90
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -80
+KPX Acircumflex W -60
+KPX Acircumflex Y -110
+KPX Acircumflex Yacute -110
+KPX Acircumflex Ydieresis -110
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -30
+KPX Acircumflex y -30
+KPX Acircumflex yacute -30
+KPX Acircumflex ydieresis -30
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -50
+KPX Adieresis Gbreve -50
+KPX Adieresis Gcommaaccent -50
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -90
+KPX Adieresis Tcaron -90
+KPX Adieresis Tcommaaccent -90
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -80
+KPX Adieresis W -60
+KPX Adieresis Y -110
+KPX Adieresis Yacute -110
+KPX Adieresis Ydieresis -110
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -30
+KPX Adieresis y -30
+KPX Adieresis yacute -30
+KPX Adieresis ydieresis -30
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -50
+KPX Agrave Gbreve -50
+KPX Agrave Gcommaaccent -50
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -90
+KPX Agrave Tcaron -90
+KPX Agrave Tcommaaccent -90
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -80
+KPX Agrave W -60
+KPX Agrave Y -110
+KPX Agrave Yacute -110
+KPX Agrave Ydieresis -110
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -30
+KPX Agrave y -30
+KPX Agrave yacute -30
+KPX Agrave ydieresis -30
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -50
+KPX Amacron Gbreve -50
+KPX Amacron Gcommaaccent -50
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -90
+KPX Amacron Tcaron -90
+KPX Amacron Tcommaaccent -90
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -80
+KPX Amacron W -60
+KPX Amacron Y -110
+KPX Amacron Yacute -110
+KPX Amacron Ydieresis -110
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -30
+KPX Amacron y -30
+KPX Amacron yacute -30
+KPX Amacron ydieresis -30
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -50
+KPX Aogonek Gbreve -50
+KPX Aogonek Gcommaaccent -50
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -90
+KPX Aogonek Tcaron -90
+KPX Aogonek Tcommaaccent -90
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -80
+KPX Aogonek W -60
+KPX Aogonek Y -110
+KPX Aogonek Yacute -110
+KPX Aogonek Ydieresis -110
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -30
+KPX Aogonek y -30
+KPX Aogonek yacute -30
+KPX Aogonek ydieresis -30
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -50
+KPX Aring Gbreve -50
+KPX Aring Gcommaaccent -50
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -90
+KPX Aring Tcaron -90
+KPX Aring Tcommaaccent -90
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -80
+KPX Aring W -60
+KPX Aring Y -110
+KPX Aring Yacute -110
+KPX Aring Ydieresis -110
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -30
+KPX Aring y -30
+KPX Aring yacute -30
+KPX Aring ydieresis -30
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -50
+KPX Atilde Gbreve -50
+KPX Atilde Gcommaaccent -50
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -90
+KPX Atilde Tcaron -90
+KPX Atilde Tcommaaccent -90
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -80
+KPX Atilde W -60
+KPX Atilde Y -110
+KPX Atilde Yacute -110
+KPX Atilde Ydieresis -110
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -30
+KPX Atilde y -30
+KPX Atilde yacute -30
+KPX Atilde ydieresis -30
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -40
+KPX D Y -70
+KPX D Yacute -70
+KPX D Ydieresis -70
+KPX D comma -30
+KPX D period -30
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -70
+KPX Dcaron Yacute -70
+KPX Dcaron Ydieresis -70
+KPX Dcaron comma -30
+KPX Dcaron period -30
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -70
+KPX Dcroat Yacute -70
+KPX Dcroat Ydieresis -70
+KPX Dcroat comma -30
+KPX Dcroat period -30
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -20
+KPX F aacute -20
+KPX F abreve -20
+KPX F acircumflex -20
+KPX F adieresis -20
+KPX F agrave -20
+KPX F amacron -20
+KPX F aogonek -20
+KPX F aring -20
+KPX F atilde -20
+KPX F comma -100
+KPX F period -100
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J comma -20
+KPX J period -20
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -15
+KPX K eacute -15
+KPX K ecaron -15
+KPX K ecircumflex -15
+KPX K edieresis -15
+KPX K edotaccent -15
+KPX K egrave -15
+KPX K emacron -15
+KPX K eogonek -15
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -15
+KPX Kcommaaccent eacute -15
+KPX Kcommaaccent ecaron -15
+KPX Kcommaaccent ecircumflex -15
+KPX Kcommaaccent edieresis -15
+KPX Kcommaaccent edotaccent -15
+KPX Kcommaaccent egrave -15
+KPX Kcommaaccent emacron -15
+KPX Kcommaaccent eogonek -15
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -90
+KPX L Tcaron -90
+KPX L Tcommaaccent -90
+KPX L V -110
+KPX L W -80
+KPX L Y -120
+KPX L Yacute -120
+KPX L Ydieresis -120
+KPX L quotedblright -140
+KPX L quoteright -140
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -90
+KPX Lacute Tcaron -90
+KPX Lacute Tcommaaccent -90
+KPX Lacute V -110
+KPX Lacute W -80
+KPX Lacute Y -120
+KPX Lacute Yacute -120
+KPX Lacute Ydieresis -120
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -140
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -90
+KPX Lcommaaccent Tcaron -90
+KPX Lcommaaccent Tcommaaccent -90
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -80
+KPX Lcommaaccent Y -120
+KPX Lcommaaccent Yacute -120
+KPX Lcommaaccent Ydieresis -120
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -140
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -90
+KPX Lslash Tcaron -90
+KPX Lslash Tcommaaccent -90
+KPX Lslash V -110
+KPX Lslash W -80
+KPX Lslash Y -120
+KPX Lslash Yacute -120
+KPX Lslash Ydieresis -120
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -140
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -50
+KPX O Aacute -50
+KPX O Abreve -50
+KPX O Acircumflex -50
+KPX O Adieresis -50
+KPX O Agrave -50
+KPX O Amacron -50
+KPX O Aogonek -50
+KPX O Aring -50
+KPX O Atilde -50
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -50
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -50
+KPX Oacute Aacute -50
+KPX Oacute Abreve -50
+KPX Oacute Acircumflex -50
+KPX Oacute Adieresis -50
+KPX Oacute Agrave -50
+KPX Oacute Amacron -50
+KPX Oacute Aogonek -50
+KPX Oacute Aring -50
+KPX Oacute Atilde -50
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -50
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -50
+KPX Ocircumflex Aacute -50
+KPX Ocircumflex Abreve -50
+KPX Ocircumflex Acircumflex -50
+KPX Ocircumflex Adieresis -50
+KPX Ocircumflex Agrave -50
+KPX Ocircumflex Amacron -50
+KPX Ocircumflex Aogonek -50
+KPX Ocircumflex Aring -50
+KPX Ocircumflex Atilde -50
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -50
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -50
+KPX Odieresis Aacute -50
+KPX Odieresis Abreve -50
+KPX Odieresis Acircumflex -50
+KPX Odieresis Adieresis -50
+KPX Odieresis Agrave -50
+KPX Odieresis Amacron -50
+KPX Odieresis Aogonek -50
+KPX Odieresis Aring -50
+KPX Odieresis Atilde -50
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -50
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -50
+KPX Ograve Aacute -50
+KPX Ograve Abreve -50
+KPX Ograve Acircumflex -50
+KPX Ograve Adieresis -50
+KPX Ograve Agrave -50
+KPX Ograve Amacron -50
+KPX Ograve Aogonek -50
+KPX Ograve Aring -50
+KPX Ograve Atilde -50
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -50
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -50
+KPX Ohungarumlaut Aacute -50
+KPX Ohungarumlaut Abreve -50
+KPX Ohungarumlaut Acircumflex -50
+KPX Ohungarumlaut Adieresis -50
+KPX Ohungarumlaut Agrave -50
+KPX Ohungarumlaut Amacron -50
+KPX Ohungarumlaut Aogonek -50
+KPX Ohungarumlaut Aring -50
+KPX Ohungarumlaut Atilde -50
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -50
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -50
+KPX Omacron Aacute -50
+KPX Omacron Abreve -50
+KPX Omacron Acircumflex -50
+KPX Omacron Adieresis -50
+KPX Omacron Agrave -50
+KPX Omacron Amacron -50
+KPX Omacron Aogonek -50
+KPX Omacron Aring -50
+KPX Omacron Atilde -50
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -50
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -50
+KPX Oslash Aacute -50
+KPX Oslash Abreve -50
+KPX Oslash Acircumflex -50
+KPX Oslash Adieresis -50
+KPX Oslash Agrave -50
+KPX Oslash Amacron -50
+KPX Oslash Aogonek -50
+KPX Oslash Aring -50
+KPX Oslash Atilde -50
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -50
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -50
+KPX Otilde Aacute -50
+KPX Otilde Abreve -50
+KPX Otilde Acircumflex -50
+KPX Otilde Adieresis -50
+KPX Otilde Agrave -50
+KPX Otilde Amacron -50
+KPX Otilde Aogonek -50
+KPX Otilde Aring -50
+KPX Otilde Atilde -50
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -50
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -100
+KPX P Aacute -100
+KPX P Abreve -100
+KPX P Acircumflex -100
+KPX P Adieresis -100
+KPX P Agrave -100
+KPX P Amacron -100
+KPX P Aogonek -100
+KPX P Aring -100
+KPX P Atilde -100
+KPX P a -30
+KPX P aacute -30
+KPX P abreve -30
+KPX P acircumflex -30
+KPX P adieresis -30
+KPX P agrave -30
+KPX P amacron -30
+KPX P aogonek -30
+KPX P aring -30
+KPX P atilde -30
+KPX P comma -120
+KPX P e -30
+KPX P eacute -30
+KPX P ecaron -30
+KPX P ecircumflex -30
+KPX P edieresis -30
+KPX P edotaccent -30
+KPX P egrave -30
+KPX P emacron -30
+KPX P eogonek -30
+KPX P o -40
+KPX P oacute -40
+KPX P ocircumflex -40
+KPX P odieresis -40
+KPX P ograve -40
+KPX P ohungarumlaut -40
+KPX P omacron -40
+KPX P oslash -40
+KPX P otilde -40
+KPX P period -120
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q comma 20
+KPX Q period 20
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -20
+KPX R Tcaron -20
+KPX R Tcommaaccent -20
+KPX R U -20
+KPX R Uacute -20
+KPX R Ucircumflex -20
+KPX R Udieresis -20
+KPX R Ugrave -20
+KPX R Uhungarumlaut -20
+KPX R Umacron -20
+KPX R Uogonek -20
+KPX R Uring -20
+KPX R V -50
+KPX R W -40
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -20
+KPX Racute Tcaron -20
+KPX Racute Tcommaaccent -20
+KPX Racute U -20
+KPX Racute Uacute -20
+KPX Racute Ucircumflex -20
+KPX Racute Udieresis -20
+KPX Racute Ugrave -20
+KPX Racute Uhungarumlaut -20
+KPX Racute Umacron -20
+KPX Racute Uogonek -20
+KPX Racute Uring -20
+KPX Racute V -50
+KPX Racute W -40
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -20
+KPX Rcaron Tcaron -20
+KPX Rcaron Tcommaaccent -20
+KPX Rcaron U -20
+KPX Rcaron Uacute -20
+KPX Rcaron Ucircumflex -20
+KPX Rcaron Udieresis -20
+KPX Rcaron Ugrave -20
+KPX Rcaron Uhungarumlaut -20
+KPX Rcaron Umacron -20
+KPX Rcaron Uogonek -20
+KPX Rcaron Uring -20
+KPX Rcaron V -50
+KPX Rcaron W -40
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -20
+KPX Rcommaaccent Tcaron -20
+KPX Rcommaaccent Tcommaaccent -20
+KPX Rcommaaccent U -20
+KPX Rcommaaccent Uacute -20
+KPX Rcommaaccent Ucircumflex -20
+KPX Rcommaaccent Udieresis -20
+KPX Rcommaaccent Ugrave -20
+KPX Rcommaaccent Uhungarumlaut -20
+KPX Rcommaaccent Umacron -20
+KPX Rcommaaccent Uogonek -20
+KPX Rcommaaccent Uring -20
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -40
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -80
+KPX T agrave -80
+KPX T amacron -80
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -80
+KPX T colon -40
+KPX T comma -80
+KPX T e -60
+KPX T eacute -60
+KPX T ecaron -60
+KPX T ecircumflex -60
+KPX T edieresis -60
+KPX T edotaccent -60
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -60
+KPX T hyphen -120
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -80
+KPX T r -80
+KPX T racute -80
+KPX T rcommaaccent -80
+KPX T semicolon -40
+KPX T u -90
+KPX T uacute -90
+KPX T ucircumflex -90
+KPX T udieresis -90
+KPX T ugrave -90
+KPX T uhungarumlaut -90
+KPX T umacron -90
+KPX T uogonek -90
+KPX T uring -90
+KPX T w -60
+KPX T y -60
+KPX T yacute -60
+KPX T ydieresis -60
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -80
+KPX Tcaron agrave -80
+KPX Tcaron amacron -80
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -80
+KPX Tcaron colon -40
+KPX Tcaron comma -80
+KPX Tcaron e -60
+KPX Tcaron eacute -60
+KPX Tcaron ecaron -60
+KPX Tcaron ecircumflex -60
+KPX Tcaron edieresis -60
+KPX Tcaron edotaccent -60
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -60
+KPX Tcaron hyphen -120
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -80
+KPX Tcaron r -80
+KPX Tcaron racute -80
+KPX Tcaron rcommaaccent -80
+KPX Tcaron semicolon -40
+KPX Tcaron u -90
+KPX Tcaron uacute -90
+KPX Tcaron ucircumflex -90
+KPX Tcaron udieresis -90
+KPX Tcaron ugrave -90
+KPX Tcaron uhungarumlaut -90
+KPX Tcaron umacron -90
+KPX Tcaron uogonek -90
+KPX Tcaron uring -90
+KPX Tcaron w -60
+KPX Tcaron y -60
+KPX Tcaron yacute -60
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -80
+KPX Tcommaaccent agrave -80
+KPX Tcommaaccent amacron -80
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -80
+KPX Tcommaaccent colon -40
+KPX Tcommaaccent comma -80
+KPX Tcommaaccent e -60
+KPX Tcommaaccent eacute -60
+KPX Tcommaaccent ecaron -60
+KPX Tcommaaccent ecircumflex -60
+KPX Tcommaaccent edieresis -60
+KPX Tcommaaccent edotaccent -60
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -60
+KPX Tcommaaccent hyphen -120
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -80
+KPX Tcommaaccent r -80
+KPX Tcommaaccent racute -80
+KPX Tcommaaccent rcommaaccent -80
+KPX Tcommaaccent semicolon -40
+KPX Tcommaaccent u -90
+KPX Tcommaaccent uacute -90
+KPX Tcommaaccent ucircumflex -90
+KPX Tcommaaccent udieresis -90
+KPX Tcommaaccent ugrave -90
+KPX Tcommaaccent uhungarumlaut -90
+KPX Tcommaaccent umacron -90
+KPX Tcommaaccent uogonek -90
+KPX Tcommaaccent uring -90
+KPX Tcommaaccent w -60
+KPX Tcommaaccent y -60
+KPX Tcommaaccent yacute -60
+KPX Tcommaaccent ydieresis -60
+KPX U A -50
+KPX U Aacute -50
+KPX U Abreve -50
+KPX U Acircumflex -50
+KPX U Adieresis -50
+KPX U Agrave -50
+KPX U Amacron -50
+KPX U Aogonek -50
+KPX U Aring -50
+KPX U Atilde -50
+KPX U comma -30
+KPX U period -30
+KPX Uacute A -50
+KPX Uacute Aacute -50
+KPX Uacute Abreve -50
+KPX Uacute Acircumflex -50
+KPX Uacute Adieresis -50
+KPX Uacute Agrave -50
+KPX Uacute Amacron -50
+KPX Uacute Aogonek -50
+KPX Uacute Aring -50
+KPX Uacute Atilde -50
+KPX Uacute comma -30
+KPX Uacute period -30
+KPX Ucircumflex A -50
+KPX Ucircumflex Aacute -50
+KPX Ucircumflex Abreve -50
+KPX Ucircumflex Acircumflex -50
+KPX Ucircumflex Adieresis -50
+KPX Ucircumflex Agrave -50
+KPX Ucircumflex Amacron -50
+KPX Ucircumflex Aogonek -50
+KPX Ucircumflex Aring -50
+KPX Ucircumflex Atilde -50
+KPX Ucircumflex comma -30
+KPX Ucircumflex period -30
+KPX Udieresis A -50
+KPX Udieresis Aacute -50
+KPX Udieresis Abreve -50
+KPX Udieresis Acircumflex -50
+KPX Udieresis Adieresis -50
+KPX Udieresis Agrave -50
+KPX Udieresis Amacron -50
+KPX Udieresis Aogonek -50
+KPX Udieresis Aring -50
+KPX Udieresis Atilde -50
+KPX Udieresis comma -30
+KPX Udieresis period -30
+KPX Ugrave A -50
+KPX Ugrave Aacute -50
+KPX Ugrave Abreve -50
+KPX Ugrave Acircumflex -50
+KPX Ugrave Adieresis -50
+KPX Ugrave Agrave -50
+KPX Ugrave Amacron -50
+KPX Ugrave Aogonek -50
+KPX Ugrave Aring -50
+KPX Ugrave Atilde -50
+KPX Ugrave comma -30
+KPX Ugrave period -30
+KPX Uhungarumlaut A -50
+KPX Uhungarumlaut Aacute -50
+KPX Uhungarumlaut Abreve -50
+KPX Uhungarumlaut Acircumflex -50
+KPX Uhungarumlaut Adieresis -50
+KPX Uhungarumlaut Agrave -50
+KPX Uhungarumlaut Amacron -50
+KPX Uhungarumlaut Aogonek -50
+KPX Uhungarumlaut Aring -50
+KPX Uhungarumlaut Atilde -50
+KPX Uhungarumlaut comma -30
+KPX Uhungarumlaut period -30
+KPX Umacron A -50
+KPX Umacron Aacute -50
+KPX Umacron Abreve -50
+KPX Umacron Acircumflex -50
+KPX Umacron Adieresis -50
+KPX Umacron Agrave -50
+KPX Umacron Amacron -50
+KPX Umacron Aogonek -50
+KPX Umacron Aring -50
+KPX Umacron Atilde -50
+KPX Umacron comma -30
+KPX Umacron period -30
+KPX Uogonek A -50
+KPX Uogonek Aacute -50
+KPX Uogonek Abreve -50
+KPX Uogonek Acircumflex -50
+KPX Uogonek Adieresis -50
+KPX Uogonek Agrave -50
+KPX Uogonek Amacron -50
+KPX Uogonek Aogonek -50
+KPX Uogonek Aring -50
+KPX Uogonek Atilde -50
+KPX Uogonek comma -30
+KPX Uogonek period -30
+KPX Uring A -50
+KPX Uring Aacute -50
+KPX Uring Abreve -50
+KPX Uring Acircumflex -50
+KPX Uring Adieresis -50
+KPX Uring Agrave -50
+KPX Uring Amacron -50
+KPX Uring Aogonek -50
+KPX Uring Aring -50
+KPX Uring Atilde -50
+KPX Uring comma -30
+KPX Uring period -30
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -50
+KPX V Gbreve -50
+KPX V Gcommaaccent -50
+KPX V O -50
+KPX V Oacute -50
+KPX V Ocircumflex -50
+KPX V Odieresis -50
+KPX V Ograve -50
+KPX V Ohungarumlaut -50
+KPX V Omacron -50
+KPX V Oslash -50
+KPX V Otilde -50
+KPX V a -60
+KPX V aacute -60
+KPX V abreve -60
+KPX V acircumflex -60
+KPX V adieresis -60
+KPX V agrave -60
+KPX V amacron -60
+KPX V aogonek -60
+KPX V aring -60
+KPX V atilde -60
+KPX V colon -40
+KPX V comma -120
+KPX V e -50
+KPX V eacute -50
+KPX V ecaron -50
+KPX V ecircumflex -50
+KPX V edieresis -50
+KPX V edotaccent -50
+KPX V egrave -50
+KPX V emacron -50
+KPX V eogonek -50
+KPX V hyphen -80
+KPX V o -90
+KPX V oacute -90
+KPX V ocircumflex -90
+KPX V odieresis -90
+KPX V ograve -90
+KPX V ohungarumlaut -90
+KPX V omacron -90
+KPX V oslash -90
+KPX V otilde -90
+KPX V period -120
+KPX V semicolon -40
+KPX V u -60
+KPX V uacute -60
+KPX V ucircumflex -60
+KPX V udieresis -60
+KPX V ugrave -60
+KPX V uhungarumlaut -60
+KPX V umacron -60
+KPX V uogonek -60
+KPX V uring -60
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W colon -10
+KPX W comma -80
+KPX W e -35
+KPX W eacute -35
+KPX W ecaron -35
+KPX W ecircumflex -35
+KPX W edieresis -35
+KPX W edotaccent -35
+KPX W egrave -35
+KPX W emacron -35
+KPX W eogonek -35
+KPX W hyphen -40
+KPX W o -60
+KPX W oacute -60
+KPX W ocircumflex -60
+KPX W odieresis -60
+KPX W ograve -60
+KPX W ohungarumlaut -60
+KPX W omacron -60
+KPX W oslash -60
+KPX W otilde -60
+KPX W period -80
+KPX W semicolon -10
+KPX W u -45
+KPX W uacute -45
+KPX W ucircumflex -45
+KPX W udieresis -45
+KPX W ugrave -45
+KPX W uhungarumlaut -45
+KPX W umacron -45
+KPX W uogonek -45
+KPX W uring -45
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -70
+KPX Y Oacute -70
+KPX Y Ocircumflex -70
+KPX Y Odieresis -70
+KPX Y Ograve -70
+KPX Y Ohungarumlaut -70
+KPX Y Omacron -70
+KPX Y Oslash -70
+KPX Y Otilde -70
+KPX Y a -90
+KPX Y aacute -90
+KPX Y abreve -90
+KPX Y acircumflex -90
+KPX Y adieresis -90
+KPX Y agrave -90
+KPX Y amacron -90
+KPX Y aogonek -90
+KPX Y aring -90
+KPX Y atilde -90
+KPX Y colon -50
+KPX Y comma -100
+KPX Y e -80
+KPX Y eacute -80
+KPX Y ecaron -80
+KPX Y ecircumflex -80
+KPX Y edieresis -80
+KPX Y edotaccent -80
+KPX Y egrave -80
+KPX Y emacron -80
+KPX Y eogonek -80
+KPX Y o -100
+KPX Y oacute -100
+KPX Y ocircumflex -100
+KPX Y odieresis -100
+KPX Y ograve -100
+KPX Y ohungarumlaut -100
+KPX Y omacron -100
+KPX Y oslash -100
+KPX Y otilde -100
+KPX Y period -100
+KPX Y semicolon -50
+KPX Y u -100
+KPX Y uacute -100
+KPX Y ucircumflex -100
+KPX Y udieresis -100
+KPX Y ugrave -100
+KPX Y uhungarumlaut -100
+KPX Y umacron -100
+KPX Y uogonek -100
+KPX Y uring -100
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -70
+KPX Yacute Oacute -70
+KPX Yacute Ocircumflex -70
+KPX Yacute Odieresis -70
+KPX Yacute Ograve -70
+KPX Yacute Ohungarumlaut -70
+KPX Yacute Omacron -70
+KPX Yacute Oslash -70
+KPX Yacute Otilde -70
+KPX Yacute a -90
+KPX Yacute aacute -90
+KPX Yacute abreve -90
+KPX Yacute acircumflex -90
+KPX Yacute adieresis -90
+KPX Yacute agrave -90
+KPX Yacute amacron -90
+KPX Yacute aogonek -90
+KPX Yacute aring -90
+KPX Yacute atilde -90
+KPX Yacute colon -50
+KPX Yacute comma -100
+KPX Yacute e -80
+KPX Yacute eacute -80
+KPX Yacute ecaron -80
+KPX Yacute ecircumflex -80
+KPX Yacute edieresis -80
+KPX Yacute edotaccent -80
+KPX Yacute egrave -80
+KPX Yacute emacron -80
+KPX Yacute eogonek -80
+KPX Yacute o -100
+KPX Yacute oacute -100
+KPX Yacute ocircumflex -100
+KPX Yacute odieresis -100
+KPX Yacute ograve -100
+KPX Yacute ohungarumlaut -100
+KPX Yacute omacron -100
+KPX Yacute oslash -100
+KPX Yacute otilde -100
+KPX Yacute period -100
+KPX Yacute semicolon -50
+KPX Yacute u -100
+KPX Yacute uacute -100
+KPX Yacute ucircumflex -100
+KPX Yacute udieresis -100
+KPX Yacute ugrave -100
+KPX Yacute uhungarumlaut -100
+KPX Yacute umacron -100
+KPX Yacute uogonek -100
+KPX Yacute uring -100
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -70
+KPX Ydieresis Oacute -70
+KPX Ydieresis Ocircumflex -70
+KPX Ydieresis Odieresis -70
+KPX Ydieresis Ograve -70
+KPX Ydieresis Ohungarumlaut -70
+KPX Ydieresis Omacron -70
+KPX Ydieresis Oslash -70
+KPX Ydieresis Otilde -70
+KPX Ydieresis a -90
+KPX Ydieresis aacute -90
+KPX Ydieresis abreve -90
+KPX Ydieresis acircumflex -90
+KPX Ydieresis adieresis -90
+KPX Ydieresis agrave -90
+KPX Ydieresis amacron -90
+KPX Ydieresis aogonek -90
+KPX Ydieresis aring -90
+KPX Ydieresis atilde -90
+KPX Ydieresis colon -50
+KPX Ydieresis comma -100
+KPX Ydieresis e -80
+KPX Ydieresis eacute -80
+KPX Ydieresis ecaron -80
+KPX Ydieresis ecircumflex -80
+KPX Ydieresis edieresis -80
+KPX Ydieresis edotaccent -80
+KPX Ydieresis egrave -80
+KPX Ydieresis emacron -80
+KPX Ydieresis eogonek -80
+KPX Ydieresis o -100
+KPX Ydieresis oacute -100
+KPX Ydieresis ocircumflex -100
+KPX Ydieresis odieresis -100
+KPX Ydieresis ograve -100
+KPX Ydieresis ohungarumlaut -100
+KPX Ydieresis omacron -100
+KPX Ydieresis oslash -100
+KPX Ydieresis otilde -100
+KPX Ydieresis period -100
+KPX Ydieresis semicolon -50
+KPX Ydieresis u -100
+KPX Ydieresis uacute -100
+KPX Ydieresis ucircumflex -100
+KPX Ydieresis udieresis -100
+KPX Ydieresis ugrave -100
+KPX Ydieresis uhungarumlaut -100
+KPX Ydieresis umacron -100
+KPX Ydieresis uogonek -100
+KPX Ydieresis uring -100
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX a v -15
+KPX a w -15
+KPX a y -20
+KPX a yacute -20
+KPX a ydieresis -20
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX aacute v -15
+KPX aacute w -15
+KPX aacute y -20
+KPX aacute yacute -20
+KPX aacute ydieresis -20
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX abreve v -15
+KPX abreve w -15
+KPX abreve y -20
+KPX abreve yacute -20
+KPX abreve ydieresis -20
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX acircumflex v -15
+KPX acircumflex w -15
+KPX acircumflex y -20
+KPX acircumflex yacute -20
+KPX acircumflex ydieresis -20
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX adieresis v -15
+KPX adieresis w -15
+KPX adieresis y -20
+KPX adieresis yacute -20
+KPX adieresis ydieresis -20
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX agrave v -15
+KPX agrave w -15
+KPX agrave y -20
+KPX agrave yacute -20
+KPX agrave ydieresis -20
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX amacron v -15
+KPX amacron w -15
+KPX amacron y -20
+KPX amacron yacute -20
+KPX amacron ydieresis -20
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aogonek v -15
+KPX aogonek w -15
+KPX aogonek y -20
+KPX aogonek yacute -20
+KPX aogonek ydieresis -20
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX aring v -15
+KPX aring w -15
+KPX aring y -20
+KPX aring yacute -20
+KPX aring ydieresis -20
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX atilde v -15
+KPX atilde w -15
+KPX atilde y -20
+KPX atilde yacute -20
+KPX atilde ydieresis -20
+KPX b l -10
+KPX b lacute -10
+KPX b lcommaaccent -10
+KPX b lslash -10
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c h -10
+KPX c k -20
+KPX c kcommaaccent -20
+KPX c l -20
+KPX c lacute -20
+KPX c lcommaaccent -20
+KPX c lslash -20
+KPX c y -10
+KPX c yacute -10
+KPX c ydieresis -10
+KPX cacute h -10
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX cacute l -20
+KPX cacute lacute -20
+KPX cacute lcommaaccent -20
+KPX cacute lslash -20
+KPX cacute y -10
+KPX cacute yacute -10
+KPX cacute ydieresis -10
+KPX ccaron h -10
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccaron l -20
+KPX ccaron lacute -20
+KPX ccaron lcommaaccent -20
+KPX ccaron lslash -20
+KPX ccaron y -10
+KPX ccaron yacute -10
+KPX ccaron ydieresis -10
+KPX ccedilla h -10
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX ccedilla l -20
+KPX ccedilla lacute -20
+KPX ccedilla lcommaaccent -20
+KPX ccedilla lslash -20
+KPX ccedilla y -10
+KPX ccedilla yacute -10
+KPX ccedilla ydieresis -10
+KPX colon space -40
+KPX comma quotedblright -120
+KPX comma quoteright -120
+KPX comma space -40
+KPX d d -10
+KPX d dcroat -10
+KPX d v -15
+KPX d w -15
+KPX d y -15
+KPX d yacute -15
+KPX d ydieresis -15
+KPX dcroat d -10
+KPX dcroat dcroat -10
+KPX dcroat v -15
+KPX dcroat w -15
+KPX dcroat y -15
+KPX dcroat yacute -15
+KPX dcroat ydieresis -15
+KPX e comma 10
+KPX e period 20
+KPX e v -15
+KPX e w -15
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute comma 10
+KPX eacute period 20
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron comma 10
+KPX ecaron period 20
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex comma 10
+KPX ecircumflex period 20
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis comma 10
+KPX edieresis period 20
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent comma 10
+KPX edotaccent period 20
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave comma 10
+KPX egrave period 20
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron comma 10
+KPX emacron period 20
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek comma 10
+KPX eogonek period 20
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f comma -10
+KPX f e -10
+KPX f eacute -10
+KPX f ecaron -10
+KPX f ecircumflex -10
+KPX f edieresis -10
+KPX f edotaccent -10
+KPX f egrave -10
+KPX f emacron -10
+KPX f eogonek -10
+KPX f o -20
+KPX f oacute -20
+KPX f ocircumflex -20
+KPX f odieresis -20
+KPX f ograve -20
+KPX f ohungarumlaut -20
+KPX f omacron -20
+KPX f oslash -20
+KPX f otilde -20
+KPX f period -10
+KPX f quotedblright 30
+KPX f quoteright 30
+KPX g e 10
+KPX g eacute 10
+KPX g ecaron 10
+KPX g ecircumflex 10
+KPX g edieresis 10
+KPX g edotaccent 10
+KPX g egrave 10
+KPX g emacron 10
+KPX g eogonek 10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX gbreve e 10
+KPX gbreve eacute 10
+KPX gbreve ecaron 10
+KPX gbreve ecircumflex 10
+KPX gbreve edieresis 10
+KPX gbreve edotaccent 10
+KPX gbreve egrave 10
+KPX gbreve emacron 10
+KPX gbreve eogonek 10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gcommaaccent e 10
+KPX gcommaaccent eacute 10
+KPX gcommaaccent ecaron 10
+KPX gcommaaccent ecircumflex 10
+KPX gcommaaccent edieresis 10
+KPX gcommaaccent edotaccent 10
+KPX gcommaaccent egrave 10
+KPX gcommaaccent emacron 10
+KPX gcommaaccent eogonek 10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX h y -20
+KPX h yacute -20
+KPX h ydieresis -20
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX l w -15
+KPX l y -15
+KPX l yacute -15
+KPX l ydieresis -15
+KPX lacute w -15
+KPX lacute y -15
+KPX lacute yacute -15
+KPX lacute ydieresis -15
+KPX lcommaaccent w -15
+KPX lcommaaccent y -15
+KPX lcommaaccent yacute -15
+KPX lcommaaccent ydieresis -15
+KPX lslash w -15
+KPX lslash y -15
+KPX lslash yacute -15
+KPX lslash ydieresis -15
+KPX m u -20
+KPX m uacute -20
+KPX m ucircumflex -20
+KPX m udieresis -20
+KPX m ugrave -20
+KPX m uhungarumlaut -20
+KPX m umacron -20
+KPX m uogonek -20
+KPX m uring -20
+KPX m y -30
+KPX m yacute -30
+KPX m ydieresis -30
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -40
+KPX n y -20
+KPX n yacute -20
+KPX n ydieresis -20
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -40
+KPX nacute y -20
+KPX nacute yacute -20
+KPX nacute ydieresis -20
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -40
+KPX ncaron y -20
+KPX ncaron yacute -20
+KPX ncaron ydieresis -20
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -40
+KPX ncommaaccent y -20
+KPX ncommaaccent yacute -20
+KPX ncommaaccent ydieresis -20
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -40
+KPX ntilde y -20
+KPX ntilde yacute -20
+KPX ntilde ydieresis -20
+KPX o v -20
+KPX o w -15
+KPX o x -30
+KPX o y -20
+KPX o yacute -20
+KPX o ydieresis -20
+KPX oacute v -20
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -20
+KPX oacute yacute -20
+KPX oacute ydieresis -20
+KPX ocircumflex v -20
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -20
+KPX ocircumflex yacute -20
+KPX ocircumflex ydieresis -20
+KPX odieresis v -20
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -20
+KPX odieresis yacute -20
+KPX odieresis ydieresis -20
+KPX ograve v -20
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -20
+KPX ograve yacute -20
+KPX ograve ydieresis -20
+KPX ohungarumlaut v -20
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -20
+KPX ohungarumlaut yacute -20
+KPX ohungarumlaut ydieresis -20
+KPX omacron v -20
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -20
+KPX omacron yacute -20
+KPX omacron ydieresis -20
+KPX oslash v -20
+KPX oslash w -15
+KPX oslash x -30
+KPX oslash y -20
+KPX oslash yacute -20
+KPX oslash ydieresis -20
+KPX otilde v -20
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -20
+KPX otilde yacute -20
+KPX otilde ydieresis -20
+KPX p y -15
+KPX p yacute -15
+KPX p ydieresis -15
+KPX period quotedblright -120
+KPX period quoteright -120
+KPX period space -40
+KPX quotedblright space -80
+KPX quoteleft quoteleft -46
+KPX quoteright d -80
+KPX quoteright dcroat -80
+KPX quoteright l -20
+KPX quoteright lacute -20
+KPX quoteright lcommaaccent -20
+KPX quoteright lslash -20
+KPX quoteright quoteright -46
+KPX quoteright r -40
+KPX quoteright racute -40
+KPX quoteright rcaron -40
+KPX quoteright rcommaaccent -40
+KPX quoteright s -60
+KPX quoteright sacute -60
+KPX quoteright scaron -60
+KPX quoteright scedilla -60
+KPX quoteright scommaaccent -60
+KPX quoteright space -80
+KPX quoteright v -20
+KPX r c -20
+KPX r cacute -20
+KPX r ccaron -20
+KPX r ccedilla -20
+KPX r comma -60
+KPX r d -20
+KPX r dcroat -20
+KPX r g -15
+KPX r gbreve -15
+KPX r gcommaaccent -15
+KPX r hyphen -20
+KPX r o -20
+KPX r oacute -20
+KPX r ocircumflex -20
+KPX r odieresis -20
+KPX r ograve -20
+KPX r ohungarumlaut -20
+KPX r omacron -20
+KPX r oslash -20
+KPX r otilde -20
+KPX r period -60
+KPX r q -20
+KPX r s -15
+KPX r sacute -15
+KPX r scaron -15
+KPX r scedilla -15
+KPX r scommaaccent -15
+KPX r t 20
+KPX r tcommaaccent 20
+KPX r v 10
+KPX r y 10
+KPX r yacute 10
+KPX r ydieresis 10
+KPX racute c -20
+KPX racute cacute -20
+KPX racute ccaron -20
+KPX racute ccedilla -20
+KPX racute comma -60
+KPX racute d -20
+KPX racute dcroat -20
+KPX racute g -15
+KPX racute gbreve -15
+KPX racute gcommaaccent -15
+KPX racute hyphen -20
+KPX racute o -20
+KPX racute oacute -20
+KPX racute ocircumflex -20
+KPX racute odieresis -20
+KPX racute ograve -20
+KPX racute ohungarumlaut -20
+KPX racute omacron -20
+KPX racute oslash -20
+KPX racute otilde -20
+KPX racute period -60
+KPX racute q -20
+KPX racute s -15
+KPX racute sacute -15
+KPX racute scaron -15
+KPX racute scedilla -15
+KPX racute scommaaccent -15
+KPX racute t 20
+KPX racute tcommaaccent 20
+KPX racute v 10
+KPX racute y 10
+KPX racute yacute 10
+KPX racute ydieresis 10
+KPX rcaron c -20
+KPX rcaron cacute -20
+KPX rcaron ccaron -20
+KPX rcaron ccedilla -20
+KPX rcaron comma -60
+KPX rcaron d -20
+KPX rcaron dcroat -20
+KPX rcaron g -15
+KPX rcaron gbreve -15
+KPX rcaron gcommaaccent -15
+KPX rcaron hyphen -20
+KPX rcaron o -20
+KPX rcaron oacute -20
+KPX rcaron ocircumflex -20
+KPX rcaron odieresis -20
+KPX rcaron ograve -20
+KPX rcaron ohungarumlaut -20
+KPX rcaron omacron -20
+KPX rcaron oslash -20
+KPX rcaron otilde -20
+KPX rcaron period -60
+KPX rcaron q -20
+KPX rcaron s -15
+KPX rcaron sacute -15
+KPX rcaron scaron -15
+KPX rcaron scedilla -15
+KPX rcaron scommaaccent -15
+KPX rcaron t 20
+KPX rcaron tcommaaccent 20
+KPX rcaron v 10
+KPX rcaron y 10
+KPX rcaron yacute 10
+KPX rcaron ydieresis 10
+KPX rcommaaccent c -20
+KPX rcommaaccent cacute -20
+KPX rcommaaccent ccaron -20
+KPX rcommaaccent ccedilla -20
+KPX rcommaaccent comma -60
+KPX rcommaaccent d -20
+KPX rcommaaccent dcroat -20
+KPX rcommaaccent g -15
+KPX rcommaaccent gbreve -15
+KPX rcommaaccent gcommaaccent -15
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -20
+KPX rcommaaccent oacute -20
+KPX rcommaaccent ocircumflex -20
+KPX rcommaaccent odieresis -20
+KPX rcommaaccent ograve -20
+KPX rcommaaccent ohungarumlaut -20
+KPX rcommaaccent omacron -20
+KPX rcommaaccent oslash -20
+KPX rcommaaccent otilde -20
+KPX rcommaaccent period -60
+KPX rcommaaccent q -20
+KPX rcommaaccent s -15
+KPX rcommaaccent sacute -15
+KPX rcommaaccent scaron -15
+KPX rcommaaccent scedilla -15
+KPX rcommaaccent scommaaccent -15
+KPX rcommaaccent t 20
+KPX rcommaaccent tcommaaccent 20
+KPX rcommaaccent v 10
+KPX rcommaaccent y 10
+KPX rcommaaccent yacute 10
+KPX rcommaaccent ydieresis 10
+KPX s w -15
+KPX sacute w -15
+KPX scaron w -15
+KPX scedilla w -15
+KPX scommaaccent w -15
+KPX semicolon space -40
+KPX space T -100
+KPX space Tcaron -100
+KPX space Tcommaaccent -100
+KPX space V -80
+KPX space W -80
+KPX space Y -120
+KPX space Yacute -120
+KPX space Ydieresis -120
+KPX space quotedblleft -80
+KPX space quoteleft -60
+KPX v a -20
+KPX v aacute -20
+KPX v abreve -20
+KPX v acircumflex -20
+KPX v adieresis -20
+KPX v agrave -20
+KPX v amacron -20
+KPX v aogonek -20
+KPX v aring -20
+KPX v atilde -20
+KPX v comma -80
+KPX v o -30
+KPX v oacute -30
+KPX v ocircumflex -30
+KPX v odieresis -30
+KPX v ograve -30
+KPX v ohungarumlaut -30
+KPX v omacron -30
+KPX v oslash -30
+KPX v otilde -30
+KPX v period -80
+KPX w comma -40
+KPX w o -20
+KPX w oacute -20
+KPX w ocircumflex -20
+KPX w odieresis -20
+KPX w ograve -20
+KPX w ohungarumlaut -20
+KPX w omacron -20
+KPX w oslash -20
+KPX w otilde -20
+KPX w period -40
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y a -30
+KPX y aacute -30
+KPX y abreve -30
+KPX y acircumflex -30
+KPX y adieresis -30
+KPX y agrave -30
+KPX y amacron -30
+KPX y aogonek -30
+KPX y aring -30
+KPX y atilde -30
+KPX y comma -80
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -80
+KPX yacute a -30
+KPX yacute aacute -30
+KPX yacute abreve -30
+KPX yacute acircumflex -30
+KPX yacute adieresis -30
+KPX yacute agrave -30
+KPX yacute amacron -30
+KPX yacute aogonek -30
+KPX yacute aring -30
+KPX yacute atilde -30
+KPX yacute comma -80
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -80
+KPX ydieresis a -30
+KPX ydieresis aacute -30
+KPX ydieresis abreve -30
+KPX ydieresis acircumflex -30
+KPX ydieresis adieresis -30
+KPX ydieresis agrave -30
+KPX ydieresis amacron -30
+KPX ydieresis aogonek -30
+KPX ydieresis aring -30
+KPX ydieresis atilde -30
+KPX ydieresis comma -80
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -80
+KPX z e 10
+KPX z eacute 10
+KPX z ecaron 10
+KPX z ecircumflex 10
+KPX z edieresis 10
+KPX z edotaccent 10
+KPX z egrave 10
+KPX z emacron 10
+KPX z eogonek 10
+KPX zacute e 10
+KPX zacute eacute 10
+KPX zacute ecaron 10
+KPX zacute ecircumflex 10
+KPX zacute edieresis 10
+KPX zacute edotaccent 10
+KPX zacute egrave 10
+KPX zacute emacron 10
+KPX zacute eogonek 10
+KPX zcaron e 10
+KPX zcaron eacute 10
+KPX zcaron ecaron 10
+KPX zcaron ecircumflex 10
+KPX zcaron edieresis 10
+KPX zcaron edotaccent 10
+KPX zcaron egrave 10
+KPX zcaron emacron 10
+KPX zcaron eogonek 10
+KPX zdotaccent e 10
+KPX zdotaccent eacute 10
+KPX zdotaccent ecaron 10
+KPX zdotaccent ecircumflex 10
+KPX zdotaccent edieresis 10
+KPX zdotaccent edotaccent 10
+KPX zdotaccent egrave 10
+KPX zdotaccent emacron 10
+KPX zdotaccent eogonek 10
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm
new file mode 100644
index 0000000..b11f6c3
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm
@@ -0,0 +1,2828 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:45:12 1997
+Comment UniqueID 43053
+Comment VMusage 14482 68586
+FontName Helvetica-BoldOblique
+FullName Helvetica Bold Oblique
+FamilyName Helvetica
+Weight Bold
+ItalicAngle -12
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -174 -228 1114 962 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StdHW 118
+StdVW 140
+StartCharMetrics 315
+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 36 -225 361 775 ;
+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 125 401 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 123 401 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 278 ; N Idieresis ; B 64 0 494 915 ;
+C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ;
+C -1 ; WX 556 ; N abreve ; B 55 -14 606 750 ;
+C -1 ; WX 611 ; N uhungarumlaut ; B 98 -14 784 750 ;
+C -1 ; WX 556 ; N ecaron ; B 70 -14 614 750 ;
+C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ;
+C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ;
+C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ;
+C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ;
+C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ;
+C -1 ; WX 556 ; N scommaaccent ; B 63 -228 584 546 ;
+C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ;
+C -1 ; WX 722 ; N Uring ; B 116 -19 804 962 ;
+C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ;
+C -1 ; WX 556 ; N aogonek ; B 55 -224 583 546 ;
+C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ;
+C -1 ; WX 611 ; N uogonek ; B 98 -228 658 532 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ;
+C -1 ; WX 722 ; N Dcroat ; B 62 0 777 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 16 -228 188 -50 ;
+C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ;
+C -1 ; WX 667 ; N Emacron ; B 76 0 757 864 ;
+C -1 ; WX 556 ; N ccaron ; B 79 -14 614 750 ;
+C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 807 718 ;
+C -1 ; WX 278 ; N lacute ; B 69 0 528 936 ;
+C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 140 -228 751 718 ;
+C -1 ; WX 722 ; N Cacute ; B 107 -19 789 936 ;
+C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ;
+C -1 ; WX 667 ; N Edotaccent ; B 76 0 757 915 ;
+C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ;
+C -1 ; WX 556 ; N scedilla ; B 63 -228 584 546 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ;
+C -1 ; WX 494 ; N lozenge ; B 90 0 564 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 76 0 778 936 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 108 -228 817 737 ;
+C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ;
+C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ;
+C -1 ; WX 722 ; N Amacron ; B 20 0 718 864 ;
+C -1 ; WX 389 ; N rcaron ; B 64 0 530 750 ;
+C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 25 0 737 915 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ;
+C -1 ; WX 778 ; N Omacron ; B 107 -19 823 864 ;
+C -1 ; WX 722 ; N Racute ; B 76 0 778 936 ;
+C -1 ; WX 667 ; N Sacute ; B 81 -19 722 936 ;
+C -1 ; WX 743 ; N dcaron ; B 82 -14 903 718 ;
+C -1 ; WX 722 ; N Umacron ; B 116 -19 804 864 ;
+C -1 ; WX 611 ; N uring ; B 98 -14 658 776 ;
+C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ;
+C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Abreve ; B 20 0 729 936 ;
+C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ;
+C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ;
+C -1 ; WX 611 ; N Tcaron ; B 140 0 751 936 ;
+C -1 ; WX 494 ; N partialdiff ; B 43 -21 585 750 ;
+C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ;
+C -1 ; WX 722 ; N Nacute ; B 69 0 807 936 ;
+C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ;
+C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ;
+C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ;
+C -1 ; WX 556 ; N cacute ; B 79 -14 627 750 ;
+C -1 ; WX 611 ; N nacute ; B 65 0 654 750 ;
+C -1 ; WX 611 ; N umacron ; B 98 -14 658 678 ;
+C -1 ; WX 722 ; N Ncaron ; B 69 0 807 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ;
+C -1 ; WX 280 ; N brokenbar ; B 52 -150 345 700 ;
+C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 108 -19 817 936 ;
+C -1 ; WX 278 ; N Idotaccent ; B 64 0 397 915 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 670 706 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ;
+C -1 ; WX 389 ; N racute ; B 64 0 543 750 ;
+C -1 ; WX 611 ; N omacron ; B 82 -14 643 678 ;
+C -1 ; WX 611 ; N Zacute ; B 25 0 737 936 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 629 704 ;
+C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 30 -228 362 718 ;
+C -1 ; WX 389 ; N tcaron ; B 100 -6 608 878 ;
+C -1 ; WX 556 ; N eogonek ; B 70 -228 593 546 ;
+C -1 ; WX 722 ; N Uogonek ; B 116 -228 804 718 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ;
+C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ;
+C -1 ; WX 500 ; N zacute ; B 20 0 599 750 ;
+C -1 ; WX 278 ; N iogonek ; B -14 -224 363 725 ;
+C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ;
+C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ;
+C -1 ; WX 556 ; N amacron ; B 55 -14 595 678 ;
+C -1 ; WX 556 ; N sacute ; B 63 -14 627 750 ;
+C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ;
+C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ;
+C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ;
+C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ;
+C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ;
+C -1 ; WX 611 ; N ohungarumlaut ; B 82 -14 784 750 ;
+C -1 ; WX 667 ; N Eogonek ; B 76 -224 757 718 ;
+C -1 ; WX 611 ; N dcroat ; B 82 -14 789 718 ;
+C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ;
+C -1 ; WX 667 ; N Scedilla ; B 81 -228 718 737 ;
+C -1 ; WX 400 ; N lcaron ; B 69 0 561 718 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 858 718 ;
+C -1 ; WX 611 ; N Lacute ; B 76 0 611 936 ;
+C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 70 -14 593 729 ;
+C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ;
+C -1 ; WX 278 ; N Imacron ; B 64 0 496 864 ;
+C -1 ; WX 611 ; N Lcaron ; B 76 0 643 718 ;
+C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 676 704 ;
+C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 116 -19 880 936 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ;
+C -1 ; WX 556 ; N emacron ; B 70 -14 595 678 ;
+C -1 ; WX 611 ; N gbreve ; B 38 -217 666 750 ;
+C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ;
+C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 81 -228 718 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 107 -19 908 936 ;
+C -1 ; WX 400 ; N degree ; B 175 426 467 712 ;
+C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ;
+C -1 ; WX 722 ; N Ccaron ; B 107 -19 789 936 ;
+C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ;
+C -1 ; WX 549 ; N radical ; B 112 -46 689 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 76 0 777 936 ;
+C -1 ; WX 389 ; N rcommaaccent ; B 26 -228 489 546 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ;
+C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 778 718 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 611 718 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ;
+C -1 ; WX 722 ; N Aogonek ; B 20 -224 702 718 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ;
+C -1 ; WX 500 ; N zdotaccent ; B 20 0 583 729 ;
+C -1 ; WX 667 ; N Ecaron ; B 76 0 757 936 ;
+C -1 ; WX 278 ; N Iogonek ; B -41 -228 367 718 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 670 718 ;
+C -1 ; WX 584 ; N minus ; B 82 197 610 309 ;
+C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ;
+C -1 ; WX 611 ; N ncaron ; B 65 0 641 750 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 58 -228 422 676 ;
+C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ;
+C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ;
+C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ;
+C -1 ; WX 549 ; N notequal ; B 32 -49 630 570 ;
+C -1 ; WX 611 ; N gcommaaccent ; B 38 -217 666 850 ;
+C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ;
+C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 629 546 ;
+C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ;
+C -1 ; WX 278 ; N imacron ; B 69 0 429 678 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2481
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -50
+KPX A Gbreve -50
+KPX A Gcommaaccent -50
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -90
+KPX A Tcaron -90
+KPX A Tcommaaccent -90
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -80
+KPX A W -60
+KPX A Y -110
+KPX A Yacute -110
+KPX A Ydieresis -110
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -30
+KPX A y -30
+KPX A yacute -30
+KPX A ydieresis -30
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -50
+KPX Aacute Gbreve -50
+KPX Aacute Gcommaaccent -50
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -90
+KPX Aacute Tcaron -90
+KPX Aacute Tcommaaccent -90
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -80
+KPX Aacute W -60
+KPX Aacute Y -110
+KPX Aacute Yacute -110
+KPX Aacute Ydieresis -110
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -30
+KPX Aacute y -30
+KPX Aacute yacute -30
+KPX Aacute ydieresis -30
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -50
+KPX Abreve Gbreve -50
+KPX Abreve Gcommaaccent -50
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -90
+KPX Abreve Tcaron -90
+KPX Abreve Tcommaaccent -90
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -80
+KPX Abreve W -60
+KPX Abreve Y -110
+KPX Abreve Yacute -110
+KPX Abreve Ydieresis -110
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -30
+KPX Abreve y -30
+KPX Abreve yacute -30
+KPX Abreve ydieresis -30
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -50
+KPX Acircumflex Gbreve -50
+KPX Acircumflex Gcommaaccent -50
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -90
+KPX Acircumflex Tcaron -90
+KPX Acircumflex Tcommaaccent -90
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -80
+KPX Acircumflex W -60
+KPX Acircumflex Y -110
+KPX Acircumflex Yacute -110
+KPX Acircumflex Ydieresis -110
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -30
+KPX Acircumflex y -30
+KPX Acircumflex yacute -30
+KPX Acircumflex ydieresis -30
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -50
+KPX Adieresis Gbreve -50
+KPX Adieresis Gcommaaccent -50
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -90
+KPX Adieresis Tcaron -90
+KPX Adieresis Tcommaaccent -90
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -80
+KPX Adieresis W -60
+KPX Adieresis Y -110
+KPX Adieresis Yacute -110
+KPX Adieresis Ydieresis -110
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -30
+KPX Adieresis y -30
+KPX Adieresis yacute -30
+KPX Adieresis ydieresis -30
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -50
+KPX Agrave Gbreve -50
+KPX Agrave Gcommaaccent -50
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -90
+KPX Agrave Tcaron -90
+KPX Agrave Tcommaaccent -90
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -80
+KPX Agrave W -60
+KPX Agrave Y -110
+KPX Agrave Yacute -110
+KPX Agrave Ydieresis -110
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -30
+KPX Agrave y -30
+KPX Agrave yacute -30
+KPX Agrave ydieresis -30
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -50
+KPX Amacron Gbreve -50
+KPX Amacron Gcommaaccent -50
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -90
+KPX Amacron Tcaron -90
+KPX Amacron Tcommaaccent -90
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -80
+KPX Amacron W -60
+KPX Amacron Y -110
+KPX Amacron Yacute -110
+KPX Amacron Ydieresis -110
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -30
+KPX Amacron y -30
+KPX Amacron yacute -30
+KPX Amacron ydieresis -30
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -50
+KPX Aogonek Gbreve -50
+KPX Aogonek Gcommaaccent -50
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -90
+KPX Aogonek Tcaron -90
+KPX Aogonek Tcommaaccent -90
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -80
+KPX Aogonek W -60
+KPX Aogonek Y -110
+KPX Aogonek Yacute -110
+KPX Aogonek Ydieresis -110
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -30
+KPX Aogonek y -30
+KPX Aogonek yacute -30
+KPX Aogonek ydieresis -30
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -50
+KPX Aring Gbreve -50
+KPX Aring Gcommaaccent -50
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -90
+KPX Aring Tcaron -90
+KPX Aring Tcommaaccent -90
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -80
+KPX Aring W -60
+KPX Aring Y -110
+KPX Aring Yacute -110
+KPX Aring Ydieresis -110
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -30
+KPX Aring y -30
+KPX Aring yacute -30
+KPX Aring ydieresis -30
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -50
+KPX Atilde Gbreve -50
+KPX Atilde Gcommaaccent -50
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -90
+KPX Atilde Tcaron -90
+KPX Atilde Tcommaaccent -90
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -80
+KPX Atilde W -60
+KPX Atilde Y -110
+KPX Atilde Yacute -110
+KPX Atilde Ydieresis -110
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -30
+KPX Atilde y -30
+KPX Atilde yacute -30
+KPX Atilde ydieresis -30
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -40
+KPX D Y -70
+KPX D Yacute -70
+KPX D Ydieresis -70
+KPX D comma -30
+KPX D period -30
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -70
+KPX Dcaron Yacute -70
+KPX Dcaron Ydieresis -70
+KPX Dcaron comma -30
+KPX Dcaron period -30
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -70
+KPX Dcroat Yacute -70
+KPX Dcroat Ydieresis -70
+KPX Dcroat comma -30
+KPX Dcroat period -30
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -20
+KPX F aacute -20
+KPX F abreve -20
+KPX F acircumflex -20
+KPX F adieresis -20
+KPX F agrave -20
+KPX F amacron -20
+KPX F aogonek -20
+KPX F aring -20
+KPX F atilde -20
+KPX F comma -100
+KPX F period -100
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J comma -20
+KPX J period -20
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -15
+KPX K eacute -15
+KPX K ecaron -15
+KPX K ecircumflex -15
+KPX K edieresis -15
+KPX K edotaccent -15
+KPX K egrave -15
+KPX K emacron -15
+KPX K eogonek -15
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -15
+KPX Kcommaaccent eacute -15
+KPX Kcommaaccent ecaron -15
+KPX Kcommaaccent ecircumflex -15
+KPX Kcommaaccent edieresis -15
+KPX Kcommaaccent edotaccent -15
+KPX Kcommaaccent egrave -15
+KPX Kcommaaccent emacron -15
+KPX Kcommaaccent eogonek -15
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -90
+KPX L Tcaron -90
+KPX L Tcommaaccent -90
+KPX L V -110
+KPX L W -80
+KPX L Y -120
+KPX L Yacute -120
+KPX L Ydieresis -120
+KPX L quotedblright -140
+KPX L quoteright -140
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -90
+KPX Lacute Tcaron -90
+KPX Lacute Tcommaaccent -90
+KPX Lacute V -110
+KPX Lacute W -80
+KPX Lacute Y -120
+KPX Lacute Yacute -120
+KPX Lacute Ydieresis -120
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -140
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -90
+KPX Lcommaaccent Tcaron -90
+KPX Lcommaaccent Tcommaaccent -90
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -80
+KPX Lcommaaccent Y -120
+KPX Lcommaaccent Yacute -120
+KPX Lcommaaccent Ydieresis -120
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -140
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -90
+KPX Lslash Tcaron -90
+KPX Lslash Tcommaaccent -90
+KPX Lslash V -110
+KPX Lslash W -80
+KPX Lslash Y -120
+KPX Lslash Yacute -120
+KPX Lslash Ydieresis -120
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -140
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -50
+KPX O Aacute -50
+KPX O Abreve -50
+KPX O Acircumflex -50
+KPX O Adieresis -50
+KPX O Agrave -50
+KPX O Amacron -50
+KPX O Aogonek -50
+KPX O Aring -50
+KPX O Atilde -50
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -50
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -50
+KPX Oacute Aacute -50
+KPX Oacute Abreve -50
+KPX Oacute Acircumflex -50
+KPX Oacute Adieresis -50
+KPX Oacute Agrave -50
+KPX Oacute Amacron -50
+KPX Oacute Aogonek -50
+KPX Oacute Aring -50
+KPX Oacute Atilde -50
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -50
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -50
+KPX Ocircumflex Aacute -50
+KPX Ocircumflex Abreve -50
+KPX Ocircumflex Acircumflex -50
+KPX Ocircumflex Adieresis -50
+KPX Ocircumflex Agrave -50
+KPX Ocircumflex Amacron -50
+KPX Ocircumflex Aogonek -50
+KPX Ocircumflex Aring -50
+KPX Ocircumflex Atilde -50
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -50
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -50
+KPX Odieresis Aacute -50
+KPX Odieresis Abreve -50
+KPX Odieresis Acircumflex -50
+KPX Odieresis Adieresis -50
+KPX Odieresis Agrave -50
+KPX Odieresis Amacron -50
+KPX Odieresis Aogonek -50
+KPX Odieresis Aring -50
+KPX Odieresis Atilde -50
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -50
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -50
+KPX Ograve Aacute -50
+KPX Ograve Abreve -50
+KPX Ograve Acircumflex -50
+KPX Ograve Adieresis -50
+KPX Ograve Agrave -50
+KPX Ograve Amacron -50
+KPX Ograve Aogonek -50
+KPX Ograve Aring -50
+KPX Ograve Atilde -50
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -50
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -50
+KPX Ohungarumlaut Aacute -50
+KPX Ohungarumlaut Abreve -50
+KPX Ohungarumlaut Acircumflex -50
+KPX Ohungarumlaut Adieresis -50
+KPX Ohungarumlaut Agrave -50
+KPX Ohungarumlaut Amacron -50
+KPX Ohungarumlaut Aogonek -50
+KPX Ohungarumlaut Aring -50
+KPX Ohungarumlaut Atilde -50
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -50
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -50
+KPX Omacron Aacute -50
+KPX Omacron Abreve -50
+KPX Omacron Acircumflex -50
+KPX Omacron Adieresis -50
+KPX Omacron Agrave -50
+KPX Omacron Amacron -50
+KPX Omacron Aogonek -50
+KPX Omacron Aring -50
+KPX Omacron Atilde -50
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -50
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -50
+KPX Oslash Aacute -50
+KPX Oslash Abreve -50
+KPX Oslash Acircumflex -50
+KPX Oslash Adieresis -50
+KPX Oslash Agrave -50
+KPX Oslash Amacron -50
+KPX Oslash Aogonek -50
+KPX Oslash Aring -50
+KPX Oslash Atilde -50
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -50
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -50
+KPX Otilde Aacute -50
+KPX Otilde Abreve -50
+KPX Otilde Acircumflex -50
+KPX Otilde Adieresis -50
+KPX Otilde Agrave -50
+KPX Otilde Amacron -50
+KPX Otilde Aogonek -50
+KPX Otilde Aring -50
+KPX Otilde Atilde -50
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -50
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -100
+KPX P Aacute -100
+KPX P Abreve -100
+KPX P Acircumflex -100
+KPX P Adieresis -100
+KPX P Agrave -100
+KPX P Amacron -100
+KPX P Aogonek -100
+KPX P Aring -100
+KPX P Atilde -100
+KPX P a -30
+KPX P aacute -30
+KPX P abreve -30
+KPX P acircumflex -30
+KPX P adieresis -30
+KPX P agrave -30
+KPX P amacron -30
+KPX P aogonek -30
+KPX P aring -30
+KPX P atilde -30
+KPX P comma -120
+KPX P e -30
+KPX P eacute -30
+KPX P ecaron -30
+KPX P ecircumflex -30
+KPX P edieresis -30
+KPX P edotaccent -30
+KPX P egrave -30
+KPX P emacron -30
+KPX P eogonek -30
+KPX P o -40
+KPX P oacute -40
+KPX P ocircumflex -40
+KPX P odieresis -40
+KPX P ograve -40
+KPX P ohungarumlaut -40
+KPX P omacron -40
+KPX P oslash -40
+KPX P otilde -40
+KPX P period -120
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q comma 20
+KPX Q period 20
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -20
+KPX R Tcaron -20
+KPX R Tcommaaccent -20
+KPX R U -20
+KPX R Uacute -20
+KPX R Ucircumflex -20
+KPX R Udieresis -20
+KPX R Ugrave -20
+KPX R Uhungarumlaut -20
+KPX R Umacron -20
+KPX R Uogonek -20
+KPX R Uring -20
+KPX R V -50
+KPX R W -40
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -20
+KPX Racute Tcaron -20
+KPX Racute Tcommaaccent -20
+KPX Racute U -20
+KPX Racute Uacute -20
+KPX Racute Ucircumflex -20
+KPX Racute Udieresis -20
+KPX Racute Ugrave -20
+KPX Racute Uhungarumlaut -20
+KPX Racute Umacron -20
+KPX Racute Uogonek -20
+KPX Racute Uring -20
+KPX Racute V -50
+KPX Racute W -40
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -20
+KPX Rcaron Tcaron -20
+KPX Rcaron Tcommaaccent -20
+KPX Rcaron U -20
+KPX Rcaron Uacute -20
+KPX Rcaron Ucircumflex -20
+KPX Rcaron Udieresis -20
+KPX Rcaron Ugrave -20
+KPX Rcaron Uhungarumlaut -20
+KPX Rcaron Umacron -20
+KPX Rcaron Uogonek -20
+KPX Rcaron Uring -20
+KPX Rcaron V -50
+KPX Rcaron W -40
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -20
+KPX Rcommaaccent Tcaron -20
+KPX Rcommaaccent Tcommaaccent -20
+KPX Rcommaaccent U -20
+KPX Rcommaaccent Uacute -20
+KPX Rcommaaccent Ucircumflex -20
+KPX Rcommaaccent Udieresis -20
+KPX Rcommaaccent Ugrave -20
+KPX Rcommaaccent Uhungarumlaut -20
+KPX Rcommaaccent Umacron -20
+KPX Rcommaaccent Uogonek -20
+KPX Rcommaaccent Uring -20
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -40
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -80
+KPX T agrave -80
+KPX T amacron -80
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -80
+KPX T colon -40
+KPX T comma -80
+KPX T e -60
+KPX T eacute -60
+KPX T ecaron -60
+KPX T ecircumflex -60
+KPX T edieresis -60
+KPX T edotaccent -60
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -60
+KPX T hyphen -120
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -80
+KPX T r -80
+KPX T racute -80
+KPX T rcommaaccent -80
+KPX T semicolon -40
+KPX T u -90
+KPX T uacute -90
+KPX T ucircumflex -90
+KPX T udieresis -90
+KPX T ugrave -90
+KPX T uhungarumlaut -90
+KPX T umacron -90
+KPX T uogonek -90
+KPX T uring -90
+KPX T w -60
+KPX T y -60
+KPX T yacute -60
+KPX T ydieresis -60
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -80
+KPX Tcaron agrave -80
+KPX Tcaron amacron -80
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -80
+KPX Tcaron colon -40
+KPX Tcaron comma -80
+KPX Tcaron e -60
+KPX Tcaron eacute -60
+KPX Tcaron ecaron -60
+KPX Tcaron ecircumflex -60
+KPX Tcaron edieresis -60
+KPX Tcaron edotaccent -60
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -60
+KPX Tcaron hyphen -120
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -80
+KPX Tcaron r -80
+KPX Tcaron racute -80
+KPX Tcaron rcommaaccent -80
+KPX Tcaron semicolon -40
+KPX Tcaron u -90
+KPX Tcaron uacute -90
+KPX Tcaron ucircumflex -90
+KPX Tcaron udieresis -90
+KPX Tcaron ugrave -90
+KPX Tcaron uhungarumlaut -90
+KPX Tcaron umacron -90
+KPX Tcaron uogonek -90
+KPX Tcaron uring -90
+KPX Tcaron w -60
+KPX Tcaron y -60
+KPX Tcaron yacute -60
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -80
+KPX Tcommaaccent agrave -80
+KPX Tcommaaccent amacron -80
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -80
+KPX Tcommaaccent colon -40
+KPX Tcommaaccent comma -80
+KPX Tcommaaccent e -60
+KPX Tcommaaccent eacute -60
+KPX Tcommaaccent ecaron -60
+KPX Tcommaaccent ecircumflex -60
+KPX Tcommaaccent edieresis -60
+KPX Tcommaaccent edotaccent -60
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -60
+KPX Tcommaaccent hyphen -120
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -80
+KPX Tcommaaccent r -80
+KPX Tcommaaccent racute -80
+KPX Tcommaaccent rcommaaccent -80
+KPX Tcommaaccent semicolon -40
+KPX Tcommaaccent u -90
+KPX Tcommaaccent uacute -90
+KPX Tcommaaccent ucircumflex -90
+KPX Tcommaaccent udieresis -90
+KPX Tcommaaccent ugrave -90
+KPX Tcommaaccent uhungarumlaut -90
+KPX Tcommaaccent umacron -90
+KPX Tcommaaccent uogonek -90
+KPX Tcommaaccent uring -90
+KPX Tcommaaccent w -60
+KPX Tcommaaccent y -60
+KPX Tcommaaccent yacute -60
+KPX Tcommaaccent ydieresis -60
+KPX U A -50
+KPX U Aacute -50
+KPX U Abreve -50
+KPX U Acircumflex -50
+KPX U Adieresis -50
+KPX U Agrave -50
+KPX U Amacron -50
+KPX U Aogonek -50
+KPX U Aring -50
+KPX U Atilde -50
+KPX U comma -30
+KPX U period -30
+KPX Uacute A -50
+KPX Uacute Aacute -50
+KPX Uacute Abreve -50
+KPX Uacute Acircumflex -50
+KPX Uacute Adieresis -50
+KPX Uacute Agrave -50
+KPX Uacute Amacron -50
+KPX Uacute Aogonek -50
+KPX Uacute Aring -50
+KPX Uacute Atilde -50
+KPX Uacute comma -30
+KPX Uacute period -30
+KPX Ucircumflex A -50
+KPX Ucircumflex Aacute -50
+KPX Ucircumflex Abreve -50
+KPX Ucircumflex Acircumflex -50
+KPX Ucircumflex Adieresis -50
+KPX Ucircumflex Agrave -50
+KPX Ucircumflex Amacron -50
+KPX Ucircumflex Aogonek -50
+KPX Ucircumflex Aring -50
+KPX Ucircumflex Atilde -50
+KPX Ucircumflex comma -30
+KPX Ucircumflex period -30
+KPX Udieresis A -50
+KPX Udieresis Aacute -50
+KPX Udieresis Abreve -50
+KPX Udieresis Acircumflex -50
+KPX Udieresis Adieresis -50
+KPX Udieresis Agrave -50
+KPX Udieresis Amacron -50
+KPX Udieresis Aogonek -50
+KPX Udieresis Aring -50
+KPX Udieresis Atilde -50
+KPX Udieresis comma -30
+KPX Udieresis period -30
+KPX Ugrave A -50
+KPX Ugrave Aacute -50
+KPX Ugrave Abreve -50
+KPX Ugrave Acircumflex -50
+KPX Ugrave Adieresis -50
+KPX Ugrave Agrave -50
+KPX Ugrave Amacron -50
+KPX Ugrave Aogonek -50
+KPX Ugrave Aring -50
+KPX Ugrave Atilde -50
+KPX Ugrave comma -30
+KPX Ugrave period -30
+KPX Uhungarumlaut A -50
+KPX Uhungarumlaut Aacute -50
+KPX Uhungarumlaut Abreve -50
+KPX Uhungarumlaut Acircumflex -50
+KPX Uhungarumlaut Adieresis -50
+KPX Uhungarumlaut Agrave -50
+KPX Uhungarumlaut Amacron -50
+KPX Uhungarumlaut Aogonek -50
+KPX Uhungarumlaut Aring -50
+KPX Uhungarumlaut Atilde -50
+KPX Uhungarumlaut comma -30
+KPX Uhungarumlaut period -30
+KPX Umacron A -50
+KPX Umacron Aacute -50
+KPX Umacron Abreve -50
+KPX Umacron Acircumflex -50
+KPX Umacron Adieresis -50
+KPX Umacron Agrave -50
+KPX Umacron Amacron -50
+KPX Umacron Aogonek -50
+KPX Umacron Aring -50
+KPX Umacron Atilde -50
+KPX Umacron comma -30
+KPX Umacron period -30
+KPX Uogonek A -50
+KPX Uogonek Aacute -50
+KPX Uogonek Abreve -50
+KPX Uogonek Acircumflex -50
+KPX Uogonek Adieresis -50
+KPX Uogonek Agrave -50
+KPX Uogonek Amacron -50
+KPX Uogonek Aogonek -50
+KPX Uogonek Aring -50
+KPX Uogonek Atilde -50
+KPX Uogonek comma -30
+KPX Uogonek period -30
+KPX Uring A -50
+KPX Uring Aacute -50
+KPX Uring Abreve -50
+KPX Uring Acircumflex -50
+KPX Uring Adieresis -50
+KPX Uring Agrave -50
+KPX Uring Amacron -50
+KPX Uring Aogonek -50
+KPX Uring Aring -50
+KPX Uring Atilde -50
+KPX Uring comma -30
+KPX Uring period -30
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -50
+KPX V Gbreve -50
+KPX V Gcommaaccent -50
+KPX V O -50
+KPX V Oacute -50
+KPX V Ocircumflex -50
+KPX V Odieresis -50
+KPX V Ograve -50
+KPX V Ohungarumlaut -50
+KPX V Omacron -50
+KPX V Oslash -50
+KPX V Otilde -50
+KPX V a -60
+KPX V aacute -60
+KPX V abreve -60
+KPX V acircumflex -60
+KPX V adieresis -60
+KPX V agrave -60
+KPX V amacron -60
+KPX V aogonek -60
+KPX V aring -60
+KPX V atilde -60
+KPX V colon -40
+KPX V comma -120
+KPX V e -50
+KPX V eacute -50
+KPX V ecaron -50
+KPX V ecircumflex -50
+KPX V edieresis -50
+KPX V edotaccent -50
+KPX V egrave -50
+KPX V emacron -50
+KPX V eogonek -50
+KPX V hyphen -80
+KPX V o -90
+KPX V oacute -90
+KPX V ocircumflex -90
+KPX V odieresis -90
+KPX V ograve -90
+KPX V ohungarumlaut -90
+KPX V omacron -90
+KPX V oslash -90
+KPX V otilde -90
+KPX V period -120
+KPX V semicolon -40
+KPX V u -60
+KPX V uacute -60
+KPX V ucircumflex -60
+KPX V udieresis -60
+KPX V ugrave -60
+KPX V uhungarumlaut -60
+KPX V umacron -60
+KPX V uogonek -60
+KPX V uring -60
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W colon -10
+KPX W comma -80
+KPX W e -35
+KPX W eacute -35
+KPX W ecaron -35
+KPX W ecircumflex -35
+KPX W edieresis -35
+KPX W edotaccent -35
+KPX W egrave -35
+KPX W emacron -35
+KPX W eogonek -35
+KPX W hyphen -40
+KPX W o -60
+KPX W oacute -60
+KPX W ocircumflex -60
+KPX W odieresis -60
+KPX W ograve -60
+KPX W ohungarumlaut -60
+KPX W omacron -60
+KPX W oslash -60
+KPX W otilde -60
+KPX W period -80
+KPX W semicolon -10
+KPX W u -45
+KPX W uacute -45
+KPX W ucircumflex -45
+KPX W udieresis -45
+KPX W ugrave -45
+KPX W uhungarumlaut -45
+KPX W umacron -45
+KPX W uogonek -45
+KPX W uring -45
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -70
+KPX Y Oacute -70
+KPX Y Ocircumflex -70
+KPX Y Odieresis -70
+KPX Y Ograve -70
+KPX Y Ohungarumlaut -70
+KPX Y Omacron -70
+KPX Y Oslash -70
+KPX Y Otilde -70
+KPX Y a -90
+KPX Y aacute -90
+KPX Y abreve -90
+KPX Y acircumflex -90
+KPX Y adieresis -90
+KPX Y agrave -90
+KPX Y amacron -90
+KPX Y aogonek -90
+KPX Y aring -90
+KPX Y atilde -90
+KPX Y colon -50
+KPX Y comma -100
+KPX Y e -80
+KPX Y eacute -80
+KPX Y ecaron -80
+KPX Y ecircumflex -80
+KPX Y edieresis -80
+KPX Y edotaccent -80
+KPX Y egrave -80
+KPX Y emacron -80
+KPX Y eogonek -80
+KPX Y o -100
+KPX Y oacute -100
+KPX Y ocircumflex -100
+KPX Y odieresis -100
+KPX Y ograve -100
+KPX Y ohungarumlaut -100
+KPX Y omacron -100
+KPX Y oslash -100
+KPX Y otilde -100
+KPX Y period -100
+KPX Y semicolon -50
+KPX Y u -100
+KPX Y uacute -100
+KPX Y ucircumflex -100
+KPX Y udieresis -100
+KPX Y ugrave -100
+KPX Y uhungarumlaut -100
+KPX Y umacron -100
+KPX Y uogonek -100
+KPX Y uring -100
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -70
+KPX Yacute Oacute -70
+KPX Yacute Ocircumflex -70
+KPX Yacute Odieresis -70
+KPX Yacute Ograve -70
+KPX Yacute Ohungarumlaut -70
+KPX Yacute Omacron -70
+KPX Yacute Oslash -70
+KPX Yacute Otilde -70
+KPX Yacute a -90
+KPX Yacute aacute -90
+KPX Yacute abreve -90
+KPX Yacute acircumflex -90
+KPX Yacute adieresis -90
+KPX Yacute agrave -90
+KPX Yacute amacron -90
+KPX Yacute aogonek -90
+KPX Yacute aring -90
+KPX Yacute atilde -90
+KPX Yacute colon -50
+KPX Yacute comma -100
+KPX Yacute e -80
+KPX Yacute eacute -80
+KPX Yacute ecaron -80
+KPX Yacute ecircumflex -80
+KPX Yacute edieresis -80
+KPX Yacute edotaccent -80
+KPX Yacute egrave -80
+KPX Yacute emacron -80
+KPX Yacute eogonek -80
+KPX Yacute o -100
+KPX Yacute oacute -100
+KPX Yacute ocircumflex -100
+KPX Yacute odieresis -100
+KPX Yacute ograve -100
+KPX Yacute ohungarumlaut -100
+KPX Yacute omacron -100
+KPX Yacute oslash -100
+KPX Yacute otilde -100
+KPX Yacute period -100
+KPX Yacute semicolon -50
+KPX Yacute u -100
+KPX Yacute uacute -100
+KPX Yacute ucircumflex -100
+KPX Yacute udieresis -100
+KPX Yacute ugrave -100
+KPX Yacute uhungarumlaut -100
+KPX Yacute umacron -100
+KPX Yacute uogonek -100
+KPX Yacute uring -100
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -70
+KPX Ydieresis Oacute -70
+KPX Ydieresis Ocircumflex -70
+KPX Ydieresis Odieresis -70
+KPX Ydieresis Ograve -70
+KPX Ydieresis Ohungarumlaut -70
+KPX Ydieresis Omacron -70
+KPX Ydieresis Oslash -70
+KPX Ydieresis Otilde -70
+KPX Ydieresis a -90
+KPX Ydieresis aacute -90
+KPX Ydieresis abreve -90
+KPX Ydieresis acircumflex -90
+KPX Ydieresis adieresis -90
+KPX Ydieresis agrave -90
+KPX Ydieresis amacron -90
+KPX Ydieresis aogonek -90
+KPX Ydieresis aring -90
+KPX Ydieresis atilde -90
+KPX Ydieresis colon -50
+KPX Ydieresis comma -100
+KPX Ydieresis e -80
+KPX Ydieresis eacute -80
+KPX Ydieresis ecaron -80
+KPX Ydieresis ecircumflex -80
+KPX Ydieresis edieresis -80
+KPX Ydieresis edotaccent -80
+KPX Ydieresis egrave -80
+KPX Ydieresis emacron -80
+KPX Ydieresis eogonek -80
+KPX Ydieresis o -100
+KPX Ydieresis oacute -100
+KPX Ydieresis ocircumflex -100
+KPX Ydieresis odieresis -100
+KPX Ydieresis ograve -100
+KPX Ydieresis ohungarumlaut -100
+KPX Ydieresis omacron -100
+KPX Ydieresis oslash -100
+KPX Ydieresis otilde -100
+KPX Ydieresis period -100
+KPX Ydieresis semicolon -50
+KPX Ydieresis u -100
+KPX Ydieresis uacute -100
+KPX Ydieresis ucircumflex -100
+KPX Ydieresis udieresis -100
+KPX Ydieresis ugrave -100
+KPX Ydieresis uhungarumlaut -100
+KPX Ydieresis umacron -100
+KPX Ydieresis uogonek -100
+KPX Ydieresis uring -100
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX a v -15
+KPX a w -15
+KPX a y -20
+KPX a yacute -20
+KPX a ydieresis -20
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX aacute v -15
+KPX aacute w -15
+KPX aacute y -20
+KPX aacute yacute -20
+KPX aacute ydieresis -20
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX abreve v -15
+KPX abreve w -15
+KPX abreve y -20
+KPX abreve yacute -20
+KPX abreve ydieresis -20
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX acircumflex v -15
+KPX acircumflex w -15
+KPX acircumflex y -20
+KPX acircumflex yacute -20
+KPX acircumflex ydieresis -20
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX adieresis v -15
+KPX adieresis w -15
+KPX adieresis y -20
+KPX adieresis yacute -20
+KPX adieresis ydieresis -20
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX agrave v -15
+KPX agrave w -15
+KPX agrave y -20
+KPX agrave yacute -20
+KPX agrave ydieresis -20
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX amacron v -15
+KPX amacron w -15
+KPX amacron y -20
+KPX amacron yacute -20
+KPX amacron ydieresis -20
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aogonek v -15
+KPX aogonek w -15
+KPX aogonek y -20
+KPX aogonek yacute -20
+KPX aogonek ydieresis -20
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX aring v -15
+KPX aring w -15
+KPX aring y -20
+KPX aring yacute -20
+KPX aring ydieresis -20
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX atilde v -15
+KPX atilde w -15
+KPX atilde y -20
+KPX atilde yacute -20
+KPX atilde ydieresis -20
+KPX b l -10
+KPX b lacute -10
+KPX b lcommaaccent -10
+KPX b lslash -10
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c h -10
+KPX c k -20
+KPX c kcommaaccent -20
+KPX c l -20
+KPX c lacute -20
+KPX c lcommaaccent -20
+KPX c lslash -20
+KPX c y -10
+KPX c yacute -10
+KPX c ydieresis -10
+KPX cacute h -10
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX cacute l -20
+KPX cacute lacute -20
+KPX cacute lcommaaccent -20
+KPX cacute lslash -20
+KPX cacute y -10
+KPX cacute yacute -10
+KPX cacute ydieresis -10
+KPX ccaron h -10
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccaron l -20
+KPX ccaron lacute -20
+KPX ccaron lcommaaccent -20
+KPX ccaron lslash -20
+KPX ccaron y -10
+KPX ccaron yacute -10
+KPX ccaron ydieresis -10
+KPX ccedilla h -10
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX ccedilla l -20
+KPX ccedilla lacute -20
+KPX ccedilla lcommaaccent -20
+KPX ccedilla lslash -20
+KPX ccedilla y -10
+KPX ccedilla yacute -10
+KPX ccedilla ydieresis -10
+KPX colon space -40
+KPX comma quotedblright -120
+KPX comma quoteright -120
+KPX comma space -40
+KPX d d -10
+KPX d dcroat -10
+KPX d v -15
+KPX d w -15
+KPX d y -15
+KPX d yacute -15
+KPX d ydieresis -15
+KPX dcroat d -10
+KPX dcroat dcroat -10
+KPX dcroat v -15
+KPX dcroat w -15
+KPX dcroat y -15
+KPX dcroat yacute -15
+KPX dcroat ydieresis -15
+KPX e comma 10
+KPX e period 20
+KPX e v -15
+KPX e w -15
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute comma 10
+KPX eacute period 20
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron comma 10
+KPX ecaron period 20
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex comma 10
+KPX ecircumflex period 20
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis comma 10
+KPX edieresis period 20
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent comma 10
+KPX edotaccent period 20
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave comma 10
+KPX egrave period 20
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron comma 10
+KPX emacron period 20
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek comma 10
+KPX eogonek period 20
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f comma -10
+KPX f e -10
+KPX f eacute -10
+KPX f ecaron -10
+KPX f ecircumflex -10
+KPX f edieresis -10
+KPX f edotaccent -10
+KPX f egrave -10
+KPX f emacron -10
+KPX f eogonek -10
+KPX f o -20
+KPX f oacute -20
+KPX f ocircumflex -20
+KPX f odieresis -20
+KPX f ograve -20
+KPX f ohungarumlaut -20
+KPX f omacron -20
+KPX f oslash -20
+KPX f otilde -20
+KPX f period -10
+KPX f quotedblright 30
+KPX f quoteright 30
+KPX g e 10
+KPX g eacute 10
+KPX g ecaron 10
+KPX g ecircumflex 10
+KPX g edieresis 10
+KPX g edotaccent 10
+KPX g egrave 10
+KPX g emacron 10
+KPX g eogonek 10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX gbreve e 10
+KPX gbreve eacute 10
+KPX gbreve ecaron 10
+KPX gbreve ecircumflex 10
+KPX gbreve edieresis 10
+KPX gbreve edotaccent 10
+KPX gbreve egrave 10
+KPX gbreve emacron 10
+KPX gbreve eogonek 10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gcommaaccent e 10
+KPX gcommaaccent eacute 10
+KPX gcommaaccent ecaron 10
+KPX gcommaaccent ecircumflex 10
+KPX gcommaaccent edieresis 10
+KPX gcommaaccent edotaccent 10
+KPX gcommaaccent egrave 10
+KPX gcommaaccent emacron 10
+KPX gcommaaccent eogonek 10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX h y -20
+KPX h yacute -20
+KPX h ydieresis -20
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX l w -15
+KPX l y -15
+KPX l yacute -15
+KPX l ydieresis -15
+KPX lacute w -15
+KPX lacute y -15
+KPX lacute yacute -15
+KPX lacute ydieresis -15
+KPX lcommaaccent w -15
+KPX lcommaaccent y -15
+KPX lcommaaccent yacute -15
+KPX lcommaaccent ydieresis -15
+KPX lslash w -15
+KPX lslash y -15
+KPX lslash yacute -15
+KPX lslash ydieresis -15
+KPX m u -20
+KPX m uacute -20
+KPX m ucircumflex -20
+KPX m udieresis -20
+KPX m ugrave -20
+KPX m uhungarumlaut -20
+KPX m umacron -20
+KPX m uogonek -20
+KPX m uring -20
+KPX m y -30
+KPX m yacute -30
+KPX m ydieresis -30
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -40
+KPX n y -20
+KPX n yacute -20
+KPX n ydieresis -20
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -40
+KPX nacute y -20
+KPX nacute yacute -20
+KPX nacute ydieresis -20
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -40
+KPX ncaron y -20
+KPX ncaron yacute -20
+KPX ncaron ydieresis -20
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -40
+KPX ncommaaccent y -20
+KPX ncommaaccent yacute -20
+KPX ncommaaccent ydieresis -20
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -40
+KPX ntilde y -20
+KPX ntilde yacute -20
+KPX ntilde ydieresis -20
+KPX o v -20
+KPX o w -15
+KPX o x -30
+KPX o y -20
+KPX o yacute -20
+KPX o ydieresis -20
+KPX oacute v -20
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -20
+KPX oacute yacute -20
+KPX oacute ydieresis -20
+KPX ocircumflex v -20
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -20
+KPX ocircumflex yacute -20
+KPX ocircumflex ydieresis -20
+KPX odieresis v -20
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -20
+KPX odieresis yacute -20
+KPX odieresis ydieresis -20
+KPX ograve v -20
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -20
+KPX ograve yacute -20
+KPX ograve ydieresis -20
+KPX ohungarumlaut v -20
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -20
+KPX ohungarumlaut yacute -20
+KPX ohungarumlaut ydieresis -20
+KPX omacron v -20
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -20
+KPX omacron yacute -20
+KPX omacron ydieresis -20
+KPX oslash v -20
+KPX oslash w -15
+KPX oslash x -30
+KPX oslash y -20
+KPX oslash yacute -20
+KPX oslash ydieresis -20
+KPX otilde v -20
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -20
+KPX otilde yacute -20
+KPX otilde ydieresis -20
+KPX p y -15
+KPX p yacute -15
+KPX p ydieresis -15
+KPX period quotedblright -120
+KPX period quoteright -120
+KPX period space -40
+KPX quotedblright space -80
+KPX quoteleft quoteleft -46
+KPX quoteright d -80
+KPX quoteright dcroat -80
+KPX quoteright l -20
+KPX quoteright lacute -20
+KPX quoteright lcommaaccent -20
+KPX quoteright lslash -20
+KPX quoteright quoteright -46
+KPX quoteright r -40
+KPX quoteright racute -40
+KPX quoteright rcaron -40
+KPX quoteright rcommaaccent -40
+KPX quoteright s -60
+KPX quoteright sacute -60
+KPX quoteright scaron -60
+KPX quoteright scedilla -60
+KPX quoteright scommaaccent -60
+KPX quoteright space -80
+KPX quoteright v -20
+KPX r c -20
+KPX r cacute -20
+KPX r ccaron -20
+KPX r ccedilla -20
+KPX r comma -60
+KPX r d -20
+KPX r dcroat -20
+KPX r g -15
+KPX r gbreve -15
+KPX r gcommaaccent -15
+KPX r hyphen -20
+KPX r o -20
+KPX r oacute -20
+KPX r ocircumflex -20
+KPX r odieresis -20
+KPX r ograve -20
+KPX r ohungarumlaut -20
+KPX r omacron -20
+KPX r oslash -20
+KPX r otilde -20
+KPX r period -60
+KPX r q -20
+KPX r s -15
+KPX r sacute -15
+KPX r scaron -15
+KPX r scedilla -15
+KPX r scommaaccent -15
+KPX r t 20
+KPX r tcommaaccent 20
+KPX r v 10
+KPX r y 10
+KPX r yacute 10
+KPX r ydieresis 10
+KPX racute c -20
+KPX racute cacute -20
+KPX racute ccaron -20
+KPX racute ccedilla -20
+KPX racute comma -60
+KPX racute d -20
+KPX racute dcroat -20
+KPX racute g -15
+KPX racute gbreve -15
+KPX racute gcommaaccent -15
+KPX racute hyphen -20
+KPX racute o -20
+KPX racute oacute -20
+KPX racute ocircumflex -20
+KPX racute odieresis -20
+KPX racute ograve -20
+KPX racute ohungarumlaut -20
+KPX racute omacron -20
+KPX racute oslash -20
+KPX racute otilde -20
+KPX racute period -60
+KPX racute q -20
+KPX racute s -15
+KPX racute sacute -15
+KPX racute scaron -15
+KPX racute scedilla -15
+KPX racute scommaaccent -15
+KPX racute t 20
+KPX racute tcommaaccent 20
+KPX racute v 10
+KPX racute y 10
+KPX racute yacute 10
+KPX racute ydieresis 10
+KPX rcaron c -20
+KPX rcaron cacute -20
+KPX rcaron ccaron -20
+KPX rcaron ccedilla -20
+KPX rcaron comma -60
+KPX rcaron d -20
+KPX rcaron dcroat -20
+KPX rcaron g -15
+KPX rcaron gbreve -15
+KPX rcaron gcommaaccent -15
+KPX rcaron hyphen -20
+KPX rcaron o -20
+KPX rcaron oacute -20
+KPX rcaron ocircumflex -20
+KPX rcaron odieresis -20
+KPX rcaron ograve -20
+KPX rcaron ohungarumlaut -20
+KPX rcaron omacron -20
+KPX rcaron oslash -20
+KPX rcaron otilde -20
+KPX rcaron period -60
+KPX rcaron q -20
+KPX rcaron s -15
+KPX rcaron sacute -15
+KPX rcaron scaron -15
+KPX rcaron scedilla -15
+KPX rcaron scommaaccent -15
+KPX rcaron t 20
+KPX rcaron tcommaaccent 20
+KPX rcaron v 10
+KPX rcaron y 10
+KPX rcaron yacute 10
+KPX rcaron ydieresis 10
+KPX rcommaaccent c -20
+KPX rcommaaccent cacute -20
+KPX rcommaaccent ccaron -20
+KPX rcommaaccent ccedilla -20
+KPX rcommaaccent comma -60
+KPX rcommaaccent d -20
+KPX rcommaaccent dcroat -20
+KPX rcommaaccent g -15
+KPX rcommaaccent gbreve -15
+KPX rcommaaccent gcommaaccent -15
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -20
+KPX rcommaaccent oacute -20
+KPX rcommaaccent ocircumflex -20
+KPX rcommaaccent odieresis -20
+KPX rcommaaccent ograve -20
+KPX rcommaaccent ohungarumlaut -20
+KPX rcommaaccent omacron -20
+KPX rcommaaccent oslash -20
+KPX rcommaaccent otilde -20
+KPX rcommaaccent period -60
+KPX rcommaaccent q -20
+KPX rcommaaccent s -15
+KPX rcommaaccent sacute -15
+KPX rcommaaccent scaron -15
+KPX rcommaaccent scedilla -15
+KPX rcommaaccent scommaaccent -15
+KPX rcommaaccent t 20
+KPX rcommaaccent tcommaaccent 20
+KPX rcommaaccent v 10
+KPX rcommaaccent y 10
+KPX rcommaaccent yacute 10
+KPX rcommaaccent ydieresis 10
+KPX s w -15
+KPX sacute w -15
+KPX scaron w -15
+KPX scedilla w -15
+KPX scommaaccent w -15
+KPX semicolon space -40
+KPX space T -100
+KPX space Tcaron -100
+KPX space Tcommaaccent -100
+KPX space V -80
+KPX space W -80
+KPX space Y -120
+KPX space Yacute -120
+KPX space Ydieresis -120
+KPX space quotedblleft -80
+KPX space quoteleft -60
+KPX v a -20
+KPX v aacute -20
+KPX v abreve -20
+KPX v acircumflex -20
+KPX v adieresis -20
+KPX v agrave -20
+KPX v amacron -20
+KPX v aogonek -20
+KPX v aring -20
+KPX v atilde -20
+KPX v comma -80
+KPX v o -30
+KPX v oacute -30
+KPX v ocircumflex -30
+KPX v odieresis -30
+KPX v ograve -30
+KPX v ohungarumlaut -30
+KPX v omacron -30
+KPX v oslash -30
+KPX v otilde -30
+KPX v period -80
+KPX w comma -40
+KPX w o -20
+KPX w oacute -20
+KPX w ocircumflex -20
+KPX w odieresis -20
+KPX w ograve -20
+KPX w ohungarumlaut -20
+KPX w omacron -20
+KPX w oslash -20
+KPX w otilde -20
+KPX w period -40
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y a -30
+KPX y aacute -30
+KPX y abreve -30
+KPX y acircumflex -30
+KPX y adieresis -30
+KPX y agrave -30
+KPX y amacron -30
+KPX y aogonek -30
+KPX y aring -30
+KPX y atilde -30
+KPX y comma -80
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -80
+KPX yacute a -30
+KPX yacute aacute -30
+KPX yacute abreve -30
+KPX yacute acircumflex -30
+KPX yacute adieresis -30
+KPX yacute agrave -30
+KPX yacute amacron -30
+KPX yacute aogonek -30
+KPX yacute aring -30
+KPX yacute atilde -30
+KPX yacute comma -80
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -80
+KPX ydieresis a -30
+KPX ydieresis aacute -30
+KPX ydieresis abreve -30
+KPX ydieresis acircumflex -30
+KPX ydieresis adieresis -30
+KPX ydieresis agrave -30
+KPX ydieresis amacron -30
+KPX ydieresis aogonek -30
+KPX ydieresis aring -30
+KPX ydieresis atilde -30
+KPX ydieresis comma -80
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -80
+KPX z e 10
+KPX z eacute 10
+KPX z ecaron 10
+KPX z ecircumflex 10
+KPX z edieresis 10
+KPX z edotaccent 10
+KPX z egrave 10
+KPX z emacron 10
+KPX z eogonek 10
+KPX zacute e 10
+KPX zacute eacute 10
+KPX zacute ecaron 10
+KPX zacute ecircumflex 10
+KPX zacute edieresis 10
+KPX zacute edotaccent 10
+KPX zacute egrave 10
+KPX zacute emacron 10
+KPX zacute eogonek 10
+KPX zcaron e 10
+KPX zcaron eacute 10
+KPX zcaron ecaron 10
+KPX zcaron ecircumflex 10
+KPX zcaron edieresis 10
+KPX zcaron edotaccent 10
+KPX zcaron egrave 10
+KPX zcaron emacron 10
+KPX zcaron eogonek 10
+KPX zdotaccent e 10
+KPX zdotaccent eacute 10
+KPX zdotaccent ecaron 10
+KPX zdotaccent ecircumflex 10
+KPX zdotaccent edieresis 10
+KPX zdotaccent edotaccent 10
+KPX zdotaccent egrave 10
+KPX zdotaccent emacron 10
+KPX zdotaccent eogonek 10
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm
new file mode 100644
index 0000000..9ea431a
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm
@@ -0,0 +1,3052 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:44:31 1997
+Comment UniqueID 43055
+Comment VMusage 14960 69346
+FontName Helvetica-Oblique
+FullName Helvetica Oblique
+FamilyName Helvetica
+Weight Medium
+ItalicAngle -12
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -170 -225 1116 931 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StdHW 76
+StdVW 88
+StartCharMetrics 315
+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 46 -225 332 775 ;
+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 127 405 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 141 405 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 278 ; N Idieresis ; B 91 0 458 901 ;
+C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ;
+C -1 ; WX 556 ; N abreve ; B 61 -15 578 731 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 94 -15 677 734 ;
+C -1 ; WX 556 ; N ecaron ; B 84 -15 580 734 ;
+C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ;
+C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ;
+C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ;
+C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ;
+C -1 ; WX 500 ; N scommaaccent ; B 63 -225 529 538 ;
+C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ;
+C -1 ; WX 722 ; N Uring ; B 123 -19 797 931 ;
+C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ;
+C -1 ; WX 556 ; N aogonek ; B 61 -220 559 538 ;
+C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ;
+C -1 ; WX 556 ; N uogonek ; B 94 -225 600 523 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ;
+C -1 ; WX 722 ; N Dcroat ; B 69 0 764 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 39 -225 172 -40 ;
+C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ;
+C -1 ; WX 667 ; N Emacron ; B 86 0 762 879 ;
+C -1 ; WX 500 ; N ccaron ; B 74 -15 553 734 ;
+C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 799 718 ;
+C -1 ; WX 222 ; N lacute ; B 67 0 461 929 ;
+C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 148 -225 750 718 ;
+C -1 ; WX 722 ; N Cacute ; B 108 -19 782 929 ;
+C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ;
+C -1 ; WX 667 ; N Edotaccent ; B 86 0 762 901 ;
+C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ;
+C -1 ; WX 500 ; N scedilla ; B 63 -225 529 538 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ;
+C -1 ; WX 471 ; N lozenge ; B 88 0 540 728 ;
+C -1 ; WX 722 ; N Rcaron ; B 88 0 773 929 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 111 -225 799 737 ;
+C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ;
+C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ;
+C -1 ; WX 667 ; N Amacron ; B 14 0 677 879 ;
+C -1 ; WX 333 ; N rcaron ; B 77 0 508 734 ;
+C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 23 0 741 901 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ;
+C -1 ; WX 778 ; N Omacron ; B 105 -19 826 879 ;
+C -1 ; WX 722 ; N Racute ; B 88 0 773 929 ;
+C -1 ; WX 667 ; N Sacute ; B 90 -19 713 929 ;
+C -1 ; WX 643 ; N dcaron ; B 84 -15 808 718 ;
+C -1 ; WX 722 ; N Umacron ; B 123 -19 797 879 ;
+C -1 ; WX 556 ; N uring ; B 94 -15 600 756 ;
+C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ;
+C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Abreve ; B 14 0 685 926 ;
+C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ;
+C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ;
+C -1 ; WX 611 ; N Tcaron ; B 148 0 750 929 ;
+C -1 ; WX 476 ; N partialdiff ; B 41 -38 550 714 ;
+C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ;
+C -1 ; WX 722 ; N Nacute ; B 76 0 799 929 ;
+C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ;
+C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ;
+C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ;
+C -1 ; WX 500 ; N cacute ; B 74 -15 559 734 ;
+C -1 ; WX 556 ; N nacute ; B 65 0 587 734 ;
+C -1 ; WX 556 ; N umacron ; B 94 -15 600 684 ;
+C -1 ; WX 722 ; N Ncaron ; B 76 0 799 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ;
+C -1 ; WX 260 ; N brokenbar ; B 62 -150 316 700 ;
+C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 111 -19 799 926 ;
+C -1 ; WX 278 ; N Idotaccent ; B 91 0 377 901 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 671 706 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ;
+C -1 ; WX 333 ; N racute ; B 77 0 475 734 ;
+C -1 ; WX 556 ; N omacron ; B 83 -14 585 684 ;
+C -1 ; WX 611 ; N Zacute ; B 23 0 741 929 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 620 674 ;
+C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ;
+C -1 ; WX 222 ; N lcommaaccent ; B 25 -225 308 718 ;
+C -1 ; WX 317 ; N tcaron ; B 102 -7 501 808 ;
+C -1 ; WX 556 ; N eogonek ; B 84 -225 578 538 ;
+C -1 ; WX 722 ; N Uogonek ; B 123 -225 797 718 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ;
+C -1 ; WX 500 ; N zacute ; B 31 0 571 734 ;
+C -1 ; WX 222 ; N iogonek ; B -61 -225 308 718 ;
+C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ;
+C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ;
+C -1 ; WX 556 ; N amacron ; B 61 -15 580 684 ;
+C -1 ; WX 500 ; N sacute ; B 63 -15 559 734 ;
+C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ;
+C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ;
+C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ;
+C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ;
+C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ;
+C -1 ; WX 556 ; N ohungarumlaut ; B 83 -14 677 734 ;
+C -1 ; WX 667 ; N Eogonek ; B 86 -220 762 718 ;
+C -1 ; WX 556 ; N dcroat ; B 84 -15 689 718 ;
+C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ;
+C -1 ; WX 667 ; N Scedilla ; B 90 -225 713 737 ;
+C -1 ; WX 299 ; N lcaron ; B 67 0 464 718 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 808 718 ;
+C -1 ; WX 556 ; N Lacute ; B 76 0 555 929 ;
+C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 84 -15 578 706 ;
+C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ;
+C -1 ; WX 278 ; N Imacron ; B 91 0 483 879 ;
+C -1 ; WX 556 ; N Lcaron ; B 76 0 570 718 ;
+C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 666 674 ;
+C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 123 -19 801 929 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ;
+C -1 ; WX 556 ; N emacron ; B 84 -15 580 684 ;
+C -1 ; WX 556 ; N gbreve ; B 42 -220 610 731 ;
+C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ;
+C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 90 -225 713 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 105 -19 829 929 ;
+C -1 ; WX 400 ; N degree ; B 169 411 468 703 ;
+C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ;
+C -1 ; WX 722 ; N Ccaron ; B 108 -19 782 929 ;
+C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ;
+C -1 ; WX 453 ; N radical ; B 79 -80 617 762 ;
+C -1 ; WX 722 ; N Dcaron ; B 81 0 764 929 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 30 -225 446 538 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ;
+C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 773 718 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 555 718 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ;
+C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ;
+C -1 ; WX 500 ; N zdotaccent ; B 31 0 571 706 ;
+C -1 ; WX 667 ; N Ecaron ; B 86 0 762 929 ;
+C -1 ; WX 278 ; N Iogonek ; B -33 -225 341 718 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 600 718 ;
+C -1 ; WX 584 ; N minus ; B 85 216 606 289 ;
+C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ;
+C -1 ; WX 556 ; N ncaron ; B 65 0 580 734 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 63 -225 368 669 ;
+C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ;
+C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ;
+C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ;
+C -1 ; WX 549 ; N notequal ; B 34 -35 623 551 ;
+C -1 ; WX 556 ; N gcommaaccent ; B 42 -220 610 822 ;
+C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 573 538 ;
+C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ;
+C -1 ; WX 278 ; N imacron ; B 95 0 417 684 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2705
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -30
+KPX A Gbreve -30
+KPX A Gcommaaccent -30
+KPX A O -30
+KPX A Oacute -30
+KPX A Ocircumflex -30
+KPX A Odieresis -30
+KPX A Ograve -30
+KPX A Ohungarumlaut -30
+KPX A Omacron -30
+KPX A Oslash -30
+KPX A Otilde -30
+KPX A Q -30
+KPX A T -120
+KPX A Tcaron -120
+KPX A Tcommaaccent -120
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -70
+KPX A W -50
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -40
+KPX A y -40
+KPX A yacute -40
+KPX A ydieresis -40
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -30
+KPX Aacute Gbreve -30
+KPX Aacute Gcommaaccent -30
+KPX Aacute O -30
+KPX Aacute Oacute -30
+KPX Aacute Ocircumflex -30
+KPX Aacute Odieresis -30
+KPX Aacute Ograve -30
+KPX Aacute Ohungarumlaut -30
+KPX Aacute Omacron -30
+KPX Aacute Oslash -30
+KPX Aacute Otilde -30
+KPX Aacute Q -30
+KPX Aacute T -120
+KPX Aacute Tcaron -120
+KPX Aacute Tcommaaccent -120
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -70
+KPX Aacute W -50
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -40
+KPX Aacute y -40
+KPX Aacute yacute -40
+KPX Aacute ydieresis -40
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -30
+KPX Abreve Gbreve -30
+KPX Abreve Gcommaaccent -30
+KPX Abreve O -30
+KPX Abreve Oacute -30
+KPX Abreve Ocircumflex -30
+KPX Abreve Odieresis -30
+KPX Abreve Ograve -30
+KPX Abreve Ohungarumlaut -30
+KPX Abreve Omacron -30
+KPX Abreve Oslash -30
+KPX Abreve Otilde -30
+KPX Abreve Q -30
+KPX Abreve T -120
+KPX Abreve Tcaron -120
+KPX Abreve Tcommaaccent -120
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -70
+KPX Abreve W -50
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -40
+KPX Abreve y -40
+KPX Abreve yacute -40
+KPX Abreve ydieresis -40
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -30
+KPX Acircumflex Gbreve -30
+KPX Acircumflex Gcommaaccent -30
+KPX Acircumflex O -30
+KPX Acircumflex Oacute -30
+KPX Acircumflex Ocircumflex -30
+KPX Acircumflex Odieresis -30
+KPX Acircumflex Ograve -30
+KPX Acircumflex Ohungarumlaut -30
+KPX Acircumflex Omacron -30
+KPX Acircumflex Oslash -30
+KPX Acircumflex Otilde -30
+KPX Acircumflex Q -30
+KPX Acircumflex T -120
+KPX Acircumflex Tcaron -120
+KPX Acircumflex Tcommaaccent -120
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -70
+KPX Acircumflex W -50
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -40
+KPX Acircumflex y -40
+KPX Acircumflex yacute -40
+KPX Acircumflex ydieresis -40
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -30
+KPX Adieresis Gbreve -30
+KPX Adieresis Gcommaaccent -30
+KPX Adieresis O -30
+KPX Adieresis Oacute -30
+KPX Adieresis Ocircumflex -30
+KPX Adieresis Odieresis -30
+KPX Adieresis Ograve -30
+KPX Adieresis Ohungarumlaut -30
+KPX Adieresis Omacron -30
+KPX Adieresis Oslash -30
+KPX Adieresis Otilde -30
+KPX Adieresis Q -30
+KPX Adieresis T -120
+KPX Adieresis Tcaron -120
+KPX Adieresis Tcommaaccent -120
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -70
+KPX Adieresis W -50
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -40
+KPX Adieresis y -40
+KPX Adieresis yacute -40
+KPX Adieresis ydieresis -40
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -30
+KPX Agrave Gbreve -30
+KPX Agrave Gcommaaccent -30
+KPX Agrave O -30
+KPX Agrave Oacute -30
+KPX Agrave Ocircumflex -30
+KPX Agrave Odieresis -30
+KPX Agrave Ograve -30
+KPX Agrave Ohungarumlaut -30
+KPX Agrave Omacron -30
+KPX Agrave Oslash -30
+KPX Agrave Otilde -30
+KPX Agrave Q -30
+KPX Agrave T -120
+KPX Agrave Tcaron -120
+KPX Agrave Tcommaaccent -120
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -70
+KPX Agrave W -50
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -40
+KPX Agrave y -40
+KPX Agrave yacute -40
+KPX Agrave ydieresis -40
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -30
+KPX Amacron Gbreve -30
+KPX Amacron Gcommaaccent -30
+KPX Amacron O -30
+KPX Amacron Oacute -30
+KPX Amacron Ocircumflex -30
+KPX Amacron Odieresis -30
+KPX Amacron Ograve -30
+KPX Amacron Ohungarumlaut -30
+KPX Amacron Omacron -30
+KPX Amacron Oslash -30
+KPX Amacron Otilde -30
+KPX Amacron Q -30
+KPX Amacron T -120
+KPX Amacron Tcaron -120
+KPX Amacron Tcommaaccent -120
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -70
+KPX Amacron W -50
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -40
+KPX Amacron y -40
+KPX Amacron yacute -40
+KPX Amacron ydieresis -40
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -30
+KPX Aogonek Gbreve -30
+KPX Aogonek Gcommaaccent -30
+KPX Aogonek O -30
+KPX Aogonek Oacute -30
+KPX Aogonek Ocircumflex -30
+KPX Aogonek Odieresis -30
+KPX Aogonek Ograve -30
+KPX Aogonek Ohungarumlaut -30
+KPX Aogonek Omacron -30
+KPX Aogonek Oslash -30
+KPX Aogonek Otilde -30
+KPX Aogonek Q -30
+KPX Aogonek T -120
+KPX Aogonek Tcaron -120
+KPX Aogonek Tcommaaccent -120
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -70
+KPX Aogonek W -50
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -40
+KPX Aogonek y -40
+KPX Aogonek yacute -40
+KPX Aogonek ydieresis -40
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -30
+KPX Aring Gbreve -30
+KPX Aring Gcommaaccent -30
+KPX Aring O -30
+KPX Aring Oacute -30
+KPX Aring Ocircumflex -30
+KPX Aring Odieresis -30
+KPX Aring Ograve -30
+KPX Aring Ohungarumlaut -30
+KPX Aring Omacron -30
+KPX Aring Oslash -30
+KPX Aring Otilde -30
+KPX Aring Q -30
+KPX Aring T -120
+KPX Aring Tcaron -120
+KPX Aring Tcommaaccent -120
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -70
+KPX Aring W -50
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -40
+KPX Aring y -40
+KPX Aring yacute -40
+KPX Aring ydieresis -40
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -30
+KPX Atilde Gbreve -30
+KPX Atilde Gcommaaccent -30
+KPX Atilde O -30
+KPX Atilde Oacute -30
+KPX Atilde Ocircumflex -30
+KPX Atilde Odieresis -30
+KPX Atilde Ograve -30
+KPX Atilde Ohungarumlaut -30
+KPX Atilde Omacron -30
+KPX Atilde Oslash -30
+KPX Atilde Otilde -30
+KPX Atilde Q -30
+KPX Atilde T -120
+KPX Atilde Tcaron -120
+KPX Atilde Tcommaaccent -120
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -70
+KPX Atilde W -50
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -40
+KPX Atilde y -40
+KPX Atilde yacute -40
+KPX Atilde ydieresis -40
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX B comma -20
+KPX B period -20
+KPX C comma -30
+KPX C period -30
+KPX Cacute comma -30
+KPX Cacute period -30
+KPX Ccaron comma -30
+KPX Ccaron period -30
+KPX Ccedilla comma -30
+KPX Ccedilla period -30
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -70
+KPX D W -40
+KPX D Y -90
+KPX D Yacute -90
+KPX D Ydieresis -90
+KPX D comma -70
+KPX D period -70
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -70
+KPX Dcaron W -40
+KPX Dcaron Y -90
+KPX Dcaron Yacute -90
+KPX Dcaron Ydieresis -90
+KPX Dcaron comma -70
+KPX Dcaron period -70
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -70
+KPX Dcroat W -40
+KPX Dcroat Y -90
+KPX Dcroat Yacute -90
+KPX Dcroat Ydieresis -90
+KPX Dcroat comma -70
+KPX Dcroat period -70
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -50
+KPX F aacute -50
+KPX F abreve -50
+KPX F acircumflex -50
+KPX F adieresis -50
+KPX F agrave -50
+KPX F amacron -50
+KPX F aogonek -50
+KPX F aring -50
+KPX F atilde -50
+KPX F comma -150
+KPX F e -30
+KPX F eacute -30
+KPX F ecaron -30
+KPX F ecircumflex -30
+KPX F edieresis -30
+KPX F edotaccent -30
+KPX F egrave -30
+KPX F emacron -30
+KPX F eogonek -30
+KPX F o -30
+KPX F oacute -30
+KPX F ocircumflex -30
+KPX F odieresis -30
+KPX F ograve -30
+KPX F ohungarumlaut -30
+KPX F omacron -30
+KPX F oslash -30
+KPX F otilde -30
+KPX F period -150
+KPX F r -45
+KPX F racute -45
+KPX F rcaron -45
+KPX F rcommaaccent -45
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J a -20
+KPX J aacute -20
+KPX J abreve -20
+KPX J acircumflex -20
+KPX J adieresis -20
+KPX J agrave -20
+KPX J amacron -20
+KPX J aogonek -20
+KPX J aring -20
+KPX J atilde -20
+KPX J comma -30
+KPX J period -30
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -40
+KPX K eacute -40
+KPX K ecaron -40
+KPX K ecircumflex -40
+KPX K edieresis -40
+KPX K edotaccent -40
+KPX K egrave -40
+KPX K emacron -40
+KPX K eogonek -40
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -50
+KPX K yacute -50
+KPX K ydieresis -50
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -40
+KPX Kcommaaccent eacute -40
+KPX Kcommaaccent ecaron -40
+KPX Kcommaaccent ecircumflex -40
+KPX Kcommaaccent edieresis -40
+KPX Kcommaaccent edotaccent -40
+KPX Kcommaaccent egrave -40
+KPX Kcommaaccent emacron -40
+KPX Kcommaaccent eogonek -40
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -50
+KPX Kcommaaccent yacute -50
+KPX Kcommaaccent ydieresis -50
+KPX L T -110
+KPX L Tcaron -110
+KPX L Tcommaaccent -110
+KPX L V -110
+KPX L W -70
+KPX L Y -140
+KPX L Yacute -140
+KPX L Ydieresis -140
+KPX L quotedblright -140
+KPX L quoteright -160
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -110
+KPX Lacute Tcaron -110
+KPX Lacute Tcommaaccent -110
+KPX Lacute V -110
+KPX Lacute W -70
+KPX Lacute Y -140
+KPX Lacute Yacute -140
+KPX Lacute Ydieresis -140
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -160
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcaron T -110
+KPX Lcaron Tcaron -110
+KPX Lcaron Tcommaaccent -110
+KPX Lcaron V -110
+KPX Lcaron W -70
+KPX Lcaron Y -140
+KPX Lcaron Yacute -140
+KPX Lcaron Ydieresis -140
+KPX Lcaron quotedblright -140
+KPX Lcaron quoteright -160
+KPX Lcaron y -30
+KPX Lcaron yacute -30
+KPX Lcaron ydieresis -30
+KPX Lcommaaccent T -110
+KPX Lcommaaccent Tcaron -110
+KPX Lcommaaccent Tcommaaccent -110
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -70
+KPX Lcommaaccent Y -140
+KPX Lcommaaccent Yacute -140
+KPX Lcommaaccent Ydieresis -140
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -160
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -110
+KPX Lslash Tcaron -110
+KPX Lslash Tcommaaccent -110
+KPX Lslash V -110
+KPX Lslash W -70
+KPX Lslash Y -140
+KPX Lslash Yacute -140
+KPX Lslash Ydieresis -140
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -160
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -20
+KPX O Aacute -20
+KPX O Abreve -20
+KPX O Acircumflex -20
+KPX O Adieresis -20
+KPX O Agrave -20
+KPX O Amacron -20
+KPX O Aogonek -20
+KPX O Aring -20
+KPX O Atilde -20
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -30
+KPX O X -60
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -20
+KPX Oacute Aacute -20
+KPX Oacute Abreve -20
+KPX Oacute Acircumflex -20
+KPX Oacute Adieresis -20
+KPX Oacute Agrave -20
+KPX Oacute Amacron -20
+KPX Oacute Aogonek -20
+KPX Oacute Aring -20
+KPX Oacute Atilde -20
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -30
+KPX Oacute X -60
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -20
+KPX Ocircumflex Aacute -20
+KPX Ocircumflex Abreve -20
+KPX Ocircumflex Acircumflex -20
+KPX Ocircumflex Adieresis -20
+KPX Ocircumflex Agrave -20
+KPX Ocircumflex Amacron -20
+KPX Ocircumflex Aogonek -20
+KPX Ocircumflex Aring -20
+KPX Ocircumflex Atilde -20
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -30
+KPX Ocircumflex X -60
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -20
+KPX Odieresis Aacute -20
+KPX Odieresis Abreve -20
+KPX Odieresis Acircumflex -20
+KPX Odieresis Adieresis -20
+KPX Odieresis Agrave -20
+KPX Odieresis Amacron -20
+KPX Odieresis Aogonek -20
+KPX Odieresis Aring -20
+KPX Odieresis Atilde -20
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -30
+KPX Odieresis X -60
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -20
+KPX Ograve Aacute -20
+KPX Ograve Abreve -20
+KPX Ograve Acircumflex -20
+KPX Ograve Adieresis -20
+KPX Ograve Agrave -20
+KPX Ograve Amacron -20
+KPX Ograve Aogonek -20
+KPX Ograve Aring -20
+KPX Ograve Atilde -20
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -30
+KPX Ograve X -60
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -20
+KPX Ohungarumlaut Aacute -20
+KPX Ohungarumlaut Abreve -20
+KPX Ohungarumlaut Acircumflex -20
+KPX Ohungarumlaut Adieresis -20
+KPX Ohungarumlaut Agrave -20
+KPX Ohungarumlaut Amacron -20
+KPX Ohungarumlaut Aogonek -20
+KPX Ohungarumlaut Aring -20
+KPX Ohungarumlaut Atilde -20
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -30
+KPX Ohungarumlaut X -60
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -20
+KPX Omacron Aacute -20
+KPX Omacron Abreve -20
+KPX Omacron Acircumflex -20
+KPX Omacron Adieresis -20
+KPX Omacron Agrave -20
+KPX Omacron Amacron -20
+KPX Omacron Aogonek -20
+KPX Omacron Aring -20
+KPX Omacron Atilde -20
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -30
+KPX Omacron X -60
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -20
+KPX Oslash Aacute -20
+KPX Oslash Abreve -20
+KPX Oslash Acircumflex -20
+KPX Oslash Adieresis -20
+KPX Oslash Agrave -20
+KPX Oslash Amacron -20
+KPX Oslash Aogonek -20
+KPX Oslash Aring -20
+KPX Oslash Atilde -20
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -30
+KPX Oslash X -60
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -20
+KPX Otilde Aacute -20
+KPX Otilde Abreve -20
+KPX Otilde Acircumflex -20
+KPX Otilde Adieresis -20
+KPX Otilde Agrave -20
+KPX Otilde Amacron -20
+KPX Otilde Aogonek -20
+KPX Otilde Aring -20
+KPX Otilde Atilde -20
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -30
+KPX Otilde X -60
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -120
+KPX P Aacute -120
+KPX P Abreve -120
+KPX P Acircumflex -120
+KPX P Adieresis -120
+KPX P Agrave -120
+KPX P Amacron -120
+KPX P Aogonek -120
+KPX P Aring -120
+KPX P Atilde -120
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -180
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -50
+KPX P oacute -50
+KPX P ocircumflex -50
+KPX P odieresis -50
+KPX P ograve -50
+KPX P ohungarumlaut -50
+KPX P omacron -50
+KPX P oslash -50
+KPX P otilde -50
+KPX P period -180
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -50
+KPX R W -30
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -50
+KPX Racute W -30
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -50
+KPX Rcaron W -30
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -30
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX S comma -20
+KPX S period -20
+KPX Sacute comma -20
+KPX Sacute period -20
+KPX Scaron comma -20
+KPX Scaron period -20
+KPX Scedilla comma -20
+KPX Scedilla period -20
+KPX Scommaaccent comma -20
+KPX Scommaaccent period -20
+KPX T A -120
+KPX T Aacute -120
+KPX T Abreve -120
+KPX T Acircumflex -120
+KPX T Adieresis -120
+KPX T Agrave -120
+KPX T Amacron -120
+KPX T Aogonek -120
+KPX T Aring -120
+KPX T Atilde -120
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -120
+KPX T aacute -120
+KPX T abreve -60
+KPX T acircumflex -120
+KPX T adieresis -120
+KPX T agrave -120
+KPX T amacron -60
+KPX T aogonek -120
+KPX T aring -120
+KPX T atilde -60
+KPX T colon -20
+KPX T comma -120
+KPX T e -120
+KPX T eacute -120
+KPX T ecaron -120
+KPX T ecircumflex -120
+KPX T edieresis -120
+KPX T edotaccent -120
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -120
+KPX T hyphen -140
+KPX T o -120
+KPX T oacute -120
+KPX T ocircumflex -120
+KPX T odieresis -120
+KPX T ograve -120
+KPX T ohungarumlaut -120
+KPX T omacron -60
+KPX T oslash -120
+KPX T otilde -60
+KPX T period -120
+KPX T r -120
+KPX T racute -120
+KPX T rcaron -120
+KPX T rcommaaccent -120
+KPX T semicolon -20
+KPX T u -120
+KPX T uacute -120
+KPX T ucircumflex -120
+KPX T udieresis -120
+KPX T ugrave -120
+KPX T uhungarumlaut -120
+KPX T umacron -60
+KPX T uogonek -120
+KPX T uring -120
+KPX T w -120
+KPX T y -120
+KPX T yacute -120
+KPX T ydieresis -60
+KPX Tcaron A -120
+KPX Tcaron Aacute -120
+KPX Tcaron Abreve -120
+KPX Tcaron Acircumflex -120
+KPX Tcaron Adieresis -120
+KPX Tcaron Agrave -120
+KPX Tcaron Amacron -120
+KPX Tcaron Aogonek -120
+KPX Tcaron Aring -120
+KPX Tcaron Atilde -120
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -120
+KPX Tcaron aacute -120
+KPX Tcaron abreve -60
+KPX Tcaron acircumflex -120
+KPX Tcaron adieresis -120
+KPX Tcaron agrave -120
+KPX Tcaron amacron -60
+KPX Tcaron aogonek -120
+KPX Tcaron aring -120
+KPX Tcaron atilde -60
+KPX Tcaron colon -20
+KPX Tcaron comma -120
+KPX Tcaron e -120
+KPX Tcaron eacute -120
+KPX Tcaron ecaron -120
+KPX Tcaron ecircumflex -120
+KPX Tcaron edieresis -120
+KPX Tcaron edotaccent -120
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -120
+KPX Tcaron hyphen -140
+KPX Tcaron o -120
+KPX Tcaron oacute -120
+KPX Tcaron ocircumflex -120
+KPX Tcaron odieresis -120
+KPX Tcaron ograve -120
+KPX Tcaron ohungarumlaut -120
+KPX Tcaron omacron -60
+KPX Tcaron oslash -120
+KPX Tcaron otilde -60
+KPX Tcaron period -120
+KPX Tcaron r -120
+KPX Tcaron racute -120
+KPX Tcaron rcaron -120
+KPX Tcaron rcommaaccent -120
+KPX Tcaron semicolon -20
+KPX Tcaron u -120
+KPX Tcaron uacute -120
+KPX Tcaron ucircumflex -120
+KPX Tcaron udieresis -120
+KPX Tcaron ugrave -120
+KPX Tcaron uhungarumlaut -120
+KPX Tcaron umacron -60
+KPX Tcaron uogonek -120
+KPX Tcaron uring -120
+KPX Tcaron w -120
+KPX Tcaron y -120
+KPX Tcaron yacute -120
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -120
+KPX Tcommaaccent Aacute -120
+KPX Tcommaaccent Abreve -120
+KPX Tcommaaccent Acircumflex -120
+KPX Tcommaaccent Adieresis -120
+KPX Tcommaaccent Agrave -120
+KPX Tcommaaccent Amacron -120
+KPX Tcommaaccent Aogonek -120
+KPX Tcommaaccent Aring -120
+KPX Tcommaaccent Atilde -120
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -120
+KPX Tcommaaccent aacute -120
+KPX Tcommaaccent abreve -60
+KPX Tcommaaccent acircumflex -120
+KPX Tcommaaccent adieresis -120
+KPX Tcommaaccent agrave -120
+KPX Tcommaaccent amacron -60
+KPX Tcommaaccent aogonek -120
+KPX Tcommaaccent aring -120
+KPX Tcommaaccent atilde -60
+KPX Tcommaaccent colon -20
+KPX Tcommaaccent comma -120
+KPX Tcommaaccent e -120
+KPX Tcommaaccent eacute -120
+KPX Tcommaaccent ecaron -120
+KPX Tcommaaccent ecircumflex -120
+KPX Tcommaaccent edieresis -120
+KPX Tcommaaccent edotaccent -120
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -120
+KPX Tcommaaccent hyphen -140
+KPX Tcommaaccent o -120
+KPX Tcommaaccent oacute -120
+KPX Tcommaaccent ocircumflex -120
+KPX Tcommaaccent odieresis -120
+KPX Tcommaaccent ograve -120
+KPX Tcommaaccent ohungarumlaut -120
+KPX Tcommaaccent omacron -60
+KPX Tcommaaccent oslash -120
+KPX Tcommaaccent otilde -60
+KPX Tcommaaccent period -120
+KPX Tcommaaccent r -120
+KPX Tcommaaccent racute -120
+KPX Tcommaaccent rcaron -120
+KPX Tcommaaccent rcommaaccent -120
+KPX Tcommaaccent semicolon -20
+KPX Tcommaaccent u -120
+KPX Tcommaaccent uacute -120
+KPX Tcommaaccent ucircumflex -120
+KPX Tcommaaccent udieresis -120
+KPX Tcommaaccent ugrave -120
+KPX Tcommaaccent uhungarumlaut -120
+KPX Tcommaaccent umacron -60
+KPX Tcommaaccent uogonek -120
+KPX Tcommaaccent uring -120
+KPX Tcommaaccent w -120
+KPX Tcommaaccent y -120
+KPX Tcommaaccent yacute -120
+KPX Tcommaaccent ydieresis -60
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -40
+KPX U period -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -40
+KPX Uacute period -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -40
+KPX Ucircumflex period -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -40
+KPX Udieresis period -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -40
+KPX Ugrave period -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -40
+KPX Uhungarumlaut period -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -40
+KPX Umacron period -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -40
+KPX Uogonek period -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -40
+KPX Uring period -40
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -40
+KPX V Gbreve -40
+KPX V Gcommaaccent -40
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -70
+KPX V aacute -70
+KPX V abreve -70
+KPX V acircumflex -70
+KPX V adieresis -70
+KPX V agrave -70
+KPX V amacron -70
+KPX V aogonek -70
+KPX V aring -70
+KPX V atilde -70
+KPX V colon -40
+KPX V comma -125
+KPX V e -80
+KPX V eacute -80
+KPX V ecaron -80
+KPX V ecircumflex -80
+KPX V edieresis -80
+KPX V edotaccent -80
+KPX V egrave -80
+KPX V emacron -80
+KPX V eogonek -80
+KPX V hyphen -80
+KPX V o -80
+KPX V oacute -80
+KPX V ocircumflex -80
+KPX V odieresis -80
+KPX V ograve -80
+KPX V ohungarumlaut -80
+KPX V omacron -80
+KPX V oslash -80
+KPX V otilde -80
+KPX V period -125
+KPX V semicolon -40
+KPX V u -70
+KPX V uacute -70
+KPX V ucircumflex -70
+KPX V udieresis -70
+KPX V ugrave -70
+KPX V uhungarumlaut -70
+KPX V umacron -70
+KPX V uogonek -70
+KPX V uring -70
+KPX W A -50
+KPX W Aacute -50
+KPX W Abreve -50
+KPX W Acircumflex -50
+KPX W Adieresis -50
+KPX W Agrave -50
+KPX W Amacron -50
+KPX W Aogonek -50
+KPX W Aring -50
+KPX W Atilde -50
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W comma -80
+KPX W e -30
+KPX W eacute -30
+KPX W ecaron -30
+KPX W ecircumflex -30
+KPX W edieresis -30
+KPX W edotaccent -30
+KPX W egrave -30
+KPX W emacron -30
+KPX W eogonek -30
+KPX W hyphen -40
+KPX W o -30
+KPX W oacute -30
+KPX W ocircumflex -30
+KPX W odieresis -30
+KPX W ograve -30
+KPX W ohungarumlaut -30
+KPX W omacron -30
+KPX W oslash -30
+KPX W otilde -30
+KPX W period -80
+KPX W u -30
+KPX W uacute -30
+KPX W ucircumflex -30
+KPX W udieresis -30
+KPX W ugrave -30
+KPX W uhungarumlaut -30
+KPX W umacron -30
+KPX W uogonek -30
+KPX W uring -30
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -85
+KPX Y Oacute -85
+KPX Y Ocircumflex -85
+KPX Y Odieresis -85
+KPX Y Ograve -85
+KPX Y Ohungarumlaut -85
+KPX Y Omacron -85
+KPX Y Oslash -85
+KPX Y Otilde -85
+KPX Y a -140
+KPX Y aacute -140
+KPX Y abreve -70
+KPX Y acircumflex -140
+KPX Y adieresis -140
+KPX Y agrave -140
+KPX Y amacron -70
+KPX Y aogonek -140
+KPX Y aring -140
+KPX Y atilde -140
+KPX Y colon -60
+KPX Y comma -140
+KPX Y e -140
+KPX Y eacute -140
+KPX Y ecaron -140
+KPX Y ecircumflex -140
+KPX Y edieresis -140
+KPX Y edotaccent -140
+KPX Y egrave -140
+KPX Y emacron -70
+KPX Y eogonek -140
+KPX Y hyphen -140
+KPX Y i -20
+KPX Y iacute -20
+KPX Y iogonek -20
+KPX Y o -140
+KPX Y oacute -140
+KPX Y ocircumflex -140
+KPX Y odieresis -140
+KPX Y ograve -140
+KPX Y ohungarumlaut -140
+KPX Y omacron -140
+KPX Y oslash -140
+KPX Y otilde -140
+KPX Y period -140
+KPX Y semicolon -60
+KPX Y u -110
+KPX Y uacute -110
+KPX Y ucircumflex -110
+KPX Y udieresis -110
+KPX Y ugrave -110
+KPX Y uhungarumlaut -110
+KPX Y umacron -110
+KPX Y uogonek -110
+KPX Y uring -110
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -85
+KPX Yacute Oacute -85
+KPX Yacute Ocircumflex -85
+KPX Yacute Odieresis -85
+KPX Yacute Ograve -85
+KPX Yacute Ohungarumlaut -85
+KPX Yacute Omacron -85
+KPX Yacute Oslash -85
+KPX Yacute Otilde -85
+KPX Yacute a -140
+KPX Yacute aacute -140
+KPX Yacute abreve -70
+KPX Yacute acircumflex -140
+KPX Yacute adieresis -140
+KPX Yacute agrave -140
+KPX Yacute amacron -70
+KPX Yacute aogonek -140
+KPX Yacute aring -140
+KPX Yacute atilde -70
+KPX Yacute colon -60
+KPX Yacute comma -140
+KPX Yacute e -140
+KPX Yacute eacute -140
+KPX Yacute ecaron -140
+KPX Yacute ecircumflex -140
+KPX Yacute edieresis -140
+KPX Yacute edotaccent -140
+KPX Yacute egrave -140
+KPX Yacute emacron -70
+KPX Yacute eogonek -140
+KPX Yacute hyphen -140
+KPX Yacute i -20
+KPX Yacute iacute -20
+KPX Yacute iogonek -20
+KPX Yacute o -140
+KPX Yacute oacute -140
+KPX Yacute ocircumflex -140
+KPX Yacute odieresis -140
+KPX Yacute ograve -140
+KPX Yacute ohungarumlaut -140
+KPX Yacute omacron -70
+KPX Yacute oslash -140
+KPX Yacute otilde -140
+KPX Yacute period -140
+KPX Yacute semicolon -60
+KPX Yacute u -110
+KPX Yacute uacute -110
+KPX Yacute ucircumflex -110
+KPX Yacute udieresis -110
+KPX Yacute ugrave -110
+KPX Yacute uhungarumlaut -110
+KPX Yacute umacron -110
+KPX Yacute uogonek -110
+KPX Yacute uring -110
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -85
+KPX Ydieresis Oacute -85
+KPX Ydieresis Ocircumflex -85
+KPX Ydieresis Odieresis -85
+KPX Ydieresis Ograve -85
+KPX Ydieresis Ohungarumlaut -85
+KPX Ydieresis Omacron -85
+KPX Ydieresis Oslash -85
+KPX Ydieresis Otilde -85
+KPX Ydieresis a -140
+KPX Ydieresis aacute -140
+KPX Ydieresis abreve -70
+KPX Ydieresis acircumflex -140
+KPX Ydieresis adieresis -140
+KPX Ydieresis agrave -140
+KPX Ydieresis amacron -70
+KPX Ydieresis aogonek -140
+KPX Ydieresis aring -140
+KPX Ydieresis atilde -70
+KPX Ydieresis colon -60
+KPX Ydieresis comma -140
+KPX Ydieresis e -140
+KPX Ydieresis eacute -140
+KPX Ydieresis ecaron -140
+KPX Ydieresis ecircumflex -140
+KPX Ydieresis edieresis -140
+KPX Ydieresis edotaccent -140
+KPX Ydieresis egrave -140
+KPX Ydieresis emacron -70
+KPX Ydieresis eogonek -140
+KPX Ydieresis hyphen -140
+KPX Ydieresis i -20
+KPX Ydieresis iacute -20
+KPX Ydieresis iogonek -20
+KPX Ydieresis o -140
+KPX Ydieresis oacute -140
+KPX Ydieresis ocircumflex -140
+KPX Ydieresis odieresis -140
+KPX Ydieresis ograve -140
+KPX Ydieresis ohungarumlaut -140
+KPX Ydieresis omacron -140
+KPX Ydieresis oslash -140
+KPX Ydieresis otilde -140
+KPX Ydieresis period -140
+KPX Ydieresis semicolon -60
+KPX Ydieresis u -110
+KPX Ydieresis uacute -110
+KPX Ydieresis ucircumflex -110
+KPX Ydieresis udieresis -110
+KPX Ydieresis ugrave -110
+KPX Ydieresis uhungarumlaut -110
+KPX Ydieresis umacron -110
+KPX Ydieresis uogonek -110
+KPX Ydieresis uring -110
+KPX a v -20
+KPX a w -20
+KPX a y -30
+KPX a yacute -30
+KPX a ydieresis -30
+KPX aacute v -20
+KPX aacute w -20
+KPX aacute y -30
+KPX aacute yacute -30
+KPX aacute ydieresis -30
+KPX abreve v -20
+KPX abreve w -20
+KPX abreve y -30
+KPX abreve yacute -30
+KPX abreve ydieresis -30
+KPX acircumflex v -20
+KPX acircumflex w -20
+KPX acircumflex y -30
+KPX acircumflex yacute -30
+KPX acircumflex ydieresis -30
+KPX adieresis v -20
+KPX adieresis w -20
+KPX adieresis y -30
+KPX adieresis yacute -30
+KPX adieresis ydieresis -30
+KPX agrave v -20
+KPX agrave w -20
+KPX agrave y -30
+KPX agrave yacute -30
+KPX agrave ydieresis -30
+KPX amacron v -20
+KPX amacron w -20
+KPX amacron y -30
+KPX amacron yacute -30
+KPX amacron ydieresis -30
+KPX aogonek v -20
+KPX aogonek w -20
+KPX aogonek y -30
+KPX aogonek yacute -30
+KPX aogonek ydieresis -30
+KPX aring v -20
+KPX aring w -20
+KPX aring y -30
+KPX aring yacute -30
+KPX aring ydieresis -30
+KPX atilde v -20
+KPX atilde w -20
+KPX atilde y -30
+KPX atilde yacute -30
+KPX atilde ydieresis -30
+KPX b b -10
+KPX b comma -40
+KPX b l -20
+KPX b lacute -20
+KPX b lcommaaccent -20
+KPX b lslash -20
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c comma -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute comma -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron comma -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla comma -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX colon space -50
+KPX comma quotedblright -100
+KPX comma quoteright -100
+KPX e comma -15
+KPX e period -15
+KPX e v -30
+KPX e w -20
+KPX e x -30
+KPX e y -20
+KPX e yacute -20
+KPX e ydieresis -20
+KPX eacute comma -15
+KPX eacute period -15
+KPX eacute v -30
+KPX eacute w -20
+KPX eacute x -30
+KPX eacute y -20
+KPX eacute yacute -20
+KPX eacute ydieresis -20
+KPX ecaron comma -15
+KPX ecaron period -15
+KPX ecaron v -30
+KPX ecaron w -20
+KPX ecaron x -30
+KPX ecaron y -20
+KPX ecaron yacute -20
+KPX ecaron ydieresis -20
+KPX ecircumflex comma -15
+KPX ecircumflex period -15
+KPX ecircumflex v -30
+KPX ecircumflex w -20
+KPX ecircumflex x -30
+KPX ecircumflex y -20
+KPX ecircumflex yacute -20
+KPX ecircumflex ydieresis -20
+KPX edieresis comma -15
+KPX edieresis period -15
+KPX edieresis v -30
+KPX edieresis w -20
+KPX edieresis x -30
+KPX edieresis y -20
+KPX edieresis yacute -20
+KPX edieresis ydieresis -20
+KPX edotaccent comma -15
+KPX edotaccent period -15
+KPX edotaccent v -30
+KPX edotaccent w -20
+KPX edotaccent x -30
+KPX edotaccent y -20
+KPX edotaccent yacute -20
+KPX edotaccent ydieresis -20
+KPX egrave comma -15
+KPX egrave period -15
+KPX egrave v -30
+KPX egrave w -20
+KPX egrave x -30
+KPX egrave y -20
+KPX egrave yacute -20
+KPX egrave ydieresis -20
+KPX emacron comma -15
+KPX emacron period -15
+KPX emacron v -30
+KPX emacron w -20
+KPX emacron x -30
+KPX emacron y -20
+KPX emacron yacute -20
+KPX emacron ydieresis -20
+KPX eogonek comma -15
+KPX eogonek period -15
+KPX eogonek v -30
+KPX eogonek w -20
+KPX eogonek x -30
+KPX eogonek y -20
+KPX eogonek yacute -20
+KPX eogonek ydieresis -20
+KPX f a -30
+KPX f aacute -30
+KPX f abreve -30
+KPX f acircumflex -30
+KPX f adieresis -30
+KPX f agrave -30
+KPX f amacron -30
+KPX f aogonek -30
+KPX f aring -30
+KPX f atilde -30
+KPX f comma -30
+KPX f dotlessi -28
+KPX f e -30
+KPX f eacute -30
+KPX f ecaron -30
+KPX f ecircumflex -30
+KPX f edieresis -30
+KPX f edotaccent -30
+KPX f egrave -30
+KPX f emacron -30
+KPX f eogonek -30
+KPX f o -30
+KPX f oacute -30
+KPX f ocircumflex -30
+KPX f odieresis -30
+KPX f ograve -30
+KPX f ohungarumlaut -30
+KPX f omacron -30
+KPX f oslash -30
+KPX f otilde -30
+KPX f period -30
+KPX f quotedblright 60
+KPX f quoteright 50
+KPX g r -10
+KPX g racute -10
+KPX g rcaron -10
+KPX g rcommaaccent -10
+KPX gbreve r -10
+KPX gbreve racute -10
+KPX gbreve rcaron -10
+KPX gbreve rcommaaccent -10
+KPX gcommaaccent r -10
+KPX gcommaaccent racute -10
+KPX gcommaaccent rcaron -10
+KPX gcommaaccent rcommaaccent -10
+KPX h y -30
+KPX h yacute -30
+KPX h ydieresis -30
+KPX k e -20
+KPX k eacute -20
+KPX k ecaron -20
+KPX k ecircumflex -20
+KPX k edieresis -20
+KPX k edotaccent -20
+KPX k egrave -20
+KPX k emacron -20
+KPX k eogonek -20
+KPX k o -20
+KPX k oacute -20
+KPX k ocircumflex -20
+KPX k odieresis -20
+KPX k ograve -20
+KPX k ohungarumlaut -20
+KPX k omacron -20
+KPX k oslash -20
+KPX k otilde -20
+KPX kcommaaccent e -20
+KPX kcommaaccent eacute -20
+KPX kcommaaccent ecaron -20
+KPX kcommaaccent ecircumflex -20
+KPX kcommaaccent edieresis -20
+KPX kcommaaccent edotaccent -20
+KPX kcommaaccent egrave -20
+KPX kcommaaccent emacron -20
+KPX kcommaaccent eogonek -20
+KPX kcommaaccent o -20
+KPX kcommaaccent oacute -20
+KPX kcommaaccent ocircumflex -20
+KPX kcommaaccent odieresis -20
+KPX kcommaaccent ograve -20
+KPX kcommaaccent ohungarumlaut -20
+KPX kcommaaccent omacron -20
+KPX kcommaaccent oslash -20
+KPX kcommaaccent otilde -20
+KPX m u -10
+KPX m uacute -10
+KPX m ucircumflex -10
+KPX m udieresis -10
+KPX m ugrave -10
+KPX m uhungarumlaut -10
+KPX m umacron -10
+KPX m uogonek -10
+KPX m uring -10
+KPX m y -15
+KPX m yacute -15
+KPX m ydieresis -15
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -20
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -20
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -20
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -20
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -20
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o comma -40
+KPX o period -40
+KPX o v -15
+KPX o w -15
+KPX o x -30
+KPX o y -30
+KPX o yacute -30
+KPX o ydieresis -30
+KPX oacute comma -40
+KPX oacute period -40
+KPX oacute v -15
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -30
+KPX oacute yacute -30
+KPX oacute ydieresis -30
+KPX ocircumflex comma -40
+KPX ocircumflex period -40
+KPX ocircumflex v -15
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -30
+KPX ocircumflex yacute -30
+KPX ocircumflex ydieresis -30
+KPX odieresis comma -40
+KPX odieresis period -40
+KPX odieresis v -15
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -30
+KPX odieresis yacute -30
+KPX odieresis ydieresis -30
+KPX ograve comma -40
+KPX ograve period -40
+KPX ograve v -15
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -30
+KPX ograve yacute -30
+KPX ograve ydieresis -30
+KPX ohungarumlaut comma -40
+KPX ohungarumlaut period -40
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -30
+KPX ohungarumlaut yacute -30
+KPX ohungarumlaut ydieresis -30
+KPX omacron comma -40
+KPX omacron period -40
+KPX omacron v -15
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -30
+KPX omacron yacute -30
+KPX omacron ydieresis -30
+KPX oslash a -55
+KPX oslash aacute -55
+KPX oslash abreve -55
+KPX oslash acircumflex -55
+KPX oslash adieresis -55
+KPX oslash agrave -55
+KPX oslash amacron -55
+KPX oslash aogonek -55
+KPX oslash aring -55
+KPX oslash atilde -55
+KPX oslash b -55
+KPX oslash c -55
+KPX oslash cacute -55
+KPX oslash ccaron -55
+KPX oslash ccedilla -55
+KPX oslash comma -95
+KPX oslash d -55
+KPX oslash dcroat -55
+KPX oslash e -55
+KPX oslash eacute -55
+KPX oslash ecaron -55
+KPX oslash ecircumflex -55
+KPX oslash edieresis -55
+KPX oslash edotaccent -55
+KPX oslash egrave -55
+KPX oslash emacron -55
+KPX oslash eogonek -55
+KPX oslash f -55
+KPX oslash g -55
+KPX oslash gbreve -55
+KPX oslash gcommaaccent -55
+KPX oslash h -55
+KPX oslash i -55
+KPX oslash iacute -55
+KPX oslash icircumflex -55
+KPX oslash idieresis -55
+KPX oslash igrave -55
+KPX oslash imacron -55
+KPX oslash iogonek -55
+KPX oslash j -55
+KPX oslash k -55
+KPX oslash kcommaaccent -55
+KPX oslash l -55
+KPX oslash lacute -55
+KPX oslash lcommaaccent -55
+KPX oslash lslash -55
+KPX oslash m -55
+KPX oslash n -55
+KPX oslash nacute -55
+KPX oslash ncaron -55
+KPX oslash ncommaaccent -55
+KPX oslash ntilde -55
+KPX oslash o -55
+KPX oslash oacute -55
+KPX oslash ocircumflex -55
+KPX oslash odieresis -55
+KPX oslash ograve -55
+KPX oslash ohungarumlaut -55
+KPX oslash omacron -55
+KPX oslash oslash -55
+KPX oslash otilde -55
+KPX oslash p -55
+KPX oslash period -95
+KPX oslash q -55
+KPX oslash r -55
+KPX oslash racute -55
+KPX oslash rcaron -55
+KPX oslash rcommaaccent -55
+KPX oslash s -55
+KPX oslash sacute -55
+KPX oslash scaron -55
+KPX oslash scedilla -55
+KPX oslash scommaaccent -55
+KPX oslash t -55
+KPX oslash tcommaaccent -55
+KPX oslash u -55
+KPX oslash uacute -55
+KPX oslash ucircumflex -55
+KPX oslash udieresis -55
+KPX oslash ugrave -55
+KPX oslash uhungarumlaut -55
+KPX oslash umacron -55
+KPX oslash uogonek -55
+KPX oslash uring -55
+KPX oslash v -70
+KPX oslash w -70
+KPX oslash x -85
+KPX oslash y -70
+KPX oslash yacute -70
+KPX oslash ydieresis -70
+KPX oslash z -55
+KPX oslash zacute -55
+KPX oslash zcaron -55
+KPX oslash zdotaccent -55
+KPX otilde comma -40
+KPX otilde period -40
+KPX otilde v -15
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -30
+KPX otilde yacute -30
+KPX otilde ydieresis -30
+KPX p comma -35
+KPX p period -35
+KPX p y -30
+KPX p yacute -30
+KPX p ydieresis -30
+KPX period quotedblright -100
+KPX period quoteright -100
+KPX period space -60
+KPX quotedblright space -40
+KPX quoteleft quoteleft -57
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright quoteright -57
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -50
+KPX quoteright sacute -50
+KPX quoteright scaron -50
+KPX quoteright scedilla -50
+KPX quoteright scommaaccent -50
+KPX quoteright space -70
+KPX r a -10
+KPX r aacute -10
+KPX r abreve -10
+KPX r acircumflex -10
+KPX r adieresis -10
+KPX r agrave -10
+KPX r amacron -10
+KPX r aogonek -10
+KPX r aring -10
+KPX r atilde -10
+KPX r colon 30
+KPX r comma -50
+KPX r i 15
+KPX r iacute 15
+KPX r icircumflex 15
+KPX r idieresis 15
+KPX r igrave 15
+KPX r imacron 15
+KPX r iogonek 15
+KPX r k 15
+KPX r kcommaaccent 15
+KPX r l 15
+KPX r lacute 15
+KPX r lcommaaccent 15
+KPX r lslash 15
+KPX r m 25
+KPX r n 25
+KPX r nacute 25
+KPX r ncaron 25
+KPX r ncommaaccent 25
+KPX r ntilde 25
+KPX r p 30
+KPX r period -50
+KPX r semicolon 30
+KPX r t 40
+KPX r tcommaaccent 40
+KPX r u 15
+KPX r uacute 15
+KPX r ucircumflex 15
+KPX r udieresis 15
+KPX r ugrave 15
+KPX r uhungarumlaut 15
+KPX r umacron 15
+KPX r uogonek 15
+KPX r uring 15
+KPX r v 30
+KPX r y 30
+KPX r yacute 30
+KPX r ydieresis 30
+KPX racute a -10
+KPX racute aacute -10
+KPX racute abreve -10
+KPX racute acircumflex -10
+KPX racute adieresis -10
+KPX racute agrave -10
+KPX racute amacron -10
+KPX racute aogonek -10
+KPX racute aring -10
+KPX racute atilde -10
+KPX racute colon 30
+KPX racute comma -50
+KPX racute i 15
+KPX racute iacute 15
+KPX racute icircumflex 15
+KPX racute idieresis 15
+KPX racute igrave 15
+KPX racute imacron 15
+KPX racute iogonek 15
+KPX racute k 15
+KPX racute kcommaaccent 15
+KPX racute l 15
+KPX racute lacute 15
+KPX racute lcommaaccent 15
+KPX racute lslash 15
+KPX racute m 25
+KPX racute n 25
+KPX racute nacute 25
+KPX racute ncaron 25
+KPX racute ncommaaccent 25
+KPX racute ntilde 25
+KPX racute p 30
+KPX racute period -50
+KPX racute semicolon 30
+KPX racute t 40
+KPX racute tcommaaccent 40
+KPX racute u 15
+KPX racute uacute 15
+KPX racute ucircumflex 15
+KPX racute udieresis 15
+KPX racute ugrave 15
+KPX racute uhungarumlaut 15
+KPX racute umacron 15
+KPX racute uogonek 15
+KPX racute uring 15
+KPX racute v 30
+KPX racute y 30
+KPX racute yacute 30
+KPX racute ydieresis 30
+KPX rcaron a -10
+KPX rcaron aacute -10
+KPX rcaron abreve -10
+KPX rcaron acircumflex -10
+KPX rcaron adieresis -10
+KPX rcaron agrave -10
+KPX rcaron amacron -10
+KPX rcaron aogonek -10
+KPX rcaron aring -10
+KPX rcaron atilde -10
+KPX rcaron colon 30
+KPX rcaron comma -50
+KPX rcaron i 15
+KPX rcaron iacute 15
+KPX rcaron icircumflex 15
+KPX rcaron idieresis 15
+KPX rcaron igrave 15
+KPX rcaron imacron 15
+KPX rcaron iogonek 15
+KPX rcaron k 15
+KPX rcaron kcommaaccent 15
+KPX rcaron l 15
+KPX rcaron lacute 15
+KPX rcaron lcommaaccent 15
+KPX rcaron lslash 15
+KPX rcaron m 25
+KPX rcaron n 25
+KPX rcaron nacute 25
+KPX rcaron ncaron 25
+KPX rcaron ncommaaccent 25
+KPX rcaron ntilde 25
+KPX rcaron p 30
+KPX rcaron period -50
+KPX rcaron semicolon 30
+KPX rcaron t 40
+KPX rcaron tcommaaccent 40
+KPX rcaron u 15
+KPX rcaron uacute 15
+KPX rcaron ucircumflex 15
+KPX rcaron udieresis 15
+KPX rcaron ugrave 15
+KPX rcaron uhungarumlaut 15
+KPX rcaron umacron 15
+KPX rcaron uogonek 15
+KPX rcaron uring 15
+KPX rcaron v 30
+KPX rcaron y 30
+KPX rcaron yacute 30
+KPX rcaron ydieresis 30
+KPX rcommaaccent a -10
+KPX rcommaaccent aacute -10
+KPX rcommaaccent abreve -10
+KPX rcommaaccent acircumflex -10
+KPX rcommaaccent adieresis -10
+KPX rcommaaccent agrave -10
+KPX rcommaaccent amacron -10
+KPX rcommaaccent aogonek -10
+KPX rcommaaccent aring -10
+KPX rcommaaccent atilde -10
+KPX rcommaaccent colon 30
+KPX rcommaaccent comma -50
+KPX rcommaaccent i 15
+KPX rcommaaccent iacute 15
+KPX rcommaaccent icircumflex 15
+KPX rcommaaccent idieresis 15
+KPX rcommaaccent igrave 15
+KPX rcommaaccent imacron 15
+KPX rcommaaccent iogonek 15
+KPX rcommaaccent k 15
+KPX rcommaaccent kcommaaccent 15
+KPX rcommaaccent l 15
+KPX rcommaaccent lacute 15
+KPX rcommaaccent lcommaaccent 15
+KPX rcommaaccent lslash 15
+KPX rcommaaccent m 25
+KPX rcommaaccent n 25
+KPX rcommaaccent nacute 25
+KPX rcommaaccent ncaron 25
+KPX rcommaaccent ncommaaccent 25
+KPX rcommaaccent ntilde 25
+KPX rcommaaccent p 30
+KPX rcommaaccent period -50
+KPX rcommaaccent semicolon 30
+KPX rcommaaccent t 40
+KPX rcommaaccent tcommaaccent 40
+KPX rcommaaccent u 15
+KPX rcommaaccent uacute 15
+KPX rcommaaccent ucircumflex 15
+KPX rcommaaccent udieresis 15
+KPX rcommaaccent ugrave 15
+KPX rcommaaccent uhungarumlaut 15
+KPX rcommaaccent umacron 15
+KPX rcommaaccent uogonek 15
+KPX rcommaaccent uring 15
+KPX rcommaaccent v 30
+KPX rcommaaccent y 30
+KPX rcommaaccent yacute 30
+KPX rcommaaccent ydieresis 30
+KPX s comma -15
+KPX s period -15
+KPX s w -30
+KPX sacute comma -15
+KPX sacute period -15
+KPX sacute w -30
+KPX scaron comma -15
+KPX scaron period -15
+KPX scaron w -30
+KPX scedilla comma -15
+KPX scedilla period -15
+KPX scedilla w -30
+KPX scommaaccent comma -15
+KPX scommaaccent period -15
+KPX scommaaccent w -30
+KPX semicolon space -50
+KPX space T -50
+KPX space Tcaron -50
+KPX space Tcommaaccent -50
+KPX space V -50
+KPX space W -40
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX space quotedblleft -30
+KPX space quoteleft -60
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -80
+KPX v e -25
+KPX v eacute -25
+KPX v ecaron -25
+KPX v ecircumflex -25
+KPX v edieresis -25
+KPX v edotaccent -25
+KPX v egrave -25
+KPX v emacron -25
+KPX v eogonek -25
+KPX v o -25
+KPX v oacute -25
+KPX v ocircumflex -25
+KPX v odieresis -25
+KPX v ograve -25
+KPX v ohungarumlaut -25
+KPX v omacron -25
+KPX v oslash -25
+KPX v otilde -25
+KPX v period -80
+KPX w a -15
+KPX w aacute -15
+KPX w abreve -15
+KPX w acircumflex -15
+KPX w adieresis -15
+KPX w agrave -15
+KPX w amacron -15
+KPX w aogonek -15
+KPX w aring -15
+KPX w atilde -15
+KPX w comma -60
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -60
+KPX x e -30
+KPX x eacute -30
+KPX x ecaron -30
+KPX x ecircumflex -30
+KPX x edieresis -30
+KPX x edotaccent -30
+KPX x egrave -30
+KPX x emacron -30
+KPX x eogonek -30
+KPX y a -20
+KPX y aacute -20
+KPX y abreve -20
+KPX y acircumflex -20
+KPX y adieresis -20
+KPX y agrave -20
+KPX y amacron -20
+KPX y aogonek -20
+KPX y aring -20
+KPX y atilde -20
+KPX y comma -100
+KPX y e -20
+KPX y eacute -20
+KPX y ecaron -20
+KPX y ecircumflex -20
+KPX y edieresis -20
+KPX y edotaccent -20
+KPX y egrave -20
+KPX y emacron -20
+KPX y eogonek -20
+KPX y o -20
+KPX y oacute -20
+KPX y ocircumflex -20
+KPX y odieresis -20
+KPX y ograve -20
+KPX y ohungarumlaut -20
+KPX y omacron -20
+KPX y oslash -20
+KPX y otilde -20
+KPX y period -100
+KPX yacute a -20
+KPX yacute aacute -20
+KPX yacute abreve -20
+KPX yacute acircumflex -20
+KPX yacute adieresis -20
+KPX yacute agrave -20
+KPX yacute amacron -20
+KPX yacute aogonek -20
+KPX yacute aring -20
+KPX yacute atilde -20
+KPX yacute comma -100
+KPX yacute e -20
+KPX yacute eacute -20
+KPX yacute ecaron -20
+KPX yacute ecircumflex -20
+KPX yacute edieresis -20
+KPX yacute edotaccent -20
+KPX yacute egrave -20
+KPX yacute emacron -20
+KPX yacute eogonek -20
+KPX yacute o -20
+KPX yacute oacute -20
+KPX yacute ocircumflex -20
+KPX yacute odieresis -20
+KPX yacute ograve -20
+KPX yacute ohungarumlaut -20
+KPX yacute omacron -20
+KPX yacute oslash -20
+KPX yacute otilde -20
+KPX yacute period -100
+KPX ydieresis a -20
+KPX ydieresis aacute -20
+KPX ydieresis abreve -20
+KPX ydieresis acircumflex -20
+KPX ydieresis adieresis -20
+KPX ydieresis agrave -20
+KPX ydieresis amacron -20
+KPX ydieresis aogonek -20
+KPX ydieresis aring -20
+KPX ydieresis atilde -20
+KPX ydieresis comma -100
+KPX ydieresis e -20
+KPX ydieresis eacute -20
+KPX ydieresis ecaron -20
+KPX ydieresis ecircumflex -20
+KPX ydieresis edieresis -20
+KPX ydieresis edotaccent -20
+KPX ydieresis egrave -20
+KPX ydieresis emacron -20
+KPX ydieresis eogonek -20
+KPX ydieresis o -20
+KPX ydieresis oacute -20
+KPX ydieresis ocircumflex -20
+KPX ydieresis odieresis -20
+KPX ydieresis ograve -20
+KPX ydieresis ohungarumlaut -20
+KPX ydieresis omacron -20
+KPX ydieresis oslash -20
+KPX ydieresis otilde -20
+KPX ydieresis period -100
+KPX z e -15
+KPX z eacute -15
+KPX z ecaron -15
+KPX z ecircumflex -15
+KPX z edieresis -15
+KPX z edotaccent -15
+KPX z egrave -15
+KPX z emacron -15
+KPX z eogonek -15
+KPX z o -15
+KPX z oacute -15
+KPX z ocircumflex -15
+KPX z odieresis -15
+KPX z ograve -15
+KPX z ohungarumlaut -15
+KPX z omacron -15
+KPX z oslash -15
+KPX z otilde -15
+KPX zacute e -15
+KPX zacute eacute -15
+KPX zacute ecaron -15
+KPX zacute ecircumflex -15
+KPX zacute edieresis -15
+KPX zacute edotaccent -15
+KPX zacute egrave -15
+KPX zacute emacron -15
+KPX zacute eogonek -15
+KPX zacute o -15
+KPX zacute oacute -15
+KPX zacute ocircumflex -15
+KPX zacute odieresis -15
+KPX zacute ograve -15
+KPX zacute ohungarumlaut -15
+KPX zacute omacron -15
+KPX zacute oslash -15
+KPX zacute otilde -15
+KPX zcaron e -15
+KPX zcaron eacute -15
+KPX zcaron ecaron -15
+KPX zcaron ecircumflex -15
+KPX zcaron edieresis -15
+KPX zcaron edotaccent -15
+KPX zcaron egrave -15
+KPX zcaron emacron -15
+KPX zcaron eogonek -15
+KPX zcaron o -15
+KPX zcaron oacute -15
+KPX zcaron ocircumflex -15
+KPX zcaron odieresis -15
+KPX zcaron ograve -15
+KPX zcaron ohungarumlaut -15
+KPX zcaron omacron -15
+KPX zcaron oslash -15
+KPX zcaron otilde -15
+KPX zdotaccent e -15
+KPX zdotaccent eacute -15
+KPX zdotaccent ecaron -15
+KPX zdotaccent ecircumflex -15
+KPX zdotaccent edieresis -15
+KPX zdotaccent edotaccent -15
+KPX zdotaccent egrave -15
+KPX zdotaccent emacron -15
+KPX zdotaccent eogonek -15
+KPX zdotaccent o -15
+KPX zdotaccent oacute -15
+KPX zdotaccent ocircumflex -15
+KPX zdotaccent odieresis -15
+KPX zdotaccent ograve -15
+KPX zdotaccent ohungarumlaut -15
+KPX zdotaccent omacron -15
+KPX zdotaccent oslash -15
+KPX zdotaccent otilde -15
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica.afm
new file mode 100644
index 0000000..d39cea0
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Helvetica.afm
@@ -0,0 +1,3052 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:38:23 1997
+Comment UniqueID 43054
+Comment VMusage 37069 48094
+FontName Helvetica
+FullName Helvetica
+FamilyName Helvetica
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -166 -225 1000 931 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StdHW 76
+StdVW 88
+StartCharMetrics 315
+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 -225 167 775 ;
+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 405 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 405 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 278 ; N Idieresis ; B 13 0 266 901 ;
+C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ;
+C -1 ; WX 556 ; N abreve ; B 36 -15 530 731 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 68 -15 521 734 ;
+C -1 ; WX 556 ; N ecaron ; B 40 -15 516 734 ;
+C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ;
+C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ;
+C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ;
+C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ;
+C -1 ; WX 500 ; N scommaaccent ; B 32 -225 464 538 ;
+C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ;
+C -1 ; WX 722 ; N Uring ; B 79 -19 644 931 ;
+C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ;
+C -1 ; WX 556 ; N aogonek ; B 36 -220 547 538 ;
+C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ;
+C -1 ; WX 556 ; N uogonek ; B 68 -225 519 523 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ;
+C -1 ; WX 722 ; N Dcroat ; B 0 0 674 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 87 -225 181 -40 ;
+C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ;
+C -1 ; WX 667 ; N Emacron ; B 86 0 616 879 ;
+C -1 ; WX 500 ; N ccaron ; B 30 -15 477 734 ;
+C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 646 718 ;
+C -1 ; WX 222 ; N lacute ; B 67 0 264 929 ;
+C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 14 -225 597 718 ;
+C -1 ; WX 722 ; N Cacute ; B 44 -19 681 929 ;
+C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ;
+C -1 ; WX 667 ; N Edotaccent ; B 86 0 616 901 ;
+C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ;
+C -1 ; WX 500 ; N scedilla ; B 32 -225 464 538 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ;
+C -1 ; WX 471 ; N lozenge ; B 10 0 462 728 ;
+C -1 ; WX 722 ; N Rcaron ; B 88 0 684 929 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 48 -225 704 737 ;
+C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ;
+C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ;
+C -1 ; WX 667 ; N Amacron ; B 14 0 654 879 ;
+C -1 ; WX 333 ; N rcaron ; B 61 0 352 734 ;
+C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 23 0 588 901 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ;
+C -1 ; WX 778 ; N Omacron ; B 39 -19 739 879 ;
+C -1 ; WX 722 ; N Racute ; B 88 0 684 929 ;
+C -1 ; WX 667 ; N Sacute ; B 49 -19 620 929 ;
+C -1 ; WX 643 ; N dcaron ; B 35 -15 655 718 ;
+C -1 ; WX 722 ; N Umacron ; B 79 -19 644 879 ;
+C -1 ; WX 556 ; N uring ; B 68 -15 489 756 ;
+C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ;
+C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Abreve ; B 14 0 654 926 ;
+C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ;
+C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ;
+C -1 ; WX 611 ; N Tcaron ; B 14 0 597 929 ;
+C -1 ; WX 476 ; N partialdiff ; B 13 -38 463 714 ;
+C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ;
+C -1 ; WX 722 ; N Nacute ; B 76 0 646 929 ;
+C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ;
+C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ;
+C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ;
+C -1 ; WX 500 ; N cacute ; B 30 -15 477 734 ;
+C -1 ; WX 556 ; N nacute ; B 65 0 491 734 ;
+C -1 ; WX 556 ; N umacron ; B 68 -15 489 684 ;
+C -1 ; WX 722 ; N Ncaron ; B 76 0 646 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ;
+C -1 ; WX 260 ; N brokenbar ; B 94 -150 167 700 ;
+C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 48 -19 704 926 ;
+C -1 ; WX 278 ; N Idotaccent ; B 91 0 188 901 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ;
+C -1 ; WX 333 ; N racute ; B 77 0 332 734 ;
+C -1 ; WX 556 ; N omacron ; B 35 -14 521 684 ;
+C -1 ; WX 611 ; N Zacute ; B 23 0 588 929 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 674 ;
+C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ;
+C -1 ; WX 222 ; N lcommaaccent ; B 67 -225 167 718 ;
+C -1 ; WX 317 ; N tcaron ; B 14 -7 329 808 ;
+C -1 ; WX 556 ; N eogonek ; B 40 -225 516 538 ;
+C -1 ; WX 722 ; N Uogonek ; B 79 -225 644 718 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ;
+C -1 ; WX 500 ; N zacute ; B 31 0 469 734 ;
+C -1 ; WX 222 ; N iogonek ; B -31 -225 183 718 ;
+C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ;
+C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ;
+C -1 ; WX 556 ; N amacron ; B 36 -15 530 684 ;
+C -1 ; WX 500 ; N sacute ; B 32 -15 464 734 ;
+C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ;
+C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ;
+C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ;
+C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ;
+C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ;
+C -1 ; WX 556 ; N ohungarumlaut ; B 35 -14 521 734 ;
+C -1 ; WX 667 ; N Eogonek ; B 86 -220 633 718 ;
+C -1 ; WX 556 ; N dcroat ; B 35 -15 550 718 ;
+C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ;
+C -1 ; WX 667 ; N Scedilla ; B 49 -225 620 737 ;
+C -1 ; WX 299 ; N lcaron ; B 67 0 311 718 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 663 718 ;
+C -1 ; WX 556 ; N Lacute ; B 76 0 537 929 ;
+C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 40 -15 516 706 ;
+C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ;
+C -1 ; WX 278 ; N Imacron ; B -17 0 296 879 ;
+C -1 ; WX 556 ; N Lcaron ; B 76 0 537 718 ;
+C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 674 ;
+C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 79 -19 644 929 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ;
+C -1 ; WX 556 ; N emacron ; B 40 -15 516 684 ;
+C -1 ; WX 556 ; N gbreve ; B 40 -220 499 731 ;
+C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ;
+C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 49 -225 620 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 39 -19 739 929 ;
+C -1 ; WX 400 ; N degree ; B 54 411 346 703 ;
+C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ;
+C -1 ; WX 722 ; N Ccaron ; B 44 -19 681 929 ;
+C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ;
+C -1 ; WX 453 ; N radical ; B -4 -80 458 762 ;
+C -1 ; WX 722 ; N Dcaron ; B 81 0 674 929 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 77 -225 332 538 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ;
+C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 684 718 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 537 718 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ;
+C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ;
+C -1 ; WX 500 ; N zdotaccent ; B 31 0 469 706 ;
+C -1 ; WX 667 ; N Ecaron ; B 86 0 616 929 ;
+C -1 ; WX 278 ; N Iogonek ; B -3 -225 211 718 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 501 718 ;
+C -1 ; WX 584 ; N minus ; B 39 216 545 289 ;
+C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ;
+C -1 ; WX 556 ; N ncaron ; B 65 0 491 734 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 14 -225 257 669 ;
+C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ;
+C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ;
+C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ;
+C -1 ; WX 549 ; N notequal ; B 12 -35 537 551 ;
+C -1 ; WX 556 ; N gcommaaccent ; B 40 -220 499 822 ;
+C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 491 538 ;
+C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ;
+C -1 ; WX 278 ; N imacron ; B 5 0 272 684 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2705
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -30
+KPX A Gbreve -30
+KPX A Gcommaaccent -30
+KPX A O -30
+KPX A Oacute -30
+KPX A Ocircumflex -30
+KPX A Odieresis -30
+KPX A Ograve -30
+KPX A Ohungarumlaut -30
+KPX A Omacron -30
+KPX A Oslash -30
+KPX A Otilde -30
+KPX A Q -30
+KPX A T -120
+KPX A Tcaron -120
+KPX A Tcommaaccent -120
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -70
+KPX A W -50
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -40
+KPX A y -40
+KPX A yacute -40
+KPX A ydieresis -40
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -30
+KPX Aacute Gbreve -30
+KPX Aacute Gcommaaccent -30
+KPX Aacute O -30
+KPX Aacute Oacute -30
+KPX Aacute Ocircumflex -30
+KPX Aacute Odieresis -30
+KPX Aacute Ograve -30
+KPX Aacute Ohungarumlaut -30
+KPX Aacute Omacron -30
+KPX Aacute Oslash -30
+KPX Aacute Otilde -30
+KPX Aacute Q -30
+KPX Aacute T -120
+KPX Aacute Tcaron -120
+KPX Aacute Tcommaaccent -120
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -70
+KPX Aacute W -50
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -40
+KPX Aacute y -40
+KPX Aacute yacute -40
+KPX Aacute ydieresis -40
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -30
+KPX Abreve Gbreve -30
+KPX Abreve Gcommaaccent -30
+KPX Abreve O -30
+KPX Abreve Oacute -30
+KPX Abreve Ocircumflex -30
+KPX Abreve Odieresis -30
+KPX Abreve Ograve -30
+KPX Abreve Ohungarumlaut -30
+KPX Abreve Omacron -30
+KPX Abreve Oslash -30
+KPX Abreve Otilde -30
+KPX Abreve Q -30
+KPX Abreve T -120
+KPX Abreve Tcaron -120
+KPX Abreve Tcommaaccent -120
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -70
+KPX Abreve W -50
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -40
+KPX Abreve y -40
+KPX Abreve yacute -40
+KPX Abreve ydieresis -40
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -30
+KPX Acircumflex Gbreve -30
+KPX Acircumflex Gcommaaccent -30
+KPX Acircumflex O -30
+KPX Acircumflex Oacute -30
+KPX Acircumflex Ocircumflex -30
+KPX Acircumflex Odieresis -30
+KPX Acircumflex Ograve -30
+KPX Acircumflex Ohungarumlaut -30
+KPX Acircumflex Omacron -30
+KPX Acircumflex Oslash -30
+KPX Acircumflex Otilde -30
+KPX Acircumflex Q -30
+KPX Acircumflex T -120
+KPX Acircumflex Tcaron -120
+KPX Acircumflex Tcommaaccent -120
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -70
+KPX Acircumflex W -50
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -40
+KPX Acircumflex y -40
+KPX Acircumflex yacute -40
+KPX Acircumflex ydieresis -40
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -30
+KPX Adieresis Gbreve -30
+KPX Adieresis Gcommaaccent -30
+KPX Adieresis O -30
+KPX Adieresis Oacute -30
+KPX Adieresis Ocircumflex -30
+KPX Adieresis Odieresis -30
+KPX Adieresis Ograve -30
+KPX Adieresis Ohungarumlaut -30
+KPX Adieresis Omacron -30
+KPX Adieresis Oslash -30
+KPX Adieresis Otilde -30
+KPX Adieresis Q -30
+KPX Adieresis T -120
+KPX Adieresis Tcaron -120
+KPX Adieresis Tcommaaccent -120
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -70
+KPX Adieresis W -50
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -40
+KPX Adieresis y -40
+KPX Adieresis yacute -40
+KPX Adieresis ydieresis -40
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -30
+KPX Agrave Gbreve -30
+KPX Agrave Gcommaaccent -30
+KPX Agrave O -30
+KPX Agrave Oacute -30
+KPX Agrave Ocircumflex -30
+KPX Agrave Odieresis -30
+KPX Agrave Ograve -30
+KPX Agrave Ohungarumlaut -30
+KPX Agrave Omacron -30
+KPX Agrave Oslash -30
+KPX Agrave Otilde -30
+KPX Agrave Q -30
+KPX Agrave T -120
+KPX Agrave Tcaron -120
+KPX Agrave Tcommaaccent -120
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -70
+KPX Agrave W -50
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -40
+KPX Agrave y -40
+KPX Agrave yacute -40
+KPX Agrave ydieresis -40
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -30
+KPX Amacron Gbreve -30
+KPX Amacron Gcommaaccent -30
+KPX Amacron O -30
+KPX Amacron Oacute -30
+KPX Amacron Ocircumflex -30
+KPX Amacron Odieresis -30
+KPX Amacron Ograve -30
+KPX Amacron Ohungarumlaut -30
+KPX Amacron Omacron -30
+KPX Amacron Oslash -30
+KPX Amacron Otilde -30
+KPX Amacron Q -30
+KPX Amacron T -120
+KPX Amacron Tcaron -120
+KPX Amacron Tcommaaccent -120
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -70
+KPX Amacron W -50
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -40
+KPX Amacron y -40
+KPX Amacron yacute -40
+KPX Amacron ydieresis -40
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -30
+KPX Aogonek Gbreve -30
+KPX Aogonek Gcommaaccent -30
+KPX Aogonek O -30
+KPX Aogonek Oacute -30
+KPX Aogonek Ocircumflex -30
+KPX Aogonek Odieresis -30
+KPX Aogonek Ograve -30
+KPX Aogonek Ohungarumlaut -30
+KPX Aogonek Omacron -30
+KPX Aogonek Oslash -30
+KPX Aogonek Otilde -30
+KPX Aogonek Q -30
+KPX Aogonek T -120
+KPX Aogonek Tcaron -120
+KPX Aogonek Tcommaaccent -120
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -70
+KPX Aogonek W -50
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -40
+KPX Aogonek y -40
+KPX Aogonek yacute -40
+KPX Aogonek ydieresis -40
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -30
+KPX Aring Gbreve -30
+KPX Aring Gcommaaccent -30
+KPX Aring O -30
+KPX Aring Oacute -30
+KPX Aring Ocircumflex -30
+KPX Aring Odieresis -30
+KPX Aring Ograve -30
+KPX Aring Ohungarumlaut -30
+KPX Aring Omacron -30
+KPX Aring Oslash -30
+KPX Aring Otilde -30
+KPX Aring Q -30
+KPX Aring T -120
+KPX Aring Tcaron -120
+KPX Aring Tcommaaccent -120
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -70
+KPX Aring W -50
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -40
+KPX Aring y -40
+KPX Aring yacute -40
+KPX Aring ydieresis -40
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -30
+KPX Atilde Gbreve -30
+KPX Atilde Gcommaaccent -30
+KPX Atilde O -30
+KPX Atilde Oacute -30
+KPX Atilde Ocircumflex -30
+KPX Atilde Odieresis -30
+KPX Atilde Ograve -30
+KPX Atilde Ohungarumlaut -30
+KPX Atilde Omacron -30
+KPX Atilde Oslash -30
+KPX Atilde Otilde -30
+KPX Atilde Q -30
+KPX Atilde T -120
+KPX Atilde Tcaron -120
+KPX Atilde Tcommaaccent -120
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -70
+KPX Atilde W -50
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -40
+KPX Atilde y -40
+KPX Atilde yacute -40
+KPX Atilde ydieresis -40
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX B comma -20
+KPX B period -20
+KPX C comma -30
+KPX C period -30
+KPX Cacute comma -30
+KPX Cacute period -30
+KPX Ccaron comma -30
+KPX Ccaron period -30
+KPX Ccedilla comma -30
+KPX Ccedilla period -30
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -70
+KPX D W -40
+KPX D Y -90
+KPX D Yacute -90
+KPX D Ydieresis -90
+KPX D comma -70
+KPX D period -70
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -70
+KPX Dcaron W -40
+KPX Dcaron Y -90
+KPX Dcaron Yacute -90
+KPX Dcaron Ydieresis -90
+KPX Dcaron comma -70
+KPX Dcaron period -70
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -70
+KPX Dcroat W -40
+KPX Dcroat Y -90
+KPX Dcroat Yacute -90
+KPX Dcroat Ydieresis -90
+KPX Dcroat comma -70
+KPX Dcroat period -70
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -50
+KPX F aacute -50
+KPX F abreve -50
+KPX F acircumflex -50
+KPX F adieresis -50
+KPX F agrave -50
+KPX F amacron -50
+KPX F aogonek -50
+KPX F aring -50
+KPX F atilde -50
+KPX F comma -150
+KPX F e -30
+KPX F eacute -30
+KPX F ecaron -30
+KPX F ecircumflex -30
+KPX F edieresis -30
+KPX F edotaccent -30
+KPX F egrave -30
+KPX F emacron -30
+KPX F eogonek -30
+KPX F o -30
+KPX F oacute -30
+KPX F ocircumflex -30
+KPX F odieresis -30
+KPX F ograve -30
+KPX F ohungarumlaut -30
+KPX F omacron -30
+KPX F oslash -30
+KPX F otilde -30
+KPX F period -150
+KPX F r -45
+KPX F racute -45
+KPX F rcaron -45
+KPX F rcommaaccent -45
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J a -20
+KPX J aacute -20
+KPX J abreve -20
+KPX J acircumflex -20
+KPX J adieresis -20
+KPX J agrave -20
+KPX J amacron -20
+KPX J aogonek -20
+KPX J aring -20
+KPX J atilde -20
+KPX J comma -30
+KPX J period -30
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -40
+KPX K eacute -40
+KPX K ecaron -40
+KPX K ecircumflex -40
+KPX K edieresis -40
+KPX K edotaccent -40
+KPX K egrave -40
+KPX K emacron -40
+KPX K eogonek -40
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -50
+KPX K yacute -50
+KPX K ydieresis -50
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -40
+KPX Kcommaaccent eacute -40
+KPX Kcommaaccent ecaron -40
+KPX Kcommaaccent ecircumflex -40
+KPX Kcommaaccent edieresis -40
+KPX Kcommaaccent edotaccent -40
+KPX Kcommaaccent egrave -40
+KPX Kcommaaccent emacron -40
+KPX Kcommaaccent eogonek -40
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -50
+KPX Kcommaaccent yacute -50
+KPX Kcommaaccent ydieresis -50
+KPX L T -110
+KPX L Tcaron -110
+KPX L Tcommaaccent -110
+KPX L V -110
+KPX L W -70
+KPX L Y -140
+KPX L Yacute -140
+KPX L Ydieresis -140
+KPX L quotedblright -140
+KPX L quoteright -160
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -110
+KPX Lacute Tcaron -110
+KPX Lacute Tcommaaccent -110
+KPX Lacute V -110
+KPX Lacute W -70
+KPX Lacute Y -140
+KPX Lacute Yacute -140
+KPX Lacute Ydieresis -140
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -160
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcaron T -110
+KPX Lcaron Tcaron -110
+KPX Lcaron Tcommaaccent -110
+KPX Lcaron V -110
+KPX Lcaron W -70
+KPX Lcaron Y -140
+KPX Lcaron Yacute -140
+KPX Lcaron Ydieresis -140
+KPX Lcaron quotedblright -140
+KPX Lcaron quoteright -160
+KPX Lcaron y -30
+KPX Lcaron yacute -30
+KPX Lcaron ydieresis -30
+KPX Lcommaaccent T -110
+KPX Lcommaaccent Tcaron -110
+KPX Lcommaaccent Tcommaaccent -110
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -70
+KPX Lcommaaccent Y -140
+KPX Lcommaaccent Yacute -140
+KPX Lcommaaccent Ydieresis -140
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -160
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -110
+KPX Lslash Tcaron -110
+KPX Lslash Tcommaaccent -110
+KPX Lslash V -110
+KPX Lslash W -70
+KPX Lslash Y -140
+KPX Lslash Yacute -140
+KPX Lslash Ydieresis -140
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -160
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -20
+KPX O Aacute -20
+KPX O Abreve -20
+KPX O Acircumflex -20
+KPX O Adieresis -20
+KPX O Agrave -20
+KPX O Amacron -20
+KPX O Aogonek -20
+KPX O Aring -20
+KPX O Atilde -20
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -30
+KPX O X -60
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -20
+KPX Oacute Aacute -20
+KPX Oacute Abreve -20
+KPX Oacute Acircumflex -20
+KPX Oacute Adieresis -20
+KPX Oacute Agrave -20
+KPX Oacute Amacron -20
+KPX Oacute Aogonek -20
+KPX Oacute Aring -20
+KPX Oacute Atilde -20
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -30
+KPX Oacute X -60
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -20
+KPX Ocircumflex Aacute -20
+KPX Ocircumflex Abreve -20
+KPX Ocircumflex Acircumflex -20
+KPX Ocircumflex Adieresis -20
+KPX Ocircumflex Agrave -20
+KPX Ocircumflex Amacron -20
+KPX Ocircumflex Aogonek -20
+KPX Ocircumflex Aring -20
+KPX Ocircumflex Atilde -20
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -30
+KPX Ocircumflex X -60
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -20
+KPX Odieresis Aacute -20
+KPX Odieresis Abreve -20
+KPX Odieresis Acircumflex -20
+KPX Odieresis Adieresis -20
+KPX Odieresis Agrave -20
+KPX Odieresis Amacron -20
+KPX Odieresis Aogonek -20
+KPX Odieresis Aring -20
+KPX Odieresis Atilde -20
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -30
+KPX Odieresis X -60
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -20
+KPX Ograve Aacute -20
+KPX Ograve Abreve -20
+KPX Ograve Acircumflex -20
+KPX Ograve Adieresis -20
+KPX Ograve Agrave -20
+KPX Ograve Amacron -20
+KPX Ograve Aogonek -20
+KPX Ograve Aring -20
+KPX Ograve Atilde -20
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -30
+KPX Ograve X -60
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -20
+KPX Ohungarumlaut Aacute -20
+KPX Ohungarumlaut Abreve -20
+KPX Ohungarumlaut Acircumflex -20
+KPX Ohungarumlaut Adieresis -20
+KPX Ohungarumlaut Agrave -20
+KPX Ohungarumlaut Amacron -20
+KPX Ohungarumlaut Aogonek -20
+KPX Ohungarumlaut Aring -20
+KPX Ohungarumlaut Atilde -20
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -30
+KPX Ohungarumlaut X -60
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -20
+KPX Omacron Aacute -20
+KPX Omacron Abreve -20
+KPX Omacron Acircumflex -20
+KPX Omacron Adieresis -20
+KPX Omacron Agrave -20
+KPX Omacron Amacron -20
+KPX Omacron Aogonek -20
+KPX Omacron Aring -20
+KPX Omacron Atilde -20
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -30
+KPX Omacron X -60
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -20
+KPX Oslash Aacute -20
+KPX Oslash Abreve -20
+KPX Oslash Acircumflex -20
+KPX Oslash Adieresis -20
+KPX Oslash Agrave -20
+KPX Oslash Amacron -20
+KPX Oslash Aogonek -20
+KPX Oslash Aring -20
+KPX Oslash Atilde -20
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -30
+KPX Oslash X -60
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -20
+KPX Otilde Aacute -20
+KPX Otilde Abreve -20
+KPX Otilde Acircumflex -20
+KPX Otilde Adieresis -20
+KPX Otilde Agrave -20
+KPX Otilde Amacron -20
+KPX Otilde Aogonek -20
+KPX Otilde Aring -20
+KPX Otilde Atilde -20
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -30
+KPX Otilde X -60
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -120
+KPX P Aacute -120
+KPX P Abreve -120
+KPX P Acircumflex -120
+KPX P Adieresis -120
+KPX P Agrave -120
+KPX P Amacron -120
+KPX P Aogonek -120
+KPX P Aring -120
+KPX P Atilde -120
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -180
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -50
+KPX P oacute -50
+KPX P ocircumflex -50
+KPX P odieresis -50
+KPX P ograve -50
+KPX P ohungarumlaut -50
+KPX P omacron -50
+KPX P oslash -50
+KPX P otilde -50
+KPX P period -180
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -50
+KPX R W -30
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -50
+KPX Racute W -30
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -50
+KPX Rcaron W -30
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -30
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX S comma -20
+KPX S period -20
+KPX Sacute comma -20
+KPX Sacute period -20
+KPX Scaron comma -20
+KPX Scaron period -20
+KPX Scedilla comma -20
+KPX Scedilla period -20
+KPX Scommaaccent comma -20
+KPX Scommaaccent period -20
+KPX T A -120
+KPX T Aacute -120
+KPX T Abreve -120
+KPX T Acircumflex -120
+KPX T Adieresis -120
+KPX T Agrave -120
+KPX T Amacron -120
+KPX T Aogonek -120
+KPX T Aring -120
+KPX T Atilde -120
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -120
+KPX T aacute -120
+KPX T abreve -60
+KPX T acircumflex -120
+KPX T adieresis -120
+KPX T agrave -120
+KPX T amacron -60
+KPX T aogonek -120
+KPX T aring -120
+KPX T atilde -60
+KPX T colon -20
+KPX T comma -120
+KPX T e -120
+KPX T eacute -120
+KPX T ecaron -120
+KPX T ecircumflex -120
+KPX T edieresis -120
+KPX T edotaccent -120
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -120
+KPX T hyphen -140
+KPX T o -120
+KPX T oacute -120
+KPX T ocircumflex -120
+KPX T odieresis -120
+KPX T ograve -120
+KPX T ohungarumlaut -120
+KPX T omacron -60
+KPX T oslash -120
+KPX T otilde -60
+KPX T period -120
+KPX T r -120
+KPX T racute -120
+KPX T rcaron -120
+KPX T rcommaaccent -120
+KPX T semicolon -20
+KPX T u -120
+KPX T uacute -120
+KPX T ucircumflex -120
+KPX T udieresis -120
+KPX T ugrave -120
+KPX T uhungarumlaut -120
+KPX T umacron -60
+KPX T uogonek -120
+KPX T uring -120
+KPX T w -120
+KPX T y -120
+KPX T yacute -120
+KPX T ydieresis -60
+KPX Tcaron A -120
+KPX Tcaron Aacute -120
+KPX Tcaron Abreve -120
+KPX Tcaron Acircumflex -120
+KPX Tcaron Adieresis -120
+KPX Tcaron Agrave -120
+KPX Tcaron Amacron -120
+KPX Tcaron Aogonek -120
+KPX Tcaron Aring -120
+KPX Tcaron Atilde -120
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -120
+KPX Tcaron aacute -120
+KPX Tcaron abreve -60
+KPX Tcaron acircumflex -120
+KPX Tcaron adieresis -120
+KPX Tcaron agrave -120
+KPX Tcaron amacron -60
+KPX Tcaron aogonek -120
+KPX Tcaron aring -120
+KPX Tcaron atilde -60
+KPX Tcaron colon -20
+KPX Tcaron comma -120
+KPX Tcaron e -120
+KPX Tcaron eacute -120
+KPX Tcaron ecaron -120
+KPX Tcaron ecircumflex -120
+KPX Tcaron edieresis -120
+KPX Tcaron edotaccent -120
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -120
+KPX Tcaron hyphen -140
+KPX Tcaron o -120
+KPX Tcaron oacute -120
+KPX Tcaron ocircumflex -120
+KPX Tcaron odieresis -120
+KPX Tcaron ograve -120
+KPX Tcaron ohungarumlaut -120
+KPX Tcaron omacron -60
+KPX Tcaron oslash -120
+KPX Tcaron otilde -60
+KPX Tcaron period -120
+KPX Tcaron r -120
+KPX Tcaron racute -120
+KPX Tcaron rcaron -120
+KPX Tcaron rcommaaccent -120
+KPX Tcaron semicolon -20
+KPX Tcaron u -120
+KPX Tcaron uacute -120
+KPX Tcaron ucircumflex -120
+KPX Tcaron udieresis -120
+KPX Tcaron ugrave -120
+KPX Tcaron uhungarumlaut -120
+KPX Tcaron umacron -60
+KPX Tcaron uogonek -120
+KPX Tcaron uring -120
+KPX Tcaron w -120
+KPX Tcaron y -120
+KPX Tcaron yacute -120
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -120
+KPX Tcommaaccent Aacute -120
+KPX Tcommaaccent Abreve -120
+KPX Tcommaaccent Acircumflex -120
+KPX Tcommaaccent Adieresis -120
+KPX Tcommaaccent Agrave -120
+KPX Tcommaaccent Amacron -120
+KPX Tcommaaccent Aogonek -120
+KPX Tcommaaccent Aring -120
+KPX Tcommaaccent Atilde -120
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -120
+KPX Tcommaaccent aacute -120
+KPX Tcommaaccent abreve -60
+KPX Tcommaaccent acircumflex -120
+KPX Tcommaaccent adieresis -120
+KPX Tcommaaccent agrave -120
+KPX Tcommaaccent amacron -60
+KPX Tcommaaccent aogonek -120
+KPX Tcommaaccent aring -120
+KPX Tcommaaccent atilde -60
+KPX Tcommaaccent colon -20
+KPX Tcommaaccent comma -120
+KPX Tcommaaccent e -120
+KPX Tcommaaccent eacute -120
+KPX Tcommaaccent ecaron -120
+KPX Tcommaaccent ecircumflex -120
+KPX Tcommaaccent edieresis -120
+KPX Tcommaaccent edotaccent -120
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -120
+KPX Tcommaaccent hyphen -140
+KPX Tcommaaccent o -120
+KPX Tcommaaccent oacute -120
+KPX Tcommaaccent ocircumflex -120
+KPX Tcommaaccent odieresis -120
+KPX Tcommaaccent ograve -120
+KPX Tcommaaccent ohungarumlaut -120
+KPX Tcommaaccent omacron -60
+KPX Tcommaaccent oslash -120
+KPX Tcommaaccent otilde -60
+KPX Tcommaaccent period -120
+KPX Tcommaaccent r -120
+KPX Tcommaaccent racute -120
+KPX Tcommaaccent rcaron -120
+KPX Tcommaaccent rcommaaccent -120
+KPX Tcommaaccent semicolon -20
+KPX Tcommaaccent u -120
+KPX Tcommaaccent uacute -120
+KPX Tcommaaccent ucircumflex -120
+KPX Tcommaaccent udieresis -120
+KPX Tcommaaccent ugrave -120
+KPX Tcommaaccent uhungarumlaut -120
+KPX Tcommaaccent umacron -60
+KPX Tcommaaccent uogonek -120
+KPX Tcommaaccent uring -120
+KPX Tcommaaccent w -120
+KPX Tcommaaccent y -120
+KPX Tcommaaccent yacute -120
+KPX Tcommaaccent ydieresis -60
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -40
+KPX U period -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -40
+KPX Uacute period -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -40
+KPX Ucircumflex period -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -40
+KPX Udieresis period -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -40
+KPX Ugrave period -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -40
+KPX Uhungarumlaut period -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -40
+KPX Umacron period -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -40
+KPX Uogonek period -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -40
+KPX Uring period -40
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -40
+KPX V Gbreve -40
+KPX V Gcommaaccent -40
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -70
+KPX V aacute -70
+KPX V abreve -70
+KPX V acircumflex -70
+KPX V adieresis -70
+KPX V agrave -70
+KPX V amacron -70
+KPX V aogonek -70
+KPX V aring -70
+KPX V atilde -70
+KPX V colon -40
+KPX V comma -125
+KPX V e -80
+KPX V eacute -80
+KPX V ecaron -80
+KPX V ecircumflex -80
+KPX V edieresis -80
+KPX V edotaccent -80
+KPX V egrave -80
+KPX V emacron -80
+KPX V eogonek -80
+KPX V hyphen -80
+KPX V o -80
+KPX V oacute -80
+KPX V ocircumflex -80
+KPX V odieresis -80
+KPX V ograve -80
+KPX V ohungarumlaut -80
+KPX V omacron -80
+KPX V oslash -80
+KPX V otilde -80
+KPX V period -125
+KPX V semicolon -40
+KPX V u -70
+KPX V uacute -70
+KPX V ucircumflex -70
+KPX V udieresis -70
+KPX V ugrave -70
+KPX V uhungarumlaut -70
+KPX V umacron -70
+KPX V uogonek -70
+KPX V uring -70
+KPX W A -50
+KPX W Aacute -50
+KPX W Abreve -50
+KPX W Acircumflex -50
+KPX W Adieresis -50
+KPX W Agrave -50
+KPX W Amacron -50
+KPX W Aogonek -50
+KPX W Aring -50
+KPX W Atilde -50
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W comma -80
+KPX W e -30
+KPX W eacute -30
+KPX W ecaron -30
+KPX W ecircumflex -30
+KPX W edieresis -30
+KPX W edotaccent -30
+KPX W egrave -30
+KPX W emacron -30
+KPX W eogonek -30
+KPX W hyphen -40
+KPX W o -30
+KPX W oacute -30
+KPX W ocircumflex -30
+KPX W odieresis -30
+KPX W ograve -30
+KPX W ohungarumlaut -30
+KPX W omacron -30
+KPX W oslash -30
+KPX W otilde -30
+KPX W period -80
+KPX W u -30
+KPX W uacute -30
+KPX W ucircumflex -30
+KPX W udieresis -30
+KPX W ugrave -30
+KPX W uhungarumlaut -30
+KPX W umacron -30
+KPX W uogonek -30
+KPX W uring -30
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -85
+KPX Y Oacute -85
+KPX Y Ocircumflex -85
+KPX Y Odieresis -85
+KPX Y Ograve -85
+KPX Y Ohungarumlaut -85
+KPX Y Omacron -85
+KPX Y Oslash -85
+KPX Y Otilde -85
+KPX Y a -140
+KPX Y aacute -140
+KPX Y abreve -70
+KPX Y acircumflex -140
+KPX Y adieresis -140
+KPX Y agrave -140
+KPX Y amacron -70
+KPX Y aogonek -140
+KPX Y aring -140
+KPX Y atilde -140
+KPX Y colon -60
+KPX Y comma -140
+KPX Y e -140
+KPX Y eacute -140
+KPX Y ecaron -140
+KPX Y ecircumflex -140
+KPX Y edieresis -140
+KPX Y edotaccent -140
+KPX Y egrave -140
+KPX Y emacron -70
+KPX Y eogonek -140
+KPX Y hyphen -140
+KPX Y i -20
+KPX Y iacute -20
+KPX Y iogonek -20
+KPX Y o -140
+KPX Y oacute -140
+KPX Y ocircumflex -140
+KPX Y odieresis -140
+KPX Y ograve -140
+KPX Y ohungarumlaut -140
+KPX Y omacron -140
+KPX Y oslash -140
+KPX Y otilde -140
+KPX Y period -140
+KPX Y semicolon -60
+KPX Y u -110
+KPX Y uacute -110
+KPX Y ucircumflex -110
+KPX Y udieresis -110
+KPX Y ugrave -110
+KPX Y uhungarumlaut -110
+KPX Y umacron -110
+KPX Y uogonek -110
+KPX Y uring -110
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -85
+KPX Yacute Oacute -85
+KPX Yacute Ocircumflex -85
+KPX Yacute Odieresis -85
+KPX Yacute Ograve -85
+KPX Yacute Ohungarumlaut -85
+KPX Yacute Omacron -85
+KPX Yacute Oslash -85
+KPX Yacute Otilde -85
+KPX Yacute a -140
+KPX Yacute aacute -140
+KPX Yacute abreve -70
+KPX Yacute acircumflex -140
+KPX Yacute adieresis -140
+KPX Yacute agrave -140
+KPX Yacute amacron -70
+KPX Yacute aogonek -140
+KPX Yacute aring -140
+KPX Yacute atilde -70
+KPX Yacute colon -60
+KPX Yacute comma -140
+KPX Yacute e -140
+KPX Yacute eacute -140
+KPX Yacute ecaron -140
+KPX Yacute ecircumflex -140
+KPX Yacute edieresis -140
+KPX Yacute edotaccent -140
+KPX Yacute egrave -140
+KPX Yacute emacron -70
+KPX Yacute eogonek -140
+KPX Yacute hyphen -140
+KPX Yacute i -20
+KPX Yacute iacute -20
+KPX Yacute iogonek -20
+KPX Yacute o -140
+KPX Yacute oacute -140
+KPX Yacute ocircumflex -140
+KPX Yacute odieresis -140
+KPX Yacute ograve -140
+KPX Yacute ohungarumlaut -140
+KPX Yacute omacron -70
+KPX Yacute oslash -140
+KPX Yacute otilde -140
+KPX Yacute period -140
+KPX Yacute semicolon -60
+KPX Yacute u -110
+KPX Yacute uacute -110
+KPX Yacute ucircumflex -110
+KPX Yacute udieresis -110
+KPX Yacute ugrave -110
+KPX Yacute uhungarumlaut -110
+KPX Yacute umacron -110
+KPX Yacute uogonek -110
+KPX Yacute uring -110
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -85
+KPX Ydieresis Oacute -85
+KPX Ydieresis Ocircumflex -85
+KPX Ydieresis Odieresis -85
+KPX Ydieresis Ograve -85
+KPX Ydieresis Ohungarumlaut -85
+KPX Ydieresis Omacron -85
+KPX Ydieresis Oslash -85
+KPX Ydieresis Otilde -85
+KPX Ydieresis a -140
+KPX Ydieresis aacute -140
+KPX Ydieresis abreve -70
+KPX Ydieresis acircumflex -140
+KPX Ydieresis adieresis -140
+KPX Ydieresis agrave -140
+KPX Ydieresis amacron -70
+KPX Ydieresis aogonek -140
+KPX Ydieresis aring -140
+KPX Ydieresis atilde -70
+KPX Ydieresis colon -60
+KPX Ydieresis comma -140
+KPX Ydieresis e -140
+KPX Ydieresis eacute -140
+KPX Ydieresis ecaron -140
+KPX Ydieresis ecircumflex -140
+KPX Ydieresis edieresis -140
+KPX Ydieresis edotaccent -140
+KPX Ydieresis egrave -140
+KPX Ydieresis emacron -70
+KPX Ydieresis eogonek -140
+KPX Ydieresis hyphen -140
+KPX Ydieresis i -20
+KPX Ydieresis iacute -20
+KPX Ydieresis iogonek -20
+KPX Ydieresis o -140
+KPX Ydieresis oacute -140
+KPX Ydieresis ocircumflex -140
+KPX Ydieresis odieresis -140
+KPX Ydieresis ograve -140
+KPX Ydieresis ohungarumlaut -140
+KPX Ydieresis omacron -140
+KPX Ydieresis oslash -140
+KPX Ydieresis otilde -140
+KPX Ydieresis period -140
+KPX Ydieresis semicolon -60
+KPX Ydieresis u -110
+KPX Ydieresis uacute -110
+KPX Ydieresis ucircumflex -110
+KPX Ydieresis udieresis -110
+KPX Ydieresis ugrave -110
+KPX Ydieresis uhungarumlaut -110
+KPX Ydieresis umacron -110
+KPX Ydieresis uogonek -110
+KPX Ydieresis uring -110
+KPX a v -20
+KPX a w -20
+KPX a y -30
+KPX a yacute -30
+KPX a ydieresis -30
+KPX aacute v -20
+KPX aacute w -20
+KPX aacute y -30
+KPX aacute yacute -30
+KPX aacute ydieresis -30
+KPX abreve v -20
+KPX abreve w -20
+KPX abreve y -30
+KPX abreve yacute -30
+KPX abreve ydieresis -30
+KPX acircumflex v -20
+KPX acircumflex w -20
+KPX acircumflex y -30
+KPX acircumflex yacute -30
+KPX acircumflex ydieresis -30
+KPX adieresis v -20
+KPX adieresis w -20
+KPX adieresis y -30
+KPX adieresis yacute -30
+KPX adieresis ydieresis -30
+KPX agrave v -20
+KPX agrave w -20
+KPX agrave y -30
+KPX agrave yacute -30
+KPX agrave ydieresis -30
+KPX amacron v -20
+KPX amacron w -20
+KPX amacron y -30
+KPX amacron yacute -30
+KPX amacron ydieresis -30
+KPX aogonek v -20
+KPX aogonek w -20
+KPX aogonek y -30
+KPX aogonek yacute -30
+KPX aogonek ydieresis -30
+KPX aring v -20
+KPX aring w -20
+KPX aring y -30
+KPX aring yacute -30
+KPX aring ydieresis -30
+KPX atilde v -20
+KPX atilde w -20
+KPX atilde y -30
+KPX atilde yacute -30
+KPX atilde ydieresis -30
+KPX b b -10
+KPX b comma -40
+KPX b l -20
+KPX b lacute -20
+KPX b lcommaaccent -20
+KPX b lslash -20
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c comma -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute comma -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron comma -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla comma -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX colon space -50
+KPX comma quotedblright -100
+KPX comma quoteright -100
+KPX e comma -15
+KPX e period -15
+KPX e v -30
+KPX e w -20
+KPX e x -30
+KPX e y -20
+KPX e yacute -20
+KPX e ydieresis -20
+KPX eacute comma -15
+KPX eacute period -15
+KPX eacute v -30
+KPX eacute w -20
+KPX eacute x -30
+KPX eacute y -20
+KPX eacute yacute -20
+KPX eacute ydieresis -20
+KPX ecaron comma -15
+KPX ecaron period -15
+KPX ecaron v -30
+KPX ecaron w -20
+KPX ecaron x -30
+KPX ecaron y -20
+KPX ecaron yacute -20
+KPX ecaron ydieresis -20
+KPX ecircumflex comma -15
+KPX ecircumflex period -15
+KPX ecircumflex v -30
+KPX ecircumflex w -20
+KPX ecircumflex x -30
+KPX ecircumflex y -20
+KPX ecircumflex yacute -20
+KPX ecircumflex ydieresis -20
+KPX edieresis comma -15
+KPX edieresis period -15
+KPX edieresis v -30
+KPX edieresis w -20
+KPX edieresis x -30
+KPX edieresis y -20
+KPX edieresis yacute -20
+KPX edieresis ydieresis -20
+KPX edotaccent comma -15
+KPX edotaccent period -15
+KPX edotaccent v -30
+KPX edotaccent w -20
+KPX edotaccent x -30
+KPX edotaccent y -20
+KPX edotaccent yacute -20
+KPX edotaccent ydieresis -20
+KPX egrave comma -15
+KPX egrave period -15
+KPX egrave v -30
+KPX egrave w -20
+KPX egrave x -30
+KPX egrave y -20
+KPX egrave yacute -20
+KPX egrave ydieresis -20
+KPX emacron comma -15
+KPX emacron period -15
+KPX emacron v -30
+KPX emacron w -20
+KPX emacron x -30
+KPX emacron y -20
+KPX emacron yacute -20
+KPX emacron ydieresis -20
+KPX eogonek comma -15
+KPX eogonek period -15
+KPX eogonek v -30
+KPX eogonek w -20
+KPX eogonek x -30
+KPX eogonek y -20
+KPX eogonek yacute -20
+KPX eogonek ydieresis -20
+KPX f a -30
+KPX f aacute -30
+KPX f abreve -30
+KPX f acircumflex -30
+KPX f adieresis -30
+KPX f agrave -30
+KPX f amacron -30
+KPX f aogonek -30
+KPX f aring -30
+KPX f atilde -30
+KPX f comma -30
+KPX f dotlessi -28
+KPX f e -30
+KPX f eacute -30
+KPX f ecaron -30
+KPX f ecircumflex -30
+KPX f edieresis -30
+KPX f edotaccent -30
+KPX f egrave -30
+KPX f emacron -30
+KPX f eogonek -30
+KPX f o -30
+KPX f oacute -30
+KPX f ocircumflex -30
+KPX f odieresis -30
+KPX f ograve -30
+KPX f ohungarumlaut -30
+KPX f omacron -30
+KPX f oslash -30
+KPX f otilde -30
+KPX f period -30
+KPX f quotedblright 60
+KPX f quoteright 50
+KPX g r -10
+KPX g racute -10
+KPX g rcaron -10
+KPX g rcommaaccent -10
+KPX gbreve r -10
+KPX gbreve racute -10
+KPX gbreve rcaron -10
+KPX gbreve rcommaaccent -10
+KPX gcommaaccent r -10
+KPX gcommaaccent racute -10
+KPX gcommaaccent rcaron -10
+KPX gcommaaccent rcommaaccent -10
+KPX h y -30
+KPX h yacute -30
+KPX h ydieresis -30
+KPX k e -20
+KPX k eacute -20
+KPX k ecaron -20
+KPX k ecircumflex -20
+KPX k edieresis -20
+KPX k edotaccent -20
+KPX k egrave -20
+KPX k emacron -20
+KPX k eogonek -20
+KPX k o -20
+KPX k oacute -20
+KPX k ocircumflex -20
+KPX k odieresis -20
+KPX k ograve -20
+KPX k ohungarumlaut -20
+KPX k omacron -20
+KPX k oslash -20
+KPX k otilde -20
+KPX kcommaaccent e -20
+KPX kcommaaccent eacute -20
+KPX kcommaaccent ecaron -20
+KPX kcommaaccent ecircumflex -20
+KPX kcommaaccent edieresis -20
+KPX kcommaaccent edotaccent -20
+KPX kcommaaccent egrave -20
+KPX kcommaaccent emacron -20
+KPX kcommaaccent eogonek -20
+KPX kcommaaccent o -20
+KPX kcommaaccent oacute -20
+KPX kcommaaccent ocircumflex -20
+KPX kcommaaccent odieresis -20
+KPX kcommaaccent ograve -20
+KPX kcommaaccent ohungarumlaut -20
+KPX kcommaaccent omacron -20
+KPX kcommaaccent oslash -20
+KPX kcommaaccent otilde -20
+KPX m u -10
+KPX m uacute -10
+KPX m ucircumflex -10
+KPX m udieresis -10
+KPX m ugrave -10
+KPX m uhungarumlaut -10
+KPX m umacron -10
+KPX m uogonek -10
+KPX m uring -10
+KPX m y -15
+KPX m yacute -15
+KPX m ydieresis -15
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -20
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -20
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -20
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -20
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -20
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o comma -40
+KPX o period -40
+KPX o v -15
+KPX o w -15
+KPX o x -30
+KPX o y -30
+KPX o yacute -30
+KPX o ydieresis -30
+KPX oacute comma -40
+KPX oacute period -40
+KPX oacute v -15
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -30
+KPX oacute yacute -30
+KPX oacute ydieresis -30
+KPX ocircumflex comma -40
+KPX ocircumflex period -40
+KPX ocircumflex v -15
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -30
+KPX ocircumflex yacute -30
+KPX ocircumflex ydieresis -30
+KPX odieresis comma -40
+KPX odieresis period -40
+KPX odieresis v -15
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -30
+KPX odieresis yacute -30
+KPX odieresis ydieresis -30
+KPX ograve comma -40
+KPX ograve period -40
+KPX ograve v -15
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -30
+KPX ograve yacute -30
+KPX ograve ydieresis -30
+KPX ohungarumlaut comma -40
+KPX ohungarumlaut period -40
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -30
+KPX ohungarumlaut yacute -30
+KPX ohungarumlaut ydieresis -30
+KPX omacron comma -40
+KPX omacron period -40
+KPX omacron v -15
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -30
+KPX omacron yacute -30
+KPX omacron ydieresis -30
+KPX oslash a -55
+KPX oslash aacute -55
+KPX oslash abreve -55
+KPX oslash acircumflex -55
+KPX oslash adieresis -55
+KPX oslash agrave -55
+KPX oslash amacron -55
+KPX oslash aogonek -55
+KPX oslash aring -55
+KPX oslash atilde -55
+KPX oslash b -55
+KPX oslash c -55
+KPX oslash cacute -55
+KPX oslash ccaron -55
+KPX oslash ccedilla -55
+KPX oslash comma -95
+KPX oslash d -55
+KPX oslash dcroat -55
+KPX oslash e -55
+KPX oslash eacute -55
+KPX oslash ecaron -55
+KPX oslash ecircumflex -55
+KPX oslash edieresis -55
+KPX oslash edotaccent -55
+KPX oslash egrave -55
+KPX oslash emacron -55
+KPX oslash eogonek -55
+KPX oslash f -55
+KPX oslash g -55
+KPX oslash gbreve -55
+KPX oslash gcommaaccent -55
+KPX oslash h -55
+KPX oslash i -55
+KPX oslash iacute -55
+KPX oslash icircumflex -55
+KPX oslash idieresis -55
+KPX oslash igrave -55
+KPX oslash imacron -55
+KPX oslash iogonek -55
+KPX oslash j -55
+KPX oslash k -55
+KPX oslash kcommaaccent -55
+KPX oslash l -55
+KPX oslash lacute -55
+KPX oslash lcommaaccent -55
+KPX oslash lslash -55
+KPX oslash m -55
+KPX oslash n -55
+KPX oslash nacute -55
+KPX oslash ncaron -55
+KPX oslash ncommaaccent -55
+KPX oslash ntilde -55
+KPX oslash o -55
+KPX oslash oacute -55
+KPX oslash ocircumflex -55
+KPX oslash odieresis -55
+KPX oslash ograve -55
+KPX oslash ohungarumlaut -55
+KPX oslash omacron -55
+KPX oslash oslash -55
+KPX oslash otilde -55
+KPX oslash p -55
+KPX oslash period -95
+KPX oslash q -55
+KPX oslash r -55
+KPX oslash racute -55
+KPX oslash rcaron -55
+KPX oslash rcommaaccent -55
+KPX oslash s -55
+KPX oslash sacute -55
+KPX oslash scaron -55
+KPX oslash scedilla -55
+KPX oslash scommaaccent -55
+KPX oslash t -55
+KPX oslash tcommaaccent -55
+KPX oslash u -55
+KPX oslash uacute -55
+KPX oslash ucircumflex -55
+KPX oslash udieresis -55
+KPX oslash ugrave -55
+KPX oslash uhungarumlaut -55
+KPX oslash umacron -55
+KPX oslash uogonek -55
+KPX oslash uring -55
+KPX oslash v -70
+KPX oslash w -70
+KPX oslash x -85
+KPX oslash y -70
+KPX oslash yacute -70
+KPX oslash ydieresis -70
+KPX oslash z -55
+KPX oslash zacute -55
+KPX oslash zcaron -55
+KPX oslash zdotaccent -55
+KPX otilde comma -40
+KPX otilde period -40
+KPX otilde v -15
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -30
+KPX otilde yacute -30
+KPX otilde ydieresis -30
+KPX p comma -35
+KPX p period -35
+KPX p y -30
+KPX p yacute -30
+KPX p ydieresis -30
+KPX period quotedblright -100
+KPX period quoteright -100
+KPX period space -60
+KPX quotedblright space -40
+KPX quoteleft quoteleft -57
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright quoteright -57
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -50
+KPX quoteright sacute -50
+KPX quoteright scaron -50
+KPX quoteright scedilla -50
+KPX quoteright scommaaccent -50
+KPX quoteright space -70
+KPX r a -10
+KPX r aacute -10
+KPX r abreve -10
+KPX r acircumflex -10
+KPX r adieresis -10
+KPX r agrave -10
+KPX r amacron -10
+KPX r aogonek -10
+KPX r aring -10
+KPX r atilde -10
+KPX r colon 30
+KPX r comma -50
+KPX r i 15
+KPX r iacute 15
+KPX r icircumflex 15
+KPX r idieresis 15
+KPX r igrave 15
+KPX r imacron 15
+KPX r iogonek 15
+KPX r k 15
+KPX r kcommaaccent 15
+KPX r l 15
+KPX r lacute 15
+KPX r lcommaaccent 15
+KPX r lslash 15
+KPX r m 25
+KPX r n 25
+KPX r nacute 25
+KPX r ncaron 25
+KPX r ncommaaccent 25
+KPX r ntilde 25
+KPX r p 30
+KPX r period -50
+KPX r semicolon 30
+KPX r t 40
+KPX r tcommaaccent 40
+KPX r u 15
+KPX r uacute 15
+KPX r ucircumflex 15
+KPX r udieresis 15
+KPX r ugrave 15
+KPX r uhungarumlaut 15
+KPX r umacron 15
+KPX r uogonek 15
+KPX r uring 15
+KPX r v 30
+KPX r y 30
+KPX r yacute 30
+KPX r ydieresis 30
+KPX racute a -10
+KPX racute aacute -10
+KPX racute abreve -10
+KPX racute acircumflex -10
+KPX racute adieresis -10
+KPX racute agrave -10
+KPX racute amacron -10
+KPX racute aogonek -10
+KPX racute aring -10
+KPX racute atilde -10
+KPX racute colon 30
+KPX racute comma -50
+KPX racute i 15
+KPX racute iacute 15
+KPX racute icircumflex 15
+KPX racute idieresis 15
+KPX racute igrave 15
+KPX racute imacron 15
+KPX racute iogonek 15
+KPX racute k 15
+KPX racute kcommaaccent 15
+KPX racute l 15
+KPX racute lacute 15
+KPX racute lcommaaccent 15
+KPX racute lslash 15
+KPX racute m 25
+KPX racute n 25
+KPX racute nacute 25
+KPX racute ncaron 25
+KPX racute ncommaaccent 25
+KPX racute ntilde 25
+KPX racute p 30
+KPX racute period -50
+KPX racute semicolon 30
+KPX racute t 40
+KPX racute tcommaaccent 40
+KPX racute u 15
+KPX racute uacute 15
+KPX racute ucircumflex 15
+KPX racute udieresis 15
+KPX racute ugrave 15
+KPX racute uhungarumlaut 15
+KPX racute umacron 15
+KPX racute uogonek 15
+KPX racute uring 15
+KPX racute v 30
+KPX racute y 30
+KPX racute yacute 30
+KPX racute ydieresis 30
+KPX rcaron a -10
+KPX rcaron aacute -10
+KPX rcaron abreve -10
+KPX rcaron acircumflex -10
+KPX rcaron adieresis -10
+KPX rcaron agrave -10
+KPX rcaron amacron -10
+KPX rcaron aogonek -10
+KPX rcaron aring -10
+KPX rcaron atilde -10
+KPX rcaron colon 30
+KPX rcaron comma -50
+KPX rcaron i 15
+KPX rcaron iacute 15
+KPX rcaron icircumflex 15
+KPX rcaron idieresis 15
+KPX rcaron igrave 15
+KPX rcaron imacron 15
+KPX rcaron iogonek 15
+KPX rcaron k 15
+KPX rcaron kcommaaccent 15
+KPX rcaron l 15
+KPX rcaron lacute 15
+KPX rcaron lcommaaccent 15
+KPX rcaron lslash 15
+KPX rcaron m 25
+KPX rcaron n 25
+KPX rcaron nacute 25
+KPX rcaron ncaron 25
+KPX rcaron ncommaaccent 25
+KPX rcaron ntilde 25
+KPX rcaron p 30
+KPX rcaron period -50
+KPX rcaron semicolon 30
+KPX rcaron t 40
+KPX rcaron tcommaaccent 40
+KPX rcaron u 15
+KPX rcaron uacute 15
+KPX rcaron ucircumflex 15
+KPX rcaron udieresis 15
+KPX rcaron ugrave 15
+KPX rcaron uhungarumlaut 15
+KPX rcaron umacron 15
+KPX rcaron uogonek 15
+KPX rcaron uring 15
+KPX rcaron v 30
+KPX rcaron y 30
+KPX rcaron yacute 30
+KPX rcaron ydieresis 30
+KPX rcommaaccent a -10
+KPX rcommaaccent aacute -10
+KPX rcommaaccent abreve -10
+KPX rcommaaccent acircumflex -10
+KPX rcommaaccent adieresis -10
+KPX rcommaaccent agrave -10
+KPX rcommaaccent amacron -10
+KPX rcommaaccent aogonek -10
+KPX rcommaaccent aring -10
+KPX rcommaaccent atilde -10
+KPX rcommaaccent colon 30
+KPX rcommaaccent comma -50
+KPX rcommaaccent i 15
+KPX rcommaaccent iacute 15
+KPX rcommaaccent icircumflex 15
+KPX rcommaaccent idieresis 15
+KPX rcommaaccent igrave 15
+KPX rcommaaccent imacron 15
+KPX rcommaaccent iogonek 15
+KPX rcommaaccent k 15
+KPX rcommaaccent kcommaaccent 15
+KPX rcommaaccent l 15
+KPX rcommaaccent lacute 15
+KPX rcommaaccent lcommaaccent 15
+KPX rcommaaccent lslash 15
+KPX rcommaaccent m 25
+KPX rcommaaccent n 25
+KPX rcommaaccent nacute 25
+KPX rcommaaccent ncaron 25
+KPX rcommaaccent ncommaaccent 25
+KPX rcommaaccent ntilde 25
+KPX rcommaaccent p 30
+KPX rcommaaccent period -50
+KPX rcommaaccent semicolon 30
+KPX rcommaaccent t 40
+KPX rcommaaccent tcommaaccent 40
+KPX rcommaaccent u 15
+KPX rcommaaccent uacute 15
+KPX rcommaaccent ucircumflex 15
+KPX rcommaaccent udieresis 15
+KPX rcommaaccent ugrave 15
+KPX rcommaaccent uhungarumlaut 15
+KPX rcommaaccent umacron 15
+KPX rcommaaccent uogonek 15
+KPX rcommaaccent uring 15
+KPX rcommaaccent v 30
+KPX rcommaaccent y 30
+KPX rcommaaccent yacute 30
+KPX rcommaaccent ydieresis 30
+KPX s comma -15
+KPX s period -15
+KPX s w -30
+KPX sacute comma -15
+KPX sacute period -15
+KPX sacute w -30
+KPX scaron comma -15
+KPX scaron period -15
+KPX scaron w -30
+KPX scedilla comma -15
+KPX scedilla period -15
+KPX scedilla w -30
+KPX scommaaccent comma -15
+KPX scommaaccent period -15
+KPX scommaaccent w -30
+KPX semicolon space -50
+KPX space T -50
+KPX space Tcaron -50
+KPX space Tcommaaccent -50
+KPX space V -50
+KPX space W -40
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX space quotedblleft -30
+KPX space quoteleft -60
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -80
+KPX v e -25
+KPX v eacute -25
+KPX v ecaron -25
+KPX v ecircumflex -25
+KPX v edieresis -25
+KPX v edotaccent -25
+KPX v egrave -25
+KPX v emacron -25
+KPX v eogonek -25
+KPX v o -25
+KPX v oacute -25
+KPX v ocircumflex -25
+KPX v odieresis -25
+KPX v ograve -25
+KPX v ohungarumlaut -25
+KPX v omacron -25
+KPX v oslash -25
+KPX v otilde -25
+KPX v period -80
+KPX w a -15
+KPX w aacute -15
+KPX w abreve -15
+KPX w acircumflex -15
+KPX w adieresis -15
+KPX w agrave -15
+KPX w amacron -15
+KPX w aogonek -15
+KPX w aring -15
+KPX w atilde -15
+KPX w comma -60
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -60
+KPX x e -30
+KPX x eacute -30
+KPX x ecaron -30
+KPX x ecircumflex -30
+KPX x edieresis -30
+KPX x edotaccent -30
+KPX x egrave -30
+KPX x emacron -30
+KPX x eogonek -30
+KPX y a -20
+KPX y aacute -20
+KPX y abreve -20
+KPX y acircumflex -20
+KPX y adieresis -20
+KPX y agrave -20
+KPX y amacron -20
+KPX y aogonek -20
+KPX y aring -20
+KPX y atilde -20
+KPX y comma -100
+KPX y e -20
+KPX y eacute -20
+KPX y ecaron -20
+KPX y ecircumflex -20
+KPX y edieresis -20
+KPX y edotaccent -20
+KPX y egrave -20
+KPX y emacron -20
+KPX y eogonek -20
+KPX y o -20
+KPX y oacute -20
+KPX y ocircumflex -20
+KPX y odieresis -20
+KPX y ograve -20
+KPX y ohungarumlaut -20
+KPX y omacron -20
+KPX y oslash -20
+KPX y otilde -20
+KPX y period -100
+KPX yacute a -20
+KPX yacute aacute -20
+KPX yacute abreve -20
+KPX yacute acircumflex -20
+KPX yacute adieresis -20
+KPX yacute agrave -20
+KPX yacute amacron -20
+KPX yacute aogonek -20
+KPX yacute aring -20
+KPX yacute atilde -20
+KPX yacute comma -100
+KPX yacute e -20
+KPX yacute eacute -20
+KPX yacute ecaron -20
+KPX yacute ecircumflex -20
+KPX yacute edieresis -20
+KPX yacute edotaccent -20
+KPX yacute egrave -20
+KPX yacute emacron -20
+KPX yacute eogonek -20
+KPX yacute o -20
+KPX yacute oacute -20
+KPX yacute ocircumflex -20
+KPX yacute odieresis -20
+KPX yacute ograve -20
+KPX yacute ohungarumlaut -20
+KPX yacute omacron -20
+KPX yacute oslash -20
+KPX yacute otilde -20
+KPX yacute period -100
+KPX ydieresis a -20
+KPX ydieresis aacute -20
+KPX ydieresis abreve -20
+KPX ydieresis acircumflex -20
+KPX ydieresis adieresis -20
+KPX ydieresis agrave -20
+KPX ydieresis amacron -20
+KPX ydieresis aogonek -20
+KPX ydieresis aring -20
+KPX ydieresis atilde -20
+KPX ydieresis comma -100
+KPX ydieresis e -20
+KPX ydieresis eacute -20
+KPX ydieresis ecaron -20
+KPX ydieresis ecircumflex -20
+KPX ydieresis edieresis -20
+KPX ydieresis edotaccent -20
+KPX ydieresis egrave -20
+KPX ydieresis emacron -20
+KPX ydieresis eogonek -20
+KPX ydieresis o -20
+KPX ydieresis oacute -20
+KPX ydieresis ocircumflex -20
+KPX ydieresis odieresis -20
+KPX ydieresis ograve -20
+KPX ydieresis ohungarumlaut -20
+KPX ydieresis omacron -20
+KPX ydieresis oslash -20
+KPX ydieresis otilde -20
+KPX ydieresis period -100
+KPX z e -15
+KPX z eacute -15
+KPX z ecaron -15
+KPX z ecircumflex -15
+KPX z edieresis -15
+KPX z edotaccent -15
+KPX z egrave -15
+KPX z emacron -15
+KPX z eogonek -15
+KPX z o -15
+KPX z oacute -15
+KPX z ocircumflex -15
+KPX z odieresis -15
+KPX z ograve -15
+KPX z ohungarumlaut -15
+KPX z omacron -15
+KPX z oslash -15
+KPX z otilde -15
+KPX zacute e -15
+KPX zacute eacute -15
+KPX zacute ecaron -15
+KPX zacute ecircumflex -15
+KPX zacute edieresis -15
+KPX zacute edotaccent -15
+KPX zacute egrave -15
+KPX zacute emacron -15
+KPX zacute eogonek -15
+KPX zacute o -15
+KPX zacute oacute -15
+KPX zacute ocircumflex -15
+KPX zacute odieresis -15
+KPX zacute ograve -15
+KPX zacute ohungarumlaut -15
+KPX zacute omacron -15
+KPX zacute oslash -15
+KPX zacute otilde -15
+KPX zcaron e -15
+KPX zcaron eacute -15
+KPX zcaron ecaron -15
+KPX zcaron ecircumflex -15
+KPX zcaron edieresis -15
+KPX zcaron edotaccent -15
+KPX zcaron egrave -15
+KPX zcaron emacron -15
+KPX zcaron eogonek -15
+KPX zcaron o -15
+KPX zcaron oacute -15
+KPX zcaron ocircumflex -15
+KPX zcaron odieresis -15
+KPX zcaron ograve -15
+KPX zcaron ohungarumlaut -15
+KPX zcaron omacron -15
+KPX zcaron oslash -15
+KPX zcaron otilde -15
+KPX zdotaccent e -15
+KPX zdotaccent eacute -15
+KPX zdotaccent ecaron -15
+KPX zdotaccent ecircumflex -15
+KPX zdotaccent edieresis -15
+KPX zdotaccent edotaccent -15
+KPX zdotaccent egrave -15
+KPX zdotaccent emacron -15
+KPX zdotaccent eogonek -15
+KPX zdotaccent o -15
+KPX zdotaccent oacute -15
+KPX zdotaccent ocircumflex -15
+KPX zdotaccent odieresis -15
+KPX zdotaccent ograve -15
+KPX zdotaccent ohungarumlaut -15
+KPX zdotaccent omacron -15
+KPX zdotaccent oslash -15
+KPX zdotaccent otilde -15
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Symbol.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Symbol.afm
new file mode 100644
index 0000000..51c39f5
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Symbol.afm
@@ -0,0 +1,214 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu May  1 15:12:25 1997
+Comment UniqueID 43064
+Comment VMusage 30820 39997
+FontName Symbol
+FullName Symbol
+FamilyName Symbol
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet Special
+FontBBox -180 -293 1090 1010 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.008
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme FontSpecific
+StdHW 92
+StdVW 85
+StartCharMetrics 190
+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 24 -14 476 685 ;
+C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
+C 50 ; WX 500 ; N two ; B 25 0 475 685 ;
+C 51 ; WX 500 ; N three ; B 43 -14 435 685 ;
+C 52 ; WX 500 ; N four ; B 15 0 469 685 ;
+C 53 ; WX 500 ; N five ; B 32 -14 445 690 ;
+C 54 ; WX 500 ; N six ; B 34 -14 468 685 ;
+C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
+C 56 ; WX 500 ; N eight ; B 56 -14 445 685 ;
+C 57 ; WX 500 ; N nine ; B 30 -18 459 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 487 ;
+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 -125 502 -75 ;
+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 28 -224 492 673 ;
+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 -293 135 707 ;
+C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
+C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
+C 160 ; WX 750 ; N Euro ; B 20 -12 714 685 ;
+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 24 -293 436 926 ;
+C 231 ; WX 384 ; N parenleftex ; B 24 -85 108 925 ;
+C 232 ; WX 384 ; N parenleftbt ; B 24 -293 436 926 ;
+C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 349 926 ;
+C 234 ; WX 384 ; N bracketleftex ; B 0 -79 77 925 ;
+C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 349 926 ;
+C 236 ; WX 494 ; N bracelefttp ; B 209 -85 445 925 ;
+C 237 ; WX 494 ; N braceleftmid ; B 20 -85 284 935 ;
+C 238 ; WX 494 ; N braceleftbt ; B 209 -75 445 935 ;
+C 239 ; WX 494 ; N braceex ; B 209 -85 284 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 308 -88 675 920 ;
+C 244 ; WX 686 ; N integralex ; B 308 -88 378 975 ;
+C 245 ; WX 686 ; N integralbt ; B 11 -87 378 921 ;
+C 246 ; WX 384 ; N parenrighttp ; B 54 -293 466 926 ;
+C 247 ; WX 384 ; N parenrightex ; B 382 -85 466 925 ;
+C 248 ; WX 384 ; N parenrightbt ; B 54 -293 466 926 ;
+C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 371 926 ;
+C 250 ; WX 384 ; N bracketrightex ; B 294 -79 371 925 ;
+C 251 ; WX 384 ; N bracketrightbt ; B 22 -80 371 926 ;
+C 252 ; WX 494 ; N bracerighttp ; B 48 -85 284 925 ;
+C 253 ; WX 494 ; N bracerightmid ; B 209 -85 473 935 ;
+C 254 ; WX 494 ; N bracerightbt ; B 48 -75 284 935 ;
+C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Times-Bold.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Bold.afm
new file mode 100644
index 0000000..188f56e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Bold.afm
@@ -0,0 +1,2589 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:52:56 1997
+Comment UniqueID 43065
+Comment VMusage 41636 52661
+FontName Times-Bold
+FullName Times Bold
+FamilyName Times
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -168 -218 1000 935 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 676
+XHeight 461
+Ascender 683
+Descender -217
+StdHW 44
+StdVW 139
+StartCharMetrics 315
+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 -218 154 782 ;
+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 536 258 691 ;
+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 -193 319 24 ;
+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 389 ; N Idieresis ; B 20 0 370 877 ;
+C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ;
+C -1 ; WX 500 ; N abreve ; B 25 -14 488 691 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 16 -14 557 713 ;
+C -1 ; WX 444 ; N ecaron ; B 25 -14 426 704 ;
+C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ;
+C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ;
+C -1 ; WX 722 ; N Yacute ; B 15 0 699 923 ;
+C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ;
+C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ;
+C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ;
+C -1 ; WX 389 ; N scommaaccent ; B 25 -218 361 473 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ;
+C -1 ; WX 722 ; N Uring ; B 16 -19 701 935 ;
+C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ;
+C -1 ; WX 500 ; N aogonek ; B 25 -193 504 473 ;
+C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ;
+C -1 ; WX 556 ; N uogonek ; B 16 -193 539 461 ;
+C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ;
+C -1 ; WX 722 ; N Dcroat ; B 6 0 690 676 ;
+C -1 ; WX 250 ; N commaaccent ; B 47 -218 203 -50 ;
+C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ;
+C -1 ; WX 667 ; N Emacron ; B 16 0 641 847 ;
+C -1 ; WX 444 ; N ccaron ; B 25 -14 430 704 ;
+C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 16 -188 701 676 ;
+C -1 ; WX 278 ; N lacute ; B 16 0 297 923 ;
+C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ;
+C -1 ; WX 667 ; N Tcommaaccent ; B 31 -218 636 676 ;
+C -1 ; WX 722 ; N Cacute ; B 49 -19 687 923 ;
+C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ;
+C -1 ; WX 667 ; N Edotaccent ; B 16 0 641 901 ;
+C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ;
+C -1 ; WX 389 ; N scedilla ; B 25 -218 361 473 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 289 713 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 26 0 715 914 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 37 -218 755 691 ;
+C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ;
+C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ;
+C -1 ; WX 722 ; N Amacron ; B 9 0 689 847 ;
+C -1 ; WX 444 ; N rcaron ; B 29 0 434 704 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ;
+C -1 ; WX 667 ; N Zdotaccent ; B 28 0 634 901 ;
+C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ;
+C -1 ; WX 778 ; N Omacron ; B 35 -19 743 847 ;
+C -1 ; WX 722 ; N Racute ; B 26 0 715 923 ;
+C -1 ; WX 556 ; N Sacute ; B 35 -19 513 923 ;
+C -1 ; WX 672 ; N dcaron ; B 25 -14 681 682 ;
+C -1 ; WX 722 ; N Umacron ; B 16 -19 701 847 ;
+C -1 ; WX 556 ; N uring ; B 16 -14 537 740 ;
+C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ;
+C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ;
+C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ;
+C -1 ; WX 722 ; N Abreve ; B 9 0 689 901 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ;
+C -1 ; WX 667 ; N Tcaron ; B 31 0 636 914 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ;
+C -1 ; WX 722 ; N Nacute ; B 16 -18 701 923 ;
+C -1 ; WX 278 ; N icircumflex ; B -37 0 300 704 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ;
+C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ;
+C -1 ; WX 444 ; N cacute ; B 25 -14 430 713 ;
+C -1 ; WX 556 ; N nacute ; B 21 0 539 713 ;
+C -1 ; WX 556 ; N umacron ; B 16 -14 537 637 ;
+C -1 ; WX 722 ; N Ncaron ; B 16 -18 701 914 ;
+C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
+C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ;
+C -1 ; WX 778 ; N Gbreve ; B 37 -19 755 901 ;
+C -1 ; WX 389 ; N Idotaccent ; B 20 0 370 901 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ;
+C -1 ; WX 444 ; N racute ; B 29 0 434 713 ;
+C -1 ; WX 500 ; N omacron ; B 25 -14 476 637 ;
+C -1 ; WX 667 ; N Zacute ; B 28 0 634 923 ;
+C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ;
+C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 16 -218 255 676 ;
+C -1 ; WX 416 ; N tcaron ; B 20 -12 425 815 ;
+C -1 ; WX 444 ; N eogonek ; B 25 -193 426 473 ;
+C -1 ; WX 722 ; N Uogonek ; B 16 -193 701 676 ;
+C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ;
+C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ;
+C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ;
+C -1 ; WX 444 ; N zacute ; B 21 0 420 713 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -193 274 691 ;
+C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ;
+C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ;
+C -1 ; WX 500 ; N amacron ; B 25 -14 488 637 ;
+C -1 ; WX 389 ; N sacute ; B 25 -14 361 713 ;
+C -1 ; WX 278 ; N idieresis ; B -37 0 300 667 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ;
+C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ;
+C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ;
+C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ;
+C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ;
+C -1 ; WX 278 ; N igrave ; B -27 0 255 713 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 25 -14 529 713 ;
+C -1 ; WX 667 ; N Eogonek ; B 16 -193 644 676 ;
+C -1 ; WX 556 ; N dcroat ; B 25 -14 534 676 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ;
+C -1 ; WX 556 ; N Scedilla ; B 35 -218 513 692 ;
+C -1 ; WX 394 ; N lcaron ; B 16 0 412 682 ;
+C -1 ; WX 778 ; N Kcommaaccent ; B 30 -218 769 676 ;
+C -1 ; WX 667 ; N Lacute ; B 19 0 638 923 ;
+C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ;
+C -1 ; WX 444 ; N edotaccent ; B 25 -14 426 691 ;
+C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ;
+C -1 ; WX 389 ; N Imacron ; B 20 0 370 847 ;
+C -1 ; WX 667 ; N Lcaron ; B 19 0 652 682 ;
+C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ;
+C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 16 -19 701 923 ;
+C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ;
+C -1 ; WX 444 ; N emacron ; B 25 -14 426 637 ;
+C -1 ; WX 500 ; N gbreve ; B 28 -206 483 691 ;
+C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ;
+C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 35 -218 513 692 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 35 -19 743 923 ;
+C -1 ; WX 400 ; N degree ; B 57 402 343 688 ;
+C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ;
+C -1 ; WX 722 ; N Ccaron ; B 49 -19 687 914 ;
+C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 14 0 690 914 ;
+C -1 ; WX 444 ; N rcommaaccent ; B 29 -218 434 473 ;
+C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ;
+C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 26 -218 715 676 ;
+C -1 ; WX 667 ; N Lcommaaccent ; B 19 -218 638 676 ;
+C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ;
+C -1 ; WX 722 ; N Aogonek ; B 9 -193 699 690 ;
+C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ;
+C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ;
+C -1 ; WX 444 ; N zdotaccent ; B 21 0 420 691 ;
+C -1 ; WX 667 ; N Ecaron ; B 16 0 641 914 ;
+C -1 ; WX 389 ; N Iogonek ; B 20 -193 370 676 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 22 -218 543 676 ;
+C -1 ; WX 570 ; N minus ; B 33 209 537 297 ;
+C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ;
+C -1 ; WX 556 ; N ncaron ; B 21 0 539 704 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 20 -218 332 630 ;
+C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ;
+C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ;
+C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 28 -206 483 829 ;
+C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ;
+C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 21 -218 539 473 ;
+C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ;
+C -1 ; WX 278 ; N imacron ; B -8 0 272 637 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2242
+KPX A C -55
+KPX A Cacute -55
+KPX A Ccaron -55
+KPX A Ccedilla -55
+KPX A G -55
+KPX A Gbreve -55
+KPX A Gcommaaccent -55
+KPX A O -45
+KPX A Oacute -45
+KPX A Ocircumflex -45
+KPX A Odieresis -45
+KPX A Ograve -45
+KPX A Ohungarumlaut -45
+KPX A Omacron -45
+KPX A Oslash -45
+KPX A Otilde -45
+KPX A Q -45
+KPX A T -95
+KPX A Tcaron -95
+KPX A Tcommaaccent -95
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -145
+KPX A W -130
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A p -25
+KPX A quoteright -74
+KPX A u -50
+KPX A uacute -50
+KPX A ucircumflex -50
+KPX A udieresis -50
+KPX A ugrave -50
+KPX A uhungarumlaut -50
+KPX A umacron -50
+KPX A uogonek -50
+KPX A uring -50
+KPX A v -100
+KPX A w -90
+KPX A y -74
+KPX A yacute -74
+KPX A ydieresis -74
+KPX Aacute C -55
+KPX Aacute Cacute -55
+KPX Aacute Ccaron -55
+KPX Aacute Ccedilla -55
+KPX Aacute G -55
+KPX Aacute Gbreve -55
+KPX Aacute Gcommaaccent -55
+KPX Aacute O -45
+KPX Aacute Oacute -45
+KPX Aacute Ocircumflex -45
+KPX Aacute Odieresis -45
+KPX Aacute Ograve -45
+KPX Aacute Ohungarumlaut -45
+KPX Aacute Omacron -45
+KPX Aacute Oslash -45
+KPX Aacute Otilde -45
+KPX Aacute Q -45
+KPX Aacute T -95
+KPX Aacute Tcaron -95
+KPX Aacute Tcommaaccent -95
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -145
+KPX Aacute W -130
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute p -25
+KPX Aacute quoteright -74
+KPX Aacute u -50
+KPX Aacute uacute -50
+KPX Aacute ucircumflex -50
+KPX Aacute udieresis -50
+KPX Aacute ugrave -50
+KPX Aacute uhungarumlaut -50
+KPX Aacute umacron -50
+KPX Aacute uogonek -50
+KPX Aacute uring -50
+KPX Aacute v -100
+KPX Aacute w -90
+KPX Aacute y -74
+KPX Aacute yacute -74
+KPX Aacute ydieresis -74
+KPX Abreve C -55
+KPX Abreve Cacute -55
+KPX Abreve Ccaron -55
+KPX Abreve Ccedilla -55
+KPX Abreve G -55
+KPX Abreve Gbreve -55
+KPX Abreve Gcommaaccent -55
+KPX Abreve O -45
+KPX Abreve Oacute -45
+KPX Abreve Ocircumflex -45
+KPX Abreve Odieresis -45
+KPX Abreve Ograve -45
+KPX Abreve Ohungarumlaut -45
+KPX Abreve Omacron -45
+KPX Abreve Oslash -45
+KPX Abreve Otilde -45
+KPX Abreve Q -45
+KPX Abreve T -95
+KPX Abreve Tcaron -95
+KPX Abreve Tcommaaccent -95
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -145
+KPX Abreve W -130
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve p -25
+KPX Abreve quoteright -74
+KPX Abreve u -50
+KPX Abreve uacute -50
+KPX Abreve ucircumflex -50
+KPX Abreve udieresis -50
+KPX Abreve ugrave -50
+KPX Abreve uhungarumlaut -50
+KPX Abreve umacron -50
+KPX Abreve uogonek -50
+KPX Abreve uring -50
+KPX Abreve v -100
+KPX Abreve w -90
+KPX Abreve y -74
+KPX Abreve yacute -74
+KPX Abreve ydieresis -74
+KPX Acircumflex C -55
+KPX Acircumflex Cacute -55
+KPX Acircumflex Ccaron -55
+KPX Acircumflex Ccedilla -55
+KPX Acircumflex G -55
+KPX Acircumflex Gbreve -55
+KPX Acircumflex Gcommaaccent -55
+KPX Acircumflex O -45
+KPX Acircumflex Oacute -45
+KPX Acircumflex Ocircumflex -45
+KPX Acircumflex Odieresis -45
+KPX Acircumflex Ograve -45
+KPX Acircumflex Ohungarumlaut -45
+KPX Acircumflex Omacron -45
+KPX Acircumflex Oslash -45
+KPX Acircumflex Otilde -45
+KPX Acircumflex Q -45
+KPX Acircumflex T -95
+KPX Acircumflex Tcaron -95
+KPX Acircumflex Tcommaaccent -95
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -145
+KPX Acircumflex W -130
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex p -25
+KPX Acircumflex quoteright -74
+KPX Acircumflex u -50
+KPX Acircumflex uacute -50
+KPX Acircumflex ucircumflex -50
+KPX Acircumflex udieresis -50
+KPX Acircumflex ugrave -50
+KPX Acircumflex uhungarumlaut -50
+KPX Acircumflex umacron -50
+KPX Acircumflex uogonek -50
+KPX Acircumflex uring -50
+KPX Acircumflex v -100
+KPX Acircumflex w -90
+KPX Acircumflex y -74
+KPX Acircumflex yacute -74
+KPX Acircumflex ydieresis -74
+KPX Adieresis C -55
+KPX Adieresis Cacute -55
+KPX Adieresis Ccaron -55
+KPX Adieresis Ccedilla -55
+KPX Adieresis G -55
+KPX Adieresis Gbreve -55
+KPX Adieresis Gcommaaccent -55
+KPX Adieresis O -45
+KPX Adieresis Oacute -45
+KPX Adieresis Ocircumflex -45
+KPX Adieresis Odieresis -45
+KPX Adieresis Ograve -45
+KPX Adieresis Ohungarumlaut -45
+KPX Adieresis Omacron -45
+KPX Adieresis Oslash -45
+KPX Adieresis Otilde -45
+KPX Adieresis Q -45
+KPX Adieresis T -95
+KPX Adieresis Tcaron -95
+KPX Adieresis Tcommaaccent -95
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -145
+KPX Adieresis W -130
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis p -25
+KPX Adieresis quoteright -74
+KPX Adieresis u -50
+KPX Adieresis uacute -50
+KPX Adieresis ucircumflex -50
+KPX Adieresis udieresis -50
+KPX Adieresis ugrave -50
+KPX Adieresis uhungarumlaut -50
+KPX Adieresis umacron -50
+KPX Adieresis uogonek -50
+KPX Adieresis uring -50
+KPX Adieresis v -100
+KPX Adieresis w -90
+KPX Adieresis y -74
+KPX Adieresis yacute -74
+KPX Adieresis ydieresis -74
+KPX Agrave C -55
+KPX Agrave Cacute -55
+KPX Agrave Ccaron -55
+KPX Agrave Ccedilla -55
+KPX Agrave G -55
+KPX Agrave Gbreve -55
+KPX Agrave Gcommaaccent -55
+KPX Agrave O -45
+KPX Agrave Oacute -45
+KPX Agrave Ocircumflex -45
+KPX Agrave Odieresis -45
+KPX Agrave Ograve -45
+KPX Agrave Ohungarumlaut -45
+KPX Agrave Omacron -45
+KPX Agrave Oslash -45
+KPX Agrave Otilde -45
+KPX Agrave Q -45
+KPX Agrave T -95
+KPX Agrave Tcaron -95
+KPX Agrave Tcommaaccent -95
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -145
+KPX Agrave W -130
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave p -25
+KPX Agrave quoteright -74
+KPX Agrave u -50
+KPX Agrave uacute -50
+KPX Agrave ucircumflex -50
+KPX Agrave udieresis -50
+KPX Agrave ugrave -50
+KPX Agrave uhungarumlaut -50
+KPX Agrave umacron -50
+KPX Agrave uogonek -50
+KPX Agrave uring -50
+KPX Agrave v -100
+KPX Agrave w -90
+KPX Agrave y -74
+KPX Agrave yacute -74
+KPX Agrave ydieresis -74
+KPX Amacron C -55
+KPX Amacron Cacute -55
+KPX Amacron Ccaron -55
+KPX Amacron Ccedilla -55
+KPX Amacron G -55
+KPX Amacron Gbreve -55
+KPX Amacron Gcommaaccent -55
+KPX Amacron O -45
+KPX Amacron Oacute -45
+KPX Amacron Ocircumflex -45
+KPX Amacron Odieresis -45
+KPX Amacron Ograve -45
+KPX Amacron Ohungarumlaut -45
+KPX Amacron Omacron -45
+KPX Amacron Oslash -45
+KPX Amacron Otilde -45
+KPX Amacron Q -45
+KPX Amacron T -95
+KPX Amacron Tcaron -95
+KPX Amacron Tcommaaccent -95
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -145
+KPX Amacron W -130
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron p -25
+KPX Amacron quoteright -74
+KPX Amacron u -50
+KPX Amacron uacute -50
+KPX Amacron ucircumflex -50
+KPX Amacron udieresis -50
+KPX Amacron ugrave -50
+KPX Amacron uhungarumlaut -50
+KPX Amacron umacron -50
+KPX Amacron uogonek -50
+KPX Amacron uring -50
+KPX Amacron v -100
+KPX Amacron w -90
+KPX Amacron y -74
+KPX Amacron yacute -74
+KPX Amacron ydieresis -74
+KPX Aogonek C -55
+KPX Aogonek Cacute -55
+KPX Aogonek Ccaron -55
+KPX Aogonek Ccedilla -55
+KPX Aogonek G -55
+KPX Aogonek Gbreve -55
+KPX Aogonek Gcommaaccent -55
+KPX Aogonek O -45
+KPX Aogonek Oacute -45
+KPX Aogonek Ocircumflex -45
+KPX Aogonek Odieresis -45
+KPX Aogonek Ograve -45
+KPX Aogonek Ohungarumlaut -45
+KPX Aogonek Omacron -45
+KPX Aogonek Oslash -45
+KPX Aogonek Otilde -45
+KPX Aogonek Q -45
+KPX Aogonek T -95
+KPX Aogonek Tcaron -95
+KPX Aogonek Tcommaaccent -95
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -145
+KPX Aogonek W -130
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek p -25
+KPX Aogonek quoteright -74
+KPX Aogonek u -50
+KPX Aogonek uacute -50
+KPX Aogonek ucircumflex -50
+KPX Aogonek udieresis -50
+KPX Aogonek ugrave -50
+KPX Aogonek uhungarumlaut -50
+KPX Aogonek umacron -50
+KPX Aogonek uogonek -50
+KPX Aogonek uring -50
+KPX Aogonek v -100
+KPX Aogonek w -90
+KPX Aogonek y -34
+KPX Aogonek yacute -34
+KPX Aogonek ydieresis -34
+KPX Aring C -55
+KPX Aring Cacute -55
+KPX Aring Ccaron -55
+KPX Aring Ccedilla -55
+KPX Aring G -55
+KPX Aring Gbreve -55
+KPX Aring Gcommaaccent -55
+KPX Aring O -45
+KPX Aring Oacute -45
+KPX Aring Ocircumflex -45
+KPX Aring Odieresis -45
+KPX Aring Ograve -45
+KPX Aring Ohungarumlaut -45
+KPX Aring Omacron -45
+KPX Aring Oslash -45
+KPX Aring Otilde -45
+KPX Aring Q -45
+KPX Aring T -95
+KPX Aring Tcaron -95
+KPX Aring Tcommaaccent -95
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -145
+KPX Aring W -130
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring p -25
+KPX Aring quoteright -74
+KPX Aring u -50
+KPX Aring uacute -50
+KPX Aring ucircumflex -50
+KPX Aring udieresis -50
+KPX Aring ugrave -50
+KPX Aring uhungarumlaut -50
+KPX Aring umacron -50
+KPX Aring uogonek -50
+KPX Aring uring -50
+KPX Aring v -100
+KPX Aring w -90
+KPX Aring y -74
+KPX Aring yacute -74
+KPX Aring ydieresis -74
+KPX Atilde C -55
+KPX Atilde Cacute -55
+KPX Atilde Ccaron -55
+KPX Atilde Ccedilla -55
+KPX Atilde G -55
+KPX Atilde Gbreve -55
+KPX Atilde Gcommaaccent -55
+KPX Atilde O -45
+KPX Atilde Oacute -45
+KPX Atilde Ocircumflex -45
+KPX Atilde Odieresis -45
+KPX Atilde Ograve -45
+KPX Atilde Ohungarumlaut -45
+KPX Atilde Omacron -45
+KPX Atilde Oslash -45
+KPX Atilde Otilde -45
+KPX Atilde Q -45
+KPX Atilde T -95
+KPX Atilde Tcaron -95
+KPX Atilde Tcommaaccent -95
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -145
+KPX Atilde W -130
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde p -25
+KPX Atilde quoteright -74
+KPX Atilde u -50
+KPX Atilde uacute -50
+KPX Atilde ucircumflex -50
+KPX Atilde udieresis -50
+KPX Atilde ugrave -50
+KPX Atilde uhungarumlaut -50
+KPX Atilde umacron -50
+KPX Atilde uogonek -50
+KPX Atilde uring -50
+KPX Atilde v -100
+KPX Atilde w -90
+KPX Atilde y -74
+KPX Atilde yacute -74
+KPX Atilde ydieresis -74
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -35
+KPX D Aacute -35
+KPX D Abreve -35
+KPX D Acircumflex -35
+KPX D Adieresis -35
+KPX D Agrave -35
+KPX D Amacron -35
+KPX D Aogonek -35
+KPX D Aring -35
+KPX D Atilde -35
+KPX D V -40
+KPX D W -40
+KPX D Y -40
+KPX D Yacute -40
+KPX D Ydieresis -40
+KPX D period -20
+KPX Dcaron A -35
+KPX Dcaron Aacute -35
+KPX Dcaron Abreve -35
+KPX Dcaron Acircumflex -35
+KPX Dcaron Adieresis -35
+KPX Dcaron Agrave -35
+KPX Dcaron Amacron -35
+KPX Dcaron Aogonek -35
+KPX Dcaron Aring -35
+KPX Dcaron Atilde -35
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -40
+KPX Dcaron Yacute -40
+KPX Dcaron Ydieresis -40
+KPX Dcaron period -20
+KPX Dcroat A -35
+KPX Dcroat Aacute -35
+KPX Dcroat Abreve -35
+KPX Dcroat Acircumflex -35
+KPX Dcroat Adieresis -35
+KPX Dcroat Agrave -35
+KPX Dcroat Amacron -35
+KPX Dcroat Aogonek -35
+KPX Dcroat Aring -35
+KPX Dcroat Atilde -35
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -40
+KPX Dcroat Yacute -40
+KPX Dcroat Ydieresis -40
+KPX Dcroat period -20
+KPX F A -90
+KPX F Aacute -90
+KPX F Abreve -90
+KPX F Acircumflex -90
+KPX F Adieresis -90
+KPX F Agrave -90
+KPX F Amacron -90
+KPX F Aogonek -90
+KPX F Aring -90
+KPX F Atilde -90
+KPX F a -25
+KPX F aacute -25
+KPX F abreve -25
+KPX F acircumflex -25
+KPX F adieresis -25
+KPX F agrave -25
+KPX F amacron -25
+KPX F aogonek -25
+KPX F aring -25
+KPX F atilde -25
+KPX F comma -92
+KPX F e -25
+KPX F eacute -25
+KPX F ecaron -25
+KPX F ecircumflex -25
+KPX F edieresis -25
+KPX F edotaccent -25
+KPX F egrave -25
+KPX F emacron -25
+KPX F eogonek -25
+KPX F o -25
+KPX F oacute -25
+KPX F ocircumflex -25
+KPX F odieresis -25
+KPX F ograve -25
+KPX F ohungarumlaut -25
+KPX F omacron -25
+KPX F oslash -25
+KPX F otilde -25
+KPX F period -110
+KPX J A -30
+KPX J Aacute -30
+KPX J Abreve -30
+KPX J Acircumflex -30
+KPX J Adieresis -30
+KPX J Agrave -30
+KPX J Amacron -30
+KPX J Aogonek -30
+KPX J Aring -30
+KPX J Atilde -30
+KPX J a -15
+KPX J aacute -15
+KPX J abreve -15
+KPX J acircumflex -15
+KPX J adieresis -15
+KPX J agrave -15
+KPX J amacron -15
+KPX J aogonek -15
+KPX J aring -15
+KPX J atilde -15
+KPX J e -15
+KPX J eacute -15
+KPX J ecaron -15
+KPX J ecircumflex -15
+KPX J edieresis -15
+KPX J edotaccent -15
+KPX J egrave -15
+KPX J emacron -15
+KPX J eogonek -15
+KPX J o -15
+KPX J oacute -15
+KPX J ocircumflex -15
+KPX J odieresis -15
+KPX J ograve -15
+KPX J ohungarumlaut -15
+KPX J omacron -15
+KPX J oslash -15
+KPX J otilde -15
+KPX J period -20
+KPX J u -15
+KPX J uacute -15
+KPX J ucircumflex -15
+KPX J udieresis -15
+KPX J ugrave -15
+KPX J uhungarumlaut -15
+KPX J umacron -15
+KPX J uogonek -15
+KPX J uring -15
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -25
+KPX K oacute -25
+KPX K ocircumflex -25
+KPX K odieresis -25
+KPX K ograve -25
+KPX K ohungarumlaut -25
+KPX K omacron -25
+KPX K oslash -25
+KPX K otilde -25
+KPX K u -15
+KPX K uacute -15
+KPX K ucircumflex -15
+KPX K udieresis -15
+KPX K ugrave -15
+KPX K uhungarumlaut -15
+KPX K umacron -15
+KPX K uogonek -15
+KPX K uring -15
+KPX K y -45
+KPX K yacute -45
+KPX K ydieresis -45
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -25
+KPX Kcommaaccent oacute -25
+KPX Kcommaaccent ocircumflex -25
+KPX Kcommaaccent odieresis -25
+KPX Kcommaaccent ograve -25
+KPX Kcommaaccent ohungarumlaut -25
+KPX Kcommaaccent omacron -25
+KPX Kcommaaccent oslash -25
+KPX Kcommaaccent otilde -25
+KPX Kcommaaccent u -15
+KPX Kcommaaccent uacute -15
+KPX Kcommaaccent ucircumflex -15
+KPX Kcommaaccent udieresis -15
+KPX Kcommaaccent ugrave -15
+KPX Kcommaaccent uhungarumlaut -15
+KPX Kcommaaccent umacron -15
+KPX Kcommaaccent uogonek -15
+KPX Kcommaaccent uring -15
+KPX Kcommaaccent y -45
+KPX Kcommaaccent yacute -45
+KPX Kcommaaccent ydieresis -45
+KPX L T -92
+KPX L Tcaron -92
+KPX L Tcommaaccent -92
+KPX L V -92
+KPX L W -92
+KPX L Y -92
+KPX L Yacute -92
+KPX L Ydieresis -92
+KPX L quotedblright -20
+KPX L quoteright -110
+KPX L y -55
+KPX L yacute -55
+KPX L ydieresis -55
+KPX Lacute T -92
+KPX Lacute Tcaron -92
+KPX Lacute Tcommaaccent -92
+KPX Lacute V -92
+KPX Lacute W -92
+KPX Lacute Y -92
+KPX Lacute Yacute -92
+KPX Lacute Ydieresis -92
+KPX Lacute quotedblright -20
+KPX Lacute quoteright -110
+KPX Lacute y -55
+KPX Lacute yacute -55
+KPX Lacute ydieresis -55
+KPX Lcommaaccent T -92
+KPX Lcommaaccent Tcaron -92
+KPX Lcommaaccent Tcommaaccent -92
+KPX Lcommaaccent V -92
+KPX Lcommaaccent W -92
+KPX Lcommaaccent Y -92
+KPX Lcommaaccent Yacute -92
+KPX Lcommaaccent Ydieresis -92
+KPX Lcommaaccent quotedblright -20
+KPX Lcommaaccent quoteright -110
+KPX Lcommaaccent y -55
+KPX Lcommaaccent yacute -55
+KPX Lcommaaccent ydieresis -55
+KPX Lslash T -92
+KPX Lslash Tcaron -92
+KPX Lslash Tcommaaccent -92
+KPX Lslash V -92
+KPX Lslash W -92
+KPX Lslash Y -92
+KPX Lslash Yacute -92
+KPX Lslash Ydieresis -92
+KPX Lslash quotedblright -20
+KPX Lslash quoteright -110
+KPX Lslash y -55
+KPX Lslash yacute -55
+KPX Lslash ydieresis -55
+KPX N A -20
+KPX N Aacute -20
+KPX N Abreve -20
+KPX N Acircumflex -20
+KPX N Adieresis -20
+KPX N Agrave -20
+KPX N Amacron -20
+KPX N Aogonek -20
+KPX N Aring -20
+KPX N Atilde -20
+KPX Nacute A -20
+KPX Nacute Aacute -20
+KPX Nacute Abreve -20
+KPX Nacute Acircumflex -20
+KPX Nacute Adieresis -20
+KPX Nacute Agrave -20
+KPX Nacute Amacron -20
+KPX Nacute Aogonek -20
+KPX Nacute Aring -20
+KPX Nacute Atilde -20
+KPX Ncaron A -20
+KPX Ncaron Aacute -20
+KPX Ncaron Abreve -20
+KPX Ncaron Acircumflex -20
+KPX Ncaron Adieresis -20
+KPX Ncaron Agrave -20
+KPX Ncaron Amacron -20
+KPX Ncaron Aogonek -20
+KPX Ncaron Aring -20
+KPX Ncaron Atilde -20
+KPX Ncommaaccent A -20
+KPX Ncommaaccent Aacute -20
+KPX Ncommaaccent Abreve -20
+KPX Ncommaaccent Acircumflex -20
+KPX Ncommaaccent Adieresis -20
+KPX Ncommaaccent Agrave -20
+KPX Ncommaaccent Amacron -20
+KPX Ncommaaccent Aogonek -20
+KPX Ncommaaccent Aring -20
+KPX Ncommaaccent Atilde -20
+KPX Ntilde A -20
+KPX Ntilde Aacute -20
+KPX Ntilde Abreve -20
+KPX Ntilde Acircumflex -20
+KPX Ntilde Adieresis -20
+KPX Ntilde Agrave -20
+KPX Ntilde Amacron -20
+KPX Ntilde Aogonek -20
+KPX Ntilde Aring -20
+KPX Ntilde Atilde -20
+KPX O A -40
+KPX O Aacute -40
+KPX O Abreve -40
+KPX O Acircumflex -40
+KPX O Adieresis -40
+KPX O Agrave -40
+KPX O Amacron -40
+KPX O Aogonek -40
+KPX O Aring -40
+KPX O Atilde -40
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -40
+KPX Oacute Aacute -40
+KPX Oacute Abreve -40
+KPX Oacute Acircumflex -40
+KPX Oacute Adieresis -40
+KPX Oacute Agrave -40
+KPX Oacute Amacron -40
+KPX Oacute Aogonek -40
+KPX Oacute Aring -40
+KPX Oacute Atilde -40
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -40
+KPX Ocircumflex Aacute -40
+KPX Ocircumflex Abreve -40
+KPX Ocircumflex Acircumflex -40
+KPX Ocircumflex Adieresis -40
+KPX Ocircumflex Agrave -40
+KPX Ocircumflex Amacron -40
+KPX Ocircumflex Aogonek -40
+KPX Ocircumflex Aring -40
+KPX Ocircumflex Atilde -40
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -40
+KPX Odieresis Aacute -40
+KPX Odieresis Abreve -40
+KPX Odieresis Acircumflex -40
+KPX Odieresis Adieresis -40
+KPX Odieresis Agrave -40
+KPX Odieresis Amacron -40
+KPX Odieresis Aogonek -40
+KPX Odieresis Aring -40
+KPX Odieresis Atilde -40
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -40
+KPX Ograve Aacute -40
+KPX Ograve Abreve -40
+KPX Ograve Acircumflex -40
+KPX Ograve Adieresis -40
+KPX Ograve Agrave -40
+KPX Ograve Amacron -40
+KPX Ograve Aogonek -40
+KPX Ograve Aring -40
+KPX Ograve Atilde -40
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -40
+KPX Ohungarumlaut Aacute -40
+KPX Ohungarumlaut Abreve -40
+KPX Ohungarumlaut Acircumflex -40
+KPX Ohungarumlaut Adieresis -40
+KPX Ohungarumlaut Agrave -40
+KPX Ohungarumlaut Amacron -40
+KPX Ohungarumlaut Aogonek -40
+KPX Ohungarumlaut Aring -40
+KPX Ohungarumlaut Atilde -40
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -40
+KPX Omacron Aacute -40
+KPX Omacron Abreve -40
+KPX Omacron Acircumflex -40
+KPX Omacron Adieresis -40
+KPX Omacron Agrave -40
+KPX Omacron Amacron -40
+KPX Omacron Aogonek -40
+KPX Omacron Aring -40
+KPX Omacron Atilde -40
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -40
+KPX Oslash Aacute -40
+KPX Oslash Abreve -40
+KPX Oslash Acircumflex -40
+KPX Oslash Adieresis -40
+KPX Oslash Agrave -40
+KPX Oslash Amacron -40
+KPX Oslash Aogonek -40
+KPX Oslash Aring -40
+KPX Oslash Atilde -40
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -40
+KPX Otilde Aacute -40
+KPX Otilde Abreve -40
+KPX Otilde Acircumflex -40
+KPX Otilde Adieresis -40
+KPX Otilde Agrave -40
+KPX Otilde Amacron -40
+KPX Otilde Aogonek -40
+KPX Otilde Aring -40
+KPX Otilde Atilde -40
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -74
+KPX P Aacute -74
+KPX P Abreve -74
+KPX P Acircumflex -74
+KPX P Adieresis -74
+KPX P Agrave -74
+KPX P Amacron -74
+KPX P Aogonek -74
+KPX P Aring -74
+KPX P Atilde -74
+KPX P a -10
+KPX P aacute -10
+KPX P abreve -10
+KPX P acircumflex -10
+KPX P adieresis -10
+KPX P agrave -10
+KPX P amacron -10
+KPX P aogonek -10
+KPX P aring -10
+KPX P atilde -10
+KPX P comma -92
+KPX P e -20
+KPX P eacute -20
+KPX P ecaron -20
+KPX P ecircumflex -20
+KPX P edieresis -20
+KPX P edotaccent -20
+KPX P egrave -20
+KPX P emacron -20
+KPX P eogonek -20
+KPX P o -20
+KPX P oacute -20
+KPX P ocircumflex -20
+KPX P odieresis -20
+KPX P ograve -20
+KPX P ohungarumlaut -20
+KPX P omacron -20
+KPX P oslash -20
+KPX P otilde -20
+KPX P period -110
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q period -20
+KPX R O -30
+KPX R Oacute -30
+KPX R Ocircumflex -30
+KPX R Odieresis -30
+KPX R Ograve -30
+KPX R Ohungarumlaut -30
+KPX R Omacron -30
+KPX R Oslash -30
+KPX R Otilde -30
+KPX R T -40
+KPX R Tcaron -40
+KPX R Tcommaaccent -40
+KPX R U -30
+KPX R Uacute -30
+KPX R Ucircumflex -30
+KPX R Udieresis -30
+KPX R Ugrave -30
+KPX R Uhungarumlaut -30
+KPX R Umacron -30
+KPX R Uogonek -30
+KPX R Uring -30
+KPX R V -55
+KPX R W -35
+KPX R Y -35
+KPX R Yacute -35
+KPX R Ydieresis -35
+KPX Racute O -30
+KPX Racute Oacute -30
+KPX Racute Ocircumflex -30
+KPX Racute Odieresis -30
+KPX Racute Ograve -30
+KPX Racute Ohungarumlaut -30
+KPX Racute Omacron -30
+KPX Racute Oslash -30
+KPX Racute Otilde -30
+KPX Racute T -40
+KPX Racute Tcaron -40
+KPX Racute Tcommaaccent -40
+KPX Racute U -30
+KPX Racute Uacute -30
+KPX Racute Ucircumflex -30
+KPX Racute Udieresis -30
+KPX Racute Ugrave -30
+KPX Racute Uhungarumlaut -30
+KPX Racute Umacron -30
+KPX Racute Uogonek -30
+KPX Racute Uring -30
+KPX Racute V -55
+KPX Racute W -35
+KPX Racute Y -35
+KPX Racute Yacute -35
+KPX Racute Ydieresis -35
+KPX Rcaron O -30
+KPX Rcaron Oacute -30
+KPX Rcaron Ocircumflex -30
+KPX Rcaron Odieresis -30
+KPX Rcaron Ograve -30
+KPX Rcaron Ohungarumlaut -30
+KPX Rcaron Omacron -30
+KPX Rcaron Oslash -30
+KPX Rcaron Otilde -30
+KPX Rcaron T -40
+KPX Rcaron Tcaron -40
+KPX Rcaron Tcommaaccent -40
+KPX Rcaron U -30
+KPX Rcaron Uacute -30
+KPX Rcaron Ucircumflex -30
+KPX Rcaron Udieresis -30
+KPX Rcaron Ugrave -30
+KPX Rcaron Uhungarumlaut -30
+KPX Rcaron Umacron -30
+KPX Rcaron Uogonek -30
+KPX Rcaron Uring -30
+KPX Rcaron V -55
+KPX Rcaron W -35
+KPX Rcaron Y -35
+KPX Rcaron Yacute -35
+KPX Rcaron Ydieresis -35
+KPX Rcommaaccent O -30
+KPX Rcommaaccent Oacute -30
+KPX Rcommaaccent Ocircumflex -30
+KPX Rcommaaccent Odieresis -30
+KPX Rcommaaccent Ograve -30
+KPX Rcommaaccent Ohungarumlaut -30
+KPX Rcommaaccent Omacron -30
+KPX Rcommaaccent Oslash -30
+KPX Rcommaaccent Otilde -30
+KPX Rcommaaccent T -40
+KPX Rcommaaccent Tcaron -40
+KPX Rcommaaccent Tcommaaccent -40
+KPX Rcommaaccent U -30
+KPX Rcommaaccent Uacute -30
+KPX Rcommaaccent Ucircumflex -30
+KPX Rcommaaccent Udieresis -30
+KPX Rcommaaccent Ugrave -30
+KPX Rcommaaccent Uhungarumlaut -30
+KPX Rcommaaccent Umacron -30
+KPX Rcommaaccent Uogonek -30
+KPX Rcommaaccent Uring -30
+KPX Rcommaaccent V -55
+KPX Rcommaaccent W -35
+KPX Rcommaaccent Y -35
+KPX Rcommaaccent Yacute -35
+KPX Rcommaaccent Ydieresis -35
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -52
+KPX T acircumflex -52
+KPX T adieresis -52
+KPX T agrave -52
+KPX T amacron -52
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -52
+KPX T colon -74
+KPX T comma -74
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -92
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -92
+KPX T i -18
+KPX T iacute -18
+KPX T iogonek -18
+KPX T o -92
+KPX T oacute -92
+KPX T ocircumflex -92
+KPX T odieresis -92
+KPX T ograve -92
+KPX T ohungarumlaut -92
+KPX T omacron -92
+KPX T oslash -92
+KPX T otilde -92
+KPX T period -90
+KPX T r -74
+KPX T racute -74
+KPX T rcaron -74
+KPX T rcommaaccent -74
+KPX T semicolon -74
+KPX T u -92
+KPX T uacute -92
+KPX T ucircumflex -92
+KPX T udieresis -92
+KPX T ugrave -92
+KPX T uhungarumlaut -92
+KPX T umacron -92
+KPX T uogonek -92
+KPX T uring -92
+KPX T w -74
+KPX T y -34
+KPX T yacute -34
+KPX T ydieresis -34
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -52
+KPX Tcaron acircumflex -52
+KPX Tcaron adieresis -52
+KPX Tcaron agrave -52
+KPX Tcaron amacron -52
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -52
+KPX Tcaron colon -74
+KPX Tcaron comma -74
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -92
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -92
+KPX Tcaron i -18
+KPX Tcaron iacute -18
+KPX Tcaron iogonek -18
+KPX Tcaron o -92
+KPX Tcaron oacute -92
+KPX Tcaron ocircumflex -92
+KPX Tcaron odieresis -92
+KPX Tcaron ograve -92
+KPX Tcaron ohungarumlaut -92
+KPX Tcaron omacron -92
+KPX Tcaron oslash -92
+KPX Tcaron otilde -92
+KPX Tcaron period -90
+KPX Tcaron r -74
+KPX Tcaron racute -74
+KPX Tcaron rcaron -74
+KPX Tcaron rcommaaccent -74
+KPX Tcaron semicolon -74
+KPX Tcaron u -92
+KPX Tcaron uacute -92
+KPX Tcaron ucircumflex -92
+KPX Tcaron udieresis -92
+KPX Tcaron ugrave -92
+KPX Tcaron uhungarumlaut -92
+KPX Tcaron umacron -92
+KPX Tcaron uogonek -92
+KPX Tcaron uring -92
+KPX Tcaron w -74
+KPX Tcaron y -34
+KPX Tcaron yacute -34
+KPX Tcaron ydieresis -34
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -52
+KPX Tcommaaccent acircumflex -52
+KPX Tcommaaccent adieresis -52
+KPX Tcommaaccent agrave -52
+KPX Tcommaaccent amacron -52
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -52
+KPX Tcommaaccent colon -74
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -92
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -18
+KPX Tcommaaccent iacute -18
+KPX Tcommaaccent iogonek -18
+KPX Tcommaaccent o -92
+KPX Tcommaaccent oacute -92
+KPX Tcommaaccent ocircumflex -92
+KPX Tcommaaccent odieresis -92
+KPX Tcommaaccent ograve -92
+KPX Tcommaaccent ohungarumlaut -92
+KPX Tcommaaccent omacron -92
+KPX Tcommaaccent oslash -92
+KPX Tcommaaccent otilde -92
+KPX Tcommaaccent period -90
+KPX Tcommaaccent r -74
+KPX Tcommaaccent racute -74
+KPX Tcommaaccent rcaron -74
+KPX Tcommaaccent rcommaaccent -74
+KPX Tcommaaccent semicolon -74
+KPX Tcommaaccent u -92
+KPX Tcommaaccent uacute -92
+KPX Tcommaaccent ucircumflex -92
+KPX Tcommaaccent udieresis -92
+KPX Tcommaaccent ugrave -92
+KPX Tcommaaccent uhungarumlaut -92
+KPX Tcommaaccent umacron -92
+KPX Tcommaaccent uogonek -92
+KPX Tcommaaccent uring -92
+KPX Tcommaaccent w -74
+KPX Tcommaaccent y -34
+KPX Tcommaaccent yacute -34
+KPX Tcommaaccent ydieresis -34
+KPX U A -60
+KPX U Aacute -60
+KPX U Abreve -60
+KPX U Acircumflex -60
+KPX U Adieresis -60
+KPX U Agrave -60
+KPX U Amacron -60
+KPX U Aogonek -60
+KPX U Aring -60
+KPX U Atilde -60
+KPX U comma -50
+KPX U period -50
+KPX Uacute A -60
+KPX Uacute Aacute -60
+KPX Uacute Abreve -60
+KPX Uacute Acircumflex -60
+KPX Uacute Adieresis -60
+KPX Uacute Agrave -60
+KPX Uacute Amacron -60
+KPX Uacute Aogonek -60
+KPX Uacute Aring -60
+KPX Uacute Atilde -60
+KPX Uacute comma -50
+KPX Uacute period -50
+KPX Ucircumflex A -60
+KPX Ucircumflex Aacute -60
+KPX Ucircumflex Abreve -60
+KPX Ucircumflex Acircumflex -60
+KPX Ucircumflex Adieresis -60
+KPX Ucircumflex Agrave -60
+KPX Ucircumflex Amacron -60
+KPX Ucircumflex Aogonek -60
+KPX Ucircumflex Aring -60
+KPX Ucircumflex Atilde -60
+KPX Ucircumflex comma -50
+KPX Ucircumflex period -50
+KPX Udieresis A -60
+KPX Udieresis Aacute -60
+KPX Udieresis Abreve -60
+KPX Udieresis Acircumflex -60
+KPX Udieresis Adieresis -60
+KPX Udieresis Agrave -60
+KPX Udieresis Amacron -60
+KPX Udieresis Aogonek -60
+KPX Udieresis Aring -60
+KPX Udieresis Atilde -60
+KPX Udieresis comma -50
+KPX Udieresis period -50
+KPX Ugrave A -60
+KPX Ugrave Aacute -60
+KPX Ugrave Abreve -60
+KPX Ugrave Acircumflex -60
+KPX Ugrave Adieresis -60
+KPX Ugrave Agrave -60
+KPX Ugrave Amacron -60
+KPX Ugrave Aogonek -60
+KPX Ugrave Aring -60
+KPX Ugrave Atilde -60
+KPX Ugrave comma -50
+KPX Ugrave period -50
+KPX Uhungarumlaut A -60
+KPX Uhungarumlaut Aacute -60
+KPX Uhungarumlaut Abreve -60
+KPX Uhungarumlaut Acircumflex -60
+KPX Uhungarumlaut Adieresis -60
+KPX Uhungarumlaut Agrave -60
+KPX Uhungarumlaut Amacron -60
+KPX Uhungarumlaut Aogonek -60
+KPX Uhungarumlaut Aring -60
+KPX Uhungarumlaut Atilde -60
+KPX Uhungarumlaut comma -50
+KPX Uhungarumlaut period -50
+KPX Umacron A -60
+KPX Umacron Aacute -60
+KPX Umacron Abreve -60
+KPX Umacron Acircumflex -60
+KPX Umacron Adieresis -60
+KPX Umacron Agrave -60
+KPX Umacron Amacron -60
+KPX Umacron Aogonek -60
+KPX Umacron Aring -60
+KPX Umacron Atilde -60
+KPX Umacron comma -50
+KPX Umacron period -50
+KPX Uogonek A -60
+KPX Uogonek Aacute -60
+KPX Uogonek Abreve -60
+KPX Uogonek Acircumflex -60
+KPX Uogonek Adieresis -60
+KPX Uogonek Agrave -60
+KPX Uogonek Amacron -60
+KPX Uogonek Aogonek -60
+KPX Uogonek Aring -60
+KPX Uogonek Atilde -60
+KPX Uogonek comma -50
+KPX Uogonek period -50
+KPX Uring A -60
+KPX Uring Aacute -60
+KPX Uring Abreve -60
+KPX Uring Acircumflex -60
+KPX Uring Adieresis -60
+KPX Uring Agrave -60
+KPX Uring Amacron -60
+KPX Uring Aogonek -60
+KPX Uring Aring -60
+KPX Uring Atilde -60
+KPX Uring comma -50
+KPX Uring period -50
+KPX V A -135
+KPX V Aacute -135
+KPX V Abreve -135
+KPX V Acircumflex -135
+KPX V Adieresis -135
+KPX V Agrave -135
+KPX V Amacron -135
+KPX V Aogonek -135
+KPX V Aring -135
+KPX V Atilde -135
+KPX V G -30
+KPX V Gbreve -30
+KPX V Gcommaaccent -30
+KPX V O -45
+KPX V Oacute -45
+KPX V Ocircumflex -45
+KPX V Odieresis -45
+KPX V Ograve -45
+KPX V Ohungarumlaut -45
+KPX V Omacron -45
+KPX V Oslash -45
+KPX V Otilde -45
+KPX V a -92
+KPX V aacute -92
+KPX V abreve -92
+KPX V acircumflex -92
+KPX V adieresis -92
+KPX V agrave -92
+KPX V amacron -92
+KPX V aogonek -92
+KPX V aring -92
+KPX V atilde -92
+KPX V colon -92
+KPX V comma -129
+KPX V e -100
+KPX V eacute -100
+KPX V ecaron -100
+KPX V ecircumflex -100
+KPX V edieresis -100
+KPX V edotaccent -100
+KPX V egrave -100
+KPX V emacron -100
+KPX V eogonek -100
+KPX V hyphen -74
+KPX V i -37
+KPX V iacute -37
+KPX V icircumflex -37
+KPX V idieresis -37
+KPX V igrave -37
+KPX V imacron -37
+KPX V iogonek -37
+KPX V o -100
+KPX V oacute -100
+KPX V ocircumflex -100
+KPX V odieresis -100
+KPX V ograve -100
+KPX V ohungarumlaut -100
+KPX V omacron -100
+KPX V oslash -100
+KPX V otilde -100
+KPX V period -145
+KPX V semicolon -92
+KPX V u -92
+KPX V uacute -92
+KPX V ucircumflex -92
+KPX V udieresis -92
+KPX V ugrave -92
+KPX V uhungarumlaut -92
+KPX V umacron -92
+KPX V uogonek -92
+KPX V uring -92
+KPX W A -120
+KPX W Aacute -120
+KPX W Abreve -120
+KPX W Acircumflex -120
+KPX W Adieresis -120
+KPX W Agrave -120
+KPX W Amacron -120
+KPX W Aogonek -120
+KPX W Aring -120
+KPX W Atilde -120
+KPX W O -10
+KPX W Oacute -10
+KPX W Ocircumflex -10
+KPX W Odieresis -10
+KPX W Ograve -10
+KPX W Ohungarumlaut -10
+KPX W Omacron -10
+KPX W Oslash -10
+KPX W Otilde -10
+KPX W a -65
+KPX W aacute -65
+KPX W abreve -65
+KPX W acircumflex -65
+KPX W adieresis -65
+KPX W agrave -65
+KPX W amacron -65
+KPX W aogonek -65
+KPX W aring -65
+KPX W atilde -65
+KPX W colon -55
+KPX W comma -92
+KPX W e -65
+KPX W eacute -65
+KPX W ecaron -65
+KPX W ecircumflex -65
+KPX W edieresis -65
+KPX W edotaccent -65
+KPX W egrave -65
+KPX W emacron -65
+KPX W eogonek -65
+KPX W hyphen -37
+KPX W i -18
+KPX W iacute -18
+KPX W iogonek -18
+KPX W o -75
+KPX W oacute -75
+KPX W ocircumflex -75
+KPX W odieresis -75
+KPX W ograve -75
+KPX W ohungarumlaut -75
+KPX W omacron -75
+KPX W oslash -75
+KPX W otilde -75
+KPX W period -92
+KPX W semicolon -55
+KPX W u -50
+KPX W uacute -50
+KPX W ucircumflex -50
+KPX W udieresis -50
+KPX W ugrave -50
+KPX W uhungarumlaut -50
+KPX W umacron -50
+KPX W uogonek -50
+KPX W uring -50
+KPX W y -60
+KPX W yacute -60
+KPX W ydieresis -60
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -35
+KPX Y Oacute -35
+KPX Y Ocircumflex -35
+KPX Y Odieresis -35
+KPX Y Ograve -35
+KPX Y Ohungarumlaut -35
+KPX Y Omacron -35
+KPX Y Oslash -35
+KPX Y Otilde -35
+KPX Y a -85
+KPX Y aacute -85
+KPX Y abreve -85
+KPX Y acircumflex -85
+KPX Y adieresis -85
+KPX Y agrave -85
+KPX Y amacron -85
+KPX Y aogonek -85
+KPX Y aring -85
+KPX Y atilde -85
+KPX Y colon -92
+KPX Y comma -92
+KPX Y e -111
+KPX Y eacute -111
+KPX Y ecaron -111
+KPX Y ecircumflex -111
+KPX Y edieresis -71
+KPX Y edotaccent -111
+KPX Y egrave -71
+KPX Y emacron -71
+KPX Y eogonek -111
+KPX Y hyphen -92
+KPX Y i -37
+KPX Y iacute -37
+KPX Y iogonek -37
+KPX Y o -111
+KPX Y oacute -111
+KPX Y ocircumflex -111
+KPX Y odieresis -111
+KPX Y ograve -111
+KPX Y ohungarumlaut -111
+KPX Y omacron -111
+KPX Y oslash -111
+KPX Y otilde -111
+KPX Y period -92
+KPX Y semicolon -92
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -35
+KPX Yacute Oacute -35
+KPX Yacute Ocircumflex -35
+KPX Yacute Odieresis -35
+KPX Yacute Ograve -35
+KPX Yacute Ohungarumlaut -35
+KPX Yacute Omacron -35
+KPX Yacute Oslash -35
+KPX Yacute Otilde -35
+KPX Yacute a -85
+KPX Yacute aacute -85
+KPX Yacute abreve -85
+KPX Yacute acircumflex -85
+KPX Yacute adieresis -85
+KPX Yacute agrave -85
+KPX Yacute amacron -85
+KPX Yacute aogonek -85
+KPX Yacute aring -85
+KPX Yacute atilde -85
+KPX Yacute colon -92
+KPX Yacute comma -92
+KPX Yacute e -111
+KPX Yacute eacute -111
+KPX Yacute ecaron -111
+KPX Yacute ecircumflex -111
+KPX Yacute edieresis -71
+KPX Yacute edotaccent -111
+KPX Yacute egrave -71
+KPX Yacute emacron -71
+KPX Yacute eogonek -111
+KPX Yacute hyphen -92
+KPX Yacute i -37
+KPX Yacute iacute -37
+KPX Yacute iogonek -37
+KPX Yacute o -111
+KPX Yacute oacute -111
+KPX Yacute ocircumflex -111
+KPX Yacute odieresis -111
+KPX Yacute ograve -111
+KPX Yacute ohungarumlaut -111
+KPX Yacute omacron -111
+KPX Yacute oslash -111
+KPX Yacute otilde -111
+KPX Yacute period -92
+KPX Yacute semicolon -92
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -35
+KPX Ydieresis Oacute -35
+KPX Ydieresis Ocircumflex -35
+KPX Ydieresis Odieresis -35
+KPX Ydieresis Ograve -35
+KPX Ydieresis Ohungarumlaut -35
+KPX Ydieresis Omacron -35
+KPX Ydieresis Oslash -35
+KPX Ydieresis Otilde -35
+KPX Ydieresis a -85
+KPX Ydieresis aacute -85
+KPX Ydieresis abreve -85
+KPX Ydieresis acircumflex -85
+KPX Ydieresis adieresis -85
+KPX Ydieresis agrave -85
+KPX Ydieresis amacron -85
+KPX Ydieresis aogonek -85
+KPX Ydieresis aring -85
+KPX Ydieresis atilde -85
+KPX Ydieresis colon -92
+KPX Ydieresis comma -92
+KPX Ydieresis e -111
+KPX Ydieresis eacute -111
+KPX Ydieresis ecaron -111
+KPX Ydieresis ecircumflex -111
+KPX Ydieresis edieresis -71
+KPX Ydieresis edotaccent -111
+KPX Ydieresis egrave -71
+KPX Ydieresis emacron -71
+KPX Ydieresis eogonek -111
+KPX Ydieresis hyphen -92
+KPX Ydieresis i -37
+KPX Ydieresis iacute -37
+KPX Ydieresis iogonek -37
+KPX Ydieresis o -111
+KPX Ydieresis oacute -111
+KPX Ydieresis ocircumflex -111
+KPX Ydieresis odieresis -111
+KPX Ydieresis ograve -111
+KPX Ydieresis ohungarumlaut -111
+KPX Ydieresis omacron -111
+KPX Ydieresis oslash -111
+KPX Ydieresis otilde -111
+KPX Ydieresis period -92
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX a v -25
+KPX aacute v -25
+KPX abreve v -25
+KPX acircumflex v -25
+KPX adieresis v -25
+KPX agrave v -25
+KPX amacron v -25
+KPX aogonek v -25
+KPX aring v -25
+KPX atilde v -25
+KPX b b -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -15
+KPX comma quotedblright -45
+KPX comma quoteright -55
+KPX d w -15
+KPX dcroat w -15
+KPX e v -15
+KPX eacute v -15
+KPX ecaron v -15
+KPX ecircumflex v -15
+KPX edieresis v -15
+KPX edotaccent v -15
+KPX egrave v -15
+KPX emacron v -15
+KPX eogonek v -15
+KPX f comma -15
+KPX f dotlessi -35
+KPX f i -25
+KPX f o -25
+KPX f oacute -25
+KPX f ocircumflex -25
+KPX f odieresis -25
+KPX f ograve -25
+KPX f ohungarumlaut -25
+KPX f omacron -25
+KPX f oslash -25
+KPX f otilde -25
+KPX f period -15
+KPX f quotedblright 50
+KPX f quoteright 55
+KPX g period -15
+KPX gbreve period -15
+KPX gcommaaccent period -15
+KPX h y -15
+KPX h yacute -15
+KPX h ydieresis -15
+KPX i v -10
+KPX iacute v -10
+KPX icircumflex v -10
+KPX idieresis v -10
+KPX igrave v -10
+KPX imacron v -10
+KPX iogonek v -10
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX k y -15
+KPX k yacute -15
+KPX k ydieresis -15
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX kcommaaccent y -15
+KPX kcommaaccent yacute -15
+KPX kcommaaccent ydieresis -15
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o v -10
+KPX o w -10
+KPX oacute v -10
+KPX oacute w -10
+KPX ocircumflex v -10
+KPX ocircumflex w -10
+KPX odieresis v -10
+KPX odieresis w -10
+KPX ograve v -10
+KPX ograve w -10
+KPX ohungarumlaut v -10
+KPX ohungarumlaut w -10
+KPX omacron v -10
+KPX omacron w -10
+KPX oslash v -10
+KPX oslash w -10
+KPX otilde v -10
+KPX otilde w -10
+KPX period quotedblright -55
+KPX period quoteright -55
+KPX quotedblleft A -10
+KPX quotedblleft Aacute -10
+KPX quotedblleft Abreve -10
+KPX quotedblleft Acircumflex -10
+KPX quotedblleft Adieresis -10
+KPX quotedblleft Agrave -10
+KPX quotedblleft Amacron -10
+KPX quotedblleft Aogonek -10
+KPX quotedblleft Aring -10
+KPX quotedblleft Atilde -10
+KPX quoteleft A -10
+KPX quoteleft Aacute -10
+KPX quoteleft Abreve -10
+KPX quoteleft Acircumflex -10
+KPX quoteleft Adieresis -10
+KPX quoteleft Agrave -10
+KPX quoteleft Amacron -10
+KPX quoteleft Aogonek -10
+KPX quoteleft Aring -10
+KPX quoteleft Atilde -10
+KPX quoteleft quoteleft -63
+KPX quoteright d -20
+KPX quoteright dcroat -20
+KPX quoteright quoteright -63
+KPX quoteright r -20
+KPX quoteright racute -20
+KPX quoteright rcaron -20
+KPX quoteright rcommaaccent -20
+KPX quoteright s -37
+KPX quoteright sacute -37
+KPX quoteright scaron -37
+KPX quoteright scedilla -37
+KPX quoteright scommaaccent -37
+KPX quoteright space -74
+KPX quoteright v -20
+KPX r c -18
+KPX r cacute -18
+KPX r ccaron -18
+KPX r ccedilla -18
+KPX r comma -92
+KPX r e -18
+KPX r eacute -18
+KPX r ecaron -18
+KPX r ecircumflex -18
+KPX r edieresis -18
+KPX r edotaccent -18
+KPX r egrave -18
+KPX r emacron -18
+KPX r eogonek -18
+KPX r g -10
+KPX r gbreve -10
+KPX r gcommaaccent -10
+KPX r hyphen -37
+KPX r n -15
+KPX r nacute -15
+KPX r ncaron -15
+KPX r ncommaaccent -15
+KPX r ntilde -15
+KPX r o -18
+KPX r oacute -18
+KPX r ocircumflex -18
+KPX r odieresis -18
+KPX r ograve -18
+KPX r ohungarumlaut -18
+KPX r omacron -18
+KPX r oslash -18
+KPX r otilde -18
+KPX r p -10
+KPX r period -100
+KPX r q -18
+KPX r v -10
+KPX racute c -18
+KPX racute cacute -18
+KPX racute ccaron -18
+KPX racute ccedilla -18
+KPX racute comma -92
+KPX racute e -18
+KPX racute eacute -18
+KPX racute ecaron -18
+KPX racute ecircumflex -18
+KPX racute edieresis -18
+KPX racute edotaccent -18
+KPX racute egrave -18
+KPX racute emacron -18
+KPX racute eogonek -18
+KPX racute g -10
+KPX racute gbreve -10
+KPX racute gcommaaccent -10
+KPX racute hyphen -37
+KPX racute n -15
+KPX racute nacute -15
+KPX racute ncaron -15
+KPX racute ncommaaccent -15
+KPX racute ntilde -15
+KPX racute o -18
+KPX racute oacute -18
+KPX racute ocircumflex -18
+KPX racute odieresis -18
+KPX racute ograve -18
+KPX racute ohungarumlaut -18
+KPX racute omacron -18
+KPX racute oslash -18
+KPX racute otilde -18
+KPX racute p -10
+KPX racute period -100
+KPX racute q -18
+KPX racute v -10
+KPX rcaron c -18
+KPX rcaron cacute -18
+KPX rcaron ccaron -18
+KPX rcaron ccedilla -18
+KPX rcaron comma -92
+KPX rcaron e -18
+KPX rcaron eacute -18
+KPX rcaron ecaron -18
+KPX rcaron ecircumflex -18
+KPX rcaron edieresis -18
+KPX rcaron edotaccent -18
+KPX rcaron egrave -18
+KPX rcaron emacron -18
+KPX rcaron eogonek -18
+KPX rcaron g -10
+KPX rcaron gbreve -10
+KPX rcaron gcommaaccent -10
+KPX rcaron hyphen -37
+KPX rcaron n -15
+KPX rcaron nacute -15
+KPX rcaron ncaron -15
+KPX rcaron ncommaaccent -15
+KPX rcaron ntilde -15
+KPX rcaron o -18
+KPX rcaron oacute -18
+KPX rcaron ocircumflex -18
+KPX rcaron odieresis -18
+KPX rcaron ograve -18
+KPX rcaron ohungarumlaut -18
+KPX rcaron omacron -18
+KPX rcaron oslash -18
+KPX rcaron otilde -18
+KPX rcaron p -10
+KPX rcaron period -100
+KPX rcaron q -18
+KPX rcaron v -10
+KPX rcommaaccent c -18
+KPX rcommaaccent cacute -18
+KPX rcommaaccent ccaron -18
+KPX rcommaaccent ccedilla -18
+KPX rcommaaccent comma -92
+KPX rcommaaccent e -18
+KPX rcommaaccent eacute -18
+KPX rcommaaccent ecaron -18
+KPX rcommaaccent ecircumflex -18
+KPX rcommaaccent edieresis -18
+KPX rcommaaccent edotaccent -18
+KPX rcommaaccent egrave -18
+KPX rcommaaccent emacron -18
+KPX rcommaaccent eogonek -18
+KPX rcommaaccent g -10
+KPX rcommaaccent gbreve -10
+KPX rcommaaccent gcommaaccent -10
+KPX rcommaaccent hyphen -37
+KPX rcommaaccent n -15
+KPX rcommaaccent nacute -15
+KPX rcommaaccent ncaron -15
+KPX rcommaaccent ncommaaccent -15
+KPX rcommaaccent ntilde -15
+KPX rcommaaccent o -18
+KPX rcommaaccent oacute -18
+KPX rcommaaccent ocircumflex -18
+KPX rcommaaccent odieresis -18
+KPX rcommaaccent ograve -18
+KPX rcommaaccent ohungarumlaut -18
+KPX rcommaaccent omacron -18
+KPX rcommaaccent oslash -18
+KPX rcommaaccent otilde -18
+KPX rcommaaccent p -10
+KPX rcommaaccent period -100
+KPX rcommaaccent q -18
+KPX rcommaaccent v -10
+KPX space A -55
+KPX space Aacute -55
+KPX space Abreve -55
+KPX space Acircumflex -55
+KPX space Adieresis -55
+KPX space Agrave -55
+KPX space Amacron -55
+KPX space Aogonek -55
+KPX space Aring -55
+KPX space Atilde -55
+KPX space T -30
+KPX space Tcaron -30
+KPX space Tcommaaccent -30
+KPX space V -45
+KPX space W -30
+KPX space Y -55
+KPX space Yacute -55
+KPX space Ydieresis -55
+KPX v a -10
+KPX v aacute -10
+KPX v abreve -10
+KPX v acircumflex -10
+KPX v adieresis -10
+KPX v agrave -10
+KPX v amacron -10
+KPX v aogonek -10
+KPX v aring -10
+KPX v atilde -10
+KPX v comma -55
+KPX v e -10
+KPX v eacute -10
+KPX v ecaron -10
+KPX v ecircumflex -10
+KPX v edieresis -10
+KPX v edotaccent -10
+KPX v egrave -10
+KPX v emacron -10
+KPX v eogonek -10
+KPX v o -10
+KPX v oacute -10
+KPX v ocircumflex -10
+KPX v odieresis -10
+KPX v ograve -10
+KPX v ohungarumlaut -10
+KPX v omacron -10
+KPX v oslash -10
+KPX v otilde -10
+KPX v period -70
+KPX w comma -55
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -70
+KPX y comma -55
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -70
+KPX yacute comma -55
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -70
+KPX ydieresis comma -55
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -70
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm
new file mode 100644
index 0000000..2e4adc8
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm
@@ -0,0 +1,2385 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 13:04:06 1997
+Comment UniqueID 43066
+Comment VMusage 45874 56899
+FontName Times-BoldItalic
+FullName Times Bold Italic
+FamilyName Times
+Weight Bold
+ItalicAngle -15
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -200 -218 996 921 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 669
+XHeight 462
+Ascender 683
+Descender -217
+StdHW 42
+StdVW 121
+StartCharMetrics 315
+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 -218 154 782 ;
+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 550 298 684 ;
+C 200 ; WX 333 ; N dieresis ; B 55 550 402 684 ;
+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 15 -183 244 34 ;
+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 -7 -9 307 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 389 ; N Idieresis ; B -32 0 450 862 ;
+C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ;
+C -1 ; WX 500 ; N abreve ; B -21 -14 471 678 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 15 -9 610 697 ;
+C -1 ; WX 444 ; N ecaron ; B 5 -13 467 690 ;
+C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ;
+C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ;
+C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ;
+C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ;
+C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ;
+C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ;
+C -1 ; WX 389 ; N scommaaccent ; B -19 -218 333 462 ;
+C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ;
+C -1 ; WX 722 ; N Uring ; B 67 -18 744 921 ;
+C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ;
+C -1 ; WX 500 ; N aogonek ; B -21 -183 455 462 ;
+C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ;
+C -1 ; WX 556 ; N uogonek ; B 15 -183 492 462 ;
+C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ;
+C -1 ; WX 722 ; N Dcroat ; B -31 0 700 669 ;
+C -1 ; WX 250 ; N commaaccent ; B -36 -218 131 -50 ;
+C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ;
+C -1 ; WX 667 ; N Emacron ; B -27 0 653 830 ;
+C -1 ; WX 444 ; N ccaron ; B -5 -13 467 690 ;
+C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B -27 -218 748 669 ;
+C -1 ; WX 278 ; N lacute ; B 2 -9 392 904 ;
+C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 50 -218 650 669 ;
+C -1 ; WX 667 ; N Cacute ; B 32 -18 677 904 ;
+C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ;
+C -1 ; WX 667 ; N Edotaccent ; B -27 0 653 862 ;
+C -1 ; WX 389 ; N scaron ; B -19 -13 424 690 ;
+C -1 ; WX 389 ; N scedilla ; B -19 -218 333 462 ;
+C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 667 ; N Rcaron ; B -29 0 623 897 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 21 -218 706 685 ;
+C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ;
+C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ;
+C -1 ; WX 667 ; N Amacron ; B -67 0 593 830 ;
+C -1 ; WX 389 ; N rcaron ; B -21 0 424 690 ;
+C -1 ; WX 444 ; N ccedilla ; B -5 -218 392 462 ;
+C -1 ; WX 611 ; N Zdotaccent ; B -11 0 590 862 ;
+C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ;
+C -1 ; WX 722 ; N Omacron ; B 27 -18 691 830 ;
+C -1 ; WX 667 ; N Racute ; B -29 0 623 904 ;
+C -1 ; WX 556 ; N Sacute ; B 2 -18 531 904 ;
+C -1 ; WX 608 ; N dcaron ; B -21 -13 675 708 ;
+C -1 ; WX 722 ; N Umacron ; B 67 -18 744 830 ;
+C -1 ; WX 556 ; N uring ; B 15 -9 492 729 ;
+C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ;
+C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ;
+C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ;
+C -1 ; WX 667 ; N Abreve ; B -67 0 593 885 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ;
+C -1 ; WX 611 ; N Tcaron ; B 50 0 650 897 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 444 ; N ydieresis ; B -94 -205 443 655 ;
+C -1 ; WX 722 ; N Nacute ; B -27 -15 748 904 ;
+C -1 ; WX 278 ; N icircumflex ; B -3 -9 324 690 ;
+C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ;
+C -1 ; WX 500 ; N adieresis ; B -21 -14 476 655 ;
+C -1 ; WX 444 ; N edieresis ; B 5 -13 448 655 ;
+C -1 ; WX 444 ; N cacute ; B -5 -13 435 697 ;
+C -1 ; WX 556 ; N nacute ; B -6 -9 493 697 ;
+C -1 ; WX 556 ; N umacron ; B 15 -9 492 623 ;
+C -1 ; WX 722 ; N Ncaron ; B -27 -15 748 897 ;
+C -1 ; WX 389 ; N Iacute ; B -32 0 432 904 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
+C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ;
+C -1 ; WX 722 ; N Gbreve ; B 21 -18 706 885 ;
+C -1 ; WX 389 ; N Idotaccent ; B -32 0 406 862 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ;
+C -1 ; WX 389 ; N racute ; B -21 0 407 697 ;
+C -1 ; WX 500 ; N omacron ; B -3 -13 462 623 ;
+C -1 ; WX 611 ; N Zacute ; B -11 0 590 904 ;
+C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ;
+C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ;
+C -1 ; WX 278 ; N lcommaaccent ; B -42 -218 290 699 ;
+C -1 ; WX 366 ; N tcaron ; B -11 -9 434 754 ;
+C -1 ; WX 444 ; N eogonek ; B 5 -183 398 462 ;
+C -1 ; WX 722 ; N Uogonek ; B 67 -183 744 669 ;
+C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ;
+C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ;
+C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ;
+C -1 ; WX 389 ; N zacute ; B -43 -78 407 697 ;
+C -1 ; WX 278 ; N iogonek ; B -20 -183 263 684 ;
+C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ;
+C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ;
+C -1 ; WX 500 ; N amacron ; B -21 -14 467 623 ;
+C -1 ; WX 389 ; N sacute ; B -19 -13 407 697 ;
+C -1 ; WX 278 ; N idieresis ; B 2 -9 364 655 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ;
+C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ;
+C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ;
+C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ;
+C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ;
+C -1 ; WX 278 ; N igrave ; B 2 -9 259 697 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B -3 -13 582 697 ;
+C -1 ; WX 667 ; N Eogonek ; B -27 -183 653 669 ;
+C -1 ; WX 500 ; N dcroat ; B -21 -13 552 699 ;
+C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ;
+C -1 ; WX 556 ; N Scedilla ; B 2 -218 526 685 ;
+C -1 ; WX 382 ; N lcaron ; B 2 -9 448 708 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B -21 -218 702 669 ;
+C -1 ; WX 611 ; N Lacute ; B -22 0 590 904 ;
+C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ;
+C -1 ; WX 444 ; N edotaccent ; B 5 -13 398 655 ;
+C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ;
+C -1 ; WX 389 ; N Imacron ; B -32 0 461 830 ;
+C -1 ; WX 611 ; N Lcaron ; B -22 0 671 718 ;
+C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ;
+C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 67 -18 744 904 ;
+C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ;
+C -1 ; WX 444 ; N emacron ; B 5 -13 439 623 ;
+C -1 ; WX 500 ; N gbreve ; B -52 -203 478 678 ;
+C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ;
+C -1 ; WX 556 ; N Scaron ; B 2 -18 553 897 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 2 -218 526 685 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 27 -18 723 904 ;
+C -1 ; WX 400 ; N degree ; B 83 397 369 683 ;
+C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ;
+C -1 ; WX 667 ; N Ccaron ; B 32 -18 677 897 ;
+C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B -46 0 685 897 ;
+C -1 ; WX 389 ; N rcommaaccent ; B -67 -218 389 462 ;
+C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ;
+C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ;
+C -1 ; WX 667 ; N Rcommaaccent ; B -29 -218 623 669 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B -22 -218 590 669 ;
+C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ;
+C -1 ; WX 667 ; N Aogonek ; B -67 -183 604 683 ;
+C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ;
+C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ;
+C -1 ; WX 389 ; N zdotaccent ; B -43 -78 368 655 ;
+C -1 ; WX 667 ; N Ecaron ; B -27 0 653 897 ;
+C -1 ; WX 389 ; N Iogonek ; B -32 -183 406 669 ;
+C -1 ; WX 500 ; N kcommaaccent ; B -23 -218 483 699 ;
+C -1 ; WX 606 ; N minus ; B 51 209 555 297 ;
+C -1 ; WX 389 ; N Icircumflex ; B -32 0 450 897 ;
+C -1 ; WX 556 ; N ncaron ; B -6 -9 523 690 ;
+C -1 ; WX 278 ; N tcommaaccent ; B -62 -218 281 594 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ;
+C -1 ; WX 500 ; N odieresis ; B -3 -13 471 655 ;
+C -1 ; WX 556 ; N udieresis ; B 15 -9 499 655 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 500 ; N gcommaaccent ; B -52 -203 478 767 ;
+C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ;
+C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ;
+C -1 ; WX 556 ; N ncommaaccent ; B -6 -218 493 462 ;
+C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ;
+C -1 ; WX 278 ; N imacron ; B 2 -9 294 623 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2038
+KPX A C -65
+KPX A Cacute -65
+KPX A Ccaron -65
+KPX A Ccedilla -65
+KPX A G -60
+KPX A Gbreve -60
+KPX A Gcommaaccent -60
+KPX A O -50
+KPX A Oacute -50
+KPX A Ocircumflex -50
+KPX A Odieresis -50
+KPX A Ograve -50
+KPX A Ohungarumlaut -50
+KPX A Omacron -50
+KPX A Oslash -50
+KPX A Otilde -50
+KPX A Q -55
+KPX A T -55
+KPX A Tcaron -55
+KPX A Tcommaaccent -55
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -95
+KPX A W -100
+KPX A Y -70
+KPX A Yacute -70
+KPX A Ydieresis -70
+KPX A quoteright -74
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -74
+KPX A w -74
+KPX A y -74
+KPX A yacute -74
+KPX A ydieresis -74
+KPX Aacute C -65
+KPX Aacute Cacute -65
+KPX Aacute Ccaron -65
+KPX Aacute Ccedilla -65
+KPX Aacute G -60
+KPX Aacute Gbreve -60
+KPX Aacute Gcommaaccent -60
+KPX Aacute O -50
+KPX Aacute Oacute -50
+KPX Aacute Ocircumflex -50
+KPX Aacute Odieresis -50
+KPX Aacute Ograve -50
+KPX Aacute Ohungarumlaut -50
+KPX Aacute Omacron -50
+KPX Aacute Oslash -50
+KPX Aacute Otilde -50
+KPX Aacute Q -55
+KPX Aacute T -55
+KPX Aacute Tcaron -55
+KPX Aacute Tcommaaccent -55
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -95
+KPX Aacute W -100
+KPX Aacute Y -70
+KPX Aacute Yacute -70
+KPX Aacute Ydieresis -70
+KPX Aacute quoteright -74
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -74
+KPX Aacute w -74
+KPX Aacute y -74
+KPX Aacute yacute -74
+KPX Aacute ydieresis -74
+KPX Abreve C -65
+KPX Abreve Cacute -65
+KPX Abreve Ccaron -65
+KPX Abreve Ccedilla -65
+KPX Abreve G -60
+KPX Abreve Gbreve -60
+KPX Abreve Gcommaaccent -60
+KPX Abreve O -50
+KPX Abreve Oacute -50
+KPX Abreve Ocircumflex -50
+KPX Abreve Odieresis -50
+KPX Abreve Ograve -50
+KPX Abreve Ohungarumlaut -50
+KPX Abreve Omacron -50
+KPX Abreve Oslash -50
+KPX Abreve Otilde -50
+KPX Abreve Q -55
+KPX Abreve T -55
+KPX Abreve Tcaron -55
+KPX Abreve Tcommaaccent -55
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -95
+KPX Abreve W -100
+KPX Abreve Y -70
+KPX Abreve Yacute -70
+KPX Abreve Ydieresis -70
+KPX Abreve quoteright -74
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -74
+KPX Abreve w -74
+KPX Abreve y -74
+KPX Abreve yacute -74
+KPX Abreve ydieresis -74
+KPX Acircumflex C -65
+KPX Acircumflex Cacute -65
+KPX Acircumflex Ccaron -65
+KPX Acircumflex Ccedilla -65
+KPX Acircumflex G -60
+KPX Acircumflex Gbreve -60
+KPX Acircumflex Gcommaaccent -60
+KPX Acircumflex O -50
+KPX Acircumflex Oacute -50
+KPX Acircumflex Ocircumflex -50
+KPX Acircumflex Odieresis -50
+KPX Acircumflex Ograve -50
+KPX Acircumflex Ohungarumlaut -50
+KPX Acircumflex Omacron -50
+KPX Acircumflex Oslash -50
+KPX Acircumflex Otilde -50
+KPX Acircumflex Q -55
+KPX Acircumflex T -55
+KPX Acircumflex Tcaron -55
+KPX Acircumflex Tcommaaccent -55
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -95
+KPX Acircumflex W -100
+KPX Acircumflex Y -70
+KPX Acircumflex Yacute -70
+KPX Acircumflex Ydieresis -70
+KPX Acircumflex quoteright -74
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -74
+KPX Acircumflex w -74
+KPX Acircumflex y -74
+KPX Acircumflex yacute -74
+KPX Acircumflex ydieresis -74
+KPX Adieresis C -65
+KPX Adieresis Cacute -65
+KPX Adieresis Ccaron -65
+KPX Adieresis Ccedilla -65
+KPX Adieresis G -60
+KPX Adieresis Gbreve -60
+KPX Adieresis Gcommaaccent -60
+KPX Adieresis O -50
+KPX Adieresis Oacute -50
+KPX Adieresis Ocircumflex -50
+KPX Adieresis Odieresis -50
+KPX Adieresis Ograve -50
+KPX Adieresis Ohungarumlaut -50
+KPX Adieresis Omacron -50
+KPX Adieresis Oslash -50
+KPX Adieresis Otilde -50
+KPX Adieresis Q -55
+KPX Adieresis T -55
+KPX Adieresis Tcaron -55
+KPX Adieresis Tcommaaccent -55
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -95
+KPX Adieresis W -100
+KPX Adieresis Y -70
+KPX Adieresis Yacute -70
+KPX Adieresis Ydieresis -70
+KPX Adieresis quoteright -74
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -74
+KPX Adieresis w -74
+KPX Adieresis y -74
+KPX Adieresis yacute -74
+KPX Adieresis ydieresis -74
+KPX Agrave C -65
+KPX Agrave Cacute -65
+KPX Agrave Ccaron -65
+KPX Agrave Ccedilla -65
+KPX Agrave G -60
+KPX Agrave Gbreve -60
+KPX Agrave Gcommaaccent -60
+KPX Agrave O -50
+KPX Agrave Oacute -50
+KPX Agrave Ocircumflex -50
+KPX Agrave Odieresis -50
+KPX Agrave Ograve -50
+KPX Agrave Ohungarumlaut -50
+KPX Agrave Omacron -50
+KPX Agrave Oslash -50
+KPX Agrave Otilde -50
+KPX Agrave Q -55
+KPX Agrave T -55
+KPX Agrave Tcaron -55
+KPX Agrave Tcommaaccent -55
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -95
+KPX Agrave W -100
+KPX Agrave Y -70
+KPX Agrave Yacute -70
+KPX Agrave Ydieresis -70
+KPX Agrave quoteright -74
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -74
+KPX Agrave w -74
+KPX Agrave y -74
+KPX Agrave yacute -74
+KPX Agrave ydieresis -74
+KPX Amacron C -65
+KPX Amacron Cacute -65
+KPX Amacron Ccaron -65
+KPX Amacron Ccedilla -65
+KPX Amacron G -60
+KPX Amacron Gbreve -60
+KPX Amacron Gcommaaccent -60
+KPX Amacron O -50
+KPX Amacron Oacute -50
+KPX Amacron Ocircumflex -50
+KPX Amacron Odieresis -50
+KPX Amacron Ograve -50
+KPX Amacron Ohungarumlaut -50
+KPX Amacron Omacron -50
+KPX Amacron Oslash -50
+KPX Amacron Otilde -50
+KPX Amacron Q -55
+KPX Amacron T -55
+KPX Amacron Tcaron -55
+KPX Amacron Tcommaaccent -55
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -95
+KPX Amacron W -100
+KPX Amacron Y -70
+KPX Amacron Yacute -70
+KPX Amacron Ydieresis -70
+KPX Amacron quoteright -74
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -74
+KPX Amacron w -74
+KPX Amacron y -74
+KPX Amacron yacute -74
+KPX Amacron ydieresis -74
+KPX Aogonek C -65
+KPX Aogonek Cacute -65
+KPX Aogonek Ccaron -65
+KPX Aogonek Ccedilla -65
+KPX Aogonek G -60
+KPX Aogonek Gbreve -60
+KPX Aogonek Gcommaaccent -60
+KPX Aogonek O -50
+KPX Aogonek Oacute -50
+KPX Aogonek Ocircumflex -50
+KPX Aogonek Odieresis -50
+KPX Aogonek Ograve -50
+KPX Aogonek Ohungarumlaut -50
+KPX Aogonek Omacron -50
+KPX Aogonek Oslash -50
+KPX Aogonek Otilde -50
+KPX Aogonek Q -55
+KPX Aogonek T -55
+KPX Aogonek Tcaron -55
+KPX Aogonek Tcommaaccent -55
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -95
+KPX Aogonek W -100
+KPX Aogonek Y -70
+KPX Aogonek Yacute -70
+KPX Aogonek Ydieresis -70
+KPX Aogonek quoteright -74
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -74
+KPX Aogonek w -74
+KPX Aogonek y -34
+KPX Aogonek yacute -34
+KPX Aogonek ydieresis -34
+KPX Aring C -65
+KPX Aring Cacute -65
+KPX Aring Ccaron -65
+KPX Aring Ccedilla -65
+KPX Aring G -60
+KPX Aring Gbreve -60
+KPX Aring Gcommaaccent -60
+KPX Aring O -50
+KPX Aring Oacute -50
+KPX Aring Ocircumflex -50
+KPX Aring Odieresis -50
+KPX Aring Ograve -50
+KPX Aring Ohungarumlaut -50
+KPX Aring Omacron -50
+KPX Aring Oslash -50
+KPX Aring Otilde -50
+KPX Aring Q -55
+KPX Aring T -55
+KPX Aring Tcaron -55
+KPX Aring Tcommaaccent -55
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -95
+KPX Aring W -100
+KPX Aring Y -70
+KPX Aring Yacute -70
+KPX Aring Ydieresis -70
+KPX Aring quoteright -74
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -74
+KPX Aring w -74
+KPX Aring y -74
+KPX Aring yacute -74
+KPX Aring ydieresis -74
+KPX Atilde C -65
+KPX Atilde Cacute -65
+KPX Atilde Ccaron -65
+KPX Atilde Ccedilla -65
+KPX Atilde G -60
+KPX Atilde Gbreve -60
+KPX Atilde Gcommaaccent -60
+KPX Atilde O -50
+KPX Atilde Oacute -50
+KPX Atilde Ocircumflex -50
+KPX Atilde Odieresis -50
+KPX Atilde Ograve -50
+KPX Atilde Ohungarumlaut -50
+KPX Atilde Omacron -50
+KPX Atilde Oslash -50
+KPX Atilde Otilde -50
+KPX Atilde Q -55
+KPX Atilde T -55
+KPX Atilde Tcaron -55
+KPX Atilde Tcommaaccent -55
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -95
+KPX Atilde W -100
+KPX Atilde Y -70
+KPX Atilde Yacute -70
+KPX Atilde Ydieresis -70
+KPX Atilde quoteright -74
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -74
+KPX Atilde w -74
+KPX Atilde y -74
+KPX Atilde yacute -74
+KPX Atilde ydieresis -74
+KPX B A -25
+KPX B Aacute -25
+KPX B Abreve -25
+KPX B Acircumflex -25
+KPX B Adieresis -25
+KPX B Agrave -25
+KPX B Amacron -25
+KPX B Aogonek -25
+KPX B Aring -25
+KPX B Atilde -25
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -25
+KPX D Aacute -25
+KPX D Abreve -25
+KPX D Acircumflex -25
+KPX D Adieresis -25
+KPX D Agrave -25
+KPX D Amacron -25
+KPX D Aogonek -25
+KPX D Aring -25
+KPX D Atilde -25
+KPX D V -50
+KPX D W -40
+KPX D Y -50
+KPX D Yacute -50
+KPX D Ydieresis -50
+KPX Dcaron A -25
+KPX Dcaron Aacute -25
+KPX Dcaron Abreve -25
+KPX Dcaron Acircumflex -25
+KPX Dcaron Adieresis -25
+KPX Dcaron Agrave -25
+KPX Dcaron Amacron -25
+KPX Dcaron Aogonek -25
+KPX Dcaron Aring -25
+KPX Dcaron Atilde -25
+KPX Dcaron V -50
+KPX Dcaron W -40
+KPX Dcaron Y -50
+KPX Dcaron Yacute -50
+KPX Dcaron Ydieresis -50
+KPX Dcroat A -25
+KPX Dcroat Aacute -25
+KPX Dcroat Abreve -25
+KPX Dcroat Acircumflex -25
+KPX Dcroat Adieresis -25
+KPX Dcroat Agrave -25
+KPX Dcroat Amacron -25
+KPX Dcroat Aogonek -25
+KPX Dcroat Aring -25
+KPX Dcroat Atilde -25
+KPX Dcroat V -50
+KPX Dcroat W -40
+KPX Dcroat Y -50
+KPX Dcroat Yacute -50
+KPX Dcroat Ydieresis -50
+KPX F A -100
+KPX F Aacute -100
+KPX F Abreve -100
+KPX F Acircumflex -100
+KPX F Adieresis -100
+KPX F Agrave -100
+KPX F Amacron -100
+KPX F Aogonek -100
+KPX F Aring -100
+KPX F Atilde -100
+KPX F a -95
+KPX F aacute -95
+KPX F abreve -95
+KPX F acircumflex -95
+KPX F adieresis -95
+KPX F agrave -95
+KPX F amacron -95
+KPX F aogonek -95
+KPX F aring -95
+KPX F atilde -95
+KPX F comma -129
+KPX F e -100
+KPX F eacute -100
+KPX F ecaron -100
+KPX F ecircumflex -100
+KPX F edieresis -100
+KPX F edotaccent -100
+KPX F egrave -100
+KPX F emacron -100
+KPX F eogonek -100
+KPX F i -40
+KPX F iacute -40
+KPX F icircumflex -40
+KPX F idieresis -40
+KPX F igrave -40
+KPX F imacron -40
+KPX F iogonek -40
+KPX F o -70
+KPX F oacute -70
+KPX F ocircumflex -70
+KPX F odieresis -70
+KPX F ograve -70
+KPX F ohungarumlaut -70
+KPX F omacron -70
+KPX F oslash -70
+KPX F otilde -70
+KPX F period -129
+KPX F r -50
+KPX F racute -50
+KPX F rcaron -50
+KPX F rcommaaccent -50
+KPX J A -25
+KPX J Aacute -25
+KPX J Abreve -25
+KPX J Acircumflex -25
+KPX J Adieresis -25
+KPX J Agrave -25
+KPX J Amacron -25
+KPX J Aogonek -25
+KPX J Aring -25
+KPX J Atilde -25
+KPX J a -40
+KPX J aacute -40
+KPX J abreve -40
+KPX J acircumflex -40
+KPX J adieresis -40
+KPX J agrave -40
+KPX J amacron -40
+KPX J aogonek -40
+KPX J aring -40
+KPX J atilde -40
+KPX J comma -10
+KPX J e -40
+KPX J eacute -40
+KPX J ecaron -40
+KPX J ecircumflex -40
+KPX J edieresis -40
+KPX J edotaccent -40
+KPX J egrave -40
+KPX J emacron -40
+KPX J eogonek -40
+KPX J o -40
+KPX J oacute -40
+KPX J ocircumflex -40
+KPX J odieresis -40
+KPX J ograve -40
+KPX J ohungarumlaut -40
+KPX J omacron -40
+KPX J oslash -40
+KPX J otilde -40
+KPX J period -10
+KPX J u -40
+KPX J uacute -40
+KPX J ucircumflex -40
+KPX J udieresis -40
+KPX J ugrave -40
+KPX J uhungarumlaut -40
+KPX J umacron -40
+KPX J uogonek -40
+KPX J uring -40
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -25
+KPX K oacute -25
+KPX K ocircumflex -25
+KPX K odieresis -25
+KPX K ograve -25
+KPX K ohungarumlaut -25
+KPX K omacron -25
+KPX K oslash -25
+KPX K otilde -25
+KPX K u -20
+KPX K uacute -20
+KPX K ucircumflex -20
+KPX K udieresis -20
+KPX K ugrave -20
+KPX K uhungarumlaut -20
+KPX K umacron -20
+KPX K uogonek -20
+KPX K uring -20
+KPX K y -20
+KPX K yacute -20
+KPX K ydieresis -20
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -25
+KPX Kcommaaccent oacute -25
+KPX Kcommaaccent ocircumflex -25
+KPX Kcommaaccent odieresis -25
+KPX Kcommaaccent ograve -25
+KPX Kcommaaccent ohungarumlaut -25
+KPX Kcommaaccent omacron -25
+KPX Kcommaaccent oslash -25
+KPX Kcommaaccent otilde -25
+KPX Kcommaaccent u -20
+KPX Kcommaaccent uacute -20
+KPX Kcommaaccent ucircumflex -20
+KPX Kcommaaccent udieresis -20
+KPX Kcommaaccent ugrave -20
+KPX Kcommaaccent uhungarumlaut -20
+KPX Kcommaaccent umacron -20
+KPX Kcommaaccent uogonek -20
+KPX Kcommaaccent uring -20
+KPX Kcommaaccent y -20
+KPX Kcommaaccent yacute -20
+KPX Kcommaaccent ydieresis -20
+KPX L T -18
+KPX L Tcaron -18
+KPX L Tcommaaccent -18
+KPX L V -37
+KPX L W -37
+KPX L Y -37
+KPX L Yacute -37
+KPX L Ydieresis -37
+KPX L quoteright -55
+KPX L y -37
+KPX L yacute -37
+KPX L ydieresis -37
+KPX Lacute T -18
+KPX Lacute Tcaron -18
+KPX Lacute Tcommaaccent -18
+KPX Lacute V -37
+KPX Lacute W -37
+KPX Lacute Y -37
+KPX Lacute Yacute -37
+KPX Lacute Ydieresis -37
+KPX Lacute quoteright -55
+KPX Lacute y -37
+KPX Lacute yacute -37
+KPX Lacute ydieresis -37
+KPX Lcommaaccent T -18
+KPX Lcommaaccent Tcaron -18
+KPX Lcommaaccent Tcommaaccent -18
+KPX Lcommaaccent V -37
+KPX Lcommaaccent W -37
+KPX Lcommaaccent Y -37
+KPX Lcommaaccent Yacute -37
+KPX Lcommaaccent Ydieresis -37
+KPX Lcommaaccent quoteright -55
+KPX Lcommaaccent y -37
+KPX Lcommaaccent yacute -37
+KPX Lcommaaccent ydieresis -37
+KPX Lslash T -18
+KPX Lslash Tcaron -18
+KPX Lslash Tcommaaccent -18
+KPX Lslash V -37
+KPX Lslash W -37
+KPX Lslash Y -37
+KPX Lslash Yacute -37
+KPX Lslash Ydieresis -37
+KPX Lslash quoteright -55
+KPX Lslash y -37
+KPX Lslash yacute -37
+KPX Lslash ydieresis -37
+KPX N A -30
+KPX N Aacute -30
+KPX N Abreve -30
+KPX N Acircumflex -30
+KPX N Adieresis -30
+KPX N Agrave -30
+KPX N Amacron -30
+KPX N Aogonek -30
+KPX N Aring -30
+KPX N Atilde -30
+KPX Nacute A -30
+KPX Nacute Aacute -30
+KPX Nacute Abreve -30
+KPX Nacute Acircumflex -30
+KPX Nacute Adieresis -30
+KPX Nacute Agrave -30
+KPX Nacute Amacron -30
+KPX Nacute Aogonek -30
+KPX Nacute Aring -30
+KPX Nacute Atilde -30
+KPX Ncaron A -30
+KPX Ncaron Aacute -30
+KPX Ncaron Abreve -30
+KPX Ncaron Acircumflex -30
+KPX Ncaron Adieresis -30
+KPX Ncaron Agrave -30
+KPX Ncaron Amacron -30
+KPX Ncaron Aogonek -30
+KPX Ncaron Aring -30
+KPX Ncaron Atilde -30
+KPX Ncommaaccent A -30
+KPX Ncommaaccent Aacute -30
+KPX Ncommaaccent Abreve -30
+KPX Ncommaaccent Acircumflex -30
+KPX Ncommaaccent Adieresis -30
+KPX Ncommaaccent Agrave -30
+KPX Ncommaaccent Amacron -30
+KPX Ncommaaccent Aogonek -30
+KPX Ncommaaccent Aring -30
+KPX Ncommaaccent Atilde -30
+KPX Ntilde A -30
+KPX Ntilde Aacute -30
+KPX Ntilde Abreve -30
+KPX Ntilde Acircumflex -30
+KPX Ntilde Adieresis -30
+KPX Ntilde Agrave -30
+KPX Ntilde Amacron -30
+KPX Ntilde Aogonek -30
+KPX Ntilde Aring -30
+KPX Ntilde Atilde -30
+KPX O A -40
+KPX O Aacute -40
+KPX O Abreve -40
+KPX O Acircumflex -40
+KPX O Adieresis -40
+KPX O Agrave -40
+KPX O Amacron -40
+KPX O Aogonek -40
+KPX O Aring -40
+KPX O Atilde -40
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -40
+KPX Oacute Aacute -40
+KPX Oacute Abreve -40
+KPX Oacute Acircumflex -40
+KPX Oacute Adieresis -40
+KPX Oacute Agrave -40
+KPX Oacute Amacron -40
+KPX Oacute Aogonek -40
+KPX Oacute Aring -40
+KPX Oacute Atilde -40
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -40
+KPX Ocircumflex Aacute -40
+KPX Ocircumflex Abreve -40
+KPX Ocircumflex Acircumflex -40
+KPX Ocircumflex Adieresis -40
+KPX Ocircumflex Agrave -40
+KPX Ocircumflex Amacron -40
+KPX Ocircumflex Aogonek -40
+KPX Ocircumflex Aring -40
+KPX Ocircumflex Atilde -40
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -40
+KPX Odieresis Aacute -40
+KPX Odieresis Abreve -40
+KPX Odieresis Acircumflex -40
+KPX Odieresis Adieresis -40
+KPX Odieresis Agrave -40
+KPX Odieresis Amacron -40
+KPX Odieresis Aogonek -40
+KPX Odieresis Aring -40
+KPX Odieresis Atilde -40
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -40
+KPX Ograve Aacute -40
+KPX Ograve Abreve -40
+KPX Ograve Acircumflex -40
+KPX Ograve Adieresis -40
+KPX Ograve Agrave -40
+KPX Ograve Amacron -40
+KPX Ograve Aogonek -40
+KPX Ograve Aring -40
+KPX Ograve Atilde -40
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -40
+KPX Ohungarumlaut Aacute -40
+KPX Ohungarumlaut Abreve -40
+KPX Ohungarumlaut Acircumflex -40
+KPX Ohungarumlaut Adieresis -40
+KPX Ohungarumlaut Agrave -40
+KPX Ohungarumlaut Amacron -40
+KPX Ohungarumlaut Aogonek -40
+KPX Ohungarumlaut Aring -40
+KPX Ohungarumlaut Atilde -40
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -40
+KPX Omacron Aacute -40
+KPX Omacron Abreve -40
+KPX Omacron Acircumflex -40
+KPX Omacron Adieresis -40
+KPX Omacron Agrave -40
+KPX Omacron Amacron -40
+KPX Omacron Aogonek -40
+KPX Omacron Aring -40
+KPX Omacron Atilde -40
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -40
+KPX Oslash Aacute -40
+KPX Oslash Abreve -40
+KPX Oslash Acircumflex -40
+KPX Oslash Adieresis -40
+KPX Oslash Agrave -40
+KPX Oslash Amacron -40
+KPX Oslash Aogonek -40
+KPX Oslash Aring -40
+KPX Oslash Atilde -40
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -40
+KPX Otilde Aacute -40
+KPX Otilde Abreve -40
+KPX Otilde Acircumflex -40
+KPX Otilde Adieresis -40
+KPX Otilde Agrave -40
+KPX Otilde Amacron -40
+KPX Otilde Aogonek -40
+KPX Otilde Aring -40
+KPX Otilde Atilde -40
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -85
+KPX P Aacute -85
+KPX P Abreve -85
+KPX P Acircumflex -85
+KPX P Adieresis -85
+KPX P Agrave -85
+KPX P Amacron -85
+KPX P Aogonek -85
+KPX P Aring -85
+KPX P Atilde -85
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -129
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -55
+KPX P oacute -55
+KPX P ocircumflex -55
+KPX P odieresis -55
+KPX P ograve -55
+KPX P ohungarumlaut -55
+KPX P omacron -55
+KPX P oslash -55
+KPX P otilde -55
+KPX P period -129
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -18
+KPX R W -18
+KPX R Y -18
+KPX R Yacute -18
+KPX R Ydieresis -18
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -18
+KPX Racute W -18
+KPX Racute Y -18
+KPX Racute Yacute -18
+KPX Racute Ydieresis -18
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -18
+KPX Rcaron W -18
+KPX Rcaron Y -18
+KPX Rcaron Yacute -18
+KPX Rcaron Ydieresis -18
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -18
+KPX Rcommaaccent W -18
+KPX Rcommaaccent Y -18
+KPX Rcommaaccent Yacute -18
+KPX Rcommaaccent Ydieresis -18
+KPX T A -55
+KPX T Aacute -55
+KPX T Abreve -55
+KPX T Acircumflex -55
+KPX T Adieresis -55
+KPX T Agrave -55
+KPX T Amacron -55
+KPX T Aogonek -55
+KPX T Aring -55
+KPX T Atilde -55
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -92
+KPX T acircumflex -92
+KPX T adieresis -92
+KPX T agrave -92
+KPX T amacron -92
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -92
+KPX T colon -74
+KPX T comma -92
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -92
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -92
+KPX T i -37
+KPX T iacute -37
+KPX T iogonek -37
+KPX T o -95
+KPX T oacute -95
+KPX T ocircumflex -95
+KPX T odieresis -95
+KPX T ograve -95
+KPX T ohungarumlaut -95
+KPX T omacron -95
+KPX T oslash -95
+KPX T otilde -95
+KPX T period -92
+KPX T r -37
+KPX T racute -37
+KPX T rcaron -37
+KPX T rcommaaccent -37
+KPX T semicolon -74
+KPX T u -37
+KPX T uacute -37
+KPX T ucircumflex -37
+KPX T udieresis -37
+KPX T ugrave -37
+KPX T uhungarumlaut -37
+KPX T umacron -37
+KPX T uogonek -37
+KPX T uring -37
+KPX T w -37
+KPX T y -37
+KPX T yacute -37
+KPX T ydieresis -37
+KPX Tcaron A -55
+KPX Tcaron Aacute -55
+KPX Tcaron Abreve -55
+KPX Tcaron Acircumflex -55
+KPX Tcaron Adieresis -55
+KPX Tcaron Agrave -55
+KPX Tcaron Amacron -55
+KPX Tcaron Aogonek -55
+KPX Tcaron Aring -55
+KPX Tcaron Atilde -55
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -92
+KPX Tcaron acircumflex -92
+KPX Tcaron adieresis -92
+KPX Tcaron agrave -92
+KPX Tcaron amacron -92
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -92
+KPX Tcaron colon -74
+KPX Tcaron comma -92
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -92
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -92
+KPX Tcaron i -37
+KPX Tcaron iacute -37
+KPX Tcaron iogonek -37
+KPX Tcaron o -95
+KPX Tcaron oacute -95
+KPX Tcaron ocircumflex -95
+KPX Tcaron odieresis -95
+KPX Tcaron ograve -95
+KPX Tcaron ohungarumlaut -95
+KPX Tcaron omacron -95
+KPX Tcaron oslash -95
+KPX Tcaron otilde -95
+KPX Tcaron period -92
+KPX Tcaron r -37
+KPX Tcaron racute -37
+KPX Tcaron rcaron -37
+KPX Tcaron rcommaaccent -37
+KPX Tcaron semicolon -74
+KPX Tcaron u -37
+KPX Tcaron uacute -37
+KPX Tcaron ucircumflex -37
+KPX Tcaron udieresis -37
+KPX Tcaron ugrave -37
+KPX Tcaron uhungarumlaut -37
+KPX Tcaron umacron -37
+KPX Tcaron uogonek -37
+KPX Tcaron uring -37
+KPX Tcaron w -37
+KPX Tcaron y -37
+KPX Tcaron yacute -37
+KPX Tcaron ydieresis -37
+KPX Tcommaaccent A -55
+KPX Tcommaaccent Aacute -55
+KPX Tcommaaccent Abreve -55
+KPX Tcommaaccent Acircumflex -55
+KPX Tcommaaccent Adieresis -55
+KPX Tcommaaccent Agrave -55
+KPX Tcommaaccent Amacron -55
+KPX Tcommaaccent Aogonek -55
+KPX Tcommaaccent Aring -55
+KPX Tcommaaccent Atilde -55
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -92
+KPX Tcommaaccent acircumflex -92
+KPX Tcommaaccent adieresis -92
+KPX Tcommaaccent agrave -92
+KPX Tcommaaccent amacron -92
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -92
+KPX Tcommaaccent colon -74
+KPX Tcommaaccent comma -92
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -92
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -37
+KPX Tcommaaccent iacute -37
+KPX Tcommaaccent iogonek -37
+KPX Tcommaaccent o -95
+KPX Tcommaaccent oacute -95
+KPX Tcommaaccent ocircumflex -95
+KPX Tcommaaccent odieresis -95
+KPX Tcommaaccent ograve -95
+KPX Tcommaaccent ohungarumlaut -95
+KPX Tcommaaccent omacron -95
+KPX Tcommaaccent oslash -95
+KPX Tcommaaccent otilde -95
+KPX Tcommaaccent period -92
+KPX Tcommaaccent r -37
+KPX Tcommaaccent racute -37
+KPX Tcommaaccent rcaron -37
+KPX Tcommaaccent rcommaaccent -37
+KPX Tcommaaccent semicolon -74
+KPX Tcommaaccent u -37
+KPX Tcommaaccent uacute -37
+KPX Tcommaaccent ucircumflex -37
+KPX Tcommaaccent udieresis -37
+KPX Tcommaaccent ugrave -37
+KPX Tcommaaccent uhungarumlaut -37
+KPX Tcommaaccent umacron -37
+KPX Tcommaaccent uogonek -37
+KPX Tcommaaccent uring -37
+KPX Tcommaaccent w -37
+KPX Tcommaaccent y -37
+KPX Tcommaaccent yacute -37
+KPX Tcommaaccent ydieresis -37
+KPX U A -45
+KPX U Aacute -45
+KPX U Abreve -45
+KPX U Acircumflex -45
+KPX U Adieresis -45
+KPX U Agrave -45
+KPX U Amacron -45
+KPX U Aogonek -45
+KPX U Aring -45
+KPX U Atilde -45
+KPX Uacute A -45
+KPX Uacute Aacute -45
+KPX Uacute Abreve -45
+KPX Uacute Acircumflex -45
+KPX Uacute Adieresis -45
+KPX Uacute Agrave -45
+KPX Uacute Amacron -45
+KPX Uacute Aogonek -45
+KPX Uacute Aring -45
+KPX Uacute Atilde -45
+KPX Ucircumflex A -45
+KPX Ucircumflex Aacute -45
+KPX Ucircumflex Abreve -45
+KPX Ucircumflex Acircumflex -45
+KPX Ucircumflex Adieresis -45
+KPX Ucircumflex Agrave -45
+KPX Ucircumflex Amacron -45
+KPX Ucircumflex Aogonek -45
+KPX Ucircumflex Aring -45
+KPX Ucircumflex Atilde -45
+KPX Udieresis A -45
+KPX Udieresis Aacute -45
+KPX Udieresis Abreve -45
+KPX Udieresis Acircumflex -45
+KPX Udieresis Adieresis -45
+KPX Udieresis Agrave -45
+KPX Udieresis Amacron -45
+KPX Udieresis Aogonek -45
+KPX Udieresis Aring -45
+KPX Udieresis Atilde -45
+KPX Ugrave A -45
+KPX Ugrave Aacute -45
+KPX Ugrave Abreve -45
+KPX Ugrave Acircumflex -45
+KPX Ugrave Adieresis -45
+KPX Ugrave Agrave -45
+KPX Ugrave Amacron -45
+KPX Ugrave Aogonek -45
+KPX Ugrave Aring -45
+KPX Ugrave Atilde -45
+KPX Uhungarumlaut A -45
+KPX Uhungarumlaut Aacute -45
+KPX Uhungarumlaut Abreve -45
+KPX Uhungarumlaut Acircumflex -45
+KPX Uhungarumlaut Adieresis -45
+KPX Uhungarumlaut Agrave -45
+KPX Uhungarumlaut Amacron -45
+KPX Uhungarumlaut Aogonek -45
+KPX Uhungarumlaut Aring -45
+KPX Uhungarumlaut Atilde -45
+KPX Umacron A -45
+KPX Umacron Aacute -45
+KPX Umacron Abreve -45
+KPX Umacron Acircumflex -45
+KPX Umacron Adieresis -45
+KPX Umacron Agrave -45
+KPX Umacron Amacron -45
+KPX Umacron Aogonek -45
+KPX Umacron Aring -45
+KPX Umacron Atilde -45
+KPX Uogonek A -45
+KPX Uogonek Aacute -45
+KPX Uogonek Abreve -45
+KPX Uogonek Acircumflex -45
+KPX Uogonek Adieresis -45
+KPX Uogonek Agrave -45
+KPX Uogonek Amacron -45
+KPX Uogonek Aogonek -45
+KPX Uogonek Aring -45
+KPX Uogonek Atilde -45
+KPX Uring A -45
+KPX Uring Aacute -45
+KPX Uring Abreve -45
+KPX Uring Acircumflex -45
+KPX Uring Adieresis -45
+KPX Uring Agrave -45
+KPX Uring Amacron -45
+KPX Uring Aogonek -45
+KPX Uring Aring -45
+KPX Uring Atilde -45
+KPX V A -85
+KPX V Aacute -85
+KPX V Abreve -85
+KPX V Acircumflex -85
+KPX V Adieresis -85
+KPX V Agrave -85
+KPX V Amacron -85
+KPX V Aogonek -85
+KPX V Aring -85
+KPX V Atilde -85
+KPX V G -10
+KPX V Gbreve -10
+KPX V Gcommaaccent -10
+KPX V O -30
+KPX V Oacute -30
+KPX V Ocircumflex -30
+KPX V Odieresis -30
+KPX V Ograve -30
+KPX V Ohungarumlaut -30
+KPX V Omacron -30
+KPX V Oslash -30
+KPX V Otilde -30
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -111
+KPX V adieresis -111
+KPX V agrave -111
+KPX V amacron -111
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -111
+KPX V colon -74
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -111
+KPX V ecircumflex -111
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -70
+KPX V i -55
+KPX V iacute -55
+KPX V iogonek -55
+KPX V o -111
+KPX V oacute -111
+KPX V ocircumflex -111
+KPX V odieresis -111
+KPX V ograve -111
+KPX V ohungarumlaut -111
+KPX V omacron -111
+KPX V oslash -111
+KPX V otilde -111
+KPX V period -129
+KPX V semicolon -74
+KPX V u -55
+KPX V uacute -55
+KPX V ucircumflex -55
+KPX V udieresis -55
+KPX V ugrave -55
+KPX V uhungarumlaut -55
+KPX V umacron -55
+KPX V uogonek -55
+KPX V uring -55
+KPX W A -74
+KPX W Aacute -74
+KPX W Abreve -74
+KPX W Acircumflex -74
+KPX W Adieresis -74
+KPX W Agrave -74
+KPX W Amacron -74
+KPX W Aogonek -74
+KPX W Aring -74
+KPX W Atilde -74
+KPX W O -15
+KPX W Oacute -15
+KPX W Ocircumflex -15
+KPX W Odieresis -15
+KPX W Ograve -15
+KPX W Ohungarumlaut -15
+KPX W Omacron -15
+KPX W Oslash -15
+KPX W Otilde -15
+KPX W a -85
+KPX W aacute -85
+KPX W abreve -85
+KPX W acircumflex -85
+KPX W adieresis -85
+KPX W agrave -85
+KPX W amacron -85
+KPX W aogonek -85
+KPX W aring -85
+KPX W atilde -85
+KPX W colon -55
+KPX W comma -74
+KPX W e -90
+KPX W eacute -90
+KPX W ecaron -90
+KPX W ecircumflex -90
+KPX W edieresis -50
+KPX W edotaccent -90
+KPX W egrave -50
+KPX W emacron -50
+KPX W eogonek -90
+KPX W hyphen -50
+KPX W i -37
+KPX W iacute -37
+KPX W iogonek -37
+KPX W o -80
+KPX W oacute -80
+KPX W ocircumflex -80
+KPX W odieresis -80
+KPX W ograve -80
+KPX W ohungarumlaut -80
+KPX W omacron -80
+KPX W oslash -80
+KPX W otilde -80
+KPX W period -74
+KPX W semicolon -55
+KPX W u -55
+KPX W uacute -55
+KPX W ucircumflex -55
+KPX W udieresis -55
+KPX W ugrave -55
+KPX W uhungarumlaut -55
+KPX W umacron -55
+KPX W uogonek -55
+KPX W uring -55
+KPX W y -55
+KPX W yacute -55
+KPX W ydieresis -55
+KPX Y A -74
+KPX Y Aacute -74
+KPX Y Abreve -74
+KPX Y Acircumflex -74
+KPX Y Adieresis -74
+KPX Y Agrave -74
+KPX Y Amacron -74
+KPX Y Aogonek -74
+KPX Y Aring -74
+KPX Y Atilde -74
+KPX Y O -25
+KPX Y Oacute -25
+KPX Y Ocircumflex -25
+KPX Y Odieresis -25
+KPX Y Ograve -25
+KPX Y Ohungarumlaut -25
+KPX Y Omacron -25
+KPX Y Oslash -25
+KPX Y Otilde -25
+KPX Y a -92
+KPX Y aacute -92
+KPX Y abreve -92
+KPX Y acircumflex -92
+KPX Y adieresis -92
+KPX Y agrave -92
+KPX Y amacron -92
+KPX Y aogonek -92
+KPX Y aring -92
+KPX Y atilde -92
+KPX Y colon -92
+KPX Y comma -92
+KPX Y e -111
+KPX Y eacute -111
+KPX Y ecaron -111
+KPX Y ecircumflex -71
+KPX Y edieresis -71
+KPX Y edotaccent -111
+KPX Y egrave -71
+KPX Y emacron -71
+KPX Y eogonek -111
+KPX Y hyphen -92
+KPX Y i -55
+KPX Y iacute -55
+KPX Y iogonek -55
+KPX Y o -111
+KPX Y oacute -111
+KPX Y ocircumflex -111
+KPX Y odieresis -111
+KPX Y ograve -111
+KPX Y ohungarumlaut -111
+KPX Y omacron -111
+KPX Y oslash -111
+KPX Y otilde -111
+KPX Y period -74
+KPX Y semicolon -92
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -74
+KPX Yacute Aacute -74
+KPX Yacute Abreve -74
+KPX Yacute Acircumflex -74
+KPX Yacute Adieresis -74
+KPX Yacute Agrave -74
+KPX Yacute Amacron -74
+KPX Yacute Aogonek -74
+KPX Yacute Aring -74
+KPX Yacute Atilde -74
+KPX Yacute O -25
+KPX Yacute Oacute -25
+KPX Yacute Ocircumflex -25
+KPX Yacute Odieresis -25
+KPX Yacute Ograve -25
+KPX Yacute Ohungarumlaut -25
+KPX Yacute Omacron -25
+KPX Yacute Oslash -25
+KPX Yacute Otilde -25
+KPX Yacute a -92
+KPX Yacute aacute -92
+KPX Yacute abreve -92
+KPX Yacute acircumflex -92
+KPX Yacute adieresis -92
+KPX Yacute agrave -92
+KPX Yacute amacron -92
+KPX Yacute aogonek -92
+KPX Yacute aring -92
+KPX Yacute atilde -92
+KPX Yacute colon -92
+KPX Yacute comma -92
+KPX Yacute e -111
+KPX Yacute eacute -111
+KPX Yacute ecaron -111
+KPX Yacute ecircumflex -71
+KPX Yacute edieresis -71
+KPX Yacute edotaccent -111
+KPX Yacute egrave -71
+KPX Yacute emacron -71
+KPX Yacute eogonek -111
+KPX Yacute hyphen -92
+KPX Yacute i -55
+KPX Yacute iacute -55
+KPX Yacute iogonek -55
+KPX Yacute o -111
+KPX Yacute oacute -111
+KPX Yacute ocircumflex -111
+KPX Yacute odieresis -111
+KPX Yacute ograve -111
+KPX Yacute ohungarumlaut -111
+KPX Yacute omacron -111
+KPX Yacute oslash -111
+KPX Yacute otilde -111
+KPX Yacute period -74
+KPX Yacute semicolon -92
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -74
+KPX Ydieresis Aacute -74
+KPX Ydieresis Abreve -74
+KPX Ydieresis Acircumflex -74
+KPX Ydieresis Adieresis -74
+KPX Ydieresis Agrave -74
+KPX Ydieresis Amacron -74
+KPX Ydieresis Aogonek -74
+KPX Ydieresis Aring -74
+KPX Ydieresis Atilde -74
+KPX Ydieresis O -25
+KPX Ydieresis Oacute -25
+KPX Ydieresis Ocircumflex -25
+KPX Ydieresis Odieresis -25
+KPX Ydieresis Ograve -25
+KPX Ydieresis Ohungarumlaut -25
+KPX Ydieresis Omacron -25
+KPX Ydieresis Oslash -25
+KPX Ydieresis Otilde -25
+KPX Ydieresis a -92
+KPX Ydieresis aacute -92
+KPX Ydieresis abreve -92
+KPX Ydieresis acircumflex -92
+KPX Ydieresis adieresis -92
+KPX Ydieresis agrave -92
+KPX Ydieresis amacron -92
+KPX Ydieresis aogonek -92
+KPX Ydieresis aring -92
+KPX Ydieresis atilde -92
+KPX Ydieresis colon -92
+KPX Ydieresis comma -92
+KPX Ydieresis e -111
+KPX Ydieresis eacute -111
+KPX Ydieresis ecaron -111
+KPX Ydieresis ecircumflex -71
+KPX Ydieresis edieresis -71
+KPX Ydieresis edotaccent -111
+KPX Ydieresis egrave -71
+KPX Ydieresis emacron -71
+KPX Ydieresis eogonek -111
+KPX Ydieresis hyphen -92
+KPX Ydieresis i -55
+KPX Ydieresis iacute -55
+KPX Ydieresis iogonek -55
+KPX Ydieresis o -111
+KPX Ydieresis oacute -111
+KPX Ydieresis ocircumflex -111
+KPX Ydieresis odieresis -111
+KPX Ydieresis ograve -111
+KPX Ydieresis ohungarumlaut -111
+KPX Ydieresis omacron -111
+KPX Ydieresis oslash -111
+KPX Ydieresis otilde -111
+KPX Ydieresis period -74
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX b b -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX c h -10
+KPX c k -10
+KPX c kcommaaccent -10
+KPX cacute h -10
+KPX cacute k -10
+KPX cacute kcommaaccent -10
+KPX ccaron h -10
+KPX ccaron k -10
+KPX ccaron kcommaaccent -10
+KPX ccedilla h -10
+KPX ccedilla k -10
+KPX ccedilla kcommaaccent -10
+KPX comma quotedblright -95
+KPX comma quoteright -95
+KPX e b -10
+KPX eacute b -10
+KPX ecaron b -10
+KPX ecircumflex b -10
+KPX edieresis b -10
+KPX edotaccent b -10
+KPX egrave b -10
+KPX emacron b -10
+KPX eogonek b -10
+KPX f comma -10
+KPX f dotlessi -30
+KPX f e -10
+KPX f eacute -10
+KPX f edotaccent -10
+KPX f eogonek -10
+KPX f f -18
+KPX f o -10
+KPX f oacute -10
+KPX f ocircumflex -10
+KPX f ograve -10
+KPX f ohungarumlaut -10
+KPX f oslash -10
+KPX f otilde -10
+KPX f period -10
+KPX f quoteright 55
+KPX k e -30
+KPX k eacute -30
+KPX k ecaron -30
+KPX k ecircumflex -30
+KPX k edieresis -30
+KPX k edotaccent -30
+KPX k egrave -30
+KPX k emacron -30
+KPX k eogonek -30
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX kcommaaccent e -30
+KPX kcommaaccent eacute -30
+KPX kcommaaccent ecaron -30
+KPX kcommaaccent ecircumflex -30
+KPX kcommaaccent edieresis -30
+KPX kcommaaccent edotaccent -30
+KPX kcommaaccent egrave -30
+KPX kcommaaccent emacron -30
+KPX kcommaaccent eogonek -30
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o v -15
+KPX o w -25
+KPX o x -10
+KPX o y -10
+KPX o yacute -10
+KPX o ydieresis -10
+KPX oacute v -15
+KPX oacute w -25
+KPX oacute x -10
+KPX oacute y -10
+KPX oacute yacute -10
+KPX oacute ydieresis -10
+KPX ocircumflex v -15
+KPX ocircumflex w -25
+KPX ocircumflex x -10
+KPX ocircumflex y -10
+KPX ocircumflex yacute -10
+KPX ocircumflex ydieresis -10
+KPX odieresis v -15
+KPX odieresis w -25
+KPX odieresis x -10
+KPX odieresis y -10
+KPX odieresis yacute -10
+KPX odieresis ydieresis -10
+KPX ograve v -15
+KPX ograve w -25
+KPX ograve x -10
+KPX ograve y -10
+KPX ograve yacute -10
+KPX ograve ydieresis -10
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -25
+KPX ohungarumlaut x -10
+KPX ohungarumlaut y -10
+KPX ohungarumlaut yacute -10
+KPX ohungarumlaut ydieresis -10
+KPX omacron v -15
+KPX omacron w -25
+KPX omacron x -10
+KPX omacron y -10
+KPX omacron yacute -10
+KPX omacron ydieresis -10
+KPX oslash v -15
+KPX oslash w -25
+KPX oslash x -10
+KPX oslash y -10
+KPX oslash yacute -10
+KPX oslash ydieresis -10
+KPX otilde v -15
+KPX otilde w -25
+KPX otilde x -10
+KPX otilde y -10
+KPX otilde yacute -10
+KPX otilde ydieresis -10
+KPX period quotedblright -95
+KPX period quoteright -95
+KPX quoteleft quoteleft -74
+KPX quoteright d -15
+KPX quoteright dcroat -15
+KPX quoteright quoteright -74
+KPX quoteright r -15
+KPX quoteright racute -15
+KPX quoteright rcaron -15
+KPX quoteright rcommaaccent -15
+KPX quoteright s -74
+KPX quoteright sacute -74
+KPX quoteright scaron -74
+KPX quoteright scedilla -74
+KPX quoteright scommaaccent -74
+KPX quoteright space -74
+KPX quoteright t -37
+KPX quoteright tcommaaccent -37
+KPX quoteright v -15
+KPX r comma -65
+KPX r period -65
+KPX racute comma -65
+KPX racute period -65
+KPX rcaron comma -65
+KPX rcaron period -65
+KPX rcommaaccent comma -65
+KPX rcommaaccent period -65
+KPX space A -37
+KPX space Aacute -37
+KPX space Abreve -37
+KPX space Acircumflex -37
+KPX space Adieresis -37
+KPX space Agrave -37
+KPX space Amacron -37
+KPX space Aogonek -37
+KPX space Aring -37
+KPX space Atilde -37
+KPX space V -70
+KPX space W -70
+KPX space Y -70
+KPX space Yacute -70
+KPX space Ydieresis -70
+KPX v comma -37
+KPX v e -15
+KPX v eacute -15
+KPX v ecaron -15
+KPX v ecircumflex -15
+KPX v edieresis -15
+KPX v edotaccent -15
+KPX v egrave -15
+KPX v emacron -15
+KPX v eogonek -15
+KPX v o -15
+KPX v oacute -15
+KPX v ocircumflex -15
+KPX v odieresis -15
+KPX v ograve -15
+KPX v ohungarumlaut -15
+KPX v omacron -15
+KPX v oslash -15
+KPX v otilde -15
+KPX v period -37
+KPX w a -10
+KPX w aacute -10
+KPX w abreve -10
+KPX w acircumflex -10
+KPX w adieresis -10
+KPX w agrave -10
+KPX w amacron -10
+KPX w aogonek -10
+KPX w aring -10
+KPX w atilde -10
+KPX w comma -37
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -15
+KPX w oacute -15
+KPX w ocircumflex -15
+KPX w odieresis -15
+KPX w ograve -15
+KPX w ohungarumlaut -15
+KPX w omacron -15
+KPX w oslash -15
+KPX w otilde -15
+KPX w period -37
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y comma -37
+KPX y period -37
+KPX yacute comma -37
+KPX yacute period -37
+KPX ydieresis comma -37
+KPX ydieresis period -37
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Times-Italic.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Italic.afm
new file mode 100644
index 0000000..e322120
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Italic.afm
@@ -0,0 +1,2668 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:56:55 1997
+Comment UniqueID 43067
+Comment VMusage 47727 58752
+FontName Times-Italic
+FullName Times Italic
+FamilyName Times
+Weight Medium
+ItalicAngle -15.5
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -169 -217 1010 883 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 653
+XHeight 441
+Ascender 683
+Descender -217
+StdHW 32
+StdVW 76
+StartCharMetrics 315
+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 -217 171 783 ;
+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 548 305 646 ;
+C 200 ; WX 333 ; N dieresis ; B 107 548 405 646 ;
+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 203 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 41 -11 312 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 333 ; N Idieresis ; B -8 0 435 818 ;
+C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ;
+C -1 ; WX 500 ; N abreve ; B 17 -11 502 650 ;
+C -1 ; WX 500 ; N uhungarumlaut ; B 42 -11 580 664 ;
+C -1 ; WX 444 ; N ecaron ; B 31 -11 482 661 ;
+C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ;
+C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ;
+C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ;
+C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ;
+C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ;
+C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ;
+C -1 ; WX 389 ; N scommaaccent ; B 16 -217 366 442 ;
+C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ;
+C -1 ; WX 722 ; N Uring ; B 102 -18 765 883 ;
+C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ;
+C -1 ; WX 500 ; N aogonek ; B 17 -169 476 441 ;
+C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ;
+C -1 ; WX 500 ; N uogonek ; B 42 -169 477 441 ;
+C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ;
+C -1 ; WX 722 ; N Dcroat ; B -8 0 700 653 ;
+C -1 ; WX 250 ; N commaaccent ; B 8 -217 133 -50 ;
+C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ;
+C -1 ; WX 611 ; N Emacron ; B -1 0 634 795 ;
+C -1 ; WX 444 ; N ccaron ; B 30 -11 482 661 ;
+C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ;
+C -1 ; WX 667 ; N Ncommaaccent ; B -20 -187 727 653 ;
+C -1 ; WX 278 ; N lacute ; B 41 -11 395 876 ;
+C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ;
+C -1 ; WX 556 ; N Tcommaaccent ; B 59 -217 633 653 ;
+C -1 ; WX 667 ; N Cacute ; B 66 -18 690 876 ;
+C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ;
+C -1 ; WX 611 ; N Edotaccent ; B -1 0 634 818 ;
+C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ;
+C -1 ; WX 389 ; N scedilla ; B 16 -217 366 442 ;
+C -1 ; WX 278 ; N iacute ; B 49 -11 355 664 ;
+C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
+C -1 ; WX 611 ; N Rcaron ; B -13 0 588 873 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 52 -217 722 666 ;
+C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ;
+C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ;
+C -1 ; WX 611 ; N Amacron ; B -51 0 564 795 ;
+C -1 ; WX 389 ; N rcaron ; B 45 0 434 661 ;
+C -1 ; WX 444 ; N ccedilla ; B 30 -217 425 441 ;
+C -1 ; WX 556 ; N Zdotaccent ; B -6 0 606 818 ;
+C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ;
+C -1 ; WX 722 ; N Omacron ; B 60 -18 699 795 ;
+C -1 ; WX 611 ; N Racute ; B -13 0 588 876 ;
+C -1 ; WX 500 ; N Sacute ; B 17 -18 508 876 ;
+C -1 ; WX 544 ; N dcaron ; B 15 -13 658 683 ;
+C -1 ; WX 722 ; N Umacron ; B 102 -18 765 795 ;
+C -1 ; WX 500 ; N uring ; B 42 -11 475 691 ;
+C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ;
+C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ;
+C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ;
+C -1 ; WX 611 ; N Abreve ; B -51 0 564 862 ;
+C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ;
+C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ;
+C -1 ; WX 556 ; N Tcaron ; B 59 0 633 873 ;
+C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ;
+C -1 ; WX 667 ; N Nacute ; B -20 -15 727 876 ;
+C -1 ; WX 278 ; N icircumflex ; B 33 -11 327 661 ;
+C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ;
+C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ;
+C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ;
+C -1 ; WX 444 ; N cacute ; B 30 -11 459 664 ;
+C -1 ; WX 500 ; N nacute ; B 14 -9 477 664 ;
+C -1 ; WX 500 ; N umacron ; B 42 -11 485 583 ;
+C -1 ; WX 667 ; N Ncaron ; B -20 -15 727 873 ;
+C -1 ; WX 333 ; N Iacute ; B -8 0 433 876 ;
+C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ;
+C -1 ; WX 275 ; N brokenbar ; B 105 -142 171 708 ;
+C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ;
+C -1 ; WX 722 ; N Gbreve ; B 52 -18 722 862 ;
+C -1 ; WX 333 ; N Idotaccent ; B -8 0 384 818 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ;
+C -1 ; WX 389 ; N racute ; B 45 0 431 664 ;
+C -1 ; WX 500 ; N omacron ; B 27 -11 495 583 ;
+C -1 ; WX 556 ; N Zacute ; B -6 0 606 876 ;
+C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 658 ;
+C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ;
+C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 22 -217 279 683 ;
+C -1 ; WX 300 ; N tcaron ; B 37 -11 407 681 ;
+C -1 ; WX 444 ; N eogonek ; B 31 -169 412 441 ;
+C -1 ; WX 722 ; N Uogonek ; B 102 -184 765 653 ;
+C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ;
+C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ;
+C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ;
+C -1 ; WX 389 ; N zacute ; B -2 -81 431 664 ;
+C -1 ; WX 278 ; N iogonek ; B 49 -169 264 654 ;
+C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ;
+C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ;
+C -1 ; WX 500 ; N amacron ; B 17 -11 495 583 ;
+C -1 ; WX 389 ; N sacute ; B 16 -13 431 664 ;
+C -1 ; WX 278 ; N idieresis ; B 49 -11 352 606 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ;
+C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ;
+C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ;
+C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ;
+C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ;
+C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 27 -11 590 664 ;
+C -1 ; WX 611 ; N Eogonek ; B -1 -169 634 653 ;
+C -1 ; WX 500 ; N dcroat ; B 15 -13 572 683 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ;
+C -1 ; WX 500 ; N Scedilla ; B 17 -217 508 667 ;
+C -1 ; WX 300 ; N lcaron ; B 41 -11 407 683 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 7 -217 722 653 ;
+C -1 ; WX 556 ; N Lacute ; B -8 0 559 876 ;
+C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ;
+C -1 ; WX 444 ; N edotaccent ; B 31 -11 412 606 ;
+C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ;
+C -1 ; WX 333 ; N Imacron ; B -8 0 441 795 ;
+C -1 ; WX 611 ; N Lcaron ; B -8 0 586 653 ;
+C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 658 ;
+C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ;
+C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 102 -18 765 876 ;
+C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ;
+C -1 ; WX 444 ; N emacron ; B 31 -11 457 583 ;
+C -1 ; WX 500 ; N gbreve ; B 8 -206 487 650 ;
+C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ;
+C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ;
+C -1 ; WX 500 ; N Scommaaccent ; B 17 -217 508 667 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 60 -18 699 876 ;
+C -1 ; WX 400 ; N degree ; B 101 390 387 676 ;
+C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ;
+C -1 ; WX 667 ; N Ccaron ; B 66 -18 689 873 ;
+C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ;
+C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
+C -1 ; WX 722 ; N Dcaron ; B -8 0 700 873 ;
+C -1 ; WX 389 ; N rcommaaccent ; B -3 -217 412 441 ;
+C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ;
+C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ;
+C -1 ; WX 611 ; N Rcommaaccent ; B -13 -187 588 653 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B -8 -217 559 653 ;
+C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ;
+C -1 ; WX 611 ; N Aogonek ; B -51 -169 566 668 ;
+C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ;
+C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ;
+C -1 ; WX 389 ; N zdotaccent ; B -2 -81 380 606 ;
+C -1 ; WX 611 ; N Ecaron ; B -1 0 634 873 ;
+C -1 ; WX 333 ; N Iogonek ; B -8 -169 384 653 ;
+C -1 ; WX 444 ; N kcommaaccent ; B 14 -187 461 683 ;
+C -1 ; WX 675 ; N minus ; B 86 220 590 286 ;
+C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ;
+C -1 ; WX 500 ; N ncaron ; B 14 -9 510 661 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 2 -217 296 546 ;
+C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ;
+C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ;
+C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ;
+C -1 ; WX 549 ; N notequal ; B 12 -29 537 541 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 8 -206 472 706 ;
+C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ;
+C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ;
+C -1 ; WX 500 ; N ncommaaccent ; B 14 -187 474 441 ;
+C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ;
+C -1 ; WX 278 ; N imacron ; B 46 -11 311 583 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2321
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -35
+KPX A Gbreve -35
+KPX A Gcommaaccent -35
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -37
+KPX A Tcaron -37
+KPX A Tcommaaccent -37
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -105
+KPX A W -95
+KPX A Y -55
+KPX A Yacute -55
+KPX A Ydieresis -55
+KPX A quoteright -37
+KPX A u -20
+KPX A uacute -20
+KPX A ucircumflex -20
+KPX A udieresis -20
+KPX A ugrave -20
+KPX A uhungarumlaut -20
+KPX A umacron -20
+KPX A uogonek -20
+KPX A uring -20
+KPX A v -55
+KPX A w -55
+KPX A y -55
+KPX A yacute -55
+KPX A ydieresis -55
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -35
+KPX Aacute Gbreve -35
+KPX Aacute Gcommaaccent -35
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -37
+KPX Aacute Tcaron -37
+KPX Aacute Tcommaaccent -37
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -105
+KPX Aacute W -95
+KPX Aacute Y -55
+KPX Aacute Yacute -55
+KPX Aacute Ydieresis -55
+KPX Aacute quoteright -37
+KPX Aacute u -20
+KPX Aacute uacute -20
+KPX Aacute ucircumflex -20
+KPX Aacute udieresis -20
+KPX Aacute ugrave -20
+KPX Aacute uhungarumlaut -20
+KPX Aacute umacron -20
+KPX Aacute uogonek -20
+KPX Aacute uring -20
+KPX Aacute v -55
+KPX Aacute w -55
+KPX Aacute y -55
+KPX Aacute yacute -55
+KPX Aacute ydieresis -55
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -35
+KPX Abreve Gbreve -35
+KPX Abreve Gcommaaccent -35
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -37
+KPX Abreve Tcaron -37
+KPX Abreve Tcommaaccent -37
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -105
+KPX Abreve W -95
+KPX Abreve Y -55
+KPX Abreve Yacute -55
+KPX Abreve Ydieresis -55
+KPX Abreve quoteright -37
+KPX Abreve u -20
+KPX Abreve uacute -20
+KPX Abreve ucircumflex -20
+KPX Abreve udieresis -20
+KPX Abreve ugrave -20
+KPX Abreve uhungarumlaut -20
+KPX Abreve umacron -20
+KPX Abreve uogonek -20
+KPX Abreve uring -20
+KPX Abreve v -55
+KPX Abreve w -55
+KPX Abreve y -55
+KPX Abreve yacute -55
+KPX Abreve ydieresis -55
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -35
+KPX Acircumflex Gbreve -35
+KPX Acircumflex Gcommaaccent -35
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -37
+KPX Acircumflex Tcaron -37
+KPX Acircumflex Tcommaaccent -37
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -105
+KPX Acircumflex W -95
+KPX Acircumflex Y -55
+KPX Acircumflex Yacute -55
+KPX Acircumflex Ydieresis -55
+KPX Acircumflex quoteright -37
+KPX Acircumflex u -20
+KPX Acircumflex uacute -20
+KPX Acircumflex ucircumflex -20
+KPX Acircumflex udieresis -20
+KPX Acircumflex ugrave -20
+KPX Acircumflex uhungarumlaut -20
+KPX Acircumflex umacron -20
+KPX Acircumflex uogonek -20
+KPX Acircumflex uring -20
+KPX Acircumflex v -55
+KPX Acircumflex w -55
+KPX Acircumflex y -55
+KPX Acircumflex yacute -55
+KPX Acircumflex ydieresis -55
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -35
+KPX Adieresis Gbreve -35
+KPX Adieresis Gcommaaccent -35
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -37
+KPX Adieresis Tcaron -37
+KPX Adieresis Tcommaaccent -37
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -105
+KPX Adieresis W -95
+KPX Adieresis Y -55
+KPX Adieresis Yacute -55
+KPX Adieresis Ydieresis -55
+KPX Adieresis quoteright -37
+KPX Adieresis u -20
+KPX Adieresis uacute -20
+KPX Adieresis ucircumflex -20
+KPX Adieresis udieresis -20
+KPX Adieresis ugrave -20
+KPX Adieresis uhungarumlaut -20
+KPX Adieresis umacron -20
+KPX Adieresis uogonek -20
+KPX Adieresis uring -20
+KPX Adieresis v -55
+KPX Adieresis w -55
+KPX Adieresis y -55
+KPX Adieresis yacute -55
+KPX Adieresis ydieresis -55
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -35
+KPX Agrave Gbreve -35
+KPX Agrave Gcommaaccent -35
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -37
+KPX Agrave Tcaron -37
+KPX Agrave Tcommaaccent -37
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -105
+KPX Agrave W -95
+KPX Agrave Y -55
+KPX Agrave Yacute -55
+KPX Agrave Ydieresis -55
+KPX Agrave quoteright -37
+KPX Agrave u -20
+KPX Agrave uacute -20
+KPX Agrave ucircumflex -20
+KPX Agrave udieresis -20
+KPX Agrave ugrave -20
+KPX Agrave uhungarumlaut -20
+KPX Agrave umacron -20
+KPX Agrave uogonek -20
+KPX Agrave uring -20
+KPX Agrave v -55
+KPX Agrave w -55
+KPX Agrave y -55
+KPX Agrave yacute -55
+KPX Agrave ydieresis -55
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -35
+KPX Amacron Gbreve -35
+KPX Amacron Gcommaaccent -35
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -37
+KPX Amacron Tcaron -37
+KPX Amacron Tcommaaccent -37
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -105
+KPX Amacron W -95
+KPX Amacron Y -55
+KPX Amacron Yacute -55
+KPX Amacron Ydieresis -55
+KPX Amacron quoteright -37
+KPX Amacron u -20
+KPX Amacron uacute -20
+KPX Amacron ucircumflex -20
+KPX Amacron udieresis -20
+KPX Amacron ugrave -20
+KPX Amacron uhungarumlaut -20
+KPX Amacron umacron -20
+KPX Amacron uogonek -20
+KPX Amacron uring -20
+KPX Amacron v -55
+KPX Amacron w -55
+KPX Amacron y -55
+KPX Amacron yacute -55
+KPX Amacron ydieresis -55
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -35
+KPX Aogonek Gbreve -35
+KPX Aogonek Gcommaaccent -35
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -37
+KPX Aogonek Tcaron -37
+KPX Aogonek Tcommaaccent -37
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -105
+KPX Aogonek W -95
+KPX Aogonek Y -55
+KPX Aogonek Yacute -55
+KPX Aogonek Ydieresis -55
+KPX Aogonek quoteright -37
+KPX Aogonek u -20
+KPX Aogonek uacute -20
+KPX Aogonek ucircumflex -20
+KPX Aogonek udieresis -20
+KPX Aogonek ugrave -20
+KPX Aogonek uhungarumlaut -20
+KPX Aogonek umacron -20
+KPX Aogonek uogonek -20
+KPX Aogonek uring -20
+KPX Aogonek v -55
+KPX Aogonek w -55
+KPX Aogonek y -55
+KPX Aogonek yacute -55
+KPX Aogonek ydieresis -55
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -35
+KPX Aring Gbreve -35
+KPX Aring Gcommaaccent -35
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -37
+KPX Aring Tcaron -37
+KPX Aring Tcommaaccent -37
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -105
+KPX Aring W -95
+KPX Aring Y -55
+KPX Aring Yacute -55
+KPX Aring Ydieresis -55
+KPX Aring quoteright -37
+KPX Aring u -20
+KPX Aring uacute -20
+KPX Aring ucircumflex -20
+KPX Aring udieresis -20
+KPX Aring ugrave -20
+KPX Aring uhungarumlaut -20
+KPX Aring umacron -20
+KPX Aring uogonek -20
+KPX Aring uring -20
+KPX Aring v -55
+KPX Aring w -55
+KPX Aring y -55
+KPX Aring yacute -55
+KPX Aring ydieresis -55
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -35
+KPX Atilde Gbreve -35
+KPX Atilde Gcommaaccent -35
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -37
+KPX Atilde Tcaron -37
+KPX Atilde Tcommaaccent -37
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -105
+KPX Atilde W -95
+KPX Atilde Y -55
+KPX Atilde Yacute -55
+KPX Atilde Ydieresis -55
+KPX Atilde quoteright -37
+KPX Atilde u -20
+KPX Atilde uacute -20
+KPX Atilde ucircumflex -20
+KPX Atilde udieresis -20
+KPX Atilde ugrave -20
+KPX Atilde uhungarumlaut -20
+KPX Atilde umacron -20
+KPX Atilde uogonek -20
+KPX Atilde uring -20
+KPX Atilde v -55
+KPX Atilde w -55
+KPX Atilde y -55
+KPX Atilde yacute -55
+KPX Atilde ydieresis -55
+KPX B A -25
+KPX B Aacute -25
+KPX B Abreve -25
+KPX B Acircumflex -25
+KPX B Adieresis -25
+KPX B Agrave -25
+KPX B Amacron -25
+KPX B Aogonek -25
+KPX B Aring -25
+KPX B Atilde -25
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -35
+KPX D Aacute -35
+KPX D Abreve -35
+KPX D Acircumflex -35
+KPX D Adieresis -35
+KPX D Agrave -35
+KPX D Amacron -35
+KPX D Aogonek -35
+KPX D Aring -35
+KPX D Atilde -35
+KPX D V -40
+KPX D W -40
+KPX D Y -40
+KPX D Yacute -40
+KPX D Ydieresis -40
+KPX Dcaron A -35
+KPX Dcaron Aacute -35
+KPX Dcaron Abreve -35
+KPX Dcaron Acircumflex -35
+KPX Dcaron Adieresis -35
+KPX Dcaron Agrave -35
+KPX Dcaron Amacron -35
+KPX Dcaron Aogonek -35
+KPX Dcaron Aring -35
+KPX Dcaron Atilde -35
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -40
+KPX Dcaron Yacute -40
+KPX Dcaron Ydieresis -40
+KPX Dcroat A -35
+KPX Dcroat Aacute -35
+KPX Dcroat Abreve -35
+KPX Dcroat Acircumflex -35
+KPX Dcroat Adieresis -35
+KPX Dcroat Agrave -35
+KPX Dcroat Amacron -35
+KPX Dcroat Aogonek -35
+KPX Dcroat Aring -35
+KPX Dcroat Atilde -35
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -40
+KPX Dcroat Yacute -40
+KPX Dcroat Ydieresis -40
+KPX F A -115
+KPX F Aacute -115
+KPX F Abreve -115
+KPX F Acircumflex -115
+KPX F Adieresis -115
+KPX F Agrave -115
+KPX F Amacron -115
+KPX F Aogonek -115
+KPX F Aring -115
+KPX F Atilde -115
+KPX F a -75
+KPX F aacute -75
+KPX F abreve -75
+KPX F acircumflex -75
+KPX F adieresis -75
+KPX F agrave -75
+KPX F amacron -75
+KPX F aogonek -75
+KPX F aring -75
+KPX F atilde -75
+KPX F comma -135
+KPX F e -75
+KPX F eacute -75
+KPX F ecaron -75
+KPX F ecircumflex -75
+KPX F edieresis -75
+KPX F edotaccent -75
+KPX F egrave -75
+KPX F emacron -75
+KPX F eogonek -75
+KPX F i -45
+KPX F iacute -45
+KPX F icircumflex -45
+KPX F idieresis -45
+KPX F igrave -45
+KPX F imacron -45
+KPX F iogonek -45
+KPX F o -105
+KPX F oacute -105
+KPX F ocircumflex -105
+KPX F odieresis -105
+KPX F ograve -105
+KPX F ohungarumlaut -105
+KPX F omacron -105
+KPX F oslash -105
+KPX F otilde -105
+KPX F period -135
+KPX F r -55
+KPX F racute -55
+KPX F rcaron -55
+KPX F rcommaaccent -55
+KPX J A -40
+KPX J Aacute -40
+KPX J Abreve -40
+KPX J Acircumflex -40
+KPX J Adieresis -40
+KPX J Agrave -40
+KPX J Amacron -40
+KPX J Aogonek -40
+KPX J Aring -40
+KPX J Atilde -40
+KPX J a -35
+KPX J aacute -35
+KPX J abreve -35
+KPX J acircumflex -35
+KPX J adieresis -35
+KPX J agrave -35
+KPX J amacron -35
+KPX J aogonek -35
+KPX J aring -35
+KPX J atilde -35
+KPX J comma -25
+KPX J e -25
+KPX J eacute -25
+KPX J ecaron -25
+KPX J ecircumflex -25
+KPX J edieresis -25
+KPX J edotaccent -25
+KPX J egrave -25
+KPX J emacron -25
+KPX J eogonek -25
+KPX J o -25
+KPX J oacute -25
+KPX J ocircumflex -25
+KPX J odieresis -25
+KPX J ograve -25
+KPX J ohungarumlaut -25
+KPX J omacron -25
+KPX J oslash -25
+KPX J otilde -25
+KPX J period -25
+KPX J u -35
+KPX J uacute -35
+KPX J ucircumflex -35
+KPX J udieresis -35
+KPX J ugrave -35
+KPX J uhungarumlaut -35
+KPX J umacron -35
+KPX J uogonek -35
+KPX J uring -35
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -35
+KPX K eacute -35
+KPX K ecaron -35
+KPX K ecircumflex -35
+KPX K edieresis -35
+KPX K edotaccent -35
+KPX K egrave -35
+KPX K emacron -35
+KPX K eogonek -35
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -40
+KPX K uacute -40
+KPX K ucircumflex -40
+KPX K udieresis -40
+KPX K ugrave -40
+KPX K uhungarumlaut -40
+KPX K umacron -40
+KPX K uogonek -40
+KPX K uring -40
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -35
+KPX Kcommaaccent eacute -35
+KPX Kcommaaccent ecaron -35
+KPX Kcommaaccent ecircumflex -35
+KPX Kcommaaccent edieresis -35
+KPX Kcommaaccent edotaccent -35
+KPX Kcommaaccent egrave -35
+KPX Kcommaaccent emacron -35
+KPX Kcommaaccent eogonek -35
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -40
+KPX Kcommaaccent uacute -40
+KPX Kcommaaccent ucircumflex -40
+KPX Kcommaaccent udieresis -40
+KPX Kcommaaccent ugrave -40
+KPX Kcommaaccent uhungarumlaut -40
+KPX Kcommaaccent umacron -40
+KPX Kcommaaccent uogonek -40
+KPX Kcommaaccent uring -40
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -20
+KPX L Tcaron -20
+KPX L Tcommaaccent -20
+KPX L V -55
+KPX L W -55
+KPX L Y -20
+KPX L Yacute -20
+KPX L Ydieresis -20
+KPX L quoteright -37
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -20
+KPX Lacute Tcaron -20
+KPX Lacute Tcommaaccent -20
+KPX Lacute V -55
+KPX Lacute W -55
+KPX Lacute Y -20
+KPX Lacute Yacute -20
+KPX Lacute Ydieresis -20
+KPX Lacute quoteright -37
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -20
+KPX Lcommaaccent Tcaron -20
+KPX Lcommaaccent Tcommaaccent -20
+KPX Lcommaaccent V -55
+KPX Lcommaaccent W -55
+KPX Lcommaaccent Y -20
+KPX Lcommaaccent Yacute -20
+KPX Lcommaaccent Ydieresis -20
+KPX Lcommaaccent quoteright -37
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -20
+KPX Lslash Tcaron -20
+KPX Lslash Tcommaaccent -20
+KPX Lslash V -55
+KPX Lslash W -55
+KPX Lslash Y -20
+KPX Lslash Yacute -20
+KPX Lslash Ydieresis -20
+KPX Lslash quoteright -37
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX N A -27
+KPX N Aacute -27
+KPX N Abreve -27
+KPX N Acircumflex -27
+KPX N Adieresis -27
+KPX N Agrave -27
+KPX N Amacron -27
+KPX N Aogonek -27
+KPX N Aring -27
+KPX N Atilde -27
+KPX Nacute A -27
+KPX Nacute Aacute -27
+KPX Nacute Abreve -27
+KPX Nacute Acircumflex -27
+KPX Nacute Adieresis -27
+KPX Nacute Agrave -27
+KPX Nacute Amacron -27
+KPX Nacute Aogonek -27
+KPX Nacute Aring -27
+KPX Nacute Atilde -27
+KPX Ncaron A -27
+KPX Ncaron Aacute -27
+KPX Ncaron Abreve -27
+KPX Ncaron Acircumflex -27
+KPX Ncaron Adieresis -27
+KPX Ncaron Agrave -27
+KPX Ncaron Amacron -27
+KPX Ncaron Aogonek -27
+KPX Ncaron Aring -27
+KPX Ncaron Atilde -27
+KPX Ncommaaccent A -27
+KPX Ncommaaccent Aacute -27
+KPX Ncommaaccent Abreve -27
+KPX Ncommaaccent Acircumflex -27
+KPX Ncommaaccent Adieresis -27
+KPX Ncommaaccent Agrave -27
+KPX Ncommaaccent Amacron -27
+KPX Ncommaaccent Aogonek -27
+KPX Ncommaaccent Aring -27
+KPX Ncommaaccent Atilde -27
+KPX Ntilde A -27
+KPX Ntilde Aacute -27
+KPX Ntilde Abreve -27
+KPX Ntilde Acircumflex -27
+KPX Ntilde Adieresis -27
+KPX Ntilde Agrave -27
+KPX Ntilde Amacron -27
+KPX Ntilde Aogonek -27
+KPX Ntilde Aring -27
+KPX Ntilde Atilde -27
+KPX O A -55
+KPX O Aacute -55
+KPX O Abreve -55
+KPX O Acircumflex -55
+KPX O Adieresis -55
+KPX O Agrave -55
+KPX O Amacron -55
+KPX O Aogonek -55
+KPX O Aring -55
+KPX O Atilde -55
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -55
+KPX Oacute Aacute -55
+KPX Oacute Abreve -55
+KPX Oacute Acircumflex -55
+KPX Oacute Adieresis -55
+KPX Oacute Agrave -55
+KPX Oacute Amacron -55
+KPX Oacute Aogonek -55
+KPX Oacute Aring -55
+KPX Oacute Atilde -55
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -55
+KPX Ocircumflex Aacute -55
+KPX Ocircumflex Abreve -55
+KPX Ocircumflex Acircumflex -55
+KPX Ocircumflex Adieresis -55
+KPX Ocircumflex Agrave -55
+KPX Ocircumflex Amacron -55
+KPX Ocircumflex Aogonek -55
+KPX Ocircumflex Aring -55
+KPX Ocircumflex Atilde -55
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -55
+KPX Odieresis Aacute -55
+KPX Odieresis Abreve -55
+KPX Odieresis Acircumflex -55
+KPX Odieresis Adieresis -55
+KPX Odieresis Agrave -55
+KPX Odieresis Amacron -55
+KPX Odieresis Aogonek -55
+KPX Odieresis Aring -55
+KPX Odieresis Atilde -55
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -55
+KPX Ograve Aacute -55
+KPX Ograve Abreve -55
+KPX Ograve Acircumflex -55
+KPX Ograve Adieresis -55
+KPX Ograve Agrave -55
+KPX Ograve Amacron -55
+KPX Ograve Aogonek -55
+KPX Ograve Aring -55
+KPX Ograve Atilde -55
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -55
+KPX Ohungarumlaut Aacute -55
+KPX Ohungarumlaut Abreve -55
+KPX Ohungarumlaut Acircumflex -55
+KPX Ohungarumlaut Adieresis -55
+KPX Ohungarumlaut Agrave -55
+KPX Ohungarumlaut Amacron -55
+KPX Ohungarumlaut Aogonek -55
+KPX Ohungarumlaut Aring -55
+KPX Ohungarumlaut Atilde -55
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -55
+KPX Omacron Aacute -55
+KPX Omacron Abreve -55
+KPX Omacron Acircumflex -55
+KPX Omacron Adieresis -55
+KPX Omacron Agrave -55
+KPX Omacron Amacron -55
+KPX Omacron Aogonek -55
+KPX Omacron Aring -55
+KPX Omacron Atilde -55
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -55
+KPX Oslash Aacute -55
+KPX Oslash Abreve -55
+KPX Oslash Acircumflex -55
+KPX Oslash Adieresis -55
+KPX Oslash Agrave -55
+KPX Oslash Amacron -55
+KPX Oslash Aogonek -55
+KPX Oslash Aring -55
+KPX Oslash Atilde -55
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -55
+KPX Otilde Aacute -55
+KPX Otilde Abreve -55
+KPX Otilde Acircumflex -55
+KPX Otilde Adieresis -55
+KPX Otilde Agrave -55
+KPX Otilde Amacron -55
+KPX Otilde Aogonek -55
+KPX Otilde Aring -55
+KPX Otilde Atilde -55
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -90
+KPX P Aacute -90
+KPX P Abreve -90
+KPX P Acircumflex -90
+KPX P Adieresis -90
+KPX P Agrave -90
+KPX P Amacron -90
+KPX P Aogonek -90
+KPX P Aring -90
+KPX P Atilde -90
+KPX P a -80
+KPX P aacute -80
+KPX P abreve -80
+KPX P acircumflex -80
+KPX P adieresis -80
+KPX P agrave -80
+KPX P amacron -80
+KPX P aogonek -80
+KPX P aring -80
+KPX P atilde -80
+KPX P comma -135
+KPX P e -80
+KPX P eacute -80
+KPX P ecaron -80
+KPX P ecircumflex -80
+KPX P edieresis -80
+KPX P edotaccent -80
+KPX P egrave -80
+KPX P emacron -80
+KPX P eogonek -80
+KPX P o -80
+KPX P oacute -80
+KPX P ocircumflex -80
+KPX P odieresis -80
+KPX P ograve -80
+KPX P ohungarumlaut -80
+KPX P omacron -80
+KPX P oslash -80
+KPX P otilde -80
+KPX P period -135
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -18
+KPX R W -18
+KPX R Y -18
+KPX R Yacute -18
+KPX R Ydieresis -18
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -18
+KPX Racute W -18
+KPX Racute Y -18
+KPX Racute Yacute -18
+KPX Racute Ydieresis -18
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -18
+KPX Rcaron W -18
+KPX Rcaron Y -18
+KPX Rcaron Yacute -18
+KPX Rcaron Ydieresis -18
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -18
+KPX Rcommaaccent W -18
+KPX Rcommaaccent Y -18
+KPX Rcommaaccent Yacute -18
+KPX Rcommaaccent Ydieresis -18
+KPX T A -50
+KPX T Aacute -50
+KPX T Abreve -50
+KPX T Acircumflex -50
+KPX T Adieresis -50
+KPX T Agrave -50
+KPX T Amacron -50
+KPX T Aogonek -50
+KPX T Aring -50
+KPX T Atilde -50
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -92
+KPX T acircumflex -92
+KPX T adieresis -92
+KPX T agrave -92
+KPX T amacron -92
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -92
+KPX T colon -55
+KPX T comma -74
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -52
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -74
+KPX T i -55
+KPX T iacute -55
+KPX T iogonek -55
+KPX T o -92
+KPX T oacute -92
+KPX T ocircumflex -92
+KPX T odieresis -92
+KPX T ograve -92
+KPX T ohungarumlaut -92
+KPX T omacron -92
+KPX T oslash -92
+KPX T otilde -92
+KPX T period -74
+KPX T r -55
+KPX T racute -55
+KPX T rcaron -55
+KPX T rcommaaccent -55
+KPX T semicolon -65
+KPX T u -55
+KPX T uacute -55
+KPX T ucircumflex -55
+KPX T udieresis -55
+KPX T ugrave -55
+KPX T uhungarumlaut -55
+KPX T umacron -55
+KPX T uogonek -55
+KPX T uring -55
+KPX T w -74
+KPX T y -74
+KPX T yacute -74
+KPX T ydieresis -34
+KPX Tcaron A -50
+KPX Tcaron Aacute -50
+KPX Tcaron Abreve -50
+KPX Tcaron Acircumflex -50
+KPX Tcaron Adieresis -50
+KPX Tcaron Agrave -50
+KPX Tcaron Amacron -50
+KPX Tcaron Aogonek -50
+KPX Tcaron Aring -50
+KPX Tcaron Atilde -50
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -92
+KPX Tcaron acircumflex -92
+KPX Tcaron adieresis -92
+KPX Tcaron agrave -92
+KPX Tcaron amacron -92
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -92
+KPX Tcaron colon -55
+KPX Tcaron comma -74
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -52
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -74
+KPX Tcaron i -55
+KPX Tcaron iacute -55
+KPX Tcaron iogonek -55
+KPX Tcaron o -92
+KPX Tcaron oacute -92
+KPX Tcaron ocircumflex -92
+KPX Tcaron odieresis -92
+KPX Tcaron ograve -92
+KPX Tcaron ohungarumlaut -92
+KPX Tcaron omacron -92
+KPX Tcaron oslash -92
+KPX Tcaron otilde -92
+KPX Tcaron period -74
+KPX Tcaron r -55
+KPX Tcaron racute -55
+KPX Tcaron rcaron -55
+KPX Tcaron rcommaaccent -55
+KPX Tcaron semicolon -65
+KPX Tcaron u -55
+KPX Tcaron uacute -55
+KPX Tcaron ucircumflex -55
+KPX Tcaron udieresis -55
+KPX Tcaron ugrave -55
+KPX Tcaron uhungarumlaut -55
+KPX Tcaron umacron -55
+KPX Tcaron uogonek -55
+KPX Tcaron uring -55
+KPX Tcaron w -74
+KPX Tcaron y -74
+KPX Tcaron yacute -74
+KPX Tcaron ydieresis -34
+KPX Tcommaaccent A -50
+KPX Tcommaaccent Aacute -50
+KPX Tcommaaccent Abreve -50
+KPX Tcommaaccent Acircumflex -50
+KPX Tcommaaccent Adieresis -50
+KPX Tcommaaccent Agrave -50
+KPX Tcommaaccent Amacron -50
+KPX Tcommaaccent Aogonek -50
+KPX Tcommaaccent Aring -50
+KPX Tcommaaccent Atilde -50
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -92
+KPX Tcommaaccent acircumflex -92
+KPX Tcommaaccent adieresis -92
+KPX Tcommaaccent agrave -92
+KPX Tcommaaccent amacron -92
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -92
+KPX Tcommaaccent colon -55
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -52
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -74
+KPX Tcommaaccent i -55
+KPX Tcommaaccent iacute -55
+KPX Tcommaaccent iogonek -55
+KPX Tcommaaccent o -92
+KPX Tcommaaccent oacute -92
+KPX Tcommaaccent ocircumflex -92
+KPX Tcommaaccent odieresis -92
+KPX Tcommaaccent ograve -92
+KPX Tcommaaccent ohungarumlaut -92
+KPX Tcommaaccent omacron -92
+KPX Tcommaaccent oslash -92
+KPX Tcommaaccent otilde -92
+KPX Tcommaaccent period -74
+KPX Tcommaaccent r -55
+KPX Tcommaaccent racute -55
+KPX Tcommaaccent rcaron -55
+KPX Tcommaaccent rcommaaccent -55
+KPX Tcommaaccent semicolon -65
+KPX Tcommaaccent u -55
+KPX Tcommaaccent uacute -55
+KPX Tcommaaccent ucircumflex -55
+KPX Tcommaaccent udieresis -55
+KPX Tcommaaccent ugrave -55
+KPX Tcommaaccent uhungarumlaut -55
+KPX Tcommaaccent umacron -55
+KPX Tcommaaccent uogonek -55
+KPX Tcommaaccent uring -55
+KPX Tcommaaccent w -74
+KPX Tcommaaccent y -74
+KPX Tcommaaccent yacute -74
+KPX Tcommaaccent ydieresis -34
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -25
+KPX U period -25
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -25
+KPX Uacute period -25
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -25
+KPX Ucircumflex period -25
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -25
+KPX Udieresis period -25
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -25
+KPX Ugrave period -25
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -25
+KPX Uhungarumlaut period -25
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -25
+KPX Umacron period -25
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -25
+KPX Uogonek period -25
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -25
+KPX Uring period -25
+KPX V A -60
+KPX V Aacute -60
+KPX V Abreve -60
+KPX V Acircumflex -60
+KPX V Adieresis -60
+KPX V Agrave -60
+KPX V Amacron -60
+KPX V Aogonek -60
+KPX V Aring -60
+KPX V Atilde -60
+KPX V O -30
+KPX V Oacute -30
+KPX V Ocircumflex -30
+KPX V Odieresis -30
+KPX V Ograve -30
+KPX V Ohungarumlaut -30
+KPX V Omacron -30
+KPX V Oslash -30
+KPX V Otilde -30
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -111
+KPX V adieresis -111
+KPX V agrave -111
+KPX V amacron -111
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -111
+KPX V colon -65
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -111
+KPX V ecircumflex -111
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -55
+KPX V i -74
+KPX V iacute -74
+KPX V icircumflex -34
+KPX V idieresis -34
+KPX V igrave -34
+KPX V imacron -34
+KPX V iogonek -74
+KPX V o -111
+KPX V oacute -111
+KPX V ocircumflex -111
+KPX V odieresis -111
+KPX V ograve -111
+KPX V ohungarumlaut -111
+KPX V omacron -111
+KPX V oslash -111
+KPX V otilde -111
+KPX V period -129
+KPX V semicolon -74
+KPX V u -74
+KPX V uacute -74
+KPX V ucircumflex -74
+KPX V udieresis -74
+KPX V ugrave -74
+KPX V uhungarumlaut -74
+KPX V umacron -74
+KPX V uogonek -74
+KPX V uring -74
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -25
+KPX W Oacute -25
+KPX W Ocircumflex -25
+KPX W Odieresis -25
+KPX W Ograve -25
+KPX W Ohungarumlaut -25
+KPX W Omacron -25
+KPX W Oslash -25
+KPX W Otilde -25
+KPX W a -92
+KPX W aacute -92
+KPX W abreve -92
+KPX W acircumflex -92
+KPX W adieresis -92
+KPX W agrave -92
+KPX W amacron -92
+KPX W aogonek -92
+KPX W aring -92
+KPX W atilde -92
+KPX W colon -65
+KPX W comma -92
+KPX W e -92
+KPX W eacute -92
+KPX W ecaron -92
+KPX W ecircumflex -92
+KPX W edieresis -52
+KPX W edotaccent -92
+KPX W egrave -52
+KPX W emacron -52
+KPX W eogonek -92
+KPX W hyphen -37
+KPX W i -55
+KPX W iacute -55
+KPX W iogonek -55
+KPX W o -92
+KPX W oacute -92
+KPX W ocircumflex -92
+KPX W odieresis -92
+KPX W ograve -92
+KPX W ohungarumlaut -92
+KPX W omacron -92
+KPX W oslash -92
+KPX W otilde -92
+KPX W period -92
+KPX W semicolon -65
+KPX W u -55
+KPX W uacute -55
+KPX W ucircumflex -55
+KPX W udieresis -55
+KPX W ugrave -55
+KPX W uhungarumlaut -55
+KPX W umacron -55
+KPX W uogonek -55
+KPX W uring -55
+KPX W y -70
+KPX W yacute -70
+KPX W ydieresis -70
+KPX Y A -50
+KPX Y Aacute -50
+KPX Y Abreve -50
+KPX Y Acircumflex -50
+KPX Y Adieresis -50
+KPX Y Agrave -50
+KPX Y Amacron -50
+KPX Y Aogonek -50
+KPX Y Aring -50
+KPX Y Atilde -50
+KPX Y O -15
+KPX Y Oacute -15
+KPX Y Ocircumflex -15
+KPX Y Odieresis -15
+KPX Y Ograve -15
+KPX Y Ohungarumlaut -15
+KPX Y Omacron -15
+KPX Y Oslash -15
+KPX Y Otilde -15
+KPX Y a -92
+KPX Y aacute -92
+KPX Y abreve -92
+KPX Y acircumflex -92
+KPX Y adieresis -92
+KPX Y agrave -92
+KPX Y amacron -92
+KPX Y aogonek -92
+KPX Y aring -92
+KPX Y atilde -92
+KPX Y colon -65
+KPX Y comma -92
+KPX Y e -92
+KPX Y eacute -92
+KPX Y ecaron -92
+KPX Y ecircumflex -92
+KPX Y edieresis -52
+KPX Y edotaccent -92
+KPX Y egrave -52
+KPX Y emacron -52
+KPX Y eogonek -92
+KPX Y hyphen -74
+KPX Y i -74
+KPX Y iacute -74
+KPX Y icircumflex -34
+KPX Y idieresis -34
+KPX Y igrave -34
+KPX Y imacron -34
+KPX Y iogonek -74
+KPX Y o -92
+KPX Y oacute -92
+KPX Y ocircumflex -92
+KPX Y odieresis -92
+KPX Y ograve -92
+KPX Y ohungarumlaut -92
+KPX Y omacron -92
+KPX Y oslash -92
+KPX Y otilde -92
+KPX Y period -92
+KPX Y semicolon -65
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -50
+KPX Yacute Aacute -50
+KPX Yacute Abreve -50
+KPX Yacute Acircumflex -50
+KPX Yacute Adieresis -50
+KPX Yacute Agrave -50
+KPX Yacute Amacron -50
+KPX Yacute Aogonek -50
+KPX Yacute Aring -50
+KPX Yacute Atilde -50
+KPX Yacute O -15
+KPX Yacute Oacute -15
+KPX Yacute Ocircumflex -15
+KPX Yacute Odieresis -15
+KPX Yacute Ograve -15
+KPX Yacute Ohungarumlaut -15
+KPX Yacute Omacron -15
+KPX Yacute Oslash -15
+KPX Yacute Otilde -15
+KPX Yacute a -92
+KPX Yacute aacute -92
+KPX Yacute abreve -92
+KPX Yacute acircumflex -92
+KPX Yacute adieresis -92
+KPX Yacute agrave -92
+KPX Yacute amacron -92
+KPX Yacute aogonek -92
+KPX Yacute aring -92
+KPX Yacute atilde -92
+KPX Yacute colon -65
+KPX Yacute comma -92
+KPX Yacute e -92
+KPX Yacute eacute -92
+KPX Yacute ecaron -92
+KPX Yacute ecircumflex -92
+KPX Yacute edieresis -52
+KPX Yacute edotaccent -92
+KPX Yacute egrave -52
+KPX Yacute emacron -52
+KPX Yacute eogonek -92
+KPX Yacute hyphen -74
+KPX Yacute i -74
+KPX Yacute iacute -74
+KPX Yacute icircumflex -34
+KPX Yacute idieresis -34
+KPX Yacute igrave -34
+KPX Yacute imacron -34
+KPX Yacute iogonek -74
+KPX Yacute o -92
+KPX Yacute oacute -92
+KPX Yacute ocircumflex -92
+KPX Yacute odieresis -92
+KPX Yacute ograve -92
+KPX Yacute ohungarumlaut -92
+KPX Yacute omacron -92
+KPX Yacute oslash -92
+KPX Yacute otilde -92
+KPX Yacute period -92
+KPX Yacute semicolon -65
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -50
+KPX Ydieresis Aacute -50
+KPX Ydieresis Abreve -50
+KPX Ydieresis Acircumflex -50
+KPX Ydieresis Adieresis -50
+KPX Ydieresis Agrave -50
+KPX Ydieresis Amacron -50
+KPX Ydieresis Aogonek -50
+KPX Ydieresis Aring -50
+KPX Ydieresis Atilde -50
+KPX Ydieresis O -15
+KPX Ydieresis Oacute -15
+KPX Ydieresis Ocircumflex -15
+KPX Ydieresis Odieresis -15
+KPX Ydieresis Ograve -15
+KPX Ydieresis Ohungarumlaut -15
+KPX Ydieresis Omacron -15
+KPX Ydieresis Oslash -15
+KPX Ydieresis Otilde -15
+KPX Ydieresis a -92
+KPX Ydieresis aacute -92
+KPX Ydieresis abreve -92
+KPX Ydieresis acircumflex -92
+KPX Ydieresis adieresis -92
+KPX Ydieresis agrave -92
+KPX Ydieresis amacron -92
+KPX Ydieresis aogonek -92
+KPX Ydieresis aring -92
+KPX Ydieresis atilde -92
+KPX Ydieresis colon -65
+KPX Ydieresis comma -92
+KPX Ydieresis e -92
+KPX Ydieresis eacute -92
+KPX Ydieresis ecaron -92
+KPX Ydieresis ecircumflex -92
+KPX Ydieresis edieresis -52
+KPX Ydieresis edotaccent -92
+KPX Ydieresis egrave -52
+KPX Ydieresis emacron -52
+KPX Ydieresis eogonek -92
+KPX Ydieresis hyphen -74
+KPX Ydieresis i -74
+KPX Ydieresis iacute -74
+KPX Ydieresis icircumflex -34
+KPX Ydieresis idieresis -34
+KPX Ydieresis igrave -34
+KPX Ydieresis imacron -34
+KPX Ydieresis iogonek -74
+KPX Ydieresis o -92
+KPX Ydieresis oacute -92
+KPX Ydieresis ocircumflex -92
+KPX Ydieresis odieresis -92
+KPX Ydieresis ograve -92
+KPX Ydieresis ohungarumlaut -92
+KPX Ydieresis omacron -92
+KPX Ydieresis oslash -92
+KPX Ydieresis otilde -92
+KPX Ydieresis period -92
+KPX Ydieresis semicolon -65
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX c h -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute h -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron h -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla h -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX comma quotedblright -140
+KPX comma quoteright -140
+KPX e comma -10
+KPX e g -40
+KPX e gbreve -40
+KPX e gcommaaccent -40
+KPX e period -15
+KPX e v -15
+KPX e w -15
+KPX e x -20
+KPX e y -30
+KPX e yacute -30
+KPX e ydieresis -30
+KPX eacute comma -10
+KPX eacute g -40
+KPX eacute gbreve -40
+KPX eacute gcommaaccent -40
+KPX eacute period -15
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -20
+KPX eacute y -30
+KPX eacute yacute -30
+KPX eacute ydieresis -30
+KPX ecaron comma -10
+KPX ecaron g -40
+KPX ecaron gbreve -40
+KPX ecaron gcommaaccent -40
+KPX ecaron period -15
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -20
+KPX ecaron y -30
+KPX ecaron yacute -30
+KPX ecaron ydieresis -30
+KPX ecircumflex comma -10
+KPX ecircumflex g -40
+KPX ecircumflex gbreve -40
+KPX ecircumflex gcommaaccent -40
+KPX ecircumflex period -15
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -20
+KPX ecircumflex y -30
+KPX ecircumflex yacute -30
+KPX ecircumflex ydieresis -30
+KPX edieresis comma -10
+KPX edieresis g -40
+KPX edieresis gbreve -40
+KPX edieresis gcommaaccent -40
+KPX edieresis period -15
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -20
+KPX edieresis y -30
+KPX edieresis yacute -30
+KPX edieresis ydieresis -30
+KPX edotaccent comma -10
+KPX edotaccent g -40
+KPX edotaccent gbreve -40
+KPX edotaccent gcommaaccent -40
+KPX edotaccent period -15
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -20
+KPX edotaccent y -30
+KPX edotaccent yacute -30
+KPX edotaccent ydieresis -30
+KPX egrave comma -10
+KPX egrave g -40
+KPX egrave gbreve -40
+KPX egrave gcommaaccent -40
+KPX egrave period -15
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -20
+KPX egrave y -30
+KPX egrave yacute -30
+KPX egrave ydieresis -30
+KPX emacron comma -10
+KPX emacron g -40
+KPX emacron gbreve -40
+KPX emacron gcommaaccent -40
+KPX emacron period -15
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -20
+KPX emacron y -30
+KPX emacron yacute -30
+KPX emacron ydieresis -30
+KPX eogonek comma -10
+KPX eogonek g -40
+KPX eogonek gbreve -40
+KPX eogonek gcommaaccent -40
+KPX eogonek period -15
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -20
+KPX eogonek y -30
+KPX eogonek yacute -30
+KPX eogonek ydieresis -30
+KPX f comma -10
+KPX f dotlessi -60
+KPX f f -18
+KPX f i -20
+KPX f iogonek -20
+KPX f period -15
+KPX f quoteright 92
+KPX g comma -10
+KPX g e -10
+KPX g eacute -10
+KPX g ecaron -10
+KPX g ecircumflex -10
+KPX g edieresis -10
+KPX g edotaccent -10
+KPX g egrave -10
+KPX g emacron -10
+KPX g eogonek -10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX g period -15
+KPX gbreve comma -10
+KPX gbreve e -10
+KPX gbreve eacute -10
+KPX gbreve ecaron -10
+KPX gbreve ecircumflex -10
+KPX gbreve edieresis -10
+KPX gbreve edotaccent -10
+KPX gbreve egrave -10
+KPX gbreve emacron -10
+KPX gbreve eogonek -10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gbreve period -15
+KPX gcommaaccent comma -10
+KPX gcommaaccent e -10
+KPX gcommaaccent eacute -10
+KPX gcommaaccent ecaron -10
+KPX gcommaaccent ecircumflex -10
+KPX gcommaaccent edieresis -10
+KPX gcommaaccent edotaccent -10
+KPX gcommaaccent egrave -10
+KPX gcommaaccent emacron -10
+KPX gcommaaccent eogonek -10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX gcommaaccent period -15
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX k y -10
+KPX k yacute -10
+KPX k ydieresis -10
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX kcommaaccent y -10
+KPX kcommaaccent yacute -10
+KPX kcommaaccent ydieresis -10
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o g -10
+KPX o gbreve -10
+KPX o gcommaaccent -10
+KPX o v -10
+KPX oacute g -10
+KPX oacute gbreve -10
+KPX oacute gcommaaccent -10
+KPX oacute v -10
+KPX ocircumflex g -10
+KPX ocircumflex gbreve -10
+KPX ocircumflex gcommaaccent -10
+KPX ocircumflex v -10
+KPX odieresis g -10
+KPX odieresis gbreve -10
+KPX odieresis gcommaaccent -10
+KPX odieresis v -10
+KPX ograve g -10
+KPX ograve gbreve -10
+KPX ograve gcommaaccent -10
+KPX ograve v -10
+KPX ohungarumlaut g -10
+KPX ohungarumlaut gbreve -10
+KPX ohungarumlaut gcommaaccent -10
+KPX ohungarumlaut v -10
+KPX omacron g -10
+KPX omacron gbreve -10
+KPX omacron gcommaaccent -10
+KPX omacron v -10
+KPX oslash g -10
+KPX oslash gbreve -10
+KPX oslash gcommaaccent -10
+KPX oslash v -10
+KPX otilde g -10
+KPX otilde gbreve -10
+KPX otilde gcommaaccent -10
+KPX otilde v -10
+KPX period quotedblright -140
+KPX period quoteright -140
+KPX quoteleft quoteleft -111
+KPX quoteright d -25
+KPX quoteright dcroat -25
+KPX quoteright quoteright -111
+KPX quoteright r -25
+KPX quoteright racute -25
+KPX quoteright rcaron -25
+KPX quoteright rcommaaccent -25
+KPX quoteright s -40
+KPX quoteright sacute -40
+KPX quoteright scaron -40
+KPX quoteright scedilla -40
+KPX quoteright scommaaccent -40
+KPX quoteright space -111
+KPX quoteright t -30
+KPX quoteright tcommaaccent -30
+KPX quoteright v -10
+KPX r a -15
+KPX r aacute -15
+KPX r abreve -15
+KPX r acircumflex -15
+KPX r adieresis -15
+KPX r agrave -15
+KPX r amacron -15
+KPX r aogonek -15
+KPX r aring -15
+KPX r atilde -15
+KPX r c -37
+KPX r cacute -37
+KPX r ccaron -37
+KPX r ccedilla -37
+KPX r comma -111
+KPX r d -37
+KPX r dcroat -37
+KPX r e -37
+KPX r eacute -37
+KPX r ecaron -37
+KPX r ecircumflex -37
+KPX r edieresis -37
+KPX r edotaccent -37
+KPX r egrave -37
+KPX r emacron -37
+KPX r eogonek -37
+KPX r g -37
+KPX r gbreve -37
+KPX r gcommaaccent -37
+KPX r hyphen -20
+KPX r o -45
+KPX r oacute -45
+KPX r ocircumflex -45
+KPX r odieresis -45
+KPX r ograve -45
+KPX r ohungarumlaut -45
+KPX r omacron -45
+KPX r oslash -45
+KPX r otilde -45
+KPX r period -111
+KPX r q -37
+KPX r s -10
+KPX r sacute -10
+KPX r scaron -10
+KPX r scedilla -10
+KPX r scommaaccent -10
+KPX racute a -15
+KPX racute aacute -15
+KPX racute abreve -15
+KPX racute acircumflex -15
+KPX racute adieresis -15
+KPX racute agrave -15
+KPX racute amacron -15
+KPX racute aogonek -15
+KPX racute aring -15
+KPX racute atilde -15
+KPX racute c -37
+KPX racute cacute -37
+KPX racute ccaron -37
+KPX racute ccedilla -37
+KPX racute comma -111
+KPX racute d -37
+KPX racute dcroat -37
+KPX racute e -37
+KPX racute eacute -37
+KPX racute ecaron -37
+KPX racute ecircumflex -37
+KPX racute edieresis -37
+KPX racute edotaccent -37
+KPX racute egrave -37
+KPX racute emacron -37
+KPX racute eogonek -37
+KPX racute g -37
+KPX racute gbreve -37
+KPX racute gcommaaccent -37
+KPX racute hyphen -20
+KPX racute o -45
+KPX racute oacute -45
+KPX racute ocircumflex -45
+KPX racute odieresis -45
+KPX racute ograve -45
+KPX racute ohungarumlaut -45
+KPX racute omacron -45
+KPX racute oslash -45
+KPX racute otilde -45
+KPX racute period -111
+KPX racute q -37
+KPX racute s -10
+KPX racute sacute -10
+KPX racute scaron -10
+KPX racute scedilla -10
+KPX racute scommaaccent -10
+KPX rcaron a -15
+KPX rcaron aacute -15
+KPX rcaron abreve -15
+KPX rcaron acircumflex -15
+KPX rcaron adieresis -15
+KPX rcaron agrave -15
+KPX rcaron amacron -15
+KPX rcaron aogonek -15
+KPX rcaron aring -15
+KPX rcaron atilde -15
+KPX rcaron c -37
+KPX rcaron cacute -37
+KPX rcaron ccaron -37
+KPX rcaron ccedilla -37
+KPX rcaron comma -111
+KPX rcaron d -37
+KPX rcaron dcroat -37
+KPX rcaron e -37
+KPX rcaron eacute -37
+KPX rcaron ecaron -37
+KPX rcaron ecircumflex -37
+KPX rcaron edieresis -37
+KPX rcaron edotaccent -37
+KPX rcaron egrave -37
+KPX rcaron emacron -37
+KPX rcaron eogonek -37
+KPX rcaron g -37
+KPX rcaron gbreve -37
+KPX rcaron gcommaaccent -37
+KPX rcaron hyphen -20
+KPX rcaron o -45
+KPX rcaron oacute -45
+KPX rcaron ocircumflex -45
+KPX rcaron odieresis -45
+KPX rcaron ograve -45
+KPX rcaron ohungarumlaut -45
+KPX rcaron omacron -45
+KPX rcaron oslash -45
+KPX rcaron otilde -45
+KPX rcaron period -111
+KPX rcaron q -37
+KPX rcaron s -10
+KPX rcaron sacute -10
+KPX rcaron scaron -10
+KPX rcaron scedilla -10
+KPX rcaron scommaaccent -10
+KPX rcommaaccent a -15
+KPX rcommaaccent aacute -15
+KPX rcommaaccent abreve -15
+KPX rcommaaccent acircumflex -15
+KPX rcommaaccent adieresis -15
+KPX rcommaaccent agrave -15
+KPX rcommaaccent amacron -15
+KPX rcommaaccent aogonek -15
+KPX rcommaaccent aring -15
+KPX rcommaaccent atilde -15
+KPX rcommaaccent c -37
+KPX rcommaaccent cacute -37
+KPX rcommaaccent ccaron -37
+KPX rcommaaccent ccedilla -37
+KPX rcommaaccent comma -111
+KPX rcommaaccent d -37
+KPX rcommaaccent dcroat -37
+KPX rcommaaccent e -37
+KPX rcommaaccent eacute -37
+KPX rcommaaccent ecaron -37
+KPX rcommaaccent ecircumflex -37
+KPX rcommaaccent edieresis -37
+KPX rcommaaccent edotaccent -37
+KPX rcommaaccent egrave -37
+KPX rcommaaccent emacron -37
+KPX rcommaaccent eogonek -37
+KPX rcommaaccent g -37
+KPX rcommaaccent gbreve -37
+KPX rcommaaccent gcommaaccent -37
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -45
+KPX rcommaaccent oacute -45
+KPX rcommaaccent ocircumflex -45
+KPX rcommaaccent odieresis -45
+KPX rcommaaccent ograve -45
+KPX rcommaaccent ohungarumlaut -45
+KPX rcommaaccent omacron -45
+KPX rcommaaccent oslash -45
+KPX rcommaaccent otilde -45
+KPX rcommaaccent period -111
+KPX rcommaaccent q -37
+KPX rcommaaccent s -10
+KPX rcommaaccent sacute -10
+KPX rcommaaccent scaron -10
+KPX rcommaaccent scedilla -10
+KPX rcommaaccent scommaaccent -10
+KPX space A -18
+KPX space Aacute -18
+KPX space Abreve -18
+KPX space Acircumflex -18
+KPX space Adieresis -18
+KPX space Agrave -18
+KPX space Amacron -18
+KPX space Aogonek -18
+KPX space Aring -18
+KPX space Atilde -18
+KPX space T -18
+KPX space Tcaron -18
+KPX space Tcommaaccent -18
+KPX space V -35
+KPX space W -40
+KPX space Y -75
+KPX space Yacute -75
+KPX space Ydieresis -75
+KPX v comma -74
+KPX v period -74
+KPX w comma -74
+KPX w period -74
+KPX y comma -55
+KPX y period -55
+KPX yacute comma -55
+KPX yacute period -55
+KPX ydieresis comma -55
+KPX ydieresis period -55
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/Times-Roman.afm b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Roman.afm
new file mode 100644
index 0000000..3e17e5e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/Times-Roman.afm
@@ -0,0 +1,2420 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.
+Comment Creation Date: Thu May  1 12:49:17 1997
+Comment UniqueID 43068
+Comment VMusage 43909 54934
+FontName Times-Roman
+FullName Times Roman
+FamilyName Times
+Weight Roman
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -168 -218 1000 898 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.  All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 662
+XHeight 450
+Ascender 683
+Descender -217
+StdHW 28
+StdVW 84
+StartCharMetrics 315
+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 -218 133 782 ;
+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 581 216 681 ;
+C 200 ; WX 333 ; N dieresis ; B 18 581 315 681 ;
+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 62 -165 243 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 333 ; N Idieresis ; B 18 0 315 835 ;
+C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ;
+C -1 ; WX 444 ; N abreve ; B 37 -10 442 664 ;
+C -1 ; WX 500 ; N uhungarumlaut ; B 9 -10 501 678 ;
+C -1 ; WX 444 ; N ecaron ; B 25 -10 424 674 ;
+C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ;
+C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ;
+C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ;
+C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ;
+C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ;
+C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ;
+C -1 ; WX 389 ; N scommaaccent ; B 51 -218 348 460 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ;
+C -1 ; WX 722 ; N Uring ; B 14 -14 705 898 ;
+C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ;
+C -1 ; WX 444 ; N aogonek ; B 37 -165 469 460 ;
+C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ;
+C -1 ; WX 500 ; N uogonek ; B 9 -155 487 450 ;
+C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ;
+C -1 ; WX 722 ; N Dcroat ; B 16 0 685 662 ;
+C -1 ; WX 250 ; N commaaccent ; B 59 -218 184 -50 ;
+C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ;
+C -1 ; WX 611 ; N Emacron ; B 12 0 597 813 ;
+C -1 ; WX 444 ; N ccaron ; B 25 -10 412 674 ;
+C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 12 -198 707 662 ;
+C -1 ; WX 278 ; N lacute ; B 19 0 290 890 ;
+C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 17 -218 593 662 ;
+C -1 ; WX 667 ; N Cacute ; B 28 -14 633 890 ;
+C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ;
+C -1 ; WX 611 ; N Edotaccent ; B 12 0 597 835 ;
+C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ;
+C -1 ; WX 389 ; N scedilla ; B 51 -215 348 460 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ;
+C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
+C -1 ; WX 667 ; N Rcaron ; B 17 0 659 886 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 32 -218 709 676 ;
+C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ;
+C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ;
+C -1 ; WX 722 ; N Amacron ; B 15 0 706 813 ;
+C -1 ; WX 333 ; N rcaron ; B 5 0 335 674 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 9 0 597 835 ;
+C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ;
+C -1 ; WX 722 ; N Omacron ; B 34 -14 688 813 ;
+C -1 ; WX 667 ; N Racute ; B 17 0 659 890 ;
+C -1 ; WX 556 ; N Sacute ; B 42 -14 491 890 ;
+C -1 ; WX 588 ; N dcaron ; B 27 -10 589 695 ;
+C -1 ; WX 722 ; N Umacron ; B 14 -14 705 813 ;
+C -1 ; WX 500 ; N uring ; B 9 -10 479 711 ;
+C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ;
+C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ;
+C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ;
+C -1 ; WX 722 ; N Abreve ; B 15 0 706 876 ;
+C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ;
+C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ;
+C -1 ; WX 611 ; N Tcaron ; B 17 0 593 886 ;
+C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ;
+C -1 ; WX 722 ; N Nacute ; B 12 -11 707 890 ;
+C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ;
+C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ;
+C -1 ; WX 444 ; N cacute ; B 25 -10 413 678 ;
+C -1 ; WX 500 ; N nacute ; B 16 0 485 678 ;
+C -1 ; WX 500 ; N umacron ; B 9 -10 479 601 ;
+C -1 ; WX 722 ; N Ncaron ; B 12 -11 707 886 ;
+C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ;
+C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ;
+C -1 ; WX 200 ; N brokenbar ; B 67 -143 133 707 ;
+C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ;
+C -1 ; WX 722 ; N Gbreve ; B 32 -14 709 876 ;
+C -1 ; WX 333 ; N Idotaccent ; B 18 0 315 835 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ;
+C -1 ; WX 333 ; N racute ; B 5 0 335 678 ;
+C -1 ; WX 500 ; N omacron ; B 29 -10 470 601 ;
+C -1 ; WX 611 ; N Zacute ; B 9 0 597 890 ;
+C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 666 ;
+C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ;
+C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 19 -218 257 683 ;
+C -1 ; WX 326 ; N tcaron ; B 13 -10 318 722 ;
+C -1 ; WX 444 ; N eogonek ; B 25 -165 424 460 ;
+C -1 ; WX 722 ; N Uogonek ; B 14 -165 705 662 ;
+C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ;
+C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ;
+C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ;
+C -1 ; WX 444 ; N zacute ; B 27 0 418 678 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -165 265 683 ;
+C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ;
+C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ;
+C -1 ; WX 444 ; N amacron ; B 37 -10 442 601 ;
+C -1 ; WX 389 ; N sacute ; B 51 -10 348 678 ;
+C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ;
+C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ;
+C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ;
+C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ;
+C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ;
+C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 29 -10 491 678 ;
+C -1 ; WX 611 ; N Eogonek ; B 12 -165 597 662 ;
+C -1 ; WX 500 ; N dcroat ; B 27 -10 500 683 ;
+C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ;
+C -1 ; WX 556 ; N Scedilla ; B 42 -215 491 676 ;
+C -1 ; WX 344 ; N lcaron ; B 19 0 347 695 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 34 -198 723 662 ;
+C -1 ; WX 611 ; N Lacute ; B 12 0 598 890 ;
+C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ;
+C -1 ; WX 444 ; N edotaccent ; B 25 -10 424 623 ;
+C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ;
+C -1 ; WX 333 ; N Imacron ; B 11 0 322 813 ;
+C -1 ; WX 611 ; N Lcaron ; B 12 0 598 676 ;
+C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 666 ;
+C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ;
+C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 14 -14 705 890 ;
+C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ;
+C -1 ; WX 444 ; N emacron ; B 25 -10 424 601 ;
+C -1 ; WX 500 ; N gbreve ; B 28 -218 470 664 ;
+C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ;
+C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 42 -218 491 676 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 34 -14 688 890 ;
+C -1 ; WX 400 ; N degree ; B 57 390 343 676 ;
+C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ;
+C -1 ; WX 667 ; N Ccaron ; B 28 -14 633 886 ;
+C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ;
+C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
+C -1 ; WX 722 ; N Dcaron ; B 16 0 685 886 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 5 -218 335 460 ;
+C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ;
+C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ;
+C -1 ; WX 667 ; N Rcommaaccent ; B 17 -198 659 662 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 12 -218 598 662 ;
+C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ;
+C -1 ; WX 722 ; N Aogonek ; B 15 -165 738 674 ;
+C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ;
+C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ;
+C -1 ; WX 444 ; N zdotaccent ; B 27 0 418 623 ;
+C -1 ; WX 611 ; N Ecaron ; B 12 0 597 886 ;
+C -1 ; WX 333 ; N Iogonek ; B 18 -165 315 662 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 7 -218 505 683 ;
+C -1 ; WX 564 ; N minus ; B 30 220 534 286 ;
+C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ;
+C -1 ; WX 500 ; N ncaron ; B 16 0 485 674 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 13 -218 279 579 ;
+C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ;
+C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ;
+C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ;
+C -1 ; WX 549 ; N notequal ; B 12 -31 537 547 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 28 -218 470 749 ;
+C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ;
+C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ;
+C -1 ; WX 500 ; N ncommaaccent ; B 16 -218 485 460 ;
+C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ;
+C -1 ; WX 278 ; N imacron ; B 6 0 271 601 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2073
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -40
+KPX A Gbreve -40
+KPX A Gcommaaccent -40
+KPX A O -55
+KPX A Oacute -55
+KPX A Ocircumflex -55
+KPX A Odieresis -55
+KPX A Ograve -55
+KPX A Ohungarumlaut -55
+KPX A Omacron -55
+KPX A Oslash -55
+KPX A Otilde -55
+KPX A Q -55
+KPX A T -111
+KPX A Tcaron -111
+KPX A Tcommaaccent -111
+KPX A U -55
+KPX A Uacute -55
+KPX A Ucircumflex -55
+KPX A Udieresis -55
+KPX A Ugrave -55
+KPX A Uhungarumlaut -55
+KPX A Umacron -55
+KPX A Uogonek -55
+KPX A Uring -55
+KPX A V -135
+KPX A W -90
+KPX A Y -105
+KPX A Yacute -105
+KPX A Ydieresis -105
+KPX A quoteright -111
+KPX A v -74
+KPX A w -92
+KPX A y -92
+KPX A yacute -92
+KPX A ydieresis -92
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -40
+KPX Aacute Gbreve -40
+KPX Aacute Gcommaaccent -40
+KPX Aacute O -55
+KPX Aacute Oacute -55
+KPX Aacute Ocircumflex -55
+KPX Aacute Odieresis -55
+KPX Aacute Ograve -55
+KPX Aacute Ohungarumlaut -55
+KPX Aacute Omacron -55
+KPX Aacute Oslash -55
+KPX Aacute Otilde -55
+KPX Aacute Q -55
+KPX Aacute T -111
+KPX Aacute Tcaron -111
+KPX Aacute Tcommaaccent -111
+KPX Aacute U -55
+KPX Aacute Uacute -55
+KPX Aacute Ucircumflex -55
+KPX Aacute Udieresis -55
+KPX Aacute Ugrave -55
+KPX Aacute Uhungarumlaut -55
+KPX Aacute Umacron -55
+KPX Aacute Uogonek -55
+KPX Aacute Uring -55
+KPX Aacute V -135
+KPX Aacute W -90
+KPX Aacute Y -105
+KPX Aacute Yacute -105
+KPX Aacute Ydieresis -105
+KPX Aacute quoteright -111
+KPX Aacute v -74
+KPX Aacute w -92
+KPX Aacute y -92
+KPX Aacute yacute -92
+KPX Aacute ydieresis -92
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -40
+KPX Abreve Gbreve -40
+KPX Abreve Gcommaaccent -40
+KPX Abreve O -55
+KPX Abreve Oacute -55
+KPX Abreve Ocircumflex -55
+KPX Abreve Odieresis -55
+KPX Abreve Ograve -55
+KPX Abreve Ohungarumlaut -55
+KPX Abreve Omacron -55
+KPX Abreve Oslash -55
+KPX Abreve Otilde -55
+KPX Abreve Q -55
+KPX Abreve T -111
+KPX Abreve Tcaron -111
+KPX Abreve Tcommaaccent -111
+KPX Abreve U -55
+KPX Abreve Uacute -55
+KPX Abreve Ucircumflex -55
+KPX Abreve Udieresis -55
+KPX Abreve Ugrave -55
+KPX Abreve Uhungarumlaut -55
+KPX Abreve Umacron -55
+KPX Abreve Uogonek -55
+KPX Abreve Uring -55
+KPX Abreve V -135
+KPX Abreve W -90
+KPX Abreve Y -105
+KPX Abreve Yacute -105
+KPX Abreve Ydieresis -105
+KPX Abreve quoteright -111
+KPX Abreve v -74
+KPX Abreve w -92
+KPX Abreve y -92
+KPX Abreve yacute -92
+KPX Abreve ydieresis -92
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -40
+KPX Acircumflex Gbreve -40
+KPX Acircumflex Gcommaaccent -40
+KPX Acircumflex O -55
+KPX Acircumflex Oacute -55
+KPX Acircumflex Ocircumflex -55
+KPX Acircumflex Odieresis -55
+KPX Acircumflex Ograve -55
+KPX Acircumflex Ohungarumlaut -55
+KPX Acircumflex Omacron -55
+KPX Acircumflex Oslash -55
+KPX Acircumflex Otilde -55
+KPX Acircumflex Q -55
+KPX Acircumflex T -111
+KPX Acircumflex Tcaron -111
+KPX Acircumflex Tcommaaccent -111
+KPX Acircumflex U -55
+KPX Acircumflex Uacute -55
+KPX Acircumflex Ucircumflex -55
+KPX Acircumflex Udieresis -55
+KPX Acircumflex Ugrave -55
+KPX Acircumflex Uhungarumlaut -55
+KPX Acircumflex Umacron -55
+KPX Acircumflex Uogonek -55
+KPX Acircumflex Uring -55
+KPX Acircumflex V -135
+KPX Acircumflex W -90
+KPX Acircumflex Y -105
+KPX Acircumflex Yacute -105
+KPX Acircumflex Ydieresis -105
+KPX Acircumflex quoteright -111
+KPX Acircumflex v -74
+KPX Acircumflex w -92
+KPX Acircumflex y -92
+KPX Acircumflex yacute -92
+KPX Acircumflex ydieresis -92
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -40
+KPX Adieresis Gbreve -40
+KPX Adieresis Gcommaaccent -40
+KPX Adieresis O -55
+KPX Adieresis Oacute -55
+KPX Adieresis Ocircumflex -55
+KPX Adieresis Odieresis -55
+KPX Adieresis Ograve -55
+KPX Adieresis Ohungarumlaut -55
+KPX Adieresis Omacron -55
+KPX Adieresis Oslash -55
+KPX Adieresis Otilde -55
+KPX Adieresis Q -55
+KPX Adieresis T -111
+KPX Adieresis Tcaron -111
+KPX Adieresis Tcommaaccent -111
+KPX Adieresis U -55
+KPX Adieresis Uacute -55
+KPX Adieresis Ucircumflex -55
+KPX Adieresis Udieresis -55
+KPX Adieresis Ugrave -55
+KPX Adieresis Uhungarumlaut -55
+KPX Adieresis Umacron -55
+KPX Adieresis Uogonek -55
+KPX Adieresis Uring -55
+KPX Adieresis V -135
+KPX Adieresis W -90
+KPX Adieresis Y -105
+KPX Adieresis Yacute -105
+KPX Adieresis Ydieresis -105
+KPX Adieresis quoteright -111
+KPX Adieresis v -74
+KPX Adieresis w -92
+KPX Adieresis y -92
+KPX Adieresis yacute -92
+KPX Adieresis ydieresis -92
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -40
+KPX Agrave Gbreve -40
+KPX Agrave Gcommaaccent -40
+KPX Agrave O -55
+KPX Agrave Oacute -55
+KPX Agrave Ocircumflex -55
+KPX Agrave Odieresis -55
+KPX Agrave Ograve -55
+KPX Agrave Ohungarumlaut -55
+KPX Agrave Omacron -55
+KPX Agrave Oslash -55
+KPX Agrave Otilde -55
+KPX Agrave Q -55
+KPX Agrave T -111
+KPX Agrave Tcaron -111
+KPX Agrave Tcommaaccent -111
+KPX Agrave U -55
+KPX Agrave Uacute -55
+KPX Agrave Ucircumflex -55
+KPX Agrave Udieresis -55
+KPX Agrave Ugrave -55
+KPX Agrave Uhungarumlaut -55
+KPX Agrave Umacron -55
+KPX Agrave Uogonek -55
+KPX Agrave Uring -55
+KPX Agrave V -135
+KPX Agrave W -90
+KPX Agrave Y -105
+KPX Agrave Yacute -105
+KPX Agrave Ydieresis -105
+KPX Agrave quoteright -111
+KPX Agrave v -74
+KPX Agrave w -92
+KPX Agrave y -92
+KPX Agrave yacute -92
+KPX Agrave ydieresis -92
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -40
+KPX Amacron Gbreve -40
+KPX Amacron Gcommaaccent -40
+KPX Amacron O -55
+KPX Amacron Oacute -55
+KPX Amacron Ocircumflex -55
+KPX Amacron Odieresis -55
+KPX Amacron Ograve -55
+KPX Amacron Ohungarumlaut -55
+KPX Amacron Omacron -55
+KPX Amacron Oslash -55
+KPX Amacron Otilde -55
+KPX Amacron Q -55
+KPX Amacron T -111
+KPX Amacron Tcaron -111
+KPX Amacron Tcommaaccent -111
+KPX Amacron U -55
+KPX Amacron Uacute -55
+KPX Amacron Ucircumflex -55
+KPX Amacron Udieresis -55
+KPX Amacron Ugrave -55
+KPX Amacron Uhungarumlaut -55
+KPX Amacron Umacron -55
+KPX Amacron Uogonek -55
+KPX Amacron Uring -55
+KPX Amacron V -135
+KPX Amacron W -90
+KPX Amacron Y -105
+KPX Amacron Yacute -105
+KPX Amacron Ydieresis -105
+KPX Amacron quoteright -111
+KPX Amacron v -74
+KPX Amacron w -92
+KPX Amacron y -92
+KPX Amacron yacute -92
+KPX Amacron ydieresis -92
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -40
+KPX Aogonek Gbreve -40
+KPX Aogonek Gcommaaccent -40
+KPX Aogonek O -55
+KPX Aogonek Oacute -55
+KPX Aogonek Ocircumflex -55
+KPX Aogonek Odieresis -55
+KPX Aogonek Ograve -55
+KPX Aogonek Ohungarumlaut -55
+KPX Aogonek Omacron -55
+KPX Aogonek Oslash -55
+KPX Aogonek Otilde -55
+KPX Aogonek Q -55
+KPX Aogonek T -111
+KPX Aogonek Tcaron -111
+KPX Aogonek Tcommaaccent -111
+KPX Aogonek U -55
+KPX Aogonek Uacute -55
+KPX Aogonek Ucircumflex -55
+KPX Aogonek Udieresis -55
+KPX Aogonek Ugrave -55
+KPX Aogonek Uhungarumlaut -55
+KPX Aogonek Umacron -55
+KPX Aogonek Uogonek -55
+KPX Aogonek Uring -55
+KPX Aogonek V -135
+KPX Aogonek W -90
+KPX Aogonek Y -105
+KPX Aogonek Yacute -105
+KPX Aogonek Ydieresis -105
+KPX Aogonek quoteright -111
+KPX Aogonek v -74
+KPX Aogonek w -52
+KPX Aogonek y -52
+KPX Aogonek yacute -52
+KPX Aogonek ydieresis -52
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -40
+KPX Aring Gbreve -40
+KPX Aring Gcommaaccent -40
+KPX Aring O -55
+KPX Aring Oacute -55
+KPX Aring Ocircumflex -55
+KPX Aring Odieresis -55
+KPX Aring Ograve -55
+KPX Aring Ohungarumlaut -55
+KPX Aring Omacron -55
+KPX Aring Oslash -55
+KPX Aring Otilde -55
+KPX Aring Q -55
+KPX Aring T -111
+KPX Aring Tcaron -111
+KPX Aring Tcommaaccent -111
+KPX Aring U -55
+KPX Aring Uacute -55
+KPX Aring Ucircumflex -55
+KPX Aring Udieresis -55
+KPX Aring Ugrave -55
+KPX Aring Uhungarumlaut -55
+KPX Aring Umacron -55
+KPX Aring Uogonek -55
+KPX Aring Uring -55
+KPX Aring V -135
+KPX Aring W -90
+KPX Aring Y -105
+KPX Aring Yacute -105
+KPX Aring Ydieresis -105
+KPX Aring quoteright -111
+KPX Aring v -74
+KPX Aring w -92
+KPX Aring y -92
+KPX Aring yacute -92
+KPX Aring ydieresis -92
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -40
+KPX Atilde Gbreve -40
+KPX Atilde Gcommaaccent -40
+KPX Atilde O -55
+KPX Atilde Oacute -55
+KPX Atilde Ocircumflex -55
+KPX Atilde Odieresis -55
+KPX Atilde Ograve -55
+KPX Atilde Ohungarumlaut -55
+KPX Atilde Omacron -55
+KPX Atilde Oslash -55
+KPX Atilde Otilde -55
+KPX Atilde Q -55
+KPX Atilde T -111
+KPX Atilde Tcaron -111
+KPX Atilde Tcommaaccent -111
+KPX Atilde U -55
+KPX Atilde Uacute -55
+KPX Atilde Ucircumflex -55
+KPX Atilde Udieresis -55
+KPX Atilde Ugrave -55
+KPX Atilde Uhungarumlaut -55
+KPX Atilde Umacron -55
+KPX Atilde Uogonek -55
+KPX Atilde Uring -55
+KPX Atilde V -135
+KPX Atilde W -90
+KPX Atilde Y -105
+KPX Atilde Yacute -105
+KPX Atilde Ydieresis -105
+KPX Atilde quoteright -111
+KPX Atilde v -74
+KPX Atilde w -92
+KPX Atilde y -92
+KPX Atilde yacute -92
+KPX Atilde ydieresis -92
+KPX B A -35
+KPX B Aacute -35
+KPX B Abreve -35
+KPX B Acircumflex -35
+KPX B Adieresis -35
+KPX B Agrave -35
+KPX B Amacron -35
+KPX B Aogonek -35
+KPX B Aring -35
+KPX B Atilde -35
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -30
+KPX D Y -55
+KPX D Yacute -55
+KPX D Ydieresis -55
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -30
+KPX Dcaron Y -55
+KPX Dcaron Yacute -55
+KPX Dcaron Ydieresis -55
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -30
+KPX Dcroat Y -55
+KPX Dcroat Yacute -55
+KPX Dcroat Ydieresis -55
+KPX F A -74
+KPX F Aacute -74
+KPX F Abreve -74
+KPX F Acircumflex -74
+KPX F Adieresis -74
+KPX F Agrave -74
+KPX F Amacron -74
+KPX F Aogonek -74
+KPX F Aring -74
+KPX F Atilde -74
+KPX F a -15
+KPX F aacute -15
+KPX F abreve -15
+KPX F acircumflex -15
+KPX F adieresis -15
+KPX F agrave -15
+KPX F amacron -15
+KPX F aogonek -15
+KPX F aring -15
+KPX F atilde -15
+KPX F comma -80
+KPX F o -15
+KPX F oacute -15
+KPX F ocircumflex -15
+KPX F odieresis -15
+KPX F ograve -15
+KPX F ohungarumlaut -15
+KPX F omacron -15
+KPX F oslash -15
+KPX F otilde -15
+KPX F period -80
+KPX J A -60
+KPX J Aacute -60
+KPX J Abreve -60
+KPX J Acircumflex -60
+KPX J Adieresis -60
+KPX J Agrave -60
+KPX J Amacron -60
+KPX J Aogonek -60
+KPX J Aring -60
+KPX J Atilde -60
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -15
+KPX K uacute -15
+KPX K ucircumflex -15
+KPX K udieresis -15
+KPX K ugrave -15
+KPX K uhungarumlaut -15
+KPX K umacron -15
+KPX K uogonek -15
+KPX K uring -15
+KPX K y -25
+KPX K yacute -25
+KPX K ydieresis -25
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -15
+KPX Kcommaaccent uacute -15
+KPX Kcommaaccent ucircumflex -15
+KPX Kcommaaccent udieresis -15
+KPX Kcommaaccent ugrave -15
+KPX Kcommaaccent uhungarumlaut -15
+KPX Kcommaaccent umacron -15
+KPX Kcommaaccent uogonek -15
+KPX Kcommaaccent uring -15
+KPX Kcommaaccent y -25
+KPX Kcommaaccent yacute -25
+KPX Kcommaaccent ydieresis -25
+KPX L T -92
+KPX L Tcaron -92
+KPX L Tcommaaccent -92
+KPX L V -100
+KPX L W -74
+KPX L Y -100
+KPX L Yacute -100
+KPX L Ydieresis -100
+KPX L quoteright -92
+KPX L y -55
+KPX L yacute -55
+KPX L ydieresis -55
+KPX Lacute T -92
+KPX Lacute Tcaron -92
+KPX Lacute Tcommaaccent -92
+KPX Lacute V -100
+KPX Lacute W -74
+KPX Lacute Y -100
+KPX Lacute Yacute -100
+KPX Lacute Ydieresis -100
+KPX Lacute quoteright -92
+KPX Lacute y -55
+KPX Lacute yacute -55
+KPX Lacute ydieresis -55
+KPX Lcaron quoteright -92
+KPX Lcaron y -55
+KPX Lcaron yacute -55
+KPX Lcaron ydieresis -55
+KPX Lcommaaccent T -92
+KPX Lcommaaccent Tcaron -92
+KPX Lcommaaccent Tcommaaccent -92
+KPX Lcommaaccent V -100
+KPX Lcommaaccent W -74
+KPX Lcommaaccent Y -100
+KPX Lcommaaccent Yacute -100
+KPX Lcommaaccent Ydieresis -100
+KPX Lcommaaccent quoteright -92
+KPX Lcommaaccent y -55
+KPX Lcommaaccent yacute -55
+KPX Lcommaaccent ydieresis -55
+KPX Lslash T -92
+KPX Lslash Tcaron -92
+KPX Lslash Tcommaaccent -92
+KPX Lslash V -100
+KPX Lslash W -74
+KPX Lslash Y -100
+KPX Lslash Yacute -100
+KPX Lslash Ydieresis -100
+KPX Lslash quoteright -92
+KPX Lslash y -55
+KPX Lslash yacute -55
+KPX Lslash ydieresis -55
+KPX N A -35
+KPX N Aacute -35
+KPX N Abreve -35
+KPX N Acircumflex -35
+KPX N Adieresis -35
+KPX N Agrave -35
+KPX N Amacron -35
+KPX N Aogonek -35
+KPX N Aring -35
+KPX N Atilde -35
+KPX Nacute A -35
+KPX Nacute Aacute -35
+KPX Nacute Abreve -35
+KPX Nacute Acircumflex -35
+KPX Nacute Adieresis -35
+KPX Nacute Agrave -35
+KPX Nacute Amacron -35
+KPX Nacute Aogonek -35
+KPX Nacute Aring -35
+KPX Nacute Atilde -35
+KPX Ncaron A -35
+KPX Ncaron Aacute -35
+KPX Ncaron Abreve -35
+KPX Ncaron Acircumflex -35
+KPX Ncaron Adieresis -35
+KPX Ncaron Agrave -35
+KPX Ncaron Amacron -35
+KPX Ncaron Aogonek -35
+KPX Ncaron Aring -35
+KPX Ncaron Atilde -35
+KPX Ncommaaccent A -35
+KPX Ncommaaccent Aacute -35
+KPX Ncommaaccent Abreve -35
+KPX Ncommaaccent Acircumflex -35
+KPX Ncommaaccent Adieresis -35
+KPX Ncommaaccent Agrave -35
+KPX Ncommaaccent Amacron -35
+KPX Ncommaaccent Aogonek -35
+KPX Ncommaaccent Aring -35
+KPX Ncommaaccent Atilde -35
+KPX Ntilde A -35
+KPX Ntilde Aacute -35
+KPX Ntilde Abreve -35
+KPX Ntilde Acircumflex -35
+KPX Ntilde Adieresis -35
+KPX Ntilde Agrave -35
+KPX Ntilde Amacron -35
+KPX Ntilde Aogonek -35
+KPX Ntilde Aring -35
+KPX Ntilde Atilde -35
+KPX O A -35
+KPX O Aacute -35
+KPX O Abreve -35
+KPX O Acircumflex -35
+KPX O Adieresis -35
+KPX O Agrave -35
+KPX O Amacron -35
+KPX O Aogonek -35
+KPX O Aring -35
+KPX O Atilde -35
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -35
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -35
+KPX Oacute Aacute -35
+KPX Oacute Abreve -35
+KPX Oacute Acircumflex -35
+KPX Oacute Adieresis -35
+KPX Oacute Agrave -35
+KPX Oacute Amacron -35
+KPX Oacute Aogonek -35
+KPX Oacute Aring -35
+KPX Oacute Atilde -35
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -35
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -35
+KPX Ocircumflex Aacute -35
+KPX Ocircumflex Abreve -35
+KPX Ocircumflex Acircumflex -35
+KPX Ocircumflex Adieresis -35
+KPX Ocircumflex Agrave -35
+KPX Ocircumflex Amacron -35
+KPX Ocircumflex Aogonek -35
+KPX Ocircumflex Aring -35
+KPX Ocircumflex Atilde -35
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -35
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -35
+KPX Odieresis Aacute -35
+KPX Odieresis Abreve -35
+KPX Odieresis Acircumflex -35
+KPX Odieresis Adieresis -35
+KPX Odieresis Agrave -35
+KPX Odieresis Amacron -35
+KPX Odieresis Aogonek -35
+KPX Odieresis Aring -35
+KPX Odieresis Atilde -35
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -35
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -35
+KPX Ograve Aacute -35
+KPX Ograve Abreve -35
+KPX Ograve Acircumflex -35
+KPX Ograve Adieresis -35
+KPX Ograve Agrave -35
+KPX Ograve Amacron -35
+KPX Ograve Aogonek -35
+KPX Ograve Aring -35
+KPX Ograve Atilde -35
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -35
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -35
+KPX Ohungarumlaut Aacute -35
+KPX Ohungarumlaut Abreve -35
+KPX Ohungarumlaut Acircumflex -35
+KPX Ohungarumlaut Adieresis -35
+KPX Ohungarumlaut Agrave -35
+KPX Ohungarumlaut Amacron -35
+KPX Ohungarumlaut Aogonek -35
+KPX Ohungarumlaut Aring -35
+KPX Ohungarumlaut Atilde -35
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -35
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -35
+KPX Omacron Aacute -35
+KPX Omacron Abreve -35
+KPX Omacron Acircumflex -35
+KPX Omacron Adieresis -35
+KPX Omacron Agrave -35
+KPX Omacron Amacron -35
+KPX Omacron Aogonek -35
+KPX Omacron Aring -35
+KPX Omacron Atilde -35
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -35
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -35
+KPX Oslash Aacute -35
+KPX Oslash Abreve -35
+KPX Oslash Acircumflex -35
+KPX Oslash Adieresis -35
+KPX Oslash Agrave -35
+KPX Oslash Amacron -35
+KPX Oslash Aogonek -35
+KPX Oslash Aring -35
+KPX Oslash Atilde -35
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -35
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -35
+KPX Otilde Aacute -35
+KPX Otilde Abreve -35
+KPX Otilde Acircumflex -35
+KPX Otilde Adieresis -35
+KPX Otilde Agrave -35
+KPX Otilde Amacron -35
+KPX Otilde Aogonek -35
+KPX Otilde Aring -35
+KPX Otilde Atilde -35
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -35
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -92
+KPX P Aacute -92
+KPX P Abreve -92
+KPX P Acircumflex -92
+KPX P Adieresis -92
+KPX P Agrave -92
+KPX P Amacron -92
+KPX P Aogonek -92
+KPX P Aring -92
+KPX P Atilde -92
+KPX P a -15
+KPX P aacute -15
+KPX P abreve -15
+KPX P acircumflex -15
+KPX P adieresis -15
+KPX P agrave -15
+KPX P amacron -15
+KPX P aogonek -15
+KPX P aring -15
+KPX P atilde -15
+KPX P comma -111
+KPX P period -111
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R T -60
+KPX R Tcaron -60
+KPX R Tcommaaccent -60
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -80
+KPX R W -55
+KPX R Y -65
+KPX R Yacute -65
+KPX R Ydieresis -65
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute T -60
+KPX Racute Tcaron -60
+KPX Racute Tcommaaccent -60
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -80
+KPX Racute W -55
+KPX Racute Y -65
+KPX Racute Yacute -65
+KPX Racute Ydieresis -65
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron T -60
+KPX Rcaron Tcaron -60
+KPX Rcaron Tcommaaccent -60
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -80
+KPX Rcaron W -55
+KPX Rcaron Y -65
+KPX Rcaron Yacute -65
+KPX Rcaron Ydieresis -65
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent T -60
+KPX Rcommaaccent Tcaron -60
+KPX Rcommaaccent Tcommaaccent -60
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -80
+KPX Rcommaaccent W -55
+KPX Rcommaaccent Y -65
+KPX Rcommaaccent Yacute -65
+KPX Rcommaaccent Ydieresis -65
+KPX T A -93
+KPX T Aacute -93
+KPX T Abreve -93
+KPX T Acircumflex -93
+KPX T Adieresis -93
+KPX T Agrave -93
+KPX T Amacron -93
+KPX T Aogonek -93
+KPX T Aring -93
+KPX T Atilde -93
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -40
+KPX T agrave -40
+KPX T amacron -40
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -40
+KPX T colon -50
+KPX T comma -74
+KPX T e -70
+KPX T eacute -70
+KPX T ecaron -70
+KPX T ecircumflex -70
+KPX T edieresis -30
+KPX T edotaccent -70
+KPX T egrave -70
+KPX T emacron -30
+KPX T eogonek -70
+KPX T hyphen -92
+KPX T i -35
+KPX T iacute -35
+KPX T iogonek -35
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -74
+KPX T r -35
+KPX T racute -35
+KPX T rcaron -35
+KPX T rcommaaccent -35
+KPX T semicolon -55
+KPX T u -45
+KPX T uacute -45
+KPX T ucircumflex -45
+KPX T udieresis -45
+KPX T ugrave -45
+KPX T uhungarumlaut -45
+KPX T umacron -45
+KPX T uogonek -45
+KPX T uring -45
+KPX T w -80
+KPX T y -80
+KPX T yacute -80
+KPX T ydieresis -80
+KPX Tcaron A -93
+KPX Tcaron Aacute -93
+KPX Tcaron Abreve -93
+KPX Tcaron Acircumflex -93
+KPX Tcaron Adieresis -93
+KPX Tcaron Agrave -93
+KPX Tcaron Amacron -93
+KPX Tcaron Aogonek -93
+KPX Tcaron Aring -93
+KPX Tcaron Atilde -93
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -40
+KPX Tcaron agrave -40
+KPX Tcaron amacron -40
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -40
+KPX Tcaron colon -50
+KPX Tcaron comma -74
+KPX Tcaron e -70
+KPX Tcaron eacute -70
+KPX Tcaron ecaron -70
+KPX Tcaron ecircumflex -30
+KPX Tcaron edieresis -30
+KPX Tcaron edotaccent -70
+KPX Tcaron egrave -70
+KPX Tcaron emacron -30
+KPX Tcaron eogonek -70
+KPX Tcaron hyphen -92
+KPX Tcaron i -35
+KPX Tcaron iacute -35
+KPX Tcaron iogonek -35
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -74
+KPX Tcaron r -35
+KPX Tcaron racute -35
+KPX Tcaron rcaron -35
+KPX Tcaron rcommaaccent -35
+KPX Tcaron semicolon -55
+KPX Tcaron u -45
+KPX Tcaron uacute -45
+KPX Tcaron ucircumflex -45
+KPX Tcaron udieresis -45
+KPX Tcaron ugrave -45
+KPX Tcaron uhungarumlaut -45
+KPX Tcaron umacron -45
+KPX Tcaron uogonek -45
+KPX Tcaron uring -45
+KPX Tcaron w -80
+KPX Tcaron y -80
+KPX Tcaron yacute -80
+KPX Tcaron ydieresis -80
+KPX Tcommaaccent A -93
+KPX Tcommaaccent Aacute -93
+KPX Tcommaaccent Abreve -93
+KPX Tcommaaccent Acircumflex -93
+KPX Tcommaaccent Adieresis -93
+KPX Tcommaaccent Agrave -93
+KPX Tcommaaccent Amacron -93
+KPX Tcommaaccent Aogonek -93
+KPX Tcommaaccent Aring -93
+KPX Tcommaaccent Atilde -93
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -40
+KPX Tcommaaccent agrave -40
+KPX Tcommaaccent amacron -40
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -40
+KPX Tcommaaccent colon -50
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -70
+KPX Tcommaaccent eacute -70
+KPX Tcommaaccent ecaron -70
+KPX Tcommaaccent ecircumflex -30
+KPX Tcommaaccent edieresis -30
+KPX Tcommaaccent edotaccent -70
+KPX Tcommaaccent egrave -30
+KPX Tcommaaccent emacron -70
+KPX Tcommaaccent eogonek -70
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -35
+KPX Tcommaaccent iacute -35
+KPX Tcommaaccent iogonek -35
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -74
+KPX Tcommaaccent r -35
+KPX Tcommaaccent racute -35
+KPX Tcommaaccent rcaron -35
+KPX Tcommaaccent rcommaaccent -35
+KPX Tcommaaccent semicolon -55
+KPX Tcommaaccent u -45
+KPX Tcommaaccent uacute -45
+KPX Tcommaaccent ucircumflex -45
+KPX Tcommaaccent udieresis -45
+KPX Tcommaaccent ugrave -45
+KPX Tcommaaccent uhungarumlaut -45
+KPX Tcommaaccent umacron -45
+KPX Tcommaaccent uogonek -45
+KPX Tcommaaccent uring -45
+KPX Tcommaaccent w -80
+KPX Tcommaaccent y -80
+KPX Tcommaaccent yacute -80
+KPX Tcommaaccent ydieresis -80
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX V A -135
+KPX V Aacute -135
+KPX V Abreve -135
+KPX V Acircumflex -135
+KPX V Adieresis -135
+KPX V Agrave -135
+KPX V Amacron -135
+KPX V Aogonek -135
+KPX V Aring -135
+KPX V Atilde -135
+KPX V G -15
+KPX V Gbreve -15
+KPX V Gcommaaccent -15
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -71
+KPX V adieresis -71
+KPX V agrave -71
+KPX V amacron -71
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -71
+KPX V colon -74
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -71
+KPX V ecircumflex -71
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -100
+KPX V i -60
+KPX V iacute -60
+KPX V icircumflex -20
+KPX V idieresis -20
+KPX V igrave -20
+KPX V imacron -20
+KPX V iogonek -60
+KPX V o -129
+KPX V oacute -129
+KPX V ocircumflex -129
+KPX V odieresis -89
+KPX V ograve -89
+KPX V ohungarumlaut -129
+KPX V omacron -89
+KPX V oslash -129
+KPX V otilde -89
+KPX V period -129
+KPX V semicolon -74
+KPX V u -75
+KPX V uacute -75
+KPX V ucircumflex -75
+KPX V udieresis -75
+KPX V ugrave -75
+KPX V uhungarumlaut -75
+KPX V umacron -75
+KPX V uogonek -75
+KPX V uring -75
+KPX W A -120
+KPX W Aacute -120
+KPX W Abreve -120
+KPX W Acircumflex -120
+KPX W Adieresis -120
+KPX W Agrave -120
+KPX W Amacron -120
+KPX W Aogonek -120
+KPX W Aring -120
+KPX W Atilde -120
+KPX W O -10
+KPX W Oacute -10
+KPX W Ocircumflex -10
+KPX W Odieresis -10
+KPX W Ograve -10
+KPX W Ohungarumlaut -10
+KPX W Omacron -10
+KPX W Oslash -10
+KPX W Otilde -10
+KPX W a -80
+KPX W aacute -80
+KPX W abreve -80
+KPX W acircumflex -80
+KPX W adieresis -80
+KPX W agrave -80
+KPX W amacron -80
+KPX W aogonek -80
+KPX W aring -80
+KPX W atilde -80
+KPX W colon -37
+KPX W comma -92
+KPX W e -80
+KPX W eacute -80
+KPX W ecaron -80
+KPX W ecircumflex -80
+KPX W edieresis -40
+KPX W edotaccent -80
+KPX W egrave -40
+KPX W emacron -40
+KPX W eogonek -80
+KPX W hyphen -65
+KPX W i -40
+KPX W iacute -40
+KPX W iogonek -40
+KPX W o -80
+KPX W oacute -80
+KPX W ocircumflex -80
+KPX W odieresis -80
+KPX W ograve -80
+KPX W ohungarumlaut -80
+KPX W omacron -80
+KPX W oslash -80
+KPX W otilde -80
+KPX W period -92
+KPX W semicolon -37
+KPX W u -50
+KPX W uacute -50
+KPX W ucircumflex -50
+KPX W udieresis -50
+KPX W ugrave -50
+KPX W uhungarumlaut -50
+KPX W umacron -50
+KPX W uogonek -50
+KPX W uring -50
+KPX W y -73
+KPX W yacute -73
+KPX W ydieresis -73
+KPX Y A -120
+KPX Y Aacute -120
+KPX Y Abreve -120
+KPX Y Acircumflex -120
+KPX Y Adieresis -120
+KPX Y Agrave -120
+KPX Y Amacron -120
+KPX Y Aogonek -120
+KPX Y Aring -120
+KPX Y Atilde -120
+KPX Y O -30
+KPX Y Oacute -30
+KPX Y Ocircumflex -30
+KPX Y Odieresis -30
+KPX Y Ograve -30
+KPX Y Ohungarumlaut -30
+KPX Y Omacron -30
+KPX Y Oslash -30
+KPX Y Otilde -30
+KPX Y a -100
+KPX Y aacute -100
+KPX Y abreve -100
+KPX Y acircumflex -100
+KPX Y adieresis -60
+KPX Y agrave -60
+KPX Y amacron -60
+KPX Y aogonek -100
+KPX Y aring -100
+KPX Y atilde -60
+KPX Y colon -92
+KPX Y comma -129
+KPX Y e -100
+KPX Y eacute -100
+KPX Y ecaron -100
+KPX Y ecircumflex -100
+KPX Y edieresis -60
+KPX Y edotaccent -100
+KPX Y egrave -60
+KPX Y emacron -60
+KPX Y eogonek -100
+KPX Y hyphen -111
+KPX Y i -55
+KPX Y iacute -55
+KPX Y iogonek -55
+KPX Y o -110
+KPX Y oacute -110
+KPX Y ocircumflex -110
+KPX Y odieresis -70
+KPX Y ograve -70
+KPX Y ohungarumlaut -110
+KPX Y omacron -70
+KPX Y oslash -110
+KPX Y otilde -70
+KPX Y period -129
+KPX Y semicolon -92
+KPX Y u -111
+KPX Y uacute -111
+KPX Y ucircumflex -111
+KPX Y udieresis -71
+KPX Y ugrave -71
+KPX Y uhungarumlaut -111
+KPX Y umacron -71
+KPX Y uogonek -111
+KPX Y uring -111
+KPX Yacute A -120
+KPX Yacute Aacute -120
+KPX Yacute Abreve -120
+KPX Yacute Acircumflex -120
+KPX Yacute Adieresis -120
+KPX Yacute Agrave -120
+KPX Yacute Amacron -120
+KPX Yacute Aogonek -120
+KPX Yacute Aring -120
+KPX Yacute Atilde -120
+KPX Yacute O -30
+KPX Yacute Oacute -30
+KPX Yacute Ocircumflex -30
+KPX Yacute Odieresis -30
+KPX Yacute Ograve -30
+KPX Yacute Ohungarumlaut -30
+KPX Yacute Omacron -30
+KPX Yacute Oslash -30
+KPX Yacute Otilde -30
+KPX Yacute a -100
+KPX Yacute aacute -100
+KPX Yacute abreve -100
+KPX Yacute acircumflex -100
+KPX Yacute adieresis -60
+KPX Yacute agrave -60
+KPX Yacute amacron -60
+KPX Yacute aogonek -100
+KPX Yacute aring -100
+KPX Yacute atilde -60
+KPX Yacute colon -92
+KPX Yacute comma -129
+KPX Yacute e -100
+KPX Yacute eacute -100
+KPX Yacute ecaron -100
+KPX Yacute ecircumflex -100
+KPX Yacute edieresis -60
+KPX Yacute edotaccent -100
+KPX Yacute egrave -60
+KPX Yacute emacron -60
+KPX Yacute eogonek -100
+KPX Yacute hyphen -111
+KPX Yacute i -55
+KPX Yacute iacute -55
+KPX Yacute iogonek -55
+KPX Yacute o -110
+KPX Yacute oacute -110
+KPX Yacute ocircumflex -110
+KPX Yacute odieresis -70
+KPX Yacute ograve -70
+KPX Yacute ohungarumlaut -110
+KPX Yacute omacron -70
+KPX Yacute oslash -110
+KPX Yacute otilde -70
+KPX Yacute period -129
+KPX Yacute semicolon -92
+KPX Yacute u -111
+KPX Yacute uacute -111
+KPX Yacute ucircumflex -111
+KPX Yacute udieresis -71
+KPX Yacute ugrave -71
+KPX Yacute uhungarumlaut -111
+KPX Yacute umacron -71
+KPX Yacute uogonek -111
+KPX Yacute uring -111
+KPX Ydieresis A -120
+KPX Ydieresis Aacute -120
+KPX Ydieresis Abreve -120
+KPX Ydieresis Acircumflex -120
+KPX Ydieresis Adieresis -120
+KPX Ydieresis Agrave -120
+KPX Ydieresis Amacron -120
+KPX Ydieresis Aogonek -120
+KPX Ydieresis Aring -120
+KPX Ydieresis Atilde -120
+KPX Ydieresis O -30
+KPX Ydieresis Oacute -30
+KPX Ydieresis Ocircumflex -30
+KPX Ydieresis Odieresis -30
+KPX Ydieresis Ograve -30
+KPX Ydieresis Ohungarumlaut -30
+KPX Ydieresis Omacron -30
+KPX Ydieresis Oslash -30
+KPX Ydieresis Otilde -30
+KPX Ydieresis a -100
+KPX Ydieresis aacute -100
+KPX Ydieresis abreve -100
+KPX Ydieresis acircumflex -100
+KPX Ydieresis adieresis -60
+KPX Ydieresis agrave -60
+KPX Ydieresis amacron -60
+KPX Ydieresis aogonek -100
+KPX Ydieresis aring -100
+KPX Ydieresis atilde -100
+KPX Ydieresis colon -92
+KPX Ydieresis comma -129
+KPX Ydieresis e -100
+KPX Ydieresis eacute -100
+KPX Ydieresis ecaron -100
+KPX Ydieresis ecircumflex -100
+KPX Ydieresis edieresis -60
+KPX Ydieresis edotaccent -100
+KPX Ydieresis egrave -60
+KPX Ydieresis emacron -60
+KPX Ydieresis eogonek -100
+KPX Ydieresis hyphen -111
+KPX Ydieresis i -55
+KPX Ydieresis iacute -55
+KPX Ydieresis iogonek -55
+KPX Ydieresis o -110
+KPX Ydieresis oacute -110
+KPX Ydieresis ocircumflex -110
+KPX Ydieresis odieresis -70
+KPX Ydieresis ograve -70
+KPX Ydieresis ohungarumlaut -110
+KPX Ydieresis omacron -70
+KPX Ydieresis oslash -110
+KPX Ydieresis otilde -70
+KPX Ydieresis period -129
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -111
+KPX Ydieresis uacute -111
+KPX Ydieresis ucircumflex -111
+KPX Ydieresis udieresis -71
+KPX Ydieresis ugrave -71
+KPX Ydieresis uhungarumlaut -111
+KPX Ydieresis umacron -71
+KPX Ydieresis uogonek -111
+KPX Ydieresis uring -111
+KPX a v -20
+KPX a w -15
+KPX aacute v -20
+KPX aacute w -15
+KPX abreve v -20
+KPX abreve w -15
+KPX acircumflex v -20
+KPX acircumflex w -15
+KPX adieresis v -20
+KPX adieresis w -15
+KPX agrave v -20
+KPX agrave w -15
+KPX amacron v -20
+KPX amacron w -15
+KPX aogonek v -20
+KPX aogonek w -15
+KPX aring v -20
+KPX aring w -15
+KPX atilde v -20
+KPX atilde w -15
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -15
+KPX c y -15
+KPX c yacute -15
+KPX c ydieresis -15
+KPX cacute y -15
+KPX cacute yacute -15
+KPX cacute ydieresis -15
+KPX ccaron y -15
+KPX ccaron yacute -15
+KPX ccaron ydieresis -15
+KPX ccedilla y -15
+KPX ccedilla yacute -15
+KPX ccedilla ydieresis -15
+KPX comma quotedblright -70
+KPX comma quoteright -70
+KPX e g -15
+KPX e gbreve -15
+KPX e gcommaaccent -15
+KPX e v -25
+KPX e w -25
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute g -15
+KPX eacute gbreve -15
+KPX eacute gcommaaccent -15
+KPX eacute v -25
+KPX eacute w -25
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron g -15
+KPX ecaron gbreve -15
+KPX ecaron gcommaaccent -15
+KPX ecaron v -25
+KPX ecaron w -25
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex g -15
+KPX ecircumflex gbreve -15
+KPX ecircumflex gcommaaccent -15
+KPX ecircumflex v -25
+KPX ecircumflex w -25
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis g -15
+KPX edieresis gbreve -15
+KPX edieresis gcommaaccent -15
+KPX edieresis v -25
+KPX edieresis w -25
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent g -15
+KPX edotaccent gbreve -15
+KPX edotaccent gcommaaccent -15
+KPX edotaccent v -25
+KPX edotaccent w -25
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave g -15
+KPX egrave gbreve -15
+KPX egrave gcommaaccent -15
+KPX egrave v -25
+KPX egrave w -25
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron g -15
+KPX emacron gbreve -15
+KPX emacron gcommaaccent -15
+KPX emacron v -25
+KPX emacron w -25
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek g -15
+KPX eogonek gbreve -15
+KPX eogonek gcommaaccent -15
+KPX eogonek v -25
+KPX eogonek w -25
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f a -10
+KPX f aacute -10
+KPX f abreve -10
+KPX f acircumflex -10
+KPX f adieresis -10
+KPX f agrave -10
+KPX f amacron -10
+KPX f aogonek -10
+KPX f aring -10
+KPX f atilde -10
+KPX f dotlessi -50
+KPX f f -25
+KPX f i -20
+KPX f iacute -20
+KPX f quoteright 55
+KPX g a -5
+KPX g aacute -5
+KPX g abreve -5
+KPX g acircumflex -5
+KPX g adieresis -5
+KPX g agrave -5
+KPX g amacron -5
+KPX g aogonek -5
+KPX g aring -5
+KPX g atilde -5
+KPX gbreve a -5
+KPX gbreve aacute -5
+KPX gbreve abreve -5
+KPX gbreve acircumflex -5
+KPX gbreve adieresis -5
+KPX gbreve agrave -5
+KPX gbreve amacron -5
+KPX gbreve aogonek -5
+KPX gbreve aring -5
+KPX gbreve atilde -5
+KPX gcommaaccent a -5
+KPX gcommaaccent aacute -5
+KPX gcommaaccent abreve -5
+KPX gcommaaccent acircumflex -5
+KPX gcommaaccent adieresis -5
+KPX gcommaaccent agrave -5
+KPX gcommaaccent amacron -5
+KPX gcommaaccent aogonek -5
+KPX gcommaaccent aring -5
+KPX gcommaaccent atilde -5
+KPX h y -5
+KPX h yacute -5
+KPX h ydieresis -5
+KPX i v -25
+KPX iacute v -25
+KPX icircumflex v -25
+KPX idieresis v -25
+KPX igrave v -25
+KPX imacron v -25
+KPX iogonek v -25
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX k y -15
+KPX k yacute -15
+KPX k ydieresis -15
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX kcommaaccent y -15
+KPX kcommaaccent yacute -15
+KPX kcommaaccent ydieresis -15
+KPX l w -10
+KPX lacute w -10
+KPX lcommaaccent w -10
+KPX lslash w -10
+KPX n v -40
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute v -40
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron v -40
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent v -40
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde v -40
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o v -15
+KPX o w -25
+KPX o y -10
+KPX o yacute -10
+KPX o ydieresis -10
+KPX oacute v -15
+KPX oacute w -25
+KPX oacute y -10
+KPX oacute yacute -10
+KPX oacute ydieresis -10
+KPX ocircumflex v -15
+KPX ocircumflex w -25
+KPX ocircumflex y -10
+KPX ocircumflex yacute -10
+KPX ocircumflex ydieresis -10
+KPX odieresis v -15
+KPX odieresis w -25
+KPX odieresis y -10
+KPX odieresis yacute -10
+KPX odieresis ydieresis -10
+KPX ograve v -15
+KPX ograve w -25
+KPX ograve y -10
+KPX ograve yacute -10
+KPX ograve ydieresis -10
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -25
+KPX ohungarumlaut y -10
+KPX ohungarumlaut yacute -10
+KPX ohungarumlaut ydieresis -10
+KPX omacron v -15
+KPX omacron w -25
+KPX omacron y -10
+KPX omacron yacute -10
+KPX omacron ydieresis -10
+KPX oslash v -15
+KPX oslash w -25
+KPX oslash y -10
+KPX oslash yacute -10
+KPX oslash ydieresis -10
+KPX otilde v -15
+KPX otilde w -25
+KPX otilde y -10
+KPX otilde yacute -10
+KPX otilde ydieresis -10
+KPX p y -10
+KPX p yacute -10
+KPX p ydieresis -10
+KPX period quotedblright -70
+KPX period quoteright -70
+KPX quotedblleft A -80
+KPX quotedblleft Aacute -80
+KPX quotedblleft Abreve -80
+KPX quotedblleft Acircumflex -80
+KPX quotedblleft Adieresis -80
+KPX quotedblleft Agrave -80
+KPX quotedblleft Amacron -80
+KPX quotedblleft Aogonek -80
+KPX quotedblleft Aring -80
+KPX quotedblleft Atilde -80
+KPX quoteleft A -80
+KPX quoteleft Aacute -80
+KPX quoteleft Abreve -80
+KPX quoteleft Acircumflex -80
+KPX quoteleft Adieresis -80
+KPX quoteleft Agrave -80
+KPX quoteleft Amacron -80
+KPX quoteleft Aogonek -80
+KPX quoteleft Aring -80
+KPX quoteleft Atilde -80
+KPX quoteleft quoteleft -74
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright l -10
+KPX quoteright lacute -10
+KPX quoteright lcommaaccent -10
+KPX quoteright lslash -10
+KPX quoteright quoteright -74
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -55
+KPX quoteright sacute -55
+KPX quoteright scaron -55
+KPX quoteright scedilla -55
+KPX quoteright scommaaccent -55
+KPX quoteright space -74
+KPX quoteright t -18
+KPX quoteright tcommaaccent -18
+KPX quoteright v -50
+KPX r comma -40
+KPX r g -18
+KPX r gbreve -18
+KPX r gcommaaccent -18
+KPX r hyphen -20
+KPX r period -55
+KPX racute comma -40
+KPX racute g -18
+KPX racute gbreve -18
+KPX racute gcommaaccent -18
+KPX racute hyphen -20
+KPX racute period -55
+KPX rcaron comma -40
+KPX rcaron g -18
+KPX rcaron gbreve -18
+KPX rcaron gcommaaccent -18
+KPX rcaron hyphen -20
+KPX rcaron period -55
+KPX rcommaaccent comma -40
+KPX rcommaaccent g -18
+KPX rcommaaccent gbreve -18
+KPX rcommaaccent gcommaaccent -18
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent period -55
+KPX space A -55
+KPX space Aacute -55
+KPX space Abreve -55
+KPX space Acircumflex -55
+KPX space Adieresis -55
+KPX space Agrave -55
+KPX space Amacron -55
+KPX space Aogonek -55
+KPX space Aring -55
+KPX space Atilde -55
+KPX space T -18
+KPX space Tcaron -18
+KPX space Tcommaaccent -18
+KPX space V -50
+KPX space W -30
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -65
+KPX v e -15
+KPX v eacute -15
+KPX v ecaron -15
+KPX v ecircumflex -15
+KPX v edieresis -15
+KPX v edotaccent -15
+KPX v egrave -15
+KPX v emacron -15
+KPX v eogonek -15
+KPX v o -20
+KPX v oacute -20
+KPX v ocircumflex -20
+KPX v odieresis -20
+KPX v ograve -20
+KPX v ohungarumlaut -20
+KPX v omacron -20
+KPX v oslash -20
+KPX v otilde -20
+KPX v period -65
+KPX w a -10
+KPX w aacute -10
+KPX w abreve -10
+KPX w acircumflex -10
+KPX w adieresis -10
+KPX w agrave -10
+KPX w amacron -10
+KPX w aogonek -10
+KPX w aring -10
+KPX w atilde -10
+KPX w comma -65
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -65
+KPX x e -15
+KPX x eacute -15
+KPX x ecaron -15
+KPX x ecircumflex -15
+KPX x edieresis -15
+KPX x edotaccent -15
+KPX x egrave -15
+KPX x emacron -15
+KPX x eogonek -15
+KPX y comma -65
+KPX y period -65
+KPX yacute comma -65
+KPX yacute period -65
+KPX ydieresis comma -65
+KPX ydieresis period -65
+EndKernPairs
+EndKernData
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/fonts/ZapfDingbats.afm b/LibrarySource/com/lowagie/text/pdf/fonts/ZapfDingbats.afm
new file mode 100644
index 0000000..430e6ff
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/fonts/ZapfDingbats.afm
@@ -0,0 +1,226 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May  1 15:14:13 1997
+Comment UniqueID 43082
+Comment VMusage 45775 55535
+FontName ZapfDingbats
+FullName ITC Zapf Dingbats
+FamilyName ZapfDingbats
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet Special
+FontBBox -1 -143 981 820 
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
+EncodingScheme FontSpecific
+StdHW 28
+StdVW 90
+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 34 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 128 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
+C 129 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
+C 130 ; WX 317 ; N a93 ; B 35 0 283 692 ;
+C 131 ; WX 317 ; N a94 ; B 35 0 283 692 ;
+C 132 ; WX 276 ; N a91 ; B 35 0 242 692 ;
+C 133 ; WX 276 ; N a92 ; B 35 0 242 692 ;
+C 134 ; WX 509 ; N a205 ; B 35 0 475 692 ;
+C 135 ; WX 509 ; N a85 ; B 35 0 475 692 ;
+C 136 ; WX 410 ; N a206 ; B 35 0 375 692 ;
+C 137 ; WX 410 ; N a86 ; B 35 0 375 692 ;
+C 138 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
+C 139 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
+C 140 ; WX 334 ; N a95 ; B 35 0 299 692 ;
+C 141 ; WX 334 ; N a96 ; B 35 0 299 692 ;
+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 ;
+EndCharMetrics
+EndFontMetrics
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/ByteVector.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/ByteVector.java
new file mode 100644
index 0000000..2ac6f83
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/ByteVector.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.io.Serializable;
+
+/**
+ * This class implements a simple byte vector with access to the
+ * underlying array.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class ByteVector implements Serializable {
+
+    /**
+     * Capacity increment size
+     */
+    private static final int DEFAULT_BLOCK_SIZE = 2048;
+    private int blockSize;
+
+    /**
+     * The encapsulated array
+     */
+    private byte[] array;
+
+    /**
+     * Points to next free item
+     */
+    private int n;
+
+    public ByteVector() {
+        this(DEFAULT_BLOCK_SIZE);
+    }
+
+    public ByteVector(int capacity) {
+        if (capacity > 0) {
+            blockSize = capacity;
+        } else {
+            blockSize = DEFAULT_BLOCK_SIZE;
+        }
+        array = new byte[blockSize];
+        n = 0;
+    }
+
+    public ByteVector(byte[] a) {
+        blockSize = DEFAULT_BLOCK_SIZE;
+        array = a;
+        n = 0;
+    }
+
+    public ByteVector(byte[] a, int capacity) {
+        if (capacity > 0) {
+            blockSize = capacity;
+        } else {
+            blockSize = DEFAULT_BLOCK_SIZE;
+        }
+        array = a;
+        n = 0;
+    }
+
+    public byte[] getArray() {
+        return array;
+    }
+
+    /**
+     * return number of items in array
+     */
+    public int length() {
+        return n;
+    }
+
+    /**
+     * returns current capacity of array
+     */
+    public int capacity() {
+        return array.length;
+    }
+
+    public void put(int index, byte val) {
+        array[index] = val;
+    }
+
+    public byte get(int index) {
+        return array[index];
+    }
+
+    /**
+     * This is to implement memory allocation in the array. Like malloc().
+     */
+    public int alloc(int size) {
+        int index = n;
+        int len = array.length;
+        if (n + size >= len) {
+            byte[] aux = new byte[len + blockSize];
+            System.arraycopy(array, 0, aux, 0, len);
+            array = aux;
+        }
+        n += size;
+        return index;
+    }
+
+    public void trimToSize() {
+        if (n < array.length) {
+            byte[] aux = new byte[n];
+            System.arraycopy(array, 0, aux, 0, n);
+            array = aux;
+        }
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/CharVector.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/CharVector.java
new file mode 100644
index 0000000..a2f3c66
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/CharVector.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.io.Serializable;
+
+/**
+ * This class implements a simple char vector with access to the
+ * underlying array.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class CharVector implements Cloneable, Serializable {
+
+    /**
+     * Capacity increment size
+     */
+    private static final int DEFAULT_BLOCK_SIZE = 2048;
+    private int blockSize;
+
+    /**
+     * The encapsulated array
+     */
+    private char[] array;
+
+    /**
+     * Points to next free item
+     */
+    private int n;
+
+    public CharVector() {
+        this(DEFAULT_BLOCK_SIZE);
+    }
+
+    public CharVector(int capacity) {
+        if (capacity > 0) {
+            blockSize = capacity;
+        } else {
+            blockSize = DEFAULT_BLOCK_SIZE;
+        }
+        array = new char[blockSize];
+        n = 0;
+    }
+
+    public CharVector(char[] a) {
+        blockSize = DEFAULT_BLOCK_SIZE;
+        array = a;
+        n = a.length;
+    }
+
+    public CharVector(char[] a, int capacity) {
+        if (capacity > 0) {
+            blockSize = capacity;
+        } else {
+            blockSize = DEFAULT_BLOCK_SIZE;
+        }
+        array = a;
+        n = a.length;
+    }
+
+    /**
+     * Reset Vector but don't resize or clear elements
+     */
+    public void clear() {
+        n = 0;
+    }
+
+    public Object clone() {
+        CharVector cv = new CharVector((char[])array.clone(), blockSize);
+        cv.n = this.n;
+        return cv;
+    }
+
+    public char[] getArray() {
+        return array;
+    }
+
+    /**
+     * return number of items in array
+     */
+    public int length() {
+        return n;
+    }
+
+    /**
+     * returns current capacity of array
+     */
+    public int capacity() {
+        return array.length;
+    }
+
+    public void put(int index, char val) {
+        array[index] = val;
+    }
+
+    public char get(int index) {
+        return array[index];
+    }
+
+    public int alloc(int size) {
+        int index = n;
+        int len = array.length;
+        if (n + size >= len) {
+            char[] aux = new char[len + blockSize];
+            System.arraycopy(array, 0, aux, 0, len);
+            array = aux;
+        }
+        n += size;
+        return index;
+    }
+
+    public void trimToSize() {
+        if (n < array.length) {
+            char[] aux = new char[n];
+            System.arraycopy(array, 0, aux, 0, n);
+            array = aux;
+        }
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphen.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphen.java
new file mode 100644
index 0000000..8642c12
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphen.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.io.Serializable;
+
+/**
+ * This class represents a hyphen. A 'full' hyphen is made of 3 parts:
+ * the pre-break text, post-break text and no-break. If no line-break
+ * is generated at this position, the no-break text is used, otherwise,
+ * pre-break and post-break are used. Typically, pre-break is equal to
+ * the hyphen character and the others are empty. However, this general
+ * scheme allows support for cases in some languages where words change
+ * spelling if they're split across lines, like german's 'backen' which
+ * hyphenates 'bak-ken'. BTW, this comes from TeX.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+
+public class Hyphen implements Serializable {
+    public String preBreak;
+    public String noBreak;
+    public String postBreak;
+
+    Hyphen(String pre, String no, String post) {
+        preBreak = pre;
+        noBreak = no;
+        postBreak = post;
+    }
+
+    Hyphen(String pre) {
+        preBreak = pre;
+        noBreak = null;
+        postBreak = null;
+    }
+
+    public String toString() {
+        if (noBreak == null 
+                && postBreak == null 
+                && preBreak != null
+                && preBreak.equals("-")) {
+            return "-";
+                }
+        StringBuffer res = new StringBuffer("{");
+        res.append(preBreak);
+        res.append("}{");
+        res.append(postBreak);
+        res.append("}{");
+        res.append(noBreak);
+        res.append('}');
+        return res.toString();
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenation.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenation.java
new file mode 100644
index 0000000..8a1c372
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenation.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+/**
+ * This class represents a hyphenated word.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class Hyphenation {
+    
+    private int[] hyphenPoints;
+    private String word;
+
+    /**
+     * number of hyphenation points in word
+     */
+    private int len;
+
+    /**
+     * rawWord as made of alternating strings and {@link Hyphen Hyphen}
+     * instances
+     */
+    Hyphenation(String word, int[] points) {
+        this.word = word;
+        hyphenPoints = points;
+        len = points.length;
+    }
+
+    /**
+     * @return the number of hyphenation points in the word
+     */
+    public int length() {
+        return len;
+    }
+
+    /**
+     * @return the pre-break text, not including the hyphen character
+     */
+    public String getPreHyphenText(int index) {
+        return word.substring(0, hyphenPoints[index]);
+    }
+
+    /**
+     * @return the post-break text
+     */
+    public String getPostHyphenText(int index) {
+        return word.substring(hyphenPoints[index]);
+    }
+
+    /**
+     * @return the hyphenation points
+     */
+    public int[] getHyphenationPoints() {
+        return hyphenPoints;
+    }
+
+    public String toString() {
+        StringBuffer str = new StringBuffer();
+        int start = 0;
+        for (int i = 0; i < len; i++) {
+            str.append(word.substring(start, hyphenPoints[i]) + "-");
+            start = hyphenPoints[i];
+        }
+        str.append(word.substring(start));
+        return str.toString();
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationException.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationException.java
new file mode 100644
index 0000000..1c435d2
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+/**
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class HyphenationException extends Exception {
+
+    public HyphenationException(String msg) {
+        super(msg);
+    }
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationTree.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationTree.java
new file mode 100644
index 0000000..9dd23a8
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/HyphenationTree.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: HyphenationTree.java,v 1.1 2004/09/06 18:03:12 gmazza Exp $ */
+ 
+package com.lowagie.text.pdf.hyphenation;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * This tree structure stores the hyphenation patterns in an efficient
+ * way for fast lookup. It provides the provides the method to
+ * hyphenate a word.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class HyphenationTree extends TernaryTree 
+            implements PatternConsumer, Serializable {
+
+    /**
+     * value space: stores the inteletter values
+     */
+    protected ByteVector vspace;
+
+    /**
+     * This map stores hyphenation exceptions
+     */
+    protected HashMap stoplist;
+
+    /**
+     * This map stores the character classes
+     */
+    protected TernaryTree classmap;
+
+    /**
+     * Temporary map to store interletter values on pattern loading.
+     */
+    private transient TernaryTree ivalues;
+
+    public HyphenationTree() {
+        stoplist = new HashMap(23);    // usually a small table
+        classmap = new TernaryTree();
+        vspace = new ByteVector();
+        vspace.alloc(1);    // this reserves index 0, which we don't use
+    }
+
+    /**
+     * Packs the values by storing them in 4 bits, two values into a byte
+     * Values range is from 0 to 9. We use zero as terminator,
+     * so we'll add 1 to the value.
+     * @param values a string of digits from '0' to '9' representing the
+     * interletter values.
+     * @return the index into the vspace array where the packed values
+     * are stored.
+     */
+    protected int packValues(String values) {
+        int i, n = values.length();
+        int m = (n & 1) == 1 ? (n >> 1) + 2 : (n >> 1) + 1;
+        int offset = vspace.alloc(m);
+        byte[] va = vspace.getArray();
+        for (i = 0; i < n; i++) {
+            int j = i >> 1;
+            byte v = (byte)((values.charAt(i) - '0' + 1) & 0x0f);
+            if ((i & 1) == 1) {
+                va[j + offset] = (byte)(va[j + offset] | v);
+            } else {
+                va[j + offset] = (byte)(v << 4);    // big endian
+            }
+        }
+        va[m - 1 + offset] = 0;    // terminator
+        return offset;
+    }
+
+    protected String unpackValues(int k) {
+        StringBuffer buf = new StringBuffer();
+        byte v = vspace.get(k++);
+        while (v != 0) {
+            char c = (char)((v >>> 4) - 1 + '0');
+            buf.append(c);
+            c = (char)(v & 0x0f);
+            if (c == 0) {
+                break;
+            }
+            c = (char)(c - 1 + '0');
+            buf.append(c);
+            v = vspace.get(k++);
+        }
+        return buf.toString();
+    }
+
+    public void loadSimplePatterns(InputStream stream) throws HyphenationException {
+        SimplePatternParser pp = new SimplePatternParser();
+        ivalues = new TernaryTree();
+
+        pp.parse(stream, this);
+
+        // patterns/values should be now in the tree
+        // let's optimize a bit
+        trimToSize();
+        vspace.trimToSize();
+        classmap.trimToSize();
+
+        // get rid of the auxiliary map
+        ivalues = null;
+    }
+
+
+    public String findPattern(String pat) {
+        int k = super.find(pat);
+        if (k >= 0) {
+            return unpackValues(k);
+        }
+        return "";
+    }
+
+    /**
+     * String compare, returns 0 if equal or
+     * t is a substring of s
+     */
+    protected int hstrcmp(char[] s, int si, char[] t, int ti) {
+        for (; s[si] == t[ti]; si++, ti++) {
+            if (s[si] == 0) {
+                return 0;
+            }
+        }
+        if (t[ti] == 0) {
+            return 0;
+        }
+        return s[si] - t[ti];
+    }
+
+    protected byte[] getValues(int k) {
+        StringBuffer buf = new StringBuffer();
+        byte v = vspace.get(k++);
+        while (v != 0) {
+            char c = (char)((v >>> 4) - 1);
+            buf.append(c);
+            c = (char)(v & 0x0f);
+            if (c == 0) {
+                break;
+            }
+            c = (char)(c - 1);
+            buf.append(c);
+            v = vspace.get(k++);
+        }
+        byte[] res = new byte[buf.length()];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = (byte)buf.charAt(i);
+        }
+        return res;
+    }
+
+    /**
+     * <p>Search for all possible partial matches of word starting
+     * at index an update interletter values. In other words, it
+     * does something like:</p>
+     * <code>
+     * for(i=0; i<patterns.length; i++) {
+     * if ( word.substring(index).startsWidth(patterns[i]) )
+     * update_interletter_values(patterns[i]);
+     * }
+     * </code>
+     * <p>But it is done in an efficient way since the patterns are
+     * stored in a ternary tree. In fact, this is the whole purpose
+     * of having the tree: doing this search without having to test
+     * every single pattern. The number of patterns for languages
+     * such as English range from 4000 to 10000. Thus, doing thousands
+     * of string comparisons for each word to hyphenate would be
+     * really slow without the tree. The tradeoff is memory, but
+     * using a ternary tree instead of a trie, almost halves the
+     * the memory used by Lout or TeX. It's also faster than using
+     * a hash table</p>
+     * @param word null terminated word to match
+     * @param index start index from word
+     * @param il interletter values array to update
+     */
+    protected void searchPatterns(char[] word, int index, byte[] il) {
+        byte[] values;
+        int i = index;
+        char p, q;
+        char sp = word[i];
+        p = root;
+
+        while (p > 0 && p < sc.length) {
+            if (sc[p] == 0xFFFF) {
+                if (hstrcmp(word, i, kv.getArray(), lo[p]) == 0) {
+                    values = getValues(eq[p]);    // data pointer is in eq[]
+                    int j = index;
+                    for (int k = 0; k < values.length; k++) {
+                        if (j < il.length && values[k] > il[j]) {
+                            il[j] = values[k];
+                        }
+                        j++;
+                    }
+                }
+                return;
+            }
+            int d = sp - sc[p];
+            if (d == 0) {
+                if (sp == 0) {
+                    break;
+                }
+                sp = word[++i];
+                p = eq[p];
+                q = p;
+
+                // look for a pattern ending at this position by searching for
+                // the null char ( splitchar == 0 )
+                while (q > 0 && q < sc.length) {
+                    if (sc[q] == 0xFFFF) {        // stop at compressed branch
+                        break;
+                    }
+                    if (sc[q] == 0) {
+                        values = getValues(eq[q]);
+                        int j = index;
+                        for (int k = 0; k < values.length; k++) {
+                            if (j < il.length && values[k] > il[j]) {
+                                il[j] = values[k];
+                            }
+                            j++;
+                        }
+                        break;
+                    } else {
+                        q = lo[q];
+
+                        /**
+                         * actually the code should be:
+                         * q = sc[q] < 0 ? hi[q] : lo[q];
+                         * but java chars are unsigned
+                         */
+                    }
+                }
+            } else {
+                p = d < 0 ? lo[p] : hi[p];
+            }
+        }
+    }
+
+    /**
+     * Hyphenate word and return a Hyphenation object.
+     * @param word the word to be hyphenated
+     * @param remainCharCount Minimum number of characters allowed
+     * before the hyphenation point.
+     * @param pushCharCount Minimum number of characters allowed after
+     * the hyphenation point.
+     * @return a {@link Hyphenation Hyphenation} object representing
+     * the hyphenated word or null if word is not hyphenated.
+     */
+    public Hyphenation hyphenate(String word, int remainCharCount,
+                                 int pushCharCount) {
+        char[] w = word.toCharArray();
+        return hyphenate(w, 0, w.length, remainCharCount, pushCharCount);
+    }
+
+    /**
+     * w = "****nnllllllnnn*****",
+     * where n is a non-letter, l is a letter,
+     * all n may be absent, the first n is at offset,
+     * the first l is at offset + iIgnoreAtBeginning;
+     * word = ".llllll.'\0'***",
+     * where all l in w are copied into word.
+     * In the first part of the routine len = w.length,
+     * in the second part of the routine len = word.length.
+     * Three indices are used:
+     * index(w), the index in w,
+     * index(word), the index in word,
+     * letterindex(word), the index in the letter part of word.
+     * The following relations exist:
+     * index(w) = offset + i - 1
+     * index(word) = i - iIgnoreAtBeginning
+     * letterindex(word) = index(word) - 1
+     * (see first loop).
+     * It follows that:
+     * index(w) - index(word) = offset - 1 + iIgnoreAtBeginning
+     * index(w) = letterindex(word) + offset + iIgnoreAtBeginning
+     */
+
+    /**
+     * Hyphenate word and return an array of hyphenation points.
+     * @param w char array that contains the word
+     * @param offset Offset to first character in word
+     * @param len Length of word
+     * @param remainCharCount Minimum number of characters allowed
+     * before the hyphenation point.
+     * @param pushCharCount Minimum number of characters allowed after
+     * the hyphenation point.
+     * @return a {@link Hyphenation Hyphenation} object representing
+     * the hyphenated word or null if word is not hyphenated.
+     */
+    public Hyphenation hyphenate(char[] w, int offset, int len,
+                                 int remainCharCount, int pushCharCount) {
+        int i;
+        char[] word = new char[len + 3];
+
+        // normalize word
+        char[] c = new char[2];
+        int iIgnoreAtBeginning = 0;
+        int iLength = len;
+        boolean bEndOfLetters = false;
+        for (i = 1; i <= len; i++) {
+            c[0] = w[offset + i - 1];
+            int nc = classmap.find(c, 0);
+            if (nc < 0) {    // found a non-letter character ...
+                if (i == (1 + iIgnoreAtBeginning)) {
+                    // ... before any letter character
+                    iIgnoreAtBeginning ++;
+                } else {
+                    // ... after a letter character
+                    bEndOfLetters = true;
+                }
+                iLength --;
+            } else {
+                if (!bEndOfLetters) {
+                    word[i - iIgnoreAtBeginning] = (char)nc;
+                } else {
+                    return null;
+                }
+            }
+        }
+        len = iLength;
+        if (len < (remainCharCount + pushCharCount)) {
+            // word is too short to be hyphenated
+            return null;
+        }
+        int[] result = new int[len + 1];
+        int k = 0;
+
+        // check exception list first
+        String sw = new String(word, 1, len);
+        if (stoplist.containsKey(sw)) {
+            // assume only simple hyphens (Hyphen.pre="-", Hyphen.post = Hyphen.no = null)
+            ArrayList hw = (ArrayList)stoplist.get(sw);
+            int j = 0;
+            for (i = 0; i < hw.size(); i++) {
+                Object o = hw.get(i);
+                // j = index(sw) = letterindex(word)?
+                // result[k] = corresponding index(w)
+                if (o instanceof String) {
+                    j += ((String)o).length();
+                    if (j >= remainCharCount && j < (len - pushCharCount)) {
+                        result[k++] = j + iIgnoreAtBeginning;
+                    }
+                }
+            }
+        } else {
+            // use algorithm to get hyphenation points
+            word[0] = '.';                    // word start marker
+            word[len + 1] = '.';              // word end marker
+            word[len + 2] = 0;                // null terminated
+            byte[] il = new byte[len + 3];    // initialized to zero
+            for (i = 0; i < len + 1; i++) {
+                searchPatterns(word, i, il);
+            }
+
+            // hyphenation points are located where interletter value is odd
+            // i is letterindex(word),
+            // i + 1 is index(word),
+            // result[k] = corresponding index(w)
+            for (i = 0; i < len; i++) {
+                if (((il[i + 1] & 1) == 1) && i >= remainCharCount
+                        && i <= (len - pushCharCount)) {
+                    result[k++] = i + iIgnoreAtBeginning;
+                }
+            }
+        }
+
+
+        if (k > 0) {
+            // trim result array
+            int[] res = new int[k];
+            System.arraycopy(result, 0, res, 0, k);
+            return new Hyphenation(new String(w, offset, len), res);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Add a character class to the tree. It is used by
+     * {@link SimplePatternParser SimplePatternParser} as callback to
+     * add character classes. Character classes define the
+     * valid word characters for hyphenation. If a word contains
+     * a character not defined in any of the classes, it is not hyphenated.
+     * It also defines a way to normalize the characters in order
+     * to compare them with the stored patterns. Usually pattern
+     * files use only lower case characters, in this case a class
+     * for letter 'a', for example, should be defined as "aA", the first
+     * character being the normalization char.
+     */
+    public void addClass(String chargroup) {
+        if (chargroup.length() > 0) {
+            char equivChar = chargroup.charAt(0);
+            char[] key = new char[2];
+            key[1] = 0;
+            for (int i = 0; i < chargroup.length(); i++) {
+                key[0] = chargroup.charAt(i);
+                classmap.insert(key, 0, equivChar);
+            }
+        }
+    }
+
+    /**
+     * Add an exception to the tree. It is used by
+     * {@link SimplePatternParser SimplePatternParser} class as callback to
+     * store the hyphenation exceptions.
+     * @param word normalized word
+     * @param hyphenatedword a vector of alternating strings and
+     * {@link Hyphen hyphen} objects.
+     */
+    public void addException(String word, ArrayList hyphenatedword) {
+        stoplist.put(word, hyphenatedword);
+    }
+
+    /**
+     * Add a pattern to the tree. Mainly, to be used by
+     * {@link SimplePatternParser SimplePatternParser} class as callback to
+     * add a pattern to the tree.
+     * @param pattern the hyphenation pattern
+     * @param ivalue interletter weight values indicating the
+     * desirability and priority of hyphenating at a given point
+     * within the pattern. It should contain only digit characters.
+     * (i.e. '0' to '9').
+     */
+    public void addPattern(String pattern, String ivalue) {
+        int k = ivalues.find(ivalue);
+        if (k <= 0) {
+            k = packValues(ivalue);
+            ivalues.insert(ivalue, (char)k);
+        }
+        insert(pattern, (char)k);
+    }
+
+    public void printStats() {
+        System.out.println("Value space size = "
+                           + Integer.toString(vspace.length()));
+        super.printStats();
+    }
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenator.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenator.java
new file mode 100644
index 0000000..142ef85
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/Hyphenator.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.Hashtable;
+import com.lowagie.text.pdf.BaseFont;
+
+/**
+ * This class is the main entry point to the hyphenation package.
+ * You can use only the static methods or create an instance.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public class Hyphenator {
+    
+    /**@todo Don't use statics */
+    private static Hashtable hyphenTrees = new Hashtable();
+
+    private HyphenationTree hyphenTree = null;
+    private int remainCharCount = 2;
+    private int pushCharCount = 2;
+    private static boolean errorDump = false;
+    private static final String defaultHyphLocation = "com/lowagie/text/pdf/hyphenation/hyph/";
+   
+    /** Holds value of property hyphenDir. */
+    private static String hyphenDir = "";    
+
+    public Hyphenator(String lang, String country, int leftMin,
+                      int rightMin) {
+        hyphenTree = getHyphenationTree(lang, country);
+        remainCharCount = leftMin;
+        pushCharCount = rightMin;
+    }
+
+    public static HyphenationTree getHyphenationTree(String lang,
+            String country) {
+        String key = lang;
+        // check whether the country code has been used
+        if (country != null && !country.equals("none")) {
+            key += "_" + country;
+        }
+            // first try to find it in the cache
+        if (hyphenTrees.containsKey(key)) {
+            return (HyphenationTree)hyphenTrees.get(key);
+        }
+        if (hyphenTrees.containsKey(lang)) {
+            return (HyphenationTree)hyphenTrees.get(lang);
+        }
+
+        HyphenationTree hTree = getResourceHyphenationTree(key);
+        if (hTree == null)
+            hTree = getFileHyphenationTree(key);
+        // put it into the pattern cache
+        if (hTree != null) {
+            hyphenTrees.put(key, hTree);
+        }
+        return hTree;
+    }
+
+    public static HyphenationTree getResourceHyphenationTree(String key) {
+        try {
+            InputStream stream = BaseFont.getResourceStream(defaultHyphLocation + key + ".xml");
+            if (stream == null && key.length() > 2)
+                stream = BaseFont.getResourceStream(defaultHyphLocation + key.substring(0, 2) + ".xml");
+            if (stream == null)
+                return null;
+            HyphenationTree hTree = new HyphenationTree();
+            hTree.loadSimplePatterns(stream);
+            return hTree;
+        }
+        catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static HyphenationTree getFileHyphenationTree(String key) {
+        try {
+            if (hyphenDir == null)
+                return null;
+            InputStream stream = null;
+            File hyphenFile = new File(hyphenDir, key + ".xml");
+            if (hyphenFile.canRead())
+                stream = new FileInputStream(hyphenFile);
+            if (stream == null && key.length() > 2) {
+                hyphenFile = new File(hyphenDir, key.substring(0, 2) + ".xml");
+                if (hyphenFile.canRead())
+                    stream = new FileInputStream(hyphenFile);
+            }
+            if (stream == null)
+                return null;
+            HyphenationTree hTree = new HyphenationTree();
+            hTree.loadSimplePatterns(stream);
+            return hTree;
+        }
+        catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static Hyphenation hyphenate(String lang, String country,
+                                        String word, int leftMin,
+                                        int rightMin) {
+        HyphenationTree hTree = getHyphenationTree(lang, country);
+        if (hTree == null) {
+            //log.error("Error building hyphenation tree for language "
+            //                       + lang);
+            return null;
+        }
+        return hTree.hyphenate(word, leftMin, rightMin);
+    }
+
+    public static Hyphenation hyphenate(String lang, String country,
+                                        char[] word, int offset, int len,
+                                        int leftMin, int rightMin) {
+        HyphenationTree hTree = getHyphenationTree(lang, country);
+        if (hTree == null) {
+            //log.error("Error building hyphenation tree for language "
+            //                       + lang);
+            return null;
+        }
+        return hTree.hyphenate(word, offset, len, leftMin, rightMin);
+    }
+
+    public void setMinRemainCharCount(int min) {
+        remainCharCount = min;
+    }
+
+    public void setMinPushCharCount(int min) {
+        pushCharCount = min;
+    }
+
+    public void setLanguage(String lang, String country) {
+        hyphenTree = getHyphenationTree(lang, country);
+    }
+
+    public Hyphenation hyphenate(char[] word, int offset, int len) {
+        if (hyphenTree == null) {
+            return null;
+        }
+        return hyphenTree.hyphenate(word, offset, len, remainCharCount,
+                                    pushCharCount);
+    }
+
+    public Hyphenation hyphenate(String word) {
+        if (hyphenTree == null) {
+            return null;
+        }
+        return hyphenTree.hyphenate(word, remainCharCount, pushCharCount);
+    }
+
+    /** Getter for property hyphenDir.
+     * @return Value of property hyphenDir.
+     */
+    public static String getHyphenDir() {
+        return hyphenDir;
+    }
+    
+    /** Setter for property hyphenDir.
+     * @param _hyphenDir New value of property hyphenDir.
+     */
+    public static void setHyphenDir(String _hyphenDir) {
+        hyphenDir = _hyphenDir;
+    }
+    
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/PatternConsumer.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/PatternConsumer.java
new file mode 100644
index 0000000..148bded
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/PatternConsumer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.util.ArrayList;
+
+/**
+ * This interface is used to connect the XML pattern file parser to
+ * the hyphenation tree.
+ *
+ * @author Carlos Villegas <cav at uniscope.co.jp>
+ */
+public interface PatternConsumer {
+
+    /**
+     * Add a character class.
+     * A character class defines characters that are considered
+     * equivalent for the purpose of hyphenation (e.g. "aA"). It
+     * usually means to ignore case.
+     * @param chargroup character group
+     */
+    void addClass(String chargroup);
+
+    /**
+     * Add a hyphenation exception. An exception replaces the
+     * result obtained by the algorithm for cases for which this
+     * fails or the user wants to provide his own hyphenation.
+     * A hyphenatedword is a vector of alternating String's and
+     * {@link Hyphen Hyphen} instances
+     */
+    void addException(String word, ArrayList hyphenatedword);
+
+    /**
+     * Add hyphenation patterns.
+     * @param pattern the pattern
+     * @param values interletter values expressed as a string of
+     * digit characters.
+     */
+    void addPattern(String pattern, String values);
+
+}
+
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/SimplePatternParser.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/SimplePatternParser.java
new file mode 100644
index 0000000..85fa57e
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/SimplePatternParser.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the License.
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+ * provisions of LGPL are applicable instead of those above.  If you wish to
+ * allow use of your version of this file only under the terms of the LGPL
+ * License and not to allow others to use your version of this file under
+ * the MPL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the LGPL.
+ * If you do not delete the provisions above, a recipient may use your version
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MPL as stated above or under the terms of the GNU
+ * Library General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+ * details.
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import com.lowagie.text.pdf.*;
+import com.lowagie.text.ExceptionConverter;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FileInputStream;
+
+/** Parses the xml hyphenation pattern.
+ *
+ * @author Paulo Soares (psoares at consiste.pt)
+ */
+public class SimplePatternParser implements SimpleXMLDocHandler, PatternConsumer {
+    int currElement;
+    PatternConsumer consumer;
+    StringBuffer token;
+    ArrayList exception;
+    char hyphenChar;
+    SimpleXMLParser parser;
+    
+    static final int ELEM_CLASSES = 1;
+    static final int ELEM_EXCEPTIONS = 2;
+    static final int ELEM_PATTERNS = 3;
+    static final int ELEM_HYPHEN = 4;
+
+    /** Creates a new instance of PatternParser2 */
+    public SimplePatternParser() {
+        token = new StringBuffer();
+        hyphenChar = '-';    // default
+    }
+    
+    public void parse(InputStream stream, PatternConsumer consumer) {
+        this.consumer = consumer;
+        try {
+            SimpleXMLParser.parse(this, stream);
+        }
+        catch (IOException e) {
+            throw new ExceptionConverter(e);
+        }
+        finally {
+            try{stream.close();}catch(Exception e){}
+        }
+    }
+    
+    protected static String getPattern(String word) {
+        StringBuffer pat = new StringBuffer();
+        int len = word.length();
+        for (int i = 0; i < len; i++) {
+            if (!Character.isDigit(word.charAt(i))) {
+                pat.append(word.charAt(i));
+            }
+        }
+        return pat.toString();
+    }
+
+    protected ArrayList normalizeException(ArrayList ex) {
+        ArrayList res = new ArrayList();
+        for (int i = 0; i < ex.size(); i++) {
+            Object item = ex.get(i);
+            if (item instanceof String) {
+                String str = (String)item;
+                StringBuffer buf = new StringBuffer();
+                for (int j = 0; j < str.length(); j++) {
+                    char c = str.charAt(j);
+                    if (c != hyphenChar) {
+                        buf.append(c);
+                    } else {
+                        res.add(buf.toString());
+                        buf.setLength(0);
+                        char[] h = new char[1];
+                        h[0] = hyphenChar;
+                        // we use here hyphenChar which is not necessarily
+                        // the one to be printed
+                        res.add(new Hyphen(new String(h), null, null));
+                    }
+                }
+                if (buf.length() > 0) {
+                    res.add(buf.toString());
+                }
+            } else {
+                res.add(item);
+            }
+        }
+        return res;
+    }
+
+    protected String getExceptionWord(ArrayList ex) {
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < ex.size(); i++) {
+            Object item = ex.get(i);
+            if (item instanceof String) {
+                res.append((String)item);
+            } else {
+                if (((Hyphen)item).noBreak != null) {
+                    res.append(((Hyphen)item).noBreak);
+                }
+            }
+        }
+        return res.toString();
+    }
+
+    protected static String getInterletterValues(String pat) {
+        StringBuffer il = new StringBuffer();
+        String word = pat + "a";    // add dummy letter to serve as sentinel
+        int len = word.length();
+        for (int i = 0; i < len; i++) {
+            char c = word.charAt(i);
+            if (Character.isDigit(c)) {
+                il.append(c);
+                i++;
+            } else {
+                il.append('0');
+            }
+        }
+        return il.toString();
+    }
+
+    public void endDocument() {
+    }
+    
+    public void endElement(String tag) {
+        if (token.length() > 0) {
+            String word = token.toString();
+            switch (currElement) {
+            case ELEM_CLASSES:
+                consumer.addClass(word);
+                break;
+            case ELEM_EXCEPTIONS:
+                exception.add(word);
+                exception = normalizeException(exception);
+                consumer.addException(getExceptionWord(exception),
+                                      (ArrayList)exception.clone());
+                break;
+            case ELEM_PATTERNS:
+                consumer.addPattern(getPattern(word),
+                                    getInterletterValues(word));
+                break;
+            case ELEM_HYPHEN:
+                // nothing to do
+                break;
+            }
+            if (currElement != ELEM_HYPHEN) {
+                token.setLength(0);
+            }
+        }
+        if (currElement == ELEM_HYPHEN) {
+            currElement = ELEM_EXCEPTIONS;
+        } else {
+            currElement = 0;
+        }
+    }
+    
+    public void startDocument() {
+    }
+    
+    public void startElement(String tag, java.util.HashMap h) {
+        if (tag.equals("hyphen-char")) {
+            String hh = (String)h.get("value");
+            if (hh != null && hh.length() == 1) {
+                hyphenChar = hh.charAt(0);
+            }
+        } else if (tag.equals("classes")) {
+            currElement = ELEM_CLASSES;
+        } else if (tag.equals("patterns")) {
+            currElement = ELEM_PATTERNS;
+        } else if (tag.equals("exceptions")) {
+            currElement = ELEM_EXCEPTIONS;
+            exception = new ArrayList();
+        } else if (tag.equals("hyphen")) {
+            if (token.length() > 0) {
+                exception.add(token.toString());
+            }
+            exception.add(new Hyphen((String)h.get("pre"),
+                                            (String)h.get("no"),
+                                            (String)h.get("post")));
+            currElement = ELEM_HYPHEN;
+        }
+        token.setLength(0);
+    }
+    
+    public void text(String str) {
+        StringTokenizer tk = new StringTokenizer(str);
+        while (tk.hasMoreTokens()) {
+            String word = tk.nextToken();
+            // System.out.println("\"" + word + "\"");
+            switch (currElement) {
+            case ELEM_CLASSES:
+                consumer.addClass(word);
+                break;
+            case ELEM_EXCEPTIONS:
+                exception.add(word);
+                exception = normalizeException(exception);
+                consumer.addException(getExceptionWord(exception),
+                                      (ArrayList)exception.clone());
+                exception.clear();
+                break;
+            case ELEM_PATTERNS:
+                consumer.addPattern(getPattern(word),
+                                    getInterletterValues(word));
+                break;
+            }
+        }
+    }
+    
+    // PatternConsumer implementation for testing purposes
+    public void addClass(String c) {
+        System.out.println("class: " + c);
+    }
+
+    public void addException(String w, ArrayList e) {
+        System.out.println("exception: " + w + " : " + e.toString());
+    }
+
+    public void addPattern(String p, String v) {
+        System.out.println("pattern: " + p + " : " + v);
+    }
+
+    public static void main(String[] args) throws Exception {
+        try {
+            if (args.length > 0) {
+                SimplePatternParser pp = new SimplePatternParser();
+                pp.parse(new FileInputStream(args[0]), pp);
+            }
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/LibrarySource/com/lowagie/text/pdf/hyphenation/TernaryTree.java b/LibrarySource/com/lowagie/text/pdf/hyphenation/TernaryTree.java
new file mode 100644
index 0000000..39658e6
--- /dev/null
+++ b/LibrarySource/com/lowagie/text/pdf/hyphenation/TernaryTree.java
@@ -0,0 +1,668 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.lowagie.text.pdf.hyphenation;
+
+import java.util.Enumeration;
+import java.util.Stack;
+import java.io.Serializable;
+
+/**
+ * <h2>Ternary Search Tree.</h2>
+ *
+ * <p>A ternary search tree is a hibrid between a binary tree and
+ * a digital search tree (trie). Keys are limited to strings.
+ * A data value of type char is stored in each leaf node.
+ * It can be used as an index (or pointer) to the data.
+ * Branches that only contain one key are compressed to one node
+ * by storing a pointer to the trailer substring of the key.
+ * This class is intended to serve as base class or helper class
+ * to implement Dictionary collections or the like. Ternary trees
+ * have some nice properties as the following: the tree can be
+ * traversed in sorted order, partial matches (wildcard) can be
+ * implemented, retrieval of all keys within a given distance
+ * from the target, etc. The storage requirements are higher than
+ * a binary tree but a lot less than a trie. Performance is
+ * comparable with a hash table, sometimes it outperforms a hash
+ * function (most of the time can determine a miss faster than a hash).</p>
+ *
+ * <p>The main purpose of this java port is to serve as a base for
+ * implementing TeX's hyphenation algorithm (see The TeXBook,
+ * appendix H). Each language requires from 5000 to 15000 hyphenation
+ * patterns which will be keys in this tree. The strings patterns
+ * are usually small (from 2 to 5 characters), but each char in the
+ * tree is stored in a node. Thus memory usage is the main concern.
+ * We will sacrify 'elegance' to keep memory requirenments to the
+ * minimum. Using java's char type as pointer (yes, I know pointer
+ * it is a forbidden word in java) we can keep the size of the node
+ * to be just 8 bytes (3 pointers and the data char). This gives
+ * room for about 65000 nodes. In my tests the english patterns
+ * took 7694 nodes and the german patterns 10055 nodes,
+ * so I think we are safe.</p>
+ *
+ * <p>All said, this is a map with strings as keys and char as value.
+ * Pretty limited!. It can be extended to a general map by
+ * using the string representation of an object and using the
+ * char value as an index to an array that contains the object
+ * values.</p>
+ *
+ * @author cav at uniscope.co.jp
+ */
+
+public class TernaryTree implements Cloneable, Serializable {
+
+    /**
+     * We use 4 arrays to represent a node. I guess I should have created
+     * a proper node class, but somehow Knuth's pascal code made me forget
+     * we now have a portable language with virtual memory management and
+     * automatic garbage collection! And now is kind of late, furthermore,
+     * if it ain't broken, don't fix it.
+     */
+
+    /**
+     * Pointer to low branch and to rest of the key when it is
+     * stored directly in this node, we don't have unions in java!
+     */
+    protected char[] lo;
+
+    /**
+     * Pointer to high branch.
+     */
+    protected char[] hi;
+
+    /**
+     * Pointer to equal branch and to data when this node is a string terminator.
+     */
+    protected char[] eq;
+
+    /**
+     * <P>The character stored in this node: splitchar.
+     * Two special values are reserved:</P>
+     * <ul><li>0x0000 as string terminator</li>
+     * <li>0xFFFF to indicate that the branch starting at
+     * this node is compressed</li></ul>
+     * <p>This shouldn't be a problem if we give the usual semantics to
+     * strings since 0xFFFF is garanteed not to be an Unicode character.</p>
+     */
+    protected char[] sc;
+
+    /**
+     * This vector holds the trailing of the keys when the branch is compressed.
+     */
+    protected CharVector kv;
+
+    protected char root;
+    protected char freenode;
+    protected int length;    // number of items in tree
+
+    protected static final int BLOCK_SIZE = 2048;    // allocation size for arrays
+
+    TernaryTree() {
+        init();
+    }
+
+    protected void init() {
+        root = 0;
+        freenode = 1;
+        length = 0;
+        lo = new char[BLOCK_SIZE];
+        hi = new char[BLOCK_SIZE];
+        eq = new char[BLOCK_SIZE];
+        sc = new char[BLOCK_SIZE];
+        kv = new CharVector();
+    }
+
+    /**
+     * Branches are initially compressed, needing
+     * one node per key plus the size of the string
+     * key. They are decompressed as needed when
+     * another key with same prefix
+     * is inserted. This saves a lot of space,
+     * specially for long keys.
+     */
+    public void insert(String key, char val) {
+        // make sure we have enough room in the arrays
+        int len = key.length()
+                  + 1;    // maximum number of nodes that may be generated
+        if (freenode + len > eq.length) {
+            redimNodeArrays(eq.length + BLOCK_SIZE);
+        }
+        char strkey[] = new char[len--];
+        key.getChars(0, len, strkey, 0);
+        strkey[len] = 0;
+        root = insert(root, strkey, 0, val);
+    }
+
+    public void insert(char[] key, int start, char val) {
+        int len = strlen(key) + 1;
+        if (freenode + len > eq.length) {
+            redimNodeArrays(eq.length + BLOCK_SIZE);
+        }
+        root = insert(root, key, start, val);
+    }
+
+    /**
+     * The actual insertion function, recursive version.
+     */
+    private char insert(char p, char[] key, int start, char val) {
+        int len = strlen(key, start);
+        if (p == 0) {
+            // this means there is no branch, this node will start a new branch.
+            // Instead of doing that, we store the key somewhere else and create
+            // only one node with a pointer to the key
+            p = freenode++;
+            eq[p] = val;           // holds data
+            length++;
+            hi[p] = 0;
+            if (len > 0) {
+                sc[p] = 0xFFFF;    // indicates branch is compressed
+                lo[p] = (char)kv.alloc(len
+                                       + 1);    // use 'lo' to hold pointer to key
+                strcpy(kv.getArray(), lo[p], key, start);
+            } else {
+                sc[p] = 0;
+                lo[p] = 0;
+            }
+            return p;
+        }
+
+        if (sc[p] == 0xFFFF) {
+            // branch is compressed: need to decompress
+            // this will generate garbage in the external key array
+            // but we can do some garbage collection later
+            char pp = freenode++;
+            lo[pp] = lo[p];    // previous pointer to key
+            eq[pp] = eq[p];    // previous pointer to data
+            lo[p] = 0;
+            if (len > 0) {
+                sc[p] = kv.get(lo[pp]);
+                eq[p] = pp;
+                lo[pp]++;
+                if (kv.get(lo[pp]) == 0) {
+                    // key completly decompressed leaving garbage in key array
+                    lo[pp] = 0;
+                    sc[pp] = 0;
+                    hi[pp] = 0;
+                } else {
+                    // we only got first char of key, rest is still there
+                    sc[pp] = 0xFFFF;
+                }
+            } else {
+                // In this case we can save a node by swapping the new node
+                // with the compressed node
+                sc[pp] = 0xFFFF;
+                hi[p] = pp;
+                sc[p] = 0;
+                eq[p] = val;
+                length++;
+                return p;
+            }
+        }
+        char s = key[start];
+        if (s < sc[p]) {
+            lo[p] = insert(lo[p], key, start, val);
+        } else if (s == sc[p]) {
+            if (s != 0) {
+                eq[p] = insert(eq[p], key, start + 1, val);
+            } else {
+                // key already in tree, overwrite data
+                eq[p] = val;
+            }
+        } else {
+            hi[p] = insert(hi[p], key, start, val);
+        }
+        return p;
+    }
+
+    /**
+     * Compares 2 null terminated char arrays
+     */
+    public static int strcmp(char[] a, int startA, char[] b, int startB) {
+        for (; a[startA] == b[startB]; startA++, startB++) {
+            if (a[startA] == 0) {
+                return 0;
+            }
+        }
+        return a[startA] - b[startB];
+    }
+
+    /**
+     * Compares a string with null terminated char array
+     */
+    public static int strcmp(String str, char[] a, int start) {
+        int i, d, len = str.length();
+        for (i = 0; i < len; i++) {
+            d = (int)str.charAt(i) - a[start + i];
+            if (d != 0) {
+                return d;
+            }
+            if (a[start + i] == 0) {
+                return d;
+        }
+        }
+        if (a[start + i] != 0) {
+            return (int)-a[start + i];
+        }
+        return 0;
+
+    }
+
+    public static void strcpy(char[] dst, int di, char[] src, int si) {
+        while (src[si] != 0) {
+            dst[di++] = src[si++];
+        }
+        dst[di] = 0;
+    }
+
+    public static int strlen(char[] a, int start) {
+        int len = 0;
+        for (int i = start; i < a.length && a[i] != 0; i++) {
+            len++;
+        }
+        return len;
+    }
+
+    public static int strlen(char[] a) {
+        return strlen(a, 0);
+    }
+
+    public int find(String key) {
+        int len = key.length();
+        char strkey[] = new char[len + 1];
+        key.getChars(0, len, strkey, 0);
+        strkey[len] = 0;
+
+        return find(strkey, 0);
+    }
+
+    public int find(char[] key, int start) {
+        int d;
+        char p = root;
+        int i = start;
+        char c;
+
+        while (p != 0) {
+            if (sc[p] == 0xFFFF) {
+                if (strcmp(key, i, kv.getArray(), lo[p]) == 0) {
+                    return eq[p];
+                } else {
+                    return -1;
+            }
+            }
+            c = key[i];
+            d = c - sc[p];
+            if (d == 0) {
+                if (c == 0) {
+                    return eq[p];
+                }
+                i++;
+                p = eq[p];
+            } else if (d < 0) {
+                p = lo[p];
+            } else {
+                p = hi[p];
+        }
+        }
+        return -1;
+    }
+
+    public boolean knows(String key) {
+        return (find(key) >= 0);
+    }
+
+    // redimension the arrays
+    private void redimNodeArrays(int newsize) {
+        int len = newsize < lo.length ? newsize : lo.length;
+        char[] na = new char[newsize];
+        System.arraycopy(lo, 0, na, 0, len);
+        lo = na;
+        na = new char[newsize];
+        System.arraycopy(hi, 0, na, 0, len);
+        hi = na;
+        na = new char[newsize];
+        System.arraycopy(eq, 0, na, 0, len);
+        eq = na;
+        na = new char[newsize];
+        System.arraycopy(sc, 0, na, 0, len);
+        sc = na;
+    }
+
+    public int size() {
+        return length;
+    }
+
+    public Object clone() {
+        TernaryTree t = new TernaryTree();
+        t.lo = (char[])this.lo.clone();
+        t.hi = (char[])this.hi.clone();
+        t.eq = (char[])this.eq.clone();
+        t.sc = (char[])this.sc.clone();
+        t.kv = (CharVector)this.kv.clone();
+        t.root = this.root;
+        t.freenode = this.freenode;
+        t.length = this.length;
+
+        return t;
+    }
+
+    /**
+     * Recursively insert the median first and then the median of the
+     * lower and upper halves, and so on in order to get a balanced
+     * tree. The array of keys is assumed to be sorted in ascending
+     * order.
+     */
+    protected void insertBalanced(String[] k, char[] v, int offset, int n) {
+        int m;
+        if (n < 1) {
+            return;
+        }
+        m = n >> 1;
+
+        insert(k[m + offset], v[m + offset]);
+        insertBalanced(k, v, offset, m);
+
+        insertBalanced(k, v, offset + m + 1, n - m - 1);
+    }
+
+
+    /**
+     * Balance the tree for best search performance
+     */
+    public void balance() {
+        // System.out.print("Before root splitchar = "); System.out.println(sc[root]);
+
+        int i = 0, n = length;
+        String[] k = new String[n];
+        char[] v = new char[n];
+        Iterator iter = new Iterator();
+        while (iter.hasMoreElements()) {
+            v[i] = iter.getValue();
+            k[i++] = (String)iter.nextElement();
+        }
+        init();
+        insertBalanced(k, v, 0, n);
+
+        // With uniform letter distribution sc[root] should be around 'm'
+        // System.out.print("After root splitchar = "); System.out.println(sc[root]);
+    }
+
+    /**
+     * Each node stores a character (splitchar) which is part of
+     * some key(s). In a compressed branch (one that only contain
+     * a single string key) the trailer of the key which is not
+     * already in nodes is stored  externally in the kv array.
+     * As items are inserted, key substrings decrease.
+     * Some substrings may completely  disappear when the whole
+     * branch is totally decompressed.
+     * The tree is traversed to find the key substrings actually
+     * used. In addition, duplicate substrings are removed using
+     * a map (implemented with a TernaryTree!).
+     *
+     */
+    public void trimToSize() {
+        // first balance the tree for best performance
+        balance();
+
+        // redimension the node arrays
+        redimNodeArrays(freenode);
+
+        // ok, compact kv array
+        CharVector kx = new CharVector();
+        kx.alloc(1);
+        TernaryTree map = new TernaryTree();
+        compact(kx, map, root);
+        kv = kx;
+        kv.trimToSize();
+    }
+
+    private void compact(CharVector kx, TernaryTree map, char p) {
+        int k;
+        if (p == 0) {
+            return;
+        }
+        if (sc[p] == 0xFFFF) {
+            k = map.find(kv.getArray(), lo[p]);
+            if (k < 0) {
+                k = kx.alloc(strlen(kv.getArray(), lo[p]) + 1);
+                strcpy(kx.getArray(), k, kv.getArray(), lo[p]);
+                map.insert(kx.getArray(), k, (char)k);
+            }
+            lo[p] = (char)k;
+        } else {
+            compact(kx, map, lo[p]);
+            if (sc[p] != 0) {
+                compact(kx, map, eq[p]);
+            }
+            compact(kx, map, hi[p]);
+        }
+    }
+
+
+    public Enumeration keys() {
+        return new Iterator();
+    }
+
+    public class Iterator implements Enumeration {
+
+        /**
+         * current node index
+         */
+        int cur;
+
+        /**
+         * current key
+         */
+        String curkey;
+
+        private class Item implements Cloneable {
+            char parent;
+            char child;
+
+            public Item() {
+                parent = 0;
+                child = 0;
+            }
+
+            public Item(char p, char c) {
+                parent = p;
+                child = c;
+            }
+
+            public Object clone() {
+                return new Item(parent, child);
+            }
+
+        }
+
+        /**
+         * Node stack
+         */
+        Stack ns;
+
+        /**
+         * key stack implemented with a StringBuffer
+         */
+        StringBuffer ks;
+
+        public Iterator() {
+            cur = -1;
+            ns = new Stack();
+            ks = new StringBuffer();
+            rewind();
+        }
+
+        public void rewind() {
+            ns.removeAllElements();
+            ks.setLength(0);
+            cur = root;
+            run();
+        }
+
+        public Object nextElement() {
+            String res = new String(curkey);
+            cur = up();
+            run();
+            return res;
+        }
+
+        public char getValue() {
+            if (cur >= 0) {
+                return eq[cur];
+            }
+            return 0;
+        }
+
+        public boolean hasMoreElements() {
+            return (cur != -1);
+        }
+
+        /**
+         * traverse upwards
+         */
+        private int up() {
+            Item i = new Item();
+            int res = 0;
+
+            if (ns.empty()) {
+                return -1;
+            }
+
+            if (cur != 0 && sc[cur] == 0) {
+                return lo[cur];
+            }
+
+            boolean climb = true;
+
+            while (climb) {
+                i = (Item)ns.pop();
+                i.child++;
+                switch (i.child) {
+                case 1:
+                    if (sc[i.parent] != 0) {
+                        res = eq[i.parent];
+                        ns.push(i.clone());
+                        ks.append(sc[i.parent]);
+                    } else {
+                        i.child++;
+                        ns.push(i.clone());
+                        res = hi[i.parent];
+                    }
+                    climb = false;
+                    break;
+
+                case 2:
+                    res = hi[i.parent];
+                    ns.push(i.clone());
+                    if (ks.length() > 0) {
+                        ks.setLength(ks.length() - 1);    // pop
+                    }
+                    climb = false;
+                    break;
+
+                default:
+                    if (ns.empty()) {
+                        return -1;
+                    }
+                    climb = true;
+                    break;
+                }
+            }
+            return res;
+        }
+
+        /**
+         * traverse the tree to find next key
+         */
+        private int run() {
+            if (cur == -1) {
+                return -1;
+            }
+
+            boolean leaf = false;
+            while (true) {
+                // first go down on low branch until leaf or compressed branch
+                while (cur != 0) {
+                    if (sc[cur] == 0xFFFF) {
+                        leaf = true;
+                        break;
+                    }
+                    ns.push(new Item((char)cur, '\u0000'));
+                    if (sc[cur] == 0) {
+                        leaf = true;
+                        break;
+                    }
+                    cur = lo[cur];
+                }
+                if (leaf) {
+                    break;
+                }
+                    // nothing found, go up one node and try again
+                cur = up();
+                if (cur == -1) {
+                    return -1;
+                }
+            }
+            // The current node should be a data node and
+            // the key should be in the key stack (at least partially)
+            StringBuffer buf = new StringBuffer(ks.toString());
+            if (sc[cur] == 0xFFFF) {
+                int p = lo[cur];
+                while (kv.get(p) != 0) {
+                    buf.append(kv.get(p++));
+            }
+            }
+            curkey = buf.toString();
+            return 0;
+        }
+
+    }
+
+    public void printStats() {
+        System.out.println("Number of keys = " + Integer.toString(length));
+        System.out.println("Node count = " + Integer.toString(freenode));
+        // System.out.println("Array length = " + Integer.toString(eq.length));
+        System.out.println("Key Array length = "
+                           + Integer.toString(kv.length()));
+
+        /*
+         * for(int i=0; i<kv.length(); i++)
+         * if ( kv.get(i) != 0 )
+         * System.out.print(kv.get(i));
+         * else
+         * System.out.println("");
+         * System.out.println("Keys:");
+         * for(Enumeration enum = keys(); enum.hasMoreElements(); )
+         * System.out.println(enum.nextElement());
+         */
+
+    }
+
+/*    public static void main(String[] args) throws Exception {
+        TernaryTree tt = new TernaryTree();
+        tt.insert("Carlos", 'C');
+        tt.insert("Car", 'r');
+        tt.insert("palos", 'l');
+        tt.insert("pa", 'p');
+        tt.trimToSize();
+        System.out.println((char)tt.find("Car"));
+        System.out.println((char)tt.find("Carlos"));
+        System.out.println((char)tt.find("alto"));
+        tt.printStats();
+    }*/
+
+}
+
+
diff --git a/LibrarySource/pal/alignment/AbstractAlignment.java b/LibrarySource/pal/alignment/AbstractAlignment.java
new file mode 100644
index 0000000..5d4d2f2
--- /dev/null
+++ b/LibrarySource/pal/alignment/AbstractAlignment.java
@@ -0,0 +1,177 @@
+// AbstractAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.io.*;
+import pal.datatype.*;
+import pal.misc.*;
+
+import java.io.*;
+
+/**
+ * abstract base class for any alignment data.
+ *
+ * @version $Id: AbstractAlignment.java,v 1.3 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+abstract public class AbstractAlignment implements Alignment, Serializable, IdGroup, Report
+{
+	//
+	// Public stuff
+	//
+
+	public AbstractAlignment()
+	{
+		
+	}
+
+	/** number of sequences */
+	protected int numSeqs;
+
+	/** length of each sequence */
+	protected int numSites;
+
+	/** sequence identifiers */
+	protected IdGroup idGroup;
+
+	/**
+	 * frequencies of the allowed states 
+	 * (scaled to sum to 1.0 and suitable for RateMatrix)
+	 */
+	protected double[] frequency;
+
+	/** data type */
+	protected DataType dataType;
+		
+	// Abstract method
+
+	/** sequence alignment at (sequence, site) */
+	abstract public char getData(int seq, int site);
+
+	/** 
+	 * returns true if there is a gap in the give position.
+	 */
+	public boolean isGap(int seq, int site) {
+		return DataTypeUtils.isGap(dataType, getData(seq, site));
+	}
+
+	/** Guess data type */
+	public void guessDataType()
+	{
+		dataType = AlignmentUtils.getSuitableInstance(this);
+	}
+
+	/** Returns the datatype of this alignment */
+	public DataType getDataType()
+	{
+		return dataType;
+	}
+
+	/** Sets the datatype of this alignment */
+	public void setDataType(DataType d)
+	{
+		dataType = d;
+
+		// if dataType was guessed incorrectly  then when corrected
+		// the frequencies should be recalculated.
+		AlignmentUtils.estimateFrequencies(this);
+	}
+
+	/** returns representation of this alignment as a string */
+	public String toString() {
+	
+		StringWriter sw = new StringWriter();
+		AlignmentUtils.print(this, new PrintWriter(sw));
+		
+		return sw.toString();
+	}
+
+	// interface Report
+	
+	public void report(PrintWriter out)
+	{
+		AlignmentUtils.report(this, out);
+	}
+
+	
+	/**
+	 * Fills a [numsequences][length] matrix with indices. 
+	 * Each index represents the sequence state, -1 means a gap.
+	 */
+	public int[][] getStates() {
+	
+		int[][] indices = new int[numSeqs][numSites];
+
+		for (int i = 0; i < numSeqs; i++) {
+			int seqcounter = 0;
+	   
+			for (int j = 0; j < numSites; j++) {
+		
+				indices[i][j] = dataType.getState(getData(i, j));
+			
+				if (indices[i][j] >= dataType.getNumStates()) {
+					indices[i][j] = -1;
+				}
+			}
+		}
+
+		return indices;
+	}
+
+   	/**
+	 * Return number of sites in this alignment
+	 */
+	public final int getLength() {
+		return numSites;
+	}
+
+	/**
+	 * Return number of sequences in this alignment
+	 */
+	public final int getSequenceCount() {
+		return numSeqs;
+	}
+
+	/**
+	 * Return number of sites for each sequence in this alignment
+	 * @note for people who like accessor methods over public instance variables...
+	 */
+	public final int getSiteCount() {
+		return numSites;
+	}
+	/**
+	 * Returns a string representing a single sequence (including gaps)
+	 * from this alignment.
+	 */
+	public String getAlignedSequenceString(int seq) {
+		char[] data = new char[numSites];
+		for (int i = 0; i < numSites; i++) {
+			data[i] = getData(seq, i);
+		}
+		return new String(data);
+	}
+
+	//IdGroup interface
+	public Identifier getIdentifier(int i) {return idGroup.getIdentifier(i);}
+	public void setIdentifier(int i, Identifier ident) { idGroup.setIdentifier(i, ident); }
+	public int getIdCount() { return idGroup.getIdCount(); }
+	public int whichIdNumber(String name) { return idGroup.whichIdNumber(name); }
+
+	public double[] getFrequency() {
+		return frequency;
+	}
+
+	public void setFrequency(double[] f) {
+		frequency = f;
+	}
+
+}
+
diff --git a/LibrarySource/pal/alignment/Alignment.java b/LibrarySource/pal/alignment/Alignment.java
new file mode 100644
index 0000000..011976d
--- /dev/null
+++ b/LibrarySource/pal/alignment/Alignment.java
@@ -0,0 +1,77 @@
+// Alignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.io.*;
+import pal.datatype.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * interface for any alignment data.
+ *
+ * @version $Id: Alignment.java,v 1.11 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public interface Alignment extends Serializable, IdGroup
+{
+	//
+	// Public stuff
+	//
+
+	/** character used to designate gaps */
+	char GAP = '-';
+
+	// Abstract method
+
+	/** sequence alignment at (sequence, site) */
+	char getData(int seq, int site);	
+	
+   	/**
+	 * Return number of sites for each sequence in this alignment
+	 * @note for people who like accessor methods over public instance variables...
+	 */
+	int getSiteCount();	
+
+	/**
+	 * Return number of sequences in this alignment
+	 */
+	int getSequenceCount();
+
+	/**
+	 * Return DataType of this alignment.
+	 */
+	DataType getDataType();
+
+	/**
+	 * Sets the dataType of this alignment.
+	 */
+	void setDataType(DataType dataType);
+
+	/**
+	 * Returns string representation of single sequence in 
+	 * alignment with gap characters included.
+	 */
+	String getAlignedSequenceString(int sequence);
+
+	/**
+	 * Returns frequency of character states.
+	 */
+	double[] getFrequency();
+
+	/**
+	 * Sets frequency of character states.
+	 */
+	void setFrequency(double[] frequencies);
+}	
+
diff --git a/LibrarySource/pal/alignment/AlignmentParseException.java b/LibrarySource/pal/alignment/AlignmentParseException.java
new file mode 100644
index 0000000..2c18b47
--- /dev/null
+++ b/LibrarySource/pal/alignment/AlignmentParseException.java
@@ -0,0 +1,26 @@
+// AlignmentParseException.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+
+/**
+ * Exception thrown by ReadAlignment
+ *
+ * @author Korbinian Strimmer
+ */
+public class AlignmentParseException extends Exception
+{
+	public AlignmentParseException() {}
+
+	public AlignmentParseException(String msg)
+	{
+		super(msg);
+	}
+}
+
diff --git a/LibrarySource/pal/alignment/AlignmentUtils.java b/LibrarySource/pal/alignment/AlignmentUtils.java
new file mode 100644
index 0000000..6d101f0
--- /dev/null
+++ b/LibrarySource/pal/alignment/AlignmentUtils.java
@@ -0,0 +1,610 @@
+// AlignmentUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.alignment;
+
+import pal.datatype.*;
+import pal.io.*;
+import pal.misc.*;
+import java.io.*;
+
+/**
+ * Helper utilities for alignments.
+ *
+ * @version $Id: AlignmentUtils.java,v 1.7 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class AlignmentUtils {
+
+	static FormattedOutput format = FormattedOutput.getInstance();
+
+
+	/** report number of sequences, sites, and data type */
+	public static void report(Alignment a, PrintWriter out)
+	{
+		if (a.getDataType() == null) {
+			a.setDataType(AlignmentUtils.getSuitableInstance(a));
+		}
+	
+		out.println("Number of sequences: " + a.getSequenceCount());
+		out.println("Number of sites: " + a.getSiteCount());
+		out.println("Data type: " + a.getDataType().getDescription() + " data");
+	}
+
+	/** print alignment (default format: INTERLEAVED) */
+	public static void print(Alignment a, PrintWriter out)
+	{
+		printInterleaved(a, out);	
+	}
+
+	/** print alignment (in plain format) */
+	public static void printPlain(Alignment a, PrintWriter out) {
+		printPlain(a, out, false);
+	}
+
+	/** print alignment (in plain format) */
+	public static void printPlain(Alignment a, PrintWriter out, boolean relaxed)
+	{
+		// PHYLIP header line
+		out.println("  " + a.getSequenceCount() + " " + a.getSiteCount());
+
+		for (int s = 0; s < a.getSequenceCount(); s++)
+		{
+ 			format.displayLabel(out, a.getIdentifier(s).getName(), (relaxed ? 20 : 10));
+			out.print("     ");
+			printNextSites(a, out, false, s, 0, a.getSiteCount());
+			out.println();
+		}
+	}
+
+	/** print alignment (in PHYLIP SEQUENTIAL format) */
+	public static void printSequential(Alignment a, PrintWriter out)
+	{
+		// PHYLIP header line
+		out.println("  " + a.getSequenceCount() + " " + a.getSiteCount() + "  S");
+
+		// Print sequences
+		for (int s = 0; s < a.getSequenceCount(); s++)
+		{
+			int n = 0;
+			while (n < a.getSiteCount())
+			{
+				if (n == 0)
+				{
+ 					format.displayLabel(out, 
+						a.getIdentifier(s).getName(), 10);
+					out.print("     ");
+				}
+				else
+				{
+					out.print("               ");
+				}
+				printNextSites(a, out, false, s, n, 50);
+				out.println();
+				n += 50;
+			}
+		}
+	}
+
+
+	/** print alignment (in PHYLIP 3.4 INTERLEAVED format) */
+	public static void printInterleaved(Alignment a, PrintWriter out)
+	{
+		int n = 0;
+
+		// PHYLIP header line
+		out.println("  " + a.getSequenceCount() + " " + a.getSiteCount());
+
+		// Print sequences
+		while (n < a.getSiteCount())
+		{
+			for (int s = 0; s < a.getSequenceCount(); s++)
+			{
+				if (n == 0)
+				{
+ 					format.displayLabel(out, 
+						a.getIdentifier(s).getName(), 10);
+					out.print("     ");
+				}
+				else
+				{
+					out.print("               ");
+				}
+				printNextSites(a, out, true, s, n, 50);
+				out.println();
+			}
+			out.println();
+			n += 50;
+		}
+	}
+
+	/** Print alignment (in CLUSTAL W format) */
+	public static void printCLUSTALW(Alignment a, PrintWriter out)
+	{
+		int n = 0;
+
+		// CLUSTAL W header line
+		out.println("CLUSTAL W multiple sequence alignment");
+		out.println();
+
+		// Print sequences
+		while (n < a.getSiteCount())
+		{
+			out.println();
+			for (int s = 0; s < a.getSequenceCount(); s++)
+			{
+ 				format.displayLabel(out, a.getIdentifier(s).getName(), 10);
+				out.print("     ");
+	
+				printNextSites(a, out, false, s, n, 50);
+				out.println();
+			}
+			// Blanks in status line are necessary for some parsers)
+			out.println("               ");
+			n += 50;
+		}
+	}	
+	
+	/**
+	 * Returns state indices for a sequence.
+	 */
+	public static final void getAlignedSequenceIndices(Alignment a, int i, int[] indices, DataType dataType) {
+
+		String sequence = a.getAlignedSequenceString(i);
+		
+		for (int j = 0; j < a.getSiteCount(); j++) {
+			indices[j] = dataType.getState(sequence.charAt(j));	
+		}
+	}
+	
+	/**
+	 * Returns total sum of pairs alignment penalty using gap creation 
+	 * and extension penalties and transition penalties in the 
+	 * TransitionPenaltyTable provided. By default this is end-weighted.
+	 */
+	public static double getAlignmentPenalty(
+					Alignment a, 
+					TransitionPenaltyTable penalties, 
+					double gapCreation, 
+					double gapExtension) {
+		
+		return getAlignmentPenalty(a, a.getDataType(), 
+			penalties, gapCreation, gapExtension, false /* end-weighted */);
+	}
+
+	/**
+	 * Returns total sum of pairs alignment distance using gap creation 
+	 * and extension penalties and transition penalties as defined in the 
+	 * TransitionPenaltyTable provided. 
+	 * @param local true if end gaps ignored, false otherwise
+	 */
+	public static double getAlignmentPenalty(
+					Alignment a, 
+					DataType dataType, 
+					TransitionPenaltyTable penalties, 
+					double gapCreation,
+					double gapExtension,
+					boolean local) {
+	
+		int[][] indices = new int[a.getSequenceCount()][a.getSiteCount()];
+		for (int i = 0; i < a.getSequenceCount(); i++) {
+			getAlignedSequenceIndices(a, i, indices[i], dataType);
+		}
+	
+		CostBag totalBag = new CostBag();
+		for (int i = 0; i < a.getSequenceCount(); i++) {
+			for (int j = i + 1; j < a.getSequenceCount(); j++) {
+				totalBag.add(getAlignmentPenalty(a, penalties, i, j, 
+					indices[i], indices[j], local));
+			}
+		}
+		return totalBag.score(gapCreation, gapExtension);
+	}
+
+	/**
+	 * guess data type suitable for a given sequence data set
+	 *
+	 * @param alignment alignment
+	 *
+	 * @return suitable DataType object
+	 */
+	public static DataType getSuitableInstance(Alignment alignment)
+	{	
+		// count A, C, G, T, U, N 
+		long numNucs = 0;
+		long numChars = 0;
+		long numBins = 0;
+		for (int i = 0; i < alignment.getSequenceCount(); i++)
+		{
+			for (int j = 0; j < alignment.getSiteCount(); j++)
+			{
+				char c = alignment.getData(i, j);
+			
+				if (c == 'A' || c == 'C' || c == 'G' ||
+			   		c == 'T' || c == 'U' || c == 'N') numNucs++;
+			
+				if (c != '-' && c != '?') numChars++;
+			
+				if (c == '0' || c == '1') numBins++;
+			}
+		}
+	
+		if (numChars == 0) numChars = 1;
+		
+		// more than 85 % frequency advocates nucleotide data
+		if ((double) numNucs / (double) numChars > 0.85)
+		{
+			return new Nucleotides();
+		}
+		else if ((double) numBins / (double) numChars > 0.2)
+		{
+			return new TwoStates();
+		}
+		else
+		{
+			return new AminoAcids();
+		}	
+	}
+
+	/** count states (creates dataType if not yet specified) */
+	public static double[] estimateFrequencies(Alignment a)
+	{
+		
+		if (a.getDataType() == null)
+		{
+			a.setDataType(getSuitableInstance(a));
+		}
+		
+		int numStates = a.getDataType().getNumStates();
+		
+		double[] frequency = new double[numStates];
+	
+		long[] stateCount = new long[numStates+1];
+		
+		for (int i = 0; i < numStates+1; i++)
+		{
+			stateCount[i] = 0;
+		}
+		
+		for (int i = 0; i < a.getSequenceCount(); i++)
+		{
+			for (int j = 0; j < a.getSiteCount(); j++)
+			{
+				stateCount[a.getDataType().getState(a.getData(i,j))] += 1;
+			}
+		}
+		
+		// Compute frequencies suitable for RateMatrix (sum = 1.0)
+		long sumStates = a.getSiteCount()*a.getSequenceCount()-stateCount[numStates];
+		for (int i = 0; i < numStates; i++)
+		{
+			frequency[i] = (double) stateCount[i]/sumStates;
+		}
+
+		a.setFrequency(frequency);
+
+		return frequency;
+	}
+
+
+	public static final boolean isSiteRedundant(Alignment a, int site) {
+		int numSeq = a.getSequenceCount();
+		for(int i = 0 ; i < numSeq ; i++) {
+			if (!isGap(a, i,site)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	public static final Alignment removeRedundantSites(Alignment a) {
+		boolean[] keep = new boolean[a.getSiteCount()];
+		int toKeep = 0;
+		for(int i = 0 ; i < keep.length ;i++) {
+			keep[i] = !isSiteRedundant(a,i);
+			if(keep[i]) {
+				toKeep++;
+			}
+		}
+		String[] newSeqs = new String[a.getSequenceCount()];
+		int numberOfSites = a.getSiteCount();
+		for(int i = 0 ; i < newSeqs.length ; i++) {
+			StringBuffer sb = new StringBuffer(toKeep);
+			for(int j = 0 ; j < numberOfSites ; j++) {
+				if(keep[j]) {
+					sb.append(a.getData(i,j));
+				}
+			}
+			newSeqs[i] = sb.toString();
+		}
+		return new SimpleAlignment(a, newSeqs);
+	}
+
+	/**
+	 * Returns true if the alignment has a gap at the site in the
+	 * sequence specified.
+	 */
+	public static boolean isGap(Alignment a, int seq, int site) {
+		return DataTypeUtils.isGap(a.getDataType(), a.getData(seq, site));
+	}
+
+	/** 
+	 * @param startingCodonPosition from {0,1,2}, representing codon position 
+	 * of first value in sequences...
+   	 * @param translator the translator to use for converting codons to 
+	 * amino acids.
+	 * @param removeIncompleteCodons removes end codons that are not complete 
+	 * (due to startingPosition, and sequence length).
+	 */
+	public static void getPositionMisalignmentInfo(Alignment a, PrintWriter
+	out, int startingCodonPosition,  CodonTable translator, boolean removeIncompleteCodons) {
+		int leftGaps, rightGaps; //The gaps to the left and right of the center nucleotide
+		for(int i = 0 ; i < a.getSequenceCount() ; i++) {
+			int codonPosition = startingCodonPosition;
+			String codon = "";
+			boolean first = true;
+			out.print(a.getIdentifier(i)+":");
+			leftGaps = 0;
+			rightGaps = 0;
+			for(int j = 0 ; j < a.getSiteCount() ; j++) {
+				char c = a.getData(i, j);
+				if(isGap(a, i, j)) {
+					switch(codonPosition) {
+						case 1: { leftGaps++; break; }
+						case 2: { rightGaps++; break; }
+						default: { out.print(c); break; }
+					}
+				} else {
+					codon+=c;
+					if(codonPosition==2) {
+						if(!first||!(first&&codon.length()!=3&&removeIncompleteCodons)) {
+							if(!first||(first&&startingCodonPosition==0)) {
+								out.print('[');
+							}
+							outputChar(out,Alignment.GAP,leftGaps);
+							out.print(translator.getAminoAcidChar(codon.toCharArray())); //Translator takes care of wrong length codons!S
+							outputChar(out,Alignment.GAP,rightGaps); out.print(']');
+						}
+						first = false; codon = ""; leftGaps = 0; rightGaps = 0;
+					}
+					codonPosition = (codonPosition+1)%3;
+				}
+			}
+			//If we finish on an incomplete codon (we ignore the case where a sequence is less than 3 nucleotides
+			if(!removeIncompleteCodons && codonPosition!=0) {
+				out.print('[');
+				outputChar(out,Alignment.GAP,leftGaps);
+				out.print('?');
+				outputChar(out,Alignment.GAP,rightGaps);
+			}
+			out.print("\n");
+		}
+	}
+
+	/**
+		@param startingCodonPosition - from {0,1,2}, representing codon position of first value in sequences...
+		@note uses middle nucelotide of code to display info...
+   */
+	public static void getPositionMisalignmentInfo(Alignment a, PrintWriter out, int startingCodonPosition) {
+		for(int i = 0 ; i < a.getSequenceCount() ; i++) {
+			int codonPosition = startingCodonPosition;
+			out.print(a.getIdentifier(i)+":");
+			for(int j = 0 ; j < a.getSiteCount(); j++) {
+				char c = a.getData(i, j);
+				if(isGap(a, i, j)) { 
+					out.print(c);
+				} 
+				else {
+					switch(codonPosition) {
+						case 0 : { out.print('['); 	break; }
+						case 1 : { out.print(c); break; }
+						case 2 : { out.print(']'); break; }
+					}
+					codonPosition = (codonPosition+1)%3;
+				}
+
+			}
+			out.print("\n");
+		}
+	}
+
+	// PRIVATE METHODS
+
+	private static final void outputChar(PrintWriter out, char c, int number) {
+		for(int i = 0 ; i < number ; i++) {
+			out.print(c);
+		}
+	}
+
+	private static void printNextSites(Alignment a, PrintWriter out, boolean chunked, int seq, int start, int num)
+	{
+		// Print next num characters
+		for (int i = 0; (i < num) && (start + i < a.getSiteCount()); i++)
+		{
+			// Chunks of 10 characters
+			if (i % 10 == 0 && i != 0 && chunked)
+			{
+				out.print(' ');
+			}
+			out.print(a.getData(seq, start+i));
+		}
+	}
+
+	/**
+	 * Returns the gap creation costs between sequences x and y from site start to site finish.
+	 * @param a alignment
+	 * @param x first sequence
+	 * @param y second sequence
+	 * @param start first site to consider (inclusive)
+	 * @param finish last site to consider (inclusive)
+	 */
+	private static int getNaturalGapCost(Alignment a, int x, int y, 
+				  int start, int finish) {
+	
+		int totalCost = 0;
+		boolean inGap = false;
+
+		// get gap creation costs
+		for (int i = start; i <= finish; i++) {
+			// if not a gap in one of them then consider column for x
+			if (!(isGap(a, y, i) && isGap(a, x, i))) {
+				// if gap in x then its the start of gap or already in gap
+				if (isGap(a, x, i)) {
+					// if not in gap then new gap
+					if (!inGap) {
+						totalCost += 1;
+						inGap = true;
+					} // else in gap and no extra cost
+				} else {
+					// else not null in x therefore not in gap
+					inGap = false;
+				}
+			}
+		}
+
+		return totalCost;
+	}
+
+//=================================================================
+	private static final boolean isGoodSite(Alignment a, DataType dt, int site) {
+		int numberOfSequences = a.getSequenceCount();
+		for(int i = 0 ; i < numberOfSequences ; i++) {
+			char c = a.getData(i,site);
+			if(c!=Alignment.GAP&&dt.isUnknownState(dt.getState(c))) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/** Returns an alignment which follows the pattern of the input alignment
+			except that all sites which do not contain states in dt (excluding the
+			gap character) are removed. The Datatype of the returned alignment is dt
+	*/
+	public static final Alignment getChangedDataType(Alignment a, DataType dt) {
+		int numberOfSites = a.getSiteCount();
+		boolean[] include = new boolean[numberOfSites];
+		int goodSiteCount = 0;
+		for(int i = 0 ; i < numberOfSites ; i++) {
+			include[i] = isGoodSite(a,dt,i);
+			if(include[i]) {
+				goodSiteCount++;
+			} 
+		}
+		//Yes, I'm aware it may be slightly faster to nest sequence
+		// in site but it's easier to program this way
+		String[] sequences = new String[a.getSequenceCount()];
+		for(int i = 0 ; i < sequences.length ; i++) {
+			char[] seq = new char[goodSiteCount];
+			int count = 0;
+			for(int j = 0 ; j < numberOfSites ; j++) {
+				if(include[j]) {
+					seq[count] = a.getData(i,j);
+					count++;
+				}
+			}
+			sequences[i] = new String(seq);
+		}
+		SimpleAlignment sa = new SimpleAlignment(new SimpleIdGroup(a), sequences);
+		sa.setDataType(dt);
+		return sa;
+	}
+	
+	/**
+	 * Returns the score of this alignment based on all pairwise distance measures.
+	 * @param a alignment to score
+	 * @param cdm the character distance matrix
+	 * @param x 
+	 */
+	private static CostBag getAlignmentPenalty(Alignment a, 
+		TransitionPenaltyTable penalties, 
+		int x, int y, int[] xindices, int[] yindices,
+		boolean local) {
+
+		int start = 0;
+		int finish = a.getSiteCount() - 1;
+		if (local) {
+			while (isGap(a, y, start) || isGap(a, x, start)) {
+				start += 1;
+			}
+			while (isGap(a, y, finish) || isGap(a, x, finish)) {
+				finish -= 1;
+			}
+		}
+
+		// get gap costs (creation penalties)
+		int gapCost = getNaturalGapCost(a, x, y, start, finish) +
+			getNaturalGapCost(a, y, x, start, finish);
+	
+		int gapExCost = 0;
+
+		double subCosts = 0.0;
+		// get substitution costs (including extension penalties)
+		for (int i = start; i <= finish; i++) {
+			if (isGap(a, x, i) || isGap(a, y, i)) {
+				if (a.getData(x, i) != a.getData(y, i)) {
+					gapExCost += 1;
+				}
+			} else {
+				subCosts += penalties.penalty(xindices[i], yindices[i]);
+			}
+		}
+
+		return new CostBag(gapCost, gapExCost, subCosts);
+	}
+
+}
+
+class CostBag {
+
+	int gc = 0;
+	int ge = 0;
+	double substitutions = 0.0;
+
+	public CostBag() {}
+
+	public CostBag(int gc, int ge, double subs) {
+		this.gc = gc;
+		this.ge = ge;
+		substitutions = subs;
+	}
+
+	public void add(CostBag bag) {
+		gc += bag.gc;
+		ge += bag.ge;
+		substitutions += bag.substitutions;
+	}
+
+	public double score(double x, double y) {
+		return substitutions + (gc * (x - y)) + (ge * y);
+	}
+
+	public double approximateIntegral(double x1, double x2, 
+		double y1, double y2) {
+		
+		double dx = (x2 - x1) / 100.0;
+		double dy = (y2 - y1) / 100.0;
+
+		double total = 0.0;
+
+		int count = 0;
+		for (double x = x1; x <= x2; x += dx) {
+			for (double y = y1; y <= y2; y += dy) {
+				total += score(x, y);
+				count += 1;
+			}
+		}
+
+		total /= (double)count;
+
+		return total * (x2 - x1) * (y2 - y1);
+	}
+
+}
+
+
diff --git a/LibrarySource/pal/alignment/AminoAcidAlignment.java b/LibrarySource/pal/alignment/AminoAcidAlignment.java
new file mode 100644
index 0000000..2ffdde6
--- /dev/null
+++ b/LibrarySource/pal/alignment/AminoAcidAlignment.java
@@ -0,0 +1,102 @@
+// AminoAcidAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.datatype.*;
+
+
+/**
+ * generates an amino acid alignment from a nucleotide alignment. Is designed to
+ * translate from nucleotide alignments that do not have gaps. Codons that include
+ * one or more gaps will be translated as a '?'.
+ *
+ * @version $Id: AminoAcidAlignment.java,v 1.5 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public class AminoAcidAlignment extends AbstractAlignment {
+
+
+
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Constructs an AminoAcidAlignment from a given alignment 
+	 * (which should be a nucleotide alignment), from codon position 0.
+	 *
+	 * @param raw original alignment
+	 * @param if a codon contains a gap or uses non nucleotide 
+	 * characters resulting amino acid will be marked as a '?'
+	 */
+	public AminoAcidAlignment(Alignment raw) {
+		this(raw,0);
+	}
+
+	/**
+	 * Constructor
+	 *
+	 * @param raw original alignment
+	 * @param startingCodonPosition - the starting codon position (0,1,2)
+	 * @param if a codon contains a gap or uses non nucleotide characters 
+	 * resulting amino acid will be marked as a '?'
+	 */
+	public AminoAcidAlignment(Alignment raw, int startingCodonPosition) {
+		this(raw,startingCodonPosition,CodonTableFactory.createUniversalTranslator());
+	}
+
+	/**
+	 * Constructor
+	 *
+	 * @param raw original alignment
+	 * @param startingCodonPosition - the starting codon position (0,1,2)
+	 * @param trans - the CodonTable to use to convert nucleotides to amino acids
+	 * @param if a codon contains a gap or uses non nucleotide 
+	 * characters resulting amino acid will be marked as a '?'
+	 */
+	public AminoAcidAlignment(Alignment raw, int startingCodonPosition,
+		CodonTable trans) {
+		numSeqs = raw.getSequenceCount();
+		idGroup = raw;
+		numSites = (raw.getSiteCount()-startingCodonPosition)/3;
+		dataType = new AminoAcids();
+		this.data_ = new char[numSeqs][numSites];
+		constructData(raw,startingCodonPosition, trans);
+	}
+
+	private void constructData(Alignment raw, int startingCodonPosition,
+		CodonTable trans) {
+		for(int i = 0 ; i < numSeqs ; i++) {
+			for(int j = 0 ; j < numSites ; j++) {
+				char[] cs = new char[3];
+				for(int k = 0 ; k < 3 ; k++) {
+					cs[k]=raw.getData(i,j*3+startingCodonPosition+k);
+				}
+				this.data_[i][j] = trans.getAminoAcidChar(cs);
+			}
+		}
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return data_[seq][site];
+	}
+
+	
+	//
+	// Private stuff
+	//
+	
+	private char[][] data_;
+}
+
diff --git a/LibrarySource/pal/alignment/BootstrappedAlignment.java b/LibrarySource/pal/alignment/BootstrappedAlignment.java
new file mode 100644
index 0000000..ca91462
--- /dev/null
+++ b/LibrarySource/pal/alignment/BootstrappedAlignment.java
@@ -0,0 +1,75 @@
+// BootstrappedAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.math.*;
+import pal.misc.*;
+
+
+/**
+ * generates bootstrapped alignments from a raw alignment
+ *
+ * @version $Id: BootstrappedAlignment.java,v 1.4 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class BootstrappedAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	 * Constructor
+	 *
+	 * @param raw original alignment
+	 */ 
+	public BootstrappedAlignment(Alignment raw)
+	{
+		rawAlignment = raw;
+		
+		numSeqs = raw.getSequenceCount();
+		idGroup = raw;
+		numSites = raw.getSiteCount();
+		dataType = raw.getDataType();
+		
+		alias = new int[numSites];
+		urn = new UrnModel(numSites);
+		
+		bootstrap();
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return rawAlignment.getData(seq, alias[site]);
+	}
+	
+	
+	/** bootstrap alignment */
+	public void bootstrap()
+	{
+		for (int i = 0; i < numSites; i++)
+		{
+			alias[i] = urn.drawPutBack();
+		}
+	}
+	
+	
+	//
+	// Private stuff
+	//
+	
+	private UrnModel urn;
+	private Alignment rawAlignment;
+	private int[] alias;
+}
+
diff --git a/LibrarySource/pal/alignment/CodonAlignment.java b/LibrarySource/pal/alignment/CodonAlignment.java
new file mode 100644
index 0000000..785f739
--- /dev/null
+++ b/LibrarySource/pal/alignment/CodonAlignment.java
@@ -0,0 +1,103 @@
+// CodonAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.datatype.*;
+
+
+/**
+ * generates an codon alignment from a nucleotide alignment. Is designed to
+ * translate from nucleotide alignments that do not have gaps. Codons that include
+ * one or more gaps will be translated as a '?' (an UNKNOWN_CHARACTER).
+ *
+ * @version $Id: CodonAlignment.java,v 1.4 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public class CodonAlignment extends AbstractAlignment {
+
+	public static final GeneralizedCodons DEFAULT_CODON_TRANSLATOR = new GeneralizedCodons();
+
+
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Constructs an CodonAlignment from a given alignment
+	 * (which should be a nucleotide alignment), from codon position 0.
+	 *
+	 * @param raw original alignment
+	 * @param if a codon contains a gap or uses non nucleotide 
+	 * characters resulting amino acid will be marked as a '?'
+	 */
+	public CodonAlignment(Alignment raw) {
+		this(raw,0);
+	}
+
+	/**
+	 * Constructor
+	 *
+	 * @param raw original alignment
+	 * @param startingCodonPosition - the starting codon position (0,1,2)
+	 * @param if a codon contains a gap or uses non nucleotide characters 
+	 * resulting amino acid will be marked as a '?'
+	 */
+	public CodonAlignment(Alignment raw, int startingCodonPosition) {
+		this(raw,startingCodonPosition,DEFAULT_CODON_TRANSLATOR);
+	}
+
+	/**
+	 * Constructor
+	 *
+	 * @param raw original alignment
+	 * @param startingCodonPosition - the starting codon position (0,1,2)
+	 * @param trans - the translator (DataType) to use to convert nucleotides to amino acids
+	 * @param if a codon contains a gap or uses non nucleotide 
+	 * characters resulting amino acid will be marked as a '?'
+	 */
+	public CodonAlignment(Alignment raw, int startingCodonPosition,
+	GeneralizedCodons trans) {
+		numSeqs = raw.getSequenceCount();
+		idGroup = raw;
+		numSites = (raw.getSiteCount()-startingCodonPosition)/3;
+		dataType = new GeneralizedCodons();
+		this.data_ = new char[numSeqs][numSites];
+		constructData(raw,startingCodonPosition, trans);
+	}
+
+	private void constructData(Alignment raw, int startingCodonPosition,
+	GeneralizedCodons trans) {
+		for(int i = 0 ; i < numSeqs ; i++) {
+			for(int j = 0 ; j < numSites ; j++) {
+				char[] cs = new char[3];
+				for(int k = 0 ; k < 3 ; k++) {
+					cs[k]=raw.getData(i,j*3+startingCodonPosition+k);
+				}
+				this.data_[i][j] = trans.getCodonCharFromCodon(cs);
+			}
+		}
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return data_[seq][site];
+	}
+
+	
+	//
+	// Private stuff
+	//
+	
+	private char[][] data_;
+}
+
diff --git a/LibrarySource/pal/alignment/ConcatenatedAlignment.java b/LibrarySource/pal/alignment/ConcatenatedAlignment.java
new file mode 100644
index 0000000..cf0f51f
--- /dev/null
+++ b/LibrarySource/pal/alignment/ConcatenatedAlignment.java
@@ -0,0 +1,89 @@
+// ConcatenatedAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+/**
+ * concatenates a list of alignments to one single alignment,
+ * increasing the number of sites
+ *
+ * @version $Id: ConcatenatedAlignment.java,v 1.3 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ConcatenatedAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	 * concatenate alignments
+	 *
+	 * @param Alignment array with alignment to concatenate
+	 */
+	public ConcatenatedAlignment(Alignment[] list)
+		throws IllegalArgumentException
+	{
+		alignmentList = list;
+		
+		numAlignments = alignmentList.length;
+		if (numAlignments == 0)
+		{
+			throw new IllegalArgumentException("NO ALIGNMENT");
+		} 
+		
+		numSeqs = alignmentList[0].getSequenceCount();
+		idGroup = alignmentList[0];
+		
+		numSites = 0;
+		for (int i = 0; i < numAlignments; i++)
+		{
+			numSites += alignmentList[i].getSiteCount();
+			
+			if (alignmentList[i].getSequenceCount() != numSeqs)
+			{
+				throw new IllegalArgumentException("INCOMPATIBLE ALIGNMENTS");
+			}
+		}
+		
+		// Create indices
+		alignmentIndex = new int[numSites];
+		siteIndex = new int[numSites];
+		
+		int s = 0;
+		for (int i = 0; i < numAlignments; i++)
+		{
+			for (int j = 0; j < alignmentList[i].getSiteCount(); j++)
+			{
+				alignmentIndex[s+j] = i;
+				siteIndex[s+j] = j;
+			}
+			s += alignmentList[i].getSiteCount();
+		}		
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return alignmentList[alignmentIndex[site]].getData(seq, siteIndex[site]);
+	}
+	
+
+	//
+	// Private stuff
+	//
+	
+	private Alignment[] alignmentList;
+	private int numAlignments;
+	private int[] alignmentIndex;
+	private int[] siteIndex;
+}
+
diff --git a/LibrarySource/pal/alignment/GapBalancedAlignment.java b/LibrarySource/pal/alignment/GapBalancedAlignment.java
new file mode 100644
index 0000000..17459c2
--- /dev/null
+++ b/LibrarySource/pal/alignment/GapBalancedAlignment.java
@@ -0,0 +1,230 @@
+// GapBalancedAcidAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.alignment;
+
+/**
+ * Creates a "Gap-Balanced" alignment.
+ *
+ * @version $Id: GapBalancedAlignment.java,v 1.5 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public class GapBalancedAlignment extends AbstractAlignment implements java.io.Serializable{
+
+	final static int DEFAULT_CODON_LENGTH = 3; /** Just in case we find some Alien DNA */
+
+	//
+	// Public stuff
+	//
+
+	/**
+	 * The standard GapBalanced constructor
+	 *
+	 * @param Alignment on which to based this gap balanced alignment
+	 * @param the estimated startingCodonPosition of the alignment
+	 */
+	public GapBalancedAlignment(Alignment base, int startingCodonPosition) {
+		calculateData(base,startingCodonPosition,DEFAULT_CODON_LENGTH);
+	}
+
+	/**
+	 * GapBalanced power user constructor
+	 *
+	 * @param Alignment on which to based this gap balanced alignment
+	 * @param startingCodonPosition the starting codon position of the alignment
+	 * @param codonLength the length of a codon (to make things general, 
+	 * - the author is a Computer Scientist)
+	 */
+	public GapBalancedAlignment(Alignment base, int startingCodonPosition,int codonLength) {
+		calculateData(base,startingCodonPosition,codonLength);
+	}
+
+
+	/** Generates Alignment information by removing sites that have misaligned codon positions */
+	private void calculateData(Alignment base, int startingCodonPosition, int codonLength) {
+		GapIterator gi = new GapIterator(base,startingCodonPosition, codonLength);
+		gi.processAllSites();
+		data_ = gi.getData();
+
+
+		this.numSeqs = gi.getNumberOfSequences();
+		this.numSites = gi.getNumberOfAcceptedSites();
+		this.idGroup = base;
+
+
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return data_[seq][site];
+	}
+
+
+	//
+	// Private stuff
+	//
+	private char[][] data_;
+
+}
+
+
+/** An statefull algorithmic solution.
+*/
+class GapIterator {
+
+	Alignment base_;
+	int startingCodonPosition_;
+
+	int numberOfSites_ = -1;
+	int numberOfSequences_ = -1;
+
+	boolean[] siteAcceptance_ = null;
+	int numberOfAcceptedSites_ = -1;
+	int[] currentSequenceCodonPosition_ = null;
+
+	int currentSite_ = -1;
+
+	int codonLength_ = -1;
+
+	int currentCodonPosition_ = -1;
+	int[] currentCodonSites_;
+	int numberOfCurrentCodonSites_ = -1;
+
+	transient boolean acceptSite_ = false;
+	transient boolean allGaps_ = false;
+	transient int predominateCodonPosition_ = -1;
+
+	public GapIterator(Alignment base, int startingCodonPosition, int codonLength) {
+		this.base_ = base;
+		this.startingCodonPosition_ = startingCodonPosition;
+		this.codonLength_ = codonLength;
+		setup();
+		reset();
+
+	}
+
+	private void setup() {
+		this.numberOfSites_ = base_.getSiteCount();
+		this.numberOfSequences_ = base_.getSequenceCount();
+		siteAcceptance_ = new boolean[numberOfSites_];
+		currentSequenceCodonPosition_ = new int[numberOfSequences_];
+		currentCodonSites_ = new int[codonLength_];
+	}
+
+	public void reset() {
+		for(int i = 0 ; i < siteAcceptance_.length ; i++) {
+			siteAcceptance_[i] = false;
+		}
+		numberOfAcceptedSites_ = 0;
+		for(int i = 0 ; i < currentSequenceCodonPosition_.length ; i++) {
+			currentSequenceCodonPosition_[i] = startingCodonPosition_;
+		}
+		currentSite_ = 0;
+		currentCodonPosition_ = startingCodonPosition_;
+	}
+
+	public final void processAllSites() {
+		while(hasMoreSites()) {
+			processAnotherSite();
+		}
+	}
+
+	public boolean hasMoreSites() {
+   	return (currentSite_ < numberOfSites_);
+	}
+
+	public int getCurrentSite() {
+   	return currentSite_;
+	}
+
+	/** Proccess a site and sets up instance variables acceptSite_, predominateCodonPosition_, allGaps_
+	*/
+	private synchronized void processSite(int siteNumber) {
+		acceptSite_ = true;
+		predominateCodonPosition_ = -1;
+		allGaps_ = true;
+		for(int currentSequence = 0 ; currentSequence < numberOfSequences_ ; currentSequence++) {
+			char c = base_.getData(currentSequence,currentSite_);
+			if(c!=Alignment.GAP) {
+				allGaps_ = false;
+				if(predominateCodonPosition_==-1) {
+					predominateCodonPosition_ = currentSequenceCodonPosition_[currentSequence];
+				} else {
+					if(currentSequenceCodonPosition_[currentSequence]!=predominateCodonPosition_) {
+						acceptSite_ = false;
+					}
+				}
+				currentSequenceCodonPosition_[currentSequence] = (currentSequenceCodonPosition_[currentSequence]+1)%codonLength_;
+			} else {
+				acceptSite_ = false;
+			}
+		}
+	}
+
+	private synchronized void acceptCurrentCodon() {
+		for(int i = 0 ; i < 3 ; i ++ ) {
+			siteAcceptance_[currentCodonSites_[i]] = true;
+		}
+		numberOfAcceptedSites_+=3;
+  	removeCurrentCodon();
+	}
+
+	private synchronized void removeCurrentCodon() {
+		currentCodonPosition_ = 0;
+	}
+	public synchronized void processAnotherSite() {
+
+		processSite(currentSite_);
+		if(acceptSite_) {
+			if(predominateCodonPosition_!=currentCodonPosition_) {  // If things don't line up we remove the related sites...
+				acceptSite_=false;
+				removeCurrentCodon();
+			}
+		} else {
+			if(!allGaps_) {
+				removeCurrentCodon();
+			}
+		}
+		if(acceptSite_) {
+			currentCodonSites_[currentCodonPosition_] = currentSite_;
+			currentCodonPosition_ = currentCodonPosition_+1;
+			if(currentCodonPosition_==3) {
+				acceptCurrentCodon();
+			}
+		}
+		currentSite_++;
+	}
+
+	public int getNumberOfSequences() {
+		return numberOfSequences_;
+	}
+
+	public int getNumberOfAcceptedSites() {
+		return numberOfAcceptedSites_;
+	}
+
+	public synchronized char[][] getData() {
+		char[][] data = new char[numberOfSequences_][numberOfAcceptedSites_];
+		int currentAcceptedSiteIndex = 0;
+		for(int j = 0 ; j < numberOfSites_ ; j++) {
+			if(siteAcceptance_[j]) {
+				for(int i = 0 ; i < numberOfSequences_; i++) {
+					data[i][currentAcceptedSiteIndex] = base_.getData(i,j);
+				}
+				currentAcceptedSiteIndex++;
+			}
+		}
+		return data;
+	}
+
+
+}
+
diff --git a/LibrarySource/pal/alignment/JumbledAlignment.java b/LibrarySource/pal/alignment/JumbledAlignment.java
new file mode 100644
index 0000000..da018a8
--- /dev/null
+++ b/LibrarySource/pal/alignment/JumbledAlignment.java
@@ -0,0 +1,78 @@
+// JumbledAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.math.*;
+import pal.misc.*;
+
+
+/**
+ * generates jumbled alignments (randomizing input order of sequences)
+ *
+ * @version $Id: JumbledAlignment.java,v 1.4 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class JumbledAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+	
+	/*
+	 * create jumbled alignment
+	 *
+	 * @param raw original alignment
+	 */
+	public JumbledAlignment(Alignment raw)
+	{
+		rawAlignment = raw;
+		
+		numSeqs = raw.getSequenceCount();
+		numSites = raw.getSiteCount();
+		
+		idGroup = new SimpleIdGroup(numSeqs);
+		alias = new int[numSeqs];
+		
+		urn = new UrnModel(numSeqs);
+		
+		jumble();
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return rawAlignment.getData(alias[seq], site);
+	}
+	
+	
+	/** jumble sequences (rearrange input order) */
+	public void jumble()
+	{
+		urn.reset();
+		for (int i = 0; i < numSeqs; i++)
+		{
+			alias[i] = urn.drawDontPutBack();
+			idGroup.setIdentifier(i, rawAlignment.getIdentifier(alias[i]));
+		}
+	}
+	
+	
+	//
+	// Private stuff
+	//
+	
+	private UrnModel urn;
+	private Alignment rawAlignment;
+	private int[] alias;
+}
+
diff --git a/LibrarySource/pal/alignment/ReadAlignment.java b/LibrarySource/pal/alignment/ReadAlignment.java
new file mode 100644
index 0000000..422f9f2
--- /dev/null
+++ b/LibrarySource/pal/alignment/ReadAlignment.java
@@ -0,0 +1,410 @@
+// ReadAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * reads aligned sequence data from plain text files.<p>
+ *
+ * recognizes PHYLIP 3.4 INTERLEAVED,
+ *              PHYLIP SEQUENTIAL,
+ *              CLUSTAL and derived formats.<p>
+ *
+ * Other features:
+ * - the dot as "copy character" is recognized, 
+ * - all base characters are capitalized,
+ * - automatic data type estimation
+ * - determination of corresponding base frequencies.
+ *
+ * @version $Id: ReadAlignment.java,v 1.4 2001/07/13 14:39:12 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class ReadAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+
+	/** read from stream */
+	public ReadAlignment(PushbackReader input)
+		throws AlignmentParseException, IOException
+ 	{
+		readFile(input);	
+	}
+ 
+	/** read from file */
+	public ReadAlignment(String file)
+		throws AlignmentParseException, IOException
+	{
+		PushbackReader input = InputSource.openFile(file);
+		readFile(input);
+		input.close();		
+	}
+
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return data[seq][site];
+	}
+
+
+	//
+	// Private stuff
+	//
+   
+	private int lineLength;
+	private Vector names, seqs, sites;
+	private FormattedInput fi = FormattedInput.getInstance();
+
+	// Raw sequence alignment [sequence][site]
+	private char[][] data = null;
+
+
+	private void readFile(PushbackReader in)
+		throws AlignmentParseException, IOException
+	{
+		// Check for CLUSTAL style alignment
+	
+		int c;
+		String id = "CLUSTAL";
+		boolean isClustal = true;
+		
+		for (int i = 0; i < id.length(); i++)
+		{
+			c = fi.readNextChar(in);
+			if (c != id.charAt(i) && isClustal)
+			{
+				isClustal = false;
+				in.unread(c);
+				break;
+			}
+		}
+		
+		if (isClustal)
+		{
+			fi.nextLine(in);
+			readCLUSTALW(in);
+		}
+		else
+		{
+			readPHYLIP(in);
+		}
+		
+		// Capitalize
+		for (int i = 0; i < numSeqs; i++)
+		{
+			for (int j = 0; j < numSites; j++)
+			{
+				data[i][j] = Character.toUpperCase(data[i][j]);
+			}
+		}
+		
+		// Estimate data type
+		guessDataType();
+		
+		// Determine frequencies
+		AlignmentUtils.estimateFrequencies(this);
+	}
+
+ 	// Read alignment (in CLUSTAL W format)
+	private void readCLUSTALW(PushbackReader in)
+		throws AlignmentParseException
+	{	
+		int EOF = -1;
+		int c, seq = 0, pos = 0;
+		
+		try
+		{
+			// Find start block
+			c = fi.readNextChar(in);
+			in.unread(c);
+			
+			names = new Vector();
+			seqs = new Vector();
+			
+			// Reading first data block 
+			c = in.read();
+			while (c != ' ' && c != '\n' && c != '\r')
+			{
+				in.unread(c);
+				names.addElement(fi.readLabel(in, 10));			
+				readSeqLineC(in, seq, pos);
+				seq++;
+				c = in.read();
+			}
+			in.unread(c);
+			
+			
+			// Skip CLUSTAL W status line
+			fi.nextLine(in);
+			
+			pos += lineLength;
+			numSeqs = seq;
+				
+			// Go to next block
+			c = fi.readNextChar(in);
+			in.unread(c);
+
+			// Reading remaining blocks
+			while (c != EOF)
+			{
+				for (seq = 0; seq < numSeqs; seq++)
+				{
+					// goto next blank
+					do
+					{
+						c = in.read();
+					}
+					while (c != ' ');
+
+					readSeqLineC(in, seq, pos);
+				}
+				
+				// Skip CLUSTAL W status line
+				fi.nextLine(in);
+				
+				pos += lineLength;
+
+				// Go to next block
+				c = fi.readNextChar(in);
+				in.unread(c);
+			}
+			
+			numSites = pos;
+			
+			// Copy to array
+			idGroup = new SimpleIdGroup(numSeqs);
+			data = new char[numSeqs][numSites];
+			for (int i = 0; i < numSeqs; i++)
+			{
+				idGroup.setIdentifier(i,
+						      new Identifier((String)names.elementAt(i)));
+			}
+			for (int i = 0; i < numSeqs; i++)
+			{
+				for (int j = 0; j < numSites; j++)
+				{
+					data[i][j] =
+						((Character)
+							((Vector) seqs.elementAt(i)
+						).elementAt(j)).charValue();
+				}
+			}
+			
+			// Help garbage collector
+			names = null;
+			for (int i = 0; i < numSeqs; i++)
+			{
+				((Vector) seqs.elementAt(i)).removeAllElements();
+			}
+			seqs = null;
+		}
+			catch (IOException e)
+			{
+				throw new AlignmentParseException("IO error after pos. " + (pos + 1) + ", seq. " + (seq + 1));
+  			}		
+	}
+	
+
+	private void readSeqLineC(PushbackReader in, int s, int pos)
+		throws IOException, AlignmentParseException
+	{
+		int c;
+
+		if (pos == 0)
+		{
+			sites = new Vector();
+			seqs.addElement(sites);
+		}
+		else
+		{
+			sites = (Vector) seqs.elementAt(s);
+		}
+
+		if (s == 0)
+		{
+			String thisLine = fi.readLine(in, false);
+			lineLength = thisLine.length();
+			
+			for (int i = 0; i < lineLength; i++)
+			{
+				c = thisLine.charAt(i);
+				if (c == '.')
+				{
+					throw new AlignmentParseException("Copy character (.) in first sequence not allowed (pos. "
+					+ (i + pos + 1) + ")");
+				}
+				sites.addElement(new Character((char) c));
+			}
+		}
+		else
+		{		
+			for (int i = 0; i < lineLength; i++)
+			{
+				c = fi.readNextChar(in);
+				if (c == '.')
+				{
+					c = ((Character)
+							((Vector) seqs.elementAt(0)
+						).elementAt(pos + i)).charValue();
+				}
+				sites.addElement(new Character((char) c));
+			}
+			fi.nextLine(in);
+		}	
+	}
+	
+ 	// Read alignment (in PHYLIP 3.4 INTERLEAVED or PHYLIP SEQUENTIAL format)
+	private void readPHYLIP(PushbackReader in)
+		throws AlignmentParseException
+	{
+		int c, pos = 0, seq = 0;
+	
+		try
+		{
+			// Parse PHYLIP header line
+			numSeqs = fi.readInt(in);
+			numSites = fi.readInt(in);
+   
+			// Reserve memory
+			idGroup = new SimpleIdGroup(numSeqs);
+			data = new char[numSeqs][numSites];
+
+
+			// Determine whether sequences are in INTERLEAVED
+			// or in sequential format
+			String header = fi.readLine(in, false);
+			
+			boolean interleaved = true;
+
+			if (header.length() > 0)
+			{
+				if (header.charAt(0) == 'S')
+				{
+					interleaved = false;
+				}
+			}
+			
+			if (interleaved) // PHYLIP INTERLEAVED
+			{
+				//System.out.println("PHYLIP INTERLEAVED");
+			
+			
+				// Reading data
+				while (pos < numSites)
+				{			
+					// Go to next block
+					c = fi.readNextChar(in);
+					in.unread(c);
+				
+					for (seq = 0; seq < numSeqs; seq++)
+					{
+						readSeqLineP(in, seq, pos, numSites);
+					}
+					pos += lineLength;
+				}
+			}
+			else // PHYLIP SEQUENTIAL
+			{
+				//System.out.println("PHYLIP SEQUENTIAL");
+			
+				for (seq = 0; seq < numSeqs; seq++)
+				{
+					// Go to next block
+					c = fi.readNextChar(in);
+					in.unread(c);
+				
+					// Read label
+					idGroup.setIdentifier(seq, new Identifier(fi.readLabel(in, 10)));
+				
+					// Read sequences
+					for (pos = 0; pos < numSites; pos++)
+					{
+						data[seq][pos] = (char) fi.readNextChar(in);
+					
+						if (data[0][pos] == '.')
+						{
+							if (seq == 0)
+							{
+								throw new AlignmentParseException(
+								"Copy character (.) in first sequence not allowed (pos. "
+								+ (pos + 1) + ")");
+							}
+							else
+							{
+								data[seq][pos] = data[0][pos];
+							}
+						}
+					}
+				}				
+			}
+		}
+			catch (IOException e)
+			{
+				throw new AlignmentParseException("IO error after pos. " + (pos + 1) + ", seq. " + (seq + 1));
+ 			}
+ 	}
+
+	private void readSeqLineP(PushbackReader in, int s, int pos, int maxPos)
+		throws IOException, AlignmentParseException
+	{
+		if (pos == 0)
+		{
+			idGroup.setIdentifier(s, new Identifier(fi.readLabel(in, 10)));			
+		}
+		
+		if (s == 0)
+		{
+			String thisLine = fi.readLine(in, false);
+			
+			if (thisLine.length() > maxPos - pos)
+			{
+				lineLength = maxPos - pos;
+			}
+			else
+			{
+				lineLength = thisLine.length();
+			}
+			
+			for (int i = 0; i < lineLength; i++)
+			{
+				data[0][pos + i] = thisLine.charAt(i);
+				if (data[0][pos + i] == '.')
+				{
+					throw new AlignmentParseException("Copy character (.) in first sequence not allowed (pos. "
+					+ (i + pos + 1) + ")");
+				}
+			}
+		}
+		else
+		{
+			for (int i = 0; i < lineLength; i++)
+			{
+				data[s][pos + i] = (char) fi.readNextChar(in);
+				if (data[s][pos + i] == '.')
+				{
+					data[s][pos + i] = data[0][pos + i];
+				}
+			}
+			fi.nextLine(in);
+		}	
+	}
+}
+
diff --git a/LibrarySource/pal/alignment/SimpleAlignment.java b/LibrarySource/pal/alignment/SimpleAlignment.java
new file mode 100644
index 0000000..5775111
--- /dev/null
+++ b/LibrarySource/pal/alignment/SimpleAlignment.java
@@ -0,0 +1,181 @@
+// SimpleAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.alignment;
+
+import pal.io.*;
+import pal.datatype.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * An alignment class that can be efficiently constructed 
+ * from an array of strings.
+ *
+ * @version $Id: SimpleAlignment.java,v 1.11 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class SimpleAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+
+	/** The sequences */
+	String[] sequences;
+
+	/**
+	 * parameterless constructor.
+	 */
+	public SimpleAlignment() {}
+
+
+	/**
+	 * Clone constructor.
+	 */
+	public SimpleAlignment(Alignment a) {
+		
+		String[] sequences = new String[a.getIdCount()];
+		for (int i = 0; i < sequences.length; i++) {
+			sequences[i] = a.getAlignedSequenceString(i);
+		}
+		String gaps = a.GAP + "";
+
+		init(new SimpleIdGroup(a), sequences, gaps);
+	}
+
+	public SimpleAlignment(Identifier[] ids, String[] sequences,  
+				   String gaps) {
+		
+		init(new SimpleIdGroup(ids), sequences, gaps);	
+	}
+
+	public SimpleAlignment(IdGroup group, String[] sequences) {
+	
+		init(group, sequences, null);
+	}
+
+	public SimpleAlignment(IdGroup group, String[] sequences,  
+				   String gaps) {
+		
+		init(group, sequences, gaps);
+	}
+
+	private void init(IdGroup group, String[] sequences, String gaps) {
+		
+		numSeqs = sequences.length;
+		numSites = sequences[0].length();
+
+		this.sequences = sequences;
+		idGroup = group;
+
+		if (gaps != null) {
+			convertGaps(gaps);
+		}
+		
+		AlignmentUtils.estimateFrequencies(this);	
+	}
+
+	/** 
+	 * Constructor taking single identifier and sequence.
+	 */
+	public SimpleAlignment(Identifier id, String sequence, DataType dataType_) {
+		this(id, sequence, dataType_ ,true);
+	}
+
+	/** 
+	 * Constructor taking single identifier and sequence.
+	 */
+	public SimpleAlignment(Identifier id, String sequence, DataType dataType_ ,boolean estFreqs) {
+
+		this.dataType = dataType_;
+		numSeqs = 1;
+		numSites = sequence.length();
+
+		sequences = new String[1];
+		sequences[0] = sequence;
+
+		Identifier[] ids = new Identifier[1];
+		ids[0] = id;
+		idGroup = new SimpleIdGroup(ids);
+
+		if (estFreqs) {
+			AlignmentUtils.estimateFrequencies(this);
+		}
+	}
+
+	/**
+	 * This constructor combines to alignments given two guide strings.
+	 */
+	public SimpleAlignment(Alignment a, Alignment b, 
+		String guide1, String guide2, char gap) {
+
+		sequences = new String[a.getSequenceCount() + b.getSequenceCount()];	
+		numSeqs = sequences.length;
+		
+		for (int i = 0; i < a.getSequenceCount(); i++) {
+	    		sequences[i] = getAlignedString(a.getAlignedSequenceString(i), guide1, gap, GAP);
+	    	}
+		for (int i = 0; i < b.getSequenceCount(); i++) {
+	    		sequences[i + a.getSequenceCount()] = 
+				getAlignedString(b.getAlignedSequenceString(i), guide2, gap, GAP);
+		}
+
+		numSites = sequences[0].length();
+		idGroup = new SimpleIdGroup(a, b);
+		AlignmentUtils.estimateFrequencies(this);
+	}
+
+	// Abstract method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site) {
+		return sequences[seq].charAt(site);
+	}
+
+	/**
+	 * Returns a string representing a single sequence (including gaps)
+	 * from this alignment.
+	 */
+	public String getAlignedSequenceString(int seq) {
+		return sequences[seq];
+	}
+
+	// PRIVATE STUFF
+
+	private String getAlignedString(String original, String guide, 
+		char guideChar, char gapChar) {
+		
+		StringBuffer buf = new StringBuffer(guide.length());
+		int seqcounter = 0;
+		for (int j = 0; j < guide.length(); j++) {
+			if (guide.charAt(j) != guideChar) {
+				buf.append(original.charAt(seqcounter));
+				seqcounter += 1;
+			} else {
+				buf.append(gapChar);
+			}
+		}
+		return new String(buf);
+	}
+
+	/**
+	 * Converts all gap characters to Alignment.GAP
+	 */
+	private void convertGaps(String gaps) {
+		for (int i = 0; i < sequences.length; i++) {
+			for (int j = 0; j < gaps.length(); j++) {
+				sequences[i] = sequences[i].replace(gaps.charAt(j), Alignment.GAP);
+			}
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/alignment/SitePattern.java b/LibrarySource/pal/alignment/SitePattern.java
new file mode 100644
index 0000000..72b331b
--- /dev/null
+++ b/LibrarySource/pal/alignment/SitePattern.java
@@ -0,0 +1,253 @@
+// SitePattern.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// Known bugs and limitations:
+// - computational complexity O(numSeqs*numSites)
+
+
+package pal.alignment;
+
+import pal.datatype.*;
+import pal.misc.*;
+
+
+/**
+ * takes an Alignment and determines its site patterns
+ *
+ * @version $Id: SitePattern.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class SitePattern extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+
+
+ 	/** number of site patterns */
+	public int numPatterns;
+
+	/** site -> site pattern */
+	public int[] alias;
+
+	/** weights of each site pattern */
+	public int weight[];
+
+	/** site patterns [sequence][site pattern] */
+	public byte[][] pattern;
+
+ 
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return dataType.getChar(pattern[seq][alias[site]]);
+	}
+
+	/**
+	 * infer site patterns for a given alignment
+	 *
+	 * @param a alignment
+	 */
+	public SitePattern(Alignment a)
+	{
+		if (a.getDataType() == null)
+		{
+			a.setDataType(AlignmentUtils.getSuitableInstance(a));
+		}
+
+		// Fields from Alignment
+		dataType = a.getDataType();
+		numSites = a.getSiteCount();
+		numSeqs = a.getSequenceCount();
+		idGroup = a;
+		frequency = a.getFrequency(); // Bernard Suh <bsuh at tigr.org>
+		
+
+		makeSitePattern(a);
+	}
+	
+	/**
+	 * construct SitePattern from scratch
+	 *
+	 * @param dataType data type
+	 * @param numSites number of sites
+	 * @param numSeqs number of sequences
+	 * @param idGroup sequence identifiers
+	 * @param numPatterns number of site patterns
+	 * @param alias link site -> site pattern
+	 * @param weight frequency of a site pattern
+	 * @param pattern site patterns
+	 */
+	public SitePattern(DataType dataType, int numSites, int numSeqs, IdGroup idGroup,
+		int numPatterns, int[] alias, int[] weight, byte[][] pattern)
+	{
+		this.dataType = dataType;
+		this.numSites = numSites;
+		this.numSeqs =  numSeqs;
+		this.idGroup = idGroup;
+
+		this.numPatterns = numPatterns;
+		this.alias = alias;
+		this.weight = weight;
+		this.pattern = pattern;
+		
+		AlignmentUtils.estimateFrequencies(this);  // Bernard Suh <bsuh at tigr.org>
+	}
+	
+
+	//
+	// Private stuff
+	//
+
+	private int[] patSort;
+
+	private void makeSitePattern(Alignment alignment)
+	{
+		alias = new int[numSites];
+
+		if (numSeqs > 0 && numSites > 0)
+		{
+			patSort = new int[numSites];
+
+			getNumpattern(alignment);
+			pattern = new byte[numSeqs][numPatterns];
+			weight = new int[numPatterns];
+			copypattern(alignment);
+
+			patSort = null;
+		}
+		else
+		{
+			numPatterns = 0;
+			pattern = null;
+ 			weight = null;
+		}
+	}
+
+	private int stateData(Alignment al, int seq, int site)
+	{
+		return dataType.getState(al.getData(seq, site));
+	}
+
+	private void getNumpattern(Alignment alignment)
+	{	
+		byte tpmradix = (byte) dataType.getNumStates();
+
+		int[] awork = new int[numSites];
+		int[] count = new int[tpmradix+1];
+
+		for (int j = 0; j < numSites; j++)
+		{
+			patSort[j] = j;
+		}
+		for (int i = numSeqs - 1; i >= 0; i--)
+		{
+			for (int k = 0; k < tpmradix+1; k++)
+			{
+ 				count[k] = 0;
+			}
+			for (int j = 0; j < numSites; j++)
+			{
+				count[stateData(alignment, i, patSort[j])]++;
+			}
+			for (int k = 1; k < tpmradix+1; k++)
+			{
+				count[k] += count[k-1];
+			}
+			for (int j = numSites-1; j >= 0; j--)
+			{
+				awork[ --count[stateData(alignment, i, patSort[j])] ] = patSort[j];
+			}
+			for (int j = 0; j < numSites; j++)
+			{
+				patSort[j] = awork[j];
+			}
+		}
+		awork = null;
+		count = null;
+
+		numPatterns = 1;
+		for (int j = 1; j < numSites; j++)
+		{
+			int s = patSort[j-1];
+			int t = patSort[j];
+			for (int i = 0; i < numSeqs; i++)
+			{
+				if (	stateData(alignment, i, t) !=
+					stateData(alignment, i, s))
+				{
+					numPatterns++;
+					break;
+				}
+			}
+		}
+	}
+
+	void copypattern(Alignment alignment)
+	{
+		int k, n;
+		boolean isSame;
+
+		n = 0;
+		k = patSort[n];
+		for (int i = 0; i < numSeqs; i++)
+		{
+			pattern[i][n] = (byte) stateData(alignment, i, k);
+		}
+		weight[n] = 1;
+		alias[k] = 0;
+
+		for (int j = 1; j < numSites; j++)
+		{
+			k = patSort[j];
+
+			isSame = true;
+			for (int i = 0; i < numSeqs; i++)
+			{
+				if (pattern[i][n] != (byte) stateData(alignment, i, k))
+				{
+					isSame = false;
+					break;
+				}
+			}
+
+			if (isSame)
+			{	
+				weight[n]++;
+				alias[k] = n;
+			}
+			else
+			{
+				n++;
+				for (int i = 0; i < numSeqs; i++)
+				{
+					pattern[i][n] = (byte) stateData(alignment, i, k);
+				}
+				weight[n] = 1;
+				alias[k] = n;
+			}
+		}
+	}
+
+	// ====================================== Static Methods ===========================
+	/**
+		@param a An alignment
+		@return alignment as a site pattern if it isn't already one (other wise just returns alighnment)
+	*/
+	public static final SitePattern getSitePattern(Alignment a) {
+		if(a instanceof SitePattern) {
+			return (SitePattern)a;
+		}
+		return new SitePattern(a);
+	}
+}
+
diff --git a/LibrarySource/pal/alignment/StrippedAlignment.java b/LibrarySource/pal/alignment/StrippedAlignment.java
new file mode 100644
index 0000000..445ddfe
--- /dev/null
+++ b/LibrarySource/pal/alignment/StrippedAlignment.java
@@ -0,0 +1,213 @@
+// StrippedAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// Known bugs and limitations:
+// - can be pretty slow, a better data structure
+//   such as a linked list would improve performance a lot
+
+
+package pal.alignment;
+
+
+/**
+ * takes an alignment and repeatedly removes sites
+ *
+ * @version $Id: StrippedAlignment.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class StrippedAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	  * Constructor
+	  *
+	  * @param raw original alignment
+	  */
+	public StrippedAlignment(Alignment raw)
+	{
+		numSeqs = raw.getSequenceCount();
+		idGroup = raw;
+		numSites = raw.getSiteCount();
+		
+		rawAlignment = raw;
+		rawNumSites = getSiteCount();
+		
+		alias = new int[getSiteCount()];
+		notDropped = new boolean[getSiteCount()];
+		for (int i = 0; i < getSiteCount(); i++)
+		{
+			alias[i] = i;
+			notDropped[i] = true;
+		}
+	}
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return rawAlignment.getData(seq, alias[site]);
+	}
+	
+	/**
+	 * drop a site
+	 * 
+	 * @param s site of original alignment
+	 */
+	public void dropSite(int s)
+	{
+		if (notDropped[s])
+		{
+			notDropped[s] = false;
+			numSites -= 1;
+			
+			// Look for s in alias
+			int n = 0;
+			while (alias[n] != s)
+			{
+				n++;
+			}
+			
+			// Drop s and shift the remaining part
+			for (int i = n; i < getSiteCount(); i++)
+			{
+				alias[i] = alias[i+1];
+			}
+			alias[getSiteCount()] = -1;
+		}
+	}
+	
+	/**
+	 * remove site that contain a specified character
+	 *
+	 * @param c character that will cause the removal of a site
+	 */
+	public void removeSites(char c)
+	{
+		// Drop sites with that character
+		for (int i = 0; i < rawAlignment.getSiteCount(); i++)
+		{
+			for (int j = 0; j < numSeqs; j++)
+			{
+				if (rawAlignment.getData(j,i) == c)
+				{
+					dropSite(i);
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * remove sites with gaps
+	 *
+	 */
+	public void removeGaps()
+	{
+		removeSites('-');
+	}
+
+
+	/**
+	 * remove sites with unknowns
+	 *
+	 */
+	public void removeUnknowns()
+	{
+		removeSites('?');
+	}
+
+
+	/**
+	 * remove constant sites
+	 */
+	public void removeConstantSites()
+	{
+		for (int i = 0; i < rawAlignment.getSiteCount(); i++)
+		{
+			char c = rawAlignment.getData(0, i);
+			int count = 1;
+			
+			for (int j = 1; j < numSeqs; j++)
+			{
+				if (rawAlignment.getData(j, i) == c)
+				{
+					count++;
+				}
+				else
+				{
+					break;
+				}
+			}
+			
+			if (count == numSeqs) dropSite(i);
+		}
+	}
+
+	/**
+	 * remove noninformative sites
+	 */
+	public void removeNoninformativeSites()
+	{
+		int[] charCount = new int[numSeqs];
+		
+		for (int i = 0; i < rawAlignment.getSiteCount(); i++)
+		{
+			for (int j = 0; j < numSeqs; j++)
+			{
+				charCount[j] = 0;
+			}
+			
+			// count how often each character appears in this column
+			for (int j = 0; j < numSeqs; j++)
+			{
+				if (charCount[j] == 0)
+				{
+					charCount[j] = 1;
+					char c = rawAlignment.getData(j, i);
+				
+					for (int k = j+1; k < numSeqs; k++)
+					{
+						if (c == rawAlignment.getData(k, i))
+						{
+							charCount[j]++;
+							charCount[k] = -1;
+						}
+					}
+				}
+			}
+			
+			// number of different characters that appear more than 1 time
+			int num = 0;
+			for (int j = 0; j < numSeqs; j++)
+			{
+				if (charCount[j] > 1)
+				{
+					num++;
+				}
+			}			
+			
+			// drop uninformative sites			
+			if (num < 2) dropSite(i);
+		}
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	private Alignment rawAlignment = null;
+	private int rawNumSites;
+	private int[] alias;
+	private boolean[] notDropped;
+}
+
diff --git a/LibrarySource/pal/alignment/makefile b/LibrarySource/pal/alignment/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/alignment/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/alignment/package.html b/LibrarySource/pal/alignment/package.html
new file mode 100644
index 0000000..188e66c
--- /dev/null
+++ b/LibrarySource/pal/alignment/package.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+Classes dealing with sequence alignments, including methods for reading
+and printing in several possible formats, as well as rearranging and
+concatenating.
+</body>
+</html>
+
diff --git a/LibrarySource/pal/coalescent/CoalescentException.java b/LibrarySource/pal/coalescent/CoalescentException.java
new file mode 100644
index 0000000..1f5ba0a
--- /dev/null
+++ b/LibrarySource/pal/coalescent/CoalescentException.java
@@ -0,0 +1,34 @@
+// CoalescentException.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+/**
+ * Exceptions to do with coalescent models et cetera.
+ *
+ * @version $Id: CoalescentException.java,v 1.2 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class CoalescentException extends Exception {
+
+	/**
+	 * Parameterless constructor.
+	 */
+	public CoalescentException() {
+		super();
+	}
+
+	/**
+	 * Constructor taking message.
+	 */
+	public CoalescentException(String s) {
+		super(s);
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/CoalescentIntervals.java b/LibrarySource/pal/coalescent/CoalescentIntervals.java
new file mode 100644
index 0000000..f575216
--- /dev/null
+++ b/LibrarySource/pal/coalescent/CoalescentIntervals.java
@@ -0,0 +1,405 @@
+// CoalescentIntervals.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.misc.*;
+import pal.tree.*;
+import pal.util.*;
+import pal.io.*;
+
+import java.util.*;
+import java.io.*;
+
+
+/**
+ * A series of coalescent intervals representing the time
+ * order information contained in a (serial) clock-constrained
+ * tree. Can model both n-coalescents and s-coalescents.
+ *
+ * @version $Id: CoalescentIntervals.java,v 1.13 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class CoalescentIntervals implements Units, Report, Serializable
+{
+
+	// PUBLIC STUFF
+
+	/** Denotes and interval after which a coalescent event is observed
+	  * (i.e. the number of lineages is smaller in the next interval) */
+	public static final int COALESCENT = 0;
+
+	/** 
+	 * Denotes an interval at the end of which a new sample addition is 
+	 * observed (i.e. the number of lineages is larger in the next interval).
+	 */
+	public static final int NEW_SAMPLE = 1;
+	
+	/** 
+	 * Denotes an interval at the end of which nothing is
+	 * observed (i.e. the number of lineages is the same in the next interval).
+	 */
+	public static final int NOTHING = 2;
+	
+	
+
+	/** The widths of the intervals. */
+	private double[] intervals;
+
+	/** The number of uncoalesced lineages within a particular interval. */
+	private int[] numLineages;
+
+	/**
+	 * Parameterless constructor.
+	 */
+	public CoalescentIntervals()
+	{
+		units = GENERATIONS;
+		
+		fo = FormattedOutput.getInstance();
+	}
+
+	/**
+	 * Constructor taking a number of intervals.
+	 */
+	public CoalescentIntervals(int size)
+	{
+		this();
+		
+		intervals = new double[size];
+		numLineages = new int[size];
+	}
+
+	/** The units in which the intervals are expressed. */
+	private int units;
+
+	/**
+	 * Sets the units these coalescent intervals are 
+	 * measured in.
+	 */
+	public void setUnits(int u)
+	{
+		units = u;
+	}
+
+	/**
+	 * Returns the units these coalescent intervals are 
+	 * measured in.
+	 */
+	public int getUnits()
+	{
+		return units;
+	}
+	
+	/**
+	 * Returns the number of uncoalesced lineages within this interval.
+	 * Required for s-coalescents, where new lineages are added as
+	 * earlier samples are come across.
+	 */
+	public int getNumLineages(int i) {
+		return numLineages[i];
+	}
+
+	/**
+	 * set the number lineages for this particular interval.
+	 */
+	public void setNumLineages(int i, int numLines) {
+		numLineages[i] = numLines;
+	}
+
+
+	/**
+	 * Returns the number coalescent events in an interval
+	 */
+	public int getCoalescentEvents(int i)
+	{
+		if (i < intervals.length-1)
+		{
+			return numLineages[i]-numLineages[i+1];
+		}
+		else
+		{
+			return numLineages[i]-1;
+		}
+	}
+
+	/**
+	 * Returns the type of interval observed.
+	 */
+	public int getIntervalType(int i)
+	{
+		int numEvents = getCoalescentEvents(i);
+		
+		if (numEvents > 0) return COALESCENT;
+		else if (numEvents < 0) return NEW_SAMPLE;
+		else return NOTHING;
+	}
+
+	/**
+	 * Gets an interval.
+	 */
+	public double getInterval(int i) {
+		return intervals[i];
+	}
+
+	/**
+	 * Sets interval.
+	 */
+	public void setInterval(int i, double value) {
+		intervals[i] = value;
+	}
+
+	/**
+	 * get the total height of the genealogy represented by these
+	 * intervals. 
+	 */
+	public double getTotalHeight() {
+		
+		double height=0.0;
+		for (int j=0; j < intervals.length; j++) {
+			height += intervals[j];
+		}
+		return height;
+	}
+
+
+	/**
+	 * get number of intervals
+	 */
+	public int getIntervalCount()
+	{
+		return intervals.length;
+	}
+
+
+	/**
+	 * Checks whether this set of coalescent intervals is fully resolved
+	 * (i.e. whether is has exactly one coalescent event in each
+	 * subsequent interval)
+	 */
+	public boolean isBinaryCoalescent()
+	{
+		for (int i = 0; i < intervals.length; i++)
+		{
+			if (getCoalescentEvents(i) != 1) return false; 
+		}
+		
+		return true;
+	}
+
+	/**
+	 * Checks whether this set of coalescent intervals coalescent only
+	 * (i.e. whether is has exactly one or more coalescent event in each
+	 * subsequent interval)
+	 */
+	public boolean isCoalescentOnly()
+	{
+		for (int i = 0; i < intervals.length; i++)
+		{
+			if (getCoalescentEvents(i) < 1) return false; 
+		}
+		
+		return true;
+	}
+
+
+	/**
+	 * Group intervals following a given (compatible) reference.
+	 * The reference must have the same number of lineages at
+	 * the start of the first interval, and the present
+	 * CoalsecentIntervals must be fully resolved. 
+	 */
+	public void groupIntervals(CoalescentIntervals reference)
+	{
+		if (!isBinaryCoalescent())
+		{
+			throw new IllegalArgumentException("CoalescentIntervals must purely consist of only single coalescents");
+		}
+		
+		if (getNumLineages(0) != reference.getNumLineages(0))
+		{
+			throw new IllegalArgumentException("Incompatible reference CoalescentIntervals");
+		}
+		
+		int refSize = reference.getIntervalCount();
+		
+		double[] newIntervals = new double[refSize];
+		int[] newNumLineages = new int[refSize];
+		
+		int count = 0;
+		for (int i = 0; i < refSize; i++)
+		{
+			newNumLineages[i] = reference.getNumLineages(i);
+			
+			int numEvents = reference.getCoalescentEvents(i);
+			for (int j = 0; j < numEvents; j++)
+			{
+				newIntervals[i] += intervals[count];
+				count++;
+			}
+		}
+		
+		intervals = newIntervals;
+		numLineages = newNumLineages;
+	}
+
+	/**
+	 * Returns a list stating which of the intervals are <= minSize
+	 * (and thus should be pooled).
+	 */
+	public void getSmallIntervals(double minSize, boolean[] smallInterval)
+	{
+		if (intervals.length != smallInterval.length)
+			throw new IllegalArgumentException("Array length incompatible");
+		
+		for (int i = 0; i < intervals.length; i++)
+		{
+			if (intervals[i] > minSize)
+			{
+				smallInterval[i] = false;
+			}
+			else
+			{
+				smallInterval[i] = true;
+			}
+		}
+	}
+
+
+	/**
+	 * Starting at time zero (i.e. with the interval with largest number of lineages),
+	 * the specified small intervals are pooled with the next non-small interval
+	 * (if this does not exist then with the previous non-small interval)
+	 */
+	public void poolIntervals(boolean[] smallInterval)
+	{
+		int uniqueIntervals = 0;
+		for (int i = 0; i < intervals.length; i++)
+		{
+			if (smallInterval[i] == false) uniqueIntervals++;
+		}
+		if (uniqueIntervals == 0) uniqueIntervals = 1;
+		
+		double[] newIntervals = new double[uniqueIntervals];
+		int[] newNumLineages = new int[uniqueIntervals];
+		
+		int count = 0;
+		int coalescences = 0;
+		int numLines = numLineages[0];
+		for (int i = 0; i < intervals.length; i++)
+		{
+			if (i < intervals.length-1)
+			{
+				coalescences += numLineages[i]-numLineages[i+1];
+			}
+			else
+			{
+				coalescences += numLineages[i]-1;
+			}
+						
+			newIntervals[count] = intervals[i] + newIntervals[count];
+			newNumLineages[count] = numLines;
+			
+			if (smallInterval[i] == false)
+			{
+				count++;
+				if (count == uniqueIntervals) count--;
+				numLines = numLines - coalescences;
+		
+				coalescences = 0;
+			}
+		}
+		
+		intervals = newIntervals;
+		numLineages = newNumLineages;
+	}
+
+
+	/**
+	 * Starting at time zero (i.e. with the interval with largest number of lineages),
+	 * small intervals (<= minSize) are pooled with the next non-small interval
+	 * (if this does not exist then with the previous non-small interval)
+	 */
+	public void poolSmallIntervals(double minSize)
+	{
+		boolean[] smallInterval = new boolean[intervals.length];
+		getSmallIntervals(minSize, smallInterval);
+		poolIntervals(smallInterval);
+	}	
+
+
+	/** 
+	 * Returns the log likelihood of this set of coalescent intervals, 
+	 * given a demographic model.
+	 */
+	public double computeLogLikelihood(DemographicModel model) {
+	
+		double total=0.0;
+		double currentTime = 0.0;
+		double intervalVal = 0.0;
+	
+		try {
+	
+			for (int j = 0; j < intervals.length; j++)
+			{		
+				total += model.computeLogLikelihood(intervals[j], currentTime, numLineages[j],
+				getIntervalType(j));
+			
+				// insert zero-length coalescent intervals
+				int diff = getCoalescentEvents(j)-1;
+				for (int k = 0; k < diff; k++)
+				{
+					total += model.computeLogLikelihood(0.0, currentTime, numLineages[j]-k-1, COALESCENT);
+				}
+			
+				currentTime += intervals[j]; 
+			}
+		} catch (ArrayIndexOutOfBoundsException e) {
+			System.out.println(this);
+		}
+		return total;
+	}
+
+	public String toString()
+	{
+		OutputTarget out = OutputTarget.openString();
+
+		out.println("Lin.\tCoal.\tSize\tTotal");
+		double total = 0.0;
+		
+		for (int i = 0; i < intervals.length; i++)
+		{		
+			total += intervals[i];
+			
+			out.print(numLineages[i] + "\t");
+			out.print(getCoalescentEvents(i) + "\t");
+			
+			fo.displayDecimal(out, intervals[i], 5);
+			out.print("\t");
+			fo.displayDecimal(out, total, 5);
+			out.println();
+		}
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println(this);
+	}
+	
+	//
+	// private stuff
+	//
+	
+	private FormattedOutput fo;
+}
+
diff --git a/LibrarySource/pal/coalescent/CoalescentSimulator.java b/LibrarySource/pal/coalescent/CoalescentSimulator.java
new file mode 100644
index 0000000..82a7f9d
--- /dev/null
+++ b/LibrarySource/pal/coalescent/CoalescentSimulator.java
@@ -0,0 +1,49 @@
+// CoalescentSimulator.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.coalescent;
+
+import pal.tree.*;
+
+/**
+ * Simulates a set of coalescent intervals given a demographic model.
+ *
+ * @version $Id: CoalescentSimulator.java,v 1.5 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class CoalescentSimulator {
+
+	/**
+	 * Simulates a set of CoalescentIntervals from a genealogy assuming
+	 * contemporaneous tips.
+	 * @param numLines the number of tips in the sample genealogy
+	 * @param model the demographic model to use
+	 */
+	public CoalescentIntervals simulateIntervals(int numLines, DemographicModel model) {
+	
+		CoalescentIntervals ci = new CoalescentIntervals(numLines-1);
+	
+		double currentTime = 0.0;
+		for (int i = 0; i < (numLines - 1); i++) {
+			//try {
+				ci.setInterval(i, 
+					model.getSimulatedInterval(numLines,
+					currentTime));
+			//} catch (CoalescentException ce) {
+			//	ce.printStackTrace();
+			//}
+			ci.setNumLineages(i, numLines);
+			currentTime += ci.getInterval(i);
+			numLines -= 1;
+		}
+		return ci;
+	}
+}
+
+
diff --git a/LibrarySource/pal/coalescent/CoalescentTree.java b/LibrarySource/pal/coalescent/CoalescentTree.java
new file mode 100644
index 0000000..5e32810
--- /dev/null
+++ b/LibrarySource/pal/coalescent/CoalescentTree.java
@@ -0,0 +1,23 @@
+// CoalescentTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.coalescent;
+
+import pal.tree.*;
+
+/**
+ * interface defining a parameterized tree that
+ * includes demographic information.
+ *
+ * @author Alexei Drummond
+ */
+public interface CoalescentTree {
+
+	CoalescentIntervals getCoalescentIntervals();
+}
+
+
diff --git a/LibrarySource/pal/coalescent/ConstExpGrowth.java b/LibrarySource/pal/coalescent/ConstExpGrowth.java
new file mode 100644
index 0000000..c7186a7
--- /dev/null
+++ b/LibrarySource/pal/coalescent/ConstExpGrowth.java
@@ -0,0 +1,416 @@
+// ConstExpGrowth.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models a population that grows
+ * exponentially from an inital population size alpha N0 to a present-day size N0.
+ * (Parameters: N0=present-day population size; r=growth rate; alpha: ratio of
+ * population sizes).
+ *   or
+ * (Parameters: N0=present-day population size; r=growth rate; N1: pre-growth
+ * ancestral population size).
+ * This model is nested with the exponential-growth model (alpha -> 0 or N1 = N0).
+ * It is similar but not identical to the model used in ExpandingPopulation.
+ * 
+ *
+ * @version $Id: ConstExpGrowth.java,v 1.4 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Andrew Rambaut
+ */
+public class ConstExpGrowth extends ExponentialGrowth implements Report, Parameterized, Serializable
+{
+	
+	//
+	// Public stuff
+	//
+	
+	/** Constants for different parameterizations  */
+	public final int ALPHA_PARAMETERIZATION = 0; 
+	public final int N1_PARAMETERIZATION = 1; 
+
+	/** parameterization */
+	public int parameterization; 
+
+
+	/** ratio of pop. sizes */
+	public double alpha; 
+
+	/** standard error of time alpha  */
+	public double alphaSE; 
+
+	/** ancestral pop. size */
+	public double N1; 
+
+	/** standard error of ancestral pop. size */
+	public double N1SE; 
+
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public ConstExpGrowth(int units, int parameterization) {
+	
+		super(units);
+		
+		this.parameterization = parameterization;
+		
+		switch (this.parameterization) {
+			case ALPHA_PARAMETERIZATION:
+				alpha = getDefaultValue(2);
+			break;
+			
+			case N1_PARAMETERIZATION:
+				N1 = getDefaultValue(2);
+			break;
+		}
+	}
+
+
+	/**
+	 * Construct demographic model of an expanding population
+	 *
+	 */
+	public ConstExpGrowth(double size, double growth, double ancestral, int units, int parameterization) {
+	
+		super(size, growth, units);
+	
+		this.parameterization = parameterization;
+		
+		switch (this.parameterization) {
+			case ALPHA_PARAMETERIZATION:
+				alpha = ancestral;
+			break;
+			
+			case N1_PARAMETERIZATION:
+				N1 = ancestral;
+			break;
+		}
+	}
+
+	public Object clone() {
+		return new ConstExpGrowth(getN0(), getGrowthRate(), getAncestral(), getUnits(), getParameterization()); 
+	}
+		
+	/**
+	 * returns ancestral population sizes
+	 */
+	public double getAncestral()
+	{
+		if (this.parameterization == N1_PARAMETERIZATION)
+			return N1;
+		else
+			return alpha;
+	}
+	
+	/**
+	 * returns parameterization
+	 */
+	public int getParameterization()
+	{
+		return parameterization;
+	}
+	
+	// Implementation of abstract methods
+	
+	public double getDemographic(double t)
+	{
+		if (this.parameterization == N1_PARAMETERIZATION)
+			alpha = N1 / N0;
+
+		if (alpha == 1.0 || r == 0.0)
+		{
+			return N0;
+		}
+		else if (alpha == 0.0)
+		{
+			return N0 * Math.exp(-t * r);
+		}
+		else
+		{
+			double tc = -Math.log(alpha)/r;
+			
+			if (t < tc)
+			{
+				return N0 * Math.exp(-t * r); 
+			}
+			else
+			{
+				return N0 * alpha;
+			} 		
+		}
+	}
+
+	public double getIntensity(double t)
+	{
+		if (this.parameterization == N1_PARAMETERIZATION)
+			alpha = N1 / N0;
+
+		if (alpha == 1.0 || r == 0.0)
+		{
+			return t/N0;
+		}
+		else if (alpha == 0.0)
+		{
+			return (Math.exp(t*r)-1.0)/N0/r;
+		}
+		else
+		{
+			double tc = -Math.log(alpha)/r;
+			
+			if (t < tc)
+			{
+				return (Math.exp(r*t)-1.0)/(N0*r); 
+			}
+			else
+			{
+				return (1.0-alpha+r*t+Math.log(alpha))/(alpha*N0*r);
+			} 		
+		}
+	}
+	
+	public double getInverseIntensity(double x)
+	{
+		if (this.parameterization == N1_PARAMETERIZATION)
+			alpha = N1 / N0;
+
+		if (r == 0)
+		{
+			return N0*x;
+		}
+		else if (alpha == 0)
+		{
+			return Math.log(1.0+N0*x*r)/r;
+		}
+		else
+		{
+			double xc = (1.0-alpha)/(alpha*N0*r);
+			
+			if (x < xc)
+			{
+				return Math.log(1.0+N0*r*x)/r; 
+			}
+			else
+			{
+				return (alpha-1.0+alpha*N0*r*x-Math.log(alpha))/r;
+			} 		
+		}
+	}
+	
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		return 3;
+	}
+	
+	public double getParameter(int k)
+	{
+		switch (k)
+		{
+			case 0: return N0;
+			case 1: return r;
+			case 2: 		
+				if (this.parameterization == N1_PARAMETERIZATION)
+					return N1;
+				else
+					return alpha;
+			default: return 0;
+		}
+	}
+
+	public double getUpperLimit(int k)
+	{
+		double max = 0;
+		switch (k)
+		{
+			case 0: max = 1e50; break;
+			case 1: max = 1000; break;
+			// we have to to compute lots of exp(rt) !!
+			case 2: 		
+				if (this.parameterization == N1_PARAMETERIZATION)
+					max = 1e50;
+				else
+					max = 1.0;
+			break;
+			default: break;
+		}
+
+		return max;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		double min = 0;
+		switch (k)
+		{
+			case 0: min = 1e-12; break;
+			case 1: min = 0; break;
+			case 2: min = 0; break;
+			default: break;
+		}
+		return min;
+	}
+
+	public double getDefaultValue(int k)
+	{
+	
+		if (k == 0)
+		{
+			//arbitrary default values
+			if (getUnits() == GENERATIONS) {
+				return 1000.0;
+			} else {
+				return 0.2;
+			}
+		}
+		else if (k == 1)
+		{
+			return 0; //constant population
+		}
+		else
+		{
+			if (this.parameterization == N1_PARAMETERIZATION)
+				return getDefaultValue(0); 
+			else
+				return 0.5; 
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0 = value; break;
+			case 1: r = value; break;
+			case 2: 
+				if (this.parameterization == N1_PARAMETERIZATION)
+					N1 = value; 
+				else
+					alpha = value; 
+			break;
+			default: break;
+		}
+	}
+
+	public void setParameterSE(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0SE = value; break;
+			case 1: rSE = value; break;
+			case 2: 
+				if (this.parameterization == N1_PARAMETERIZATION)
+					N1SE = value; 
+				else
+					alphaSE = value; 
+			break;
+			default: break;
+		}
+	}
+	
+	public String toString()
+	{		
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Demographic model: const-exp growth");
+		if (this.parameterization == N1_PARAMETERIZATION) {
+			out.println("Demographic function: N(t) = N0 exp(-r t) for t < -ln(N1/N0)/r");
+			out.println("                             N1           otherwise");
+		} else {
+			out.println("Demographic function: N(t) = N0 exp(-r t) for t < -ln(alpha)/r");
+			out.println("                             N0 alpha     otherwise");
+		}	
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		out.print(" present-day population size N0: ");
+		fo.displayDecimal(out, N0, 6);
+		if (N0SE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, N0SE, 6);
+			out.print(")");
+		}	
+		out.println();
+		
+		out.print(" growth rate r: ");
+		fo.displayDecimal(out, r, 6);
+		if (rSE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, rSE, 6);
+			out.print(")");
+		}	
+		out.println();
+
+		if (this.parameterization == N1_PARAMETERIZATION) {
+			out.print(" pre-growth population size N1: ");
+			fo.displayDecimal(out, N1, 6);
+			if (N1SE != 0.0)
+			{
+				out.print(" (S.E. ");
+				fo.displayDecimal(out, N1SE, 6);
+				out.print(")");
+			}	
+			
+			out.println();
+			out.print(" Ratio of poulation sizes alpha: ");
+			fo.displayDecimal(out, N1/N0, 6);
+			out.println();
+		} else {
+			out.print(" ratio of population sizes alpha: ");
+			fo.displayDecimal(out, alpha, 6);
+			if (alphaSE != 0.0)
+			{
+				out.print(" (S.E. ");
+				fo.displayDecimal(out, alphaSE, 6);
+				out.print(")");
+			}	
+
+			out.println();
+			out.print(" initial population size alpha N0: ");
+			fo.displayDecimal(out, alpha*N0, 6);
+			out.println();
+		}	
+		out.println();
+		
+		if (getLogL() != 0.0)
+		{
+			out.println();
+			out.print("log L: ");
+			fo.displayDecimal(out, getLogL(), 6);
+			out.println();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/ConstantPopulation.java b/LibrarySource/pal/coalescent/ConstantPopulation.java
new file mode 100644
index 0000000..d9d067b
--- /dev/null
+++ b/LibrarySource/pal/coalescent/ConstantPopulation.java
@@ -0,0 +1,236 @@
+// ConstantPopulation.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+ 
+package pal.coalescent;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models coalescent intervals for a constant population
+ * (parameter: N0=present-day population size). <BR>
+ * If time units are set to Units.EXPECTED_SUBSTITUTIONS then
+ * the N0 parameter will be interpreted as N0 * mu. <BR>
+ * Also note that if you are dealing with a diploid population
+ * N0 will be out by a factor of 2.
+ *
+ * @version $Id: ConstantPopulation.java,v 1.12 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ + @author Korbinian Strimmer
+ */
+public class ConstantPopulation extends DemographicModel implements Report, Summarizable, Parameterized, Serializable
+{
+
+	//
+	// private stuff
+	//
+	/** The summary descriptor stuff for the public values of this
+			class
+			@see Summarizable, getSummaryDescriptors()
+	*/
+	private static final String[] CP_SUMMARY_TYPES = {"N0","N0SE"}; //This is still 1.0 compliant...
+
+	//
+	// Public stuff
+	//
+
+	/** population size */
+	public double N0;
+
+	/** standard error of population size */
+	public double N0SE = 0.0;
+
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public ConstantPopulation(int units) {
+	
+		super();
+	
+		setUnits(units);
+
+		N0 = getDefaultValue(0);
+		
+		// necessary to conform to Java 1.0 language standard
+	 //	SUMMARY_TYPES[0] = "N0";
+		//SUMMARY_TYPES[1] = "N0SE";
+	}
+
+
+	/**
+	 * Construct demographic model of a constant population size.
+	 */
+	public ConstantPopulation(double size, int units) {
+	
+		super();
+	
+		N0 = size;
+		setUnits(units);
+
+
+	}
+
+	public Object clone()
+	{
+		return new ConstantPopulation(getN0(), getUnits()); 
+	}
+
+	public String[] getSummaryTypes() {
+		return CP_SUMMARY_TYPES;
+	}
+
+	public double getSummaryValue(int summaryType) {
+		switch(summaryType) {
+			case 0 : {
+				return N0;
+			}
+			case 1 : {
+				return N0SE;
+			}
+		}
+		throw new RuntimeException("Assertion error: unknown summary type :"+summaryType);
+	}
+
+	/**
+	 * returns initial population size.
+	 */
+	public double getN0()
+	{
+		return N0;
+	}
+
+		
+	// Implementation of abstract methods
+	
+	public double getDemographic(double t)
+	{
+		return N0;
+	}
+
+	public double getIntensity(double t)
+	{
+		return t/N0;
+	}
+
+	public double getInverseIntensity(double x)
+	{
+		return N0*x;
+	}
+
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public double getParameter(int k)
+	{
+		return N0;
+	}
+
+	public double getUpperLimit(int k)
+	{
+		return 1e50;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		return 1e-12;
+	}
+
+	public double getDefaultValue(int k)
+	{
+		//arbitrary default values
+		if (getUnits() == GENERATIONS) {
+			return 1000.0;
+		} else {
+			return 0.2;
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		N0 = value;
+	}
+
+	public void setParameterSE(double value, int k)
+	{
+		N0SE = value;
+	}
+
+	public String toString()
+	{
+		/*
+		String s = 
+			"Constant Population:\n";
+
+		if (getUnits() == GENERATIONS) {
+			s += "Effective Population Size = " + N0 + "\n";
+		} else {
+			s += "Theta (haploid) = " + (N0 * 2) + "\n";
+		}
+		return s;
+		*/
+				
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Demographic model: constant population size ");
+		out.println("Demographic function: N(t) = N0");
+		
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print(" present day population size N0: ");
+			fo.displayDecimal(out, N0, 6);
+		}
+		else
+		{
+			out.print(" present day Theta (N0 * mu): ");
+			fo.displayDecimal(out, N0, 6);
+		}
+		if (N0SE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, N0SE, 6);
+			out.print(")");
+		}	
+		out.println();
+		
+		if (getLogL() != 0.0)
+		{
+			out.println();
+			out.print("log L: ");
+			fo.displayDecimal(out, getLogL(), 6);
+			out.println();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/DemographicClockTree.java b/LibrarySource/pal/coalescent/DemographicClockTree.java
new file mode 100644
index 0000000..ce3a300
--- /dev/null
+++ b/LibrarySource/pal/coalescent/DemographicClockTree.java
@@ -0,0 +1,110 @@
+// DemographicClockTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.coalescent;
+
+import pal.misc.*;
+import pal.tree.*;
+
+/**
+ * Provides parameter interface to a clock-like genealogy which is
+ * assumed to have some demographic pattern of theta (diversity) as 
+ * well as branch parameters (the minimal node height differences
+ * at each internal node).
+ *
+ * <em>Must be used in conjunction with DemographicLikelihoodFunction! </em>
+ *
+ * @author Alexei Drummond
+ */
+public class DemographicClockTree extends ClockTree implements DemographicTree {
+	
+	//
+	// Public stuff
+	//
+
+	DemographicModel model;
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like genealogy, under a certain demographic
+	 * assumption.
+	 * <p>
+	 * <em>This parameterisation of branches, ensuring that
+	 * all parameters are independent of each other is due to
+         * Andrew Rambaut (personal communication).</em>
+	 */
+	public DemographicClockTree(Tree t, DemographicModel model)
+	{
+		setBaseTree(t);
+
+		this.model = model;
+
+		if (t.getRoot().getChildCount() < 2)
+		{
+			throw new IllegalArgumentException(
+			"The root node must have at least two childs!");
+		}
+				
+		NodeUtils.heights2Lengths(getRoot());
+
+		parameter = new double[getInternalNodeCount() + model.getNumParameters()];
+		heights2parameters();
+	}
+
+	/**
+	 * Returns the likelihood of the current demographic model, given
+	 * the current branch lengths.
+	 */
+	public double computeDemoLogLikelihood() {
+	
+		CoalescentIntervals ci = IntervalsExtractor.extractFromTree(this);
+	
+		double value = ci.computeLogLikelihood(model);
+		
+		return value;
+	}
+	
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return getInternalNodeCount() + model.getNumParameters();
+	}		
+	
+	//
+	// Private stuff
+	//
+		
+	protected void parameters2Heights()
+	{
+		super.parameters2Heights();
+	
+		for (int i = 0; i < model.getNumParameters(); i++) {
+			model.setParameter(parameter[getInternalNodeCount() + i], i);
+		}
+	}
+	
+	protected void heights2parameters()
+	{
+		super.heights2parameters();
+		
+		if (model != null) {
+			for (int i = 0; i < model.getNumParameters(); i++) {
+				parameter[getInternalNodeCount() + i] = model.getParameter(i);
+			}
+		}
+	}
+
+	/** 
+	 * Return the demographic model being used to optimize the
+	 * likelihood of this tree.
+	 */
+	public DemographicModel getDemographicModel() {
+		return model;
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/DemographicModel.java b/LibrarySource/pal/coalescent/DemographicModel.java
new file mode 100644
index 0000000..b046a97
--- /dev/null
+++ b/LibrarySource/pal/coalescent/DemographicModel.java
@@ -0,0 +1,189 @@
+// DemographicModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+import java.io.*;
+
+
+/**
+ * This abstract class contains methods that are of general use for
+ * modelling coalescent intervals given a demographic model.
+ *
+ * Parts of this class were inspired by C++ code
+ * generously provided by Oliver Pybus.
+ *
+ * @version $Id: DemographicModel.java,v 1.11 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public abstract class DemographicModel implements Units,
+	Parameterized, Report, Cloneable, Serializable, Summarizable
+{
+	
+	//
+	// Public stuff
+	//
+	
+	public DemographicModel()
+	{
+		rng = new MersenneTwisterFast();
+		binom = new Binomial();
+	
+		units = GENERATIONS;
+		
+		fo = FormattedOutput.getInstance();
+	}
+
+	public abstract Object clone();
+
+
+	//
+	// functions that define a demographic model (left for subclass)
+	//
+
+	/**
+	 * Gets the value of the demographic function N(t) at time t.
+	 */
+	public abstract double getDemographic(double t);
+
+	/**
+	 * Returns value of demographic intensity function at time t
+	 * (= integral 1/N(x) dx from 0 to t).
+	 */
+	public abstract double getIntensity(double t);
+
+	/**
+	 * Returns value of inverse demographic intensity function 
+	 * (returns time, needed for simulation of coalescent intervals).
+	 */
+	public abstract double getInverseIntensity(double x);
+
+	// Parameterized and Report interface is also left for subclass
+
+
+	// general functions
+
+	/**
+	 * Returns an random interval size selected from the Kingman prior of the demographic model.
+	 */
+	public double getSimulatedInterval (int numLin, double timeOfLastCoal)
+	{
+		double U = rng.nextDouble(); // create unit uniform random variate				
+		// has to be done somewhere! 
+		binom.setMax(numLin);
+			
+		double tmp = -Math.log(U)/binom.getNChoose2(numLin) + getIntensity(timeOfLastCoal);
+		double interval = getInverseIntensity(tmp) - timeOfLastCoal;
+		
+		return interval;
+	}
+
+	/**
+	 * Calculates the integral 1/N(x) dx between start and finish.
+	 */
+	public double getIntegral(double start, double finish)
+	{
+		return getIntensity(finish) - getIntensity(start);
+	}
+	
+	
+	/**
+	 * Returns the likelihood of a given *coalescent* interval
+	 */
+	public double computeLogLikelihood(double width, double timeOfPrevCoal, int numLineages)
+	{
+		
+		return computeLogLikelihood(width, timeOfPrevCoal, 
+			numLineages, CoalescentIntervals.COALESCENT);
+	}
+	
+	/**
+	 * Returns the likelihood of a given interval,coalescent or otherwise.
+	 */
+	public double computeLogLikelihood(double width, 
+		double timeOfPrevCoal, int numLineages, int type)
+	{
+		binom.setMax(numLineages);
+		
+		double timeOfThisCoal = width + timeOfPrevCoal;
+
+		double intervalArea = getIntegral(timeOfPrevCoal, timeOfThisCoal);
+		double like = 0;
+		switch (type) {
+			case CoalescentIntervals.COALESCENT:
+				like = -Math.log(getDemographic(timeOfThisCoal)) - 
+					(binom.getNChoose2(numLineages)*intervalArea);
+				break;
+			case CoalescentIntervals.NEW_SAMPLE:
+				like = -(binom.getNChoose2(numLineages)*intervalArea);
+				break;
+		}
+	
+		return like;
+	}
+
+
+	/**
+	 * Units in which population size is measured.
+	 */
+	private int units;
+
+	/**
+	 * sets units of measurement.
+	 *
+	 * @param u units
+	 */
+	public void setUnits(int u)
+	{
+		units = u;
+	}
+
+	/**
+	 * returns units of measurement.
+	 */
+	public int getUnits()
+	{
+		return units;
+	}
+	
+	private double logL = 0.0;
+	
+	/**
+	 * sets log likelihood
+	 *
+	 * @param l log-likelihood
+	 */
+	public void setLogL(double l)
+	{
+		logL = l;
+	}
+
+	/**
+	 * returns log-likelihood.
+	 */
+	public double getLogL()
+	{
+		return logL;
+	}
+	
+		
+	//
+	// Private and protected stuff
+	//
+	
+	private MersenneTwisterFast rng;
+	private Binomial binom;
+		
+	protected FormattedOutput fo;
+}
+
diff --git a/LibrarySource/pal/coalescent/DemographicTree.java b/LibrarySource/pal/coalescent/DemographicTree.java
new file mode 100644
index 0000000..a4468de
--- /dev/null
+++ b/LibrarySource/pal/coalescent/DemographicTree.java
@@ -0,0 +1,27 @@
+// DemographicTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+// - partial likelihoods need a lot of memory storage
+//   memory usage could be opimized by working in a single site
+
+
+package pal.coalescent;
+
+/**
+ * interface defining a parameterized tree that
+ * includes demographic information.
+ *
+ * @author Alexei Drummond
+ */
+public interface DemographicTree {
+
+	double computeDemoLogLikelihood();
+
+	DemographicModel getDemographicModel();
+}
+
+
diff --git a/LibrarySource/pal/coalescent/ExpandingPopulation.java b/LibrarySource/pal/coalescent/ExpandingPopulation.java
new file mode 100644
index 0000000..773026a
--- /dev/null
+++ b/LibrarySource/pal/coalescent/ExpandingPopulation.java
@@ -0,0 +1,287 @@
+// ExpandingPopulation.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models a population that grows 
+ * exponentially from an inital population size alpha N0 to a present-day size N0.
+ * (Parameters: N0=present-day population size; r=growth rate; alpha: ratio of
+ * population sizes).
+ * This model is nested with the exponential-growth model (alpha -> 0).
+ * 
+ *
+ * @version $Id: ExpandingPopulation.java,v 1.6 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ExpandingPopulation extends ExponentialGrowth implements Report, Parameterized, Serializable
+{
+	
+	//
+	// Public stuff
+	//
+	
+	/** ratio of pop. sizes */
+	public double alpha; 
+
+
+	/** standard error of time alpha  */
+	public double alphaSE; 
+
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public ExpandingPopulation(int units) {
+	
+		super(units);
+		
+		alpha = getDefaultValue(2);
+	}
+
+
+	/**
+	 * Construct demographic model of an expanding population
+	 *
+	 */
+	public ExpandingPopulation(double size, double growth, double ratio, int units) {
+	
+		super(size, growth, units);
+	
+		alpha = ratio;
+	}
+
+	public Object clone() {
+		return new ExpandingPopulation(getN0(), getGrowthRate(), getRatio(), getUnits()); 
+	}
+		
+	/**
+	 * returns ratio of population sizes
+	 */
+	public double getRatio()
+	{
+		return alpha;
+	}
+	
+	// Implementation of abstract methods
+	
+	public double getDemographic(double t)
+	{
+		if (r == 0)
+		{
+			return N0;
+		}
+		else if (alpha == 0)
+		{
+			return N0 * Math.exp(-t * r);
+		}
+		else
+		{
+			return N0 * (alpha + (1.0-alpha) * Math.exp(-t * r));
+		}
+	}
+
+	public double getIntensity(double t)
+	{
+		if (r == 0)
+		{
+			return t/N0;
+		}
+		else if (alpha == 0)
+		{
+			return (Math.exp(t*r)-1.0)/N0/r;
+		}
+		else
+		{
+			return Math.log(1.0+alpha*(Math.exp(t*r)-1.0))/alpha/N0/r;
+		}
+	}
+	
+	public double getInverseIntensity(double x)
+	{
+		if (r == 0)
+		{
+			return N0*x;
+		}
+		else if (alpha == 0)
+		{
+			return Math.log(1.0+N0*x*r)/r;
+		}
+		else
+		{
+			return Math.log( (alpha-1.0+Math.exp(alpha*N0*x*r) )/alpha )/r;
+		}
+	}
+	
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		return 3;
+	}
+	
+	public double getParameter(int k)
+	{
+		switch (k)
+		{
+			case 0: return N0;
+			case 1: return r;
+			case 2: return alpha;
+			default: return 0;
+		}
+	}
+
+	public double getUpperLimit(int k)
+	{
+		double max = 0;
+		switch (k)
+		{
+			case 0: max = 1e50; break;
+			case 1: max = 1000; break;
+			// we have to to compute lots of exp(rt) !!
+			case 2: max = 1; break;
+			default: break;
+		}
+
+		return max;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		double min = 0;
+		switch (k)
+		{
+			case 0: min = 1e-12; break;
+			case 1: min = 0; break;
+			case 2: min = 0; break;
+			default: break;
+		}
+		return min;
+	}
+
+	public double getDefaultValue(int k)
+	{
+	
+		if (k == 0)
+		{
+			//arbitrary default values
+			if (getUnits() == GENERATIONS) {
+				return 1000.0;
+			} else {
+				return 0.2;
+			}
+		}
+		else if (k == 1)
+		{
+			return 0; //constant population
+		}
+		else
+		{
+			return 0.5; 
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0 = value; break;
+			case 1: r = value; break;
+			case 2: alpha = value; break;
+			default: break;
+		}
+	}
+
+	public void setParameterSE(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0SE = value; break;
+			case 1: rSE = value; break;
+			case 2: alphaSE = value; break;
+			default: break;
+		}
+	}
+	
+	public String toString()
+	{		
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Demographic model: expanding population");
+		out.println("Demographic function: N(t) = N0 (alpha + (1-alpha) exp(-r t)");
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		out.print(" present-day population size N0: ");
+		fo.displayDecimal(out, N0, 6);
+		if (N0SE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, N0SE, 6);
+			out.print(")");
+		}	
+		out.println();
+		
+		out.print(" growth rate r: ");
+		fo.displayDecimal(out, r, 6);
+		if (rSE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, rSE, 6);
+			out.print(")");
+		}	
+		out.println();
+
+		out.print(" ratio of population sizes alpha: ");
+		fo.displayDecimal(out, alpha, 6);
+		if (alphaSE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, alphaSE, 6);
+			out.print(")");
+		}	
+		out.println();
+		
+		out.println();
+		out.print(" initial poulation size alpha N0: ");
+		fo.displayDecimal(out, alpha*N0, 6);
+		out.println();
+
+		if (getLogL() != 0.0)
+		{
+			out.println();
+			out.print("log L: ");
+			fo.displayDecimal(out, getLogL(), 6);
+			out.println();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/ExponentialGrowth.java b/LibrarySource/pal/coalescent/ExponentialGrowth.java
new file mode 100644
index 0000000..0f26c9e
--- /dev/null
+++ b/LibrarySource/pal/coalescent/ExponentialGrowth.java
@@ -0,0 +1,285 @@
+// ExponentialGrowth.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models an exponentially growing (or shrinking) population
+ * (Parameters: N0=present-day population size; r=growth rate).
+ * This model is nested with the constant-population size model (r=0).
+ * 
+ * Parts of this class were inspired by C++ code
+ * generously provided by Oliver Pybus.
+ *
+ * @version $Id: ExponentialGrowth.java,v 1.10 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class ExponentialGrowth extends ConstantPopulation implements Report, Parameterized, Serializable, Summarizable
+{
+	
+	//
+	// Public stuff
+	//
+
+	private static final String[] EG_SUMMARY_TYPES = {"N0","N0SE", "R", "RSE"}; //This is dependent on ConstantPopulation!
+
+
+	/** growth rate r */
+	public double r; 
+
+
+	/** standard error of growth rate r  */
+	public double rSE; 
+
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public ExponentialGrowth(int units) {
+	
+		super(units);
+		
+		r = getDefaultValue(1);
+	}
+
+
+	/**
+	 * Construct demographic model of an exponentially growing population
+	 */
+	public ExponentialGrowth(double size, double growth, int units) {
+	
+		super(size, units);
+	
+		r = growth;
+	}
+
+	public String[] getSummaryTypes() {
+   	return EG_SUMMARY_TYPES;
+	}
+
+	public double getSummaryValue(int summaryType) {  //This is dependent on ConstantPopulation!
+		switch(summaryType) {
+			case 2 : {
+				return r;
+			}
+			case 3 : {
+				return rSE;
+			}
+			default : {
+       	return super.getSummaryValue(summaryType);
+			}
+		}
+	}
+
+
+	public Object clone() {
+		return new ExponentialGrowth(getN0(), getGrowthRate(), getUnits()); 
+	}
+		
+	/**
+	 * returns growth rate.
+	 */
+	public double getGrowthRate() {
+		return r;
+	}
+	
+	// Implementation of abstract methods
+	
+	public double getDemographic(double t)
+	{
+		if (r == 0)
+		{
+			return N0;
+		}
+		else
+		{
+			return N0 * Math.exp(-t * r);
+		}
+	}
+
+	public double getIntensity(double t)
+	{
+		if (r == 0)
+		{
+			return t/N0;
+		}
+		else
+		{
+			return (Math.exp(t*r)-1.0)/N0/r;
+		}
+	}
+	
+	public double getInverseIntensity(double x)
+	{
+		if (r == 0)
+		{
+			return N0*x;
+		}
+		else
+		{
+			return Math.log(1.0+N0*x*r)/r;
+		}
+	}
+	
+
+	
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		return 2;
+	}
+	
+	public double getParameter(int k)
+	{
+		if (k == 0) return N0;
+
+		return r;
+	}
+
+	public double getUpperLimit(int k)
+	{
+		double max = 0;
+		switch (k)
+		{
+			case 0: max = 1e50; break;
+			case 1: max = 1000; break;
+			// we have to to compute lots of exp(rt) !!
+			default: break;
+		}
+
+		return max;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		double min = 0;
+		switch (k)
+		{
+			case 0: min = 1e-12; break;
+			case 1: min = -200; break;
+			// we allow also shrinking populations
+			default: break;
+		}
+		return min;
+	}
+
+	public double getDefaultValue(int k)
+	{
+	
+		if (k == 0)
+		{
+			//arbitrary default values
+			if (getUnits() == GENERATIONS) {
+				return 1000.0;
+			} else {
+				return 0.2;
+			}
+		} else
+		{
+			return 0; //constant population
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0 = value; break;
+			case 1: r = value; break;
+			default: break;
+		}
+	}
+
+	public void setParameterSE(double value, int k)
+	{
+		switch (k)
+		{
+			case 0: N0SE = value; break;
+			case 1: rSE = value; break;
+			default: break;
+		}
+	}
+	
+	public String toString()
+	{
+		/*
+		String s = 
+			"Exponentially growing population:\n";
+
+		if (getUnits() == GENERATIONS) {
+			s += "Effective Population Size = " + N0 + "\n";
+			s += "Growth rate (r) = " + r + "\n";
+		} else {
+			s += "Theta (haploid) = " + (N0 * 2) + "\n";
+			s += "Growth rate (rho) = " + r + "\n";
+		}
+		return s;
+		*/
+		
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Demographic model: exponential growth");
+		out.println("Demographic function: N(t) = N0 exp(-r t)");
+		
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		out.print(" present-day population size N0: ");
+		fo.displayDecimal(out, N0, 6);
+		if (N0SE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, N0SE, 6);
+			out.print(")");
+		}	
+		out.println();
+		out.print(" growth rate r: ");
+		fo.displayDecimal(out, r, 6);
+		if (rSE != 0.0)
+		{
+			out.print(" (S.E. ");
+			fo.displayDecimal(out, rSE, 6);
+			out.print(")");
+		}	
+		out.println();
+		
+		if (getLogL() != 0.0)
+		{
+			out.println();
+			out.print("log L: ");
+			fo.displayDecimal(out, getLogL(), 6);
+			out.println();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/IntervalsExtractor.java b/LibrarySource/pal/coalescent/IntervalsExtractor.java
new file mode 100644
index 0000000..1862978
--- /dev/null
+++ b/LibrarySource/pal/coalescent/IntervalsExtractor.java
@@ -0,0 +1,237 @@
+// IntervalsExtractor.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.misc.*;
+import pal.tree.*;
+import pal.util.*;
+import pal.mep.*;
+import java.util.Vector;
+
+/**
+ * A series of coalescent intervals representing the time
+ * order information contained in a (serial) clock-constrained
+ * tree.
+ *
+ * @version $Id: IntervalsExtractor.java,v 1.12 2001/07/12 12:17:43 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class IntervalsExtractor implements Units
+{
+
+	/**
+	 * extracts intervals from clock tree.
+	 */
+	public static CoalescentIntervals extractFromClockTree(Tree tree)
+	{	
+		return extractFromClockTree(tree, -1);
+	}
+	
+	/**
+	 * extracts intervals from clock tree. Leafs are assumed to have
+	 * height zero.  Starting at time zero, small (<= minSize) intervals are pooled
+	 * with the next non-small interval (if this does not exist then
+	 * with the previous non-small interval) 
+	 */
+	public static CoalescentIntervals extractFromClockTree(Tree tree, double minSize)
+	{	
+		tree.createNodeList(); //make consistent
+		NodeUtils.lengths2Heights(tree.getRoot());
+		//NodeUtils.lengths2HeightsKeepTips(tree.getRoot(),true);
+		
+		// Set heights of all external nodes to zero
+		// we need a proper clock-tree
+		//for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		//{
+		//	tree.getExternalNode(i).setNodeHeight(0.0);
+		//}
+
+		
+		Vector times = new Vector();
+		Vector childs = new Vector();
+		collectInternalNodeHeights(tree.getRoot(), times, childs);
+		int[] indices = new int[times.size()];
+
+		HeapSort.sort(times, indices);
+
+		int uniqueIntervals = 0;
+		
+		double currentTime = 0.0;
+		for (int i = 0; i < times.size(); i++) {
+			double time = ((ComparableDouble)times.elementAt(indices[i])).doubleValue();
+			if (Math.abs(time - currentTime) > minSize)
+			{
+				uniqueIntervals += 1;
+			}
+			currentTime = time;	
+		}
+		if (uniqueIntervals == 0) uniqueIntervals = 1;
+
+		CoalescentIntervals ci = new CoalescentIntervals(uniqueIntervals);	
+		ci.setUnits(tree.getUnits());
+		
+		double start = 0.0;
+		int numLines = tree.getExternalNodeCount();
+		
+		int count = 0;
+		int coalescences = 0;
+		for (int i = 0; i < times.size(); i++)
+		{
+			double finish = ((ComparableDouble)times.elementAt(indices[i])).doubleValue();
+			int childCount = ((Integer)childs.elementAt(indices[i])).intValue();
+			
+			double length = Math.abs(finish - start);
+			coalescences += childCount-1;
+						
+			ci.setInterval(count, length + ci.getInterval(count) );
+			ci.setNumLineages(count, numLines);
+			
+			if (length > minSize)
+			{
+				count++;
+				if (count == uniqueIntervals) count--;
+				numLines = numLines - coalescences;
+		
+				coalescences = 0;
+			}
+			
+			start = finish;	
+		}
+		
+		return ci;
+	}
+
+	/**
+	 * extracts intervals in generation times from serial clock tree (in mutation times) 
+	 * after taking into account mutation rate model.
+	 */
+	public static CoalescentIntervals extractFromTree(Tree tree, MutationRateModel muModel) {
+		
+		Tree newTree = TreeUtils.mutationsToGenerations(tree, muModel);
+		return extractFromTree(newTree);
+	}
+
+	/**
+	 * extracts intervals from serial clock tree.
+	 */
+	public static CoalescentIntervals extractFromTree(Tree tree)
+	{
+		double MULTIFURCATION_LIMIT = BranchLimits.MINARC;
+		
+		// get heights if it looks necessary
+		if (tree.getRoot().getNodeHeight() == 0.0) {
+			NodeUtils.lengths2Heights(tree.getRoot());
+		}
+		
+		Vector times = new Vector();
+		Vector childs = new Vector();
+		collectAllTimes(tree.getRoot(), times, childs);
+		int[] indices = new int[times.size()];
+		Vector lineages = new Vector();
+		Vector intervals = new Vector();
+
+		HeapSort.sort(times, indices);
+
+		double start = 0.0;
+		int numLines = 0;
+		int i = 0;
+		while (i < times.size())
+		{
+			
+			int lineagesRemoved = 0;
+			int lineagesAdded = 0;
+			
+			double finish = ((ComparableDouble)times.elementAt(indices[i])).doubleValue();
+			double next = finish;
+			
+			while (Math.abs(next - finish) < MULTIFURCATION_LIMIT) {
+				int children = ((Integer)childs.elementAt(indices[i])).intValue();
+				if (children == 0) {
+					lineagesAdded += 1;
+				} else {
+					lineagesRemoved += (children - 1);
+				}
+				i += 1;
+				if (i < times.size()) {
+					next = ((ComparableDouble)times.elementAt(indices[i])).doubleValue();
+				} else break;
+			}
+			//System.out.println("time = " + finish + " removed = " + lineagesRemoved + " added = " + lineagesAdded);			
+			if (lineagesAdded > 0) {
+			
+				if ((intervals.size() > 0) || ((finish - start) > MULTIFURCATION_LIMIT)) {
+					intervals.addElement(new Double(finish - start));
+					lineages.addElement(new Integer(numLines));
+				}
+			
+				start = finish;
+			}
+			// add sample event
+			numLines += lineagesAdded;
+			
+			if (lineagesRemoved > 0) {
+			
+				intervals.addElement(new Double(finish - start));
+				lineages.addElement(new Integer(numLines));			
+				start = finish;
+			}
+			// coalescent event
+			numLines -= lineagesRemoved;
+			
+			
+				
+		}
+
+		CoalescentIntervals ci = new CoalescentIntervals(intervals.size());
+		for (i = 0; i < intervals.size(); i++) {
+			ci.setInterval(i, ((Double)intervals.elementAt(i)).doubleValue());
+			ci.setNumLineages(i, ((Integer)lineages.elementAt(i)).intValue());
+		}
+			
+		// Same Units as tree	
+		ci.setUnits(tree.getUnits());
+		
+
+		return ci;
+	}
+
+	// PRIVATE STUFF
+
+	/**
+	 * extract coalescent times and tip information into Vector times from tree.
+	 */
+	private static void collectAllTimes(Node node, Vector times, Vector childs) {
+
+		times.addElement(new ComparableDouble(node.getNodeHeight()));
+		childs.addElement(new Integer(node.getChildCount()));
+		
+		for (int i = 0; i < node.getChildCount(); i++) {
+			collectAllTimes(node.getChild(i), times, childs);
+		}
+	}
+	
+	/**
+	 * extract internal node heights Vector times from tree.
+	 */
+	private static void collectInternalNodeHeights(Node node, Vector times, Vector childs)
+	{
+		if (!node.isLeaf())
+		{
+			times.addElement(new ComparableDouble(node.getNodeHeight()));
+			childs.addElement(new Integer(node.getChildCount()));
+		
+			for (int i = 0; i < node.getChildCount(); i++) {
+				collectInternalNodeHeights(node.getChild(i), times, childs);
+			}
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/coalescent/SkylinePlot.java b/LibrarySource/pal/coalescent/SkylinePlot.java
new file mode 100644
index 0000000..47ab9e3
--- /dev/null
+++ b/LibrarySource/pal/coalescent/SkylinePlot.java
@@ -0,0 +1,415 @@
+// SkylinePlot.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.coalescent;
+
+import pal.tree.*;
+import pal.misc.*;
+import pal.math.*;
+import pal.io.*;
+import pal.statistics.*;
+
+import java.io.*;
+
+/**
+ * Skyline plot derived from a strictly bifurcating tree
+ * or a coalescent interval.
+ *
+ * This class provides the "classic" skyline plot method by
+ * Pybus, Rambaut and Harvey .2000. Genetics 155:1429-1437, as well
+ * as the "generalized" skyline plot method  described in
+ * Strimmer and Pybus. 2001. MBE submitted.
+ * 
+ * @version $Id: SkylinePlot.java,v 1.16 2001/07/11 13:51:16 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class SkylinePlot implements Report, Units, Serializable
+{
+	//
+	// Public stuff
+	//
+	
+
+	/**
+	 * Construct skyline plot from tree
+	 *
+	 * @param epsilon smoothing parameter (if set < 0 then epsilon will be optimized)
+	 */
+	public SkylinePlot(Tree tree, double epsilon)
+	{
+		this(IntervalsExtractor.extractFromClockTree(tree), epsilon);
+	}
+
+
+	/**
+	 * Construct skyline plot from given coalescent intervals
+	 * 
+	 * @param epsilon smoothing parameter (if set < 0 then epsilon will be optimized)
+	 */
+	public SkylinePlot(CoalescentIntervals ci, double epsilon)
+	{
+		if (!ci.isBinaryCoalescent())
+		{
+			throw new IllegalArgumentException("All coalescent intervals must contain only a single coalescent");
+		}
+		
+		fo = FormattedOutput.getInstance();
+		
+		size = ci.getIntervalCount();
+		
+		this.ci = ci;
+		
+		// population size in each coalescent interval
+		populationSize = new double[size];
+				
+		// cumulative interval sizes
+		cis = new double[size];
+		
+		maxTime = 0.0;
+		for (int i = 0; i < size; i++)
+		{
+			cis[i] = maxTime;
+			maxTime += ci.getInterval(i);
+		}
+		
+		if (epsilon == 0.0)
+		{
+			/* init with classic skyline plot */
+			computeClassic();
+		}
+		else if (epsilon > 0.0)
+		{
+			/* init with generalized skyline plot */
+			computeGeneralized(epsilon);
+		}
+		else
+		{
+			// find optimal generalized skyline plot
+			optimize();
+		}
+	}
+
+	
+	public String toString()
+	{		
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Skyline Plot");
+		out.println();
+		out.print("Smoothing parameter epsilon = " + eps + " ");
+		if (eps == 0.0) out.println("(classic skyline plot)");
+		else out.println("(generalized skyline plot)");
+		
+		out.print("Unit of time: ");
+		if (ci.getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		
+		printIntervals(out);
+		
+		out.println();
+		out.println("For each composite interval the first and the last simple interval is given.");
+		out.println();
+		out.println("log L = " + getLogLikelihood());
+		out.println("Number of intervals: " + size);
+		out.println("Number of composite intervals:" + params);
+		if (params > size-2)
+		out.println("log L(AICC) not available");
+		else
+		out.println("log L(AICC) = " + getAICC());
+	}
+
+	private void printIntervals(PrintWriter out)
+	{
+		out.println("Int.\tTime\tEstimated N(t)");
+		double total = 0.0;
+		for (int i = 0; i < size; i++)
+		{
+			double m = populationSize[i];
+			
+			printLine(out, i, total, m);
+			total += ci.getInterval(i);
+			
+			int j;
+			for (j = i+1; j < size; j++)
+			{
+				if (populationSize[j] != m) break;
+			}
+			i=j-1;
+			
+			printLine(out, i, total, m);
+		}
+	}
+
+
+	private void printLine(PrintWriter out, int i, double total, double m)
+	{
+			out.print((size-i) + "\t");
+			fo.displayDecimal(out, total, 4);
+			out.print("\t");
+			fo.displayDecimal(out, m, 4);
+			out.println();
+	}
+
+
+
+	/**
+	 * Compute classic skyline plot
+	 */
+	public void computeClassic()
+	{
+		for (int i = 0; i < size; i++)
+		{
+			double w = ci.getInterval(i);
+			double n = ci.getNumLineages(i);
+			
+			populationSize[i] = w * (n*(n-1))/2.0 ;
+		}
+		
+		params = size;
+		eps = 0.0;
+	}
+
+	/**
+	 * Compute generalized skyline plot
+	 */
+	public void computeGeneralized(double epsilon)
+	{
+		params = 0;
+		double cw = 0; //cumulative w
+		
+		for (int i = 0; i < size; i++)
+		{
+			double n = ci.getNumLineages(i);
+			
+			double w = ci.getInterval(i);
+			
+			int start = i;
+			int k = 1;
+			while (w < epsilon && i < size-1)
+			{
+				i++;
+				k++;
+				w += ci.getInterval(i);
+				
+				//System.out.println(ci.getInterval(i));
+			} 
+			
+			//System.out.println("w=" + w + " k=" + k + "  i=" + i);
+			
+			// if remainder is smaller than epsilon
+			// continue pooling until the end
+			if (maxTime - cw - w < epsilon) 
+			{				
+				for (int j = i+1; j < size; j++)
+				{
+					i++;
+					k++;
+					w += ci.getInterval(i);
+				}
+
+			}
+			
+			double m = w * (n*(n-k))/(2.0*k);
+			
+			// assign the same pop.size to all sub intervals
+			for (int j = start; j < start+k; j++)
+			{
+				populationSize[j] = m;
+			}
+			params++;
+			cw += w;
+		}
+		eps = epsilon;
+	}
+
+	/**
+	 * Optimize generalized skyline plot
+	 */
+	public void optimize()
+	{
+		// this is the naive way of doing this ...
+		
+		double besteps = getMaxTime();
+		computeGeneralized(besteps);
+		double bestaicc = getAICC();
+		
+		int GRID = 1000;
+		double delta = besteps/GRID;
+		
+		double MINEPS = 1e-6;
+		// Why MINEPS?
+		// Because most "clock-like" trees are not properly
+		// clock-like for a variety of reasons, i.e. the heights
+		// of the tips are not exactly zero.
+		
+		
+		
+		eps = eps - delta;
+		while(eps > MINEPS)
+		{
+			computeGeneralized(eps);
+			double aicc = getAICC();
+			
+			if (aicc > bestaicc && params < size-1)
+			{
+				besteps = eps;
+				bestaicc = aicc;
+			}
+			eps = eps - delta;
+		}
+		
+		computeGeneralized(besteps);
+	}
+
+	/**
+	 * Compute log-likelihood
+	 */
+	public double getLogLikelihood()
+	{
+		double logL = 0.0;
+		
+		for (int i = 0; i < size; i++)
+		{
+			double w = ci.getInterval(i);
+			double m = populationSize[i];
+			
+			double n = ci.getNumLineages(i);
+			double nc2 = n*(n-1.0)/2.0;
+			
+			logL += Math.log(nc2/m) - w*nc2/m   ;
+		}
+		
+		return logL;
+	}
+
+	/**
+	 * Compute AICC-corrected log-likelihood
+	 */
+	public double getAICC()
+	{
+		double logL = getLogLikelihood();
+	
+		return PenalizedLikelihood.AICC(logL, params, size);
+	}
+
+	/**
+	 * Find interval corresponding to a specific time
+	 */
+	public double findInterval(double time)
+	{
+		if (time < 0) throw new IllegalArgumentException("Negative values for time are not allowed");
+		
+		for (int i = 0; i < size-1; i++)
+		{
+			if (time >= cis[i] && time < cis[i+1]) return i;
+		}
+		
+		return size-1;
+	}
+	 
+	/**
+	 * Returns the largest value of time defined in this plot 
+	 * (= maximum value for epsilon)
+	 */
+	public double getMaxTime()
+	{
+		return maxTime;
+	}
+
+
+	/**
+	 * Returns the largest estimate of population size.
+	 */
+	public double getMaxPopulationSize() {
+		double max = 0.0;
+		for (int i = 0; i < size; i++) {
+			if (populationSize[i] > max) {
+				max = populationSize[i];
+			}
+		}
+
+		return max;
+	}
+
+	/**
+	 * Returns the coalescent intervals in this skyline plot.
+	 */
+	public CoalescentIntervals getIntervals() {
+		return ci;
+	}
+
+	/**
+	 * Returns the number of intervals in this skyline plot.
+	 */
+	public int getSize() {
+		return size;
+	}
+	
+	/**
+	 * Returns the number of composite intervals (=number of parameters).
+	 */
+	public int getParameterCount() {
+		return params;
+	}
+
+	/**
+	 * Returns epsilon
+	 */
+	public double getEpsilon() {
+		return eps;
+	}
+	
+	/**
+	 * Returns the population size in interval i.
+	 */
+	public double getPopulationSize(int i) {
+		return populationSize[i];
+	}
+
+	/**
+	 * Returns unit of time.
+	 */
+	public int getUnits()
+	{
+		return ci.getUnits();
+	}
+
+
+	// private
+	
+	private CoalescentIntervals ci;
+	private FormattedOutput fo;
+	private int size;
+	private double maxTime;
+	private double eps;
+	private int params;
+	
+	/** cummulative interval sizes */
+	private double[] cis;
+	
+	/** estimated population size in a coalescent interval */
+	private double[] populationSize; 
+
+
+}
+
diff --git a/LibrarySource/pal/coalescent/makefile b/LibrarySource/pal/coalescent/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/coalescent/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/coalescent/package.html b/LibrarySource/pal/coalescent/package.html
new file mode 100644
index 0000000..7518094
--- /dev/null
+++ b/LibrarySource/pal/coalescent/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Classes to model population genetic processes using the coalescent.
+</body>
+</html>
diff --git a/LibrarySource/pal/datatype/AminoAcids.java b/LibrarySource/pal/datatype/AminoAcids.java
new file mode 100644
index 0000000..640f829
--- /dev/null
+++ b/LibrarySource/pal/datatype/AminoAcids.java
@@ -0,0 +1,164 @@
+// AminoAcidData.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * implements DataType for amino acids
+ *
+ * @version $Id: AminoAcids.java,v 1.10 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @note The Terminate state is not part of the "true" states of this DataType. It exists for terms of translating but
+					is regarded as a unknowncharacter in general. (but using getChar('*') will not return getNumStates(), but isUnknown() will classify it as unknown)
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ * @author Matthew Goode
+ */
+public class AminoAcids extends SimpleDataType
+{
+
+	public static final char TERMINATE_CHARACTER = '*';
+	public static final int TERMINATE_STATE = 21;
+	// Get number of amino acids
+	public int getNumStates()
+	{
+		return 20;
+	}
+
+	// Get state corresponding to character c
+	public int getState(char c)
+	{
+		switch (c)
+		{
+			case 'A':
+				return 0;
+			case 'C':
+				return 4;
+			case 'D':
+				return 3;
+			case 'E':
+				return 6;
+			case 'F':
+				return 13;
+			case 'G':
+				return 7;
+			case 'H':
+				return 8;
+			case 'I': 
+				return 9;
+			case 'K': 
+				return 11;
+			case 'L': 
+				return 10;
+			case 'M': 
+				return 12;
+			case 'N': 
+				return 2;
+			case 'P': 
+				return 14;
+			case 'Q': 
+				return 5;
+			case 'R': 
+				return 1;
+			case 'S':
+				return 15;
+			case 'T': 
+				return 16;
+			case 'V': 
+				return 19;
+			case 'W': 
+				return 17;
+			case 'Y':
+				return 18;
+			case UNKNOWN_CHARACTER:
+				return 20;
+			case TERMINATE_CHARACTER:
+				return 21; //Terminate
+			default:
+				return 20;
+		}
+	}
+
+	// Get character corresponding to a given state
+	public char getChar(int state)
+	{
+		switch (state)
+		{
+			case 0:
+				return 'A';
+			case 1:
+				return 'R';
+			case 2:
+				return 'N';
+			case 3:
+				return 'D';
+			case 4:
+				return 'C';
+			case 5:
+				return 'Q';
+			case 6:
+				return 'E';
+ 			case 7:
+				return 'G';
+			case 8:
+				return 'H';
+			case 9:
+				return 'I';
+			case 10:
+				return 'L';
+			case 11:
+				return 'K';
+			case 12:
+				return 'M';
+			case 13:
+				return 'F';
+			case 14:
+				return 'P';
+			case 15:
+				return 'S';
+			case 16:
+				return 'T';
+			case 17:
+				return 'W';
+ 			case 18:
+				return 'Y';
+			case 19:
+				return 'V';
+			case 20:
+				return UNKNOWN_CHARACTER;
+			case 21:
+				return TERMINATE_CHARACTER; //Terminate
+
+
+			default:
+				return UNKNOWN_CHARACTER;
+		}
+	}
+
+	/**
+		* @retrun true if this state is an unknown state
+		*/
+	public boolean isUnknownState(int state) {
+		return(state>=20);
+	}
+
+	// String describing the data type
+	public String getDescription()
+	{
+		return "Amino acid";
+	}
+
+	// Get numerical code describing the data type
+	public int getTypeID()
+	{
+		return 1;
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/CodonTable.java b/LibrarySource/pal/datatype/CodonTable.java
new file mode 100644
index 0000000..0a09afc
--- /dev/null
+++ b/LibrarySource/pal/datatype/CodonTable.java
@@ -0,0 +1,56 @@
+// CodonTable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * Describes a device for translating Nucleotide triplets
+ * or codon indices into amino acid codes
+ *
+ * @author Matthew Goode
+ * @author Alexei Drummond
+ *
+ * @version $Id: CodonTable.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ */
+
+public interface CodonTable extends java.io.Serializable {
+
+	/** 
+	 * Returns the char associated with AminoAcid represented by 'codon'
+	 * @note char is as defined by AminoAcids.java
+	 * @see AminoAcids
+	 * @return state for '?' if codon unknown or wrong length
+	 */
+	char getAminoAcidChar(char[] codon);
+
+	/** 
+	 * Returns the state associated with AminoAcid represented by 'codon'
+	 * @note state is as defined by AminoAcids.java
+	 * @see AminoAcids
+	 * @return '?' if codon unknown or wrong length
+	 */
+	int getAminoAcidState(char[] codon);
+
+	/** Returns the amino acid char at the corresponding codonIndex */
+	char getAminoAcidCharFromCodonIndex(int codonIndex);
+
+	/** Returns the amino acid state at the corresponding codonIndex */
+	int getAminoAcidStateFromCodonIndex(int codonIndex);
+
+	/**
+	 * Returns the codon indexes of terminator amino acids.
+	 */
+	int[] getTerminatorIndexes();
+
+	/**
+	 * Returns the number of terminator amino acids.
+	 */
+	int getNumberOfTerminatorIndexes();
+}
+
diff --git a/LibrarySource/pal/datatype/CodonTableFactory.java b/LibrarySource/pal/datatype/CodonTableFactory.java
new file mode 100644
index 0000000..d9fc286
--- /dev/null
+++ b/LibrarySource/pal/datatype/CodonTableFactory.java
@@ -0,0 +1,271 @@
+// CodonTableFactory.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * Generates CodonTables
+ *
+ * @author Matthew Goode
+ * @version $Id: CodonTableFactory.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ */
+
+
+public class CodonTableFactory {
+
+	/** Universal type */
+	public static final int UNIVERSAL = 0; 
+
+	/** Mitochondrial Vertebrate type */
+	public static final int M_VERTEBRATE = 1; 
+
+	public static final String[] TYPE_NAMES = {
+		"Universal",
+		"Mitochondrial Vertebrate"
+	};
+
+	/** 
+	 * Creates a translator of a given types
+	 * @param type - UNIVERSAL, M_VERTEBRATE
+	 */
+	public static CodonTable createTranslator(int type) {
+		switch(type) {
+			case UNIVERSAL : {
+				return new UniversalTranslator();
+			}
+			case M_VERTEBRATE : {
+				return new MVertebrateTranslator();
+			}
+			default : {
+				return new UniversalTranslator();
+			}
+		}
+	}
+
+	public static final CodonTable createUniversalTranslator() {
+		return createTranslator(UNIVERSAL);
+	}
+}
+
+// ========================================================================
+
+
+/** 
+ * A concrete implementation of a NucleotideTranslator for
+ * the Standard/Universal set of codes.
+ */
+class UniversalTranslator implements CodonTable {
+	int[] translations_ = new int[64];
+	int[] terminatorIndexes_ = null;
+	DataType aminoAcids_ = new AminoAcids();
+	DataType nucleotides_ = new Nucleotides();
+GeneralizedCodons generalizedCodons_ = new GeneralizedCodons();
+
+
+	private void addTerminalIndex(int index) {
+	 	int[] ts = new int[terminatorIndexes_.length+1];
+
+		for(int i = 0 ; i < terminatorIndexes_.length ; i++) {
+			ts[i] = terminatorIndexes_[i];
+		}
+		ts[ts.length-1] = index;
+		terminatorIndexes_ = ts;
+	}
+
+	/**
+	 * state must already be in set!
+	 */
+	private void removeTerminalIndex(int index) {
+
+	 	int[] ts = new int[terminatorIndexes_.length-1];
+		int toAddIndex = 0;
+
+		for(int i = 0 ; i < terminatorIndexes_.length ; i++) {
+			if(index!=terminatorIndexes_[i]) {
+				ts[toAddIndex] = terminatorIndexes_[i];
+				toAddIndex++;
+			}
+		}
+	}
+
+	/** Add a codon/aminoAcid translation into table. 
+	 * Overwrites previous translation for that codon. 
+	 * If the codon is invalid will throw a runtime exception!
+	 */
+	protected void add(String codon, char aminoAcid) {
+		int index = generalizedCodons_.getCodonIndexFromCodon(codon.toCharArray());
+		if(index<0) {
+			throw new RuntimeException("Assertion error: Adding invalid Codon:"+codon);
+		}
+		if(aminoAcid!= AminoAcids.TERMINATE_CHARACTER) {
+			//Are we obscuring a terminate?
+			if(translations_[index]==AminoAcids.TERMINATE_STATE) {
+				removeTerminalIndex(index);
+			}
+		} else {
+			addTerminalIndex(index);
+		}
+		translations_[index] = aminoAcids_.getState(aminoAcid);
+	}
+
+	/** 
+	 * Returns the char associated with AminoAcid represented by 'codon'.
+	 * @note char is as defined by AminoAcids.java
+	 * @see AminoAcids
+	 * @return state for '?' if codon unknown or wrong length
+	 */
+	public char getAminoAcidChar(char[] codon) {
+		return aminoAcids_.getChar(getAminoAcidState(codon));
+	}
+
+
+	/** 
+	 * Returns the state associated with AminoAcid represented by 'codon'.
+	 * @note state is as defined by AminoAcids.java
+	 * @return '?' if codon unknown or wrong length
+	 * @see AminoAcids
+	 */
+	public int getAminoAcidState(char[] codon) {
+		int index = generalizedCodons_.getCodonIndexFromCodon(codon);
+		if(index<0) {
+			return aminoAcids_.getState(DataType.UNKNOWN_CHARACTER);
+		}
+		return translations_[index];
+	}
+
+	public char getAminoAcidCharFromCodonIndex(int codonIndex) {
+		return aminoAcids_.getChar(getAminoAcidStateFromCodonIndex(codonIndex));
+	}
+
+	public int getAminoAcidStateFromCodonIndex(int codonIndex) {
+		return translations_[codonIndex];
+	}
+
+	/** 
+	 * Reset all values of the translation tables to -1 to 
+	 * signify they have not be initialised.
+	 */
+	private void clearTranslationTables() {
+		for(int i = 0 ; i < translations_.length ; i++) {
+		 	translations_[i] = -1;
+		}
+		terminatorIndexes_ = new int[0];
+	}
+
+	public UniversalTranslator() {
+		clearTranslationTables();
+		//Phe
+		add("UUU", 'F'); add("UUC", 'F');
+
+		//Leu
+		add("UUA", 'L'); add("UUG", 'L'); add("CUU", 'L'); add("CUC", 'L'); add("CUA", 'L'); add("CUG", 'L');
+
+		//Ile
+		add("AUU", 'I'); add("AUC", 'I'); add("AUA", 'I');
+
+		//Met
+		add("AUG", 'M');
+
+		//Val
+		add("GUU", 'V'); add("GUC", 'V'); add("GUA", 'V'); add("GUG", 'V');
+
+		//Ser
+		add("UCU", 'S'); add("UCC", 'S'); add("UCA", 'S'); add("UCG", 'S');
+
+		//Pro
+		add("CCU", 'P'); add("CCC", 'P'); add("CCA", 'P'); add("CCG", 'P');
+
+		//Thr
+		add("ACU", 'T'); add("ACC", 'T'); add("ACA", 'T'); add("ACG", 'T');
+
+		//Ala
+		add("GCU", 'A'); add("GCC", 'A'); add("GCA", 'A'); add("GCG", 'A');
+
+		//Tyr
+		add("UAU", 'Y'); add("UAC", 'Y');
+
+		//Ter
+		add("UAA", AminoAcids.TERMINATE_CHARACTER); add("UAG", AminoAcids.TERMINATE_CHARACTER);
+
+		//His
+		add("CAU", 'H'); add("CAC", 'H');
+
+		//Gln
+		add("CAA", 'Q'); add("CAG", 'Q');
+
+		//Asn
+		add("AAU", 'N'); add("AAC", 'N');
+
+		//Lys
+		add("AAA", 'K'); add("AAG", 'K');
+
+		//Asp
+		add("GAU", 'D'); add("GAC", 'D');
+
+		//Glu
+		add("GAA", 'E'); add("GAG", 'E');
+
+		//Cys
+		add("UGU", 'C'); add("UGC", 'C');
+
+		//Ter
+		add("UGA", AminoAcids.TERMINATE_CHARACTER);
+
+		//Trp
+		add("UGG", 'W');
+
+		//Arg
+		add("CGU", 'R'); add("CGC" , 'R'); add("CGA", 'R'); add("CGG", 'R');
+
+		//Ser
+		add("AGU", 'S'); add("AGC" , 'S');
+
+		//Arg
+		add("AGA", 'R'); add("AGG", 'R');
+
+		//Gly
+		add("GGU", 'G'); add("GGC" , 'G'); add("GGA", 'G'); add("GGG", 'G');
+
+		//check();
+	}
+
+	public void check() {
+		System.out.println("Checking");
+		for(int i = 0 ; i < translations_.length ; i++) {
+			if(translations_[i] == -1) {
+				System.out.println("No Translation for codon:"+i+"("+(new String(generalizedCodons_.getCodonFromCodonIndex(i)))+")");
+			}
+		}
+	}
+
+	public int[] getTerminatorIndexes() {
+		return terminatorIndexes_;
+	}
+	public int getNumberOfTerminatorIndexes() {
+	 	return terminatorIndexes_.length;
+	}
+}
+
+class MVertebrateTranslator extends UniversalTranslator {
+	public MVertebrateTranslator() {
+		super();
+		//Tro
+		add("UGA", 'W');
+
+		//Ter
+		add("AGA", AminoAcids.TERMINATE_CHARACTER); add("AGG", AminoAcids.TERMINATE_CHARACTER);
+
+		//Met
+		add("AUA", 'M');
+	}
+}
+
+
+
+
diff --git a/LibrarySource/pal/datatype/CodonTableUtils.java b/LibrarySource/pal/datatype/CodonTableUtils.java
new file mode 100644
index 0000000..5728e78
--- /dev/null
+++ b/LibrarySource/pal/datatype/CodonTableUtils.java
@@ -0,0 +1,76 @@
+// CodonTableUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * Nucleotide Translating Utilities
+ *
+ * @author Matthew Goode
+ *
+ * @version $Id: CodonTableUtils.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ */
+
+public class CodonTableUtils {
+
+
+	/**
+	 * Translates a Nucleotide sequence into a Amino Acid sequence
+	 */
+	public static final String convertNucleotideToAminoAcid(String
+	nucleotideSequence, int startingPosition, int length, boolean reverse, 
+		CodonTable translator) {
+		return (convertNucleotideToAminoAcid(nucleotideSequence.toCharArray(), startingPosition,length, reverse, translator)).toString();
+	}
+
+
+	/**
+	 * Translates a Nucleotide sequence into a Amino Acid sequence
+	 * @param nucleotideSequence - the base nucleotide sequence as a char array
+	 * @param starting position - the starting position to begin reading from
+	 * @param length - the length of the reading frame (in nucleotide units - 
+	 * should be a multiple of 3, if not remainder is truncated!)
+	 * @param reverse - if true works backwards with codon at starting 
+	 * position being last in translation (codon read in reverse as well). 
+	 * Else reads forwards.
+	 * @param translator - the nucleotide translator to use for translation
+	 * nucleotides into amino acids.
+	 * @note can handle circular reading frames (ie startingPositon+length 
+	 * can be greater than seuqnce length)
+	 */
+	public static final char[] convertNucleotideToAminoAcid(char[]
+	nucleotideSequence, int startingPosition, int length, boolean reverse, 
+	CodonTable translator) {
+		char[] work = new char[3];
+		//Normal dircection
+		int numberOfAminoAcids = (length)/3;
+		char[] aas = new char[numberOfAminoAcids];
+		if(reverse) {
+			for(int i = 0 ; i < numberOfAminoAcids ; i++) {
+				int index = i*3+startingPosition;;
+				for(int j = 0 ; j < 3 ; j++) {
+					work[j] = nucleotideSequence[(index+2-j)%nucleotideSequence.length];
+				}
+				aas[numberOfAminoAcids-i-1] = translator.getAminoAcidChar(work);
+			}
+		} else {
+			for(int i = 0 ; i < numberOfAminoAcids ; i++) {
+				int index = i*3+startingPosition;
+				for(int j = 0 ; j < 3 ; j++) {
+					work[j] = nucleotideSequence[(index+j)%nucleotideSequence.length];
+				}
+				aas[i] = translator.getAminoAcidChar(work);
+			}
+		}
+		return aas;
+
+	}
+
+}
+
diff --git a/LibrarySource/pal/datatype/Codons.java b/LibrarySource/pal/datatype/Codons.java
new file mode 100644
index 0000000..71054ae
--- /dev/null
+++ b/LibrarySource/pal/datatype/Codons.java
@@ -0,0 +1,73 @@
+// Codons.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * implements DataType for all Codons (including terminators).
+ * Accepts the same characters as those given by
+ * CodonTranslator.getUniqueCharacter(), 
+ * states here are index for CodonTranslator.getCodonIndex()
+ * That is. Codons.getCharacter(CondonTranslator.getIndex("codon")) ==
+ * CondonTranslator.getUniqueCharacter("codon")
+ *
+ * @version $Id: Codons.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class Codons extends SimpleDataType
+{
+
+	// Get number of bases
+	public int getNumStates()
+	{
+		return 64;
+	}
+
+	
+	public int getState(char c)
+	{
+  	if(c==UNKNOWN_CHARACTER) {
+			return 64;
+		}
+		return (int)(c - 64);
+	}
+
+	/**
+	 * Get character corresponding to a given state
+	 */
+	public char getChar(int state)
+	{
+
+		if(state>=64) {
+			return UNKNOWN_CHARACTER;
+		}
+		return (char)(state + 64);
+	}
+
+	// String describing the data type
+	public String getDescription()
+	{
+		return "Codon";
+	}
+
+	/**
+		* @retrun true if this state is an unknown state
+		*/
+	public boolean isUnknownState(int state) {
+		return(state>=64);
+	}
+
+	// Get numerical code describing the data type
+	public int getTypeID()
+	{
+		return DataType.CODONS;
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/DataType.java b/LibrarySource/pal/datatype/DataType.java
new file mode 100644
index 0000000..1bd2529
--- /dev/null
+++ b/LibrarySource/pal/datatype/DataType.java
@@ -0,0 +1,103 @@
+// DataType.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// Known bugs and limitations:
+// - all states must have a non-negative value 0..getNumStates()-1
+// - ? (unknown state) has value getNumStates()
+
+
+package pal.datatype;
+
+import java.io.Serializable;
+
+/**
+ * interface for sequence data types
+ *
+ * @version $Id: DataType.java,v 1.11 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public interface DataType extends Serializable
+{
+	//
+	// Public stuff
+	//
+
+	char UNKNOWN_CHARACTER = '?';
+	
+	int NUCLEOTIDES = 0;
+	int AMINOACIDS = 1;
+	int TWOSTATES = 2;
+	int IUPACNUCLEOTIDES = 3;
+	int CODONS = 4;
+	int GENERALIZEDCODONS = 5;
+	
+	/**
+	 * get number of unique states
+	 *
+	 * @return number of unique states
+	 */
+	int getNumStates();
+
+	/**
+	 * get number of unique non-ambiguous states
+	 *
+	 * @return number of unique states
+	 */
+	int getNumSimpleStates();
+
+	/**
+	 * get state corresponding to a character
+	 *
+	 * @param c character
+	 *
+	 * @return state
+	 */
+	int getState(char c);
+
+	/**
+	 * get character corresponding to a given state
+	 *
+	 * @param state state
+	 *
+	 * return corresponding character
+	 */
+	char getChar(int state);
+	
+	/**
+	 * returns true if this state is an ambiguous state.
+	 */
+	boolean isAmbiguousState(int state);
+
+	/**
+	 * returns an array containing the non-ambiguous states that this state represents.
+	 */
+	int[] getSimpleStates(int state);
+	
+	/**
+	 * description of data type
+	 *
+	 * @return string describing the data type
+	 */
+	String getDescription();
+	
+	/**
+	 * get numerical code describing the data type
+	 *
+	 * @return numerical code
+	 */
+	int getTypeID();
+
+	/**
+	 * @return true if this state is an unknown state 
+	 * (the same as check if a state is >= the number of states... but neater)
+	 */
+	boolean isUnknownState(int state);
+}
+
diff --git a/LibrarySource/pal/datatype/DataTypeUtils.java b/LibrarySource/pal/datatype/DataTypeUtils.java
new file mode 100644
index 0000000..48ad485
--- /dev/null
+++ b/LibrarySource/pal/datatype/DataTypeUtils.java
@@ -0,0 +1,81 @@
+// DataTypeUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.datatype;
+
+import java.io.Serializable;
+
+/**
+ * helper class for sequence data types.
+ *
+ * @version $Id: DataTypeUtils.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class DataTypeUtils implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * create object according to this code
+	 *
+	 * @param typeID selected data type
+	 *
+	 * @return DataType object
+	 */
+	public static DataType getInstance(int typeID)
+	{
+		if (typeID == DataType.NUCLEOTIDES)
+		{
+			return new Nucleotides();
+		}
+		else if (typeID == DataType.AMINOACIDS)
+		{
+			return new AminoAcids();
+		}
+		else if (typeID == DataType.TWOSTATES)
+		{
+			return new TwoStates();
+		}
+		else if (typeID == DataType.CODONS)
+		{
+			return new Codons();
+		}
+		else if (typeID == DataType.GENERALIZEDCODONS)
+		{
+			return new Codons();
+		}
+		else
+		{
+			throw new IllegalArgumentException("Wrong typeID");
+		}
+	}
+
+	/**
+	 * Return states of a sequence.
+	 */
+	public final static int[] getSequenceStates(DataType d, String sequence) {
+		
+		int[] states = new int[sequence.length()];
+		
+		for (int i = 0; i < sequence.length(); i++) {
+			states[i] = d.getState(sequence.charAt(i));
+		}
+		return states;
+	}
+
+	/**
+	 * returns true if the character represents a gap in the sequence.
+	 */
+	public final static boolean isGap(DataType d, char c) {
+		return d.getState(c) == d.getNumStates();
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/GeneralizedCodons.java b/LibrarySource/pal/datatype/GeneralizedCodons.java
new file mode 100644
index 0000000..6ad4636
--- /dev/null
+++ b/LibrarySource/pal/datatype/GeneralizedCodons.java
@@ -0,0 +1,223 @@
+// GeneralizedCodons.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.datatype;
+
+import pal.math.MathUtils;
+
+// Note this class used to be called CodonTranslator
+
+/** 
+ * Used for mapping an exact codon to an exact state, and vice versa
+ * Can also be used as a DataType (exactly as for Codons, but more versatile).
+ * 
+ * @author Matthew Goode
+ * @version $Id: GeneralizedCodons.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ */
+public class GeneralizedCodons extends SimpleDataType implements java.io.Serializable {
+
+	DataType characterType_ = null;
+	int numberOfCharacterStates_ =	-1; // Caching of characterType_.getNumStates()
+	int codonLength_;
+
+	//==== For Datatype Interface ====
+	int numberOfCodonStates_;
+
+	/** The Biologists, what else do we need, constructor (nucleode character types, codon length 3) */
+	public GeneralizedCodons () {
+		this(new Nucleotides(),3);
+	}
+
+	/** The Computer Scientist's want of abstraction consturctor */
+	public GeneralizedCodons (DataType characterType, int codonLength) {
+		this.characterType_ = characterType;
+		this.numberOfCharacterStates_ = characterType_.getNumStates();
+		this.codonLength_ = codonLength;
+		numberOfCodonStates_ = 1;
+		for(int i = 0 ; i < codonLength_ ; i++) {
+			numberOfCodonStates_*=numberOfCharacterStates_;
+		}
+	}
+
+	/** Returns -1 if the codon has unknowns, or gaps in it, or is less than length length! */
+	public final int getCodonIndexFromCodon(char[] codon) {
+		if(codon.length<codonLength_) {
+			return -1;
+		}
+		int index = 0;
+		for(int i = 0 ; i < codonLength_ ; i++) {
+			index*=numberOfCharacterStates_;
+			int state = characterType_.getState(codon[i]);
+			if(state>=numberOfCharacterStates_) {
+				return -1;
+			}
+			index+=state;
+		}
+		return index;
+	}
+
+	/** Translates an index into a codon */
+	public final char[] getCodonFromCodonIndex(int index) {
+		char[] cs = new char[codonLength_];
+		for(int i = codonLength_-1 ; i >=0 ; i--) {
+			cs[i] = characterType_.getChar(index%numberOfCharacterStates_);
+			index/=numberOfCharacterStates_;
+		}
+		return cs;
+	}
+
+	/**
+	 * Returns a unique ascii character for any given codon index
+	 */
+	public final char getCodonCharFromCodonIndex(int index) {
+		return (char)(index + 64);
+	}
+
+	/**
+	 * Returns a unique ascii character for any given codon index
+	 */
+	public final int getCodonIndexFromCodonChar(char c) {
+		return (int)(c - 64);
+	}
+
+	/**
+	 * Returns a unique ascii character for any given codon
+	 */
+	public final char getCodonCharFromCodon(char[] codon) {
+		return getCodonCharFromCodonIndex(getCodonIndexFromCodon(codon));
+	}
+
+
+	/**
+	 * Translates a Nucleotide sequence into a Codon sequence
+	 */
+	public final String convertNucleotideToCodon(String nucleotideSequence, int startingPosition, int length, boolean reverse ) {
+		return (convertNucleotideToCodon(nucleotideSequence.toCharArray(), startingPosition,length, reverse )).toString();
+	}
+
+	/**
+	 * Translates a Nucleotide sequence into a Codon sequence
+	 * @param nucleotideSequence - the base nucleotide sequence as a char array
+	 * @param starting position - the starting position to begin reading from
+	 * @param length - the length of the reading frame (in nucleotide units -
+	 * should be a multiple of 3, if not remainder is truncated!)
+	 * @param reverse - if true works backwards with codon at starting
+	 * position being last in translation (codon read in reverse as well). 
+	 * Else reads forwards.
+	 * @param translator - the nucleotide translator to use for translation
+	 * nucleotides into amino acids.
+	 * @note can handle circular reading frames (ie startingPositon+length
+	 * can be greater than seuqnce length)
+	 */
+	public final char[] convertNucleotideToCodon(char[] nucleotideSequence, int startingPosition, int length, boolean reverse) {
+
+		char[] work = new char[codonLength_];
+		//Normal direction
+		int numberOfCodons = (length)/codonLength_;
+		char[] aas = new char[numberOfCodons];
+		if(reverse) {
+			for(int i = 0 ; i < numberOfCodons ; i++) {
+				int index = i*codonLength_+startingPosition;;
+				for(int j = 0 ; j < codonLength_ ; j++) {
+					work[j] = nucleotideSequence[(index+codonLength_-1-j)%nucleotideSequence.length];
+				}
+				aas[numberOfCodons-i-1] = getCodonCharFromCodon(work);
+			}
+		} else {
+			for(int i = 0 ; i < numberOfCodons ; i++) {
+				int index = i*codonLength_+startingPosition;
+				for(int j = 0 ; j < codonLength_ ; j++) {
+					work[j] = nucleotideSequence[(index+j)%nucleotideSequence.length];
+				}
+				aas[i] = getCodonCharFromCodon(work);
+			}
+		}
+		return aas;
+	}
+
+	// ============================== Datatype Stuff	============================
+
+	/**
+	 * get number of unique states
+	 *
+	 * @return number of unique states
+	 */
+	public int getNumStates() { return numberOfCodonStates_;	}
+
+	/**
+	 * get state corresponding to a character
+	 *
+	 * @param c character
+	 *
+	 * @return state
+	 */
+	public int getState(char c)	{
+		if(c==UNKNOWN_CHARACTER) {
+		 	return numberOfCodonStates_;
+		}
+		return getCodonIndexFromCodonChar(c);
+	}
+
+	/**
+	 * Get character corresponding to a given state
+ 	 */
+	public char getChar(int state) {
+
+		if(state>=numberOfCodonStates_) {
+		 	return UNKNOWN_CHARACTER;
+		}
+		return getCodonCharFromCodonIndex(state);
+	}
+
+	/**
+	 * String describing the data type
+	 */
+	public String getDescription() {
+		return "Codon";
+	}
+
+	/**
+	 * @return true if this state is an unknown state
+	 */
+	public boolean isUnknownState(int state) {
+		return(state>=64);
+	}	
+
+	/**
+	 * Get numerical code describing the data type
+	 */
+	public int getTypeID() 	{
+		return DataType.GENERALIZEDCODONS;
+	}
+
+	//======
+
+	public double[] getCodonFrequencies(double[] residueFrequencies) {
+		residueFrequencies = MathUtils.getNormalized(residueFrequencies);
+		double[] codonFreqs = new double[numberOfCodonStates_];
+
+		for(int j = 0 ; j < numberOfCodonStates_ ; j++) {
+			int index = j;
+			double prob = 1;
+
+			for(int i = codonLength_-1 ; i >=0 ; i--) {
+				prob	*= residueFrequencies[index%numberOfCharacterStates_];
+				index/=numberOfCharacterStates_;
+			}
+
+			codonFreqs[j] = prob;
+		}
+		return MathUtils.getNormalized(codonFreqs);
+	}
+
+	/** Not correctly implemented!! */
+	public double[] getNucleotideFrequencies(double[] codonFrequencies) {
+		return new double[] {0.25,0.25,0.25,0.25};
+	}
+
+}
+
diff --git a/LibrarySource/pal/datatype/IUPACNucleotides.java b/LibrarySource/pal/datatype/IUPACNucleotides.java
new file mode 100644
index 0000000..5ae2afb
--- /dev/null
+++ b/LibrarySource/pal/datatype/IUPACNucleotides.java
@@ -0,0 +1,148 @@
+// IUPACNucleotides.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * implements DataType for nucleotides with ambiguous characters
+ *
+ * @version $Id: IUPACNucleotides.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class IUPACNucleotides implements DataType
+{
+	/**
+	 * Get number of states.
+	 */
+	public int getNumStates()
+	{
+		return 15;
+	}
+
+	/**
+	 * @retrun true if this state is an unknown state
+	 */
+	public boolean isUnknownState(int state) {
+		return(state>=getNumStates());
+	}
+
+	/**
+	 * returns the number of true non-ambiguous states.
+	 */
+	public int getNumSimpleStates() {
+		return 4;
+	}
+
+
+	// Get state corresponding to character c
+	public final int getState(char c) {
+	
+		switch (c) {
+			case 'A': return  0;
+			case 'C': return  1;
+			case 'G': return  2;
+			case 'T': return  3;
+			case 'U': return  3;
+			case 'K': return  4;
+			case 'M': return  5;
+			case 'R': return  6;
+			case 'S': return  7;
+			case 'W': return  8;
+			case 'Y': return  9;
+			case 'B': return 10;
+			case 'D': return 11;
+			case 'H': return 12;
+			case 'V': return 13;
+			case 'N': return 14;
+			default: return  15;
+		}
+	}
+
+	// Get character corresponding to a given state
+	public final char getChar(int c) {
+		
+		switch (c) {
+			case  0: return 'A';
+			case  1: return 'C';
+			case  2: return 'G';
+			case  3: return 'U';
+			case  4: return 'K';
+			case  5: return 'M';
+			case  6: return 'R';
+			case  7: return 'S';
+			case  8: return 'W';
+			case  9: return 'Y';
+			case 10: return 'B';
+			case 11: return 'D';
+			case 12: return 'H';
+			case 13: return 'V';
+			case 14: return 'N';
+			default: return '?';
+		}
+	}
+
+	// String describing the data type
+	public String getDescription()
+	{
+		return "IUPACNucleotide";
+	}
+	
+	// Get numerical code describing the data type
+	public int getTypeID()
+	{
+		return DataType.IUPACNUCLEOTIDES;
+	}
+
+	/**
+	 * returns true if this state is an ambiguous state.
+	 */
+	public boolean isAmbiguousState(int state) {
+		if ((state > 3) && (state < getNumStates())) {
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * returns an array containing the non-ambiguous states 
+	 * that this state represents.
+	 */
+	public int[] getSimpleStates(int state) {
+		
+		String stateString = "";
+		
+		switch (state) {
+			case 0: stateString = "A"; break;
+			case 1: stateString = "C"; break;
+			case 2: stateString = "G"; break;
+			case 3: stateString = "T"; break;
+			case 4: stateString = "GT"; break;
+			case 5: stateString = "AC"; break;
+			case 6: stateString = "AG"; break;
+			case 7: stateString = "CG"; break;
+			case 8: stateString = "AT"; break;
+			case 9: stateString = "CT"; break;
+			case 10: stateString = "CGT"; break;
+			case 11: stateString = "AGT"; break;
+			case 12: stateString = "ACT"; break;
+			case 13: stateString = "ACG"; break;
+			case 14: stateString = "ACGT"; break;
+			default: stateString = "ACGT"; break;
+		}
+		
+		int[] states = new int[stateString.length()];
+		for (int i = 0; i < stateString.length(); i++) {
+			states[i] = getState(stateString.charAt(i));
+		}
+		
+		return states;
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/IUPACPenaltyTable.java b/LibrarySource/pal/datatype/IUPACPenaltyTable.java
new file mode 100644
index 0000000..e24a693
--- /dev/null
+++ b/LibrarySource/pal/datatype/IUPACPenaltyTable.java
@@ -0,0 +1,67 @@
+// IUPACPenaltyTable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+/**
+ * Implements a table of transition penalties for a DNA states 
+ * and IUPAC ambiguous states. A mismatch is normalized to a
+ * penalty of 1.0 <br>
+ * Used for alignment scoring. 
+ *
+ * @version $Id: IUPACPenaltyTable.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+ 
+public class IUPACPenaltyTable implements TransitionPenaltyTable {
+
+	private static final double hlf = 0.5;
+	private static final double tth = 2.0 / 3.0;
+	private static final double fsx = 5.0 / 6.0;
+	private static final double thq = 3.0 / 4.0;
+	private static final double sni = 7.0 / 9.0;
+ 
+	public double[][] IUPACPenalties = { 
+	// A	C    G    T     K    M    R    S    W    Y      B    D    H    V     N   -	
+	{  0,   1,   1,   1,    1, hlf, hlf,   1, hlf,   1,     1, tth, tth, tth,  thq,	1}, // A
+	{  1,   0,   1,   1,    1, hlf,   1, hlf,   1, hlf,   tth,   1, tth, tth,  thq,	1}, // C
+	{  1,   1,   0,   1,  hlf,   1, hlf, hlf,   1,   1,   tth, tth,   1, tth,  thq,	1}, // G
+	{  1,   1,   1,   0,  hlf,   1,   1,   1, hlf, hlf,   tth, tth, tth,   1,  thq,	1}, // T
+	
+	{  1,   1, hlf, hlf,  hlf,   1, thq, thq, thq, thq,   tth, tth, fsx, fsx,  thq,  1}, // K
+	{hlf, hlf,   1,   1,    1, hlf, thq, thq, thq, thq,   fsx, fsx, tth, tth,  thq,  1}, // M
+	{hlf,   1, hlf,   1,  thq, thq, hlf, thq, thq,   1,   fsx, tth, fsx, tth,  thq,  1}, // R
+	{  1, hlf, hlf,   1,  thq, thq, thq, hlf,   1, thq,   tth, fsx, fsx, tth,  thq,  1}, // S
+	{hlf,   1,   1, hlf,  thq, thq, thq,   1, hlf, thq,   fsx, tth, tth, fsx,  thq,  1}, // W
+	{  1, hlf,   1, hlf,  thq, thq,   1, thq, thq, hlf,   tth, fsx, tth, fsx,  thq,  1}, // Y
+	
+	{  1, tth, tth, tth,  tth, fsx, fsx, tth, fsx, tth,   tth, sni, sni, sni,  thq,  1}, // B
+	{tth,   1, tth, tth,  tth, fsx, tth, fsx, tth, fsx,   sni, tth, sni, sni,  thq,  1}, // D
+	{tth, tth,   1, tth,  fsx, tth, fsx, fsx, tth, tth,   sni, sni, tth, sni,  thq,  1}, // H
+	{tth, tth, tth,   1,  fsx, tth, tth, tth, fsx, fsx,   sni, sni, sni, tth,  thq,  1}, // V
+	
+	{thq, thq, thq, thq,  thq, thq, thq, thq, thq, thq,   thq, thq, thq, thq,  thq,  1}, // N
+	
+	{  1,   1,   1,   1,    1,   1,   1,   1,   1,   1,     1,   1,   1,   1,    1,  0}  // -
+	};
+	
+	public static final String[] all = {"A", "C", "G", "U", "K", "M", "R", "S", "W", "Y", "B", "D", "H", "V", "N", "-"};
+
+	private DataType dataType = new IUPACNucleotides();
+
+	public final double penalty(int a, int b) {
+   
+		return IUPACPenalties[a][b];
+	}
+
+	public final DataType getDataType() {
+		return dataType;
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/Nucleotides.java b/LibrarySource/pal/datatype/Nucleotides.java
new file mode 100644
index 0000000..4edb35a
--- /dev/null
+++ b/LibrarySource/pal/datatype/Nucleotides.java
@@ -0,0 +1,151 @@
+// NucleotideData.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * implements DataType for nucleotides
+ *
+ * @version $Id: Nucleotides.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class Nucleotides extends SimpleDataType {
+	public static final int A_STATE = 0;
+  public static final int C_STATE = 1;
+	public static final int G_STATE = 2;
+	public static final int UT_STATE = 3;
+
+
+	boolean isRNA_;
+
+
+	public Nucleotides() {
+  	this(false);
+  }
+
+  /** If isRNA is true than getChar(state) will return a U instead of a T */
+  public Nucleotides(boolean isRNA) {
+  	this.isRNA_ = isRNA;
+  }
+
+	// Get number of bases
+	public int getNumStates()
+	{
+		return 4;
+	}
+
+		/**
+		* @retrun true if this state is an unknown state
+		*/
+	public boolean isUnknownState(int state) {
+		return(state>=4);
+	}
+	// Get state corresponding to character c
+	// NOTE: IF YOU CHANGE THIS IT MAY STOP THE NUCLEOTIDE TRANSLATOR FROM WORKING!
+	//  - It relies on the fact that all the states for 'ACGTU' are between [0, 3]
+	public int getState(char c)
+	{
+		switch (c)
+		{
+ 			case 'A':
+				return A_STATE;
+			case 'C':
+				return C_STATE;
+			case 'G':
+				return G_STATE;
+			case 'T':
+				return UT_STATE;
+			case 'U':
+				return UT_STATE;
+
+			case UNKNOWN_CHARACTER:
+				return 4;
+
+			default:
+				return 4;
+		}
+	}
+
+	// Get character corresponding to a given state
+	public char getChar(int state) {
+		switch (state)
+		{
+			case A_STATE:
+				return 'A';
+			case C_STATE:
+				return 'C';
+			case G_STATE:
+				return 'G';
+			case UT_STATE:
+				return (isRNA_ ? 'U' :'T');
+
+			case 4:
+				return UNKNOWN_CHARACTER;
+
+			default:
+				return UNKNOWN_CHARACTER;
+		}
+	}
+
+	// String describing the data type
+	public String getDescription()	{
+		return "Nucleotide";
+	}
+
+	// Get numerical code describing the data type
+	public int getTypeID() {
+		return 0;
+	}
+
+	/**
+		Returns true if A->G, G->A, C->T, or T->C
+		if firstState equals secondState returns FALSE!
+	*/
+	public final boolean isTransistionByState(int firstState, int secondState) {
+		switch(firstState) {
+			case A_STATE: {
+				if(secondState==G_STATE) {
+					return true;
+				}
+				return false;
+			}
+			case C_STATE : {
+				if(secondState==UT_STATE) {
+					return true;
+				}
+				return false;
+			}
+			case G_STATE : {
+				if(secondState==A_STATE) {
+					return true;
+				}
+				return false;
+			}
+			case UT_STATE : {
+				if(secondState==C_STATE) {
+					return true;
+				}
+				return false;
+			}
+		}
+		return false;
+	}
+	/**
+		Returns true if A->G, G->A, C->T, or T->C
+		if firstState equals secondState returns FALSE!
+		(I've renamed things to avoid confusion between java typing of ints and chars)
+	*/
+	public final boolean isTransistionByChar(char firstChar, char secondChar) {
+		//I'm leaving it open to a possible optimisation if anyone cares.
+		return isTransistionByState(getState(firstChar), getState(secondChar));
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/SimpleDataType.java b/LibrarySource/pal/datatype/SimpleDataType.java
new file mode 100644
index 0000000..0a697f3
--- /dev/null
+++ b/LibrarySource/pal/datatype/SimpleDataType.java
@@ -0,0 +1,60 @@
+// SimpleDataType.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// Known bugs and limitations:
+// - all states must have a non-negative value 0..getNumStates()-1
+// - ? (unknown state) has value getNumStates()
+
+
+package pal.datatype;
+
+import java.io.Serializable;
+
+/**
+ * interface for sequence data types
+ *
+ * @version $Id: SimpleDataType.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public abstract class SimpleDataType implements DataType
+{
+	
+	/**
+	 * returns true if this state is an ambiguous state.
+	 */
+	public final boolean isAmbiguousState(int state) {
+		return false;
+	}
+	
+	/**
+	 * returns an array containing the non-ambiguous states that this state represents.
+	 */
+	public final int[] getSimpleStates(int state) {
+		int[] simple = new int[1];
+		simple[0] = state;
+		return simple;
+	}
+
+	/**
+	 * get number of unique non-ambiguous states
+	 *
+	 * @return number of unique states
+	 */
+	public final int getNumSimpleStates() {
+		return getNumStates();
+	}
+
+	/**
+	 * Returns true if state is unknown
+	 */
+	public boolean isUnknownState(int state) {
+		return state >= getNumStates();
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/StateRemover.java b/LibrarySource/pal/datatype/StateRemover.java
new file mode 100644
index 0000000..a07db44
--- /dev/null
+++ b/LibrarySource/pal/datatype/StateRemover.java
@@ -0,0 +1,91 @@
+// StateRemover.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.datatype;
+
+/** A standard data type, but with characters removed */
+public class StateRemover extends SimpleDataType implements java.io.Serializable {
+	DataType toAdjust_;
+
+  int[] originalToAdjusted_; /** A translation array -> originalToAdjusted_["original State"] = "adjusted state" */
+  int[] adjustedToOriginal_; /** A translation array -> originalToAdjusted_["adjusted State"] = "original state" */
+
+  public StateRemover(DataType toAdjust, int[] statesToRemove) {
+    this.toAdjust_ = toAdjust;
+  	createTranslationTables(toAdjust.getNumStates(),statesToRemove);
+  }
+
+  private final void createTranslationTables(int numberOfOriginalStates, int[] statesToRemove) {
+  	originalToAdjusted_ = new int[numberOfOriginalStates];
+		adjustedToOriginal_ = new int[numberOfOriginalStates-statesToRemove.length];
+    int currentAdjustedState = 0;
+    for(int i = 0 ; i < numberOfOriginalStates ; i++ ) {
+    	boolean removeState = false;
+    	for(int j = 0 ; j < statesToRemove.length ; j++) {
+      	if(statesToRemove[j] == i) {
+        	removeState = true;
+        	break;
+        }
+			}
+			if(removeState) {
+				originalToAdjusted_[i] = adjustedToOriginal_.length;
+			} else {
+				originalToAdjusted_[i] = currentAdjustedState;
+				adjustedToOriginal_[currentAdjustedState] = i;
+				currentAdjustedState++;
+      }
+    }
+  }
+
+	// Get number of bases
+	public int getNumStates()	{
+		return adjustedToOriginal_.length;
+	}
+
+	/**
+		* @retrun true if this state is an unknown state
+		*/
+	public boolean isUnknownState(int state) {
+		return(state>=adjustedToOriginal_.length);
+	}
+
+
+	public int getState(char c)	{
+  	int unadjustedState = toAdjust_.getState(c);
+  	if(!toAdjust_.isUnknownState(unadjustedState)) {
+			return originalToAdjusted_[unadjustedState]; /* May also return unknown, see constructor*/
+		}
+		return adjustedToOriginal_.length;
+	}
+
+	/**
+	 * Get character corresponding to a given state
+ 	 */
+	public char getChar(int state)
+	{
+  	if(state>adjustedToOriginal_.length) {
+     	return UNKNOWN_CHARACTER;
+    }
+  	return toAdjust_.getChar(adjustedToOriginal_[state]);
+	}
+
+	// String describing the data type
+	public String getDescription()
+	{
+		return toAdjust_.getDescription()+" with states removed";
+	}
+
+	// Get numerical code describing the data type
+	public int getTypeID()
+	{
+		return toAdjust_.getTypeID();
+	}
+
+
+
+}
+
diff --git a/LibrarySource/pal/datatype/TransitionPenaltyTable.java b/LibrarySource/pal/datatype/TransitionPenaltyTable.java
new file mode 100644
index 0000000..c3c4d79
--- /dev/null
+++ b/LibrarySource/pal/datatype/TransitionPenaltyTable.java
@@ -0,0 +1,25 @@
+// TransitionPenaltyTable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * Implements a table of transition penalties for a particular datatype.
+ * Used for alignment scoring. 
+ *
+ * @version $Id: TransitionPenaltyTable.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface TransitionPenaltyTable  {
+    
+	double penalty(int a, int b);
+	DataType getDataType();
+}
+
diff --git a/LibrarySource/pal/datatype/TwoStates.java b/LibrarySource/pal/datatype/TwoStates.java
new file mode 100644
index 0000000..48d9e41
--- /dev/null
+++ b/LibrarySource/pal/datatype/TwoStates.java
@@ -0,0 +1,83 @@
+// TwoStateData.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.datatype;
+
+
+/**
+ * implements DataType for two-state data
+ *
+ * @version $Id: TwoStates.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class TwoStates extends SimpleDataType
+{
+	// Get number of bases
+	public int getNumStates()
+	{
+		return 2;
+	}
+
+	// Get state corresponding to character c
+	public int getState(char c)
+	{
+		switch (c)
+		{
+ 			case '0': 
+				return 0;
+			case '1': 
+				return 1;
+				
+			case UNKNOWN_CHARACTER:
+				return 2;
+
+			default:
+				return 2;
+		}
+	}
+
+	/**
+		* @retrun true if this state is an unknown state
+		*/
+	public boolean isUnknownState(int state) {
+		return(state>=2);
+	}
+
+	// Get character corresponding to a given state
+	public char getChar(int state)
+	{
+		switch (state)
+		{
+			case 0:
+				return '0';
+			case 1:
+				return '1';
+
+			case 2:
+				return UNKNOWN_CHARACTER;
+
+			default:
+				return UNKNOWN_CHARACTER;
+		}
+	}
+
+	// String describing the data type
+	public String getDescription()
+	{
+		return "Two state";
+	}
+
+	// Get numerical code describing the data type
+	public int getTypeID()
+	{
+		return 2;
+	}
+}
+
diff --git a/LibrarySource/pal/datatype/makefile b/LibrarySource/pal/datatype/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/datatype/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/datatype/package.html b/LibrarySource/pal/datatype/package.html
new file mode 100644
index 0000000..39a3297
--- /dev/null
+++ b/LibrarySource/pal/datatype/package.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+Classes describing data types (nucleotides, amino acids, codons, codon tables etc.)
+</body>
+</html>
+
diff --git a/LibrarySource/pal/distance/AlignmentDistanceMatrix.java b/LibrarySource/pal/distance/AlignmentDistanceMatrix.java
new file mode 100644
index 0000000..c83cfd1
--- /dev/null
+++ b/LibrarySource/pal/distance/AlignmentDistanceMatrix.java
@@ -0,0 +1,109 @@
+// AlignmentDistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+// Known bugs and limitations:
+// - computational complexity of order O(numSeqs^2)
+
+
+package pal.distance;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import java.io.*;
+
+
+/**
+ * compute distance matrix (observed and ML) from alignment (SitePattern)
+ *
+ * @version $Id: AlignmentDistanceMatrix.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class AlignmentDistanceMatrix extends DistanceMatrix implements Serializable {
+	//
+	// Public stuff
+	//
+
+	/**
+	 * compute observed distances
+	 *
+	 * @param sp site pattern
+	 */
+	public AlignmentDistanceMatrix(SitePattern sp)
+	{
+		numSeqs = sp.getSequenceCount();
+		idGroup = sp;
+		distance = new double[numSeqs][numSeqs];
+		
+		pwd = new PairwiseDistance(sp);
+
+		computeDistances();
+	}
+
+	/**
+	 * compute maximum-likelihood distances
+	 *
+	 * @param sp site pattern
+	 * @param m  evolutionary model
+	 */
+	public AlignmentDistanceMatrix(SitePattern sp, SubstitutionModel m)
+	{
+		numSeqs = sp.getSequenceCount();
+		idGroup = sp;
+		distance = new double[numSeqs][numSeqs];
+				
+		pwd = new PairwiseDistance(sp, m);
+
+		computeDistances();
+	}
+
+	/**
+	 * recompute maximum-likelihood distances under new model
+	 *
+	 * @param m  evolutionary model
+	 */
+	public void recompute(SubstitutionModel m)
+	{
+		pwd.updateModel(m);
+
+		computeDistances();
+	}
+	
+	/**
+	 * recompute maximum-likelihood distances under new site pattern
+	 *
+	 * @param sp site pattern
+	 */
+	public void recompute(SitePattern sp)
+	{
+		pwd.updateSitePattern(sp);
+
+		computeDistances();
+	}
+
+	
+	//
+	// Private stuff
+	//
+	
+	private PairwiseDistance pwd;
+	
+	private void computeDistances()
+	{
+		for (int i = 0; i < numSeqs; i++)
+		{
+			distance[i][i] = 0;
+			for (int j = i + 1; j < numSeqs; j++)
+			{
+				distance[i][j] = pwd.getDistance(i, j);
+				distance[j][i] = distance[i][j];
+			}
+		} 		
+	}
+}
+
diff --git a/LibrarySource/pal/distance/DistanceMatrix.java b/LibrarySource/pal/distance/DistanceMatrix.java
new file mode 100644
index 0000000..e7e50a7
--- /dev/null
+++ b/LibrarySource/pal/distance/DistanceMatrix.java
@@ -0,0 +1,286 @@
+// DistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+
+/**
+ * storage for pairwise distance matrices.<p>
+ *
+ * features:
+ * - printing in in PHYLIP format,
+ * - computation of (weighted) squared distance to other distance matrix
+ * - Fills in all of array...	
+ *
+ * @version $Id: DistanceMatrix.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class DistanceMatrix implements Serializable, IdGroup
+{
+
+	/**
+	 * This class has a hard-coded serialVersionUID
+	 * all fields should be maintained under the same name
+	 * for backwards compatibility with serialized objects.
+	 */
+	static final long serialVersionUID = 4725925229860707633L;
+
+	//
+	// Public stuff
+	//
+
+	/** 
+	 * number of sequences. Should be replaced by method that 
+	 * looks directly at size of distance matrix.
+	 */
+	public int numSeqs = 0;
+
+	/** sequence identifiers */
+	public IdGroup idGroup;
+
+ 	/** distances [seq1][seq2] */
+ 	public double[][] distance = null;
+
+
+
+	/** constructor */
+	public DistanceMatrix()
+	{
+		format = FormattedOutput.getInstance();
+	}
+
+	/** constructor taking distances array and IdGroup */
+	public DistanceMatrix(double[][] distance, IdGroup idGroup)
+	{
+		super();
+
+		this.distance = distance;
+		this.idGroup = idGroup;
+		numSeqs = distance.length;
+		format = FormattedOutput.getInstance();
+	}
+
+	/** 
+	 * constructor that takes a distance matrix and clones the distances
+	 * but uses the same idGroup.
+	 */
+	public DistanceMatrix(DistanceMatrix dm) {
+		distance = new double[dm.getSize()][dm.getSize()];
+		for (int i = 0; i < dm.getSize(); i++) {
+			for (int j = 0; j < dm.getSize(); j++) {
+				distance[i][j] = dm.distance[i][j];
+			}
+		}
+		numSeqs = distance.length;
+		format = dm.format;
+		idGroup = dm.getIdGroup();
+	}
+
+	/**
+	 * constructor that takes a distance matrix and clones the distances,
+	 * of a the identifiers in idGroup.
+	 */
+	public DistanceMatrix(DistanceMatrix dm, IdGroup subset) {
+		
+		int index1, index2;
+		
+		distance = new double[subset.getIdCount()][subset.getIdCount()];
+		for (int i = 0; i < distance.length; i++) {
+			index1 = dm.whichIdNumber(subset.getIdentifier(i).getName());
+				
+			for (int j = 0; j < i; j++) {
+				index2 = dm.whichIdNumber(subset.getIdentifier(j).getName());	
+				distance[i][j] = dm.distance[index1][index2];
+				distance[j][i] = distance[i][j];
+			}
+		}
+		numSeqs = distance.length;
+		format = dm.format;
+		idGroup = subset;
+	}
+
+	/** print alignment (PHYLIP format) */
+	public void printPHYLIP(PrintWriter out)
+	{
+ 		// PHYLIP header line
+		out.println("  " + numSeqs);
+
+		for (int i = 0; i < numSeqs; i++)
+		{
+			format.displayLabel(out, 
+				idGroup.getIdentifier(i).getName(), 10);
+			out.print("      ");
+
+			for (int j = 0; j < numSeqs; j++)
+			{
+				// Chunks of 6 blocks each
+				if (j % 6 == 0 && j != 0)
+				{
+					out.println();
+					out.print("                ");
+				}
+
+				out.print("  ");
+				format.displayDecimal(out, distance[i][j], 5);
+			}
+			out.println();
+		}
+	}
+	
+	/** returns representation of this alignment as a string */
+	public String toString() {
+	
+		StringWriter sw = new StringWriter();
+		printPHYLIP(new PrintWriter(sw));
+		
+		return sw.toString();
+	}
+	
+	/** compute squared distance to second distance matrix */
+	public double squaredDistance(DistanceMatrix mat, boolean weighted)
+	{
+		double sum = 0;
+		for (int i = 0; i < numSeqs-1; i++)
+		{
+			for (int j = i+1; j < numSeqs; j++)
+			{
+				double diff = distance[i][j] - mat.distance[i][j];
+				double weight;
+				if (weighted)
+				{
+					// Fitch-Margoliash weight
+					// (variances proportional to distances)
+					weight = 1.0/(distance[i][j]*distance[i][j]);
+				}
+				else
+				{
+					// Cavalli-Sforza-Edwards weight
+					// (homogeneity of variances)
+					weight = 1.0;
+				}
+				sum += weight*diff*diff;
+			}
+		}
+		
+		return 2.0*sum; // we counted only half the matrix
+	}
+
+	/** compute absolute distance to second distance matrix */
+	public double absoluteDistance(DistanceMatrix mat)
+	{   
+		double sum = 0;
+		for (int i = 0; i < numSeqs-1; i++)
+		{
+			for (int j = i+1; j < numSeqs; j++)
+			{
+				double diff = 
+					Math.abs(distance[i][j] - mat.distance[i][j]);
+				
+				sum += diff;
+			}
+		}
+		
+		return 2.0*sum; // we counted only half the matrix
+	}
+
+	/**
+	 * Returns the number of rows and columns that the distance matrix has.
+	 */
+	public int getSize() {
+		return distance.length;
+	}
+
+	/**
+	 * Returns the distances as a 2-dimensional array of doubles.
+	 */
+	public double[][] getDistances() {
+		return distance;
+	}
+
+	/**
+	 * Sets both upper and lower triangles.
+	 */
+	public void setDistance(int i, int j, double dist) {
+		distance[i][j] = distance[j][i] = dist;
+	}
+
+	/**
+	 * Adds a delta to both upper and lower triangle distances.
+	 */
+	public void addDistance(int i, int j, double delta) {
+		distance[i][j] += delta;
+		distance[j][i] += delta;
+	}
+
+	/**
+	 * Returns the mean pairwise distance of this matrix
+	 */
+	public double meanDistance() {
+		double dist = 0.0;
+		int count = 0;
+		for (int i = 0; i < distance.length; i++) {
+			for (int j = 0; j < distance[i].length; j++) {
+				if (i != j) {
+					dist += distance[i][j];
+					count += 1;
+				}
+			}
+		}
+		return dist / (double)count;
+	}
+	
+	//IdGroup interface
+	public Identifier getIdentifier(int i) {return idGroup.getIdentifier(i);}
+	public void setIdentifier(int i, Identifier ident) { idGroup.setIdentifier(i, ident); }
+	public int getIdCount() { return idGroup.getIdCount(); }
+	public int whichIdNumber(String name) { return idGroup.whichIdNumber(name); }
+
+	/**
+	 * Return id group of this alignment. 
+	 * @deprecated distance matrix now implements IdGroup
+	 */
+	public IdGroup getIdGroup() { return idGroup; }
+
+
+	/**
+	 * test whether this matrix is a symmetric distance matrix
+	 *
+	 */
+	public boolean isSymmetric()
+	{
+		for (int i = 0; i < distance.length; i++)
+		{
+			if (distance[i][i] != 0) return false;
+		}
+		for (int i = 0; i < distance.length-1; i++)
+		{
+			for (int j = i+1; j < distance.length; j++)
+			{
+				if (distance[i][j] != distance[j][i]) return false;
+			}
+		}
+		return true;
+	}
+	
+
+	//
+	// Private stuff
+	//
+	
+	FormattedOutput format;
+}
+
diff --git a/LibrarySource/pal/distance/DistanceMatrixUtils.java b/LibrarySource/pal/distance/DistanceMatrixUtils.java
new file mode 100644
index 0000000..62208b0
--- /dev/null
+++ b/LibrarySource/pal/distance/DistanceMatrixUtils.java
@@ -0,0 +1,121 @@
+// DistanceMatrixUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.distance;
+
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * Auxillary functions for distance matrices<p> 
+ *
+ * @version $Id: DistanceMatrixUtils.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class DistanceMatrixUtils implements Serializable {
+		
+	/** 
+	 * compute squared distance to second distance matrix.
+	 * If both matrices have the same size it is assumed that the order of the taxa
+	 * is identical. 
+	 */
+	public static double squaredDistance(DistanceMatrix mat1, DistanceMatrix mat2, boolean weighted) {
+
+		boolean aliasNeeded = false;
+		if (mat1.getSize() != mat2.getSize())
+		{
+			aliasNeeded = true;
+		}
+		
+		int[] alias = null;
+		
+		if (aliasNeeded) {
+			if (mat1.getSize() > mat2.getSize()) {
+				//swap so mat1 is the smaller of the two
+				DistanceMatrix temp = mat2;
+				mat2 = mat1;
+				mat1 = temp;
+			}
+			alias = new int[mat1.getSize()];
+			for (int i = 0; i < alias.length; i++) {
+				alias[i] = mat2.whichIdNumber(mat1.getIdentifier(i).getName());
+			}
+		} else {
+			alias = new int[mat1.getSize()];
+			for (int i = 0; i < alias.length; i++) {
+				alias[i] = i;
+			}
+		}
+			
+		
+		double sum = 0;
+		int ai;
+		for (int i = 0; i < mat1.numSeqs-1; i++)
+		{
+			ai = alias[i];	
+		
+			for (int j = i+1; j < mat1.numSeqs; j++)
+			{
+				double diff = mat1.distance[i][j] - mat2.distance[ai][alias[j]];
+				double weight;
+				if (weighted)
+				{
+					// Fitch-Margoliash weight
+					// (variances proportional to distances)
+					weight = 1.0/(mat1.distance[i][j]*mat2.distance[ai][alias[j]]);
+				}
+				else
+				{
+					// Cavalli-Sforza-Edwards weight
+					// (homogeneity of variances)
+					weight = 1.0;
+				}
+				sum += weight*diff*diff;
+			}
+		}
+		
+		return 2.0*sum; // we counted only half the matrix
+	}
+
+	/**
+	 * Returns a distance matrix with the specified taxa removed.
+	 */
+	public static DistanceMatrix minus(DistanceMatrix parent, int taxaToRemove) {
+	
+		int size = parent.getIdCount() - 1;
+	
+		double[][] distances = new double[size][size];
+		Identifier[] ids = new Identifier[size];
+		int counti = 0, countj = 0;
+		for (int i = 0; i < size; i++) {
+			if (counti == taxaToRemove) {
+				counti += 1;
+			}
+			ids[i] = parent.getIdentifier(counti);
+		
+			countj = 0;
+			for (int j = 0; j < size; j++) {
+				if (countj == taxaToRemove) {
+					countj += 1;
+				}
+				distances[i][j] = parent.distance[counti][countj];
+				countj += 1;
+			}
+			counti += 1;
+		}
+	
+		DistanceMatrix smaller = new DistanceMatrix(distances, new SimpleIdGroup(ids));
+
+		return smaller;
+	}
+}
+
diff --git a/LibrarySource/pal/distance/DistanceParseException.java b/LibrarySource/pal/distance/DistanceParseException.java
new file mode 100644
index 0000000..5d4c87a
--- /dev/null
+++ b/LibrarySource/pal/distance/DistanceParseException.java
@@ -0,0 +1,26 @@
+// DistanceParseException.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+
+/**
+ * exception thrown by ReadDistanceMatrix
+ *
+ * @author Korbinian Strimmer
+ */
+public class DistanceParseException extends Exception
+{
+	public DistanceParseException() {}
+
+	public DistanceParseException(String msg)
+	{
+		super(msg);
+	}
+}
+
diff --git a/LibrarySource/pal/distance/JukesCantorDistanceMatrix.java b/LibrarySource/pal/distance/JukesCantorDistanceMatrix.java
new file mode 100644
index 0000000..ba602b3
--- /dev/null
+++ b/LibrarySource/pal/distance/JukesCantorDistanceMatrix.java
@@ -0,0 +1,130 @@
+// JukesCantorDistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import pal.misc.*;
+
+
+/**
+ * compute jukes-cantor corrected distance matrix
+ *
+ * @version $Id: JukesCantorDistanceMatrix.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class JukesCantorDistanceMatrix extends DistanceMatrix
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * compute jukes-cantor corrected distances
+	 * (assumes nucleotides as underlying data)
+	 *
+	 * @param dist distance matrix
+	 */
+	public JukesCantorDistanceMatrix(DistanceMatrix dist)
+	{
+		this(dist, 4);
+	}
+
+
+	/**
+	 * compute jukes-cantor corrected distances
+	 *
+	 * @param dist distance matrix
+	 * @param numStates number of states of underlying data
+	 */
+	public JukesCantorDistanceMatrix(DistanceMatrix dist, int numStates)
+	{
+		numSeqs = dist.numSeqs;
+		idGroup = dist.getIdGroup();
+		distance = new double[numSeqs][numSeqs];
+		
+		obsDistance = dist.distance;
+		
+		double n = numStates;
+
+		const1 = (n-1)/n;
+		const2 = n/(n-1);
+
+		computeDistances();
+	}
+
+
+	/**
+	 * compute jukes-cantor corrected distances
+	 *
+	 * @param alignment Alignment
+	 */
+	public JukesCantorDistanceMatrix(Alignment alignment)
+	{
+		this(new SitePattern(alignment));
+	}
+
+	/**
+	 * compute jukes-cantor corrected distances
+	 *
+	 * @param sitePattern SitePattern
+	 */
+	public JukesCantorDistanceMatrix(SitePattern sitePattern)
+	{
+		this(	new AlignmentDistanceMatrix(sitePattern),
+			sitePattern.getDataType().getNumStates());
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private double[][] obsDistance;
+
+	//used in correction formula
+	private double const1, const2;
+	
+	private void computeDistances()
+	{
+		for (int i = 0; i < numSeqs-1; i++)
+		{
+			distance[i][i] = 0.0;
+			for (int j = i+1; j < numSeqs; j++)
+			{
+				distance[i][j] = distance[j][i] = jccorrection(obsDistance[i][j]);
+			}
+		}
+	}
+
+    
+	private double jccorrection(double obsdist)
+	{
+		if (obsdist == 0.0) return 0.0;
+	
+		if (obsdist >= const1)
+		{
+			return BranchLimits.MAXARC;
+		} 
+        
+		double expDist = -const1 * Math.log(1.0 - (const2 * obsdist));
+
+		if (expDist < BranchLimits.MAXARC)
+		{
+			return expDist;
+		}
+		else
+		{
+			return BranchLimits.MAXARC;
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/distance/PairwiseDistance.java b/LibrarySource/pal/distance/PairwiseDistance.java
new file mode 100644
index 0000000..a252d9c
--- /dev/null
+++ b/LibrarySource/pal/distance/PairwiseDistance.java
@@ -0,0 +1,213 @@
+// PairwiseDistance.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import pal.misc.*;
+import pal.math.*;
+
+
+/**
+ * determines the (observed and ML) distance between a pair of sequences
+ *
+ * @version $Id: PairwiseDistance.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class PairwiseDistance
+{
+	//
+	// Public stuff
+	//
+	
+	/** last estimated distance */
+	public double distance;
+	
+	/** last estimate standard error of a distance */
+	public double distanceSE;
+	
+	
+	/**
+	 * Constructor 1 (estimate observed distances only)
+	 *
+	 * @param sp site pattern
+	 */
+	public PairwiseDistance(SitePattern sp)
+	{
+		updateSitePattern(sp);
+	}
+
+	/**
+	 * Constructor 2 (uses evolutionary model)
+	 *
+	 * @param sp site pattern
+	 * @param m evolutionary model
+	 */
+	public PairwiseDistance(SitePattern sp, SubstitutionModel m)
+	{
+		this(sp);
+		
+		modelBased = true;
+		of = new SequencePairLikelihood(sp, m);
+		um = new UnivariateMinimum();
+	}
+
+	/**
+	 * update model of substitution
+	 *
+	 * @param model of substitution
+	 */
+	public void updateModel(SubstitutionModel m)
+	{
+		of.updateModel(m);
+	}
+
+	/**
+	 * update site pattern
+	 *
+	 * @param site pattern
+	 */
+	public void updateSitePattern(SitePattern sp)
+	{
+		sitePattern = sp;
+		numSites = sp.getSiteCount();
+		numPatterns = sp.numPatterns;
+		numStates = sp.getDataType().getNumStates();
+		weight = sp.weight;
+		
+		jcratio = ((double) numStates-1.0)/(double) numStates;		
+	
+		if (modelBased) of.updateSitePattern(sp);
+	}
+
+	/**
+	 * compute distance between two sequences in the given alignment
+	 * 
+	 * @param s1 number of first sequence
+	 * @param s2 number of second sequence
+	 *
+	 * @return estimated distance (observed or ML, depending on constructor used)
+	 */
+	public double getDistance(int s1, int s2)
+	{
+		return getDistance(sitePattern.pattern[s1], sitePattern.pattern[s2]);
+	}
+	
+	/**
+	 * compute distance between two sequences (not necessarly
+	 * in the given alignment but with the same weights in the site pattern)
+	 * 
+	 * @param s1 site pattern of first sequence
+	 * @param s2 site pattern of second sequence
+	 *
+	 * @return estimated distance (observed or ML, depending on constructor used)
+	 */
+	public double getDistance(byte[] s1, byte[] s2)
+	{	
+		double dist = getObservedDistance(s1, s2);
+		
+		if (modelBased && dist != 0.0)
+		{
+			// Apply generalized JC correction if possible
+			double start = 1.0 - dist/jcratio;
+			if (start > 0.0)
+			{
+				start = -jcratio*Math.log(start);	
+			}
+			else
+			{
+				start = dist;
+			}
+				
+			// Determine ML distance
+			of.setSequences(s1, s2);
+			if (start > BranchLimits.MAXARC || start < BranchLimits.MINARC)
+			{
+				// Don�t use start value
+				dist = um.findMinimum(of, BranchLimits.FRACDIGITS);
+			}
+			else
+			{
+				// Use start value
+				dist = um.findMinimum(start, of, BranchLimits.FRACDIGITS);
+			}
+		}		
+		
+		if (modelBased)
+		{
+			double f2x = um.f2minx;
+
+			if (1.0/(BranchLimits.MAXARC*BranchLimits.MAXARC) < f2x)
+			{
+				distanceSE = Math.sqrt(1.0/f2x);
+			}
+			else
+			{
+				distanceSE = BranchLimits.MAXARC;
+			}
+		}
+		else
+		{
+			distanceSE = 0.0;
+		}
+		
+		distance = dist;
+		
+		return dist;
+	}
+
+
+	//
+	// Private stuff
+	//
+
+	private int numSites;
+	private int numPatterns;
+	private int numStates;	
+	private int[] weight;
+	private double jcratio;
+	private boolean modelBased;	
+	private SitePattern sitePattern;
+	private UnivariateMinimum um;
+	private SequencePairLikelihood of;
+
+	private boolean isDifferent(int s1, int s2)
+	{
+ 		// ? is considered identical to anything
+		if (s1 == numStates || s2 == numStates)
+		{
+			return false;
+		}
+		
+		// Check for identity
+		if (s1 == s2)
+		{
+			return false;
+		}
+
+		// The remaining pairs are all different
+		return true;		
+	}
+	
+	private double getObservedDistance(byte[] seqPat1, byte[] seqPat2)
+	{
+		int diff = 0;
+		for (int i = 0; i < numPatterns; i++)
+		{
+			if (isDifferent(seqPat1[i], seqPat2[i]))
+			{
+				diff += weight[i];
+			}
+		}
+
+		return (double) diff/(double) numSites;
+	}
+}
+
diff --git a/LibrarySource/pal/distance/ReadDistanceMatrix.java b/LibrarySource/pal/distance/ReadDistanceMatrix.java
new file mode 100644
index 0000000..9877724
--- /dev/null
+++ b/LibrarySource/pal/distance/ReadDistanceMatrix.java
@@ -0,0 +1,88 @@
+// ReadDistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * reads pairwise distance matrices in PHYLIP format
+ *  (full matrix)
+ *
+ * @version $Id: ReadDistanceMatrix.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class ReadDistanceMatrix extends DistanceMatrix
+{
+	//
+	// Public stuff
+	//
+
+	/** read from stream */
+	public ReadDistanceMatrix(PushbackReader input)
+		throws DistanceParseException
+	{
+		readSquare(input);
+	}
+
+	/** read from file */
+	public ReadDistanceMatrix(String file)
+		throws DistanceParseException, IOException
+	{
+		PushbackReader input = InputSource.openFile(file);
+		readSquare(input);
+		input.close();
+	}
+
+
+	//
+	// Private stuff
+	//
+
+	// Read square matrix
+	private void readSquare(PushbackReader in)
+		throws DistanceParseException
+	{
+		FormattedInput fi = FormattedInput.getInstance();
+		
+		try
+		{
+			// Parse PHYLIP header line
+			numSeqs = fi.readInt(in);
+			fi.nextLine(in);
+
+			// Read distance and sequence names
+			distance = new double[numSeqs][numSeqs];
+ 			idGroup = new SimpleIdGroup(numSeqs);
+			for (int i = 0; i < numSeqs; i++)
+			{
+				idGroup.setIdentifier(i, new Identifier(fi.readLabel(in, 10)));				
+				for (int j = 0; j < numSeqs; j++)
+				{
+					distance[i][j] = fi.readDouble(in);
+				}
+				fi.nextLine(in);
+			}
+		}
+			catch (IOException e)
+			{
+				throw new DistanceParseException("IO error");
+			}
+			catch (NumberFormatException e)
+			{
+				throw new DistanceParseException("Number format error");
+			}
+	}
+}
+
diff --git a/LibrarySource/pal/distance/SUPGMADistanceMatrix.java b/LibrarySource/pal/distance/SUPGMADistanceMatrix.java
new file mode 100644
index 0000000..f136228
--- /dev/null
+++ b/LibrarySource/pal/distance/SUPGMADistanceMatrix.java
@@ -0,0 +1,48 @@
+// SUPGMADistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.misc.*;
+
+/**
+ * Corrects distances in a distance matrix such that all tips appear
+ * contemporaneous, given a time/date and rate information for the 
+ * taxa.
+ *
+ * @version $Id: SUPGMADistanceMatrix.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class SUPGMADistanceMatrix extends DistanceMatrix {
+    
+
+	/**
+	 * Uses date/time information and a constant rate to correct distance matrices.
+	 */
+	public SUPGMADistanceMatrix(DistanceMatrix raw, TimeOrderCharacterData tocd, double rate) {
+	
+		super(raw);
+	
+		double[] tips = new double[tocd.getIdGroup().getIdCount()];
+		for (int i = 0; i < tips.length; i++) {
+			if (tocd.hasTimes()) {
+				tips[i] = rate * tocd.getTime(i);
+			} else {
+				tips[i] = 0.0;
+			}
+	
+			for (int j = 0; j < tips.length; j++) {
+				if (i != j) {
+					addDistance(i, j, tips[i]);
+				}
+			}
+		}		
+	}
+}
+
diff --git a/LibrarySource/pal/distance/SequencePairLikelihood.java b/LibrarySource/pal/distance/SequencePairLikelihood.java
new file mode 100644
index 0000000..9741e4a
--- /dev/null
+++ b/LibrarySource/pal/distance/SequencePairLikelihood.java
@@ -0,0 +1,168 @@
+// SequencePairLikelihood.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.distance;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import pal.misc.*;
+import pal.math.*;
+
+
+/**
+ * computation of the (negative) log-likelihood for a pair of sequences
+ *
+ * @version $Id: SequencePairLikelihood.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class SequencePairLikelihood implements UnivariateFunction
+{
+	/**
+	 * initialisation
+	 *
+	 * @param sp site pattern
+	 * @param m model of substitution
+	 */
+	public SequencePairLikelihood(SitePattern sp, SubstitutionModel m)
+	{
+		updateSitePattern(sp);		
+		updateModel(m);
+	}
+	
+	/**
+	 * update model of substitution
+	 *
+	 * @param model of substitution
+	 */
+	public void updateModel(SubstitutionModel m)
+	{
+		model = m;
+		numRates = model.rateDistribution.numRates;
+		rateProb = model.rateDistribution.probability;
+		rateMatrix = model.rateMatrix;
+	}
+
+	/**
+	 * update site pattern 
+	 *
+	 * @param site pattern
+	 */
+	public void updateSitePattern(SitePattern sp)
+	{
+		sitePattern = sp;
+		
+		numPatterns = sp.numPatterns;
+		numSites = sp.getSiteCount();
+		numStates = sp.getDataType().getNumStates();
+		weight = sp.weight;
+	}
+
+	
+	/**
+	 * specification of two sequences in the given alignment
+	 * 
+	 * @param s1 number of first sequence
+	 * @param s2 number of second sequence
+	 */
+	public void setSequences(int s1, int s2)
+	{
+		setSequences(sitePattern.pattern[s1], sitePattern.pattern[s2]);
+	}
+
+	/**
+	 * specification of two sequences (not necessarily in the given
+	 * alignment but with the same weights in the site pattern)
+	 * 
+	 * @param s1 site pattern of first sequence
+	 * @param s2 site pattern of second sequence
+	 */
+	public void setSequences(byte[] s1, byte[] s2)
+	{
+		seqPat1 = s1;
+		seqPat2 = s2;
+	}
+	
+	/**
+	 * compute (negative) log-likelihood for a given distance
+	 * between the two sequences
+	 *
+	 * @param arc expected distance
+	 *
+	 * @return negative log-likelihood
+	 */
+	public double evaluate(double arc)
+	{
+		model.setDistance(arc);
+		
+		double loglkl = 0;
+		for (int i = 0; i < numPatterns; i++)
+		{
+			double sumprob = 0;
+			for (int r = 0; r < numRates; r++)
+			{
+				sumprob += rateProb[r]*probConfig(r, seqPat1[i], seqPat2[i]);
+			}
+			loglkl += weight[i]*Math.log(sumprob);
+		}
+		
+		return -loglkl;
+	}
+	
+	public double getLowerBound()
+	{
+		return BranchLimits.MINARC;
+	}
+	
+	public double getUpperBound()
+	{
+		return BranchLimits.MAXARC;
+	}
+		
+	
+	//
+	// Private stuff
+	//
+	
+	private SubstitutionModel model;
+	private RateMatrix rateMatrix;
+	private SitePattern sitePattern;	
+	private int numPatterns;
+	private int numSites;
+	private int numStates;
+	private int numRates;
+	private int[] weight;
+	private double[] rateProb;
+	private byte[] seqPat1;
+	private byte[] seqPat2;
+	
+	private double probConfig(int r, int i, int j)
+	{
+		double p;
+		
+		if (i == numStates && j == numStates)
+		{
+			p = 1.0;
+		}
+		else if (i == numStates)
+		{
+			p = rateMatrix.getEqulibriumFrequency(j);
+		}
+		else if (j == numStates)
+		{
+			p = rateMatrix.getEqulibriumFrequency(i);
+		}
+		else
+		{
+			p = rateMatrix.getEqulibriumFrequency(i)*model.transProb(r, i, j);
+		}
+		
+		return p;
+	}	
+}
+
diff --git a/LibrarySource/pal/distance/makefile b/LibrarySource/pal/distance/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/distance/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/distance/package.html b/LibrarySource/pal/distance/package.html
new file mode 100644
index 0000000..0f05a80
--- /dev/null
+++ b/LibrarySource/pal/distance/package.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+Classes for reading and generating distance matrices, including computation
+of pairwise distances for sequence data (maximum-likelihood and observed
+distances). 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/eval/ChiSquareValue.java b/LibrarySource/pal/eval/ChiSquareValue.java
new file mode 100644
index 0000000..6b231e6
--- /dev/null
+++ b/LibrarySource/pal/eval/ChiSquareValue.java
@@ -0,0 +1,196 @@
+// ChiSquareValue.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.eval;
+
+import pal.distance.*;
+import pal.math.*;
+import pal.misc.*;
+import pal.tree.*;
+
+
+/**
+ * computes chi-square value of a (parameterized) tree for
+ * its set of parameters (e.g., branch lengths)
+ * and a given distance matrix
+ *
+ * @version $Id: ChiSquareValue.java,v 1.12 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ChiSquareValue implements MultivariateFunction
+{
+	//
+	// Public stuff
+	//
+		
+	/**
+	 * initialization
+	 *
+	 * @param m distance matrix
+	 * @param w determines whether weighted or 
+	 *        unweighted chi-squares are computed
+	 */
+	public ChiSquareValue(DistanceMatrix m, boolean w)
+	{
+		givenMat = m;
+		weighted = w;
+	}
+	
+	
+	/**
+	 * define (parameterized) tree
+	 *
+	 * @param t tree
+	 */
+	public void setTree(Tree t)
+	{
+		tree = t;
+
+		//changed so that smaller trees could be easily handled
+		//for tree-search purposes
+		inducedMat = new TreeDistanceMatrix(tree);
+		
+		if (tree instanceof ParameterizedTree)
+		{
+			ptree = (ParameterizedTree) tree;
+			numParams = ptree.getNumParameters();
+		}
+		else
+		{
+			ptree = null;
+			numParams = 0;
+		}
+	}
+
+
+	/**
+	 * Returns the (parameterized) tree of this likelihood value.
+	 */
+	public Tree getTree()
+	{
+		return tree;
+	}
+
+
+	/**
+	 * compute (weighted) least-square value
+	 * for current tree (fixed branch lengths)
+	 *
+	 * return chi-square value
+	 */
+	public double compute()
+	{		
+		inducedMat.computeDistances();
+			
+		return DistanceMatrixUtils.squaredDistance(inducedMat, 
+			givenMat, weighted);
+	}
+
+	/**
+	 * optimise parameters of a tree by minimising its chi-square value
+	 * (tree must be a ParameterizedTree)
+	 *
+	 * @return minimimum chi-square value 
+	 */
+	public double optimiseParameters()
+	{
+		return optimiseParameters(null);
+	}
+
+
+	/**
+	 * optimise parameters of a tree by minimising its chi-square value
+	 * (tree must be a ParameterizedTree)
+	 *
+	 * @param mm optimiser for ParameterizedTree
+	 *
+	 * @return minimum chi-square value 
+	 */
+	public double optimiseParameters(MultivariateMinimum mm)
+	{
+		if (!(tree instanceof ParameterizedTree))
+		{
+			// we need a ParameterizedTree here!
+			new IllegalArgumentException("ParameterizedTree required");
+		}
+
+		if (mm == null)
+		{
+			if (mvm == null) mvm = new DifferentialEvolution(numParams);
+		}
+		else
+		{
+			mvm = mm;
+		}
+		
+		// first guess are the default parameters of the tree
+		double[] estimate = new double[numParams];
+		for (int i = 0; i < numParams; i++)
+		{
+			estimate[i] = ptree.getDefaultValue(i);
+		}
+		
+		mvm.findMinimum(this, estimate, BranchLimits.FRACDIGITS, BranchLimits.FRACDIGITS);
+										
+		return evaluate(estimate);
+	}
+
+
+	
+	// interface MultivariateFunction
+	
+	/**
+	 * compute (weighted) least-squares value
+	 *
+	 * @param params parameters (branch lengths) of the tree
+	 */
+	public double evaluate(double[] params)
+	{
+		for (int i = 0; i < numParams; i++)
+		{
+			ptree.setParameter(params[i], i);
+		}
+		
+		return compute();
+	}
+	
+	/**
+	 * get number of parameters in tree
+	 *
+	 * @return number of parameters
+	 */
+	public int getNumArguments()
+	{
+		return ptree.getNumParameters();
+	}
+	
+	public double getLowerBound(int n)
+	{
+		return ptree.getLowerLimit(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return ptree.getUpperLimit(n);
+	}
+
+	
+	//
+	// Private stuff
+	//
+
+	private int numParams;
+	private Tree tree;
+	private ParameterizedTree ptree;
+	private DistanceMatrix givenMat;
+	private TreeDistanceMatrix inducedMat;
+	private boolean weighted;
+	private MultivariateMinimum mvm = null;
+}
+
diff --git a/LibrarySource/pal/eval/DemographicLikelihoodValue.java b/LibrarySource/pal/eval/DemographicLikelihoodValue.java
new file mode 100644
index 0000000..06903d2
--- /dev/null
+++ b/LibrarySource/pal/eval/DemographicLikelihoodValue.java
@@ -0,0 +1,58 @@
+// DemographicLikelihoodValue.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+// - partial likelihoods need a lot of memory storage
+//   memory usage could be opimized by working in a single site
+
+
+package pal.eval;
+
+import pal.coalescent.*;
+import pal.alignment.*;
+
+/**
+ * Estimates the likelihood for a tree using a specified
+ * model of sequence evolution and a sequence alignment and
+ * a specific demographic model as a prior on coalescent intervals.
+ *
+ * <em>Must be used in conjunction with DemographicClockTree! </em>
+ *
+ * @version $Id: DemographicLikelihoodValue.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class DemographicLikelihoodValue extends LikelihoodValue
+{
+	//
+	// Public stuff
+	//	
+
+	/**
+	 * Parameter taking a site pattern.
+	 */
+	public DemographicLikelihoodValue(SitePattern sp) {
+		super(sp);
+	}
+
+
+	/**
+	 * compute log-likelihood
+	 * for current branch lengths and model
+	 *
+	 * return negative log-likelihood
+	 */
+	public double compute()
+	{		
+		super.compute();
+
+		logL += ((DemographicTree)tree).computeDemoLogLikelihood();
+
+		return -logL;
+	}
+}
+
+
diff --git a/LibrarySource/pal/eval/DemographicValue.java b/LibrarySource/pal/eval/DemographicValue.java
new file mode 100644
index 0000000..5c4b0a8
--- /dev/null
+++ b/LibrarySource/pal/eval/DemographicValue.java
@@ -0,0 +1,178 @@
+// DemographicValue.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.eval;
+
+import pal.coalescent.*;
+import pal.tree.*;
+import pal.math.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * estimates demographic parameters by maximising the coalescent
+ * prior for a tree with given branch lengths.
+ *
+ * @version $Id: DemographicValue.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @authro Korbinian Strimmer
+ */
+public class DemographicValue implements MultivariateFunction
+{
+	//
+	// Public stuff
+	//
+
+	/** Log-Likelihood */
+	public double logL;
+
+	/**
+	 * define model
+	 *
+	 * @param m model of demographic
+	 */
+	public void setDemographicModel(DemographicModel m)
+	{
+		model = m;
+		numParams = model.getNumParameters();
+		
+		
+		// likelihood functions contains many local optima
+		mvm = new DifferentialEvolution(numParams, 20*numParams);
+		//mvm = new ConjugateGradientSearch();
+	}
+
+	/**
+	 * Returns the demographic model of this likelihood value
+	 */
+	public DemographicModel getDemographicModel() {
+		return model;
+	}
+	
+	/**
+	 * Returns the coalescent tree of this likelihood value.
+	 */
+	public CoalescentIntervals getCoalescentIntervals() {
+		return intervals;
+	}
+
+	/**
+	 * define coalescent tree.
+	 *
+	 * @param t tree
+	 */
+	public void setCoalescentIntervals(CoalescentIntervals ci)
+	{
+		intervals = ci;
+	}
+
+	/**
+	 * compute log-likelihood
+	 * for current model
+	 *
+	 * return negative log-likelihood
+	 */
+	public double compute()
+	{		
+		computeLogLikelihood();
+
+		return -logL;
+	}
+
+	/**
+	 * optimize log-likelihood
+	 * using default optimizer
+	 *
+	 * return minimum negative log-likelihood
+	 */
+	public double optimize()
+	{
+		return optimize(mvm);
+	}
+
+	/**
+	 * optimize log-likelihood value and compute corresponding SEs
+	 * given an optimizer
+	 *
+	 * @return minimimum negative log-likelihood value 
+	 */
+	public double optimize(MultivariateMinimum givenMvm)
+	{		
+		double[] estimate = new double[numParams];
+			
+		for (int i = 0; i < numParams; i++)
+		{
+			estimate[i] = model.getParameter(i);
+		}
+			
+		givenMvm.findMinimum(this, estimate,
+			BranchLimits.FRACDIGITS, BranchLimits.FRACDIGITS);
+					
+			
+		// Corresponding SEs
+		double[] estimateSE = new double[numParams];
+		estimateSE = NumericalDerivative.diagonalHessian(this, estimate);
+		for (int i = 0; i < numParams; i++)
+		{
+			estimateSE[i] = Math.sqrt(Math.abs(1.0/estimateSE[i]));
+			model.setParameterSE(estimateSE[i], i);
+		}
+		evaluate(estimate);
+		
+		model.setLogL(logL);
+						
+		return -logL;
+	}
+	
+	// interface MultivariateFunction
+
+	public double evaluate(double[] params)
+	{
+		// set tree parameters
+		for (int i = 0; i < numParams; i++)
+		{
+			model.setParameter(params[i], i);
+		}
+
+		return compute();
+	}
+	
+	public int getNumArguments()
+	{
+	 	return numParams;
+	}
+	
+	public double getLowerBound(int n)
+	{
+		return model.getLowerLimit(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return model.getUpperLimit(n);
+	}
+
+	//
+	// Private stuff
+	//
+
+	private int numParams;
+	protected CoalescentIntervals intervals;
+	protected DemographicModel model;
+	private MultivariateMinimum mvm;
+
+	// Calculate likelihood of model given intervals
+	
+	protected void computeLogLikelihood() {		
+		logL = intervals.computeLogLikelihood(model);
+	}
+}
+
+
diff --git a/LibrarySource/pal/eval/LikelihoodValue.java b/LibrarySource/pal/eval/LikelihoodValue.java
new file mode 100644
index 0000000..6407eec
--- /dev/null
+++ b/LibrarySource/pal/eval/LikelihoodValue.java
@@ -0,0 +1,1358 @@
+// LikelihoodValue.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.eval;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import pal.tree.*;
+import pal.distance.*;
+import pal.math.*;
+import pal.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * Computes the likelihood for a tree given a
+ * model of sequence evolution and a sequence alignment;
+ * also optimises tree parameters such as branch lengths
+ * by maximising the likelihood (for optimal performance
+ * special optimisation procedures are
+ * employed for UnconstrainedTree, ClockTree and DatedTipsClockTree;
+ * a general optimisation precedure is used for another
+ * ParameterizedTree). 
+ *
+ * @version $Id: LikelihoodValue.java,v 1.32 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class LikelihoodValue
+{
+	//
+	// Public stuff
+	//
+
+	/** Log-Likelihood */
+	public double logL;
+	
+	/** log-likelihood for each site pattern */
+	public double[] siteLogL;
+	
+	/** map estimation of rate at site pattern */
+	public int[] rateAtSite;
+
+
+	/**
+	 * initialization
+	 *
+	 * @param sp site pattern
+	 */
+	public LikelihoodValue(SitePattern sp)
+	{	
+		sitePattern = sp;
+		
+		numPatterns = sp.numPatterns;
+		siteLogL = new double[numPatterns];
+		rateAtSite = new int[numPatterns];
+	}
+
+	/**
+	 * Returns the site pattern of this likelihood value
+	 */
+	public SitePattern getSitePattern() {
+		return sitePattern;
+	}
+
+
+	/**
+	 * Set new site pattern (while keeping tree and model)
+	 */
+	public void renewSitePattern(SitePattern sp)
+	{
+		sitePattern = sp;
+		
+		numPatterns = sp.numPatterns;
+		siteLogL = new double[numPatterns];
+		rateAtSite = new int[numPatterns];
+
+		setModel(getModel());
+		setTree(getTree());
+	}
+	 
+
+	/**
+	 * define model
+	 * (a site pattern must have been set before calling this method)
+	 *
+	 * @param m model of substitution (rate matrix + rate distribution)
+	 */
+	public void setModel(SubstitutionModel m)
+	{
+		model = m;
+			
+		frequency = model.rateMatrix.getEqulibriumFrequencies();
+		rprob = model.rateDistribution.probability;
+		numStates = model.dimension;
+		numRates = model.numRates;
+				
+		int maxNodes = 2*sitePattern.getSequenceCount()-2;
+		
+		allocatePartialMemory(maxNodes);
+	}
+
+	/**
+	 * Returns the model of this likelihood value.
+	 */
+	public SubstitutionModel getModel() {
+		return model;
+	}
+
+
+	/**
+	 * define (parameterized) tree
+	 *,(must only be called only after a site pattern has been defined).
+	 *
+	 * @param t tree
+	 */
+	public void setTree(Tree t)
+	{
+		tree = t;
+		
+		// Assign sequences to leaves
+		int[] alias = 
+		    TreeUtils.mapExternalIdentifiers(sitePattern, tree);
+		
+		for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		{
+			tree.getExternalNode(i).setSequence(sitePattern.pattern[alias[i]]);	
+		}
+		
+		if (tree instanceof ParameterizedTree)
+		{
+			ptree = (ParameterizedTree) tree;
+			numParams = ptree.getNumParameters();
+		}
+		else
+		{
+			ptree = null;
+			numParams = 0;
+		}
+	}
+
+	/**
+	 * Returns the (potentially parameterized) tree of this likelihood value.
+	 */
+	public Tree getTree()
+	{
+		return tree;
+	}
+
+	
+	/**
+	 * compute log-likelihood for current tree (fixed branch lengths and model)
+	 *
+	 * return log-likelihood
+	 */
+	public double compute()
+	{		
+		treeLikelihood();
+
+		return logL;
+	}
+
+
+	/**
+	 * optimise parameters of tree by maximising its likelihood
+	 * (this assumes that tree is a ParameterizedTree)
+	 *
+	 * @return minimimum log-likelihood value 
+	 */
+	public double optimiseParameters()
+	{
+		return optimiseParameters(null);
+	}
+
+
+	/**
+	 * optimise parameters of tree by maximising its likelihood
+	 * (this assumes that tree is a ParameterizedTree)
+	 *
+	 * @param mm optimiser for generic ParameterisedTree
+	 *
+	 * @return minimimum log-likelihood value 
+	 */
+	public double optimiseParameters(MultivariateMinimum mm)
+	{		
+		if (!(tree instanceof ParameterizedTree))
+		{
+			// we need a ParameterizedTree here!
+			new IllegalArgumentException("ParameterizedTree required");
+		}
+
+		double[] estimate = new double[numParams];
+
+		// we need these in any case
+		if (um == null) um = new UnivariateMinimum();
+		if (tl == null) tl = new TreeLikelihood(this);
+		
+		if (bl == null) bl = new BranchLikelihood(this);
+		else bl.update();
+	
+		if (tree instanceof UnconstrainedTree)
+		{
+			optimiseUnconstrainedTree(true);
+		}
+		else if (tree instanceof ClockTree)
+		{
+			if (nl == null) nl = new NodeLikelihood(this);
+			else nl.update();
+			
+			int ns;			
+			do
+			{
+				optimiseClockTree(false);
+							
+				ns = collapseShortInternalBranches();
+				
+				// make consistent
+				((ClockTree) ptree).update();
+								
+				numParams = numParams - ns;
+			}
+			while (ns != 0);
+			
+			numParams += restoreShortInternalBranches();
+			
+			// make consistent
+			((ClockTree) ptree).update();
+		}
+		else if (tree instanceof DatedTipsClockTree)
+		{
+			if (nl == null) nl = new NodeLikelihood(this);
+			else nl.update();
+			if (rl == null) rl = new RateLikelihood(this);
+			else rl.update();
+						
+			int ns;			
+			do
+			{
+				optimiseClockTree(true);
+			
+				ns = collapseShortInternalBranches();
+				
+				// make consistent
+				((DatedTipsClockTree) ptree).update();
+				
+				numParams = numParams - ns;
+			}
+			while (ns != 0);
+			
+			numParams += restoreShortInternalBranches();
+			
+			// make consistent
+			((DatedTipsClockTree) ptree).update();
+		}
+		else
+		{
+			for (int i = 0; i < numParams; i++)
+			{
+				estimate[i] = ptree.getParameter(i);
+			}
+
+			if (mm == null)
+			{
+				if (mvm == null) mvm = new DifferentialEvolution(numParams);
+			}
+			else
+			{
+				mvm = mm;
+			}
+			mvm.findMinimum(tl, estimate, BranchLimits.FRACDIGITS,
+				BranchLimits.FRACDIGITS);
+		}
+	
+		// compute estimates for SEs of branch lengths
+		optimiseUnconstrainedTree(false);
+		
+		for (int i = 0; i < numParams; i++)
+		{
+			estimate[i] = ptree.getParameter(i);
+		}
+				
+		return -tl.evaluate(estimate);
+	}
+
+	
+	//
+	// Friendly stuff
+	//
+
+	int numStates;
+	int numRates;
+	int numPatterns;
+	double[] frequency;
+	double[] rprob;
+	SitePattern sitePattern;
+	int numParams;
+	Tree tree;
+	ParameterizedTree ptree;
+
+	/** get partial likelihood of a branch */
+	double[][][] getPartial(Node branch)
+	{
+		return partials[getKey(branch)];
+	}
+	
+	/** get next branch around a center node
+	   (center may be root, but root is never returned) */
+	Node getNextBranch(Node branch, Node center)
+	{		
+		Node b = getNextBranchOrRoot(branch, center);
+		
+		if (b.isRoot())
+		{
+			b = b.getChild(0);
+		}
+		
+		return b;
+	}
+		
+	/** multiply partials into the neighbour of branch */
+	void productPartials(Node branch, Node center)
+	{		
+		int numBranches = getBranchCount(center);
+		
+		Node nextBranch = getNextBranch(branch, center);
+		double[][][] partial = getPartial(nextBranch);
+		
+		for (int i = 0; i < numBranches-2; i++)
+		{
+			nextBranch = getNextBranch(nextBranch, center);
+			double[][][] partial2 = getPartial(nextBranch);
+			
+			for (int l = 0; l < numPatterns; l++)
+			{
+				for (int r = 0; r < numRates; r++)
+				{
+					double[] p = partial[l][r];
+					double[] p2 = partial2[l][r];
+
+					for (int d = 0; d < numStates; d++)
+					{ 
+						p[d] *= p2[d];
+					}
+						
+				}
+			}
+		}
+	}	
+	
+
+	/** compute partials for branch around center node
+	    (it is assumed that multiplied partials are available in
+	    the neighbor branch) */
+	void partialsInternal(Node branch, Node center)
+	{
+		double[][][] partial = getPartial(branch);
+		double[][][] multPartial = getPartial(getNextBranch(branch, center));
+		
+		model.setDistance(branch.getBranchLength());
+		for (int l = 0; l < numPatterns; l++)
+		{
+			for (int r = 0; r < numRates; r++)
+			{
+				double[] p = partial[l][r];
+				double[] mp = multPartial[l][r];
+				
+				for (int d = 0; d < numStates; d++)
+				{
+					double sum = 0;
+					for (int j = 0; j < numStates; j++)
+					{
+						sum += model.transProb(r, d, j)*mp[j];
+					}
+					p[d] = sum;
+				}
+			}
+		}		
+	}
+
+	/** compute partials for external branch */
+	void partialsExternal(Node branch)
+	{
+		double[][][] partial = getPartial(branch);
+		byte[] seq = branch.getSequence();
+		
+		model.setDistance(branch.getBranchLength());
+		
+		for (int l = 0; l < numPatterns; l++)
+		{
+			for (int r = 0; r < numRates; r++)
+			{
+				double[] p = partial[l][r];
+				int sl = seq[l];
+				
+				if (sl == numStates)
+				{
+					for (int d = 0; d < numStates; d++)
+					{ 
+						p[d] = 1;	
+					}		
+				}
+				else
+				{
+					for (int d = 0; d < numStates; d++)
+					{ 
+						p[d] = model.transProb(r, d, sl);	
+					}		
+				}				
+			}
+		}
+	}
+
+
+
+	//
+	// Private stuff
+	//
+
+	// max. number of iterations in ml optimization
+	private int MAXROUNDS = 1000;
+	
+	private SubstitutionModel model;
+	private AlignmentDistanceMatrix distMat;
+	private double[][][][] partials;
+	private boolean down;
+	private Node currentBranch;
+	private UnivariateMinimum um;
+	private MultivariateMinimum mvm;
+	private BranchLikelihood bl;
+	private TreeLikelihood tl;
+	private NodeLikelihood nl;
+	private RateLikelihood rl;
+		
+	private void allocatePartialMemory(int numNodes) {
+
+		// I love the profiler!
+		// This 'if' statement sped my MCMC algorithm up by nearly 300%
+		// Never underestimate the time it takes to allocate and de-allocate memory!
+		// AD 
+		if (
+			(partials == null) || 
+			(numNodes != partials.length) ||
+			(numPatterns != partials[0].length) ||
+			(numRates != partials[0][0].length) ||
+			(numStates != partials[0][0][0].length)) {
+				
+			partials = new double[numNodes][numPatterns][numRates][numStates];
+		}
+	}
+
+	/** get next branch around a center node
+	   (center may be root, and root may also be returned) */
+	private Node getNextBranchOrRoot(Node branch, Node center)
+	{		
+		int numChilds = center.getChildCount();
+		
+		int num;
+		for (num = 0; num < numChilds; num++)
+		{
+			if (center.getChild(num) == branch)
+			{
+				break;
+			}
+		}
+		
+		// num is now child number (if num = numChilds then branch == center)
+		
+		// next node
+		num++;
+		
+		if (num > numChilds)
+		{
+			num = 0;
+		}
+		
+		if (num == numChilds)
+		{
+			return center;
+		}
+		else
+		{
+			return center.getChild(num);
+		}
+	}
+
+	private int getKey(Node node)
+	{
+		int key;
+		if (node.isLeaf())
+		{
+			key = node.getNumber();
+		}
+		else
+		{
+			key = node.getNumber() + tree.getExternalNodeCount();
+		}
+		
+		return key;		
+	}
+	
+	/** returns number of branches centered around an internal node */
+	private int getBranchCount(Node center)
+	{
+		if (center.isRoot())
+		{
+			return center.getChildCount();
+		}
+		else
+		{
+			return center.getChildCount()+1;
+		}
+	}
+	
+	private void traverseTree()
+	{
+		if ((!currentBranch.isLeaf() && down) || currentBranch.isRoot()) 
+		{
+			currentBranch = currentBranch.getChild(0);
+			down = true;
+		}
+		else
+		{
+			Node center = currentBranch.getParent();
+			currentBranch = getNextBranchOrRoot(currentBranch, center);
+			
+			if (currentBranch == center)
+			{
+				down = false;
+			}
+			else
+			{
+				down = true;
+			}
+		}
+	}
+	
+	/** init partial likelihoods */
+	private void initPartials()
+	{
+		currentBranch = tree.getRoot();
+		down = true;
+		
+		Node firstBranch = currentBranch;
+				
+		do
+		{	
+			if (currentBranch.isRoot())
+			{
+				//do nothing
+			}
+			else
+			if (currentBranch.isLeaf())
+			{
+				partialsExternal(currentBranch);
+			}
+			else if (!down)
+			{
+				productPartials(currentBranch, currentBranch);
+				partialsInternal(currentBranch, currentBranch);
+			}
+			
+			traverseTree();
+		}
+		while (currentBranch != firstBranch);
+	}
+
+	/** calculate likelihood of any tree and infer MAP estimates of rates at a site */
+	private void treeLikelihood()
+	{
+		initPartials();
+		
+		Node center = tree.getRoot();
+				
+		Node firstBranch = center.getChild(0);
+		Node lastBranch = center.getChild(center.getChildCount()-1);
+		
+		double[][][] partial1 = getPartial(firstBranch);
+		double[][][] partial2 = getPartial(lastBranch);
+
+		productPartials(lastBranch, center);
+
+		logL = 0;
+		for (int l = 0; l < numPatterns; l++)
+		{
+			int bestR = 0;
+			double maxSum = 0;
+			
+			double rsum = 0.0;
+			for (int r = 0; r < numRates; r++)
+			{
+				double[] p1 = partial1[l][r];
+				double[] p2 = partial2[l][r];
+				
+				double sum = 0.0;
+				for (int d = 0; d < numStates; d++)
+				{ 
+					sum += frequency[d]*p1[d]*p2[d];
+				}
+				sum *= rprob[r];
+				
+				// find rate category that contributes the most
+				if (r == 0)
+				{
+					bestR = 0;
+					maxSum = sum;
+				}
+				else
+				{
+					if (sum > maxSum)
+					{
+						bestR = r;
+						maxSum = sum;
+					}
+				}
+				
+				rsum += sum;	
+			}
+			
+			siteLogL[l] = Math.log(rsum);
+			rateAtSite[l] =  bestR;
+			logL += siteLogL[l]*sitePattern.weight[l];
+		}
+		
+	}
+
+	/** optimise branch lengths and find SEs (UnconstrainedTree) */
+	private void optimiseUnconstrainedTree(boolean optimise)
+	{
+		int numBranches = tree.getInternalNodeCount() + tree.getExternalNodeCount()-1;
+		
+		initPartials();		
+				
+		Node firstBranch = currentBranch;
+		double len, lenOld, lenDiff;
+		int nconv = 0;
+		
+		int numRounds = 0;
+		
+		double lenSE;
+		double INVARC = 1.0/(BranchLimits.MAXARC*BranchLimits.MAXARC);
+		do
+		{
+			if (currentBranch.isRoot())
+			{
+				// do nothing
+			}	
+			else if (currentBranch.isLeaf())
+			{
+				productPartials(currentBranch, currentBranch.getParent());
+				bl.setBranch(currentBranch);
+				lenOld = currentBranch.getBranchLength();
+				
+				//optimise
+				if (optimise)
+				{
+					len = um.findMinimum(lenOld, bl, BranchLimits.FRACDIGITS);
+					currentBranch.setBranchLength(len);
+				}
+				else
+				{
+					// find corresponding SE
+					len = lenOld;
+					lenSE = NumericalDerivative.secondDerivative(bl, lenOld);
+					if (INVARC < lenSE)
+						lenSE = Math.sqrt(1.0/lenSE);
+					else
+						lenSE = BranchLimits.MAXARC;
+					currentBranch.setBranchLengthSE(lenSE);
+				}
+								
+				// check progress				
+				lenDiff = Math.abs(len-lenOld);
+				if (lenDiff < BranchLimits.ABSTOL) nconv++;
+				else nconv = 0;
+				
+				if (nconv >= numBranches || numRounds == MAXROUNDS)
+				{
+					bl.evaluate(len);
+					break;
+				}				
+				
+				// update partials
+				partialsExternal(currentBranch);
+			}
+			else if (down)
+			{
+				productPartials(currentBranch, currentBranch.getParent());
+				partialsInternal(currentBranch, currentBranch.getParent());				
+			}
+			else // !down
+			{
+				productPartials(currentBranch, currentBranch);
+				bl.setBranch(currentBranch);
+				lenOld = currentBranch.getBranchLength();
+				
+				//optimise
+				if (optimise)
+				{
+					len = um.findMinimum(lenOld, bl, BranchLimits.FRACDIGITS);
+					currentBranch.setBranchLength(len);
+				}
+				else
+				{
+					// find corresponding SE
+					len = lenOld;
+					lenSE = NumericalDerivative.secondDerivative(bl, lenOld);
+					if (INVARC < lenSE)
+						lenSE = Math.sqrt(1.0/lenSE);
+					else
+						lenSE = BranchLimits.MAXARC;
+					currentBranch.setBranchLengthSE(lenSE);
+				}
+				
+				// check progress
+				lenDiff = Math.abs(len-lenOld);
+				if (lenDiff < BranchLimits.ABSTOL) nconv++;
+				else nconv = 0;
+				
+				if (nconv >= numBranches || numRounds == MAXROUNDS)
+				{
+					bl.evaluate(len);
+					break;
+				}
+				
+				// update branch length and partials
+				partialsInternal(currentBranch, currentBranch);
+			}
+			
+			traverseTree();
+			
+			if (currentBranch == firstBranch) numRounds++;
+		}
+		while (true);
+	}
+	
+	private Vector shortBranches = null;
+
+	/** collapse internal branches that are close to zero */
+	private int collapseShortInternalBranches()
+	{
+		// minus 1 because root node has no own branch
+		int numInternalBranches = tree.getInternalNodeCount()-1;
+		int numShortBranches = 0;
+		for (int i = 0; i < numInternalBranches; i++)
+		{
+			Node b = tree.getInternalNode(i);
+			if (b.getBranchLength() <= 2*BranchLimits.MINARC)
+			{
+				numShortBranches++;
+				
+				NodeUtils.removeBranch(b);
+				
+				if (shortBranches == null) shortBranches = new Vector();
+				
+				shortBranches.addElement(b);	
+			}
+		}
+		
+		//numParams = numParams - numShortBranches;
+		tree.createNodeList();
+		
+		return numShortBranches;
+	}
+	
+	/** restore internal branches */
+	private int restoreShortInternalBranches()
+	{
+		int size = 0;
+		
+		if (shortBranches != null)
+		{
+			size = shortBranches.size();
+			for (int i = size-1; i >= 0; i--)
+			{
+				Node node = (Node) shortBranches.elementAt(i);
+				NodeUtils.restoreBranch(node);
+				node.setBranchLength(BranchLimits.MINARC);
+				node.setNodeHeight(node.getParent().getNodeHeight()-BranchLimits.MINARC);
+				shortBranches.removeElementAt(i);
+			}
+		}
+		
+		//numParams = numParams+size;
+		tree.createNodeList();
+		
+		return size;
+	}
+
+	
+	/** optimise branch lengths (ClockTree) */
+	private void optimiseClockTree(boolean datedTips)
+	{
+		int numNodes = tree.getInternalNodeCount();
+		
+		double MAXHEIGHT = numNodes*BranchLimits.MAXARC;
+				
+		initPartials();		
+				
+		Node firstBranch = currentBranch;
+		double h, hOld, hDiff, hMin, hMax, hSE;
+		int nconv = 0;
+		
+		int numRounds = 0;
+		
+		double INVMAX = 1.0/(MAXHEIGHT*MAXHEIGHT);
+		do
+		{
+			if (currentBranch.isRoot())
+			{
+				if (datedTips && numRounds > 0)
+				{
+					// in the first round we did not adjust the rate
+					// so we assume that the likelihood has not converged
+					if (numRounds == 1) nconv = 0;
+					//nconv = 0;
+					
+					double oldLogL = logL;
+					
+					// optimise rate
+					DatedTipsClockTree dtree = (DatedTipsClockTree) ptree;
+					double rOld = dtree.getRate();
+					double maxR = dtree.getMaxRate();
+					double r = um.findMinimum(rOld, rl);
+					rl.evaluate(r);	
+					
+					// find corresponding SE	
+					double rSE = um.f2minx;
+					if (1 < rSE)
+						rSE = Math.sqrt(1.0/rSE);
+					else
+						rSE = 1;
+					dtree.setRateSE(rSE);
+					
+					// check progress				
+					/*double logLDiff = Math.abs(logL-oldLogL);
+					if (logLDiff > 0.001)
+					{
+						// reset 
+						nconv = 0;
+					}*/
+				}
+						
+				// min-max heights
+				hMin = NodeUtils.findLargestChild(currentBranch)+BranchLimits.MINARC;
+				hMax = MAXHEIGHT-BranchLimits.MINARC;
+				
+				//optimise
+				nl.setBranch(currentBranch, hMin, hMax);
+				hOld = currentBranch.getNodeHeight();
+				h = um.findMinimum(hOld, nl, BranchLimits.FRACDIGITS);
+				nl.evaluate(h);
+								
+				// find corresponding SE	
+				hSE = um.f2minx;
+				if (INVMAX < hSE)
+					hSE = Math.sqrt(1.0/hSE);
+				else
+					hSE = MAXHEIGHT;
+				currentBranch.setNodeHeightSE(hSE);
+				
+				// check progress				
+				hDiff = Math.abs(h-hOld);
+				if (hDiff < BranchLimits.ABSTOL) nconv++;
+				else nconv = 0;
+				
+				if (nconv >= numNodes || numRounds == MAXROUNDS)
+				{
+					break;
+				}
+			}	
+			else if (currentBranch.isLeaf())
+			{
+				productPartials(currentBranch, currentBranch.getParent());
+				partialsExternal(currentBranch);
+			}
+			else if (down)
+			{
+				productPartials(currentBranch, currentBranch.getParent());
+				
+				// min-max heights
+				hMin = NodeUtils.findLargestChild(currentBranch)+BranchLimits.MINARC;
+				hMax = currentBranch.getParent().getNodeHeight()-BranchLimits.MINARC;
+				
+				//optimise
+				nl.setBranch(currentBranch, hMin, hMax);
+				hOld = currentBranch.getNodeHeight();
+				h = um.findMinimum(hOld, nl, BranchLimits.FRACDIGITS);
+				nl.evaluate(h);
+								
+				// find corresponding SE	
+				hSE = um.f2minx;
+				if (INVMAX < hSE)
+					hSE = Math.sqrt(1.0/hSE);
+				else
+					hSE = MAXHEIGHT;
+				currentBranch.setNodeHeightSE(hSE);
+				
+				// check progress				
+				hDiff = Math.abs(h-hOld);
+				if (hDiff < BranchLimits.ABSTOL) nconv++;
+				else nconv = 0;
+				
+				if (nconv >= numNodes || numRounds == MAXROUNDS)
+				{
+					break;
+				}				
+				
+				partialsInternal(currentBranch, currentBranch.getParent());				
+			}
+			else // !down
+			{
+				productPartials(currentBranch, currentBranch);
+				partialsInternal(currentBranch, currentBranch);
+			}
+			
+			traverseTree();
+			
+			if (currentBranch == firstBranch) numRounds++;
+		}
+		while (true);
+	}
+}
+
+class RateLikelihood implements UnivariateFunction
+{
+	public RateLikelihood(LikelihoodValue lv)
+	{
+		this.lv = lv;
+		update();
+	}
+	
+	public void update()
+	{
+		dtree = (DatedTipsClockTree) lv.ptree;
+	}
+	
+	public double evaluate(double param)
+	{
+		// set rate parameters
+		dtree.setRate(param);
+
+		return -lv.compute();
+	}
+		
+	public double getLowerBound()
+	{
+		return 0;
+	}
+
+	public double getUpperBound()
+	{
+		return dtree.getMaxRate();
+	}
+	
+	// private stuff
+	private LikelihoodValue lv;
+	private DatedTipsClockTree dtree;
+}
+
+class TreeLikelihood implements MultivariateFunction
+{
+
+
+
+	public TreeLikelihood(LikelihoodValue lv)
+	{
+		this.lv = lv;
+	}
+
+	public double evaluate(double[] params)
+	{
+		// set tree parameters
+		for (int i = 0; i < lv.numParams; i++)
+		{
+			lv.ptree.setParameter(params[i], i);
+		}
+
+		return -lv.compute();
+	}
+
+	public int getNumArguments()
+	{
+		return lv.numParams;
+	}
+
+	public double getLowerBound(int n)
+	{
+		return lv.ptree.getLowerLimit(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return lv.ptree.getUpperLimit(n);
+	}
+
+	// private stuff
+	private LikelihoodValue lv;
+}
+
+class ModelLikelihood implements MultivariateFunction
+{
+
+	public ModelLikelihood(LikelihoodValue lv)
+	{
+		this.lv = lv;
+		this.model_ = lv.getModel();
+	}
+
+	public double evaluate(double[] params)
+	{
+		// set tree parameters
+		for (int i = 0; i < lv.numParams; i++)
+		{
+			model_.setParameter(params[i], i);
+		}
+
+		return -lv.compute();
+	}
+
+	public int getNumArguments()
+	{
+		return model_.getNumParameters();
+	}
+
+	public double getLowerBound(int n)
+	{
+		return model_.getLowerLimit(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return model_.getUpperLimit(n);
+	}
+
+	// private stuff
+	private LikelihoodValue lv;
+	private SubstitutionModel model_; //Cached results
+}
+
+/** Basically for cobmining model and tree likelihood optimising functions */
+class CombinedLikelihood implements MultivariateFunction {
+	public CombinedLikelihood(MultivariateFunction f1, MultivariateFunction f2, LikelihoodValue lv) {
+		this.f1_ = f1;
+		this.f2_ = f2;
+		this.f1Params_ = new double[f1.getNumArguments()];
+		this.f2Params_ = new double[f2.getNumArguments()];
+	}
+	public double evaluate(double[] params)	{
+		for(int i = 0 ; i < f1Params_.length ; i++) {
+			f1Params_[i] = params[i];
+		}
+		for(int i = 0 ; i < f2Params_.length ; i++) {
+			f2Params_[i] = params[i-f1Params_.length];
+		}
+		return -lv.compute();
+	}
+
+	public int getNumArguments() {
+		return f1Params_.length+f2Params_.length;
+	}
+
+	public double getLowerBound(int n) {
+		if(n<f1Params_.length) {
+			f1_.getLowerBound(n);
+		}
+		return f2_.getLowerBound(n-f1Params_.length);
+	}
+
+	public double getUpperBound(int n) {
+		if(n<f1Params_.length) {
+			f1_.getUpperBound(n);
+		}
+		return f2_.getUpperBound(n-f1Params_.length);
+	}
+
+	private double[] f1Params_;
+	private double[] f2Params_;
+
+	private LikelihoodValue lv;
+	private MultivariateFunction f1_, f2_; //Cached results
+}
+
+
+class BranchLikelihood implements UnivariateFunction
+{
+	public BranchLikelihood(LikelihoodValue lv)
+	{
+		this.lv = lv;
+		update();
+	}
+	
+	public void update()
+	{
+		model = lv.getModel();
+		
+		numPatterns = lv.numPatterns;
+		numRates = lv.numRates;
+		numStates = lv.numStates;
+		frequency = lv.frequency;
+		rprob = lv.rprob;
+		
+		sitePattern = lv.sitePattern;	
+	}
+	
+	public void setBranch(Node branch)
+	{
+		if (branch.isRoot())
+		{
+			throw new IllegalArgumentException();
+		}
+		else if (branch.isLeaf())
+		{
+			Node multNode = lv.getNextBranch(branch, branch.getParent());
+			multPartial = lv.getPartial(multNode);
+			seq = branch.getSequence();
+		}
+		else
+		{
+			Node multNode1 = lv.getNextBranch(branch, branch.getParent());
+			multPartial1 = lv.getPartial(multNode1);
+		
+			Node multNode2 = lv.getNextBranch(branch, branch);
+			multPartial2 = lv.getPartial(multNode2);		
+		}
+		this.branch = branch;
+	}
+
+	public double evaluate(double arc)
+	{
+		model.setDistance(arc);
+		
+		lv.logL = 0;
+		for (int l = 0; l < numPatterns; l++)
+		{
+			double rsum = 0.0;
+			for (int r = 0; r < numRates; r++)
+			{
+				double sum = 0;
+				
+				if (branch.isLeaf())
+				{
+					double[] mp = multPartial[l][r];
+					int sl = seq[l];
+				
+					if (sl == numStates)
+					{
+						for (int d = 0; d < numStates; d++)
+						{ 
+							sum += frequency[d]*mp[d];
+						}
+					}
+					else
+					{
+						for (int d = 0; d < numStates; d++)
+						{ 
+							sum += frequency[d]*mp[d]*model.transProb(r, d, sl);	
+						}
+					}		
+				}
+				else
+				{
+					double[] mp1 = multPartial1[l][r];
+					double[] mp2 = multPartial2[l][r];
+				
+					for (int i = 0; i < numStates; i++)
+					{ 
+						double sum2 = 0.0;
+						for (int j = 0; j < numStates; j++)
+						{ 
+							sum2 += mp2[j]*model.transProb(r, i, j);
+						}
+						sum += frequency[i]*mp1[i]*sum2;
+					}		
+				}
+		
+				
+				sum *= rprob[r];
+				rsum += sum;
+			}
+			
+			lv.siteLogL[l] = Math.log(rsum);
+			lv.logL += lv.siteLogL[l]*sitePattern.weight[l];
+		}
+	
+		return -lv.logL;
+	}
+	
+	public double getLowerBound()
+	{
+		return BranchLimits.MINARC;
+	}
+	
+	public double getUpperBound()
+	{
+		return BranchLimits.MAXARC;
+	}
+	
+	// private
+	
+	private LikelihoodValue lv;
+	private double[][][] multPartial, multPartial1, multPartial2;
+	private byte[] seq;
+	private int numStates;
+	private int numRates;
+	private int numPatterns;
+	private double[] frequency;
+	private double[] rprob;
+	private SitePattern sitePattern;
+	private SubstitutionModel model;
+	private Node branch;
+}
+
+class NodeLikelihood implements UnivariateFunction
+{
+	public NodeLikelihood(LikelihoodValue lv)
+	{
+		this.lv = lv;
+		update();
+	}
+	
+	public void update()
+	{
+		model = lv.getModel();
+		
+		numPatterns = lv.numPatterns;
+		numRates = lv.numRates;
+		numStates = lv.numStates;
+		frequency = lv.frequency;
+		rprob = lv.rprob;
+		
+		sitePattern = lv.sitePattern;	
+	}
+	
+	public void setBranch(Node branch, double min, double max)
+	{
+		center = branch;
+		
+		if (center.isLeaf())
+		{
+			throw new IllegalArgumentException();
+		}
+		else if (center.isRoot())
+		{
+			firstBranch = center.getChild(0);
+			lastBranch = center.getChild(center.getChildCount()-1);
+		
+			partial1 = lv.getPartial(firstBranch);
+			partial2 = lv.getPartial(lastBranch);
+		}
+		else
+		{
+			partial1 = lv.getPartial(center);
+			partial2 = lv.getPartial(lv.getNextBranch(center, center.getParent()));
+		}
+		
+		minHeight = min;
+		maxHeight = max;
+	}
+
+	public double evaluate(double h)
+	{
+		center.setNodeHeight(h);
+								
+		// branch lengths to child
+		for (int i = 0; i < center.getChildCount(); i++)
+		{
+			Node child = center.getChild(i);
+			child.setBranchLength(h-child.getNodeHeight());
+		}
+		
+		// update partials of childs
+		for (int i = 0; i < center.getChildCount(); i++)
+		{
+			Node child = center.getChild(i);
+			if (child.isLeaf())
+			{
+				lv.partialsExternal(child);
+			}
+			else
+			{
+				lv.partialsInternal(child, child);
+			}
+		}
+
+		if (center.isRoot())
+		{
+			lv.productPartials(lastBranch, center);
+		}
+		else
+		{
+			// multiply child partials
+			lv.productPartials(center, center);
+			
+			center.setBranchLength(maxHeight-h);
+			
+			lv.partialsInternal(center, center);
+		}
+		
+		lv.logL = 0;
+		for (int l = 0; l < numPatterns; l++)
+		{
+			double rsum = 0.0;
+			for (int r = 0; r < numRates; r++)
+			{
+				double[] p1 = partial1[l][r];
+				double[] p2 = partial2[l][r];
+				
+				double sum = 0.0;
+				for (int d = 0; d < numStates; d++)
+				{ 
+					sum += frequency[d]*p1[d]*p2[d];
+				}
+				sum *= rprob[r];
+				rsum += sum;	
+			}
+			
+			lv.siteLogL[l] = Math.log(rsum);
+			lv.logL += lv.siteLogL[l]*sitePattern.weight[l];
+		}
+	
+		return -lv.logL;
+	}
+	
+	public double getLowerBound()
+	{
+		return minHeight;
+	}
+	
+	public double getUpperBound()
+	{
+		return maxHeight;
+	}
+	
+	// private
+	
+	private LikelihoodValue lv;
+	private double[][][] partial1;
+	private double[][][] partial2;
+	private byte[] seq;
+	private int numStates;
+	private int numRates;
+	private int numPatterns;
+	private double[] frequency;
+	private double[] rprob;
+	private SitePattern sitePattern;
+	private SubstitutionModel model;
+	private double minHeight, maxHeight;
+	private Node center, firstBranch, lastBranch;
+}
+
diff --git a/LibrarySource/pal/eval/ModelParameters.java b/LibrarySource/pal/eval/ModelParameters.java
new file mode 100644
index 0000000..ca13fab
--- /dev/null
+++ b/LibrarySource/pal/eval/ModelParameters.java
@@ -0,0 +1,236 @@
+// ModelParameters.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.eval;
+
+import pal.alignment.*;
+import pal.substmodel.*;
+import pal.tree.*;
+import pal.distance.*;
+import pal.math.*;
+import pal.misc.*;
+
+import java.io.*;
+
+/**
+ * estimates substitution model parameters from the data
+ *
+ * @version $Id: ModelParameters.java,v 1.7 2001/07/13 14:39:13 korbinian Exp $
+ * @author Korbinian Strimmer
+ */
+public class ModelParameters implements MultivariateFunction
+{
+	//
+	// public stuff
+	//
+	
+	/** fractional digits desired for parameters */
+	public final static int FRACDIGITS = 3;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param sp site pattern
+	 * @param m substitution model
+	 */
+	public ModelParameters(SitePattern sp, SubstitutionModel m)
+	{
+		sitePattern = sp;
+		model = m;
+		numParams = model.getNumParameters();
+		
+		lv = new LikelihoodValue(sitePattern);
+		lv.setModel(model);
+
+		if (numParams == 1)
+		{
+			mvm = new OrthogonalSearch();
+		}
+		else
+		{
+			mvm = new ConjugateGradientSearch();
+			//((ConjugateGradientSearch) mvm).prin = 2;
+		}
+	}
+	
+	/**
+	 * estimate (approximate) values for the model parameters
+	 * from the data using a neighbor-joining tree
+	 *
+	 * @return parameter estimates
+	 */
+	public double[] estimate()
+	{			
+		double[] p = new double[numParams];			
+		for (int i = 0; i < numParams; i++)
+		{
+			p[i] = model.getDefaultValue(i);
+		}
+		double fp;
+		
+		AlignmentDistanceMatrix distMat = null;
+		double tolfp = Math.pow(10, -1-FRACDIGITS);
+		double tolp = Math.pow(10, -1-FRACDIGITS);
+		boolean first = true;
+		do
+		{
+			if (first)
+			{		
+				distMat = new AlignmentDistanceMatrix(sitePattern, model);;
+			}
+			else
+			{
+				distMat.recompute(model);
+			}
+			
+			NeighborJoiningTree t = new NeighborJoiningTree(distMat);
+			ParameterizedTree pt = new UnconstrainedTree(t);
+						
+			//ChiSquareValue cs = new ChiSquareValue(distMat, true);		
+			//cs.setTree(pt);
+			//cs.optimiseParameters();
+
+			lv.setTree(pt);
+			
+			if (first)
+			{
+				fp = evaluate(p);
+				mvm.stopCondition(fp, p, tolfp, tolp, true);
+				first = false;
+			}
+			
+			mvm.optimize(this, p, tolfp, tolp);
+		
+			fp = evaluate(p);			
+		}
+		while (!mvm.stopCondition(fp, p, tolfp, tolp, false));
+				
+		// trim p
+		double m = Math.pow(10, FRACDIGITS);
+		for (int i = 0;  i < p.length; i++)
+		{
+			p[i] = Math.round(p[i]*m)/m;
+		}
+		
+		fp = evaluate(p);
+		
+		// Corresponding SEs
+		double[] pSE = new double[numParams];
+		pSE = NumericalDerivative.diagonalHessian(this, p);
+		for (int i = 0; i < numParams; i++)
+		{
+			pSE[i] = Math.sqrt(1.0/pSE[i]);
+			model.setParameterSE(pSE[i], i);
+		}
+		return p;
+	}
+
+	/**
+	 * estimate (approximate) values for the model parameters
+	 * from the data using a given (parameterized) tree
+	 * @return parameter estimates
+	 */		
+	public double[] estimateFromTree(ParameterizedTree t)
+	{			
+		// there is a horrible amount of code duplication
+		// here - should be cleaned up at some time
+		
+		
+		double[] p = new double[numParams];			
+		for (int i = 0; i < numParams; i++)
+		{
+			p[i] = model.getDefaultValue(i);
+		}
+		double fp;
+		
+		double tolfp = Math.pow(10, -1-FRACDIGITS);
+		double tolp = Math.pow(10, -1-FRACDIGITS);
+		boolean first = true;
+		do
+		{
+			lv.setTree(t);
+			
+			if (first)
+			{
+				fp = evaluate(p);
+				mvm.stopCondition(fp, p, tolfp, tolp, true);
+				first = false;
+			}
+			
+			mvm.optimize(this, p, tolfp, tolp);
+		
+			fp = evaluate(p);			
+		}
+		while (!mvm.stopCondition(fp, p, tolfp, tolp, false));
+				
+		// trim p
+		double m = Math.pow(10, FRACDIGITS);
+		for (int i = 0;  i < p.length; i++)
+		{
+			p[i] = Math.round(p[i]*m)/m;
+		}
+		
+		fp = evaluate(p);
+		
+		// Corresponding SEs
+		double[] pSE = new double[numParams];
+		pSE = NumericalDerivative.diagonalHessian(this, p);
+		for (int i = 0; i < numParams; i++)
+		{
+			pSE[i] = Math.sqrt(1.0/pSE[i]);
+			model.setParameterSE(pSE[i], i);
+		}
+		return p;
+	}
+
+
+	
+	// interface MultivariateFunction
+
+	public double evaluate(double[] params)
+	{
+		// set model parameters
+		for (int i = 0; i < numParams; i++)
+		{
+			model.setParameter(params[i], i);
+		}
+
+		double r = -lv.compute();
+		//double r = -lv.optimiseParameters();
+
+		return r;
+	}
+	
+	public int getNumArguments()
+	{
+	 	return numParams;
+	}
+	
+	public double getLowerBound(int n)
+	{
+		return model.getLowerLimit(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return model.getUpperLimit(n);
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private int numParams;
+	private SubstitutionModel model;
+	private SitePattern sitePattern;
+	private ParameterizedTree tree;
+	private LikelihoodValue lv;
+	private MultivariateMinimum mvm;
+}
+
diff --git a/LibrarySource/pal/eval/makefile b/LibrarySource/pal/eval/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/eval/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/eval/package.html b/LibrarySource/pal/eval/package.html
new file mode 100644
index 0000000..cfc3903
--- /dev/null
+++ b/LibrarySource/pal/eval/package.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+Classes for evaluating evolutionary hypothesis (chi-square and likelihood
+criteria) and estimating model parameters. 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/gui/CircularGraphics.java b/LibrarySource/pal/gui/CircularGraphics.java
new file mode 100644
index 0000000..80a3337
--- /dev/null
+++ b/LibrarySource/pal/gui/CircularGraphics.java
@@ -0,0 +1,213 @@
+// CircularGraphics.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import headless.awt.*;
+
+/**
+		@author Matthew Goode
+*/
+
+public class CircularGraphics {
+
+	double worldRadius_, worldAngle_;
+	public int screenCentreX;
+	public int screenCentreY;
+	public int screenRadius;
+
+	final static double TWO_PI = 2*Math.PI;
+
+	Graphics g_;
+	FontMetrics fm_;
+	Font font_;
+	boolean invertY_;
+
+	public CircularGraphics(Graphics g, double worldAngle, double worldRadius, int screenX, int screenY, int screenWidth, int screenHeight) {
+		this(g,worldAngle,worldRadius,screenX, screenY, screenWidth, screenHeight,false);
+	}
+	public CircularGraphics(Graphics g, double worldAngle, double worldRadius, int screenX, int screenY, int screenWidth, int screenHeight, boolean invertY) {
+		this.g_ = g;
+		this.invertY_ = invertY;
+		this.worldAngle_ = worldAngle;
+		this.worldRadius_ = worldRadius;
+		screenRadius = Math.min(screenWidth/2, screenHeight/2);
+		screenCentreX = screenX+screenWidth/2;
+		screenCentreY = screenY+screenHeight/2;
+
+		font_ = g_.getFont();
+		if(font_!=null) {
+			fm_ = g_.getFontMetrics(font_);
+		}
+	}
+
+	public void setFont(Font newFont) {
+		g_.setFont(newFont);
+		this.font_ = newFont;
+		fm_ = g_.getFontMetrics(font_);
+	}
+
+	/** For drawing arbitary lines */
+	public void drawLine( double angle1, double radius1, double angle2, double radius2) {
+		g_.drawLine(getScreenX(angle1,radius1), getScreenY(angle1, radius1), getScreenX(angle2,radius2),getScreenY(angle2,radius2) );
+	}
+
+	/** For drawing arbitary lines */
+	public void drawLine( double angle, double radiusStart, double radiusEnd) {
+		g_.drawLine(getScreenX(angle,radiusStart), getScreenY(angle, radiusStart), getScreenX(angle,radiusEnd),getScreenY(angle,radiusEnd) );
+	}
+
+	/** For drawing arbitary lines */
+	public void drawLineDegreeAlign( double angle, double radiusStart, double radiusEnd) {
+		angle = ((int)(angle*360/worldAngle_))*worldAngle_/360;
+		g_.drawLine(getScreenX(angle,radiusStart), getScreenY(angle, radiusStart), getScreenX(angle,radiusEnd),getScreenY(angle,radiusEnd) );
+	}
+	private final double convertRadius(double radius) {
+		//return radius;
+		return worldRadius_ - radius;
+	}
+
+	/** For drawing arbitary lines */
+	public void drawArc( double angleStart, double angleEnd, double radius) {
+		int actualRadius = (int)(screenRadius*convertRadius(radius)/worldRadius_);
+		if(actualRadius<1) {
+			return;
+		}
+		int startAngle, endAngle;
+//		if(invertY_) {
+			startAngle = (int)(angleStart*360/worldAngle_);
+			endAngle = (int)(angleEnd*360/worldAngle_);
+//		} else {
+//			startAngle = (int)(angleStart*360/worldAngle_);
+//			endAngle = (int)(angleEnd*360/worldAngle_);
+//		}
+//		if(invertY_) {
+//			g_.drawArc(screenCentreX-actualRadius,  screenCentreY+actualRadius, actualRadius*2,-actualRadius*2, startAngle, endAngle-startAngle );
+//		} else {
+			g_.drawArc(screenCentreX-actualRadius,  screenCentreY-actualRadius, actualRadius*2,actualRadius*2, startAngle, endAngle-startAngle );
+			/*System.out.println(""+(screenCentreX-actualRadius)+ "   "+
+												( screenCentreY-actualRadius)+ "   " +
+												( actualRadius*2) + "    " +
+												( actualRadius*2 ) + "   " +
+												( startAngle ) + "    " +
+												( endAngle-startAngle ));
+        */
+//		}
+	}
+
+	public void setColor(Color c) {
+		g_.setColor(c);
+	}
+
+
+	public void drawString(String s, double angle, double radius) {
+		int sX =getScreenX(angle,radius);
+		int sY = getScreenY(angle,radius);
+		FontMetrics fm = g_.getFontMetrics(g_.getFont());
+		int stringWidth = fm.stringWidth(s);
+		int stringHeight = fm.getHeight();
+
+		g_.drawString(s,sX-stringWidth/2,sY+stringHeight/2);
+
+
+	}
+	public void drawString(String s, double angle, double radius,int outdent) {
+		int sX =getScreenX(angle,radius,outdent);
+		int sY = getScreenY(angle,radius,outdent);
+		FontMetrics fm = g_.getFontMetrics(g_.getFont());
+		int stringWidth = fm.stringWidth(s);
+		int stringHeight = fm.getHeight();
+
+		g_.drawString(s,sX-stringWidth/2,sY+stringHeight/2);
+	}
+
+	public void circleString(String s, double angle, double radius,int outdent) {
+		int sX =getScreenX(angle,radius,outdent);
+		int sY = getScreenY(angle,radius,outdent);
+		FontMetrics fm = g_.getFontMetrics(g_.getFont());
+		int stringWidth = fm.stringWidth(s);
+		int stringHeight = fm.getHeight();
+
+		g_.drawString(s,sX-stringWidth/2,sY+stringHeight/2);
+		g_.drawOval(sX-stringWidth/2-5,sY-stringHeight/2-2 ,stringWidth+10, stringHeight+10);
+	}
+	public int getScreenX(double angle, double radius) {
+		return screenCentreX + (int)(convertRadius(radius)*screenRadius*Math.cos(angle*TWO_PI/worldAngle_)/worldRadius_);
+	}
+	public int getScreenX(double angle, double radius, int outdent) {
+		double trigBit = Math.cos(angle*TWO_PI/worldAngle_);
+		return screenCentreX + (int)(outdent*trigBit + convertRadius(radius)*screenRadius*trigBit/worldRadius_);
+	}
+
+	public int getScreenDeltaX(double angle, double radius) {
+
+		return (int)(convertRadius(radius)*screenRadius*Math.cos(angle*TWO_PI/worldAngle_
+								)/worldRadius_ );
+
+	}
+
+	public int getScreenY(double angle, double radius) {
+		int offset = (int)(convertRadius(radius)*screenRadius*Math.sin(angle*TWO_PI/worldAngle_)/worldRadius_);
+
+		return (invertY_ ? (screenCentreY + offset) : (screenCentreY - offset));
+	}
+	public int getScreenY(double angle, double radius, int outdent) {
+		double trigBit = Math.sin(angle*TWO_PI/worldAngle_);
+		int offset =  (int)(outdent*trigBit + convertRadius(radius)*screenRadius*trigBit/worldRadius_);
+		return (invertY_ ? (screenCentreY + offset) : (screenCentreY - offset));
+	}
+
+	public int getScreenDeltaY(double angle, double radius) {
+		return (invertY_ ? 1 : -1 )*(int)(convertRadius(radius)*screenRadius*Math.sin(angle*TWO_PI/worldAngle_)/worldRadius_);
+	}
+	public void fillPoint(double angle, double radius, int size) {
+		int x = getScreenX(angle,radius);
+		int y = getScreenY(angle,radius);
+
+		g_.fillOval(x-size,y-size,2*size,2*size);
+	}
+
+
+	public void drawPoint(double angle, double radius, int size) {
+		int x = getScreenX(angle,radius);
+		int y = getScreenY(angle,radius);
+
+		g_.drawOval(x-size,y-size,2*size,2*size);
+	}
+
+	public void drawSymbol(double angle, double radius, int outdent, int width, int symbol) {
+
+		int halfWidth = width / 2;
+		int x = getScreenX(angle,radius,outdent);
+		int y = getScreenY(angle,radius,outdent);
+
+		switch (symbol% 6) {
+			case 0: g_.fillRect(x, y, width, width); break;
+			case 1: g_.drawRect(x, y, width, width); break;
+			case 2: g_.fillOval(x, y, width, width); break;
+			case 3: g_.drawOval(x, y, width, width); break;
+			case 4: // draw triangle
+				g_.drawLine(x, y + width, x + halfWidth, y);
+				g_.drawLine(x + halfWidth, y, x + width, y + width);
+				g_.drawLine(x, y + width, x + width, y + width);
+				break;
+			case 5: // draw X
+				g_.drawLine(x, y, x + width, y + width);
+				g_.drawLine(x, y + width, x + width, y);
+				break;
+		}
+	}
+
+
+
+
+
+
+
+
+}
+
diff --git a/LibrarySource/pal/gui/Painter.java b/LibrarySource/pal/gui/Painter.java
new file mode 100644
index 0000000..2db4d00
--- /dev/null
+++ b/LibrarySource/pal/gui/Painter.java
@@ -0,0 +1,26 @@
+// Painter.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import headless.awt.Graphics;
+import headless.awt.Dimension;
+
+
+/**
+ * An interface for objects which are used for painting themselves in a
+ * general Graphics object
+ *
+ * @author Matthew Goode
+ */
+
+public interface Painter {
+	void paint(Graphics g, int displayWidth, int displayHeight);
+	Dimension getPreferredSize();
+
+} 
+
diff --git a/LibrarySource/pal/gui/PositionedNode.java b/LibrarySource/pal/gui/PositionedNode.java
new file mode 100644
index 0000000..38e3b32
--- /dev/null
+++ b/LibrarySource/pal/gui/PositionedNode.java
@@ -0,0 +1,80 @@
+// PositionedNode.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import pal.tree.*;
+
+
+/**
+ * A tree node that has a scalar position for the purposes of drawing the tree.
+ *
+ * @author Alexei Drummond
+ * @version $Id: PositionedNode.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ */
+public class PositionedNode extends SimpleNode {
+
+	protected double x; //Please excuse this - it will be returned to its non public state eventually - MG
+
+	boolean highlight_;
+
+
+	/** Builds a tree based on node, but highlights highlightNode */
+	public PositionedNode(Node node, Node highlightNode) {
+
+		init(node);
+		if (!node.isLeaf()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				addChild(new PositionedNode(node.getChild(i),highlightNode));
+			}
+		}
+
+		highlight_ = (node==highlightNode);
+	}
+
+	public PositionedNode(Node node) {
+	
+		init(node);
+		if (!node.isLeaf()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				addChild(new PositionedNode(node.getChild(i)));
+			}
+		}
+	}
+	
+	public void calculatePositions() {
+
+		double[] currentXPos = {0.0};
+		calculateXPositions(currentXPos);
+	}
+
+	private double calculateXPositions(double[] currentXPos) {
+
+		if (!isLeaf()) {
+			// find average x position
+			x = ((PositionedNode)getChild(0)).calculateXPositions(currentXPos);
+			for (int i = 1; i < getChildCount(); i++) {
+				x += ((PositionedNode)getChild(i)).calculateXPositions(currentXPos);
+			}
+			x /= getChildCount();
+		} else {
+			x = currentXPos[0];
+			currentXPos[0] += 1.0;
+		}
+
+		return x;
+	}
+
+	public boolean isHighlighted() {
+   	return highlight_;
+	}
+
+	public double getX() {
+   	return x;
+	}
+}
+
diff --git a/LibrarySource/pal/gui/TreeComponent.java b/LibrarySource/pal/gui/TreeComponent.java
new file mode 100644
index 0000000..2212ff3
--- /dev/null
+++ b/LibrarySource/pal/gui/TreeComponent.java
@@ -0,0 +1,152 @@
+// TreeComponent.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import pal.tree.*;
+import pal.misc.*;
+
+import headless.awt.*;
+
+
+/**
+ * An AWT Component for displaying a tree.  
+ *
+ * @author Alexei Drummond
+ * @version $Id: TreeComponent.java,v 1.12 2001/07/13 14:39:13 korbinian Exp $
+ */
+public class TreeComponent extends Component {
+
+	boolean circular_ = false;
+
+	public final static int NORMAL_BW = 0;
+	public final static int CIRCULAR_BW = 1;
+	public final static int NORMAL_COLOR = 2;
+	public final static int CIRCULAR_COLOR = 3;
+
+	int mode_;
+
+	public final static String[] MODE_NAMES = new String[4];
+
+	// unfortunate but necessary to avoid Java 1.1 language features
+	static 	{
+		MODE_NAMES[NORMAL_BW] = "Normal (bw)";
+		MODE_NAMES[CIRCULAR_BW] = "Circular (bw)";
+		MODE_NAMES[NORMAL_COLOR] = "Normal (color)";
+		MODE_NAMES[CIRCULAR_COLOR] = "Circular (color)";
+
+	}
+
+	TreePainterCircular circlePainter_;
+	TreePainter painter_;
+
+	boolean invertCiruclar_;
+
+	// constructors
+
+	public TreeComponent(Tree tree, boolean usingSymbols) {
+		this(tree, (TimeOrderCharacterData)null, usingSymbols);
+	}
+	public TreeComponent(Tree tree, boolean usingSymbols, Node highlighNode) {
+		this(tree, (TimeOrderCharacterData)null, usingSymbols, highlighNode);
+	}
+	public TreeComponent(Tree tree, TimeOrderCharacterData tocd, boolean usingSymbols) {
+		this(tree,tocd, usingSymbols,null);
+
+	}
+	public TreeComponent(Tree tree, TimeOrderCharacterData tocd, boolean usingSymbols, Node highlightNode) {
+		this(tree,highlightNode);
+
+		if (tocd != null) {
+			painter_.setTimeOrderCharacterData(tocd);
+		}
+		painter_.setUsingSymbols(usingSymbols);
+	}
+	public TreeComponent(Tree tree, Node highlightNode) {
+		this(tree, "", false, highlightNode);
+	}
+
+	public TreeComponent(Tree tree) {
+		this(tree, "", false,null);
+	}
+
+	public TreeComponent(Tree tree, String title) {
+		this(tree, title, true,null);
+	}
+	public TreeComponent(Tree tree, String title, Node highlightNode) {
+		this(tree, title, true,highlightNode);
+	}
+	private TreeComponent(Tree tree, String title, boolean showTitle, Node highlightNode) {
+		painter_ = new TreePainterNormal(tree,title,showTitle,highlightNode);
+		circlePainter_ = new TreePainterCircular(tree,title,showTitle, highlightNode);
+		setMode(NORMAL_COLOR);
+		setSize(getPreferredSize());
+	}
+
+	public void setTree(Tree tree) {
+		painter_.setTree(tree);
+		circlePainter_.setTree(tree);
+	}
+
+	public void setTitle(String title) {
+		painter_.setTitle(title);
+		circlePainter_.setTitle(title);
+	}
+
+	public Dimension getPreferredSize() {
+		return painter_.getPreferredSize();
+	}
+	public void setInvertCircular(boolean invert) {
+		this.invertCiruclar_ = invert;
+	}
+
+
+	public Dimension getMinimumSize() {
+		return getPreferredSize();
+	}
+
+	public String getTitle() {
+			return painter_.getTitle();
+	}
+
+	/** 
+	 * Sets the mode of display for this component.
+	 * @param the mode to switch to. Valid arguments are NORMAL (for normal tree
+	 * display), and CIRCULAR (for a circular view of the trees)
+	 */
+	public void setMode(int mode) {
+		this.mode_= mode;
+		switch(mode) {
+			case NORMAL_BW : {
+				circular_ = false; painter_.setUsingColor(false);
+				break;
+			}
+			case NORMAL_COLOR : {
+				circular_ = false; painter_.setUsingColor(true);
+				break;
+			}
+			case CIRCULAR_BW : {
+				circular_ = true; circlePainter_.setUsingColor(false);
+				break;
+			}
+			case CIRCULAR_COLOR : {
+				circular_ = true; circlePainter_.setUsingColor(true);
+				break;
+			}
+		}
+	}
+
+	public void paint(Graphics g) {
+		if(!circular_) {
+			painter_.paint(g,getSize().width,getSize().height);
+		} else {
+			circlePainter_.paint(g,getSize().width,getSize().height,invertCiruclar_);
+		}
+
+	}
+}
+
diff --git a/LibrarySource/pal/gui/TreePainter.java b/LibrarySource/pal/gui/TreePainter.java
new file mode 100644
index 0000000..97c34e3
--- /dev/null
+++ b/LibrarySource/pal/gui/TreePainter.java
@@ -0,0 +1,247 @@
+// TreePainter.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import pal.tree.*;
+import pal.io.*;
+import pal.misc.*;
+
+import headless.awt.*;
+
+/**
+ * A class that can paint a tree into a Graphics object.  
+ *
+ * @version $Id: TreePainter.java,v 1.10 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+abstract public class TreePainter implements Painter {
+
+	public static final Color BACKGROUND = Color.white;
+	public static final Color FOREGROUND = Color.black;
+	public static final Color NORMAL_LABEL_COLOR = Color.green.darker();
+
+	public PositionedNode treeNode;
+
+	public String title_;
+
+	boolean showTitle_;
+
+	/** The tree being painted */
+	private Tree tree;
+
+	/** The time order character data used for determining symbols. */
+	private TimeOrderCharacterData tocd = null;
+
+	double width, height;
+
+	double maxLeafTime = 0.0;
+	double sizeOfScale = 0.0;
+
+	/** Width of pen used to paint lines */
+	private int penWidth = 2;
+
+	/** determines whether colors are used to distinguish branch depth */
+	private boolean usingColor = true;
+
+	/** determines whether node heights are displayed on the tree */
+	private boolean showingNodeHeights = false;
+
+	/** determines whether internal nodes are labelled */
+	protected boolean showingInternalLabels = true;
+
+	/** determines whether symbols are used instead of names */
+	private boolean usingSymbols = false;
+
+	public TreePainter(Tree toDisplay, String title, boolean showTitle) {
+
+		this.title_ = title;
+		this.showTitle_ = showTitle;
+		this.tree = toDisplay;
+
+		if (toDisplay instanceof DatedTipsClockTree) {
+			tocd = ((DatedTipsClockTree)toDisplay).getTimeOrderCharacterData();
+		}
+	}
+
+	/** Rotates the tree by leaf count, creates a positioned node version of the
+			trees root and calculates postions and width and height information.
+			@param highlightNode
+	*/
+	protected void standardTreePrep(Node highlightNode) {
+		TreeUtils.rotateByLeafCount(tree);
+
+		if(highlightNode!=null) {
+			treeNode = new PositionedNode(tree.getRoot(),highlightNode);
+		} else {
+			treeNode = new PositionedNode(tree.getRoot());
+		}
+		treeNode.calculatePositions();
+
+		width = NodeUtils.getLeafCount(treeNode);
+		height = treeNode.getNodeHeight();
+
+		maxLeafTime = 0.0;
+		maxLeafTime = getMaxLeafTime(treeNode);
+		maxLeafTime *= 1.5;
+
+		sizeOfScale = getSizeOfScale( height / 5.0);
+	}
+
+	public final void setPenWidth(int p) {
+		penWidth = p;
+	}
+
+	public final int getPenWidth() {
+		return penWidth;
+	}
+
+	public final void setTree(Tree tree) {
+		this.tree = tree;
+		standardTreePrep(null);
+	}
+
+  
+	public final void setTree(Tree tree, Node highlightNode) {
+		this.tree = tree;
+		standardTreePrep(highlightNode);
+	}
+
+	public final void setUsingColor(boolean use) {
+		usingColor = use;
+	}
+
+	public final boolean isUsingColor() {
+		return usingColor;
+	}
+
+	public final void setShowingNodeHeights(boolean s) {
+		showingNodeHeights = s;
+	}
+
+	public final boolean isShowingNodeHeights() {
+		return showingNodeHeights;
+	}
+
+	public final boolean isShowingInternalLabels() {
+		return showingInternalLabels;
+	}
+
+	public final TimeOrderCharacterData getTimeOrderCharacterData() {
+		return this.tocd;
+	}
+
+	public final void setTimeOrderCharacterData(TimeOrderCharacterData tocd) {
+		this.tocd = tocd;
+		usingSymbols = true;
+	}
+
+	public final boolean isUsingSymbols() {
+		return usingSymbols;
+	}
+
+	/**
+	 * Sets whether the tree is painted with symbols. This can
+	 * only be set to true of a TimeOrderCharacterData has been set.
+	 */
+	public final void setUsingSymbols(boolean use) {
+		usingSymbols = use;
+		if (tocd == null) usingSymbols = false;
+	}
+
+
+
+	protected final double getSizeOfScale(double target) {
+
+		double sos = 0.1;
+		boolean accept = false;
+		boolean divideByTwo = true;
+
+		while (!accept) {
+			if ((sos / target) >= 5.0) {
+				sos /= (divideByTwo ? 2.0 : 5.0);
+				divideByTwo = !divideByTwo;
+			} else if ((sos / target) < 0.2) {
+				sos *= (divideByTwo ? 5.0 : 2.0);
+				divideByTwo = !divideByTwo;
+			} else accept = true;
+		}
+
+		return sos;
+	}
+
+
+	protected static final double getMaxLeafTime(Node node) {
+
+		if (!node.isLeaf()) {
+		double max = getMaxLeafTime(node.getChild(0));
+			double posmax = 0.0;
+			for (int i = 1; i < node.getChildCount(); i++) {
+				posmax = getMaxLeafTime(node.getChild(i));
+				if (posmax > max) max = posmax;
+			}
+			return max;
+		} else {
+			return node.getNodeHeight();
+		}
+	}
+
+	public final static void drawSymbol(Graphics g, int x, int y, int width, int index) {
+
+		int halfWidth = width / 2;
+
+		switch (index % 6) {
+			case 0: g.fillRect(x, y, width, width); break;
+			case 1: g.drawRect(x, y, width, width); break;
+			case 2: g.fillOval(x, y, width, width); break;
+			case 3: g.drawOval(x, y, width, width); break;
+			case 4: // draw triangle
+				g.drawLine(x, y + width, x + halfWidth, y);
+				g.drawLine(x + halfWidth, y, x + width, y + width);
+				g.drawLine(x, y + width, x + width, y + width);
+				break;
+			case 5: // draw X
+				g.drawLine(x, y, x + width, y + width);
+				g.drawLine(x, y + width, x + width, y);
+				break;
+		}
+	}
+
+	public final boolean isShowTitle() {
+		return showTitle_;
+	}
+
+	public final void setTitle(String title) {
+		this.title_ = title;
+		showTitle_ = true;
+	}
+
+	public final String getTitle() {
+		return title_;
+	}
+
+	public final void doTitle(Graphics g, int x, int y) {
+		if(showTitle_) {
+			g.drawString(title_, x,y);
+		}
+	}
+
+	protected final void doScale(Graphics g, double xScale, int x, int y) {
+		g.setColor(FOREGROUND);
+		g.drawLine(x,
+				 y,
+				 x+ (int)Math.round(sizeOfScale * xScale),
+				 y);
+
+		g.drawString(sizeOfScale + ((tree.getUnits() == Tree.GENERATIONS) ?
+			" generations" : " substitutions"),
+				 x,y-12);
+	}
+
+}
+
diff --git a/LibrarySource/pal/gui/TreePainterCircular.java b/LibrarySource/pal/gui/TreePainterCircular.java
new file mode 100644
index 0000000..2424b7f
--- /dev/null
+++ b/LibrarySource/pal/gui/TreePainterCircular.java
@@ -0,0 +1,142 @@
+// TreePainter.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.gui;
+
+import pal.tree.*;
+import pal.io.*;
+import pal.misc.*;
+
+import headless.awt.*;
+
+/**
+ * A class that can paint a tree (in a circular fashion) into a Graphics object .
+ *
+ * @version $Id: TreePainterCircular.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond, Matthew Goode
+ */
+public class TreePainterCircular extends TreePainter {
+
+	public static final int RIGHTBORDER = 75;
+	public static final int LEFTBORDER = 10;
+	public static final int TOPBORDER = 20;
+	public static final int BOTTOMBORDER = 30;
+	static final int SYMBOL_SIZE = 8;
+	public static final int FONT_SIZE = 9;
+	public static final int YSPACER = 20;
+	public static final int XSPACER = 10;
+
+	double maxAngle_, maxRadius_;
+  public TreePainterCircular(Tree toDisplay, String title, boolean showTitle) {
+		this(toDisplay, title, showTitle,null);
+	}
+	public TreePainterCircular(Tree toDisplay, String title, boolean showTitle, Node highlightNode) {
+		super(toDisplay, title, showTitle);
+		standardTreePrep(highlightNode);
+		maxRadius_ = treeNode.getNodeHeight();
+		maxAngle_ = NodeUtils.getLeafCount(treeNode);
+	}
+	
+	/**
+	 * Returns the preferred size for drawing
+	 * (that is the size that will show everything nicely)
+	 */
+	public Dimension getPreferredSize() {
+		return new Dimension(100 + LEFTBORDER + RIGHTBORDER, 
+			100+TOPBORDER+ BOTTOMBORDER);
+	}
+
+	protected void paint(PositionedNode node, CircularGraphics cg) {
+		cg.setColor(FOREGROUND);
+		double angle = node.x;
+		double radius = node.getNodeHeight();
+
+		if (node.hasChildren()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				paintLeafBranch(node, (PositionedNode)node.getChild(i), cg);
+			}
+
+			for (int i = 0; i < node.getChildCount(); i++) {
+				paint((PositionedNode)node.getChild(i), cg);
+			}
+		} else {
+
+			if ((maxLeafTime > 0.0) && isUsingColor()) {
+				cg.setColor(Color.getHSBColor((float)(maxLeafTime - radius)/(float)maxLeafTime, 1.0f, 1.0f));
+			} else {
+				cg.setColor(NORMAL_LABEL_COLOR);
+			}
+
+
+			if (isUsingColor()) {
+				cg.fillPoint(angle,radius,2);
+			}
+			if (isUsingSymbols() && (getTimeOrderCharacterData() != null)) {
+				cg.drawSymbol(angle,radius, XSPACER, SYMBOL_SIZE,	getTimeOrderCharacterData().getTimeOrdinal(getTimeOrderCharacterData().whichIdNumber(node.getIdentifier().getName())));
+			} else {
+        if(isUsingColor()) {
+					cg.drawString( node.getIdentifier().getName(), angle,radius, XSPACER);
+					if(node.isHighlighted()) {
+						cg.setColor(Color.red);
+						cg.circleString(node.getIdentifier().getName(), angle,radius, XSPACER);
+					}
+				} else {
+					if(node.isHighlighted()) {
+						cg.setColor(Color.red);
+					}
+					cg.drawString( node.getIdentifier().getName(), angle,radius, XSPACER);
+				}
+
+			}
+		}
+
+	}
+
+
+	private void paintLeafBranch(PositionedNode parentNode, PositionedNode childNode, CircularGraphics g) {
+
+		// paint join to parent
+		g.drawArc(parentNode.x,childNode.x, parentNode.getNodeHeight()	);
+		// paint branch
+		g.drawLineDegreeAlign(childNode.x, childNode.getNodeHeight(), parentNode.getNodeHeight()
+							);
+
+		if (isShowingNodeHeights()) {
+
+			String label = FormattedOutput.getInstance().getDecimalString(childNode.getNodeHeight(), 4);
+			g.drawString(label, childNode.x, childNode.getNodeHeight(), XSPACER);
+		}
+	}
+
+	public void paint(Graphics g, int displayWidth, int displayHeight) {
+		paint(g,displayWidth,displayHeight,false);
+	}
+	public void paint(Graphics g, int displayWidth, int displayHeight,boolean invert) {
+
+		CircularGraphics cg =
+			new CircularGraphics(g,maxAngle_,maxRadius_,
+				LEFTBORDER,TOPBORDER,
+				(displayWidth - LEFTBORDER - RIGHTBORDER),
+				(displayHeight - TOPBORDER - BOTTOMBORDER),
+				invert
+			);
+
+		cg.setFont(new Font("Times", Font.PLAIN, FONT_SIZE));
+
+		g.setColor(BACKGROUND);
+		g.fillRect(0, 0, displayWidth, displayHeight);
+		paint(treeNode, cg);
+
+		doTitle(g,LEFTBORDER, TOPBORDER - 8);
+		//doScale(g,1,LEFTBORDER,displayHeight - BOTTOMBORDER + 12);
+
+	}
+}
+
+
+
diff --git a/LibrarySource/pal/gui/TreePainterNormal.java b/LibrarySource/pal/gui/TreePainterNormal.java
new file mode 100644
index 0000000..54a5156
--- /dev/null
+++ b/LibrarySource/pal/gui/TreePainterNormal.java
@@ -0,0 +1,168 @@
+// TreePainterNormal.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.gui;
+
+import pal.tree.*;
+import pal.io.*;
+import pal.misc.*;
+
+import headless.awt.*;
+
+/**
+ * A class that can paint a tree into a Graphics object.  
+ *
+ * @version $Id: TreePainterNormal.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class TreePainterNormal extends TreePainter {
+
+	public static final int RIGHTBORDER = 75;
+	public static final int LEFTBORDER = 10;
+	public static final int TOPBORDER = 20;
+	public static final int BOTTOMBORDER = 30;
+
+	public static final int FONT_SIZE = 9;
+	public static final int YSPACER = 20;
+	public static final int XSPACER = 4;
+
+	private double xScale = 1.0;
+	private double yScale = 1.0;
+
+
+  public TreePainterNormal(Tree toDisplay, String title, boolean showTitle) {
+		this(toDisplay,title,showTitle,null);
+	}
+	public TreePainterNormal(Tree toDisplay, String title, boolean showTitle, Node highlightNode) {
+		super(toDisplay,title,showTitle);
+		standardTreePrep(highlightNode);
+		System.out.println("HLNODE:"+highlightNode);
+	}
+
+
+	/** 
+	 * Returns the preferred size for drawing 
+	 * (that is the size that will show everything nicely)
+	 */
+	public Dimension getPreferredSize() {
+		return new Dimension(100 + LEFTBORDER + RIGHTBORDER, 
+			(int)Math.round(width * FONT_SIZE) + TOPBORDER + BOTTOMBORDER);
+	}
+
+	protected void paint(PositionedNode node, Graphics g,
+		int displayWidth, int displayHeight) {
+
+		Point p = getPoint(node,displayWidth, displayHeight);
+		g.setColor(FOREGROUND);
+
+		if (node.hasChildren()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				paintLeafBranch(p, getPoint((PositionedNode)node.getChild(i), 
+					displayWidth,displayHeight), node, g);
+			}
+
+			for (int i = 0; i < node.getChildCount(); i++) {
+				paint((PositionedNode)node.getChild(i), g,displayWidth, displayHeight);
+			}
+		} else {
+
+			if ((maxLeafTime > 0.0) && isUsingColor()) {
+				g.setColor(Color.getHSBColor((float)(maxLeafTime - node.getNodeHeight())/(float)maxLeafTime, 1.0f, 1.0f));
+			} else {
+				g.setColor(NORMAL_LABEL_COLOR);
+			}
+
+			if (isUsingColor()) {
+				int halfWidth = getPenWidth() / 2;
+				g.fillRect(p.x - halfWidth, p.y - halfWidth, getPenWidth(), getPenWidth());
+			}
+			if (isUsingSymbols()&&getTimeOrderCharacterData()!=null) {
+
+				drawSymbol(g, p.x + XSPACER, p.y - (FONT_SIZE / 2), FONT_SIZE,
+					getTimeOrderCharacterData().getTimeOrdinal(getTimeOrderCharacterData().whichIdNumber(node.getIdentifier().getName())));
+			} else {
+				String name = node.getIdentifier().getName();
+				int width = g.getFontMetrics().stringWidth(name);
+				if(isUsingColor()) {
+					g.drawString(name, p.x + XSPACER,
+							p.y + (FONT_SIZE / 2));
+					if(node.isHighlighted()) {
+						g.setColor(Color.red);
+						g.drawOval(p.x - 4+XSPACER, p.y-FONT_SIZE/2-5, width +10, FONT_SIZE+8 );
+					}
+				} else {
+					if(node.isHighlighted()) {
+						g.setColor(Color.red);
+					}
+					g.drawString(name, p.x + XSPACER,
+						p.y + (FONT_SIZE / 2));
+				}
+			}
+		}
+
+	}
+
+	public Point getPoint(PositionedNode node, int displayWidth, int displayHeight) {
+
+		return new Point(displayWidth -
+			(int)Math.round(node.getNodeHeight() * xScale) - RIGHTBORDER,
+			(int)Math.round(node.x * yScale) + TOPBORDER);
+	}
+
+	private void paintLeafBranch(Point p, Point lp, PositionedNode node, Graphics g) {
+
+		int halfWidth = getPenWidth() / 2;
+
+		// paint join to parent
+		g.fillRect(p.x - halfWidth, Math.min(p.y, lp.y) - halfWidth,
+				getPenWidth(), Math.abs(lp.y - p.y) + getPenWidth());
+
+		// paint branch
+		g.fillRect(Math.min(p.x, lp.x) - halfWidth, lp.y - halfWidth,
+				 Math.abs(lp.x - p.x) + getPenWidth(), getPenWidth());
+
+		if (isShowingNodeHeights()) {
+
+			String label = FormattedOutput.getInstance().getDecimalString(node.getNodeHeight(), 4);
+			int width = g.getFontMetrics().stringWidth(label);
+
+			int x = Math.min(p.x, lp.x) - (width / 2);
+
+			g.drawString(label, x, p.y - halfWidth - 1);
+
+		}
+
+		if (isShowingInternalLabels()) {
+			String label = node.getIdentifier().getName();
+			int width = g.getFontMetrics().stringWidth(label);
+
+			int x = Math.min(p.x, lp.x) - (width / 2);
+
+			g.drawString(label, x, p.y - halfWidth - 1);
+		}
+	}
+
+
+	public void paint(Graphics g, int displayWidth, int displayHeight) {
+
+		g.setFont(new Font("Times", Font.PLAIN, FONT_SIZE));
+
+		xScale = (double)(displayWidth - LEFTBORDER - RIGHTBORDER) / height;
+		yScale = (double)(displayHeight - TOPBORDER - BOTTOMBORDER) / width;
+
+		g.setColor(BACKGROUND);
+		g.fillRect(0, 0, displayWidth, displayHeight);
+		paint(treeNode, g, displayWidth, displayHeight);
+
+		doTitle(g,LEFTBORDER, TOPBORDER - 8);
+		doScale(g,xScale,LEFTBORDER,displayHeight - BOTTOMBORDER + 12);
+	}
+
+}
+
diff --git a/LibrarySource/pal/gui/makefile b/LibrarySource/pal/gui/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/gui/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/gui/package.html b/LibrarySource/pal/gui/package.html
new file mode 100644
index 0000000..3ec991c
--- /dev/null
+++ b/LibrarySource/pal/gui/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+GUI components for some special objects (e.g., trees).
+</body>
+</html>
diff --git a/LibrarySource/pal/io/FormattedInput.java b/LibrarySource/pal/io/FormattedInput.java
new file mode 100644
index 0000000..b7b2256
--- /dev/null
+++ b/LibrarySource/pal/io/FormattedInput.java
@@ -0,0 +1,362 @@
+// FormattedInput.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.io;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+
+/**
+ * tools to simplify formatted input from an input stream
+ *
+ * @version $Id: FormattedInput.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class FormattedInput implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * create new instance of this object
+	 * (note that there is no public constructor
+	 * because this class is a singleton!)
+	 */
+	public static FormattedInput getInstance()
+	{
+		if (singleton == null)
+		{
+			singleton = new FormattedInput();
+		}
+		
+		return singleton;
+	}
+	
+	/**
+	 * go to the beginning of the next line.
+         * Recognized line terminators:
+	 * Unix: \n, DOS: \r\n, Macintosh: \r
+	 *
+	 * @param in input stream
+	 */
+	public void nextLine(PushbackReader in)
+		throws IOException
+	{
+		readLine(in, false);
+	}
+	
+	/**
+	 * read a whole line
+	 *
+	 * @param in              input stream
+	 * @param keepWhiteSpace  keep or drop white space
+	 *
+	 * @return string with content of line
+	 */
+	public String readLine(PushbackReader in, boolean keepWhiteSpace)
+		throws IOException
+	{
+		StringBuffer buffer = new StringBuffer();
+
+		int EOF = -1;
+		int c;
+		
+		c = in.read();
+		while (c != EOF && c != '\n' && c != '\r')
+		{
+			if (!isWhite(c) || keepWhiteSpace)
+			{
+				buffer.append((char) c);
+			}
+			c = in.read();
+		}
+		
+		if (c == '\r')
+		{
+			c = in.read();
+			if (c != '\n')
+			{
+				in.unread(c);
+			}
+		}
+	
+		return buffer.toString();
+	}
+
+	/**
+	 * go to first non-whitespace character
+	 *
+	 * @param in input stream
+	 *
+	 * @return character or EOF
+	 */
+	public int skipWhiteSpace(PushbackReader in)
+		throws IOException
+	{
+		int EOF = -1;
+		int c;
+		
+		// search for first non-whitespace character
+		do
+		{
+			c = in.read();
+		}
+		while (c != EOF && isWhite(c));
+				
+		return c;
+	}
+
+	/**
+	 * read next character from stream
+	 * (EOF does not count as character but will throw exception)
+	 *
+	 * @param input input stream
+	 *
+	 * @return character
+	 */
+	public int readNextChar(PushbackReader input)
+		throws IOException
+	{
+		int EOF = -1;
+		
+		int c = skipWhiteSpace(input);
+		
+		if (c == EOF)
+		{
+			new IOException("End of file/stream");
+		}
+		
+		return c;
+	}
+
+	/**
+	 * read word from stream
+	 *
+	 * @param input stream
+	 *
+	 * @return word read from stream
+	 */
+	public String readWord(PushbackReader in)
+		throws IOException
+	{
+		StringBuffer buffer = new StringBuffer();
+		
+		int EOF = -1;
+		int c;
+		
+		c = skipWhiteSpace(in);
+		
+		// search for last non-whitespace character
+		while (c != EOF && !isWhite(c))
+		{
+			buffer.append((char) c);
+			c = in.read();
+		}
+		
+		if (c != EOF)
+		{
+			in.unread(c);
+		}
+		
+		return buffer.toString();
+	}
+
+	/**
+	 * read sequence label from stream
+	 *
+	 * A sequence label is not allowed to contain
+	 * whitespace and either of :,;()[]{}.  Note
+	 * that newline/cr is NOT counted as white space!!
+	 *
+	 * @param in input stream
+	 * @param maxLength maximum allowed length of label
+	 *        (if negative any length is permitted)
+	 *
+	 * @return label
+	 */
+	public String readLabel(PushbackReader in, int maxLength)
+		throws IOException
+	{
+		StringBuffer buffer = new StringBuffer();
+		
+		int EOF = -1;
+		int c;
+		int len = 0;
+		
+		
+		c = skipWhiteSpace(in);
+				
+		// search for last label character
+		while (c != EOF && buffer.length() != maxLength &&
+			!(
+			(isWhite(c) && c != '\n' && c != '\r') ||
+			c == ':' || c == ',' || c == ';' ||
+			c == '(' || c == ')' ||
+			c == '[' || c == ']' ||
+			c == '{' || c == '}'))
+		{
+			// read over newline/cr
+			if (c != '\n' && c != '\r') buffer.append((char) c);
+			c = in.read();
+		}
+		
+		if (c != EOF)
+		{
+			in.unread(c);
+		}
+		
+		return buffer.toString();
+	}
+
+	/*
+	 * read next number from stream
+	 *
+	 * @param in input stream
+	 * @param ignoreNewlineCR  ignore newline/cr as separator
+	 *
+	 * @return number (as string)
+	 */
+	public String readNumber(PushbackReader in, boolean ignoreNewlineCR)
+		throws IOException
+	{
+		StringBuffer buffer = new StringBuffer();
+		
+		int EOF = -1;
+		int c;
+		
+		// search for first number character
+		do
+		{
+			c = in.read();
+		}
+		while (c != EOF &&
+			!(c == '-' || c == '.' || Character.isDigit((char) c)));
+		
+		// search for last number character
+		while (c != EOF &&
+			(c == '-' || c == '.' || c == 'e'
+			|| c == 'E' || Character.isDigit((char) c))
+			|| (isNewlineCR(c) && ignoreNewlineCR) )
+		{
+			if (!(isNewlineCR(c) && ignoreNewlineCR))
+				buffer.append((char) c);
+			c = in.read();
+		}
+		
+		if (c != EOF)
+		{
+			in.unread(c);
+		}
+				
+		return buffer.toString();
+	}
+
+	/**
+	 * read next number from stream and convert it to a double
+	 * (newline/cr are treated as separators)
+	 *
+	 * @param in input stream
+	 *
+	 * @return double
+	 */
+	public double readDouble(PushbackReader in)
+		throws IOException, NumberFormatException
+	{
+		return readDouble(in, false);
+	}
+
+	/**
+	 * read next number from stream and convert it to a double
+	 *
+	 * @param in input stream
+	 * @param ignoreNewlineCR  ignore newline/cr as separator
+	 *
+	 * @return double
+	 */
+	public double readDouble(PushbackReader in, boolean ignoreNewlineCR)
+		throws IOException, NumberFormatException
+	{
+		String w = readNumber(in, ignoreNewlineCR);
+		if (w.length() == 0)
+		{
+			throw new IOException("End of file/stream");
+		}
+		
+		return Double.valueOf(w).doubleValue();
+	}
+
+
+	/**
+	 * read next number from stream and convert it to a int
+	 * (newline/cr are treated as separators)
+	 *
+	 * @param in input stream
+	 *
+	 * @return integer
+	 */
+	public int readInt(PushbackReader in)
+		throws IOException, NumberFormatException
+	{
+		return readInt(in, false);
+	}
+
+	/**
+	 * read next number from stream and convert it to a int
+	 *
+	 * @param in input stream
+	 * @param ignoreNewlineCR  ignore newline/cr as separator
+	 *
+	 * @return integer
+	 */
+	public int readInt(PushbackReader in, boolean ignoreNewlineCR)
+		throws IOException, NumberFormatException
+	{
+		String w = readNumber(in, ignoreNewlineCR);
+		if (w.length() == 0)
+		{
+			throw new IOException("End of file/stream");
+		}
+		
+		return Integer.valueOf(w).intValue();
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	// private constructor
+	private FormattedInput()
+	{
+		// Just to prevent a public constructor
+	}
+	
+	private static FormattedInput singleton;
+	
+	private static boolean isWhite(int c)
+	{
+		return Character.isWhitespace((char) c);
+	}
+	
+	private static boolean isNewlineCR(int c)
+	{
+		if (c == '\n' || c == 'r')
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/io/FormattedOutput.java b/LibrarySource/pal/io/FormattedOutput.java
new file mode 100644
index 0000000..bdb79ad
--- /dev/null
+++ b/LibrarySource/pal/io/FormattedOutput.java
@@ -0,0 +1,312 @@
+// FormattedOutput.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.io;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+import java.math.*;
+
+/**
+ * tools to simplify formatted output to a stream
+ *
+ * @version $Id: FormattedOutput.java,v 1.14 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class FormattedOutput implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * create instance of this class
+	 * (note that there is no public constructor
+	 * as this class is a singleton)
+	 */
+	public synchronized static FormattedOutput getInstance()
+	{
+		if (singleton == null)
+		{
+			singleton = new FormattedOutput();
+		}
+
+		return singleton;
+	}
+
+	/**
+	 * print decimal number with a prespecified number
+	 * of digits after the point
+	 *
+	 * @param out output stream
+	 * @param number to be printed
+	 * @param width number of fraction digits
+	 *
+	 * @return length of the string printed
+	 */
+	public int displayDecimal(PrintWriter out, double number, int width)
+	{
+		String s = getDecimalString(number, width);
+
+		out.print(s);
+
+		return s.length();
+	}
+
+	/**
+	 * Returns a decimal string representation of a number with
+	 * constrained width.
+	 */
+	public synchronized String getDecimalString(double number, int width) {
+		nf.setMinimumFractionDigits(width);
+		nf.setMaximumFractionDigits(width);
+
+		return nf.format(number);
+	}
+
+	private static final double round(double number, int sf) {
+		double decimals = Math.floor(Math.log(number) / Math.log(10.0));
+		double power =  Math.pow(10, decimals - sf+1);
+		number /= power;
+		number = Math.round(number);
+		number *= power;
+		return number;
+	}
+
+	//public String getSFString(double number, int sf) {
+	//	double decimals = Math.floor(Math.log(number) / Math.log(10.0));
+	//	double power =  Math.pow(10, decimals - sf);
+	//	number /= power;
+	//	number = Math.round(number);
+	//	number *= power;
+	//
+	//	return "" + number;
+	//}
+		
+	/** Used by getSFString3() */
+	private SFStringInfo getSFStringInfo(String buffer,int sf, boolean includeRightZeros, boolean previousCarry) {
+		char[] b2 = new char[(includeRightZeros ? buffer.length() : Math.min(sf,buffer.length()))];
+		boolean carry = (sf>=buffer.length() ? previousCarry : buffer.charAt(sf) >= '5');
+		for(int i = b2.length-1 ; i >=0; i--) {
+			if(i<sf) {
+				b2[i] = buffer.charAt(i);
+				if(carry) {
+					if(b2[i] == '9') {
+						b2[i] = '0';
+					} else {
+						b2[i]++;
+          	carry = false;
+					}
+				}
+			} else {
+				carry = buffer.charAt(i)>='5';
+				b2[i] = '0';
+			}
+		}
+		return new SFStringInfo(new String(b2), carry);
+
+	}
+
+	/**
+	 * An alternative version of getSFString which works on the actual string
+	 * Returns a string representing the given number to the number
+	 * of significant figures requested.
+	 */
+	 public String getSFString(double number, int sf) {
+		String s = number+"";
+		String preFullStop = null;
+		String postFullStop = null;
+		String postE = null;
+
+		int fullStopIndex = s.indexOf('.');
+		int eIndex = s.indexOf('e');
+		if(eIndex<0) {
+			eIndex = s.indexOf('E');
+		}
+
+		if(eIndex>=0) {
+			postE = s.substring(eIndex+1);
+		}
+		eIndex = s.length();
+		if(fullStopIndex>=0) {
+			postFullStop = s.substring(fullStopIndex+1,eIndex);
+
+		} else {
+			fullStopIndex = eIndex;
+		}
+
+		preFullStop = s.substring(0,fullStopIndex);
+
+		SFStringInfo postFSI = null;
+
+
+		boolean postCarry = false;
+		if(postFullStop!=null) {
+			int postSF = sf - preFullStop.length();
+			if(postSF>0) {
+				postFSI =   getSFStringInfo(postFullStop, postSF, false,false);
+				postCarry = postFSI.carry;
+			} else {
+
+				postCarry = postFullStop.charAt(0)>='5';
+			}
+
+		}
+		SFStringInfo preFSI;
+		preFSI = getSFStringInfo(preFullStop,sf,true,postCarry);
+		if(preFSI.carry) {
+			preFSI.string = "1"+preFSI.string;
+		}
+		String b;
+		if(postFSI!=null) {
+			b = preFSI.string+"."+postFSI.string;
+		} else {
+			b = preFSI.string;
+		}
+		if(postE != null) {
+     			b+='e'+postE;
+		}
+
+		while (b.charAt(b.length() - 1) == '0') {
+			b = b.substring(0, b.length()-1);
+		}
+		if (b.charAt(b.length() - 1) == '.') {
+			b = b.substring(0, b.length()-1);
+		}
+
+		return b;
+	}
+	/**
+	 * print label with a prespecified length
+	 * (label will be shortened or spaces will introduced, if necessary)
+	 *
+	 * @param out output stream
+	 * @param label label to be printed
+	 * @param width desired length
+	 */
+	public void displayLabel(PrintWriter out, String label, int width)
+	{
+		int len = label.length();
+
+		if (len == width)
+		{
+			// Print as is
+			out.print(label);
+		}
+		else if (len < width)
+		{
+			// fill rest with spaces
+			out.print(label);
+			multiplePrint(out, ' ', width - len);
+		}
+		else
+		{
+			// Print first width characters
+			for (int i = 0; i < width; i++)
+			{
+				out.print(label.charAt(i));
+			}			
+		}		
+	}
+	
+	/**
+	 * print integer, aligned to a reference number,
+	 * (introducing space at the left side)
+	 *
+	 * @param out output stream
+	 * @param num number to be printed
+	 * @param maxNum reference number
+	 */
+	public void displayInteger(PrintWriter out, int num, int maxNum)
+	{
+		int lenNum = Integer.toString(num).length();
+		int lenMaxNum = Integer.toString(maxNum).length();
+		
+		if (lenNum < lenMaxNum)
+		{
+			multiplePrint(out, ' ', lenMaxNum - lenNum);
+		}
+		out.print(num);
+	}
+
+	/**
+	 * print whitespace of length of a string displaying a given integer
+	 *
+	 * @param output stream
+	 * @param maxNum number
+	 */
+	public void displayIntegerWhite(PrintWriter out, int maxNum)
+	{
+		int lenMaxNum = Integer.toString(maxNum).length();
+		
+		multiplePrint(out, ' ', lenMaxNum);
+	}
+
+	/**
+	 * repeatedly print a character
+	 *
+	 * @param out output stream
+	 * @param c   character
+	 * @param num number of repeats
+	 */
+	public void multiplePrint(PrintWriter out, char c, int num)
+	{
+		for (int i = 0; i < num; i++)
+		{
+			out.print(c);
+		}
+	}
+
+	/**
+	 * returns of string of a given length of a single character.
+	 *
+	 * @param size length of the string required
+	 * @param c   character
+	 */
+	public static String space(int size, char c) {
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < size; i++) {
+			sb.append(c);
+		}		
+		return new String(sb);
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	// private constructor
+	private FormattedOutput()
+	{
+		nf = NumberFormat.getInstance(Locale.UK);
+		nf.setGroupingUsed(false);
+	}
+	
+	private static FormattedOutput singleton = null;
+	
+	private NumberFormat nf;
+}
+
+/**
+ * helper class
+ */
+class SFStringInfo
+{
+	String string;
+	boolean carry;
+
+	public SFStringInfo(String s, boolean c)
+	{
+		this.string = s;
+		this.carry = c;
+	}
+}
+
diff --git a/LibrarySource/pal/io/InputSource.java b/LibrarySource/pal/io/InputSource.java
new file mode 100644
index 0000000..2c102fb
--- /dev/null
+++ b/LibrarySource/pal/io/InputSource.java
@@ -0,0 +1,81 @@
+// InputSource.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.io;
+
+import java.io.*;
+
+
+/**
+ * convenience class to open input streams
+ * linked to files, stdin, and strings
+ *
+ * @version $Id: InputSource.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class InputSource extends PushbackReader
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * open file for reading
+	 *
+	 * @param name file name
+	 *
+	 * @return input stream
+	 */
+	public static InputSource openFile(String name)
+		throws FileNotFoundException
+	{
+		return new InputSource(
+			new BufferedReader(
+			new FileReader(name)));
+	}
+
+	/**
+	 * open standard input
+	 *
+	 * @return input stream
+	 */			
+	public static InputSource openStdIn()
+	{
+		return
+			new InputSource(
+			new BufferedReader(
+			new InputStreamReader(System.in)));
+	}
+
+	/**
+	 * "open" string for reading
+	 *
+	 * @param input string serving as source
+	 *
+	 * @return input stream
+	 */
+	public static InputSource openString(String input)
+	{
+		return new InputSource(new StringReader(input));
+	}
+	
+	
+	//
+	// Private stuff
+	//
+	
+	
+	// Private constructor
+
+	private InputSource(Reader in)
+	{
+		super(in);
+	}
+}
+
diff --git a/LibrarySource/pal/io/OutputTarget.java b/LibrarySource/pal/io/OutputTarget.java
new file mode 100644
index 0000000..653df71
--- /dev/null
+++ b/LibrarySource/pal/io/OutputTarget.java
@@ -0,0 +1,102 @@
+// OutputTarget.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.io;
+
+import java.io.*;
+
+
+/**
+ * convenience class to create output streams linked to
+ * files, stdout, and strings
+ *
+ * @version $Id: OutputTarget.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class OutputTarget extends PrintWriter
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * open file for writing
+	 *
+	 * @param name file name
+	 *
+	 * @return output stream
+	 */
+	public static OutputTarget openFile(String name)
+		throws IOException
+	{
+		return new OutputTarget(
+			new PrintWriter(
+			new BufferedWriter(
+			new FileWriter(name))));
+	}
+	
+	/**
+	 * open standard out
+	 *
+	 * @return output stream
+	 */		
+	public static OutputTarget openStdOut()
+	{
+		return new OutputTarget(new PrintWriter(System.out));
+	}
+
+	/**
+	 * "open" string to write into
+	 *
+	 * @return output stream
+	 */
+	public static OutputTarget openString()
+	{
+		StringWriter sw = new StringWriter();
+
+		return new OutputTarget(new PrintWriter(sw), sw);
+	}
+	
+	/**
+	 * get string corresponding to current stream created by openString()
+	 *
+	 * @return string 
+	 */
+	public String getString()
+	{
+		if (stringWriter == null)
+		{
+			return "";
+		}
+		else
+		{
+			return stringWriter.toString();
+		}
+	}
+	
+	
+	//
+	// Private stuff
+	//
+	
+	private StringWriter stringWriter;
+	
+	// Private constructor
+	private OutputTarget(PrintWriter out)
+	{
+		super(out);
+	}
+
+	private OutputTarget(PrintWriter out, StringWriter sw)
+	{
+		super(out);
+		stringWriter = sw;
+	}
+}
+
diff --git a/LibrarySource/pal/io/makefile b/LibrarySource/pal/io/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/io/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/io/package.html b/LibrarySource/pal/io/package.html
new file mode 100644
index 0000000..b4d214f
--- /dev/null
+++ b/LibrarySource/pal/io/package.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+Classes for simple (formatted) input/output from/to files,
+strings and standard-in/out streams.
+</body>
+</html>
+
diff --git a/LibrarySource/pal/makefile b/LibrarySource/pal/makefile
new file mode 100644
index 0000000..df5da00
--- /dev/null
+++ b/LibrarySource/pal/makefile
@@ -0,0 +1,52 @@
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: 
+	(cd alignment; $(MAKE) classes)
+	(cd distance; $(MAKE) classes)
+	(cd eval; $(MAKE) classes)
+	(cd gui; $(MAKE) classes)
+	(cd io; $(MAKE) classes)
+	(cd math; $(MAKE) classes)
+	(cd mep; $(MAKE) classes)
+	(cd misc; $(MAKE) classes)
+	(cd statistics; $(MAKE) classes)
+	(cd substmodel; $(MAKE) classes)
+	(cd tree; $(MAKE) classes)
+	(cd datatype; $(MAKE) classes)
+	(cd util; $(MAKE) classes)
+	(cd coalescent; $(MAKE) classes)
+
+native: 
+	(cd alignment; $(MAKE) native)
+	(cd distance; $(MAKE) native)
+	(cd eval; $(MAKE) native)
+	#(cd gui; $(MAKE) native)
+	(cd io; $(MAKE) native)
+	(cd math; $(MAKE) native)
+	(cd mep; $(MAKE) native)
+	(cd misc; $(MAKE) native)
+	(cd statistics; $(MAKE) native)
+	(cd substmodel; $(MAKE) native)
+	(cd tree; $(MAKE) native)
+	(cd datatype; $(MAKE) native)
+	(cd util; $(MAKE) native)
+	(cd coalescent; $(MAKE) native)
+
+clean:
+	(cd alignment; $(MAKE) clean)
+	(cd distance; $(MAKE) clean)
+	(cd eval; $(MAKE) clean)
+	(cd gui; $(MAKE) clean)
+	(cd io; $(MAKE) clean)
+	(cd math; $(MAKE) clean)
+	(cd mep; $(MAKE) clean)
+	(cd misc; $(MAKE) clean)
+	(cd statistics; $(MAKE) clean)
+	(cd substmodel; $(MAKE) clean)
+	(cd tree; $(MAKE) clean)
+	(cd datatype; $(MAKE) clean)
+	(cd util; $(MAKE) clean)
+	(cd coalescent; $(MAKE) clean)
+
diff --git a/LibrarySource/pal/math/Binomial.java b/LibrarySource/pal/math/Binomial.java
new file mode 100644
index 0000000..31ef14c
--- /dev/null
+++ b/LibrarySource/pal/math/Binomial.java
@@ -0,0 +1,81 @@
+// Binomial.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+/**
+ * Binomial coefficients
+ *
+ * @version $Id: Binomial.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class Binomial implements java.io.Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Binomial coefficient n choose k
+	 */
+	public double choose(double n, double k)
+	{
+		n = Math.floor(n + 0.5);
+		k = Math.floor(k + 0.5);
+
+		double lchoose = GammaFunction.lnGamma(n + 1.0) -
+		GammaFunction.lnGamma(k + 1.0) - GammaFunction.lnGamma(n - k + 1.0);
+
+		return Math.floor(Math.exp(lchoose) + 0.5);
+	}
+
+	/**
+	 * get (precomputed) n choose 2
+	 */
+	public double getNChoose2(int n)
+	{
+		return nChoose2[n];
+	}
+
+	/**
+	 * set capacity and precompute the n choose 2 values
+	 */
+	public void setMax(int max)
+	{
+		if (nChoose2 == null)
+		{
+			precalculate(max);
+		}
+		else if (max >= nChoose2.length)
+		{
+			precalculate(Math.max(nChoose2.length * 2, max));
+		}
+	}
+
+
+	//
+	// private stuff
+	//
+
+	private double[] nChoose2 = null;
+
+	/**
+	 * pre-calculates n choose 2 up to a given number of lineages, if
+	 * not already pre-calculated.
+	 */
+	private void precalculate(int n) {
+	
+		nChoose2 = new double[n+1];
+	
+		for (int i=0; i < (n+1); i++) {
+			nChoose2[i] = ((double) (i*(i-1))) * 0.5;
+		}
+	}	
+}
+
diff --git a/LibrarySource/pal/math/BoundsCheckedFunction.java b/LibrarySource/pal/math/BoundsCheckedFunction.java
new file mode 100644
index 0000000..da4e17b
--- /dev/null
+++ b/LibrarySource/pal/math/BoundsCheckedFunction.java
@@ -0,0 +1,96 @@
+// BoundsCheckedFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * returns a very large number instead of the function value
+ * if arguments are out of bound (useful for minimization with
+ * minimizers that don't check argument boundaries)
+ *
+ * @author Korbinian Strimmer
+ */
+public class BoundsCheckedFunction implements MultivariateFunction
+{	
+	/**
+	 * construct bound-checked multivariate function
+	 * (a large number will be returned on function evaluation if argument
+	 * is out of bounds; default is 1000000)
+	 *
+	 * @param func   unconstrained multivariate function
+	 * @param minArg lower constraint
+	 * @param maxArg upper constraint
+	 */
+	public BoundsCheckedFunction(MultivariateFunction func)
+	{
+		this(func, 1000000);
+	}
+	
+	/**
+	 * construct constrained multivariate function
+	 *
+	 * @param func    unconstrained multivariate function
+	 * @param largeNumber  value returned on function evaluation
+	 *                     if argument is out of bounds
+	 */
+	public BoundsCheckedFunction(MultivariateFunction func, double largeNumber)
+	{
+		f = func;
+		veryLarge = largeNumber;
+	}
+		
+	/**
+	 * computes function value, taking into account the constraints on the
+	 * argument 
+	 *
+	 * @param x function argument
+	 *
+	 * @return function value (if argument is not in the predefined constrained area
+	 * a very large number is returned instead of the true function value)
+	 */
+	public double evaluate(double[] x)
+	{
+		int len = f.getNumArguments();
+		
+		for (int i = 0; i < len; i++)
+		{
+			if (x[i] < f.getLowerBound(i) ||
+				x[i] > f.getUpperBound(i))
+			{
+				return veryLarge;
+			}
+		}
+		
+		return f.evaluate(x);
+	}
+
+	public int getNumArguments()
+	{
+		return f.getNumArguments();
+	}
+
+	public double getLowerBound(int n)
+	{
+		return f.getLowerBound(n);
+	}
+
+	public double getUpperBound(int n)
+	{
+		return f.getUpperBound(n);
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private MultivariateFunction f;
+	private double veryLarge;
+}
+
diff --git a/LibrarySource/pal/math/ConjugateDirectionSearch.java b/LibrarySource/pal/math/ConjugateDirectionSearch.java
new file mode 100644
index 0000000..fbe6c42
--- /dev/null
+++ b/LibrarySource/pal/math/ConjugateDirectionSearch.java
@@ -0,0 +1,953 @@
+// ConjugateDirectionSearch.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// - algorithm is based on Brent's modification of a conjugate direction
+//   search method proposed by Powell (praxis)
+//   Richard P. Brent.  1973.   Algorithms for finding zeros and extrema
+//   of functions without calculating derivatives.  Prentice-Hall.
+
+
+package pal.math;
+
+
+/**
+ * methods for minimization of a real-valued function of
+ * several variables without using derivatives (Brent's modification
+ * of a conjugate direction search method proposed by Powell)
+ *
+ * @author Korbinian Strimmer
+ */
+public class ConjugateDirectionSearch extends MultivariateMinimum 
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * constructor
+	 */
+	public ConjugateDirectionSearch()
+	{
+		// random number generator
+		rng = new MersenneTwisterFast();
+	}
+	
+	
+	// Variables that control aspects of the inner workings of the
+	// minimization algorithm. Setting them is optional, they      
+	// are all set to some reasonable default values given below.        
+
+	/**
+	 *  controls the printed output from the routine        
+	 *  (0 -> no output, 1 -> print only starting and final values,            
+	 *   2 -> detailed map of the minimization process,         
+	 *   3 -> print also eigenvalues and vectors of the       
+	 *   search directions), the default value is 0                                
+	 */
+	public int prin = 0;
+	
+	/**
+	 * step is a steplength parameter and should be set equal     
+	 * to the expected distance from the solution.          
+	 * exceptionally small or large values of step lead to   
+	 * slower convergence on the first few iterations        
+	 * the default value for step is 1.0                     
+	 */
+	public double step = 1.0;
+	
+	/**
+	 * scbd is a scaling parameter. 1.0 is the default and        
+	 * indicates no scaling. if the scales for the different 
+	 * parameters are very different, scbd should be set to  
+	 * a value of about 10.0.                                
+	 */
+	public double scbd = 1.0;
+	
+	/**
+	 * illc  should be set to true
+	 * if the problem is known to  
+	 * be ill-conditioned. the default is false. this   
+	 * variable is automatically set, when the problem   
+         * is found to to be ill-conditioned during iterations.  
+	 */
+	public boolean illc = false;
+ 	
+ 	// implementation of abstract method 
+	
+	public void optimize(MultivariateFunction f, double[] xvector,
+		double tolfx, double tolx)
+	{
+		t = tolx;
+		
+		fun = f;
+		x = xvector;
+		
+		checkBounds(x);
+		h = step;		
+
+		dim = fun.getNumArguments();;
+
+		d = new double[dim];
+		y = new double[dim];
+		z = new double[dim];
+		q0 = new double[dim];
+		q1 = new double[dim];
+		v = new double[dim][dim];
+		tflin = new double[dim];
+		
+		small = MachineAccuracy.EPSILON*MachineAccuracy.EPSILON;
+		vsmall = small*small;
+		large = 1.0/small;
+		vlarge = 1.0/vsmall;
+		ldfac = (illc ? 0.1 : 0.01);
+		nl = kt = 0;
+		numFun = 1;
+		fx = fun.evaluate(x);
+		
+		stopCondition(fx, x, tolfx, tolx, true);
+		
+		qf1 = fx;
+		t2 = small + Math.abs(t);
+		t = t2;
+		dmin = small;
+
+		if (h < 100.0*t) h = 100.0*t;
+		ldt = h;
+		for (i = 0; i < dim; i++)
+		{
+			for (j = 0; j < dim; j++)
+			{
+				v[i][j] = (i == j ? 1.0 : 0.0);
+			}
+		}
+		d[0] = 0.0;
+		qd0 = 0.0;
+		for (i = 0; i < dim; i++)
+			q1[i] = x[i];
+
+		if (prin > 1)
+		{
+			System.out.println("\n------------- enter function praxis -----------\n");
+			System.out.println("... current parameter settings ...");
+			System.out.println("... scaling ... " + scbd);
+			System.out.println("...   tolx  ... " + t);
+			System.out.println("...  tolfx  ... " + tolfx);
+			System.out.println("... maxstep ... " + h);
+			System.out.println("...   illc  ... " + illc);
+			System.out.println("... maxFun  ... " + maxFun);
+		}
+   		if (prin > 0)
+   			System.out.println();
+
+		while(true)
+		{
+			sf = d[0];
+			s = d[0] = 0.0;
+	
+			/* minimize along first direction */
+			
+			min1 = d[0];
+			min2 = s;
+			min(0, 2, fx, false);
+			d[0] = min1;
+			s = min2;
+			
+			if (s <= 0.0)
+				for (i = 0; i < dim; i++)
+				{
+					v[i][0] = -v[i][0];
+				}	
+			if ((sf <= (0.9 * d[0])) || ((0.9 * sf) >= d[0]))
+				for (i=1; i < dim; i++)
+					d[i] = 0.0;
+			
+			boolean gotoFret = false;
+			for (k=1; k < dim; k++)
+			{
+				for (i=0; i< dim; i++)
+				{
+					y[i] = x[i];
+				}
+				sf = fx;
+				illc = illc || (kt > 0);
+
+				boolean gotoNext;
+				do
+				{
+					kl = k;
+					df = 0.0;
+					if (illc)
+					{        /* random step to get off resolution valley */
+		          			for (i=0; i < dim; i++)
+		          			{
+							z[i] = (0.1 * ldt + t2 * Math.pow(10.0,(double)kt)) * (rng.nextDouble() - 0.5);
+							s = z[i];
+							for (j=0; j < dim; j++)
+							{
+								x[j] += s * v[j][i];
+							}
+						}
+						
+						checkBounds(x);
+						
+						fx = fun.evaluate(x);
+						numFun++;
+					}
+		       
+					/* minimize along non-conjugate directions */ 
+					for (k2=k; k2 < dim; k2++)
+					{  
+						sl = fx;
+						s = 0.0;
+						
+						min1 = d[k2];
+						min2 = s;
+						min(k2, 2, fx, false);
+						d[k2] = min1;
+						s = min2;
+						
+						if (illc)
+						{
+							double szk = s + z[k2];
+		         				s = d[k2] * szk*szk;
+			   			}
+						else 
+							s = sl - fx;
+						if (df < s)
+						{
+							df = s;
+							kl = k2;
+						}
+					}
+					
+					if (!illc && (df < Math.abs(100.0 * MachineAccuracy.EPSILON * fx)))
+					{
+						illc = true;
+						gotoNext = true;
+					}
+					else
+						gotoNext = false;
+				} while (gotoNext);
+
+				
+				
+	 			if ((k == 1) && (prin > 1))
+					vecprint("\n... New Direction ...", d);
+				/* minimize along conjugate directions */ 
+				for (k2=0; k2<=k-1; k2++)
+				{
+					s = 0.0;
+					
+					min1 = d[k2];
+					min2 = s;
+					min(k2, 2, fx, false);
+					d[k2] = min1;
+					s = min2;
+				}
+				f1 = fx;
+				fx = sf;
+				lds = 0.0;
+				for (i=0; i<dim; i++)
+				{
+					sl = x[i];
+					x[i] = y[i];
+					y[i] = sl - y[i];
+					sl = y[i];
+					lds = lds + sl*sl;
+				}
+				checkBounds(x);
+				
+				lds = Math.sqrt(lds);
+				if (lds > small)
+				{
+					for (i=kl-1; i>=k; i--)
+					{
+						for (j=0; j < dim; j++)
+							v[j][i+1] = v[j][i];
+						d[i+1] = d[i];
+					}
+					d[k] = 0.0;
+					for (i=0; i < dim; i++)
+						v[i][k] = y[i] / lds;
+					
+					min1 = d[k];
+					min2 = lds;
+					min(k, 4, f1, true);
+					d[k] = min1;
+					lds = min2;
+					
+					if (lds <= 0.0)
+					{
+						lds = -lds;
+						for (i=0; i< dim; i++)
+							v[i][k] = -v[i][k];
+					}
+	 			}
+				ldt = ldfac * ldt;
+				if (ldt < lds)
+					ldt = lds;
+				if (prin > 1)
+					print();
+				
+				
+				if(stopCondition(fx, x, tolfx, tolx, false))
+				{
+					kt++;
+				}
+				else
+				{
+					kt = 0;
+				}
+				if (kt > 1)
+				{
+					gotoFret = true;
+					break;
+				}
+				
+			}
+	   
+	   		if (gotoFret) break;
+	   
+   
+			/*  try quadratic extrapolation in case    */
+			/*  we are stuck in a curved valley        */
+			quadr();
+			dn = 0.0;
+			for (i=0; i < dim; i++)
+			{
+				d[i] = 1.0 / Math.sqrt(d[i]);
+				if (dn < d[i])
+					dn = d[i];
+			}
+			if (prin > 2)
+				matprint("\n... New Matrix of Directions ...",v);
+			for (j=0; j < dim; j++)
+			{
+				s = d[j] / dn;
+				for (i=0; i < dim; i++)
+					v[i][j] *= s;
+			}
+			if (scbd > 1.0)
+			{       /* scale axis to reduce condition number */
+				s = vlarge;
+				for (i=0; i < dim; i++)
+				{
+					sl = 0.0;
+					for (j=0; j < dim; j++)
+						sl += v[i][j]*v[i][j];
+					z[i] = Math.sqrt(sl);
+					if (z[i] < MachineAccuracy.SQRT_SQRT_EPSILON)
+						z[i] = MachineAccuracy.SQRT_SQRT_EPSILON;
+					if (s > z[i])
+						s = z[i];
+				}
+				for (i=0; i < dim; i++)
+				{
+					sl = s / z[i];
+					z[i] = 1.0 / sl;
+					if (z[i] > scbd)
+					{
+						sl = 1.0 / scbd;
+						z[i] = scbd;
+					}
+				}
+	   		}
+	   		for (i=1; i < dim; i++)
+				for (j=0; j<=i-1; j++)
+				{
+					s = v[i][j];
+					v[i][j] = v[j][i];
+					v[j][i] = s;
+				}
+			minfit(dim, MachineAccuracy.EPSILON, vsmall, v, d);
+			if (scbd > 1.0)
+			{
+				for (i=0; i < dim; i++)
+				{
+					s = z[i];
+					for (j=0; j < dim; j++)
+						v[i][j] *= s;
+				}
+				for (i=0; i < dim; i++)
+				{
+					s = 0.0;
+					for (j=0; j < dim; j++)
+						s += v[j][i]*v[j][i];
+					s = Math.sqrt(s);
+					d[i] *= s;
+					s = 1.0 / s;
+					for (j=0; j < dim; j++)
+						v[j][i] *= s;
+				}
+			}
+			for (i=0; i < dim; i++)
+			{
+				if ((dn * d[i]) > large)
+					d[i] = vsmall;
+				else if ((dn * d[i]) < small)
+					d[i] = vlarge;
+				else 
+					d[i] = Math.pow(dn * d[i],-2.0);
+			}
+			sort();               /* the new eigenvalues and eigenvectors */
+			dmin = d[dim-1];
+			if (dmin < small)
+				dmin = small;
+			illc = (MachineAccuracy.SQRT_EPSILON * d[0]) > dmin;
+			if ((prin > 2) && (scbd > 1.0))
+				vecprint("\n... Scale Factors ...",z);
+			if (prin > 2)
+				vecprint("\n... Eigenvalues of A ...",d);
+			if (prin > 2)
+				matprint("\n... Eigenvectors of A ...",v);
+		
+			if ((maxFun > 0) && (nl > maxFun))
+			{
+				if (prin > 0)
+					System.out.println("\n... maximum number of function calls reached ...");
+				break;
+			}
+		}
+
+		if (prin > 0)
+		{
+			vecprint("\n... Final solution is ...", x);
+			System.out.println("\n... Function value reduced to " + fx + " ...");
+			System.out.println("... after " + numFun + " function calls.");
+		}
+	   
+		//return (fx);
+	}
+                                                                	
+
+	//
+	// Private stuff
+	//
+
+	// some global variables
+	private int i, j, k, k2, nl, kl, kt;
+	private double s, sl, dn, dmin,
+		fx, f1, lds, ldt, sf, df,
+		qf1, qd0, qd1, qa, qb, qc, small, vsmall, large, 
+		vlarge, ldfac, t2;
+		
+	// need to be initialised
+	private double[] d;
+	private double[] y;
+	private double[] z;
+	private double[] q0;
+	private double[] q1;
+	private double[][] v;
+
+	private double[] tflin;
+
+	private int dim;	
+	private double[] x;
+	private MultivariateFunction fun;
+
+	// these will be set by praxis to the global control parameters
+	private double h, t;
+
+	// Random number generator
+	private MersenneTwisterFast rng;
+
+	// sort d and v in descending order
+	private void sort()		
+	{
+		int k, i, j;
+		double s;
+
+		for (i=0; i < dim-1; i++)
+		{
+			k = i; s = d[i];
+			for (j=i+1; j < dim; j++)
+			{
+				if (d[j] > s)
+				{
+					k = j;
+					s = d[j];
+				}
+			}
+			if (k > i)
+       			{
+				d[k] = d[i];
+				d[i] = s;
+				for (j=0; j < dim; j++)
+	  			{
+					s = v[j][i];
+					v[j][i] = v[j][k];
+					v[j][k] = s;
+				}
+			}
+		}
+	}
+
+	private void vecprint(String s, double[] x)
+	{
+		System.out.println(s);
+		for (int i=0; i < x.length; i++)
+			System.out.print(x[i] + "  ");
+		System.out.println();
+	}
+
+	private void print() /* print a line of traces */
+	{
+		System.out.println();
+		System.out.println("... function value reduced to ... " + fx);
+		System.out.println("... after " + numFun + " function calls ...");
+		System.out.println("... including " + nl + " linear searches ...");
+		vecprint("... current values of x ...", x);
+	}
+
+	private void matprint(String s, double[][] v)
+	{
+		System.out.println(s);
+		for (int k=0; k<v.length; k++)
+		{
+			for (int i=0; i<v.length; i++)
+			{
+				System.out.print(v[k][i] + " ");
+			}
+			System.out.println();
+		}
+	}
+
+	private double flin(double l, int j)
+	{
+		if (j != -1)
+		{ /* linear search */
+			for (int i = 0; i < dim; i++)
+				tflin[i] = x[i] + l*v[i][j];
+		}
+		else
+		{ /* search along parabolic space curve */
+			qa = l*(l-qd1)/(qd0*(qd0+qd1));
+			qb = (l+qd0)*(qd1-l)/(qd0*qd1);
+			qc = l*(l+qd0)/(qd1*(qd0+qd1));
+			for (int i = 0; i < dim; i++)
+			{
+				tflin[i] = qa*q0[i]+qb*x[i]+qc*q1[i];
+			}
+		}
+		
+		checkBounds(tflin);
+		
+		numFun++;
+		return fun.evaluate(tflin);
+	}
+
+	private void checkBounds(double[] p)
+	{
+		for (int i = 0; i < dim; i++)
+		{
+			if (p[i] < fun.getLowerBound(i))
+			{
+				p[i] = fun.getLowerBound(i);
+			}
+			if (p[i] > fun.getUpperBound(i))
+			{
+				p[i] = fun.getUpperBound(i);
+			}
+		}
+	}
+
+	private double min1;
+	private double min2;
+
+	private void min(int j, int nits, double f1, boolean fk)
+	{
+		int k;
+		double x2, xm, f0, f2, fm, d1, t2, s, sf1, sx1;
+
+		sf1 = f1; sx1 = min2;
+		k = 0; xm = 0.0; fm = f0 = fx;
+		boolean dz = (min1 < MachineAccuracy.EPSILON);
+
+		/* find step size */
+		s = 0;
+		for (int i=0; i < dim; i++)
+		{
+			s += x[i]*x[i];
+		}
+		s = Math.sqrt(s);
+		if (dz)
+		{
+			t2 = MachineAccuracy.SQRT_SQRT_EPSILON*
+				Math.sqrt(Math.abs(fx)/dmin + s*ldt) +
+				MachineAccuracy.SQRT_EPSILON*ldt;
+		}
+		else
+		{
+			t2 = MachineAccuracy.SQRT_SQRT_EPSILON*
+				Math.sqrt(Math.abs(fx)/(min1) + s*ldt) +
+				MachineAccuracy.SQRT_EPSILON*ldt;
+		}
+		s = s*MachineAccuracy.SQRT_SQRT_EPSILON + t;
+		if (dz && t2 > s)
+			t2 = s;
+		if (t2 < small)
+			t2 = small;
+		if (t2 > 0.01*h)
+			t2 = 0.01 * h;
+		if (fk && f1 <= fm)
+		{
+			xm = min2;
+			fm = f1;
+		}
+		if (!fk || Math.abs(min2) < t2)
+		{
+			min2 = (min2 > 0 ? t2 : -t2);
+      			f1 = flin(min2, j);
+		}
+		if (f1 <= fm)
+		{
+			xm = min2;
+			fm = f1;
+		}
+
+		boolean gotoNext;
+		do
+		{
+			if (dz)
+			{
+				x2 = (f0 < f1 ? -(min2) : 2*(min2));
+				f2 = flin(x2, j);
+				if (f2 <= fm)
+				{
+					xm = x2;
+					fm = f2;
+				}
+				min1 = (x2*(f1-f0) - (min2)*(f2-f0))/((min2)*x2*((min2)-x2));
+			}
+			d1 = (f1-f0)/(min2) - min2*min1;
+			dz = true;
+			if (min1 <= small)
+			{
+				x2 = (d1 < 0 ? h : -h);
+			}
+			else
+			{
+				x2 = - 0.5*d1/(min1);
+			}
+			if (Math.abs(x2) > h)
+				x2 = (x2 > 0 ? h : -h);
+
+			f2 = flin(x2, j);
+		
+			gotoNext = false;
+		
+			while ((k < nits) && (f2 > f0))
+			{
+				k++;
+				if ((f0 < f1) && (min2*x2 > 0.0))
+				{
+					gotoNext = true;
+					break;
+				}
+				
+				
+				x2 *= 0.5;
+				f2 = flin(x2, j);	
+			}
+		} while (gotoNext);
+		
+
+		nl++;
+		if (f2 > fm)
+			x2 = xm;
+		else fm = f2;
+		if (Math.abs(x2*(x2-min2)) > small)
+		{
+			min1 = (x2*(f1-f0) - min2*(fm-f0))/(min2*x2*(min2-x2));
+		}
+		else
+		{
+			if (k > 0) min1 = 0;
+		}
+		if (min1 <= small)
+			min1 = small;
+		min2 = x2; fx = fm;
+		if (sf1 < fx)
+		{
+			fx = sf1;
+			min2 = sx1;
+		}
+		if (j != -1)
+		{
+			for (i=0; i < dim; i++)
+			{
+				x[i] += (min2)*v[i][j];
+			}
+			checkBounds(x);
+		}
+	}
+
+	// Look for a minimum along the curve q0, q1, q2
+	private void quadr()	
+	{
+		int i;
+		double l, s;
+
+		s = fx; fx = qf1; qf1 = s; qd1 = 0.0;
+		for (i=0; i < dim; i++)
+		{
+			s = x[i]; l = q1[i]; x[i] = l; q1[i] = s;
+			qd1 = qd1 + (s-l)*(s-l);
+		}
+		s = 0.0; qd1 = Math.sqrt(qd1); l = qd1;
+		if (qd0>0.0 && qd1>0.0 &&nl>=3*dim*dim)
+		{
+			min1 = s;
+			min2 = l;
+			min(-1, 2, qf1, true);
+			s = min1;
+			l = min2;
+			
+			qa = l*(l-qd1)/(qd0*(qd0+qd1));
+			qb = (l+qd0)*(qd1-l)/(qd0*qd1);
+			qc = l*(l+qd0)/(qd1*(qd0+qd1));
+		}
+		else
+		{
+			fx = qf1; qa = qb = 0.0; qc = 1.0;
+		}
+		qd0 = qd1;
+		for (i=0; i<dim; i++)
+		{
+			s = q0[i]; q0[i] = x[i];
+			x[i] = qa*s + qb*x[i] + qc*q1[i];
+		}
+		
+		checkBounds(x);
+	}
+
+	// Singular value decomposition
+	private void minfit(int n, double eps, double tol, double[][] ab, double[] q)
+	{
+		int l=0, kt, l2, i, j, k;
+		double c, f, g, h, s, x, y, z;
+
+		double[] e = new double[dim];
+
+
+		/* householder's reduction to bidiagonal form */
+		x = g = 0.0;
+		for (i=0; i<n; i++)
+		{
+			e[i] = g; s = 0.0; l = i+1;
+			for (j=i; j<n; j++)
+				s += ab[j][i] * ab[j][i];
+			if (s < tol)
+			{
+				g = 0.0;
+			}
+			else
+			{
+				f = ab[i][i];
+				if (f < 0.0) 
+					g = Math.sqrt(s);
+				else
+					g = -Math.sqrt(s);
+				h = f*g - s; ab[i][i] = f - g;
+				for (j=l; j<n; j++)
+				{
+					f = 0.0;
+					for (k=i; k<n; k++)
+						f += ab[k][i] * ab[k][j];
+					f /= h;
+					for (k=i; k<n; k++)
+						ab[k][j] += f * ab[k][i];
+				}
+			}
+			q[i] = g; s = 0.0;
+			if (i < n)
+				for (j=l; j<n; j++)
+					s += ab[i][j] * ab[i][j];
+			if (s < tol)
+			{
+				g = 0.0;
+			}
+			else
+		    	{
+				f = ab[i][i+1];
+				if (f < 0.0)
+					g = Math.sqrt(s);
+				else 
+					g = - Math.sqrt(s);
+				h = f*g - s;
+				ab[i][i+1] = f - g;
+				for (j=l; j<n; j++)
+			    		e[j] = ab[i][j]/h;
+				for (j=l; j<n; j++)
+				{
+					s = 0;
+					for (k=l; k<n; k++)
+						s += ab[j][k]*ab[i][k];
+					for (k=l; k<n; k++)
+						ab[j][k] += s * e[k];
+				}
+			}
+			y = Math.abs(q[i]) + Math.abs(e[i]);
+			if (y > x)
+				x = y;
+		}
+		/* accumulation of right hand transformations */
+		for (i=n-1; i >= 0; i--)
+		{
+			if (g != 0.0)
+			{
+				h = ab[i][i+1]*g;
+		   		for (j=l; j<n; j++) ab[j][i] = ab[i][j] / h;
+		    		for (j=l; j<n; j++)
+				{
+			   		s = 0.0;
+					for (k=l; k<n; k++) s += ab[i][k] * ab[k][j];
+					for (k=l; k<n; k++) ab[k][j] += s * ab[k][i];
+				}
+			}
+			for (j=l; j<n; j++)
+			ab[i][j] = ab[j][i] = 0.0;
+			ab[i][i] = 1.0; g = e[i]; l = i;
+		}
+		/* diagonalization to bidiagonal form */
+		eps *= x;
+		boolean converged = false;
+		for (k=n-1; k>= 0; k--)
+		{
+			kt = 0;
+
+			do
+			{
+				kt++;
+
+				boolean skipNext = false;
+				for (l2=k; l2>=0; l2--)
+				{
+					l = l2;
+					if (Math.abs(e[l]) <= eps)
+					{
+						skipNext = true;
+						break;
+					}
+			    
+					if (Math.abs(q[l-1]) <= eps)
+						break;
+				}
+		
+				if (skipNext == false)
+				{
+			
+					c = 0.0; s = 1.0;
+					for (i=l; i<=k; i++)
+					{
+						f = s * e[i]; e[i] *= c;
+						if (Math.abs(f) <= eps)
+							break;
+						g = q[i];
+						if (Math.abs(f) < Math.abs(g))
+						{
+							double fg = f/g;
+							h = Math.abs(g)*Math.sqrt(1.0+fg*fg);
+					   	}
+						else
+						{
+							double gf = g/f;
+							h = (f!=0.0 ? Math.abs(f)*Math.sqrt(1.0+gf*gf) : 0.0);
+						}
+						q[i] = h;
+						if (h == 0.0)
+						{
+							h = 1.0; g = 1.0;
+						}
+						c = g/h; s = -f/h;
+					}
+				}
+			
+				z = q[k];
+				if (l == k)
+				{
+					converged = true;
+					break;
+				}
+			
+			
+				/* shift from bottom 2x2 minor */
+				x = q[l]; y = q[k-l]; g = e[k-1]; h = e[k];
+				f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2.0*h*y);
+				g = Math.sqrt(f*f+1.0);
+				if (f <= 0.0)
+					f = ((x-z)*(x+z) + h*(y/(f-g)-h))/x;
+				else
+					f = ((x-z)*(x+z) + h*(y/(f+g)-h))/x;
+				/* next qr transformation */
+				s = c = 1.0;
+				for (i=l+1; i<=k; i++)
+				{
+					g = e[i]; y = q[i]; h = s*g; g *= c;
+					if (Math.abs(f) < Math.abs(h))
+					{
+						double fh = f/h;
+						z = Math.abs(h) * Math.sqrt(1.0 + fh*fh);
+					}
+					else
+					{
+						double hf = h/f;
+						z = (f!=0.0 ? Math.abs(f)*Math.sqrt(1.0+hf*hf) : 0.0);
+					}
+					e[i-1] = z;
+					if (z == 0.0) 
+						f = z = 1.0;
+					c = f/z; s = h/z;
+					f = x*c + g*s; g = - x*s + g*c; h = y*s;
+					y *= c;
+					for (j=0; j<n; j++)
+					{
+						x = ab[j][i-1]; z = ab[j][i];
+						ab[j][i-1] = x*c + z*s;
+						ab[j][i] = - x*s + z*c;
+					}
+					if (Math.abs(f) < Math.abs(h))
+					{
+						double fh = f/h;
+						z = Math.abs(h) * Math.sqrt(1.0 + fh*fh);
+					}
+					else
+					{
+						double hf = h/f;
+						z = (f!=0.0 ? Math.abs(f)*Math.sqrt(1.0+hf*hf) : 0.0);
+					}
+					q[i-1] = z;
+					if (z == 0.0)
+						z = f = 1.0;
+					c = f/z; s = h/z;
+					f = c*g + s*y; x = - s*g + c*y;
+				}
+				e[l] = 0.0; e[k] = f; q[k] = x;
+       
+       
+			} while (kt <= 30);
+       
+			if (!converged)
+			{
+				e[k] = 0.0;
+				System.out.println("\n+++ qr failed\n");
+				return;
+				//System.exit(1); //how rude of a library!
+			}
+
+ 
+			if (z < 0.0)
+			{
+				q[k] = - z;
+				for (j=0; j<n; j++)
+					ab[j][k] = - ab[j][k];
+			}
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/math/ConjugateGradientSearch.java b/LibrarySource/pal/math/ConjugateGradientSearch.java
new file mode 100644
index 0000000..583215a
--- /dev/null
+++ b/LibrarySource/pal/math/ConjugateGradientSearch.java
@@ -0,0 +1,492 @@
+// ConjugateGradientSearch.java
+//
+// (c) 2000-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * minimization of a real-valued function of
+ * several variables using a the nonlinear
+ * conjugate gradient method where several variants of the direction
+ * update are available (Fletcher-Reeves, Polak-Ribiere,
+ * Beale-Sorenson, Hestenes-Stiefel) and bounds are respected.
+ * Gradients are computed numerically if they are not supplied by the
+ * user.  The line search is entirely based on derivative
+ * evaluation, similar to the strategy used in macopt (Mackay).
+ *
+ * @version $Id: ConjugateGradientSearch.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ConjugateGradientSearch extends MultivariateMinimum
+{
+	//
+	// Public stuff
+	//
+
+	public final static int FLETCHER_REEVES_UPDATE = 0;
+	public final static int POLAK_RIBIERE_UPDATE = 1;
+	public final static int BEALE_SORENSON_HESTENES_STIEFEL_UPDATE = 2;
+
+	// Variables that control aspects of the inner workings of the
+	// minimization algorithm. Setting them is optional, they      
+	// are all set to some reasonable default values given below.
+
+	/**
+	 *  controls the printed output from the routine        
+	 *  (0 -> no output, 1 -> print only starting and final values,            
+	 *   2 -> detailed map of the minimisation process),
+	 *  the default value is 0
+	 */
+	public int prin = 0;
+	
+	/**
+	 * defaultStep is a steplength parameter and should be set equal     
+	 * to the expected distance from the solution (in a line search)          
+	 * exceptionally small or large values of defaultStep lead to   
+	 * slower convergence on the first few iterations (the step length
+	 * itself is adapted during search), the default value is 1.0                     
+	 */
+	public double defaultStep = 1.0;
+		
+
+	/**
+	 * conjugateGradientStyle determines the method for the
+	 * conjugate gradient direction update
+	 * update (0 -> Fletcher-Reeves, 1 -> Polak-Ribiere,
+	 * 2 -> Beale-Sorenson, Hestenes-Stiefel), the default is 2.
+	 */
+	public int conjugateGradientStyle = BEALE_SORENSON_HESTENES_STIEFEL_UPDATE;
+
+
+	public ConjugateGradientSearch() {
+	}
+
+	public ConjugateGradientSearch(int conGradStyle) {
+		this.conjugateGradientStyle = conGradStyle;
+	}
+
+
+	// implementation of abstract method
+
+	public void optimize(MultivariateFunction f, double[] x, double tolfx, double tolx)
+	{
+		xvec = x;
+		numArgs = f.getNumArguments();
+		
+		boolean numericalGradient;
+		if (f instanceof MFWithGradient)
+		{
+			numericalGradient = false;
+			fgrad = (MFWithGradient) f;
+		}
+		else
+		{
+			numericalGradient = true;
+			fgrad = null;
+		}
+		
+		
+		// line function
+		LineFunction lf = new LineFunction(f);
+		
+		// xvec contains current guess for minimum
+		lf.checkPoint(xvec);
+		double[] xold = new double[numArgs];
+		copy(xold, xvec);
+		
+		// function value and gradient at current guess
+		numFun = 0;
+		double fx;
+		numGrad = 0;
+		gvec = new double[numArgs];
+		if (numericalGradient)
+		{
+			fx = f.evaluate(xvec);
+			numFun++;
+			NumericalDerivative.gradient(f, xvec, gvec);
+			numFun += 2*numArgs;
+		}
+		else
+		{
+			fx = fgrad.evaluate(xvec, gvec);
+			numFun++;
+			numGrad++;
+		}
+		double[] gold = new double[numArgs];
+		copy(gold, gvec);
+
+		// init stop condition
+		stopCondition(fx, xvec, tolfx, tolx, true);
+
+		// currently active variables
+		boolean[] active = new boolean[numArgs];
+		double numActive = lf.checkVariables(xvec, gvec, active);
+		
+		// if no variables are active return
+		if (numActive == 0)
+		{
+			return;
+		}
+
+		// initial search direction (steepest descent)
+		sdir = new double[numArgs];
+		steepestDescentDirection(sdir, gvec, active);
+		lf.update(xvec, sdir);
+
+		// slope at start point in initial direction
+		double slope = gradientProjection(sdir, gvec);
+
+		
+		if (prin > 0)
+		{
+			System.out.println("--- starting minimization ---");
+			System.out.println("... current parameter settings ...");
+			System.out.println("...   tolx   ... " + tolx);
+			System.out.println("...   tolfx   ... " + tolfx);
+			System.out.println("... maxFun  ... " + maxFun);
+			System.out.println();
+			printVec("... start vector ...", xvec);
+			System.out.println();
+			printVec("... start direction ...", sdir);	
+		}
+		
+		
+		int numLin = 0;
+		lastStep = defaultStep;
+		while(true)
+		{
+			// determine an appropriate step length
+			double step = findStep(lf, fx, slope, numericalGradient);
+			lastStep = step;
+			numLin++;
+			
+			// update xvec
+			lf.getPoint(step, xvec);
+			lf.checkPoint(xvec);
+
+			
+			// function value at current guess
+			if (numericalGradient)
+			{
+				fx = f.evaluate(xvec);
+				numFun++;
+			}
+			else
+			{
+				// compute gradient as well
+				fx = fgrad.evaluate(xvec, gvec);
+				numFun++;
+				numGrad++;
+			}
+
+			// test for for convergence
+			if (stopCondition(fx, xvec, tolfx, tolx, false)
+				|| (maxFun > 0 && numFun > maxFun))
+			{
+				break;
+			}
+	
+			// Compute numerical gradient
+			if (numericalGradient)
+			{
+				NumericalDerivative.gradient(f, xvec, gvec);
+				numFun += 2*numArgs;
+			}
+			
+			
+			numActive = lf.checkVariables(xvec, gvec, active);
+			
+			// if all variables are inactive return
+			if (numActive == 0)
+			{
+				break;
+			}
+					
+			// determine new search direction
+			conjugateGradientDirection(sdir, gvec, gold, active);
+			lf.checkDirection(xvec, sdir);
+			
+			// compute slope in new direction
+			slope = gradientProjection(sdir, gvec);
+			
+			if (slope >= 0)
+			{
+				//reset to steepest descent direction
+				steepestDescentDirection(sdir, gvec, active);
+
+				// compute slope in new direction
+				slope = gradientProjection(sdir, gvec);
+				
+				// reset to default step length
+				lastStep = defaultStep;
+			}
+				
+			
+			// other updates
+			lf.update(xvec, sdir);
+			copy(xold, xvec);
+			copy(gold, gvec);
+			
+			if (prin > 1)
+			{
+				System.out.println();
+				System.out.println("Function value: " +
+				f.evaluate(xvec));
+				System.out.println();
+				printVec("... new vector ...", xvec);
+				System.out.println();
+				printVec("... new direction ...", sdir);	
+				System.out.println("... numFun  ... " + numFun);
+				if (!numericalGradient)
+				{
+					System.out.println("... numGrad  ... " + numGrad);
+				}
+				System.out.println("... numLin  ... " + numLin);
+				System.out.println();
+			}		
+		}
+		
+		if (prin > 0)
+		{
+			System.out.println();
+			printVec("... final vector ...", xvec);	
+			System.out.println("... numFun  ... " + numFun);
+			System.out.println("... numLin  ... " + numLin);
+			System.out.println();
+			System.out.println("--- end of minimization ---");
+		}
+	}
+                                                                	
+
+	//
+	// Private stuff
+	//
+	
+	private int numArgs, numGrad;
+	private double lastStep;
+	private double[] xvec, gvec, sdir;
+	private MFWithGradient fgrad;
+
+	private double findStep(LineFunction lf, double f0, double s0, boolean numericalGradient)
+	{
+		// f0 function value at step = 0
+		// s0 slope at step = 0
+	
+		double step;
+		double maxStep = lf.getUpperBound();
+		if (maxStep <= 0 || s0 == 0)
+		{
+			return 0.0;
+		}
+		
+		//step = Math.abs(lf.findMinimum());
+
+
+		// growing/shrinking factors for bracketing
+				
+		double g1 = 2.0;
+		double g2 = 1.25;
+		double g3 = 0.5;
+		
+		// x1 and x2 try to bracket the minimum
+
+		double x1 = 0;
+		double s1 = s0;
+		double x2 = lastStep*g2;
+		if(x2 > maxStep)
+		{
+			x2 = maxStep*g3;
+		}
+		double s2 = computeDerivative(lf, x2, numericalGradient);
+				
+		// we need to go further to bracket minimum
+		boolean boundReached = false;
+		while (s2 <= 0 && !boundReached) 
+		{
+			x1 = x2;
+			s1 = s2;
+			x2 = x2*g1;
+			if (x2 > maxStep)
+			{
+				x2 = maxStep;
+				boundReached = true;
+			}
+			s2 = computeDerivative(lf, x2, numericalGradient);
+		}
+		
+		// determine step length by quadratic interpolation
+		// for minimum in interval [x1,x2]
+		
+		if (s2 <= 0)
+		{
+			// true local minimum could NOT be bracketed
+			// instead we have a local minimum on a boundary 
+			
+			step = x2;
+		}
+		else
+		{
+			// minimum is bracketed
+			
+			step = (x1*s2-x2*s1)/(s2-s1);
+			// note that nominator is always positive
+		}			
+		
+		// just to be safe - should not be necessary
+		if (step >= maxStep)
+		{
+			step = maxStep;
+		}
+		if (step < 0)
+		{
+			step = 0;
+		}
+						
+		return step;
+	}
+
+	private double computeDerivative(LineFunction lf, double lambda, boolean numericalGradient)
+	{
+		if (numericalGradient)
+		{
+			numFun += 2;
+			return NumericalDerivative.firstDerivative(lf, lambda);
+		}
+		else
+		{
+			lf.getPoint(lambda, xvec);
+			lf.checkPoint(xvec);
+			fgrad.computeGradient(xvec, gvec);
+			numGrad++;
+			return gradientProjection(sdir, gvec);
+		}
+	}
+
+	private void testStep(double f0, double s0, double f1, double s1, double step)
+	{
+		// f0  function value at x=0
+		// s0  slope at x=0
+		
+		// f1 function value at x=step
+		// f2 function value at x=step
+		
+		double mue = 0.0001;
+		double eta = 0.9;
+		
+		// sufficent decrease in function value
+		if (f1 <= mue*s0*step + f0)
+		{
+			System.out.println("<<< Sufficient decrease in function value");
+		}
+		else
+		{
+			System.out.println("<<< NO sufficient decrease in function value");
+		}
+		
+		// sufficient decrease in slope
+		if (Math.abs(s1) <= eta*Math.abs(s0))
+		{
+			System.out.println("<<< Sufficient decrease in slope");
+		}
+		else
+		{
+			System.out.println("<<< NO sufficient decrease in slope");
+		}
+	}
+
+
+	private void conjugateGradientDirection(double[] sdir, double[] gvec, double[] gold,
+		boolean[] active)
+	{
+		double gg = 0;
+		double dgg = 0;
+		for (int i = 0; i < numArgs; i++)
+		{
+			if (active[i])
+			{
+				switch (conjugateGradientStyle)
+				{
+					case 0:
+						// Fletcher-Reeves
+						dgg += gvec[i]*gvec[i];
+						gg += gold[i]*gold[i];
+						break;
+	
+					case 1:
+						// Polak-Ribiere
+						dgg += gvec[i]*(gvec[i]-gold[i]);
+						gg += gold[i]*gold[i];
+						break;
+					
+					case 2:
+						// Beale-Sorenson
+						// Hestenes-Stiefel
+						dgg += gvec[i] * (gvec[i] - gold[i]);
+						gg += sdir[i] * (gvec[i] - gold[i]);
+						break;
+				}
+			}
+		}
+		double beta = dgg/gg;
+		if (beta < 0 || gg == 0)
+		{
+			// better convergence (Gilbert and Nocedal)
+			beta = 0;
+		}
+		for (int i = 0; i < numArgs; i++)
+		{
+			if (active[i])
+			{
+				sdir[i] = -gvec[i] + beta*sdir[i];
+			}
+			else
+			{
+				sdir[i] = 0;
+			}
+		}
+	}
+
+	private void steepestDescentDirection(double[] sdir, double[] gvec, boolean[] active)
+	{
+		for (int i = 0; i < numArgs; i++)
+		{
+			if (active[i])
+			{
+				sdir[i] = -gvec[i];
+			}
+			else
+			{
+				sdir[i] = 0;
+			}
+		}
+	}
+
+	private double gradientProjection(double[] sdir, double[] gvec)
+	{
+		double s = 0;
+		double n = gvec.length;
+		for (int i = 0; i < n; i++)
+		{
+			s += gvec[i]*sdir[i];
+		}
+		
+		return s;
+	}
+	
+	private void printVec(String s, double[] x)
+	{
+		System.out.println(s);
+		for (int i=0; i < x.length; i++)
+		{
+			System.out.print(x[i] + "  ");
+		}
+		System.out.println();
+	}
+}
+
diff --git a/LibrarySource/pal/math/DifferentialEvolution.java b/LibrarySource/pal/math/DifferentialEvolution.java
new file mode 100644
index 0000000..85b6899
--- /dev/null
+++ b/LibrarySource/pal/math/DifferentialEvolution.java
@@ -0,0 +1,371 @@
+// DifferentialEvolution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+//  Price, K., and R. Storn.  1997.  Differential evolution: a simple
+//  strategy for fast optimization.  Dr. Dobb's Journal 264(April), pp. 18-24.
+//  Strategy used here:  DE/rand-to-best/1/bin
+//  http://www.icsi.berkeley.edu/~storn/code.html
+
+
+package pal.math;
+
+
+/**
+ * <b>global</b> minimization of a real-valued function of several
+ * variables without using derivatives using a genetic algorithm
+ * (Differential Evolution)
+ * @author Korbinian Strimmer
+ */
+public class DifferentialEvolution extends MultivariateMinimum
+{
+	//
+	// Public stuff
+	//
+        
+	// Variables that control aspects of the inner workings of the
+        // minimization algorithm. Setting them is optional, they      
+        // are all set to some reasonable default values given below.        
+
+	/** weight factor (default 0.7) */
+	public double F = 0.7 /* 0.5*/;
+	
+	/** Crossing over factor (default 0.9) */
+	public double CR = 0.9 /*1.0*/;
+		
+	/**
+	 * variable controlling print out, default value = 0
+	 * (0 -> no output, 1 -> print final value, 
+	 * 2 -> detailed map of optimization process)
+	 */
+	public int prin = 0; 
+
+
+	/**
+	 * construct DE optimization modul (population size is
+	 * selected automatically)
+	 *
+	 * <p><em>DE web page:</em> 
+	 * <a href="http://www.icsi.berkeley.edu/~storn/code.html"
+	 * >http://www.icsi.berkeley.edu/~storn/code.html</a> 
+         *
+	 * @param dim dimension of optimization vector 
+	 */ 
+	public DifferentialEvolution (int dim)
+	{
+		this(dim, 5*dim);
+	}
+
+	/**
+	 * construct optimization modul
+	 *
+	 * @param dim dimension of optimization vector
+	 * @param popSize population size 
+	 */ 	
+	public DifferentialEvolution (int dim, int popSize) 
+	{
+		// random number generator
+		rng = new MersenneTwisterFast();
+		
+		// Dimension and Population size
+		dimension = dim;
+		populationSize = popSize;
+		
+		numFun = 0;		
+		
+		// Allocate memory
+		currentPopulation = new double[populationSize][dimension];
+		nextPopulation = new double[populationSize][dimension];
+		costs = new double[populationSize];
+		trialVector = new double[dimension];
+				
+		// helper variable
+		//numr = 5; // for strategy DE/best/2/bin
+		numr = 3; // for stragey DE/rand-to-best/1/bin
+		r = new int[numr]; 
+	}
+	
+	
+	// implementation of abstract method 
+	
+	public void optimize(MultivariateFunction func, double[] xvec, double tolfx, double tolx)
+	{
+		f = func;
+		x = xvec;
+	
+		// Create first generation
+		firstGeneration ();
+		
+		stopCondition(fx, x, tolfx, tolx, true);
+			
+		while (true)
+		{
+			boolean xHasChanged;
+			do
+			{
+				xHasChanged = nextGeneration ();
+				
+				if (maxFun > 0 && numFun > maxFun)
+				{
+					break;
+				}
+
+				if (prin > 1 && currGen % 20 == 0)
+				{
+					printStatistics();
+				}
+			}
+			while (!xHasChanged);
+			
+			
+			if (stopCondition(fx, x, tolfx, tolx, false) || 
+				(maxFun > 0 && numFun > maxFun))
+			{
+				break;		
+			}
+		}
+		
+		if (prin > 0) printStatistics();
+	}
+	
+	//
+	// Private stuff
+	//
+
+	private MultivariateFunction f;
+	private int currGen;
+	private double fx;
+	private double[] x;
+	
+	// Dimension
+	private int dimension;
+	
+	// Population size
+	private int populationSize; 
+			
+	// Population data
+	private double trialCost;
+	private double[] costs;
+	private double[] trialVector;
+	private double[][] currentPopulation;
+	private double[][] nextPopulation;
+
+	// Random number generator
+	private MersenneTwisterFast rng;
+	
+	// Helper variable
+	private int numr;
+	private int[] r;
+	
+	private void printStatistics()
+	{
+		// Compute mean
+		double meanCost = 0.0;
+		for (int i = 0; i < populationSize; i++)
+		{
+			meanCost += costs[i];
+		}
+		meanCost = meanCost/populationSize;
+				
+		// Compute variance
+		double varCost = 0.0;
+		for (int i = 0; i < populationSize; i++)
+		{
+			double tmp = (costs[i]-meanCost);
+			varCost += tmp*tmp;
+		}
+		varCost = varCost/(populationSize-1);
+			
+		System.out.println();
+		System.out.println();
+		System.out.println();
+		System.out.println("Smallest value: " + fx);
+		System.out.println();
+		for (int k = 0; k < dimension; k++)
+		{
+			System.out.println("x[" + k + "] = " + x[k]);
+		}
+		System.out.println();
+		System.out.println("Current Generation: " + currGen);
+		System.out.println("Function evaluations: " + numFun);
+		System.out.println("Populations size (populationSize): " + populationSize);
+		System.out.println("Average value: " + meanCost);
+		System.out.println("Variance: " + varCost);
+
+		System.out.println("Weight factor (F): " + F);
+		System.out.println("Crossing-over (CR): " + CR);
+		System.out.println();
+	}
+	
+	// Generate starting population
+	private void firstGeneration()
+	{
+		currGen = 1;
+		
+		// Construct populationSize random start vectors
+		for (int i = 0; i < populationSize; i++)
+		{
+			for (int j = 0; j < dimension; j++ )
+			{
+				double min = f.getLowerBound(j);
+				double max = f.getUpperBound(j);
+				
+				double diff = max - min;
+				
+				// Uniformly distributed sample points
+				currentPopulation[i][j] = min + diff*rng.nextDouble();
+			}
+			costs[i] = f.evaluate(currentPopulation[i]);
+		}
+		numFun += populationSize;
+		
+		findSmallestCost ();
+	}
+	
+	// check whether a parameter is out of range
+	private double checkBounds(double param, int numParam)
+	{
+		if (param < f.getLowerBound(numParam))
+		{
+			return f.getLowerBound(numParam);
+		}
+		else if (param > f.getUpperBound(numParam))
+		{
+			return f.getUpperBound(numParam);
+		}
+		else
+		{
+			return param;
+		}
+	}
+	
+	// Generate next generation
+	private boolean nextGeneration()
+	{
+		boolean updateFlag = false;
+		int best = 0; // to avoid compiler complaints
+		double[][] swap;
+		
+		currGen++;
+		
+		// Loop through all population vectors
+		for (int r0 = 0; r0 < populationSize; r0++)
+		{
+			// Choose ri so that r0 != r[1] != r[2] != r[3] != r[4] ...
+		
+			r[0] = r0;			
+			for (int k = 1; k < numr; k++)
+			{
+				r[k] = randomInteger (populationSize-k);
+				for (int l = 0; l < k; l++)
+				{
+					if (r[k] >= r[l])
+					{
+						r[k]++;
+					}
+				}
+			}
+			
+			copy(trialVector, currentPopulation[r0]);
+			int n = randomInteger (dimension); 
+			for (int i = 0; i < dimension; i++) // perform binomial trials
+			{
+				// change at least one parameter
+				if (rng.nextDouble() < CR || i == dimension - 1)
+				{                       
+					// DE/rand-to-best/1/bin
+					// (change to 'numr=3' in constructor when using this strategy)
+					trialVector[n] = trialVector[n] +
+						F*(x[n] - trialVector[n]) +
+						F*(currentPopulation[r[1]][n] - currentPopulation[r[2]][n]);
+
+					//DE/rand-to-best/2/bin
+					//double K = rng.nextDouble();
+					//trialVector[n] = trialVector[n] +
+					//	K*(x[n] - trialVector[n]) +
+					//	F*(currentPopulation[r[1]][n] - currentPopulation[r[2]][n]);
+					
+							     
+	       				// DE/best/2/bin
+					// (change to 'numr=5' in constructor when using this strategy)
+	       				//trialVector[n] = x[n] + 
+		     			//	 (currentPopulation[r[1]][n]+currentPopulation[r[2]][n]
+					//	 -currentPopulation[r[3]][n]-currentPopulation[r[4]][n])*F;
+				}
+				n = (n+1) % dimension;
+			}
+
+			// make sure that trial vector obeys boundaries
+			for (int i = 0; i < dimension; i++)
+			{
+				trialVector[i] = checkBounds(trialVector[i], i);
+			}
+			
+			
+			// Test this choice
+			trialCost = f.evaluate(trialVector);
+			if (trialCost < costs[r0])
+			{
+				// Better than old vector
+				costs[r0] = trialCost;
+				copy(nextPopulation[r0], trialVector);
+				
+				// Check for new best vector
+				if (trialCost < fx)
+				{
+					fx = trialCost;
+					best = r0;
+					updateFlag = true;
+				}
+			}
+			else
+			{
+				// Keep old vector
+				copy(nextPopulation[r0], currentPopulation[r0]);
+			}			
+		}
+		numFun += populationSize;
+		
+		// Update best vector
+		if (updateFlag)
+		{
+			copy(x, nextPopulation[best]);
+		}
+		
+		// Switch pointers
+		swap = currentPopulation;
+		currentPopulation = nextPopulation;
+		nextPopulation = swap;
+		
+		return updateFlag;
+	}
+	
+	// Determine vector with smallest cost in current population
+	private void findSmallestCost()
+	{
+		int best = 0;
+		fx = costs[0];
+		
+		for (int i = 1; i < populationSize; i++)
+		{
+			if (costs[i] < fx)
+			{
+				fx = costs[i];
+				best = i;
+			}
+		}
+		copy(x, currentPopulation[best]);
+	}
+	
+	// draw random integer in the range from 0 to n-1
+	private int randomInteger(int n)
+	{
+		return rng.nextInt(n);
+	}
+}
+
+
diff --git a/LibrarySource/pal/math/ErrorFunction.java b/LibrarySource/pal/math/ErrorFunction.java
new file mode 100644
index 0000000..b0b81f4
--- /dev/null
+++ b/LibrarySource/pal/math/ErrorFunction.java
@@ -0,0 +1,104 @@
+// ErrorFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * error function and related stuff
+ *
+ * @version $Id: ErrorFunction.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ErrorFunction
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * error function
+	 *
+	 * @param x argument
+	 *
+	 * @return function value
+	 */
+	public static double erf(double x)
+	{
+		if (x > 0.0)
+		{
+			return GammaFunction.incompleteGammaP(0.5, x*x);
+		}
+		else if (x < 0.0)
+		{
+			return -GammaFunction.incompleteGammaP(0.5, x*x);
+		}
+		else
+		{
+			return 0.0;
+		}
+	}
+	
+	/**
+	 * complementary error function = 1-erf(x)
+	 *
+	 * @param x argument
+	 *
+	 * @return function value
+	 */
+	public static double erfc(double x)
+	{
+		return 1.0-erf(x);
+	}
+
+	
+	/**
+	 * inverse error function
+	 *
+	 * @param z argument
+	 *
+	 * @return function value
+	 */
+	public static double inverseErf(double z)
+	{
+		return pointNormal(0.5*z+0.5)/Math.sqrt(2.0);
+	}
+
+
+	// Private
+
+	// Returns z so that Prob{x<z}=prob where x ~ N(0,1) and (1e-12) < prob<1-(1e-12)
+	private static double pointNormal(double prob)
+	{
+		// Odeh RE & Evans JO (1974) The percentage points of the normal distribution.
+		// Applied Statistics 22: 96-97 (AS70)
+	
+		// Newer methods:
+		// Wichura MJ (1988) Algorithm AS 241: the percentage points of the
+		// normal distribution.  37: 477-484.
+		// Beasley JD & Springer SG  (1977).  Algorithm AS 111: the percentage 
+		// points of the normal distribution.  26: 118-121.
+	
+		double a0 = -0.322232431088, a1 = -1, a2 = -0.342242088547, a3 = -0.0204231210245;
+		double a4 = -0.453642210148e-4, b0 = 0.0993484626060, b1 = 0.588581570495;
+		double b2 = 0.531103462366, b3 = 0.103537752850, b4 = 0.0038560700634;
+		double y, z = 0, p = prob, p1;
+	
+		p1 = (p < 0.5 ? p : 1-p);
+		if (p1 < 1e-20)
+		{
+			new IllegalArgumentException("Argument prob out of range");
+		}
+	
+		y = Math.sqrt(Math.log(1/(p1*p1)));   
+		z = y + ((((y*a4+a3)*y+a2)*y+a1)*y+a0)/((((y*b4+b3)*y+b2)*y+b1)*y+b0);
+		return (p < 0.5 ? -z : z);
+	}
+}
+
diff --git a/LibrarySource/pal/math/GammaFunction.java b/LibrarySource/pal/math/GammaFunction.java
new file mode 100644
index 0000000..f94c9b3
--- /dev/null
+++ b/LibrarySource/pal/math/GammaFunction.java
@@ -0,0 +1,205 @@
+// GammaFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * gamma function
+ *
+ * @version $Id: GammaFunction.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class GammaFunction
+{
+	//
+	// Public stuff
+	//
+		
+
+	// Gamma function
+
+	/**
+	 * log Gamma function: ln(gamma(alpha)) for alpha>0, accurate to 10 decimal places
+	 *
+	 * @param alpha argument
+	 * 
+	 * @param function value
+	 */
+	public static double lnGamma(double alpha)
+	{
+		// Pike MC & Hill ID (1966) Algorithm 291: Logarithm of the gamma function.
+		// Communications of the Association for Computing Machinery, 9:684
+
+		double x = alpha, f = 0.0, z;
+
+		if (x < 7)
+		{
+			f = 1;
+			z = x-1;
+			while (++z < 7)
+			{
+				f *= z;
+			}
+			x = z;
+			f = -Math.log(f);
+		}
+		z = 1/(x*x);
+		
+		return
+			f + (x-0.5)*Math.log(x) - x + 0.918938533204673 +
+			(((-0.000595238095238*z+0.000793650793651) *
+			z-0.002777777777778)*z + 0.083333333333333)/x;  
+	}
+
+	/**
+	 * Incomplete Gamma function Q(a,x)
+	 * (a cleanroom implementation of Numerical Recipes gammq(a,x);
+	 * in Mathematica this function is called GammaRegularized)
+	 *
+	 * @param a parameter
+	 * @param x argument
+	 *
+	 * @return function value
+	 */
+	public static double incompleteGammaQ(double a, double x)
+	{
+		return 1.0 - incompleteGamma(x, a, lnGamma(a));
+	}
+	
+	/**
+	 * Incomplete Gamma function P(a,x) = 1-Q(a,x)
+	 * (a cleanroom implementation of Numerical Recipes gammp(a,x);
+	 * in Mathematica this function is 1-GammaRegularized)
+	 *
+	 * @param a parameter
+	 * @param x argument
+	 *
+	 * @return function value
+	 */
+	public static double incompleteGammaP(double a, double x)
+	{
+		return incompleteGamma(x, a, lnGamma(a));
+	}
+
+	/**
+	 * Incomplete Gamma function P(a,x) = 1-Q(a,x)
+	 * (a cleanroom implementation of Numerical Recipes gammp(a,x);
+	 * in Mathematica this function is 1-GammaRegularized)
+	 *
+	 * @param a parameter
+	 * @param x argument
+	 * @param double lnGammaA precomputed lnGamma(a) 
+	 *
+	 * @return function value
+	 */
+	public static double incompleteGammaP(double a, double x, double lnGammaA)
+	{
+		return incompleteGamma(x, a, lnGammaA);
+	}
+
+
+	/**
+	 * Returns the incomplete gamma ratio I(x,alpha) where x is the upper 
+	 * limit of the integration and alpha is the shape parameter.
+	 */
+	private static double incompleteGamma(double x, double alpha, double ln_gamma_alpha)
+	{
+		// (1) series expansion     if (alpha>x || x<=1)
+		// (2) continued fraction   otherwise
+		// RATNEST FORTRAN by
+		// Bhattacharjee GP (1970) The incomplete gamma integral.  Applied Statistics,
+		// 19: 285-287 (AS32)
+	
+		int i;
+		double p = alpha, g = ln_gamma_alpha;
+		double accurate = 1e-8, overflow = 1e30;
+		double factor, gin = 0, rn = 0, a = 0,b = 0,an = 0, dif = 0, term = 0;
+		double pn0, pn1, pn2, pn3, pn4, pn5;
+	
+		if (x == 0.0)
+		{
+			return 0.0;
+		}
+		if ( x < 0.0 || p <= 0.0)
+		{
+			throw new IllegalArgumentException("Arguments out of bounds");
+		}
+	
+		factor = Math.exp(p*Math.log(x)-x-g);   
+	
+		if (x > 1 && x >= p)
+		{
+			// continued fraction
+			a = 1-p;
+			b = a+x+1;
+			term = 0;
+			pn0 = 1;
+			pn1 = x;
+			pn2 = x+1;
+			pn3 = x*b;
+			gin = pn2/pn3;
+	 
+	 		do
+			{
+				a++;
+				b += 2;
+				term++;
+				an = a*term;
+				pn4 = b*pn2-an*pn0;
+				pn5 = b*pn3-an*pn1;
+
+				if (pn5 != 0)
+				{
+					rn = pn4/pn5;
+					dif = Math.abs(gin-rn);
+					if (dif <= accurate)
+					{
+						if (dif <= accurate*rn)
+						{
+							break;
+						}
+	 				}
+	 
+					gin=rn;
+				}
+				pn0 = pn2;
+				pn1 = pn3;
+				pn2 = pn4;
+				pn3 = pn5;
+				if (Math.abs(pn4) >= overflow)
+				{
+					pn0 /= overflow;
+					pn1 /= overflow;
+					pn2 /= overflow;
+					pn3 /= overflow;
+				}
+			} while (true);
+			gin = 1-factor*gin;
+		}
+		else
+		{
+			// series expansion
+			gin = 1;
+			term = 1;
+			rn = p;
+	 		do
+			{
+				rn++;
+				term *= x/rn;
+				gin += term;
+			}
+			while (term > accurate);
+			gin *= factor/p;
+		}
+		return gin;
+	}
+	
+}
+
diff --git a/LibrarySource/pal/math/GeneralizedDEOptimizer.java b/LibrarySource/pal/math/GeneralizedDEOptimizer.java
new file mode 100644
index 0000000..f9731bc
--- /dev/null
+++ b/LibrarySource/pal/math/GeneralizedDEOptimizer.java
@@ -0,0 +1,51 @@
+// GeneralizedDEOptimizer.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.math;
+
+
+/**
+ * Provides an general interface to the DifferentialEvolution class that is not
+ * tied to a certain number of parameters (as DifferentialEvolution is). Works but
+ * creating a new DiffentialEvolution engine when presented with a new number of
+ * parameters. All the actual optimisation work is handled by DifferentialEvolution.,
+ * @author Matthew Goode
+ */
+
+
+public class GeneralizedDEOptimizer extends MultivariateMinimum {
+
+	private DifferentialEvolution optimiser_;
+
+  private int currentNumberOfParameters_ = 0;
+
+	public GeneralizedDEOptimizer() {
+	}
+
+
+
+	/**
+	 * The actual optimization routine
+	 * It finds a minimum close to vector x when the
+	 * absolute tolerance for each parameter is specified.
+         *
+	 * @param f multivariate function
+	 * @param xvec initial guesses for the minimum
+	 *         (contains the location of the minimum on return)
+	 * @param tolfx absolute tolerance of function value
+	 * @param tolx absolute tolerance of each parameter
+ 	 */
+	public void optimize(MultivariateFunction f, double[] xvec, double tolfx, double tolx) {
+   	if(optimiser_==null||xvec.length!=currentNumberOfParameters_) {
+     	optimiser_ = new DifferentialEvolution(xvec.length);
+      this.currentNumberOfParameters_= xvec.length;
+    }
+    optimiser_.optimize(f,xvec,tolfx, tolx);
+  }
+
+}
+
diff --git a/LibrarySource/pal/math/LineFunction.java b/LibrarySource/pal/math/LineFunction.java
new file mode 100644
index 0000000..871889b
--- /dev/null
+++ b/LibrarySource/pal/math/LineFunction.java
@@ -0,0 +1,295 @@
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+/**
+ * converts a multivariate function into a univariate function
+ *
+ * @author Korbinian Strimmer
+ */
+public class LineFunction implements UnivariateFunction
+{
+	/**
+	 * construct univariate function from multivariate function
+	 *
+	 * @param func multivariate function
+	 * @param start start point
+	 * @param dir direction vector
+	 */
+	public LineFunction(MultivariateFunction func)
+	{
+		f = func;
+		
+		dim = f.getNumArguments();
+		
+		x = new double[dim];
+	}
+
+	/**
+	 * update start point and direction
+	 * (bounds and search direction are NOT checked)
+	 *
+	 * @param start new start point
+	 * @param dir new direction vector
+	 */
+	public void update(double[] start, double[] dir)
+	{
+		s = start;
+		d = dir;
+		
+		computeBounds();
+	}
+
+	
+	/**
+	 * get point associated with the one-dimensional parameter
+	 * (bounds of of multivariate function are NOT checked)
+	 *
+	 * @param lambda argument
+	 * @param p array for coordinates of corresponding point
+	 */  
+	public void getPoint(double lambda, double[] p)
+	{
+		for (int i = 0; i < dim; i++)
+		{
+			p[i] = s[i] + lambda*d[i];
+		}
+	}
+
+	
+	// implementation of UnivariateFunction
+	
+	/**
+	 * evaluate f(start+lambda*dir)
+	 */
+	public double evaluate(double lambda)
+	{
+		getPoint(lambda, x);
+		
+		return f.evaluate(x);
+	}
+
+	public double getLowerBound()
+	{		
+		return lowerBound;
+	}
+
+	public double getUpperBound()
+	{
+		return upperBound;
+	}
+	
+	/**
+	 * find parameter lambda within the given bounds
+	 * that minimizes the univariate function
+	 * (due to numerical inaccuaries it may happen
+	 * that getPoint for the returned lambda produces
+	 * a point that lies
+	 * slightly out of bounds)
+	 *
+	 * @return lambda that achieves minimum
+	 */
+	public double findMinimum()
+	{
+		if (um == null)
+		{
+			um = new UnivariateMinimum();
+		}
+		return um.findMinimum(this);
+	}
+
+
+	/**
+	 * get parameter that limits the upper bound
+	 *
+	 * @return parameter number 
+	 */
+	public int getUpperBoundParameter()
+	{
+		return upperBoundParam;
+	}
+
+	/**
+	 * get parameter that limits the lower bound
+	 *
+	 * @return parameter number 
+	 */
+	public int getLowerBoundParameter()
+	{
+		return lowerBoundParam;
+	}
+
+
+	/**
+	 * check (and modify, if necessary) whether a point lies properly
+	 * within the predefined bounds
+	 *
+	 * @param p coordinates of point
+	 *
+	 * @return true if p was modified, false otherwise
+	 */
+	public boolean checkPoint(double[] p)
+	{
+		boolean modified = false; 
+		for (int i = 0; i < dim; i++)
+		{
+			if (p[i] < f.getLowerBound(i))
+			{
+				p[i] = f.getLowerBound(i);
+				modified = true;
+			}
+			if (p[i] > f.getUpperBound(i))
+			{
+				p[i] = f.getUpperBound(i);
+				modified = true;
+			}
+		}
+		
+		return modified;
+	}
+
+	/**
+	 * determine active variables at a point p and corresponding
+	 * gradient grad (if a component of p lies on a border and
+	 * the corresponding component of the gradient points
+	 * out of the border the variable is considered inactive)
+	 *
+	 * @param p coordinates of point
+	 * @param grad gradient at that point
+	 * @param list of active variables (on return)
+	 *
+	 * @return number of active variables
+	 */
+	public int checkVariables(double[] p, double[] grad, boolean[] active)
+	{
+		// this seems to be a reasonable small value
+		double EPS = MachineAccuracy.SQRT_EPSILON;
+		
+		int numActive = 0;
+		for (int i = 0; i < dim; i++)
+		{
+			active[i] = true;
+			if (p[i] <= f.getLowerBound(i)+EPS)
+			{
+				// no search towards lower boundary
+				if (grad[i] > 0) 
+				{
+					active[i] = false;
+				}
+			}
+			else if (p[i] >= f.getUpperBound(i)-EPS)
+			{
+				// no search towards upper boundary
+				if (grad[i] < 0)
+				{
+					active[i] = false;
+				}
+			}
+			else
+			{
+				numActive++;
+			}
+		}
+		
+		return numActive;
+	}
+
+	/**
+	 * check direction vector. If it points out of the defined
+	 * area at a point at the boundary the corresponding component
+	 * of the direction vector is set to zero. 
+	 *
+	 * @param p coordinates of point
+	 * @param dir direction vector at that point
+	 *
+	 * @return number of changed components in direction vector
+	 */
+	public int checkDirection(double[] p, double[] dir)
+	{
+		// this seems to be a reasonable small value
+		double EPS = MachineAccuracy.SQRT_EPSILON;
+		
+		int numChanged = 0;
+		for (int i = 0; i < dim; i++)
+		{
+			if (p[i] <= f.getLowerBound(i)+EPS)
+			{
+				// no search towards lower boundary
+				if (dir[i] < 0) 
+				{
+					dir[i] = 0;
+					numChanged++;
+				}
+			}
+			else if (p[i] >= f.getUpperBound(i)-EPS)
+			{
+				// no search towards upper boundary
+				if (dir[i] > 0)
+				{
+					dir[i] = 0;
+					numChanged++;
+				}
+			}
+		}
+		
+		return numChanged;
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private MultivariateFunction f;
+	private int lowerBoundParam, upperBoundParam;
+	private int dim;
+	private double lowerBound, upperBound;
+	private double[] s, d, x, min, max;
+	private UnivariateMinimum um = null;
+	
+	private void computeBounds()
+	{
+		boolean firstVisit = true;
+		for (int i = 0; i < dim; i++)
+		{
+			if (d[i] != 0)
+			{
+				double upper = (f.getUpperBound(i) - s[i])/d[i];
+				double lower = (f.getLowerBound(i) - s[i])/d[i];			
+				if (lower > upper)
+				{
+					double tmp = upper;
+					upper = lower;
+					lower = tmp;
+				}
+				
+				if (firstVisit)
+				{
+					lowerBound = lower;
+					lowerBoundParam = i;
+					upperBound = upper;
+					upperBoundParam = i;
+					firstVisit = false;
+				}
+				else
+				{
+					if (lower > lowerBound)
+					{
+						lowerBound = lower;
+						lowerBoundParam = i;
+					}
+					if (upper < upperBound)
+					{
+						upperBound = upper;
+						upperBoundParam = i;
+					}
+				}
+			}
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/math/MFWithGradient.java b/LibrarySource/pal/math/MFWithGradient.java
new file mode 100644
index 0000000..b07dc25
--- /dev/null
+++ b/LibrarySource/pal/math/MFWithGradient.java
@@ -0,0 +1,39 @@
+// MFWithGradient.java
+//
+// (c) 2000-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * interface for a function of several variables with a gradient
+ *
+ * @version $Id: MFWithGradient.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface MFWithGradient extends MultivariateFunction
+{
+	/**
+	 * compute both function value and gradient at a point
+	 *
+	 * @param argument  function argument (vector)
+	 * @param gradient  gradient (on return)
+	 *
+	 * @return function value
+	 */
+	double evaluate(double[] argument, double[] gradient);
+	
+	/**
+	 * compute gradient at a point
+	 *
+	 * @param argument  function argument (vector)
+	 * @param gradient  gradient (on return)
+	 */
+	void computeGradient(double[] argument, double[] gradient);
+}
+
diff --git a/LibrarySource/pal/math/MachineAccuracy.java b/LibrarySource/pal/math/MachineAccuracy.java
new file mode 100644
index 0000000..a3ad129
--- /dev/null
+++ b/LibrarySource/pal/math/MachineAccuracy.java
@@ -0,0 +1,45 @@
+// MachineAccuracy.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * determines machine accuracy
+ *
+ * @version $Id: MachineAccuracy.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class MachineAccuracy
+{
+	//
+	// Public stuff
+	//
+
+	/** machine accuracy constant */
+	public static double EPSILON = 2.220446049250313E-16;
+	
+	public static double SQRT_EPSILON = 1.4901161193847656E-8;
+	public static double SQRT_SQRT_EPSILON = 1.220703125E-4;
+
+	/** compute EPSILON from scratch */
+	public static double computeEpsilon()
+	{
+		double eps = 1.0;
+
+		while( eps + 1.0 != 1.0 )
+		{
+			eps /= 2.0;
+		}
+		eps *= 2.0;
+		
+		return eps;
+	}
+}
+
diff --git a/LibrarySource/pal/math/MathUtils.java b/LibrarySource/pal/math/MathUtils.java
new file mode 100644
index 0000000..f8f1de1
--- /dev/null
+++ b/LibrarySource/pal/math/MathUtils.java
@@ -0,0 +1,67 @@
+// MathUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * Handy utility functions which have some Mathematical relavance.
+ *
+ * @author Matthew Goode
+ * @author Alexei Drummon
+ *
+ * @version $Id: MathUtils.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ */
+
+
+public class MathUtils {
+
+	public MathUtils() {}
+
+	/**
+	 * A random number generator that is initialized with the clock when this
+	 * class is loaded into the JVM. Use this for all random numbers.
+	 */
+	public static MersenneTwisterFast random = new MersenneTwisterFast();
+
+	/**
+	 * @return a new double array where all the values sum to 1. 
+	 * Relative ratios are preserved.
+	 */
+	public static final double[] getNormalized(double[] array) {
+		double[] newArray = new double[array.length];
+		double total = getTotal(array);
+		for(int i = 0 ; i < array.length ; i++) {
+			newArray[i] = array[i]/total;
+		}
+		return newArray;
+	}
+
+	/**
+	 * @param end the index of the element after the last one to be included
+	 * @return the total of a the values in a range of an array
+	 */
+	public static final double getTotal(double[] array, int start, int end) {
+		double total = 0.0;
+		for(int i = start ; i < array.length ; i++) {
+			total+=array[i];
+		}
+		return total;
+	}
+	
+	/**
+	 * @return the total of the values in an array
+	 */
+	public static final double getTotal(double[] array) {
+		return getTotal(array,0, array.length);
+
+	}
+
+
+}
+
diff --git a/LibrarySource/pal/math/MersenneTwisterFast.java b/LibrarySource/pal/math/MersenneTwisterFast.java
new file mode 100644
index 0000000..9352c55
--- /dev/null
+++ b/LibrarySource/pal/math/MersenneTwisterFast.java
@@ -0,0 +1,771 @@
+// MersenneTwisterFast.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+
+// Original file MersenneTwisterFast.java
+// (c) 1999-2000 by Michael Lecuyer and Sean Luke
+// see also http://www.cs.umd.edu/users/seanl/
+
+
+package pal.math;
+
+import java.io.*;
+import java.util.*;
+
+
+/** 
+ * MersenneTwisterFast:
+ *
+ * A simulation quality fast random number generator (MT19937)
+ * with the  same public methods as java.util.Random.
+ 
+ * <p>About the Mersenne Twister.
+ * This is a Java version of the C-program for MT19937: Integer version.
+ * next(32) generates one pseudorandom unsigned integer (32bit)
+ * which is uniformly distributed among 0 to 2^32-1  for each
+ * call.  next(int bits) >>>'s by (32-bits) to get a value ranging
+ * between 0 and 2^bits-1 long inclusive; hope that's correct.
+ * setSeed(seed) set initial values to the working area
+ * of 624 words. For setSeed(seed), seed is any 32-bit integer 
+ * except for 0.
+ *<p>
+ * Reference. 
+ * M. Matsumoto and T. Nishimura,
+ * "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform
+ * Pseudo-Random Number Generator",
+ * <i>ACM Transactions on Modeling and Computer Simulation,</i>
+ * Vol. 8, No. 1, January 1998, pp 3--30.
+ *
+ * <p>Bug Fixes. This implementation implements the bug fixes made
+ * in Java 1.2's version of Random, which means it can be used with
+ * earlier versions of Java.  See 
+ * <a href="http://www.javasoft.com/products/jdk/1.2/docs/api/java/util/Random.html">
+ * the JDK 1.2 java.util.Random documentation</a> for further documentation
+ * on the random-number generation contracts made.  Additionally, there's
+ * an undocumented bug in the JDK java.util.Random.nextBytes() method,
+ * which this code fixes.
+ *
+ * <p> Important Note.  Just like java.util.Random, this
+ * generator accepts a long seed but doesn't use all of it.  java.util.Random
+ * uses 48 bits.  The Mersenne Twister instead uses 32 bits (int size).
+ * So it's best if your seed does not exceed the int range.
+ *
+ * <p><a href="http://www.cs.umd.edu/users/seanl/">Sean Luke's web page</a>
+ *
+ * <P>
+ * - added shuffling method (Alexei Drummond)
+ */
+public class MersenneTwisterFast implements Serializable
+    {
+    // Period parameters
+    private static final int N = 624;
+    private static final int M = 397;
+    private static final int MATRIX_A = 0x9908b0df;   //  private static final * constant vector a
+    private static final int UPPER_MASK = 0x80000000; // most significant w-r bits
+    private static final int LOWER_MASK = 0x7fffffff; // least significant r bits
+
+
+    // Tempering parameters
+    private static final int TEMPERING_MASK_B = 0x9d2c5680;
+    private static final int TEMPERING_MASK_C = 0xefc60000;
+    
+    // #define TEMPERING_SHIFT_U(y)  (y >>> 11)
+    // #define TEMPERING_SHIFT_S(y)  (y << 7)
+    // #define TEMPERING_SHIFT_T(y)  (y << 15)
+    // #define TEMPERING_SHIFT_L(y)  (y >>> 18)
+    
+    private int mt[]; // the array for the state vector
+    private int mti; // mti==N+1 means mt[N] is not initialized
+    private int mag01[];
+    
+    // a good initial seed (of int size, though stored in a long)
+    private static final long GOOD_SEED = 4357;
+
+    private double nextNextGaussian;
+    private boolean haveNextNextGaussian;
+
+
+    /**
+     * Constructor using the time of day as default seed.
+     */
+    public MersenneTwisterFast()
+        {
+		this((new Date()).getTime());
+        }
+    
+    /**
+     * Constructor using a given seed.  Though you pass this seed in
+     * as a long, it's best to make sure it's actually an integer.
+     *
+     * @param seed generator starting number, often the time of day.
+     */
+    public MersenneTwisterFast(long seed)
+	{
+		if (seed == 0)
+		{
+			setSeed(GOOD_SEED);
+		}
+		else
+		{
+			setSeed(seed);
+		}
+        }
+
+	/**
+	 * Returns an array of shuffled indices of length l.
+	 * @param l length of the array required.
+	 */
+	 public int[] shuffled(int l) {
+	 
+	 	int[] array = new int[l];
+		
+		// initialize array
+		for (int i = 0; i < l; i++) {
+			array[i] = i;
+		}
+
+		for (int i = 0; i < l; i++) {
+			int index = nextInt(l-i) + i;
+			int temp = array[index];
+			array[index] = array[i];
+			array[i] = temp;
+		} 
+	
+		return array;
+	}
+    
+    /**
+     * Initalize the pseudo random number generator.
+     * The Mersenne Twister only uses an integer for its seed;
+     * It's best that you don't pass in a long that's bigger
+     * than an int.
+     *
+     * @param seed from constructor
+     *
+     */
+    public final void setSeed(long seed)
+        {
+	haveNextNextGaussian = false;
+
+	mt = new int[N];
+	
+	// setting initial seeds to mt[N] using
+	// the generator Line 25 of Table 1 in
+	// [KNUTH 1981, The Art of Computer Programming
+	//    Vol. 2 (2nd Ed.), pp102]
+
+	// the 0xffffffff is commented out because in Java
+	// ints are always 32 bits; hence i & 0xffffffff == i
+
+	mt[0]= ((int)seed); // & 0xffffffff;
+
+	for (mti = 1; mti < N; mti++)
+	    mt[mti] = (69069 * mt[mti-1]); //& 0xffffffff;
+
+	// mag01[x] = x * MATRIX_A  for x=0,1
+	mag01 = new int[2];
+	mag01[0] = 0x0;
+	mag01[1] = MATRIX_A;
+        }
+    
+    public final int nextInt()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return y;
+	}
+
+
+
+    public final short nextShort()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return (short)(y >>> 16);
+	}
+
+
+
+    public final char nextChar()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return (char)(y >>> 16);
+	}
+
+
+    public final boolean nextBoolean()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return (boolean)((y >>> 31) != 0);
+	}
+
+
+    public final byte nextByte()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return (byte)(y >>> 24);
+	}
+
+
+    public final void nextBytes(byte[] bytes)
+	{
+	int y;
+	
+	for (int x=0;x<bytes.length;x++)
+	    {
+	    if (mti >= N)   // generate N words at one time
+		{
+		int kk;
+		
+		for (kk = 0; kk < N - M; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		for (; kk < N-1; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+		
+		mti = 0;
+		}
+	    
+	    y = mt[mti++];
+	    y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	    y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	    y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	    y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	    bytes[x] = (byte)(y >>> 24);
+	    }
+	}
+
+
+    public final long nextLong()
+	{
+	int y;
+	int z;
+
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1];
+		}
+	    z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
+	    
+	    mti = 0;
+	    }
+	
+	z = mt[mti++];
+	z ^= z >>> 11;                          // TEMPERING_SHIFT_U(z)
+	z ^= (z << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(z)
+	z ^= (z << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(z)
+	z ^= (z >>> 18);                        // TEMPERING_SHIFT_L(z)
+	
+	return (((long)y) << 32) + (long)z;
+	}
+
+
+    public final double nextDouble()
+	{
+	int y;
+	int z;
+
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1];
+		}
+	    z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
+	    
+	    mti = 0;
+	    }
+	
+	z = mt[mti++];
+	z ^= z >>> 11;                          // TEMPERING_SHIFT_U(z)
+	z ^= (z << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(z)
+	z ^= (z << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(z)
+	z ^= (z >>> 18);                        // TEMPERING_SHIFT_L(z)
+	
+	/* derived from nextDouble documentation in jdk 1.2 docs, see top */
+	return ((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53);
+	}
+
+
+
+
+
+    public final double nextGaussian()
+	{
+	if (haveNextNextGaussian)
+	    {
+	    haveNextNextGaussian = false;
+	    return nextNextGaussian;
+	    } 
+	else 
+	    {
+	    double v1, v2, s;
+	    do 
+		{ 
+		int y;
+		int z;
+		int a;
+		int b;
+		    
+		    if (mti >= N)   // generate N words at one time
+			{
+			int kk;
+			
+			for (kk = 0; kk < N - M; kk++)
+			    {
+			    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			    mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+			    }
+			for (; kk < N-1; kk++)
+			    {
+			    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			    mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+			    }
+			y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+			mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+			
+			mti = 0;
+			}
+		
+		y = mt[mti++];
+		y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+		y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+		y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+		y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+		
+		if (mti >= N)   // generate N words at one time
+		    {
+		    int kk;
+		    
+		    for (kk = 0; kk < N - M; kk++)
+			{
+			z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1];
+			}
+		    for (; kk < N-1; kk++)
+			{
+			z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1];
+			}
+		    z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		    mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
+		    
+		    mti = 0;
+		    }
+		
+		z = mt[mti++];
+		z ^= z >>> 11;                          // TEMPERING_SHIFT_U(z)
+		z ^= (z << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(z)
+		z ^= (z << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(z)
+		z ^= (z >>> 18);                        // TEMPERING_SHIFT_L(z)
+		
+		if (mti >= N)   // generate N words at one time
+		    {
+		    int kk;
+		    
+		    for (kk = 0; kk < N - M; kk++)
+			{
+			a = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+M] ^ (a >>> 1) ^ mag01[a & 0x1];
+			}
+		    for (; kk < N-1; kk++)
+			{
+			a = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+(M-N)] ^ (a >>> 1) ^ mag01[a & 0x1];
+			}
+		    a = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		    mt[N-1] = mt[M-1] ^ (a >>> 1) ^ mag01[a & 0x1];
+		    
+		    mti = 0;
+		    }
+		
+		a = mt[mti++];
+		a ^= a >>> 11;                          // TEMPERING_SHIFT_U(a)
+		a ^= (a << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(a)
+		a ^= (a << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(a)
+		a ^= (a >>> 18);                        // TEMPERING_SHIFT_L(a)
+		
+		if (mti >= N)   // generate N words at one time
+		    {
+		    int kk;
+		    
+		    for (kk = 0; kk < N - M; kk++)
+			{
+			b = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+M] ^ (b >>> 1) ^ mag01[b & 0x1];
+			}
+		    for (; kk < N-1; kk++)
+			{
+			b = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+			mt[kk] = mt[kk+(M-N)] ^ (b >>> 1) ^ mag01[b & 0x1];
+			}
+		    b = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		    mt[N-1] = mt[M-1] ^ (b >>> 1) ^ mag01[b & 0x1];
+		    
+		    mti = 0;
+		    }
+		
+		b = mt[mti++];
+		b ^= b >>> 11;                          // TEMPERING_SHIFT_U(b)
+		b ^= (b << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(b)
+		b ^= (b << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(b)
+		b ^= (b >>> 18);                        // TEMPERING_SHIFT_L(b)
+		
+		/* derived from nextDouble documentation in jdk 1.2 docs, see top */
+		v1 = 2 *
+		    (((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53))
+		    - 1;
+		v2 = 2 * (((((long)(a >>> 6)) << 27) + (b >>> 5)) / (double)(1L << 53))
+		    - 1;
+		s = v1 * v1 + v2 * v2;
+		} while (s >= 1);
+	    double multiplier = Math.sqrt(-2 * Math.log(s)/s);
+	    nextNextGaussian = v2 * multiplier;
+	    haveNextNextGaussian = true;
+	    return v1 * multiplier;
+	    }
+	}
+    
+    
+    
+    
+
+
+
+
+
+
+
+
+    public final float nextFloat()
+	{
+	int y;
+	
+	if (mti >= N)   // generate N words at one time
+	    {
+	    int kk;
+	    
+	    for (kk = 0; kk < N - M; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    for (; kk < N-1; kk++)
+		{
+		y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		}
+	    y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+	    mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+
+	    mti = 0;
+	    }
+  
+	y = mt[mti++];
+	y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+
+	return (y >>> 8) / ((float)(1 << 24));
+	}
+
+
+
+    /** Returns an integer drawn uniformly from 0 to n-1.  Suffice it to say,
+	n must be > 0, or an IllegalArgumentException is raised. */
+    public int nextInt(int n)
+	{
+	if (n<=0)
+	    throw new IllegalArgumentException("n must be positive");
+	
+	if ((n & -n) == n)  // i.e., n is a power of 2
+	    {
+	    int y;
+	
+	    if (mti >= N)   // generate N words at one time
+		{
+		int kk;
+		
+		for (kk = 0; kk < N - M; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		for (; kk < N-1; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+		
+		mti = 0;
+		}
+	    
+	    y = mt[mti++];
+	    y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	    y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	    y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	    y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+	    
+	    return (int)((n * (long) (y >>> 1) ) >> 31);
+	    }
+	
+	int bits, val;
+	do 
+	    {
+	    int y;
+	    
+	    if (mti >= N)   // generate N words at one time
+		{
+		int kk;
+		
+		for (kk = 0; kk < N - M; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		for (; kk < N-1; kk++)
+		    {
+		    y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+		    mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1];
+		    }
+		y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+		mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
+		
+		mti = 0;
+		}
+	    
+	    y = mt[mti++];
+	    y ^= y >>> 11;                          // TEMPERING_SHIFT_U(y)
+	    y ^= (y << 7) & TEMPERING_MASK_B;       // TEMPERING_SHIFT_S(y)
+	    y ^= (y << 15) & TEMPERING_MASK_C;      // TEMPERING_SHIFT_T(y)
+	    y ^= (y >>> 18);                        // TEMPERING_SHIFT_L(y)
+	
+	    bits = (y >>> 1);
+	    val = bits % n;
+	    } while(bits - val + (n-1) < 0);
+	return val;
+	}
+  
+    }
+
diff --git a/LibrarySource/pal/math/MultivariateFunction.java b/LibrarySource/pal/math/MultivariateFunction.java
new file mode 100644
index 0000000..327118d
--- /dev/null
+++ b/LibrarySource/pal/math/MultivariateFunction.java
@@ -0,0 +1,54 @@
+// MultivariateFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * interface for a function of several variables
+ *
+ * @author Korbinian Strimmer
+ */
+public interface MultivariateFunction
+{
+	/**
+	 * compute function value
+	 *
+	 * @param argument  function argument (vector)
+	 *
+	 * @return function value
+	 */
+	double evaluate(double[] argument);
+	
+	
+	/**
+	 * get number of arguments
+	 *
+	 * @return number of arguments
+	 */
+	 int getNumArguments();
+
+	/**
+	 * get lower bound of argument n
+	 *
+	 * @param n argument number
+	 *
+	 * @return lower bound
+	 */
+	double getLowerBound(int n);
+	
+	/**
+	 * get upper bound of argument n
+	 *
+	 * @param n argument number
+	 *
+	 * @return upper bound
+	 */
+	double getUpperBound(int n);
+}
+
diff --git a/LibrarySource/pal/math/MultivariateMinimum.java b/LibrarySource/pal/math/MultivariateMinimum.java
new file mode 100644
index 0000000..b242541
--- /dev/null
+++ b/LibrarySource/pal/math/MultivariateMinimum.java
@@ -0,0 +1,218 @@
+// MultivariateMinimum.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+
+package pal.math;
+
+
+/**
+ * abstract base class for minimisation of a multivariate function
+ *
+ * @author Korbinian Strimmer
+ */
+public abstract class MultivariateMinimum
+{
+	//
+	// Public stuff
+	//
+	
+	/** total number of function evaluations necessary */
+	public int numFun;
+ 	
+	/**
+	 * maxFun is the maximum number of calls to fun allowed. 
+	 * the default value of 0 indicates no limit on the number
+	 * of calls.            
+	 */
+	public int maxFun = 0;
+ 
+ 	/**
+	 * numFuncStops is the number of consecutive positive
+	 * evaluations of the stop criterion based on function evaluation
+	 * necessary to cause the abortion of the optimization
+	 * (default is 4)
+	 */
+	public int numFuncStops = 4;
+
+                                                                  
+	/**
+	 * Find minimum close to vector x
+ 	 *
+	 * @param f multivariate function
+	 * @param xvec initial guesses for the minimum
+	 *         (contains the location of the minimum on return) 
+	 *
+	 * @return minimal function value
+ 	 */
+	public double findMinimum(MultivariateFunction f, double[] xvec)
+	{
+		optimize(f, xvec, MachineAccuracy.EPSILON, MachineAccuracy.EPSILON);
+		
+		return f.evaluate(xvec);
+	}
+
+	/**
+	 * Find minimum close to vector x
+	 * (desired fractional digits for each parameter is specified)
+ 	 *
+	 * @param f multivariate function
+	 * @param xvec initial guesses for the minimum
+	 *         (contains the location of the minimum on return)
+	 * @param fxFracDigits desired fractional digits in the function value
+	 * @param xFracDigits desired fractional digits in parameters x
+	 *
+	 * @return minimal function value
+ 	 */
+	public double findMinimum(MultivariateFunction f, double[] xvec,
+		int fxFracDigits, int xFracDigits)
+	{
+		double tolfx = Math.pow(10, -1-fxFracDigits);
+		double tolx = Math.pow(10, -1-xFracDigits);
+		
+		optimize(f, xvec, tolfx, tolx);
+		
+		// trim x
+		double m = Math.pow(10, xFracDigits);
+		for (int i = 0;  i < xvec.length; i++)
+		{
+			xvec[i] = Math.round(xvec[i]*m)/m;
+		}
+
+		// trim fx
+		return Math.round(f.evaluate(xvec)*m)/m;
+	}
+	
+	/**
+	 * The actual optimization routine
+	 * (needs to be implemented in a subclass of MultivariateMinimum).
+	 * It finds a minimum close to vector x when the
+	 * absolute tolerance for each parameter is specified.
+         *
+	 * @param f multivariate function
+	 * @param xvec initial guesses for the minimum
+	 *         (contains the location of the minimum on return)
+	 * @param tolfx absolute tolerance of function value
+	 * @param tolx absolute tolerance of each parameter
+ 	 */
+	public abstract void optimize(MultivariateFunction f, double[] xvec, double tolfx, double tolx);
+
+
+	/**
+	 * Checks whether optimization should stop
+         *
+	 * @param fx current function value
+	 * @param x current values of function parameters
+	 * @param tolfx absolute tolerance of function value
+	 * @param tolx absolute tolerance of each parameter
+	 * @param firstCall needs to be set to true when this routine is first called
+	 *        otherwise it should be set to false
+	 *
+	 * @return true if either x and its previous value are sufficiently similar
+	 *         or if fx and its previous values are sufficiently similar
+	 *         (test on function value has to be succesful numFuncStops consecutive
+	 *         times)
+ 	 */
+	public boolean stopCondition(double fx, double[] x, double tolfx,
+		double tolx, boolean firstCall)
+	{
+		boolean stop = false;
+		
+		if (firstCall)
+		{
+			countFuncStops = 0;
+			fxold = fx;
+			xold = new double[x.length];
+			copy(xold, x);
+		}
+		else
+		{
+			if (xStop(x, xold, tolx))
+			{
+				stop = true;
+			}
+			else
+			{
+				if (fxStop(fx, fxold, tolfx))
+				{
+					countFuncStops++;
+				}
+				else
+				{
+					countFuncStops = 0;
+				}
+				
+				if (countFuncStops >= numFuncStops)
+				{
+					stop = true;
+				}
+			}
+		}
+		
+		if (!stop)
+		{
+			fxold = fx;
+			copy(xold, x);
+		}
+		
+		return stop;
+	}
+
+
+	/**
+	 * Copy source vector into target vector
+	 *
+	 * @param target parameter array
+	 * @param source parameter array
+	 */
+	public void copy(double[] target, double[] source)
+	{
+		for (int i = 0; i < source.length; i++)
+		{
+			target[i] = source[i];
+		}
+	}	
+
+	//
+	// Private stuff
+	//
+
+	// number of fStops
+	private int countFuncStops;
+
+	// old function and parameter values
+	private double fxold;
+	private double[] xold;
+
+	private boolean xStop(double[] x, double[] xold, double tolx)
+	{
+		boolean stop = true;
+		
+		for (int i = 0; i < x.length && stop == true; i++)
+		{
+			if (Math.abs(x[i]-xold[i]) > tolx)
+			{
+				stop = false;
+			}
+		}
+		
+		return stop;
+	}
+	
+	private boolean fxStop(double fx, double fxold, double tolfx)
+	{
+		if (Math.abs(fx-fxold) > tolfx)
+		{
+			return false;
+		}
+		else
+		{
+			return true;
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/math/NumericalDerivative.java b/LibrarySource/pal/math/NumericalDerivative.java
new file mode 100644
index 0000000..3d829a4
--- /dev/null
+++ b/LibrarySource/pal/math/NumericalDerivative.java
@@ -0,0 +1,138 @@
+// NumericalDerivative.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// Known bugs and limitations:
+// - the sparse number of function evaluations used can potentially
+//   lead to strong inaccuracies if the function is ill-behaved
+
+
+package pal.math;
+
+
+/**
+ * approximates numerically the first and second derivatives of a
+ * function of a single variable and  approximates gradient and
+ * diagonal of Hessian for multivariate functions
+ *
+ * @author Korbinian Strimmer
+ */
+public class NumericalDerivative
+{
+	//
+	// Public stuff
+	//
+
+
+	/**
+	 * determine first derivative
+	 *
+	 * @param f univariate function
+	 * @param x argument
+	 *
+	 * @return first derivate at x
+	 */
+	public static double firstDerivative(UnivariateFunction f, double x)
+	{	
+		double h = MachineAccuracy.SQRT_EPSILON*(Math.abs(x) + 1.0);
+
+		// Centered first derivative
+		return (f.evaluate(x + h) - f.evaluate(x - h))/(2.0*h);
+	}
+
+	/**
+	 * determine second derivative
+	 *
+	 * @param f univariate function
+	 * @param x argument
+	 *
+	 * @return second derivate at x
+	 */
+	public static double secondDerivative(UnivariateFunction f, double x)
+	{
+		double h = MachineAccuracy.SQRT_SQRT_EPSILON*(Math.abs(x) + 1.0);
+	
+		// Centered second derivative
+		return (f.evaluate(x + h) - 2.0*f.evaluate(x) + f.evaluate(x - h))/(h*h);
+	}
+
+	
+	/**
+	 * determine gradient
+	 *
+	 * @param f multivariate function
+	 * @param x argument vector
+	 *
+	 * @return gradient at x
+	 */
+	public static double[] gradient(MultivariateFunction f, double[] x)
+	{	
+		double[] result = new double[x.length];
+
+		gradient(f, x, result);
+		
+		return result;
+	}
+
+	/**
+	 * determine gradient
+	 *
+	 * @param f multivariate function
+	 * @param x argument vector
+	 * @param grad vector for gradient
+	 */
+	public static void gradient(MultivariateFunction f, double[] x, double[] grad)
+	{	
+		for (int i = 0; i < f.getNumArguments(); i++)
+		{
+			double h = MachineAccuracy.SQRT_EPSILON*(Math.abs(x[i]) + 1.0);
+		
+			double oldx = x[i];
+			x[i] = oldx + h;
+			double fxplus = f.evaluate(x);
+			x[i] = oldx - h;
+			double fxminus = f.evaluate(x);
+			x[i] = oldx;
+
+			// Centered first derivative
+			grad[i] = (fxplus-fxminus)/(2.0*h);
+		}
+	}
+
+	/**
+	 * determine diagonal of Hessian
+	 *
+	 * @param f multivariate function
+	 * @param x argument vector
+	 *
+	 * @return vector with diagonal entries of Hessian
+	 */
+	public static double[] diagonalHessian(MultivariateFunction f, double[] x)
+	{
+		int len = f.getNumArguments();
+		double[] result = new double[len];
+
+		for (int i = 0; i < len; i++)
+		{
+			double h = MachineAccuracy.SQRT_SQRT_EPSILON*(Math.abs(x[i]) + 1.0);
+		
+			double oldx = x[i];
+			x[i] = oldx + h;
+			double fxplus = f.evaluate(x);
+			x[i] = oldx - h;
+			double fxminus = f.evaluate(x);
+			x[i] = oldx;
+			double fx = f.evaluate(x);
+
+			// Centered second derivative
+			result[i] = (fxplus - 2.0*fx + fxminus)/(h*h);
+		}
+		
+		return result;
+	}
+}
+
diff --git a/LibrarySource/pal/math/OrthogonalLineFunction.java b/LibrarySource/pal/math/OrthogonalLineFunction.java
new file mode 100644
index 0000000..d0f27b5
--- /dev/null
+++ b/LibrarySource/pal/math/OrthogonalLineFunction.java
@@ -0,0 +1,102 @@
+// OrthogonalLineFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * converts a multivariate function into a univariate function
+ * by keeping all but one argument constant
+ *
+ * @author Korbinian Strimmer
+ */
+public class OrthogonalLineFunction implements UnivariateFunction
+{
+	/**
+	 * construct univariate function from multivariate function
+	 *
+	 * @param func multivariate function
+	 */
+	public OrthogonalLineFunction(MultivariateFunction func)
+	{
+		f = func;
+		numArgs = f.getNumArguments();
+		x = new double[numArgs];
+	}
+
+	/**
+	 * set (change) values of all arguments (start values)
+	 *
+	 * @param start start values
+	 */
+	public void setAllArguments(double[] start)
+	{
+		for (int i = 0; i < numArgs; i++)
+		{
+			x[i] = start[i];
+		}
+	}
+
+	/**
+	 * set (change) value of a single argument
+	 * (the one currently active)
+	 *
+	 * @param val value of argument
+	 */
+	public void setArgument(double val)
+	{
+		x[n] = val;
+		bak = x[n];
+	}
+
+
+	/**
+	 * use only the specified argument in the
+	 * constructed univariate function
+	 * and keep all others constant
+	 *
+	 * @param num argument number
+	 */
+	public void selectArgument(int num)
+	{
+		n = num;
+		bak = x[n];
+	}
+	
+	// implementation of UnivariateFunction
+	
+	public double evaluate(double arg)
+	{
+		x[n] = arg;
+		double v = f.evaluate(x);
+		x[n] = bak;
+		
+		return v;
+	}
+
+	public double getLowerBound()
+	{
+		return f.getLowerBound(n);
+	}
+
+	public double getUpperBound()
+	{
+		return f.getUpperBound(n);
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private MultivariateFunction f;
+	private int numArgs, n;
+	private double bak;
+	private double[] s, x;
+}
+
diff --git a/LibrarySource/pal/math/OrthogonalSearch.java b/LibrarySource/pal/math/OrthogonalSearch.java
new file mode 100644
index 0000000..95100b0
--- /dev/null
+++ b/LibrarySource/pal/math/OrthogonalSearch.java
@@ -0,0 +1,80 @@
+// OrthogonalSearch.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * minimization of a real-valued function of
+ * several variables without using derivatives, using the simple
+ * strategy of optimizing variables one by one.
+ *
+ * @author Korbinian Strimmer
+ */
+public class OrthogonalSearch extends MultivariateMinimum
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Initialization
+	 */
+	public OrthogonalSearch()
+	{
+		um = new UnivariateMinimum();
+	}
+	
+ 
+	// implementation of abstract method
+	
+	public void optimize(MultivariateFunction f, double[] xvec, double tolfx, double tolx)
+	{
+		numArgs = f.getNumArguments();
+		
+		numFun = 1;
+		double fx = f.evaluate(xvec);
+		
+		stopCondition(fx, xvec, tolfx, tolx, true);
+				
+		OrthogonalLineFunction olf = new OrthogonalLineFunction(f);
+		olf.setAllArguments(xvec);
+		
+		while (true)
+		{
+			for (int i = 0; i < numArgs; i++)
+			{
+				olf.selectArgument(i);
+				
+				// Note that we don't use xvec as starting point
+				// in the 1d line minimization.
+				xvec[i] = um.optimize(olf, tolx);
+				olf.setArgument(xvec[i]);
+				
+				numFun += um.numFun;
+			}
+			fx = um.fminx;
+
+			if (stopCondition(fx, xvec, tolfx, tolx, false) ||
+				(maxFun > 0 && numFun > maxFun) ||
+				 numArgs == 1)
+			{
+				break;		
+			}	
+		}
+	}
+	
+
+	//
+	// Private stuff
+	//
+
+	private UnivariateMinimum um;
+	private int numArgs;
+}
+
diff --git a/LibrarySource/pal/math/UnivariateFunction.java b/LibrarySource/pal/math/UnivariateFunction.java
new file mode 100644
index 0000000..9629154
--- /dev/null
+++ b/LibrarySource/pal/math/UnivariateFunction.java
@@ -0,0 +1,42 @@
+// UnivariateFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * interface for a function of one variable
+ *
+ * @author Korbinian Strimmer
+ */
+public interface UnivariateFunction
+{
+	/**
+	 * compute function value
+	 *
+	 * @param function argument
+	 * 
+	 * @return function value
+	 */
+	double evaluate(double argument);
+	
+	/**
+	 * get lower bound of argument
+	 *
+	 * @return lower bound
+	 */
+	double getLowerBound();
+	
+	/**
+	 * get upper bound of argument
+	 *
+	 * @return upper bound
+	 */
+	double getUpperBound();
+}
+
diff --git a/LibrarySource/pal/math/UnivariateMinimum.java b/LibrarySource/pal/math/UnivariateMinimum.java
new file mode 100644
index 0000000..df241e7
--- /dev/null
+++ b/LibrarySource/pal/math/UnivariateMinimum.java
@@ -0,0 +1,479 @@
+// UnivariateMinimum.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * minimization of a real-valued function of one variable
+ * without using derivatives.
+ *
+ * <p>algorithm: Brent's golden section method
+ * (Richard P. Brent.  1973.   Algorithms for finding zeros and extrema
+ *  of functions without calculating derivatives.  Prentice-Hall.)
+ *
+ * @version $Id: UnivariateMinimum.java,v 1.7 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class UnivariateMinimum
+{
+	//
+	// Public stuff
+	//
+
+	/** last minimum */
+	public double minx;
+	
+	/** function value at minimum */
+	public double fminx;
+	
+	/** curvature at minimum */
+	public double f2minx; 
+	
+	/** total number of function evaluations neccessary */
+	public int numFun;
+	
+	/**
+	 * maximum number of function evaluations
+	 * (default 0 indicates no limit on calls)
+	 */
+	public int maxFun = 0;
+
+	/**
+	 * Find minimum
+	 * (first estimate given)
+	 *
+	 * @param x   first estimate
+	 * @param f   function
+	 * 
+	 * @return position of minimum
+	 */
+	public double findMinimum(double x, UnivariateFunction f)
+	{
+		double tol = MachineAccuracy.EPSILON;
+		
+		return optimize(x, f, tol);
+	}
+
+	/**
+	 * Find minimum 
+	 * (first estimate given, desired number of fractional digits specified)
+	 *
+	 * @param x   first estimate
+	 * @param f   function
+	 * @param fracDigits desired fractional digits
+	 * 
+	 * @return position of minimum
+	 */
+	public double findMinimum(double x, UnivariateFunction f, int fracDigits)
+	{
+		double tol = Math.pow(10, -1-fracDigits);
+		
+		double optx = optimize(x, f, tol);
+		
+		//return trim(optx, fracDigits);
+		return optx;
+	}
+
+	/**
+	 * Find minimum
+	 * (no first estimate given)
+	 *
+	 * @param f   function
+	 * 
+	 * @return position of minimum
+	 */
+	public double findMinimum(UnivariateFunction f)
+	{
+		double tol = MachineAccuracy.EPSILON;
+				
+		return optimize(f, tol);
+	}
+
+	/**
+	 * Find minimum
+	 * (no first estimate given, desired number of fractional digits specified)
+	 *
+	 * @param f   function
+	 * @param fracDigits desired fractional digits
+	 * 
+	 * @return position of minimum
+	 */
+	public double findMinimum(UnivariateFunction f, int fracDigits)
+	{
+		double tol = Math.pow(10, -1-fracDigits);
+		
+		double optx = optimize(f, tol);
+		
+		//return trim(optx, fracDigits);
+		return optx; 
+	}
+
+	/**
+	 * The actual optimization routine (Brent's golden section method)
+         *
+	 * @param f univariate function
+	 * @param tol absolute tolerance of each parameter
+	 *
+	 * @return  position of minimum
+ 	 */
+	public double optimize(UnivariateFunction f, double tol)
+	{
+		numFun = 2;
+		double min = f.getLowerBound();
+		double max = f.getUpperBound();
+		
+		return minin(min, max, f.evaluate(min), f.evaluate(max), f, tol);
+	}
+
+	/**
+	 * The actual optimization routine (Brent's golden section method)
+         *
+	 * @param x initial guess
+	 * @param f univariate function
+	 * @param tol absolute tolerance of each parameter
+	 *
+	 * @return  position of minimum
+ 	 */
+	public double optimize(double x, UnivariateFunction f, double tol)
+	{
+		double[] range = bracketize(f.getLowerBound(), x, f.getUpperBound(), f);
+
+		return minin(range[0], range[1], range[2], range[3], f, tol);
+	}
+
+	//
+	// Private stuff
+	//
+
+	private static final double C = (3.0- Math.sqrt(5.0))/2.0; // = 0.38197
+	private static final double GOLD = (Math.sqrt(5.0) + 1.0)/2.0; // = 1.61803
+	private static final double delta = 0.01; // Determines second trial point
+
+	// trim x to have a specified number of fractional digits
+	private double trim(double x, int fracDigits)
+	{
+		double m = Math.pow(10, fracDigits);
+		
+		return Math.round(x*m)/m;
+	}
+	
+	private double constrain(double x, boolean toMax, double min, double max)
+	{
+		if (toMax)
+		{
+			if (x > max)
+			{
+				return max;
+			}
+			else
+			{
+				return x;
+			}
+		}
+		else
+		{
+			if (x < min)
+			{
+				return min;
+			}
+			else
+			{
+				return x;
+			}
+		}
+	}	
+
+	private double[] bracketize(double min, double a, double max, UnivariateFunction f)
+	{
+		if (min > max)
+		{
+			throw new IllegalArgumentException("Argument min (" + min +
+			") larger than argument max (" + max + ")");
+		}
+		
+		if (a < min)
+		{
+			a = min;
+		}
+		else if (a > max)
+		{
+			a = max;
+		}
+
+
+		if (a < min || a > max)
+		{
+			throw new IllegalArgumentException("Starting point not in given range ("
+			+ min + ", " + a + ", " + max + ")");
+		}
+		
+		
+		// Get second point
+		double b;
+		if (a - min < max - a)
+		{
+			b = a + delta*(max - a);
+		}
+		else
+		{
+			b = a - delta*(a - min);
+		}
+	
+		numFun = 0;
+    
+		double fa = f.evaluate(a); numFun++;
+		double fb = f.evaluate(b); numFun++;
+		
+		double tmp;
+		if (fb > fa)
+		{
+			tmp = a; a = b; b = tmp;
+			tmp = fa; fa = fb; fb = tmp;
+		}
+		
+		// From here on we always have fa >= fb
+		// Our aims is to determine a new point c with fc >= fb
+		
+		// Direction of search (towards min or towards max)
+		boolean searchToMax;
+		double ulim;
+		if (b > a)
+		{
+			searchToMax = true;
+			ulim = max;
+		}
+		else
+		{
+			searchToMax = false;
+			ulim = min;
+		}
+		
+		// First guess: default magnification
+		double c = b + GOLD * (b - a);
+		c = constrain(c, searchToMax, min, max);
+		double fc = f.evaluate(c); numFun++;
+        
+		while (fb > fc)
+		{
+			// Compute u as minimum of a parabola through a, b, c
+			double r = (b - a) * (fb - fc);
+			double q = (b - c) * (fb - fa);
+			if (q == r)
+			{
+                		q += MachineAccuracy.EPSILON;
+			}
+			double u = b - ((b - c) * q - (b - a) * r) / 2.0 / (q - r);
+			u = constrain(u, searchToMax, min, max);
+			double fu = 0; // Don�t evaluate now
+			
+			boolean magnify = false;
+			
+			// Check out all possibilities
+			
+			// u is between b and c
+			if ((b - u) * (u - c) > 0)
+			{
+				fu = f.evaluate(u); numFun++;
+				
+				// minimum between b and c
+				if (fu < fc)
+				{
+					a = b; b = u;
+					fa = fb; fb = fu;
+					
+					break;
+				}
+				// minimum between a and u
+				else if (fu > fb)
+				{
+					c = u;
+					fc = fu;
+					
+					break;
+				}
+				
+				magnify = true;
+            		}
+			// u is between c and limit
+			else if ((c - u) * (u - ulim) > 0)
+			{
+				fu = f.evaluate(u); numFun++;
+				
+				// u is not a minimum
+				if (fu < fc)
+				{
+					b = c; c = u;
+					fb = fc; fc = fu; 
+					
+					magnify = true;
+				}
+            		}
+			//  u equals limit
+			else if (u == ulim)
+			{
+				fu = f.evaluate(u); numFun++;
+			}
+			// All other cases
+			else
+			{
+				magnify = true;
+			}
+
+			if (magnify)
+			{
+				// Next guess: default magnification
+				u = c + GOLD * (c - b);
+				u = constrain(u, searchToMax, min, max);
+				fu = f.evaluate(u); numFun++;
+			}
+
+			a = b; b = c; c = u;
+			fa = fb; fb = fc; fc = fu;
+		}
+		
+		// Once we are here be have a minimum in [a, c]
+		double[] result = new double[4];
+		result[0] = a;
+		result[1] = c;
+		result[2] = fa;
+		result[3] = fc;
+		return result;
+	}
+
+
+	private double minin(double a, double b, double fa , double fb, UnivariateFunction f, double tol)
+	{
+		double z, d = 0, e, m, p, q, r, t, u, v, w, fu, fv, fw, fz, tmp;
+
+		if (tol <= 0)
+		{
+			throw new IllegalArgumentException("Nonpositive absolute tolerance tol");
+		}
+
+		if (a == b)
+		{
+			minx = a;
+			fminx = fa;
+		
+			f2minx = NumericalDerivative.secondDerivative(f, minx);
+		
+			return  minx;
+
+			//throw new IllegalArgumentException("Borders of range not distinct");
+		}
+
+		if (b < a)
+		{
+			tmp = a; a = b; b = tmp;
+			tmp = fa; fa = fb; fb = tmp;
+		}
+
+		w = a; fw = fa;
+		z = b; fz = fb;
+		if (fz > fw) // Exchange z and w
+		{
+			v = z; z = w; w = v;
+			v = fz; fz = fw; fw = v;
+		}
+		v = w;
+		fv = fw;
+		e = 0.0;
+		while (maxFun == 0 || numFun <= maxFun)
+		{
+			m = (a + b)*0.5;
+			double tol_act = MachineAccuracy.SQRT_EPSILON + tol; // Absolute tolerance
+			//double tol_act = MachineAccuracy.SQRT_EPSILON*Math.abs(z) + tol/3; // Actual tolerance
+			double tol_act2 = 2.0*tol_act;
+			if (Math.abs(z-m) <= tol_act2-(b - a)*0.5)
+			{
+				break;
+			}
+			p = q = r = 0.0;
+			if (Math.abs(e) > tol_act)
+			{
+				r = (z-w)*(fz-fv);
+				q = (z-v)*(fz-fw);
+				p = (z-v)*q-(z-w)*r;
+				q = (q-r)*2.0;
+				if (q > 0.0)
+				{
+					p = -p;
+				}
+				else
+				{
+					q = -q;
+				}
+				r = e;
+				e = d;
+			}
+			if (Math.abs(p) < Math.abs(q*r*0.5) && p > (a-z)*q && p < (b-z)*q)
+			{
+				d = p/q;
+				u = z+d;
+				if (u-(a) < tol_act2 || (b)-u < tol_act2)
+				{
+					d = ((z < m) ? tol_act : -tol_act);
+				}
+			}
+			else
+			{
+				e = ((z < m) ? b : a) - z;
+				d = C*e;
+			}
+			u = z + ((Math.abs(d) >= tol_act) ? d : ((d > 0.0) ? tol_act : -tol_act));
+			fu = f.evaluate(u); numFun++;
+			if (fu <= fz)
+			{
+				if (u < z)
+				{
+					b = z;
+				}
+				else
+				{
+					a = z;
+				}
+				v = w;
+				fv = fw;
+				w = z;
+				fw = fz;
+				z = u;
+				fz = fu;
+			}
+			else
+			{
+				if (u < z)
+				{
+					a = u;
+				}
+				else
+				{
+					b = u;
+				}
+				if (fu <= fw)
+				{
+					v = w; fv = fw;
+					w = u; fw = fu;
+				}
+				else if (fu <= fv || v == w)
+				{
+					v = u;
+					fv = fu;
+				}
+			}
+		}
+		minx = z;
+		fminx = fz;
+		
+		f2minx = NumericalDerivative.secondDerivative(f, minx);
+		
+		return  z;
+	}
+}
+
diff --git a/LibrarySource/pal/math/UrnModel.java b/LibrarySource/pal/math/UrnModel.java
new file mode 100644
index 0000000..a8133bc
--- /dev/null
+++ b/LibrarySource/pal/math/UrnModel.java
@@ -0,0 +1,121 @@
+// Urn.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.math;
+
+
+/**
+ * class for drawing numbers from an urn with and
+ * without laying back
+ *
+ * @version $Id: UrnModel.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class UrnModel implements java.io.Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * create urn model
+	 *
+	 * @param n  capacity (corresponding to numbers 0..n-1)
+	 */
+	public UrnModel(int n)
+	{
+		capacity = n;
+		isAvailable = new boolean[n];
+		
+		rng = new MersenneTwisterFast();
+		
+		reset();
+	}
+
+	/**
+	 * draw a number without putting back
+	 *
+	 * @return number drawn (random integer between 0..n-1, if empty return -1)
+	 */
+ 	public int drawDontPutBack()
+	{
+		if (numNumbers == numDrawn)
+		{
+			next = -1;
+		}
+		else
+		{
+			draw();
+			
+			isAvailable[next] = false;			
+			numDrawn++;
+		}
+		
+		return next;
+	}
+
+	/** refill urn */
+	public void reset()
+	{
+		numNumbers = capacity;
+		numDrawn = 0;
+		
+		for (int i = 0; i < capacity; i++)
+		{
+			isAvailable[i] = true;
+		}	
+	}
+
+	/**
+	 * draws a number with putting back 
+	 *
+	 * @return number drawn (random integer between 0..n-1, if empty return -1)
+	 */
+ 	public int drawPutBack()
+	{
+		if (numNumbers == numDrawn)
+		{
+			next = -1;
+		}
+		else
+		{
+			draw();
+		}
+		
+		return next;
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private int capacity, numNumbers, numDrawn, next;
+	private boolean[] isAvailable;
+	private MersenneTwisterFast rng;
+	
+	private void draw()
+	{
+		// Random integer 0..numNumbers-numDrawn-1
+		int i = rng.nextInt(numNumbers-numDrawn);		
+		
+		next = -1;
+		int k = -1;
+		do
+		{
+			next++;
+			if (isAvailable[next] == true)
+			{
+				k++;
+			}
+		}
+		while (k != i);
+	}
+}
+
diff --git a/LibrarySource/pal/math/makefile b/LibrarySource/pal/math/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/math/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/math/package.html b/LibrarySource/pal/math/package.html
new file mode 100644
index 0000000..4772222
--- /dev/null
+++ b/LibrarySource/pal/math/package.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+Classes for math stuff such as optimisation, numerical derivatives, matrix exponentials,
+random numbers, special function etc. 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/mep/ConstantMutationRate.java b/LibrarySource/pal/mep/ConstantMutationRate.java
new file mode 100644
index 0000000..131daa9
--- /dev/null
+++ b/LibrarySource/pal/mep/ConstantMutationRate.java
@@ -0,0 +1,198 @@
+// ConstantMutationRate.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+ 
+package pal.mep;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models a constant mutation rate
+ * (parameter: mu = mutation rate). <BR>
+ *
+ * @version $Id: ConstantMutationRate.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class ConstantMutationRate extends MutationRateModel implements Report, Summarizable, Parameterized, Serializable
+{
+
+	//
+	// private stuff
+	//
+	/** The summary descriptor stuff for the public values of this
+			class
+			@see Summarizable, getSummaryDescriptors()
+	*/
+	private static final String[] CP_SUMMARY_TYPES = {"mu", "muSE"}; //This is still 1.0 compliant...
+
+	//
+	// Public stuff
+	//
+
+	/** mutation rate */
+	public double mu;
+	public double muSE;
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public ConstantMutationRate(int units) {
+	
+		super();
+	
+		setUnits(units);
+
+		mu = getDefaultValue(0);
+	}
+
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public ConstantMutationRate(double rate, int units) {
+	
+		super();
+	
+		mu = rate;
+		setUnits(units);
+	}
+
+	public Object clone()
+	{
+		return new ConstantMutationRate(getMu(), getUnits()); 
+	}
+
+	public String[] getSummaryTypes() {
+		return CP_SUMMARY_TYPES;
+	}
+
+	public double getSummaryValue(int summaryType) {
+		switch(summaryType) {
+			case 0 : {
+				return mu;
+			}
+			case 1 : {
+				return muSE;
+			}
+		}
+		throw new RuntimeException("Assertion error: unknown summary type :"+summaryType);
+	}
+
+	/**
+	 * returns initial population size.
+	 */
+	public double getMu()
+	{
+		return mu;
+	}
+
+		
+	// Implementation of abstract methods
+	
+	public final double getMutationRate(double t)
+	{
+		return mu;
+	}
+
+	public final double getExpectedSubstitutions(double t)
+	{
+		return mu * t;
+	}
+
+	public final double getTime(double expectedSubs) {
+		return expectedSubs / mu;
+	}
+
+	/**
+	 * Linearly scales this mutation rate model.
+	 * @param scale getExpectedSubstitutions should return scale instead of 1.0 at time t.
+	 */
+	public final void scale(double scale) {
+		mu *= scale;
+	}
+
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public double getParameter(int k)
+	{
+		return mu;
+	}
+
+	public double getUpperLimit(int k)
+	{
+		return 1e12;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		return 1e-12;
+	}
+
+	public double getDefaultValue(int k)
+	{
+		//arbitrary default values
+		if (getUnits() == GENERATIONS) {
+			return 1e-6;
+		} else {
+			return 1e-6;
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		mu = value;
+	}
+
+	public void setParameterSE(double value, int k) {
+		muSE = value;
+	}
+
+	public String toString()
+	{
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Mutation rate model: constant mutation rate ");
+		out.println("Function: mu(t) = mu");
+		
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of function:");
+		out.print(" mutation rate: ");
+		fo.displayDecimal(out, mu, 6);
+		out.println();
+	}
+
+	public String toSingleLine() {
+		return "mu\t" + mu;
+	}	
+}
+
diff --git a/LibrarySource/pal/mep/MutationRateModel.java b/LibrarySource/pal/mep/MutationRateModel.java
new file mode 100644
index 0000000..6fc2dd5
--- /dev/null
+++ b/LibrarySource/pal/mep/MutationRateModel.java
@@ -0,0 +1,113 @@
+// MutationRateModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.mep;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+import java.io.*;
+
+
+/**
+ * This abstract class contains methods that are of general use for
+ * modelling mutation rate changes over time.
+ *
+ * @version $Id: MutationRateModel.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public abstract class MutationRateModel implements Units,
+	Parameterized, Report, Cloneable, Serializable, Summarizable
+{
+	
+	//
+	// Public stuff
+	//
+	
+	public MutationRateModel()
+	{	
+		units = GENERATIONS;
+		
+		fo = FormattedOutput.getInstance();
+	}
+
+	public abstract Object clone();
+
+	//
+	// functions that define a demographic model (left for subclass)
+	//
+
+	/**
+	 * Gets the mutation rate, value of mu(t) at time t.
+	 */
+	public abstract double getMutationRate(double t);
+
+	/**
+	 * Returns integral of mutation rate function
+	 * (= integral mu(x) dx from 0 to t).
+	 */
+	public abstract double getExpectedSubstitutions(double t);
+
+	/**
+	 * Return the time at which expected substitutions has occurred.
+	 */
+	public abstract double getTime(double expectedSubs);
+	
+
+	/**
+	 * Linearly scales this mutation rate model.
+	 * @param scale getExpectedSubstitutions should return scale instead of 1.0 at time t.
+	 */
+	public abstract void scale(double scale);
+
+	// Parameterized and Report interface is also left for subclass
+
+
+	// general functions
+
+	/**
+	 * Calculates the integral 1/mu(x) dx between start and finish.
+	 */
+	public double getExpectedSubstitutions(double start, double finish)
+	{
+		return getExpectedSubstitutions(finish) - getExpectedSubstitutions(start);
+	}
+
+	/**
+	 * Units in which time units are measured.
+	 */
+	private int units;
+
+	/**
+	 * sets units of measurement.
+	 *
+	 * @param u units
+	 */
+	public void setUnits(int u)
+	{
+		units = u;
+	}
+
+	/**
+	 * returns units of measurement.
+	 */
+	public int getUnits()
+	{
+		return units;
+	}
+		
+	public abstract String toSingleLine();
+		
+	//
+	// Private and protected stuff
+	//
+		
+	protected FormattedOutput fo;
+}
+
diff --git a/LibrarySource/pal/mep/SteppedMutationRate.java b/LibrarySource/pal/mep/SteppedMutationRate.java
new file mode 100644
index 0000000..85bf52f
--- /dev/null
+++ b/LibrarySource/pal/mep/SteppedMutationRate.java
@@ -0,0 +1,374 @@
+// SteppedMutationRate.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+ 
+package pal.mep;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models a step-wise mutation rate. <BR>
+ * parameters: <BR>
+ * mus[] = vector of mutation rates <BR>
+ * muChanges[] = vector of change times <P>
+ * Drummond, Forsberg and Rodrigo (2001). The inference of step-wise changes in substitution rates using serial sequence samples. accepted in MBE.
+ *
+ * @version $Id: SteppedMutationRate.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class SteppedMutationRate extends MutationRateModel implements Report, Summarizable, Parameterized, Serializable
+{	
+	//
+	// Public stuff
+	//
+
+	/** mutation rates */
+	public double[] mus;
+
+	/** mutation rate SEs */
+	public double[] muSEs;
+	
+	/** mutation rate change times */
+	public double[] muChanges;
+
+	/** whether or not the mu values are optimizable */
+	public boolean fixedMus = false;
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public SteppedMutationRate(double[] muChanges, int units) {
+	
+		super();
+	
+		setUnits(units);
+
+		this.muChanges = muChanges;
+
+		mus = new double[muChanges.length + 1];
+		muSEs = new double[muChanges.length + 1];
+		for (int i = 0; i < mus.length; i++) {
+			mus[i] = getDefaultValue(0);
+		}
+	}
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public SteppedMutationRate(double[] rates, double[] muChanges, int units) {
+		this(rates, muChanges, units, false);
+	}
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public SteppedMutationRate(double[] rates, double[] muChanges, int units, boolean fixed) {
+	
+		super();
+	
+		fixedMus = fixed;
+		mus = rates;
+		muSEs = new double[rates.length];
+		this.muChanges = muChanges;
+		setUnits(units);
+	}
+
+	public Object clone()
+	{
+		return new SteppedMutationRate(getMus(), getMuChanges(), getUnits(), fixedMus); 
+	}
+
+	public String[] getSummaryTypes() {
+		if (summaryTypes == null) {
+			summaryTypes = new String[mus.length];
+			for (int i = 0; i < summaryTypes.length; i++) {
+				summaryTypes[i] = "mu " + i;
+			}
+		}
+		return summaryTypes;
+	}
+
+	public double getSummaryValue(int summaryType) {
+		
+		if (summaryType < mus.length) {
+			return mus[summaryType];
+		}
+		throw new RuntimeException("Assertion error: unknown summary type :"+summaryType);
+	}
+
+	/**
+	 * returns current day mutation rate.
+	 */
+	public double getMu()
+	{
+		return mus[0];
+	}
+
+		
+	// Implementation of abstract methods
+	
+	public final double getMutationRate(double t)
+	{
+		int muIndex = 0;
+		while ((muIndex < muChanges.length) && (t > muChanges[muIndex])) {
+			muIndex += 1;
+		}
+		return mus[muIndex];
+	}
+
+	public final double getExpectedSubstitutions(double time)
+	{
+		double currentTime = 0.0;
+		double height = 0.0;
+		int muIndex = 0;
+		double timeInterval = 0.0;	
+	
+		while (time > currentTime) {
+		
+			// if no more changes in mu go straight to the end
+			if (muIndex >= muChanges.length) {
+				timeInterval = time - currentTime;
+
+				//update current time
+				currentTime = time;
+				
+			} else {
+				//find out the next time interval
+				timeInterval = muChanges[muIndex] - currentTime;
+			
+				//truncate time interval if it exceeds node height.
+				if ((currentTime + timeInterval) > time) {
+					timeInterval = time - currentTime;
+					
+					//update current time
+					currentTime = time;
+				} else {
+					//update current time
+					currentTime = muChanges[muIndex];
+				}
+
+			}
+
+			
+			// update total height in substitutions
+			height += mus[muIndex] * timeInterval;
+	
+			//update mu index
+			muIndex += 1;
+	
+		}
+		return height;
+	}
+
+	public final double getTime(double expectedSubs) {
+			
+		int changePoint = 0;
+		while ((changePoint < muChanges.length) && 
+			(expectedSubs < getExpectedSubstitutions(muChanges[changePoint]))) {
+			changePoint += 1;
+		}
+		
+		if (changePoint == 0) {
+			// before first change point
+			return expectedSubs / mus[changePoint];
+		} else {
+			double time = muChanges[changePoint-1];
+			double expectedSoFar = getExpectedSubstitutions(time);
+			time += (expectedSubs - expectedSoFar) / mus[changePoint];
+			return time;
+		}
+	}
+		
+	/**
+	 * Linearly scales this mutation rate model.
+	 * @param scale getExpectedSubstitutions should return scale instead of 1.0 at time t.
+	 */
+	public final void scale(double scale) {
+		for (int i =0 ; i < mus.length; i++) {
+			mus[i] *= scale;
+		}
+	}
+
+	public static double[] getTimeIntervals(double[] muChanges, double smallTime, double bigTime) {
+		
+		double[] intervals = new double[muChanges.length + 1];
+	
+		double currentTime = smallTime;
+		double height = 0.0;
+		
+		int muIndex = 0;
+		while((muIndex < muChanges.length) && (muChanges[muIndex] < smallTime)) {
+			muIndex += 1;
+		}
+		
+		double timeInterval = 0.0;
+		
+		while (bigTime > currentTime) {
+		
+			// if no more changes in mu go straight to the end
+			if (muIndex >= muChanges.length) {
+				intervals[muIndex] = bigTime - currentTime;
+			
+				//update current time
+				currentTime = bigTime;
+			} else {
+				//find out the next time interval
+				intervals[muIndex] = muChanges[muIndex] - currentTime;
+			
+				//truncate time interval if it exceeds node height.
+				if ((currentTime + intervals[muIndex]) > bigTime) {
+					intervals[muIndex] = bigTime - currentTime;
+
+					//update current time
+					currentTime = bigTime;
+				} else {
+					//update current time
+					currentTime = muChanges[muIndex];
+				}
+			}
+		
+			//update mu index
+			muIndex += 1;
+		}
+	
+		return intervals;
+	}
+
+	
+	public double[] getDeltas(double[] times) {
+		double height = 0.0;
+		double[] deltas = new double[times.length-1];
+		for (int i = 0; i < deltas.length; i++) {
+			deltas[i] = getExpectedSubstitutions(times[i+1]) - height;
+			height += deltas[i];
+		}
+		return deltas;
+	}
+	
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		if (fixedMus) 
+			return 0;
+		else return mus.length;
+	}
+	
+	public double getParameter(int k)
+	{
+		return mus[k];
+	}
+
+	public double getUpperLimit(int k)
+	{
+		return 1e12;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		return 0.0;
+	}
+
+	public double getDefaultValue(int k)
+	{
+		//arbitrary default values
+		if (getUnits() == GENERATIONS) {
+			return 1e-6;
+		} else {
+			return 1e-6;
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		mus[k] = value;
+	}
+
+	public void setParameterSE(double value, int k) {
+		muSEs[k] = value;
+	}
+
+	public String toString()
+	{
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Mutation rate model: stepped mutation rate ");
+			
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		out.println(" mu\tinterval");
+		for (int i = 0; i < mus.length; i++) {
+			fo.displayDecimal(out, mus[i], 6);
+			if (i == 0) {
+				out.print("\t0.0 to ");
+				fo.displayDecimal(out, muChanges[i], 6);
+				out.println();
+			} else {
+				out.print("\t");
+				fo.displayDecimal(out, muChanges[i-1], 6);
+				out.print(" to ");
+				if (i < muChanges.length) {
+					fo.displayDecimal(out, muChanges[i], 6);
+					out.println();
+				} else {
+					out.println("infinity");
+				}
+			}
+		}
+	}
+
+	public double[] getMus() {
+		double[] newMus = new double[mus.length];
+		for (int i = 0; i < newMus.length; i++) {
+			newMus[i] = mus[i];
+		}
+		return newMus;
+	}
+
+	private double[] getMuChanges() {
+		double[] newMCs = new double[muChanges.length];
+		for (int i = 0; i < newMCs.length; i++) {
+			newMCs[i] = muChanges[i];
+		}
+		return newMCs;
+	}
+
+	public String toSingleLine() {
+		String line = "";
+		for (int i = 0; i < mus.length; i++) {
+			line += "mu[" + i + "]\t" + mus[i];
+			if (i < (mus.length - 1)) {
+				line += "\t";
+			}
+		}
+		return line;
+	}
+
+	String[] summaryTypes = null;
+}
+
diff --git a/LibrarySource/pal/mep/WindowedMutationRate.java b/LibrarySource/pal/mep/WindowedMutationRate.java
new file mode 100644
index 0000000..a19dc22
--- /dev/null
+++ b/LibrarySource/pal/mep/WindowedMutationRate.java
@@ -0,0 +1,310 @@
+// WindowedMutationRate.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+ 
+package pal.mep;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * This class models a windowed mutation rate
+ * (parameter: mu = mutation rate). <BR>
+ *
+ * @version $Id: WindowedMutationRate.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class WindowedMutationRate extends MutationRateModel implements Report, Summarizable, Parameterized, Serializable
+{	
+	//
+	// Public stuff
+	//
+
+	/** mutation rates */
+	public double muBackground;
+	public double muWindow;
+
+	/** mutation rate SEs */
+	public double muBackgroundSE;
+	public double muWindowSE;
+	
+	/** mutation rate change times */
+	public double windowCenter;
+	public double windowWidth;
+
+	public boolean backgroundFixed = false;
+
+	/**
+	 * Construct demographic model with default settings
+	 */
+	public WindowedMutationRate(double windowCenter, double windowWidth, int units) {
+	
+		super();
+	
+		setUnits(units);
+
+		this.windowCenter = windowCenter;
+		this.windowWidth = windowWidth;
+
+		muBackground = getDefaultValue(0);
+		muWindow = getDefaultValue(0);	
+	}
+
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public WindowedMutationRate(double muBackground, 
+		double windowCenter, double windowWidth, int units) {
+	
+		super();
+
+		this.muBackground = muBackground;
+		backgroundFixed = true;
+
+		this.windowCenter = windowCenter;
+		this.windowWidth = windowWidth;
+
+		muWindow = getDefaultValue(0);	
+		setUnits(units);
+	}
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public WindowedMutationRate(double muWindow, double muBackground, 
+		double windowCenter, double windowWidth, int units, boolean fixedb) {
+	
+		super();
+
+		this.muWindow = muWindow;
+		this.muBackground = muBackground;
+		backgroundFixed = fixedb;
+
+		this.windowCenter = windowCenter;
+		this.windowWidth = windowWidth;
+	
+		setUnits(units);
+	}
+
+	/**
+	 * Construct mutation rate model of a give rate in given units.
+	 */
+	public WindowedMutationRate(double muWindow, double muBackground, 
+		double windowCenter, double windowWidth, int units) {
+	
+		this(muWindow, muBackground, windowCenter, windowWidth, units, false);	
+	}
+
+
+	public Object clone()
+	{
+		return new WindowedMutationRate(muWindow, muBackground, 
+			windowCenter, windowWidth, getUnits(), backgroundFixed); 
+	}
+
+	public String[] getSummaryTypes() {
+		if (summaryTypes == null) {
+			summaryTypes = new String[4];
+			summaryTypes[0] = "window mu";
+			summaryTypes[1] = "background mu";
+			summaryTypes[2] = "window center";
+			summaryTypes[3] = "window width";
+		}
+		return summaryTypes;
+	}
+
+	public double getSummaryValue(int summaryType) {
+		
+		switch (summaryType) {
+			case 0: return muWindow;
+			case 1: return muBackground;
+			case 2: return windowCenter;
+			case 3: return windowWidth;
+		}
+		throw new RuntimeException("Assertion error: unknown summary type :"+summaryType);
+	}
+
+	/**
+	 * returns current day mutation rate.
+	 */
+	public double getMu()
+	{
+		return getMutationRate(0.0);
+	}
+
+		
+	// Implementation of abstract methods
+	
+	public final double getMutationRate(double t)
+	{
+		if ((t > windowCenter - (windowWidth / 2.0)) && 
+			(t <= windowCenter + (windowWidth / 2.0))) {
+		
+			return muWindow;
+		} 
+
+		return muBackground;
+	}
+
+	/**
+	 * Window must not span zero!
+	 */
+	public final double getExpectedSubstitutions(double time)
+	{
+		double height = 0.0;
+	
+		// bit before window
+		double totalTime = windowCenter - (windowWidth / 2.0);
+		if (totalTime > time) return muBackground * time;
+		if (totalTime >= 0.0) 
+			height += muBackground * totalTime;	
+		else System.err.println("Mutation window spans time zero!");
+	
+		// window
+		if ((totalTime + windowWidth) > time) { 
+			return height + (muWindow * (time - totalTime));
+		}
+		height += muWindow * windowWidth;
+		
+		totalTime += windowWidth;
+		
+		// bit after window
+		return height + (muBackground * (time - totalTime));
+	}
+
+	/**
+	 * Window must not span zero!
+	 */
+	public final double getTime(double expected)
+	{
+		//NOTE: VERY APPROXIMATE!!! SHOULD BE IMPLEMENTED PROPERLY
+	
+		return expected / muBackground;	
+	}
+
+	/**
+	 * Linearly scales this mutation rate model.
+	 * @param scale getExpectedSubstitutions should return scale instead of 1.0 at time t.
+	 */
+	public final void scale(double scale) {
+		muBackground *= scale;
+		muWindow *= scale;
+	}
+	
+	// Parameterized interface
+
+	public int getNumParameters()
+	{
+		if (backgroundFixed) return 1;
+		return 2;
+	}
+	
+	public double getParameter(int k)
+	{
+		switch (k) {
+			case 0: return muWindow;
+			case 1: return muBackground;
+		}
+		return muWindow;
+	}
+
+	public double getUpperLimit(int k)
+	{
+		return 1e12;
+	}
+
+	public double getLowerLimit(int k)
+	{
+		return 1e-12;
+	}
+
+	public double getDefaultValue(int k)
+	{
+		//arbitrary default values
+		if (getUnits() == GENERATIONS) {
+			return 1e-6;
+		} else {
+			return 1e-6;
+		}
+	}
+
+	public void setParameter(double value, int k)
+	{
+		switch (k) {
+			case 0: muWindow = value; break;
+			case 1: muBackground = value; break;
+		}
+	}
+
+	public void setParameterSE(double value, int k) {
+		switch (k) {
+			case 0: muWindowSE = value; break;
+			case 1: muBackgroundSE = value; break;
+		}
+	}
+
+	public String toString()
+	{
+		OutputTarget out = OutputTarget.openString();
+		report(out);
+		out.close();
+		
+		return out.getString();
+	}
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Mutation rate model: windowed mutation rate ");
+			
+		out.print("Unit of time: ");
+		if (getUnits() == GENERATIONS)
+		{
+			out.print("generations");
+		}
+		else
+		{
+			out.print("expected substitutions");
+		}
+		out.println();
+		out.println();
+		out.println("Parameters of demographic function:");
+		out.print("window = ");
+		fo.displayDecimal(out, windowCenter - (windowWidth / 2.0), 6);
+		out.print(" - ");
+		fo.displayDecimal(out, windowCenter + (windowWidth / 2.0), 6);
+		out.println();
+		out.print("window mutation rate = ");
+		fo.displayDecimal(out, muWindow, 9);
+		out.println();
+		out.print("background mutation rate = ");
+		fo.displayDecimal(out, muBackground, 9);
+		out.println();
+		if (backgroundFixed) {
+			out.println("background mutation rate fixed.");
+		} else {
+			out.println("background mutation rate free to vary.");
+		}
+	}
+
+	public String toSingleLine() {
+		String line = "";
+		line += "win mu\t" + muWindow + "\t";
+		line += "bg mu\t" + muBackground + "\t";
+		line += "win cen\t" + windowCenter + "\t";
+		line += "win wid\t" + windowWidth + "\t";
+		return line;
+	}
+
+
+
+	String[] summaryTypes = null;
+}
+
diff --git a/LibrarySource/pal/mep/makefile b/LibrarySource/pal/mep/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/mep/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/mep/package.html b/LibrarySource/pal/mep/package.html
new file mode 100644
index 0000000..3ec8ce6
--- /dev/null
+++ b/LibrarySource/pal/mep/package.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+Classes for the analysis of "measurably evolving populations" (mep). 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/misc/BranchLimits.java b/LibrarySource/pal/misc/BranchLimits.java
new file mode 100644
index 0000000..48a1545
--- /dev/null
+++ b/LibrarySource/pal/misc/BranchLimits.java
@@ -0,0 +1,40 @@
+// BranchLimits.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+
+/**
+ * limits for branch lengths
+ *
+ * @version $Id: BranchLimits.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface BranchLimits
+{
+	//
+	// Public stuff
+	//
+
+	/** minimum branch length */
+	double MINARC = 1.0e-6;
+	
+	/** maximum branch length */
+	double MAXARC = 6.0;
+	
+	/** default branch length */
+	double DEFAULT_LENGTH = 0.04;
+	
+	/** maximum tolerated error when determining branch lengths */
+	double ABSTOL = 5.0e-07;
+	
+	/** desired fractional digits when determining branch lengths */
+	int FRACDIGITS = 6;
+}
+
diff --git a/LibrarySource/pal/misc/GeneralFunction.java b/LibrarySource/pal/misc/GeneralFunction.java
new file mode 100644
index 0000000..0c451e8
--- /dev/null
+++ b/LibrarySource/pal/misc/GeneralFunction.java
@@ -0,0 +1,22 @@
+// GeneralFunction.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * interface for classes which provide general function mechanisms. Essentially mappings from a n-dimensional space to a scalar value
+ *
+ * @version $Id: GeneralFunction.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+ 
+public interface GeneralFunction {
+	double compute(double[] parameters);
+	GeneralFunction getGeneralFunctionCopy();
+}
+
diff --git a/LibrarySource/pal/misc/IdGenerator.java b/LibrarySource/pal/misc/IdGenerator.java
new file mode 100644
index 0000000..39e38cc
--- /dev/null
+++ b/LibrarySource/pal/misc/IdGenerator.java
@@ -0,0 +1,42 @@
+// IdGenerator.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import java.math.*;
+import pal.io.*;
+
+/**
+ * Generates IdGroup objects given certain parameters. 
+ * 
+ * @version $Id: IdGenerator.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class IdGenerator {
+
+	/**
+	 * generates a group of unique identifiers numbered from zero.
+	 */
+	public static IdGroup createIdGroup(int size) {
+	
+		int width = (int)Math.ceil(Math.log(size) / Math.log(10.0));
+	
+		IdGroup idGroup = new SimpleIdGroup(size);
+	
+		String name;
+		for (int i = 0; i < size; i++) {
+			name = (new Integer(i)).toString();
+			name = FormattedOutput.space(width - name.length(), '0') + name;
+			idGroup.setIdentifier(i, new Identifier(name));
+		}
+	
+		return idGroup;
+	}	
+}
+
+
diff --git a/LibrarySource/pal/misc/IdGroup.java b/LibrarySource/pal/misc/IdGroup.java
new file mode 100644
index 0000000..7787125
--- /dev/null
+++ b/LibrarySource/pal/misc/IdGroup.java
@@ -0,0 +1,41 @@
+// IdGroup.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * An indexed group of identifiers. For example of group of taxa
+ * related by a phylogenetic tree. 
+ * <BR><B>NOTE:</B> Was called Taxa but not general enough.
+ *
+ * @version $Id: IdGroup.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface IdGroup extends java.io.Serializable {
+
+	/**
+	 * Returns the number of identifiers in this group
+	 */
+	int getIdCount();
+
+	/**
+	 * Returns the ith identifier.
+	 */
+	Identifier getIdentifier(int i);
+
+	/**
+	 * Sets the ith identifier.
+	 */
+	void setIdentifier(int i, Identifier id);
+
+	/**
+	 * returns the index of the identifier with the given name.
+	 */
+	int whichIdNumber(String name);
+}
+
diff --git a/LibrarySource/pal/misc/Identifier.java b/LibrarySource/pal/misc/Identifier.java
new file mode 100644
index 0000000..327ad22
--- /dev/null
+++ b/LibrarySource/pal/misc/Identifier.java
@@ -0,0 +1,67 @@
+// Identifier.java
+//
+// (c) 1999-2000 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import java.io.*;
+import pal.util.Comparable;
+
+/**
+ * An identifier for some sampled data. This will most often be 
+ * for example, the accession number of a DNA sequence, or the
+ * taxonomic name that the sequence represents, et cetera.
+ *
+ * @version $Id: Identifier.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+
+
+public class Identifier implements Serializable, 
+				   pal.util.Comparable, Nameable { 
+	
+    private String name = null;
+
+    public static Identifier ANONYMOUS = new Identifier("");
+
+    public Identifier() {}
+    
+    public Identifier(String name) {
+	setName(name);
+    }
+    
+    public String toString() {
+	return getName();
+    }
+    
+    // implements Comparable interface
+
+    public int compareTo(Object c) {
+	
+	return getName().compareTo(((Identifier)c).getName());
+    }
+
+    public boolean equals(Object c) {
+	
+	if (c instanceof Identifier) {
+	    return getName().equals(((Identifier)c).getName());
+	} else return false;
+    }
+     
+    // implements Nameable interface
+
+    public String getName() {
+	return name;
+    }
+    
+    public void setName(String s) {
+	name = s;
+    }
+    
+}
+
+
diff --git a/LibrarySource/pal/misc/Nameable.java b/LibrarySource/pal/misc/Nameable.java
new file mode 100644
index 0000000..bdfa915
--- /dev/null
+++ b/LibrarySource/pal/misc/Nameable.java
@@ -0,0 +1,35 @@
+// Nameable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import java.io.*;
+
+/**
+ * interface for classes that can be named.
+ *
+ * @version $Id: Nameable.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Nameable
+{
+	/**
+	 * get the name of this object.
+	 *
+	 * @return name of this object.
+	 */
+	String getName();
+
+	/**
+	 * set the name of this object.
+	 *
+	 * @param name the new name.
+	 */
+	void setName(String name);
+}
+
diff --git a/LibrarySource/pal/misc/Parameterized.java b/LibrarySource/pal/misc/Parameterized.java
new file mode 100644
index 0000000..2215ca1
--- /dev/null
+++ b/LibrarySource/pal/misc/Parameterized.java
@@ -0,0 +1,85 @@
+// Parameterized.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+import java.io.*;
+
+
+/**
+ * interface for class with (optimizable) parameters
+ *
+ * @version $Id: Parameterized.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface Parameterized
+{
+	/**
+	 * get number of parameters
+	 *
+	 * @return number of parameters
+	 */
+	int getNumParameters();
+
+	/**
+	 * set model parameter
+	 *
+	 * @param param  parameter value
+	 * @param n  parameter number
+	 */
+	void setParameter(double param, int n);
+
+	/**
+	 * get model parameter
+	 *
+	 * @param n  parameter number
+	 *
+	 * @return parameter value
+	 */
+	double getParameter(int n);
+
+	
+	/**
+	 * set standard errors for model parameter
+	 *
+	 * @param paramSE  standard error of parameter value
+	 * @param n parameter number
+	 */
+	void setParameterSE(double paramSE, int n);
+
+	
+	/**
+	 * get lower parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return lower bound
+	 */
+	double getLowerLimit(int n);
+
+	/**
+	 * get upper parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return upper bound
+	 */
+	double getUpperLimit(int n);
+
+
+	/**
+	 * get default value of parameter
+	 *
+	 * @param n parameter number
+	 *
+	 * @return default value
+	 */
+	double getDefaultValue(int n);
+}
+
diff --git a/LibrarySource/pal/misc/ParameterizedDouble.java b/LibrarySource/pal/misc/ParameterizedDouble.java
new file mode 100644
index 0000000..62f49ed
--- /dev/null
+++ b/LibrarySource/pal/misc/ParameterizedDouble.java
@@ -0,0 +1,144 @@
+// ParameterizedDouble.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+import java.io.*;
+
+
+/**
+ * interface for a double that might be used as a parameter
+ *
+ * @version $Id: ParameterizedDouble.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public class ParameterizedDouble implements Parameterized{
+	double defaultValue_;
+	double currentValue_;
+	double minimumValue_;
+	double maximumValue_;
+	double se_;
+
+	/** The default value is also the initial value.
+	*/
+	public ParameterizedDouble(double defaultValue, double minimumValue, double maximumValue) {
+		this.currentValue_ = defaultValue;
+		this.defaultValue_ = defaultValue;
+		this.minimumValue_ = minimumValue;
+		this.maximumValue_ = maximumValue;
+	}
+
+	/** Set the current value of this double */
+	public final void setValue(double value) {
+		this.currentValue_ = value;
+	}
+
+	/** Get the current value of this double */
+	public final double getValue() {
+   	return currentValue_;
+	}
+
+	public final double getLowerLimit() {
+		return minimumValue_;
+	}
+
+	public final double getUpperLimit() {
+		return maximumValue_;
+	}
+
+	public final double getDefaultValue() {
+		return defaultValue_;
+	}
+
+	public final double getSE() {
+		return se_;
+	}
+
+	public final void setSE(double value) {
+		se_ = value;
+	}
+
+
+
+	/**
+	 *
+	 * @return 1
+	 */
+	public int getNumParameters() {
+		return 1;
+	}
+
+	/**
+	 * set model parameter
+	 *
+	 * @param param  parameter value
+	 * @param n  parameter number (ignored)
+	 */
+	public void setParameter(double param, int n) {
+		this.currentValue_ = param;
+	}
+
+	/**
+	 * get model parameter
+	 *
+	 * @param n  parameter number
+	 *
+	 * @return parameter value
+	 */
+	public double getParameter(int n) {
+   	return currentValue_;
+	}
+
+
+	/**
+	 * set standard errors for model parameter
+	 *
+	 * @param paramSE  standard error of parameter value
+	 * @param n parameter number
+	 */
+	public void setParameterSE(double paramSE, int n) {
+		this.se_ = paramSE;
+	}
+
+	
+	/**
+	 * get lower parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return lower bound
+	 */
+	public double getLowerLimit(int n) {
+   	return minimumValue_;
+	}
+
+	/**
+	 * get upper parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return upper bound
+	 */
+	public double getUpperLimit(int n) {
+   	return maximumValue_;
+	}
+
+
+	/**
+	 * get default value of parameter
+	 *
+	 * @param n parameter number
+	 *
+	 * @return default value
+	 */
+	public double getDefaultValue(int n) {
+		return defaultValue_;
+	}
+}
+
diff --git a/LibrarySource/pal/misc/Product.java b/LibrarySource/pal/misc/Product.java
new file mode 100644
index 0000000..2bd8f41
--- /dev/null
+++ b/LibrarySource/pal/misc/Product.java
@@ -0,0 +1,32 @@
+// Product.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * A GeneralFucnction that multiplies all the input values.
+ *
+ * @version $Id: Product.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+
+public class Product implements GeneralFunction {
+	public double compute(double[] parameters) {
+		double product = 1.0;
+		for(int i = 0 ; i < parameters.length ; i++) {
+			product *= parameters[i];
+		}
+		return product;
+	}
+	/** No actual cloning is performed (returns self), as no state is
+		kept */
+	public GeneralFunction getGeneralFunctionCopy() {
+		return this;
+	}
+} 
+
diff --git a/LibrarySource/pal/misc/ReleaseInfo.java b/LibrarySource/pal/misc/ReleaseInfo.java
new file mode 100644
index 0000000..169aefd
--- /dev/null
+++ b/LibrarySource/pal/misc/ReleaseInfo.java
@@ -0,0 +1,31 @@
+// ReleaseInfo.java
+//
+// (c) 1999-2001 Korbinian Strimmer
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+
+/**
+ * release information
+ *
+ * @version $Id: ReleaseInfo.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ReleaseInfo
+{
+	//
+	// Public stuff
+	//
+
+	/** version */
+	public final static String VERSION = "PAL 1.3";
+	
+	/** release date */
+	public final static String RELEASE_DATE = "July 14, 2001";
+}
+
diff --git a/LibrarySource/pal/misc/Report.java b/LibrarySource/pal/misc/Report.java
new file mode 100644
index 0000000..1493f71
--- /dev/null
+++ b/LibrarySource/pal/misc/Report.java
@@ -0,0 +1,30 @@
+// Report.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+import java.io.*;
+
+
+/**
+ * interface for classes that can print out a human readable report of itself
+ *
+ * @version $Id: Report.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface Report
+{
+	/**
+	 * print human readable report (e.g., on parameters and associated model)
+	 *
+	 * @param out output stream
+	 */
+	void report(PrintWriter out);
+}
+
diff --git a/LibrarySource/pal/misc/SimpleIdGroup.java b/LibrarySource/pal/misc/SimpleIdGroup.java
new file mode 100644
index 0000000..e111bf6
--- /dev/null
+++ b/LibrarySource/pal/misc/SimpleIdGroup.java
@@ -0,0 +1,169 @@
+// SimpleIdGroup.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Default implementation of IdGroup interface. 
+ * Memory-inefficient to allow fast whichIdNumber calls.
+ *
+ * @version $Id: SimpleIdGroup.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class SimpleIdGroup implements IdGroup, Serializable, Nameable {
+	
+	private String name;
+	private Identifier[] ids;
+	private Hashtable indices;
+	
+	/**
+	 * Constructor taking the size of the group.
+	 */
+	public SimpleIdGroup(int size) {
+	  this(size,false);
+
+	}
+
+	/**
+	 * Constructor taking an array of strings.
+	 */
+	public SimpleIdGroup(String[] labels) {
+		this(labels.length);
+		for (int i = 0; i < labels.length; i++) {
+			setIdentifier(i, new Identifier(labels[i]));
+		}
+	}
+
+
+	/**
+	 * Constructor taking the size of the group.
+   * @param size - the number of ids
+   * @param createIDs - if true creates default Indetifiers.
+                        Otherwise leaves blank (for user to fill in)
+	 */
+	public SimpleIdGroup(int size, boolean createIDs) {
+
+		ids = new Identifier[size];
+		indices = new Hashtable(size);
+    if(createIDs) {
+      for(int i = 0 ; i < size ; i++ ) {
+        setIdentifier(i, new Identifier(""+i));
+      }
+    }
+	}
+
+	/**
+	 * Constructor taking an array of identifiers.
+	 */
+	public SimpleIdGroup(Identifier[] id) {
+		this(id.length);
+		for (int i = 0; i < id.length; i++) {
+			setIdentifier(i, id[i]);
+		}
+	}
+
+	/**
+	 * Constructor taking two separate id groups and merging them.
+	 */
+	public SimpleIdGroup(IdGroup a, IdGroup b) {
+		this(a.getIdCount() + b.getIdCount());
+
+		for (int i = 0; i < a.getIdCount(); i++) {
+			setIdentifier(i, a.getIdentifier(i));
+		}
+		for (int i = 0; i < b.getIdCount(); i++) {
+			setIdentifier(i + a.getIdCount(), b.getIdentifier(i));
+		}
+	}
+	/**
+	 * Impersonating Constructor.
+	 */
+	public SimpleIdGroup(IdGroup a) {
+		this(a.getIdCount());
+
+		for (int i = 0; i < a.getIdCount(); i++) {
+			setIdentifier(i, a.getIdentifier(i));
+		}
+	}
+	/**
+	 * Returns the number of identifiers in this group
+	 */
+	public int getIdCount() {
+		return ids.length;
+	}
+	
+	/**
+	 * Returns the ith identifier.
+	 */
+	public Identifier getIdentifier(int i) {
+		return ids[i];
+	}
+
+	/**
+	 * Convenience method to return the name of identifier i
+	 */
+	public final String getName(int i) {
+		return ids[i].getName();
+	}
+
+	/**
+	 * Sets the ith identifier.
+	 */
+	public void setIdentifier(int i, Identifier id) {
+		ids[i] = id;	
+		indices.put(id.getName(), new Integer(i));
+	}
+	
+	/**
+	 * Return index of identifier with name or -1 if not found
+	 */
+	public int whichIdNumber(String name) {
+
+		Integer index = (Integer)indices.get(name);
+		if (index != null) {
+			return index.intValue();
+		}
+		return -1;
+	}
+	
+	/**
+	 * Returns a string representation of this IdGroup in the form of 
+	 * a bracketed list.
+	 */
+	public String toString() {
+	
+		StringBuffer sb = new StringBuffer();
+		sb.append("[ ");
+		for (int i = 0; i < getIdCount(); i++) {
+			sb.append(getIdentifier(i) + " ");
+		}
+		sb.append("]");
+		return new String(sb);
+	}
+
+	// implement Nameable interface 
+
+	/**
+	 * Return the name of this IdGroup.
+	 */
+	public String getName() { 
+		return name; 
+	}
+	
+	/**
+	 * Sets the name of this IdGroup.
+	 */
+	public void setName(String n) { 
+		name = n; 
+	}
+}
+
+
diff --git a/LibrarySource/pal/misc/SimpleSummarizable.java b/LibrarySource/pal/misc/SimpleSummarizable.java
new file mode 100644
index 0000000..5a199cc
--- /dev/null
+++ b/LibrarySource/pal/misc/SimpleSummarizable.java
@@ -0,0 +1,56 @@
+// SimpleSummarizable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+/**
+ * A simple implementation of a Summarizable object. Can be used to provide a
+ * summarizable object based upon another summarizable object but with the
+ * minimum storage requirement (see SimpleSummarizable(Summarizable) constructor.
+ *
+ *
+ * @version $Id: SimpleSummarizable.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+package pal.misc;
+
+public class SimpleSummarizable implements Summarizable, java.io.Serializable {
+	private String[] types_;
+	private double[] values_;
+
+	/**
+			The simple constructor
+			@note param types and param values should be of the same length
+	*/
+	public SimpleSummarizable(String[] types, double[] values) {
+		this.types_ = types;
+		this.values_ = values;
+	}
+
+	/** The Imitation constructor - for immitating another Summarizable object with
+			minimum memory requirements
+			@param toImitiate - the Summarizable to imitate. This summarizable with contatin
+													the same types and values as toImitate (at the time of construction)
+			@note No reference to toImitate is maintained.
+	*/
+	public SimpleSummarizable(Summarizable toImitate) {
+		this.types_ = toImitate.getSummaryTypes();
+		this.values_ = new double[this.types_.length];
+		for(int i = 0 ; i < values_.length ; i++) {
+			this.values_[i] = toImitate.getSummaryValue(i);
+		}
+	}
+
+	public String[] getSummaryTypes() {
+		return this.types_;
+	}
+
+	public double getSummaryValue(int type) {
+   	return this.values_[type];
+	}
+
+} 
+
diff --git a/LibrarySource/pal/misc/Sum.java b/LibrarySource/pal/misc/Sum.java
new file mode 100644
index 0000000..b7907e9
--- /dev/null
+++ b/LibrarySource/pal/misc/Sum.java
@@ -0,0 +1,33 @@
+// Sum.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * A GeneralFucnction that sums all the input values.
+ *
+ * @version $Id: Sum.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+ 
+public class Sum implements GeneralFunction {
+	public double compute(double[] parameters) {
+		double sum = 0.0;
+		for(int i = 0 ; i < parameters.length ; i++) {
+			sum += parameters[i];
+		}
+		return sum;
+	}
+
+	/** No actual cloning is performed (returns self), as no state is
+			kept */
+	public GeneralFunction getGeneralFunctionCopy() {
+		return this;
+	}
+} 
+
diff --git a/LibrarySource/pal/misc/SumToOneWeighting.java b/LibrarySource/pal/misc/SumToOneWeighting.java
new file mode 100644
index 0000000..cb88323
--- /dev/null
+++ b/LibrarySource/pal/misc/SumToOneWeighting.java
@@ -0,0 +1,198 @@
+// Weighting.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+import java.io.*;
+
+/**
+ * A weighting for n values. Has n-1 parameters. Weightings sum to 1.
+ *
+ * @version $Id: SumToOneWeighting.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+
+public class SumToOneWeighting implements Weighting {
+	double[] parameters_; /** The parameters */
+	double[] parametersSE_; /** The parameters' SE*/
+	double[] defaultValues_; /** The default values for the parameters */
+	double[] weightings_; /** The weightings (dependent on p0, p1) */
+	boolean rigidParameters_;
+
+	/**
+		* @param defaultValues The default, and initial, parameters (n is determined by the number of parameters + 1)
+		*/
+	public SumToOneWeighting(double[] defaultParameters) {
+		this(defaultParameters,defaultParameters.length+1);
+	}
+	/**
+		* @param defaultValues The default, and initial, parameters and n the number of weights (ignores extra parameters)
+		* @param n The number of weights (not the number of parameters!)
+		* @note Parameters are not rigid and can be adjusted.
+		*/
+	public SumToOneWeighting(double[] defaultParameters, int n) {
+		this(defaultParameters,n,false);
+	}
+	/**
+		* @param defaultValues The default, and initial, parameters and n the number of weights (ignores extra parameters)
+		* @param n The number of weights (not the number of parameters!)
+		* @param rigidParam If true than this weighting has not adjustable paramters (that is, is reported is as having zero parameters in the Paraterizable interface)
+		*/
+	public SumToOneWeighting(double[] defaultParameters, int n, boolean rigidParameters) {
+		this.rigidParameters_ = rigidParameters;
+		weightings_ = new double[n];
+		defaultValues_ = new double[n-1];
+		parameters_ = new double[n-1];
+		parametersSE_ = new double[n-1];
+		for(int i = 0 ; i < n ; i++) {
+			defaultValues_[i] = defaultParameters[i];
+			parameters_[i] = defaultParameters[i];
+		}
+		recalculateWeightings();
+
+	}
+	public SumToOneWeighting(SumToOneWeighting toCopy) {
+		int n = toCopy.weightings_.length;
+		weightings_ = new double[n];
+		defaultValues_ = new double[n-1];
+		parameters_ = new double[n-1];
+		parametersSE_ = new double[n-1];
+		for(int i = 0 ; i < (n-1) ; i++) {
+			this.defaultValues_[i] = toCopy.defaultValues_[i];
+			this.parameters_[i] = toCopy.parameters_[i];
+			this.parametersSE_[i] = toCopy.parametersSE_[i];
+		}
+		recalculateWeightings();
+	}
+
+	public double getWeight(int weightNumber) {
+		return weightings_[weightNumber];
+	}
+
+	public double[] getWeights() {
+		return weightings_;
+	}
+	/** For people who don't like casting...*/
+	public Weighting getWeightingCopy() {
+		return new SumToOneWeighting(this);
+	}
+	/**
+	 * get number of parameters
+	 *
+	 * @return number of parameters
+	 */
+	public int getNumParameters() {
+		return (rigidParameters_ ? 0 : parameters_.length);
+	}
+
+	/** Calculate the weightings from the current parameter values */
+	private void recalculateWeightings() {
+    double total = 1;
+		for(int i = 0 ; i < parameters_.length ; i++) {
+			total+=parameters_[i];
+		}
+		for(int i = 0 ; i < parameters_.length ; i++) {
+			weightings_[i] = parameters_[i]/total;
+		}
+		weightings_[parameters_.length] = 1/total;
+	}
+
+	/**
+	 * set model parameter
+	 *
+	 * @param param  parameter value
+	 * @param n  parameter number
+	 */
+	public void setParameter(double param, int n) {
+		if(rigidParameters_) {
+			throw new RuntimeException("Assertion error - Attempting to set rigid paramters");
+		}
+		parameters_[n] = param;
+		recalculateWeightings();
+	}
+
+	/**
+	 * get model parameter
+	 *
+	 * @param n  parameter number
+	 *
+	 * @return parameter value
+	 */
+	public double getParameter(int n) {
+		return parameters_[n];
+	}
+
+
+	/**
+	 * set standard errors for model parameter
+	 *
+	 * @param paramSE  standard error of parameter value
+	 * @param n parameter number
+	 */
+	public void setParameterSE(double paramSE, int n) {
+		parametersSE_[n] = paramSE;
+	}
+
+
+	/**
+	 * get lower parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return lower bound
+	 */
+	public double getLowerLimit(int n) {
+		return 0;
+	}
+
+	/**
+	 * get upper parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return upper bound
+	 */
+	public double getUpperLimit(int n) {
+		return Double.MAX_VALUE;
+	}
+
+
+	/**
+	 * get default value of parameter
+	 *
+	 * @param n parameter number
+	 *
+	 * @return default value
+	 */
+	public double getDefaultValue(int n) {
+		return defaultValues_[n];
+	}
+
+	public void report(PrintWriter out) {
+		out.print("Sum To One Weighting");
+		if(rigidParameters_) {
+			out.println("(Rigid Parameters)");
+		} else {
+			out.println("");
+		}
+		out.print("Weights:");
+		for(int i = 0 ; i < weightings_.length ; i++) {
+			out.print(weightings_[i]+" ");
+		}
+		out.println();
+		out.println("Parameters:");
+		for(int i = 0 ; i < parameters_.length ; i++) {
+			out.print(parameters_[i]+" ");
+		}
+		out.println();
+		out.println("Parameters SE:");
+		for(int i = 0 ; i < parametersSE_.length ; i++) {
+			out.print(parametersSE_[i]+" ");
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/misc/Summarizable.java b/LibrarySource/pal/misc/Summarizable.java
new file mode 100644
index 0000000..b590074
--- /dev/null
+++ b/LibrarySource/pal/misc/Summarizable.java
@@ -0,0 +1,23 @@
+// Parameterized.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+/**
+ * interface for classes that can provide summaries
+ *
+ * @version $Id: Summarizable.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Summarizable extends java.io.Serializable
+{
+	String[] getSummaryTypes();
+	double getSummaryValue(int summaryType);
+} 
+
diff --git a/LibrarySource/pal/misc/TimeOrderCharacterData.java b/LibrarySource/pal/misc/TimeOrderCharacterData.java
new file mode 100644
index 0000000..96f4cc7
--- /dev/null
+++ b/LibrarySource/pal/misc/TimeOrderCharacterData.java
@@ -0,0 +1,387 @@
+// TimeOrderCharacterData.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import java.io.*;
+import pal.util.*;
+import pal.math.*;
+
+/**
+ * Character data that expresses an order through time.
+ * 
+ * @version $Id: TimeOrderCharacterData.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class TimeOrderCharacterData implements Serializable, BranchLimits, IdGroup {
+	 
+	/** Order of times */
+	protected int[] timeOrdinals = null;
+	
+	/** Actual times of each sample */
+	protected double[] times = null;
+	
+	/** the identifier group */
+	protected IdGroup taxa;
+
+	protected int units = Units.GENERATIONS;
+	
+	/**
+	 * Parameterless constructor for superclasses.
+	 */
+	protected TimeOrderCharacterData() {}
+	
+	/**
+	 * Constructor taking only IdGroup.
+	 * Beware! This constructor does not initialize 
+	 * any time ordinals or times.
+	 */
+	public TimeOrderCharacterData(IdGroup taxa, int units) {
+		this.taxa = taxa;
+	}
+   
+	/**
+	 * Constructs a TimeOrderCharacterData.
+	 */
+	public TimeOrderCharacterData(int numSeqsPerSample, int numSamples, 
+		double timeBetweenSamples, int units) {
+		
+		int n = numSeqsPerSample * numSamples;
+		
+		taxa = IdGenerator.createIdGroup(n);
+
+		// create times and ordinals
+		timeOrdinals = new int[taxa.getIdCount()];
+		times = new double[taxa.getIdCount()];
+	
+		
+		int index = 0;
+		for (int i = 0; i < numSamples; i++) {
+			for (int j = 0; j < numSeqsPerSample; j++) {
+				times[index] = timeBetweenSamples * (double)i;
+				timeOrdinals[index] = i;
+				index += 1;
+			}
+		}
+
+		this.units = units;
+	}
+
+	/**
+	 * Returns a clone of the specified TimeOrderCharacterData 
+	 */
+	public static TimeOrderCharacterData clone(TimeOrderCharacterData tocd) {
+		return tocd.subset(tocd);
+	}
+	 
+	/**
+	 * Extracts a subset of a TimeOrderCharacterData.
+	 */
+	public TimeOrderCharacterData subset(IdGroup staxa) {
+	
+		TimeOrderCharacterData subset = 
+			new TimeOrderCharacterData(staxa, getUnits());
+	 
+		subset.timeOrdinals = new int[staxa.getIdCount()];
+		if (hasTimes()) {
+			subset.times = new double[staxa.getIdCount()];
+		}
+		
+		for (int i = 0; i < subset.timeOrdinals.length; i++) {
+			int index = taxa.whichIdNumber(staxa.getIdentifier(i).getName());
+			subset.timeOrdinals[i] = timeOrdinals[index];
+	
+			if (hasTimes()) {
+				subset.times[i] = times[index];
+			}
+		}
+		return subset;
+	}
+
+	public int getUnits() {
+		return units;
+	}
+
+	/**
+	 * Sets the times, and works out what the ordinals should be.
+	 */
+	public void setTimes(double[] times, int units) {
+		setTimes(times, units, true);
+	}
+	 
+	/**
+	 * Sets the times. 
+	 * @param recalculateOrdinals true if ordinals should be 
+	 * recalculated from the times.
+	 */
+	public void setTimes(double[] times, int units, boolean recalculateOrdinals) {
+		this.times = times;
+		this.units = units;
+		if (recalculateOrdinals) {
+			setOrdinalsFromTimes();
+		}
+	}
+
+	public TimeOrderCharacterData scale(double rate, int newUnits) {
+		
+		TimeOrderCharacterData scaled = clone(this);
+		
+		scaled.units = newUnits;
+		for (int i = 0; i < times.length; i++) {
+			scaled.times[i] = times[i] * rate;
+		}
+
+		return scaled;
+	}
+
+	/** 
+	 * Sets ordinals.
+	 */
+	public void setOrdinals(int[] ordinals) {
+		timeOrdinals = ordinals;
+	}
+
+	/**
+	 * Gets ordinals.
+	 */
+	public int[] getOrdinals() {
+		return timeOrdinals;
+	}
+
+	/**
+	 * Returns a copy of the times in the form of an array.
+	 */
+	public double[] getCopyOfTimes() {
+		double[] copyTimes = new double[times.length];
+		System.arraycopy(times, 0, copyTimes, 0, times.length);
+
+		return copyTimes;
+	}
+
+	/**
+	 * Remove time character data.
+	 */
+	public void removeTimes() {
+		times = null;
+	}
+	
+	/**
+	 * Set time ordinals from another TimeOrderCharacterData.
+	 * Select ordinals by matching names.
+	 * @param tocd to take ordinals from.
+	 */
+	public void setOrdinals(TimeOrderCharacterData tocd) {
+		setOrdinals(tocd, null, false);
+	}
+
+	public void setTimesAndOrdinals(TimeOrderCharacterData tocd) {
+		setOrdinals(tocd, null, true);
+	}
+
+	/**
+	 * Set time ordinals from another TimeOrderCharacterData.
+	 * Select ordinals by matching names.
+	 * @param tocd to take ordinals from
+	 * @param idgroup use these labels to match indices in given tocd.
+	 * @param doTimes if set then sets times as well
+	 */
+	public void setOrdinals(TimeOrderCharacterData tocd, IdGroup standard, boolean doTimes) {
+		
+		if (timeOrdinals == null) {
+			timeOrdinals = new int[taxa.getIdCount()];
+		}
+
+		if (doTimes && tocd.hasTimes()) {
+			times = new double[taxa.getIdCount()];
+		}
+		
+		if (standard == null) {
+			standard = tocd;
+		}
+	
+		for (int i = 0; i < taxa.getIdCount(); i++) {
+			
+			String name = taxa.getIdentifier(i).getName();
+			int index = standard.whichIdNumber(name);
+		 	if (index == -1) {
+				System.err.println("Identifiers don't match!");
+				System.err.println("Trying to find: '" + name + "' in:");
+				System.err.println(standard);
+				//System.exit(1);
+			}
+			
+			timeOrdinals[i] = tocd.getTimeOrdinal(index);
+			if (doTimes && tocd.hasTimes()) {
+				times[i] = tocd.getTime(index);
+			}
+		}
+	}
+
+	private void setOrdinalsFromTimes() {
+		
+		int[] indices = new int[times.length];
+		timeOrdinals = new int[times.length];
+		HeapSort.sort(times, indices);
+
+		int ordinal = 0;
+		int lastIndex = 0;
+		timeOrdinals[indices[0]] = ordinal;
+		
+		for (int i = 1; i < indices.length; i++) {
+			if (Math.abs(times[indices[i]] - times[indices[lastIndex]]) <= ABSTOL) {
+				// this time is still within the tolerated error
+			} else {
+				// this is definitely a new time
+				lastIndex = i;
+				ordinal += 1;
+			}
+			timeOrdinals[indices[i]] = ordinal;
+		}
+	}
+	
+	/**
+	 * Returns the number of characters per identifier 
+	 */
+	public int getNumChars() {
+		if (hasTimes()) {
+			return 2;
+		} else return 1;
+	}
+	
+	/**
+	 * Returns a name for this character data.
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Sets the name of this character data.
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public double getTime(int taxon) {
+		return times[taxon];
+	}
+
+	/**
+	 * NOTE: currently assumes times exist!
+	 */
+	public double getHeight(int taxon, double rate) {
+		return times[taxon] * rate; 
+	}
+	
+	public int getTimeOrdinal(int taxon) {
+		return timeOrdinals[taxon];
+	}
+	
+	public boolean hasTimes() {
+		return times != null;
+	}
+
+	/**
+	 * Returns an ordered vector of unique times in this
+	 * time order character data.
+	 */
+	public double[] getUniqueTimeArray() {
+		int count = getSampleCount();
+	
+		double[] utimes = new double[count];
+		for (int i = 0; i < times.length; i++) {
+			utimes[getTimeOrdinal(i)] = times[i];
+		}
+
+		return utimes;
+	}
+
+	/**
+	 * Returns a matrix of times between samples. A
+	 * sample is any set of identifiers that have the same times.
+	 */
+	public double[][] getUniqueTimeMatrix() {
+	
+		
+		double[] utimes = getUniqueTimeArray();
+		int count = utimes.length;
+		
+		double[][] stimes = new double[count][count];
+		for (int i = 0; i < count; i++) {
+			for (int j = 0; j < count; j++) {
+				stimes[i][j] = Math.abs(utimes[i] - utimes[j]);
+			}
+		}
+		
+		return stimes;
+	}
+		
+	/**
+	 * Returns the number of unique times in this data.
+	 * A sample is any set of identifiers that have the same times.
+	 */
+	public int getSampleCount() {
+		int max = 0;
+		for (int i = 0; i < timeOrdinals.length; i++) {
+			if (timeOrdinals[i] > max) max = timeOrdinals[i];
+		}
+		return max + 1;
+	}
+	
+	/** 
+	 * Returns a string representation of this time order character data.
+	 */
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		
+		sb.append("Identifier\t"+ (hasTimes() ? "Times\t" : "") + "Sample\n");
+		for (int i = 0; i < taxa.getIdCount(); i++) {
+			sb.append(taxa.getIdentifier(i) + "\t" + 
+				(hasTimes() ? getTime(i) + "\t" : "") + 
+				getTimeOrdinal(i)+"\n"); 
+		}
+		return new String(sb);
+	}
+
+	public void shuffleTimes() {
+		MersenneTwisterFast mtf = new MersenneTwisterFast();
+		
+		int[] indices = mtf.shuffled(timeOrdinals.length);
+		
+		int[] newOrdinals = new int[timeOrdinals.length];
+		double[] newTimes = null;
+		if (hasTimes()) {
+			newTimes = new double[times.length];
+		}
+		for (int i = 0; i < timeOrdinals.length; i++) {
+			newOrdinals[i] = timeOrdinals[indices[i]];
+			if (hasTimes()) { newTimes[i] = times[indices[i]]; }
+		}
+
+		timeOrdinals = newOrdinals;
+		if (hasTimes()) times = newTimes;
+	}
+
+	//IdGroup interface
+	public Identifier getIdentifier(int i) {return taxa.getIdentifier(i);}
+	public void setIdentifier(int i, Identifier ident) { taxa.setIdentifier(i, ident); }
+	public int getIdCount() { return taxa.getIdCount(); }
+	public int whichIdNumber(String name) { return taxa.whichIdNumber(name); }
+
+	/**
+	 * Return id group of this alignment. 
+	 * @deprecated TimeOrderCharacterData now implements IdGroup
+	 */
+	public IdGroup getIdGroup() { return taxa; }
+
+	// PRIVATE STUFF
+
+	/** Name of this character data */
+	private String name = "Time/order character data";
+}
+
diff --git a/LibrarySource/pal/misc/TimeStamp.java b/LibrarySource/pal/misc/TimeStamp.java
new file mode 100644
index 0000000..5341f5d
--- /dev/null
+++ b/LibrarySource/pal/misc/TimeStamp.java
@@ -0,0 +1,66 @@
+// TimeStamp.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.misc;
+
+import java.util.*;
+import java.io.*;
+
+
+/**
+ * keeps track of program runtime
+ *
+ * @author Korbinian Strimmer
+ */
+public class TimeStamp
+{
+	//
+	// Public stuff
+	//
+
+	/** create object and start timer */
+	public TimeStamp()
+	{
+		startDate = new Date();
+		startTime = startDate.getTime();
+		stopDate = null;
+	}
+
+	/** stop timer */
+	public void stop()
+	{
+		stopDate = new Date();
+		stopTime = stopDate.getTime();
+			
+		runSecs = Math.round((stopTime - startTime)/100.0)/10.0;
+		
+	}
+	
+	/**
+	 * report on runtime
+	 *
+	 * @param out output stream
+	 */
+	public void report(PrintWriter out)
+	{
+		if (stopDate == null) return;
+		
+		out.println("Date: " + startDate.toString());
+		out.println("Runtime: " + runSecs + " seconds");
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	private double runSecs;
+	private int status;
+	private Date startDate, stopDate;
+	private long startTime, stopTime;
+}
+
diff --git a/LibrarySource/pal/misc/UniformWeighting.java b/LibrarySource/pal/misc/UniformWeighting.java
new file mode 100644
index 0000000..553844c
--- /dev/null
+++ b/LibrarySource/pal/misc/UniformWeighting.java
@@ -0,0 +1,124 @@
+// UniformWeighting.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+import java.io.*;
+
+/**
+ * A uniform weighting for n values (where each weighting is 1/n)
+ * @version $Id: UniformWeighting.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+
+public class UniformWeighting implements Weighting {
+	private double[] weightings_; 
+	/**
+		* @param The number of weightings
+		*/
+	public UniformWeighting(int n) {
+		this.weightings_ = new double[n];
+		for(int i = 0 ; i < n ; i++) {
+     	weightings_[i] = 1.0/(double)n;
+		}
+	}
+
+	public UniformWeighting(UniformWeighting toCopy) {
+		weightings_ = pal.misc.Utils.getCopy(toCopy.weightings_);
+	}
+
+	public double getWeight(int weightNumber) {
+		return weightings_[weightNumber];
+	}
+
+	public double[] getWeights() {
+		return weightings_;
+	}
+	/** For people who don't like casting...*/
+	public Weighting getWeightingCopy() {
+		return new UniformWeighting(this);
+	}
+	/**
+	 * get number of parameters
+	 *
+	 * @return number of parameters
+	 */
+	public int getNumParameters() {
+		return 0;
+	}
+	/**
+	 * set model parameter
+	 *
+	 * @param param  parameter value
+	 * @param n  parameter number
+	 */
+	public void setParameter(double param, int n) {
+		throw new RuntimeException("Assertion error - Attempting to set paramters");
+	}
+
+	/**
+	 * get model parameter
+	 *
+	 * @param n  parameter number
+	 *
+	 * @return parameter value
+	 */
+	public double getParameter(int n) {
+		throw new RuntimeException("Assertion error - Attempting to get paramters");
+	}
+
+
+	/**
+	 * set standard errors for model parameter
+	 *
+	 * @param paramSE  standard error of parameter value
+	 * @param n parameter number
+	 */
+	public void setParameterSE(double paramSE, int n) {
+		throw new RuntimeException("Assertion error - Illegal paramter usage");
+	}
+
+
+	/**
+	 * get lower parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return lower bound
+	 */
+	public double getLowerLimit(int n) {
+		throw new RuntimeException("Assertion error - Illegal paramter usage");
+	}
+
+	/**
+	 * get upper parameter limit
+	 *
+	 * @param n parameter number
+	 *
+	 * @return upper bound
+	 */
+	public double getUpperLimit(int n) {
+		throw new RuntimeException("Assertion error - Illegal paramter usage");
+	}
+
+
+	/**
+	 * get default value of parameter
+	 *
+	 * @param n parameter number
+	 *
+	 * @return default value
+	 */
+	public double getDefaultValue(int n) {
+		throw new RuntimeException("Assertion error - Illegal paramter usage");
+	}
+
+	public void report(PrintWriter out) {
+		out.print("Uniform Weighting");
+	}
+}
+
diff --git a/LibrarySource/pal/misc/Units.java b/LibrarySource/pal/misc/Units.java
new file mode 100644
index 0000000..ac7be17
--- /dev/null
+++ b/LibrarySource/pal/misc/Units.java
@@ -0,0 +1,24 @@
+// Units.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * interface holding unit constants
+ *
+ * @version $Id: Units.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Units
+{
+    int EXPECTED_SUBSTITUTIONS = 0;
+    int GENERATIONS = 1;
+    int DAYS = 2;
+    int YEARS = 3;
+}
+
diff --git a/LibrarySource/pal/misc/Utils.java b/LibrarySource/pal/misc/Utils.java
new file mode 100644
index 0000000..1349f73
--- /dev/null
+++ b/LibrarySource/pal/misc/Utils.java
@@ -0,0 +1,118 @@
+// Utils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+import pal.math.*;
+
+/**
+ * Provides some miscellaneous methods.
+ *
+ * @version $Id: Utils.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public class Utils {
+
+	/** Clones an array of doubles
+		* @return null if input is null, otherwise return complete copy.
+		*/
+	public static final double[] getCopy(double[] array) {
+		if(array == null) {
+			return null;
+		}
+		double[] copy = new double[array.length];
+		for(int i = 0 ; i < copy.length ; i++) {
+			copy[i] = array[i];
+		}
+		return copy;
+	}
+
+	/** A simple toString method for an array of doubles.
+		* No fancy formating.
+		* Puts spaces between each value
+		*/
+	public static final String toString(double[] array) {
+		StringBuffer sb = new StringBuffer(array.length*7);
+		for(int i = 0 ; i < array.length ; i++) {
+			sb.append(array[i]);
+			sb.append(' ');
+		}
+		return sb.toString();
+	}
+
+	/** Creates an interface between a parameterised object to allow it to act as
+			a multivariate minimum.
+	*/
+	public static final MultivariateFunction combineMultivariateFunction(MultivariateFunction base, Parameterized[] additionalParameters) {
+		return new U_CombineMultiParam(base,additionalParameters);
+	}
+}
+
+class U_CombineMultiParam implements MultivariateFunction {
+	Parameterized[] additionalParameters_;
+	MultivariateFunction base_;
+
+	double[] baseArgumentStorage_;
+	double[] lowerBounds_;
+	double[] upperBounds_;
+
+	public U_CombineMultiParam(MultivariateFunction base, Parameterized[] additionalParameters) {
+		this.additionalParameters_ = additionalParameters;
+		this.base_ = base;
+		int numberOfArguments = base_.getNumArguments();
+		baseArgumentStorage_ = new double[numberOfArguments];
+
+		for(int i = 0 ; i < additionalParameters.length ; i++) {
+			numberOfArguments+=additionalParameters[i].getNumParameters();
+		}
+		lowerBounds_ = new double[numberOfArguments];
+		upperBounds_ = new double[numberOfArguments];
+		int argumentNumber = 0;
+		for(int i = 0 ; i < base_.getNumArguments() ; i++) {
+			lowerBounds_[argumentNumber] = base_.getLowerBound(i);
+			upperBounds_[argumentNumber] = base_.getUpperBound(i);
+			argumentNumber++;
+		}
+		for(int i = 0 ; i < additionalParameters.length ; i++) {
+			for(int j = 0 ; j < additionalParameters[i].getNumParameters() ; j++) {
+				lowerBounds_[argumentNumber] = additionalParameters[i].getLowerLimit(j);
+				upperBounds_[argumentNumber] = additionalParameters[i].getUpperLimit(j);
+				argumentNumber++;
+			}
+		}
+
+	}
+
+
+	public double evaluate(double[] argument) {
+		int argumentNumber = 0;
+		for(int i = 0 ; i < baseArgumentStorage_.length ; i++) {
+			baseArgumentStorage_[i] = argument[argumentNumber];
+			argumentNumber++;
+		}
+		for(int i = 0 ; i < additionalParameters_.length ; i++) {
+			int numParam = additionalParameters_[i].getNumParameters();
+			for(int j = 0 ; j < numParam ;  j++) {
+				additionalParameters_[i].setParameter(argument[argumentNumber], j);
+				argumentNumber++;
+			}
+		}
+		return base_.evaluate(baseArgumentStorage_);
+	}
+	public int getNumArguments() {
+		return lowerBounds_.length;
+	}
+	public double getLowerBound(int n) {
+		return lowerBounds_[n];
+	}
+
+	public double getUpperBound(int n) {
+		return upperBounds_[n];
+	}
+}
+
diff --git a/LibrarySource/pal/misc/WeightedFunction.java b/LibrarySource/pal/misc/WeightedFunction.java
new file mode 100644
index 0000000..928bf6d
--- /dev/null
+++ b/LibrarySource/pal/misc/WeightedFunction.java
@@ -0,0 +1,51 @@
+// Product.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * A GeneralFucnction that multiplies all the input values.
+ *
+ * @version $Id: WeightedFunction.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+
+public class WeightedFunction implements GeneralFunction {
+	GeneralFunction toWeight_;
+	Weighting weighting_;
+	double[] parameterStore_ = null;
+
+	public WeightedFunction(GeneralFunction toWeight, Weighting weighting) {
+		this.toWeight_ = toWeight;
+		this.weighting_ = weighting;
+	}
+
+	protected WeightedFunction(WeightedFunction toCopy) {
+		this.toWeight_ = toCopy.toWeight_.getGeneralFunctionCopy();
+		this.weighting_ = toCopy.weighting_.getWeightingCopy();
+		this.parameterStore_ = Utils.getCopy(toCopy.parameterStore_);
+	}
+
+	/** Assumes number of weights returned by weighting matches number of parameters (ignores additional parameters if not the case)
+	*/
+	public double compute(double[] parameters) {
+		double[] weights = weighting_.getWeights();
+		if(parameterStore_ == null || parameterStore_.length != weights.length) {
+			parameterStore_ = new double[weights.length];
+		}
+		for(int i = 0 ; i < parameterStore_.length ; i++) {
+			parameterStore_[i] = weights[i]*parameters[i];
+		}
+		return toWeight_.compute(parameterStore_);
+	}
+
+	public GeneralFunction getGeneralFunctionCopy() {
+		return new WeightedFunction(this);
+	}
+} 
+
diff --git a/LibrarySource/pal/misc/Weighting.java b/LibrarySource/pal/misc/Weighting.java
new file mode 100644
index 0000000..39251dc
--- /dev/null
+++ b/LibrarySource/pal/misc/Weighting.java
@@ -0,0 +1,26 @@
+// Weighting.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.misc;
+
+/**
+ * interface for classes which provide weighting mechanisms
+ *
+ * @version $Id: Weighting.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Matthew Goode
+ */
+public interface Weighting extends Parameterized, Report, java.io.Serializable {
+
+	/** @return an array of weights.
+		*	@note Users of this array should not alter it in anyway as it may be the array that is used internally by a weighting.
+		*/
+	double[] getWeights();
+	/** For people who don't like casting...*/
+	Weighting getWeightingCopy();
+}
+
diff --git a/LibrarySource/pal/misc/makefile b/LibrarySource/pal/misc/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/misc/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/misc/package.html b/LibrarySource/pal/misc/package.html
new file mode 100644
index 0000000..6a4adf0
--- /dev/null
+++ b/LibrarySource/pal/misc/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Classes that don't fit elsewhere ;^) 
+</body>
+</html>
diff --git a/LibrarySource/pal/statistics/BootstrapStatistics.java b/LibrarySource/pal/statistics/BootstrapStatistics.java
new file mode 100644
index 0000000..01a440f
--- /dev/null
+++ b/LibrarySource/pal/statistics/BootstrapStatistics.java
@@ -0,0 +1,172 @@
+// BootstrapStatistics.java
+//
+// (c) 2000-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.util.*;
+
+
+/**
+ * computation of bootstrap estimators (BIAS, SD, VAR, CI)
+ * given a statistic theta and corresponding bootstrap replicates.
+ *
+ * See for background theory:
+ * i) B. Efron and R. J.Tibshirani. 1993. An introduction
+ *    to the bootstrap. Chapman and Hall, New York
+ * ii) P. Hall. 1992. The bootstrap and Edgeworth expansion.
+ *     Springer, New York
+ *
+ * @version $Id: BootstrapStatistics.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class BootstrapStatistics
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * compute bias of a statistic thetaHat in estimating the true theta
+	 * 
+	 * @param thetaHat      the statistic
+	 * @param thetaHatStar  bootstrap replicates of thetaHat
+	 *
+	 * @return estimate of bias (notation: BIAS with hat)
+	 */
+	public static double computeBIAS(double thetaHat, double[] thetaHatStar)
+	{
+		double thetaHatStarMean = DiscreteStatistics.mean(thetaHatStar);
+		
+		return thetaHatStarMean - thetaHat;
+	}
+
+	/**
+	 * correct a statistic thetaHat for its bias
+	 * 
+	 * @param thetaHat      the statistic
+	 * @param thetaHatStar  bootstrap replicates of thetaHat
+	 *
+	 * @return bias-corrected estimate
+	 */
+	public static double biasCorrectedEstimate(double thetaHat, double[] thetaHatStar)
+	{
+		return thetaHat - computeBIAS(thetaHat, thetaHatStar);
+	}
+
+	/**
+	 * compute variance of a statistic thetaHat
+	 * 
+	 * @param thetaHatStar  bootstrap replicates of statistic thetaHat
+	 *
+	 * @return estimate of variance of thetaHat (notation: VAR with hat)
+	 */
+	public static double computeVAR(double[] thetaHatStar)
+	{
+		return DiscreteStatistics.variance(thetaHatStar);
+	}
+
+	/**
+	 * compute standard error (accuracy) of a statistic thetaHat
+	 * 
+	 * @param thetaHatStar  bootstrap replicates of statistic thetaHat
+	 *
+	 * @return estimate of standard error of thetaHat (notation: SD with hat)
+	 */
+	public static double computeSD(double[] thetaHatStar)
+	{
+		return DiscreteStatistics.stdev(thetaHatStar);
+	}
+	
+
+	/**
+	 * compute approximate central confidence interval for thetaHat
+	 * (Efron percentile method)
+	 * 
+	 * @param level        confidence level (e.g., 0.95)
+	 * @param thetaHatStar bootstrap replicates of statistic thetaHat
+	 *
+	 * @return confidence set (array of two doubles)
+	 */
+	public static double[] efronCI(double level, double[] thetaHatStar)
+	{
+		int[] indices = new int[thetaHatStar.length];
+		
+		return efronCI(level, thetaHatStar, indices);
+	}
+
+	/**
+	 * compute approximate central confidence interval for thetaHat
+	 * (Efron percentile method)
+	 * 
+	 * @param level        confidence level (e.g., 0.95)
+	 * @param thetaHatStar bootstrap replicates of statistic thetaHat
+	 * @param array        helper integer array (same length as thetaHatStar) 
+	 *
+	 * @return confidence set (array of two doubles)
+	 */
+	public static double[] efronCI(double level, double[] thetaHatStar, int[] array)
+	{
+		HeapSort.sort(thetaHatStar, array);
+		
+		double alpha = (1.0-level)/2.0;
+		double[] result = new double[2];
+		
+		result[0] = DiscreteStatistics.quantile(alpha, thetaHatStar, array);
+		result[1] = DiscreteStatistics.quantile(1.0-alpha, thetaHatStar, array);
+		
+		return result;
+	}
+
+	/**
+	 * compute approximate central confidence interval for thetaHat
+	 * (Hall percentile method)
+	 * 
+	 * @param level        confidence level (e.g., 0.95)
+	 * @param thetaHat     the statistic
+	 * @param thetaHatStar bootstrap replicates of statistic thetaHat
+	 *
+	 * @return confidence set (array of two doubles)
+	 */
+	public static double[] hallCI(double level, double thetaHat, double[] thetaHatStar)
+	{
+		int[] indices = new int[thetaHatStar.length];
+		
+		return hallCI(level, thetaHat, thetaHatStar, indices);
+	}
+
+	/**
+	 * compute approximate central confidence interval for thetaHat
+	 * (Hall percentile method)
+	 * 
+	 * @param level        confidence level (e.g., 0.95)
+	 * @param thetaHat     the statistic
+	 * @param thetaHatStar bootstrap replicates of statistic thetaHat
+	 * @param array        helper integer array (same length as thetaHatStar) 
+	 *
+	 * @return confidence set (array of two doubles)
+	 */
+	public static double[] hallCI(double level, double thetaHat, double[] thetaHatStar, int[] array)
+	{
+		HeapSort.sort(thetaHatStar, array);
+		
+		double alpha = (1.0-level)/2.0;
+		double[] result = new double[2];
+		
+		// confidence set for the bias (=thetaHatStar-thetaHat)
+		double t1 = DiscreteStatistics.quantile(alpha, thetaHatStar, array)-thetaHat;
+		double t2 = DiscreteStatistics.quantile(1.0-alpha, thetaHatStar, array)-thetaHat;
+		
+		// confidence set for the theta
+		result[0] = thetaHat-t2;
+		result[1] = thetaHat-t1;
+		
+		return result;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/ChiSquareDistribution.java b/LibrarySource/pal/statistics/ChiSquareDistribution.java
new file mode 100644
index 0000000..c5d77ab
--- /dev/null
+++ b/LibrarySource/pal/statistics/ChiSquareDistribution.java
@@ -0,0 +1,97 @@
+// ChiSquareDistribution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * chi-square distribution
+ * (distribution of sum of squares of n uniform random variables)
+ *
+ * (Parameter: n; mean: n; variance: 2*n)
+ *
+ * The chi-square distribution is a special case of the Gamma distribution
+ * (shape parameter = n/2.0, scale = 2.0).
+ *
+ * @version $Id: ChiSquareDistribution.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ChiSquareDistribution extends GammaDistribution
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * probability density function of the chi-square distribution
+	 * 
+	 * @param x argument
+	 * @param n degrees of freedom
+	 *
+	 * @return pdf value
+	 */
+	public static double pdf(double x, double n)
+	{
+		return pdf(x, n/2.0, 2.0);
+	}
+
+	/**
+	 * cumulative density function of the chi-square distribution
+	 * 
+	 * @param x argument
+	 * @param n degrees of freedom
+	 *
+	 * @return cdf value
+	 */
+	public static double cdf(double x, double n)
+	{
+		return cdf(x, n/2.0, 2.0);
+	}
+
+
+	/**
+	 * quantile (inverse cumulative density function) of the chi-square distribution
+	 * 
+	 * @param x argument
+	 * @param n degrees of freedom
+	 *
+	 * @return icdf value
+	 */
+	public static double quantile(double y, double n)
+	{
+		return quantile(y, n/2.0, 2.0);
+	}
+	
+	/**
+	 * mean of the chi-square distribution
+	 * 
+	 * @param n degrees of freedom
+	 *
+	 * @return mean
+	 */
+	public static double mean(double n)
+	{
+		return n;
+	}
+
+	/**
+	 * variance of the chi-square distribution
+	 * 
+	 * @param n degrees of freedom
+	 *
+	 * @return variance
+	 */
+	public static double variance(double n)
+	{
+		return 2.0*n;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/ChiSquareTest.java b/LibrarySource/pal/statistics/ChiSquareTest.java
new file mode 100644
index 0000000..c8d086f
--- /dev/null
+++ b/LibrarySource/pal/statistics/ChiSquareTest.java
@@ -0,0 +1,103 @@
+// ChiSquareTest.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * chi-square test
+ *
+ * @version $Id: ChiSquareTest.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ChiSquareTest
+{
+	//
+	// Public stuff
+	//
+	
+	/** 
+	 * chi square test
+	 *
+	 * @param  ef      expected frequencies (sum up to 1 !!)
+	 * @param  of      observed frequencies (sum up to the number of samples)
+	 *
+	 * @return critical significance level (negative if in chi2 test may be invalid)
+	 */
+	public static double compare(double[] ef, int[] of)
+	{	
+		int samples;
+		boolean chi2failed = false;
+		
+		/* compute number of samples */
+		samples = 0;
+		for (int i = 0; i <of.length; i++)
+		{
+			samples = samples + of[i];
+		}
+		
+		/* compute chi square */
+		double chi2 = 0;
+		int below1 = 0;
+		int below5 = 0;
+		for (int i = 0; i < of.length; i++)
+		{
+			double efn = ef[i]*((double) samples);
+			if (efn < 1.0)
+			{
+				below1++;
+			}
+			if (efn < 5.0)
+			{
+				below5++;
+			}
+			chi2 = chi2 + ((double) of[i]-efn)*((double) of[i]-efn)/efn;
+		}
+	
+		/* compute significance */
+		double criticals = chi2prob(of.length-1, chi2);
+		
+		/* no expected frequency category (sum up to # samples) below 1.0 */
+		if (below1 > 0)
+		{
+			chi2failed = true;
+		}
+		/* no more than 1/5 of the frequency categories below 5.0 */
+		if (below5 > (int) Math.floor(samples/5.0))
+		{
+			chi2failed = true;
+		}
+	
+		if (chi2failed)
+		{
+			return -criticals;
+		}
+		else
+		{
+			return criticals;
+		}
+	}
+	
+	/**
+	 * probability that the observed chi-square
+	 * exceeds chi2 even if model is correct
+	 *
+	 * @param deg degrees of freedom
+	 * @param chi2 chi-square
+	 *
+	 * @return probability
+	 */
+	private static double chi2prob (int deg, double chi2)
+	{
+		return 1.0-ChiSquareDistribution.cdf(chi2, deg);
+	}	
+}
+
diff --git a/LibrarySource/pal/statistics/DiscreteStatistics.java b/LibrarySource/pal/statistics/DiscreteStatistics.java
new file mode 100644
index 0000000..017000c
--- /dev/null
+++ b/LibrarySource/pal/statistics/DiscreteStatistics.java
@@ -0,0 +1,234 @@
+// DiscreteStatistics.java
+//
+// (c) 2000-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.util.*;
+
+
+/**
+ * simple discrete statistics (mean, variance, cumulative probability, quantiles etc.)
+ *
+ * @version $Id: DiscreteStatistics.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class DiscreteStatistics
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * compute mean
+	 * 
+	 * @param x list of numbers
+	 *
+	 * @return mean
+	 */
+	public static double mean(double[] x)
+	{
+		double m = 0;
+		int len = x.length;
+		for (int i = 0; i < len; i++)
+		{
+			m += x[i];
+		}
+		
+		return m/(double) len;
+	}
+
+	/**
+	 * compute variance (ML estimator)
+	 * 
+	 * @param x list of numbers
+	 * @param mean assumed mean of x
+	 *
+	 * @return variance of x (ML estimator)
+	 */
+	public static double variance(double[] x, double mean)
+	{
+		double var = 0;
+		int len = x.length;
+		for (int i = 0; i < len; i++)
+		{
+			double diff = x[i]-mean;
+			var += diff*diff;
+		}
+		
+		int n;
+		if (len < 2)
+		{
+			n = 1; // to avoid division by zero
+		}
+		else
+		{
+			n = len-1; // for ML estimate
+		}
+		
+		return var/ (double) n;
+	}
+	
+	/**
+	 * compute fisher skewness 
+	 * 
+	 * @param x list of numbers
+	 *
+	 * @return skewness of x 
+	 */
+	public static double skewness(double[] x) {
+	
+		double mean = mean(x);
+		double stdev = stdev(x);
+		double skew = 0.0;
+		double len = x.length;
+		
+		for (int i = 0; i < x.length; i++)
+		{
+			double diff = x[i]-mean;
+			diff /= stdev;
+			
+			skew += (diff*diff*diff);
+		}
+
+		skew *= (len / ((len - 1) * (len - 2)));
+	
+		return skew;
+	}
+
+	/**
+	 * compute standard deviation 
+	 * 
+	 * @param x list of numbers
+	 *
+	 * @return standard deviation of x 
+	 */
+	public static double stdev(double[] x) {
+		return Math.sqrt(variance(x));
+	}
+
+	/**
+	 * compute variance (ML estimator)
+	 * 
+	 * @param x list of numbers
+	 *
+	 * @return variance of x (ML estimator)
+	 */
+	public static double variance(double[] x)
+	{
+		double m = mean(x);
+		return variance(x, m);
+	}
+
+
+	/**
+	 * compute variance of sample mean (ML estimator)
+	 * 
+	 * @param x list of numbers
+	 * @param mean assumed mean of x
+	 *
+	 * @return variance of x (ML estimator)
+	 */
+	public static double varianceSampleMean(double[] x, double mean)
+	{
+		return variance(x, mean)/(double) x.length;
+	}
+
+	/**
+	 * compute variance of sample mean (ML estimator)
+	 * 
+	 * @param x list of numbers
+	 *
+	 * @return variance of x (ML estimator)
+	 */
+	public static double varianceSampleMean(double[] x)
+	{
+		return variance(x)/(double) x.length;
+	}
+
+
+	/**
+	 * compute the q-th quantile for a distribution of x
+	 * (= inverse cdf)
+	 * 
+	 * @param q quantile (0 < q <= 1)
+	 * @param x discrete distribution (an unordered list of numbers)
+	 * @param indices index sorting x
+	 *
+	 * @return q-th quantile
+	 */
+	public static double quantile(double q, double[] x, int[] indices)
+	{
+		if (q < 0.0 || q > 1.0) throw new IllegalArgumentException("Quantile out of range");
+		
+		if (q == 0.0)
+		{
+			// for q==0 we have to "invent" an entry smaller than the smallest x
+			
+			return x[indices[0]] - 1.0;
+		}
+		
+		return x[indices[(int) Math.ceil(q*x.length)-1]];
+	}	
+
+	/**
+	 * compute the q-th quantile for a distribution of x
+	 * (= inverse cdf)
+	 * 
+	 * @param q quantile (0 <= q <= 1)
+	 * @param x discrete distribution (an unordered list of numbers)
+	 *
+	 * @return q-th quantile
+	 */
+	public static double quantile(double q, double[] x)
+	{
+		int[] indices = new int[x.length];
+		HeapSort.sort(x, indices);
+		
+		return quantile(q, x, indices);
+	}
+	
+	/**
+	 * compute the cumulative probability Pr(x <= z) for a given z
+	 * and a distribution of x
+	 * 
+	 * @param z threshold value
+	 * @param x discrete distribution (an unordered list of numbers)
+	 * @param indices index sorting x
+	 *
+	 * @return cumulative probability
+	 */
+	public static double cdf(double z, double[] x, int[] indices)
+	{
+		int i;
+		for (i = 0; i < x.length; i++)
+		{
+			if (x[indices[i]] > z) break;
+		}
+		
+		return (double) i/ (double) x.length;
+	}
+	
+	/**
+	 * compute the cumulative probability Pr(x <= z) for a given z
+	 * and a distribution of x
+	 * 
+	 * @param z threshold value
+	 * @param x discrete distribution (an unordered list of numbers)
+	 *
+	 * @return cumulative probability
+	 */
+	public static double cdf(double z, double[] x)
+	{
+		int[] indices = new int[x.length];
+		HeapSort.sort(x, indices);
+		
+		return cdf(z, x, indices);
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/ExponentialDistribution.java b/LibrarySource/pal/statistics/ExponentialDistribution.java
new file mode 100644
index 0000000..903de96
--- /dev/null
+++ b/LibrarySource/pal/statistics/ExponentialDistribution.java
@@ -0,0 +1,100 @@
+// ExponentialDistribution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * exponential distribution.
+ *
+ * (Parameter: lambda; mean: 1/lambda; variance: 1/lambda^2)
+ *
+ * The exponential distribution is a special case of the Gamma distribution
+ * (shape parameter = 1.0, scale = 1/lambda).
+ *
+ * @version $Id: ExponentialDistribution.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ExponentialDistribution extends GammaDistribution
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * probability density function of the exponential distribution
+	 * (mean = 1/lambda)
+	 * 
+	 * @param x argument
+	 * @param lambda parameter of exponential distribution
+	 *
+	 * @return pdf value
+	 */
+	public static double pdf(double x, double lambda)
+	{
+		return lambda*Math.exp(-lambda*x);
+		//return pdf(x, 1.0, 1/lambda);
+	}
+
+	/**
+	 * cumulative density function of the exponential distribution
+	 * 
+	 * @param x argument
+	 * @param lambda parameter of exponential distribution
+	 *
+	 * @return cdf value
+	 */
+	public static double cdf(double x, double lambda)
+	{
+		return 1.0-Math.exp(-lambda*x);
+		//return cdf(x, 1.0, 1/lambda);
+	}
+
+
+	/**
+	 * quantile (inverse cumulative density function) of the exponential distribution
+	 *
+	 * @param y argument
+	 * @param lambda parameter of exponential distribution
+	 *
+	 * @return icdf value
+	 */
+	public static double quantile(double y, double lambda)
+	{
+		return -(1.0/lambda)*Math.log(1.0-y);
+		//return quantile(y, 1.0, 1/lambda);
+	}
+	
+	/**
+	 * mean of the exponential distribution
+	 *
+	 * @param lambda parameter of exponential distribution
+	 *
+	 * @return mean
+	 */
+	public static double mean(double lambda)
+	{
+		return 1.0/(lambda);
+	}
+
+	/**
+	 * variance of the exponential distribution
+	 *
+	 * @param lambda parameter of exponential distribution
+	 *
+	 * @return variance
+	 */
+	public static double variance(double lambda)
+	{
+		return 1.0/(lambda*lambda);
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/GammaDistribution.java b/LibrarySource/pal/statistics/GammaDistribution.java
new file mode 100644
index 0000000..df933bc
--- /dev/null
+++ b/LibrarySource/pal/statistics/GammaDistribution.java
@@ -0,0 +1,180 @@
+// GammaDistribution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * gamma distribution.
+ *
+ * (Parameters: shape, scale; mean: scale*shape; variance: scale^2*shape)
+ *
+ * @version $Id: GammaDistribution.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class GammaDistribution
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * probability density function of the Gamma distribution 
+	 * 
+	 * @param x argument
+	 * @param shape shape parameter
+	 * @param scale scale parameter
+	 *
+	 * @return pdf value
+	 */
+	public static double pdf(double x, double shape, double scale)
+	{
+		return	Math.pow(scale,-shape)*Math.pow(x, shape-1.0)/
+	 		Math.exp(x/scale + GammaFunction.lnGamma(shape));
+	}
+
+	/**
+	 * cumulative density function of the Gamma distribution 
+	 * 
+	 * @param x argument
+	 * @param shape shape parameter
+	 * @param scale scale parameter
+	 *
+	 * @return cdf value
+	 */
+	public static double cdf(double x, double shape, double scale)
+	{
+		return GammaFunction.incompleteGammaP(shape, x/scale);
+	}
+
+
+	/**
+	 * quantile (inverse cumulative density function) of the Gamma distribution
+	 *
+	 * @param y argument
+	 * @param shape shape parameter
+	 * @param scale scale parameter
+	 *
+	 * @return icdf value
+	 */
+	public static double quantile(double y, double shape, double scale)
+	{
+		return 0.5*scale*pointChi2(y, 2.0*shape);
+	}
+	
+	/**
+	 * mean of the Gamma distribution
+	 *
+	 * @param shape shape parameter
+	 * @param scale scale parameter
+	 *
+	 * @return mean
+	 */
+	public static double mean(double shape, double scale)
+	{
+		return scale*shape;
+	}
+
+	/**
+	 * variance of the Gamma distribution
+	 *
+	 * @param shape shape parameter
+	 * @param scale scale parameter
+	 *
+	 * @return variance
+	 */
+	public static double variance(double shape, double scale)
+	{
+		return scale*scale * shape;
+	}	
+	
+	// Private
+	
+	private static double pointChi2(double prob, double v)
+	{
+		// Returns z so that Prob{x<z}=prob where x is Chi2 distributed with df = v
+		// RATNEST FORTRAN by
+		// Best DJ & Roberts DE (1975) The percentage points of the 
+		// Chi2 distribution.  Applied Statistics 24: 385-388.  (AS91)
+
+		double e = 0.5e-6, aa = 0.6931471805, p = prob, g;
+		double xx, c, ch, a = 0, q = 0, p1 = 0, p2 = 0, t = 0, x = 0, b = 0, s1, s2, s3, s4, s5, s6;
+	
+		if (p < 0.000002 || p > 0.999998 || v <= 0)
+		{
+			throw new IllegalArgumentException("Arguments out of range");
+		}
+		g = GammaFunction.lnGamma(v/2);
+		xx = v/2;
+		c = xx-1;
+		if (v < -1.24*Math.log(p))
+		{
+			ch = Math.pow((p*xx*Math.exp(g+xx*aa)), 1/xx);
+			if (ch-e < 0)
+			{
+				return ch;
+			}
+		}
+		else
+		{
+			if (v > 0.32)
+			{
+				x = NormalDistribution.quantile(p, 0, 1);
+				p1 = 0.222222/v;
+				ch = v*Math.pow((x*Math.sqrt(p1)+1-p1), 3.0);
+				if(ch>2.2*v+6)
+				{
+					ch=-2*(Math.log(1-p)-c*Math.log(.5*ch)+g);
+				}			
+			}
+			else
+			{
+				ch = 0.4;
+				a = Math.log(1-p);
+
+				do
+				{
+					q = ch;
+					p1 = 1+ch*(4.67+ch);
+					p2 = ch*(6.73+ch*(6.66+ch));
+					t = -0.5+(4.67+2*ch)/p1 - (6.73+ch*(13.32+3*ch))/p2;
+					ch -= (1-Math.exp(a+g+.5*ch+c*aa)*p2/p1)/t;
+				}
+				while (Math.abs(q/ch-1)-.01 > 0);
+			}
+		}
+		do
+		{
+			q = ch;
+			p1 = 0.5*ch;
+			if ((t = GammaFunction.incompleteGammaP(xx, p1, g)) < 0)
+			{
+				throw new IllegalArgumentException("Arguments out of range: t < 0");
+			}
+			p2 = p-t;
+			t = p2*Math.exp(xx*aa+g+p1-c*Math.log(ch));   
+			b = t/ch;
+			a = 0.5*t-b*c;
+
+			s1 = (210+a*(140+a*(105+a*(84+a*(70+60*a)))))/420;
+			s2 = (420+a*(735+a*(966+a*(1141+1278*a))))/2520;
+			s3 = (210+a*(462+a*(707+932*a)))/2520;
+			s4 = (252+a*(672+1182*a)+c*(294+a*(889+1740*a)))/5040;
+			s5 = (84+264*a+c*(175+606*a))/2520;
+			s6 = (120+c*(346+127*c))/5040;
+			ch += t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6))))));
+		}
+		while (Math.abs(q/ch-1) > e);
+
+		return (ch);
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/KishinoHasegawaTest.java b/LibrarySource/pal/statistics/KishinoHasegawaTest.java
new file mode 100644
index 0000000..2e4a7aa
--- /dev/null
+++ b/LibrarySource/pal/statistics/KishinoHasegawaTest.java
@@ -0,0 +1,202 @@
+// KishinoHasegawaTest.java
+//
+// (c) 1999-2001 PAL Core Development Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+/**
+ * Kishino-Hasegawa-(Templeton)-Test (1989, 1983) to
+ * compare a set of evolutionary hypotheses
+ *
+ * @version $Id: KishinoHasegawaTest.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ * 
+ * @author Korbinian Strimmer
+ */
+public class KishinoHasegawaTest implements Report
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * number of maximum likelihood hypothesis
+	 */ 	
+	public int bestH;
+	
+	/**
+	 * log-likelihood difference to maximum likelihood hypothesis
+	 */ 	
+	public double[] delta;
+	
+	/**
+	 * estimated error of log-likelihood differences
+	 */ 	
+	public double[] deltaSE;
+	
+	/**
+	 * corresponding p-value (two-sided test on normal distribution)
+	 */ 	
+	public double[] pval;
+
+	/** 
+	 * Compare all given hypotheses to the best (ML) hypothesis
+	 * and store results in public arrays delta, deltaSE, pval
+	 * (which will automatically be created by this procedure).
+	 *
+	 * @param  sLogL       log-likelihoods of each site
+	 */	
+	public void compare(double[][] sLogL)
+	{
+		khtest(sLogL, null);
+	}
+
+	/** 
+	 * Compare all given hypotheses to the best (ML) hypothesis
+	 * and store results in public arrays delta, deltaSE, pval
+	 * (which will automatically be created by this procedure).
+	 *
+	 * @param  pLogL       log-likelihoods of each pattern
+	 * @param  alias       map of patterns to sites in sequence
+	 */	
+	public void compare(double[][] pLogL, int[] alias)
+	{
+		khtest(pLogL, alias);
+	}
+
+	public void report(PrintWriter out)
+	{
+		FormattedOutput fo = FormattedOutput.getInstance();
+		out.println("KISHINO-HASEGAWA TEST:");
+		out.println();
+		out.println("tree\tdeltaL\tS.E.\tpval (two-sided)");
+		out.println("----------------------------------------");
+		for (int i = 0; i < pval.length; i++)
+		{
+			out.print((i+1) + "\t");
+			fo.displayDecimal(out, delta[i], 2);
+			out.print("\t");
+			fo.displayDecimal(out, deltaSE[i], 2);
+			out.print("\t");
+			fo.displayDecimal(out, pval[i], 4);
+			if (pval[i] < 0.05)
+			{
+				out.println(" **");
+			}
+			else
+			{
+				out.println();
+			}
+		}
+		out.println();
+		out.println("** indicates a tree that is significantly worse than the ML tree (5% level)");
+	}
+
+	//
+	// Private stuff
+	//
+		
+	private void khtest(double[][] pLogL, int[] alias)
+	{
+		// number of hypotheses 
+		int numH = pLogL.length;
+
+		// allocate memory for results
+		delta = new double[numH];
+		deltaSE = new double[numH];
+		pval = new double[numH];
+		
+		// number of sites
+		// if alias==null assume one-to-one mapping of sites and patterns
+		int numSites;
+		if (alias == null)
+		{
+			numSites = pLogL[0].length;
+		}
+		else
+		{
+			numSites = alias.length;
+		}
+		
+		// log likelihood of each hypothesis
+		double[] logL = new double[numH];
+		for (int i = 0; i < numSites; i++)
+		{
+			int p;
+			if (alias == null)
+			{
+				p = i;
+			}
+			else
+			{
+				p = alias[i];
+			}
+			
+			for (int j = 0; j < numH; j++)
+			{
+				logL[j] += pLogL[j][p];
+			}
+		}
+
+		// find maximum-likelihood hypothesis
+		bestH = 0;
+		double maxLogL = logL[0];
+		for (int i = 1; i < numH; i++)
+		{
+			if (logL[i] > maxLogL)
+			{
+				bestH = i;
+				maxLogL = logL[i];
+			}
+		}
+				
+		// compute log-likelihood differences to best hypothesis
+		for (int i = 0; i < numH; i++)
+		{
+			delta[i] = logL[bestH]-logL[i];
+		}
+		
+		// estimate standard error of log-likelihood differences
+		for (int i = 0; i < numH; i++)
+		{
+			double mean = delta[i]/numSites;
+			double var = 0.0;
+			for (int j = 0; j < numSites; j++)
+			{
+				int p;
+				if (alias == null)
+				{
+					p = j;
+				}
+				else
+				{
+					p = alias[j];
+				}
+				
+				double diff = pLogL[bestH][p]-pLogL[i][p]-mean;
+				var += diff*diff;
+			}
+			
+			deltaSE[i] = Math.sqrt(numSites*var/(numSites-1));
+		}
+		
+		// compute corresponding p-values
+		for (int i = 0; i < numH; i++)
+		{
+			pval[i] = ErrorFunction.erfc(delta[i]/deltaSE[i]/Math.sqrt(2.0));
+		}
+		
+		// free memory
+		logL = null;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/LikelihoodRatioTest.java b/LibrarySource/pal/statistics/LikelihoodRatioTest.java
new file mode 100644
index 0000000..337cc1e
--- /dev/null
+++ b/LibrarySource/pal/statistics/LikelihoodRatioTest.java
@@ -0,0 +1,41 @@
+// LikelihoodRatioTest.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * Likelihood ratio test based on chi-square statistics
+ *
+ * @version $Id: LikelihoodRatioTest.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $ 
+ *
+ * @author Korbinian Strimmer
+ */
+public class LikelihoodRatioTest
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	 * compute significance level for the differences
+	 * in log-likelihood (based on chi-square distribution)
+	 *
+	 * @param deltaL  difference of Log Likelihood values (>=0)
+	 * @param df      degrees of freedom
+	 *
+	 * @return        significance level
+	 */
+	public static double getSignificance(double deltaL, int df)
+	{
+		return 1.0-ChiSquareDistribution.cdf(2.0*deltaL, df);
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/ModelSupport.java b/LibrarySource/pal/statistics/ModelSupport.java
new file mode 100644
index 0000000..bac3442
--- /dev/null
+++ b/LibrarySource/pal/statistics/ModelSupport.java
@@ -0,0 +1,341 @@
+// ModelSupport.java
+//
+// (c) 2001 PAL Core Development Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+import pal.util.*;
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+
+/**
+ * Computes Akaike weights and expected Akaike weights
+ * (relative evidence, expected relative evidence)
+ * for a set of models and computes corresponding confidence sets 
+ *
+ * @version $Id: ModelSupport.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ModelSupport implements Report
+{
+	//
+	// Public stuff
+	//
+		
+	/**
+	 * likelhood order of the tree hypotheses 
+	 */
+	public int[] likelihoodOrder;
+
+	/**
+	 * support order of the tree hypotheses
+	 */
+	public int[] supportOrder;
+
+	/**
+	 * log-likelihood differences to the best tree
+	 */ 
+	public double[] deltaL;
+	
+	/**
+	 * posterior probabilities for each hypothesis
+	 */ 	
+	public double[] posterior;
+	
+	/**
+	 * support in each hypothesis
+	 */ 	
+	public double[] support;
+	
+	/**
+	 * number of bootstrap replicates
+	 */ 	
+	public int numBootstraps;
+
+	/** 
+	 * Determine posterior probabilties and support values
+	 * for each hypothesis and store results in public arrays
+	 * posterior, support etc which will automatically be
+	 * created by this procedure.
+	 *
+	 * @param  sLogL       log-likelihoods of each site
+	 * @param  numBoot     number of bootstraps
+	 */	
+	public void compare(double[][] sLogL, int numBoot)
+	{
+		srtest(sLogL, null, numBoot);
+	}
+
+	/** 
+	 * Determine posterior probabilties and support values
+	 * for each hypothesis and store results in public arrays
+	 * posterior, support etc which will automatically be
+	 * created by this procedure.
+	 *
+	 * @param  pLogL       log-likelihoods of each pattern
+	 * @param  alias       map of patterns to sites in sequence
+	 * @param  numBoot     number of bootstraps
+	 */	
+	public void compare(double[][] pLogL, int[] alias, int numBoot)
+	{
+		srtest(pLogL, alias, numBoot);
+	}
+
+	public void report(PrintWriter out)
+	{
+		FormattedOutput fo = FormattedOutput.getInstance();
+		
+		out.println("CREDIBLE SET " + numBootstraps + " bootstraps):");
+		out.println();
+		out.println("tree\tdeltaL\tpost\tsupp");
+		out.println("--------------------------------");
+
+		for (int i = 0; i < deltaL.length; i++)
+		{
+			out.print((i+1) + "\t");
+			fo.displayDecimal(out, deltaL[i], 2);
+			out.print("\t");
+			fo.displayDecimal(out, posterior[i], 4);
+			out.print("\t");
+			fo.displayDecimal(out, support[i], 4);
+			out.println();
+		}
+		out.println();
+		out.println("prob = Akaike weight (non-informative posterior probability)");
+		out.println("supp = expected Akaike weight");
+		
+		out.println();
+		out.println();
+		out.println("supp\toptimal 95% credible sets (expected Akaike weights)");
+		out.println("------------------------------------------------------------");
+		printSets(out, supportOrder, 0.95);
+		
+		/*out.println();
+		out.println();
+		out.println("supp\talternative 95% confidence sets (using deltaL order)");
+		out.println("------------------------------------------------------------");
+		printSets(out, likelihoodOrder, 0.95);*/
+			
+		out.println();
+	}
+
+	//
+	// Private stuff
+	//
+
+	private void printSets(PrintWriter out, int[] order, double level)
+	{
+		FormattedOutput fo = FormattedOutput.getInstance();
+		
+		double conf = 0.0;
+		double conf2;
+		int pos = 0;
+			
+		while (conf < level)
+		{
+			conf += support[order[pos]];
+			
+			if (pos+1 < order.length)
+			{
+				conf2 = conf + support[order[pos+1]];
+			}
+			else
+			{
+				conf2 = conf;
+			}
+			
+			if (conf2 >= level)
+			{
+				fo.displayDecimal(out, conf, 4);
+				out.print("\t{" + (order[0]+1));	
+				for (int i = 0; i < pos; i++)
+				{
+					out.print(", " + (order[i+1]+1));
+				}
+				out.println("}");
+			}
+				
+			pos++;	
+		}
+	}
+		
+	private void srtest(double[][] pLogL, int[] alias,  int numBoot)
+	{
+		// number of hypothesis 
+		int numH = pLogL.length;
+		
+		// allocate public arrays
+		deltaL = new double[numH];
+		support = new double[numH];
+		posterior = new double[numH];
+		likelihoodOrder = new int[numH];
+		supportOrder = new int[numH];	
+		
+		// number of bootstrap replicates
+		numBootstraps = numBoot;
+
+		// number of sites
+		// if alias==null assume one-to-one mapping of sites and patterns
+		int numSites;
+		if (alias == null)
+		{
+			numSites = pLogL[0].length;
+		}
+		else
+		{
+			numSites = alias.length;
+		}
+		
+
+		// Compute log-likelihoods, their order, 
+		// their deltas and their posteriors
+		for (int j = 0; j < numSites; j++)
+		{
+			int p;
+			if (alias == null)
+			{
+				p = j;
+			}
+			else
+			{
+				p = alias[j];
+			}
+				
+			for (int k = 0; k < numH; k++)
+			{
+				deltaL[k] -= pLogL[k][p];
+			}
+		}
+		HeapSort.sort(deltaL, likelihoodOrder);
+
+		// Compute deltas
+		double maxL= -deltaL[likelihoodOrder[0]];
+		for (int j = 0; j < numH; j++)
+		{
+			deltaL[j] = -(deltaL[j]+maxL);
+		}
+		
+		// compute posterior probabilities 
+		double sum1 = 0;
+		for (int j = 0; j < numH; j++)
+		{
+			posterior[j] = Math.exp(deltaL[j]);
+			sum1 += posterior[j];
+		}
+		for (int j = 0; j < numH; j++)
+		{
+			posterior[j] = posterior[j]/sum1;
+		}
+		
+		// reverse sign of delta L
+		for (int j = 0; j < numH; j++)
+		{
+			deltaL[j] = -deltaL[j];
+		}
+		deltaL[likelihoodOrder[0]] = 0.0;
+		
+	
+		// Resample data
+
+		// temporary memory 
+		double[] rs = new double[numH];
+		
+		MersenneTwisterFast mt = new MersenneTwisterFast();
+		for (int i = 0; i < numBoot; i++)
+		{
+			for (int k = 0; k < numH; k++)
+			{
+					rs[k] = 0;
+			}
+
+			for (int j = 0; j < numSites; j++)
+			{
+				int s = mt.nextInt(numSites);
+				
+				int p;
+				if (alias == null)
+				{
+					p = s;
+				}
+				else
+				{
+					p = alias[s];
+				}
+				
+				for (int k = 0; k < numH; k++)
+				{
+					rs[k] += pLogL[k][p];
+				}
+			}
+			
+			// find ml hypothesis
+			double maxLogL = findMax(rs);
+			
+			// compute log-likelihood difference
+			for (int k = 0; k < numH; k++)
+			{
+				rs[k] = rs[k] - maxLogL;
+			}
+
+			// compute posteriors and sum over resampleds data set
+			double sum = 0;
+			for (int k = 0; k < numH; k++)
+			{
+				rs[k] = Math.exp(rs[k]);
+				sum += rs[k];
+			}
+			for (int k = 0; k < numH; k++)
+			{
+				support[k] += rs[k]/sum;
+			}
+		}  
+		
+		// compute support values
+		for (int j = 0; j < numH; j++)
+		{
+			support[j] = support[j]/numBoot;
+		}
+
+		// determine order of support (smallest->largest)
+		HeapSort.sort(support, supportOrder);
+		
+		// reversing the order 
+		int len = supportOrder.length;
+		for (int i = 0; i < len/2; i++)
+		{
+			int tmp = supportOrder[i];
+			supportOrder[i] = supportOrder[len-i-1];
+			supportOrder[len-i-1] = tmp;
+		}
+		
+		// free temporary memory
+		rs = null;
+	}
+	
+	private double findMax(double[] array)
+	{
+		int len = array.length;
+		
+		int best = 0;
+		double max = array[0];
+		for (int i = 1; i < len; i++)
+		{
+			if (array[i] > max)
+			{
+				best = i;
+				max = array[i];
+			}
+		}
+		
+		return max;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/NormalDistribution.java b/LibrarySource/pal/statistics/NormalDistribution.java
new file mode 100644
index 0000000..ef62680
--- /dev/null
+++ b/LibrarySource/pal/statistics/NormalDistribution.java
@@ -0,0 +1,99 @@
+// NormalDistribution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+/**
+ * normal distribution (pdf, cdf, quantile)
+ *
+ * @version $Id: NormalDistribution.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class NormalDistribution
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * probability density function
+	 *
+	 * @param x argument
+	 * @param m mean
+	 * @param sd standard deviation
+	 *
+	 * @return pdf at x
+	 */
+	public static double pdf(double x, double m, double sd)
+	{
+		double a = 1.0/(Math.sqrt(2.0*Math.PI)*sd);
+		double b = -(x-m)*(x-m)/(2.0*sd*sd);
+		
+		return a*Math.exp(b);
+	}
+
+	/**
+	 * cumulative density function
+	 *
+	 * @param x argument
+	 * @param m mean
+	 * @param sd standard deviation
+	 *
+	 * @return cdf at x
+	 */
+	public static double cdf(double x, double m, double sd)
+	{
+		double a = (x-m)/(Math.sqrt(2.0)*sd);
+		
+		return 0.5*(1.0+ErrorFunction.erf(a));
+	}
+	
+	/**
+	 * quantiles (=inverse cumulative density function)
+	 *
+	 * @param z argument
+	 * @param m mean
+	 * @param sd standard deviation
+	 *
+	 * @return icdf at z
+	 */
+	public static double quantile(double z, double m, double sd)
+	{
+		return m + Math.sqrt(2.0)*sd*ErrorFunction.inverseErf(2.0*z-1.0);
+	}
+	
+	/**
+	 * mean
+	 *
+	 * @param m mean
+	 * @param sd standard deviation
+	 *
+	 * @return mean
+	 */
+	public static double mean(double m, double sd)
+	{
+		return m;
+	}
+
+	/**
+	 * variance
+	 *
+	 * @param m mean
+	 * @param sd standard deviation
+	 *
+	 * @return variance
+	 */
+	public static double variance(double m, double sd)
+	{
+		return sd*sd;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/ParetoDistribution.java b/LibrarySource/pal/statistics/ParetoDistribution.java
new file mode 100644
index 0000000..bd7ca1f
--- /dev/null
+++ b/LibrarySource/pal/statistics/ParetoDistribution.java
@@ -0,0 +1,122 @@
+// ParetoDistribution.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * Pareto distribution
+ * (scale-free distribution without characteristic length scale).
+ *
+ * Parameters: shape parameter k>0, scale parameter m>0 ("minimum income")
+ *
+ * @version $Id: ParetoDistribution.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ParetoDistribution
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * probability density function of the Pareto distribution
+	 * 
+	 * @param x argument (>=m)
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return pdf value
+	 */
+	public static double pdf(double x, double k, double m)
+	{
+		return k*Math.pow(m,k)*Math.pow(x,-(k+1));
+	}
+
+	/**
+	 * cumulative density function of the Pareto distribution
+	 * 
+	 * @param x argument (>=m)
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return cdf value
+	 */
+	public static double cdf(double x, double k, double m)
+	{
+		return 1.0-Math.pow(m/x, k);
+	}
+
+
+	/**
+	 * quantile (inverse cumulative density function) of the Pareto distribution
+	 * 
+	 * @param p argument (0 < p < 1)
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return icdf value
+	 */
+	public static double quantile(double p, double k, double m)
+	{
+		return m/Math.pow(1.0-p,1.0/k);
+	}
+	
+	/**
+	 * mean of the Pareto distribution
+	 * 
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return mean
+	 */
+	public static double mean(double k, double m)
+	{
+		if (k > 1.0)
+			return m*k/(k-1.0);
+		else
+			return Double.POSITIVE_INFINITY;
+	}
+
+	/**
+	 * variance of the Pareto distribution
+	 * 
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return variance
+	 */
+	public static double variance(double k, double m)
+	{
+		if (k > 2.0)
+			return m*m*k/((k-1.0)*(k-1.0)*(k-2.0));
+		else
+			return Double.POSITIVE_INFINITY;
+	}
+	
+	/**
+	 * moments E(X^n) of the Pareto distribution
+	 * 
+	 * @param n moment
+	 * @param k shape parameter (>0)
+	 * @param m scale parameter (>0, "minimum income")
+	 *
+	 * @return variance
+	 */
+	public static double moment(int n, double k, double m)
+	{
+		if (k > n)
+			return Math.pow(m,n)*k/(k-n);
+		else
+			return Double.POSITIVE_INFINITY;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/PenalizedLikelihood.java b/LibrarySource/pal/statistics/PenalizedLikelihood.java
new file mode 100644
index 0000000..cdadb50
--- /dev/null
+++ b/LibrarySource/pal/statistics/PenalizedLikelihood.java
@@ -0,0 +1,71 @@
+// PenalizedLikelihood.java
+//
+// (c) 20001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+
+
+/**
+ * Penalized likelihood criteria
+ *
+ * @version $Id: PenalizedLikelihood.java,v 1.1 2001/07/10 09:16:29 korbinian Exp $ 
+ *
+ * @author Korbinian Strimmer
+ */
+public class PenalizedLikelihood
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	 * Akaike (AIC) correction (Akaike 1974)
+	 *
+	 * @param l    log-likelihood
+	 * @param k    number of inferred parameters
+	 *
+	 * @return     l - k   
+	 */
+	public static double AIC(double l, int k)
+	{
+		return l - (double) k;
+	}
+	
+	/**
+	 * BIC correction (Schwarz 1978)
+	 *
+	 * @param l    log-likelihood
+	 * @param k    number of inferred parameters
+	 * @param n    sample size 
+	 *
+	 * @return     l - k/2 log(n)   
+	 */
+	public static double BIC(double l, int k, int n)
+	{
+		return l - (double)k/2.0* Math.log(n);
+	}
+	
+	/**
+	 * Second-order Akaike (AICC) correction (Hurvich and Tsai 1989)
+	 *
+	 * @param l    log-likelihood
+	 * @param k    number of inferred parameters
+	 * @param n    sample size 
+	 *
+	 * @return     l - k - (k(k+1))/(n - k - 1)   
+	 */
+	public static double AICC(double l, int k, int n)
+	{
+		if (k > n-2) throw new IllegalArgumentException("k must be smaller than n-1");
+		
+		return  l - k - (double) (k*(k+1.0))/ (double) (n - k - 1.0) ;
+	}
+
+}
+
diff --git a/LibrarySource/pal/statistics/ShimodairaHasegawaTest.java b/LibrarySource/pal/statistics/ShimodairaHasegawaTest.java
new file mode 100644
index 0000000..4d9666d
--- /dev/null
+++ b/LibrarySource/pal/statistics/ShimodairaHasegawaTest.java
@@ -0,0 +1,262 @@
+// ShimodairaHasegawaTest.java
+//
+// (c) 1999-2001 PAL Core Development Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.statistics;
+
+import pal.math.*;
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Shimodaira-Hasegawa-Test (1999) to
+ * compare a set of evolutionary hypotheses
+ *
+ * @version $Id: ShimodairaHasegawaTest.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ShimodairaHasegawaTest implements Report
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * number of maximum likelihood hypothesis
+	 */ 	
+	public int bestH;
+	
+	/**
+	 * log-likelihood difference to maximum likelihood hypothesis
+	 */ 	
+	public double[] delta;
+		
+	/**
+	 * corresponding p-value
+	 */ 	
+	public double[] pval;
+
+	/**
+	 * number of bootstrap replicates
+	 */ 	
+	public int numBootstraps;
+
+
+	/** 
+	 * Compare all given hypotheses to the best (ML) hypothesis
+	 * and store results in public arrays delta, pval
+	 * (which will automatically be created by this procedure).
+	 *
+	 * @param  sLogL       log-likelihoods of each site
+	 * @param  numBoot     number of bootstraps
+	 */	
+	public void compare(double[][] sLogL, int numBoot)
+	{
+		shtest(sLogL, null, numBoot);
+	}
+
+	/** 
+	 * Compare all given hypotheses to the best (ML) hypothesis
+	 * and store results in public arrays delta, pval
+	 * (which will automatically be created by this procedure).
+	 *
+	 * @param  pLogL       log-likelihoods of each pattern
+	 * @param  alias       map of patterns to sites in sequence
+	 * @param  numBoot     number of bootstraps
+	 */	
+	public void compare(double[][] pLogL, int[] alias, int numBoot)
+	{
+		shtest(pLogL, alias, numBoot);
+	}
+
+	public void report(PrintWriter out)
+	{
+		FormattedOutput fo = FormattedOutput.getInstance();
+		out.println("SHIMODAIRA-HASEGAWA TEST (" + numBootstraps + " bootstraps):");
+		out.println();
+		out.println("tree\tdeltaL\tpval");
+		out.println("--------------------------");
+
+		for (int i = 0; i < pval.length; i++)
+		{
+			out.print((i+1) + "\t");
+			fo.displayDecimal(out, delta[i], 2);
+			out.print("\t");
+			fo.displayDecimal(out, pval[i], 4);
+			if (pval[i] < 0.05)
+			{
+				out.println(" **");
+			}
+			else
+			{
+				out.println();
+			}
+		}
+			
+		out.println();
+		out.println("** indicates a tree that is significantly worse than the ML tree (5% level)");
+	}
+
+	//
+	// Private stuff
+	//
+		
+	private void shtest(double[][] pLogL, int[] alias,  int numBoot)
+	{
+		// number of hypothesis 
+		int numH = pLogL.length;
+		
+		// number of bootstrap replicates
+		numBootstraps = numBoot;
+		
+		// allocate memory for results
+		delta = new double[numH];
+		pval = new double[numH];
+
+		// number of sites
+		// if alias==null assume one-to-one mapping of sites and patterns
+		int numSites;
+		if (alias == null)
+		{
+			numSites = pLogL[0].length;
+		}
+		else
+		{
+			numSites = alias.length;
+		}
+		
+		// log likelihood of each hypothesis
+		double[] logL = new double[numH];
+		for (int i = 0; i < numSites; i++)
+		{
+			int p;
+			if (alias == null)
+			{
+				p = i;
+			}
+			else
+			{
+				p = alias[i];
+			}
+			
+			for (int j = 0; j < numH; j++)
+			{
+				logL[j] += pLogL[j][p];
+			}
+		}
+		
+		// find maximum-likelihood hypothesis
+		bestH = 0;
+		double maxLogL = logL[0];
+		for (int i = 1; i < numH; i++)
+		{
+			if (logL[i] > maxLogL)
+			{
+				bestH = i;
+				maxLogL = logL[i];
+			}
+		}
+		
+		// compute log-likelihood differences to best hypothesis
+		for (int i = 0; i < numH; i++)
+		{
+			delta[i] = logL[bestH]-logL[i];
+		}
+		
+		// allocate temporary memory for resampling procedure
+		double[][] rs = new double[numH][numBoot];
+		
+		// Resample data
+		MersenneTwisterFast mt = new MersenneTwisterFast();
+		for (int i = 0; i < numBoot; i++)
+		{
+			for (int j = 0; j < numSites; j++)
+			{
+				int s = mt.nextInt(numSites);
+				
+				int p;
+				if (alias == null)
+				{
+					p = s;
+				}
+				else
+				{
+					p = alias[s];
+				}
+				
+				for (int k = 0; k < numH; k++)
+				{
+					rs[k][i] += pLogL[k][p];
+				}
+			}
+		}  
+		
+		// center resampled log-likelihoods
+		for (int i = 0; i < numH; i++)
+		{
+			double m = DiscreteStatistics.mean(rs[i]);
+			
+			for (int j = 0; j < numBoot; j++)
+			{
+				rs[i][j] = rs[i][j]-m;
+			}
+		}
+		
+		// compute resampled log-likelihood differences
+		for (int i = 0; i < numBoot; i++)
+		{
+			double max = findMaxInColumn(rs, i);
+						
+			for (int j = 0; j < numH; j++)
+			{
+				rs[j][i] = max - rs[j][i];
+			}
+		}
+			
+		// compute p-values for each hypothesis
+		for (int i = 0; i < numH; i++)
+		{
+			int count = 0;
+			for (int j = 0; j < numBoot; j++)
+			{
+				if (rs[i][j] >= delta[i])
+				{
+					count++;
+				}
+			}
+			
+			pval[i] = (double) count/(double) numBoot;
+		}
+		
+		// free memory
+		rs = null;
+		logL = null;
+	}
+	
+	private double findMaxInColumn(double[][] array, int column)
+	{
+		int len = array.length;
+		
+		int best = 0;
+		double max = array[0][column];
+		for (int i = 1; i < len; i++)
+		{
+			if (array[i][column] > max)
+			{
+				best = i;
+				max = array[i][column];
+			}
+		}
+		
+		return max;
+	}
+}
+
diff --git a/LibrarySource/pal/statistics/makefile b/LibrarySource/pal/statistics/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/statistics/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/statistics/package.html b/LibrarySource/pal/statistics/package.html
new file mode 100644
index 0000000..69311da
--- /dev/null
+++ b/LibrarySource/pal/statistics/package.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+Classes with useful for statistics (normal distribution, 
+Gamma distribution, chi-square distribution, exponential distribution,
+likelihood-ratio test, chi-square test, descriptive statistics, bootstrap estimators etc.) 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/substmodel/AbstractRateMatrix.java b/LibrarySource/pal/substmodel/AbstractRateMatrix.java
new file mode 100644
index 0000000..7f69bbf
--- /dev/null
+++ b/LibrarySource/pal/substmodel/AbstractRateMatrix.java
@@ -0,0 +1,278 @@
+// RateMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.io.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * abstract base class for all rate matrices
+ *
+ * @version $Id: AbstractRateMatrix.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+abstract public class AbstractRateMatrix implements RateMatrix
+{
+	//
+	// Public stuff
+	//
+
+	// Constraints and conventions:
+	// - first argument: row
+	// - second argument: column
+	// - transition: from row to column
+	// - sum of every row = 0
+	// - sum of frequencies = 1
+	// - frequencies * rate matrix = 0 (stationarity)
+	// - expected number of substitutions = 1 (Sum_i pi_i*R_ii = 0)
+
+	/** dimension */
+	public int dimension;
+
+	/** stationary frequencies (sum = 1.0) */
+	public double[] frequency;
+
+	/**
+	 * rate matrix (transition: from 1st index to 2nd index)
+	 */
+	public double[][] rate;
+
+	/** data type */
+	public DataType dataType;
+
+	/**
+	 * get numerical code describing the data type
+	 *
+	 * @return integer code identifying a data type
+	 */
+	public int getTypeID()	{
+		return dataType.getTypeID();
+	}
+
+	/**
+	 * get numerical code describing the model type
+	 *
+	 * @return integer code identifying a substitution model
+	 */
+	abstract public int getModelID();
+
+	public int getDimension() {
+   	return dimension;
+	}
+
+	/**
+		* @return stationary frequencies (sum = 1.0)
+		*/
+	public double[] getEqulibriumFrequencies() {
+		return frequency;
+	}
+
+	/**
+		* @return stationary frequencie (sum = 1.0) for ith state
+		*/
+	public double getEqulibriumFrequency(int i) {
+		return frequency[i];
+	}
+
+
+	/** For those that like Getter/Setters */
+	public DataType getDataType() {
+		return dataType;
+	}
+
+	/**
+		Return a matrix exponential appropriate to this ratematrix (generally returns SimpleRateMatrix())
+	*/
+	public TransitionProbability getTransitionProbability() {
+		return new MatrixExponential(this);
+	}
+
+		/**
+		Return a matrix exponential appropriate to this ratematrix (generally returns SimpleRateMatrix())
+		given an old matrix exponential (may reuse old matrix exponential)
+	*/
+	public TransitionProbability getTransitionProbability(TransitionProbability old) {
+		if(old instanceof MatrixExponential) {
+			((MatrixExponential)old).setMatrix(this);
+			return old;
+		}
+		return getTransitionProbability();
+	}
+
+	/**
+	 * @return rate matrix (transition: from 1st index to 2nd index)
+	 */
+	public double[][] getRelativeRates() {
+		return rate;
+	}
+
+	// interface Report (remains abstract)
+	
+	// interface Parameterized (remains abstract)
+
+
+ 	//
+	// Protected stuff (for use in derived classes)
+	//
+
+	// Constructor 
+	protected AbstractRateMatrix(int dim)
+	{
+		format = FormattedOutput.getInstance();
+		
+		dimension = dim;
+		frequency = new double[dim];
+		rate = new double[dim][dim];
+	}
+ 
+	protected FormattedOutput format;
+	
+	protected void printFrequencies(PrintWriter out)
+	{
+		for (int i = 0; i < dimension; i++)
+		{
+			out.print("pi(" + dataType.getChar(i) + ") = ");
+			format.displayDecimal(out, frequency[i], 5);
+			out.println();
+		}
+		out.println();
+	}
+ 
+ 	protected void setFrequencies(double[] f)
+	{
+		for (int i = 0; i < dimension; i++)
+		{
+			frequency[i] = f[i];
+		}
+		checkFrequencies();
+	}
+ 
+	// Computes normalized rate matrix from Q matrix (general reversible model)
+	// - Q_ii = 0
+	// - Q_ij = Q_ji
+	// - Q_ij is stored in R_ij (rate)
+	// - only upper triangular is used
+	protected void fromQToR()
+	{
+		double q;
+		
+		for (int i = 0; i < dimension; i++)
+		{
+			for (int j = i + 1; j < dimension; j++)
+			{
+				q = rate[i][j];
+				rate[i][j] = q*frequency[j];
+				rate[j][i] = q*frequency[i];
+			}
+		}
+	
+		makeValid();
+		normalize();
+	}
+
+
+ 	//
+	// Private stuff
+	//
+	
+	// Make it a valid rate matrix (make sum of rows = 0)
+	private void makeValid()
+	{
+		for (int i = 0; i < dimension; i++)
+		{
+			double sum = 0.0;
+			for (int j = 0; j < dimension; j++)
+			{
+				if (i != j)
+				{
+					sum += rate[i][j];
+				}
+			}
+			rate[i][i] = -sum;
+		}
+	}
+	
+	// Normalize rate matrix to one expected substitution per unit time
+	private void normalize()
+	{
+		double subst = 0.0;
+		
+		for (int i = 0; i < dimension; i++)
+		{
+			subst += -rate[i][i]*frequency[i];
+		}
+		for (int i = 0; i < dimension; i++)
+		{
+			for (int j = 0; j < dimension; j++)
+			{
+				rate[i][j] = rate[i][j]/subst;
+			}
+		}
+	}
+
+	/**
+	 * ensures that frequencies are not smaller than MINFREQ and
+	 * that two frequencies differ by at least 2*MINFDIFF.
+	 * This avoids potentiak problems later when eigenvalues
+	 * are computed.
+	 */
+	private void checkFrequencies()
+	{
+		// required frequency difference
+		double MINFDIFF = 1e-10;
+
+		// lower limit on frequency
+		double MINFREQ = 1e-10;  
+
+		int maxi = 0;
+		double sum = 0.0;
+		double maxfreq = 0.0;
+		for (int i = 0; i < dimension; i++)
+		{
+			double freq = frequency[i];
+			if (freq < MINFREQ) frequency[i] = MINFREQ;
+			if (freq > maxfreq)
+			{
+				maxfreq = freq;
+				maxi = i;
+			}
+			sum += frequency[i];
+		}
+		frequency[maxi] += 1.0 - sum;
+	
+		for (int i = 0; i < dimension - 1; i++)
+		{
+			for (int j = i+1; j < dimension; j++)
+			{
+				if (frequency[i] == frequency[j])
+				{
+					frequency[i] += MINFDIFF;
+					frequency[j] -= MINFDIFF;
+				}
+			}
+		}
+	}
+
+	public Object clone() {
+		try {
+			RateMatrix matrix = (RateMatrix)super.clone();
+			return matrix;
+		} catch (CloneNotSupportedException e) {
+			// this shouldn't happen
+			throw new InternalError();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/AminoAcidModel.java b/LibrarySource/pal/substmodel/AminoAcidModel.java
new file mode 100644
index 0000000..96219f3
--- /dev/null
+++ b/LibrarySource/pal/substmodel/AminoAcidModel.java
@@ -0,0 +1,192 @@
+// AminoAcidModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * base class of rate matrices for amino acids
+ *
+ * @version $Id: AminoAcidModel.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public abstract class AminoAcidModel extends AbstractRateMatrix implements RateMatrix
+{
+
+	/**
+	 * Create amino acid model according to model type
+	 *
+	 * @param modelID model code
+	 * @param freq  model frequencies
+	 *
+	 * @return amino acid rate matrix
+	 */
+	public static AminoAcidModel getInstance(int modelID, double[] freq)
+	{
+		if (modelID == AminoAcidModelID.DAYHOFF)
+		{
+			return new Dayhoff(freq);
+		}
+		else if (modelID == AminoAcidModelID.JTT)
+		{
+			return new JTT(freq);
+		}
+		else if (modelID == AminoAcidModelID.MTREV24)
+		{
+			return new MTREV24(freq);
+		}
+		else if (modelID == AminoAcidModelID.BLOSUM62)
+		{
+			return new BLOSUM62(freq);
+		}
+		else if (modelID == AminoAcidModelID.VT)
+		{
+			return new VT(freq);
+		}
+		else if (modelID == AminoAcidModelID.WAG)
+		{
+			return new WAG(freq);
+		}
+		else if (modelID == AminoAcidModelID.CPREV)
+		{
+			return new CPREV(freq);
+		}
+		else
+		{
+			return new Dayhoff(freq);
+		}
+	}
+
+	/**
+	 * get numerical code of amino acid model that would probably
+	 * be suitable for a given sequence data set
+	 *
+	 * @param freq amino acid frequencies of the data set
+	 *
+	 * @return numerical code of suitable AminoAcidModel
+	 */
+	public static int getSuitableModelID(double[] freq)
+	{	
+		int NUMMODELS = AminoAcidModelID.MODELCOUNT;
+		double[] ofreq = new double[20];
+		double[] dist = new double[NUMMODELS];
+		
+		Dayhoff.getOriginalFrequencies(ofreq);
+		dist[0] = getDist(freq, ofreq);
+		JTT.getOriginalFrequencies(ofreq);
+		dist[1] = getDist(freq, ofreq);
+		MTREV24.getOriginalFrequencies(ofreq);
+		dist[2] = getDist(freq, ofreq);
+		BLOSUM62.getOriginalFrequencies(ofreq);
+		dist[3] = getDist(freq, ofreq);
+		VT.getOriginalFrequencies(ofreq);
+		dist[4] = getDist(freq, ofreq);
+		WAG.getOriginalFrequencies(ofreq);
+		dist[5] = getDist(freq, ofreq);
+		CPREV.getOriginalFrequencies(ofreq);
+		dist[6] = getDist(freq, ofreq);
+
+		int bestModel = 0;
+		double minDist = dist[0];
+		
+		for (int i = 1; i < NUMMODELS; i++)
+		{
+			if (dist[i] < minDist)
+			{
+				minDist = dist[i];
+				bestModel = i;
+			}
+		}
+		
+		return bestModel; 
+	}
+
+	// interface Report
+
+	public abstract void report(PrintWriter out);
+	
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 0;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		return;
+	}
+
+	public double getParameter(int n)
+	{
+		return 0.0;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.0;
+	}
+	
+
+	
+	//
+	// Protected stuff
+	//
+
+	// Constructor
+	protected AminoAcidModel(double[] f)
+	{
+		// Dimension = 20
+		super(20);
+		
+		dataType = new AminoAcids();
+		setFrequencies(f);
+	}
+	
+	protected void printFrequencies(PrintWriter out)
+	{
+		out.println("Amino acid frequencies:");
+		super.printFrequencies(out);
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	private static double getDist(double[] f1, double[] f2)
+	{
+		double sum = 0.0;
+		for (int i = 0; i < f1.length; i++)
+		{
+			double diff = f1[i]-f2[i];
+			sum += diff*diff;
+		}
+		return sum;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/AminoAcidModelID.java b/LibrarySource/pal/substmodel/AminoAcidModelID.java
new file mode 100644
index 0000000..880b63c
--- /dev/null
+++ b/LibrarySource/pal/substmodel/AminoAcidModelID.java
@@ -0,0 +1,36 @@
+// AminoAcidModelID.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import java.io.Serializable;
+
+/**
+ * interface for IDs of amino acid models
+ *
+ * @version $Id: AminoAcidModelID.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface AminoAcidModelID extends Serializable
+{
+	//
+	// Public stuff
+	//
+
+	int DAYHOFF = 0;
+	int JTT = 1;
+	int MTREV24 = 2;
+	int BLOSUM62 = 3;
+	int VT = 4;
+	int WAG = 5;
+	int CPREV = 6;
+	
+	int MODELCOUNT = 7;
+
+}
+
diff --git a/LibrarySource/pal/substmodel/BLOSUM62.java b/LibrarySource/pal/substmodel/BLOSUM62.java
new file mode 100644
index 0000000..946492a
--- /dev/null
+++ b/LibrarySource/pal/substmodel/BLOSUM62.java
@@ -0,0 +1,195 @@
+// BLOSUM62.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * BLOSUM62 model of amino acid evolution
+ *
+ * @version $Id: BLOSUM62.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class BLOSUM62 extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public BLOSUM62(double[] f)
+	{
+		super(f);
+
+		makeBLOSUM62();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 3;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: BLOSUM62 (Henikoff-Henikoff 1992)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0]=0.074; f[1]=0.052; f[2]=0.045; f[3]=0.054;
+		f[4]=0.025; f[5]=0.034; f[6]=0.054; f[7]=0.074;
+		f[8]=0.026; f[9]=0.068; f[10]=0.099; f[11]=0.058;
+		f[12]=0.025; f[13]=0.047; f[14]=0.039; f[15]=0.057;
+		f[16]=0.051; f[17]=0.013; f[18]=0.032; f[19]=0.073;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// BLOSUM62 model of amino acid evolution
+	// Henikoff, S., and J. G. Henikoff. 1992. PNAS USA 89:10915-10919.
+	private void makeBLOSUM62()
+	{		
+		// Q matrix
+		rate[0][1]=7.3579038969751e-01; 	rate[0][2]=4.8539105546575e-01;
+		rate[0][3]=5.4316182089867e-01; 	rate[0][4]=1.4599953104700e+00;
+		rate[0][5]=1.1997057046020e+00; 	rate[0][6]=1.1709490427999e+00;
+		rate[0][7]=1.9558835749595e+00; 	rate[0][8]=7.1624144499779e-01;
+		rate[0][9]=6.0589900368677e-01; 	rate[0][10]=8.0001653051838e-01;
+		rate[0][11]=1.2952012667833e+00; 	rate[0][12]=1.2537582666635e+00;
+		rate[0][13]=4.9296467974759e-01; 	rate[0][14]=1.1732759009239e+00;
+		rate[0][15]=4.3250926870566e+00; 	rate[0][16]=1.7291780194850e+00;
+		rate[0][17]=4.6583936772479e-01; 	rate[0][18]=7.1820669758623e-01;
+		rate[0][19]=2.1877745220045e+00; 
+	
+		rate[1][2]=1.2974467051337e+00; 	rate[1][3]=5.0096440855513e-01;
+		rate[1][4]=2.2782657420895e-01; 	rate[1][5]=3.0208336100636e+00;
+		rate[1][6]=1.3605741904203e+00; 	rate[1][7]=4.1876330851753e-01;
+		rate[1][8]=1.4561411663360e+00; 	rate[1][9]=2.3203644514174e-01;
+		rate[1][10]=6.2271166969249e-01; 	rate[1][11]=5.4111151414889e+00;
+		rate[1][12]=9.8369298745695e-01; 	rate[1][13]=3.7164469320875e-01;
+		rate[1][14]=4.4813366171831e-01; 	rate[1][15]=1.1227831042096e+00;
+		rate[1][16]=9.1466595456337e-01; 	rate[1][17]=4.2638231012175e-01;
+		rate[1][18]=7.2051744121611e-01; 	rate[1][19]=4.3838834377202e-01;
+
+		rate[2][3]=3.1801000482161e+00; 	rate[2][4]=3.9735894989702e-01;
+		rate[2][5]=1.8392161469920e+00; 	rate[2][6]=1.2404885086396e+00;
+		rate[2][7]=1.3558723444845e+00; 	rate[2][8]=2.4145014342081e+00;
+		rate[2][9]=2.8301732627800e-01; 	rate[2][10]=2.1188815961519e-01;
+		rate[2][11]=1.5931370434574e+00; 	rate[2][12]=6.4844127878707e-01;
+		rate[2][13]=3.5486124922252e-01; 	rate[2][14]=4.9488704370192e-01;
+		rate[2][15]=2.9041016564560e+00; 	rate[2][16]=1.8981736345332e+00;
+		rate[2][17]=1.9148204624678e-01; 	rate[2][18]=5.3822251903674e-01;
+		rate[2][19]=3.1285879799342e-01; 
+	
+		rate[3][4]=2.4083661480204e-01; 	rate[3][5]=1.1909457033960e+00;
+		rate[3][6]=3.7616252083685e+00; 	rate[3][7]=7.9847324896839e-01;
+		rate[3][8]=7.7814266402188e-01; 	rate[3][9]=4.1855573246161e-01;
+		rate[3][10]=2.1813157759360e-01; 	rate[3][11]=1.0324479249521e+00;
+		rate[3][12]=2.2262189795786e-01; 	rate[3][13]=2.8173069420651e-01;
+		rate[3][14]=7.3062827299842e-01; 	rate[3][15]=1.5827541420653e+00;
+		rate[3][16]=9.3418750943056e-01; 	rate[3][17]=1.4534504627853e-01;
+		rate[3][18]=2.6142220896504e-01; 	rate[3][19]=2.5812928941763e-01;
+
+		rate[4][5]=3.2980150463028e-01; 	rate[4][6]=1.4074889181440e-01;
+		rate[4][7]=4.1820319228376e-01; 	rate[4][8]=3.5405810983129e-01;
+		rate[4][9]=7.7489402279418e-01; 	rate[4][10]=8.3184264014158e-01;
+		rate[4][11]=2.8507880090648e-01; 	rate[4][12]=7.6768882347954e-01;
+		rate[4][13]=4.4133747118660e-01; 	rate[4][14]=3.5600849876863e-01;
+		rate[4][15]=1.1971884150942e+00; 	rate[4][16]=1.1198313585160e+00;
+		rate[4][17]=5.2766441887169e-01; 	rate[4][18]=4.7023773369610e-01;
+		rate[4][19]=1.1163524786062e+00; 
+	
+		rate[5][6]=5.5289191779282e+00; 	rate[5][7]=6.0984630538281e-01;
+		rate[5][8]=2.4353411311401e+00; 	rate[5][9]=2.3620245120365e-01;
+		rate[5][10]=5.8073709318144e-01; 	rate[5][11]=3.9452776745146e+00;
+		rate[5][12]=2.4948960771127e+00; 	rate[5][13]=1.4435695975031e-01;
+		rate[5][14]=8.5857057567418e-01; 	rate[5][15]=1.9348709245965e+00;
+		rate[5][16]=1.2774802945956e+00; 	rate[5][17]=7.5865380864172e-01;
+		rate[5][18]=9.5898974285014e-01; 	rate[5][19]=5.3078579012486e-01;
+
+		rate[6][7]=4.2357999217628e-01; 	rate[6][8]=1.6268910569817e+00;
+		rate[6][9]=1.8684804693170e-01; 	rate[6][10]=3.7262517508685e-01;
+		rate[6][11]=2.8024271516787e+00; 	rate[6][12]=5.5541539747043e-01;
+		rate[6][13]=2.9140908416530e-01; 	rate[6][14]=9.2656393484598e-01;
+		rate[6][15]=1.7698932389373e+00; 	rate[6][16]=1.0710972360073e+00;
+		rate[6][17]=4.0763564893830e-01; 	rate[6][18]=5.9671930034577e-01;
+		rate[6][19]=5.2425384633796e-01; 
+	
+		rate[7][8]=5.3985912495418e-01; 	rate[7][9]=1.8929629237636e-01;
+		rate[7][10]=2.1772115923623e-01; 	rate[7][11]=7.5204244030271e-01;
+		rate[7][12]=4.5943617357855e-01; 	rate[7][13]=3.6816646445253e-01;
+		rate[7][14]=5.0408659952683e-01; 	rate[7][15]=1.5093262532236e+00;
+		rate[7][16]=6.4143601140497e-01; 	rate[7][17]=5.0835892463812e-01;
+		rate[7][18]=3.0805573703500e-01; 	rate[7][19]=2.5334079019018e-01;
+
+		rate[8][9]=2.5271844788492e-01; 	rate[8][10]=3.4807220979697e-01;
+		rate[8][11]=1.0225070358890e+00; 	rate[8][12]=9.8431152535870e-01;
+		rate[8][13]=7.1453370392764e-01; 	rate[8][14]=5.2700733915060e-01;
+		rate[8][15]=1.1170297629105e+00; 	rate[8][16]=5.8540709022472e-01;
+		rate[8][17]=3.0124860078016e-01; 	rate[8][18]=4.2189539693890e+00;
+		rate[8][19]=2.0155597175031e-01; 
+	
+		rate[9][10]=3.8909637733035e+00; 	rate[9][11]=4.0619358664202e-01;
+		rate[9][12]=3.3647977631042e+00; 	rate[9][13]=1.5173593259539e+00;
+		rate[9][14]=3.8835540920564e-01; 	rate[9][15]=3.5754441245967e-01;
+		rate[9][16]=1.1790911972601e+00; 	rate[9][17]=3.4198578754023e-01;
+		rate[9][18]=6.7461709322842e-01; 	rate[9][19]=8.3118394054582e+00;
+
+		rate[10][11]=4.4557027426059e-01; 	rate[10][12]=6.0305593795716e+00;
+		rate[10][13]=2.0648397032375e+00; 	rate[10][14]=3.7455568747097e-01;
+		rate[10][15]=3.5296918452729e-01; 	rate[10][16]=9.1525985769421e-01;
+		rate[10][17]=6.9147463459998e-01; 	rate[10][18]=8.1124585632307e-01;
+		rate[10][19]=2.2314056889131e+00; 
+	
+		rate[11][12]=1.0730611843319e+00; 	rate[11][13]=2.6692475051102e-01;
+		rate[11][14]=1.0473834507215e+00; 	rate[11][15]=1.7521659178195e+00;
+		rate[11][16]=1.3038752007987e+00; 	rate[11][17]=3.3224304063396e-01;
+		rate[11][18]=7.1799348690032e-01; 	rate[11][19]=4.9813847530407e-01;
+
+		rate[12][13]=1.7738551688305e+00; 	rate[12][14]=4.5412362510273e-01;
+		rate[12][15]=9.1872341574605e-01; 	rate[12][16]=1.4885480537218e+00;
+		rate[12][17]=8.8810109815193e-01; 	rate[12][18]=9.5168216224591e-01;
+		rate[12][19]=2.5758507553153e+00; 
+	
+		rate[13][14]=2.3359790962888e-01; 	rate[13][15]=5.4002764482413e-01;
+		rate[13][16]=4.8820611879305e-01; 	rate[13][17]=2.0743248934965e+00;
+		rate[13][18]=6.7472604308008e+00; 	rate[13][19]=8.3811961017754e-01;
+
+		rate[14][15]=1.1691295777157e+00; 	rate[14][16]=1.0054516831488e+00;
+		rate[14][17]=2.5221483002727e-01; 	rate[14][18]=3.6940531935451e-01;
+		rate[14][19]=4.9690841067567e-01; 
+	
+		rate[15][16]=5.1515562922704e+00; 	rate[15][17]=3.8792562209837e-01;
+		rate[15][18]=7.9675152076106e-01; 	rate[15][19]=5.6192545744165e-01;
+
+		rate[16][17]=5.1312812689059e-01; 	rate[16][18]=8.0101024319939e-01;
+		rate[16][19]=2.2530740511763e+00; 
+	
+		rate[17][18]=4.0544190065580e+00; 	rate[17][19]=2.6650873142646e-01;
+
+		rate[18][19]=1.0000000000000e+00; 
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/CPREV.java b/LibrarySource/pal/substmodel/CPREV.java
new file mode 100644
index 0000000..66d70dc
--- /dev/null
+++ b/LibrarySource/pal/substmodel/CPREV.java
@@ -0,0 +1,210 @@
+// CPREV.java
+//
+// (c) 2000-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * CPREV model of amino acid evolution (J.Adachi et al. 2000)
+ *
+ * @version $Id: CPREV.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class CPREV extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public CPREV(double[] f)
+	{
+		super(f);
+
+		makeCPREV();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 6;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: CPREV (Adachi et al. 2000)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0] = 0.076;
+		f[1] = 0.062;
+		f[2] = 0.041;
+		f[3] = 0.037;
+		f[4] = 0.009;
+		f[5] = 0.038;
+		f[6] = 0.049;
+		f[7] = 0.084;
+		f[8] = 0.025;
+		f[9] = 0.081;
+		f[10] = 0.101;
+		f[11] = 0.050;
+		f[12] = 0.022;
+		f[13] = 0.051;
+		f[14] = 0.043;
+		f[15] = 0.062;
+		f[16] = 0.054;
+		f[17] = 0.018;
+		f[18] = 0.031;
+		f[19] = 0.066;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// CPREV 45 model of amino acid evolution
+	// Adachi, J., P.J. Waddell, W. Martin, and M. Hasegawa. 2000. JME 50:348-358
+	private void makeCPREV()
+	{		
+		// Q matrix
+		rate[0][1] = 105; rate[0][2] = 227; 
+		rate[0][3] = 175; rate[0][4] = 669; 
+		rate[0][5] = 157; rate[0][6] = 499; 
+		rate[0][7] = 665; rate[0][8] = 66; 
+		rate[0][9] = 145; rate[0][10] = 197; 
+		rate[0][11] = 236; rate[0][12] = 185; 
+		rate[0][13] = 68; rate[0][14] = 490; 
+		rate[0][15] = 2440; rate[0][16] = 1340; 
+		rate[0][17] = 14; rate[0][18] = 56; 
+		rate[0][19] = 968; 
+		
+		rate[1][2] = 357; rate[1][3] = 43; 
+		rate[1][4] = 823; rate[1][5] = 1745; 
+		rate[1][6] = 152; rate[1][7] = 243; 
+		rate[1][8] = 715; rate[1][9] = 136; 
+		rate[1][10] = 203; rate[1][11] = 4482; 
+		rate[1][12] = 125; rate[1][13] = 53; 
+		rate[1][14] = 87; rate[1][15] = 385; 
+		rate[1][16] = 314; rate[1][17] = 230; 
+		rate[1][18] = 323; rate[1][19] = 92; 
+		
+		rate[2][3] = 4435; rate[2][4] = 538; 
+		rate[2][5] = 768; rate[2][6] = 1055; 
+		rate[2][7] = 653; rate[2][8] = 1405; 
+		rate[2][9] = 168; rate[2][10] = 113; 
+		rate[2][11] = 2430; rate[2][12] = 61; 
+		rate[2][13] = 97; rate[2][14] = 173; 
+		rate[2][15] = 2085; rate[2][16] = 1393; 
+		rate[2][17] = 40; rate[2][18] = 754; 
+		rate[2][19] = 83; 
+		
+		rate[3][4] = 10; rate[3][5] = 400; 
+		rate[3][6] = 3691; rate[3][7] = 431; 
+		rate[3][8] = 331; rate[3][9] = 10; 
+		rate[3][10] = 10; rate[3][11] = 412; 
+		rate[3][12] = 47; rate[3][13] = 22; 
+		rate[3][14] = 170; rate[3][15] = 590; 
+		rate[3][16] = 266; rate[3][17] = 18; 
+		rate[3][18] = 281; rate[3][19] = 75; 
+		
+		rate[4][5] = 10; rate[4][6] = 10; 
+		rate[4][7] = 303; rate[4][8] = 441; 
+		rate[4][9] = 280; rate[4][10] = 396; 
+		rate[4][11] = 48; rate[4][12] = 159; 
+		rate[4][13] = 726; rate[4][14] = 285; 
+		rate[4][15] = 2331; rate[4][16] = 576; 
+		rate[4][17] = 435; rate[4][18] = 1466; 
+		rate[4][19] = 592; 
+		
+		rate[5][6] = 3122; rate[5][7] = 133; 
+		rate[5][8] = 1269; rate[5][9] = 92; 
+		rate[5][10] = 286; rate[5][11] = 3313; 
+		rate[5][12] = 202; rate[5][13] = 10; 
+		rate[5][14] = 323; rate[5][15] = 396; 
+		rate[5][16] = 241; rate[5][17] = 53; 
+		rate[5][18] = 391; rate[5][19] = 54; 
+		
+		rate[6][7] = 379; rate[6][8] = 162; 
+		rate[6][9] = 148; rate[6][10] = 82; 
+		rate[6][11] = 2629; rate[6][12] = 113; 
+		rate[6][13] = 145; rate[6][14] = 185; 
+		rate[6][15] = 568; rate[6][16] = 369; 
+		rate[6][17] = 63; rate[6][18] = 142; 
+		rate[6][19] = 200; 
+		
+		rate[7][8] = 19; rate[7][9] = 40; 
+		rate[7][10] = 20; rate[7][11] = 263; 
+		rate[7][12] = 21; rate[7][13] = 25; 
+		rate[7][14] = 28; rate[7][15] = 691; 
+		rate[7][16] = 92; rate[7][17] = 82; 
+		rate[7][18] = 10; rate[7][19] = 91; 
+		
+		rate[8][9] = 29; rate[8][10] = 66; 
+		rate[8][11] = 305; rate[8][12] = 10; 
+		rate[8][13] = 127; rate[8][14] = 152; 
+		rate[8][15] = 303; rate[8][16] = 32; 
+		rate[8][17] = 69; rate[8][18] = 1971; 
+		rate[8][19] = 25; 
+		
+		rate[9][10] = 1745; rate[9][11] = 345; 
+		rate[9][12] = 1772; rate[9][13] = 454; 
+		rate[9][14] = 117; rate[9][15] = 216; 
+		rate[9][16] = 1040; rate[9][17] = 42; 
+		rate[9][18] = 89; rate[9][19] = 4797; 
+		
+		rate[10][11] = 218; rate[10][12] = 1351; 
+		rate[10][13] = 1268; rate[10][14] = 219; 
+		rate[10][15] = 516; rate[10][16] = 156; 
+		rate[10][17] = 159; rate[10][18] = 189; 
+		rate[10][19] = 865; 
+		
+		rate[11][12] = 193; rate[11][13] = 72; 
+		rate[11][14] = 302; rate[11][15] = 868; 
+		rate[11][16] = 918; rate[11][17] = 10; 
+		rate[11][18] = 247; rate[11][19] = 249; 
+		
+		rate[12][13] = 327; rate[12][14] = 100; 
+		rate[12][15] = 93; rate[12][16] = 645; 
+		rate[12][17] = 86; rate[12][18] = 215; 
+		rate[12][19] = 475; 
+		
+		rate[13][14] = 43; rate[13][15] = 487; 
+		rate[13][16] = 148; rate[13][17] = 468; 
+		rate[13][18] = 2370; rate[13][19] = 317; 
+		
+		rate[14][15] = 1202; rate[14][16] = 260; 
+		rate[14][17] = 49; rate[14][18] = 97; 
+		rate[14][19] = 122; 
+		
+		rate[15][16] = 2151; rate[15][17] = 73; 
+		rate[15][18] = 522; rate[15][19] = 167; 
+		
+		rate[16][17] = 29; rate[16][18] = 71; 
+		rate[16][19] = 760; 
+		
+		rate[17][18] = 346; rate[17][19] = 10; 
+		
+		rate[18][19] = 119; 		
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/CodonModel.java b/LibrarySource/pal/substmodel/CodonModel.java
new file mode 100644
index 0000000..b9f9b60
--- /dev/null
+++ b/LibrarySource/pal/substmodel/CodonModel.java
@@ -0,0 +1,89 @@
+// CodonModel.java
+//
+// (c) 1999-2001 PAL Development Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * base class for nucleotide rate matrices
+ *
+ * @version $Id: CodonModel.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Andrew Rambaut
+ */
+abstract public class CodonModel extends AbstractRateMatrix implements RateMatrix, Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Create codon substitution model according to model type
+	 *
+	 * @param modelID model code
+	 * @param params model parameters
+	 * @param freq  model frequencies
+	 *
+	 * @return codon rate matrix
+	 */
+	public static CodonModel getInstance(int modelID, double[] params, double[] freq)
+	{
+		if (modelID == 0)
+		{
+			return new YangCodonModel(params, freq);
+		}
+		else
+		{
+// Throw error?
+			return new YangCodonModel(params, freq);
+		}
+	}
+
+	// interface Report (inherited, remains abstract)
+	
+	// interface Parameterized (inherited, remains abstract)
+	
+
+	//
+	// Protected stuff (for use in derived classes)
+	//
+
+	// Constructor
+	protected CodonModel(double[] f)
+	{
+		// Dimension = 64
+		super(64);
+		
+		dataType = new Codons();
+		setFrequencies(f);
+	}
+
+	protected void printFrequencies(PrintWriter out)
+	{
+		out.println("Codon frequencies:");
+		super.printFrequencies(out);
+	}
+	
+	protected void printRatios(PrintWriter out)
+	{
+	}
+
+	//
+	// Private stuff
+	//
+
+	private void computeRatios()
+	{
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/Dayhoff.java b/LibrarySource/pal/substmodel/Dayhoff.java
new file mode 100644
index 0000000..a1ca3d3
--- /dev/null
+++ b/LibrarySource/pal/substmodel/Dayhoff.java
@@ -0,0 +1,198 @@
+// Dayhoff.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Dayhoff model for amino acid evolution
+ *
+ * @version $Id: Dayhoff.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class Dayhoff extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public Dayhoff(double[] f)
+	{
+		super(f);
+		
+		makeDayhoff();
+		fromQToR();
+	}
+ 
+ 	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 0;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: Dayhoff (Dayhoff et al. 1978)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0] = 0.087; f[1] = 0.041; f[2] = 0.040; f[3] = 0.047;
+		f[4] = 0.033; f[5] = 0.038; f[6] = 0.05; f[7] = 0.089;
+		f[8] = 0.034; f[9] = 0.037; f[10] = 0.085; f[11] = 0.08;
+		f[12] = 0.015; f[13] = 0.04; f[14] = 0.051; f[15] = 0.07;
+		f[16] = 0.058; f[17] = 0.01; f[18] = 0.03; f[19] = 0.065;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// Dayhoff model for amino acid evolution
+	// Dayhoff, M.O., Schwartz, R.M., Orcutt, B.C. (1978)
+	// A model of evolutionary change in proteins.
+	// Dayhoff, M.O. (ed.) Atlas of Protein Sequence Structur., Vol5, Suppl. 3,
+	// National Biomedical Research Foundation, Washington DC, pp. 345-352.
+	private void makeDayhoff()
+	{		
+		// Q matrix
+		rate[0][1]=9.6472567159749e-01; 	rate[0][2]=3.5927991886410e+00;
+		rate[0][3]=4.3200552414656e+00; 	rate[0][4]=1.3184584178499e+00;
+		rate[0][5]=3.2267534963169e+00; 	rate[0][6]=7.0141987829615e+00;
+		rate[0][7]=8.5773867857875e+00; 	rate[0][8]=8.1434196396611e-01;
+		rate[0][9]=2.3518447453539e+00; 	rate[0][10]=1.4735711728911e+00;
+		rate[0][11]=9.3940162271805e-01; 	rate[0][12]=2.5490196078431e+00;
+		rate[0][13]=6.5922920892495e-01; 	rate[0][14]=8.9189834148670e+00;
+		rate[0][15]=1.4540712836859e+01; 	rate[0][16]=1.3411904595370e+01;
+		rate[0][17]=3.8517964118027e-02; 	rate[0][18]=8.7897227856660e-01;
+		rate[0][19]=7.4036511156187e+00; 
+	
+		rate[1][2]=1.1890243902439e+00; 	rate[1][3]=5.9525626545377e-02;
+		rate[1][4]=8.4778922655537e-01; 	rate[1][5]=8.8348561504191e+00;
+		rate[1][6]=5.5954088952654e-02; 	rate[1][7]=3.1434881434075e-01;
+		rate[1][8]=8.4753987678285e+00; 	rate[1][9]=2.2684090115941e+00;
+		rate[1][10]=5.5954088952654e-01; 	rate[1][11]=1.6681312769010e+01;
+		rate[1][12]=3.1707317073171e+00; 	rate[1][13]=4.8959827833572e-01;
+		rate[1][14]=3.6754156468900e+00; 	rate[1][15]=5.4755072760812e+00;
+		rate[1][16]=9.6472567159749e-01; 	rate[1][17]=7.5538020086083e+00;
+		rate[1][18]=2.7977044476327e-01; 	rate[1][19]=8.6083213773314e-01;
+
+		rate[2][3]=3.2459324155194e+01; 	rate[2][4]=7.3852625416383e-02;
+		rate[2][5]=3.7732198142415e+00; 	rate[2][6]=5.3911764705882e+00;
+		rate[2][7]=5.0264375413087e+00; 	rate[2][8]=1.9061418685121e+01;
+		rate[2][9]=2.7901430842607e+00; 	rate[2][10]=1.2482698961938e+00;
+		rate[2][11]=1.1542279411765e+01; 	rate[2][12]=1.9117647058824e-01;
+		rate[2][13]=5.0183823529412e-01; 	rate[2][14]=1.5181660899654e+00;
+		rate[2][15]=1.7697478991597e+01; 	rate[2][16]=8.3557302231237e+00;
+		rate[2][17]=8.6029411764706e-01; 	rate[2][18]=3.4411764705882e+00;
+		rate[2][19]=5.7352941176471e-01; 
+	
+		rate[3][4]=2.5534152404601e-02; 	rate[3][5]=4.8811013767209e+00;
+		rate[3][6]=4.0561952440551e+01; 	rate[3][7]=4.4423506911730e+00;
+		rate[3][8]=3.0865788117500e+00; 	rate[3][9]=8.5749078239692e-01;
+		rate[3][10]=2.5926985518518e-02; 	rate[3][11]=2.5930851063830e+00;
+		rate[3][12]=1.1667143483333e-01; 	rate[3][13]=1.2963492759259e-02;
+		rate[3][14]=4.7853935065891e-01; 	rate[3][15]=3.4167709637046e+00;
+		rate[3][16]=2.3984722282163e+00; 	rate[3][17]=3.2408731898147e-02;
+		rate[3][18]=8.1351689612015e-02; 	rate[3][19]=6.3829787234043e-01;
+
+		rate[4][5]=2.1864264103535e-02; 	rate[4][6]=1.4770525083277e-02;
+		rate[4][7]=3.9055458751427e-01; 	rate[4][8]=1.0223340673168e+00;
+		rate[4][9]=1.5970515970516e+00; 	rate[4][10]=3.9098448749850e-02;
+		rate[4][11]=8.0776309049169e-03; 	rate[4][12]=1.4155086538140e-01;
+		rate[4][13]=8.6898395721925e-02; 	rate[4][14]=6.8155604487784e-01;
+		rate[4][15]=5.8097784568373e+00; 	rate[4][16]=5.9929928084086e-01;
+		rate[4][17]=3.4759358288770e-01; 	rate[4][18]=3.4759358288770e+00;
+		rate[4][19]=1.7647058823529e+00; 
+	
+		rate[5][6]=2.5476780185759e+01; 	rate[5][7]=1.0174974779977e+00;
+		rate[5][8]=2.1573939173192e+01; 	rate[5][9]=6.5266504894988e-01;
+		rate[5][10]=2.6634492806410e+00; 	rate[5][11]=5.5466331269350e+00;
+		rate[5][12]=4.0247678018576e+00; 	rate[5][13]=1.8038017885416e-02;
+		rate[5][14]=5.5044618466582e+00; 	rate[5][15]=2.0267580716497e+00;
+		rate[5][16]=1.9256432155439e+00; 	rate[5][17]=9.6202762055552e-02;
+		rate[5][18]=1.0061919504644e-01; 	rate[5][19]=1.2538699690402e+00;
+
+		rate[6][7]=2.8869795109055e+00; 	rate[6][8]=1.5519031141869e+00;
+		rate[6][9]=2.1701112877583e+00; 	rate[6][10]=4.0484429065744e-01;
+		rate[6][11]=2.9823529411765e+00; 	rate[6][12]=1.0705882352941e+00;
+		rate[6][13]=1.9801735189768e-02; 	rate[6][14]=1.7993079584775e+00;
+		rate[6][15]=2.8184873949580e+00; 	rate[6][16]=1.2261663286004e+00;
+		rate[6][17]=7.3114099162219e-02; 	rate[6][18]=7.6470588235294e-01;
+		rate[6][19]=1.3058823529412e+00; 
+	
+		rate[7][8]=3.7906768788150e-01; 	rate[7][9]=2.3128004846840e-02;
+		rate[7][10]=2.5776602775942e-01; 	rate[7][11]=9.6662260409782e-01;
+		rate[7][12]=6.0145406477198e-01; 	rate[7][13]=5.4775280898876e-01;
+		rate[7][14]=1.2382877804129e+00; 	rate[7][15]=8.2853366065527e+00;
+		rate[7][16]=1.1110604644803e+00; 	rate[7][17]=1.2888301387971e-01;
+		rate[7][18]=1.7114723586662e-02; 	rate[7][19]=1.9233311302049e+00;
+
+		rate[8][9]=2.7354343963341e-01; 	rate[8][10]=1.5876246692449e+00;
+		rate[8][11]=9.6993944636678e-01; 	rate[8][12]=1.2544085640577e-01;
+		rate[8][13]=1.6868512110727e+00; 	rate[8][14]=3.3075513942601e+00;
+		rate[8][15]=1.2530894710826e+00; 	rate[8][16]=8.1434196396611e-01;
+		rate[8][17]=1.0121107266436e+00; 	rate[8][18]=4.4982698961938e+00;
+		rate[8][19]=1.5570934256055e+00; 
+	
+		rate[9][10]=9.2275320303002e+00; 	rate[9][11]=1.6663354531002e+00;
+		rate[9][12]=1.1780604133545e+01; 	rate[9][13]=6.9753577106518e+00;
+		rate[9][14]=4.2551201720752e-01; 	rate[9][15]=8.8575970928912e-01;
+		rate[9][16]=6.8951811852420e+00; 	rate[9][17]=9.8802836705702e-02;
+		rate[9][18]=1.3434022257552e+00; 	rate[9][19]=3.1526232114467e+01;
+
+		rate[10][11]=6.5787197231834e-01; 	rate[10][12]=1.8622837370242e+01;
+		rate[10][13]=5.6340830449827e+00; 	rate[10][14]=1.1377976796255e+00;
+		rate[10][15]=6.1690558576372e-01; 	rate[10][16]=1.2098794893211e+00;
+		rate[10][17]=1.7543252595156e+00; 	rate[10][18]=1.0346020761246e+00;
+		rate[10][19]=6.2906574394464e+00; 
+	
+		rate[11][12]=8.6029411764706e+00; 	rate[11][13]=6.6640454965565e-03;
+		rate[11][14]=1.2089100346021e+00; 	rate[11][15]=3.4411764705882e+00;
+		rate[11][16]=4.9442190669371e+00; 	rate[11][17]=3.4272233982290e-02;
+		rate[11][18]=4.7794117647059e-01; 	rate[11][19]=3.7500000000000e-01;
+
+		rate[12][13]=3.2500000000000e+00; 	rate[12][14]=5.9976931949250e-01;
+		rate[12][15]=2.1848739495798e+00; 	rate[12][16]=3.6916835699797e+00;
+		rate[12][17]=1.6247577591604e-01; 	rate[12][18]=1.1508700794053e-01;
+		rate[12][19]=9.0588235294118e+00; 
+	
+		rate[13][14]=3.9359861591695e-01; 	rate[13][15]=1.6386554621849e+00;
+		rate[13][16]=4.9442190669371e-01; 	rate[13][17]=2.8676470588235e+00;
+		rate[13][18]=2.4852941176471e+01; 	rate[13][19]=4.4117647058824e-01;
+
+		rate[14][15]=8.6431043005437e+00; 	rate[14][16]=2.8308077795013e+00;
+		rate[14][17]=3.5840244687362e-02; 	rate[14][18]=4.3804743506776e-02;
+		rate[14][19]=1.7301038062284e+00; 
+	
+		rate[15][16]=1.9663865546218e+01; 	rate[15][17]=2.7857142857143e+00;
+		rate[15][18]=1.2016806722689e+00; 	rate[15][19]=1.0840336134454e+00;
+
+		rate[16][17]=4.2019597219666e-02; 	rate[16][18]=1.5162271805274e+00;
+		rate[16][19]=5.6592292089249e+00; 
+	
+		rate[17][18]=2.2941176470588e+00; 	rate[17][19]=1.2654363316538e-01;
+
+		rate[18][19]=1.0000000000000e+00; 
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/F81.java b/LibrarySource/pal/substmodel/F81.java
new file mode 100644
index 0000000..a3b054f
--- /dev/null
+++ b/LibrarySource/pal/substmodel/F81.java
@@ -0,0 +1,104 @@
+// F81.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Felsenstein 1981 model of nucleotide evolution
+ *
+ * @version $Id: F81.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class F81 extends NucleotideModel implements Serializable
+{
+	/**
+	 * constructor
+	 *
+	 * @param freq nucleotide frequencies
+	 */
+	public F81(double[] freq)
+	{
+		super(freq);
+		
+		makeF81();
+		fromQToR();
+	}
+ 
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 4;
+	}
+ 
+ 	// interface Report
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: F81 (Felsenstein 1981)");
+		printFrequencies(out);
+		printRatios(out);
+	}	
+	
+	// interface Parameterized
+	
+	public int getNumParameters()
+	{
+		return 0;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		return;
+	}
+
+	public double getParameter(int n)
+	{
+		return 0.0;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.0;
+	}
+
+
+	//
+	// Private stuff
+	// 
+
+	// Make F81 model
+	private void makeF81()
+	{
+		// Q matrix
+		rate[0][1] = 1; rate[0][2] = 1.0; rate[0][3] = 1;
+		rate[1][2] = 1; rate[1][3] = 1.0;
+		rate[2][3] = 1;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/F84.java b/LibrarySource/pal/substmodel/F84.java
new file mode 100644
index 0000000..3ab6ad6
--- /dev/null
+++ b/LibrarySource/pal/substmodel/F84.java
@@ -0,0 +1,168 @@
+// F84.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Felsenstein 1984 (PHYLIP) model of nucleotide evolution
+ *
+ * @version $Id: F84.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class F84 extends NucleotideModel implements Serializable
+{
+	/**
+	 * constructor 1
+	 *
+	 * @param expectedTsTv expected transition-transversion ratio
+	 * @param freq nucleotide frequencies
+	 */
+	public F84(double expectedTsTv, double[] freq)
+	{
+		super(freq);
+		
+		this.expectedTsTv = expectedTsTv;
+		
+		convertToTN();		
+		makeTN();
+		fromQToR();
+		
+		showSE = false;
+	}
+ 
+	/**
+	 * Constructor 2
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotide frequencies
+	 */
+	public F84(double[] params, double[] freq)
+	{
+		this(params[0], freq);
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 3;
+	}
+ 
+ 	// interface Report
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: F84 (Felsenstein 1984, PHYLIP)");
+		out.print("PHYLIP Transition/transversion parameter: ");
+		format.displayDecimal(out, expectedTsTv, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, expectedTsTvSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.println();
+		printFrequencies(out);
+		printRatios(out);
+		out.println();
+		out.println("This model corresponds to a Tamura-Nei (1993) model with");
+		out.print(" Transition/transversion rate ratio kappa: ");
+		format.displayDecimal(out, kappa, 2);
+		out.println();
+		out.print(" Y/R transition rate ratio: ");
+		format.displayDecimal(out, r, 2);
+		out.println();
+		out.println("and the above nucleotide frequencies.");
+		out.println();
+	}	
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		expectedTsTv = param;
+
+		convertToTN();
+		makeTN();
+		fromQToR();
+	}
+
+	public double getParameter(int n)
+	{
+		return expectedTsTv;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		expectedTsTvSE = paramSE;
+	
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 100.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 2.0;
+	}
+
+
+	//
+	// Private stuff
+	// 
+
+	private boolean showSE;
+	private double kappa, r;
+	private double expectedTsTv, expectedTsTvSE;
+	
+	private void convertToTN()
+	{
+		double piA = frequency[0];
+		double piC = frequency[1];
+		double piG = frequency[2];
+		double piT = frequency[3];
+		double piR = piA + piG;
+		double piY = piC + piT;
+		
+		double rho = (piR*piY*(piR*piY*expectedTsTv - (piA*piG + piC*piT)))/
+			(piC*piT*piR + piA*piG*piY);
+			
+		kappa = 1.0 + 0.5*rho*(1.0/piR + 1.0/piY);
+		r = (piY + rho)/piY * piR/(piR + rho);
+	}
+
+	// Make TN model
+	private void makeTN()
+	{
+		// Q matrix
+		rate[0][1] = 1; rate[0][2] = 2.0*kappa/(r+1.0); rate[0][3] = 1;
+		rate[1][2] = 1; rate[1][3] = 2.0*kappa*r/(r+1.0);
+		rate[2][3] = 1;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/GTR.java b/LibrarySource/pal/substmodel/GTR.java
new file mode 100644
index 0000000..c5c9b0f
--- /dev/null
+++ b/LibrarySource/pal/substmodel/GTR.java
@@ -0,0 +1,227 @@
+// GTR.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * GTR (general time reversible) model of nucleotide evolution
+ *
+ * @version $Id: GTR.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class GTR extends NucleotideModel implements Serializable
+{
+	/**
+	 * constructor 1
+	 *
+	 * @param a entry in rate matrix
+	 * @param b entry in rate matrix
+	 * @param c entry in rate matrix
+	 * @param d entry in rate matrix
+	 * @param e entry in rate matrix
+	 * @param freq nucleotide frequencies
+	 */
+	public GTR(double a, double b, double c, double d, double e, double[] freq)
+	{
+		super(freq);
+		
+		this.a = a;
+		this.b = b;
+		this.c = c;
+		this.d = d;
+		this.e = e;
+		
+		makeGTR();
+		fromQToR();
+		
+		showSE = false;
+	}
+
+	/**
+	 * constructor 2
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotide frequencies
+	 */
+	public GTR(double[] params, double[] freq)
+	{
+		this(params[0], params[1], params[2],
+			params[3], params[4], freq);
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 0;
+	}
+ 
+ 	// interface Report
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: GTR (Lanave et al. 1984)");
+		
+		out.print("Parameter a: ");
+		format.displayDecimal(out, a, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, aSE, 2);
+			out.print(")");
+		}
+		out.println();
+	
+		out.print("Parameter b: ");
+		format.displayDecimal(out, b, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, bSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.print("Parameter c: ");
+		format.displayDecimal(out, c, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, cSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.print("Parameter d: ");
+		format.displayDecimal(out, d, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, dSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.print("Parameter e: ");
+		format.displayDecimal(out, e, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, eSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.println("                                   A  C  G  T");
+		out.println("Corresponding rate matrix      ----------------");
+		out.println("(shown without frequencies):     A    a  b  c");
+		out.println("                                 C       d  e");
+		out.println("                                 G          1");
+				
+		out.println();
+		printFrequencies(out);
+		printRatios(out);
+	}	
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 5;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		switch(n)
+		{
+			case 0: a = param; break;
+			case 1: b = param; break;
+			case 2: c = param; break;
+			case 3: d = param; break;
+			case 4: e = param; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+				
+		makeGTR();
+		fromQToR();
+	}
+
+	public double getParameter(int n)
+	{
+		double value;
+		
+		switch(n)
+		{
+			case 0: value = a; break;
+			case 1: value = b; break;
+			case 2: value = c; break;
+			case 3: value = d; break;
+			case 4: value = e; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+				
+		return value;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		switch(n)
+		{
+			case 0: aSE = paramSE; break;
+			case 1: bSE = paramSE; break;
+			case 2: cSE = paramSE; break;
+			case 3: dSE = paramSE; break;
+			case 4: eSE = paramSE; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+		
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 10000.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 1.0;
+	}
+	
+
+	//
+	// Private stuff
+	// 
+
+	private boolean showSE;
+	private double a, b, c, d, e;
+	private double aSE, bSE, cSE, dSE, eSE;
+
+	// Make REV model
+	private void makeGTR()
+	{
+		// Q matrix
+		rate[0][1] = a; rate[0][2] = b; rate[0][3] = c;
+		rate[1][2] = d; rate[1][3] = e;
+		rate[2][3] = 1;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/GammaRates.java b/LibrarySource/pal/substmodel/GammaRates.java
new file mode 100644
index 0000000..1b46413
--- /dev/null
+++ b/LibrarySource/pal/substmodel/GammaRates.java
@@ -0,0 +1,133 @@
+// GammaRates.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.statistics.*;
+
+import java.io.*;
+
+
+/**
+ * discrete Gamma distribution (Z. Yang. 1994. JME 39:306-314)
+ *
+ * @version $Id: GammaRates.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class GammaRates extends RateDistribution implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * construct discrete Gamma distribution (mean = 1.0)
+	 *
+	 * @param n number of categories
+	 * @param a shape parameter (alpha)
+	 */
+	public GammaRates(int n, double a)
+	{
+		super(n);
+		alpha = a;
+		showSE = false;
+
+		makeGamma(alpha);
+	}
+	
+	// interface Report
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Model of rate heterogeneity: Discrete Gamma");
+		out.println("Number of rate categories: " + numRates);
+		out.print("Gamma distribution parameter alpha: ");
+		format.displayDecimal(out, alpha, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, alphaSE, 2);
+			out.println(")");
+		}
+		else
+		{
+			out.println();
+		}
+		out.println();
+		printRates(out);
+	}
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		alpha = param;
+		makeGamma(alpha);
+	}
+
+	public double getParameter(int n)
+	{
+		return alpha;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		alphaSE = paramSE;
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 100.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.5;
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private boolean showSE;
+	
+	// Shape parameter
+	private double alpha;
+	private double alphaSE;
+	
+	private void makeGamma(double a)
+	{
+		double mean = 0.0;
+		for (int i = 0; i < numRates; i++)
+		{
+			rate[i] = GammaDistribution.quantile((2.0*i+1.0)/(2.0*numRates), a, 1.0/a);
+			mean += rate[i];
+		}
+		mean = mean/(double) numRates;
+		for (int i = 0; i < numRates; i++)
+		{
+			rate[i] /= mean;
+			probability[i] = 1.0/(double) numRates;
+		}	
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/HKY.java b/LibrarySource/pal/substmodel/HKY.java
new file mode 100644
index 0000000..df91bc4
--- /dev/null
+++ b/LibrarySource/pal/substmodel/HKY.java
@@ -0,0 +1,140 @@
+// HKY.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Hasegawa-Kishino-Yano model of nucleotide evolution
+ *
+ * @version $Id: HKY.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class HKY extends NucleotideModel implements Serializable
+{
+	/**
+	 * Constructor 1
+	 *
+	 * @param kappa transition/transversion rate ratio
+	 * @param freq nucleotide frequencies
+	 */
+	public HKY(double kappa, double[] freq)
+	{
+		super(freq);
+		
+		this.kappa = kappa;
+		
+		makeHKY();
+		fromQToR();
+		
+		showSE = false;
+	}
+ 
+	/**
+	 * Constructor 2
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotide frequencies
+	 */
+	public HKY(double[] params, double[] freq)
+	{
+		this(params[0], freq);
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 2;
+	}
+
+  
+ 	// interface Report
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: HKY (Hasegawa et al. 1985)");
+		out.print("Transition/transversion rate ratio kappa: ");
+		format.displayDecimal(out, kappa, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, kappaSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		out.println();
+		printFrequencies(out);
+		printRatios(out);
+	}	
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		kappa = param;
+		
+		makeHKY();
+		fromQToR();
+	}
+
+	public double getParameter(int n)
+	{
+		return kappa;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		kappaSE = paramSE;
+	
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 100.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 4.0;
+	}
+
+
+	//
+	// Private stuff
+	// 
+
+	private boolean showSE;
+	private double kappa, kappaSE;
+
+	// Make HKY model
+	private void makeHKY()
+	{
+		// Q matrix
+		rate[0][1] = 1; rate[0][2] = kappa; rate[0][3] = 1;
+		rate[1][2] = 1; rate[1][3] = kappa;
+		rate[2][3] = 1;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/InvariableSites.java b/LibrarySource/pal/substmodel/InvariableSites.java
new file mode 100644
index 0000000..e69e1e8
--- /dev/null
+++ b/LibrarySource/pal/substmodel/InvariableSites.java
@@ -0,0 +1,126 @@
+// InvariableSites.java
+//
+// (c) 2000--2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.math.*;
+
+import java.io.*;
+
+
+/**
+ * invariable sites model (two-rate model with mean rate = 1.0)
+ *
+ * @version $Id: InvariableSites.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class InvariableSites extends RateDistribution implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * construct discrete rate distribution with two rates
+	 * (one invariable and one variable)
+	 *
+	 * @param f fraction of invariable sites
+	 */
+	public InvariableSites(double f)
+	{
+		super(2);
+		frac = f;
+		showSE = false;
+
+		makeDistrib(frac);
+	}
+	
+	// interface Report
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Model of rate heterogeneity: Invariable sites model");
+		out.println("Number of rate categories: " + numRates);
+		out.print("Fraction of invariable sites: ");
+		format.displayDecimal(out, frac, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, fracSE, 2);
+			out.println(")");
+		}
+		else
+		{
+			out.println();
+		}
+		out.println();
+		printRates(out);
+	}
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 1;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		frac = param;
+		makeDistrib(frac);
+	}
+
+	public double getParameter(int n)
+	{
+		return frac;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		fracSE = paramSE;
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 1.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.0;
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private boolean showSE;
+	
+	// fraction of invariable sites
+	private double frac;
+	private double fracSE;
+	
+	private void makeDistrib(double f)
+	{
+		rate[0] = 0.0;
+		rate[1] = 1.0/(1.0-f);  // ensures that mean rate = 1.0
+		
+		probability[0] = f;
+		probability[1] = 1.0-f;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/JTT.java b/LibrarySource/pal/substmodel/JTT.java
new file mode 100644
index 0000000..e6b16ed
--- /dev/null
+++ b/LibrarySource/pal/substmodel/JTT.java
@@ -0,0 +1,197 @@
+// JTT.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * JTT model of amino acid evolution
+ *
+ * @version $Id: JTT.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class JTT extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public JTT(double[] f)
+	{
+		super(f);
+		
+		makeJTT();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 1;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: JTT (Jones et al. 1992)");
+		out.println();
+		printFrequencies(out);
+	}	
+	
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0] = 0.077; f[1] = 0.051; f[2] = 0.043; f[3] = 0.052;
+		f[4] = 0.02; f[5] = 0.041; f[6] = 0.062; f[7] = 0.074;
+		f[8] = 0.023; f[9] = 0.052; f[10] = 0.091; f[11] = 0.059;
+		f[12] = 0.024; f[13] = 0.04; f[14] = 0.051; f[15] = 0.069;
+		f[16] = 0.059; f[17] = 0.014; f[18] = 0.032; f[19] = 0.066;
+	}
+	
+	//
+	// Private stuff
+	// 
+
+	// JTT model for amino acid evolution
+	// D.T. Jones, W.R. Taylor, and J.M. Thornton
+	// The rapid generation of mutation data matrices from protein sequences
+	// CABIOS  vol. 8 no. 3 1992 pp. 275-282
+	private void makeJTT()
+	{
+		// Q matrix
+		rate[0][1]=3.1628651460584e+00; 	rate[0][2]=3.2804935927860e+00;
+		rate[0][3]=4.8477237048666e+00; 	rate[0][4]=3.4612244897959e+00;
+		rate[0][5]=3.3130910900946e+00; 	rate[0][6]=6.3199473337722e+00;
+		rate[0][7]=1.0440154440154e+01; 	rate[0][8]=1.3061224489796e+00;
+		rate[0][9]=2.1726844583987e+00; 	rate[0][10]=1.8443597219107e+00;
+		rate[0][11]=2.2137668626773e+00; 	rate[0][12]=2.7210884353741e+00;
+		rate[0][13]=8.3265306122449e-01; 	rate[0][14]=1.1537414965986e+01;
+		rate[0][15]=2.2838213546288e+01; 	rate[0][16]=2.7007955724663e+01;
+		rate[0][17]=5.1311953352770e-01; 	rate[0][18]=8.3673469387755e-01;
+		rate[0][19]=1.7474335188621e+01; 
+	
+		rate[1][2]=2.6598918637222e+00; 	rate[1][3]=9.1014867485456e-01;
+		rate[1][4]=6.1624649859944e+00; 	rate[1][5]=1.8036482885837e+01;
+		rate[1][6]=1.8924731182796e+00; 	rate[1][7]=8.1810886516769e+00;
+		rate[1][8]=1.9119717452198e+01; 	rate[1][9]=1.4410687351864e+00;
+		rate[1][10]=2.2211961707760e+00; 	rate[1][11]=3.9239234676922e+01;
+		rate[1][12]=2.5060690943044e+00; 	rate[1][13]=3.9439775910364e-01;
+		rate[1][14]=4.1953094963476e+00; 	rate[1][15]=5.9016766126741e+00;
+		rate[1][16]=3.8437069743152e+00; 	rate[1][17]=7.6766706682673e+00;
+		rate[1][18]=1.4173669467787e+00; 	rate[1][19]=1.0308123249300e+00;
+
+		rate[2][3]=3.2226935854843e+01; 	rate[2][4]=1.8710963455150e+00;
+		rate[2][5]=4.5351268130622e+00; 	rate[2][6]=3.3951344979102e+00;
+		rate[2][7]=4.5987249708180e+00; 	rate[2][8]=2.3693774375271e+01;
+		rate[2][9]=2.9235880398671e+00; 	rate[2][10]=8.0960899565551e-01;
+		rate[2][11]=1.5024269384537e+01; 	rate[2][12]=1.9003322259136e+00;
+		rate[2][13]=4.3853820598007e-01; 	rate[2][14]=7.1083317047749e-01;
+		rate[2][15]=2.9456208772690e+01; 	rate[2][16]=1.3735908553410e+01;
+		rate[2][17]=1.6706217370669e-01; 	rate[2][18]=4.1661129568106e+00;
+		rate[2][19]=9.7452934662237e-01; 
+	
+		rate[3][4]=6.2857142857143e-01; 	rate[3][5]=3.0662020905923e+00;
+		rate[3][6]=4.5450549450549e+01; 	rate[3][7]=7.5402435402435e+00;
+		rate[3][8]=6.0544672718586e+00; 	rate[3][9]=6.8808114961961e-01;
+		rate[3][10]=3.6130902064968e-01; 	rate[3][11]=1.6718197057180e+00;
+		rate[3][12]=1.0879120879121e+00; 	rate[3][13]=1.9340659340659e-01;
+		rate[3][14]=7.3949579831933e-01; 	rate[3][15]=3.4196528109572e+00;
+		rate[3][16]=2.4749487800335e+00; 	rate[3][17]=3.4536891679749e-01;
+		rate[3][18]=2.6895604395604e+00; 	rate[3][19]=1.8608058608059e+00;
+
+		rate[4][5]=5.5191637630662e-01; 	rate[4][6]=3.2442396313364e-01;
+		rate[4][7]=3.3297297297297e+00; 	rate[4][8]=4.3726708074534e+00;
+		rate[4][9]=9.1868131868132e-01; 	rate[4][10]=9.9466248037677e-01;
+		rate[4][11]=2.9830508474576e-01; 	rate[4][12]=2.4095238095238e+00;
+		rate[4][13]=4.1485714285714e+00; 	rate[4][14]=7.3949579831933e-01;
+		rate[4][15]=1.2862939958592e+01; 	rate[4][16]=2.8125907990315e+00;
+		rate[4][17]=6.8244897959184e+00; 	rate[4][18]=1.2885714285714e+01;
+		rate[4][19]=3.7714285714286e+00; 
+	
+		rate[5][6]=2.0316061593796e+01; 	rate[5][7]=1.3922214897825e+00;
+		rate[5][8]=3.3861536130889e+01; 	rate[5][9]=4.7172339855267e-01;
+		rate[5][10]=4.2320327755868e+00; 	rate[5][11]=1.7835941652395e+01;
+		rate[5][12]=2.6573751451800e+00; 	rate[5][13]=2.7595818815331e-01;
+		rate[5][14]=9.4992143198743e+00; 	rate[5][15]=3.2350653941322e+00;
+		rate[5][16]=3.0973838067678e+00; 	rate[5][17]=1.0512692882031e+00;
+		rate[5][18]=1.5331010452962e+00; 	rate[5][19]=1.0778164924506e+00;
+
+		rate[6][7]=6.6857641051189e+00; 	rate[6][8]=1.4458024443999e+00;
+		rate[6][9]=6.7068415455512e-01; 	rate[6][10]=5.7932850559579e-01;
+		rate[6][11]=1.0365070686558e+01; 	rate[6][12]=1.0138248847926e+00;
+		rate[6][13]=2.6359447004608e-01; 	rate[6][14]=1.1291226167887e+00;
+		rate[6][15]=1.8337006611901e+00; 	rate[6][16]=1.9520424900414e+00;
+		rate[6][17]=6.9519420671494e-01; 	rate[6][18]=3.8018433179723e-01;
+		rate[6][19]=2.7772657450077e+00; 
+	
+		rate[7][8]=1.2113479939567e+00; 	rate[7][9]=3.2670032670033e-01;
+		rate[7][10]=4.1817641817642e-01; 	rate[7][11]=1.6354950592239e+00;
+		rate[7][12]=7.6447876447876e-01; 	rate[7][13]=3.0579150579151e-01;
+		rate[7][14]=1.2391551215081e+00; 	rate[7][15]=1.1138492529797e+01;
+		rate[7][16]=1.8888816176952e+00; 	rate[7][17]=3.3491450634308e+00;
+		rate[7][18]=3.1853281853282e-01; 	rate[7][19]=2.8416988416988e+00;
+
+		rate[8][9]=1.0931677018634e+00; 	rate[8][10]=3.2194389461470e+00;
+		rate[8][11]=3.1498052426571e+00; 	rate[8][12]=1.9130434782609e+00;
+		rate[8][13]=2.7329192546584e+00; 	rate[8][14]=6.7304834977469e+00;
+		rate[8][15]=4.3726708074534e+00; 	rate[8][16]=2.8162964522581e+00;
+		rate[8][17]=7.8083407275954e-01; 	rate[8][18]=3.5118012422360e+01;
+		rate[8][19]=7.2877846790890e-01; 
+	
+		rate[9][10]=1.4069798333535e+01; 	rate[9][11]=1.2292791953809e+00;
+		rate[9][12]=2.8366300366300e+01; 	rate[9][13]=4.7384615384615e+00;
+		rate[9][14]=5.8780435251023e-01; 	rate[9][15]=2.4105749323141e+00;
+		rate[9][16]=1.5243062022723e+01; 	rate[9][17]=8.2888540031397e-01;
+		rate[9][18]=1.8434065934066e+00; 	rate[9][19]=5.7699633699634e+01;
+
+		rate[10][11]=8.8039805231089e-01; 	rate[10][12]=2.2425954997384e+01;
+		rate[10][13]=1.5099529042386e+01; 	rate[10][14]=6.2626896912611e+00;
+		rate[10][15]=3.4917298022888e+00; 	rate[10][16]=1.6109411169944e+00;
+		rate[10][17]=3.2366001345593e+00; 	rate[10][18]=1.4505494505495e+00;
+		rate[10][19]=1.0557823129252e+01; 
+	
+		rate[11][12]=3.6577885391445e+00; 	rate[11][13]=1.4915254237288e-01;
+		rate[11][14]=1.2868062479229e+00; 	rate[11][15]=2.8162964522581e+00;
+		rate[11][16]=5.7494151926786e+00; 	rate[11][17]=5.4790729851263e-01;
+		rate[11][18]=5.3268765133172e-01; 	rate[11][19]=7.4899112187248e-01;
+
+		rate[12][13]=2.5666666666667e+00; 	rate[12][14]=9.4491129785247e-01;
+		rate[12][15]=1.6397515527950e+00; 	rate[12][16]=1.2180790960452e+01;
+		rate[12][17]=1.1972789115646e+00; 	rate[12][18]=1.1130952380952e+00;
+		rate[12][19]=1.7746031746032e+01; 
+	
+		rate[13][14]=8.8739495798319e-01; 	rate[13][15]=5.6298136645963e+00;
+		rate[13][16]=8.3099273607748e-01; 	rate[13][17]=3.3224489795918e+00;
+		rate[13][18]=3.3392857142857e+01; 	rate[13][19]=3.6000000000000e+00;
+
+		rate[14][15]=1.6261762676085e+01; 	rate[14][16]=6.8852490148602e+00;
+		rate[14][17]=4.2256902761104e-01; 	rate[14][18]=6.7787114845938e-01;
+		rate[14][19]=1.2549019607843e+00; 
+	
+		rate[15][16]=2.7891216619293e+01; 	rate[15][17]=1.8740017746229e+00;
+		rate[15][18]=3.7349896480331e+00; 	rate[15][19]=2.4182194616977e+00;
+
+		rate[16][17]=4.8702870978900e-01; 	rate[16][18]=1.1985472154964e+00;
+		rate[16][19]=6.7925746569814e+00; 
+	
+		rate[17][18]=4.6020408163265e+00; 	rate[17][19]=1.4693877551020e+00;
+
+		rate[18][19]=1.0000000000000e+00; 
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/MTREV24.java b/LibrarySource/pal/substmodel/MTREV24.java
new file mode 100644
index 0000000..70460d5
--- /dev/null
+++ b/LibrarySource/pal/substmodel/MTREV24.java
@@ -0,0 +1,196 @@
+// MTREV24.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * MTREV24 model of amino acid evolution
+ *
+ * @version $Id: MTREV24.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class MTREV24 extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public MTREV24(double[] f)
+	{
+		super(f);
+		
+		makeMTREV24();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 2;
+	}
+  
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: MTREV24 (Adachi-Hasegawa 1996)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0]=0.072; f[1]=0.019; f[2]=0.039; f[3]=0.019; f[4]=0.006;
+		f[5]=0.025; f[6]=0.024; f[7]=0.056; f[8]=0.028; f[9]=0.088;
+		f[10]=0.168; f[11]=0.023; f[12]=0.054; f[13]=0.061; f[14]=0.054;
+		f[15]=0.072; f[16]=0.086; f[17]=0.029; f[18]=0.033; f[19]=0.043;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// MTREV24 model of amino acid evolution
+	// (complete sequence data of mtDNA from 24 vertebrate species)
+	// Adachi, J., and Hasegawa, M. 1996. J. Mol. Evol. 42:459-468.
+	public void makeMTREV24()
+	{
+		// Q matrix
+		rate[0][1]=1.2199217606346e+01; 	rate[0][2]=1.4182139942122e+01;
+		rate[0][3]=9.2985091873208e+00; 	rate[0][4]=3.1542792981957e+01;
+		rate[0][5]=1.0025852846688e+00; 	rate[0][6]=5.1418866803338e+00;
+		rate[0][7]=6.3531246495131e+01; 	rate[0][8]=7.3137132861715e+00;
+		rate[0][9]=5.0782382656186e+01; 	rate[0][10]=1.3399741808481e+01;
+		rate[0][11]=4.4021672780560e+00; 	rate[0][12]=7.4673480520104e+01;
+		rate[0][13]=3.3513021631978e+00; 	rate[0][14]=2.8582502221773e+01;
+		rate[0][15]=2.0413623195312e+02; 	rate[0][16]=2.5301305153906e+02;
+		rate[0][17]=1.0000000000000e+00; 	rate[0][18]=3.4084158197615e+00;
+		rate[0][19]=1.0266468401249e+02; 
+	
+		rate[1][2]=6.9661274444534e+00; 	rate[1][3]=1.0000000000000e+00;
+		rate[1][4]=5.4384584796568e+01; 	rate[1][5]=1.1631134513343e+02;
+		rate[1][6]=1.0000000000000e+00; 	rate[1][7]=1.2122831341194e+01;
+		rate[1][8]=8.6961067087353e+01; 	rate[1][9]=1.0000000000000e+00;
+		rate[1][10]=8.1976829394538e+00; 	rate[1][11]=7.4423215395318e+01;
+		rate[1][12]=1.0000000000000e+00; 	rate[1][13]=2.4659158338099e+00;
+		rate[1][14]=1.2439947713615e+01; 	rate[1][15]=3.1791814866372e+00;
+		rate[1][16]=1.0935327216119e+00; 	rate[1][17]=1.1550775790126e+01;
+		rate[1][18]=1.0000000000000e+00; 	rate[1][19]=4.0211417480338e+00;
+
+		rate[2][3]=4.1809325468160e+02; 	rate[2][4]=3.1020979842967e+01;
+		rate[2][5]=9.1349622725361e+01; 	rate[2][6]=3.3185663516310e+01;
+		rate[2][7]=2.8052324651124e+01; 	rate[2][8]=2.6112087577885e+02;
+		rate[2][9]=1.4261453863336e+01; 	rate[2][10]=7.9775653461977e+00;
+		rate[2][11]=3.2036829276162e+02; 	rate[2][12]=3.4424354918739e+01;
+		rate[2][13]=7.9996445145608e+00; 	rate[2][14]=3.8586541461044e+01;
+		rate[2][15]=2.6020426225852e+02; 	rate[2][16]=1.2550758780474e+02;
+		rate[2][17]=5.6207759736659e+00; 	rate[2][18]=1.0071406219571e+02;
+		rate[2][19]=1.0000000000000e+00; 
+	
+		rate[3][4]=1.0000000000000e+00; 	rate[3][5]=2.9097352675564e+01;
+		rate[3][6]=3.0713149855302e+02; 	rate[3][7]=2.9877072751897e+01;
+		rate[3][8]=5.9995408885817e+01; 	rate[3][9]=2.2827096245105e+00;
+		rate[3][10]=1.0000000000000e+00; 	rate[3][11]=1.2183938185384e+00;
+		rate[3][12]=1.0000000000000e+00; 	rate[3][13]=2.6221929413096e+00;
+		rate[3][14]=7.0708004204733e+00; 	rate[3][15]=3.6327934317139e+01;
+		rate[3][16]=1.4743408713748e+01; 	rate[3][17]=1.0453246057102e+01;
+		rate[3][18]=1.1165627147496e+01; 	rate[3][19]=1.0000000000000e+00;
+
+		rate[4][5]=3.9599394038972e+01; 	rate[4][6]=1.0000000000000e+00;
+		rate[4][7]=1.6163581056674e+01; 	rate[4][8]=7.4467985406234e+01;
+		rate[4][9]=3.3018175376623e+01; 	rate[4][10]=1.3500725995091e+01;
+		rate[4][11]=1.0000000000000e+00; 	rate[4][12]=3.2504095376923e+00;
+		rate[4][13]=3.7264767083096e+01; 	rate[4][14]=1.6454136037822e+01;
+		rate[4][15]=1.4581783243113e+02; 	rate[4][16]=9.4720031458442e+01;
+		rate[4][17]=1.7684087896962e+01; 	rate[4][18]=1.3409157685926e+02;
+		rate[4][19]=1.0000000000000e+00; 
+	
+		rate[5][6]=1.6503249008836e+02; 	rate[5][7]=3.5530760735494e+00;
+		rate[5][8]=3.0652523140859e+02; 	rate[5][9]=4.3905393139325e+00;
+		rate[5][10]=2.0895470525345e+01; 	rate[5][11]=2.4504076430724e+02;
+		rate[5][12]=2.4931300477797e+01; 	rate[5][13]=1.0059428264289e+01;
+		rate[5][14]=7.2256314165467e+01; 	rate[5][15]=2.8480937892158e+01;
+		rate[5][16]=4.9962974409828e+01; 	rate[5][17]=1.0000000000000e+00;
+		rate[5][18]=2.0430790980529e+01; 	rate[5][19]=9.9986289000676e+00;
+
+		rate[6][7]=1.4884496769963e+01; 	rate[6][8]=2.5853576435567e+01;
+		rate[6][9]=1.7418201388328e+00; 	rate[6][10]=1.0000000000000e+00;
+		rate[6][11]=1.6519126809071e+02; 	rate[6][12]=1.0000000000000e+00;
+		rate[6][13]=1.4067850525292e+00; 	rate[6][14]=6.7547121641947e+00;
+		rate[6][15]=2.8794794140840e+01; 	rate[6][16]=7.8001372062558e+00;
+		rate[6][17]=1.0000000000000e+00; 	rate[6][18]=6.9067239183061e+00;
+		rate[6][19]=1.1127702362585e+01; 
+	
+		rate[7][8]=1.0000000000000e+00; 	rate[7][9]=3.1466649021550e+00;
+		rate[7][10]=1.2699794194865e+00; 	rate[7][11]=1.1962111069278e+01;
+		rate[7][12]=1.0000000000000e+00; 	rate[7][13]=1.0000000000000e+00;
+		rate[7][14]=1.0000000000000e+00; 	rate[7][15]=6.6277950574411e+01;
+		rate[7][16]=5.8800079133028e+00; 	rate[7][17]=5.7494182626674e+00;
+		rate[7][18]=1.6887657206208e+00; 	rate[7][19]=1.3320553471351e+00;
+
+		rate[8][9]=6.4536986087271e+00; 	rate[8][10]=6.0472584534958e+00;
+		rate[8][11]=6.7197196398961e+01; 	rate[8][12]=6.2977633277779e+00;
+		rate[8][13]=2.5347805183364e+01; 	rate[8][14]=3.2089868698728e+01;
+		rate[8][15]=4.0766987134407e+01; 	rate[8][16]=2.3570850628539e+01;
+		rate[8][17]=3.7286635325194e+00; 	rate[8][18]=3.5270764890474e+02;
+		rate[8][19]=1.0000000000000e+00; 
+	
+		rate[9][10]=1.7320653206333e+02; 	rate[9][11]=1.0298655619743e+01;
+		rate[9][12]=2.7262244199514e+02; 	rate[9][13]=4.4561065036310e+01;
+		rate[9][14]=1.0856482766156e+01; 	rate[9][15]=2.5107659603898e+01;
+		rate[9][16]=1.9391167162525e+02; 	rate[9][17]=1.0000000000000e+00;
+		rate[9][18]=1.3161329199391e+01; 	rate[9][19]=6.4365086389428e+02;
+
+		rate[10][11]=7.8314019154706e+00; 	rate[10][12]=2.8290920517725e+02;
+		rate[10][13]=1.1371735519833e+02; 	rate[10][14]=2.1105885757279e+01;
+		rate[10][15]=3.8741359395934e+01; 	rate[10][16]=6.6524559321657e+01;
+		rate[10][17]=1.7071378554833e+01; 	rate[10][18]=2.3234516108847e+01;
+		rate[10][19]=4.8247261078055e+01; 
+	
+		rate[11][12]=4.8092094826036e+01; 	rate[11][13]=3.3887559483420e+00;
+		rate[11][14]=2.6368577564199e+01; 	rate[11][15]=5.5679895711418e+01;
+		rate[11][16]=7.1750284708933e+01; 	rate[11][17]=1.2631893872825e+01;
+		rate[11][18]=2.6932728996777e+01; 	rate[11][19]=1.0000000000000e+00;
+
+		rate[12][13]=4.7798798034572e+01; 	rate[12][14]=9.9165053447429e+00;
+		rate[12][15]=5.8505442466161e+01; 	rate[12][16]=2.7798190504760e+02;
+		rate[12][17]=1.1427000119701e+01; 	rate[12][18]=2.1029990530586e+01;
+		rate[12][19]=2.0397078683768e+02; 
+	
+		rate[13][14]=9.1089574817139e+00; 	rate[13][15]=3.3835737720574e+01;
+		rate[13][16]=1.7815549567056e+01; 	rate[13][17]=4.1272404968214e+00;
+		rate[13][18]=2.4504156395152e+02; 	rate[13][19]=3.3435675442163e+00;
+
+		rate[14][15]=8.9421193040709e+01; 	rate[14][16]=6.7485067008375e+01;
+		rate[14][17]=2.2161693733113e+00; 	rate[14][18]=8.5338209390745e+00;
+		rate[14][19]=4.3342126659660e+00; 
+	
+		rate[15][16]=3.1432036618746e+02; 	rate[15][17]=2.0305343047059e+01;
+		rate[15][18]=3.4167877957799e+01; 	rate[15][19]=1.0000000000000e+00;
+
+		rate[16][17]=5.2559565123081e+00; 	rate[16][18]=2.0382362288681e+01;
+		rate[16][19]=1.0765527137500e+02; 
+	
+		rate[17][18]=1.3814733274637e+01; 	rate[17][19]=2.8259139240676e+00;
+
+		rate[18][19]=1.0000000000000e+00;
+	}
+
+}
+
diff --git a/LibrarySource/pal/substmodel/MatrixExponential.java b/LibrarySource/pal/substmodel/MatrixExponential.java
new file mode 100644
index 0000000..644b763
--- /dev/null
+++ b/LibrarySource/pal/substmodel/MatrixExponential.java
@@ -0,0 +1,894 @@
+// MatrixExponential.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import pal.math.*;
+
+
+/**
+ * compute matrix exponential and, subsequently, transition probabilities
+ * for a given rate matrix
+ *
+ * @version $Id: MatrixExponential.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class MatrixExponential implements TransitionProbability, Cloneable, java.io.Serializable
+{
+	//
+	// Public stuff
+	//
+
+	// Constraints and conventions:
+	// - first argument: row
+	// - second argument: column
+	// - transition: from row to column
+	// - sum of every row = 1
+	// - sum of frequencies = 1
+	// - frequencies * rate matrix = 1 (stationarity)
+
+	/** dimension of rate matrix */
+	public int dimension;
+
+	/** transition probability matrix */
+	public double[][] transProb;
+
+	/**
+	 * create module
+	 *
+	 * @param r rate matrix
+	 */
+	public MatrixExponential(RateMatrix r)
+	{
+		dimension = r.getDimension();
+		transProb = new double[dimension][dimension];
+		Eval = new double[dimension];
+		Evec = new double[dimension][dimension];
+		Ievc = new double[dimension][dimension];
+		iexp = new double[dimension][dimension];
+		amat = new double[dimension][dimension];
+		
+		ordr = new int[dimension];
+		evali = new double[dimension];
+
+		setMatrix(r);
+	}
+	
+	public double getTransitionProbability(int row, int column) {
+		return transProb[row][column];
+	}
+
+	public int getDimension() {
+   	return dimension;
+	}
+
+	/**
+	 * update rate matrix used in present module
+	 *
+	 * @param r rate matrix
+	 */
+	public void setMatrix(RateMatrix r)
+	{
+		/* compute eigenvalues and eigenvectors */
+		double[][] rate = r.getRelativeRates();
+		for (int i = 0; i < dimension; i++)
+		{
+			for (int j = 0; j < dimension; j++)
+			{
+				amat[i][j] = rate[i][j];
+			}
+		}
+		
+		elmhes(amat, ordr, dimension);
+		eltran(amat, Evec, ordr, dimension);
+		hqr2(dimension, 1, dimension, amat, Evec, Eval, evali);
+		luinverse(Evec, Ievc, dimension);
+	}
+	/**
+	 * compute transition probabilities for a expected distance
+	 * using the prespecified rate matrix
+	 *
+	 * @param arc expected distance
+	 */
+	public void setTime(double start, double end) {
+   	setDistance(end-start);
+	}
+	/**
+	 * compute transition probabilities for a expected distance
+	 * using the prespecified rate matrix
+	 *
+	 * @param arc expected distance
+	 */
+	public void setDistance(double arc)
+	{
+		int i, j, k;
+		double temp;
+
+		for (k = 0; k < dimension; k++)
+		{
+			temp = Math.exp(arc * Eval[k]);
+			for (j = 0; j < dimension; j++)
+			{
+				iexp[k][j] = Ievc[k][j] * temp;
+			}
+		}
+		for (i = 0; i < dimension; i++)
+		{
+			for (j = 0; j < dimension; j++)
+			{
+				temp = 0.0;
+				for (k = 0; k < dimension; k++)
+				{
+					temp += Evec[i][k] * iexp[k][j];
+				}
+				transProb[i][j] = Math.abs(temp);
+			}
+		}	
+	}
+
+	//
+	// Private stuff
+	//
+	
+	// Eigenvalues, eigenvectors, and inverse eigenvectors
+	private double[] Eval;
+	private double[][] Evec;
+	private double[][] Ievc;
+	private double[][] iexp;
+	private int[] ordr;
+	private double[] evali;
+	private double amat[][];
+
+	
+	private void elmhes(double[][] a, int[] ordr, int n)
+	{
+		int m, j, i;
+		double y, x;
+
+		for (i = 0; i < n; i++)
+		{
+			ordr[i] = 0;
+		}
+		for (m = 2; m < n; m++)
+		{
+			x = 0.0;
+			i = m;
+			for (j = m; j <= n; j++)
+			{
+				if (Math.abs(a[j - 1][m - 2]) > Math.abs(x))
+				{
+					x = a[j - 1][m - 2];
+					i = j;
+				}
+			}
+			ordr[m - 1] = i;
+			if (i != m)
+			{
+				for (j = m - 2; j < n; j++)
+				{
+					y = a[i - 1][j];
+					a[i - 1][j] = a[m - 1][j];
+					a[m - 1][j] = y;
+				}
+				for (j = 0; j < n; j++)
+				{
+					y = a[j][i - 1];
+					a[j][i - 1] = a[j][m - 1];
+					a[j][m - 1] = y;
+				}
+			}
+			if (x != 0.0)
+			{
+				for (i = m; i < n; i++)
+				{
+					y = a[i][m - 2];
+					if (y != 0.0)
+					{
+						y /= x;
+						a[i][m - 2] = y;
+						for (j = m - 1; j < n; j++)
+						{
+							a[i][j] -= y * a[m - 1][j];
+						}
+						for (j = 0; j < n; j++)
+						{
+							a[j][m - 1] += y * a[j][i];
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// Helper variables for mcdiv
+	private double cr, ci;
+
+	private void mcdiv(double ar, double ai, double br, double bi)
+	{
+		double s, ars, ais, brs, bis;
+
+		s = Math.abs(br) + Math.abs(bi);
+		ars = ar/s;
+		ais = ai/s;
+		brs = br/s;
+		bis = bi/s;
+		s = brs * brs + bis * bis;
+		cr = (ars * brs + ais * bis)/s;
+		ci = (ais * brs - ars * bis)/s;
+	}
+
+	void hqr2(int n, int low, int hgh, double[][] h, double[][] zz,
+		double[] wr, double[] wi) throws ArithmeticException
+	{
+		int i, j, k, l=0, m, en, na, itn, its;
+		double p=0, q=0, r=0, s=0, t, w, x=0, y, ra, sa, vi, vr, z=0, norm, tst1, tst2;
+		boolean notLast;
+	
+	
+		norm = 0.0;
+		k = 1;
+		/* store isolated roots and compute matrix norm */
+		for (i = 0; i < n; i++)
+		{
+			for (j = k - 1; j < n; j++)
+			{
+				norm += Math.abs(h[i][j]);
+			}
+			k = i + 1;
+			if (i + 1 < low || i + 1 > hgh)
+			{
+				wr[i] = h[i][i];
+				wi[i] = 0.0;
+			}
+		}
+		en = hgh;
+		t = 0.0;
+		itn = n * 30;
+		while (en >= low)
+		{	/* search for next eigenvalues */
+			its = 0;
+			na = en - 1;
+			while (en >= 1)
+			{
+				/* look for single small sub-diagonal element */
+				boolean fullLoop = true;
+				for (l = en; l > low; l--)
+				{
+					s = Math.abs(h[l - 2][l - 2]) + Math.abs(h[l - 1][l - 1]);
+					if (s == 0.0)
+					{
+						s = norm;
+					}
+					tst1 = s;
+					tst2 = tst1 + Math.abs(h[l - 1][l - 2]);
+					if (tst2 == tst1)
+					{
+						fullLoop = false;
+						break;
+					}
+				}
+				if (fullLoop)
+				{
+					l = low;
+				}
+				
+				x = h[en - 1][en - 1];	/* form shift */
+				if (l == en || l == na)
+				{
+					break;
+				}
+				if (itn == 0)
+				{
+					/* eigenvalues have not converged */
+					System.out.println("Eigenvalues not converged");
+					throw new ArithmeticException();
+				}
+				y = h[na - 1][na - 1];
+				w = h[en - 1][na - 1] * h[na - 1][en - 1];
+				/* form exceptional shift */
+				if (its == 10 || its == 20)
+				{
+					t += x;
+					for (i = low - 1; i < en; i++)
+					{
+						h[i][i] -= x;
+					}
+					s = Math.abs(h[en - 1][na - 1]) + Math.abs(h[na - 1][en - 3]);
+					x = 0.75 * s;
+					y = x;
+					w = -0.4375 * s * s;
+				}
+				its++;
+				itn--;
+				/* look for two consecutive small sub-diagonal elements */
+				for (m = en - 2; m >= l; m--)
+				{
+					z = h[m - 1][m - 1];
+					r = x - z;
+					s = y - z;
+					p = (r * s - w) / h[m][m - 1] + h[m - 1][m];
+					q = h[m][m] - z - r - s;
+					r = h[m + 1][m];
+					s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+					p /= s;
+					q /= s;
+					r /= s;
+					if (m == l)
+					{
+						break;
+					}
+					tst1 = Math.abs(p) * (Math.abs(h[m - 2][m - 2]) + Math.abs(z) + Math.abs(h[m][m]));
+					tst2 = tst1 + Math.abs(h[m - 1][m - 2]) * (Math.abs(q) + Math.abs(r));
+					if (tst2 == tst1)
+					{
+						break;
+					}
+				}
+				for (i = m + 2; i <= en; i++)
+				{
+					h[i - 1][i - 3] = 0.0;
+					if (i != m + 2)
+					{
+						h[i - 1][i - 4] = 0.0;
+					}
+				}
+				for (k = m; k <= na; k++)
+				{
+					if (k == na)
+					{
+						notLast = false;
+					}
+					else
+					{
+						notLast = true;
+					}			
+					if (k != m)
+					{
+						p = h[k - 1][k - 2];
+						q = h[k][k - 2];
+						r = 0.0;
+						if (notLast)
+						{
+							r = h[k + 1][k - 2];
+						}
+						x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+						if (x != 0.0)
+						{
+							p /= x;
+							q /= x;
+							r /= x;
+						}
+					}
+					if (x != 0.0)
+					{
+						if (p < 0.0)
+						{	/* sign */
+							s = - Math.sqrt(p * p + q * q + r * r);
+						}
+						else
+						{
+							s = Math.sqrt(p * p + q * q + r * r);
+						}
+						if (k != m)
+						{
+							h[k - 1][k - 2] = -s * x;
+						}
+						else if (l != m)
+						{
+							h[k - 1][k - 2] = -h[k - 1][k - 2];
+						}
+						p += s;
+						x = p / s;
+						y = q / s;
+						z = r / s;
+						q /= p;
+						r /= p;
+						if (!notLast)
+						{
+							for (j = k - 1; j < n; j++)
+							{	/* row modification */
+								p = h[k - 1][j] + q * h[k][j];
+								h[k - 1][j] -= p * x;
+								h[k][j] -= p * y;
+							}
+							j = (en < (k + 3)) ? en : (k + 3); /* min */
+							for (i = 0; i < j; i++)
+							{	/* column modification */
+								p = x * h[i][k - 1] + y * h[i][k];
+								h[i][k - 1] -= p;
+								h[i][k] -= p * q;
+							}
+							/* accumulate transformations */
+							for (i = low - 1; i < hgh; i++)
+							{
+								p = x * zz[i][k - 1] + y * zz[i][k];
+								zz[i][k - 1] -= p;
+								zz[i][k] -= p * q;
+							}
+						}
+						else
+						{
+							for (j = k - 1; j < n; j++)
+							{	/* row modification */
+								p = h[k - 1][j] + q * h[k][j] + r * h[k + 1][j];
+								h[k - 1][j] -= p * x;
+								h[k][j] -= p * y;
+								h[k + 1][j] -= p * z;
+							}
+							j = (en < (k + 3)) ? en : (k + 3); /* min */
+							for (i = 0; i < j; i++)
+							{	/* column modification */
+								p = x * h[i][k - 1] + y * h[i][k] + z * h[i][k + 1];
+								h[i][k - 1] -= p;
+								h[i][k] -= p * q;
+								h[i][k + 1] -= p * r;
+							}
+							/* accumulate transformations */
+							for (i = low - 1; i < hgh; i++)
+							{
+								p = x * zz[i][k - 1] + y * zz[i][k] +
+									z * zz[i][k + 1];
+								zz[i][k - 1] -= p;
+								zz[i][k] -= p * q;
+								zz[i][k + 1] -= p * r;
+							}
+						}
+					}
+				}	       /* for k */
+			}		       /* while infinite loop */
+			if (l == en)
+			{	       /* one root found */
+				h[en - 1][en - 1] = x + t;
+				wr[en - 1] = h[en - 1][en - 1];
+				wi[en - 1] = 0.0;
+				en = na;
+				continue;
+			}
+			y = h[na - 1][na - 1];
+			w = h[en - 1][na - 1] * h[na - 1][en - 1];
+			p = (y - x) / 2.0;
+			q = p * p + w;
+			z = Math.sqrt(Math.abs(q));
+			h[en - 1][en - 1] = x + t;
+			x = h[en - 1][en - 1];
+			h[na - 1][na - 1] = y + t;
+			if (q >= 0.0)
+			{	 /* real pair */
+				if (p < 0.0)
+				{	/* sign */
+					z = p - Math.abs(z);
+				}
+				else
+				{
+					z = p + Math.abs(z);
+				}
+				wr[na - 1] = x + z;
+				wr[en - 1] = wr[na - 1];
+				if (z != 0.0)
+				{
+					wr[en - 1] = x - w / z;
+				}
+				wi[na - 1] = 0.0;
+				wi[en - 1] = 0.0;
+				x = h[en - 1][na - 1];
+				s = Math.abs(x) + Math.abs(z);
+				p = x / s;
+				q = z / s;
+				r = Math.sqrt(p * p + q * q);
+				p /= r;
+				q /= r;
+				for (j = na - 1; j < n; j++)
+				{	/* row modification */
+					z = h[na - 1][j];
+					h[na - 1][j] = q * z + p * h[en - 1][j];
+					h[en - 1][j] = q * h[en - 1][j] - p * z;
+				}
+				for (i = 0; i < en; i++)
+				{	/* column modification */
+					z = h[i][na - 1];
+					h[i][na - 1] = q * z + p * h[i][en - 1];
+					h[i][en - 1] = q * h[i][en - 1] - p * z;
+				}
+				/* accumulate transformations */
+				for (i = low - 1; i < hgh; i++)
+				{
+					z = zz[i][na - 1];
+					zz[i][na - 1] = q * z + p * zz[i][en - 1];
+					zz[i][en - 1] = q * zz[i][en - 1] - p * z;
+				}
+			}
+			else
+			{	/* complex pair */
+				wr[na - 1] = x + p;
+				wr[en - 1] = x + p;
+				wi[na - 1] = z;
+				wi[en - 1] = -z;
+			}
+			en -= 2;
+		} /* while en >= low */
+		/* backsubstitute to find vectors of upper triangular form */
+		if (norm != 0.0)
+		{
+			for (en = n; en >= 1; en--)
+			{
+				p = wr[en - 1];
+				q = wi[en - 1];
+				na = en - 1;
+				if (q == 0.0)
+				{/* real vector */
+					m = en;
+					h[en - 1][en - 1] = 1.0;
+					if (na != 0)
+					{
+						for (i = en - 2; i >= 0; i--)
+						{
+							w = h[i][i] - p;
+							r = 0.0;
+							for (j = m - 1; j < en; j++)
+							{
+								r += h[i][j] * h[j][en - 1];
+							}
+							if (wi[i] < 0.0)
+							{
+								z = w;
+								s = r;
+							}
+							else
+							{
+								m = i + 1;
+								if (wi[i] == 0.0)
+								{
+									t = w;
+									if (t == 0.0)
+									{
+										tst1 = norm;
+										t = tst1;
+										do
+										{
+											t = 0.01 * t;
+											tst2 = norm + t;
+										}
+										while (tst2 > tst1);
+									}
+									h[i][en - 1] = -(r / t);
+								}
+								else
+								{	/* solve real equations */
+									x = h[i][i + 1];
+									y = h[i + 1][i];
+									q = (wr[i] - p) * (wr[i] - p) + wi[i] * wi[i];
+									t = (x * s - z * r) / q;
+									h[i][en - 1] = t;
+									if (Math.abs(x) > Math.abs(z))
+										h[i + 1][en - 1] = (-r - w * t) / x;
+									else
+										h[i + 1][en - 1] = (-s - y * t) / z;
+								}
+								/* overflow control */
+								t = Math.abs(h[i][en - 1]);
+								if (t != 0.0)
+								{
+									tst1 = t;
+									tst2 = tst1 + 1.0 / tst1;
+									if (tst2 <= tst1)
+									{
+										for (j = i; j < en; j++)
+										{
+											h[j][en - 1] /= t;
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				else if (q > 0.0)
+				{
+					m = na;
+					if (Math.abs(h[en - 1][na - 1]) > Math.abs(h[na - 1][en - 1]))
+					{
+						h[na - 1][na - 1] = q / h[en - 1][na - 1];
+						h[na - 1][en - 1] = (p - h[en - 1][en - 1])/h[en - 1][na - 1];
+					}
+					else
+					{
+						mcdiv(0.0, -h[na - 1][en - 1], h[na - 1][na - 1] - p, q);
+						h[na - 1][na - 1] = cr;
+						h[na - 1][en - 1] = ci;
+					}
+					h[en - 1][na - 1] = 0.0;
+					h[en - 1][en - 1] = 1.0;
+					if (en != 2)
+					{
+						for (i = en - 3; i >= 0; i--)
+						{
+							w = h[i][i] - p;
+							ra = 0.0;
+							sa = 0.0;
+							for (j = m - 1; j < en; j++)
+							{
+								ra += h[i][j] * h[j][na - 1];
+								sa += h[i][j] * h[j][en - 1];
+							}
+							if (wi[i] < 0.0)
+							{
+								z = w;
+								r = ra;
+								s = sa;
+							}
+							else
+							{
+								m = i + 1;
+								if (wi[i] == 0.0)
+								{
+									mcdiv(-ra, -sa, w, q);
+									h[i][na - 1] = cr;
+									h[i][en - 1] = ci;
+								}
+								else
+								{	/* solve complex equations */
+									x = h[i][i + 1];
+									y = h[i + 1][i];
+									vr = (wr[i] - p) * (wr[i] - p);
+									vr = vr + wi[i] * wi[i] - q * q;	
+									vi = (wr[i] - p) * 2.0 * q;
+									if (vr == 0.0 && vi == 0.0)
+									{
+										tst1 = norm * (Math.abs(w) + Math.abs(q) + Math.abs(x) +
+													   Math.abs(y) + Math.abs(z));
+										vr = tst1;
+										do
+										{
+											vr = 0.01 * vr;
+											tst2 = tst1 + vr;
+										}
+										while (tst2 > tst1);
+									}
+									mcdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
+									h[i][na - 1] = cr;
+									h[i][en - 1] = ci;
+									if (Math.abs(x) > Math.abs(z) + Math.abs(q))
+									{
+										h[i + 1]
+											[na - 1] = (q * h[i][en - 1] -
+														w * h[i][na - 1] - ra) / x;
+										h[i + 1][en - 1] = (-sa - w * h[i][en - 1] -
+															q * h[i][na - 1]) / x;
+									}
+									else
+									{
+										mcdiv(-r - y * h[i][na - 1], -s - y * h[i][en - 1], z, q);
+										h[i + 1][na - 1] = cr;
+										h[i + 1][en - 1] = ci;
+									}
+								}
+								/* overflow control */
+								t = (Math.abs(h[i][na - 1]) > Math.abs(h[i][en - 1])) ?
+									 Math.abs(h[i][na - 1]) : Math.abs(h[i][en - 1]);
+								if (t != 0.0)
+								{
+									tst1 = t;
+									tst2 = tst1 + 1.0 / tst1;
+									if (tst2 <= tst1)
+									{
+										for (j = i; j < en; j++)
+										{
+											h[j][na - 1] /= t;
+											h[j][en - 1] /= t;
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			/* end back substitution. vectors of isolated roots */
+			for (i = 0; i < n; i++)
+			{
+				if (i + 1 < low || i + 1 > hgh)
+				{
+					for (j = i; j < n; j++)
+					{
+						zz[i][j] = h[i][j];
+					}
+				}
+			}
+			/* multiply by transformation matrix to give vectors of
+			 * original full matrix. */
+			for (j = n - 1; j >= low - 1; j--)
+			{
+				m = ((j + 1) < hgh) ? (j + 1) : hgh; /* min */
+				for (i = low - 1; i < hgh; i++)
+				{
+					z = 0.0;
+					for (k = low - 1; k < m; k++)
+					{
+						z += zz[i][k] * h[k][j];
+					}
+					zz[i][j] = z;
+				}
+			}
+		}
+	}
+	
+	private void eltran(double[][] a, double[][] zz, int[] ordr, int n)
+	{
+		int i, j, m;
+
+		for (i = 0; i < n; i++)
+		{
+			for (j = i + 1; j < n; j++)
+			{
+				zz[i][j] = 0.0;
+				zz[j][i] = 0.0;
+			}
+			zz[i][i] = 1.0;
+		}
+		if (n <= 2)
+		{
+			return;
+		}
+		for (m = n - 1; m >= 2; m--)
+		{
+			for (i = m; i < n; i++)
+			{
+				zz[i][m - 1] = a[i][m - 2];
+			}
+			i = ordr[m - 1];
+			if (i != m)
+			{
+				for (j = m - 1; j < n; j++)
+				{
+					zz[m - 1][j] = zz[i - 1][j];
+					zz[i - 1][j] = 0.0;
+				}
+				zz[i - 1][m - 1] = 1.0;
+			}
+		}
+	}
+
+	void luinverse(double[][] inmat, double[][] imtrx, int size) throws IllegalArgumentException
+	{
+		int i, j, k, l, maxi=0, idx, ix, jx;
+		double sum, tmp, maxb, aw;
+		int[] index;
+		double[] wk;
+		double[][] omtrx;
+	
+		
+		index = new int[size];
+		omtrx = new double[size][size];
+		
+		/* copy inmat to omtrx */
+		for (i = 0; i < size; i++)
+		{
+			for (j = 0; j < size; j++)
+			{
+				omtrx[i][j] = inmat[i][j];
+			}
+		}
+		
+		wk = new double[size];
+		aw = 1.0;
+		for (i = 0; i < size; i++)
+		{
+			maxb = 0.0;
+			for (j = 0; j < size; j++)
+			{
+				if (Math.abs(omtrx[i][j]) > maxb)
+				{
+					maxb = Math.abs(omtrx[i][j]);
+				}
+			}
+			if (maxb == 0.0)
+			{
+				/* Singular matrix */
+				System.out.println("Singular matrix encountered");
+				throw new IllegalArgumentException("Singular matrix");
+			}
+			wk[i] = 1.0/maxb;
+		}
+		for (j = 0; j < size; j++)
+		{
+			for (i = 0; i < j; i++)
+			{
+				sum = omtrx[i][j];
+				for (k = 0; k < i; k++)
+				{
+					sum -= omtrx[i][k] * omtrx[k][j];
+				}
+				omtrx[i][j] = sum;
+			}
+			maxb = 0.0;
+			for (i = j; i < size; i++)
+			{
+				sum = omtrx[i][j];
+				for (k = 0; k < j; k++)
+				{
+					sum -= omtrx[i][k] * omtrx[k][j];
+				}
+				omtrx[i][j] = sum;
+				tmp = wk[i] * Math.abs(sum);
+				if (tmp >= maxb)
+				{
+					maxb = tmp;
+					maxi = i;
+				}
+			}
+			if (j != maxi)
+			{
+				for (k = 0; k < size; k++)
+				{
+					tmp = omtrx[maxi][k];
+					omtrx[maxi][k] = omtrx[j][k];
+					omtrx[j][k] = tmp;
+				}
+				aw = -aw;
+				wk[maxi] = wk[j];
+			}
+			index[j] = maxi;
+			if (omtrx[j][j] == 0.0)
+			{
+				omtrx[j][j] = MachineAccuracy.EPSILON;
+			}
+			if (j != size - 1)
+			{
+				tmp = 1.0 / omtrx[j][j];
+				for (i = j + 1; i < size; i++)
+				{
+					omtrx[i][j] *= tmp;
+				}
+			}
+		}
+		for (jx = 0; jx < size; jx++)
+		{
+			for (ix = 0; ix < size; ix++)
+			{
+				wk[ix] = 0.0;
+			}
+			wk[jx] = 1.0;
+			l = -1;
+			for (i = 0; i < size; i++)
+			{
+				idx = index[i];
+				sum = wk[idx];
+				wk[idx] = wk[i];
+				if (l != -1)
+				{
+					for (j = l; j < i; j++)
+					{
+						sum -= omtrx[i][j] * wk[j];
+					}
+				}
+				else if (sum != 0.0)
+				{
+					l = i;
+				}
+				wk[i] = sum;
+			}
+			for (i = size - 1; i >= 0; i--)
+			{
+				sum = wk[i];
+				for (j = i + 1; j < size; j++)
+				{
+					sum -= omtrx[i][j] * wk[j];
+				}
+				wk[i] = sum/omtrx[i][i];
+			}
+			for (ix = 0; ix < size; ix++)
+			{
+				imtrx[ix][jx] = wk[ix];
+			}
+		}
+		wk = null;
+		index = null;
+		omtrx = null;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/NucleotideModel.java b/LibrarySource/pal/substmodel/NucleotideModel.java
new file mode 100644
index 0000000..5d52c1d
--- /dev/null
+++ b/LibrarySource/pal/substmodel/NucleotideModel.java
@@ -0,0 +1,132 @@
+// NucleotideModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * base class for nucleotide rate matrices
+ *
+ * @version $Id: NucleotideModel.java,v 1.7 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+abstract public class NucleotideModel extends AbstractRateMatrix implements RateMatrix, Serializable {
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Create nucleotide substitution model according to model type
+	 *
+	 * @param modelID model code
+	 * @param params model parameters
+	 * @param freq  model frequencies
+	 *
+	 * @return nucleotide rate matrix
+	 */
+	public static NucleotideModel getInstance(int modelID, double[] params, double[] freq)
+	{
+		if (modelID == NucleotideModelID.GTR)
+		{
+			return new GTR(params, freq);
+		}
+		else if (modelID == NucleotideModelID.TN)
+		{
+			return new TN(params, freq);
+		}
+		else if (modelID == NucleotideModelID.HKY)
+		{
+			return new HKY(params, freq);
+		}
+		else if (modelID == NucleotideModelID.F84)
+		{
+			return new F84(params, freq);
+		}
+		else if (modelID == NucleotideModelID.F81)
+		{
+			return new F81(freq);
+		}
+		else
+		{
+			return new F81(freq);
+		}
+	}
+
+	// interface Report (inherited, remains abstract)
+	
+	// interface Parameterized (inherited, remains abstract)
+	
+
+	//
+	// Protected stuff (for use in derived classes)
+	//
+
+	// Constructor
+	protected NucleotideModel(double[] f)
+	{
+		// Dimension = 4
+		super(4);
+		
+		dataType = new Nucleotides();
+		setFrequencies(f);
+	}
+
+	protected void printFrequencies(PrintWriter out)
+	{
+		out.println("Nucleotide frequencies:");
+		super.printFrequencies(out);
+	}
+	
+	protected void printRatios(PrintWriter out)
+	{
+		computeRatios();
+		out.print("Expected transition/transversion ratio: ");
+		format.displayDecimal(out, expectedTsTvRatio, 2);
+		out.println();
+		out.print("Expected pyrimidine transition/purine transition ratio: ");
+		format.displayDecimal(out, expectedYRTsRatio, 2);
+		out.println();
+	}
+
+	//
+	// Private stuff
+	//
+
+	private void computeRatios()
+	{
+		// Compute expectation ratios		
+		int A = 0; double piA = frequency[0];
+		int C = 1; double piC = frequency[1];
+		int G = 2; double piG = frequency[2];
+		int T = 3; double piT = frequency[3];
+
+		double numYTs = piC*rate[C][T] + piT*rate[T][C];
+		double numRTs = piA*rate[A][G] + piG*rate[G][A];
+		double numTv = 
+			piA*rate[A][C] + piC*rate[C][A] +
+			piA*rate[A][T] + piT*rate[T][A] +
+			piC*rate[C][G] + piG*rate[G][C] +
+			piG*rate[G][T] + piT*rate[T][G];
+
+		expectedTsTvRatio = (numYTs + numRTs)/numTv;
+		expectedYRTsRatio = numYTs/numRTs;
+	}
+	
+	// Expected transition-transversion ratio
+	private double expectedTsTvRatio;
+	
+	// Expected ratio of pyrimidine and purine transitions
+	private double expectedYRTsRatio;
+}
+
diff --git a/LibrarySource/pal/substmodel/NucleotideModelID.java b/LibrarySource/pal/substmodel/NucleotideModelID.java
new file mode 100644
index 0000000..ec2cb61
--- /dev/null
+++ b/LibrarySource/pal/substmodel/NucleotideModelID.java
@@ -0,0 +1,34 @@
+// NucleotideModelID.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import java.io.Serializable;
+
+/**
+ * interface for IDs of nucleotide models
+ *
+ * @version $Id: NucleotideModelID.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public interface NucleotideModelID extends Serializable
+{
+	//
+	// Public stuff
+	//
+
+	int GTR = 0;
+	int TN = 1;
+	int HKY = 2;
+	int F84 = 3;
+	int F81 = 4;
+	
+	int MODELCOUNT = 5;
+
+}
+
diff --git a/LibrarySource/pal/substmodel/RateDistribution.java b/LibrarySource/pal/substmodel/RateDistribution.java
new file mode 100644
index 0000000..4fdbe9f
--- /dev/null
+++ b/LibrarySource/pal/substmodel/RateDistribution.java
@@ -0,0 +1,92 @@
+// RateDistribution.java
+//
+// (c) 1999-2000 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+
+
+/**
+ * abstract base class for models of rate variation over sites
+ * employing a discrete rate distribution
+ *
+ * @version $Id: RateDistribution.java,v 1.7 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+
+public abstract class RateDistribution implements Parameterized, Report, Cloneable, Serializable
+{
+	//
+	// Public stuff
+	//
+		
+	/** number of rate categories*/
+	public int numRates;
+	
+	/** rates of each rate category */
+	public double[] rate;
+	
+	/** probability of each rate */
+	public double[] probability;
+
+	/**
+	 * construct discrete distribution
+	 *
+	 *  @param n number of rate categories
+	 */
+	public RateDistribution(int n)
+	{
+		format = FormattedOutput.getInstance();
+		
+		numRates = n;
+		rate = new double[n];
+		probability = new double[n];
+	}
+	
+	// interface Report (remains abstract)
+	
+	// interface Parameterized (remains abstract)
+
+	//
+	// Protected stuff
+	//
+	
+	protected FormattedOutput format;
+	
+	protected void printRates(PrintWriter out)
+	{
+		out.println("Relative rates and their probabilities:\n");
+		format.displayIntegerWhite(out, numRates);
+		out.println("   Rate      Probability");
+		for (int i = 0; i < numRates; i++)
+		{
+			format.displayInteger(out, i+1, numRates);
+			out.print("   ");
+			format.displayDecimal(out, rate[i], 5);
+			out.print("   ");
+			format.displayDecimal(out, probability[i], 5);
+			out.println();
+		}
+	}
+
+	public Object clone() {
+		try {
+			RateDistribution rd = (RateDistribution)super.clone();
+			return rd;
+		} catch (CloneNotSupportedException e) {
+			// this shouldn't happen
+			throw new InternalError();
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/RateMatrix.java b/LibrarySource/pal/substmodel/RateMatrix.java
new file mode 100644
index 0000000..d91d4a8
--- /dev/null
+++ b/LibrarySource/pal/substmodel/RateMatrix.java
@@ -0,0 +1,86 @@
+// RateMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.io.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * abstract base class for all rate matrices
+ *
+ * @version $Id: RateMatrix.java,v 1.14 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public interface RateMatrix
+	extends Parameterized, Report, Cloneable, Serializable {
+
+	/**
+	 * get numerical code describing the data type
+	 *
+	 * @return integer code identifying a data type
+	 */
+	int getTypeID();
+
+	int getDimension();
+
+	/**
+		* @return stationary frequencies (sum = 1.0)
+		*/
+	double[] getEqulibriumFrequencies();
+
+	/**
+		* @return stationary frequencie (sum = 1.0) for ith state
+		* Preferred method for infrequent use.
+		*/
+	double getEqulibriumFrequency(int i);
+
+	/**
+	 * get numerical code describing the model type
+	 *
+	 * @return integer code identifying a substitution model
+	 */
+	int getModelID();
+
+
+
+	/** For those that like Getter/Setters */
+	DataType getDataType();
+
+	/**
+	 * @return rate matrix (transition: from 1st index to 2nd index)
+	 * @note should be deprecated. Try not to use!
+	 */
+	double[][] getRelativeRates();
+
+	
+	/**
+		Return a transitionProbability calculting thing appropriate to this ratematrix (generally returns SimpleRateMatrix())
+	*/
+	TransitionProbability getTransitionProbability();
+
+	/**
+		Return a matrix exponential appropriate to this ratematrix (generally returns SimpleRateMatrix())
+		given an old matrix exponential (may reuse old matrix exponential)
+	*/
+	TransitionProbability getTransitionProbability(TransitionProbability old);
+
+	// interface Report (remains abstract)
+
+	// interface Parameterized (remains abstract)
+
+	Object clone();
+
+}
+
diff --git a/LibrarySource/pal/substmodel/RateMatrixUtils.java b/LibrarySource/pal/substmodel/RateMatrixUtils.java
new file mode 100644
index 0000000..e730073
--- /dev/null
+++ b/LibrarySource/pal/substmodel/RateMatrixUtils.java
@@ -0,0 +1,64 @@
+// RateMatrixUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import pal.datatype.*;
+
+/**
+ * @version $Id: RateMatrixUtils.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ * @author Matthew Goode
+ */
+
+public class RateMatrixUtils {
+
+	/**
+	 * Create rate matrix given model and data type codes
+	 *
+	 * @param typeID  code for data type
+	 * @param modelID code for model of substitution
+	 * @param params      model parameters
+	 * @param freq        model frequencies
+	 *
+	 * @return rate matrix
+	 */
+	public static RateMatrix getInstance(int typeID, int modelID,
+		double[] params, double[] freq)
+	{
+		if (typeID == DataType.NUCLEOTIDES)
+		{
+			return NucleotideModel.getInstance(modelID, params, freq);
+		}
+		else if (typeID == DataType.AMINOACIDS)
+		{
+			return AminoAcidModel.getInstance(modelID, freq);
+		}
+		else if (typeID == DataType.TWOSTATES)
+		{
+			return TwoStateModel.getInstance(freq);
+		}
+		else
+		{
+			return NucleotideModel.getInstance(modelID, params, freq);
+		}
+	}
+
+	public static final RateMatrix[] getCopy(RateMatrix[] toCopy) {
+		if(toCopy==null) {
+			return null;
+		}
+		RateMatrix[] copy = new RateMatrix[toCopy.length];
+		for(int i = 0 ; i < copy.length ; i++) {
+     	copy[i] = (RateMatrix)toCopy[i].clone();
+		}
+		return copy;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/SubstitutionModel.java b/LibrarySource/pal/substmodel/SubstitutionModel.java
new file mode 100644
index 0000000..c40cbf7
--- /dev/null
+++ b/LibrarySource/pal/substmodel/SubstitutionModel.java
@@ -0,0 +1,288 @@
+// SubstitutionModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.math.*;
+
+import java.io.*;
+
+
+/**
+ * <b>model of sequence substitution (rate matrix + rate variation)</b>.
+ * provides a convenient interface for the computation of transition probabilities
+ *
+ * @version $Id: SubstitutionModel.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class SubstitutionModel implements Parameterized, Report, java.io.Serializable, Cloneable {
+	//
+	// Public stuff
+	//
+	
+	/** rate matrix */
+	public RateMatrix rateMatrix;
+	
+	/** rate distribution */
+	public RateDistribution rateDistribution;
+	
+	/** dimension of rate matrix */	
+	public int dimension;
+	
+	/** number of categories in discrete rate distribution */
+	public int numRates;
+
+	/**
+	 * constructor 1 (uniform rate distribution)
+	 *
+	 * @param rmat rate matrix
+	 */
+	public SubstitutionModel(RateMatrix rmat)
+	{
+		this(rmat, new UniformRate());
+	}
+
+	/**
+	 * constructor 2 (gamma rate distribution)
+	 *
+	 * @param rmat rate matrix
+	 * @param n number of rate categories
+	 * @param a shape parameter
+	 */
+	public SubstitutionModel(RateMatrix rmat, int n, double a)
+	{
+		this(rmat, new GammaRates(n, a));
+	}
+	
+	/**
+	 * constructor 3 (arbitrary rate distribution)
+	 *
+	 * @param rmat rate matrix
+	 * @param rdist rate distribution
+	 */
+	public SubstitutionModel(RateMatrix rmat, RateDistribution rdist)
+	{
+		dimension = rmat.getDimension();
+		numRates = rdist.numRates;
+		
+		rateMatrix = rmat;
+		rateDistribution = rdist;
+		
+		tpm = rmat.getTransitionProbability();
+		probs = new double[numRates][dimension][dimension];
+		
+		numRmatParams = rmat.getNumParameters();
+		numRdistParams = rdist.getNumParameters();
+		numParams = numRmatParams + numRdistParams;
+	}
+	
+	/**
+	 * Return a copy of this substitution model.
+	 */
+	public SubstitutionModel(SubstitutionModel model) {
+	
+		dimension = model.rateMatrix.getDimension();
+		numRates = model.rateDistribution.numRates;
+		numRmatParams = model.rateMatrix.getNumParameters();
+		numRdistParams = model.rateDistribution.getNumParameters();
+		
+		rateMatrix = (RateMatrix)model.rateMatrix.clone();
+		rateDistribution = 
+			(RateDistribution)model.rateDistribution.clone();
+		
+		tpm =  rateMatrix.getTransitionProbability();
+		probs = new double[numRates][dimension][dimension];
+		
+		numParams = numRmatParams + numRdistParams;
+	}
+
+	// interface Report
+	public void report(PrintWriter out)
+	{
+		rateMatrix.report(out);
+		out.println();
+		rateDistribution.report(out);
+	}
+
+	/**
+	 * Return string representation of substitution model.
+	 */
+	public String toString() {
+		StringWriter sw = new StringWriter();
+		report(new PrintWriter(sw));
+		return sw.toString();
+	}
+	
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return numParams;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		if (n < numRmatParams)
+		{
+			rateMatrix.setParameter(param, n);
+			tpm = rateMatrix.getTransitionProbability(tpm);
+		}
+		else
+		{
+			rateDistribution.setParameter(param, n-numRmatParams);
+		}		
+	}
+
+	public double getParameter(int n)
+	{
+		if (n < numRmatParams)
+		{
+			return rateMatrix.getParameter(n);
+		}
+		else
+		{
+			return rateDistribution.getParameter(n-numRmatParams);
+		}		
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		if (n < numRmatParams)
+		{
+			rateMatrix.setParameterSE(paramSE, n);
+		}
+		else
+		{
+			rateDistribution.setParameterSE(paramSE, n-numRmatParams);
+		}		
+	}
+
+	public double getLowerLimit(int n)
+	{
+		if (n < numRmatParams)
+		{
+			return rateMatrix.getLowerLimit(n);
+		}
+		else
+		{
+			return rateDistribution.getLowerLimit(n-numRmatParams);
+		}		
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		if (n < numRmatParams)
+		{
+			return rateMatrix.getUpperLimit(n);
+		}
+		else
+		{
+			return rateDistribution.getUpperLimit(n-numRmatParams);
+		}		
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		if (n < numRmatParams)
+		{
+			return rateMatrix.getDefaultValue(n);
+		}
+		else
+		{
+			return rateDistribution.getDefaultValue(n-numRmatParams);
+		}		
+	}
+
+
+	/**
+	 * set distance and corresponding computation transition probabilities
+	 *
+	 * @param k distance
+	 */
+	public void setDistance(double k)
+	{
+		for (int r = 0; r < numRates; r++)
+		{
+			double kk = k*rateDistribution.rate[r];
+			
+			if (kk < BranchLimits.MINARC)
+			{
+				kk = BranchLimits.MINARC;
+			}
+			if (kk > BranchLimits.MAXARC)
+			{
+				kk = BranchLimits.MAXARC;
+			}
+		
+			tpm.setDistance(kk);
+			
+			for (int i = 0; i < dimension; i++)
+			{
+				for (int j = 0; j < dimension; j++)
+				{
+					probs[r][i][j] = tpm.getTransitionProbability(i,j);
+				}
+			}
+		}
+	}
+
+	/**
+	 * get transition probability for the preselected model and
+	 * the previously specified distance
+	 *
+	 * @param r rate category
+	 * @param i start state
+	 * @param j end state
+	 *
+	 * @return transition probability
+	 */
+	public double transProb(int r, int i, int j)
+	{
+		return probs[r][i][j];
+	}
+
+	public boolean isSimpleJukesCantor() {
+		
+		// if more then one rate the not a simple jukes cantor
+		if (numRates > 1) return false;
+		
+		// NOT if frequencies are different
+		double[] frequencies = rateMatrix.getEqulibriumFrequencies();
+		double freq = frequencies[0];
+		for (int i = 1; i < frequencies.length; i++) {
+			if (frequencies[i] != freq) {
+				return false;	
+			}
+		}
+
+		double[][] relRates = rateMatrix.getRelativeRates();
+		// NOT if rates are different
+		double rate = relRates[0][1];
+		for (int i = 0; i < relRates.length; i++) {
+			for (int j = 0; j < relRates[i].length; j++) {
+				if ((i != j) && (relRates[i][j] != rate)) {
+					return false;
+				}
+			}
+		}
+		
+		return true;
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	private TransitionProbability tpm;
+	private double[][][] probs;
+	private int numRmatParams, numRdistParams, numParams;
+}
+
diff --git a/LibrarySource/pal/substmodel/TN.java b/LibrarySource/pal/substmodel/TN.java
new file mode 100644
index 0000000..dfdae00
--- /dev/null
+++ b/LibrarySource/pal/substmodel/TN.java
@@ -0,0 +1,183 @@
+// TN.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * Tamura-Nei model of nucleotide evolution
+ *
+ * @version $Id: TN.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class TN extends NucleotideModel
+{
+	/**
+	 * constructor 1
+	 *
+	 * @param kappa transition/transversion rate ratio
+	 * @param r pyrimidine/purin transition rate ratio
+	 * @param freq nucleotide frequencies
+	 */
+	public TN(double kappa, double r, double[] freq)
+	{
+		super(freq);
+		
+		this.kappa = kappa;
+		this.r = r;
+		
+		makeTN();
+		fromQToR();
+		
+		showSE = false;
+	}
+
+	/**
+	 * constructor 2
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotode frequencies
+	 */
+	public TN(double[] params, double[] freq)
+	{
+		this(params[0], params[1], freq);
+	}
+ 
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 1;
+	}
+ 
+ 	// interface Parameterized
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: TN (Tamura-Nei 1993)");
+		out.print("Transition/transversion rate ratio kappa: ");
+		format.displayDecimal(out, kappa, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, kappaSE, 2);
+			out.print(")");
+		}
+		out.println();
+		
+		out.print("Y/R transition rate ratio: ");
+		format.displayDecimal(out, r, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, rSE, 2);
+			out.print(")");
+		}
+		out.println();
+		
+		out.println();
+		printFrequencies(out);
+		printRatios(out);
+	}	
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 2;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		switch(n)
+		{
+			case 0: kappa = param; break;
+			case 1: r = param; break;
+
+			default: throw new IllegalArgumentException();
+		}
+
+		makeTN();
+		fromQToR();
+	}
+
+	public double getParameter(int n)
+	{
+		double value;
+		
+		switch(n)
+		{
+			case 0: value = kappa; break;
+			case 1: value = r; break;
+
+			default: throw new IllegalArgumentException();
+		}
+				
+		return value;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		switch(n)
+		{
+			case 0: kappaSE = paramSE; break;
+			case 1: rSE = paramSE; break;
+
+			default: throw new IllegalArgumentException();
+		}
+
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 100.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		double value;
+		
+		switch(n)
+		{
+			case 0: value = 4.0; break;
+			case 1: value = 0.5; break;
+
+			default: throw new IllegalArgumentException();
+		}
+				
+		return value;
+	}
+
+	
+	//
+	// Private stuff
+	// 
+
+	private boolean showSE;
+	private double kappa, kappaSE, r, rSE;
+
+	// Make TN model
+	private void makeTN()
+	{
+		// Q matrix
+		rate[0][1] = 1; rate[0][2] = 2.0*kappa/(r+1.0); rate[0][3] = 1;
+		rate[1][2] = 1; rate[1][3] = 2.0*kappa*r/(r+1.0);
+		rate[2][3] = 1;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/TransitionProbability.java b/LibrarySource/pal/substmodel/TransitionProbability.java
new file mode 100644
index 0000000..a00809c
--- /dev/null
+++ b/LibrarySource/pal/substmodel/TransitionProbability.java
@@ -0,0 +1,48 @@
+// TransistionProbability.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.substmodel;
+
+import pal.math.*;
+
+
+/**
+ * For objects that represent a source of transition probabilities
+ *
+ * TransitionProbability.java,v 1.3 2000/08/08 22:58:29 alexi Exp $
+ *
+ * @author Matthew Goode
+ */
+public interface TransitionProbability extends Cloneable, java.io.Serializable {
+
+	/**
+	 * compute transition probabilities for a expected distance
+	 * using the prespecified rate matrix
+	 *
+	 * @param arc expected distance
+	 */
+	void setDistance(double arc);
+	/**
+	 * compute transition probabilities for a expected time span
+	 * using the prespecified rate matrix
+	 *
+	 * @param start start time
+	 * @param end end time
+	 */
+	void setTime(double start, double end);
+
+	/**
+		* Returns the transition probability for changing from
+		* startState into endState
+		* @param startState - the starting state
+		* @param endState - the resulting state
+		*/
+	double getTransitionProbability(int startState, int endState);
+
+	int getDimension();
+}
+
diff --git a/LibrarySource/pal/substmodel/TwoStateModel.java b/LibrarySource/pal/substmodel/TwoStateModel.java
new file mode 100644
index 0000000..d6ee4f8
--- /dev/null
+++ b/LibrarySource/pal/substmodel/TwoStateModel.java
@@ -0,0 +1,115 @@
+// TwoStateModel.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * implements the most general reversible rate matrix for two-state data
+ *
+ * @version $Id: TwoStateModel.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class TwoStateModel extends AbstractRateMatrix implements RateMatrix
+{
+	/**
+	 * constructor
+	 *
+	 * @param f frequencies
+	 *
+	 * @return rate matrix
+	 */
+	public TwoStateModel(double[] f)
+	{
+		// Dimension = 2
+		super(2);
+		
+		dataType = new TwoStates();
+		
+		setFrequencies(f);
+		// Q matrix
+		rate[0][1] = 1;
+		fromQToR();
+	}
+
+	/**
+	 * get numerical code describing the model type
+	 *
+	 * @return 0 (there is only one model)
+	 */
+	public int getModelID()
+	{
+		return 0;
+	}
+	
+	/**
+	 * create object using an instance method
+	 *
+	 * @param freq model frequencies
+	 *
+	 * @return rate matrix
+	 */ 
+	public static TwoStateModel getInstance(double[] freq)
+	{
+ 		return new TwoStateModel(freq);
+ 	}
+	
+ 	// interface Report
+
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: Proportional Model (F81)");
+		out.println();
+		out.println("Frequencies of the two states:");
+		printFrequencies(out);
+	}
+	
+	// interface Parameterized
+	
+	public int getNumParameters()
+	{
+		return 0;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		return;
+	}
+
+	public double getParameter(int n)
+	{
+		return 0.0;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.0;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/UniformRate.java b/LibrarySource/pal/substmodel/UniformRate.java
new file mode 100644
index 0000000..1887c88
--- /dev/null
+++ b/LibrarySource/pal/substmodel/UniformRate.java
@@ -0,0 +1,84 @@
+// UniformRate.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * uniform rate distribution
+ *
+ * @version $Id: UniformRate.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class UniformRate extends RateDistribution implements Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * construct uniform rate distribution
+	 */
+	public UniformRate()
+	{
+		super(1);
+		
+		rate[0] = 1.0;
+		probability[0] = 1.0;
+	}
+	
+	// interface Report
+	
+	public void report(PrintWriter out)
+	{
+		out.println("Model of rate heterogeneity: Uniform rate at all sites");
+	}
+
+	// interface Parameterized
+	
+	public int getNumParameters()
+	{
+		return 0;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		return;
+	}
+
+	public double getParameter(int n)
+	{
+		return 0.0;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 0.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 0.0;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/VT.java b/LibrarySource/pal/substmodel/VT.java
new file mode 100644
index 0000000..f6d57da
--- /dev/null
+++ b/LibrarySource/pal/substmodel/VT.java
@@ -0,0 +1,210 @@
+// VT.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * VT (variable time matrix) model of amino acid evolution
+ *
+ * @version $Id: VT.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class VT extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public VT(double[] f)
+	{
+		super(f);
+
+		makeVT();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 4;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: VT (Mueller-Vingron 2000)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0]=0.078837 ;
+		f[1]=0.051238 ;
+		f[2]=0.042313 ;
+		f[3]=0.053066 ;
+		f[4]=0.015175 ;
+		f[5]=0.036713 ;
+		f[6]=0.061924 ;
+		f[7]=0.070852 ;
+		f[8]=0.023082 ;
+		f[9]=0.062056 ;
+		f[10]=0.096371 ;
+		f[11]=0.057324 ;
+		f[12]=0.023771 ;
+		f[13]=0.043296 ;
+		f[14]=0.043911 ;
+		f[15]=0.063403 ;
+		f[16]=0.055897 ;
+		f[17]=0.013272 ;
+		f[18]=0.034399 ;
+		f[19]=0.073101 ;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// VT model of amino acid evolution
+	// Mueller, T. and Vingron, M. 2000. J. Comp. Biol.?:?-?.
+	private void makeVT()
+	{		
+		// Q matrix
+		rate[0][1] = 0.233108 ; rate[0][2] = 0.199097 ;
+		rate[0][3] = 0.265145 ; rate[0][4] = 0.227333 ;
+		rate[0][5] = 0.310084 ; rate[0][6] = 0.567957 ;
+		rate[0][7] = 0.876213 ; rate[0][8] = 0.078692 ;
+		rate[0][9] = 0.222972 ; rate[0][10] = 0.424630 ;
+		rate[0][11] = 0.393245 ; rate[0][12] = 0.211550 ;
+		rate[0][13] = 0.116646 ; rate[0][14] = 0.399143 ;
+		rate[0][15] = 1.817198 ; rate[0][16] = 0.877877 ;
+		rate[0][17] = 0.030309 ; rate[0][18] = 0.087061 ;
+		rate[0][19] = 1.230985 ;
+		
+		rate[1][2] = 0.210797 ; rate[1][3] = 0.105191 ;
+		rate[1][4] = 0.031726 ; rate[1][5] = 0.493763 ;
+		rate[1][6] = 0.255240 ; rate[1][7] = 0.156945 ;
+		rate[1][8] = 0.213164 ; rate[1][9] = 0.081510 ;
+		rate[1][10] = 0.192364 ; rate[1][11] = 1.755838 ;
+		rate[1][12] = 0.087930 ; rate[1][13] = 0.042569 ;
+		rate[1][14] = 0.128480 ; rate[1][15] = 0.292327 ;
+		rate[1][16] = 0.204109 ; rate[1][17] = 0.046417 ;
+		rate[1][18] = 0.097010 ; rate[1][19] = 0.113146 ;
+		
+		rate[2][3] = 0.883422 ; rate[2][4] = 0.027495 ;
+		rate[2][5] = 0.275700 ; rate[2][6] = 0.270417 ;
+		rate[2][7] = 0.362028 ; rate[2][8] = 0.290006 ;
+		rate[2][9] = 0.087225 ; rate[2][10] = 0.069245 ;
+		rate[2][11] = 0.503060 ; rate[2][12] = 0.057420 ;
+		rate[2][13] = 0.039769 ; rate[2][14] = 0.083956 ;
+		rate[2][15] = 0.847049 ; rate[2][16] = 0.471268 ;
+		rate[2][17] = 0.010459 ; rate[2][18] = 0.093268 ;
+		rate[2][19] = 0.049824 ;
+		
+		rate[3][4] = 0.010313 ; rate[3][5] = 0.205842 ;
+		rate[3][6] = 1.599461 ; rate[3][7] = 0.311718 ;
+		rate[3][8] = 0.134252 ; rate[3][9] = 0.011720 ;
+		rate[3][10] = 0.060863 ; rate[3][11] = 0.261101 ;
+		rate[3][12] = 0.012182 ; rate[3][13] = 0.016577 ;
+		rate[3][14] = 0.160063 ; rate[3][15] = 0.461519 ;
+		rate[3][16] = 0.178197 ; rate[3][17] = 0.011393 ;
+		rate[3][18] = 0.051664 ; rate[3][19] = 0.048769 ;
+		
+		rate[4][5] = 0.004315 ; rate[4][6] = 0.005321 ;
+		rate[4][7] = 0.050876 ; rate[4][8] = 0.016695 ;
+		rate[4][9] = 0.046398 ; rate[4][10] = 0.091709 ;
+		rate[4][11] = 0.004067 ; rate[4][12] = 0.023690 ;
+		rate[4][13] = 0.051127 ; rate[4][14] = 0.011137 ;
+		rate[4][15] = 0.175270 ; rate[4][16] = 0.079511 ;
+		rate[4][17] = 0.007732 ; rate[4][18] = 0.042823 ;
+		rate[4][19] = 0.163831 ;
+		
+		rate[5][6] = 0.960976 ; rate[5][7] = 0.128660 ;
+		rate[5][8] = 0.315521 ; rate[5][9] = 0.054602 ;
+		rate[5][10] = 0.243530 ; rate[5][11] = 0.738208 ;
+		rate[5][12] = 0.120801 ; rate[5][13] = 0.026235 ;
+		rate[5][14] = 0.156570 ; rate[5][15] = 0.358017 ;
+		rate[5][16] = 0.248992 ; rate[5][17] = 0.021248 ;
+		rate[5][18] = 0.062544 ; rate[5][19] = 0.112027 ;
+		
+		rate[6][7] = 0.250447 ; rate[6][8] = 0.104458 ;
+		rate[6][9] = 0.046589 ; rate[6][10] = 0.151924 ;
+		rate[6][11] = 0.888630 ; rate[6][12] = 0.058643 ;
+		rate[6][13] = 0.028168 ; rate[6][14] = 0.205134 ;
+		rate[6][15] = 0.406035 ; rate[6][16] = 0.321028 ;
+		rate[6][17] = 0.018844 ; rate[6][18] = 0.055200 ;
+		rate[6][19] = 0.205868 ;
+		
+		rate[7][8] = 0.058131 ; rate[7][9] = 0.051089 ;
+		rate[7][10] = 0.087056 ; rate[7][11] = 0.193243 ;
+		rate[7][12] = 0.046560 ; rate[7][13] = 0.050143 ;
+		rate[7][14] = 0.124492 ; rate[7][15] = 0.612843 ;
+		rate[7][16] = 0.136266 ; rate[7][17] = 0.023990 ;
+		rate[7][18] = 0.037568 ; rate[7][19] = 0.082579 ;
+		
+		rate[8][9] = 0.020039 ; rate[8][10] = 0.103552 ;
+		rate[8][11] = 0.153323 ; rate[8][12] = 0.021157 ;
+		rate[8][13] = 0.079807 ; rate[8][14] = 0.078892 ;
+		rate[8][15] = 0.167406 ; rate[8][16] = 0.101117 ;
+		rate[8][17] = 0.020009 ; rate[8][18] = 0.286027 ;
+		rate[8][19] = 0.068575 ;
+		
+		rate[9][10] = 2.089890 ; rate[9][11] = 0.093181 ;
+		rate[9][12] = 0.493845 ; rate[9][13] = 0.321020 ;
+		rate[9][14] = 0.054797 ; rate[9][15] = 0.081567 ;
+		rate[9][16] = 0.376588 ; rate[9][17] = 0.034954 ;
+		rate[9][18] = 0.086237 ; rate[9][19] = 3.654430 ;
+		
+		rate[10][11] = 0.201204 ; rate[10][12] = 1.105667 ;
+		rate[10][13] = 0.946499 ; rate[10][14] = 0.169784 ;
+		rate[10][15] = 0.214977 ; rate[10][16] = 0.243227 ;
+		rate[10][17] = 0.083439 ; rate[10][18] = 0.189842 ;
+		rate[10][19] = 1.337571 ;
+		
+		rate[11][12] = 0.096474 ; rate[11][13] = 0.038261 ;
+		rate[11][14] = 0.212302 ; rate[11][15] = 0.400072 ;
+		rate[11][16] = 0.446646 ; rate[11][17] = 0.023321 ;
+		rate[11][18] = 0.068689 ; rate[11][19] = 0.144587 ;
+		
+		rate[12][13] = 0.173052 ; rate[12][14] = 0.010363 ;
+		rate[12][15] = 0.090515 ; rate[12][16] = 0.184609 ;
+		rate[12][17] = 0.022019 ; rate[12][18] = 0.073223 ;
+		rate[12][19] = 0.307309 ;
+		
+		rate[13][14] = 0.042564 ; rate[13][15] = 0.138119 ;
+		rate[13][16] = 0.085870 ; rate[13][17] = 0.128050 ;
+		rate[13][18] = 0.898663 ; rate[13][19] = 0.247329 ;
+		
+		rate[14][15] = 0.430431 ; rate[14][16] = 0.207143 ;
+		rate[14][17] = 0.014584 ; rate[14][18] = 0.032043 ;
+		rate[14][19] = 0.129315 ;
+		
+		rate[15][16] = 1.767766 ; rate[15][17] = 0.035933 ;
+		rate[15][18] = 0.121979 ; rate[15][19] = 0.127700 ;
+		
+		rate[16][17] = 0.020437 ; rate[16][18] = 0.094617 ;
+		rate[16][19] = 0.740372 ;
+		
+		rate[17][18] = 0.124746 ; rate[17][19] = 0.022134 ;
+		
+		rate[18][19] = 0.125733 ;
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/WAG.java b/LibrarySource/pal/substmodel/WAG.java
new file mode 100644
index 0000000..d5feb2f
--- /dev/null
+++ b/LibrarySource/pal/substmodel/WAG.java
@@ -0,0 +1,210 @@
+// WAG.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * WAG model of amino acid evolution (S. Whelan and N. Goldman 2000)
+ *
+ * @version $Id: WAG.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class WAG extends AminoAcidModel
+{
+	/**
+	 * constructor
+	 *
+	 * @param f amino acid frequencies
+	 */
+	public WAG(double[] f)
+	{
+		super(f);
+
+		makeWAG();
+		fromQToR();
+	}
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 5;
+	}
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: WAG (Whelan-Goldman 2000)");
+		out.println();
+		printFrequencies(out);
+	}	
+
+	/**
+	 * get the frequencies of the original data set that
+	 * formed the basis for the estimation of the rate matrix
+	 *
+	 * @param f array where amino acid frequencies will be stored
+	 */
+	public static void getOriginalFrequencies(double[] f)
+	{
+		f[0] = 0.0866;
+		f[1] = 0.0440;
+		f[2] = 0.0391;
+		f[3] = 0.0570;
+		f[4] = 0.0193;
+		f[5] = 0.0367;
+		f[6] = 0.0581;
+		f[7] = 0.0833;
+		f[8] = 0.0244;
+		f[9] = 0.0485;
+		f[10] = 0.0862;
+		f[11] = 0.0620;
+		f[12] = 0.0195;
+		f[13] = 0.0384;
+		f[14] = 0.0458;
+		f[15] = 0.0695;
+		f[16] = 0.0610;
+		f[17] = 0.0144;
+		f[18] = 0.0353;
+		f[19] = 0.0709;
+	}
+
+	//
+	// Private stuff
+	// 
+
+	// WAG model of amino acid evolution
+	// Whelan, S. and N. Goldman. 2000. in prep.
+	private void makeWAG()
+	{		
+		// Q matrix
+		rate[0][1] = 0.610810; rate[0][2] = 0.569079; 
+		rate[0][3] = 0.821500; rate[0][4] = 1.141050; 
+		rate[0][5] = 1.011980; rate[0][6] = 1.756410; 
+		rate[0][7] = 1.572160; rate[0][8] = 0.354813; 
+		rate[0][9] = 0.219023; rate[0][10] = 0.443935; 
+		rate[0][11] = 1.005440; rate[0][12] = 0.989475; 
+		rate[0][13] = 0.233492; rate[0][14] = 1.594890; 
+		rate[0][15] = 3.733380; rate[0][16] = 2.349220; 
+		rate[0][17] = 0.125227; rate[0][18] = 0.268987; 
+		rate[0][19] = 2.221870; 
+
+		rate[1][2] = 0.711690; rate[1][3] = 0.165074; 
+		rate[1][4] = 0.585809; rate[1][5] = 3.360330; 
+		rate[1][6] = 0.488649; rate[1][7] = 0.650469; 
+		rate[1][8] = 2.362040; rate[1][9] = 0.206722; 
+		rate[1][10] = 0.551450; rate[1][11] = 5.925170; 
+		rate[1][12] = 0.758446; rate[1][13] = 0.116821; 
+		rate[1][14] = 0.753467; rate[1][15] = 1.357640; 
+		rate[1][16] = 0.613776; rate[1][17] = 1.294610; 
+		rate[1][18] = 0.423612; rate[1][19] = 0.280336; 
+
+		rate[2][3] = 6.013660; rate[2][4] = 0.296524; 
+		rate[2][5] = 1.716740; rate[2][6] = 1.056790; 
+		rate[2][7] = 1.253910; rate[2][8] = 4.378930; 
+		rate[2][9] = 0.615636; rate[2][10] = 0.147156; 
+		rate[2][11] = 3.334390; rate[2][12] = 0.224747; 
+		rate[2][13] = 0.110793; rate[2][14] = 0.217538; 
+		rate[2][15] = 4.394450; rate[2][16] = 2.257930; 
+		rate[2][17] = 0.078463; rate[2][18] = 1.208560; 
+		rate[2][19] = 0.221176; 
+
+		rate[3][4] = 0.033379; rate[3][5] = 0.691268; 
+		rate[3][6] = 6.833400; rate[3][7] = 0.961142; 
+		rate[3][8] = 1.032910; rate[3][9] = 0.043523; 
+		rate[3][10] = 0.093930; rate[3][11] = 0.533362; 
+		rate[3][12] = 0.116813; rate[3][13] = 0.052004; 
+		rate[3][14] = 0.472601; rate[3][15] = 1.192810; 
+		rate[3][16] = 0.417372; rate[3][17] = 0.146348; 
+		rate[3][18] = 0.363243; rate[3][19] = 0.169417; 
+
+		rate[4][5] = 0.109261; rate[4][6] = 0.023920; 
+		rate[4][7] = 0.341086; rate[4][8] = 0.275403; 
+		rate[4][9] = 0.189890; rate[4][10] = 0.428414; 
+		rate[4][11] = 0.083649; rate[4][12] = 0.437393; 
+		rate[4][13] = 0.441300; rate[4][14] = 0.122303; 
+		rate[4][15] = 1.560590; rate[4][16] = 0.570186; 
+		rate[4][17] = 0.795736; rate[4][18] = 0.604634; 
+		rate[4][19] = 1.114570; 
+
+		rate[5][6] = 6.048790; rate[5][7] = 0.366510; 
+		rate[5][8] = 4.749460; rate[5][9] = 0.131046; 
+		rate[5][10] = 0.964886; rate[5][11] = 4.308310; 
+		rate[5][12] = 1.705070; rate[5][13] = 0.110744; 
+		rate[5][14] = 1.036370; rate[5][15] = 1.141210; 
+		rate[5][16] = 0.954144; rate[5][17] = 0.243615; 
+		rate[5][18] = 0.252457; rate[5][19] = 0.333890; 
+
+		rate[6][7] = 0.630832; rate[6][8] = 0.635025; 
+		rate[6][9] = 0.141320; rate[6][10] = 0.172579; 
+		rate[6][11] = 2.867580; rate[6][12] = 0.353912; 
+		rate[6][13] = 0.092310; rate[6][14] = 0.755791; 
+		rate[6][15] = 0.782467; rate[6][16] = 0.914814; 
+		rate[6][17] = 0.172682; rate[6][18] = 0.217549; 
+		rate[6][19] = 0.655045; 
+
+		rate[7][8] = 0.276379; rate[7][9] = 0.034151; 
+		rate[7][10] = 0.068651; rate[7][11] = 0.415992; 
+		rate[7][12] = 0.194220; rate[7][13] = 0.055288; 
+		rate[7][14] = 0.273149; rate[7][15] = 1.486700; 
+		rate[7][16] = 0.251477; rate[7][17] = 0.374321; 
+		rate[7][18] = 0.114187; rate[7][19] = 0.209108; 
+		
+		rate[8][9] = 0.152215; rate[8][10] = 0.555096; 
+		rate[8][11] = 0.992083; rate[8][12] = 0.450867; 
+		rate[8][13] = 0.756080; rate[8][14] = 0.771387; 
+		rate[8][15] = 0.822459; rate[8][16] = 0.525511; 
+		rate[8][17] = 0.289998; rate[8][18] = 4.290350; 
+		rate[8][19] = 0.131869; 
+
+		rate[9][10] = 3.517820; rate[9][11] = 0.360574; 
+		rate[9][12] = 4.714220; rate[9][13] = 1.177640; 
+		rate[9][14] = 0.111502; rate[9][15] = 0.353443; 
+		rate[9][16] = 1.615050; rate[9][17] = 0.234326; 
+		rate[9][18] = 0.468951; rate[9][19] = 8.659740; 
+		
+		rate[10][11] = 0.287583; rate[10][12] = 5.375250; 
+		rate[10][13] = 2.348200; rate[10][14] = 0.462018; 
+		rate[10][15] = 0.382421; rate[10][16] = 0.364222; 
+		rate[10][17] = 0.740259; rate[10][18] = 0.443205; 
+		rate[10][19] = 1.997370; 
+		
+		rate[11][12] = 1.032220; rate[11][13] = 0.098843; 
+		rate[11][14] = 0.619503; rate[11][15] = 1.073780; 
+		rate[11][16] = 1.537920; rate[11][17] = 0.152232; 
+		rate[11][18] = 0.147411; rate[11][19] = 0.342012; 
+		
+		rate[12][13] = 1.320870; rate[12][14] = 0.194864; 
+		rate[12][15] = 0.556353; rate[12][16] = 1.681970; 
+		rate[12][17] = 0.570369; rate[12][18] = 0.473810; 
+		rate[12][19] = 2.282020; 
+		
+		rate[13][14] = 0.179896; rate[13][15] = 0.606814; 
+		rate[13][16] = 0.191467; rate[13][17] = 1.699780; 
+		rate[13][18] = 7.154480; rate[13][19] = 0.725096; 
+		
+		rate[14][15] = 1.786490; rate[14][16] = 0.885349; 
+		rate[14][17] = 0.156619; rate[14][18] = 0.239607; 
+		rate[14][19] = 0.351250; 
+		
+		rate[15][16] = 4.847130; rate[15][17] = 0.578784; 
+		rate[15][18] = 0.872519; rate[15][19] = 0.258861; 
+		
+		rate[16][17] = 0.126678; rate[16][18] = 0.325490; 
+		rate[16][19] = 1.547670; 
+		
+		rate[17][18] = 2.763540; rate[17][19] = 0.409817; 
+		
+		rate[18][19] = 0.347826; 
+	}
+}
+
diff --git a/LibrarySource/pal/substmodel/YangCodonModel.java b/LibrarySource/pal/substmodel/YangCodonModel.java
new file mode 100644
index 0000000..86879b8
--- /dev/null
+++ b/LibrarySource/pal/substmodel/YangCodonModel.java
@@ -0,0 +1,276 @@
+// YangCodonModel.java
+//
+// (c) 1999-2001 PAL Development Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.substmodel;
+
+import pal.misc.*;
+import pal.datatype.*;
+
+import java.io.*;
+
+
+/**
+ * Yang's model of codon evolution
+ *
+ * @version $Id: YangCodonModel.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Andrew Rambaut
+ */
+public class YangCodonModel extends CodonModel implements Serializable
+{
+	/**
+	 * constructor 1
+	 *
+	 * @param omega N/S rate ratio
+	 * @param kappa transition/transversion rate ratio
+	 * @param freq codon frequencies
+	 * @param codonTable codon table
+	 */
+	public YangCodonModel(double omega, double kappa, double[] freq,
+		CodonTable codonTable)
+	{
+		super(freq);
+		
+		this.kappa = kappa;
+		this.omega = omega;
+		this.codonTable = codonTable;
+				
+		makeYangModel();
+		fromQToR();
+		
+		showSE = false;
+	}
+	
+	/**
+	 * constructor 2 (universal codon table)
+	 *
+	 * @param omega N/S rate ratio
+	 * @param kappa transition/transversion rate ratio
+	 * @param freq codon frequencies
+	 */
+	public YangCodonModel(double omega, double kappa, double[] freq)
+	{
+		this(omega, kappa, freq, CodonTableFactory.createUniversalTranslator());
+	}
+
+	/**
+	 * constructor 4 (universal codon table)
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotide frequencies
+	 */
+	public YangCodonModel(double[] params, double[] freq)
+	{
+		this(params[0], params[1], freq, CodonTableFactory.createUniversalTranslator());
+	}
+
+	/**
+	 * constructor 3
+	 *
+	 * @param params parameter list
+	 * @param freq nucleotide frequencies
+	 * @param codonTable codon table
+	 */
+	public YangCodonModel(double[] params, double[] freq,
+		CodonTable codonTable)
+	{
+		this(params[0], params[1], freq, codonTable);
+	}
+
+
+	// Get numerical code describing the model type
+	public int getModelID()
+	{
+		return 0;
+	}
+ 
+ 	// interface Report
+ 
+	public void report(PrintWriter out)
+	{
+		out.println("Model of substitution: YANG (Yang, ????)");
+		
+		out.print("Parameter kappa: ");
+		format.displayDecimal(out, kappa, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, kappaSE, 2);
+			out.print(")");
+		}
+		out.println();
+	
+		out.print("Parameter omega: ");
+		format.displayDecimal(out, omega, 2);
+		if (showSE)
+		{
+			out.print("  (S.E. ");
+			format.displayDecimal(out, omegaSE, 2);
+			out.print(")");
+		}
+		out.println();
+
+		printFrequencies(out);
+		printRatios(out);
+	}	
+
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return 2;
+	}
+	
+	public void setParameter(double param, int n)
+	{
+		switch(n)
+		{
+			case 0: kappa = param; break;
+			case 1: omega = param; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+				
+		makeYangModel();
+		fromQToR();
+	}
+
+	public double getParameter(int n)
+	{
+		double value;
+		
+		switch(n)
+		{
+			case 0: value = kappa; break;
+			case 1: value = omega; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+				
+		return value;
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		switch(n)
+		{
+			case 0: kappaSE = paramSE; break;
+			case 1: omegaSE = paramSE; break;
+			
+			default: throw new IllegalArgumentException();
+		}
+		
+		showSE = true;
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0.0001;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return 100.0;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return 1.0;
+	}
+	
+
+	//
+	// Private stuff
+	// 
+
+	private boolean showSE;
+	private double kappa, omega;
+	private double kappaSE, omegaSE;
+	private byte[] rateMap;
+
+	// Make REV model
+	private void makeYangModel()
+	{
+		int numRates = ( dimension * (dimension - 1) ) / 2;
+		rateMap = new byte[numRates];
+	
+//	NewArray(rateMap, char, numRates);
+	
+		int u, v, rateClass;
+		char aa1, aa2;
+		char[] codon1, codon2;
+		GeneralizedCodons generalizedCodons = new GeneralizedCodons();
+		
+		for (u = 0; u < dimension; u++) {
+			codon1 = generalizedCodons.getCodonFromCodonIndex(u);
+
+			for (v = u+1; v < dimension; v++) {
+				codon2 = generalizedCodons.getCodonFromCodonIndex(v);
+				
+				rateClass = -1;
+				if (codon1[0] != codon2[0]) {
+					if ( (codon1[0] == 'A' && codon2[0] == 'G') || 
+						(codon1[0] == 'G' && codon2[0] == 'A') || // A <-> G
+						(codon1[0] == 'C' && codon2[0] == 'T') || 
+						(codon1[0] == 'T' && codon2[0] == 'C') )  // C <-> T
+						rateClass = 1; // Transition
+					else
+						rateClass = 2; // Transversion
+				}
+				if (codon1[1] != codon2[1]) {
+					if (rateClass == -1) {
+						if ( (codon1[1] == 'A' && codon2[1] == 'G') || 
+							(codon1[1] == 'G' && codon2[1] == 'A') || // A <-> G
+							(codon1[1] == 'C' && codon2[1] == 'T') || 
+							(codon1[1] == 'T' && codon2[1] == 'C') )  // C <-> T
+							rateClass = 1; // Transition
+						else
+							rateClass = 2; // Transversion
+					} else 
+						rateClass = 0; // Codon changes at more than one position
+				}
+				if (codon1[2] != codon2[2]) {
+					if (rateClass == -1) {
+						if ( (codon1[2] == 'A' && codon2[2] == 'G') || 
+							(codon1[2] == 'G' && codon2[2] == 'A') || // A <-> G
+						 	(codon1[2] == 'C' && codon2[2] == 'T') || 
+							(codon1[2] == 'T' && codon2[2] == 'C') )  // C <-> T
+							rateClass = 1; // Transition
+						else
+							rateClass = 2; // Transversion
+					} else 
+						rateClass = 0; // Codon changes at more than one position
+				}
+				 					 
+	 			if (rateClass != 0) {
+					aa1 = codonTable.getAminoAcidChar(codon1);
+					aa2 = codonTable.getAminoAcidChar(codon2);
+					if (aa1 == AminoAcids.TERMINATE_CHARACTER || aa2 == AminoAcids.TERMINATE_CHARACTER)
+						rateClass = 0; // Can't change to a stop codon
+					else if (aa1 != aa2)
+						rateClass += 2; // Is a non-synonymous change
+				}
+				
+				switch (rateClass) {
+					case 0: rate[u][v] = 0.0; break;	// codon changes in more than one codon position
+					case 1: rate[u][v] = kappa; break;			// synonymous transition
+					case 2: rate[u][v] = 1.0; break;			// synonymous transversion
+					case 3: rate[u][v] = kappa * omega; break;	// non-synonymous transition
+					case 4: rate[u][v] = omega; break;			// non-synonymous transversion
+				}
+				rate[v][u] = rate[u][v];
+			}
+			rate[u][u] = 0.0;
+		}
+	}
+	
+	// genetic code used to figure out stop codons
+	private CodonTable codonTable;
+
+}
+
diff --git a/LibrarySource/pal/substmodel/makefile b/LibrarySource/pal/substmodel/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/substmodel/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/substmodel/package.html b/LibrarySource/pal/substmodel/package.html
new file mode 100644
index 0000000..9d91c60
--- /dev/null
+++ b/LibrarySource/pal/substmodel/package.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+Classes describing substitution models, i.e. rate matrices (e.g., the HKY
+matrix) and rate heterogeneity distributions (e.g., the discrete Gamma
+distribution), as well as a class for conveniently computing transition
+probabilities. 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/tree/ClockTree.java b/LibrarySource/pal/tree/ClockTree.java
new file mode 100644
index 0000000..0175826
--- /dev/null
+++ b/LibrarySource/pal/tree/ClockTree.java
@@ -0,0 +1,143 @@
+// ClockTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+
+
+/**
+ * provides parameter interface to a clock tree
+ * (parameters are the minimal node height differences
+ * at each internal node)
+ *
+ * @version $Id: ClockTree.java,v 1.10 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class ClockTree extends ParameterizedTree
+{
+	//
+	// Public stuff
+	//
+
+	public ClockTree() {}
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like tree (parameters
+	 * are the minimal node height differences at each internal node).
+	 * <p>
+	 * <em>This parameterisation of a clock-tree, ensuring that
+	 * all parameters are independent of each other is due to
+         * Andrew Rambaut (personal communication).</em>
+	 */
+	public ClockTree(Tree t)
+	{
+		setBaseTree(t);	
+		
+		if (getRoot().getChildCount() < 2)
+		{
+			throw new IllegalArgumentException(
+			"The root node must have at least two childs!");
+		}
+						
+		parameter = new double[getNumParameters()];
+		
+		for (int i = 0; i < parameter.length; i++)
+		{
+			parameter[i] = getDefaultValue(i);
+		}
+
+		
+		// init
+		parameters2Heights();
+		NodeUtils.heights2Lengths(getRoot());
+	}
+	
+	/** make clocktree consistent with branch lengths */
+	public void update()
+	{
+		createNodeList();
+		NodeUtils.lengths2Heights(getRoot());
+		heights2parameters();
+	}
+	
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return getInternalNodeCount();
+	}
+
+	public void setParameter(double param, int n)
+	{
+		parameter[n] = param;
+		
+		parameters2Heights();
+		NodeUtils.heights2Lengths(getRoot());
+	}
+
+	public double getParameter(int n)
+	{
+		return parameter[n];
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return; // we are not interested in these SEs
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return BranchLimits.MINARC;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return BranchLimits.MAXARC;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return BranchLimits.DEFAULT_LENGTH;
+	}
+	
+	//
+	// Private stuff
+	//
+
+	protected void parameters2Heights()
+	{
+		// nodes have been stored by a post-order traversal
+		
+		for (int i = 0; i < getExternalNodeCount(); i++)
+		{
+			getExternalNode(i).setNodeHeight(0.0);
+		}
+		
+		for (int i = 0; i < getInternalNodeCount(); i++)
+		{
+			Node node = getInternalNode(i);
+			node.setNodeHeight(parameter[i] + NodeUtils.findLargestChild(node));
+		}
+	}
+	
+	protected void heights2parameters()
+	{
+		for (int i = 0; i < getInternalNodeCount(); i++)
+		{
+			Node node = getInternalNode(i);
+			parameter[i] = node.getNodeHeight()-NodeUtils.findLargestChild(node);
+		}
+	}
+	
+	protected double[] parameter;
+}
+
diff --git a/LibrarySource/pal/tree/DatedTipsClockTree.java b/LibrarySource/pal/tree/DatedTipsClockTree.java
new file mode 100644
index 0000000..dc7bead
--- /dev/null
+++ b/LibrarySource/pal/tree/DatedTipsClockTree.java
@@ -0,0 +1,446 @@
+// DatedTipsClockTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+
+
+/**
+ * provides parameter interface to a clock tree with dated tips,
+ * following A. Rambaut. 2000. Bioinformatics 16:395-399.
+ * (parameters are the minimal node height differences
+ * at each internal node and the evolutionary rate)
+ *
+ * @version $Id: DatedTipsClockTree.java,v 1.12 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class DatedTipsClockTree extends ParameterizedTree
+	implements java.io.Serializable {
+
+	//
+	// Public stuff
+	//
+
+
+	/**
+	 * Constructor without TimeOrderCharacterData.
+	 * Dates are extracted from labels.
+	 */
+	public DatedTipsClockTree(Tree t) {
+		this(t,  null, true);
+	}
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like tree with dated tips (parameters
+	 * are the minimal node height differences at each internal node
+	 * and the rate).
+	 *
+	 * This constructor uses the standard definition of a rate (default value = 0, min value = 0, max value = 1)
+	 * and does include the rate as the parameter
+	 * <p>
+	 * <em>This parameterisation of a clock-tree, ensuring that
+	 * all parameters are independent of each other is due to
+	 * Andrew Rambaut (personal communication).</em>
+	 */
+	public DatedTipsClockTree(Tree t, TimeOrderCharacterData tocd, boolean useDefaultParameters)
+	{
+		this(t,new ParameterizedDouble(0,0,1),tocd,useDefaultParameters,true);
+	}
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like tree with dated tips (parameters
+	 * are the minimal node height differences at each internal node
+	 * and the rate).
+	 * This constructor does not include the rate as the parameter
+	 * <p>
+	 * <em>This parameterisation of a clock-tree, ensuring that
+	 * all parameters are independent of each other is due to
+				 * Andrew Rambaut (personal communication).</em>
+	 */
+	public DatedTipsClockTree(Tree t, ParameterizedDouble rate, TimeOrderCharacterData tocd, boolean useDefaultParameters)
+	{
+		this(t,rate,tocd,useDefaultParameters,false);
+	}
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like tree with dated tips (parameters
+	 * are the minimal node height differences at each internal node
+	 * and the rate).
+	 * <p>
+	 * <em>This parameterisation of a clock-tree, ensuring that
+	 * all parameters are independent of each other is due to
+				 * Andrew Rambaut (personal communication).</em>
+	 */
+	public DatedTipsClockTree(Tree t, ParameterizedDouble rate, TimeOrderCharacterData tocd, boolean useDefaultParameters, boolean includeRateAsParameter)
+	{
+		this.includeRateAsParameter_ = includeRateAsParameter;
+		this.rate = rate;
+		setBaseTree(t);
+		this.tocd = tocd;
+
+		if (getRoot().getChildCount() < 2)
+		{
+			throw new IllegalArgumentException(
+			"The root node must have at least two childs!");
+		}
+
+		parameter = new double[getInternalNodeCount()];
+
+		date = new double[t.getExternalNodeCount()];
+		getDates();
+
+		if (useDefaultParameters) {
+			for (int i = 0; i < parameter.length; i++) {
+				parameter[i] = getDefaultValue(i);
+			}
+		} else {
+			// assumes that the tree heights are already valid
+			// DatedTipClockTree heights.
+			// extracts rate on this assumption with aid of
+			// TimeOrderCharacterData.
+
+			heights2parameters();
+
+			boolean found = false;
+			int i = 0;
+			while ((i < getExternalNodeCount()) && !found) {
+
+				String name = getExternalNode(i).getIdentifier().getName();
+
+				int index = tocd.getIdGroup().whichIdNumber(name);
+
+				double time = tocd.getTime(index);
+
+				if (time > 0.0) {
+					double height = getExternalNode(i).getNodeHeight();
+
+					rate.setValue(height / time);
+					System.out.println("rate = " + rate);
+					found = true;
+				}
+				i += 1;
+			}
+			if (!found) {
+				rate.setValue(0.0);
+			}
+		}
+
+
+		// init
+		parameters2Heights();
+		NodeUtils.heights2Lengths(getRoot());
+	}
+	
+	/** make parameters consistent with branch lengths and rate parameter */
+	public void update()
+	{
+		createNodeList();
+		getDates(); // order of tips may have changed!
+		NodeUtils.lengths2Heights(getRoot());
+		heights2parameters();
+	}
+	
+	// interface Parameterized (Rambaut paremeterisation)
+
+	public int getNumParameters()
+	{
+		return getInternalNodeCount()+(includeRateAsParameter_ ? 1 : 0);
+	}
+
+	public void setParameter(double param, int n)
+	{
+		if (n < getInternalNodeCount())
+		{
+			parameter[n] = param;
+		}
+		else
+		{
+			rate.setValue(param);
+		}
+		
+		parameters2Heights();
+		NodeUtils.heights2Lengths(getRoot());
+	}
+
+	public double getParameter(int n)
+	{
+		if (n < getInternalNodeCount())
+		{
+			return parameter[n];
+		}
+		else
+		{
+			return rate.getValue();
+		}
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		// we are only interested in SE of rate
+		if (n < getInternalNodeCount())
+		{
+			// do nothing
+		}
+		else
+		{
+			rate.setSE(paramSE);
+		}
+		return;
+	}
+
+	/** return standard error of parameter */
+	public double getParameterSE(int n)
+	{
+		// we are only interested in SE of rate
+		if (n < getInternalNodeCount())
+		{
+			return 0.0;
+		}
+		else
+		{
+			return rate.getSE();
+		}
+	}
+
+
+	public double getLowerLimit(int n)
+	{
+		if (n < getInternalNodeCount())
+		{
+			return BranchLimits.MINARC;
+		}
+		else
+		{
+			return rate.getLowerLimit();
+		}
+	}
+
+	public double getUpperLimit(int n)
+	{
+		if (n < getInternalNodeCount())
+		{
+			return BranchLimits.MAXARC;
+		}
+		else
+		{
+			return rate.getUpperLimit(); // subst. per unit time
+		}
+	}
+
+	public double getDefaultValue(int n)
+	{
+		if (n < getInternalNodeCount())
+		{
+			return BranchLimits.DEFAULT_LENGTH;
+		}
+		else
+		{
+			return rate.getDefaultValue(); // contemporaneous tips
+		}
+	}
+	
+	/** 
+	 * set rate (and thus node heights and branch lengths of leaves) without
+	 * changing all other node heights and branch lengths
+	 */
+	public void setRate(double r)
+	{
+		rate.setValue(r);
+		for (int i = 0; i < getExternalNodeCount(); i++)
+		{
+			Node leaf = getExternalNode(i);
+			double h = (maxDate-date[i])*rate.getValue();
+			leaf.setNodeHeight(Math.abs(h));
+			double hp = leaf.getParent().getNodeHeight();
+			leaf.setBranchLength(Math.abs(hp-h));
+		}
+	}
+
+	/** 
+	 * get rate 
+	 */
+	public double getRate()
+	{
+		return rate.getValue();
+	}
+
+
+	/** 
+	 * set rate SE
+	 */
+	public void setRateSE(double rSE)
+	{
+		rate.setSE(rSE);
+	}
+
+
+	/**
+	 * find max. rate (for setRate) allowed by current node heights
+	 */
+	public double getMaxRate()
+	{
+		double maxRate = 0;
+
+		for (int i = 0; i < getExternalNodeCount(); i++)
+		{
+			Node leaf = getExternalNode(i);
+			
+			// maximum rate for this leaf
+			double maxRateLeaf = (leaf.getParent().getNodeHeight()-BranchLimits.MINARC)/(maxDate-date[i]);
+			
+			if (i == 0 || maxRateLeaf < maxRate)
+			{
+				maxRate = maxRateLeaf;
+			}
+		}
+		
+		return maxRate;
+	}
+
+	/**
+	 * Gets the TimeOrderCharacterData
+	 */
+	public TimeOrderCharacterData getTimeOrderCharacterData() {
+		if (tocd != null) {
+			return tocd;
+		} else {
+			//extract from tree.
+			//WHAT UNITS TO USE!? Defaulting to EXPECTED_SUBSTITUTIONS
+			
+			TimeOrderCharacterData tempTOCD = 
+				new TimeOrderCharacterData(TreeUtils.getLeafIdGroup(this),
+					Units.EXPECTED_SUBSTITUTIONS);
+			tempTOCD.setTimes(date, Units.EXPECTED_SUBSTITUTIONS, true);
+
+			return tempTOCD;
+		}
+	}	
+
+	//
+	// Private stuff
+	//
+
+	private void parameters2Heights()
+	{
+		// nodes have been stored by a post-order traversal
+		
+		for (int i = 0; i < getExternalNodeCount(); i++)
+		{
+			getExternalNode(i).setNodeHeight(  (maxDate-date[i])*rate.getValue()  );
+		}
+		
+		for (int i = 0; i < getInternalNodeCount(); i++)
+		{
+			Node node = getInternalNode(i);
+			node.setNodeHeight(parameter[i] + NodeUtils.findLargestChild(node));
+		}
+	}
+	
+	private void heights2parameters()
+	{
+		for (int i = 0; i < getInternalNodeCount(); i++)
+		{
+			Node inode = getInternalNode(i);
+			parameter[i] = inode.getNodeHeight()-NodeUtils.findLargestChild(inode);
+		}
+	}
+
+	private void getDates()
+	{
+
+		double maxTime = 0.0;
+		if (tocd != null) {
+			for (int i = 0; i < date.length; i++) {
+				if (tocd.getTime(i) > maxTime) {
+					maxTime = tocd.getTime(i);
+				}
+			}
+		}
+
+		for (int i = 0; i < getExternalNodeCount(); i++)
+		{
+			if (tocd == null) {
+				// extract dates from sequence identifiers
+				date[i] = extractDate(getExternalNode(i).getIdentifier().getName());
+			} else {
+
+				if (tocd.hasTimes()) {
+					String name = getExternalNode(i).getIdentifier().getName();	
+				
+					int index = tocd.getIdGroup().whichIdNumber(name);
+					
+					//times are measured backwards from zero at most recent tip. 
+					// this needs to be converted to forward-time dates starting
+					// from time zero at oldest tip.
+					
+					date[i] = maxTime - tocd.getTime(index);
+				} else {
+					//no times available 
+					throw new IllegalArgumentException("TimeOrderCharacterData does not have any times!");
+				}
+			}
+		} 
+		
+		// find maximum and minimum date
+		minDate = maxDate = date[0];
+		for (int i = 1; i < getExternalNodeCount(); i++)
+		{
+			if (date[i] > maxDate) maxDate = date[i];
+			if (date[i] < minDate) minDate = date[i];
+		}
+		
+		// check for equality of dates
+		if (minDate == maxDate)
+		{
+			throw new IllegalArgumentException("Tip dates must not be the same for all tips");
+		}	
+	}
+
+	private double extractDate(String string)
+	{
+		StringBuffer buffer = new StringBuffer();
+		
+		int len = string.length();
+		
+		boolean readDot = false;
+		for (int i = len-1; i > -1; i--)
+		{
+			char c = string.charAt(i);
+			
+			if ( !Character.isDigit(c) &&  !(c == '.' && !readDot) ) break;
+			buffer.append(c);
+			if (c == '.') readDot = true;
+			
+		}
+		buffer.reverse();
+		
+		String date = buffer.toString();
+		
+		if (date.length() == 0)
+		{
+			return 0.0;
+		}
+		else
+		{
+			return (Double.valueOf(buffer.toString())).doubleValue();
+		}
+	}
+	
+	private double[] parameter;
+	private ParameterizedDouble rate;
+	private boolean includeRateAsParameter_; /** If true than the rate is included as a parameter of this object */ 
+	private double minDate, maxDate;
+	private double[] date;
+	private TimeOrderCharacterData tocd;
+}
+
diff --git a/LibrarySource/pal/tree/LogParameterizedTree.java b/LibrarySource/pal/tree/LogParameterizedTree.java
new file mode 100644
index 0000000..d6d9023
--- /dev/null
+++ b/LibrarySource/pal/tree/LogParameterizedTree.java
@@ -0,0 +1,100 @@
+// LogParameterizedTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+
+
+/**
+ * This class logarithmically transforms tree parameters.
+ * Hopefully this makes the function look more like a quadratic
+ * for the optimizer!
+ *
+ * @version $Id: LogParameterizedTree.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class LogParameterizedTree
+	extends ParameterizedTree
+{
+	//
+	// Public stuff
+	//
+
+	ParameterizedTree params;
+	
+	private double[] logMins;
+	private double[] logMaxs;
+	private double[] logDefaults;
+	
+
+	/**
+	 * Takes a parameterized object and transforms 
+	 * the parameters logarithmically.
+	 */
+	public LogParameterizedTree(ParameterizedTree params)
+	{
+		setBaseTree(params);		
+		
+		this.params = params;
+	
+		setUnits(params.getUnits());
+		
+		logMins = new double[params.getNumParameters()];
+		logMaxs = new double[params.getNumParameters()];
+		logDefaults = new double[params.getNumParameters()];
+
+		for (int i = 0; i < logMins.length; i++) {
+			logMins[i] = Math.log(params.getLowerLimit(i));
+			logMaxs[i] = Math.log(params.getUpperLimit(i));
+			logDefaults[i] = Math.log(params.getDefaultValue(i));
+		}
+	}
+
+		// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return params.getNumParameters();
+	}
+
+	public void setParameter(double logParam, int n)
+	{
+		// - logMins scales the value to lower bound of 0
+		double realParam = Math.exp(logParam + logMins[n]);
+		
+		params.setParameter(realParam, n);
+	}
+
+	public double getParameter(int n)
+	{
+		return Math.log(params.getParameter(n)) - logMins[n];
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		return; // DEBUG - not yet done
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return 0;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return logMaxs[n] - logMins[n];
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return logDefaults[n] - logMins[n];
+	}
+}
+
diff --git a/LibrarySource/pal/tree/MutationRateModelTree.java b/LibrarySource/pal/tree/MutationRateModelTree.java
new file mode 100644
index 0000000..dee9c10
--- /dev/null
+++ b/LibrarySource/pal/tree/MutationRateModelTree.java
@@ -0,0 +1,175 @@
+// MutationRateModelTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+//
+
+package pal.tree;
+
+import pal.misc.*;
+import pal.mep.*;
+
+
+import pal.util.*;
+
+/**
+ * Provides parameter interface to any clock-like tree with
+ * serially sampled tips (parameters are the minimal node height differences
+ * at each internal node). Any mutation rate model can be used. <P>
+ * @see pal.mep.MutationRateModel
+ *
+ * @version $Id: MutationRateModelTree.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class MutationRateModelTree extends ParameterizedTree {
+
+	//
+	// Public stuff
+	//
+
+	TimeOrderCharacterData tocd = null;
+	MutationRateModel model = null;
+	int numParameters;
+	
+	//private
+
+	private double MIN_MU = 1e-12;
+	private double MIN_DELTA = 1e-12;
+	private double lnL = 0.0; 
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for a clock-like tree (parameters
+	 * are the minimal node height differences at each internal node).
+	 * <p>
+	 * <em>This parameterisation of a clock-tree, ensuring that
+	 * all parameters are independent of each other is due to
+	 * Andrew Rambaut (personal communication).</em>
+	 */
+	public MutationRateModelTree(Tree t, TimeOrderCharacterData tocd, MutationRateModel model) throws RuntimeException {
+
+  		setBaseTree(t);
+	
+		this.tocd = tocd;
+		this.model = model;
+		
+		if (t.getRoot().getChildCount() < 2) {
+			throw new RuntimeException(
+				"The root node must have at least two childs!");
+		}
+		
+		NodeUtils.heights2Lengths(getRoot());
+		
+		numParameters = getInternalNodeCount() + model.getNumParameters();
+		
+		
+		if (!tocd.hasTimes()) {
+			throw new RuntimeException("Must have times!");
+		}
+		
+		parameter = new double[numParameters - model.getNumParameters()];
+		heights2parameters();
+	}
+	
+	// interface Parameterized
+	
+	public int getNumParameters() {
+		return numParameters;
+	}
+   
+	public void setParameter(double param, int n) {
+	
+		if (n < getInternalNodeCount()) {
+			parameter[n] = param;
+		} else model.setParameter(param, n - getInternalNodeCount());
+
+		// call this parameter2Heights
+		parameters2Heights();
+		NodeUtils.heights2Lengths(getRoot());
+	}
+	
+	public double getParameter(int n) {
+		if (n < getInternalNodeCount()) {
+			return parameter[n];
+		} else {
+			return model.getParameter(n - getInternalNodeCount());
+		}
+	}
+
+	/**
+	 * Returns lower limit of parameter estimate.
+	 */
+	public double getLowerLimit(int n) {
+		if (n < getInternalNodeCount()) {
+			return BranchLimits.MINARC;
+		} else {
+			return MIN_MU;
+		}
+	}
+
+	//
+	// Private stuff
+	//
+	
+	private double[] parameter;
+
+	public double getDefaultValue(int n) {
+		return BranchLimits.DEFAULT_LENGTH;
+	}
+
+	public void setParameterSE(double paramSE, int n) {
+		return; // DEBUG - not yet done
+	}
+
+	public double getUpperLimit(int n) {
+		return BranchLimits.MAXARC;
+	}
+
+	/**
+	 * returns mu
+	 */
+	public MutationRateModel getMutationRateModel() {
+		return model;
+	}
+
+	protected void parameters2Heights() {
+		// nodes have been stored by a post-order traversal
+
+		int index;
+	
+		for (int i = 0; i < getExternalNodeCount(); i++) {
+	
+			index = tocd.getIdGroup().whichIdNumber(getExternalNode(i).getIdentifier().getName());
+			//System.err.println(index + ":" + i);
+
+			getExternalNode(i).setNodeHeight(model.getExpectedSubstitutions(tocd.getTime(index)));	
+		}
+
+		// this could be more efficient
+		for (int i = 0; i < getInternalNodeCount(); i++) {
+			Node node = getInternalNode(i);
+			node.setNodeHeight(parameter[i] + NodeUtils.findLargestChild(node));
+		}
+	}
+
+	protected void heights2parameters() {
+		for (int i = 0; i < getInternalNodeCount(); i++) {
+			Node node = getInternalNode(i);
+			parameter[i] = node.getNodeHeight()-NodeUtils.findLargestChild(node);
+		}
+
+		// need to convert heights to model parameters somehow!	
+	}	
+
+	public void setLnL(double lnL) {
+		this.lnL = lnL; 
+	}
+
+	public double getLnL() {
+		return lnL;
+	}
+}
+
diff --git a/LibrarySource/pal/tree/NeighborJoiningTree.java b/LibrarySource/pal/tree/NeighborJoiningTree.java
new file mode 100644
index 0000000..164e1d1
--- /dev/null
+++ b/LibrarySource/pal/tree/NeighborJoiningTree.java
@@ -0,0 +1,209 @@
+// NeighborJoiningTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+// computational complexity O(numSeqs^3)
+
+
+package pal.tree;
+
+import pal.distance.*;
+
+
+/**
+ * constructs a neighbor-joining tree from pairwise distances
+ * 
+ * @version $Id: NeighborJoiningTree.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class NeighborJoiningTree extends SimpleTree
+{
+	//
+	// Public stuff
+	//	
+
+	/**
+	 * construct NJ tree
+	 *
+	 * @param m distance matrix
+	 */
+	public NeighborJoiningTree(DistanceMatrix m)
+	{
+		if (m.numSeqs < 3)
+		{
+			new IllegalArgumentException("LESS THAN 3 TAXA IN DISTANCE MATRIX");
+		}
+		if (!m.isSymmetric())
+		{
+			new IllegalArgumentException("UNSYMMETRIC DISTANCE MATRIX");
+		}
+		
+		init(m);
+
+		//while (numClusters > 3)
+		while (true)
+		{
+			findNextPair();
+			newBranchLengths();
+			if (numClusters == 3)
+			{
+				break;
+			}
+			newCluster();
+		}
+		
+		finish();
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private int numClusters;
+	private Node newCluster;
+	private int besti, abi;
+	private int bestj, abj;
+	private int[] alias;
+	private double[][] distance;
+	private double[] r;
+	private double scale;	
+
+	private double getDist(int a, int b)
+	{
+		return distance[alias[a]][alias[b]];
+	}
+	
+	private void init(DistanceMatrix m)
+	{
+		numClusters = m.numSeqs;
+
+		distance = new double[numClusters][numClusters];
+		for (int i = 0; i < numClusters; i++)
+		{
+			for (int j = 0; j < numClusters; j++)
+			{
+				distance[i][j] = m.distance[i][j];
+			}
+		}
+
+		for (int i = 0; i < numClusters; i++)
+		{
+			Node tmp = NodeFactory.createNode();
+			tmp.setIdentifier(m.getIdentifier(i));
+			getRoot().addChild(tmp);
+		}
+		
+		alias = new int[numClusters];
+		for (int i = 0; i < numClusters; i++)
+		{
+			alias[i] = i;
+		}
+		
+		r = new double[numClusters];
+	}
+
+	private void finish()
+	{
+		if (besti != 0 && bestj != 0)
+		{
+			getRoot().getChild(0).setBranchLength(updatedDistance(besti, bestj, 0));
+		}
+		else if (besti != 1 && bestj != 1)
+		{
+			getRoot().getChild(1).setBranchLength(updatedDistance(besti, bestj, 1));
+		}
+		else
+		{
+			getRoot().getChild(2).setBranchLength(updatedDistance(besti, bestj, 2));
+		}
+		distance = null;
+
+		// make node heights available also
+		NodeUtils.lengths2Heights(getRoot());
+	}
+
+	private void findNextPair()
+	{
+		for (int i = 0; i < numClusters; i++)
+		{
+			r[i] = 0;
+			for (int j = 0; j < numClusters; j++)
+			{
+				r[i] += getDist(i,j);
+			}
+		}
+
+		besti = 0;
+		bestj = 1;
+		double smax = -1.0;
+		scale = 1.0/(numClusters-2);
+		for (int i = 0; i < numClusters-1; i++)
+		{
+			for (int j = i+1; j < numClusters; j++)
+			{
+				double sij = (r[i] + r[j] ) * scale - getDist(i, j);
+			
+				if (sij > smax)
+				{
+					smax = sij;
+					besti = i;
+					bestj = j;
+				}
+			}
+		}
+		abi = alias[besti];
+		abj = alias[bestj];
+	}
+
+	private void newBranchLengths()
+	{
+		double dij = getDist(besti, bestj);
+		double li = (dij + (r[besti]-r[bestj])*scale)*0.5;
+		double lj = dij - li; // = (dij + (r[bestj]-r[besti])*scale)*0.5
+
+		getRoot().getChild(besti).setBranchLength(li);
+		getRoot().getChild(bestj).setBranchLength(lj);
+	}
+
+	private void newCluster()
+	{
+		// Update distances
+		for (int k = 0; k < numClusters; k++)
+		{
+			if (k != besti && k != bestj)
+			{
+				int ak = alias[k];	
+				distance[ak][abi] = distance[abi][ak] = updatedDistance(besti, bestj, k);
+			}
+		}
+		distance[abi][abi] = 0.0;
+		
+		// Replace besti with new cluster
+		NodeUtils.joinChilds(getRoot(), besti, bestj);
+		
+		// Update alias
+		for (int i = bestj; i < numClusters-1; i++)
+		{
+			alias[i] = alias[i+1];
+		}
+		
+		numClusters--;
+	}
+	
+	/**
+	 * compute updated distance between the new cluster (i,j)
+	 * to any other cluster k
+	 */
+	private double updatedDistance(int i, int j, int k)
+	{
+		return (getDist(k, i) + getDist(k, j) - getDist(i, j))*0.5;
+	}
+}
+
diff --git a/LibrarySource/pal/tree/Node.java b/LibrarySource/pal/tree/Node.java
new file mode 100644
index 0000000..c965100
--- /dev/null
+++ b/LibrarySource/pal/tree/Node.java
@@ -0,0 +1,138 @@
+// Node.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import java.io.*;
+import pal.io.*;
+
+
+/**
+ * interface for a node (includes branch) in a binary/non-binary
+ * rooted/unrooted tree
+ *
+ * @version $Id: Node.java,v 1.17 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ * 
+ */
+
+public interface Node extends Serializable {
+
+
+	/** Returns the parent node of this node. */
+	Node getParent();
+
+	/** Set the parent node of this node. */
+	void setParent(Node node);
+	
+	/** Returns the sequence at this node, in the form an array of bytes. */
+	byte[] getSequence();
+
+	/** Sets the sequence using an array of bytes. */
+	void setSequence(byte[] array);
+
+	/** return the index of this node */
+	int getNumber();
+
+	/** set the number of this node */
+	void setNumber(int number);
+
+	/** Get the length of the branch attaching this node to its parent. */
+	double getBranchLength();
+	
+	/** Set the length of the branch attaching this node to its parent. */
+	void setBranchLength(double value);
+
+	/** Get the length SE of the branch attaching this node to its parent. */
+	double getBranchLengthSE();
+
+	/** Set the length SE of the branch attaching this node to its parent. */
+	void setBranchLengthSE(double value);
+
+	/** Get the height of this node relative to the most recent node. */
+	double getNodeHeight();
+
+	/** Set the height of this node relative to the most recent node. */
+	void setNodeHeight(double value);
+
+	/** Set the height SE of this node relative to the most recent node. */
+	void setNodeHeightSE(double value);
+
+	/** Get the height SE of this node relative to the most recent node. */
+	double getNodeHeightSE();
+
+
+	/** Returns the identifier for this node. */
+	Identifier getIdentifier();
+
+	/** Set identifier for this node. */
+	Identifier setIdentifier(Identifier id);
+
+	/**
+	 * Returns the number of children this node has.
+	 */
+	int getChildCount();
+		
+	/**
+	 * check whether this node is an external node
+	 *
+	 * @return result (true or false)
+	 */
+	boolean isLeaf();
+	
+	/**
+	 * check whether this node is a root node 
+	 *
+	 * @return result (true or false)
+	 */
+	boolean isRoot();
+
+	/**
+	 * get child node
+	 *
+	 * @param n number of child
+	 *
+	 * @return child node
+	 */ 
+	Node getChild(int n);
+
+	/**
+	 * set child node
+	 *
+	 * @param n number
+	 * @node node new child node
+	 */
+	void setChild(int n, Node node);
+	
+	/**
+	 * add new child node
+	 *
+	 * @param c new child node
+	 */
+	void addChild(Node c);
+
+	/**
+	 * add new child node (insertion at a specific position)
+	 *
+	 * @param c new child node
+	 + @param pos position
+	 */
+	void insertChild(Node c, int pos);
+
+	
+	/**
+	 * remove child
+	 *
+	 * @param n number of child to be removed
+	 */
+	void removeChild(int n);		
+}
+
diff --git a/LibrarySource/pal/tree/NodeFactory.java b/LibrarySource/pal/tree/NodeFactory.java
new file mode 100644
index 0000000..0aab313
--- /dev/null
+++ b/LibrarySource/pal/tree/NodeFactory.java
@@ -0,0 +1,40 @@
+// NodeFactory.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+
+/**
+ * Creates nodes
+ * <b>
+ * The purpose of this class is to decouple the creation of
+ * a class of type "Node" from its actual implementation.  This
+ * class should be used instead of calling the constructor
+ * of an implementation of "Node"
+ * (at the moment "SimpleNode") as it may change in the future.</b><p>
+ *
+ * Other plans: add features here to recyle old nodes rather than
+ * leaving them to the Java garbage collector
+ *
+ * @author Korbinian Strimmer
+ */
+public class NodeFactory
+{
+	/** create a node */
+	public static Node createNode()
+	{
+		return new SimpleNode();
+	}
+	
+	/** constructor used to clone a node and all children */
+	public static Node createNode(Node node)
+	{
+		return new SimpleNode(node);
+	}
+}
+
diff --git a/LibrarySource/pal/tree/NodeUtils.java b/LibrarySource/pal/tree/NodeUtils.java
new file mode 100644
index 0000000..e37f233
--- /dev/null
+++ b/LibrarySource/pal/tree/NodeUtils.java
@@ -0,0 +1,629 @@
+// NodeUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import java.io.*;
+import pal.io.*;
+import pal.util.*;
+
+/**
+ * Helper routines for dealing with nodes. 
+ *
+ * @version $Id: NodeUtils.java,v 1.14 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class NodeUtils {
+
+	/**
+	 * Converts lengths to heights, *without* assuming contemporaneous
+	 * tips.
+	 */
+	public static void lengths2Heights(Node root) {
+	
+		lengths2Heights(root, getGreatestDistance(root));
+	}
+
+	/**
+	 * Converts lengths to heights, but maintains tip heights.
+	 */
+	public static void lengths2HeightsKeepTips(Node node, boolean useMax) {
+		
+		if (!node.isLeaf()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				lengths2HeightsKeepTips(node.getChild(i), useMax);
+			}
+
+			double totalHL = 0.0;
+			double maxHL = 0.0;
+			double hl = 0.0;
+			double maxH = 0.0;
+			double h = 0.0;
+			for (int i = 0; i < node.getChildCount(); i++) {
+				h = node.getChild(i).getNodeHeight();
+				hl = node.getChild(i).getBranchLength() + h;
+				if (hl > maxHL) maxHL = hl;
+				if (h > maxH) maxH = h;
+				totalHL += hl;
+			}
+			if (useMax) {
+				hl = maxHL; // set parent height to maximum parent height implied by children
+			} else {
+				hl = totalHL /  node.getChildCount(); // get mean parent height
+				if (hl < maxH) hl = maxHL; // if mean parent height is not greater than all children height, fall back on max parent height.
+			}
+			node.setNodeHeight(hl); // set new parent height
+			
+			// change lengths in children to reflect changes.
+			for (int i = 0; i < node.getChildCount(); i++) {
+				h = node.getChild(i).getNodeHeight();
+				node.getChild(i).setBranchLength(hl - h);
+			}
+		}
+	}
+	
+
+	/**
+	 * sets this nodes height value to newHeight and all children's
+	 * height values based on length of branches.
+	 */
+	private static void lengths2Heights(Node node, double newHeight) {
+	
+		if (!node.isRoot()) {
+			newHeight -= node.getBranchLength();
+			node.setNodeHeight(newHeight);
+		} else {
+			node.setNodeHeight(newHeight);
+		}
+		
+		for (int i = 0; i < node.getChildCount(); i++) {
+			lengths2Heights(node.getChild(i), newHeight);
+		} 
+	}
+  
+  	/**
+	 * Exchange field info between two nodes. Specifically
+	 * identifiers, branch lengths, node heights and branch length
+	 * SEs.
+	 */
+	public static void exchangeInfo(Node node1, Node node2) {
+		
+		Identifier swaps;
+		double swapd;
+		
+		swaps = node1.getIdentifier();
+		node1.setIdentifier(node2.getIdentifier());
+		node2.setIdentifier(swaps);
+		
+		swapd = node1.getBranchLength();
+		node1.setBranchLength(node2.getBranchLength());
+		node2.setBranchLength(swapd);
+
+		swapd = node1.getNodeHeight();
+		node1.setNodeHeight(node2.getNodeHeight());
+		node2.setNodeHeight(swapd);
+
+		swapd = node1.getBranchLengthSE();
+		node1.setBranchLengthSE(node2.getBranchLengthSE());
+		node2.setBranchLengthSE(swapd);
+	}
+
+	/**
+	 * determines branch lengths of this and all descendent nodes
+	 * from heights
+	 */
+	public static void heights2Lengths(Node node) {
+		heights2Lengths(node, true); //respect minimum
+	}
+
+	/**
+	 * determines branch lengths of this and all descendent nodes
+	 * from heights
+	 */
+	public static void heights2Lengths(Node node, boolean respectMinimum) {
+	
+		for (int i = 0; i < node.getChildCount(); i++) {
+			heights2Lengths(node.getChild(i));
+		}
+		
+		if (node.isRoot()) {
+			node.setBranchLength(0.0);
+		}
+		else {
+			node.setBranchLength(node.getParent().getNodeHeight() - node.getNodeHeight());
+			if (respectMinimum && (node.getBranchLength() < BranchLimits.MINARC))
+			{
+				node.setBranchLength(BranchLimits.MINARC);
+			}
+		}
+	}
+
+	/**
+	 * determines branch lengths of this node and its immediate descendent nodes
+	 * from heights.
+	 */
+	public static void localHeights2Lengths(Node node, boolean respectMinimum) {
+	
+		for (int i = 0; i < node.getChildCount(); i++) {
+			Node child = node.getChild(i);
+			
+			child.setBranchLength(node.getNodeHeight() - child.getNodeHeight());
+		}
+		
+		if (node.isRoot()) {
+			node.setBranchLength(0.0);
+		}
+		else {
+			node.setBranchLength(node.getParent().getNodeHeight() - node.getNodeHeight());
+			if (respectMinimum && (node.getBranchLength() < BranchLimits.MINARC))
+			{
+				node.setBranchLength(BranchLimits.MINARC);
+			}
+		}
+	}
+
+   
+	/**
+	 * Get the distance to furthest leaf from this nodes parent.
+	 */
+	private static double getGreatestDistance(Node node) {
+		
+		double distance = 0.0;
+		if (!node.isLeaf()) {
+			if (!node.isRoot()) {
+				distance = node.getBranchLength();
+			}
+			double max = getGreatestDistance(node.getChild(0));
+			double posmax = 0.0;
+			for (int i = 1; i < node.getChildCount(); i++) {
+				posmax = getGreatestDistance(node.getChild(i));
+				if (posmax > max) max = posmax;
+			}
+			distance += max;
+	    
+	    		return distance;
+		} else {
+	    		return node.getBranchLength();
+		}
+	}
+
+	/**
+	 * Finds the largest child (in terms of node height).
+	 */
+	public static double findLargestChild(Node node) {
+		// find child with largest height
+		double max = node.getChild(0).getNodeHeight();
+		for (int j = 1; j < node.getChildCount(); j++)
+		{
+			if (node.getChild(j).getNodeHeight() > max)
+			{
+				max = node.getChild(j).getNodeHeight();
+			}
+		}
+		return max;
+	}
+
+	/**
+	 * remove child
+	 *
+	 * @param node child node to be removed
+	 */
+	public static void removeChild(Node parent, Node child)
+	{
+		int rm = -1;
+		for (int i = 0; i < parent.getChildCount(); i++)
+		{
+			if (child == parent.getChild(i))
+			{
+				rm = i;
+				break;
+			}
+		}
+		
+		parent.removeChild(rm);
+	}
+	
+	/**
+	 * remove internal branch (collapse node with its parent)
+	 *
+	 * @param node node associated with internal branch
+	 */
+	public static void removeBranch(Node node)
+	{
+		if (node.isRoot() || node.isLeaf())
+		{
+			throw new IllegalArgumentException("INTERNAL NODE REQUIRED (NOT ROOT)");
+		}
+		
+		Node parent = node.getParent();
+		
+		// add childs of node to parent
+		// (node still contains the link to childs
+		// to allow later restoration)
+		int numChilds = node.getChildCount();
+		for (int i = 0; i < numChilds; i++)
+		{
+			parent.addChild(node.getChild(i));
+		}
+		
+		// remove node from parent
+		// (link to parent is restored and the 
+		// position is stored)
+		int rm = -1;
+		for (int i = 0; i < parent.getChildCount(); i++)
+		{
+			if (node == parent.getChild(i))
+			{
+				rm = i;
+				break;
+			}
+		}
+		parent.removeChild(rm);
+		node.setParent(parent);
+		node.setNumber(rm);
+	}
+
+	/**
+	 * restore internal branch 
+	 *
+	 * @param node node associated with internal branch
+	 */
+	public static void restoreBranch(Node node)
+	{
+		if (node.isRoot() || node.isLeaf())
+		{
+			throw new IllegalArgumentException("INTERNAL NODE REQUIRED (NOT ROOT)");
+		}
+		
+		Node parent = node.getParent();
+		
+		// remove childs of node from parent and make node their parent
+		int numChilds = node.getChildCount();
+		for (int i = 0; i < numChilds; i++)
+		{
+			Node c = node.getChild(i);
+			removeChild(parent, c);
+			c.setParent(node);
+		}
+		
+		// insert node into parent
+		parent.insertChild(node, node.getNumber());
+	}
+
+	
+	
+	/**
+	 * join two childs, introducing a new node/branch in the tree
+	 * that replaces the first child
+	 * 
+	 * @param n1 number of first child
+	 * @param n2 number of second child 
+	 */
+	public static void joinChilds(Node node, int n1, int n2) {
+	
+		if (n1 == n2) {
+			throw new IllegalArgumentException("CHILDREN MUST BE DIFFERENT");
+		}
+				
+		int c1, c2;
+		if (n2 < n1)
+		{
+			c1 = n2;
+			c2 = n1;
+		}
+		else
+		{
+			c1 = n1;
+			c2 = n2;
+		}
+
+		Node newNode = NodeFactory.createNode();
+
+		Node child1 = node.getChild(c1);
+		Node child2 = node.getChild(c2);
+		
+		node.setChild(c1, newNode);
+		newNode.setParent(node);
+		node.removeChild(c2); // now parent of child2 = null
+				
+		newNode.addChild(child1);
+		newNode.addChild(child2);
+	}
+
+	/**
+	 * determine preorder successor of this node
+	 *
+	 * @return next node
+	 */ 
+	public static Node preorderSuccessor(Node node) {
+		
+		Node next = null;
+		
+		if (node.isLeaf()) {
+			Node cn = node, ln = null; // Current and last node
+			
+			// Go up
+			do
+			{
+				if (cn.isRoot())
+				{
+					next = cn;
+					break;
+				}
+				ln = cn;
+				cn = cn.getParent();
+			}
+			while (cn.getChild(cn.getChildCount()-1) == ln);
+				
+			// Determine next node
+			if (next == null)
+			{
+				// Go down one node
+				for (int i = 0; i < cn.getChildCount()-1; i++)
+				{
+					if (cn.getChild(i) == ln)
+					{
+						next = cn.getChild(i+1);
+						break;
+					}
+				}
+			}
+		}
+		else
+		{
+			next = node.getChild(0);
+		}
+		
+		return next;
+	}
+
+	/**
+	 * determine postorder successor of a node
+	 *
+	 * @return next node
+	 */ 
+	public static Node postorderSuccessor(Node node) {
+		
+		Node cn = null;
+		Node parent = node.getParent();
+		
+		if (node.isRoot())
+		{
+			cn = node;
+		}
+		else
+		{
+			
+			// Go up one node
+			if (parent.getChild(parent.getChildCount()-1) == node) {
+				return parent;
+			}
+			// Go down one node
+			for (int i = 0; i < parent.getChildCount()-1; i++)
+			{
+				if (parent.getChild(i) == node)
+				{
+					cn = parent.getChild(i+1);
+					break;
+				}
+			}
+		}
+		
+		// Go down until leaf
+		while (cn.getChildCount() > 0)
+		{
+				
+			cn = cn.getChild(0);
+		}
+		
+		return cn;
+	}
+
+	/**
+	 * prints node in New Hamshire format.
+	 */
+	static void printNH(PrintWriter out, Node node, 
+		boolean printLengths, boolean printInternalLabels) {
+		
+		printNH(out, node, printLengths, printInternalLabels, 0);
+	}
+
+	
+	private static int printNH(PrintWriter out, Node node,
+		boolean printLengths, boolean printInternalLabels, int column) {
+		
+		column = breakLine(out, column);
+
+		if (!node.isLeaf())
+		{
+			out.print("(");
+			column++;
+			
+			for (int i = 0; i < node.getChildCount(); i++)
+			{
+				if (i != 0)
+				{
+					out.print(",");
+					column++;
+				}
+				
+				column = printNH(out, node.getChild(i), printLengths, printInternalLabels, column);
+			}
+			
+			out.print(")");
+			column++;
+		}
+		
+		if (!node.isRoot())
+		{
+			if (node.isLeaf() || printInternalLabels)
+			{
+				column = breakLine(out, column);
+		
+				String id = node.getIdentifier().toString();
+				out.print(id);
+				column += id.length();
+			}
+
+			if (printLengths)
+			{
+				out.print(":");
+				column++;
+		
+				column = breakLine(out, column);
+		
+				column += FormattedOutput.getInstance().displayDecimal(out, node.getBranchLength(), 7);
+			}
+		}
+		
+		return column;
+	}
+
+	private static int breakLine(PrintWriter out, int column)
+	{
+		if (column > 70)
+		{
+			out.println();
+			column = 0;
+		}
+		
+		return column;
+	}
+
+	/**
+	 * Returns the first node in this tree that has the
+	 * required identifier.
+	 */
+	public static Node findByIdentifier(Node node, Identifier identifier) {
+
+		Log.getDefaultLogger().debug("node identifier = " + node.getIdentifier());
+		Log.getDefaultLogger().debug("target identifier = " + identifier);
+
+		if (node.getIdentifier().getName().equals(identifier.getName())) {
+			return node;
+		} else {
+			Node pos = null;
+			for (int i = 0; i < node.getChildCount(); i++) {
+				pos = findByIdentifier(node.getChild(i), identifier);
+				if (pos != null) return pos;
+			}
+			//if (pos == null && !node.isRoot()) {
+			//	pos = findByIdentifier(node.getParent(), identifier);
+			//}
+			if (pos != null) return pos;
+			return null;
+		}
+	}
+
+	/**
+	 * Root tree at this node.
+	 */
+	public static Node root(Node node) {
+	
+		if (!node.isRoot()) {
+	  
+			Node myParent = node.getParent();
+			removeChild(myParent, node);
+		
+			root(myParent);
+		
+			while (myParent.getChildCount() == 1) {
+				myParent = myParent.getChild(0);
+			}
+		
+			node.addChild(myParent);
+			lengths2Heights(node);
+		}
+		return node;
+	}
+
+	/**
+	 * Root the tree above the node with this identifier.
+	 */
+	public static Node rootAbove(Identifier id, Node root) {
+		return rootAbove(findByIdentifier(root, id));
+	}
+
+	/**
+	 * Root tree above this node;
+	 */
+	public static Node rootAbove(Node node) {
+		
+		if (!node.isRoot()) {
+
+			Node root = NodeFactory.createNode();
+		
+			Node myParent = node.getParent();
+			removeChild(myParent, node);
+		
+			Log.getDefaultLogger().debug("Before root() call");
+			root(myParent);
+			Log.getDefaultLogger().debug("After root() call");
+			
+			while (myParent.getChildCount() == 1) {
+				myParent = myParent.getChild(0);
+			}
+		
+			root.addChild(myParent);
+			root.addChild(node);
+
+			lengths2Heights(root);
+
+			return root;
+		
+		} else return node;
+	}
+
+	/**
+	 * determine distance to root
+	 *
+	 * @return distance to root
+	 */
+	public static double getDistanceToRoot(Node node)
+	{
+		if (node.isRoot())
+		{
+			return 0.0;
+		}
+		else
+		{
+			return node.getBranchLength() + getDistanceToRoot(node.getParent());
+		}
+	}
+
+	/**
+	 * Return the number of terminal leaves below this node or 1 if this is
+	 * a terminal leaf.
+	 */
+	public static int getLeafCount(Node node) {
+		
+		int count = 0;
+		if (!node.isLeaf()) {
+			for (int i = 0; i < node.getChildCount(); i++) {
+				count += getLeafCount(node.getChild(i));
+			}
+		} else {
+			count = 1;
+		}
+		return count;
+	}
+
+		/** returns number of branches centered around an internal node in an unrooted tree */
+	public static final int getUnrootedBranchCount(Node center) {
+		if (center.isRoot()) 	{
+			return center.getChildCount();
+		}
+		else {
+			return center.getChildCount()+1;
+		}
+	}
+}
+
diff --git a/LibrarySource/pal/tree/ParameterizedTree.java b/LibrarySource/pal/tree/ParameterizedTree.java
new file mode 100644
index 0000000..b3db0c2
--- /dev/null
+++ b/LibrarySource/pal/tree/ParameterizedTree.java
@@ -0,0 +1,112 @@
+// ParameterizedTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import java.io.*;
+
+
+/**
+ * abstract base class for a tree with an Parameterized interface
+ *
+ * @version $Id: ParameterizedTree.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public abstract class ParameterizedTree implements Parameterized, Tree
+{
+	//
+	// Public stuff
+	//
+
+	public void setBaseTree(Tree tree)
+	{
+		this.tree = tree;
+		
+		// make consistent
+		createNodeList();
+	}
+
+	public Tree getBaseTree() {
+		return tree;
+	}
+	
+	// interface tree
+	
+	/**
+	 * Returns the root node of this tree.
+	 */
+	public final Node getRoot() {
+		return tree.getRoot();
+	}
+
+	/**
+	 * returns a count of the number of external nodes (tips) in this
+	 * tree.
+	 */
+	public final int getExternalNodeCount() {
+		return tree.getExternalNodeCount();
+	}
+	
+	/**
+	 * returns a count of the number of internal nodes (and hence clades)
+	 * in this tree.
+	 */
+	public final int getInternalNodeCount() {
+		return tree.getInternalNodeCount();
+	}
+
+	/**
+	 * returns the ith external node in the tree.
+	 */
+	public final Node getExternalNode(int i) {
+		return tree.getExternalNode(i);
+	}
+	
+	/**
+	 * returns the ith internal node in the tree.
+	 */
+	public final Node getInternalNode(int i) {
+		return tree.getInternalNode(i);
+	}
+
+	/**
+	 * This method is called to ensure that the calls to other methods
+	 * in this interface are valid.
+	 */
+	public final void createNodeList() {
+		tree.createNodeList();
+	}
+
+	public final int getUnits() {
+		return tree.getUnits();
+	}
+
+	public final void setUnits(int units) {
+		tree.setUnits(units);
+	}
+
+	public String toString() {
+		StringWriter sw = new StringWriter();
+		TreeUtils.printNH(this, new PrintWriter(sw), true, false);
+
+		return sw.toString();
+	}
+	
+	// interface parameterized (remains abstract)
+	
+	/**
+	 * The non-parameterized tree that this parameterized tree is
+	 * based on.
+	 */
+	private Tree tree;
+
+}
+
diff --git a/LibrarySource/pal/tree/ReadTree.java b/LibrarySource/pal/tree/ReadTree.java
new file mode 100644
index 0000000..032561d
--- /dev/null
+++ b/LibrarySource/pal/tree/ReadTree.java
@@ -0,0 +1,157 @@
+// ReadTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.io.*;
+import pal.misc.*;
+
+import java.io.*;
+
+
+/**
+ * constructs a tree reading in a New Hampshire treefile, taking care
+ * for internal labels and branch lengths and binary/nonbinary and
+ * rooted/unrooted trees
+ *
+ * @version $Id: ReadTree.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class ReadTree extends SimpleTree
+{
+	//
+	// Public stuff
+	//
+	
+	/**
+	 * read tree from input stream
+	 *
+	 * @param input input stream
+	 */
+	public ReadTree(PushbackReader input) throws TreeParseException
+	{
+		super();
+
+		readNH(input);
+
+		// node heights should be populated as well - AD
+		NodeUtils.lengths2Heights(getRoot());
+	}
+
+	/**
+	 * read tree from file
+	 *
+	 * @param file name of file
+	 */
+	public ReadTree(String file) throws TreeParseException, IOException
+	{
+		super();
+	
+		PushbackReader input = InputSource.openFile(file);
+		readNH(input);
+		input.close();	
+
+		// node heights should be populated as well - AD
+		NodeUtils.lengths2Heights(getRoot());
+	}
+
+	
+	//
+	// Private stuff
+	//
+
+	private FormattedInput fi = FormattedInput.getInstance();
+
+	// Construct tree by reading a New Hampshire tree
+	private void readNH(PushbackReader input, Node currentNode)
+		throws TreeParseException
+	{
+		try
+		{
+			int c = fi.readNextChar(input);					
+			if (c == '(')
+			{
+				int count = 0;
+				do
+				{
+					Node newNode = NodeFactory.createNode();
+					currentNode.addChild(newNode);
+					readNH(input, newNode);
+					count++;
+					
+					c = fi.readNextChar(input);					
+				}
+				while (c == ',');
+				
+				if (c != ')')
+				{
+					throw new TreeParseException("Missing closing bracket");
+				}
+				
+				if (count < 2)
+				{
+					throw new TreeParseException("Node with single parent enountered");
+				}
+
+			}
+			else
+			{
+				input.unread(c);
+			}
+			
+			// Read label (any length)
+			currentNode.setIdentifier(new Identifier(fi.readLabel(input, -1)));
+			
+			// Read distance
+			c = fi.readNextChar(input);
+			
+			if (c == ':')
+			{
+				currentNode.setBranchLength(fi.readDouble(input,true));
+			}
+			else
+			{
+				input.unread(c);
+			}
+		}
+		
+			catch (IOException e)
+			{
+				throw new TreeParseException("IO error");
+			}
+			
+			catch (NumberFormatException e)
+			{
+				throw new TreeParseException("Error while parsing number");
+			}
+	}
+
+	// Construct tree by reading a New Hampshire tree
+	private void readNH(PushbackReader input) throws TreeParseException
+	{
+		try
+		{
+			readNH(input, getRoot());
+
+			// Drop terminating semicolon
+			int c = fi.readNextChar(input);
+			if (c != ';')
+			{
+				throw new TreeParseException("Missing terminating semicolon");
+			}
+		}
+		
+			catch (IOException e)
+			{
+				throw new TreeParseException();
+			}
+	}
+}
+
diff --git a/LibrarySource/pal/tree/SUPGMATree.java b/LibrarySource/pal/tree/SUPGMATree.java
new file mode 100644
index 0000000..5e65333
--- /dev/null
+++ b/LibrarySource/pal/tree/SUPGMATree.java
@@ -0,0 +1,102 @@
+// SUPGMATree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+// Known bugs and limitations:
+// - computational complexity O(numSeqs^3)
+//   (this could be brought down to O(numSeqs^2)
+//   but this needs more clever programming ...)
+
+
+package pal.tree;
+
+import pal.distance.*;
+import pal.misc.*;
+
+/**
+ * constructs an SUPGMA tree from pairwise distances. <BR>
+ * Reference: <BR>
+ * Alexei Drummond and Allen G. Rodrigo (2000). Reconstructing Genealogies of Serial Samples Under the Assumption of a Molecular Clock Using Serial-Sample UPGMA. Molecular Biology and Evolution 17:1807-1815
+ *
+ * @version $Id: SUPGMATree.java,v 1.6 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class SUPGMATree extends UPGMATree
+{
+	//
+	// Public stuff
+	//	
+
+	/**
+	 * constructor SUPGMA tree
+	 *
+	 * @param m *uncorrected* distance matrix
+	 */
+	public SUPGMATree(DistanceMatrix m, TimeOrderCharacterData tocd, double rate) {
+		
+		this(m, tocd, rate, true);	
+	}
+
+
+	/**
+	 * constructor SUPGMA tree
+	 *
+	 * @param m *uncorrected* distance matrix
+	 */
+	public SUPGMATree(DistanceMatrix m, TimeOrderCharacterData tocd, double rate, boolean allowNegatives) {
+		
+		super(new SUPGMADistanceMatrix(m, tocd, rate));
+		
+		this.tocd = tocd;
+
+		IdGroup idgroup = tocd.getIdGroup();
+		
+		createNodeList();
+		
+		
+		/*//go through and check for maximum allowed rate
+		if (!allowNegatives) {
+			for (int i = 0; i < getExternalNodeCount(); i++) {
+				int index = idgroup.whichIdNumber(getExternalNode(i).getIdentifier().getName());
+				double time = tocd.getTime(index);
+				
+				double maxRateThisTip = getExternalNode(i).getParent().getNodeHeight() / time;
+
+				if (maxRateThisTip < rate) {
+					rate = maxRateThisTip;
+				}
+			}
+		}*/
+
+		// go through and set heights.
+		for (int i = 0; i < getExternalNodeCount(); i++) {
+			int index = idgroup.whichIdNumber(getExternalNode(i).getIdentifier().getName());
+			getExternalNode(i).setNodeHeight(tocd.getHeight(index, rate));		
+			if (!allowNegatives) {
+				if (getExternalNode(i).getParent().getNodeHeight() < getExternalNode(i).getNodeHeight()) {
+					fixHeight(getExternalNode(i).getParent(), getExternalNode(i).getNodeHeight());
+				}
+			}
+		}
+	}
+	
+	public DatedTipsClockTree getDatedTipsClockTree() {
+		return new DatedTipsClockTree(this, tocd, false);	
+	}
+
+	private void fixHeight(Node node, double height) {
+		node.setNodeHeight(height);
+		if (!node.isRoot()) {
+			if (node.getParent().getNodeHeight() < height) {
+				fixHeight(node.getParent(), height);
+			}
+		}
+	}
+		
+	private TimeOrderCharacterData tocd;
+}
+
diff --git a/LibrarySource/pal/tree/SimpleNode.java b/LibrarySource/pal/tree/SimpleNode.java
new file mode 100644
index 0000000..fb77c64
--- /dev/null
+++ b/LibrarySource/pal/tree/SimpleNode.java
@@ -0,0 +1,448 @@
+// SimpleNode.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import java.io.*;
+import pal.io.*;
+
+
+/**
+ * data structure for a node (includes branch) in a binary/non-binary
+ * rooted/unrooted tree
+ *
+ * @version $Id: SimpleNode.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class SimpleNode implements Node
+{	
+	/** parent node */
+	private Node parent;
+	
+	/** number of child nodes */
+	private int numChilds;
+
+	/** number of node as displayed */
+	private int number;
+	
+	/** sequences associated with node */
+	private byte[] sequence;
+	
+	/** partial likelihood associated with node */
+	private double[][][] partial;
+	
+	/** length of branch to parent node */
+	private double length;
+	
+	/** standard error of length of branch to parent node */ 
+	private double lengthSE;
+	
+	/** height of this node */
+	private double height;
+
+	/** height SE of this node */
+	private double heightSE;
+
+	
+	/** identifier of node/associated branch */
+	private Identifier identifier;
+
+
+
+	// the following constructors should eventually become
+	// "friendly" to prevent anyone calling them directly.
+	// Instead, the NodeFactory should be used!
+	
+	/** constructor default node */
+	public SimpleNode()
+	{
+		parent = null;
+		child = null;
+		numChilds = 0;
+		length = 0.0;
+		lengthSE = 0.0;
+		height = 0.0;
+		identifier = Identifier.ANONYMOUS;
+		
+		number = 0;
+		sequence = null;
+		partial = null;
+	}	
+
+	/** constructor used to clone a node and all children */
+	public SimpleNode(Node n)
+	{
+		this(n, true);
+	}	
+
+
+
+	public void reset()
+	{
+		parent = null;
+		child = null;
+		numChilds = 0;
+		length = 0.0;
+		lengthSE = 0.0;
+		height = 0.0;
+		identifier = Identifier.ANONYMOUS;
+		
+		number = 0;
+		sequence = null;
+		partial = null;
+	}
+
+	public SimpleNode(Node n, boolean keepIds) {
+		init(n, keepIds);
+		for (int i = 0; i < n.getChildCount(); i++) {
+			addChild(new SimpleNode(n.getChild(i)));
+		}
+	}
+
+
+	protected void init(Node n) {
+		init(n, true);
+	}
+
+	/**
+	 * Initialized node instance variables based on given Node.
+	 * children are ignored.
+	 */
+	protected void init(Node n, boolean keepId) {
+		parent = null;
+		length = n.getBranchLength();
+		lengthSE = n.getBranchLengthSE();
+		height = n.getNodeHeight();
+		if (keepId) {
+			identifier = n.getIdentifier();
+		} else { identifier = Identifier.ANONYMOUS; }
+		
+		number = n.getNumber();
+		sequence = n.getSequence();
+		
+		child = null;
+		numChilds = 0;
+	}
+
+	/**
+	 * Returns the parent node of this node.
+	 */
+	public final Node getParent() {
+		return parent;
+	}
+
+	/** Set the parent node of this node. */
+	public void setParent(Node node)
+	{
+		parent = node;
+	}
+
+	/**
+	 * removes parent.
+	 */
+	public final void removeParent() {
+		parent = null;
+	}
+
+	/**
+	 * Returns the sequence at this node, in the form of a String.
+	 */
+	public String getSequenceString() {
+		return new String(sequence);
+	}
+
+	/**
+	 * Returns the sequence at this node, in the form of an array of bytes.
+	 */
+	public byte[] getSequence() {
+		return sequence;
+	}
+
+	/**
+	 * Sets the sequence at this node, in the form of an array of bytes.
+	 */
+	public void setSequence(byte[] s) {
+		sequence = s;
+	}
+
+	/**
+	 * Get the length of the branch attaching this node to its parent.
+	 */
+	public final double getBranchLength() {
+		return length;
+	}
+
+	/**
+	 * Set the length of the branch attaching this node to its parent.
+	 */
+	public final void setBranchLength(double value) {
+		length = value;
+	}
+
+	/**
+	 * Get the length SE of the branch attaching this node to its parent.
+	 */
+	public final double getBranchLengthSE() {
+		return lengthSE;
+	}
+
+	/**
+	 * Set the length SE of the branch attaching this node to its parent.
+	 */
+	public final void setBranchLengthSE(double value) {
+		lengthSE = value;
+	}
+
+
+	/**
+	 * Get the height of this node relative to the most recent node.
+	 */
+	public final double getNodeHeight() {
+		return height;
+	}
+
+	/**
+	 * Set the height of this node relative to the most recent node.
+	 */
+	public final void setNodeHeight(double value) {
+		height = Math.abs(value);
+	}
+
+	/**
+	 * Set the height SE of this node relative to the most recent node.
+	 */
+	public final void setNodeHeightSE(double value) {
+		heightSE = value;
+	}
+
+	/**
+	 * Set the height SE of this node relative to the most recent node.
+	 */
+	public final double getNodeHeightSE() {
+		return heightSE;
+	}
+
+	/**
+	 * Returns the identifier for this node.
+	 */
+	public final Identifier getIdentifier() {
+		return identifier;
+	}
+
+	/**
+	 * Set identifier for this node.
+	 */
+	public final Identifier setIdentifier(Identifier id) {
+		identifier = id;
+		return identifier;
+	}
+
+	public void setNumber(int n) {
+		number = n;
+	}
+
+	public int getNumber() {
+		return number;
+	}
+
+	
+
+	/**
+	 * get child node
+	 *
+	 * @param n number of child
+	 *
+	 * @return child node
+	 */ 
+	public Node getChild(int n)
+	{
+		return child[n];
+	}
+	
+	/**
+	 * set child node
+	 *
+	 * @param n number
+	 * @node node new child node
+	 */
+	public void setChild(int n, Node node)
+	{
+		child[n] = node;
+		child[n].setParent(this);
+	}
+	
+	/**
+	 * check whether this node is an internal node
+	 *
+	 * @return result (true or false)
+	 */
+	public boolean hasChildren()
+	{
+		return !isLeaf();
+	}
+
+	/**
+	 * check whether this node is an external node
+	 *
+	 * @return result (true or false)
+	 */
+	public boolean isLeaf()
+	{
+		if (numChilds == 0)
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	/**
+	 * check whether this node is a root node 
+	 *
+	 * @return result (true or false)
+	 */
+	public boolean isRoot()
+	{
+		if (parent == null)
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+
+	/**
+	 * add new child node
+	 *
+	 * @param n new child node
+	 */
+	public void addChild(Node n)
+	{
+		insertChild(n, numChilds);
+	}
+
+	/**
+	 * add new child node (insertion at a specific position)
+	 *
+	 * @param n new child node
+	 + @param pos position
+	 */
+	public void insertChild(Node n, int pos)
+	{
+		SimpleNode c = (SimpleNode) n;
+	
+		Node[] newChild = new Node[numChilds + 1];
+		
+		for (int i = 0; i < pos; i++)
+		{
+			newChild[i] = child[i];
+		}
+		newChild[pos] = c;
+		for (int i = pos; i < numChilds; i++)
+		{
+			newChild[i+1] = child[i];
+		}
+		
+		child = newChild;
+
+		numChilds++;
+		
+		c.setParent(this);	
+	}
+
+	
+	/**
+	 * remove child
+	 *
+	 * @param n number of child to be removed
+	 */
+	public void removeChild(int n)
+	{
+		if (n >= numChilds)
+		{
+			throw new IllegalArgumentException("Nonexistent child");
+		}
+		Node[] newChild = new Node[numChilds-1];
+		
+		for (int i = 0; i < n; i++)
+		{
+			newChild[i] = child[i];
+		}
+		
+		for (int i = n; i < numChilds-1; i++)
+		{
+			newChild[i] = child[i+1];
+		}
+	
+		//remove parent link from removed child!
+		((Node)child[n]).setParent(null);
+	
+		child = newChild;
+		numChilds--;
+	}
+
+	/**
+	 * determines the height of this node and its descendants
+	 * from branch lengths, assuming contemporaneous tips.
+	 */
+	public void lengths2HeightsContemp()
+	{
+		double largestHeight = 0.0;
+		
+		if (!isLeaf())
+		{
+			for (int i = 0; i < numChilds; i++)
+			{
+				NodeUtils.lengths2Heights(getChild(i));
+				
+				double newHeight = 
+					getChild(i).getNodeHeight() + getChild(i).getBranchLength();
+				
+				if (newHeight > largestHeight)
+				{
+					largestHeight = newHeight;
+				}
+			}
+		}
+		
+		setNodeHeight(largestHeight);
+	}
+	
+	/**
+	 * Returns the number of children this node has.
+	 */
+	public int getChildCount() {
+		return numChilds;
+	}
+	  
+
+
+
+	public String toString() {
+	
+		StringWriter sw = new StringWriter();
+		NodeUtils.printNH(new PrintWriter(sw), this, true, false);
+		return sw.toString();
+	}
+	
+	
+	//
+	// Private stuff
+	//
+	
+	private Node[] child;
+}
+
diff --git a/LibrarySource/pal/tree/SimpleTree.java b/LibrarySource/pal/tree/SimpleTree.java
new file mode 100644
index 0000000..44da6b9
--- /dev/null
+++ b/LibrarySource/pal/tree/SimpleTree.java
@@ -0,0 +1,274 @@
+// SimpleTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import pal.io.*;
+import pal.alignment.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * data structure for a binary/non-binary rooted/unrooted trees
+ *
+ * @version $Id: SimpleTree.java,v 1.11 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ *
+ */
+public class SimpleTree implements Tree, Report, Units, Serializable
+{
+	//
+	// Public stuff
+	//
+
+	/** root node */
+	private Node root;
+
+	/** list of internal nodes (including root) */
+	private Node[] internalNode;
+	
+	/** number of internal nodes (including root) */
+	private int numInternalNodes;
+
+	/** list of external nodes */
+	private Node[] externalNode;
+	
+	/** number of external nodes */
+	private int numExternalNodes;
+
+	
+	/** holds the units of the trees branches. */
+	private int units = EXPECTED_SUBSTITUTIONS;
+	
+	/** constructor tree consisting solely of root node */
+	public SimpleTree() {
+		
+		// Default configuration
+		root = new SimpleNode();
+		root.setIdentifier(new Identifier("ROOT"));
+		root.setBranchLength(0.0);
+		root.setBranchLengthSE(0.0);
+	}
+
+	/** constructor taking a root node */
+	public SimpleTree(Node r) {
+		
+		root = r;
+		createNodeList();
+	}
+
+	/** clone constructor */
+	public SimpleTree(Tree tree)
+	{
+		root = new SimpleNode(tree.getRoot());
+		setUnits(tree.getUnits());
+		createNodeList();
+	}
+
+	/** clone constructor */
+	public SimpleTree(Tree tree, boolean keepIdentifiers)
+	{
+		root = new SimpleNode(tree.getRoot(), keepIdentifiers);
+		setUnits(tree.getUnits());
+		createNodeList();
+	}
+
+	/**
+	 * Return the units that this tree is expressed in.
+	 */
+	public final int getUnits() {
+		return units;
+	}
+
+	/**
+	 * Sets the units that this tree is expressed in.
+	 */
+	public final void setUnits(int units) {
+		this.units = units;
+	}
+
+
+	/**
+	 * Returns the number of external nodes.
+	 */
+	public final int getExternalNodeCount() {
+		return numExternalNodes;
+	}
+
+	/**
+	 * Returns the ith external node.
+	 */
+	public final Node getExternalNode(int i) {
+		return externalNode[i];
+	}
+	
+	/**
+	 * Returns the number of internal nodes.
+	 */
+	public final int getInternalNodeCount() {
+		return numInternalNodes;
+	}
+
+	/**
+	 * Returns the ith internal node.
+	 */
+	public final Node getInternalNode(int i) {
+		return internalNode[i];
+	}
+
+	/**
+	 * Returns the root node of this tree.
+	 */
+	public final Node getRoot() {
+		return root;
+	}
+
+	/**
+	 * Set a new node as root node.
+	 */
+	public final void setRoot(Node r) {
+		root = r;
+		createNodeList();
+	}
+
+	/** count and list external and internal nodes and
+		compute heights of each node */
+	public void createNodeList()
+	{
+		numInternalNodes = 0;
+		numExternalNodes = 0;
+		Node node = root;
+		do
+		{
+			node = NodeUtils.postorderSuccessor(node);
+			if (node.isLeaf())
+			{
+				node.setNumber(numExternalNodes);
+				numExternalNodes++;
+			}
+			else
+			{
+				node.setNumber(numInternalNodes);
+				numInternalNodes++;
+			}
+		}
+		while(node != root);
+		
+		internalNode = new Node[numInternalNodes];
+		externalNode = new Node[numExternalNodes];
+		node = root;
+		do
+		{
+			node = NodeUtils.postorderSuccessor(node);
+			if (node.isLeaf())
+			{
+				externalNode[node.getNumber()] = node;
+			}
+			else
+			{
+				internalNode[node.getNumber()] = node;
+			}	
+		}
+		while(node != root);
+				
+		// compute heights if it seems necessary
+		if (root.getNodeHeight() == 0.0) {
+			NodeUtils.lengths2Heights(root);
+		}
+	}
+
+	public String toString() {
+		StringWriter sw = new StringWriter();
+		TreeUtils.printNH(this, new PrintWriter(sw), true, false);
+
+		return sw.toString();
+	}
+
+
+	/**
+	 * return node with number num (as displayed in ASCII tree)
+	 *
+	 * @param num number of node
+	 *
+	 * @return node
+	 */
+	public Node findNode(int num)
+	{
+		createNodeList();
+	
+		if (num <= numExternalNodes)
+		{
+			return externalNode[num-1];
+		}
+		else
+		{
+			return internalNode[num-1-numExternalNodes];
+		}
+	}
+
+	/**
+	 * make node with number num to root node
+	 *
+	 * @param num number of node
+	 */
+	public void reroot(int num)
+	{
+		reroot(findNode(num));
+	}
+
+	/**
+	 * make given node to root node
+	 *
+	 * @param node new root node
+	 */
+	public void reroot(Node node)
+	{
+		if (node.isRoot() || node.isLeaf())
+		{
+			return;
+		}
+		
+		if (!node.getParent().isRoot())
+		{
+			reroot(node.getParent());
+		}
+		
+		// Now the parent of node is root
+		
+		if (node.getParent().getChildCount() < 3)
+		{
+			// Rerooting not possible
+			return;
+		}
+		
+		// Exchange branch label, length et cetera
+		NodeUtils.exchangeInfo(node.getParent(), node);
+		
+		// Rearange topology
+		Node parent = node.getParent();
+		NodeUtils.removeChild(parent, node);
+		node.addChild(parent);
+		root = node;
+	}
+
+	// interface Report
+	
+	public void report(PrintWriter out)
+	{
+		TreeUtils.report(this, out);
+	}
+	
+	
+
+}
+
diff --git a/LibrarySource/pal/tree/SimulatedAlignment.java b/LibrarySource/pal/tree/SimulatedAlignment.java
new file mode 100644
index 0000000..f92fe74
--- /dev/null
+++ b/LibrarySource/pal/tree/SimulatedAlignment.java
@@ -0,0 +1,211 @@
+// SimulatedAlignment.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.datatype.*;
+import pal.substmodel.*;
+import pal.alignment.*;
+import pal.math.*;
+import pal.misc.*;
+
+
+/**
+ * generates an artificial data set
+ *
+ * @version $Id: SimulatedAlignment.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class SimulatedAlignment extends AbstractAlignment
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Inititalisation
+	 *
+	 * @param sites number of sites
+	 * @param t     tree relating the sequences
+	 * @param m     model of evolution
+	 */
+	public SimulatedAlignment(int sites, Tree t, SubstitutionModel m)
+	{
+		dataType = m.rateMatrix.getDataType();
+		numStates = dataType.getNumStates();
+		model = m;
+		
+		rng = new MersenneTwisterFast();
+		
+		tree = t;
+		tree.createNodeList();
+
+		numSeqs = tree.getExternalNodeCount();
+		numSites = sites;
+		idGroup = new SimpleIdGroup(numSeqs);
+				
+		for (int i = 0; i < numSeqs; i++)
+		{
+			idGroup.setIdentifier(i, tree.getExternalNode(i).getIdentifier());
+		}
+
+		stateData = new byte[numSeqs][numSites];
+		
+		for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		{
+			tree.getExternalNode(i).setSequence(stateData[i]);
+		}
+		for (int i = 0; i < tree.getInternalNodeCount()-1; i++)
+		{
+			tree.getInternalNode(i).setSequence(new byte[numSites]);
+		}
+		
+		rootSequence = new byte[numSites];
+				
+		rateAtSite = new int[numSites];
+		cumFreqs = new double[numStates];
+		cumRateProbs = new double[m.rateDistribution.numRates];
+	}
+
+
+	// Implementation of abstract Alignment method
+
+	/** sequence alignment at (sequence, site) */
+	public char getData(int seq, int site)
+	{
+		return dataType.getChar(stateData[seq][site]);
+	}
+
+
+	/** generate new artificial data set (random root sequence) */
+	public void simulate()
+	{
+		makeRandomRootSequence();
+		simulate(rootSequence);
+	}
+	
+	/** generate new artificial data set (specified root sequence) */
+	public void simulate(byte[] rootSeq)
+	{
+		// Check root sequence
+		for (int i = 0; i < numSites; i++)
+		{
+			if (rootSeq[i] >= numStates || rootSeq[i] < 0)
+			{
+				throw new IllegalArgumentException("Root sequence contains illegal state (?,-, etc.)");
+			}
+		}
+		
+		tree.getInternalNode(tree.getInternalNodeCount()-1).setSequence(rootSeq);
+		
+		// Assign new rate categories
+		assignRates();
+		
+		// Visit all nodes except root
+		Node node = NodeUtils.preorderSuccessor(tree.getRoot());
+		do
+		{
+			determineMutatedSequence(node);
+			node = NodeUtils.preorderSuccessor(node);	
+		}
+		while (node != tree.getRoot());
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private Tree tree;
+	private SubstitutionModel model;
+	private byte[] rootSequence;
+	private double[] cumFreqs;
+	private int[] rateAtSite;
+	private double[] cumRateProbs;
+	private int numStates;
+	private byte[][] stateData;
+	private MersenneTwisterFast rng;
+	
+	private void determineMutatedSequence(Node node)
+	{
+		if (node.isRoot()) throw new IllegalArgumentException("Root node not allowed");
+		
+		model.setDistance(node.getBranchLength());
+
+		byte[] oldS = node.getParent().getSequence();
+		byte[] newS = node.getSequence();		
+		
+		for (int i = 0; i < numSites; i++)
+		{
+			cumFreqs[0] = model.transProb(rateAtSite[i], oldS[i], 0);
+			for (int j = 1; j < numStates; j++)
+			{
+				cumFreqs[j] = cumFreqs[j-1] + model.transProb(rateAtSite[i], oldS[i], j);
+			}		
+			
+			newS[i] = (byte) randomChoice(cumFreqs);
+		}
+	}
+
+	private void makeRandomRootSequence()
+	{
+		double[] frequencies = model.rateMatrix.getEqulibriumFrequencies();
+		cumFreqs[0] = frequencies[0];
+		for (int i = 1; i < numStates; i++)	{
+			cumFreqs[i] = cumFreqs[i-1] + frequencies[i];
+		}
+
+		for (int i = 0; i < numSites; i++)
+		{
+			rootSequence[i] = (byte) randomChoice(cumFreqs);
+		}
+	}
+	
+	private void assignRates()
+	{
+		cumRateProbs[0] = model.rateDistribution.probability[0];
+		for (int i = 1; i < model.rateDistribution.numRates; i++)
+		{
+			cumRateProbs[i] = cumRateProbs[i-1] + model.rateDistribution.probability[i];
+		}		
+
+		for (int i = 0; i < numSites; i++)
+		{
+			rateAtSite[i] = randomChoice(cumRateProbs);
+		}
+
+
+	}
+	
+	// Chooses one category if a cumulative probability distribution is given
+	private int randomChoice(double[] cf)
+	{
+		double rnd = rng.nextDouble();
+			
+		int s;
+		if (rnd <= cf[0])
+		{
+			s = 0;
+		}
+		else
+		{
+			for (s = 1; s < cf.length; s++)
+			{
+				if (rnd <= cf[s] && rnd > cf[s-1])
+				{
+					break;
+				}
+			}
+		}
+			
+		return s;
+	}
+}
+
diff --git a/LibrarySource/pal/tree/SplitSystem.java b/LibrarySource/pal/tree/SplitSystem.java
new file mode 100644
index 0000000..2ccfdff
--- /dev/null
+++ b/LibrarySource/pal/tree/SplitSystem.java
@@ -0,0 +1,127 @@
+// SplitSystem.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.tree;
+
+import java.io.*;
+
+import pal.misc.*;
+
+/**
+ * data structure for a set of splits 
+ *
+ * @version $Id: SplitSystem.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class SplitSystem
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * @param idGroup  sequence labels
+	 * @param size     number of splits
+	 */
+	public SplitSystem(IdGroup idGroup, int size)
+	{
+		this.idGroup = idGroup;
+		
+		labelCount = idGroup.getIdCount();
+		splitCount = size;
+		
+		splits = new boolean[splitCount][labelCount];
+	}
+
+	/** get number of splits */
+	public int getSplitCount()
+	{		
+		return splitCount;
+	}
+
+	/** get number of labels */
+	public int getLabelCount()
+	{		
+		return labelCount;
+	}
+
+	/** get split vector */
+	public boolean[][] getSplitVector()
+	{		
+		return splits;
+	}
+
+	/** get split */
+	public boolean[] getSplit(int i)
+	{		
+		return splits[i];
+	}
+
+
+	/** get idGroup */
+	public IdGroup getIdGroup()
+	{		
+		return idGroup;
+	}
+
+	/**
+	  + test whether a split is contained in this split system
+	  * (assuming the same leaf order)
+	  *
+	  * @param split split
+	  */
+	public boolean hasSplit(boolean[] split)
+	{
+		for (int i = 0; i < splitCount; i++)
+		{
+			if (SplitUtils.isSame(split, splits[i])) return true;
+		}
+			
+		return false;
+	}
+
+
+	/** print split system */
+	public String toString()
+	{
+		StringWriter sw = new StringWriter();
+		PrintWriter pw = new PrintWriter(sw);
+		
+		for (int i = 0; i < labelCount; i++)
+		{
+			pw.println(idGroup.getIdentifier(i));
+		}
+		pw.println();
+		
+		
+		for (int i = 0; i < splitCount; i++)
+		{
+			for (int j = 0; j < labelCount; j++)
+			{
+				if (splits[i][j] == true)
+					pw.print('*');
+				else
+					pw.print('.');
+			}
+			
+			pw.println();
+		}
+
+		return sw.toString();
+	}
+
+	
+	//
+	// Private stuff
+	//
+	
+	private int labelCount, splitCount;
+	private IdGroup idGroup;
+	private boolean[][] splits;
+}
+
diff --git a/LibrarySource/pal/tree/SplitUtils.java b/LibrarySource/pal/tree/SplitUtils.java
new file mode 100644
index 0000000..e4e2dd7
--- /dev/null
+++ b/LibrarySource/pal/tree/SplitUtils.java
@@ -0,0 +1,169 @@
+// SplitUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.tree;
+
+import pal.misc.*;
+
+/**
+ * utilities for split systems
+ *
+ * @version $Id: SplitUtils.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class SplitUtils
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * creates a split system from a tree
+	 * (using a pre-specified order of sequences)
+	 *
+	 * @param idGroup  sequence order for the matrix
+	 * @param tree
+	 */
+	public static SplitSystem getSplits(IdGroup idGroup, Tree tree)
+	{
+		tree.createNodeList();
+		
+		int size = tree.getInternalNodeCount()-1;
+		SplitSystem splitSystem = new SplitSystem(idGroup, size);
+		
+		boolean[][] splits = splitSystem.getSplitVector();
+		
+		for (int i = 0; i < size; i++)
+		{
+			getSplit(idGroup, tree.getInternalNode(i), splits[i]);
+		}
+		
+		
+		return splitSystem;
+	}
+
+
+
+	/**
+	 * creates a split system from a tree
+	 * (using tree-induced order of sequences)
+	 *
+	 * @param tree
+	 */
+	public static SplitSystem getSplits(Tree tree)
+	{
+		IdGroup idGroup = TreeUtils.getLeafIdGroup(tree);
+		
+		return getSplits(idGroup, tree);
+	}
+
+
+
+	/**
+	 * get split for branch associated with internal node
+	 *
+	 * @param idGroup order of labels
+	 * @param internalNode Node
+	 * @param boolean[] split
+	 */
+	public static void getSplit(IdGroup idGroup, Node internalNode, boolean[] split)
+	{
+		if (internalNode.isLeaf() || internalNode.isRoot())
+		{
+			throw new IllegalArgumentException("Only internal nodes (and no root) nodes allowed");
+		}
+		
+		// make sure split is reset
+		for (int i = 0; i < split.length; i++)
+		{
+			split[i] = false;
+		}
+		
+		// mark all leafs downstream of the node
+		
+		for (int i = 0; i < internalNode.getChildCount(); i++)
+		{
+			markNode(idGroup, internalNode, split);
+		}
+		
+		// standardize split (i.e. first index is alway true)
+		if (split[0] == false)
+		{
+			for (int i = 0; i < split.length; i++)
+			{
+				if (split[i] == false)
+					split[i] = true;
+				else
+					split[i] = false;
+			}
+		}		
+	}
+
+	/**
+	 * checks whether two splits are identical
+	 * (assuming they are of the same length
+	 * and use the same leaf order)
+	 *
+	 * @param s1 split 1
+	 * @param s2 split 2
+	 */
+	public static boolean isSame(boolean[] s1, boolean[] s2)
+	{
+		boolean reverse;
+		if (s1[0] == s2[0]) reverse = false;
+		else reverse = true;
+		
+		if (s1.length != s2.length) 
+			throw new IllegalArgumentException("Splits must be of the same length!");
+		
+		for (int i = 0; i < s1.length; i++)
+		{
+			if (reverse)
+			{
+				// splits not identical
+				if (s1[i] == s2[i]) return false;			
+			}
+			else
+			{
+				// splits not identical
+				if (s1[i] != s2[i]) return false;
+			}
+		}
+		
+		return true;
+	}
+
+	//
+	// Private stuff
+	//
+	
+	private static void markNode(IdGroup idGroup, Node node, boolean[] split)
+	{
+		if (node.isLeaf())
+		{
+			String name = node.getIdentifier().getName();
+			int index = idGroup.whichIdNumber(name);
+			
+			if (index < 0)
+			{
+				throw new IllegalArgumentException("INCOMPATIBLE IDENTIFIER (" + name + ")");
+			} 
+			
+			split[index] = true;
+		}
+		else
+		{
+			for (int i = 0; i < node.getChildCount(); i++)
+			{
+				markNode(idGroup, node.getChild(i), split);
+			}
+		}
+	}
+	
+}
+
diff --git a/LibrarySource/pal/tree/Tree.java b/LibrarySource/pal/tree/Tree.java
new file mode 100644
index 0000000..de9d368
--- /dev/null
+++ b/LibrarySource/pal/tree/Tree.java
@@ -0,0 +1,72 @@
+// Tree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import pal.io.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * Interface for a phylogenetic or genealogical tree.
+ *
+ * @version $Id: Tree.java,v 1.15 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Tree extends Units, Serializable {
+
+	/**
+	 * Returns the root node of this tree.
+	 */
+	Node getRoot();
+
+	/**
+	 * returns a count of the number of external nodes (tips) in this
+	 * tree.
+	 */
+	int getExternalNodeCount();
+	
+	/**
+	 * returns a count of the number of internal nodes (and hence clades)
+	 * in this tree.
+	 */
+	int getInternalNodeCount();
+
+	/**
+	 * returns the ith external node in the tree.
+	 */
+	Node getExternalNode(int i);
+	
+	/**
+	 * returns the ith internal node in the tree.
+	 */
+	Node getInternalNode(int i);
+
+	/**
+	 * This method is called to ensure that the calls to other methods
+	 * in this interface are valid.
+	 */
+	void createNodeList();
+
+	/**
+	 * Gets the units that this tree's branch lengths and node
+	 * heights are expressed in.
+	 */
+	int getUnits();
+
+	/**
+	 * Sets the units that this tree's branch lengths and node
+	 * heights are expressed in.
+	 */
+	void setUnits(int units);
+}
+
diff --git a/LibrarySource/pal/tree/TreeDistanceMatrix.java b/LibrarySource/pal/tree/TreeDistanceMatrix.java
new file mode 100644
index 0000000..c2a5e3d
--- /dev/null
+++ b/LibrarySource/pal/tree/TreeDistanceMatrix.java
@@ -0,0 +1,135 @@
+// TreeDistanceMatrix.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.tree;
+
+import pal.distance.*;
+import pal.misc.*;
+
+
+/**
+ * computes distance matrix induced by a tree
+ * (needs only O(n^2) time, following algorithm DistanceInTree by
+ * D.Bryant and P. Wadell. 1998. MBE 15:1346-1359)
+ * 
+ *
+ * @version $Id: TreeDistanceMatrix.java,v 1.8 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class TreeDistanceMatrix extends DistanceMatrix
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * compute induced distance matrix
+	 *
+	 * @param idGroup  sequence order for the matrix
+	 * @param t tree
+	 * @param countEdges boolean variable deciding whether the actual
+	 *                   branch lengths are used in computing the distance
+	 *                   or whether simply all edges larger or equal a certain
+	 *                   threshold length are counted (each with weight 1.0)
+	 * @param epsilon    minimum branch length for a which an edge is counted
+	 */
+	public TreeDistanceMatrix(IdGroup idGroup, Tree t, boolean countEdges, double epsilon)
+	{
+		numSeqs = idGroup.getIdCount();
+		this.idGroup = idGroup;
+		tree = t;
+		
+		distance = new double[numSeqs][numSeqs];
+		
+		alias = TreeUtils.mapExternalIdentifiers(idGroup, tree);
+		
+		dist = new double[tree.getExternalNodeCount()];
+		idist = new double[tree.getInternalNodeCount()];
+		
+		computeDistances(countEdges, epsilon);
+	}
+
+	/**
+	 * compute induced distance matrix using actual branch lengths
+	 *
+	 * @param idGroup  sequence order for the matrix
+	 * @param t tree
+	 */
+	public TreeDistanceMatrix(IdGroup idGroup, Tree t)
+	{
+		this(idGroup, t, false, 0.0);
+	}
+
+	/**
+	 * compute induced distance matrix
+	 * (using tree-induced order of sequences)
+	 *
+	 * @param t tree
+	 * @param countEdges boolean variable deciding whether the actual
+	 *                   branch lengths are used in computing the distance
+	 *                   or whether simply all edges larger or equal a certain
+	 *                   threshold length are counted (each with weight 1.0)
+	 * @param epsilon    minimum branch length for a which an edge is counted
+	 */
+	public TreeDistanceMatrix(Tree t, boolean countEdges, double epsilon)
+	{
+		this(TreeUtils.getLeafIdGroup(t), t, countEdges, epsilon);
+	}
+
+	/**
+	 * compute induced distance matrix using actual branch lengths
+	 * (using tree-induced order of sequences)
+	 *
+	 * @param t tree
+	 */
+	public TreeDistanceMatrix(Tree t)
+	{
+		this(t, false, 0.0);
+	}
+
+
+
+	/** recompute distances (actual branch lengths) */
+	public void computeDistances()
+	{		
+		computeDistances(false, 0.0);
+	}
+	
+	/** recompute distances
+	 * @param countEdges boolean variable deciding whether the actual
+	 *                   branch lengths are used in computing the distance
+	 *                   or whether simply all edges larger or equal a certain
+	 *                   threshold length are counted (each with weight 1.0)
+	 * @param epsilon    minimum branch length for a which an edge is counted
+	 */	
+	public void computeDistances(boolean countEdges, double epsilon)
+	{		
+		// fast O(n^2) computation of induced distance matrix
+		for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		{
+			TreeUtils.computeAllDistances(tree, i, dist, idist, countEdges, epsilon);
+			int ai = alias[i];
+			
+			for (int j = 0; j < tree.getExternalNodeCount(); j++)
+			{
+				distance[ai][alias[j]] = dist[j];				
+			}
+		}
+
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	private int[] alias;
+	private Tree tree;
+	private double[] dist, idist;
+}
+
diff --git a/LibrarySource/pal/tree/TreeParseException.java b/LibrarySource/pal/tree/TreeParseException.java
new file mode 100644
index 0000000..4d0dd0f
--- /dev/null
+++ b/LibrarySource/pal/tree/TreeParseException.java
@@ -0,0 +1,26 @@
+// TreeParseException.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+
+/**
+ * exception thrown by ReadTree
+ *
+ * @author Korbinian Strimmer
+ */
+public class TreeParseException extends Exception
+{
+	public TreeParseException() {}
+
+	public TreeParseException(String msg)
+	{
+		super(msg);
+	}
+}
+
diff --git a/LibrarySource/pal/tree/TreeUtils.java b/LibrarySource/pal/tree/TreeUtils.java
new file mode 100644
index 0000000..0df0d0f
--- /dev/null
+++ b/LibrarySource/pal/tree/TreeUtils.java
@@ -0,0 +1,1042 @@
+// TreeUtils.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+import pal.io.*;
+import pal.alignment.*;
+import pal.util.*;
+import pal.math.*;
+import pal.mep.*;
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * various utility functions on trees.
+ *
+ * @version $Id: TreeUtils.java,v 1.29 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class TreeUtils
+{
+
+	/**
+	 * computes Robinson-Foulds (1981) distance between two trees
+	 *
+	 * @param t1 tree 1
+	 * @param t2 tree 2
+	 *
+	 * Definition: Assuming that t1 is the reference tree, let fn be the
+	 * false negatives, i.e. the number of edges in t1 missing in t2,
+	 * and fp the number of false positives, i.e. the number of edges
+	 * in t2 missing in t1.  The RF distance is then (fn + fp)/2
+	 */
+	public static double getRobinsonFouldsDistance(Tree t1, Tree t2)
+	{
+		SplitSystem s1 = SplitUtils.getSplits(t1);
+		
+		return getRobinsonFouldsDistance(s1, t2);
+	}
+
+
+	/**
+	 * computes Robinson-Foulds (1981) distance between two trees
+	 *
+	 * @param s1 tree 1 (as represented by a SplitSystem)
+	 * @param t2 tree 2
+	 */
+	public static double getRobinsonFouldsDistance(SplitSystem s1, Tree t2)
+	{
+		IdGroup idGroup = s1.getIdGroup();
+		SplitSystem s2 = SplitUtils.getSplits(idGroup, t2);
+		
+		if (s1.getLabelCount() != s2.getLabelCount())
+			throw new IllegalArgumentException("Number of labels must be the same!");			
+		
+		int ns1 = s1.getSplitCount();
+		int ns2 = s1.getSplitCount();
+		
+		// number of splits in t1 missing in t2
+		int fn = 0;
+		for (int i = 0; i < ns1; i++)
+		{
+			if (!s2.hasSplit(s1.getSplit(i))) fn++;
+		}
+		
+		// number of splits in t2 missing in t1
+		int fp = 0;
+		for (int i = 0; i < ns2; i++)
+		{
+			if (!s1.hasSplit(s2.getSplit(i))) fp++;
+		}
+		
+		
+		return 0.5*((double) fp + (double) fn);
+	}
+
+	/**
+	 * computes Robinson-Foulds (1981) distance between two trees
+	 * rescaled to a number between 0 and 1
+	 *
+	 * @param t1 tree 1 
+	 * @param t2 tree 2
+	 */
+	public static double getRobinsonFouldsRescaledDistance(Tree t1, Tree t2)
+	{
+		SplitSystem s1 = SplitUtils.getSplits(t1);
+		
+		return getRobinsonFouldsRescaledDistance(s1, t2);
+	}
+
+
+	/**
+	 * computes Robinson-Foulds (1981) distance between two trees
+	 * rescaled to a number between 0 and 1
+	 *
+	 * @param s1 tree 1 (as represented by a SplitSystem)
+	 * @param t2 tree 2
+	 */
+	public static double getRobinsonFouldsRescaledDistance(SplitSystem s1, Tree t2)
+	{
+		return getRobinsonFouldsRescaledDistance(s1, t2)/(double) s1.getSplitCount();
+	}
+
+	private static MersenneTwisterFast random = new MersenneTwisterFast();
+
+	/**
+	 * Returns a uniformly distributed random node from the tree, including
+	 * both internal and external nodes.
+	 */
+	public static Node getRandomNode(Tree tree) {
+		int index = random.nextInt(tree.getExternalNodeCount() + tree.getInternalNodeCount());
+		if (index >= tree.getExternalNodeCount()) {
+			return tree.getInternalNode(index - tree.getExternalNodeCount());
+		} else {
+			return tree.getExternalNode(index);
+		}
+	}
+
+	/**
+	 * Returns the first found node that has a certain name (as determind by the nodes Identifier)
+	 *  in the tree defined by a root node
+	 *  @param tree The Tree supposidly containing such a named node
+	 *  @param name The name of the node to find.
+	 *  @return The node with the name, or null if no such node exists
+	 *	@see Identifier, Node
+	 */
+	 public static final Node getNodeByName(Tree tree, String name) {
+			return getNodeByName(tree.getRoot(),name);
+	 }
+	/**
+	 * Returns the first found node that has a certain name (as determind by the nodes Identifier)
+	 *  in the tree defined by a root node
+	 *  @param root The root node of a tree
+	 *  @param name The name of the node to find.
+	 *  @return The node with the name, or null if no such node exists
+	 *	@see Identifier, Node
+	 */
+	 public static final Node getNodeByName(Node root, String name) {
+			if(root.getIdentifier().getName().equals(name)) {
+				return root;
+			}
+			for(int i = 0 ; i < root.getChildCount() ; i++) {
+				Node result = getNodeByName(root.getChild(i), name);
+				if(result!=null) {
+					return result;
+				}
+			}
+			return null;
+	 }
+
+
+	/**
+	 * Takes a tree (in mutation units) and returns a scaled version of it (in generation units).
+	 * @param mutationRateModel the mutation rate model used for scaling
+	 * and the desired units are expected substitutions then this scale
+	 * factor should be equal to the mutation rate.
+	 * @param newUnits the new units of the tree.
+	 */
+	public static Tree mutationsToGenerations(Tree mutationTree, MutationRateModel muModel) {
+		
+		Tree tree = new SimpleTree(mutationTree);
+
+		for (int i = 0; i < tree.getExternalNodeCount(); i++) {
+			double oldHeight = tree.getExternalNode(i).getNodeHeight();
+			tree.getExternalNode(i).setNodeHeight(muModel.getTime(oldHeight));
+		}
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+			double oldHeight = tree.getInternalNode(i).getNodeHeight();
+			tree.getInternalNode(i).setNodeHeight(muModel.getTime(oldHeight));
+		}
+		NodeUtils.heights2Lengths(tree.getRoot());
+		tree.setUnits(Units.GENERATIONS);
+
+		return tree;
+	}
+
+		/**
+	 * Takes a tree (in generation units) and returns a scaled version of it (in mutation units).
+	 * @param mutationRateModel the mutation rate model used for scaling
+	 * and the desired units are expected substitutions then this scale
+	 * factor should be equal to the mutation rate.
+	 * @param newUnits the new units of the tree.
+	 */
+	public static Tree generationsToMutations(Tree generationTree, MutationRateModel muModel) {
+		
+		Tree tree = new SimpleTree(generationTree);
+
+		for (int i = 0; i < tree.getExternalNodeCount(); i++) {
+			double oldHeight = tree.getExternalNode(i).getNodeHeight();
+			tree.getExternalNode(i).setNodeHeight(muModel.getExpectedSubstitutions(oldHeight));
+		}
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+			double oldHeight = tree.getInternalNode(i).getNodeHeight();
+			tree.getInternalNode(i).setNodeHeight(muModel.getExpectedSubstitutions(oldHeight));
+		}
+		//Don't respect minimum branch lengths
+		NodeUtils.heights2Lengths(tree.getRoot(), false);
+		tree.setUnits(Units.EXPECTED_SUBSTITUTIONS);
+
+		return tree;
+	}
+
+	/**
+	 * Takes a tree and returns a scaled version of it.
+	 * @param rate scale factor. If the original tree is in generations
+	 * and the desired units are expected substitutions then this scale
+	 * factor should be equal to the mutation rate.
+	 * @param newUnits the new units of the tree.
+	 */
+	public static Tree scale(Tree oldTree, double rate, int newUnits) {
+		
+		Tree tree = new SimpleTree(oldTree);
+
+		for (int i = 0; i < tree.getExternalNodeCount(); i++) {
+			double oldHeight = tree.getExternalNode(i).getNodeHeight();
+			tree.getExternalNode(i).setNodeHeight(oldHeight * rate);
+		}
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+			double oldHeight = tree.getInternalNode(i).getNodeHeight();
+			tree.getInternalNode(i).setNodeHeight(oldHeight * rate);
+		}
+		NodeUtils.heights2Lengths(tree.getRoot());
+		tree.setUnits(newUnits);
+
+		return tree;
+	}
+
+	/**
+	 * Given a translation table where the keys are the current
+	 * identifier names and the values are the new identifier names,
+	 * this method replaces the current identifiers in the tree with new
+	 * identifiers.
+	 */
+	public static void renameNodes(Tree tree, Hashtable table) {
+	
+	    tree.createNodeList();
+
+		for (int i = 0; i < tree.getExternalNodeCount(); i++) {
+			String newName =
+				(String)table.get(tree.getExternalNode(i).getIdentifier().getName());
+
+			if (newName != null) {
+				tree.getExternalNode(i).setIdentifier(new Identifier(newName));
+			}
+		}
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+
+		    
+
+			String newName = 
+				(String)table.get(tree.getInternalNode(i).getIdentifier().getName());
+
+			if (newName != null) {
+				tree.getInternalNode(i).setIdentifier(new Identifier(newName));
+			}
+		}
+	}
+	
+	/**
+     	 * Rotates branches by leaf count. 
+	 * WARNING: assumes binary tree!
+     	 */
+	public static void rotateByLeafCount(Tree tree) {
+		
+		rotateByLeafCount(tree.getRoot());
+	}
+
+	/**
+	 * get list of the identifiers of the external nodes
+	 *
+	 * @return leaf identifier group
+	 */
+	public static final IdGroup getLeafIdGroup(Tree tree)
+	{
+		tree.createNodeList();
+		
+		IdGroup labelList = 
+			new SimpleIdGroup(tree.getExternalNodeCount());
+		
+		for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		{
+			labelList.setIdentifier(i, tree.getExternalNode(i).getIdentifier());
+		}
+		
+		return labelList;
+	}
+
+	/**
+	 * map external identifiers in the tree to a set of given identifiers
+	 * (which can be larger than the set of external identifiers but
+	 * must contain all of them)
+	 *
+	 * @param idGroup an ordered group of identifiers
+	 *
+	 * @return list of links
+	 */
+	public static final int[] mapExternalIdentifiers(IdGroup idGroup, Tree tree)
+		throws IllegalArgumentException {
+		
+		tree.createNodeList();
+		
+		int[] alias = new int[tree.getExternalNodeCount()];
+		
+		// Check whether for each label in tree there is
+		// a correspondence in the given set of labels
+		for (int i = 0; i < tree.getExternalNodeCount(); i++)
+		{
+			alias[i] = idGroup.whichIdNumber(tree.getExternalNode(i).getIdentifier() .getName());
+			
+			if (alias[i] == -1)
+			{
+				throw new IllegalArgumentException("Tree label "
+					+ tree.getExternalNode(i).getIdentifier() +
+				" not present in given set of labels");
+			}
+		}
+
+		return alias;
+	}
+
+	/**
+	 *  Makes a copy of this tree for every possible rooting 
+	 * and fills a vector with all possible rootings of the given tree.
+	 */
+	public static void getEveryRoot(Tree tree, Vector roots) {
+		
+		NodeUtils.heights2Lengths(tree.getRoot());
+
+		// must be able to reference every node in tree uniquely
+		labelInternalNodes(tree);
+
+		Vector identifierList = 
+			new Vector(tree.getInternalNodeCount() + tree.getExternalNodeCount() - 2);
+	
+		// add all nodes except root node and root node's first child
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+			if ((tree.getInternalNode(i) != tree.getRoot()) && 
+			(tree.getInternalNode(i) != tree.getRoot().getChild(0))) {
+			
+				identifierList.addElement(tree.getInternalNode(i).getIdentifier());
+			}
+		}
+		for (int i = 0; i < tree.getExternalNodeCount(); i++) {
+			if (tree.getExternalNode(i) != tree.getRoot().getChild(0)) {
+				identifierList.addElement(tree.getExternalNode(i).getIdentifier());
+			}
+		}
+
+		//WHATS GOING ON?
+		for (int i = 0; i < identifierList.size(); i++) {
+			Log.getDefaultLogger().log("identifier " + i + " = " + 
+				((Identifier)identifierList.elementAt(i)));
+		}
+
+		for (int i = 0; i < identifierList.size(); i++) {
+			roots.addElement(NodeFactory.createNode(tree.getRoot()));
+		}
+	
+		for (int i = 0; i < roots.size(); i++) {
+			Identifier id = (Identifier)identifierList.elementAt(i);
+			Log.getDefaultLogger().log("Rooting above " + id);
+			
+			Node node = NodeUtils.rootAbove(id, ((Node)roots.elementAt(i)));
+
+			roots.setElementAt(new SimpleTree(node), i);
+		}
+	}
+
+	/**
+	 * Labels the internal nodes of the tree using numbers starting from 0.
+	 * Skips numbers already used by external leaves.
+	 */
+	public static final void labelInternalNodes(Tree tree) {
+
+		int counter = 0;
+		String pos = "0";
+
+		IdGroup ids = getLeafIdGroup(tree);
+
+		for (int i = 0; i < tree.getInternalNodeCount(); i++) {
+			
+			//if label already used find a better one
+			while (ids.whichIdNumber(pos) >= 0) {
+				counter += 1;
+				pos = "" + counter;
+			}
+			tree.getInternalNode(i).setIdentifier(new Identifier(pos));
+			counter += 1;
+			pos = "" + counter;
+		}
+	}
+
+	/**
+	 * Extracts a time order character data from a tree.
+	 */
+	public static TimeOrderCharacterData extractTimeOrderCharacterData(Tree tree, int units) {
+		
+		tree.createNodeList();
+
+		IdGroup identifiers = getLeafIdGroup(tree);
+
+		TimeOrderCharacterData tocd = new TimeOrderCharacterData(identifiers, units);
+
+		double[] times = new double[tree.getExternalNodeCount()];
+		
+		// WARNING: following code assumes that getLeafIdGroup 
+		//has same order as external node list.
+		for (int i = 0; i < times.length; i++) {
+			times[i] = tree.getExternalNode(i).getNodeHeight();	
+		}
+		
+		// this sets the ordinals as well
+		tocd.setTimes(times, units);
+
+		return tocd;
+	}
+
+	/**
+	 * Extracts an alignment from a tree.
+	 */
+	public static Alignment extractAlignment(Tree tree, boolean leaveSeqsInTree) {
+		
+		tree.createNodeList();
+		String[] sequences = new String[tree.getExternalNodeCount()];
+		Identifier[] ids = new Identifier[sequences.length];
+		
+		for (int i = 0; i < sequences.length; i++) {
+			sequences[i] = new String(tree.getExternalNode(i).getSequence());
+			ids[i] = tree.getExternalNode(i).getIdentifier();
+			if (!leaveSeqsInTree) {
+				tree.getExternalNode(i).setSequence(null);
+			}
+		}
+
+		return new SimpleAlignment(ids, sequences, "-");
+	}
+
+	/**
+	 * Extracts an alignment from a tree.
+	 */
+	public static Alignment extractAlignment(Tree tree) {
+		return extractAlignment(tree, true);	
+	}
+
+
+	/**
+	 * print a this tree in New Hampshire format
+	 * (including distances and internal labels)
+	 *
+	 * @param out output stream
+	 */
+	public static void printNH(Tree tree, PrintWriter out) {
+		printNH(tree, out, true, true);
+	}
+
+	/**
+	 * print this tree in New Hampshire format
+	 *
+	 * @param out output stream
+	 * @param printLengths boolean variable determining whether
+	 *		branch lengths should be included in output
+	 * @param printInternalLabels boolean variable determining whether
+	 *		internal labels should be included in output
+	 */
+	public static void printNH(Tree tree, PrintWriter out, 
+		boolean printLengths, boolean printInternalLabels) {
+		
+		NodeUtils.printNH(out, tree.getRoot(), 
+			printLengths, printInternalLabels);
+		out.println(";");
+	}
+	
+	/*
+	 * compute distance of external node a to all other leaves
+	 * (computational complexity of this method is only O(n), following
+	 * D.Bryant and P. Wadell. 1998. MBE 15:1346-1359)
+	 *
+	 * @param tree tree
+	 * @param a node
+	 * @param dist array for the node-to-node distance distances
+	 * @param idist array for the distance between a and all internal nodes
+	 * @param countEdges boolean variable deciding whether the actual
+	 *                   branch lengths are used in computing the distance
+	 *                   or whether simply all edges larger or equal a certain
+	 *                   threshold length are counted (each with weight 1.0)
+	 * @param epsilon    minimum branch length for a which an edge is counted
+	 */
+	public static void computeAllDistances(Tree tree,
+		int a, double[] dist, double[] idist,
+		boolean countEdges, double epsilon)
+	{
+		tree.createNodeList();
+		
+		dist[a] = 0.0;
+		
+		Node node = tree.getExternalNode(a);
+		
+		computeNodeDist(node, node.getParent(), dist, idist, countEdges, epsilon);
+	}
+	
+	private static void computeNodeDist(Node origin, Node center,
+		double[] dist, double[] idist,
+		boolean countEdges, double epsilon)
+	{
+		int indexCenter = center.getNumber();
+		int indexOrigin = origin.getNumber();
+		double[] distCenter;
+		double[] distOrigin;
+		if (center.isLeaf()) distCenter = dist;
+		else distCenter = idist;
+		if (origin.isLeaf()) distOrigin = dist;
+		else distOrigin = idist;
+		
+		double len;
+		double tmp;
+		if (origin.getParent() == center)
+		{
+			// center is parent of origin
+			tmp = origin.getBranchLength();
+		}
+		else
+		{
+			// center is child of origin
+			tmp = center.getBranchLength();
+		}
+		
+		
+		if (countEdges) // count all edges >= epsilon
+		{
+			if (tmp < epsilon)
+			{
+				len = 0.0;
+			}
+			else
+			{
+				len = 1.0;
+			}
+		}
+		else // use branch lengths
+		{
+			len = tmp;
+		}
+		
+		
+		distCenter[indexCenter] = distOrigin[indexOrigin] + len;
+
+		if (!center.isLeaf())
+		{
+			for (int i = 0; i < center.getChildCount(); i++)
+			{
+				Node c = center.getChild(i);
+				
+				if (c != origin) computeNodeDist(center, c, dist, idist, countEdges, epsilon);
+			}
+			
+			if (!center.isRoot())
+			{
+				Node p = center.getParent();
+				
+				if (p != origin) computeNodeDist(center,p, dist, idist, countEdges, epsilon);
+			}
+		}
+	}
+
+
+	private static Node[] path;
+	
+	/**
+	 * compute distance between two external nodes
+	 * 
+	 * @param tree tree
+	 * @param a external node 1
+	 * @param b external node 2
+	 *
+	 * @return distance between node a and b
+	 */
+	public static final double computeDistance(Tree tree, int a, int b)
+	{
+		tree.createNodeList();
+		int maxLen = tree.getInternalNodeCount()+1;
+		if (path == null || path.length < maxLen)
+		{
+			path = new Node[maxLen];
+		}	
+		
+		// len might be different from path.length
+		int len = findPath(tree, a, b);
+		
+		double dist = 0.0;
+		for (int i = 0; i < len; i++)
+		{
+			dist += path[i].getBranchLength();
+		}
+		
+		return dist;
+	}
+
+	// Find path between external nodes a and b
+	// After calling this method path contains all nodes
+	// with edges lying between a and b (including a and b)
+	// (note that the node lying on the intersection of a-root
+	// and b-root is NOT contained because this node does
+	// not contain a branch of the path)
+	// The length of the path is also returned
+	private static final int findPath(Tree tree, int a, int b)
+	{
+		// clean path
+		for (int i = 0; i < path.length; i++)
+		{
+			path[i] = null;
+		}
+		// path from node a to root
+		Node node = tree.getExternalNode(a);
+		int len = 0;
+		path[len] = node;
+		len++;
+		while (!node.isRoot())
+		{
+			node = node.getParent();
+			path[len] = node;
+			len++;
+		}
+		
+		// find intersection with path from node b to root
+		Node stopNode = null;
+		node = tree.getExternalNode(b);
+		while (!node.isRoot())
+		{
+			node = node.getParent();
+			int pos = findInPath(node);
+			
+			if (pos != -1)
+			{
+				len = pos;
+				stopNode = node;
+				break;
+			}
+		}
+		
+		// fill rest of path
+		node = tree.getExternalNode(b);
+		path[len] = node;
+		len++;
+		node = node.getParent();
+		while (node != stopNode)
+		{
+			path[len] = node;
+			len++;
+			node = node.getParent();
+		}
+		
+		// clean rest
+		for (int i = len; i < path.length; i++)
+		{
+			path[i] = null;
+		}
+		
+		return len;
+	}
+	
+	private static final int findInPath(Node node)
+	{
+		for (int i = 0; i < path.length; i++)
+		{
+			if (path[i] == node)
+			{
+				return i;
+			}
+			else if (path[i] == null)
+			{
+				return -1;
+			}
+		}
+		
+		return -1;
+	}
+
+	/**
+     	 * Rotates branches by leaf count.
+	 * WARNING: assumes binary tree!
+			 */
+    	private static void rotateByLeafCount(Node node) {
+		if (!node.isLeaf()) {
+	    		
+			if (NodeUtils.getLeafCount(node.getChild(0)) >
+				NodeUtils.getLeafCount(node.getChild(1))) {
+			
+				Node temp = node.getChild(0);
+				node.removeChild(0);
+				node.addChild(temp);
+			}
+			
+			//List childList = Arrays.asList(children);
+			//Collections.sort(childList, leafCountComparator);
+			//children = (Coalescent[])childList.toArray(children);	
+	    
+	    		for (int i = 0; i < node.getChildCount(); i++) {
+				rotateByLeafCount(node.getChild(i));
+			}
+		} 
+	}
+	
+	
+	
+	public static void report(Tree tree, PrintWriter out)
+	{
+		printASCII(tree, out);
+		out.println();
+		branchInfo(tree, out);
+		out.println();
+		heightInfo(tree, out);
+	}
+	
+	
+	private static FormattedOutput format;
+	
+	private static double proportion;
+	private static int minLength;
+	private static boolean[] umbrella;
+	private static int[] position;
+
+	private static int numExternalNodes;
+	private static int numInternalNodes;
+	private static int numBranches;
+
+	
+	// Print picture of current tree in ASCII
+	private static void printASCII(Tree tree, PrintWriter out)
+	{
+		format = FormattedOutput.getInstance();
+		
+		tree.createNodeList();
+
+		numExternalNodes = tree.getExternalNodeCount();
+		numInternalNodes = tree.getInternalNodeCount();
+		numBranches = numInternalNodes+numExternalNodes-1;
+		
+		umbrella = new boolean[numExternalNodes];
+		position = new int[numExternalNodes];
+		
+		minLength = (Integer.toString(numBranches)).length() + 1;
+		
+		int MAXCOLUMN = 40;
+		Node root = tree.getRoot();
+		if (root.getNodeHeight() == 0.0) {
+			NodeUtils.lengths2Heights(root);
+		}
+		proportion = (double) MAXCOLUMN/root.getNodeHeight();
+	
+		for (int n = 0; n < numExternalNodes; n++)
+		{
+			umbrella[n] = false;
+		}
+		
+		position[0] = 1;
+		for (int i = root.getChildCount()-1; i > -1; i--)
+		{
+			printNodeInASCII(out, root.getChild(i), 1, i, root.getChildCount());
+			if (i != 0)
+			{
+				putCharAtLevel(out, 0, '|');
+				out.println();
+			}
+		}
+	}
+
+	// Print branch information
+	private static void branchInfo(Tree tree, PrintWriter out)
+	{
+		
+		//
+		// CALL PRINTASCII FIRST !!!
+		//
+		
+		// check if some SE values differ from the default zero
+		boolean showSE = false;
+		for (int i = 0; i < numExternalNodes && showSE == false; i++)
+		{
+			if (tree.getExternalNode(i).getBranchLengthSE() != 0.0)
+			{
+				showSE = true;
+			}
+			if (i < numInternalNodes-1)
+			{
+				if (tree.getInternalNode(i).getBranchLengthSE() != 0.0)
+				{
+					showSE = true;
+				}			
+			}
+		}
+		
+		format.displayIntegerWhite(out, numExternalNodes);
+		out.print("   Length    ");
+		if (showSE) out.print("S.E.      ");
+		out.print("Label     ");
+		if (numInternalNodes > 1)
+		{
+			format.displayIntegerWhite(out, numBranches);
+			out.print("        Length    ");
+			if (showSE) out.print("S.E.      ");
+			out.print("Label");
+		}
+		out.println();
+		
+		for (int i = 0; i < numExternalNodes; i++)
+		{
+			format.displayInteger(out, i+1, numExternalNodes);
+			out.print("   ");
+			format.displayDecimal(out, tree.getExternalNode(i).getBranchLength(), 5);
+			out.print("   ");
+			if (showSE)
+			{
+				format.displayDecimal(out, tree.getExternalNode(i).getBranchLengthSE(), 5);
+				out.print("   ");
+			}
+			format.displayLabel(out, tree.getExternalNode(i).getIdentifier().getName(), 10);
+			
+			if (i < numInternalNodes-1)
+			{
+				format.multiplePrint(out, ' ', 5);				
+				format.displayInteger(out, i+1+numExternalNodes, numBranches);
+				out.print("   ");
+				format.displayDecimal(out, tree.getInternalNode(i).getBranchLength(), 5);
+				out.print("   ");
+				if (showSE)
+				{
+					format.displayDecimal(out, tree.getInternalNode(i).getBranchLengthSE(), 5);
+					out.print("   ");
+				}
+				format.displayLabel(out, tree.getInternalNode(i).getIdentifier().getName(), 10);			
+			}
+			
+			out.println();
+		}
+	}
+
+
+	// Print height information
+	private static void heightInfo(Tree tree, PrintWriter out)
+	{
+		//
+		// CALL PRINTASCII FIRST
+		// 
+		
+		if (tree.getRoot().getNodeHeight() == 0.0) {
+			NodeUtils.lengths2Heights(tree.getRoot());
+		}
+		
+		// check if some SE values differ from the default zero
+		boolean showSE = false;
+		for (int i = 0; i < numInternalNodes && showSE == false; i++)
+		{
+			if (tree.getInternalNode(i).getNodeHeightSE() != 0.0)
+			{
+				showSE = true;
+			}			
+		}
+		
+		format.displayIntegerWhite(out, numExternalNodes);
+		out.print("   Height    ");
+		format.displayIntegerWhite(out, numBranches);
+		out.print("        Height    ");
+		if (showSE) out.print("S.E.");
+		
+		out.println();
+		
+		for (int i = 0; i < numExternalNodes; i++)
+		{
+			format.displayInteger(out, i+1, numExternalNodes);
+			out.print("   ");
+			format.displayDecimal(out, tree.getExternalNode(i).getNodeHeight(), 7);
+			out.print("   ");
+			
+			if (i < numInternalNodes)
+			{
+				format.multiplePrint(out, ' ', 5);				
+				
+				if (i == numInternalNodes-1)
+				{
+					out.print("R");
+					format.multiplePrint(out, ' ', Integer.toString(numBranches).length()-1);
+				}
+				else
+				{
+					format.displayInteger(out, i+1+numExternalNodes, numBranches);
+				}
+				
+				out.print("   ");
+				format.displayDecimal(out, tree.getInternalNode(i).getNodeHeight(), 7);
+				out.print("   ");
+				if (showSE)
+				{
+					format.displayDecimal(out, tree.getInternalNode(i).getNodeHeightSE(), 7);
+				}			
+			}
+			
+			out.println();
+		}
+	}
+
+
+
+	private static void printNodeInASCII(PrintWriter out, Node node, int level, int m, int maxm)
+	{
+		position[level] = (int) (node.getBranchLength()*proportion);
+		
+		if (position[level] < minLength)
+		{
+			position[level] = minLength;
+		}
+
+		if (node.isLeaf()) // external branch
+		{
+			if (m == maxm-1)
+			{
+				umbrella[level-1] = true;
+			}
+			
+			printlnNodeWithNumberAndLabel(out, node, level);
+			
+			if (m == 0)
+			{
+				umbrella[level-1] = false;
+			}
+		}
+		else // internal branch
+		{
+			for (int n = node.getChildCount()-1; n > -1; n--)
+			{
+				printNodeInASCII(out, node.getChild(n), level+1, n, node.getChildCount());
+				
+				if (m == maxm-1 && n == node.getChildCount()/2)
+				{
+					umbrella[level-1] = true;
+				}
+				
+				if (n != 0)
+				{
+					if (n == node.getChildCount()/2)
+					{
+						printlnNodeWithNumberAndLabel(out, node, level);
+					}
+					else
+					{
+						for (int i = 0; i < level+1; i++)
+						{
+							if (umbrella[i])
+							{
+								putCharAtLevel(out, i, '|');
+							}
+							else
+							{
+								putCharAtLevel(out, i, ' ');
+							}
+						}
+						out.println();
+					}
+				}
+				
+				if (m == 0 && n == node.getChildCount()/2)
+				{
+					umbrella[level-1] = false;
+				}
+			}
+		}
+	}
+
+
+
+	private static void printlnNodeWithNumberAndLabel(PrintWriter out, Node node, int level)
+	{
+		for (int i = 0; i < level-1; i++)
+		{
+			if (umbrella[i])
+			{
+				putCharAtLevel(out, i, '|');
+			}
+			else
+			{
+				putCharAtLevel(out, i, ' ');
+			}
+		}
+	
+		putCharAtLevel(out, level-1, '+');
+		
+		int branchNumber;
+		if (node.isLeaf())
+		{
+			branchNumber = node.getNumber()+1;
+		}
+		else
+		{
+			branchNumber = node.getNumber()+1+numExternalNodes;
+		}
+		 
+		String numberAsString = Integer.toString(branchNumber);
+
+		int numDashs = position[level]-numberAsString.length();		
+		for (int i = 0; i < numDashs; i++)
+		{
+			out.print('-');
+		}
+		out.print(numberAsString);
+		
+		if (node.isLeaf())
+		{
+			out.println(" " + node.getIdentifier());
+		}
+		else
+		{
+			if (!node.getIdentifier().equals(Identifier.ANONYMOUS))
+			{
+				out.print("(" + node.getIdentifier() + ")");
+			}
+			out.println();
+		}
+	}
+
+
+	
+	private static void putCharAtLevel(PrintWriter out, int level, char c)
+	{
+		int n = position[level]-1;
+		for (int i = 0; i < n; i++)
+		{
+			out.print(' ');
+		}
+		out.print(c);
+	}
+	
+	
+}
+
diff --git a/LibrarySource/pal/tree/UPGMATree.java b/LibrarySource/pal/tree/UPGMATree.java
new file mode 100644
index 0000000..dd32f91
--- /dev/null
+++ b/LibrarySource/pal/tree/UPGMATree.java
@@ -0,0 +1,201 @@
+// UPGMATree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+// Known bugs and limitations:
+// - computational complexity O(numSeqs^3)
+//   (this could be brought down to O(numSeqs^2)
+//   but this needs more clever programming ...)
+
+
+package pal.tree;
+
+import pal.distance.*;
+
+/**
+ * constructs a UPGMA tree from pairwise distances
+ *
+ * @version $Id: UPGMATree.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class UPGMATree extends SimpleTree
+{
+	//
+	// Public stuff
+	//	
+
+	/**
+	 * constructor UPGMA tree
+	 *
+	 * @param m distance matrix
+	 */
+	public UPGMATree(DistanceMatrix m)
+	{
+		if (m.numSeqs < 2)
+		{
+			new IllegalArgumentException("LESS THAN 2 TAXA IN DISTANCE MATRIX");
+		}
+		if (!m.isSymmetric())
+		{
+			new IllegalArgumentException("UNSYMMETRIC DISTANCE MATRIX");
+		}
+		
+		init(m);
+
+		while (true)
+		{
+			findNextPair();
+			newBranchLengths();
+			
+			if (numClusters == 2)
+			{
+				break;
+			}
+			
+			newCluster();
+		}
+		
+		finish();
+		createNodeList();
+	}
+
+
+	//
+	// Private stuff
+	//
+	
+	private int numClusters;
+	private Node newCluster;
+	private int besti, abi;
+	private int bestj, abj;
+	private int[] alias;
+	private double[][] distance;
+
+	private double[] height;
+	private int[] oc;
+
+	private double getDist(int a, int b)
+	{
+		return distance[alias[a]][alias[b]];
+	}
+	
+	private void init(DistanceMatrix m)
+	{
+		numClusters = m.numSeqs;
+
+		distance = new double[numClusters][numClusters];
+		for (int i = 0; i < numClusters; i++)
+		{
+			for (int j = 0; j < numClusters; j++)
+			{
+				distance[i][j] = m.distance[i][j];
+			}
+		}
+
+		for (int i = 0; i < numClusters; i++)
+		{
+			Node tmp = NodeFactory.createNode();
+			tmp.setIdentifier(m.getIdentifier(i));
+			getRoot().addChild(tmp);
+		}
+		
+		alias = new int[numClusters];
+		for (int i = 0; i < numClusters; i++)
+		{
+			alias[i] = i;
+		}
+				
+		height = new double[numClusters];
+		oc = new int[numClusters];
+		for (int i = 0; i < numClusters; i++)
+		{
+			height[i] = 0.0;
+			oc[i] = 1;
+		}
+	}
+
+	private void finish()
+	{
+		distance = null;		
+	}
+
+	private void findNextPair()
+	{
+		besti = 0;
+		bestj = 1;
+		double dmin = getDist(0, 1);
+		for (int i = 0; i < numClusters-1; i++)
+		{
+			for (int j = i+1; j < numClusters; j++)
+			{
+				if (getDist(i, j) < dmin)
+				{
+					dmin = getDist(i, j);
+					besti = i;
+					bestj = j;
+				}
+			}
+		}
+		abi = alias[besti];
+		abj = alias[bestj];
+	}
+
+	private void newBranchLengths()
+	{
+		double dij = getDist(besti, bestj);
+		
+		getRoot().getChild(besti).setBranchLength(dij/2.0-height[abi]);
+		getRoot().getChild(bestj).setBranchLength(dij/2.0-height[abj]);
+	}
+
+	private void newCluster()
+	{
+		// Update distances
+		for (int k = 0; k < numClusters; k++)
+		{
+			if (k != besti && k != bestj)
+			{
+				int ak = alias[k];	
+				distance[ak][abi] = distance[abi][ak] = updatedDistance(besti, bestj, k);
+			}
+		}
+		distance[abi][abi] = 0.0;
+
+		// Update UPGMA variables
+		height[abi] = getDist(besti, bestj)/2.0;
+		oc[abi] += oc[abj];
+		
+		// Index besti now represent the new cluster
+		NodeUtils.joinChilds(getRoot(), besti, bestj);
+		
+		// Update alias
+		for (int i = bestj; i < numClusters-1; i++)
+		{
+			alias[i] = alias[i+1];
+		}
+		
+		numClusters--;
+	}
+
+	
+	/**
+	 * compute updated distance between the new cluster (i,j)
+	 * to any other cluster k
+	 */
+	private double updatedDistance(int i, int j, int k)
+	{
+		int ai = alias[i];
+		int aj = alias[j];
+		
+		double ocsum = (double) (oc[ai]+oc[aj]);
+		
+		return 	(oc[ai]/ocsum)*getDist(k, i) +
+			(oc[aj]/ocsum)*getDist(k, j);
+	}
+}
+
diff --git a/LibrarySource/pal/tree/UnconstrainedTree.java b/LibrarySource/pal/tree/UnconstrainedTree.java
new file mode 100644
index 0000000..a509822
--- /dev/null
+++ b/LibrarySource/pal/tree/UnconstrainedTree.java
@@ -0,0 +1,110 @@
+// UnconstrainedTree.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+
+package pal.tree;
+
+import pal.misc.*;
+
+
+/**
+ * provides parameter interface to an unconstrained tree
+ * (parameters are all available branch lengths)
+ *
+ * @version $Id: UnconstrainedTree.java,v 1.5 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ * @author Alexei Drummond
+ */
+public class UnconstrainedTree extends ParameterizedTree
+{
+	//
+	// Public stuff
+	//
+
+	/**
+	 * take any tree and afford it with an interface
+	 * suitable for an unconstrained tree (parameters
+	 * are all available branch lengths) 
+	 */
+	public UnconstrainedTree(Tree t)
+	{
+		setBaseTree(t);
+		
+		if (getRoot().getChildCount() < 3)
+		{
+			throw new IllegalArgumentException(
+			"The root node must have at least three childs!");
+		}
+		
+		// set default values
+		for (int i = 0; i < getNumParameters(); i++)
+		{
+			setParameter(getDefaultValue(i), i);
+		}
+	}
+	
+	
+	// interface Parameterized
+
+	public int getNumParameters()
+	{
+		return getInternalNodeCount()+getExternalNodeCount()-1;
+	}
+
+	public void setParameter(double param, int n)
+	{
+		if (n < getExternalNodeCount())
+		{
+			getExternalNode(n).setBranchLength(param);
+		}
+		else
+		{
+			getInternalNode(n-getExternalNodeCount()).setBranchLength(param);
+		}
+	}
+
+	public double getParameter(int n)
+	{
+		if (n < getExternalNodeCount())
+		{
+			return getExternalNode(n).getBranchLength();
+		}
+		else
+		{
+			return getInternalNode(n-getExternalNodeCount()).getBranchLength();
+		}
+	}
+
+	public void setParameterSE(double paramSE, int n)
+	{
+		if (n < getExternalNodeCount())
+		{
+			getExternalNode(n).setBranchLengthSE(paramSE);
+		}
+		else
+		{
+			getInternalNode(n-getExternalNodeCount()).setBranchLengthSE(paramSE);
+		}
+	}
+
+	public double getLowerLimit(int n)
+	{
+		return BranchLimits.MINARC;
+	}
+	
+	public double getUpperLimit(int n)
+	{
+		return BranchLimits.MAXARC;
+	}
+	
+	public double getDefaultValue(int n)
+	{
+		return BranchLimits.DEFAULT_LENGTH;
+	}
+}
+
diff --git a/LibrarySource/pal/tree/makefile b/LibrarySource/pal/tree/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/tree/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/tree/package.html b/LibrarySource/pal/tree/package.html
new file mode 100644
index 0000000..fe66302
--- /dev/null
+++ b/LibrarySource/pal/tree/package.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+Classes for providing the data structure of
+trees, for constructing and modifying trees, and for parameterizing
+trees (e.g., clock constraint). 
+</body>
+</html>
+
diff --git a/LibrarySource/pal/util/Comparable.java b/LibrarySource/pal/util/Comparable.java
new file mode 100644
index 0000000..b102e7b
--- /dev/null
+++ b/LibrarySource/pal/util/Comparable.java
@@ -0,0 +1,36 @@
+// Comparable.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.util;
+
+/**
+ * interface for an object that is comparable.
+ * This interface is analogous to the Comparable interface in
+ * Java 1.2, and it should be superceded by the JDK 1.2 collections
+ * framework when PAL is moved to 1.2.
+ *
+ * @version $Id: Comparable.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Comparable
+{
+	/**
+	 * Returns a number representing the ordering relationship that
+	 * the object has with the given object.
+	 * A negative number indicates that the object is "smaller" than
+	 * the parameter, a positive number means it is "larger" and zero
+	 * indicates that the objects are equal.
+	 */
+	int compareTo(Object o);
+
+	/**
+	 * Returns true if this object is equal to the given object.
+	 */
+	boolean equals(Object o);
+}
+
diff --git a/LibrarySource/pal/util/ComparableDouble.java b/LibrarySource/pal/util/ComparableDouble.java
new file mode 100644
index 0000000..2c6feae
--- /dev/null
+++ b/LibrarySource/pal/util/ComparableDouble.java
@@ -0,0 +1,50 @@
+// ComparableDouble.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.util;
+
+/** 
+ * This class is unfortunate but necessary to conform to JDK 1.1
+ *
+ * @version $Id: ComparableDouble.java,v 1.3 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public class ComparableDouble implements Comparable {
+	
+	private double value;
+
+	public ComparableDouble(double d) {
+		value = d;
+	}
+
+	public int compareTo(Object o) {
+		
+		ComparableDouble cd = (ComparableDouble)o;
+
+		if (value < cd.value) {
+			return -1;
+		} else if (value > cd.value) {
+			return 1;
+		} else return 0;
+	}
+
+	public boolean equals(Object o) {
+	
+		ComparableDouble cd = (ComparableDouble)o;
+		return cd.value == value;
+	}
+
+	public double doubleValue() {
+		return value;
+	}
+
+	public String toString() {
+		return value + "";
+	}
+}
+
diff --git a/LibrarySource/pal/util/Comparator.java b/LibrarySource/pal/util/Comparator.java
new file mode 100644
index 0000000..0dd4d84
--- /dev/null
+++ b/LibrarySource/pal/util/Comparator.java
@@ -0,0 +1,37 @@
+// Comparator.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.util;
+
+/**
+ * interface for an object that can compare other objects for the
+ * purposes of ordering them.
+ * This interface is analogous to the Comparator interface in
+ * Java 1.2 and higher, and it should be superceded by the collections
+ * framework when PAL is moved to 1.2 or higher.
+ *
+ * @version $Id: Comparator.java,v 1.2 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ */
+public interface Comparator
+{
+	/**
+	 * Returns a number representing the ordering relationship that
+	 * the two objects have.
+	 * A negative number indicates that the first object is "smaller" than
+	 * the second object, a positive number means it is "larger" and zero
+	 * indicates that the objects are equal.
+	 */
+	int compare(Object o1, Object o2);
+
+	/**
+	 * Returns true if the two objects are equal.
+	 */
+	boolean equals(Object o1, Object o2);
+}
+
diff --git a/LibrarySource/pal/util/HeapSort.java b/LibrarySource/pal/util/HeapSort.java
new file mode 100644
index 0000000..5cdd146
--- /dev/null
+++ b/LibrarySource/pal/util/HeapSort.java
@@ -0,0 +1,411 @@
+// HeapSort.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.util;
+
+import pal.math.*;
+
+import java.util.*;
+
+/**
+ * sorts numbers and comparable objects by treating contents of array as a binary tree.
+ * KNOWN BUGS: There is a horrible amount of code duplication here!
+ *
+ * @version $Id: HeapSort.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Alexei Drummond
+ * @author Korbinian Strimmer
+ */
+public class HeapSort {
+	
+	//
+	// Public stuff
+	//
+
+	/**
+	 * Sorts an array of indices to vector of comparable objects 
+	 * into increasing order.
+	 */
+	public static void sort(Vector array, int[] indices) {
+	
+		// ensures we are starting with valid indices
+		for (int i = 0; i < indices.length; i++) {
+			indices[i] = i;
+		}
+	
+		int temp;
+		int j, n = array.size();
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, indices, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = indices[0];
+			indices[0] = indices[j];
+			indices[j] = temp;
+			adjust(array, indices, 1, j);
+		}
+	}	
+
+	/**
+	 * Sorts a vector of comparable objects into increasing order.
+	 */
+	public static void sort(Vector array) {
+	
+		Object temp;
+		int j, n = array.size();
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = array.elementAt(0);
+			array.setElementAt(array.elementAt(j), 0);
+			array.setElementAt(temp, j);
+			adjust(array, 1, j);
+		}
+	}	
+
+	/**
+	 * Sorts an array of comparable objects into increasing order.
+	 */
+	public static void sort(pal.util.Comparable[] array) {
+	
+		pal.util.Comparable temp;
+		int j, n = array.length;
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = array[0];
+			array[0] = array[j];
+			array[j] = temp;
+			adjust(array, 1, j);
+		}
+	}
+
+	/**
+	 * Sorts an array of objects into increasing order given a comparator.
+	 */
+	public static void sort(Object[] array, Comparator c) {
+	
+		Object temp;
+		int j, n = array.length;
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, c, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = array[0];
+			array[0] = array[j];
+			array[j] = temp;
+			adjust(array, c, 1, j);
+		}
+	}	
+
+	/**
+	 * Sorts an array of doubles into increasing order.
+	 */
+	public static void sort(double[] array) {
+	
+		double temp;
+		int j, n = array.length;
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = array[0];
+			array[0] = array[j];
+			array[j] = temp;
+			adjust(array, 1, j);
+		}
+	}
+
+	/**
+	 * Sorts an array of indices into an array of doubles
+	 * into increasing order.
+	 */
+	public static void sort(double[] array, int[] indices)
+	{
+	
+		// ensures we are starting with valid indices
+		for (int i = 0; i < indices.length; i++)
+		{
+			indices[i] = i;
+		}
+	
+		int temp;
+		int j, n = array.length;
+		
+		// turn input array into a heap
+		for (j = n/2; j > 0; j--) {
+			adjust(array, indices, j, n);
+		}
+
+		// remove largest elements and put them at the end
+		// of the unsorted region until you are finished
+		for (j = n-1; j > 0; j--) {
+			temp = indices[0];
+			indices[0] = indices[j];
+			indices[j] = temp;
+			adjust(array, indices, 1, j);
+		}
+	}
+
+
+	/** test harness for heapsort algorithm */
+	public static void main(String[] args) {
+	
+		MersenneTwisterFast m = new MersenneTwisterFast();
+
+		int testSize = 100;
+
+		// test array of Comparable objects
+		
+		pal.util.ComparableDouble[] test = new pal.util.ComparableDouble[testSize];
+		
+		for (int i = 0; i < test.length; i++) {
+			test[i] = new pal.util.ComparableDouble(m.nextInt(testSize * 10));
+		}
+
+		sort(test);
+		for (int i = 0; i < test.length; i++) {
+			System.out.print(test[i] + " ");
+		}
+		System.out.println();
+
+		// test index to Vector of Comparable objects
+		
+		Vector testv = new Vector();
+		int[] indices = new int[testSize];
+		
+		for (int i = 0; i < testSize; i++) {
+			testv.addElement(new pal.util.ComparableDouble(m.nextInt(testSize * 10)));
+		}
+
+		sort(testv, indices);
+		for (int i = 0; i < test.length; i++) {
+			System.out.print(testv.elementAt(indices[i]) + " ");
+		}
+		System.out.println();
+		
+		
+		// test index to array of doubles
+		
+		double[] testd = new double[testSize];
+		//int[] indices = new int[testSize];
+		
+		for (int i = 0; i < testSize; i++)
+		{
+			testd[i] = m.nextInt(testSize * 10);
+		}
+
+		sort(testd, indices);
+		for (int i = 0; i < test.length; i++)
+		{
+			System.out.print(testd[indices[i]] + " ");
+		}
+		System.out.println();
+
+	}
+
+	// PRIVATE STUFF
+
+	/**
+	 * helps sort an array of indices into a vector of comparable objects.
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(Vector array, int[] indices, int lower, int upper) {
+	
+		int j, k;
+		int temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper) {
+			if ((k < upper) && (((pal.util.Comparable)array.elementAt(indices[k-1])).compareTo(array.elementAt(indices[k])) < 0)) {
+				k += 1;
+			}
+			if (((pal.util.Comparable)array.elementAt(indices[j-1])).compareTo(array.elementAt(indices[k-1])) < 0) {
+				temp = indices[j-1];
+				indices[j-1] = indices[k-1];
+				indices[k-1] = temp;
+			}
+			j = k;
+			k *= 2;
+		}
+	} 
+
+	/**
+	 * helps sort an vector of comparable objects.
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(Vector array, int lower, int upper) {
+	
+		int j, k;
+		Object temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper) {
+			if ((k < upper) && (((pal.util.Comparable)array.elementAt(k-1)).compareTo(array.elementAt(k)) < 0)) {
+				k += 1;
+			}
+			if (((pal.util.Comparable)array.elementAt(j-1)).compareTo(array.elementAt(k-1)) < 0) {
+				temp = array.elementAt(j-1);
+				array.setElementAt(array.elementAt(k-1), j-1);
+				array.setElementAt(temp, k-1);
+			}
+			j = k;
+			k *= 2;
+		}
+	} 
+
+	/**
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(pal.util.Comparable[] array, int lower, int upper) {
+	
+		int j, k;
+		pal.util.Comparable temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper) {
+			if ((k < upper) && (array[k-1].compareTo(array[k]) < 0)) {
+				k += 1;
+			}
+			if (array[j-1].compareTo(array[k-1]) < 0) {
+				temp = array[j-1];
+				array[j-1] = array[k-1];
+				array[k-1] = temp;
+			}
+			j = k;
+			k *= 2;
+		}
+	}
+
+	/**
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(Object[] array, Comparator c, int lower, int upper) {
+	
+		int j, k;
+		Object temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper) {
+			if ((k < upper) && (c.compare(array[k-1], array[k]) < 0)) {
+				k += 1;
+			}
+			if (c.compare(array[j-1], array[k-1]) < 0) {
+				temp = array[j-1];
+				array[j-1] = array[k-1];
+				array[k-1] = temp;
+			}
+			j = k;
+			k *= 2;
+		}
+	}
+
+	/**
+	 * helps sort an array of doubles.
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(double[] array, int lower, int upper) {
+	
+		int j, k;
+		double temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper) {
+			if ((k < upper) && (array[k-1] < array[k])) {
+				k += 1;
+			}
+			if (array[j-1] < array[k-1]) {
+				temp = array[j-1];
+				array[j-1] = array[k-1];
+				array[k-1] = temp;
+			}
+			j = k;
+			k *= 2;
+		}
+	} 
+	
+	/**
+	 * helps sort an array of indices into an array of doubles.
+	 * Assumes that array[lower+1] through to array[upper] is
+	 * already in heap form and then puts array[lower] to
+	 * array[upper] in heap form.
+	 */
+	private static void adjust(double[] array, int[] indices, int lower, int upper) {
+	
+		int j, k;
+		int temp;
+		
+		j = lower;
+		k = lower * 2;
+
+		while (k <= upper)
+		{
+			if ((k < upper) && (array[indices[k-1]] < array[indices[k]]))
+			{
+				k += 1;
+			}
+			if (array[indices[j-1]] < array[indices[k-1]])
+			{
+				temp = indices[j-1];
+				indices[j-1] = indices[k-1];
+				indices[k-1] = temp;
+			}
+			j = k;
+			k *= 2;
+		}
+	} 
+}
+
+
diff --git a/LibrarySource/pal/util/Log.java b/LibrarySource/pal/util/Log.java
new file mode 100644
index 0000000..198a106
--- /dev/null
+++ b/LibrarySource/pal/util/Log.java
@@ -0,0 +1,55 @@
+// Log.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.util;
+
+/**
+ * Log provides a mechanism for logging and debugging to the
+ * standard output stream.
+ *
+ * @author Alexei Drummond
+ * @version $Revision: 1.2 $
+ */
+public class Log implements Logger {
+
+    static Logger defaultLogger = new Log();
+
+    private boolean isDebugOn = false;
+    
+    public void setDebug(boolean on) {
+	
+        isDebugOn = on;
+    }
+
+    public boolean isDebugging() {
+	return isDebugOn;
+    }
+    
+    public void log(Object s) {
+	System.out.println(s);
+    }
+
+    public void debug(Object s) {
+
+        if (isDebugOn) {
+	    log(s);
+        }
+    }
+
+    public static Logger getDefaultLogger() {
+	return defaultLogger;
+    }
+
+    public static void setDefaultLogger(Logger logger) {
+	defaultLogger = logger;
+    }
+
+}
+
+
+
+
diff --git a/LibrarySource/pal/util/Logger.java b/LibrarySource/pal/util/Logger.java
new file mode 100644
index 0000000..dceaa7e
--- /dev/null
+++ b/LibrarySource/pal/util/Logger.java
@@ -0,0 +1,25 @@
+// Logger.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+package pal.util;
+
+/**
+ * Interface for all objects that provide a logging facility. 
+ *
+ * @author Alexei Drummond
+ * @version $Revision: 1.3 $
+ */
+
+
+public interface Logger {
+	void log(Object obj);
+
+	void debug(Object obj);
+
+   // boolean isDebugging();
+}
+
diff --git a/LibrarySource/pal/util/ThreeNumberSort.java b/LibrarySource/pal/util/ThreeNumberSort.java
new file mode 100644
index 0000000..a599081
--- /dev/null
+++ b/LibrarySource/pal/util/ThreeNumberSort.java
@@ -0,0 +1,237 @@
+// ThreeNumberSort.java
+//
+// (c) 1999-2001 PAL Development Core Team
+//
+// This package may be distributed under the
+// terms of the Lesser GNU General Public License (LGPL)
+
+ 
+package pal.util;
+
+import pal.math.*;
+
+/**
+ * sorts three numbers (doubles) and choose randomly among the
+ * minimum/maximum values
+ *
+ * @version $Id: ThreeNumberSort.java,v 1.4 2001/07/13 14:39:13 korbinian Exp $
+ *
+ * @author Korbinian Strimmer
+ */
+public class ThreeNumberSort
+{
+	//
+	// Public stuff
+	//
+
+	/** the three numbers */
+	public double[] numbers;
+
+	/** order of the numbers (0-2) */
+	public int first, second, third;
+
+	/** constructor */
+	public ThreeNumberSort()
+	{
+		numbers = new double[3];
+		rng = new MersenneTwisterFast();
+	}
+
+	/**
+	 * get input index of largest number
+	 *
+	 * @return index (if two or even all three numbers are
+	 *               of equally large value the index is drawn at
+	 *               random from that subset
+	 */
+	public int getIndexOfLargestNumber()
+	{
+		int numBest = 1;
+		double valBest = numbers[first];
+		
+		if (numbers[second] == valBest)
+		{
+			numBest++;
+			if (numbers[third] == valBest)
+			{
+				numBest++;
+			}
+		}
+		
+		if (numBest == 1)
+		{
+			return first;
+		}
+		else if (numBest == 2)
+		{
+			double rand = 2.0*rng.nextDouble();
+			
+			if (rand < 1.0)
+			{
+				return first;
+			}
+			else
+			{
+				return second;
+			}
+		}
+		else
+		{	
+			double rand = 3.0*rng.nextDouble();
+			
+			if (rand < 1.0)
+			{
+				return first;
+			}
+			else if (rand < 2.0)
+			{
+				return second;
+			}
+			else
+			{
+				return third;
+			}
+		}
+	}
+
+	/**
+	 * get input index of smallest number
+	 *
+	 * @return index (if two or even all three numbers are
+	 *               of equally small value the index is drawn at
+	 *               random from that subset
+	 */
+	public int getIndexOfSmallestNumber()
+	{
+		int numBest = 1;
+		double valBest = numbers[third];
+		
+		if (numbers[second] == valBest)
+		{
+			numBest++;
+			if (numbers[first] == valBest)
+			{
+				numBest++;
+			}
+		}
+		
+		if (numBest == 1)
+		{
+			return third;
+		}
+		else if (numBest == 2)
+		{
+			double rand = 2.0*rng.nextDouble();
+			
+			if (rand < 1.0)
+			{
+				return third;
+			}
+			else
+			{
+				return second;
+			}
+		}
+		else
+		{	
+			double rand = 3.0*rng.nextDouble();
+			
+			if (rand < 1.0)
+			{
+				return third;
+			}
+			else if (rand < 2.0)
+			{
+				return second;
+			}
+			else
+			{
+				return first;
+			}
+		}
+	}
+
+	/**
+	 * get smallest number
+	 *
+	 * @return number
+	 */
+	public double getSmallestNumber()
+	{
+		return numbers[getIndexOfSmallestNumber()];
+	}
+
+	/**
+	 * get largest number
+	 *
+	 * @return number
+	 */
+	public double getLargestNumber()
+	{
+		return numbers[getIndexOfLargestNumber()];
+	}
+
+	/**
+	 * sort three doubles
+	 *
+	 * @param n0 first double
+	 * @param n1 second double
+	 * @param n2 third double
+	 */
+	public void sort(double n0, double n1, double n2)
+	{	
+		numbers[0] = n0;
+		numbers[1] = n1;
+		numbers[2] = n2;
+	
+		if (n0 > n1)
+		{
+			if(n2 > n0)
+			{
+				first = 2;
+				second = 0;
+				third = 1;		
+			}
+			else if (n2 < n1)
+			{
+				first = 0;
+				second = 1;
+				third = 2;		
+			}
+			else
+			{
+				first = 0;
+				second = 2;
+				third = 1;		
+			}
+		}
+		else
+		{
+			if(n2 > n1)
+			{
+				first = 2;
+				second = 1;
+				third = 0;		
+			}
+			else if (n2 < n0)
+			{
+				first = 1;
+				second = 0;
+				third = 2;		
+			}
+			else
+			{
+				first = 1;
+				second = 2;
+				third = 0;		
+			}
+		}
+	}
+	
+	//
+	// Private stuff
+	//
+	
+	MersenneTwisterFast rng;
+}
+
diff --git a/LibrarySource/pal/util/makefile b/LibrarySource/pal/util/makefile
new file mode 100644
index 0000000..dca8f11
--- /dev/null
+++ b/LibrarySource/pal/util/makefile
@@ -0,0 +1,42 @@
+### VARIABLES ###
+
+JIKESOPTS := +P
+GCJOPTS := 
+
+# Always check dependencies
+JIKESOPTS += +M
+
+SRC := $(wildcard *.java)
+CLS := $(patsubst %.java, %.class, $(SRC))
+OBJ := $(patsubst %.class, %.o, $(wildcard *.class))
+
+
+### RULES ###
+
+# Compile Java sources into class files
+%.class: %.java
+	jikes $(JIKESOPTS) $<
+
+# Alternative to using jikes: gcj -C
+	
+# Compile class files into native code
+%.o: %.class
+	gcj -c $(GCJOPTS) $<
+
+	
+### TARGETS ###
+
+.PHONY: classes native clean
+
+classes: $(CLS)
+
+ifneq ($(OBJ),)
+native: $(OBJ)
+	(ar -rv package.a *.o; ranlib package.a)
+else
+native: $(OBJ)
+endif
+	
+clean:
+	rm -f *.class *.o *.u *.a *~
+
diff --git a/LibrarySource/pal/util/package.html b/LibrarySource/pal/util/package.html
new file mode 100644
index 0000000..d6827e5
--- /dev/null
+++ b/LibrarySource/pal/util/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Utility classes for sorting etc.
+</body>
+</html>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..380dd4f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+MesquiteCore
+============
+
+The core Mesquite repository.
diff --git a/Resources/Mesquite_Start_Script.bat b/Resources/Mesquite_Start_Script.bat
new file mode 100755
index 0000000..fe981d4
--- /dev/null
+++ b/Resources/Mesquite_Start_Script.bat
@@ -0,0 +1 @@
+java -Xmx500M -Xss2m -Djava.library.path=lib -Djri.ignore.ule="yes" -cp . mesquite.Mesquite
diff --git a/Resources/Mesquite_Start_Script.command b/Resources/Mesquite_Start_Script.command
new file mode 100755
index 0000000..8474114
--- /dev/null
+++ b/Resources/Mesquite_Start_Script.command
@@ -0,0 +1,4 @@
+dir=`dirname "$0"`
+java -d64 -Xmx4000M -Xss2m -Djava.library.path=lib -Djri.ignore.ule="yes" -cp "$dir" mesquite.Mesquite
+#increase the numbers above to enable more than 500M total and 2M per thread for the stack. The latter enables larger trees, e.g. more than 5000 taxa
+# add flag -d64 to enable 64 bit support and thus larger memory allocation, e.g. above 2gb
diff --git a/Resources/documentation.html b/Resources/documentation.html
new file mode 100755
index 0000000..2ad8f2c
--- /dev/null
+++ b/Resources/documentation.html
@@ -0,0 +1,17 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<title>Mesquite Read Me</title>
+	</head>
+
+	<body>
+		<h2>Mesquite: a modular system for evolutionary analysis</h2>
+		<p><font size="4"><b>The documentation for Mesquite can be found <a href="http://mesquiteproject.wikispaces.com">here</a></b></font><font size="4"><b>.</b></font></p>
+		
+		<hr>
+Copyright 1999 and onwards W. & D. Maddison 
+</body>
+
+</html>
+
diff --git a/Resources/examples/Ancestral_States/01-DataMatrix.nex b/Resources/examples/Ancestral_States/01-DataMatrix.nex
new file mode 100755
index 0000000..11a9756
--- /dev/null
+++ b/Resources/examples/Ancestral_States/01-DataMatrix.nex
@@ -0,0 +1,418 @@
+#NEXUS
+[written Sat Jun 07 09:55:30 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM1148988015a107;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-DataMatrix.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM1148988018a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-DataMatrix.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01568627) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+	AN T = 1  A = 0 DC = 2006.5.6.21.26.27 DM = 2006.5.6.21.26.27 ID = 010b0d18a84a50 I = 162 TF = (CM ) ;
+
+	AN T = 2  A = 0 DC = 2006.5.6.21.26.27 DM = 2006.5.6.21.26.27 ID = 010b0d18a84a51 I = 155 TF = (CM ) ;
+
+	AN T = 11  A = 0 DC = 2006.5.6.21.26.27 DM = 2006.5.6.21.26.27 ID = 010b0d18a84b52 I = 161 TF = (CM ) ;
+
+	AN T = 13  A = 0 DC = 2006.5.6.21.26.27 DM = 2006.5.6.21.26.27 ID = 010b0d18a84b53 I = 160 TF = (CM ) ;
+
+	AN T = 15  A = 0 DC = 2006.5.6.21.26.27 DM = 2006.5.6.21.26.27 ID = 010b0d18a84b54 I = 163 TF = (CM ) ;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                   Geneva '9' '100' '1'                   all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                   001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                   100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                   00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                   10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                   110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                   1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                   0;
+	Charts  Geneva '9' (                  normal )                   0010;
+	NexusOptions '0' '0' '50'                   001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                  normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                   1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                   1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                   1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                   0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                   1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                   Geneva '9' (                  normal )                   Geneva '10' (                  normal )                   Geneva '9' (                  normal )                   Geneva '9' (                  normal )                   Geneva '9' (                  bold )                   Geneva '9' (                  normal )                   Geneva '9' (                  normal ) '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                   00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                   100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                   1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148988015a107;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148988018a0;
+			checksum 0 2915397944 WM1148988018a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 268;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 960 497;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #206796807167704052 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 32;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 620 428;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-TreeWindow.nex';
+			setPrevFileName '../Introduction.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 262 480;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Morphological data for species of Bembidion ground beetles.^n^nTo reconstruct ancestral states for these characters, you first need to go to tree window so as to be viewing a tree.  To obtain a tree window, select Tree window under Taxa&Trees.  You will be asked what trees to show; you can choose to show Stored Trees, if any are available in your data file, or if not, to show default trees which you can edit into the desired tree.  (You can read in trees from other fi [...]
+				toggleFileNames off;
+				setPrevButtonName Return_to_main_Intro;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/02-TreeWindow.nex b/Resources/examples/Ancestral_States/02-TreeWindow.nex
new file mode 100755
index 0000000..5a8b6eb
--- /dev/null
+++ b/Resources/examples/Ancestral_States/02-TreeWindow.nex
@@ -0,0 +1,440 @@
+#NEXUS
+[written Sat Jun 07 09:55:55 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM114898948ea108;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-TreeWindow.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114898949130;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-TreeWindow.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01176471) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                 unord PolyTcount =                 MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                  Geneva '9' '100' '1'                  all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                  001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                  100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                  00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                  10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                  110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                  1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                  0;
+	Charts  Geneva '9' (                 normal )                  0010;
+	NexusOptions '0' '0' '50'                  001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                 normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                  1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                  1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                  1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                  0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                  1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                  Geneva '9' (                 normal )                  Geneva '10' (                 normal )                  Geneva '9' (                 normal )                  Geneva '9' (                 normal )                  Geneva '9' (                 bold )                  Geneva '9' (                 normal )                  Geneva '9' (                 normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                  00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                  100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                  1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114898948ea108;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114898949130;
+			checksum 0 2915397944 WM114898949130;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 220;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1064 565;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 772 508;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 954 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-TraceCharPars.nex';
+			setPrevFileName '01-DataMatrix.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 214 548;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This is the Tree Window^n^nTo show graphically a reconstruction of ancestral states, select Trace Character History under the Analysis:Tree menu of the tree window.  You may be asked what method to use (parsimony or likelihood) and what source of characters.';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/03-TraceCharPars.nex b/Resources/examples/Ancestral_States/03-TraceCharPars.nex
new file mode 100755
index 0000000..7a8404f
--- /dev/null
+++ b/Resources/examples/Ancestral_States/03-TraceCharPars.nex
@@ -0,0 +1,475 @@
+#NEXUS
+[written Sat Jun 07 09:56:22 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM1148989a469109;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-TraceCharPars.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM1148989a4970;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-TraceCharPars.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                   unord PolyTcount =                   MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                    Geneva '9' '100' '1'                    all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                    001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                    100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                    00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                    10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                    110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                    1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                    0;
+	Charts  Geneva '9' (                   normal )                    0010;
+	NexusOptions '0' '0' '50'                    001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                   normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                    1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                    1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                    1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                    0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                    1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                    Geneva '9' (                   normal )                    Geneva '10' (                   normal )                    Geneva '9' (                   normal )                    Geneva '9' (                   normal )                    Geneva '9' (                   bold )                    Geneva '9' (                   normal )                    Geneva '9' (                   normal ) '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                    00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                    100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                    1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148989a469109;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148989a4970;
+			checksum 0 2915397944 WM1148989a4970;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 246;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1042 583;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 724 526;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 954 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -950;
+					setInitialOffsetY -437;
+					setLegendWidth 142;
+					setLegendHeight 160;
+					resume ;
+					modifyColors  1 0  255 250 128 1 1  67 20 255;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03b-LiveUpdate.nex';
+			setPrevFileName '02-TreeWindow.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 240 566;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here a character is traced - ancestral states are reconstructed by parsimony^n^nWith the character shown, the most parsimonious ancestral states are obvious by inspection.^n^nYou can scroll through characters using the blue arrows in the Trace Character legend.  You can scroll through trees using the blue arrows at the top left corner of the tree window.  You can edit the tree using the tools of the tool palette.^n^nThe colors of states has been altered to the user''s [...]
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/03b-LiveUpdate.nex b/Resources/examples/Ancestral_States/03b-LiveUpdate.nex
new file mode 100755
index 0000000..4cd6573
--- /dev/null
+++ b/Resources/examples/Ancestral_States/03b-LiveUpdate.nex
@@ -0,0 +1,545 @@
+#NEXUS
+[written Sat Jun 07 09:57:18 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM114898f610e115;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03b-LiveUpdate.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114898f61280;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03b-LiveUpdate.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01568627) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                    unord PolyTcount =                    MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                     Geneva '9' '100' '1'                     all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                     001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                     100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                     00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                     10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                     110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                     1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                     0;
+	Charts  Geneva '9' (                    normal )                     0010;
+	NexusOptions '0' '0' '50'                     001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                    normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                     1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                     1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                     1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                     0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                     1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                     Geneva '9' (                    normal )                     Geneva '10' (                    normal )                     Geneva '9' (                    normal )                     Geneva '9' (                    normal )                     Geneva '9' (                    bold )                     Geneva '9' (                    normal )                     Geneva '9' (                    normal ) '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                     00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                     100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                     1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114898f610e115;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114898f61280;
+			checksum 0 2915397944 WM114898f61280;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 180;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 634 571;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 646 548;
+					setLocation 661 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 754 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -365;
+					setInitialOffsetY -374;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #206796807167704052 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 382 514;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-Equivocal.nex';
+			setPrevFileName '03-TraceCharPars.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 174 554;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The reconstruction of ancestral states is updated live as conditions change.^n^nFor instance, change the character states in the matrix, and the trace will be updated.^n^nEdit the tree, and the trace will be updated.';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/04-Equivocal.nex b/Resources/examples/Ancestral_States/04-Equivocal.nex
new file mode 100755
index 0000000..4f6efb6
--- /dev/null
+++ b/Resources/examples/Ancestral_States/04-Equivocal.nex
@@ -0,0 +1,474 @@
+#NEXUS
+[written Sat Jun 07 09:57:41 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM114898ffa14116;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-Equivocal.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114898ffa440;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-Equivocal.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                   unord PolyTcount =                   MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                    Geneva '9' '100' '1'                    all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                    001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                    100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                    00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                    10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                    110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                    1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                    0;
+	Charts  Geneva '9' (                   normal )                    0010;
+	NexusOptions '0' '0' '50'                    001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                   normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                    1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                    1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                    1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                    0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                    1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                    Geneva '9' (                   normal )                    Geneva '10' (                   normal )                    Geneva '9' (                   normal )                    Geneva '9' (                   normal )                    Geneva '9' (                   bold )                    Geneva '9' (                   normal )                    Geneva '9' (                   normal ) '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                    00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                    100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                    1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114898ffa14116;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114898ffa440;
+			checksum 0 2915397944 WM114898ffa440;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 261;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1068 569;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 735 512;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 754 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -750;
+					setInitialOffsetY -452;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-TreeForm.nex';
+			setPrevFileName '03b-LiveUpdate.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 255 552;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this character trace, some branches are multicolored, indicating that more than one state can be placed at the branch equally parsimoniously ("equivocal").^n^nTo see the states reconstructed at a node, make sure the treewindow is frontmost, and move the cursor over the branch.  A list of state will appear at the bottom of the Trace Character legend.^n^nIf the tree is drawn in different styles, these equivocal assignments can be seen more easily, as shown in the nex [...]
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/05-TreeForm.nex b/Resources/examples/Ancestral_States/05-TreeForm.nex
new file mode 100755
index 0000000..163fa45
--- /dev/null
+++ b/Resources/examples/Ancestral_States/05-TreeForm.nex
@@ -0,0 +1,477 @@
+#NEXUS
+[written Sat Jun 07 09:58:11 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM11489904131117;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-TreeForm.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM1148990414c0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-TreeForm.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                   Geneva '9' '100' '1'                   all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                   001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                   100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                   00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                   10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                   110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                   1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                   0;
+	Charts  Geneva '9' (                  normal )                   0010;
+	NexusOptions '0' '0' '50'                   001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                  normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                   1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                   1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                   1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                   0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                   1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                   Geneva '9' (                  normal )                   Geneva '10' (                  normal )                   Geneva '9' (                  normal )                   Geneva '9' (                  normal )                   Geneva '9' (                  bold )                   Geneva '9' (                  normal )                   Geneva '9' (                  normal ) '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                   00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                   100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                   1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM11489904131117;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148990414c0;
+			checksum 0 2915397944 WM1148990414c0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 133;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1001 597;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 796 540;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 1154 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -1150;
+					setInitialOffsetY -488;
+					setLegendWidth 142;
+					setLegendHeight 192;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-ParsimonyModels.nex';
+			setPrevFileName '04-Equivocal.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 127 580;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here the Balls & sticks drawing style is used to show the equivocal assignments more clearly.  (Use of Balls & Sticks is particularly important for likelihood reconstructions.)';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/06-ParsimonyModels.nex b/Resources/examples/Ancestral_States/06-ParsimonyModels.nex
new file mode 100755
index 0000000..a84d34a
--- /dev/null
+++ b/Resources/examples/Ancestral_States/06-ParsimonyModels.nex
@@ -0,0 +1,512 @@
+#NEXUS
+[written Sat Jun 07 09:58:23 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM11489909891118;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-ParsimonyModels.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114899098b50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-ParsimonyModels.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                      Geneva '9' '100' '1'                      all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                      001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                      100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                      00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                      10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                      110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                      1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                      0;
+	Charts  Geneva '9' (                     normal )                      0010;
+	NexusOptions '0' '0' '50'                      001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                     normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                      1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                      1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                      1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                      0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                      1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                      Geneva '9' (                     normal )                      Geneva '10' (                     normal )                      Geneva '9' (                     normal )                      Geneva '9' (                     normal )                      Geneva '9' (                     bold )                      Geneva '9' (                     normal )                      Geneva '9' (                     [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                      00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                      100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                      1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM11489909891118;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114899098b50;
+			checksum 0 2915397944 WM114899098b50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 746 508;
+					setLocation 547 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 954 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -471;
+					setInitialOffsetY -393;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showCharacters #206796807167704052 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					newAssistant  #mesquite.stochchar.CharListProbModels.CharListProbModels;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 696 415;
+					setLocation 11 470;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-EditingParsModels.nex';
+			setPrevFileName '05-TreeForm.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 447;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The reconstruction of ancestral states in the tree window above uses parsimony as an inference method, and uses a model of evolution as an assumption.^n^nIn the example here, the model of evolution is "ordered", i.e., the number of steps counted for a change from state x to state y is |x-y|.  Thus, a change from state 0 to state 2 is two steps.^n^nYou can change the model of evolution for a character by selecting the character in the List of Characters window, touchin [...]
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/07-EditingParsModels.nex b/Resources/examples/Ancestral_States/07-EditingParsModels.nex
new file mode 100755
index 0000000..ea8aa59
--- /dev/null
+++ b/Resources/examples/Ancestral_States/07-EditingParsModels.nex
@@ -0,0 +1,547 @@
+#NEXUS
+[written Sat Jun 07 09:58:35 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM11489922ea2119;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-EditingParsModels.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM11489922ec30;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-EditingParsModels.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                      unord PolyTcount =                      MINSTEPS;
+		USERTYPE my_assumption (Stepmatrix) = 
+		 4
+	0	1	2	3
+	0	3	3	4
+	1	0	2	4
+	1	1	0	3
+	1	1	1	0
+;
+
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  2 4 -  33 35 -  63 65 -  85, my_assumption:  3;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                       Geneva '9' '100' '1'                       all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                       001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                       100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                       00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                       10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                       110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                       1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                       0;
+	Charts  Geneva '9' (                      normal )                       0010;
+	NexusOptions '0' '0' '50'                       001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                      normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                       1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                       1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                       1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                       0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                       1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                       Geneva '9' (                      normal )                       Geneva '10' (                      normal )                       Geneva '9' (                      normal )                       Geneva '9' (                      normal )                       Geneva '9' (                      bold )                       Geneva '9' (                      normal )                       Geneva '9' (        [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                       00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                       100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                       1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM11489922ea2119;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM11489922ec30;
+			checksum 0 2915397944 WM11489922ec30;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 572 377;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 672 498;
+					setLocation 630 333;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 954 636;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -537;
+					setInitialOffsetY -401;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showCharacters #206796807167704052 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					newAssistant  #mesquite.stochchar.CharListProbModels.CharListProbModels;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 599 301;
+					setLocation 5 467;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.parsimony.StepMatrixCurator.StepMatrixCurator;
+			tell It;
+				editModel my_assumption #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 20;
+						setAnnotationSize 20;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 425 186;
+						setLocation 615 32;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-ParsimonyMacClade.nex';
+			setPrevFileName '06-ParsimonyModels.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 500 360;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Stepmatrices are flexible parsimony models that allow you to specify how much change is counted between any pair of states.  Stepmatrices can be used in calculations with polytomous trees as long as the polytomies are treated as "hard".^n^nTo make a stepmatrix model, select the menu item: Characters>New Character Model>Stepmatrix.  Give the new model a name, and indicate the maximum state by selecting the menu item Step_matrix>Set maximum state... .  Edit the matrix t [...]
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/08-ParsimonyMacClade.nex b/Resources/examples/Ancestral_States/08-ParsimonyMacClade.nex
new file mode 100755
index 0000000..a799e40
--- /dev/null
+++ b/Resources/examples/Ancestral_States/08-ParsimonyMacClade.nex
@@ -0,0 +1,495 @@
+#NEXUS
+[written Wed Aug 26 11:48:27 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM1148992da80120;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-ParsimonyMacClade.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM1148992daa80;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-ParsimonyMacClade.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE fromIsland_1 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))))));
+	TREE fromIsland_8 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(24,((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),(32,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16)))))))))))))))))))))));
+	TREE fromIsland_12a = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),((24,(28,29)),((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))));
+	TREE fromIsland_12b = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((30,((22,23),(27,(25,26)))),(28,(24,(29,((19,(20,21)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_160 = (53,(52,(((46,(47,(44,45))),((48,49),(50,51))),(((39,(38,40)),(41,(42,43))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(5,(3,4))))))),(((31,33),(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))));
+	TREE fromIsland32 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,((20,21),(5,(3,4))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16))))))))))))))))))));
+	TREE fromIsland36 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),(4,(3,5))))))),(34,((31,33),(32,((35,(36,37)),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))))))))))))));
+	TREE fromIsland_40 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(30,(((28,29),(27,(25,26))),((23,(22,(19,((20,21),(5,(3,4)))))),(24,(31,((33,(34,(32,(35,(36,37))))),((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16))))))))))))))))))));
+	TREE fromIsland_44 = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,(30,(27,(25,26)))),((24,(28,29)),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16)))))))))))))))))));
+	TREE fromIsland_48 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(21,(20,(6,(4,(3,5))))))))),((30,(28,(27,(25,26)))),(29,(34,(32,((31,(33,(35,(36,37)))),((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15))))))))))))))))))))));
+	TREE fromIsland_68 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,(((24,(28,29)),(30,(27,(25,26)))),(34,((31,33),(32,((35,(36,37)),((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE fromIsland_84 = (53,(52,(44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),(22,((19,(20,21)),(23,((30,((28,29),(27,(25,26)))),(24,(31,((1,2),((34,(33,(35,(36,37)))),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS DEFTYPE =                      unord PolyTcount =                      MINSTEPS;
+		USERTYPE my_assumption (Stepmatrix) = 
+		 4
+	0	1	2	3
+	0	3	3	4
+	1	0	2	4
+	1	1	0	3
+	1	1	1	0
+;
+
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  2 4 -  33 35 -  63 65 -  85, my_assumption:  3;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0 81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                       Geneva '9' '100' '1'                       all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                       001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                       100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                       00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                       10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                       110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                       1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                       0;
+	Charts Geneva '9' (                      normal )                       0010;
+	NexusOptions '0' '0' '50'                       001011011;
+	TipLabel '1';
+	TreeFont Geneva '9' (                      normal );
+	TreeShape 1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                       1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                       1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                       1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                       0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                       1;
+	PrintTree 10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                       Geneva '9' (                      normal )                       Geneva '10' (                      normal )                       Geneva '9' (                      normal )                       Geneva '9' (                      normal )                       Geneva '9' (                      bold )                       Geneva '9' (                      normal )                       Geneva '9' (         [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                       00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                       100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                       1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148992da80120;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148992daa80;
+			checksumv 0 2 667277701 WM1148992daa80;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 488 509;
+			setLocation 1 26;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 629 489;
+					setLocation 512 27;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 2 954 636  0 0;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 4;
+					setInitialOffsetY -405;
+					setLegendWidth 142;
+					setLegendHeight 193;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-Continuous.nex';
+			setPrevFileName '07-EditingParsModels.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 416 492;
+					setLocation 1 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'MacClade and Mesquite differ in features offered for parsimony reconstructions of ancestral states.  Here are some differences.^n^nMacClade has (but not Mesquite): ^na paintbrush to fix character states at nodes, a sophisticated Trace All Changes mode, a changes and stasis chart, and several models of character evolution (character state trees, Dollo, irreversible) not supported by Mesquite.^n^nMesquite has (but not MacClade): ^nlikelihood ancestral state reconstructi [...]
+				setTitle MacClade_Comparison;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/09-Continuous.nex b/Resources/examples/Ancestral_States/09-Continuous.nex
new file mode 100755
index 0000000..d5a1724
--- /dev/null
+++ b/Resources/examples/Ancestral_States/09-Continuous.nex
@@ -0,0 +1,465 @@
+#NEXUS
+[written Sat Jun 07 09:58:56 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM11489939e51121;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM11489939e620;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM11489939e8a0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM11489939ea10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-Continuous.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM11489939e51121;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM11489939e620;
+			checksum 0 737652128 WM11489939e620;
+			setID 1 2904659670370408267 WM11489939e8a0;
+			checksum 1 573928344 WM11489939e8a0;
+			setID 2 7285741872021222516 WM11489939ea10;
+			checksum 2 1458690238 WM11489939ea10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 533 266;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8853494381083195946  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 576 626;
+					setLocation 571 41;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(21<selected = on >,((19<selected = on >,12<selected = on >)<selected = on >,(((8<selected = on >,2<selected = on >)<selected = on >,5<selected = on >)<selected = on >,((22<selected = on >,15<selected = on >)<selected = on >,((10<selected = on >,6<selected = on >)<selected = on >,((((7<selected = on >,11<selected = on >)<selected = on >,((9<selected = on >,28<selected = on >)<selected = on >,16<selected = on >)<selected = on >)<selected = on >,((27<selected = on >,20<select [...]
+					setTreeAnnotation 'Taxon: bahorucoensis';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5443567030079148118;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 20;
+					setInitialOffsetY -307;
+					setLegendWidth 142;
+					setLegendHeight 302;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5443567030079148118 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 544 340;
+					setLocation 10 352;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-PlotTree.nex';
+			setPrevFileName '08-ParsimonyMacClade.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 461 249;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here a continous valued trait is traced.  There are two options for parsimony reconstructions: linear parsimony and squared-changed (least squares) parsimony.  ';
+				setTitle Continuous_data;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/10-PlotTree.nex b/Resources/examples/Ancestral_States/10-PlotTree.nex
new file mode 100755
index 0000000..ffc6e4b
--- /dev/null
+++ b/Resources/examples/Ancestral_States/10-PlotTree.nex
@@ -0,0 +1,449 @@
+#NEXUS
+[written Sat Jun 07 09:59:07 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM11489940754122;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM1148994077a0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114899407ba0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114899407cf0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "10-PlotTree.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM11489940754122;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM1148994077a0;
+			checksum 0 737652128 WM1148994077a0;
+			setID 1 2904659670370408267 WM114899407ba0;
+			checksum 1 573928344 WM114899407ba0;
+			setID 2 7285741872021222516 WM114899407cf0;
+			checksum 2 1458690238 WM114899407cf0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 521 299;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8853494381083195946  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 696 586;
+					setLocation 554 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+					tell It;
+						setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+						tell It;
+							hide;
+							setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+							tell It;
+								getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+								tell It;
+									setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+									tell It;
+										setDataSet #5443567030079148118;
+									endTell;
+								endTell;
+								setCharacter 4;
+								setItem 0;
+								getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+								tell It;
+									setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+									toggleMPRsMode off;
+									getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+									tell It;
+										toggleWeight on;
+									endTell;
+								endTell;
+							endTell;
+							toggleShowLegend on;
+							setInitialOffsetX -538;
+							setInitialOffsetY -220;
+							setCurrentX 6;
+							setCurrentY 4;
+							show;
+						endTell;
+						setSpotDiameter 10;
+						toggleShowTerminals on;
+						toggleShowInternals on;
+						toggleShowTree on;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(21,((19,12),(((8,2),5),((22,15),((10,6),((((7,11),((9,28),16)),((27,20),((3,30),(18,(25,(24,4)))))),((1<selected = on >,(26<selected = on >,23<selected = on >)<selected = on >)<selected = on >,(29<selected = on >,(17<selected = on >,(13<selected = on >,14<selected = on >)<selected = on >)<selected = on >)<selected = on >)<selected = on >))))));';
+					setTreeAnnotation 'Taxon: bahorucoensis';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5443567030079148118 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 449 242;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-TraceCharMLE.nex';
+			setPrevFileName '09-Continuous.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 449 282;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Continuous character tracing can take various forms, including visualization in two dimensional space.  The axes could be the raw characters, or, using the Rhetenor package, they could be axes from ordinations such as Principal components.  Rhetenor also supplies a 3D plot tree in which the tree floats in a 3D space, and is rotatable.^n^nSome branches are black and others gray because only one clade of the tree is selected (shown in black).';
+				setTitle Plot_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/11-TraceCharMLE.nex b/Resources/examples/Ancestral_States/11-TraceCharMLE.nex
new file mode 100755
index 0000000..e6e9183
--- /dev/null
+++ b/Resources/examples/Ancestral_States/11-TraceCharMLE.nex
@@ -0,0 +1,297 @@
+#NEXUS
+[written Sat Jun 07 09:59:40 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		X._multilineatus X._nigrensis X._cortezi X._malinche X._continens X._nezahualcoyti X._montezumae X._pygmaeus X._birchmanii X._couchianus X._gordoni X._meyeri X._xiphidium X._variatus X._evelynae X._clemenciae X._milleri X._maculatus X._andersi X._alvarezi X._helleri X._signum P._olmaceae P._interm P._compressa 
+	;
+	BLOCKID WM11489945b02123;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "11-TraceCharMLE.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 Tail /  swordless swords ; 
+	MATRIX
+	X._multilineatus  1
+	X._nigrensis      1
+	X._cortezi        1
+	X._malinche       1
+	X._continens      0
+	X._nezahualcoyti  1
+	X._montezumae     1
+	X._pygmaeus       0
+	X._birchmanii     1
+	X._couchianus     0
+	X._gordoni        0
+	X._meyeri         0
+	X._xiphidium      0
+	X._variatus       0
+	X._evelynae       0
+	X._clemenciae     1
+	X._milleri        0
+	X._maculatus      0
+	X._andersi        0
+	X._alvarezi       1
+	X._helleri        1
+	X._signum         1
+	P._olmaceae       0
+	P._interm         0
+	P._compressa      0
+
+;
+		BLOCKID WM11489945b3c0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "11-TraceCharMLE.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 X._multilineatus,
+		2 X._nigrensis,
+		3 X._cortezi,
+		4 X._malinche,
+		5 X._continens,
+		6 X._nezahualcoyti,
+		7 X._montezumae,
+		8 X._pygmaeus,
+		9 X._birchmanii,
+		10 X._couchianus,
+		11 X._gordoni,
+		12 X._meyeri,
+		13 X._xiphidium,
+		14 X._variatus,
+		15 X._evelynae,
+		16 X._clemenciae,
+		17 X._milleri,
+		18 X._maculatus,
+		19 X._andersi,
+		20 X._alvarezi,
+		21 X._helleri,
+		22 X._signum,
+		23 P._olmaceae,
+		24 P._interm,
+		25 P._compressa;
+	TREE Figure_5 = ((((((((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0,5:1.0):1.0,6:1.0):1.0,7:1.0):1.0,(8:1.0,9:1.0):1.0):1.0,((((((((((10:1.0,11:1.0):1.0,12:1.0):1.0,13:1.0):1.0,14:1.0):1.0,15:1.0):1.0,16:1.0):1.0,17:1.0):1.0,18:1.0):1.0,19:1.0):1.0,((20:1.0,21:1.0):1.0,22:1.0):1.0):1.0):1.0,((25:1.0,24:1.0):1.0,23:1.0):1.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8265138006560775301 WM11489945b02123;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6115459465024062079 WM11489945b3c0;
+			checksum 0 3737896798 WM11489945b3c0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 501 534;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8265138006560775301  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 298.1019014879746.4115002201943536709;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 733 542;
+					setLocation 553 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 18;
+						setEdgeWidth 2;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #6115459465024062079;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -239;
+					setInitialOffsetY -190;
+					setLegendWidth 218;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11b-TextView.nex';
+			setPrevFileName '10-PlotTree.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 401 517;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite has the option to reconstruct ancestral states using likelihood.  Two models of evolution are available: a symmetrical one-parameter model (Lewis''s Markov k model, called here the Mk1 model) and an asymmetrical two parameter model, in which increases in state (e.g., 0 to 1) have a different rate from decreased (1 to 0).^n^nHere shown is an example from Figure 5 of Schluter et al., 1997 (Evolution 51:1699), of swordtail fish.^n^nThe reconstruction method focu [...]
+				setTitle Likelihood;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/11b-TextView.nex b/Resources/examples/Ancestral_States/11b-TextView.nex
new file mode 100755
index 0000000..b54cbec
--- /dev/null
+++ b/Resources/examples/Ancestral_States/11b-TextView.nex
@@ -0,0 +1,298 @@
+#NEXUS
+[written Sat Jun 07 09:59:50 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		X._multilineatus X._nigrensis X._cortezi X._malinche X._continens X._nezahualcoyti X._montezumae X._pygmaeus X._birchmanii X._couchianus X._gordoni X._meyeri X._xiphidium X._variatus X._evelynae X._clemenciae X._milleri X._maculatus X._andersi X._alvarezi X._helleri X._signum P._olmaceae P._interm P._compressa 
+	;
+	BLOCKID WM11489949bb7124;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "11b-TextView.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 Tail /  swordless swords ; 
+	MATRIX
+	X._multilineatus  1
+	X._nigrensis      1
+	X._cortezi        1
+	X._malinche       1
+	X._continens      0
+	X._nezahualcoyti  1
+	X._montezumae     1
+	X._pygmaeus       0
+	X._birchmanii     1
+	X._couchianus     0
+	X._gordoni        0
+	X._meyeri         0
+	X._xiphidium      0
+	X._variatus       0
+	X._evelynae       0
+	X._clemenciae     1
+	X._milleri        0
+	X._maculatus      0
+	X._andersi        0
+	X._alvarezi       1
+	X._helleri        1
+	X._signum         1
+	P._olmaceae       0
+	P._interm         0
+	P._compressa      0
+
+;
+		BLOCKID WM11489949bd50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "11b-TextView.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 X._multilineatus,
+		2 X._nigrensis,
+		3 X._cortezi,
+		4 X._malinche,
+		5 X._continens,
+		6 X._nezahualcoyti,
+		7 X._montezumae,
+		8 X._pygmaeus,
+		9 X._birchmanii,
+		10 X._couchianus,
+		11 X._gordoni,
+		12 X._meyeri,
+		13 X._xiphidium,
+		14 X._variatus,
+		15 X._evelynae,
+		16 X._clemenciae,
+		17 X._milleri,
+		18 X._maculatus,
+		19 X._andersi,
+		20 X._alvarezi,
+		21 X._helleri,
+		22 X._signum,
+		23 P._olmaceae,
+		24 P._interm,
+		25 P._compressa;
+	TREE Figure_5 = ((((((((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0,5:1.0):1.0,6:1.0):1.0,7:1.0):1.0,(8:1.0,9:1.0):1.0):1.0,((((((((((10:1.0,11:1.0):1.0,12:1.0):1.0,13:1.0):1.0,14:1.0):1.0,15:1.0):1.0,16:1.0):1.0,17:1.0):1.0,18:1.0):1.0,19:1.0):1.0,((20:1.0,21:1.0):1.0,22:1.0):1.0):1.0):1.0,((25:1.0,24:1.0):1.0,23:1.0):1.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8265138006560775301 WM11489949bb7124;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6115459465024062079 WM11489949bd50;
+			checksum 0 3737896798 WM11489949bd50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 410 414;
+			setLocation 11 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8265138006560775301  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 298.1019014879746.4115002201943536709;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 733 542;
+					setLocation 429 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					showPage 1;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 18;
+						setEdgeWidth 2;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #6115459465024062079;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -159;
+					setLegendWidth 142;
+					setLegendHeight 126;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '12-Mk1Likelihood.nex';
+			setPrevFileName '11-TraceCharMLE.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 338 397;
+					setLocation 11 25;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'You can also see details of the likelihood recontruction presented in text format by touching on the "Text" tab at the top of the tree window.  Scroll down to see a text version of the reconstruction.^n';
+				setTitle Likelihood;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/12-Mk1Likelihood.nex b/Resources/examples/Ancestral_States/12-Mk1Likelihood.nex
new file mode 100755
index 0000000..06da762
--- /dev/null
+++ b/Resources/examples/Ancestral_States/12-Mk1Likelihood.nex
@@ -0,0 +1,439 @@
+#NEXUS
+[written Sat Jun 07 09:59:57 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=19;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle striatum 
+	;
+	BLOCKID WM1148994dec7125;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "12-Mk1Likelihood.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  'absent-v._slight_mirrors' slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser [...]
+	MATRIX
+	balli             1010-00(1 2)1000011000000010(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1010-00(1 2)10(0 1)1011000000010(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       12(2 3)(0 1)-002000201000000(0 1)010(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         12(2 3)0-(0 1)02001001010000(0 1)0100001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1120-002000301000000101000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        123(0 2)000(1 2)000011100000001010030001020310120001-00-0000003021???????????????????????????
+	carinula          12(0 1 2)0-00210(0 1)101100000001030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             12(0 1 2)1-0021000011000000010(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        12(0 1 2 3)(0 2)000210(0 1)00110000000101013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  12(0 1 2)1-0001002010000110200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(1 2)3(0 2)0(0 1)(0 1 2)1000001100000(0 1)010(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1231-(0 1)0(0 1)0000011000001010(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          123(2 3)0(0 1)02101001100001(0 1)010(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1233010210(0 1)0011000010200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1233010210(0 1)0011000010200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1233(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0011000010200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1233(0 1)(0 1)02(0 1)0(0 1)000100000101000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1233(0 1)(0 1)02000000?00001(0 1)110(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	striatum          0010--0211-0011000000010(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+
+;
+		BLOCKID WM1148994deef0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "12-Mk1Likelihood.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 striatum;
+	TREE Untitled_Tree = (19,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18)))))));
+	TREE Untitled_Tree = (19,6,7,8,9,10,(1,2),(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+	TREE Untitled_Tree = (19,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16)))))))));
+	TREE Untitled_Tree = ((4,(3,5)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15)))))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))));
+	TREE Untitled_Tree = ((3,4,5),(19,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                unord PolyTcount =                MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel My_Mk1_Model (Mk1) = 
+		 rate 0.1 maxState 2;
+
+	ProbModelSet * UNTITLED   =  My_Mk1_Model:  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1187776091;
+	FileSettings editor '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                 Geneva '9' '100' '1'                 all;
+	EditorPosition '46' '9' '451' '1011';
+	TreeWindowPosition '46' '6' '636' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '434'                 001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '278'                 100;
+	ListWindow Trees closed Geneva '9' '50' '10' '273' '386';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Data List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                 00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                 10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                 110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                 1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                 0;
+	Charts  Geneva '9' (                normal )                 0010;
+	NexusOptions '0' '0' '50'                 001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                 1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                 1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                 1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                 0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                 1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                 Geneva '9' (                normal )                 Geneva '10' (                normal )                 Geneva '9' (                normal )                 Geneva '9' (                normal )                 Geneva '9' (                bold )                 Geneva '9' (                normal )                 Geneva '9' (                normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                 00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                 100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                 1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148994dec7125;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148994deef0;
+			checksum 0 4161077265 WM1148994deef0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 492 337;
+			setLocation 15 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 550 660;
+					setLocation 527 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 4;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 20;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 4;
+					setInitialOffsetY -196;
+					setLegendWidth 196;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.MkModelCurator.MkModelCurator;
+			tell It;
+				editModel My_Mk1_Model #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						setSweetMin 0.0;
+						setSweetMax 1.0;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 307 134;
+						setLocation 202 442;
+						setFont SanSerif;
+						setFontSize 10;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '13-AsymmLikelihood.nex';
+			setPrevFileName '11b-TextView.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 320;
+					setLocation 15 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The Mk1 model is a simple stochastic model of character evolution, in which there is a single rate of change between any two states.  If the built-in Mk1 model is used, this rate of change is estimated based on the character distribution and the tree. Alternatively, if create a new Mk1 model (using the New Character Model submenu of the Characters menu) you can specify the rate of change.  In the small window below is an editor for an Mk1 model.  If you move the slide [...]
+				setTitle Rate_of_change;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/13-AsymmLikelihood.nex b/Resources/examples/Ancestral_States/13-AsymmLikelihood.nex
new file mode 100755
index 0000000..88af0a9
--- /dev/null
+++ b/Resources/examples/Ancestral_States/13-AsymmLikelihood.nex
@@ -0,0 +1,453 @@
+#NEXUS
+[written Wed Aug 26 11:49:29 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=19;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle striatum 
+	;
+	BLOCKID WM114899559a6126;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "13-AsymmLikelihood.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  'absent-v._slight_mirrors' slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser [...]
+	MATRIX
+	balli             1010-00(1 2)1000011000000010(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1010-00(1 2)10(0 1)1011000000010(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       12(2 3)(0 1)-002000201000000(0 1)010(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         12(2 3)0-(0 1)02001001010000(0 1)0100001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1120-002000301000000101000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        123(0 2)000(1 2)000011100000001010030001020310120001-00-0000003021???????????????????????????
+	carinula          12(0 1 2)0-00210(0 1)101100000001030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             12(0 1 2)1-0021000011000000010(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        12(0 1 2 3)(0 2)000210(0 1)00110000000101013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  12(0 1 2)1-0001002010000110200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(1 2)3(0 2)0(0 1)(0 1 2)1000001100000(0 1)010(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1231-(0 1)0(0 1)0000011000001010(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          123(2 3)0(0 1)02101001100001(0 1)010(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1233010210(0 1)0011000010200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1233010210(0 1)0011000010200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1233(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0011000010200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1233(0 1)(0 1)02(0 1)0(0 1)000100000101000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1233(0 1)(0 1)02000000?00001(0 1)110(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	striatum          0010--0211-0011000000010(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+
+;
+		BLOCKID WM114899559ca0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "13-AsymmLikelihood.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 striatum;
+	TREE Untitled_Tree = (19,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18)))))));
+	TREE Untitled_Tree = (19,6,7,8,9,10,(1,2),(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+	TREE Untitled_Tree = (19,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16)))))))));
+	TREE Untitled_Tree = ((4,(3,5)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15)))))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))));
+	TREE Untitled_Tree = ((3,4,5),(19,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS DEFTYPE =              unord PolyTcount =              MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel My_Mk1_Model (Mk1) = 
+		 rate 0.2;
+	CharModel My_Asymmetrical_Model (AsymmMk) = 
+		 rate 0.2 bias 0.1 equilibAsPrior;
+
+	ProbModelSet * UNTITLED   =  My_Asymmetrical_Model:  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0 81;
+	LastModified -1187776091;
+	FileSettings editor '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'               Geneva '9' '100' '1'               all;
+	EditorPosition '46' '9' '451' '1011';
+	TreeWindowPosition '46' '6' '636' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '434'               001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '278'               100;
+	ListWindow Trees closed Geneva '9' '50' '10' '273' '386';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder Data List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /               00 ? -;
+	Correlation '0' '0' '1000' '0' '0'               10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'               110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'               1;
+	Calculations 0000001;
+	SummaryMode '0' '0'               0;
+	Charts Geneva '9' (              normal )               0010;
+	NexusOptions '0' '0' '50'               001011011;
+	TipLabel '1';
+	TreeFont Geneva '9' (              normal );
+	TreeShape 1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'               1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'               1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'               1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'               0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'               1;
+	PrintTree 10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'               Geneva '9' (              normal )               Geneva '10' (              normal )               Geneva '9' (              normal )               Geneva '9' (              normal )               Geneva '9' (              bold )               Geneva '9' (              normal )               Geneva '9' (              normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' ' [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'               00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'               100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'               1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114899559a6126;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114899559ca0;
+			checksumv 0 2 238762464 WM114899559ca0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 492 259;
+			setLocation -7 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 515 612;
+					setLocation 501 32;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 4;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 20;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 3;
+					setInitialOffsetY 4;
+					setLegendWidth 183;
+					setLegendHeight 161;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.AsymmModelCurator.AsymmModelCurator;
+			tell It;
+				editModel My_Asymmetrical_Model #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 420 259;
+						setLocation 32 400;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '14-AsymmEstLikelihood.nex';
+			setPrevFileName '12-Mk1Likelihood.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 242;
+					setLocation -7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'The asymmetrical model (AsymmMk) has two parameters, which can either be expressed as a rate of change and a bias of gains vs. loses (as shown above in the editor window) or as a rate of forward evolution (0 to 1) and a rate of backward evolution.^n';
+				setTitle Asymmetrical_model;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/14-AsymmEstLikelihood.nex b/Resources/examples/Ancestral_States/14-AsymmEstLikelihood.nex
new file mode 100755
index 0000000..6fe159a
--- /dev/null
+++ b/Resources/examples/Ancestral_States/14-AsymmEstLikelihood.nex
@@ -0,0 +1,485 @@
+#NEXUS
+[written Sat Jun 07 10:00:28 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=19;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle striatum 
+	;
+	BLOCKID WM1148995c47d127;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "14-AsymmEstLikelihood.nex"';
+	DIMENSIONS  NCHAR=66;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 mentum_shape /  triangular 'trapezoid-rectangular', 2 tooth_emarg.? /  no yes, 3 tooth_bulbous? /  no slightly markedly, 4 mentum_epilobes /  indistinct 'slight-distinct', 5 pronotum /  rounded trapezoid, 6 pronot._carina /  absent short 'long_-_gap' 'long_-_basal', 7 metasternum /  unbordered bordered, 8 elytral_impression /  absent slight definite, 9 humeral_margin /  absent short moderate long, 10 interneur_4_shape /  straight slightly_sinuate distinctly_sinuate, 11 'ed3 + ed5 are [...]
+	MATRIX
+	balli             00010(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            00010(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       0(0 1)010(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         0(0 1)0100001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          0101000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        0001010030001020310120001-00-0000003021???????????????????????????
+	carinula          0001030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             00010(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        000101013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  10200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         0(0 1)010(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         01010(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          1(0 1)010(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       10200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      10200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         10200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          0101000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1(0 1)110(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	striatum          00010(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+
+;
+		BLOCKID WM1148995c4970;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "14-AsymmEstLikelihood.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 striatum;
+	TREE Untitled_Tree = (19,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18)))))));
+	TREE Untitled_Tree = (19,6,7,8,9,10,(1,2),(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+	TREE Untitled_Tree = (19,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16)))))))));
+	TREE Untitled_Tree = ((4,(3,5)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15)))))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))));
+	TREE Untitled_Tree = ((3,4,5),(19,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01176471) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  17;
+	CHARSET Male_Genitalia   =   18 -  33;
+	CHARSET Female_Genitalia   =   34 -  39;
+	CHARSET Chromosomes   =   40 -  41;
+	CHARSET Larvae   =   42 -  66;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  17, Male_Genitalia :  18 -  33, Female_Genitalia :  34 -  39, Chromosomes :  40 -  41, Larval_Structure :  42 -  66;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  17, Male_Genitalia :  18 -  33, Female_Genitalia :  34 -  39, Chromosomes :  40 -  41, Larval_Structure :  42 -  66;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  39, Chromosomes :  40 -  41, Larval_Structure :  42 -  66;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                 unord PolyTcount =                 MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  15 45, ord:  1 -  14 16 -  44 46 -  66;
+TYPESET types   =  unord:  15 45, ord:  1 -  14 16 -  44 46 -  66;
+
+	EXSET larval_only  =  1 -  41;
+EXSET adult_external  =  18 -  66;
+EXSET genitalia  =  1 -  17 40 -  66;
+
+	WTSET 123polyerror  =  3: 1 1 3 -  5 7 11 -  12 14 -  15 20 22 -  25 28 -  31 33 -  37 39 -  40 42 -  44 46 -  50 52 -  53 55 57 -  62 65 -  66 , 2: 2 2 6 10 13 17 -  19 38 45 51 54 56 64, 1: 8 -  9 16 21 26 -  27 32 41 63;
+WTSET 12error_only  =  2: 1 -  7 10 -  12 14 -  15 20 22 -  25 28 -  31 33 -  40 42 -  44 46 -  50 52 -  53 55 -  62 65 -  66 , 1: 8 -  9 13 16 -  19 21 26 -  27 32 41 45 51 54 63 -  64;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 40 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel My_Mk1_Model (Mk1) = 
+		 rate 0.2;
+
+	ProbModelSet * UNTITLED   =  'Asymm. 2 param. (estimate)':  1 -  66;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1187776091;
+	FileSettings editor '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                  Geneva '9' '100' '1'                  all;
+	EditorPosition '46' '9' '451' '1011';
+	TreeWindowPosition '46' '6' '636' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '434'                  001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '278'                  100;
+	ListWindow Trees closed Geneva '9' '50' '10' '273' '386';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Data List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                  00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                  10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                  110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                  1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                  0;
+	Charts  Geneva '9' (                 normal )                  0010;
+	NexusOptions '0' '0' '50'                  001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                 normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                  1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                  1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                  1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                  0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                  1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                  Geneva '9' (                 normal )                  Geneva '10' (                 normal )                  Geneva '9' (                 normal )                  Geneva '9' (                 normal )                  Geneva '9' (                 bold )                  Geneva '9' (                 normal )                  Geneva '9' (                 normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                  00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                  100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                  1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  66;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148995c47d127;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM1148995c4970;
+			checksum 0 328200364 WM1148995c4970;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 533 314;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 569 669;
+					setLocation 579 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 4;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 1;
+					setInitialOffsetY -198;
+					setLegendWidth 212;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #206796807167704052 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 500 486;
+					setLocation 17 418;
+					setFont SansSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames off;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15-Mk1AsymmCompare.nex';
+			setPrevFileName '13-AsymmLikelihood.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 461 297;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The calculation at right uses the asymmetrical AsymmMk model, but without specifying rates in advance.  Thus, the rates of forward and backward changes are estimated from the data.^n^nIn the box in the Trace Character legend can be seen the estimated forward and backward rates.^n^nIf you edit the character matrix (character 1) the calculations will be updated and you may see the estimated rates change.  Likewise changing the tree will affect the estimates.';
+				setTitle Estimating_parameters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15-Mk1AsymmCompare.nex b/Resources/examples/Ancestral_States/15-Mk1AsymmCompare.nex
new file mode 100755
index 0000000..0ad0d6e
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15-Mk1AsymmCompare.nex
@@ -0,0 +1,527 @@
+#NEXUS
+[written Sat Jun 07 10:00:49 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=19;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle striatum 
+	;
+	BLOCKID WM11489963a59128;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15-Mk1AsymmCompare.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  'absent-v._slight_mirrors' slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser [...]
+	MATRIX
+	balli             1010-00(1 2)1000011000000010(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1010-00(1 2)10(0 1)1011000000010(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       12(2 3)(0 1)-002000201000000(0 1)010(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         12(2 3)0-(0 1)02001001010000(0 1)0100001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1120-002000301000000101000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        123(0 2)000(1 2)000011100000001010030001020310120001-00-0000003021???????????????????????????
+	carinula          12(0 1 2)0-00210(0 1)101100000001030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             12(0 1 2)1-0021000011000000010(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        12(0 1 2 3)(0 2)000210(0 1)00110000000101013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  12(0 1 2)1-0001002010000110200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(1 2)3(0 2)0(0 1)(0 1 2)1000001100000(0 1)010(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1231-(0 1)0(0 1)0000011000001010(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          123(2 3)0(0 1)02101001100001(0 1)010(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1233010210(0 1)0011000010200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1233010210(0 1)0011000010200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1233(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0011000010200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1233(0 1)(0 1)02(0 1)0(0 1)000100000101000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1233(0 1)(0 1)02000000?00001(0 1)110(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	striatum          0010--0211-0011000000010(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+
+;
+		BLOCKID WM11489963a7f0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "15-Mk1AsymmCompare.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 striatum;
+	TREE Untitled_Tree = (19,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18)))))));
+	TREE Untitled_Tree = (19,6,7,8,9,10,(1,2),(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+	TREE Untitled_Tree = (19,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16)))))))));
+	TREE Untitled_Tree = ((4,(3,5)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15)))))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))));
+	TREE Untitled_Tree = ((3,4,5),(19,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel My_Mk1_Model (Mk1) = 
+		 rate 0.2;
+
+	ProbModelSet * UNTITLED   =  'Asymm. 2 param. (estimate)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1187776091;
+	FileSettings editor '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                      Geneva '9' '100' '1'                      all;
+	EditorPosition '46' '9' '451' '1011';
+	TreeWindowPosition '46' '6' '636' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '434'                      001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '278'                      100;
+	ListWindow Trees closed Geneva '9' '50' '10' '273' '386';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Data List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                      00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                      10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                      110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                      1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                      0;
+	Charts  Geneva '9' (                     normal )                      0010;
+	NexusOptions '0' '0' '50'                      001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                     normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                      1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                      1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                      1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                      0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                      1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                      Geneva '9' (                     normal )                      Geneva '10' (                     normal )                      Geneva '9' (                     normal )                      Geneva '9' (                     normal )                      Geneva '9' (                     bold )                      Geneva '9' (                     normal )                      Geneva '9' (                     [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                      00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                      100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                      1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM11489963a59128;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM11489963a7f0;
+			checksum 0 4161077265 WM11489963a7f0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 356 384;
+			setLocation 3 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 284 327;
+					setLocation 3 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 4;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 720 640;
+						setLocation 407 22;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #206796807167704052;
+								endTell;
+							endTell;
+							setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+							tell It;
+								setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+								tell It;
+									setModel 1   'Mk1 (est.)';
+								endTell;
+								getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+								tell It;
+									setReportMode Proportional_Likelihoods;
+									setRootMode Use_Root_State_Frequencies_as_Prior;
+									setDecision 2.0;
+									setUnderflowCheckFreq 2;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 20;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -178;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #206796807167704052;
+								endTell;
+							endTell;
+							setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+							tell It;
+								setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+								tell It;
+									setModel 0   'Asymm. 2 param. (estimate)';
+								endTell;
+								getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+								tell It;
+									setReportMode Proportional_Likelihoods;
+									setRootMode Use_Root_State_Frequencies_as_Prior;
+									setDecision 2.0;
+									setUnderflowCheckFreq 2;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 20;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -163;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+						tell It;
+							setSpotDiameter 22;
+							setEdgeWidth 4;
+							orientLeft;
+							useDiagonal;
+							toggleCosmic off;
+							getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter on;
+								toggleEven on;
+							endTell;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15aa-xiphLikelihood.nex';
+			setPrevFileName '14-AsymmEstLikelihood.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 284 367;
+					setLocation 3 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The mirror tree window at right shows two reconstructions, one using the symmetrical Mk1 model (at left) and the other using the asymmetrical AsymmMk model (at right).';
+				setTitle Mk1_vs._AsymmMk;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15a-estimatingParameters.nex b/Resources/examples/Ancestral_States/15a-estimatingParameters.nex
new file mode 100755
index 0000000..e8ba8dd
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15a-estimatingParameters.nex
@@ -0,0 +1,228 @@
+#NEXUS
+[written Wed May 17 14:28:23 PDT 2006 by Mesquite  version 1.1 (build h59) at Yepoella.local/10.0.1.7]
+
+BEGIN TAXA;
+	TITLE Untitled_Taxa_Block;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		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 AA BB CC DD 
+	;
+
+END;
+
+
+BEGIN MESQUITECHARMODELS;
+	CharModel 'Mk1-simulated' (Mk1) = 
+		 rate 0.1 maxState 1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4409151645800273408;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.MkModelCurator.MkModelCurator;
+			tell It;
+				editModel 'Mk1-simulated' #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						setSweetMin 0.0;
+						setSweetMax 1.0;
+						setSize 200 100;
+						setLocation 447 536;
+						setFont SanSerif;
+						setFontSize 10;
+						offInfoBar;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4409151645800273408  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 10.0;
+					endTell;
+					setSeed 1063722105846;
+				endTell;
+				setAssignedID 1608.1063722049484.8324690498246735778;
+				getTreeWindow;
+				tell It;
+					setSize 550 411;
+					setLocation 438 24;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleCenter on;
+							toggleEven on;
+							namesAngle ?;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths off;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharacterValuesChart.CharacterValuesChart;
+		tell It;
+			setTaxa #4409151645800273408;
+			setCalculator  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.stochchar.Mk1Rate.Mk1Rate;
+				tell It;
+					getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+					tell It;
+						setDecision 2.0;
+						setUnderflowCheckFreq 2;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1608.1063722049484.8324690498246735778;
+				endTell;
+			endTell;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+				tell It;
+					setSeed 1063722235442;
+					setCharacterSimulator  #mesquite.stochchar.EvolveCategChars.EvolveCategChars;
+					tell It;
+						setModelByName 'Mk1-simulated';
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1608.1063722049484.8324690498246735778;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 425 332;
+					setLocation 5 23;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					showAverageToggle on;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+				endTell;
+					toggleColorItems on;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15b-estimatingParameters.nex';
+			setPrevFileName '15-Mk1AsymmCompare.nex';
+			getWindow;
+			tell It;
+					setSize 429 212;
+					setLocation 5 469;
+					setFont SanSerif;
+					setFontSize 10;
+					offInfoBar;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setActive;
+				setExplanation 'Estimation of the parameters of model of character evolution need not be done in the context of reconstruction of ancestral states.  Here, 100 characters are simulated under the Mk1 model with rate 0.1, on the tree shown.  The rate of evolution is then estimated as if it weren''t known.  The chart above shows the results.  Note that the average estimate is too high; this is typical, for a few lucky cases in which simulated change happens on short branches could yield  [...]
+				setTitle Estimating_parameters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15aa-xiphLikelihood.nex b/Resources/examples/Ancestral_States/15aa-xiphLikelihood.nex
new file mode 100644
index 0000000..15d770e
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15aa-xiphLikelihood.nex
@@ -0,0 +1,343 @@
+#NEXUS
+[written Wed Aug 26 11:50:07 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		X._multilineatus X._nigrensis X._cortezi X._malinche X._continens X._nezahualcoyti X._montezumae X._pygmaeus X._birchmanii X._couchianus X._gordoni X._meyeri X._xiphidium X._variatus X._evelynae X._clemenciae X._milleri X._maculatus X._andersi X._alvarezi X._helleri X._signum P._olmaceae P._interm P._compressa 
+	;
+	BLOCKID 010a90b186ef1;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15aa-xiphLikelihood.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 Tail /  swordless swords ; 
+	MATRIX
+	X._multilineatus  1
+	X._nigrensis      1
+	X._cortezi        1
+	X._malinche       1
+	X._continens      0
+	X._nezahualcoyti  1
+	X._montezumae     1
+	X._pygmaeus       0
+	X._birchmanii     1
+	X._couchianus     0
+	X._gordoni        0
+	X._meyeri         0
+	X._xiphidium      0
+	X._variatus       0
+	X._evelynae       0
+	X._clemenciae     1
+	X._milleri        0
+	X._maculatus      0
+	X._andersi        0
+	X._alvarezi       1
+	X._helleri        1
+	X._signum         1
+	P._olmaceae       0
+	P._interm         0
+	P._compressa      0
+
+;
+		BLOCKID 010a90b187b50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "15aa-xiphLikelihood.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 X._multilineatus,
+		2 X._nigrensis,
+		3 X._cortezi,
+		4 X._malinche,
+		5 X._continens,
+		6 X._nezahualcoyti,
+		7 X._montezumae,
+		8 X._pygmaeus,
+		9 X._birchmanii,
+		10 X._couchianus,
+		11 X._gordoni,
+		12 X._meyeri,
+		13 X._xiphidium,
+		14 X._variatus,
+		15 X._evelynae,
+		16 X._clemenciae,
+		17 X._milleri,
+		18 X._maculatus,
+		19 X._andersi,
+		20 X._alvarezi,
+		21 X._helleri,
+		22 X._signum,
+		23 P._olmaceae,
+		24 P._interm,
+		25 P._compressa;
+	TREE Figure_5 = ((((((((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0,5:1.0):1.0,6:1.0):1.0,7:1.0):1.0,(8:1.0,9:1.0):1.0):1.0,((((((((((10:1.0,11:1.0):1.0,12:1.0):1.0,13:1.0):1.0,14:1.0):1.0,15:1.0):1.0,16:1.0):1.0,17:1.0):1.0,18:1.0):1.0,19:1.0):1.0,((20:1.0,21:1.0):1.0,22:1.0):1.0):1.0):1.0,((25:1.0,24:1.0):1.0,23:1.0):1.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel mk1_model (Mk1) = 
+		 rate 0.067 maxState 1;
+	CharModel Asymmetrical_model (AsymmMk) = 
+		 forward  ?  backward  ?  equilibAsPrior;
+
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8265138006560775301 010a90b186ef1;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6115459465024062079 010a90b187b50;
+			checksumv 0 2 1326791329 010a90b187b50;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 460 319;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8265138006560775301  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 298.1019014879746.4115002201943536709;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 607 748;
+					setLocation 495 32;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((((((((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0,5:3.0):1.0,6:4.0):1.0,7:5.0):1.0,(8:1.0,9:1.0):5.0):5.0,((((((((((10:1.0,11:1.0):1.0,12:2.0):1.0,13:3.0):1.0,14:4.0):1.0,15:5.0):1.0,16:6.0):1.0,17:7.0):1.0,18:8.0):1.0,19:9.0):1.0,((20:1.0,21:1.0):1.0,22:2.0):8.0):1.0):1.0,((25:1.0,24:1.0):1.0,23:2.0):10.0):1.0;';
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #6115459465024062079;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 3   Asymmetrical_model;
+							endTell;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 20;
+					setInitialOffsetY 4;
+					setLegendWidth 243;
+					setLegendHeight 161;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.AsymmModelCurator.AsymmModelCurator;
+			tell It;
+				editModel Asymmetrical_model #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 434 325;
+						setLocation 15 467;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15ab-xiphStochCharMap.nex';
+			setPrevFileName '15-Mk1AsymmCompare.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 388 302;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'The asymmetrical model of evolution (AsymmMk) has two options: either the root state frequencies are assumed to be the same as the implicit equilibrium frequencies, or they are assumed to be equal (i.e. a flat prior).  Try choosing the alternative options in the editor for the model.  Note how the reconstruction at the root changes if the root state option is changed.  This effect is particularly strong if one of the states is more common than the other.';
+				setTitle Likelihood;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15ab-xiphStochCharMap.nex b/Resources/examples/Ancestral_States/15ab-xiphStochCharMap.nex
new file mode 100644
index 0000000..015a10a
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15ab-xiphStochCharMap.nex
@@ -0,0 +1,329 @@
+#NEXUS
+[written Sat Jun 07 10:12:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		X._multilineatus X._nigrensis X._cortezi X._malinche X._continens X._nezahualcoyti X._montezumae X._pygmaeus X._birchmanii X._couchianus X._gordoni X._meyeri X._xiphidium X._variatus X._evelynae X._clemenciae X._milleri X._maculatus X._andersi X._alvarezi X._helleri X._signum P._olmaceae P._interm P._compressa 
+	;
+	BLOCKID 010a90b186ef1;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15ab-xiphStochCharMap.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 Tail /  swordless swords ; 
+	MATRIX
+	X._multilineatus  1
+	X._nigrensis      1
+	X._cortezi        1
+	X._malinche       1
+	X._continens      0
+	X._nezahualcoyti  1
+	X._montezumae     1
+	X._pygmaeus       0
+	X._birchmanii     1
+	X._couchianus     0
+	X._gordoni        0
+	X._meyeri         0
+	X._xiphidium      0
+	X._variatus       0
+	X._evelynae       0
+	X._clemenciae     1
+	X._milleri        0
+	X._maculatus      0
+	X._andersi        0
+	X._alvarezi       1
+	X._helleri        1
+	X._signum         1
+	P._olmaceae       0
+	P._interm         0
+	P._compressa      0
+
+;
+		BLOCKID 010a90b187b50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "15ab-xiphStochCharMap.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 X._multilineatus,
+		2 X._nigrensis,
+		3 X._cortezi,
+		4 X._malinche,
+		5 X._continens,
+		6 X._nezahualcoyti,
+		7 X._montezumae,
+		8 X._pygmaeus,
+		9 X._birchmanii,
+		10 X._couchianus,
+		11 X._gordoni,
+		12 X._meyeri,
+		13 X._xiphidium,
+		14 X._variatus,
+		15 X._evelynae,
+		16 X._clemenciae,
+		17 X._milleri,
+		18 X._maculatus,
+		19 X._andersi,
+		20 X._alvarezi,
+		21 X._helleri,
+		22 X._signum,
+		23 P._olmaceae,
+		24 P._interm,
+		25 P._compressa;
+	TREE Figure_5 = ((((((((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0,5:1.0):1.0,6:1.0):1.0,7:1.0):1.0,(8:1.0,9:1.0):1.0):1.0,((((((((((10:1.0,11:1.0):1.0,12:1.0):1.0,13:1.0):1.0,14:1.0):1.0,15:1.0):1.0,16:1.0):1.0,17:1.0):1.0,18:1.0):1.0,19:1.0):1.0,((20:1.0,21:1.0):1.0,22:1.0):1.0):1.0):1.0,((25:1.0,24:1.0):1.0,23:1.0):1.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel mk1_model (Mk1) = 
+		 rate 0.067 maxState 1;
+
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8265138006560775301 010a90b186ef1;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6115459465024062079 010a90b187b50;
+			checksum 0 3737896798 010a90b187b50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 475 402;
+			setLocation 3 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8265138006560775301  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 298.1019014879746.4115002201943536709;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 634 717;
+					setLocation 506 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 10;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((23:2.0,(24:1.0,25:1.0):1.0):10.0,(((8:1.0,9:1.0):5.0,(7:5.0,(6:4.0,(5:3.0,((1:1.0,2:1.0):1.0,(3:1.0,4:1.0):1.0):1.0):1.0):1.0):1.0):5.0,((22:2.0,(20:1.0,21:1.0):1.0):8.0,(19:9.0,(18:8.0,(17:7.0,(16:6.0,(15:5.0,(14:4.0,(13:3.0,(12:2.0,(10:1.0,11:1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #6115459465024062079;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.StochCharMapper.StochCharMapper;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 2   mk1_model;
+							endTell;
+							setSeed 1146962907862;
+							setMax 1000;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 7;
+					setInitialOffsetY -175;
+					setLegendWidth 243;
+					setLegendHeight 175;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.MkModelCurator.MkModelCurator;
+			tell It;
+				editModel mk1_model #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						setSweetMin 0.0;
+						setSweetMax 1.0;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 325 172;
+						setLocation 57 508;
+						setFont SanSerif;
+						setFontSize 10;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15b1-estimatingParameters.nex';
+			setPrevFileName '15aa-xiphLikelihood.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 403 385;
+					setLocation 3 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This shows a realization of character evolution made by stochastic character mapping.  Stochastic character mapping is available as a reconstruction method for categorical data.^n^nUse the "realization" arrows to see alternative realizations.  The model of evolution, shown in the small window, has its rate estimated from the tree and data.  Try raising the rate to see how the realizations change.';
+				setTitle Stochastic_character_mapping;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Show_Manual  'http://mesquiteproject.wikispaces.com/Ancestral+States#scm';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15b-estimatingParameters.nex b/Resources/examples/Ancestral_States/15b-estimatingParameters.nex
new file mode 100755
index 0000000..50298fc
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15b-estimatingParameters.nex
@@ -0,0 +1,288 @@
+#NEXUS
+[written Wed May 17 14:28:35 PDT 2006 by Mesquite  version 1.1 (build h59) at Yepoella.local/10.0.1.7]
+
+BEGIN TAXA;
+	TITLE Untitled_Taxa_Block;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		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 AA BB CC DD 
+	;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Matrix_#1_simulated_by_Evolve_Categorical_Characters;
+	DIMENSIONS  NCHAR=100;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A   1000100111110110010011101010100100001010000001110011101010101110000110010101101011100100011011111010
+	B   0001001011100000011101000100111100011011111011111001001011001111101011010110100001101101011100111000
+	C   0100001001101100111001111110000001111100110010111000100011011110011110011101101111100001011011010100
+	D   0000001111101100110000111010000100101110110000100011110000000110011111111111000110100000010111110010
+	E   0100000111000110111110101010000101110110110010010011101111001011000000100111001001110011111011010100
+	F   0000000101100100011111111011111100111101101110100001111111000100011110010111001011110101111101101000
+	G   0101101101111100110111011011001101011000000110010011101010000111010011001010101101000001011010100000
+	H   0101101010100100011011100011010100110100110111110001010010101111110110111101000011111001000101100000
+	I   0101101111110100111001100011110101111000110101110001100000000111010101011111001101100001011000010000
+	J   0100001111000101111000000010001111011100000101101001100110010111100110111111110101110001010011110010
+	K   0001001011100001100011011011010100100110111000110101100010101100001111110111111010100010011110111100
+	L   0101011100000100110010011010111011111010110010011111101011011001110101000011001101101000011001100111
+	M   0110101111100100111111001010011110101100010000111001010010101000111001111111011111100101011011110010
+	N   0100000101001111000101011010010101111110110010011001101010010010011111111111101011110010111011110010
+	O   1110001100101001110011100010110100000110101100111010110000010111010101010011010011000100011111111010
+	P   1111001111101101000110011111111100000111111110100101111111000101011011000111000000111100001001100101
+	Q   0101001111100100110111111011100100111111111000110011110111010011011110111100101011100000010011101100
+	R   0110011101100011101100011011110011001010010110100000100110110001110110111111100001110110011101110010
+	S   0001001001001100111011101010011011010101110010111001101111011111001101000110111111001001011001000101
+	T   0001001111111101101111011110110111011010110100100001110010001101010101011011110101000011011000110010
+	U   1111100011110110010011001010110100001010110001110001101000000111101101111101100010100100011011111011
+	V   0001001010111000010110111011000101101111111010100001110111100011010110011101010011110100011011101000
+	W   0101101010000100011111101010010100110000110011110101010010111111111111110010100111111000000111100010
+	X   1100100111110110110011101110100101001010000001110011001010101110001100000101100111010100011111001010
+	Y   0110011101000101101100011011110011101110110110100101010110110011111100111111100011110010011011110010
+	Z   0110001011100100011110001110111110101100110100011101000010101000110001111111010111100101011110110010
+	AA  0101001100000100110010010010111001111000110110011010001111011011110101000111000001101000011001100110
+	BB  0001001011100100011101000100111110011011111011111001001011001111101011010110100001101101011100111000
+	CC  1100100110110110110011101011100100001010000001110011001010101110001000000101100011110100011111101010
+	DD  1000100111110110010011101010100100001010001001110011101010101110000110010101101011100100011011111010
+
+;
+
+END;
+BEGIN MESQUITECHARMODELS;
+	CharModel 'Mk1-simulated' (Mk1) = 
+		 rate 0.1 maxState 1;
+	CharModel 'AsymmMk-simulated' (AsymmMk) = 
+		 rate 0.1 bias 1.0 equilibAsPrior;
+	CharModel reconstruct (AsymmMk) = 
+		 forward 0.08279683 backward 1.13258E-7 equilibAsPrior;
+
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  100;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  100;
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  100;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4409151645800273408;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6717564632715537289;
+			checksum 0 631240850;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.AsymmModelCurator.AsymmModelCurator;
+			tell It;
+				editModel 'AsymmMk-simulated' #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						setSize 260 200;
+						setLocation 438 529;
+						setFont SanSerif;
+						setFontSize 10;
+						offInfoBar;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4409151645800273408  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 10.0;
+					endTell;
+					setSeed 1063722105846;
+				endTell;
+				setAssignedID 1608.1063722049484.8324690498246735778;
+				getTreeWindow;
+				tell It;
+					setSize 550 411;
+					setLocation 438 24;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleCenter on;
+							toggleEven on;
+							namesAngle ?;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths off;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharacterValuesChart.CharacterValuesChart;
+		tell It;
+			setTaxa #4409151645800273408;
+			setCalculator  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.stochchar.GainLossRates.GainLossRates;
+				tell It;
+					setReportMode Bias;
+					getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+					tell It;
+						setDecision 2.0;
+						setUnderflowCheckFreq 2;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1608.1063722049484.8324690498246735778;
+				endTell;
+			endTell;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+				tell It;
+					setSeed 1064193252724;
+					setCharacterSimulator  #mesquite.stochchar.EvolveCategChars.EvolveCategChars;
+					tell It;
+						setModelByName 'AsymmMk-simulated';
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1608.1063722049484.8324690498246735778;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 388 327;
+					setLocation 2 26;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					showAverageToggle on;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+				endTell;
+					toggleColorItems on;
+					setNumberItems 5;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16b-BranchLengths.nex';
+			setPrevFileName '15a-estimatingParameters.nex';
+			getWindow;
+			tell It;
+					setSize 426 218;
+					setLocation 4 453;
+					setFont SanSerif;
+					setFontSize 10;
+					offInfoBar;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+				setExplanation 'Here a different model of character evolution is used in the simulation, one in which the rate of forward change (0 to 1) may be different from the rate of backward change (1 to 0).  Their ratio is the bias shown in the model editing window at right.  The chart shows the bias estimated from characters simulated on the tree shown.^n^nThe chart is shown with only 5 replicate simulations because the calculations take a while.  If you want, select Number of Characters in  [...]
+				setTitle Estimating_parameters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15b1-estimatingParameters.nex b/Resources/examples/Ancestral_States/15b1-estimatingParameters.nex
new file mode 100644
index 0000000..5611850
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15b1-estimatingParameters.nex
@@ -0,0 +1,270 @@
+#NEXUS
+[written Sat Jun 07 10:12:46 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		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 AA BB CC DD 
+	;
+	BLOCKID WM114899806e9131;
+
+END;
+
+
+BEGIN MESQUITECHARMODELS;
+	CharModel 'Mk1-simulated' (Mk1) = 
+		 rate 0.1 maxState 1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4409151645800273408 WM114899806e9131;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 499 443;
+			setLocation 14 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4409151645800273408  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 10.0;
+					endTell;
+					setSeed 1063722105846;
+				endTell;
+				setAssignedID 1608.1063722049484.8324690498246735778;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 517 330;
+					setLocation 587 35;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.MkModelCurator.MkModelCurator;
+			tell It;
+				editModel 'Mk1-simulated' #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						setSweetMin 0.0;
+						setSweetMax 1.0;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 275 180;
+						setLocation 51 598;
+						setFont SanSerif;
+						setFontSize 10;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharacterValuesChart.CharacterValuesChart;
+		tell It;
+			setTaxa #4409151645800273408;
+			setCalculator  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.stochchar.Mk1Rate.Mk1Rate;
+				tell It;
+					getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+					tell It;
+						setDecision 2.0;
+						setUnderflowCheckFreq 2;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1608.1063722049484.8324690498246735778;
+				endTell;
+			endTell;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+				tell It;
+					setSeed 1;
+					setCharacterSimulator  #mesquite.stochchar.EvolveCategChars.EvolveCategChars;
+					tell It;
+						setModelByName 'Mk1-simulated';
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1608.1063722049484.8324690498246735778;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 559 327;
+					setLocation 582 516;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems on;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15b2-estimatingParameters.nex';
+			setPrevFileName '15ab-xiphStochCharMap.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 427 426;
+					setLocation 14 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Estimation of the parameters of model of character evolution need not be done in the context of reconstruction of ancestral states.  Here, 100 characters are simulated under the Mk1 model with rate 0.1, on the tree shown.  The rate of evolution is then estimated as if it weren''t known.  The chart shows the results.  Note that the average estimate is too high; this is typical, for a few lucky cases in which simulated change happens on short branches could yield an est [...]
+				setTitle Estimating_parameters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/15b2-estimatingParameters.nex b/Resources/examples/Ancestral_States/15b2-estimatingParameters.nex
new file mode 100644
index 0000000..e4a5ded
--- /dev/null
+++ b/Resources/examples/Ancestral_States/15b2-estimatingParameters.nex
@@ -0,0 +1,347 @@
+#NEXUS
+[written Wed Aug 26 11:51:07 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		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 AA BB CC DD 
+	;
+	BLOCKID WM114899a08b0132;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15b2-estimatingParameters.nex"';
+	DIMENSIONS  NCHAR=100;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A   1000100111110110010011101010100100001010000001110011101010101110000110010101101011100100011011111010
+	B   0001001011100000011101000100111100011011111011111001001011001111101011010110100001101101011100111000
+	C   0100001001101100111001111110000001111100110010111000100011011110011110011101101111100001011011010100
+	D   0000001111101100110000111010000100101110110000100011110000000110011111111111000110100000010111110010
+	E   0100000111000110111110101010000101110110110010010011101111001011000000100111001001110011111011010100
+	F   0000000101100100011111111011111100111101101110100001111111000100011110010111001011110101111101101000
+	G   0101101101111100110111011011001101011000000110010011101010000111010011001010101101000001011010100000
+	H   0101101010100100011011100011010100110100110111110001010010101111110110111101000011111001000101100000
+	I   0101101111110100111001100011110101111000110101110001100000000111010101011111001101100001011000010000
+	J   0100001111000101111000000010001111011100000101101001100110010111100110111111110101110001010011110010
+	K   0001001011100001100011011011010100100110111000110101100010101100001111110111111010100010011110111100
+	L   0101011100000100110010011010111011111010110010011111101011011001110101000011001101101000011001100111
+	M   0110101111100100111111001010011110101100010000111001010010101000111001111111011111100101011011110010
+	N   0100000101001111000101011010010101111110110010011001101010010010011111111111101011110010111011110010
+	O   1110001100101001110011100010110100000110101100111010110000010111010101010011010011000100011111111010
+	P   1111001111101101000110011111111100000111111110100101111111000101011011000111000000111100001001100101
+	Q   0101001111100100110111111011100100111111111000110011110111010011011110111100101011100000010011101100
+	R   0110011101100011101100011011110011001010010110100000100110110001110110111111100001110110011101110010
+	S   0001001001001100111011101010011011010101110010111001101111011111001101000110111111001001011001000101
+	T   0001001111111101101111011110110111011010110100100001110010001101010101011011110101000011011000110010
+	U   1111100011110110010011001010110100001010110001110001101000000111101101111101100010100100011011111011
+	V   0001001010111000010110111011000101101111111010100001110111100011010110011101010011110100011011101000
+	W   0101101010000100011111101010010100110000110011110101010010111111111111110010100111111000000111100010
+	X   1100100111110110110011101110100101001010000001110011001010101110001100000101100111010100011111001010
+	Y   0110011101000101101100011011110011101110110110100101010110110011111100111111100011110010011011110010
+	Z   0110001011100100011110001110111110101100110100011101000010101000110001111111010111100101011110110010
+	AA  0101001100000100110010010010111001111000110110011010001111011011110101000111000001101000011001100110
+	BB  0001001011100100011101000100111110011011111011111001001011001111101011010110100001101101011100111000
+	CC  1100100110110110110011101011100100001010000001110011001010101110001000000101100011110100011111101010
+	DD  1000100111110110010011101010100100001010001001110011101010101110000110010101101011100100011011111010
+
+;
+		BLOCKID WM114899a08ca0;
+
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  100;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel 'Mk1-simulated' (Mk1) = 
+		 rate 0.1 maxState 1;
+	CharModel 'AsymmMk-simulated' (AsymmMk) = 
+		 rate 0.1 bias 1.0 equilibAsPrior;
+	CharModel reconstruct (AsymmMk) = 
+		 forward 0.08279683 backward 1.13258E-7 equilibAsPrior;
+
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  100;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  100;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4409151645800273408 WM114899a08b0132;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6717564632715537289 WM114899a08ca0;
+			checksumv 0 2 1587477094 WM114899a08ca0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 475 338;
+			setLocation 12 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4409151645800273408  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 10.0;
+					endTell;
+					setSeed 1063722105846;
+					toggleRepeatable on;
+				endTell;
+				setAssignedID 1608.1063722049484.8324690498246735778;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 476 310;
+					setLocation 534 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						setCornerMode Right_Angle  50;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharModels.ManageCharModels;
+		tell It;
+			getEmployee #mesquite.stochchar.AsymmModelCurator.AsymmModelCurator;
+			tell It;
+				editModel 'AsymmMk-simulated' #mesquite.minimal.WindowBabysitter.WindowBabysitter;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 403 338;
+						setLocation 63 501;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharacterValuesChart.CharacterValuesChart;
+		tell It;
+			setTaxa #4409151645800273408;
+			setCalculator  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.stochchar.GainLossRates.GainLossRates;
+				tell It;
+					setReportMode Bias;
+					getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+					tell It;
+						setDecision 2.0;
+						setUnderflowCheckFreq 2;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1608.1063722049484.8324690498246735778;
+				endTell;
+			endTell;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+				tell It;
+					setSeed 1064193252724;
+					setCharacterSimulator  #mesquite.stochchar.EvolveCategChars.EvolveCategChars;
+					tell It;
+						setModelByName 'AsymmMk-simulated';
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1608.1063722049484.8324690498246735778;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 544 386;
+					setLocation 533 476;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					toggleAutoRecalc on;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems on;
+					setNumberItems 5;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16b-BranchLengths.nex';
+			setPrevFileName '15b1-estimatingParameters.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 403 321;
+					setLocation 12 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Here a different model of character evolution is used in the simulation, one in which the rate of forward change (0 to 1) may be different from the rate of backward change (1 to 0).  Their ratio is the bias shown in the model editing window below.  The chart shows the bias estimated from characters simulated on the tree shown.^n^nThe chart is shown with only 5 replicate simulations because the calculations take a while.  If you want, select Number of Characters in the [...]
+				setTitle Estimating_parameters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/16b-BranchLengths.nex b/Resources/examples/Ancestral_States/16b-BranchLengths.nex
new file mode 100755
index 0000000..228e742
--- /dev/null
+++ b/Resources/examples/Ancestral_States/16b-BranchLengths.nex
@@ -0,0 +1,406 @@
+#NEXUS
+[written Sat Jun 07 10:13:12 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=8;
+	TAXLABELS
+		A B C D E F G H 
+	;
+	BLOCKID WM114899aa574133;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  categorical;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  0
+	B  0
+	C  1
+	D  1
+	E  0
+	F  0
+	G  0
+	H  0
+
+;
+		BLOCKID WM114899aa5890;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  continuous;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+	MATRIX
+	A   -1.4606048803385268
+	B   -0.193359596320595
+	C   3.264132
+	D   -2.057461055293982
+	E   0.6847354011457061
+	F   -0.4816171497053599
+	G   0.5491410459479807
+	H   0.2752307217126102
+
+;
+		BLOCKID WM114899aa5a50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "16b-BranchLengths.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H;
+	TREE example_tree = (((1:0.5563733523696296,7:0.5563733523696296):2.628632228380894,3:3.1850055807505235):1.8149944192494767,((2:1.5582030415182246,(6:0.47359858995526644,8:0.47359858995526644):1.0846044515629583):0.8228523723677698,(4:1.8632498066403747,5:1.8632498066403747):0.5178056072456201):2.6189445861140057);
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = categorical)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = categorical)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = continuous)  =  Squared:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = categorical)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = continuous)  =  Brownian_default:  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4887592468791851101 WM114899aa574133;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5098131390805215500 WM114899aa5890;
+			checksum 0 193681281 WM114899aa5890;
+			setID 1 6202394371766150871 WM114899aa5a50;
+			checksum 1 1560782452 WM114899aa5a50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 568 324;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4887592468791851101  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 5.0;
+					endTell;
+					setSeed 1024954232643;
+				endTell;
+				setAssignedID 502.1024954218635.3391073105798146224;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 659 433;
+					setLocation 643 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BranchLengthsAdjust.AdjustToolExtra.stretchAdjustor;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 10;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 3;
+					setTree '(((1:0.5563733523696296,7:0.5563733523696296):2.628632228380894,3:3.1850055807505235):1.8149944192494767,((2:1.5582030415182246,(6:0.47359858995526644,8:0.47359858995526644):1.0846044515629583):0.8228523723677698,(4:1.8632498066403747,5:1.8632498066403747):0.5178056072456201):2.6189445861140057);';
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 360 400;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #6202394371766150871;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -199;
+					setInitialOffsetY -377;
+					setLegendWidth 142;
+					setLegendHeight 302;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+						tell It;
+							setSpotDiameter 22;
+							setEdgeWidth 4;
+							orientUp;
+							useDiagonal;
+							toggleCosmic off;
+							getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle on;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter on;
+								toggleEven on;
+							endTell;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 587 471;
+						setLocation 15 416;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #5098131390805215500;
+								endTell;
+							endTell;
+							setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+							tell It;
+								setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+								tell It;
+									setModel 0   'Asymm. 2 param. (estimate)';
+								endTell;
+								getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+								tell It;
+									setReportMode Proportional_Likelihoods;
+									setRootMode Use_Root_State_Frequencies_as_Prior;
+									setDecision 2.0;
+									setUnderflowCheckFreq 2;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -161;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16c-TraceAllChars.nex';
+			setPrevFileName '15b-estimatingParameters.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 496 307;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Many calculations in Mesquite are branch length sensitive.  The Tree Window shows a continuous character reconstructed with squared change parsimony, which depends on branch lengths.  The Dependent Tree Window shows a likelihood reconstruction for a categorical character.  Both reconstructions depend on branch lengths.^n^nYou can edit branch lengths by going to the tree with colored branches touching on a branch with the ruler tool (currently selected) and stretching  [...]
+				setTitle Branch_lengths;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/16c-TraceAllChars.nex b/Resources/examples/Ancestral_States/16c-TraceAllChars.nex
new file mode 100755
index 0000000..3f62785
--- /dev/null
+++ b/Resources/examples/Ancestral_States/16c-TraceAllChars.nex
@@ -0,0 +1,402 @@
+#NEXUS
+[written Wed Aug 26 11:51:27 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=19;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle striatum 
+	;
+	BLOCKID WM114899bc7f0134;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "16c-TraceAllChars.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  'absent-v._slight_mirrors' slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser [...]
+	MATRIX
+	balli             1010-00(1 2)1000011000000010(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1010-00(1 2)10(0 1)1011000000010(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       12(2 3)(0 1)-002000201000000(0 1)010(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         12(2 3)0-(0 1)02001001010000(0 1)0100001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1120-002000301000000101000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        123(0 2)000(1 2)000011100000001010030001020310120001-00-0000003021???????????????????????????
+	carinula          12(0 1 2)0-00210(0 1)101100000001030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             12(0 1 2)1-0021000011000000010(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        12(0 1 2 3)(0 2)000210(0 1)00110000000101013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  12(0 1 2)1-0001002010000110200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(1 2)3(0 2)0(0 1)(0 1 2)1000001100000(0 1)010(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1231-(0 1)0(0 1)0000011000001010(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          123(2 3)0(0 1)02101001100001(0 1)010(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1233010210(0 1)0011000010200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1233010210(0 1)0011000010200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1233(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0011000010200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1233(0 1)(0 1)02(0 1)0(0 1)000100000101000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1233(0 1)(0 1)02000000?00001(0 1)110(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	striatum          0010--0211-0011000000010(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+
+;
+		BLOCKID WM114899bc80c0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "16c-TraceAllChars.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 striatum;
+	TREE Untitled_Tree = (19,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18)))))));
+	TREE Untitled_Tree = (19,6,7,8,9,10,(1,2),(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+	TREE Untitled_Tree = (19,((1,2),((10,(9,(8,(6,7)))),((4,(3,5)),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,(15,16)))))))));
+	TREE Untitled_Tree = ((4,(3,5)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = ((5,(3,4)),(19,((1,2),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(15,(14,16)))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(13,(11,(12,(17,(18,(16,(14,15)))))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((17,18),(14,15,16))))))));
+	TREE Untitled_Tree = (19,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((1,2),(19,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))));
+	TREE Untitled_Tree = ((3,4,5),(19,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((6,(4,(3,5))),(19,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))));
+	TREE Untitled_Tree = ((19,(10,((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))),((4,(3,5)),(7,(6,(8,9)))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS DEFTYPE =                        unord PolyTcount =                        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN MacClade;
+	Version 4.0 81;
+	LastModified -1187776091;
+	FileSettings editor '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                         Geneva '9' '100' '1'                         all;
+	EditorPosition '46' '9' '451' '1011';
+	TreeWindowPosition '46' '6' '636' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '434'                         001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '278'                         100;
+	ListWindow Trees closed Geneva '9' '50' '10' '273' '386';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder Data List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                         00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                         10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                         110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                         1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                         0;
+	Charts Geneva '9' (                        normal )                         0010;
+	NexusOptions '0' '0' '50'                         001011011;
+	TipLabel '1';
+	TreeFont Geneva '9' (                        normal );
+	TreeShape 1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                         1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                         1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                         1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                         0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                         1;
+	PrintTree 10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                         Geneva '9' (                        normal )                         Geneva '10' (                        normal )                         Geneva '9' (                        normal )                         Geneva '9' (                        normal )                         Geneva '9' (                        bold )                         Geneva '9' (                        normal )                    [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                         00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                         100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                         1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114899bc7f0134;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114899bc80c0;
+			checksumv 0 2 238762464 WM114899bc80c0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 925 307;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 777 404;
+					setLocation 22 409;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 4;
+					setTree '(19,((1,2),((4,(3,5)),((10<selected = on >,(9<selected = on >,(8<selected = on >,(6<selected = on >,7<selected = on >)<selected = on >)<selected = on >)<selected = on >)<selected = on >,((11,12),(13:0.9269102643825389,(17,(18,(16,(14,15))))))))));';
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceAllCharacters.TraceAllCharacters;
+				tell It;
+					toggleByCharacters on;
+					toggleSelectedOnly on;
+					toggleSelectedCharsOnly off;
+					toggleShowTerminals off;
+					getCharSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+						tell It;
+							setDataSet #206796807167704052;
+						endTell;
+					endTell;
+					getReconstructor #mesquite.ancstates.AncestralStatesAll.AncestralStatesAll;
+					tell It;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					desuppress;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '17-TraceOverTrees.nex';
+			setPrevFileName '16b-BranchLengths.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 453 290;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				setExplanation 'Trace All Characters (available in the Analysis:Tree menu) summarizes ancestral states in many characters.  A text window shows a crude table listing states at different nodes for all the characters.^n^nBy default the table lists reconstructions only for those nodes selected in the tree, and for all selected characters.  You can adjust these options using items in the Trace_All menu of the Tree Window.  There you can also change the specifications of the reconstruction.';
+				setTitle Trace_All_Characters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual_page  'http://mesquiteproject.wikispaces.com/Ancestral+States#tac';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/17-TraceOverTrees.nex b/Resources/examples/Ancestral_States/17-TraceOverTrees.nex
new file mode 100755
index 0000000..c8f3803
--- /dev/null
+++ b/Resources/examples/Ancestral_States/17-TraceOverTrees.nex
@@ -0,0 +1,674 @@
+#NEXUS
+[written Sat Jun 07 10:13:55 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM114899cecdc135;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "17-TraceOverTrees.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114899ced0d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "17-TraceOverTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                                     unord PolyTcount =                                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "17-TraceOverTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE PAUP_1 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_2 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,(((14,15),16),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_3 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_4 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_5 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_6 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((((14,15),16),18),17)))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_7 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((14,(15,16)),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_8 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((14,15,16),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_9 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_10 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_11 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_12 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_13 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_14 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_15 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_16 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_17 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_18 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_19 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_20 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_21 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_22 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_23 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_24 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_25 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_26 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_27 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_28 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_29 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_30 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_31 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_32 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_33 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_34 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_35 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_36 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_37 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_38 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_39 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_40 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_41 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_42 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_43 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_44 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_45 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_46 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_47 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_48 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_49 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_50 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_51 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_52 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_53 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_54 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_55 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_56 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_57 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_58 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_59 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_60 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_61 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_62 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_63 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_64 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_65 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_66 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_67 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_68 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_69 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_70 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_71 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_72 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_73 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_74 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_75 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_76 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_77 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_78 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_79 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_80 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_81 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_82 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_83 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_84 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_85 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_86 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_87 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_88 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_89 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_90 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_91 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_92 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_93 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_94 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_95 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_96 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_97 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_98 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_99 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_100 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_101 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_102 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_103 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_104 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_105 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_106 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_107 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_108 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_109 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_110 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_111 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_112 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_113 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_114 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_115 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_116 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_117 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_118 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_119 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_120 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_121 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_122 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_123 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_124 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_125 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_126 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_127 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_128 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_129 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_130 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_131 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_132 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_133 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_134 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_135 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_136 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_137 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_138 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_139 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_140 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+
+END;
+
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                                      Geneva '9' '100' '1'                                      all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                                      001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                                      100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                                      00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                                      10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                                      110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                                      1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                                      0;
+	Charts  Geneva '9' (                                     normal )                                      0010;
+	NexusOptions '0' '0' '50'                                      001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                                     normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                                      1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                                      1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                                      1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                                      0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                                      1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                                      Geneva '9' (                                     normal )                                      Geneva '10' (                                     normal )                                      Geneva '9' (                                     normal )                                      Geneva '9' (                                     normal )                                      Geneva '9' ( [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                                      00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                                      100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                                      1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114899cecdc135;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114899ced0d0;
+			checksum 0 2915397944 WM114899ced0d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 399 490;
+			setLocation 12 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 620 639;
+					setLocation 437 33;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 5;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 654 1036;
+					toggleLegendFloat on;
+					setOrigin -96 -391;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 2;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 2;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX 96;
+					setInitialOffsetY -249;
+					setLegendWidth 142;
+					setLegendHeight 222;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '18-TraceOverResolutions.nex';
+			setPrevFileName '16c-TraceAllChars.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 327 473;
+					setLocation 12 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this tree window is shown the "Trace Over Trees" feature, available in the Analysis:Tree menu of a Tree Window.  This reconstructs ancestral states over a series of selected trees, and attempts to summarize them on a single tree.  Usually you would use this by first displaying some sort of consensus tree in the tree window, then selecting a series of trees from which the consensus was derived.  Trace over Trees does NOT calculate the consensus tree automatically, b [...]
+				setTitle Trace_over_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual_page  'http://mesquiteproject.wikispaces.com/Ancestral+States#tcot';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/17a-TraceOverTrees.nex b/Resources/examples/Ancestral_States/17a-TraceOverTrees.nex
new file mode 100644
index 0000000..74f1bdc
--- /dev/null
+++ b/Resources/examples/Ancestral_States/17a-TraceOverTrees.nex
@@ -0,0 +1,1339 @@
+#NEXUS
+[written Sat Jun 07 10:40:30 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Bembidion;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM11a641c6a1d1;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Bembidion_matrix;
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM11a641c6a720;
+
+
+END;
+BEGIN TREES;
+	Title Summary_trees;
+	LINK Taxa = Bembidion;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                                     unord PolyTcount =                                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN TREES;
+	Title Parsimonious_Trees;
+	LINK Taxa = Bembidion;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE PAUP_1 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_2 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,(((14,15),16),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_3 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_4 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_5 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_6 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((((14,15),16),18),17)))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_7 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((14,(15,16)),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_8 = (((((((((((((((((1,2),((((3,5),4),((11,12),(13,((14,15,16),(17,18))))),((((6,7),8),9),10))),32),(31,(33,(35,(36,37))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_9 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_10 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_11 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_12 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_13 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_14 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_15 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_16 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_17 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_18 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_19 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_20 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_21 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_22 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_23 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_24 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_25 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_26 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_27 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_28 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_29 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_30 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_31 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_32 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30)),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_33 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_34 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_35 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_36 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_37 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_38 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_39 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_40 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_41 = (((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_42 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_43 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_44 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_45 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((31,33),(35,(36,37)))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_46 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_47 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_48 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_49 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_50 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_51 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((31,33),(35,(36,37)))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_52 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_53 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_54 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_55 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_56 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_57 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_58 = ((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_59 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_60 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_61 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_62 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_63 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_64 = (((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)),(38,((39,(41,(42,43))),40))),((44,45),(46,47))),(48,49)),(50,51)),52,53);
+	TREE PAUP_65 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_66 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_67 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_68 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_69 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_70 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_71 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_72 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_73 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_74 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(31,(33,(35,(36,37))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_75 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_76 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_77 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((31,33),(35,(36,37)))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_78 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_79 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_80 = ((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(((31,33),(35,(36,37))),32)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_81 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_82 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_83 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((31,33),(35,(36,37)))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_84 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_85 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_86 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_87 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_88 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_89 = (((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_90 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_91 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_92 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_93 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_94 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_95 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_96 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_97 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_98 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_99 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_100 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_101 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_102 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_103 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(35,(36,37))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_104 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_105 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_106 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_107 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_108 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_109 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_110 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_111 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(34,(35,(36,37)))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_112 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_113 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_114 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(34,(35,(36,37))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_115 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_116 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_117 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_118 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_119 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),(33,(35,(36,37)))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_120 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_121 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_122 = ((((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(35,(36,37))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_123 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_124 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_125 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(35,(36,37)))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_126 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_127 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_128 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),((32,(35,(36,37))),34)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_129 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_130 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_131 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),32),((33,(35,(36,37))),34)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_132 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_133 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_134 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_135 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_136 = (((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(33,(35,(36,37)))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_137 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_138 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_139 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,(33,(35,(36,37))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+	TREE PAUP_140 = ((((((((((((((((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(32,34,(35,(36,37)))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22),(((38,40),(41,(42,43))),39)),((48,49),(50,51))),(46,47)),45),44),52,53);
+
+END;
+
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN TREES;
+	Title 'Tree block 3 from "Bembidion.trees"';
+	LINK Taxa = Bembidion;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE island.1.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.8.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,(((14,15),16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((((14,15),16),18),17)))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,(15,16)),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,15,16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.12a.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.32.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.36.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.40.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.44.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.2 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.3 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.4 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.5 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.11 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.12 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.13 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.14 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.15 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.16 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.17 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.18 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.19 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.20 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.21 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.22 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.23 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.24 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.25 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.26 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.27 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.28 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.29 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.30 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.31 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.32 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.33 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.35 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.37 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.39 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.41 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.42 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.43 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.44 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.48.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.68.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.84.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.69 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.70 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.71 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.72 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.73 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.74 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.75 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.76 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.77 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.78 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.79 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.80 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.81 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.82 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.83 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.84 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.160.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.3 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.4 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.5 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.20 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.21 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.22 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.23 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.24 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.25 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.26 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.27 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.28 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.29 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.30 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.31 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.32 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.33 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.35 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.37 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.39 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.41 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.66 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.67 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.68 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.69 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.70 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.71 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.72 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.73 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.74 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.75 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.76 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.77 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.78 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.79 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.80 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.81 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.82 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.83 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.84 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.85 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.86 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.87 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.88 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.89 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.90 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.91 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.92 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.93 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.94 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.95 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.96 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.97 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.98 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.99 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.100 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.101 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.102 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.103 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.104 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.105 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.106 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.107 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.108 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.109 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.110 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.111 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.112 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.113 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.114 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.115 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.116 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.117 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.118 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.119 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.120 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.121 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.122 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.123 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.124 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.125 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.126 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.127 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.128 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.129 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.130 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.131 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.132 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.133 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.134 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.135 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.136 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.137 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.138 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.139 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.140 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.141 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.142 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.143 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.144 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.145 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.146 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.147 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.148 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.149 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.150 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.151 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.152 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.153 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.154 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.155 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.156 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.157 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.158 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.159 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.160 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                                      Geneva '9' '100' '1'                                      all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                                      001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                                      100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                                      00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                                      10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                                      110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                                      1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                                      0;
+	Charts  Geneva '9' (                                     normal )                                      0010;
+	NexusOptions '0' '0' '50'                                      001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                                     normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                                      1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                                      1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                                      1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                                      0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                                      1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                                      Geneva '9' (                                     normal )                                      Geneva '10' (                                     normal )                                      Geneva '9' (                                     normal )                                      Geneva '9' (                                     normal )                                      Geneva '9' ( [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                                      00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                                      100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                                      1010;
+	BothTools '1';
+
+END;
+BEGIN TREES;
+	Title 'Tree block 4 from "bemb.con"';
+	LINK Taxa = Bembidion;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE MajRule = (1,(2,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))),19,(20,21),22,23,((24,(28,29)),(((25,26),27),30)),(31,33),32,34,(35,(36,37)),((((38,40),(41,(42,43))),39),((((44,(52,53)),45),(46,47)),((48,49),(50,51)))))));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Bembidion TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM11a641c6a1d1;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM11a641c6a720;
+			checksum 0 2915397944 WM11a641c6a720;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 357;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1073 876;
+			setLocation 0 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 4;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 644 819;
+					setLocation 0 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 18;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 7;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 3;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX 4;
+					setInitialOffsetY -248;
+					setLegendWidth 239;
+					setLegendHeight 218;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '18-TraceOverResolutions.nex';
+			setPrevFileName '16c-TraceAllChars.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 351 859;
+					setLocation 0 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this tree window is shown the "Trace Over Trees" feature, available in the Analysis:Tree menu of a Tree Window.  This reconstructs ancestral states over a series of selected trees, and attempts to summarize them on a single tree.  Usually you would use this by first displaying some sort of consensus tree in the tree window, then selecting a series of trees from which the consensus was derived.  Trace over Trees does NOT calculate the consensus tree automatically, b [...]
+				setTitle Trace_over_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual_page  'http://mesquiteproject.wikispaces.com/Ancestral+States#tcot';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/18-TraceOverResolutions.nex b/Resources/examples/Ancestral_States/18-TraceOverResolutions.nex
new file mode 100755
index 0000000..e55f470
--- /dev/null
+++ b/Resources/examples/Ancestral_States/18-TraceOverResolutions.nex
@@ -0,0 +1,479 @@
+#NEXUS
+[written Sat Jun 07 10:40:41 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM114899d2596136;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "18-TraceOverResolutions.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114899d25c20;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "18-TraceOverResolutions.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                             unord PolyTcount =                             MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                              Geneva '9' '100' '1'                              all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                              001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                              100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                              00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                              10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                              110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                              1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                              0;
+	Charts  Geneva '9' (                             normal )                              0010;
+	NexusOptions '0' '0' '50'                              001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                             normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                              1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                              1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                              1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                              0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                              1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                              Geneva '9' (                             normal )                              Geneva '10' (                             normal )                              Geneva '9' (                             normal )                              Geneva '9' (                             normal )                              Geneva '9' (                             bold )                              Geneva  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                              00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                              100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                              1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM114899d2596136;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114899d25c20;
+			checksum 0 2915397944 WM114899d25c20;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 423 414;
+			setLocation 11 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4388395586715833634  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 553.1024349539831.1587552359099835858;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 682 636;
+					setLocation 451 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 4;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 654 1036;
+					toggleLegendFloat on;
+					setOrigin -17 -376;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #206796807167704052;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 2;
+					setTreeSource  #mesquite.treefarm.RandomModifTree.RandomModifTree;
+					tell It;
+						setTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 553.1024349539831.1587552359099835858;
+						endTell;
+						setSeed 1024467734012;
+						setModifier  #mesquite.treefarm.RandomResolve.RandomResolve;
+						tell It;
+							setProportion 0.0;
+						endTell;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX 22;
+					setInitialOffsetY -312;
+					setLegendWidth 142;
+					setLegendHeight 222;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '19-likelihoodTot.nex';
+			setPrevFileName '17-TraceOverTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 351 397;
+					setLocation 11 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The source of trees used for Trace over Trees can vary.  It might be a series of trees randomly modified from an existing tree by adding error to branch length; it might be a series of trees derived from a given tree by randomly resolving its polytomies.  The latter was used in this tree window; it summarizes reconstructions over 100 trees randomly resolved from this polytomous tree.^n';
+				setTitle Trace_over_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/19-likelihoodTot.nex b/Resources/examples/Ancestral_States/19-likelihoodTot.nex
new file mode 100755
index 0000000..62e9d03
--- /dev/null
+++ b/Resources/examples/Ancestral_States/19-likelihoodTot.nex
@@ -0,0 +1,400 @@
+#NEXUS
+[written Sat Jun 07 10:40:55 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=10;
+	TAXLABELS
+		A B C D E F G H I J 
+	;
+	BLOCKID WM114899d6675137;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "19-likelihoodTot.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  0
+	B  0
+	C  1
+	D  1
+	E  1
+	F  0
+	G  0
+	H  0
+	I  0
+	J  0
+
+;
+		BLOCKID WM114899d66950;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "19-likelihoodTot.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J;
+	TREE Tree_1 = (((((1:7.75,(2:6.75,(((5:3.0,3:3.0):0.25,4:3.25):0.5,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_2 = (((((1:7.75,(2:6.75,(((5:1.1413990732406842,3:1.1413990732406842):1.684915434733532,4:2.8263145079742165):0.9236854920257835,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_3 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,(4:1.875,6:1.875):1.875):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_4 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,6:3.75):3.0):1.0):1.0,(4:4.375,7:4.375):4.375):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3096529116964699576 WM114899d6675137;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5088788982642008211 WM114899d66950;
+			checksum 0 69473247 WM114899d66950;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 602 304;
+			setLocation 10 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3096529116964699576  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 550.1054705101351.7296501086209055721;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 617 422;
+					setLocation 17 403;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((((1:7.75,(2:6.75,((5:1.5,3:3.0):1.5,4:3.25,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5088788982642008211;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 1;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX -162;
+					setInitialOffsetY -263;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '20-likelihoodToT.nex';
+			setPrevFileName '18-TraceOverResolutions.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 530 287;
+					setLocation 10 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here are four trees with likelihood reconstructions of a character shown.  In the window with a single tree is the Trace Character Over Trees facility, summarizing these reconstructions.  ^n^nNote that the most recent common ancestor (MRCA) of E and C is shown as black in the Trace Over Trees image, because in each of the trees at left it is reconstructed with strong likelihood preference for state 1.  Hold the cursor over this node in the tree above; note the legend  [...]
+				setTitle 'Trace over trees: likelihood';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #3096529116964699576;
+			setNumColumns 1;
+			setNumRows 4;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				assignNumTrees 4;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+			tell It;
+				suspend ;
+				setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+				tell It;
+					toggleLabels off;
+					toggleGray off;
+				endTell;
+				setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+				tell It;
+					getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #5088788982642008211;
+						endTell;
+					endTell;
+					setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+					tell It;
+						setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+						getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+						tell It;
+							setReportMode Proportional_Likelihoods;
+							setRootMode Use_Root_State_Frequencies_as_Prior;
+							setDecision 2.0;
+							setUnderflowCheckFreq 2;
+						endTell;
+					endTell;
+				endTell;
+				setCharacter 1;
+				setMapping 1;
+				toggleShowLegend off;
+				toggleGray off;
+				toggleWeights on;
+				resume ;
+			endTell;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 475 640;
+				setLocation 669 33;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+				tell It;
+					setSpotDiameter 18;
+					setEdgeWidth 2;
+					orientUp;
+					useDiagonal;
+					toggleCosmic off;
+					getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle on;
+						toggleScale off;
+						toggleBroadScale off;
+						toggleCenter on;
+						toggleEven on;
+					endTell;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/20-likelihoodToT.nex b/Resources/examples/Ancestral_States/20-likelihoodToT.nex
new file mode 100755
index 0000000..2a6c092
--- /dev/null
+++ b/Resources/examples/Ancestral_States/20-likelihoodToT.nex
@@ -0,0 +1,422 @@
+#NEXUS
+[written Sat Jun 07 10:41:06 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=10;
+	TAXLABELS
+		A B C D E F G H I J 
+	;
+	BLOCKID WM114899ef45e142;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "20-likelihoodToT.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  0
+	B  0
+	C  1
+	D  1
+	E  1
+	F  0
+	G  0
+	H  0
+	I  0
+	J  0
+
+;
+		BLOCKID WM114899ef46c0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "20-likelihoodToT.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J;
+	TREE Tree_1 = (((((1:7.75,(2:6.75,(((5:3.0,3:3.0):0.25,4:3.25):0.5,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_2 = (((((1:7.75,(2:6.75,(((5:1.1413990732406842,3:1.1413990732406842):1.684915434733532,4:2.8263145079742165):0.9236854920257835,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_3 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,(4:1.875,6:1.875):1.875):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_4 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,6:3.75):3.0):1.0):1.0,(4:4.375,7:4.375):4.375):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3096529116964699576 WM114899ef45e142;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5088788982642008211 WM114899ef46c0;
+			checksum 0 69473247 WM114899ef46c0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 576 301;
+			setLocation 7 32;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3096529116964699576  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 500.1054703857709.1750868529321274114;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 543 545;
+					setLocation 627 38;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 2;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5088788982642008211;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 1   'Mk1 (est.)';
+							endTell;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 3;
+					setInitialOffsetY -178;
+					setLegendWidth 188;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #3096529116964699576  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 550.1054705101351.7296501086209055721;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 602 386;
+					setLocation 9 414;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((((1:7.75,(2:6.75,((5:1.5,3:3.0):1.5,4:3.25,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5088788982642008211;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 1;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX 3;
+					setInitialOffsetY -368;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '21-likelihoodTot.nex';
+			setPrevFileName '19-likelihoodTot.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 504 284;
+					setLocation 7 32;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Below is the same Trace over Trees as in the previous example.  At right is the tree on which there appears to be strong support for state 0 at the MRCA of ECDF.  Why didn''t this get counted in the Trace over Trees?  The reason is that the difference in likelihoods of states 0 and 1 isn''t large enough to be considered "significant".  Hold the cursor over the MRCA of ECDF in the tree at left. The relative likelihoods are 0.81 and 0.19.  However, in the window''s Trac [...]
+				setTitle 'Trace over trees: likelihood';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Ancestral_States/21-likelihoodTot.nex b/Resources/examples/Ancestral_States/21-likelihoodTot.nex
new file mode 100755
index 0000000..780f564
--- /dev/null
+++ b/Resources/examples/Ancestral_States/21-likelihoodTot.nex
@@ -0,0 +1,426 @@
+#NEXUS
+[written Sat Jun 07 10:41:16 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=10;
+	TAXLABELS
+		A B C D E F G H I J 
+	;
+	BLOCKID WM11489a05025145;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "21-likelihoodTot.nex"';
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  001
+	B  001
+	C  100
+	D  110
+	E  101
+	F  011
+	G  000
+	H  000
+	I  000
+	J  000
+
+;
+		BLOCKID WM11489a050470;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "21-likelihoodTot.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J;
+	TREE Tree_1 = (((((1:7.75,(2:6.75,(((5:3.0,3:3.0):0.25,4:3.25):0.5,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_2 = (((((1:7.75,(2:6.75,(((5:1.1413990732406842,3:1.1413990732406842):1.684915434733532,4:2.8263145079742165):0.9236854920257835,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_3 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,(4:1.875,6:1.875):1.875):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+	TREE Tree_4 = (((((1:7.75,(2:6.75,((5:1.1413990732406845,3:1.1413990732406845):2.6086009267593155,6:3.75):3.0):1.0):1.0,(4:4.375,7:4.375):4.375):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  3;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  3;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3096529116964699576 WM11489a05025145;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5088788982642008211 WM11489a050470;
+			checksum 0 1329282022 WM11489a050470;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 570 208;
+			setLocation 5 27;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3096529116964699576  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 550.1054705101351.7296501086209055721;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 648 498;
+					setLocation 613 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((((1:7.75,(2:6.75,((5:1.5,3:3.0):1.5,4:3.25,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5088788982642008211;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 1;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_All_Trees_with_State;
+					setInitialOffsetX 3;
+					setInitialOffsetY -388;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #3096529116964699576  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 983.1054828001311.5267897939385195433;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 594 435;
+					setLocation 6 318;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientRight;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((((1:7.75,(2:6.75,((5:1.5,3:3.0):1.5,4:3.25,6:3.75):3.0):1.0):1.0,7:8.75):1.0,10:9.75):1.0,9:10.75):1.0,8:11.75):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharOverTrees.TraceCharOverTrees;
+				tell It;
+					suppress ;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5088788982642008211;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.CurrentProbModels.CurrentProbModels;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Use_Root_State_Frequencies_as_Prior;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+					tell It;
+						setTreeBlock 1;
+						toggleUseWeights off;
+					endTell;
+					setNumTrees 100;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					toggleShowLegend on;
+					toggleShowNodeAbsent on;
+					toggleShowEquivocal on;
+					setMode Count_Trees_with_Uniquely_Best_States;
+					setInitialOffsetX 3;
+					setInitialOffsetY -399;
+					setLegendWidth 142;
+					setLegendHeight 190;
+					desuppress ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../Introduction.nex';
+			setPrevFileName '20-likelihoodTot.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 498 191;
+					setLocation 5 27;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Below is the same Trace over Trees as in the previous examples, with states counted at the nodes only if they appear as uniquely best supported states with one of the trees.  At right, the counting rule has changed (using the Calculate submenu under Trace_Over_Trees) to "Count All Trees with State".  With this, a state is counted once at a node if it appears among the equally best supported states at the node in a tree.  Thus, for instance, the root of the whole tree  [...]
+				setTitle 'Trace over trees: likelihood';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/01-basics.nex b/Resources/examples/Basic_Examples/basic_operation/01-basics.nex
new file mode 100755
index 0000000..5ae4b6b
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/01-basics.nex
@@ -0,0 +1,129 @@
+#NEXUS
+[written Sun May 04 14:32:29 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114861883b02;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-basics.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114861883d90;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-basics.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                        unord PolyTcount =                        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114861883b02;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114861883d90;
+			checksum 0 4129971366 WM114861883d90;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 420 31;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-standardMenus.nex';
+			setPrevFileName '../introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 420 31;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite has a few standard windows, such as the startup window, and the main Mesquite window (showing the Mesquite log, Project and Files, and Search results).  ^n^nThe Mesquite Log window shows you a log of what commands have been given, and it may display errors.  Also, you can use it to give commands if you have that mode selected in its Defaults submenu of the File menu.^n^nThe Projects and Files window shows the files that are currently open, and some of their m [...]
+				setTitle 'Windows, Log, and Projects';
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+				addFileLink 'Extra example: linking'  '13-blockOfTaxa.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/02-standardMenus.nex b/Resources/examples/Basic_Examples/basic_operation/02-standardMenus.nex
new file mode 100755
index 0000000..11125a4
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/02-standardMenus.nex
@@ -0,0 +1,129 @@
+#NEXUS
+[written Sun May 04 14:38:36 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148618b2783;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-standardMenus.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148618b2900;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-standardMenus.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                       unord PolyTcount =                       MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148618b2783;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148618b2900;
+			checksum 0 4129971366 WM1148618b2900;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 417 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-characterMatrices.nex';
+			setPrevFileName '01-basics.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 417 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite has several standard menus:^n^nFile - Making new files, open, saving, printing, and closing files, quitting.^n^nEdit - Copying, pasting, undoing, and some other basic features for editing.^n^nCharacters - Managing characters, character matrices, and associated information like assumptions about characters.^n^nTaxa&Trees - Managing trees and taxa, showing tree windows.^n^nAnalysis - Displaying charts for trees, taxa and characters, tracing characters, creating [...]
+				setTitle Standard_menus;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Menu_documentation  'http://mesquiteproject.wikispaces.com/Menus';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/03-characterMatrices.nex b/Resources/examples/Basic_Examples/basic_operation/03-characterMatrices.nex
new file mode 100755
index 0000000..bd82d14
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/03-characterMatrices.nex
@@ -0,0 +1,205 @@
+#NEXUS
+[written Sun May 04 14:38:14 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114861935156;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-characterMatrices.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114861935490;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-characterMatrices.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114861935156;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114861935490;
+			checksum 0 4129971366 WM114861935490;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1023 484;
+			setLocation 16 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 52;
+					setAnnotationSize 52;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 523 363;
+					setLocation 16 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-treeWindow.nex';
+			setPrevFileName '02-standardMenus.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 467;
+					setLocation 16 23;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This file shows the spreadsheet editor for character matrices.  At its left side is a tool palette with a selection tool (the arrow), an editing tool (the I-beam), and others. When you select a tool by touching its button, its explanation shows up in the explanation area at the bottom of the window.^n^nThe matrix editing window has a "Matrix" menu which controls many of its functions.  In it you can control appearance and operate utilities that alter the data.  You ca [...]
+				setTitle Character_matrix_editor;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink More_details_on_characters  '../characters/01-characters.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/04-treeWindow.nex b/Resources/examples/Basic_Examples/basic_operation/04-treeWindow.nex
new file mode 100755
index 0000000..e6230f2
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/04-treeWindow.nex
@@ -0,0 +1,227 @@
+#NEXUS
+[written Sun May 04 14:37:26 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486199fff7;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-treeWindow.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148619a00b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-treeWindow.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                           unord PolyTcount =                           MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486199fff7;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148619a00b0;
+			checksum 0 4129971366 WM1148619a00b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 368;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1002 478;
+			setLocation 21 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 534 389;
+					setLocation 21 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04a-windowTabs.nex';
+			setPrevFileName '03-characterMatrices.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 362 461;
+					setLocation 21 22;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This file shows the tree window in which trees can be viewed and edited.  At left is a tool palette, whose tools can be used for manipulating the tree.  There is also a control with blue arrows to scroll from one tree to another from the current source of trees.  ^n^nThe Tree Window has  a Tree menu in which you can control the trees appearance, and choose the source of trees.  There is also an Analysis:Tree menu from which you can initiate analyses with the tree.^n^n [...]
+				setTitle Tree_window;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Viewing_trees  '../tree_viewing/01-treeWindow.nex';
+				addFileLink Manipulating_trees  '../tree_manipulation/01-editingTrees.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/04a-windowTabs.nex b/Resources/examples/Basic_Examples/basic_operation/04a-windowTabs.nex
new file mode 100644
index 0000000..e5c5452
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/04a-windowTabs.nex
@@ -0,0 +1,320 @@
+#NEXUS
+[written Sun May 04 14:36:52 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486199fff7;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04a-windowTabs.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148619a00b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04a-windowTabs.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                            unord PolyTcount =                            MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486199fff7;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148619a00b0;
+			checksum 0 4129971366 WM1148619a00b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 747 464;
+			setLocation 500 34;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 647 397;
+					setLocation 500 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 647 375;
+					setLocation 500 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 647 397;
+					setLocation 500 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-windowModes.nex';
+			setPrevFileName '04-treeWindow.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 480 353;
+					setLocation 8 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This file shows how Mesquite''s functional windows are grouped as tabs within a single window of your operating system.  At right is a window showing a list of taxa (the List of Taxa window).  If you touch on the tabs along the top of the window, you can see a Tree Window, and a Character Matrix Editor.  ^n^nThis system of tabs represents a change from version 1 of Mesquite.  You can pop out a window to be independent by touching on the little circled arrow in the tab [...]
+				setTitle Window_Tabs;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				setEditorsVisible;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/05-windowModes.nex b/Resources/examples/Basic_Examples/basic_operation/05-windowModes.nex
new file mode 100755
index 0000000..4b8abc0
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/05-windowModes.nex
@@ -0,0 +1,486 @@
+#NEXUS
+[written Sun May 04 14:36:03 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114861a64c410;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-windowModes.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114861a64f80;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-windowModes.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                         unord PolyTcount =                         MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114861a64c410;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114861a64f80;
+			checksum 0 4129971366 WM114861a64f80;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 502 373;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 537 282;
+					setLocation 533 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 886.1053111291939.6488771259174774010;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 492 395;
+					setLocation 9 403;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					showPage 1;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.1053111292798.248682516746150818;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 487 225;
+					setLocation 529 400;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					showPage 2;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 930.1053111293428.7666447681000981525;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 485 265;
+					setLocation 706 505;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					showPage 3;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-helpMenu.nex';
+			setPrevFileName '04a-windowTabs.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 502 356;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Most windows have several modes for viewing, controlled by the View Mode submenu of the window''s Window menu.  The menu has 5 choices, "Graphics (Standard)", "Text", "Parameters", "Modules" and "Citations".  ^n^nThe four windows shown here are all tree windows, being show in each of four different modes.  The "Graphics" mode is the standard mode in which you''re likely to work.  The "Text" mode gives an alternative, text-based view of the window.  The "Parameters" mo [...]
+				setTitle Window_modes;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/06-helpMenu.nex b/Resources/examples/Basic_Examples/basic_operation/06-helpMenu.nex
new file mode 100644
index 0000000..15feb17
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/06-helpMenu.nex
@@ -0,0 +1,226 @@
+#NEXUS
+[written Sun May 04 14:35:42 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114861b8cfd11;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-helpMenu.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114861b8d080;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-helpMenu.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114861b8cfd11;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114861b8d080;
+			checksum 0 4129971366 WM114861b8d080;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1125 528;
+			setLocation 14 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 725 439;
+					setLocation 14 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-moreHelp.nex';
+			setPrevFileName '05-windowModes.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 511;
+					setLocation 14 22;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'An important first step in learning Mesquite is to discover where to find instructions and information.  Because Mesquite is modular, there are many challenges in providing documentation, since what options are available depend on what is installed.  Mesquite may also be confusing at times, since its interface changes with what is installed and what calculations are being done.  ^n^nTo overcome these challenges, there are various features designed to give you informat [...]
+				setTitle Help;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Page_on_learning_Mesquite  'http://mesquiteproject.wikispaces.com/Learning+how+to+use+Mesquite';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/07-moreHelp.nex b/Resources/examples/Basic_Examples/basic_operation/07-moreHelp.nex
new file mode 100644
index 0000000..984d865
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/07-moreHelp.nex
@@ -0,0 +1,226 @@
+#NEXUS
+[written Sun May 04 14:35:05 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11488f6e2f59;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-moreHelp.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11488f6e3000;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-moreHelp.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                        unord PolyTcount =                        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11488f6e2f59;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11488f6e3000;
+			checksum 0 4129971366 WM11488f6e3000;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1041 482;
+			setLocation 13 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 84;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 641 361;
+					setLocation 13 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-logFile.nex';
+			setPrevFileName '06-helpMenu.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 465;
+					setLocation 13 25;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'You can learn what different menu items and tools do by using several features:^n^n-- if you hold down the Shift key as you select a menu item, an explanation of the menu item will appear in the explanation area of the window associated with the menu (try this with menus of the Tree Window -- you can''t do it for this note, since this note has no explanation area)^n^n-- if you touch on a button for a tool in a tool palette, like the one at the left of the tree window, [...]
+				setTitle More_help;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Page_on_Learning_Mesquite  'http://mesquiteproject.wikispaces.com/Learning+how+to+use+Mesquite';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/08-logFile.nex b/Resources/examples/Basic_Examples/basic_operation/08-logFile.nex
new file mode 100755
index 0000000..fc42e47
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/08-logFile.nex
@@ -0,0 +1,136 @@
+#NEXUS
+[written Sun May 04 14:34:34 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486dc41c048;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-logFile.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11486dc41dd0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-logFile.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486dc41c048;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11486dc41dd0;
+			checksum 0 4129971366 WM11486dc41dd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 417 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-windowFonts.nex';
+			setPrevFileName '07-moreHelp.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 417 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite maintains a log file ("Mesquite log") automatically that records commands given.  You can see it by selecting the Mesquite Log menu item in the View menu.^n^nMesquite saves the current log file and the previous five log files automatically in the Mesquite_Support_Files on your hard disk.  If you wish to save a log file, you can copy it from that directory or rename it so that Mesquite won''t overwrite it.';
+				setTitle Log_file;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/09-windowFonts.nex b/Resources/examples/Basic_Examples/basic_operation/09-windowFonts.nex
new file mode 100644
index 0000000..eab40e0
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/09-windowFonts.nex
@@ -0,0 +1,209 @@
+#NEXUS
+[written Sun May 04 14:34:09 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486dc73da49;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "09-windowFonts.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11486dc73e00;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-windowFonts.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                               unord PolyTcount =                               MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486dc73da49;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11486dc73e00;
+			checksum 0 4129971366 WM11486dc73e00;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1042 503;
+			setLocation 15 27;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					getTable;
+					tell It;
+						rowNamesWidth 171;
+					endTell;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 542 446;
+					setLocation 15 27;
+					setFont SansSerif;
+					setFontSize 18;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-scripting.nex';
+			setPrevFileName '08-logFile.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 486;
+					setLocation 15 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'The font of a window may be changed by selecting the menu items in the Edit window.  This changes the font of many parts of a window, but not necessarily all.  For instance, the names of taxa in the Tree Window are controlled separately, via menu items in the Display menu.^n^nWindows may be printed using the menu items in the File menu.  ^n^nTo see the Mesquite documentation on windows, use the button below.';
+				setTitle Fonts_&_printing;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Window_Documentation  'http://mesquiteproject.wikispaces.com/Windows';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/10-scripting.nex b/Resources/examples/Basic_Examples/basic_operation/10-scripting.nex
new file mode 100644
index 0000000..6474a29
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/10-scripting.nex
@@ -0,0 +1,402 @@
+#NEXUS
+[written Sat Jun 07 10:41:41 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486dcec5052;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "10-scripting.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11486dcecad0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "10-scripting.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                     unord PolyTcount =                                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486dcec5052;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11486dcecad0;
+			checksum 0 4129971366 WM11486dcecad0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 550 36;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 908.983934835544.585850784873249678;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 316;
+					setLocation 552 515;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #974864624972105434;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -163;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1475.1040308559226.8020642082026213926;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 375;
+					setLocation 550 36;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #974864624972105434;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -163;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-newFile.nex';
+			setPrevFileName '09-windowFonts.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 531 514;
+					setLocation 7 45;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Mesquite is scriptable. Indeed, when you select menu items or hit buttons, your action is implemented by scripting: a little command script is sent from one object within Mesquite to another.  If you learn how to write scripts yourself you can create macros, but many users won''t need to write any scripts themselves.  Mesquite writes a lot of scripts itself, for instance in saving  files (open a saved file with a text editor and look at the Mesquite block) and  clonin [...]
+				setTitle Scripting;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Scripting_Documentation  'http://mesquiteproject.wikispaces.com/Scripts+%26+Macros';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/11-newFile.nex b/Resources/examples/Basic_Examples/basic_operation/11-newFile.nex
new file mode 100644
index 0000000..88cdac2
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/11-newFile.nex
@@ -0,0 +1,46 @@
+#NEXUS
+[written Sun May 04 14:33:30 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 9 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '12-fileFormats.nex';
+			setPrevFileName '10-scripting.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 9 26;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'When you create a new file using the New menu item in the  File menu, Mesquite offers the chance to create a new block of taxa to go in the file.  It does this under the assumption that analyses will probably depend on a block of taxa being available.  This particular file doesn''t have any blocks of taxa, because its purpose is only to give you this message!^n^nYou can also create a new block of taxa after you already have a file open.  Mesquite allows more than one  [...]
+				setTitle New_Files;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/12-fileFormats.nex b/Resources/examples/Basic_Examples/basic_operation/12-fileFormats.nex
new file mode 100644
index 0000000..ea5bba2
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/12-fileFormats.nex
@@ -0,0 +1,46 @@
+#NEXUS
+[written Sun May 04 14:33:25 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 10 27;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '13-blockOfTaxa.nex';
+			setPrevFileName '11-newFile.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 10 27;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'When Mesquite saves and reads files, its default file format currently is the NEXUS format (D. Maddison et al., Systematic Biology, 1997).  This is the format used if you choose the Save or Save As menu items.^n^nMesquite can import and export other formats as well.  If you choose the Export... menu item from the File menu, you are presented with a list of file formats that could be used to export some of the information in the file.  (Just what is in the list depends [...]
+				setTitle File_formats;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/13-blockOfTaxa.nex b/Resources/examples/Basic_Examples/basic_operation/13-blockOfTaxa.nex
new file mode 100755
index 0000000..f407877
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/13-blockOfTaxa.nex
@@ -0,0 +1,198 @@
+#NEXUS
+[written Sun May 04 14:33:10 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486f4fa7653;
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		linkFile '13-matrix.nex';
+		linkFile '13-trees.nex';
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2922513977941723938 WM11486f4fa7653;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2018120398716524197 WM11486f4fad20;
+			checksum 0 4129971366 WM11486f4fad20;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 970 482;
+			setLocation 28 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #2922513977941723938 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2922513977941723938;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 419 270;
+					setLocation 472 552;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTrees 0 #mesquite.lists.TreesList.TreesList;
+			tell It;
+				setTreeBlock 1;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.NumForTreeList.NumForTreeList;
+				tell It;
+					suppress;
+					setValueTask  #mesquite.trees.NumberOfTaxa.NumberOfTaxa;
+					desuppress;
+				endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 423 298;
+					setLocation 813 284;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2018120398716524197 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 470 425;
+					setLocation 28 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '14-included.nex';
+			setPrevFileName '12-fileFormats.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 465;
+					setLocation 28 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Some programs for evolutionary biology can incorporate information from other files on disk while you''re working on a main data file.  The secondary files are typically tree files, read in after you''ve already read in the main data file.  In Mesquite, you can similarly incorporate information from various files in a single analysis.  The secondary files can include taxa blocks, data matrices, trees, and other information.^n^nHere three separate files are linked toge [...]
+				setTitle Linking_files;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Projects_&_Files  'http://mesquiteproject.wikispaces.com/Files';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/13-matrix.nex b/Resources/examples/Basic_Examples/basic_operation/13-matrix.nex
new file mode 100755
index 0000000..28671d5
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/13-matrix.nex
@@ -0,0 +1,40 @@
+#NEXUS
+[written Sun May 04 14:33:10 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "13-matrix.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11486f4fad20;
+
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/13-trees.nex b/Resources/examples/Basic_Examples/basic_operation/13-trees.nex
new file mode 100755
index 0000000..d28ea05
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/13-trees.nex
@@ -0,0 +1,25 @@
+#NEXUS
+[written Sun May 04 14:33:10 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+BEGIN TREES;
+	Title 'Trees from "13-trees.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/14-included.nex b/Resources/examples/Basic_Examples/basic_operation/14-included.nex
new file mode 100755
index 0000000..126c596
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/14-included.nex
@@ -0,0 +1,254 @@
+#NEXUS
+[written Sun May 04 14:39:34 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11486f66e3f54;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "14-included.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11486f66e5a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "14-included.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2922513977941723938 WM11486f66e3f54;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2018120398716524197 WM11486f66e5a0;
+			checksum 0 4129971366 WM11486f66e5a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 298;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 753 466;
+			setLocation 18 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #2922513977941723938 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2922513977941723938;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 475 222;
+					setLocation 728 62;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTrees 0 #mesquite.lists.TreesList.TreesList;
+			tell It;
+				setTreeBlock 1;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.NumForTreeList.NumForTreeList;
+				tell It;
+					suppress;
+					setValueTask  #mesquite.trees.NumberOfTaxa.NumberOfTaxa;
+					desuppress;
+				endTell;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 355 409;
+					setLocation 18 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2018120398716524197 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 453 301;
+					setLocation 766 419;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15-annotations.nex';
+			setPrevFileName '13-blockOfTaxa.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 292 449;
+					setLocation 18 26;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This example is exactly the same as the last, except this time the information from the three separate files has all been included in a single file.^n^nThis can be done by the "Include" menu item in the File menu.  When you have a main data file open and choose to include another file, the information from the secondary file is brought directly into the main data file.  The secondary file is not linked to the first.  Thus, when you save the main data file, this new in [...]
+				setTitle Including_files;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/15-annotations.nex b/Resources/examples/Basic_Examples/basic_operation/15-annotations.nex
new file mode 100644
index 0000000..5e6e2af
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/15-annotations.nex
@@ -0,0 +1,225 @@
+#NEXUS
+[written Sun May 04 14:39:54 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		Fubonidia Snorolopa Quidnubia Zorabynyx 
+	;
+	BLOCKID WM11486f6fc0d55;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15-annotations.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 knobble /  flat dimpled, 2 gizmoid /  pointy spatulate, 3 zibinator_shape /  smooth edgy, 4 zibinator_setae /  single_sided double_sided ; 
+	MATRIX
+	Fubonidia  1001
+	Snorolopa  1011
+	Quidnubia  0100
+	Zorabynyx  0101
+
+;
+		BLOCKID WM11486f6fc1d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "15-annotations.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Fubonidia,
+		2 Snorolopa,
+		3 Quidnubia,
+		4 Zorabynyx;
+	TREE 'First Tree+' = (((1,3),2),4);
+	TREE 'Second Tree+' = ((2,1),(4,3));
+	TREE 'Third Tree+' = (1,((4,2),3));
+	TREE 'Polytomous+' = ((1,3),4,2);
+	TREE 'Partial tree+' = ((1,4),3);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT   TAXON = 1 CHARACTER = 1 TEXT = 'This striking dimple was first noticed by Snerp (1965)';
+
+	AN T = 1 C = 1  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3033 I = 'fubonidianImages/fubonidiaKnobble.gif' TF = (CM 'This is distinct dimple, unlike others among the fubonidians.  Quite pretty, actually.') TF = (R 'Snerp, 1965') L = (TEXT = distinct_dimple FONT = SanSerif COLOR = Blue SIZE = 14 x = -78 y = 24 fixedToImage = true pointerX = 105 pointerY = 157 showpointer = true width = 57  );
+
+	AN T = 2 C = 1  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3634 I = 'fubonidianImages/snorolopaKnobble.gif' TF = (CM A_rather_shallow_dimple) ;
+
+	AN T = 3 C = 1  AU = _ DM = 2007.8.20.22.48.46 ID = 0105b30eea3635 I = 'fubonidianImages/quidnubiaKnobble.gif' TF = (CM A_rather_shallow_dimple) ;
+
+	AN T = 4 C = 1  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3736 I = 'fubonidianImages/zorabynyxKnobble.gif' TF = (CM 'Although Spuff (1978) claimed a dimple was present in Zorabynyx, all subsequent authors have agreed on its absence.') ;
+
+	AN T = 1 C = 2  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3837 I = 'fubonidianImages/fubonidiaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 2 C = 2  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3838 I = 'fubonidianImages/snorolopaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 3 C = 2  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3939 I = 'fubonidianImages/quidnubiaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 4 C = 2  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3940 I = 'fubonidianImages/zorabynyxGizmoid.gif' TF = (CM ) ;
+
+	AN T = 1 C = 3  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3a41 I = 'fubonidianImages/fubonidiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 2 C = 3  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3b42 I = 'fubonidianImages/snorolopaZibinator.gif' TF = (CM ) ;
+
+	AN T = 3 C = 3  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3b43 I = 'fubonidianImages/quidnubiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 4 C = 3  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3c44 I = 'fubonidianImages/zorabynyxZibinator.gif' TF = (CM ) ;
+
+	AN T = 1 C = 4  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea3d45 I = 'fubonidianImages/fubonidiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 2 C = 4  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea6246 I = 'fubonidianImages/snorolopaZibinator.gif' TF = (CM ) ;
+
+	AN T = 3 C = 4  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea6747 I = 'fubonidianImages/quidnubiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 4 C = 4  AU = _ DM = 2005.8.13.20.36.3 ID = 0105b30eea6c48 I = 'fubonidianImages/zorabynyxZibinator.gif' TF = (CM ) ;
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  4;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                              unord PolyTcount =                              MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  4;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11486f6fc0d55;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11486f6fc1d0;
+			checksum 0 2110737444 WM11486f6fc1d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 999 464;
+			setLocation 459 28;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 40;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 899 387;
+					setLocation 459 28;
+					setFont SanSerif;
+					setFontSize 14;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel on;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16-webLinks.nex';
+			setPrevFileName '14-included.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 447 473;
+					setLocation 7 28;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Mesquite has two styles of annotations: simple footnotes and more complex annotations.  Footnotes to taxa, characters, cells of the matrix and character states can be assigned and viewed in the small white area the bottom of the Character Matrix Editor, the List windows, and the State Names Editor for categorical data.  For instance, in the matrix above the cell for character "knobble" in the taxon Fubonidia has a footnote, as indicated by the * in the cell of the mat [...]
+				setTitle Annotations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/16-webLinks.nex b/Resources/examples/Basic_Examples/basic_operation/16-webLinks.nex
new file mode 100755
index 0000000..d745514
--- /dev/null
+++ b/Resources/examples/Basic_Examples/basic_operation/16-webLinks.nex
@@ -0,0 +1,47 @@
+#NEXUS
+[written Sun May 04 14:41:24 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 9 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '15-annotations.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 9 25;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'The files that Mesquite reads can either be local, for instance on your hard drive, or at a URL on the internet.  You can read the latter using the "URL" item in the Open menu of the File menu.  For instance, if you touch the Go button below, you will be taken to a file on Mesquite''s website.^n^nOnce you touch on the "Go" button, you will not have a button to return to this file.';
+				setTitle Web_Links;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_Intro;
+				addFileLink Go_to_file_on_website  'http://mesquiteproject.org/mesquite/salticidae/salticidae.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaGizmoid.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaGizmoid.gif
new file mode 100755
index 0000000..44fab16
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaKnobble.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaKnobble.gif
new file mode 100755
index 0000000..3e94547
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaZibinator.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaZibinator.gif
new file mode 100755
index 0000000..26fc3d5
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/fubonidiaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaGizmoid.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaGizmoid.gif
new file mode 100755
index 0000000..06d3c96
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaKnobble.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaKnobble.gif
new file mode 100755
index 0000000..f1ef8e9
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaZibinator.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaZibinator.gif
new file mode 100755
index 0000000..1574a78
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/quidnubiaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaGizmoid.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaGizmoid.gif
new file mode 100755
index 0000000..b5e2ed9
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaKnobble.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaKnobble.gif
new file mode 100755
index 0000000..c94bf38
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaZibinator.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaZibinator.gif
new file mode 100755
index 0000000..67866ee
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/snorolopaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxGizmoid.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxGizmoid.gif
new file mode 100755
index 0000000..b745340
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxKnobble.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxKnobble.gif
new file mode 100755
index 0000000..e54314a
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxZibinator.gif b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxZibinator.gif
new file mode 100755
index 0000000..cf2ce5e
Binary files /dev/null and b/Resources/examples/Basic_Examples/basic_operation/fubonidianImages/zorabynyxZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/01-characters.nex b/Resources/examples/Basic_Examples/characters/01-characters.nex
new file mode 100755
index 0000000..9a5cd5c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/01-characters.nex
@@ -0,0 +1,403 @@
+#NEXUS
+[written Sat Jun 07 10:42:02 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148911925e35;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148911928b0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  16epq_sequence;
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Aus         AACATCTGGGAACCGTGCG
+
+	Fubonidia   C?CG--TGAGACCCGTCCG
+
+	Ibbinidibe  AAGATACGGGTACCGTCCG
+
+	Snorolopa   AACATACGGGAAGCGTCCG
+
+	Quidnubia   AAGGTACGGGAACCGTCCG
+
+	Suinon      AAAGTACGGGACCCGTGCG
+
+	Zorabynyx   AACGTACGGGAACCGTGCG
+
+	Huichoros   AAAGCACGGGAACCGTGCG
+
+	Jotinupa    AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM114891192a20;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM114891192bd0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-characters.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+	CODESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  universal:  1 -  19;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  unord:  1 -  19;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = 16epq_sequence)  =  'Mk1 (est.)':  1 -  19;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148911925e35;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148911928b0;
+			checksum 0 4129971366 WM1148911928b0;
+			setID 1 7634018259203763187 WM114891192a20;
+			checksum 1 1838322636 WM114891192a20;
+			setID 2 3243446279249302787 WM114891192bd0;
+			checksum 2 2830407910 WM114891192bd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 461 279;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 465 302;
+					setLocation 5 364;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+			showDataWindow #7634018259203763187 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 580 264;
+					setLocation 491 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #3243446279249302787 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 572 280;
+					setLocation 489 379;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-newMatrix.nex';
+			setPrevFileName '../introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 389 262;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite supports data matrices of various kinds, including molecular sequences, categorical phenotypic data, and continuous-valued measurements.^n^nHere are three data matrices in a single file. (Mesquite allows more than one matrix per file).^n^nThe windows shown are Character Matrix Editors, which can be opened via the Characters menu.  ';
+				setTitle Character_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/02-newMatrix.nex b/Resources/examples/Basic_Examples/characters/02-newMatrix.nex
new file mode 100755
index 0000000..0612601
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/02-newMatrix.nex
@@ -0,0 +1,84 @@
+#NEXUS
+[written Sat Jun 07 10:42:12 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489124ea136;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "02-newMatrix.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489124ea136;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-newMatrix.nex';
+			setPrevFileName '01-characters.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 447;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file has no character matrices.  To make a new, blank character matrix, go to the Characters menu and choose New Empty Matrix...  You will be presented with a dialog box allowing you to:^n^n-- set the name of the matrix (in Mesquite it''s a good idea to give informative names to your matrices, since you can have several in a single file)^n^n-- indicate how many characters the matrix is to start out with^n^n-- what type of matrix it will be.^n^nWhat types of matri [...]
+				setTitle Making_matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/03-newMatrix.nex b/Resources/examples/Basic_Examples/characters/03-newMatrix.nex
new file mode 100644
index 0000000..24763b1
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/03-newMatrix.nex
@@ -0,0 +1,92 @@
+#NEXUS
+[written Tue Aug 26 15:07:52 PDT 2014 by Mesquite  version 3.0 beta 3 (build 637) at Thrandina.local/192.168.1.64 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148912a19b37;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "03-newMatrix.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+[0] 		1 Aus,
+[1] 		2 Fubonidia,
+[2] 		3 Ibbinidibe,
+[3] 		4 Snorolopa,
+[4] 		5 Quidnubia,
+[5] 		6 Suinon,
+[6] 		7 Zorabynyx,
+[7] 		8 Huichoros,
+[8] 		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		timeSaved 1409090872737;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148912a19b37;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 492 464;
+			setLocation 2 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-characterLists.nex';
+			setPrevFileName '02-newMatrix.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 442;
+					setLocation 2 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Character matrices already filled with data can be created in various ways using the "Make New Matrix from" submenu in the Characters menu.  The options in the submenu depend on what modules are installed, but there should be at least two options:^n^n-- Stored Matrices: This will make a new matrix that is initially a copy of an existing matrix.  You can edit the new copy without changing the original, and both will be stored in the file.^n^n-- Simulated Matrices on Cu [...]
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/04-characterLists.nex b/Resources/examples/Basic_Examples/characters/04-characterLists.nex
new file mode 100755
index 0000000..3262f49
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/04-characterLists.nex
@@ -0,0 +1,315 @@
+#NEXUS
+[written Sat Jun 07 10:42:55 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114891329f138;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114891329f70;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  16epq_sequence;
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Aus         AACATCTGGGAACCGTGCG
+
+	Fubonidia   C?CG--TGAGACCCGTCCG
+
+	Ibbinidibe  AAGATACGGGTACCGTCCG
+
+	Snorolopa   AACATACGGGAAGCGTCCG
+
+	Quidnubia   AAGGTACGGGAACCGTCCG
+
+	Suinon      AAAGTACGGGACCCGTGCG
+
+	Zorabynyx   AACGTACGGGAACCGTGCG
+
+	Huichoros   AAAGCACGGGAACCGTGCG
+
+	Jotinupa    AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM11489132a0b0;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM11489132a190;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-characterLists.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+	CODESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  universal:  1 -  19;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                       unord PolyTcount =                       MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  unord:  1 -  19;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+	EXSET * UNTITLED  (CHARACTERS = 16epq_sequence) = ;
+EXSET * UNTITLED  (CHARACTERS = Measurements) =  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = 16epq_sequence)  =  'Mk1 (est.)':  1 -  19;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114891329f138;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114891329f70;
+			checksum 0 4129971366 WM114891329f70;
+			setID 1 7634018259203763187 WM11489132a0b0;
+			checksum 1 1838322636 WM11489132a0b0;
+			setID 2 3243446279249302787 WM11489132a190;
+			checksum 2 2830407910 WM11489132a190;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 436 483;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showDatasList  #mesquite.lists.DatasetList.DatasetList;
+			tell It;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DatasetsListTaxa.DatasetsListTaxa;
+					newAssistant  #mesquite.lists.DatasetsListNumChars.DatasetsListNumChars;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 443 149;
+					setLocation 11 629;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+			showCharacters #974864624972105434 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 391 130;
+					setLocation 494 414;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showCharacters #3243446279249302787 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 2;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 438 173;
+					setLocation 496 667;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showCharacters #7634018259203763187 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 1;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 478 304;
+					setLocation 471 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-dataEditing.nex';
+			setPrevFileName '03-newMatrix.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 364 466;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The characters of a data matrix can be manipulated in Character Matrix Editors as in previous examples, or in Character List windows as here.  ^n^nEach of these windows summarizes information about each of the characters in a matrix.  There may be one or more columns.  In these examples, there are three columns: one indicating whether the character is currently included, a second showing the number of states or range of states, and a third indicating the assumption us [...]
+				setTitle Character_Lists;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/05-dataEditing.nex b/Resources/examples/Basic_Examples/characters/05-dataEditing.nex
new file mode 100644
index 0000000..c4bbd5e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/05-dataEditing.nex
@@ -0,0 +1,199 @@
+#NEXUS
+[written Sat Jun 07 10:43:44 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489146ef239;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-dataEditing.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489146f230;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-dataEditing.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                         unord PolyTcount =                         MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489146ef239;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489146f230;
+			checksum 0 4129971366 WM11489146f230;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 390 393;
+			setLocation 9 32;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 40;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 328;
+					setLocation 460 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-fill.nex';
+			setPrevFileName '04-characterLists.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 318 376;
+					setLocation 9 32;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Let''s look at a character matrix editor in more detail.  The editor shows taxa as rows, and characters as columns (currently, matrices can''t be transposed).^n^nAt left in the editor window is a tool palette.  The first tool, the arrow, allows you to select rows, columns, or cells of matrix.  By holding down the Shift key you can accumulate a larger selection.  Selecting is useful for copying and pasting, and using tools like the paint bucket, or menu items like thos [...]
+				setTitle Matrix_Editor;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/06-fill.nex b/Resources/examples/Basic_Examples/characters/06-fill.nex
new file mode 100755
index 0000000..f73a5e7
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/06-fill.nex
@@ -0,0 +1,200 @@
+#NEXUS
+[written Sat Jun 07 10:43:55 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114891496a240;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-fill.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114891496c90;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-fill.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                         unord PolyTcount =                         MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114891496a240;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114891496c90;
+			checksum 0 4129971366 WM114891496c90;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 438 436;
+			setLocation 15 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 312;
+					setLocation 472 39;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.DataPainter.DataPainter.fill;
+					endTell;
+					setTool mesquite.charMatrices.DataPainter.DataPainter.fill;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-dataEditing.nex';
+			setPrevFileName '05-dataEditing.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 366 419;
+					setLocation 15 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The tool currently selected is the Fill tool (the paint bucket).  It changes the character state in cells that you touch.^n^nBefore you can fill states using the paint bucket, you need to fill the tool with a state.  You can do this either by touching on the button in the palette and holding down the mouse until a popup menu appears, or you can simply select the paint bucket and attempt to touch on the cell you want to change (a dialog box will appear requesting the s [...]
+				setTitle Fill_Tool;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/07-dataEditing.nex b/Resources/examples/Basic_Examples/characters/07-dataEditing.nex
new file mode 100755
index 0000000..f04508a
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/07-dataEditing.nex
@@ -0,0 +1,199 @@
+#NEXUS
+[written Sat Jun 07 10:44:01 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148914c3fa41;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-dataEditing.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148914c4230;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-dataEditing.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148914c3fa41;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148914c4230;
+			checksum 0 4129971366 WM1148914c4230;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 431 439;
+			setLocation 21 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 449 301;
+					setLocation 492 31;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-addDelete.nex';
+			setPrevFileName '06-fill.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 359 422;
+					setLocation 21 26;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'You can find other means to edit or study your data using items in the Utilities and the Alter/transform submenus of the Matrix menu of the character matrix editor.  Just what appears in those submenus depends on what modules are installed and what type of data matrix is being shown.^n^nThe items in the Alter/Transform submenu often work on just those cells of the matrix that are selected. Thus, you can select a series of cells and apply one of the transformations to  [...]
+				setTitle Editing_utilities;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/08-addDelete.nex b/Resources/examples/Basic_Examples/characters/08-addDelete.nex
new file mode 100755
index 0000000..58fee57
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/08-addDelete.nex
@@ -0,0 +1,200 @@
+#NEXUS
+[written Sat Jun 07 10:44:08 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489150db942;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-addDelete.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489150dca0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-addDelete.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                        unord PolyTcount =                        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489150db942;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489150dca0;
+			checksum 0 4129971366 WM11489150dca0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 420 456;
+			setLocation 10 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 286;
+					setLocation 452 30;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.AddDeleteData.AddDeleteData.addChars;
+					endTell;
+					setTool mesquite.charMatrices.AddDeleteData.AddDeleteData.addChars;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-copyPaste.nex';
+			setPrevFileName '07-dataEditing.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 348 439;
+					setLocation 10 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Characters can be added to the end of an existing matrix by selecting Add Characters from the Matrix menu of the Character Matrix Editor window.  ^n^nIf you use the Add Characters tool (the one currently selected in the character matrix editor in this example), you can insert characters by touching on the column heading.  A dialog box will ask you how many characters to add; they will be added in front of the character touched.^n^nYou can delete characters by selectin [...]
+				setTitle Adding_characters_&_taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/09-copyPaste.nex b/Resources/examples/Basic_Examples/characters/09-copyPaste.nex
new file mode 100755
index 0000000..9bd18d3
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/09-copyPaste.nex
@@ -0,0 +1,294 @@
+#NEXUS
+[written Sat Jun 07 10:44:15 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148915906c43;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11?
+	Fubonidia   11?
+	Ibbinidibe  11?
+	Snorolopa   1(0 1)?
+	Quidnubia   00?
+	Suinon      00?
+	Zorabynyx   00?
+	Huichoros   00?
+	Jotinupa    00?
+
+;
+		BLOCKID WM114891590920;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Behavior;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2";
+	CHARSTATELABELS 
+		1 attitude /  friendly hostile dangerous ; 
+	MATRIX
+	Aus         0
+	Fubonidia   0
+	Ibbinidibe  0
+	Snorolopa   1
+	Quidnubia   2
+	Suinon      2
+	Zorabynyx   1
+	Huichoros   0
+	Jotinupa    0
+
+;
+		BLOCKID WM114891590c10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-copyPaste.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  3;
+	CODESET * UNTITLED  (CHARACTERS = Behavior)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  3;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  3;
+TYPESET * UNTITLED  (CHARACTERS = Behavior)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  3;
+ProbModelSet * UNTITLED  (CHARACTERS = Behavior)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148915906c43;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114891590920;
+			checksum 0 689268197 WM114891590920;
+			setID 1 7262648673951950406 WM114891590c10;
+			checksum 1 1391987657 WM114891590c10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 532 566;
+			setLocation 12 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 424 241;
+					setLocation 575 442;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+			showDataWindow #7262648673951950406 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 376 281;
+					setLocation 578 33;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-names.nex';
+			setPrevFileName '08-addDelete.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 460 549;
+					setLocation 12 26;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite allows copying and pasting of character data in an editor window like those to the right.  ^n^nIf you select all or a portion of the data matrix, and choose Copy from the Edit menu, then the data will be copied to the clipboard.  There are two ways to copy: a simple Copy that puts into the clipboard the underlying character state codes so that they can be pasted elsewhere in matrices, and a Copy Literal that copies the text in the table more exactly, for inst [...]
+				setTitle Copy_&_Paste;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/10-names.nex b/Resources/examples/Basic_Examples/characters/10-names.nex
new file mode 100644
index 0000000..ec6b7c6
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/10-names.nex
@@ -0,0 +1,245 @@
+#NEXUS
+[written Wed Aug 26 10:19:18 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148916ba1844;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "10-names.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148916ba1f0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "10-names.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                               unord PolyTcount =                               MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148916ba1844;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148916ba1f0;
+			tell It;
+				setSelected  1;
+				attachments ;
+			endTell;
+			checksumv 0 2 3673400160 WM1148916ba1f0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 469 496;
+			setLocation 10 26;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 751 267;
+					setLocation 523 27;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleThinRows off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+					getInfoPanel;
+					tell It;
+						btspOpen true;
+						apOpen true;
+						fpOpen true;
+					endTell;
+					toggleInfoPanel on;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesEditor.StateNamesEditor;
+				tell It;
+					makeWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 40;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 547 221;
+						setLocation 520 418;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+							setTool mesquite.categ.StateNamesEditor.StateNamesWindow.arrow;
+						endTell;
+						rowsAreCharacters on;
+						toggleConstrainChar on;
+						toggleConstrainCharNum 3;
+						togglePanel off;
+						toggleSummaryPanel off;
+					endTell;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-viewingStyles.nex';
+			setPrevFileName '09-copyPaste.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 397 479;
+					setLocation 10 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Characters can be assigned names, for instance by editing the column heading in the Character Matrix editor.  ^n^nIf the matrix is Categorical data, there is a State Names Editor (shown below) that is available by choosing Edit State Names in the Matrix menu of the Character Matrix editor window.  The State Names Editor shows characters on one axis, and states on the other.  You can choose whether characters are rows or columns by hitting the double arrow at the top l [...]
+				setTitle Character_&_state_names;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/11-viewingStyles.nex b/Resources/examples/Basic_Examples/characters/11-viewingStyles.nex
new file mode 100755
index 0000000..c52b37e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/11-viewingStyles.nex
@@ -0,0 +1,415 @@
+#NEXUS
+[written Sat Jun 07 10:44:47 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148919cac147;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148919cad60;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  16epq_sequence;
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Aus         AACATCTGGGAACCGTGCG
+
+	Fubonidia   C?CG--TGAGACCCGTCCG
+
+	Ibbinidibe  AAGATACGGGTACCGTCCG
+
+	Snorolopa   AACATACGGGAAGCGTCCG
+
+	Quidnubia   AAGGTACGGGAACCGTCCG
+
+	Suinon      AAAGTACGGGACCCGTGCG
+
+	Zorabynyx   AACGTACGGGAACCGTGCG
+
+	Huichoros   AAAGCACGGGAACCGTGCG
+
+	Jotinupa    AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM1148919cae50;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM1148919caf50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "11-viewingStyles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	SU  T = 4 C = 1 N = color I = 7;
+
+	TEXT   TAXON = 3 CHARACTER = 2 TEXT = 'At least, it looks red to me';
+
+	CHARACTERS = 16epq_sequence TAXA = Taxa;
+
+CODESET *  UNTITLED ( CHARACTERS =  Structure_&_Color ) =   universal :   1 -   2;
+CODESET *  UNTITLED ( CHARACTERS =  16epq_sequence ) =   universal :   1 -   19;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = 16epq_sequence)  =  'Mk1 (est.)':  1 -  19;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  unord:  1 -  19;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+	CODESET * UNTITLED  (CHARACTERS = 16epq_sequence)  =  universal:  1 -  19;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148919cac147;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148919cad60;
+			checksum 0 4129971366 WM1148919cad60;
+			setID 1 7634018259203763187 WM1148919cae50;
+			checksum 1 1838322636 WM1148919cae50;
+			setID 2 3243446279249302787 WM1148919caf50;
+			checksum 2 2830407910 WM1148919caf50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 512 350;
+			setLocation 10 28;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 330;
+					setLocation -7 463;
+					setFont Serif;
+					setFontSize 18;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByFootnote.ColorByFootnote;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Yellow;
+					removeColor off;
+				endTell;
+					setBackground Dark_Gray;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+			showDataWindow #7634018259203763187 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 330;
+					setLocation 555 485;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #3243446279249302787 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 330;
+					setLocation 561 42;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11a-annotations.nex';
+			setPrevFileName '10-names.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 440 333;
+					setLocation 10 28;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The Character Matrix editor has various options for display.  These example show:^n^n-- Cells can be colored in various ways using the Color Cells submenu of the Display menu.  For instance, they can be colored according to the character state, as shown in the sequence and continuous valued matrices, or they can be colored green if a footnote is present as shown in the categorical matrix. Colors can be assigned to cells manually using the paintbrush tool; these will b [...]
+				setTitle Editor_options;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/11a-annotations.nex b/Resources/examples/Basic_Examples/characters/11a-annotations.nex
new file mode 100644
index 0000000..94ac4ad
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/11a-annotations.nex
@@ -0,0 +1,229 @@
+#NEXUS
+[written Sat Jun 07 10:45:04 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		Fubonidia Snorolopa Quidnubia Zorabynyx 
+	;
+	BLOCKID WM114891af2ea48;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "11a-annotations.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 knobble /  flat dimpled, 2 gizmoid /  pointy spatulate, 3 zibinator_shape /  smooth edgy, 4 zibinator_setae /  single_sided double_sided ; 
+	MATRIX
+	Fubonidia  1001
+	Snorolopa  1011
+	Quidnubia  0100
+	Zorabynyx  0101
+
+;
+		BLOCKID WM114891af32d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "11a-annotations.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Fubonidia,
+		2 Snorolopa,
+		3 Quidnubia,
+		4 Zorabynyx;
+	TREE 'First Tree+' = (((1,3),2),4);
+	TREE 'Second Tree+' = ((2,1),(4,3));
+	TREE 'Third Tree+' = (1,((4,2),3));
+	TREE 'Polytomous+' = ((1,3),4,2);
+	TREE 'Partial tree+' = ((1,4),3);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT   TAXON = 1 CHARACTER = 1 TEXT = 'This striking dimple was first noticed by Snerp (1965)';
+
+	AN T = 1 C = 1  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83c381 I = 'fubonidianImages/fubonidiaKnobble.gif' TF = (CM 'This is a distinct dimple, unlike others among the fubonidians.  Quite pretty, actually.') TF = (R Illustration_from_specimen_AMNH_6788975) L = (TEXT = distinct_dimple FONT = SanSerif COLOR = Blue SIZE = 14 x = -78 y = 24 fixedToImage = true pointerX = 105 pointerY = 157 showpointer = true width = 57  );
+
+	AN T = 1 C = 1  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83c882 I = _ TF = (CM '"In contrast to other fubonidians, the nominal genus has a pronounced and distinct dimple on the upper surface of the knobble.  While we can only speculate on its function, I might note that only Fubonidia is found in high salt environments."') TF = (R Snerp_1965);
+
+	AN T = 2 C = 1  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83c8f3 I = 'fubonidianImages/snorolopaKnobble.gif' TF = (CM A_rather_shallow_dimple) ;
+
+	AN T = 3 C = 1  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83c984 I = 'fubonidianImages/quidnubiaKnobble.gif' TF = (CM Note_absence_of_dimple.) ;
+
+	AN T = 4 C = 1  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83ca15 I = 'fubonidianImages/zorabynyxKnobble.gif' TF = (CM 'Although Spuff (1978) claimed a dimple was present in Zorabynyx, all subsequent authors have agreed on its absence.') ;
+
+	AN T = 1 C = 2  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83caa6 I = 'fubonidianImages/fubonidiaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 2 C = 2  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cb37 I = 'fubonidianImages/snorolopaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 3 C = 2  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83ccc8 I = 'fubonidianImages/quidnubiaGizmoid.gif' TF = (CM ) ;
+
+	AN T = 4 C = 2  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cd49 I = 'fubonidianImages/zorabynyxGizmoid.gif' TF = (CM )  L = (TEXT = impressive! FONT = SanSerif COLOR = Red SIZE = 12 x = 49 y = 16 fixedToImage = true pointerX = 95 pointerY = 60 showpointer = false width = 100  );
+
+	AN T = 1 C = 3  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cde10 I = 'fubonidianImages/fubonidiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 2 C = 3  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83ce711 I = 'fubonidianImages/snorolopaZibinator.gif' TF = (CM ) ;
+
+	AN T = 3 C = 3  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cf012 I = 'fubonidianImages/quidnubiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 4 C = 3  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cf613 I = 'fubonidianImages/zorabynyxZibinator.gif' TF = (CM ) ;
+
+	AN T = 1 C = 4  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cf714 I = 'fubonidianImages/fubonidiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 2 C = 4  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cf915 I = 'fubonidianImages/snorolopaZibinator.gif' TF = (CM ) ;
+
+	AN T = 3 C = 4  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cfb16 I = 'fubonidianImages/quidnubiaZibinator.gif' TF = (CM ) ;
+
+	AN T = 4 C = 4  AU = _ DC = 2005.4.29.18.11.14 DM = 2005.4.29.18.11.14 ID = 010390a83cfc17 I = 'fubonidianImages/zorabynyxZibinator.gif' TF = (CM ) ;
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  4;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                  unord PolyTcount =                                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  4;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114891af2ea48;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114891af32d0;
+			checksum 0 2110737444 WM114891af32d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 392 587;
+			setLocation 18 34;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #974864624972105434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 40;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 942 383;
+					setLocation 430 28;
+					setFont SanSerif;
+					setFontSize 14;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel on;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '12-continuous.nex';
+			setPrevFileName '11-viewingStyles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 392 570;
+					setLocation 18 34;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Simple footnotes and more complex annotations can be used to illustrate a character matrix.  Footnotes to taxa, characters, cells of the matrix and character states can be assigned and viewed in the small white area the bottom of the Character Matrix Editor, the List windows, and the State Names Editor for categorical data.  For instance, in the matrix above the cell for character "knobble" in the taxon Fubonidia has a footnote, as indicated by the * in the cell of th [...]
+				setTitle Annotations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/12-continuous.nex b/Resources/examples/Basic_Examples/characters/12-continuous.nex
new file mode 100755
index 0000000..10e8c84
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/12-continuous.nex
@@ -0,0 +1,176 @@
+#NEXUS
+[written Sat Jun 07 10:45:24 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa Abnyora Syphorchus Lissaminopus Chaelodonter Chloroxyxops Mincinia Phoronibium 
+	;
+	BLOCKID WM114891b48ad49;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "12-continuous.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	Aus            9.367 5.022 2.763 38.57 1.723
+	Fubonidia      8.793 3.244 4.664 38.81 0.296
+	Ibbinidibe     8.576 6.245 2.528 38.5 -1.0239
+	Snorolopa      11.54 8.718 5.862 40.54 -2.039
+	Quidnubia      9.977 6.082 5.984 38.32 0.7256
+	Suinon         9.381 5.468 4.398 38.48 1.213
+	Zorabynyx      8.162 5.782 4.894 39.69 0.8212
+	Huichoros      8.676 4.86 4.186 39.61 0.5508
+	Jotinupa       9.356 6.75 4.649 38.01 0.795
+	Abnyora        8.107 5.989 2.975 40.13 -1.686
+	Syphorchus     9.692 7.227 5.747 39.52 -0.8719
+	Lissaminopus   8.902 6.05 4.337 37.5 -0.9571
+	Chaelodonter   9.055 6.575 4.896 40.48 -0.293
+	Chloroxyxops   10.11 4.199 3.327 38.94 -0.1349
+	Mincinia       10.2 3.975 4.623 37.1 -0.4575
+	Phoronibium    7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891b48d40;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Continuous data can be edited using a spreadsheet as at left.  To edit a cell, touch on it with the I-beam cursor and edit it.  If several cells (or a character, or a taxon) are selected, then you can use the items in the "Alter/Transform" submenu of the Matrix menu to alter or transform the data in those cells.  These items may or may not include:^n^nFill:  This fills the selected cells with a string typed by the user.^n^nRandom Fill (Gaussian): this fills the select [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 911995890865637530 WM114891b48ad49;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4132708679229515777 WM114891b48d40;
+			checksum 0 487214761 WM114891b48d40;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 464 455;
+			setLocation 11 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4132708679229515777 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 470 476;
+					setLocation 496 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '13-continuousItems.nex';
+			setPrevFileName '11a-annotations.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 392 438;
+					setLocation 11 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Continuous data can be edited using a spreadsheet as at left.  To edit a cell, touch on it with the I-beam tool and edit it.  If several cells (or a character, or a taxon) are selected, then you can use the items in the "Alter/Transform" submenu of the Matrix menu to alter or transform the data in those cells.  These items may or may not include:^n^nFill:  This fills the selected cells with a string typed by the user.^n^nRandom Fill (Gaussian): this fills the selected [...]
+				setTitle Continuous_data;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/13-continuousItems.nex b/Resources/examples/Basic_Examples/characters/13-continuousItems.nex
new file mode 100644
index 0000000..fffa461
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/13-continuousItems.nex
@@ -0,0 +1,156 @@
+#NEXUS
+[written Sat Jun 07 10:45:30 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		A B C 
+	;
+	BLOCKID WM114891b71e550;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "13-continuousItems.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (mean variance )  GAP = - MISSING = ?;
+	MATRIX
+	A   (0.0 1.1)
+	B   (1.0 2.2)
+	C   (2.0 3.3)
+
+;
+		BLOCKID WM114891b72140;
+
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1;
+TYPESET Current_Parsimony_Models   =  Linear:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4833122407699725302 WM114891b71e550;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6095372519071501230 WM114891b72140;
+			checksum 0 3701101314 WM114891b72140;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 478 454;
+			setLocation 25 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #6095372519071501230 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					getTable;
+					tell It;
+						rowNamesWidth 201;
+					endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 492 304;
+					setLocation 537 32;
+					setFont SanSerif;
+					setFontSize 14;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '14-partitions.nex';
+			setPrevFileName '12-continuous.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 406 437;
+					setLocation 25 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Continuous matrices in Mesquite are allowed to be three dimensional; that is, the matrix can be taxon X character X item, where the items might be mean, variance, sample size (for example).  If there is more than one item, each cell in the matrix would show more than one number.  ^n^nThis little file shows cells with two items each, a mean and a variance.  (The names of the items are shown toward the lower left of the data window).^n^nTo add, remove or rename items fr [...]
+				setTitle Items;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/14-partitions.nex b/Resources/examples/Basic_Examples/characters/14-partitions.nex
new file mode 100644
index 0000000..93d971e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/14-partitions.nex
@@ -0,0 +1,298 @@
+#NEXUS
+[written Sat Jun 07 10:45:39 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa Abnyora Syphorchus Lissaminopus Chaelodonter Chloroxyxops Mincinia Phoronibium 
+	;
+	BLOCKID WM114891babcf51;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "14-partitions.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	Aus            9.367 5.022 2.763 38.57 1.723
+	Fubonidia      8.793 3.244 4.664 38.81 0.296
+	Ibbinidibe     8.576 6.245 2.528 38.5 -1.0239
+	Snorolopa      11.54 8.718 5.862 40.54 -2.039
+	Quidnubia      9.977 6.082 5.984 38.32 0.7256
+	Suinon         9.381 5.468 4.398 38.48 1.213
+	Zorabynyx      8.162 5.782 4.894 39.69 0.8212
+	Huichoros      8.676 4.86 4.186 39.61 0.5508
+	Jotinupa       9.356 6.75 4.649 38.01 0.795
+	Abnyora        8.107 5.989 2.975 40.13 -1.686
+	Syphorchus     9.692 7.227 5.747 39.52 -0.8719
+	Lissaminopus   8.902 6.05 4.337 37.5 -0.9571
+	Chaelodonter   9.055 6.575 4.896 40.48 -0.293
+	Chloroxyxops   10.11 4.199 3.327 38.94 -0.1349
+	Mincinia       10.2 3.975 4.623 37.1 -0.4575
+	Phoronibium    7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891babdd0;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Just as with taxa, characters can be partitioned into assigned groups.  Thus, in this example, the first two characters are placed in the group "Morphology", while the second two characters are placed in the group "Physiology & Behavior".  Partitioning is useful for display (e.g., in these examples colors are associated with the groups).  In the future it will become more important as various modules perform analyses that compare results from characters belonging in d [...]
+
+END;
+
+BEGIN LABELS;
+	CHARGROUPLABEL Morphology COLOR = (RGB 0.45882353 0.13725490 1.0) ;
+	CHARGROUPLABEL Physiology_&_Behavior COLOR = (RGB 0.74901961 1.0 0.03137255) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARPARTITION * UNTITLED  =  Morphology :  1 -  2, Physiology_&_Behavior :  3 -  5;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 911995890865637530 WM114891babcf51;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4132708679229515777 WM114891babdd0;
+			checksum 0 487214761 WM114891babdd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 485 363;
+			setLocation 0 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4132708679229515777 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 532 446;
+					setLocation 546 360;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showCharacters #4132708679229515777 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					newAssistant  #mesquite.lists.CharListPartition.CharListPartition;
+					getTable;
+					tell It;
+						columnWidth 1 102;
+						columnWidth 3 150;
+					endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 596 206;
+					setLocation 535 38;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #4132708679229515777;
+				endTell;
+			endTell;
+			setTaxa #911995890865637530;
+			axesDifferent;
+			setValuesX  #mesquite.trees.NumForCharOnTree.NumForCharOnTree;
+			tell It;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 10.0;
+					endTell;
+					setSeed 1053123227719;
+				endTell;
+				setTreeNumber 0;
+				getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight on;
+					endTell;
+				endTell;
+			endTell;
+			setValuesY  #mesquite.cont.MeanValue.MeanValue;
+			tell It;
+				setItem 0;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 1;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 512 343;
+					setLocation 17 463;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15-selecting.nex';
+			setPrevFileName '13-continuousItems.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 413 346;
+					setLocation 0 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Just as with taxa, characters can be partitioned into assigned groups.  Thus, in this example, the first two characters are placed in the group "Morphology", while the second two characters are placed in the group "Physiology & Behavior".  Partitioning is useful for display (e.g., in these examples colors are associated with the groups).  In the future it will become more important as various modules perform analyses that compare results from characters belonging in d [...]
+				setTitle 'Character groups (partitions)';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/15-selecting.nex b/Resources/examples/Basic_Examples/characters/15-selecting.nex
new file mode 100755
index 0000000..bfa7133
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/15-selecting.nex
@@ -0,0 +1,306 @@
+#NEXUS
+[written Sat Jun 07 10:45:48 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa Abnyora Syphorchus Lissaminopus Chaelodonter Chloroxyxops Mincinia Phoronibium 
+	;
+	BLOCKID WM114891c644752;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "15-selecting.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	Aus            9.367 5.022 2.763 38.57 1.723
+	Fubonidia      8.793 3.244 4.664 38.81 0.296
+	Ibbinidibe     8.576 6.245 2.528 38.5 -1.0239
+	Snorolopa      11.54 8.718 5.862 40.54 -2.039
+	Quidnubia      9.977 6.082 5.984 38.32 0.7256
+	Suinon         9.381 5.468 4.398 38.48 1.213
+	Zorabynyx      8.162 5.782 4.894 39.69 0.8212
+	Huichoros      8.676 4.86 4.186 39.61 0.5508
+	Jotinupa       9.356 6.75 4.649 38.01 0.795
+	Abnyora        8.107 5.989 2.975 40.13 -1.686
+	Syphorchus     9.692 7.227 5.747 39.52 -0.8719
+	Lissaminopus   8.902 6.05 4.337 37.5 -0.9571
+	Chaelodonter   9.055 6.575 4.896 40.48 -0.293
+	Chloroxyxops   10.11 4.199 3.327 38.94 -0.1349
+	Mincinia       10.2 3.975 4.623 37.1 -0.4575
+	Phoronibium    7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891c64710;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'When a character is selected in a List of Characters window or in a Character Matrix Editor, it is not selected only in that window.  Rather, the character becomes selected throughout Mesquite.  Thus, if you select a character in the List window above by touching on a row number, it gets selected in the Character Matrix editor and the Scattergram chart as well.  Likewise, if you select a character in either the Character Matrix editor or the chart, the character is se [...]
+
+END;
+
+BEGIN LABELS;
+	CHARGROUPLABEL Morphology COLOR = (RGB 0.45882353 0.13725490 1.0) ;
+	CHARGROUPLABEL Physiology_&_Behavior COLOR = (RGB 0.74901961 1.0 0.03137255) ;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 911995890865637530 WM114891c644752;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4132708679229515777 WM114891c64710;
+			tell It;
+				setSelected  2;
+				attachments ;
+			endTell;
+			checksum 0 487214761 WM114891c64710;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 474 359;
+			setLocation 7 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4132708679229515777 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 529 411;
+					setLocation 507 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showCharacters #4132708679229515777 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.lists.CharacterStats.CharacterStats;
+				tell It;
+					toggleSelectedOnly off;
+				endTell;
+					newAssistant  #mesquite.parsimony.CharListParsModels.CharListParsModels;
+					newAssistant  #mesquite.lists.CharNumForList.CharNumForList;
+				tell It;
+					suppress;
+					setValueTask  #mesquite.cont.MeanValue.MeanValue;
+					tell It;
+						setItem 0;
+					endTell;
+					toggleShadeCells off;
+					desuppress;
+				endTell;
+					getTable;
+					tell It;
+						columnWidth 1 102;
+						columnWidth 3 130;
+					endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 593 202;
+					setLocation 511 587;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.lists.CharacterList.CharacterListWindow.wand;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #4132708679229515777;
+				endTell;
+			endTell;
+			setTaxa #911995890865637530;
+			axesDifferent;
+			setValuesX  #mesquite.trees.NumForCharOnTree.NumForCharOnTree;
+			tell It;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 100.0;
+					endTell;
+					setSeed 984005063645;
+				endTell;
+				setTreeNumber 0;
+				getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight on;
+					endTell;
+				endTell;
+			endTell;
+			setValuesY  #mesquite.cont.MeanValue.MeanValue;
+			tell It;
+				setItem 0;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 1;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 491 403;
+					setLocation 3 456;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16-charSources.nex';
+			setPrevFileName '14-partitions.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 402 342;
+					setLocation 7 25;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'When a character is selected in a List of Characters window or in a Character Matrix Editor, it is not selected only in that window.  Rather, the character becomes selected throughout Mesquite.  Thus, if you select a character in the List window above by touching on a row number, it gets selected in the Character Matrix editor and the Scattergram chart as well.  Likewise, if you select a character in either the Character Matrix editor or the chart, the character is se [...]
+				setTitle Selecting_characters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/16-charSources.nex b/Resources/examples/Basic_Examples/characters/16-charSources.nex
new file mode 100755
index 0000000..de9e2e0
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/16-charSources.nex
@@ -0,0 +1,263 @@
+#NEXUS
+[written Sat Jun 07 10:46:17 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa Abnyora Syphorchus Lissaminopus Chaelodonter Chloroxyxops Mincinia Phoronibium 
+	;
+	BLOCKID WM114891d2b5b53;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  measurements;
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	Aus            9.367 5.022 2.763 40.57 1.723
+	Fubonidia      8.793 3.244 4.664 38.81 0.296
+	Ibbinidibe     8.576 6.245 2.528 38.5 -1.0239
+	Snorolopa      11.54 8.718 5.862 37.54 -2.039
+	Quidnubia      9.977 6.082 5.984 38.32 0.7256
+	Suinon         9.381 5.468 4.398 39.48 1.213
+	Zorabynyx      8.162 5.782 4.894 39.69 0.8212
+	Huichoros      8.676 4.86 4.186 39.61 0.5508
+	Jotinupa       9.356 6.75 4.649 39.01 0.795
+	Abnyora        8.107 5.989 2.975 38.13 -0.0686
+	Syphorchus     9.692 7.227 5.747 39.52 -0.8719
+	Lissaminopus   8.902 6.05 4.337 37.5 -0.9571
+	Chaelodonter   9.055 6.575 4.896 40.48 1.1
+	Chloroxyxops   10.11 4.199 3.327 38.94 -0.1349
+	Mincinia       10.2 3.975 4.623 37.1 -0.4575
+	Phoronibium    7.604 5.438 2.809 37.09 -2.129
+
+;
+		BLOCKID WM114891d2b7e0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  More_measurements;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+	MATRIX
+	Aus            -0.44835771207670727 -0.3797290583888003 -0.8473437479546313
+	Fubonidia      1.8787474634121184 -1.6628411407927441 1.3305339069030753
+	Ibbinidibe     0.5960784267767305 -0.19626241735628674 2.120545092056362
+	Snorolopa      0.6376501422042263 -1.3339999769107858 -0.7374513502737137
+	Quidnubia      -0.7856631590858153 -0.2438980692080539 -0.06469390647661954
+	Suinon         -0.7979581461440539 1.8093435335289423 0.23749305816291386
+	Zorabynyx      1.958420391026524 -1.960140523438535 -0.41812351593109226
+	Huichoros      -0.04134351636816476 0.4570514137757342 -0.27091355283989355
+	Jotinupa       -0.6470454958089034 -0.6365393791704902 -0.7122495953512764
+	Abnyora        -0.5793819331826592 -0.23794091386454264 -0.47671347515466217
+	Syphorchus     0.38070937183553694 1.1168852079263176 0.4306475583795559
+	Lissaminopus   0.3341728298684051 -0.5380897066110796 0.11696665016772648
+	Chaelodonter   -0.8883060603845221 -1.6923548317466945 1.6261366769333483
+	Chloroxyxops   0.4241922926500759 -0.28244180611184677 0.3612897707209503
+	Mincinia       1.5009366517968572 0.21515106608395454 1.855329533875133
+	Phoronibium    0.28270802572170994 -0.908159396181896 -1.6021543652220862
+
+;
+		BLOCKID WM114891d2b9b0;
+
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Morphology COLOR = (RGB 0.45882353 0.13725490 1.0) ;
+	CHARGROUPLABEL Physiology_&_Behavior COLOR = (RGB 0.74901961 1.0 0.03137255) ;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = measurements)  =  Squared:  1 -  5;
+TYPESET * UNTITLED  (CHARACTERS = More_measurements)  =  Squared:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = measurements)  =  Brownian_default:  1 -  5;
+ProbModelSet * UNTITLED  (CHARACTERS = More_measurements)  =  Brownian_default:  1 -  3;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 911995890865637530 WM114891d2b5b53;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4132708679229515777 WM114891d2b7e0;
+			checksum 0 1628742248 WM114891d2b7e0;
+			setID 1 7825336589848395740 WM114891d2b9b0;
+			checksum 1 2246663599 WM114891d2b9b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 436 411;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4132708679229515777 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 462 415;
+					setLocation 479 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #911995890865637530;
+			endTell;
+			setTaxa #911995890865637530;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #4132708679229515777;
+					endTell;
+				endTell;
+				setCharacter 5;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 4;
+					setY 5;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 508 363;
+					setLocation 480 542;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '17-charSources.nex';
+			setPrevFileName '15-selecting.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 364 394;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The previous examples focused on character matrices that are stored in the file.  When you save the file to disk, these matrices will be saved in the file.  These "stored matrices" are indicated in List of Character Matrices (available in the Characters menu) and in the Project panel (at left of this window).^n^nStored matrices and their contained characters are used for calculations throughout Mesquite.  At right for example is a plot of the value in character 5 in a [...]
+				setTitle Stored_matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/17-charSources.nex b/Resources/examples/Basic_Examples/characters/17-charSources.nex
new file mode 100755
index 0000000..f2cc089
--- /dev/null
+++ b/Resources/examples/Basic_Examples/characters/17-charSources.nex
@@ -0,0 +1,287 @@
+#NEXUS
+[written Sat Jun 07 10:46:26 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa Abnyora Syphorchus Lissaminopus Chaelodonter Chloroxyxops Mincinia Phoronibium 
+	;
+	BLOCKID WM114891dc17a54;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "17-charSources.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	Aus            9.367 5.022 2.763 40.57 1.723
+	Fubonidia      8.793 3.244 4.664 38.81 0.296
+	Ibbinidibe     8.576 6.245 2.528 38.5 -1.0239
+	Snorolopa      11.54 8.718 5.862 37.54 -2.039
+	Quidnubia      9.977 6.082 5.984 38.32 0.7256
+	Suinon         9.381 5.468 4.398 39.48 1.213
+	Zorabynyx      8.162 5.782 4.894 39.69 0.8212
+	Huichoros      8.676 4.86 4.186 39.61 0.5508
+	Jotinupa       9.356 6.75 4.649 39.01 0.795
+	Abnyora        8.107 5.989 2.975 38.13 -0.0686
+	Syphorchus     9.692 7.227 5.747 39.52 -0.8719
+	Lissaminopus   8.902 6.05 4.337 37.5 -0.9571
+	Chaelodonter   9.055 6.575 4.896 40.48 1.1
+	Chloroxyxops   10.11 4.199 3.327 38.94 -0.1349
+	Mincinia       10.2 3.975 4.623 37.1 -0.4575
+	Phoronibium    7.604 5.438 2.809 37.09 -2.129
+
+;
+		BLOCKID WM114891dc1ae0;
+
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Morphology COLOR = (RGB 0.45882353 0.13725490 1.0) ;
+	CHARGROUPLABEL Physiology_&_Behavior COLOR = (RGB 0.74901961 1.0 0.03137255) ;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 911995890865637530 WM114891dc17a54;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4132708679229515777 WM114891dc1ae0;
+			checksum 0 1628742248 WM114891dc1ae0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 505 338;
+			setLocation 11 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #911995890865637530  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 100.0;
+					endTell;
+					setSeed 984368796031;
+				endTell;
+				setAssignedID 1878.984368778789.6090046772113142399;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 40;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 555 479;
+					setLocation 559 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.SelectTaxaInClade.SelectTaxaToolExtra.SelectTaxaInClade;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 12;
+						setEdgeWidth 3;
+						orientUp;
+						useDiagonal;
+						toggleCosmic off;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Red;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1:2.175015<selected = on >,(8:2.146535<selected = on >,9:2.146535<selected = on >):0.028476<selected = on >):14.560079<selected = on >,(((2:3.048454<selected = on >,(11:2.331105<selected = on >,14:2.331105<selected = on >):0.717349<selected = on >):2.713946<selected = on >,7:5.7624<selected = on >):7.0687699<selected = on >,(5:0.9452599<selected = on >,16:0.9452599<selected = on >):11.88591<selected = on >):3.903925<selected = on >):8.995177<selected = on >,(((3:1.567647 [...]
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #911995890865637530;
+			endTell;
+			setTaxa #911995890865637530;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+					tell It;
+						setSeed 984369049827;
+						setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+						tell It;
+							setModelByName Brownian_default;
+						endTell;
+						getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 1878.984368778789.6090046772113142399;
+						endTell;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 527 442;
+					setLocation 12 427;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '16-charSources.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 433 321;
+					setLocation 11 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Most of the previous examples concerned making, editing and using stored character matrices.  However, stored matrices aren''t the only matrices used in Mesquite''s calculations.  Most calculations using characters or matrices can use alternative sources of characters.  ^n^nFor example, here is a scattergram of taxa, with the Y and X axes being the values of two characters that are simulated on demand.  These characters are not stored in any matrix; they are simulated [...]
+				setTitle Character_sources;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaGizmoid.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaGizmoid.gif
new file mode 100755
index 0000000..44fab16
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaKnobble.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaKnobble.gif
new file mode 100755
index 0000000..3e94547
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaZibinator.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaZibinator.gif
new file mode 100755
index 0000000..26fc3d5
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/fubonidiaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaGizmoid.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaGizmoid.gif
new file mode 100755
index 0000000..06d3c96
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaKnobble.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaKnobble.gif
new file mode 100755
index 0000000..f1ef8e9
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaZibinator.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaZibinator.gif
new file mode 100755
index 0000000..1574a78
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/quidnubiaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaGizmoid.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaGizmoid.gif
new file mode 100755
index 0000000..b5e2ed9
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaKnobble.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaKnobble.gif
new file mode 100755
index 0000000..c94bf38
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaZibinator.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaZibinator.gif
new file mode 100755
index 0000000..67866ee
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/snorolopaZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxGizmoid.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxGizmoid.gif
new file mode 100755
index 0000000..b745340
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxGizmoid.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxKnobble.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxKnobble.gif
new file mode 100755
index 0000000..e54314a
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxKnobble.gif differ
diff --git a/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxZibinator.gif b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxZibinator.gif
new file mode 100755
index 0000000..cf2ce5e
Binary files /dev/null and b/Resources/examples/Basic_Examples/characters/fubonidianImages/zorabynyxZibinator.gif differ
diff --git a/Resources/examples/Basic_Examples/charts/01-charts.nex b/Resources/examples/Basic_Examples/charts/01-charts.nex
new file mode 100755
index 0000000..5b7460e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/charts/01-charts.nex
@@ -0,0 +1,307 @@
+#NEXUS
+[written Sat Jun 07 10:46:47 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114898249d0100;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114898249e60;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          2.434 45.96 0.0 20.0
+	Fubonidia    2.22 38.0 20.0 20.0
+	Ibbinidibe   2.04 84.0 40.0 7.0
+	Snorolopa    2.24 74.0 60.0 0.0
+	Quidnubia    2.74 26.0 80.0 17.4
+	Suinon       2.9 58.0 100.0 1.0
+	Zorabynyx    2.7800000000000002 54.0 120.0 4.0
+	Huichoros    2.16 70.0 140.0 0.0
+	Jotinupa     3.12 45.96 160.0 0.0
+
+;
+		BLOCKID WM11489824a040;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-charts.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	CHARACTERS = Measurements TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Fubonidiines :  1 -  3 5, Jotinupiines :  4 6 -  9;
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                             unord PolyTcount =                             MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114898249d0100;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114898249e60;
+			checksum 0 4129971366 WM114898249e60;
+			setID 1 1065345207404390442 WM11489824a040;
+			checksum 1 2480804147 WM11489824a040;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 409 418;
+			setLocation -2 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 509 345;
+					setLocation 447 472;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #8476784597994698209;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+				tell It;
+					setTime 100.0;
+				endTell;
+				setSeed 984014567088;
+			endTell;
+			setCalculator  #mesquite.parsimony.StepsInCharacter.StepsInCharacter;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 1;
+				getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight off;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 523 307;
+					setLocation 449 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 1000;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-histogram.nex';
+			setPrevFileName '../introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 337 401;
+					setLocation -2 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite currently has charts, including bar & line charts and scattergrams.  Bar & line charts summarize a value for each of several objects; scattergrams summarize two values for each of several objects.  The objects may be trees, taxa, characters, or character matrices.^n^nWhat values can be shown depend on what modules are installed in Mesquite.  Thus, if you want to show a histogram for trees, any module calculating a number for a tree can be used as a source of  [...]
+				setTitle Charts;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/charts/02-histogram.nex b/Resources/examples/Basic_Examples/charts/02-histogram.nex
new file mode 100755
index 0000000..48ce0c5
--- /dev/null
+++ b/Resources/examples/Basic_Examples/charts/02-histogram.nex
@@ -0,0 +1,252 @@
+#NEXUS
+[written Sat Jun 07 10:46:54 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148982e6f4101;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148982e70b0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          2.434 45.96 0.0 20.0
+	Fubonidia    2.22 38.0 20.0 20.0
+	Ibbinidibe   2.04 84.0 40.0 7.0
+	Snorolopa    2.24 74.0 60.0 0.0
+	Quidnubia    2.74 26.0 80.0 17.4
+	Suinon       2.9 58.0 100.0 1.0
+	Zorabynyx    2.7800000000000002 54.0 120.0 4.0
+	Huichoros    2.16 70.0 140.0 0.0
+	Jotinupa     3.12 45.96 160.0 0.0
+
+;
+		BLOCKID WM1148982e7190;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-histogram.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	CHARACTERS = Measurements TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Fubonidiines :  1 -  3 5, Jotinupiines :  4 6 -  9;
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                    unord PolyTcount =                                    MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148982e6f4101;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148982e70b0;
+			checksum 0 4129971366 WM1148982e70b0;
+			setID 1 1065345207404390442 WM1148982e7190;
+			checksum 1 2480804147 WM1148982e7190;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 435 439;
+			setLocation 4 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #8476784597994698209;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+				tell It;
+					setTime 100.0;
+				endTell;
+				setSeed 984014567088;
+			endTell;
+			setCalculator  #mesquite.parsimony.StepsInCharacter.StepsInCharacter;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 1;
+				getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight off;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 576 416;
+					setLocation 469 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 1000;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-scattergram.nex';
+			setPrevFileName '01-charts.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 363 422;
+					setLocation 4 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The histogram shown is controlled by Chart menu.  In this menu will be various items, depending on the chart shown, but included are:^n^n-- an Orientation submenu, in which you choose whether the histogram shows the items (e.g., trees) on the X axis in sequence versus their calculated values on the Y axis, or the values calculated on the Y axis versus the number of items with each value on the Y axis.^n^n-- a Grouping on X submenu, in which you choose whether the char [...]
+				setTitle Bar_&_Line_charts;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/charts/03-scattergram.nex b/Resources/examples/Basic_Examples/charts/03-scattergram.nex
new file mode 100755
index 0000000..b8bba92
--- /dev/null
+++ b/Resources/examples/Basic_Examples/charts/03-scattergram.nex
@@ -0,0 +1,297 @@
+#NEXUS
+[written Sat Jun 07 10:47:01 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148984a9e0104;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148984aa0a0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          2.434 45.96 0.0 20.0
+	Fubonidia    2.22 38.0 20.0 20.0
+	Ibbinidibe   2.04 84.0 40.0 7.0
+	Snorolopa    2.24 74.0 60.0 0.0
+	Quidnubia    2.74 26.0 80.0 17.4
+	Suinon       2.9 58.0 100.0 1.0
+	Zorabynyx    2.7800000000000002 54.0 120.0 4.0
+	Huichoros    2.16 70.0 140.0 0.0
+	Jotinupa     3.12 45.96 160.0 0.0
+
+;
+		BLOCKID WM1148984aa220;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-scattergram.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Taxa;
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Fubonidiines :  1 -  3 5, Jotinupiines :  4 6 -  9;
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                               unord PolyTcount =                               MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148984a9e0104;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148984aa0a0;
+			checksum 0 4129971366 WM1148984aa0a0;
+			setID 1 1065345207404390442 WM1148984aa220;
+			checksum 1 2480804147 WM1148984aa220;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 471 361;
+			setLocation 13 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1065345207404390442 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 495 247;
+					setLocation 10 475;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 490 442;
+					setLocation 512 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+						newAssistant  #mesquite.charts.ShowYEqualsX.ShowYEqualsX;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-scattergram.nex';
+			setPrevFileName '02-histogram.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 399 344;
+					setLocation 13 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Some of the scattergrams give you a choice of either showing the same type of value on both axes, or different types.  The former is useful if you want one axis to show the state in character 1, and the other axis to show the state in character 2 in the same matrix.  Both axes are showing states in characters, but they show it for different characters.  The latter is useful if you want to show completely different values, such as (for a Trees scattergram) the branch l [...]
+				setTitle Scattergrams;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/charts/04-scattergram.nex b/Resources/examples/Basic_Examples/charts/04-scattergram.nex
new file mode 100755
index 0000000..76f3891
--- /dev/null
+++ b/Resources/examples/Basic_Examples/charts/04-scattergram.nex
@@ -0,0 +1,567 @@
+#NEXUS
+[written Sat Jun 07 10:47:11 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489852dcc105;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489852de40;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          2.434 45.96 0.0 20.0
+	Fubonidia    2.22 38.0 20.0 20.0
+	Ibbinidibe   2.04 84.0 40.0 7.0
+	Snorolopa    2.24 74.0 60.0 0.0
+	Quidnubia    2.74 26.0 80.0 17.4
+	Suinon       2.9 58.0 100.0 1.0
+	Zorabynyx    2.7800000000000002 54.0 120.0 4.0
+	Huichoros    2.16 70.0 140.0 0.0
+	Jotinupa     3.12 45.96 160.0 0.0
+
+;
+		BLOCKID WM11489852dec0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-scattergram.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE Tree_1 = ((((1:2.75,(2:2.25,(3:2.0,5:2.0):0.25):0.5):1.0,4:3.75):1.0,(7:1.0,6:1.0):3.75):1.0,(9:1.0,8:1.0):4.75):1.0;
+	TREE Tree_2 = (((2:6.875,(9:5.75,5:5.75):1.125):1.5,(1:2.75,4:2.75):5.625):1.0,(3:3.375,((7:1.0,8:1.0):0.5,6:1.5):1.875):6.0):1.0;
+	TREE Tree_3 = (((2:6.875,5:6.875):5.875,((1:5.75,9:5.75):1.375,4:7.125):5.625):1.0,((3:1.6875,7:1.6875):1.6875,(8:1.5,6:1.5):1.875):10.375):1.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Taxa;
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                 unord PolyTcount =                                 MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489852dcc105;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489852de40;
+			checksum 0 4129971366 WM11489852de40;
+			setID 1 1065345207404390442 WM11489852dec0;
+			checksum 1 2480804147 WM11489852dec0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 486 311;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 272.984361350464.1689918410706365797;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 454 297;
+					setLocation 528 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 272.984361350464.1689918410706365799;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 463 291;
+					setLocation 623 198;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 2;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 272.984361350464.1689918410706365798;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 466 301;
+					setLocation 707 419;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 3;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+				tell It;
+					setSeed 984361558596;
+					setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+					tell It;
+						setModelByName Brownian_default;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 272.984361350464.1689918410706365797;
+					endTell;
+				endTell;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesDifferent;
+			setValuesX  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					tell It;
+						setDefaultModel 13;
+					endTell;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight on;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 272.984361350464.1689918410706365797;
+				endTell;
+			endTell;
+			setValuesY  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					tell It;
+						setDefaultModel 13;
+					endTell;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight on;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 272.984361350464.1689918410706365799;
+				endTell;
+			endTell;
+			showColors on;
+			setColorValues  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+					tell It;
+						setDefaultModel 13;
+					endTell;
+					getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+					tell It;
+						toggleWeight on;
+					endTell;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 272.984361350464.1689918410706365798;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 580 415;
+					setLocation 8 413;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+						newAssistant  #mesquite.charts.ShowYEqualsX.ShowYEqualsX;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '03-scattergram.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 414 294;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The scattergram may give you the option of coloring the spots to represent a third dimension, via the "Color by third value" menu item in the Colors menu of the scattergram (this menu is not always available).  ^n^nHere is a scattergram for 100 continuous-valued characters simulated by Brownian motion on the tree shown in the leftmost tree window.  Note that there are three tree windows.  The X axis of the scattergram shows the squared length of the character from a p [...]
+				setTitle Colored_scattergrams;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/01-editContinuous.nex b/Resources/examples/Basic_Examples/continuous/01-editContinuous.nex
new file mode 100755
index 0000000..5961fef
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/01-editContinuous.nex
@@ -0,0 +1,170 @@
+#NEXUS
+[written Sun May 04 15:10:29 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		A B C D E F G H I J K L M N O P 
+	;
+	BLOCKID WM114891ea28156;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-editContinuous.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	A   9.367 5.022 2.763 38.57 1.723
+	B   8.793 3.244 4.664 38.81 0.296
+	C   8.576 6.245 2.528 38.5 -1.0239
+	D   11.54 8.718 5.862 40.54 -2.039
+	E   9.977 6.082 5.984 38.32 0.7256
+	F   9.381 5.468 4.398 38.48 1.213
+	G   8.162 5.782 4.894 39.69 0.8212
+	H   8.676 4.86 4.186 39.61 0.5508
+	I   9.356 6.75 4.649 38.01 0.795
+	J   8.107 5.989 2.975 40.13 -1.686
+	K   9.692 7.227 5.747 39.52 -0.8719
+	L   8.902 6.05 4.337 37.5 -0.9571
+	M   9.055 6.575 4.896 40.48 -0.293
+	N   10.11 4.199 3.327 38.94 -0.1349
+	O   10.2 3.975 4.623 37.1 -0.4575
+	P   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891ea2940;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Mesquite can handle continuous data as well as categorical.  In the spreadsheet at left are 5 characters for 16 taxa.^n^nMore details about editing data matrices, including continuous-valued, in the introductory examples for characters.  In particular look at the file linked by the blue window.^n^nIn the following examples, some analyses of continuous valued data are shown.  The reader should keep in mind that other packages of modules with many more analyses have bee [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 156393696224404377 WM114891ea28156;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8888556603099012391 WM114891ea2940;
+			checksum 0 487214761 WM114891ea2940;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 343;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1098 500;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #8888556603099012391 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 655 443;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-trace.nex';
+			setPrevFileName '../introduction.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 337 483;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Mesquite can handle continuous data as well as categorical.  In the spreadsheet window shown here are 5 characters for 16 taxa.^n^nMore details about editing data matrices, including continuous-valued, are in the introductory examples for characters.  ^n^nIn the following examples, some analyses of continuous valued data are shown.  The reader should keep in mind that other packages of modules with many more analyses have been under development, including Rhetenor by  [...]
+				setTitle Continuous_data;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+				addFileLink Editing_matrices  '../characters/12-continuous.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/03-trace.nex b/Resources/examples/Basic_Examples/continuous/03-trace.nex
new file mode 100644
index 0000000..4afeeee
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/03-trace.nex
@@ -0,0 +1,359 @@
+#NEXUS
+[written Sun May 04 15:10:53 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114891f200a57;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-trace.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891f20190;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-trace.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:6.0,(11:5.0,(((7:1.0,12:1.0):1.0,15:2.0):2.0,(6:3.0,((8:1.0,14:1.0):1.0,(16:1.0,5:1.0):1.0):1.0):1.0):1.0):1.0):1.0,3:7.0):1.0,(13:4.0,(((4:1.0,10:1.0):1.0,9:2.0):1.0,2:3.0):1.0):4.0):1.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows a tree window in which you can edit and analyze trees.  The evolution of a character is reconstructed and traced using squared change parsimony.  There is also a legend showing the treelength summed over the characters in the matrix.^n^nUse the tools to edit the tree.  Note that the reconstruction and treelength are updated.  Also, edit the data matrix.  The reconstruction and treelength are updated as you make changes.^n';
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5221598931228393166 WM114891f200a57;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2482145747186088434 WM114891f20190;
+			checksum 0 3542125815 WM114891f20190;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 610 294;
+			setLocation 7 33;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5221598931228393166  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 533.967563158321.34715281069351178;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 585 442;
+					setLocation 633 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeLegendMaker.TreeLegendMaker;
+				tell It;
+					setOffsetsX 13;
+					setOffsetsY 295;
+					getLegendsVector;
+					tell It;
+					distributeCommands;
+						setBounds 13 295 137 39;
+						setOffsetX 13;
+						setOffsetY 295;
+					endDistributeCommands;
+					endTell;
+					newLegendItemNoCalc  #mesquite.parsimony.Treelength.Treelength;
+					tell It;
+						getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+						tell It;
+							getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #2482145747186088434;
+							endTell;
+						endTell;
+					endTell;
+					calculate;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #2482145747186088434;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -307;
+					setLegendWidth 142;
+					setLegendHeight 305;
+					resume ;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2482145747186088434 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 581 387;
+					setLocation 10 370;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-branchLengths.nex';
+			setPrevFileName '01-editContinuous.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 610 277;
+					setLocation 7 33;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a tree window in which you can edit and analyze trees.  The evolution of a character is reconstructed and traced using squared change parsimony.  There is also a legend showing the treelength summed over the characters in the matrix.^n^nUse the tools to edit the tree.  Note that the reconstruction and treelength are updated.  Also, edit the data matrix.  The reconstruction and treelength are updated as you make changes.^n';
+				setTitle Ancestral_states;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/04-branchLengths.nex b/Resources/examples/Basic_Examples/continuous/04-branchLengths.nex
new file mode 100755
index 0000000..429be1e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/04-branchLengths.nex
@@ -0,0 +1,363 @@
+#NEXUS
+[written Sun May 04 15:11:09 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114891f882458;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-branchLengths.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891f88520;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-branchLengths.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:23.83,(11:8.833,(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0,((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571):1.857,(13:16.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):2.5):5.5):2.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'The tree is drawn here to show branch lengths.  (The labels on each node are the reconstructed states.) Because squared-change parsimony uses branch lengths as weights, the reconstruction is sensitive to branch lengths.  If you change branch lengths, the reconstruction will change.  You can change the branch lengths using the Adjust Branch Length tool (the vertical ruler).^n';
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1597744227345086770 WM114891f882458;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5838355485285540067 WM114891f88520;
+			checksum 0 3542125815 WM114891f88520;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 485 210;
+			setLocation 7 33;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #1597744227345086770  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1397.970632252800.6902725252983283785;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 722 497;
+					setLocation 632 34;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 500 400;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeLegendMaker.TreeLegendMaker;
+				tell It;
+					setOffsetsX 65;
+					setOffsetsY 23;
+					getLegendsVector;
+					tell It;
+					distributeCommands;
+						setBounds 285 363 137 39;
+						setOffsetX 65;
+						setOffsetY 23;
+					endDistributeCommands;
+					endTell;
+					newLegendItemNoCalc  #mesquite.parsimony.Treelength.Treelength;
+					tell It;
+						getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+						tell It;
+							getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #5838355485285540067;
+							endTell;
+						endTell;
+					endTell;
+					calculate;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels on;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #5838355485285540067;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -322;
+					setLegendWidth 142;
+					setLegendHeight 305;
+					resume ;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5838355485285540067 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 557 375;
+					setLocation 9 311;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-treeSearch.nex';
+			setPrevFileName '03-trace.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 485 193;
+					setLocation 7 33;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The tree is drawn here to show branch lengths.  (The labels on each node are the reconstructed states.) Because squared-change parsimony uses branch lengths as weights, the reconstruction is sensitive to branch lengths.  If you change branch lengths, the reconstruction will change.  You can change the branch lengths using the Adjust Branch Length tool (the vertical ruler).^n';
+				setTitle Branch_lengths;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/05-treeSearch.nex b/Resources/examples/Basic_Examples/continuous/05-treeSearch.nex
new file mode 100755
index 0000000..9648f4e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/05-treeSearch.nex
@@ -0,0 +1,322 @@
+#NEXUS
+[written Sun May 04 15:13:30 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114891ff7d559;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-treeSearch.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114891ff8060;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-treeSearch.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE one_tree = ((((1,4),13),5),(11,(((3,10),9),(((6,14),15),((((7,12),16),8),2)))));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Reconstruction of phylogenetic trees has been dominated (in practice) by categorical data.  Mesquite allows other criteria for tree search, including parsimony searches using continuous valued data.^n^nMesquite has a general concept of "a number for a tree".  Examples could be the treelength, the number of steps in a character, the likelihood of the tree, its symmetry, and so on.  Each of these is a number that applies to the tree.  For any given number for a tree, on [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 9019647525474091584 WM114891ff7d559;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8548924366163732821 WM114891ff8060;
+			checksum 0 3542125815 WM114891ff8060;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 515 353;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #9019647525474091584  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 6039.975479485824.5658383844903825957;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 527 461;
+					setLocation 595 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground Green;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont Serif;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeLegendMaker.TreeLegendMaker;
+				tell It;
+					setOffsetsX 6;
+					setOffsetsY 294;
+					getLegendsVector;
+					tell It;
+					distributeCommands;
+						setBounds 6 294 137 39;
+						setOffsetX 6;
+						setOffsetY 294;
+					endDistributeCommands;
+					endTell;
+					newLegendItemNoCalc  #mesquite.parsimony.Treelength.Treelength;
+					tell It;
+						getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+						tell It;
+							getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #8548924366163732821;
+							endTell;
+						endTell;
+					endTell;
+					calculate;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #8548924366163732821 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 572 425;
+					setLocation 277 468;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-sim.nex';
+			setPrevFileName '04-branchLengths.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 515 336;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Reconstruction of phylogenetic trees has been dominated (in practice) by categorical data.  Mesquite allows other criteria for tree search, including parsimony searches using continuous valued data.^n^nMesquite has a general concept of "a number for a tree".  Examples could be the treelength, the number of steps in a character, the likelihood of the tree, its symmetry, and so on.  Each of these is a number that applies to the tree.  For any given number for a tree, on [...]
+				setTitle Tree_search;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/06-sim.nex b/Resources/examples/Basic_Examples/continuous/06-sim.nex
new file mode 100755
index 0000000..ece6898
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/06-sim.nex
@@ -0,0 +1,283 @@
+#NEXUS
+[written Sun May 04 15:14:25 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM1148920861360;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-sim.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114892086260;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-sim.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:23.83,(11:8.833,(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0,((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571):1.857,(13:16.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):2.5):5.5):2.0;
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel My_Brownian (Brownian) = 
+		rate 1.0;
+
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7557143514317563732 WM1148920861360;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6377312818483312110 WM114892086260;
+			checksum 0 3542125815 WM114892086260;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 250;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1060 597;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7557143514317563732  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 4656.968738959275.4595870811122188564;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 810 540;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1:5.83,(11:8.833,(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0,((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571):1.857,(13:6.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):4.5):7.5):2.0;';
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 500 400;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+							tell It;
+								setSeed 984410176631;
+								setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+								tell It;
+									setModelByName My_Brownian;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 4656.968738959275.4595870811122188564;
+								endTell;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							tell It;
+								setDefaultModel 13;
+							endTell;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -177;
+					setInitialOffsetY -330;
+					setLegendWidth 142;
+					setLegendHeight 305;
+					resume ;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-mirrorTree.nex';
+			setPrevFileName '05-treeSearch.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 244 580;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Characters for tracing and other purposes can come from simulations instead of data matrices.  Here, a character is simulated by Brownian motion evolution on the tree.  Scroll through other characters.  Note that the longer branches tend to show more change.^n^nYou can change branch lengths using the tool that looks like a vertical ruler, or by using the items in the "Branch lengths" submenu of the Tree menu of the tree window.  ^n^nYou can change the rate of the evol [...]
+				setTitle Simulations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/07-mirrorTree.nex b/Resources/examples/Basic_Examples/continuous/07-mirrorTree.nex
new file mode 100755
index 0000000..f0524f6
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/07-mirrorTree.nex
@@ -0,0 +1,371 @@
+#NEXUS
+[written Sun May 04 15:19:02 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114894ef89161;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-mirrorTree.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114894ef8ba0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-mirrorTree.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:23.83,(11:8.833,(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0,((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571):1.857,(13:16.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):2.5):5.5):2.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'To study correlation among characters, a Mirror Tree window can help in initial explorations.  The mirror tree window shows a tree reflected on left and right sides, to allow two character reconstructions to be compared.  The mirror tree window shows the characters length and width on left and right.  Scroll through other characters.^n^nThe tree in the mirror tree window is borrowed from the Tree Window at left.  If you edit the tree at left, the tree in the mirror tr [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 38907207727035647 WM114894ef89161;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4082975111581186249 WM114894ef8ba0;
+			checksum 0 3542125815 WM114894ef8ba0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 478;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1120 518;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #38907207727035647  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 301.967563409238.7947967923754259967;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 642 461;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile true;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 472 501;
+						setLocation 4 22;
+						setFont SanSerif;
+						setFontSize 10;
+						setActive;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #4082975111581186249;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 9;
+						setInitialOffsetY -307;
+						setLegendWidth 142;
+						setLegendHeight 305;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #4082975111581186249;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 2;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -142;
+						setInitialOffsetY -307;
+						setLegendWidth 142;
+						setLegendHeight 305;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-plotTree.nex';
+			setPrevFileName '06-sim.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 674 159;
+					setLocation -8 626;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'To study correlation among characters, a Mirror Tree window can help in initial explorations.  The mirror tree window shows a tree reflected on left and right sides, to allow two character reconstructions to be compared.  The mirror tree window shows the characters length and width on left and right.  Scroll through other characters.^n^nThe tree in the mirror tree window is borrowed from the Tree Window.  If you edit the tree in the Tree Window, the tree in the mirror [...]
+				setTitle Mirror_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/08-plotTree.nex b/Resources/examples/Basic_Examples/continuous/08-plotTree.nex
new file mode 100755
index 0000000..fe30642
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/08-plotTree.nex
@@ -0,0 +1,310 @@
+#NEXUS
+[written Sun May 04 15:19:19 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114894f8e2762;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-plotTree.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114894f8e530;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-plotTree.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:23.83,(11:8.833,(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0,((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571):1.857,(13:16.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):2.5):5.5):2.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'The relationships of different characters and phylogeny can be visualized by plotting a tree in a character space.  In the tree window at right, the terminal taxa are placed at their positions in a space of two characters.  The internal nodes are placed at the positions corresponding to their reconstructed ancestral states.  The internal nodes are slightly paler.^n^nBy using the two scrolls you can examine the tree plotted onto other characters.  You can edit the tree [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4132960006106429058 WM114894f8e2762;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 351059586327712100 WM114894f8e530;
+			checksum 0 3542125815 WM114894f8e530;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 542 300;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4132960006106429058  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2152.979145119595.5853167994523254131;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 554 558;
+					setLocation 594 52;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+					tell It;
+						setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+						tell It;
+							hide;
+							setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+							tell It;
+								getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+								tell It;
+									setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+									tell It;
+										setDataSet #351059586327712100;
+									endTell;
+								endTell;
+								setCharacter 2;
+								setItem 0;
+								getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+								tell It;
+									setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+									toggleMPRsMode off;
+									getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+									tell It;
+										toggleWeight on;
+									endTell;
+								endTell;
+							endTell;
+							toggleShowLegend on;
+							setInitialOffsetX -421;
+							setInitialOffsetY -156;
+							setCurrentX 1;
+							setCurrentY 2;
+							show;
+						endTell;
+						setSpotDiameter 12;
+						toggleShowTerminals on;
+						toggleShowInternals on;
+						toggleShowTree on;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #351059586327712100 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 555 228;
+					setLocation 16 389;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 66;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-plotTreeSim.nex';
+			setPrevFileName '07-mirrorTree.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 542 283;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The relationships of different characters and phylogeny can be visualized by plotting a tree in a character space.  In the tree window at right, the terminal taxa are placed at their positions in a space of two characters.  The internal nodes are placed at the positions corresponding to their reconstructed ancestral states.  The internal nodes are slightly paler.^n^nBy using the two scrolls you can examine the tree plotted onto other characters.  You can edit the tree [...]
+				setTitle Plot_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/continuous/09-plotTreeSim.nex b/Resources/examples/Basic_Examples/continuous/09-plotTreeSim.nex
new file mode 100755
index 0000000..283352e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/continuous/09-plotTreeSim.nex
@@ -0,0 +1,332 @@
+#NEXUS
+[written Sun May 04 15:19:51 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114894fd56a63;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "09-plotTreeSim.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 length,
+		2 width,
+		3 speed,
+		4 temperature,
+		5 personality ; 
+	MATRIX
+	taxon_0    9.367 5.022 2.763 38.57 1.723
+	taxon_1    8.793 3.244 4.664 38.81 0.296
+	taxon_2    8.576 6.245 2.528 38.5 -0.0239
+	taxon_3    11.54 8.718 5.862 40.54 -2.039
+	taxon_4    9.977 6.082 5.984 38.32 0.7256
+	taxon_5    9.381 5.468 4.398 38.48 1.213
+	taxon_6    8.162 5.782 4.894 39.69 0.8212
+	taxon_7    8.676 4.86 4.186 39.61 0.5508
+	taxon_8    9.356 6.75 4.649 38.01 0.795
+	taxon_9    8.107 5.989 2.975 40.13 -1.686
+	taxon_10   9.692 7.227 5.747 39.52 -0.8719
+	taxon_11   8.902 6.05 4.337 37.5 -0.9571
+	taxon_12   9.055 6.575 4.896 40.48 -0.293
+	taxon_13   10.11 4.199 3.327 38.94 -0.1349
+	taxon_14   10.2 3.975 4.623 37.1 -0.4575
+	taxon_15   7.604 5.438 2.809 37.69 -2.129
+
+;
+		BLOCKID WM114894fd5950;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-plotTreeSim.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE Phylogeny = (((1:23.83[%color = 6 ],(11:8.833[%color = 10 ],(((7:2.0[%color = 11 ],12:1.778[%color = 11 ]):1.857[%color = 11 ],15:1.857[%color = 11 ]):3.2,(6:9.0[%color = 14 ],((8:4.0[%color = 14 ],14:3.5[%color = 14 ]):4.0[%color = 14 ],(16:2.8[%color = 14 ],5:1.636[%color = 14 ]):3.25[%color = 14 ]):3.0[%color = 14 ]):8.0[%color = 0 ]):1.6):1.7):1.538,3:8.571[%color = 13 ]):1.857,(13:16.0[%color = 5 ],(((4:4.0[%color = 5 ],10:2.25[%color = 5 ]):2.0[%color = 5 ],9:2.143[%color = 5 [...]
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Above left is a tree; above right is the same tree plotted into a space of characters evolving by Brownian motion simulations on the tree itself.  The clades are colored to make them distinguishable.  Note that the long branches tend to show up as outliers in character space.^n^nYou can scroll from simulated character to character using the blue arrows in the Plot Tree legend.';
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+TYPESET Current_Parsimony_Models   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1742309196559577302 WM114894fd56a63;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8484372108263586382 WM114894fd5950;
+			checksum 0 3542125815 WM114894fd5950;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 524 244;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #1742309196559577302  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 464.967909619582.506440536801120907;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 554 405;
+					setLocation 614 39;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.stochchar.SimulatedCharacters.SimulatedCharacters;
+										tell It;
+											setSeed 984410506553;
+											setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+											tell It;
+												setModelByName Brownian_default;
+											endTell;
+											getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+											tell It;
+												setContextID 464.967909619582.506440536801120907;
+											endTell;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend on;
+								setInitialOffsetX -387;
+								setInitialOffsetY -156;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 554 465;
+						setLocation 17 345;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '08-plotTree.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 524 227;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here are two windows; one with a tree, and the other with the same tree plotted into a space of characters evolving by Brownian motion simulations on the tree itself.  The clades are colored to make them distinguishable.  Note that the long branches tend to show up as outliers in character space.^n^nYou can scroll from simulated character to character using the blue arrows in the Plot Tree legend.';
+				setTitle Simulations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/introduction.nex b/Resources/examples/Basic_Examples/introduction.nex
new file mode 100755
index 0000000..9f1404c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/introduction.nex
@@ -0,0 +1,69 @@
+#NEXUS
+[written Sun May 04 14:32:21 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 
+	;
+	BLOCKID WM114861837ad1;
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3143466173537330668 WM114861837ad1;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 16 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 16 25;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'Here are various Mesquite example files to introduce you to using Mesquite.  To navigate from one to another, use the buttons below.  ^nIf you''re new to Mesquite and want to learn what it can or might do, hit the "Show page" button in the blue-green panel.';
+				setTitle Introduction_to_Mesquite;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Introducing_the_basic_functioning_of_Mesquite  'basic_operation/01-basics.nex';
+				addFileLink Taxa_and_taxa_blocks  'taxa/01-taxa.nex';
+				addFileLink 'Character data: editing and analyzing.'  'characters/01-characters.nex';
+				addFileLink Examples_with_continuous_characters  'continuous/01-editContinuous.nex';
+				addFileLink Viewing_phylogenies_and_gene_trees  'tree_viewing/01-treeWindow.nex';
+				addFileLink Editing_and_manipulating_trees  'tree_manipulation/01-editingTrees.nex';
+				addFileLink Charts  'charts/01-charts.nex';
+				addWebLink Mesquite_Manual  'http://mesquiteproject.wikispaces.com';
+				addFileLink Return_to_main_introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/01-taxa.nex b/Resources/examples/Basic_Examples/taxa/01-taxa.nex
new file mode 100644
index 0000000..8d1a17a
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/01-taxa.nex
@@ -0,0 +1,166 @@
+#NEXUS
+[written Sun May 04 15:07:17 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11488fd3cf722;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-taxa.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11488fd3cff0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-taxa.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                            unord PolyTcount =                            MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11488fd3cf722;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11488fd3cff0;
+			checksum 0 4129971366 WM11488fd3cff0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 968 469;
+			setLocation 8 28;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 52;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 468 380;
+					setLocation 8 28;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-addingDeleting.nex';
+			setPrevFileName '../introduction.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 452;
+					setLocation 8 28;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Taxa (which may represent species or gene sequences) are usually the central entities analyzed by Mesquite.  For instance, character matrices and information about host-parasite associations both relate to taxa. While a block of taxa can exist without a character matrix, a character matrix cannot exist without the taxa to which it refers.  Thus, data files typically have a block of taxa even if they have nothing else.  When you ask Mesquite to create a new file, it as [...]
+				setTitle Taxa;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/02-addingDeleting.nex b/Resources/examples/Basic_Examples/taxa/02-addingDeleting.nex
new file mode 100755
index 0000000..3576509
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/02-addingDeleting.nex
@@ -0,0 +1,166 @@
+#NEXUS
+[written Sun May 04 15:07:37 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11488fdc25523;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-addingDeleting.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11488fdc25a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-addingDeleting.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11488fdc25523;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11488fdc25a0;
+			checksum 0 4129971366 WM11488fdc25a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 979 484;
+			setLocation 12 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 479 427;
+					setLocation 12 30;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-partitions.nex';
+			setPrevFileName '01-taxa.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 467;
+					setLocation 12 30;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'After you''ve created a taxa block you can add or delete taxa using either the List of Taxa window (shown at left), or using the Character Matrix Editor window.^n^nTo delete taxa, select them (by touching on the number to the left of the taxon name) and choose Delete selected Taxa from the List menu of the list window.^n^nTo add taxa to the end, choose Add Taxa from the List menu.  There is a tool in the Character Matrix editor that allows you to insert taxa between e [...]
+				setTitle Managing_taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/03-partitions.nex b/Resources/examples/Basic_Examples/taxa/03-partitions.nex
new file mode 100644
index 0000000..202046d
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/03-partitions.nex
@@ -0,0 +1,178 @@
+#NEXUS
+[written Sun May 04 15:07:58 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148906eec324;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-partitions.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148906eed10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-partitions.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41568627 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.84313725 0.33725490) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Fubonidiines :  1 -  3 5, Jotinupiines :  4 6 -  9;
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                           unord PolyTcount =                           MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148906eec324;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148906eed10;
+			checksum 0 4129971366 WM1148906eed10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1007 474;
+			setLocation 14 29;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 507 417;
+					setLocation 14 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-partitions.nex';
+			setPrevFileName '02-addingDeleting.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 394 457;
+					setLocation 14 29;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'The List window has a Columns menu, which allows you to add columns of information to the list.  In the window at upper left, the Group column is shown.  You can delete existing columns by selecting them (touch on the bar just above the name of the column) and choosing Hide Selected Columns from the List menu.^n^nGroups and taxa partitions are useful in various contexts.  A taxa partition assigns each taxon to a group; in this case the two groups are "Fubonidiines" an [...]
+				setTitle 'Taxa Groups (Partitions)';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/04-partitions.nex b/Resources/examples/Basic_Examples/taxa/04-partitions.nex
new file mode 100755
index 0000000..56c22b4
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/04-partitions.nex
@@ -0,0 +1,348 @@
+#NEXUS
+[written Sun May 04 15:08:09 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489072c7525;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489072c9b0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM11489072cb10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-partitions.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE A_Tree = (((7,6),((9,8),4)),(2,((1,5),3)));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Untitled_Block_of_Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Untitled_Block_of_Taxa;
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Fubonidiines :  1 -  3 5, Jotinupiines :  4 6 -  9;
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                           unord PolyTcount =                           MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489072c7525;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489072c9b0;
+			checksum 0 4129971366 WM11489072c9b0;
+			setID 1 1065345207404390442 WM11489072cb10;
+			checksum 1 2830407910 WM11489072cb10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 467;
+			setLocation 438 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 600 410;
+					setLocation 438 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 535.984012888567.5426059272482531248;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 600 410;
+					setLocation 438 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition off;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 543 419;
+					setLocation 17 324;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-selecting.nex';
+			setPrevFileName '03-partitions.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 424 245;
+					setLocation 11 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'When taxa are assigned to groups in a partition, as was shown in the last example file, any group colors will be used in other contexts.  Thus, the tree window highlights taxon names by the group color.  A scattergram of taxa colors the spots by their taxon''s group color. ';
+				setTitle Group_colors;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/05-selecting.nex b/Resources/examples/Basic_Examples/taxa/05-selecting.nex
new file mode 100755
index 0000000..ac47950
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/05-selecting.nex
@@ -0,0 +1,375 @@
+#NEXUS
+[written Sun May 04 15:08:40 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489080c6d26;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489080c980;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM11489080cac0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-selecting.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE A_Tree = (((7,6),((9,8),4)),(2,((1,5),3)));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Taxa;
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                unord PolyTcount =                                MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489080c6d26;
+			tell It;
+				setSelected  4;
+				attachments ;
+			endTell;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489080c980;
+			checksum 0 4129971366 WM11489080c980;
+			setID 1 1065345207404390442 WM11489080cac0;
+			checksum 1 2830407910 WM11489080cac0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 523 433;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 535.984012888567.5426059272482531248;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 511 366;
+					setLocation 5 401;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1065345207404390442 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 562 329;
+					setLocation 461 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 600 407;
+					setLocation 523 433;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-selecting.nex';
+			setPrevFileName '04-partitions.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 417 303;
+					setLocation 5 24;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'When taxa are selected in a Character Matrix editor (like that at right), the taxa are not selected merely in that window, but they become selected throughout Mesquite. Note that when this file opens, the taxon Snorolopa is selected in the tree,  matrix and scattergram.^n^nTry selecting a row in the matrix above by touching on the taxon number (to the left of its name); you will see the taxon is selected in the tree window and in the scattergram.^n^nThe Character Matr [...]
+				setTitle Selecting_taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/06-selecting.nex b/Resources/examples/Basic_Examples/taxa/06-selecting.nex
new file mode 100755
index 0000000..601f8d3
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/06-selecting.nex
@@ -0,0 +1,392 @@
+#NEXUS
+[written Sat Jun 07 10:47:42 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114890bf69c29;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114890bf6bd0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM114890bf6dd0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-selecting.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE A_Tree = (((7,6),((9,8),4)),(2,((1,5),3)));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Untitled_Block_of_Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Untitled_Block_of_Taxa;
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                  unord PolyTcount =                                  MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114890bf69c29;
+			tell It;
+				setSelected  1 -  3 5;
+				attachments ;
+			endTell;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114890bf6bd0;
+			checksum 0 4129971366 WM114890bf6bd0;
+			setID 1 1065345207404390442 WM114890bf6dd0;
+			checksum 1 2830407910 WM114890bf6dd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 517 29;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 535.984012888567.5426059272482531248;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 518 302;
+					setLocation -4 451;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.SelectTaxaInClade.SelectTaxaToolExtra.SelectTaxaInClade;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1065345207404390442 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 407;
+					setLocation 517 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 541 362;
+					setLocation 528 449;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-selecting.nex';
+			setPrevFileName '05-selecting.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 489 337;
+					setLocation 10 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Taxa can also be selected in the Tree Window using the Select Taxa tool or the Select Taxa in Clade tool.^n^nThe Select Taxa in Clade tool is that currently in use in the tree window at upper right (the tool looks like a white triangle with small black squares above it).  When you touch on a branch, all the taxa in that clade are selected.  If you hold down the Shift or Control keys, you can accumulate selections.  ^n^nThe Select Taxa tool looks like a black rectangle [...]
+				setTitle Selecting_Taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/07-selecting.nex b/Resources/examples/Basic_Examples/taxa/07-selecting.nex
new file mode 100755
index 0000000..8766dee
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/07-selecting.nex
@@ -0,0 +1,387 @@
+#NEXUS
+[written Sat Jun 07 10:48:02 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114890ece9431;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114890eceb10;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 toe_length,
+		2 slime_index,
+		3 puncture_density,
+		4 sneakiness ; 
+	MATRIX
+	Aus          0.1217 2.298 0.0 1.0
+	Fubonidia    0.111 1.9 1.0 1.0
+	Ibbinidibe   0.102 4.2 2.0 0.35
+	Snorolopa    0.112 3.7 3.0 0.0
+	Quidnubia    0.137 1.3 4.0 0.87
+	Suinon       0.145 2.9 5.0 0.05
+	Zorabynyx    0.139 2.7 6.0 0.2
+	Huichoros    0.108 3.5 7.0 0.0
+	Jotinupa     0.156 2.298 8.0 0.0
+
+;
+		BLOCKID WM114890ecec90;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-selecting.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE A_Tree = (((7,6),((9,8),4)),(2,((1,5),3)));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = Structure_&_Color TAXA = Taxa;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+	CHARACTERS = Measurements TAXA = Taxa;
+
+END;
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Fubonidiines COLOR = (RGB 0.03137255 0.41176471 1.0) ;
+	TAXAGROUPLABEL Jotinupiines COLOR = (RGB 1.0 0.83137255 0.33725490) ;
+
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                unord PolyTcount =                                MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114890ece9431;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114890eceb10;
+			checksum 0 4129971366 WM114890eceb10;
+			setID 1 1065345207404390442 WM114890ecec90;
+			checksum 1 2830407910 WM114890ecec90;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 100;
+			setPopoutState 349;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1051 478;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 535.984012888567.5426059272482531248;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 535 347;
+					setLocation 7 565;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1065345207404390442 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 531 253;
+					setLocation 554 563;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #8476784597994698209;
+			endTell;
+			setTaxa #8476784597994698209;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #1065345207404390442;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 602 421;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-multipleBlocks.nex';
+			setPrevFileName '06-selecting.nex';
+			getWindow;
+			tell It;
+					popAsTile true;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 343 461;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'You can also select taxa in the Taxa Scattergram.  With the arrow tool, touch on a spot, or click and drag to surround a series of spots with a rectangle.  Those spots will be selected.^n^n';
+				setTitle Selecting_Taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/taxa/08-multipleBlocks.nex b/Resources/examples/Basic_Examples/taxa/08-multipleBlocks.nex
new file mode 100755
index 0000000..189f98f
--- /dev/null
+++ b/Resources/examples/Basic_Examples/taxa/08-multipleBlocks.nex
@@ -0,0 +1,402 @@
+#NEXUS
+[written Sun May 04 15:09:34 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Fubonidians;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM11489100a4832;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Niconaceae;
+	DIMENSIONS NTAX=8;
+	TAXLABELS
+		Niconus Saraplisia Conotypinium Snariolus Phybunica Ytuna Lapicorea Salipunta 
+	;
+	BLOCKID WM11489100a6533;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-multipleBlocks.nex"';
+	LINK TAXA = Fubonidians;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM11489100a780;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees block 2 from 08-multipleBlocks.nex';
+	LINK Taxa = Fubonidians;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 08-multipleBlocks.nex';
+	LINK Taxa = Niconaceae;
+	TRANSLATE
+		1 Niconus,
+		2 Saraplisia,
+		3 Conotypinium,
+		4 Snariolus,
+		5 Phybunica,
+		6 Ytuna,
+		7 Lapicorea,
+		8 Salipunta;
+	TREE Smith_1998 = (1,(((2,5),3),((4,7),(6,8))));
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Fubonidians TAXON = 5 TEXT = Lives_deep_in_dark_caves;
+
+	CHARACTERS = 'Matrix in file "08-multipleBlocks.nex"' TAXA = Fubonidians;
+	TEXT   TAXON = 4 CHARACTER = 2 TEXT = 'Some individuals are blue, others are red.  Why, no one knows.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM11489100a4832;
+			setID 1 6050503871130632551 WM11489100a6533;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM11489100a780;
+			checksum 0 4129971366 WM11489100a780;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 449 358;
+			setLocation 4 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8476784597994698209 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8476784597994698209;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 315 316;
+					setLocation 442 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #6050503871130632551 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #6050503871130632551;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 365 225;
+					setLocation 13 455;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #8476784597994698209;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 679.984013351205.6490942559320754920;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 486 307;
+					setLocation 761 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #6050503871130632551  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #6050503871130632551;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 691.984013362206.425371040947643172;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 500 299;
+					setLocation 392 431;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '07-selecting.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 449 341;
+					setLocation 4 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Mesquite allows more than one block of taxa in a file.  Here is a file with two blocks of taxa, the Fubonidians, and the Noconaceae (these are both fictitious, but you can image the former to be herbivores that eat the latter).^n^nYou can create additional blocks of taxa by choosing New Block of Taxa from the Taxa&Trees menu.^n';
+				setTitle Multiple_taxa_blocks;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/01-editingTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/01-editingTrees.nex
new file mode 100755
index 0000000..a20760c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/01-editingTrees.nex
@@ -0,0 +1,239 @@
+#NEXUS
+[written Wed Aug 26 11:14:05 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895c843584;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-editingTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895c84590;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-editingTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895c843584;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895c84590;
+			checksumv 0 2 3673400160 WM114895c84590;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 491 489;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 432;
+					setLocation 516 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-editingTrees.nex';
+			setPrevFileName '../basic_operation/04-treeWindow.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 419 472;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'This file introduces tree manipulation.  It shows a tree window, currently showing a tree stored in the file (notice that the name of the tree appears just beneath the tree in a little bar).  At the left of the window is a tool palette containing tools by which you can modify the tree or its appearance.  ^n^nThe currently active tool is the simple Move Branch tool.  With it you can pick up and move branches in the tree, using the conventions originated by MacClade.  M [...]
+				setTitle Editing_trees;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/02-editingTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/02-editingTrees.nex
new file mode 100755
index 0000000..03b3419
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/02-editingTrees.nex
@@ -0,0 +1,230 @@
+#NEXUS
+[written Sat Jun 07 10:48:53 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895cc52a85;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-editingTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895cc5500;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-editingTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                unord PolyTcount =                MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895cc52a85;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895cc5500;
+			checksum 0 4129971366 WM114895cc5500;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 475 466;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 402;
+					setLocation 508 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.interchange;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-editingTrees.nex';
+			setPrevFileName '01-editingTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 403 449;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The currently selected tool is a branch interchange tool.  ^n^nAs you select a tool in the palette, the explanation area at the bottom of the window shows a detailed explanation of the tool.  Try selecting various tools to see their explanations.  Then, return to the branch exchange tool for use.^n^nThe branch interchange tool is used just as the Move Branch tool, in that you pick up a branch and drop it on another branch.  Its effect is to make the two branches trade [...]
+				setTitle Editing_tools;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/03-editingTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/03-editingTrees.nex
new file mode 100755
index 0000000..5063b43
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/03-editingTrees.nex
@@ -0,0 +1,230 @@
+#NEXUS
+[written Sat Jun 07 10:49:05 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895d1c6f86;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-editingTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895d1c8a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-editingTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895d1c6f86;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895d1c8a0;
+			checksum 0 4129971366 WM114895d1c8a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 447 451;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 409;
+					setLocation 477 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.collapse;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-branchLengths.nex';
+			setPrevFileName '02-editingTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 375 434;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The currently selected tool in the tool palette at left is a collapse branch tool.  It is usually used to collapse a branch to create or enlarge a polytomy.  ^n^nThe next tool, at the start of the second row, is a collapse clade tool, which collapses all resolution in a clade to a single polytomous bush.  Holding down the Option/Alt key will cause all branches outside of the clade touched to be collapsed into a single polytomy.^n^nSome additional tools in the tool pal [...]
+				setTitle Editing_tools;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/04-branchLengths.nex b/Resources/examples/Basic_Examples/tree_manipulation/04-branchLengths.nex
new file mode 100755
index 0000000..e5d3b43
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/04-branchLengths.nex
@@ -0,0 +1,232 @@
+#NEXUS
+[written Sat Jun 07 10:49:13 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895e586787;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-branchLengths.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895e58770;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-branchLengths.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895e586787;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895e58770;
+			checksum 0 4129971366 WM114895e58770;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 429 466;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 396;
+					setLocation 457 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BranchLengthsAdjust.AdjustToolExtra.stretchAdjustor;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((((1:1.0,5:1.0):1.0,4:2.0):1.0,((7:1.0,6:1.0):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):1.0,3:2.0):2.0):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-branchColorNames.nex';
+			setPrevFileName '03-editingTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 357 449;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The currently selected tool in the tool palette at left is the Stretch Branch tool.  The branches are drawn with length proportional to their stored lengths.  Thus, you''ll see the branches change as you stretch and shrink them.  Touch on a branch with the Stretch Branch tool, and drag up or down to change the branch length. (If you make a branch with zero length and can''t select it any more, you can always find it again by turning off the Branches Proportional to Le [...]
+				setTitle Branch_lengths;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/05-branchColorNames.nex b/Resources/examples/Basic_Examples/tree_manipulation/05-branchColorNames.nex
new file mode 100755
index 0000000..43f079b
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/05-branchColorNames.nex
@@ -0,0 +1,231 @@
+#NEXUS
+[written Sat Jun 07 10:49:19 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895e917988;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-branchColorNames.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895e91890;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-branchColorNames.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                     unord PolyTcount =                     MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895e917988;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895e91890;
+			checksum 0 4129971366 WM114895e91890;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 421 476;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 420;
+					setLocation 439 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.ColorBranches.ColorToolExtra.ColorBranches;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((((1:1.0,5:1.0):1.0,4:2.0<color = 11 >):1.0,((7:1.0,6:1.0):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):1.0,3:2.0)Jotinupinae:2.0):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-branchSelection.nex';
+			setPrevFileName '04-branchLengths.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 349 459;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The currently selected tool in the tool palette at left is the Color Branches tool.  It colors a branch a chosen color.  This has nothing to do with reconstructions of character evolution; it can be used to highlight particular clades, for instance for use with Dependent Tree windows (or for demonstrations or example files).^n^nTo color a branch, touch on it.  You can change the color of paint by touching on the tool in the tool palette and holding the mouse button do [...]
+				setTitle Branch_colors_&_names;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/06-branchSelection.nex b/Resources/examples/Basic_Examples/tree_manipulation/06-branchSelection.nex
new file mode 100755
index 0000000..c2e2a26
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/06-branchSelection.nex
@@ -0,0 +1,234 @@
+#NEXUS
+[written Sat Jun 07 11:13:19 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895ec8fd89;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-branchSelection.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895ec92b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-branchSelection.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                       unord PolyTcount =                       MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895ec8fd89;
+			tell It;
+				setSelected  2;
+				attachments ;
+			endTell;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895ec92b0;
+			checksum 0 4129971366 WM114895ec92b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 499 587;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 84;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 348;
+					setLocation 545 31;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((((1:1.0,5:1.0):1.0,4:2.0):1.0,((7:1.0<selected = on >,6:1.0):1.0,2:2.0<selected = on >):1.0):1.0,((9:1.0,8:1.0):1.0,3:2.0):2.0):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-storedTrees.nex';
+			setPrevFileName '05-branchColorNames.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 427 570;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Selecting branches or taxa in the tree window can be done by the standard arrow tool, or by special tools for selecting clades.^n^nIf no branches are selected, then the entire tree looks normal.  However, when some branches are selected, the other branches (those not selected) are dimmed, as shown here.  This can be useful to highlight branches both on trees and in other contexts such as Node Scattergram.  It also allows other modules to restrict calculations to only  [...]
+				setTitle 'Selecting Taxa/Branches';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/07-storedTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/07-storedTrees.nex
new file mode 100755
index 0000000..435cbba
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/07-storedTrees.nex
@@ -0,0 +1,281 @@
+#NEXUS
+[written Sat Jun 07 11:13:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895ef84090;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-storedTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895ef8710;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-storedTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                        unord PolyTcount =                        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895ef84090;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895ef8710;
+			checksum 0 4129971366 WM114895ef8710;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 513 248;
+			setLocation 7 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTrees 0 #mesquite.lists.TreesList.TreesList;
+			tell It;
+				setTreeBlock 1;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.NumForTreeList.NumForTreeList;
+				tell It;
+					suppress;
+					setValueTask  #mesquite.trees.NumberOfTaxa.NumberOfTaxa;
+					desuppress;
+				endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 344 196;
+					setLocation 540 257;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+			showTreeBlocks  #mesquite.lists.TreeblockList.TreeblockList;
+			tell It;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.TreeblocksListNumber.TreeblocksListNumber;
+					newAssistant  #mesquite.lists.TreeblocksListTaxa.TreeblocksListTaxa;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 406 142;
+					setLocation 538 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 422;
+					setLocation 11 363;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-listOfTrees.nex';
+			setPrevFileName '06-branchSelection.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 441 231;
+					setLocation 7 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Trees can be stored in files in groups of trees called "tree blocks".  The Tree Block window shows that there is a single tree block called "Basic Trees" in the file, containing 6 trees.  The Trees List window lists these 6 trees.^n^nYou can store a tree into the tree block by going to the Store Tree As... menu item of the Tree menu of the Tree window.  It will give you a dialog box by which you can indicate the name under which the tree is to be stored.  (If there we [...]
+				setTitle Tree_blocks;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/08-listOfTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/08-listOfTrees.nex
new file mode 100755
index 0000000..c6e5d33
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/08-listOfTrees.nex
@@ -0,0 +1,160 @@
+#NEXUS
+[written Sat Jun 07 11:16:49 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895fea9c91;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-listOfTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895feaa70;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-listOfTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                           unord PolyTcount =                           MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895fea9c91;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895feaa70;
+			checksum 0 4129971366 WM114895feaa70;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 463 375;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTrees 0 #mesquite.lists.TreesList.TreesList;
+			tell It;
+				setTreeBlock 1;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.NumForTreeList.NumForTreeList;
+				tell It;
+					suppress;
+					setValueTask  #mesquite.trees.NumberOfTaxa.NumberOfTaxa;
+					desuppress;
+				endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 451 320;
+					setLocation 499 24;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.lists.TreesList.TreesListWindow.arrow;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-treeBlocks.nex';
+			setPrevFileName '07-storedTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 391 358;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The stored blocks of trees are listed at left, in the Project Panel.  ^n^nIn the Trees list window you can manage stored trees.^n^nBy selecting the Edit tool (the I-beam) and touching on a tree''s name, you can edit its name. (If the arrow is the current cursor, you can also double click on the tree name to edit it.)^n^nBy selecting a row using the arrow tool (touch on the row number), and selecting "Delete selected trees" from the List menu of the Trees List window,  [...]
+				setTitle Stored_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/09-treeBlocks.nex b/Resources/examples/Basic_Examples/tree_manipulation/09-treeBlocks.nex
new file mode 100755
index 0000000..e75700d
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/09-treeBlocks.nex
@@ -0,0 +1,272 @@
+#NEXUS
+[written Sat Jun 07 11:17:11 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148960247e92;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "09-treeBlocks.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148960249a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-treeBlocks.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "09-treeBlocks.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE Alphabetical_ladder = ((((((((1,2),8),3),9),5),4),6),7);
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                              unord PolyTcount =                              MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148960247e92;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148960249a0;
+			checksum 0 4129971366 WM1148960249a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 515 636;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTreeBlocks  #mesquite.lists.TreeblockList.TreeblockList;
+			tell It;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.TreeblocksListNumber.TreeblocksListNumber;
+					newAssistant  #mesquite.lists.TreeblocksListTaxa.TreeblocksListTaxa;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 422 174;
+					setLocation 554 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 534 373;
+					setLocation 547 331;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-externalTrees.nex';
+			setPrevFileName '08-listOfTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 443 619;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this file a second tree block has been created, and so now there are two places in which trees can be stored.  The two tree blocks are listed in the Tree blocks list window shown.  To create a new tree block in which to store trees, choose New Empty Block of Trees... from the Taxa&Trees menu.  You''ll be asked to give it a name.^n^nIf you have more than one tree block in the file and you ask to store a tree in the Tree Window using the Store Tree... menu item, you  [...]
+				setTitle Tree_blocks;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/10-externalTrees.nex b/Resources/examples/Basic_Examples/tree_manipulation/10-externalTrees.nex
new file mode 100755
index 0000000..0a96b44
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/10-externalTrees.nex
@@ -0,0 +1,283 @@
+#NEXUS
+[written Wed Aug 26 11:16:54 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114896111d693;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "10-externalTrees.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114896111fd0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "10-externalTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "10-externalTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE Alphabetical_ladder = ((((((((1,2),8),3),9),5),4),6),7);
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                              unord PolyTcount =                              MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		linkFile '10-treeFile.nex';
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114896111d693;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114896111fd0;
+			checksumv 0 2 3673400160 WM114896111fd0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 518 450;
+			setLocation 6 312;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.ManageTrees.ManageTrees;
+		tell It;
+			showTreeBlocks  #mesquite.lists.TreeblockList.TreeblockList;
+			tell It;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.TreeblocksListNumber.TreeblocksListNumber;
+					newAssistant  #mesquite.lists.TreeblocksListTaxa.TreeblocksListTaxa;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 528 257;
+					setLocation 555 28;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 400;
+					setLocation 622 334;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-treeSources.nex';
+			setPrevFileName '09-treeBlocks.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 446 433;
+					setLocation 6 312;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'This file illustrates how trees can be obtained from an external tree file.^n^nMesquite can consider information from several files on disk when doing its calculations.  Once a file is open, other files can be linked or included within it, thus making their information available for calculations.  This information is not necessarily restricted to trees in external tree files (for further information see the example files on basic Mesquite operation), but for this exam [...]
+				setTitle External_tree_files;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/10-treeFile.nex b/Resources/examples/Basic_Examples/tree_manipulation/10-treeFile.nex
new file mode 100755
index 0000000..079561c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/10-treeFile.nex
@@ -0,0 +1,30 @@
+#NEXUS
+[written Wed Aug 26 11:16:55 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+BEGIN TREES;
+	Title 'Tree block 3 from "10-treeFile.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE 'Tree # 1 simulated by Uniform speciation (Yule)' = (((1:1.703015,9:1.703015):76.560245,(3:48.271825,6:48.271825):29.991425):21.736745,((((2:18.365655,8:18.365655):14.356185,7:32.721841):22.848645,5:55.570485):10.889825,4:66.460305):33.539693);
+	TREE 'Tree # 2 simulated by Uniform speciation (Yule)' = (((1:23.293445,(4:22.363587,5:22.363587):0.929865):32.112585,((3:0.427324,9:0.427324):10.027105,7:10.45443):44.951605):44.593965,((2:4.827383,8:4.827383):9.246845,6:14.074224):85.925775);
+	TREE 'Tree # 3 simulated by Uniform speciation (Yule)' = ((((1:6.666365,7:6.666365):29.387456,(4:2.816477,8:2.816477):33.237345):29.556011,(3:22.682945,(6:0.632975,9:0.632975):22.049965):42.926885):34.390175,(2:27.4306997,5:27.4306997):72.5693);
+	TREE 'Tree # 4 simulated by Uniform speciation (Yule)' = ((1:31.279625,(3:5.844405,7:5.844405):25.43522):68.720372,(2:18.242205,(4:16.10576,(5:15.715144,((6:1.3364898,9:1.3364898):3.070995,8:4.407485):11.307658):0.390616):2.136446):81.757793);
+	TREE 'Tree # 5 simulated by Uniform speciation (Yule)' = ((((1:1.667595,8:1.667595):14.625975,(7:0.282177,9:0.282177):16.011395):58.878815,((3:57.788306,6:57.788306):16.563775,4:74.352085):0.820305):24.827615,(2:63.969165,5:63.969165):36.030839);
+	TREE 'Tree # 6 simulated by Uniform speciation (Yule)' = (((1:28.378215,(6:21.851352,8:21.851352):6.5268598):51.962205,(3:79.998505,(4:24.374577,(7:20.571215,9:20.571215):3.803355):55.623931):0.3419098):19.659581,(2:67.916801,5:67.916801):32.083195);
+	TREE 'Tree # 7 simulated by Uniform speciation (Yule)' = ((1:32.146405,(6:23.677024,8:23.677024):8.469385):67.853595,((2:7.748275,9:7.748275):67.229305,(3:65.258731,(4:63.971965,(5:26.52003,7:26.52003):37.451935):1.2867697):9.718852):25.022416);
+	TREE 'Tree # 8 simulated by Uniform speciation (Yule)' = (((1:5.716215,6:5.716215):19.810545,(3:23.749493,(4:4.100375,7:4.100375):19.649115):1.777266):74.473245,(2:15.850345,((5:1.178665,9:1.178665):1.5289695,8:2.707635):13.142711):84.149653);
+	TREE 'Tree # 9 simulated by Uniform speciation (Yule)' = (((1:14.482155,((4:2.024885,9:2.024885):12.388698,5:14.413585):0.068565):15.883165,(3:7.739799,((6:5.804895,8:5.804895):1.794605,7:7.599505):0.140296):22.625521):69.6346795,2:99.9999999);
+	TREE 'Tree # 10 simulated by Uniform speciation (Yule)' = ((1:37.520065,(5:4.39122,8:4.39122):33.128843):62.479936,((2:10.357478,(7:2.810265,9:2.810265):7.547215):67.668655,(3:76.997715,(4:31.954895,6:31.954895):45.042822):1.028423):21.973864);
+
+END;
+
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/11-treeSources.nex b/Resources/examples/Basic_Examples/tree_manipulation/11-treeSources.nex
new file mode 100755
index 0000000..d8f005e
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/11-treeSources.nex
@@ -0,0 +1,347 @@
+#NEXUS
+[written Sat Jun 07 11:18:04 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114897ca38394;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "11-treeSources.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114897ca3e50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "11-treeSources.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "11-treeSources.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE Alphabetical_ladder = ((((((((1,2),8),3),9),5),4),6),7);
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                              unord PolyTcount =                              MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114897ca38394;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114897ca3e50;
+			checksum 0 4129971366 WM114897ca3e50;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 345 436;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 563 354;
+					setLocation 423 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+					tell It;
+						setTime 100.0;
+					endTell;
+					setSeed 983499638345;
+				endTell;
+				setAssignedID 3412.1053130084637.392292706092630953;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 564 368;
+					setLocation 423 473;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Dark Gray;
+					removeColor on;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '12-treeSources.nex';
+			setPrevFileName '10-storedTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 273 419;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The previous example files used blocks of trees stored in the file.  Many of Mesquite''s calculations that use trees can obtain their trees either from those stored in the file, or from other sources.  Other sources of trees can include simulations that generate trees on demand according to some model of tree creation.^n^nFor instance, the two tree windows above are similar except that one is using Stored Trees as the source of trees, while the other one  is using Sim [...]
+				setTitle Tree_sources;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/12-treeSources.nex b/Resources/examples/Basic_Examples/tree_manipulation/12-treeSources.nex
new file mode 100755
index 0000000..910ded3
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/12-treeSources.nex
@@ -0,0 +1,321 @@
+#NEXUS
+[written Sat Jun 07 11:18:11 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114897e1c2c95;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114897e1c4a0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114897e1c5d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "12-treeSources.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "12-treeSources.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE Alphabetical_ladder = ((((((((1,2),8),3),9),5),4),6),7);
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                                    unord PolyTcount =                                    MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114897e1c2c95;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114897e1c4a0;
+			checksum 0 4129971366 WM114897e1c4a0;
+			setID 1 2821694224149906583 WM114897e1c5d0;
+			checksum 1 4236368331 WM114897e1c5d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 442 523;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #8476784597994698209;
+			setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+			tell It;
+				setTreeBlock 1;
+				toggleUseWeights off;
+			endTell;
+			setCalculator  #mesquite.parsimony.Treelength.Treelength;
+			tell It;
+				getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+				tell It;
+					getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+					tell It;
+						setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+						getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+						tell It;
+							toggleWeight off;
+						endTell;
+					endTell;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+					tell It;
+						setDataSet #2821694224149906583;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 347;
+					setLocation 468 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 0;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 6;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #8476784597994698209;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.trees.EqualRatesMarkovSp.EqualRatesMarkovSp;
+				tell It;
+					setTime 100.0;
+				endTell;
+				setSeed 983501043822;
+			endTell;
+			setCalculator  #mesquite.parsimony.Treelength.Treelength;
+			tell It;
+				getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+				tell It;
+					getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+					tell It;
+						setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+						getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+						tell It;
+							toggleWeight off;
+						endTell;
+					endTell;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+					tell It;
+						setDataSet #2821694224149906583;
+					endTell;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 541 327;
+					setLocation 454 505;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 50;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 1000;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '13-instability.nex';
+			setPrevFileName '11-treeSources.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 370 506;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows that alternative sources of trees can be used in various contexts, including charts.  Shown here are two simple histograms showing the numbers of trees with different treelengths (parsimony scores, using a continuous-valued data matrix).  Above is a window with Stored Trees as the source of trees; below is a window with Simulated Trees, using a uniform speciation model, as a source of trees.  ^n^nTreelength is not the only statistic that can be so char [...]
+				setTitle Tree_sources;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_manipulation/13-instability.nex b/Resources/examples/Basic_Examples/tree_manipulation/13-instability.nex
new file mode 100755
index 0000000..a52bead
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_manipulation/13-instability.nex
@@ -0,0 +1,1080 @@
+#NEXUS
+[written Sat Jun 07 11:18:32 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+	BLOCKID WM1148980454098;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "13-instability.nex"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+		BLOCKID WM114898045620;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "13-instability.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE Mental = (53,(52,44,45,46,47,48,49,50,51,((39,38,40,(41,(42,43))),((35,36,37),(19,20,21),(23,22),24,30,(27,(25,26)),33,(29,28),34,31,32,((1,2),((((4,3,5),6),(7,(8,9))),10,(12,11,(13,(15,14,16,(17,18))))))))));
+	TREE equal_wt_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(19,20,21,22,23,24,28,29,30,31,32,33,34,6,7,8,9,10,(1,2),(35,(36,37)),(25,26,27),(3,4,5),(11,12,13,(17,18,(14,15,16))))))));
+	TREE super_consensus = (53,(52,(44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),20,21,22,23,24,28,29,30,31,19,33,34,(25,26,27),(35,(36,37)),32,(1,2),7,6,8,9,10,(3,4,5),(11,12,13,(17,18,(14,15,16)))))));
+	TREE 1_of_4_common = (53,(52,((50,51),((48,49),(((44,45),(46,47)),((38,(40,(39,(41,(42,43))))),((22,(19,(20,21))),((23,((24,(28,29)),(30,(27,(25,26))))),(34,((31,(33,(35,(36,37)))),(32,((1,2),((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,(17,(18,(16,(14,15))))))))))))))))))));
+	TREE 545_class_1 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(30,(19,(20,21)),22,23,24,(25,26,27),28,29,((35,(36,37)),31,32,33,34,((1,2),((4,(3,5)),(10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))));
+	TREE 545_class_2 = (44,45,(46,47),(48,49),(50,51),((38,39,40,(41,(42,43))),(22,(19,(20,21)),(30,23,24,(27,(25,26)),(28,29),((35,(36,37)),31,34,33,(1,2),(32,((4,(3,5)),((10,(9,(8,(6,7)))),((11,12),(13,((14,15,16),17,18)))))))))));
+	TREE 545_class_3 = (44,45,46,47,(48,49),(50,51),((38,39,40,(41,(42,43))),(30,29,24,(27,(25,26)),28,(23,(22,(19,((20,21),(3,4,5))))),((35,(36,37)),31,32,33,34,((1,2),((10,(9,(8,(6,7)))),(11,12,13,((14,15,16),17,18))))))));
+	TREE 545_class_4 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((24,(23,(22,(19,(20,21,(6,(4,(3,5)))))))),((30,(28,(27,(25,26)))),(29,(34,((31,(33,(35,(36,37)))),32,((1,2),((10,(7,(8,9))),(11,12,13,((14,15,16),17,18))))))))))))));
+	TREE 545_class_5 = (44,(45,((46,47),(((48,49),(50,51)),((39,((38,40),(41,(42,43)))),((34,(32,((10,(35,(36,37))),((31,33),((1,2),(13,(11,(12,(17,(18,(16,(14,15)))))))))))),(((24,(28,29)),(30,(27,(25,26)))),(23,(22,(19,((20,21),((4,(3,5)),(7,(6,(8,9)))))))))))))));
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.12156863 0.72941176 0.12156863) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.12156863) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.01960784) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                                 unord PolyTcount =                                 MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "13-instability.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE island.1.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.8.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,(((14,15),16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((((14,15),16),18),17)))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,(15,16)),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,15,16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.12a.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.32.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.36.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.40.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.44.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.2 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.3 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.4 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.5 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.11 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.12 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.13 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.14 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.15 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.16 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.17 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.18 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.19 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.20 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.21 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.22 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.23 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.24 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.25 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.26 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.27 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.28 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.29 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.30 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.31 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.32 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.33 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.35 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.37 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.39 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.41 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.42 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.43 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.44 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.48.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.68.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.84.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.69 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.70 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.71 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.72 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.73 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.74 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.75 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.76 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.77 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.78 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.79 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.80 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.81 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.82 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.83 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.84 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.160.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.3 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.4 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.5 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.20 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.21 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.22 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.23 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.24 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.25 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.26 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.27 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.28 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.29 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.30 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.31 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.32 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.33 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.35 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.37 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.39 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.41 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.66 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.67 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.68 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.69 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.70 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.71 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.72 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.73 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.74 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.75 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.76 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.77 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.78 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.79 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.80 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.81 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.82 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.83 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.84 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.85 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.86 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.87 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.88 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.89 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.90 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.91 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.92 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.93 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.94 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.95 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.96 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.97 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.98 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.99 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.100 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.101 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.102 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.103 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.104 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.105 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.106 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.107 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.108 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.109 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.110 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.111 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.112 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.113 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.114 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.115 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.116 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.117 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.118 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.119 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.120 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.121 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.122 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.123 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.124 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.125 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.126 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.127 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.128 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.129 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.130 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.131 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.132 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.133 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.134 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.135 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.136 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.137 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.138 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.139 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.140 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.141 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.142 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.143 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.144 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.145 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.146 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.147 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.148 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.149 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.150 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.151 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.152 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.153 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.154 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.155 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.156 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.157 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.158 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.159 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.160 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+
+END;
+
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+BEGIN NOTES;
+
+	TEXT  TAXA = Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 11 CHARACTER = 3 TEXT = Maybe_not_quite_so_distinct;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  81;
+	LastModified -1204394462;
+	FileSettings treewindow '2' '2' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'                                  Geneva '9' '100' '1'                                  all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '632' '899';
+	ListWindow Characters open Geneva '9' '80' '597' '273' '480'                                  001;
+	ListWindow Taxa closed Geneva '9' '117' '383' '209' '302'                                  100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '515' '211' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '482' '441' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Tree List Characters List GroupLabels List CharPartitions;
+	OtherSymbols & /                                  00 ? -;
+	Correlation '0' '0' '1000' '0' '0'                                  10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'                                  110000;
+	PrettyPrint 10;
+	CharLegendPosition '519' '697' '120' '111';
+	TreeLegendPosition '575' '601' '64' '93';
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 00;
+	TreeWindow 0000;
+	Continuous '0' '3'                                  1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                                  0;
+	Charts  Geneva '9' (                                 normal )                                  0010;
+	NexusOptions '0' '0' '50'                                  001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (                                 normal );
+	TreeShape  1.0 1.0 1101;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'                                  1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                                  1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '0'                                  1;
+	BarsOnBranchesDisplay '5' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'                                  0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                                  1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                                  Geneva '9' (                                 normal )                                  Geneva '10' (                                 normal )                                  Geneva '9' (                                 normal )                                  Geneva '9' (                                 normal )                                  Geneva '9' (                                 bol [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'                                  00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'                                  100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'                                  1010;
+	BothTools '1';
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4388395586715833634 WM1148980454098;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 206796807167704052 WM114898045620;
+			checksum 0 2915397944 WM114898045620;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 574 249;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '12-treeSources.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 502 232;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'One way to compare trees and assess taxa is by the module Taxon Instability among Trees.  It is available as a value for taxa, and thus can be plotted in charts as that shown here.  Each point represents a taxon, with the Y axis the instability of the taxon''s relationships among trees, and the X axis being the taxon''s percent of missing data.  Note that there is no apparent correlation; those taxa with more missing data do not seem to be any more variable in their p [...]
+				setTitle Taxon_instability_among_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #4388395586715833634;
+			endTell;
+			setTaxa #4388395586715833634;
+			axesDifferent;
+			setValuesX  #mesquite.molec.PercentMissingInTaxon.PercentMissingInTaxon;
+			tell It;
+				getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+					tell It;
+						setDataSet #206796807167704052;
+					endTell;
+				endTell;
+			endTell;
+			setValuesY  #mesquite.treefarm.TerminalInstability.TerminalInstability;
+			tell It;
+				setExponent 2.0;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 2;
+					toggleUseWeights off;
+				endTell;
+				setNumTrees 100;
+				setSkipping 10;
+				doCalc;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 594 492;
+					setLocation 12 351;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #4388395586715833634;
+			setNumColumns 2;
+			setNumRows 2;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				assignNumTrees 9;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 546 775;
+				setLocation 624 22;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle off;
+						toggleScale on;
+						toggleBroadScale off;
+						toggleCenter on;
+						toggleEven on;
+					endTell;
+					setEdgeWidth 6;
+					orientRight;
+					toggleCorners off;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setFontSize 9;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/01-treeWindow.nex b/Resources/examples/Basic_Examples/tree_viewing/01-treeWindow.nex
new file mode 100755
index 0000000..ec61075
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/01-treeWindow.nex
@@ -0,0 +1,229 @@
+#NEXUS
+[written Sat Jun 07 11:20:51 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148950c7fa65;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-treeWindow.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148950c8010;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-treeWindow.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                    unord PolyTcount =                    MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148950c7fa65;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148950c8010;
+			checksum 0 4129971366 WM1148950c8010;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 509 397;
+			setLocation 6 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 52;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 529 362;
+					setLocation 563 30;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-treeForm.nex';
+			setPrevFileName '../basic_operation/04-treeWindow.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 437 380;
+					setLocation 6 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a tree window, currently showing a tree stored in the file.  At the left of the window is a tool palette with which you can modify the tree or its appearance (more details on tree editing, storing, and generating can be found among the tree manipulation example files).  To see the other trees stored in the tree block of the file, hit the blue triangular arrows above the tool palette.  (If the arrow is dim, that means that you can''t scroll more in that [...]
+				setTitle Tree_window;
+				toggleFileNames off;
+				setPrevButtonName Return;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/02-treeForm.nex b/Resources/examples/Basic_Examples/tree_viewing/02-treeForm.nex
new file mode 100755
index 0000000..6b97219
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/02-treeForm.nex
@@ -0,0 +1,231 @@
+#NEXUS
+[written Sat Jun 07 11:21:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148951041266;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-treeForm.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895104240;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-treeForm.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                unord PolyTcount =                MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148951041266;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895104240;
+			checksum 0 4129971366 WM114895104240;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 503 402;
+			setLocation 9 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 381;
+					setLocation 548 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-drawingSize.nex';
+			setPrevFileName '01-treeWindow.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 431 385;
+					setLocation 9 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows the tree window with an alternative style of tree drawing.  Three changes have been made from the previous file:  (1) "Square Tree" was selected from the Tree Form submenu in the Display menu of the Tree window, (2) "Right" was selected from the Orientation submenu of the Display menu, and 18 was selected as the Font Size from the submenu in the Display menu (there is another Font Size submenu under Edit, but that changes font size elsewhere in the win [...]
+				setTitle Drawing_form;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/03-drawingSize.nex b/Resources/examples/Basic_Examples/tree_viewing/03-drawingSize.nex
new file mode 100755
index 0000000..22fc2fb
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/03-drawingSize.nex
@@ -0,0 +1,233 @@
+#NEXUS
+[written Sat Jun 07 11:21:46 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148951d68675;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-drawingSize.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148951d69f0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-drawingSize.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1,5),4),((7,6),2)),((9,8),3));
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                 unord PolyTcount =                 MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148951d68675;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148951d69f0;
+			checksum 0 4129971366 WM1148951d69f0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 525 426;
+			setLocation 8 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 421;
+					setLocation 561 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 1200 800;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-moreTreeForms.nex';
+			setPrevFileName '02-treeForm.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 453 409;
+					setLocation 8 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For trees with large numbers of terminal taxa, it may be inconvenient to fit the tree drawing into the small rectangle of the window.  Mesquite can display the tree by drawing it in a larger field over which you can scroll.  (Mesquite does this automatically by default if you start up a tree window for a taxa block with many taxa.)^n^nIn the tree window shown here, only a small portion of the tree is shown.  You can scroll over the rest of the tree using the scroll ba [...]
+				setTitle Drawing_size;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/04-moreTreeForms.nex b/Resources/examples/Basic_Examples/tree_viewing/04-moreTreeForms.nex
new file mode 100755
index 0000000..d1a1be6
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/04-moreTreeForms.nex
@@ -0,0 +1,367 @@
+#NEXUS
+[written Wed Aug 26 11:08:41 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148952502776;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148952502e0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM1148952503c0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-moreTreeForms.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148952502776;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148952502e0;
+			checksumv 0 2 3673400160 WM1148952502e0;
+			setID 1 3539015483384763311 WM1148952503c0;
+			checksumv 1 2 4236368331 WM1148952503c0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 551 161;
+			setLocation 7 23;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1284.967851092611.9112317805264017777;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 392;
+					setLocation 18 277;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale off;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientRight;
+						setCornerMode Diagonal  50;
+					endTell;
+					setBackground Wood;
+					setBranchColor Sienna;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 18;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 426.983378392297.1912349616257064461;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 392;
+					setLocation 613 40;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-moreTreeForms.nex';
+			setPrevFileName '03-drawingSize.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 479 144;
+					setLocation 7 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Here are two more modes of tree drawing (Curvogram and Square Tree with diagnonal corners; both have lengths proportional).';
+				setTitle More_forms;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/05-moreTreeForms.nex b/Resources/examples/Basic_Examples/tree_viewing/05-moreTreeForms.nex
new file mode 100755
index 0000000..3510b99
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/05-moreTreeForms.nex
@@ -0,0 +1,494 @@
+#NEXUS
+[written Wed Aug 26 11:08:23 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148953550b77;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM1148953551d0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895355320;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-moreTreeForms.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148953550b77;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM1148953551d0;
+			checksumv 0 2 3673400160 WM1148953551d0;
+			setID 1 3539015483384763311 WM114895355320;
+			checksumv 1 2 4236368331 WM114895355320;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 565 263;
+			setLocation -5 25;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 405.983378206854.2915181347041568270;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 538 395;
+					setLocation 1 342;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+					tell It;
+						setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+						tell It;
+							hide;
+							setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+							tell It;
+								getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+								tell It;
+									setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+									tell It;
+										setDataSet #3539015483384763311;
+									endTell;
+								endTell;
+								setCharacter 2;
+								setItem 0;
+								getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+								tell It;
+									setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+									toggleMPRsMode off;
+									getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+									tell It;
+										toggleWeight on;
+									endTell;
+								endTell;
+							endTell;
+							toggleShowLegend on;
+							setInitialOffsetX 4;
+							setInitialOffsetY -322;
+							setCurrentX 1;
+							setCurrentY 2;
+							show;
+						endTell;
+						setSpotDiameter 16;
+						toggleShowTerminals on;
+						toggleShowInternals on;
+						toggleShowTree on;
+					endTell;
+					setBackground Goldenrod;
+					setBranchColor Gray;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 556.983378650668.3313559907369500737;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 550 371;
+					setLocation 561 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 24;
+						setEdgeWidth 4;
+						orientUp;
+						useCurved;
+						toggleCosmic on;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground Light_Green;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 4847.1251309942593.1748310754480117010;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 553 286;
+					setLocation 558 492;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 2;
+						orientRight;
+						setCornerMode Curved  50;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 0;
+					toggleLegendFloat on;
+					scale 0;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					toggleShow consensusFrequency;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-printingTrees.nex';
+			setPrevFileName '04-moreTreeForms.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 493 246;
+					setLocation -5 25;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Here are three more modes of tree drawing:^n(1) Balls & sticks in Cosmic mode with light green and blue as background and branch color and Curved line style^n(2) Plot tree with grey as branch color^n(3) Square tree with Corners set to Curved and branches drawn proportional to lengths';
+				setTitle More_forms;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/06-printingTrees.nex b/Resources/examples/Basic_Examples/tree_viewing/06-printingTrees.nex
new file mode 100755
index 0000000..ac8874c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/06-printingTrees.nex
@@ -0,0 +1,261 @@
+#NEXUS
+[written Sat Jun 07 11:22:08 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148954470478;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895447320;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895447420;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-printingTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                  unord PolyTcount =                  MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM1148954470478;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895447320;
+			checksum 0 4129971366 WM114895447320;
+			setID 1 3539015483384763311 WM114895447420;
+			checksum 1 4236368331 WM114895447420;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 500 391;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 556.983378650668.3313559907369500737;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 374;
+					setLocation 540 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 24;
+						setEdgeWidth 4;
+						orientRight;
+						useCurved;
+						toggleCosmic on;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale off;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont Times;
+						setFontSize 14;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-dependentWindow.nex';
+			setPrevFileName '05-moreTreeForms.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 428 374;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'To print a tree graphic, choose Print Tree or Print Tree to Fit from the File menu of the Tree window.  Print Tree to Fit will resize the tree to fit on the printed page.  Print Tree will keep the tree at its size according to the screen appearance, and it will be printed over more than one page if needed.^n^nTo save a graphics file, you can use Save Tree as PDF (in the File menu of the Tree window).  Occasionally the results of Save Tree as PDF might not be exactly a [...]
+				setTitle Printing;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/07-dependentWindow.nex b/Resources/examples/Basic_Examples/tree_viewing/07-dependentWindow.nex
new file mode 100755
index 0000000..3b3cb5f
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/07-dependentWindow.nex
@@ -0,0 +1,409 @@
+#NEXUS
+[written Sat Jun 07 11:22:21 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895a54ef79;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895a54fd0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895a550d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-dependentWindow.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                    unord PolyTcount =                    MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895a54ef79;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895a54fd0;
+			checksum 0 4129971366 WM114895a54fd0;
+			setID 1 3539015483384763311 WM114895a550d0;
+			checksum 1 4236368331 WM114895a550d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 559 265;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 556.983378650668.3313559907369500737;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 526 400;
+					setLocation 594 41;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont Times;
+						setFontSize 14;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #974864624972105434;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -161;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+						tell It;
+							setSpotDiameter 24;
+							setEdgeWidth 4;
+							orientUp;
+							useDiagonal;
+							toggleCosmic off;
+							getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle on;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter on;
+								toggleEven on;
+							endTell;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 526 440;
+						setLocation 29 365;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #3539015483384763311;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -142;
+						setInitialOffsetY -305;
+						setLegendWidth 142;
+						setLegendHeight 302;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-mirrorTree.nex';
+			setPrevFileName '06-printingTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 487 248;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'There are several special windows in which to view trees, in addition to the standard Tree Window.  Below is a Dependent Tree Window.  You can obtain one from the Tree menu of an existing Tree Window.^n^nA Dependent Tree Window shows the exact same tree as in the Tree Window from which it was called.  Thus, if you scroll to another tree, or edit the tree, in the Tree window at left, the tree in the Dependent window will change in concert.  (Try it!)^n^nThe purpose of  [...]
+				setTitle Dependent_tree_window;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/08-mirrorTree.nex b/Resources/examples/Basic_Examples/tree_viewing/08-mirrorTree.nex
new file mode 100755
index 0000000..84a999c
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/08-mirrorTree.nex
@@ -0,0 +1,398 @@
+#NEXUS
+[written Sat Jun 07 11:22:32 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895b0c4180;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895b0c510;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895b0c730;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-mirrorTree.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                      unord PolyTcount =                      MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895b0c4180;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895b0c510;
+			checksum 0 4129971366 WM114895b0c510;
+			setID 1 3539015483384763311 WM114895b0c730;
+			checksum 1 4236368331 WM114895b0c730;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 569 307;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8476784597994698209  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 556.983378650668.3313559907369500737;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 552 401;
+					setLocation 624 42;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont Times;
+						setFontSize 14;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 552 441;
+						setLocation 6 401;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #974864624972105434;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -161;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #3539015483384763311;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -305;
+						setLegendWidth 142;
+						setLegendHeight 302;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-multiTrees.nex';
+			setPrevFileName '07-dependentWindow.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 497 290;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Below is another special window in which to view a tree.  It is a Mirror Tree Window.  You can obtain one from the Tree menu of an existing Tree Window.^n^nA Mirror Tree Window shows the exact same tree as in the Tree Window from which it was called.  Thus, if you scroll to another tree, or edit the tree, in the Tree window at left, the tree in the Mirror Tree window will change in concert.  (Try it!)^n^nThe purpose of a Mirror Tree Window is to give you an alternativ [...]
+				setTitle Mirror_tree_window;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/09-multiTrees.nex b/Resources/examples/Basic_Examples/tree_viewing/09-multiTrees.nex
new file mode 100755
index 0000000..4624968
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/09-multiTrees.nex
@@ -0,0 +1,240 @@
+#NEXUS
+[written Sat Jun 07 11:22:48 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895b6f3c81;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895b6f530;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895b6f7b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-multiTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895b6f3c81;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895b6f530;
+			checksum 0 4129971366 WM114895b6f530;
+			setID 1 3539015483384763311 WM114895b6f7b0;
+			checksum 1 4236368331 WM114895b6f7b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 410 478;
+			setLocation 2 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #8476784597994698209;
+			setNumColumns 4;
+			setNumRows 2;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				assignNumTrees 6;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 851 497;
+				setLocation 429 23;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle off;
+						toggleScale on;
+						toggleBroadScale off;
+						toggleCenter on;
+						toggleEven on;
+					endTell;
+					setEdgeWidth 4;
+					orientRight;
+				endTell;
+				setBackground White;
+				setBranchColor Blue;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-multiTrees.nex';
+			setPrevFileName '08-mirrorTree.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 338 461;
+					setLocation 2 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This shows another tree-viewing window, the Multi-Tree Window.  It is available under the Taxa&Trees menu.  It shows a series of trees from a single source.  In this case, it is showing trees simulated by a random process of speciation.  You could also show trees stored in a file.^n^nYou can change the number of columns and rows of trees displayed by selecting Number of Rows or Number of Columns from the Multi-Tree menu.  You can scroll through the trees using the scr [...]
+				setTitle 'Multi-tree window';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Basic_Examples/tree_viewing/10-multiTrees.nex b/Resources/examples/Basic_Examples/tree_viewing/10-multiTrees.nex
new file mode 100755
index 0000000..8d4b371
--- /dev/null
+++ b/Resources/examples/Basic_Examples/tree_viewing/10-multiTrees.nex
@@ -0,0 +1,305 @@
+#NEXUS
+[written Sat Jun 07 11:22:56 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM114895c2a6882;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Structure_&_Color;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 number_of_eyes /  one two, 2 tail_color /  blue red ; 
+	MATRIX
+	Aus         11
+	Fubonidia   11
+	Ibbinidibe  11
+	Snorolopa   1(0 1)
+	Quidnubia   00
+	Suinon      00
+	Zorabynyx   00
+	Huichoros   00
+	Jotinupa    00
+
+;
+		BLOCKID WM114895c2a990;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Growth_rate,
+		2 Q_index ; 
+	MATRIX
+	Aus          3.386483113203565 0.22275735218545334
+	Fubonidia    0.9597444210869673 0.7238288647096488
+	Ibbinidibe   0.47313918478048966 0.5532366339375796
+	Snorolopa    1.7895302029430193 2.6011148989978747
+	Quidnubia    2.457244946267127 2.0876469753892044
+	Suinon       0.8340376426612434 -0.6995203993072017
+	Zorabynyx    1.194800658526412 1.2182074121461475
+	Huichoros    1.794841197250114 0.14619510866889623
+	Jotinupa     1.8506946108999534 0.6447107189708169
+
+;
+		BLOCKID WM114895c2aab0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "10-multiTrees.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:3.1,5:1.0):0.5,4:2.0):0.478265,((7:1.0,6:1.923075):1.0,2:2.0):1.0):1.0,((9:1.0,8:1.0):0.444444,3:2.0):2.369235):1.0;
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+	TREE Polytomous = ((1,5),(7,6,2),4,((9,8),3));
+	TREE Partial_tree = (((9,(1,2)),(8,7)),(3,5));
+	TREE Taxonomy = (((1:3.1,5:1.0,4:2.0)Snorolopini:0.478265,(7:1.0,6:1.923075,2:2.0)Fubonidiini:1.0)Fubonidiinae:1.0,(9:1.0,8:1.0,3:2.0)Jotinupinae:2.369235)Fubonidiidae:1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                          unord PolyTcount =                          MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = Structure_&_Color)  =  unord:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Structure_&_Color)  =  'Mk1 (est.)':  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8476784597994698209 WM114895c2a6882;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 974864624972105434 WM114895c2a990;
+			checksum 0 4129971366 WM114895c2a990;
+			setID 1 3539015483384763311 WM114895c2aab0;
+			checksum 1 4236368331 WM114895c2aab0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 415 466;
+			setLocation 2 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #8476784597994698209;
+			setNumColumns 3;
+			setNumRows 2;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				assignNumTrees 6;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				newAssistant  #mesquite.trees.TreeLegendMaker.TreeLegendMaker;
+			tell It;
+				setOffsetsX 4;
+				setOffsetsY 4;
+				getLegendsVector;
+				tell It;
+				distributeCommands;
+					setBounds 4 4 89 39;
+					setOffsetX 4;
+					setOffsetY 4;
+				endDistributeCommands;
+				endTell;
+				newLegendItemNoCalc  #mesquite.parsimony.Treelength.Treelength;
+				tell It;
+					getEmployee #mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix;
+					tell It;
+						getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+						endTell;
+					endTell;
+					getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+						tell It;
+							setDataSet #974864624972105434;
+						endTell;
+					endTell;
+				endTell;
+				calculate;
+			endTell;
+				newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+			tell It;
+				suspend ;
+				setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+				tell It;
+					toggleLabels off;
+					toggleGray off;
+				endTell;
+				setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+				tell It;
+					getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #3539015483384763311;
+						endTell;
+					endTell;
+					setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+					tell It;
+						setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+						toggleMPRsMode off;
+						getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+						tell It;
+							toggleWeight on;
+						endTell;
+					endTell;
+				endTell;
+				setCharacter 1;
+				setMapping 1;
+				toggleShowLegend off;
+				toggleGray off;
+				toggleWeights on;
+				resume ;
+			endTell;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 842 482;
+				setLocation 428 22;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle on;
+						branchLengthsToggle off;
+						toggleScale on;
+						toggleBroadScale off;
+						toggleCenter off;
+						toggleEven off;
+					endTell;
+					setEdgeWidth 12;
+					orientUp;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../introduction.nex';
+			setPrevFileName '09-multiTrees.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 343 449;
+					setLocation 2 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This shows that analyses can be shown for each of the trees in the Multi-Tree Window.  A continuous-valued character is traced, and treelength is calculated for each of the trees.  These trees are stored in the file.^n';
+				setTitle 'Multi-tree analysis';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Character_Simulations/00-introduction.nex b/Resources/examples/Character_Simulations/00-introduction.nex
new file mode 100755
index 0000000..ba42007
--- /dev/null
+++ b/Resources/examples/Character_Simulations/00-introduction.nex
@@ -0,0 +1,40 @@
+#NEXUS
+[written Mon Sep 03 09:21:31 PDT 2007 by Mesquite  version 2.0BETA3 (build i55) at Thrandina.local/127.0.0.1 (Wayne Maddison)]
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Example files for coalescence calculations^n^nThe files linked to this one illustrate some of the coalescence calculations that can be done by the package of coalescence modules of the Mesquite system.  To learn more about this package, use the Coalescence Package menu item of the Help menu, or touch on the banner in the Mesquite Startup window. (It should take you to your web browser, perhaps after asking you to locate the browser.)^n^nTo go from one file to another, [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-modelTree.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 261;
+					setLocation 2 22;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'Example files for character simulations and hypothesis testing.^n^nTo go from one file to another, hit the "Next" button.';
+				setTitle Character_Simulations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual  'http://mesquiteproject.wikispaces.com/Ancestral+States';
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Character_Simulations/01-modelTree.nex b/Resources/examples/Character_Simulations/01-modelTree.nex
new file mode 100755
index 0000000..ab44ee6
--- /dev/null
+++ b/Resources/examples/Character_Simulations/01-modelTree.nex
@@ -0,0 +1,559 @@
+#NEXUS
+[written Sun Jun 08 13:13:13 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=49;
+	TAXLABELS
+		Omus Oxycheila Clinidium Omoglymmius Trachypachus Systolosoma Metrius Pachyteles Scaphinotus Nebria Loricera Elaphrus Antarctonomus Omophron Pasimachus Clivinini Dyschirius Creobius Bembidion Psydrus Mecyclothorax Agonum Chlaenius Haliplus_laminatus Haliplus_ruficollis Copelatus Cybister Hydroporus Laccophilus Neoporus Gyrinus Spanglerogyrus Hygrobius Hydrocanthus Noterus Suphis Bruchela Tenebrio Helochares Dynastes Cyphon Clambus Hydroscapha Torridincola Distocupes Sialis Anisochrysa  [...]
+	;
+	BLOCKID WM114cbd0cfc02;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-modelTree.nex"';
+	DIMENSIONS  NCHAR=2543;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Omus                 TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAAA--TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACATATACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGC-----GTCC--C--GGGCTCCATATGATTCTGTACCTTTGCGTA--CG--TTCATGT-GTCCTGG-TGTGCGTTCACACAT-ATTACTGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAACGGCT [...]
+TGTG---C-GGT-------------ACGTGTTATGCACTTTGTGTATTACCTCCGTGCCGTCATTTGTT----TCGTA--CT-TG---CTCGT-------GTCGG-CAACGATA--CT--GGTTGTTT--GTGGGCGATCTTTACTACCGGCGTACACATA-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCATGTC-CTCCCTGGCCGAGAGGTCCGGGTAATCCGGTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCCGACCGGTACTC--CGAC-G----AC [...]
+
+	Oxycheila            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CTTAA---TGAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTAC------AAAGTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCGTACCGGAGACGGAATGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGC-----ATCC--CTAAGGCTCCATATGATTCTGTGTCTTTGCACA--CG--TTCATAT-GTCCTGGGTGTATGTTCATATTTTTTTATTGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAACGGCT [...]
+TTTG---A-TGT-------------ATATAATACTTGTTAT-TGTATATATTTGG-------ATGTGTT----TTA----CT-TG---TTTGC-------GTCGAATAATGTAA--CT--AGTTGTTT--GTTGGCAATCTTTACTACCGGCGTATATTTG-TATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCTGTTCGAGAGAACCGGGTAATCCGTTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATAAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACT-CGGCCG----AT [...]
+
+	Clinidium            TCGTCTCAAAGATTAGGCCACGCATGTCTAAGTACAGCTTTCTATGTA-ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGGAGGAGTGCTTTTATTAGAACAAAACTGAT-CG---------GTGTTTCGTCTATTT------------------TATAGG--CG--TGC-----ATCGCAAGT---------GA-----AC--TGGTGAATCTGAATAACTTT-TGCTGATCGCATAGTCATAGCACTAGCGACAAATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTTGATTTCCT--------------CACGGGGTTGAT------------------------AAGTGTTCGGCTCGTATGAGGTGGTTAGTACTTGGAATGCTGGGGTCCCTCAGTGCCCACTTGTT---GGTCACGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCTGGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGG--CACG-TGGC-A----AT [...]
+
+	Omoglymmius          -----------------CCATGCATGTCTAAGTACAGCTTTCTATGTAACAAAAGTGAACCCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACAGGAGACTGAAGGAGTGCTTTTATTAGATCAAAACTGAT-CGGTGTGTTTTACGGC-CGGACGTTTTA----------------CGTACG--TG--TCCGTAG-GCCACCG-----------CAAGT--GAACTGGTGAATCTGAATAACTT-ATGCTGATCGCATGGTC-ACGTACCGGCGACGCATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATAGGGCATGGCTT----------GTATGAGATT---------------------------ATTAGTTTTC-TTGAA----ATGCT-TGCGT--------CCCAA-------GGTGCCCACTTGTT---GGTCACGGTTTTTACTACCGGCGTACAATTT-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCTGGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGG--CACG-TGGC-A----AT [...]
+
+	Trachypachus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCGGAGACGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CGGTCGCTT-------------------GCGAT--CG--TTC-----GCCGGCA-----------CA-------CTTGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGGTGTTAAGTT-------------------------------------------------ATGTACTTTA-GCGTG---TTTG---TACATT-------TCCG-----------TTTGTGGAGTT------TGTGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACCGG--TACG-CGAT-G----AC [...]
+
+	Systolosoma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--CGTTGCTTTA----------------CGGCTT---CG--TTC-----ACCGGCA-----------CA-----TT--TGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCCGCACGGTA--------------GTGTAC-C------------------------------TGTGCGGGT-GTGTGTGTTGTG---TGCGTGGCCGGCGGTGGTGT-----G--CTTGTGGAGTT------TGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGAATGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGAT-G----AC [...]
+
+	Metrius              TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTTTTTA-TAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCCAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGGCG------GCGA--CTATTGTTT--TA-------------TTACTTT--AG--TTCGTAC-GTCGCAA----------ATA------T--TGGTGACTCTGAGTAACTT-ATGCTGATCGTACGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGG-AATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATG---A-TGTTTCGTCTTAATTGACGTTCTTATAGTTGTACCGCTACCTATTCAAACACATTATGTT----GTTTG--TT-AG---TTCACT----GGGTTCTTGTCCGTGA--TCTGGGCGGTCT--GTTCACGGTTTTTACTACCGGCGTACACATA-AATCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTAATTCCTTGGCCGAAAGGTCCGGGTAAACCGTTGAATCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACCGG--CACC-CGGC-G----GT [...]
+
+	Pachyteles           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTTTTTA-TAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC-----ACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCTAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGACG------GCAT--TATTTATTTTTAATAA------------ATTAA--TG--TAC-----GTCGTTT-T---------TA------T--TGATGAATCTGAGTAACTT-ATGCAGATCGTATGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGACTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTCA---T-TACTAGTTGATGTTTAATATAGTTTTCTGCTTTCAATCTAATTTGTAAACATATTTCATT----GTTGT--TT-TG---TGTATATATAAGGGTTTGTTTTGTGA--TCTGGGCGGTCT--GTTCACGGTTTTTACTACCGGCGTACACATA-TATCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTATTTCCTTGGCCGAAAGGTCCGGGTAAACCGTTGAAACTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACTGG--CACC-CGAC-G----GT [...]
+
+	Scaphinotus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAAA--ATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTTC-------------GCGTTCGCG----CG--TTCA--C-GTCCACCGT---------CAA-----TAATGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGGG---TGTAC--------------CGTGCGTTTTGGCGTTTGGTCACA-----------CTCTCGTTCAT-TCGCG--TA-TA---TACATTACTACGGGCAA--------G--GC--GGGAGTT------CGTGGTTTTTACTACCGGCGTACAATTG-TATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGAATGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGCCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTTGGACTGG--CACG-CGGC-A----GC [...]
+
+	Nebria               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---ATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACACGCAAACAGAGCTCCGACCAGAGATGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGG-CAGGCACTGC-----------------TGTC----TG--TTC-----GTCGCCC-----------TA-------TTTGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CATA-------------------------------------------------------------CACTGTGCGAGCATTTTGCGGC-TTCGT--------GCGG-----------GC-GGAATGTT-------GTGGTTTTTACTACCGGCGTACATTTT-AATCTTCTTAGAGGGACAAACGGCTTATAGCCGTATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAACTCGTGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACT-CGGCCG----GG [...]
+
+	Loricera             TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAG---CTAAA---ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGACCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTAGA-C--GGGTCCGTTACGG-----CG-----GTCTC--CG--TTT-----ATCGTACAC---------CA-------AATGGTGACTCTGAATAACTTT-TGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTG---CCTGT---------------ATGA--------------------------------TGTGTT----CTG-------TG---TGCGT--------TATGTT----------C--GGTGGTT------CATGGTTTTTACTACCGGCGTACATATG-AATCTTCTTAGAGGGACAGGCGACTTCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTTGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATTATTTAGTGAGGTCTTCAGACTGG--CACC-CGGT-G----GC [...]
+
+	Elaphrus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAGCCAAT-CG--GC-----GTC---T--GGGTTC-------------------GCC----CG--TTC-----GCCGCCC-T---------CA------T--TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ACGG---C-GGT-------------GCATGT------------GCGT------------------TGTT----ACTGG--CG-TG---CGCGG-------G----------------C--GGGAGTT------CGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTCTTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATTAACTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGAT-G----GT [...]
+
+	Antarctonomus        TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CTAAA---ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTTCGTTTCGG---------------CGTTCTC-CG--TTC-----GTCGCAC-----------TG-------TTTGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-GAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTG-----------------------------------------------------------CCTGTT-----CA--------G---TACGTT------GTCCG---------------GGGCGTTA--GTTCACGGTTTTTACTACCGGCGTACATATG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACG-CGGC-G----GC [...]
+
+	Omophron             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACTGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGT--C--GGGTTCCGT--------TTACGCGGGCT----CG--TTC-----GTCGCCC-----------TA------T-TTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATGAAATGTGTAATGGTAGCAATACTATTGCATATGATTATCAAGTGTAGGTCTATA---TATCCACTGCA-TTAGT--TT-TG---GCCAT-------GTTTA---C----G--GTACGAGTGTT------CGCGGTTTTTACTACCGGCGTACAATTA-AATCTTCTTAGAGGGACAGGTGGCGCTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGTGG----AA [...]
+
+	Pasimachus           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACATA---CTATA---ATAAAGTAAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCATTAGATCGTACCACTATAAGTTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAATTCTGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACTAAT-CG---------ATGT--CG-GAATTTT-T-----------------TTTC--CG--TTT-----ATCGTAAAT-----TTTTTA------TG-TGGTGAATCTGAATAACTTT-TGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ATCAATTCACTTTA-------------ATTTGTTTTGGTGTTATTGTTGTTTCTATTGTTAAATGAGTTGTT-GTGAAACCT-TG---ACCGGT----GTATCCAATTCATTGG--TC--GAATGTA----TGTGTTGTTTTTACTACCGGCGTACATTAA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGACTCAACGTGTC-CTCCCTGACCGAATGGTCCGGGTAACCCGTTGAAACTCCTTCGTGATTGGGATTGGGGATTGCAATTTTTCCCCATGAACGAGGAATTCCAAGTAAACGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGG--TACCACGGC-G----AT [...]
+
+	Clivinini            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACTAAT-CG---------GCGA--CGGTGACTCTTTTTAA-----GGGTTTTAT-----CG--TTC-----GTCGTTC-T--------ATA------T---GGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGTACCGGCGACATATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+AGGG---T-TAC-------------GCATGTTTC-----------------------------TCTGCT----GCG-------TG---CGCGT-------GTTTG--------G--TC--GGATGTT----TGTGCGGTTTTTACTACCGGCGTACAATTA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTT-TTCCCTGGCCGAATAGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATGTAGTGAGGTCTTCAGACTGG--TACG-CGGC-G----GT [...]
+
+	Dyschirius           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CGGTGTTTC------------------GGC-AT--CG--TTT-----GTCGTCC-----------TA-------TTTGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TCGTACCGGCGATGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTCG-------------------G---GTGG---------------------------------ATGATGG--GCA-----T-CG---GCCGTAT------GCCGG----------TC--GGAAGTT----TGTGTGGTTTTTACTACCGGCGTACAATTA-ATTCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGTGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGCGG----TA [...]
+
+	Creobius             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CTAAA---CTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATTGTACCACA-AAAATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTTTAACCAGAGATGGAAAAAGTGCTTTTATTTGAACAAAACCAAT-CG---------GTGA--C--GTGTTTC----------------CAGTTTAC-TGGTTTCACATAATCACTG----------AAA-----TTTATGATGAGTCTGAATAACTTTTTGCTGATCGCATGGTC-TTGCACCGGCGACGTATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATTTGCGCCTACCATGGTTGTTACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ATTG-----------------------------------------------------------CGTATTG---GTGCCTTCCATTGAACACGT-------AACCACG---------GTGCAAGAGTT------TGCGGTTTTTACTACCGGCGTACATATA-TATCTTCTTAGAGGGACAGGCGTCTTCCAGACGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCTGGCCGAAAGGTCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGCTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACA-CGAT-G----GT [...]
+
+	Bembidion            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGTC-AGTACGTTTCG---G------------CGTTAC--TG--TTC-----GTCGCAC-T-----------------TTTTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TAGG-----CG----------------GTG---------------------------------TGCGTC----GCACG------G---GGTAT-------GTTCA--------G---TGCGGGAGTT------CACGGTTTTTACTACCGGCGTACATATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTT-TTCCCTGGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGC-G----GC [...]
+
+	Psydrus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CG-GTGTCTT-----------------TGCGATGCCG--TTC-----GTCGCAT-----------TG------T-TTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCTG------------------------------------------------------------TGGTCATCTGCGTGCATGTCG----GTATT------GTTGG-----------CC--GAGATTT------CGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGTGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGA--TACA-CGGCTC----GT [...]
+
+	Mecyclothorax        TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACCA---CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCAGAGATGGGAGGAGTGCTTTTATTAGATCAAAACCAAA-CGGCA------GCAGT-CATTACTTTCGGGTG-----------TGGCT-G--TG--TTT-----GTCGATTTT--------ATG-------ATTGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ACTA---TTTGT-------------ACTTGTGCAAATGTGTGCGG------------------TTTGCT----GCGGG---T-CG---GGTGT-------GTTGTATGGGTGGC--TCTGGAATGATG--TTGTTGGGTTTTTACTACCGGCGTATATATACAATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTTTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGG--TACT-CGGT-G----AT [...]
+
+	Agonum               TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTATA---TTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACCACA--ACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG--GC-----ATCGG-TAACATTTCGGT--G-----------TTATC----CG--TTT-----GTCGCTC-------AATATA---------TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-----TGT---------------ATAT--C-----------------------------CTCATTGGT-TTG-------TG---CTTGT-------GGTTGG-----------TTTAGGAGTT------TGTGGTTTTTACTACTGGCGTACATATA-TATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGG--------- [...]
+
+	Chlaenius            TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTATA---TTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGG--TAACGTTTC-------------GGCGTTAT-----CG--TTC-----GTCGCTC---------AATA------AA-TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------TGTT----TCA-G--TT-GG---TGTGT-------GGTGG-----------AC--AGGAGTT------TGTGGTTTTTACTACTAGCGTACATATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGT-G----GT [...]
+
+	Haliplus_laminatus   TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGGCACGACTGTTTA------------------ACGACGGCGCGTCC-----GCCGAAG------------A------AACTGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------CGTT-----CGT------CGGT-CGCGTG------GCCTTAG---------TC--GCGGGTT-----GCG-GGTTTTTACTGCCGGCGTACATA-ATAATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGGTTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Haliplus_ruficollis  TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGGCACGACTGTTTAACG------------ACGGCG----CG--TCC-----GCCGAAG------------A------AACTGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCGG----------------------GTG---------------------------------TCGGCTCTCGGCGGTAGTCGTG---CGCGT-------GTCCGC------AG--TC---GCGGTT-----GCG-AGTTTTTACTGCCGGCGTACATA-ATAATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACACGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTG-TAGGGGATGGGGCTTGCAATG--TCCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Copelatus            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTGCGTTC-------------------GCGCATCCG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------CGTTT---GCGCGCGCCTCG---TTCGT--------CCGG-----------TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Cybister             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGG--C--GTGTTCGTT-------------CGCGTTCA--CG--TTC-----GCCGCCC------------A------ACTTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGCG-----------------------------------------------------------CGCGCT----CCG----TT-CG---TTTGT-----------------------TC--GGTTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGACCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACG-CGGC-G----AG [...]
+
+	Hydroporus           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCCGA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCG------GCGGG-C--GCGTTCG-----------------CGCGTC--CG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCCGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGTCCGC-GCGCG-CCC-CG---TCCGT---------CCG--------G--TC--GGGAGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Laccophilus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCT---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGG-C--GAGTTCGCT---------------CGTC----CG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG------------------------------------------------------------CGGTT----GCGCG-CTCCCG---TCCGT---------CCG--------G--TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATT-TATCTTCTTAGAGGGACAGGCGGCTCCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Neoporus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGCGCGTCC-------------------GCGCGTCCG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTAGGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG------------------------------------------------------------CGGTT----GCGCG-CTCCCG---TCCGT--------CCGG-----------TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Gyrinus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACGAG---CCGCA---TCAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGCAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGCCCGTTCACG--------------CGGCGTC--CG--TCC-----GTCGTCC----------TCA--------CTGGTGACTCTGAATAACTCTATGCCGATCGCACGGTC-TCGCACCGGCGACGCGTCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG-----------------------------------------------------------TGTACCTCCGGC--------CG---TGCGT--------CCGG-----------CC--GTCCGTT------CGCGGTTTTTACTACCGGCGTTCAATGA-TATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+	Spanglerogyrus       TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGG-C--CCGTTC-------------------GCGCG--GG--TCCTACC-GTCGTAC-----------TG-----GC--TGGTGACTCTGAATAACTTGACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCAGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG-------------------------------------------------------------CGTCCC--GCACG-----TG---ACCGT-----------------------------GCGTT------CGCGGTTTTTACTACCGGCGTACACATA-ATTCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGGGTCAGCGTGTCCTCCCTTGGCCGAGCGGCCCGGGTAACCCGCTGAACTCCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+	Hygrobius            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCTAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTGCGTCC-------------------GCGTGCCCG--TTC-----GCCGCTC------------A-----AC-TTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGCTT---GCGCGCGCCCCG---TCCGT--------CCGG-----------TC--GGGCGTT------CGCGGTTTTTACTGCCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AA [...]
+
+	Hydrocanthus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGTC-GGTCCGTTCT-----------------CGCGGAT-CG--TTC-----GTCGCAT----------TCA--------CTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATCGCAGCCGTACGTGCCG----TCGT--------TCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGG--TATG-CGGC-G----GG [...]
+
+	Noterus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGATCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGT-C---GGTTCG-----------------CGC-----CG--GTCGT-C-GTCGCTC------------------TCGCTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATC----GCAGC-----CG---TACGTGCCGTCGTTCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGG--TATG-CGGC-G----GG [...]
+
+	Suphis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGC-GGTCCGTTCA-----------------CGCGGTC-CG--TTC-----GTCGCAT----------TCA--------CTGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATCGCAGCCGTACGTGCCG----TCGT--------TCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCGGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATACCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTT-------------------------------------- [...]
+
+	Bruchela             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTTC-------------------GC----------TC-----GTCATCG-T--------ACA----ACT--TGGTGACTCTGAATAACTTTGTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+------------------------------------------------------------------GTT----TCG--------G---CTC-------------------------CT--TGTCGC------GCGCGGTTTCTACTGTCGGCGTACAAACA-ATTCTTCTTAGAGGGACAGGCGGCT-CTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCAGGCCGAGTGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--CTCG-CGAT-G----GC [...]
+
+	Tenebrio             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAAACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGTCTC--------------------------CG---TC-----ATCGTAC------------A-----AC-TTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG--------------------------------------------------------------GTT--------------CG---CTCG------------GT--------------GACCGT------GCGCGGTTTTTACTGTCGGCGTACAAACA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGAACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Helochares           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--CGGGCGTTTG-----------------CGCGCT--CG---TC-----ATCGTAC------------A------TTTTGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-----------------------------------------------------------TGTGTC---------------G---GTGAC----------------------------GGTGTC---GCGCGCGGTTTTTACTGTCGGCGTACAATCA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGAGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Dynastes             TTGTCTCAAAGAT-AAGCCATGCATGTCTCAGTACGAG---CCGTA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGTTCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTCT------------------TACT----CG---TC-----ATCGTAC------------A------CCTTGGTGACTCTGAATAACTTCTTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGTT-------------------CTCGT------------------------CGCGGCCGT------GCGCGGTTTTTACTGTCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCGTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG-CGGTTGCGTTAA [...]
+
+	Cyphon               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACAT-TACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GCGC--C--GATTTC---------------------------G--GTCG----GTCGTCG-T--------ACA------TCTTGGTGAATCTGAATAACTTT--GCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+------------------------------------------------------------------GTT----GTA------------TTC-----------------------------GGTTGC------GCTTACTTTTTACTGCCGGCGTACAAGCA-GTTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCTAGCCCGAGAGGGCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CCGC-G----GC [...]
+
+	Clambus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCATA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA----CACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCTGAACCGGAGACGGAACGGACGCTTTTATTAGATCAAAACCAAT-CG---------GCAA--TGAGTATTT------------------TACT----TA--TT------GTCGTAT-----------TA-----TT--TGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------TATT-------------------GTTAT------------------------------TGT------GCGTAGTTTTTACTGCCGGCGTACATTAA-ATTCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTATGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Hydroscapha          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACTGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CG---------GCGG--CGGGAGTTTAAC---------------GACTTT--CG--TCC-----GCCGTTT-----------TA-------ATTGGCGAGTCTGAATAACTTTTTGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGGG------------------------------------------------------------CAACCGGGTGCGTGTTCGTTGC--CATATCG-----GTTTGTTAATG-GTCGCCCTCGCTGCT----TGTCCGGCTTTTACTACCGGCGTACACTAA-ATTCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGTCCGAAAGGACCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG-CGGT-G----AC [...]
+
+	Torridincola         ---------------------------------ACAAA---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CGGTGTGC---GCGTGTCGTCCGTACGCG---------------GGCGGC--CG---TC-----GCCACCG----------CTA-----ATCATGATGAATCTGAATAACTTTTTGCTGATCGCACGGTC-CAGAACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGGCACGGCG----------------------------------------------------CATGTTCGGTTCACG---CAAGCCTCCCGTGC------CCCG------------TAACGCCGTCATTGTCCGCGGTTTTTACTACCGGCGTAC-TGCAAATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-ATCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG------------- [...]
+
+	Distocupes           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCACACA-GGAAGGGATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGC-GGCGTGTTTTA----------------CGCGCGTCCG--TTT-----GCCGTTC------------A-----ACTCTGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG------------------------------------------------------------CTGTCG---CCGC------CG---CTCGT-------GCCGGC----------CC---GGTGTC---GCGCGCGGTTTTTACTACCGGCGTACAATTT-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTTTTCGGACTGG--TGCG-CGGC-G----GC [...]
+
+	Sialis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAGGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC-----CCAGTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGACGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GCGTCGCGA---------------AGCG-G--CG--TTCGCAC-ACCGTAC-----------GA-----CC--TGGTGACTCTGAATAACTTTCAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+GCGGCGGTTTCGGCC----------GTGCGTGCGTGTCGGCGTGTACGTTCACCGTGCGGTGTGATGTCGGGCGTGCG-----CG---CGCGTGT-----GTTGGC----GCGC--GTTCGTGCGTCGCGGCGTGTGGTTTTTACTACCGGCGTACAAATA-TATCTTCTTAGAGGGACAGGCGGTAACTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAATCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TGCG-TGAC-G----AT [...]
+
+	Anisochrysa          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GTGT-----AAATTTT-------------------CA-----A--TTTG--C-ATCGTTT------------A------ATTTGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTTGAGATTTA----------------ACGATCAAGATT----ATAT----------------TTTGTATATATTGTGCTTTATGT--TGCATAT-----GTTATGGTGTATGG--GTA-CGCAGTTTTTTGATGTGGTTTTTACTGCCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCAGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGC-A----AT [...]
+
+	Oliarces             TTGTTTCAAAGAATAAGCCATGCATGTCTCAGTACAAG---CCATA---TTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGATGTG----GCTATATGCCCGTTCTGTG-------------GTATATT--TG--TTG---C-ATCGTTT------------A------ATTTGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+GTTGTGTGTTGTTTTCACAAT----GCACGCACACTTACACTACTCTACACTTCTTGAACATATATCTTGTGTGTATGTTTTATGTT-TGCAT-------GTAGACACGTGCGG--GC--CACAGTTTTTTGGTGTGGTTTTTACTGCCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGTCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTATTGAGGTCTTCGGACTGG--TACG-CGGCAACGTCAC [...]
+
+	Phaeostigma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAAGGTGAAACGGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGGTG------GCGGC-GGTGCGTTCG-----------------CGCGTGC-CG--TTCGTTC-GCCGTCT------------A------TTTTGATGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGCGGG---------------------------------------------------------CGTACGGCACGTGCGCTCGACGT--TTCGTTCCGTGTGCCTGTC---------GCCGCGGTGTC----GGTGCGGTTTTTACTACCGGCGTGATTTTA-ACTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGTCGAAAGATCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+
+;
+
+
+		BLOCKID WM114cbd0d0c60;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "01-modelTree.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Omus,
+		2 Oxycheila,
+		3 Clinidium,
+		4 Omoglymmius,
+		5 Trachypachus,
+		6 Systolosoma,
+		7 Metrius,
+		8 Pachyteles,
+		9 Scaphinotus,
+		10 Nebria,
+		11 Loricera,
+		12 Elaphrus,
+		13 Antarctonomus,
+		14 Omophron,
+		15 Pasimachus,
+		16 Clivinini,
+		17 Dyschirius,
+		18 Creobius,
+		19 Bembidion,
+		20 Psydrus,
+		21 Mecyclothorax,
+		22 Agonum,
+		23 Chlaenius,
+		24 Haliplus_laminatus,
+		25 Haliplus_ruficollis,
+		26 Copelatus,
+		27 Cybister,
+		28 Hydroporus,
+		29 Laccophilus,
+		30 Neoporus,
+		31 Gyrinus,
+		32 Spanglerogyrus,
+		33 Hygrobius,
+		34 Hydrocanthus,
+		35 Noterus,
+		36 Suphis,
+		37 Bruchela,
+		38 Tenebrio,
+		39 Helochares,
+		40 Dynastes,
+		41 Cyphon,
+		42 Clambus,
+		43 Hydroscapha,
+		44 Torridincola,
+		45 Distocupes,
+		46 Sialis,
+		47 Anisochrysa,
+		48 Oliarces,
+		49 Phaeostigma;
+	TREE model_tree = (((((((((((1:0.019807,2:0.048887):0.068362,(((((3:0.035589,4:0.020202):0.126366,15:0.131641):0.005995,(7:0.020804,8:0.02306):0.047065):0.009431,(22:0.016178,23:0.008502):0.01947):0.003527,21:0.058138):0.007428):0.003257,(11:0.059574,18:0.06156):0.012893):0.00864,13:0.012588):0.008196,(((9:0.029557,10:0.044205):0.001834,(12:0.037896,(14:0.036211,19:0.033253):0.007177,20:0.041281):0.010022):0.002728,(16:0.030509,17:0.020178):0.014379):0.001601):0.004095,((24:0.004012,25: [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  =  N:  1- 2543 ;
+	CODONPOSSET CodonPositions  =  N:  1- 2543 ;
+
+	CODESET * UNTITLED   =  universal:  1 -  2543;
+
+
+END;
+
+begin paup;
+	outgroup PhaeosOUT;
+	set torder =                            right tcompress;
+	taxset dytiscidae =                             CopelaDYT CybistDYT HydropDYT LaccopDYT NeoporDYT;
+	taxset gyrinidae =                             GyrgyrGYR SpanglGYR;
+	taxset noteridae =                             HydrocNOT NoteruNOT  SuphisNOT;
+	constraint coleomono = (                            SialisOUT ,                            AnisocOUT ,                            OliarcOUT ,                            PhaeosOUT , (                            OmusCIC -                            DistocARC ) );
+	constraint  adephmono = (                            SialisOUT ,                             AnisocOUT ,                             OliarcOUT ,                             PhaeosOUT ,                             DistocARC ,                             TorridMYX ,                             HydrosMYX ,                             ClambuPOL ,                             CyphonPOL ,                             DynastPOL ,                             HelochPOL ,                            [...]
+	constraint  carabmono (                            backbone ) = ( (                            MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                             ElaphrELA ,                             AntarcMIG ,                             OmophrOMO ,                             PasimaSCA ,                             ScaritSCA ,                          [...]
+	constraint  beutel = (                            PhaeosOUT ,                             OliarcOUT ,                             AnisocOUT ,                             SialisOUT ,                             DistocARC ,                             TorridMYX ,                             HydrosMYX ,                             ClambuPOL ,                             CyphonPOL ,                             DynastPOL ,                             HelochPOL ,                             T [...]
+	constraint hydradeph = (                            OmusCIC -                            ChlaenCHL ,                            BruchePOL -                            PhaeosOUT , (                            HaliprHAL ,                            HaliplHAL ,                            dytiscidae ,                             noteridae ,                             HygrobHYG ,                            gyrinidae ) );
+	constraint trachdytisc = (                            OmusCIC -                            OmoglyRHY ,                            MetriuPAU -                            HaliprHAL ,                            BruchePOL -                            PhaeosOUT , (                            TrachyTRA ,                            SystolTRA ,                            dytiscidae ,                             noteridae ,                             HygrobHYG ) );
+	constraint  adephHydmono = ( (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             TrachyTRA ,                             SystolTRA ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                         [...]
+	constraint  hydraPoly = (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             TrachyTRA ,                             SystolTRA ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                              [...]
+	constraint  strong = (                            PhaeosOUT , (                            OmusCIC ,                             OxycheCIC ) , (                            ClinidRHY ,                             OmoglyRHY ) ,                             TrachyTRA ,                             SystolTRA , (                            MetriuPAU ,                             PachytPAU ) ,                             ScaphiCYC ,                             NebriaNEB ,                        [...]
+	constraint  GeadHydAdeph = ( ( (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                             ElaphrELA ,                             AntarcMIG ,                       [...]
+	constraint  TrachHydAdeph = ( ( (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                             ElaphrELA ,                             AntarcMIG ,                      [...]
+	constraint  THback (                            backbone ) = ( ( (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                             ElaphrELA ,                             [...]
+	constraint  THB2 (                            backbone ) = ( (                            OmusCIC ,                             OxycheCIC ,                             ClinidRHY ,                             OmoglyRHY ,                             MetriuPAU ,                             PachytPAU ,                             ScaphiCYC ,                             NebriaNEB ,                             LoriceLOR ,                             ElaphrELA ,                             Ant [...]
+	lset nst =                            6 rmatrix = (                            1.8516775 4.2080535 2.4489583 0.6302258 8.5377063 )                             shape =                            0.452070 pinvar =                            0.512218 rates =                            gamma basefreq =                            empirical;
+
+END;
+BEGIN MacClade;
+	Version 3.5  13;
+	LastModified -1288801818;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 100;
+	Editor 00001000111111 '24'                             Geneva '9' '100' '1'                             all;
+	OtherSymbols & /                             00 ? -;
+	ListWindow Characters closed Geneva '9';
+	ListWindow Taxa closed Geneva '9'                             1;
+	ListWindow Trees closed Geneva '9';
+	ListWindow TypeSets closed Geneva '9';
+	ListWindow WtSets closed Geneva '9';
+	ListWindow ExSets closed Geneva '9';
+	ListWindow CharSets closed Geneva '9';
+	ListWindow TaxSets closed Geneva '9';
+	ListWindow NexusBlocks closed Geneva '9';
+	StateNamesSymbols closed Geneva '9';
+	Correlation 10011010 '0' '0' '1000' '0' '0';
+	Salmo 0000001;
+	EditorFile '2';
+	TreeWindow 0000;
+	Continuous '0' '3'                             1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                            0;
+	Charts  Geneva '9' (                            normal )                             0010;
+	NexusOptions '0' '0' '50'                             001011001;
+	ChartFont  Geneva '9' (                            normal );
+	TipLabel  Geneva '9' (                            normal ) '1';
+	TreeShape  1.0 1.0 000;
+	TraceLabels 0101;
+	ChartColors '0' '0' '-1' '9'                             11;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                             1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'                             000011;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                             1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                             Geneva '9' (                            normal )                             Geneva '10' (                            normal )                             Geneva '9' (                            normal )                             Geneva '9' (                            normal )                             Geneva '9' (                            bold )                             Geneva '9' (       [...]
+	MatchChar 00 .;
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                            unord PolyTcount =                            MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2543;
+
+	EXSET * UNTITLED  =  105 -  110 212 -  220 225 -  229 236 -  266 268 -  273 281 -  302 777 -  1180 1209 -  1213 1259 -  1294 1860 -  1869 1872 -  1877 1881 -  1889 1900 -  1923 1926 -  2066 2070 -  2088 2092 -  2123 2127 -  2134;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2543;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7662907117210050989 WM114cbd0cfc02;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1994580233913892502 WM114cbd0d0c60;
+			checksum 0 1120043444 WM114cbd0d0c60;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 897 464;
+			setLocation 4 473;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7662907117210050989  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 440.990719884171.298610461924319084;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 629 457;
+					setLocation 614 30;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 4;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((((((((((1:0.019807,2:0.048887):0.068362,(((((3:0.035589,4:0.020202):0.126366,15:0.131641):0.005995,(7:0.020804,8:0.02306):0.047065):0.009431,(22:0.016178,23:0.008502):0.01947):0.003527,21:0.058138):0.007428):0.003257,(11:0.059574,18:0.06156):0.012893):0.00864,13:0.012588):0.008196,(((9:0.029557,10:0.044205):0.001834,(12:0.037896,(14:0.036211,19:0.033253):0.007177,20:0.041281):0.010022):0.002728,(16:0.030509,17:0.020178):0.014379):0.001601):0.004095,((24:0.004012,25:0.007 [...]
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1994580233913892502 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 636 407;
+					setLocation 4 473;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-gammaTest.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 591 386;
+					setLocation 3 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This file illustrates the basics of simulation.^n^nA model tree, with branch lengths, is already stored in this file, and is displayed.  You need to add a model of character evolution.^n^nThe model we will build is a very simple one: we will presume that data are DNA sequences, with equal frequences of A,C,G, and T, and that the rate of change between these bases is equal for all kinds of change.  However, we will presume that the characters vary in their rate, follow [...]
+				setTitle A_simple_simulation_of_DNA;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Character_Simulations/02-gammaTest.nex b/Resources/examples/Character_Simulations/02-gammaTest.nex
new file mode 100755
index 0000000..2d9c4c0
--- /dev/null
+++ b/Resources/examples/Character_Simulations/02-gammaTest.nex
@@ -0,0 +1,569 @@
+#NEXUS
+[written Sun Jun 08 13:13:29 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=49;
+	TAXLABELS
+		Omus Oxycheila Clinidium Omoglymmius Trachypachus Systolosoma Metrius Pachyteles Scaphinotus Nebria Loricera Elaphrus Antarctonomus Omophron Pasimachus Clivinini Dyschirius Creobius Bembidion Psydrus Mecyclothorax Agonum Chlaenius Haliplus_laminatus Haliplus_ruficollis Copelatus Cybister Hydroporus Laccophilus Neoporus Gyrinus Spanglerogyrus Hygrobius Hydrocanthus Noterus Suphis Bruchela Tenebrio Helochares Dynastes Cyphon Clambus Hydroscapha Torridincola Distocupes Sialis Anisochrysa  [...]
+	;
+	BLOCKID WM114cbd225743;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-gammaTest.nex"';
+	DIMENSIONS  NCHAR=2543;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Omus                 TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAAA--TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACATATACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGC-----GTCC--C--GGGCTCCATATGATTCTGTACCTTTGCGTA--CG--TTCATGT-GTCCTGG-TGTGCGTTCACACAT-ATTACTGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAACGGCT [...]
+TGTG---C-GGT-------------ACGTGTTATGCACTTTGTGTATTACCTCCGTGCCGTCATTTGTT----TCGTA--CT-TG---CTCGT-------GTCGG-CAACGATA--CT--GGTTGTTT--GTGGGCGATCTTTACTACCGGCGTACACATA-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCATGTC-CTCCCTGGCCGAGAGGTCCGGGTAATCCGGTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCCGACCGGTACTC--CGAC-G----AC [...]
+
+	Oxycheila            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CTTAA---TGAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTAC------AAAGTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCGTACCGGAGACGGAATGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGC-----ATCC--CTAAGGCTCCATATGATTCTGTGTCTTTGCACA--CG--TTCATAT-GTCCTGGGTGTATGTTCATATTTTTTTATTGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAACGGCT [...]
+TTTG---A-TGT-------------ATATAATACTTGTTAT-TGTATATATTTGG-------ATGTGTT----TTA----CT-TG---TTTGC-------GTCGAATAATGTAA--CT--AGTTGTTT--GTTGGCAATCTTTACTACCGGCGTATATTTG-TATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCTGTTCGAGAGAACCGGGTAATCCGTTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATAAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACT-CGGCCG----AT [...]
+
+	Clinidium            TCGTCTCAAAGATTAGGCCACGCATGTCTAAGTACAGCTTTCTATGTA-ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGGAGGAGTGCTTTTATTAGAACAAAACTGAT-CG---------GTGTTTCGTCTATTT------------------TATAGG--CG--TGC-----ATCGCAAGT---------GA-----AC--TGGTGAATCTGAATAACTTT-TGCTGATCGCATAGTCATAGCACTAGCGACAAATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTTGATTTCCT--------------CACGGGGTTGAT------------------------AAGTGTTCGGCTCGTATGAGGTGGTTAGTACTTGGAATGCTGGGGTCCCTCAGTGCCCACTTGTT---GGTCACGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCTGGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGG--CACG-TGGC-A----AT [...]
+
+	Omoglymmius          -----------------CCATGCATGTCTAAGTACAGCTTTCTATGTAACAAAAGTGAACCCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACAGGAGACTGAAGGAGTGCTTTTATTAGATCAAAACTGAT-CGGTGTGTTTTACGGC-CGGACGTTTTA----------------CGTACG--TG--TCCGTAG-GCCACCG-----------CAAGT--GAACTGGTGAATCTGAATAACTT-ATGCTGATCGCATGGTC-ACGTACCGGCGACGCATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATAGGGCATGGCTT----------GTATGAGATT---------------------------ATTAGTTTTC-TTGAA----ATGCT-TGCGT--------CCCAA-------GGTGCCCACTTGTT---GGTCACGGTTTTTACTACCGGCGTACAATTT-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCTGGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGG--CACG-TGGC-A----AT [...]
+
+	Trachypachus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCGGAGACGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CGGTCGCTT-------------------GCGAT--CG--TTC-----GCCGGCA-----------CA-------CTTGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGGTGTTAAGTT-------------------------------------------------ATGTACTTTA-GCGTG---TTTG---TACATT-------TCCG-----------TTTGTGGAGTT------TGTGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACCGG--TACG-CGAT-G----AC [...]
+
+	Systolosoma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--CGTTGCTTTA----------------CGGCTT---CG--TTC-----ACCGGCA-----------CA-----TT--TGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCCGCACGGTA--------------GTGTAC-C------------------------------TGTGCGGGT-GTGTGTGTTGTG---TGCGTGGCCGGCGGTGGTGT-----G--CTTGTGGAGTT------TGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGAATGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGAT-G----AC [...]
+
+	Metrius              TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTTTTTA-TAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCCAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGGCG------GCGA--CTATTGTTT--TA-------------TTACTTT--AG--TTCGTAC-GTCGCAA----------ATA------T--TGGTGACTCTGAGTAACTT-ATGCTGATCGTACGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGG-AATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATG---A-TGTTTCGTCTTAATTGACGTTCTTATAGTTGTACCGCTACCTATTCAAACACATTATGTT----GTTTG--TT-AG---TTCACT----GGGTTCTTGTCCGTGA--TCTGGGCGGTCT--GTTCACGGTTTTTACTACCGGCGTACACATA-AATCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTAATTCCTTGGCCGAAAGGTCCGGGTAAACCGTTGAATCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACCGG--CACC-CGGC-G----GT [...]
+
+	Pachyteles           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTTTTTA-TAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC-----ACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCTAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGACG------GCAT--TATTTATTTTTAATAA------------ATTAA--TG--TAC-----GTCGTTT-T---------TA------T--TGATGAATCTGAGTAACTT-ATGCAGATCGTATGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGACTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTCA---T-TACTAGTTGATGTTTAATATAGTTTTCTGCTTTCAATCTAATTTGTAAACATATTTCATT----GTTGT--TT-TG---TGTATATATAAGGGTTTGTTTTGTGA--TCTGGGCGGTCT--GTTCACGGTTTTTACTACCGGCGTACACATA-TATCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTATTTCCTTGGCCGAAAGGTCCGGGTAAACCGTTGAAACTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACTGG--CACC-CGAC-G----GT [...]
+
+	Scaphinotus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAAA--ATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTTC-------------GCGTTCGCG----CG--TTCA--C-GTCCACCGT---------CAA-----TAATGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGGG---TGTAC--------------CGTGCGTTTTGGCGTTTGGTCACA-----------CTCTCGTTCAT-TCGCG--TA-TA---TACATTACTACGGGCAA--------G--GC--GGGAGTT------CGTGGTTTTTACTACCGGCGTACAATTG-TATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGAATGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGCCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTTGGACTGG--CACG-CGGC-A----GC [...]
+
+	Nebria               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---ATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACACGCAAACAGAGCTCCGACCAGAGATGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGG-CAGGCACTGC-----------------TGTC----TG--TTC-----GTCGCCC-----------TA-------TTTGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CATA-------------------------------------------------------------CACTGTGCGAGCATTTTGCGGC-TTCGT--------GCGG-----------GC-GGAATGTT-------GTGGTTTTTACTACCGGCGTACATTTT-AATCTTCTTAGAGGGACAAACGGCTTATAGCCGTATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAACTCGTGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACT-CGGCCG----GG [...]
+
+	Loricera             TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAG---CTAAA---ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGACCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTAGA-C--GGGTCCGTTACGG-----CG-----GTCTC--CG--TTT-----ATCGTACAC---------CA-------AATGGTGACTCTGAATAACTTT-TGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTG---CCTGT---------------ATGA--------------------------------TGTGTT----CTG-------TG---TGCGT--------TATGTT----------C--GGTGGTT------CATGGTTTTTACTACCGGCGTACATATG-AATCTTCTTAGAGGGACAGGCGACTTCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTTGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATTATTTAGTGAGGTCTTCAGACTGG--CACC-CGGT-G----GC [...]
+
+	Elaphrus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAGCCAAT-CG--GC-----GTC---T--GGGTTC-------------------GCC----CG--TTC-----GCCGCCC-T---------CA------T--TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ACGG---C-GGT-------------GCATGT------------GCGT------------------TGTT----ACTGG--CG-TG---CGCGG-------G----------------C--GGGAGTT------CGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTCTTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATTAACTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGAT-G----GT [...]
+
+	Antarctonomus        TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CTAAA---ATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTTCGTTTCGG---------------CGTTCTC-CG--TTC-----GTCGCAC-----------TG-------TTTGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-GAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGTG-----------------------------------------------------------CCTGTT-----CA--------G---TACGTT------GTCCG---------------GGGCGTTA--GTTCACGGTTTTTACTACCGGCGTACATATG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACG-CGGC-G----GC [...]
+
+	Omophron             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACTGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGT--C--GGGTTCCGT--------TTACGCGGGCT----CG--TTC-----GTCGCCC-----------TA------T-TTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TATGAAATGTGTAATGGTAGCAATACTATTGCATATGATTATCAAGTGTAGGTCTATA---TATCCACTGCA-TTAGT--TT-TG---GCCAT-------GTTTA---C----G--GTACGAGTGTT------CGCGGTTTTTACTACCGGCGTACAATTA-AATCTTCTTAGAGGGACAGGTGGCGCTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGTGG----AA [...]
+
+	Pasimachus           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACATA---CTATA---ATAAAGTAAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCATTAGATCGTACCACTATAAGTTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAATTCTGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACTAAT-CG---------ATGT--CG-GAATTTT-T-----------------TTTC--CG--TTT-----ATCGTAAAT-----TTTTTA------TG-TGGTGAATCTGAATAACTTT-TGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ATCAATTCACTTTA-------------ATTTGTTTTGGTGTTATTGTTGTTTCTATTGTTAAATGAGTTGTT-GTGAAACCT-TG---ACCGGT----GTATCCAATTCATTGG--TC--GAATGTA----TGTGTTGTTTTTACTACCGGCGTACATTAA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGACTCAACGTGTC-CTCCCTGACCGAATGGTCCGGGTAACCCGTTGAAACTCCTTCGTGATTGGGATTGGGGATTGCAATTTTTCCCCATGAACGAGGAATTCCAAGTAAACGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGG--TACCACGGC-G----AT [...]
+
+	Clivinini            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACTAAT-CG---------GCGA--CGGTGACTCTTTTTAA-----GGGTTTTAT-----CG--TTC-----GTCGTTC-T--------ATA------T---GGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGTACCGGCGACATATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+AGGG---T-TAC-------------GCATGTTTC-----------------------------TCTGCT----GCG-------TG---CGCGT-------GTTTG--------G--TC--GGATGTT----TGTGCGGTTTTTACTACCGGCGTACAATTA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTT-TTCCCTGGCCGAATAGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATGTAGTGAGGTCTTCAGACTGG--TACG-CGGC-G----GT [...]
+
+	Dyschirius           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CGGTGTTTC------------------GGC-AT--CG--TTT-----GTCGTCC-----------TA-------TTTGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TCGTACCGGCGATGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTCG-------------------G---GTGG---------------------------------ATGATGG--GCA-----T-CG---GCCGTAT------GCCGG----------TC--GGAAGTT----TGTGTGGTTTTTACTACCGGCGTACAATTA-ATTCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGTGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGCGG----TA [...]
+
+	Creobius             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CTAAA---CTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATTGTACCACA-AAAATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTTTAACCAGAGATGGAAAAAGTGCTTTTATTTGAACAAAACCAAT-CG---------GTGA--C--GTGTTTC----------------CAGTTTAC-TGGTTTCACATAATCACTG----------AAA-----TTTATGATGAGTCTGAATAACTTTTTGCTGATCGCATGGTC-TTGCACCGGCGACGTATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATTTGCGCCTACCATGGTTGTTACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ATTG-----------------------------------------------------------CGTATTG---GTGCCTTCCATTGAACACGT-------AACCACG---------GTGCAAGAGTT------TGCGGTTTTTACTACCGGCGTACATATA-TATCTTCTTAGAGGGACAGGCGTCTTCCAGACGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCTGGCCGAAAGGTCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGCTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACA-CGAT-G----GT [...]
+
+	Bembidion            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGTC-AGTACGTTTCG---G------------CGTTAC--TG--TTC-----GTCGCAC-T-----------------TTTTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TAGG-----CG----------------GTG---------------------------------TGCGTC----GCACG------G---GGTAT-------GTTCA--------G---TGCGGGAGTT------CACGGTTTTTACTACCGGCGTACATATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTT-TTCCCTGGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGC-G----GC [...]
+
+	Psydrus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAA---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGG--CG-GTGTCTT-----------------TGCGATGCCG--TTC-----GTCGCAT-----------TG------T-TTGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCTG------------------------------------------------------------TGGTCATCTGCGTGCATGTCG----GTATT------GTTGG-----------CC--GAGATTT------CGCGGTTTTTACTACCGGCGTACAATTG-AATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGTGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCTGGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGA--TACA-CGGCTC----GT [...]
+
+	Mecyclothorax        TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACCA---CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCAGAGATGGGAGGAGTGCTTTTATTAGATCAAAACCAAA-CGGCA------GCAGT-CATTACTTTCGGGTG-----------TGGCT-G--TG--TTT-----GTCGATTTT--------ATG-------ATTGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+ACTA---TTTGT-------------ACTTGTGCAAATGTGTGCGG------------------TTTGCT----GCGGG---T-CG---GGTGT-------GTTGTATGGGTGGC--TCTGGAATGATG--TTGTTGGGTTTTTACTACCGGCGTATATATACAATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTTTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGG--TACT-CGGT-G----AT [...]
+
+	Agonum               TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTATA---TTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACCACA--ACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG--GC-----ATCGG-TAACATTTCGGT--G-----------TTATC----CG--TTT-----GTCGCTC-------AATATA---------TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-----TGT---------------ATAT--C-----------------------------CTCATTGGT-TTG-------TG---CTTGT-------GGTTGG-----------TTTAGGAGTT------TGTGGTTTTTACTACTGGCGTACATATA-TATCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGG--------- [...]
+
+	Chlaenius            TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAA---CTATA---TTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGG--TAACGTTTC-------------GGCGTTAT-----CG--TTC-----GTCGCTC---------AATA------AA-TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------TGTT----TCA-G--TT-GG---TGTGT-------GGTGG-----------AC--AGGAGTT------TGTGGTTTTTACTACTAGCGTACATATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGT-G----GT [...]
+
+	Haliplus_laminatus   TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGGCACGACTGTTTA------------------ACGACGGCGCGTCC-----GCCGAAG------------A------AACTGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------CGTT-----CGT------CGGT-CGCGTG------GCCTTAG---------TC--GCGGGTT-----GCG-GGTTTTTACTGCCGGCGTACATA-ATAATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGGTTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Haliplus_ruficollis  TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGGCACGACTGTTTAACG------------ACGGCG----CG--TCC-----GCCGAAG------------A------AACTGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCGG----------------------GTG---------------------------------TCGGCTCTCGGCGGTAGTCGTG---CGCGT-------GTCCGC------AG--TC---GCGGTT-----GCG-AGTTTTTACTGCCGGCGTACATA-ATAATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACACGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTG-TAGGGGATGGGGCTTGCAATG--TCCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Copelatus            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTGCGTTC-------------------GCGCATCCG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------CGTTT---GCGCGCGCCTCG---TTCGT--------CCGG-----------TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Cybister             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGAACAAAACCAAT-CG---------GCGG--C--GTGTTCGTT-------------CGCGTTCA--CG--TTC-----GCCGCCC------------A------ACTTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGCG-----------------------------------------------------------CGCGCT----CCG----TT-CG---TTTGT-----------------------TC--GGTTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGACCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--CACG-CGGC-G----AG [...]
+
+	Hydroporus           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCCGA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCG------GCGGG-C--GCGTTCG-----------------CGCGTC--CG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCCGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGTCCGC-GCGCG-CCC-CG---TCCGT---------CCG--------G--TC--GGGAGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Laccophilus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCT---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGG-C--GAGTTCGCT---------------CGTC----CG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG------------------------------------------------------------CGGTT----GCGCG-CTCCCG---TCCGT---------CCG--------G--TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATT-TATCTTCTTAGAGGGACAGGCGGCTCCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Neoporus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGCGCGTCC-------------------GCGCGTCCG--TTC-----GCCGCTC------------A-----AC-CTGGTGACTCTGAATAACTTTAGGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG------------------------------------------------------------CGGTT----GCGCG-CTCCCG---TCCGT--------CCGG-----------TC--GGGTGTT------CGCGGTTTTTACTGCCGGCGTACACATG-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AG [...]
+
+	Gyrinus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACGAG---CCGCA---TCAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGCAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGCCCGTTCACG--------------CGGCGTC--CG--TCC-----GTCGTCC----------TCA--------CTGGTGACTCTGAATAACTCTATGCCGATCGCACGGTC-TCGCACCGGCGACGCGTCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG-----------------------------------------------------------TGTACCTCCGGC--------CG---TGCGT--------CCGG-----------CC--GTCCGTT------CGCGGTTTTTACTACCGGCGTTCAATGA-TATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+	Spanglerogyrus       TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCACA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGG-C--CCGTTC-------------------GCGCG--GG--TCCTACC-GTCGTAC-----------TG-----GC--TGGTGACTCTGAATAACTTGACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCAGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG-------------------------------------------------------------CGTCCC--GCACG-----TG---ACCGT-----------------------------GCGTT------CGCGGTTTTTACTACCGGCGTACACATA-ATTCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGGGTCAGCGTGTCCTCCCTTGGCCGAGCGGCCCGGGTAACCCGCTGAACTCCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+	Hygrobius            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCTAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGCGGGTGCGTCC-------------------GCGTGCCCG--TTC-----GCCGCTC------------A-----AC-TTGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGCTT---GCGCGCGCCCCG---TCCGT--------CCGG-----------TC--GGGCGTT------CGCGGTTTTTACTGCCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----AA [...]
+
+	Hydrocanthus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGTC-GGTCCGTTCT-----------------CGCGGAT-CG--TTC-----GTCGCAT----------TCA--------CTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATCGCAGCCGTACGTGCCG----TCGT--------TCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGG--TATG-CGGC-G----GG [...]
+
+	Noterus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGATCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCG------GCGGT-C---GGTTCG-----------------CGC-----CG--GTCGT-C-GTCGCTC------------------TCGCTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATC----GCAGC-----CG---TACGTGCCGTCGTTCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGG--TATG-CGGC-G----GG [...]
+
+	Suphis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GCGGC-GGTCCGTTCA-----------------CGCGGTC-CG--TTC-----GTCGCAT----------TCA--------CTGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CACG----------------------------------------------------------CCGTATCGCAGCCGTACGTGCCG----TCGT--------TCCGCGTCCGCGG--TC--GGGCGTA------CGCGGTTTTTACTGTCGGCGTACACATT-AATCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCGGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATACCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTT-------------------------------------- [...]
+
+	Bruchela             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTTC-------------------GC----------TC-----GTCATCG-T--------ACA----ACT--TGGTGACTCTGAATAACTTTGTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+------------------------------------------------------------------GTT----TCG--------G---CTC-------------------------CT--TGTCGC------GCGCGGTTTCTACTGTCGGCGTACAAACA-ATTCTTCTTAGAGGGACAGGCGGCT-CTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCAGGCCGAGTGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--CTCG-CGAT-G----GC [...]
+
+	Tenebrio             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAAACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGTCTC--------------------------CG---TC-----ATCGTAC------------A-----AC-TTGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG--------------------------------------------------------------GTT--------------CG---CTCG------------GT--------------GACCGT------GCGCGGTTTTTACTGTCGGCGTACAAACA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGAACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGCGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Helochares           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--CGGGCGTTTG-----------------CGCGCT--CG---TC-----ATCGTAC------------A------TTTTGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-----------------------------------------------------------TGTGTC---------------G---GTGAC----------------------------GGTGTC---GCGCGCGGTTTTTACTGTCGGCGTACAATCA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAGAGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Dynastes             TTGTCTCAAAGAT-AAGCCATGCATGTCTCAGTACGAG---CCGTA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGTTCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GGGTCT------------------TACT----CG---TC-----ATCGTAC------------A------CCTTGGTGACTCTGAATAACTTCTTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CCGG-------------------------------------------------------------CGTT-------------------CTCGT------------------------CGCGGCCGT------GCGCGGTTTTTACTGTCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCGTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG-CGGTTGCGTTAA [...]
+
+	Cyphon               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACAT-TACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CG---------GCGC--C--GATTTC---------------------------G--GTCG----GTCGTCG-T--------ACA------TCTTGGTGAATCTGAATAACTTT--GCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+------------------------------------------------------------------GTT----GTA------------TTC-----------------------------GGTTGC------GCTTACTTTTTACTGCCGGCGTACAAGCA-GTTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCTAGCCCGAGAGGGCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CCGC-G----GC [...]
+
+	Clambus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCATA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA----CACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCTGAACCGGAGACGGAACGGACGCTTTTATTAGATCAAAACCAAT-CG---------GCAA--TGAGTATTT------------------TACT----TA--TT------GTCGTAT-----------TA-----TT--TGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGG-------------------------------------------------------------TATT-------------------GTTAT------------------------------TGT------GCGTAGTTTTTACTGCCGGCGTACATTAA-ATTCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTATGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGT-G----GC [...]
+
+	Hydroscapha          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACTGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CG---------GCGG--CGGGAGTTTAAC---------------GACTTT--CG--TCC-----GCCGTTT-----------TA-------ATTGGCGAGTCTGAATAACTTTTTGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGGG------------------------------------------------------------CAACCGGGTGCGTGTTCGTTGC--CATATCG-----GTTTGTTAATG-GTCGCCCTCGCTGCT----TGTCCGGCTTTTACTACCGGCGTACACTAA-ATTCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGTCCGAAAGGACCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG-CGGT-G----AC [...]
+
+	Torridincola         ---------------------------------ACAAA---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CGGTGTGC---GCGTGTCGTCCGTACGCG---------------GGCGGC--CG---TC-----GCCACCG----------CTA-----ATCATGATGAATCTGAATAACTTTTTGCTGATCGCACGGTC-CAGAACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TCGGCACGGCG----------------------------------------------------CATGTTCGGTTCACG---CAAGCCTCCCGTGC------CCCG------------TAACGCCGTCATTGTCCGCGGTTTTTACTACCGGCGTAC-TGCAAATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-ATCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TGCG------------- [...]
+
+	Distocupes           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCACACA-GGAAGGGATGCTTTTATTAGATCAAAACCAAT-CG---------GCGGC-GGCGTGTTTTA----------------CGCGCGTCCG--TTT-----GCCGTTC------------A-----ACTCTGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+CGCG------------------------------------------------------------CTGTCG---CCGC------CG---CTCGT-------GCCGGC----------CC---GGTGTC---GCGCGCGGTTTTTACTACCGGCGTACAATTT-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTTTTCGGACTGG--TGCG-CGGC-G----GC [...]
+
+	Sialis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAGGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC-----CCAGTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGACGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GTGG--C--GCGTCGCGA---------------AGCG-G--CG--TTCGCAC-ACCGTAC-----------GA-----CC--TGGTGACTCTGAATAACTTTCAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+GCGGCGGTTTCGGCC----------GTGCGTGCGTGTCGGCGTGTACGTTCACCGTGCGGTGTGATGTCGGGCGTGCG-----CG---CGCGTGT-----GTTGGC----GCGC--GTTCGTGCGTCGCGGCGTGTGGTTTTTACTACCGGCGTACAAATA-TATCTTCTTAGAGGGACAGGCGGTAACTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCTGGCCGAAAGGTCCGGGTAATCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TGCG-TGAC-G----AT [...]
+
+	Anisochrysa          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCAAA---TTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CG---------GTGT-----AAATTTT-------------------CA-----A--TTTG--C-ATCGTTT------------A------ATTTGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TTTGAGATTTA----------------ACGATCAAGATT----ATAT----------------TTTGTATATATTGTGCTTTATGT--TGCATAT-----GTTATGGTGTATGG--GTA-CGCAGTTTTTTGATGTGGTTTTTACTGCCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCAGGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGG--TACG-CGGC-A----AT [...]
+
+	Oliarces             TTGTTTCAAAGAATAAGCCATGCATGTCTCAGTACAAG---CCATA---TTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGATGTG----GCTATATGCCCGTTCTGTG-------------GTATATT--TG--TTG---C-ATCGTTT------------A------ATTTGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+GTTGTGTGTTGTTTTCACAAT----GCACGCACACTTACACTACTCTACACTTCTTGAACATATATCTTGTGTGTATGTTTTATGTT-TGCAT-------GTAGACACGTGCGG--GC--CACAGTTTTTTGGTGTGGTTTTTACTGCCGGCGTACAAATA-ATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGTCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTATTGAGGTCTTCGGACTGG--TACG-CGGCAACGTCAC [...]
+
+	Phaeostigma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAG---CCGCA---TTAAGGTGAAACGGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGGTG------GCGGC-GGTGCGTTCG-----------------CGCGTGC-CG--TTCGTTC-GCCGTCT------------A------TTTTGATGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAACGGCT [...]
+TGCGGG---------------------------------------------------------CGTACGGCACGTGCGCTCGACGT--TTCGTTCCGTGTGCCTGTC---------GCCGCGGTGTC----GGTGCGGTTTTTACTACCGGCGTGATTTTA-ACTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCTGGTCGAAAGATCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGG--TACG-CGGC-G----GC [...]
+
+
+;
+
+
+		BLOCKID WM114cbd2260e0;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "02-gammaTest.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Omus,
+		2 Oxycheila,
+		3 Clinidium,
+		4 Omoglymmius,
+		5 Trachypachus,
+		6 Systolosoma,
+		7 Metrius,
+		8 Pachyteles,
+		9 Scaphinotus,
+		10 Nebria,
+		11 Loricera,
+		12 Elaphrus,
+		13 Antarctonomus,
+		14 Omophron,
+		15 Pasimachus,
+		16 Clivinini,
+		17 Dyschirius,
+		18 Creobius,
+		19 Bembidion,
+		20 Psydrus,
+		21 Mecyclothorax,
+		22 Agonum,
+		23 Chlaenius,
+		24 Haliplus_laminatus,
+		25 Haliplus_ruficollis,
+		26 Copelatus,
+		27 Cybister,
+		28 Hydroporus,
+		29 Laccophilus,
+		30 Neoporus,
+		31 Gyrinus,
+		32 Spanglerogyrus,
+		33 Hygrobius,
+		34 Hydrocanthus,
+		35 Noterus,
+		36 Suphis,
+		37 Bruchela,
+		38 Tenebrio,
+		39 Helochares,
+		40 Dynastes,
+		41 Cyphon,
+		42 Clambus,
+		43 Hydroscapha,
+		44 Torridincola,
+		45 Distocupes,
+		46 Sialis,
+		47 Anisochrysa,
+		48 Oliarces,
+		49 Phaeostigma;
+	TREE model_tree = ((((((((((((1:0.019807,2:0.048887):0.068362,(((((3:0.035589,4:0.020202):0.126366,15:0.131641):0.005995,(7:0.020804,8:0.02306):0.047065):0.009431,(22:0.016178,23:0.008502):0.01947):0.003527,21:0.058138):0.007428):0.003257,(11:0.059574,18:0.06156):0.012893):0.00864,13:0.012588):0.008196,(((9:0.029557,10:0.044205):0.001834,(12:0.037896,(14:0.036211,19:0.033253):0.007177,20:0.041281):0.010022):0.002728,(16:0.030509,17:0.020178):0.014379):0.001601):0.004095,(5:0.010988,6:0. [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  =  N:  1- 2543 ;
+	CODONPOSSET CodonPositions  =  N:  1- 2543 ;
+
+	CODESET * UNTITLED   =  universal:  1 -  2543;
+
+
+END;
+
+begin paup;
+	outgroup PhaeosOUT;
+	set torder =                         right tcompress;
+	taxset dytiscidae =                          CopelaDYT CybistDYT HydropDYT LaccopDYT NeoporDYT;
+	taxset gyrinidae =                          GyrgyrGYR SpanglGYR;
+	taxset noteridae =                          HydrocNOT NoteruNOT  SuphisNOT;
+	constraint coleomono = (                         SialisOUT ,                         AnisocOUT ,                         OliarcOUT ,                         PhaeosOUT , (                         OmusCIC -                         DistocARC ) );
+	constraint  adephmono = (                         SialisOUT ,                          AnisocOUT ,                          OliarcOUT ,                          PhaeosOUT ,                          DistocARC ,                          TorridMYX ,                          HydrosMYX ,                          ClambuPOL ,                          CyphonPOL ,                          DynastPOL ,                          HelochPOL ,                          TenebrPOL ,                        [...]
+	constraint  carabmono (                         backbone ) = ( (                         MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          AntarcMIG ,                          OmophrOMO ,                          PasimaSCA ,                          ScaritSCA ,                          DyschiCLI ,                      [...]
+	constraint  beutel = (                         PhaeosOUT ,                          OliarcOUT ,                          AnisocOUT ,                          SialisOUT ,                          DistocARC ,                          TorridMYX ,                          HydrosMYX ,                          ClambuPOL ,                          CyphonPOL ,                          DynastPOL ,                          HelochPOL ,                          TenebrPOL ,                           [...]
+	constraint hydradeph = (                         OmusCIC -                         ChlaenCHL ,                         BruchePOL -                         PhaeosOUT , (                         HaliprHAL ,                         HaliplHAL ,                         dytiscidae ,                          noteridae ,                          HygrobHYG ,                         gyrinidae ) );
+	constraint trachdytisc = (                         OmusCIC -                         OmoglyRHY ,                         MetriuPAU -                         HaliprHAL ,                         BruchePOL -                         PhaeosOUT , (                         TrachyTRA ,                         SystolTRA ,                         dytiscidae ,                          noteridae ,                          HygrobHYG ) );
+	constraint  adephHydmono = ( (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          TrachyTRA ,                          SystolTRA ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                     [...]
+	constraint  hydraPoly = (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          TrachyTRA ,                          SystolTRA ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          [...]
+	constraint  strong = (                         PhaeosOUT , (                         OmusCIC ,                          OxycheCIC ) , (                         ClinidRHY ,                          OmoglyRHY ) ,                          TrachyTRA ,                          SystolTRA , (                         MetriuPAU ,                          PachytPAU ) ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                    [...]
+	constraint  GeadHydAdeph = ( ( (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          AntarcMIG ,                          OmophrOMO ,                   [...]
+	constraint  TrachHydAdeph = ( ( (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          AntarcMIG ,                          OmophrOMO ,                  [...]
+	constraint  THback (                         backbone ) = ( ( (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          AntarcMIG ,                         [...]
+	constraint  THB2 (                         backbone ) = ( (                         OmusCIC ,                          OxycheCIC ,                          ClinidRHY ,                          OmoglyRHY ,                          MetriuPAU ,                          PachytPAU ,                          ScaphiCYC ,                          NebriaNEB ,                          LoriceLOR ,                          ElaphrELA ,                          AntarcMIG ,                          Om [...]
+	lset nst =                         6 rmatrix = (                         1.8516775 4.2080535 2.4489583 0.6302258 8.5377063 )                          shape =                         0.452070 pinvar =                         0.512218 rates =                         gamma basefreq =                         empirical;
+
+END;
+BEGIN MacClade;
+	Version 3.5  13;
+	LastModified -1288801818;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 100;
+	Editor 00001000111111 '24'                          Geneva '9' '100' '1'                          all;
+	OtherSymbols & /                          00 ? -;
+	ListWindow Characters closed Geneva '9';
+	ListWindow Taxa closed Geneva '9'                          1;
+	ListWindow Trees closed Geneva '9';
+	ListWindow TypeSets closed Geneva '9';
+	ListWindow WtSets closed Geneva '9';
+	ListWindow ExSets closed Geneva '9';
+	ListWindow CharSets closed Geneva '9';
+	ListWindow TaxSets closed Geneva '9';
+	ListWindow NexusBlocks closed Geneva '9';
+	StateNamesSymbols closed Geneva '9';
+	Correlation 10011010 '0' '0' '1000' '0' '0';
+	Salmo 0000001;
+	EditorFile '2';
+	TreeWindow 0000;
+	Continuous '0' '3'                          1;
+	Calculations 0000001;
+	SummaryMode '0' '0'                         0;
+	Charts  Geneva '9' (                         normal )                          0010;
+	NexusOptions '0' '0' '50'                          001011001;
+	ChartFont  Geneva '9' (                         normal );
+	TipLabel  Geneva '9' (                         normal ) '1';
+	TreeShape  1.0 1.0 000;
+	TraceLabels 0101;
+	ChartColors '0' '0' '-1' '9'                          11;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'                          1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'                          000011;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'                          1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'                          Geneva '9' (                         normal )                          Geneva '10' (                         normal )                          Geneva '9' (                         normal )                          Geneva '9' (                         normal )                          Geneva '9' (                         bold )                          Geneva '9' (                         normal )       [...]
+	MatchChar 00 .;
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =                         unord PolyTcount =                         MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2543;
+
+	EXSET * UNTITLED  =  105 -  110 212 -  220 225 -  229 236 -  266 268 -  273 281 -  302 777 -  1180 1209 -  1213 1259 -  1294 1860 -  1869 1872 -  1877 1881 -  1889 1900 -  1923 1926 -  2066 2070 -  2088 2092 -  2123 2127 -  2134;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel gamma2 (Gamma) = 
+		shape = 2.0 discrete categories = 4;
+	CharModel gamma2Model (DNASimulationModel) = 
+		'setRootStatesModel Equal_Frequencies; setEquilStatesModel Equal_Frequencies; setCharRatesModel gamma2; setRateMatrixModel Single_Rate; setScalingFactor 1.0; ';
+
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2543;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7662907117210050989 WM114cbd225743;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1994580233913892502 WM114cbd2260e0;
+			checksum 0 1120043444 WM114cbd2260e0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 909 464;
+			setLocation 13 533;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7662907117210050989  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 589.1029790829010.5031380462431139912;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 630 444;
+					setLocation 665 31;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 2;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1994580233913892502 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 648 407;
+					setLocation 13 533;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.batchArch.BatchTemplateManager.BatchTemplateManager;
+		tell It;
+			fileSpecifics myLikelihood 'lset nst = 6;';
+			fileSpecifics myParsimony 'maxtrees = 50;';
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-TestingTreeStructure.nex';
+			setPrevFileName '01-modelTree.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 632 413;
+					setLocation 6 27;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation This_example_file_allows_one_to_test_the_quality_of_one_aspect_of_the_simulation_routines_used_in_Mesquite.__See_the_Simulating_DNA_Sequence_Evolution_page_in_the_Mesquite_Manual_for_more_details.;
+				setTitle Testing_Simulations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual  'http://mesquiteproject.wikispaces.com/Simulating+DNA+Evolution';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Character_Simulations/03-TestingTreeStructure.nex b/Resources/examples/Character_Simulations/03-TestingTreeStructure.nex
new file mode 100755
index 0000000..048aed5
--- /dev/null
+++ b/Resources/examples/Character_Simulations/03-TestingTreeStructure.nex
@@ -0,0 +1,588 @@
+#NEXUS
+[written Sun Jun 08 13:13:39 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=49;
+	TAXLABELS
+		Omus Oxycheila Clinidium Omoglymmius Trachypachus Systolosoma Metrius Pachyteles Scaphinotus Nebria Loricera Elaphrus Antarctonomus Omophron Pasimachus Clivinini Dyschirius Creobius Bembidion Psydrus Mecyclothorax Agonum Chlaenius Haliplus_laminatus Haliplus_ruficollis Copelatus Cybister Hydroporus Laccophilus Neoporus Gyrinus Spanglerogyrus Hygrobia Hydrocanthus Noterus Suphis Bruchela Tenebrio Helochares Dynastes Cyphon Clambus Hydroscapha Torridincola Distocupes Sialis Anisochrysa O [...]
+	;
+	BLOCKID WM114cbd2c8d74;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-TestingTreeStructure.nex"';
+	DIMENSIONS  NCHAR=2529;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Omus                 TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAAA-----ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACATATACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGCGTC------------------CCGGGCTCCATATGATTCTGTACCTTTGCGTACGTTCATGTGTCCTGGTGTGCGTTCACACATATTAC--TGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAAC [...]
+TTCGTACTTGCTCGTGTCGGCAACGATACTGGTTGTTTGTGG---------------------------------------------------------------------------GCG-ATCTTTACTACCGGCGTACACATA-AA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCATGTC-CTCCCT-GGCCGAGAGGTCCGGGTAATCCGGTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCCGACCGGTAC-TCCGACGACGTTT-----CGAC------- [...]
+
+	Oxycheila            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAACTTA------ATGAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA------AAGTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCGTACCGGAGACGGAATGAGTGCTTTTATTAGATCAAAACCAAT-TGTGGCATC----------------CCTAAGGCTCCATATGATTCTGTGTCTTTGCACACGTTCATATGTCCTGGGTGTATGTTCATATTTTTTTATTGGTGAATCTGAATAACTT---GCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTTTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCTTGAGAAAC [...]
+TGCGTCGAATAATGTAACTAGTTGTTTGTTG--------------------------------------------------------------------------------------GCA-ATCTTTACTACCGGCGTATATTTG-TA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCT-GTTCGAGAGAACCGGGTAATCCGTTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATAAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-TC-GGCCGATGTT---TCGACG------- [...]
+
+	Clinidium            TCGTCTCAAAGATTAGGCCACGCATGTCTAAGTACAGCTTTCTATGT-AATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGGAGGAGTGCTTTTATTAGAACAAAACTGAT-CGGTGTTTC-----------------GTCTATTTTATAGGCGTGCATCGCAAGTGAAC---------------------------------------TGGTGAATCTGAATAACTTT-TGCTGATCGCATAGTCATAGCACTAGCGACAAATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+AGTGTTCGGCTCGTATGAGGTGGTTAGTACTTGGAATGCTGGGGTCCCTCAGTGCCCACTTGTTGGTC-------------------------------------------------ACG-GTTTTTACTACCGGCGTACAATTG-AA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCT-GGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGGCAC-GT-GGCAATGTTT-----CGGCA-TTGCT [...]
+
+	Omoglymmius          -----------------CCATGCATGTCTAAGTACAGCTTTCTATGTAACAAAAGTGAACCCGCGAAAGGCTCATTAAATCAGTCATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACAGGAGACTGAAGGAGTGCTTTTATTAGATCAAAACTGAT-CGGTGTGTTTTACGGCCGGACGTTTTACGTACGTGTCCGTAGGCCACCGCAAGTGAAC---------------------------------------TGGTGAATCTGAATAACTT-ATGCTGATCGCATGGTC-ACGTACCGGCGACGCATCTTTCAAATGTCTGCCCTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTGATAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TGAGATTATTAGTTTTCTTGAAATGCTTGCGTCCCAAGGTGCCCACTTGTTGGTC--------------------------------------------------------------ACG-GTTTTTACTACCGGCGTACAATTT-AA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTCCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTG-CTCCCT-GGCTGAGAGGCCCGGGTAATCCGTTGAACCTCCTTCGTGCTAGGGATCGGGGATTGCAATTATTCCCCGTGAACGAGGAATTCCTAGTAAACGTCTGTCATAAGCGGGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTGGTGAGGTCTTCGGACCGGCAC-GT-GGCAATGTTT---------------C [...]
+
+	Trachypachus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCGGAGACGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG--------------------TCGCTTGCGATCGTTCGCCGGCACACT-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GTTT-----------------------------------------------------------------------------------------------------------------GTG-GTTTTTACTACCGGCGTACAATTG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACCGGTAC-GC-GATGACGTTT-----CGACG-T---- [...]
+
+	Systolosoma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAC------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGTGGCGT------------------TGCTTTACGGCTTCGTTCACCGGCACATT-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TGTGTTGTGTGCGTGGCCGGCGGTGGTGTGCTTGTGGAGTTT---------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGAATGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GATGACATTT----CGTGTG-TGATC [...]
+
+	Metrius              TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAACTTTTT----ATAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCCAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGGCGGCGA---------CTATTGTTTTATTACTTTAGTTCGTACGTCGCAAATAT-----------------------------------------TGGTGACTCTGAGTAACTT-ATGCTGATCGTACGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGG-AATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+ACGTTCTTATAGTTGTACCGCTACCTATTCAAACACATTATGTTGTTTGTTAGTTCACTGGGTTCTTGTCCGTGATCTGGGCGGTCTGTTC--------------------------ACG-GTTTTTACTACCGGCGTACACATA-AA-TCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTAATTCCTT-GGCCGAAAGGTCCGGGTAAACCGTTGAATCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACCGGCAC-CC-GGCGGTGTTT-----CGATA-TCGCC [...]
+
+	Pachyteles           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAACTTTTT----ATAAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTACC-----ACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACTGAGCTCTAACCGGTGACGGAAGGAGTGCTTTTATTAGATCAAAACCAATACGACGGCAT----------TATTTATTTTTAATAAATTAATGTACGTCGTTTTTAT-----------------------------------------TGATGAATCTGAGTAACTT-ATGCAGATCGTATGGTC-TAGTACCGACGACGCATCTTTCAAATGTCTGACTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TGATGTTTAATATAGTTTTCTGCTTTCAATCTAATTTGTAAACATATTTCATTGTTGTTTTGTGTATATATAAGGGTTTGTTTTGTGATCTGGGCGGTCTGTTC-------------ACG-GTTTTTACTACCGGCGTACACATA-TA-TCTTCTTAGAGGGACTGGCGGCATCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTATTTCCTT-GGCCGAAAGGTCCGGGTAAACCGTTGAAACTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTCCGGACTGGCAC-CC-GACGGTATTA-----CGATA-TCGCC [...]
+
+	Scaphinotus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAAA-----AATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG------------GTTCGCGTTCGCGCGTTCACGTCCACCGTCAATAA-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+CGTATATACATTACTACGGGCAAGGCGGGAGTTC-----------------------------------------------------------------------------------GTG-GTTTTTACTACCGGCGTACAATTG-TA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGAATGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAACGGCCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGAATACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTTGGACTGGCAC-GC-GGCAGCGTTT-----CCACA-TTGCC [...]
+
+	Nebria               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------AATAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACACGCAAACAGAGCTCCGACCAGAGATGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGGCA-------------------GGCACTGCTGTCTGTTCGTCGCCCTATT-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGTACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GTG-GTTTTTACTACCGGCGTACATTTT-AA-TCTTCTTAGAGGGACAAACGGCTTATAGCCGTATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAACTCGTGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-TC-GGCCGGGGTT----TCGACA-T---- [...]
+
+	Loricera             TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAGCTAA------AATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGACCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGTAGACG------------GGTCCGTTACGGCGGTCTCCGTTTATCGTACACCAAA---------------------------------------TGGTGACTCTGAATAACTTT-TGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------ATG-GTTTTTACTACCGGCGTACATATG-AA-TCTTCTTAGAGGGACAGGCGACTTCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAGAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTTGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATTATTTAGTGAGGTCTTCAGACTGGCAC-CC-GGTGGCGTTT---------------- [...]
+
+	Elaphrus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACATGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAGCCAAT-CGGCGTCTG-----------------------GGTTCGCCCGTTCGCCGCCCTCAT-----------------------------------------TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTG-AA-TCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAAACTCCTTCGTGCTAGGGATTGGGGCTTGCAATTCTTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATTAACTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GATGGTGTTT-----CGACA-C---- [...]
+
+	Antarctonomus        TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAACTAA------AATAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG-------------GTTCGTTTCGGCGTTCTCCGTTCGTCGCACTGTT-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-GAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------ACG-GTTTTTACTACCGGCGTACATATG-AA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGCAC-GC-GGCGGCGTTT-----CGACA-TCGCC [...]
+
+	Omophron             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACTGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGTCGG-------------GTTCCGTTTACGCGGGCTCGTTCGTCGCCCTATT-----------------------------------------TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+ATTGCATATGATTATCAAGTGTAGGTCTATATATCCACTGCATTAGTTTTGGCCATGTTTACGGTACGAGTGTTC------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTA-AA-TCTTCTTAGAGGGACAGGTGGCGCTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GGTGGAATTT---------------- [...]
+
+	Pasimachus           TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACATACTAT------AATAAAGTAAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCATTAGATCGTACCACTATAAGTTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAATTCTGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACTAAT-CGATGTCGG--------------------AATTTTTTTTCCGTTTATCGTAAATTTTTTATG-----------------------------------TGGTGAATCTGAATAACTTT-TGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TTTTGGTGTTATTGTTGTTTCTATTGTTAAATGAGTTGTTGTGAAACCTTGACCGGTGTATCCAATTCATTGGTCGAATGTATGT--------------------------------GTT-GTTTTTACTACCGGCGTACA-TTA-AATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCATGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACAATGAAGGACTCAACGTGTC-CTCCCT-GACCGAATGGTCCGGGTAACCCGTTGAAACTCCTTCGTGATTGGGATTGGGGATTGCAATTTTTCCCCATGAACGAGGAATTCCAAGTAAACGCGAGTCATAAGCTTGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGGTACCAC-GGCGATGCGT---------------- [...]
+
+	Clivinini            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACTAAT-CGGCGACGG---------TGACTCTTTTTAAGGGTTTTATCGTTCGTCGTTCTATA-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCACGGTC-TCGTACCGGCGACATATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTT-TTCCCT-GGCCGAATAGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGATTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATGTAGTGAGGTCTTCAGACTGGTAC-GC-GGCGGTATTT---------------- [...]
+
+	Dyschirius           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAAGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG--------------------TGTTTCGGCATCGTTTGTCGTCCTATT-----------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TCGTACCGGCGATGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GTG-GTTTTTACTACCGGCGTACAATTA-AT-TCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-TTCCCT-GGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGTGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GGCGGTAGTT----TCGATTATTGCC [...]
+
+	Creobius             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCTAA------ACTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATTGTACC-ACAAAAATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTTTAACCAGAGATGGAAAAAGTGCTTTTATTTGAACAAAACCAAT-CGGTGACGT--------GTTTCCAGTTTACTGGTTTCACATAATCACTGAAATTTA-----------------------------------------TGATGAGTCTGAATAACTTTTTGCTGATCGCATGGTC-TTGCACCGGCGACGTATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATTTGCGCCTACCATGGTTGTTACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GGTGCAAGAGTTT--------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACATATA-TA-TCTTCTTAGAGGGACAGGCGTCTTCCAGACGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCT-GGCCGAAAGGTCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGCTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGCAC-AC-GATGGTGTCT----TCGATA-CCATT [...]
+
+	Bembidion            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGTCAG---------------TACGTTTCGGCGTTACTGTTCGTCGCACTTTT-----------------------------------------TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------ACG-GTTTTTACTACCGGCGTACATATA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTT-TTCCCT-GGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTAAGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GGCGGCATTT---------------T [...]
+
+	Psydrus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAACCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG-----------------TGTCTTTGCGATGCCGTTCGTCGCATTGTT-----------------------------------------TGGTGACTCTGAATAACTTTTGGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTG-AA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGTGCAATAACAGGTCTGTAATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAACGTGTC-CTCCCT-GGCCGAATGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGATAC-AC-GGCTCGTGTTT----CGACA-TGGCC [...]
+
+	Mecyclothorax        TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC---ACACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCAGAGATGGGAGGAGTGCTTTTATTAGATCAAAACCAAA-CGGCAGCAG---------TCATTACTTTCGGGTGTGGCTGTGTTTGTCGATTTTATGAT--------------------------------------TGGTGACTCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAAGATCTGCGCTTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GGGTCGGGTGTGTTGTATGGGTGGCTCTGGAATGATGTTGTT---------------------------------------------------------------------------G-G-GTTTTTACTACCGGCGTATATATACAA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTTTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCAGACTGGTAC-TC-GGTGATGTTT----CGTACA-TTACC [...]
+
+	Agonum               TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAACTAT------ATTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC--ACAACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAAACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCATCGG-------------TAACATTTCGGTGTTATCCGTTTGTCGCTCAATATA---------------------------------------TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GTG-GTTTTTACTACTGGCGTACATATA-TA-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGTGAGTCATAAGCTCACGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GG------------------------ [...]
+
+	Chlaenius            TTGTCTCAAAGATTAAGCCATGCATGTCTAAGTACAAACTAT------ATTAAAGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCTGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG--------------TAACGTTTCGGCGTTATCGTTCGTCGCTCAATAAA---------------------------------------TGGTGAATCTGAATAACTTTATGCTGATCGCATGGTC-TTGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGATCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GTG-GTTTTTACTACTAGCGTACATATA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GGTGGTGTTT-----CGACA-T---- [...]
+
+	Haliplus_laminatus   TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCGGCAC-------------GACTGTTTAACGACGGCGCGTCCGCCGAAGAAAC-----------------------------------------TGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCGGGTTTTTACTGCCGGCGTACATA-ATAA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGGTTTAGTGAGGTCTTCGGACCGGTAC-GC-GGTGGCGTTT-----CGGCG-TCACC [...]
+
+	Haliplus_ruficollis  TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCGGCAC-------------GACTGTTTAACGACGGCGCGTCCGCCGAAGAAAC-----------------------------------------TGGTGAATCTGAATAACTTTACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCGAGTTTTTACTGCCGGCGTACATA-ATAA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACACGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAACGGTCCGGGTAACCCGCTGAACCTCCTTCGTG-TAGGGGATGGGGCTTGCAAT-GT-CCCCATGAACGAGGAATTTCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGTGGCGTTT-----CGACG-TCGCC [...]
+
+	Copelatus            TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAC------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG----------------GTGCGTTCGCGCATCCGTTCGCCGCTCAACC-----------------------------------------TGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGAGGTTT-----CGACG-T---- [...]
+
+	Cybister             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAGACGGAAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCGGCGT----------------GTTCGTTCGCGTTCACGTTCGCCGCCCAACT-----------------------------------------TGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GACCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGCAC-GC-GGCGAGGTTT-----CGACG-TCGCC [...]
+
+	Hydroporus           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCCG------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGAACAAAACCAAT-CGGCGGCGG----------------GCGCGTTCGCGCGTCCGTTCGCCGCTCAACC-----------------------------------------TGGTGACTCTGAATAACTTTCCGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGAGGTTC-----CGACC-CCGCC [...]
+
+	Laccophilus          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGC------TTTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG----------------GCGAGTTCGCTCGTCCGTTCGCCGCTCAACC-----------------------------------------TGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATT-TA-TCTTCTTAGAGGGACAGGCGGCTCCTAGTCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGAGGTTT-----CGACG-T---- [...]
+
+	Neoporus             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG----------------GCGCGTCCGCGCGTCCGTTCGCCGCTCAACC-----------------------------------------TGGTGACTCTGAATAACTTTAGGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATG-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGAGGTTC-----CGACC-CCGCC [...]
+
+	Gyrinus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACGAGCCGC------ATCAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGCAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG-------------GCCCGTTCACGCGGCGTCCGTCCGTCGTCCTCAC-----------------------------------------TGGTGACTCTGAATAACTCTATGCCGATCGCACGGTC-TCGCACCGGCGACGCGTCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTTCA-ATGATA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGGCGTTC-----CGACG-TCGCC [...]
+
+	Spanglerogyrus       TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAC------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGGAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG--------------GCCCGTTCGCGCGGGTCCTACCGTCGTACTGGC-----------------------------------------TGGTGACTCTGAATAACTTGACGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCAGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACACATA-AT-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGGGTCAGCGTGTC-CTCCCTTGGCCGAGCGGCCCGGGTAACCCGCTGAACTCCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGGCGTTT-----CGACG-TCGCC [...]
+
+	Hygrobia             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCTA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGGAGGAATGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG----------------GTGCGTCCGCGTGCCCGTTCGCCGCTCAACT-----------------------------------------TGGTGACTCTGAATAACTTTCGGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGCCGGCGTACACATT-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGAAGTTT-----CGACG-TCGCC [...]
+
+	Hydrocanthus         TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGTCGG----------------TCCGTTCTCGCGGATCGTTCGTCGCATTCAC-----------------------------------------TGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GCGGTCGGGCGTAC-------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACACATT-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGGTAT-GC-GGCGGGGTTT-----CGAGT-ACACC [...]
+
+	Noterus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACACTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGATCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG-----------------TCGGTTCGCGCCGGTCGTCGTCGCTCTCGC-----------------------------------------TGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GCGGTCGGGCGTAC-------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACACATT-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCTGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGG----CAATTTTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATGGAATGATTTAGCGAGGTCTCCTTTATGGTAT-GC-GGCGGGGTTT-----CGAGT-ACACC [...]
+
+	Suphis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG----------------TCCGTTCACGCGGTCCGTTCGTCGCATTCAC-----------------------------------------TGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GCGGTCGGGCGTAC-------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACACATT-AA-TCTTCTTAGAGGGACAGGCGGCTCCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCGGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTTTTCCCCATGAACGAGGAATACCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTT---------------------------------------------------- [...]
+
+	Bruchela             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACAATTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGTGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG-------------------------GTTCGCTCGTCATCGTACAACT-----------------------------------------TGGTGACTCTGAATAACTTTGTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+--------------------------------------------------------------------------------------------------------------------------TCT--ACTGTCGGCGTACAAACA-AT-TCTTCTTAGAGGGACAGGCGGCT-CTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCA-GGCCGAGTGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGCTC-GC-GATGGCGTTT-----CCGCG-TTCTC [...]
+
+	Tenebrio             TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCAACCGGAAACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG----------------------------TCTCCGTCATCGTACAACT-----------------------------------------TGGTGACTCTGAATAACTTTACGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACAAACA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGAACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGCGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGTGGCGTTT-----CGGCG-TCGCC [...]
+
+	Helochares           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG-------------------GCGTTTGCGCGCTCGTCATCGTACATTT-----------------------------------------TGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-CAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACAATCA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAGAGGCCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGTGGCGCTC-----CTGCG-TCGCC [...]
+
+	Dynastes             TTGTCTCAAAGAT-AAGCCATGCATGTCTCAGTACGAGCCGT------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGTTCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGCTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG------------------------GTCTTACTCGTCATCGTACACCT-----------------------------------------TGGTGACTCTGAATAACTTCTTGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTGTCGGCGTACAAATA-AT-TCTTCTTAGAGGGACAGGCGGCGTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAGCGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTGC-GC-GGTTGCGTTAAGTTACTACG-TCGCC [...]
+
+	Cyphon               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC-----ACA-TTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAACTCCGACCGGAGACGGAAGGAGCGCTTTTATTAGATCAAAACCAAT-CGGCGCCGA------------------------TTTCGGTCGGTCGTCGTACATCT-----------------------------------------TGGTGAATCTGAATAACTTT--GCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------AC---TTTTTACTGCCGGCGTACAAGCA-GT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCTA-GCCCGAGAGGGCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-CGCGGCGTTT-----CGACG-TCGCA [...]
+
+	Clambus              TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAT------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACA---CACAA-TTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCTGAACCGGAGACGGAACGGACGCTTTTATTAGATCAAAACCAAT-CGGCAATGA----------------------GTATTTTACTTATTGTCGTATTATT-----------------------------------------TGGTGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TTGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+---------------------------------------------------------------------------------------------------------------------A---GTTTTTACTGCCGGCGTACA-TTA-AATTCTTCTTAGAGGGACAGGCGGCTTTCAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAGTGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTATTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGTGTTGATTATGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGTGGCGTTT-----CGACG-TTGCC [...]
+
+	Hydroscapha          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACTGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CGGCGGCGG----------------GAGTTTAACGACTTTCGTCCGCCGTTTTAAT-----------------------------------------TGGCGAGTCTGAATAACTTTTTGCTGATCGCACGGTC-TAGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TGGTCGCCCTCGCTGCTTGTC-------------------------------------------------------------------------------------------------CG-GCTTTTACTACCGGCGTACAC-TA-AATTCTTCTTAGAGGGACAGGCGGCTTTTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GTCCGAAAGGACCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTGC-GC-GGTGACGTTT-----CGGCG-TAACC [...]
+
+	Torridincola         ---------------------------------ACAAACCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCGGAGACGGAAGGGATGCTTTTATTAGATCAAAACCGAT-CGGTGTGCG------------CGTGTCGTCCGTACGCGGGCGGCCGTCGCCACCGCTAATCA-----------------------------------TGATGAATCTGAATAACTTTTTGCTGATCGCACGGTC-CAGAACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+CCGTGCCCCGTAACGCCGTCATTGTCC------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTAC-TGCA-AATTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-ATCCCT-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTGC-G---------------------------- [...]
+
+	Distocupes           TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGC------ATTAAGGTGAAACCGCGAAAGGCTCATTAAATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTCCCGACCACACA-GGAAGGGATGCTTTTATTAGATCAAAACCAAT-CGGCGGCGG--------------CGTGTTTTACGCGCGTCCGTTTGCCGTTCAACTC----------------------------------------TGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGCACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTCGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+CGC------------------------------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTACAATTT-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATCGGGGCTTGCAATTATTCCCCGTGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTTTTCGGACTGGTGC-GC-GGCGGCGTTT---------------- [...]
+
+	Sialis               TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGC------ATTAGGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC-----CCAGTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCGGAGACGGACGGAATGCTTTTATTAGATCAAAACCAAT-CGGTGGCGC---------------GTCGCGAAGCGGCGTTCGCACACCGTACGACC-----------------------------------------TGGTGACTCTGAATAACTTTCAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+CGTGTCGGCGTGTACGTTCACCGTGCGGTGTGATGTCGGGCGTGCGCGCGCGTGTGTTGGCGCGCGTTCGTGCGTCGCGGCGT----------------------------------GTG-GTTTTTACTACCGGCGTACAAATA-TA-TCTTCTTAGAGGGACAGGCGGTAACTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-TTCCCT-GGCCGAAAGGTCCGGGTAATCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTGC-GT-GACGATGCTC-----CCGCA-TTGTT [...]
+
+	Anisochrysa          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCAA------ATTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGGTGTAAA------------------------TTTTCAATTTGCATCGTTTAATT-----------------------------------------TGGTGACTCTGAATAACTTTAAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TTGTATATATTGTGCTTTATGTTGCATATGTTATGGTGTATGGGTACGCAGTTTTTTGAT---------------------------------------------------------GTG-GTTTTTACTGCCGGCGTACAAATA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCA-GGCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACTGGTAC-GC-GGCAATATTT----CTGATA-TTGCC [...]
+
+	Oliarces             TTGTTTCAAAGAATAAGCCATGCATGTCTCAGTACAAGCCAT------ATTAAGGTGAAACCGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCAACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGATGTGGC------TATATGCCCGTTCTGTGGTATATTTGTTGCATCGTTTAATT-----------------------------------------TGGTGACTCTGAATAACTTTTAGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+TTGTGTGTTGTTTTCACAATGCACGCACACTTACACTACTCTACACTTCTTGAACATATATCTTGTGTGTATGTTTTATGTTTGCATGTAGACACGTGCGGGCCACAGTTTTTTGGTGTG-GTTTTTACTGCCGGCGTACAAATA-AT-TCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GTCCGAAAGGTCCGGGTAACCCGCTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTATTGAGGTCTTCGGACTGGTAC-GC-GGCAACGTCACTTACTGACA-TGACC [...]
+
+	Phaeostigma          TTGTCTCAAAGATTAAGCCATGCATGTCTCAGTACAAGCCGC------ATTAAGGTGAAACGGCGAAAGGCTCATTATATCAGTTATGGTTCCTTAGATCGTACC----CACATTTACTTGGATAACTGTGGTAATTCTAGAGCTAATACATGCAAACAGAGTTCCGACCAGAGATGGAAGGAATGCTTTTATTAGATCAAAACCAAT-CGGTGGCGG---------CGGTGCGTTCGCGCGTGCCGTTCGTTCGCCGTCTATTT-----------------------------------------TGATGACTCTGAATAACTTTTTGCTGATCGCACGGTC-TCGTACCGGCGACGCATCTTTCAAATGTCTGCCTTATCAACTGTCGATGGTAGGTTCTGCGCCTACCATGGTTGTAACGGGTAACGGGGAATCAGGGTTCGATTCCGGAGAGGGAGCCTGAGAAAC [...]
+GTGCCTGTCGCCGCGGTGTCGGT----------------------------------------------------------------------------------------------GCG-GTTTTTACTACCGGCGTG-ATTTT-AACTCTTCTTAGAGGGACAGGCGGCTTCTAGCCGCACGAGATTGAGCAATAACAGGTCTGTGATGCCCTTAGATGTTCTGGGCCGCACGCGCGCTACACTGAAGGAATCAGCGTGTC-CTCCCT-GGTCGAAAGATCCGGGTAACCCGTTGAACCTCCTTCGTGCTAGGGATTGGGGCTTGCAATTGTTCCCCATGAACGAGGAATTCCCAGTAAGCGCGAGTCATAAGCTCGCGTTGATTACGTCCCTGCCCTTTGTACACACCGCCCGTCGCTACTACCGATTGAATGATTTAGTGAGGTCTTCGGACCGGTAC-GC-GGCGGCATTA----ACACTG-TCGCC [...]
+
+
+;
+
+
+		BLOCKID WM114cbd2c98e0;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "03-TestingTreeStructure.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Omus,
+		2 Oxycheila,
+		3 Clinidium,
+		4 Omoglymmius,
+		5 Trachypachus,
+		6 Systolosoma,
+		7 Metrius,
+		8 Pachyteles,
+		9 Scaphinotus,
+		10 Nebria,
+		11 Loricera,
+		12 Elaphrus,
+		13 Antarctonomus,
+		14 Omophron,
+		15 Pasimachus,
+		16 Clivinini,
+		17 Dyschirius,
+		18 Creobius,
+		19 Bembidion,
+		20 Psydrus,
+		21 Mecyclothorax,
+		22 Agonum,
+		23 Chlaenius,
+		24 Haliplus_laminatus,
+		25 Haliplus_ruficollis,
+		26 Copelatus,
+		27 Cybister,
+		28 Hydroporus,
+		29 Laccophilus,
+		30 Neoporus,
+		31 Gyrinus,
+		32 Spanglerogyrus,
+		33 Hygrobia,
+		34 Hydrocanthus,
+		35 Noterus,
+		36 Suphis,
+		37 Bruchela,
+		38 Tenebrio,
+		39 Helochares,
+		40 Dynastes,
+		41 Cyphon,
+		42 Clambus,
+		43 Hydroscapha,
+		44 Torridincola,
+		45 Distocupes,
+		46 Sialis,
+		47 Anisochrysa,
+		48 Oliarces,
+		49 Phaeostigma;
+	TREE MLE_Trachy_Dyt_Together = (((((((((((1:0.01326,2:0.025822):0.041631,(((((3:0.025429,4:0.009475):0.096781,15:0.073878):0.006201,(7:0.018716,8:0.011625):0.037189):0.005133,(22:0.007708,23:0.005387):0.010051):0.005321,21:0.024634):0.003992):0.002732,(11:0.042282,18:0.036237):0.006859):0.005134,13:0.008836):0.005299,10:0.025811,(((12:0.021417,14:0.019758):0.002351,20:0.020515):0.001333,19:0.01871):0.004783):0.001944,(16:0.015309,17:0.010893):0.006487):0.002682,((((5:0.006749[%color = 1 [...]
+	TREE TD_constraint = (1:1.0,2:1.0,3:1.0,4:1.0,15:1.0,7:1.0,8:1.0,22:1.0,23:1.0,21:1.0,11:1.0,18:1.0,13:1.0,10:1.0,12:1.0,14:1.0,20:1.0,19:1.0,16:1.0,17:1.0,(26:1.0[%color = 14 ],5:1.0[%color = 11 ],6:1.0[%color = 11 ],29:1.0[%color = 14 ],33:1.0[%color = 14 ],28:1.0[%color = 14 ],30:1.0[%color = 14 ],27:1.0[%color = 14 ],34:1.0[%color = 14 ],35:1.0[%color = 14 ],36:1.0[%color = 14 ]):1.0,24:1.0,25:1.0,37:1.0,39:1.0,40:1.0,38:1.0,42:1.0,41:1.0,31:1.0,32:1.0,9:1.0,43:1.0,44:1.0,45:1.0,46: [...]
+
+END;
+
+
+BEGIN paup;
+	outgroup PhaeosOUT;
+	set torder =             right tcompress;
+	taxset dytiscidae =              CopelaDYT CybistDYT HydropDYT LaccopDYT NeoporDYT;
+	taxset gyrinidae =              GyrgyrGYR SpanglGYR;
+	taxset noteridae =              HydrocNOT NoteruNOT  SuphisNOT;
+	constraint  coleomono = (             SialisOUT ,             AnisocOUT ,             OliarcOUT ,             PhaeosOUT , (             OmusCIC -             DistocARC ) );
+	constraint  carabmono (             backbone ) = ( (             MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,              PsydruPSY ,              MecyclPSY ,              AgonumPLA ,              ChlaenCHL ) ,              [...]
+	constraint  hydradeph = (             OmusCIC -             ChlaenCHL ,             BruchePOL -             PhaeosOUT , (             HaliprHAL ,             HaliplHAL ,             dytiscidae ,              noteridae ,              HygrobHYG ,             gyrinidae ) );
+	constraint  adephHydmono = ( (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              TrachyTRA ,              SystolTRA ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,               [...]
+	constraint  strong = (             PhaeosOUT , (             OmusCIC ,              OxycheCIC ) , (             ClinidRHY ,              OmoglyRHY ) ,              TrachyTRA ,              SystolTRA , (             MetriuPAU ,              PachytPAU ) ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA , (             ScaritSCA ,              DyschiCLI ) ,           [...]
+	constraint  A = (             SialisOUT ,              AnisocOUT ,              OliarcOUT ,              PhaeosOUT ,              DistocARC ,              TorridMYX ,              HydrosMYX ,              ClambuPOL ,              CyphonPOL ,              DynastPOL ,              HelochPOL ,              TenebrPOL ,              BruchePOL , (             SuphisNOT ,              NoteruNOT ,              HydrocNOT ,              HygrobHYG ,              SpanglGYR ,              GyrgyrGYR  [...]
+	constraint  GTHA = ( ( (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,              PsydruPSY ,              Mecycl [...]
+	constraint  HTGA = ( ( (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,              PsydruPSY ,              Mecycl [...]
+	constraint  THback (             backbone ) = ( ( (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,              Psyd [...]
+	constraint  TDB (             backbone ) = ( (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,              PsydruPSY [...]
+	constraint  TD = (             OmusCIC -             OmoglyRHY ,             MetriuPAU -             HaliprHAL ,             BruchePOL -             PhaeosOUT , (             TrachyTRA ,             SystolTRA ,             dytiscidae ,              noteridae ,              HygrobHYG ) );
+	constraint  Beutel = (             PhaeosOUT ,              OliarcOUT ,              AnisocOUT ,              SialisOUT ,              DistocARC ,              TorridMYX ,              HydrosMYX ,              ClambuPOL ,              CyphonPOL ,              DynastPOL ,              HelochPOL ,              TenebrPOL ,              BruchePOL , ( (             SpanglGYR ,              GyrgyrGYR ) , ( (             HaliprHAL ,              HaliplHAL ) , ( ( ( ( (             NeoporDYT ,  [...]
+	constraint  PH = (             OmusCIC ,              OxycheCIC ,              ClinidRHY ,              OmoglyRHY ,              TrachyTRA ,              SystolTRA ,              MetriuPAU ,              PachytPAU ,              ScaphiCYC ,              NebriaNEB ,              LoriceLOR ,              ElaphrELA ,              AntarcMIG ,              OmophrOMO ,              PasimaSCA ,              ScaritSCA ,              DyschiCLI ,              CreobiBRO ,              BembidBEM ,  [...]
+	lset nst =             6 rmatrix = (             2.0618003 5.0491873 2.6143968 0.42480768 8.2421577 )              rates =             gamma basefreq =             empirical shape =             0.513359 pinvar =             0.531193;
+
+END;
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  =  N:  1- 2529 ;
+	CODONPOSSET CodonPositions  =  N:  1- 2529 ;
+
+	CODESET * UNTITLED   =  universal:  1 -  2529;
+
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  80;
+	LastModified -1232394066;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 100;
+	Editor 000110011101111001100101 '1' '12'              Geneva '9' '100' '1'              all;
+	EditorPosition '61' '259' '659' '651';
+	TreeWindowPosition '40' '2' '728' '1018';
+	ListWindow Characters closed Geneva '9' '312' '26' '265' '486'              001;
+	ListWindow Taxa closed Geneva '9' '50' '10' '276' '490'              100;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '47' '77' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames open Geneva '9' '315' '145' '377' '223';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder;
+	OtherSymbols & /              00 ? -;
+	Correlation '0' '0' '1000' '0' '0'              10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'              110000;
+	PrettyPrint 10;
+	EditorToolsPosition '37' '7' '291' '57';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'              1;
+	Calculations 0000001;
+	SummaryMode '0' '0'              0;
+	Charts  Geneva '9' (             normal )              0010;
+	NexusOptions '0' '0' '50'              001011001;
+	TipLabel '1';
+	TreeFont  Geneva '9' (             normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '-1' '9' '0'              1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'              1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'              1;
+	BarsOnBranchesDisplay '0' '0' '-5536' '10000' '10000' '10000' '10000' '-5536' '-536' '-536' '-536' '6' '1'              0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'              1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'              Geneva '9' (             normal )              Geneva '10' (             normal )              Geneva '9' (             normal )              Geneva '9' (             normal )              Geneva '9' (             bold )              Geneva '9' (             normal )              Geneva '9' (             normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 0;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'              00100111111101110;
+	EditorTools '0' '2' '0' '1000' '0' '0' '2' '9' '2'              100010101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'              1011;
+	BothTools '1';
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =             unord PolyTcount =             MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2529;
+
+	EXSET * UNTITLED  =  106 -  113 215 -  253 259 -  306 733 -  740 746 -  750 757 -  762 781 -  1173 1258 -  1276 1347 -  1350 1859 -  1884 1900 -  2127 2141 -  2149 2461 -  2529;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	CharModel MLE_GammaInvar_TD (GammaInvar) = 
+		pInvar = 0.53124 shape = 0.493338 discrete categories = 4;
+	CharModel MLE_GTR_TD (RateMatrixGTR) = 
+		RMatrix = (2.081685 5.099413 2.618544 0.437 8.731375 1.0) ;
+	CharModel 'GTR + G + I' (DNASimulationModel) = 
+		'setRootStatesModel Empirical_Frequencies; setEquilStatesModel Empirical_Frequencies; setCharRatesModel MLE_GammaInvar_TD; setRateMatrixModel MLE_GTR_TD; setScalingFactor 1.0; ';
+
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  2529;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6203602635193277121 WM114cbd2c8d74;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 212957930981682860 WM114cbd2c98e0;
+			checksum 0 2730136686 WM114cbd2c98e0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 831 464;
+			setLocation 14 409;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6203602635193277121  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 724.990594842367.3423146183066538833;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 434;
+					setLocation 602 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 4;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #212957930981682860 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 570 407;
+					setLocation 14 409;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.batchArch.BatchTemplateManager.BatchTemplateManager;
+		tell It;
+			fileSpecifics search_options 'addseq=random nreps=20';
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00-introduction.nex';
+			setPrevFileName '02-gammaTest.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 559 288;
+					setLocation 10 26;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation This_example_file_allows_one_to_test_the_monophyly_of_a_group_using_standard_parametric_bootstrapping_methods.__See_Study_1_in_the_Mesquite_Manual_for_more_details.;
+				setTitle Parametric_Bootstrapping;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_intro;
+				addWebLink Explanation_of_example  'http://mesquiteproject.wikispaces.com/Testing+monophyly+of+a+group+of+beetles';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Character_Simulations/templates/GIGTRTest.template b/Resources/examples/Character_Simulations/templates/GIGTRTest.template
new file mode 100755
index 0000000..30c8898
--- /dev/null
+++ b/Resources/examples/Character_Simulations/templates/GIGTRTest.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = GammaPInvar_GTR_Model_Test
+ explanation = 'This template produces a batch file to request PAUP to quickly find a tree using neighbor joining.  It asks PAUP to calculate the likelihood value for the tree, estimating any parameters specified in the snippet''s lset command, and then write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	dset distance=hky85;^n	lset basefreq=empirical nst=6 rmatrix=estimate pinvar=estimate rates=gamma shape=estimate ncat=6;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	nj;^n 	lscore 1/scorefile=''<name>Score.scr'' append;^n'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = PaupCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 7^nnumFiles = 1^nfile1 = ''itemsPerRecord=18 v1=12 v2=13 v3=14 v4=15 v5=16 v6=17 v7=18''^nrecordLabel = ''Replicates''^nlabel1 = ''R(a)''^nlabel2 = ''R(b)''^nlabel3 = ''R(c)''^nlabel4 = ''R(d)''^nlabel5 = ''R(e)''^nlabel6 = ''proportion invariable''^nlabel7 = ''gamma shape''^n'
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file
diff --git a/Resources/examples/Character_Simulations/templates/GTRTest.template b/Resources/examples/Character_Simulations/templates/GTRTest.template
new file mode 100755
index 0000000..6f077e9
--- /dev/null
+++ b/Resources/examples/Character_Simulations/templates/GTRTest.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = GTR_Model_Test
+ explanation = 'This template produces a batch file to request PAUP to quickly find a tree using neighbor joining.  It asks PAUP to calculate the likelihood value for the tree, estimating any parameters specified in the snippet''s lset command, and then write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	dset distance=hky85;^n	lset basefreq=empirical nst=6 rmatrix=estimate pinvar=0 rates=equal;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	nj;^n 	lscore 1/scorefile=''<name>Score.scr'' append;^n'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = PaupCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 5^nnumFiles = 1^nfile1 = ''itemsPerRecord=14 v1=10 v2=11 v3=12 v4=13 v5=14''^nrecordLabel = ''Replicates''^nlabel1 = ''R(a)''^nlabel2 = ''R(b)''^nlabel3 = ''R(c)''^nlabel4 = ''R(d)''^nlabel5 = ''R(e)''^n'
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file
diff --git a/Resources/examples/Character_Simulations/templates/GammaInvarTest.template b/Resources/examples/Character_Simulations/templates/GammaInvarTest.template
new file mode 100755
index 0000000..ef9eb52
--- /dev/null
+++ b/Resources/examples/Character_Simulations/templates/GammaInvarTest.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = GammaInvar_Model_Test
+ explanation = 'This template produces a batch file to request PAUP to quickly find a tree using neighbor joining.  It asks PAUP to calculate the likelihood value for the tree, estimating any parameters specified in the snippet''s lset command, and then write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	dset distance=hky85;^n	lset basefreq=empirical nst=1 pinvar=estimate rates=gamma shape=estimate ncat=4;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	nj;^n 	lscore 1/scorefile=''<name>Score.scr'' append;^n'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = PaupCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 2^nnumFiles = 1^nfile1 = ''itemsPerRecord=8 v1=7 v2=8''^nrecordLabel = ''Replicates''^nlabel1 = ''proportion invariable''^nlabel2 = ''gamma shape''^n'
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file
diff --git a/Resources/examples/Character_Simulations/templates/GammaTest.template b/Resources/examples/Character_Simulations/templates/GammaTest.template
new file mode 100755
index 0000000..4ddd569
--- /dev/null
+++ b/Resources/examples/Character_Simulations/templates/GammaTest.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = Gamma_Model_Test
+ explanation = 'This template produces a batch file to request PAUP to quickly find a tree using neighbor joining.  It asks PAUP to calculate the likelihood value for the tree, estimating any parameters specified in the snippet''s lset command, and then write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	dset distance=hky85;^n	lset basefreq=empirical nst=1 pinvar=0 rates=gamma shape=estimate ncat=4;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	nj;^n 	lscore 1/scorefile=''<name>Score.scr'' append;^n'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = gammaCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 1^nnumFiles = 1^nfile1 = ''itemsPerRecord=6 v1=6''^nrecordLabel = ''Replicates''^nlabel1 = ''gamma shape''^n'
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file
diff --git a/Resources/examples/Character_Simulations/templates/TiTvTest.template b/Resources/examples/Character_Simulations/templates/TiTvTest.template
new file mode 100755
index 0000000..d025caf
--- /dev/null
+++ b/Resources/examples/Character_Simulations/templates/TiTvTest.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = TiTv_Model_Test
+ explanation = 'This template produces a batch file to request PAUP to quickly find a tree using neighbor joining.  It asks PAUP to calculate the likelihood value for the tree, estimating any parameters specified in the snippet''s lset command, and then write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	dset distance=hky85;^n	lset basefreq=empirical nst=2 tratio=estimate pinvar=0 rates=equal;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	nj;^n 	lscore 1/scorefile=''<name>Score.scr'' append;^n'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = PaupCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 1^nnumFiles = 1^nfile1 = ''itemsPerRecord=6 v1=6''^nrecordLabel = ''Replicates''^nlabel1 = ''ti/tv ratio''^n'
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file
diff --git a/Resources/examples/Coalescence/00-introduction.nex b/Resources/examples/Coalescence/00-introduction.nex
new file mode 100755
index 0000000..ad143d3
--- /dev/null
+++ b/Resources/examples/Coalescence/00-introduction.nex
@@ -0,0 +1,53 @@
+#NEXUS
+[written Sat Jun 07 11:23:24 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Example files for coalescence calculations^n^nThe files linked to this one illustrate some of the coalescence calculations that can be done by the package of coalescence modules of the Mesquite system.  To learn more about this package, use the Coalescence Package menu item of the Help menu, or touch on the banner in the Mesquite Startup window. (It should take you to your web browser, perhaps after asking you to locate the browser.)^n^nTo go from one file to another, [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-coalescence.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'Example files for coalescence calculations^n^nThe files linked to this one illustrate some of the coalescence calculations that can be done by the package of coalescence modules of the Mesquite system.  To learn more about this package, go to the population genetics section of the manual using the button below, or use the Coalescence Package menu item of the Help menu, or touch on the banner in the Mesquite Startup window. (It should take you to your web browser, perh [...]
+				setTitle Coalescence_examples;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Manual  'http://mesquiteproject.wikispaces.com/Gene+Trees';
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/01-coalescence.nex b/Resources/examples/Coalescence/01-coalescence.nex
new file mode 100755
index 0000000..b37bfa0
--- /dev/null
+++ b/Resources/examples/Coalescence/01-coalescence.nex
@@ -0,0 +1,231 @@
+#NEXUS
+[written Sat Jun 07 11:23:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		g1 g2 g3 g4 g5 g6 g7 g8 g9 
+	;
+	BLOCKID WM1148c10e06e14;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-coalescence.nex"';
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	g1  AACATCTGGGAACCGTGCG
+
+	g2  C?CGTCTGAGACCCGTCCG
+
+	g3  AAGATACGGGTACCGTCCG
+
+	g4  AACATACGGGAAGCGTCCG
+
+	g5  AAGGTACGGGAACCGTCCG
+
+	g6  AAAGTACGGGACCCGTGCG
+
+	g7  AACGTACGGGAACCGTGCG
+
+	g8  AAAGCACGGGAACCGTGCG
+
+	g9  AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM1148c10e0900;
+
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows a tree window with gene trees simulated by coalescence within a population.  Scroll through trees to see other simulated gene trees.   The organisms simulated are haploids. The effective population size is by default 10000.  To change this, choose Set Ne from the Tree menu.^n^nTo go to next example file: click the button in the "Go To File" window.^n^nTo duplicate this file: Select "New" from the File menu, and indicate the name of the set of taxa (gen [...]
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  19;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  19;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  19;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  19;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1469954533384391314 WM1148c10e06e14;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4636206365576148138 WM1148c10e0900;
+			checksum 0 1947097330 WM1148c10e0900;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 452 430;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #1469954533384391314  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.CoalescentTrees.CoalescentTrees;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 10000;
+							toggleExponential on;
+						endTell;
+					endTell;
+					setSeed 983242417684;
+				endTell;
+				setAssignedID 302.971276427933.7117688824995678366;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 459 407;
+					setLocation 490 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+							setFixedScaling 30000.0;
+						endTell;
+						setEdgeWidth 4;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-coalescence2.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 452 413;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a tree window with gene trees simulated by coalescence within a population.  Scroll through trees to see other simulated gene trees.   The organisms simulated are haploids. The effective population size is by default 10000.  To change this, choose Set Ne from the Coalescent Simulation submenu of the Tree menu.^n^nTo duplicate this file: Select "New" from the File menu, and indicate the name of the set of taxa (genes) and the number of taxa (gene copies [...]
+				setTitle Simulated_gene_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/02-coalescence2.nex b/Resources/examples/Coalescence/02-coalescence2.nex
new file mode 100755
index 0000000..6abba53
--- /dev/null
+++ b/Resources/examples/Coalescence/02-coalescence2.nex
@@ -0,0 +1,215 @@
+#NEXUS
+[written Sat Jun 07 11:24:31 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		g1 g2 g3 g4 g5 g6 g7 g8 g9 
+	;
+	BLOCKID WM1148c1835ae15;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-coalescence2.nex"';
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	g1  AACATCTGGGAACCGTGCG
+
+	g2  C?CGTCTGAGACCCGTCCG
+
+	g3  AAGATACGGGTACCGTCCG
+
+	g4  AACATACGGGAAGCGTCCG
+
+	g5  AAGGTACGGGAACCGTCCG
+
+	g6  AAAGTACGGGACCCGTGCG
+
+	g7  AACGTACGGGAACCGTGCG
+
+	g8  AAAGCACGGGAACCGTGCG
+
+	g9  AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM1148c1835cf0;
+
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'At left is a "Multi Tree Window" to show a series of gene trees simulated by coalescence within a population.  You can scroll down to see other such simulated trees.  Note that the root tends to be between 1000 and 2000 generations deep.^n^nThe effective population size is 1000 (haploid), and can be changed using the "Set Ne.." menu item in the Multi-Tree menu of the Trees window.';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  19;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  19;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  19;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  19;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4451700786596653131 WM1148c1835ae15;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4972659033594616137 WM1148c1835cf0;
+			checksum 0 1947097330 WM1148c1835cf0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 422 474;
+			setLocation 13 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #4451700786596653131;
+			setNumColumns 4;
+			setNumRows 4;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.CoalescentTrees.CoalescentTrees;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 1000;
+							toggleExponential on;
+						endTell;
+					endTell;
+					setSeed 1189475568974;
+				endTell;
+				assignNumTrees 100;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 626 641;
+				setLocation 456 22;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle on;
+						toggleScale on;
+						toggleBroadScale off;
+						toggleCenter on;
+						toggleEven on;
+						setFixedScaling 2500.0;
+					endTell;
+					setEdgeWidth 3;
+					orientUp;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setFont SanSerif;
+					setFontSize 10;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-coalescenceDepth.nex';
+			setPrevFileName '01-coalescence.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 350 457;
+					setLocation 13 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'At left is a "Multi Tree Window" to show a series of gene trees simulated by coalescence within a population.  You can scroll down to see other such simulated trees.  Note that the root tends to be between 1000 and 2000 generations deep.^n^nThe effective population size is 1000 (haploid), and can be changed using the "Set Ne.." menu item in the Coalescent SImulation submenu of the Multi-Tree menu of the Trees window.';
+				setTitle Gene_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/03-coalescenceDepth.nex b/Resources/examples/Coalescence/03-coalescenceDepth.nex
new file mode 100755
index 0000000..aad8d8f
--- /dev/null
+++ b/Resources/examples/Coalescence/03-coalescenceDepth.nex
@@ -0,0 +1,180 @@
+#NEXUS
+[written Sat Jun 07 11:24:47 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		g1 g2 g3 g4 g5 g6 g7 g8 g9 
+	;
+	BLOCKID WM1148c2865d916;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-coalescenceDepth.nex"';
+	DIMENSIONS  NCHAR=19;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	g1  AACATCTGGGAACCGTGCG
+
+	g2  C?CGTCTGAGACCCGTCCG
+
+	g3  AAGATACGGGTACCGTCCG
+
+	g4  AACATACGGGAAGCGTCCG
+
+	g5  AAGGTACGGGAACCGTCCG
+
+	g6  AAAGTACGGGACCCGTGCG
+
+	g7  AACGTACGGGAACCGTGCG
+
+	g8  AAAGCACGGGAACCGTGCG
+
+	g9  AACGCACGAGAACCGTGCG
+
+
+;
+
+
+		BLOCKID WM1148c2865eb0;
+
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file contains a small set of taxa representing gene copies within a population.  The chart shows the depth to the last coalescence in a sample of 100 gene trees simulated by coalescence.  ^n^nTo change the number of trees sampled, go to the chart window and select "Number of Trees" from the Chart menu.  The effective population size (haploid) is 1000; change this by choosing "Set Ne" from the Chart window..^n^nTo duplicate this file: Select "New" from the File me [...]
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  19;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  19;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  19;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  19;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2914423799126459326 WM1148c2865d916;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5851865005210875165 WM1148c2865eb0;
+			checksum 0 1947097330 WM1148c2865eb0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 442 463;
+			setLocation 2 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #2914423799126459326;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.CoalescentTrees.CoalescentTrees;
+				tell It;
+					getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+					tell It;
+						setEffective 1000;
+						toggleExponential on;
+					endTell;
+				endTell;
+				setSeed 983242234061;
+			endTell;
+			setCalculator  #mesquite.coalesce.TreeDepth.TreeDepth;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 443 426;
+					setLocation 472 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 50;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-associations.nex';
+			setPrevFileName '02-coalescence2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 370 446;
+					setLocation 2 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file contains a small set of taxa representing gene copies within a population.  The chart shows the depth to the last coalescence in a sample of 100 gene trees simulated by coalescence.  ^n^nTo change the number of trees sampled, go to the chart window and select "Number of Trees" from the Chart menu.  The effective population size (haploid) is 1000; change this by choosing "Set Ne" from the Coalescent Simulation submenu of the Chart menu of the Chart window.^n^ [...]
+				setTitle Gene_tree_depths;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/04-associations.nex b/Resources/examples/Coalescence/04-associations.nex
new file mode 100755
index 0000000..983acdd
--- /dev/null
+++ b/Resources/examples/Coalescence/04-associations.nex
@@ -0,0 +1,476 @@
+#NEXUS
+[written Sat Jun 07 11:24:56 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148c28a29d17;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148c28a2ae18;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 04-associations.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 speciesA,
+		2 speciesB,
+		3 speciesC;
+	TREE Species_tree = ((1,2),3);
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 04-associations.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 geneA1,
+		2 geneA2,
+		3 geneB,
+		4 geneC1,
+		5 geneC2;
+	TREE concordant = (((1,2),3),(4,5));
+	TREE discordant = ((1,2),((4,3),5));
+	TREE unresolved = ((1,2),4,3,5);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'The ability to handle more than one set of taxa in a file, and to associate the taxa between the sets, allows analysis of gene trees within species trees.  This file has a set of taxa of three species, and a second set of taxa for five genes (see tree windows at left).  Above is a species tree drawn using the "Contained Associates" tree drawer, showing a gene tree within the species tree.  Scroll through trees in the gene tree window at left to see that there are thre [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6147812854687186808 WM1148c28a29d17;
+			setID 1 6651160229924971687 WM1148c28a2ae18;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 540 356;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6147812854687186808  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #6147812854687186808;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 558.964495543348.6195579460590305404;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 556 317;
+					setLocation 612 502;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 32 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 4;
+						setOffsetY 32;
+						setNote Species_Tree;
+						setOffsetX 4;
+						setOffsetY 32;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #6651160229924971687  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #6651160229924971687;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 577.964495543796.3141002713096155948;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 556 317;
+					setLocation 5 445;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 34 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 4;
+						setOffsetY 34;
+						setNote Gene_Tree;
+						setOffsetX 4;
+						setOffsetY 34;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #6147812854687186808  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #6147812854687186808;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 596.964495544767.2058576892485762804;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 608 391;
+					setLocation 590 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+						tell It;
+							setTaxa #6651160229924971687;
+							setTreeBlock 1;
+							toggleUseWeights off;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -406;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-twoPopulations.nex';
+			setPrevFileName '03-coalescenceDepth.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 468 339;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The ability to handle more than one set of taxa in a file, and to associate the taxa between the sets, allows analysis of gene trees within species trees.  This file has a set of taxa of three species, and a second set of taxa for five genes (see tree windows at left).  At right is a species tree drawn using the "Contained Associates" tree drawer, showing a gene tree within the species tree.  Scroll through trees in the gene tree window below to see that there are thr [...]
+				setTitle Associations_between_taxa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink 'Tutorial: How to duplicate this file'  'tutorial/01-associationsHow1.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/05-twoPopulations.nex b/Resources/examples/Coalescence/05-twoPopulations.nex
new file mode 100755
index 0000000..e2b78bb
--- /dev/null
+++ b/Resources/examples/Coalescence/05-twoPopulations.nex
@@ -0,0 +1,409 @@
+#NEXUS
+[written Sat Jun 07 11:32:09 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Populations;
+	DIMENSIONS NTAX=2;
+	TAXLABELS
+		East West 
+	;
+	BLOCKID WM1148c2c4a0319;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		East1 East2 East3 East4 West1 West2 West3 West4 West5 
+	;
+	BLOCKID WM1148c2c4a1820;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 05-twoPopulations.nex';
+	LINK Taxa = Populations;
+	TRANSLATE
+		1 East,
+		2 West;
+	TREE tree = (1:10.0,2:10.0):100.0;
+	TREE tree = (1:50.0,2:50.0):100.0;
+	TREE tree = (1:100.0,2:100.0):100.0;
+	TREE tree = (1:200.0,2:200.0):100.0;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE location;
+TAXA Populations ,  genes_sampled;
+ASSOCIATES 
+
+	East /  East1 East2 East3 East4 , 
+	West /  West1 West2 West3 West4 West5
+
+;
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Eastern_samples COLOR = (RGB 0.20392157 1.0 0.42745098) ;
+	TAXAGROUPLABEL Western_Samples COLOR = (RGB 1.0 0.81568627 0.20392157) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Eastern_samples :  1 -  4, Western_Samples :  5 -  9;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Coalescence simulations can be blended with associations between containing and contained trees by simulating gene trees within a species tree.  In this file, the species tree is actually a population tree, and there are only two populations.^n^nThere are two sets of taxa, one representing populations (East and West) and the other representing genes sampled from those populations.  At left is a population tree within which is simulated a gene tree by coalescence.  The [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2717996828273828747 WM1148c2c4a0319;
+			setID 1 2319072353600653909 WM1148c2c4a1820;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 546 521;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #2717996828273828747  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #2717996828273828747;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1442.971300502392.3825508766828255405;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 458;
+					setLocation 572 32;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1442.971300502392.3825508766828255405;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 984411246198;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -424;
+						setInitialOffsetY -177;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(1:50.0,2:50.0):100.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 328 221 123 86;
+						setFont Serif;
+						setFontSize 18;
+						setOffsetX 328;
+						setOffsetY 221;
+						setNote Population_tree_with_contained_gene_tree;
+						setOffsetX 328;
+						setOffsetY 221;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #2319072353600653909  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+					tell It;
+						getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 1442.971300502392.3825508766828255405;
+						endTell;
+						setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+						tell It;
+							getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+							tell It;
+								setEffective 100;
+								toggleExponential on;
+							endTell;
+						endTell;
+						forgetAssociation ;
+					endTell;
+					setSeed 984411246666;
+				endTell;
+				setAssignedID 1471.971300503030.3721084600339604932;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 518 301;
+					setLocation 587 584;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 4;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition off;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 23 4 100 24;
+						setFont Serif;
+						setFontSize 18;
+						setOffsetX 23;
+						setOffsetY 4;
+						setNote Gene_tree;
+						setOffsetX 23;
+						setOffsetY 4;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-twoPopulations2.nex';
+			setPrevFileName '04-associations.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 474 504;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Coalescence simulations can be blended with associations between containing and contained trees by simulating gene trees within a species tree.  In this file, the species tree is actually a population tree, and there are only two populations.^n^nThere are two sets of taxa, one representing populations (East and West) and the other representing genes sampled from those populations.  At right, above, is a population tree within which is simulated a gene tree by coalesce [...]
+				setTitle Diverging_populations;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/06-twoPopulations2.nex b/Resources/examples/Coalescence/06-twoPopulations2.nex
new file mode 100755
index 0000000..b42da5c
--- /dev/null
+++ b/Resources/examples/Coalescence/06-twoPopulations2.nex
@@ -0,0 +1,339 @@
+#NEXUS
+[written Sat Jun 07 11:25:29 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Populations;
+	DIMENSIONS NTAX=2;
+	TAXLABELS
+		East West 
+	;
+	BLOCKID WM1148e5376f035;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		East1 East2 East3 East4 West1 West2 West3 West4 West5 
+	;
+	BLOCKID WM1148e5376fa36;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 06-twoPopulations2.nex';
+	LINK Taxa = Populations;
+	TRANSLATE
+		1 East,
+		2 West;
+	TREE tree = (1:10.0,2:10.0):100.0;
+	TREE tree = (1:50.0,2:50.0):100.0;
+	TREE tree = (1:100.0,2:100.0):100.0;
+	TREE tree = (1:200.0,2:200.0):100.0;
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Eastern_samples COLOR = (RGB 0.20392157 1.0 0.42745098) ;
+	TAXAGROUPLABEL Western_Samples COLOR = (RGB 1.0 0.81568627 0.20392157) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Eastern_samples :  1 -  4, Western_Samples :  5 -  9;
+
+END;
+
+BEGIN TaxaAssociation;
+TITLE location;
+TAXA Populations ,  genes_sampled;
+ASSOCIATES 
+
+	East /  East1 East2 East3 East4 , 
+	West /  West1 West2 West3 West4 West5
+
+;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'The degree to which the gene tree is expected to show a clean separation of genes sampled in the West from those sampled in the East depends on the time since separation of the populations.  Slatkin and Maddison (1989) suggested using as a statistic the number of parsimony steps in a character for the genes whose states represent the source population of the genes (i.e., location sampled).  The time since separation can be estimated by measuring "s" on a reconstructed [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7114850956850836156 WM1148e5376f035;
+			setID 1 4791169349505029750 WM1148e5376fa36;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 522 397;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7114850956850836156  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #7114850956850836156;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1533.971300618301.6347497454875668222;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 467 413;
+					setLocation 565 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1533.971300618301.6347497454875668222;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 984411288026;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -142;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 2;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #4791169349505029750;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+				tell It;
+					getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1533.971300618301.6347497454875668222;
+					endTell;
+					setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 100;
+							toggleExponential on;
+						endTell;
+					endTell;
+					forgetAssociation ;
+				endTell;
+				setSeed 984411288443;
+			endTell;
+			setCalculator  #mesquite.coalesce.SlatkinMaddisonS.SlatkinMaddisonS;
+			tell It;
+				getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+				tell It;
+					setCurrentAssociation 0;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 513 323;
+					setLocation 10 515;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 0;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-fluctuating.nex';
+			setPrevFileName '05-twoPopulations.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 450 380;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The degree to which the gene tree is expected to show a clean separation of genes sampled in the West from those sampled in the East depends on the time since separation of the populations.  Slatkin and Maddison (1989) suggested using as a statistic the number of parsimony steps in a character for the genes whose states represent the source population of the genes (i.e., location sampled).  The time since separation can be estimated by measuring "s" on a reconstructed [...]
+				setTitle Coalescence_depth;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/08-fluctuating.nex b/Resources/examples/Coalescence/08-fluctuating.nex
new file mode 100755
index 0000000..d8a642c
--- /dev/null
+++ b/Resources/examples/Coalescence/08-fluctuating.nex
@@ -0,0 +1,313 @@
+#NEXUS
+[written Sat Jun 07 11:25:37 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE population;
+	DIMENSIONS NTAX=1;
+	TAXLABELS
+		population 
+	;
+	BLOCKID WM1148e54189c37;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes;
+	DIMENSIONS NTAX=8;
+	TAXLABELS
+		g_1 g_2 g_3 g_4 g_5 g_6 g_7 g_8 
+	;
+	BLOCKID WM1148e5418b238;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE Untitled;
+TAXA population ,  genes;
+ASSOCIATES 
+
+	population /  g_1 g_2 g_3 g_4 g_5 g_6 g_7 g_8
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 08-fluctuating.nex';
+	LINK Taxa = population;
+	TRANSLATE
+		1 population;
+	TREE three_segments = (((1:100.0[%width = 10.0 ]):100.0[%width = 10.0 ]):100.0[%width = 10.0 ]):100.0[%width = 1.0 ];
+	TREE oneBottleneck = (((1:100.0[%width = 10.0 ]):100.0[%width = 1.0 ]):100.0[%width = 10.0 ]):100.0[%width = 1.0 ];
+	TREE twoBottlenecks = (((((1:100.0[%width = 10.0 ]):100.0[%width = 1.0 ]):100.0[%width = 10.0 ]):100.0[%width = 1.0 ]):100.0[%width = 10.0 ]):100.0[%width = 1.0 ];
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8262476367526418552 WM1148e54189c37;
+			setID 1 5229699258384705612 WM1148e5418b238;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 475 460;
+			setLocation 9 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8262476367526418552  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #8262476367526418552;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1678.971300678609.5190757585608322126;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 686 424;
+					setLocation 532 35;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.coalesce.LineageWidth.WidthsToolExtra.LineageWidth;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 128;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1678.971300678609.5190757585608322126;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 984411941782;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -142;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 2;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #5229699258384705612;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+				tell It;
+					getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1678.971300678609.5190757585608322126;
+					endTell;
+					setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 100;
+							toggleExponential on;
+						endTell;
+					endTell;
+					forgetAssociation ;
+				endTell;
+				setSeed 984411942829;
+			endTell;
+			setCalculator  #mesquite.coalesce.TreeDepth.TreeDepth;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 561 268;
+					setLocation 231 550;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 50;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 4;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 500;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-genesInSpecies.nex';
+			setPrevFileName '06-twoPopulations2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 403 443;
+					setLocation 9 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows the effects of fluctuating population size on coalescent gene tree depth.  There are two sets of taxa, the genes and the populations.  But there is only a single population, and so the population tree containing the gene tree consists of a single population descending through time.  By placing unbranched nodes (using the Insert Node tool) the population history has been broken into segments, each of which has its own length (time) and width (population [...]
+				setTitle Fluctuating_Ne;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/09-genesInSpecies.nex b/Resources/examples/Coalescence/09-genesInSpecies.nex
new file mode 100755
index 0000000..bd01e2f
--- /dev/null
+++ b/Resources/examples/Coalescence/09-genesInSpecies.nex
@@ -0,0 +1,455 @@
+#NEXUS
+[written Sat Jun 07 11:29:53 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=8;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Huichoros Jotinupa 
+	;
+	BLOCKID WM1148e549b6239;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		nd1_Aus1 nd1_Aus2 nd1_Aus3 nd1_Aus4 nd1_Fubonidia1 nd1_Ibbinidibe1 nd1_Ibbinidibe2 nd1_Snorolopa1 nd1_Quidnubia1 nd1_Quidnubia2 nd1_Suinon1 nd1_Suinon2 nd1_Huichoros1 nd1_Huichoros2 nd1_Huichoros3 nd1_Jotinupa1 
+	;
+	BLOCKID WM1148e549b7940;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 09-genesInSpecies.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE short_branches = (((9:10.0,3:30.0):30.0,(6:16.0,5:24.0):20.0):30.0,((1:19.0,4:22.0):20.0,(8:30.0,2:23.0):30.0):20.0):100.0;
+	TREE medium_branches = (((9:110.0,3:130.0):120.0,(6:116.0,5:124.0):120.0):130.0,((1:119.0,4:122.0):120.0,(8:130.0,2:123.0):130.0):120.0):100.0;
+	TREE long_branches = (((9:410.0,3:490.0):400.0,(6:496.0,5:494.0):420.0):490.0,((1:430.0,4:440.0):436.0,(8:430.0,2:440.0):430.0):420.0):100.0;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 09-genesInSpecies.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 nd1_Aus1,
+		2 nd1_Aus2,
+		3 nd1_Aus3,
+		4 nd1_Aus4,
+		5 nd1_Fubonidia1,
+		6 nd1_Ibbinidibe1,
+		7 nd1_Ibbinidibe2,
+		8 nd1_Snorolopa1,
+		9 nd1_Quidnubia1,
+		10 nd1_Quidnubia2,
+		11 nd1_Suinon1,
+		12 nd1_Suinon2,
+		13 nd1_Huichoros1,
+		14 nd1_Huichoros2,
+		15 nd1_Huichoros3,
+		16 nd1_Jotinupa1;
+	TREE first = (((((((1,2),3),4),(9,10)),8),((11,12),5)),((6,7),(((13,14),15),16)));
+	TREE second = ((((((1,(9,3)),4),10),8),(((11,12),2),5)),((6,7),(((13,14),15),16)));
+	TREE third = (((((1,(9,3)),(4,10)),8),(((11,12),2),5)),((6,7),((13,14),(15,16))));
+	TREE fourth = ((((1,(9,3)),8),(((11,12),2),5)),((6,7),(((13,14),(4,10)),(15,16))));
+	TREE fifth = (((1,8),((((11,12),15),2),5)),((6,7),(((13,14),(4,10)),((9,3),16))));
+	TREE sixth = (((1,8),((11,15),5)),((6,7),((((13,14),2),((4,12),10)),((9,3),16))));
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE ND1;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	Aus /  nd1_Aus1 nd1_Aus2 nd1_Aus3 nd1_Aus4 , 
+	Fubonidia /  nd1_Fubonidia1 , 
+	Ibbinidibe /  nd1_Ibbinidibe1 nd1_Ibbinidibe2 , 
+	Snorolopa /  nd1_Snorolopa1 , 
+	Quidnubia /  nd1_Quidnubia1 nd1_Quidnubia2 , 
+	Suinon /  nd1_Suinon1 nd1_Suinon2 , 
+	Huichoros /  nd1_Huichoros1 nd1_Huichoros2 nd1_Huichoros3 , 
+	Jotinupa /  nd1_Jotinupa1
+
+;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows gene tree in species trees.  There are two sets of taxa, the species ("Species") and the genes ("Genes").   In the window above, the species tree is shown with a gene tree within it.  The gene tree is simulated by coalescence within the species tree, with an effective population size of 50 (the simulations are inefficient) and time-length of a branch representing generations.  Scrolling the "Contained Tree" legend you can see other simulated gene trees [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2046441391949022346 WM1148e549b6239;
+			setID 1 5956075209877644797 WM1148e549b7940;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 622 392;
+			setLocation 8 24;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #2046441391949022346  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #2046441391949022346;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1781.971300755730.9011240768122521286;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 375;
+					setLocation 682 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 66;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1781.971300755730.9011240768122521286;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 984412128481;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #5956075209877644797;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+				tell It;
+					getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1781.971300755730.9011240768122521286;
+					endTell;
+					setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 100;
+							toggleExponential on;
+						endTell;
+					endTell;
+					forgetAssociation ;
+				endTell;
+				setSeed 984412128990;
+			endTell;
+			setCalculator  #mesquite.coalesce.SlatkinMaddisonS.SlatkinMaddisonS;
+			tell It;
+				getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+				tell It;
+					setCurrentAssociation 0;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 615 325;
+					setLocation 696 491;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 0;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #5956075209877644797;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+				tell It;
+					getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 1781.971300755730.9011240768122521286;
+					endTell;
+					setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 100;
+							toggleExponential on;
+						endTell;
+					endTell;
+					forgetAssociation ;
+				endTell;
+				setSeed 984412129472;
+			endTell;
+			setCalculator  #mesquite.coalesce.DeepCoalescencesG.DeepCoalescencesG;
+			tell It;
+				setTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1781.971300755730.9011240768122521286;
+				endTell;
+				getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+				tell It;
+					setCurrentAssociation 0;
+				endTell;
+				getEmployee #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+				tell It;
+					toggleUnrooted off;
+					toggleResolve on;
+					toggleUseLengths on;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 660 344;
+					setLocation 5 464;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 0;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 100;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-speciesTreeSearch.nex';
+			setPrevFileName '08-fluctuating.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 550 375;
+					setLocation 8 24;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows gene tree in species trees.  There are two sets of taxa, the species ("Species") and the genes ("Genes").   In the Tree Window, the species tree is shown with a gene tree within it.  The gene tree is simulated by coalescence within the species tree, with an effective population size of 50 (the simulations are inefficient) and time-length of a branch representing generations.  Scrolling the "Contained Tree" legend you can see other simulated gene trees. [...]
+				setTitle Gene_in_species_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/10-speciesTreeSearch.nex b/Resources/examples/Coalescence/10-speciesTreeSearch.nex
new file mode 100755
index 0000000..dec0523
--- /dev/null
+++ b/Resources/examples/Coalescence/10-speciesTreeSearch.nex
@@ -0,0 +1,270 @@
+#NEXUS
+[written Sat Jun 07 11:30:00 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Aus Fubonidia Ibbinidibe Snorolopa Quidnubia Suinon Zorabynyx Huichoros Jotinupa 
+	;
+	BLOCKID WM1148e55ddbf41;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		nd1_Aus1 nd1_Aus2 nd1_Aus3 nd1_Aus4 nd1_Fubonidia1 nd1_Ibbinidibe1 nd1_Ibbinidibe2 nd1_Snorolopa1 nd1_Quidnubia1 nd1_Quidnubia2 nd1_Suinon1 nd1_Suinon2 nd1_Huichoros1 nd1_Huichoros2 nd1_Huichoros3 nd1_Jotinupa1 
+	;
+	BLOCKID WM1148e55ddd242;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 10-speciesTreeSearch.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 Aus,
+		2 Fubonidia,
+		3 Ibbinidibe,
+		4 Snorolopa,
+		5 Quidnubia,
+		6 Suinon,
+		7 Zorabynyx,
+		8 Huichoros,
+		9 Jotinupa;
+	TREE First_Tree = ((((1:60.0,5:70.0):40.0,4:30.0):30.0,((7:60.0,6:80.0):30.0,2:40.0):70.0):80.0,((9:40.0,8:60.0):40.0,3:90.0):87.0);
+	TREE Second_Tree = ((((9,((4,1),2)),6),3),((8,7),5));
+	TREE Third_Tree = ((8,((2,6),1)),((((3,9),7),4),5));
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 10-speciesTreeSearch.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 nd1_Aus1,
+		2 nd1_Aus2,
+		3 nd1_Aus3,
+		4 nd1_Aus4,
+		5 nd1_Fubonidia1,
+		6 nd1_Ibbinidibe1,
+		7 nd1_Ibbinidibe2,
+		8 nd1_Snorolopa1,
+		9 nd1_Quidnubia1,
+		10 nd1_Quidnubia2,
+		11 nd1_Suinon1,
+		12 nd1_Suinon2,
+		13 nd1_Huichoros1,
+		14 nd1_Huichoros2,
+		15 nd1_Huichoros3,
+		16 nd1_Jotinupa1;
+	TREE gene_tree = (((((((1,2),3),9),(4,10)),8),((11,12),5)),((6,7),(((13,16),15),14)));
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE Genes_in_Species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	Aus /  nd1_Aus1 nd1_Aus2 nd1_Aus3 nd1_Aus4 , 
+	Fubonidia /  nd1_Fubonidia1 , 
+	Ibbinidibe /  nd1_Ibbinidibe1 nd1_Ibbinidibe2 , 
+	Snorolopa /  nd1_Snorolopa1 , 
+	Quidnubia /  nd1_Quidnubia1 nd1_Quidnubia2 , 
+	Suinon /  nd1_Suinon1 nd1_Suinon2 , 
+	Huichoros /  nd1_Huichoros1 nd1_Huichoros2 nd1_Huichoros3 , 
+	Jotinupa /  nd1_Jotinupa1
+
+;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'In this file is a stored gene tree.  Imagine that one sought to infer a species tree using the gene tree.  The species tree shown above containing the gene tree has a lot of discordance with the gene tree, indicated by the high cost (18) of "extra lineages" (also called "deep coalescences" by Maddison 1997).  You can try moving branches of the species tree to try find one that is more concordant with the gene tree.^n^nMesquite has a general concept of "a number for a  [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3724502825702124430 WM1148e55ddbf41;
+			setID 1 2577575139471600534 WM1148e55ddd242;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 592 515;
+			setLocation 15 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3724502825702124430  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #3724502825702124430;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 686.979143280190.3783168923320340251;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 614 507;
+					setLocation 658 28;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 66;
+						setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+						tell It;
+							setTaxa #2577575139471600534;
+							setTreeBlock 1;
+							toggleUseWeights off;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -514;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((((9:0.2,4:0.6):0.3,3:0.5):0.6,((6:0.2,5:0.5):0.4,1:0.6):0.4):0.3,((8:0.4,7:0.5):0.4,2:0.5):0.3);';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-geneInSpecies2.nex';
+			setPrevFileName '09-genesInSpecies.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 498;
+					setLocation 15 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this file is a stored gene tree.  Imagine that one sought to infer a species tree using the gene tree.  The species tree shown here containing the gene tree has a lot of discordance with the gene tree, indicated by the high cost (18) of "extra lineages" (also called "deep coalescences" by Maddison 1997).  You can try moving branches of the species tree to try find one that is more concordant with the gene tree.^n^nMesquite has a general concept of "a number for a t [...]
+				setTitle Best_species_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/11-geneInSpecies2.nex b/Resources/examples/Coalescence/11-geneInSpecies2.nex
new file mode 100755
index 0000000..f909ef1
--- /dev/null
+++ b/Resources/examples/Coalescence/11-geneInSpecies2.nex
@@ -0,0 +1,465 @@
+#NEXUS
+[written Sat Jun 07 11:30:11 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE genes;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 g10 g11 g12 g13 g14 g15 
+	;
+	BLOCKID WM1148e56383f43;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE species;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		speciesA speciesB speciesC speciesD speciesE 
+	;
+	BLOCKID WM1148e56385444;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE genes_in_species;
+TAXA species ,  genes;
+ASSOCIATES 
+
+	speciesA /  g0 g1 g2 g3 , 
+	speciesB /  g4 g5 g6 , 
+	speciesC /  g7 g8 g9 , 
+	speciesD /  g10 g11 g12 , 
+	speciesE /  g13 g14 g15
+
+;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "11-geneInSpecies2.nex"';
+	LINK TAXA = genes;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4";
+	MATRIX
+	g0   0
+	g1   0
+	g2   0
+	g3   0
+	g4   1
+	g5   1
+	g6   1
+	g7   2
+	g8   2
+	g9   2
+	g10  3
+	g11  3
+	g12  3
+	g13  4
+	g14  4
+	g15  4
+
+;
+		BLOCKID WM1148e5638680;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees block 2 from 11-geneInSpecies2.nex';
+	LINK Taxa = genes;
+	TRANSLATE
+		1 g0,
+		2 g1,
+		3 g2,
+		4 g3,
+		5 g4,
+		6 g5,
+		7 g6,
+		8 g7,
+		9 g8,
+		10 g9,
+		11 g10,
+		12 g11,
+		13 g12,
+		14 g13,
+		15 g14,
+		16 g15;
+	TREE tree1 = (((((1,(4,2)),15),((6,8),(7,(12,((11,14),(13,((10,16),5))))))),3),9);
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 11-geneInSpecies2.nex';
+	LINK Taxa = species;
+	TRANSLATE
+		1 speciesA,
+		2 speciesB,
+		3 speciesC,
+		4 speciesD,
+		5 speciesE;
+	TREE branches_300_generations = ((1:300.0,2:300.0):300.0,((3:300.0,4:300.0):300.0,5:300.0):300.0):100.0;
+	TREE branches_100_generations = ((1:100.0,2:100.0):100.0,((3:100.0,4:100.0):100.0,5:100.0):100.0):100.0;
+	TREE branches_50_generations = ((1:50.0,2:50.0):50.0,((3:50.0,4:50.0):50.0,5:50.0):50.0):100.0;
+	TREE branches_10_generations = ((1:10.0,2:10.0):10.0,((3:10.0,4:10.0):10.0,5:10.0):10.0):100.0;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows genes within a species tree.  Above left is the species tree, with a gene tree simulated by coalescence within it.  Note that the branches are 3 units long, where a unit is generations times the effective population size.  At this branch length, most of the time the gene copies coalesce within a species lineage before reaching an ancestor.^n^nAt right are gene trees simulated by coalescence within the species tree.  The character traced reflects the so [...]
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 9111955463946540057 WM1148e56383f43;
+			setID 1 2657072223882610337 WM1148e56385444;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5995841124927942431 WM1148e5638680;
+			checksum 0 392543930 WM1148e5638680;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 558 243;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #2657072223882610337  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #2657072223882610337;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1937.971300798628.1753245341533659733;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 619 554;
+					setLocation 20 342;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1937.971300798628.1753245341533659733;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 984412357003;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -402;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #9111955463946540057;
+			setNumColumns 3;
+			setNumRows 3;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+					tell It;
+						getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 1937.971300798628.1753245341533659733;
+						endTell;
+						setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+						tell It;
+							getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+							tell It;
+								setEffective 100;
+								toggleExponential on;
+							endTell;
+						endTell;
+						forgetAssociation ;
+					endTell;
+					setSeed 984412357678;
+				endTell;
+				assignNumTrees 100;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+			tell It;
+				suspend ;
+				setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+				tell It;
+					toggleLabels off;
+					toggleGray off;
+				endTell;
+				setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+				tell It;
+					getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setTaxa #9111955463946540057;
+							setDataSet #5995841124927942431;
+						endTell;
+					endTell;
+					setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+					tell It;
+						setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+						toggleMPRsMode off;
+					endTell;
+				endTell;
+				setCharacter 1;
+				setMapping 1;
+				toggleShowLegend off;
+				toggleGray off;
+				toggleWeights on;
+				resume ;
+			endTell;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 535 638;
+				setLocation 718 51;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle off;
+						toggleScale on;
+						toggleBroadScale off;
+						toggleCenter off;
+						toggleEven off;
+					endTell;
+					setEdgeWidth 12;
+					orientRight;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setFont SanSerif;
+					setFontSize 10;
+					setColor Black;
+					toggleColorPartition on;
+					toggleShadePartition off;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 'outOfAfrica/01-outOfAfrica.nex';
+			setPrevFileName '10-speciesTreeSearch.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 558 226;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows genes within a species tree.  In the window with a single tree is the species tree, with a gene tree simulated by coalescence within it.  Note that the branches are 3 units long, where a unit is generations times the effective population size.  At this branch length, most of the time the gene copies coalesce within a species lineage before reaching an ancestor.^n^nIn the multi-tree window are gene trees simulated by coalescence within the species tree. [...]
+				setTitle Branch_lengths;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/outOfAfrica/01-outOfAfrica.nex b/Resources/examples/Coalescence/outOfAfrica/01-outOfAfrica.nex
new file mode 100755
index 0000000..cef10b7
--- /dev/null
+++ b/Resources/examples/Coalescence/outOfAfrica/01-outOfAfrica.nex
@@ -0,0 +1,232 @@
+#NEXUS
+[written Sat Jun 07 11:30:21 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE populations;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		Africa Eurasia chimpanzee 
+	;
+	BLOCKID WM1148e575fb845;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 C1 C2 C3 C4 C5 
+	;
+	BLOCKID WM1148e575fd146;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-outOfAfrica.nex"';
+	LINK TAXA = genes_sampled;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 root_?, 2 rooted_in_E, 3 rooted_in_A ; 
+	MATRIX
+	A1   000
+	A2   000
+	A3   000
+	A4   000
+	A5   000
+	A6   000
+	A7   000
+	A8   000
+	A9   000
+	A10  000
+	E1   111
+	E2   111
+	E3   111
+	E4   111
+	E5   111
+	E6   111
+	E7   111
+	E8   111
+	E9   111
+	E10  111
+	C1   ?10
+	C2   ?10
+	C3   ?10
+	C4   ?10
+	C5   ?10
+
+;
+		BLOCKID WM1148e575feb0;
+
+
+END;
+BEGIN TaxaAssociation;
+TITLE genes_in_populations;
+TAXA populations ,  genes_sampled;
+ASSOCIATES 
+
+	Africa /  A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 , 
+	Eurasia /  E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 , 
+	chimpanzee /  C1 C2 C3 C4 C5
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 01-outOfAfrica.nex';
+	LINK Taxa = populations;
+	TRANSLATE
+		1 Africa,
+		2 Eurasia,
+		3 chimpanzee;
+	TREE bottleneck_0.5 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.5 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.1 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.1 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.01 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.01 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Africa COLOR = (RGB 1.0 0.70196078 0.12941176) ;
+	TAXAGROUPLABEL Eurasia COLOR = (RGB 0.05882353 1.0 0.60392157) ;
+	TAXAGROUPLABEL Chimp COLOR = (RGB 0.50980392 0.13725490 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Africa :  1 -  10, Eurasia :  11 -  20, Chimp :  21 -  25;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  3;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  3;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 703462755303490792 WM1148e575fb845;
+			setID 1 2887061083080516111 WM1148e575fd146;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7325247286052868622 WM1148e575feb0;
+			checksum 0 1674843106 WM1148e575feb0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 31 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #703462755303490792 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #703462755303490792;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 365 156;
+					setLocation 404 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #2887061083080516111 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2887061083080516111;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 355 658;
+					setLocation 781 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-outOfAfrica.nex';
+			setPrevFileName '../11-geneInSpecies2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 447;
+					setLocation 31 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This example shows how large population size can confuse estimations of ancestral localities in a gene tree.  For instance, consider the rooting of a human gene tree in Africa as evidence for the "Out of Africa" hypothesis.  An alternative interpretation is that Africa had a persistently larger population size than Eurasia.^n^nIn this ficticious data file there are three populations, Africa and Eurasia for humans and a third population, chimps.  A second block of taxa [...]
+				setTitle Out_of_Africa;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/outOfAfrica/02-outOfAfrica.nex b/Resources/examples/Coalescence/outOfAfrica/02-outOfAfrica.nex
new file mode 100755
index 0000000..a475b30
--- /dev/null
+++ b/Resources/examples/Coalescence/outOfAfrica/02-outOfAfrica.nex
@@ -0,0 +1,419 @@
+#NEXUS
+[written Sat Jun 07 11:30:31 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE populations;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		Africa Eurasia chimpanzee 
+	;
+	BLOCKID WM1148e57d62e47;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 C1 C2 C3 C4 C5 
+	;
+	BLOCKID WM1148e57d63648;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-outOfAfrica.nex"';
+	LINK TAXA = genes_sampled;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 root_?, 2 rooted_in_E, 3 rooted_in_A ; 
+	MATRIX
+	A1   000
+	A2   000
+	A3   000
+	A4   000
+	A5   000
+	A6   000
+	A7   000
+	A8   000
+	A9   000
+	A10  000
+	E1   111
+	E2   111
+	E3   111
+	E4   111
+	E5   111
+	E6   111
+	E7   111
+	E8   111
+	E9   111
+	E10  111
+	C1   ?10
+	C2   ?10
+	C3   ?10
+	C4   ?10
+	C5   ?10
+
+;
+		BLOCKID WM1148e57d6480;
+
+
+END;
+BEGIN TaxaAssociation;
+TITLE genes_in_populations;
+TAXA populations ,  genes_sampled;
+ASSOCIATES 
+
+	Africa /  A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 , 
+	Eurasia /  E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 , 
+	chimpanzee /  C1 C2 C3 C4 C5
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 02-outOfAfrica.nex';
+	LINK Taxa = populations;
+	TRANSLATE
+		1 Africa,
+		2 Eurasia,
+		3 chimpanzee;
+	TREE bottleneck_0.5 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.5 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.1 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.1 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.01 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.01 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Africa COLOR = (RGB 1.0 0.70196078 0.12941176) ;
+	TAXAGROUPLABEL Eurasia COLOR = (RGB 0.05882353 1.0 0.60392157) ;
+	TAXAGROUPLABEL Chimp COLOR = (RGB 0.50980392 0.13725490 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Africa :  1 -  10, Eurasia :  11 -  20, Chimp :  21 -  25;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  3;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  3;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 703462755303490792 WM1148e57d62e47;
+			setID 1 2887061083080516111 WM1148e57d63648;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7325247286052868622 WM1148e57d6480;
+			checksum 0 1674843106 WM1148e57d6480;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 542 234;
+			setLocation 11 25;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #703462755303490792  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #703462755303490792;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 401.982328606974.8040224577453098533;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 490 578;
+					setLocation 592 32;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 401.982328606974.8040224577453098533;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100000;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 983165680400;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -350;
+						setInitialOffsetY -181;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.trees.MultiTreeWindowMaker.MultiTreeWindowMaker;
+		tell It;
+			setTaxa #2887061083080516111;
+			setNumColumns 2;
+			setNumRows 2;
+			getTreeSource #mesquite.trees.DefiniteTreeSource.DefiniteTreeSource;
+			tell It;
+				setTreeSource #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+					tell It;
+						getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 401.982328606974.8040224577453098533;
+						endTell;
+						setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+						tell It;
+							getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+							tell It;
+								setEffective 100000;
+								toggleExponential on;
+							endTell;
+						endTell;
+						forgetAssociation ;
+					endTell;
+					setSeed 983166394560;
+				endTell;
+				assignNumTrees 100;
+			endTell;
+			makeWindow;
+			toggleLegendBotRight off;
+			setNamesVisible on;
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 543 583;
+				setLocation 11 326;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+			tell It;
+				suppress;
+				setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+				tell It;
+					setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+					tell It;
+						stretchToggle off;
+						branchLengthsToggle on;
+						toggleScale off;
+						toggleBroadScale off;
+						toggleCenter on;
+						toggleEven on;
+						setFixedScaling 40000.0;
+					endTell;
+					setEdgeWidth 3;
+					orientRight;
+				endTell;
+				setBackground White;
+				setBranchColor Black;
+				showNodeNumbers off;
+				showBranchColors on;
+				labelBranchLengths off;
+				centerBrLenLabels on;
+				showBrLensUnspecified on;
+				showBrLenLabelsOnTerminals on;
+				setBrLenLabelColor 0 0 255;
+				setNumBrLenDecimals 6;
+				desuppress;
+				getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+				tell It;
+					setColor Black;
+					toggleColorPartition off;
+					toggleShadePartition on;
+					toggleNodeLabels on;
+					toggleCenterNodeNames off;
+					toggleShowNames on;
+					namesAngle ?;
+				endTell;
+			endTell;
+			showWindow;
+			getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+			tell It;
+				colorByPartition off;
+			endTell;
+			getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+			tell It;
+				setOn on;
+				setDigits 4;
+				writeAsPercentage off;
+				toggleHorizontal on;
+				setFontSize 10;
+				setOffset 0  0;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-outOfAfrica.nex';
+			setPrevFileName '01-outOfAfrica.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 542 217;
+					setLocation 11 25;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In the single Tree window, the population tree shows two sister populations for Africa and Eurasia; neither is ancestral to the other.  Note the bottleneck in Eurasia.  In the multi-tree window are gene trees simulated by coalescence within the population tree.  Note that there is some mixing, but not much, between African and Eurasian gene clades.^n^nIn the file are stored several alternative population trees, differing by the strength of the bottleneck.  To see the  [...]
+				setTitle Simulated_gene_trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/outOfAfrica/03-outOfAfrica.nex b/Resources/examples/Coalescence/outOfAfrica/03-outOfAfrica.nex
new file mode 100755
index 0000000..404bfcb
--- /dev/null
+++ b/Resources/examples/Coalescence/outOfAfrica/03-outOfAfrica.nex
@@ -0,0 +1,570 @@
+#NEXUS
+[written Sat Jun 07 11:30:42 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE populations;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		Africa Eurasia chimpanzee 
+	;
+	BLOCKID WM1148e589c4949;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 C1 C2 C3 C4 C5 
+	;
+	BLOCKID WM1148e589c5b50;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-outOfAfrica.nex"';
+	LINK TAXA = genes_sampled;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 root_?, 2 rooted_in_E, 3 rooted_in_A ; 
+	MATRIX
+	A1   000
+	A2   000
+	A3   000
+	A4   000
+	A5   000
+	A6   000
+	A7   000
+	A8   000
+	A9   000
+	A10  000
+	E1   111
+	E2   111
+	E3   111
+	E4   111
+	E5   111
+	E6   111
+	E7   111
+	E8   111
+	E9   111
+	E10  111
+	C1   ?10
+	C2   ?10
+	C3   ?10
+	C4   ?10
+	C5   ?10
+
+;
+		BLOCKID WM1148e589c6b0;
+
+
+END;
+BEGIN TaxaAssociation;
+TITLE genes_in_populations;
+TAXA populations ,  genes_sampled;
+ASSOCIATES 
+
+	Africa /  A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 , 
+	Eurasia /  E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 , 
+	chimpanzee /  C1 C2 C3 C4 C5
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 03-outOfAfrica.nex';
+	LINK Taxa = populations;
+	TRANSLATE
+		1 Africa,
+		2 Eurasia,
+		3 chimpanzee;
+	TREE bottleneck_0.5 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.5 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.1 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.1 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.01 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.01 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Africa COLOR = (RGB 1.0 0.70196078 0.12941176) ;
+	TAXAGROUPLABEL Eurasia COLOR = (RGB 0.05882353 1.0 0.60392157) ;
+	TAXAGROUPLABEL Chimp COLOR = (RGB 0.50980392 0.13725490 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Africa :  1 -  10, Eurasia :  11 -  20, Chimp :  21 -  25;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  3;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  3;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 703462755303490792 WM1148e589c4949;
+			setID 1 2887061083080516111 WM1148e589c5b50;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7325247286052868622 WM1148e589c6b0;
+			checksum 0 1674843106 WM1148e589c6b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 527 419;
+			setLocation 17 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #703462755303490792  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #703462755303490792;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 401.982328606974.8040224577453098533;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 667 374;
+					setLocation 587 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 401.982328606974.8040224577453098533;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100000;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 983165680400;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -525;
+						setInitialOffsetY -209;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 3;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #2887061083080516111  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+				tell It;
+					setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+					tell It;
+						getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+						tell It;
+							setContextID 401.982328606974.8040224577453098533;
+						endTell;
+						setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+						tell It;
+							getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+							tell It;
+								setEffective 100000;
+								toggleExponential on;
+							endTell;
+						endTell;
+						forgetAssociation ;
+					endTell;
+					setSeed 983165302039;
+				endTell;
+				setAssignedID 359.982329727023.8315870631220030835;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 524 422;
+					setLocation 43 523;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition off;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 524 462;
+						setLocation 646 502;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #2887061083080516111;
+									setDataSet #7325247286052868622;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -161;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #2887061083080516111;
+									setDataSet #7325247286052868622;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -163;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition off;
+							toggleShadePartition on;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-outOfAfrica.nex';
+			setPrevFileName '02-outOfAfrica.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 527 402;
+					setLocation 17 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Even though Africa and Eurasia are sister populations, and thus neither is ancestral to the other, does the bottleneck in Eurasia cause simulated gene trees to be biased toward showing a rooting in Africa? Mesquite does not yet have a method to count root locations of gene trees, but a trick allows us to count.  This data file has two artificial characters, shown in the mirror tree window.  One assigns states 0, 0, 1 to chimp genes, African genes and Eurasian genes, r [...]
+				setTitle Effect_of_bottleneck;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/outOfAfrica/04-outOfAfrica.nex b/Resources/examples/Coalescence/outOfAfrica/04-outOfAfrica.nex
new file mode 100755
index 0000000..e2b3293
--- /dev/null
+++ b/Resources/examples/Coalescence/outOfAfrica/04-outOfAfrica.nex
@@ -0,0 +1,401 @@
+#NEXUS
+[written Sat Jun 07 11:30:52 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE populations;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		Africa Eurasia chimpanzee 
+	;
+	BLOCKID WM1148e7859e85;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE genes_sampled;
+	DIMENSIONS NTAX=25;
+	TAXLABELS
+		A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 C1 C2 C3 C4 C5 
+	;
+	BLOCKID WM1148e7859ff6;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-outOfAfrica.nex"';
+	LINK TAXA = genes_sampled;
+	DIMENSIONS  NCHAR=3;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 root_?, 2 rooted_in_E, 3 rooted_in_A ; 
+	MATRIX
+	A1   000
+	A2   000
+	A3   000
+	A4   000
+	A5   000
+	A6   000
+	A7   000
+	A8   000
+	A9   000
+	A10  000
+	E1   111
+	E2   111
+	E3   111
+	E4   111
+	E5   111
+	E6   111
+	E7   111
+	E8   111
+	E9   111
+	E10  111
+	C1   ?10
+	C2   ?10
+	C3   ?10
+	C4   ?10
+	C5   ?10
+
+;
+		BLOCKID WM1148e785a0c0;
+
+
+END;
+BEGIN TaxaAssociation;
+TITLE genes_in_populations;
+TAXA populations ,  genes_sampled;
+ASSOCIATES 
+
+	Africa /  A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 , 
+	Eurasia /  E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 , 
+	chimpanzee /  C1 C2 C3 C4 C5
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 04-outOfAfrica.nex';
+	LINK Taxa = populations;
+	TRANSLATE
+		1 Africa,
+		2 Eurasia,
+		3 chimpanzee;
+	TREE bottleneck_0.5 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.5 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.1 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.1 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+	TREE bottleneck_0.01 = (3:40000.0[%width = 0.1 ],((1:30000.0[%width = 1.0 ],((2:15000.0[%width = 1.0 ]):5000.0[%width = 0.01 ]):10000.0[%width = 1.0 ]):1000.0[%width = 1.0 ]):9000.0[%width = 0.01 ]):10000.0[%width = 0.1 ];
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Africa COLOR = (RGB 1.0 0.70196078 0.12941176) ;
+	TAXAGROUPLABEL Eurasia COLOR = (RGB 0.05882353 1.0 0.60392157) ;
+	TAXAGROUPLABEL Chimp COLOR = (RGB 0.50980392 0.13725490 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  (TAXA = genes_sampled) =  Africa :  1 -  10, Eurasia :  11 -  20, Chimp :  21 -  25;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  3;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  3;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  3;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 703462755303490792 WM1148e7859e85;
+			setID 1 2887061083080516111 WM1148e7859ff6;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7325247286052868622 WM1148e785a0c0;
+			checksum 0 1674843106 WM1148e785a0c0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 575 323;
+			setLocation 23 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #703462755303490792  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #703462755303490792;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 401.982328606974.8040224577453098533;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 618 404;
+					setLocation 662 28;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+						tell It;
+							setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+							tell It;
+								getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+								tell It;
+									setCurrentAssociation 0;
+								endTell;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 401.982328606974.8040224577453098533;
+								endTell;
+								setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+								tell It;
+									getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+									tell It;
+										setEffective 100000;
+										toggleExponential on;
+									endTell;
+								endTell;
+								forgetAssociation ;
+							endTell;
+							setSeed 983165680400;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -384;
+						setInitialOffsetY -170;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TreeValuesChart.TreeValuesChart;
+		tell It;
+			suspendCalculations;
+			setTaxa #2887061083080516111;
+			setTreeSource  #mesquite.trees.SimulateTree.SimulateTree;
+			tell It;
+				setTreeSimulator  #mesquite.coalesce.ContainedCoalescence.ContainedCoalescence;
+				tell It;
+					getAssociationTask  #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+					getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+					tell It;
+						setContextID 401.982328606974.8040224577453098533;
+					endTell;
+					setSimulator  #mesquite.coalesce.ContainedCoalescSim.ContainedCoalescSim;
+					tell It;
+						getEmployee #mesquite.coalesce.NeutralCoalescence.NeutralCoalescence;
+						tell It;
+							setEffective 100000;
+							toggleExponential on;
+						endTell;
+					endTell;
+					forgetAssociation ;
+				endTell;
+				setSeed 983165461875;
+			endTell;
+			setCalculator  #mesquite.parsimony.CharStepsDifference.CharStepsDifference;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setTaxa #2887061083080516111;
+						setDataSet #7325247286052868622;
+					endTell;
+				endTell;
+				setCharacters 2 3;
+				getEmployee #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 618 404;
+					setLocation 24 422;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					itemsByValues;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 5.0 1.0;
+					setMode 0;
+					resume;
+				endTell;
+					toggleColorItems off;
+					setNumberItems 1000;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			resumeCalculations;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../00-introduction.nex';
+			setPrevFileName '03-outOfAfrica.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 575 306;
+					setLocation 23 26;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The chart shows the number of gene trees that show one more (+1), one less (-1), or the same (0) number of steps with the special character indicating Eurasian rooting than with that indicating African rooting.  (See the previous example file for explanation.) Thus, a +1 indicates the gene tree prefers to root in Africa, a -1 that it prefers to root in Eurasia. ^n^nThe gene trees of the chart are simulated by neutral coalescence within the population tree in the tree  [...]
+				setTitle Probability_of_African_root;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Intro.;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/tutorial/01-associationsHow1.nex b/Resources/examples/Coalescence/tutorial/01-associationsHow1.nex
new file mode 100755
index 0000000..6f20e0b
--- /dev/null
+++ b/Resources/examples/Coalescence/tutorial/01-associationsHow1.nex
@@ -0,0 +1,474 @@
+#NEXUS
+[written Sat Jun 07 11:31:16 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148c2d411a23;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148c2d412124;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 01-associationsHow1.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 speciesA,
+		2 speciesB,
+		3 speciesC;
+	TREE Species_tree = ((1,2),3);
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 01-associationsHow1.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 geneA1,
+		2 geneA2,
+		3 geneB,
+		4 geneC1,
+		5 geneC2;
+	TREE concordant = (((1,2),3),(4,5));
+	TREE discordant = ((1,2),((4,3),5));
+	TREE unresolved = ((1,2),4,3,5);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file contains two sets of taxa, one for genes and one for the species containing them.  Above is a species tree drawn using the "Contained Associates" tree drawer, showing a gene tree within the species tree.  Scroll through trees in the gene tree window at left to see that there are three stored trees, one concordant with the species tree, one discordant, and one poorly resolved. To see each of the gene trees within the species trees, scroll through them in the  [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4420490413033044488 WM1148c2d411a23;
+			setID 1 3639664332017854208 WM1148c2d412124;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 501 319;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4420490413033044488  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #4420490413033044488;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1943.961441437307.6630178226258085721;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 539 301;
+					setLocation 547 481;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 32 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 4;
+						setOffsetY 32;
+						setNote Species_Tree;
+						setOffsetX 4;
+						setOffsetY 32;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #3639664332017854208  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #3639664332017854208;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1962.961441437580.1274436323766023904;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 539 301;
+					setLocation -45 480;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 34 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 4;
+						setOffsetY 34;
+						setNote Gene_Tree;
+						setOffsetX 4;
+						setOffsetY 34;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #4420490413033044488  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #4420490413033044488;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1981.961441437933.4173812948425450185;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 539 301;
+					setLocation 568 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+						tell It;
+							setTaxa #3639664332017854208;
+							setTreeBlock 1;
+							toggleUseWeights off;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -406;
+						setInitialOffsetY -160;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-associationsHow2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 429 302;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file contains two sets of taxa, one for genes and one for the species containing them.  At right is a species tree drawn using the "Contained Associates" tree drawer, showing a gene tree within the species tree.  Scroll through trees in the gene tree window below to see that there are three stored trees, one concordant with the species tree, one discordant, and one poorly resolved. To see each of the gene trees within the species trees, scroll through them in the [...]
+				setTitle Tutorial;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/tutorial/02-associationsHow2.nex b/Resources/examples/Coalescence/tutorial/02-associationsHow2.nex
new file mode 100755
index 0000000..ebdbe89
--- /dev/null
+++ b/Resources/examples/Coalescence/tutorial/02-associationsHow2.nex
@@ -0,0 +1,152 @@
+#NEXUS
+[written Sat Jun 07 11:31:22 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148c2dd53525;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148c2dd54126;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file was created as follows.  First, I chose "New" from the File menu.  I indicated the file name in the file dialog box.  Then, when the dialog box came up asking me about a set of taxa, I entered the name ("Species"), and how many taxa (3).  In the taxa list window (e.g., at left), I renamed the taxa (species A, B, C). Next, I made the second set of taxa (e.g., "Genes") by selecting the "New block of taxa" menu item in the Taxa&Trees menu.^n^nNext, I began to i [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2038936534183152982 WM1148c2dd53525;
+			setID 1 2451688679550742169 WM1148c2dd54126;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 546 303;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #2038936534183152982 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2038936534183152982;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 550 287;
+					setLocation 621 416;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #2451688679550742169 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2451688679550742169;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 550 287;
+					setLocation 23 411;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02b-associationsHow2.nex';
+			setPrevFileName '01-associationsHow1.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 474 286;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'To indicate what genes belong to what species, you need to define a correspondence between taxa in the two taxa blocks (genes and species).^n^nI created this file as follows.  First, I chose "New" from the File menu.  I indicated the file name in the file dialog box.  Then, when the dialog box came up asking me about a set of taxa, I entered the name ("Species"), and how many taxa (3).  In the taxa list window (e.g., at left), I renamed the taxa (species A, B, C). Nex [...]
+				setTitle Building_a_Taxa_Association;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/tutorial/02b-associationsHow2.nex b/Resources/examples/Coalescence/tutorial/02b-associationsHow2.nex
new file mode 100755
index 0000000..4369563
--- /dev/null
+++ b/Resources/examples/Coalescence/tutorial/02b-associationsHow2.nex
@@ -0,0 +1,165 @@
+#NEXUS
+[written Sat Jun 07 11:31:29 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148c2e1e9227;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148c2e1e9628;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file was created as follows.  First, I chose "New" from the File menu.  I indicated the file name in the file dialog box.  Then, when the dialog box came up asking me about a set of taxa, I entered the name ("Species"), and how many taxa (3).  In the taxa list window (e.g., at left), I renamed the taxa (species A, B, C). Next, I made the second set of taxa (e.g., "Genes") by selecting the "New block of taxa" menu item in the Taxa&Trees menu.^n^nNext, I began to i [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2038936534183152982 WM1148c2e1e9227;
+			tell It;
+				setSelected  3;
+				attachments ;
+			endTell;
+			setID 1 2451688679550742169 WM1148c2e1e9628;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 583 306;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #2038936534183152982 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2038936534183152982;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getAssociationsTask Stored Taxa Associations (id# 12358);
+					resetAssociation;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 603 246;
+					setLocation 586 405;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #2451688679550742169 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #2451688679550742169;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 536 252;
+					setLocation 4 403;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-associationsHow3.nex';
+			setPrevFileName '02-associationsHow2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 511 289;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The List of Taxa window above for species has a column showing the genes associated with each species, and at right has an editor for the association.  To change what genes are associated with what species, do the following:^n^n1.  select a species^n2. Go to the Associations Editor panel and touch on the genes you want to assign to that species.  Hit the arrow button to assign the genes.^n^nYou can also use the add and subtract buttons to change what genes are assigne [...]
+				setTitle Building_a_Taxa_Association;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/tutorial/03-associationsHow3.nex b/Resources/examples/Coalescence/tutorial/03-associationsHow3.nex
new file mode 100755
index 0000000..4f095d0
--- /dev/null
+++ b/Resources/examples/Coalescence/tutorial/03-associationsHow3.nex
@@ -0,0 +1,405 @@
+#NEXUS
+[written Sat Jun 07 11:31:52 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148c2e7cf929;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148c2e7d3130;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 03-associationsHow3.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 geneA1,
+		2 geneA2,
+		3 geneB,
+		4 geneC1,
+		5 geneC2;
+	TREE gene_tree = ((1,2),(3,(4,5)));
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 03-associationsHow3.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 speciesA,
+		2 speciesB,
+		3 speciesC;
+	TREE species_tree = ((1,2),3);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'To make and store a species tree, I then selected "Species" from the Tree Window submenu of the Taxa&Trees menu.  The tree window showed a default tree.  I edited the tree, then chose "Store tree" from the Tree menu.  I indicated a species tree name, and a name for the new stored block of trees that would be stored in the file.  Then, I went to the "Tree Source" submenu of the Tree window, to select "Stored Trees" so that the tree window would be using the stored tree [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8288541384075770764 WM1148c2e7cf929;
+			setID 1 6392911796161625183 WM1148c2e7d3130;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 677 402;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #8288541384075770764 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #8288541384075770764;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 605 345;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #6392911796161625183 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #6392911796161625183;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 605 345;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8288541384075770764  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #8288541384075770764;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2074.961441452141.764377467975426235;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 420 246;
+					setLocation 568 494;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 20 0 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 20;
+						setOffsetY 0;
+						setNote Species_Tree;
+						setOffsetX 20;
+						setOffsetY 0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #6392911796161625183  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #6392911796161625183;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2093.961441452522.7571579123104976198;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 464 261;
+					setLocation 27 505;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 32 5 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 32;
+						setOffsetY 5;
+						setNote Gene_Tree;
+						setOffsetX 32;
+						setOffsetY 5;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-associationsHow4.nex';
+			setPrevFileName '02b-associationsHow2.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 605 385;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'To make and store a species tree, I then selected "Species" from the Tree Window submenu of the Taxa&Trees menu.  The tree window showed a default tree.  I edited the tree, then chose "Store tree" from the Tree menu.  I indicated a species tree name, and a name for the new stored block of trees that would be stored in the file.  Then, I went to the "Tree Source" submenu of the Tree window, to select "Stored Trees" so that the tree window would be using the stored tree [...]
+				setTitle Trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Coalescence/tutorial/04-associationsHow4.nex b/Resources/examples/Coalescence/tutorial/04-associationsHow4.nex
new file mode 100755
index 0000000..d05b770
--- /dev/null
+++ b/Resources/examples/Coalescence/tutorial/04-associationsHow4.nex
@@ -0,0 +1,526 @@
+#NEXUS
+[written Sat Jun 07 11:32:02 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Species;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		speciesA speciesB speciesC 
+	;
+	BLOCKID WM1148e51203131;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE Genes;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		geneA1 geneA2 geneB geneC1 geneC2 
+	;
+	BLOCKID WM1148e51204232;
+
+END;
+
+
+BEGIN TaxaAssociation;
+TITLE how_genes_fit_into_species;
+TAXA Species ,  Genes;
+ASSOCIATES 
+
+	speciesA /  geneA1 geneA2 , 
+	speciesB /  geneB , 
+	speciesC /  geneC1 geneC2
+
+;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 04-associationsHow4.nex';
+	LINK Taxa = Genes;
+	TRANSLATE
+		1 geneA1,
+		2 geneA2,
+		3 geneB,
+		4 geneC1,
+		5 geneC2;
+	TREE gene_tree = ((1,2),(3,(4,5)));
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees block 2 from 04-associationsHow4.nex';
+	LINK Taxa = Species;
+	TRANSLATE
+		1 speciesA,
+		2 speciesB,
+		3 speciesC;
+	TREE species_tree = ((1,2),3);
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'I then selected "Species" from the Tree Window submenu of the Taxa&Trees menu to make another tree window for species.  Then, I selected "Contained Associates" from the Tree Form submenu of the Tree menu.  As the source of contained trees, I chose "Stored Trees". ^n^nYou can edit the species tree in the window above to see how the gene tree fits into alternative species trees.^n^nIf you edit the gene tree or species tree in the windows at left, the trees in the window [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1963741844661190195 WM1148e51203131;
+			setID 1 5722364036087266137 WM1148e51204232;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 526 363;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1963741844661190195 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1963741844661190195;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 454 306;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+			showTaxa #5722364036087266137 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #5722364036087266137;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 454 306;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #1963741844661190195  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #1963741844661190195;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1050.961102274764.5286454844660449827;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 537 327;
+					setLocation 608 471;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 25 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 4;
+						setOffsetY 25;
+						setNote Species_Tree;
+						setOffsetX 4;
+						setOffsetY 25;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #5722364036087266137  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #5722364036087266137;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1070.961102275088.6857060515227952487;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 537 327;
+					setLocation 28 476;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 1 32 100 22;
+						setFont SanSerif;
+						setFontSize 14;
+						setOffsetX 1;
+						setOffsetY 32;
+						setNote Gene_Tree;
+						setOffsetX 1;
+						setOffsetY 32;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #1963741844661190195  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTaxa #1963741844661190195;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1090.961102275835.4906690214422134086;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 36;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 537 327;
+					setLocation 589 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.assoc.ContainedAssociates.ContainedAssociates;
+					tell It;
+						suppress ;
+						getAssociationSource  #mesquite.assoc.StoredAssociations.StoredAssociations;
+						tell It;
+							setCurrentAssociation 0;
+						endTell;
+						getReconstructor  #mesquite.coalesce.RecCoalescenceHistory.RecCoalescenceHistory;
+						tell It;
+							toggleUnrooted off;
+							toggleResolve on;
+							toggleUseLengths on;
+						endTell;
+						setEdgeWidth 64;
+						setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+						tell It;
+							setTaxa #5722364036087266137;
+							setTreeBlock 1;
+							toggleUseWeights off;
+						endTell;
+						setContained 1;
+						toggleScale on;
+						setInitialOffsetX -405;
+						setInitialOffsetY -167;
+						desuppress ;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Blue;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../05-twoPopulations.nex';
+			setPrevFileName '03-associationsHow3.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 454 346;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'I then selected "Species" from the Tree Window submenu of the Taxa&Trees menu to make another tree window for species.  Then, I selected "Contained Associates" from the Tree Form submenu of the Tree menu.  As the source of contained trees, I chose "Stored Trees". ^n^nYou can edit the species tree in the window with the blue tree to see how the gene tree fits into alternative species trees.^n^nIf you edit the gene tree or species tree in the windows below, the trees in [...]
+				setTitle Displaying_contained_tree;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/00-introduction.nex b/Resources/examples/Correlation/00-introduction.nex
new file mode 100644
index 0000000..d7fa170
--- /dev/null
+++ b/Resources/examples/Correlation/00-introduction.nex
@@ -0,0 +1,46 @@
+#NEXUS
+[written Sat Jun 07 11:32:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00a-FelsensteinsContrasts.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 447;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 12;
+					setActive;
+				setExplanation 'Phylogenetic tests of whether two characters have correlated evolution can be done in three ways using Mesquite:^n^n(1) Two continuous characters: Felsenstein''s independent contrasts^n^n(2) Two categorical two-state characters: Pagel''s 1994 method.^n^n(3) Two categorical or one categorical and one continuous character: pairwise comparisons.^n^nHere are example files for these various methods^n^nTo go from one file to another, hit the "Next" button';
+				setTitle Character_Correlation;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/00a-FelsensteinsContrasts.nex b/Resources/examples/Correlation/00a-FelsensteinsContrasts.nex
new file mode 100644
index 0000000..af0bc5a
--- /dev/null
+++ b/Resources/examples/Correlation/00a-FelsensteinsContrasts.nex
@@ -0,0 +1,431 @@
+#NEXUS
+[written Sat Jun 07 11:33:27 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=49;
+	TAXLABELS
+		Tm Ur Um Nn pl Mp Ml Cp Ct Lp Ca Uc Vf Hh Cc Aj Pp Pt Pq Tb Cs Db Eh Ec Eb Lg Cd Gc Sc Bb To Gg Gt Ac Mk Oa Oc He Am Cu Dl Ab Aa cq Dd Al Rt Ov Oh 
+	;
+	BLOCKID WM114cc2658fc35;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "00a-FelsensteinsContrasts.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+	MATRIX
+	Tm   2.423245874 2.062957834
+	Ur   2.400192489 1.918030337
+	Um   1.970346876 1.754348336
+	Nn   0.6434526765 0.0211892991
+	pl   0.84509804 0.0569048513
+	Mp   0.3979400087 0.3979400087
+	Ml   1.064457989 -0.060480747
+	Cp   1.547774705 2.307067951
+	Ct   1.123851641 1.653212514
+	Lp   1.301029996 2.204119983
+	Ca   0.9444826722 0.9590413923
+	Uc   0.5682017241 0.0413926852
+	Vf   0.6812412374 0.587710965
+	Hh   1.428134794 2.184123354
+	Cc   1.716003344 1.397940009
+	Aj   1.769377326 1.7930916
+	Pp   1.719331287 1.365487985
+	Pt   2.206825876 1.84260924
+	Pq   2.192567453 2.372912003
+	Tb   2.397940009 0.3010299957
+	Cs   3.301029996 0.8228216453
+	Db   3.079181246 1.193124598
+	Eh   2.301029996 1.544068044
+	Ec   2.544068044 1.352182518
+	Eb   2.371067862 2.217483944
+	Lg   1.977723605 -0.301029996
+	Cd   2.740362689 2.0
+	Gc   3.031408464 1.927370363
+	Sc   2.792391689 2.139879086
+	Bb   2.937016107 2.123851641
+	To   2.7084209 1.942008053
+	Gg   1.795880017 1.301029996
+	Gt   1.311753861 0.7242758696
+	Ac   1.574031268 0.8129133566
+	Mk   0.6989700043 -1.36653154
+	Oa   2.054995862 1.356981401
+	Oc   1.929418926 1.15624619
+	He   2.355068206 1.903089987
+	Am   1.726319612 0.5797835966
+	Cu   2.334453751 1.875061263
+	Dl   2.113943352 0.3424226808
+	Ab   2.133538908 0.6989700043
+	Aa   1.698970004 1.0
+	cq   2.477121255 1.111598525
+	Dd   1.740362689 0.1139433523
+	Al   2.584331224 1.206825876
+	Rt   2.0 1.477121255
+	Ov   1.755874856 0.2922560714
+	Oh   1.86923172 0.45484486
+
+;
+		BLOCKID WM114cc26593f0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "00a-FelsensteinsContrasts.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Tm,
+		2 Ur,
+		3 Um,
+		4 Nn,
+		5 pl,
+		6 Mp,
+		7 Ml,
+		8 Cp,
+		9 Ct,
+		10 Lp,
+		11 Ca,
+		12 Uc,
+		13 Vf,
+		14 Hh,
+		15 Cc,
+		16 Aj,
+		17 Pp,
+		18 Pt,
+		19 Pq,
+		20 Tb,
+		21 Cs,
+		22 Db,
+		23 Eh,
+		24 Ec,
+		25 Eb,
+		26 Lg,
+		27 Cd,
+		28 Gc,
+		29 Sc,
+		30 Bb,
+		31 To,
+		32 Gg,
+		33 Gt,
+		34 Ac,
+		35 Mk,
+		36 Oa,
+		37 Oc,
+		38 He,
+		39 Am,
+		40 Cu,
+		41 Dl,
+		42 Ab,
+		43 Aa,
+		44 cq,
+		45 Dd,
+		46 Al,
+		47 Rt,
+		48 Ov,
+		49 Oh;
+	TREE Untitled_Tree = ((((((1:2000000.0,2:2000000.0)n95:3000000.0,3:5000000.0)n31:3.9E7,((4:5000000.0,5:5000000.0)n92:2.6E7,(6:2.0E7,7:2.0E7)n07:1.1E7)n93:1.3E7)n06:8000000.0,(((((8:2500000.0,9:2500000.0)n34:500000.0,10:3000000.0)n32:3000000.0,11:6000000.0)n28:3000000.0,12:9000000.0)n22:500000.0,13:9500000.0)n21:4.25E7)n05:6000000.0,((14:5000000.0,15:5000000.0)n18:2.1E7,(16:9000000.0,(17:2500000.0,(18:2000000.0,19:2000000.0)n36:500000.0)n35:6500000.0)n23:1.7E7)n10:3.2E7)n03:1.2E7,(((20:5 [...]
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7933746709840163491 WM114cc2658fc35;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4190772235764235829 WM114cc26593f0;
+			checksum 0 2240152432 WM114cc26593f0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 543 451;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7933746709840163491  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 404.985450020823.5565377021587689415;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 471 384;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 2;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 30;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 543 446;
+						setLocation 614 29;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #4190772235764235829;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #4190772235764235829;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 2;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels off;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00b-pagel94Hominids.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 471 434;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This example file shows the distribution of two continuous characters on a tree.  To test whether there is a significant association, Felsenstein''s Independent Contrasts can be used.  ^n^nCalculation of Felsenstein''s independent contrasts is not part of the basic version of Mesquite, but rather is available in the PDAP package of modules for Mesquite.  It is available at http://mesquiteproject.org/pdap_mesquite (see link below).  ^n^nTo learn more about Felsenstein' [...]
+				setTitle 'Felsenstein''s independent contrasts';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Mesquite_PDAP_website  'http://mesquiteproject.org/pdap_mesquite';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/00b-pagel94Hominids.nex b/Resources/examples/Correlation/00b-pagel94Hominids.nex
new file mode 100644
index 0000000..783f97d
--- /dev/null
+++ b/Resources/examples/Correlation/00b-pagel94Hominids.nex
@@ -0,0 +1,395 @@
+#NEXUS
+[written Wed Aug 26 12:13:38 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Homo_sapiens Pan_troglodytes Pan_paniscus Gorilla_gorilla Pongo_pygmaeus Hylobates_syndactylus Hylobates_sp. Colobus_guereza Colobus_badius 
+	;
+	IDS 010a627b503f49 010a627b503f50 010a627b503f51 010a627b503f52 010a627b503f53 010a627b504054 010a627b504055 010a627b504056 010a627fb2ef57 ;
+	BLOCKID 010a627b503c3;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "00b-pagel94Hominids.nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 advertisement /  absent present, 2 mating_system /  one_male 'multi-male' ; 
+	MATRIX
+	Homo_sapiens           00
+	Pan_troglodytes        11
+	Pan_paniscus           11
+	Gorilla_gorilla        00
+	Pongo_pygmaeus         10
+	Hylobates_syndactylus  00
+	Hylobates_sp.          00
+	Colobus_guereza        00
+	Colobus_badius         11
+
+;
+	IDS 010a627b503f4 010a627b503f5 ;
+	BLOCKID WM114cc27480d0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "00b-pagel94Hominids.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Homo_sapiens,
+		2 Pan_troglodytes,
+		3 Pan_paniscus,
+		4 Gorilla_gorilla,
+		5 Pongo_pygmaeus,
+		6 Hylobates_syndactylus,
+		7 Hylobates_sp.,
+		8 Colobus_guereza,
+		9 Colobus_badius;
+	TREE page_16_example = ((8:2.0,9:2.0):56.0,((5:22.0,(4:20.0,(1:29.0,(2:9.0,3:5.0):15.0):11.0):10.0):18.0,(6:3.0,7:2.0):28.0):10.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 878585605735200005 010a627b503c3;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7359026449824636807 WM114cc27480d0;
+			checksumv 0 2 2052433749 WM114cc27480d0;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 462 343;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #878585605735200005  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1199.1144113549683.1862327035904205997;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 702 543;
+					setLocation 488 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BranchLengthsAdjust.AdjustToolExtra.adjustor;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale off;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						setCornerMode Right_Angle  50;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 14;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 0;
+					toggleLegendFloat on;
+					scale 0;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 30;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 476 392;
+						setLocation 12 409;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7359026449824636807;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7359026449824636807;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 2;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								inhibitStretchToggle off;
+								branchLengthsToggle off;
+								toggleScale off;
+								toggleBroadScale off;
+								toggleCenter on;
+								toggleEven on;
+							endTell;
+							setEdgeWidth 10;
+							orientLeft;
+							setCornerMode Right_Angle  50;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFontSize 12;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleShowFootnotes on;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleCentred on;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+					newWindowAssistant  #mesquite.correl.CorrelationViewer.CorrelationViewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #7359026449824636807;
+						endTell;
+					endTell;
+					setCorrelationCalculator  #mesquite.correl.Pagel94.Pagel94;
+					tell It;
+						setSeed 1188836136528;
+						setSimCount 100;
+						togglePresentPValue off;
+						setNumIterations 10;
+					endTell;
+					setX -1;
+					setY 0;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00c-pairwiseIntro.nex';
+			setPrevFileName '00a-FelsensteinsContrasts.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 462 326;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				setExplanation 'Pagel''s 1994 method uses likelihood ratio tests to determine if two categorical characters are correlated.  Mesquite requires the two characters to be binary (0,1) characters.  To turn on an analysis, choose Pagel 94 Analysis from the Analysis:Tree menu of the Tree Window.^n^nThis is an example from Pagel''s Discrete manual.  Two characters appear to be associated as shown in the Mirror tree window above.  At right is the analysis.  To estimate the significance value [...]
+				setTitle 'Pagel''s method';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Page_in_manual  'http://mesquiteproject.wikispaces.com/Processes+of+Character+Evolution#pagel94';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/00c-pairwiseIntro.nex b/Resources/examples/Correlation/00c-pairwiseIntro.nex
new file mode 100644
index 0000000..9cb38be
--- /dev/null
+++ b/Resources/examples/Correlation/00c-pairwiseIntro.nex
@@ -0,0 +1,47 @@
+#NEXUS
+[written Sat Jun 07 11:33:51 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 12 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-pairwise.nex';
+			setPrevFileName '00b-pagel94Hominids.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 628 447;
+					setLocation 12 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The following examples concern pairwise tests of character association^n^nThey illustrate the methods described in: ^n^nMaddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis paper describes methods to choose pairs of taxa for comparative method calculations (tests of character association). The corresponding Mesquite modules automatically find phylogenetically separate pair [...]
+				setTitle Pairwise_comparison_examples;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				setEditorsVisible;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/01-pairwise.nex b/Resources/examples/Correlation/01-pairwise.nex
new file mode 100644
index 0000000..a7e6fc3
--- /dev/null
+++ b/Resources/examples/Correlation/01-pairwise.nex
@@ -0,0 +1,467 @@
+#NEXUS
+[written Sat Jun 07 11:39:52 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=24;
+	TAXLABELS
+		species_0 species_1 species_2 species_3 species_4 species_5 species_6 species_7 species_8 species_9 species_10 species_11 species_12 species_13 species_14 species_15 species_16 species_17 species_18 species_19 species_20 species_21 species_22 species_23 
+	;
+	BLOCKID WM114cc2916be37;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  habitat;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 habitat /  aquatic terrestrial ; 
+	MATRIX
+	species_0   0
+	species_1   1
+	species_2   0
+	species_3   0
+	species_4   1
+	species_5   1
+	species_6   0
+	species_7   0
+	species_8   1
+	species_9   1
+	species_10  0
+	species_11  0
+	species_12  0
+	species_13  0
+	species_14  0
+	species_15  1
+	species_16  1
+	species_17  1
+	species_18  0
+	species_19  0
+	species_20  1
+	species_21  0
+	species_22  0
+	species_23  0
+
+;
+		BLOCKID WM114cc2916ef0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  physiology;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 metabolic_rate,
+		2 sprint_speed ; 
+	MATRIX
+	species_0    1.219 11.3
+	species_1    3.56 17.98
+	species_2    0.98 15.16
+	species_3    2.341 19.53
+	species_4    1.998 23.07
+	species_5    2.951 20.78
+	species_6    0.5681 20.44
+	species_7    1.153 17.82
+	species_8    2.713 22.37
+	species_9    5.673 20.12
+	species_10   0.112 13.0
+	species_11   0.6743 15.91
+	species_12   0.9881 16.19
+	species_13   1.231 20.35
+	species_14   1.987 20.32
+	species_15   1.7 18.87
+	species_16   2.987 22.82
+	species_17   3.209 29.87
+	species_18   0.456 19.53
+	species_19   0.9868 16.07
+	species_20   1.233 24.62
+	species_21   0.871 21.01
+	species_22   0.3451 12.83
+	species_23   0.795 13.99
+
+;
+		BLOCKID WM114cc2917030;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-pairwise.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 species_0,
+		2 species_1,
+		3 species_2,
+		4 species_3,
+		5 species_4,
+		6 species_5,
+		7 species_6,
+		8 species_7,
+		9 species_8,
+		10 species_9,
+		11 species_10,
+		12 species_11,
+		13 species_12,
+		14 species_13,
+		15 species_14,
+		16 species_15,
+		17 species_16,
+		18 species_17,
+		19 species_18,
+		20 species_19,
+		21 species_20,
+		22 species_21,
+		23 species_22,
+		24 species_23;
+	TREE mtDNA_phylogeny = (((((1,16),((9,17),14)),(((6,20),(((8,24),(15,(18,21))),(10,((11,22),12)))),(7,(2,19)))),4),((3,(13,23)),5));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = habitat)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = habitat)  =  unord:  1;
+TYPESET Current_Parsimony_Models  (CHARACTERS = habitat)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = physiology)  =  Linear:  1 -  2;
+TYPESET Current_Parsimony_Models  (CHARACTERS = physiology)  =  Linear:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = habitat)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = physiology)  =  Brownian_default:  1 -  2;
+ProbModelSet Current_Probability_Models  (CHARACTERS = physiology)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5616496406151607698 WM114cc2916be37;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5359875599842773608 WM114cc2916ef0;
+			checksum 0 2437689620 WM114cc2916ef0;
+			setID 1 1344182101150933612 WM114cc2917030;
+			checksum 1 573191175 WM114cc2917030;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 529 239;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5616496406151607698  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 865.967565541874.2516291620293279705;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 584 546;
+					setLocation 559 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates off;
+					setPairSelector  #mesquite.pairwise.PairsOneChar.PairsOneChar;
+					tell It;
+						setLimit 4000;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #5359875599842773608;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #1344182101150933612;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 1;
+					setPairing 1;
+					setInitialOffsetX 14;
+					setInitialOffsetY -522;
+					calculate;
+				endTell;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 562 470;
+						setLocation 6 336;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #5359875599842773608;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -161;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #1344182101150933612;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -305;
+						setLegendWidth 142;
+						setLegendHeight 302;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-pairwiseFig2(1).nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 529 222;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows the use of pairwise comparisons to test association between characters on a phylogeny.  At right are two data matrices, categorical and continuous.  The first character of each is compared  in the mirror tree window.  Above left is an analysis of pairwise comparisons automatically chosen by the algorithm of W. Maddison (2000).  There are 3696 pairings of terminal taxa with 7 pairs contrasting the independent (categorical) variable.  The first pairing ( [...]
+				setTitle Pairwise_comparison;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/02-pairwiseFig2(1).nex b/Resources/examples/Correlation/02-pairwiseFig2(1).nex
new file mode 100644
index 0000000..509342a
--- /dev/null
+++ b/Resources/examples/Correlation/02-pairwiseFig2(1).nex
@@ -0,0 +1,347 @@
+#NEXUS
+[written Sat Jun 07 11:40:00 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=20;
+	TAXLABELS
+		A B C D E F G H I J K L M N O P Q R S T 
+	;
+	BLOCKID WM114cc29a60438;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-pairwiseFig2(1).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  00
+	B  11
+	C  00
+	D  00
+	E  11
+	F  11
+	G  01
+	H  00
+	I  00
+	J  00
+	K  11
+	L  11
+	M  00
+	N  00
+	O  11
+	P  11
+	Q  10
+	R  00
+	S  00
+	T  00
+
+;
+		BLOCKID WM114cc29a6140;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-pairwiseFig2(1).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J,
+		11 K,
+		12 L,
+		13 M,
+		14 N,
+		15 O,
+		16 P,
+		17 Q,
+		18 R,
+		19 S,
+		20 T;
+	TREE UNTITLED = ((9,14),((15,11),(18,(((7,(20,19)),12),(((1,(10,((16,17),6))),(13,8)),(((4,5),2),3))))));
+
+END;
+
+
+BEGIN MACCLADE;
+Version 3.05;
+LastModified - 1306936660;
+Singles 0100& /              0;
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =             unord PolyTcount =             MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3196237234391053769 WM114cc29a60438;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2832606891834185499 WM114cc29a6140;
+			checksum 0 4257668035 WM114cc29a6140;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 385 455;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3196237234391053769  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2369.970632536606.3126887053844580137;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 859 497;
+					setLocation 398 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsNoChars.PairsNoChars;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #2832606891834185499;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #2832606891834185499;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -200;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2832606891834185499 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 385 398;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-pairwiseFig2(2).nex';
+			setPrevFileName '01-pairwise.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 385 438;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For figure 2 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows choice of pairs without regard to states of characters.  The grey boxes over the terminal taxa show in bold what is designated the Independent variable, and below that the dependent  variable.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/03-pairwiseFig2(2).nex b/Resources/examples/Correlation/03-pairwiseFig2(2).nex
new file mode 100644
index 0000000..cb2e3af
--- /dev/null
+++ b/Resources/examples/Correlation/03-pairwiseFig2(2).nex
@@ -0,0 +1,350 @@
+#NEXUS
+[written Sat Jun 07 11:36:48 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=20;
+	TAXLABELS
+		A B C D E F G H I J K L M N O P Q R S T 
+	;
+	BLOCKID WM114cc29f73d39;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-pairwiseFig2(2).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  00
+	B  11
+	C  00
+	D  00
+	E  11
+	F  11
+	G  01
+	H  00
+	I  00
+	J  00
+	K  11
+	L  11
+	M  00
+	N  00
+	O  11
+	P  11
+	Q  10
+	R  00
+	S  00
+	T  00
+
+;
+		BLOCKID WM114cc29f77a0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-pairwiseFig2(2).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J,
+		11 K,
+		12 L,
+		13 M,
+		14 N,
+		15 O,
+		16 P,
+		17 Q,
+		18 R,
+		19 S,
+		20 T;
+	TREE UNTITLED = ((9,14),((15,11),(18,(((7,(20,19)),12),(((1,(10,((16,17),6))),(13,8)),(((4,5),2),3))))));
+
+END;
+
+
+BEGIN MACCLADE;
+Version 3.05;
+LastModified - 1306936660;
+Singles 0100& /           0;
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =          unord PolyTcount =          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6595404229671493286 WM114cc29f73d39;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8234977281528109195 WM114cc29f77a0;
+			checksum 0 4257668035 WM114cc29f77a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 338 466;
+			setLocation 6 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6595404229671493286  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2440.970632551984.9050636877436007407;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 854 499;
+					setLocation 370 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsOneChar.PairsOneChar;
+					tell It;
+						setLimit 5;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #8234977281528109195;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #8234977281528109195;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -200;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #8234977281528109195 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 338 409;
+					setLocation 6 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-pairwiseFig2(3).nex';
+			setPrevFileName '02-pairwiseFig2(1).nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 338 449;
+					setLocation 6 26;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For figure 2 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows choice of pairs to contrast the states of character 1.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/04-pairwiseFig2(3).nex b/Resources/examples/Correlation/04-pairwiseFig2(3).nex
new file mode 100644
index 0000000..cc677f6
--- /dev/null
+++ b/Resources/examples/Correlation/04-pairwiseFig2(3).nex
@@ -0,0 +1,350 @@
+#NEXUS
+[written Sat Jun 07 11:40:16 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=20;
+	TAXLABELS
+		A B C D E F G H I J K L M N O P Q R S T 
+	;
+	BLOCKID WM114cc2a351040;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-pairwiseFig2(3).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  00
+	B  11
+	C  00
+	D  00
+	E  11
+	F  11
+	G  01
+	H  00
+	I  00
+	J  00
+	K  11
+	L  11
+	M  00
+	N  00
+	O  11
+	P  11
+	Q  10
+	R  00
+	S  00
+	T  00
+
+;
+		BLOCKID WM114cc2a35620;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-pairwiseFig2(3).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G,
+		8 H,
+		9 I,
+		10 J,
+		11 K,
+		12 L,
+		13 M,
+		14 N,
+		15 O,
+		16 P,
+		17 Q,
+		18 R,
+		19 S,
+		20 T;
+	TREE UNTITLED = ((9,14),((15,11),(18,(((7,(20,19)),12),(((1,(10,((16,17),6))),(13,8)),(((4,5),2),3))))));
+
+END;
+
+
+BEGIN MACCLADE;
+Version 3.05;
+LastModified - 1306936660;
+Singles 0100& /            0;
+
+END;
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =           unord PolyTcount =           MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5715784789562340009 WM114cc2a351040;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5834500797987800771 WM114cc2a35620;
+			checksum 0 4257668035 WM114cc2a35620;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 362 482;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5715784789562340009  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2511.970632567011.3284971206291078;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 807 457;
+					setLocation 396 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsTwoChars.PairsTwoChars;
+					tell It;
+						setLimit 5;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #5834500797987800771;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #5834500797987800771;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -200;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5834500797987800771 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 362 425;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-pairwiseFig3-6(1).nex';
+			setPrevFileName '03-pairwiseFig2(2).nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 362 465;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For figure 2 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows choice of pairs to contrast the states of character 1 and 2.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/05-pairwiseFig3-6(1).nex b/Resources/examples/Correlation/05-pairwiseFig3-6(1).nex
new file mode 100644
index 0000000..463ba76
--- /dev/null
+++ b/Resources/examples/Correlation/05-pairwiseFig3-6(1).nex
@@ -0,0 +1,318 @@
+#NEXUS
+[written Sat Jun 07 11:40:27 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		A B C D E F G 
+	;
+	BLOCKID WM114cc2ad68f41;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-pairwiseFig3-6(1).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  01
+	B  00
+	C  11
+	D  11
+	E  10
+	F  00
+	G  00
+
+;
+		BLOCKID WM114cc2ad6bd0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-pairwiseFig3-6(1).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G;
+	TREE UNTITLED = ((1,2),(3,(4,(5,(6,7)))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =         unord PolyTcount =         MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3084515409736916712 WM114cc2ad68f41;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 3151283466373346864 WM114cc2ad6bd0;
+			checksum 0 2906558003 WM114cc2ad6bd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 369 487;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #3084515409736916712  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2582.970632584400.5389116702340311286;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 834 474;
+					setLocation 399 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsNoChars.PairsNoChars;
+					tell It;
+						setLimit 5;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #3151283466373346864;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #3151283466373346864;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -181;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #3151283466373346864 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 369 430;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-pairwiseFig3-6(2).nex';
+			setPrevFileName '04-pairwiseFig2(3).nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 369 470;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For Figures 3-6 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows pairs chosen without regard to characters.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/06-pairwiseFig3-6(2).nex b/Resources/examples/Correlation/06-pairwiseFig3-6(2).nex
new file mode 100644
index 0000000..dc3c5cd
--- /dev/null
+++ b/Resources/examples/Correlation/06-pairwiseFig3-6(2).nex
@@ -0,0 +1,318 @@
+#NEXUS
+[written Sat Jun 07 11:40:37 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		A B C D E F G 
+	;
+	BLOCKID WM114cc2b337442;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-pairwiseFig3-6(2).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  01
+	B  00
+	C  11
+	D  11
+	E  10
+	F  00
+	G  00
+
+;
+		BLOCKID WM114cc2b33790;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-pairwiseFig3-6(2).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G;
+	TREE UNTITLED = ((1,2),(3,(4,(5,(6,7)))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =          unord PolyTcount =          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2596676973405663252 WM114cc2b337442;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1042956646603933045 WM114cc2b33790;
+			checksum 0 2906558003 WM114cc2b33790;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 377 518;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #2596676973405663252  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2653.970632600171.2195120930278183531;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 816 495;
+					setLocation 400 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsOneChar.PairsOneChar;
+					tell It;
+						setLimit 5;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #1042956646603933045;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #1042956646603933045;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -181;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1042956646603933045 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 377 461;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-pairwiseFig3-6(3).nex';
+			setPrevFileName '05-pairwiseFig3-6(1).nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 377 501;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For Figures 3-6 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows pairs chosen to contrast the states of character 1.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Correlation/07-pairwiseFig3-6(3).nex b/Resources/examples/Correlation/07-pairwiseFig3-6(3).nex
new file mode 100644
index 0000000..480bb15
--- /dev/null
+++ b/Resources/examples/Correlation/07-pairwiseFig3-6(3).nex
@@ -0,0 +1,249 @@
+#NEXUS
+[written Sat Jun 07 11:41:08 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		A B C D E F G 
+	;
+	BLOCKID WM114cc2b75d043;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-pairwiseFig3-6(3).nex"';
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	A  01
+	B  00
+	C  11
+	D  11
+	E  10
+	F  00
+	G  00
+
+;
+		BLOCKID WM114cc2b75e10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-pairwiseFig3-6(3).nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A,
+		2 B,
+		3 C,
+		4 D,
+		5 E,
+		6 F,
+		7 G;
+	TREE UNTITLED = ((1,2),(3,(4,(5,(6,7)))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =          unord PolyTcount =          MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+TYPESET Current_Parsimony_Models   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 2797435016968775186 WM114cc2b75d043;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2027440424851978578 WM114cc2b75e10;
+			checksum 0 2906558003 WM114cc2b75e10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 391 477;
+			setLocation 0 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #2797435016968775186  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2913.962688975207.242157289790097838;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 813 456;
+					setLocation 402 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.pairwise.PairwiseComparison.PairwiseComparison;
+				tell It;
+					requireCalculate;
+					showStates on;
+					setPairSelector  #mesquite.pairwise.PairsTwoChars.PairsTwoChars;
+					tell It;
+						setLimit 5;
+					endTell;
+					getCharacterSourceA  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #2027440424851978578;
+						endTell;
+					endTell;
+					getCharacterSourceB  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #2027440424851978578;
+						endTell;
+					endTell;
+					setCharacterA 1;
+					setCharacterB 2;
+					setPairing 1;
+					setInitialOffsetX -181;
+					setInitialOffsetY -340;
+					calculate;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00-introduction.nex';
+			setPrevFileName '06-pairwiseFig3-6(2).nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 391 460;
+					setLocation 0 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For Figures 3-6 of Maddison, W.P.  2000. Testing character correlation using pairwise comparisons on a phylogeny.  Journal of Theoretical Biology. 202: 195-204.^n^nThis shows pairs chosen to contrast the states of characters 1 and 2.';
+				setTitle Pairwise;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_Intro;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/00-introduction.nex b/Resources/examples/Diversification/00-introduction.nex
new file mode 100644
index 0000000..20e05c4
--- /dev/null
+++ b/Resources/examples/Diversification/00-introduction.nex
@@ -0,0 +1,46 @@
+#NEXUS
+[written Sun May 04 16:20:41 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 553 359;
+			setLocation 7 29;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-lineagesThroughTime.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 553 342;
+					setLocation 7 29;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Phylogeny can be used to explore species diversification, speciation and extinction.  Here are some example files of relevant Mesquite features.^n^nTo go from one file to another, hit the "Next" button';
+				setTitle Species_Diversification;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/01-lineagesThroughTime.nex b/Resources/examples/Diversification/01-lineagesThroughTime.nex
new file mode 100644
index 0000000..1b6a6df
--- /dev/null
+++ b/Resources/examples/Diversification/01-lineagesThroughTime.nex
@@ -0,0 +1,371 @@
+#NEXUS
+[written Sat Jun 07 11:41:54 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-lineagesThroughTime.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM114911738c20;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-lineagesThroughTime.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM114911738c20;
+			checksum 0 909469476 WM114911738c20;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 933 464;
+			setLocation 351 26;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 397;
+					setLocation 351 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 2;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 9;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.diverse.LineagesThroughTime.LineagesThroughTime;
+				tell It;
+					makeWindow;
+					getWindow;
+					tell It;
+						popAsTile true;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 394 447;
+						setLocation 351 26;
+						setFont SanSerif;
+						setFontSize 10;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.charts.Histogram.Histogram;
+					tell It;
+						suspend;
+						showAverageToggle on;
+						showPercentToggle off;
+						setCumulativeMode 0;
+						showAsBarChartToggle off;
+						showRawToggle off;
+						setNumberIntervals 20;
+						setIntervalSize 1.0;
+						setMovingWindowSize 5.0 1.0;
+						setMode 0;
+						resume;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 397;
+					setLocation 351 26;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-speciationExtinctionRates.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 330 363;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'Available in the Analysis:Tree menu of the Tree Window is Lineages Through Time, which plots the logarithm of the number of lineages in a tree through time.  With a pure birth process, one expects the plot to be a straight line.';
+				setTitle Lineages_Through_Time;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/02-speciationExtinctionRates.nex b/Resources/examples/Diversification/02-speciationExtinctionRates.nex
new file mode 100644
index 0000000..0c2a428
--- /dev/null
+++ b/Resources/examples/Diversification/02-speciationExtinctionRates.nex
@@ -0,0 +1,353 @@
+#NEXUS
+[written Sat Jun 07 11:42:37 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-speciationExtinctionRates.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM114910e80a10;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-speciationExtinctionRates.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM114910e80a10;
+			checksum 0 909469476 WM114910e80a10;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 413;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1070 536;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1070 469;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.diverse.CharIndepDivViewer.CharIndepDivViewer;
+				tell It;
+					setCalculator  #mesquite.diverse.SpecExtincLikelihood.SpecExtincLikelihood;
+					tell It;
+						getIntegTask  #mesquite.diverse.SpecExtincMLCalculator.SpecExtincMLCalculator;
+						tell It;
+							setUnderflowCheckFreq -1;
+							setStepCount 1000.0;
+							conditionOnSurvival  off;
+						endTell;
+						setS ?;
+						setE ?;
+					endTell;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1070 469;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-sisterDiversification.nex';
+			setPrevFileName '01-lineagesThroughTime.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 465 193;
+					setLocation 7 654;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'A likelihood analysis can give estimates of speciation and extinction rates.  Here a method reduced from Maddison, Midford & Otto''s BiSSE method is used to calculate likelihoods for a simple birth/death model, where lambda = birth = speciation rate, and mu = death = extinction rate.^n^nThis calculation is available as Diversification (Char. Indep.) in the Analysis:Tree menu of the Tree Window.';
+				setTitle Speciation_and_Extinction_Rates;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/03-sisterDiversification.nex b/Resources/examples/Diversification/03-sisterDiversification.nex
new file mode 100644
index 0000000..3d5b6f7
--- /dev/null
+++ b/Resources/examples/Diversification/03-sisterDiversification.nex
@@ -0,0 +1,386 @@
+#NEXUS
+[written Sat Jun 07 11:43:33 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-sisterDiversification.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM1149106b2f00;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-sisterDiversification.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM1149106b2f00;
+			checksum 0 909469476 WM1149106b2f00;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1213 622;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #444104661901299517;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -362;
+					setInitialOffsetY -175;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.diverse.CharAssocDivViewer.CharAssocDivViewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #444104661901299517;
+						endTell;
+					endTell;
+					setCalculator  #mesquite.diverse.SisterDiversification.SisterDiversification;
+					setCharacter -1;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-BiSSEViewer.nex';
+			setPrevFileName '02-speciationExtinctionRates.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 522 211;
+					setLocation 18 715;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This and the following two example files answer the question: are rates of diversification (speciation and extinction) associated with the state of a binary character?^n^nThis analysis, available by chosing Character-Associated Diversification from the Analysis:Tree menu of the Tree window, uses the simple sign test analysis for independent sister clade pairs in the style of Mitter, Farrell and Wiegmann 1988.  The analysis automatically finds sister clade pairs that c [...]
+				setTitle Sister_Clade_comparison;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/04-BiSSEViewer.nex b/Resources/examples/Diversification/04-BiSSEViewer.nex
new file mode 100644
index 0000000..7418bdb
--- /dev/null
+++ b/Resources/examples/Diversification/04-BiSSEViewer.nex
@@ -0,0 +1,414 @@
+#NEXUS
+[written Wed Aug 26 12:51:33 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-BiSSEViewer.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM11490f84ae00;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-BiSSEViewer.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM11490f84ae00;
+			checksumv 0 2 1451138313 WM11490f84ae00;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1207 576;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1135 509;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #444104661901299517;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 4;
+					setInitialOffsetY -221;
+					setLegendWidth 142;
+					setLegendHeight 178;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+					newWindowAssistant  #mesquite.diverse.CharAssocDivViewer.CharAssocDivViewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #444104661901299517;
+						endTell;
+					endTell;
+					setCalculator  #mesquite.diverse.BiSSELikelihood.BiSSELikelihood;
+					tell It;
+						suspend ;
+						setParameters  ?  ?  ?  ?  =2 ?  ?  =4;
+						setReportMode Likelihood;
+						getIntegTask  #mesquite.diverse.BiSSELikelihoodCalculator.BiSSELikelihoodCalculator;
+						tell It;
+							suspend ;
+							setUnderflowCheckFreq 2;
+							setStepCount 1000.0;
+							setIterations 2;
+							conditionOnSurvival  off;
+							getStartFromConstrainedModel off;
+							resume ;
+						endTell;
+						resume ;
+					endTell;
+					setCharacter 1;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1135 509;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleThinRows off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-BiSSENetViewer.nex';
+			setPrevFileName '03-sisterDiversification.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 524 264;
+					setLocation 13 679;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				setExplanation 'Here the BiSSE likelihood calculations are done.  When you have a tree and a binary character (here stored in a matrix), you can select Character-Associated Diversification from the Analysis:Tree menu of the Tree window, and indicate you want BiSSE Speciation/Extinction likelihood to be calculated. The BiSSE method is described by Maddison, Midford and Otto 2007.^n^nIn the panel are shown the estimated values of the speciation (lambda) and extinction (mu) rates for st [...]
+				setTitle BiSSE_Diversification;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/05-BiSSENetViewer.nex b/Resources/examples/Diversification/05-BiSSENetViewer.nex
new file mode 100644
index 0000000..85ca83b
--- /dev/null
+++ b/Resources/examples/Diversification/05-BiSSENetViewer.nex
@@ -0,0 +1,411 @@
+#NEXUS
+[written Wed Aug 26 12:51:46 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-BiSSENetViewer.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM11493c252d50;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-BiSSENetViewer.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM11493c252d50;
+			checksumv 0 2 1451138313 WM11493c252d50;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1213 622;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #444104661901299517;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 4;
+					setInitialOffsetY -175;
+					setLegendWidth 142;
+					setLegendHeight 161;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+					newWindowAssistant  #mesquite.diverse.CharAssocDivViewer.CharAssocDivViewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #444104661901299517;
+						endTell;
+					endTell;
+					setCalculator  #mesquite.diverse.DiversCategCharLikelihood.DiversCategCharLikelihood;
+					tell It;
+						getIntegTask  #mesquite.diverse.DivCategCharMLCalculator.DivCategCharMLCalculator;
+						tell It;
+							suspend ;
+							setUnderflowCheckFreq 2;
+							setStepCount 1000.0;
+							setIterations 2;
+							conditionOnSurvival  off;
+							getStartFromConstrainedModel off;
+							resume ;
+						endTell;
+						setParameters  ?  ?  ?  ?  =2 ?  ?  =4;
+					endTell;
+					setCharacter 1;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleThinRows off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-BiSSEtrees.nex';
+			setPrevFileName '04-BiSSEViewer.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 510 110;
+					setLocation 17 725;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				setExplanation 'Here a modified version of BiSSE likelihood calculations is given, which is reparameterized in terms of net diversification (r, speciation minus extinction) and the speciation/extinction ratio (a).';
+				setTitle BiSSE_Net_Diversification;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/06-BiSSEtrees.nex b/Resources/examples/Diversification/06-BiSSEtrees.nex
new file mode 100644
index 0000000..db0eabf
--- /dev/null
+++ b/Resources/examples/Diversification/06-BiSSEtrees.nex
@@ -0,0 +1,415 @@
+#NEXUS
+[written Wed Aug 26 12:52:00 PDT 2009 by Mesquite  version 2.6+ (build 508) at thrandina.zoology.ubc.ca/137.82.80.142 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "06-BiSSEtrees.nex"';
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	taxon_1   0
+	taxon_2   1
+	taxon_3   0
+	taxon_4   0
+	taxon_5   0
+	taxon_6   1
+	taxon_7   0
+	taxon_8   1
+	taxon_9   1
+	taxon_10  1
+	taxon_11  1
+	taxon_12  1
+	taxon_13  1
+	taxon_14  1
+	taxon_15  1
+	taxon_16  1
+	taxon_17  1
+	taxon_18  0
+	taxon_19  1
+	taxon_20  0
+	taxon_21  0
+	taxon_22  0
+	taxon_23  1
+	taxon_24  1
+	taxon_25  1
+	taxon_26  1
+	taxon_27  1
+	taxon_28  1
+	taxon_29  1
+	taxon_30  1
+	taxon_31  1
+	taxon_32  0
+
+;
+	IDS WM1148f4828fe0 ;
+	BLOCKID WM114988797040;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-BiSSEtrees.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32;
+	TREE Tree = (((((7:5.187000000000067,22:5.186999999999937):2.4919999999998366,(2:5.19600000000007,((31:2.6009999999998246,14:2.6009999999998246):2.269999999999861,26:4.870999999999961):0.32500000000000023):2.4829999999999215):0.6730000000000005,((((6:0.8290000000000006,9:0.8290000000000006):0.3140000000000002,16:1.142999999999985):2.6749999999998164,(((15:0.20300000000000015,12:0.20300000000000015):0.2490000000000002,8:0.45200000000000035):1.360999999999961,32:1.8129999999999111):2.0049 [...]
+	TREE Tree2 = (((((7:5.187000000000067,22:5.187000000000067):2.4919999999999245,(2:5.19600000000007,((31:3.7774048022868723,14:3.7774048022868723):1.093595197713089,26:4.870999999999961):0.32500000000010854):2.4829999999999215):2.0339999999996135,((((6:0.8290000000000006,9:0.8290000000000006):1.8698616304384839,16:2.6988616304384845):2.4801383695612778,(((15:0.20300000000000007,12:0.20300000000000007):1.609999999999911,32:1.8129999999999111):1.360999999999961,8:3.173999999999872):2.00499 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 444104661901299517 WM114988797040;
+			checksumv 0 2 1451138313 WM114988797040;
+		endTell;
+		getWindow;
+		tell It;
+			suppress;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1213 622;
+			setLocation 5 22;
+			setFont SanSerif;
+			setFontSize 10;
+			getToolPalette;
+			tell It;
+			endTell;
+			desuppress;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.ArcTree.ArcTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							inhibitStretchToggle on;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleShowFootnotes on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setDrawingSizeMode 1;
+					toggleLegendFloat on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #444104661901299517;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 4;
+					setInitialOffsetY -175;
+					setLegendWidth 142;
+					setLegendHeight 161;
+					resume ;
+					modifyColors  1 1  70 235 97;
+				endTell;
+					newWindowAssistant  #mesquite.diverse.CharAssocDivViewer.CharAssocDivViewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+						tell It;
+							setDataSet #444104661901299517;
+						endTell;
+					endTell;
+					setCalculator  #mesquite.diverse.BiSSELikelihood.BiSSELikelihood;
+					tell It;
+						suspend ;
+						setParameters  ?  ?  =0 ?  ?  =2 ?  ?  =4;
+						setReportMode Likelihood;
+						getIntegTask  #mesquite.diverse.BiSSELikelihoodCalculator.BiSSELikelihoodCalculator;
+						tell It;
+							suspend ;
+							setUnderflowCheckFreq 2;
+							setStepCount 1000.0;
+							setIterations 2;
+							conditionOnSurvival  off;
+							getStartFromConstrainedModel off;
+							resume ;
+						endTell;
+						resume ;
+					endTell;
+					setCharacter 1;
+					doCounts;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleCentred on;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #444104661901299517 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1141 555;
+					setLocation 5 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleThinRows off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-contTreeSim.nex';
+			setPrevFileName '05-BiSSENetViewer.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 564 433;
+					setLocation 58 458;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				setExplanation 'To save BiSSE results (with parameter values) for multiple trees, you can either do a chart for Trees (indicating you want to save a results table) or you can set up a tree window as shown, with the BiSSE analysis running.  Then, go to the Tree menu of the Tree window, and select Step Through Trees.  Indicate you want to record results from BiSSE Speciation/Extinction Likelihood.  A tab-delimited table will be stored in a text file with the results. You can examine th [...]
+				setTitle Results_from_Multiple_Trees;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/07-contTreeSim.nex b/Resources/examples/Diversification/07-contTreeSim.nex
new file mode 100644
index 0000000..ad9981d
--- /dev/null
+++ b/Resources/examples/Diversification/07-contTreeSim.nex
@@ -0,0 +1,507 @@
+#NEXUS
+[written Sat Jun 07 11:47:58 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=100;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 taxon_33 taxon_34 taxon_35 taxon_36 taxon_37 taxon_38 taxon_39 taxon_40 taxon_41 taxon_42 taxon_43 taxon_44 taxon_45 taxon_46 taxon_47 taxon_48 taxon_49 taxon_50 taxon_51 taxon_52 taxon_53 taxon_54 taxon_55 taxo [...]
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "07-contTreeSim.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = CONTINUOUS GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 Sim._with_tree_1,
+		2 Sim._with_tree_2,
+		3 Sim._with_tree_3,
+		4 Sim._with_tree_4,
+		5 Sim._with_tree_5 ; 
+	MATRIX
+	taxon_1     0.09224472101786713 -1.5077552789821327 -2.3077552789821327 -1.9077552789821326 -1.1077552789821328
+	taxon_2     -1.9077552789821326 -1.9077552789821326 -1.5077552789821327 -0.3077552789821329 -1.5077552789821327
+	taxon_3     -1.1077552789821328 -1.9077552789821326 -1.5077552789821327 -1.1077552789821328 -0.7077552789821329
+	taxon_4     -0.7077552789821329 -0.7077552789821329 -3.507755278982134 -0.7077552789821329 -1.5077552789821327
+	taxon_5     -0.7077552789821329 -0.7077552789821329 -5.507755278982136 -1.5077552789821327 -1.5077552789821327
+	taxon_6     -0.3077552789821329 -3.1077552789821334 -1.5077552789821327 -5.107755278982135 -0.3077552789821329
+	taxon_7     -0.3077552789821329 -3.1077552789821334 -3.1077552789821334 -1.5077552789821327 -0.7077552789821329
+	taxon_8     -0.3077552789821329 -3.907755278982134 -3.507755278982134 -1.1077552789821328 -0.3077552789821329
+	taxon_9     -0.7077552789821329 -5.507755278982136 -1.5077552789821327 0.09224472101786713 -2.707755278982133
+	taxon_10    0.49224472101786715 -0.7077552789821329 -1.5077552789821327 -1.1077552789821328 -1.1077552789821328
+	taxon_11    -0.7077552789821329 -0.3077552789821329 -1.9077552789821326 -0.7077552789821329 -1.1077552789821328
+	taxon_12    -0.7077552789821329 -1.5077552789821327 -1.5077552789821327 -1.9077552789821326 -0.7077552789821329
+	taxon_13    -1.5077552789821327 -3.1077552789821334 -1.1077552789821328 -0.3077552789821329 -5.507755278982136
+	taxon_14    -0.3077552789821329 -1.1077552789821328 -1.5077552789821327 -0.7077552789821329 -1.1077552789821328
+	taxon_15    -0.3077552789821329 -0.3077552789821329 -1.9077552789821326 -1.9077552789821326 -6.707755278982137
+	taxon_16    0.49224472101786715 -0.7077552789821329 -1.1077552789821328 0.09224472101786713 -2.707755278982133
+	taxon_17    -0.3077552789821329 -1.5077552789821327 -3.907755278982134 -0.3077552789821329 -1.5077552789821327
+	taxon_18    0.49224472101786715 -9.107755278982134 -2.707755278982133 -2.3077552789821327 -0.7077552789821329
+	taxon_19    0.49224472101786715 -0.7077552789821329 -1.9077552789821326 -2.3077552789821327 -1.1077552789821328
+	taxon_20    -0.3077552789821329 -1.5077552789821327 -2.707755278982133 -1.1077552789821328 -1.5077552789821327
+	taxon_21    -1.5077552789821327 -0.3077552789821329 -2.3077552789821327 -1.5077552789821327 -2.3077552789821327
+	taxon_22    -0.3077552789821329 -1.5077552789821327 -7.107755278982137 -0.7077552789821329 -2.3077552789821327
+	taxon_23    0.09224472101786713 -0.7077552789821329 -2.707755278982133 -0.7077552789821329 -1.1077552789821328
+	taxon_24    -0.7077552789821329 -0.3077552789821329 -1.9077552789821326 -1.1077552789821328 -1.5077552789821327
+	taxon_25    -1.5077552789821327 -0.7077552789821329 -0.3077552789821329 0.09224472101786713 -1.1077552789821328
+	taxon_26    -0.7077552789821329 -2.3077552789821327 -3.907755278982134 -1.9077552789821326 -1.1077552789821328
+	taxon_27    -0.7077552789821329 -0.7077552789821329 -2.3077552789821327 -0.3077552789821329 -1.1077552789821328
+	taxon_28    -1.1077552789821328 0.09224472101786713 -2.707755278982133 -1.5077552789821327 -1.5077552789821327
+	taxon_29    0.09224472101786713 -0.7077552789821329 -1.9077552789821326 -0.7077552789821329 0.09224472101786713
+	taxon_30    -8.707755278982136 -1.5077552789821327 -3.1077552789821334 -1.5077552789821327 -0.7077552789821329
+	taxon_31    -0.3077552789821329 -0.3077552789821329 -5.107755278982135 -1.1077552789821328 -1.5077552789821327
+	taxon_32    -0.7077552789821329 -1.9077552789821326 -1.1077552789821328 -0.7077552789821329 -1.9077552789821326
+	taxon_33    0.09224472101786713 -1.5077552789821327 -3.507755278982134 -0.7077552789821329 -0.7077552789821329
+	taxon_34    0.09224472101786713 -1.1077552789821328 -2.707755278982133 -0.3077552789821329 -1.5077552789821327
+	taxon_35    -0.3077552789821329 -1.5077552789821327 -2.707755278982133 -7.907755278982138 -4.707755278982135
+	taxon_36    -6.307755278982136 -0.3077552789821329 -1.9077552789821326 -0.7077552789821329 -1.1077552789821328
+	taxon_37    -0.7077552789821329 -0.3077552789821329 -1.9077552789821326 -0.7077552789821329 -1.1077552789821328
+	taxon_38    -0.7077552789821329 -1.1077552789821328 -1.9077552789821326 -1.9077552789821326 -0.7077552789821329
+	taxon_39    -0.3077552789821329 -1.1077552789821328 -2.3077552789821327 -1.5077552789821327 -1.1077552789821328
+	taxon_40    -1.5077552789821327 -1.9077552789821326 -3.907755278982134 -0.7077552789821329 -1.5077552789821327
+	taxon_41    0.49224472101786715 -3.1077552789821334 -1.9077552789821326 -0.3077552789821329 -2.3077552789821327
+	taxon_42    0.09224472101786713 -1.9077552789821326 -2.707755278982133 -0.7077552789821329 -2.3077552789821327
+	taxon_43    -0.3077552789821329 -3.507755278982134 -2.3077552789821327 -0.3077552789821329 -1.1077552789821328
+	taxon_44    -0.7077552789821329 -1.5077552789821327 -1.1077552789821328 -0.7077552789821329 -0.3077552789821329
+	taxon_45    -0.3077552789821329 -1.1077552789821328 -1.9077552789821326 -0.3077552789821329 -1.5077552789821327
+	taxon_46    -0.3077552789821329 -0.7077552789821329 -1.1077552789821328 -0.7077552789821329 -0.7077552789821329
+	taxon_47    0.09224472101786713 -0.7077552789821329 -0.7077552789821329 -1.1077552789821328 -1.1077552789821328
+	taxon_48    -1.9077552789821326 -0.7077552789821329 -1.5077552789821327 -0.3077552789821329 -1.5077552789821327
+	taxon_49    -0.3077552789821329 -0.7077552789821329 -0.7077552789821329 0.09224472101786713 -1.5077552789821327
+	taxon_50    -5.107755278982135 -0.7077552789821329 -2.707755278982133 -0.3077552789821329 -0.7077552789821329
+	taxon_51    -2.707755278982133 -1.1077552789821328 -5.107755278982135 -1.1077552789821328 -3.1077552789821334
+	taxon_52    -0.7077552789821329 -0.7077552789821329 -3.507755278982134 -0.3077552789821329 -0.7077552789821329
+	taxon_53    -1.1077552789821328 -1.5077552789821327 -1.5077552789821327 -0.7077552789821329 -0.7077552789821329
+	taxon_54    -0.7077552789821329 -1.1077552789821328 -2.3077552789821327 -0.7077552789821329 -1.9077552789821326
+	taxon_55    -0.7077552789821329 -2.707755278982133 -1.1077552789821328 -1.1077552789821328 -1.5077552789821327
+	taxon_56    -0.3077552789821329 -2.707755278982133 -3.1077552789821334 -0.7077552789821329 -1.9077552789821326
+	taxon_57    -2.3077552789821327 -1.5077552789821327 -1.5077552789821327 -0.3077552789821329 -1.5077552789821327
+	taxon_58    -0.3077552789821329 -0.3077552789821329 -1.9077552789821326 -1.5077552789821327 -1.5077552789821327
+	taxon_59    -1.1077552789821328 -1.9077552789821326 -3.1077552789821334 -1.1077552789821328 -3.1077552789821334
+	taxon_60    -0.3077552789821329 -3.507755278982134 -2.3077552789821327 -0.7077552789821329 -6.307755278982136
+	taxon_61    -0.3077552789821329 -1.1077552789821328 -1.1077552789821328 -1.5077552789821327 -1.5077552789821327
+	taxon_62    -0.3077552789821329 -0.7077552789821329 -2.3077552789821327 -0.7077552789821329 -3.1077552789821334
+	taxon_63    -0.3077552789821329 -1.5077552789821327 -3.507755278982134 0.09224472101786713 -2.707755278982133
+	taxon_64    -5.107755278982135 -0.7077552789821329 -1.9077552789821326 -0.7077552789821329 -1.1077552789821328
+	taxon_65    -1.1077552789821328 -0.7077552789821329 -1.9077552789821326 -2.3077552789821327 -0.7077552789821329
+	taxon_66    -0.7077552789821329 -1.9077552789821326 -3.1077552789821334 -1.9077552789821326 -2.3077552789821327
+	taxon_67    0.09224472101786713 -1.1077552789821328 -5.507755278982136 -1.1077552789821328 -0.7077552789821329
+	taxon_68    0.49224472101786715 0.09224472101786713 -1.1077552789821328 -0.7077552789821329 -1.1077552789821328
+	taxon_69    -1.9077552789821326 -1.5077552789821327 -1.5077552789821327 -0.3077552789821329 -1.9077552789821326
+	taxon_70    -0.3077552789821329 -0.7077552789821329 -1.1077552789821328 -0.7077552789821329 -1.5077552789821327
+	taxon_71    -0.3077552789821329 -0.3077552789821329 -2.3077552789821327 -0.3077552789821329 -1.1077552789821328
+	taxon_72    -1.1077552789821328 -5.107755278982135 -4.707755278982135 -0.7077552789821329 -2.707755278982133
+	taxon_73    -0.7077552789821329 -1.1077552789821328 -1.5077552789821327 -0.7077552789821329 -1.5077552789821327
+	taxon_74    0.09224472101786713 -0.3077552789821329 -2.3077552789821327 -0.7077552789821329 -0.7077552789821329
+	taxon_75    -1.1077552789821328 -1.1077552789821328 -3.907755278982134 -0.3077552789821329 -3.907755278982134
+	taxon_76    0.09224472101786713 -2.3077552789821327 -3.907755278982134 -1.5077552789821327 -0.3077552789821329
+	taxon_77    -0.7077552789821329 -1.9077552789821326 -2.3077552789821327 -1.5077552789821327 -2.3077552789821327
+	taxon_78    -0.7077552789821329 -0.3077552789821329 -2.707755278982133 -2.3077552789821327 -0.7077552789821329
+	taxon_79    -0.7077552789821329 -1.1077552789821328 -2.3077552789821327 -0.7077552789821329 -0.7077552789821329
+	taxon_80    0.49224472101786715 -0.7077552789821329 -2.3077552789821327 -0.7077552789821329 -0.7077552789821329
+	taxon_81    0.09224472101786713 -5.907755278982136 -3.507755278982134 0.09224472101786713 -0.3077552789821329
+	taxon_82    -0.3077552789821329 -1.5077552789821327 -3.507755278982134 -0.3077552789821329 -1.9077552789821326
+	taxon_83    0.09224472101786713 -0.7077552789821329 -2.707755278982133 -0.7077552789821329 0.09224472101786713
+	taxon_84    -0.3077552789821329 -0.3077552789821329 -2.3077552789821327 -1.1077552789821328 -0.7077552789821329
+	taxon_85    -0.7077552789821329 -2.3077552789821327 -1.5077552789821327 -5.107755278982135 -0.7077552789821329
+	taxon_86    -0.7077552789821329 -2.3077552789821327 -2.3077552789821327 0.09224472101786713 -0.3077552789821329
+	taxon_87    -0.3077552789821329 -1.1077552789821328 -1.1077552789821328 -0.3077552789821329 -2.707755278982133
+	taxon_88    0.49224472101786715 -1.1077552789821328 -1.9077552789821326 -0.7077552789821329 -2.707755278982133
+	taxon_89    -4.3077552789821345 -1.5077552789821327 -2.707755278982133 -7.907755278982138 -1.1077552789821328
+	taxon_90    -1.1077552789821328 -1.1077552789821328 -2.707755278982133 -0.7077552789821329 -1.5077552789821327
+	taxon_91    -0.3077552789821329 -7.107755278982137 -1.5077552789821327 -0.3077552789821329 -2.707755278982133
+	taxon_92    -0.7077552789821329 -0.7077552789821329 -1.5077552789821327 -0.3077552789821329 -2.3077552789821327
+	taxon_93    -0.7077552789821329 -1.9077552789821326 -1.1077552789821328 -0.3077552789821329 -0.7077552789821329
+	taxon_94    -0.7077552789821329 -1.1077552789821328 -1.5077552789821327 -0.7077552789821329 -1.1077552789821328
+	taxon_95    -0.3077552789821329 -2.3077552789821327 -4.3077552789821345 -0.7077552789821329 -0.7077552789821329
+	taxon_96    -0.3077552789821329 -0.3077552789821329 -1.1077552789821328 -1.5077552789821327 -2.707755278982133
+	taxon_97    0.09224472101786713 -0.7077552789821329 -1.1077552789821328 -0.7077552789821329 -8.707755278982136
+	taxon_98    -0.3077552789821329 -0.7077552789821329 -5.907755278982136 -0.3077552789821329 -2.3077552789821327
+	taxon_99    -0.3077552789821329 -0.7077552789821329 -1.9077552789821326 0.09224472101786713 -2.3077552789821327
+	taxon_100   0.09224472101786713 -0.7077552789821329 -1.1077552789821328 0.09224472101786713 -3.507755278982134
+
+;
+	IDS WM1149124016241 WM1149124016242 WM1149124016243 WM1149124016244 WM1149124016245 ;
+	BLOCKID WM11493f9adec0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-contTreeSim.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32,
+		33 taxon_33,
+		34 taxon_34,
+		35 taxon_35,
+		36 taxon_36,
+		37 taxon_37,
+		38 taxon_38,
+		39 taxon_39,
+		40 taxon_40,
+		41 taxon_41,
+		42 taxon_42,
+		43 taxon_43,
+		44 taxon_44,
+		45 taxon_45,
+		46 taxon_46,
+		47 taxon_47,
+		48 taxon_48,
+		49 taxon_49,
+		50 taxon_50,
+		51 taxon_51,
+		52 taxon_52,
+		53 taxon_53,
+		54 taxon_54,
+		55 taxon_55,
+		56 taxon_56,
+		57 taxon_57,
+		58 taxon_58,
+		59 taxon_59,
+		60 taxon_60,
+		61 taxon_61,
+		62 taxon_62,
+		63 taxon_63,
+		64 taxon_64,
+		65 taxon_65,
+		66 taxon_66,
+		67 taxon_67,
+		68 taxon_68,
+		69 taxon_69,
+		70 taxon_70,
+		71 taxon_71,
+		72 taxon_72,
+		73 taxon_73,
+		74 taxon_74,
+		75 taxon_75,
+		76 taxon_76,
+		77 taxon_77,
+		78 taxon_78,
+		79 taxon_79,
+		80 taxon_80,
+		81 taxon_81,
+		82 taxon_82,
+		83 taxon_83,
+		84 taxon_84,
+		85 taxon_85,
+		86 taxon_86,
+		87 taxon_87,
+		88 taxon_88,
+		89 taxon_89,
+		90 taxon_90,
+		91 taxon_91,
+		92 taxon_92,
+		93 taxon_93,
+		94 taxon_94,
+		95 taxon_95,
+		96 taxon_96,
+		97 taxon_97,
+		98 taxon_98,
+		99 taxon_99,
+		100 taxon_100;
+	TREE 'Simulated Tree (with character) 1' = (((((((69:0.03,13:0.03):0.03,48:0.060000000000000005):0.12999999999999998,((((5:0.01,66:0.01):0.05,(((4:0.02,55:0.02):0.02,9:0.04):0.01,((72:0.02,90:0.02):0.02,(((86:0.01,26:0.01):0.01,11:0.02):0.01,(99:0.02,(38:0.01,27:0.01):0.01):0.01):0.01):0.01):0.01):0.03,(25:0.02,65:0.02):0.07):0.07,((((((((6:0.01,20:0.01):0.01,(49:0.01,8:0.01):0.01):0.02,(88:0.03,((47:0.01,74:0.01):0.01,(7:0.01,62:0.01):0.01):0.01):0.01):0.01,(((63:0.01,31:0.01):0.01,(78 [...]
+	TREE 'Simulated Tree (with character) 2' = (18:3.139999999999977,((9:0.7000000000000004,81:0.7000000000000004):0.24000000000000007,((((((93:0.04,56:0.04):0.02,2:0.060000000000000005):0.01,(59:0.060000000000000005,66:0.060000000000000005):0.01):0.48000000000000026,6:0.5500000000000003):0.10999999999999999,91:0.6600000000000004):0.10999999999999999,(((76:0.09,((26:0.07,7:0.07):0.01,(((32:0.02,86:0.02):0.03,(35:0.03,44:0.03):0.02):0.02,(95:0.02,85:0.02):0.05):0.01):0.01):0.2100000000000000 [...]
+	TREE 'Simulated Tree (with character) 3' = (22:2.159999999999998,((((67:0.5100000000000002,5:0.5100000000000002):0.15,40:0.6600000000000004):0.22000000000000006,((((62:0.060000000000000005,74:0.060000000000000005):0.3300000000000001,((63:0.09,((7:0.02,18:0.02):0.02,(76:0.01,17:0.01):0.03):0.05):0.10999999999999999,75:0.20000000000000004):0.19000000000000003):0.01,((((20:0.01,50:0.01):0.01,42:0.02):0.17,((80:0.060000000000000005,60:0.060000000000000005):0.04,((43:0.04,(36:0.03,58:0.03):0 [...]
+	TREE 'Simulated Tree (with character) 4' = (89:2.8399999999999834,((((((((((37:0.01,42:0.01):0.01,32:0.02):0.01,((91:0.01,98:0.01):0.01,68:0.02):0.01):0.02,(11:0.01,64:0.01):0.04):0.01,((80:0.01,79:0.01):0.01,(71:0.01,43:0.01):0.01):0.04):0.08,((((30:0.08,((28:0.04,(65:0.02,18:0.02):0.02):0.01,(1:0.02,39:0.02):0.03):0.03):0.02,(78:0.04,(66:0.02,19:0.02):0.02):0.060000000000000005):0.02,(((34:0.02,13:0.02):0.01,(51:0.02,36:0.02):0.01):0.08,(61:0.09,(((((86:0.02,25:0.02):0.01,(57:0.02,90: [...]
+	TREE 'Simulated Tree (with character) 5' = (97:3.799999999999963,(15:1.0100000000000007,((((((96:0.05,(41:0.03,9:0.03):0.02):0.09999999999999999,62:0.15):0.09999999999999999,((((36:0.03,(49:0.01,2:0.01):0.02):0.03,82:0.060000000000000005):0.03,21:0.09):0.12999999999999998,((((77:0.03,22:0.03):0.07,(((67:0.03,50:0.03):0.03,56:0.060000000000000005):0.03,(((8:0.02,29:0.02):0.02,((83:0.02,6:0.02):0.01,(81:0.02,38:0.02):0.01):0.01):0.01,((79:0.03,95:0.03):0.01,((71:0.02,33:0.02):0.01,65:0.03 [...]
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2591902839263838224 WM11493f9adec0;
+			checksum 0 2295126586 WM11493f9adec0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1163 648;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1091 581;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+						toggleCorners on;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 3;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #2591902839263838224;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 3;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -307;
+					setLegendWidth 142;
+					setLegendHeight 302;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2591902839263838224 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1091 581;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-binaryTreeSim.nex';
+			setPrevFileName '06-BiSSEtrees.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 515 205;
+					setLocation 108 630;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This shows a tree and character simulated together. The character evolved by brownian motion; the tree speciated with a rate that is the value of the simulated character.^n^nA block of simulated trees and accompanying matrix (such that the i''th character was simulated with the i''th tree) was made by selecting Trees & Diversification Characters from the Taxa & Trees menu.  You can choose to simulate as shown (with a continuous character) or with the BiSSE model using [...]
+				setTitle Simulated_trees_&_characters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Diversification/08-binaryTreeSim.nex b/Resources/examples/Diversification/08-binaryTreeSim.nex
new file mode 100644
index 0000000..511249a
--- /dev/null
+++ b/Resources/examples/Diversification/08-binaryTreeSim.nex
@@ -0,0 +1,599 @@
+#NEXUS
+[written Sat Jun 07 11:48:06 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=140;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 taxon_16 taxon_17 taxon_18 taxon_19 taxon_20 taxon_21 taxon_22 taxon_23 taxon_24 taxon_25 taxon_26 taxon_27 taxon_28 taxon_29 taxon_30 taxon_31 taxon_32 taxon_33 taxon_34 taxon_35 taxon_36 taxon_37 taxon_38 taxon_39 taxon_40 taxon_41 taxon_42 taxon_43 taxon_44 taxon_45 taxon_46 taxon_47 taxon_48 taxon_49 taxon_50 taxon_51 taxon_52 taxon_53 taxon_54 taxon_55 taxo [...]
+	;
+	IDS WM1148f47d2061 WM1148f47d2072 WM1148f47d2073 WM1148f47d2074 WM1148f47d2075 WM1148f47d2076 WM1148f47d2077 WM1148f47d2078 WM1148f47d2079 WM1148f47d20710 WM1148f47d20711 WM1148f47d20712 WM1148f47d20713 WM1148f47d20714 WM1148f47d20715 WM1148f47d20716 WM1148f47d20717 WM1148f47d20718 WM1148f47d20719 WM1148f47d20720 WM1148f47d20721 WM1148f47d20722 WM1148f47d20723 WM1148f47d20724 WM1148f47d20725 WM1148f47d20726 WM1148f47d20727 WM1148f47d20728 WM1148f47d20729 WM1148f47d20830 WM1148f47d20831  [...]
+	BLOCKID WM1148f47d2081;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "08-binaryTreeSim.nex"';
+	DIMENSIONS  NCHAR=5;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 Sim._with_tree_1, 2 Sim._with_tree_2, 3 Sim._with_tree_3, 4 Sim._with_tree_4, 5 Sim._with_tree_5 ; 
+	MATRIX
+	taxon_1    11001
+	taxon_2    11111
+	taxon_3    11111
+	taxon_4    01111
+	taxon_5    11111
+	taxon_6    11111
+	taxon_7    11111
+	taxon_8    11111
+	taxon_9    11011
+	taxon_10   01111
+	taxon_11   11111
+	taxon_12   11111
+	taxon_13   11111
+	taxon_14   11111
+	taxon_15   11111
+	taxon_16   11101
+	taxon_17   11111
+	taxon_18   11111
+	taxon_19   11111
+	taxon_20   11111
+	taxon_21   11111
+	taxon_22   11111
+	taxon_23   11111
+	taxon_24   11111
+	taxon_25   11111
+	taxon_26   11111
+	taxon_27   11111
+	taxon_28   11111
+	taxon_29   11111
+	taxon_30   11111
+	taxon_31   11111
+	taxon_32   11111
+	taxon_33   11111
+	taxon_34   11111
+	taxon_35   11111
+	taxon_36   11111
+	taxon_37   11111
+	taxon_38   11111
+	taxon_39   11111
+	taxon_40   11111
+	taxon_41   11111
+	taxon_42   01111
+	taxon_43   11111
+	taxon_44   11111
+	taxon_45   11111
+	taxon_46   11111
+	taxon_47   11111
+	taxon_48   11111
+	taxon_49   11111
+	taxon_50   01111
+	taxon_51   11111
+	taxon_52   11111
+	taxon_53   11111
+	taxon_54   11111
+	taxon_55   11111
+	taxon_56   11111
+	taxon_57   01111
+	taxon_58   11111
+	taxon_59   11111
+	taxon_60   11111
+	taxon_61   11111
+	taxon_62   11111
+	taxon_63   11111
+	taxon_64   11111
+	taxon_65   11111
+	taxon_66   11111
+	taxon_67   11111
+	taxon_68   11111
+	taxon_69   11111
+	taxon_70   11111
+	taxon_71   11111
+	taxon_72   01111
+	taxon_73   11111
+	taxon_74   11111
+	taxon_75   11111
+	taxon_76   11111
+	taxon_77   11111
+	taxon_78   11111
+	taxon_79   11111
+	taxon_80   11111
+	taxon_81   11111
+	taxon_82   11111
+	taxon_83   11111
+	taxon_84   11111
+	taxon_85   11111
+	taxon_86   11111
+	taxon_87   11111
+	taxon_88   11111
+	taxon_89   11011
+	taxon_90   11111
+	taxon_91   11111
+	taxon_92   11111
+	taxon_93   11111
+	taxon_94   11111
+	taxon_95   11111
+	taxon_96   11111
+	taxon_97   11111
+	taxon_98   11111
+	taxon_99   11111
+	taxon_100  11111
+	taxon_101  ?????
+	taxon_102  ?????
+	taxon_103  ?????
+	taxon_104  ?????
+	taxon_105  ?????
+	taxon_106  ?????
+	taxon_107  ?????
+	taxon_108  ?????
+	taxon_109  ?????
+	taxon_110  ?????
+	taxon_111  ?????
+	taxon_112  ?????
+	taxon_113  ?????
+	taxon_114  ?????
+	taxon_115  ?????
+	taxon_116  ?????
+	taxon_117  ?????
+	taxon_118  ?????
+	taxon_119  ?????
+	taxon_120  ?????
+	taxon_121  ?????
+	taxon_122  ?????
+	taxon_123  ?????
+	taxon_124  ?????
+	taxon_125  ?????
+	taxon_126  ?????
+	taxon_127  ?????
+	taxon_128  ?????
+	taxon_129  ?????
+	taxon_130  ?????
+	taxon_131  ?????
+	taxon_132  ?????
+	taxon_133  ?????
+	taxon_134  ?????
+	taxon_135  ?????
+	taxon_136  ?????
+	taxon_137  ?????
+	taxon_138  ?????
+	taxon_139  ?????
+	taxon_140  ?????
+
+;
+	IDS WM11493f556a312 WM11493f556a313 WM11493f556a314 WM11493f556a315 WM11493f556a316 ;
+	BLOCKID WM1149667c69b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-binaryTreeSim.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_1,
+		2 taxon_2,
+		3 taxon_3,
+		4 taxon_4,
+		5 taxon_5,
+		6 taxon_6,
+		7 taxon_7,
+		8 taxon_8,
+		9 taxon_9,
+		10 taxon_10,
+		11 taxon_11,
+		12 taxon_12,
+		13 taxon_13,
+		14 taxon_14,
+		15 taxon_15,
+		16 taxon_16,
+		17 taxon_17,
+		18 taxon_18,
+		19 taxon_19,
+		20 taxon_20,
+		21 taxon_21,
+		22 taxon_22,
+		23 taxon_23,
+		24 taxon_24,
+		25 taxon_25,
+		26 taxon_26,
+		27 taxon_27,
+		28 taxon_28,
+		29 taxon_29,
+		30 taxon_30,
+		31 taxon_31,
+		32 taxon_32,
+		33 taxon_33,
+		34 taxon_34,
+		35 taxon_35,
+		36 taxon_36,
+		37 taxon_37,
+		38 taxon_38,
+		39 taxon_39,
+		40 taxon_40,
+		41 taxon_41,
+		42 taxon_42,
+		43 taxon_43,
+		44 taxon_44,
+		45 taxon_45,
+		46 taxon_46,
+		47 taxon_47,
+		48 taxon_48,
+		49 taxon_49,
+		50 taxon_50,
+		51 taxon_51,
+		52 taxon_52,
+		53 taxon_53,
+		54 taxon_54,
+		55 taxon_55,
+		56 taxon_56,
+		57 taxon_57,
+		58 taxon_58,
+		59 taxon_59,
+		60 taxon_60,
+		61 taxon_61,
+		62 taxon_62,
+		63 taxon_63,
+		64 taxon_64,
+		65 taxon_65,
+		66 taxon_66,
+		67 taxon_67,
+		68 taxon_68,
+		69 taxon_69,
+		70 taxon_70,
+		71 taxon_71,
+		72 taxon_72,
+		73 taxon_73,
+		74 taxon_74,
+		75 taxon_75,
+		76 taxon_76,
+		77 taxon_77,
+		78 taxon_78,
+		79 taxon_79,
+		80 taxon_80,
+		81 taxon_81,
+		82 taxon_82,
+		83 taxon_83,
+		84 taxon_84,
+		85 taxon_85,
+		86 taxon_86,
+		87 taxon_87,
+		88 taxon_88,
+		89 taxon_89,
+		90 taxon_90,
+		91 taxon_91,
+		92 taxon_92,
+		93 taxon_93,
+		94 taxon_94,
+		95 taxon_95,
+		96 taxon_96,
+		97 taxon_97,
+		98 taxon_98,
+		99 taxon_99,
+		100 taxon_100,
+		101 taxon_101,
+		102 taxon_102,
+		103 taxon_103,
+		104 taxon_104,
+		105 taxon_105,
+		106 taxon_106,
+		107 taxon_107,
+		108 taxon_108,
+		109 taxon_109,
+		110 taxon_110,
+		111 taxon_111,
+		112 taxon_112,
+		113 taxon_113,
+		114 taxon_114,
+		115 taxon_115,
+		116 taxon_116,
+		117 taxon_117,
+		118 taxon_118,
+		119 taxon_119,
+		120 taxon_120,
+		121 taxon_121,
+		122 taxon_122,
+		123 taxon_123,
+		124 taxon_124,
+		125 taxon_125,
+		126 taxon_126,
+		127 taxon_127,
+		128 taxon_128,
+		129 taxon_129,
+		130 taxon_130,
+		131 taxon_131,
+		132 taxon_132,
+		133 taxon_133,
+		134 taxon_134,
+		135 taxon_135,
+		136 taxon_136,
+		137 taxon_137,
+		138 taxon_138,
+		139 taxon_139,
+		140 taxon_140;
+	TREE 'Simulated Tree (with character) 1' = (((13:0.26414291654120825,89:0.26414291654120825):12.66569902022103,((4:2.245005924397304,(57:1.4365952502271064,72:1.4365952502271064):0.808410674170198):10.061848574720196,((((5:6.7062377792435,(21:4.397116509475041,(((33:1.493667627615986,71:1.493667627615986):2.5854357019863663,((40:2.976067881831738,53:2.976067881831738):0.2557339990166187,49:3.2318018808483564):0.8473014487539956):0.09137888232724879,(36:3.179102152041311,50:3.17910215204 [...]
+	TREE 'Simulated Tree (with character) 2' = ((((57:8.740564889482517,12:8.740564889482515):0.08951737253490406,(11:2.686632950623149,49:2.6866329506231486):6.143449311394269):1.9682270009255305,3:10.798309262942945):0.10691079279564765,((((((((((2:0.3076379941221983,94:0.3076379941221983):0.14765376902865543,(87:0.008091472062248412,100:0.008091472062248412):0.44720029108860526):1.1528414010681944,(62:1.5798099269923387,80:1.5798099269923387):0.028323237226710315):5.315645902764501,(13:5 [...]
+	TREE 'Simulated Tree (with character) 3' = (((((((1:1.5622844604031214,68:1.5622844604031214):0.6620126144845917,(56:1.0301802241163402,78:1.0301802241163402):1.1941168507713722):1.7548017644175342,(32:0.16290197669355147,99:0.16290197669355147):3.8161968626116964):2.4374614041472977,((15:0.6272692628633048,89:0.6272692628633048):3.036006628479801,(((38:0.48495012101992835,94:0.48495012101992835):0.5399002029330823,(79:0.906466918413682,((81:0.2517086324661378,96:0.2517086324661378):0.3 [...]
+	TREE 'Simulated Tree (with character) 4' = (1:15.208188673335862,((12:5.178290028326698,(5:4.979128402850933,28:4.979128402850933):0.19916162547576394):8.425939537084158,(((4:3.01780032402549,53:3.01780032402549):8.353066041129946,((((16:0.6015336970588279,90:0.6015336970588279):0.7258305059401745,71:1.3273642029990025):8.264151809784806,(10:3.323232475098665,((50:1.0205650056491342,(72:0.4423424282945011,92:0.4423424282945011):0.578222577354633):1.3985087173354256,(58:1.874224925730212 [...]
+	TREE 'Simulated Tree (with character) 5' = ((((((((26:0.23038280848456946,91:0.23038280848456946):0.1019006233978754,67:0.3322834318824449):0.8900761763597418,(68:0.42710801362424444,86:0.42710801362424444):0.7952515946179421):1.2332693329896927,((48:1.0315561945675082,74:1.0315561945675082):0.2834716738487835,41:1.315027868416292):1.1406010728155873):5.133045939225098,((13:6.274108818958306,(21:1.062440989315495,72:1.062440989315495):5.211667829642811):0.12429726790346002,(20:5.8027897 [...]
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  5;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  5;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  5;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6732219986260810463 WM1148f47d2081;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7885352486418568017 WM1149667c69b0;
+			checksum 0 905627623 WM1149667c69b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 72;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1163 648;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6732219986260810463  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 786.1187814845004.4817563795317733133;
+				getTreeWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1091 581;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow.arrow;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+						toggleCorners on;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #7885352486418568017;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -307;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7885352486418568017 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1091 581;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal on;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '../Introduction.nex';
+			setPrevFileName '07-contTreeSim.nex';
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 524 161;
+					setLocation 108 630;
+					setFont SanSerif;
+					setFontSize 10;
+				setExplanation 'This shows a tree and character simulated together. The BiSSE model was used, with rate of speciation with state 0 = 0.1, with state 1 = 0.3, rate of extinction with state 0 = 0.05, with state 1 = 0.05, and rates of state change 0.005.^n^nA block of simulated trees and accompanying matrix (such that the i''th character was simulated with the i''th tree) was made by selecting Trees & Diversification Characters from the Taxa & Trees menu.  ';
+				setTitle Simulated_trees_&_characters;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_main_Intro.;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Introduction.nex b/Resources/examples/Introduction.nex
new file mode 100755
index 0000000..9a5f2e2
--- /dev/null
+++ b/Resources/examples/Introduction.nex
@@ -0,0 +1,52 @@
+#NEXUS
+[written Sun May 04 14:32:01 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 421 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 421 23;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'Here are links to example files that serve as a guided tour to using Mesquite and the analyses it can perform. ^n^n';
+				setTitle Mesquite_Examples;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Basic_Examples  'Basic_Examples/introduction.nex';
+				addFileLink Reconstructing_Ancestral_States  'Ancestral_States/01-DataMatrix.nex';
+				addFileLink Molecular_Examples  'Molecular/00-introduction.nex';
+				addFileLink 'Coalescence/Population genetics'  'Coalescence/00-introduction.nex';
+				addFileLink Character_Simulations  'Character_Simulations/00-introduction.nex';
+				addFileLink Multivariate_Continuous_Analyses  'Multivariate_Continuous/00-introduction.nex';
+				addFileLink Character_Correlation  'Correlation/00-introduction.nex';
+				addFileLink Species_Diversification  'Diversification/00-introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/00-introduction.nex b/Resources/examples/Molecular/00-introduction.nex
new file mode 100755
index 0000000..8395b7c
--- /dev/null
+++ b/Resources/examples/Molecular/00-introduction.nex
@@ -0,0 +1,54 @@
+#NEXUS
+[written Sat Jun 07 12:28:17 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Example files for coalescence calculations^n^nThe files linked to this one illustrate some of the coalescence calculations that can be done by the package of coalescence modules of the Mesquite system.  To learn more about this package, use the Coalescence Package menu item of the Help menu, or touch on the banner in the Mesquite Startup window. (It should take you to your web browser, perhaps after asking you to locate the browser.)^n^nTo go from one file to another, [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 810 464;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-gcContentChart.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 810 447;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 14;
+					setActive;
+				setExplanation 'Example files for molecular evolution and phylogeny^n^nThe files linked to this one illustrate some of the calculations for DNA and protein sequence data that can be done by Mesquite.  These examples are incomplete.  More examples can be found in the Simulations folder, in connection with the Simulations & Randomizations section of the manual, and in the Coalescence folder.^n^nTo go to the first example, hit the "Next" button above.';
+				setTitle Molecular_Evolution_&_Phylogeny;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addWebLink Simulations  'http://mesquiteproject.wikispaces.com/Simulating+DNA+Evolution';
+				addFileLink Coalescence  '../Coalescence/00-introduction.nex';
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/01-gcContentChart.nex b/Resources/examples/Molecular/01-gcContentChart.nex
new file mode 100755
index 0000000..7232caa
--- /dev/null
+++ b/Resources/examples/Molecular/01-gcContentChart.nex
@@ -0,0 +1,571 @@
+#NEXUS
+[written Sat Jun 07 12:28:36 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=101;
+	TAXLABELS
+		Sand_S127W Papacheus_093X Pshoshoensis_430Z Plongimanus_510Z ustul_RailX_211Z ustul_Mar_551Z cfsign_AV_570Z signat_684Z amicus_387Z alachua_527X cognatus_294W peckhami_382X elegans_213Z conjun_179AX geron_60Z doroth_LS_621Z huast_Chp_623X cfparat_88W venat_119Z carolin_134X cocker_108Z splend_525Z ocala_612Z pugill_459Z hallini_37Z cambrid_443Z fall_TX_288Z fallax_Chp_647X fallax_WComp_648W oregon_05Z icenog_196Z taras_643Z cftaras_554Z texanus_494X altan_AZ_124Z altan_Chih_325Z altan_ [...]
+	;
+	BLOCKID WM1148b0459f41;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-gcContentChart.nex"';
+	DIMENSIONS  NCHAR=716;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+CHARSTATELABELS 
+18 #17, 244 ex1., 245 Int1, 391 int1, 392 ex2., 573 ex2., 574 int2, 665 int2, 666 ex3. ; 
+	MATRIX
+	Sand_S127W         TACATTAAAAAGATTGGTTATAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAATATGGGATGGTACAAAGGTTGGTCCATTGAACGTAAAACCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-TGTGTT-ACCTTAATTTTTTTTTTCTAT--ACT-TGCAG-TAACTCTA-G---TCT---AACAGT-ACTTGAATT--AATTTG-AACAACT--GAGTA---TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTGGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACT [...]
+
+	Papacheus_093X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATGT-----TTTTTT-ACT-TGGAG--AACTCAA----TTTT---AACAA-----------------TAGAATAATT-T-TTTAACCTTTTTTTACTAA--------------CCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Pshoshoensis_430Z  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGAGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATAT-----TTTATT-----TCAAG--TACTTAA----TTTT---AACAATTACTTAAGTG-AAAAATTGAATAATT-TTTTTAACCTTTT-TTACCTA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Plongimanus_510Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATGT----TTTCTTT-ACT-TGGAA--TACT-AA----TTTT---AACAATTACTTAAATG-AACA-TTGGATAATT-TTTTTAACCTTTT-TTACCAA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_RailX_211Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGGAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT--------------AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_Mar_551Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTATTATTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	cfsign_AV_570Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	signat_684Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT------AATTACTT------AAACTT--AACAACT--GAGTATTATTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	amicus_387Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAGCGTAAAGGCAACAAGACTGAAGGGAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AACAATTACTT------TAACTT--AACAACT--GAGTATTATTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	alachua_527X       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAA-T--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cognatus_294W      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGG-GACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACA-TTACTTAAATT--AACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGG-ATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	peckhami_382X      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTC-TCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	elegans_213Z       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACC-ATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	conjun_179AX       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAG-ACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGA-AAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	geron_60Z          TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doroth_LS_621Z     TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	huast_Chp_623X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTAT-GAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGC-ATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAA--G--TTTTCTTT-ACT-TGGTA--TACACAA-GTCTTCT---AAC-ATTGCTTAAATT-AAACTT--GATAACT--GAGTAA--TTTTGCTGC-TACCTATAT-------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTT-AAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfparat_88W        TACATTAAAAAAATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCGA-GTCTTCT---AACAATTGCTTACATT-AAACTT-----------GAGTAA--TTTTACTA----TTTTTTTTTT----TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	venat_119Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCCTT-ACTCTAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACA--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carolin_134X       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTT-GAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCATT-ACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACT--AAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cocker_108Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TAGTG--TACTCAA-ATCTTCT---AACAATTGCTTGAATT-GAACAA--AATAAC----AGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	splend_525Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTCGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ocala_612Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTAG--TTTTCTTTTACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pugill_459Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTT---AACAATT-CTTGAATT-AAACT-TTAATAACT--GAGTAA--TTTTGCTGCCAA--------------TCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	hallini_37Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAACCTGAAATT------TTCTTT-ACT-TGGTG--TACTGAA-ATCTTCT---AACAATTGTTTTAATT-AAACTT--AATAACA--GAGTAA--TTTTGCTATAAAT-------------TTTGTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cambrid_443Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGAATT-AAACTATTAATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fall_TX_288Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACG-AAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_Chp_647X    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATCC-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_WComp_648W  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGGATT-TAACTTT-AATGACT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	oregon_05Z         TACATCAAGAAGATTGGTTACAATCCTGCAACAGTTCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	icenog_196Z        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTTTTCT---AACAATTGCTTGAATT-AAA----------TT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	taras_643Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCGTTTGTTCCAATTTCTGGGTGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TAC--------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cftaras_554Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGG-TGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGG-AAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACT-------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	texanus_494X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGG-TGGAATGGCGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCCCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ATT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACTCTGAGTAA--TTTTGTTACCAATC------------TTGTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_AZ_124Z      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATA-AAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Chih_325Z    TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAAT-TG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Oax_645W     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsugill_Nay_281X  TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGCTGAAGTTTG--TGTTCTTT-ACT-TGGTG--TATTAAA-GTCTTCT---AACAACTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTGAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_Cham_639W   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCAATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACA-TGGTG--TACTT---GTCTTCA---AACG-TTGCTTGATTT-AAACTT------------AGTAA--TTTTGCTACCAATCTTTTTTTTTTT-TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LG_638W     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTTTTT------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LY_608Z     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTT---------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	yucun_636Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAATTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCA----CTTCTTCTAACAATTGCTTGAATT-AAACTTT-AATAACA--GAGTTAA-TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	banksi_104X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCACCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTATGTCGAACT-----TTTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--GAATAA--TTTTGCTACCAATCT-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	amer_WM_316W       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTTTTTTTTTTTTTACT-TGGTG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATTAAAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	amer_DG_345X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTCGTTTTTTTA---ACT-TGGTG--TACTCAA-GTCTTCGAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTCGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	bulb_Long_536Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATT----------------AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	waughi_129W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTTTACT-TCGTG--TACTCAA-GTCTT-GAATTATAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsans_349W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTA--ACT-TGGAG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	sans_368W          TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTT--ACT-TGGTG--TACTCAA-GTCTT-GAATTAAAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kubai_540W         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATAAAACTTGCTTGAATT-AAACTTC--ATAACT--GAG-AA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_KR_377Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTAAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_Baja_591Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACAGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	must_BRB_365X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGGCCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT--TTTTC????????????????????????????????????????????????????????C--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ophrys_SL_352X     TACATTAAGAAGATTGGTTACAATCCTGC-ACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGA-CCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT??????????????????????????????????????????????????????????????????ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tuber_WP_464X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCC-CTCCAAGATGTATATAAGATTGGTGGTATGT-T---TTCTTAACCTGAAATTTG--TTT-CTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAAC?????????????????????????????--?????????TTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kawini_592X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGA-CCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAG-CCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTT-AATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	notial_471X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGT-CCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTCTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGCTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGATGTATATTAAA-CTC-TCT---AACAATTAATGGAATT-AAACTTC-AATAATT--GAATAA--TTTTGCTACCAATCTT----------TATTTTGAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTAAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	jucun_395Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TGTTCTTT-ACT-TGGTGTATATTAAA-GTCT------AACAATTGCTGGAATT-AAACTTT-AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calcalc_524Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTCCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTGTATATTA---GTCTTCT---AACAATTGCTGGAATT-AAACT---AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virid_470X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calmadd_16Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACAT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTAC-TTTGCTCCAGCTAACA [...]
+
+	cfcalc_546W        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAATAATTGCTTCAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	trim_559X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAATTTAAAC----AATAACT--TAG-AA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	orbus_27Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT----GTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAA-TTAAACTT--AATAACT--TAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCGGCTAACA [...]
+
+	morat_485Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCT-TTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAA-AATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	cfmor_ET_611W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_LY_667W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTTGATAAACCTCTTCGTTTGCCCCTGCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TTTTTTCTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_Cham_662Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATCACTTTAAATTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAA--------------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	divar_563W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTTGTTAT-----------------T-TTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	caldiv_ES_600Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTT---AT-----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cyncity_468Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAATTG--TTTTCTTT-ACT-TGGT---TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCATTTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	silvcty_285W       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Chir_274W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GA-TAA--TTTTGCTATCAATTTTTTTTT-----TTTTTTTTAGGTATTGGAAC-GTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGGATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Yec_531X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AA??TT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTT--------TTTTTTTTAGGTATTGGTACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_LS_659X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-AT-CTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_Teq_661Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAGGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-ATACTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fort_290Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCC-ATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAGC-TGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTTCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TCTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	aztec_218W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cffest_517Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGGCTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Heuco_502Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACATTTGCTTTAATT-AA-CTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Bis_390Z     TACATTAAGAAGATTGGTTACAA-CCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAA-ACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAAC---GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	zebra_442W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCCAAGAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGTT-TC----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tlax_674X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAA-ACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCA????????????????????????????????????????????--????????????????????????T---------CTTTTTTTAGGTATTGGAACAGTCCCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Pach_652W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACTTGAAATTTG--TTTTCTTT-GCT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTAATT-AAACTT--AATAACG--GAGTAA--TTTTGCTATCAATTTTTTTATTTATTTTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Cat_167Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Swiss_682Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCACTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	mexic_496Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACC-GTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carp_LS_670Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	boreal_130Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCT------AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coec_96Z           TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT-----AACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cusp_550Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coecgrp_Mag_580Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TGCTTAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pyr_10Z            TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAATA [...]
+
+	ball_383X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAG-CCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAA-CTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTT-----AAACTT------ACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCC-GGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfanep_576Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGATG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_LB_557Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_ITT_314Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTAT-AATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ammo_556Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACC-GAAG------TTTTCTTT-A-T-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpyrr_578X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T-CTCAA-GTCTTCTAACAACAATTGCTTTTATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	brunn_543X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAA-ATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCT????????????????????????????????????????????????????????????????????????????????--?????????????????????????????????????TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	schlin_160X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAA-AAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG????????????????????????????????????????????????????????????????????????--????????????????????????-----------TCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GG-ATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+
+;
+
+
+		BLOCKID WM1148b045a600;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "01-gcContentChart.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Sand_S127W,
+		2 Papacheus_093X,
+		3 Pshoshoensis_430Z,
+		4 Plongimanus_510Z,
+		5 ustul_RailX_211Z,
+		6 ustul_Mar_551Z,
+		7 cfsign_AV_570Z,
+		8 signat_684Z,
+		9 amicus_387Z,
+		10 alachua_527X,
+		11 cognatus_294W,
+		12 peckhami_382X,
+		13 elegans_213Z,
+		14 conjun_179AX,
+		15 geron_60Z,
+		16 doroth_LS_621Z,
+		17 huast_Chp_623X,
+		18 cfparat_88W,
+		19 venat_119Z,
+		20 carolin_134X,
+		21 cocker_108Z,
+		22 splend_525Z,
+		23 ocala_612Z,
+		24 pugill_459Z,
+		25 hallini_37Z,
+		26 cambrid_443Z,
+		27 fall_TX_288Z,
+		28 fallax_Chp_647X,
+		29 fallax_WComp_648W,
+		30 oregon_05Z,
+		31 icenog_196Z,
+		32 taras_643Z,
+		33 cftaras_554Z,
+		34 texanus_494X,
+		35 altan_AZ_124Z,
+		36 altan_Chih_325Z,
+		37 altan_Oax_645W,
+		38 cfsugill_Nay_281X,
+		39 cfpoch_Cham_639W,
+		40 cfpoch_LG_638W,
+		41 cfpoch_LY_608Z,
+		42 yucun_636Z,
+		43 banksi_104X,
+		44 amer_WM_316W,
+		45 amer_DG_345X,
+		46 bulb_Long_536Z,
+		47 waughi_129W,
+		48 cfsans_349W,
+		49 sans_368W,
+		50 kubai_540W,
+		51 tars_KR_377Z,
+		52 tars_Baja_591Z,
+		53 must_BRB_365X,
+		54 ophrys_SL_352X,
+		55 tuber_WP_464X,
+		56 kawini_592X,
+		57 notial_471X,
+		58 jucun_395Z,
+		59 calcalc_524Z,
+		60 virid_470X,
+		61 calmadd_16Z,
+		62 cfcalc_546W,
+		63 trim_559X,
+		64 orbus_27Z,
+		65 morat_485Z,
+		66 cfmor_ET_611W,
+		67 cfmor_LY_667W,
+		68 cfmor_Cham_662Z,
+		69 divar_563W,
+		70 caldiv_ES_600Z,
+		71 cyncity_468Z,
+		72 silvcty_285W,
+		73 doss_Chir_274W,
+		74 doss_Yec_531X,
+		75 veliv_LS_659X,
+		76 veliv_Teq_661Z,
+		77 fort_290Z,
+		78 aztec_218W,
+		79 cffest_517Z,
+		80 klaus_Heuco_502Z,
+		81 klaus_Bis_390Z,
+		82 zebra_442W,
+		83 tlax_674X,
+		84 virg_Pach_652W,
+		85 virg_Cat_167Z,
+		86 virg_Swiss_682Z,
+		87 mexic_496Z,
+		88 carp_LS_670Z,
+		89 boreal_130Z,
+		90 coec_96Z,
+		91 cusp_550Z,
+		92 coecgrp_Mag_580Z,
+		93 pyr_10Z,
+		94 ball_383X,
+		95 cfanep_576Z,
+		96 anep_LB_557Z,
+		97 anep_ITT_314Z,
+		98 ammo_556Z,
+		99 cfpyrr_578X,
+		100 brunn_543X,
+		101 schlin_160X;
+	TREE Griswold = (1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,( [...]
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL introns COLOR = (RGB 0.88627451 0.00392157 0.28627451) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET * UNTITLED   =   245 -  391 574 -  665;
+	CHARSET introns   =   245 -  391 574 -  665;
+	CHARSET exons   =   1 -  244 392 -  573 666 -  716;
+
+	CHARPARTITION * UNTITLED  =  introns :  245 -  391 574 -  665;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  716;
+
+	EXSET * UNTITLED  = ;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = '1. special character: GC bias for taxon^n^n2. *** number for character: GC bias chart^n^n3. Parsimony steps^n^n4. Gaps';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  716;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  716;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5362004184182154199 WM1148b0459f41;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5453088708553656046 WM1148b045a600;
+			checksum 0 2175300760 WM1148b045a600;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 684 232;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5453088708553656046 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 746 442;
+					setLocation 724 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharacterValuesChart.CharacterValuesChart;
+		tell It;
+			setTaxa #5362004184182154199;
+			setCalculator  #mesquite.molec.CharacterGCBias.CharacterGCBias;
+			tell It;
+				setMode 0;
+			endTell;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #5453088708553656046;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 718 455;
+					setLocation 3 322;
+					setFont Dialog;
+					setFontSize 12;
+					getToolPalette;
+					tell It;
+					endTell;
+					valuesByItems;
+					setChartType  #mesquite.charts.Histogram.Histogram;
+				tell It;
+					suspend;
+					showAverageToggle on;
+					showPercentToggle off;
+					setCumulativeMode 0;
+					showAsBarChartToggle on;
+					showRawToggle off;
+					setNumberIntervals 20;
+					setIntervalSize 1.0;
+					setMovingWindowSize 10.0 2.0;
+					setMode 3;
+					resume;
+				endTell;
+					toggleColorItems on;
+					setNumberItems 716;
+				endTell;
+				enableCalculations;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-gcContentMatrix.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 684 215;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In the Character Matrix Editor are DNA sequences of EF1-alpha in some spiders.  The cells of the matrix are colored using Color By State from the Color Cells submenu.^n^nBelow is a chart of average (across taxa) GC bias for each site along the sequence.  The chart is using amoving window analysis to smooth the chart.  The red regions are the introns.  As expected, the introns are less GC rich (i.e. more AT rich) than the exons.';
+				setTitle GC_bias;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/02-gcContentMatrix.nex b/Resources/examples/Molecular/02-gcContentMatrix.nex
new file mode 100644
index 0000000..9d676e0
--- /dev/null
+++ b/Resources/examples/Molecular/02-gcContentMatrix.nex
@@ -0,0 +1,516 @@
+#NEXUS
+[written Sat Jun 07 12:28:56 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=101;
+	TAXLABELS
+		Sand_S127W Papacheus_093X Pshoshoensis_430Z Plongimanus_510Z ustul_RailX_211Z ustul_Mar_551Z cfsign_AV_570Z signat_684Z amicus_387Z alachua_527X cognatus_294W peckhami_382X elegans_213Z conjun_179AX geron_60Z doroth_LS_621Z huast_Chp_623X cfparat_88W venat_119Z carolin_134X cocker_108Z splend_525Z ocala_612Z pugill_459Z hallini_37Z cambrid_443Z fall_TX_288Z fallax_Chp_647X fallax_WComp_648W oregon_05Z icenog_196Z taras_643Z cftaras_554Z texanus_494X altan_AZ_124Z altan_Chih_325Z altan_ [...]
+	;
+	BLOCKID WM1148b0501542;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-gcContentMatrix.nex"';
+	DIMENSIONS  NCHAR=716;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+CHARSTATELABELS 
+244 ex1., 245 Int1, 391 int1, 392 ex2., 573 ex2., 574 int2, 665 int2, 666 ex3. ; 
+	MATRIX
+	Sand_S127W         TACATTAAAAAGATTGGTTATAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAATATGGGATGGTACAAAGGTTGGTCCATTGAACGTAAAACCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-TGTGTT-ACCTTAATTTTTTTTTTCTAT--ACT-TGCAG-TAACTCTA-G---TCT---AACAGT-ACTTGAATT--AATTTG-AACAACT--GAGTA---TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTGGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACT [...]
+
+	Papacheus_093X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATGT-----TTTTTT-ACT-TGGAG--AACTCAA----TTTT---AACAA-----------------TAGAATAATT-T-TTTAACCTTTTTTTACTAA--------------CCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Pshoshoensis_430Z  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGAGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATAT-----TTTATT-----TCAAG--TACTTAA----TTTT---AACAATTACTTAAGTG-AAAAATTGAATAATT-TTTTTAACCTTTT-TTACCTA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Plongimanus_510Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATGT----TTTCTTT-ACT-TGGAA--TACT-AA----TTTT---AACAATTACTTAAATG-AACA-TTGGATAATT-TTTTTAACCTTTT-TTACCAA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_RailX_211Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGGAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT--------------AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_Mar_551Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTATTATTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	cfsign_AV_570Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	signat_684Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT------AATTACTT------AAACTT--AACAACT--GAGTATTATTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	amicus_387Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAGCGTAAAGGCAACAAGACTGAAGGGAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AACAATTACTT------TAACTT--AACAACT--GAGTATTATTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	alachua_527X       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAA-T--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cognatus_294W      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGG-GACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACA-TTACTTAAATT--AACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGG-ATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	peckhami_382X      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTC-TCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	elegans_213Z       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACC-ATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	conjun_179AX       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAG-ACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGA-AAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	geron_60Z          TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doroth_LS_621Z     TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	huast_Chp_623X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTAT-GAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGC-ATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAA--G--TTTTCTTT-ACT-TGGTA--TACACAA-GTCTTCT---AAC-ATTGCTTAAATT-AAACTT--GATAACT--GAGTAA--TTTTGCTGC-TACCTATAT-------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTT-AAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfparat_88W        TACATTAAAAAAATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCGA-GTCTTCT---AACAATTGCTTACATT-AAACTT-----------GAGTAA--TTTTACTA----TTTTTTTTTT----TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	venat_119Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCCTT-ACTCTAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACA--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carolin_134X       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTT-GAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCATT-ACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACT--AAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cocker_108Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TAGTG--TACTCAA-ATCTTCT---AACAATTGCTTGAATT-GAACAA--AATAAC----AGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	splend_525Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTCGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ocala_612Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTAG--TTTTCTTTTACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pugill_459Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTT---AACAATT-CTTGAATT-AAACT-TTAATAACT--GAGTAA--TTTTGCTGCCAA--------------TCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	hallini_37Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAACCTGAAATT------TTCTTT-ACT-TGGTG--TACTGAA-ATCTTCT---AACAATTGTTTTAATT-AAACTT--AATAACA--GAGTAA--TTTTGCTATAAAT-------------TTTGTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cambrid_443Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGAATT-AAACTATTAATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fall_TX_288Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACG-AAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_Chp_647X    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATCC-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_WComp_648W  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGGATT-TAACTTT-AATGACT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	oregon_05Z         TACATCAAGAAGATTGGTTACAATCCTGCAACAGTTCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	icenog_196Z        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTTTTCT---AACAATTGCTTGAATT-AAA----------TT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	taras_643Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCGTTTGTTCCAATTTCTGGGTGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TAC--------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cftaras_554Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGG-TGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGG-AAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACT-------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	texanus_494X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGG-TGGAATGGCGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCCCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ATT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACTCTGAGTAA--TTTTGTTACCAATC------------TTGTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_AZ_124Z      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATA-AAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Chih_325Z    TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAAT-TG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Oax_645W     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsugill_Nay_281X  TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGCTGAAGTTTG--TGTTCTTT-ACT-TGGTG--TATTAAA-GTCTTCT---AACAACTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTGAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_Cham_639W   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCAATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACA-TGGTG--TACTT---GTCTTCA---AACG-TTGCTTGATTT-AAACTT------------AGTAA--TTTTGCTACCAATCTTTTTTTTTTT-TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LG_638W     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTTTTT------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LY_608Z     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTT---------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	yucun_636Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAATTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCA----CTTCTTCTAACAATTGCTTGAATT-AAACTTT-AATAACA--GAGTTAA-TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	banksi_104X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCACCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTATGTCGAACT-----TTTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--GAATAA--TTTTGCTACCAATCT-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	amer_WM_316W       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTTTTTTTTTTTTTACT-TGGTG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATTAAAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	amer_DG_345X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTCGTTTTTTTA---ACT-TGGTG--TACTCAA-GTCTTCGAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTCGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	bulb_Long_536Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATT----------------AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	waughi_129W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTTTACT-TCGTG--TACTCAA-GTCTT-GAATTATAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsans_349W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTA--ACT-TGGAG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	sans_368W          TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTT--ACT-TGGTG--TACTCAA-GTCTT-GAATTAAAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kubai_540W         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATAAAACTTGCTTGAATT-AAACTTC--ATAACT--GAG-AA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_KR_377Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTAAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_Baja_591Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACAGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	must_BRB_365X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGGCCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT--TTTTC????????????????????????????????????????????????????????C--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ophrys_SL_352X     TACATTAAGAAGATTGGTTACAATCCTGC-ACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGA-CCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT??????????????????????????????????????????????????????????????????ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tuber_WP_464X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCC-CTCCAAGATGTATATAAGATTGGTGGTATGT-T---TTCTTAACCTGAAATTTG--TTT-CTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAAC?????????????????????????????--?????????TTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kawini_592X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGA-CCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAG-CCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTT-AATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	notial_471X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGT-CCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTCTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGCTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGATGTATATTAAA-CTC-TCT---AACAATTAATGGAATT-AAACTTC-AATAATT--GAATAA--TTTTGCTACCAATCTT----------TATTTTGAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTAAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	jucun_395Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TGTTCTTT-ACT-TGGTGTATATTAAA-GTCT------AACAATTGCTGGAATT-AAACTTT-AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calcalc_524Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTCCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTGTATATTA---GTCTTCT---AACAATTGCTGGAATT-AAACT---AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virid_470X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calmadd_16Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACAT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTAC-TTTGCTCCAGCTAACA [...]
+
+	cfcalc_546W        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAATAATTGCTTCAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	trim_559X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAATTTAAAC----AATAACT--TAG-AA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	orbus_27Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT----GTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAA-TTAAACTT--AATAACT--TAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCGGCTAACA [...]
+
+	morat_485Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCT-TTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAA-AATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	cfmor_ET_611W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_LY_667W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTTGATAAACCTCTTCGTTTGCCCCTGCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TTTTTTCTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_Cham_662Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATCACTTTAAATTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAA--------------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	divar_563W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTTGTTAT-----------------T-TTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	caldiv_ES_600Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTT---AT-----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cyncity_468Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAATTG--TTTTCTTT-ACT-TGGT---TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCATTTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	silvcty_285W       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Chir_274W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GA-TAA--TTTTGCTATCAATTTTTTTTT-----TTTTTTTTAGGTATTGGAAC-GTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGGATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Yec_531X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AA??TT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTT--------TTTTTTTTAGGTATTGGTACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_LS_659X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-AT-CTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_Teq_661Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAGGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-ATACTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fort_290Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCC-ATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAGC-TGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTTCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TCTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	aztec_218W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cffest_517Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGGCTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Heuco_502Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACATTTGCTTTAATT-AA-CTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Bis_390Z     TACATTAAGAAGATTGGTTACAA-CCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAA-ACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAAC---GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	zebra_442W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCCAAGAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGTT-TC----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tlax_674X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAA-ACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCA????????????????????????????????????????????--????????????????????????T---------CTTTTTTTAGGTATTGGAACAGTCCCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Pach_652W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACTTGAAATTTG--TTTTCTTT-GCT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTAATT-AAACTT--AATAACG--GAGTAA--TTTTGCTATCAATTTTTTTATTTATTTTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Cat_167Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Swiss_682Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCACTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	mexic_496Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACC-GTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carp_LS_670Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	boreal_130Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCT------AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coec_96Z           TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT-----AACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cusp_550Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coecgrp_Mag_580Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TGCTTAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pyr_10Z            TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAATA [...]
+
+	ball_383X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAG-CCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAA-CTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTT-----AAACTT------ACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCC-GGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfanep_576Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGATG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_LB_557Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_ITT_314Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTAT-AATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ammo_556Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACC-GAAG------TTTTCTTT-A-T-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpyrr_578X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T-CTCAA-GTCTTCTAACAACAATTGCTTTTATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	brunn_543X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAA-ATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCT????????????????????????????????????????????????????????????????????????????????--?????????????????????????????????????TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	schlin_160X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAA-AAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG????????????????????????????????????????????????????????????????????????--????????????????????????-----------TCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GG-ATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+
+;
+
+
+		BLOCKID WM1148b0501ae0;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "02-gcContentMatrix.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Sand_S127W,
+		2 Papacheus_093X,
+		3 Pshoshoensis_430Z,
+		4 Plongimanus_510Z,
+		5 ustul_RailX_211Z,
+		6 ustul_Mar_551Z,
+		7 cfsign_AV_570Z,
+		8 signat_684Z,
+		9 amicus_387Z,
+		10 alachua_527X,
+		11 cognatus_294W,
+		12 peckhami_382X,
+		13 elegans_213Z,
+		14 conjun_179AX,
+		15 geron_60Z,
+		16 doroth_LS_621Z,
+		17 huast_Chp_623X,
+		18 cfparat_88W,
+		19 venat_119Z,
+		20 carolin_134X,
+		21 cocker_108Z,
+		22 splend_525Z,
+		23 ocala_612Z,
+		24 pugill_459Z,
+		25 hallini_37Z,
+		26 cambrid_443Z,
+		27 fall_TX_288Z,
+		28 fallax_Chp_647X,
+		29 fallax_WComp_648W,
+		30 oregon_05Z,
+		31 icenog_196Z,
+		32 taras_643Z,
+		33 cftaras_554Z,
+		34 texanus_494X,
+		35 altan_AZ_124Z,
+		36 altan_Chih_325Z,
+		37 altan_Oax_645W,
+		38 cfsugill_Nay_281X,
+		39 cfpoch_Cham_639W,
+		40 cfpoch_LG_638W,
+		41 cfpoch_LY_608Z,
+		42 yucun_636Z,
+		43 banksi_104X,
+		44 amer_WM_316W,
+		45 amer_DG_345X,
+		46 bulb_Long_536Z,
+		47 waughi_129W,
+		48 cfsans_349W,
+		49 sans_368W,
+		50 kubai_540W,
+		51 tars_KR_377Z,
+		52 tars_Baja_591Z,
+		53 must_BRB_365X,
+		54 ophrys_SL_352X,
+		55 tuber_WP_464X,
+		56 kawini_592X,
+		57 notial_471X,
+		58 jucun_395Z,
+		59 calcalc_524Z,
+		60 virid_470X,
+		61 calmadd_16Z,
+		62 cfcalc_546W,
+		63 trim_559X,
+		64 orbus_27Z,
+		65 morat_485Z,
+		66 cfmor_ET_611W,
+		67 cfmor_LY_667W,
+		68 cfmor_Cham_662Z,
+		69 divar_563W,
+		70 caldiv_ES_600Z,
+		71 cyncity_468Z,
+		72 silvcty_285W,
+		73 doss_Chir_274W,
+		74 doss_Yec_531X,
+		75 veliv_LS_659X,
+		76 veliv_Teq_661Z,
+		77 fort_290Z,
+		78 aztec_218W,
+		79 cffest_517Z,
+		80 klaus_Heuco_502Z,
+		81 klaus_Bis_390Z,
+		82 zebra_442W,
+		83 tlax_674X,
+		84 virg_Pach_652W,
+		85 virg_Cat_167Z,
+		86 virg_Swiss_682Z,
+		87 mexic_496Z,
+		88 carp_LS_670Z,
+		89 boreal_130Z,
+		90 coec_96Z,
+		91 cusp_550Z,
+		92 coecgrp_Mag_580Z,
+		93 pyr_10Z,
+		94 ball_383X,
+		95 cfanep_576Z,
+		96 anep_LB_557Z,
+		97 anep_ITT_314Z,
+		98 ammo_556Z,
+		99 cfpyrr_578X,
+		100 brunn_543X,
+		101 schlin_160X;
+	TREE Griswold = (1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,( [...]
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL introns COLOR = (RGB 0.88627451 0.00392157 0.28627451) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET * UNTITLED   =   245 -  391 574 -  665;
+	CHARSET introns   =   245 -  391 574 -  665;
+	CHARSET exons   =   1 -  244 392 -  573 666 -  716;
+
+	CHARPARTITION * UNTITLED  =  introns :  245 -  391 574 -  665;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  716;
+
+	EXSET * UNTITLED  =  245 -  391 574 -  665;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = '1. special character: GC bias for taxon^n^n2. *** number for character: GC bias chart^n^n3. Parsimony steps^n^n4. Gaps';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  716;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  716;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5362004184182154199 WM1148b0501542;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5453088708553656046 WM1148b0501ae0;
+			checksum 0 2175300760 WM1148b0501ae0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 435 398;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5453088708553656046 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 907 401;
+					setLocation 466 27;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 12;
+				endTell;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight on;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-gcContentBirdsEye.nex';
+			setPrevFileName '01-gcContentChart.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 435 381;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here the sequence matrix is colored not by colors for A, C, G and T, but by GC content using a moving window analysis.  For each site in each sequence, the density of blue shows the average GC content over a moving window of bases to the left and right of the site.  The moving window width can be changed using the "Moving Window" menu item in the Display menu of the character matrix editor window.';
+				setTitle GC_bias;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/03-gcContentBirdsEye.nex b/Resources/examples/Molecular/03-gcContentBirdsEye.nex
new file mode 100755
index 0000000..9fde08e
--- /dev/null
+++ b/Resources/examples/Molecular/03-gcContentBirdsEye.nex
@@ -0,0 +1,515 @@
+#NEXUS
+[written Sat Jun 07 12:29:15 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=101;
+	TAXLABELS
+		Sand_S127W Papacheus_093X Pshoshoensis_430Z Plongimanus_510Z ustul_RailX_211Z ustul_Mar_551Z cfsign_AV_570Z signat_684Z amicus_387Z alachua_527X cognatus_294W peckhami_382X elegans_213Z conjun_179AX geron_60Z doroth_LS_621Z huast_Chp_623X cfparat_88W venat_119Z carolin_134X cocker_108Z splend_525Z ocala_612Z pugill_459Z hallini_37Z cambrid_443Z fall_TX_288Z fallax_Chp_647X fallax_WComp_648W oregon_05Z icenog_196Z taras_643Z cftaras_554Z texanus_494X altan_AZ_124Z altan_Chih_325Z altan_ [...]
+	;
+	BLOCKID WM1148b0538fb3;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-gcContentBirdsEye.nex"';
+	DIMENSIONS  NCHAR=716;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+CHARSTATELABELS 
+18 #17, 244 ex1., 245 Int1, 391 int1, 392 ex2., 573 ex2., 574 int2, 665 int2, 666 ex3. ; 
+	MATRIX
+	Sand_S127W         TACATTAAAAAGATTGGTTATAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAATATGGGATGGTACAAAGGTTGGTCCATTGAACGTAAAACCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-TGTGTT-ACCTTAATTTTTTTTTTCTAT--ACT-TGCAG-TAACTCTA-G---TCT---AACAGT-ACTTGAATT--AATTTG-AACAACT--GAGTA---TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTGGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACT [...]
+
+	Papacheus_093X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATGT-----TTTTTT-ACT-TGGAG--AACTCAA----TTTT---AACAA-----------------TAGAATAATT-T-TTTAACCTTTTTTTACTAA--------------CCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Pshoshoensis_430Z  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGAGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATAT-----TTTATT-----TCAAG--TACTTAA----TTTT---AACAATTACTTAAGTG-AAAAATTGAATAATT-TTTTTAACCTTTT-TTACCTA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Plongimanus_510Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATGT----TTTCTTT-ACT-TGGAA--TACT-AA----TTTT---AACAATTACTTAAATG-AACA-TTGGATAATT-TTTTTAACCTTTT-TTACCAA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_RailX_211Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGGAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT--------------AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_Mar_551Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTATTATTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	cfsign_AV_570Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	signat_684Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT------AATTACTT------AAACTT--AACAACT--GAGTATTATTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	amicus_387Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAGCGTAAAGGCAACAAGACTGAAGGGAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AACAATTACTT------TAACTT--AACAACT--GAGTATTATTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	alachua_527X       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAA-T--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cognatus_294W      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGG-GACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACA-TTACTTAAATT--AACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGG-ATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	peckhami_382X      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTC-TCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	elegans_213Z       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACC-ATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	conjun_179AX       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAG-ACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGA-AAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	geron_60Z          TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doroth_LS_621Z     TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	huast_Chp_623X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTAT-GAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGC-ATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAA--G--TTTTCTTT-ACT-TGGTA--TACACAA-GTCTTCT---AAC-ATTGCTTAAATT-AAACTT--GATAACT--GAGTAA--TTTTGCTGC-TACCTATAT-------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTT-AAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfparat_88W        TACATTAAAAAAATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCGA-GTCTTCT---AACAATTGCTTACATT-AAACTT-----------GAGTAA--TTTTACTA----TTTTTTTTTT----TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	venat_119Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCCTT-ACTCTAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACA--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carolin_134X       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTT-GAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCATT-ACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACT--AAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cocker_108Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TAGTG--TACTCAA-ATCTTCT---AACAATTGCTTGAATT-GAACAA--AATAAC----AGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	splend_525Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTCGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ocala_612Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTAG--TTTTCTTTTACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pugill_459Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTT---AACAATT-CTTGAATT-AAACT-TTAATAACT--GAGTAA--TTTTGCTGCCAA--------------TCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	hallini_37Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAACCTGAAATT------TTCTTT-ACT-TGGTG--TACTGAA-ATCTTCT---AACAATTGTTTTAATT-AAACTT--AATAACA--GAGTAA--TTTTGCTATAAAT-------------TTTGTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cambrid_443Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGAATT-AAACTATTAATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fall_TX_288Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACG-AAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_Chp_647X    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATCC-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_WComp_648W  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGGATT-TAACTTT-AATGACT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	oregon_05Z         TACATCAAGAAGATTGGTTACAATCCTGCAACAGTTCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	icenog_196Z        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTTTTCT---AACAATTGCTTGAATT-AAA----------TT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	taras_643Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCGTTTGTTCCAATTTCTGGGTGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TAC--------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cftaras_554Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGG-TGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGG-AAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACT-------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	texanus_494X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGG-TGGAATGGCGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCCCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ATT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACTCTGAGTAA--TTTTGTTACCAATC------------TTGTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_AZ_124Z      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATA-AAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Chih_325Z    TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAAT-TG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Oax_645W     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsugill_Nay_281X  TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGCTGAAGTTTG--TGTTCTTT-ACT-TGGTG--TATTAAA-GTCTTCT---AACAACTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTGAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_Cham_639W   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCAATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACA-TGGTG--TACTT---GTCTTCA---AACG-TTGCTTGATTT-AAACTT------------AGTAA--TTTTGCTACCAATCTTTTTTTTTTT-TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LG_638W     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTTTTT------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LY_608Z     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTT---------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	yucun_636Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAATTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCA----CTTCTTCTAACAATTGCTTGAATT-AAACTTT-AATAACA--GAGTTAA-TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	banksi_104X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCACCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTATGTCGAACT-----TTTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--GAATAA--TTTTGCTACCAATCT-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	amer_WM_316W       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTTTTTTTTTTTTTACT-TGGTG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATTAAAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	amer_DG_345X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTCGTTTTTTTA---ACT-TGGTG--TACTCAA-GTCTTCGAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTCGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	bulb_Long_536Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATT----------------AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	waughi_129W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTTTACT-TCGTG--TACTCAA-GTCTT-GAATTATAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsans_349W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTA--ACT-TGGAG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	sans_368W          TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTT--ACT-TGGTG--TACTCAA-GTCTT-GAATTAAAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kubai_540W         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATAAAACTTGCTTGAATT-AAACTTC--ATAACT--GAG-AA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_KR_377Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTAAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_Baja_591Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACAGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	must_BRB_365X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGGCCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT--TTTTC????????????????????????????????????????????????????????C--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ophrys_SL_352X     TACATTAAGAAGATTGGTTACAATCCTGC-ACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGA-CCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT??????????????????????????????????????????????????????????????????ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tuber_WP_464X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCC-CTCCAAGATGTATATAAGATTGGTGGTATGT-T---TTCTTAACCTGAAATTTG--TTT-CTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAAC?????????????????????????????--?????????TTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kawini_592X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGA-CCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAG-CCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTT-AATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	notial_471X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGT-CCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTCTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGCTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGATGTATATTAAA-CTC-TCT---AACAATTAATGGAATT-AAACTTC-AATAATT--GAATAA--TTTTGCTACCAATCTT----------TATTTTGAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTAAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	jucun_395Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TGTTCTTT-ACT-TGGTGTATATTAAA-GTCT------AACAATTGCTGGAATT-AAACTTT-AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calcalc_524Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTCCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTGTATATTA---GTCTTCT---AACAATTGCTGGAATT-AAACT---AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virid_470X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calmadd_16Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACAT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTAC-TTTGCTCCAGCTAACA [...]
+
+	cfcalc_546W        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAATAATTGCTTCAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	trim_559X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAATTTAAAC----AATAACT--TAG-AA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	orbus_27Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT----GTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAA-TTAAACTT--AATAACT--TAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCGGCTAACA [...]
+
+	morat_485Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCT-TTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAA-AATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	cfmor_ET_611W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_LY_667W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTTGATAAACCTCTTCGTTTGCCCCTGCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TTTTTTCTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_Cham_662Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATCACTTTAAATTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAA--------------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	divar_563W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTTGTTAT-----------------T-TTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	caldiv_ES_600Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTT---AT-----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cyncity_468Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAATTG--TTTTCTTT-ACT-TGGT---TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCATTTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	silvcty_285W       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Chir_274W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GA-TAA--TTTTGCTATCAATTTTTTTTT-----TTTTTTTTAGGTATTGGAAC-GTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGGATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Yec_531X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AA??TT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTT--------TTTTTTTTAGGTATTGGTACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_LS_659X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-AT-CTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_Teq_661Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAGGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-ATACTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fort_290Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCC-ATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAGC-TGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTTCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TCTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	aztec_218W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cffest_517Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGGCTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Heuco_502Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACATTTGCTTTAATT-AA-CTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Bis_390Z     TACATTAAGAAGATTGGTTACAA-CCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAA-ACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAAC---GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	zebra_442W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCCAAGAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGTT-TC----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tlax_674X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAA-ACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCA????????????????????????????????????????????--????????????????????????T---------CTTTTTTTAGGTATTGGAACAGTCCCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Pach_652W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACTTGAAATTTG--TTTTCTTT-GCT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTAATT-AAACTT--AATAACG--GAGTAA--TTTTGCTATCAATTTTTTTATTTATTTTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Cat_167Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Swiss_682Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCACTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	mexic_496Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACC-GTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carp_LS_670Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	boreal_130Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCT------AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coec_96Z           TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT-----AACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cusp_550Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coecgrp_Mag_580Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TGCTTAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pyr_10Z            TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAATA [...]
+
+	ball_383X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAG-CCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAA-CTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTT-----AAACTT------ACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCC-GGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfanep_576Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGATG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_LB_557Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_ITT_314Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTAT-AATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ammo_556Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACC-GAAG------TTTTCTTT-A-T-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpyrr_578X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T-CTCAA-GTCTTCTAACAACAATTGCTTTTATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	brunn_543X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAA-ATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCT????????????????????????????????????????????????????????????????????????????????--?????????????????????????????????????TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	schlin_160X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAA-AAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG????????????????????????????????????????????????????????????????????????--????????????????????????-----------TCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GG-ATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+
+;
+
+
+		BLOCKID WM1148b0539570;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "03-gcContentBirdsEye.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Sand_S127W,
+		2 Papacheus_093X,
+		3 Pshoshoensis_430Z,
+		4 Plongimanus_510Z,
+		5 ustul_RailX_211Z,
+		6 ustul_Mar_551Z,
+		7 cfsign_AV_570Z,
+		8 signat_684Z,
+		9 amicus_387Z,
+		10 alachua_527X,
+		11 cognatus_294W,
+		12 peckhami_382X,
+		13 elegans_213Z,
+		14 conjun_179AX,
+		15 geron_60Z,
+		16 doroth_LS_621Z,
+		17 huast_Chp_623X,
+		18 cfparat_88W,
+		19 venat_119Z,
+		20 carolin_134X,
+		21 cocker_108Z,
+		22 splend_525Z,
+		23 ocala_612Z,
+		24 pugill_459Z,
+		25 hallini_37Z,
+		26 cambrid_443Z,
+		27 fall_TX_288Z,
+		28 fallax_Chp_647X,
+		29 fallax_WComp_648W,
+		30 oregon_05Z,
+		31 icenog_196Z,
+		32 taras_643Z,
+		33 cftaras_554Z,
+		34 texanus_494X,
+		35 altan_AZ_124Z,
+		36 altan_Chih_325Z,
+		37 altan_Oax_645W,
+		38 cfsugill_Nay_281X,
+		39 cfpoch_Cham_639W,
+		40 cfpoch_LG_638W,
+		41 cfpoch_LY_608Z,
+		42 yucun_636Z,
+		43 banksi_104X,
+		44 amer_WM_316W,
+		45 amer_DG_345X,
+		46 bulb_Long_536Z,
+		47 waughi_129W,
+		48 cfsans_349W,
+		49 sans_368W,
+		50 kubai_540W,
+		51 tars_KR_377Z,
+		52 tars_Baja_591Z,
+		53 must_BRB_365X,
+		54 ophrys_SL_352X,
+		55 tuber_WP_464X,
+		56 kawini_592X,
+		57 notial_471X,
+		58 jucun_395Z,
+		59 calcalc_524Z,
+		60 virid_470X,
+		61 calmadd_16Z,
+		62 cfcalc_546W,
+		63 trim_559X,
+		64 orbus_27Z,
+		65 morat_485Z,
+		66 cfmor_ET_611W,
+		67 cfmor_LY_667W,
+		68 cfmor_Cham_662Z,
+		69 divar_563W,
+		70 caldiv_ES_600Z,
+		71 cyncity_468Z,
+		72 silvcty_285W,
+		73 doss_Chir_274W,
+		74 doss_Yec_531X,
+		75 veliv_LS_659X,
+		76 veliv_Teq_661Z,
+		77 fort_290Z,
+		78 aztec_218W,
+		79 cffest_517Z,
+		80 klaus_Heuco_502Z,
+		81 klaus_Bis_390Z,
+		82 zebra_442W,
+		83 tlax_674X,
+		84 virg_Pach_652W,
+		85 virg_Cat_167Z,
+		86 virg_Swiss_682Z,
+		87 mexic_496Z,
+		88 carp_LS_670Z,
+		89 boreal_130Z,
+		90 coec_96Z,
+		91 cusp_550Z,
+		92 coecgrp_Mag_580Z,
+		93 pyr_10Z,
+		94 ball_383X,
+		95 cfanep_576Z,
+		96 anep_LB_557Z,
+		97 anep_ITT_314Z,
+		98 ammo_556Z,
+		99 cfpyrr_578X,
+		100 brunn_543X,
+		101 schlin_160X;
+	TREE Griswold = (1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,( [...]
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL introns COLOR = (RGB 0.88627451 0.00392157 0.28627451) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET * UNTITLED   =   245 -  391 574 -  665;
+	CHARSET introns   =   245 -  391 574 -  665;
+	CHARSET exons   =   1 -  244 392 -  573 666 -  716;
+
+	CHARPARTITION * UNTITLED  =  introns :  245 -  391 574 -  665;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  716;
+
+	EXSET * UNTITLED  =  245 -  391 574 -  665;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = '1. special character: GC bias for taxon^n^n2. *** number for character: GC bias chart^n^n3. Parsimony steps^n^n4. Gaps';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  716;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  716;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5362004184182154199 WM1148b0538fb3;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5453088708553656046 WM1148b0539570;
+			checksum 0 2175300760 WM1148b0539570;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 392 455;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5453088708553656046 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 913 488;
+					setLocation 459 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 15;
+				endTell;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 3;
+					toggleBirdsEye on;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03a-cytochromeB.nex';
+			setPrevFileName '02-gcContentMatrix.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 392 438;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In this "bird''s eye" view of the data matrix, the columns are made very narrow and the ^nstate names are suppressed.  The moving window for the GC bias coloring is 15 bases.';
+				setTitle GC_bias;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/03a-cytochromeB.nex b/Resources/examples/Molecular/03a-cytochromeB.nex
new file mode 100755
index 0000000..d906198
--- /dev/null
+++ b/Resources/examples/Molecular/03a-cytochromeB.nex
@@ -0,0 +1,387 @@
+#NEXUS
+[written Sat Jun 07 12:29:24 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=46;
+	TAXLABELS
+		Lamprey Alligator crow chicken ostrich Chrysem Pelomed Blue_Whale Fin_whale Hippo Pig sheep cow white_rhino Black_Rhino donkey horse dog Halicho seal_vitulina cat gibbon Man baboon Myoxus Rat mouse possum Kangaroo platypus Frog lung_fish Polypterus Carassi carp trout Salmon smooth_dog_fish Scyliorhinus Spiny_dog_fish Skate amphioxus p_urchin S_urchin Fly Mosquito 
+	;
+	BLOCKID WM1148b79af636;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03a-cytochromeB.nex"';
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	MATRIX
+	Lamprey          -SHQPSIIRKTHPLLSLGNSMLVDLPSPANISAWWNFGSLLSLCLILQIITGLILAMHYTANTELAFSSVMHICRDVNNGWLMRNLHANGASMFFICIYAHIGRGIYYGSYLYKETWNVGVILFALTAATAFVGYVLPWGQMSFWGATVITNLISAMPYVGNDIVVWLWGGFSVSNATLTRFFTFHFILPFILAAMTMIHIMFLHQTGSSNPMGINSNLDKIQFHPYFSFKDILGFVILLGILFMISLLAPNALGEPDNFIYANPLSTPPHIKPEWYFLFAYAILRSVPNKLGGVVALAAAIMILLIIPFTHTSKQRGMQFRPLAQITFWILIADLALLTWLGGEPAEYPFILMTQIASTVYFMIFILVFPILGYLENKMLL
+
+	Alligator        ---MTHQLRKSHPIIKLINRSLIDLPTPSNISAWWNFGSLLGLTLLIQILTGFFLMMHFSSSDTLAFSSVSYTSREVWFGWLIRNLHTNGASLFFMFIFLHIGRGLYYTSYLHESTWNIGVIMLLLLMATAFMGYVLPWGQMSFWGATVITNLLSATPYVGSTVVPWIWGGPSVDNATLTRFTALHFLLPFALLASLITHLIFLHERGSFNPLGISPNADKIPFHPYFTMKDALGAALAASSLLILALYLPALLGDPENFTPANSMITPTHIKPEWYFLFAYAILRSIPNKLGGVLAMFSSILVLFLMPALHTAKQQPMSMRPMSQLLFWALTLDFLLLTWIGGQPVNPPYILIGQTASLFYFIIILILMPMAGLLENKMVE
+
+	crow             ---MGLNLRKNHPLLKIINNSLIDLPTPSNISAWWNFGSLLGLCLIMQIITGLLLAMHYTADTSLAFASVAHMCRDVQFGWLIRNLHANGASFFFICIYLHIGRGFYYGSYLNKETWNIGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWLWGGFSVDNPTLTRFFAFHFLLPFVIAGLTLVHLTFLHETGSNNPLGIPSDCDKIPFHPYYSIKDLLGFALMLIPLITLALFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLVLFLIPLLHVSKQRSMTFRPLSQILFWTLVADLLILTWVGSQPVEHPFIIIGQLASFAYFAIILILFPVVSALENKILK
+
+	chicken          ---MAPNIRKSHPLLKMINNSLIDLPAPSNISAWWNFGSLLAVCLMTQILTGLLLAMHYTADTSLAFSSVAHTCRNVQYGWLIRNLHANGASFFFICIFLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGHTLVEWAWGGFSVDNPTLTRFFALHFLLPFAIAGITIIHLTFLHESGSNNPLGISSDSDKIPFHPYYSFKDILGLTLMLTPFLTLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPFLHKSKQRTMTFRPLSQTLFWLLVANLLILTWIGSQPVEHPFIIIGQMASLSYFTILLILFPTIGTLENKMLN
+
+	ostrich          ---MAPNIRKSHPLLKIINNSLIDLPSPSNISAWWNFGSLLGICLITQILTGLLLAMHYTADTTLAFSSVAHTCRNVQYGWFIRNLHANGASFFFICIYLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWAWGGFSVDNPTLTRFFALHFLLPFVIAGITLVHLTFLHESGSNNPLGIISHCDKIPFHPYFSLKDILGFTLMFIPLLSLAFFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPLLHKSKQRSMTFRPLSQLLFWFLVANLLILTWIGSQPVEHPFIIIGQVASFTYFLILLVLFPAIAALENKMI-
+
+	Chrysem          ---MTMNHRKTHPLTKIINNSFIDLPSPSNISAWWNFGSLLGTCLILQTITGIFLAMHYSPDISLAFSSVAHITRDVQYGWLIRNMHANGASLFFMCIYLHIGRGLYYGSYLYKETWNTGIILLLLTMATAFMGYVLPWGQMSFWGATVITNLLSAIPFIGNTLVQWIWGGFSVDNATLTRFFTLHFLLPFTIMGLTMVHLLFLHETGSNNPTGLNSNTDKIPFHPYFSYKDLLGVILMLTLLLTLTLFSPNLLGDPDNFTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLFLMPALHTSKQRTTQFRPLTQTLFWSFIANLLVLTWIGGQPVENPFITIGQVASILYFSTLLILIPIAGVIENKML-
+
+	Pelomed          ---MGTLHLKQNPLLKITNKSLINLPSPSNISAWWNFGSLLGMCLILQITTGIFLAMHYTPNITTAFSSVAHITRDVQYGWLLRGLHANGASIFFICLYFHIGRGIYYGSFLNKKTWYTGIMLLFLTMATAFMGYILPWGQMSFWGATVITNLLSAIPYMGTNLVQWIWGGFSVDNATLTRFFTLHFLTPFIISSLTTIHLLLLHEKGSNNPTGLNSNPDKIPFHPYFSYKDLLGVNLLMIGLLTLTLFLPNLLTDPENFTPANPLSTPKHIKPEWYFLFAYAILRSIPNKLGGVLALLSSVTILFIMPTLHTSKQRSATFRPFTQILFWSPTADLVILTWIGAQPVEDPFIMIGQTASVFYFTLILLLIPLAAILENKLLD
+
+	Blue_Whale       ----MTNIRKTHPLMKIINDAFIDLPTPSNISSWWNFGSLLGLCLIVQILTGLFLAMHYTPDTMTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLYAHMGRGLYYGSHAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYYTIKDILGALLLILTLLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLALIPMLHTSKQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYVIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Fin_whale        ----MTNIRKTHPLMKIVNDAFVDLPTPSNISSWWNFGSLLGLCLIMQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYAHMGRGLYYGSYAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYHTIKDILGALLLILILLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILILAFIPMLHTSNQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYMIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Hippo            ----MTNIRKSHPLMKIINDAFVDLPAPSNISSWWNFGSLLGVCLILQILTGLFLAMHYTPDTLTAFSSVTHICRDVNYGWVIRYMHANGASIFFICLFTHVGRGLYYGSHTFLETWNIGVILLLTTMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFVITALAIVHLLFLHETGSNNPTGIPSNADKIPFHPYYTIKDILGILLLMTTLLTLTLFAPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALALSILILALIPMLHTSKQRSLMFRPLSQCLFWALIADLLTLTWIGGQPVEHPFIIIGQVASILYFLLILVLMPVAGIIENKLLK
+
+	Pig              ----MTNIRKSHPLMKIINNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLFIHVGRGLYYGSYMFLETWNIGVVLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIITALAAVHLLFLHETGSNNPTGISSDMDKIPFHPYYTIKDILGALFMMLILLILVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILMPMLHTSKQRGMMFRPLSQCLFWMLVADLITLTWIGGQPVEHPFIIIGQLASILYFLIILVLMPITSIIENNLLK
+
+	sheep            ----MINIRKTHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFMHVGRGLYYGSYTFLETWNIGVILLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFIFPFIIAALAMVHLLFLHETGSNNPTGIPSDTDKIPFHPYYTIKDILGAILLILILMLLVLFTPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILVLVIMPLLHTSKQRSMMFRPISQCMFWILVADLLTLTWIGGQPVEHPYIIIGQLASIMYFLIILVMMPVASIIENNLLK
+
+	cow              ----MTNIRKSHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLYMHVGRGLYYGSYTFLETWNIGVILLLTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMAIAMVHLLFLHETGSNNPTGISSDVDKIPFHPYYTIKDILGALLLILALMLLVLFAPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILALIPLLHTSKQRSMMFRPLSQCLFWALVADLLTLTWIGGQPVEHPYITIGQLASVLYFLLILVLMPTAGTIENKLLK
+
+	white_rhino      ----MTNIRKSHPLIKIINHSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTPDTMTAFSSVAHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGIYYGSYTFLETWNIGVILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGILLLILALLALVLFSPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILTLLIIPFLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFTLILVLMPLAGIIENNLLK
+
+	Black_Rhino      ----MTNIRKSHPLVKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWMIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGALLLILVLLILVLFFPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILLLIPYLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFSLILVLMPLAGIIENNLLK
+
+	donkey           ----MTNIRKSHPLIKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVIVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLVLLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	horse            ----MTNIRKSHPLIKIINHSFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVVVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLILLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	dog              ----MTNIRKTHPLAKIVNNSFIDLPAPSNISAWWNFGSLLGVCLILQILTGLFLAMHYTSDTATAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFLHVGRGLYYGSYVFMETWNIGIVLLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAMVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGALLLLLILMSLVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAFIPLLHTSKQRSMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFIIIGQVASILYFTILLILMPTVSVIENNLLK
+
+	Halicho          ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTIMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGFSVDKATLTGFFAFHFILPFVVLALAAVHLLFLHETGSNNPSGIMPDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILILAIVPLLHTSKQRGMMFRPISQCLFWLLVADLLTLTWIGGQPVEHPYITIGQLASILYFMILLVLMPIASIIENNILK
+
+	seal_vitulina    ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYVGTDLVQWIWGGFSVDKATLTRFFAFHFILPFVVLALDAVHLLFLHETGSNNPSGIMSDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPPNPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIMPLLHTSKQRGMMFRPISQCLFWFLVADLLTLTWIGGQPVEHPYITVGQLASILYFTILLVLMPIASIIENNILK
+
+	cat              ----MTNIRKSHPLIKIINHSFIDLPAPSNISAWWNFGSLLGVCLTLQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGMYYGSYTFSETWNIGIMLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTELVEWIWGGFSVDKATLTRFFGFHFILPFIISALAGVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGLLVLVLTLMLLVLFSPDLLGDPDNYIPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIIPILHTSKQRGMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFITIGQLASILYFSTLLILMPISGIIENRLLK
+
+	gibbon           ----MTPLRKTNPLMKLINHSLIDLPAPSNISMWWNFGSLLGACLILQIITGLFLAMHYTPDASTAFSSVAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYLETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTDLVQWVWGGYSVDNATLTRFFTFHFILPFIITALAALHLLFLHETGSNNPLGISSQPDKIAFHPYYTIKDILGLFLLLLMLMSLVLFSPDLLGDPSNYTQANPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALLLSILILAMIPALHTAKQQSMMFRPLSQLTYWLLVMNLLILTWIGGQPVSYPFITIGQVASALYFTTILVLMPAASLIENKMLK
+
+	Man              ----MTPMRKINPLMKLINHSFIDLPTPSNISAWWNFGSLLGACLILQITTGLFLAMHYSPDASTAFSSIAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYSETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGYSVDSPTLTRFFTFHFILPFIIATLAALHLLFLHETGSNNPLGITSHSDKITFHPYYTIKDTLGLLLFLLSLMTLTLFSPDLLGDPDNYTLANPLNTPPHIKPEWYFLFAYTILRSVPNKLGGVLALLLSILILAMIPILHMSKQQSMMFRPLSQSLYWLLAADLLILTWIGGQPVSYPFTIIGQVASVLYFTTILILMPTISLIENKMLK
+
+	baboon           ----MTPMRKSNPIMKMINHSFIDLPTPSNISIWWNFGSLLATCLILQIITGLFLAMHYSPDTSSAFSSIAHITRDVNYGWTIRYLHANGASMLFICLFLHVGRGLYYGSYLLLKTWNIGIMLLLMTMTTAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTNLVQWVWGGPAIDNPTLMRFFTLHFILPFGIVALTIVHLLFLHETGSNNPCGISSDPDKITFHPYYTTKDILGVAPLLLALMTLTLFSPDLLNDPDNYTPADPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALFLSILILAAIPMLHKSKQQSMMFRPLSQFLFWLLATTLLTLTWIGSQPVIQPLTTIGQVASMVYFLTTLVLMPLAAQVENNLLK
+
+	Myoxus           ----MTIIRKSHPLIKIINHSFIDLPTPSNISAWWIFGSLLGACLGIQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGMYYGSYMFIETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALVMVHLLFLHETGSNNPSGLNSDTDKIPFHPYYTIKDILGLLLLIFLLMTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAILPVLQFSKQRSMMFRPLSQCPFWILTADLFTLTWIGGQPVEHPFIIIGQLASILYFSIILFFLPTFSLLENKLLK
+
+	Rat              ----MTNIRKSHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYLQANGASMFFICLFLHVGRGLYYGSYTFLETWNIGIILLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDLLGVFMLLLFLMTLV--FPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVVALILSILILAFLPFLHTSKQRSLTFRPITQILYWILVANLLVLTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIVEDKMLK
+
+	mouse            ----MTNMRKTHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQIITGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGLYYGSYTFMETWNIGVLLLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDILGILIMFLILMTLVLFFPDMLGDPDNYMPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALMPFLHTSKQRSLMFRPITQILYWILVANLLILTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIIEDKMLK
+
+	possum           ----MTNIRKTHPLMKIINDSFIDLPTPSNISAWWNFGSLLGVCLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNIHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGSTLVEWIWGGFSVDKATLTRFFAFHFILPFIILAMVVVHLLFLHETGSSNPTGLDPNSDKIPFHPYYTMKDILGLFLMIIILLSLAMFSPDLLGDPDNFTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILVLLIIPMLHTSTQRSMAFRPISQTLFWMLTANLIILTWIGGQPVEQPYITIGQWASISYFTIIIILMPLAGMLENYMLK
+
+	Kangaroo         ----MTNLRKSHPLIKIVNHSFIDLPAPSNISAWWNFGSLLGACLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNLHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYVGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVLVHLLFLHETGSNNPSGINPDSDKIPFHPYYTIKDALGLMLMLFILLMLALFSPDMLGDPDNFSPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILILLIIPLLHTSKQRSLMFRPISQTLFWILTANLITLTWIGGQPVEQPFIIIGQLASISYFLLIIILMPLAGLFENYMLE
+
+	platypus         ----MNNLRKTHPLIKIVNHSFIDLPTPSNISSWWNFGSLLGLCLIIQILTGLFLAMHYTSDTSTAFSSVAHICRDVNYGWLIRYMHANGASLFFMCIFLHIGRGLYYGSYTQTETWNIGVVLLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFVIAALAVIHLLFLHETGSNNPSGLNSDPDKIPFHPYYSVKDLVGFFMTILVLLTLVLFTPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILVPLLHTSYQRGLAFRPLTQMLFWILVTDLLTLTWIGGQPVEQPFIIIGQLASILYFLLITTLIPLTGLLENDLLK
+
+	Frog             --LMAPNIRKSHPLIKIINNSFIDLPTPSNISSLWNFGSLLGVCLIAQIITGLFLAMHYTADTSMAFSSVAHICFDVNYGLLIRNLHANGLSFFFICIYLHIGRGLYYGSFLYKETWNIGVILLFLVMATAFVGYVLPWGQMSFWGATVITNLLSAKPYIGNVLVQWSLGGFSVDNATLTRFFAFHFLLPFIIAGASILHLLFLHETGSTNPTGLNSDPDKVPFHPYFSYKDLLGFLIMLTALTLLAMFSPNLLGDPDNFTPANPLITPPHIKPEWYFLFAYAILRSMN-KLGGVLALVLSILILALMPLLHTSKQRSLMFRPFTQIMFWALVADTLILTWIGGQPVEDPYTMIGQLASVIYFSIFIIMFPLMGWVENKLLN
+
+	lung_fish        ---MATNIRKTHPLLKIVNNSLIDLPTPSNISAWWNFGSLLGFCLITQILTGLFLAMHYTADTSTAFSSIAHIARDVNYGWLLRNIHANGASMFFICIYIHIGRGIYYGSFLYTETWNIGVVLFLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYLGDTLVQWIWGGFSVDNATLTRFFAFHFLLPFIISAMTAAHFLFLHETGSNNPTGLNSNLDKISFHPYFTMKDLLGFLMLASFLCLLALFSPNLLGDPENFTPANPLVTPTHIKPEWYFLFAYAILRSIPNKLGGVLALMASILILFIIPFLHRAKQRTMSYRPLSQFMFWLLTADMLILTWIGGQPVEHPFILIGQIASATYFLLFLLLFPLITSLENKLLY
+
+	Polypterus       ----MAIIRKTHPLAKIINSAFIDLPAPSNISSWWNMGSLLGLCLIAQIITGLFLAMHYVSDINSAFSSVAHICRDVNYGWLIRNFHANGASLFFICIYLHIARGLYYGSYLYTETWNMGVILLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAIPYIGDTLVQWIWGGFSVDKPTLTRFFAFHFILPFAIAAASLVHIVFLHETGSNNPVGINSDADQIPFHPYFTFKDLLGFIILLLIIIMLALLSPNLLNDPGNFTPANPLITPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPLLHTSKIRSATFRPLFKITLWILAADVLILTWIGGQPVEDPYIIIGQAASILYFLIFLVLMPLSGWLENKMLN
+
+	Carassi          ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFIIAAATVIHLLFLHETGSNNPIGLNSDADKISFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLVLFPLAGWLENKALK
+
+	carp             ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNVHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFVIAAATIIHLLFLHETGSNNPIGLNSDADKVSFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLIFMPLAGWLENKALK
+
+	trout            ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWALVADMLILTWIGGMPVEHPFIIIGQVASVIYFTIFLVLSPLAGWAEIKALQ
+
+	Salmon           ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWTLVADMLILTWIGGMPVEHPFIIIGQIASVIYFTIFLVLAPLAGWAENKALE
+
+	smooth_dog_fish  ---MATNIRKTHPLLKIMNHALVDLPAPSNISLWWNFGSLMGLCLLIQILTGLFLAMHYTADISMAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYLHIARGLYYGSYLNKETWDIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNMLVQWIWGGFSVDNATLTRFFAFHFLLPFLIMALSIIHLLFLHESGSNNPLGINSDADKVSFHPYFSYKDLLGFFVMIFLLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKQRSIIFRPLTQIFFWVLVANSIILTWIGGQPVEQPFIMVGQIASISYFALFLIIMPFISWCENKILS
+
+	Scyliorhinus     ---MATNIRKTHPLLKIVNHALIDLPAPSNISVWWNFGSLLGLCLIMQIITGLFLAMHYTADISMAFSSVIHISRDVNYGWLMRNIHAYGASFFFICIYLHIARGLYYGSYLNKEAWNIGVVLLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNLLVQWIWGGFSVDNATLTRFFAFHFLLPFLILALSVIHILFLHETGANNPMGINSNTDKISFHPYFSYKDLFGFLIVITLLATLALFMPNLLGDAENFIPANPLVTPLHIQPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKLRSNIFRPLTQIFFWSLVTNAIILTWIGGQPVEQPFIMVGQIASVAYFSLFLFVIPITSWCENKFLS
+
+	Spiny_dog_fish   ---MTTNIRKTHPLIKIVNHALVDLPSPSNISIWWNFGSLLGLCLIIQILTGLFLAMHYTADISTAFSSVVHICRDVNYGWLIRNIHANGASLFFICVYLHIARGLYYGSYLFKEAWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGDMLVQWIWGGFSIDNATLTRFFAFHFLLPFLIVGLTLIHLLFLHETGSNNPMGLNSDMDKISFHPYFSYKDLLGFFLMIILLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILMLIPMLHTSKQRSNIFRPMTQFLFWTLVANAIILTWIGGQPVEQPFILVGQIASVTYFSLFLIIIPLTGWWENKMLN
+
+	Skate            ---MTTNIRKTHPLFKIINSSLIDLPTPVNISIWWNYGSLLGLCLIIQILTGLFLAMHYTPDIASAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYIHMARGFYYGSYLNKETWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNILVEWIWGGFSVDNATLTRFFAFHFLFPFLIVALTLLHLLFLHEMGSNNPTGLNSNTDKIPFHPYFSYKDLLGFFILGLLLTLLALFTPNLLGDTENFIPADPLLTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPMLHTSKQRSATFRPITQILFWTLLTNTIILTWIGGQPVEQPFIIIGQIASVIYFLLFLILLPLAGWWENKILN
+
+	amphioxus        ---MSGPLRKHHPLLKVVNHSVIDLPVPSNISVMWNFGSLLGLCLVSQILTGLFLAMHYTADVNLAFSSVAHICRDVNYGWLLRNLHANGASFMFICLYMHIGRGLYYGSYFYRETWNIGVMLLVLTMATAFLGYVLPWGQMSFWGATVITNLFSAIPYLGPDLVQWLWGGFSVDNATLTRFFAFHFFLPFMIAGLSVVHLLFLHQTGANNPTGLAGDVDKVPFHAYFSYKDVVGFVVLLAGLVFIALFSPNLLTDPENYIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVVALAMSIVVLFFMPFVHSSRQTSHNFRPLAQVLFWLMVVNVLLLTWLGGQPVEYPYIFLGQAASVIYFVNILLLIPIVGYVENKLL-
+
+	p_urchin         ---MLGPLRKEHPIFRILKSTFVDLPLPSKLSIWWKFGSLLGLCLMTQILTGLFLAMHYTADISLAFSSASHMCRDVNYGWLLRKVHAKGASLFFICMYCHMGRGLYYGGSNKMETWKVGVILFLVTVLTAFVGYVLVWGRMSFWAATVIANLVTAVPCVGTTIVQWLWGGFSVDNATLTRFFAFHFLFPFIMAALAMIDLVFLHNSGANNPVGLKSNYDKAPFHIYYTTKDTVGFMALIAALFVLALLFPCALKDPEKFIPANPLSHPPHMQPEWYFLFAYAILRSIPNKLGGVMALVAAMLVLFLMPLLKTSKKESNSFRPLSQATFWMLVATFFVLTWMGSQPVEQPFVLMGQMASLLYFSLFMFGFPLVSSLEKKMMF
+
+	S_urchin         IKIMAAPLRKEHPIFRILKSTFVDLPLPSNLSIWWNSGSLLGLCLVVQMLTGMFLAMHYTADITLAFSSVMHILRDVNYGWFLRYVHAKGVSLFFICMYCHMGRGLYYGSYKKIETWKVGVILFLVTILTAFMGYVLVWGQMSFWAATVITNLVSAIPYMGTIMVQWLWGGFSVDKATLTRFFPFHFLFPFMMAALAVMHLVFLHNSGANNPFAFKSNYDKAPFHIYFTTKDTVGFILLVAALFSLALLFPGALKDPEKFIPANPLVTPPHIQPEWYFLFAYAILRSIPNKLGGVIALVAAMLVLFLMPLLNTSKKESNSFRPLSQAAFWLLVAHLFMLTWMGSQPVEYPYVLLGQVASVLYFSLFMFGFPMVSSMENKIMF
+
+	Fly              ---MHKPLRNSHPLFKIANNALVDLPAPINISSWWNFGSLLGLCLIIQILTGLFLAMHYTADVNLAFYSVNHICRDVNYGWLLRTLHANGASFFFICIYLHIGRGIYYGSYLFTPTWLVGVIILFLVMGTAFMGYVLPWGQMSFWGATVITNLLSAIPYLGMDLVQWLWGGFAVDNATLTRFFTFHFILPFIVLAMTMIHLLFLHQTGSNNPIGLNSNIDKIPFHPYFTFKDIVGFIVMIFILISLVLISPNLLGDPDNFIPANPLVTPAHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILMILPFYNLSKFRGIQFYPINQILFWSMLVTVILLTWIGARPVEEPYVLIGQILTIIYFLYYLINPLVTKWWDNLLN-
+
+	Mosquito         ---MFKPIRKTHPLISIANNALVDLPAPSNISAWWNFGSLLGLCLMLQILTGLFLAMHYAADIETAFNSVNHICRDVNNGWFLRICHANGASFFFACLFIHVGRGVYYESYLYHMTWNTGVIILFLTMATGFLGYVLPWGQMSFWGATVITNLLSAVPYLGMDLVQWIWGGFAVDNATLTRFFTFHFIFPFIILALMMIHLLFLHQTGSNNPLGLNSNVDKIPFHPYFIYKDIFGFIVFLWILVTFIWKFNYLLMDPENFIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILLILPFTHSSKFRGLQFYPLNQILFWNMVIVASLLTWIGARPVEDPYILTGQILTVLYFSYFIINPLLAKFWDKLLN-
+
+
+;
+
+		BLOCKID WM1148b79af8a0;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "03a-cytochromeB.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Lamprey,
+		2 Alligator,
+		3 crow,
+		4 chicken,
+		5 ostrich,
+		6 Chrysem,
+		7 Pelomed,
+		8 Blue_Whale,
+		9 Fin_whale,
+		10 Hippo,
+		11 Pig,
+		12 sheep,
+		13 cow,
+		14 white_rhino,
+		15 Black_Rhino,
+		16 donkey,
+		17 horse,
+		18 dog,
+		19 Halicho,
+		20 seal_vitulina,
+		21 cat,
+		22 gibbon,
+		23 Man,
+		24 baboon,
+		25 Myoxus,
+		26 Rat,
+		27 mouse,
+		28 possum,
+		29 Kangaroo,
+		30 platypus,
+		31 Frog,
+		32 lung_fish,
+		33 Polypterus,
+		34 Carassi,
+		35 carp,
+		36 trout,
+		37 Salmon,
+		38 smooth_dog_fish,
+		39 Scyliorhinus,
+		40 Spiny_dog_fish,
+		41 Skate,
+		42 amphioxus,
+		43 p_urchin,
+		44 S_urchin,
+		45 Fly,
+		46 Mosquito;
+	TREE true = ((((1,((((((((2,(3,(4,5))),(6,7)),((((((((((8,9),10),11),(12,13)),((14,15),(16,17))),((18,(19,20)),21)),((22,23),24)),(25,(26,27))),(28,29)),30)),31),32),33),((34,35),(36,37))),(((38,39),40),41))),42),(43,44)),(45,46));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  382;
+
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  84;
+	LastModified -1170153337;
+	FileSettings treewindow '0' '0' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'              Geneva '9' '100' '1'              all;
+	EditorPosition '46' '6' '691' '1083';
+	TreeWindowPosition '46' '6' '699' '1102';
+	ListWindow Characters closed Geneva '9' '50' '10' '273' '405'              000;
+	ListWindow Taxa closed Geneva '9' '50' '10' '273' '377'              100000;
+	ListWindow Trees closed Geneva '9' '50' '25' '129' '379';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '686' '1092';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Tree;
+	OtherSymbols & /              00 ? -;
+	Correlation '0' '0' '1000' '0' '0'              10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'              110000;
+	PrettyPrint 10;
+	TreeLegendPosition '662' '909' '64' '93';
+	EditorToolsPosition '579' '46' '115' '165';
+	TreeToolsPosition '584' '9' '126' '138';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'              1;
+	Calculations 0000001;
+	SummaryMode '0' '0'              0;
+	Charts  Geneva '9' (             normal )              0010;
+	NexusOptions '0' '0' '50'              001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (             normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'              1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'              1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'              1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'              0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'              1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'              Geneva '9' (             normal )              Geneva '10' (             normal )              Geneva '9' (             normal )              Geneva '9' (             normal )              Geneva '9' (             bold )              Geneva '9' (             normal )              Geneva '9' (             normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'              00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'              100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'              1010;
+	BothTools '1';
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =             unord PolyTcount =             MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  382;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  382;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5749286926902316461 WM1148b79af636;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7273041429729163753 WM1148b79af8a0;
+			checksum 0 4171134048 WM1148b79af8a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 368 451;
+			setLocation 12 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7273041429729163753 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1007 489;
+					setLocation 413 32;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.AminoAcidProperties.AminoAcidProperties;
+					tell It;
+						setProperty  #mesquite.molec.AAHydrophobicity.AAHydrophobicity;
+					endTell;
+					setWindowWidth 15;
+				endTell;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight on;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 [...]
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-gcContentTaxa.nex';
+			setPrevFileName '03-gcContentBirdsEye.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 368 434;
+					setLocation 12 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This matrix is of cytochrome B amino acid sequences.  In this case the coloring is amino acid hydrophobicity, with a moving window of 15 sites.';
+				setTitle Amino_Acid_hydrophobicity;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/04-gcContentTaxa.nex b/Resources/examples/Molecular/04-gcContentTaxa.nex
new file mode 100755
index 0000000..fe3d16d
--- /dev/null
+++ b/Resources/examples/Molecular/04-gcContentTaxa.nex
@@ -0,0 +1,664 @@
+#NEXUS
+[written Sat Jun 07 12:29:38 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=101;
+	TAXLABELS
+		Sand_S127W Papacheus_093X Pshoshoensis_430Z Plongimanus_510Z ustul_RailX_211Z ustul_Mar_551Z cfsign_AV_570Z signat_684Z amicus_387Z alachua_527X cognatus_294W peckhami_382X elegans_213Z conjun_179AX geron_60Z doroth_LS_621Z huast_Chp_623X cfparat_88W venat_119Z carolin_134X cocker_108Z splend_525Z ocala_612Z pugill_459Z hallini_37Z cambrid_443Z fall_TX_288Z fallax_Chp_647X fallax_WComp_648W oregon_05Z icenog_196Z taras_643Z cftaras_554Z texanus_494X altan_AZ_124Z altan_Chih_325Z altan_ [...]
+	;
+	BLOCKID WM1148b79e4d77;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "04-gcContentTaxa.nex"';
+	DIMENSIONS  NCHAR=716;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+CHARSTATELABELS 
+18 #17, 244 ex1., 245 Int1, 391 int1, 392 ex2., 573 ex2., 574 int2, 665 int2, 666 ex3. ; 
+	MATRIX
+	Sand_S127W         TACATTAAAAAGATTGGTTATAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAATATGGGATGGTACAAAGGTTGGTCCATTGAACGTAAAACCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-TGTGTT-ACCTTAATTTTTTTTTTCTAT--ACT-TGCAG-TAACTCTA-G---TCT---AACAGT-ACTTGAATT--AATTTG-AACAACT--GAGTA---TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTGGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACT [...]
+
+	Papacheus_093X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATGT-----TTTTTT-ACT-TGGAG--AACTCAA----TTTT---AACAA-----------------TAGAATAATT-T-TTTAACCTTTTTTTACTAA--------------CCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Pshoshoensis_430Z  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGAGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATAT-----TTTATT-----TCAAG--TACTTAA----TTTT---AACAATTACTTAAGTG-AAAAATTGAATAATT-TTTTTAACCTTTT-TTACCTA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Plongimanus_510Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATGT----TTTCTTT-ACT-TGGAA--TACT-AA----TTTT---AACAATTACTTAAATG-AACA-TTGGATAATT-TTTTTAACCTTTT-TTACCAA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_RailX_211Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGGAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT--------------AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_Mar_551Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTATTATTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	cfsign_AV_570Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	signat_684Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT------AATTACTT------AAACTT--AACAACT--GAGTATTATTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	amicus_387Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAGCGTAAAGGCAACAAGACTGAAGGGAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AACAATTACTT------TAACTT--AACAACT--GAGTATTATTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	alachua_527X       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAA-T--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cognatus_294W      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGG-GACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACA-TTACTTAAATT--AACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGG-ATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	peckhami_382X      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTC-TCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	elegans_213Z       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACC-ATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	conjun_179AX       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAG-ACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGA-AAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	geron_60Z          TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doroth_LS_621Z     TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	huast_Chp_623X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTAT-GAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGC-ATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAA--G--TTTTCTTT-ACT-TGGTA--TACACAA-GTCTTCT---AAC-ATTGCTTAAATT-AAACTT--GATAACT--GAGTAA--TTTTGCTGC-TACCTATAT-------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTT-AAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfparat_88W        TACATTAAAAAAATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCGA-GTCTTCT---AACAATTGCTTACATT-AAACTT-----------GAGTAA--TTTTACTA----TTTTTTTTTT----TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	venat_119Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCCTT-ACTCTAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACA--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carolin_134X       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTT-GAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCATT-ACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACT--AAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cocker_108Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TAGTG--TACTCAA-ATCTTCT---AACAATTGCTTGAATT-GAACAA--AATAAC----AGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	splend_525Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTCGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ocala_612Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTAG--TTTTCTTTTACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pugill_459Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTT---AACAATT-CTTGAATT-AAACT-TTAATAACT--GAGTAA--TTTTGCTGCCAA--------------TCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	hallini_37Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAACCTGAAATT------TTCTTT-ACT-TGGTG--TACTGAA-ATCTTCT---AACAATTGTTTTAATT-AAACTT--AATAACA--GAGTAA--TTTTGCTATAAAT-------------TTTGTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cambrid_443Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGAATT-AAACTATTAATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fall_TX_288Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACG-AAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_Chp_647X    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATCC-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_WComp_648W  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGGATT-TAACTTT-AATGACT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	oregon_05Z         TACATCAAGAAGATTGGTTACAATCCTGCAACAGTTCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	icenog_196Z        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTTTTCT---AACAATTGCTTGAATT-AAA----------TT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	taras_643Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCGTTTGTTCCAATTTCTGGGTGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TAC--------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cftaras_554Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGG-TGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGG-AAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACT-------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	texanus_494X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGG-TGGAATGGCGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCCCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ATT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACTCTGAGTAA--TTTTGTTACCAATC------------TTGTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_AZ_124Z      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATA-AAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Chih_325Z    TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAAT-TG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Oax_645W     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsugill_Nay_281X  TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGCTGAAGTTTG--TGTTCTTT-ACT-TGGTG--TATTAAA-GTCTTCT---AACAACTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTGAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_Cham_639W   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCAATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACA-TGGTG--TACTT---GTCTTCA---AACG-TTGCTTGATTT-AAACTT------------AGTAA--TTTTGCTACCAATCTTTTTTTTTTT-TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LG_638W     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTTTTT------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LY_608Z     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTT---------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	yucun_636Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAATTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCA----CTTCTTCTAACAATTGCTTGAATT-AAACTTT-AATAACA--GAGTTAA-TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	banksi_104X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCACCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTATGTCGAACT-----TTTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--GAATAA--TTTTGCTACCAATCT-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	amer_WM_316W       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTTTTTTTTTTTTTACT-TGGTG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATTAAAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	amer_DG_345X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTCGTTTTTTTA---ACT-TGGTG--TACTCAA-GTCTTCGAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTCGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	bulb_Long_536Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATT----------------AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	waughi_129W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTTTACT-TCGTG--TACTCAA-GTCTT-GAATTATAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsans_349W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTA--ACT-TGGAG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	sans_368W          TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTT--ACT-TGGTG--TACTCAA-GTCTT-GAATTAAAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kubai_540W         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATAAAACTTGCTTGAATT-AAACTTC--ATAACT--GAG-AA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_KR_377Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTAAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_Baja_591Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACAGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	must_BRB_365X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGGCCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT--TTTTC????????????????????????????????????????????????????????C--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ophrys_SL_352X     TACATTAAGAAGATTGGTTACAATCCTGC-ACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGA-CCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT??????????????????????????????????????????????????????????????????ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tuber_WP_464X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCC-CTCCAAGATGTATATAAGATTGGTGGTATGT-T---TTCTTAACCTGAAATTTG--TTT-CTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAAC?????????????????????????????--?????????TTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kawini_592X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGA-CCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAG-CCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTT-AATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	notial_471X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGT-CCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTCTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGCTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGATGTATATTAAA-CTC-TCT---AACAATTAATGGAATT-AAACTTC-AATAATT--GAATAA--TTTTGCTACCAATCTT----------TATTTTGAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTAAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	jucun_395Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TGTTCTTT-ACT-TGGTGTATATTAAA-GTCT------AACAATTGCTGGAATT-AAACTTT-AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calcalc_524Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTCCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTGTATATTA---GTCTTCT---AACAATTGCTGGAATT-AAACT---AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virid_470X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calmadd_16Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACAT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTAC-TTTGCTCCAGCTAACA [...]
+
+	cfcalc_546W        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAATAATTGCTTCAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	trim_559X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAATTTAAAC----AATAACT--TAG-AA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	orbus_27Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT----GTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAA-TTAAACTT--AATAACT--TAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCGGCTAACA [...]
+
+	morat_485Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCT-TTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAA-AATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	cfmor_ET_611W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_LY_667W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTTGATAAACCTCTTCGTTTGCCCCTGCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TTTTTTCTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_Cham_662Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATCACTTTAAATTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAA--------------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	divar_563W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTTGTTAT-----------------T-TTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	caldiv_ES_600Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTT---AT-----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cyncity_468Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAATTG--TTTTCTTT-ACT-TGGT---TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCATTTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	silvcty_285W       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Chir_274W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GA-TAA--TTTTGCTATCAATTTTTTTTT-----TTTTTTTTAGGTATTGGAAC-GTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGGATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Yec_531X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AA??TT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTT--------TTTTTTTTAGGTATTGGTACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_LS_659X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-AT-CTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_Teq_661Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAGGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-ATACTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fort_290Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCC-ATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAGC-TGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTTCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TCTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	aztec_218W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cffest_517Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGGCTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Heuco_502Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACATTTGCTTTAATT-AA-CTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Bis_390Z     TACATTAAGAAGATTGGTTACAA-CCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAA-ACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAAC---GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	zebra_442W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCCAAGAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGTT-TC----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tlax_674X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAA-ACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCA????????????????????????????????????????????--????????????????????????T---------CTTTTTTTAGGTATTGGAACAGTCCCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Pach_652W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACTTGAAATTTG--TTTTCTTT-GCT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTAATT-AAACTT--AATAACG--GAGTAA--TTTTGCTATCAATTTTTTTATTTATTTTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Cat_167Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Swiss_682Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCACTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	mexic_496Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACC-GTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carp_LS_670Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	boreal_130Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCT------AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coec_96Z           TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT-----AACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cusp_550Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coecgrp_Mag_580Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TGCTTAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pyr_10Z            TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAATA [...]
+
+	ball_383X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAG-CCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAA-CTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTT-----AAACTT------ACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCC-GGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfanep_576Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGATG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_LB_557Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_ITT_314Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTAT-AATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ammo_556Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACC-GAAG------TTTTCTTT-A-T-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpyrr_578X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T-CTCAA-GTCTTCTAACAACAATTGCTTTTATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	brunn_543X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAA-ATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCT????????????????????????????????????????????????????????????????????????????????--?????????????????????????????????????TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	schlin_160X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAA-AAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG????????????????????????????????????????????????????????????????????????--????????????????????????-----------TCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GG-ATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+
+;
+
+
+		BLOCKID WM1148b79e5240;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "04-gcContentTaxa.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Sand_S127W,
+		2 Papacheus_093X,
+		3 Pshoshoensis_430Z,
+		4 Plongimanus_510Z,
+		5 ustul_RailX_211Z,
+		6 ustul_Mar_551Z,
+		7 cfsign_AV_570Z,
+		8 signat_684Z,
+		9 amicus_387Z,
+		10 alachua_527X,
+		11 cognatus_294W,
+		12 peckhami_382X,
+		13 elegans_213Z,
+		14 conjun_179AX,
+		15 geron_60Z,
+		16 doroth_LS_621Z,
+		17 huast_Chp_623X,
+		18 cfparat_88W,
+		19 venat_119Z,
+		20 carolin_134X,
+		21 cocker_108Z,
+		22 splend_525Z,
+		23 ocala_612Z,
+		24 pugill_459Z,
+		25 hallini_37Z,
+		26 cambrid_443Z,
+		27 fall_TX_288Z,
+		28 fallax_Chp_647X,
+		29 fallax_WComp_648W,
+		30 oregon_05Z,
+		31 icenog_196Z,
+		32 taras_643Z,
+		33 cftaras_554Z,
+		34 texanus_494X,
+		35 altan_AZ_124Z,
+		36 altan_Chih_325Z,
+		37 altan_Oax_645W,
+		38 cfsugill_Nay_281X,
+		39 cfpoch_Cham_639W,
+		40 cfpoch_LG_638W,
+		41 cfpoch_LY_608Z,
+		42 yucun_636Z,
+		43 banksi_104X,
+		44 amer_WM_316W,
+		45 amer_DG_345X,
+		46 bulb_Long_536Z,
+		47 waughi_129W,
+		48 cfsans_349W,
+		49 sans_368W,
+		50 kubai_540W,
+		51 tars_KR_377Z,
+		52 tars_Baja_591Z,
+		53 must_BRB_365X,
+		54 ophrys_SL_352X,
+		55 tuber_WP_464X,
+		56 kawini_592X,
+		57 notial_471X,
+		58 jucun_395Z,
+		59 calcalc_524Z,
+		60 virid_470X,
+		61 calmadd_16Z,
+		62 cfcalc_546W,
+		63 trim_559X,
+		64 orbus_27Z,
+		65 morat_485Z,
+		66 cfmor_ET_611W,
+		67 cfmor_LY_667W,
+		68 cfmor_Cham_662Z,
+		69 divar_563W,
+		70 caldiv_ES_600Z,
+		71 cyncity_468Z,
+		72 silvcty_285W,
+		73 doss_Chir_274W,
+		74 doss_Yec_531X,
+		75 veliv_LS_659X,
+		76 veliv_Teq_661Z,
+		77 fort_290Z,
+		78 aztec_218W,
+		79 cffest_517Z,
+		80 klaus_Heuco_502Z,
+		81 klaus_Bis_390Z,
+		82 zebra_442W,
+		83 tlax_674X,
+		84 virg_Pach_652W,
+		85 virg_Cat_167Z,
+		86 virg_Swiss_682Z,
+		87 mexic_496Z,
+		88 carp_LS_670Z,
+		89 boreal_130Z,
+		90 coec_96Z,
+		91 cusp_550Z,
+		92 coecgrp_Mag_580Z,
+		93 pyr_10Z,
+		94 ball_383X,
+		95 cfanep_576Z,
+		96 anep_LB_557Z,
+		97 anep_ITT_314Z,
+		98 ammo_556Z,
+		99 cfpyrr_578X,
+		100 brunn_543X,
+		101 schlin_160X;
+	TREE Griswold = (1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,( [...]
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL introns COLOR = (RGB 0.88627451 0.00392157 0.28627451) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET * UNTITLED   =   245 -  391 574 -  665;
+	CHARSET introns   =   245 -  391 574 -  665;
+	CHARSET exons   =   1 -  244 392 -  573 666 -  716;
+
+	CHARPARTITION * UNTITLED  =  introns :  245 -  391 574 -  665;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  716;
+
+	EXSET * UNTITLED  = ;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = '1. special character: GC bias for taxon^n^n2. *** number for character: GC bias chart^n^n3. Parsimony steps^n^n4. Gaps';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  716;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  716;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5362004184182154199 WM1148b79e4d77;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5453088708553656046 WM1148b79e5240;
+			checksum 0 2175300760 WM1148b79e5240;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 571 276;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5362004184182154199  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 419.967566324406.1416342777910267728;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 734 575;
+					setLocation 558 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.ornamental.CircularTree.CircularTree;
+					tell It;
+						setEdgeWidth 4;
+						getEmployee #mesquite.ornamental.NodeLocsCircular.NodeLocsCircular;
+						tell It;
+							branchLengthsToggle off;
+							toggleScale on;
+						endTell;
+					endTell;
+					setBackground Light_Blue;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,((11 [...]
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 500 500;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.molec.TaxonGCBias.TaxonGCBias;
+							tell It;
+								getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+								tell It;
+									setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+									tell It;
+										setDataSet #5453088708553656046;
+									endTell;
+								endTell;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							tell It;
+								setDefaultModel 13;
+							endTell;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -319;
+					setLegendWidth 142;
+					setLegendHeight 302;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5453088708553656046 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 522 415;
+					setLocation 9 370;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.ColorByNumber.ColorByNumber;
+				tell It;
+					setNumberTask  #mesquite.molec.GCAsNumber.GCAsNumber;
+					setWindowWidth 1;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-gcContentTaxaExons.nex';
+			setPrevFileName '03a-cytochromeB.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 571 259;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'For the spider EF1-alpha data, GC Bias for each taxon is shown as a continuous character traced on the tree at right.  Note that some clades appear to be considerably more GC rich than others, which may lead to concerns about compositional bias influencing phylogenetic inference.';
+				setTitle GC_bias;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/05-gcContentTaxaExons.nex b/Resources/examples/Molecular/05-gcContentTaxaExons.nex
new file mode 100755
index 0000000..6da7ab7
--- /dev/null
+++ b/Resources/examples/Molecular/05-gcContentTaxaExons.nex
@@ -0,0 +1,581 @@
+#NEXUS
+[written Sat Jun 07 12:29:48 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=101;
+	TAXLABELS
+		Sand_S127W Papacheus_093X Pshoshoensis_430Z Plongimanus_510Z ustul_RailX_211Z ustul_Mar_551Z cfsign_AV_570Z signat_684Z amicus_387Z alachua_527X cognatus_294W peckhami_382X elegans_213Z conjun_179AX geron_60Z doroth_LS_621Z huast_Chp_623X cfparat_88W venat_119Z carolin_134X cocker_108Z splend_525Z ocala_612Z pugill_459Z hallini_37Z cambrid_443Z fall_TX_288Z fallax_Chp_647X fallax_WComp_648W oregon_05Z icenog_196Z taras_643Z cftaras_554Z texanus_494X altan_AZ_124Z altan_Chih_325Z altan_ [...]
+	;
+	BLOCKID WM1148b7a5a768;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "05-gcContentTaxaExons.nex"';
+	DIMENSIONS  NCHAR=716;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+CHARSTATELABELS 
+18 #17, 244 ex1., 245 Int1, 391 int1, 392 ex2., 573 ex2., 574 int2, 665 int2, 666 ex3. ; 
+	MATRIX
+	Sand_S127W         TACATTAAAAAGATTGGTTATAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAATATGGGATGGTACAAAGGTTGGTCCATTGAACGTAAAACCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-TGTGTT-ACCTTAATTTTTTTTTTCTAT--ACT-TGCAG-TAACTCTA-G---TCT---AACAGT-ACTTGAATT--AATTTG-AACAACT--GAGTA---TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTGGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACT [...]
+
+	Papacheus_093X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATGT-----TTTTTT-ACT-TGGAG--AACTCAA----TTTT---AACAA-----------------TAGAATAATT-T-TTTAACCTTTTTTTACTAA--------------CCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Pshoshoensis_430Z  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGAGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATAT-----TTTATT-----TCAAG--TACTTAA----TTTT---AACAATTACTTAAGTG-AAAAATTGAATAATT-TTTTTAACCTTTT-TTACCTA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	Plongimanus_510Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCTAGCACCAACATGGGATGGTACAAGGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCCAGACCTCTAGACAAACCTCTTCGTTTACCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATGT----TTTCTTT-ACT-TGGAA--TACT-AA----TTTT---AACAATTACTTAAATG-AACA-TTGGATAATT-TTTTTAACCTTTT-TTACCAA--------------TATTTTTAAGGTATTGGAACAGTACCTGTTGGTCGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_RailX_211Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGGAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT--------------AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ustul_Mar_551Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTTTATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTATTATTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	cfsign_AV_570Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AATAATTACTT------AAACTT--AACAACT--GAGTA---TTTCGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	signat_684Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TGGTG--TACTCAATG-CTTCT------AATTACTT------AAACTT--AACAACT--GAGTATTATTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	amicus_387Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAGCGTAAAGGCAACAAGACTGAAGGGAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAGGATGTATATAAAATTGGTGGTATGTATT-GCTCTTAACCTGAAATTT-----TTCTTT-GCT-TG-TG--TACTCAATG-CTTCT---AACAATTACTT------TAACTT--AACAACT--GAGTATTATTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCCCCAGCTAACA [...]
+
+	alachua_527X       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAA-T--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cognatus_294W      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGG-GACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACA-TTACTTAAATT--AACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGG-ATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	peckhami_382X      TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAAT-GGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTC-TCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	elegans_213Z       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGCTACC-ATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	conjun_179AX       TATATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAG-ACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGA-AAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATCGGTGGTATGTATT-GCTGTTAACCTGAAATTTGTTTATTC--T-ACT-TGATG--TACTCAA-GTCTTCT---AACAATTACTT------AAACTT--AACAACT--GAGTA---TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	geron_60Z          TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doroth_LS_621Z     TACATTAAGAAGATTGGTTACAATCCAGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT--G--TTTTCTTT-ACT-TGGTG--TACACAA-GTCTTCT---AACAATTG-----ATT-AAATTT--GATAACT--GAGTAA--TTTTGCTACCTATCTTTT--------TTCTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	huast_Chp_623X     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTAT-GAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGC-ATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAA--G--TTTTCTTT-ACT-TGGTA--TACACAA-GTCTTCT---AAC-ATTGCTTAAATT-AAACTT--GATAACT--GAGTAA--TTTTGCTGC-TACCTATAT-------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTT-AAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfparat_88W        TACATTAAAAAAATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCGA-GTCTTCT---AACAATTGCTTACATT-AAACTT-----------GAGTAA--TTTTACTA----TTTTTTTTTT----TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	venat_119Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCCTT-ACTCTAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACA--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carolin_134X       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTT-GAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCATT-ACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTG--AATAACT--AAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cocker_108Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TAGTG--TACTCAA-ATCTTCT---AACAATTGCTTGAATT-GAACAA--AATAAC----AGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	splend_525Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTCGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ocala_612Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAACCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTT--AATTAG--TTTTCTTTTACT-TAGTG--TACTCAA-GTCTTCT---AACAATTGCTTGAATT-GAACTA--AATAACT--GAGTAA--TTTTGCTACCAATCTTTC--------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pugill_459Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTT---AACAATT-CTTGAATT-AAACT-TTAATAACT--GAGTAA--TTTTGCTGCCAA--------------TCTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	hallini_37Z        TACATTAAAAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAACCTGAAATT------TTCTTT-ACT-TGGTG--TACTGAA-ATCTTCT---AACAATTGTTTTAATT-AAACTT--AATAACA--GAGTAA--TTTTGCTATAAAT-------------TTTGTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cambrid_443Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTGCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGAATT-AAACTATTAATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fall_TX_288Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACG-AAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-ACTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_Chp_647X    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-ATCTTTTA--AACAATTCCTTGGATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATCC-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fallax_WComp_648W  TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTGCAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTAAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GTCTTTTA--AACAATTCCTTGGATT-TAACTTT-AATGACT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	oregon_05Z         TACATCAAGAAGATTGGTTACAATCCTGCAACAGTTCCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	icenog_196Z        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCAA-GTTTTCT---AACAATTGCTTGAATT-AAA----------TT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	taras_643Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCGTTTGTTCCAATTTCTGGGTGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TAC--------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cftaras_554Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGG-TGGAATGGTGATAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGG-AAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTGGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AAGTTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACT-------TTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--AAGTAA--TTTTGCTACCAATC------------TTTCTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	texanus_494X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGG-TGGAATGGCGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCCCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ATT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACTCTGAGTAA--TTTTGTTACCAATC------------TTGTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_AZ_124Z      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATA-AAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Chih_325Z    TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAAT-TG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	altan_Oax_645W     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATTTGCTGTTAAGCTGAAATTTG--TGTTCTTT-ACT-TGGTG--TACTCAA-GT----------------CTTGAATT-AAACTTT-AATAACT--GAGTAA--TTTTGTTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsugill_Nay_281X  TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGCTGAAGTTTG--TGTTCTTT-ACT-TGGTG--TATTAAA-GTCTTCT---AACAACTGCTTGAATT-AAACTTT-AATAATT--GAGTAA--TTTTGCTACCAATC------------TTTTTTGAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_Cham_639W   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCAATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACA-TGGTG--TACTT---GTCTTCA---AACG-TTGCTTGATTT-AAACTT------------AGTAA--TTTTGCTACCAATCTTTTTTTTTTT-TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LG_638W     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTTTTT------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpoch_LY_608Z     TACATTAAGAAAATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTTTAGACAAACCTCTTCGTTTGCCTCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TTTTCTTT-ACG-TGGTG--TACTCAA-GTCTTCT---AACA-TTGCTTGGATT-AAACTT-----AACT--GAGTAA--TTTTGCTACCAATCTTT---------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	yucun_636Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCTCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAAATTGAAATTTG--TGTTCTTT-ACT-TGGTG--TATTCA----CTTCTTCTAACAATTGCTTGAATT-AAACTTT-AATAACA--GAGTTAA-TTTTGCTACCAATC------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	banksi_104X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAATATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCACCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTATGTCGAACT-----TTTTCTTT-ACT-TGGTG--TATTCAA-GTCTTCT---AACAATTGCTTGAATT-AAACTT--AATAACT--GAATAA--TTTTGCTACCAATCT-----------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	amer_WM_316W       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTTTTTTTTTTTTTACT-TGGTG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATTAAAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	amer_DG_345X       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTCGTTTTTTTA---ACT-TGGTG--TACTCAA-GTCTTCGAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTCGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	bulb_Long_536Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATT----------------AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	waughi_129W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTTTACT-TCGTG--TACTCAA-GTCTT-GAATTATAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfsans_349W        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTA--ACT-TGGAG--TACTCAA-GTCTT-GAATTAAACTTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	sans_368W          TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTT--ACT-TGGTG--TACTCAA-GTCTT-GAATTAAAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kubai_540W         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTGT---CTCTTAACCTGAAATTTGTTTTTTTTTT-ACT-TGGTG--TACTCAA-GTCTT-GAATAAAACTTGCTTGAATT-AAACTTC--ATAACT--GAG-AA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_KR_377Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTAAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tars_Baja_591Z     TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGACGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTGAATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACAGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	must_BRB_365X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGGCCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT--TTTTC????????????????????????????????????????????????????????C--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ophrys_SL_352X     TACATTAAGAAGATTGGTTACAATCCTGC-ACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGA-CCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTT??????????????????????????????????????????????????????????????????ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tuber_WP_464X      TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCC-CTCCAAGATGTATATAAGATTGGTGGTATGT-T---TTCTTAACCTGAAATTTG--TTT-CTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAAC?????????????????????????????--?????????TTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	kawini_592X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGA-CCAAGCACAAACATGGGATGGTACAAAGGGTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGA-GCTATGGAGCCTCCATCAAG-CCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAGATTGGTGGTATGTAT---CTCTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTT-AATT-AAACTTC--ATAACT--GAGTAA--TTTTGCTGCCAAT-------------CTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	notial_471X        TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGT-CCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTCTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGCTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGATGTATATTAAA-CTC-TCT---AACAATTAATGGAATT-AAACTTC-AATAATT--GAATAA--TTTTGCTACCAATCTT----------TATTTTGAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTAAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	jucun_395Z         TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTA--TGTTCTTT-ACT-TGGTGTATATTAAA-GTCT------AACAATTGCTGGAATT-AAACTTT-AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calcalc_524Z       TACATTAAGAAGATTGGTTACAATCCTGCAACAGTACCATTTGTCCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGTTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTTCAAGATGTGTACAAAATTGGTGGTATGTATT-GCTGTTAAGTTGAAATTTG--TGTTCTTT-ACT-TGGTGTATATTA---GTCTTCT---AACAATTGCTGGAATT-AAACT---AATAATT--GAATAA--TTTTTCTACCAATCTT----------TATTTTTAAGGTATTGGAACAGTACCTGTTGGCAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virid_470X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	calmadd_16Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAACAATTGCTTTAATTTAAACAT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTAC-TTTGCTCCAGCTAACA [...]
+
+	cfcalc_546W        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGT-AACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAATAATTGCTTCAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	trim_559X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCT-CAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAATTTAAAC----AATAACT--TAG-AA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	orbus_27Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT----GTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CATTCAA-GTCTTCTAACAACAATTGCTTTAA-TTAAACTT--AATAACT--TAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCGGCTAACA [...]
+
+	morat_485Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGACAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCT-TTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--CACTGAA-GTCTTCTAACAA-AATTGCTTTAATTTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT------------TTTTCTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	cfmor_ET_611W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_LY_667W      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTTGATAAACCTCTTCGTTTGCCCCTGCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TTTTTTCTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfmor_Cham_662Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAT-----TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATCACTTTAAATTAAACTT--AATAACT--GAGTAA--TTTTGCTATCAA--------------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	divar_563W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTTGTTAT-----------------T-TTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	caldiv_ES_600Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATATAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTTATT-AAACTT--AATAATT--GAGTAA--TTTT---AT-----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cyncity_468Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAAATTG--TTTTCTTT-ACT-TGGT---TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCATTTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	silvcty_285W       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Chir_274W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GA-TAA--TTTTGCTATCAATTTTTTTTT-----TTTTTTTTAGGTATTGGAAC-GTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGGATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	doss_Yec_531X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AA??TT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTT--------TTTTTTTTAGGTATTGGTACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_LS_659X      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-AT-CTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	veliv_Teq_661Z     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAGGATGTATACAAAATTGGTGGTATGTATT-GTTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTA--TAC------TCTTCTAACAACAATTGCTTTAATT-ATACTT--AATAACT--GAGTAA--TTTTGCTGTCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	fort_290Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCC-ATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAGC-TGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTTCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTT----------TCTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	aztec_218W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATT---------------TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cffest_517Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGGCTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Heuco_502Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACATTTGCTTTAATT-AA-CTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	klaus_Bis_390Z     TACATTAAGAAGATTGGTTACAA-CCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAA-ACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGT-------TTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAAC---GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	zebra_442W         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCCAAGAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGTT-TC----------------TTTTTTTAAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	tlax_674X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAA-ACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCA????????????????????????????????????????????--????????????????????????T---------CTTTTTTTAGGTATTGGAACAGTCCCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Pach_652W     TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAGACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACTTGAAATTTG--TTTTCTTT-GCT-TGGTG--TACTCAA-GTCTTCTAAGAACAATTGCTTTAATT-AAACTT--AATAACG--GAGTAA--TTTTGCTATCAATTTTTTTATTTATTTTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Cat_167Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	virg_Swiss_682Z    TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAAGGAAAAACTTTGTTACAAGCTTTAGATGCTATGGAGCCTCCATCAAGACCACTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTGTCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGTATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	mexic_496Z         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACC-GTTGGTAGAGTTGAAACTGGTATCTTGAAACCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	carp_LS_670Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T----AA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	boreal_130Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT---------CCTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTGAA-GTCT------AACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coec_96Z           TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTTCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT-----AACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cusp_550Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG-------TTTCTTT-ACT-TGGTG--TACTGAA-GTCTTCT---AACAATTGCTTT-----AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	coecgrp_Mag_580Z   TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGATGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TGCTTAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTTTTC--------TTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	pyr_10Z            TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCTAACAACAATTGCTTTAATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAATA [...]
+
+	ball_383X          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAG-CCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAA-CTGAAGTTTG--TTTTCTTT-ACT-TGGTG--TACTCAA-GTCTTCT---AACAATTGCTTT-----AAACTT------ACT--GAGTAA--TTTTGCTATCAATTTTT---------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCC-GGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfanep_576Z        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGATG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_LB_557Z       TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTATTAACCCGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	anep_ITT_314Z      TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAG------TTTTCTTT-ACT-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTAT-AATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	ammo_556Z          TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACC-GAAG------TTTTCTTT-A-T-TGGTG--TACTCAA-GTC------------------------AAACTT--AATAACT--GAGTAA--TTTTGCTATCAATTT-----------TTCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	cfpyrr_578X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGCAAAGGCAACAAGACTGAGGGGAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAATTTG--TTTTCTTT-ACT-TGGTG--T-CTCAA-GTCTTCTAACAACAATTGCTTTTATT-AAACTT--AATAACT--GAGTAA--TTTTGCTATCAAATT-----------CTTTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACTGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAA-A [...]
+
+	brunn_543X         TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAA-ATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAACAAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCT????????????????????????????????????????????????????????????????????????????????--?????????????????????????????????????TTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAACCGGTATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+	schlin_160X        TACATTAAGAAGATTGGTTACAATCCTGCAACTGTACCATTTGTTCCAATTTCTGGGTGGAATGGTGACAACATGTTAGAACCAAGCACAAACATGGGATGGTACAAAGGCTGGTCTATTGAACGTAAAGGCAA-AAGACTGAGGGAAAAACTTTGTTACAAGCTTTGGATGCTATGGAGCCTCCATCAAGACCTCTAGATAAACCTCTTCGTTTGCCCCTCCAAGATGTATACAAAATTGGTGGTATGTATT-GCTGTTAACCTGAAGTTTG????????????????????????????????????????????????????????????????????????--????????????????????????-----------TCTTTTTAGGTATTGGAACAGTACCTGTTGGTAGAGTTGAAAC-GG-ATCTTGAAGCCAGGAATGGTTGTTACATTTGCTCCAGCTAACA [...]
+
+
+;
+
+
+		BLOCKID WM1148b7a5ac90;
+
+
+END;
+
+BEGIN TREES;
+	Title 'Trees from "05-gcContentTaxaExons.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Sand_S127W,
+		2 Papacheus_093X,
+		3 Pshoshoensis_430Z,
+		4 Plongimanus_510Z,
+		5 ustul_RailX_211Z,
+		6 ustul_Mar_551Z,
+		7 cfsign_AV_570Z,
+		8 signat_684Z,
+		9 amicus_387Z,
+		10 alachua_527X,
+		11 cognatus_294W,
+		12 peckhami_382X,
+		13 elegans_213Z,
+		14 conjun_179AX,
+		15 geron_60Z,
+		16 doroth_LS_621Z,
+		17 huast_Chp_623X,
+		18 cfparat_88W,
+		19 venat_119Z,
+		20 carolin_134X,
+		21 cocker_108Z,
+		22 splend_525Z,
+		23 ocala_612Z,
+		24 pugill_459Z,
+		25 hallini_37Z,
+		26 cambrid_443Z,
+		27 fall_TX_288Z,
+		28 fallax_Chp_647X,
+		29 fallax_WComp_648W,
+		30 oregon_05Z,
+		31 icenog_196Z,
+		32 taras_643Z,
+		33 cftaras_554Z,
+		34 texanus_494X,
+		35 altan_AZ_124Z,
+		36 altan_Chih_325Z,
+		37 altan_Oax_645W,
+		38 cfsugill_Nay_281X,
+		39 cfpoch_Cham_639W,
+		40 cfpoch_LG_638W,
+		41 cfpoch_LY_608Z,
+		42 yucun_636Z,
+		43 banksi_104X,
+		44 amer_WM_316W,
+		45 amer_DG_345X,
+		46 bulb_Long_536Z,
+		47 waughi_129W,
+		48 cfsans_349W,
+		49 sans_368W,
+		50 kubai_540W,
+		51 tars_KR_377Z,
+		52 tars_Baja_591Z,
+		53 must_BRB_365X,
+		54 ophrys_SL_352X,
+		55 tuber_WP_464X,
+		56 kawini_592X,
+		57 notial_471X,
+		58 jucun_395Z,
+		59 calcalc_524Z,
+		60 virid_470X,
+		61 calmadd_16Z,
+		62 cfcalc_546W,
+		63 trim_559X,
+		64 orbus_27Z,
+		65 morat_485Z,
+		66 cfmor_ET_611W,
+		67 cfmor_LY_667W,
+		68 cfmor_Cham_662Z,
+		69 divar_563W,
+		70 caldiv_ES_600Z,
+		71 cyncity_468Z,
+		72 silvcty_285W,
+		73 doss_Chir_274W,
+		74 doss_Yec_531X,
+		75 veliv_LS_659X,
+		76 veliv_Teq_661Z,
+		77 fort_290Z,
+		78 aztec_218W,
+		79 cffest_517Z,
+		80 klaus_Heuco_502Z,
+		81 klaus_Bis_390Z,
+		82 zebra_442W,
+		83 tlax_674X,
+		84 virg_Pach_652W,
+		85 virg_Cat_167Z,
+		86 virg_Swiss_682Z,
+		87 mexic_496Z,
+		88 carp_LS_670Z,
+		89 boreal_130Z,
+		90 coec_96Z,
+		91 cusp_550Z,
+		92 coecgrp_Mag_580Z,
+		93 pyr_10Z,
+		94 ball_383X,
+		95 cfanep_576Z,
+		96 anep_LB_557Z,
+		97 anep_ITT_314Z,
+		98 ammo_556Z,
+		99 cfpyrr_578X,
+		100 brunn_543X,
+		101 schlin_160X;
+	TREE Griswold = (1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,( [...]
+
+END;
+
+
+BEGIN LABELS;
+	CHARGROUPLABEL introns COLOR = (RGB 0.88627451 0.00392157 0.28627451) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET * UNTITLED   =   245 -  391 574 -  665;
+	CHARSET introns   =   245 -  391 574 -  665;
+	CHARSET exons   =   1 -  244 392 -  573 666 -  716;
+
+	CHARPARTITION * UNTITLED  =  introns :  245 -  391 574 -  665;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  716;
+
+	EXSET * UNTITLED  =  245 -  391 574 -  665;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = '1. special character: GC bias for taxon^n^n2. *** number for character: GC bias chart^n^n3. Parsimony steps^n^n4. Gaps';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  716;
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  716;
+
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5362004184182154199 WM1148b7a5a768;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5453088708553656046 WM1148b7a5ac90;
+			checksum 0 2175300760 WM1148b7a5ac90;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 499 440;
+			setLocation 3 33;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5362004184182154199  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 419.967566324406.1416342777910267728;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 734 531;
+					setLocation 549 31;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.ornamental.CircularTree.CircularTree;
+					tell It;
+						setEdgeWidth 6;
+						getEmployee #mesquite.ornamental.NodeLocsCircular.NodeLocsCircular;
+						tell It;
+							branchLengthsToggle off;
+							toggleScale on;
+						endTell;
+					endTell;
+					setBackground Light_Blue;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(1,((2,(3,4)),((((((5,6),7),8),9),((((15,16),17),18),((((((19,20),((21,23),22)),((32,33),43)),(39,(40,41))),((24,(26,((27,28),29))),(((((30,31),((57,59),58)),38),42),((34,37),(35,36))))),(((((((((((25,(75,76)),(((60,(61,(62,65))),(63,64)),(66,(68,(71,((((((((79,(80,89)),81),91),90),(((((95,96),98),97),100),101)),(85,86)),94),(83,((87,88),(92,(93,99)))))))))),84),67),72),78),74),73),77),((69,70),82)),((((((((((44,46),50),48),45),(47,49)),52),51),56),(53,54)),55))))),(10,((11 [...]
+					useSuggestedSize off;
+					toggleSizeToFit off;
+					sizeDrawing 500 500;
+					toggleLegendFloat on;
+					setOrigin 0 0;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.molec.TaxonGCBias.TaxonGCBias;
+							tell It;
+								getEmployee #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+								tell It;
+									setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+									tell It;
+										setDataSet #5453088708553656046;
+									endTell;
+								endTell;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							tell It;
+								setDefaultModel 13;
+							endTell;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -319;
+					setLegendWidth 142;
+					setLegendHeight 302;
+					resume ;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-cytochromeB.nex';
+			setPrevFileName '04-gcContentTaxa.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 419 423;
+					setLocation 3 33;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This shows the same analysis of GC bias across taxa as the previous example, except that the introns are now excluded from the calculations.  The variation in GC bias appears not so extreme. Some of the variation in GC bias across taxa appears not to be due to compositional bias in homologous sites, but rather to the fact that some taxa have longer introns than others, which  leads to a lower GC bias for these taxa (because the introns are AT rich).';
+				setTitle GC_bias;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/06-cytochromeB.nex b/Resources/examples/Molecular/06-cytochromeB.nex
new file mode 100755
index 0000000..969f515
--- /dev/null
+++ b/Resources/examples/Molecular/06-cytochromeB.nex
@@ -0,0 +1,541 @@
+#NEXUS
+[written Sat Jun 07 12:30:00 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=46;
+	TAXLABELS
+		Lamprey Alligator Blue_Whale Fin_whale dog Carassi white_rhino Chrysem crow carp possum donkey horse cat chicken Halicho Hippo gibbon Kangaroo smooth_dog_fish Myoxus trout platypus sheep baboon Pelomed seal_vitulina Polypterus lung_fish Skate Rat Black_Rhino Salmon Scyliorhinus Spiny_dog_fish ostrich Pig Man Fly Frog cow mouse amphioxus Mosquito p_urchin S_urchin 
+	;
+	BLOCKID WM1148b7aa9a99;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Amino_acids;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = location;
+	MATRIX
+	Lamprey          -SHQPSIIRKTHPLLSLGNSMLVDLPSPANISAWWNFGSLLSLCLILQIITGLILAMHYTANTELAFSSVMHICRDVNNGWLMRNLHANGASMFFICIYAHIGRGIYYGSYLYKETWNVGVILFALTAATAFVGYVLPWGQMSFWGATVITNLISAMPYVGNDIVVWLWGGFSVSNATLTRFFTFHFILPFILAAMTMIHIMFLHQTGSSNPMGINSNLDKIQFHPYFSFKDILGFVILLGILFMISLLAPNALGEPDNFIYANPLSTPPHIKPEWYFLFAYAILRSVPNKLGGVVALAAAIMILLIIPFTHTSKQRGMQFRPLAQITFWILIADLALLTWLGGEPAEYPFILMTQIASTVYFMIFILVFPILGYLENKMLL
+
+	Alligator        ---MTHQLRKSHPIIKLINRSLIDLPTPSNISAWWNFGSLLGLTLLIQILTGFFLMMHFSSSDTLAFSSVSYTSREVWFGWLIRNLHTNGASLFFMFIFLHIGRGLYYTSYLHESTWNIGVIMLLLLMATAFMGYVLPWGQMSFWGATVITNLLSATPYVGSTVVPWIWGGPSVDNATLTRFTALHFLLPFALLASLITHLIFLHERGSFNPLGISPNADKIPFHPYFTMKDALGAALAASSLLILALYLPALLGDPENFTPANSMITPTHIKPEWYFLFAYAILRSIPNKLGGVLAMFSSILVLFLMPALHTAKQQPMSMRPMSQLLFWALTLDFLLLTWIGGQPVNPPYILIGQTASLFYFIIILILMPMAGLLENKMVE
+
+	Blue_Whale       ----MTNIRKTHPLMKIINDAFIDLPTPSNISSWWNFGSLLGLCLIVQILTGLFLAMHYTPDTMTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLYAHMGRGLYYGSHAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYYTIKDILGALLLILTLLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLALIPMLHTSKQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYVIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Fin_whale        ----MTNIRKTHPLMKIVNDAFVDLPTPSNISSWWNFGSLLGLCLIMQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYAHMGRGLYYGSYAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYHTIKDILGALLLILILLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILILAFIPMLHTSNQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYMIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	dog              ----MTNIRKTHPLAKIVNNSFIDLPAPSNISAWWNFGSLLGVCLILQILTGLFLAMHYTSDTATAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFLHVGRGLYYGSYVFMETWNIGIVLLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAMVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGALLLLLILMSLVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAFIPLLHTSKQRSMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFIIIGQVASILYFTILLILMPTVSVIENNLLK
+
+	Carassi          ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFIIAAATVIHLLFLHETGSNNPIGLNSDADKISFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLVLFPLAGWLENKALK
+
+	white_rhino      ----MTNIRKSHPLIKIINHSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTPDTMTAFSSVAHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGIYYGSYTFLETWNIGVILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGILLLILALLALVLFSPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILTLLIIPFLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFTLILVLMPLAGIIENNLLK
+
+	Chrysem          ---MTMNHRKTHPLTKIINNSFIDLPSPSNISAWWNFGSLLGTCLILQTITGIFLAMHYSPDISLAFSSVAHITRDVQYGWLIRNMHANGASLFFMCIYLHIGRGLYYGSYLYKETWNTGIILLLLTMATAFMGYVLPWGQMSFWGATVITNLLSAIPFIGNTLVQWIWGGFSVDNATLTRFFTLHFLLPFTIMGLTMVHLLFLHETGSNNPTGLNSNTDKIPFHPYFSYKDLLGVILMLTLLLTLTLFSPNLLGDPDNFTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLFLMPALHTSKQRTTQFRPLTQTLFWSFIANLLVLTWIGGQPVENPFITIGQVASILYFSTLLILIPIAGVIENKML-
+
+	crow             ---MGLNLRKNHPLLKIINNSLIDLPTPSNISAWWNFGSLLGLCLIMQIITGLLLAMHYTADTSLAFASVAHMCRDVQFGWLIRNLHANGASFFFICIYLHIGRGFYYGSYLNKETWNIGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWLWGGFSVDNPTLTRFFAFHFLLPFVIAGLTLVHLTFLHETGSNNPLGIPSDCDKIPFHPYYSIKDLLGFALMLIPLITLALFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLVLFLIPLLHVSKQRSMTFRPLSQILFWTLVADLLILTWVGSQPVEHPFIIIGQLASFAYFAIILILFPVVSALENKILK
+
+	carp             ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNVHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFVIAAATIIHLLFLHETGSNNPIGLNSDADKVSFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLIFMPLAGWLENKALK
+
+	possum           ----MTNIRKTHPLMKIINDSFIDLPTPSNISAWWNFGSLLGVCLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNIHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGSTLVEWIWGGFSVDKATLTRFFAFHFILPFIILAMVVVHLLFLHETGSSNPTGLDPNSDKIPFHPYYTMKDILGLFLMIIILLSLAMFSPDLLGDPDNFTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILVLLIIPMLHTSTQRSMAFRPISQTLFWMLTANLIILTWIGGQPVEQPYITIGQWASISYFTIIIILMPLAGMLENYMLK
+
+	donkey           ----MTNIRKSHPLIKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVIVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLVLLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	horse            ----MTNIRKSHPLIKIINHSFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVVVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLILLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	cat              ----MTNIRKSHPLIKIINHSFIDLPAPSNISAWWNFGSLLGVCLTLQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGMYYGSYTFSETWNIGIMLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTELVEWIWGGFSVDKATLTRFFGFHFILPFIISALAGVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGLLVLVLTLMLLVLFSPDLLGDPDNYIPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIIPILHTSKQRGMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFITIGQLASILYFSTLLILMPISGIIENRLLK
+
+	chicken          ---MAPNIRKSHPLLKMINNSLIDLPAPSNISAWWNFGSLLAVCLMTQILTGLLLAMHYTADTSLAFSSVAHTCRNVQYGWLIRNLHANGASFFFICIFLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGHTLVEWAWGGFSVDNPTLTRFFALHFLLPFAIAGITIIHLTFLHESGSNNPLGISSDSDKIPFHPYYSFKDILGLTLMLTPFLTLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPFLHKSKQRTMTFRPLSQTLFWLLVANLLILTWIGSQPVEHPFIIIGQMASLSYFTILLILFPTIGTLENKMLN
+
+	Halicho          ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTIMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGFSVDKATLTGFFAFHFILPFVVLALAAVHLLFLHETGSNNPSGIMPDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILILAIVPLLHTSKQRGMMFRPISQCLFWLLVADLLTLTWIGGQPVEHPYITIGQLASILYFMILLVLMPIASIIENNILK
+
+	Hippo            ----MTNIRKSHPLMKIINDAFVDLPAPSNISSWWNFGSLLGVCLILQILTGLFLAMHYTPDTLTAFSSVTHICRDVNYGWVIRYMHANGASIFFICLFTHVGRGLYYGSHTFLETWNIGVILLLTTMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFVITALAIVHLLFLHETGSNNPTGIPSNADKIPFHPYYTIKDILGILLLMTTLLTLTLFAPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALALSILILALIPMLHTSKQRSLMFRPLSQCLFWALIADLLTLTWIGGQPVEHPFIIIGQVASILYFLLILVLMPVAGIIENKLLK
+
+	gibbon           ----MTPLRKTNPLMKLINHSLIDLPAPSNISMWWNFGSLLGACLILQIITGLFLAMHYTPDASTAFSSVAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYLETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTDLVQWVWGGYSVDNATLTRFFTFHFILPFIITALAALHLLFLHETGSNNPLGISSQPDKIAFHPYYTIKDILGLFLLLLMLMSLVLFSPDLLGDPSNYTQANPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALLLSILILAMIPALHTAKQQSMMFRPLSQLTYWLLVMNLLILTWIGGQPVSYPFITIGQVASALYFTTILVLMPAASLIENKMLK
+
+	Kangaroo         ----MTNLRKSHPLIKIVNHSFIDLPAPSNISAWWNFGSLLGACLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNLHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYVGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVLVHLLFLHETGSNNPSGINPDSDKIPFHPYYTIKDALGLMLMLFILLMLALFSPDMLGDPDNFSPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILILLIIPLLHTSKQRSLMFRPISQTLFWILTANLITLTWIGGQPVEQPFIIIGQLASISYFLLIIILMPLAGLFENYMLE
+
+	smooth_dog_fish  ---MATNIRKTHPLLKIMNHALVDLPAPSNISLWWNFGSLMGLCLLIQILTGLFLAMHYTADISMAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYLHIARGLYYGSYLNKETWDIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNMLVQWIWGGFSVDNATLTRFFAFHFLLPFLIMALSIIHLLFLHESGSNNPLGINSDADKVSFHPYFSYKDLLGFFVMIFLLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKQRSIIFRPLTQIFFWVLVANSIILTWIGGQPVEQPFIMVGQIASISYFALFLIIMPFISWCENKILS
+
+	Myoxus           ----MTIIRKSHPLIKIINHSFIDLPTPSNISAWWIFGSLLGACLGIQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGMYYGSYMFIETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALVMVHLLFLHETGSNNPSGLNSDTDKIPFHPYYTIKDILGLLLLIFLLMTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAILPVLQFSKQRSMMFRPLSQCPFWILTADLFTLTWIGGQPVEHPFIIIGQLASILYFSIILFFLPTFSLLENKLLK
+
+	trout            ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWALVADMLILTWIGGMPVEHPFIIIGQVASVIYFTIFLVLSPLAGWAEIKALQ
+
+	platypus         ----MNNLRKTHPLIKIVNHSFIDLPTPSNISSWWNFGSLLGLCLIIQILTGLFLAMHYTSDTSTAFSSVAHICRDVNYGWLIRYMHANGASLFFMCIFLHIGRGLYYGSYTQTETWNIGVVLLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFVIAALAVIHLLFLHETGSNNPSGLNSDPDKIPFHPYYSVKDLVGFFMTILVLLTLVLFTPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILVPLLHTSYQRGLAFRPLTQMLFWILVTDLLTLTWIGGQPVEQPFIIIGQLASILYFLLITTLIPLTGLLENDLLK
+
+	sheep            ----MINIRKTHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFMHVGRGLYYGSYTFLETWNIGVILLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFIFPFIIAALAMVHLLFLHETGSNNPTGIPSDTDKIPFHPYYTIKDILGAILLILILMLLVLFTPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILVLVIMPLLHTSKQRSMMFRPISQCMFWILVADLLTLTWIGGQPVEHPYIIIGQLASIMYFLIILVMMPVASIIENNLLK
+
+	baboon           ----MTPMRKSNPIMKMINHSFIDLPTPSNISIWWNFGSLLATCLILQIITGLFLAMHYSPDTSSAFSSIAHITRDVNYGWTIRYLHANGASMLFICLFLHVGRGLYYGSYLLLKTWNIGIMLLLMTMTTAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTNLVQWVWGGPAIDNPTLMRFFTLHFILPFGIVALTIVHLLFLHETGSNNPCGISSDPDKITFHPYYTTKDILGVAPLLLALMTLTLFSPDLLNDPDNYTPADPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALFLSILILAAIPMLHKSKQQSMMFRPLSQFLFWLLATTLLTLTWIGSQPVIQPLTTIGQVASMVYFLTTLVLMPLAAQVENNLLK
+
+	Pelomed          ---MGTLHLKQNPLLKITNKSLINLPSPSNISAWWNFGSLLGMCLILQITTGIFLAMHYTPNITTAFSSVAHITRDVQYGWLLRGLHANGASIFFICLYFHIGRGIYYGSFLNKKTWYTGIMLLFLTMATAFMGYILPWGQMSFWGATVITNLLSAIPYMGTNLVQWIWGGFSVDNATLTRFFTLHFLTPFIISSLTTIHLLLLHEKGSNNPTGLNSNPDKIPFHPYFSYKDLLGVNLLMIGLLTLTLFLPNLLTDPENFTPANPLSTPKHIKPEWYFLFAYAILRSIPNKLGGVLALLSSVTILFIMPTLHTSKQRSATFRPFTQILFWSPTADLVILTWIGAQPVEDPFIMIGQTASVFYFTLILLLIPLAAILENKLLD
+
+	seal_vitulina    ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYVGTDLVQWIWGGFSVDKATLTRFFAFHFILPFVVLALDAVHLLFLHETGSNNPSGIMSDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPPNPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIMPLLHTSKQRGMMFRPISQCLFWFLVADLLTLTWIGGQPVEHPYITVGQLASILYFTILLVLMPIASIIENNILK
+
+	Polypterus       ----MAIIRKTHPLAKIINSAFIDLPAPSNISSWWNMGSLLGLCLIAQIITGLFLAMHYVSDINSAFSSVAHICRDVNYGWLIRNFHANGASLFFICIYLHIARGLYYGSYLYTETWNMGVILLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAIPYIGDTLVQWIWGGFSVDKPTLTRFFAFHFILPFAIAAASLVHIVFLHETGSNNPVGINSDADQIPFHPYFTFKDLLGFIILLLIIIMLALLSPNLLNDPGNFTPANPLITPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPLLHTSKIRSATFRPLFKITLWILAADVLILTWIGGQPVEDPYIIIGQAASILYFLIFLVLMPLSGWLENKMLN
+
+	lung_fish        ---MATNIRKTHPLLKIVNNSLIDLPTPSNISAWWNFGSLLGFCLITQILTGLFLAMHYTADTSTAFSSIAHIARDVNYGWLLRNIHANGASMFFICIYIHIGRGIYYGSFLYTETWNIGVVLFLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYLGDTLVQWIWGGFSVDNATLTRFFAFHFLLPFIISAMTAAHFLFLHETGSNNPTGLNSNLDKISFHPYFTMKDLLGFLMLASFLCLLALFSPNLLGDPENFTPANPLVTPTHIKPEWYFLFAYAILRSIPNKLGGVLALMASILILFIIPFLHRAKQRTMSYRPLSQFMFWLLTADMLILTWIGGQPVEHPFILIGQIASATYFLLFLLLFPLITSLENKLLY
+
+	Skate            ---MTTNIRKTHPLFKIINSSLIDLPTPVNISIWWNYGSLLGLCLIIQILTGLFLAMHYTPDIASAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYIHMARGFYYGSYLNKETWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNILVEWIWGGFSVDNATLTRFFAFHFLFPFLIVALTLLHLLFLHEMGSNNPTGLNSNTDKIPFHPYFSYKDLLGFFILGLLLTLLALFTPNLLGDTENFIPADPLLTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPMLHTSKQRSATFRPITQILFWTLLTNTIILTWIGGQPVEQPFIIIGQIASVIYFLLFLILLPLAGWWENKILN
+
+	Rat              ----MTNIRKSHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYLQANGASMFFICLFLHVGRGLYYGSYTFLETWNIGIILLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDLLGVFMLLLFLMTLV--FPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVVALILSILILAFLPFLHTSKQRSLTFRPITQILYWILVANLLVLTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIVEDKMLK
+
+	Black_Rhino      ----MTNIRKSHPLVKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWMIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGALLLILVLLILVLFFPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILLLIPYLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFSLILVLMPLAGIIENNLLK
+
+	Salmon           ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWTLVADMLILTWIGGMPVEHPFIIIGQIASVIYFTIFLVLAPLAGWAENKALE
+
+	Scyliorhinus     ---MATNIRKTHPLLKIVNHALIDLPAPSNISVWWNFGSLLGLCLIMQIITGLFLAMHYTADISMAFSSVIHISRDVNYGWLMRNIHAYGASFFFICIYLHIARGLYYGSYLNKEAWNIGVVLLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNLLVQWIWGGFSVDNATLTRFFAFHFLLPFLILALSVIHILFLHETGANNPMGINSNTDKISFHPYFSYKDLFGFLIVITLLATLALFMPNLLGDAENFIPANPLVTPLHIQPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKLRSNIFRPLTQIFFWSLVTNAIILTWIGGQPVEQPFIMVGQIASVAYFSLFLFVIPITSWCENKFLS
+
+	Spiny_dog_fish   ---MTTNIRKTHPLIKIVNHALVDLPSPSNISIWWNFGSLLGLCLIIQILTGLFLAMHYTADISTAFSSVVHICRDVNYGWLIRNIHANGASLFFICVYLHIARGLYYGSYLFKEAWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGDMLVQWIWGGFSIDNATLTRFFAFHFLLPFLIVGLTLIHLLFLHETGSNNPMGLNSDMDKISFHPYFSYKDLLGFFLMIILLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILMLIPMLHTSKQRSNIFRPMTQFLFWTLVANAIILTWIGGQPVEQPFILVGQIASVTYFSLFLIIIPLTGWWENKMLN
+
+	ostrich          ---MAPNIRKSHPLLKIINNSLIDLPSPSNISAWWNFGSLLGICLITQILTGLLLAMHYTADTTLAFSSVAHTCRNVQYGWFIRNLHANGASFFFICIYLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWAWGGFSVDNPTLTRFFALHFLLPFVIAGITLVHLTFLHESGSNNPLGIISHCDKIPFHPYFSLKDILGFTLMFIPLLSLAFFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPLLHKSKQRSMTFRPLSQLLFWFLVANLLILTWIGSQPVEHPFIIIGQVASFTYFLILLVLFPAIAALENKMI-
+
+	Pig              ----MTNIRKSHPLMKIINNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLFIHVGRGLYYGSYMFLETWNIGVVLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIITALAAVHLLFLHETGSNNPTGISSDMDKIPFHPYYTIKDILGALFMMLILLILVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILMPMLHTSKQRGMMFRPLSQCLFWMLVADLITLTWIGGQPVEHPFIIIGQLASILYFLIILVLMPITSIIENNLLK
+
+	Man              ----MTPMRKINPLMKLINHSFIDLPTPSNISAWWNFGSLLGACLILQITTGLFLAMHYSPDASTAFSSIAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYSETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGYSVDSPTLTRFFTFHFILPFIIATLAALHLLFLHETGSNNPLGITSHSDKITFHPYYTIKDTLGLLLFLLSLMTLTLFSPDLLGDPDNYTLANPLNTPPHIKPEWYFLFAYTILRSVPNKLGGVLALLLSILILAMIPILHMSKQQSMMFRPLSQSLYWLLAADLLILTWIGGQPVSYPFTIIGQVASVLYFTTILILMPTISLIENKMLK
+
+	Fly              ---MHKPLRNSHPLFKIANNALVDLPAPINISSWWNFGSLLGLCLIIQILTGLFLAMHYTADVNLAFYSVNHICRDVNYGWLLRTLHANGASFFFICIYLHIGRGIYYGSYLFTPTWLVGVIILFLVMGTAFMGYVLPWGQMSFWGATVITNLLSAIPYLGMDLVQWLWGGFAVDNATLTRFFTFHFILPFIVLAMTMIHLLFLHQTGSNNPIGLNSNIDKIPFHPYFTFKDIVGFIVMIFILISLVLISPNLLGDPDNFIPANPLVTPAHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILMILPFYNLSKFRGIQFYPINQILFWSMLVTVILLTWIGARPVEEPYVLIGQILTIIYFLYYLINPLVTKWWDNLLN-
+
+	Frog             --LMAPNIRKSHPLIKIINNSFIDLPTPSNISSLWNFGSLLGVCLIAQIITGLFLAMHYTADTSMAFSSVAHICFDVNYGLLIRNLHANGLSFFFICIYLHIGRGLYYGSFLYKETWNIGVILLFLVMATAFVGYVLPWGQMSFWGATVITNLLSAKPYIGNVLVQWSLGGFSVDNATLTRFFAFHFLLPFIIAGASILHLLFLHETGSTNPTGLNSDPDKVPFHPYFSYKDLLGFLIMLTALTLLAMFSPNLLGDPDNFTPANPLITPPHIKPEWYFLFAYAILRSMN-KLGGVLALVLSILILALMPLLHTSKQRSLMFRPFTQIMFWALVADTLILTWIGGQPVEDPYTMIGQLASVIYFSIFIIMFPLMGWVENKLLN
+
+	cow              ----MTNIRKSHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLYMHVGRGLYYGSYTFLETWNIGVILLLTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMAIAMVHLLFLHETGSNNPTGISSDVDKIPFHPYYTIKDILGALLLILALMLLVLFAPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILALIPLLHTSKQRSMMFRPLSQCLFWALVADLLTLTWIGGQPVEHPYITIGQLASVLYFLLILVLMPTAGTIENKLLK
+
+	mouse            ----MTNMRKTHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQIITGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGLYYGSYTFMETWNIGVLLLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDILGILIMFLILMTLVLFFPDMLGDPDNYMPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALMPFLHTSKQRSLMFRPITQILYWILVANLLILTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIIEDKMLK
+
+	amphioxus        ---MSGPLRKHHPLLKVVNHSVIDLPVPSNISVMWNFGSLLGLCLVSQILTGLFLAMHYTADVNLAFSSVAHICRDVNYGWLLRNLHANGASFMFICLYMHIGRGLYYGSYFYRETWNIGVMLLVLTMATAFLGYVLPWGQMSFWGATVITNLFSAIPYLGPDLVQWLWGGFSVDNATLTRFFAFHFFLPFMIAGLSVVHLLFLHQTGANNPTGLAGDVDKVPFHAYFSYKDVVGFVVLLAGLVFIALFSPNLLTDPENYIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVVALAMSIVVLFFMPFVHSSRQTSHNFRPLAQVLFWLMVVNVLLLTWLGGQPVEYPYIFLGQAASVIYFVNILLLIPIVGYVENKLL-
+
+	Mosquito         ---MFKPIRKTHPLISIANNALVDLPAPSNISAWWNFGSLLGLCLMLQILTGLFLAMHYAADIETAFNSVNHICRDVNNGWFLRICHANGASFFFACLFIHVGRGVYYESYLYHMTWNTGVIILFLTMATGFLGYVLPWGQMSFWGATVITNLLSAVPYLGMDLVQWIWGGFAVDNATLTRFFTFHFIFPFIILALMMIHLLFLHQTGSNNPLGLNSNVDKIPFHPYFIYKDIFGFIVFLWILVTFIWKFNYLLMDPENFIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILLILPFTHSSKFRGLQFYPLNQILFWNMVIVASLLTWIGARPVEDPYILTGQILTVLYFSYFIINPLLAKFWDKLLN-
+
+	p_urchin         ---MLGPLRKEHPIFRILKSTFVDLPLPSKLSIWWKFGSLLGLCLMTQILTGLFLAMHYTADISLAFSSASHMCRDVNYGWLLRKVHAKGASLFFICMYCHMGRGLYYGGSNKMETWKVGVILFLVTVLTAFVGYVLVWGRMSFWAATVIANLVTAVPCVGTTIVQWLWGGFSVDNATLTRFFAFHFLFPFIMAALAMIDLVFLHNSGANNPVGLKSNYDKAPFHIYYTTKDTVGFMALIAALFVLALLFPCALKDPEKFIPANPLSHPPHMQPEWYFLFAYAILRSIPNKLGGVMALVAAMLVLFLMPLLKTSKKESNSFRPLSQATFWMLVATFFVLTWMGSQPVEQPFVLMGQMASLLYFSLFMFGFPLVSSLEKKMMF
+
+	S_urchin         IKIMAAPLRKEHPIFRILKSTFVDLPLPSNLSIWWNSGSLLGLCLVVQMLTGMFLAMHYTADITLAFSSVMHILRDVNYGWFLRYVHAKGVSLFFICMYCHMGRGLYYGSYKKIETWKVGVILFLVTILTAFMGYVLVWGQMSFWAATVITNLVSAIPYMGTIMVQWLWGGFSVDKATLTRFFPFHFLFPFMMAALAVMHLVFLHNSGANNPFAFKSNYDKAPFHIYFTTKDTVGFILLVAALFSLALLFPGALKDPEKFIPANPLVTPPHIQPEWYFLFAYAILRSIPNKLGGVIALVAAMLVLFLMPLLNTSKKESNSFRPLSQAAFWLLVAHLFMLTWMGSQPVEYPYVLLGQVASVLYFSLFMFGFPMVSSMENKIMF
+
+
+;
+
+		BLOCKID WM1148b7aa9d50;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  location;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y z )  GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = Amino_acids;
+	MATRIX
+	Lamprey           (? ? ?) (? ? ?) (? ? ?) (22.224 -9.668 17.52) (22.584 -9.432 13.672) (19.596 -7.388 12.448) (20.432 -4.54 14.864) (16.876 -3.428 14.072) (15.284 -6.116 16.228) (17.732 -5.752 19.14) (17.716 -1.984 19.856) (15.188 -1.076 22.644) (13.552 1.612 20.476) (13.812 0.428 16.884) (12.544 -2.944 18.092) (9.428 -1.028 19.1) (9.044 0.348 15.596) (10.136 -2.744 13.672) (7.44 -4.52 15.676) (4.656 -2.056 14.932) (5.168 -0.828 11.4) (7.376 -3.576 9.98) (7.588 -7.32 10.648) (4.172 -6.8 [...]
+	Alligator         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Blue_Whale        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fin_whale         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	dog               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Carassi           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	white_rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Chrysem           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	crow              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	carp              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	possum            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	donkey            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	horse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	chicken           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Halicho           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Hippo             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	gibbon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Kangaroo          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	smooth_dog_fish   (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Myoxus            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	trout             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	platypus          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	sheep             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	baboon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pelomed           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	seal_vitulina     (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Polypterus        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	lung_fish         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Skate             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Rat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Black_Rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Salmon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Scyliorhinus      (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Spiny_dog_fish    (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	ostrich           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pig               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Man               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fly               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Frog              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cow               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	mouse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	amphioxus         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Mosquito          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	p_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	S_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+
+;
+		BLOCKID WM1148b7aaa900;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-cytochromeB.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Lamprey,
+		2 Alligator,
+		3 Blue_Whale,
+		4 Fin_whale,
+		5 dog,
+		6 Carassi,
+		7 white_rhino,
+		8 Chrysem,
+		9 crow,
+		10 carp,
+		11 possum,
+		12 donkey,
+		13 horse,
+		14 cat,
+		15 chicken,
+		16 Halicho,
+		17 Hippo,
+		18 gibbon,
+		19 Kangaroo,
+		20 smooth_dog_fish,
+		21 Myoxus,
+		22 trout,
+		23 platypus,
+		24 sheep,
+		25 baboon,
+		26 Pelomed,
+		27 seal_vitulina,
+		28 Polypterus,
+		29 lung_fish,
+		30 Skate,
+		31 Rat,
+		32 Black_Rhino,
+		33 Salmon,
+		34 Scyliorhinus,
+		35 Spiny_dog_fish,
+		36 ostrich,
+		37 Pig,
+		38 Man,
+		39 Fly,
+		40 Frog,
+		41 cow,
+		42 mouse,
+		43 amphioxus,
+		44 Mosquito,
+		45 p_urchin,
+		46 S_urchin;
+	TREE true = ((((1,((((((((2,(9,(15,36))),(8,26)),((((((((((3,4),17),37),(24,41)),((7,32),(12,13))),((5,(16,27)),14)),((18,38),25)),(21,(31,42))),(11,19)),23)),40),29),28),((6,10),(22,33))),(((20,34),35),30))),43),(45,46)),(39,44));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Amino_acids)  =  universal:  1 -  382;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                             unord PolyTcount =                             MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Amino_acids)  =  unord:  1 -  382;
+TYPESET * UNTITLED  (CHARACTERS = location)  =  Squared:  1 -  382;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Amino_acids)  =  'Mk1 (est.)':  1 -  382;
+ProbModelSet * UNTITLED  (CHARACTERS = location)  =  Brownian_default:  1 -  382;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5749286926902316461 WM1148b7aa9a99;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7273041429729163753 WM1148b7aa9d50;
+			checksum 0 2913214590 WM1148b7aa9d50;
+			setID 1 1052710308229948178 WM1148b7aaa900;
+			checksum 1 3995003137 WM1148b7aaa900;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 590 232;
+			setLocation 8 30;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5749286926902316461  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1329.965277834391.3318683272318096025;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 496 453;
+					setLocation 11 339;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle on;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 4;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7273041429729163753 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 669 224;
+					setLocation 518 566;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 [...]
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #7273041429729163753;
+				endTell;
+			endTell;
+			setTaxa #5749286926902316461;
+			axesSame;
+			setValues  #mesquite.molec.MeanValueLinked.MeanValueLinked;
+			showColors on;
+			setColorValues  #mesquite.trees.NumForCharCurrentTree.NumForCharCurrentTree;
+			tell It;
+				setNumberTask  #mesquite.parsimony.ParsCharSteps.ParsCharSteps;
+				tell It;
+					setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+				endTell;
+				getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+				tell It;
+					setContextID 1329.965277834391.3318683272318096025;
+				endTell;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 617 572;
+					setLocation 650 28;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 7;
+					toggleJoin on;
+					toggleThickJoin on;
+					toggleLastToFirst off;
+					toggleShowDots off;
+					movingWindowSize 5;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-cytochromeBHydro.nex';
+			setPrevFileName '05-gcContentTaxaExons.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 590 215;
+					setLocation 8 30;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'At upper right is the cytochrome B protein with amino acids colored according to number of amino acid changes inferred by parsimony on the phylogeny above (averaged over a moving window of size 5).  The colors indicate which regions of the molecule show fewer changes than others.^n^n(Data kindly supplied by Gavin Naylor; analysis inspired by the work of Vander Velden & Naylor.)';
+				setTitle Cytochrome_B;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/07-cytochromeBHydro.nex b/Resources/examples/Molecular/07-cytochromeBHydro.nex
new file mode 100755
index 0000000..6a4ffc3
--- /dev/null
+++ b/Resources/examples/Molecular/07-cytochromeBHydro.nex
@@ -0,0 +1,433 @@
+#NEXUS
+[written Sat Jun 07 12:30:12 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=46;
+	TAXLABELS
+		Lamprey Alligator Blue_Whale Fin_whale dog Carassi white_rhino Chrysem crow carp possum donkey horse cat chicken Halicho Hippo gibbon Kangaroo smooth_dog_fish Myoxus trout platypus sheep baboon Pelomed seal_vitulina Polypterus lung_fish Skate Rat Black_Rhino Salmon Scyliorhinus Spiny_dog_fish ostrich Pig Man Fly Frog cow mouse amphioxus Mosquito p_urchin S_urchin 
+	;
+	BLOCKID WM1148c0850785;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Amino_acids;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = location;
+	MATRIX
+	Lamprey          -SHQPSIIRKTHPLLSLGNSMLVDLPSPANISAWWNFGSLLSLCLILQIITGLILAMHYTANTELAFSSVMHICRDVNNGWLMRNLHANGASMFFICIYAHIGRGIYYGSYLYKETWNVGVILFALTAATAFVGYVLPWGQMSFWGATVITNLISAMPYVGNDIVVWLWGGFSVSNATLTRFFTFHFILPFILAAMTMIHIMFLHQTGSSNPMGINSNLDKIQFHPYFSFKDILGFVILLGILFMISLLAPNALGEPDNFIYANPLSTPPHIKPEWYFLFAYAILRSVPNKLGGVVALAAAIMILLIIPFTHTSKQRGMQFRPLAQITFWILIADLALLTWLGGEPAEYPFILMTQIASTVYFMIFILVFPILGYLENKMLL
+
+	Alligator        ---MTHQLRKSHPIIKLINRSLIDLPTPSNISAWWNFGSLLGLTLLIQILTGFFLMMHFSSSDTLAFSSVSYTSREVWFGWLIRNLHTNGASLFFMFIFLHIGRGLYYTSYLHESTWNIGVIMLLLLMATAFMGYVLPWGQMSFWGATVITNLLSATPYVGSTVVPWIWGGPSVDNATLTRFTALHFLLPFALLASLITHLIFLHERGSFNPLGISPNADKIPFHPYFTMKDALGAALAASSLLILALYLPALLGDPENFTPANSMITPTHIKPEWYFLFAYAILRSIPNKLGGVLAMFSSILVLFLMPALHTAKQQPMSMRPMSQLLFWALTLDFLLLTWIGGQPVNPPYILIGQTASLFYFIIILILMPMAGLLENKMVE
+
+	Blue_Whale       ----MTNIRKTHPLMKIINDAFIDLPTPSNISSWWNFGSLLGLCLIVQILTGLFLAMHYTPDTMTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLYAHMGRGLYYGSHAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYYTIKDILGALLLILTLLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLALIPMLHTSKQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYVIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Fin_whale        ----MTNIRKTHPLMKIVNDAFVDLPTPSNISSWWNFGSLLGLCLIMQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYAHMGRGLYYGSYAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYHTIKDILGALLLILILLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILILAFIPMLHTSNQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYMIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	dog              ----MTNIRKTHPLAKIVNNSFIDLPAPSNISAWWNFGSLLGVCLILQILTGLFLAMHYTSDTATAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFLHVGRGLYYGSYVFMETWNIGIVLLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAMVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGALLLLLILMSLVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAFIPLLHTSKQRSMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFIIIGQVASILYFTILLILMPTVSVIENNLLK
+
+	Carassi          ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFIIAAATVIHLLFLHETGSNNPIGLNSDADKISFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLVLFPLAGWLENKALK
+
+	white_rhino      ----MTNIRKSHPLIKIINHSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTPDTMTAFSSVAHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGIYYGSYTFLETWNIGVILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGILLLILALLALVLFSPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILTLLIIPFLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFTLILVLMPLAGIIENNLLK
+
+	Chrysem          ---MTMNHRKTHPLTKIINNSFIDLPSPSNISAWWNFGSLLGTCLILQTITGIFLAMHYSPDISLAFSSVAHITRDVQYGWLIRNMHANGASLFFMCIYLHIGRGLYYGSYLYKETWNTGIILLLLTMATAFMGYVLPWGQMSFWGATVITNLLSAIPFIGNTLVQWIWGGFSVDNATLTRFFTLHFLLPFTIMGLTMVHLLFLHETGSNNPTGLNSNTDKIPFHPYFSYKDLLGVILMLTLLLTLTLFSPNLLGDPDNFTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLFLMPALHTSKQRTTQFRPLTQTLFWSFIANLLVLTWIGGQPVENPFITIGQVASILYFSTLLILIPIAGVIENKML-
+
+	crow             ---MGLNLRKNHPLLKIINNSLIDLPTPSNISAWWNFGSLLGLCLIMQIITGLLLAMHYTADTSLAFASVAHMCRDVQFGWLIRNLHANGASFFFICIYLHIGRGFYYGSYLNKETWNIGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWLWGGFSVDNPTLTRFFAFHFLLPFVIAGLTLVHLTFLHETGSNNPLGIPSDCDKIPFHPYYSIKDLLGFALMLIPLITLALFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLVLFLIPLLHVSKQRSMTFRPLSQILFWTLVADLLILTWVGSQPVEHPFIIIGQLASFAYFAIILILFPVVSALENKILK
+
+	carp             ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNVHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFVIAAATIIHLLFLHETGSNNPIGLNSDADKVSFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLIFMPLAGWLENKALK
+
+	possum           ----MTNIRKTHPLMKIINDSFIDLPTPSNISAWWNFGSLLGVCLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNIHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGSTLVEWIWGGFSVDKATLTRFFAFHFILPFIILAMVVVHLLFLHETGSSNPTGLDPNSDKIPFHPYYTMKDILGLFLMIIILLSLAMFSPDLLGDPDNFTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILVLLIIPMLHTSTQRSMAFRPISQTLFWMLTANLIILTWIGGQPVEQPYITIGQWASISYFTIIIILMPLAGMLENYMLK
+
+	donkey           ----MTNIRKSHPLIKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVIVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLVLLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	horse            ----MTNIRKSHPLIKIINHSFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVVVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLILLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	cat              ----MTNIRKSHPLIKIINHSFIDLPAPSNISAWWNFGSLLGVCLTLQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGMYYGSYTFSETWNIGIMLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTELVEWIWGGFSVDKATLTRFFGFHFILPFIISALAGVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGLLVLVLTLMLLVLFSPDLLGDPDNYIPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIIPILHTSKQRGMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFITIGQLASILYFSTLLILMPISGIIENRLLK
+
+	chicken          ---MAPNIRKSHPLLKMINNSLIDLPAPSNISAWWNFGSLLAVCLMTQILTGLLLAMHYTADTSLAFSSVAHTCRNVQYGWLIRNLHANGASFFFICIFLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGHTLVEWAWGGFSVDNPTLTRFFALHFLLPFAIAGITIIHLTFLHESGSNNPLGISSDSDKIPFHPYYSFKDILGLTLMLTPFLTLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPFLHKSKQRTMTFRPLSQTLFWLLVANLLILTWIGSQPVEHPFIIIGQMASLSYFTILLILFPTIGTLENKMLN
+
+	Halicho          ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTIMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGFSVDKATLTGFFAFHFILPFVVLALAAVHLLFLHETGSNNPSGIMPDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILILAIVPLLHTSKQRGMMFRPISQCLFWLLVADLLTLTWIGGQPVEHPYITIGQLASILYFMILLVLMPIASIIENNILK
+
+	Hippo            ----MTNIRKSHPLMKIINDAFVDLPAPSNISSWWNFGSLLGVCLILQILTGLFLAMHYTPDTLTAFSSVTHICRDVNYGWVIRYMHANGASIFFICLFTHVGRGLYYGSHTFLETWNIGVILLLTTMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFVITALAIVHLLFLHETGSNNPTGIPSNADKIPFHPYYTIKDILGILLLMTTLLTLTLFAPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALALSILILALIPMLHTSKQRSLMFRPLSQCLFWALIADLLTLTWIGGQPVEHPFIIIGQVASILYFLLILVLMPVAGIIENKLLK
+
+	gibbon           ----MTPLRKTNPLMKLINHSLIDLPAPSNISMWWNFGSLLGACLILQIITGLFLAMHYTPDASTAFSSVAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYLETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTDLVQWVWGGYSVDNATLTRFFTFHFILPFIITALAALHLLFLHETGSNNPLGISSQPDKIAFHPYYTIKDILGLFLLLLMLMSLVLFSPDLLGDPSNYTQANPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALLLSILILAMIPALHTAKQQSMMFRPLSQLTYWLLVMNLLILTWIGGQPVSYPFITIGQVASALYFTTILVLMPAASLIENKMLK
+
+	Kangaroo         ----MTNLRKSHPLIKIVNHSFIDLPAPSNISAWWNFGSLLGACLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNLHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYVGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVLVHLLFLHETGSNNPSGINPDSDKIPFHPYYTIKDALGLMLMLFILLMLALFSPDMLGDPDNFSPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILILLIIPLLHTSKQRSLMFRPISQTLFWILTANLITLTWIGGQPVEQPFIIIGQLASISYFLLIIILMPLAGLFENYMLE
+
+	smooth_dog_fish  ---MATNIRKTHPLLKIMNHALVDLPAPSNISLWWNFGSLMGLCLLIQILTGLFLAMHYTADISMAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYLHIARGLYYGSYLNKETWDIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNMLVQWIWGGFSVDNATLTRFFAFHFLLPFLIMALSIIHLLFLHESGSNNPLGINSDADKVSFHPYFSYKDLLGFFVMIFLLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKQRSIIFRPLTQIFFWVLVANSIILTWIGGQPVEQPFIMVGQIASISYFALFLIIMPFISWCENKILS
+
+	Myoxus           ----MTIIRKSHPLIKIINHSFIDLPTPSNISAWWIFGSLLGACLGIQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGMYYGSYMFIETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALVMVHLLFLHETGSNNPSGLNSDTDKIPFHPYYTIKDILGLLLLIFLLMTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAILPVLQFSKQRSMMFRPLSQCPFWILTADLFTLTWIGGQPVEHPFIIIGQLASILYFSIILFFLPTFSLLENKLLK
+
+	trout            ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWALVADMLILTWIGGMPVEHPFIIIGQVASVIYFTIFLVLSPLAGWAEIKALQ
+
+	platypus         ----MNNLRKTHPLIKIVNHSFIDLPTPSNISSWWNFGSLLGLCLIIQILTGLFLAMHYTSDTSTAFSSVAHICRDVNYGWLIRYMHANGASLFFMCIFLHIGRGLYYGSYTQTETWNIGVVLLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFVIAALAVIHLLFLHETGSNNPSGLNSDPDKIPFHPYYSVKDLVGFFMTILVLLTLVLFTPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILVPLLHTSYQRGLAFRPLTQMLFWILVTDLLTLTWIGGQPVEQPFIIIGQLASILYFLLITTLIPLTGLLENDLLK
+
+	sheep            ----MINIRKTHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFMHVGRGLYYGSYTFLETWNIGVILLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFIFPFIIAALAMVHLLFLHETGSNNPTGIPSDTDKIPFHPYYTIKDILGAILLILILMLLVLFTPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILVLVIMPLLHTSKQRSMMFRPISQCMFWILVADLLTLTWIGGQPVEHPYIIIGQLASIMYFLIILVMMPVASIIENNLLK
+
+	baboon           ----MTPMRKSNPIMKMINHSFIDLPTPSNISIWWNFGSLLATCLILQIITGLFLAMHYSPDTSSAFSSIAHITRDVNYGWTIRYLHANGASMLFICLFLHVGRGLYYGSYLLLKTWNIGIMLLLMTMTTAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTNLVQWVWGGPAIDNPTLMRFFTLHFILPFGIVALTIVHLLFLHETGSNNPCGISSDPDKITFHPYYTTKDILGVAPLLLALMTLTLFSPDLLNDPDNYTPADPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALFLSILILAAIPMLHKSKQQSMMFRPLSQFLFWLLATTLLTLTWIGSQPVIQPLTTIGQVASMVYFLTTLVLMPLAAQVENNLLK
+
+	Pelomed          ---MGTLHLKQNPLLKITNKSLINLPSPSNISAWWNFGSLLGMCLILQITTGIFLAMHYTPNITTAFSSVAHITRDVQYGWLLRGLHANGASIFFICLYFHIGRGIYYGSFLNKKTWYTGIMLLFLTMATAFMGYILPWGQMSFWGATVITNLLSAIPYMGTNLVQWIWGGFSVDNATLTRFFTLHFLTPFIISSLTTIHLLLLHEKGSNNPTGLNSNPDKIPFHPYFSYKDLLGVNLLMIGLLTLTLFLPNLLTDPENFTPANPLSTPKHIKPEWYFLFAYAILRSIPNKLGGVLALLSSVTILFIMPTLHTSKQRSATFRPFTQILFWSPTADLVILTWIGAQPVEDPFIMIGQTASVFYFTLILLLIPLAAILENKLLD
+
+	seal_vitulina    ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYVGTDLVQWIWGGFSVDKATLTRFFAFHFILPFVVLALDAVHLLFLHETGSNNPSGIMSDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPPNPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIMPLLHTSKQRGMMFRPISQCLFWFLVADLLTLTWIGGQPVEHPYITVGQLASILYFTILLVLMPIASIIENNILK
+
+	Polypterus       ----MAIIRKTHPLAKIINSAFIDLPAPSNISSWWNMGSLLGLCLIAQIITGLFLAMHYVSDINSAFSSVAHICRDVNYGWLIRNFHANGASLFFICIYLHIARGLYYGSYLYTETWNMGVILLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAIPYIGDTLVQWIWGGFSVDKPTLTRFFAFHFILPFAIAAASLVHIVFLHETGSNNPVGINSDADQIPFHPYFTFKDLLGFIILLLIIIMLALLSPNLLNDPGNFTPANPLITPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPLLHTSKIRSATFRPLFKITLWILAADVLILTWIGGQPVEDPYIIIGQAASILYFLIFLVLMPLSGWLENKMLN
+
+	lung_fish        ---MATNIRKTHPLLKIVNNSLIDLPTPSNISAWWNFGSLLGFCLITQILTGLFLAMHYTADTSTAFSSIAHIARDVNYGWLLRNIHANGASMFFICIYIHIGRGIYYGSFLYTETWNIGVVLFLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYLGDTLVQWIWGGFSVDNATLTRFFAFHFLLPFIISAMTAAHFLFLHETGSNNPTGLNSNLDKISFHPYFTMKDLLGFLMLASFLCLLALFSPNLLGDPENFTPANPLVTPTHIKPEWYFLFAYAILRSIPNKLGGVLALMASILILFIIPFLHRAKQRTMSYRPLSQFMFWLLTADMLILTWIGGQPVEHPFILIGQIASATYFLLFLLLFPLITSLENKLLY
+
+	Skate            ---MTTNIRKTHPLFKIINSSLIDLPTPVNISIWWNYGSLLGLCLIIQILTGLFLAMHYTPDIASAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYIHMARGFYYGSYLNKETWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNILVEWIWGGFSVDNATLTRFFAFHFLFPFLIVALTLLHLLFLHEMGSNNPTGLNSNTDKIPFHPYFSYKDLLGFFILGLLLTLLALFTPNLLGDTENFIPADPLLTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPMLHTSKQRSATFRPITQILFWTLLTNTIILTWIGGQPVEQPFIIIGQIASVIYFLLFLILLPLAGWWENKILN
+
+	Rat              ----MTNIRKSHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYLQANGASMFFICLFLHVGRGLYYGSYTFLETWNIGIILLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDLLGVFMLLLFLMTLV--FPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVVALILSILILAFLPFLHTSKQRSLTFRPITQILYWILVANLLVLTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIVEDKMLK
+
+	Black_Rhino      ----MTNIRKSHPLVKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWMIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGALLLILVLLILVLFFPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILLLIPYLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFSLILVLMPLAGIIENNLLK
+
+	Salmon           ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWTLVADMLILTWIGGMPVEHPFIIIGQIASVIYFTIFLVLAPLAGWAENKALE
+
+	Scyliorhinus     ---MATNIRKTHPLLKIVNHALIDLPAPSNISVWWNFGSLLGLCLIMQIITGLFLAMHYTADISMAFSSVIHISRDVNYGWLMRNIHAYGASFFFICIYLHIARGLYYGSYLNKEAWNIGVVLLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNLLVQWIWGGFSVDNATLTRFFAFHFLLPFLILALSVIHILFLHETGANNPMGINSNTDKISFHPYFSYKDLFGFLIVITLLATLALFMPNLLGDAENFIPANPLVTPLHIQPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKLRSNIFRPLTQIFFWSLVTNAIILTWIGGQPVEQPFIMVGQIASVAYFSLFLFVIPITSWCENKFLS
+
+	Spiny_dog_fish   ---MTTNIRKTHPLIKIVNHALVDLPSPSNISIWWNFGSLLGLCLIIQILTGLFLAMHYTADISTAFSSVVHICRDVNYGWLIRNIHANGASLFFICVYLHIARGLYYGSYLFKEAWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGDMLVQWIWGGFSIDNATLTRFFAFHFLLPFLIVGLTLIHLLFLHETGSNNPMGLNSDMDKISFHPYFSYKDLLGFFLMIILLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILMLIPMLHTSKQRSNIFRPMTQFLFWTLVANAIILTWIGGQPVEQPFILVGQIASVTYFSLFLIIIPLTGWWENKMLN
+
+	ostrich          ---MAPNIRKSHPLLKIINNSLIDLPSPSNISAWWNFGSLLGICLITQILTGLLLAMHYTADTTLAFSSVAHTCRNVQYGWFIRNLHANGASFFFICIYLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWAWGGFSVDNPTLTRFFALHFLLPFVIAGITLVHLTFLHESGSNNPLGIISHCDKIPFHPYFSLKDILGFTLMFIPLLSLAFFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPLLHKSKQRSMTFRPLSQLLFWFLVANLLILTWIGSQPVEHPFIIIGQVASFTYFLILLVLFPAIAALENKMI-
+
+	Pig              ----MTNIRKSHPLMKIINNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLFIHVGRGLYYGSYMFLETWNIGVVLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIITALAAVHLLFLHETGSNNPTGISSDMDKIPFHPYYTIKDILGALFMMLILLILVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILMPMLHTSKQRGMMFRPLSQCLFWMLVADLITLTWIGGQPVEHPFIIIGQLASILYFLIILVLMPITSIIENNLLK
+
+	Man              ----MTPMRKINPLMKLINHSFIDLPTPSNISAWWNFGSLLGACLILQITTGLFLAMHYSPDASTAFSSIAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYSETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGYSVDSPTLTRFFTFHFILPFIIATLAALHLLFLHETGSNNPLGITSHSDKITFHPYYTIKDTLGLLLFLLSLMTLTLFSPDLLGDPDNYTLANPLNTPPHIKPEWYFLFAYTILRSVPNKLGGVLALLLSILILAMIPILHMSKQQSMMFRPLSQSLYWLLAADLLILTWIGGQPVSYPFTIIGQVASVLYFTTILILMPTISLIENKMLK
+
+	Fly              ---MHKPLRNSHPLFKIANNALVDLPAPINISSWWNFGSLLGLCLIIQILTGLFLAMHYTADVNLAFYSVNHICRDVNYGWLLRTLHANGASFFFICIYLHIGRGIYYGSYLFTPTWLVGVIILFLVMGTAFMGYVLPWGQMSFWGATVITNLLSAIPYLGMDLVQWLWGGFAVDNATLTRFFTFHFILPFIVLAMTMIHLLFLHQTGSNNPIGLNSNIDKIPFHPYFTFKDIVGFIVMIFILISLVLISPNLLGDPDNFIPANPLVTPAHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILMILPFYNLSKFRGIQFYPINQILFWSMLVTVILLTWIGARPVEEPYVLIGQILTIIYFLYYLINPLVTKWWDNLLN-
+
+	Frog             --LMAPNIRKSHPLIKIINNSFIDLPTPSNISSLWNFGSLLGVCLIAQIITGLFLAMHYTADTSMAFSSVAHICFDVNYGLLIRNLHANGLSFFFICIYLHIGRGLYYGSFLYKETWNIGVILLFLVMATAFVGYVLPWGQMSFWGATVITNLLSAKPYIGNVLVQWSLGGFSVDNATLTRFFAFHFLLPFIIAGASILHLLFLHETGSTNPTGLNSDPDKVPFHPYFSYKDLLGFLIMLTALTLLAMFSPNLLGDPDNFTPANPLITPPHIKPEWYFLFAYAILRSMN-KLGGVLALVLSILILALMPLLHTSKQRSLMFRPFTQIMFWALVADTLILTWIGGQPVEDPYTMIGQLASVIYFSIFIIMFPLMGWVENKLLN
+
+	cow              ----MTNIRKSHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLYMHVGRGLYYGSYTFLETWNIGVILLLTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMAIAMVHLLFLHETGSNNPTGISSDVDKIPFHPYYTIKDILGALLLILALMLLVLFAPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILALIPLLHTSKQRSMMFRPLSQCLFWALVADLLTLTWIGGQPVEHPYITIGQLASVLYFLLILVLMPTAGTIENKLLK
+
+	mouse            ----MTNMRKTHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQIITGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGLYYGSYTFMETWNIGVLLLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDILGILIMFLILMTLVLFFPDMLGDPDNYMPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALMPFLHTSKQRSLMFRPITQILYWILVANLLILTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIIEDKMLK
+
+	amphioxus        ---MSGPLRKHHPLLKVVNHSVIDLPVPSNISVMWNFGSLLGLCLVSQILTGLFLAMHYTADVNLAFSSVAHICRDVNYGWLLRNLHANGASFMFICLYMHIGRGLYYGSYFYRETWNIGVMLLVLTMATAFLGYVLPWGQMSFWGATVITNLFSAIPYLGPDLVQWLWGGFSVDNATLTRFFAFHFFLPFMIAGLSVVHLLFLHQTGANNPTGLAGDVDKVPFHAYFSYKDVVGFVVLLAGLVFIALFSPNLLTDPENYIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVVALAMSIVVLFFMPFVHSSRQTSHNFRPLAQVLFWLMVVNVLLLTWLGGQPVEYPYIFLGQAASVIYFVNILLLIPIVGYVENKLL-
+
+	Mosquito         ---MFKPIRKTHPLISIANNALVDLPAPSNISAWWNFGSLLGLCLMLQILTGLFLAMHYAADIETAFNSVNHICRDVNNGWFLRICHANGASFFFACLFIHVGRGVYYESYLYHMTWNTGVIILFLTMATGFLGYVLPWGQMSFWGATVITNLLSAVPYLGMDLVQWIWGGFAVDNATLTRFFTFHFIFPFIILALMMIHLLFLHQTGSNNPLGLNSNVDKIPFHPYFIYKDIFGFIVFLWILVTFIWKFNYLLMDPENFIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILLILPFTHSSKFRGLQFYPLNQILFWNMVIVASLLTWIGARPVEDPYILTGQILTVLYFSYFIINPLLAKFWDKLLN-
+
+	p_urchin         ---MLGPLRKEHPIFRILKSTFVDLPLPSKLSIWWKFGSLLGLCLMTQILTGLFLAMHYTADISLAFSSASHMCRDVNYGWLLRKVHAKGASLFFICMYCHMGRGLYYGGSNKMETWKVGVILFLVTVLTAFVGYVLVWGRMSFWAATVIANLVTAVPCVGTTIVQWLWGGFSVDNATLTRFFAFHFLFPFIMAALAMIDLVFLHNSGANNPVGLKSNYDKAPFHIYYTTKDTVGFMALIAALFVLALLFPCALKDPEKFIPANPLSHPPHMQPEWYFLFAYAILRSIPNKLGGVMALVAAMLVLFLMPLLKTSKKESNSFRPLSQATFWMLVATFFVLTWMGSQPVEQPFVLMGQMASLLYFSLFMFGFPLVSSLEKKMMF
+
+	S_urchin         IKIMAAPLRKEHPIFRILKSTFVDLPLPSNLSIWWNSGSLLGLCLVVQMLTGMFLAMHYTADITLAFSSVMHILRDVNYGWFLRYVHAKGVSLFFICMYCHMGRGLYYGSYKKIETWKVGVILFLVTILTAFMGYVLVWGQMSFWAATVITNLVSAIPYMGTIMVQWLWGGFSVDKATLTRFFPFHFLFPFMMAALAVMHLVFLHNSGANNPFAFKSNYDKAPFHIYFTTKDTVGFILLVAALFSLALLFPGALKDPEKFIPANPLVTPPHIQPEWYFLFAYAILRSIPNKLGGVIALVAAMLVLFLMPLLNTSKKESNSFRPLSQAAFWLLVAHLFMLTWMGSQPVEYPYVLLGQVASVLYFSLFMFGFPMVSSMENKIMF
+
+
+;
+
+		BLOCKID WM1148c08509e0;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  location;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y z )  GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = Amino_acids;
+	MATRIX
+	Lamprey           (? ? ?) (? ? ?) (? ? ?) (22.224 -9.668 17.52) (22.584 -9.432 13.672) (19.596 -7.388 12.448) (20.432 -4.54 14.864) (16.876 -3.428 14.072) (15.284 -6.116 16.228) (17.732 -5.752 19.14) (17.716 -1.984 19.856) (15.188 -1.076 22.644) (13.552 1.612 20.476) (13.812 0.428 16.884) (12.544 -2.944 18.092) (9.428 -1.028 19.1) (9.044 0.348 15.596) (10.136 -2.744 13.672) (7.44 -4.52 15.676) (4.656 -2.056 14.932) (5.168 -0.828 11.4) (7.376 -3.576 9.98) (7.588 -7.32 10.648) (4.172 -6.8 [...]
+	Alligator         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Blue_Whale        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fin_whale         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	dog               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Carassi           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	white_rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Chrysem           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	crow              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	carp              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	possum            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	donkey            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	horse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	chicken           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Halicho           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Hippo             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	gibbon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Kangaroo          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	smooth_dog_fish   (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Myoxus            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	trout             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	platypus          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	sheep             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	baboon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pelomed           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	seal_vitulina     (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Polypterus        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	lung_fish         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Skate             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Rat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Black_Rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Salmon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Scyliorhinus      (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Spiny_dog_fish    (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	ostrich           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pig               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Man               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fly               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Frog              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cow               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	mouse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	amphioxus         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Mosquito          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	p_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	S_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+
+;
+		BLOCKID WM1148c08517b0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-cytochromeBHydro.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Lamprey,
+		2 Alligator,
+		3 Blue_Whale,
+		4 Fin_whale,
+		5 dog,
+		6 Carassi,
+		7 white_rhino,
+		8 Chrysem,
+		9 crow,
+		10 carp,
+		11 possum,
+		12 donkey,
+		13 horse,
+		14 cat,
+		15 chicken,
+		16 Halicho,
+		17 Hippo,
+		18 gibbon,
+		19 Kangaroo,
+		20 smooth_dog_fish,
+		21 Myoxus,
+		22 trout,
+		23 platypus,
+		24 sheep,
+		25 baboon,
+		26 Pelomed,
+		27 seal_vitulina,
+		28 Polypterus,
+		29 lung_fish,
+		30 Skate,
+		31 Rat,
+		32 Black_Rhino,
+		33 Salmon,
+		34 Scyliorhinus,
+		35 Spiny_dog_fish,
+		36 ostrich,
+		37 Pig,
+		38 Man,
+		39 Fly,
+		40 Frog,
+		41 cow,
+		42 mouse,
+		43 amphioxus,
+		44 Mosquito,
+		45 p_urchin,
+		46 S_urchin;
+	TREE true = ((((1,((((((((2,(9,(15,36))),(8,26)),((((((((((3,4),17),37),(24,41)),((7,32),(12,13))),((5,(16,27)),14)),((18,38),25)),(21,(31,42))),(11,19)),23)),40),29),28),((6,10),(22,33))),(((20,34),35),30))),43),(45,46)),(39,44));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Amino_acids)  =  universal:  1 -  382;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                             unord PolyTcount =                             MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Amino_acids)  =  unord:  1 -  382;
+TYPESET * UNTITLED  (CHARACTERS = location)  =  Squared:  1 -  382;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Amino_acids)  =  'Mk1 (est.)':  1 -  382;
+ProbModelSet * UNTITLED  (CHARACTERS = location)  =  Brownian_default:  1 -  382;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5749286926902316461 WM1148c0850785;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7273041429729163753 WM1148c08509e0;
+			checksum 0 2913214590 WM1148c08509e0;
+			setID 1 1052710308229948178 WM1148c08517b0;
+			checksum 1 3995003137 WM1148c08517b0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 591 283;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7273041429729163753 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 620 238;
+					setLocation 21 418;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 [...]
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #7273041429729163753;
+				endTell;
+			endTell;
+			setTaxa #5749286926902316461;
+			axesSame;
+			setValues  #mesquite.molec.MeanValueLinked.MeanValueLinked;
+			showColors on;
+			setColorValues  #mesquite.molec.SiteProperty.SiteProperty;
+			tell It;
+				setProperty  #mesquite.molec.AAHydrophobicity.AAHydrophobicity;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 617 594;
+					setLocation 655 31;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 7;
+					toggleJoin on;
+					toggleThickJoin on;
+					toggleLastToFirst off;
+					toggleShowDots off;
+					movingWindowSize 5;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-cytochromeBlinked.nex';
+			setPrevFileName '06-cytochromeB.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 591 266;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The colors now show average (across taxa) hydrophobicity of the amino acids at each site, averaged over a moving window of size 5.  There is a band of hydrophobic regions across the middle.^n^nIf character are selected in the character matrix editor, they become selected in the plot of the molecule, and vice versa.  Try selecting regions of the molecule by clicking and dragging in the plot.  Try also selecting characters in the character matrix editor using the arrow  [...]
+				setTitle Cytochrome_B;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/08-cytochromeBlinked.nex b/Resources/examples/Molecular/08-cytochromeBlinked.nex
new file mode 100755
index 0000000..026b316
--- /dev/null
+++ b/Resources/examples/Molecular/08-cytochromeBlinked.nex
@@ -0,0 +1,438 @@
+#NEXUS
+[written Sat Jun 07 12:30:33 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=46;
+	TAXLABELS
+		Lamprey Alligator Blue_Whale Fin_whale dog Carassi white_rhino Chrysem crow carp possum donkey horse cat chicken Halicho Hippo gibbon Kangaroo smooth_dog_fish Myoxus trout platypus sheep baboon Pelomed seal_vitulina Polypterus lung_fish Skate Rat Black_Rhino Salmon Scyliorhinus Spiny_dog_fish ostrich Pig Man Fly Frog cow mouse amphioxus Mosquito p_urchin S_urchin 
+	;
+	BLOCKID WM1148c0d0cc56;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Amino_acids;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = location;
+	MATRIX
+	Lamprey          -SHQPSIIRKTHPLLSLGNSMLVDLPSPANISAWWNFGSLLSLCLILQIITGLILAMHYTANTELAFSSVMHICRDVNNGWLMRNLHANGASMFFICIYAHIGRGIYYGSYLYKETWNVGVILFALTAATAFVGYVLPWGQMSFWGATVITNLISAMPYVGNDIVVWLWGGFSVSNATLTRFFTFHFILPFILAAMTMIHIMFLHQTGSSNPMGINSNLDKIQFHPYFSFKDILGFVILLGILFMISLLAPNALGEPDNFIYANPLSTPPHIKPEWYFLFAYAILRSVPNKLGGVVALAAAIMILLIIPFTHTSKQRGMQFRPLAQITFWILIADLALLTWLGGEPAEYPFILMTQIASTVYFMIFILVFPILGYLENKMLL
+
+	Alligator        ---MTHQLRKSHPIIKLINRSLIDLPTPSNISAWWNFGSLLGLTLLIQILTGFFLMMHFSSSDTLAFSSVSYTSREVWFGWLIRNLHTNGASLFFMFIFLHIGRGLYYTSYLHESTWNIGVIMLLLLMATAFMGYVLPWGQMSFWGATVITNLLSATPYVGSTVVPWIWGGPSVDNATLTRFTALHFLLPFALLASLITHLIFLHERGSFNPLGISPNADKIPFHPYFTMKDALGAALAASSLLILALYLPALLGDPENFTPANSMITPTHIKPEWYFLFAYAILRSIPNKLGGVLAMFSSILVLFLMPALHTAKQQPMSMRPMSQLLFWALTLDFLLLTWIGGQPVNPPYILIGQTASLFYFIIILILMPMAGLLENKMVE
+
+	Blue_Whale       ----MTNIRKTHPLMKIINDAFIDLPTPSNISSWWNFGSLLGLCLIVQILTGLFLAMHYTPDTMTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLYAHMGRGLYYGSHAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYYTIKDILGALLLILTLLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLALIPMLHTSKQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYVIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Fin_whale        ----MTNIRKTHPLMKIVNDAFVDLPTPSNISSWWNFGSLLGLCLIMQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYAHMGRGLYYGSYAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYHTIKDILGALLLILILLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILILAFIPMLHTSNQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYMIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	dog              ----MTNIRKTHPLAKIVNNSFIDLPAPSNISAWWNFGSLLGVCLILQILTGLFLAMHYTSDTATAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFLHVGRGLYYGSYVFMETWNIGIVLLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAMVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGALLLLLILMSLVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAFIPLLHTSKQRSMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFIIIGQVASILYFTILLILMPTVSVIENNLLK
+
+	Carassi          ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFIIAAATVIHLLFLHETGSNNPIGLNSDADKISFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLVLFPLAGWLENKALK
+
+	white_rhino      ----MTNIRKSHPLIKIINHSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTPDTMTAFSSVAHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGIYYGSYTFLETWNIGVILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGILLLILALLALVLFSPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILTLLIIPFLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFTLILVLMPLAGIIENNLLK
+
+	Chrysem          ---MTMNHRKTHPLTKIINNSFIDLPSPSNISAWWNFGSLLGTCLILQTITGIFLAMHYSPDISLAFSSVAHITRDVQYGWLIRNMHANGASLFFMCIYLHIGRGLYYGSYLYKETWNTGIILLLLTMATAFMGYVLPWGQMSFWGATVITNLLSAIPFIGNTLVQWIWGGFSVDNATLTRFFTLHFLLPFTIMGLTMVHLLFLHETGSNNPTGLNSNTDKIPFHPYFSYKDLLGVILMLTLLLTLTLFSPNLLGDPDNFTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLFLMPALHTSKQRTTQFRPLTQTLFWSFIANLLVLTWIGGQPVENPFITIGQVASILYFSTLLILIPIAGVIENKML-
+
+	crow             ---MGLNLRKNHPLLKIINNSLIDLPTPSNISAWWNFGSLLGLCLIMQIITGLLLAMHYTADTSLAFASVAHMCRDVQFGWLIRNLHANGASFFFICIYLHIGRGFYYGSYLNKETWNIGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWLWGGFSVDNPTLTRFFAFHFLLPFVIAGLTLVHLTFLHETGSNNPLGIPSDCDKIPFHPYYSIKDLLGFALMLIPLITLALFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLVLFLIPLLHVSKQRSMTFRPLSQILFWTLVADLLILTWVGSQPVEHPFIIIGQLASFAYFAIILILFPVVSALENKILK
+
+	carp             ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNVHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFVIAAATIIHLLFLHETGSNNPIGLNSDADKVSFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLIFMPLAGWLENKALK
+
+	possum           ----MTNIRKTHPLMKIINDSFIDLPTPSNISAWWNFGSLLGVCLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNIHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGSTLVEWIWGGFSVDKATLTRFFAFHFILPFIILAMVVVHLLFLHETGSSNPTGLDPNSDKIPFHPYYTMKDILGLFLMIIILLSLAMFSPDLLGDPDNFTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILVLLIIPMLHTSTQRSMAFRPISQTLFWMLTANLIILTWIGGQPVEQPYITIGQWASISYFTIIIILMPLAGMLENYMLK
+
+	donkey           ----MTNIRKSHPLIKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVIVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLVLLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	horse            ----MTNIRKSHPLIKIINHSFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVVVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLILLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	cat              ----MTNIRKSHPLIKIINHSFIDLPAPSNISAWWNFGSLLGVCLTLQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGMYYGSYTFSETWNIGIMLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTELVEWIWGGFSVDKATLTRFFGFHFILPFIISALAGVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGLLVLVLTLMLLVLFSPDLLGDPDNYIPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIIPILHTSKQRGMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFITIGQLASILYFSTLLILMPISGIIENRLLK
+
+	chicken          ---MAPNIRKSHPLLKMINNSLIDLPAPSNISAWWNFGSLLAVCLMTQILTGLLLAMHYTADTSLAFSSVAHTCRNVQYGWLIRNLHANGASFFFICIFLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGHTLVEWAWGGFSVDNPTLTRFFALHFLLPFAIAGITIIHLTFLHESGSNNPLGISSDSDKIPFHPYYSFKDILGLTLMLTPFLTLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPFLHKSKQRTMTFRPLSQTLFWLLVANLLILTWIGSQPVEHPFIIIGQMASLSYFTILLILFPTIGTLENKMLN
+
+	Halicho          ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTIMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGFSVDKATLTGFFAFHFILPFVVLALAAVHLLFLHETGSNNPSGIMPDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILILAIVPLLHTSKQRGMMFRPISQCLFWLLVADLLTLTWIGGQPVEHPYITIGQLASILYFMILLVLMPIASIIENNILK
+
+	Hippo            ----MTNIRKSHPLMKIINDAFVDLPAPSNISSWWNFGSLLGVCLILQILTGLFLAMHYTPDTLTAFSSVTHICRDVNYGWVIRYMHANGASIFFICLFTHVGRGLYYGSHTFLETWNIGVILLLTTMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFVITALAIVHLLFLHETGSNNPTGIPSNADKIPFHPYYTIKDILGILLLMTTLLTLTLFAPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALALSILILALIPMLHTSKQRSLMFRPLSQCLFWALIADLLTLTWIGGQPVEHPFIIIGQVASILYFLLILVLMPVAGIIENKLLK
+
+	gibbon           ----MTPLRKTNPLMKLINHSLIDLPAPSNISMWWNFGSLLGACLILQIITGLFLAMHYTPDASTAFSSVAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYLETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTDLVQWVWGGYSVDNATLTRFFTFHFILPFIITALAALHLLFLHETGSNNPLGISSQPDKIAFHPYYTIKDILGLFLLLLMLMSLVLFSPDLLGDPSNYTQANPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALLLSILILAMIPALHTAKQQSMMFRPLSQLTYWLLVMNLLILTWIGGQPVSYPFITIGQVASALYFTTILVLMPAASLIENKMLK
+
+	Kangaroo         ----MTNLRKSHPLIKIVNHSFIDLPAPSNISAWWNFGSLLGACLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNLHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYVGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVLVHLLFLHETGSNNPSGINPDSDKIPFHPYYTIKDALGLMLMLFILLMLALFSPDMLGDPDNFSPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILILLIIPLLHTSKQRSLMFRPISQTLFWILTANLITLTWIGGQPVEQPFIIIGQLASISYFLLIIILMPLAGLFENYMLE
+
+	smooth_dog_fish  ---MATNIRKTHPLLKIMNHALVDLPAPSNISLWWNFGSLMGLCLLIQILTGLFLAMHYTADISMAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYLHIARGLYYGSYLNKETWDIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNMLVQWIWGGFSVDNATLTRFFAFHFLLPFLIMALSIIHLLFLHESGSNNPLGINSDADKVSFHPYFSYKDLLGFFVMIFLLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKQRSIIFRPLTQIFFWVLVANSIILTWIGGQPVEQPFIMVGQIASISYFALFLIIMPFISWCENKILS
+
+	Myoxus           ----MTIIRKSHPLIKIINHSFIDLPTPSNISAWWIFGSLLGACLGIQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGMYYGSYMFIETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALVMVHLLFLHETGSNNPSGLNSDTDKIPFHPYYTIKDILGLLLLIFLLMTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAILPVLQFSKQRSMMFRPLSQCPFWILTADLFTLTWIGGQPVEHPFIIIGQLASILYFSIILFFLPTFSLLENKLLK
+
+	trout            ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWALVADMLILTWIGGMPVEHPFIIIGQVASVIYFTIFLVLSPLAGWAEIKALQ
+
+	platypus         ----MNNLRKTHPLIKIVNHSFIDLPTPSNISSWWNFGSLLGLCLIIQILTGLFLAMHYTSDTSTAFSSVAHICRDVNYGWLIRYMHANGASLFFMCIFLHIGRGLYYGSYTQTETWNIGVVLLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFVIAALAVIHLLFLHETGSNNPSGLNSDPDKIPFHPYYSVKDLVGFFMTILVLLTLVLFTPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILVPLLHTSYQRGLAFRPLTQMLFWILVTDLLTLTWIGGQPVEQPFIIIGQLASILYFLLITTLIPLTGLLENDLLK
+
+	sheep            ----MINIRKTHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFMHVGRGLYYGSYTFLETWNIGVILLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFIFPFIIAALAMVHLLFLHETGSNNPTGIPSDTDKIPFHPYYTIKDILGAILLILILMLLVLFTPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILVLVIMPLLHTSKQRSMMFRPISQCMFWILVADLLTLTWIGGQPVEHPYIIIGQLASIMYFLIILVMMPVASIIENNLLK
+
+	baboon           ----MTPMRKSNPIMKMINHSFIDLPTPSNISIWWNFGSLLATCLILQIITGLFLAMHYSPDTSSAFSSIAHITRDVNYGWTIRYLHANGASMLFICLFLHVGRGLYYGSYLLLKTWNIGIMLLLMTMTTAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTNLVQWVWGGPAIDNPTLMRFFTLHFILPFGIVALTIVHLLFLHETGSNNPCGISSDPDKITFHPYYTTKDILGVAPLLLALMTLTLFSPDLLNDPDNYTPADPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALFLSILILAAIPMLHKSKQQSMMFRPLSQFLFWLLATTLLTLTWIGSQPVIQPLTTIGQVASMVYFLTTLVLMPLAAQVENNLLK
+
+	Pelomed          ---MGTLHLKQNPLLKITNKSLINLPSPSNISAWWNFGSLLGMCLILQITTGIFLAMHYTPNITTAFSSVAHITRDVQYGWLLRGLHANGASIFFICLYFHIGRGIYYGSFLNKKTWYTGIMLLFLTMATAFMGYILPWGQMSFWGATVITNLLSAIPYMGTNLVQWIWGGFSVDNATLTRFFTLHFLTPFIISSLTTIHLLLLHEKGSNNPTGLNSNPDKIPFHPYFSYKDLLGVNLLMIGLLTLTLFLPNLLTDPENFTPANPLSTPKHIKPEWYFLFAYAILRSIPNKLGGVLALLSSVTILFIMPTLHTSKQRSATFRPFTQILFWSPTADLVILTWIGAQPVEDPFIMIGQTASVFYFTLILLLIPLAAILENKLLD
+
+	seal_vitulina    ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYVGTDLVQWIWGGFSVDKATLTRFFAFHFILPFVVLALDAVHLLFLHETGSNNPSGIMSDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPPNPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIMPLLHTSKQRGMMFRPISQCLFWFLVADLLTLTWIGGQPVEHPYITVGQLASILYFTILLVLMPIASIIENNILK
+
+	Polypterus       ----MAIIRKTHPLAKIINSAFIDLPAPSNISSWWNMGSLLGLCLIAQIITGLFLAMHYVSDINSAFSSVAHICRDVNYGWLIRNFHANGASLFFICIYLHIARGLYYGSYLYTETWNMGVILLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAIPYIGDTLVQWIWGGFSVDKPTLTRFFAFHFILPFAIAAASLVHIVFLHETGSNNPVGINSDADQIPFHPYFTFKDLLGFIILLLIIIMLALLSPNLLNDPGNFTPANPLITPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPLLHTSKIRSATFRPLFKITLWILAADVLILTWIGGQPVEDPYIIIGQAASILYFLIFLVLMPLSGWLENKMLN
+
+	lung_fish        ---MATNIRKTHPLLKIVNNSLIDLPTPSNISAWWNFGSLLGFCLITQILTGLFLAMHYTADTSTAFSSIAHIARDVNYGWLLRNIHANGASMFFICIYIHIGRGIYYGSFLYTETWNIGVVLFLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYLGDTLVQWIWGGFSVDNATLTRFFAFHFLLPFIISAMTAAHFLFLHETGSNNPTGLNSNLDKISFHPYFTMKDLLGFLMLASFLCLLALFSPNLLGDPENFTPANPLVTPTHIKPEWYFLFAYAILRSIPNKLGGVLALMASILILFIIPFLHRAKQRTMSYRPLSQFMFWLLTADMLILTWIGGQPVEHPFILIGQIASATYFLLFLLLFPLITSLENKLLY
+
+	Skate            ---MTTNIRKTHPLFKIINSSLIDLPTPVNISIWWNYGSLLGLCLIIQILTGLFLAMHYTPDIASAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYIHMARGFYYGSYLNKETWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNILVEWIWGGFSVDNATLTRFFAFHFLFPFLIVALTLLHLLFLHEMGSNNPTGLNSNTDKIPFHPYFSYKDLLGFFILGLLLTLLALFTPNLLGDTENFIPADPLLTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPMLHTSKQRSATFRPITQILFWTLLTNTIILTWIGGQPVEQPFIIIGQIASVIYFLLFLILLPLAGWWENKILN
+
+	Rat              ----MTNIRKSHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYLQANGASMFFICLFLHVGRGLYYGSYTFLETWNIGIILLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDLLGVFMLLLFLMTLV--FPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVVALILSILILAFLPFLHTSKQRSLTFRPITQILYWILVANLLVLTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIVEDKMLK
+
+	Black_Rhino      ----MTNIRKSHPLVKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWMIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGALLLILVLLILVLFFPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILLLIPYLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFSLILVLMPLAGIIENNLLK
+
+	Salmon           ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWTLVADMLILTWIGGMPVEHPFIIIGQIASVIYFTIFLVLAPLAGWAENKALE
+
+	Scyliorhinus     ---MATNIRKTHPLLKIVNHALIDLPAPSNISVWWNFGSLLGLCLIMQIITGLFLAMHYTADISMAFSSVIHISRDVNYGWLMRNIHAYGASFFFICIYLHIARGLYYGSYLNKEAWNIGVVLLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNLLVQWIWGGFSVDNATLTRFFAFHFLLPFLILALSVIHILFLHETGANNPMGINSNTDKISFHPYFSYKDLFGFLIVITLLATLALFMPNLLGDAENFIPANPLVTPLHIQPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKLRSNIFRPLTQIFFWSLVTNAIILTWIGGQPVEQPFIMVGQIASVAYFSLFLFVIPITSWCENKFLS
+
+	Spiny_dog_fish   ---MTTNIRKTHPLIKIVNHALVDLPSPSNISIWWNFGSLLGLCLIIQILTGLFLAMHYTADISTAFSSVVHICRDVNYGWLIRNIHANGASLFFICVYLHIARGLYYGSYLFKEAWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGDMLVQWIWGGFSIDNATLTRFFAFHFLLPFLIVGLTLIHLLFLHETGSNNPMGLNSDMDKISFHPYFSYKDLLGFFLMIILLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILMLIPMLHTSKQRSNIFRPMTQFLFWTLVANAIILTWIGGQPVEQPFILVGQIASVTYFSLFLIIIPLTGWWENKMLN
+
+	ostrich          ---MAPNIRKSHPLLKIINNSLIDLPSPSNISAWWNFGSLLGICLITQILTGLLLAMHYTADTTLAFSSVAHTCRNVQYGWFIRNLHANGASFFFICIYLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWAWGGFSVDNPTLTRFFALHFLLPFVIAGITLVHLTFLHESGSNNPLGIISHCDKIPFHPYFSLKDILGFTLMFIPLLSLAFFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPLLHKSKQRSMTFRPLSQLLFWFLVANLLILTWIGSQPVEHPFIIIGQVASFTYFLILLVLFPAIAALENKMI-
+
+	Pig              ----MTNIRKSHPLMKIINNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLFIHVGRGLYYGSYMFLETWNIGVVLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIITALAAVHLLFLHETGSNNPTGISSDMDKIPFHPYYTIKDILGALFMMLILLILVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILMPMLHTSKQRGMMFRPLSQCLFWMLVADLITLTWIGGQPVEHPFIIIGQLASILYFLIILVLMPITSIIENNLLK
+
+	Man              ----MTPMRKINPLMKLINHSFIDLPTPSNISAWWNFGSLLGACLILQITTGLFLAMHYSPDASTAFSSIAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYSETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGYSVDSPTLTRFFTFHFILPFIIATLAALHLLFLHETGSNNPLGITSHSDKITFHPYYTIKDTLGLLLFLLSLMTLTLFSPDLLGDPDNYTLANPLNTPPHIKPEWYFLFAYTILRSVPNKLGGVLALLLSILILAMIPILHMSKQQSMMFRPLSQSLYWLLAADLLILTWIGGQPVSYPFTIIGQVASVLYFTTILILMPTISLIENKMLK
+
+	Fly              ---MHKPLRNSHPLFKIANNALVDLPAPINISSWWNFGSLLGLCLIIQILTGLFLAMHYTADVNLAFYSVNHICRDVNYGWLLRTLHANGASFFFICIYLHIGRGIYYGSYLFTPTWLVGVIILFLVMGTAFMGYVLPWGQMSFWGATVITNLLSAIPYLGMDLVQWLWGGFAVDNATLTRFFTFHFILPFIVLAMTMIHLLFLHQTGSNNPIGLNSNIDKIPFHPYFTFKDIVGFIVMIFILISLVLISPNLLGDPDNFIPANPLVTPAHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILMILPFYNLSKFRGIQFYPINQILFWSMLVTVILLTWIGARPVEEPYVLIGQILTIIYFLYYLINPLVTKWWDNLLN-
+
+	Frog             --LMAPNIRKSHPLIKIINNSFIDLPTPSNISSLWNFGSLLGVCLIAQIITGLFLAMHYTADTSMAFSSVAHICFDVNYGLLIRNLHANGLSFFFICIYLHIGRGLYYGSFLYKETWNIGVILLFLVMATAFVGYVLPWGQMSFWGATVITNLLSAKPYIGNVLVQWSLGGFSVDNATLTRFFAFHFLLPFIIAGASILHLLFLHETGSTNPTGLNSDPDKVPFHPYFSYKDLLGFLIMLTALTLLAMFSPNLLGDPDNFTPANPLITPPHIKPEWYFLFAYAILRSMN-KLGGVLALVLSILILALMPLLHTSKQRSLMFRPFTQIMFWALVADTLILTWIGGQPVEDPYTMIGQLASVIYFSIFIIMFPLMGWVENKLLN
+
+	cow              ----MTNIRKSHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLYMHVGRGLYYGSYTFLETWNIGVILLLTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMAIAMVHLLFLHETGSNNPTGISSDVDKIPFHPYYTIKDILGALLLILALMLLVLFAPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILALIPLLHTSKQRSMMFRPLSQCLFWALVADLLTLTWIGGQPVEHPYITIGQLASVLYFLLILVLMPTAGTIENKLLK
+
+	mouse            ----MTNMRKTHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQIITGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGLYYGSYTFMETWNIGVLLLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDILGILIMFLILMTLVLFFPDMLGDPDNYMPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALMPFLHTSKQRSLMFRPITQILYWILVANLLILTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIIEDKMLK
+
+	amphioxus        ---MSGPLRKHHPLLKVVNHSVIDLPVPSNISVMWNFGSLLGLCLVSQILTGLFLAMHYTADVNLAFSSVAHICRDVNYGWLLRNLHANGASFMFICLYMHIGRGLYYGSYFYRETWNIGVMLLVLTMATAFLGYVLPWGQMSFWGATVITNLFSAIPYLGPDLVQWLWGGFSVDNATLTRFFAFHFFLPFMIAGLSVVHLLFLHQTGANNPTGLAGDVDKVPFHAYFSYKDVVGFVVLLAGLVFIALFSPNLLTDPENYIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVVALAMSIVVLFFMPFVHSSRQTSHNFRPLAQVLFWLMVVNVLLLTWLGGQPVEYPYIFLGQAASVIYFVNILLLIPIVGYVENKLL-
+
+	Mosquito         ---MFKPIRKTHPLISIANNALVDLPAPSNISAWWNFGSLLGLCLMLQILTGLFLAMHYAADIETAFNSVNHICRDVNNGWFLRICHANGASFFFACLFIHVGRGVYYESYLYHMTWNTGVIILFLTMATGFLGYVLPWGQMSFWGATVITNLLSAVPYLGMDLVQWIWGGFAVDNATLTRFFTFHFIFPFIILALMMIHLLFLHQTGSNNPLGLNSNVDKIPFHPYFIYKDIFGFIVFLWILVTFIWKFNYLLMDPENFIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILLILPFTHSSKFRGLQFYPLNQILFWNMVIVASLLTWIGARPVEDPYILTGQILTVLYFSYFIINPLLAKFWDKLLN-
+
+	p_urchin         ---MLGPLRKEHPIFRILKSTFVDLPLPSKLSIWWKFGSLLGLCLMTQILTGLFLAMHYTADISLAFSSASHMCRDVNYGWLLRKVHAKGASLFFICMYCHMGRGLYYGGSNKMETWKVGVILFLVTVLTAFVGYVLVWGRMSFWAATVIANLVTAVPCVGTTIVQWLWGGFSVDNATLTRFFAFHFLFPFIMAALAMIDLVFLHNSGANNPVGLKSNYDKAPFHIYYTTKDTVGFMALIAALFVLALLFPCALKDPEKFIPANPLSHPPHMQPEWYFLFAYAILRSIPNKLGGVMALVAAMLVLFLMPLLKTSKKESNSFRPLSQATFWMLVATFFVLTWMGSQPVEQPFVLMGQMASLLYFSLFMFGFPLVSSLEKKMMF
+
+	S_urchin         IKIMAAPLRKEHPIFRILKSTFVDLPLPSNLSIWWNSGSLLGLCLVVQMLTGMFLAMHYTADITLAFSSVMHILRDVNYGWFLRYVHAKGVSLFFICMYCHMGRGLYYGSYKKIETWKVGVILFLVTILTAFMGYVLVWGQMSFWAATVITNLVSAIPYMGTIMVQWLWGGFSVDKATLTRFFPFHFLFPFMMAALAVMHLVFLHNSGANNPFAFKSNYDKAPFHIYFTTKDTVGFILLVAALFSLALLFPGALKDPEKFIPANPLVTPPHIQPEWYFLFAYAILRSIPNKLGGVIALVAAMLVLFLMPLLNTSKKESNSFRPLSQAAFWLLVAHLFMLTWMGSQPVEYPYVLLGQVASVLYFSLFMFGFPMVSSMENKIMF
+
+
+;
+
+		BLOCKID WM1148c0d0d070;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  location;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y z )  GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = Amino_acids;
+	MATRIX
+	Lamprey           (? ? ?) (? ? ?) (? ? ?) (22.224 -9.668 17.52) (22.584 -9.432 13.672) (19.596 -7.388 12.448) (20.432 -4.54 14.864) (16.876 -3.428 14.072) (15.284 -6.116 16.228) (17.732 -5.752 19.14) (17.716 -1.984 19.856) (15.188 -1.076 22.644) (13.552 1.612 20.476) (13.812 0.428 16.884) (12.544 -2.944 18.092) (9.428 -1.028 19.1) (9.044 0.348 15.596) (10.136 -2.744 13.672) (7.44 -4.52 15.676) (4.656 -2.056 14.932) (5.168 -0.828 11.4) (7.376 -3.576 9.98) (7.588 -7.32 10.648) (4.172 -6.8 [...]
+	Alligator         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Blue_Whale        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fin_whale         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	dog               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Carassi           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	white_rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Chrysem           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	crow              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	carp              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	possum            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	donkey            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	horse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	chicken           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Halicho           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Hippo             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	gibbon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Kangaroo          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	smooth_dog_fish   (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Myoxus            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	trout             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	platypus          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	sheep             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	baboon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pelomed           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	seal_vitulina     (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Polypterus        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	lung_fish         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Skate             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Rat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Black_Rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Salmon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Scyliorhinus      (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Spiny_dog_fish    (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	ostrich           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pig               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Man               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fly               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Frog              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cow               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	mouse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	amphioxus         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Mosquito          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	p_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	S_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+
+;
+		BLOCKID WM1148c0d0dd90;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-cytochromeBlinked.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 Lamprey,
+		2 Alligator,
+		3 Blue_Whale,
+		4 Fin_whale,
+		5 dog,
+		6 Carassi,
+		7 white_rhino,
+		8 Chrysem,
+		9 crow,
+		10 carp,
+		11 possum,
+		12 donkey,
+		13 horse,
+		14 cat,
+		15 chicken,
+		16 Halicho,
+		17 Hippo,
+		18 gibbon,
+		19 Kangaroo,
+		20 smooth_dog_fish,
+		21 Myoxus,
+		22 trout,
+		23 platypus,
+		24 sheep,
+		25 baboon,
+		26 Pelomed,
+		27 seal_vitulina,
+		28 Polypterus,
+		29 lung_fish,
+		30 Skate,
+		31 Rat,
+		32 Black_Rhino,
+		33 Salmon,
+		34 Scyliorhinus,
+		35 Spiny_dog_fish,
+		36 ostrich,
+		37 Pig,
+		38 Man,
+		39 Fly,
+		40 Frog,
+		41 cow,
+		42 mouse,
+		43 amphioxus,
+		44 Mosquito,
+		45 p_urchin,
+		46 S_urchin;
+	TREE true = ((((1,((((((((2,(9,(15,36))),(8,26)),((((((((((3,4),17),37),(24,41)),((7,32),(12,13))),((5,(16,27)),14)),((18,38),25)),(21,(31,42))),(11,19)),23)),40),29),28),((6,10),(22,33))),(((20,34),35),30))),43),(45,46)),(39,44));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Amino_acids)  =  universal:  1 -  382;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                         unord PolyTcount =                         MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Amino_acids)  =  unord:  1 -  382;
+TYPESET * UNTITLED  (CHARACTERS = location)  =  Squared:  1 -  382;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Amino_acids)  =  'Mk1 (est.)':  1 -  382;
+ProbModelSet * UNTITLED  (CHARACTERS = location)  =  Brownian_default:  1 -  382;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5749286926902316461 WM1148c0d0cc56;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7273041429729163753 WM1148c0d0d070;
+			checksum 0 2913214590 WM1148c0d0d070;
+			setID 1 1052710308229948178 WM1148c0d0dd90;
+			checksum 1 3995003137 WM1148c0d0dd90;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 578 354;
+			setLocation 12 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7273041429729163753 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 599 316;
+					setLocation 631 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 [...]
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #1052710308229948178 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 599 306;
+					setLocation 633 431;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-cytochromeBscatter.nex';
+			setPrevFileName '07-cytochromeBHydro.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 578 337;
+					setLocation 12 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'How were the plots of cytochrome B in the previous example made?  At present, the way to do this in Mesquite is a bit convoluted.  The trick is to subvert the characters scattergram, showing position in space of the amino acids as X and Y axes, then coloring the amino acids by the desired statistic.  The position in space is stored as a second matrix (below right) linked to the protein sequence matrix (above right).^n^nTo reproduce this yourself, first make the molecu [...]
+				setTitle Cytochrome_B;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Molecular/09-cytochromeBscatter.nex b/Resources/examples/Molecular/09-cytochromeBscatter.nex
new file mode 100755
index 0000000..86bf93d
--- /dev/null
+++ b/Resources/examples/Molecular/09-cytochromeBscatter.nex
@@ -0,0 +1,453 @@
+#NEXUS
+[written Sat Jun 07 12:30:47 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=46;
+	TAXLABELS
+		Lamprey Alligator Blue_Whale Fin_whale dog Carassi white_rhino Chrysem crow carp possum donkey horse cat chicken Halicho Hippo gibbon Kangaroo smooth_dog_fish Myoxus trout platypus sheep baboon Pelomed seal_vitulina Polypterus lung_fish Skate Rat Black_Rhino Salmon Scyliorhinus Spiny_dog_fish ostrich Pig Man Fly Frog cow mouse amphioxus Mosquito p_urchin S_urchin 
+	;
+	BLOCKID WM1148c0dd3617;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Amino_acids;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = location;
+	MATRIX
+	Lamprey          -SHQPSIIRKTHPLLSLGNSMLVDLPSPANISAWWNFGSLLSLCLILQIITGLILAMHYTANTELAFSSVMHICRDVNNGWLMRNLHANGASMFFICIYAHIGRGIYYGSYLYKETWNVGVILFALTAATAFVGYVLPWGQMSFWGATVITNLISAMPYVGNDIVVWLWGGFSVSNATLTRFFTFHFILPFILAAMTMIHIMFLHQTGSSNPMGINSNLDKIQFHPYFSFKDILGFVILLGILFMISLLAPNALGEPDNFIYANPLSTPPHIKPEWYFLFAYAILRSVPNKLGGVVALAAAIMILLIIPFTHTSKQRGMQFRPLAQITFWILIADLALLTWLGGEPAEYPFILMTQIASTVYFMIFILVFPILGYLENKMLL
+
+	Alligator        ---MTHQLRKSHPIIKLINRSLIDLPTPSNISAWWNFGSLLGLTLLIQILTGFFLMMHFSSSDTLAFSSVSYTSREVWFGWLIRNLHTNGASLFFMFIFLHIGRGLYYTSYLHESTWNIGVIMLLLLMATAFMGYVLPWGQMSFWGATVITNLLSATPYVGSTVVPWIWGGPSVDNATLTRFTALHFLLPFALLASLITHLIFLHERGSFNPLGISPNADKIPFHPYFTMKDALGAALAASSLLILALYLPALLGDPENFTPANSMITPTHIKPEWYFLFAYAILRSIPNKLGGVLAMFSSILVLFLMPALHTAKQQPMSMRPMSQLLFWALTLDFLLLTWIGGQPVNPPYILIGQTASLFYFIIILILMPMAGLLENKMVE
+
+	Blue_Whale       ----MTNIRKTHPLMKIINDAFIDLPTPSNISSWWNFGSLLGLCLIVQILTGLFLAMHYTPDTMTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLYAHMGRGLYYGSHAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYYTIKDILGALLLILTLLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLALIPMLHTSKQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYVIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	Fin_whale        ----MTNIRKTHPLMKIVNDAFVDLPTPSNISSWWNFGSLLGLCLIMQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYAHMGRGLYYGSYAFRETWNIGVILLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAIVHLIFLHETGSNNPTGIPSDMDKIPFHPYHTIKDILGALLLILILLMLTLFAPDLLGDPDNYTPANPLSTPAHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILILAFIPMLHTSNQRSMMFRPFSQFLFWVLVADLLTLTWIGGQPVEHPYMIVGQLASILYFLLILVLMPVTSLIENKLMK
+
+	dog              ----MTNIRKTHPLAKIVNNSFIDLPAPSNISAWWNFGSLLGVCLILQILTGLFLAMHYTSDTATAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFLHVGRGLYYGSYVFMETWNIGIVLLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAMVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGALLLLLILMSLVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAFIPLLHTSKQRSMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFIIIGQVASILYFTILLILMPTVSVIENNLLK
+
+	Carassi          ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFIIAAATVIHLLFLHETGSNNPIGLNSDADKISFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLVLFPLAGWLENKALK
+
+	white_rhino      ----MTNIRKSHPLIKIINHSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTPDTMTAFSSVAHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGIYYGSYTFLETWNIGVILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGILLLILALLALVLFSPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILTLLIIPFLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFTLILVLMPLAGIIENNLLK
+
+	Chrysem          ---MTMNHRKTHPLTKIINNSFIDLPSPSNISAWWNFGSLLGTCLILQTITGIFLAMHYSPDISLAFSSVAHITRDVQYGWLIRNMHANGASLFFMCIYLHIGRGLYYGSYLYKETWNTGIILLLLTMATAFMGYVLPWGQMSFWGATVITNLLSAIPFIGNTLVQWIWGGFSVDNATLTRFFTLHFLLPFTIMGLTMVHLLFLHETGSNNPTGLNSNTDKIPFHPYFSYKDLLGVILMLTLLLTLTLFSPNLLGDPDNFTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLLSILVLFLMPALHTSKQRTTQFRPLTQTLFWSFIANLLVLTWIGGQPVENPFITIGQVASILYFSTLLILIPIAGVIENKML-
+
+	crow             ---MGLNLRKNHPLLKIINNSLIDLPTPSNISAWWNFGSLLGLCLIMQIITGLLLAMHYTADTSLAFASVAHMCRDVQFGWLIRNLHANGASFFFICIYLHIGRGFYYGSYLNKETWNIGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWLWGGFSVDNPTLTRFFAFHFLLPFVIAGLTLVHLTFLHETGSNNPLGIPSDCDKIPFHPYYSIKDLLGFALMLIPLITLALFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLVLFLIPLLHVSKQRSMTFRPLSQILFWTLVADLLILTWVGSQPVEHPFIIIGQLASFAYFAIILILFPVVSALENKILK
+
+	carp             ----MASLRKTHPLIKIANDALVDLPTPSNISAWWNFGSLLGLCLITQILTGLFLAMHYTSDISTAFSSVTHICRDVNYGWLIRNVHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLVMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYMGDMLVQWIWGGFSVDNATLTRFFAFHFLLPFVIAAATIIHLLFLHETGSNNPIGLNSDADKVSFHPYFSYKDLLGFVIMLLALTLLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPLLHTSKQRGLTFRPITQFLFWTLVADMIILTWIGGMPVEHPFIIIGQIASVLYFALFLIFMPLAGWLENKALK
+
+	possum           ----MTNIRKTHPLMKIINDSFIDLPTPSNISAWWNFGSLLGVCLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNIHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGSTLVEWIWGGFSVDKATLTRFFAFHFILPFIILAMVVVHLLFLHETGSSNPTGLDPNSDKIPFHPYYTMKDILGLFLMIIILLSLAMFSPDLLGDPDNFTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILVLLIIPMLHTSTQRSMAFRPISQTLFWMLTANLIILTWIGGQPVEQPYITIGQWASISYFTIIIILMPLAGMLENYMLK
+
+	donkey           ----MTNIRKSHPLIKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVIVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLVLLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	horse            ----MTNIRKSHPLIKIINHSFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVVVHLLFLHETGSNNPSGIPSDMDKIPFHPYYTIKDILGLLLLILLLLTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALIPTLHMSKQRSMMFRPLSQCVFWLLVADLLTLTWIGGQPVEHPYVIIGQLASILYFSLILIFMPLASTIENNLLK
+
+	cat              ----MTNIRKSHPLIKIINHSFIDLPAPSNISAWWNFGSLLGVCLTLQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGMYYGSYTFSETWNIGIMLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTELVEWIWGGFSVDKATLTRFFGFHFILPFIISALAGVHLLFLHETGSNNPSGITSDSDKIPFHPYYTIKDILGLLVLVLTLMLLVLFSPDLLGDPDNYIPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIIPILHTSKQRGMMFRPLSQCLFWLLVADLLTLTWIGGQPVEHPFITIGQLASILYFSTLLILMPISGIIENRLLK
+
+	chicken          ---MAPNIRKSHPLLKMINNSLIDLPAPSNISAWWNFGSLLAVCLMTQILTGLLLAMHYTADTSLAFSSVAHTCRNVQYGWLIRNLHANGASFFFICIFLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGHTLVEWAWGGFSVDNPTLTRFFALHFLLPFAIAGITIIHLTFLHESGSNNPLGISSDSDKIPFHPYYSFKDILGLTLMLTPFLTLALFSPNLLGDPENFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPFLHKSKQRTMTFRPLSQTLFWLLVANLLILTWIGSQPVEHPFIIIGQMASLSYFTILLILFPTIGTLENKMLN
+
+	Halicho          ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTIMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGFSVDKATLTGFFAFHFILPFVVLALAAVHLLFLHETGSNNPSGIMPDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILILAIVPLLHTSKQRGMMFRPISQCLFWLLVADLLTLTWIGGQPVEHPYITIGQLASILYFMILLVLMPIASIIENNILK
+
+	Hippo            ----MTNIRKSHPLMKIINDAFVDLPAPSNISSWWNFGSLLGVCLILQILTGLFLAMHYTPDTLTAFSSVTHICRDVNYGWVIRYMHANGASIFFICLFTHVGRGLYYGSHTFLETWNIGVILLLTTMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFVITALAIVHLLFLHETGSNNPTGIPSNADKIPFHPYYTIKDILGILLLMTTLLTLTLFAPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALALSILILALIPMLHTSKQRSLMFRPLSQCLFWALIADLLTLTWIGGQPVEHPFIIIGQVASILYFLLILVLMPVAGIIENKLLK
+
+	gibbon           ----MTPLRKTNPLMKLINHSLIDLPAPSNISMWWNFGSLLGACLILQIITGLFLAMHYTPDASTAFSSVAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYLETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTDLVQWVWGGYSVDNATLTRFFTFHFILPFIITALAALHLLFLHETGSNNPLGISSQPDKIAFHPYYTIKDILGLFLLLLMLMSLVLFSPDLLGDPSNYTQANPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALLLSILILAMIPALHTAKQQSMMFRPLSQLTYWLLVMNLLILTWIGGQPVSYPFITIGQVASALYFTTILVLMPAASLIENKMLK
+
+	Kangaroo         ----MTNLRKSHPLIKIVNHSFIDLPAPSNISAWWNFGSLLGACLIIQILTGLFLAMHYTSDTLTAFSSVAHICRDVNYGWLIRNLHANGASMFFMCLFLHVGRGIYYGSYLYKETWNIGVILLLTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYVGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIITALVLVHLLFLHETGSNNPSGINPDSDKIPFHPYYTIKDALGLMLMLFILLMLALFSPDMLGDPDNFSPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLASILILLIIPLLHTSKQRSLMFRPISQTLFWILTANLITLTWIGGQPVEQPFIIIGQLASISYFLLIIILMPLAGLFENYMLE
+
+	smooth_dog_fish  ---MATNIRKTHPLLKIMNHALVDLPAPSNISLWWNFGSLMGLCLLIQILTGLFLAMHYTADISMAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYLHIARGLYYGSYLNKETWDIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNMLVQWIWGGFSVDNATLTRFFAFHFLLPFLIMALSIIHLLFLHESGSNNPLGINSDADKVSFHPYFSYKDLLGFFVMIFLLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKQRSIIFRPLTQIFFWVLVANSIILTWIGGQPVEQPFIMVGQIASISYFALFLIIMPFISWCENKILS
+
+	Myoxus           ----MTIIRKSHPLIKIINHSFIDLPTPSNISAWWIFGSLLGACLGIQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGMYYGSYMFIETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALVMVHLLFLHETGSNNPSGLNSDTDKIPFHPYYTIKDILGLLLLIFLLMTLVLFSPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVFSILILAILPVLQFSKQRSMMFRPLSQCPFWILTADLFTLTWIGGQPVEHPFIIIGQLASILYFSIILFFLPTFSLLENKLLK
+
+	trout            ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWALVADMLILTWIGGMPVEHPFIIIGQVASVIYFTIFLVLSPLAGWAEIKALQ
+
+	platypus         ----MNNLRKTHPLIKIVNHSFIDLPTPSNISSWWNFGSLLGLCLIIQILTGLFLAMHYTSDTSTAFSSVAHICRDVNYGWLIRYMHANGASLFFMCIFLHIGRGLYYGSYTQTETWNIGVVLLFTVMATAFVGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFVIAALAVIHLLFLHETGSNNPSGLNSDPDKIPFHPYYSVKDLVGFFMTILVLLTLVLFTPDLLGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILVPLLHTSYQRGLAFRPLTQMLFWILVTDLLTLTWIGGQPVEQPFIIIGQLASILYFLLITTLIPLTGLLENDLLK
+
+	sheep            ----MINIRKTHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLFMHVGRGLYYGSYTFLETWNIGVILLFATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFIFPFIIAALAMVHLLFLHETGSNNPTGIPSDTDKIPFHPYYTIKDILGAILLILILMLLVLFTPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILVLVIMPLLHTSKQRSMMFRPISQCMFWILVADLLTLTWIGGQPVEHPYIIIGQLASIMYFLIILVMMPVASIIENNLLK
+
+	baboon           ----MTPMRKSNPIMKMINHSFIDLPTPSNISIWWNFGSLLATCLILQIITGLFLAMHYSPDTSSAFSSIAHITRDVNYGWTIRYLHANGASMLFICLFLHVGRGLYYGSYLLLKTWNIGIMLLLMTMTTAFMGYVLPWGQMSFWGATVITNLLSAVPYIGTNLVQWVWGGPAIDNPTLMRFFTLHFILPFGIVALTIVHLLFLHETGSNNPCGISSDPDKITFHPYYTTKDILGVAPLLLALMTLTLFSPDLLNDPDNYTPADPLNTPPHIKPEWYFLFAYAILRSVPNKLGGVLALFLSILILAAIPMLHKSKQQSMMFRPLSQFLFWLLATTLLTLTWIGSQPVIQPLTTIGQVASMVYFLTTLVLMPLAAQVENNLLK
+
+	Pelomed          ---MGTLHLKQNPLLKITNKSLINLPSPSNISAWWNFGSLLGMCLILQITTGIFLAMHYTPNITTAFSSVAHITRDVQYGWLLRGLHANGASIFFICLYFHIGRGIYYGSFLNKKTWYTGIMLLFLTMATAFMGYILPWGQMSFWGATVITNLLSAIPYMGTNLVQWIWGGFSVDNATLTRFFTLHFLTPFIISSLTTIHLLLLHEKGSNNPTGLNSNPDKIPFHPYFSYKDLLGVNLLMIGLLTLTLFLPNLLTDPENFTPANPLSTPKHIKPEWYFLFAYAILRSIPNKLGGVLALLSSVTILFIMPTLHTSKQRSATFRPFTQILFWSPTADLVILTWIGAQPVEDPFIMIGQTASVFYFTLILLLIPLAAILENKLLD
+
+	seal_vitulina    ----MTNIRKTHPLMKIINNSFIDLPTPSNISAWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYLHANGASMFFICLYMHVGRGLYYGSYTFTETWNIGIILLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYVGTDLVQWIWGGFSVDKATLTRFFAFHFILPFVVLALDAVHLLFLHETGSNNPSGIMSDSDKIPFHPYYTIKDILGALLLILVLTLLVLFSPDLLGDPDNYIPPNPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVLSILVLAIMPLLHTSKQRGMMFRPISQCLFWFLVADLLTLTWIGGQPVEHPYITVGQLASILYFTILLVLMPIASIIENNILK
+
+	Polypterus       ----MAIIRKTHPLAKIINSAFIDLPAPSNISSWWNMGSLLGLCLIAQIITGLFLAMHYVSDINSAFSSVAHICRDVNYGWLIRNFHANGASLFFICIYLHIARGLYYGSYLYTETWNMGVILLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAIPYIGDTLVQWIWGGFSVDKPTLTRFFAFHFILPFAIAAASLVHIVFLHETGSNNPVGINSDADQIPFHPYFTFKDLLGFIILLLIIIMLALLSPNLLNDPGNFTPANPLITPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPLLHTSKIRSATFRPLFKITLWILAADVLILTWIGGQPVEDPYIIIGQAASILYFLIFLVLMPLSGWLENKMLN
+
+	lung_fish        ---MATNIRKTHPLLKIVNNSLIDLPTPSNISAWWNFGSLLGFCLITQILTGLFLAMHYTADTSTAFSSIAHIARDVNYGWLLRNIHANGASMFFICIYIHIGRGIYYGSFLYTETWNIGVVLFLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYLGDTLVQWIWGGFSVDNATLTRFFAFHFLLPFIISAMTAAHFLFLHETGSNNPTGLNSNLDKISFHPYFTMKDLLGFLMLASFLCLLALFSPNLLGDPENFTPANPLVTPTHIKPEWYFLFAYAILRSIPNKLGGVLALMASILILFIIPFLHRAKQRTMSYRPLSQFMFWLLTADMLILTWIGGQPVEHPFILIGQIASATYFLLFLLLFPLITSLENKLLY
+
+	Skate            ---MTTNIRKTHPLFKIINSSLIDLPTPVNISIWWNYGSLLGLCLIIQILTGLFLAMHYTPDIASAFSSVVHICRDVNYGWLIRNIHANGASLFFICIYIHMARGFYYGSYLNKETWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNILVEWIWGGFSVDNATLTRFFAFHFLFPFLIVALTLLHLLFLHEMGSNNPTGLNSNTDKIPFHPYFSYKDLLGFFILGLLLTLLALFTPNLLGDTENFIPADPLLTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILILMLVPMLHTSKQRSATFRPITQILFWTLLTNTIILTWIGGQPVEQPFIIIGQIASVIYFLLFLILLPLAGWWENKILN
+
+	Rat              ----MTNIRKSHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQILTGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYLQANGASMFFICLFLHVGRGLYYGSYTFLETWNIGIILLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDLLGVFMLLLFLMTLV--FPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVVALILSILILAFLPFLHTSKQRSLTFRPITQILYWILVANLLVLTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIVEDKMLK
+
+	Black_Rhino      ----MTNIRKSHPLVKIINHSFIDLPTPSNISSWWNFGSLLGICLILQILTGLFLAMHYTPDTTTAFSSVTHICRDVNYGWMIRYLHANGASMFFICLFIHVGRGLYYGSYTFLETWNIGIILLFTLMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIILALAITHLLFLHETGSNNPSGIPSNMDKIPFHPYYTIKDILGALLLILVLLILVLFFPDILGDPDNYTPANPLSTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILLLIPYLHTSKQRSMMFRPLSQCMFWLLVADLLTLTWIGGQPVEHPFIIIGQLASILYFSLILVLMPLAGIIENNLLK
+
+	Salmon           ----MANLRKTHPLLKIANDALVDLPAPSNISVWWNFGSLLGLCLATQILTGLFLAMHYTSDISTAFSSVCHICRDVSYGWLIRNIHANGASFFFICIYMHIARGLYYGSYLYKETWNIGVVLLLLTMMTAFVGYVLPWGQMSFWGATVITNLLSAVPYVGGALVQWIWGGFSVDNATLTRFFAFHFLFPFVIAAATVLHLLFLHETGSNNPAGINSDADKISFHPYFSYKDLLGFVAMLLGLTSLALFAPNLLGDPDNFTPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSILVLMVVPILHTSKQRGLTFRPLTQFLFWTLVADMLILTWIGGMPVEHPFIIIGQIASVIYFTIFLVLAPLAGWAENKALE
+
+	Scyliorhinus     ---MATNIRKTHPLLKIVNHALIDLPAPSNISVWWNFGSLLGLCLIMQIITGLFLAMHYTADISMAFSSVIHISRDVNYGWLMRNIHAYGASFFFICIYLHIARGLYYGSYLNKEAWNIGVVLLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGNLLVQWIWGGFSVDNATLTRFFAFHFLLPFLILALSVIHILFLHETGANNPMGINSNTDKISFHPYFSYKDLFGFLIVITLLATLALFMPNLLGDAENFIPANPLVTPLHIQPEWYFLFAYAILRSIPNKLGGVLALLFSIFILLLVPLLHTSKLRSNIFRPLTQIFFWSLVTNAIILTWIGGQPVEQPFIMVGQIASVAYFSLFLFVIPITSWCENKFLS
+
+	Spiny_dog_fish   ---MTTNIRKTHPLIKIVNHALVDLPSPSNISIWWNFGSLLGLCLIIQILTGLFLAMHYTADISTAFSSVVHICRDVNYGWLIRNIHANGASLFFICVYLHIARGLYYGSYLFKEAWNIGVILLFLLMATAFVGYVLPWGQMSFWGATVITNLLSAFPYIGDMLVQWIWGGFSIDNATLTRFFAFHFLLPFLIVGLTLIHLLFLHETGSNNPMGLNSDMDKISFHPYFSYKDLLGFFLMIILLALLALFLPNLLGDAENFIPANPLVTPPHIKPEWYFLFAYAILRSIPNKLGGVLALLFSIFILMLIPMLHTSKQRSNIFRPMTQFLFWTLVANAIILTWIGGQPVEQPFILVGQIASVTYFSLFLIIIPLTGWWENKMLN
+
+	ostrich          ---MAPNIRKSHPLLKIINNSLIDLPSPSNISAWWNFGSLLGICLITQILTGLLLAMHYTADTTLAFSSVAHTCRNVQYGWFIRNLHANGASFFFICIYLHIGRGLYYGSYLYKETWNTGVILLLTLMATAFVGYVLPWGQMSFWGATVITNLFSAIPYIGQTLVEWAWGGFSVDNPTLTRFFALHFLLPFVIAGITLVHLTFLHESGSNNPLGIISHCDKIPFHPYFSLKDILGFTLMFIPLLSLAFFSPNLLGDPENFTPANPLATPPHIKPEWYFLFAYAILRSIPNKLGGVLALAASVLILFLIPLLHKSKQRSMTFRPLSQLLFWFLVANLLILTWIGSQPVEHPFIIIGQVASFTYFLILLVLFPAIAALENKMI-
+
+	Pig              ----MTNIRKSHPLMKIINNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWVIRYLHANGASMFFICLFIHVGRGLYYGSYMFLETWNIGVVLLFTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVEWIWGGFSVDKATLTRFFAFHFILPFIITALAAVHLLFLHETGSNNPTGISSDMDKIPFHPYYTIKDILGALFMMLILLILVLFSPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALVASILILILMPMLHTSKQRGMMFRPLSQCLFWMLVADLITLTWIGGQPVEHPFIIIGQLASILYFLIILVLMPITSIIENNLLK
+
+	Man              ----MTPMRKINPLMKLINHSFIDLPTPSNISAWWNFGSLLGACLILQITTGLFLAMHYSPDASTAFSSIAHITRDVNYGWIIRYLHANGASMFFICLFLHIGRGLYYGSFLYSETWNIGIILLLATMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTDLVQWIWGGYSVDSPTLTRFFTFHFILPFIIATLAALHLLFLHETGSNNPLGITSHSDKITFHPYYTIKDTLGLLLFLLSLMTLTLFSPDLLGDPDNYTLANPLNTPPHIKPEWYFLFAYTILRSVPNKLGGVLALLLSILILAMIPILHMSKQQSMMFRPLSQSLYWLLAADLLILTWIGGQPVSYPFTIIGQVASVLYFTTILILMPTISLIENKMLK
+
+	Fly              ---MHKPLRNSHPLFKIANNALVDLPAPINISSWWNFGSLLGLCLIIQILTGLFLAMHYTADVNLAFYSVNHICRDVNYGWLLRTLHANGASFFFICIYLHIGRGIYYGSYLFTPTWLVGVIILFLVMGTAFMGYVLPWGQMSFWGATVITNLLSAIPYLGMDLVQWLWGGFAVDNATLTRFFTFHFILPFIVLAMTMIHLLFLHQTGSNNPIGLNSNIDKIPFHPYFTFKDIVGFIVMIFILISLVLISPNLLGDPDNFIPANPLVTPAHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILMILPFYNLSKFRGIQFYPINQILFWSMLVTVILLTWIGARPVEEPYVLIGQILTIIYFLYYLINPLVTKWWDNLLN-
+
+	Frog             --LMAPNIRKSHPLIKIINNSFIDLPTPSNISSLWNFGSLLGVCLIAQIITGLFLAMHYTADTSMAFSSVAHICFDVNYGLLIRNLHANGLSFFFICIYLHIGRGLYYGSFLYKETWNIGVILLFLVMATAFVGYVLPWGQMSFWGATVITNLLSAKPYIGNVLVQWSLGGFSVDNATLTRFFAFHFLLPFIIAGASILHLLFLHETGSTNPTGLNSDPDKVPFHPYFSYKDLLGFLIMLTALTLLAMFSPNLLGDPDNFTPANPLITPPHIKPEWYFLFAYAILRSMN-KLGGVLALVLSILILALMPLLHTSKQRSLMFRPFTQIMFWALVADTLILTWIGGQPVEDPYTMIGQLASVIYFSIFIIMFPLMGWVENKLLN
+
+	cow              ----MTNIRKSHPLMKIVNNAFIDLPAPSNISSWWNFGSLLGICLILQILTGLFLAMHYTSDTTTAFSSVTHICRDVNYGWIIRYMHANGASMFFICLYMHVGRGLYYGSYTFLETWNIGVILLLTVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTNLVEWIWGGFSVDKATLTRFFAFHFILPFIIMAIAMVHLLFLHETGSNNPTGISSDVDKIPFHPYYTIKDILGALLLILALMLLVLFAPDLLGDPDNYTPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALAFSILILALIPLLHTSKQRSMMFRPLSQCLFWALVADLLTLTWIGGQPVEHPYITIGQLASVLYFLLILVLMPTAGTIENKLLK
+
+	mouse            ----MTNMRKTHPLFKIINHSFIDLPAPSNISSWWNFGSLLGVCLMVQIITGLFLAMHYTSDTMTAFSSVTHICRDVNYGWLIRYMHANGASMFFICLFLHVGRGLYYGSYTFMETWNIGVLLLFAVMATAFMGYVLPWGQMSFWGATVITNLLSAIPYIGTTLVEWIWGGFSVDKATLTRFFAFHFILPFIIAALAIVHLLFLHETGSNNPTGLNSDADKIPFHPYYTIKDILGILIMFLILMTLVLFFPDMLGDPDNYMPANPLNTPPHIKPEWYFLFAYAILRSIPNKLGGVLALILSILILALMPFLHTSKQRSLMFRPITQILYWILVANLLILTWIGGQPVEHPFIIIGQLASISYFSIILILMPISGIIEDKMLK
+
+	amphioxus        ---MSGPLRKHHPLLKVVNHSVIDLPVPSNISVMWNFGSLLGLCLVSQILTGLFLAMHYTADVNLAFSSVAHICRDVNYGWLLRNLHANGASFMFICLYMHIGRGLYYGSYFYRETWNIGVMLLVLTMATAFLGYVLPWGQMSFWGATVITNLFSAIPYLGPDLVQWLWGGFSVDNATLTRFFAFHFFLPFMIAGLSVVHLLFLHQTGANNPTGLAGDVDKVPFHAYFSYKDVVGFVVLLAGLVFIALFSPNLLTDPENYIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVVALAMSIVVLFFMPFVHSSRQTSHNFRPLAQVLFWLMVVNVLLLTWLGGQPVEYPYIFLGQAASVIYFVNILLLIPIVGYVENKLL-
+
+	Mosquito         ---MFKPIRKTHPLISIANNALVDLPAPSNISAWWNFGSLLGLCLMLQILTGLFLAMHYAADIETAFNSVNHICRDVNNGWFLRICHANGASFFFACLFIHVGRGVYYESYLYHMTWNTGVIILFLTMATGFLGYVLPWGQMSFWGATVITNLLSAVPYLGMDLVQWIWGGFAVDNATLTRFFTFHFIFPFIILALMMIHLLFLHQTGSNNPLGLNSNVDKIPFHPYFIYKDIFGFIVFLWILVTFIWKFNYLLMDPENFIPANPLVTPVHIQPEWYFLFAYAILRSIPNKLGGVIALVLSIAILLILPFTHSSKFRGLQFYPLNQILFWNMVIVASLLTWIGARPVEDPYILTGQILTVLYFSYFIINPLLAKFWDKLLN-
+
+	p_urchin         ---MLGPLRKEHPIFRILKSTFVDLPLPSKLSIWWKFGSLLGLCLMTQILTGLFLAMHYTADISLAFSSASHMCRDVNYGWLLRKVHAKGASLFFICMYCHMGRGLYYGGSNKMETWKVGVILFLVTVLTAFVGYVLVWGRMSFWAATVIANLVTAVPCVGTTIVQWLWGGFSVDNATLTRFFAFHFLFPFIMAALAMIDLVFLHNSGANNPVGLKSNYDKAPFHIYYTTKDTVGFMALIAALFVLALLFPCALKDPEKFIPANPLSHPPHMQPEWYFLFAYAILRSIPNKLGGVMALVAAMLVLFLMPLLKTSKKESNSFRPLSQATFWMLVATFFVLTWMGSQPVEQPFVLMGQMASLLYFSLFMFGFPLVSSLEKKMMF
+
+	S_urchin         IKIMAAPLRKEHPIFRILKSTFVDLPLPSNLSIWWNSGSLLGLCLVVQMLTGMFLAMHYTADITLAFSSVMHILRDVNYGWFLRYVHAKGVSLFFICMYCHMGRGLYYGSYKKIETWKVGVILFLVTILTAFMGYVLVWGQMSFWAATVITNLVSAIPYMGTIMVQWLWGGFSVDKATLTRFFPFHFLFPFMMAALAVMHLVFLHNSGANNPFAFKSNYDKAPFHIYFTTKDTVGFILLVAALFSLALLFPGALKDPEKFIPANPLVTPPHIQPEWYFLFAYAILRSIPNKLGGVIALVAAMLVLFLMPLLNTSKKESNSFRPLSQAAFWLLVAHLFMLTWMGSQPVEYPYVLLGQVASVLYFSLFMFGFPMVSSMENKIMF
+
+
+;
+
+		BLOCKID WM1148c0dd38d0;
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  location;
+	DIMENSIONS  NCHAR=382;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y z )  GAP = - MISSING = ?;
+	OPTIONS  LINKCHARACTERS = Amino_acids;
+	MATRIX
+	Lamprey           (? ? ?) (? ? ?) (? ? ?) (22.224 -9.668 17.52) (22.584 -9.432 13.672) (19.596 -7.388 12.448) (20.432 -4.54 14.864) (16.876 -3.428 14.072) (15.284 -6.116 16.228) (17.732 -5.752 19.14) (17.716 -1.984 19.856) (15.188 -1.076 22.644) (13.552 1.612 20.476) (13.812 0.428 16.884) (12.544 -2.944 18.092) (9.428 -1.028 19.1) (9.044 0.348 15.596) (10.136 -2.744 13.672) (7.44 -4.52 15.676) (4.656 -2.056 14.932) (5.168 -0.828 11.4) (7.376 -3.576 9.98) (7.588 -7.32 10.648) (4.172 -6.8 [...]
+	Alligator         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Blue_Whale        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fin_whale         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	dog               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Carassi           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	white_rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Chrysem           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	crow              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	carp              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	possum            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	donkey            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	horse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	chicken           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Halicho           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Hippo             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	gibbon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Kangaroo          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	smooth_dog_fish   (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Myoxus            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	trout             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	platypus          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	sheep             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	baboon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pelomed           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	seal_vitulina     (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Polypterus        (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	lung_fish         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Skate             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Rat               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Black_Rhino       (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Salmon            (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Scyliorhinus      (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Spiny_dog_fish    (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	ostrich           (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Pig               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Man               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Fly               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Frog              (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	cow               (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	mouse             (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	amphioxus         (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	Mosquito          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	p_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+	S_urchin          (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) (? ? ?) ( [...]
+
+;
+		BLOCKID WM1148c0dd4740;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-cytochromeBscatter.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 Lamprey,
+		2 Alligator,
+		3 Blue_Whale,
+		4 Fin_whale,
+		5 dog,
+		6 Carassi,
+		7 white_rhino,
+		8 Chrysem,
+		9 crow,
+		10 carp,
+		11 possum,
+		12 donkey,
+		13 horse,
+		14 cat,
+		15 chicken,
+		16 Halicho,
+		17 Hippo,
+		18 gibbon,
+		19 Kangaroo,
+		20 smooth_dog_fish,
+		21 Myoxus,
+		22 trout,
+		23 platypus,
+		24 sheep,
+		25 baboon,
+		26 Pelomed,
+		27 seal_vitulina,
+		28 Polypterus,
+		29 lung_fish,
+		30 Skate,
+		31 Rat,
+		32 Black_Rhino,
+		33 Salmon,
+		34 Scyliorhinus,
+		35 Spiny_dog_fish,
+		36 ostrich,
+		37 Pig,
+		38 Man,
+		39 Fly,
+		40 Frog,
+		41 cow,
+		42 mouse,
+		43 amphioxus,
+		44 Mosquito,
+		45 p_urchin,
+		46 S_urchin;
+	TREE true = ((((1,((((((((2,(9,(15,36))),(8,26)),((((((((((3,4),17),37),(24,41)),((7,32),(12,13))),((5,(16,27)),14)),((18,38),25)),(21,(31,42))),(11,19)),23)),40),29),28),((6,10),(22,33))),(((20,34),35),30))),43),(45,46)),(39,44));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = Amino_acids)  =  universal:  1 -  382;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+OPTIONS DEFTYPE =                              unord PolyTcount =                              MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = Amino_acids)  =  unord:  1 -  382;
+TYPESET * UNTITLED  (CHARACTERS = location)  =  Squared:  1 -  382;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Amino_acids)  =  'Mk1 (est.)':  1 -  382;
+ProbModelSet * UNTITLED  (CHARACTERS = location)  =  Brownian_default:  1 -  382;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5749286926902316461 WM1148c0dd3617;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7273041429729163753 WM1148c0dd38d0;
+			checksum 0 2913214590 WM1148c0dd38d0;
+			setID 1 1052710308229948178 WM1148c0dd4740;
+			checksum 1 3995003137 WM1148c0dd4740;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 511 334;
+			setLocation 8 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #7273041429729163753;
+				endTell;
+			endTell;
+			setTaxa #5749286926902316461;
+			axesSame;
+			setValues  #mesquite.molec.MeanValueLinked.MeanValueLinked;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 470 365;
+					setLocation 549 472;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 7;
+					toggleJoin on;
+					toggleThickJoin on;
+					toggleLastToFirst off;
+					toggleShowDots off;
+					movingWindowSize 5;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00-introduction.nex';
+			setPrevFileName '08-cytochromeBlinked.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 511 317;
+					setLocation 8 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Once the linked matrix of xyz amino acid positions is entered, they can be used to build the plot by using New Scattergram for Characters (Analysis menu).  Here are shown the scattergram in various stages of construction.^n^nIndicate you want the scattergram to be for stored characters, indicate same value for the two axes, choose "Mean Value of Character (Linked Matrix)".  Select the molecular sequence matrix as the matrix to be used.  This will result in the plot ab [...]
+				setTitle Cytochrome_B;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Return_to_Intro;
+			endTell;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #7273041429729163753;
+				endTell;
+			endTell;
+			setTaxa #5749286926902316461;
+			axesSame;
+			setValues  #mesquite.molec.MeanValueLinked.MeanValueLinked;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 466 334;
+					setLocation 553 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.charts.CharsScattergram.CharsScattergram;
+		tell It;
+			getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+			tell It;
+				setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+				tell It;
+					setDataSet #7273041429729163753;
+				endTell;
+			endTell;
+			setTaxa #5749286926902316461;
+			axesSame;
+			setValues  #mesquite.molec.MeanValueLinked.MeanValueLinked;
+			showColors on;
+			setColorValues  #mesquite.molec.SiteProperty.SiteProperty;
+			tell It;
+				setProperty  #mesquite.molec.AAHydrophobicity.AAHydrophobicity;
+			endTell;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 488 361;
+					setLocation 37 465;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 8;
+					toggleJoin on;
+					toggleThickJoin on;
+					toggleLastToFirst off;
+					toggleShowDots off;
+					movingWindowSize 5;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/00-introduction.nex b/Resources/examples/Multivariate_Continuous/00-introduction.nex
new file mode 100755
index 0000000..db5e698
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/00-introduction.nex
@@ -0,0 +1,52 @@
+#NEXUS
+[written Sun May 04 15:25:47 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Example files for the Rhetenor morphometrics package by Eric Dyreson and Wayne Maddison^n^nThe files linked to this one illustrate some of the calculations available in the Rhetenor package of modules for morphometrics analyses.  The morphometrics components in the Mesquite system are still in their infancy, and could be much enhanced by efforts of other programmers (this is an invitation).^n^nTo learn more about the current state of Rhetenor, select "Rhetenor package [...]
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 700 464;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '01-wingsPlot.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 447;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 12;
+					setActive;
+				setExplanation 'Example files for the Rhetenor morphometrics package by Eric Dyreson and Wayne Maddison^n^nThe files linked to this one illustrate some of the calculations available in the Rhetenor package of modules for morphometrics analyses.  The morphometrics components in the Mesquite system are still in their infancy, and could be much enhanced by efforts of other programmers (this is an invitation).^n^nTo learn more about the current state of Rhetenor, select "Rhetenor package [...]
+				setTitle Rhetenor_examples;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+				addFileLink Return_to_main_Introduction  '../Introduction.nex';
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/01-wingsPlot.nex b/Resources/examples/Multivariate_Continuous/01-wingsPlot.nex
new file mode 100755
index 0000000..782baf4
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/01-wingsPlot.nex
@@ -0,0 +1,327 @@
+#NEXUS
+[written Sun May 04 15:25:54 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=48;
+	TAXLABELS
+		nig1 nig2 nig3 nig4 nig5 nig6 nig7 nig8 nig9 nig10 nig11 nig12 met1 met2 met3 met4 met5 met6 met7 met8 met9 met10 met11 met12 moj1 moj2 moj3 moj4 moj5 moj6 moj7 moj8 moj9 moj10 moj11 moj12 pac1 pac2 pac3 pac4 pac5 pac6 pac7 pac8 pac9 pac10 pac11 pac12 
+	;
+	BLOCKID WM114cbd3ad085;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "01-wingsPlot.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 V1,
+		2 V2,
+		3 ACV,
+		4 PCV ; 
+	MATRIX
+	nig1    1.784 1.994 0.1007 0.2488
+	nig2    1.662 1.946 0.0882 0.2503
+	nig3    1.92 2.244 0.0678 0.2707
+	nig4    1.838 2.107 0.0678 0.2653
+	nig5    1.843 2.111 0.0784 0.2791
+	nig6    1.953 2.194 0.0671 0.2696
+	nig7    1.782 2.03 0.0795 0.2678
+	nig8    1.792 2.137 0.0852 0.2694
+	nig9    1.889 2.203 0.0746 0.2575
+	nig10   1.836 2.092 0.0925 0.2592
+	nig11   1.877 2.13 0.0941 0.2696
+	nig12   1.826 2.133 0.0741 0.2751
+	met1    1.451 1.659 0.0805 0.2425
+	met2    1.672 1.949 0.0754 0.2687
+	met3    1.67 1.943 0.0745 0.2862
+	met4    1.783 2.037 0.1074 0.2612
+	met5    1.734 2.048 0.0814 0.2503
+	met6    1.624 1.858 0.0736 0.2555
+	met7    1.697 1.939 0.0871 0.2728
+	met8    1.695 1.979 0.0923 0.2748
+	met9    1.552 1.835 0.0674 0.2417
+	met10   1.7 1.994 0.0875 0.2781
+	met11   1.723 1.945 0.0808 0.2705
+	met12   1.688 1.987 0.0875 0.2847
+	moj1    1.19 1.298 0.0667 0.1871
+	moj2    1.209 1.336 0.06 0.1962
+	moj3    1.255 1.387 0.0806 0.2011
+	moj4    1.224 1.351 0.0666 0.1847
+	moj5    1.196 1.318 0.0596 0.176
+	moj6    1.188 1.345 0.074 0.1991
+	moj7    1.187 1.314 0.0696 0.1745
+	moj8    1.235 1.371 0.06 0.1877
+	moj9    1.153 1.29 0.0471 0.1688
+	moj10   1.208 1.352 0.0731 0.1818
+	moj11   1.177 1.29 0.0679 0.1777
+	moj12   1.226 1.363 0.06 0.1909
+	pac1    1.343 1.479 0.0821 0.1719
+	pac2    1.429 1.56 0.0731 0.2052
+	pac3    1.391 1.537 0.0731 0.2192
+	pac4    1.496 1.673 0.093 0.2283
+	pac5    1.347 1.514 0.0795 0.1978
+	pac6    1.311 1.449 0.062 0.1795
+	pac7    1.424 1.62 0.0682 0.21
+	pac8    1.411 1.596 0.0787 0.2128
+	pac9    1.338 1.502 0.0653 0.2077
+	pac10   1.449 1.618 0.0745 0.231
+	pac11   1.447 1.603 0.0787 0.2346
+	pac12   1.465 1.621 0.0765 0.214
+
+;
+		BLOCKID WM114cbd3ad1e0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "01-wingsPlot.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 nig1,
+		2 nig2,
+		3 nig3,
+		4 nig4,
+		5 nig5,
+		6 nig6,
+		7 nig7,
+		8 nig8,
+		9 nig9,
+		10 nig10,
+		11 nig11,
+		12 nig12,
+		13 met1,
+		14 met2,
+		15 met3,
+		16 met4,
+		17 met5,
+		18 met6,
+		19 met7,
+		20 met8,
+		21 met9,
+		22 met10,
+		23 met11,
+		24 met12,
+		25 moj1,
+		26 moj2,
+		27 moj3,
+		28 moj4,
+		29 moj5,
+		30 moj6,
+		31 moj7,
+		32 moj8,
+		33 moj9,
+		34 moj10,
+		35 moj11,
+		36 moj12,
+		37 pac1,
+		38 pac2,
+		39 pac3,
+		40 pac4,
+		41 pac5,
+		42 pac6,
+		43 pac7,
+		44 pac8,
+		45 pac9,
+		46 pac10,
+		47 pac11,
+		48 pac12;
+	TREE colored = (((1[%color = 5 ],(2[%color = 5 ],(3[%color = 5 ],(4[%color = 5 ],(5[%color = 5 ],(6[%color = 5 ],(7[%color = 5 ],(8[%color = 5 ],(9[%color = 5 ],(10[%color = 5 ],(11[%color = 5 ],12[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ],(13[%color = 8 ],(14[%color = 8 ],(15[%color = 8 ],(16[%color = 8 ],(17[%color = 8 ],(18[%color = 8 ],(19[%color = 8 ],(20[%co [...]
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL nig COLOR = (RGB 1.0 0.03137255 0.25882353) ;
+	TAXAGROUPLABEL met COLOR = (RGB 0.25882353 1.0 0.08627451) ;
+	TAXAGROUPLABEL moj COLOR = (RGB 1.0 0.62745098 0.05882353) ;
+	TAXAGROUPLABEL pac COLOR = (RGB 0.02745098 0.58431373 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+	TAXPARTITION species  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows data of Eric Dyreson for wing characteristics measured for specimens of four species of Drosophila.  The taxa are individual specimens, and they are grouped (by color) into four species.  (The grouping is done by a taxa partition, which can be done via the List of Taxa window).^n^nAbove right is a plot of character 2 versus character 1, which are obviously highly correlated because of their correlation with size.  This plot is phylogeny-free.';
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 208212565903807533 WM114cbd3ad085;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 124634251740354766 WM114cbd3ad1e0;
+			checksum 0 578547273 WM114cbd3ad1e0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 513 324;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #124634251740354766 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 493 470;
+					setLocation 18 371;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #208212565903807533;
+			endTell;
+			setTaxa #208212565903807533;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #124634251740354766;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 493 470;
+					setLocation 534 36;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '02-wingsPCA.nex';
+			setPrevFileName '00-introduction.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 513 307;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows data of Eric Dyreson for wing characteristics measured for specimens of four species of Drosophila.  The taxa are individual specimens, and they are grouped (by color) into four species.  (The grouping is done by a taxa partition, which can be done via the List of Taxa window).^n^nThe scattergram shows a plot of character 2 versus character 1, which are obviously highly correlated because of their correlation with size.  This plot is phylogeny-free.';
+				setTitle Raw_data;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/02-wingsPCA.nex b/Resources/examples/Multivariate_Continuous/02-wingsPCA.nex
new file mode 100755
index 0000000..d75530a
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/02-wingsPCA.nex
@@ -0,0 +1,372 @@
+#NEXUS
+[written Sun May 04 15:26:05 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=48;
+	TAXLABELS
+		nig1 nig2 nig3 nig4 nig5 nig6 nig7 nig8 nig9 nig10 nig11 nig12 met1 met2 met3 met4 met5 met6 met7 met8 met9 met10 met11 met12 moj1 moj2 moj3 moj4 moj5 moj6 moj7 moj8 moj9 moj10 moj11 moj12 pac1 pac2 pac3 pac4 pac5 pac6 pac7 pac8 pac9 pac10 pac11 pac12 
+	;
+	BLOCKID WM114cbd522e46;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "02-wingsPCA.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 V1,
+		2 V2,
+		3 ACV,
+		4 PCV ; 
+	MATRIX
+	nig1    1.784 1.994 0.1007 0.2488
+	nig2    1.662 1.946 0.0882 0.2503
+	nig3    1.92 2.244 0.0678 0.2707
+	nig4    1.838 2.107 0.0678 0.2653
+	nig5    1.843 2.111 0.0784 0.2791
+	nig6    1.953 2.194 0.0671 0.2696
+	nig7    1.782 2.03 0.0795 0.2678
+	nig8    1.792 2.137 0.0852 0.2694
+	nig9    1.889 2.203 0.0746 0.2575
+	nig10   1.836 2.092 0.0925 0.2592
+	nig11   1.877 2.13 0.0941 0.2696
+	nig12   1.826 2.133 0.0741 0.2751
+	met1    1.451 1.659 0.0805 0.2425
+	met2    1.672 1.949 0.0754 0.2687
+	met3    1.67 1.943 0.0745 0.2862
+	met4    1.783 2.037 0.1074 0.2612
+	met5    1.734 2.048 0.0814 0.2503
+	met6    1.624 1.858 0.0736 0.2555
+	met7    1.697 1.939 0.0871 0.2728
+	met8    1.695 1.979 0.0923 0.2748
+	met9    1.552 1.835 0.0674 0.2417
+	met10   1.7 1.994 0.0875 0.2781
+	met11   1.723 1.945 0.0808 0.2705
+	met12   1.688 1.987 0.0875 0.2847
+	moj1    1.19 1.298 0.0667 0.1871
+	moj2    1.209 1.336 0.06 0.1962
+	moj3    1.255 1.387 0.0806 0.2011
+	moj4    1.224 1.351 0.0666 0.1847
+	moj5    1.196 1.318 0.0596 0.176
+	moj6    1.188 1.345 0.074 0.1991
+	moj7    1.187 1.314 0.0696 0.1745
+	moj8    1.235 1.371 0.06 0.1877
+	moj9    1.153 1.29 0.0471 0.1688
+	moj10   1.208 1.352 0.0731 0.1818
+	moj11   1.177 1.29 0.0679 0.1777
+	moj12   1.226 1.363 0.06 0.1909
+	pac1    1.343 1.479 0.0821 0.1719
+	pac2    1.429 1.56 0.0731 0.2052
+	pac3    1.391 1.537 0.0731 0.2192
+	pac4    1.496 1.673 0.093 0.2283
+	pac5    1.347 1.514 0.0795 0.1978
+	pac6    1.311 1.449 0.062 0.1795
+	pac7    1.424 1.62 0.0682 0.21
+	pac8    1.411 1.596 0.0787 0.2128
+	pac9    1.338 1.502 0.0653 0.2077
+	pac10   1.449 1.618 0.0745 0.231
+	pac11   1.447 1.603 0.0787 0.2346
+	pac12   1.465 1.621 0.0765 0.214
+
+;
+		BLOCKID WM114cbd522f20;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "02-wingsPCA.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 nig1,
+		2 nig2,
+		3 nig3,
+		4 nig4,
+		5 nig5,
+		6 nig6,
+		7 nig7,
+		8 nig8,
+		9 nig9,
+		10 nig10,
+		11 nig11,
+		12 nig12,
+		13 met1,
+		14 met2,
+		15 met3,
+		16 met4,
+		17 met5,
+		18 met6,
+		19 met7,
+		20 met8,
+		21 met9,
+		22 met10,
+		23 met11,
+		24 met12,
+		25 moj1,
+		26 moj2,
+		27 moj3,
+		28 moj4,
+		29 moj5,
+		30 moj6,
+		31 moj7,
+		32 moj8,
+		33 moj9,
+		34 moj10,
+		35 moj11,
+		36 moj12,
+		37 pac1,
+		38 pac2,
+		39 pac3,
+		40 pac4,
+		41 pac5,
+		42 pac6,
+		43 pac7,
+		44 pac8,
+		45 pac9,
+		46 pac10,
+		47 pac11,
+		48 pac12;
+	TREE colored = (((1[%color = 5 ],(2[%color = 5 ],(3[%color = 5 ],(4[%color = 5 ],(5[%color = 5 ],(6[%color = 5 ],(7[%color = 5 ],(8[%color = 5 ],(9[%color = 5 ],(10[%color = 5 ],(11[%color = 5 ],12[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ],(13[%color = 8 ],(14[%color = 8 ],(15[%color = 8 ],(16[%color = 8 ],(17[%color = 8 ],(18[%color = 8 ],(19[%color = 8 ],(20[%co [...]
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL nig COLOR = (RGB 1.0 0.03137255 0.25882353) ;
+	TAXAGROUPLABEL met COLOR = (RGB 0.25882353 1.0 0.08627451) ;
+	TAXAGROUPLABEL moj COLOR = (RGB 1.0 0.62745098 0.05882353) ;
+	TAXAGROUPLABEL pac COLOR = (RGB 0.02745098 0.58431373 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+	TAXPARTITION species  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 208212565903807533 WM114cbd522e46;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 124634251740354766 WM114cbd522f20;
+			checksum 0 578547273 WM114cbd522f20;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 497 346;
+			setLocation 6 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #124634251740354766 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 505 252;
+					setLocation 1 433;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				hideWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #208212565903807533;
+			endTell;
+			setTaxa #208212565903807533;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+					tell It;
+						getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #124634251740354766;
+							endTell;
+						endTell;
+						setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+						setItem 0;
+						hireAssistant  #mesquite.rhetenor.ShowCharLoadings.ShowCharLoadings;
+						tell It;
+							getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+							tell It;
+								getWindow;
+								tell It;
+									popAsTile false;
+									popOut;
+									setExplanationSize 20;
+									setAnnotationSize 20;
+									setFontIncAnnot 0;
+									setFontIncExp 0;
+									setSize 505 252;
+									setLocation 3 433;
+									setFont SanSerif;
+									setFontSize 10;
+									getToolPalette;
+									tell It;
+									endTell;
+									valuesByItems;
+									setChartType  #mesquite.charts.Histogram.Histogram;
+								tell It;
+									suspend;
+									showAverageToggle on;
+									showPercentToggle off;
+									setCumulativeMode 0;
+									showAsBarChartToggle on;
+									showRawToggle off;
+									setNumberIntervals 20;
+									setIntervalSize 1.0;
+									setMovingWindowSize 5.0 1.0;
+									setMode 0;
+									resume;
+								endTell;
+									toggleColorItems off;
+									setNumberItems 4;
+								endTell;
+								enableCalculations;
+							endTell;
+							setChartVisible;
+							doCounts;
+							showWindow;
+						endTell;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 493 470;
+					setLocation 526 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '03-wingsCVA.nex';
+			setPrevFileName '01-wingsPlot.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 497 329;
+					setLocation 6 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In the scatter plot, a Principal Components Analysis is shown of the Drosophila data from the previous example.  The bar chart shows character loadings on the different components.  Scroll with the blue arrows to see loadings on the other components.^n^n(This analysis is likewise phylogeny-free.)^n';
+				setTitle Principal_Components;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/03-wingsCVA.nex b/Resources/examples/Multivariate_Continuous/03-wingsCVA.nex
new file mode 100755
index 0000000..ef234b9
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/03-wingsCVA.nex
@@ -0,0 +1,371 @@
+#NEXUS
+[written Sun May 04 15:26:24 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=48;
+	TAXLABELS
+		nig1 nig2 nig3 nig4 nig5 nig6 nig7 nig8 nig9 nig10 nig11 nig12 met1 met2 met3 met4 met5 met6 met7 met8 met9 met10 met11 met12 moj1 moj2 moj3 moj4 moj5 moj6 moj7 moj8 moj9 moj10 moj11 moj12 pac1 pac2 pac3 pac4 pac5 pac6 pac7 pac8 pac9 pac10 pac11 pac12 
+	;
+	BLOCKID WM114cbd5b9f97;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "03-wingsCVA.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 V1,
+		2 V2,
+		3 ACV,
+		4 PCV ; 
+	MATRIX
+	nig1    1.784 1.994 0.1007 0.2488
+	nig2    1.662 1.946 0.0882 0.2503
+	nig3    1.92 2.244 0.0678 0.2707
+	nig4    1.838 2.107 0.0678 0.2653
+	nig5    1.843 2.111 0.0784 0.2791
+	nig6    1.953 2.194 0.0671 0.2696
+	nig7    1.782 2.03 0.0795 0.2678
+	nig8    1.792 2.137 0.0852 0.2694
+	nig9    1.889 2.203 0.0746 0.2575
+	nig10   1.836 2.092 0.0925 0.2592
+	nig11   1.877 2.13 0.0941 0.2696
+	nig12   1.826 2.133 0.0741 0.2751
+	met1    1.451 1.659 0.0805 0.2425
+	met2    1.672 1.949 0.0754 0.2687
+	met3    1.67 1.943 0.0745 0.2862
+	met4    1.783 2.037 0.1074 0.2612
+	met5    1.734 2.048 0.0814 0.2503
+	met6    1.624 1.858 0.0736 0.2555
+	met7    1.697 1.939 0.0871 0.2728
+	met8    1.695 1.979 0.0923 0.2748
+	met9    1.552 1.835 0.0674 0.2417
+	met10   1.7 1.994 0.0875 0.2781
+	met11   1.723 1.945 0.0808 0.2705
+	met12   1.688 1.987 0.0875 0.2847
+	moj1    1.19 1.298 0.0667 0.1871
+	moj2    1.209 1.336 0.06 0.1962
+	moj3    1.255 1.387 0.0806 0.2011
+	moj4    1.224 1.351 0.0666 0.1847
+	moj5    1.196 1.318 0.0596 0.176
+	moj6    1.188 1.345 0.074 0.1991
+	moj7    1.187 1.314 0.0696 0.1745
+	moj8    1.235 1.371 0.06 0.1877
+	moj9    1.153 1.29 0.0471 0.1688
+	moj10   1.208 1.352 0.0731 0.1818
+	moj11   1.177 1.29 0.0679 0.1777
+	moj12   1.226 1.363 0.06 0.1909
+	pac1    1.343 1.479 0.0821 0.1719
+	pac2    1.429 1.56 0.0731 0.2052
+	pac3    1.391 1.537 0.0731 0.2192
+	pac4    1.496 1.673 0.093 0.2283
+	pac5    1.347 1.514 0.0795 0.1978
+	pac6    1.311 1.449 0.062 0.1795
+	pac7    1.424 1.62 0.0682 0.21
+	pac8    1.411 1.596 0.0787 0.2128
+	pac9    1.338 1.502 0.0653 0.2077
+	pac10   1.449 1.618 0.0745 0.231
+	pac11   1.447 1.603 0.0787 0.2346
+	pac12   1.465 1.621 0.0765 0.214
+
+;
+		BLOCKID WM114cbd5ba370;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "03-wingsCVA.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 nig1,
+		2 nig2,
+		3 nig3,
+		4 nig4,
+		5 nig5,
+		6 nig6,
+		7 nig7,
+		8 nig8,
+		9 nig9,
+		10 nig10,
+		11 nig11,
+		12 nig12,
+		13 met1,
+		14 met2,
+		15 met3,
+		16 met4,
+		17 met5,
+		18 met6,
+		19 met7,
+		20 met8,
+		21 met9,
+		22 met10,
+		23 met11,
+		24 met12,
+		25 moj1,
+		26 moj2,
+		27 moj3,
+		28 moj4,
+		29 moj5,
+		30 moj6,
+		31 moj7,
+		32 moj8,
+		33 moj9,
+		34 moj10,
+		35 moj11,
+		36 moj12,
+		37 pac1,
+		38 pac2,
+		39 pac3,
+		40 pac4,
+		41 pac5,
+		42 pac6,
+		43 pac7,
+		44 pac8,
+		45 pac9,
+		46 pac10,
+		47 pac11,
+		48 pac12;
+	TREE colored = (((1[%color = 5 ],(2[%color = 5 ],(3[%color = 5 ],(4[%color = 5 ],(5[%color = 5 ],(6[%color = 5 ],(7[%color = 5 ],(8[%color = 5 ],(9[%color = 5 ],(10[%color = 5 ],(11[%color = 5 ],12[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ])[%color = 5 ],(13[%color = 8 ],(14[%color = 8 ],(15[%color = 8 ],(16[%color = 8 ],(17[%color = 8 ],(18[%color = 8 ],(19[%color = 8 ],(20[%co [...]
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL nig COLOR = (RGB 1.0 0.03137255 0.25882353) ;
+	TAXAGROUPLABEL met COLOR = (RGB 0.25882353 1.0 0.08627451) ;
+	TAXAGROUPLABEL moj COLOR = (RGB 1.0 0.62745098 0.05882353) ;
+	TAXAGROUPLABEL pac COLOR = (RGB 0.02745098 0.58431373 1.0) ;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+	TAXPARTITION species  =  nig :  1 -  12, met :  13 -  24, moj :  25 -  36, pac :  37 -  48;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5510618219447170949 WM114cbd5b9f97;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 3229888185240561153 WM114cbd5ba370;
+			checksum 0 578547273 WM114cbd5ba370;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 478 203;
+			setLocation 12 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #3229888185240561153 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 478 146;
+					setLocation 12 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #5510618219447170949;
+			endTell;
+			setTaxa #5510618219447170949;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+					tell It;
+						getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #3229888185240561153;
+							endTell;
+						endTell;
+						setOrdinator #mesquite.rhetenor.CanonicalVariates.CanonicalVariates;
+						setItem 0;
+						hireAssistant  #mesquite.rhetenor.ShowCharLoadings.ShowCharLoadings;
+						tell It;
+							getCharter #mesquite.charts.ItemValuesChart.ItemValuesChart;
+							tell It;
+								getWindow;
+								tell It;
+									popAsTile false;
+									popOut;
+									setExplanationSize 20;
+									setAnnotationSize 20;
+									setFontIncAnnot 0;
+									setFontIncExp 0;
+									setSize 492 463;
+									setLocation 8 322;
+									setFont SanSerif;
+									setFontSize 10;
+									getToolPalette;
+									tell It;
+									endTell;
+									valuesByItems;
+									setChartType  #mesquite.charts.Histogram.Histogram;
+								tell It;
+									suspend;
+									showAverageToggle on;
+									showPercentToggle off;
+									setCumulativeMode 0;
+									showAsBarChartToggle on;
+									showRawToggle off;
+									setNumberIntervals 20;
+									setIntervalSize 1.0;
+									setMovingWindowSize 5.0 1.0;
+									setMode 0;
+									resume;
+								endTell;
+									toggleColorItems off;
+									setNumberItems 4;
+								endTell;
+								enableCalculations;
+							endTell;
+							setChartVisible;
+							doCounts;
+							showWindow;
+						endTell;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 518 433;
+					setLocation 538 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '04-anoles.nex';
+			setPrevFileName '02-wingsPCA.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 478 186;
+					setLocation 12 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'In the scatter plot, a Canonical Variates Analysis is shown, which uses the partition into the four species as the a priori grouping.  The bar chart shows the character loadings on each of the canonical variates.  Note that character 1 loads most highly on the first variate.';
+				setTitle Canonical_Variates;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/04-anoles.nex b/Resources/examples/Multivariate_Continuous/04-anoles.nex
new file mode 100755
index 0000000..a5ebf44
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/04-anoles.nex
@@ -0,0 +1,448 @@
+#NEXUS
+[written Sun May 04 15:34:09 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM114cbd648a88;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM114cbd648dc0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114cbd649010;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114cbd649140;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "04-anoles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM114cbd648a88;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM114cbd648dc0;
+			checksum 0 737652128 WM114cbd648dc0;
+			setID 1 2904659670370408267 WM114cbd649010;
+			checksum 1 573928344 WM114cbd649010;
+			setID 2 7285741872021222516 WM114cbd649140;
+			checksum 2 1458690238 WM114cbd649140;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 369 452;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5443567030079148118 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 342 491;
+					setLocation 413 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+			showDataWindow #2904659670370408267 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 321 490;
+					setLocation 1071 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+			showDataWindow #7285741872021222516 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 307 494;
+					setLocation 758 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleDiagonal off;
+					setDiagonalHeight 80;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.categ.SmallStateNamesEditor.SmallStateNamesEditor;
+				tell It;
+					panelOpen true;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '05-anoles.nex';
+			setPrevFileName '03-wingsCVA.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 369 435;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file and the next several show data and phylogenies from the work of Jonathan Losos and colleagues (Losos et al., Science, 1998 and Losos & de Queiroz, Biol. J. Linn. Soc., 1997) on Anolis lizards of the caribbean that looks at convergence in ecomorphs.  ^n^nThere are three matrices shown here, one on body measurements of the lizards, one categorizing the lizards by "ecomorph", and the final categorizing the lizards by the island from which they come.  In the fol [...]
+				setTitle Anole_example;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/05-anoles.nex b/Resources/examples/Multivariate_Continuous/05-anoles.nex
new file mode 100755
index 0000000..45bd08d
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/05-anoles.nex
@@ -0,0 +1,489 @@
+#NEXUS
+[written Sun May 04 15:34:21 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM114cbd996869;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM114cbd996b00;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114cbd996e50;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114cbd996fa0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "05-anoles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM114cbd996869;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM114cbd996b00;
+			checksum 0 737652128 WM114cbd996b00;
+			setID 1 2904659670370408267 WM114cbd996e50;
+			checksum 1 573928344 WM114cbd996e50;
+			setID 2 7285741872021222516 WM114cbd996fa0;
+			checksum 2 1458690238 WM114cbd996fa0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 439 259;
+			setLocation 10 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8853494381083195946  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 425 456;
+					setLocation 12 342;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 542 498;
+						setLocation 459 22;
+						setFont SanSerif;
+						setFontSize 10;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #2904659670370408267;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -193;
+						setLegendWidth 142;
+						setLegendHeight 193;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7285741872021222516;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -225;
+						setLegendWidth 142;
+						setLegendHeight 225;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 8;
+							orientLeft;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '06-anoles.nex';
+			setPrevFileName '04-anoles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 439 242;
+					setLocation 10 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows the phylogeny of the lizards (see the work of Losos and colleagues), and in the Mirror Tree window shows the island and ecomorph plotted on the tree.  This plotting is not done to imply a reconstruction of ancestral locations or ecomorphs, but rather merely to show the distributions of the locations and ecomorphs across the phylogeny.';
+				setTitle Island_&_Ecomorph;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/06-anoles.nex b/Resources/examples/Multivariate_Continuous/06-anoles.nex
new file mode 100755
index 0000000..2ff452a
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/06-anoles.nex
@@ -0,0 +1,517 @@
+#NEXUS
+[written Sun May 04 15:34:35 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM114cbdb754714;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM114cbdb75780;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114cbdb75860;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114cbdb75940;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "06-anoles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM114cbdb754714;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM114cbdb75780;
+			checksum 0 737652128 WM114cbdb75780;
+			setID 1 2904659670370408267 WM114cbdb75860;
+			checksum 1 573928344 WM114cbdb75860;
+			setID 2 7285741872021222516 WM114cbdb75940;
+			checksum 2 1458690238 WM114cbdb75940;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 546 276;
+			setLocation 4 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8853494381083195946  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 549 462;
+					setLocation 6 367;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.SelectBranches.SelectToolExtra.SelectClade;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #2904659670370408267;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 5;
+					setInitialOffsetY -195;
+					setLegendWidth 142;
+					setLegendHeight 193;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+										tell It;
+											setDataSet #5443567030079148118;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend on;
+								setInitialOffsetX -484;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 598 578;
+						setLocation 599 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7285741872021222516;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -146;
+						setInitialOffsetY -447;
+						setLegendWidth 142;
+						setLegendHeight 225;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '07-anoles.nex';
+			setPrevFileName '05-anoles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 546 259;
+					setLocation 4 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'At right is a window showing the phylogeny plotted into the character space (Character 2 versus character 1).  These characters are highly correlated with size.  On the plot the ecomorph character is traced.  Note that the crown-giant ecomorphs are down toward the lower right of the plot.^n^nYou can highlight particular regions of the tree using the branch selection tools of the tree window below.  The currently selected tool, the "Select Clade" tool, allows you to hi [...]
+				setTitle Tree_in_character_space;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/07-anoles.nex b/Resources/examples/Multivariate_Continuous/07-anoles.nex
new file mode 100755
index 0000000..3b54556
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/07-anoles.nex
@@ -0,0 +1,529 @@
+#NEXUS
+[written Sun May 04 15:34:50 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM114cbdc2ffe15;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM114cbdc303b0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114cbdc30520;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114cbdc30650;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "07-anoles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 8853494381083195946 WM114cbdc2ffe15;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5443567030079148118 WM114cbdc303b0;
+			checksum 0 737652128 WM114cbdc303b0;
+			setID 1 2904659670370408267 WM114cbdc30520;
+			checksum 1 573928344 WM114cbdc30520;
+			setID 2 7285741872021222516 WM114cbdc30650;
+			checksum 2 1458690238 WM114cbdc30650;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 514 236;
+			setLocation 14 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #8853494381083195946  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 586 472;
+					setLocation 13 362;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.SelectBranches.SelectToolExtra.SelectClade;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(21,((19,12),(((8,2),5),((22,15),((10,6),((((7,11),((9,28),16)),((27,20),((3,30),(18,(25,(24,4)))))),((1,(26,23)),(29,(17,(13,14))))))))));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #2904659670370408267;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 5;
+					setInitialOffsetY -195;
+					setLegendWidth 116;
+					setLegendHeight 193;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setDataSet #5443567030079148118;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend on;
+								setInitialOffsetX -312;
+								setInitialOffsetY -453;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 586 512;
+						setLocation 633 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7285741872021222516;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -128;
+						setInitialOffsetY -474;
+						setLegendWidth 123;
+						setLegendHeight 225;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '08-anoles.nex';
+			setPrevFileName '06-anoles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 514 219;
+					setLocation 14 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Now the tree at right is not plotted in raw character space, but in a principle components space.  ^n^nTry highlighting particular regions of the tree using the branch selection tools of the tree window below. ';
+				setTitle Tree_in_PCA_space;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/08-anoles.nex b/Resources/examples/Multivariate_Continuous/08-anoles.nex
new file mode 100755
index 0000000..0e450cf
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/08-anoles.nex
@@ -0,0 +1,536 @@
+#NEXUS
+[written Sun May 04 15:54:20 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		ahli aliniger alutaceus angusticeps bahorucoensis barahonae brevirostris coelestinus cristatellus cuvieri distichus equestris garmani grahami insolitus krugi lineatopus loysiana luteogularis marcanoi occultus olssoni ophiolepis paternus porcatus sagrei strahmi stratulus valencienni vanidicus 
+	;
+	BLOCKID WM114cbdc8fec16;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Measurements;
+	DIMENSIONS  NCHAR=6;
+	FORMAT DATATYPE = CONTINUOUS;
+CHARSTATELABELS 
+		1 'snout-vent length',
+		2 mass,
+		3 foreleg,
+		4 hindleg,
+		5 tail,
+		6 lamellae ; 
+	MATRIX
+	ahli            57.643 4.843 27.643 46.786 91.0 15.143
+	aliniger        55.9 4.69 23.7 34.8 92.25 22.5
+	alutaceus       35.333 0.633 12.667 27.083 92.0 17.167
+	angusticeps     48.2 1.9 16.6 26.0 64.9 19.5
+	bahorucoensis   43.933 1.667 17.933 36.2 111.444 19.5
+	barahonae       156.333 80.833 67.667 105.333 275.0 31.0
+	brevirostris    47.0 2.7 23.0 35.0 65.0 18.2
+	coelestinus     71.667 9.25 30.333 47.667 128.0 27.9
+	cristatellus    63.8 8.131 32.114 53.771 114.6 19.6
+	cuvieri         133.5 47.6 61.1 100.6 284.5 30.0
+	distichus       51.267 3.913 25.933 38.333 71.5 17.6
+	equestris       156.0 76.333 64.833 98.5 301.0 42.333
+	garmani         107.9 30.148 47.4 78.8 216.7 28.4
+	grahami         61.071 6.211 28.385 45.429 108.3 25.9
+	insolitus       41.8 1.0 13.2 23.4 53.2 15.0
+	krugi           48.6 2.355 21.12 38.88 128.3 19.5
+	lineatopus      56.545 4.657 26.714 46.048 107.6 18.4
+	loysiana        40.0 1.2 17.75 24.75 51.0 17.5
+	luteogularis    183.0 112.0 72.0 112.0 331.0 40.0
+	marcanoi        55.563 4.957 27.688 46.188 113.25 20.313
+	occultus        37.7 0.5 10.7 17.0 43.0 18.0
+	olssoni         46.462 1.569 16.538 35.769 141.417 18.8
+	ophiolepis      38.0 1.2 14.0 24.111 89.0 15.333
+	paternus        47.0 2.0 16.5 26.0 84.0 19.0
+	porcatus        77.643 10.243 30.5 45.786 167.25 30.429
+	sagrei          49.0 2.958 21.2 36.2 94.9 18.1
+	strahmi         74.333 11.333 39.0 65.333 141.5 21.333
+	stratulus       44.45 1.88 21.5 32.75 71.7 19.0
+	valencienni     72.7 7.067 26.0 38.7 90.5 22.6
+	vanidicus       37.75 0.663 12.125 25.625 96.6 13.625
+
+;
+		BLOCKID WM114cbdc90220;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  island;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3";
+	CHARSTATELABELS 
+		1 Island /  Puerto_Rico Jamaica Cuba Hispaniola ; 
+	MATRIX
+	ahli           2
+	aliniger       3
+	alutaceus      2
+	angusticeps    2
+	bahorucoensis  3
+	barahonae      3
+	brevirostris   3
+	coelestinus    3
+	cristatellus   0
+	cuvieri        0
+	distichus      3
+	equestris      2
+	garmani        1
+	grahami        1
+	insolitus      3
+	krugi          0
+	lineatopus     1
+	loysiana       2
+	luteogularis   2
+	marcanoi       3
+	occultus       0
+	olssoni        3
+	ophiolepis     2
+	paternus       2
+	porcatus       2
+	sagrei         2
+	strahmi        3
+	stratulus      0
+	valencienni    1
+	vanidicus      2
+
+;
+		BLOCKID WM114cbdc903b0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  Ecomorph;
+	DIMENSIONS  NCHAR=1;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6";
+	CHARSTATELABELS 
+		1 Ecomorph /  doesnt_exist 'trunk-ground' 'trunk-crown' trunk 'grass-bush' 'crown-giant' twig ; 
+	MATRIX
+	ahli           1
+	aliniger       2
+	alutaceus      4
+	angusticeps    6
+	bahorucoensis  4
+	barahonae      5
+	brevirostris   3
+	coelestinus    2
+	cristatellus   1
+	cuvieri        5
+	distichus      3
+	equestris      5
+	garmani        5
+	grahami        2
+	insolitus      6
+	krugi          4
+	lineatopus     1
+	loysiana       3
+	luteogularis   5
+	marcanoi       1
+	occultus       6
+	olssoni        4
+	ophiolepis     4
+	paternus       6
+	porcatus       ?
+	sagrei         1
+	strahmi        1
+	stratulus      2
+	valencienni    6
+	vanidicus      4
+
+;
+		BLOCKID WM114cbdc904e0;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "08-anoles.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		23 ahli,
+		6 aliniger,
+		18 alutaceus,
+		22 angusticeps,
+		4 bahorucoensis,
+		30 barahonae,
+		10 brevirostris,
+		5 coelestinus,
+		13 cristatellus,
+		9 cuvieri,
+		11 distichus,
+		3 equestris,
+		28 garmani,
+		29 grahami,
+		8 insolitus,
+		12 krugi,
+		27 lineatopus,
+		19 loysiana,
+		2 luteogularis,
+		15 marcanoi,
+		1 occultus,
+		7 olssoni,
+		25 ophiolepis,
+		21 paternus,
+		20 porcatus,
+		24 sagrei,
+		16 strahmi,
+		14 stratulus,
+		26 valencienni,
+		17 vanidicus;
+	TREE Anole_Tree = (1,((2,3),(((5,6),4),((7,8),((9,30),((((10,11),((13,14),12)),((16,15),((18,17),(19,(20,(21,22)))))),((23,(24,25)),(26,(27,(28,29))))))))));
+
+END;
+
+
+BEGIN CODONS;
+	CODESET * UNTITLED  (CHARACTERS = island)  =  universal:  1;
+	CODESET * UNTITLED  (CHARACTERS = Ecomorph)  =  universal:  1;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Measurements)  =  Squared:  1 -  6;
+TYPESET * UNTITLED  (CHARACTERS = island)  =  unord:  1;
+TYPESET * UNTITLED  (CHARACTERS = Ecomorph)  =  unord:  1;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Measurements)  =  Brownian_default:  1 -  6;
+ProbModelSet * UNTITLED  (CHARACTERS = island)  =  'Mk1 (est.)':  1;
+ProbModelSet * UNTITLED  (CHARACTERS = Ecomorph)  =  'Mk1 (est.)':  1;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7359766042395362478 WM114cbdc8fec16;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 3439750308037465817 WM114cbdc90220;
+			checksum 0 737652128 WM114cbdc90220;
+			setID 1 7189053912013154391 WM114cbdc903b0;
+			checksum 1 573928344 WM114cbdc903b0;
+			setID 2 3137483036444525899 WM114cbdc904e0;
+			checksum 2 1458690238 WM114cbdc904e0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 513 305;
+			setLocation 3 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7359766042395362478  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 849.965158753516.5670471821649633161;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 511 433;
+					setLocation 9 409;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.SelectBranches.SelectToolExtra.SelectClade;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(21,((19<selected = on >,12<selected = on >)<selected = on >,(((8,2),5),((22,15),((10,6),((((7,11),((9,28),16)),((27,20),((3<selected = on >,30<selected = on >)<selected = on >,(18<selected = on >,(25<selected = on >,(24<selected = on >,4<selected = on >)<selected = on >)<selected = on >)<selected = on >)<selected = on >)),((1<selected = on >,(26<selected = on >,23<selected = on >)<selected = on >)<selected = on >,(29,(17,(13,14))))))))));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #7189053912013154391;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 3;
+					setInitialOffsetY -195;
+					setLegendWidth 116;
+					setLegendHeight 193;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.rhetenor.PlotTree3D.PlotTree3D;
+						tell It;
+							setNodeLocs  #mesquite.rhetenor.NodeLocs3DPlot.NodeLocs3DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setDataSet #3439750308037465817;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 3;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend on;
+								toggleShowAxes on;
+								setInitialOffsetH -243;
+								setInitialOffsetV -180;
+								setTheta 1.76552314;
+								setPhi 1.83450666;
+								setD 21.48760335;
+								setCurrentX 1;
+								setCurrentY 2;
+								setCurrentZ 3;
+								show;
+							endTell;
+							setSpotDiameter 10;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+							toggleFog off;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 754 747;
+						setLocation 528 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+							setTool mesquite.trees.DependentTreeWindow.DepTreeWindow.arrow;
+						endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #3137483036444525899;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend on;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -169;
+						setInitialOffsetY -463;
+						setLegendWidth 142;
+						setLegendHeight 225;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '09-pcaSim.nex';
+			setPrevFileName '07-anoles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 513 288;
+					setLocation 3 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The tree is now plotted in a 3-dimensional space of principal components.  You can rotate the view using the green bars, and change the magnification using the red bar.  The larger spots are closer to you.  Enjoy your flight through morphospace.^n^nNote that the species from Cuba are highlighted.  If you turn on "Use Fog" in the Display menu, and de-select the Cuban species in the tree window above, the more distant the point in the third dimension, the more it will b [...]
+				setTitle 3D_plot;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/09-pcaSim.nex b/Resources/examples/Multivariate_Continuous/09-pcaSim.nex
new file mode 100755
index 0000000..85cb199
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/09-pcaSim.nex
@@ -0,0 +1,397 @@
+#NEXUS
+[written Sun May 04 15:54:34 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114cbdd482a17;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "09-pcaSim.nex"';
+	DIMENSIONS  NCHAR=50;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	taxon_0    2.992210463104165 -0.5213796212123114 -3.1933608712155848 -0.2380414477440551 3.069338067864813 0.6350921841170124 -2.6503509149104265 2.641646658530784 -5.059102625151112 -2.4386173699395433 2.5845701126632075 -2.0473976448968 -3.596960412307545 -0.8637710076749665 5.1307348768653815 -2.2774077261335 -5.772428413201568 -1.6210860251077548 -7.018314185792198 1.2784880654198518 0.26418598552638706 -2.962340357371817 -0.7451474147272754 -0.12016682211005533 1.333832991953333 -1 [...]
+	taxon_1    -0.6159089185463594 2.8251237433505123 5.966914902224667 -1.3176328349660005 2.0941476552549565 0.44826630641625714 1.3996089919193146 -1.8532609049922442 1.194787888600039 3.1995846401899177 -3.3767991782135516 4.078721540595769 -1.8825066729903543 -2.1790587847454193 -2.341422971612696 -1.7221567195257916 6.488290666168001 -2.8157613471956098 2.140899424517751 7.42031539664155 3.1089578391529162 5.192756964318315 5.125858723642327 2.7855834150038055 -4.088988914259199 0.763 [...]
+	taxon_2    6.3624224064335975 1.8173101565294902 2.171088928715866 6.823934646313486 2.2604710950087457 3.8337119064827956 -6.464618023811242 3.1187400284883946 -1.046349744590067 -3.2087683040313095 -6.052522276296489 -0.7366381903523069 -6.31561123183821 -3.2944871838806615 0.9988153898179807 2.4419823617890932 -2.6115945171794124 -4.608438307935261 -1.363071804984885 -0.6911421370388441 6.866530892676542 2.8513577200354208 -2.433151696664187 -5.489272271532662 -2.308495464191093 -0.3 [...]
+	taxon_3    -5.201832848109966 -0.8746546751985125 4.859598341823185 -10.96477642311772 1.5204975201441648 1.3578425910414385 -2.2199189338672234 1.590256816332689 7.017491272025122 4.245976423341276 -3.278078452270021 1.6127812289970946 -4.607341873331669 -6.342903750993334 1.1298613943032256 -2.2320638717399603 2.315516487815637 -1.1952732127851067 4.335321394945093 4.36985762581831 0.8958525707555314 -3.9862985905926784 1.693317382658954 9.374992707026973 -2.4880839144774765 4.5369157 [...]
+	taxon_4    -6.463485243641799 4.94421175499709 -2.853757463987187 3.3594087843644296 -1.5720253151370036 -4.99154712449598 7.825025262470588 -2.69097154924848 0.9841281873137764 -3.8362660792611787 -0.8817197347999509 -3.71810933723565 -8.94599184468518 1.1710322609471149 4.839513930438739 -5.970074190286658 0.3808855996973477 -0.07046063869206298 -0.5306946781829824 4.267848017580845 0.08983407407248434 -0.5579010333999708 -3.3421800569495304 8.319564395358586 1.7980669328726966 3.6972 [...]
+	taxon_5    -3.235189667445917 -3.2074435127789394 -1.515072637351711 5.129019140711172 -0.2511919982420254 -6.004518295536943 9.66948839642005 -4.305809631395871 -4.847624054233453 -0.019721192643707197 -3.983032444626711 -4.866030864332769 -9.028562085137592 1.692067880252972 -1.9474799446120752 -7.434833286186466 -0.3539631783105346 -1.9777517687377841 0.9263836526145435 7.830049530228649 11.109393642392627 -3.74592278002007 -2.163920230281321 2.9687399740306013 -6.777474784216082 -5. [...]
+	taxon_6    -3.699479960972744 4.53800427959125 -2.066932104434697 8.985412472537655 0.22039166638329655 1.824272563477916 4.008793941929678 2.8248272016958165 -3.633177666559673 -6.540269125459169 -3.9091653752985 -3.1397185490353112 -5.004209616382209 6.245979201979994 -1.927228911994047 -2.2490196459708045 0.7092262026234639 2.8428511039597852 -5.027495383570602 0.54423943799513 -1.5850516247688553 -5.813920464408541 -1.9723175646893893 3.297508287197868 -4.121890237272859 -2.19066721 [...]
+	taxon_7    -5.148929648774498 3.469933541841339 -2.3186344332896605 3.6093098490172038 0.44895247644908265 -9.684672098815653 10.145395609629364 -3.26196348111565 5.347583658716699 0.9412173429168371 -0.8176574653090629 -10.502749274710565 -14.584748449032737 -2.6917146090965565 5.6161136222092605 -10.434823776983642 -1.7715389666415304 -1.4385622858509435 1.5226896377309767 5.927830656878157 7.239808551702298 -0.15869558258888583 0.8629857843416985 4.64370493773493 1.5648211067744155 8 [...]
+	taxon_8    0.5722443579091707 -0.10995907911662861 4.142286055744222 -3.0658070631071928 -0.4237265275489378 -1.8586288766488512 -4.053685422166835 -3.840380447936093 4.0638687078249 6.49228400466243 -2.091839846655442 4.646385456665855 -1.9443277487898516 -2.5977470505629467 5.044187992455365 -2.4210148238386133 2.292875746434741 0.546034857502701 -0.3262725062405689 6.269070297191394 -1.2105885924562547 4.20147718304619 2.8483200600485388 6.640649744753104 -1.0166497375739931 -0.61680 [...]
+	taxon_9    -4.18262041797215 -2.7649886913304043 1.4296463397605161 -3.834727817597635 -0.465590068878241 -0.5383941766816311 -3.0284871108972857 -0.05629736619712772 5.980846426317518 6.825308412516355 -0.6900213963766032 2.7136291950043843 -2.7004152031103774 -3.4338999702432953 2.658337210121168 -3.0975278146446006 -1.7380400754317402 -1.365382508623073 3.834122630902766 7.615596786355233 -1.5221612800014603 -1.577214469703946 -0.31673152895328616 6.752084381819787 0.2446132089427565 [...]
+	taxon_10   -0.7984014847917035 1.6645953040765509 -4.08077316600221 0.5373688677972157 1.490446117783925 -6.812190477068703 2.1380651790565577 0.07832692810750519 -1.5096393046752625 -6.498260815558502 -1.4702800155479006 0.028669847647889907 1.585379176078419 1.2633909156979837 -0.6905822798896253 0.05225244049801159 -0.9525178185661819 -2.5093527839800593 2.302359434929261 -3.373671143806518 5.1338367288843285 1.8789082289101515 -1.1449802406029406 4.520948211663615 -1.167809746870788 [...]
+	taxon_11   0.8360500930032865 3.7199644983362923 0.8451499732199488 7.4818579577105 -1.0788236234014275 0.9188853348675519 1.445067483480759 2.240917547533641 -3.825385769102208 -4.29889774641609 -6.324924163469797 -0.3145366572930186 -3.536017745052546 4.6853033878729455 -3.3298969876877558 -1.8119059547310918 -1.0305078754774941 2.161933705234238 -1.7718765640333531 1.2712904388409343 4.763405909619582 -5.7093921476256675 -4.981564546902445 6.121266970969877 -2.282250438289009 2.44512 [...]
+	taxon_12   4.093418494872468 5.122811167228835 2.962067090000816 -0.3600342333113205 0.9845813939315629 1.3035777162553865 -1.607453932576031 0.3042689605306027 0.702455139273628 -3.3876169410138735 2.8641999351798066 3.174504680969588 -2.4488867416498348 2.2208158459534624 3.394037784646745 1.1269568659015419 5.588532817310609 -1.4239330049474042 0.4086880297748585 5.516669947018912 -0.42917631464815875 -0.2298713899902407 -0.30193982470331693 4.449894363161521 1.3684477293560398 -0.25 [...]
+	taxon_13   -8.617383286913775 5.366504683306542 -5.8457948614263024 7.117346683117635 2.4719309431084096 -10.9878149309132 6.206666666290314 -4.81355283878034 2.556481864248628 1.544607529026366 0.32771719963811274 -8.347194008599761 -11.8841639324856 0.0783224610589292 4.734256868586167 -5.0586763297713535 1.0247243033606428 2.71570126073173 0.9887901698910944 9.023420847965944 5.474188338073132 -2.9483436105022633 0.6301843990004704 4.953143907421322 0.34586533024462857 6.127912615402 [...]
+	taxon_14   1.073353760505365 5.5734767990134735 -2.6843066156558515 5.677935472306026 -2.699643233128126 -2.728007905793043 -0.392790446305412 2.6458388804094986 -1.3060865093811895 -1.7520250611103338 0.1575923757219606 -0.8077917459859683 -3.9200291928398183 6.27052847533536 -0.32977023164093744 -0.3712239781314066 -1.7577272515336166 -0.5884619750569766 -0.5957274215226168 -0.3593748972020159 4.0348907086606 -2.7033121473612303 -3.4139018429061174 4.551128612056906 -1.423983699996695 [...]
+	taxon_15   -12.444465554325378 4.836625200513874 -2.2657018000555906 5.28275932092579 -3.0404718381934486 -7.643380653321292 8.150185373958202 -4.598657218930686 -0.7608563739597207 -2.918546721420061 -1.7231515608650922 -3.403627855882959 -6.029797738139418 1.2895373765695695 2.08574412638709 -4.381707660719245 -2.222864063494854 1.648798837291138 0.13256620707433586 7.562033262921517 -0.5521287547663918 2.2010800670211257 -4.129730887884562 8.013380743209533 -2.8655472264901 5.2292916 [...]
+
+;
+		BLOCKID WM114cbdd48540;
+
+
+END;
+BEGIN TREES;
+	Title 'Trees from "09-pcaSim.nex"';
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE species_phylogeny = (((1:5.83,(11:8.833[%color = 5 ],(((7:2.0,12:1.778):1.857,15:1.857):3.2,(6:9.0[%color = 11 ],((8:4.0,14:3.5):4.0,(16:2.8,5:1.636):3.25):3.0):8.0):1.6):1.7):1.538,3:8.571[%color = 6 ]):1.857,(13:6.0,(((4:4.0,10:2.25):2.0,9:2.143):2.2,2:4.333):4.5):7.5):2.0;
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  50;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  50;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 662863783909563173 WM114cbdd482a17;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2885845513937770954 WM114cbdd48540;
+			checksum 0 284355860 WM114cbdd48540;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 435 268;
+			setLocation 2 31;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #662863783909563173  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2151.964555237631.1796649727975159086;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 293;
+					setLocation 447 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 8;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #662863783909563173  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2169.964555238096.1130981136534120104;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 533 362;
+					setLocation 453 437;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+					tell It;
+						setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+						tell It;
+							hide;
+							setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+							tell It;
+								getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+								tell It;
+									setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+									tell It;
+										getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+										tell It;
+											setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+											tell It;
+												setDataSet #2885845513937770954;
+											endTell;
+										endTell;
+										setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+										setItem 0;
+									endTell;
+								endTell;
+								setCharacter 2;
+								setItem 0;
+								getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+								tell It;
+									setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+									tell It;
+										setDefaultModel 13;
+									endTell;
+									toggleMPRsMode off;
+									getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+									tell It;
+										toggleWeight on;
+									endTell;
+								endTell;
+							endTell;
+							toggleShowLegend on;
+							setInitialOffsetX -253;
+							setInitialOffsetY -129;
+							setCurrentX 1;
+							setCurrentY 2;
+							show;
+						endTell;
+						setSpotDiameter 10;
+						toggleShowTerminals on;
+						toggleShowInternals on;
+						toggleShowTree on;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2885845513937770954 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 427 327;
+					setLocation 4 384;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '10-pcaLiveSim.nex';
+			setPrevFileName '08-anoles.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 435 251;
+					setLocation 2 31;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The tree at right was used to simulate evolution by Brownian motion to yield the data matrix shown below.  The same tree is plotted in PCA space calculated from the simulated characters, lower right.  Notice that the different clades stand out clearly on the plot.^n';
+				setTitle Simulated_data;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/10-pcaLiveSim.nex b/Resources/examples/Multivariate_Continuous/10-pcaLiveSim.nex
new file mode 100755
index 0000000..f5e7760
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/10-pcaLiveSim.nex
@@ -0,0 +1,290 @@
+#NEXUS
+[written Sun May 04 15:54:44 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114cbde64ec18;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "10-pcaLiveSim.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE species_phylogeny = (((1:5.831,(11:8.833[%color = 5 ],(((7:2.0[%color = 16 ],12:1.778[%color = 16 ]):1.857[%color = 16 ],15:1.857[%color = 16 ]):3.2[%color = 16 ],(6:9.0[%color = 13 ],((8:4.0[%color = 14 ],14:3.5[%color = 14 ]):4.0[%color = 14 ],(16:2.8[%color = 14 ],5:1.636[%color = 14 ]):3.25[%color = 14 ]):3.0[%color = 14 ]):8.0):1.6):1.7):1.538,3:8.571[%color = 6 ]):1.857,(13:6.0[%color = 11 ],(((4:4.0[%color = 11 ],10:2.25[%color = 11 ]):2.0[%color = 11 ],9:2.143[%color = 11 ] [...]
+	TREE symmetrical = ((((1:0.2[%color = 5 ],3:0.2[%color = 5 ]):0.2[%color = 5 ],(6:0.2[%color = 5 ],2:0.2[%color = 5 ]):0.2[%color = 5 ]):0.2[%color = 5 ],((7:0.2[%color = 11 ],12:0.2[%color = 11 ]):0.2[%color = 11 ],(11:0.2[%color = 11 ],15:0.2[%color = 11 ]):0.2[%color = 11 ]):0.2[%color = 11 ]):5.0[%color = 0 ],(((8:0.2[%color = 14 ],14:0.2[%color = 14 ]):0.2[%color = 14 ],(16:0.2[%color = 14 ],5:0.2[%color = 14 ]):0.2[%color = 14 ]):0.2[%color = 14 ],((4:0.2[%color = 6 ],10:0.2[%colo [...]
+
+END;
+
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 719598498838827296 WM114cbde64ec18;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 521 231;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #719598498838827296  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2437.964555407410.6795675411464486307;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 532 386;
+					setLocation 4 352;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.stochchar.SimulatedMatrix.SimulatedMatrix;
+												tell It;
+													setMatrix 1;
+													setNumChars 50;
+													setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+													tell It;
+														setModelByName Brownian_default;
+													endTell;
+													setSeed 985885061550;
+													getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+													tell It;
+														setContextID 2437.964555407410.6795675411464486307;
+													endTell;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend on;
+								setInitialOffsetX -199;
+								setInitialOffsetY -377;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 10;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 590 548;
+						setLocation 559 74;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '11-cvaLiveSim.nex';
+			setPrevFileName '09-pcaSim.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 521 214;
+					setLocation 8 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a "live" PCA on simulated data.  That is, a data set of 50 characters is evolved on the tree in the tree window below via Brownian motion evolution, using the branch lengths in the tree.  Then, the resulting characters are subjected to PCA and the tree plotted in PC2 versus PC1 in the window at right.  This is live in the sense that the characters are simulated on the fly just before the plot is made.  To request a new simulated data set, choose "Next  [...]
+				setTitle Live_simulation;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/11-cvaLiveSim.nex b/Resources/examples/Multivariate_Continuous/11-cvaLiveSim.nex
new file mode 100755
index 0000000..f0182da
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/11-cvaLiveSim.nex
@@ -0,0 +1,306 @@
+#NEXUS
+[written Sun May 04 15:54:53 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=48;
+	TAXLABELS
+		A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 
+	;
+	BLOCKID WM114cc1e74c719;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "11-cvaLiveSim.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 A1,
+		2 A2,
+		3 A3,
+		4 A4,
+		5 A5,
+		6 A6,
+		7 A7,
+		8 A8,
+		9 A9,
+		10 A10,
+		11 A11,
+		12 A12,
+		13 B1,
+		14 B2,
+		15 B3,
+		16 B4,
+		17 B5,
+		18 B6,
+		19 B7,
+		20 B8,
+		21 B9,
+		22 B10,
+		23 B11,
+		24 B12,
+		25 C1,
+		26 C2,
+		27 C3,
+		28 C4,
+		29 C5,
+		30 C6,
+		31 C7,
+		32 C8,
+		33 C9,
+		34 C10,
+		35 C11,
+		36 C12,
+		37 D1,
+		38 D2,
+		39 D3,
+		40 D4,
+		41 D5,
+		42 D6,
+		43 D7,
+		44 D8,
+		45 D9,
+		46 D10,
+		47 D11,
+		48 D12;
+	TREE tree = (((((1:2.0,(2:1.0,4:1.0):1.0):2.0,(9:3.0,(10:2.0,(11:1.0,12:1.0):1.0):1.0):1.0):1.0,((3:1.0,6:1.0):2.0,(5:2.0,(7:1.0,8:1.0):1.0):1.0):2.0):2.0[%color = 5 ],((13:1.0,14:1.0):4.0,((((15:1.0,16:1.0):1.0,(18:1.0,19:1.0):1.0):1.0,(17:1.0,22:1.0):2.0):1.0,((20:1.0,21:1.0):1.0,(23:1.0,24:1.0):1.0):2.0):1.0):2.0[%color = 6 ]):3.0,(((25:2.0,(35:1.0,36:1.0):1.0):5.0,(26:6.0,((27:4.0,(29:3.0,(30:2.0,(31:1.0,32:1.0):1.0):1.0):1.0):1.0,(28:2.0,(33:1.0,34:1.0):1.0):3.0):1.0):1.0):2.0[%col [...]
+
+END;
+
+
+BEGIN LABELS;
+	TAXAGROUPLABEL Red COLOR = (RGB 1.0 0.15686275 0.10980392) ;
+	TAXAGROUPLABEL Orange COLOR = (RGB 1.0 0.61176471 0.15686275) ;
+	TAXAGROUPLABEL Cyan COLOR = (RGB 0.28627451 1.0 0.85882353) ;
+	TAXAGROUPLABEL Green COLOR = (RGB 0.21176471 1.0 0.18431373) ;
+	TAXAGROUPLABEL Yellow COLOR = (RGB 0.88235294 1.0 0.17254902) ;
+	TAXAGROUPLABEL Goldenrod;
+
+
+END;
+
+BEGIN SETS;
+	TAXPARTITION * UNTITLED  =  Red :  1 -  12, Orange :  13 -  24, Cyan :  25 -  36, Green :  37 -  48;
+	TAXPARTITION untitled  =  Red :  1 -  12, Orange :  13 -  24, Cyan :  25 -  36, Green :  37 -  48;
+	TAXPARTITION untitled  =  Red :  1 -  12, Orange :  13 -  24, Yellow :  25 -  36, Green :  37 -  48;
+	TAXPARTITION species  =  Red :  1 -  12, Orange :  13 -  24, Yellow :  25 -  36, Goldenrod :  37 -  48;
+	TAXPARTITION untitled  =  Red :  1 -  12, Orange :  13 -  24, Cyan :  25 -  36, Green :  37 -  48;
+	TAXPARTITION untitled  =  Red :  1 -  12, Orange :  13 -  24, Yellow :  25 -  36, Green :  37 -  48;
+	TAXPARTITION species  =  Red :  1 -  12, Orange :  13 -  24, Yellow :  25 -  36, Goldenrod :  37 -  48;
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6690059761767473967 WM114cc1e74c719;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 521 263;
+			setLocation 9 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6690059761767473967  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1836.967910171762.6568711385870313008;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 512 472;
+					setLocation 11 351;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 4;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition off;
+						toggleShadePartition on;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.charts.TaxaScattergram.TaxaScattergram;
+		tell It;
+			setTaxonSource  #mesquite.minimal.StoredTaxa.StoredTaxa;
+			tell It;
+				setTaxa #6690059761767473967;
+			endTell;
+			setTaxa #6690059761767473967;
+			axesSame;
+			setValues  #mesquite.cont.ContinuousStatesT.ContinuousStatesT;
+			tell It;
+				getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+				tell It;
+					setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+					tell It;
+						getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.stochchar.SimulatedMatrix.SimulatedMatrix;
+							tell It;
+								setMatrix 1;
+								setNumChars 10;
+								setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+								tell It;
+									setModelByName Brownian_default;
+								endTell;
+								setSeed 995374620870;
+								getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+								tell It;
+									setContextID 1836.967910171762.6568711385870313008;
+								endTell;
+							endTell;
+						endTell;
+						setOrdinator #mesquite.rhetenor.CanonicalVariates.CanonicalVariates;
+						setItem 0;
+					endTell;
+				endTell;
+				setCharacter 2;
+				setItem 0;
+			endTell;
+			showNamesToggle on;
+			getCharter #mesquite.charts.ItemsBiplot.ItemsBiplot;
+			tell It;
+				getWindow;
+				tell It;
+					setX 1;
+					setY 2;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 512 472;
+					setLocation 557 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				enableCalculations;
+				getEmployee #mesquite.charts.Scattergram.Scattergram;
+				tell It;
+					markerSize 10;
+					toggleJoin off;
+					toggleShowDots on;
+					movingWindowSize 1;
+					sumByBlocks off;
+				endTell;
+			endTell;
+			setChartVisible;
+			doCounts;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '12-epca.nex';
+			setPrevFileName '10-pcaLiveSim.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 521 246;
+					setLocation 9 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a Canonical Variates Analysis performed on a data set simulated "live" using Brownian motion evolution on the tree below.  The partition of taxa used to define groups for the CVA represents the four major clades of the tree.  By changing the lengths of the colored branches in the tree, the characters simulated will do better or worse at distinguishing the clades via CVA.^n^nTo to ask to resimulate the data, select "Next Simulated matrix" from the "Scat [...]
+				setTitle 'Live Simulation -CVA';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/12-epca.nex b/Resources/examples/Multivariate_Continuous/12-epca.nex
new file mode 100755
index 0000000..58594bb
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/12-epca.nex
@@ -0,0 +1,604 @@
+#NEXUS
+[written Sun May 04 15:55:58 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE species;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		a b c d e f g 
+	;
+	BLOCKID WM114cc1ef7b720;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE speciesSupplemented;
+	DIMENSIONS NTAX=14;
+	TAXLABELS
+		a b c d e f g h i j g2 h2 i2 j2 
+	;
+	BLOCKID WM114cc1ef7bd21;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  space;
+	LINK TAXA = species;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a   0.1889 0.0807
+	b   0.0052 -0.0073
+	c   0.0813 0.0744
+	d   4.02 3.821
+	e   4.03 3.942
+	f   4.153 4.047
+	g   -0.0721 1.149
+
+;
+		BLOCKID WM114cc1ef7ca0;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  space2;
+	LINK TAXA = speciesSupplemented;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a    0.1889 0.0807
+	b    0.0052 -0.0073
+	c    0.0813 0.0744
+	d    4.02 3.821
+	e    4.03 3.942
+	f    4.153 4.047
+	g    -0.0721 1.149
+	h    0.0569 0.9767
+	i    0.1782 0.8074
+	j    0.0733 1.104
+	g2   -0.028 0.9647
+	h2   -0.0539 0.9679
+	i2   0.0479 1.086
+	j2   -0.0861 1.136
+
+;
+		BLOCKID WM114cc1ef80d0;
+
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = space)  =  Squared:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = space2)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = space)  =  Brownian_default:  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = space2)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 686378446142612087 WM114cc1ef7b720;
+			setID 1 8789595508264872182 WM114cc1ef7bd21;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8560806027600134777 WM114cc1ef7ca0;
+			checksum 0 2390669759 WM114cc1ef7ca0;
+			setID 1 246536950136951271 WM114cc1ef80d0;
+			checksum 1 977018013 WM114cc1ef80d0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 422 280;
+			setLocation 7 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #686378446142612087  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1603.967565686342.6573736635669045704;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 305;
+					setLocation 701 454;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1<color = 0 >,4<color = 0 >)<color = 0 >,((2<color = 0 >,5<color = 0 >)<color = 0 >,(3<color = 0 >,6<color = 0 >)<color = 0 >)<color = 0 >)<color = 0 >,7<color = 0 >)<color = 0 >;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #686378446142612087;
+								setDataSet #8560806027600134777;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #686378446142612087;
+													setDataSet #8560806027600134777;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 345;
+						setLocation 473 31;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 118 4 106 26;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX 8;
+							setOffsetY -101;
+							setNote Standard_PCA;
+							setOffsetX 8;
+							setOffsetY -101;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #686378446142612087;
+									setDataSet #8560806027600134777;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+										tell It;
+											setTaxa #686378446142612087;
+											setDataSet #8560806027600134777;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 345;
+						setLocation 904 49;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 94 10 106 42;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX 8;
+							setOffsetY -104;
+							setNote Raw_characters;
+							setOffsetX 8;
+							setOffsetY -104;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #686378446142612087;
+									setDataSet #8560806027600134777;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #8560806027600134777 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 414 294;
+					setLocation 11 381;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 70;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '13-epca.nex';
+			setPrevFileName '11-cvaLiveSim.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 422 263;
+					setLocation 7 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file introduces the effect of phylogenetic non-independence and taxon sampling on cross-species ordinations.^n^nBelow is a highly artificial data set and accompanying phylogeny of 7 species.  Note that sister species have a consistent large difference between the two characters.^n^nAt right the tree is plotted into the raw character space, and separately into a Principle Components space.  As expected, the PCA chooses an axis highlighting the dominant variation i [...]
+				setTitle EPCA_intro;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/13-epca.nex b/Resources/examples/Multivariate_Continuous/13-epca.nex
new file mode 100755
index 0000000..8029f5c
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/13-epca.nex
@@ -0,0 +1,711 @@
+#NEXUS
+[written Sun May 04 15:56:13 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE species;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		a b c d e f g 
+	;
+	BLOCKID WM114cc1f90dc22;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE speciesSupplemented;
+	DIMENSIONS NTAX=14;
+	TAXLABELS
+		a b c d e f g h i j g2 h2 i2 j2 
+	;
+	BLOCKID WM114cc1f90e723;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  space;
+	LINK TAXA = species;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a   0.1889 0.0807
+	b   0.0052 -0.0073
+	c   0.0813 0.0744
+	d   4.02 3.821
+	e   4.03 3.942
+	f   4.153 4.047
+	g   -0.0721 1.149
+
+;
+		BLOCKID WM114cc1f91160;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  space2;
+	LINK TAXA = speciesSupplemented;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a    0.1889 0.0807
+	b    0.0052 -0.0073
+	c    0.0813 0.0744
+	d    4.02 3.821
+	e    4.03 3.942
+	f    4.153 4.047
+	g    -0.0721 1.149
+	h    0.0569 0.9767
+	i    0.1782 0.8074
+	j    0.0733 1.104
+	g2   -0.028 0.9647
+	h2   -0.0539 0.9679
+	i2   0.0479 1.086
+	j2   -0.0861 1.136
+
+;
+		BLOCKID WM114cc1f91220;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'Here there are two sets of taxa, the same as shown in the previous file, and a set of taxa identical to the first except for the addition of 7 species to the clade containing species "g".  ^n^nNote that because of the large number of species in the blue clade, the Principle components analysis shifts its first axis to accommodate them.^n';
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = space)  =  Squared:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = space2)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = space)  =  Brownian_default:  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = space2)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 686378446142612087 WM114cc1f90dc22;
+			setID 1 8789595508264872182 WM114cc1f90e723;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8560806027600134777 WM114cc1f91160;
+			checksum 0 2390669759 WM114cc1f91160;
+			setID 1 246536950136951271 WM114cc1f91220;
+			checksum 1 977018013 WM114cc1f91220;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 397 295;
+			setLocation 11 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #686378446142612087  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1603.967565686342.6573736635669045704;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 281;
+					setLocation 450 452;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1<color = 0 >,4<color = 0 >)<color = 0 >,((2<color = 0 >,5<color = 0 >)<color = 0 >,(3<color = 0 >,6<color = 0 >)<color = 0 >)<color = 0 >)<color = 0 >,7<color = 0 >)<color = 0 >;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 70 140 100 20;
+						setOffsetX 70;
+						setOffsetY 140;
+						setNote second_clade_small;
+						setOffsetX 70;
+						setOffsetY 140;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #686378446142612087;
+								setDataSet #8560806027600134777;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #686378446142612087;
+													setDataSet #8560806027600134777;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 321;
+						setLocation 456 36;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 104 4 106 26;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX 8;
+							setOffsetY -95;
+							setNote Standard_PCA;
+							setOffsetX 8;
+							setOffsetY -95;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #686378446142612087;
+									setDataSet #8560806027600134777;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #8789595508264872182  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1733.967565688167.6875230740143230555;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 281;
+					setLocation 889 452;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground Light_Gray;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1,4),((2,5),(3,6))),((7,8),(9,(10,(11,(12,(13,14)))))));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 79 161 100 20;
+						setOffsetX 79;
+						setOffsetY 161;
+						setNote second_clade_large;
+						setOffsetX 79;
+						setOffsetY 161;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #8789595508264872182;
+								setDataSet #246536950136951271;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #8789595508264872182;
+													setDataSet #246536950136951271;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -221;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground Light_Gray;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 321;
+						setLocation 882 29;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 85 4 106 26;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX -19;
+							setOffsetY -121;
+							setNote Standard_PCA;
+							setOffsetX -19;
+							setOffsetY -121;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #8789595508264872182;
+									setDataSet #246536950136951271;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '14-epca.nex';
+			setPrevFileName '12-epca.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 397 278;
+					setLocation 11 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here there are two sets of taxa, the same as shown in the previous file, and a set of taxa identical to the first except for the addition of 7 species to the clade containing species "g".  ^n^nNote that because of the large number of species in the clade with g, h, i, j and others, the Principle components analysis shifts its first axis to accommodate them.^n';
+				setTitle 'PCA - clade effects';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/14-epca.nex b/Resources/examples/Multivariate_Continuous/14-epca.nex
new file mode 100755
index 0000000..a00ba9b
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/14-epca.nex
@@ -0,0 +1,729 @@
+#NEXUS
+[written Sun May 04 15:57:19 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE species;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		a b c d e f g 
+	;
+	BLOCKID WM114cc20069d24;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE speciesSupplemented;
+	DIMENSIONS NTAX=14;
+	TAXLABELS
+		a b c d e f g h i j g2 h2 i2 j2 
+	;
+	BLOCKID WM114cc20069f25;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  space;
+	LINK TAXA = species;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a   0.1889 0.0807
+	b   0.0052 -0.0073
+	c   0.0813 0.0744
+	d   4.02 3.821
+	e   4.03 3.942
+	f   4.153 4.047
+	g   -0.0721 1.149
+
+;
+		BLOCKID WM114cc2006b00;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  space2;
+	LINK TAXA = speciesSupplemented;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a    0.1889 0.0807
+	b    0.0052 -0.0073
+	c    0.0813 0.0744
+	d    4.02 3.821
+	e    4.03 3.942
+	f    4.153 4.047
+	g    -0.0721 1.149
+	h    0.0569 0.9767
+	i    0.1782 0.8074
+	j    0.0733 1.104
+	g2   -0.028 0.9647
+	h2   -0.0539 0.9679
+	i2   0.0479 1.086
+	j2   -0.0861 1.136
+
+;
+		BLOCKID WM114cc2006ef0;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'The figure above illustrates why the addition of taxa to the blue clade affects the PCA.  In order to find the axis that maximizes the variance explained, PCA minimizes the variance explained orthogonally (i.e., it minimizes the residuals from the first axis).   PCA counts the residuals of the species in clade B (the blue clade) separately, and thus the more species in clade B, the more powerful its "gravitational" effect on the first axis.  ^n^nThe problem with PCA i [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = space)  =  Squared:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = space2)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = space)  =  Brownian_default:  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = space2)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 835465756695001242 WM114cc20069d24;
+			setID 1 1991710532467474024 WM114cc20069f25;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4918009697969523908 WM114cc2006b00;
+			checksum 0 2390669759 WM114cc2006b00;
+			setID 1 3533841213786404322 WM114cc2006ef0;
+			checksum 1 977018013 WM114cc2006ef0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 402 306;
+			setLocation 11 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #835465756695001242  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1603.967565686342.6573736635669045704;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 273;
+					setLocation 420 414;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1<color = 0 >,4<color = 0 >)<color = 0 >,((2<color = 0 >,5<color = 0 >)<color = 0 >,(3<color = 0 >,6<color = 0 >)<color = 0 >)<color = 0 >)<color = 0 >,7<color = 0 >)<color = 0 >;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 45 150 100 20;
+						setOffsetX 45;
+						setOffsetY 150;
+						setNote second_clade_small;
+						setOffsetX 45;
+						setOffsetY 150;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #835465756695001242;
+								setDataSet #4918009697969523908;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #835465756695001242;
+													setDataSet #4918009697969523908;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 313;
+						setLocation 425 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 104 4 106 26;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX 8;
+							setOffsetY -95;
+							setNote Standard_PCA;
+							setOffsetX 8;
+							setOffsetY -95;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #835465756695001242;
+									setDataSet #4918009697969523908;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #1991710532467474024  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1733.967565688167.6875230740143230555;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 273;
+					setLocation 847 415;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground Light_Gray;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1,4),((2,5),(3,6))),((7,8),(9,(10,(11,(12,(13,14)))))));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 53 126 100 20;
+						setOffsetX 53;
+						setOffsetY 126;
+						setNote second_clade_large;
+						setOffsetX 53;
+						setOffsetY 126;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #1991710532467474024;
+								setDataSet #3533841213786404322;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #1991710532467474024;
+													setDataSet #3533841213786404322;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -221;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground Light_Gray;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 313;
+						setLocation 848 32;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 87 4 106 26;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX -19;
+							setOffsetY -118;
+							setNote Standard_PCA;
+							setOffsetX -19;
+							setOffsetY -118;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #1991710532467474024;
+									setDataSet #3533841213786404322;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.ornamental.PictureWindowMaker.PictureWindowMaker;
+		tell It;
+			setPicture 'epca/Image1.gif';
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 271 192;
+				setLocation 79 468;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '15-epca.nex';
+			setPrevFileName '13-epca.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 402 289;
+					setLocation 11 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'The figure below illustrates why the addition of taxa to the blue clade affects the PCA.  In order to find the axis that maximizes the variance explained, PCA minimizes the variance explained orthogonally (i.e., it minimizes the residuals from the first axis).   PCA counts the residuals of the species in clade B (the blue clade) separately, and thus the more species in clade B, the more powerful its "gravitational" effect on the first axis.  ^n^nThe problem with PCA i [...]
+				setTitle 'Clade effects cont''d';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/15-epca.nex b/Resources/examples/Multivariate_Continuous/15-epca.nex
new file mode 100755
index 0000000..04c2cd9
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/15-epca.nex
@@ -0,0 +1,741 @@
+#NEXUS
+[written Sun May 04 15:57:35 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE species;
+	DIMENSIONS NTAX=7;
+	TAXLABELS
+		a b c d e f g 
+	;
+	BLOCKID WM114cc20a14926;
+
+END;
+
+
+
+BEGIN TAXA;
+	TITLE speciesSupplemented;
+	DIMENSIONS NTAX=14;
+	TAXLABELS
+		a b c d e f g h i j g2 h2 i2 j2 
+	;
+	BLOCKID WM114cc20a14b27;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  space;
+	LINK TAXA = species;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a   0.1889 0.0807
+	b   0.0052 -0.0073
+	c   0.0813 0.0744
+	d   4.02 3.821
+	e   4.03 3.942
+	f   4.153 4.047
+	g   -0.0721 1.149
+
+;
+		BLOCKID WM114cc20a1780;
+
+
+END;
+BEGIN CHARACTERS;
+	TITLE  space2;
+	LINK TAXA = speciesSupplemented;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = CONTINUOUS;
+	MATRIX
+	a    0.1889 0.0807
+	b    0.0052 -0.0073
+	c    0.0813 0.0744
+	d    4.02 3.821
+	e    4.03 3.942
+	f    4.153 4.047
+	g    -0.0721 1.149
+	h    0.0569 0.9767
+	i    0.1782 0.8074
+	j    0.0733 1.104
+	g2   -0.028 0.9647
+	h2   -0.0539 0.9679
+	i2   0.0479 1.086
+	j2   -0.0861 1.136
+
+;
+		BLOCKID WM114cc20a1890;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file illustrates an alternative to PCA for visualizing multidimensional data among species, under development by W. Maddison & Eric Dryeson.  It''s called "Evolutionary PCA" because it finds the axes that maximize evolutionary change, not static variance.  It allows the change on the basal branch of clade B, for example, to be counted only once during the ordination.^n^nThe results are shown at left. Note that the two plots are nearly identical, because the blue  [...]
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = space)  =  Squared:  1 -  2;
+TYPESET * UNTITLED  (CHARACTERS = space2)  =  Squared:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = space)  =  Brownian_default:  1 -  2;
+ProbModelSet * UNTITLED  (CHARACTERS = space2)  =  Brownian_default:  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 835465756695001242 WM114cc20a14926;
+			setID 1 1991710532467474024 WM114cc20a14b27;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4918009697969523908 WM114cc20a1780;
+			checksum 0 2390669759 WM114cc20a1780;
+			setID 1 3533841213786404322 WM114cc20a1890;
+			checksum 1 977018013 WM114cc20a1890;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 412 329;
+			setLocation 11 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #835465756695001242  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1603.967565686342.6573736635669045704;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 292;
+					setLocation 434 452;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1<color = 0 >,4<color = 0 >)<color = 0 >,((2<color = 0 >,5<color = 0 >)<color = 0 >,(3<color = 0 >,6<color = 0 >)<color = 0 >)<color = 0 >)<color = 0 >,7<color = 0 >)<color = 0 >;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 50 129 100 20;
+						setOffsetX 50;
+						setOffsetY 129;
+						setNote second_clade_small;
+						setOffsetX 50;
+						setOffsetY 129;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #835465756695001242;
+								setDataSet #4918009697969523908;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #835465756695001242;
+													setDataSet #4918009697969523908;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.EvolutionaryPCA.EvolutionaryPCA;
+											tell It;
+												getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+												tell It;
+													setContextID 1603.967565686342.6573736635669045704;
+												endTell;
+											endTell;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -224;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 332;
+						setLocation 437 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 112 4 137 32;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX 13;
+							setOffsetY -100;
+							setNote Evolutionary_PCA;
+							setOffsetX 13;
+							setOffsetY -100;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #835465756695001242;
+									setDataSet #4918009697969523908;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			makeTreeWindow #1991710532467474024  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 1733.967565688167.6875230740143230555;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 400 292;
+					setLocation 873 451;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground Light_Gray;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '(((1,4),((2,5),(3,6))),((7,8),(9,(10,(11,(12,(13,14)))))));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 50 142 100 20;
+						setOffsetX 50;
+						setOffsetY 142;
+						setNote second_clade_large;
+						setOffsetX 50;
+						setOffsetY 142;
+					endTell;
+				endTell;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+						toggleGray off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setTaxa #1991710532467474024;
+								setDataSet #3533841213786404322;
+							endTell;
+						endTell;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend off;
+					toggleGray off;
+					toggleWeights on;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+												tell It;
+													setTaxa #1991710532467474024;
+													setDataSet #3533841213786404322;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.EvolutionaryPCA.EvolutionaryPCA;
+											tell It;
+												getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+												tell It;
+													setContextID 1733.967565688167.6875230740143230555;
+												endTell;
+											endTell;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -200;
+								setInitialOffsetY -220;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 16;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground Light_Gray;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 400 332;
+						setLocation 871 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 102 41 137 32;
+							setFont SanSerif;
+							setFontSize 14;
+							setOffsetX -6;
+							setOffsetY -112;
+							setNote Evolutionary_PCA;
+							setOffsetX -6;
+							setOffsetY -112;
+						endTell;
+					endTell;
+						newAssistant #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+							toggleGray off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setTaxa #1991710532467474024;
+									setDataSet #3533841213786404322;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						resume ;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.ornamental.PictureWindowMaker.PictureWindowMaker;
+		tell It;
+			setPicture 'epca/Image2.gif';
+			getWindow;
+			tell It;
+				popAsTile false;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 277 189;
+				setLocation 69 454;
+				setFont SanSerif;
+				setFontSize 10;
+			endTell;
+			showWindow;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '16-epcaLiveSim.nex';
+			setPrevFileName '14-epca.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 412 312;
+					setLocation 11 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file illustrates an alternative to PCA for visualizing multidimensional data among species, under development by Wayne Maddison & Eric Dryeson.  It''s called "Evolutionary PCA" because it finds the axes that maximize evolutionary change, not static variance.  It allows the change on the basal branch of clade B, for example, to be counted only once during the ordination.^n^nThe results are shown at right. Note that the two plots are nearly identical, because the b [...]
+				setTitle EPCA;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/16-epcaLiveSim.nex b/Resources/examples/Multivariate_Continuous/16-epcaLiveSim.nex
new file mode 100755
index 0000000..e58e8c3
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/16-epcaLiveSim.nex
@@ -0,0 +1,452 @@
+#NEXUS
+[written Sun May 04 15:57:48 PDT 2008 by Mesquite  version 2.01+ (build j65) at Thrandina.local/10.0.1.8 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=16;
+	TAXLABELS
+		taxon_0 taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 taxon_6 taxon_7 taxon_8 taxon_9 taxon_10 taxon_11 taxon_12 taxon_13 taxon_14 taxon_15 
+	;
+	BLOCKID WM114cc211d7328;
+
+END;
+
+
+BEGIN TREES;
+	Title 'Trees from "16-epcaLiveSim.nex"';
+	LINK Taxa = Taxa;
+	TRANSLATE
+		1 taxon_0,
+		2 taxon_1,
+		3 taxon_2,
+		4 taxon_3,
+		5 taxon_4,
+		6 taxon_5,
+		7 taxon_6,
+		8 taxon_7,
+		9 taxon_8,
+		10 taxon_9,
+		11 taxon_10,
+		12 taxon_11,
+		13 taxon_12,
+		14 taxon_13,
+		15 taxon_14,
+		16 taxon_15;
+	TREE species_phylogeny = (((1:5.831,(11:8.833[%color = 5 ],(((7:2.0[%color = 16 ],12:1.778[%color = 16 ]):1.857[%color = 16 ],15:1.857[%color = 16 ]):3.2[%color = 16 ],(6:9.0[%color = 13 ],((8:4.0[%color = 14 ],14:3.5[%color = 14 ]):4.0[%color = 14 ],(16:2.8[%color = 14 ],5:1.636[%color = 14 ]):3.25[%color = 14 ]):3.0[%color = 14 ]):8.0):1.6):1.7):1.538,3:8.571[%color = 6 ]):1.857,(13:6.0[%color = 11 ],(((4:4.0[%color = 11 ],10:2.25[%color = 11 ]):2.0[%color = 11 ],9:2.143[%color = 11 ] [...]
+	TREE symmetrical = ((((1:0.2[%color = 5 ],3:0.2[%color = 5 ]):0.2[%color = 5 ],(6:0.2[%color = 5 ],2:0.2[%color = 5 ]):0.2[%color = 5 ]):0.2[%color = 5 ],((7:0.2[%color = 11 ],12:0.2[%color = 11 ]):0.2[%color = 11 ],(11:0.2[%color = 11 ],15:0.2[%color = 11 ]):0.2[%color = 11 ]):0.2[%color = 11 ]):5.0[%color = 0 ],(((8:0.2[%color = 8 ],14:0.2[%color = 8 ]):0.2[%color = 8 ],(16:0.2[%color = 8 ],5:0.2[%color = 8 ]):0.2[%color = 8 ]):0.2[%color = 8 ],((4:0.2[%color = 6 ],10:0.2[%color = 6 ] [...]
+
+END;
+
+
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows a "live" EPCA on simulated data of 50 characters, to contrast to a PCA on simulated data.  Note that the EPCA doesn''t emphasize the distinctness of major clades nearly as much as does the PCA.  To request a new simulated data set, choose "Next source matrix" from the Plot menu of each of the Dependent Tree Windows.^n^nAlso, if you scroll to tree number 2 in the tree window at upper left,  you will see characters evolved under a very different tree.^n';
+
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 7000731484956992281 WM114cc211d7328;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 459 228;
+			setLocation 1 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #7000731484956992281  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 2398.967910429453.8640835773843590908;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 472 341;
+					setLocation 1 362;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter on;
+							toggleEven on;
+						endTell;
+						setEdgeWidth 6;
+						orientUp;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+				tell It;
+					getNote;
+					tell It;
+						setBounds 4 26 100 20;
+						setOffsetX 4;
+						setOffsetY 26;
+						setNote Model_tree;
+						setOffsetX 4;
+						setOffsetY 26;
+					endTell;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.stochchar.SimulatedMatrix.SimulatedMatrix;
+												tell It;
+													setMatrix 1;
+													setNumChars 50;
+													setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+													tell It;
+														setModelByName Brownian_default;
+													endTell;
+													setSeed 1;
+													getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+													tell It;
+														setContextID 2398.967910429453.8640835773843590908;
+													endTell;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.EvolutionaryPCA.EvolutionaryPCA;
+											tell It;
+												getEmployee #mesquite.trees.TreeOfContext.TreeOfContext;
+												tell It;
+													setContextID 2398.967910429453.8640835773843590908;
+												endTell;
+											endTell;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -248;
+								setInitialOffsetY -285;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 10;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 467 381;
+						setLocation 978 30;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 4 4 56 32;
+							setFont SanSerif;
+							setFontSize 18;
+							setOffsetX 4;
+							setOffsetY 4;
+							setNote EPCA;
+							setOffsetX 4;
+							setOffsetY 4;
+						endTell;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.cont.PlotTree.PlotTree;
+						tell It;
+							setNodeLocs  #mesquite.cont.NodeLocs2DPlot.NodeLocs2DPlot;
+							tell It;
+								hide;
+								setAxis  #mesquite.cont.MapContinuous.MapContinuous;
+								tell It;
+									getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+									tell It;
+										setCharacterSource #mesquite.rhetenor.CharFromOrdinations.CharFromOrdinations;
+										tell It;
+											getCharacterSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+											tell It;
+												setCharacterSource #mesquite.stochchar.SimulatedMatrix.SimulatedMatrix;
+												tell It;
+													setMatrix 1;
+													setNumChars 50;
+													setCharacterSimulator  #mesquite.stochchar.EvolveContinuous.EvolveContinuous;
+													tell It;
+														setModelByName Brownian_default;
+													endTell;
+													setSeed 1;
+													getTreeSource  #mesquite.trees.TreeOfContext.TreeOfContext;
+													tell It;
+														setContextID 2398.967910429453.8640835773843590908;
+													endTell;
+												endTell;
+											endTell;
+											setOrdinator #mesquite.rhetenor.PrincipalComponents.PrincipalComponents;
+											setItem 0;
+										endTell;
+									endTell;
+									setCharacter 2;
+									setItem 0;
+									getEmployee #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+									tell It;
+										setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+										tell It;
+											setDefaultModel 13;
+										endTell;
+										toggleMPRsMode off;
+										getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+										tell It;
+											toggleWeight on;
+										endTell;
+									endTell;
+								endTell;
+								toggleShowLegend off;
+								setInitialOffsetX -218;
+								setInitialOffsetY -288;
+								setCurrentX 1;
+								setCurrentY 2;
+								show;
+							endTell;
+							setSpotDiameter 10;
+							toggleShowTerminals on;
+							toggleShowInternals on;
+							toggleShowTree on;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 0;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 470 382;
+						setLocation 494 31;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistantD #mesquite.trees.TreeNotesMaker.TreeNotesMaker;
+					tell It;
+						getNote;
+						tell It;
+							setBounds 4 4 49 29;
+							setFont SanSerif;
+							setFontSize 18;
+							setOffsetX 4;
+							setOffsetY 4;
+							setNote PCA;
+							setOffsetX 4;
+							setOffsetY 4;
+						endTell;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+				endTell;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '17-landmarks.nex';
+			setPrevFileName '15-epca.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 459 211;
+					setLocation 1 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows a "live" EPCA on simulated data of 50 characters, to contrast to a PCA on simulated data.  Note that the EPCA doesn''t emphasize the distinctness of major clades nearly as much as does the PCA.  To request a new simulated data set, choose "Next Simulated matrix" from the Plot menu of each of the Dependent Tree Windows.^n^nAlso, if you scroll to tree number 2 in the tree window below,  you will see characters evolved under a very different tree.^n';
+				setTitle 'Live sim. - EPCA';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/17-landmarks.nex b/Resources/examples/Multivariate_Continuous/17-landmarks.nex
new file mode 100755
index 0000000..c1c652a
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/17-landmarks.nex
@@ -0,0 +1,386 @@
+#NEXUS
+[written Sat Jun 07 12:31:14 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		one_fish two_fish red_fish blue_fish 
+	;
+	BLOCKID WM114cc24056831;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "17-landmarks.nex"';
+	DIMENSIONS  NCHAR=9;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y )  GAP = - MISSING = ?;
+CHARSTATELABELS 
+		1 landmark_1,
+		2 landmark_2,
+		3 landmark_3,
+		4 landmark_4,
+		5 landmark_5,
+		6 landmark_6,
+		7 landmark_7,
+		8 landmark_8 ; 
+	MATRIX
+	one_fish    (0.0 1.0) (2.0 3.0) (5.0 3.0) (6.5 2.0) (9.5 2.5) (9.5 0.0) (6.5 0.5) (4.0 0.0) (2.0 0.0)
+	two_fish    (0.0 1.5) (2.5 2.8) (4.7 3.0) (6.5 2.0) (9.5 2.5) (8.5 0.0) (6.5 0.5) (4.0 0.0) (2.0 0.0)
+	red_fish    (0.0 1.2) (2.0 3.0) (4.7 3.0) (7.5 2.0) (12.5 2.5) (9.5 0.0) (7.5 0.9) (4.0 0.0) (2.0 0.0)
+	blue_fish   (0.0 1.0) (2.0 3.0) (5.0 3.0) (7.5 2.0) (9.0 2.5) (8.5 0.5) (7.5 0.8) (4.0 0.0) (2.0 0.0)
+
+;
+		BLOCKID WM114cc2405880;
+
+
+END;
+BEGIN NOTES;
+
+	TEXT  FILE TEXT = 'This file shows the use of landmark data to reconstruct the form of ancestors.  The data matrix shows x,y positions of each of 9 landmarks.  Squared change parsimony is used to reconstruct the landmarks of ancestors.  Because the reconstruction is sensitive to branch lengths, it will change if branch lengths change.  This can be done by changing the branch lengths in the tree window at upper left using the ruler tool.^n^nThe following example files show how to build a [...]
+
+	AN T = 1  A = 0 DC = 2006.5.6.22.5.44 DM = 2006.5.6.22.5.44 ID = 010b0d3c9e5455 I = 'fish/one.gif' TF = (CM ) ;
+
+	AN T = 2  A = 0 DC = 2006.5.6.22.5.44 DM = 2006.5.6.22.5.44 ID = 010b0d3c9e5456 I = 'fish/two.gif' TF = (CM ) ;
+
+	AN T = 3  A = 0 DC = 2006.5.6.22.5.44 DM = 2006.5.6.22.5.44 ID = 010b0d3c9e5457 I = 'fish/red.gif' TF = (CM ) ;
+
+	AN T = 4  A = 0 DC = 2006.5.6.22.5.44 DM = 2006.5.6.22.5.44 ID = 010b0d3c9e5558 I = 'fish/blue.gif' TF = (CM ) ;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  9;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  9;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 4684932117850311189 WM114cc24056831;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 2364200711958207605 WM114cc2405880;
+			checksum 0 834511649 WM114cc2405880;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 100;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 508 261;
+			setLocation 1 29;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #4684932117850311189  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 3446.961442092478.5319374357487583883;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 573 413;
+					setLocation 0 371;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientRight;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFont SanSerif;
+						setFontSize 10;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((1:1.0,2:1.0):1.0,(3:0.43,4:1.0):1.0):1.0;';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newWindowAssistant  #mesquite.trees.DependentTreeWindow.DependentTreeWindow;
+				tell It;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale on;
+								toggleBroadScale off;
+								toggleCenter off;
+								toggleEven off;
+							endTell;
+							setEdgeWidth 12;
+							orientUp;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						showBranchColors on;
+						labelBranchLengths off;
+						centerBrLenLabels on;
+						showBrLensUnspecified on;
+						showBrLenLabelsOnTerminals on;
+						setBrLenLabelColor 0 0 255;
+						setNumBrLenDecimals 6;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFont SanSerif;
+							setFontSize 10;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleCenterNodeNames off;
+							toggleShowNames on;
+							namesAngle ?;
+						endTell;
+					endTell;
+					getWindow;
+					tell It;
+						popAsTile false;
+						popOut;
+						setExplanationSize 30;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setSize 670 466;
+						setLocation 595 22;
+						setFont SanSerif;
+						setFontSize 10;
+						getToolPalette;
+						tell It;
+						endTell;
+						newAssistant #mesquite.rhetenor.LandmarkDrawings.LandmarkDrawings;
+					tell It;
+						sizeDrawing 140 70;
+						setInitialOffsetX -605;
+						setInitialOffsetY -147;
+						setItems 0 1;
+						toggleLastToFirst on;
+						getCharacterSource  #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+							tell It;
+								setDataSet #2364200711958207605;
+							endTell;
+						endTell;
+						getReconstructor  #mesquite.ancstates.AncestralStatesAll.AncestralStatesAll;
+						tell It;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+								toggleMPRsMode off;
+								getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+								tell It;
+									toggleWeight on;
+								endTell;
+							endTell;
+						endTell;
+					endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+					tell It;
+						colorByPartition off;
+					endTell;
+					getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+					tell It;
+						setOn on;
+						setDigits 4;
+						writeAsPercentage off;
+						toggleHorizontal on;
+						setFontSize 10;
+						setOffset 0  0;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.Projector.Projector;
+				tell It;
+					getExtra 0;
+					tell It;
+						showTaxonPicture 0;
+						showTaxonPicture 1;
+						showTaxonPicture 2;
+						showTaxonPicture 3;
+					endTell;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #2364200711958207605 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 508 194;
+					setLocation 1 29;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getWindow;
+				tell It;
+					forceAutosize;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '18-landmarks.nex';
+			setPrevFileName '16-epcaLiveSim.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 508 244;
+					setLocation 1 29;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows the use of landmark data to reconstruct the form of ancestors.  The data matrix shows x,y positions of each of 9 landmarks.  Squared change parsimony is used to reconstruct the landmarks of ancestors.  Because the reconstruction is sensitive to branch lengths, it will change if branch lengths change.  This can be done by changing the branch lengths in the tree window at upper left using the ruler tool.^n^nThe following example files show how to build a [...]
+				setTitle Ancestral_forms;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/18-landmarks.nex b/Resources/examples/Multivariate_Continuous/18-landmarks.nex
new file mode 100755
index 0000000..7ef2ae8
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/18-landmarks.nex
@@ -0,0 +1,152 @@
+#NEXUS
+[written Sat Jun 07 12:31:23 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		Box_1 Box_2 Box_3 Box_4 
+	;
+	BLOCKID WM114cc24fb5c32;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "18-landmarks.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y )  GAP = - MISSING = ?;
+	MATRIX
+	Box_1   (? ?) (? ?) (? ?) (? ?)
+	Box_2   (? ?) (? ?) (? ?) (? ?)
+	Box_3   (? ?) (? ?) (? ?) (? ?)
+	Box_4   (? ?) (? ?) (? ?) (? ?)
+
+;
+		BLOCKID WM114cc24fb660;
+
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5420325524222062819 WM114cc24fb5c32;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4430408865877702767 WM114cc24fb660;
+			checksum 0 3957422510 WM114cc24fb660;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 528 340;
+			setLocation 16 23;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4430408865877702767 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 538 310;
+					setLocation 589 23;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 72;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '19-landmarks.nex';
+			setPrevFileName '17-landmarks.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 528 323;
+					setLocation 16 23;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'This file shows how to enter and use landmark data in Mesquite. ^n^nWe''ve made a new file with four taxa.  Next, "New Empty Matrix..." from the Characters menu was chosen.  The type of the matrix chosen was Continuous, and the number of characters is the number of landmarks (each landmark is represented by a character).^n^nContinuous matrices can be three dimensional (characters x taxa x items), where the third dimension (items) represents a series of values in each  [...]
+				setTitle 'Landmarks how-to';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/19-landmarks.nex b/Resources/examples/Multivariate_Continuous/19-landmarks.nex
new file mode 100755
index 0000000..8597c34
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/19-landmarks.nex
@@ -0,0 +1,152 @@
+#NEXUS
+[written Sat Jun 07 12:31:31 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		Box_1 Box_2 Box_3 Box_4 
+	;
+	BLOCKID WM114cc25476e33;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "19-landmarks.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y )  GAP = - MISSING = ?;
+	MATRIX
+	Box_1   (0.0 0.0) (0.0 1.0) (1.0 0.0) (1.0 1.0)
+	Box_2   (0.0 0.0) (0.0 1.0) (1.0 0.0) (1.0 1.0)
+	Box_3   (0.0 0.0) (0.0 1.0) (1.0 0.0) (0.8 0.8)
+	Box_4   (0.0 0.0) (0.0 1.0) (1.0 0.0) (1.0 1.0)
+
+;
+		BLOCKID WM114cc25478a0;
+
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5420325524222062819 WM114cc25476e33;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4430408865877702767 WM114cc25478a0;
+			checksum 0 2803930463 WM114cc25478a0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 530 334;
+			setLocation 20 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4430408865877702767 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 545 310;
+					setLocation 599 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 72;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '20-landmarks.nex';
+			setPrevFileName '18-landmarks.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 530 317;
+					setLocation 20 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Here we''ve edited the matrix to place a series of (x,y) points in each cell.  Note that Box 1, 2 and 4 are simple boxes of landmarks; Box 3 has its corner punched in (0.8, 0.8 instead of 1.0, 1.0).  The format is "(x y)".^n^nRhetenor does not yet have analyses to adjust and scale points into alignment like Procrustes analyses, and so you''ll have to do that first, and enter the adjusted landmarks.^n';
+				setTitle 'Landmarks cont''d.';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/20-landmarks.nex b/Resources/examples/Multivariate_Continuous/20-landmarks.nex
new file mode 100755
index 0000000..27b9644
--- /dev/null
+++ b/Resources/examples/Multivariate_Continuous/20-landmarks.nex
@@ -0,0 +1,279 @@
+#NEXUS
+[written Sat Jun 07 12:31:49 PDT 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Thrandina.local/192.168.0.136 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=4;
+	TAXLABELS
+		Box_1 Box_2 Box_3 Box_4 
+	;
+	BLOCKID WM114cc25684034;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "20-landmarks.nex"';
+	DIMENSIONS  NCHAR=4;
+	FORMAT DATATYPE = CONTINUOUS ITEMS = (x y )  GAP = - MISSING = ?;
+CHARSTATELABELS 
+		3 #4,
+		4 #3 ; 
+	MATRIX
+	Box_1   (0.0 0.0) (0.0 1.0) (1.0 1.0) (1.0 0.0)
+	Box_2   (0.0 0.0) (0.0 1.0) (1.0 1.0) (1.0 0.0)
+	Box_3   (0.0 0.0) (0.0 1.0) (0.8 0.8) (1.0 0.0)
+	Box_4   (0.0 0.0) (0.0 1.0) (1.0 1.0) (1.0 0.0)
+
+;
+		BLOCKID WM114cc2568440;
+
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  Squared:  1 -  4;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  Brownian_default:  1 -  4;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5420325524222062819 WM114cc25684034;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4430408865877702767 WM114cc2568440;
+			checksum 0 4234720301 WM114cc2568440;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false true 80;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 520 411;
+			setLocation 3 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #5420325524222062819  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				suppressEPCResponse;
+				setTreeSource  #mesquite.trees.DefaultTrees.DefaultTrees;
+				setAssignedID 6850.985887405751.627258943310845990;
+				getTreeWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 650 392;
+					setLocation 557 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.DiagonalDrawTree.DiagonalDrawTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle off;
+							toggleScale on;
+							toggleBroadScale off;
+							toggleCenter off;
+							toggleEven off;
+						endTell;
+						setEdgeWidth 12;
+						orientUp;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					showBranchColors on;
+					labelBranchLengths off;
+					centerBrLenLabels on;
+					showBrLensUnspecified on;
+					showBrLenLabelsOnTerminals on;
+					setBrLenLabelColor 0 0 255;
+					setNumBrLenDecimals 6;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleCenterNodeNames off;
+						toggleShowNames on;
+						namesAngle ?;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					setTree '((1,2),(3,4));';
+					useSuggestedSize off;
+					toggleSizeToFit on;
+					toggleTextOnTree off;
+					showWindow;
+					newAssistant  #mesquite.rhetenor.LandmarkDrawings.LandmarkDrawings;
+				tell It;
+					sizeDrawing 100 60;
+					setInitialOffsetX -204;
+					setInitialOffsetY -146;
+					setItems 0 1;
+					toggleLastToFirst on;
+					getCharacterSource  #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+					tell It;
+						setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices;
+						tell It;
+							setDataSet #4430408865877702767;
+						endTell;
+					endTell;
+					getReconstructor  #mesquite.ancstates.AncestralStatesAll.AncestralStatesAll;
+					tell It;
+						setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+						tell It;
+							setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							toggleMPRsMode off;
+							getEmployee #mesquite.parsimony.ParsimonySquared.ParsimonySquared;
+							tell It;
+								toggleWeight on;
+							endTell;
+						endTell;
+					endTell;
+				endTell;
+				endTell;
+				desuppressEPCResponse;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.ornamental.DrawTreeAssocDoubles.DrawTreeAssocDoubles;
+				tell It;
+					setOn on;
+					setDigits 4;
+					writeAsPercentage off;
+					toggleHorizontal on;
+					setFontSize 10;
+					setOffset 0  0;
+				endTell;
+				getEmployee #mesquite.trees.TreeInfoValues.TreeInfoValues;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4430408865877702767 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 20;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 633 158;
+					setLocation 560 531;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 72;
+					toggleBirdsEye off;
+					toggleAllowAutosize on;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.cont.ItemsEditorForInfoPanel.ItemsEditorForInfoPanel;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName '00-introduction.nex';
+			setPrevFileName '19-landmarks.nex';
+			getWindow;
+			tell It;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 520 394;
+					setLocation 3 22;
+					setFont SanSerif;
+					setFontSize 10;
+					setActive;
+				setExplanation 'Once the data matrix was entered, we then selected "Landmark Drawings" from the Analysis:Tree menu of the Tree window.  We chose Stored Matrices.^n^nNote that the most recent common ancestor of Box 3 and Box 4 have the corner somewhat punched in, and the change to Box 3 is indicated by the distortion grid calculated by thin plate splines.^n^nYou''ll notice that some of the points are at the edge of the drawings and not easily visible.  The Landmark Drawings module is  [...]
+				setTitle 'Landmarks cont''d.';
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Intro.;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Multivariate_Continuous/epca/Image1.gif b/Resources/examples/Multivariate_Continuous/epca/Image1.gif
new file mode 100755
index 0000000..d085c7a
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/epca/Image1.gif differ
diff --git a/Resources/examples/Multivariate_Continuous/epca/Image2.gif b/Resources/examples/Multivariate_Continuous/epca/Image2.gif
new file mode 100755
index 0000000..b636be8
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/epca/Image2.gif differ
diff --git a/Resources/examples/Multivariate_Continuous/fish/blue.gif b/Resources/examples/Multivariate_Continuous/fish/blue.gif
new file mode 100755
index 0000000..ed976da
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/fish/blue.gif differ
diff --git a/Resources/examples/Multivariate_Continuous/fish/one.gif b/Resources/examples/Multivariate_Continuous/fish/one.gif
new file mode 100755
index 0000000..92579b7
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/fish/one.gif differ
diff --git a/Resources/examples/Multivariate_Continuous/fish/red.gif b/Resources/examples/Multivariate_Continuous/fish/red.gif
new file mode 100755
index 0000000..8099ed4
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/fish/red.gif differ
diff --git a/Resources/examples/Multivariate_Continuous/fish/two.gif b/Resources/examples/Multivariate_Continuous/fish/two.gif
new file mode 100755
index 0000000..331417f
Binary files /dev/null and b/Resources/examples/Multivariate_Continuous/fish/two.gif differ
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/01.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/01.concatenatingMatrices.nex
new file mode 100644
index 0000000..6373ab6
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/01.concatenatingMatrices.nex
@@ -0,0 +1,337 @@
+#NEXUS
+[written Sun Jun 08 13:17:40 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a9813467;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a9813910;
+
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'             Geneva '9' '238' '1'             all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'             000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'             000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /             00 ? -;
+	Correlation '0' '0' '1000' '0' '0'             10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'             110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'             1;
+	Calculations 0000001;
+	SummaryMode '0' '0'             0;
+	Charts  Geneva '9' (            normal )             0010;
+	NexusOptions '0' '0' '50'             001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (            normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'             1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'             1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'             1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'             0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'             1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'             Geneva '9' (            normal )             Geneva '10' (            normal )             Geneva '9' (            normal )             Geneva '9' (            normal )             Geneva '9' (            bold )             Geneva '9' (            normal )             Geneva '9' (            normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'             00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'             100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'             1010;
+	BothTools '1';
+
+END;
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  =  N:  1- 1013 ;
+
+	CODESET * UNTITLED   =  universal:  1 -  1013;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =            unord PolyTcount =            MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  1013;
+
+	EXSET * UNTITLED  =  1 -  75 934 -  1013;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  1013;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3109700918920506439 WM1166a9813467;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a9813910;
+			checksum 0 2406567345 WM1166a9813910;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1160 506;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #3109700918920506439 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #3109700918920506439;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 899 439;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 899 439;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 02.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'This exercise shows how to concatenate a matrix of one gene onto the end of another when the taxon names in the two genes don''t match. ^n^nFirst, open up the matrix that will be the master matrix.  In general this will be the matrix with the largest number of taxa.  ^n^nIt is a good idea for the taxa block and character blocks to be named with the gene names (in this file the taxa block is named "28S Taxa" and the character matrix "28S").  You can rename these entiti [...]
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/02.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/02.concatenatingMatrices.nex
new file mode 100644
index 0000000..1898e3d
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/02.concatenatingMatrices.nex
@@ -0,0 +1,509 @@
+#NEXUS
+[written Sun Jun 08 13:17:44 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a983aef8;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	LINK TAXA = 28S_Taxa;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a983b250;
+
+
+END;
+
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' 'Lodus mundum CA:Cache  [...]
+	;
+	BLOCKID WM1166a983b8f9;
+
+END;
+
+
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'             Geneva '9' '238' '1'             all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'             000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'             000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /             00 ? -;
+	Correlation '0' '0' '1000' '0' '0'             10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'             110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'             1;
+	Calculations 0000001;
+	SummaryMode '0' '0'             0;
+	Charts  Geneva '9' (            normal )             0010;
+	NexusOptions '0' '0' '50'             001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (            normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'             1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'             1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'             1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'             0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'             1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'             Geneva '9' (            normal )             Geneva '10' (            normal )             Geneva '9' (            normal )             Geneva '9' (            normal )             Geneva '9' (            bold )             Geneva '9' (            normal )             Geneva '9' (            normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'             00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'             100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'             1010;
+	BothTools '1';
+
+END;
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	LINK TAXA = COI_Taxa;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                      -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_UT_1431                      -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_WA_1285                      --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	'Lodus darlingontielum CA:Cache Ck 2081'   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'            -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'            ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'          ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'          ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 1980'           ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 2000'           -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus nitidum AZ: Safford 2121'           ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'       --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2122'              ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2123'              ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGM [...]
+
+	'Lodus mundum CA:Cache Ck 2079'            --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Cache Ck 2080'            ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Kern R. 1973'             ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Smith R. 1979'            ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum NV:Weeks 1981'               ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum OR:Nestucca R 2001'          -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum WA:Nooksack R 1329'          ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'       ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'       ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'       ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'       ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120'    ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: San Fran R. 1426' -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGG [...]
+
+	Lodus_sp_nr_jucundum_AZ_2172               ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2170               ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2171               ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+
+;
+
+
+		BLOCKID WM1166a983baf0;
+
+
+END;
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET * UNTITLED  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 [...]
+	CODONPOSSET CodonPositions  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 [...]
+
+	CODESET * UNTITLED  (CHARACTERS = 28S)  =  universal:  1 -  1013;
+	CODESET * UNTITLED  (CHARACTERS = COI_matrix)  =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =            unord PolyTcount =            MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = 28S)  =  unord:  1 -  1013;
+TYPESET * UNTITLED  (CHARACTERS = COI_matrix)  =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  (CHARACTERS = 28S) =  1 -  75 934 -  1013;
+EXSET * UNTITLED  (CHARACTERS = COI_matrix) =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = 28S)  =  'Jukes-Cantor':  1 -  1013;
+ProbModelSet * UNTITLED  (CHARACTERS = COI_matrix)  =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a983aef8;
+			setID 1 7930456106631574389 WM1166a983b8f9;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a983b250;
+			checksum 0 2406567345 WM1166a983b250;
+			setID 1 5612116444611320697 WM1166a983baf0;
+			checksum 1 1740396078 WM1166a983baf0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1110 484;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1706495900755261206 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1706495900755261206;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 03.concatenatingMatrices.nex;
+			setPrevFileName 01.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'Now the second matrix (called "COI matrix") with the second taxa block (called "COI Taxa") is included in this file.^n^nNext, tell Mesquite to establish an association between the two taxa block. To do this, choose New Assocation from the Taxa&Trees menu.  In the dialog box that appears, choose the taxa block that is the "master" block - in this case, "28S Taxa".  You will then be asked to name the association.  Let''s call this one "28S - COI" to indicate that it is  [...]
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/03.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/03.concatenatingMatrices.nex
new file mode 100644
index 0000000..649bbeb
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/03.concatenatingMatrices.nex
@@ -0,0 +1,530 @@
+#NEXUS
+[written Sun Jun 08 13:17:51 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a985af710;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	LINK TAXA = 28S_Taxa;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a985b3c0;
+
+
+END;
+
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' 'Lodus mundum CA:Cache  [...]
+	;
+	BLOCKID WM1166a985b8b11;
+
+END;
+
+
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'             Geneva '9' '238' '1'             all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'             000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'             000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /             00 ? -;
+	Correlation '0' '0' '1000' '0' '0'             10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'             110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'             1;
+	Calculations 0000001;
+	SummaryMode '0' '0'             0;
+	Charts  Geneva '9' (            normal )             0010;
+	NexusOptions '0' '0' '50'             001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (            normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'             1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'             1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'             1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'             0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'             1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'             Geneva '9' (            normal )             Geneva '10' (            normal )             Geneva '9' (            normal )             Geneva '9' (            normal )             Geneva '9' (            bold )             Geneva '9' (            normal )             Geneva '9' (            normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'             00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'             100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'             1010;
+	BothTools '1';
+
+END;
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	LINK TAXA = COI_Taxa;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                      -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_UT_1431                      -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_WA_1285                      --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	'Lodus darlingontielum CA:Cache Ck 2081'   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'            -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'            ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'          ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'          ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 1980'           ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 2000'           -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus nitidum AZ: Safford 2121'           ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'       --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2122'              ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2123'              ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGM [...]
+
+	'Lodus mundum CA:Cache Ck 2079'            --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Cache Ck 2080'            ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Kern R. 1973'             ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Smith R. 1979'            ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum NV:Weeks 1981'               ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum OR:Nestucca R 2001'          -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum WA:Nooksack R 1329'          ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'       ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'       ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'       ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'       ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120'    ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: San Fran R. 1426' -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGG [...]
+
+	Lodus_sp_nr_jucundum_AZ_2172               ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2170               ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2171               ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+
+;
+
+
+		BLOCKID WM1166a985bac0;
+
+
+END;
+
+BEGIN TaxaAssociation;
+TITLE '28S - COI';
+TAXA 28S_Taxa ,  COI_Taxa;
+ASSOCIATES 
+
+	Lodus_radians_CA_2076 /  Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' [...]
+
+;
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET * UNTITLED  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 [...]
+	CODONPOSSET CodonPositions  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 [...]
+
+	CODESET * UNTITLED  (CHARACTERS = 28S)  =  universal:  1 -  1013;
+	CODESET * UNTITLED  (CHARACTERS = COI_matrix)  =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =            unord PolyTcount =            MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = 28S)  =  unord:  1 -  1013;
+TYPESET * UNTITLED  (CHARACTERS = COI_matrix)  =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  (CHARACTERS = 28S) =  1 -  75 934 -  1013;
+EXSET * UNTITLED  (CHARACTERS = COI_matrix) =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = 28S)  =  'Jukes-Cantor':  1 -  1013;
+ProbModelSet * UNTITLED  (CHARACTERS = COI_matrix)  =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a985af710;
+			setID 1 7930456106631574389 WM1166a985b8b11;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a985b3c0;
+			checksum 0 2406567345 WM1166a985b3c0;
+			setID 1 5612116444611320697 WM1166a985bac0;
+			checksum 1 1740396078 WM1166a985bac0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1110 484;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1706495900755261206 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1706495900755261206;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getAssociationsTask Stored Taxa Associations (id# 1097);
+					resetAssociation;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 04.concatenatingMatrices.nex;
+			setPrevFileName 02.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'Mesquite has opened up the taxa list window showing the 28S taxa on the left, and a list on the right of the COI taxa.  In between is a new column, called COI Taxa, in which you are to list which taxon in the COI Taxa block corresponds to which one in the 28S Taxa block.  At the moment that list is empty.^n^nTo establish a specific association, you can select the line in the 28S Taxa list (by touching on that taxon''s row number, for example), then select the correspo [...]
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/04.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/04.concatenatingMatrices.nex
new file mode 100644
index 0000000..56f165a
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/04.concatenatingMatrices.nex
@@ -0,0 +1,534 @@
+#NEXUS
+[written Sun Jun 08 13:17:58 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a987ab712;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	LINK TAXA = 28S_Taxa;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a987af70;
+
+
+END;
+
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' 'Lodus mundum CA:Cache  [...]
+	;
+	BLOCKID WM1166a987b3e13;
+
+END;
+
+
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'            Geneva '9' '238' '1'            all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'            000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'            000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /            00 ? -;
+	Correlation '0' '0' '1000' '0' '0'            10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'            110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'            1;
+	Calculations 0000001;
+	SummaryMode '0' '0'            0;
+	Charts  Geneva '9' (           normal )            0010;
+	NexusOptions '0' '0' '50'            001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (           normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'            1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'            1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'            1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'            0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'            1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'            Geneva '9' (           normal )            Geneva '10' (           normal )            Geneva '9' (           normal )            Geneva '9' (           normal )            Geneva '9' (           bold )            Geneva '9' (           normal )            Geneva '9' (           normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '1' '1' '1 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'            00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'            100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'            1010;
+	BothTools '1';
+
+END;
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	LINK TAXA = COI_Taxa;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                      -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_UT_1431                      -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_WA_1285                      --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	'Lodus darlingontielum CA:Cache Ck 2081'   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'            -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'            ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'          ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'          ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 1980'           ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 2000'           -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus nitidum AZ: Safford 2121'           ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'       --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2122'              ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2123'              ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGM [...]
+
+	'Lodus mundum CA:Cache Ck 2079'            --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Cache Ck 2080'            ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Kern R. 1973'             ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Smith R. 1979'            ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum NV:Weeks 1981'               ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum OR:Nestucca R 2001'          -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum WA:Nooksack R 1329'          ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'       ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'       ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'       ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'       ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120'    ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: San Fran R. 1426' -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGG [...]
+
+	Lodus_sp_nr_jucundum_AZ_2172               ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2170               ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2171               ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+
+;
+
+
+		BLOCKID WM1166a987b660;
+
+
+END;
+
+BEGIN TaxaAssociation;
+TITLE '28S - COI';
+TAXA 28S_Taxa ,  COI_Taxa;
+ASSOCIATES 
+
+	Lodus_radians_CA_2076 /  Lodus_radians_CA_2076
+
+;
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET * UNTITLED  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 [...]
+	CODONPOSSET CodonPositions  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 [...]
+
+	CODESET * UNTITLED  (CHARACTERS = 28S)  =  universal:  1 -  1013;
+	CODESET * UNTITLED  (CHARACTERS = COI_matrix)  =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =           unord PolyTcount =           MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = 28S)  =  unord:  1 -  1013;
+TYPESET * UNTITLED  (CHARACTERS = COI_matrix)  =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  (CHARACTERS = 28S) =  1 -  75 934 -  1013;
+EXSET * UNTITLED  (CHARACTERS = COI_matrix) =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = 28S)  =  'Jukes-Cantor':  1 -  1013;
+ProbModelSet * UNTITLED  (CHARACTERS = COI_matrix)  =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a987ab712;
+			setID 1 7930456106631574389 WM1166a987b3e13;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a987af70;
+			checksum 0 2406567345 WM1166a987af70;
+			setID 1 5612116444611320697 WM1166a987b660;
+			checksum 1 1740396078 WM1166a987b660;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1110 484;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1706495900755261206 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1706495900755261206;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getAssociationsTask Stored Taxa Associations (id# 1284);
+					resetAssociation;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+					getTable;
+					tell It;
+						columnWidth 2 90;
+					endTell;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 849 417;
+					setLocation 60 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 05.concatenatingMatrices.nex;
+			setPrevFileName 03.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'You might want to expand that COI Tax column in the middle so that you can see the whole name; you can do this by moving the mouse up to the boundary of the column to the right of the column''s title, and dragging to the right.^n^nWhile you could do this one at a time, it''s easiest to do this by asking Mesquite to look at the names of the taxa and trying to find matches.  To do this, choose Select All from the Edit menu to select the entire table.  Then, touch on the [...]
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/05.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/05.concatenatingMatrices.nex
new file mode 100644
index 0000000..ef0dc54
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/05.concatenatingMatrices.nex
@@ -0,0 +1,557 @@
+#NEXUS
+[written Sun Jun 08 13:18:02 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a989c4314;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	LINK TAXA = 28S_Taxa;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a989c7f0;
+
+
+END;
+
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' 'Lodus mundum CA:Cache  [...]
+	;
+	BLOCKID WM1166a989cd415;
+
+END;
+
+
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'              Geneva '9' '238' '1'              all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'              000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'              000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /              00 ? -;
+	Correlation '0' '0' '1000' '0' '0'              10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'              110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'              1;
+	Calculations 0000001;
+	SummaryMode '0' '0'              0;
+	Charts  Geneva '9' (             normal )              0010;
+	NexusOptions '0' '0' '50'              001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (             normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'              1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'              1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'              1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'              0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'              1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'              Geneva '9' (             normal )              Geneva '10' (             normal )              Geneva '9' (             normal )              Geneva '9' (             normal )              Geneva '9' (             bold )              Geneva '9' (             normal )              Geneva '9' (             normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0 [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'              00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'              100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'              1010;
+	BothTools '1';
+
+END;
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	LINK TAXA = COI_Taxa;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                      -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_UT_1431                      -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_WA_1285                      --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	'Lodus darlingontielum CA:Cache Ck 2081'   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'            -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'            ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'          ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'          ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 1980'           ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 2000'           -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus nitidum AZ: Safford 2121'           ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'       --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2122'              ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2123'              ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGM [...]
+
+	'Lodus mundum CA:Cache Ck 2079'            --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Cache Ck 2080'            ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Kern R. 1973'             ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Smith R. 1979'            ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum NV:Weeks 1981'               ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum OR:Nestucca R 2001'          -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum WA:Nooksack R 1329'          ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'       ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'       ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'       ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'       ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120'    ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: San Fran R. 1426' -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGG [...]
+
+	Lodus_sp_nr_jucundum_AZ_2172               ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2170               ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2171               ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+
+;
+
+
+		BLOCKID WM1166a989cef0;
+
+
+END;
+
+BEGIN TaxaAssociation;
+TITLE '28S - COI';
+TAXA 28S_Taxa ,  COI_Taxa;
+ASSOCIATES 
+
+	Lodus_radians_CA_2076 /  Lodus_radians_CA_2076 , 
+	Lodus_radians_UT_1431 /  Lodus_radians_UT_1431 , 
+	Lodus_radians_WA_1285 /  Lodus_radians_WA_1285 , 
+	'Lodus sierra CA:Putah Ck 1414' /  'Lodus sierra CA:Putah Ck 1414' , 
+	'Lodus sierra CA:Cache Ck 2167' /  'Lodus sierra CA:Cache Ck 2167' , 
+	'Lodus jucundum CA:Cache Ck 2077' /  'Lodus jucundum CA:Cache Ck 2077' , 
+	'Lodus jucundum CA:Cache Ck 2078' /  'Lodus jucundum CA:Cache Ck 2078' , 
+	'Lodus jucundum CA:Shively 1980' /  'Lodus jucundum CA:Shively 1980' , 
+	'Lodus jucundum CA:Shively 2000' /  'Lodus jucundum CA:Shively 2000' , 
+	'Lodus nitidum CA: Pine Valley 1972' /  'Lodus nitidum CA: Pine Valley 1972' , 
+	'Lodus nitidum NM: Gila 2122' /  'Lodus nitidum NM: Gila 2122' , 
+	'Lodus nitidum NM: Gila 2123' /  'Lodus nitidum NM: Gila 2123' , 
+	'Lodus mundum CA: Cache Ck 2079' /  'Lodus mundum CA:Cache Ck 2079' , 
+	'Lodus mundum CA: Cache Ck 2080' /  'Lodus mundum CA:Cache Ck 2080' , 
+	'Lodus mundum CA: Kern R. 1973' /  'Lodus mundum CA:Kern R. 1973' , 
+	'Lodus mundum CA: Smith R. 1979' /  'Lodus mundum CA:Smith R. 1979' , 
+	'Lodus mundum NV: Weeks 1981' /  'Lodus mundum NV:Weeks 1981' , 
+	'Lodus mundum OR: Nestucca R 2001' /  'Lodus mundum OR:Nestucca R 2001' , 
+	'Lodus mundum WA: Nooksack R 1329' /  'Lodus mundum WA:Nooksack R 1329' , 
+	'Lodus sp nr jucundum NM: Gila 2115' /  'Lodus sp nr jucundum NM: Gila 2115' , 
+	'Lodus sp nr jucundum NM: Gila 2116' /  'Lodus sp nr jucundum NM: Gila 2116' , 
+	'Lodus sp nr jucundum NM: Gila 2132' /  'Lodus sp nr jucundum NM: Gila 2132' , 
+	'Lodus sp nr jucundum NM: Gila 2133' /  'Lodus sp nr jucundum NM: Gila 2133' , 
+	'Lodus sp nr jucundum NM: Reserve 2120' /  'Lodus sp nr jucundum NM: Reserve 2120'
+
+;
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET * UNTITLED  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 [...]
+	CODONPOSSET CodonPositions  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 [...]
+
+	CODESET * UNTITLED  (CHARACTERS = 28S)  =  universal:  1 -  1013;
+	CODESET * UNTITLED  (CHARACTERS = COI_matrix)  =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =             unord PolyTcount =             MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = 28S)  =  unord:  1 -  1013;
+TYPESET * UNTITLED  (CHARACTERS = COI_matrix)  =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  (CHARACTERS = 28S) =  1 -  75 934 -  1013;
+EXSET * UNTITLED  (CHARACTERS = COI_matrix) =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = 28S)  =  'Jukes-Cantor':  1 -  1013;
+ProbModelSet * UNTITLED  (CHARACTERS = COI_matrix)  =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a989c4314;
+			setID 1 7930456106631574389 WM1166a989cd415;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a989c7f0;
+			checksum 0 2406567345 WM1166a989c7f0;
+			setID 1 5612116444611320697 WM1166a989cef0;
+			checksum 1 1740396078 WM1166a989cef0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1175 484;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1706495900755261206 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1706495900755261206;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getAssociationsTask Stored Taxa Associations (id# 1471);
+					resetAssociation;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+					getTable;
+					tell It;
+						columnWidth 2 132;
+					endTell;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 06.concatenatingMatrices.nex;
+			setPrevFileName 04.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'You could now move over from the "holding bin" on the right the remaining taxa that Mesquite could not match manually.  These taxa without a match are still shown in black and indented, whereas the matched taxa are now shown in gray.  ^n^nBut instead of doing it manually, you could redo the Auto-Assign feature but this time ask for Mesquite to look for numbers in the names to do the match.';
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/06.concatenatingMatrices.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/06.concatenatingMatrices.nex
new file mode 100644
index 0000000..40e87f9
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/06.concatenatingMatrices.nex
@@ -0,0 +1,563 @@
+#NEXUS
+[written Sun Jun 08 13:18:09 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE 28S_Taxa;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a98c15516;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  28S;
+	LINK TAXA = 28S_Taxa;
+	DIMENSIONS  NCHAR=1013;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+
+
+;
+
+
+		BLOCKID WM1166a98c18a0;
+
+
+END;
+
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus darlingontielum CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' 'Lodus nitidum AZ: Safford 2121' 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus mundum CA:Cache Ck 2079' 'Lodus mundum CA:Cache  [...]
+	;
+	BLOCKID WM1166a98c1dd17;
+
+END;
+
+
+BEGIN paup;
+	outgroup Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285;
+
+END;
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076749792;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001111111100100010111 '1' '12'               Geneva '9' '238' '1'               all;
+	EditorPosition '49' '221' '723' '909';
+	TreeWindowPosition '46' '6' '797' '1230';
+	ListWindow Characters closed Geneva '9' '50' '10' '129' '406'               000;
+	ListWindow Taxa closed Geneva '9' '50' '25' '225' '535'               000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /               00 ? -;
+	Correlation '0' '0' '1000' '0' '0'               10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'               110000;
+	PrettyPrint 10;
+	EditorToolsPosition '611' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'               1;
+	Calculations 0000001;
+	SummaryMode '0' '0'               0;
+	Charts  Geneva '9' (              normal )               0010;
+	NexusOptions '0' '0' '50'               001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (              normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'               1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'               1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'               1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'               0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'               1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'               Geneva '9' (              normal )               Geneva '10' (              normal )               Geneva '9' (              normal )               Geneva '9' (              normal )               Geneva '9' (              bold )               Geneva '9' (              normal )               Geneva '9' (              normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'  [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'               00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'               100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'               1010;
+	BothTools '1';
+
+END;
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	LINK TAXA = COI_Taxa;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                      -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_UT_1431                      -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	Lodus_radians_WA_1285                      --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGA [...]
+
+	'Lodus darlingontielum CA:Cache Ck 2081'   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Putah Ck 1414'            -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus sierra CA:Cache Ck 2167'            ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2077'          ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Cache Ck 2078'          ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 1980'           ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus jucundum CA:Shively 2000'           -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus nitidum AZ: Safford 2121'           ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum CA: Pine Valley 1972'       --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2122'              ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGA [...]
+
+	'Lodus nitidum NM: Gila 2123'              ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGM [...]
+
+	'Lodus mundum CA:Cache Ck 2079'            --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Cache Ck 2080'            ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Kern R. 1973'             ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum CA:Smith R. 1979'            ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum NV:Weeks 1981'               ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum OR:Nestucca R 2001'          -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus mundum WA:Nooksack R 1329'          ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2132'       ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2133'       ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2115'       ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Gila 2116'       ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: Reserve 2120'    ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	'Lodus sp nr jucundum NM: San Fran R. 1426' -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGG [...]
+
+	Lodus_sp_nr_jucundum_AZ_2172               ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2170               ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+	Lodus_sp_nr_jucundum_AZ_2171               ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGA [...]
+
+
+;
+
+
+		BLOCKID WM1166a98c1fd0;
+
+
+END;
+
+BEGIN TaxaAssociation;
+TITLE '28S - COI';
+TAXA 28S_Taxa ,  COI_Taxa;
+ASSOCIATES 
+
+	Lodus_radians_CA_2076 /  Lodus_radians_CA_2076 , 
+	Lodus_radians_UT_1431 /  Lodus_radians_UT_1431 , 
+	Lodus_radians_WA_1285 /  Lodus_radians_WA_1285 , 
+	'Lodus sierra CA:Cache Ck 2081' /  'Lodus darlingontielum CA:Cache Ck 2081' , 
+	'Lodus sierra CA:Putah Ck 1414' /  'Lodus sierra CA:Putah Ck 1414' , 
+	'Lodus sierra CA:Cache Ck 2167' /  'Lodus sierra CA:Cache Ck 2167' , 
+	'Lodus jucundum CA:Cache Ck 2077' /  'Lodus jucundum CA:Cache Ck 2077' , 
+	'Lodus jucundum CA:Cache Ck 2078' /  'Lodus jucundum CA:Cache Ck 2078' , 
+	'Lodus jucundum CA:Shively 1980' /  'Lodus jucundum CA:Shively 1980' , 
+	'Lodus jucundum CA:Shively 2000' /  'Lodus jucundum CA:Shively 2000' , 
+	Lodus_nitidum_AZ_2121 /  'Lodus nitidum AZ: Safford 2121' , 
+	'Lodus nitidum CA: Pine Valley 1972' /  'Lodus nitidum CA: Pine Valley 1972' , 
+	'Lodus nitidum NM: Gila 2122' /  'Lodus nitidum NM: Gila 2122' , 
+	'Lodus nitidum NM: Gila 2123' /  'Lodus nitidum NM: Gila 2123' , 
+	'Lodus mundum CA: Cache Ck 2079' /  'Lodus mundum CA:Cache Ck 2079' , 
+	'Lodus mundum CA: Cache Ck 2080' /  'Lodus mundum CA:Cache Ck 2080' , 
+	'Lodus mundum CA: Kern R. 1973' /  'Lodus mundum CA:Kern R. 1973' , 
+	'Lodus mundum CA: Smith R. 1979' /  'Lodus mundum CA:Smith R. 1979' , 
+	'Lodus mundum NV: Weeks 1981' /  'Lodus mundum NV:Weeks 1981' , 
+	'Lodus mundum OR: Nestucca R 2001' /  'Lodus mundum OR:Nestucca R 2001' , 
+	'Lodus mundum WA: Nooksack R 1329' /  'Lodus mundum WA:Nooksack R 1329' , 
+	'Lodus sp nr jucundum NM: Alma 1426' /  'Lodus sp nr jucundum NM: San Fran R. 1426' , 
+	'Lodus sp nr jucundum NM: Gila 2115' /  'Lodus sp nr jucundum NM: Gila 2115' , 
+	'Lodus sp nr jucundum NM: Gila 2116' /  'Lodus sp nr jucundum NM: Gila 2116' , 
+	'Lodus sp nr jucundum NM: Gila 2132' /  'Lodus sp nr jucundum NM: Gila 2132' , 
+	'Lodus sp nr jucundum NM: Gila 2133' /  'Lodus sp nr jucundum NM: Gila 2133' , 
+	'Lodus sp nr jucundum NM: Reserve 2120' /  'Lodus sp nr jucundum NM: Reserve 2120' , 
+	'Lodus sp nr jucundum AZ: Sedona 2171' /  Lodus_sp_nr_jucundum_AZ_2171 , 
+	'Lodus sp nr jucundum AZ: Sedona 2170' /  Lodus_sp_nr_jucundum_AZ_2170 , 
+	'Lodus sp nr jucundum AZ: Sedona 2172' /  Lodus_sp_nr_jucundum_AZ_2172
+
+;
+
+END;
+
+
+BEGIN CODONS;
+	CODONPOSSET * UNTITLED  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET CodonPositions  (CHARACTERS = 28S) =  N:  1- 1013 ;
+	CODONPOSSET * UNTITLED  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 [...]
+	CODONPOSSET CodonPositions  (CHARACTERS = COI_matrix) =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 [...]
+
+	CODESET * UNTITLED  (CHARACTERS = 28S)  =  universal:  1 -  1013;
+	CODESET * UNTITLED  (CHARACTERS = COI_matrix)  =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =              unord PolyTcount =              MINSTEPS;
+	TYPESET * UNTITLED  (CHARACTERS = 28S)  =  unord:  1 -  1013;
+TYPESET * UNTITLED  (CHARACTERS = COI_matrix)  =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  (CHARACTERS = 28S) =  1 -  75 934 -  1013;
+EXSET * UNTITLED  (CHARACTERS = COI_matrix) =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = 28S)  =  'Jukes-Cantor':  1 -  1013;
+ProbModelSet * UNTITLED  (CHARACTERS = COI_matrix)  =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a98c15516;
+			setID 1 7930456106631574389 WM1166a98c1dd17;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 1716441836526165232 WM1166a98c18a0;
+			checksum 0 2406567345 WM1166a98c18a0;
+			setID 1 5612116444611320697 WM1166a98c1fd0;
+			checksum 1 1740396078 WM1166a98c1fd0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 1175 484;
+			setLocation 60 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #1706495900755261206 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #1706495900755261206;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getAssociationsTask Stored Taxa Associations (id# 1658);
+					resetAssociation;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+					getTable;
+					tell It;
+						columnWidth 2 132;
+					endTell;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #1716441836526165232 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 914 417;
+					setLocation 60 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setNextFileName 07.mergedMatrix.nex;
+			setPrevFileName 05.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 494 323;
+					setLocation 431 538;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'Mesquite''s now managed to match all of the COI taxa with 28S taxa.^n^nThe association if now fully established.^n^nYou can now merge the matrices by exporting this file to a new Mesquite file.  Choose Export... from the File menu, and choose "Fused Matrix Export (NEXUS)".  You will be given various options; after making your choice, press the Export button.  You will be asked to choose the master block of taxa; in this example, the master block is "28S Taxa".  You wi [...]
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/07.mergedMatrix.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/07.mergedMatrix.nex
new file mode 100644
index 0000000..74b2be7
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/07.mergedMatrix.nex
@@ -0,0 +1,332 @@
+#NEXUS
+[written Sun Jun 08 13:18:13 MST 2008 by Mesquite  version 2.5 BETA 2 (build j76) at Odontium/192.168.0.3 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Taxa_Block;
+	DIMENSIONS NTAX=32;
+	TAXLABELS
+		Lodus_radians_CA_2076 Lodus_radians_UT_1431 Lodus_radians_WA_1285 'Lodus sierra CA:Cache Ck 2081' 'Lodus sierra CA:Putah Ck 1414' 'Lodus sierra CA:Cache Ck 2167' 'Lodus jucundum CA:Cache Ck 2077' 'Lodus jucundum CA:Cache Ck 2078' 'Lodus jucundum CA:Shively 1980' 'Lodus jucundum CA:Shively 2000' Lodus_nitidum_AZ_2121 'Lodus nitidum CA: Pine Valley 1972' 'Lodus nitidum NM: Gila 2122' 'Lodus nitidum NM: Gila 2123' 'Lodus nitidum NM: Largo Ck 1408' 'Lodus mundum CA: Cache Ck 2079' 'Lodus m [...]
+	;
+	BLOCKID WM1166a98e96b18;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=2021;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Lodus_radians_CA_2076                  ------------cagcactgaAGCCCGTggtCggaaacggctactgggcaatgtAgtgtttgg-agagcccGtttaACccgagcactgttagcgtgtccaagtMYtKcttgaagRKKScYACWCGCSCATAGAggGTGcCAGGCCCGTtATGACCGTTAATATGttcgggtGGgYKtctccttagagTCGGGTTGCTTGAGAGTGCAGCTCtAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACcgtGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+---------------------
+
+	Lodus_radians_UT_1431                  ------aaagcccagcactgaagcccgtggtcggaaacggctactgggcaatgtagtgtt-gggagagcccgtttaacccgagcactgttagcgtgtccaagtccttcttgaagggggccactcgcccatagagggtgccaggcccgttatgaccgttaatatgttcgggtgggtWtctccttagagtcgggttgcttgAGAgtgCAgctctaAGTGGgtggtaaactccatctaagGCTAAATAtaaccacgAGACcgATAGCGAACAAGTAccgTgAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+---------------------
+
+	Lodus_radians_WA_1285                  --------------------------------------------------------gYtY-gggaKagCccGtttaacccGagcactgttagcgtgtccaaKtccttcTTgaaRgggGCCACTCGCCCATAGAGGGTGCCAGGCCCGTTATGACCGTTAATATGTTMgGGTGGGTTTCTCCTTaGaGTCKGGTTGCTTGAGAGTGCAGCTCTAWGTGGGTGGTAAACTCCATCTAAGGCTAAATATAMCCWCGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCRAAAGTTCGAACGGGGAGATTCAATTGCTTTACCGGTGGTGATCAATAGTGCAGTATTTGGGACGCATATGGTGT-GCAGTTTCGGCTGTATT-ATTG [...]
+---------------------
+
+	'Lodus sierra CA:Cache Ck 2081'        -----------------------cccgtggtcgGAAACGgctactgggcaATGTagtGTTTGGGagagccCGtttaacCCGAGCActgttagcgtgtccaagtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus sierra CA:Putah Ck 1414'        -----atgagcccagcactgaagcccgtggtcgRaa-cggctactgGGCAAtgtagtgtt-tggagagccCSTTTAACCCGAGCACTGTTAGCGTGTCCAagtctttcttgaAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTARAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus sierra CA:Cache Ck 2167'        ---------------cactgaagCccgtggtCGGAAACGGCtacTGGGcaaTGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTACGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATACGATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus jucundum CA:Cache Ck 2077'      ------------------tgaagcccgtgttcggaaacgGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus jucundum CA:Cache Ck 2078'      -------------------------cgtggtcgGAAACGGCTActgggca-tgtagtgtt-gGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+agctttagggtt---------
+
+	'Lodus jucundum CA:Shively 1980'       -----------------------------------aacgGCTACTGGGCAATGtAgtgtttggGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus jucundum CA:Shively 2000'       ---------gcccagcactgAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtagtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGGTCGAATGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	Lodus_nitidum_AZ_2121                  ---------------agcactgaAGCccgtgtcgGAAACGGCTACTGGGCAATGtagtgttgGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+agct-----------------
+
+	'Lodus nitidum CA: Pine Valley 1972'   ----------------------------ggtCGGAAACGGCTACTGGGCAATGtagtgtt-gggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+---------------------
+
+	'Lodus nitidum NM: Gila 2122'          ------------ccagcactgAAGCCCGTGGTCGGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGtttaAcCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATtR [...]
+agctttaggatttg-------
+
+	'Lodus nitidum NM: Gila 2123'          -----------gcCCAGCactgagcccgtggtcgGAAACGGCTACTGGGCAATGtAgtgttKGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtcctTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+---------------------
+
+	'Lodus nitidum NM: Largo Ck 1408'      --------------gcactgaagCCCGTGGtCGGAAACGGCTACTGGGCAATGtAGTgtt-tgGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGCCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAT-GCAATTTCGATTGTATT-ATTA [...]
+---------------------
+
+	'Lodus mundum CA: Cache Ck 2079'       ----------------------------------aaacggctactgggcaatgtagtgtttGggagagCCCGtttAACCCGAGCAcTgttagcgtgtccaagtccttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus mundum CA: Cache Ck 2080'       ---------gcccagcactgagccccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGtccttCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus mundum CA: Kern R. 1973'        ------aaagcCCAGCactGAAGCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGAATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus mundum CA: Smith R. 1979'       ----------------actgAAGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+agcattaggat----------
+
+	'Lodus mundum NV: Weeks 1981'          ------------------tgaagCccgtgttcggAAACGgCTACTGGGCAATGtagtgtt-gggAGAGCCCGtttAACCCGAGCACTgttagcGTGTCCaagtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus mundum OR: Nestucca R 2001'     acaggaaaagcccagcactgaAgCccgtg-tcgGAAACGGCTACTGGGCAATGtAgtgtttgggAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGtccTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAGGATATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus mundum WA: Nooksack R 1329'     ------aaagcccagcactgaaGCccgtgttcggAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAAACCCGAAAGGTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATAgRaTATTGCAATTTCGATTGTATTTATTA [...]
+---------------------
+
+	'Lodus sp nr jucundum NM: Alma 1426'   ------------cccagcactgaAgCccgtgtcgGAAACGGCTACTGGGCAATGtAgtgttgggAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+gagcttaggat----------
+
+	'Lodus sp nr jucundum NM: Gila 2115'   ----------------------------------AAACGGCtactgggCAATGtagtgtttggGAGAGCCCGtttaACCCGAGCActgttaGcgtgtccaAGTCcttcttGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum NM: Gila 2116'   ----------------------------------GAAACGGCtAcTGGGCAatgtagtgttKGGAGAGCCCGtttAACCCGAGCactgttagcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+agctttaggatttgtatttct
+
+	'Lodus sp nr jucundum NM: Gila 2132'   ------------cagcactgaagCCcgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum NM: Gila 2133'   ------------cagcactgaagcccgtgttcgaaaacggCtactgGGCAATKTAGTGTTTGGGAGAGCcCGtttAACccgagcActGTTAgcgtgtccaagtcctTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum NM: Reserve 2120' --aggaaaagccCAgcactgaagcccgtggtcgGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCcTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATT [...]
+---------------------
+
+	'Lodus sp nr jucundum AZ: Sedona 2171' ----------cccagcactgaagCccgtggtCGGAAACGgctACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum AZ: Sedona 2170' ----------cccagcactgaagCccgtggtCGGAAACGgctactgGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum AZ: Sedona 2169' ----------cccagcactgaagCccgtggtcgGAAACGgctactGGGCAATGTAGTGTTTGGGAGAGCCCGtttAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+	'Lodus sp nr jucundum AZ: Sedona 2172' ----------cccAgcactgaAGCCCGtggtCGGAAACGGCTACTGGGCAATGTAGTGTTTGGGAGAGCCCGTTTAACCCGAGCACTGTTAGCGTGTCCAAGTCCTTCTTGAAGGGGGTCACTCGCCCATAGAGGGTGCCAGTCCCGTTATGACCGTTAATATGTTCGGGTGGGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATAACCACGAGACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACCGTTCAGGGGTAAACCTGAGAGACCCGAAAGTTCGAACGGGGAGATTCAATTGATTTACCGGTGATGATCAATAGTGCAGTATTTGGGACGCATATGATAATGCAATTTCGATTGTATTTATTT [...]
+---------------------
+
+
+;
+
+
+		BLOCKID WM1166a98e9ab0;
+
+
+END;
+
+begin mrbayes;
+	charset 28S =     1 -1013;
+	charset COI_matrix =     1014 -2021;
+	charset COI_matrixNonCoding =      1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021;
+	charset COI_matrixCodonPos1 =      1015 -1978 \    3;
+	charset COI_matrixCodonPos2 =      1016 -1979 \    3;
+	charset COI_matrixCodonPos3 =      1014 -1980 \    3;
+	partition matrices =     2 :     28S ,     COI_matrix;
+	set partition =     matrices;
+	lset applyto = (    1 ,     2 )      nst =    6 rates =    invgamma;
+	unlink statefreq = (    all )     revmat = (    all )     shape = (    all )     pinvar = (    all );
+	prset applyto = (    all )     ratepr =    variable;
+	mcmcp ngen =     10000000 relburnin =    yes burninfrac =    0.5 printfreq =    1000  samplefreq =    1000 nchains =    4 savebrlens =    yes;
+	mcmc;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL 28S;
+	CHARGROUPLABEL COI_matrix;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET 28S   =   1 -  1013;
+	CHARSET COI_matrix   =   1014 -  2021;
+
+	CHARPARTITION * UNTITLED  =  28S :  1 -  1013, COI_matrix :  1014 -  2021;
+	CHARPARTITION matrices  =  28S :  1 -  1013, COI_matrix :  1014 -  2021;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2021;
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  2021;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  2021;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3390976928178081870 WM1166a98e96b18;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6777793195415541253 WM1166a98e9ab0;
+			checksum 0 248462374 WM1166a98e9ab0;
+		endTell;
+		getWindow;
+		tell It;
+			setResourcesState false false 261;
+			setPopoutState 400;
+			setExplanationSize 0;
+			setAnnotationSize 0;
+			setFontIncAnnot 0;
+			setFontIncExp 0;
+			setSize 991 475;
+			setLocation 8 22;
+			setFont SanSerif;
+			setFontSize 10;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #6777793195415541253 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 730 408;
+					setLocation 8 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					colorRowNames  #mesquite.charMatrices.TaxonGroupColor.TaxonGroupColor;
+					colorColumnNames  #mesquite.charMatrices.CharGroupColor.CharGroupColor;
+					colorText  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleAllowAutosize off;
+					toggleColorsPanel off;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.molec.ColorByAA.ColorByAA;
+				tell It;
+					emphasizeDegeneracy off;
+				endTell;
+				getEmployee #mesquite.molec.SequenceInfoEditor.SequenceInfoEditor;
+				tell It;
+					panelOpen false;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			showCharacters #6777793195415541253 #mesquite.lists.CharacterList.CharacterList;
+			tell It;
+				setData 0;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.CharListInclusion.CharListInclusion;
+					newAssistant  #mesquite.stochchar.CharListProbModels.CharListProbModels;
+					newAssistant  #mesquite.lists.CharListCodonPos.CharListCodonPos;
+					newAssistant  #mesquite.lists.CharListPartition.CharListPartition;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 730 408;
+					setLocation 8 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.CharListAnnotPanel.CharListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.ExamplesNavigator.ExamplesNavigator;
+		tell It;
+			setPrevFileName 06.concatenatingMatrices.nex;
+			getWindow;
+			tell It;
+					popAsTile false;
+					popOut;
+					setExplanationSize 0;
+					setAnnotationSize 0;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 502 257;
+					setLocation 247 534;
+					setFont Arial;
+					setFontSize 14;
+				setExplanation 'Here''s the merged matrix.';
+				setTitle Concatenating_Matrices;
+				toggleFileNames off;
+				setPrevButtonName Previous;
+				setNextButtonName Next;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/otherGeneMatrix.nex b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/otherGeneMatrix.nex
new file mode 100644
index 0000000..a9bfd03
--- /dev/null
+++ b/Resources/examples/Other_Examples/ConcatenatingMatrices/TaxonNamesAreDifferent/otherGeneMatrix.nex
@@ -0,0 +1,258 @@
+#NEXUS
+[written Thu Nov 22 19:42:13 PST 2007 by Mesquite  version 2.0+ (build j18a) at Thrandina.local/10.0.1.3 (Wayne Maddison)]
+
+BEGIN TAXA;
+	TITLE COI_Taxa;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		beetle_1 beetle_2 beetle_3 beetle_4 beetle_5 beetle_6 beetle_7 beetle_8 beetle_9 beetle_10 beetle_11 beetle_12 beetle_13 beetle_14 beetle_15 beetle_16 beetle_17 beetle_18 beetle_19 beetle_20 beetle_21 beetle_22 beetle_23 beetle_24 beetle_25 beetle_26 beetle_27 beetle_28 beetle_29 beetle_30 
+	;
+	BLOCKID WM1166a99165219;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  COI_matrix;
+	DIMENSIONS  NCHAR=1008;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	beetle_1   -cataaggatattgGAaCTTTATATTTTATTTTTGGTGCTTGAtctggaATAGTtggaACCTCTTTAAGAatACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGAGCTGTAAATTTTATTACCACTATTATTAATAT [...]
+
+	beetle_2   -------------------------------tttggtgcttGAtCTggAATAGTTGGAAcCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGAGCTGTAAATTTTATTACCACTATTATTAATAT [...]
+
+	beetle_3   --ataaGGATAtTGgaaCTTTATATTTTATTTTTGGTGCTTGATctggAATAGTTGGAACCTCTTTAAGAATACTAATTCGAGCTGAATTAGGTAACCCCGGATCTTTAATTGGTGATGATCAAATTTATAATGTAATTGTTACTGCTCATGCATTTGTTATAATTTTCTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCTTTAATGTTAGGAGCACCAGATATAGCATTTCCACGAATGAATAATATAAGATTTTGATTATTACCTCCTTCTTTAACTTTATTAATAATAAGCTCTATAGTAGAAAGAGGAGCTGGGACAGGTTGAACCGTTTACCCTCCCCTATCTTCTTCTATTGCCCATAGAGGAGCATCTGTCGACCTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCTTCTATTTTAGGAGCTGTAAATTTTATTACCACTATTATTAATAT [...]
+
+	beetle_4   ---taaggatattggaacactatatTttatttttggagcttgATCaggaatagTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCMGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCCACAATTATTAATAT [...]
+
+	beetle_5   -------------------------------------------------ATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCCACAATTATTAATAT [...]
+
+	beetle_6   ---------tattggaacactaTATTTTaTTTTtggAgcttgatcaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCCGAATTAGGAAATCCAGGATCTTTAATTGGAGACRATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTTCCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGGGCAGGTACAGGTTGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCCACAATTATTAATAT [...]
+
+	beetle_7   ccataaGGATaTTGgaacactatatttcatttttggagcttgatcaGGTATAGTAGGAACTtctTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_8   ----------------------------------------tgatcaggtATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_9   ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_10  -cataaGGaTattggaacacTatatttcatttttggagcttgatcaggTATAGTAGGAAcTTCTTTAAGAatatTAATTCGAGCTGAATTAGGAAATCCGGGATCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAACATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTTTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGACTACATCTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_11  ----------attggRacRctatatttcatYtttggagcttgatcaggaatagTAGGAACTTctttaAgAATATTAATTCGAGCAGAATTAGGAAATCCMGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCCGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_12  --ataaGGatattggaacactatATTtcaTTTTTGGAGCTTGATCaggaATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_13  ccataaggataTTGGAAcactATATTtcatttttgGAgcttgatcaRgaATagTARGAACTTCTTTAAGAATATTAATTCGAGCAGAATTAGGAAATCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCWTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAGTTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_14  ----aaggatatKggaRcRctatatttcWttYttggagcttgAtcaRgaatagTAGGAACTTctYYaagAMTATTAATTCGAGCAGAATTAGGAAMTCCAGGATCTTTAATTGGAGATGATCAAATCTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTTATACCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTAATACTAGGAGCCCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCAGGTACAGGTTGAACCGTTTACCCTCCTCTTTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTMGATTACATTTAGCAGGAGTTTCATCTATTTTAGGMGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_15  --ataaGGATattggaacaTtatatttcatttTTGGAgCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_16  ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_17  ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_18  ----------------------------------------TGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCTCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTTAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_19  ----------AtTGGAACATTATATTTcatTTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_20  -catAAGGATATTGgaaCATTATATTTCAtttttggagCTTgAtcagGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_21  ------------------------------TTTTGGAGCTTGATCAGGTATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAATCCAGGGTCTCTAATTGGAGATGACCAAATCTATAATGTAATTGTCACCGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGTAATTGATTAGTACCATTGATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCACTAACGTTACTATTAATAAGCTCTATAGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCTCATAGAGGAGCTTCAGTAGATTTAGCAATTTTCAGATTACATTTAGCAGGAATTTCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_22  ----aaggatattggaacactatatttcatttttggagcttgatcaggaatagtaggaacttctttaagaatatTaattcGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_23  ----------attggaacgctataTTTcatTTTTGgAgcttGAtcaggaATAGTaggaacTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_24  ---taaggatattggaAcactataTTtcatTTTTGGAgCTTGATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_25  ---taaggatattGGAACactatATTTCATTTTTGgagCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_26  ---taaggaTAttGGAACgctatATTtcatTTTTGGAGCTTgATCAGGAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_27  -------------------------------------------------ATAGTAGGAACTTCTTTAAgaatatTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGACGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGGGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_28  ----------attggaacactATATTTtatttttggagcttgATCaggAATAGTAGGAACTTCTTTAAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_29  ---taaggatattggaacactaTATTTTATTTTTGGAgCTTGATCAGgAATAGTAGGAACTTctttaAGAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+	beetle_30  ----------attggaacactatatttcatttttggagcttgatcaggaATagTAGGAACTtctttAagAATATTAATTCGAGCTGAATTAGGAAACCCAGGATCTCTAATTGGAGATGACCAAATTTATAATGTAATTGTTACTGCACATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGGTTTGGTAATTGATTAGTACCATTAATACTAGGAGCTCCAGATATAGCATTTCCTCGAATAAATAATATAAGATTCTGACTTTTACCTCCTTCATTAACATTATTATTAATAAGTTCTATGGTAGAAAGAGGAGCAGGCACAGGATGAACCGTTTACCCCCCTCTCTCATCTTCAATTGCCCATAGAGGAGCTTCAGTAGATTTGGCAATTTTTAGACTACATTTAGCAGGAGTATCATCTATTTTAGGAGCAGTTAATTTTATTTCTACAATTATTAATAT [...]
+
+
+;
+
+
+		BLOCKID WM1166a99167d0;
+
+
+END;
+
+BEGIN CODONS;
+CODONPOSSET * UNTITLED  =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 344 347 350 353 356 359 36 [...]
+CODONPOSSET CodonPositions  =  N:  968- 1008 , 1: 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 176 179 182 185 188 191 194 197 200 203 206 209 212 215 218 221 224 227 230 233 236 239 242 245 248 251 254 257 260 263 266 269 272 275 278 281 284 287 290 293 296 299 302 305 308 311 314 317 320 323 326 329 332 335 338 341 344 347 350 353 356 35 [...]
+
+CODESET * UNTITLED   =  universal:  1 -  1008;
+
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1076486776;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 100;
+	Editor 00011001111111100100010111 '1' '12'     Geneva '9' '244' '1'     all;
+	EditorPosition '45' '6' '771' '1227';
+	TreeWindowPosition '46' '6' '805' '1230';
+	ListWindow Characters closed Geneva '9' '70' '45' '129' '406'     000;
+	ListWindow Taxa closed Geneva '9' '44' '332' '401' '610'     000000010;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /     00 ? -;
+	Correlation '0' '0' '1000' '0' '0'     10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'     110000;
+	PrettyPrint 10;
+	EditorToolsPosition '658' '46' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'     1;
+	Calculations 0000001;
+	SummaryMode '0' '0'     0;
+	Charts  Geneva '9' (    normal )     0010;
+	NexusOptions '0' '0' '50'     001011001;
+	TipLabel '1';
+	TreeFont  Geneva '9' (    normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'     1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'     1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'     1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'     0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'     1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'     Geneva '9' (    normal )     Geneva '10' (    normal )     Geneva '9' (    normal )     Geneva '9' (    normal )     Geneva '9' (    bold )     Geneva '9' (    normal )     Geneva '9' (    normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '1' '1' '1' '1' '0' '0' '-39' '4' '-40' '0' '1' '2' '1' '8' '0' '0' '0' '2'     1000111000000000000100000111000;
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'     00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '1'     100010101110011;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'     1010;
+	BothTools '1';
+
+END;
+BEGIN paup;
+	outgroup Lodus_radians_WA_1285 Lodus_radians_UT_1431 Lodus_radians_CA_2076;
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =    unord PolyTcount =    MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  1008;
+
+	EXSET * UNTITLED  =  1 -  46 743 -  1008;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  1008;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1706495900755261206 WM1166a99165219;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5612116444611320697 WM1166a99167d0;
+			checksum 0 1740396078 WM1166a99167d0;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5612116444611320697 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 700 500;
+					setLocation 8 22;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Resources/images/32arrow.gif b/Resources/images/32arrow.gif
new file mode 100644
index 0000000..cc68630
Binary files /dev/null and b/Resources/images/32arrow.gif differ
diff --git a/Resources/images/32bucket.gif b/Resources/images/32bucket.gif
new file mode 100644
index 0000000..9ef8536
Binary files /dev/null and b/Resources/images/32bucket.gif differ
diff --git a/Resources/images/32disabled.gif b/Resources/images/32disabled.gif
new file mode 100644
index 0000000..bebace0
Binary files /dev/null and b/Resources/images/32disabled.gif differ
diff --git a/Resources/images/32dropper.gif b/Resources/images/32dropper.gif
new file mode 100644
index 0000000..9c54da2
Binary files /dev/null and b/Resources/images/32dropper.gif differ
diff --git a/Resources/images/32ibeam.gif b/Resources/images/32ibeam.gif
new file mode 100644
index 0000000..251f4c2
Binary files /dev/null and b/Resources/images/32ibeam.gif differ
diff --git a/Resources/images/32info.gif b/Resources/images/32info.gif
new file mode 100644
index 0000000..d5959a9
Binary files /dev/null and b/Resources/images/32info.gif differ
diff --git a/Resources/images/32notesTool.gif b/Resources/images/32notesTool.gif
new file mode 100644
index 0000000..5cb4d95
Binary files /dev/null and b/Resources/images/32notesTool.gif differ
diff --git a/Resources/images/32pointer.gif b/Resources/images/32pointer.gif
new file mode 100644
index 0000000..18ff0e0
Binary files /dev/null and b/Resources/images/32pointer.gif differ
diff --git a/Resources/images/32revSort.gif b/Resources/images/32revSort.gif
new file mode 100644
index 0000000..43846b1
Binary files /dev/null and b/Resources/images/32revSort.gif differ
diff --git a/Resources/images/32sort.gif b/Resources/images/32sort.gif
new file mode 100644
index 0000000..18fa8d4
Binary files /dev/null and b/Resources/images/32sort.gif differ
diff --git a/Resources/images/32wand.gif b/Resources/images/32wand.gif
new file mode 100644
index 0000000..19340d5
Binary files /dev/null and b/Resources/images/32wand.gif differ
diff --git a/Resources/images/32wandMinus.gif b/Resources/images/32wandMinus.gif
new file mode 100644
index 0000000..de41963
Binary files /dev/null and b/Resources/images/32wandMinus.gif differ
diff --git a/Resources/images/32wandPlus.gif b/Resources/images/32wandPlus.gif
new file mode 100644
index 0000000..9409b51
Binary files /dev/null and b/Resources/images/32wandPlus.gif differ
diff --git a/Resources/images/32zoomIn.gif b/Resources/images/32zoomIn.gif
new file mode 100644
index 0000000..94345ed
Binary files /dev/null and b/Resources/images/32zoomIn.gif differ
diff --git a/Resources/images/32zoomOut.gif b/Resources/images/32zoomOut.gif
new file mode 100644
index 0000000..d2854ee
Binary files /dev/null and b/Resources/images/32zoomOut.gif differ
diff --git a/Resources/images/64arrow.gif b/Resources/images/64arrow.gif
new file mode 100644
index 0000000..e4aec3d
Binary files /dev/null and b/Resources/images/64arrow.gif differ
diff --git a/Resources/images/64bucket.gif b/Resources/images/64bucket.gif
new file mode 100644
index 0000000..a94333a
Binary files /dev/null and b/Resources/images/64bucket.gif differ
diff --git a/Resources/images/64disabled.gif b/Resources/images/64disabled.gif
new file mode 100644
index 0000000..3b434f0
Binary files /dev/null and b/Resources/images/64disabled.gif differ
diff --git a/Resources/images/64dropper.gif b/Resources/images/64dropper.gif
new file mode 100644
index 0000000..97e2c9a
Binary files /dev/null and b/Resources/images/64dropper.gif differ
diff --git a/Resources/images/64ibeam.gif b/Resources/images/64ibeam.gif
new file mode 100644
index 0000000..811cde4
Binary files /dev/null and b/Resources/images/64ibeam.gif differ
diff --git a/Resources/images/64info.gif b/Resources/images/64info.gif
new file mode 100644
index 0000000..87b4956
Binary files /dev/null and b/Resources/images/64info.gif differ
diff --git a/Resources/images/64notesTool.gif b/Resources/images/64notesTool.gif
new file mode 100644
index 0000000..09f52f0
Binary files /dev/null and b/Resources/images/64notesTool.gif differ
diff --git a/Resources/images/64pointer.gif b/Resources/images/64pointer.gif
new file mode 100644
index 0000000..51d69a1
Binary files /dev/null and b/Resources/images/64pointer.gif differ
diff --git a/Resources/images/64revSort.gif b/Resources/images/64revSort.gif
new file mode 100644
index 0000000..1d7e502
Binary files /dev/null and b/Resources/images/64revSort.gif differ
diff --git a/Resources/images/64sort.gif b/Resources/images/64sort.gif
new file mode 100644
index 0000000..2415bde
Binary files /dev/null and b/Resources/images/64sort.gif differ
diff --git a/Resources/images/64wand.gif b/Resources/images/64wand.gif
new file mode 100644
index 0000000..d2cea7e
Binary files /dev/null and b/Resources/images/64wand.gif differ
diff --git a/Resources/images/64wandMinus.gif b/Resources/images/64wandMinus.gif
new file mode 100644
index 0000000..df01095
Binary files /dev/null and b/Resources/images/64wandMinus.gif differ
diff --git a/Resources/images/64wandPlus.gif b/Resources/images/64wandPlus.gif
new file mode 100644
index 0000000..d31fcc8
Binary files /dev/null and b/Resources/images/64wandPlus.gif differ
diff --git a/Resources/images/64zoomIn.gif b/Resources/images/64zoomIn.gif
new file mode 100644
index 0000000..f81cdf5
Binary files /dev/null and b/Resources/images/64zoomIn.gif differ
diff --git a/Resources/images/64zoomOut.gif b/Resources/images/64zoomOut.gif
new file mode 100644
index 0000000..f208c52
Binary files /dev/null and b/Resources/images/64zoomOut.gif differ
diff --git a/Resources/images/add.gif b/Resources/images/add.gif
new file mode 100755
index 0000000..7982ce1
Binary files /dev/null and b/Resources/images/add.gif differ
diff --git a/Resources/images/addGray.gif b/Resources/images/addGray.gif
new file mode 100644
index 0000000..69cb7c8
Binary files /dev/null and b/Resources/images/addGray.gif differ
diff --git a/Resources/images/addRemote.gif b/Resources/images/addRemote.gif
new file mode 100755
index 0000000..1e60282
Binary files /dev/null and b/Resources/images/addRemote.gif differ
diff --git a/Resources/images/and.gif b/Resources/images/and.gif
new file mode 100644
index 0000000..c59561d
Binary files /dev/null and b/Resources/images/and.gif differ
diff --git a/Resources/images/annot.gif b/Resources/images/annot.gif
new file mode 100755
index 0000000..a45775e
Binary files /dev/null and b/Resources/images/annot.gif differ
diff --git a/Resources/images/ant_logo_large.gif b/Resources/images/ant_logo_large.gif
new file mode 100644
index 0000000..e99363b
Binary files /dev/null and b/Resources/images/ant_logo_large.gif differ
diff --git a/Resources/images/arrow.gif b/Resources/images/arrow.gif
new file mode 100644
index 0000000..11774aa
Binary files /dev/null and b/Resources/images/arrow.gif differ
diff --git a/Resources/images/back.gif b/Resources/images/back.gif
new file mode 100644
index 0000000..f8223ba
Binary files /dev/null and b/Resources/images/back.gif differ
diff --git a/Resources/images/backDim.gif b/Resources/images/backDim.gif
new file mode 100644
index 0000000..2c30651
Binary files /dev/null and b/Resources/images/backDim.gif differ
diff --git a/Resources/images/banner.gif b/Resources/images/banner.gif
new file mode 100644
index 0000000..d831783
Binary files /dev/null and b/Resources/images/banner.gif differ
diff --git a/Resources/images/bannerBeta.gif b/Resources/images/bannerBeta.gif
new file mode 100755
index 0000000..1221e1b
Binary files /dev/null and b/Resources/images/bannerBeta.gif differ
diff --git a/Resources/images/blackPixel.gif b/Resources/images/blackPixel.gif
new file mode 100644
index 0000000..c9fa37e
Binary files /dev/null and b/Resources/images/blackPixel.gif differ
diff --git a/Resources/images/blackPixel3.gif b/Resources/images/blackPixel3.gif
new file mode 100644
index 0000000..1a77d0c
Binary files /dev/null and b/Resources/images/blackPixel3.gif differ
diff --git a/Resources/images/blank-off.gif b/Resources/images/blank-off.gif
new file mode 100644
index 0000000..c86c20b
Binary files /dev/null and b/Resources/images/blank-off.gif differ
diff --git a/Resources/images/blank-off22.gif b/Resources/images/blank-off22.gif
new file mode 100644
index 0000000..3424066
Binary files /dev/null and b/Resources/images/blank-off22.gif differ
diff --git a/Resources/images/blank-on.gif b/Resources/images/blank-on.gif
new file mode 100644
index 0000000..7bc7f06
Binary files /dev/null and b/Resources/images/blank-on.gif differ
diff --git a/Resources/images/blank-on22.gif b/Resources/images/blank-on22.gif
new file mode 100644
index 0000000..613fc5b
Binary files /dev/null and b/Resources/images/blank-on22.gif differ
diff --git a/Resources/images/blue-ball-small.gif b/Resources/images/blue-ball-small.gif
new file mode 100644
index 0000000..d4c5cde
Binary files /dev/null and b/Resources/images/blue-ball-small.gif differ
diff --git a/Resources/images/bucket.gif b/Resources/images/bucket.gif
new file mode 100644
index 0000000..4525238
Binary files /dev/null and b/Resources/images/bucket.gif differ
diff --git a/Resources/images/buttons.gif b/Resources/images/buttons.gif
new file mode 100644
index 0000000..c7eaa97
Binary files /dev/null and b/Resources/images/buttons.gif differ
diff --git a/Resources/images/checkMark.gif b/Resources/images/checkMark.gif
new file mode 100755
index 0000000..0dde9dd
Binary files /dev/null and b/Resources/images/checkMark.gif differ
diff --git a/Resources/images/closeTriangleUp.gif b/Resources/images/closeTriangleUp.gif
new file mode 100644
index 0000000..a726d54
Binary files /dev/null and b/Resources/images/closeTriangleUp.gif differ
diff --git a/Resources/images/colorLegend.gif b/Resources/images/colorLegend.gif
new file mode 100755
index 0000000..4bced41
Binary files /dev/null and b/Resources/images/colorLegend.gif differ
diff --git a/Resources/images/colors/0 b/Resources/images/colors/0
new file mode 100644
index 0000000..0d4e478
--- /dev/null
+++ b/Resources/images/colors/0
@@ -0,0 +1,6 @@
+1.0 0.894 0.7686  bisquePALE  Color scheme: sand/tan
+0.949 0.878 0.7255  peachypaleGoldenRodLIGHT
+0.87 0.7216 0.5294  burlywoodMEDIUM
+0.6275 0.3216 0.1765 siennaDARK
+0.87 0.7216 0.5294  burlywoodPROJECT
+
diff --git a/Resources/images/colors/0blank-off.gif b/Resources/images/colors/0blank-off.gif
new file mode 100644
index 0000000..a0b6b68
Binary files /dev/null and b/Resources/images/colors/0blank-off.gif differ
diff --git a/Resources/images/colors/0blank-on copy.gif b/Resources/images/colors/0blank-on copy.gif
new file mode 100644
index 0000000..4cb42ef
Binary files /dev/null and b/Resources/images/colors/0blank-on copy.gif differ
diff --git a/Resources/images/colors/0blank-on.gif b/Resources/images/colors/0blank-on.gif
new file mode 100644
index 0000000..d8d0e1c
Binary files /dev/null and b/Resources/images/colors/0blank-on.gif differ
diff --git a/Resources/images/colors/0citationsTab.gif b/Resources/images/colors/0citationsTab.gif
new file mode 100644
index 0000000..0bfb9d1
Binary files /dev/null and b/Resources/images/colors/0citationsTab.gif differ
diff --git a/Resources/images/colors/0graphicsTab.gif b/Resources/images/colors/0graphicsTab.gif
new file mode 100644
index 0000000..4d3f24a
Binary files /dev/null and b/Resources/images/colors/0graphicsTab.gif differ
diff --git a/Resources/images/colors/0infoBarBase.gif b/Resources/images/colors/0infoBarBase.gif
new file mode 100644
index 0000000..1c08b01
Binary files /dev/null and b/Resources/images/colors/0infoBarBase.gif differ
diff --git a/Resources/images/colors/0modulesTab.gif b/Resources/images/colors/0modulesTab.gif
new file mode 100644
index 0000000..1876d3d
Binary files /dev/null and b/Resources/images/colors/0modulesTab.gif differ
diff --git a/Resources/images/colors/0parametersTab.gif b/Resources/images/colors/0parametersTab.gif
new file mode 100644
index 0000000..9d7a198
Binary files /dev/null and b/Resources/images/colors/0parametersTab.gif differ
diff --git a/Resources/images/colors/0textTab.gif b/Resources/images/colors/0textTab.gif
new file mode 100644
index 0000000..83c952a
Binary files /dev/null and b/Resources/images/colors/0textTab.gif differ
diff --git a/Resources/images/colors/1 b/Resources/images/colors/1
new file mode 100644
index 0000000..65bb5eb
--- /dev/null
+++ b/Resources/images/colors/1
@@ -0,0 +1,7 @@
+0.8086 0.824 1.0  pale  Color scheme: blue
+0.7267 0.8098  0.9333 LIGHT
+0.5294 0.5216  0.87 MEDIUM
+0.2000 0.2500 0.5875 DARK
+0.5294 0.5216  0.87 PROJECT
+
+
diff --git a/Resources/images/colors/1blank-off.gif b/Resources/images/colors/1blank-off.gif
new file mode 100644
index 0000000..2a0c8eb
Binary files /dev/null and b/Resources/images/colors/1blank-off.gif differ
diff --git a/Resources/images/colors/1blank-on.gif b/Resources/images/colors/1blank-on.gif
new file mode 100644
index 0000000..0705815
Binary files /dev/null and b/Resources/images/colors/1blank-on.gif differ
diff --git a/Resources/images/colors/1citationsTab.gif b/Resources/images/colors/1citationsTab.gif
new file mode 100644
index 0000000..7d604d3
Binary files /dev/null and b/Resources/images/colors/1citationsTab.gif differ
diff --git a/Resources/images/colors/1graphicsTab.gif b/Resources/images/colors/1graphicsTab.gif
new file mode 100644
index 0000000..5ea4480
Binary files /dev/null and b/Resources/images/colors/1graphicsTab.gif differ
diff --git a/Resources/images/colors/1infoBarBase.gif b/Resources/images/colors/1infoBarBase.gif
new file mode 100644
index 0000000..bd2b5cb
Binary files /dev/null and b/Resources/images/colors/1infoBarBase.gif differ
diff --git a/Resources/images/colors/1modulesTab.gif b/Resources/images/colors/1modulesTab.gif
new file mode 100644
index 0000000..c8a1de0
Binary files /dev/null and b/Resources/images/colors/1modulesTab.gif differ
diff --git a/Resources/images/colors/1parametersTab.gif b/Resources/images/colors/1parametersTab.gif
new file mode 100644
index 0000000..1516a6b
Binary files /dev/null and b/Resources/images/colors/1parametersTab.gif differ
diff --git a/Resources/images/colors/1textTab.gif b/Resources/images/colors/1textTab.gif
new file mode 100644
index 0000000..8de7ae0
Binary files /dev/null and b/Resources/images/colors/1textTab.gif differ
diff --git a/Resources/images/colors/2 b/Resources/images/colors/2
new file mode 100644
index 0000000..eccc8a2
--- /dev/null
+++ b/Resources/images/colors/2
@@ -0,0 +1,22 @@
+0.8086 1.0 0.824  pale  Color scheme: green
+0.7267  0.886 0.64 LIGHT
+0.5294  0.87 0.5216 MEDIUM
+0.1500 0.5075 0.1516 DARK
+0.5294  0.87 0.5216 PROJECT
+
+
+old version:
+0.8086 1.0 0.824  pale  Color scheme: green
+0.7267  0.9333 0.8098 LIGHT
+0.5294  0.87 0.5216 MEDIUM
+0.2765 0.6275 0.3216 DARK
+0.5294  0.87 0.5216 PROJECT
+
+
+older version:
+0.7686 1.0 0.894  pale  Color scheme: green
+0.6667  0.9333 0.9398 LIGHT
+0.5294  0.87 0.7216 MEDIUM
+0.1765 0.6275 0.3216 DARK
+0.5294  0.87 0.7216 PROJECT
+
diff --git a/Resources/images/colors/2blank-off.gif b/Resources/images/colors/2blank-off.gif
new file mode 100644
index 0000000..46969e8
Binary files /dev/null and b/Resources/images/colors/2blank-off.gif differ
diff --git a/Resources/images/colors/2blank-on.gif b/Resources/images/colors/2blank-on.gif
new file mode 100644
index 0000000..7d095c7
Binary files /dev/null and b/Resources/images/colors/2blank-on.gif differ
diff --git a/Resources/images/colors/2citationsTab.gif b/Resources/images/colors/2citationsTab.gif
new file mode 100644
index 0000000..ef33f0e
Binary files /dev/null and b/Resources/images/colors/2citationsTab.gif differ
diff --git a/Resources/images/colors/2graphicsTab.gif b/Resources/images/colors/2graphicsTab.gif
new file mode 100644
index 0000000..44615f5
Binary files /dev/null and b/Resources/images/colors/2graphicsTab.gif differ
diff --git a/Resources/images/colors/2infoBarBase.gif b/Resources/images/colors/2infoBarBase.gif
new file mode 100644
index 0000000..75dac55
Binary files /dev/null and b/Resources/images/colors/2infoBarBase.gif differ
diff --git a/Resources/images/colors/2modulesTab.gif b/Resources/images/colors/2modulesTab.gif
new file mode 100644
index 0000000..fa28b3b
Binary files /dev/null and b/Resources/images/colors/2modulesTab.gif differ
diff --git a/Resources/images/colors/2parametersTab.gif b/Resources/images/colors/2parametersTab.gif
new file mode 100644
index 0000000..b6c5c22
Binary files /dev/null and b/Resources/images/colors/2parametersTab.gif differ
diff --git a/Resources/images/colors/2textTab.gif b/Resources/images/colors/2textTab.gif
new file mode 100644
index 0000000..2ec5f27
Binary files /dev/null and b/Resources/images/colors/2textTab.gif differ
diff --git a/Resources/images/colors/3 b/Resources/images/colors/3
new file mode 100644
index 0000000..6459e42
--- /dev/null
+++ b/Resources/images/colors/3
@@ -0,0 +1,6 @@
+1.0 0.794 1  PALE  color scheme: violet
+0.9333 0.6667 0.9398  LIGHT
+0.87 0.5294 0.7816  MEDIUM
+0.4275 0.1765 0.4216 DARK
+0.87 0.5294 0.7816  PROJECT
+
diff --git a/Resources/images/colors/3blank-off.gif b/Resources/images/colors/3blank-off.gif
new file mode 100644
index 0000000..880533f
Binary files /dev/null and b/Resources/images/colors/3blank-off.gif differ
diff --git a/Resources/images/colors/3blank-on.gif b/Resources/images/colors/3blank-on.gif
new file mode 100644
index 0000000..b6db394
Binary files /dev/null and b/Resources/images/colors/3blank-on.gif differ
diff --git a/Resources/images/colors/3citationsTab.gif b/Resources/images/colors/3citationsTab.gif
new file mode 100644
index 0000000..af9f72a
Binary files /dev/null and b/Resources/images/colors/3citationsTab.gif differ
diff --git a/Resources/images/colors/3graphicsTab.gif b/Resources/images/colors/3graphicsTab.gif
new file mode 100644
index 0000000..206e2be
Binary files /dev/null and b/Resources/images/colors/3graphicsTab.gif differ
diff --git a/Resources/images/colors/3infoBarBase.gif b/Resources/images/colors/3infoBarBase.gif
new file mode 100644
index 0000000..8ccd825
Binary files /dev/null and b/Resources/images/colors/3infoBarBase.gif differ
diff --git a/Resources/images/colors/3modulesTab.gif b/Resources/images/colors/3modulesTab.gif
new file mode 100644
index 0000000..affb9e2
Binary files /dev/null and b/Resources/images/colors/3modulesTab.gif differ
diff --git a/Resources/images/colors/3parametersTab.gif b/Resources/images/colors/3parametersTab.gif
new file mode 100644
index 0000000..5c0651e
Binary files /dev/null and b/Resources/images/colors/3parametersTab.gif differ
diff --git a/Resources/images/colors/3textTab.gif b/Resources/images/colors/3textTab.gif
new file mode 100644
index 0000000..ae870d1
Binary files /dev/null and b/Resources/images/colors/3textTab.gif differ
diff --git a/Resources/images/colors/blank-off.gif b/Resources/images/colors/blank-off.gif
new file mode 100644
index 0000000..dcc41be
Binary files /dev/null and b/Resources/images/colors/blank-off.gif differ
diff --git a/Resources/images/colors/blank-offBordered.gif b/Resources/images/colors/blank-offBordered.gif
new file mode 100644
index 0000000..8c771e0
Binary files /dev/null and b/Resources/images/colors/blank-offBordered.gif differ
diff --git a/Resources/images/colors/blank-offClear.gif b/Resources/images/colors/blank-offClear.gif
new file mode 100644
index 0000000..b0cf23a
Binary files /dev/null and b/Resources/images/colors/blank-offClear.gif differ
diff --git a/Resources/images/colors/infoBarBase copy 2.gif b/Resources/images/colors/infoBarBase copy 2.gif
new file mode 100644
index 0000000..269d98e
Binary files /dev/null and b/Resources/images/colors/infoBarBase copy 2.gif differ
diff --git a/Resources/images/colors/infoBarBase copy.gif b/Resources/images/colors/infoBarBase copy.gif
new file mode 100644
index 0000000..3760e27
Binary files /dev/null and b/Resources/images/colors/infoBarBase copy.gif differ
diff --git a/Resources/images/colors/infoBarBase.gif b/Resources/images/colors/infoBarBase.gif
new file mode 100644
index 0000000..d78b5d7
Binary files /dev/null and b/Resources/images/colors/infoBarBase.gif differ
diff --git a/Resources/images/compactTransparent.gif b/Resources/images/compactTransparent.gif
new file mode 100644
index 0000000..47aa6ec
Binary files /dev/null and b/Resources/images/compactTransparent.gif differ
diff --git a/Resources/images/construction.gif b/Resources/images/construction.gif
new file mode 100644
index 0000000..a9317fe
Binary files /dev/null and b/Resources/images/construction.gif differ
diff --git a/Resources/images/dataSearch.gif b/Resources/images/dataSearch.gif
new file mode 100644
index 0000000..6959a43
Binary files /dev/null and b/Resources/images/dataSearch.gif differ
diff --git a/Resources/images/decompactTransparent.gif b/Resources/images/decompactTransparent.gif
new file mode 100644
index 0000000..15db966
Binary files /dev/null and b/Resources/images/decompactTransparent.gif differ
diff --git a/Resources/images/decrease.gif b/Resources/images/decrease.gif
new file mode 100644
index 0000000..aee0a1e
Binary files /dev/null and b/Resources/images/decrease.gif differ
diff --git a/Resources/images/disabled.gif b/Resources/images/disabled.gif
new file mode 100644
index 0000000..38770c4
Binary files /dev/null and b/Resources/images/disabled.gif differ
diff --git a/Resources/images/downarrow-blue.gif b/Resources/images/downarrow-blue.gif
new file mode 100644
index 0000000..769b5ef
Binary files /dev/null and b/Resources/images/downarrow-blue.gif differ
diff --git a/Resources/images/downarrow-green.gif b/Resources/images/downarrow-green.gif
new file mode 100644
index 0000000..0b6bca0
Binary files /dev/null and b/Resources/images/downarrow-green.gif differ
diff --git a/Resources/images/downarrow-red.gif b/Resources/images/downarrow-red.gif
new file mode 100644
index 0000000..80f7c9e
Binary files /dev/null and b/Resources/images/downarrow-red.gif differ
diff --git a/Resources/images/downarrow.gif b/Resources/images/downarrow.gif
new file mode 100644
index 0000000..3899ab0
Binary files /dev/null and b/Resources/images/downarrow.gif differ
diff --git a/Resources/images/downarrowDisabled.gif b/Resources/images/downarrowDisabled.gif
new file mode 100644
index 0000000..bd16181
Binary files /dev/null and b/Resources/images/downarrowDisabled.gif differ
diff --git a/Resources/images/downarrowPressed.gif b/Resources/images/downarrowPressed.gif
new file mode 100644
index 0000000..0329e04
Binary files /dev/null and b/Resources/images/downarrowPressed.gif differ
diff --git a/Resources/images/download.gif b/Resources/images/download.gif
new file mode 100644
index 0000000..788a20d
Binary files /dev/null and b/Resources/images/download.gif differ
diff --git a/Resources/images/dropper.gif b/Resources/images/dropper.gif
new file mode 100644
index 0000000..85d29d8
Binary files /dev/null and b/Resources/images/dropper.gif differ
diff --git a/Resources/images/empty.gif b/Resources/images/empty.gif
new file mode 100644
index 0000000..5fb34e8
Binary files /dev/null and b/Resources/images/empty.gif differ
diff --git a/Resources/images/enterHoriz.gif b/Resources/images/enterHoriz.gif
new file mode 100644
index 0000000..3212620
Binary files /dev/null and b/Resources/images/enterHoriz.gif differ
diff --git a/Resources/images/enterHorizDisabled.gif b/Resources/images/enterHorizDisabled.gif
new file mode 100644
index 0000000..bf145d2
Binary files /dev/null and b/Resources/images/enterHorizDisabled.gif differ
diff --git a/Resources/images/enterHorizPressed.gif b/Resources/images/enterHorizPressed.gif
new file mode 100644
index 0000000..41e50c0
Binary files /dev/null and b/Resources/images/enterHorizPressed.gif differ
diff --git a/Resources/images/enterVert.gif b/Resources/images/enterVert.gif
new file mode 100644
index 0000000..16f5a38
Binary files /dev/null and b/Resources/images/enterVert.gif differ
diff --git a/Resources/images/enterVertDisabled.gif b/Resources/images/enterVertDisabled.gif
new file mode 100644
index 0000000..20fa46e
Binary files /dev/null and b/Resources/images/enterVertDisabled.gif differ
diff --git a/Resources/images/enterVertPressed.gif b/Resources/images/enterVertPressed.gif
new file mode 100644
index 0000000..87b5cf1
Binary files /dev/null and b/Resources/images/enterVertPressed.gif differ
diff --git a/Resources/images/equilstatestab.gif b/Resources/images/equilstatestab.gif
new file mode 100644
index 0000000..6a1e256
Binary files /dev/null and b/Resources/images/equilstatestab.gif differ
diff --git a/Resources/images/equilstatestabOff.gif b/Resources/images/equilstatestabOff.gif
new file mode 100644
index 0000000..ba3522f
Binary files /dev/null and b/Resources/images/equilstatestabOff.gif differ
diff --git a/Resources/images/equivocal.gif b/Resources/images/equivocal.gif
new file mode 100644
index 0000000..398f502
Binary files /dev/null and b/Resources/images/equivocal.gif differ
diff --git a/Resources/images/explanationMinus.gif b/Resources/images/explanationMinus.gif
new file mode 100644
index 0000000..537d77a
Binary files /dev/null and b/Resources/images/explanationMinus.gif differ
diff --git a/Resources/images/explanationMinusOff.gif b/Resources/images/explanationMinusOff.gif
new file mode 100644
index 0000000..64bfa74
Binary files /dev/null and b/Resources/images/explanationMinusOff.gif differ
diff --git a/Resources/images/explanationPlus.gif b/Resources/images/explanationPlus.gif
new file mode 100644
index 0000000..0f2cb65
Binary files /dev/null and b/Resources/images/explanationPlus.gif differ
diff --git a/Resources/images/functionIcons/charSource.gif b/Resources/images/functionIcons/charSource.gif
new file mode 100644
index 0000000..8fd512f
Binary files /dev/null and b/Resources/images/functionIcons/charSource.gif differ
diff --git a/Resources/images/functionIcons/characterNumber.gif b/Resources/images/functionIcons/characterNumber.gif
new file mode 100644
index 0000000..db5ec7e
Binary files /dev/null and b/Resources/images/functionIcons/characterNumber.gif differ
diff --git a/Resources/images/functionIcons/chart.gif b/Resources/images/functionIcons/chart.gif
new file mode 100644
index 0000000..683197b
Binary files /dev/null and b/Resources/images/functionIcons/chart.gif differ
diff --git a/Resources/images/functionIcons/fileInterpret.gif b/Resources/images/functionIcons/fileInterpret.gif
new file mode 100644
index 0000000..608fe89
Binary files /dev/null and b/Resources/images/functionIcons/fileInterpret.gif differ
diff --git a/Resources/images/functionIcons/matrixEditor.gif b/Resources/images/functionIcons/matrixEditor.gif
new file mode 100644
index 0000000..349ad39
Binary files /dev/null and b/Resources/images/functionIcons/matrixEditor.gif differ
diff --git a/Resources/images/functionIcons/matrixEditorUtil.gif b/Resources/images/functionIcons/matrixEditorUtil.gif
new file mode 100644
index 0000000..ac99f7c
Binary files /dev/null and b/Resources/images/functionIcons/matrixEditorUtil.gif differ
diff --git a/Resources/images/functionIcons/matrixNumber.gif b/Resources/images/functionIcons/matrixNumber.gif
new file mode 100644
index 0000000..82bf145
Binary files /dev/null and b/Resources/images/functionIcons/matrixNumber.gif differ
diff --git a/Resources/images/functionIcons/matrixSource.gif b/Resources/images/functionIcons/matrixSource.gif
new file mode 100644
index 0000000..2f28643
Binary files /dev/null and b/Resources/images/functionIcons/matrixSource.gif differ
diff --git a/Resources/images/functionIcons/simulate.gif b/Resources/images/functionIcons/simulate.gif
new file mode 100644
index 0000000..d4d45d5
Binary files /dev/null and b/Resources/images/functionIcons/simulate.gif differ
diff --git a/Resources/images/functionIcons/treeCharNumber.gif b/Resources/images/functionIcons/treeCharNumber.gif
new file mode 100644
index 0000000..0c5c636
Binary files /dev/null and b/Resources/images/functionIcons/treeCharNumber.gif differ
diff --git a/Resources/images/functionIcons/treeNumber.gif b/Resources/images/functionIcons/treeNumber.gif
new file mode 100644
index 0000000..6584ca2
Binary files /dev/null and b/Resources/images/functionIcons/treeNumber.gif differ
diff --git a/Resources/images/functionIcons/treeSource.gif b/Resources/images/functionIcons/treeSource.gif
new file mode 100644
index 0000000..3cb5063
Binary files /dev/null and b/Resources/images/functionIcons/treeSource.gif differ
diff --git a/Resources/images/functionIcons/treeWindow.gif b/Resources/images/functionIcons/treeWindow.gif
new file mode 100644
index 0000000..8e8c42b
Binary files /dev/null and b/Resources/images/functionIcons/treeWindow.gif differ
diff --git a/Resources/images/functionIcons/treeWindowUtil.gif b/Resources/images/functionIcons/treeWindowUtil.gif
new file mode 100644
index 0000000..b736dd0
Binary files /dev/null and b/Resources/images/functionIcons/treeWindowUtil.gif differ
diff --git a/Resources/images/goaway.gif b/Resources/images/goaway.gif
new file mode 100755
index 0000000..695914f
Binary files /dev/null and b/Resources/images/goaway.gif differ
diff --git a/Resources/images/goawayTransparent.gif b/Resources/images/goawayTransparent.gif
new file mode 100644
index 0000000..442b503
Binary files /dev/null and b/Resources/images/goawayTransparent.gif differ
diff --git a/Resources/images/green-ball-small.gif b/Resources/images/green-ball-small.gif
new file mode 100644
index 0000000..17fea5b
Binary files /dev/null and b/Resources/images/green-ball-small.gif differ
diff --git a/Resources/images/help.gif b/Resources/images/help.gif
new file mode 100644
index 0000000..59af096
Binary files /dev/null and b/Resources/images/help.gif differ
diff --git a/Resources/images/helpPressed.gif b/Resources/images/helpPressed.gif
new file mode 100644
index 0000000..c5b398e
Binary files /dev/null and b/Resources/images/helpPressed.gif differ
diff --git a/Resources/images/how.gif b/Resources/images/how.gif
new file mode 100644
index 0000000..918f5a4
Binary files /dev/null and b/Resources/images/how.gif differ
diff --git a/Resources/images/ibeam.gif b/Resources/images/ibeam.gif
new file mode 100644
index 0000000..3f2f136
Binary files /dev/null and b/Resources/images/ibeam.gif differ
diff --git a/Resources/images/increase.gif b/Resources/images/increase.gif
new file mode 100644
index 0000000..55e330b
Binary files /dev/null and b/Resources/images/increase.gif differ
diff --git a/Resources/images/info.gif b/Resources/images/info.gif
new file mode 100644
index 0000000..65b747d
Binary files /dev/null and b/Resources/images/info.gif differ
diff --git a/Resources/images/infoBarBase.gif b/Resources/images/infoBarBase.gif
new file mode 100644
index 0000000..951ba5c
Binary files /dev/null and b/Resources/images/infoBarBase.gif differ
diff --git a/Resources/images/infoBarIcons.gif b/Resources/images/infoBarIcons.gif
new file mode 100644
index 0000000..dd9fb0a
Binary files /dev/null and b/Resources/images/infoBarIcons.gif differ
diff --git a/Resources/images/infoBarTriangle.gif b/Resources/images/infoBarTriangle.gif
new file mode 100644
index 0000000..f95a45e
Binary files /dev/null and b/Resources/images/infoBarTriangle.gif differ
diff --git a/Resources/images/leftarrow-blue.gif b/Resources/images/leftarrow-blue.gif
new file mode 100644
index 0000000..b4f8d5d
Binary files /dev/null and b/Resources/images/leftarrow-blue.gif differ
diff --git a/Resources/images/leftarrow-gray.gif b/Resources/images/leftarrow-gray.gif
new file mode 100644
index 0000000..0714886
Binary files /dev/null and b/Resources/images/leftarrow-gray.gif differ
diff --git a/Resources/images/leftarrow-green.gif b/Resources/images/leftarrow-green.gif
new file mode 100644
index 0000000..670e2af
Binary files /dev/null and b/Resources/images/leftarrow-green.gif differ
diff --git a/Resources/images/leftarrow-red.gif b/Resources/images/leftarrow-red.gif
new file mode 100644
index 0000000..d6d522e
Binary files /dev/null and b/Resources/images/leftarrow-red.gif differ
diff --git a/Resources/images/leftarrow.gif b/Resources/images/leftarrow.gif
new file mode 100644
index 0000000..8ab156c
Binary files /dev/null and b/Resources/images/leftarrow.gif differ
diff --git a/Resources/images/leftarrowDisabled.gif b/Resources/images/leftarrowDisabled.gif
new file mode 100644
index 0000000..c51da45
Binary files /dev/null and b/Resources/images/leftarrowDisabled.gif differ
diff --git a/Resources/images/leftarrowPressed.gif b/Resources/images/leftarrowPressed.gif
new file mode 100644
index 0000000..bf38b14
Binary files /dev/null and b/Resources/images/leftarrowPressed.gif differ
diff --git a/Resources/images/link.gif b/Resources/images/link.gif
new file mode 100644
index 0000000..a7ffc3f
Binary files /dev/null and b/Resources/images/link.gif differ
diff --git a/Resources/images/list.gif b/Resources/images/list.gif
new file mode 100755
index 0000000..75dc97b
Binary files /dev/null and b/Resources/images/list.gif differ
diff --git a/Resources/images/listC.gif b/Resources/images/listC.gif
new file mode 100755
index 0000000..0a0d6d5
Binary files /dev/null and b/Resources/images/listC.gif differ
diff --git a/Resources/images/listP.GIF b/Resources/images/listP.GIF
new file mode 100644
index 0000000..79a381e
Binary files /dev/null and b/Resources/images/listP.GIF differ
diff --git a/Resources/images/listS.gif b/Resources/images/listS.gif
new file mode 100644
index 0000000..40dfad0
Binary files /dev/null and b/Resources/images/listS.gif differ
diff --git a/Resources/images/listT.gif b/Resources/images/listT.gif
new file mode 100755
index 0000000..7f7a1ea
Binary files /dev/null and b/Resources/images/listT.gif differ
diff --git a/Resources/images/manual.gif b/Resources/images/manual.gif
new file mode 100644
index 0000000..a8b6628
Binary files /dev/null and b/Resources/images/manual.gif differ
diff --git a/Resources/images/manualPressed.gif b/Resources/images/manualPressed.gif
new file mode 100644
index 0000000..18883f0
Binary files /dev/null and b/Resources/images/manualPressed.gif differ
diff --git a/Resources/images/matrix.gif b/Resources/images/matrix.gif
new file mode 100755
index 0000000..9c93a09
Binary files /dev/null and b/Resources/images/matrix.gif differ
diff --git a/Resources/images/maximizeTransparent.gif b/Resources/images/maximizeTransparent.gif
new file mode 100644
index 0000000..53cccbb
Binary files /dev/null and b/Resources/images/maximizeTransparent.gif differ
diff --git a/Resources/images/mediumizeTransparent.gif b/Resources/images/mediumizeTransparent.gif
new file mode 100644
index 0000000..c1967d1
Binary files /dev/null and b/Resources/images/mediumizeTransparent.gif differ
diff --git a/Resources/images/menuDropArrow.gif b/Resources/images/menuDropArrow.gif
new file mode 100644
index 0000000..32ff56d
Binary files /dev/null and b/Resources/images/menuDropArrow.gif differ
diff --git a/Resources/images/menus.gif b/Resources/images/menus.gif
new file mode 100644
index 0000000..e79d9be
Binary files /dev/null and b/Resources/images/menus.gif differ
diff --git a/Resources/images/mesquite.gif b/Resources/images/mesquite.gif
new file mode 100644
index 0000000..d5cc16d
Binary files /dev/null and b/Resources/images/mesquite.gif differ
diff --git a/Resources/images/mesquiteBeta.gif b/Resources/images/mesquiteBeta.gif
new file mode 100755
index 0000000..4311fcf
Binary files /dev/null and b/Resources/images/mesquiteBeta.gif differ
diff --git a/Resources/images/mesquiteIcon.gif b/Resources/images/mesquiteIcon.gif
new file mode 100644
index 0000000..578fdcb
Binary files /dev/null and b/Resources/images/mesquiteIcon.gif differ
diff --git a/Resources/images/mesquiteIcon128.gif b/Resources/images/mesquiteIcon128.gif
new file mode 100644
index 0000000..9ee00df
Binary files /dev/null and b/Resources/images/mesquiteIcon128.gif differ
diff --git a/Resources/images/mesquiteIcon16.gif b/Resources/images/mesquiteIcon16.gif
new file mode 100644
index 0000000..80cbc4c
Binary files /dev/null and b/Resources/images/mesquiteIcon16.gif differ
diff --git a/Resources/images/mesquiteIcon48.gif b/Resources/images/mesquiteIcon48.gif
new file mode 100644
index 0000000..1dc9e4e
Binary files /dev/null and b/Resources/images/mesquiteIcon48.gif differ
diff --git a/Resources/images/mesquitePlain.gif b/Resources/images/mesquitePlain.gif
new file mode 100644
index 0000000..7e8fad2
Binary files /dev/null and b/Resources/images/mesquitePlain.gif differ
diff --git a/Resources/images/mesquitesmall.gif b/Resources/images/mesquitesmall.gif
new file mode 100644
index 0000000..b287251
Binary files /dev/null and b/Resources/images/mesquitesmall.gif differ
diff --git a/Resources/images/miniScroll.jpg b/Resources/images/miniScroll.jpg
new file mode 100755
index 0000000..8398069
Binary files /dev/null and b/Resources/images/miniScroll.jpg differ
diff --git a/Resources/images/minimize.gif b/Resources/images/minimize.gif
new file mode 100644
index 0000000..428cb3b
Binary files /dev/null and b/Resources/images/minimize.gif differ
diff --git a/Resources/images/minimizeTransparent.gif b/Resources/images/minimizeTransparent.gif
new file mode 100644
index 0000000..68108ec
Binary files /dev/null and b/Resources/images/minimizeTransparent.gif differ
diff --git a/Resources/images/miniscrollHoriz.gif b/Resources/images/miniscrollHoriz.gif
new file mode 100755
index 0000000..30a4150
Binary files /dev/null and b/Resources/images/miniscrollHoriz.gif differ
diff --git a/Resources/images/miniscrollVert.gif b/Resources/images/miniscrollVert.gif
new file mode 100755
index 0000000..4dfaddd
Binary files /dev/null and b/Resources/images/miniscrollVert.gif differ
diff --git a/Resources/images/new.gif b/Resources/images/new.gif
new file mode 100755
index 0000000..8cb82b0
Binary files /dev/null and b/Resources/images/new.gif differ
diff --git a/Resources/images/notesTool.gif b/Resources/images/notesTool.gif
new file mode 100644
index 0000000..efd3028
Binary files /dev/null and b/Resources/images/notesTool.gif differ
diff --git a/Resources/images/ok.gif b/Resources/images/ok.gif
new file mode 100644
index 0000000..50bce81
Binary files /dev/null and b/Resources/images/ok.gif differ
diff --git a/Resources/images/or.gif b/Resources/images/or.gif
new file mode 100644
index 0000000..7633bb7
Binary files /dev/null and b/Resources/images/or.gif differ
diff --git a/Resources/images/pause.gif b/Resources/images/pause.gif
new file mode 100755
index 0000000..75dd021
Binary files /dev/null and b/Resources/images/pause.gif differ
diff --git a/Resources/images/play.gif b/Resources/images/play.gif
new file mode 100755
index 0000000..1de4c53
Binary files /dev/null and b/Resources/images/play.gif differ
diff --git a/Resources/images/pointer.gif b/Resources/images/pointer.gif
new file mode 100644
index 0000000..2eaa456
Binary files /dev/null and b/Resources/images/pointer.gif differ
diff --git a/Resources/images/prerelease.gif b/Resources/images/prerelease.gif
new file mode 100644
index 0000000..42ee1ac
Binary files /dev/null and b/Resources/images/prerelease.gif differ
diff --git a/Resources/images/queryGray.gif b/Resources/images/queryGray.gif
new file mode 100644
index 0000000..47bc6d7
Binary files /dev/null and b/Resources/images/queryGray.gif differ
diff --git a/Resources/images/ratematrixtab.gif b/Resources/images/ratematrixtab.gif
new file mode 100644
index 0000000..0a53069
Binary files /dev/null and b/Resources/images/ratematrixtab.gif differ
diff --git a/Resources/images/ratematrixtabOff.gif b/Resources/images/ratematrixtabOff.gif
new file mode 100644
index 0000000..1fc6cda
Binary files /dev/null and b/Resources/images/ratematrixtabOff.gif differ
diff --git a/Resources/images/release.gif b/Resources/images/release.gif
new file mode 100644
index 0000000..f38f4e9
Binary files /dev/null and b/Resources/images/release.gif differ
diff --git a/Resources/images/replaceLeft.gif b/Resources/images/replaceLeft.gif
new file mode 100644
index 0000000..1283822
Binary files /dev/null and b/Resources/images/replaceLeft.gif differ
diff --git a/Resources/images/revSort.gif b/Resources/images/revSort.gif
new file mode 100644
index 0000000..123de60
Binary files /dev/null and b/Resources/images/revSort.gif differ
diff --git a/Resources/images/rightarrow-blue.gif b/Resources/images/rightarrow-blue.gif
new file mode 100644
index 0000000..d939222
Binary files /dev/null and b/Resources/images/rightarrow-blue.gif differ
diff --git a/Resources/images/rightarrow-green.gif b/Resources/images/rightarrow-green.gif
new file mode 100644
index 0000000..0a98edb
Binary files /dev/null and b/Resources/images/rightarrow-green.gif differ
diff --git a/Resources/images/rightarrow-red.gif b/Resources/images/rightarrow-red.gif
new file mode 100644
index 0000000..82e2953
Binary files /dev/null and b/Resources/images/rightarrow-red.gif differ
diff --git a/Resources/images/rightarrow.gif b/Resources/images/rightarrow.gif
new file mode 100644
index 0000000..7f46626
Binary files /dev/null and b/Resources/images/rightarrow.gif differ
diff --git a/Resources/images/rightarrowDisabled.gif b/Resources/images/rightarrowDisabled.gif
new file mode 100644
index 0000000..df18a0f
Binary files /dev/null and b/Resources/images/rightarrowDisabled.gif differ
diff --git a/Resources/images/rightarrowPressed.gif b/Resources/images/rightarrowPressed.gif
new file mode 100644
index 0000000..5a8fa69
Binary files /dev/null and b/Resources/images/rightarrowPressed.gif differ
diff --git a/Resources/images/rootstatestab.gif b/Resources/images/rootstatestab.gif
new file mode 100644
index 0000000..8d7b246
Binary files /dev/null and b/Resources/images/rootstatestab.gif differ
diff --git a/Resources/images/rootstatestabOff.gif b/Resources/images/rootstatestabOff.gif
new file mode 100644
index 0000000..b11ea5a
Binary files /dev/null and b/Resources/images/rootstatestabOff.gif differ
diff --git a/Resources/images/search.gif b/Resources/images/search.gif
new file mode 100644
index 0000000..4830e3f
Binary files /dev/null and b/Resources/images/search.gif differ
diff --git a/Resources/images/showInfo.gif b/Resources/images/showInfo.gif
new file mode 100644
index 0000000..e6d7a83
Binary files /dev/null and b/Resources/images/showInfo.gif differ
diff --git a/Resources/images/showInfoOld.gif b/Resources/images/showInfoOld.gif
new file mode 100644
index 0000000..8bd5c3e
Binary files /dev/null and b/Resources/images/showInfoOld.gif differ
diff --git a/Resources/images/showTransparent.gif b/Resources/images/showTransparent.gif
new file mode 100644
index 0000000..c1967d1
Binary files /dev/null and b/Resources/images/showTransparent.gif differ
diff --git a/Resources/images/simplification/blueRing.gif b/Resources/images/simplification/blueRing.gif
new file mode 100644
index 0000000..c18356e
Binary files /dev/null and b/Resources/images/simplification/blueRing.gif differ
diff --git a/Resources/images/simplification/load.gif b/Resources/images/simplification/load.gif
new file mode 100644
index 0000000..0ffc7ad
Binary files /dev/null and b/Resources/images/simplification/load.gif differ
diff --git a/Resources/images/simplification/power.gif b/Resources/images/simplification/power.gif
new file mode 100644
index 0000000..57df81b
Binary files /dev/null and b/Resources/images/simplification/power.gif differ
diff --git a/Resources/images/simplification/redRing.gif b/Resources/images/simplification/redRing.gif
new file mode 100644
index 0000000..8e55466
Binary files /dev/null and b/Resources/images/simplification/redRing.gif differ
diff --git a/Resources/images/simplification/simple.gif b/Resources/images/simplification/simple.gif
new file mode 100644
index 0000000..c8d6842
Binary files /dev/null and b/Resources/images/simplification/simple.gif differ
diff --git a/Resources/images/sitetositetab.gif b/Resources/images/sitetositetab.gif
new file mode 100644
index 0000000..2abd057
Binary files /dev/null and b/Resources/images/sitetositetab.gif differ
diff --git a/Resources/images/sitetositetabOff.gif b/Resources/images/sitetositetabOff.gif
new file mode 100644
index 0000000..0da3eb2
Binary files /dev/null and b/Resources/images/sitetositetabOff.gif differ
diff --git a/Resources/images/sliderHoriz.gif b/Resources/images/sliderHoriz.gif
new file mode 100644
index 0000000..22ebe64
Binary files /dev/null and b/Resources/images/sliderHoriz.gif differ
diff --git a/Resources/images/sliderVert.gif b/Resources/images/sliderVert.gif
new file mode 100644
index 0000000..b8ddf32
Binary files /dev/null and b/Resources/images/sliderVert.gif differ
diff --git a/Resources/images/small.top.arrow.gif b/Resources/images/small.top.arrow.gif
new file mode 100755
index 0000000..4dec1bf
Binary files /dev/null and b/Resources/images/small.top.arrow.gif differ
diff --git a/Resources/images/sort.gif b/Resources/images/sort.gif
new file mode 100644
index 0000000..d543f5d
Binary files /dev/null and b/Resources/images/sort.gif differ
diff --git a/Resources/images/spot.gif b/Resources/images/spot.gif
new file mode 100755
index 0000000..15814ae
Binary files /dev/null and b/Resources/images/spot.gif differ
diff --git a/Resources/images/spotgreen.gif b/Resources/images/spotgreen.gif
new file mode 100755
index 0000000..0343b58
Binary files /dev/null and b/Resources/images/spotgreen.gif differ
diff --git a/Resources/images/substantiveBug.gif b/Resources/images/substantiveBug.gif
new file mode 100644
index 0000000..4891756
Binary files /dev/null and b/Resources/images/substantiveBug.gif differ
diff --git a/Resources/images/subtract.gif b/Resources/images/subtract.gif
new file mode 100644
index 0000000..bc85da8
Binary files /dev/null and b/Resources/images/subtract.gif differ
diff --git a/Resources/images/subtractGray.gif b/Resources/images/subtractGray.gif
new file mode 100644
index 0000000..d0e037c
Binary files /dev/null and b/Resources/images/subtractGray.gif differ
diff --git a/Resources/images/tabLeft.gif b/Resources/images/tabLeft.gif
new file mode 100644
index 0000000..d4c5cde
Binary files /dev/null and b/Resources/images/tabLeft.gif differ
diff --git a/Resources/images/tabOff.gif b/Resources/images/tabOff.gif
new file mode 100644
index 0000000..cd730c7
Binary files /dev/null and b/Resources/images/tabOff.gif differ
diff --git a/Resources/images/tabOn.gif b/Resources/images/tabOn.gif
new file mode 100644
index 0000000..3313acf
Binary files /dev/null and b/Resources/images/tabOn.gif differ
diff --git a/Resources/images/tabRight.gif b/Resources/images/tabRight.gif
new file mode 100644
index 0000000..d4c5cde
Binary files /dev/null and b/Resources/images/tabRight.gif differ
diff --git a/Resources/images/taxon.gif b/Resources/images/taxon.gif
new file mode 100755
index 0000000..e6e8377
Binary files /dev/null and b/Resources/images/taxon.gif differ
diff --git a/Resources/images/trashcan.gif b/Resources/images/trashcan.gif
new file mode 100644
index 0000000..b2c3fbe
Binary files /dev/null and b/Resources/images/trashcan.gif differ
diff --git a/Resources/images/triangleDown.gif b/Resources/images/triangleDown.gif
new file mode 100644
index 0000000..8f4ffe2
Binary files /dev/null and b/Resources/images/triangleDown.gif differ
diff --git a/Resources/images/triangleDownOff.gif b/Resources/images/triangleDownOff.gif
new file mode 100755
index 0000000..c41cd87
Binary files /dev/null and b/Resources/images/triangleDownOff.gif differ
diff --git a/Resources/images/triangleDownOn.gif b/Resources/images/triangleDownOn.gif
new file mode 100755
index 0000000..bc64f59
Binary files /dev/null and b/Resources/images/triangleDownOn.gif differ
diff --git a/Resources/images/triangleRightOff.gif b/Resources/images/triangleRightOff.gif
new file mode 100755
index 0000000..779bc99
Binary files /dev/null and b/Resources/images/triangleRightOff.gif differ
diff --git a/Resources/images/triangleRightOn.gif b/Resources/images/triangleRightOn.gif
new file mode 100755
index 0000000..0e12bb5
Binary files /dev/null and b/Resources/images/triangleRightOn.gif differ
diff --git a/Resources/images/triangleUpOn.gif b/Resources/images/triangleUpOn.gif
new file mode 100644
index 0000000..f628a90
Binary files /dev/null and b/Resources/images/triangleUpOn.gif differ
diff --git a/Resources/images/uparrow-blue.gif b/Resources/images/uparrow-blue.gif
new file mode 100644
index 0000000..1a21207
Binary files /dev/null and b/Resources/images/uparrow-blue.gif differ
diff --git a/Resources/images/uparrow-green.gif b/Resources/images/uparrow-green.gif
new file mode 100644
index 0000000..e90adbc
Binary files /dev/null and b/Resources/images/uparrow-green.gif differ
diff --git a/Resources/images/uparrow-red.gif b/Resources/images/uparrow-red.gif
new file mode 100644
index 0000000..9cad65f
Binary files /dev/null and b/Resources/images/uparrow-red.gif differ
diff --git a/Resources/images/uparrow.gif b/Resources/images/uparrow.gif
new file mode 100644
index 0000000..4750986
Binary files /dev/null and b/Resources/images/uparrow.gif differ
diff --git a/Resources/images/uparrowDisabled.gif b/Resources/images/uparrowDisabled.gif
new file mode 100644
index 0000000..1dc01e7
Binary files /dev/null and b/Resources/images/uparrowDisabled.gif differ
diff --git a/Resources/images/uparrowPressed.gif b/Resources/images/uparrowPressed.gif
new file mode 100644
index 0000000..f538537
Binary files /dev/null and b/Resources/images/uparrowPressed.gif differ
diff --git a/Resources/images/wand.gif b/Resources/images/wand.gif
new file mode 100644
index 0000000..17ad5a9
Binary files /dev/null and b/Resources/images/wand.gif differ
diff --git a/Resources/images/wandMinus.gif b/Resources/images/wandMinus.gif
new file mode 100644
index 0000000..1715031
Binary files /dev/null and b/Resources/images/wandMinus.gif differ
diff --git a/Resources/images/wandPlus.gif b/Resources/images/wandPlus.gif
new file mode 100644
index 0000000..f87fc96
Binary files /dev/null and b/Resources/images/wandPlus.gif differ
diff --git a/Resources/images/windowIcons/goAway old.gif b/Resources/images/windowIcons/goAway old.gif
new file mode 100644
index 0000000..38cd49d
Binary files /dev/null and b/Resources/images/windowIcons/goAway old.gif differ
diff --git a/Resources/images/windowIcons/goAway.gif b/Resources/images/windowIcons/goAway.gif
new file mode 100644
index 0000000..dbf8e06
Binary files /dev/null and b/Resources/images/windowIcons/goAway.gif differ
diff --git a/Resources/images/windowIcons/listC.gif b/Resources/images/windowIcons/listC.gif
new file mode 100644
index 0000000..85b5627
Binary files /dev/null and b/Resources/images/windowIcons/listC.gif differ
diff --git a/Resources/images/windowIcons/listT.gif b/Resources/images/windowIcons/listT.gif
new file mode 100644
index 0000000..a2b8103
Binary files /dev/null and b/Resources/images/windowIcons/listT.gif differ
diff --git a/Resources/images/windowIcons/matrix.gif b/Resources/images/windowIcons/matrix.gif
new file mode 100644
index 0000000..7803255
Binary files /dev/null and b/Resources/images/windowIcons/matrix.gif differ
diff --git a/Resources/images/windowIcons/matrixSequence.gif b/Resources/images/windowIcons/matrixSequence.gif
new file mode 100644
index 0000000..f999187
Binary files /dev/null and b/Resources/images/windowIcons/matrixSequence.gif differ
diff --git a/Resources/images/windowIcons/tree.gif b/Resources/images/windowIcons/tree.gif
new file mode 100644
index 0000000..1c4999d
Binary files /dev/null and b/Resources/images/windowIcons/tree.gif differ
diff --git a/Resources/images/zoomIn.gif b/Resources/images/zoomIn.gif
new file mode 100644
index 0000000..8cb501f
Binary files /dev/null and b/Resources/images/zoomIn.gif differ
diff --git a/Resources/images/zoomOut.gif b/Resources/images/zoomOut.gif
new file mode 100644
index 0000000..ab986bb
Binary files /dev/null and b/Resources/images/zoomOut.gif differ
diff --git a/Resources/lesser.txt b/Resources/lesser.txt
new file mode 100755
index 0000000..b1e3f5a
--- /dev/null
+++ b/Resources/lesser.txt
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+

+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+

+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+

+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+

+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+

+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+

+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+

+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+

+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/Resources/mesquite.sh b/Resources/mesquite.sh
new file mode 100755
index 0000000..06ee3e2
--- /dev/null
+++ b/Resources/mesquite.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+#Script to identify java VM. Also modifies classpath on cygwin.
+#Written by Travis Wheeler (www.traviswheeler.com)
+
+#If you find bugs or modify the script to improve functionality, 
+# please let us know so we can improve the script for everyone
+
+
+# Thanks to William Cook (http://www.cs.utexas.edu/users/wcook/) for the bit that
+# identifies the path containing this script, and uses it to set the classpath. 
+# (the exact site of the work that served as inspiration for this code is lost to antiquity)
+
+#Note from W. Maddison:  to increase memory allocation adjust the following lines:
+#     java -Djava.library.path=lib -cp "$dir" mesquite.Mesquite $*
+# by adding the extra arguments  -Xmx and  -Xss
+# For instance, 
+#     java -Djava.library.path=lib -Xmx500M -Xss4m -cp "$dir" mesquite.Mesquite $*
+# will allocate 500M for the heap, which helps with large data and calculations,
+# and 4M stack size per thread, which helps with large trees (> 5000 taxa).
+
+#figure out where java lives 
+if [ $MESQUITE_JAVA_HOME ]
+then
+  java="$MESQUITE_JAVA_HOME/bin/java"
+elif [ $JAVA_HOME ]
+then
+  java="$JAVA_HOME/bin/java"
+else
+  tmp=`java -version 2>&1`
+  if echo "$tmp" | grep -q "command not found"  # no "java", so try "jre"
+  then
+    tmp=`jre -version 2>&1`
+    if echo "$tmp" | grep -q "command not found"
+    then
+       echo "Can't find java. Try setting either the JAVA_HOME environment variable"
+       exit
+    else
+       java="jre"
+    fi
+  else
+   java="java" 
+  fi
+fi
+
+
+# figure out where I live, then run java w/ my containing dir as classpath  
+dir=`dirname "$0"`
+os=`uname`
+if test ${os:0:6} = "CYGWIN"
+then
+  if test ${dir:1:8} = "cygdrive"
+  then
+    dir="${dir:10:1}:/${dir:12}"
+  fi
+  chmod -R u+w  "$dir/com/"
+  cp -r  "$dir/../Resources/com/"* "$dir/com/" >& /dev/null
+  $java -Djava.library.path=lib -Djri.ignore.ule="yes" -cp "$dir" mesquite.Mesquite $*
+else
+  chmod -R u+w  "$dir/com/"
+  cp -r  "$dir/../Resources/com/"* "$dir/com/" >& /dev/null
+  $java -Djava.library.path=lib -Djri.ignore.ule="yes" -cp "$dir" mesquite.Mesquite $*
+fi
+
diff --git a/Resources/startingMesquiteAndMemoryAllocation.txt b/Resources/startingMesquiteAndMemoryAllocation.txt
new file mode 100644
index 0000000..51aa4cf
--- /dev/null
+++ b/Resources/startingMesquiteAndMemoryAllocation.txt
@@ -0,0 +1,76 @@
+To Run Mesquite
+
+To run Mesquite, you need Java installed.  Mesquite now runs only on Java 1.4 and higher.  We suggest Java 1.6 on Mac OS X, Java 1.7 on others.
+
+Once Mesquite_Folder is installed, you can start Mesquite as follows:
+
+==================
+Mac OS X
+There are 3 ways to start Mesquite under OS X:
+
+1. Default: Double click Mesquite[500GB].app,  Mesquite[1GB].app, or  Mesquite[2GB].app, depending on how much memory you want to give to Mesquite.
+
+3. Or, to adjust how exactly Mesquite starts, including memory allocation:
+Run Mesquite by double clicking the file Mesquite_Start_Script.command.  If double clicking this file does not start Mesquite, select the file in the Finder, choose Get Info, and change the "Open With" to "Terminal.app", which is in /Applications/Utilities/
+
+To give Mesquite even more memory, open the file with a text editor and edit the line:
+
+   java  -Xmx500M -Xss2m -Djava.library.path=lib -cp . mesquite.Mesquite
+
+The part -Xmx500M indicates how much heap memory to give to Mesquite in general. With more heap memory Mesquite can handle more trees, bigger matrices, bigger charts, and so on.
+The part -Xss2m indicates how much stack memory to give to each thread.  With more stack memory, Mesquite can handle bigger trees, e.g. more than 5000 taxa.  To be able to handle 10000 taxa, you may need to increase this to 4m.
+
+If you change these settings, make sure you don't introduce any spaces.
+
+Here are some example configurations:
+
+   java  -Xmx1000M -Xss4m -Djava.library.path=lib -cp . mesquite.Mesquite
+
+This can handle big matrices and trees, but you'll probably need at least 2 GB memory in your computer to use it conveniently.
+
+   java  -Xmx3000M -Xss4m -d64 -Djava.library.path=lib -cp . mesquite.Mesquite
+
+This gives much memory to Mesquite, but 3000 MB (= 3 GB) memory exceeds the ability of 32 bit Java.  For that reason the command -d64 was added, to indicate you want to use 64 bit java.  This is available only on intel-based Macs with Core 2 Duo or better processors and updated versions of Java.
+
+
+==================
+Windows
+
+There are 3 ways to start Mesquite under Windows:
+
+1. Default: use the installer and double click one of the executable icons (Mesquite[500MB].exe,  Mesquite[1GB].exe,  Mesquite[2GB].exe), depending on how much memory you want to give to Mesquite.
+
+2. Or, to adjust how exactly Mesquite starts, including memory allocation:
+Run Mesquite by double clicking the file Mesquite_Start_Script.bat.  To give Mesquite even more memory, open the file with a text editor and edit the line:
+
+   java  -Xmx500M -Xss2m -Djava.library.path=lib -cp . mesquite.Mesquite
+
+The part -Xmx500M indicates how much heap memory to give to Mesquite in general. With more heap memory Mesquite can handle more trees, bigger matrices, bigger charts, and so on.
+The part -Xss2m indicates how much stack memory to give to each thread.  With more stack memory, Mesquite can handle bigger trees, e.g. more than 5000 taxa.  To be able to handle 10000 taxa, you may need to increase this to 4m
+
+If you change these settings, make sure you don't introduce any spaces.
+
+
+==================
+Linux etc.
+
+Run Mesquite by double clicking mesquite.sh or running mesquite.sh from the command line like this:
+	./mesquite.sh
+
+Alternatively, run it from the command line by cd'ing into Mesquite_Folder and then giving a command like this:
+
+   java  -Xmx500M -Xss2m -Djava.library.path=lib -cp . mesquite.Mesquite
+
+The part -Xmx500M indicates how much heap memory to give to Mesquite in general. With more heap memory Mesquite can handle more trees, bigger matrices, bigger charts, and so on.
+The part -Xss2m indicates how much stack memory to give to each thread.  With more stack memory, Mesquite can handle bigger trees, e.g. more than 5000 taxa.  To be able to handle 10000 taxa, you may need to increase this to 4m
+
+Here are some example configurations:
+
+   java  -Xmx1000M -Xss4m -Djava.library.path=lib -cp . mesquite.Mesquite
+
+This can handle big matrices and trees, but you'll probably need at least 2 GB memory in your computer to use it conveniently.
+
+   java  -Xmx3000M -Xss4m -d64 -Djava.library.path=lib -cp . mesquite.Mesquite
+
+This gives much memory to Mesquite, but 3000 MB (= 3 GB) memory exceeds the ability of 32 bit Java.  For that reason the command -d64 was added, to indicate you want to use 64 bit java.  
+
diff --git a/Source/corejava/Format.java b/Source/corejava/Format.java
new file mode 100644
index 0000000..a2e940b
--- /dev/null
+++ b/Source/corejava/Format.java
@@ -0,0 +1,565 @@
+/*
+ * Cay S. Horstmann & Gary Cornell, Core Java
+ * Published By Sun Microsystems Press/Prentice-Hall
+ * Copyright (C) 1997 Sun Microsystems Inc.
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this 
+ * software and its documentation for NON-COMMERCIAL purposes
+ * and without fee is hereby granted provided that this 
+ * copyright notice appears in all copies. 
+ * 
+ * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR 
+ * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
+ * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED 
+ * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+ 
+/**
+ * A class for formatting numbers that follows printf conventions.
+ * Also implements C-like atoi and atof functions
+ * @version 1.04 13 Sep 1998
+ * @author Cay Horstmann
+ */
+
+package corejava;
+
+import java.io.*;
+
+public class Format
+
+{ /** 
+  * Formats the number following printf conventions.
+  * Main limitation: Can only handle one format parameter at a time
+  * Use multiple Format objects to format more than one number
+  * @param s the format string following printf conventions
+  * The string has a prefix, a format code and a suffix. The prefix and suffix
+  * become part of the formatted output. The format code directs the
+  * formatting of the (single) parameter to be formatted. The code has the
+  * following structure
+  * <ul>
+  * <li> a % (required)
+  * <li> a modifier (optional)
+  * <dl>
+  * <dt> + <dd> forces display of + for positive numbers
+  * <dt> 0 <dd> show leading zeroes
+  * <dt> - <dd> align left in the field
+  * <dt> space <dd> prepend a space in front of positive numbers
+  * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers. Don't suppress trailing zeroes in general floating point format.
+  * </dl>
+  * <li> an integer denoting field width (optional)
+  * <li> a period followed by an integer denoting precision (optional)
+  * <li> a format descriptor (required)
+  * <dl>
+  * <dt>f <dd> floating point number in fixed format
+  * <dt>e, E <dd> floating point number in exponential notation (scientific format). The E format results in an uppercase E for the exponent (1.14130E+003), the e format in a lowercase e.
+  * <dt>g, G <dd> floating point number in general format (fixed format for small numbers, exponential format for large numbers). Trailing zeroes are suppressed. The G format results in an uppercase E for the exponent (if any), the g format in a lowercase e.
+  * <dt>d, i <dd> integer in decimal
+  * <dt>x <dd> integer in hexadecimal
+  * <dt>o <dd> integer in octal
+  * <dt>s <dd> string
+  * <dt>c <dd> character
+  * </dl>
+  * </ul>
+  * @exception IllegalArgumentException if bad format
+  */
+
+   public Format(String s)
+   {  width = 0;
+      precision = -1;
+      pre = "";
+      post = "";
+      leading_zeroes = false;
+      show_plus = false;
+      alternate = false;
+      show_space = false;
+      left_align = false;
+      fmt = ' '; 
+      
+      int state = 0; 
+      int length = s.length();
+      int parse_state = 0; 
+      // 0 = prefix, 1 = flags, 2 = width, 3 = precision,
+      // 4 = format, 5 = end
+      int i = 0;
+      
+      while (parse_state == 0)
+      {  if (i >= length) parse_state = 5;
+         else if (s.charAt(i) == '%')
+         {  if (i < length - 1)
+            {  if (s.charAt(i + 1) == '%')
+               {  pre = pre + '%';
+                  i++;
+               }
+               else
+                  parse_state = 1;
+            }
+            else throw new java.lang.IllegalArgumentException();
+         }
+         else
+            pre = pre + s.charAt(i);
+         i++;
+      }
+      while (parse_state == 1)
+      {  if (i >= length) parse_state = 5;
+         else if (s.charAt(i) == ' ') show_space = true;
+         else if (s.charAt(i) == '-') left_align = true; 
+         else if (s.charAt(i) == '+') show_plus = true;
+         else if (s.charAt(i) == '0') leading_zeroes = true;
+         else if (s.charAt(i) == '#') alternate = true;
+         else { parse_state = 2; i--; }
+         i++;
+      }      
+      while (parse_state == 2)
+      {  if (i >= length) parse_state = 5;
+         else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')
+         {  width = width * 10 + s.charAt(i) - '0';
+            i++;
+         }
+         else if (s.charAt(i) == '.')
+         {  parse_state = 3;
+            precision = 0;
+            i++;
+         }
+         else 
+            parse_state = 4;            
+      }
+      while (parse_state == 3)
+      {  if (i >= length) parse_state = 5;
+         else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')
+         {  precision = precision * 10 + s.charAt(i) - '0';
+            i++;
+         }
+         else 
+            parse_state = 4;                  
+      }
+      if (parse_state == 4) 
+      {  if (i >= length) parse_state = 5;
+         else fmt = s.charAt(i);
+         i++;
+      }
+      if (i < length)
+         post = s.substring(i, length);
+   }      
+
+  /** 
+  * prints a formatted number following printf conventions
+  * @param s a PrintStream
+  * @param fmt the format string
+  * @param x the double to print
+  */
+  
+   public static void print(java.io.PrintStream s, String fmt, double x)
+   {  s.print(new Format(fmt).form(x));
+   }
+
+  /** 
+  * prints a formatted number following printf conventions
+  * @param s a PrintStream
+  * @param fmt the format string
+  * @param x the long to print
+  */
+  public static void print(java.io.PrintStream s, String fmt, long x)
+   {  s.print(new Format(fmt).form(x));
+   }
+
+  /** 
+  * prints a formatted number following printf conventions
+  * @param s a PrintStream
+  * @param fmt the format string
+  * @param x the character to 
+  */
+  
+   public static void print(java.io.PrintStream s, String fmt, char x)
+   {  s.print(new Format(fmt).form(x));
+   }
+
+  /** 
+  * prints a formatted number following printf conventions
+  * @param s a PrintStream, fmt the format string
+  * @param x a string that represents the digits to print
+  */
+  
+   public static void print(java.io.PrintStream s, String fmt, String x)
+   {  s.print(new Format(fmt).form(x));
+   }
+   
+  /** 
+  * Converts a string of digits (decimal, octal or hex) to an integer
+  * @param s a string
+  * @return the numeric value of the prefix of s representing a base 10 integer
+  */
+  
+   public static int atoi(String s)
+   {  return (int)atol(s);
+   } 
+   
+  /** 
+  * Converts a string of digits (decimal, octal or hex) to a long integer
+  * @param s a string
+  * @return the numeric value of the prefix of s representing a base 10 integer
+  */
+  
+   public static long atol(String s)
+   {  int i = 0;
+
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
+      if (i < s.length() && s.charAt(i) == '0')
+      {  if (i + 1 < s.length() && (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X'))
+            return parseLong(s.substring(i + 2), 16);
+         else return parseLong(s, 8);
+      }
+      else return parseLong(s, 10);
+   }
+
+   private static long parseLong(String s, int base)
+   {  int i = 0;
+      int sign = 1;
+      long r = 0;
+      
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
+      if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }
+      else if (i < s.length() && s.charAt(i) == '+') { i++; }
+      while (i < s.length())
+      {  char ch = s.charAt(i);
+         if ('0' <= ch && ch < '0' + base)
+            r = r * base + ch - '0';
+         else if ('A' <= ch && ch < 'A' + base - 10)
+            r = r * base + ch - 'A' + 10 ;
+         else if ('a' <= ch && ch < 'a' + base - 10)
+            r = r * base + ch - 'a' + 10 ;
+         else 
+            return r * sign;
+         i++;
+      }
+      return r * sign;      
+   }
+      
+   /** 
+   * Converts a string of digits to an double
+   * @param s a string
+   */
+   
+   public static double atof(String s)
+   {  int i = 0;
+      int sign = 1;
+      double r = 0; // integer part
+      double f = 0; // fractional part
+      double p = 1; // exponent of fractional part
+      int state = 0; // 0 = int part, 1 = frac part
+      
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
+      if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }
+      else if (i < s.length() && s.charAt(i) == '+') { i++; }
+      while (i < s.length())
+      {  char ch = s.charAt(i);
+         if ('0' <= ch && ch <= '9')
+         {  if (state == 0)
+               r = r * 10 + ch - '0';
+            else if (state == 1)
+            {  p = p / 10;
+               r = r + p * (ch - '0');
+            }
+         }
+         else if (ch == '.') 
+         {  if (state == 0) state = 1; 
+            else return sign * r;
+         }
+         else if (ch == 'e' || ch == 'E')
+         {  long e = (int)parseLong(s.substring(i + 1), 10);
+            return sign * r * Math.pow(10, e);
+         }
+         else return sign * r;
+         i++;
+      }
+      return sign * r;
+   }
+            
+   /** 
+   * Formats a double into a string (like sprintf in C)
+   * @param x the number to format
+   * @return the formatted string 
+   * @exception IllegalArgumentException if bad argument
+   */
+   
+   public String form(double x)
+   {  String r;
+      if (precision < 0) precision = 6;
+      int s = 1;
+      if (x < 0) { x = -x; s = -1; }
+      if (fmt == 'f')
+         r = fixed_format(x);
+      else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G')
+         r = exp_format(x);
+      else throw new java.lang.IllegalArgumentException();
+      
+      return pad(sign(s, r));
+   }
+   
+   /** 
+   * Formats a long integer into a string (like sprintf in C)
+   * @param x the number to format
+   * @return the formatted string 
+   */
+   
+   public String form(long x)
+   {  String r; 
+      int s = 0;
+      if (fmt == 'd' || fmt == 'i')
+      {  if (x < 0) 
+         {  r = ("" + x).substring(1);
+            s = -1; 
+         }
+         else 
+         {  r = "" + x; 
+            s = 1;
+         }
+      }
+      else if (fmt == 'o')
+         r = convert(x, 3, 7, "01234567");
+      else if (fmt == 'x')
+         r = convert(x, 4, 15, "0123456789abcdef");
+      else if (fmt == 'X')
+         r = convert(x, 4, 15, "0123456789ABCDEF");
+      else throw new java.lang.IllegalArgumentException();
+         
+      return pad(sign(s, r));
+   }
+   
+   /** 
+   * Formats a character into a string (like sprintf in C)
+   * @param x the value to format
+   * @return the formatted string 
+   */
+   
+   public String form(char c)
+   {  if (fmt != 'c')
+         throw new java.lang.IllegalArgumentException();
+
+      String r = "" + c;
+      return pad(r);
+   }
+   
+   /** 
+   * Formats a string into a larger string (like sprintf in C)
+   * @param x the value to format
+   * @return the formatted string 
+   */
+   
+   public String form(String s)
+   {  if (fmt != 's')
+         throw new java.lang.IllegalArgumentException();
+      if (precision >= 0 && precision < s.length()) 
+          s = s.substring(0, precision);
+      return pad(s);
+   }
+   
+    
+   /**
+   * a test stub for the format class
+   */
+   
+   public static void main(String[] a)
+   {  double x = 1.23456789012;
+      double y = 123;
+      double z = 1.2345e30;
+      double w = 1.02;
+      double u = 1.234e-5;
+      int d = 0xCAFE;
+      Format.print(System.out, "x = |%f|\n", x);
+      Format.print(System.out, "u = |%20f|\n", u);
+      Format.print(System.out, "x = |% .5f|\n", x);
+      Format.print(System.out, "w = |%20.5f|\n", w);
+      Format.print(System.out, "x = |%020.5f|\n", x);
+      Format.print(System.out, "x = |%+20.5f|\n", x);
+      Format.print(System.out, "x = |%+020.5f|\n", x);
+      Format.print(System.out, "x = |% 020.5f|\n", x);
+      Format.print(System.out, "y = |%#+20.5f|\n", y);
+      Format.print(System.out, "y = |%-+20.5f|\n", y);
+      Format.print(System.out, "z = |%20.5f|\n", z);
+      
+      Format.print(System.out, "x = |%e|\n", x);
+      Format.print(System.out, "u = |%20e|\n", u);
+      Format.print(System.out, "x = |% .5e|\n", x);
+      Format.print(System.out, "w = |%20.5e|\n", w);
+      Format.print(System.out, "x = |%020.5e|\n", x);
+      Format.print(System.out, "x = |%+20.5e|\n", x);
+      Format.print(System.out, "x = |%+020.5e|\n", x);
+      Format.print(System.out, "x = |% 020.5e|\n", x);
+      Format.print(System.out, "y = |%#+20.5e|\n", y);
+      Format.print(System.out, "y = |%-+20.5e|\n", y);
+      
+      Format.print(System.out, "x = |%g|\n", x);
+      Format.print(System.out, "z = |%g|\n", z);
+      Format.print(System.out, "w = |%g|\n", w);
+      Format.print(System.out, "u = |%g|\n", u);
+      Format.print(System.out, "y = |%.2g|\n", y);
+      Format.print(System.out, "y = |%#.2g|\n", y);
+
+      Format.print(System.out, "d = |%d|\n", d);
+      Format.print(System.out, "d = |%20d|\n", d);            
+      Format.print(System.out, "d = |%020d|\n", d);    
+      Format.print(System.out, "d = |%+20d|\n", d);
+      Format.print(System.out, "d = |% 020d|\n", d);
+      Format.print(System.out, "d = |%-20d|\n", d);
+      Format.print(System.out, "d = |%20.8d|\n", d);
+      Format.print(System.out, "d = |%x|\n", d);            
+      Format.print(System.out, "d = |%20X|\n", d);    
+      Format.print(System.out, "d = |%#20x|\n", d);
+      Format.print(System.out, "d = |%020X|\n", d);
+      Format.print(System.out, "d = |%20.8x|\n", d);
+      Format.print(System.out, "d = |%o|\n", d);            
+      Format.print(System.out, "d = |%020o|\n", d);    
+      Format.print(System.out, "d = |%#20o|\n", d);
+      Format.print(System.out, "d = |%#020o|\n", d);
+      Format.print(System.out, "d = |%20.12o|\n", d);
+      
+      Format.print(System.out, "s = |%-20s|\n", "Hello");      
+      Format.print(System.out, "s = |%-20c|\n", '!');      
+
+      // regression test to confirm fix of reported bugs
+
+      Format.print(System.out, "|%i|\n", Long.MIN_VALUE);
+
+      Format.print(System.out, "|%6.2e|\n", 0.0);
+      Format.print(System.out, "|%6.2g|\n", 0.0);
+
+      Format.print(System.out, "|%6.2f|\n", 9.99);
+      Format.print(System.out, "|%6.2f|\n", 9.999);
+
+      Format.print(System.out, "|%6.0f|\n", 9.999);
+   }
+   
+   private static String repeat(char c, int n)
+   {  if (n <= 0) return "";
+      StringBuffer s = new StringBuffer(n);
+      for (int i = 0; i < n; i++) s.append(c);
+      return s.toString();
+   }
+
+   private static String convert(long x, int n, int m, String d)
+   {  if (x == 0) return "0";
+      String r = "";
+      while (x != 0)
+      {  r = d.charAt((int)(x & m)) + r;
+         x = x >>> n;
+      }
+      return r;
+   }
+
+   private String pad(String r)
+   {  String p = repeat(' ', width - r.length());
+      if (left_align) return pre + r + p + post;
+      else return pre + p + r + post;
+   }
+   
+   private String sign(int s, String r)
+   {  String p = "";
+      if (s < 0) p = "-"; 
+      else if (s > 0)
+      {  if (show_plus) p = "+";
+         else if (show_space) p = " ";
+      }
+      else
+      {  if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0') p = "0";
+         else if (fmt == 'x' && alternate) p = "0x";
+         else if (fmt == 'X' && alternate) p = "0X";
+      }
+      int w = 0;
+      if (leading_zeroes) 
+         w = width;
+      else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o') 
+         && precision > 0) w = precision;
+      
+      return p + repeat('0', w - p.length() - r.length()) + r;
+   }
+   
+   private String fixed_format(double d)
+   {  boolean removeTrailing
+         = (fmt == 'G' || fmt == 'g') && !alternate;
+         // remove trailing zeroes and decimal point
+
+      if (d > 0x7FFFFFFFFFFFFFFFL) return exp_format(d);
+      if (precision == 0) 
+         return (long)(d + 0.5) + (removeTrailing ? "" : ".");
+
+      long whole = (long)d;
+      double fr = d - whole; // fractional part
+      if (fr >= 1 || fr < 0) return exp_format(d);
+
+      double factor = 1;
+      String leading_zeroes = "";
+      for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) 
+      {  factor *= 10; 
+         leading_zeroes = leading_zeroes + "0"; 
+      }
+      long l = (long) (factor * fr + 0.5);
+      if (l >= factor) { l = 0; whole++; } // CSH 10-25-97
+      
+      String z = leading_zeroes + l;
+      z = "." + z.substring(z.length() - precision, z.length());
+
+      if (removeTrailing)
+      {  int t = z.length() - 1;
+         while (t >= 0 && z.charAt(t) == '0') t--;
+         if (t >= 0 && z.charAt(t) == '.') t--;
+         z = z.substring(0, t + 1);
+      }
+
+      return whole + z;
+   }
+
+   private String exp_format(double d)
+   {  String f = "";
+      int e = 0;
+      double dd = d;
+      double factor = 1;
+      if (d != 0)
+      {  while (dd > 10) { e++; factor /= 10; dd = dd / 10; }
+         while (dd < 1) { e--; factor *= 10; dd = dd * 10; }
+      }
+      if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision) 
+         return fixed_format(d);
+      
+      d = d * factor;
+      f = f + fixed_format(d);
+      
+      if (fmt == 'e' || fmt == 'g')
+         f = f + "e";
+      else
+         f = f + "E";
+
+      String p = "000";      
+      if (e >= 0) 
+      {  f = f + "+";
+         p = p + e;
+      }
+      else
+      {  f = f + "-";
+         p = p + (-e);
+      }
+         
+      return f + p.substring(p.length() - 3, p.length());
+   }
+   
+   private int width;
+   private int precision;
+   private String pre;
+   private String post;
+   private boolean leading_zeroes;
+   private boolean show_plus;
+   private boolean alternate;
+   private boolean show_space;
+   private boolean left_align;
+   private char fmt; // one of cdeEfgGiosxXos
+}
+
+
+
+
+
+
diff --git a/Source/edu/stanford/ejalbert/BrowserLauncher.java b/Source/edu/stanford/ejalbert/BrowserLauncher.java
new file mode 100644
index 0000000..14fd1ad
--- /dev/null
+++ b/Source/edu/stanford/ejalbert/BrowserLauncher.java
@@ -0,0 +1,583 @@
+package edu.stanford.ejalbert;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * BrowserLauncher is a class that provides one static method, openURL, which opens the default
+ * web browser for the current user of the system to the given URL.  It may support other
+ * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously
+ * tested and is not guaranteed to work.
+ * <p>
+ * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms
+ * that are not part of the standard JDK.  What we're trying to do, though, is to take something
+ * that's frequently desirable but inherently platform-specific -- opening a default browser --
+ * and allow programmers (you, for example) to do so without worrying about dropping into native
+ * code or doing anything else similarly evil.
+ * <p>
+ * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without
+ * modification or a need for additional libraries.  All classes that are required on certain
+ * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not
+ * found, will not cause this to do anything other than returning an error when opening the
+ * browser.
+ * <p>
+ * There are certain system requirements for this class, as it's running through Runtime.exec(),
+ * which is Java's way of making a native system call.  Currently, this requires that a Macintosh
+ * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that
+ * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder
+ * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and
+ * 8.1), and for all Mac OS 8.5 and later systems.  On Windows, it only runs under Win32 systems
+ * (Windows 95, 98, and NT 4.0, as well as later versions of all).  On other systems, this drops
+ * back from the inherently platform-sensitive concept of a default browser and simply attempts
+ * to launch Netscape via a shell command.
+ * <p>
+ * This code is Copyright 1999-2001 by Eric Albert (ejalbert at cs.stanford.edu) and may be
+ * redistributed or modified in any form without restrictions as long as the portion of this
+ * comment from this paragraph through the end of the comment is not removed.  The author
+ * requests that he be notified of any application, applet, or other binary that makes use of
+ * this code, but that's more out of curiosity than anything and is not required.  This software
+ * includes no warranty.  The author is not repsonsible for any loss of data or functionality
+ * or any adverse or unexpected effects of using this software.
+ * <p>
+ * Credits:
+ * <br>Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>)
+ * <br>Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore,
+ * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
+ *
+ * @author Eric Albert (<a href="mailto:ejalbert at cs.stanford.edu">ejalbert at cs.stanford.edu</a>)
+ * @version 1.4b1 (Released June 20, 2001)
+ */
+public class BrowserLauncher {
+
+	/**
+	 * The Java virtual machine that we are running on.  Actually, in most cases we only care
+	 * about the operating system, but some operating systems require us to switch on the VM. */
+	private static int jvm;
+
+	/** The browser for the system */
+	private static Object browser;
+
+	/**
+	 * Caches whether any classes, methods, and fields that are not part of the JDK and need to
+	 * be dynamically loaded at runtime loaded successfully.
+	 * <p>
+	 * Note that if this is <code>false</code>, <code>openURL()</code> will always return an
+	 * IOException.
+	 */
+	private static boolean loadedWithoutErrors;
+
+	/** The com.apple.mrj.MRJFileUtils class */
+	private static Class mrjFileUtilsClass;
+
+	/** The com.apple.mrj.MRJOSType class */
+	private static Class mrjOSTypeClass;
+
+	/** The com.apple.MacOS.AEDesc class */
+	private static Class aeDescClass;
+	
+	/** The <init>(int) method of com.apple.MacOS.AETarget */
+	private static Constructor aeTargetConstructor;
+	
+	/** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */
+	private static Constructor appleEventConstructor;
+	
+	/** The <init>(String) method of com.apple.MacOS.AEDesc */
+	private static Constructor aeDescConstructor;
+	
+	/** The findFolder method of com.apple.mrj.MRJFileUtils */
+	private static Method findFolder;
+
+	/** The getFileCreator method of com.apple.mrj.MRJFileUtils */
+	private static Method getFileCreator;
+	
+	/** The getFileType method of com.apple.mrj.MRJFileUtils */
+	private static Method getFileType;
+	
+	/** The openURL method of com.apple.mrj.MRJFileUtils */
+	private static Method openURL;
+	
+	/** The makeOSType method of com.apple.MacOS.OSUtils */
+	private static Method makeOSType;
+	
+	/** The putParameter method of com.apple.MacOS.AppleEvent */
+	private static Method putParameter;
+	
+	/** The sendNoReply method of com.apple.MacOS.AppleEvent */
+	private static Method sendNoReply;
+	
+	/** Actually an MRJOSType pointing to the System Folder on a Macintosh */
+	private static Object kSystemFolderType;
+
+	/** The keyDirectObject AppleEvent parameter type */
+	private static Integer keyDirectObject;
+
+	/** The kAutoGenerateReturnID AppleEvent code */
+	private static Integer kAutoGenerateReturnID;
+	
+	/** The kAnyTransactionID AppleEvent code */
+	private static Integer kAnyTransactionID;
+
+	/** The linkage object required for JDirect 3 on Mac OS X. */
+	private static Object linkage;
+	
+	/** The framework to reference on Mac OS X */
+	private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
+
+	/** JVM constant for MRJ 2.0 */
+	private static final int MRJ_2_0 = 0;
+	
+	/** JVM constant for MRJ 2.1 or later */
+	private static final int MRJ_2_1 = 1;
+
+	/** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */
+	private static final int MRJ_3_0 = 3;
+	
+	/** JVM constant for MRJ 3.1 */
+	private static final int MRJ_3_1 = 4;
+
+	/** JVM constant for any Windows NT JVM */
+	private static final int WINDOWS_NT = 5;
+	
+	/** JVM constant for any Windows 9x JVM */
+	private static final int WINDOWS_9x = 6;
+
+	/** JVM constant for any other platform */
+	private static final int OTHER = -1;
+
+	/**
+	 * The file type of the Finder on a Macintosh.  Hardcoding "Finder" would keep non-U.S. English
+	 * systems from working properly.
+	 */
+	private static final String FINDER_TYPE = "FNDR";
+
+	/**
+	 * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the
+	 * application.
+	 */
+	private static final String FINDER_CREATOR = "MACS";
+
+	/** The name for the AppleEvent type corresponding to a GetURL event. */
+	private static final String GURL_EVENT = "GURL";
+
+	/**
+	 * The first parameter that needs to be passed into Runtime.exec() to open the default web
+	 * browser on Windows.
+	 */
+    private static final String FIRST_WINDOWS_PARAMETER = "/c";
+    
+    /** The second parameter for Runtime.exec() on Windows. */
+    private static final String SECOND_WINDOWS_PARAMETER = "start";
+    
+    /**
+     * The third parameter for Runtime.exec() on Windows.  This is a "title"
+     * parameter that the command line expects.  Setting this parameter allows
+     * URLs containing spaces to work.
+     */
+    private static final String THIRD_WINDOWS_PARAMETER = "\"\"";
+	
+	/**
+	 * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape
+	 * on many command-line systems.
+	 */
+	private static final String NETSCAPE_REMOTE_PARAMETER = "-remote";
+	private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL(";
+	private static final String NETSCAPE_OPEN_PARAMETER_END = ")'";
+	
+	/**
+	 * The message from any exception thrown throughout the initialization process.
+	 */
+	private static String errorMessage;
+
+	/**
+	 * An initialization block that determines the operating system and loads the necessary
+	 * runtime data.
+	 */
+	static {
+		loadedWithoutErrors = true;
+		String osName = System.getProperty("os.name");
+		if (osName.startsWith("Mac OS")) {
+			String mrjVersion = System.getProperty("mrj.version");
+			String majorMRJVersion = mrjVersion.substring(0, 3);
+			try {
+				double version = Double.valueOf(majorMRJVersion).doubleValue();
+				if (version == 2) {
+					jvm = MRJ_2_0;
+				} else if (version >= 2.1 && version < 3) {
+					// Assume that all 2.x versions of MRJ work the same.  MRJ 2.1 actually
+					// works via Runtime.exec() and 2.2 supports that but has an openURL() method
+					// as well that we currently ignore.
+					jvm = MRJ_2_1;
+				} else if (version == 3.0) {
+					jvm = MRJ_3_0;
+				} else if (version >= 3.1) {
+					// Assume that all 3.1 and later versions of MRJ work the same.
+					jvm = MRJ_3_1;
+				} else {
+					loadedWithoutErrors = false;
+					errorMessage = "Unsupported MRJ version: " + version;
+				}
+			} catch (NumberFormatException nfe) {
+				loadedWithoutErrors = false;
+				errorMessage = "Invalid MRJ version: " + mrjVersion;
+			}
+		} else if (osName.startsWith("Windows")) {
+			if (osName.indexOf("9") != -1) {
+				jvm = WINDOWS_9x;
+			} else {
+				jvm = WINDOWS_NT;
+			}
+		} else {
+			jvm = OTHER;
+		}
+		
+		if (loadedWithoutErrors) {	// if we haven't hit any errors yet
+			loadedWithoutErrors = loadClasses();
+		}
+	}
+
+	/**
+	 * This class should be never be instantiated; this just ensures so.
+	 */
+	private BrowserLauncher() { }
+	
+	/**
+	 * Called by a static initializer to load any classes, fields, and methods required at runtime
+	 * to locate the user's web browser.
+	 * @return <code>true</code> if all intialization succeeded
+	 *			<code>false</code> if any portion of the initialization failed
+	 */
+	private static boolean loadClasses() {
+		switch (jvm) {
+			case MRJ_2_0:
+				try {
+					Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget");
+					Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils");
+					Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent");
+					Class aeClass = Class.forName("com.apple.MacOS.ae");
+					aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
+
+					aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class });
+					appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class });
+					aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class });
+
+					makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class });
+					putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass });
+					sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { });
+
+					Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject");
+					keyDirectObject = (Integer) keyDirectObjectField.get(null);
+					Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID");
+					kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null);
+					Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID");
+					kAnyTransactionID = (Integer) anyTransactionIDField.get(null);
+				} catch (ClassNotFoundException cnfe) {
+					errorMessage = cnfe.getMessage();
+					return false;
+				} catch (NoSuchMethodException nsme) {
+					errorMessage = nsme.getMessage();
+					return false;
+				} catch (NoSuchFieldException nsfe) {
+					errorMessage = nsfe.getMessage();
+					return false;
+				} catch (IllegalAccessException iae) {
+					errorMessage = iae.getMessage();
+					return false;
+				}
+				break;
+			case MRJ_2_1:
+				try {
+					mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+					mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
+					Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType");
+					kSystemFolderType = systemFolderField.get(null);
+					findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass });
+					getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class });
+					getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class });
+				} catch (ClassNotFoundException cnfe) {
+					errorMessage = cnfe.getMessage();
+					return false;
+				} catch (NoSuchFieldException nsfe) {
+					errorMessage = nsfe.getMessage();
+					return false;
+				} catch (NoSuchMethodException nsme) {
+					errorMessage = nsme.getMessage();
+					return false;
+				} catch (SecurityException se) {
+					errorMessage = se.getMessage();
+					return false;
+				} catch (IllegalAccessException iae) {
+					errorMessage = iae.getMessage();
+					return false;
+				}
+				break;
+			case MRJ_3_0:
+			    try {
+					Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
+					Constructor constructor = linker.getConstructor(new Class[]{ Class.class });
+					linkage = constructor.newInstance(new Object[] { BrowserLauncher.class });
+				} catch (ClassNotFoundException cnfe) {
+					errorMessage = cnfe.getMessage();
+					return false;
+				} catch (NoSuchMethodException nsme) {
+					errorMessage = nsme.getMessage();
+					return false;
+				} catch (InvocationTargetException ite) {
+					errorMessage = ite.getMessage();
+					return false;
+				} catch (InstantiationException ie) {
+					errorMessage = ie.getMessage();
+					return false;
+				} catch (IllegalAccessException iae) {
+					errorMessage = iae.getMessage();
+					return false;
+				}
+				break;
+			case MRJ_3_1:
+				try {
+					mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+					openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class });
+				} catch (ClassNotFoundException cnfe) {
+					errorMessage = cnfe.getMessage();
+					return false;
+				} catch (NoSuchMethodException nsme) {
+					errorMessage = nsme.getMessage();
+					return false;
+				}
+				break;
+			default:
+			    break;
+		}
+		return true;
+	}
+
+	/**
+	 * Attempts to locate the default web browser on the local system.  Caches results so it
+	 * only locates the browser once for each use of this class per JVM instance.
+	 * @return The browser for the system.  Note that this may not be what you would consider
+	 *			to be a standard web browser; instead, it's the application that gets called to
+	 *			open the default web browser.  In some cases, this will be a non-String object
+	 *			that provides the means of calling the default browser.
+	 */
+	private static Object locateBrowser() {
+		if (browser != null) {
+			return browser;
+		}
+		switch (jvm) {
+			case MRJ_2_0:
+				try {
+					Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR });
+					Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode });
+					Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT });
+					Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID });
+					// Don't set browser = appleEvent because then the next time we call
+					// locateBrowser(), we'll get the same AppleEvent, to which we'll already have
+					// added the relevant parameter. Instead, regenerate the AppleEvent every time.
+					// There's probably a way to do this better; if any has any ideas, please let
+					// me know.
+					return appleEvent;
+				} catch (IllegalAccessException iae) {
+					browser = null;
+					errorMessage = iae.getMessage();
+					return browser;
+				} catch (InstantiationException ie) {
+					browser = null;
+					errorMessage = ie.getMessage();
+					return browser;
+				} catch (InvocationTargetException ite) {
+					browser = null;
+					errorMessage = ite.getMessage();
+					return browser;
+				}
+			case MRJ_2_1:
+				File systemFolder;
+				try {
+					systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType });
+				} catch (IllegalArgumentException iare) {
+					browser = null;
+					errorMessage = iare.getMessage();
+					return browser;
+				} catch (IllegalAccessException iae) {
+					browser = null;
+					errorMessage = iae.getMessage();
+					return browser;
+				} catch (InvocationTargetException ite) {
+					browser = null;
+					errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+					return browser;
+				}
+				String[] systemFolderFiles = systemFolder.list();
+				// Avoid a FilenameFilter because that can't be stopped mid-list
+				for(int i = 0; i < systemFolderFiles.length; i++) {
+					try {
+						File file = new File(systemFolder, systemFolderFiles[i]);
+						if (!file.isFile()) {
+							continue;
+						}
+						// We're looking for a file with a creator code of 'MACS' and
+						// a type of 'FNDR'.  Only requiring the type results in non-Finder
+						// applications being picked up on certain Mac OS 9 systems,
+						// especially German ones, and sending a GURL event to those
+						// applications results in a logout under Multiple Users.
+						Object fileType = getFileType.invoke(null, new Object[] { file });
+						if (FINDER_TYPE.equals(fileType.toString())) {
+							Object fileCreator = getFileCreator.invoke(null, new Object[] { file });
+							if (FINDER_CREATOR.equals(fileCreator.toString())) {
+								browser = file.toString();	// Actually the Finder, but that's OK
+								return browser;
+							}
+						}
+					} catch (IllegalArgumentException iare) {
+						browser = browser;
+						errorMessage = iare.getMessage();
+						return null;
+					} catch (IllegalAccessException iae) {
+						browser = null;
+						errorMessage = iae.getMessage();
+						return browser;
+					} catch (InvocationTargetException ite) {
+						browser = null;
+						errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+						return browser;
+					}
+				}
+				browser = null;
+				break;
+			case MRJ_3_0:
+			case MRJ_3_1:
+				browser = "";	// Return something non-null
+				break;
+			case WINDOWS_NT:
+				browser = "cmd.exe";
+				break;
+			case WINDOWS_9x:
+				browser = "command.com";
+				break;
+			case OTHER:
+			default:
+				browser = "netscape";
+				break;
+		}
+		return browser;
+	}
+
+	/**
+	 * Attempts to open the default web browser to the given URL.
+	 * @param url The URL to open
+	 * @throws IOException If the web browser could not be located or does not run
+	 */
+	public static void openURL(String url) throws IOException {
+		if (!loadedWithoutErrors) {
+			throw new IOException("Exception in finding browser: " + errorMessage);
+		}
+		Object browser = locateBrowser();
+		if (browser == null) {
+			throw new IOException("Unable to locate browser: " + errorMessage);
+		}
+		
+		switch (jvm) {
+			case MRJ_2_0:
+				Object aeDesc = null;
+				try {
+					aeDesc = aeDescConstructor.newInstance(new Object[] { url });
+					putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
+					sendNoReply.invoke(browser, new Object[] { });
+				} catch (InvocationTargetException ite) {
+					throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
+				} catch (IllegalAccessException iae) {
+					throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
+				} catch (InstantiationException ie) {
+					throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
+				} finally {
+					aeDesc = null;	// Encourage it to get disposed if it was created
+					browser = null;	// Ditto
+				}
+				break;
+			case MRJ_2_1:
+				Runtime.getRuntime().exec(new String[] { (String) browser, url } );
+				break;
+			case MRJ_3_0:
+				int[] instance = new int[1];
+				int result = ICStart(instance, 0);
+				if (result == 0) {
+					int[] selectionStart = new int[] { 0 };
+					byte[] urlBytes = url.getBytes();
+					int[] selectionEnd = new int[] { urlBytes.length };
+					result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
+											urlBytes.length, selectionStart,
+											selectionEnd);
+					if (result == 0) {
+						// Ignore the return value; the URL was launched successfully
+						// regardless of what happens here.
+						ICStop(instance);
+					} else {
+						throw new IOException("Unable to launch URL: " + result);
+					}
+				} else {
+					throw new IOException("Unable to create an Internet Config instance: " + result);
+				}
+				break;
+			case MRJ_3_1:
+				try {
+					openURL.invoke(null, new Object[] { url });
+				} catch (InvocationTargetException ite) {
+					throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
+				} catch (IllegalAccessException iae) {
+					throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
+				}
+				break;
+		    case WINDOWS_NT:
+		    case WINDOWS_9x:
+		    	// Add quotes around the URL to allow ampersands and other special
+		    	// characters to work.
+				Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
+																FIRST_WINDOWS_PARAMETER,
+																SECOND_WINDOWS_PARAMETER,
+																THIRD_WINDOWS_PARAMETER,
+																'"' + url + '"' });
+				// This avoids a memory leak on some versions of Java on Windows.
+				// That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
+				try {
+					process.waitFor();
+					process.exitValue();
+				} catch (InterruptedException ie) {
+					throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+				}
+				break;
+			case OTHER:
+				// Assume that we're on Unix and that Netscape is installed
+				
+				// First, attempt to open the URL in a currently running session of Netscape
+				process = Runtime.getRuntime().exec(new String[] { (String) browser,
+													NETSCAPE_REMOTE_PARAMETER,
+													NETSCAPE_OPEN_PARAMETER_START +
+													url +
+													NETSCAPE_OPEN_PARAMETER_END });
+				try {
+					int exitCode = process.waitFor();
+					if (exitCode != 0) {	// if Netscape was not open
+						Runtime.getRuntime().exec(new String[] { (String) browser, url });
+					}
+				} catch (InterruptedException ie) {
+					throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+				}
+				break;
+			default:
+				// This should never occur, but if it does, we'll try the simplest thing possible
+				Runtime.getRuntime().exec(new String[] { (String) browser, url });
+				break;
+		}
+	}
+
+	/**
+	 * Methods required for Mac OS X.  The presence of native methods does not cause
+	 * any problems on other platforms.
+	 */
+	private native static int ICStart(int[] instance, int signature);
+	private native static int ICStop(int[] instance);
+	private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
+											int[] selectionStart, int[] selectionEnd);
+}
diff --git a/Source/mesquite/Mesquite.java b/Source/mesquite/Mesquite.java
new file mode 100644
index 0000000..103587e
--- /dev/null
+++ b/Source/mesquite/Mesquite.java
@@ -0,0 +1,2564 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+import javax.imageio.ImageIO;
+
+import com.apple.mrj.MRJFileUtils;
+import com.apple.mrj.MRJOSType;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.*;
+import mesquite.lib.characters.*;
+import mesquite.trunk.*;
+
+/* The root module of the tree of modules.  This contains the main method which uses MesquiteModuleLoader to compile information
+about available modules.  Also hires FileCoordinator modules (which in turn hire others to do analyses).   */
+
+public class Mesquite extends MesquiteTrunk 
+{
+	/*.................................................................................................................*/
+	public String getCitation() {
+		return "Maddison, W.P. & D.R. Maddison. 2015.  Mesquite: A modular system for evolutionary analysis.  Version 3.04.  http://mesquiteproject.org";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return "3.04";
+	}
+
+	/*.................................................................................................................*/
+	public int getVersionInt() {
+		return 304;
+	}
+	/*.................................................................................................................*/
+	public double getMesquiteVersionNumber(){
+		return 3.04;
+	}
+	/*.................................................................................................................*/
+	public String getDateReleased() {
+		return "August 2015"; //"April 2007";
+	}
+	/*.................................................................................................................*/
+	/** returns the URL of the notices file for this module so that it can phone home and check for messages */
+	public String  getHomePhoneNumber(){ 
+		if (!isPrerelease() && !debugMode)
+			return "http://mesquiteproject.org/mesquite/notice/notices.xml";   
+		else
+			return "http://mesquiteproject.org/mesquite/prereleasenotices/notices.xml";   
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed ee = registerEmployeeNeed(FileCoordinator.class, "The file coordinator supervises activities with files.",
+				"These are activated when new projects/files are made or read. ");
+		ee.setAsEntryPoint(null);
+		EmployeeNeed e = registerEmployeeNeed(MesquiteInit.class, "INIT modules assist Mesquite.",
+				"These are activated automatically. ");
+		e.setAsEntryPoint(null);
+		EmployeeNeed e2 = registerEmployeeNeed(BrowseHierarchy.class, "Mesquite uses these modules for hierarchical display of employee and project trees.",
+				"These are activated automatically. ");
+		e2.setAsEntryPoint(null);
+		EmployeeNeed e3 = registerEmployeeNeed(WindowHolder.class, "Mesquite uses a WindowHolder to assist displaying windows.",
+				"These are activated automatically. ");
+		e3.setAsEntryPoint(null);
+	}
+	ClockWatcherThread cwt;
+	public static Image general, calculations, display, left, right;
+	public boolean openFilesNowUsed = false;
+	public boolean ready=false;
+	public int numDirectories = 0;
+	private boolean preferencesSet = false;
+	protected int lastVersionUsedInt = 0;
+	protected String lastVersionRun = "1.04";
+	//private String storedManualString = null;
+	private boolean showLogWindow = true;
+	private boolean showAbout = true;
+	private boolean consoleMode = false;
+	private Vector splashURLInfo = new Vector(3);
+	private ListableVector splashNames = new ListableVector(3);
+	public static AboutWindow about;
+	private String supportFilesPath;
+	private File supportFilesDirectory;
+	private int numUses =0;
+	String configFile = "all";
+	HPanel browser;
+	ListableVector configurations;
+	private  FileOpener fileHandler;
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		deleteTempDirectory();
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public void dispose(){
+		/*	if (logWindow != null){
+			MesquiteFrame f = logWindow.getParentFrame();
+			f.setVisible(false);
+		}*/
+		splashNames.dispose();
+		configurations.dispose();
+		super.dispose();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void substantivePrereleasesFound(){
+		if (!substantivePrereleasesExist){
+			substantivePrereleasesExist = true;
+			if (about!=null && about.aboutPanel!=null)
+				about.aboutPanel.repaint();
+		}
+	}
+
+
+	static boolean startedFromOSXJava17Executable = false;
+	/*.................................................................................................................*/
+	public void init()
+	{
+		boolean verboseStartup = false;
+		long startingTime = System.currentTimeMillis();
+		System.setProperty("awt.useSystemAAFontSettings","on");
+		System.setProperty("swing.aatext", "true");
+		if (verboseStartup) System.out.println("main init 1");
+		if (isApplet())
+			mesquiteTrunk = this;
+		author.setCurrent(true);
+		incrementMenuResetSuppression();
+		boolean makeNewPrefsDirectory = false;
+		configurations = new ListableVector(); 
+		packages = new ListableVector();
+		if (isPrerelease())
+			errorReportURL =  "http://mesquiteproject.org/pyMesquiteFeedbackPrerelease";
+
+		/* 
+(1) Look for Mesquite.pref file in .Mesquite_Prefs folder of user.home.  If exists, read it 
+(2) Try to find mesquite manual.  If not found, query user for manual.  Remember that it hadn't been found, and later store its place
+		 */
+
+		if (verboseStartup) System.out.println("main init 2");
+
+
+		String sep = MesquiteFile.fileSeparator;
+		supportFilesPath = System.getProperty("user.home") + sep + "Mesquite_Support_Files";
+
+		//finding mesquite directory
+		ClassLoader cl = mesquite.Mesquite.class.getClassLoader();
+		String loc = cl.getResource("mesquite/Mesquite.class").getPath();
+
+		String sepp = MesquiteFile.fileSeparator;
+		if (loc.indexOf(sepp)<0){
+			sepp = "/";
+			if (loc.indexOf(sepp)<0)
+				System.out.println("Not a recognized separator in path to Mesquite class!");
+			loc = loc.substring(0, loc.lastIndexOf(sepp));
+			loc = loc.substring(0, loc.lastIndexOf(sepp));
+			System.out.println("@ " + loc);
+
+			try {
+				if (startedFromOSXJava17Executable)  //for OS X executable built by Oracle appBundler
+					loc = StringUtil.encodeForURL(loc);
+				URI uri = new URI(loc);
+				mesquiteDirectory = new File(uri.getSchemeSpecificPart());
+			} catch (URISyntaxException e) {
+				e.printStackTrace();
+			}
+
+
+
+
+		}
+		else {
+			loc = loc.substring(0, loc.lastIndexOf(sepp));
+			loc = loc.substring(0, loc.lastIndexOf(sepp));
+			System.out.println("@ " + loc);
+			try {
+				if (startedFromOSXJava17Executable) //for OS X executable built by Oracle appBundler
+					loc = StringUtil.encodeForURL(loc);
+				URI uri = new URI(loc);
+				mesquiteDirectory = new File(uri.getSchemeSpecificPart());
+			} catch (URISyntaxException e) {
+				e.printStackTrace();
+			}
+		}
+
+		if (mesquiteDirectory == null){
+			StringTokenizer st = new StringTokenizer(System.getProperty("java.class.path"), ":");
+			while (st.hasMoreElements()){
+				String token = st.nextToken();
+				File mesquiteClass = new File(token + MesquiteFile.fileSeparator + "mesquite" + MesquiteFile.fileSeparator + "Mesquite.class");
+				if (mesquiteClass.exists()) {
+					mesquiteDirectory = new File(token);
+					if (!mesquiteDirectory.exists())
+						mesquiteDirectory = null;
+				}
+			}
+		}
+
+
+
+		if (mesquiteDirectory ==null){
+			File mesquiteClass = new File(System.getProperty("user.dir") + MesquiteFile.fileSeparator + "mesquite" + MesquiteFile.fileSeparator + "Mesquite.class");
+			if (mesquiteClass.exists()) {
+				mesquiteDirectory = new File(System.getProperty("user.dir"));
+				if (!mesquiteDirectory.exists())
+					mesquiteDirectory = null;
+			}
+		}
+		if (verboseStartup) System.out.println("main init 3");
+
+		/* EMBEDDED delete these if embedded */
+		userDirectory = new File(System.getProperty("user.home")+sep);  //used to be user.dir, but caused permission problems in linux
+
+		supportFilesDirectory = new File(supportFilesPath);
+		if (!supportFilesDirectory.exists()){
+			supportFilesDirectory.mkdir();
+		}
+		boolean supportFilesWritable = MesquiteFile.canWrite(supportFilesPath);
+		boolean writabilityWarned = false;
+		if (!supportFilesWritable || !supportFilesDirectory.exists()){
+			String oldPath = supportFilesPath;
+			supportFilesPath = mesquiteDirectory.getPath() + sep + "Mesquite_Support_Files";
+			supportFilesDirectory = new File(supportFilesPath);
+			if (!supportFilesDirectory.exists())
+				supportFilesDirectory.mkdir();
+			if (!supportFilesDirectory.exists()){
+				writabilityWarned = true;
+				if (MesquiteWindow.headless)
+					System.out.println("Mesquite does not have permission to write its log file or its preferences files.  It has attempted to create both " + oldPath +
+							"\" and \"" + supportFilesPath + "\" but failed.");
+				else
+					alert("Mesquite does not have permission to write its log file or its preferences files.  It has attempted to create both " + oldPath +
+							"\" and \"" + supportFilesPath + "\" but failed.  This will prevent Mesquite from functioning properly.  Please check that your system permits " +
+							"Mesquite to write to " + userDirectory);
+			}
+		}
+		if (verboseStartup) System.out.println("main init 4");
+
+
+
+		MesquiteModule.prefsDirectory = new File(supportFilesPath + sep + "Mesquite_Prefs"); //checking both possible names
+		File prefsFile = new File(prefsDirectory.toString() + sep + "Mesquite.pref");
+		File prefsFileXML = new File(prefsDirectory.toString() + sep + "Mesquite.xml");
+
+
+		if (verboseStartup) System.out.println("main init 5");
+		if (!MesquiteModule.prefsDirectory.exists() || !MesquiteModule.prefsDirectory.isDirectory()) {
+			makeNewPrefsDirectory = true;
+			setMesquiteDirectoryPath();
+		}
+		else if (prefsFile.exists() || prefsFileXML.exists()) {
+			if (MesquiteModule.mesquiteDirectory==null) 
+				setMesquiteDirectoryPath();
+			else
+				setMesquiteDirectoryPath();
+		}
+		else {
+			setMesquiteDirectoryPath();
+		}
+		if (verboseStartup) System.out.println("main init 6");
+
+		//loading jar files
+		DirectInit di = new DirectInit(this);
+
+		if (prefsFile.exists() || prefsFileXML.exists()) {
+			loadPreferences();
+			if (!preferencesSet) {
+				setMesquiteDirectoryPath();
+			}
+		}
+		if (verboseStartup) System.out.println("main init 7");
+
+
+		String logPath = supportFilesPath + sep + MesquiteTrunk.logFileName; 
+		File logFile = new File(logPath);
+
+		boolean logFileExistsButCantWrite = (logFile.exists() &&!logFile.canWrite());
+		boolean logFileAbsentButCantWriteContainer = (!logFile.exists() && !(new File(supportFilesPath).canWrite()));
+		if (verboseStartup) System.out.println("main init 8");
+		if ((logFileExistsButCantWrite || logFileAbsentButCantWriteContainer) && !writabilityWarned){
+			if (MesquiteWindow.headless)
+				System.out.println("Mesquite does not have permission to write its log file.");
+			else
+				alert("Mesquite does not have permission to write its log file.  This may indicate issues with your system configuration that will prevent Mesquite from functioning properly.  Please check that your system permits " +
+						"Mesquite to write to " + userDirectory);
+			MesquiteMessage.println("Log can't be written (" + logFileExistsButCantWrite + ", " + logFileAbsentButCantWriteContainer + " at " + logPath + ")");
+		}
+		if (verboseStartup) System.out.println("main init 9");
+
+		if (logFile.exists()) {
+			for (int i = MesquiteTrunk.numPrevLogs-1; i>0; i--) {
+				String iPath = supportFilesPath  + sep + MesquiteTrunk.logFileName + "_(Previous#" + i + ")";
+				String iPlusOnePath = supportFilesPath + sep + MesquiteTrunk.logFileName + "_(Previous#" + (i+1) + ")";
+				MesquiteFile.rename(iPath, iPlusOnePath);
+			}
+			MesquiteFile.rename(logPath, supportFilesPath + sep + MesquiteTrunk.logFileName + "_(Previous#1)");
+		}
+		if (verboseStartup) System.out.println("main init 10");
+		/*
+		 * 		String recentFilesPath = supportFilesPath + sep + MesquiteTrunk.recentFilesFileName; 
+		File recentFilesFile = new File(recentFilesPath);
+		if (recentFilesFile.exists()) {
+		}
+		 */
+
+		/**/
+		/*
+(3) Try to find the logo for the about window
+		 */
+		String logInitString = "Mesquite version " + getMesquiteVersion() + getBuildVersion() + "\n";
+		if (StringUtil.notEmpty(MesquiteModule.getSpecialVersion()))
+			logInitString  +="  " + MesquiteModule.getSpecialVersion()+ "\n";
+		logInitString  += ("Copyright (c) 1997-2015 W. Maddison and D. Maddison\n");
+		logInitString  += "The basic Mesquite package (class library and basic modules) is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License. "
+				+ "  Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.  For details on license and "
+				+ "lack of warranty see the GNU Lesser General Public License by selecting \"Display License\" from the Window menu or at www.gnu.org\n"
+				+ "\nPrincipal Authors: Wayne Maddison & David Maddison\nDevelopment Team: Wayne Maddison, David Maddison, Peter Midford, Rutger Vos, Jeff Oliver, Daisie Huang"
+				+ "\nDevelopment Team Alumnus: Danny Mandel\n";
+
+		if (verboseStartup) System.out.println("main init 11");
+		logWindow = new LogWindow(logInitString);
+		if (verboseStartup) System.out.println("main init 12");
+		logWindow.setAsPrimaryMesquiteWindow(true);
+		setModuleWindow(logWindow);
+		if (verboseStartup) System.out.println("main init 13");
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease()) {
+			mesquiteTrunk.logo = MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/mesquiteBeta.gif");
+		}
+		else
+			mesquiteTrunk.logo = MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/mesquite.gif");
+
+		BufferedImage equiv = null;
+		try {
+			equiv = ImageIO.read(new File(MesquiteModule.getRootPath() + "images/equivocal.gif"));
+		} catch (IOException e) {
+			MesquiteMessage.println(" IOException trying to read equivocal texture ");
+		}
+		GraphicsUtil.missingDataTexture = new TexturePaint(equiv, new Rectangle(0, 0, 16, 16));
+
+		if (verboseStartup) System.out.println("main init 14");
+		MediaTracker mt = new MediaTracker(logWindow.getOuterContentsArea());
+		mt.addImage(logo, 0);
+		try {
+			mt.waitForAll();
+		} catch (Exception e) {
+			MesquiteMessage.warnProgrammer("logo image exception------------");
+			e.printStackTrace();
+		}
+		if (verboseStartup) System.out.println("main init 15");
+		if (about !=null)
+			about.setImage(logo);
+		if (verboseStartup) System.out.println("main init 16");
+
+
+		tempDirectory = createTempDirectory();
+
+
+		/*EMBEDDED include following if embedded *
+		setLayout( new BorderLayout() );
+		embeddedPanel = new Panel();
+		add("Center", embeddedPanel);
+		embeddedPanel.setBackground(Color.cyan);
+		embeddedPanel.setVisible(true);
+		embeddedPanel.setLayout(null);
+		embeddedPanel.repaint();
+		/*EMBEDDED include above if embedded */
+
+
+		if (verboseStartup) System.out.println("main init 17");
+		if (isApplet()) { 
+			mesquiteTrunk = this;
+			prepareMesquite();
+		}
+		if (verboseStartup) System.out.println("main init 18");
+		if (isJavaVersionLessThan(1.6)){
+			discreetAlert("This version of Mesquite requires Java 1.6 or higher.  Please update your version of Java, or use an older version of Mesquite.  Please be aware however that earlier versions of Mesquite may have bugs that affect your results.  Please check the Mesquite website for information.");
+			exit(true, 0);
+		}
+
+		if (verboseStartup) System.out.println("main init 19");
+		logWindow.setConsoleMode(consoleMode);
+		if (verboseStartup) System.out.println("main init 19a");
+		//logWindow.setWindowSize(380,351); //this and later setWindowSize done because of bug in OS X 1.4.X
+		logWindow.setWindowLocation(8, 8, false);
+		if (verboseStartup) System.out.println("main init 19b");
+		if (showLogWindow)
+			logWindow.setVisible(true);
+		if (verboseStartup) System.out.println("main init 19c");
+		logWindow.setWindowSize(400,450);
+
+		if (verboseStartup) System.out.println("main init 20");
+		//		logln(System.getenv().toString());
+		logln(" ");
+		//logln(notice);
+		startupTime = System.currentTimeMillis();
+		Date dnow = new Date(startupTime);
+		logln(StringUtil.getDateTime(dnow));
+		//logln( dnow.toString());
+		if (startupTime <1100000000000L) {
+			discreetAlert("The clock on your computer appears to be set incorrectly.  This version of Mesquite was compiled after November 2004, but your computer's date appears to be " + dnow.toString());
+		}
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			mrj = "";
+		else
+			mrj = "; MRJ version " + mrj;
+		if (verboseStartup) System.out.println("main init 21");
+		logln("Running under Java " + System.getProperty("java.version") +"; virtual machine by " + System.getProperty("java.vendor") + mrj + " on " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " (architecture: " + System.getProperty("os.arch") + ")");
+		logln("User: " + System.getProperty("user.name") );
+		logln(" ");
+		/* EMBEDDED add following if embedded *
+		logWindow.setVisible(false);
+		 /* */
+		logln(jarFilesLoaded.toString());
+
+
+		makeEmployeeVector();
+		if (verboseStartup) System.out.println("main init 22");
+
+
+		Random rNG = new Random();
+
+		MesquiteWindow.centerWindow(about);
+
+
+		if (!preferencesSet){
+			//WelcomeDialog is being phased out
+			if (false && !MesquiteWindow.headless && !MesquiteThread.suppressInteractionAsLibrary){  //hackathon
+				String s = "Welcome to Mesquite.  If this is the first time you've run Mesquite, you might want to try the example files to learn about how to use it (example files in \"Mesquite_Folder/examples\").  You might also check the menu items in the Help menu for links to documentation.";
+				s += "\n\nAlso, please sign up to the Mesquite Discussion e-mail list to learn about bugs and updates (instructions for signing up at http://mesquiteproject.org).";
+				new WelcomeDialog(containerOfModule(), "Welcome to Mesquite", s);
+			}
+			if (makeNewPrefsDirectory) {
+				MesquiteModule.prefsDirectory.mkdir();
+			}
+			storePreferences();
+		}
+		if (verboseStartup) System.out.println("main init 23");
+		if (about !=null) {
+			if (isApplet())
+				about.setVisible(false);
+			else {
+				if (verboseStartup) System.out.println("main init 23a");
+				MesquiteWindow.centerWindow(about);
+				if (verboseStartup) System.out.println("main init 23b");
+				about.setVisible(true);
+				if (verboseStartup) System.out.println("main init 23c");
+			}
+			about.setBackground(ColorTheme.getInterfaceBackground());
+			about.repaint();
+		}
+		if (verboseStartup) System.out.println("main init 24");
+
+		/*----*/
+
+		suggestedDirectory = mesquiteDirectoryPath + "examples";
+		if (mesquiteDirectory!=null)
+			logln("Mesquite directory: " + mesquiteDirectoryPath);
+		else
+			logln("Mesquite directory null ");
+		if (userDirectory!=null)
+			logln("Log file located in: " + supportFilesPath);
+		if (prefsDirectory!=null) {
+			logln("Prefs directory: " + prefsDirectory.getAbsolutePath());
+			if (MesquiteWindow.headless)  //hackathon
+				MesquiteFile.putFileContents(prefsDirectory + MesquiteFile.fileSeparator + "mesquiteHeadlessLocation.txt", mesquiteDirectoryPath, true);
+			else
+				MesquiteFile.putFileContents(prefsDirectory + MesquiteFile.fileSeparator + "mesquiteLocation.txt", mesquiteDirectoryPath, true);
+		}
+		else
+			logln("Prefs directory null ");
+
+		logln(" ");
+
+
+
+		/* loading in modules (MesquiteModules) */
+		MesquiteModule.mesquiteTrunk = this;
+
+
+		if (verboseStartup) System.out.println("main init 25");
+		setupColors();
+
+		if (MesquiteWindow.headless){
+			logln("RUNNING HEADLESS MODE");
+		}
+
+		if (InterfaceManager.enabled){
+			interfaceManager = new InterfaceManager();
+			//InterfaceManager.importSettingsFiles();
+		}
+
+		ModuleLoader mBL = new ModuleLoader(this);
+		boolean minimalStartup = MesquiteFile.fileExists(MesquiteModule.getRootPath() + "minimalStartup");
+		if (minimalStartup)
+			logln("File called \"minimalStartup\" detected at " + MesquiteModule.getRootPath()+ ".  Mesquite will start with a minimal configuration of modules.");
+
+
+		if (verboseStartup) System.out.println("main init 26");
+		mBL.init(configFile, configurations, minimalStartup);
+		if (verboseStartup) System.out.println("main init 27");
+
+		int count = 0;
+		if (isPrerelease())
+			count++;
+		boolean first = true;
+		for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+			if (mmi.isSubstantive() && mmi.isPrerelease()) {
+				count++;
+			}
+			if (mmi.getIsPackageIntro() && !mmi.isBuiltInPackage()){
+				if (first)
+					logln("\n------------------------------------\nExtra package(s) installed:");
+				first = false;
+				String s = "\n" + mmi.getPackageName();
+				if (!StringUtil.blank(mmi.getPackageVersion()))
+					s += " version " + mmi.getPackageVersion();
+				if (mmi.getPackageBuildNumber() > 0)
+					s += " build " + mmi.getPackageBuildNumber();
+				if (!StringUtil.blank(mmi.getPackageAuthors()))
+					s += " (by " + mmi.getPackageAuthors() + ")";
+				if (!StringUtil.blank(mmi.getPackageCitation()))
+					s += " [" + mmi.getPackageCitation() + "]";
+				logln(s);
+
+			}
+		}
+		if (!first)
+			logln("\n------------------------------------");
+		if (verboseStartup) System.out.println("main init 28");
+
+
+
+		logln(" ");
+		logln(Integer.toString(mesquiteModulesInfoVector.size()) + " modules installed.");
+
+		if (count > 0){
+			logln(Integer.toString(count) + " prerelease substantive modules installed.");
+		}
+		logln(" ");
+
+		String ackn = "Mesquite makes use of BrowserLauncher by Eric Albert,  corejava.Format by Horstmann & Cornell, and iText by Lowagie & Soares  .";
+		ackn += "  Some modules make use of JAMA by The MathWorks and NIST, and JSci by Mark Hale, Jaco van Kooten and others (see Mesquite source code for details).";
+		ackn += "  The PAL library by Drummond and Strimmer is used by the GTR substitution model for DNA sequence simulations.";
+		if (MesquiteTrunk.isWindows())
+			ackn += " The Windows executable is wrapped with Launch4j by Grzegorz Kowal, copyright Grzegorz Kowal 2005-2014, distributed under a BSD license (http://opensource.org/licenses/bsd-license.html) and a MIT license (http://opensource.org/licenses/mit-license.html).";
+		logln(ackn);
+
+		logln(" ");
+		logln("====================================");
+		logln(" ");
+		makeMenu("Mesquite"); //just in case employees have no where else to put
+
+		openExternalSMS = new MesquiteSubmenuSpec(null, "Open Other", this);
+		openExternalSMS.setCommand(makeCommand("openGeneral", this));
+		openExternalSMS.setList(GeneralFileMaker.class);
+
+		addMenuItem(helpMenu, "Mesquite Documentation", makeCommand("showHomePage",  this));
+		addMenuItem(helpMenu, "Support and Advice", makeCommand("showSupport",  this));
+		addMenuItem(helpMenu, "Modules Loaded", makeCommand("showModules",  this));
+		addMenuItem(helpMenu, "Keyword Search...", makeCommand("keywordSearch",  this));
+		/*New code added Feb.05.07 oliver*/ //TODO: Delete new code comments	
+		addMenuItem(helpMenu, "Web Search...", makeCommand("webSearch",  this));
+		/*End new code added Feb.05.07 oliver*/
+		/*New code added April.02.07 oliver*/ //TODO: Delete new code comments
+		addMenuItem(helpMenu, "Mesquite FAQs", makeCommand("mesquiteFAQ", this));
+		/*End new code added April.02.07 oliver*/
+		addMenuItem(helpMenu, "Scripting Commands", makeCommand("showCommands",  this));
+		addMenuItem(helpMenu, "-", null);
+		for (int i=0; i<splashNames.size(); i++) {
+			MesquiteString ms = (MesquiteString)splashNames.elementAt(i);
+			MesquiteCommand mc = makeCommand("showPackageInfo", this);
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)splashURLInfo.elementAt(i);
+			mc.setDefaultArguments(ParseUtil.tokenize(mmi.getSplashURL()));
+			addMenuItem(helpMenu, ms.getValue(), mc);
+		}
+		addMenuItem(helpMenu, "-", null);
+		addMenuItem(helpMenu, "Active Module Tree", makeCommand("showEmployeeTree",  this));
+		addMenuItem(helpMenu, "List active modules", makeCommand("dumpEmployeeTree",  this));
+		addMenuItem(helpMenu, "List prerelease modules", makeCommand("dumpSubstantivePrerelease",  this));
+		//addMenuItem(helpMenu, "List ALL prerelease modules", makeCommand("dumpAllPrerelease",  this)); //delete this before release
+		addMenuItem(helpMenu, "List all modules", makeCommand("dumpAllModules",  this));
+		addMenuItem(helpMenu, "List new modules", makeCommand("dumpNewModules",  this));
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease()) 
+			addMenuItem(helpMenu, "List modules new for next release", makeCommand("dumpNextReleaseModules",  this));
+		addMenuItem(helpMenu, "Show Developer Statistics", makeCommand("showStatistics",  this));
+
+		MesquiteSubmenuSpec mms = addSubmenu(fileMenu, "Activate/Deactivate Packages");
+		mms.setFilterable(false);
+		addItemToSubmenu(fileMenu, mms, "Use All Installed Packages", makeCommand("setConfigAll",  this));
+		addItemToSubmenu(fileMenu, mms, "Choose Configuration...", makeCommand("setConfig",  this));
+		addItemToSubmenu(fileMenu, mms, "Delete Configuration...", makeCommand("deleteConfig",  this));
+		addItemToSubmenu(fileMenu, mms, "-", null);
+		addItemToSubmenu(fileMenu, mms, "Define Configuration...", makeCommand("defineConfig",  this));
+		MesquiteSubmenuSpec macroSM = addSubmenu(fileMenu, "Macros");
+		macroSM.setFilterable(false);
+		addItemToSubmenu(fileMenu, macroSM, "Show Macro List...", makeCommand("showMacros",  this));
+		addItemToSubmenu(fileMenu, macroSM, "Edit Macro Information...", makeCommand("editMacroInfo",  this));
+		addItemToSubmenu(fileMenu, macroSM, "Delete Auto-saved Macros...", makeCommand("deleteAutoMacros",  this));
+		addMenuItem(fileMenu, "Rename Log File...", makeCommand("renameLog",  this));
+		addMenuItem(fileMenu, "-", null);
+
+		new MesquiteColorTable(); //initialize default charstate colors
+
+		resetContainingMenuBar();
+		/* hire all inits */
+		if (verboseStartup) System.out.println("main init 29");
+		hireAllEmployees(MesquiteInit.class);
+
+
+		if (!isApplet()){
+			//setModuleWindow(null);
+			BrowseHierarchy projectHierarchyTask= (BrowseHierarchy)hireEmployee(BrowseHierarchy.class, "Hierarchy browser");
+			projectsWindow = new ProjectTreeWindow(this, projectHierarchyTask);
+			//setModuleWindow(projectsWindow);
+			//projectsWindow.setVisible(true);
+			showLogWindow();
+		}
+		helpSearchManager = new HelpSearchManager();
+		helpSearchManager.makeWindow();
+		if (InterfaceManager.enabled){
+			if (InterfaceManager.simplicityModule != null)
+				InterfaceManager.simplicityModule.init();
+		}
+		if (about !=null) {
+			about.setQuitIfGoAway(false);
+			about.hide();
+		}
+		if (verboseStartup) System.out.println("main init 30");
+
+		/* */
+		addMenuItem(MesquiteTrunk.fileMenu, "Check Now for Notices/Installs...", new MesquiteCommand("checkNotices", this));
+		if (MesquiteTrunk.phoneHome){
+			PhoneHomeThread pht = new PhoneHomeThread();
+			pht.start();
+		}
+		/**/
+
+		if (verboseStartup) System.out.println("main init 31");
+		decrementMenuResetSuppression();
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease()) 
+			logln("\nTHIS IS A PRERELEASE (BETA) VERSION: We discourage you from publishing results with this version of Mesquite, unless you check with the authors.\n");
+
+		if (logWindow!=null) {
+			if (logWindow.isConsoleMode()){
+				logln("Command-line Mode On.  Type \"help\" for some console commands.  Note: command-line mode is experimental.  Currently it is not properly protected against simultaneous calculations, e.g. doing different modifications simultaneously of the same tree or data.");
+				logWindow.showPrompt();
+			}
+			logWindow.setVisible(true);
+		}
+
+		/* */
+		cwt = new ClockWatcherThread(this);
+		cwt.start();  
+		/**/
+		if (!MesquiteTrunk.consoleListenSuppressed) {
+			ConsoleThread cot = new ConsoleThread(this, this, true);
+			cot.start();
+			consoleThread = cot;
+		}
+		storePreferences();
+
+
+		if (verboseStartup) System.out.println("main init 32 ");
+		if (debugMode) MesquiteMessage.println("startup time: " + (System.currentTimeMillis()-startingTime));
+		if (MesquiteTrunk.debugMode)
+			addMenuItem(helpMenu, "Test Error Reporting", makeCommand("testError", this));
+	} 
+
+	/*.................................................................................................................*/
+	public void refreshBrowser(Class c){
+		if (c == FileElement.class) {
+			MesquiteMessage.printStackTrace();
+		}
+		else if (c == MesquiteProject.class || c == MesquiteFile.class) {
+			if (projectsWindow!=null)
+				projectsWindow.renew();
+		}
+		else
+			super.refreshBrowser(c);
+	}
+	/*.................................................................................................................*/
+	/** add a package splash banner to Mesquite's list of currently active packages */
+	public void addSplash(MesquiteModuleInfo mmi){
+		if (InterfaceManager.enabled){
+			if (mmi.getModuleClass() == mesquite.Mesquite.class)
+				;
+			else if (mmi.getIsPackageIntro()){
+				String name = mmi.getPackageName();
+				Class c = mmi.getModuleClass();
+				String path =  StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(c.getName(), "."), ".");
+				InterfaceManager.addPackageToList(name, path, mmi.getExplanation(), mmi.getHideable(), true);
+			}
+			else if (mmi.getHideable()) {
+				String name = mmi.getName();
+				Class c = mmi.getModuleClass();
+				String path =  StringUtil.getAllButLastItem(c.getName(), ".");
+				InterfaceManager.addPackageToList(name, path, mmi.getExplanation(), mmi.getHideable(), false);
+			}
+		}
+		if (mmi.hasSplash() || mmi.getSplashURL()!=null) {
+			if (about !=null && mmi.hasSplash()) 
+				about.addSplash(mmi);
+			if (!StringUtil.blank(mmi.getSplashURL())) {
+				splashURLInfo.addElement(mmi);
+				if (StringUtil.blank(mmi.getPackageName()))
+					splashNames.addElement(new MesquiteString(mmi.getName()), false);
+				else
+					splashNames.addElement(new MesquiteString(mmi.getPackageName()), false);
+			}
+		}
+	}
+	/*.................................................................................................................EMBEDDED delete this if embedded */
+	private void setMesquiteDirectoryPath(){
+		if (mesquiteDirectory!=null){
+			mesquiteDirectoryPath = mesquiteDirectory.getAbsolutePath();
+			if (isWindows() && mesquiteDirectoryPath.lastIndexOf(MesquiteFile.fileSeparator + ".")== mesquiteDirectoryPath.length()-2)
+				mesquiteDirectoryPath = mesquiteDirectoryPath.substring(0, mesquiteDirectoryPath.length()-1);
+			else if (mesquiteDirectoryPath.lastIndexOf(MesquiteFile.fileSeparator)!= mesquiteDirectoryPath.length()-1)
+				mesquiteDirectoryPath+= MesquiteFile.fileSeparator;
+		}
+	}
+	/*.................................................................................................................EMBEDDED delete this if embedded *
+	private void findMesquiteDirectory(){
+		String sep = "" + MesquiteFile.fileSeparator;
+		if (mesquiteDirectory!=null) {
+			String manualString = mesquiteDirectory + sep + "docs/mesquite" + sep + "manual.html";
+			File manualM = new File(manualString);
+			if (manualM.exists()) {
+				storedManualString = manualString;
+			}
+		}
+		else {
+			String manualString = mesquiteDirectory  + sep + "docs/mesquite" + sep + "manual.html";
+			File manual = new File(manualString);
+
+			storedManualString = manualString; 
+		}
+
+		setMesquiteDirectoryPath();
+	}
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			preferencesSet = true; //done to see that prefs file found; if not ask for registration
+			//showLogWindow=prefs[0].charAt(0) == 'L';
+			if (prefs.length<2)
+				return;
+			//storedManualString = prefs[1];
+			if (prefs.length<3)
+				return;
+
+			int iq = MesquiteInteger.fromString(prefs[2]);
+			if (MesquiteInteger.isCombinable(iq))
+				MesquiteModule.textEdgeCompensationHeight = iq;
+			MesquiteModule.textEdgeRemembered = true;
+			if (prefs.length<4)
+				return;			
+			iq = MesquiteInteger.fromString(prefs[3]);
+			if (MesquiteInteger.isCombinable(iq))
+				MesquiteModule.textEdgeCompensationWidth = iq;
+
+			if (prefs.length<6)
+				return;
+			/* EMBEDDED disable if embedded */
+			setMesquiteDirectoryPath();
+			/**/
+			if (prefs.length<7)
+				return;
+			iq = MesquiteInteger.fromString(prefs[6]);
+			if (prefs.length<8)
+				return;
+			numUses = MesquiteInteger.fromString(prefs[7]);
+			if (!MesquiteInteger.isCombinable(numUses))
+				numUses = 0;
+			else
+				numUses++;
+			if (prefs.length<9)
+				return;
+			browserString = prefs[8];
+			if (prefs.length<10)
+				return;
+			if (prefs[9].length()>0)
+				defaultHideMesquiteWindow=prefs[9].charAt(0) == 'H';
+			if (prefs.length<11)
+				return;
+			if (prefs[10].length()>0)
+				numDirectories =MesquiteInteger.fromString(prefs[10], false);
+			if (prefs.length<12)
+				return;
+			if (prefs[11].length()>0)
+				configFile = prefs[11];
+			if (prefs.length<13)
+				return;
+			if (prefs[12]!=null)
+				consoleMode = "console".equals(prefs[12]);
+			if (prefs.length<14)
+				return;
+			if (prefs[13] !=null) {
+				int numLogs = MesquiteInteger.fromString(prefs[13]);
+				if (MesquiteInteger.isCombinable(numLogs))
+					MesquiteTrunk.numPrevLogs = numLogs;
+
+			}
+			if (prefs.length<15) {
+				lastVersionRun = "1.04"; //104 or before
+				return;
+			}
+			else if (prefs[14] != null) {
+				lastVersionRun = prefs[14];
+			}
+			if (prefs.length<16)
+				return;
+			if (prefs.length<17)
+				return;
+			if (prefs[16] != null) {
+				int search = MesquiteInteger.fromString(prefs[16]);
+				if (MesquiteInteger.isCombinable(search))
+					HelpSearchStrip.searchMODE = search;
+			}
+			if (prefs.length<18)
+				return;
+			if (prefs[17] != null) {
+				if (prefs[17].equalsIgnoreCase("true"))
+					MesquiteCommand.logEverything = true;
+			}
+			if (prefs.length<19)
+				return;
+			if (prefs[18] != null) {
+				MesquiteInteger pos = new MesquiteInteger(0);
+				int lastVersionUsedInt = MesquiteInteger.fromString(prefs[18], pos);
+				int lastVersionNoticed = MesquiteInteger.fromString(prefs[18], pos);
+				int lastNotice = MesquiteInteger.fromString(prefs[18], pos);
+				int lastNoticeForMyVersion = MesquiteInteger.fromString(prefs[18], pos);
+				if (MesquiteInteger.isCombinable(lastVersionUsedInt))
+					this.lastVersionUsedInt = lastVersionUsedInt;
+				if (MesquiteInteger.isCombinable(lastVersionNoticed))
+					this.lastVersionNoticed = lastVersionNoticed;
+				if (MesquiteInteger.isCombinable(lastNotice))
+					this.lastNotice = lastNotice;
+				if (MesquiteInteger.isCombinable(lastNoticeForMyVersion))
+					this.lastNoticeForMyVersion = lastNoticeForMyVersion;
+				if (lastVersionUsedInt != getVersionInt())
+					this.lastNoticeForMyVersion = 0;
+			}
+		}
+	}
+	public void processSingleXMLPreference (String tag, String content) {
+		preferencesSet = true; //done to see that prefs file found; if not ask for registration
+		if ("storedManualString".equalsIgnoreCase(tag)){
+			//	storedManualString = (content);  DEFUNCT with v. 3
+		}
+		else if ("textEdgeCompensationHeight".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq)) {
+				MesquiteModule.textEdgeCompensationHeight = iq;
+				MesquiteModule.textEdgeRemembered = true;
+			}
+		}
+		else if ("textEdgeCompensationWidth".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq)){
+				MesquiteModule.textEdgeCompensationWidth = iq;
+				MesquiteModule.textEdgeRemembered = true;
+				if (MesquiteModule.textEdgeCompensationWidth>20)  //put max
+					MesquiteModule.textEdgeCompensationWidth = 20;
+			}
+		}
+		else if ("numUses".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				numUses = iq+1;
+			else
+				numUses = 0;
+		}
+		else if ("browserString".equalsIgnoreCase(tag)){
+			browserString = (content);
+		}
+		else if ("defaultHideMesquiteWindow".equalsIgnoreCase(tag)){
+			defaultHideMesquiteWindow=MesquiteBoolean.fromTrueFalseString(content);
+		}
+		else if ("numDirectories".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				numDirectories = iq;
+		}
+		else if ("configFile".equalsIgnoreCase(tag)){
+			configFile = (content);
+		}
+		else if ("consoleMode".equalsIgnoreCase(tag)){
+			consoleMode = MesquiteBoolean.fromTrueFalseString(content);
+		}
+		else if ("numPrevLogs".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				numPrevLogs = iq;
+		}
+		else if ("maxNumMatrixUndoTaxa".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				maxNumMatrixUndoTaxa = iq;
+		}
+		else if ("maxNumMatrixUndoChars".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				maxNumMatrixUndoChars = iq;
+		}
+		else if ("lastVersionRun".equalsIgnoreCase(tag)){
+			lastVersionRun = (content);
+		}
+		else if ("listUrgeGiven".equalsIgnoreCase(tag)){
+		}
+		else if ("searchMODE".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				HelpSearchStrip.searchMODE = iq;
+		}
+		else if ("logEverything".equalsIgnoreCase(tag)){
+			MesquiteCommand.logEverything = MesquiteBoolean.fromTrueFalseString(content);
+		}
+		else if ("lastVersionUsedInt".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				lastVersionUsedInt = iq;
+		}
+		else if ("lastVersionNoticed".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				lastVersionNoticed = iq;
+		}
+		else if ("lastNotice".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				lastNotice = iq;
+		}
+		else if ("lastNoticeForMyVersion".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				lastNoticeForMyVersion = iq;
+
+			if (lastVersionUsedInt != getVersionInt())
+				lastNoticeForMyVersion = 0;		
+		}
+		else if ("mesquiteHeadlessPath".equalsIgnoreCase(tag)){ //hackathon
+			previousMesquiteHeadlessPath = (content);
+		}
+		else if ("mesquitePath".equalsIgnoreCase(tag)){
+			previousMesquitePath = (content);
+		}
+		else if ("projPanelWidth".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq))
+				MesquiteFrame.defaultResourcesWidth = iq;
+		}
+		else if ("colorTheme".equalsIgnoreCase(tag)){
+			int iq = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(iq)){
+				ColorTheme.THEME = iq;
+				ColorTheme.THEME_FOR_NEXT_STARTUP = iq;
+			}
+		}
+		/* EMBEDDED disable if embedded */
+		setMesquiteDirectoryPath();
+		/**/
+
+	}
+	String previousMesquiteHeadlessPath = "";//hackathon
+	String previousMesquitePath = "";
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		//	StringUtil.appendXMLTag(buffer, 2, "storedManualString", storedManualString);  
+		StringUtil.appendXMLTag(buffer, 2, "textEdgeCompensationHeight", MesquiteModule.textEdgeCompensationHeight);  
+		StringUtil.appendXMLTag(buffer, 2, "textEdgeCompensationWidth", MesquiteModule.textEdgeCompensationWidth);  
+		StringUtil.appendXMLTag(buffer, 2, "numUses", numUses);  
+		StringUtil.appendXMLTag(buffer, 2, "browserString", browserString);  
+		StringUtil.appendXMLTag(buffer, 2, "colorTheme", ColorTheme.THEME_FOR_NEXT_STARTUP);  
+		StringUtil.appendXMLTag(buffer, 2, "defaultHideMesquiteWindow", defaultHideMesquiteWindow);  
+		StringUtil.appendXMLTag(buffer, 2, "numDirectories", numDirectories);  
+		StringUtil.appendXMLTag(buffer, 2, "projPanelWidth", MesquiteFrame.defaultResourcesWidth);  
+		StringUtil.appendXMLTag(buffer, 2, "configFile", configFile);  
+		StringUtil.appendXMLTag(buffer, 2, "consoleMode", consoleMode);  
+		StringUtil.appendXMLTag(buffer, 2, "numPrevLogs", numPrevLogs);  
+		StringUtil.appendXMLTag(buffer, 2, "maxNumMatrixUndoTaxa", maxNumMatrixUndoTaxa);  
+		StringUtil.appendXMLTag(buffer, 2, "maxNumMatrixUndoChars", maxNumMatrixUndoChars);  
+
+		StringUtil.appendXMLTag(buffer, 2, "lastVersionRun", lastVersionRun);  
+		//	StringUtil.appendXMLTag(buffer, 2, "listUrgeGiven", listUrgeGiven);  
+		StringUtil.appendXMLTag(buffer, 2, "searchMODE", HelpSearchStrip.searchMODE);  
+		StringUtil.appendXMLTag(buffer, 2, "logEverything", MesquiteCommand.logEverything);  
+		StringUtil.appendXMLTag(buffer, 2, "lastVersionUsedInt", lastVersionUsedInt);  
+		StringUtil.appendXMLTag(buffer, 2, "lastVersionNoticed", lastVersionNoticed);  
+		StringUtil.appendXMLTag(buffer, 2, "lastNotice", lastNotice);  
+		StringUtil.appendXMLTag(buffer, 2, "lastNoticeForMyVersion", lastNoticeForMyVersion);  
+
+		if (MesquiteWindow.headless) { //hackathon
+			StringUtil.appendXMLTag(buffer, 2, "mesquiteHeadlessPath", stripPath(mesquiteDirectoryPath));  
+			StringUtil.appendXMLTag(buffer, 2, "mesquitePath", stripPath(previousMesquitePath));  
+		}
+		else {
+			StringUtil.appendXMLTag(buffer, 2, "mesquiteHeadlessPath", stripPath(previousMesquiteHeadlessPath));  
+			StringUtil.appendXMLTag(buffer, 2, "mesquitePath", stripPath(mesquiteDirectoryPath));  
+		}
+
+		return buffer.toString();
+	}
+	String stripPath(String path){
+		if (path.lastIndexOf("../") == path.length()-3 || path.lastIndexOf("..") == path.length()-2){
+			path = StringUtil.getAllButLastItem(path, "/..");
+			path =  StringUtil.getAllButLastItem(path, "/");
+		}
+		return path;
+	}
+	/*.................................................................................................................*
+	public String[] preparePreferencesForFile () {
+		String[] prefs;
+		prefs = new String[19];
+
+		if (logWindow != null && logWindow.isVisible())
+			prefs[0] = "L";
+		else
+			prefs[0]= "N";
+		prefs[0] += "A02Y8O*=#";
+		prefs[1]= "" + storedManualString;
+		prefs[2]= Integer.toString(MesquiteModule.textEdgeCompensationHeight);
+		prefs[3]= Integer.toString(MesquiteModule.textEdgeCompensationWidth);
+		prefs[4]= "mq";
+		prefs[5]= "0";
+		prefs[6] = "1"; 
+		prefs[7]= Integer.toString(numUses);
+		if (browserString != null)
+			prefs[8] = browserString;
+		else
+			prefs[8] = "";
+		if (showAbout)
+			prefs[9] = "H";
+		else
+			prefs[9] = "S";
+		prefs[10] = Integer.toString(numDirectories);
+		prefs[11] = configFile;
+		if (logWindow != null && logWindow.isConsoleMode())
+			prefs[12] = "console";
+		else
+			prefs[12] = "noconsole";
+		prefs[13] = Integer.toString(MesquiteTrunk.numPrevLogs);
+		prefs[14]= getMesquiteVersion();
+		if (listUrgeGiven)
+			prefs[15] = "U";
+		else
+			prefs[15] = "N";
+		prefs[16] = Integer.toString(HelpSearchStrip.searchMODE);
+		prefs[17] = Boolean.toString(MesquiteCommand.logEverything);
+		prefs[18] = Integer.toString(getVersionInt()) + " " + Integer.toString(lastVersionNoticed) + " " + Integer.toString(lastNotice)  + " " + Integer.toString(lastNoticeForMyVersion);
+		return prefs;
+	}
+	/*.................................................................................................................*/
+	void setupColors(){
+		/*for (int i=0; i<ColorDistribution.numColorSchemes; i++){
+			String[] colorStrings = MesquiteFile.getFileContentsAsStrings(MesquiteModule.getRootPath() + "images/colors/" + i);
+			if (colorStrings !=null && colorStrings.length>=5){
+				stringPos.setValue(0);
+				/*The old system brought in full color schemes from the files.  As of v. 2. 1, the color scheme is muted, more gray,
+		 * and only two colors are brought in, projectLight and projectDark.  The old color scheme setting is still here, though nullified by
+		 * subsequent calls *
+				float r = (float)MesquiteDouble.fromString(colorStrings[0], stringPos);
+				float g = (float)MesquiteDouble.fromString(colorStrings[0], stringPos);
+				float b = (float)MesquiteDouble.fromString(colorStrings[0], stringPos);
+				//ColorDistribution.pale[i] = new Color(r, g, b);
+				//ColorDistribution.pale[i] = ColorDistribution.veryLightGray;//ggray
+				stringPos.setValue(0);
+				r = (float)MesquiteDouble.fromString(colorStrings[1], stringPos);
+				g = (float)MesquiteDouble.fromString(colorStrings[1], stringPos);
+				b = (float)MesquiteDouble.fromString(colorStrings[1], stringPos);
+				//ColorDistribution.projectLight[i] = new Color(r, g, b);
+				ColorDistribution.projectLight[i] = new Color(r, g, b);
+				//ColorDistribution.projectLight[i] = ColorDistribution.veryLightGray;//ggray
+				stringPos.setValue(0);
+				r = (float)MesquiteDouble.fromString(colorStrings[2], stringPos);
+				g = (float)MesquiteDouble.fromString(colorStrings[2], stringPos);
+				b = (float)MesquiteDouble.fromString(colorStrings[2], stringPos);
+				//ColorDistribution.medium[i] = new Color(r, g, b);
+				//ColorDistribution.medium[i] = Color.lightGray;//ggray
+				stringPos.setValue(0);
+				r = (float)MesquiteDouble.fromString(colorStrings[3], stringPos);
+				g = (float)MesquiteDouble.fromString(colorStrings[3], stringPos);
+				b = (float)MesquiteDouble.fromString(colorStrings[3], stringPos);
+				//ColorDistribution.dark[i] = new Color(r, g, b);
+				ColorDistribution.projectDark[i] = new Color(r, g, b);
+				//ColorDistribution.dark[i] = Color.gray;//ggray
+				stringPos.setValue(0);
+				r = (float)MesquiteDouble.fromString(colorStrings[4], stringPos);
+				g = (float)MesquiteDouble.fromString(colorStrings[4], stringPos);
+				b = (float)MesquiteDouble.fromString(colorStrings[4], stringPos);
+				//ColorDistribution.project[i] = new Color(r, g, b);
+				//ColorDistribution.project[i] = Color.lightGray;//ggray
+			}
+			else {
+			/*	ColorDistribution.pale[i] = ColorDistribution.veryLightGray;
+				ColorDistribution.projectLight[i] = ColorDistribution.veryLightGray;
+				ColorDistribution.medium[i] = Color.lightGray;
+				ColorDistribution.dark[i] = Color.gray;
+				ColorDistribution.project[i] = Color.lightGray;*
+				ColorDistribution.projectLight[i] = ColorDistribution.paleGoldenRod;
+				ColorDistribution.projectDark[i] = ColorDistribution.sienna;
+
+			}
+			InfoBar.baseImage[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/infoBarBase.gif");  
+			//InfoBar.baseImage[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "infoBarBase.gif");  
+			InfoBar.graphicsTab[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "graphicsTab.gif");  
+			InfoBar.textTab[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "textTab.gif");  
+			InfoBar.parametersTab[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "parametersTab.gif");  
+			InfoBar.modulesTab[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "modulesTab.gif");  
+			InfoBar.citationsTab[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/colors/" + i + "citationsTab.gif");  
+			MesquiteButton.offImage[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/colors/blank-off.gif");  //gray
+			//MesquiteButton.offImage[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/colors/" + i + "blank-off.gif");  
+			MesquiteButton.onImage[i]=  MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/colors/" + i + "blank-on.gif");  
+		}
+		 */
+		InfoBar.triangleImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/infoBarTriangle.gif");  
+		InfoBar.triangleImageDown=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/triangleDown.gif");  
+		InfoBar.releaseImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/release.gif");  
+		InfoBar.prereleaseImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/prerelease.gif");  
+		ExplanationArea.plusImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/explanationPlus.gif");  
+		ExplanationArea.minusImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/explanationMinus.gif");  
+		ExplanationArea.minusOffImage=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/explanationMinusOff.gif");  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Mesquite";
+	}
+	/*.................................................................................................................*/
+	public String getDutyName() {
+		return "Root module for Mesquite system";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "This is the central module for the Mesquite system. " +
+				"In it is the main method that starts up the Mesquite application.  This module" +
+				"loads information for all of the other modules, and hires FileCoordinator " +
+				"modules as needed to deal with open files.  Thus, in the tree of employees" +
+				"that active modules make, this module is at its root.";
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String getAuthors() {
+		return "Wayne P. Maddison and David R. Maddison";
+	}
+
+
+
+	/*.................................................................................................................*/
+	/*New code added Feb.05.07 oliver*/ //TODO: Delete new code comments	
+	/*.................................................................................................................*/
+	private void searchWeb(String queryTerm, MesquiteBoolean addMesquiteToSearch, MesquiteBoolean restrictSearchToManual){
+		String textToGoogle = "";
+		queryTerm = queryTerm.replaceAll("\'", "\"");
+		queryTerm = queryTerm.replaceAll("\\\"", "%22");
+		String[] result = queryTerm.split("\\s");
+		for(int x = 0; x < result.length; x++){
+			if (x == 0)
+				textToGoogle = result[x];
+			else
+				textToGoogle += "+" + result[x];
+		}
+		if (addMesquiteToSearch.getValue())
+			textToGoogle += "+" + "Mesquite";
+		if (restrictSearchToManual.getValue())
+			textToGoogle += "&as_sitesearch=http%3A%2F%2Fmesquiteproject.wikispaces.com%2F";
+		showWebPage("http://www.google.com/search?q=" + textToGoogle, false);
+	}
+	/*End new code added Feb.05.07 oliver*/
+	/*New code added April.02.07 oliver*/ //TODO: delete new code comments
+	/*.................................................................................................................*/
+	private void openMesquiteFAQ(){
+		String manualPath = mesquiteWebSite + "/FAQ" ; 
+		showWebPage(manualPath, false);
+	}
+	/*End new code added April.02.07 oliver*/
+
+	public void employeeQuit(MesquiteModule mb){
+		helpSearchManager.employeeQuit(mb);
+		super.employeeQuit(mb);
+	}
+	/*.................................................................................................................*/
+
+	public void exit(boolean emergency, int status){
+		if (startedAsLibrary){
+			if (!emergency){
+				logln("Mesquite is being used by another program.  You should avoid asking Mesquite to quit, and instead let the other program ask Mesquite to quit");
+				return;
+			}
+			mesquiteExiting = true;
+			doomed = true;
+			MesquiteFrame f = logWindow.getParentFrame();
+			f.setVisible(false);
+			iQuit();
+			while (windowVector.size()>0) {
+				Enumeration e = windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					mw.setVisible(false);
+					MesquiteFrame ff = mw.getParentFrame();
+					if (ff != null){
+						ff.setVisible(false);
+						ff.dispose();
+					}
+					mw.dispose();
+				}
+			}
+			MesquiteFile.closeLog();		
+		}
+		else
+			System.exit(status);
+	}
+	/*.................................................................................................................*/
+	public void start() {
+		incrementMenuResetSuppression();
+		ready = true;
+		if (fileHandler !=null && fileHandler.isWaiting())
+			fileHandler.openFilesNow();
+		/*
+		else if (isApplet()) { //EMBEDDED
+			String urlString = getParameter("URL");
+			if (urlString!=null) {
+				openURLString(urlString);
+			}
+		}
+		 */
+		decrementMenuResetSuppression();
+	}
+
+	/*.................................................................................................................*/
+	public MesquiteProject openGeneral(String readerString){
+		return newProject(readerString, 3);
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject openURLString(String urlString){
+		return newProject(urlString, 2);
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject openFile(String pathname, String originalArguments){ //hackathon
+		return newProject(pathname, 1, false, originalArguments);
+	}
+	/*.................................................................................................................*/
+	/* give alternative method which takes full file and passes it to FileCoordinator,
+	which then uses alternative methods in MesquiteProject reader that parses this string
+	instead of input stream*/
+	public MesquiteProject openFile(String pathname){
+		return newProject(pathname, 1);
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project, in process making taxa block.*/
+	public MesquiteProject newFileWithTaxa(String arguments){
+		return newProject(arguments, 0);
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project.*/
+	public MesquiteProject newFile(String arguments){
+		return newProject(arguments, -1);
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project.*/
+	public MesquiteProject newProject(String arguments, int code){
+		return newProject(arguments, code, false);
+	}
+	/* makes and returns a new project.*/ //hackathon
+	public MesquiteProject newProject(String arguments, int code, boolean actAsScriptingRegardless){
+		return newProject(arguments, code, actAsScriptingRegardless, null);
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project.*///hackathon
+	public MesquiteProject newProject(String arguments, int code, boolean actAsScriptingRegardless, String originalArguments){
+		if (MesquiteThread.isScripting() || actAsScriptingRegardless) {
+			ObjectContainer projCont = new ObjectContainer();
+			ProjectRead pr = new ProjectRead(arguments,  code, mesquiteTrunk, projCont);
+			if (originalArguments != null)
+				pr.setOriginalArguments(originalArguments);
+			pr.run();
+			MesquiteProject p = (MesquiteProject)projCont.getObject();
+			projCont.setObject(null); //This is done because Threads not being finalized, and need to remove references to projects
+			return p;
+		}
+		else {
+			ProjectRead pr = new ProjectRead(arguments,  code, mesquiteTrunk, null);
+			ProjectReadThread pt = new ProjectReadThread(pr);
+			if (originalArguments != null)
+				pr.setOriginalArguments(originalArguments);
+			pt.settempID(arguments);
+			pr.setThread(pt);
+			pt.start();
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project.*///hackathon
+	public MesquiteProject newProject(InputStream stream, String arguments, boolean actAsScriptingRegardless, String originalArguments){
+		if (MesquiteThread.isScripting() || actAsScriptingRegardless) {
+			ObjectContainer projCont = new ObjectContainer();
+			ProjectRead pr = new ProjectRead(arguments,  4, mesquiteTrunk, projCont);
+			pr.stream = stream;
+			if (originalArguments != null)
+				pr.setOriginalArguments(originalArguments);
+			pr.run();
+			MesquiteProject p = (MesquiteProject)projCont.getObject();
+			projCont.setObject(null); //This is done because Threads not being finalized, and need to remove references to projects
+			return p;
+		}
+		else {
+			ProjectRead pr = new ProjectRead(arguments,  4, mesquiteTrunk, null);
+			pr.stream = stream;
+			ProjectReadThread pt = new ProjectReadThread(pr);
+			if (originalArguments != null)
+				pr.setOriginalArguments(originalArguments);
+			pt.settempID(arguments);
+			pr.setThread(pt);
+			pt.start();
+			return null;
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+	boolean closeAllProjects(){
+		Projects projs = getProjectList();
+		MesquiteProject[] ps = new MesquiteProject[projs.getNumProjects()];
+		for (int i= 0; i<ps.length; i++) {
+			ps[i]= projs.getProject(i);
+		}
+		for (int i= 0; i<ps.length; i++) {
+			MesquiteProject p = ps[i];
+			if (p!=null) {
+				FileCoordinator fc = p.getCoordinatorModule();
+				if (fc!=null) {
+					if (!fc.closeFile(p.getHomeFile())){
+						logln("Sorry, unable to close " + p.getName());
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+	void saveAllProjects(){
+		Projects projs = getProjectList();
+		MesquiteProject[] ps = new MesquiteProject[projs.getNumProjects()];
+		for (int i= 0; i<ps.length; i++) {
+			ps[i]= projs.getProject(i);
+		}
+		for (int i= 0; i<ps.length; i++) {
+			MesquiteProject p = ps[i];
+			if (p!=null) {
+				FileCoordinator fc = p.getCoordinatorModule();
+				if (fc!=null) 
+					fc.saveAllFiles();
+			}
+		}
+	}
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (command !=null && command.getOwner() == this && ("quit".equalsIgnoreCase(command.getName()) || "exit".equalsIgnoreCase(command.getName())))
+			return;
+		super.fileDirtiedByCommand(command);
+	}
+	/*.................................................................................................................*/
+	private ListableVector getMacroRecords(boolean autoOnly){
+		ListableVector macros = new ListableVector();
+		for (int i = 0; i<mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+			if (mmi.getMacros()!=null && mmi.getMacros().size()>0){
+				Vector mForM = mmi.getMacros();
+				for (int j = 0; j<mForM.size(); j++){
+					MesquiteMacro mmr = (MesquiteMacro)mForM.elementAt(j);
+					if (!autoOnly || mmr.isAutoSave())
+						macros.addElement(mmr, false);
+				}
+			}
+		}
+		if (macros.size() == 0)
+			return null;
+		return macros;
+	}
+	public void reportMemory(){
+		if (!checkMemory) {
+			logln("Memory status cannot be reported because checkMemory is not set");
+			return;
+		}
+		Vector cre, fin, ct, ctd;
+		cre = FileElement.classesCreated;
+		fin = FileElement.classesFinalized;
+		ct = FileElement.countsOfClasses;
+		ctd = FileElement.countsOfClassesDisposed;
+		if (cre.size()>fin.size()){
+			logln("File element classes created but not finalized    " );
+			for (int i=0; i<cre.size(); i++){
+				if (fin.indexOf(cre.elementAt(i))<0)
+					logln("    " + cre.elementAt(i) + "  count: " + ct.elementAt(i));
+			}
+		}
+		logln("File element classes with fewer disposals than creations    " );
+		for (int i=0; i<ct.size() && i<ctd.size(); i++){
+			MesquiteInteger mi = (MesquiteInteger)ct.elementAt(i);
+			MesquiteInteger mid = (MesquiteInteger)ctd.elementAt(i);
+			if (mi.getValue()!=mid.getValue())
+				logln("    " + cre.elementAt(i) + "  created: " + mi + " disposed: " + mid);
+		}
+
+		logln("NexusBlock.totalFinalized " +  NexusBlock.totalFinalized + " NexusBlock.totalDisposed " + NexusBlock.totalDisposed + " NexusBlock.totalCreated " +  NexusBlock.totalCreated);
+		cre = NexusBlock.classesCreated;
+		fin = NexusBlock.classesFinalized;
+		ct = NexusBlock.countsOfClasses;
+		ctd = NexusBlock.countsOfClassesFinalized;
+		logln("NexusBlock class instantiations    " );
+		for (int i=0; i<cre.size(); i++){
+			logln("    " + cre.elementAt(i) + "  count: " + ct.elementAt(i) + "  ever finalized? " + (fin.indexOf(cre.elementAt(i))>=0) + "  num finalizations " + ctd.elementAt(i));
+		}
+
+		logln("ListableVector.totalFinalized " +  ListableVector.totalFinalized + " ListableVector.totalDisposed " + ListableVector.totalDisposed + " ListableVector.totalCreated " +  ListableVector.totalCreated);
+		logln("MesquiteCommand.totalFinalized " +  MesquiteCommand.totalFinalized + " MesquiteCommand.totalDisposed " + MesquiteCommand.totalDisposed + " MesquiteCommand.totalCreated " +  MesquiteCommand.totalCreated);
+
+		cre = MesquiteCommand.classesLinked;
+		fin = MesquiteCommand.classesUnlinked;
+		ct = MesquiteCommand.countsOfClasses;
+		if (cre.size()>fin.size()){
+			logln("MesquiteCommand objects linked but not unlinked    " );
+			for (int i=0; i<cre.size(); i++){
+				if (fin.indexOf(cre.elementAt(i))<0)
+					logln("    " + cre.elementAt(i) + "  count: " + ct.elementAt(i));
+			}
+		}
+
+		logln(" MesquiteMenuItem.totalFinalized " +  MesquiteMenuItem.totalFinalized + " MesquiteMenuItem.totalDisposed " + MesquiteMenuItem.totalDisposed + " MesquiteMenuItem.totalCreated " +  MesquiteMenuItem.totalCreated);
+		logln(" MesquiteMenuItemSpec.totalFinalized " +  MesquiteMenuItemSpec.totalFinalized + " MesquiteMenuItemSpec.totalDisposed " + MesquiteMenuItemSpec.totalDisposed + " MesquiteMenuItemSpec.totalCreated " +  MesquiteMenuItemSpec.totalCreated);
+		logln(" MesquiteModule.totalFinalized " +  MesquiteModule.totalFinalized + " EmployerEmployee.totalDisposed " +  EmployerEmployee.totalDisposed + " EmployerEmployee.totalCreated " +  EmployerEmployee.totalCreated);
+		logln("Projects.projectsAdded " + Projects.projectsAdded + " Projects.projectsRemoved " +  Projects.projectsRemoved);
+		logln("FileCoordinator.totalFinalized " + FileCoordinator.totalFinalized + " FileCoordinator.totalCreated " +  FileCoordinator.totalCreated);
+		logln("MesquiteTree.totalFinalized " + MesquiteTree.totalFinalized  + " MesquiteTree.totalDisposed " + MesquiteTree.totalDisposed + " MesquiteTree.totalCreated " +  MesquiteTree.totalCreated);
+		logln("Taxon.totalFinalized " + Taxon.totalFinalized  + " Taxon.totalCreated " +  Taxon.totalCreated);
+		logln("Associable.totalFinalizedA " + Associable.totalFinalizedA  + " Associable.totalDisposedA " +  Associable.totalDisposedA + " Associable.totalCreatedA " +  Associable.totalCreatedA);
+		logln("CharacterData.totalDisposed " + CharacterData.totalDisposed + " CharacterData.totalCreated " +  CharacterData.totalCreated);
+		logln("TreeVector.totalDisposed " + TreeVector.totalDisposed + " TreeVector.totalCreated " +  TreeVector.totalCreated);
+		logln("Listened.listenersRemaining " + Listened.listenersRemaining);
+		logln("Listened.listenersReport\n" + Listened.reportListeners());
+		logln("Threads");
+		for (int i=0; i<MesquiteThread.threads.size(); i++){
+			logln("    " + MesquiteThread.threads.elementAt(i));
+		}
+	}
+	/*.................................................................................................................*/
+	public void showHTMLSnippet(String s){
+		if (helpSearchManager != null)
+			helpSearchManager.showHTML(s);
+	}
+	/*.................................................................................................................*/
+	public void searchKeyword(String s, boolean useBrowser){
+		if (helpSearchManager != null)
+			helpSearchManager.searchKeyword(s, useBrowser);
+
+	}
+	public void searchData(String s, MesquiteWindow window){
+		if (helpSearchManager != null)
+			helpSearchManager.searchData(s, window);
+	}
+
+	public String getNumModuleStarts() {
+		StringBuffer sb=new StringBuffer();
+		for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+			int starts = mmi.getNumStarts();
+			if (starts>0)
+				sb.append(mmi.getClassName() + "\t" + starts+StringUtil.lineEnding());
+		}
+		return sb.toString();
+	}
+
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	String noticeLocation = "http://"; //before release, change URL to "http://"
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the packages of modules loaded at startup, using a configuration file", null, commandName, "setConfig")) {
+			//need Module Activation menu item with submenu items: Use All Installed Modules; Choose Module set
+			//use MesquiteTrunks.configs, a vector of configurations found (each stores name, explanation)
+			Listable[] list = new Listable[configurations.size()];
+			for (int i=0; i<configurations.size(); i++){
+				Object o = configurations.elementAt(i);
+				ConfigFileRecord cfr = (ConfigFileRecord)o;
+				list[i]= cfr;
+			}
+			String c = configuration;
+			if (c == null)
+				c = "All Installed Modules";
+			Listable chosen = ListDialog.queryList(containerOfModule(), "Choose configuration", "Choose the configuration file that indicates what packages of modules are to be loaded at startup.  Current configuration is \"" + c + "\".", MesquiteString.helpString, list, 0);
+			if (chosen != null){
+				configFile = ((ConfigFileRecord)chosen).getPath();
+				storePreferences();
+				discreetAlert("You will need to restart Mesquite to load the selected configuration");
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Defines a set of  packages to be loaded at startup, using a configuration file", null, commandName, "defineConfig")) {
+			boolean[] selected = new boolean[packages.size()];
+			for (int i= 0; i<packages.size(); i++){
+				MesquitePackageRecord mpr = (MesquitePackageRecord)packages.elementAt(i);
+				selected[i] =mpr.getLoaded();
+
+			}
+			String c = getConfiguration();
+			if (c == null)
+				c = "All Installed Modules";
+			Listable[] list = ChecklistDialog.queryListMultiple(containerOfModule(), "Define Configuration", "Shown are packages of modules available in this installation of Mesquite.  The currently loaded packages are shown in boldface.  Select and deselect to define a new configuration of packages to be loaded.  Current configuration is \"" + c + "\".", packages, selected);
+			if (list!=null && list.length>0) {
+				String[] contents = new String[list.length+1];
+
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteString name = new MesquiteString("User-defined module configuration");
+				MesquiteString explanation = new MesquiteString("");
+				MesquiteString.queryTwoStrings(containerOfModule(), "Specify saved configuration", "Name of configuration of module packages", "Explanation of configuration of module packages",  answer, name, explanation,true);
+				if (!answer.getValue())
+					return null;
+				contents[0] = ParseUtil.tokenize(name.getValue()) + "   " +  ParseUtil.tokenize(explanation.getValue());
+				for (int i=0; i<list.length; i++) {
+					MesquitePackageRecord mpr = (MesquitePackageRecord)list[i];
+					contents[i+1] = mpr.getPackageName();
+				}
+				String base = MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator +"configs";
+				if (!MesquiteFile.fileExists(base)) {
+					File f = new File(base);
+					f.mkdir();
+				}
+				String candidate = base + "/test1.config";
+				int count = 2;
+				while (MesquiteFile.fileExists(candidate)){
+					candidate = base + "/test" + (count++) + ".config";
+				}
+				MesquiteFile.putFileContents(candidate, contents, true); 
+				configFile = candidate;
+				storePreferences();
+				discreetAlert("You will need to restart Mesquite to load the defined configuration");
+				ConfigFileRecord cfr = new ConfigFileRecord(true);
+				cfr.cStored[0] = candidate;
+				cfr.cStored[1] = name.getValue();
+				cfr.cStored[2]= explanation.getValue();
+				configurations.addElement(cfr, false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Brings up a dialog box by which user-defined configuration files can be deleted", null, commandName, "deleteConfig")) {
+
+			//first get list of user-defined configs; must filter configurations vector to include only user-defined.  Then delete corresponding files!
+			ListableVector ud = new ListableVector();
+			for (int i= 0; i<configurations.size(); i++){
+				ConfigFileRecord config = (ConfigFileRecord)configurations.elementAt(i);
+				if (config.isUserDefined())
+					ud.addElement(config, false);
+			}
+			String c = configuration;
+			if (c == null)
+				c = "All Installed Modules";
+			Listable[] list = ListDialog.queryListMultiple(containerOfModule(), "Delete Configuration", "Select the configurations to be deleted and hit \"OK\" to delete them.  Current configuration is \"" + c + "\".", MesquiteString.helpString, "Delete", false, ud, null);
+			if (list!=null && list.length>0) {
+				if (AlertDialog.query(containerOfModule(), "Delete?", "Are you sure you want to delete the configuration(s)?")){
+					for (int i=0; i<list.length; i++) {
+						ConfigFileRecord config = (ConfigFileRecord)list[i];
+						File f = new File(config.getPath());
+						f.delete();
+						configurations.removeElement(config, false);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Brings up a dialog box to change name and explanation of user-saved macros", null, commandName, "editMacroInfo")) {
+			MesquiteMacro macro = MesquiteMacro.findMacro(parser.getFirstToken(arguments));
+			if (macro==null)
+				return null;
+			String[] oldFile = MesquiteFile.getFileContentsAsStrings(macro.getPath());
+			if (oldFile == null || oldFile.length ==0)
+				return null;
+			MesquiteBoolean answer = new MesquiteBoolean(false);
+			MesquiteString name = new MesquiteString(macro.getName());
+			MesquiteString explanation = new MesquiteString(macro.getRawExplanation());
+			MesquiteString.queryTwoStrings(containerOfModule(), "Edit Macro Information", "Name of macro for window (to appear as menu item)", "Explanation of macro",  answer, name, explanation, true);
+			if (!answer.getValue())
+				return null;
+			macro.setName(name.getValue());
+			macro.setExplanation(explanation.getValue());
+			//SAVE FILE
+			oldFile[0] = "telling " +   macro.getModuleInfo().getClassName()  + "  " + ParseUtil.tokenize(name.getValue()) + "   " +  ParseUtil.tokenize(explanation.getValue()) + ";" + StringUtil.lineEnding();
+			MesquiteFile.putFileContents(macro.getPath(), oldFile, true);
+			resetAllMenuBars();
+		}
+		else if (checker.compare(this.getClass(), "Brings up a dialog box to examine macro files", null, commandName, "showMacros")) {
+
+			//first get list of user-defined configs; must filter configurations vector to include only user-defined.  Then delete corresponding files!
+			ListableVector ud = getMacroRecords(false);
+
+			Listable[] list = ListDialog.queryListMultiple(containerOfModule(), "Macro Information", "These are the installed macros.  Touch on their names to see an explanation.", MesquiteString.helpString, ud, null);
+		}
+		else if (checker.compare(this.getClass(), "Crashes with a NullPointerException", null, commandName, "crash")) {
+			logln("Mesquite will now crash with a NullPointerException.  Please enjoy.");
+			MesquiteInteger mi = null;
+			logln("This will crash: " +mi.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Checks for notices or installs at the location specified", null, commandName, "checkNotices")) {
+			noticeLocation = MesquiteString.queryString(containerOfModule(), "Notices Location", "Indicate URL to notices file to be checked.  (For instance, for Mesquite the default notices file is at " + getHomePhoneNumber() + ")", noticeLocation);
+			PhoneHomeUtil.checkForNotices(noticeLocation); 
+			PhoneHomeUtil.adHocRecord = null;
+			resetAllMenuBars();
+		}
+		else if (checker.compare(this.getClass(), "Brings up a dialog box by which automatically-defined macros files can be deleted", null, commandName, "deleteAutoMacros")) {
+
+			//first get list of user-defined configs; must filter configurations vector to include only user-defined.  Then delete corresponding files!
+			ListableVector ud = getMacroRecords(true);
+
+			Listable[] list = ListDialog.queryListMultiple(containerOfModule(), "Delete Macro", "Select the macros to be deleted and hit \"OK\" to delete them", MesquiteString.helpString, "Delete", false, ud, null);
+
+			if (list!=null && list.length>0) {
+				if (AlertDialog.query(containerOfModule(), "Delete?", "Are you sure you want to delete the macro(s)?")){
+					for (int i=0; i<list.length; i++) {
+						MesquiteMacro macro = (MesquiteMacro)list[i];
+						MesquiteModuleInfo mmi = macro.getModuleInfo();
+						File f = new File(macro.getPath());
+						f.delete();
+						if (mmi !=null)
+							mmi.removeMacro(macro);
+					}
+					resetAllMenuBars();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Redirects log saving to the given filename", "[filename]", commandName, "redirectLog")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name))
+				name = MesquiteString.queryString(containerOfModule(), "Redirect Log", "Indicate name of log file to which subsequent log output is to be directored.  It will be saved in the directory " + supportFilesPath, MesquiteTrunk.logFileName);
+			if (StringUtil.blank(name))
+				return null;
+			logln("Log redirected to \"" + name + "\"");
+			MesquiteFile.closeLog();
+			MesquiteTrunk.logFileName = name;
+		}
+		else if (checker.compare(this.getClass(), "Changes the current log file's name", "[filename]", commandName, "renameLog")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name))
+				name = MesquiteString.queryString(containerOfModule(), "Rename Log", "Indicate new name of log file.  It will be saved in the directory " + supportFilesPath, MesquiteTrunk.logFileName);
+			if (StringUtil.blank(name))
+				return null;
+			MesquiteFile.closeLog();
+			logln("Log renamed to \"" + name + "\"");
+			String currentPath = supportFilesPath  + MesquiteFile.fileSeparator + MesquiteTrunk.logFileName;
+			MesquiteTrunk.logFileName = name;
+			MesquiteFile.rename(currentPath, supportFilesPath + MesquiteFile.fileSeparator + MesquiteTrunk.logFileName);
+
+
+		}
+		else if (checker.compare(this.getClass(), "Indicates that all installed modules are to be loaded at startup", null, commandName, "setConfigAll")) {
+			configFile = "all";
+			storePreferences();
+			discreetAlert("You will need to restart Mesquite to load all of the modules");
+		}
+		else if (checker.compare(this.getClass(), "Opens file on disk.  The file will be opened as a separate project (i.e. not sharing information) from any other files currently open.", "[name and path of file] - if parameter absent then presents user with dialog box to choose file", commandName, "openFile")) {
+			//hackathon
+			String path = ParseUtil.getFirstToken(arguments, stringPos);
+			String completeArguments = arguments;
+			MesquiteProject f;
+			CommandRecord comRec  = MesquiteThread.getCurrentCommandRecord();
+			CommandRecord cr;
+			if (comRec == null || comRec == CommandRecord.nonscriptingRecord || comRec.getID()<2) {
+				cr =new CommandRecord((CommandThread)null, false);
+				if (comRec == null)
+					cr.setFromCommandLine(Thread.currentThread() instanceof ConsoleThread);
+				else
+					cr.setFromCommandLine(comRec.isFromCommandLine());
+			}
+			else
+				cr = comRec;
+			CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(cr);
+			if (StringUtil.blank(path)) {
+				f = openFile(null); 
+			}
+			else {
+				String baseN = null;
+				if (MesquiteThread.isScripting()) {
+					MesquiteFile base = null;
+					base = CommandRecord.getScriptingFileS();
+					if (base !=null)
+						baseN = base.getDirectoryName();
+				}
+				if (!MesquiteFile.fileExists(path) && (!StringUtil.blank(baseN) && MesquiteFile.fileExists(baseN+path)))
+					path = baseN+path;
+				f= openFile(path, completeArguments);
+			}
+			MesquiteThread.setCurrentCommandRecord(prevR);
+			return f;
+		}
+		else if (checker.compare(this.getClass(), "Opens file on web server.  The file will be opened as a separate project (i.e. not sharing information) from any other files currently open.", "[URL of file] - if parameter absent then presents user with dialog box to enter URL", commandName, "openURL")){
+			arguments = ParseUtil.getFirstToken(arguments, stringPos);
+			return openURLString(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Opens module for project reading or making.", "[module]", commandName, "openGeneral")){
+			//arguments = ParseUtil.getFirstToken(arguments, stringPos);
+			return openGeneral(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Closes file and any other files linked to it (i.e. closes the project)", "[ID number of project]", commandName, "closeProjectByID")) {
+			int num = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(num)) {
+				MesquiteProject proj = MesquiteTrunk.mesquiteTrunk.projects.getProjectByID(num);
+				if (proj==null)
+					return null;
+				FileCoordinator coord = proj.getCoordinatorModule();
+				if (coord==null)
+					return null;
+				coord.closeFile(proj.getHomeFile());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Makes a new file (as a new project)", null, commandName, "newProject")) {
+			return newFileWithTaxa(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Makes a new file (as a new project)", null, commandName, "newEmptyProject")) {
+			return newFile(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Forces a reset of the menus.", null, commandName, "resetMenus")) {
+			zeroMenuResetSuppression();
+			resetAllMenuBars();
+		}
+		else if (checker.compare(this.getClass(), "Shows the GNU Lesser General Public License.", null, commandName, "showLicense")) {
+			TextDisplayer displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+			if (displayer!=null)
+				displayer.showFile(getRootPath()  + "lesser.txt", 100000, true); 
+			return displayer;
+		}
+		else if (checker.compare(this.getClass(), "Shows the currently executing command and offers to stop it.", null, commandName, "currentCommand")) {
+			if (MainThread.getCurrentlyExecuting()!=null) {
+				MainThread.mainThread.suspend();
+				if (!AlertDialog.query(containerOfModule(), "Current Command", "The current command is\n" + MainThread.getCurrentlyExecuting().getListName(), "Continue", "STOP COMMAND")) {
+					MainThread.getCurrentlyExecuting().interrupted = true;
+					MainThread.mainThread.interrupt();
+					MainThread.mainThread.stop();
+					alert("Stopped " + MainThread.getCurrentlyExecuting().getListName()); 
+					MainThread.mainThread = new MainThread();
+					MainThread.mainThread.start();
+				}
+				else 
+					MainThread.mainThread.resume();
+			}
+			else
+				alert("There is no command currently executing");
+		}
+		else if (checker.compare(this.getClass(), "Shows the list of pending commands and offers some to be suspended.", null, commandName, "pendingCommands")) {
+			if (MesquiteCommand.anyQueuedCommands(true)) {
+				String message = "This is a list of pending commands.  If you want to suspend any commands, select them and hit STOP COMMAND.  Otherwise, hit CANCEL.  The currently executing command is NOT listed.";
+				Listable[] commandsToKill = ListDialog.queryListMultiple(containerOfModule(), "Commands pending", message, MesquiteString.helpString, "STOP COMMAND", false, MainThread.listPendingCommands(), null);
+				if (commandsToKill !=null && commandsToKill.length>0){
+					for (int i=0; i<commandsToKill.length;  i++)
+						MainThread.pendingCommands.removeElement(commandsToKill[i], false);
+				}
+			}
+			else
+				alert("There are no commands pending");
+		}
+		else if (checker.compare(this.getClass(), "Reports memory status, for debugging of memory leaks.  Static boolean checkMemory needs to have been set first.", null, commandName, "reportMemory")) {
+			reportMemory();
+		}
+		else if (checker.compare(this.getClass(), "Quits Mesquite", null, commandName, "quit") || checker.compare(this.getClass(), "Quits Mesquite", null, commandName, "exit")) {
+			//CommandRecord.checkThread = false; //suppress thread checking
+			if (startedAsLibrary){
+				logln("Mesquite is being used by another program.  You should avoid asking Mesquite to quit, and instead let the other program ask Mesquite to quit");
+				return null;
+			}
+			PendingCommand pc = MainThread.getCurrentlyExecuting();
+
+			if (pc!=null && pc.getCommandRecord() != MesquiteThread.getCurrentCommandRecord() && !pc.permitQuitUnqueried()) {
+				if (AlertDialog.query(containerOfModule(), "Command executing", "Are you sure you want to quit?  There is a command currently executing (" + MainThread.getCurrentlyExecuting().getListName() + ").", "Continue", "Quit")){
+					//CommandRecord.checkThread = true;
+					System.out.println("Quit cancelled");
+					return null;
+				}
+			}
+			MesquiteTrunk.startupShutdownThread = Thread.currentThread();
+
+			incrementMenuResetSuppression();
+			attemptingToQuit = true;
+			if (!closeAllProjects()){
+				decrementMenuResetSuppression();
+				//CommandRecord.checkThread = true;
+				System.out.println("Quit cancelled");
+				attemptingToQuit = false;
+				return null;
+			}
+			if (debugMode){
+				/**/
+				logln("==vvvvvvvvvvvvvvvvvvvv==");
+				logln("The following is used to to check efficiencies.");
+				logln("Associable.totalPartsAdded " + Associable.totalPartsAdded);
+				logln("ListableVector.totalElementsAdded " + Associable.totalPartsAdded);
+				logln("MesquiteWindow.totalCheckDoomedCount " + MesquiteWindow.totalCheckDoomedCount);
+				logln("mesquite.minimal.BasicFileCoordinator.BasicFileCoordinator.totalProjectPanelRefreshes " + mesquite.minimal.BasicFileCoordinator.BasicFileCoordinator.totalProjectPanelRefreshes);
+				logln("--Classes painted\n" + MesquiteWindow.componentsPainted.recordsToString());
+				logln("Listened.notifications " + Listened.notifications);
+				logln("--Classes notifying\n" + Listened.classes.recordsToString());
+				logln("--Classes notified\n" + Listened.classesNotified.recordsToString());
+				logln("MesquiteProject.totalFinalized " +  MesquiteProject.totalFinalized + " totalDisposed " + MesquiteProject.totalDisposed + " totalCreated " +  MesquiteProject.totalCreated);
+				logln("MesquiteFile.totalFinalized " +  MesquiteFile.totalFinalized + " totalDisposed " + MesquiteFile.totalDisposed + " totalCreated " +  MesquiteFile.totalCreated);
+				logln("ProjectRead.totalFinalized " +  ProjectRead.totalFinalized + " totalCreated " +  ProjectRead.totalCreated);
+				logln("FileElement.totalFinalized " +  FileElement.totalFinalized + " totalDisposed " + FileElement.totalDisposed + " totalCreated " +  FileElement.totalCreated);
+				logln("MesquiteFrame.totalFinalized " +  MesquiteFrame.totalFinalized + " totalDisposed " + MesquiteFrame.totalDisposed + " totalCreated " +  MesquiteFrame.totalCreated);
+				logln("MesquiteWindow.totalFinalized " +  MesquiteWindow.totalFinalized + " totalDisposed " + MesquiteWindow.totalDisposed + " numDisposing " +  MesquiteWindow.numDisposing + " totalCreated " +  MesquiteWindow.totalCreated);
+				logln("MesquiteDialogParent.totalFinalized " +  MesquiteDialogParent.totalFinalized + " totalDisposed " + MesquiteDialogParent.totalDisposed + " totalCreated " +  MesquiteDialogParent.totalCreated);
+				logln("ListableVector.totalFinalized " +  ListableVector.totalFinalized + " totalDisposed " + ListableVector.totalDisposed + " totalCreated " +  ListableVector.totalCreated);
+				logln("MesquiteMenuItem.totalFinalized " +  MesquiteMenuItem.totalFinalized + " totalDisposed " + MesquiteMenuItem.totalDisposed + " totalCreated " +  MesquiteMenuItem.totalCreated);
+				logln("MesquiteMenuItemSpec.totalFinalized " +  MesquiteMenuItemSpec.totalFinalized + " totalDisposed " + MesquiteMenuItemSpec.totalDisposed + " totalCreated " +  MesquiteMenuItemSpec.totalCreated);
+				logln("NexusBlock.totalFinalized " +  NexusBlock.totalFinalized + " totalDisposed " + NexusBlock.totalDisposed + " totalCreated " +  NexusBlock.totalCreated);
+				logln("MesquiteModule.totalFinalized " +  MesquiteModule.totalFinalized + " totalDisposed " + MesquiteModule.totalDisposed + " totalCreated " +  MesquiteModule.totalCreated);
+				if (MesquiteTrunk.checkMemory){
+					logln("==vvvvvvvvvvvvvvvvvvvv==");
+					logln("The following is used to trace memory leaks");
+					reportMemory();
+					logln("==^^^^^^^^^^^^^^^^^^^^==");
+				}
+
+			}
+			logln("\n");
+			logln("All modules that have been started at least once, and the number of times they have been started:");
+			logln(getNumModuleStarts());
+			/*
+				if (Listened.listenersRemaining>0) {
+					for (int i = 0; i<Listened.allListeners.size(); i++){
+						Object r = Listened.allListeners.elementAt(i);
+						MesquiteMessage.println("listener remaining " + r);
+					}
+
+				}
+			 */
+			//	logln("Mesquite is quitting with some listeners remaining.  This is a symptom that some objects were not properly disposed, and it may relate to inflation of memory use.  Please report this problem.");
+			/**/
+
+
+			/*
+				logln("total time to startup modules "  + EmployerEmployee.startupTime.getAccumulatedTime() );
+				logln("total time to make window "  + MesquiteWindow.startingTime.getAccumulatedTime() );
+				logln("total time to show window "  + MesquiteWindow.windowShowTime.getAccumulatedTime() );
+				logln("total time to compose menus "  + MenuOwner.menuCompositionTime.getAccumulatedTime() );
+				logln("total time to reset menus "  + MesquiteWindow.resetMenuTime.getAccumulatedTime() );
+				logln("total time to make tables  "  + MesquiteTable.tableTime.getAccumulatedTime() );
+				logln("Modules: total started: " + EmployerEmployee.totalCreated + "; total ended: " + EmployerEmployee.totalDisposed);
+				logln("Trees: total created: " + MesquiteTree.totalCreated + "; total disposed: " + MesquiteTree.totalDisposed);
+			 */
+			doomed = true;
+			showAbout = (about!= null && !about.isShowing());
+			storePreferences();
+			logln("Main Mesquite module quitting  " );
+
+			iQuit();
+			if (debugMode)
+				logln("disposing remaining windows  " );
+			while (windowVector.size()>0) {
+				Enumeration e = windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					mw.setVisible(false);
+					mw.dispose();
+				}
+			}
+			if (debugMode)
+				logln("exiting " );
+			MesquiteFile.closeLog();
+			mesquiteExiting = true;
+			if (!startedAsLibrary)
+				System.exit(0);
+		}
+		else if (checker.compare(this.getClass(), "Force Quit Mesquite (data may be lost) via click go-away", null, commandName, "goAwayForceQuit")) {
+			incrementMenuResetSuppression();
+			doomed = true;
+			while (windowVector.size()>0) {
+				Enumeration e = windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					mw.setVisible(false);
+					mw.dispose();
+				}
+			}
+			showAbout = false;
+			System.exit(0);
+		}
+		else if (checker.compare(this.getClass(), "Force Quit Mesquite (data may be lost)", null, commandName, "forceQuit")) {
+			System.exit(0);
+		}
+		else if (checker.compare(this.getClass(), "Closes down all threads and modules, but doesn't stop JVM", null, commandName, "vanish")) {
+			mesquiteExiting = true;
+			doomed = true;
+			iQuit();
+			while (windowVector.size()>0) {
+				Enumeration e = windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					mw.setVisible(false);
+					mw.dispose();
+				}
+			}
+			MesquiteFile.closeLog();		
+		}
+		else if (checker.compare(this.getClass(), "Brings all windows to front", null, commandName, "showAllWindows")) {
+			Enumeration e = windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				MesquiteFrame mf = mw.getParentFrame();
+				if (mf.isVisible())
+					mf.setVisible(true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes all current projects and files", null, commandName, "closeAllProjects")) {
+			closeAllProjects();
+		}
+		else if (checker.compare(this.getClass(), "Saves all current projects and files", null, commandName, "saveAllProjects")) {
+			int numFiles = 0;
+			Projects projs = getProjectList();
+			for (int i= 0; i<projs.getNumProjects(); i++) {
+				numFiles += projs.getProject(i).getNumberLinkedFiles();
+			}
+			String s= "Do you want to save all of the open files?  There are currently " + numFiles + " files open";
+			if (numFiles == getProjectList().getNumProjects())
+				s += ".";
+			else
+				s += " in " + getProjectList().getNumProjects() + " separate projects." ;
+			if (MesquiteThread.isScripting() || AlertDialog.query(containerOfModule(), "Save all?", s, "Save", "Cancel", 1))
+				saveAllProjects();
+		}
+		else if (checker.compare(this.getClass(), "Performs keyword search to find module with particular function.", null, commandName, "keywordSearch")) {
+			//system could log employers used for various modules to give examples of use
+			String s = parser.getFirstToken(arguments);
+			if (StringUtil.blank(s) && !MesquiteThread.isScripting())
+				s = MesquiteString.queryString(containerOfModule(), "Keyword", "Enter a search string.  Mesquite will search through module information for a match (currently, the string as a whole must match).", "");
+			if (s!=null) {
+				searchKeyword(s, true);
+			}
+		}
+		/*New code added Feb.05.07 oliver*/ //TODO: Delete new code comments
+		else if (checker.compare(this.getClass(), "Searches the internet for user-provided terms.", null, commandName, "webSearch")) {
+			String queryTerm = "";
+			MesquiteBoolean addMesquiteToSearch = new MesquiteBoolean(true);
+			MesquiteBoolean restrictSearchToManual = new MesquiteBoolean(true);
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog webQueryDialog = new ExtensibleDialog(containerOfModule(), "Web Search", buttonPressed);
+			webQueryDialog.addLargeOrSmallTextLabel("Enter a search string. Mesquite will open a web browser and search for the terms using the Google search engine.");
+			TextArea queryText = webQueryDialog.addTextArea("", 4);
+			Checkbox addMesquite = webQueryDialog.addCheckBox("Include 'Mesquite' in search terms?", addMesquiteToSearch.getValue());
+			Checkbox restrictToManual = webQueryDialog.addCheckBox("Restrict search to Mesquite's online manual?", restrictSearchToManual.getValue());
+			webQueryDialog.appendToHelpString("The terms entered will be searched for on your web browser, using the Google search engine.  Use single or double quotes to group terms in your search.");
+			webQueryDialog.completeAndShowDialog(true);
+			if (buttonPressed.getValue()==0)  {
+				queryTerm = queryText.getText();
+				addMesquiteToSearch.setValue(addMesquite.getState());
+				restrictSearchToManual.setValue(restrictToManual.getState());
+			}
+			if (queryTerm!=null && buttonPressed.getValue()==0){
+				searchWeb(queryTerm, addMesquiteToSearch, restrictSearchToManual);
+			}
+			webQueryDialog.dispose();
+		}
+		/*End new code added Feb.05.07 oliver*/
+		/*New code added April.04.07 oliver*/ //TODO: Delete new code comments
+		else if (checker.compare(this.getClass(), "Opens the Mesquite FAQ in a web browser", null, commandName, "mesquiteFAQ")){
+			openMesquiteFAQ();
+		}
+		/*End new code added April.04.07 oliver*/
+		else if (checker.compare(this.getClass(), "Shows web page of installed and loaded modules", null, commandName, "showModules")) {
+			if (MesquiteTrunk.isApplet()) 
+				return null;
+			if (!CommandChecker.documentationComposed) {
+				CommandChecker cchecker = new CommandChecker();
+				cchecker.composeDocumentation();
+			}	
+			String moduleListPath= MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "modules.html";
+			File testing = new File(moduleListPath);
+			if (testing.exists()) {
+				showWebPage(moduleListPath, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows web page introducing a package of installed modules", null, commandName, "showPackageInfo")) {
+			if (MesquiteTrunk.isApplet()) 
+				return null;
+			String packageURL= parser.getFirstToken(arguments); //MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "modules.html";
+			if (StringUtil.notEmpty(packageURL)) {
+				if (packageURL.startsWith("http"))
+					showWebPage(packageURL,false);
+				else {
+					File testing = new File(packageURL);
+					if (testing.exists()) {
+						showWebPage(packageURL, false);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows web page of available commands for scripting", null, commandName, "showCommands")) {
+			if (MesquiteTrunk.isApplet()) 
+				return null;
+			if (!CommandChecker.documentationComposed) {
+				CommandChecker cchecker = new CommandChecker();
+				cchecker.composeDocumentation();
+			}	
+			String commandListPath= MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "commands.html";
+			File testing = new File(commandListPath);
+			if (testing.exists()) {
+				showWebPage(commandListPath, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows home page of Mesquite", null, commandName, "showHomePage")) {
+			if (MesquiteTrunk.isApplet()) 
+				return null;
+
+			String manualPath = mesquiteWebSite; 
+			//File testing = new File(manualPath);
+			showWebPage(manualPath, false);
+
+		}
+		else if (checker.compare(this.getClass(), "Shows Support page of Mesquite manual", null, commandName, "showSupport")) {
+			if (MesquiteTrunk.isApplet()) 
+				return null;
+
+			String manualPath = mesquiteWebSite + "/Getting+Help" ;
+			showWebPage(manualPath, false);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the Mesquite window appears automatically when no windows are showing", "[on or off]", commandName, "windowAutoShow")){
+			MesquiteWindow.autoShow = MesquiteBoolean.fromOffOnString(ParseUtil.getFirstToken(arguments, stringPos));
+		}
+		else if (checker.compare(this.getClass(), "Returns string (\"on\", \"off\") whether the Mesquite window appears automatically when no windows are showing", null, commandName, "getWindowAutoShow")){
+			return MesquiteBoolean.toOffOnString(MesquiteWindow.autoShow);
+		}
+		else if (checker.compare(this.getClass(), "Dumps the entire employee tree to the log", null, commandName, "dumpEmployeeTree")) {
+			showLogWindow();
+			logln("======= Module Employee Tree =======\n" + listEmployees("  ") + "\n================================");
+		}
+		else if (checker.compare(this.getClass(), "Shows some statistics that might be of interest to developers", null, commandName, "showStatistics")) {
+			showLogWindow();
+			logln("Number of modules installed " + MesquiteTrunk.mesquiteModulesInfoVector.size());
+			dumpFileList(getRootPath() + "mesquite", "mesquite", " ");
+			logln("MesquiteWindow.totalCheckDoomedCount " + MesquiteWindow.totalCheckDoomedCount);
+			logln("--Classes painted\n" + MesquiteWindow.componentsPainted.recordsToString());
+			logln("Listened.notifications " + Listened.notifications);
+			logln("--Classes notifying\n" + Listened.classes.recordsToString());
+			logln("--Classes notified\n" + Listened.classesNotified.recordsToString());
+		}
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of those modules that are substantive and (prerelease or without citations)", null, commandName, "dumpSubstantivePrerelease")) {
+			showLogWindow();
+			logln("\nModules that are marked as substantive and prerelease:\n");
+			int count = 0;
+			if (isPrerelease()) {
+				count++;
+				logln(getClass().getName());
+			}
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				if (mmi.isSubstantive() && mmi.isPrerelease()) {
+					logln(mmi.getClassName());
+					count++;
+				}
+			}
+			if (count == 0)
+				logln("   There are no modules marked as substantive and prerelease.\n");
+			else
+				logln("\n[number of substantive and prerelease: " + count + "]\n");
+			if (false){ //these are useful to list to find those who should be asking to have their citations shown!
+				logln("======= Substantive Modules that don't ask to have their citations shown =======");
+				count = 0;
+				for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+					MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+					if (mmi.isSubstantive() && !mmi.showCitation()) {
+						logln(mmi.getClassName());
+						count++;
+					}
+				}
+				logln("============ number substantive but without citation " + count + " ==============");
+			}
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of those modules that are prerelease", null, commandName, "dumpAllPrerelease")) {
+			showLogWindow();
+			logln("\nModules that are marked as prerelease:\n");
+			int count = 0;
+			if (isPrerelease()) {
+				count++;
+				logln(getClass().getName());
+			}
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				if (mmi.isPrerelease()) {
+					logln(mmi.getClassName());
+					count++;
+				}
+			}
+			if (count == 0)
+				logln("   There are no modules marked as prerelease.\n");
+			else
+				logln("\n[number of prerelease: " + count + "]\n");
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of modules, their names and explanations, and their needs", null, commandName, "dumpEN")) {
+			showLogWindow();
+			logln("\nModules and their informations:\n");
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				String s = "<li><strong>" + mmi.getName() + ":</strong>  " + mmi.getExplanation() + "   <font color = AAAAAA> " +mmi.getClassName() + "</font>";
+				if (mmi.hasNeeds()){
+					Vector v = mmi.getEmployeeNeedsVector();
+					s += "<ul>";
+					for (int k = 0; k<v.size(); k++){
+						EmployeeNeed need = (EmployeeNeed)v.elementAt(k);
+						s += "<li>" + need.getDutyClass().getName() + "</li>";
+					}
+					s += "</ul>";
+				}
+				s += "</li>";
+				logln(s);
+			}
+
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of those modules that are new to this version", null, commandName, "dumpNewModules")) {
+			showLogWindow();
+			logln("\n=======================================\nModules that are new to this release of Mesquite:\n");
+			int count = 0;
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				if (mmi.getVersionOfFirstRelease()>= getVersionInt()) {
+					logln(mmi.getName());
+					logln("\t" + mmi.getExplanation());
+					logln("\t  ["+mmi.getClassName()+"]");
+					logln("");
+					count++;
+				}
+			}
+			if (count == 0)
+				logln("   There are no new modules.\n");
+			else
+				logln("\n[number of new modules: " + count + "]\n");
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of those modules that are new to the next release version", null, commandName, "dumpNextReleaseModules")) {
+			showLogWindow();
+			logln("\n=======================================\nModules that will be new in the next release of Mesquite:\n");
+			int count = 0;
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				if (mmi.getVersionOfFirstRelease()== NEXTRELEASE) {
+					logln(mmi.getName());
+					logln("\t" + mmi.getExplanation());
+					logln("\t  ["+mmi.getClassName()+"]");
+					logln("");
+					count++;
+				}
+			}
+			if (count == 0)
+				logln("   There will be no new modules.\n");
+			else
+				logln("\n[number of new modules in next release: " + count + "]\n");
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of all modules installed", null, commandName, "dumpAllModules")) {
+			showLogWindow();
+			logln("\n=======================================\nModules installed:\n");
+			int count = 0;
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				String vers = mmi.getVersion();
+				if (vers == null)
+					vers = "";
+				else
+					vers = " (" + mmi.getPackageName() + ", version " + vers + ")";
+				logln(mmi.getName() + "\t" + mmi.getExplanation() + vers);
+				count++;
+			}
+			logln("Modules installed: " + count);
+
+		}	
+		else if (checker.compare(this.getClass(), "Dumps to the log a list of all modules installed", null, commandName, "dumpAllModuleClasses")) {
+			showLogWindow();
+			logln("\n=======================================\nModules installed:\n");
+			int count = 0;
+			for (int i= 0; i<mesquiteModulesInfoVector.size(); i++){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)mesquiteModulesInfoVector.elementAt(i);
+				logln(mmi.getClassName());
+				count++;
+			}
+
+		}	
+		else if (checker.compare(this.getClass(), "Sends Error to Server", null, commandName, "testError")) {
+			reportProblemToHome("TESTING ERROR REPORTING");
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	private void dumpFileList(String path, String name, String spacer){
+		File f = new File(path);  //
+		if (!f.exists())
+			return;
+		if (name != null){
+			if (f.isDirectory())
+				MesquiteMessage.println(spacer + name + "--------------"); 
+			else if (name.indexOf(".class")>=0)
+				MesquiteMessage.println(spacer + name + "    " + (new Date(f.lastModified()))); //class files only
+		}
+
+		if (f.isDirectory()){  // is a directory; hence look inside at each item
+			String[] filesList = f.list();
+			for (int i=0; i<filesList.length; i++){
+				dumpFileList(path+ MesquiteFile.fileSeparator + filesList[i], filesList[i], spacer + "   ");
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static void prepareMesquite(){
+		windowVector = new ListableVector();
+		dialogVector = new ListableVector();
+		fileMenu=new MesquiteMenuSpec(null, "File", mesquiteTrunk, true);
+		fileMenu.setFilterable(false);
+		editMenu=new MesquiteMenuSpec(null, "Edit", mesquiteTrunk, true);
+		windowsMenu=new MesquiteMenuSpec(null, "View", mesquiteTrunk, true);
+		charactersMenu = new MesquiteMenuSpec(null, "Characters", mesquiteTrunk, true);
+		treesMenu = new MesquiteMenuSpec(null, "Taxa&Trees", mesquiteTrunk, true);
+		analysisMenu = new MesquiteMenuSpec(null, "Analysis", mesquiteTrunk, true);
+		helpMenu = new MesquiteMenuSpec(null, "Help", mesquiteTrunk, true);
+		helpMenu.setFilterable(false);
+		projects = new Projects();
+		mesquiteTrunk.newFileCommand = makeCommand("newProject",  mesquiteTrunk);
+		mesquiteTrunk.openFileCommand = makeCommand("openFile",  mesquiteTrunk);
+		mesquiteTrunk.openURLCommand = makeCommand("openURL",  mesquiteTrunk);
+		mesquiteTrunk.currentCommandCommand = makeCommand("currentCommand",  mesquiteTrunk);
+		mesquiteTrunk.currentCommandCommand.setQueueBypass(true);
+		mesquiteTrunk.pendingCommandsCommand = makeCommand("pendingCommands",  mesquiteTrunk);
+		mesquiteTrunk.pendingCommandsCommand.setQueueBypass(true);
+		mesquiteTrunk.resetMenusCommand = makeCommand("resetMenus",  mesquiteTrunk);
+		mesquiteTrunk.showLicenseCommand = makeCommand("showLicense",  mesquiteTrunk);
+		mesquiteTrunk.quitCommand = makeCommand("quit",  mesquiteTrunk);
+		mesquiteTrunk.quitCommand.setQueueBypass(true);
+		mesquiteTrunk.forceQuitCommand = makeCommand("forceQuit",  mesquiteTrunk);
+		mesquiteTrunk.forceQuitCommand.setQueueBypass(true);
+		mesquiteTrunk.showAllCommand = makeCommand("showAllWindows", mesquiteTrunk);
+		mesquiteTrunk.closeAllCommand = makeCommand("closeAllProjects", mesquiteTrunk);
+		mesquiteTrunk.saveAllCommand = makeCommand("saveAllProjects", mesquiteTrunk);
+
+		about =new AboutWindow(mesquiteTrunk);
+		about.setResizable(false);
+		//about.setWindowSize(AboutWindow.totalWidth, AboutWindow.aboutHeight); 
+		about.setQuitIfGoAway(true);
+
+		MesquiteWindow.centerWindow(about);
+
+		/*EMBEDDED	if embedded delete the following    */
+		//about.addToWindow(mesquiteTrunk);
+		/**/
+		CommandChecker.registerClass(Mesquite.class, MesquiteModule.class);
+
+		CommandChecker.registerClass(AboutWindow.class, MesquiteWindow.class);
+		CommandChecker.registerClass(MesquitePanel.class, MesquitePanel.class);
+
+		CommandChecker.registerClass(System.class, System.class);
+	}
+
+	private void registerMacHandlers(){
+		if (!MesquiteWindow.GUIavailable)
+			return;
+		else if (MesquiteTrunk.isMacOSX()) {
+			fileHandler = new EAWTHandler(this);
+			((EAWTHandler)fileHandler).register();
+		}
+	}
+
+	public Mesquite(){
+		super();
+	}
+
+	/* separated as a constructor in v. 2. 01 in preparation for Mesquite being instantiated other than as standalone application */
+	public Mesquite(String args[]){
+		super();
+		boolean outputVersion = false;
+		boolean otherArgumentFound = false;
+		if (args !=null){
+			startupArguments = new String[args.length];
+			for (int i=0; i<args.length; i++){
+				startupArguments[i] = args[i];
+				if (args[i]!=null){
+					if (args[i].equals("-w"))
+						MesquiteWindow.suppressAllWindows = true;
+					else if (args[i].equals("-b"))
+						MesquiteTrunk.consoleListenSuppressed = true;
+					else if (args[i].equals("-nv"))
+						MesquiteTrunk.suppressVersionReporting = true;
+					else if (args[i].equals("-ne"))
+						MesquiteTrunk.suppressErrorReporting = true;
+					else if (args[i].equals("-nb"))
+						MesquiteTrunk.noBeans = true;
+					else if (args[i].equals("-mqex"))
+						MesquiteTrunk.startedFromExecutable = true;
+					else if (args[i].equals("-mq17"))
+						startedFromOSXJava17Executable = true;
+					else if (args[i].equals("-d"))
+						MesquiteTrunk.debugMode = true;
+					else if (args[i].equals("--version"))
+						outputVersion = true;
+					else
+						otherArgumentFound = true;
+				}
+			}
+		}
+		//if passed --version then write text file with stringForVersion, tab, stringForBuild
+		if (outputVersion){
+			Writer stream;
+			try {
+				stream = new OutputStreamWriter(new FileOutputStream("MesquiteVersion.txt"));
+				stream.write(getVersion() + "\t" + getBuildNumber());
+				stream.flush();
+				stream.close();
+			}
+			catch( Throwable e ) {
+			}
+
+			System.out.println(getVersion() + "\t" + getBuildNumber());
+			if (!otherArgumentFound){
+				if (!startedAsLibrary)
+					System.exit(0);
+				return;
+			}
+		}
+		if (MesquiteTrunk.debugMode)
+			System.out.println("main constructor 1");
+		MesquiteWindow.componentsPainted = new ClassVector();//for detecting efficiency problems
+		Listened.classes = new ClassVector();//for detecting efficiency problems
+		Listened.classesNotified = new ClassVector();//for detecting efficiency problems
+		if (MesquiteWindow.GUIavailable){
+			try { //code testing for GUI from Kevin Herrboldt via java-dev at lists.apple.com
+				Frame foo = new Frame();
+
+				if (foo==null)
+					MesquiteWindow.GUIavailable = false;// no GUI available, need to be non-gui
+				else {
+					foo.pack();
+					foo.getToolkit();       // will throw exception if unable to open GUI
+				}
+			} catch (Throwable t) {
+				MesquiteWindow.GUIavailable = false;// no GUI available, need to be non-gui
+			}
+		}
+		if (MesquiteTrunk.debugMode)
+			System.out.println("main constructor 2");
+		try {
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 3");
+			MesquiteTrunk.startupShutdownThread = Thread.currentThread();
+			incrementMenuResetSuppression();
+			isApplication = true;
+
+			// create a new instance of this applet 
+			mesquiteTrunk = this;
+			Mesquite mesq = (Mesquite)mesquiteTrunk;  //for easy of reference below
+			if (MesquiteTrunk.isWindows()){
+				textEdgeCompensationHeight = 7; //6 on mac; 7 on pc
+				textEdgeCompensationWidth = 22; //12 on mac; 28 on pc
+			}
+			mesq.registerMacHandlers();
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 4");
+			MainThread.mainThread = new MainThread();
+			MainThread.mainThread.start();
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 5");
+			prepareMesquite();
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 6");
+
+			// initialize the applet
+			mesquiteTrunk.init();
+			//EMBEDDED: include this  
+			((Mesquite)mesquiteTrunk).start(); 
+
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 7");
+			// open the files requested at startup
+			if (args != null && args.length>0) {
+				// report arguments
+				String s = "Arguments: ";
+				for ( int i = 0; i < args.length; i++ ) {
+					s += " [ " + args[i] + " ]";
+				}
+				MesquiteTrunk.mesquiteTrunk.logln(s);
+
+				for ( int i = 0; i < args.length; i++ ) {
+					if (args[i]!=null && !args[i].startsWith("-"))
+						mesquiteTrunk.openFile(args[i]);
+				}
+			}
+
+			if (MesquiteTrunk.debugMode)
+				System.out.println("main constructor 8");
+			mesquiteTrunk.resetAllMenuBars();
+			MesquiteTrunk.startupShutdownThread = null;
+			decrementMenuResetSuppression();
+		}
+		catch (Exception e){
+			if (!Mesquite.mesquiteExiting){
+				MesquiteFile.throwableToLog(this, e);
+				exceptionAlert(e, "Exception caught in Mesquite");
+			}
+		}
+		catch (Error e){
+			if (!Mesquite.mesquiteExiting){
+				MesquiteFile.throwableToLog(this, e);
+				exceptionAlert(e, "Error caught in Mesquite");
+			}
+
+		}
+		if (MesquiteTrunk.debugMode)
+			System.out.println("main constructor 6");
+		if (about !=null && mesquiteTrunk.getProjectList()!=null && mesquiteTrunk.getProjectList().getNumProjects()>0 && defaultHideMesquiteWindow)
+			about.hide();
+	}
+
+	/*.................................................................................................................*
+	public boolean externalStart(String args[]){
+		MesquiteWindow.GUIavailable = true;
+		mesquiteTrunk = this;
+		OMStartupThread t = new OMStartupThread(args);
+		t.start();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public static void main(String args[])
+	{
+		MesquiteWindow.GUIavailable = !MesquiteWindow.headless;
+		mesquiteTrunk = new Mesquite(args);
+		/*
+		if (args !=null){
+			for (int i=0; i<args.length; i++)
+				if (args[i]!=null){
+					if (args[i].equals("-w"))
+						MesquiteWindow.suppressAllWindows = true;
+					else if (args[i].equals("-b"))
+						MesquiteTrunk.consoleListenSuppressed = true;
+				}
+		}
+		MesquiteWindow.componentsPainted = new ClassVector();//for detecting efficiency problems
+		Listened.classes = new ClassVector();//for detecting efficiency problems
+		Listened.classesNotified = new ClassVector();//for detecting efficiency problems
+		try { //code testing for GUI from Kevin Herrboldt via java-dev at lists.apple.com
+			Frame foo = new Frame();
+
+			if (foo==null)
+				MesquiteWindow.GUIavailable = false;// no GUI available, need to be non-gui
+			else {
+				foo.pack();
+				foo.getToolkit();       // will throw exception if unable to open GUI
+			}
+		} catch (Throwable t) {
+			MesquiteWindow.GUIavailable = false;// no GUI available, need to be non-gui
+		}
+		try { 
+			String mrj = System.getProperty("mrj.version");
+			if (!StringUtil.blank(mrj) && (mrj.startsWith("3.0") || mrj.startsWith("3.1"))) //Java2D turned off for OS X prior to 10.2 because of bugs
+				MesquiteWindow.Java2Davailable = false;
+			else {
+				BasicStroke bs = new BasicStroke();
+				MesquiteWindow.Java2Davailable = bs !=null;
+			}
+		} catch (Throwable t) {
+			MesquiteWindow.Java2Davailable = false;
+		}
+		MesquiteWindow.pdfOutputAvailable = MesquiteTrunk.isJavaVersionLessThan(1.3);
+		try {
+			MesquiteTrunk.startupShutdownThread = Thread.currentThread();
+			incrementMenuResetSuppression();
+			isApplication = true;
+
+			// create a new instance of this applet 
+			mesquiteTrunk = new Mesquite();
+			Mesquite mesq = (Mesquite)mesquiteTrunk;  //for easy of reference below
+			mesq.registerMacHandlers();
+			MainThread.mainThread = new MainThread();
+			MainThread.mainThread.start();
+			prepareMesquite();
+
+			// initialize the applet
+			mesquiteTrunk.init();
+			//EMBEDDED: include this  
+			((Mesquite)mesquiteTrunk).start(); 
+
+			// open the files requested at startup
+			if (args.length>0) {
+				// report arguments
+				String s = "Arguments: ";
+				for ( int i = 0; i < args.length; i++ ) {
+					s += " [ " + args[i] + " ]";
+				}
+				MesquiteTrunk.mesquiteTrunk.logln(s);
+
+				for ( int i = 0; i < args.length; i++ ) {
+					if (args[i]!=null && !args[i].startsWith("-"))
+						mesquiteTrunk.openFile(args[i]);
+				}
+			}
+
+			mesquiteTrunk.resetAllMenuBars();
+			MesquiteTrunk.startupShutdownThread = null;
+			decrementMenuResetSuppression();
+		}
+		catch (Exception e){
+			if (!Mesquite.mesquiteExiting){
+				MesquiteFile.throwableToLog(null, e);
+				MesquiteMessage.warnProgrammer("Exception caught in Mesquite: " + e.getMessage());
+				MesquiteModule.showLogWindow();
+			}
+		}
+		catch (Error e){
+			if (!Mesquite.mesquiteExiting){
+				MesquiteFile.throwableToLog(null, e);
+				MesquiteMessage.warnProgrammer("Error caught in Mesquite: " + e.getMessage());
+				MesquiteModule.showLogWindow();
+				throw e;
+			}
+
+		}
+		if (about !=null && mesquiteTrunk.getProjectList()!=null && mesquiteTrunk.getProjectList().getNumProjects()>0 && defaultHideMesquiteWindow)
+			about.hide();
+		 */
+	}
+
+
+}
+
+
+
diff --git a/Source/mesquite/align/AlignDNAToProtein/AlignDNAToProtein.java b/Source/mesquite/align/AlignDNAToProtein/AlignDNAToProtein.java
new file mode 100644
index 0000000..39b1bcc
--- /dev/null
+++ b/Source/mesquite/align/AlignDNAToProtein/AlignDNAToProtein.java
@@ -0,0 +1,180 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.AlignDNAToProtein;
+
+import java.awt.Checkbox;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.molec.lib.*;
+import mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep;
+
+
+
+
+public class AlignDNAToProtein extends DNADataAltererCon {
+	CharMatrixCoordIndep characterSourceTask;
+	boolean adjustCodonPositions = true;
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharMatrixCoordIndep.class, getName() + " needs a module to supply a character matrix.",
+		"The matrix source is chosen initially.");
+	}
+
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		characterSourceTask = (CharMatrixCoordIndep)hireCompatibleEmployee(CharMatrixCoordIndep.class, ProteinState.class, "Protein Matrix");
+//	characterSourceTask = (CharMatrixCoordIndep)hireCompatibleEmployee(CharMatrixCoordIndep.class, ProteinState.class, "Protein Matrix");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no protein matrix obtained");
+		if (!MesquiteThread.isScripting())
+			if (!queryOptions())
+				return false;
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "AlignDNAToProtein",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Align DNA to Protein");
+		Checkbox adjustCodonPositionsBox = dialog.addCheckBox("adjust codon positions if necessary in re-aligned sequences", adjustCodonPositions);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			adjustCodonPositions = adjustCodonPositionsBox.getState();
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+
+	/*.................................................................................................................*/
+	public boolean forceAlignment(DNAData dnaData, ProteinData proteinData, int it) {
+		if (dnaData == null || proteinData == null)
+			return false;
+		int numBases = dnaData.getNumberApplicableInTaxon(it, true);
+		int numAAs = proteinData.getNumberApplicableInTaxon(it, true);
+		if (numAAs*3!= numBases) {
+			logln("Number of nucleotides in sequence does not correspond to number of amino acids in protein sequence (taxon " + it + ")");
+			return false;
+		}
+		
+		int numInDNA = dnaData.getNumChars();
+		int numInProtein = proteinData.getNumChars();
+		MesquiteBoolean dataChanged = new MesquiteBoolean();
+		MesquiteInteger charAdded = new MesquiteInteger(0);
+		if (numInDNA<numInProtein*3) {
+			dnaData.addCharacters(numInDNA, numInProtein*3-numInDNA, false);
+			dnaData.assignCodonPositionsToTerminalChars(numInProtein*3-numInDNA);
+//			dnaData.assignGeneticCodeToTerminalChars(numInProtein*3-numInDNA);
+			dnaData.addInLinked(numInDNA, numInProtein*3-numInDNA, true);
+			dataChanged.setValue(true);
+		}
+		dnaData.collapseGapsInCellBlockRight(it, 0, dnaData.getNumChars()-1, false);   //move everything to right so we only need to shift them left
+		//note that this means it only works on whole sequences! with codon positions defined
+
+		int icProtein = 0;
+		int icDNA = 0;
+		
+		while (icProtein<numInProtein) {   // now zip through the protein and find bases and move the nucleotides to correspond
+			icProtein = proteinData.nextApplicable(it, icProtein, true)	;
+			if (icProtein<0) break;
+			int adjustedPosInDNA = icProtein*3; // new location
+			for (int codPos=0; codPos<=2; codPos++){
+				icDNA = dnaData.nextApplicable(it, icDNA, true);
+				if (icDNA>=0) {
+					int distance = icDNA-adjustedPosInDNA;
+					dnaData.moveCells(icDNA,icDNA, -distance, it,it, false, false, true,  false, dataChanged, charAdded, null);
+					if (charAdded.isCombinable() && charAdded.getValue()!=0) {
+						dnaData.assignCodonPositionsToTerminalChars(charAdded.getValue());
+//						dnaData.assignGeneticCodeToTerminalChars(charAdded.getValue());
+					}
+					else if (adjustCodonPositions)  // adjust codpos so it fits for this taxon
+						dnaData.setCodonPosition(adjustedPosInDNA, codPos+1, false, false);
+					adjustedPosInDNA++;
+					icDNA++;
+				}
+			}
+			icProtein++;
+		}
+		
+		
+	return dataChanged.getValue();
+	
+
+	}
+	/*.................................................................................................................*/
+	public boolean alterBlockInTaxon(CharacterData data, int icStart, int icEnd, int it) {
+		if (data==null || !(data instanceof DNAData))
+			return false;
+		Taxa taxa = data.getTaxa();
+
+		MCharactersDistribution m =  characterSourceTask.getCurrentMatrix(taxa);
+		if (m == null || !(m.getParentData() instanceof ProteinData))
+			return false;
+		ProteinData proteinData = (ProteinData)m.getParentData();
+
+		return forceAlignment((DNAData)data,proteinData, it);
+	}
+
+	public boolean alterBlockOfCharacters(CharacterData data, int icStart, int icEnd) {
+		if (data==null || !(data instanceof DNAData))
+			return false;
+		Taxa taxa = data.getTaxa();
+
+		MCharactersDistribution m =  characterSourceTask.getCurrentMatrix(taxa);
+		if (m == null || !(m.getParentData() instanceof ProteinData))
+			return false;
+		ProteinData proteinData = (ProteinData)m.getParentData();
+		boolean result = false;
+		for (int it = 0; it< data.getNumTaxa(); it++){
+			boolean success = forceAlignment((DNAData)data,proteinData, it);
+			result = result || success;
+		}
+		return result;
+	}
+	public String getName() {
+		return "Align DNA to Protein";
+	}
+
+	public String getNameForMenuItem() {
+		return "Align DNA to Protein...";
+	}
+
+	public String getExplanation() {
+		return "Realigns a DNA matrix to match the alignment in an amino acid alignment.";
+	}
+	public boolean requestPrimaryChoice() {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return -111;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/align/AlignScoreForTaxon/AlignScoreForTaxon.java b/Source/mesquite/align/AlignScoreForTaxon/AlignScoreForTaxon.java
new file mode 100644
index 0000000..fcf727a
--- /dev/null
+++ b/Source/mesquite/align/AlignScoreForTaxon/AlignScoreForTaxon.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.AlignScoreForTaxon;
+
+import mesquite.align.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+public class AlignScoreForTaxon extends AlignScoreForTaxonGen {
+	/*.................................................................................................................*/
+	protected  void getAlignmentScore(DNAData data, MCategoricalDistribution observedStates,  int it1, int it2, MesquiteNumber score) {
+		if (aligner!=null)
+			aligner.alignSequences(observedStates, it1, it2,MesquiteInteger.unassigned,MesquiteInteger.unassigned,false,score);
+   	 }
+	   /*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return -100;  
+   }
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Alignment Score To Ref.";  
+	 }
+	/*.................................................................................................................*/
+	 public String getScoreName() {
+	return "Alignment Score";  
+	 }
+  
+		/*.................................................................................................................*/
+	 public String getExplanation() {
+		 String s = super.getExplanation();  
+		 return s+ " The score for each taxon is the cost of aligning that taxon's sequence against the reference taxon using Mesquite's default pairwise aligner.  Lower scores mean a better alignment.";
+	 }
+	 /*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+
+}
+
+
+
diff --git a/Source/mesquite/align/AlignScoreForTaxonRC/AlignScoreForTaxonRC.java b/Source/mesquite/align/AlignScoreForTaxonRC/AlignScoreForTaxonRC.java
new file mode 100644
index 0000000..7e75cec
--- /dev/null
+++ b/Source/mesquite/align/AlignScoreForTaxonRC/AlignScoreForTaxonRC.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.AlignScoreForTaxonRC;
+
+import mesquite.align.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+public class AlignScoreForTaxonRC extends AlignScoreForTaxonGen {
+	/*.................................................................................................................*/
+	protected  void getAlignmentScore(DNAData data, MCategoricalDistribution observedStates, int it1, int it2, MesquiteNumber score) {
+		if (aligner==null)
+			return;
+		int firstSite = 0;
+		int lastSite = data.getNumChars()-1;
+		int numChars = lastSite - firstSite+1;
+		
+		long[] extracted1 = new long[numChars];
+		long[] extracted2 = new long[numChars];
+		
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[ic] = data.getState(ic, it1);
+			extracted2[ic] = data.getState(ic, it2);
+		}
+		MesquiteNumber alignScore = new MesquiteNumber();
+  		CategoricalState state = (CategoricalState)data.makeCharacterState();
+		aligner.alignSequences(extracted1, extracted2, false, alignScore);
+
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[lastSite-ic] = DNAState.complement(data.getState(ic, it1));
+		}
+		MesquiteNumber alignRCScore = new MesquiteNumber();
+		aligner.alignSequences(extracted1, extracted2, false, alignRCScore);
+		alignScore.divideBy(alignRCScore);
+		score.setValue(alignScore);
+
+   	 }
+	   /*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return -100;  
+   }
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Align Score/RC Align Score To Ref.";  
+	 }
+	/*.................................................................................................................*/
+	 public String getScoreName() {
+	return "Alignment Score / Reverse Complement Alignment Score";  
+	 }
+		/*.................................................................................................................*/
+	 public String getExplanation() {
+		 String s = super.getExplanation();  
+		 return s+ " The score for each taxon is the cost of aligning that taxon's sequence against the reference taxon using Mesquite's default pairwise aligner, divided by the score for aligning the reverse complement of the sequence against the reference.  Scores  greater than one mean that alignment is better if one of the sequences is reverse complemented .";
+	 }
+	  	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+  	 
+}
+
+
+
diff --git a/Source/mesquite/align/AlignSequences/AlignSequences.java b/Source/mesquite/align/AlignSequences/AlignSequences.java
new file mode 100644
index 0000000..f17f762
--- /dev/null
+++ b/Source/mesquite/align/AlignSequences/AlignSequences.java
@@ -0,0 +1,231 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.AlignSequences;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public class AlignSequences extends MolecDataEditorInit {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(MultipleSequenceAligner.class, getName() + " needs a module to calculate alignments.",
+		"The sequence aligner is chosen in the Align Multiple Sequences submenu of the Matrix menu");
+	}
+	static boolean separateThreadDefault = false;
+	boolean separateThread = separateThreadDefault;
+	MolecularData data ;
+	MultipleSequenceAligner aligner;
+
+	MesquiteTable table;
+
+	MesquiteSubmenuSpec mss= null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		mss = addSubmenu(null, "Align Multiple Sequences", makeCommand("doAlign",  this));
+		mss.setList(MultipleSequenceAligner.class);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (!(data instanceof MolecularData)){
+			mss.setEnabled(false);
+			resetContainingMenuBar();
+			return;
+		}
+		this.table = table;
+		this.data = (MolecularData)data;
+		mss.setCompatibilityCheck(data.getStateClass());
+		resetContainingMenuBar();
+
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires module to align sequences", "[name of module]", commandName, "doAlign")) {
+			if (table!=null && data !=null){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				aligner= (MultipleSequenceAligner)hireNamedEmployee(MultipleSequenceAligner.class, arguments);
+				if (aligner!=null) {
+					boolean a = alterData(data, table);
+					if (a) {
+						table.repaintAll();
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+						data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));
+					}
+					if (!separateThread) {
+						fireEmployee(aligner);
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean integrateAlignment(long[][] alignedMatrix, MolecularData data, int icStart, int icEnd, int itStart, int itEnd){
+		if (alignedMatrix == null || data == null)
+			return false;
+		getProject().incrementProjectWindowSuppression();
+		boolean success = AlignUtil.integrateAlignment(alignedMatrix, data,  icStart,  icEnd,  itStart,  itEnd);
+		
+		/*
+		AlignUtil util = new AlignUtil();
+		Rectangle problem = null;
+		//alignedMatrix.setName("Aligned (" + data.getName() + ")");
+		boolean wasSel;
+		if (data.anySelected()) {
+			wasSel = true;
+		}
+		else {
+			wasSel = false;
+		}
+		logln("Alignment for " + (icEnd-icStart+1) + " sites; aligned to " + alignedMatrix.length + " sites.");
+		problem = util.forceAlignment(data, icStart, icEnd, itStart, itEnd, 0, alignedMatrix);
+		if (wasSel) {
+			data.deselectAll();
+			int numCharsOrig = icEnd-icStart+1;
+			if (alignedMatrix.length>numCharsOrig)
+				numCharsOrig = alignedMatrix.length;
+			for (int i = icStart; i<icStart + numCharsOrig; i++)
+				data.setSelected(i, true);
+
+		}
+		
+	*/
+		getProject().decrementProjectWindowSuppression();
+		if (separateThread)
+			fireEmployee(aligner);
+		return success;
+	}	
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table){
+		this.data = (MolecularData)data;
+		//to work, either nothing is selected (in which case it works on whole matrix), or 
+		// whole characters are selected (and they must be contiguous, AND more than one character
+//		if (table.anyCellSelectedAnyWay() && (!this.data.contiguousSelection() || !this.data.anySelected() || this.data.numberSelected()<=1)) {
+		if (table.anyCellSelectedAnyWay() && !table.contiguousColumnsSelected()) {
+			if (!MesquiteThread.isScripting()) {
+				if (AlertDialog.query(containerOfModule(), "Align entire matrix?", "Some data are currently selected, but not a block of data that can be aligned by Mesquite.  Data can be aligned only for the whole matrix or for a contiguous set of selected characters. If you wish to align only part of the matrix, then press Cancel and select a contiguous set of whole characters. ", "Align entire matrix", "Cancel"))
+					table.deselectAll();
+				else
+					return false;
+			}
+			else {
+				discreetAlert( "Data can be aligned only for the whole matrix or for a contiguous set of selected characters.  Please make sure that nothing in the matrix is selected, or that a contiguous set of characters (sites) is selected.");
+				return false;
+			}
+		}
+		//firstRowWithSelectedCell() != 
+		if (	aligner.permitSeparateThread() && (separateThread= !AlertDialog.query(containerOfModule(), "Separate Thread?", "Run on separate thread? (Beware! Don't close window before done)","No", "Separate"))){
+			AlignThread alignThread = new AlignThread(this, aligner, this.data, this.table);
+			alignThread.separateThread = true;
+			alignThread.start();
+		}
+		else {
+			AlignThread alignThread = new AlignThread(this, aligner, this.data, this.table);
+			alignThread.separateThread = false;
+			alignThread.run();  
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Align Sequences";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sends the selected sequence to be aligned." ;
+	}
+
+
+}
+
+class AlignThread extends Thread {
+	AlignSequences ownerModule;
+	MultipleSequenceAligner aligner;
+	MolecularData data;
+	MesquiteTable table;
+	boolean separateThread = false;
+	public AlignThread(AlignSequences ownerModule, MultipleSequenceAligner aligner, MolecularData data, MesquiteTable table){
+		this.aligner = aligner;
+		this.ownerModule = ownerModule;
+		this.data = data;
+		this.table = table;
+	}
+
+	public void run() {
+
+		MesquiteInteger firstRow = new MesquiteInteger();
+		MesquiteInteger lastRow = new MesquiteInteger();
+		MesquiteInteger firstColumn = new MesquiteInteger();
+		MesquiteInteger lastColumn = new MesquiteInteger();
+
+		boolean entireColumnsSelected = false;
+		int oldNumChars = data.getNumChars();
+		if (!table.singleCellBlockSelected(firstRow, lastRow,  firstColumn, lastColumn)) {
+			firstRow.setValue(0);
+			lastRow.setValue(data.getNumTaxa()-1);
+			firstColumn.setValue(0);
+			lastColumn.setValue(data.getNumChars()-1);
+		}
+		else 				
+			entireColumnsSelected =  table.isColumnSelected(firstColumn.getValue());
+		//NOTE: at present this deals only with whole character selecting, and with all taxa
+		long[][] m  = aligner.alignSequences((MCategoricalDistribution)data.getMCharactersDistribution(), null, firstColumn.getValue(), lastColumn.getValue(), firstRow.getValue(), lastRow.getValue());
+		ownerModule.integrateAlignment(m, data,  firstColumn.getValue(), lastColumn.getValue(), firstRow.getValue(), lastRow.getValue());
+		if (entireColumnsSelected) {
+			for (int ic = 0; ic<data.getNumChars(); ic++) 
+				data.setSelected(ic,ic>=firstColumn.getValue() && ic<=lastColumn.getValue()- (oldNumChars - data.getNumChars()));
+			table.selectColumns(firstColumn.getValue(),lastColumn.getValue()- (oldNumChars - data.getNumChars()));
+		}
+		if (separateThread)
+			data.notifyListeners(ownerModule, new Notification(MesquiteListener.DATA_CHANGED));
+		table.repaintAll();
+
+	}
+}
+
diff --git a/Source/mesquite/align/AlignToDropped/32alignToDropped.gif b/Source/mesquite/align/AlignToDropped/32alignToDropped.gif
new file mode 100644
index 0000000..bc357af
Binary files /dev/null and b/Source/mesquite/align/AlignToDropped/32alignToDropped.gif differ
diff --git a/Source/mesquite/align/AlignToDropped/64alignToDropped.gif b/Source/mesquite/align/AlignToDropped/64alignToDropped.gif
new file mode 100644
index 0000000..46766e8
Binary files /dev/null and b/Source/mesquite/align/AlignToDropped/64alignToDropped.gif differ
diff --git a/Source/mesquite/align/AlignToDropped/AlignToDropped.java b/Source/mesquite/align/AlignToDropped/AlignToDropped.java
new file mode 100644
index 0000000..6a06511
--- /dev/null
+++ b/Source/mesquite/align/AlignToDropped/AlignToDropped.java
@@ -0,0 +1,369 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.AlignToDropped; 
+
+
+import java.awt.*;
+
+import mesquite.align.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class AlignToDropped extends DataWindowAssistantI {
+	public String getFunctionIconPath(){  //path to icon explaining function, e.g. a tool
+		return getPath() + "alignToDropped.gif";
+	}
+	MesquiteTable table;
+	CategoricalData data;
+	TableTool alignDropTool;
+	int firstColumnTouched = -2;
+	int firstRowTouched = -2;
+	boolean defaultWarnCheckSum  =true;
+	MesquiteBoolean warnCheckSum = new MesquiteBoolean(defaultWarnCheckSum);
+	boolean defaultAllowNewGaps  =true;
+	MesquiteBoolean allowNewGaps = new MesquiteBoolean(defaultAllowNewGaps);
+	long originalCheckSum;
+	MesquiteInteger gapOpen = new MesquiteInteger();
+	MesquiteInteger gapExtend = new MesquiteInteger();
+	MesquiteInteger gapOpenTerminal = new MesquiteInteger();
+	MesquiteInteger gapExtendTerminal = new MesquiteInteger();
+	int[][] subs =null;
+	int alphabetLength;	 
+	PairwiseAligner aligner;
+	AlignUtil alignUtil = new AlignUtil();
+
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand touchCommand = MesquiteModule.makeCommand("alignDropTouched",  this);
+			touchCommand.setSuppressLogging(true);
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("alignDropDragged",  this);
+			dragCommand.setSuppressLogging(true);
+			MesquiteCommand dropCommand = MesquiteModule.makeCommand("alignDropDropped",  this);
+			dropCommand.setSuppressLogging(true);
+			alignDropTool = new TableTool(this, "alignToDropped", getPath(), "alignToDropped.gif", 13,14,"Pairwise Aligner: Aligns touched sequences to the sequence on which they are dropped.", "Aligns touched sequences to the sequence on which they are dropped.", touchCommand, dragCommand, dropCommand);
+			alignDropTool.setWorksOnRowNames(true);
+			//alignDropTool.setWorksAsArrowOnRowColumnNumbers(true);
+			alignDropTool.setPopUpOwner(this);
+			alignDropTool.setEmphasizeRowsOnMouseDrag(true);
+			((MesquiteWindow)containerOfModule()).addTool(alignDropTool);
+
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		setUseMenubar(false); //menu available by touching on button
+		addMenuItem("Gap Costs...", MesquiteModule.makeCommand("gapCosts", this));
+		addMenuItem("Substitution Costs...", MesquiteModule.makeCommand("subCosts", this));
+		addCheckMenuItem(null, "Check Data Integrity", makeCommand("toggleWarnCheckSum",  this), warnCheckSum);
+		addCheckMenuItem(null, "Allow New Internal Gaps", makeCommand("toggleAllowNewGaps",  this), allowNewGaps);
+		AlignUtil.getDefaultGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal); 
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Pairwise Aligner", "(A tool of a Character Matrix Window) Aligns touched sequences to the sequence on which they are dropped.", null, getPath() + "alignToDropped.gif"));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (warnCheckSum.getValue()!=defaultWarnCheckSum)
+			temp.addLine("toggleWarnCheckSum " + warnCheckSum.toOffOnString());
+		if (allowNewGaps.getValue()!=defaultAllowNewGaps)
+			temp.addLine("toggleAllowNewGaps " + allowNewGaps.toOffOnString());
+		temp.addLine("gapCosts " + gapOpen + " " + gapExtend + " " + gapOpenTerminal + " "+ gapExtendTerminal);
+
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i<alphabetLength; i++)
+			for (int j = 0; j<alphabetLength; j++) 
+				if (i!=j && i<=subs.length && j<=subs[i].length)
+					sb.append(" " + subs[i][j]);
+		temp.addLine("subCosts " + sb.toString());
+		//		if (subs==null)
+		//			subs = AlignUtil.getDefaultSubstitutionCosts(alphabetLength); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = (CategoricalData)data;
+		alphabetLength = ((CategoricalState)data.makeCharacterState()).getMaxPossibleState()+1;	 
+		if (subs==null)
+			subs = AlignUtil.getDefaultSubstitutionCosts(alphabetLength); 
+	}
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+	private boolean alignTouchedToDropped(int rowToAlign, int recipientRow){
+		MesquiteNumber score = new MesquiteNumber();
+		if (aligner==null) {
+			aligner = new PairwiseAligner(true,allowNewGaps.getValue(), subs,gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue(), alphabetLength);
+			//aligner.setUseLowMem(true);
+		}
+		if (aligner!=null){
+			//aligner.setUseLowMem(data.getNumChars()>aligner.getCharThresholdForLowMemory());
+			originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars()-1,rowToAlign, rowToAlign);
+			aligner.setAllowNewInternalGaps(allowNewGaps.getValue());
+			long[][] aligned = aligner.alignSequences((MCategoricalDistribution)data.getMCharactersDistribution(), recipientRow, rowToAlign,MesquiteInteger.unassigned,MesquiteInteger.unassigned,true,score);
+			if (aligned==null) {
+				logln("Alignment failed!");
+				return false;
+			}
+			logln("Align " + (rowToAlign+1) + " onto " + (recipientRow+1));
+			long[] newAlignment = Long2DArray.extractRow(aligned,1);
+
+			int[] newGaps = aligner.getGapInsertionArray();
+			if (newGaps!=null) 
+				alignUtil.insertNewGaps((MolecularData)data, newGaps, aligner.getPreSequenceTerminalFlaggedGap(), aligner.getPostSequenceTerminalFlaggedGap());
+			Rectangle problem = alignUtil.forceAlignment((MolecularData)data, 0, data.getNumChars()-1, rowToAlign, rowToAlign, 1, aligned);
+
+			((CategoricalData)data).examineCheckSum(0, data.getNumChars()-1,rowToAlign, rowToAlign, "Bad checksum; alignment has inappropriately altered data!", warnCheckSum, originalCheckSum);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	boolean alignJustTouchedRow = true;
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "AlignToDropped tool touched on row.", "[column touched] [row touched]", commandName, "alignDropTouched")) {
+			if (table!=null && data !=null){
+				alignJustTouchedRow = true;
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				firstColumnTouched= MesquiteInteger.fromString(arguments, io);
+				firstRowTouched= MesquiteInteger.fromString(arguments, io);
+
+				if (!table.rowLegal(firstRowTouched))
+					return null;
+				if (table.isRowSelected(firstRowTouched)) {
+					alignJustTouchedRow = false;
+				}
+				else{  // it's not select, so deselect everyone else
+					table.offAllEdits();
+					table.deselectAndRedrawAllSelectedRows();
+
+					table.selectRow(firstRowTouched);
+					table.redrawFullRow(firstRowTouched);
+				}
+				//shimmerVerticalOn();
+				// table.shimmerHorizontalOn(_);
+			}
+		}
+		else if (checker.compare(this.getClass(), "AlignToDropped tool dragged.", "[column dragged] [row dragged]", commandName, "alignDropDragged")) {
+			if (table!=null && data !=null && (firstRowTouched>=0)){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDragged = MesquiteInteger.fromString(arguments, io);
+				int rowDragged= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(rowDragged)) {
+					return null;
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "AlignToDropped tool dropped.", "[column dropped] [row dropped]", commandName, "alignDropDropped")) {
+
+			if (table!=null && data !=null && (firstRowTouched>=0)){
+				//	table.deEmphasizeRow(previousRowDragged);
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDropped = MesquiteInteger.fromString(arguments, io);
+				int rowDropped= MesquiteInteger.fromString(arguments, io);
+
+				if (!table.rowLegal(rowDropped))
+					return null;
+
+				if  (!alignJustTouchedRow){  // we are going to align all selected rows 
+					if (!table.isRowSelected(rowDropped)){     // we didn't drop it on a selected row
+						ProgressIndicator progIndicator = new ProgressIndicator(getProject(),getName(), "Aligning sequences", table.numRowsSelected(), true);
+						if (progIndicator!=null){
+							progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+							progIndicator.setOfferContinueMessageString("Are you sure you want to stop the alignment?");
+							progIndicator.start();
+						}
+						UndoReference undoReference = new UndoReference(data,this, new int[] {UndoInstructions.CHAR_ADDED});
+						int count = 0;
+						boolean changed = false;
+						int oldNumChars = data.getNumChars();
+						for (int it = 0; it<table.getNumRows(); it++) 
+							if (table.isRowSelected(it) && (it!=rowDropped)) {
+								if (alignTouchedToDropped(it,rowDropped))
+									changed = true;
+								if (progIndicator != null) {
+									if (progIndicator.isAborted()) {
+										progIndicator.goAway();
+										return null;
+									}
+									count++;
+									progIndicator.setText("Aligning " + data.getTaxa().getTaxonName(it) + " to " + data.getTaxa().getTaxonName(rowDropped));
+									progIndicator.setCurrentValue(count);
+								}
+							}
+						if (changed){
+							UndoReference uR = undoReference;
+							if (data.getDataLinkages() != null && data.getDataLinkages().size()==0)
+								uR = null;
+							data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, null, uR));
+							data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED, null, null));
+							if (oldNumChars!=data.getNumChars()){
+								data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null, null));
+								data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+							}
+						}
+						if (progIndicator != null)
+							progIndicator.goAway();
+
+					}
+				}			 
+				else if (firstRowTouched!=rowDropped) {
+					UndoReference undoReference = new UndoReference();
+					UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.CHAR_ADDED});
+					boolean changed=false;
+					int oldNumChars = data.getNumChars();
+					if (alignTouchedToDropped(firstRowTouched,rowDropped))
+						changed = true;
+					UndoReference uR=null;
+					if (undoInstructions!=null) {
+						undoInstructions.setNewData(data);
+						if (undoReference!=null && changed){
+							undoReference.setUndoer(undoInstructions);
+							undoReference.setResponsibleModule(this);
+							uR = undoReference;
+							if (data.getDataLinkages() != null && data.getDataLinkages().size()==0)
+								uR = null;
+						}
+					} 
+					if (changed) {
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, null, uR));
+						data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED, null, null));
+						if (oldNumChars!=data.getNumChars()){
+							data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null, null));
+							data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+						}
+					}
+				}
+				alignJustTouchedRow = true;
+			}
+		}
+
+		else  if (checker.compare(this.getClass(), "Toggles whether the data integrity is checked or not after each use.", "[on; off]", commandName, "toggleWarnCheckSum")) {
+			boolean current = warnCheckSum.getValue();
+			warnCheckSum.toggleValue(parser.getFirstToken(arguments));
+		}
+		else  if (checker.compare(this.getClass(), "Toggles whether the new gaps can be introduced into one or the other sequence.", "[on; off]", commandName, "toggleAllowNewGaps")) {
+			boolean current = allowNewGaps.getValue();
+			allowNewGaps.toggleValue(parser.getFirstToken(arguments));
+		}
+		else  if (checker.compare(this.getClass(), "Allows one to specify gap opening and extension costs.", "[open; extend]", commandName, "gapCosts")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int newGapOpen = MesquiteInteger.fromString(arguments, io);
+			int newGapExtend= MesquiteInteger.fromString(arguments, io);
+			int newGapOpenTerminal = MesquiteInteger.fromString(arguments, io);
+			int newGapExtendTerminal= MesquiteInteger.fromString(arguments, io);
+			if (newGapOpen<0 || newGapExtend<0 || !MesquiteInteger.isCombinable(newGapOpen) || !MesquiteInteger.isCombinable(newGapExtend) || newGapOpenTerminal<0 || newGapExtendTerminal<0 || !MesquiteInteger.isCombinable(newGapOpenTerminal) || !MesquiteInteger.isCombinable(newGapExtendTerminal)){
+				if (!MesquiteThread.isScripting())
+					AlignUtil.queryGapCosts(containerOfModule(),this,gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);
+			}
+			else{
+				gapOpen.setValue(newGapOpen);
+				gapExtend.setValue(newGapExtend);
+				gapOpenTerminal.setValue(newGapOpenTerminal);
+				gapExtendTerminal.setValue(newGapExtendTerminal);
+			}
+			resetAligner();
+			//parametersChanged(null);
+
+		}
+		else  if (checker.compare(this.getClass(), "Allows one to specify substitution costs.", "[matrix of costs]", commandName, "subCosts")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			if (subs==null)
+				subs = AlignUtil.getDefaultSubstitutionCosts(alphabetLength); 
+			boolean badCost = false;
+			for (int i = 0; i<alphabetLength && !badCost; i++)
+				for (int j = 0; j<alphabetLength && !badCost; j++) 
+					if (i!=j) {
+						int newSubCost = MesquiteInteger.fromString(arguments, io);
+						if (newSubCost<0 ||  !MesquiteInteger.isCombinable(newSubCost)) {
+							badCost = true;
+						} else
+							subs[i][j] = newSubCost;
+					}
+			if (badCost && !MesquiteThread.isScripting()){
+				Integer2DArray subArray = new Integer2DArray(subs);
+				if (AlignUtil.querySubCosts(containerOfModule(),this,subArray,data.getSymbols()))
+					subs = subArray.getMatrix();
+			}
+			resetAligner();
+			//parametersChanged(null);
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void resetAligner() {
+		if (aligner!=null) {
+			aligner.setGapCosts(gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue());
+			aligner.setSubsCostMatrix(subs);
+			aligner.setAllowNewInternalGaps(allowNewGaps.getValue());
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return -100;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Align To Dropped";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies an alignment tool that can be used on a set of sequences.  Sequences dropped by this tool on another sequence will be aligned to that other sequence (pairwise)." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/align/AlignToDropped/alignToDropped.gif b/Source/mesquite/align/AlignToDropped/alignToDropped.gif
new file mode 100644
index 0000000..29586a9
Binary files /dev/null and b/Source/mesquite/align/AlignToDropped/alignToDropped.gif differ
diff --git a/Source/mesquite/align/ClustalAlign/ClustalAlign.java b/Source/mesquite/align/ClustalAlign/ClustalAlign.java
new file mode 100644
index 0000000..12ec0c1
--- /dev/null
+++ b/Source/mesquite/align/ClustalAlign/ClustalAlign.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.ClustalAlign;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public class ClustalAlign extends ExternalSequenceAligner{
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}	
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getCitation()  {
+		return "Please remember to cite the version of ClustalW you used.";
+	}
+
+	/*.................................................................................................................*/
+	public String getHelpString() {
+		String s = "<i>You must use the command line version of Clustal, i.e., ClustalW.</i><br><br>"
+			+ " \nIn the Clustal Options field, place any Clustal options you wish to use.  For example, if you wished to change the"
+			+ " gap opening cost to 8 and the gap extension cost to 3, the options would be \"-gapopen=8 -gapext=3\".";
+		s+= "<br><br>Note that ClustalAlign has changed; you now need to specify the full path to Clustal, including the name of the program, not just the "
+			+ "directory in which the program resides.";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "ClustalW Align";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "ClustalW Align...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sends the selected sequence to ClustalW to align." ;
+	}
+	
+	public String getProgramName(){
+		 return "ClustalW";
+	 }
+	
+	/*.................................................................................................................*/
+	public String getProgramCommand(){
+		if (MesquiteTrunk.isWindows())
+			return StringUtil.protectForWindows(getProgramPath());
+		else
+			return StringUtil.protectForUnix(getProgramPath());
+	}
+	/*.................................................................................................................*/
+	public String getDefaultProgramOptions(){
+		return "";
+	}
+	
+	public void appendDefaultOptions(StringBuffer shellScript, String inFilePath, String outFilePath, MolecularData data) {
+	if (!MesquiteTrunk.isWindows())
+		shellScript.append("  -infile=" + StringUtil.protectForUnix(inFilePath) + " -outfile=" + StringUtil.protectForUnix(outFilePath) + " -align -output=pir ");
+	else
+		shellScript.append(" \\ -infile=" + StringUtil.protectForWindows(inFilePath) + " -outfile=" + StringUtil.protectForWindows(outFilePath) + " -align -output=pir ");
+	if (data instanceof ProteinData)
+		shellScript.append("-type=protein ");
+	else
+		shellScript.append("-type=dna ");
+	}
+
+	
+	public String getDNAExportInterpreter () {
+		return "#InterpretNBRFDNA";
+	}
+	public String getProteinExportInterpreter () {
+		return "#InterpretNBRFProtein";
+	}
+	public String getDNAImportInterpreter () {
+		return "#InterpretNBRFDNA";
+	}
+	public String getProteinImportInterpreter () {
+		return "#InterpretNBRFProtein";
+	}
+	public  String getExportExtension() {
+		return ".nbrf";
+	}
+	public  String getImportExtension() {
+		return ".nbrf";
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return -100;  
+	}
+
+}
+
diff --git a/Source/mesquite/align/ColorForAlignment/ColorForAlignment.java b/Source/mesquite/align/ColorForAlignment/ColorForAlignment.java
new file mode 100644
index 0000000..b71d445
--- /dev/null
+++ b/Source/mesquite/align/ColorForAlignment/ColorForAlignment.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.ColorForAlignment; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorForAlignment extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	Color Acolor, Ccolor, Gcolor, Tcolor, AGcolor, CTcolor;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		Acolor = Color.red;
+		Gcolor = Color.orange;
+		Ccolor = ColorDistribution.veryLightBlue;
+		Tcolor = Color.blue;
+		AGcolor = new Color((Acolor.getRed() + Gcolor.getRed())/2, (Acolor.getGreen() + Gcolor.getGreen())/2, (Acolor.getBlue() + Gcolor.getBlue())/2);
+		CTcolor = new Color((Tcolor.getRed() + Ccolor.getRed())/2, (Tcolor.getGreen() + Ccolor.getGreen())/2, (Tcolor.getBlue() + Ccolor.getBlue())/2);
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; 
+
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color For Aligning";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	public String getNameForMenuItem() {
+		return "Aligning Colors";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors the cells of a character matrix for easy of alignment.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+		if (!isActive())
+			return null;
+		return "Colored to show state of character";
+	}
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		if (data == null)
+			return null;
+		legend = null;
+		if (data instanceof DNAData){
+			legend = new ColorRecord[4];
+			legend[0] = new ColorRecord(Acolor, DNAData.getDefaultStateSymbol(0));
+			legend[1] = new ColorRecord(Ccolor, DNAData.getDefaultStateSymbol(1));
+			legend[2] = new ColorRecord(Gcolor, DNAData.getDefaultStateSymbol(2));
+			legend[3] = new ColorRecord(Tcolor, DNAData.getDefaultStateSymbol(3));
+		}
+		return legend;
+	}
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		if (data.getClass() == CategoricalData.class){
+			return "Colors of states may vary from character to character";
+		}
+		return null;
+	}
+
+	public Color getCellColor(int ic, int it){
+		if (data == null)
+			return null;
+		else {
+			if (data instanceof DNAData){
+				DNAData dData = (DNAData)data;
+				long state = dData.getState(ic, it) & CategoricalState.statesBitsMask;
+				if (state == DNAState.A)
+					return Acolor;
+				else if (state == DNAState.G)
+					return Gcolor;
+				else if (state == (DNAState.A | DNAState.G))
+					return AGcolor;
+				else if (state == DNAState.C)
+					return Ccolor;
+				else if (state == DNAState.T)
+					return Tcolor;
+				else if (state == (DNAState.C | DNAState.T))
+					return CTcolor;
+				return Color.lightGray;
+
+			}
+			return data.getColorOfStates(ic, it);
+		}
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/align/ColorGapsInCodingSequence/ColorGapsInCodingSequence.java b/Source/mesquite/align/ColorGapsInCodingSequence/ColorGapsInCodingSequence.java
new file mode 100644
index 0000000..65222cb
--- /dev/null
+++ b/Source/mesquite/align/ColorGapsInCodingSequence/ColorGapsInCodingSequence.java
@@ -0,0 +1,139 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.ColorGapsInCodingSequence; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorGapsInCodingSequence extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	protected DNAData data;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; //TODO: check success
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data instanceof DNAData)
+			this.data = (DNAData)data;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Highlight Gaps in Coding Regions";
+	}
+	public String getNameForMenuItem() {
+		return "Highlight Gaps in Coding Regions";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Highlights gaps if site has a codon position, or if both sites to either side have codon positions, and if sites to both sides have states or missing.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+		if (!isActive())
+			return null;
+			return "Cells colored to highlight gaps if site has a codon position, or if both sites to either side have codon positions, and if sites to both sides have states or missing";
+	}
+	ColorRecord[] legend;
+	/*.................................................................................................................*/
+	public ColorRecord[] getLegendColors(){
+		return null;
+		/*if (data == null)
+			return null;
+		legend = new ColorRecord[ProteinState.maxProteinState+1];
+		Color color;
+		for (int is = 0; is<=ProteinState.maxProteinState; is++) {
+			 if (emphasizeDegeneracy.getValue()) {
+				 color = ProteinData.getProteinColorOfState(is);
+				 color = ((DNAData)data).alterColorToDeemphasizeDegeneracy(is,color);
+			 } else
+				 color = ProteinData.getProteinColorOfState(is);
+			 legend[is] = new ColorRecord(color, ProteinData.getStateLongName(is));
+		}
+		return legend;
+	*/
+	}
+	/*.................................................................................................................*/
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		/*  		if (data.getClass() == CategoricalData.class){
+   			return "Colors of states may vary from character to character";
+   		}
+		 */
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public Color getCellColor(int ic, int it){
+
+		if (ic<0 || it<0)
+			return null;
+		if (data == null)
+			return null;
+			if (data.isInapplicable(ic, it) && (((data.isCoding(ic-1) && !data.isInapplicable(ic-1, it)) || (data.isCoding(ic-2) && !data.isInapplicable(ic-2, it))) && ((data.isCoding(ic+1)&& !data.isInapplicable(ic+1, it)) || (data.isCoding(ic+2)&& !data.isInapplicable(ic+2, it))))){
+				return Color.blue;
+			}
+		
+			
+			Color color = data.getColorOfStates(ic, it);
+			//return color;
+			return ColorDistribution.brighter(color, 0.15);
+		
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/align/ColorMisaligned/ColorMisaligned.java b/Source/mesquite/align/ColorMisaligned/ColorMisaligned.java
new file mode 100644
index 0000000..a734445
--- /dev/null
+++ b/Source/mesquite/align/ColorMisaligned/ColorMisaligned.java
@@ -0,0 +1,293 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.ColorMisaligned; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class ColorMisaligned extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	int[][] freqs;
+	double[][] scores;
+	int[][] offsets; 
+	long oldID = -1;
+	long oldStatesVersion = -1;
+	int distance = 2;
+	int widthHalf = 2;
+	long A = CategoricalState.makeSet(0);
+	long C = CategoricalState.makeSet(1);
+	long G = CategoricalState.makeSet(2);
+	long T = CategoricalState.makeSet(3);
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		boolean wasActive = isActive();
+		setActive(active);
+		if (isActive() && !wasActive){
+			calculateNums();
+
+		}
+		else {
+		}
+		resetContainingMenuBar();
+		return true; //TODO: check success
+	}
+	public void endJob(){
+		if (data!=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (this.data!=data && this.data!=null)
+			this.data.removeListener(this);
+		this.data = data;
+		data.addListener(this);
+		calculateNums();
+	}
+	double compareStateToSite(long state, int ic){
+		int notIn = 0;
+		if ((A & state) == 0L)  //state doesn't include A; therefore column's freq of A to cost
+			notIn += freqs[ic][0];
+		if ((C & state) == 0L) //likewise for C
+			notIn += freqs[ic][1];
+		if ((G & state) == 0L)
+			notIn += freqs[ic][2];
+		if ((T & state) == 0L)
+			notIn += freqs[ic][3];
+		int tot = freqs[ic][0] + freqs[ic][1] + freqs[ic][2] + freqs[ic][3];
+		if (tot == 0)
+			return 0;
+		return (notIn*1.0/(tot));
+	}
+
+	//give score of comparison of sequence of states around ic in taxon it to 
+	double score(DNAData dData, int ic, int it, int offset){
+		double s = 0;
+		for (int ic2 = ic-widthHalf; ic2<= ic + widthHalf; ic2++){ //surveying window
+			if (ic2>=0 && ic2<dData.getNumChars() && ic2+offset>=0 && ic2+offset<dData.getNumChars()){
+				long state = dData.getState(ic2, it);
+				s += compareStateToSite(state, ic2+offset);
+			}
+		}
+		return s;
+
+	}
+	boolean notCalculated = true;
+	public void calculateNums(){
+		notCalculated = true;
+		if (!isActive())
+			return;
+		if (data == null || !(data instanceof DNAData)) {
+			return;
+		}
+		DNAData dData = (DNAData)data;
+		if (freqs == null || freqs.length!=dData.getNumChars()){
+			freqs = new int[dData.getNumChars()][4];
+		}
+		if (offsets == null || offsets.length != dData.getNumChars() || offsets[0].length != dData.getNumTaxa()){
+			offsets = new int[dData.getNumChars()][dData.getNumTaxa()];
+			scores = new double[dData.getNumChars()][dData.getNumTaxa()];
+		}
+
+		//calculating frequencies for each character
+		for (int ic2 = 0; ic2 < dData.getNumChars(); ic2++)
+			for (int it2 = 0; it2 < dData.getNumTaxa(); it2++){
+				if ((A & dData.getState(ic2, it2)) != 0L)
+					freqs[ic2][0]++;
+				if ((C & dData.getState(ic2, it2)) != 0L)
+					freqs[ic2][1]++;
+				if ((G & dData.getState(ic2, it2)) != 0L)
+					freqs[ic2][2]++;
+				if ((T & dData.getState(ic2, it2)) != 0L)
+					freqs[ic2][3]++;
+			}
+		//filling score and offsets matrices
+		for (int ic = 0; ic<dData.getNumChars(); ic++){
+			for (int it = 0; it< dData.getNumTaxa(); it++){
+				double s = score(dData, ic, it, 0);
+				double best = s;
+				int o = 0;
+				for (int offset= -distance; offset<=distance; offset++){
+					if (ic+offset>=0 && ic+offset<dData.getNumChars()){
+						double sD = score(dData, ic, it,  offset);
+						if (sD < best) {
+							best = sD;
+							o = offset;
+						}
+					}
+				}
+				offsets[ic][it] = o;
+				scores[ic][it] = 0;
+				if (s != 0)
+					scores[ic][it] =  widthHalf+widthHalf - (best/s);
+			}
+		}
+		notCalculated = false;
+		table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		calculateNums();
+		if (table !=null)
+			table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Highlight Apparently Slightly Misaligned";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors aligned sequences to emphasize sections that seem slightly misaligned.";
+	}
+	/*.................................................................................................................*/
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		return null;
+		/*
+		if (legend == null) {
+			legend = new ColorRecord[6];
+			legend[0] = new ColorRecord(Color.white, "Apparently aligned");
+			legend[1] = new ColorRecord(Color.yellow, "Better shifted to right 1 site");
+			legend[2] = new ColorRecord(Color.red, "Better shifted to right 2 sites");
+			legend[3] = new ColorRecord(Color.green, "Better shifted to left 1 site");
+			legend[4] = new ColorRecord(Color.blue, "Better shifted to left 2 sited");
+			legend[5] = new ColorRecord(ColorDistribution.straw, "Inapplicable");
+		}
+		return legend;
+		*/
+	}
+	/*.................................................................................................................*/
+	public Color getCellColor(int ic, int it){
+		if (ic<0 || it<0 || notCalculated)
+			return null;
+
+		if (data == null || scores == null || offsets == null)
+			return null;
+		else if (data.isInapplicable(ic, it)){
+			return ColorDistribution.straw;
+		}
+		else {
+			if (!(data instanceof DNAData))
+				return Color.white;
+			DNAData	dData = (DNAData)data;
+			long state = dData.getState(ic, it);
+			if (offsets[ic][it] == 0) {
+				if (A == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfStatePale(0);
+				else if (C == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfStatePale(1);
+				else if (G == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfStatePale(2);
+				else if (T == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfStatePale(3);
+			}
+			else {
+				if (A == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfState(0);
+				else if (C == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfState(1);
+				else if (G == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfState(2);
+				else if (T == (state & CategoricalState.statesBitsMask))
+					return DNAData.getDNAColorOfState(3);
+			}
+			return ColorDistribution.veryLightGray;
+			/*
+			if (offsets[ic][it] == 0)
+				return Color.white;
+			if (offsets[ic][it] ==1)
+				return MesquiteColorTable.getYellowScale(scores[ic][it], 0, 5, false);
+			if (offsets[ic][it] >1)
+				return MesquiteColorTable.getRedScale(scores[ic][it], 0, 5, false);
+			if (offsets[ic][it] ==-1)
+				return MesquiteColorTable.getGreenScale(scores[ic][it], 0, 5, false);
+			if (offsets[ic][it] <-1)
+				return MesquiteColorTable.getBlueScale(scores[ic][it], 0, 5, false);
+			 */
+		}
+//		return Color.black;
+	}
+	/*.................................................................................................................*/
+	public String getCellString(int ic, int it){
+		if (ic<0 || it<0 || notCalculated)
+			return null;
+
+		if (data == null || scores == null || offsets == null)
+			return null;
+		else if (data.isInapplicable(ic, it)){
+			return "Gap";
+		}
+		else {
+			if (offsets[ic][it] == 0)
+				return "No clear misalignment";
+			if (offsets[ic][it] == 1)
+				return "Better shifted to right one site?";
+			if (offsets[ic][it] >= 2)
+				return "Better shifted to right two sites?";
+			if (offsets[ic][it] == -1)
+				return "Better shifted to left one site?";
+			if (offsets[ic][it] <= -2)
+				return "Better shifted to left two sites?";
+		}
+		return null;
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof CharacterData){
+			if (Notification.appearsCosmetic(notification))
+				return;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return true;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+}
+
+
diff --git a/Source/mesquite/align/MAFFTAlign/MAFFTAlign.java b/Source/mesquite/align/MAFFTAlign/MAFFTAlign.java
new file mode 100644
index 0000000..4613e66
--- /dev/null
+++ b/Source/mesquite/align/MAFFTAlign/MAFFTAlign.java
@@ -0,0 +1,268 @@
+package mesquite.align.MAFFTAlign;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.JLabel;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public class MAFFTAlign extends ExternalSequenceAligner implements ItemListener{
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}	
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getCitation()  {
+		return "Please remember to cite the version of MAFFT you used.";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "MAFFT Align";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "MAFFT Align...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sends the selected sequences to MAFFT to align." ;
+	}
+
+	public String getProgramName(){
+		return "MAFFT";
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("alignmentMethod".equalsIgnoreCase(tag)) {
+			alignmentMethod = MesquiteInteger.fromString(content);
+		}
+		else if ("alignmentMethodText".equalsIgnoreCase(tag)) {
+			alignmentMethodText = StringUtil.cleanXMLEscapeCharacters(content);
+		}
+		else if ("useMaxCores".equalsIgnoreCase(tag))
+			useMaxCores = MesquiteBoolean.fromTrueFalseString(content);
+
+		super.processSingleXMLPreference(tag, content);
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "alignmentMethod", alignmentMethod);  
+		StringUtil.appendXMLTag(buffer, 2, "alignmentMethodText", alignmentMethodText);  
+		StringUtil.appendXMLTag(buffer, 2, "useMaxCores", useMaxCores);  
+
+		return super.preparePreferencesForXML()+buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	public String getHelpString() {
+		String s =  " In the MAFFT Options field, place any MAFFT options you wish to use.  For example, if you wished to "
+				+ " invoke the linsi option (for more thorough alignment search), you would use \"--localpair --maxiterate 1000\".";
+		return s;   //linsi option:  --localpair --maxiterate 1000 --thread -1
+	}
+	/*.................................................................................................................*/
+	public String getHelpURL(){
+		return "http://mafft.cbrc.jp/alignment/software/manual/manual.html";
+	}
+
+	static int DEFAULTSUGGESTEDMETHOD=0;
+	static final int LINSI = 1;
+	static final int GINSI = 2;
+	static final int EINSI = 3; 
+	static final int FFTNSI2 = 4; 
+	static final int FFTNSI1000 = 5; 
+	static final int FFTNS2 =6; 
+	static final int FFTNS1 = 7; 
+	static final int NWNSI = 8; 
+	static final int NWNS2 = 9; 
+	static final int NWNSPT1 = 10; 
+	boolean useMaxCores = true;
+	int alignmentMethod = DEFAULTSUGGESTEDMETHOD;
+	String alignmentMethodText = "";
+	Checkbox useMaxThreadsCheckBox;
+	Choice alignmentMethodChoice;
+	SingleLineTextField alignmentTextField;
+
+	/*.................................................................................................................*/
+	public String getAlignmentText(int value) {
+		String alignmentText="";
+		switch (value) {
+		case LINSI:
+			alignmentText=" --localpair --maxiterate 1000 ";
+			break;
+		case GINSI:
+			alignmentText=" --globalpair --maxiterate 1000 ";
+			break;
+		case EINSI:
+			alignmentText=" --ep 0 --genafpair --maxiterate 1000 ";
+			break;
+		case FFTNSI2:
+			alignmentText=" --retree 2 --maxiterate 2 ";
+			break;
+		case FFTNSI1000:
+			alignmentText=" --retree 2 --maxiterate 1000 ";
+			break;
+		case FFTNS2:
+			alignmentText=" --retree 2 --maxiterate 0 ";
+			break;
+		case FFTNS1:
+			alignmentText=" --retree 1 --maxiterate 0 ";
+			break;
+		case NWNSI:
+			alignmentText=" --retree 2 --maxiterate 2 --nofft ";
+			break;
+		case NWNS2:
+			alignmentText=" --retree 2 --maxiterate 0 --nofft ";
+			break;
+		case NWNSPT1:
+			alignmentText=" --retree 1 --maxiterate 0 --nofft --parttree ";
+			break;
+		default: 
+			alignmentText="";
+		}
+		return alignmentText;
+	}
+/*.................................................................................................................*/
+	public void setAlignmentTextFromChoice() {
+		String alignmentText=getAlignmentText(alignmentMethodChoice.getSelectedIndex());
+		if (alignmentTextField!=null)
+			alignmentTextField.setText(alignmentText);
+	}
+	/*.................................................................................................................*/
+	public void itemStateChanged(ItemEvent e) {
+		if (e.getItemSelectable() == alignmentMethodChoice){
+			setAlignmentTextFromChoice();
+		}				
+	}
+/*.................................................................................................................*/
+	public void queryProgramOptions(ExtensibleDialog dialog) {
+		useMaxThreadsCheckBox = dialog.addCheckBox("use maximum number of computer cores", useMaxCores);
+		
+		alignmentMethodChoice = dialog.addPopUpMenu("Suggested Methods", new String[] {"Default",  "L-INS-i", "G-INSI-i", "E-INS-i", "FFT-NS-i 2", "FFT-NS-i 1000", "FFT-NS-2", "FFT-NS-1", "NW-NS-i", "NW-NS-2", "NW-NS-PartTree-1"}, alignmentMethod);
+		alignmentTextField = dialog.addTextField("Basic alignment method", alignmentMethodText, 40);
+		alignmentMethodChoice.addItemListener(this);
+		//linsi --localpair --maxiterate 1000
+		//ginsi --globalpair --maxiterate 1000
+		//einsi --ep 0 --genafpair --maxiterate 1000
+
+		//fftnsi2 --retree 2 --maxiterate 2
+		//fftnsi1000 --retree 2 --maxiterate 1000
+		//fftns2 --retree 2 --maxiterate 0
+		//fftns1--retree 1 --maxiterate 0
+		//nwnsi --retree 2 --maxiterate 2 --nofft
+		//nwns2 --retree 2 --maxiterate 0 --nofft
+		//nwnsPT1 --retree 1 --maxiterate 0 --nofft --parttree
+
+	}
+	/*.................................................................................................................*/
+	public void processQueryProgramOptions(ExtensibleDialog dialog) {
+		useMaxCores = useMaxThreadsCheckBox.getState();
+		int temp = alignmentMethodChoice.getSelectedIndex();
+		if (temp>=0)
+			alignmentMethod = temp;
+		alignmentMethodText = alignmentTextField.getText();
+		storePreferences();
+
+	}
+
+	/*.................................................................................................................*/
+	public String getQueryProgramOptions() {
+		String options = "";
+		if (useMaxCores)
+			options+=" --thread -1 ";
+		options += " " + alignmentMethodText + " ";
+		return options;
+	}
+
+	/*.................................................................................................................*/
+	public String getProgramCommand(){
+		if (MesquiteTrunk.isWindows())
+			return "call " + StringUtil.protectForWindows(getProgramPath());
+		else
+			return StringUtil.protectForUnix(getProgramPath());
+	}
+	public boolean programOptionsComeFirst(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getDefaultProgramOptions(){
+		return "";
+	}
+
+	public void appendDefaultOptions(StringBuffer shellScript, String inFilePath, String outFilePath, MolecularData data) {
+		if (!MesquiteTrunk.isWindows())
+			shellScript.append("  " + StringUtil.protectForUnix(inFilePath) + " > " + StringUtil.protectForUnix(outFilePath));
+		else
+			shellScript.append(" --out " + StringUtil.protectForUnix(outFilePath) + " " + StringUtil.protectForUnix(inFilePath));  
+	}
+
+
+	public String getDNAExportInterpreter () {
+		return "#InterpretFastaDNA";
+	}
+	public String getProteinExportInterpreter () {
+		return "#InterpretFastaProtein";
+	}
+	public String getDNAImportInterpreter () {
+		return "#InterpretFastaDNA";
+	}
+	public String getProteinImportInterpreter () {
+		return "#InterpretFastaProtein";
+	}
+	public  String getExportExtension() {
+		return ".fas";
+	}
+	public  String getImportExtension() {
+		return ".fas";
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+}
diff --git a/Source/mesquite/align/MultiBlockSplitter/32CrossHair.gif b/Source/mesquite/align/MultiBlockSplitter/32CrossHair.gif
new file mode 100644
index 0000000..f1a710c
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/32CrossHair.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitter.gif b/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitter.gif
new file mode 100644
index 0000000..953b1c6
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitter.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitterOption.gif b/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitterOption.gif
new file mode 100644
index 0000000..fa22e65
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/32MultiBlockSplitterOption.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/64CrossHair.gif b/Source/mesquite/align/MultiBlockSplitter/64CrossHair.gif
new file mode 100644
index 0000000..d8d5260
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/64CrossHair.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitter.gif b/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitter.gif
new file mode 100644
index 0000000..aa528df
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitter.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitterOption.gif b/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitterOption.gif
new file mode 100644
index 0000000..01b8ba4
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/64MultiBlockSplitterOption.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/CrossHair.gif b/Source/mesquite/align/MultiBlockSplitter/CrossHair.gif
new file mode 100644
index 0000000..8c2b206
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/CrossHair.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.gif b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.gif
new file mode 100644
index 0000000..45733a3
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.gif differ
diff --git a/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.java b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.java
new file mode 100644
index 0000000..c584e05
--- /dev/null
+++ b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitter.java
@@ -0,0 +1,473 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.MultiBlockSplitter;
+
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public  class MultiBlockSplitter extends MultiBlockMoveBase {
+	protected MultiBlockTool moveTool;
+	CellBlock leftCellBlock =null;
+	CellBlock rightCellBlock =null;
+
+	boolean defaultMoveWholeSequenceOnOneSide = false;
+	MesquiteBoolean moveWholeSequenceOnOneSide =new MesquiteBoolean(defaultMoveWholeSequenceOnOneSide);
+
+	protected int endOfLeftBlockAtTouch = 0;
+	protected int startOfRightBlockAtTouch = 0;
+
+
+	public Class getDutyClass() {
+		return MultiBlockSplitter.class;
+	}
+	public String getDutyName() {
+		return "Multi Block Splitter";
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand touchCommand = MesquiteModule.makeCommand("moveTouchCell",  this);
+			touchCommand.setSuppressLogging(true);
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("moveDragCell",  this);
+			dragCommand.setSuppressLogging(true);
+			MesquiteCommand dropCommand = MesquiteModule.makeCommand("moveDropCell",  this);
+			dropCommand.setSuppressLogging(true);
+			moveTool = new MultiBlockTool(this, "multiBlockSplitter", getPath(), "MultiBlockSplitter.gif", 8,8,"CrossHair.gif",8,8,"Splits multiple sequences","This tool splits and moves blocks of sequences for manual alignment.", touchCommand, dragCommand, dropCommand);
+			setOptionTools();
+			moveTool.setDeselectIfOutsideOfCells(false);
+			moveTool.setAcceptsOutsideDrops(true);
+			moveTool.setOptionImageFileName( "multiBlockSplitterOption.gif", 8, 8);
+
+			((MesquiteWindow)containerOfModule()).addTool(moveTool);
+			moveTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching on button
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		addBasicMultiSequenceMenuItems();
+		addCheckMenuItem(null, "Move full sequences on each side", makeCommand("toggleAllOnSide",  this), moveWholeSequenceOnOneSide);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void addExtraSnapshotItems(Snapshot temp) {
+		if (moveWholeSequenceOnOneSide.getValue()!=defaultMoveWholeSequenceOnOneSide)
+			temp.addLine("toggleAllOnSide " + moveWholeSequenceOnOneSide.toOffOnString());
+	}
+	/*.................................................................................................................*/
+	public void setOptionTools(){
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveLeft(){
+		if (leftCellBlock==null || rightCellBlock==null)
+			return false;
+		return (!leftCellBlock.isLocked()&&leftCellBlock.getCurrentLeftMovement()<leftCellBlock.getMaxLeftMovement());
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveRight(){
+		if (leftCellBlock==null || rightCellBlock==null)
+			return false;
+		return (!rightCellBlock.isLocked()&&rightCellBlock.getCurrentRightMovement()<rightCellBlock.getMaxRightMovement());
+	}
+	public void clearBetweenSelection() {
+		table.clearBetweenColumnSelection();
+		table.clearBetweenRowSelection();
+		table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSelectedBlock(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSequenceToLeft(){
+		return moveWholeSequenceOnOneSide.getValue();
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSequenceToRight(){
+		return moveWholeSequenceOnOneSide.getValue();
+	}
+	/*.................................................................................................................*
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	public void initialize(MesquiteTable table, CharacterData data) {
+		leftCellBlock = new CellBlock((CategoricalData)data, table);
+		leftCellBlock.setLeft(true);
+		leftCellBlock.setRight(false);
+		rightCellBlock = new CellBlock((CategoricalData)data, table);
+		rightCellBlock.setRight(true);
+		rightCellBlock.setLeft(false);
+
+	}
+	/*.................................................................................................................*/
+	protected void stopMoving() {
+		table.clearBetweenColumnSelection();
+		super.stopMoving();
+	}
+	/*.................................................................................................................*/
+	void switchBlocks(boolean switchToRight) {
+		if (switchToRight) {
+			if (!rightCellBlock.isLocked()) {
+				leftCellBlock.restoreCharBlock(dataChanged);
+				currentBlock = rightCellBlock;
+				if (leftEdge)
+					effectiveFirstColumnTouched = firstColumnTouched;
+				else
+					effectiveFirstColumnTouched = firstColumnTouched+1;
+				currentlyMovingRight = true;
+			}
+		} else {
+			if (!leftCellBlock.isLocked()) {
+				rightCellBlock.restoreCharBlock(dataChanged);
+				currentBlock = leftCellBlock;
+				if (leftEdge)
+					effectiveFirstColumnTouched = firstColumnTouched-1;
+				else
+					effectiveFirstColumnTouched = firstColumnTouched;
+				currentlyMovingRight = false;
+			}
+		}
+		currentMoveFromOriginal = 0;
+
+	}
+	/*.................................................................................................................*/
+	public void checkSwitchBlocks(int moveFromOriginal) {
+
+		if (canMoveRight() && moveFromOriginal>0 &&  !currentlyMovingRight) {  //was dragging left, now switch to dragging right
+			switchBlocks(true);
+		}
+		else if (canMoveLeft() && moveFromOriginal<0 && currentlyMovingRight) {  //was dragging right, now switch to dragging left
+			switchBlocks(false);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public void addCharactersToBlocks(int added, boolean toStart) {
+		leftCellBlock.addCharacters(Math.abs(added),toStart);
+		rightCellBlock.addCharacters(Math.abs(added),toStart);
+	}
+
+	/*.................................................................................................................*/
+	protected void redrawTable() {
+		table.redrawOldAndNewBlocks(currentBlock.getPreviousFirstCharInBlock(), currentBlock.getPreviousLastCharInBlock(), currentBlock.getCurrentFirstCharInBlock(), currentBlock.getCurrentLastCharInBlock(), currentBlock.getWhichTaxa(),false);
+	}
+	/*.................................................................................................................*/
+	public void resetBlocks() {
+		leftCellBlock.reset();
+		rightCellBlock.reset();
+	}
+	public  void getFirstAndLastSequences(boolean optionDown){
+		if (!optionDown) {
+			firstSequenceInBlock = table.getStartBetweenRowSelection();
+			lastSequenceInBlock = table.getEndBetweenRowSelection();
+		}
+		else {
+			firstSequenceInBlock = 0;
+			lastSequenceInBlock = data.getNumTaxa()-1;
+		}
+	}
+	public  Bits getWhichTaxa(boolean optionDown){
+		Bits whichTaxa = new Bits(data.getNumTaxa());
+		for (int it=table.getStartBetweenRowSelection(); it<=table.getEndBetweenRowSelection(); it++)
+			whichTaxa.setBit(it);
+		if (optionDown) 
+			whichTaxa.invertAllBits();
+		return whichTaxa;
+
+	}
+
+	/*.................................................................................................................*/
+	public boolean findBlocks(boolean optionDown) {
+		MesquiteInteger firstInBlock= new MesquiteInteger();
+		MesquiteInteger lastInBlock= new MesquiteInteger();
+		MesquiteBoolean cellHasInapplicable = new MesquiteBoolean(false);
+		MesquiteBoolean leftIsInapplicable = new MesquiteBoolean(false);
+		MesquiteBoolean rightIsInapplicable = new MesquiteBoolean(false);
+		int startOfBlock = table.numColumnsTotal;
+		int endOfBlock = 0;
+
+		leftCellBlock.setWhichTaxa(table.getStartBetweenRowSelection(), table.getEndBetweenRowSelection());
+		if (optionDown)
+			leftCellBlock.reverseWhichTaxa();
+		leftCellBlock.getCellBlock(endOfLeftBlockAtTouch, endOfLeftBlockAtTouch, leftCellBlock.getWhichTaxa(), firstInBlock, lastInBlock,  wholeSelectedBlock(), wholeSequenceToLeft(), wholeSequenceToRight(), cellHasInapplicable, leftIsInapplicable, rightIsInapplicable);
+		startOfBlock = MesquiteInteger.minimum(startOfBlock,firstInBlock.getValue());
+		rightCellBlock.setWhichTaxa(table.getStartBetweenRowSelection(), table.getEndBetweenRowSelection());
+		if (optionDown)
+			rightCellBlock.reverseWhichTaxa();
+		rightCellBlock.getCellBlock(startOfRightBlockAtTouch,startOfRightBlockAtTouch, rightCellBlock.getWhichTaxa(), firstInBlock, lastInBlock,  wholeSelectedBlock(), wholeSequenceToLeft(), wholeSequenceToRight(), cellHasInapplicable, leftIsInapplicable, rightIsInapplicable);
+		endOfBlock = MesquiteInteger.maximum(endOfBlock,lastInBlock.getValue());
+
+		if (rightIsInapplicable.getValue()&& leftIsInapplicable.getValue()) {
+			firstColumnTouched = -1;
+			return false;
+		}
+		if (leftIsInapplicable.getValue()){
+			leftCellBlock.setLocked(true);
+			currentlyMovingRight=true;
+		}
+		if (rightIsInapplicable.getValue()) {
+			rightCellBlock.setLocked(true);
+			currentlyMovingRight=false;
+		}
+
+		leftCellBlock.setAllBlocks(startOfBlock, firstColumnTouched, firstSequenceInBlock, lastSequenceInBlock);
+		rightCellBlock.setAllBlocks(firstColumnTouched+1, endOfBlock, firstSequenceInBlock, lastSequenceInBlock);
+		leftCellBlock.setMaximumMovements();
+		rightCellBlock.setMaximumMovements();
+
+		if (currentlyMovingRight)
+			currentBlock=rightCellBlock;
+		else
+			currentBlock = leftCellBlock;
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public void getSplitRows(MesquiteInteger top, MesquiteInteger bottom, int row, int percentVertical, boolean onDrop) {
+		if (row == table.getMatrixPanel().BEYONDMATRIX) row = table.numRowsTotal-1;
+		if (row<0) row=0;
+		int topRow = firstRowTouched;
+		int bottomRow = row;
+		if (firstRowTouched<row){ // we've gone down;
+			topRow = firstRowTouched;
+			bottomRow = row;
+			if (firstTouchPercentVertical>60)
+				topRow++;
+			if (percentVertical<40)
+				bottomRow--;
+		}
+		else if (firstRowTouched>row){ // we've gone up;
+			topRow = row;
+			bottomRow = firstRowTouched;
+			if (firstTouchPercentVertical<40)
+				bottomRow--;
+			if (percentVertical>60)
+				topRow++;
+		} 
+		else if (!onDrop)
+			if (firstTouchPercentVertical < percentVertical){
+				if (firstTouchPercentVertical>60)
+					topRow++;
+				if (percentVertical<40)
+					bottomRow--;
+			}
+			else if (firstTouchPercentVertical > percentVertical){
+				if (firstTouchPercentVertical<40)
+					bottomRow--;
+				if (percentVertical>60)
+					topRow++;
+			}
+		if (topRow<0)
+			topRow=0;
+		if (bottomRow>=table.numRowsTotal)
+			bottomRow=table.numRowsTotal-1;
+		if (top!=null)
+			top.setValue(topRow);
+		if (bottom!=null)
+			bottom.setValue(bottomRow);
+	}
+	int previousDrawTop =-1;
+	int previousDrawBottom=-1 ;
+
+	/*.................................................................................................................*/
+	public boolean mouseDown(boolean optionDown, boolean shiftDown) {
+		checkCurrentBlockIntegrity(table,data);
+		effectiveFirstColumnTouched = firstColumnTouched;
+		endOfLeftBlockAtTouch = firstColumnTouched;
+		startOfRightBlockAtTouch = firstColumnTouched;
+
+		betweenCells = false;
+		leftEdge = false;
+		rightEdge = false;
+		if (firstTouchPercentHorizontal<=edgePercent) {  //at far left edge of cell
+			endOfLeftBlockAtTouch = firstColumnTouched-1;
+			leftEdge = true;
+			firstColumnTouched --;
+			currentlyMovingRight=true;
+			betweenCells=true;
+		} else if (firstTouchPercentHorizontal>=(100-edgePercent)) {  //at far right edge of cell
+			startOfRightBlockAtTouch = firstColumnTouched+1;
+			rightEdge = true;
+			currentlyMovingRight=false;
+			betweenCells=true;
+		}
+
+		if (table.inBetweenSelectionRowColumns(firstColumnTouched, firstRowTouched)) {  //then we are in the selected part between columns, about to start a move, if possible
+			choosingNewSelection = false;
+			if (!prepareToMoveMultiSequences(optionDown)){
+				currentlyMoving=false;
+				return false;
+			}
+		}	else {
+			choosingNewSelection = true;
+			table.deselectAll();
+			previousDrawTop = -1;
+			previousDrawBottom = -1;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDragged(int columnDragged, int rowDragged,	int percentHorizontal, int percentVertical) {
+		if (choosingNewSelection) {
+			MesquiteInteger topRow = new MesquiteInteger();
+			MesquiteInteger bottomRow = new MesquiteInteger();
+			getSplitRows(topRow, bottomRow, rowDragged, percentVertical, false);
+
+			if (topRow.isCombinable() && bottomRow.isCombinable()) {
+				if (previousDrawTop>0 && previousDrawBottom>0) {
+					if (previousDrawTop<topRow.getValue())
+						table.redrawBlock(firstColumnTouched, previousDrawTop, firstColumnTouched+1, topRow.getValue()-1);
+					if (previousDrawBottom>bottomRow.getValue())
+						table.redrawBlock(firstColumnTouched, bottomRow.getValue()+1, firstColumnTouched+1, previousDrawBottom);
+				}
+				Graphics g = table.getMatrixPanel().getGraphics();
+				if (g != null){
+					int x = table.getColumnX(firstColumnTouched)-MesquiteTable.BETWEENLINEWIDTH/2;
+					int y = table.getRowY(topRow.getValue()-1)+1;
+					int width = MesquiteTable.BETWEENLINEWIDTH;
+					int height =  table.getRowY(bottomRow.getValue()) - y;
+					g.setColor(Color.black);
+					g.fillRect(x, y, width, height);
+					previousDrawTop = topRow.getValue();
+					previousDrawBottom = bottomRow.getValue();
+				}
+
+			}
+			previousRowDragged = rowDragged;
+
+		} else if (currentlyMoving) {
+			dragMultiSequences(percentHorizontal,  rowDragged,  columnDragged);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDropped(int columnDropped, int rowDropped,	int percentHorizontal, int percentVertical) {
+		if (choosingNewSelection) {
+			if (rowDropped == table.getMatrixPanel().BEYONDMATRIX) rowDropped = table.numRowsTotal-1;
+			if (rowDropped<0) rowDropped=0;
+		} else {
+			table.deselectAllNotify();
+		}
+		if (!table.rowLegal(rowDropped)|| !table.columnLegal(columnDropped))
+			return false;
+		if (choosingNewSelection) {
+			table.setStartBetweenColumnSelection(firstColumnTouched);
+			table.setEndBetweenColumnSelection(firstColumnTouched);
+
+
+			MesquiteInteger topRow = new MesquiteInteger();
+			MesquiteInteger bottomRow = new MesquiteInteger();
+			getSplitRows(topRow, bottomRow, rowDropped, percentVertical, true);
+
+			if (topRow.isCombinable() && bottomRow.isCombinable() && topRow.getValue()<=bottomRow.getValue()) {
+				table.setStartBetweenRowSelection(topRow.getValue());
+				table.setEndBetweenRowSelection(bottomRow.getValue());
+				table.repaintAll();
+			}
+
+			choosingNewSelection=false;
+		} else if (currentlyMoving){
+			afterMoveMultiSequences();
+		} else stopMoving();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Toggles whether the entire sequences on one side are moved.", "[on = moveWholeSequenceOnOneSide; off]", commandName, "toggleAllOnSide")) {
+			moveWholeSequenceOnOneSide.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Splits multi-sequence block";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Splits blocks of multiple sequences." ;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+
+
+
+
+	public class MultiBlockTool extends TableTool {
+		MesquiteCursor crossHairCursor=null;
+		MesquiteCursor optionEdgeCursor=null;
+		MesquiteCursor optionBetweenSelectionCursor = null;
+
+
+		public MultiBlockTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String extraImageFileName, int extraHotX, int extraHotY, String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand dragCommand, MesquiteCommand droppedCommand) {
+			super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation, touchedCommand, dragCommand, droppedCommand);
+			this.initiator = initiator;
+			this.name = name;
+			setDeselectIfOutsideOfCells(true);
+			setHasTemporaryOptionCursor(true);
+			setHasTemporaryShiftCursor(true);
+
+
+			crossHairCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, extraImageFileName, extraHotX, extraHotY);
+			optionBetweenSelectionCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, "multiBlockSplitterOption.gif", 8, 8);
+
+		}
+		public void setOptionEdgeCursor(String extraImageFileName, int extraHotX, int extraHotY) {
+			optionEdgeCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, extraImageFileName, extraHotX, extraHotY);
+		}
+		public void turningOff(){
+			((MultiBlockSplitter)initiator).clearBetweenSelection();
+		}
+
+		public void cursorInCell(int modifiers, int column, int row, int regionInCellH, int regionInCellV, EditorPanel panel){
+			if (table.inBetweenSelection(column, row, regionInCellH, regionInCellV))  {
+				setCurrentStandardCursor(null);
+				if (optionBetweenSelectionCursor!=null && MesquiteEvent.optionKeyDown(modifiers)) {
+					setCurrentOptionCursor(optionBetweenSelectionCursor);
+				}
+			}
+			else {
+				setCurrentOptionCursor(crossHairCursor);
+				setCurrentStandardCursor(crossHairCursor);
+				if (optionEdgeCursor!=null) {
+					setCurrentOptionCursor(optionEdgeCursor);
+				}
+			}
+		}
+
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitterOption.gif b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitterOption.gif
new file mode 100644
index 0000000..140d6ff
Binary files /dev/null and b/Source/mesquite/align/MultiBlockSplitter/MultiBlockSplitterOption.gif differ
diff --git a/Source/mesquite/align/MuscleAlign/MuscleAlign.java b/Source/mesquite/align/MuscleAlign/MuscleAlign.java
new file mode 100644
index 0000000..c4cefc5
--- /dev/null
+++ b/Source/mesquite/align/MuscleAlign/MuscleAlign.java
@@ -0,0 +1,126 @@
+package mesquite.align.MuscleAlign;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public class MuscleAlign extends ExternalSequenceAligner{
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}	
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getCitation()  {
+		return "Please remember to cite the version of Muscle you used.";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Muscle Align";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Muscle Align...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sends the selected sequence to Muscle to align." ;
+	}
+	
+	public String getProgramName(){
+		 return "Muscle";
+	 }
+	
+	/*.................................................................................................................*/
+	public String getHelpString() {
+	  String s =  " In the Muscle Options field, place any Muscle options you wish to use.  For example, if you wished to change the"
+		  + " gap opening cost to 3 and the gap extension cost to 8, the options would be \"-gapopen -8.0  -gapextend -3.0\".";
+	  return s;
+	}
+
+	/*.................................................................................................................*/
+	public String getProgramCommand(){
+		if (MesquiteTrunk.isWindows())
+			return StringUtil.protectForWindows(getProgramPath());
+		else
+			return StringUtil.protectForUnix(getProgramPath());
+	}
+	/*.................................................................................................................*/
+	public String getDefaultProgramOptions(){
+		return "";
+	}
+	
+	public void appendDefaultOptions(StringBuffer shellScript, String inFilePath, String outFilePath, MolecularData data) {
+	if (!MesquiteTrunk.isWindows())
+		shellScript.append("  -in " + StringUtil.protectForUnix(inFilePath) + " -out " + StringUtil.protectForUnix(outFilePath));
+	else
+		shellScript.append("  -in " + StringUtil.protectForWindows(inFilePath) + " -out " + StringUtil.protectForWindows(outFilePath));
+	}
+
+	
+	public String getDNAExportInterpreter () {
+		return "#InterpretFastaDNA";
+	}
+	public String getProteinExportInterpreter () {
+		return "#InterpretFastaProtein";
+	}
+	public String getDNAImportInterpreter () {
+		return "#InterpretFastaDNA";
+	}
+	public String getProteinImportInterpreter () {
+		return "#InterpretFastaProtein";
+	}
+	public  String getExportExtension() {
+		return ".fas";
+	}
+	public  String getImportExtension() {
+		return ".fas";
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return -111;  
+	}
+
+}
diff --git a/Source/mesquite/align/Notes/Align Notes b/Source/mesquite/align/Notes/Align Notes
new file mode 100644
index 0000000..e3ea01f
--- /dev/null
+++ b/Source/mesquite/align/Notes/Align Notes	
@@ -0,0 +1,46 @@
+Align ToDo
+
+
+
+
+==============
+
+	
+	- speed up getCost
+	- test code
+
+	Basic PairwiseAligner:
+		- have preprocess cost matrix for DNA data
+		- deal with terminal gaps with lower cost
+		- give it access to a user-supplied cost matrix
+		- GUI for costs
+		- preferences
+		
+
+======
+Travis: 
+	- pickCosts is no longer used to set the basic costs.  That is now done by getDefaultCosts in AlignUtil
+	
+	- I've changed the code so that it copes with amino acid data (it didn't before).  e.g., alphabetLength
+	is now passed along; the substitution matrix produced by getDefaultCosts is now
+	of a size appropriate to the data
+	
+	- Ambiguity codes are now dealt with.  This requires different storage in the int[] A and int[]B.
+	The values in these arrays NO LONGER correspond to the A=0, C=1, G=2, T=3.  Instead, the values
+	here are simply int representations of the lower 32 bits of the state set.  
+	e.g., the following state sets will have the following integer values:
+		A = 1
+		C = 2
+		G = 4
+		T = 8
+		A or G = 5
+		
+	This requires that when two values are compared, a method is now used to calculate the subsitution cost.  
+	This function is  AlignUtil.getCost(subs,a,b,alphabetLength), and it figures out the ambiguity cost.
+	We should make this faster for DNA data by having a pre-processed subs matrix that is
+	16x16, but I just haven't managed to do that yet.
+	
+	- I commented out your "score is" logging as it was taking too long!
+	
+	- some of the modules I wrote (e.g., AlignMatch)  now use PairwiseAligner rather than a module.
+	
\ No newline at end of file
diff --git a/Source/mesquite/align/Notes/align.nex b/Source/mesquite/align/Notes/align.nex
new file mode 100644
index 0000000..0c89f01
--- /dev/null
+++ b/Source/mesquite/align/Notes/align.nex
@@ -0,0 +1,172 @@
+#NEXUS
+[written Tue May 02 21:58:45 MST 2006 by Mesquite  version 1.06+ (build h57) at em/192.168.1.110]
+BEGIN AUTHORS;
+AUTHOR  NAME =  David_Maddison CODE =  bembidion LASTSAVER;
+
+END;
+
+BEGIN TAXA;
+	TITLE Untitled_Taxa_Block;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 taxon_4 taxon_5 
+	;
+	IDS bembidion10a77cd018680 bembidion10a77cd018681 bembidion10a77cd018682 bembidion10a77cd018683 bembidion10a77cd018684 ;
+	BLOCKID bembidion10a77cd01872;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=23;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	taxon_1  ---ACG{C,G}TT--GTTGAACCGGGG
+
+	taxon_2  ---ACGAGTTGAA----------
+
+	taxon_3  ACGTT---GTACAAC--------
+
+	taxon_4  ACGTTGGTACAAC----------
+
+	taxon_5  -----------------------
+
+
+;
+
+
+	IDS  _  _  _ bembidion10a77cd33602801 bembidion10a77cd33602802 bembidion10a77cd33602803 bembidion10a77cd33602804 bembidion10a77cd33602805 bembidion10a77cd33602806 bembidion10a77cd33602807 bembidion10a77cd33602808 bembidion10a77cd33602809 bembidion10a77cd33602810 bembidion10a77cd33602811 bembidion10a77cd33602812 bembidion10a77cd33602813 bembidion10a77cd33602814 bembidion10a77cd33602815 bembidion10a77cd33602816 bembidion10a77cd33602817 bembidion10a77cd33602818 bembidion10a77cd33602819 bem [...]
+
+
+END;
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=7;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	taxon_1  C------
+
+	taxon_2  C------
+
+	taxon_3  -------
+
+	taxon_4  -------
+
+	taxon_5  -------
+
+
+;
+
+
+	IDS bembidion10a77d5a58420 bembidion10a77d5a58421 bembidion10a77d5a58422 bembidion10a77d5a58423 bembidion10a77d5a58424 bembidion10a77d5a58425 bembidion10a77d5a58426 ;
+
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  universal:  1 -  23;
+CODESET * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  universal:  1 -  7;
+
+
+END;
+
+BEGIN CHARCHANGEHISTORY;
+LINK CHARACTERS =  Untitled_Character_Matrix;
+LINK CHARACTERS =  Untitled_Character_Matrix;
+
+END;
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  unord:  1 -  23;
+TYPESET * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  unord:  1 -  7;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  'Jukes-Cantor':  1 -  7;
+ProbModelSet * UNTITLED  (CHARACTERS = Untitled_Character_Matrix)  =  'Jukes-Cantor':  1 -  7;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5103472236502170046 bembidion10a77cd01872;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 949177808083695603;
+			checksum 0 3286705137;
+			setID 1 3564779954115045874;
+			checksum 1 1310667400;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #949177808083695603 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 835 323;
+					setLocation 153 412;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.align.AlignToDropped.AlignToDropped.alignToDropped;
+					endTell;
+					setActive;
+					setTool mesquite.align.AlignToDropped.AlignToDropped.alignToDropped;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3;
+				endTell;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
+
diff --git a/Source/mesquite/align/Notes/bugs/bug.PairwiseAligner.nex b/Source/mesquite/align/Notes/bugs/bug.PairwiseAligner.nex
new file mode 100644
index 0000000..5f63631
--- /dev/null
+++ b/Source/mesquite/align/Notes/bugs/bug.PairwiseAligner.nex
@@ -0,0 +1,171 @@
+#NEXUS
+[written Sat Oct 13 09:50:16 MST 2007 by Mesquite  version 2.0+ (build j07) at dhcp-96875d2a.cals.arizona.edu/150.135.93.42 (David Maddison)]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=10;
+	TAXLABELS
+		Bemb_transversale_ID_2184 Bemb_transversale_NS_2158 Bemb_transversale_NS_2160 Bemb_transversale_UT_2183 Bemb_transversale_WY_2097 Bemb_transversale_ID_2164 Bemb_transversale_MT_2185 Bemb_transversale_UT_2251 Bemb_cf.transversale_CA_2321 Bemb_cf.transversale_CA_2318 
+	;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=73;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Bemb_transversale_ID_2184     ctgaagcccgtggtcggaaacggctactgggcaatgtagtgtttgggagagcccgtctaacccgagtactgtt
+
+	Bemb_transversale_NS_2158     cccgtggtcggaaacggctactgggcaatgtagtgtttgggaGAGCccgtctaacccgagtactgtt------
+
+	Bemb_transversale_NS_2160     ctgaagcccgtggtcggaaAcggctactgggcaatgtagtgtttgggagagcccgtctaacccgagtactgtt
+
+	Bemb_transversale_UT_2183     ctgaagcccgtggtcggaaAcggctactgggcMatgtagtgtttgggagagcccgtctaacccgagtactgtt
+
+	Bemb_transversale_WY_2097     ctgaagcccgtggtcggaaacggctactgggcaatgtagtgtttgggagagcccgtctaacccgagtactgtt
+
+	Bemb_transversale_ID_2164     gcccgtctaacccgagtactgttagcgtgtccaagtccttcttgAAGGGGGCcactcg---------------
+
+	Bemb_transversale_MT_2185     gcccgtctaacccgagtactgttagcgtgtccaagtccttcttgaaGGGgGCcactcg---------------
+
+	Bemb_transversale_UT_2251     gcccgtctaacccgagtactgttagcgtgtccaagtccttcttgaaGGGGGCcactcg---------------
+
+	Bemb_cf.transversale_CA_2321  gCccgtctaacCCgagtattgttagcgtgtccaagtccttcttgAAGGGGGCcactcg---------------
+
+	Bemb_cf.transversale_CA_2318  GCccgtctaacCCgagtattgttagcGtgtccaagtcctTCTTGAAGGGGGCcactcg---------------
+
+
+;
+
+
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  73;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  73;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  73;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 1931082895948101767;
+			tell It;
+				setSelected  6 -  10;
+				setDefaultOrder  14 18 19 20 22 13 17 21 8 5;
+				attachments ;
+			endTell;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 8552805928968270532;
+			checksum 0 3695288835 null;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #8552805928968270532 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					setSize 1513 387;
+					setLocation 5 81;
+					setFont Arial;
+					setFontSize 10;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleShowTaxonNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3 2 2;
+					subCosts  10 5 10 10 10 5 5 10 10 10 5 10;
+				endTell;
+				getEmployee #mesquite.chromaseq.ColorQuality.ColorQuality;
+				tell It;
+					toggleAmbiguities on;
+					toggleMarks on;
+				endTell;
+			endTell;
+		endTell;
+		newAssistant  #mesquite.basic.TextWindowMaker.TextWindowMaker;
+		tell It;
+			setText 'Pairwise aligner bug:^n^n	- drop taxa 6 through 10 on 5.  ^n^nNote the way the dragged sequences on the right are not aligned.';
+			getWindow;
+			tell It;
+				popOut;
+				setExplanationSize 0;
+				setAnnotationSize 0;
+				setFontIncAnnot 0;
+				setFontIncExp 0;
+				setSize 1041 290;
+				setLocation 76 636;
+				setFont Arial;
+				setFontSize 10;
+			endTell;
+			showWindow;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/align/Notes/clustal Option List b/Source/mesquite/align/Notes/clustal Option List
new file mode 100644
index 0000000..9abf812
--- /dev/null
+++ b/Source/mesquite/align/Notes/clustal Option List	
@@ -0,0 +1,71 @@
+clustalw option list:-
+                -help 
+                -check 
+                -options 
+                -align 
+                -newtree=filename 
+                -usetree=filename 
+                -newtree1=filename 
+                -usetree1=filename 
+                -newtree2=filename 
+                -usetree2=filename 
+                -bootstrap 
+                -tree 
+                -quicktree 
+                -convert 
+                -interactive 
+                -batch 
+                -infile=filename 
+                -profile1=filename 
+                -profile2=filename 
+                -type=protein OR dna
+                -profile 
+                -sequences 
+                -matrix=filename 
+                -dnamatrix=filename 
+                -negative 
+                -noweights 
+                -gapopen=f 
+                -gapext=f 
+                -endgaps 
+                -nopgap 
+                -nohgap 
+                -novgap 
+                -hgapresidues=string 
+                -maxdiv=n 
+                -gapdist=n 
+                -pwmatrix=filename 
+                -pwdnamatrix=filename 
+                -pwgapopen=f 
+                -pwgapext=f 
+                -ktuple=n 
+                -window=n 
+                -pairgap=n 
+                -topdiags=n 
+                -score=percent OR absolute
+                -transweight=f 
+                -seed=n 
+                -kimura 
+                -tossgaps 
+                -bootlabels=node OR branch
+                -debug=n 
+                -output=gcg OR gde OR pir OR phylip OR nexus OR fasta
+                -outputtree=nj OR phylip OR dist OR nexus
+                -outfile=filename 
+                -outorder=input OR aligned
+                -case=lower OR upper
+                -seqnos=off OR on
+                -seqno_range=off OR on
+                -range=string 
+                -nosecstr1 
+                -nosecstr2 
+                -secstrout=structure OR mask OR both OR none
+                -helixgap=n 
+                -strandgap=n 
+                -loopgap=n 
+                -terminalgap=n 
+                -helixendin=n 
+                -helixendout=n 
+                -strandendin=n 
+                -strandendout=n 
+Peziza:~ david$ 
diff --git a/Source/mesquite/align/Notes/coiLong.nex b/Source/mesquite/align/Notes/coiLong.nex
new file mode 100644
index 0000000..8ee234d
--- /dev/null
+++ b/Source/mesquite/align/Notes/coiLong.nex
@@ -0,0 +1,200 @@
+#NEXUS
+[written Sat May 06 13:12:01 MST 2006 by Mesquite  version 1.06+ (build h57) at Fume-Hood-Computer.local/169.254.176.45]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=5;
+	TAXLABELS
+		Bemb_rothfelsi_NC_1951 Bemb_antiquum_MO_1963 Bemb_rothfelsi_MO_1962 Bemb_rothfelsi_MO_1961 Bemb_rothfelsi_MO_1960 
+	;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "coiPseudoRootFull.nex"';
+	DIMENSIONS  NCHAR=1533;
+	FORMAT DATATYPE = DNA GAP = - MISSING = ?;
+	MATRIX
+	Bemb_rothfelsi_NC_1951  ----------------------------------------ttttggagcatgatcgggaataGtaggtActtctctaagAataCTAATTCGAGCAGAATTAGGAAACCCTGGCTCATTaatcggaGATGATCAAATTTATAATGTTATTGTAACTGCTCATGCTTTTGTAATAATTTTTTTTATAGTAATGCCAATTTTAATTGGAGGATTTGGAAATTGATTAGTTCCATTAATATTAGGAGCACCTGATATAGCCTTTCCtCGAATAAATAAtaTAAGATTCTGATTACTCCCTCCTTCATTAACTTTACTATTAATAAGTTCTATAGTAGAAAGAGGAGCTGGCACAGGTTGAACAGTGTATCCTCCACTAtcatCTTCAATTGCTCACAGAGGAGCATCCGTAGATCTAGCAATTTTTAGATTACATTTGGCAGGGGTATCTTCAATTTTAGGAGCTGTAAAT [...]
+
+	Bemb_antiquum_MO_1963   ----------------ggatattggaactttatattttatttttggagcatgatcaggaATAGTAGGAACTTCTTTAAGAATACTAATTCGAGCAGAATTAGGAAATCCGGGCTCATTAATTGGAGACGATCAAATTTATAATGTTATTGTAACTGCTCATGCTTTTGTAATAATTTTTTTTATAGTAATACCAATTTTAATTGGAGGATTTGGAAATTGATTAGTCCCATTAATATTAGGAGCACCAGATATAGCTTTCCCACGAATAAATAATATAAGATTTTGATTACTTCCTCCTTCATTAACTTTATTATTAATAAGCTCTATGGTAGAAAGAGGGGCTGGTACAGGCTGAACAGTATACCCACCCCTATCCTCTTCAATTGCCCATAGAGGGGCATCCGTAGACCTAGCAATTTTTAGATTACATTTAGCAGGGGTATCTTCAATTTTAGGAGCTGTAAAT [...]
+
+	Bemb_rothfelsi_MO_1962  -------------------------------------------------------------------------------------------------------------cTGGCTCaTTAATTtgAgat{C,T}atcAAATTTATAATGTTATTGTaacTgctcaTGCTTTTGTAAtactTTTTtta{A,T}a{A,G}tAA{A,T}gCcaa{C,T}t{A,T}ta{A,G}ttgGagGattggGAAattgttTaGTTCc{A,C}tTAatgtaagGagc{A,C}cc{C,T}g{A,C}tATAGCctt{C,T}cctCGAATAAATAA{C,T}aTAAGattCTGATTAct{C,G}cctCCTTCATTAACTTTACTATTAATAAGTTc{C,T}{A,C}tagtaGAAAGa{G,T}gagc{C,T}ggcac{A,C}{C,G}{C,G}tTGAACAgt{A,G}taCCCTCCACTa{A,T} [...]
+
+	Bemb_rothfelsi_MO_1961  ------------------------------------------------------------------------------------------------------------CctggctcaTTAAtttgAgat{C,T}atcAAATTTATAatgttATtgtaacTGCTCATGCTTTtgtaata{A,C}tttTTtta{A,T}a{A,G}tAa{A,T}gccaa{A,C}tt{C,T}{A,T}{A,G}tt{G,T}Ga{A,G}g{A,G}ttgggaaa{A,T}t{G,T}{G,T}ttag{C,T}Tcc{A,C}ttaa{A,T}g{G,T}aa{A,G}{G,T}agcacc{C,T}g{A,C}{C,T}aT{A,T}GCctttc{C,G}{G,T}cGAa{G,T}aAAtaa{C,T}ataag{A,T}tt{C,T}tGATTAct{C,G}c{C,G}{G,T}cc{G,T}TCATTA{A,G}{C,G}TTTACtatTAA{ [...]
+
+	Bemb_rothfelsi_MO_1960  -------------------------------------------------------------------------------------------------------------CTggctcaTTAAtTtGAgat{C,T}atcAAATTTAtAatgttattgtaacTGCTCATGCTTTTGTAAtactTTTTtta{A,T}a{A,G}taa{A,T}g{C,G}c{A,C}a{A,C}tt{C,T}a{A,G}ttgga{A,G}ga{A,T}tggGAAattg{G,T}tta{A,G}tt{C,T}c{A,C}ttaa{A,T}g{G,T}aa{A,G}g{A,G}{A,G}c{A,C}cc{C,T}ga{A,T}a{A,T}{A,T}gcc{C,T}t{C,T}cc{C,T}c{C,G}aataaaTaac{A,C}taa{A,G}{A,G}{A,T}t{C,T}{C,T}ga{A,T}tac{C,T}tcc{C,T}cc{C,T}tc{A,C}ttaac [...]
+
+
+;
+
+
+
+END;
+
+BEGIN CODONS;
+CODONPOSSET * UNTITLED  =  1: 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 258 261 264 267 270 273 276 279 282 285 288 291 294 297 300 303 306 309 312 315 318 321 324 327 330 333 336 339 342 345 348 351 354 357 360 363 366 369 372 37 [...]
+CODONPOSSET CodonPositions  =  1: 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 258 261 264 267 270 273 276 279 282 285 288 291 294 297 300 303 306 309 312 315 318 321 324 327 330 333 336 339 342 345 348 351 354 357 360 363 366 369 37 [...]
+
+CODESET * UNTITLED   =  universal:  1 -  1533;
+
+
+END;
+
+BEGIN paup;
+	outgroup Bemb_californicum_CA_1451 Bemb_concolor_NS_1470;
+
+END;
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =  unord PolyTcount =  MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  1 -  1533;
+
+	EXSET * UNTITLED  =  1 -  50 1479 -  1533;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Jukes-Cantor':  1 -  1533;
+END;
+
+BEGIN MacClade;
+	Version 4.0  87;
+	LastModified -1071261665;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 00011001110111100100010111 '4' '8'   Geneva '9' '216' '1'   all;
+	EditorPosition '70' '118' '643' '999';
+	TreeWindowPosition '46' '6' '809' '1230';
+	ListWindow Characters closed Geneva '9' '70' '45' '129' '406'   000;
+	ListWindow Taxa closed Geneva '9' '50' '10' '276' '490'   100000000;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartNames closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ChartWindowPosition '52' '30' '772' '1220';
+	StateNamesSymbols closed Geneva '9' '10' '50' '30' '148' '220';
+	WindowOrder  Data;
+	OtherSymbols & /   00 ? -;
+	Correlation '0' '0' '1000' '0' '0'   10011010;
+	Salmo 00000001;
+	EditorFile '4';
+	ExportHTML _ MOSS '100'   110000;
+	PrettyPrint 10;
+	EditorToolsPosition '720' '44' '115' '165';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'   1;
+	Calculations 0000001;
+	SummaryMode '0' '0'   0;
+	Charts  Geneva '9' (  normal )   0010;
+	NexusOptions '0' '0' '50'   001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (  normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'   1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'   1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'   1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'   0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'   1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'   Geneva '9' (  normal )   Geneva '10' (  normal )   Geneva '9' (  normal )   Geneva '9' (  normal )   Geneva '9' (  bold )   Geneva '9' (  normal )   Geneva '9' (  normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '1' '1' '1' '1' '0' '0' '-39' '4' '-40' '0' '1' '2' '1' '8' '0' '0' '0' '2'   1000111000000000000100000111000;
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 00;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'   00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'   100010101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'   1010;
+	BothTools '1';
+
+END;
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6370606309008394174;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 6733066121074379816;
+			checksum 0 2978122628;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #6733066121074379816 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 1484 556;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.align.AlignToDropped.AlignToDropped.alignToDropped;
+					endTell;
+					setActive;
+					setTool mesquite.align.AlignToDropped.AlignToDropped.alignToDropped;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges off;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWCharNames off;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3;
+				endTell;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/align/Notes/prot.nex b/Source/mesquite/align/Notes/prot.nex
new file mode 100644
index 0000000..23a5279
--- /dev/null
+++ b/Source/mesquite/align/Notes/prot.nex
@@ -0,0 +1,153 @@
+#NEXUS
+[written Sun Apr 30 12:16:37 MST 2006 by Mesquite  version 1.06+ (build h57) at david-maddisons-computer.local/192.168.0.4]
+
+BEGIN TAXA;
+	TITLE Untitled_Taxa_Block;
+	DIMENSIONS NTAX=3;
+	TAXLABELS
+		taxon_1 taxon_2 taxon_3 
+	;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=15;
+	FORMAT DATATYPE = Protein GAP = - MISSING = ?;
+	MATRIX
+	taxon_1  AGVLTT--GGVL---
+
+	taxon_2  HGEQPGVLTTGGMNI
+
+	taxon_3  MFGATACCTCEQRDM
+
+
+;
+
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  15;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  15;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  15;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 5649887706477911529;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 5596208106298272285;
+			checksum 0 3074286207;
+		endTell;
+		getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			showTaxa #5649887706477911529 #mesquite.lists.TaxonList.TaxonList;
+			tell It;
+				setTaxa #5649887706477911529;
+				getWindow;
+				tell It;
+					newAssistant  #mesquite.lists.DefaultTaxaOrder.DefaultTaxaOrder;
+					newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+					setSize 360 400;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.lists.TaxonListAnnotPanel.TaxonListAnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #5596208106298272285 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 699 286;
+					setLocation 113 176;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.ibeam;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.ibeam;
+					colorCells  #mesquite.charMatrices.ColorByState.ColorByState;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWithCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.align.AlignToDropped.AlignToDropped;
+				tell It;
+					gapCosts 8 3;
+				endTell;
+			endTell;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/align/RemoveAllGaps/RemoveAllGaps.java b/Source/mesquite/align/RemoveAllGaps/RemoveAllGaps.java
new file mode 100644
index 0000000..e81879e
--- /dev/null
+++ b/Source/mesquite/align/RemoveAllGaps/RemoveAllGaps.java
@@ -0,0 +1,92 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.RemoveAllGaps;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RemoveAllGaps extends MolecularDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+		if (!(cData instanceof MolecularData))
+			return false;
+		MolecularData data = (MolecularData)cData;
+		int oldNumChars = data.getNumChars();
+		data.removeCharactersThatAreEntirelyGaps(false);
+		logln("" + (oldNumChars-data.getNumChars()) +  " characters removed");
+/*		if (oldNumChars!=data.getNumChars()) {
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			data.notifyInLinked(new Notification(MesquiteListener.PARTS_DELETED));
+			return true;
+		}
+*/
+		return oldNumChars!=data.getNumChars();
+
+   	}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return -100;  
+     	}
+  	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Remove Gaps-Only Characters";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+    			return "Remove Gaps-Only Characters";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Removes all characters that are gaps only." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/align/ScrollToData/32scrollerLeft.gif b/Source/mesquite/align/ScrollToData/32scrollerLeft.gif
new file mode 100644
index 0000000..efb6f8a
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/32scrollerLeft.gif differ
diff --git a/Source/mesquite/align/ScrollToData/32scrollerRight.gif b/Source/mesquite/align/ScrollToData/32scrollerRight.gif
new file mode 100644
index 0000000..5d1e6a7
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/32scrollerRight.gif differ
diff --git a/Source/mesquite/align/ScrollToData/64scrollerLeft.gif b/Source/mesquite/align/ScrollToData/64scrollerLeft.gif
new file mode 100644
index 0000000..46afea4
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/64scrollerLeft.gif differ
diff --git a/Source/mesquite/align/ScrollToData/64scrollerRight.gif b/Source/mesquite/align/ScrollToData/64scrollerRight.gif
new file mode 100644
index 0000000..c7bfb7c
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/64scrollerRight.gif differ
diff --git a/Source/mesquite/align/ScrollToData/ScrollToData.java b/Source/mesquite/align/ScrollToData/ScrollToData.java
new file mode 100644
index 0000000..13dcfda
--- /dev/null
+++ b/Source/mesquite/align/ScrollToData/ScrollToData.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.ScrollToData;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.DataWindowAssistantI;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lib.table.TableTool;
+
+public class ScrollToData extends DataWindowAssistantI {
+	protected MesquiteTable table;
+	protected CharacterData  data;
+	protected ScrollToDataTool scrollTool;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getCompatibilityTest();
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("scrollDragCell",  this);
+			dragCommand.setSuppressLogging(true);
+			scrollTool = new ScrollToDataTool(this, "scrollerRight", getPath(), "scrollerRight.gif", 8,8,"Scrolls to next data cell","This tool scrolls to the next cell in the sequence with data.", MesquiteModule.makeCommand("scrollTouchCell",  this) , dragCommand, MesquiteModule.makeCommand("scrollDropCell",  this));
+			scrollTool.setDeselectIfOutsideOfCells(false);
+			scrollTool.setOptionImageFileName( "scrollerLeft.gif", 8, 8);
+
+			((MesquiteWindow)containerOfModule()).addTool(scrollTool);
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		return true;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (!(data instanceof CategoricalData))
+			return;
+		this.table = table;
+		this.data = data;
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Touched.", "[column touched] [row touched] [percent horizontal] [percent vertical] [modifiers]", commandName, "scrollTouchCell")) {
+		}
+		else if (checker.compare(this.getClass(), "Dragging", "[column dragged] [row dragged] [percent horizontal] [percent vertical] [modifiers]", commandName, "scrollDragCell")) {
+		}
+		else if (checker.compare(this.getClass(), "Dropping.", "[column dropped] [row dropped] [percent horizontal] [percent vertical] [modifiers]", commandName, "scrollDropCell")) {
+			if (table!=null && data !=null){
+				boolean optionDown = arguments.indexOf("option")>=0;
+				MesquiteInteger io = new MesquiteInteger(0);
+				int firstColumnTouched= MesquiteInteger.fromString(arguments, io);
+				int firstRowTouched= MesquiteInteger.fromString(arguments, io);
+
+				if (data.isInapplicable(firstColumnTouched, firstRowTouched)) {
+					if (optionDown) {
+						for (int ic = firstColumnTouched-1; ic>=0; ic--) {
+							if (!data.isInapplicable(ic, firstRowTouched)) {
+								table.scrollToColumn(ic);
+								break;
+							}
+						}
+					} else {
+						for (int ic = firstColumnTouched+1; ic<table.numColumnsTotal; ic++) {
+							if (!data.isInapplicable(ic, firstRowTouched)) {
+								table.scrollToColumn(ic);
+								break;
+							}
+						}
+
+					}
+				}
+			}
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public String getName() {
+		return "Scroll To Data";
+	}
+	public String getExplanation() {
+		return "Provides a tool that will scroll the data matrix to the next cell that contains data (i.e., that contains something other than a gap/inapplicable)";
+	}
+
+
+	public class ScrollToDataTool extends TableTool {
+
+		public ScrollToDataTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY,  String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand dragCommand, MesquiteCommand droppedCommand) {
+			super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation, touchedCommand, dragCommand, droppedCommand);
+			this.initiator = initiator;
+			this.name = name;
+			setDeselectIfOutsideOfCells(true);
+		}
+	}
+
+}
diff --git a/Source/mesquite/align/ScrollToData/scrollerLeft.gif b/Source/mesquite/align/ScrollToData/scrollerLeft.gif
new file mode 100644
index 0000000..6a68ec4
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/scrollerLeft.gif differ
diff --git a/Source/mesquite/align/ScrollToData/scrollerRight.gif b/Source/mesquite/align/ScrollToData/scrollerRight.gif
new file mode 100644
index 0000000..e3a2b66
Binary files /dev/null and b/Source/mesquite/align/ScrollToData/scrollerRight.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/32CrossHair.gif b/Source/mesquite/align/SelectedBlockMover/32CrossHair.gif
new file mode 100644
index 0000000..f1a710c
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/32CrossHair.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/32SelectedBlockMover.gif b/Source/mesquite/align/SelectedBlockMover/32SelectedBlockMover.gif
new file mode 100644
index 0000000..227f8cd
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/32SelectedBlockMover.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/64CrossHair.gif b/Source/mesquite/align/SelectedBlockMover/64CrossHair.gif
new file mode 100644
index 0000000..d8d5260
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/64CrossHair.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/64SelectedBlockMover.gif b/Source/mesquite/align/SelectedBlockMover/64SelectedBlockMover.gif
new file mode 100644
index 0000000..35297d7
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/64SelectedBlockMover.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/CrossHair.gif b/Source/mesquite/align/SelectedBlockMover/CrossHair.gif
new file mode 100644
index 0000000..8c2b206
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/CrossHair.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.gif b/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.gif
new file mode 100644
index 0000000..7042a12
Binary files /dev/null and b/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.gif differ
diff --git a/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.java b/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.java
new file mode 100644
index 0000000..aec3619
--- /dev/null
+++ b/Source/mesquite/align/SelectedBlockMover/SelectedBlockMover.java
@@ -0,0 +1,318 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.SelectedBlockMover;
+
+
+
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.align.lib.*;
+
+
+/*
+ * The block selector might be easier if it highlighted the block during
+the process of selection so that you can see more exactly which
+sequences you were including, but that's a very minor point and not
+critical.
+
+ * */
+
+/* ======================================================================== */
+public  class SelectedBlockMover extends MultiBlockMoveBase {
+	protected SelectedBlockTool moveTool;
+
+	boolean defaultSelectWholeSequences = false;
+	MesquiteBoolean selectWholeSequences =new MesquiteBoolean(defaultSelectWholeSequences);
+
+
+
+	public Class getDutyClass() {
+		return SelectedBlockMover.class;
+	}
+	public String getDutyName() {
+		return "Selected Block Mover";
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand touchCommand = MesquiteModule.makeCommand("moveTouchCell",  this);
+			touchCommand.setSuppressLogging(true);
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("moveDragCell",  this);
+			dragCommand.setSuppressLogging(true);
+			MesquiteCommand dropCommand = MesquiteModule.makeCommand("moveDropCell",  this);
+			dropCommand.setSuppressLogging(true);
+			moveTool = new SelectedBlockTool(this, "selectedBlockMover", getPath(), "SelectedBlockMover.gif", 8,8,"CrossHair.gif",8,8,"Moves a selected block of multiple sequences","This tool moves selected blocks of sequences for manual alignment.", touchCommand , dragCommand, dropCommand);
+			setOptionTools();
+			moveTool.setDeselectIfOutsideOfCells(false);
+			moveTool.setAcceptsOutsideDrops(true);
+			((MesquiteWindow)containerOfModule()).addTool(moveTool);
+			moveTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching on button
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		//addPopUpMenuItems();
+		addBasicMultiSequenceMenuItems();
+		addCheckMenuItem(null, "Select entire sequences", makeCommand("toggleWholeSequences",  this), selectWholeSequences);
+		return true;
+	}
+	public void initialize(MesquiteTable table, CharacterData data) {
+		currentBlock = new CellBlock((CategoricalData)data, table);
+		currentBlock.setRight(true);
+		currentBlock.setLeft(true);
+	}
+	/*.................................................................................................................*/
+	public void addExtraSnapshotItems(Snapshot temp) {
+		if (selectWholeSequences.getValue()!=defaultSelectWholeSequences)
+			temp.addLine("toggleWholeSequences " + selectWholeSequences.toOffOnString());
+	}
+	/*.................................................................................................................*/
+	public void setOptionTools(){
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveLeft(){
+		if (currentBlock==null)
+			return false;
+		return (!currentBlock.isLocked()&&currentBlock.getCurrentLeftMovement()<currentBlock.getMaxLeftMovement());
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveRight(){
+		if (currentBlock==null)
+			return false;
+		return (!currentBlock.isLocked()&&currentBlock.getCurrentRightMovement()<currentBlock.getMaxRightMovement());
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSelectedBlock(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSequence(){
+		return selectWholeSequences.getValue();
+	}
+	/*.................................................................................................................*/
+	protected void redrawTable() {
+		table.redrawOldAndNewBlocks(currentBlock.getPreviousFirstCharInBlock(), firstSequenceInBlock, currentBlock.getPreviousLastCharInBlock(), lastSequenceInBlock, currentBlock.getCurrentFirstCharInBlock(), firstSequenceInBlock, currentBlock.getCurrentLastCharInBlock(), lastSequenceInBlock,true);
+	}
+
+	/*.................................................................................................................*/
+	public  void getFirstAndLastSequences(boolean optionDown){
+		MesquiteInteger firstRow = new MesquiteInteger();
+		MesquiteInteger lastRow = new MesquiteInteger();
+		MesquiteInteger firstColumn = new MesquiteInteger();
+		MesquiteInteger lastColumn = new MesquiteInteger();
+
+		if (table.findBlockSurroundingCell(firstColumnTouched, firstRowTouched, firstRow,  lastRow,  firstColumn,  lastColumn) ) {
+			if (firstColumnTouched>=firstColumn.getValue() && firstColumnTouched<=lastColumn.getValue() && firstRowTouched>=firstRow.getValue() && firstRowTouched<=lastRow.getValue()){
+				firstSequenceInBlock = firstRow.getValue();
+				lastSequenceInBlock = lastRow.getValue();
+			}
+
+		}
+		else {
+			firstSequenceInBlock = MesquiteInteger.unassigned;
+			lastSequenceInBlock = MesquiteInteger.unassigned;
+		}
+	}
+	/*.................................................................................................................*/
+
+	public  Bits getWhichTaxa(boolean optionDown){
+		Bits whichTaxa = new Bits(data.getNumTaxa());
+		getFirstAndLastSequences(optionDown);
+		if (!MesquiteInteger.isCombinable(firstSequenceInBlock) || !MesquiteInteger.isCombinable(lastSequenceInBlock))
+			return null;
+		for (int it=firstSequenceInBlock; it<=lastSequenceInBlock; it++)
+			whichTaxa.setBit(it);
+		return whichTaxa;
+
+	}
+
+	/*.................................................................................................................*/
+	public  boolean acceptableSelection(){
+		MesquiteInteger firstRow = new MesquiteInteger();
+		MesquiteInteger lastRow = new MesquiteInteger();
+		MesquiteInteger firstColumn = new MesquiteInteger();
+		MesquiteInteger lastColumn = new MesquiteInteger();
+		if (table.findBlockSurroundingCell(firstColumnTouched, firstRowTouched, firstRow,  lastRow,  firstColumn,  lastColumn) ) {
+			return table.boundedBlockSelected( firstRow,  lastRow,  firstColumn,  lastColumn);
+		}
+		return false;
+
+	}
+	/*.................................................................................................................*/
+	public boolean findBlocks(boolean optionDown) {
+		//get rectangular selected block of which firstRowTouched, firstColumnTouched is a part.
+
+		MesquiteInteger firstRow = new MesquiteInteger();
+		MesquiteInteger lastRow = new MesquiteInteger();
+		MesquiteInteger firstColumn = new MesquiteInteger();
+		MesquiteInteger lastColumn = new MesquiteInteger();
+
+		if (table.findBlockSurroundingCell(firstColumnTouched, firstRowTouched, firstRow,  lastRow,  firstColumn,  lastColumn) ) {
+			if (firstColumnTouched>=firstColumn.getValue() && firstColumnTouched<=lastColumn.getValue() && firstRowTouched>=firstRow.getValue() && firstRowTouched<=lastRow.getValue()){
+				currentBlock.setAllBlocks(firstColumn.getValue() , lastColumn.getValue() , firstRow.getValue(), lastRow.getValue());
+				currentBlock.setWhichTaxa(firstRow.getValue(), lastRow.getValue());
+
+				currentBlock.setMaximumMovements();
+				return true;
+			}
+
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  boolean mouseDown(boolean optionDown, boolean shiftDown){
+		betweenCells = false;
+		leftEdge = false;
+		rightEdge = false;
+
+		if (table.isCellSelected(firstColumnTouched, firstRowTouched)) {  //then we are in the selected part between columns, about to start a move, if possible
+			choosingNewSelection = false;
+			if (!acceptableSelection()) {
+				currentlyMoving=false;
+				return false;
+			}
+			if (!prepareToMoveMultiSequences(optionDown)){
+				currentlyMoving=false;
+				return false;
+			}
+		}	else {
+			choosingNewSelection = true;
+			table.deselectAll();
+			table.selectCell(firstColumnTouched, firstRowTouched);
+		}
+		return true;
+
+	}
+	/*.................................................................................................................*/
+	public  void trackNewSelection(int column, int row){
+		MesquiteInteger firstInBlock= new MesquiteInteger();
+		MesquiteInteger lastInBlock= new MesquiteInteger();
+		MesquiteBoolean cellHasInapplicable = new MesquiteBoolean(false);
+		MesquiteBoolean leftIsInapplicable = new MesquiteBoolean(false);
+		MesquiteBoolean rightIsInapplicable = new MesquiteBoolean(false);
+		int firstColumn = MesquiteInteger.minimum(firstColumnTouched, column);
+		int lastColumn = MesquiteInteger.maximum(firstColumnTouched, column);
+		int firstRow = MesquiteInteger.minimum(firstRowTouched, row);
+		int lastRow = MesquiteInteger.maximum(firstRowTouched, row);
+		if (!data.isInapplicable(firstColumnTouched, firstRowTouched) && !data.isInapplicable(column, row)) {
+			currentBlock.getCellBlock(firstColumn, lastColumn, firstRow, lastRow, firstInBlock, lastInBlock,  wholeSelectedBlock(), wholeSequence(), wholeSequence(), cellHasInapplicable, leftIsInapplicable, rightIsInapplicable);
+			table.selectBlock(firstInBlock.getValue(),firstRow, lastInBlock.getValue(), lastRow);
+			table.repaintCells(liveUpdate.getValue());
+		}
+	}
+
+	/*.................................................................................................................*/
+	public  boolean mouseDragged(int columnDragged, int rowDragged,	int percentHorizontal, int percentVertical){
+		if (choosingNewSelection) {
+			trackNewSelection(columnDragged, rowDragged);
+
+		} else if (currentlyMoving) {
+			dragMultiSequences(percentHorizontal,  rowDragged,  columnDragged);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public  boolean mouseDropped(int columnDropped, int rowDropped,	int percentHorizontal, int percentVertical){
+		if (choosingNewSelection) {
+			if (rowDropped == table.getMatrixPanel().BEYONDMATRIX) rowDropped = table.numRowsTotal-1;
+			if (rowDropped<0) rowDropped=0;
+		} else if (!currentlyMoving){
+			table.deselectAllNotify();
+		}
+		if (!table.rowLegal(rowDropped)|| !table.columnLegal(columnDropped))
+			return false;
+		if (choosingNewSelection) {
+			trackNewSelection(columnDropped, rowDropped);
+
+			choosingNewSelection=false;
+		} else if (currentlyMoving){
+			afterMoveMultiSequences();
+		} else stopMoving();
+		return true;
+	}
+
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Toggles whether the entire sequences are moved.", "[on = moveWholeSequences; off]", commandName, "toggleWholeSequences")) {
+			selectWholeSequences.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Selected Block Mover";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Moves selected blocks of multiple sequences." ;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+
+
+
+
+	public class SelectedBlockTool extends TableTool {
+		MesquiteCursor crossHairCursor=null;
+
+
+		public SelectedBlockTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String extraImageFileName, int extraHotX, int extraHotY, String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand dragCommand, MesquiteCommand droppedCommand) {
+			super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation, touchedCommand, dragCommand, droppedCommand);
+			this.initiator = initiator;
+			setDeselectIfOutsideOfCells(true);
+			setHasTemporaryOptionCursor(true);
+			setHasTemporaryShiftCursor(true);
+
+			this.name = name;
+
+			crossHairCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, extraImageFileName, extraHotX, extraHotY);
+		}
+		public void turningOff(){
+		}
+
+		public void cursorInCell(int modifiers, int column, int row, int regionInCellH, int regionInCellV, EditorPanel panel){
+			if (table.isCellSelected(column, row))  {
+				setCurrentStandardCursor(null);
+			}
+			else {
+				setCurrentStandardCursor(crossHairCursor);
+			}
+		}
+
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/align/ShiftOtherToMatch/ShiftOtherToMatch.java b/Source/mesquite/align/ShiftOtherToMatch/ShiftOtherToMatch.java
new file mode 100644
index 0000000..59e2e71
--- /dev/null
+++ b/Source/mesquite/align/ShiftOtherToMatch/ShiftOtherToMatch.java
@@ -0,0 +1,217 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.ShiftOtherToMatch;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+
+
+/* ======================================================================== */
+public class ShiftOtherToMatch extends CategDataAlterer {
+	CharacterState cs1;
+	CharacterState cs2 ;
+	double matchFraction=0.75;
+	int it1= MesquiteInteger.unassigned;
+	int it2= MesquiteInteger.unassigned;
+	boolean preferencesSet = false;
+	boolean reverseComplementIfNecessary = true;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("matchFraction".equalsIgnoreCase(tag)) {
+			matchFraction = MesquiteDouble.fromString(content);
+		}
+		else if ("reverseComplementIfNecessary".equalsIgnoreCase(tag)) {
+			reverseComplementIfNecessary = MesquiteBoolean.fromOffOnString(content);
+		}
+	
+		preferencesSet = true;
+}
+/*.................................................................................................................*/
+public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "matchFraction", matchFraction);  
+		StringUtil.appendXMLTag(buffer, 2, "reverseComplementIfNecessary", reverseComplementIfNecessary);  
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions(int it, int max) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryFilesDialog = new ExtensibleDialog(containerOfModule(), "Shift Other To Match",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		queryFilesDialog.addLabel("Shift Other To Match");
+		
+		if (!MesquiteInteger.isCombinable(it1) || !MesquiteInteger.isCombinable(it2) || it1>max || it2>max){
+			if (it>=max) {
+				it1=1;
+			} else
+				it1 = it+2;  // it+1 to bump it over one, +2 because of the translation to 1-based numbering
+			it2=max;
+		}
+		IntegerField it1Field =  queryFilesDialog.addIntegerField ("First Sequence", it1, 4, 1, max);
+		IntegerField it2Field =  queryFilesDialog.addIntegerField ("Last Sequence", it2, 4, 1, max);
+		DoubleField matchFractionField = queryFilesDialog.addDoubleField ("Fraction of Match", matchFraction, 6, 0.00001, 1.0);
+		
+		Checkbox reverseSequencesCheckBox = queryFilesDialog.addCheckBox("Reverse complement sequences if necessary", reverseComplementIfNecessary);
+		
+		queryFilesDialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			matchFraction = matchFractionField.getValue();
+			it1 = it1Field.getValue();
+			it2 = it2Field.getValue();
+			reverseComplementIfNecessary = reverseSequencesCheckBox.getState();
+			storePreferences();
+		}
+		queryFilesDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData data, int ic, int it){
+   	}
+	/*.................................................................................................................*/
+	boolean findMatchInSequence(CharacterData data, int masterRow, int masterStart, int masterEnd, int it, int start, MesquiteInteger matchEnd){
+		if (data.dataMatches(it, start, masterRow, masterStart, masterEnd, matchEnd, false, true, matchFraction, cs1, cs2)) {
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	boolean findMatch(CharacterData data, MesquiteTable table, int masterRow, int masterStart, int masterEnd, int it, MesquiteInteger matchStart, MesquiteInteger matchEnd){
+		for (int i = 0; i<data.getNumChars(); i++) {  // cycle through possible starting points of match
+			if (findMatchInSequence(data,masterRow, masterStart, masterEnd, it, i, matchEnd)){
+				matchStart.setValue(i);
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+		if (data==null || table==null)
+			return false;
+		MesquiteInteger row = new MesquiteInteger();
+		MesquiteInteger firstColumn = new MesquiteInteger();
+		MesquiteInteger lastColumn = new MesquiteInteger();
+		if (table.onlySingleRowBlockSelected(row,firstColumn, lastColumn)) {
+			if (!queryOptions(row.getValue(), data.getNumTaxa()))
+					return false;
+			MesquiteBoolean dataChanged = new MesquiteBoolean (false);
+			MesquiteInteger charAdded = new MesquiteInteger(0);
+
+			cs1 = data.getCharacterState(null, 0, 0); //to serve as persistent container
+			cs2  = data.getCharacterState(null, 0, 0);
+			MesquiteInteger matchStart = new MesquiteInteger();
+			MesquiteInteger matchEnd = new MesquiteInteger();
+			boolean match=false;
+			int totalAddedToStart = 0;
+			boolean someAdded = false;
+			for (int it = it1-1; it<=it2-1; it++) {  // must subtract 1 off of it1 and it2 as these are 1-based numbers
+				if (row.getValue()!=it) {
+					match = findMatch(data,table, row.getValue(), firstColumn.getValue(), lastColumn.getValue(), it,matchStart,matchEnd);
+					if (reverseComplementIfNecessary && !match && data instanceof DNAData) {
+						MolecularDataUtil.reverseComplementSequencesIfNecessary((DNAData)data, this, data.getTaxa(), it, it, row.getValue(), false, false, false);
+
+					}
+					if (match) {
+						int added = data.shiftAllCells(firstColumn.getValue()-matchStart.getValue(), it, true, true, true, dataChanged,charAdded, null);
+						if (charAdded.isCombinable() && charAdded.getValue()!=0 && data instanceof DNAData) {
+							((DNAData)data).assignCodonPositionsToTerminalChars(charAdded.getValue());
+//							((DNAData)data).assignGeneticCodeToTerminalChars(charAdded.getValue());
+						}
+						if (added!=0)
+							someAdded=true;
+						if (added<0) {
+							totalAddedToStart -=added;
+							firstColumn.add(-added);
+							lastColumn.add(-added);
+						}
+					}
+				}
+			}
+			if (totalAddedToStart>0) {
+				if (table!=null) {
+					table.shiftHorizScroll(totalAddedToStart);
+					table.selectBlock(firstColumn.getValue(), row.getValue(), lastColumn.getValue(), row.getValue());  //Wayne: why doesn't this select a block in the matrix?
+				}
+			}
+			return dataChanged.getValue();
+		}
+		else {
+   			discreetAlert( "A portion of only one sequence can be selected.");
+			return false;
+   		}
+   	}
+   	
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	   /*.................................................................................................................*/
+   	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+   	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+   	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+      	public int getVersionOfFirstRelease(){
+      		return -100;  
+    }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Shift Other To Match";
+   	 }
+    		/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Shift Other To Match...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shifts other sequences to match the one selected." ;
+   	 }
+   	 
+}
+
+
+
diff --git a/Source/mesquite/align/ShiftToMinimizeStops/ShiftToMinimizeStops.java b/Source/mesquite/align/ShiftToMinimizeStops/ShiftToMinimizeStops.java
new file mode 100644
index 0000000..81da80c
--- /dev/null
+++ b/Source/mesquite/align/ShiftToMinimizeStops/ShiftToMinimizeStops.java
@@ -0,0 +1,155 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.ShiftToMinimizeStops;
+
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+public class ShiftToMinimizeStops extends DNADataAlterer {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData data, int ic, int it){
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+		return alterData(data,table,undoReference,null);
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference, AlteredDataParameters alteredDataParameters){
+		if (data==null || table==null || !(data instanceof DNAData))
+			return false;
+
+		DNAData dnaData = (DNAData)data;
+		if (!dnaData.someCoding()) 
+			return false;
+		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.CHAR_ADDED_TO_END});
+
+		MesquiteBoolean dataChanged = new MesquiteBoolean();
+		MesquiteInteger charAdded = new MesquiteInteger(0);
+		boolean someCharAdded = false;
+		int singleTaxonChanged = -1;
+		
+		
+		int[] numStops= new int[3];
+		for (int it=0; it<dnaData.getNumTaxa(); it++) 
+			if (table.wholeRowSelectedAnyWay(it)) {
+				numStops[0]= dnaData.getAminoAcidNumbers(it,ProteinData.TER);   //unshifted amount
+				if (numStops[0]>0) {
+					int added = data.shiftAllCells(1, it, true, true, false, dataChanged,charAdded, null);
+					if (charAdded.isCombinable() && charAdded.getValue()!=0) {
+						dnaData.assignCodonPositionsToTerminalChars(charAdded.getValue());
+//						dnaData.assignGeneticCodeToTerminalChars(charAdded.getValue());
+						someCharAdded=true;
+					}
+					numStops[1] = dnaData.getAminoAcidNumbers(it,ProteinData.TER);  //amount if shift by 1
+					if (numStops[1]>0) {
+						added = data.shiftAllCells(1, it, true, true, false, dataChanged,charAdded, null);
+						if (charAdded.isCombinable() && charAdded.getValue()!=0) {
+							dnaData.assignCodonPositionsToTerminalChars(charAdded.getValue());
+//							dnaData.assignGeneticCodeToTerminalChars(charAdded.getValue());
+							someCharAdded=true;
+						}
+						numStops[2] = dnaData.getAminoAcidNumbers(it,ProteinData.TER);  //amount if shift by 2
+						if (numStops[0]<=numStops[1] && numStops[0]<=numStops[2] ) {  // no change is best, but have shifted by 2, need to shift back
+							added = data.shiftAllCells(-2, it, true, true, false, dataChanged,charAdded, null);
+							dataChanged.setValue(false);
+						}
+						else if (numStops[1]<=numStops[0] && numStops[1]<=numStops[2] ) {  // one shift change is best, but have shifted by 1, need to shift back
+							added = data.shiftAllCells(-1, it, true, true, false, dataChanged,charAdded, null);							
+						}
+					}
+					if (dataChanged.getValue())
+						if (singleTaxonChanged<0)
+							singleTaxonChanged=it;
+						else if (MesquiteInteger.isCombinable(singleTaxonChanged))
+							singleTaxonChanged=MesquiteInteger.unassigned;
+
+				}
+			}
+		if (!someCharAdded && alteredDataParameters!=null) {
+			if (singleTaxonChanged>=0 && MesquiteInteger.isCombinable(singleTaxonChanged)) {
+				alteredDataParameters.setSubcodes(new int[] {MesquiteListener.SINGLE_TAXON});
+				alteredDataParameters.setParameters(new int[] {singleTaxonChanged});
+
+			} else
+				alteredDataParameters.setSubcodes(new int[] {MesquiteListener.ALL_CELLS_ONLY_SHIFTED});
+		}
+
+		if (undoInstructions!=null) {
+			undoInstructions.setNewData(data);
+			if (undoReference!=null){
+				undoReference.setUndoer(undoInstructions);
+				undoReference.setResponsibleModule(this);
+			}
+		}
+
+		return dataChanged.getValue();
+
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return -111;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Shift to Minimize Stop Codons";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Shift to Minimize Stop Codons";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shifts each sequence by 0, 1, or 2 bases to minimize number of stop codons implied." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/align/SidePusher/32leftGrab.gif b/Source/mesquite/align/SidePusher/32leftGrab.gif
new file mode 100644
index 0000000..67dda78
Binary files /dev/null and b/Source/mesquite/align/SidePusher/32leftGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/32rightGrab.gif b/Source/mesquite/align/SidePusher/32rightGrab.gif
new file mode 100644
index 0000000..d061f54
Binary files /dev/null and b/Source/mesquite/align/SidePusher/32rightGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/32splitBlockLeft.gif b/Source/mesquite/align/SidePusher/32splitBlockLeft.gif
new file mode 100644
index 0000000..2a3ddf2
Binary files /dev/null and b/Source/mesquite/align/SidePusher/32splitBlockLeft.gif differ
diff --git a/Source/mesquite/align/SidePusher/32splitBlockRight.gif b/Source/mesquite/align/SidePusher/32splitBlockRight.gif
new file mode 100644
index 0000000..8ca43ff
Binary files /dev/null and b/Source/mesquite/align/SidePusher/32splitBlockRight.gif differ
diff --git a/Source/mesquite/align/SidePusher/64leftGrab.gif b/Source/mesquite/align/SidePusher/64leftGrab.gif
new file mode 100644
index 0000000..2a5ef6a
Binary files /dev/null and b/Source/mesquite/align/SidePusher/64leftGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/64rightGrab.gif b/Source/mesquite/align/SidePusher/64rightGrab.gif
new file mode 100644
index 0000000..a78b04b
Binary files /dev/null and b/Source/mesquite/align/SidePusher/64rightGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/64splitBlockLeft.gif b/Source/mesquite/align/SidePusher/64splitBlockLeft.gif
new file mode 100644
index 0000000..ec1ade1
Binary files /dev/null and b/Source/mesquite/align/SidePusher/64splitBlockLeft.gif differ
diff --git a/Source/mesquite/align/SidePusher/64splitBlockRight.gif b/Source/mesquite/align/SidePusher/64splitBlockRight.gif
new file mode 100644
index 0000000..a8853c2
Binary files /dev/null and b/Source/mesquite/align/SidePusher/64splitBlockRight.gif differ
diff --git a/Source/mesquite/align/SidePusher/SidePusher.java b/Source/mesquite/align/SidePusher/SidePusher.java
new file mode 100644
index 0000000..275fad4
--- /dev/null
+++ b/Source/mesquite/align/SidePusher/SidePusher.java
@@ -0,0 +1,109 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.SidePusher; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class SidePusher extends BlockMover {
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Grab right/left", "Grabs right or left", null, getPath() + getCellToolImageFileName()));
+		registerSubfunction(new FunctionExplanation("Split block right/left", "Splits block left or right", null, getPath() + getSplitToolImageFileName()));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+   	 public  String getToolName(){
+		return "push";
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getCellToolImageFileName(){
+		return "rightGrab.gif";
+   	 }
+	/*.................................................................................................................*/
+   	 public  Point getCellToolHotSpot(){
+		return new Point (1,8);
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getSplitToolImageFileName(){
+		return "splitBlockRight.gif";
+   	 }
+	/*.................................................................................................................*/
+   	 public  Point getSplitToolHotSpot(){
+		return new Point (8,8);
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getExplanationForTool(){
+		return "This tool pushes the sequences for manual alignment.";
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getFullDescriptionForTool(){
+		return "Push Sequence";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean allowSplits(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Side Pusher";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean canMoveRight(){
+   	 	return !getOptionDown();
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean canMoveLeft(){
+   	 	return getOptionDown();
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean wholeSequenceToLeft(){
+   	 	return getOptionDown();
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean wholeSequenceToRight(){
+   	 	return !getOptionDown();
+   	 }
+   	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	   /*.................................................................................................................*/
+   	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+   	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+   	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+      	public int getVersionOfFirstRelease(){
+      		return -100;  
+    }
+	/*.................................................................................................................*/
+   	 public void setOptionTools(){
+    	 	moveTool.setOptionImageFileName("leftGrab.gif", 15,8);
+    	 	moveTool.setOptionEdgeCursor("SplitBlockLeft.gif", 8,8);
+  	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Pushes all sequences on one side." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/align/SidePusher/leftGrab.gif b/Source/mesquite/align/SidePusher/leftGrab.gif
new file mode 100644
index 0000000..3710902
Binary files /dev/null and b/Source/mesquite/align/SidePusher/leftGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/rightGrab.gif b/Source/mesquite/align/SidePusher/rightGrab.gif
new file mode 100644
index 0000000..2df390c
Binary files /dev/null and b/Source/mesquite/align/SidePusher/rightGrab.gif differ
diff --git a/Source/mesquite/align/SidePusher/splitBlockLeft.gif b/Source/mesquite/align/SidePusher/splitBlockLeft.gif
new file mode 100644
index 0000000..7a8532b
Binary files /dev/null and b/Source/mesquite/align/SidePusher/splitBlockLeft.gif differ
diff --git a/Source/mesquite/align/SidePusher/splitBlockRight.gif b/Source/mesquite/align/SidePusher/splitBlockRight.gif
new file mode 100644
index 0000000..d21fc7b
Binary files /dev/null and b/Source/mesquite/align/SidePusher/splitBlockRight.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/32BlockMover.gif b/Source/mesquite/align/SimpleBlockMover/32BlockMover.gif
new file mode 100644
index 0000000..4847ff4
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/32BlockMover.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/32Hand.gif b/Source/mesquite/align/SimpleBlockMover/32Hand.gif
new file mode 100644
index 0000000..d57adc6
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/32Hand.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/32splitBlock.gif b/Source/mesquite/align/SimpleBlockMover/32splitBlock.gif
new file mode 100644
index 0000000..5286a4e
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/32splitBlock.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/64BlockMover.gif b/Source/mesquite/align/SimpleBlockMover/64BlockMover.gif
new file mode 100644
index 0000000..ad839a2
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/64BlockMover.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/64Hand.gif b/Source/mesquite/align/SimpleBlockMover/64Hand.gif
new file mode 100644
index 0000000..51fa161
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/64Hand.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/64splitBlock.gif b/Source/mesquite/align/SimpleBlockMover/64splitBlock.gif
new file mode 100644
index 0000000..8d6655c
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/64splitBlock.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/BlockMover.gif b/Source/mesquite/align/SimpleBlockMover/BlockMover.gif
new file mode 100644
index 0000000..58ae03d
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/BlockMover.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/Hand.gif b/Source/mesquite/align/SimpleBlockMover/Hand.gif
new file mode 100644
index 0000000..374c6aa
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/Hand.gif differ
diff --git a/Source/mesquite/align/SimpleBlockMover/SimpleBlockMover.java b/Source/mesquite/align/SimpleBlockMover/SimpleBlockMover.java
new file mode 100644
index 0000000..9e1c0c7
--- /dev/null
+++ b/Source/mesquite/align/SimpleBlockMover/SimpleBlockMover.java
@@ -0,0 +1,142 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.SimpleBlockMover; 
+
+
+import java.awt.*;
+import mesquite.align.lib.*;
+import mesquite.categ.lib.CategoricalData;
+import mesquite.lib.CommandChecker;
+import mesquite.lib.CommandRecord;
+import mesquite.lib.MesquiteBoolean;
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteListener;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteWindow;
+import mesquite.lib.Notification;
+import mesquite.lib.Snapshot;
+
+
+/* ======================================================================== */
+public class SimpleBlockMover extends BlockMover {
+	MesquiteBoolean selectedBlock;
+	boolean defaultSelectedBlock  =false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		boolean superStart = super.startJob(arguments, condition, hiredByName);
+		if (!superStart)
+			return false;
+		selectedBlock = new MesquiteBoolean(defaultSelectedBlock);
+		//addCheckMenuItem(null, "Move Selected Block", makeCommand("toggleSelectedBlock",  this), selectedBlock);
+		return true;
+	}
+	/*.................................................................................................................*
+ 	 public Snapshot getSnapshot(MesquiteFile file) {
+ 	 	Snapshot temp = new Snapshot();
+		if (selectedBlock.getValue()!=defaultSelectedBlock)
+			temp.addLine("toggleSelectedBlock " + selectedBlock.toOffOnString());
+ 	 	return temp;
+ 	 }
+   	/*.................................................................................................................*
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	  if (checker.compare(this.getClass(), "Toggles whether the selected block is moved", "[on; off]", commandName, "toggleSelectedBlock")) {
+	 		boolean current = selectedBlock.getValue();
+	 		selectedBlock.toggleValue(parser.getFirstToken(arguments));
+	 	}
+	 	else
+	 		return  super.doCommand(commandName, arguments, checker);
+	 	return null;
+	 }
+	 
+		/*.................................................................................................................*/
+   	 public boolean wholeSelectedBlock(){
+   	 	return selectedBlock.getValue();
+   	 }
+ 	protected void adjustSelection() {
+		table.deselectAll();
+	}
+	/*.................................................................................................................*/
+   	 public  String getToolName(){
+		return "blockMover";
+   	 }
+ 	/*.................................................................................................................*/
+   	 public void setOptionTools(){
+    	 	moveTool.setOptionImageFileName("Hand.gif", 8,8);
+    	 	moveTool.setOptionEdgeCursor("Hand.gif", 8,8);
+  	 }
+  	/*.................................................................................................................*/
+   	 public boolean moveWholeSequence() {
+   		return getOptionDown();
+   	 }
+  	/*.................................................................................................................*/
+ 	public boolean wholeSequenceToLeft(){
+ 		return moveWholeSequence();
+ 	}
+ 	/*.................................................................................................................*/
+ 	public boolean wholeSequenceToRight(){
+ 		return moveWholeSequence();
+ 	}
+	/*.................................................................................................................*/
+   	 public  String getCellToolImageFileName(){
+		return "BlockMover.gif";
+   	 }
+	/*.................................................................................................................*/
+   	 public  Point getCellToolHotSpot(){
+		return new Point (8,8);
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getSplitToolImageFileName(){
+		return "splitBlock.gif";
+   	 }
+	/*.................................................................................................................*/
+   	 public  Point getSplitToolHotSpot(){
+		return new Point (8,8);
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getExplanationForTool(){
+		return "This tool moves blocks of sequences for manual alignment.";
+   	 }
+	/*.................................................................................................................*/
+   	 public  String getFullDescriptionForTool(){
+		return "Move Blocks";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return -100;  
+     	}
+    	/*.................................................................................................................*/
+      	 public boolean isPrerelease(){
+      	 	return false;
+      	 }
+ 	/*.................................................................................................................*/
+   	 public boolean allowSplits(){
+  		return !moveWholeSequence();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Move block";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Allows one to manually blocks in a sequence, and split the blocks." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/align/SimpleBlockMover/splitBlock.gif b/Source/mesquite/align/SimpleBlockMover/splitBlock.gif
new file mode 100644
index 0000000..ec9fffa
Binary files /dev/null and b/Source/mesquite/align/SimpleBlockMover/splitBlock.gif differ
diff --git a/Source/mesquite/align/ZapGaps/ZapGaps.java b/Source/mesquite/align/ZapGaps/ZapGaps.java
new file mode 100644
index 0000000..b1477a0
--- /dev/null
+++ b/Source/mesquite/align/ZapGaps/ZapGaps.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.ZapGaps;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+public class ZapGaps extends MolecularDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+		if (!(cData instanceof MolecularData))
+			return false;
+		boolean found = false;
+		MolecularData data = (MolecularData)cData;
+
+		MesquiteInteger row= new MesquiteInteger();
+		MesquiteInteger firstColumn= new MesquiteInteger();
+		MesquiteInteger lastColumn= new MesquiteInteger();
+		if (!table.anythingSelected()){
+			for (int it = 0; it<data.getNumTaxa(); it++)
+				data.collapseGapsInCellBlock(it, 0, data.getNumChars()-1, false);
+		}
+		else while (table.nextSingleRowBlockSelected(row,firstColumn,lastColumn)) {
+				data.collapseGapsInCellBlock(row.getValue(), firstColumn.getValue(), lastColumn.getValue(), false);
+		}
+		data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));
+		return found;
+   	}
+   	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return -100;  
+     	}
+    /*.................................................................................................................*/
+      	 public boolean isPrerelease(){
+      	 	return false;
+      	 }
+  	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Collapse Sequences to Left (Remove all Gaps)";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Collapse Sequences to Left (Remove all Gaps)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Collapses sequences in the selected block of cells to yield unaligned sequences, by removing all gaps." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/align/ZapGapsRight/ZapGapsRight.java b/Source/mesquite/align/ZapGapsRight/ZapGapsRight.java
new file mode 100644
index 0000000..f44a514
--- /dev/null
+++ b/Source/mesquite/align/ZapGapsRight/ZapGapsRight.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.ZapGapsRight;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+public class ZapGapsRight extends MolecularDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+		if (!(cData instanceof MolecularData))
+			return false;
+		boolean found = false;
+		MolecularData data = (MolecularData)cData;
+
+		MesquiteInteger row= new MesquiteInteger();
+		MesquiteInteger firstColumn= new MesquiteInteger();
+		MesquiteInteger lastColumn= new MesquiteInteger();
+		if (table == null || !table.anythingSelected()){
+			for (int it = 0; it<data.getNumTaxa(); it++)
+				data.collapseGapsInCellBlockRight(it, 0, data.getNumChars()-1, false);
+		}
+		else while (table.nextSingleRowBlockSelected(row,firstColumn,lastColumn)) {
+				data.collapseGapsInCellBlockRight(row.getValue(), firstColumn.getValue(), lastColumn.getValue(), false);
+		}
+		data.notifyListeners(this, new Notification(CharacterData.DATA_CHANGED));
+		data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));
+		return found;
+   	}
+   	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+     /*.................................................................................................................*/
+      	 public boolean isPrerelease(){
+      	 	return false;
+      	 }
+     	/*.................................................................................................................*/
+     	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+     	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+     	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 200;  
+     	}
+ 	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Collapse Gaps to Right";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Collapse Gaps to Right";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Collapses gaps in the selected block of cells to the right, to yield unaligned sequences." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/align/aAlignIntro/Templates/standard.dwt b/Source/mesquite/align/aAlignIntro/Templates/standard.dwt
new file mode 100644
index 0000000..93d0f7a
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/Templates/standard.dwt
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- TemplateBeginEditable name="doctitle" -->
+<title>Untitled Document</title>
+<!-- TemplateEndEditable -->
+<link rel="stylesheet" href="../styles/mesquitePackage.css" type="text/css">
+<!-- TemplateBeginEditable name="head" --><!-- TemplateEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="../splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- TemplateBeginEditable name="subtitle" -->subtitle<!-- TemplateEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- TemplateBeginEditable name="content" -->content<!-- TemplateEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="../index.html">Home</a></li>
+      <li><a href="../manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="../automated.html">Automated Alignment</a></li>
+      <li><a href="../visualization.html">Visualization Features</a></li>
+      <li><a href="../statistics.html">Statistics</a></li>
+      <li><a href="../citation.html">Citation</a></li>
+      <li><a href="../faq.html">FAQs</a></li>
+      <li><a href="../future.html">Future Directions</a></li>
+      <li><a href="../acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="../sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="../images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+</html>
+
diff --git a/Source/mesquite/align/aAlignIntro/_notes/2col_leftNav.css.mno b/Source/mesquite/align/aAlignIntro/_notes/2col_leftNav.css.mno
new file mode 100755
index 0000000..44757da
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/_notes/2col_leftNav.css.mno
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<info>
+	<infoitem key="mm_new_doc_type" value="exclude" />
+</info>
diff --git a/Source/mesquite/align/aAlignIntro/aAlignIntro.java b/Source/mesquite/align/aAlignIntro/aAlignIntro.java
new file mode 100644
index 0000000..a1eb52b
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/aAlignIntro.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.aAlignIntro;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class aAlignIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public Class getDutyClass(){
+		return aAlignIntro.class;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Align is a Mesquite package providing tools for the alignment of sequence data.";
+	}
+
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Align Package";
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+	public String getPackageName(){
+		return "Align Package";
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+	public String getPackageCitation(){
+		return "Maddison, D.R., T.J. Wheeler, and W.P. Maddison. 2014.  Align: A Mesquite package for aligning sequence data. Version " + getPackageVersion();
+	}
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+		return true; 
+	}
+	/*.................................................................................................................*/
+	 public String getPackageVersion() {
+		return "1.70";
+ 	 }
+		/*.................................................................................................................*/
+ 	 public int getPackageVersionInt() {
+		return 170;
+  	 }
+  	/*.................................................................................................................*/
+  	/** Returns the URL for the web page about the package*/
+  	public String getPackageURL(){
+  		return "http://mesquitealign.wikispaces.com";  
+  	}
+ 	/*.................................................................................................................*/
+ 	/** Returns the URL for the manual about the package*/
+ 	public String getManualPath(){
+ 		return "http://mesquitealign.wikispaces.com";  
+ 	}
+
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+}
+
diff --git a/Source/mesquite/align/aAlignIntro/acknowledgements.html b/Source/mesquite/align/aAlignIntro/acknowledgements.html
new file mode 100644
index 0000000..ca4675a
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/acknowledgements.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Acknowledgements</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Acknowledgements<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <p>We can't really think of anyone to thank at the moment. </p>
+  <!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/additions.html b/Source/mesquite/align/aAlignIntro/additions.html
new file mode 100644
index 0000000..13c7d73
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/additions.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Untitled Document</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body>
+<h3>Coloring Cells for Alignment</h3>
+<p>Manual alignment can be made easier by appropriate choice of a method to color 
+  cells. You can set the method to color cells using the Matrix>Color cells 
+  submenu. Three useful methods are:</p>
+<ul>
+  <li><strong>Character State</strong> — This colors cells according to 
+    nucleotide. This is the default coloring, but in case it has been turned off, 
+    you can turn it back on by going to Matrix>Color Cells>Character State.</li>
+  <li><strong>Aligning Colors</strong> — This colors pyrimidines by similar 
+    colors, and likewise purines</li>
+  <li><strong>Highlight Apparently Slightly Misaligned</strong> — This highlights 
+    subsequences that appear better shifted one or two sites left or right:<br>
+    <img src="colorMisaligned.jpg" width="249" height="252"> <br>
+    It bases its calculations on the dominant nucleotides in the columns, and 
+    hence is useful only in a matrix that is mostly well aligned. Shifts more 
+    distant than one or two sites are not considered. Do not consider this a definitive 
+    indication that the cells should move; its purpose is only to help you find 
+    possible issues, but the decision as to whether to shift or not is still up 
+    to you. The highlight does not specify which direction the subsequences might 
+    be best shifted; to learn this, hold the cursor over the sites in question.</li>
+</ul>
+<h3>Selecting Hint</h3>
+<p>To select from one cell to the end of the sequence, select the cell and then 
+  hit Shift-Alt-Arrow key (or, on OS X, Shift-Option-Arrow key), where the arrow 
+  key is either the right or left arrow key.</p>
+<h3>Preparing the Matrix</h3>
+<p>Several options under Matrix>Alter/Transform may be useful to modify the 
+  matrix in preparation for alignment. Some of these options are under "Other 
+  Choices...".</p>
+<ul>
+  <li>Collapse Gaps to Left</li>
+  <li>Collapse Gaps to Right</li>
+  <li>Trim Terminal Gaps Character</li>
+  <li>Gaps to Missing </li>
+  <li>Missing to Gaps</li>
+  <li>Terminal Gaps to ?</li>
+  <li>Terminal ? to Gaps</li>
+  <li>Reverse Complement</li>
+  <li>Reverse</li>
+  <li>Nucleotide Complement</li>
+</ul>
+<p> </p>
+</body>
+</html>
+
diff --git a/Source/mesquite/align/aAlignIntro/automated.html b/Source/mesquite/align/aAlignIntro/automated.html
new file mode 100644
index 0000000..d52b467
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/automated.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Automated Alignment Tools</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Automated Alignment <!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <h3><img src="images/alignToDropped.gif" alt="Pairwise Aligner" width="16" height="16">Pairwise Alignment tool  </h3>
+  <p>This tool allows one to drop one or a selected set of sequences onto a reference sequence; the sequences dropped will then be aligned to the reference sequence, preserving whatever gaps are present in the reference sequence. In the process, if gaps need to be inserted into the reference sequence, then they will be also inserted into other, non-selected sequences. </p>
+  <p>The dropdown menu for this tool allows you to change the gap opening cost (default
+    8) the gap extension cost (default 3) within bases of a sequences, as well
+    as the equivalent costs at the ends of the sequence (default 2 and 2, respectively).    </p>
+  <p>The default substitution costs
+      are:</p>
+  <ul>
+    <li>for DNA and RNA data, 5 for a transition and 10 for a transversion</li>
+    <li>for protein data, 5 for each substitution.</li>
+  </ul>
+   <p>These costs can be changed using the Substitution Costs dialog box available from the tool's dropdown menu.</p>
+ 
+  
+  <h3>Aligning nucleotide sequences to match an amino acid alignment </h3>
+  <p>This feature allows one to take a matrix of nucleotides, and an existing alignment of their translated amino acids, and have the nucleotides realigned to match the amino acid alignment.
+  To do this, you will need to have in the same Mesquite file both the nucleotide matrix and the protein matrix.  For example, you could do the following: </p>
+  <ul>
+ 	<li>Assign codon positions and genetic code to a nucleotide matrix (see the main Mesquite manual for details).</li>
+	<li>Adjust each sequence so that its reading frame is correct, by using the <a href="manualAlignment.html#shiftMinStops">Shift To Minimize Stops</a> feature.</li>
+	<li>Trim any incomplete codons from the ends of the sequences by selecting the
+	  entire matrix and choosing <font size="-1"><u>Matrix>Alter/Transform>Other
+	      Choices</u></font>... and selecting 
+	Trim Terminal Incomplete Codons.  "Terminal Incomplete Codons" are nucleotides
+	that are only part of a codon. For example, if one sequence starts at a third
+	position, then that third position nucleotide represents only one-third of a
+	codon, and it will be trimmed. Once this is done, only complete codons will
+	be left in the sequence </li>
+	<li>Translate the DNA matrix to amino acids by choosing <font size="-1"><u>Characters>Make New Matrix From>Translate
+      DNA To Protein</u></font>.  You will now have the protein matrix in your file.</li>
+
+    <li>Align the protein matrix. You could use, for example, the Clustal Align
+      feature described below. If instead you export the matrix (e.g., using
+      the <u><font size="-1">File>Export</font></u> options), align the proteins in a separate program, you
+      will then need to choose <u><font size="-1">File>Include</font></u> file to include the output of the
+      alignment program into your file.</li>
+    <li>Finally, go to your DNA matrix, and choose <font size="-1"><u>Matrix>Alter/Transform>Align
+          DNA to Protein</u></font>. </li>
+  </ul>
+
+  <h3>MAFFT Align </h3>
+  <p>This feature allows one to select a single block of sequences, and then have MAFFT align them. To do this, select the block, then choose Matrix>Align Multiple Sequences>MAFFT Align... </p>
+  <p>You will be presented first with a query as to whether you want to do the MAFFT alignment on a separate thread, or on the same thread. Mesquite can do multiple things at once, because it can have one thing running on one computational "thread", and another thing happening on a separate thread. There is a main thread of the program that is the thread the user deals with directly, and that allows you to give commands to Mesquite (via menus, etc.). If this main thread is busy [...]
+  <p>Once you make that choice, you will see a dialog box in which you must enter the directory location of MAFFT. This is necessary as without it Mesquite won't know how to use MAFFT. In this dialog box you can also set options for MAFFT.</p>
+  <p><img src="images/MAFFT dialog box.png" width="572" height="325"></p>
+  <p>To set the directory location, you can either type in the path directly, or you can use the Browse button and then you can find MAFFT and the location filled in automatically. (On a Mac, by default the standard version of MAFFT is installed in /usr/local/bin, so the path would be /usr/local/bin/mafft )  </p>
+  <p>If you wish, you can also alter the options of MAFFT. The <a href="http://mafft.cbrc.jp/alignment/software/manual/manual.html">MAFFT manual</a> notes some standard alignment procedure settings, including some accuracy-oriented methods (e.g., L-INS-i, G-INS-i, and E-INS-i) and some speed-oriented methods (including FFT-NS-i). Mesquite offers these standard methods in the pull-down menu beside "Suggested methods". Choosing one of these will fill the "basic alignment met [...]
+  <p>For additional options, which you can enter into the "Addition MAFFT options" text box, see the <a href="http://mafft.cbrc.jp/alignment/software/manual/manual.html">MAFFT manual</a> for more details.  </p>
+  <p>If you then press OK, Mesquite will send that section of the matrix to MAFFT and ask for it to be aligned; it will then harvest the results and reincorporate that piece into the matrix.</p>
+  <p>If you use MAFFT from within Mesquite, then you should cite MAFFT as appropriate; see the <a href="http://mafft.cbrc.jp/alignment/software/manual/manual.html">MAFFT manual</a> for citation details.  </p>
+  <p>   </p>
+
+  <h3>ClustalW Align</h3>
+  <p>This tool is just like the MAFFT Align feature described above, except that it works for the ClustalWprogram. The version of ClustalW that is to be used by Mesquite <em>must</em> be a version of ClustalW that is executable from the command line of your operating system.</p>
+  <p>  </p>
+  <h3>Muscle Align </h3>
+  <p>This tool is just like the MAFFT Align feature described above, except that it works for Robert C. Edgar's <a href="http://www.drive5.com/muscle/">MUSCLE</a> program. </p>
+  <p>  </p>
+<!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/citation.html b/Source/mesquite/align/aAlignIntro/citation.html
new file mode 100644
index 0000000..d763bcb
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/citation.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Untitled Document</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Citation<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <p><font face="Trebuchet MS">Align should be cited as:</font></p>
+  <p><font face="Trebuchet MS"><br />
+    Maddison, D.R., T.J. Wheeler, and W.P. Maddison. 2007. Align: a Mesquite
+    package for aligning sequence data. Version 1.11.<em> http://mesquiteproject.org</em></font></p>
+  <p> </p>
+  <!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/colorMisaligned.jpg b/Source/mesquite/align/aAlignIntro/colorMisaligned.jpg
new file mode 100644
index 0000000..67cc054
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/colorMisaligned.jpg differ
diff --git a/Source/mesquite/align/aAlignIntro/faq.html b/Source/mesquite/align/aAlignIntro/faq.html
new file mode 100644
index 0000000..9c0c79a
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/faq.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Frequently Asked Questions</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Frequently Asked Questions <!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <p> </p>
+  <p>Q: Can I change the substitution costs used by the pairwise aligner tools? </p>
+  <p>A: Yes. You can now do this using the Substitution Costs menu item that
+    is available in the dropdown menu that appears if you touch down on the Pairwise
+    Aligner tool in the tool palette.</p>
+  <p>  </p>
+<!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/future.html b/Source/mesquite/align/aAlignIntro/future.html
new file mode 100644
index 0000000..c91dc43
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/future.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Future Directions</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Future Directions <!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" --> 
+  <p>In the future, we plan to:</p>
+  <ul>
+    <li>allow more control by the user over the alignment parameters used by the pairwise aligner</li>
+    <li>add various graphical features for aiding with alignment of ribosomal DNA</li>
+    <li>add more manual alignment tools, including a tools that lets one manipulate multiple sequences at once <br>
+    </li>
+    <li>add more features derived from the pairwise aligner calculations. </li>
+  </ul>
+  <h3> </h3>
+  <!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/images/BlockMover.gif b/Source/mesquite/align/aAlignIntro/images/BlockMover.gif
new file mode 100644
index 0000000..498f7a9
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/BlockMover.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/MAFFT Dialog Box.png b/Source/mesquite/align/aAlignIntro/images/MAFFT Dialog Box.png
new file mode 100644
index 0000000..518b66f
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/MAFFT Dialog Box.png differ
diff --git a/Source/mesquite/align/aAlignIntro/images/alignToDropped.gif b/Source/mesquite/align/aAlignIntro/images/alignToDropped.gif
new file mode 100644
index 0000000..29586a9
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/alignToDropped.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/email.jpg b/Source/mesquite/align/aAlignIntro/images/email.jpg
new file mode 100644
index 0000000..d4d68a7
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/email.jpg differ
diff --git a/Source/mesquite/align/aAlignIntro/images/leftGrab.gif b/Source/mesquite/align/aAlignIntro/images/leftGrab.gif
new file mode 100644
index 0000000..3710902
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/leftGrab.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/mesquiteIcon.gif b/Source/mesquite/align/aAlignIntro/images/mesquiteIcon.gif
new file mode 100644
index 0000000..e2332d4
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/mesquiteIcon.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/multiBlockSpitter.gif b/Source/mesquite/align/aAlignIntro/images/multiBlockSpitter.gif
new file mode 100644
index 0000000..4344c4c
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/multiBlockSpitter.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/multiBlockSplitterOther.gif b/Source/mesquite/align/aAlignIntro/images/multiBlockSplitterOther.gif
new file mode 100644
index 0000000..ee279e9
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/multiBlockSplitterOther.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/multiSplitBefore.gif b/Source/mesquite/align/aAlignIntro/images/multiSplitBefore.gif
new file mode 100644
index 0000000..93c42cf
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/multiSplitBefore.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/multisplitAfter.gif b/Source/mesquite/align/aAlignIntro/images/multisplitAfter.gif
new file mode 100644
index 0000000..5a0493f
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/multisplitAfter.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/rightGrab.gif b/Source/mesquite/align/aAlignIntro/images/rightGrab.gif
new file mode 100644
index 0000000..2df390c
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/rightGrab.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/scrollToData.gif b/Source/mesquite/align/aAlignIntro/images/scrollToData.gif
new file mode 100644
index 0000000..87e67e6
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/scrollToData.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/images/selectedBlockMover.gif b/Source/mesquite/align/aAlignIntro/images/selectedBlockMover.gif
new file mode 100644
index 0000000..5002737
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/images/selectedBlockMover.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/manualAlignment.html b/Source/mesquite/align/aAlignIntro/manualAlignment.html
new file mode 100644
index 0000000..8d6bf16
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/manualAlignment.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Manual Alignment Tools</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Manual Alignment <!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <h2>Moving bases by hand </h2>
+  <p>There are two tools available for moving bases by hand. One is the Move Blocks tool (<img src="images/BlockMover.gif" alt="Block Mover" width="16" height="16">), the other is the Push Sequence tool (<img src="images/rightGrab.gif" alt="Push Sequence" width="16" height="16">). </p>
+  <p>Both of these tools have a "Live update analyses, etc." option in their popup menus. If this is chosen, then all calculations (e.g., charts, character tracings, etc.) that depend upon these data will be redone <em>as you use</em> these tools. (Recalculations will be done once you let go of the mouse button, in any event.) If some of these calculations take a while, this can dramatically slow down use of these tools. </p>
+  <p>There are some <a href="visualization.html">visualization features</a> in Mesquite that can aid in manual
+    alignment.</p>
+  <h3><img src="images/BlockMover.gif" alt="Block Mover" width="16" height="16">Move Blocks Tool</h3>
+  <p>This tool will move a contiguous block of a single sequence. If you move the tool between two bases it will let you split a block in two, inserting gaps. </p>
+  <p>If you wish, you can move more than a single, contiguous block by turning on "Move Selected Block" within the tool's popup menu, then using the tool to move selected bases and gaps. </p>
+  <h3><img src="images/multiBlockSpitter.gif" alt="Multiple Block Splitter" width="21" height="20">Multiple Block Splitter</h3>
+  <p>This tool allows one to draw a line between two sites, through one or more
+    sequences, as shown in the following image:</p>
+  <p align="center"><img src="images/multiSplitBefore.gif" width="224" height="151"></p>
+  <p>Then, if the tool use used upon the line,   those sequences can be dragged,
+    opening up gaps along the line:</p>
+  <p align="center"><img src="images/multisplitAfter.gif" width="224" height="151"></p>
+  <p align="left">If you hold the Option key down, then all sequences <em>other</em> than
+    those delimited will be moved. There are additional options in the popup
+    menu of the tool's button that allow you to request that entire sequences
+    are moved, or all sequences on one side. You can also request that the matrix
+    be expanded on either end as necessary as you move sequences around; by default
+    this option is off.</p>
+  <h3><img src="images/selectedBlockMover.gif" alt="Selected Block Mover" width="22" height="21">Selected Block Mover</h3>
+  <p>This tool move move a selected block of cells. There are additional options
+    in the popup menu of the tool's button. For example, you can also request
+    that the matrix be expanded on either end as necessary as you move sequences
+    around;
+    by default
+    this option is off.</p>
+
+
+  <h3><img src="images/rightGrab.gif" alt="Push Sequence" width="16" height="16"> Push Sequence Tool</h3>
+  <p>This tool pushes to the right the entire sequence to the right of the tool, or, if you have the Option key held down, it pushes to the left the entire sequence to the left of the tool. </p>
+  <h2>Shifting sequences </h2>
+  <p>Select a portion of a single sequence. If you then choose Matrix>Alter/Transform>Shift Other to Match..., then you will be presented with a dialog box that lets you choose a range of taxa, as well as a percentage. By default the range of taxa is the remaining taxa in the matrix. The default percentage is 75%. </p>
+  <p>If you press OK, Mesquite will look at each of the taxa within the range, and see if it can find a portion of each that is at least as similar as the percentage indicated to the selected portion (no gaps allowed). For each taxon that it can find such a match, it will shift those sequence such that the matched regions are lined up with the selected region. </p>
+  <p>Note that this is not an alignment algorithm; it simply shifts the sequences, maintaining whatever gaps are there or not in the sequences to be shifted. </p>
+  <p><a name="shiftMinStops"></a> You can also choose Matrix>Alter/Transform>Shift To Minimize Stop
+    Codons to shifts each <br>
+sequence 0, 1, or 2 bases so as to minimize the number of stop codons. The amount
+each sequence will be shifted will vary from sequence to sequence. This feature
+requires that codon
+positions be designated.</p>
+  <h2>Removal of Gaps</h2>
+  <h3>Remove All-Gap Characters </h3>
+  <p>Choosing this from Matrix>Alter/Transform>Remove All-Gap Characters will remove all sites in the matrix that consist entirely of gaps. </p>
+  <h3>Collapse Gaps </h3>
+  <p>With a block of the matrix selected, choosing  Matrix>Alter/Transform>Collapse Gaps will remove all gaps in the selected block, with the bases or amino acids pushed as far to the left as possible. </p>
+<h2>Selecting Hint</h2>
+<p>To select from one cell to the end of the sequence, select the cell and then 
+  hit Shift-Alt-Arrow key (or, on OS X, Shift-Option-Arrow key), where the arrow 
+  key is either the right or left arrow key.</p>
+<h2>Preparing the Matrix</h2>
+<p>Several options under Matrix>Alter/Transform may be useful to modify the 
+  matrix in preparation for alignment. Some of these options are under "Other 
+  Choices...".</p>
+<ul>
+  <li>Collapse Gaps to Left</li>
+  <li>Collapse Gaps to Right</li>
+  <li>Trim Terminal Gaps Character</li>
+  <li>Gaps to Missing </li>
+  <li>Missing to Gaps</li>
+  <li>Terminal Gaps to ?</li>
+  <li>Terminal ? to Gaps</li>
+  <li>Reverse Complement</li>
+  <li>Reverse</li>
+  <li>Nucleotide Complement</li>
+</ul>
+<!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/overview.html b/Source/mesquite/align/aAlignIntro/overview.html
new file mode 100644
index 0000000..eecce91
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/overview.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Chromaseq Overview</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Overview<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <p>The Align package contains:</p>
+  <ul>
+    <li>Tools for <a href="manualAlignment.html">manual alignment</a>
+      <ul>
+        <li>a Move Blocks tool</li>
+        <li>a Push Sequence tool</li>
+        <li>commands to remove gaps <em>en masse</em> </li>
+      </ul>
+    </li>
+    <li>Tools for <a href="automated.html">automated alignment </a>
+      <ul>
+        <li>a Pairwise Aligner tool</li>
+        <li>the ability to send a block of the matrix to ClustalW to align </li>
+      </ul>
+    </li>
+    <li>Various <a href="statistics.html">statistics</a> about taxa based about alignments    
+      <ul>
+        <li>the alignment score of a taxon against a reference taxon</li>
+        <li>the ratio of the alignment score of a taxon and its reverse complement against a reference taxon; this allows one to quickly detect sequences that are reverse complements of others. </li>
+      </ul>
+    </li>
+    </ul>
+  <!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/sourceCode.html b/Source/mesquite/align/aAlignIntro/sourceCode.html
new file mode 100644
index 0000000..f24cfc2
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/sourceCode.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Source Code</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Source Code<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+  <p><font face="Trebuchet MS">The source code for Align is distributed as part of the standard <a href="http://mesquiteproject.org/mesquite/download/source.html">source distribution</a> of Mesquite. </font></p>
+    <!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/splash.gif b/Source/mesquite/align/aAlignIntro/splash.gif
new file mode 100644
index 0000000..2ab07e3
Binary files /dev/null and b/Source/mesquite/align/aAlignIntro/splash.gif differ
diff --git a/Source/mesquite/align/aAlignIntro/statistics.html b/Source/mesquite/align/aAlignIntro/statistics.html
new file mode 100644
index 0000000..3446e35
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/statistics.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Alignment Statistics</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Statistics<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" --> 
+  <p>Align provides two statistics that can be calculate for each taxon in a matrix. 
+  </p>
+  <p>The first, the <strong>Alignment Score</strong>, is simply the "cost" of the alignment between that taxon and a reference sequence, using Mesquite's default pairwise aligner. By default, the reference sequence is the first one in the matrix; it can be reset by choosing the menu item "Reference Taxon..". If you have asked to see this in a Taxa List window (by List>Show Column>Number for Taxon>Other Choices...> Alignment Score to Ref.), then the "R [...]
+    <p>The second, the <strong>Alignment Score/Reverse Complement Alignment Score</strong>, is the cost of the alignment of that taxon to the reference sequence, divided by the cost of the alignment of the reverse complement of that taxon's sequence to the reference sequence. If this value is low (<1), it means that the alignment is better if both sequence are in their current orientation than if one is reverse complemented; if it is greater than 1, then it might be an indication that [...]
+<!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/aAlignIntro/styles/mesquitePackage.css b/Source/mesquite/align/aAlignIntro/styles/mesquitePackage.css
new file mode 100755
index 0000000..6058a19
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/styles/mesquitePackage.css
@@ -0,0 +1,302 @@
+/***********************************************/
+/* Based on Dreamweaver's 2col_leftNav.css     */
+/***********************************************/
+
+/***********************************************/
+/* HTML tag styles                             */
+/***********************************************/ 
+
+body{
+	font-family: "Trebuchet MS", Arial, sans-serif;
+	color: #333333;
+	line-height: 1.166;	
+	margin: 0px;
+	padding: 0px;
+}
+
+a:link, a:visited, a:hover {
+	color: #3300CC;
+	text-decoration: none;
+	font-weight: bold;
+}
+
+a:visited {
+	color:#330066;
+}
+
+
+a:hover {
+	text-decoration:underline;
+}
+/* overrides decoration from previous rule for hovered links */
+
+h1, h2, h3, h4, h5, h6 {
+	font-family: "Trebuchet MS", Arial, sans-serif;
+	margin: 0px;
+	padding: 0px;
+	color: #662200;
+}
+
+h1{
+ font-size: 140%;
+}
+
+h2{
+ margin-top:20px;
+ font-size: 120%;
+ border-top: 1px solid #eebb88;
+}
+
+h3, h4, h5, h6 {
+	color: #bb8855;
+}
+
+h3{
+ font-style:italic;
+}
+
+h4{
+ font-size: 100%;
+ text-indent: 20px;
+}
+
+h5{
+ font-size: 100%;
+  text-indent: 40px;
+   font-weight: normal;
+}
+
+ul{
+ list-style-type: square;
+}
+
+ul ul{
+ list-style-type: disc;
+}
+
+ul ul ul{
+ list-style-type: none;
+}
+
+label{
+	font-family: "Trebuchet MS",sans-serif;
+ 	color: #334d55;
+}
+				
+
+/***********************************************/
+/* Layout Divs                                 */
+/***********************************************/
+
+#masthead{
+	margin: 0;
+	padding: 4px 0px;
+	background-color: #ffcc99;
+	border-bottom: 1px solid #eebb88;
+	width: 100%;
+	height: 100px;
+}
+
+#banner{
+	float: left;
+	margin: 0;
+	padding: 4px 10px;
+	background-color: #ffcc99;
+	vertical-align:middle;
+	width: 20%;
+}
+
+#navBar{
+	padding: 0px;
+	background-color: #ffcc99;
+	border-right: 1px solid #eebb88;
+	width: 20%;
+}
+#navBarExtension{
+	padding: 0px;
+	background-color: #ffcc99;
+	border-right: 1px solid #eebb88;
+	width: 20%;
+	height: 100%;
+	min-height: 100px;
+	
+	float: left;
+}
+
+#content{
+	width: 75%;
+	left: 25%;
+	margin: 0;
+	padding: 8px 3% 0 8px;
+	float: right;
+	background-color:#ffffff;
+	text-align: left;
+}
+
+
+
+/***********************************************/
+/*Component Divs                               */
+/***********************************************/
+
+#siteName{
+	margin: 0px;
+	padding: 0px 0px 10px 10px;
+	font-family:Georgia, "Times New Roman", Times, serif;
+	font-weight:bold;
+	font-size: 36px;
+	vertical-align:middle;
+	background-color: #ffcc99;
+	color:#330033;
+	
+}
+
+#packageName{
+	font-size:28px;
+}
+
+#version{
+	font-size:86%;
+}
+
+#mainTitle{
+	margin: 0px;
+	padding: 0px 0px 10px 10px;
+	font-family:Georgia, "Times New Roman", Times, serif;
+	font-size: 14px;
+	vertical-align:middle;
+	color:#320032;
+	background-color: #ffcc99;
+	float: left;
+	
+}
+
+#subtitle{
+	color: #330033;
+	background-color: #ffcc99;
+	padding-right: 20px;
+	font-family:Georgia, "Times New Roman", Times, serif;
+	font-weight:bold;
+	font-size: 18px;
+	font-style:italic;
+	float: right;
+	height:80px;
+	vertical-align:-450%;
+}
+
+
+/*************** #pageName styles **************/
+
+#pageName{
+	padding: 0px 0px 10px 10px;
+}
+
+
+/************* #globalNav styles **************/
+
+#globalNav{
+color: #eebb88;
+padding: 0px 0px 0px 10px;
+white-space: nowrap;
+}
+/* 'nowrap' prevents links from line-wrapping if there are too many to fit in one line
+   this will force a horizontal scrollbar if there isn't enough room for all links
+   remove rule or change value to 'normal' if you want the links to line-wrap */
+
+#globalNav img{
+ display: block;
+}
+
+#globalNav a {
+	font-size: 90%;
+	padding: 0px 4px 0px 0px; 
+}
+
+
+
+
+/************* #siteInfo styles ***************/
+
+#siteInfo{
+	border: 1px solid #eebb88;
+	font-size: 75%;
+	color: #555555;
+	padding: 10px 10px 10px 10px;
+	margin-top: 0px;
+	margin-right: 10px;
+
+	width: 75%;
+	left: 25%;
+	float: right;
+	
+}
+/* negative top margin pulls siteinfo up so its top border overlaps (and thus lines up with)
+	the bottom border of the navBar in cases where they "touch" */
+
+#siteInfo img{
+	padding: 4px 4px 4px 0px;
+	vertical-align: middle;
+}
+
+
+
+/*********** #navBar link styles ***********/
+
+#navBar ul a:link, #navBar ul a:visited {display: block;}
+#navBar ul {list-style: none; margin: 0; padding: 0;}
+#navBar a:link {color:#773300;}
+#navBar a:visited {color:#bb6644;}
+
+/* hack to fix IE/Win's broken rendering of block-level anchors in lists */
+#navBar li {border-bottom: 1px solid #EEE;}
+
+/* fix for browsers that don't need the hack */
+html>body #navBar li {border-bottom: none;}
+
+#subUL {list-style: none; margin; 0; padding-left: 6px; font-size: 75%; text-indent:8px;}
+
+#extraTopMarginLI {padding-top: 12px}
+
+/*********** #sectionLinks styles ***********/
+
+#sectionLinks{
+	position: relative;
+	margin: 0px;
+	padding: 0px;
+	border-bottom: 1px solid #eebb88;
+	font-size: 90%;
+}
+
+#sectionLinks h3{
+	padding: 10px 0px 2px 10px;
+}
+
+#sectionLinks a:link{
+	padding: 2px 0px 2px 10px;
+	border-top: 1px solid #eebb88;
+	width: 100%;
+  voice-family: "\"}\""; 
+  voice-family:inherit;
+	width: auto;
+}
+
+#sectionLinks a:visited{
+	border-top: 1px solid #eebb88;
+	padding: 2px 0px 2px 10px;
+}
+
+#sectionLinks a:hover{
+	border-top: 1px solid #eebb88;
+	background-color: #eebb88;
+	padding: 2px 0px 2px 10px;
+}
+
+
+
+
+
+#menu {
+	font-family:Georgia, "Times New Roman", Times, serif;
+	color: #000000;
+	font-weight:600;
+	}
diff --git a/Source/mesquite/align/aAlignIntro/visualization.html b/Source/mesquite/align/aAlignIntro/visualization.html
new file mode 100644
index 0000000..719dfb5
--- /dev/null
+++ b/Source/mesquite/align/aAlignIntro/visualization.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html><!-- InstanceBegin template="/Templates/standard.dwt" codeOutsideHTMLIsLocked="false" -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=">
+<!-- InstanceBeginEditable name="doctitle" -->
+<title>Visualization Features</title>
+<!-- InstanceEndEditable -->
+<link rel="stylesheet" href="styles/mesquitePackage.css" type="text/css">
+<!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
+</head>
+
+
+<body>
+<div id="masthead">
+  <div id="banner"><img src="splash.gif" width="164" height="64"></div>
+  <div id="mainTitle"><font id="packageName"><b>Align</b></font><font id="version"><br>
+    Version 1.7<br>
+    7 August 2014</font><BR>
+  David R. Maddison, Travis J. Wheeler, and Wayne P. Maddison </div>
+  <div id="subtitle"><!-- InstanceBeginEditable name="subtitle" -->Visualization
+      Features<!-- InstanceEndEditable --></div>
+ 
+</div>
+<div>
+<!-- end masthead -->
+<div id="content"><!-- InstanceBeginEditable name="content" -->
+<h3>Coloring Cells for Alignment</h3>
+<p>Manual alignment can be made easier by appropriate choice of a method to color 
+  cells. You can set the method to color cells using the Matrix>Color cells 
+  submenu. Three useful methods are:</p>
+<ul>
+  <li><strong>Character State</strong> — This colors cells according to 
+    nucleotide. This is the default coloring, but in case it has been turned off, 
+    you can turn it back on by going to Matrix>Color Cells>Character State.</li>
+  <li><strong>Aligning Colors</strong> — This colors pyrimidines by similar 
+    colors, and likewise purines</li>
+  <li><strong>Highlight Apparently Slightly Misaligned</strong> — This highlights 
+    subsequences that appear better shifted one or two sites left or right:<br>
+    <img src="colorMisaligned.jpg" width="249" height="252"> <br>
+    It bases its calculations on the dominant nucleotides in the columns, and 
+    hence is useful only in a matrix that is mostly well aligned. Shifts more 
+    distant than one or two sites are not considered. Do not consider this a definitive 
+    indication that the cells should move; its purpose is only to help you find 
+    possible issues, but the decision as to whether to shift or not is still up 
+    to you. The highlight does not specify which direction the subsequences might 
+    be best shifted; to learn this, hold the cursor over the sites in question.</li>
+</ul>
+<!-- InstanceEndEditable --></div>
+<!--end content -->
+<div id="navBar">
+  <div id="sectionLinks">
+    <ul>
+      <li><a href="index.html">Home</a></li>
+      <li><a href="manualAlignment.html">Manual Alignment</a></li>
+      <li><a href="automated.html">Automated Alignment</a></li>
+      <li><a href="visualization.html">Visualization Features</a></li>
+      <li><a href="statistics.html">Statistics</a></li>
+      <li><a href="citation.html">Citation</a></li>
+      <li><a href="faq.html">FAQs</a></li>
+      <li><a href="future.html">Future Directions</a></li>
+      <li><a href="acknowledgements.html">Acknowledgements</a></li>
+      <li style="margin-top: 20px;"></li>
+      <li><a href="sourceCode.html">Source Code</a></li>
+      <li style="margin-top: 20px;"></li>
+	  <li><protectedURL>a href="../../../docs/mesquite/manual.html"</protectedURL>Mesquite Manual</a></li>
+    </ul>
+	<p> </p>
+	<ul><li> <a href="http://mesquiteproject.org"  style="border: 0px;"><img src="images/mesquiteIcon.gif" alt="Mesquite Home" width="32" height="32"> Mesquite Home</a> </li>
+    </ul>
+  </div>
+</div>
+</div>
+<div id="navBarExtension"> </div>
+<!--end navbar -->
+<div id="siteInfo"> Copyright © 2008-2009 <a href="http://david.bembidion.org">David
+R. Maddison, </a><a href="http://traviswheeler.com/">Travis J. Wheeler</a>, and <a href="http://salticidae.org/wpm/home.html">Wayne
+P. Maddison</a></div>
+<br>
+</body>
+<!-- InstanceEnd --></html>
+
diff --git a/Source/mesquite/align/lib/AlignMatch.java b/Source/mesquite/align/lib/AlignMatch.java
new file mode 100644
index 0000000..eebcb5f
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignMatch.java
@@ -0,0 +1,171 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.lib; 
+
+
+import java.util.Enumeration;
+
+import mesquite.align.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public abstract class AlignMatch extends CategDataMatcher {
+	 boolean preferencesSet = false;
+	PairwiseAligner aligner;
+	long originalState, candidateState;
+	int alphabetLength;
+	int maxLengthDiff = 2;
+	MesquiteCommand ptC;
+	protected MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+
+		mss = addSubmenu(null, getName());//getFileCoordinator().
+  		addItemToSubmenu(null, mss,"Allowed Length Differences...", makeCommand("setMaxLengthDiff", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** Override if one wishes to modify the alignment costs away from the default. */
+ 	 	public int[][] modifyAlignmentCosts(int[][] defaultSubs) {
+	 		return defaultSubs;
+	}
+	/*.................................................................................................................*/
+	protected void initAligner() {
+  		MesquiteInteger gapOpen = new MesquiteInteger();
+   		MesquiteInteger gapExtend = new MesquiteInteger();
+ 		MesquiteInteger gapOpenTerminal = new MesquiteInteger();
+   		MesquiteInteger gapExtendTerminal = new MesquiteInteger();
+  		alphabetLength = ((CategoricalState)state).getMaxPossibleState()+1;
+ 		AlignUtil.getDefaultGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);  
+  		int subs[][] = AlignUtil.getDefaultSubstitutionCosts(alphabetLength);  
+  		subs = modifyAlignmentCosts(subs);
+   		aligner = new PairwiseAligner(false,subs,gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue(), alphabetLength);
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData( MesquiteTable table, CharacterData data) {
+		super.setTableAndData(table,data);
+		if (state!=null)
+			initAligner();
+	}
+	/*.................................................................................................................*/
+ 	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	Snapshot temp = new Snapshot();
+	 	temp.addLine("setMaxLengthDiff " + maxLengthDiff);
+	 	return temp;
+ 	 }
+ 
+	/*.................................................................................................................*/
+   	/** Returns whether or not better matches have higher values or not.*/
+	public boolean getHigherIsBetter() {
+		if (aligner==null)
+			return false;
+		return aligner.getHigherIsBetter();
+	}   	
+	
+	/*.................................................................................................................*/
+   	/** Returns the match of the two long arrays*/
+	public double sequenceMatch(long[] originalArray, long[] candidateArray){
+ 		if (candidateArray==null || aligner ==null || originalArray==null)
+   			return MesquiteDouble.unassigned;
+  		MesquiteNumber score = new MesquiteNumber();
+   		aligner.alignSequences(originalArray,candidateArray,false, score);
+   		return score.getDoubleValue();
+	}
+
+	
+	public double getBestMatchValue(long[] originalArray){
+		if (aligner ==null || originalArray==null)
+   			return MesquiteDouble.unassigned;
+  		MesquiteNumber score = aligner.getScoreOfIdenticalSequences(originalArray);
+   		return score.getDoubleValue();
+	}
+	
+	public double getApproximateWorstMatchValue(long[] originalArray){
+		if (aligner ==null || originalArray==null)
+   			return MesquiteDouble.unassigned;
+ 		MesquiteNumber score;
+		double worstScore = MesquiteDouble.unassigned;
+		int startLength = MesquiteInteger.maximum(1,originalArray.length-maxLengthDiff);
+   		int endLength = MesquiteInteger.minimum(data.getNumChars(),originalArray.length+maxLengthDiff);
+   		for (int length = startLength; length<=endLength; length++) {
+   	  		score = aligner.getVeryBadScore(originalArray, length, alphabetLength);
+
+   	  		if (!MesquiteDouble.isCombinable(worstScore))
+   	  			worstScore = score.getDoubleValue();
+	  		if ((aligner.getHigherIsBetter() && (worstScore>score.getDoubleValue())) || (!aligner.getHigherIsBetter() && (worstScore<score.getDoubleValue()))) {
+	  			worstScore = score.getDoubleValue();
+	  		}
+  		}
+   		
+    		return worstScore;
+	}
+
+		
+		/** Returns whether candidate stretch of matrix matches the data contained in the long array*/
+   	public double sequenceMatch(long[] originalArray, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar){
+   		if (data==null || aligner ==null || originalArray==null)
+   			return MesquiteDouble.unassigned;
+  		
+   		double numberOfMatches = 0.0;
+   		int basesCompared =0;
+   		
+   		int startLength = MesquiteInteger.maximum(1,originalArray.length-maxLengthDiff);
+   		int endLength = MesquiteInteger.minimum(data.getNumChars(),originalArray.length+maxLengthDiff);
+   		MesquiteNumber score = new MesquiteNumber();
+   		double bestScore = MesquiteDouble.unassigned;
+   		int bestLength = originalArray.length;
+   		for (int length = startLength; length<=endLength; length++) {
+   	  		long[] candidateArray = ((CategoricalData)data).getLongArray(candidateStartChar,length,candidateTaxon, false);
+   	  		candidateArray = getTransformedCandidateArray(candidateArray);
+   	  		aligner.alignSequences(originalArray,candidateArray,false,score);
+   	  		double newScore = 1.0*score.getIntValue();
+   	  		if ((aligner.getHigherIsBetter() && (newScore>bestScore)) || (!aligner.getHigherIsBetter() && (newScore<bestScore))) {
+   	  			bestScore = newScore;
+   	  			bestLength = length;
+   	  		}
+   	  	}
+   		
+
+   		if (candidateEndChar!=null)
+   			candidateEndChar.setValue(MesquiteInteger.minimum(candidateStartChar + bestLength-1, data.getNumChars()-1));
+   		return bestScore;
+	}
+   	/*.................................................................................................................*/
+	 public abstract long[] 	getTransformedCandidateArray(long[] candidateArray);
+ 
+	 
+ 		MesquiteInteger pos = new MesquiteInteger(0);
+ 		/*.................................................................................................................*/
+ 		public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+  			if (checker.compare(this.getClass(), "Sets the maximum number of length differences between the two sequences", "[number]", commandName, "setMaxLengthDiff")) {
+ 				int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+ 				if (!MesquiteInteger.isCombinable(newNum))
+ 					newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Allowed Length Differences", "Allowed Length Differences:", maxLengthDiff, 0, MesquiteInteger.infinite);
+ 				if (newNum>=0  && newNum!=maxLengthDiff) {
+ 					maxLengthDiff = newNum;
+ 					parametersChanged();
+ 				}
+ 			}
+ 			else
+ 				return  super.doCommand(commandName, arguments, checker);
+ 			return null;
+ 		}
+
+}
+
diff --git a/Source/mesquite/align/lib/AlignScoreForTaxonGen.java b/Source/mesquite/align/lib/AlignScoreForTaxonGen.java
new file mode 100644
index 0000000..75189f1
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignScoreForTaxonGen.java
@@ -0,0 +1,197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.lib;
+
+import mesquite.align.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* TODO: 
+ *   allow user to alter pairwise alignment parameters
+ */
+
+public abstract class AlignScoreForTaxonGen extends NumberForTaxon {
+	protected MatrixSourceCoord matrixSourceTask;
+	protected Taxa currentTaxa = null;
+	protected MCharactersDistribution observedStates =null;
+	protected PairwiseAligner aligner;
+	protected int alphabetLength;
+	protected MesquiteInteger comparisonTaxon = new MesquiteInteger(0);
+	//MesquiteTimer timer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, new RequiresAnyDNAData(), "Source of character matrix (for number of stops)"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		//timer =  new MesquiteTimer();
+		addMenuItem("Reference Taxon...", MesquiteModule.makeCommand("setReferenceTaxon", this));
+		/*
+		 pairwiseTask = (TwoSequenceAligner)hireEmployee(TwoSequenceAligner.class, "Pairwise Aligner");
+		 if (pairwiseTask == null)
+		 return sorry(getName() + " couldn't start because no pairwise aligner obtained.");
+		 */		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (comparisonTaxon.getValue()!=0)
+			temp.addLine("setReferenceTaxon " + comparisonTaxon.getValue());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** Override if one wishes to modify the alignment costs away from the default. */
+	public int[][] modifyAlignmentCosts(int[][] defaultSubs) {
+		return defaultSubs;
+	}
+	/*.................................................................................................................*/
+	public void initAligner() {
+		MesquiteInteger gapOpen = new MesquiteInteger();
+		MesquiteInteger gapExtend = new MesquiteInteger();
+		MesquiteInteger gapOpenTerminal = new MesquiteInteger();
+		MesquiteInteger gapExtendTerminal = new MesquiteInteger();
+		AlignUtil.getDefaultGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);  
+		int subs[][] = AlignUtil.getDefaultSubstitutionCosts(alphabetLength);  
+		subs = modifyAlignmentCosts(subs);
+		aligner = new PairwiseAligner(false,subs,gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue(), alphabetLength);
+		aligner.setUseLowMem(true);
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+		
+	}
+	
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (taxon == null || comparisonTaxon == null)
+			return;
+		Taxa taxa = taxon.getTaxa();
+		if (comparisonTaxon.getValue()<0 || comparisonTaxon.getValue()>=taxa.getNumTaxa())
+			comparisonTaxon.setValue(0);
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null || !(observedStates.getParentData() instanceof DNAData))
+			return;
+		DNAData data = (DNAData)observedStates.getParentData();
+		if (data == null)
+			return;
+		MesquiteNumber score = new MesquiteNumber();
+		
+		
+		if (aligner==null) {
+			alphabetLength = ((CategoricalState)data.makeCharacterState()).getMaxPossibleState()+1;	  
+			initAligner();
+		}
+		
+		getAlignmentScore(data, (MCategoricalDistribution)observedStates,comparisonTaxon.getValue(),it,score);
+		
+		
+		if (result !=null)
+			result.setValue(score);
+		if (resultString!=null)
+			resultString.setValue(getScoreName() + " of sequence in matrix "+ observedStates.getName() + ": " + score.getIntValue());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	protected abstract void getAlignmentScore(DNAData data, MCategoricalDistribution observedStates, int it1, int it2, MesquiteNumber score) ;
+	
+	/*.................................................................................................................*/
+	public boolean queryReferenceTaxon() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Reference Taxon",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		
+		int maxNum = MesquiteInteger.unassigned;
+		if (currentTaxa!=null)
+			maxNum = currentTaxa.getNumTaxa();
+		IntegerField refTaxonField = dialog.addIntegerField("Reference Taxon", comparisonTaxon.getValue()+1, 8, 1, maxNum);
+		
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			comparisonTaxon.setValue(refTaxonField.getValue()-1);
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Allows one to specify which taxon is the reference taxon.", "[taxon number]", commandName, "setReferenceTaxon")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int newRefTaxon = MesquiteInteger.fromString(arguments, io);
+			if (newRefTaxon<0 ||  !MesquiteInteger.isCombinable(newRefTaxon)){
+				queryReferenceTaxon();
+			}
+			else{
+				comparisonTaxon.setValue(newRefTaxon);
+			}
+			parametersChanged();
+			
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public abstract String getScoreName() ;
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	
+	public String getParameters() {
+		return getScoreName() + " of sequence in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+	
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the " + getScoreName() + " for a taxon in a data matrix." ;
+	}
+	
+}
+
+
+
diff --git a/Source/mesquite/align/lib/AlignTool.java b/Source/mesquite/align/lib/AlignTool.java
new file mode 100644
index 0000000..18529ac
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignTool.java
@@ -0,0 +1,53 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.align.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+	/** This subclass of TableTool is used in data windows for aligning data; adds an edgeCursor for between cells.
+	*/
+public class AlignTool extends TableTool {
+	MesquiteCursor edgeCursor=null;
+	MesquiteCursor optionEdgeCursor=null;
+	
+	
+	public AlignTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String extraImageFileName, int extraHotX, int extraHotY, String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand dragCommand, MesquiteCommand droppedCommand) {
+		super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation, touchedCommand, dragCommand, droppedCommand);
+		this.initiator = initiator;
+		this.name = name;
+		
+		edgeCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, extraImageFileName, extraHotX, extraHotY);
+	}
+	public void setOptionEdgeCursor(String extraImageFileName, int extraHotX, int extraHotY) {
+		optionEdgeCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, extraImageFileName, extraHotX, extraHotY);
+	}
+	public void cursorInCell(int modifiers, int column, int row, int regionInCellH, int regionInCellV, EditorPanel panel){
+		if ((regionInCellH<20 ||  regionInCellH>80) && edgeCursor!=null)  {
+			setCurrentStandardCursor(edgeCursor);
+			if (optionEdgeCursor!=null)
+				setCurrentOptionCursor(optionEdgeCursor);
+		}
+		else {
+			setCurrentStandardCursor(null);
+			if (optionCursor!=null)
+				setCurrentOptionCursor(optionCursor);
+		}
+	}
+	
+}
+
diff --git a/Source/mesquite/align/lib/AlignUtil.java b/Source/mesquite/align/lib/AlignUtil.java
new file mode 100644
index 0000000..c578d4f
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignUtil.java
@@ -0,0 +1,576 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib;
+/*~~  */
+
+import java.util.*;
+import java.util.zip.CRC32;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AlignUtil {
+	StringBuffer sb = new StringBuffer();
+	private boolean checksumValid = false;
+	CRC32 checksum = new CRC32();
+	
+	public long getChecksum(Object o, int it, int icStart, int icEnd){
+		if (o instanceof MolecularData){
+			MolecularData data = (MolecularData)o;
+			checksum.reset();
+			for (int ic = icStart; ic<=icEnd; ic++){
+				long s = data.getState(ic, it);
+				if (!CategoricalState.isInapplicable(s))
+					checksum.update(Long.toString(s).getBytes());
+			}
+			return checksum.getValue();
+		}
+		else if (o instanceof MCategoricalDistribution){
+			MCategoricalDistribution data = (MCategoricalDistribution)o;
+			checksum.reset();
+			for (int ic = icStart; ic<=icEnd; ic++){
+				long s = data.getState(ic, it);
+				if (!CategoricalState.isInapplicable(s))
+					checksum.update(Long.toString(s).getBytes());
+			}
+			return checksum.getValue();
+		}
+		else if (o instanceof long[][]){
+			long[][] states = (long[][])o;
+			checksum.reset();
+			for (int ic = 0; ic<states.length; ic++){
+				long s = states[ic][it];
+				if (!CategoricalState.isInapplicable(s))
+					checksum.update(Long.toString(s).getBytes());
+			}
+			return checksum.getValue();
+		}
+		else if (o instanceof long[]){
+			long[] states = (long[])o;
+			checksum.reset();
+			for (int ic = 0; ic<states.length; ic++){
+				long s = states[ic];
+				if (!CategoricalState.isInapplicable(s))
+					checksum.update(Long.toString(s).getBytes());
+			}
+			return checksum.getValue();
+		}
+		return 0;
+	}
+	
+	/** given an original matrix, orig,  */	
+	int findTaxonAligned(MolecularData orig, int itOrig, int itAlignedStart, Object aligned){
+		if (aligned instanceof String[])
+			return itOrig+itAlignedStart;
+		if (aligned instanceof long[][])
+			return itOrig+itAlignedStart;
+		if (aligned instanceof long[])  //there is only one taxon here
+			return itAlignedStart;
+		if (aligned instanceof CharacterData){
+			Taxa origTaxa = orig.getTaxa();
+			Taxa alignTaxa = ((CharacterData)aligned).getTaxa();
+			if (origTaxa == alignTaxa)
+				return itOrig+itAlignedStart;
+			else
+				return alignTaxa.whichTaxonNumber(origTaxa.getTaxonName(itOrig));
+		}
+		if (aligned instanceof MCategoricalDistribution){
+			Taxa origTaxa = orig.getTaxa();
+			Taxa alignTaxa = ((MCategoricalDistribution)aligned).getTaxa();
+			if (origTaxa == alignTaxa)
+				return itOrig+itAlignedStart;
+			else
+				return alignTaxa.whichTaxonNumber(origTaxa.getTaxonName(itOrig));
+		}
+		
+		return itOrig+itAlignedStart;
+	}
+	int getNumChars(Object o){
+		if (o == null)
+			return 0;
+		if (o instanceof String[]){
+			String[] s = (String[])o;
+			if (s.length == 0)
+				return 0;
+			if (s[0] == null)
+				return 0;
+			return s[0].length();
+		}
+		if (o instanceof long[][])
+			return ((long[][])o).length;
+		if (o instanceof long[])
+			return ((long[])o).length;
+		if (o instanceof CharacterData){
+			CharacterData data = (CharacterData)o;
+			return data.getNumChars();
+		}
+		else if (o instanceof MCategoricalDistribution){
+			MCategoricalDistribution data = (MCategoricalDistribution)o;
+			return data.getNumChars();
+		}
+		return 0;
+	}
+	boolean isInapplicable(Object o, int ic, int it){
+		if (o == null)
+			return true;
+		if (o instanceof String[]){
+			String[] s = (String[])o;
+			if (it >= s.length)
+				return true;
+			if (s[it] == null)
+				return true;
+			if (ic >= s[it].length())
+				return true;
+			return s[it].charAt(ic) == '-' || s[it].charAt(ic) == '0';
+		}
+		if (o instanceof long[][] ){
+			long[][] s = (long[][])o;
+			if (ic >= s.length)
+				return true;
+			if (s[ic] == null)
+				return true;
+			if (it >= s[ic].length)
+				return true;
+			return CategoricalState.isInapplicable(s[ic][it]) || s[ic][it]==0L;
+		}
+		if (o instanceof long[]){
+			long[] s = (long[])o;
+			if (s == null)
+				return true;
+			if (ic >= s.length)
+				return true;
+			return CategoricalState.isInapplicable(s[ic]) || s[ic]==0L;
+		}
+		if (o instanceof CharacterData){
+			CharacterData data = (CharacterData)o;
+			if (it >= data.getNumTaxa() || ic >= data.getNumChars())
+				return true;
+			return data.isInapplicable(ic, it);
+		}
+		if (o instanceof MCategoricalDistribution){
+			MCategoricalDistribution data = (MCategoricalDistribution)o;
+			if (it >= data.getNumTaxa() || ic >= data.getNumChars())
+				return true;
+			return CategoricalState.isInapplicable(data.getState(ic, it));
+		}
+		return true;
+	}
+	boolean sameState(CategoricalData orig, int icOrig, int itOrig, Object o, int icAligned, int itAligned){
+		if (o == null)
+			return false;
+		if (o instanceof long[][] ){
+			long[][] s = (long[][])o;
+			if (icAligned >= s.length)
+				return false;
+			if (s[icAligned] == null)
+				return false;
+			if (itAligned >= s[icAligned].length)
+				return false;
+			long aligned = CategoricalState.setUncertainty(s[icAligned][itAligned],false);
+			long origState = CategoricalState.setUncertainty(orig.getState(icOrig, itOrig),false);
+			if (!((CategoricalState.statesBitsMask & s[icAligned][itAligned]) == (CategoricalState.statesBitsMask & orig.getState(icOrig, itOrig))))
+				MesquiteMessage.println("   Incorporation mismatch, aligned: " + aligned + ", orig: " + origState);
+			
+			return (CategoricalState.statesBitsMask & s[icAligned][itAligned]) == (CategoricalState.statesBitsMask & orig.getState(icOrig, itOrig));
+		}
+		if (o instanceof long[] ){
+			long[] s = (long[])o;
+			if (s == null)
+				return false;
+			if (icAligned >= s.length)
+				return false;
+			long aligned = s[icAligned];
+			long origState = orig.getState(icOrig, itOrig);
+			if (!((CategoricalState.statesBitsMask & s[icAligned]) == (CategoricalState.statesBitsMask & orig.getState(icOrig, itOrig))))
+				MesquiteMessage.println("   Incorporation mismatch, aligned: " + aligned + ", orig: " + origState);
+			
+			return (CategoricalState.statesBitsMask & s[icAligned]) == (CategoricalState.statesBitsMask & orig.getState(icOrig, itOrig));
+		}
+		if (o instanceof String[]){
+			String[] s = (String[])o;
+			if (itAligned >= s.length)
+				return false;
+			if (s[itAligned] == null)
+				return false;
+			if (icAligned >= s[itAligned].length())
+				return false;
+			sb.setLength(0);
+			orig.statesIntoStringBuffer(icOrig, itOrig, sb, true);
+			if (sb.length()!= 1)
+				return false;
+			return s[itAligned].charAt(icAligned) == sb.charAt(0);
+		}
+		else if (o instanceof CategoricalData){
+			CategoricalData aligned = (CategoricalData)o;
+			return aligned.getState(icAligned, itAligned) == orig.getState(icOrig, itOrig);
+		}
+		else if (o instanceof MCategoricalDistribution){
+			MCategoricalDistribution aligned = (MCategoricalDistribution)o;
+			return aligned.getState(icAligned, itAligned) == orig.getState(icOrig, itOrig);
+		}
+		return false;
+	}
+	
+	/** This inserts the needed new characters into the matrix contained in the MolecularData object.  The number of new characters
+	 * to be inserted at each site is contained in the newGaps array.  Those sites that are to receive new terminal gaps are indicated
+	 * by the values of preSequenceTerminalFlaggedGap and postSequenceTerminalFlaggedGap.
+	 * */
+	public void  insertNewGaps(MolecularData data, int[] newGaps,  int preSequenceTerminalFlaggedGap,  int postSequenceTerminalFlaggedGap){
+		//preSequenceTerminalFlaggedGap,  int postSequenceTerminalFlaggedGap added DRM 7 Aug 2014
+		int start = newGaps.length-1;
+		if (data.getNumChars()<newGaps.length)
+			start = data.getNumChars()-1;
+		for (int ic = start; ic>=0; ic--) {  // go down from last characters to see if there are any gaps that need to be inserted, and insert them.
+			if (newGaps[ic]>0){
+				data.addCharacters(ic-1, newGaps[ic], false); 
+				data.addInLinked(ic-1, newGaps[ic], false);
+			}
+		}
+		start = newGaps.length-1;
+		if (data.getNumChars()<newGaps.length)
+			start = data.getNumChars()-1;
+		
+		for (int ic = start; ic>=0; ic--) {   // go down from start and look for negative values denoting terminal gaps at the END that might need to be inserted
+			if (newGaps[ic]<0 && postSequenceTerminalFlaggedGap==ic){  // negative value AND this is the array position marked as the terminal gap AFTER the sequence
+				int numGaps = - newGaps[ic] - (data.getNumChars()-1-ic);  // are extra characters needed?
+				if (numGaps>0) {
+					data.addCharacters(data.getNumChars(), numGaps, false); 
+					data.addInLinked(data.getNumChars(), numGaps, false);
+				}
+				newGaps[ic]=0;  // have to zero it so that it isn't acted upon by the next loop.  *** added by DRM 7 Aug 2014
+				break;
+			} 
+		}
+		
+		for (int ic = 0; ic<data.getNumChars() && ic<newGaps.length; ic++) {   // go up from zero and look for negative values denoting terminals
+			if (newGaps[ic]<0 && preSequenceTerminalFlaggedGap==ic){ // negative value AND this is the array position marked as the terminal gap BEFORE the sequence
+				int numGaps = - newGaps[ic] - (ic);  // are extra characters needed?
+				if (numGaps>0) {
+					data.addCharacters(0, numGaps, false); 
+					data.addInLinked(0, numGaps, false);
+				}
+				break;
+			}
+		}
+	}
+	
+	/** This takes the original data matrix "origData", and re-aligns the block from icOrigStart, icOrigEnd, itOrigStart, and itOrigEnd 
+	 * according to the alignment present in alignedSequences.   Note that alignedData need not be exactly the same same size as the block.  
+	 * In particular, sometimes there will be more sequences in alignedSequences than in origData.  The sequences to which origData should be
+	 * matched should start within alignedSequences at itAlignedStart.
+	 * */
+	public Rectangle forceAlignment(MolecularData origData, int icOrigStart, int icOrigEnd, int itOrigStart, int itOrigEnd, int itAlignedStart, Object alignedSequences){
+		if (!MesquiteInteger.isCombinable(icOrigStart) || icOrigStart<0)
+			icOrigStart = 0;
+		if (!MesquiteInteger.isCombinable(icOrigEnd) || icOrigEnd<0)
+			icOrigEnd = origData.getNumChars()-1;
+		if (!MesquiteInteger.isCombinable(itOrigStart) || itOrigStart<0)
+			itOrigStart = 0;
+		if (!MesquiteInteger.isCombinable(itOrigEnd) || itOrigEnd<0)
+			itOrigEnd = origData.getNumTaxa()-1;
+		int numCharsAligned = getNumChars(alignedSequences);
+		int numCharsOrig = icOrigEnd-icOrigStart+1;
+		int[] charsToAddToOrig = new int[numCharsOrig];
+		for (int ic = 0; ic<numCharsOrig; ic++)
+			charsToAddToOrig[ic] = 0;
+		int csproblem = -1;
+		int numTaxaInOrig = itOrigEnd - itOrigStart+1;  //numtaxa within the matrix.  this should match the number of taxa in "aligned"
+		long[] checkSums = new long[numTaxaInOrig];
+		//checksums on original matrix
+		for (int it = 0; it<numTaxaInOrig; it++)
+			checkSums[it] = getChecksum(origData, it+itOrigStart,  0, origData.getNumChars()-1);
+		
+		if (numCharsAligned>numCharsOrig) {
+			origData.addCharacters(icOrigEnd, numCharsAligned-numCharsOrig, false);
+			origData.addInLinked(icOrigEnd, numCharsAligned-numCharsOrig, false);
+			numCharsOrig = numCharsAligned;
+		}
+		//prepareAligned(alignedSequences);
+		Rectangle rect = null;
+		boolean failed = false;
+		String failedReportString = "";
+		for (int itOrig = itOrigStart; itOrig<=itOrigEnd; itOrig++){   //cycle through taxa in "aligned"
+			int itAligned = findTaxonAligned(origData, itOrig-itOrigStart, itAlignedStart, alignedSequences);  //this gives one the taxon number within "aligned"
+			if (itAligned>=0){
+				int icAligned = 0;
+				int icOrig = icOrigStart;
+				int icOrigEnd2 = icOrigStart+numCharsOrig-1;
+				while(icAligned < numCharsAligned && icOrig <= icOrigEnd2){ //keep marching along looking for mismatch of gaps
+					
+					// start at left side; proceed as long as both gaps or both nucleotides.  
+					while (icAligned< numCharsAligned && icOrig <= icOrigEnd2 && ((isInapplicable(alignedSequences, icAligned, itAligned) && isInapplicable(origData, icOrig, itOrig)) || (!isInapplicable(alignedSequences, icAligned, itAligned) && !isInapplicable(origData, icOrig, itOrig)))){
+						icAligned++;
+						icOrig++;
+					}
+					//aligned and orig differ at this point on whether gap or nucleotide; push or pull original accordingly
+					if (icAligned < numCharsAligned && icOrig <= icOrigEnd2) {
+						// if aligned has gap, need to open up gap in orig.  
+						if (isInapplicable(alignedSequences, icAligned, itAligned)) {
+							int startOfGapAligned = icAligned;
+							//first, find end of gap in aligned to know how much has to be opened in original
+							while(icAligned < numCharsAligned && isInapplicable(alignedSequences, icAligned, itAligned))
+								icAligned++;
+							
+							if (icAligned<numCharsAligned){
+								int gapSize = icAligned-startOfGapAligned;
+								//now know how big of a gap is needed; push original to match
+								//in case gaps that can be eaten up in orig are not all at end, but push block by block until a big enough gap has opened
+								int spaceNeeded = gapSize;
+								while (spaceNeeded >0){
+									int startOfGapOrig = icOrig;
+									int endOfGapOrig = -1;
+									while (startOfGapOrig <= icOrigEnd2 && !origData.isInapplicable(startOfGapOrig, itOrig))
+										startOfGapOrig++;
+									if (origData.isInapplicable(startOfGapOrig, itOrig)){ //actually is gap
+										endOfGapOrig = startOfGapOrig;
+										while (endOfGapOrig <= icOrigEnd2 && origData.isInapplicable(endOfGapOrig, itOrig))
+											endOfGapOrig++;
+										endOfGapOrig--;
+										if (origData.isInapplicable(endOfGapOrig, itOrig)){
+											int spaceAvailable = endOfGapOrig-startOfGapOrig +1;
+											int gapToUse = spaceNeeded;
+											if (spaceAvailable<spaceNeeded)
+												gapToUse = spaceAvailable;
+											int added = origData.moveCells(icOrig, startOfGapOrig-1, gapToUse, itOrig,itOrig, false, true, true, false,null,null, null);
+											icOrig += gapToUse;
+											spaceNeeded -= gapToUse;
+											if (added>0)
+												MesquiteMessage.warnProgrammer("Alignment added characters when shouldn't have");
+										}
+										else 
+											spaceNeeded = 0;
+									}
+									else 
+										spaceNeeded = 0; 
+								}
+							}
+						}
+						// if original has gap, pull accordingly from end of chunk forward
+						else {
+							int startOfGap = icOrig;
+							//findEndOf gap
+							while(icOrig <= icOrigEnd2 && isInapplicable(origData, icOrig, itOrig))
+								icOrig++;
+							if (icOrig<=icOrigEnd2){
+								int gapSize = icOrig-startOfGap;
+								//now know how big of a gap must be closed
+								int added = origData.moveCells(icOrig, icOrigEnd2, -gapSize, itOrig,itOrig, false, true, true, false,null,null, null);
+								icOrig -= gapSize;
+								if (added>0)
+									MesquiteMessage.warnProgrammer("Alignment added characters when shouldn't have");
+							}
+						}
+					}
+				}
+				for (int ic = 0; ic < numCharsAligned; ic++)
+					if (!sameState(origData, ic+icOrigStart, itOrig, alignedSequences, ic, itAligned)) {
+						if (!failed){ //firsttime
+							rect = new Rectangle(ic+icOrigStart, itOrig , ic, itAligned);
+						}
+						failed = true;
+						failedReportString = "At least one site has had its character state changed (site " + ic + "). ";
+						break;
+					}
+				
+				
+			}
+		}
+		
+		//checksums on alignment
+		for (int it = 0; it<numTaxaInOrig && csproblem == -1; it++){
+			long cs = getChecksum(origData, it+itOrigStart,  0, origData.getNumChars()-1);
+			if (cs != checkSums[it]) {
+				csproblem = it;
+				failedReportString += " Sequence " + it + " failed checksum.";
+			}
+		}
+		if (csproblem >=0){
+			rect = new Rectangle(0, csproblem , origData.getNumChars()-1, csproblem);
+			failed = true;
+		}
+		if (failed)
+			MesquiteTrunk.mesquiteTrunk.alert("ERROR: alignment incorporation failed to recover states as in aligned matrix. " + failedReportString);
+		else {
+			MesquiteTrunk.mesquiteTrunk.logln("Checksum passed for incorporating data alignment. ");
+			if (numCharsAligned< icOrigEnd-icOrigStart+1 && numTaxaInOrig == origData.getNumTaxa()) {  // the aligned section has fewer characters than the old section
+				int ic = icOrigEnd;  //set ic to the end of the piece aligned in the original matrix
+				int numToDelete=0;
+				int firstDelete = -1;
+				while (origData.entirelyInapplicable(ic) && ic >= icOrigStart + numCharsAligned) {
+					if (origData.entirelyInapplicable(ic)) {
+						numToDelete++;
+						firstDelete=ic;
+					}
+					ic--;
+				}
+				if (firstDelete>=0){
+					origData.deleteCharacters(firstDelete, numToDelete, false); 
+					origData.deleteInLinked(firstDelete, numToDelete, false); 
+				}
+			}
+		}
+		return rect;
+		
+	}
+	
+	public static void getDefaultGapCosts(MesquiteInteger gapOpen, MesquiteInteger gapExtend, MesquiteInteger gapOpenTerminal, MesquiteInteger gapExtendTerminal){
+		if (gapOpen!=null)
+			gapOpen.setValue(8);
+		if (gapExtend!=null)
+			gapExtend.setValue(3);
+		if (gapOpenTerminal!=null)
+			gapOpenTerminal.setValue(2);
+		if (gapExtendTerminal!=null)
+			gapExtendTerminal.setValue(2);
+	}
+	
+	/*.................................................................................................................*/
+	public static int[][] getDefaultSubstitutionCosts(int alphabetLength){
+		
+		int subs[][] =  new int[alphabetLength][alphabetLength];	
+		for (int i = 0; i<alphabetLength; i++) 
+			for (int j = 0; j<alphabetLength; j++) {
+				if (i!=j)
+					subs[i][j] = 5;
+				else
+					subs[i][j] = 0;
+			}
+		if (alphabetLength==4) {  //then  it should be DNA
+			subs[0][1] = subs[1][0] = subs[0][3] = subs[3][0] = 10; //transversions involving A
+			subs[2][3] = subs[3][2] = subs[1][2] = subs[2][1]= 10; //transversions involving G
+		}
+		return subs;
+	}
+	
+	/*.................................................................................................................*/
+	/** Given a matrix, int[][] subs, containing costs for going from state i to state j, 
+	 *  and two int a and b representing 32-bit state sets, and the alphabetLength, this
+	 *  method calculates the minimum cost for going between the two statesets. 
+	 *  Note that this presumes multiple states in each state set represents ambiguity!
+	 */
+	public static int getCost(int[][] subs, int a, int b, int alphabetLength) {
+		if ((a & b) != 0 || CategoricalState.isUnassignedInt(a) || CategoricalState.isUnassignedInt(b))  //  the sets intersect, so there is no cost
+			return 0;
+		int minCost = Integer.MAX_VALUE;
+		for (int elementA=0; elementA<alphabetLength; elementA++)   
+			if (((1<<elementA)&a)!=0){ //then e is in set a
+				for (int elementB=0; elementB<alphabetLength; elementB++)
+					if (((1<<elementB)&b)!=0){ //then e is in set b
+						if (minCost>subs[elementA][elementB])
+							minCost = subs[elementA][elementB];   // find the minimum cost between a member of a and a member of b
+					}
+			}
+		if (minCost==Integer.MAX_VALUE) {
+			return 0;
+		}
+		return minCost;
+		
+	}
+	
+	/*.................................................................................................................*/
+	public static boolean queryGapCosts(MesquiteWindow parent, MesquiteModule module, MesquiteInteger gapOpen, MesquiteInteger gapExtend, MesquiteInteger gapOpenTerminal, MesquiteInteger gapExtendTerminal) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(parent, "Gap Costs",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		
+		IntegerField gapOpenField=null;
+		IntegerField gapExtendField=null;
+		IntegerField gapOpenTerminalField=null;
+		IntegerField gapExtendTerminalField=null;
+		
+		if (gapOpen!=null)
+			gapOpenField = dialog.addIntegerField("Gap Opening Cost", gapOpen.getValue(), 5, 0, 1000);
+		if (gapExtend!=null)
+			gapExtendField = dialog.addIntegerField("Gap Extension Cost", gapExtend.getValue(), 5, 0, 1000);
+		if (gapOpenTerminal!=null)
+			gapOpenTerminalField = dialog.addIntegerField("Terminal Gap Opening Cost", gapOpenTerminal.getValue(), 5, 0, 1000);
+		if (gapExtendTerminal!=null)
+			gapExtendTerminalField = dialog.addIntegerField("Terminal Gap Extension Cost", gapExtendTerminal.getValue(), 5, 0, 1000);
+		
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			if (gapOpen!=null)
+				gapOpen.setValue(gapOpenField.getValue());
+			if (gapExtend!=null)
+				gapExtend.setValue(gapExtendField.getValue());
+			if (gapOpenTerminal!=null)
+				gapOpenTerminal.setValue(gapOpenTerminalField.getValue());
+			if (gapExtendTerminal!=null)
+				gapExtendTerminal.setValue(gapExtendTerminalField.getValue());
+			module.storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+
+	/*.................................................................................................................*/
+	public static boolean querySubCosts(MesquiteWindow parent, MesquiteModule module, Integer2DArray subArray, String[] labels) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(parent, "Substitution Costs",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		
+		IntegerSqMatrixFields subsField;
+		int[][] matrix = subArray.getMatrix();
+		if (matrix.length<11)
+			subsField = new IntegerSqMatrixFields(dialog, matrix, labels, false, false, 3);
+		else
+			subsField = new IntegerSqMatrixFields(dialog, matrix, labels, false, false, 2);
+		subsField.setLastValueEditable(true);
+		
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			module.storePreferences();
+			subArray.setValues(subsField.getInteger2DArray());
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean integrateAlignment(long[][] alignedMatrix, MolecularData data, int icStart, int icEnd, int itStart, int itEnd){
+		if (alignedMatrix == null || data == null)
+			return false;
+		AlignUtil util = new AlignUtil();
+		Rectangle problem = null;
+		//alignedMatrix.setName("Aligned (" + data.getName() + ")");
+		boolean wasSel;
+		if (data.anySelected()) {
+			wasSel = true;
+		}
+		else {
+			wasSel = false;
+		}
+		MesquiteTrunk.mesquiteTrunk.logln("Alignment for " + (icEnd-icStart+1) + " sites; aligned to " + alignedMatrix.length + " sites.");
+		problem = util.forceAlignment(data, icStart, icEnd, itStart, itEnd, 0, alignedMatrix);
+		if (wasSel) {
+			data.deselectAll();
+			int numCharsOrig = icEnd-icStart+1;
+			if (alignedMatrix.length>numCharsOrig)
+				numCharsOrig = alignedMatrix.length;
+			for (int i = icStart; i<icStart + numCharsOrig; i++)
+				data.setSelected(i, true);
+
+		}
+		MesquiteTrunk.mesquiteTrunk.logln("Alignment completed.");
+
+		return true;
+	}	
+
+}
+
diff --git a/Source/mesquite/align/lib/AlignmentHelper.java b/Source/mesquite/align/lib/AlignmentHelper.java
new file mode 100644
index 0000000..5a6304e
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignmentHelper.java
@@ -0,0 +1,105 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.lib;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.Debugg;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteNumber;
+
+public abstract class AlignmentHelper {
+
+	int[] A;
+	int[] B;		
+	
+	int[][] subs;
+	int gapOpen;
+	int gapExtend;
+	int gapOpenTerminal;
+	int gapExtendTerminal;	
+	int alphabetLength;
+	boolean isMinimize = true;
+	
+	int lengthA, lengthB;
+	int gapInsertionArray[];
+
+	
+	
+	long[][] ReInsertGaps (int k, int[] followsGapSize, int totalGapChars, boolean seqsWereExchanged, long[][] inputSequence) {	
+	
+		int i,j;
+		//put the gaps back in
+		long gappedSeq2return[][] = new long[k+totalGapChars][2];
+		gapInsertionArray = new int[k+totalGapChars];
+		for(i=0; i<k+totalGapChars; i++) {
+			gapInsertionArray[i] = 0;
+		}
+		
+		int usedGaps=0;
+		int recentGapRunLength=0;
+		j=0; // counts the number of letters in A seen so far
+		int retainedGapsSeen = 0;
+		boolean onLeftEnd = true;
+		int numPosnsToShift=0; // used at most, in the event of a terminal original gap in A that's longer than the one in the alignmnt of A and B  
+		for (i=0; i<k; i++) {
+			if(inputSequence[i][0] == CategoricalState.inapplicable) {
+				recentGapRunLength++;
+				if (j+retainedGapsSeen < gapInsertionArray.length && j < followsGapSize.length) //Wayne's workaround to crash
+				gapInsertionArray[j+retainedGapsSeen] = Math.max(0, recentGapRunLength - followsGapSize[j]);
+				if (j< followsGapSize.length && followsGapSize[j] > recentGapRunLength) { 	
+					retainedGapsSeen++;
+				}
+			} else {
+				if ( onLeftEnd && i == retainedGapsSeen && followsGapSize[j]>recentGapRunLength ){
+					numPosnsToShift = retainedGapsSeen; // used at most once, to make the left side of the alignment look right 
+														// in the event of a terminal original gap in A that's longer than the one in the alignmnt of A and B
+				}
+				for (int m=0 ; m < followsGapSize[j]-recentGapRunLength; m++){
+					gappedSeq2return[i+usedGaps][0] =  CategoricalState.inapplicable; 
+					gappedSeq2return[i+usedGaps][1] =  CategoricalState.inapplicable; 
+					usedGaps++;
+					retainedGapsSeen++;
+				}
+				if (numPosnsToShift>0) {//will only happen at most once, in special terminal gap case
+					int c; 
+					long tmp[] = new long[numPosnsToShift];
+					for (c=0; c<numPosnsToShift; c++){
+						tmp[c] = gappedSeq2return[c][1];
+						gappedSeq2return[c][1] = CategoricalState.inapplicable;
+					}
+					for (c=0; c<numPosnsToShift; c++){
+						gappedSeq2return[retainedGapsSeen-numPosnsToShift+c][1] = tmp[c];				
+					}
+					numPosnsToShift = 0;
+				}				
+				onLeftEnd = false;
+				j++;
+				recentGapRunLength=0;
+			}
+			gappedSeq2return[i+usedGaps][0] = inputSequence[i][0] ;
+			gappedSeq2return[i+usedGaps][1] = inputSequence[i][1] ;
+		}		
+		
+		return gappedSeq2return;	
+	}
+
+	
+	
+	public int[] getGapInsertionArray () {
+		return gapInsertionArray;
+	}			
+		
+	
+	
+}
+
diff --git a/Source/mesquite/align/lib/AlignmentHelperLinearSpace.java b/Source/mesquite/align/lib/AlignmentHelperLinearSpace.java
new file mode 100644
index 0000000..8f7e552
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignmentHelperLinearSpace.java
@@ -0,0 +1,411 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.lib;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.Debugg;
+import mesquite.lib.IntegerArray;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteMessage;
+import mesquite.lib.MesquiteNumber;
+import mesquite.lib.MesquiteTrunk;
+
+public class AlignmentHelperLinearSpace extends AlignmentHelper {
+
+	
+	boolean keepGaps = false;
+	int[] followsGapSize;	
+	
+	/* enumerting the possible shapes (preceding and succeding) */
+	public static int noGap = 0;
+	public static int gapInA = 1;
+	public static int gapInB = 2;
+	
+	public int bigNumber = MesquiteInteger.infinite/3; // can't use "infinite", because adding anything to it makes a negative number ... bad for minimization problems
+	
+	/* forward arrays*/
+	public int fH[];
+	public int fD[];
+	public int fV[];
+	
+	/*reverse arrays*/
+	public int rH[];
+	public int rD[];
+	public int rV[];	
+
+	private int lastB_BeforeNextA[]; 
+	private int shapeLeavingPosInA[];
+	
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int alphabetLength) {
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpen, gapExtend, alphabetLength, false);
+	}
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength) {
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal, alphabetLength, false);
+	}
+	
+	
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int alphabetLength, boolean keepGaps, int[] followsGapSize) {
+		this.keepGaps = keepGaps;
+		this.followsGapSize = followsGapSize;
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpen, gapExtend, alphabetLength, false);
+	}
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength, boolean keepGaps, int[] followsGapSize) {
+		this.keepGaps = keepGaps;
+		this.followsGapSize = followsGapSize;
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal, alphabetLength, false);
+	}	
+	
+	
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int alphabetLength, boolean forwardArrayOnly) {
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpen, gapExtend, alphabetLength, forwardArrayOnly);
+	}
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength, boolean forwardArrayOnly) {
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal, alphabetLength, forwardArrayOnly);
+	}
+
+	
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int alphabetLength, boolean forwardArrayOnly, boolean keepGaps, int[] followsGapSize) {
+		this.keepGaps = keepGaps;
+		this.followsGapSize = followsGapSize;
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpen, gapExtend, alphabetLength, forwardArrayOnly);
+	}
+	public AlignmentHelperLinearSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength, boolean forwardArrayOnly, boolean keepGaps, int[] followsGapSize) {
+		this.keepGaps = keepGaps;
+		this.followsGapSize = followsGapSize;
+		initialize(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal, alphabetLength, forwardArrayOnly);
+	}	
+	
+	
+	private void initialize (int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength, boolean forwardArrayOnly) {
+		A = seq1;
+		B = seq2;
+
+		this.subs = subs;
+		this.gapOpen = gapOpen;
+		this.gapExtend = gapExtend;
+		this.gapOpenTerminal = gapOpenTerminal;
+		this.gapExtendTerminal = gapExtendTerminal;
+
+		
+		fH = new int[lengthB+1];
+		fD = new int[lengthB+1];
+		fV = new int[lengthB+1];
+		rH = new int[lengthB+1];
+		rD = new int[lengthB+1];
+		rV = new int[lengthB+1];
+		
+		this.alphabetLength = alphabetLength;
+
+		this.lengthA = lengthA;
+		this.lengthB = lengthB;
+		
+		lastB_BeforeNextA = new int[lengthA +1];
+		shapeLeavingPosInA  = new int[lengthA +1];
+	}
+
+	public void fillArrays (int firstRow, int lastRow, int firstColumn, int lastColumn, int precedingShape, int succeedingShape) {
+		int middleRow = (firstRow+lastRow)/2;
+		fillForward(firstRow, middleRow, firstColumn, lastColumn, precedingShape);
+		fillReverse(middleRow+1,lastRow, firstColumn, lastColumn, succeedingShape);
+	}
+	
+	
+	public void fillForward(int firstRow, int lastRow, int firstColumn, int lastColumn, int shape) {
+		
+		int i,j;
+		
+		int gapExtendOnB, gapExtendOnA;
+		int gapOpenOnB, gapOpenOnA;		
+
+		fH[firstColumn] = fV[firstColumn] =   (0==firstColumn) ? gapOpenTerminal : gapOpen;
+		fD[firstColumn] = 0;
+		
+		if (shape == gapInA) {
+			fH[firstColumn] = 0;
+		} else if ( shape == gapInB) {
+			fV[firstColumn] = 0;
+		}
+
+		//fill row-by-row. First row is a special case
+		gapExtendOnA = (0==firstRow || lengthA==firstRow) ? gapExtendTerminal : gapExtend ;
+		for (j=firstColumn+1; j<=lastColumn; j++) {
+			fD[j] = fV[j] = bigNumber;
+			fH[j] = fH[j-1] + gapExtendOnA;
+        }
+
+
+		int tmp1H, tmp1D, tmp1V, tmp2H, tmp2D, tmp2V;
+	//reuse the arrays, treating it as the next row in the DP table. Keep one temp variable for each array
+		for (i=firstRow+1; i<=lastRow; i++) { // for each "row" in DP table
+			tmp1H = fH[firstColumn];
+			tmp1D = fD[firstColumn];
+			tmp1V = fV[firstColumn];
+		
+			fD[firstColumn] = fH[firstColumn] = bigNumber;
+			fV[firstColumn] += (0==firstColumn || lengthB==firstColumn) ? gapExtendTerminal : gapExtend ;
+
+			gapOpenOnA =  (lengthA==i) ? gapOpenTerminal : gapOpen;
+			gapExtendOnA = (lengthA==i) ? gapExtendTerminal : gapExtend ;
+			//gapOpenOnA = gapOpen;
+			if (keepGaps &&  i<followsGapSize.length && followsGapSize[i]>0)
+				gapOpenOnA = 0;
+
+			
+			for (j=firstColumn+1; j<=lastColumn; j++) { // for each column
+				tmp2H = fH[j];
+				tmp2D = fD[j];
+				tmp2V = fV[j];
+
+				gapOpenOnB =  (lengthB==j) ? gapOpenTerminal : gapOpen;
+				gapExtendOnB = (lengthB==j) ? gapExtendTerminal : gapExtend ;
+				
+				if (isMinimize) {
+					fV[j] = Math.min(  fH[j] + gapOpenOnB + gapExtendOnB,  
+							Math.min ( fD[j]  + gapOpenOnB + gapExtendOnB ,
+									   fV[j] + gapExtendOnB));
+
+					fH[j] = Math.min(  fH[j-1] + gapExtendOnA,  
+							Math.min ( fD[j-1] + gapOpenOnA + gapExtendOnA,
+					  				   fV[j-1] + gapOpenOnA + gapExtendOnA));
+	
+					fD[j] = AlignUtil.getCost(subs,A[i-1],B[j-1],alphabetLength) +  Math.min(  tmp1H, Math.min ( tmp1D , tmp1V));
+				} else { //maximize
+					fV[j] = Math.max(  fH[j] + gapOpenOnB + gapExtendOnB,  
+							Math.max ( fD[j] + gapOpenOnB + gapExtendOnB ,
+									   fV[j] + gapExtendOnB));
+					
+					fH[j] = Math.max(  fH[j-1] + gapExtendOnA,  
+							Math.max(  fD[j-1] + gapOpenOnA + gapExtendOnA,
+									   fV[j-1] + gapOpenOnA + gapExtendOnA));
+					
+					fD[j] = AlignUtil.getCost(subs,A[i-1],B[j-1],alphabetLength) +  Math.max(  tmp1H , Math.max( tmp1D, tmp1V ));
+				}
+
+				tmp1H = tmp2H;
+				tmp1D = tmp2D;
+				tmp1V = tmp2V;
+			}
+		}
+	}
+
+	public void fillReverse(int firstRow, int lastRow, int firstColumn, int lastColumn, int shape) {
+
+	    int i,j;
+		int gapExtendOnA;
+		int gapOpenOnA;	
+		if (lastColumn<0){
+			MesquiteTrunk.mesquiteTrunk.logln("LastColumn in AlignmentHelperLinearSpace.fillReverse is NEGATIVE!");
+			return;
+		}
+		rH[lastColumn] = rV[lastColumn] = (lengthB==lastColumn) ? gapOpenTerminal : gapOpen;;
+		rD[lastColumn] = 0;
+		
+		if (shape == gapInA || (keepGaps &&  lastRow<followsGapSize.length && followsGapSize[lastRow]>0)) {
+			rH[lastColumn] = 0;
+		} else if ( shape == gapInB) {
+			rV[lastColumn] = 0;
+		}
+		
+		//fill row-by-row. Last row is a special case 
+		gapExtendOnA = (0==lastRow || lengthA==lastRow) ? gapExtendTerminal : gapExtend ;
+		for (j=lastColumn-1; j>=firstColumn; j--) {
+			rD[j] = rV[j] = bigNumber;
+            rH[j] = rH[j+1] + gapExtendOnA;
+		}
+		
+		int tmp1H, tmp1D, tmp1V, tmp2H, tmp2D, tmp2V;
+		//reuse the arrays, treating it as the next row in the DP table. Keep one temp variable for each array
+		for (i=lastRow-1; i>=firstRow; i--) { // for each "row" in DP table
+			tmp1H = rH[lastColumn];
+			tmp1D = rD[lastColumn];
+			tmp1V = rV[lastColumn];
+
+			rD[lastColumn] = rH[lastColumn] = bigNumber ;
+			rV[lastColumn] +=  (0==lastColumn || lengthB==lastColumn) ? gapExtendTerminal : gapExtend ;
+			
+			gapOpenOnA =  (0==i) ? gapOpenTerminal : gapOpen;
+			gapExtendOnA = (0==i) ? gapExtendTerminal : gapExtend ;
+
+			if (keepGaps &&  i<followsGapSize.length && followsGapSize[i]>0) // followsGapSize[i] means reversePrecedsGapSize[i-1]
+				gapOpenOnA = 0;
+			
+			for (j=lastColumn-1; j>=firstColumn; j--) { // for each column
+				tmp2H = rH[j];
+				tmp2D = rD[j];
+				tmp2V = rV[j];
+
+				
+				if (isMinimize) {
+					rV[j] = Math.min(  rH[j] + gapOpen + gapExtend,  
+							Math.min ( rD[j]  + gapOpen + gapExtend ,
+											 rV[j] + gapExtend));
+					
+					rH[j] = Math.min(  rH[j+1] + gapExtend,  
+								Math.min ( rD[j+1] + gapOpenOnA + gapExtend,
+												 rV[j+1] + gapOpenOnA + gapExtend));
+	
+					rD[j] = AlignUtil.getCost(subs,A[i],B[j],alphabetLength) +  Math.min(  tmp1H, Math.min ( tmp1D , tmp1V));		
+				} else { //maximize
+				
+					rV[j] = Math.max(  rH[j] + gapOpen + gapExtend,  
+								Math.max ( rD[j] + gapOpen + gapExtend ,
+												 rV[j] + gapExtend));					
+
+					rH[j] = Math.max(  rH[j+1] + gapExtend,  
+							Math.max( rD[j+1] + gapOpenOnA + gapExtend,
+											rV[j+1] + gapOpenOnA + gapExtend));
+
+					rD[j] = AlignUtil.getCost(subs,A[i],B[j],alphabetLength)  +  Math.max(  tmp1H , Math.max( tmp1D, tmp1V ));
+				}
+				tmp1H = tmp2H;
+				tmp1D = tmp2D;
+				tmp1V = tmp2V;
+			}
+		}
+	}
+
+	/** Fills in portions of the full DP-table, then identifies which column (corresponding to a position in seqB) 
+	 * an optimal alignment must pass through in the middle row (corresponding to the middle of seqA) of the full DP table.
+	 * Fills shape array, which is used by recoverAlignment to find the actual alignment.  
+	 * */
+	public int recursivelyFillArray(int firstRow, int lastRow, int firstColumn, int lastColumn, int precedingShape, int succeedingShape) {
+
+		int gapOpenOnB, gapExtendOnB;		
+		
+		//Height (of the 2d array)=lengthA, Width = lengthB
+		
+		fillArrays(firstRow, lastRow, firstColumn, lastColumn, precedingShape, succeedingShape );
+		
+		int midRow = (firstRow + lastRow)/2;  //in seqA
+
+		int i, verticalColScore, diagonalColScore; 
+		int bestColScore = bigNumber , bestCol = -1, bestColShape = noGap;
+		for (i=firstColumn; i<=lastColumn; i++) {
+			gapOpenOnB  =  (0==i || lengthB==i) ? gapOpenTerminal : gapOpen;
+			gapExtendOnB = (0==i || lengthB==i) ? gapExtendTerminal : gapExtend ;
+			// best of the ways of leaving the i,j cell of the full DP table with a vertical edge 
+			verticalColScore = Math.min(fH[i] + rH[i] + gapExtendOnB + gapOpenOnB,
+							Math.min(fH[i] + rD[i] + gapExtendOnB + gapOpenOnB,
+							Math.min(fH[i] + rV[i] + gapExtendOnB,
+							Math.min(fD[i] + rH[i] + gapExtendOnB + gapOpenOnB,
+							Math.min(fD[i] + rD[i] + gapExtendOnB + gapOpenOnB,
+							Math.min(fD[i] + rV[i] + gapExtendOnB,			
+							Math.min(fV[i] + rH[i] + gapExtendOnB,
+							Math.min(fV[i] + rD[i] + gapExtendOnB,
+										fV[i] + rV[i] + gapExtendOnB - gapOpenOnB))))))));			
+
+			// best of the ways of leaving the i,j cell of the full DP table with a diagonal edge
+			if (i == lastColumn) { 
+				diagonalColScore = verticalColScore + 1; // i.e. don't allow diagonal exit from i,j (make diagonalColScore > verticalColScore) 
+					//why not leave with a diagonal? because "leaving" means "going to the first row of the reverse table" ... 
+				    //  and there isn't a column called "lastColumn+1" to go to in the reverse table  
+			} else {
+				int a = A[midRow];
+				int b = B[i];
+				int s = AlignUtil.getCost(subs,a,b,alphabetLength);
+				diagonalColScore = Math.min(fH[i], Math.min (fD[i], fV[i])) +
+								   Math.min(rH[i+1], Math.min (rD[i+1], rV[i+1])) +
+								   s;
+			}
+			// no need to track horizontal edges - those are already stored in the forward and reverse arrays
+			if (verticalColScore < diagonalColScore) {
+				if ( verticalColScore < bestColScore) {
+					bestColScore = verticalColScore;
+					bestCol = i;
+					bestColShape = gapInB;
+				}
+			} else {
+				if ( diagonalColScore < bestColScore) {
+					bestColScore = diagonalColScore;
+					bestCol = i;
+					bestColShape = noGap;
+				}				
+			}
+		}
+		lastB_BeforeNextA[midRow] = bestCol;
+		shapeLeavingPosInA[midRow] = bestColShape;
+				
+
+		//	Recurse to find the full list of cells through which the alignment passes.
+		if ( firstRow != midRow){
+			recursivelyFillArray(firstRow, midRow, firstColumn, bestCol, precedingShape, bestColShape);
+		}
+		if (midRow+1 != lastRow){
+			int col_shift = (bestColShape == noGap) ? /*diagonal*/ 1 : /*vertical*/ 0;
+			recursivelyFillArray(midRow+1, lastRow, bestCol+col_shift, lastColumn, bestColShape, succeedingShape); 
+		}
+		
+		return bestColScore; // useful for the first level of recursion - returns the total alignment cost
+	}
+	
+	/**  Based on the shape array filled out by the recursive call above, determine the alignment 
+	 * */
+	public long[][] recoverAlignment (int totalGapChars, boolean seqsWereExchanged) {
+		int i=0, j=0, k=0;
+		
+		long[][] alignment = new long[lengthA + lengthB][2];
+		for (i = 0; i<lengthA; i++) {
+
+			//gap in A
+			while ( j < lastB_BeforeNextA[i] ) {
+				alignment[k][0] = CategoricalState.inapplicable;
+				alignment[k][1] = CategoricalState.expandFromInt(B[j]);
+				j++;
+				k++;					
+			}
+
+			//now we're ready to burn off a letter from B, and possibly a letter from A if diagonal.
+			alignment[k][0] = CategoricalState.expandFromInt(A[i]);
+			if (shapeLeavingPosInA[i] == noGap) {
+				alignment[k][1] = CategoricalState.expandFromInt(B[j]);
+				j++;
+			} else {		// gap In B								
+				alignment[k][1] = CategoricalState.inapplicable;
+			}
+			k++;
+		}
+
+		while (j < lengthB) { //gap in A at the end 
+			alignment[k][0] = CategoricalState.inapplicable;
+			alignment[k][1] = CategoricalState.expandFromInt(B[j]);
+			j++;
+			k++;					
+		}		
+		
+		
+		//trim off all the empty space at the end
+		long seq2return[][] = new long[k][2];
+		int ii=0; 		
+		for (i=0; i<k; i++) {
+			if (seqsWereExchanged) {//exhange the sequences
+				seq2return[i][0] = alignment[i][1];
+				seq2return[i][1] = alignment[i][0];				
+			} else {
+				seq2return[i][0] = alignment[i][0];
+				seq2return[i][1] = alignment[i][1];
+			}
+		}
+				
+		
+
+		if (keepGaps) {
+			return ReInsertGaps(k, followsGapSize, totalGapChars, seqsWereExchanged, seq2return) ;
+			
+		}  else {
+			return seq2return;
+		}
+	}
+	
+}
+
+
diff --git a/Source/mesquite/align/lib/AlignmentHelperQuadraticSpace.java b/Source/mesquite/align/lib/AlignmentHelperQuadraticSpace.java
new file mode 100644
index 0000000..c14d280
--- /dev/null
+++ b/Source/mesquite/align/lib/AlignmentHelperQuadraticSpace.java
@@ -0,0 +1,217 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.lib;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.*;
+
+public class AlignmentHelperQuadraticSpace extends AlignmentHelper {	
+	
+    public int bigNumber = MesquiteInteger.infinite/3; // can't use "infinite", because adding anything to it makes a negative number ... bad for minimization problems
+
+    public AlignmentHelperQuadraticSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int alphabetLength) {
+		this(seq1, seq2, lengthA, lengthB, subs, gapOpen, gapExtend, gapOpen, gapExtend, alphabetLength);
+	}
+
+	public AlignmentHelperQuadraticSpace(int[] seq1, int[] seq2, int lengthA, int lengthB, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength) {
+		A = seq1;
+		B = seq2;
+		this.lengthA = lengthA;
+		this.lengthB = lengthB;
+		this.subs = subs;
+		this.gapOpen = gapOpen;
+		this.gapExtend = gapExtend;
+		this.gapOpenTerminal = gapOpenTerminal;
+		this.gapExtendTerminal = gapExtendTerminal;		
+		this.alphabetLength=alphabetLength;
+	}
+	
+	public long[][] doAlignment (boolean returnAlignment, MesquiteNumber score, boolean keepGaps, int[] followsGapSize, int totalGapChars) {
+		//Height = lengthA, Width = lengthB
+		
+		int H[][] = new int[lengthA+1][lengthB+1];
+		int D[][] = new int[lengthA+1][lengthB+1];
+		int V[][] = new int[lengthA+1][lengthB+1];
+
+		int i,j;
+		
+		//first column
+		for (i=1; i<=lengthA; i++) {
+          V[i][0] = gapOpenTerminal + gapExtendTerminal*i;
+          H[i][0] = D[i][0] = bigNumber;
+		}
+		
+		//first row
+		for (j=1; j<=lengthB; j++) {
+			H[0][j] = gapOpenTerminal + gapExtendTerminal*j;
+			V[0][j] = D[0][j] = bigNumber;
+		}
+		
+		int gapOpenOnA, gapOpenOnB, gapExtendOnA, gapExtendOnB;
+		for (i=1; i<=lengthA; i++) {
+
+			gapOpenOnA =  (i==lengthA) ? gapOpenTerminal : gapOpen;
+			gapExtendOnA = (i==lengthA) ? gapExtendTerminal : gapExtend ;			
+			if (keepGaps && i<followsGapSize.length && followsGapSize[i]>0) {
+				gapOpenOnA = 0;
+			}
+
+			for (j=1; j<=lengthB; j++) {
+//				look at three preceding values.				
+
+				gapOpenOnB =  (j==lengthB) ? gapOpenTerminal : gapOpen;
+				gapExtendOnB = (j==lengthB) ? gapExtendTerminal : gapExtend ;
+				
+				if (isMinimize) {
+					V[i][j] = Math.min(  V[i-1][j] + gapExtendOnB,  
+							  Math.min ( D[i-1][j] + gapOpenOnB + gapExtendOnB,
+										 H[i-1][j] + gapOpenOnB + gapExtendOnB));
+	
+					H[i][j] = Math.min(  V[i][j-1] + gapOpenOnA + gapExtendOnA,  
+							  Math.min ( D[i][j-1] + gapOpenOnA + gapExtendOnA ,
+										 H[i][j-1] + gapExtendOnA));
+
+					D[i][j] = AlignUtil.getCost(subs,A[i-1],B[j-1],alphabetLength)  +  Math.min(  V[i-1][j-1] , Math.min ( D[i-1][j-1] , H[i-1][j-1] ));
+				} else { //maximize
+					V[i][j] = Math.max( V[i-1][j] + gapExtendOnB,
+							  Math.max( D[i-1][j] + gapOpenOnB + gapExtendOnB,
+										H[i-1][j] + gapOpenOnB + gapExtendOnB));
+				
+					H[i][j] = Math.max(  V[i][j-1] + gapOpenOnA + gapExtendOnA,  
+							  Math.max ( D[i][j-1] + gapOpenOnA + gapExtendOnA ,
+										 H[i][j-1] + gapExtendOnA));
+	
+					D[i][j] = AlignUtil.getCost(subs,A[i-1],B[j-1],alphabetLength) +  Math.max(  V[i-1][j-1] , Math.max( D[i-1][j-1] , H[i-1][j-1] ));
+				}
+			}
+		}
+
+        
+		i--;
+		j--;
+		int myScore ;
+		if (isMinimize) {
+			myScore = Math.min ( H[i][j], Math.min (D[i][j] ,V[i][j] )) ;
+		} else {
+			myScore = Math.max ( H[i][j], Math.max (D[i][j] ,V[i][j] )) ;
+		}
+		
+		if (score != null)
+			score.setValue( myScore );
+
+		if ( !returnAlignment) { //save space
+			return null;
+		}
+		
+		//Trace back for sequence:
+		long backtrack[][] = new long[lengthA+lengthB][2];
+		int k=0;
+		i = lengthA;
+		j = lengthB;
+		int a_cnt = 0; //count of letters from A used in path so far 
+		while (i>0 || j>0 ) {
+			
+			if (i ==0) { 
+				while (j>0){
+					backtrack[k][0] = CategoricalState.inapplicable;
+					backtrack[k][1] = CategoricalState.expandFromInt(B[j-1]);
+					j--;
+					k++;
+				}
+			} else if ( j == 0 ) {
+				while (i>0){
+					backtrack[k][0] = CategoricalState.expandFromInt(A[i-1]);
+					backtrack[k][1] = CategoricalState.inapplicable;
+					i--;
+					k++;
+					a_cnt++;
+				}				
+			} else if  ( V[i][j] == myScore) { //an optimal path came from vertical (letter from A with gap in B)
+				gapOpenOnB =  (j==lengthB) ? gapOpenTerminal : gapOpen;
+				gapExtendOnB = (j==lengthB) ? gapExtendTerminal : gapExtend ;				
+				
+				backtrack[k][0] = CategoricalState.expandFromInt(A[i-1]);
+				backtrack[k][1] = CategoricalState.inapplicable;
+				if ( V[i][j] == V[i-1][j] + gapExtendOnB){
+					myScore -= gapExtendOnB;
+				} else { //V[i][j]  == D[i-1][j] + gapOpen + gapExtend  or V[i][j] == H[i-1][j] + gapOpen + gapExtend
+					myScore -= gapOpenOnB + gapExtendOnB;
+				}
+				i--;
+				k++;
+				a_cnt++;
+			} else if (H[i][j] == myScore) { //an optimal path came from horizontal (letter from B with gap in A)
+				gapOpenOnA=  (i==lengthA) ? gapOpenTerminal : gapOpen;
+				gapExtendOnA= (i==lengthA) ? gapExtendTerminal : gapExtend ;				
+			
+				if (keepGaps && i<followsGapSize.length && followsGapSize[i]>0)
+					gapOpenOnA = 0;
+				
+				backtrack[k][0] = CategoricalState.inapplicable;
+				backtrack[k][1] = CategoricalState.expandFromInt(B[j-1]);
+				if ( H[i][j] == H[i][j-1] + gapExtendOnA){
+					myScore -= gapExtendOnA;
+				} else { //H[i][j]  == D[i-1][j] + gapOpen + gapExtend  or H[i][j] == V[i-1][j] + gapOpen + gapExtend
+						myScore -= gapOpenOnA + gapExtendOnA;
+				}
+				j--;
+				k++;
+			} else if (D[i][j] == myScore) { // from diagonal
+				backtrack[k][0] = CategoricalState.expandFromInt(A[i-1]);
+				backtrack[k][1] = CategoricalState.expandFromInt(B[j-1]);
+				myScore -= AlignUtil.getCost(subs,A[i-1],B[j-1],alphabetLength) ;
+				i--;
+				j--;
+				k++;
+				a_cnt++;
+			} else { 
+				// error
+				MesquiteMessage.println ("Error in recovering alignment");
+				MesquiteMessage.println ("   myScore: " + myScore);
+				MesquiteMessage.println ("   i = " + i + ", j = " + j);
+				MesquiteMessage.println ("   D[i][j]: " + D[i][j]);
+				MesquiteMessage.println ("   V[i][j]: " + V[i][j]);
+				MesquiteMessage.println ("   H[i][j]: " + H[i][j]);
+				MesquiteMessage.println ("   D[i][j]: " + D[i][j]);
+				return null;
+			}
+		}
+		
+		//reverse the sequence, and trim off all the empty space at the end
+		long seq2return[][] = new long[k][2];
+		int left  = 0;          // index of leftmost element
+		int right = k-1; // index of rightmost element
+		  
+		while (left <= right) {
+		      seq2return[left][0]  = backtrack[right][0]; 
+		      seq2return[right][0] = backtrack[left][0];
+
+		      seq2return[left][1]  = backtrack[right][1]; 
+		      seq2return[right][1] = backtrack[left][1];
+		      
+		      // move the bounds toward the center
+		      left++;
+		      right--;
+		}
+				
+		if (keepGaps) {
+			return ReInsertGaps(k, followsGapSize, totalGapChars, false, seq2return) ;
+		} else {
+			return seq2return;
+		}
+		
+	}
+	
+}
+
+
diff --git a/Source/mesquite/align/lib/BlockMover.java b/Source/mesquite/align/lib/BlockMover.java
new file mode 100644
index 0000000..2bffb7e
--- /dev/null
+++ b/Source/mesquite/align/lib/BlockMover.java
@@ -0,0 +1,454 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public abstract class BlockMover extends DataWindowAssistantI {
+	protected MesquiteTable table;
+	CharacterData  data;
+	int currentNumChars = 0;
+	int currentNumTaxa = 0;
+
+	protected AlignTool moveTool;
+	CellBlock cellBlock =null;
+	boolean defaultCanExpand = false;
+	MesquiteBoolean canExpand =new MesquiteBoolean(defaultCanExpand);
+
+	MesquiteBoolean warnCheckSum = new MesquiteBoolean(true);
+	long originalCheckSum;
+	int edgePercent = 20;
+	int previousPercentHorizontal=0;
+	int previousColumnDragged=-2;
+	int firstColumnTouched = -2;
+	int effectiveFirstColumnTouched = -2;
+	int firstRowTouched = -2;
+	boolean betweenCells = false;
+	boolean atLeftEdgeOfCell = false;
+	boolean atRightEdgeOfCell = false;
+	boolean alreadyMoved = false;
+	boolean lastWasMoveRight=false;
+	boolean optionDown = false;
+	MesquiteBoolean liveUpdate;
+	boolean defaultLiveUpdate = false;
+	MesquiteBoolean dataChanged = new MesquiteBoolean(false);
+	UndoReference undoReference = null;
+
+	public Class getDutyClass() {
+		return BlockMover.class;
+	}
+	public String getDutyName() {
+		return "Block Mover";
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand touchCommand = MesquiteModule.makeCommand("moveTouchCell",  this);
+			touchCommand.setSuppressLogging(true);
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("moveDragCell",  this);
+			dragCommand.setSuppressLogging(true);
+			MesquiteCommand dropCommand = MesquiteModule.makeCommand("moveDropCell",  this);
+			dropCommand.setSuppressLogging(true);
+			moveTool = new AlignTool(this, getToolName(), getPath(), getCellToolImageFileName(), getCellToolHotSpot().x,getCellToolHotSpot().y,getSplitToolImageFileName(), getSplitToolHotSpot().x,getSplitToolHotSpot().y,getFullDescriptionForTool(),getExplanationForTool(), touchCommand, dragCommand, dropCommand);
+			setOptionTools();
+			//moveTool.setUseTableTouchRules(true);
+			((MesquiteWindow)containerOfModule()).addTool(moveTool);
+			moveTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching on button
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		addPopUpMenuItems();
+		liveUpdate = new MesquiteBoolean(defaultLiveUpdate);
+		addCheckMenuItem(null, "Live update of analyses, etc.", makeCommand("toggleLiveUpdate",  this), liveUpdate);
+		addCheckMenuItem(null, "Can expand matrix", makeCommand("toggleCanExpand",  this), canExpand);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public abstract String getToolName();
+	/*.................................................................................................................*/
+	public abstract String getCellToolImageFileName();
+	/*.................................................................................................................*/
+	public abstract Point getCellToolHotSpot();
+	/*.................................................................................................................*/
+	public abstract String getSplitToolImageFileName();
+	/*.................................................................................................................*/
+	public abstract Point getSplitToolHotSpot();
+	/*.................................................................................................................*/
+	public abstract String getExplanationForTool();
+	/*.................................................................................................................*/
+	public abstract String getFullDescriptionForTool();
+	/*.................................................................................................................*/
+	public void addPopUpMenuItems(){
+	}
+	/*.................................................................................................................*/
+	public void setOptionTools(){
+	}
+	/*.................................................................................................................*/
+	public boolean allowSplits(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveLeft(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canMoveRight(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSelectedBlock(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSequenceToLeft(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSequenceToRight(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean getOptionDown(){
+		return optionDown;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//David:  add compatibility check for CategoricalData
+		if (!(data instanceof CategoricalData))
+			return;
+		this.table = table;
+		this.data = data;
+		currentNumChars = data.getNumChars();
+		currentNumTaxa = data.getNumTaxa();
+		initialize(table,data);
+	}
+	/*.................................................................................................................*/
+	public void initialize(MesquiteTable table, CharacterData data){
+		cellBlock = new mesquite.lib.characters.CellBlock((CategoricalData)data, table);
+		currentNumChars = data.getNumChars();
+		currentNumTaxa = data.getNumTaxa();
+
+	}
+	/*.................................................................................................................*/
+	public void checkCellBlockIntegrity(MesquiteTable table, CharacterData data){
+		if (data.getNumChars()!=currentNumChars || data.getNumTaxa()!=currentNumTaxa) {
+			initialize(table,data);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (liveUpdate.getValue()!=defaultLiveUpdate)
+			temp.addLine("toggleLiveUpdate " + liveUpdate.toOffOnString());
+		if (canExpand.getValue()!=defaultCanExpand)
+			temp.addLine("toggleCanExpand " + canExpand.toOffOnString());
+		return temp;
+	}
+	boolean movingRight = false;
+	int storedPreviousColumnDragged = MesquiteInteger.unassigned;
+	int storedPreviousPercentHorizontal = MesquiteInteger.unassigned;
+	int gapsAvailableToRight = 0;
+	int gapsAvailableToLeft = 0;
+	boolean directionRecorded = false;
+	boolean pleaseDefineCellBlock = false;
+
+
+	/*.................................................................................................................*/
+	private boolean mouseDragged(String arguments) {
+		MesquiteInteger io = new MesquiteInteger(0);
+		int columnDragged = MesquiteInteger.fromString(arguments, io);
+		int rowDragged= MesquiteInteger.fromString(arguments, io);
+
+		int percentHorizontal= MesquiteInteger.fromString(arguments, io);
+		if (!table.rowLegal(rowDragged)|| !table.columnLegal(columnDragged) || (previousColumnDragged == columnDragged && previousPercentHorizontal == percentHorizontal))
+			return false;
+		if (!canMoveRight() && columnDragged>effectiveFirstColumnTouched)
+			columnDragged = effectiveFirstColumnTouched;
+		if (!canMoveLeft() && columnDragged<effectiveFirstColumnTouched)
+			columnDragged = effectiveFirstColumnTouched;
+		int moveFromOriginal = columnDragged-effectiveFirstColumnTouched;
+		//	boolean switchDirections = movingRight != moveFromOriginal>0;
+		movingRight = moveFromOriginal>0;
+		if (!directionRecorded) {  // first time dragged, need to record details of move direction for next time through
+
+			if (moveFromOriginal>0 || (moveFromOriginal==0 &&  previousPercentHorizontal > percentHorizontal)) {
+				movingRight = true;
+				lastWasMoveRight = true;
+				directionRecorded = true;
+				pleaseDefineCellBlock = true;
+			} else if (moveFromOriginal<0 || (moveFromOriginal==0 &&  previousPercentHorizontal < percentHorizontal)) {
+				movingRight = false;
+				lastWasMoveRight = false;
+				directionRecorded = true;
+				pleaseDefineCellBlock = true; 
+			}
+
+		} else {
+			//	boolean switchDirections = movingRight != moveFromOriginal>0;
+			int moveFromPrevious = columnDragged-previousColumnDragged;
+			previousColumnDragged = columnDragged;
+			previousPercentHorizontal = percentHorizontal;
+			MesquiteBoolean isTerminalBlock = new MesquiteBoolean(false);
+			MesquiteInteger boundaryOfAvailableSpace = new MesquiteInteger(0);
+
+			if (canMoveRight() && betweenCells && (moveFromOriginal>0 || (moveFromOriginal==0 && previousPercentHorizontal > percentHorizontal)) && (!lastWasMoveRight || pleaseDefineCellBlock)) {  //was dragging left, now switch to dragging right
+
+
+				if (alreadyMoved)
+					cellBlock.restoreCharBlock(dataChanged);
+				if (atLeftEdgeOfCell)
+					effectiveFirstColumnTouched = firstColumnTouched;
+				else
+					effectiveFirstColumnTouched = firstColumnTouched+1;
+				moveFromOriginal = columnDragged-effectiveFirstColumnTouched;
+				cellBlock.switchCharBlock(effectiveFirstColumnTouched,cellBlock.getOriginalLastCharInFullBlock());
+				gapsAvailableToRight = data.checkCellMoveDistanceAvailable(data.getNumChars()-cellBlock.getCurrentLastCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+				gapsAvailableToLeft = data.checkCellMoveDistanceAvailable(-cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+
+				lastWasMoveRight = true;
+				alreadyMoved = false;
+				if (MesquiteInteger.isCombinable(storedPreviousColumnDragged))
+					previousColumnDragged = storedPreviousColumnDragged;
+				if (MesquiteInteger.isCombinable(storedPreviousPercentHorizontal))
+					previousPercentHorizontal = storedPreviousPercentHorizontal;
+				pleaseDefineCellBlock = false;
+			}
+			else if (canMoveLeft() && betweenCells && (moveFromOriginal<0 || (moveFromOriginal==0 && previousPercentHorizontal < percentHorizontal)) &&  (lastWasMoveRight || pleaseDefineCellBlock)) {  //was dragging right, now switch to dragging left
+
+
+				if (alreadyMoved)
+					cellBlock.restoreCharBlock(dataChanged);
+				if (atLeftEdgeOfCell)
+					effectiveFirstColumnTouched = firstColumnTouched-1;
+				else
+					effectiveFirstColumnTouched = firstColumnTouched;
+				moveFromOriginal = columnDragged-effectiveFirstColumnTouched;
+
+				cellBlock.switchCharBlock(cellBlock.getOriginalFirstCharInFullBlock(),effectiveFirstColumnTouched);
+				gapsAvailableToRight = data.checkCellMoveDistanceAvailable(data.getNumChars()-cellBlock.getCurrentLastCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+				gapsAvailableToLeft = data.checkCellMoveDistanceAvailable(-cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+
+				lastWasMoveRight = false;
+				alreadyMoved = false;
+				if (MesquiteInteger.isCombinable(storedPreviousColumnDragged))
+					previousColumnDragged = storedPreviousColumnDragged;
+				if (MesquiteInteger.isCombinable(storedPreviousPercentHorizontal))
+					previousPercentHorizontal = storedPreviousPercentHorizontal;
+				pleaseDefineCellBlock = false;
+			}
+			else  if (moveFromOriginal>= gapsAvailableToLeft && moveFromOriginal <= gapsAvailableToRight) {
+				cellBlock.setCurrentCharBlock(cellBlock.getOriginalFirstCharInBlock()+moveFromOriginal,cellBlock.getOriginalLastCharInBlock()+ moveFromOriginal);
+
+				if (moveFromPrevious != 0) {  // move it over from previous position by this amount; at least, that is the request
+					int redrawStartBlock = cellBlock.getPreviousFirstCharInBlock();
+					int redrawEndBlock = cellBlock.getPreviousLastCharInBlock();
+					alreadyMoved= true;
+
+					int distanceToMove = data.checkCellMoveDistanceAvailable(moveFromPrevious, cellBlock.getPreviousFirstCharInBlock(), cellBlock.getPreviousLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+
+					if (distanceToMove!=0) {
+
+						if ((moveFromPrevious > 0 && distanceToMove<= moveFromPrevious) || (moveFromPrevious<0 && distanceToMove>=moveFromPrevious))  {  // we can't move it as much as desired
+							cellBlock.setCurrentCharBlock(cellBlock.getPreviousFirstCharInBlock()+distanceToMove,cellBlock.getPreviousLastCharInBlock()+ distanceToMove);
+						}
+						int showDistance = cellBlock.getCurrentFirstCharInBlock()-cellBlock.getOriginalFirstCharInBlock();
+						if (moveFromPrevious>0)
+							redrawEndBlock = cellBlock.getCurrentFirstCharInBlock()-1;
+						else 
+							redrawStartBlock = cellBlock.getCurrentLastCharInBlock()+1;
+
+
+						int added = data.moveCells(cellBlock.getPreviousFirstCharInBlock(), cellBlock.getPreviousLastCharInBlock(), distanceToMove, firstRowTouched,firstRowTouched, canExpand.getValue(), false, true, false,dataChanged,null, null);
+						if (added<0){ //now start adjusting all the values as we may have added taxa at the start of the matrix
+							added = -added;
+							cellBlock.addToCharBlockValues(added);
+							firstColumnTouched += added;
+							effectiveFirstColumnTouched += added;
+							columnDragged += added;
+							previousColumnDragged += added;
+						}
+						if (added!=0 || liveUpdate.getValue()) {
+							Notification notification = new Notification(MesquiteListener.DATA_CHANGED, new int[] {firstRowTouched});
+							notification.setSubcodes(new int[] {MesquiteListener.SINGLE_TAXON});
+							data.notifyListeners(this, notification);
+							data.notifyInLinked(notification);
+						}
+
+						//data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+						table.redrawBlock(MesquiteInteger.minimum(cellBlock.getPreviousFirstCharInBlock(),cellBlock.getCurrentFirstCharInBlock()) , firstRowTouched, MesquiteInteger.maximum(cellBlock.getPreviousLastCharInBlock(),cellBlock.getCurrentLastCharInBlock()), firstRowTouched);
+
+						//table.redrawBlockBlank(redrawStartBlock, firstRowTouched, redrawEndBlock, firstRowTouched); //draw the blanks that are opened up
+						//table.redrawBlockOffset(firstInBlock.getValue()+showDistance, firstRowTouched, lastInBlock.getValue()+showDistance , firstRowTouched, -showDistance, 0);
+					}
+				}
+			} else {
+				if (MesquiteInteger.isCombinable(storedPreviousColumnDragged))
+					previousColumnDragged = storedPreviousColumnDragged;
+				if (MesquiteInteger.isCombinable(storedPreviousPercentHorizontal))
+					previousPercentHorizontal = storedPreviousPercentHorizontal;
+
+			}
+			storedPreviousColumnDragged = previousColumnDragged;
+			storedPreviousPercentHorizontal = previousPercentHorizontal;
+			cellBlock.transferCurrentToPrevious();
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "move touched cell or selected cells", "[column touched] [row touched] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveTouchCell")) {
+			if (table!=null && data !=null && cellBlock !=null){
+				directionRecorded = false;
+				pleaseDefineCellBlock = false;
+				storedPreviousColumnDragged = MesquiteInteger.unassigned;
+				storedPreviousPercentHorizontal = MesquiteInteger.unassigned;
+
+				checkCellBlockIntegrity(table,data);
+				adjustSelection();
+				optionDown = arguments.indexOf("option")>=0;
+
+				MesquiteInteger io = new MesquiteInteger(0);
+				firstColumnTouched= MesquiteInteger.fromString(arguments, io);
+				effectiveFirstColumnTouched = firstColumnTouched;
+				firstRowTouched= MesquiteInteger.fromString(arguments, io);
+				originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars(),firstRowTouched, firstRowTouched);
+				int percentHorizontal= MesquiteInteger.fromString(arguments, io);
+				betweenCells = false;
+				atLeftEdgeOfCell = false;
+				atRightEdgeOfCell = false;
+				if (percentHorizontal<=edgePercent) {  //at far left edge of cell
+					if (allowSplits())
+						betweenCells = true;
+					atLeftEdgeOfCell = true;
+				}
+				if (percentHorizontal>=(100-edgePercent)) {  //at far right edge of cell
+					if (allowSplits())
+						betweenCells = true;
+					atRightEdgeOfCell = true;
+				}
+
+				previousPercentHorizontal = percentHorizontal;
+				MesquiteInteger firstInBlock= new MesquiteInteger();
+				MesquiteInteger lastInBlock= new MesquiteInteger();
+				MesquiteBoolean cellHasInapplicable = new MesquiteBoolean();
+				MesquiteBoolean leftIsInapplicable = new MesquiteBoolean();
+				MesquiteBoolean rightIsInapplicable = new MesquiteBoolean();
+				cellBlock.getBlockInSequence(firstColumnTouched, firstRowTouched, firstInBlock, lastInBlock,  wholeSelectedBlock(), wholeSequenceToLeft(), wholeSequenceToRight(), cellHasInapplicable, leftIsInapplicable, rightIsInapplicable);
+				if (cellHasInapplicable.getValue()){ // then the cell touched has inapplicable data
+					firstColumnTouched = -1;
+					return null;
+				}
+
+				cellBlock.setOriginalFullBlockOnTouch(firstInBlock.getValue(),lastInBlock.getValue(), firstRowTouched,firstRowTouched);
+				lastWasMoveRight=false;
+
+				if (betweenCells) {   //set it initially as if we were pulling to the rightho
+					if (atLeftEdgeOfCell) 
+						firstInBlock.setValue(firstColumnTouched);
+					else 
+						effectiveFirstColumnTouched = firstColumnTouched+1;
+					firstInBlock.setValue(effectiveFirstColumnTouched);
+				}
+				previousColumnDragged = effectiveFirstColumnTouched;
+				cellBlock.setAllBlocks(firstInBlock.getValue(),lastInBlock.getValue(), firstRowTouched,firstRowTouched);
+				if (!canExpand.getValue())
+					undoReference = new UndoReference(data,this,0,data.getNumChars(), firstRowTouched,firstRowTouched);
+				else
+					undoReference = new UndoReference(data,this, new int[] {UndoInstructions.CHAR_ADDED_TO_END, UndoInstructions.CHAR_ADDED_TO_START});
+				MesquiteBoolean isTerminalBlock = new MesquiteBoolean(false);
+				MesquiteInteger boundaryOfAvailableSpace = new MesquiteInteger(0);
+				gapsAvailableToRight = data.checkCellMoveDistanceAvailable(data.getNumChars()-cellBlock.getCurrentLastCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+				gapsAvailableToLeft = data.checkCellMoveDistanceAvailable(-cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentFirstCharInBlock(), cellBlock.getCurrentLastCharInBlock(), firstRowTouched,firstRowTouched, isTerminalBlock, boundaryOfAvailableSpace, canExpand.getValue());
+			}
+		}
+		else if (checker.compare(this.getClass(), "moving dragged.", "[column dragged] [row dragged] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveDragCell")) {
+			if (!mouseDragged(arguments))
+				return null;
+		}
+		else if (checker.compare(this.getClass(), "moving cells.", "[column dropped] [row dropped] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveDropCell")) {
+			if (table!=null && data !=null && (firstColumnTouched>=0)&& (firstRowTouched>=0)){
+				checkCellBlockIntegrity(table,data);
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDropped = MesquiteInteger.fromString(arguments, io);
+				int rowDropped= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(rowDropped)|| !table.columnLegal(columnDropped))
+					return null;
+				//		int moveFromOriginal = columnDropped-firstColumnTouched;
+				//		move(firstInBlock.getValue(), lastInBlock.getValue(), moveFromOriginal, firstRowTouched, false);
+				boolean success = ((CategoricalData)data).examineCheckSum(0, data.getNumChars(),firstRowTouched, firstRowTouched, "WARNING!  This tool has changed the data inappropriately!", warnCheckSum, originalCheckSum);
+				if (dataChanged.getValue()) {
+					Notification notification = new Notification(MesquiteListener.DATA_CHANGED, new int[] {firstRowTouched}, undoReference);
+					notification.setSubcodes(new int[] {MesquiteListener.SINGLE_TAXON});
+					data.notifyListeners(this, notification);
+					data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));
+				}
+				if (!success){
+					if (undoReference!=null) {
+						Undoer[] undoer = undoReference.getUndoer();
+						if (undoer!=null && undoer[0]!=null)
+							undoer[0].undo();
+					}
+				}
+				table.repaintAll();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether live update is active", "[on = live update; off]", commandName, "toggleLiveUpdate")) {
+			boolean current = liveUpdate.getValue();
+			liveUpdate.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether the matrix is allowed to expand if one attempts to move a block beyond the edges of the matrix.", "[on = canExpand; off]", commandName, "toggleCanExpand")) {
+			boolean current = canExpand.getValue();
+			canExpand.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	protected void adjustSelection() {
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Move block";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Moves blocks in a sequence." ;
+	}
+
+}
+
diff --git a/Source/mesquite/align/lib/ExternalSequenceAligner.java b/Source/mesquite/align/lib/ExternalSequenceAligner.java
new file mode 100644
index 0000000..b317552
--- /dev/null
+++ b/Source/mesquite/align/lib/ExternalSequenceAligner.java
@@ -0,0 +1,448 @@
+package mesquite.align.lib;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+/* ======================================================================== */
+public abstract class ExternalSequenceAligner extends MultipleSequenceAligner implements ActionListener{
+	String programPath;
+	SingleLineTextField programPathField =  null;
+	boolean preferencesSet = false;
+	boolean includeGaps = false;
+	String programOptions = "" ;
+	Random rng;
+	public static int runs = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random(System.currentTimeMillis());
+		programOptions = getDefaultProgramOptions();
+		loadPreferences();
+		return true;
+	}
+	public abstract String getProgramCommand();
+	public abstract String getProgramName();
+	public abstract String getDefaultProgramOptions();
+	public abstract String getDNAExportInterpreter () ;
+	public abstract String getProteinExportInterpreter () ;
+	public abstract String getDNAImportInterpreter () ;
+	public abstract String getExportExtension();
+	public abstract String getImportExtension();
+	public abstract String getProteinImportInterpreter () ;
+	public abstract void appendDefaultOptions(StringBuffer shellScript, String inFilePath, String outFilePath, MolecularData data);
+
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean programOptionsComeFirst(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public String getProgramPath(){
+		return programPath;  
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("programPath".equalsIgnoreCase(tag)) {
+			programPath = StringUtil.cleanXMLEscapeCharacters(content);
+		}
+		else if ("programOptions".equalsIgnoreCase(tag))
+			programOptions = StringUtil.cleanXMLEscapeCharacters(content);
+
+		preferencesSet = true;
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "programPath", programPath);  
+		StringUtil.appendXMLTag(buffer, 2, "programOptions", programOptions);  
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public String getHelpString(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String getHelpURL(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** If a subclass wishes to add more options to the GUI dialog box, the GUI elements (CheckBoxes, etc.) should created in an override of this method. */
+	public void queryProgramOptions(ExtensibleDialog dialog) {
+	}
+	/*.................................................................................................................*/
+	/** Any GUI elements (CheckBoxes, etc.) that were created in queryProgramOptions should have their values harvested here. */
+	public void processQueryProgramOptions(ExtensibleDialog dialog) {
+	}
+	/*.................................................................................................................*/
+	/** The command-line flags for the queryProgramOptions should be entered here. */
+	public String getQueryProgramOptions() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying Options"))  
+			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), getProgramName() + " Locations & Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel(getProgramName() + " - File Locations & Options");
+		dialog.appendToHelpString(getHelpString());
+		dialog.setHelpURL(getHelpURL());
+
+		programPathField = dialog.addTextField("Path to " + getProgramName() + ":", programPath, 40);
+		Button programBrowseButton = dialog.addAListenedButton("Browse...",null, this);
+		programBrowseButton.setActionCommand("programBrowse");
+
+		Checkbox includeGapsCheckBox = dialog.addCheckBox("include gaps", includeGaps);
+		
+		queryProgramOptions(dialog);
+
+		SingleLineTextField programOptionsField = dialog.addTextField("Additional " + getProgramName() + " options:", programOptions, 26, true);
+		
+
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			programPath = programPathField.getText();
+			File pp = new File(programPath);
+			if (!pp.canExecute()){
+				alert( "Sorry, the file or location specified for " + getProgramName() + " appears to be incorrect, as it appears not to be an executable program.  The attempt to align may fail.  Please make sure that you have specified correctly the location of " + getProgramName());
+			}
+			programOptions = programOptionsField.getText();
+			includeGaps = includeGapsCheckBox.getState();
+			processQueryProgramOptions(dialog);
+			storePreferences();
+			//preferencesSet = true;
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+
+	/*.................................................................................................................*/
+	private boolean saveExportFile(MolecularData data, String directoryPath, String fileName, boolean[] taxaToAlign, int firstSite, int lastSite) {
+		if (data==null)
+			return false;
+
+		runs++;
+		String path = createSupportDirectory() + MesquiteFile.fileSeparator + fileName;  // place files in support directory for module
+		incrementMenuResetSuppression();
+		Taxa taxa = data.getTaxa();
+
+		FileCoordinator coord = getFileCoordinator();
+		MesquiteFile tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(path), CommandChecker.defaultChecker); //TODO: never scripting???
+
+		TaxaManager taxaManager = (TaxaManager)findElementManager(Taxa.class);
+		Taxa newTaxa =taxa.cloneTaxa(taxaToAlign);
+		newTaxa.addToFile(tempDataFile, null, taxaManager);
+
+		//rename taxa so program doesn't screw around with names
+		for (int it=0; it<newTaxa.getNumTaxa(); it++)
+			newTaxa.setTaxonName(it, "t" + it);
+		logln("Number of taxa to be aligned: " + newTaxa.getNumTaxa());
+		CharMatrixManager matrixManager = data.getMatrixManager();
+		int numNewChars=0;
+		int firstChar = -1;
+		for (int ic=0; ic<data.getNumChars(); ic++){
+			if (data.getSelected(ic) || (firstSite>=0 && MesquiteInteger.isCombinable(firstSite) && ic>= firstSite && lastSite<data.getNumChars() && MesquiteInteger.isCombinable(lastSite) && ic<= lastSite)){
+				numNewChars++;
+				if (firstChar<0) //first one found
+					firstChar=ic;
+			}
+		}
+		MolecularData newData = (MolecularData)matrixManager.getNewData(newTaxa, numNewChars);
+		for (int ic=0; ic<newData.getNumChars(); ic++){
+			if (taxaToAlign!=null) {
+				int count=0;
+				for (int i  =  0; i<taxaToAlign.length; i++) 
+					if (taxaToAlign[i]) {
+						newData.setState(ic, count, data.getState(ic+firstChar, i));
+						count++;
+					}
+			}
+			else for (int it=0; it<newTaxa.getNumTaxa(); it++)
+				newData.setState(ic, it, data.getState(ic+firstChar, it));
+		}
+		//newData = data.cloneData(); ???		
+		newData.setName(data.getName());
+		newData.addToFile(tempDataFile, getProject(), null);
+
+		boolean success = false;
+		FileInterpreterI exporter=null;
+		if (data instanceof DNAData)
+			exporter = (FileInterpreterI)coord.findEmployeeWithName(getDNAExportInterpreter());
+		else if (data instanceof ProteinData)
+			exporter = (FileInterpreterI)coord.findEmployeeWithName(getProteinExportInterpreter());
+		if (exporter!=null) {
+			String ext = exporter.preferredDataFileExtension();
+			if (StringUtil.blank(ext))
+				ext = "";
+			else
+				ext = "." + ext;
+
+
+			String s = "file = " + StringUtil.tokenize(fileName + ext) + " directory = " + StringUtil.tokenize(directoryPath) + " noTrees suppressAllGapTaxa";
+			if (includeGaps)
+				s+= " includeGaps";
+			//if (data.anySelected()) 
+			//	s += " writeOnlySelectedData";
+			s+= " usePrevious";
+			success = coord.export(exporter, tempDataFile, s);
+		}
+
+		tempDataFile.close();
+
+		decrementMenuResetSuppression();
+		return success;
+	}
+	/*.................................................................................................................*/
+	public long[][] alignSequences(MCategoricalDistribution matrix, boolean[] taxaToAlign, int firstSite, int lastSite, int firstTaxon, int lastTaxon) {
+		if (!queryOptions())
+			return null;
+		if (!(matrix.getParentData() != null && matrix.getParentData() instanceof MolecularData)){
+			discreetAlert( "Sorry, " + getName() + " works only if given a full MolecularData object");
+			return null;
+		}
+		MolecularData data = (MolecularData)matrix.getParentData();
+		boolean isProtein = data instanceof ProteinData;
+		boolean pleaseStorePref = false;
+		if (!preferencesSet) {
+			programPath = MesquiteFile.openFileDialog("Choose " + getProgramName()+ ": ", null, null);
+			if (StringUtil.blank(programPath))
+				return null;
+			if (!programPath.endsWith(MesquiteFile.fileSeparator))
+				programPath+=MesquiteFile.fileSeparator;
+			pleaseStorePref = true;
+		}
+		File pp = new File(programPath);
+		if (!pp.canExecute()){
+			discreetAlert( "Sorry, the file or location specified for " + getProgramName() + " appears to be incorrect, as it appears not to be an executable program.  The attempt to align may fail.  Please make sure that you have specified correctly the location of " + getProgramName());
+		}
+		getProject().incrementProjectWindowSuppression();
+		if (pleaseStorePref)
+			storePreferences();
+		data.setEditorInhibition(true);
+		String unique = MesquiteTrunk.getUniqueIDBase() + Math.abs(rng.nextInt());
+
+		String rootDir = createSupportDirectory() + MesquiteFile.fileSeparator;  //replace this with current directory of file
+
+//		StringBuffer fileBuffer = getFileInBuffer(data);
+		String fileName = "tempAlign" + MesquiteFile.massageStringToFilePathSafe(unique) + getExportExtension();   //replace this with actual file name?
+		String filePath = rootDir +  fileName;
+
+		boolean success = false;
+		
+		logln("Exporting file for " + getProgramName());
+		int numTaxaToAlign=data.getNumTaxa();
+
+		
+		if (taxaToAlign!=null){
+			success = saveExportFile(data, rootDir, fileName, taxaToAlign, firstSite, lastSite);
+			int count=0;
+			for (int j=0; j<taxaToAlign.length; j++)
+				if (taxaToAlign[j])
+					count++;
+			numTaxaToAlign=count;
+		}
+		else if (!(firstTaxon==0 && lastTaxon==matrix.getNumTaxa())) {  // we are doing something other than all taxa.
+			boolean[] taxaToAlignLocal = new boolean[matrix.getNumTaxa()];
+			for (int it = 0; it<matrix.getNumTaxa(); it++)
+				taxaToAlignLocal[it] =  (it>=firstTaxon && it<= lastTaxon);
+			success = saveExportFile(data, rootDir, fileName, taxaToAlignLocal, firstSite, lastSite);
+			numTaxaToAlign=lastTaxon-firstTaxon+1;
+		}
+		else
+			success = saveExportFile(data, rootDir, fileName, null, -1, -1);
+
+		if (!success) {
+			logln("File export failed");
+			data.setEditorInhibition(false);
+			return null;
+		}
+		String runningFilePath = rootDir + "running" + MesquiteFile.massageStringToFilePathSafe(unique);
+		String outFileName = "alignedFile" + MesquiteFile.massageStringToFilePathSafe(unique) + getImportExtension();
+		String outFilePath = rootDir + outFileName;
+
+//		MesquiteFile.putFileContents(filePath, fileBuffer.toString(), true);
+
+		StringBuffer shellScript = new StringBuffer(1000);
+		shellScript.append(ShellScriptUtil.getChangeDirectoryCommand(rootDir));
+		shellScript.append(getProgramCommand());
+		StringBuffer argumentsForLogging = new StringBuffer();
+		logln("Options: " + programOptions + " " + getQueryProgramOptions());
+		if (programOptionsComeFirst()){
+			shellScript.append(" " + programOptions + " " + getQueryProgramOptions() + " ");
+			argumentsForLogging.append(" " + programOptions + " " + getQueryProgramOptions() + " ");
+		}
+		appendDefaultOptions(shellScript, fileName,  outFileName,  data);
+		appendDefaultOptions(argumentsForLogging, fileName,  outFileName,  data);
+		
+		if (!programOptionsComeFirst()){
+			shellScript.append(" " + programOptions + " "+ getQueryProgramOptions());
+			argumentsForLogging.append(" " + programOptions + " "+ getQueryProgramOptions());
+		}
+		shellScript.append(StringUtil.lineEnding());
+//		shellScript.append(ShellScriptUtil.getRemoveCommand(runningFilePath));
+
+		String scriptPath = rootDir + "alignerScript" + MesquiteFile.massageStringToFilePathSafe(unique) + ".bat";
+		MesquiteFile.putFileContents(scriptPath, shellScript.toString(), false);
+		
+		logln("Requesting the operating system to run " + getProgramName());
+		logln("Location of  " + getProgramName()+ ": " + getProgramPath());
+		logln("Arguments given in running alignment program:\r" + argumentsForLogging.toString()); 
+		MesquiteTimer timer = new MesquiteTimer();
+		timer.start();
+
+		 success = ShellScriptUtil.executeAndWaitForShell(scriptPath, runningFilePath, null, true, getName());
+
+		if (success){
+			logln("Alignment completed by external program in " + timer.timeSinceLastInSeconds() + " seconds");
+			logln("Processing results...");
+			FileCoordinator coord = getFileCoordinator();
+			MesquiteFile tempDataFile = null;
+			CommandRecord oldCR = MesquiteThread.getCurrentCommandRecord();
+			CommandRecord scr = new CommandRecord(true);
+			MesquiteThread.setCurrentCommandRecord(scr);
+			String failureText = StringUtil.tokenize("Output file containing aligned sequences");
+			if (data instanceof DNAData)
+				tempDataFile = (MesquiteFile)coord.doCommand("linkFileExp", failureText +" " + StringUtil.tokenize(outFilePath) + " " + StringUtil.tokenize(getDNAImportInterpreter()) + " suppressImportFileSave ", CommandChecker.defaultChecker); //TODO: never scripting???
+			else
+				tempDataFile = (MesquiteFile)coord.doCommand("linkFileExp", failureText +" " + StringUtil.tokenize(outFilePath) + " " + StringUtil.tokenize(getProteinImportInterpreter()) + " suppressImportFileSave ", CommandChecker.defaultChecker); //TODO: never scripting???
+			MesquiteThread.setCurrentCommandRecord(oldCR);
+			CharacterData alignedData = getProject().getCharacterMatrix(tempDataFile,  0);
+			alignedData.removeTaxaThatAreEntirelyGaps();
+			long[][] aligned = null;
+			Taxa alignedTaxa =  alignedData.getTaxa();
+			Taxa originalTaxa =  data.getTaxa();
+
+			if (alignedData!=null) {
+				logln("Acquired aligned data");
+				int numChars = alignedData.getNumChars();
+				//sorting to get taxon names in correct order
+				int[] keys = new int[alignedData.getNumTaxa()];
+				for (int it = 0; it<alignedData.getNumTaxa(); it++){
+					String name = alignedTaxa.getTaxonName(it);
+					keys[it] = MesquiteInteger.fromString(name.substring(1, name.length()));  //this is original taxon number
+					if (it<numTaxaToAlign && !MesquiteInteger.isCombinable(keys[it])) {   // unsuccessful
+						MesquiteMessage.println("Processing unsuccessful: can't find incoming taxon \"" + name+"\"");
+						MesquiteMessage.println("  Taxa in incoming: ");
+						for (int i=0; i<alignedData.getNumTaxa(); i++) {
+							MesquiteMessage.println("    "+ alignedTaxa.getTaxonName(i) + " (" + i + ")\tsome data: " + alignedData.hasDataForTaxon(i));
+						}
+						MesquiteMessage.println("  Number of taxa in incoming matrix: "+ alignedTaxa.getNumTaxa());
+						if (taxaToAlign!=null) {
+							MesquiteMessage.println("  Number of taxa set to true in taxaToAlign: "+ numTaxaToAlign);
+						}
+						MesquiteMessage.println("  Number of taxa in original: "+ data.getNumTaxa());
+
+						success=false;
+						break;
+					}
+
+				}
+				if (success) {
+					for (int i=1; i<alignedTaxa.getNumTaxa() ; i++) {
+						for (int j= i-1; j>=0 && j+1<keys.length && keys[j]>keys[j+1]; j--) {
+							alignedTaxa.swapParts(j, j+1);
+							int kj = keys[j];
+							keys[j] = keys[j+1];
+							keys[j+1] = kj;
+							//alignedData.swapTaxa(j, j+1);
+						}
+					}
+					alignedData.changed(this, alignedTaxa, new Notification(MesquiteListener.PARTS_MOVED));
+
+					if (alignedData instanceof MolecularData){
+						aligned = new long[alignedData.getNumChars()][originalTaxa.getNumTaxa()];
+						for (int ic = 0; ic<alignedData.getNumChars(); ic++)
+							for (int it = 0; it<alignedData.getNumTaxa(); it++){
+								//	String name = alignedTaxa.getTaxonName(it);
+								//	int iCurrent = MesquiteInteger.fromString(name.substring(1, name.length()));  //this is original taxon number
+								//	int iTaxon = IntegerArray.indexOf(keys, iCurrent);
+								//if (iTaxon>=0 && MesquiteInteger.isCombinable(iTaxon))
+								aligned[ic][keys[it]] = ((MolecularData)alignedData).getState(ic, it);
+							}
+					}
+				}
+			} else
+				MesquiteMessage.println("Processing unsuccessful: alignedData is null");
+
+			if (tempDataFile!=null)
+				tempDataFile.close();
+			getProject().decrementProjectWindowSuppression();
+			if (runs == 1)
+				deleteSupportDirectory();
+			runs--;
+			data.setEditorInhibition(false);
+			if (success) 
+				return aligned;
+			return null;
+		}
+		if (runs == 1)
+			deleteSupportDirectory();
+		runs--;
+		getProject().decrementProjectWindowSuppression();
+		data.setEditorInhibition(false);
+		return null;
+	}	
+
+	/*.................................................................................................................*/
+	public boolean recoverProgramResults(MolecularData data, String outFilePath){
+
+		//reading aligned file
+		FileCoordinator coord = getFileCoordinator();
+		MesquiteFile tempDataFile = null;
+		String failureText = StringUtil.tokenize("Output file containing aligned sequences");
+		if (data instanceof DNAData)
+			tempDataFile = (MesquiteFile)coord.doCommand("linkFileExp", failureText +" " + StringUtil.tokenize(outFilePath) + " " + StringUtil.tokenize(getDNAImportInterpreter()) + " suppressImportFileSave ", CommandChecker.defaultChecker); //TODO: never scripting???
+		else
+			tempDataFile = (MesquiteFile)coord.doCommand("linkFileExp", failureText +" " + StringUtil.tokenize(outFilePath) + " " + StringUtil.tokenize(getProteinImportInterpreter()) + " suppressImportFileSave ", CommandChecker.defaultChecker); //TODO: never scripting???
+		CharacterData alignedData = getProject().getCharacterMatrix(tempDataFile,  0);
+		return true;
+	}	
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public  void actionPerformed(ActionEvent e) {
+		if (e.getActionCommand().equalsIgnoreCase("programBrowse")) {
+			
+			programPath = MesquiteFile.openFileDialog("Choose " + getProgramName()+ ": ", null, null);
+			if (!StringUtil.blank(programPath)) {
+				programPathField.setText(programPath);
+			}
+		}
+	}
+
+}
diff --git a/Source/mesquite/align/lib/MultiBlockMoveBase.java b/Source/mesquite/align/lib/MultiBlockMoveBase.java
new file mode 100644
index 0000000..2736ec2
--- /dev/null
+++ b/Source/mesquite/align/lib/MultiBlockMoveBase.java
@@ -0,0 +1,360 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib;
+
+
+
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public  abstract class MultiBlockMoveBase extends DataWindowAssistantI {
+	protected MesquiteTable table;
+	protected CharacterData  data;
+	protected CellBlock currentBlock = null;
+	protected int currentNumTaxa = 0;
+	protected int currentNumChars = 0;
+
+	protected MesquiteBoolean warnCheckSum = new MesquiteBoolean(true);
+	protected long originalCheckSum;
+	protected int edgePercent = 50;
+	protected int previousPercentHorizontal=0;
+	protected int previousColumnDragged=-2;
+	protected int previousRowDragged = -2;
+	protected int firstColumnTouched = -2;
+	protected int effectiveFirstColumnTouched = -2;
+	protected int firstRowTouched = -2;
+	protected boolean betweenCells = false;
+	protected boolean leftEdge = false;
+	protected boolean rightEdge = false;
+	protected boolean currentlyMoving = false;
+	protected boolean currentlyMovingRight=false;
+	protected boolean optionDown = false;
+	protected Bits originalWhichTaxa;
+
+	protected boolean defaultCanExpand = false;
+	protected MesquiteBoolean canExpand =new MesquiteBoolean(defaultCanExpand);
+
+	protected boolean defaultLiveUpdate = false;
+	protected MesquiteBoolean liveUpdate = new MesquiteBoolean(defaultLiveUpdate);
+
+	protected MesquiteBoolean dataChanged = new MesquiteBoolean(false);
+
+
+
+	protected boolean choosingNewSelection = true;
+	protected int firstTouchPercentHorizontal;
+	protected int firstTouchPercentVertical;
+	protected int firstSequenceInBlock;
+	protected int lastSequenceInBlock;
+	protected int currentMoveFromOriginal = 0;
+
+	protected long pendingCommandsIDLimit = 0;
+
+	/*.................................................................................................................*/
+	protected void addBasicMultiSequenceMenuItems() {
+		addCheckMenuItem(null, "Live update of analyses, etc.", makeCommand("toggleLiveUpdate",  this), liveUpdate);
+		addCheckMenuItem(null, "Can expand matrix", makeCommand("toggleCanExpand",  this), canExpand);
+	}
+	/*.................................................................................................................*/
+	public void addExtraSnapshotItems(Snapshot temp) {
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (liveUpdate.getValue()!=defaultLiveUpdate)
+			temp.addLine("toggleLiveUpdate " + liveUpdate.toOffOnString());
+		if (canExpand.getValue()!=defaultCanExpand)
+			temp.addLine("toggleCanExpand " + canExpand.toOffOnString());
+		addExtraSnapshotItems(temp);
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean wholeSelectedBlock(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean getOptionDown(){
+		return optionDown;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+
+	public void initialize(MesquiteTable table, CharacterData data) {
+		currentBlock = new CellBlock((CategoricalData)data, table);
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//David:  add compatibility check for CategoricalData
+		if (!(data instanceof CategoricalData))
+			return;
+		this.table = table;
+		this.data = data;
+		currentNumChars = data.getNumChars();
+		currentNumTaxa = data.getNumTaxa();
+		initialize( table,  data);
+	}
+	/*.................................................................................................................*/
+	public void checkCurrentBlockIntegrity(MesquiteTable table, CharacterData data){
+		if (data.getNumChars()!=currentNumChars || data.getNumTaxa()!=currentNumTaxa) {
+			initialize(table,data);
+			currentNumChars = data.getNumChars();
+			currentNumTaxa = data.getNumTaxa();
+		}
+	}
+
+	/*.................................................................................................................*/
+	protected void stopMoving() {
+		currentlyMoving = false;
+		table.repaintCells(liveUpdate.getValue());
+		undoReference = null;
+	}
+	/*.................................................................................................................*/
+	public void addCharactersToBlocks(int added, boolean toStart) {
+		currentBlock.addCharacters(Math.abs(added),toStart);
+	}
+
+	/*.................................................................................................................*/
+	public void resetBlocks() {
+		currentBlock.reset();
+	}
+	/*.................................................................................................................*/
+	public void checkSwitchBlocks(int moveFromOriginal) {
+	}
+	/*.................................................................................................................*/
+	public abstract boolean findBlocks(boolean optionDown);
+
+	public abstract void getFirstAndLastSequences(boolean optionDown);
+	public  abstract Bits getWhichTaxa(boolean optionDown);
+
+	/*.................................................................................................................*/
+	public boolean prepareToMoveMultiSequences(boolean optionDown) {
+
+		getFirstAndLastSequences(optionDown);
+		currentMoveFromOriginal = 0;
+		originalWhichTaxa = getWhichTaxa(optionDown);
+		if (originalWhichTaxa==null)
+			return false;
+		originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars(),originalWhichTaxa);
+		if (!canExpand.getValue())
+			undoReference = new UndoReference(data,this,0,data.getNumChars(), firstSequenceInBlock,lastSequenceInBlock);
+		else
+			undoReference = new UndoReference(data,this, new int[] {UndoInstructions.CHAR_ADDED_TO_END, UndoInstructions.CHAR_ADDED_TO_START});
+		resetBlocks();
+		previousPercentHorizontal = firstTouchPercentHorizontal;
+
+		if (!findBlocks(optionDown)) 
+			return false;
+
+
+		effectiveFirstColumnTouched = firstColumnTouched;
+		previousColumnDragged = effectiveFirstColumnTouched;
+		currentlyMoving = true;
+		return true;
+	}
+	/*.................................................................................................................*/
+	protected void redrawTable() {
+	}
+	/*.................................................................................................................*/
+	public boolean attemptBlockMove(int candidateMovement) {
+		if (currentBlock==null) 
+			return false;
+		if (candidateMovement !=0) {  // move it over from previous position by this amount; at least, that is the request
+			int distanceToMove = currentBlock.movementAllowed(candidateMovement, canExpand.getValue());
+			if (distanceToMove!=0) {
+				long[] checkSums = null;
+				int numTaxaToMove=0;
+				Bits taxaToMove = currentBlock.getWhichTaxa();
+				if (MesquiteTrunk.debugMode) {
+					//logln("Candidate movement: " + candidateMovement + ", memory available: " + MesquiteTrunk.getMaxAvailableMemory());
+					logln("Candidate movement: " + candidateMovement);
+					numTaxaToMove = taxaToMove.numBitsOn();
+					checkSums = new long[numTaxaToMove];
+					int count = 0;
+					for (int it=0; it<data.getNumTaxa() && count<numTaxaToMove; it++) {
+						if (taxaToMove.isBitOn(it)) {
+							checkSums[count] = ((CategoricalData)data).storeCheckSum(0, data.getNumChars(),it,it);
+							count++;
+						}
+					}
+				}
+				int added = data.moveCells(currentBlock.getCurrentFirstCharInBlock(), currentBlock.getCurrentLastCharInBlock(), distanceToMove, taxaToMove, canExpand.getValue(), false, true, false,dataChanged,null, null);
+				if (MesquiteTrunk.debugMode) {
+					numTaxaToMove = taxaToMove.numBitsOn();
+					int count = 0;
+					for (int it=0; it<data.getNumTaxa() && count<numTaxaToMove; it++) {
+						if (taxaToMove.isBitOn(it)) {
+							long newCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars(),it,it);
+							if (newCheckSum!=checkSums[count]) {
+								logln("CHECKSUM of taxon " + (it+1) + " changed!!!!!!");
+							}
+							count++;
+						}
+					}
+				}
+				if (added<0){ //now start adjusting all the values as we may have added taxa at the start of the matrix
+					firstColumnTouched -= added;
+					effectiveFirstColumnTouched -= added;
+					previousColumnDragged -= added;
+				} 
+				if (added!=0){  //we've added some characters
+					addCharactersToBlocks(Math.abs(added), added<0);
+					if (MesquiteTrunk.debugMode)
+						logln("Number of characters added: " + Math.abs(added));
+				}
+				currentBlock.adjustToMove(distanceToMove);
+
+				if (added!=0 || liveUpdate.getValue()) {
+					data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));
+				}
+
+				currentMoveFromOriginal += distanceToMove;
+
+				redrawTable();
+
+				currentBlock.transferCurrentToPrevious();
+				pendingCommandsIDLimit = PendingCommand.numInstances;
+				MesquiteCommand.deleteSpecifiedCommands(0, pendingCommandsIDLimit, this, "moveDragCell");
+			}
+		}
+
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean dragMultiSequences(int percentHorizontal, int rowDragged, int columnDragged) {
+		if (currentBlock==null)
+			return false;
+
+		if (!table.rowLegal(rowDragged)|| !table.columnLegal(columnDragged) || (previousColumnDragged == columnDragged && previousPercentHorizontal == percentHorizontal))
+			return false;
+
+		double exactMoveFromOriginal = columnDragged-firstColumnTouched;
+		exactMoveFromOriginal+= 0.01*(percentHorizontal-firstTouchPercentHorizontal);
+		int moveFromOriginal = (int)exactMoveFromOriginal;
+		int candidateMovement =  moveFromOriginal - currentMoveFromOriginal;
+
+		previousColumnDragged = columnDragged;
+		previousPercentHorizontal = percentHorizontal;
+
+		checkSwitchBlocks(moveFromOriginal);
+
+		return attemptBlockMove(candidateMovement);
+	}
+	/*.................................................................................................................*/
+	public boolean afterMoveMultiSequences() {
+		boolean success = ((CategoricalData)data).examineCheckSum(0, data.getNumChars(),currentBlock.getWhichTaxa(), "WARNING! The data have been altered inappropriately by this tool! The changes you have made will be undone.", warnCheckSum, originalCheckSum);
+		if (!success) {   //&& MesquiteTrunk.debugMode) 
+			logln("WARNING! The data have been altered inappropriately by this tool! The changes you have made will be undone.");
+			logln("Original sequences to be moved: " + originalWhichTaxa.getListOfBitsOn(1));
+			logln("Sequences moved: " + currentBlock.getWhichTaxa().getListOfBitsOn(1));
+		}
+		if (dataChanged.getValue()) {
+			data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, null, undoReference));
+			data.notifyInLinked(new Notification(MesquiteListener.DATA_CHANGED));  //TODO: have undo for linked?  or is this automatically taken care of?
+		}
+		if (!success){
+			if (undoReference!=null) {
+				Undoer[] undoer = undoReference.getUndoer();
+				if (undoer!=null && undoer[0]!=null)
+					undoer[0].undo();
+			}
+		}
+		stopMoving();
+		return true;
+	}
+
+	UndoReference undoReference = null;
+	/*.................................................................................................................*/
+	public abstract boolean mouseDown(boolean optionDown, boolean shiftDown);
+	/*.................................................................................................................*/
+	public abstract boolean mouseDragged(int columnDragged, int rowDragged,	int percentHorizontal, int percentVertical);
+	/*.................................................................................................................*/
+	public abstract boolean mouseDropped(int columnDropped, int rowDropped,	int percentHorizontal, int percentVertical);
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Touched.", "[column touched] [row touched] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveTouchCell")) {
+			if (table!=null && data !=null){
+				optionDown = arguments.indexOf("option")>=0;
+				boolean shiftDown = arguments.indexOf("shift")>=0;
+				MesquiteInteger io = new MesquiteInteger(0);
+				firstColumnTouched= MesquiteInteger.fromString(arguments, io);
+				firstRowTouched= MesquiteInteger.fromString(arguments, io);
+				firstTouchPercentHorizontal= MesquiteInteger.fromString(arguments, io);
+				firstTouchPercentVertical= MesquiteInteger.fromString(arguments, io);
+
+				if (!mouseDown(optionDown, shiftDown))
+					return null;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Dragging", "[column dragged] [row dragged] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveDragCell")) {
+			if (table!=null && data !=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDragged = MesquiteInteger.fromString(arguments, io);
+				int rowDragged= MesquiteInteger.fromString(arguments, io);
+				int percentHorizontal= MesquiteInteger.fromString(arguments, io);
+				int percentVertical= MesquiteInteger.fromString(arguments, io);
+
+				if (!mouseDragged (columnDragged, rowDragged, percentHorizontal, percentVertical)) {
+					//undoReference = null;
+					return null;
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Dropping.", "[column dropped] [row dropped] [percent horizontal] [percent vertical] [modifiers]", commandName, "moveDropCell")) {
+			if (table!=null && data !=null && (firstColumnTouched>=0)&& (firstRowTouched>=0)){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDropped = MesquiteInteger.fromString(arguments, io);
+				int rowDropped= MesquiteInteger.fromString(arguments, io);
+				int droppedPercentHorizontal= MesquiteInteger.fromString(arguments, io);
+				int droppedPercentVertical= MesquiteInteger.fromString(arguments, io);
+				if (!mouseDropped (columnDropped, rowDropped, droppedPercentHorizontal, droppedPercentVertical))
+					//undoReference = null;
+					return null;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether live update is active", "[on = live update; off]", commandName, "toggleLiveUpdate")) {
+			liveUpdate.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether the matrix is allowed to expand if one attempts to move a block beyond the edges of the matrix.", "[on = canExpand; off]", commandName, "toggleCanExpand")) {
+			canExpand.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/align/lib/MultipleSequenceAligner.java b/Source/mesquite/align/lib/MultipleSequenceAligner.java
new file mode 100644
index 0000000..b18e15e
--- /dev/null
+++ b/Source/mesquite/align/lib/MultipleSequenceAligner.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib;
+
+/* ~~ */
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public abstract class MultipleSequenceAligner extends MesquiteModule {
+	protected Class characterDataClass = null;
+	protected boolean isProtein = true;
+
+	public Class getDutyClass() {
+		return MultipleSequenceAligner.class;
+	}
+
+	public String getDutyName() {
+		return "Multiple Sequence Aligner";
+	}
+ 	 public String[] getDefaultModule() {
+    	 	return new String[] {"#OpalMultiSeqAligner"};
+    	 }
+
+	public boolean permitSeparateThread(){
+		return true;
+	}
+	/**
+	 * Subclasses can override this to have access to full information about
+	 * data.  What are to be aligned are only the taxa indicated for the block (firstSite to lastSite) indicated.
+	 * These sites, aligned, are to be returned as a long[][].  Thus, this array may be smaller in dimensions than the 
+	 * MCategoricalDistribution passed.  The MCategoricalDistribution may be queried for states by
+	 * long nucleotide = data.getState(iCharacter, iTaxon);
+	 * Longs are used as bitsets for state sets (see mesquite.lib.CategoricalState).
+
+	 *	 * Note that LIKE MOST PLACES IN MESQUITE, the long[][] returned here has characters first and taxa second;
+	 * thus, it should be returned as a long[numChars][numTaxa]
+	 * 
+	 */
+	public long[][] alignSequences(MCategoricalDistribution matrix, boolean[] taxaToAlign, int firstSite, int lastSite, int firstTaxon, int lastTaxon) {
+		characterDataClass=matrix.getCharacterDataClass();
+		isProtein = (characterDataClass==ProteinData.class);
+		int numChars = lastSite - firstSite+1;
+		if (numChars <0 || !MesquiteInteger.isCombinable(firstSite) || !MesquiteInteger.isCombinable(lastSite)){
+			numChars = matrix.getNumChars();
+			firstSite = 0;
+			lastSite = numChars-1;
+		}
+		int numTaxa = 0;
+		if (taxaToAlign == null)
+			numTaxa = lastTaxon-firstTaxon+1;
+		else {
+			for (int i = 0; i < taxaToAlign.length; i++)
+				if (taxaToAlign[i])
+					numTaxa++;
+			
+		}
+		if (numTaxa<=1)
+			return null;
+		
+		long[][] extracted = new long[numChars][numTaxa];
+
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			int st = 0;
+			for (int it = 0; it<matrix.getNumTaxa(); it++){
+				if ((taxaToAlign == null && it>=firstTaxon && it<=lastTaxon) || taxaToAlign[it]){
+					extracted[ic-firstSite][st] = matrix.getState(ic, it);
+					st++;
+				}
+			}
+		}
+		long[][] aligned =  alignSequences(extracted);
+		return aligned;
+	}
+
+	/**
+	 * This method is not called directly by Mesquite, but modules preferring to
+	 * receive and return the information as long[][] can override this and let the previous
+	 * method call it.  Also, this method receives only the pieces to be aligned.
+	 */
+	protected long[][] alignSequences(long[][] sequences) {
+		return null;
+	}
+
+}
+
diff --git a/Source/mesquite/align/lib/PairwiseAligner.java b/Source/mesquite/align/lib/PairwiseAligner.java
new file mode 100644
index 0000000..383e99a
--- /dev/null
+++ b/Source/mesquite/align/lib/PairwiseAligner.java
@@ -0,0 +1,514 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.align.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+
+
+/*TODO:
+ *  need to be able to specify whether costs are to be applied for opening gaps on the left or right side of each sequence
+ */
+public class PairwiseAligner  {
+
+	boolean preferencesSet = false;
+	boolean isMinimize = true;	
+	int defaultCharThresholdForLowMemory = 5000000;
+																 
+	int charThresholdForLowMemory = defaultCharThresholdForLowMemory;
+
+    //first gap char costs gapOpen + gapExtend, and each additional character costs gapExtend 
+	private int gapOpen;
+	private int gapExtend;
+	private int gapOpenTerminal;
+	private int gapExtendTerminal;
+	private int subs[][];
+	private boolean keepGaps = false;  
+	private boolean allowNewInternalGaps = true;
+	private boolean maintainOrder = false;
+	private boolean flagGapArrayTerminals = true;
+	
+	public int totalGapChars = 0;
+		
+	public int A[];
+	public int B[];
+	public int followsGapSize[] = null; // unused if "keepGaps" is false
+	public int lengthA;
+	public int lengthB;
+	
+	private int alphabetLength=4;
+	private int gapInsertionArray[];
+		
+	private boolean gapCostsInitialized = false;
+	private boolean subCostsInitialized = false;
+	private boolean seqsWereExchanged = false;
+		
+	public PairwiseAligner (boolean keepGaps, boolean allowNewInternalGaps, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength) {
+	    setSubsCostMatrix(subs);
+		setGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);
+		setKeepGaps (keepGaps);
+	    setAllowNewInternalGaps(allowNewInternalGaps);
+		this.alphabetLength=alphabetLength;
+		gapCostsInitialized = subCostsInitialized = true;
+	}	
+
+	public PairwiseAligner (boolean keepGaps, int[][] subs, int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal, int alphabetLength) {
+		setSubsCostMatrix(subs);
+		setGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);
+		setKeepGaps (keepGaps);
+		this.alphabetLength=alphabetLength;
+		gapCostsInitialized = subCostsInitialized = true;
+	}	
+
+	public PairwiseAligner (boolean keepGaps, int[][] subs, int gapOpen, int gapExtend, int alphabetLength) {
+		setSubsCostMatrix(subs);
+		setGapCosts(gapOpen, gapExtend);
+		setKeepGaps (keepGaps);
+		this.alphabetLength=alphabetLength;
+		gapCostsInitialized = subCostsInitialized = true;
+	}	
+	
+	public PairwiseAligner () {
+		// not much to do here ???
+	}
+
+	public static PairwiseAligner getDefaultAligner(boolean keepGaps, MolecularData data){
+		MesquiteInteger gapOpen = new MesquiteInteger();
+		MesquiteInteger gapExtend = new MesquiteInteger();
+		MesquiteInteger gapOpenTerminal = new MesquiteInteger();
+		MesquiteInteger gapExtendTerminal = new MesquiteInteger();
+		AlignUtil.getDefaultGapCosts(gapOpen, gapExtend, gapOpenTerminal, gapExtendTerminal);  
+		int alphabetLength = ((CategoricalState)data.makeCharacterState()).getMaxPossibleState()+1;	  
+		int subs[][] = AlignUtil.getDefaultSubstitutionCosts(alphabetLength);  
+		PairwiseAligner aligner = new PairwiseAligner(keepGaps,subs,gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue(), alphabetLength);
+		aligner.setUseLowMem(true);
+		return aligner;
+	}
+	
+	public static PairwiseAligner getDefaultAligner(MolecularData data){
+		return getDefaultAligner(false,data);
+	}
+	
+	
+
+	
+	public long[][] stripEmptyBases(long[][] alignment, int minLength){
+		int numExtras = 0;
+		for (int i=alignment.length-1; i>=0; i--) {
+			if ((CategoricalState.isInapplicable(alignment[i][0]) || CategoricalState.isEmpty(alignment[i][0])) && (CategoricalState.isInapplicable(alignment[i][1])| CategoricalState.isEmpty(alignment[i][1])))
+				numExtras++;
+			else
+				break;
+		}
+		if (numExtras>0) {
+			long[][] ret = new long[alignment.length-numExtras][2];
+			for (int i=0; i<alignment.length-numExtras; i++) {
+				ret[i][0] = alignment[i][0];
+				ret[i][1] = alignment[i][1];
+			}
+			return ret;
+		}
+		return alignment;
+
+	}
+	
+	int preSequenceTerminalFlaggedGap = -1;
+	int postSequenceTerminalFlaggedGap = -1;
+	
+	
+	
+	public int getPreSequenceTerminalFlaggedGap() {
+		return preSequenceTerminalFlaggedGap;
+	}
+
+	public int getPostSequenceTerminalFlaggedGap() {
+		return postSequenceTerminalFlaggedGap;
+	}
+
+	private void doFlagGapArrayTerminals(long[] recipientSequence) {
+		if (gapInsertionArray==null)
+			return;
+		for (int i=0; i<gapInsertionArray.length; i++) { // going up from start
+			if (gapInsertionArray[i]>0) {
+				boolean terminal=true;
+				for (int j=0; j<=i+1 && j<recipientSequence.length; j++) {
+					if (recipientSequence[j]!=MolecularState.inapplicable)
+						terminal=false;
+				}
+				if (terminal) {
+					gapInsertionArray[i] = -gapInsertionArray[i];  //having them as negative will flag them as terminal gaps
+					preSequenceTerminalFlaggedGap = i;
+				}
+				break;
+			}
+		}
+		for (int i=gapInsertionArray.length-1; i>=0; i--) {
+			if (gapInsertionArray[i]>0) {
+				boolean terminal=true;
+				for (int j=recipientSequence.length-1; j>i && j>=0; j--) {
+					if (recipientSequence[j]!=MolecularState.inapplicable)
+						terminal=false;
+				}
+				if (terminal) {
+					gapInsertionArray[i] = -gapInsertionArray[i]; //having them as negative will flag them as terminal gaps
+					postSequenceTerminalFlaggedGap = i;
+				}
+				break;  
+			}
+		}
+	}
+	
+	
+	/** This method returns a 2d-long array ([site][taxon]) representing the alignment of the passed sequences.
+	 * If object has been told to retain gaps, gaps in A_withGaps will remain intact (new ones  may be added)*/
+	public synchronized long[][] alignSequences( long[] A_withGaps, long[] B_withGaps, boolean returnAlignment, MesquiteNumber score) {
+		
+		if (!gapCostsInitialized  || !subCostsInitialized) {
+			if (score != null)
+				score.setValue( -1 );
+			return null;
+		}
+		
+		int gO  = gapOpen;
+		int gE  = gapExtend;
+        int gOt = gapOpenTerminal;
+        int gEt = gapExtendTerminal;
+        if (! this.allowNewInternalGaps)  // make internal gaps impossibly expensive .. but not high enough to cause wrap around of the capacity of an int
+            gE = Integer.MAX_VALUE / 10 ;
+        
+		totalGapChars = preProcess(A_withGaps, B_withGaps);
+		
+		if ( returnAlignment) { 
+		
+			long ret[][];
+			long charThreshold = getCharThresholdForLowMemory();
+			if ((lengthA*lengthB)>charThreshold) { 
+				//low memory (but slower, due to recursion) alignment
+			    AlignmentHelperLinearSpace helper = new AlignmentHelperLinearSpace(A, B, lengthA, lengthB, subs, gO, gE, gOt, gEt, alphabetLength, keepGaps, followsGapSize);
+				int myScore =  helper.recursivelyFillArray(0, lengthA, 0, lengthB, helper.noGap, helper.noGap);
+				ret = helper.recoverAlignment(totalGapChars, seqsWereExchanged);
+				gapInsertionArray = helper.getGapInsertionArray();  
+	            if (score != null)
+	                score.setValue( myScore );
+			} else {
+//				 fast (but quadratic space) alignment
+			    AlignmentHelperQuadraticSpace helper = new AlignmentHelperQuadraticSpace(A, B, lengthA, lengthB, subs, gO, gE, gOt, gEt, alphabetLength);
+				ret = helper.doAlignment(returnAlignment,score,keepGaps, followsGapSize, totalGapChars);
+				gapInsertionArray = helper.getGapInsertionArray();
+			}
+
+			if (ret==null)
+				return null;
+			for (int i=0; i<ret.length; i++) {
+				if (ret[i][0]==0L)
+					ret[i][0] = CategoricalState.inapplicable;
+				if (ret[i][1] ==0L)
+					ret[i][1] = CategoricalState.inapplicable;
+			}
+			
+			if (ret.length>lengthA && ret.length>lengthB)
+				ret = stripEmptyBases(ret, MesquiteInteger.maximum(lengthA, lengthB));
+			
+			if (flagGapArrayTerminals && gapInsertionArray!=null) {
+				doFlagGapArrayTerminals(A_withGaps);
+			}
+			return ret;
+
+		} else { 
+			if (lengthA == 0 || lengthB == 0){
+				if (score != null)
+					score.setToUnassigned(  );
+				return null;
+			}
+			//linear space, and since it only makes one pass, it's the fastest option for score-only requests.
+			AlignmentHelperLinearSpace helper = new AlignmentHelperLinearSpace(A, B, lengthA, lengthB, subs, gO, gE, gOt, gEt, alphabetLength, true, keepGaps, followsGapSize);
+			helper.fillForward(0,lengthA,0,lengthB,helper.noGap);			
+			int myScore = Math.min(helper.fH[lengthB], Math.min (helper.fD[lengthB], helper.fV[lengthB])) ;
+			if (score != null)
+				score.setValue( myScore );
+
+			
+			return null;  // no alignment
+		}
+	}
+	
+	/** private method used to convert seqs from mesquite long values to the correct indexes for the subs table
+	 * */
+	private synchronized int preProcess (long[] A_withGaps, long[] B_withGaps) { //translates sequences to ints, strips gaps, and possibly swaps A and B.
+		int i;
+		int totalGapChars = 0;
+		
+		A = new int[A_withGaps.length];
+		B = new int[B_withGaps.length];
+		
+		if (keepGaps) { // only do this in case where gaps in A are tracked
+			followsGapSize = new int[A_withGaps.length + 1];
+
+			for (i=0; i<A_withGaps.length; i++) 
+				followsGapSize[i] = 0;
+		}
+		
+		//translate sequences to ints, and remove gaps
+		lengthA = 0; 
+		lengthB = 0;
+		for (i=0; i<A_withGaps.length; i++) {
+			if (!CategoricalState.isInapplicable(A_withGaps[i])) {
+				A[lengthA]= MolecularState.compressToInt(A_withGaps[i]);  //gets the lower 32 bits of the state set
+				lengthA++;
+			}	else if (keepGaps) {
+				followsGapSize[lengthA]++;
+				totalGapChars++;	
+			}
+		}
+		if (keepGaps)
+			followsGapSize[lengthA] = 0; //the final entry in this array is a placeholder ... it says the character after the last character in the string follows 0 spacers ...  
+		
+		lengthB = 0;
+		for (i=0; i<B_withGaps.length; i++) { 
+			if (!CategoricalState.isInapplicable(B_withGaps[i])) {
+				if (lengthB>=B.length) {
+					MesquiteMessage.println("|||||||| OVERFLOW B   |||||||||\n   i: " + i + "\n   A.length: " + A.length + "\n   lengthA: " + lengthA + "\n   B.length: " + B.length + "\n   lengthB: " + lengthB + "\n   A_withGaps.length: " + A_withGaps.length + "\n   B_withGaps.length: " + B_withGaps.length + "\n      keepGaps: " + keepGaps);
+				}
+				B[lengthB] = MolecularState.compressToInt(B_withGaps[i]);  //gets the lower 32 bits of the state set
+				lengthB++;
+			}
+		}	
+		
+		
+		//Just to decrease the amount of memory used to O(min of A_length and B_length)
+		//note: the "withGaps" version won't do this (at least at first), since then the "A" that needs to have gaps retained would be wrong. 
+		if (!maintainOrder && !keepGaps && lengthB < lengthA) {
+			int [] tmp2 = A;
+			A = B;
+			B = tmp2;
+
+			int tmp = lengthA;
+			lengthA = lengthB;
+			lengthB = tmp;
+			
+			seqsWereExchanged = true;
+		}		
+		
+		return totalGapChars;
+	}
+	
+	
+	/** If object wasn't called with gap cost arguments, this must be called or alignment will fail*/
+	public void setGapCosts(int gapOpen, int gapExtend){
+        //	first gap char costs gapOpen+gapExtend, and each additional character costs gapExtend
+		this.gapOpen = gapOpen;
+		this.gapExtend = gapExtend;
+		this.gapOpenTerminal = gapOpen;
+		this.gapExtendTerminal = gapExtend;
+
+		gapCostsInitialized = true;
+	}
+
+	/** If object wasn't called with gap cost arguments, this must be called or alignment will fail*/
+	public void setGapCosts(int gapOpen, int gapExtend, int gapOpenTerminal, int gapExtendTerminal){
+	    //	first gap char costs gapOpen+gapExtend, and each additional character costs gapExtend
+		if (gapOpen >=0)  //allows passing of -1 to leave as is
+			this.gapOpen = gapOpen;
+		if (gapExtend >=0)
+			this.gapExtend = gapExtend;
+		if (gapOpenTerminal >=0)
+			this.gapOpenTerminal = gapOpenTerminal;
+		if (gapExtendTerminal >=0)
+			this.gapExtendTerminal = gapExtendTerminal;
+		gapCostsInitialized = true;
+	}
+
+	/** If object wasn't called with subs cost arguments, this must be called or alignment will fail*/
+	public void setSubsCostMatrix(int[][] subs){
+		this.subs = subs;
+		subCostsInitialized = true;
+	}
+	
+	public void setKeepGaps (boolean keep) {
+		keepGaps = keep;	
+	}
+	
+	public void setUseLowMem (boolean lowMem) {
+		if (lowMem)
+			setCharThresholdForLowMemory(0);
+		else
+			setCharThresholdForLowMemory(Integer.MAX_VALUE);
+		//this.useLowMem = lowMem;	
+	}
+
+	public long getCharThresholdForLowMemory(){
+		//return charThresholdForLowMemory;
+		long charsFitInMemWithQuadraticDPTable = MesquiteTrunk.getMaxAvailableMemory()/10; //rough approximation
+		return charsFitInMemWithQuadraticDPTable/3; // conservative - if it should only use up third of available memory, use quadratic space algorithm (faster); else use linear space	
+	}
+
+	public void setCharThresholdForLowMemory(int numChars){
+		 charThresholdForLowMemory = numChars;
+	}
+	
+	public void setCharThresholdForLowMemoryToDefault(){
+		 charThresholdForLowMemory = defaultCharThresholdForLowMemory;
+	}
+		
+	
+	public void setIsMinimizationProblem (boolean isMin) {
+		isMinimize = isMin;
+	}
+	
+	/** returns an array where the ith position indicates the number of new gap positions inserted 
+	 * in front of the ith site of the fixed sequence. */
+	public int[] getGapInsertionArray() {
+		return gapInsertionArray;
+	}			
+	
+	public boolean isFlagGapArrayTerminals() {
+		return flagGapArrayTerminals;
+	}
+
+	public void setFlagGapArrayTerminals(boolean flagGapArrayTerminals) {
+		this.flagGapArrayTerminals = flagGapArrayTerminals;
+	}
+
+
+		
+	/** This method returns true if better alignment scores are higher.  Override if needed. */
+	public boolean getHigherIsBetter() {
+		return false;
+	}   	
+
+	/** This method returns the score of two identical copies of the passed sequence.  Override if needed. */
+	public MesquiteNumber getScoreOfIdenticalSequences(long[] sequence) {
+		return new MesquiteNumber(0.0);
+	}
+
+
+	/** This method returns the score of the worst possible match with the passed sequence.  Acceptable if result is approximate.  Override if needed. */
+	public MesquiteNumber getVeryBadScore(long[] sequence, int oppositeLength, int alphabetLength) {
+		MesquiteNumber score = new MesquiteNumber();
+		long[]opposite = new long[oppositeLength];
+		for (int i=0; i<sequence.length && i<oppositeLength; i++) {
+			long newSet = CategoricalState.emptySet();
+			boolean switched =false;
+			if (!switched) {
+				for (int e=0; e<alphabetLength; e++) {
+					if (CategoricalState.isElement(sequence[i],e))  {
+						int farElement = -1;
+						int maxSub = 0;
+						for (int j = 0; j<alphabetLength; j++) {
+							if (maxSub<subs[e][j]) {
+								maxSub=subs[e][j];
+								farElement = j;
+							}
+						}
+						if (farElement>=0 && !CategoricalState.isElement(sequence[i],farElement)) {
+							newSet = CategoricalState.addToSet(newSet,farElement);
+							switched = true;
+							break;
+						}
+					}
+				}
+			}
+			int first = (int)Math.random() * alphabetLength;  // pick random bit
+			if (!switched) {
+				if (first>alphabetLength-1)
+					first = alphabetLength-1;
+				if (first<0)
+					first = 0;
+				for (int e=first; e<alphabetLength; e++) {
+					if (!CategoricalState.isElement(sequence[i],e))  {
+						newSet = CategoricalState.addToSet(newSet,e);
+						switched = true;
+						break;
+					}
+				}
+			}
+			if (!switched)
+				for (int e=first; e>=0; e--) {
+					if (!CategoricalState.isElement(sequence[i],e))  {
+						newSet = CategoricalState.addToSet(newSet,e);
+						switched = true;
+						break;
+					}
+				}
+			if (!switched)
+				opposite[i]=sequence[i];
+			else
+				opposite[i] =newSet;
+		}
+		alignSequences(sequence,opposite, false, score);
+		return score;
+	}
+
+	public long[][] getAlignment(MolecularData data1, int it1, MolecularData data2, int it2, MesquiteNumber alignScore, boolean maintainOrder) {
+		if (data1==null || data2==null)
+			return null;
+		long[] extracted1 = new long[data1.getNumChars()];
+		long[] extracted2 = new long[data2.getNumChars()];
+		
+		for (int ic = 0; ic<data1.getNumChars(); ic++){
+			extracted1[ic] = data1.getState(ic, it1);
+		}
+		for (int ic = 0; ic<data2.getNumChars(); ic++){
+			extracted2[ic] = data2.getState(ic, it2);
+		}
+		setMaintainOrder(maintainOrder);
+		long[][] aligned = alignSequences(extracted1, extracted2, true, alignScore);
+		return aligned;
+	}
+
+
+	/** This method returns a 2d-long array ([site][taxon]) representing the alignment of the sequences identified by the "taxon" and "site" arguments.
+	 * If object has been told to retain gaps, gaps in taxon1 will remain intact (new ones  may be added)*/
+	public long[][] alignSequences(MCategoricalDistribution data, int taxon1, int taxon2, int firstSite, int lastSite, boolean returnAlignment, MesquiteNumber score) {
+		if (lastSite - firstSite+1 <0 || !MesquiteInteger.isCombinable(firstSite) || !MesquiteInteger.isCombinable(lastSite)){
+			firstSite = 0;
+			lastSite = data.getNumChars()-1;
+		}
+		if (firstSite<0)
+			firstSite=0;
+		if (lastSite>data.getNumChars()-1 || lastSite<0)
+			lastSite = data.getNumChars()-1;
+		int numChars = lastSite - firstSite+1;
+		
+		long[] extracted1 = new long[numChars];
+		long[] extracted2 = new long[numChars];
+		
+
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[ic-firstSite] = data.getState(ic, taxon1);
+			extracted2[ic-firstSite] = data.getState(ic, taxon2);
+		}
+		CategoricalState state=(CategoricalState)(data.getParentData().makeCharacterState());
+		
+		long[][] aligned =  alignSequences(extracted1, extracted2, returnAlignment, score);
+	
+		return aligned;
+	}
+
+	public boolean isMaintainOrder() {
+		return maintainOrder;
+	}
+
+	public void setMaintainOrder(boolean maintainOrder) {
+		this.maintainOrder = maintainOrder;
+	}
+
+	public boolean getAllowNewInternalGaps() {
+		return allowNewInternalGaps;
+	}
+
+	public void setAllowNewInternalGaps(boolean allowNewInternalGaps) {
+		this.allowNewInternalGaps = allowNewInternalGaps;
+	}
+
+}
diff --git a/Source/mesquite/align/lib/TwoSequenceAligner.java b/Source/mesquite/align/lib/TwoSequenceAligner.java
new file mode 100644
index 0000000..b98e023
--- /dev/null
+++ b/Source/mesquite/align/lib/TwoSequenceAligner.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib;
+
+/* ~~ */
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public abstract class TwoSequenceAligner extends MesquiteModule {
+	public Class getDutyClass() {
+		return TwoSequenceAligner.class;
+	}
+
+	public String getDutyName() {
+		return "Pairwise Sequence Aligner";
+	}
+
+	/**
+	 * Subclasses can override this to have access to full information about
+	 * data.  What are to be aligned are only the taxa indicated for the block (firstSite to lastSite) indicated.
+	 * These sites, aligned, are to be returned as a long[][].  Thus, this array may be smaller in dimensions than the 
+	 * MCategoricalDistribution passed.  The MCategoricalDistribution may be queried for states by
+	 * long nucleotide = data.getState(iCharacter, iTaxon);
+	 * Longs are used as bitsets for state sets (see mesquite.lib.CategoricalState).
+	 * 
+	 * Note that LIKE MOST PLACES IN MESQUITE, the long[][] returned here has characters first and taxa second;
+	 * thus, it should be returned as a long[numChars][2]
+	 * 
+	 * If score is non-null, then the subclass should fill this with the score of the alignment.
+	 *
+	 */
+	public long[][] alignSequences(MCategoricalDistribution data, int taxon1, int taxon2, int firstSite, int lastSite, boolean returnAlignment, MesquiteNumber score) {
+		if (lastSite - firstSite+1 <0 || !MesquiteInteger.isCombinable(firstSite) || !MesquiteInteger.isCombinable(lastSite)){
+			firstSite = 0;
+			lastSite = data.getNumChars()-1;
+		}
+		if (firstSite<0)
+			firstSite=0;
+		if (lastSite>data.getNumChars()-1 || lastSite<0)
+			lastSite = data.getNumChars()-1;
+		int numChars = lastSite - firstSite+1;
+		
+		long[] extracted1 = new long[numChars];
+		long[] extracted2 = new long[numChars];
+		
+
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[ic-firstSite] = data.getState(ic, taxon1);
+			extracted2[ic-firstSite] = data.getState(ic, taxon2);
+		}
+		CategoricalState state=(CategoricalState)(data.getParentData().makeCharacterState());
+		long[][] aligned =  alignSequences(extracted1, extracted2, returnAlignment, score, state);
+	
+		return aligned;
+	}
+
+	/**
+	 * This method is not called directly by Mesquite, but modules preferring to
+	 * receive and return the information as long[][] can override this and let the previous
+	 * method call it.  Also, this method receives only the pieces to be aligned.
+	 * Note that the long that is returned should be long[][2] in size.  
+	 */
+	public long[][] alignSequences(long[] sequence1, long[] sequence2, boolean returnAlignment, MesquiteNumber score, CategoricalState state) {
+		return null;
+	}
+	
+	/** This method returns the score of two identical copies of the passed sequence.  Override if needed. *
+	public MesquiteNumber getScoreOfIdenticalSequences(long[] sequence) {
+		return new MesquiteNumber(0.0);
+	}
+
+	/** This method returns the score of the worst possible match with the passed sequence.  Acceptable if result is approximate.  Override if needed. 
+	public MesquiteNumber getVeryBadScore(long[] sequence, CategoricalState state) {
+		MesquiteNumber score = new MesquiteNumber();
+		long[]opposite = new long[sequence.length];
+		for (int i=0; i<sequence.length; i++) {
+			opposite[i] = DNAState.complement(sequence[i]);
+		}
+		alignSequences(sequence,opposite, false, score, state);
+		return score;
+	}
+
+
+	/*
+	 * public int[][] pickCosts(MesquiteInteger gapOpen, MesquiteInteger gapExtend, int alphabetLength){
+	    //	internal representation of gap costs is that first gap char costs gapOpen+gapExtend, and each additional character costs gapExtend
+		gapOpen.setValue(8);
+		gapExtend.setValue(3);
+		
+		int subs[][] =  new int[alphabetLength][alphabetLength];	
+		subs[0][0] = subs[1][1] = subs[2][2] = subs[3][3] = 0;
+		subs[0][1] = subs[1][0] = subs[0][3] = subs[3][0] = 10; //transversions involving A
+		subs[0][2] = subs[2][0] = subs[1][3] = subs[3][1]  = 5; //transitions
+		subs[2][3] = subs[3][2] = subs[1][2] = subs[2][1]= 10; //transversions involving G
+		return subs;
+	}
+*/
+	
+	
+}
+
diff --git a/Source/mesquite/align/lib/TwoSequenceAlignerGaps.java b/Source/mesquite/align/lib/TwoSequenceAlignerGaps.java
new file mode 100644
index 0000000..4937c47
--- /dev/null
+++ b/Source/mesquite/align/lib/TwoSequenceAlignerGaps.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.align.lib;
+
+/* ~~ */
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public abstract class TwoSequenceAlignerGaps extends TwoSequenceAligner {
+	public Class getDutyClass() {
+		return TwoSequenceAlignerGaps.class;
+	}
+
+	public String getDutyName() {
+		return "Pairwise Sequence Aligner (Maintains Gaps)";
+	}
+
+	/**
+	 * As a subclass of TwoSequenceAligner, the methods here have passed into them some 
+	 * additional arguments that ideally would be dealt with.
+	 * If maintainGaps is true, then the gaps that are present in sequence1 should be maintained.
+	 * 
+	 * Also, if maintainGaps is true, and newGaps1 is non-null, then newGaps1 should returned 
+	 * with bits filled where new gaps are added to sequence1.  Imagine that newGaps1 came in
+	 * as a Bits with 10 elements.  It should come in with all bits turned off, like this:  0000000000.  
+	 * If 3 new gaps were added to
+	 * sequence1, after positions 3, 6, and 8, then newGaps1 should come out with 13 elements, looking
+	 * like this:  0001000100100.  To do this, use the methods in Bits.  e.g., Bits.addParts to insert new bits, and
+	 * then Bits.setBit to turn on the bits for the newly added bits.
+	 */
+
+	public long[][] alignSequences(MCategoricalDistribution data, int taxon1, int taxon2, int firstSite, int lastSite, boolean returnAlignment, MesquiteNumber score, boolean maintainGaps, Bits newGaps1 ) {
+		int numChars = lastSite - firstSite+1;
+		if (numChars <0 || !MesquiteInteger.isCombinable(firstSite) || !MesquiteInteger.isCombinable(lastSite)){
+			numChars = data.getNumChars();
+			firstSite = 0;
+			lastSite = numChars-1;
+		}
+		long[] extracted1 = new long[numChars];
+		long[] extracted2 = new long[numChars];
+
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[ic-firstSite] = data.getState(ic, taxon1);
+			extracted2[ic-firstSite] = data.getState(ic, taxon2);
+		}
+		CategoricalState state=(CategoricalState)(data.getParentData().makeCharacterState());
+		long[][] aligned =  alignSequences(extracted1, extracted2, returnAlignment,score, state,  maintainGaps, newGaps1);
+		return aligned;
+	}
+
+	public long[][] alignSequences(MCategoricalDistribution data, int taxon1, int taxon2, int firstSite, int lastSite, boolean returnAlignment, MesquiteNumber score) {
+		return alignSequences(data,taxon1,taxon2,firstSite, lastSite,returnAlignment,score,false,null);
+	}
+	
+	/**
+	 * This method is not called directly by Mesquite, but modules preferring to
+	 * receive and return the information as long[][] can override this and let the previous
+	 * method call it.  Also, this method receives only the pieces to be aligned.
+	 * Note that the long that is returned should be long[][2] in size.  
+	 */
+	public long[][] alignSequences(long[] sequence1, long[] sequence2, boolean returnAlignment, MesquiteNumber score, CategoricalState state,  boolean maintainGaps, Bits newGaps1) {
+		return null;
+	}
+	
+	public long[][] alignSequences(long[] sequence1, long[] sequence2, boolean returnAlignment, MesquiteNumber score, CategoricalState state) {
+		return alignSequences(sequence1,sequence2,returnAlignment,score,state, false, null);
+	}
+
+}
+
diff --git a/Source/mesquite/ancstates/AncestralStatesAll/AncestralStatesAll.java b/Source/mesquite/ancstates/AncestralStatesAll/AncestralStatesAll.java
new file mode 100644
index 0000000..d95d37d
--- /dev/null
+++ b/Source/mesquite/ancstates/AncestralStatesAll/AncestralStatesAll.java
@@ -0,0 +1,128 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.AncestralStatesAll;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AncestralStatesAll extends CharsStatesForNodes {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharStatesForNodes.class, getName() + " needs a module to calculate ancestral state reconstructions.",
+		"The reconstruction method is chosen initially or using the Reconstruction Method submenu");
+	}
+	CharStatesForNodes assignTask;
+	MCharactersHistory resultStates;
+	MesquiteString assignTaskName;
+	MesquiteCommand atC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		assignTask = (CharStatesForNodes)hireEmployee(CharStatesForNodes.class, "Reconstruction method");
+		if (assignTask == null){
+ 			return sorry(getName() + " couldn't start because no reconstruction module was obtained");
+ 		}
+		atC = makeCommand("setMethod",  this);
+		assignTask.setHiringCommand(atC);
+
+		assignTaskName = new MesquiteString(assignTask.getName());
+		if (numModulesAvailable(CharStatesForNodes.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Reconstruction Method", atC, CharStatesForNodes.class);
+			mss.setSelected(assignTaskName);
+		}
+  		return true;
+ 	}
+ 	
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setMethod ",assignTask);
+  	 	return temp;
+  	 }
+	public boolean allowsStateWeightChoice(){
+		return false;
+	}
+/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets module used to reconstruct ancestral states", "[name of module]", commandName, "setMethod")) {
+    	 		CharStatesForNodes temp=  (CharStatesForNodes)replaceEmployee(CharStatesForNodes.class, arguments, "Reconstruction method", assignTask);
+ 			if (temp!=null) {
+ 				assignTask= temp;
+				assignTask.setHiringCommand(atC);
+				assignTaskName.setValue(assignTask.getName());
+				parametersChanged();
+ 			}
+ 			return assignTask;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+	/*...............................................................................................................*/
+	public MCharactersHistory calculateStates(Tree tree, MCharactersDistribution observedStates, MCharactersHistory resultStates, MesquiteString resultString){
+		if (observedStates==null || tree == null)
+			return null;
+		resultStates=observedStates.adjustHistorySize(tree, resultStates);
+	     	CharacterDistribution oneObserved = observedStates.getCharacterDistribution(0);
+		CharacterHistory oneReconstructed = oneObserved.adjustHistorySize(tree, null);
+		if (assignTask!=null) {
+     	 		for (int ic=0; ic<observedStates.getNumChars(); ic++) {
+	     	 		oneObserved = observedStates.getCharacterDistribution(ic);
+				assignTask.calculateStates(tree, oneObserved, oneReconstructed, null);
+				resultStates.transferFrom(ic, oneReconstructed);
+ 			}
+ 		}
+ 		return resultStates;
+	}
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Ancestral States All";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameAndParameters() {
+		if (assignTask == null)
+			return getName();
+		return "Reconstructed Ancestral States (" + assignTask.getName() + ")";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Reconstructs ancestral states at nodes for all characters supplied by character source." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		if (assignTask == null)
+ 			return "";
+		return "Reconstructed Ancestral States (" + assignTask.getName() + ")";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/ancstates/ExportAncRec/ExportAncRec.java b/Source/mesquite/ancstates/ExportAncRec/ExportAncRec.java
new file mode 100644
index 0000000..5d32e91
--- /dev/null
+++ b/Source/mesquite/ancstates/ExportAncRec/ExportAncRec.java
@@ -0,0 +1,198 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.ExportAncRec;
+
+import java.util.*;
+
+import mesquite.categ.lib.*;
+import mesquite.ancstates.TraceCharacterHistory.TraceCharacterOperator;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ExportAncRec extends TraceCharacterInit {
+	public String getName() {
+		return "Export Ancestral States Trace";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Exports the ancestral state trace from Trace Character History.";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	Vector traces;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		MesquiteSubmenuSpec treeStringSM = addSubmenu(null, "Export Ancestral States Trace"); 
+		addItemToSubmenu(null, treeStringSM, "SIMMAP 1.5 Format...", makeCommand("showTreeStringSIMMAP15",  this));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void setCharacterHistoryContainers(Vector historyContainers){
+		traces = historyContainers;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows the trace as a tree string", null, commandName, "showTreeStringSIMMAP15")) {
+			//todo: if more than one traced, query user which one to store��������������������
+
+			if (traces == null || traces.size()<1 || !(traces.elementAt(0) instanceof CharHistoryContainer))
+				return null;
+			TraceCharacterOperator trace = (TraceCharacterOperator)traces.elementAt(0);
+			if (!(trace.history instanceof mesquite.categ.lib.CategoricalHistory)){
+				discreetAlert("Sorry, SIMMAP format tree exporting works only for categorical data");
+				return null;
+			}
+			MesquiteTree tree = (MesquiteTree)trace.getTree();
+			String s = getTreeBlockSIMMAP(tree, trace);
+			if (s == null)
+				return null;
+			MesquiteFile.putFileContentsQuery("Save Ancestral States On Tree (SIMMAP)", s, true);
+			return s;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*-%%%%%%%%%%%%%%%%%%  SIMMAP 1.5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%--*/
+	/** Writes a tree description into the StringBuffer using translation table labels if available */
+	private void writeTreeByLabelsSIMMAP(MesquiteTree tree, int node, StringBuffer buffer, mesquite.categ.lib.CategoricalHistory history, int writeMode) {
+		if (tree.nodeIsInternal(node)) {
+			buffer.append('(');
+			int thisSister = tree.firstDaughterOfNode(node);
+			writeTreeByLabelsSIMMAP(tree,thisSister, buffer, history, writeMode);
+			while (tree.nodeExists(thisSister = tree.nextSisterOfNode(thisSister))) {
+				buffer.append(',');
+				writeTreeByLabelsSIMMAP(tree, thisSister, buffer, history, writeMode);
+			}
+			buffer.append(')');
+			if (tree.nodeHasLabel(node))
+				buffer.append(StringUtil.tokenize(tree.getNodeLabel(node)));
+		}
+		else {
+			if (writeMode == Tree.BY_TABLE)//use treeVector's translation table if one is available
+				buffer.append(tree.getTreeVector().getTranslationLabel(tree.taxonNumberOfNode(node))); 
+			else if (writeMode == Tree.BY_NUMBERS)
+				buffer.append(Integer.toString(Taxon.toExternal(tree.taxonNumberOfNode(node))));
+			else
+				buffer.append(StringUtil.tokenize(tree.getTaxa().getTaxonName(tree.taxonNumberOfNode(node))));
+		}
+		buffer.append(':');
+		int num = history.getNumberOfEvents(node);
+		if (num>0 && node != tree.getRoot()){
+			String par = "";
+
+			boolean found = false;
+			double lastPos = 0;
+			for (int i= num-1; i>=0; i--){
+				CategInternodeEvent event = history.getInternodeEvent(node, i);
+
+				if (event.getChangeVersusSample()){
+					if (found)
+						par += ", ";
+					found = true;
+					par += CategoricalState.toString(event.getState(), false);
+					par += ", " + MesquiteDouble.toStringDigitsSpecified(tree.getBranchLength(node, 1)*((1.0-event.getPosition())-lastPos), 4);
+					lastPos = 1.0-event.getPosition();
+				}
+
+			}
+			long state = history.getState(tree.motherOfNode(node));
+			if (CategoricalState.cardinality(state) == 1){
+				if (found)
+					par += ", ";
+				par += CategoricalState.toString(state, false);  //ancestorward state
+			}
+
+			buffer.append("[&map={");
+			buffer.append(par);
+			buffer.append("}]");
+		}
+		else {
+			long state = history.getState(node);
+			if (CategoricalState.cardinality(state) == 1){
+				buffer.append("[&map={");
+				buffer.append(CategoricalState.toString(state, false));
+				buffer.append("}]");
+			}
+		}
+		buffer.append(MesquiteDouble.toStringDigitsSpecified(tree.getBranchLength(node, 1.0), -1)); 
+
+	}
+	/*-----------------------------------------*/
+	public String getTreeBlockSIMMAP(MesquiteTree tree, TraceCharacterOperator trace){
+		String endLine = ";" + StringUtil.lineEnding();
+		StringBuffer block = new StringBuffer(5000);
+		Taxa taxa = tree.getTaxa();
+		block.append("#NEXUS");
+		block.append( StringUtil.lineEnding());
+		block.append("BEGIN TREES");
+		block.append(endLine);
+		block.append("\tTRANSLATE" + StringUtil.lineEnding());
+		int writeMode = Tree.BY_NUMBERS;
+		String tt = null;
+
+		if (tree.getTreeVector() != null){
+			TreeVector trees = tree.getTreeVector();
+			tt =trees.getTranslationTable();
+			if (tt != null)
+				writeMode = Tree.BY_TABLE;
+		}
+		if (tt==null) {
+			tt = "";
+			if (taxa!=null)
+				for(int i=0; i<taxa.getNumTaxa(); i++) {
+					if (i>0)
+						tt += ","+ StringUtil.lineEnding();
+					tt += "\t\t" + Taxon.toExternal(i) + "\t" + StringUtil.tokenize(taxa.getTaxonName(i)) ;
+				}
+			writeMode = Tree.BY_NUMBERS;
+		}
+		block.append( tt);
+
+		block.append(endLine);
+
+		block.append("\tTREE ");
+		block.append(StringUtil.tokenize(tree.getName() )+ " = " );
+		writeTreeByLabelsSIMMAP( tree, tree.getRoot(), block, (mesquite.categ.lib.CategoricalHistory)trace.history, writeMode);
+		block.append(endLine);
+		block.append("END;" + StringUtil.lineEnding()+ StringUtil.lineEnding());
+		return block.toString();
+	}
+	/*-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%--*/
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/ancstates/LabelStatesOnTree/LabelStatesOnTree.java b/Source/mesquite/ancstates/LabelStatesOnTree/LabelStatesOnTree.java
new file mode 100644
index 0000000..d710d51
--- /dev/null
+++ b/Source/mesquite/ancstates/LabelStatesOnTree/LabelStatesOnTree.java
@@ -0,0 +1,134 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.LabelStatesOnTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class LabelStatesOnTree extends DisplayStatesAtNodes {
+	TreeDisplay treeDisplay;
+ 	Vector labellers;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		labellers = new Vector();
+ 		return true;
+	}
+	/*.................................................................................................................*/
+	public   TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		LabelStatesDecorator newLabeller = new LabelStatesDecorator(this, treeDisplay, ownerExtra);
+		labellers.addElement(newLabeller);
+		return newLabeller;
+	}
+ 	
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	public void endJob() {
+		Enumeration e = labellers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof LabelStatesDecorator) {
+				LabelStatesDecorator tCO = (LabelStatesDecorator)obj;
+	 			tCO.turnOff();
+	 		}
+		}
+ 		super.endJob();
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Label states";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "A module that displays character states on tree using labels.  This is a display-only module,"
+ 		+ " and would be hired by another module that organizes assigning states to the nodes." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class LabelStatesDecorator extends TreeDecorator {
+ 	LabelStatesOnTree ownerModule;
+
+	public LabelStatesDecorator (LabelStatesOnTree ownerModule, TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		super(treeDisplay, ownerExtra);
+		this.ownerModule=ownerModule;
+	}
+	/*.................................................................................................................*/
+	public   void labelNode(int N,  Tree tree, CharacterHistory statesAtNodes, CharacterDistribution observedStates, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				labelNode(d, tree, statesAtNodes, observedStates, g);
+		int nodeX = treeDisplay.getTreeDrawing().x[N];
+		int nodeY = treeDisplay.getTreeDrawing().y[N];
+		String label = statesAtNodes.toString(N, "\n"); 
+		if (label != null){
+			int width = StringUtil.getStringDrawLength(g, label);
+			int height = StringUtil.getTextLineHeight(g);
+			g.setColor(ColorDistribution.veryLightGray);
+			g.fillRect(nodeX-4, nodeY-4, width+8, height+8);
+			g.setColor(Color.black);
+			g.drawRect(nodeX-4, nodeY-4, width+8, height+8);
+			g.drawString(label, nodeX, nodeY+ height);
+		}
+		//g.setColor(Color.black);
+		/*Note: this does not yet show the observed states separately.  In light of the likely limited use of this compared to ShadeStates, it doesn't
+		seem worth enhancing this too much.
+		if (tree.nodeIsTerminal(N)) {
+			if (observedStates !=null) {
+				if (!observedStates.isUnassigned(tree.taxonNumberOfNode(N))&&!(observedStates.isInapplicable(tree.taxonNumberOfNode(N))))
+					;
+			}
+			else
+				;
+		}
+		*/
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Object obj, Object obj2, Object obj3, Graphics g) {
+		if (!(obj instanceof CharacterHistory))
+			return;
+		CharacterHistory statesAtNodes = (CharacterHistory)obj;
+		CharacterDistribution observedStates = (CharacterDistribution)obj2;
+		if (treeDisplay!=null && tree!=null && statesAtNodes!=null) {
+				if (observedStates == null)
+					observedStates = statesAtNodes.getObservedStates();
+			
+			statesAtNodes.prepareColors(tree, drawnRoot);
+			labelNode(drawnRoot, tree, statesAtNodes,observedStates, g);
+
+		}
+		else
+			MesquiteMessage.warnProgrammer("Error: draw on tree label states//null");
+	}
+	
+	/*.................................................................................................................*/
+	public void turnOff() {
+	}
+}
+
diff --git a/Source/mesquite/ancstates/RecAncestralStates/RecAncestralStates.java b/Source/mesquite/ancstates/RecAncestralStates/RecAncestralStates.java
new file mode 100644
index 0000000..1145de8
--- /dev/null
+++ b/Source/mesquite/ancstates/RecAncestralStates/RecAncestralStates.java
@@ -0,0 +1,313 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.RecAncestralStates;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class RecAncestralStates extends CharHistorySource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters whose ancestral states are to be reconstructed.",
+		"The source of characters for reconstruction can be chosen initially or later in the Source of Characters or Character Source submenus");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(CharMapper.class, getName() + " needs a method by which to reconstruct ancestral states.",
+		"The reconstruction method can be chosen initially or in the Reconstrction Method submenu");
+	}
+	CharMapper assignTask;
+	public CharSourceCoordObed characterSourceTask;
+
+	private CharacterDistribution currentObservedStates=null;
+	private Taxa currentTaxa=null;
+	int lastCharRetrieved = -1;
+	long oldTreeVersion = 0;
+	long oldTreeID = 0;
+	MesquiteString assignTaskName;
+	MesquiteCommand atC;
+	//private CharacterHistory recon;
+	Object hiringCondition;
+	boolean doMappings = false;
+	Selectionable selectionable = null;
+	MesquiteCMenuItemSpec selectedOnlyMenuItem;
+	MesquiteBoolean showSelectedOnly = new MesquiteBoolean(false);
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hiringCondition = condition;
+		if (condition!=null) 
+			characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, condition, "Source of characters to reconstruct");
+		else
+			characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters to reconstruct");
+		if (characterSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of characters obtained.");
+		}
+		assignTask = (CharMapper)hireEmployee(CharMapper.class, "Ancestral state reconstruction method");
+		if (assignTask == null) {
+			return sorry(getName() + " couldn't start because no reconstruction module obtained.");
+		}
+		assignTask.setOneCharacterAtATime(true);
+		atC = makeCommand("setMethod",  this);
+		assignTask.setHiringCommand(atC);
+
+		assignTaskName = new MesquiteString(assignTask.getName());
+		if (numModulesAvailable(CharMapper.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Reconstruction Method", atC, CharMapper.class);
+			mss.setSelected(assignTaskName);
+		}
+
+		selectionable = characterSourceTask.getSelectionable();
+		if (selectionable != null)
+			selectedOnlyMenuItem=addCheckMenuItem(null, "Selected Characters Only", makeCommand("toggleShowSelectedOnly",  this), showSelectedOnly);
+		return true;
+	}
+	boolean permissiveOfNoSeparateMappings = false;
+	public void prepareForMappings(boolean permissiveOfNoSeparateMappings){
+		this.permissiveOfNoSeparateMappings = permissiveOfNoSeparateMappings;
+		if (assignTask!=null) {
+			assignTask.prepareForMappings(permissiveOfNoSeparateMappings);
+			doMappings = true;
+		}
+		
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask || employee == assignTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	public boolean allowsStateWeightChoice(){
+		if (assignTask == null)
+			return false;
+		else
+			return assignTask.allowsStateWeightChoice();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setMethod ",assignTask);
+		temp.addLine("toggleShowSelectedOnly " + showSelectedOnly.toOffOnString());  
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to reconstruct ancestral states", "[name of module]", commandName, "setMethod")) {
+			CharMapper temp=  (CharMapper)replaceEmployee(CharMapper.class, arguments, "Reconstruction method", assignTask);
+			if (temp!=null) {
+				assignTask= temp;
+				assignTask.setHiringCommand(atC);
+				assignTaskName.setValue(assignTask.getName());
+				assignTask.setOneCharacterAtATime(true);
+				if (doMappings)
+					assignTask.prepareForMappings(permissiveOfNoSeparateMappings);
+				parametersChanged();
+			}
+			return assignTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the number of histories", null, commandName, "getNumHistories")) {
+			return new MesquiteInteger(getNumberOfHistories(currentTaxa));
+		}
+		else if (checker.compare(this.getClass(), "Returns the number of mappings", null, commandName, "getNumMappings")) {
+			return new MesquiteLong(getNumberOfMappings(currentTaxa, lastCharRetrieved));
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) { //temporary while data files still exist that don't use coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not only selected characters are returned", "[on = show; off]", commandName, "toggleShowSelectedOnly")) {
+			showSelectedOnly.toggleValue(parser.getFirstToken(arguments));
+			lastCharRetrieved = -1;
+			currentObservedStates = null;
+			parametersChanged();
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	Tree tree = null;
+	public  void prepareHistory(Tree tree, int ic){
+		this.tree = tree;
+		if (tree == null) {
+			return;
+		}
+		if (tree.getTaxa() != currentTaxa|| (characterSourceTask.usesTree() && (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion)) || ic != lastCharRetrieved || currentObservedStates == null ) {
+			
+			int maxnum = getNumberOfHistories(tree);
+			if (ic>= maxnum)
+				ic = maxnum-1;
+			
+			currentObservedStates = characterSourceTask.getCharacter(tree, translateIfSelectedOnly(ic, tree.getTaxa()));
+			
+			
+			currentTaxa = tree.getTaxa();
+			oldTreeVersion = tree.getVersionNumber();
+			oldTreeID = tree.getID();
+			lastCharRetrieved = ic;
+		}
+		if (currentObservedStates == null)
+			return;
+
+		assignTask.setObservedStates(tree, currentObservedStates);
+	}
+	public String getMappingTypeName(){
+		if (assignTask == null)
+			return "Mapping";
+		return assignTask.getMappingTypeName();
+	}
+	/*.................................................................................................................*/
+	public CharacterHistory getMapping(long im, CharacterHistory history, MesquiteString resultString) {
+		clearLastResult();
+		if (tree == null){
+			if (!MesquiteThread.isScripting())
+				MesquiteMessage.warnUser("Error: tree not obtained for reconstruct ancestral states");
+			if (resultString!=null)
+				resultString.setValue("No character history could be reconstructed because no tree was supplied for the calculations");
+			return null;
+		}
+		if (currentObservedStates == null) {
+			if (!MesquiteThread.isScripting())
+				MesquiteMessage.warnUser("Error: character distribution not obtained for reconstruct ancestral states");
+			if (resultString!=null)
+				resultString.setValue("No character history could be reconstructed because no character distribution was supplied for the calculations");
+			return null;
+		}
+
+		//preparing to receive mapping
+		history =currentObservedStates.adjustHistorySize(tree, history);
+		boolean success = assignTask.getMapping(im, history, resultString);
+		if (resultString!=null)
+			resultString.prepend("Character: " + currentObservedStates.getName() + "\n");
+		if (history == null || !success) { 
+			if (resultString!=null)
+				resultString.setValue("Ancestral states not successfully reconstructed at nodes.");
+			MesquiteMessage.warnProgrammer("Error: states not successfully reconstructed at nodes (Reconstruct Ancestral States)");
+			return null;
+		}
+		else  {
+			history.setObservedStates(currentObservedStates);
+			saveLastResult(history);
+			return history;
+		}
+	}
+	private int translateIfSelectedOnly(int ic, Taxa taxa){
+		if (selectionable == null || !showSelectedOnly.getValue())
+			return ic;
+		int count = -1;
+		for (int i = 0; i< characterSourceTask.getNumberOfCharacters(taxa); i++){
+			if (selectionable.getSelected(i))
+				count++;
+			if (count == ic)
+				return i;
+		}
+		return ic;
+	}
+	/** returns the name of history ic*/
+	public String getHistoryName(Taxa taxa, int ic){
+		return characterSourceTask.getCharacterName(taxa, translateIfSelectedOnly(ic, taxa));
+	}
+	/** returns the name of history ic*/
+	public String getHistoryName(Tree tree, int ic){
+		return characterSourceTask.getCharacterName(tree, translateIfSelectedOnly(ic, tree.getTaxa()));
+	}
+	public int getNumberOfHistories(Tree tree){
+		if (characterSourceTask == null || tree == null)
+			return 0;
+		
+		if (selectionable != null && showSelectedOnly.getValue()){
+			characterSourceTask.getNumberOfCharacters(tree.getTaxa()); // to initialize if needed
+			
+			return selectionable.numberSelected();
+		}
+		return characterSourceTask.getNumberOfCharacters(tree.getTaxa());
+	}
+	public int getNumberOfHistories(Taxa taxa){
+		if (characterSourceTask == null)
+			return 0;
+		if (selectionable != null && showSelectedOnly.getValue()){
+			characterSourceTask.getNumberOfCharacters(taxa); // to initialize if needed
+			return selectionable.numberSelected();
+		}
+		return characterSourceTask.getNumberOfCharacters(taxa);
+	}
+	public long getNumberOfMappings(Tree tree,  int ic){
+		if (assignTask == null)
+			return 0;
+		return assignTask.getNumberOfMappings();
+	}
+	public long getNumberOfMappings(Taxa taxa,  int ic){
+		if (assignTask == null)
+			return 0;
+		return assignTask.getNumberOfMappings();
+	}
+	/** returns the name of history ic and mapping im*/
+	public String getMappingName(Taxa taxa, int ic, long im){
+		return getHistoryName(taxa, ic);
+	}
+	/** returns the name of history ic and mapping im*/
+	public String getMappingName(Tree tree, int ic, long im){
+		return getHistoryName(tree, ic);
+	}
+	/** returns the name of histories for menu items, e.g. if each history represents a character, return "Character"*/
+	public  String getHistoryTypeName(){
+		return "Character";
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask || employee == assignTask) {
+			currentObservedStates = null;  // to force retrieval of new observedStates
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Reconstruct Ancestral States";
+	}
+
+	/*.................................................................................................................*/
+	public String getNameAndParameters() {
+		if (assignTask == null)
+			return getName();
+		return "Reconstructed Ancestral States (" + assignTask.getName() + ")";
+	}
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Reconstructs ancestral states on the nodes of a tree.";
+	}
+}
+
+
diff --git a/Source/mesquite/ancstates/ShadeStatesOnTree/ShadeStatesOnTree.java b/Source/mesquite/ancstates/ShadeStatesOnTree/ShadeStatesOnTree.java
new file mode 100644
index 0000000..e0327ca
--- /dev/null
+++ b/Source/mesquite/ancstates/ShadeStatesOnTree/ShadeStatesOnTree.java
@@ -0,0 +1,251 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.ShadeStatesOnTree;
+
+import java.util.*;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ShadeStatesOnTree extends DisplayStatesAtNodes {
+	Vector shaders;
+	public boolean holding = false;
+	MesquiteBoolean showLabels;
+	MesquiteBoolean showPredictions;
+	MesquiteBoolean useGray;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showLabels = new MesquiteBoolean(false);
+		useGray = new MesquiteBoolean(false);
+		showPredictions = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Show Labels for States", makeCommand("toggleLabels", this), showLabels);
+		addCheckMenuItem(null, "Show Predictions for Missing and Inapplicable Data", makeCommand("togglePredictions", this), showPredictions);
+		addCheckMenuItem(null, "Use Gray for Equivocal", makeCommand("toggleGray", this), useGray);
+		shaders = new Vector();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		ShadeStatesDecorator newShader = new ShadeStatesDecorator(this, treeDisplay, ownerExtra);
+		shaders.addElement(newShader);
+		return newShader;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("toggleLabels " + showLabels.toOffOnString());
+		temp.addLine("togglePredictions " + showPredictions.toOffOnString());
+		temp.addLine("toggleGray " + useGray.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not states are labeled", "[on = labeled; off]", commandName, "toggleLabels")) {
+			showLabels.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else	if (checker.compare(this.getClass(), "Sets whether or not states equivocal is shown as gray", "[on = labeled; off]", commandName, "toggleGray")) {
+			useGray.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else	if (checker.compare(this.getClass(), "Sets whether or not predictions are shown for clades with missing or inapplicable data", "[on = labeled; off]", commandName, "togglePredictions")) {
+			showPredictions.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Shade states";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Shows the states at nodes by shading branches or nodes using colors, black and white, or shades of gray.";
+	}
+	public void onHold() {
+		holding = true;
+	}
+
+	public void offHold() {
+		holding = false;
+	}
+}
+/* ======================================================================== */
+class ShadeStatesDecorator extends TreeDecorator {
+	ShadeStatesOnTree ownerModule;
+	ColorDistribution colors;
+	ColorDistribution grayEquivocal;
+	ColorEventVector colorSequence;
+	TreeDrawing oldDrawing = null;
+	boolean turnedOff = false;
+
+	public ShadeStatesDecorator (ShadeStatesOnTree ownerModule, TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		super(treeDisplay, ownerExtra);
+		this.ownerModule=ownerModule;
+		colors = new ColorDistribution();
+		grayEquivocal = new ColorDistribution();
+		grayEquivocal.setColor(0, Color.lightGray);
+		turnedOff = false;
+		if (treeDisplay!=null && treeDisplay.getTreeDrawing()!=null) {
+			treeDisplay.getTreeDrawing().incrementEnableTerminalBoxes();
+			oldDrawing = treeDisplay.getTreeDrawing();
+		}
+	}
+	/*.................................................................................................................*/
+	private   void writeStateAtNode(CharacterHistory statesAtNodes,CharacterDistribution observedStates, Graphics g, int N,  Tree tree) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			writeStateAtNode(statesAtNodes, observedStates, g, d, tree);
+		int nodeX = treeDisplay.getTreeDrawing().x[N];
+		int nodeY = treeDisplay.getTreeDrawing().y[N];
+		if (treeDisplay.getOrientation() == treeDisplay.UP) {
+			nodeY+=10;
+			//nodeX+=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.DOWN) {
+			nodeY-=10;
+			//nodeX+=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.RIGHT) {
+			//nodeY=20;
+			nodeX-=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.LEFT) {
+			//nodeY+=20;
+			nodeX+=10;
+		}
+		StringUtil.highlightString(g, statesAtNodes.toString(N, " "), nodeX, nodeY, Color.blue, Color.white);
+	}
+	CharacterState cs;
+
+	MesquiteColorTable colorTable = MesquiteColorTable.DEFAULTCOLORTABLE; //MesquiteColorTable.GRAYSCALE
+
+	/*.................................................................................................................*/
+	private boolean shadeNode(int N, Tree tree, CharacterHistory statesAtNodes, CharacterDistribution observedStates, MesquiteBoolean showStateWeights, Graphics g) {
+		boolean anyDataInClade = ownerModule.showPredictions.getValue();
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)){
+			boolean dataInDaughterClade = shadeNode(d, tree, statesAtNodes, observedStates, showStateWeights, g);
+			if (dataInDaughterClade)
+				anyDataInClade = true;
+		}
+		//This is the tracing of changes along the internode, for instance for stochastic character mapping
+		colorSequence = statesAtNodes.getColorSequenceAtNode(N, colorTable);
+		if (colorSequence != null) {
+			treeDisplay.getTreeDrawing().fillBranchWithColorSequence(tree,  N, colorSequence, g);
+			anyDataInClade = true;
+		}
+		else {
+
+			if (tree.nodeIsTerminal(N)) {  //terminal
+				if (observedStates !=null) {
+					int M = tree.taxonNumberOfNode(N);
+					if (!observedStates.isUnassigned(M)&&!(observedStates.isInapplicable(M))) {
+						int numColors=0;
+						
+						numColors=statesAtNodes.getColorsAtNode(N, colors, colorTable, showStateWeights == null || showStateWeights.getValue()); //, ownerModule.getProject().stateColors
+						treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  N, colors, g);
+						numColors = statesAtNodes.getColorsOfState(cs = observedStates.getCharacterState(cs, M), colors, colorTable); //, ownerModule.getProject().stateColors
+
+						treeDisplay.getTreeDrawing().fillTerminalBoxWithColors(tree,  N, colors, g);
+						anyDataInClade = true;
+					}
+					else {  //missing data! Terminal
+						if (ownerModule.showPredictions.getValue()){
+							int numColors=statesAtNodes.getColorsAtNode(N, colors, colorTable, showStateWeights == null || showStateWeights.getValue()); //, ownerModule.getProject().stateColors
+							treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  N, colors, g);
+						}
+						else
+							treeDisplay.getTreeDrawing().fillBranchWithMissingData(tree,  N, g);
+					}
+				}
+				else {
+					int numColors=statesAtNodes.getColorsAtNode(N, colors, colorTable, showStateWeights == null || showStateWeights.getValue()); //, ownerModule.getProject().stateColors
+					if (numColors!=0)
+						treeDisplay.getTreeDrawing().fillTerminalBoxWithColors(tree,  N, colors, g);
+					anyDataInClade = true;
+				}
+			}
+			else {
+				if (!anyDataInClade){  //missing data!!!
+					treeDisplay.getTreeDrawing().fillBranchWithMissingData(tree,  N, g);
+				}
+				else {
+					int numColors=statesAtNodes.getColorsAtNode(N, colors, colorTable, showStateWeights == null || showStateWeights.getValue()); //, ownerModule.getProject().stateColors
+
+					if (ownerModule.useGray.getValue() && numColors >1) {
+						treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  N, grayEquivocal, g);
+					}
+					//This is the basic, old-fashioned tracing of a character
+					else
+						treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  N, colors, g);
+				}
+			}
+
+		}
+
+		g.setColor(Color.black);
+		return anyDataInClade;
+	}
+	public void useColorTable(MesquiteColorTable table){  
+		colorTable = table;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Object obj, Object obj2, Object obj3, Graphics g) {
+		if (!(obj instanceof CharacterHistory))
+			return;
+		CharacterHistory statesAtNodes = (CharacterHistory)obj;
+		CharacterDistribution observedStates = (CharacterDistribution)obj2;
+		MesquiteBoolean showStateWeights = null;
+		if (obj3 instanceof MesquiteBoolean)
+			showStateWeights= (MesquiteBoolean)obj3;
+		if (treeDisplay.getTreeDrawing()!=oldDrawing) {
+			oldDrawing = treeDisplay.getTreeDrawing();
+			oldDrawing.incrementEnableTerminalBoxes();
+		}
+		if (!ownerModule.holding) {
+			if (treeDisplay!=null && tree!=null && statesAtNodes!=null) {
+				if (observedStates == null)
+					observedStates = statesAtNodes.getObservedStates();
+				statesAtNodes.prepareColors(tree, drawnRoot);
+				shadeNode(drawnRoot, tree, statesAtNodes, observedStates, showStateWeights, g);
+				if (ownerModule.showLabels.getValue())
+					writeStateAtNode(statesAtNodes, observedStates, g,drawnRoot,tree);
+			}
+			else
+				MesquiteMessage.warnProgrammer("Shade states -- null tree display, tree, or states at nodes");
+		}
+	}
+	public void turnOff() {
+		if (!turnedOff && treeDisplay!=null && treeDisplay.getTreeDrawing()!=null)
+			treeDisplay.getTreeDrawing().decrementEnableTerminalBoxes();
+		turnedOff = true;
+	}
+}
+
diff --git a/Source/mesquite/ancstates/SummarizeChanges/SummarizeChanges.java b/Source/mesquite/ancstates/SummarizeChanges/SummarizeChanges.java
new file mode 100644
index 0000000..3b64d89
--- /dev/null
+++ b/Source/mesquite/ancstates/SummarizeChanges/SummarizeChanges.java
@@ -0,0 +1,761 @@
+package mesquite.ancstates.SummarizeChanges;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.ancstates.lib.*;
+
+/* 
+ * 
+ * doesn't listen properly to changes
+ * 
+ * */
+/* this is a special module designed to be used in one of two ways, to summarize
+ * changes over trees without reference to a tree with selected branches, the other wiith reference to such a tree.
+ * If setup(taxa, boolean) is called, it is assumed the latter is in effect. (branchesMode = false)
+ * if setTree(tree) is called, it is assumed the former is in effect   (branchesMode = true)*/
+
+/*======================================================================== */
+public class SummarizeChanges extends ChgSummarizerMultTrees {
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharHistorySource.class, getName() + " needs a source of character histories.",
+				"The source of a traced history can be chosen using the Character History Source submenu");
+	}
+
+	static int maxNumMappings = 50;
+	int maxChangesRecorded = 10;
+	static boolean queryLimits = true;
+	MesquiteBoolean saveDetailsToFile = new MesquiteBoolean(false);
+
+	CharHistorySource historyTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand cstC;
+	TreeSource treeSourceTask;
+	MesquiteMenuItemSpec numTreesItem = null;
+	private int numTrees = 100;
+	//not yet ready double minPercent = 0.0;
+	boolean[][] allowedChanges =null;
+	int maxState = CategoricalState.maxCategoricalState;
+
+
+	StringArray modes;
+	MesquiteString modeName;
+
+	private boolean numTreesSet = false;
+	boolean suppress = false;
+	int currentChar=0;
+	MesquiteCommand htC;
+	MesquiteString historyTaskName;
+	Taxa currentTaxa;
+	MesquiteTextWindow textWindow;
+	boolean branchesMode = false;
+	boolean poppedOut;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (MesquiteThread.isScripting())
+			suppress = true;
+		historyTask = (CharHistorySource)hireCompatibleEmployee(CharHistorySource.class, CategoricalState.class,"Source of character history (for Summarize_Changes)");
+
+		if (historyTask == null) {
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		}
+		makeMenu("Summarize_Changes");
+		historyTaskName  = new MesquiteString(historyTask.getName());
+		htC = makeCommand("setHistorySource",  this);
+		if (numModulesAvailable(CharHistorySource.class)>1) {
+			historyTask.setHiringCommand(htC);
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character History Source", htC, CharHistorySource.class);
+			mss.setSelected(historyTaskName);
+		}
+		MesquiteMenuItemSpec mm = addMenuItem( "Next Character History", makeCommand("nextCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_RIGHT); //right
+		mm = addMenuItem( "Previous Character History", makeCommand("previousCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_LEFT); //right
+		addMenuItem( "Choose Character History", makeCommand("chooseCharacter",  this));
+		addMenuItem( "Allowed Changes...", makeCommand("allowedChanges",  this));
+		addMenuItem( "Maximum Number of Changes Recorded...", makeCommand("setMaxChangesRecorded",  this));
+		addMenuItem( "Maximum Number of Mappings...", makeCommand("setMaxNumMappings",  this));
+
+
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class,  "Source of trees for comparison by for Summarize Changes");
+		if (treeSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		}
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+
+
+		cstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(TreeSource.class)>1){ 
+			MesquiteSubmenuSpec mss3 = addSubmenu(null, "Tree source",cstC, TreeSource.class);
+			mss3.setSelected(treeSourceName);
+		}
+
+		numTreesItem = addMenuItem("Number of Trees...", makeCommand("setNumTrees", this));
+		numTreesItem.setEnabled(false);
+		addCheckMenuItem(null, "Save Details To File...", makeCommand("toggleSaveDetails", this), saveDetailsToFile);
+
+		addMenuItem( "Close Summarize Changes", makeCommand("closeSummarizeChanges",  this));
+		addMenuItem( "-", null);
+
+
+		allowedChanges = new boolean[CategoricalState.maxCategoricalState][CategoricalState.maxCategoricalState];
+		zeroAllowedChanges();
+
+		loadPreferences();
+
+		resetContainingMenuBar();
+
+		return true;
+	}
+	//this is called if without tree window to show changes over whole trees
+	public void setup(Taxa taxa, boolean poppedOut){
+		currentTaxa = taxa;
+		this.poppedOut = poppedOut;
+		branchesMode = false;
+
+		setup();
+		if (!MesquiteThread.isScripting() && textWindow == null) {
+			textWindow= new MesquiteTextWindow( this, "State Changes Over Trees", true, true, false);
+			setModuleWindow(textWindow);
+			textWindow.setPopAsTile(true);
+			if (poppedOut)
+				textWindow.popOut(true);
+			else textWindow.setVisible(true);
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+			recalculate();
+		}
+		if (textWindow != null)
+			textWindow.setTitle("State Changes Over Trees");
+	}
+	/*.................................................................................................................*/
+	public   void setup() {
+		checkNumTreesFromSource();
+		int numTrees2 = treeSourceTask.getNumberOfTrees(currentTaxa);
+		numTreesItem.setEnabled(!MesquiteInteger.isFinite(numTrees2));
+		MesquiteTrunk.resetMenuItemEnabling();
+	}
+	/*.................................................................................................................*/
+	public void checkNumTreesFromSource() {
+		if (treeSourceTask==null || currentTaxa==null)
+			return;
+		int nt = treeSourceTask.getNumberOfTrees(currentTaxa);
+		if (MesquiteInteger.isFinite(nt)) {
+			numTrees = nt;
+			numTreesSet = true;
+		}
+	}
+	/**/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		if (whichWindow != textWindow)
+			return;
+		whichWindow.hide();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == treeSourceTask || employee == historyTask)  
+			iQuit();
+	}
+
+	/*.................................................................................................................*/
+	public void zeroAllowedChanges(){
+		for (int i=0; i<allowedChanges.length; i++)
+			for (int j=0; j<allowedChanges[i].length; j++)
+				allowedChanges[i][j]=true;
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("maxNumMappings".equalsIgnoreCase(tag))
+			maxNumMappings = MesquiteInteger.fromString(content);
+		if ("maxChangesRecorded".equalsIgnoreCase(tag))
+			maxChangesRecorded = MesquiteInteger.fromString(content);
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "maxNumMappings", maxNumMappings);  
+		StringUtil.appendXMLTag(buffer, 2, "maxChangesRecorded", maxChangesRecorded);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress ");
+		temp.addLine("setBranchMode " + branchesMode);
+		temp.addLine("setHistorySource ",historyTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		temp.addLine("setMaxNumMappings " + maxNumMappings);
+		temp.addLine("setMaxChangesRecorded " + maxChangesRecorded);
+		temp.addLine( "setTreeSource " , treeSourceTask);
+		temp.addLine("setNumTrees " + numTrees);
+		temp.addLine("makeWindow");
+		temp.addLine("tell It");
+		Snapshot fromWindow = textWindow.getSnapshot(file);
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+		temp.addLine("desuppress ");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+
+	public boolean queryAllowedChanges(){
+		if (MesquiteThread.isScripting())
+			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Allowed Changes",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Allowed Changes");
+
+		int numStates = maxState+1;
+		String[] labels = new String[numStates];
+		for (int i=0; i<numStates; i++)
+			labels[i]=""+i;
+		Checkbox[][] changesAllowed = dialog.addCheckboxMatrix(numStates, numStates, labels, labels);
+
+		dialog.addHorizontalLine(1);
+
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			for (int i=0; i<numStates && i<allowedChanges.length; i++)
+				for (int j=0; j<numStates && j<allowedChanges[i].length; j++)
+					allowedChanges[j][i]=changesAllowed[i][j].getState();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0) ;
+	}
+	/*.................................................................................................................*/
+	public boolean saveDetails(){
+		return saveDetailsToFile.getValue() && !MesquiteThread.isScripting();
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Makes but doesn't show the window", null, commandName, "makeWindow")) {
+			if (textWindow==null) {
+				textWindow= new MesquiteTextWindow( this, "Summary of Changes", true, true, false);
+				if (branchesMode)
+					textWindow.setTitle("State Changes on Branches");
+				else
+					textWindow.setTitle("State Changes Over Trees");
+				setModuleWindow(textWindow);
+				resetContainingMenuBar();
+				resetAllWindowsMenus();
+			}
+			return textWindow;
+		}
+		else if (checker.compare(this.getClass(), "Sets branches mode", null, commandName, "setBranchMode")) {
+			String t = parser.getFirstToken(arguments);
+			branchesMode = ("true".equalsIgnoreCase(t));
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character history", null, commandName, "nextCharacter")) {
+			if (currentChar>=historyTask.getNumberOfHistories(currentTaxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			recalculate();
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character history", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=historyTask.getNumberOfHistories(currentTaxa)-1;
+			else
+				currentChar--;
+			recalculate();
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character history", null, commandName, "allowedChanges")) {
+			if (queryAllowedChanges())
+				recalculate();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to save all the calculation details to a file", "[on; off]", commandName, "toggleSaveDetails")) {
+			saveDetailsToFile.toggleValue(parser.getFirstToken(arguments));
+			if (saveDetails())
+				recalculate();
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum number of mappings", null, commandName, "setMaxNumMappings")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(getModuleWindow(), "Maximum number of mappings to sample", "Maximum number of mappings to sample for the character on each tree",maxNumMappings, 1, Integer.MAX_VALUE);
+			if (newNum>0 && MesquiteInteger.isCombinable(newNum) && maxNumMappings!=newNum) {
+				maxNumMappings=newNum;
+				storePreferences();
+				recalculate();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum number of changes recorded", null, commandName, "setMaxChangesRecorded")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(getModuleWindow(), "Maximum number of changes to record", "Maximum number of changes to record for the character on each tree",maxChangesRecorded, 1, Integer.MAX_VALUE);
+			if (newNum>0 && MesquiteInteger.isCombinable(newNum) && maxChangesRecorded!=newNum) {
+				maxChangesRecorded=newNum;
+				storePreferences();
+				recalculate();
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Queries user about which character history to use", null, commandName, "chooseCharacter")) {
+			int ic=historyTask.queryUserChoose(currentTaxa, " to trace ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				recalculate();
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Sets which character history to use", "[history number]", commandName, "setCharacter")) {
+			pos.setValue(0);
+			int icNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && (ic<=historyTask.getNumberOfHistories(currentTaxa)-1)) {
+				currentChar = ic;
+				recalculate();
+			}
+		}
+		else /**/
+			if (checker.compare(this.getClass(), "Sets the number of trees", "[number]", commandName, "setNumTrees")) {
+				int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(newNum))
+					newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for Summarize Changes over Trees):", numTrees, 0, MesquiteInteger.infinite);
+				if (newNum>0  && newNum!=numTrees) {
+					numTrees = newNum;
+					numTreesSet = true;
+					if (!suppress){
+					}
+				}
+				else if (numTrees == newNum)
+					numTreesSet = true;
+			}
+			else /**/
+				if (checker.compare(this.getClass(), "Sets the source of trees for comparison", "[name of module]", commandName, "setTreeSource")) {
+					TreeSource temp =  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees for comparison by for Summarize Changes over Trees", treeSourceTask);
+					if (temp!=null) {
+						treeSourceTask=  temp;
+						treeSourceTask.setHiringCommand(cstC);
+						treeSourceName.setValue(treeSourceTask.getName());
+						numTreesSet = false;
+						checkNumTreesFromSource();
+						if (!suppress){
+							recalculate();
+							parametersChanged();
+						}
+					}	
+					return temp;
+				}
+				else if (checker.compare(this.getClass(), "Sets module supplying character histories", "[name of module]", commandName, "setHistorySource")) {
+					CharHistorySource temp =  (CharHistorySource)replaceEmployee(CharHistorySource.class, arguments, "Source of character histories", historyTask);
+					if (temp!=null) {
+						historyTask=  temp;
+						historyTask.setHiringCommand(htC);
+						historyTaskName.setValue(historyTask.getName());
+						currentChar=0;
+						recalculate();
+						if (!suppress)
+							recalculate();
+					}
+					return historyTask;
+				}
+				else if (checker.compare(this.getClass(), "Suppresses calculations", null, commandName, "suppress")) {
+					suppress = true;
+				}
+				else if (checker.compare(this.getClass(), "Desuppresses calculations", null, commandName, "desuppress")) {
+					suppress = false;
+					if (textWindow != null)
+						textWindow.setVisible(true);
+
+					recalculate();
+				}
+				else if (checker.compare(this.getClass(), "Returns ancestral states calculating module", null, commandName, "getAncStSource")) {
+					return historyTask;
+				}
+				else if (checker.compare(this.getClass(), "Turns off Summarize Changes over Trees", null, commandName, "closeSummarizeChanges")) {
+					iQuit();
+					resetContainingMenuBar();
+				}
+				else
+					return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public int getNumTrees(){
+		if (MesquiteThread.isScripting() || numTreesSet)
+			return numTrees;
+		int newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for Summarize Changes over Trees):", numTrees, 0, MesquiteInteger.infinite);
+		if (newNum>0) {
+			numTrees = newNum;
+			numTreesSet = true;
+		}
+		return numTrees;
+	}
+	public void setNumTrees(int numTrees){
+		if (numTrees>0 && MesquiteInteger.isCombinable(numTrees)) {
+			this.numTrees = numTrees;
+			numTreesSet = true;
+		}
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj instanceof Tree) {
+			if (code!=MesquiteListener.SELECTION_CHANGED  || getSensitiveToBranchSelection()) {
+				recalculate();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+			recalculate();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "State Change Summarizer (over trees)";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Summarizes reconstructions of state changes of a character over a series of trees.";
+	}
+	public int getMaxState() {
+		return maxState;
+	}
+	public void setMaxState(int maxState, CategStateChanges stateChanges) {
+		this.maxState = maxState;
+		stateChanges.adjustNumStates(maxState+1);
+	}
+	public void setAcceptableChanges(CategStateChanges stateChanges) {
+		if (stateChanges!=null)
+			for (int i=0; i<=maxState && i<allowedChanges.length; i++)
+				for (int j=0; j<=maxState && j<allowedChanges[i].length; j++)
+					stateChanges.setAcceptableChange(i, j,allowedChanges[i][j]);
+	}
+
+	/**********&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*************/
+	Tree myTree;
+	int totalTrees =0;
+	MesquiteString resultString = new MesquiteString();
+	String currentText = "";
+
+	boolean firstTreeHasAllTaxa = true;
+
+	/*.................................................................................................................*/
+
+	public void addFullDetailsHeader (int numStates, StringBuffer sb) {
+		if (sb==null)
+			return;
+		sb.append("tree\t");
+
+		for (int i=0; i<numStates; i++)
+			for (int j=0; j<numStates; j++)
+				if (i!=j)
+					sb.append(""+i+"->"+j+"\t");
+		sb.append("\n");
+	}
+	/*.................................................................................................................*/
+	public   void recalculate(){
+		totalTrees =0;
+		if (!suppress && (historyTask !=null)){ 
+			/* preliminaries .......... */
+
+			if (branchesMode && (myTree == null || !myTree.anySelected())) {
+				String s = "No changes are summarized because no branches are selected in current tree in Tree Window. Make sure only a single branch is selected, not an entire clade; use the Select Branch tool.";
+				resultString.setValue(s);
+				textWindow.setText(s);
+				return;
+			}
+
+			/*if (myTree != null && myTree instanceof MesquiteTree) DAVID: I commented this out because was already done in setTree, and hence there would have been 2 additions & thus memory leaks
+				((MesquiteTree)myTree).addListener(this);
+			 */
+
+			//		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+
+			resultString.setValue("Please wait; calculating.");
+
+			int numTrees = treeSourceTask.getNumberOfTrees(currentTaxa);
+			boolean en = !MesquiteInteger.isFinite(numTrees);
+			if (en)
+				numTrees = getNumTrees();
+			else
+				setNumTrees(numTrees);
+			if (en != numTreesItem.isEnabled()) {
+				numTreesItem.setEnabled(en);
+				MesquiteTrunk.resetMenuItemEnabling();
+			}
+
+
+			CategoricalHistory tempCharStates = null;
+
+			MesquiteTree tempTree = (MesquiteTree)treeSourceTask.getTree(currentTaxa, 0);
+			int maxnum = historyTask.getNumberOfHistories(tempTree);
+
+			if (currentChar>= maxnum)
+				currentChar = maxnum-1;
+			if (currentChar<0)
+				currentChar = 0;
+
+			StringBuffer fullDetails= new StringBuffer();
+
+
+			String modeString = "Shown for each state at each node is the number of trees on which the reconstructed state set at the node";
+			if (MesquiteInteger.isCombinable(numTrees))
+				resultString.setValue("Character " + CharacterStates.toExternal(currentChar) + "\n" + historyTask.getNameAndParameters() + " over " + numTrees + " trees (" + treeSourceTask.getName() + "; " + treeSourceTask.getParameters() + ").  " + modeString);
+			else
+				resultString.setValue("Character " + CharacterStates.toExternal(currentChar) + "\n" + historyTask.getNameAndParameters() + " over trees (" + treeSourceTask.getName() + "; " + treeSourceTask.getParameters() + ").  " + modeString);
+			totalTrees = numTrees;
+			//			IntegerArray.zeroArray(validTrees);
+			firstTreeHasAllTaxa = true;
+			boolean firstTree=true;
+
+			ProgressIndicator progIndicator = new ProgressIndicator(getProject(),getName(), "Surveying trees for character histories", numTrees, true);
+			if (progIndicator!=null){
+				progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+				progIndicator.setOfferContinueMessageString("Are you sure you want to stop the survey?");
+				progIndicator.start();
+			}
+			/* checking all trees .......... */
+			int it = 0;
+			int processedTrees=0;
+			boolean oneValidMapping = false;
+
+			CategStateChanges stateChanges=null;
+			MesquiteInteger newMaxMappings = new MesquiteInteger();
+			MesquiteInteger numMappingsSampled = new MesquiteInteger();
+			int minSampled = Integer.MAX_VALUE;
+			int maxSampled = 0;
+
+			if (!branchesMode || (myTree != null && myTree.numberSelectedInClade(myTree.getRoot())<=1)) {
+				for (it = 0; it< numTrees && tempTree != null; it++){
+					if (progIndicator != null) {
+						if (progIndicator.isAborted()) {
+							progIndicator.goAway();
+							return;
+						}
+						progIndicator.setText("Tree " + it);
+						progIndicator.setCurrentValue(it);
+					}
+					if (MesquiteInteger.isCombinable(numTrees))
+						CommandRecord.tick("Examining ancestral state reconstruction on tree " + it + " of " + numTrees);
+					else 
+						CommandRecord.tick("Examining ancestral state reconstruction on tree " + it);
+					historyTask.prepareForMappings(true);
+					historyTask.prepareHistory(tempTree, currentChar);
+
+					CharacterHistory ch = historyTask.getMapping(0, tempCharStates, null);
+					if (!(ch instanceof CategoricalHistory)){
+						discreetAlert("To summarize changes, they must be of categorical characters.  Continuous and meristic characters cannot be summarized.  We don't know how you managed to get to this point, but the calculation will fail.");
+						resultString.setValue("Calculation not done; character type incompatible");
+						return;
+					}
+					tempCharStates = (CategoricalHistory)ch;
+					if (tempCharStates!=null) {
+						oneValidMapping = true;
+						if (stateChanges==null) {
+							stateChanges = new CategStateChanges(tempCharStates.getMaxState()+1, maxChangesRecorded+1);
+							if (saveDetails())
+								addFullDetailsHeader(tempCharStates.getMaxState()+1,fullDetails);
+						}
+						setMaxState(tempCharStates.getMaxState(), stateChanges);
+						setAcceptableChanges(stateChanges);
+
+						boolean processTree = true;
+						int node = tempTree.getRoot();
+						if (branchesMode && myTree.numberSelectedInClade(myTree.getRoot())==1) {
+							node = myTree.getFirstSelected(myTree.getRoot());
+							Bits terminals = myTree.getTerminalTaxaAsBits(node);
+							processTree = tempTree.isClade(terminals);
+							if (processTree)
+								node = tempTree.mrca(terminals);
+						}
+
+						if (processTree){
+							processedTrees++;
+							stateChanges.addOneHistory(tempTree, historyTask, currentChar,node, numMappingsSampled, maxNumMappings, newMaxMappings, queryLimits, fullDetails, ""+(it+1));
+							if (newMaxMappings.isCombinable()) {
+								maxNumMappings=newMaxMappings.getValue();
+								queryLimits = false;
+								storePreferences();
+							}
+							if (numMappingsSampled.isCombinable()) {
+								if (numMappingsSampled.getValue()<minSampled)
+									minSampled = numMappingsSampled.getValue();
+								if (numMappingsSampled.getValue()>maxSampled)
+									maxSampled = numMappingsSampled.getValue();
+							}
+
+
+						} 
+					}
+					if (it+1<numTrees)
+						tempTree = (MesquiteTree)treeSourceTask.getTree(currentTaxa, it+1);
+					if (saveDetails())
+						fullDetails.append("\n");
+
+				}
+			}
+
+			logln(" " + processedTrees + " trees processed.");
+
+			totalTrees = it;
+			if (progIndicator!=null) 
+				progIndicator.goAway();
+
+			if (stateChanges!=null && processedTrees>0) {
+				stateChanges.cleanUp();
+				currentText = stateChanges.toVerboseString(); 
+				String leadText;
+				leadText = "\nSummarizing changes over trees in character " + (currentChar+1);
+				if (branchesMode){
+					leadText += " in the clade whose ancestor is selected in the tree in Tree Window.  Trees are considered only if they also have this " +
+							"clade, and changes are counted only within the clade.";
+				}
+				leadText += "\nSource of Trees: " + treeSourceTask.getName() + "\n";
+				leadText += "Further details about Source of Trees: " + treeSourceTask.getParameters() + "\n";
+				leadText += "Number of Trees: " + processedTrees + "\n";
+				if (minSampled==maxSampled)
+					leadText += "Number of mappings sampled per tree: " + minSampled +"\n";
+				else
+					leadText += "Number of mappings sampled per tree: " + minSampled + "-"+maxSampled+"\n";
+				currentText = leadText+"\n"+ currentText;
+				textWindow.setText(currentText);
+				if (saveDetails())
+					MesquiteFile.putFileContentsQuery("Save file with full details", fullDetails.toString(), true);
+			}
+			else
+				if (processedTrees<=0) {
+					if (!oneValidMapping)
+						textWindow.setText("Sorry, changes not calculated; character mappings could not be sampled for any of the trees examined.");
+					else if (branchesMode)
+						textWindow.setText("Sorry, changes not calculated; none of the trees examined have the selected branch.");
+					else
+						textWindow.setText("Sorry, changes not calculated.  No trees were processed.");
+				}
+				else if (branchesMode)
+					textWindow.setText("Sorry, changes not calculated. Make sure only a single branch is selected, not an entire clade.  Use the arrow tool, and touch on the branch.");
+				else
+					textWindow.setText("Sorry, changes not calculated.");
+
+
+		}
+	}
+	TreeReference myTreeRef = null;
+	/*.................................................................................................................*/
+	//	this is called if used by tree window assistant to show changes on branches
+	public   void setTree(Tree tree){
+		if (tree == null)
+			return;
+		currentTaxa = tree.getTaxa();
+		setup();
+		this.poppedOut = true;
+		branchesMode = true;
+		if (!MesquiteThread.isScripting() && textWindow == null) {
+			textWindow= new MesquiteTextWindow( this, "State Changes on Branches", true, true, false);
+			setModuleWindow(textWindow);
+			textWindow.setPopAsTile(true);
+			if (poppedOut)
+				textWindow.popOut(true);
+			else textWindow.setVisible(true);
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+		if (textWindow != null)
+			textWindow.setTitle("State Changes on Branches");
+
+		if (tree != null && myTreeRef != null && tree instanceof MesquiteTree && ((MesquiteTree)tree).sameTreeVersions(myTreeRef, true, false) && !MesquiteThread.isScripting()) {
+			myTreeRef = ((MesquiteTree)tree).getTreeReference(myTreeRef);
+			return;
+		}
+		if (myTree!=null && myTree instanceof MesquiteTree) {
+			((MesquiteTree)tree).removeListener(this);
+		}
+		myTree = tree;
+		if (tree==null)
+			return;
+		if (tree instanceof MesquiteTree) {
+			myTreeRef = ((MesquiteTree)tree).getTreeReference(myTreeRef);
+			((MesquiteTree)tree).addListener(this);
+		}
+
+		currentTaxa = tree.getTaxa();
+		int numTrees = treeSourceTask.getNumberOfTrees(currentTaxa);
+		boolean en = !MesquiteInteger.isFinite(numTrees); 
+		if (!en)
+			setNumTrees(numTrees);
+		if (en != numTreesItem.isEnabled()) {
+			numTreesItem.setEnabled(en);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+		recalculate();
+	}
+	private int cladeInTree(Tree tree, int node,  int[] target){
+		if (target == null)
+			return -1;
+		if (target.length == 1) {
+			if (tree.nodeIsTerminal(node) && target[0] == tree.taxonNumberOfNode(node))
+				return node;
+			else 
+				return -1;
+		}
+
+		if (tree.nodeIsInternal(node)){
+			int[] taxaHere = tree.getTerminalTaxa(node);
+			if (IntegerArray.arraysSame(taxaHere, target))
+				return node;	
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				int t = (cladeInTree(tree, daughter, target));
+				if (t>0)
+					return t;
+			}
+		}
+		return -1;
+	}
+}
+
diff --git a/Source/mesquite/ancstates/SummarizeChgOnBranches/SummarizeChgOnBranches.java b/Source/mesquite/ancstates/SummarizeChgOnBranches/SummarizeChgOnBranches.java
new file mode 100644
index 0000000..cfddac6
--- /dev/null
+++ b/Source/mesquite/ancstates/SummarizeChgOnBranches/SummarizeChgOnBranches.java
@@ -0,0 +1,101 @@
+package mesquite.ancstates.SummarizeChgOnBranches;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.ancstates.lib.*;
+
+
+/* 
+ * 
+ * doesn't listen properly to changes
+ * 
+ * */
+
+/*======================================================================== */
+public class SummarizeChgOnBranches extends TreeWindowAssistantOA {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(ChgSummarizerMultTrees.class, getName() + " needs a calculator.",
+		"This is chosen automatically");
+	}
+	ChgSummarizerMultTrees summarizerTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		summarizerTask = (ChgSummarizerMultTrees)hireNamedEmployee(ChgSummarizerMultTrees.class,"#SummarizeChanges");
+
+		if (summarizerTask == null) {
+			return sorry(getName() + " couldn't start because no summarizer was obtained.");
+		}
+		summarizerTask.setSensitiveToBranchSelection(true);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getSummarizer ",summarizerTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the summarizer", null, commandName, "getSummarizer")) {
+			return summarizerTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Summarize Changes In Selected Clade Over Trees";  //Name changed Sept 2011
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Summarizes reconstructions of state changes of a character on descendants of selected branch, over a series of trees.  The branches defined are those that are the descendants of the single branch selected on the tree in the tree window.";
+	}
+	/*.................................................................................................................*/
+//	this is called if used by tree window assistant to show changes on branches
+	public   void setTree(Tree tree){
+		summarizerTask.setTree(tree);
+	}
+}
+
diff --git a/Source/mesquite/ancstates/SummarizeChgOverTrees/SummarizeChgOverTrees.java b/Source/mesquite/ancstates/SummarizeChgOverTrees/SummarizeChgOverTrees.java
new file mode 100644
index 0000000..b5b1eff
--- /dev/null
+++ b/Source/mesquite/ancstates/SummarizeChgOverTrees/SummarizeChgOverTrees.java
@@ -0,0 +1,105 @@
+package mesquite.ancstates.SummarizeChgOverTrees;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.ancstates.lib.*;
+
+
+/* 
+ * 
+ * doesn't listen properly to changes
+ * 
+ * */
+
+/*======================================================================== */
+public class SummarizeChgOverTrees extends FileAssistantA {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(ChgSummarizerMultTrees.class, getName() + " needs a calculator.",
+		"This is chosen automatically");
+	}
+	ChgSummarizerMultTrees summarizerTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		summarizerTask = (ChgSummarizerMultTrees)hireNamedEmployee(ChgSummarizerMultTrees.class,"#SummarizeChanges");
+
+		if (summarizerTask == null) {
+			return sorry(getName() + " couldn't start because no summarizer was obtained.");
+		}
+		summarizerTask.setSensitiveToBranchSelection(false);
+		Taxa taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to summarize changes over trees?");
+		if (taxa == null)
+			return false;
+		summarizerTask.setup(taxa, false);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getSummarizer ",summarizerTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the summarizer", null, commandName, "getSummarizer")) {
+			return summarizerTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Summarize State Changes Over Trees";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Summarizes reconstructions of state changes of a character over a series of trees.";
+	}
+	/*.................................................................................................................*/
+//	this is called if used by tree window assistant to show changes on branches
+	public   void setTree(Tree tree){
+		summarizerTask.setTree(tree);
+	}
+}
+
diff --git a/Source/mesquite/ancstates/TraceAllCharacters/TraceAllCharacters.java b/Source/mesquite/ancstates/TraceAllCharacters/TraceAllCharacters.java
new file mode 100644
index 0000000..b46ec80
--- /dev/null
+++ b/Source/mesquite/ancstates/TraceAllCharacters/TraceAllCharacters.java
@@ -0,0 +1,507 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.TraceAllCharacters;
+/*~~  */
+
+import java.applet.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/*======================================================================== */
+public class TraceAllCharacters extends TreeDisplayAssistantA {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharStatesForNodes.class, getName() + " needs a source of reconstructed ancestral states.",
+		"The reconstruction method is chosen initially or using the Reconstruction Method submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(MatrixSourceCoord.class, getName() + " needs a source of matrices whose ancestral states will be reconstructed",
+		"The source of characters is chosen initially or in the Source of Character Matrices submenu");
+	}
+	CharsStatesForNodes allCharsTask;
+	//DisplayCharsStsAtNodes displayTask;
+	MatrixSourceCoord characterSourceTask;
+	Vector traces;
+	//MesquiteString displayTaskName;
+	MesquiteCommand dtC;
+	MesquiteBoolean byCharacters, selectedOnly, selectedCharactersOnly, showTerminals;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		traces = new Vector();
+		byCharacters = new MesquiteBoolean(true);
+		selectedOnly = new MesquiteBoolean(true);
+		selectedCharactersOnly = new MesquiteBoolean(false);
+		showTerminals = new MesquiteBoolean(false);
+ 		makeMenu("Trace_All");
+ 		characterSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class,"Source of characters (for Trace All Characters)");
+ 		suppressed = MesquiteThread.isScripting();
+ 		if (characterSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+ 		}
+ 		allCharsTask = (CharsStatesForNodes)hireEmployee(CharsStatesForNodes.class, "Reconstruction method");
+ 		if ( allCharsTask == null ) {
+ 			return sorry(getName() + " couldn't start because no character reconstructor was obtained.");
+ 		}
+ 		/*
+ 		displayTask = (DisplayCharsStsAtNodes)hireEmployee(DisplayCharsStsAtNodes.class, "Displayer of ancestral states");
+ 		if (displayTask == null) {
+ 			return sorry(getName() + " couldn't start because now display module was obtained.");
+ 		}
+ 		dtC = makeCommand("setDisplayMode",  this);
+ 		displayTask.setHiringCommand(dtC);
+ 		displayTaskName = new MesquiteString(displayTask.getName());
+		if (numModulesAvailable(DisplayCharsStsAtNodes.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Trace All display mode...", dtC, DisplayCharsStsAtNodes.class);
+ 			mss.setSelected(displayTaskName);
+		}
+ 		*/
+		addCheckMenuItem(null, "Show Selected Nodes Only", makeCommand("toggleSelectedOnly", this), selectedOnly);
+		addCheckMenuItem(null, "Show Selected Characters Only", makeCommand("toggleSelectedCharsOnly", this), selectedCharactersOnly);
+		addCheckMenuItem(null, "Show Terminal Nodes", makeCommand("toggleShowTerminals", this), showTerminals);
+		addCheckMenuItem(null, "Rows are Characters", makeCommand("toggleByCharacters", this), byCharacters);
+		addMenuItem( "Close Trace All", makeCommand("closeTrace",  this));
+		addMenuItem( "-", null);
+ 		resetContainingMenuBar();
+		return true;
+ 	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == allCharsTask || employee == characterSourceTask)  
+ 			iQuit();
+ 		if (employee instanceof TextDisplayer){
+ 			for (int i = 0; i<traces.size(); i++){
+ 				TraceAllOperator tao = (TraceAllOperator)traces.elementAt(i);
+ 				if (tao.displayer == employee){
+ 					tao.turnOff();
+ 					traces.removeElement(tao);
+ 				}
+ 			}
+ 			if (traces.size() == 0)
+ 				iQuit();
+ 		}
+	}
+ 	MesquiteWindow window;
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		TextDisplayer displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+		if (displayer!=null) {
+			displayer.setWrap(false);
+			displayer.setPoppedOut(1);
+			displayer.showText("Trace All Characters", "Trace All Characters", true);
+			window = displayer.getModuleWindow();
+		}
+		TraceAllOperator newTrace = new TraceAllOperator(this, treeDisplay, displayer);
+		traces.addElement(newTrace);
+		return newTrace;
+	}
+  	 
+   
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("toggleByCharacters " + byCharacters.toOffOnString());
+  	 	temp.addLine("toggleSelectedOnly " + selectedOnly.toOffOnString());
+  	 	temp.addLine("toggleSelectedCharsOnly " + selectedCharactersOnly.toOffOnString());
+  	 	temp.addLine("toggleShowTerminals " + showTerminals.toOffOnString());
+   	 	temp.addLine("getCharSource", characterSourceTask);
+  	 	temp.addLine("getReconstructor", allCharsTask);
+ 	 	temp.addLine("desuppress");
+   	 	//temp.addLine("setDisplayMode ",displayTask);
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	/*
+    	 	if (checker.compare(this.getClass(), "Sets module used to display reconstructed states", "[name of module]", commandName, "setDisplayMode")) {
+    	 		DisplayCharsStsAtNodes temp=  (DisplayCharsStsAtNodes)replaceEmployee(DisplayCharsStsAtNodes.class, arguments, "Display mode", displayTask);
+ 			if (temp != null) {
+ 				displayTask= temp;
+		 		displayTask.setHiringCommand(dtC);
+ 				displayTaskName.setValue(displayTask.getName());
+				resetAllTraceOperators();
+ 				parametersChanged();
+ 				return displayTask;
+ 			}
+    	 	}
+    	 	*/
+    	 	if (checker.compare(this.getClass(), "Undoes suppression of calculations when scripting", null, commandName, "desuppress")) {
+    	 		suppressed = false;
+ 			recalcAllTraceOperators();
+			resetAllTraceOperators();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether to show states only for selected nodes", "[on or off]", commandName, "toggleSelectedOnly")) {
+    	 		selectedOnly.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting())
+				resetAllTraceOperators();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether to show states only for selected characters", "[on or off]", commandName, "toggleSelectedCharsOnly")) {
+    	 		selectedCharactersOnly.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting())
+				resetAllTraceOperators();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether to show states for terminal nodes", "[on or off]", commandName, "toggleShowTerminals")) {
+    	 		showTerminals.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting())
+				resetAllTraceOperators();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether to show states with rows = nodes and columns = characters, or the reverse", "[on or off]", commandName, "toggleByCharacters")) {
+    	 		byCharacters.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting())
+				resetAllTraceOperators();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns source of chars", null, commandName, "getCharSource")) {
+   	 		return characterSourceTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns reconstructor", null, commandName, "getReconstructor")) {
+   	 		return allCharsTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Turns off Trace All Characters", null, commandName, "closeTrace")) {
+    	 		iQuit();
+			resetContainingMenuBar();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (!suppressed){
+ 			recalcAllTraceOperators();
+			parametersChanged();
+		}
+	}
+	
+	void recalcAllTraceOperators(){
+		if (suppressed)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceAllOperator) {
+				TraceAllOperator tCO = (TraceAllOperator)obj;
+	 			tCO.recalculate();
+	 		}
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void resetAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceAllOperator) {
+				TraceAllOperator tCO = (TraceAllOperator)obj;
+	 			tCO.refresh();
+	 		}
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void closeAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceAllOperator) {
+				TraceAllOperator tCO = (TraceAllOperator)obj;
+	 			tCO.turnOff();
+	 		}
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void endJob() {
+ 		if (window != null){
+ 			window.hide();
+ 		window.dispose();
+ 		}
+   	 	closeAllTraceOperators();
+		super.endJob();
+ 	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Trace All Characters";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getVersion() {
+		return null;
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		if (characterSourceTask == null || allCharsTask== null)
+ 			return "";
+		return "Ancestral States:\n" + allCharsTask.getNameAndParameters() + "\nusing:\n" + characterSourceTask.getNameAndParameters();
+   	 }
+/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Summarizes for each node the reconstructions of the states at all characters of the tree.";
+   	 }
+}
+
+/*======================================================================== */
+class TraceAllOperator extends TreeDisplayDrawnExtra implements MesquiteListener {
+	Tree myTree;
+	TraceAllCharacters traceAllModule;
+	MCharactersHistory charsStates;
+	MCharactersDistribution matrix;
+	CharacterData oldData;
+	TextDisplayer displayer;
+	boolean turnedOff = false;
+	public TraceAllOperator (TraceAllCharacters ownerModule, TreeDisplay treeDisplay, TextDisplayer displayer) {
+		super(ownerModule, treeDisplay);
+		traceAllModule = ownerModule;
+		this.displayer = displayer;
+	}
+	/*.................................................................................................................*/
+	public   void recalculate(){
+		
+		if (turnedOff)
+			return;
+		if (traceAllModule.allCharsTask!=null) {
+			//note: following doesn't pass MesquiteString for results since does character by character and would only get message from last
+ 			charsStates = traceAllModule.allCharsTask.calculateStates(myTree, matrix = traceAllModule.characterSourceTask.getCurrentMatrix(myTree), charsStates, null);
+			int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+			if (!myTree.nodeExists(drawnRoot))
+				drawnRoot = myTree.getRoot();
+			refresh();
+ 		}
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree){
+		myTree = tree;
+		if (turnedOff)
+			return;
+ 		if (traceAllModule.allCharsTask!=null) {
+			charsStates = traceAllModule.allCharsTask.calculateStates(tree, matrix = traceAllModule.characterSourceTask.getCurrentMatrix(tree), charsStates, null);
+			refresh();
+ 		}
+	}
+	
+	public void refresh(){
+		if (turnedOff)
+			return;
+		if (displayer!=null)
+			displayer.showText(composeText(myTree, charsStates), "Trace All Characters", true);
+	}
+	
+	public String composeText(Tree tree, MCharactersHistory charStates){
+		if (traceAllModule == null || tree == null || charStates == null)
+			return null;
+		if (turnedOff)
+			return null;
+		StringBuffer sb = new StringBuffer(100);
+		StringBuffer sb2 = new StringBuffer(100);
+		MesquiteBoolean anyAdded = new MesquiteBoolean(false);
+		CharacterData data = null;
+		if (matrix !=null)
+			data = matrix.getParentData();
+		if (oldData !=null && data !=null && data !=oldData)
+			oldData.removeListener(this);
+		if (data !=null && data !=oldData)
+			data.addListener(this);
+		oldData = data;
+		CharInclusionSet incl = null;
+		
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		
+		sb.append("Trace All Characters\n\n");
+		if (traceAllModule.allCharsTask!=null) {
+			sb.append(traceAllModule.getParameters());
+			sb.append("\n======================================\n");
+		}
+		sb.append("Ancestral states are listed by character and by node on the tree.  Node numbers are shown in red on the tree drawing.\n\n");
+		int drawnRoot = 0;
+		if (treeDisplay != null && treeDisplay.getTreeDrawing() != null)
+			drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		if (incl !=null && incl.numberSelected()==0){
+			sb.append("All characters are excluded.  You change the inclusion/exclusion of characters using the first column of the List of Characters window.");
+		}
+		/*else if (traceAllModule.selectedOnly.getValue() && !tree.anySelected()) {
+			sb.append("No nodes are selected.  To show the results of Trace All Characters, either turn off the menu item \"Show Selected Nodes Only\", or select some branches of the tree.");
+			
+		}*/
+		else if (data !=null && traceAllModule.selectedCharactersOnly.getValue() && !data.anySelected()) {
+			sb.append("No characters are selected.  To show the results of Trace All Characters, either turn off the menu item \"Show Selected Characters Only\", or select some characters of the matrix.");
+			
+		}
+		else if (traceAllModule.byCharacters.getValue()){
+			if (incl !=null && data !=null && (incl.numberSelected()< data.getNumChars()))
+				sb.append(Integer.toString(incl.numberSelected()) + " of " + data.getNumChars() + " characters included.\n\n");
+			sb.append("Char.\\Node");
+			boolean ignoreSelection = !traceAllModule.selectedOnly.getValue() || !tree.anySelected();
+			composeOneCharRec(tree, drawnRoot, null, sb, null, ignoreSelection);
+			sb.append('\n');
+			for (int ic=0; ic<charStates.getNumChars(); ic++) {
+				if ((!traceAllModule.selectedCharactersOnly.getValue() || data == null || data.getSelected(ic)) && (incl == null || incl.isBitOn(ic))){
+					CharacterHistory cH = charStates.getCharacterHistory(ic);
+					anyAdded.setValue(false);
+					sb2.setLength(0);
+					composeOneCharRec(tree, drawnRoot, cH, sb2, anyAdded, ignoreSelection);
+					if (anyAdded.getValue()){
+						sb.append("character ");
+						sb.append(Integer.toString(ic+1));
+						sb.append(sb2.toString());
+						sb.append('\n');
+					}
+				}
+			}
+		}
+		else {
+			if (incl !=null && data !=null && (incl.numberSelected()< data.getNumChars()))
+				sb.append(Integer.toString(incl.numberSelected()) + " of " + data.getNumChars() + " characters included.\n\n");
+			sb.append("Node\\Char.");
+			for (int ic=0; ic<charStates.getNumChars(); ic++) {
+				if ((!traceAllModule.selectedCharactersOnly.getValue() || data == null || data.getSelected(ic)) && (incl == null || incl.isBitOn(ic))){
+					sb.append('\t');
+					sb.append(Integer.toString(ic+1));
+				}
+			}
+			sb.append('\n');
+			boolean ignoreSelection = !traceAllModule.selectedOnly.getValue() || !tree.anySelected();
+			composeRecByNodes(tree, drawnRoot, charStates, data, incl, sb, ignoreSelection);
+		}
+		
+		/*====experimental
+		sb.append("\nTaxa compared to immediate ancestor\n");
+		for (int it = 0; it < tree.getTaxa().getNumTaxa(); it++){
+			int taxon = tree.nodeOfTaxonNumber(it);
+			if (taxon > 0){
+				int anc = tree.motherOfNode(taxon);
+				if (anc >0){
+					int differences = 0;
+					CharacterState csTaxon = null;
+					CharacterState csAnc = null;
+					for (int ic = 0; ic < charStates.getNumChars(); ic++){
+						csTaxon = charStates.getCharacterState(csTaxon, ic, taxon);
+						csAnc = charStates.getCharacterState(csAnc, ic, anc);
+						if (!csAnc.equals(csTaxon))
+						//if (!csAnc.equals(csTaxon, true, true, true))
+							differences++;
+					}
+					if (differences == 0)
+						tree.getTaxa().setSelected(it, true);
+					sb.append(tree.getTaxa().getTaxonName(it) + " with " + differences + " differences compared to immediate ancestor\n");
+					
+				}
+			}
+		}
+		*/
+		return sb.toString();
+		
+	} 
+	private String nodeName(Tree tree, int node, boolean verbose){
+		if (tree.nodeIsInternal(node)) {
+			if (verbose)
+				return ("node " + node);
+			else
+				return Integer.toString(node);
+		}
+		return tree.getTaxa().getName(tree.taxonNumberOfNode(node));
+		
+	}
+	
+	/*.................................................................................................................*/
+	public   void composeOneCharRec(Tree tree, int node, CharacterHistory states, StringBuffer sb, MesquiteBoolean anyAdded, boolean ignoreSelection) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				composeOneCharRec(tree, d, states, sb, anyAdded, ignoreSelection);
+		if ((ignoreSelection || ((MesquiteTree)tree).getSelected(node)) && (traceAllModule.showTerminals.getValue() || tree.nodeIsInternal(node))){
+			sb.append('\t');
+			if (states != null){
+				String s = states.toString(node, "; ");
+				if (!StringUtil.blank(s)) {
+					sb.append(s);
+					if (anyAdded!=null)
+						anyAdded.setValue(true);
+				}
+			}
+			else
+				sb.append(nodeName(tree, node, false));
+		}
+	}
+	/*.................................................................................................................*/
+	public   void composeRecByNodes(Tree tree, int node, MCharactersHistory states, CharacterData data, CharInclusionSet incl, StringBuffer sb, boolean ignoreSelection) {
+		if (states == null)
+			return;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				composeRecByNodes(tree, d, states, data, incl, sb, ignoreSelection);
+		if ((ignoreSelection || ((MesquiteTree)tree).getSelected(node)) && (traceAllModule.showTerminals.getValue() || tree.nodeIsInternal(node))){
+			sb.append(nodeName(tree, node, true) + ": ");
+			for (int ic=0; ic<states.getNumChars(); ic++) {
+				if ((!traceAllModule.selectedCharactersOnly.getValue() || data == null || data.getSelected(ic)) && (incl == null || incl.isBitOn(ic))){
+					sb.append('\t');
+					CharacterHistory cH = states.getCharacterHistory(ic);
+					sb.append(cH.toString(node, "; "));
+				}
+			}
+			sb.append('\n');
+		}
+	}
+	/*.................................................................................................................*/
+	private   void drawNumber(Tree tree, Graphics g, int N) {
+		if (tree.nodeExists(N)) {
+			if (tree.nodeIsInternal(N))
+				StringUtil.highlightString(g, Integer.toString(N), treeDisplay.getTreeDrawing().x[N]+8, treeDisplay.getTreeDrawing().y[N]+8, Color.red, Color.white);
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawNumber(tree, g, d);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawNumber(tree, g, drawnRoot);
+	}
+	/*.................................................................................................................*/
+	CharacterState cs = null;
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (charsStates!=null) {
+			return "(" + node + ")";
+		}
+		return "";
+	}
+	
+	/**return any additional explanatory text, e.g. if there is extensive information too verbose for a legend but which should be output to text view*/
+	public String additionalText(Tree tree, int node){
+		return "";
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+	
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == oldData && (code == MesquiteListener.SELECTION_CHANGED || code == MesquiteListener.NAMES_CHANGED)){
+			refresh();
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){return true;}
+	
+	public void turnOff(){
+		turnedOff = true;
+		if (oldData !=null)
+			oldData.removeListener(this);
+		super.turnOff();
+	}
+}
+
diff --git a/Source/mesquite/ancstates/TraceCharOverTrees/TraceCharOverTrees.java b/Source/mesquite/ancstates/TraceCharOverTrees/TraceCharOverTrees.java
new file mode 100644
index 0000000..8a397c3
--- /dev/null
+++ b/Source/mesquite/ancstates/TraceCharOverTrees/TraceCharOverTrees.java
@@ -0,0 +1,1492 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.TraceCharOverTrees;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+//TODO: ideally have it check to see if reconstructor generates frequencies before it lets user switch to average frequencies
+
+/*======================================================================== */
+public class TraceCharOverTrees extends TreeDisplayAssistantA implements TraceModule{
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharHistorySource.class, getName() + " needs a source of character histories.",
+		"The source of a traced history can be chosen using the Character History Source submenu");
+	}
+	DisplayStatesAtNodes displayTask;
+	Vector traces;
+	MesquiteString displayTaskName;
+	MesquiteCommand dtC;
+	CharHistorySource historyTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand cstC;
+	TreeSource treeSourceTask;
+	MesquiteMenuItemSpec numTreesItem = null;
+	MesquiteMenuItemSpec showEquivocalItem = null;
+	private int numTrees = 100;
+	//not yet ready double minPercent = 0.0;
+	public MesquiteBoolean showLegend;
+	private MesquiteBoolean showNodeAbsentSlice = new MesquiteBoolean(true);
+	private MesquiteBoolean showEquivocalSlice = new MesquiteBoolean(true);   
+
+	int mode = TraceCOTOperator.UNIQUELY_BEST;
+	int previousMode = TraceCOTOperator.UNIQUELY_BEST;
+
+	StringArray modes;
+	MesquiteString modeName;
+
+	private boolean numTreesSet = false;
+	boolean suppress = false;
+	int currentChar=0;
+	int initialOffsetX=MesquiteInteger.unassigned;
+	int initialOffsetY= MesquiteInteger.unassigned;
+	MesquiteCommand htC;
+	MesquiteString historyTaskName;
+	Taxa currentTaxa;
+	int initialLegendWidth=MesquiteInteger.unassigned;
+	int initialLegendHeight= MesquiteInteger.unassigned;
+	int nodeToOutput=MesquiteInteger.unassigned;
+	String nodeInfo = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showLegend = new MesquiteBoolean(true);
+		if (MesquiteThread.isScripting())
+			suppress = true;
+		traces = new Vector();
+
+		historyTask = (CharHistorySource)hireCompatibleEmployee(CharHistorySource.class, CategoricalState.class,"Source of character history (for Trace Character Over Trees)");
+
+		if (historyTask == null) {
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		}
+		makeMenu("Trace_Over_Trees");
+		historyTaskName  = new MesquiteString(historyTask.getName());
+		htC = makeCommand("setHistorySource",  this);
+		if (numModulesAvailable(CharHistorySource.class)>1) {
+			historyTask.setHiringCommand(htC);
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character History Source", htC, CharHistorySource.class);
+			mss.setSelected(historyTaskName);
+		}
+		MesquiteMenuItemSpec mm = addMenuItem( "Next Character History", makeCommand("nextCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_RIGHT); //right
+		mm = addMenuItem( "Previous Character History", makeCommand("previousCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_LEFT); //right
+		addMenuItem( "Choose Character History...", makeCommand("chooseCharacter",  this));
+
+		modes = new StringArray(3);
+		modes.setValue(TraceCOTOperator.UNIQUELY_BEST, "Count Trees with Uniquely Best States");
+		modes.setValue(TraceCOTOperator.COUNT_EQUIVOCAL, "Count All Trees with State");
+		modes.setValue(TraceCOTOperator.AVERAGE_FREQUENCIES, "Average Frequencies Across Trees");
+		modeName = new MesquiteString(modes.getValue(mode));
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Calculate", makeCommand("setMode",  this), modes);
+		mss.setSelected(modeName);
+
+		addCheckMenuItem(null, "Show Legend", makeCommand("toggleShowLegend",  this), showLegend);
+		addCheckMenuItem(null, "Show Fraction of Trees with Node Absent", makeCommand("toggleShowNodeAbsent",  this), showNodeAbsentSlice);
+		showEquivocalItem = addCheckMenuItem(null, "Show Fraction of Trees with Equivocal", makeCommand("toggleShowEquivocal",  this), showEquivocalSlice);
+		showEquivocalItem.setEnabled(mode == TraceCOTOperator.UNIQUELY_BEST);
+
+		addMenuItem( "Save Values for a Node...", makeCommand("saveNodeValues",  this));
+
+		displayTask = (DisplayStatesAtNodes)hireEmployee(DisplayStatesAtNodes.class, "Displayer of ancestral states");
+		if (displayTask == null) {
+			return sorry(getName() + " couldn't start because now display module was obtained.");
+		}
+		dtC = makeCommand("setDisplayMode",  this);
+		displayTask.setHiringCommand(dtC);
+		displayTaskName = new MesquiteString(displayTask.getName());
+		if (numModulesAvailable(DisplayStatesAtNodes.class)>1){
+			MesquiteSubmenuSpec mss2 = addSubmenu(null, "Trace Over Trees Display Mode", dtC, DisplayStatesAtNodes.class);
+			mss2.setSelected(displayTaskName);
+		}
+
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class,  "Source of trees for comparison by for Trace Character Over Trees");
+		if (treeSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		}
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+
+
+		cstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(TreeSource.class)>1){ 
+			MesquiteSubmenuSpec mss3 = addSubmenu(null, "Tree source",cstC, TreeSource.class);
+			mss3.setSelected(treeSourceName);
+		}
+		numTreesItem = addMenuItem("Number of Trees...", makeCommand("setNumTrees", this));
+		numTreesItem.setEnabled(false);
+		addMenuItem( "Close Trace Over Trees", makeCommand("closeTrace",  this));
+		addMenuItem( "-", null);
+		resetContainingMenuBar();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == displayTask || employee == historyTask)  
+			iQuit();
+	}
+	public int getInitialOffsetX(){
+		return initialOffsetX;
+	}
+	public int getInitialOffsetY(){
+		return initialOffsetY;
+	}
+	public boolean showLegend(){
+		return showLegend.getValue();
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		TraceCOTOperator newTrace = new TraceCOTOperator(this, treeDisplay);
+		traces.addElement(newTrace);
+		Tree tree = treeDisplay.getTree();
+		if (tree !=null){
+			currentTaxa = tree.getTaxa();
+			int numTrees2 = treeSourceTask.getNumberOfTrees(currentTaxa);
+			numTreesItem.setEnabled(!MesquiteInteger.isFinite(numTrees2));
+			showEquivocalItem.setEnabled(mode == TraceCOTOperator.UNIQUELY_BEST);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+		return newTrace;
+	}
+
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress ");
+		temp.addLine("setHistorySource ",historyTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		temp.addLine( "setTreeSource " , treeSourceTask);
+		temp.addLine("setNumTrees " + numTrees);
+		temp.addLine("setDisplayMode ",displayTask);
+		temp.addLine("toggleShowLegend " + showLegend.toOffOnString());
+		temp.addLine("toggleShowNodeAbsent " + showNodeAbsentSlice.toOffOnString());
+		temp.addLine("toggleShowEquivocal " + showEquivocalSlice.toOffOnString());
+		temp.addLine("setMode " + ParseUtil.tokenize(modes.getValue(mode)));
+		//temp.addLine("setMinPercent " + minPercent);
+		TraceCOTOperator tco = (TraceCOTOperator)traces.elementAt(0);
+		if (tco!=null && tco.traceLegend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.traceLegend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.traceLegend.getOffsetY());
+			temp.addLine("setLegendWidth " + tco.traceLegend.getLegendWidth()); //Should go operator by operator!!!
+			temp.addLine("setLegendHeight " + tco.traceLegend.getLegendHeight());
+		}
+		temp.addLine("desuppress ");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	private boolean querySaveNodeValues() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Save Values for Node",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Save Values for Node");
+		String helpString = "This will let you save the values for a node for each tree to a text file.  You will need to enter the node number.  "
+			+"To see node numbers, you can choose \"Show Node Numbers\" from the Display menu in the Tree window.";
+
+		dialog.appendToHelpString(helpString);
+
+
+		IntegerField nodeField = dialog.addIntegerField("Node Number:", nodeToOutput, 20);
+		dialog.addHorizontalLine(1);
+
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			nodeToOutput = nodeField.getValue();
+
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void setToMode(int newMode) {
+		previousMode = mode;
+		mode = newMode;
+		modeName.setValue(modes.getValue(mode));
+		toggleModeAllTraceOperators();
+		parametersChanged();
+		showEquivocalItem.setEnabled(mode == TraceCOTOperator.UNIQUELY_BEST);
+		MesquiteTrunk.resetMenuItemEnabling();
+	}
+	/*.................................................................................................................*/
+	public void setToPreviousMode() {
+		setToMode(previousMode);
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		/* not yet ready
+    	 	if (checker.compare(this.getClass(), "Sets the minimum percent of occurances of a node for its states to be shown", "[minimum percent]", commandName, "setMinPercent")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		double T = MesquiteDouble.fromString(arguments, pos);
+    	 		if (!MesquiteDouble.isCombinable(T))
+				T = MesquiteDouble.queryDouble(containerOfModule(), "Minimum Percent Occurance", "Minimum percent of occurances of a node for its states to be shown.  If you set this to 10% and the node is present in only 9% of the trees, then its reconstructed states will not be summarized.", minPercent, 0, 100);
+    	 		if (!MesquiteDouble.isCombinable(T))
+    	 			return null;
+	    	 	if (minPercent != T) {
+	    	 		minPercent = T;
+ 				if (!MesquiteThread.isScripting())
+ 					redrawAllTraceOperators();
+ 			}
+    	 	}
+    	 	else 
+		 */
+		if (checker.compare(this.getClass(), "Sets module used to display reconstructed states", "[name of module]", commandName, "setDisplayMode")) {
+			DisplayStatesAtNodes temp=  (DisplayStatesAtNodes)replaceEmployee(DisplayStatesAtNodes.class, arguments, "Display mode", displayTask);
+			if (temp != null) {
+				displayTask= temp;
+				displayTask.setHiringCommand(dtC);
+				displayTaskName.setValue(displayTask.getName());
+				if (!suppress)
+					parametersChanged();
+				resetAllTraceOperators();
+				return displayTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character history", null, commandName, "nextCharacter")) {
+			if (currentChar>=historyTask.getNumberOfHistories(currentTaxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			recalcAllTraceOperators();
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character history", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=historyTask.getNumberOfHistories(currentTaxa)-1;
+			else
+				currentChar--;
+			recalcAllTraceOperators();
+		}
+
+		else if (checker.compare(this.getClass(), "Queries user about which character history to use", null, commandName, "chooseCharacter")) {
+			int ic=historyTask.queryUserChoose(currentTaxa, " to trace ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				recalcAllTraceOperators();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries user about which node number to save values for", null, commandName, "saveNodeValues")) {
+			if (querySaveNodeValues() && MesquiteInteger.isCombinable(nodeToOutput)) {
+				nodeInfo=null;
+				recalcAllTraceOperators();
+				if (StringUtil.notEmpty(nodeInfo))
+					MesquiteFile.putFileContentsQuery("Save file containing information about the designated node", nodeInfo,true);
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Sets whether or not the legend is shown", "[on = show; off]", commandName, "toggleShowLegend")) {
+			showLegend.toggleValue(parser.getFirstToken(arguments));
+			toggleLegendAllTraceOperators();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the fraction of trees with node absent is shown", "[on = show; off]", commandName, "toggleShowNodeAbsent")) {
+			showNodeAbsentSlice.toggleValue(parser.getFirstToken(arguments));
+			recalcAllTraceOperators();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the fraction of trees with equivocal states is shown", "[on = show; off]", commandName, "toggleShowEquivocal")) {
+			showEquivocalSlice.toggleValue(parser.getFirstToken(arguments));
+			recalcAllTraceOperators();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets how to count ambiguous state assignments at each node for each tree", "[0 = count state if in optimal state set, or has non-zero likelihood or other score, " +
+				"1 = count state only if unique in assignment, with no others of non-zero score, 2 = count state if unique in assignment or if uniquely has best score]", commandName, "setMode")) {
+			previousMode = mode;
+			String name = parser.getFirstToken(arguments);
+			int newMode = modes.indexOf(name);
+			if (newMode >=0 && newMode!=mode){
+				setToMode(newMode);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which character history to use", "[history number]", commandName, "setCharacter")) {
+			pos.setValue(0);
+			int icNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && (ic<=historyTask.getNumberOfHistories(currentTaxa)-1)) {
+				currentChar = ic;
+				recalcAllTraceOperators();
+			}
+		}
+		else /**/
+			if (checker.compare(this.getClass(), "Sets the number of trees", "[number]", commandName, "setNumTrees")) {
+				int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(newNum))
+					newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for Trace Character over Trees):", numTrees, 0, MesquiteInteger.infinite);
+				if (newNum>0  && newNum!=numTrees) {
+					numTrees = newNum;
+					numTreesSet = true;
+					if (!suppress){
+						recalcAllTraceOperators();
+						parametersChanged();
+					}
+				}
+				else if (numTrees == newNum)
+					numTreesSet = true;
+			}
+			else /**/
+				if (checker.compare(this.getClass(), "Sets the source of trees for comparison", "[name of module]", commandName, "setTreeSource")) {
+					TreeSource temp =  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees for comparison by for Trace Character Over Trees", treeSourceTask);
+					if (temp!=null) {
+						treeSourceTask=  temp;
+						treeSourceTask.setHiringCommand(cstC);
+						treeSourceName.setValue(treeSourceTask.getName());
+						numTreesSet = false;
+						if (!suppress){
+							recalcAllTraceOperators();
+							parametersChanged();
+						}
+					}	
+					return temp;
+				}
+				else if (checker.compare(this.getClass(), "Sets module supplying character histories", "[name of module]", commandName, "setHistorySource")) {
+					CharHistorySource temp =  (CharHistorySource)replaceCompatibleEmployee(CharHistorySource.class, arguments, historyTask, CategoricalState.class);
+					if (temp!=null) {
+						historyTask=  temp;
+						historyTask.setHiringCommand(htC);
+						historyTaskName.setValue(historyTask.getName());
+						currentChar=0;
+						resetAllTraceOperators();
+						recalcAllTraceOperators();
+						if (!suppress)
+							parametersChanged();
+					}
+					return historyTask;
+				}
+				else if (checker.compare(this.getClass(), "Suppresses calculations", null, commandName, "suppress")) {
+					suppress = true;
+				}
+				else if (checker.compare(this.getClass(), "Desuppresses calculations", null, commandName, "desuppress")) {
+					suppress = false;
+					parametersChanged();
+				}
+				else if (checker.compare(this.getClass(), "Returns ancestral states calculating module", null, commandName, "getAncStSource")) {
+					return historyTask;
+				}
+				else if (checker.compare(this.getClass(), "Turns off Trace Character Over Trees", null, commandName, "closeTrace")) {
+					iQuit();
+					resetContainingMenuBar();
+				}
+				else if (checker.compare(this.getClass(), "Sets initial horizontal offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetX")) {
+					int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+					if (MesquiteInteger.isCombinable(offset)) {
+						initialOffsetX = offset;
+						Enumeration e = traces.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof TraceCOTOperator) {
+								TraceCOTOperator tCO = (TraceCOTOperator)obj;
+								if (tCO.traceLegend!=null)
+									tCO.traceLegend.setOffsetX(offset);
+							}
+						}
+
+					}
+				}
+				else if (checker.compare(this.getClass(), "Sets initial vertical offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetY")) {
+					int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+					if (MesquiteInteger.isCombinable(offset)) {
+						initialOffsetY = offset;
+						Enumeration e = traces.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof TraceCOTOperator) {
+								TraceCOTOperator tCO = (TraceCOTOperator)obj;
+								if (tCO.traceLegend!=null)
+									tCO.traceLegend.setOffsetY(offset);
+							}
+						}
+					}
+				}
+				else if (checker.compare(this.getClass(), "Sets initial width of legend", "[width in pixels]", commandName, "setLegendWidth")) {
+					int x= MesquiteInteger.fromFirstToken(arguments, pos);
+					if (MesquiteInteger.isCombinable(x)) {
+						initialLegendWidth = x;
+						if (initialLegendWidth<50)
+							initialLegendWidth=50;
+						Enumeration e = traces.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof TraceCOTOperator) {
+								TraceCOTOperator tCO = (TraceCOTOperator)obj;
+								if (tCO.traceLegend!=null)
+									tCO.traceLegend.setLegendWidth(x);
+							}
+						}
+
+					}
+				}
+				else if (checker.compare(this.getClass(), "Sets initial height of legend", "[height in pixels]", commandName, "setLegendHeight")) {
+					int x= MesquiteInteger.fromFirstToken(arguments, pos);
+					if (MesquiteInteger.isCombinable(x)) {
+						initialLegendHeight = x;
+						if (initialLegendHeight<50)
+							initialLegendHeight=50;
+						Enumeration e = traces.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof TraceCOTOperator) {
+								TraceCOTOperator tCO = (TraceCOTOperator)obj;
+								if (tCO.traceLegend!=null)
+									tCO.traceLegend.setLegendHeight(x);
+							}
+						}
+					}
+				}
+				else
+					return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public int getNumTrees(){
+		if (MesquiteThread.isScripting() || numTreesSet)
+			return numTrees;
+		int newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for Trace Character over Trees):", numTrees, 0, MesquiteInteger.infinite);
+		if (newNum>0) {
+			numTrees = newNum;
+			numTreesSet = true;
+		}
+		return numTrees;
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee == displayTask)
+			redrawAllTraceOperators();
+		else if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+			recalcAllTraceOperators();
+	}
+	/*.................................................................................................................*/
+	public void recalcAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				tCO.recalculate();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				tCO.decorator = null;
+				tCO.resetTreeDecorator();
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.repaint();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void redrawAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.repaint();
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(false);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void closeAllTraceOperators() {
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				tCO.turnOff();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void toggleLegendAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(false);
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.setVisible(showLegend.getValue());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void toggleModeAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCOTOperator) {
+				TraceCOTOperator tCO = (TraceCOTOperator)obj;
+				tCO.setMode(mode);
+				tCO.recalculate();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		closeAllTraceOperators();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Trace Character Over Trees";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Summarizes at each node reconstructions of the states of a character over a series of trees.  The summary is shown on the current tree; if you want to show it on a consensus of the trees, make sure that the current tree is that consensus.";
+	}
+	public boolean getShowNodeAbsentSlice() {
+		return showNodeAbsentSlice.getValue();
+	}
+	public void setShowNodeAbsentSlice(boolean showNodeAbsentSlice) {
+		this.showNodeAbsentSlice.setValue(showNodeAbsentSlice);
+	}
+	public boolean getShowEquivocalSlice() {
+		return showEquivocalSlice.getValue();
+	}
+	public void setShowEquivocalSlice(boolean showEquivocalSlice) {
+		this.showEquivocalSlice.setValue(showEquivocalSlice);
+	}
+	public int getNodeToOutput() {
+		return nodeToOutput;
+	}
+	public void setNodeToOutput(int nodeToOutput) {
+		this.nodeToOutput = nodeToOutput;
+	}
+
+	public void setNodeOutputString(String s) {
+		nodeInfo =s;
+	}
+}
+
+/*======================================================================== */
+class TraceCOTOperator extends TreeDisplayDrawnExtra {
+	Tree myTree;
+	TraceCharOverTrees traceModule;
+	CategoricalHistory charStates;
+	public TraceLegend traceLegend;
+	TreeDecorator decorator;
+	MesquiteColorTable colorTable = MesquiteColorTable.DEFAULTCOLORTABLE;
+	int currentChar = 0;
+	Taxa taxa = null;
+	long allStates = 0L;
+	static final int UNIQUELY_BEST=0;
+	static final int COUNT_EQUIVOCAL=1;
+	static final int AVERAGE_FREQUENCIES =2;
+	static final int NODE_EQUIVOCAL =  1;
+	static final int NODE_ABSENT = 0;
+	static final int numExtraFrequencies = 2;
+	//	static int maxFrequencyBin = CategoricalState.maxCategoricalState+1;
+	int mode;
+	int[] treeCounts;
+	int[] apparentTrees;
+	int[] validTrees;
+	int totalTrees =0;
+	MesquiteString resultString = new MesquiteString();
+	int[] numEquivocal;
+
+
+	public TraceCOTOperator (TraceCharOverTrees ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		traceModule = ownerModule;
+		mode = traceModule.mode;
+	}
+
+	public void setMode(int mode){
+		this.mode = mode;
+	}
+
+	boolean firstTreeHasAllTaxa = true;
+	/*.................................................................................................................*/
+	public void resetTreeDecorator(int drawnRoot) {
+		if (decorator==null)
+			decorator = traceModule.displayTask.createTreeDecorator(treeDisplay, this);
+		if (decorator!=null) {
+			Graphics g = treeDisplay.getGraphics();
+			if (g!=null) {
+				decorator.drawOnTree(myTree, drawnRoot,  charStates, null, null, g); 
+				g.dispose();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetTreeDecorator() {
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+		resetTreeDecorator(drawnRoot);
+	}
+	int[] nodeInfoTerminals;
+	StringBuffer nodeInfoBuffer = null;
+	/*.................................................................................................................*/
+	public   void recalculate(){
+		int place = 0;
+		try {
+			totalTrees =0;
+			nodeInfoBuffer = null;
+			if (traceModule == null || myTree == null || treeDisplay == null || traceModule.suppress)
+				return;
+
+			if (MesquiteInteger.isCombinable(traceModule.getNodeToOutput()))
+				nodeInfoBuffer = new StringBuffer();
+			place = 1;
+			if (!traceModule.suppress && (traceModule.historyTask !=null) && traceModule.treeSourceTask != null && myTree !=null){ 
+				/* preliminaries .......... */
+				place = 2;
+				if (traceLegend!=null && traceModule.showLegend != null && traceModule.showLegend.getValue()) {
+					traceLegend.onHold();
+					int max = traceModule.historyTask.getNumberOfHistories(myTree);
+					if (traceModule.currentChar >= max)
+						traceModule.currentChar = max-1;
+					traceLegend.adjustScroll(CharacterStates.toExternal(traceModule.currentChar), max);
+
+				}
+				place = 3;
+				taxa = myTree.getTaxa();
+				traceModule.currentTaxa = taxa;
+				nodeInfoTerminals=null;
+				if (MesquiteInteger.isCombinable(traceModule.getNodeToOutput()))
+					nodeInfoTerminals = myTree.getTerminalTaxa(traceModule.getNodeToOutput());
+				int drawnRoot = 0;
+				if (treeDisplay.getTreeDrawing() != null){
+					drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+					resetTreeDecorator(drawnRoot);
+				}
+				place = 4;
+
+				if (charStates != null)
+					charStates.deassignStates();
+				/*	if (charStates == null)
+ 				charStates = new CategoricalHistory(taxa, myTree.getNumNodeSpaces());
+ 			charStates.adjustSize(myTree);
+			charStates.deassignStates();
+				 */
+				if (resultString != null)
+					resultString.setValue("Please wait; calculating.");
+				if (traceLegend!=null && traceModule.showLegend != null && traceModule.showLegend.getValue()) {
+					traceLegend.refreshSpecsBox();
+				}
+
+				place = 5;
+				if (treeCounts == null || treeCounts.length != myTree.getNumNodeSpaces())
+					treeCounts = new int[myTree.getNumNodeSpaces()];
+				IntegerArray.zeroArray(treeCounts);
+
+				if (apparentTrees == null || apparentTrees.length != myTree.getNumNodeSpaces())
+					apparentTrees = new int[myTree.getNumNodeSpaces()];
+				IntegerArray.zeroArray(apparentTrees);
+
+				if (validTrees == null || validTrees.length != myTree.getNumNodeSpaces())
+					validTrees = new int[myTree.getNumNodeSpaces()];
+				IntegerArray.zeroArray(validTrees);
+				place = 6;
+
+				int numTrees = traceModule.treeSourceTask.getNumberOfTrees(taxa);
+				boolean en = !MesquiteInteger.isFinite(numTrees);
+				if (en)
+					numTrees = traceModule.getNumTrees();
+				if (traceModule.numTreesItem != null && en != traceModule.numTreesItem.isEnabled()) {
+					traceModule.numTreesItem.setEnabled(en);
+					MesquiteTrunk.resetMenuItemEnabling();
+				}
+				en = mode == TraceCOTOperator.UNIQUELY_BEST;
+				if (traceModule.showEquivocalItem != null && en != traceModule.showEquivocalItem.isEnabled()) {
+					traceModule.showEquivocalItem.setEnabled(en);
+					MesquiteTrunk.resetMenuItemEnabling();
+				}
+				place = 7;
+
+
+				if (!myTree.nodeExists(drawnRoot))
+					drawnRoot = myTree.getRoot();
+				CategoricalHistory tempCharStates = null;
+				double[][] frequencies = new double[myTree.getNumNodeSpaces()][CategoricalState.maxCategoricalState+1];
+				for (int i = 0; i<frequencies.length; i++)
+					DoubleArray.zeroArray(frequencies[i]);
+				double[][] extraFrequencies = new double[myTree.getNumNodeSpaces()][numExtraFrequencies];
+				for (int i = 0; i<extraFrequencies.length; i++)
+					DoubleArray.zeroArray(extraFrequencies[i]);
+				if (numEquivocal == null || numEquivocal.length <= myTree.getNumNodeSpaces())
+					numEquivocal = new int[myTree.getNumNodeSpaces()];
+				IntegerArray.zeroArray(numEquivocal);
+				place = 8;
+
+				Tree tempTree = traceModule.treeSourceTask.getTree(taxa, 0);
+				if (tempTree == null)
+					return;
+				place = 9;
+				int maxnum = traceModule.historyTask.getNumberOfHistories(tempTree);
+				allStates = 0L;
+				if (traceModule.currentChar>= maxnum)
+					traceModule.currentChar = maxnum-1;
+				if (traceModule.currentChar<0)
+					traceModule.currentChar = 0;
+				place = 10;
+				String modeString = "Shown for each state at each node is the number of trees on which the reconstructed state set at the node";
+				if (mode == UNIQUELY_BEST)
+					modeString += " contains that state as uniquely best according to the reconstruction criteria.";
+				else if (mode == COUNT_EQUIVOCAL)
+					modeString += " includes that state (it may also include other states as equally or sufficiently optimal according to the reconstruction criteria).";
+				else if (mode == AVERAGE_FREQUENCIES)
+					modeString = "Shown for each state at each node is the average value (e.g., likelihood) of that state across trees that have that node.";
+				place = 11;
+				String note =  traceModule.historyTask.getHistoryName(taxa, traceModule.currentChar) + "\n";
+				note += traceModule.historyTask.getNameAndParameters();
+				if (resultString != null){
+					if (MesquiteInteger.isCombinable(numTrees))
+						resultString.setValue(note + " over " + numTrees + " trees (" + traceModule.treeSourceTask.getName() + "; " + traceModule.treeSourceTask.getParameters() + ").  " + modeString);
+					else
+						resultString.setValue(note + " over trees (" + traceModule.treeSourceTask.getName() + "; " + traceModule.treeSourceTask.getParameters() + ").  " + modeString);
+				}
+				place = 12;
+				totalTrees = numTrees;
+				IntegerArray.zeroArray(validTrees);
+				firstTreeHasAllTaxa = true;
+				boolean firstTree=true;
+
+				ProgressIndicator progIndicator = new ProgressIndicator(ownerModule.getProject(),ownerModule.getName(), "Surveying trees for character histories", numTrees, true);
+				if (progIndicator!=null){
+					progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+					progIndicator.setOfferContinueMessageString("Are you sure you want to stop the survey?");
+					progIndicator.start();
+				}
+				place = 13;
+				/* checking all trees .......... */
+				int it = 0;
+				boolean warnNoFrequencies = false;
+
+
+
+
+				for (it = 0; it< numTrees && tempTree != null; it++){
+					place = 14;
+					if (progIndicator != null) {
+						if (progIndicator.isAborted()) {
+							progIndicator.goAway();
+							traceModule.closeAllTraceOperators();
+							return;
+						}
+						progIndicator.setText("Tree " + it);
+						progIndicator.setCurrentValue(it);
+					}
+					if (MesquiteInteger.isCombinable(numTrees))
+						CommandRecord.tick("Examining ancestral state reconstruction on tree " + it + " of " + numTrees);
+					else 
+						CommandRecord.tick("Examining ancestral state reconstruction on tree " + it);
+					place = 15;
+					traceModule.historyTask.prepareHistory(tempTree, traceModule.currentChar);
+					//				CharacterHistory currentHistory = historyTask.getMapping(0, null, resultString);
+					tempCharStates = (CategoricalHistory)traceModule.historyTask.getMapping(0, tempCharStates, null);
+
+
+					if (tempCharStates == null)
+						return;
+					else if (tempCharStates.frequenciesExist() || mode != AVERAGE_FREQUENCIES) {  
+						//this tree has the relevant information to process it
+
+						place = 16;
+						charStates = (CategoricalHistory)tempCharStates.adjustHistorySize(myTree, charStates);
+						if (charStates == null)
+							return;
+
+						//					this next section captures the states in the terminal taxa. 
+						//					if there are multiple states for a terminal taxon, then each is given equal frequencies
+						if (firstTree || !firstTreeHasAllTaxa) {
+							CharacterDistribution charDist = tempCharStates.getObservedStates();
+							if (charDist == null)
+								return;
+							place = 17;
+							CategoricalState cs = new CategoricalState();
+							for (int i=0; i<taxa.getNumTaxa(); i++) 
+								if (tempTree.taxonInTree(i)) {	//TODO: what if it is in myTree but not in TempTree?
+									cs = (CategoricalState)charDist.getCharacterState (cs,i);
+									if ((cs.isUnassigned() || cs.isInapplicable()) && charStates!=null && myTree!=null) {
+										charStates.setState(myTree.nodeOfTaxonNumber(i), cs.getValue());  // set the charStates value so that the system will know later this was applicable or missing
+									} else {
+										long s = cs.getValue();
+										int numStates = cs.cardinality(s);
+										for (int e = 0; e < cs.getMaxPossibleState(); e++)
+											if (cs.isElement(e)) {
+												frequencies[myTree.nodeOfTaxonNumber(i)][e] = 1.0/numStates;
+											}
+									}
+								} else if (firstTree)
+									firstTreeHasAllTaxa = false;
+							place = 18;
+							firstTree = false;
+						}
+
+						allStates |= tempCharStates.getAllStates();
+						//survey original nodes to see if node is in tree, and if so record char reconstructed
+						visitOriginalNodes(myTree, drawnRoot, tempTree, tempCharStates, frequencies, extraFrequencies, numEquivocal);
+						place = 19;
+
+						if (it+1<numTrees)
+							tempTree = traceModule.treeSourceTask.getTree(taxa, it+1);
+					} 
+					else if (!tempCharStates.frequenciesExist() && mode == AVERAGE_FREQUENCIES) {
+						place = 20;
+						if (!warnNoFrequencies)
+							MesquiteMessage.discreetNotifyUser("Ancestral state reconstructor does not calculate frequencies, so the Average Frequencies mode is not available");
+						warnNoFrequencies = true;
+						if (progIndicator!=null) 
+							progIndicator.goAway();
+						traceModule.setToPreviousMode();
+						return;
+					}
+				}
+
+
+				place = 21;
+				if (!firstTree)
+					visitOriginalNodesAgain(myTree, drawnRoot, tempCharStates, frequencies, extraFrequencies, numEquivocal, numTrees);
+
+				totalTrees = it;
+				if (progIndicator!=null) 
+					progIndicator.goAway();
+				place = 22;
+
+
+
+				/*for (int n = 0; n<frequencies.length; n++){
+				double sum =0;
+				for (int i=0; i<frequencies[n].length; i++)
+					sum += frequencies[n][i];
+				if (sum!=0.0)
+					for (int i=0; i<frequencies[n].length; i++)
+						frequencies[n][i] /= sum;
+
+			}
+				 */
+				captureFrequencies(myTree, drawnRoot, charStates, frequencies, extraFrequencies);
+
+				place = 23;
+				ColorDistribution extraColors = new ColorDistribution();
+				String[] extraNames =null;
+				int numExtraNames = 2;
+				boolean showNodeAbsent = traceModule.getShowNodeAbsentSlice();
+				boolean showEquivocal = mode==UNIQUELY_BEST && traceModule.getShowEquivocalSlice();
+				extraNames = new String[numExtraNames];
+				for (int i = 0; i<numExtraNames; i++)
+					extraNames[i] ="";
+				place = 24;
+				if (showEquivocal) {
+					extraNames[NODE_EQUIVOCAL] = "Equivocal";
+					extraColors.setColor(NODE_EQUIVOCAL,Color.lightGray);
+				}
+				if (showNodeAbsent){
+					extraNames[NODE_ABSENT] = "Node Absent";
+					extraColors.setColor(NODE_ABSENT,Color.red);
+				}
+				charStates.setExtraFrequencyNames(extraNames);
+				charStates.setExtraFrequencyColors(extraColors);
+
+				place = 25;
+				/*
+				 * 		for (int i=0; i<taxa.getNumTaxa(); i++) 
+				if (myTree.taxonInTree(i)) {
+					int node = myTree.nodeOfTaxonNumber(i);
+					charStates.setFrequencies(node, stateset);
+					charStates.setState(node, stateset);
+				}
+				 */
+
+
+				charStates.prepareColors(myTree, drawnRoot);
+				colorTable = charStates.getColorTable(colorTable);
+				treeDisplay.pleaseUpdate(false);
+				place = 26;
+				if (traceLegend!=null && traceModule.showLegend()) {
+					traceLegend.setColorTable(colorTable);
+					traceLegend.offHold();
+					traceLegend.repaint();
+				}
+			}
+
+			if (nodeInfoBuffer!=null && (StringUtil.notEmpty(nodeInfoBuffer.toString())))
+				traceModule.setNodeOutputString(nodeInfoBuffer.toString());
+			place = 27;
+		}
+		catch(NullPointerException e){
+			MesquiteMessage.println("NullPointerException in recalculate of TraceCharacterOverTrees " + place);
+		}
+
+	}
+	TreeReference myTreeRef = null;
+	/*.................................................................................................................*/
+	boolean toShow = false;
+	public   void setTree(Tree tree){
+		if (tree != null && myTreeRef != null && tree instanceof MesquiteTree && ((MesquiteTree)tree).sameTreeVersions(myTreeRef, true, false) && !MesquiteThread.isScripting()) {
+			myTreeRef = ((MesquiteTree)tree).getTreeReference(myTreeRef);
+			return;
+		}
+		myTree = tree;
+		if (tree==null)
+			return;
+		if (tree instanceof MesquiteTree)
+			myTreeRef = ((MesquiteTree)tree).getTreeReference(myTreeRef);
+		taxa = tree.getTaxa();
+		traceModule.currentTaxa = taxa;
+		int numTrees = traceModule.treeSourceTask.getNumberOfTrees(taxa);
+		boolean en = !MesquiteInteger.isFinite(numTrees); 
+		if (en != traceModule.numTreesItem.isEnabled()) {
+			traceModule.numTreesItem.setEnabled(en);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+		if (traceLegend==null  && traceModule.showLegend()) {
+			traceLegend = new TraceLegend(traceModule, treeDisplay, resultString, "Trace over Trees", Color.red);
+			traceLegend.adjustScroll(CharacterStates.toExternal(traceModule.currentChar), traceModule.historyTask.getNumberOfHistories(myTree)); 
+			addPanelPlease(traceLegend);
+			toShow = true;
+		}
+		recalculate();
+	}
+	private long freqToStateSet(double[] f){
+		if (f == null)
+			return 0L;
+		long result = 0L;
+		for (int i=0; i<f.length && i<=CategoricalState.maxCategoricalState; i++)
+			if (f[i]>0.0)
+				result = CategoricalState.addToSet(result, i);
+		return result;
+	}
+	private void captureFrequencies(Tree tree,int node, CategoricalHistory summaryCharStates, double[][] frequencies, double[][] extraFrequencies){
+		if (summaryCharStates==null)
+			return;
+		if (tree.nodeIsInternal(node)){
+			summaryCharStates.setFrequencies(node, frequencies[node]);
+			summaryCharStates.setExtraFrequencies(node, extraFrequencies[node]);
+			summaryCharStates.setState(node, freqToStateSet(frequencies[node]));
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				captureFrequencies(tree, daughter, summaryCharStates, frequencies, extraFrequencies); 
+
+		} else {
+			summaryCharStates.setFrequencies(node, frequencies[node]);
+			summaryCharStates.setExtraFrequencies(node, extraFrequencies[node]);
+			long s = freqToStateSet(frequencies[node]);
+			if (s!=0L)  // don't overwrite the value saved for terminal nodes that are inapplicable or missing
+				summaryCharStates.setState(node, s);
+		}
+	}
+
+
+	private void visitOriginalNodesAgain(Tree tree,int node, CategoricalHistory tempCharStates, double[][] frequencies, double[][] extraFrequencies, int[] numEquivocal, int numTrees){
+		if (tree.nodeIsInternal(node)){
+			if (mode==COUNT_EQUIVOCAL) {
+				for (int i=0; i<=tempCharStates.getMaxState(); i++)
+					if (MesquiteDouble.isCombinable(frequencies[node][i]))
+						frequencies[node][i] = frequencies[node][i]*validTrees[node]/apparentTrees[node];
+			}
+			else if (validTrees[node]>0) {
+				if (mode == AVERAGE_FREQUENCIES){
+					for (int i=0; i<=tempCharStates.getMaxState(); i++)
+						if (MesquiteDouble.isCombinable(frequencies[node][i]))
+							frequencies[node][i] = 1.0*frequencies[node][i] /validTrees[node];
+
+					//frequencies will now sum up to 1.0.  We then want to compensate extraFrequencies by the same amount so that they are relative the same 
+					for (int i=0; i<numExtraFrequencies; i++)
+						extraFrequencies[node][i] =  extraFrequencies[node][i] /validTrees[node];  
+				}
+			}
+
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginalNodesAgain(tree, daughter, tempCharStates, frequencies, extraFrequencies, numEquivocal, numTrees);
+		}
+	}
+
+	private void visitOriginalNodes(Tree tree,int node,  Tree otherTree, CategoricalHistory tempCharStates, double[][] frequencies, double[][] extraFrequencies, int[] numEquivocal){
+		int[] taxaInClade = tree.getTerminalTaxa(node);
+		boolean outputNodeInfo = false;
+		if (nodeInfoTerminals!=null)
+			outputNodeInfo= IntegerArray.arraysSame(taxaInClade,nodeInfoTerminals);
+
+
+		if (tree.nodeIsInternal(node)){
+
+			int c = cladeInTree(otherTree, otherTree.getRoot(), taxaInClade);
+			if (c>0) {
+				treeCounts[node]++; //record that node is in tree
+				long stateSet = tempCharStates.getState(c);
+				int card = CategoricalState.cardinality(stateSet);
+				if (outputNodeInfo) {
+					double[] tempFreq = tempCharStates.getFrequencies(c);
+					if (tempFreq!=null){
+						validTrees[node]++;
+						for (int i=0; i<=CategoricalState.maxCategoricalState && i<tempFreq.length;  i++)
+							nodeInfoBuffer.append(""+ tempFreq[i]+"\t");
+					} else {
+						nodeInfoBuffer.append(tempCharStates.toString(c,""));
+					}
+				}
+				if (mode == UNIQUELY_BEST){
+					if (card==1)
+						frequencies[node][CategoricalState.minimum(stateSet)] += 1;
+					else if (traceModule.getShowEquivocalSlice())
+						extraFrequencies[node][NODE_EQUIVOCAL] += 1;
+				}
+				else if (mode == COUNT_EQUIVOCAL){
+					if (card!=0){
+						validTrees[node]++;
+						//double worth = 1.0/CategoricalState.cardinality(stateSet);
+						for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+							if (CategoricalState.isElement(stateSet, i)) {
+								frequencies[node][i] += 1;
+								apparentTrees[node] +=1;
+							}
+					}
+				}
+				else if (mode == AVERAGE_FREQUENCIES){
+					double[] tempFreq = tempCharStates.getFrequencies(c);
+					if (outputNodeInfo)
+						nodeInfoBuffer.append("-");
+					if (tempFreq!=null){
+						validTrees[node]++;
+						//grab all of them,no just ones in state set
+						for (int i=0; i<=CategoricalState.maxCategoricalState && i<tempFreq.length;  i++)
+							frequencies[node][i] += tempFreq[i];
+					}
+				}
+				if (card>1)
+					numEquivocal[node]++;
+
+			} else {
+				if (outputNodeInfo)
+					nodeInfoBuffer.append("-");
+				if (traceModule.getShowNodeAbsentSlice()) {
+					extraFrequencies[node][NODE_ABSENT] += 1;
+				}
+			}
+			if (outputNodeInfo)
+				nodeInfoBuffer.append("\n");
+
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginalNodes(tree, daughter, otherTree, tempCharStates, frequencies, extraFrequencies, numEquivocal);
+
+		}
+	}
+	private int cladeInTree(Tree tree, int node,  int[] target){
+		if (target == null)
+			return -1;
+		if (target.length == 1) {
+			if (tree.nodeIsTerminal(node) && target[0] == tree.taxonNumberOfNode(node))
+				return node;
+			else 
+				return -1;
+		}
+
+		if (tree.nodeIsInternal(node)){
+			int[] taxaHere = tree.getTerminalTaxa(node);
+			if (IntegerArray.arraysSame(taxaHere, target))
+				return node;	
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				int t = (cladeInTree(tree, daughter, target));
+				if (t>0)
+					return t;
+			}
+		}
+		return -1;
+	}
+	CharacterState cs = null;
+	public void cursorEnterBranch(Tree tree, int N, Graphics g) {
+		String nodeReport = "";
+		if (tree.nodeIsTerminal(N)) {
+			if (traceModule.showLegend() && traceLegend!=null && charStates!=null) {
+				cs = charStates.getCharacterState(cs, N);
+				nodeReport = "\nTerminal branch\nObserved states are: "+cs.toDisplayString();
+				if (((CategoricalState)cs).cardinality() >1) {
+					nodeReport += "\n(each state shown in equal proportion) ";
+				}
+				traceLegend.setMessage(nodeReport);
+			}
+		}
+		else {
+			if (treeCounts!=null && treeCounts.length>N)
+				nodeReport = "\nNode present in " + treeCounts[N] + " of " + totalTrees + " trees";
+			if (traceModule.showLegend() && traceLegend!=null && charStates!=null) {
+				cs = charStates.getCharacterState(cs, N);
+				if (!cs.isCombinable() && treeCounts[N]>0) {
+					if (mode == UNIQUELY_BEST)
+						nodeReport = "\nNo states reported for this node.  It may have no uniquely best states on any tree. " + nodeReport;
+					else if (mode == COUNT_EQUIVOCAL)
+						nodeReport = "\nNo states reported for this node.  " + nodeReport;
+					else if (mode == AVERAGE_FREQUENCIES)
+						nodeReport = "\nNo states reported for this node  " + nodeReport;
+				}
+				if (numEquivocal[N]==1)
+					nodeReport = "\n" + numEquivocal[N] + " tree with equivocal reconstruction. " + nodeReport;
+				else if (numEquivocal[N]>1)
+					nodeReport = "\n" + numEquivocal[N] + " trees with equivocal reconstructions. " + nodeReport;
+				traceLegend.setMessage(charStates.toString(N, "\n") + nodeReport);
+			}
+		}
+	}
+	public void cursorExitBranch(Tree tree, int N, Graphics g) {
+		if (traceModule.showLegend() && traceLegend!=null)
+			traceLegend.setMessage("");
+	}
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g) {
+		if (traceModule.showLegend() && traceLegend!=null && charStates!=null && charStates.getObservedStates()!=null)
+			traceLegend.setMessage("Reconstruction counts not made for observed states in terminal taxa");
+	}
+	public void cursorExitTaxon(Tree tree, int M, Graphics g) {
+		if (traceModule.showLegend() && traceLegend!=null)
+			traceLegend.setMessage("");
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if ((traceModule.historyTask!=null) && (charStates!=null) && (decorator!=null)) {
+			decorator.useColorTable(colorTable);
+			decorator.drawOnTree(tree, drawnRoot,  charStates, null, null, g); 
+			if (traceModule.showLegend() && traceLegend !=null) {
+				charStates.prepareColors(tree, drawnRoot);
+				traceLegend.setStates(charStates);
+				traceLegend.adjustLocation();
+				if (toShow || !traceLegend.isVisible())
+					traceLegend.setVisible(true);
+				toShow=false;
+			}
+		}
+	}
+
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (tree.nodeIsTerminal(node))
+			return null;
+		String nodeReport = "";
+		if (treeCounts!=null && treeCounts.length>node)
+			nodeReport = "Node in " + treeCounts[node] + " trees.";
+		if (charStates!=null) {
+			cs = charStates.getCharacterState(cs, node);
+			if (!cs.isCombinable() && treeCounts[node]>0) {
+				if (mode == UNIQUELY_BEST)
+					nodeReport += "No states reported for this node.  This may be due to its having no uniquely best states on any tree. ";
+				else if (mode == COUNT_EQUIVOCAL || mode==AVERAGE_FREQUENCIES)
+					nodeReport += "No states reported for this node.  ";
+			}
+			else if (mode==AVERAGE_FREQUENCIES)
+				nodeReport += "  States and relative average probabilities of each across trees: " + charStates.toString(node, "; ");
+			else
+				nodeReport += "  Optimal states and count of trees with each: " + charStates.toString(node, "; ");
+		}
+		return nodeReport;
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		return resultString.getValue();
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	public void turnOff(){
+		if (treeDisplay!=null && traceLegend !=null)
+			treeDisplay.removePanelPlease(traceLegend);
+		super.turnOff();
+
+	}
+}
+
+interface TraceModule extends Commandable {
+	public int getInitialOffsetX();
+	public int getInitialOffsetY();
+	public boolean showLegend();
+}
+/* ======================================================================== */
+class TraceLegend extends TreeDisplayLegend {
+	private TraceModule traceModule;
+	public MiniScroll characterScroll = null;
+	private MesquiteString resultString;
+	private String[] stateNames;
+	private Color[] legendColors;
+	private static final int defaultLegendWidth=142;
+	private static final int defaultLegendHeight=120;
+	private int numBoxes=0;
+	private int oldNumChars = 0;
+	private int oldNumBoxes=0;
+	private int oldCurrentChar = -1;
+	private boolean resizingLegend=false;
+	private TCMPanel messageBox;
+	private TextArea specsBox;
+	private boolean holding = false;
+	final int scrollAreaHeight = 41;
+	private int messageHeight = 22;
+	final int defaultSpecsHeight = (14 + MesquiteModule.textEdgeCompensationHeight) * 3;
+	private int specsHeight = defaultSpecsHeight;
+	private int e = 4;
+	private String title;
+	private Color titleColor;
+
+	public TraceLegend(TraceCharOverTrees traceModule, TreeDisplay treeDisplay, MesquiteString resultString, String title, Color titleColor) {
+		super(treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		if (MesquiteInteger.isCombinable(traceModule.initialLegendWidth))
+			legendWidth = traceModule.initialLegendWidth;
+		if (MesquiteInteger.isCombinable(traceModule.initialLegendHeight))
+			legendHeight = traceModule.initialLegendHeight;
+		setVisible(false);
+		this.title = title;
+		this.titleColor = titleColor;
+		this.resultString = resultString;
+		legendWidth=defaultLegendWidth;
+		legendHeight=defaultLegendHeight;
+		setOffsetX(traceModule.getInitialOffsetX());
+		setOffsetY(traceModule.getInitialOffsetY());
+		this.traceModule = traceModule;
+		//setBackground(ColorDistribution.light);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+		stateNames = new String[64];
+		legendColors = new Color[64];
+		for (int i=0; i<64; i++) {
+			stateNames[i] = null;
+			legendColors[i] = null;
+		}
+		specsBox = new TextArea(" ", 2, 2, TextArea.SCROLLBARS_NONE);
+		specsBox.setEditable(false);
+		if (traceModule.showLegend())// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(false);
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		add(specsBox);
+
+		messageBox = new TCMPanel();
+		messageBox.setBounds(2,legendHeight-messageHeight-8,legendWidth-6, messageHeight);
+		messageBox.setText("\n");
+		//messageBox.setColor(Color.pink);
+		//messageBox.setBackground(Color.pink);
+		add(messageBox);
+	}
+
+	public void adjustScroll(int currentCharExternal, int numChars) {
+		if (characterScroll == null) {
+			characterScroll = new MiniScroll( MesquiteModule.makeCommand("setCharacter",  (Commandable)traceModule), false, currentCharExternal, 1,  numChars, "character");
+			add(characterScroll);
+			characterScroll.setLocation(2,18);//18);
+			characterScroll.setColor(Color.blue);
+			repaint();
+			oldNumChars = numChars;
+			oldCurrentChar = currentCharExternal;
+		}
+		else {
+			if (oldNumChars != numChars) {
+				characterScroll.setMaximumValue(numChars);
+				oldNumChars = numChars;
+			}
+			if (oldCurrentChar != currentCharExternal) {
+				characterScroll.setCurrentValue(currentCharExternal);
+				oldCurrentChar = currentCharExternal;
+			}
+		}
+	}
+
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (characterScroll !=null)
+			characterScroll.setVisible(b);
+		if (messageBox!=null)
+			messageBox.setVisible(b);
+		if (specsBox!=null)// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(b);
+	}
+
+	public void refreshSpecsBox(){
+		specsBox.setText(resultString.getValue()); 
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!holding) {
+			g.setColor(Color.black);
+			if (numBoxes!=0) {
+				int boxCount =0;
+				for (int ibox=0; ibox<numBoxes; ibox++) {
+					if (!StringUtil.blank(stateNames[ibox])){
+						g.setColor(legendColors[ibox]);
+						g.fillRect(4, boxCount*16+scrollAreaHeight + specsHeight+ e, 20, 12);
+						g.setColor(Color.black);
+						g.drawRect(4, boxCount*16+scrollAreaHeight + specsHeight + e, 20, 12);
+						if (stateNames[ibox]!=null)
+							g.drawString(stateNames[ibox], 28, boxCount*16 + specsHeight+scrollAreaHeight + 12 + e);
+						boxCount++;
+					}
+				}
+			}
+			g.setColor(Color.cyan);
+			g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+			g.fillRect(legendWidth-6, legendHeight-6, 6, 6);
+			g.drawLine(0, scrollAreaHeight, legendWidth-1, scrollAreaHeight);
+
+			g.setColor(titleColor);
+			g.drawString(title, 4, 14);
+			g.setColor(Color.black);
+			if (resultString.getValue()!=null && !resultString.getValue().equals(specsBox.getText()))
+				specsBox.setText(resultString.getValue()); 
+
+			if (specsBox.getBackground() != getBackground())
+				specsBox.setBackground(getBackground());
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void printAll(Graphics g) {
+		g.setColor(Color.black);
+		g.drawString("Trace Character", 4, 14);
+		String info = resultString.getValue();
+		StringInABox sib = new StringInABox(info, g.getFont(), legendWidth);
+		sib.draw(g, 4, 16);
+		int QspecsHeight = sib.getHeight();
+		int lastBox = QspecsHeight + 20;
+		//int QspecsHeight = 0;
+		//int lastBox = scrollAreaHeight + QspecsHeight + 20 + 12;
+		if (numBoxes!=0) {
+			for (int ibox=0; ibox<numBoxes; ibox++) {
+				g.setColor(legendColors[ibox]);
+				g.fillRect(4, ibox*16+ QspecsHeight + 20, 20, 12);
+				g.setColor(Color.black);
+				g.drawRect(4, ibox*16+ QspecsHeight + 20, 20, 12);
+				g.drawString(stateNames[ibox], 28, ibox*16 + QspecsHeight + 32);
+				lastBox =ibox*16 + QspecsHeight + 20 + 12;
+			}
+		}
+	}
+	MesquiteColorTable colorTable;
+	public void setColorTable(MesquiteColorTable colorTable){
+		this.colorTable = colorTable;
+	}
+	public void setStates(CharacterHistory statesAtNodes){
+		numBoxes = statesAtNodes.getLegendStates(legendColors, stateNames, null, colorTable);
+
+		//		if (((CategoricalHistory)statesAtNodes).extraFrequenciesExist())
+		//			numBoxes += (((CategoricalHistory)statesAtNodes).getExtraNumFreqCategories());
+		if (numBoxes!=oldNumBoxes) {
+			reviseBounds();
+			oldNumBoxes=numBoxes;
+		}
+		repaint();
+	}
+
+	public void legendResized(int widthChange, int heightChange){
+		if ((specsHeight + heightChange)>= defaultSpecsHeight)
+			specsHeight += heightChange;
+		else
+			specsHeight  = defaultSpecsHeight;
+		checkComponentSizes();
+	}
+	public void setLegendWidth(int w){
+		legendWidth = w;
+	}
+	public void setLegendHeight(int h){
+		legendHeight = h;
+	}
+	public void reviseBounds(){
+		checkComponentSizes();
+		Point where = getLocation();
+		setBounds(where.x,where.y,legendWidth, legendHeight);
+	}
+	public void checkComponentSizes(){
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		specsBox.setVisible(true);
+		messageHeight = messageBox.getHeightNeeded();
+		if (messageHeight<20)
+			messageHeight = 20;
+		legendHeight=numBoxes*16+scrollAreaHeight + specsHeight + e + messageHeight + 4;
+		messageBox.setBounds(2,legendHeight-messageHeight-7,legendWidth-6, messageHeight);
+	}
+
+	public void setMessage(String s) {
+		if (s==null || s.equals("")) {
+			//messageBox.setBackground(ColorDistribution.light);
+			messageBox.setText("\n");
+			reviseBounds();
+		}
+		else {
+			//messageBox.setBackground(Color.white);
+			messageBox.setText(s);
+			reviseBounds();
+		}
+	}
+	public void onHold() {
+		holding = true;
+	}
+
+	public void offHold() {
+		holding = false;
+	}
+}
+
+class TCMPanel extends Panel {
+	String message = "";
+	StringInABox box;
+	public TCMPanel(){
+		super();
+		box =  new StringInABox("", null, getBounds().width);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		box.setWidth(w);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		box.setWidth(w);
+	}
+	public int getHeightNeeded(){
+		return box.getHeight();
+	}
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		box.setFont(g.getFont());
+		box.draw(g,0, 0);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setText(String s) {
+		message = s;
+		box.setString(s);
+		repaint();
+	}
+}
+
+
diff --git a/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterHistory.java b/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterHistory.java
new file mode 100644
index 0000000..e033e93
--- /dev/null
+++ b/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterHistory.java
@@ -0,0 +1,984 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.TraceCharacterHistory;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class TraceCharacterHistory extends TreeDisplayAssistantMA {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharHistorySource.class, getName() + " needs a source of character histories.",
+				"The source of a traced history is be default a reconstruction from a supplied character distribution.  Afterwards you may choose an alternative source using the Character History Source submenu");
+		EmployeeNeed e3 = registerEmployeeNeed(DisplayStatesAtNodes.class, getName() + " needs a method to display the results.",
+				"The method to display results can be selected in the Trace Display Mode submenu");
+		EmployeeNeed e4 = registerEmployeeNeed(TraceCharacterInit.class, getName() + " uses assistant modules to extend the analysis.",
+				"These assistant modules are arranged automatically by " + getName());
+	}
+	CharHistorySource historyTask;
+	DisplayStatesAtNodes displayTask;
+	private CharacterHistory currentHistory=null;
+	private Tree currentTree=null;
+	private Taxa currentTaxa=null;
+	int currentChar=0;
+	long currentMapping = 0;
+	int lastCharRetrieved = -1;
+	private String currentCharacterName;
+	MesquiteString historyTaskName;
+	MesquiteString displayTaskName;
+	public MesquiteBoolean showLegend, showWindow;
+	int initialOffsetX=MesquiteInteger.unassigned;
+	int initialOffsetY= MesquiteInteger.unassigned;
+	int initialLegendWidth=MesquiteInteger.unassigned;
+	int initialLegendHeight= MesquiteInteger.unassigned;
+	Vector traces;
+	MesquiteCommand htC, dtC;
+	MesquiteBoolean showStateWeights;
+	MesquiteInteger colorMode;
+	boolean suspend = false;
+	MesquiteMenuItemSpec propWeight = null;
+	MesquiteMenuItemSpec  revertColorsItem;
+	MesquiteMenuItemSpec  setColorsAsDefaultItem;
+	MesquiteMenuItemSpec  binsMenuItem, numBinsMenuItem;
+	MesquiteSubmenuSpec colorSubmenu;
+	double[] binBoundaries;
+	double[] usedBoundaries;
+	boolean enableStore = false;  //should be false for release
+	Point[] whichColorsModified = new Point[64];
+	Color[] newColors = new Color[64];
+	String startingColors = null;
+	MesquiteString colorModeName;
+	String[] colorModeNames;
+	MesquiteModule windowBabySitter;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showLegend = new MesquiteBoolean(true);
+		showWindow = new MesquiteBoolean(false);
+		// todo: if hit goaway, then set showWindow to false and adjust menu checkmark;
+		// correct size to begin with
+		// snapshot
+		suspend = MesquiteThread.isScripting();
+
+		historyTask = (CharHistorySource)hireNamedEmployee(CharHistorySource.class, "#RecAncestralStates");
+		if (historyTask == null)
+			historyTask = (CharHistorySource)hireEmployee(CharHistorySource.class, "Source of character histories to trace");
+		if (historyTask == null) {
+			return sorry(getName() + " couldn't start because source of character histories not obtained.");
+		}
+		historyTaskName = new MesquiteString(historyTask.getName());
+		traces = new Vector();
+		displayTask = (DisplayStatesAtNodes)hireEmployee(DisplayStatesAtNodes.class, null);
+		if (displayTask == null) {
+			return sorry(getName() + " couldn't start because display module not obtained.");
+		}
+		dtC = makeCommand("setDisplayMode",  this);
+		displayTask.setHiringCommand(dtC);
+		makeMenu("Trace");
+		resetContainingMenuBar();
+		displayTaskName = new MesquiteString(displayTask.getName());
+
+		htC = makeCommand("setHistorySource",  this);
+		if (numModulesAvailable(CharHistorySource.class)>1) {
+			historyTask.setHiringCommand(htC);
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character History Source", htC, CharHistorySource.class);
+			mss.setSelected(historyTaskName);
+		}
+		MesquiteMenuItemSpec mm = addMenuItem( "Next " + historyTask.getHistoryTypeName(), makeCommand("nextCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_RIGHT); //right
+		mm = addMenuItem( "Previous " + historyTask.getHistoryTypeName(), makeCommand("previousCharacter",  this));
+		mm.setShortcut(KeyEvent.VK_LEFT); //right
+		addMenuItem( "Choose " + historyTask.getHistoryTypeName(), makeCommand("chooseCharacter",  this));
+		if (enableStore)
+			addMenuItem( "Store History...", makeCommand("storeHistory",  this));
+		addCheckMenuItem(null, "Show Legend", makeCommand("toggleShowLegend",  this), showLegend);
+		MesquiteSubmenuSpec msDT = addSubmenu(null, "Trace Display Mode", dtC, DisplayStatesAtNodes.class); 
+		msDT.setSelected(displayTaskName);
+
+		colorSubmenu = addSubmenu(null, "Colors");
+
+		colorMode = new MesquiteInteger(0);
+		ListableVector f  = new ListableVector();
+		colorModeNames = new String[5];
+		colorModeNames[0] = "Full Colors";
+		colorModeNames[1] = "Grayscale";
+		colorModeNames[2] = "Redscale";
+		colorModeNames[3] = "Greenscale";
+		colorModeNames[4] = "Bluescale";
+		colorSubmenu.setEnabled(false);
+
+		for (int i= 0; i<colorModeNames.length; i++)
+			f.addElement(new MesquiteString(colorModeNames[i]), false);
+		MesquiteSubmenuSpec mcms = addSubmenu(null, "Colors", makeCommand("setColorMode", this), f);
+		colorModeName = new MesquiteString(colorModeNames[colorMode.getValue()]);
+		mcms.setSelected(colorModeName);
+
+		numBinsMenuItem = addMenuItem("Set Number of Bins...", makeCommand("setNumBins", this));
+		numBinsMenuItem.setEnabled(false);
+		binsMenuItem = addMenuItem("Set Bin Boundaries...", makeCommand("setBins", this));
+		binsMenuItem.setEnabled(false);
+		setColorsAsDefaultItem = addMenuItem("Set Custom Colors as Defaults", makeCommand("saveModColors", this));
+		setColorsAsDefaultItem.setEnabled(false);
+		revertColorsItem = addMenuItem("Revert Default Colors to Factory", makeCommand("revertColors", this));
+		revertColorsItem.setEnabled(false);
+		showStateWeights = new MesquiteBoolean(true);
+		propWeight = addCheckMenuItem(null, "Display Proportional to Weight", makeCommand("toggleWeights", this), showStateWeights);
+		propWeight.setEnabled(historyTask.allowsStateWeightChoice());
+		addCheckMenuItem(null, "Show Differences Window", makeCommand("toggleShowWindow",  this), showWindow);
+		addMenuItem(null, "Export Table of Node Differences...", makeCommand("exportDifferences",  this));
+		MesquiteTrunk.resetMenuItemEnabling();
+		addMenuItem( "Close Trace", makeCommand("closeTrace",  this));
+		addMenuItem( "-", null);
+		boolean someInits = false;
+		hireAllEmployees(TraceCharacterInit.class);
+		Enumeration enumeration=getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TraceCharacterInit) {
+				TraceCharacterInit init = (TraceCharacterInit)obj;
+				init.setCharacterHistoryContainers(traces);
+				someInits = true;
+			}
+		}
+		loadPreferences();
+		return true;
+	}
+	MesquiteHTMLWindow window;
+	void initiateWindow(){
+		if (window == null) {
+			windowBabySitter = hireNamedEmployee (WindowHolder.class, "#WindowBabysitter");
+			if (windowBabySitter == null)
+				return;
+			window = new MesquiteHTMLWindow(windowBabySitter, null, "Trace Character", false);
+			window.setBackEnabled(false);
+			windowBabySitter.setModuleWindow(window);
+		}
+		window.setText(getTracesText());
+		window.setPopAsTile(true);
+		window.setPreferredPopoutWidth(300);
+		window.popOut(true);
+		lastWindowStatePopped = true;
+		window.setVisible(true);
+		window.show();
+		window.setWindowSize(300, MesquiteInteger.unassigned);
+		resetAllMenuBars();
+
+	}
+	boolean lastWindowStatePopped = true;
+	int resetCount = 0;
+	/*.................................................................................................................*/
+	void resetWindow(){
+		if (window != null) {
+			if (showWindow.getValue()){
+				if (!window.isVisible()){
+					window.setVisible(true);
+				}
+
+				if (lastWindowStatePopped && !window.isPoppedOut()){
+					window.setPopAsTile(true);
+					window.setPreferredPopoutWidth(300);
+					window.popOut(true);
+				}
+				
+				window.setText(getTracesText());
+			}
+			else {
+				lastWindowStatePopped = window.isPoppedOut();
+				window.setVisible(false);
+			}
+		}
+	}
+	String getTracesText(){
+		StringBuffer sb = new StringBuffer();
+		sb.append("<h2>Trace Character</h2>");
+		sb.append(getTraceHTMLAllOperators());
+		sb.append("<p>You can see the node numbers by going to the Tree Window and selecting the menu item Display>Show Node Numbers, " 
+		+ "or by looking at the text view of the Tree Window (menu item Window>View Mode>Text.");
+		return sb.toString();
+		
+	}
+	public boolean suppliesWritableResults(){
+		return traces.size()<2;
+	}
+	public Object getWritableResults(){
+		if (traces == null || traces.size() != 1)
+			return null;
+		TraceCharacterOperator trace = (TraceCharacterOperator)traces.elementAt(0);
+		if (trace.history == null)
+			return null;
+		String results = historyTask.getName();
+
+		results += "\t" + trace.history.toStringWithDetails();
+		return results;
+	}
+
+	public Object getResultsHeading(){
+		if (traces.size() != 1)
+			return null;
+		TraceCharacterOperator trace = (TraceCharacterOperator)traces.elementAt(0);
+		String results = historyTask.getName();
+		return results;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == displayTask || employee == historyTask)  
+			iQuit();
+		else if (employee == windowBabySitter){
+			windowBabySitter = null;
+			showWindow.setValue(false);
+			window = null;
+			lastWindowStatePopped = true;
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		currentTaxa = treeDisplay.getTaxa();
+		TraceCharacterOperator newTrace = new TraceCharacterOperator(this, treeDisplay);
+		traces.addElement(newTrace);
+		if (startingColors != null){
+			String command = parser.getFirstToken(startingColors);
+			String arguments = parser.getRemaining();
+			doCommand(command, arguments, CommandChecker.defaultChecker);
+		}
+		return newTrace;
+	}
+	/*.................................................................................................................*/
+	public boolean showLegend(){
+		return showLegend.getValue();
+	}
+	public int getInitialOffsetX(){
+		return initialOffsetX;
+	}
+	public int getInitialOffsetY(){
+		return initialOffsetY;
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("startingColors".equalsIgnoreCase(tag)) {
+			startingColors = StringUtil.cleanXMLEscapeCharacters(content);
+			if (StringUtil.blank(startingColors))
+				startingColors = null;
+		}
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(20);
+		if (startingColors == null)
+			StringUtil.appendXMLTag(buffer, 2, "startingColors", "");  
+		else
+			StringUtil.appendXMLTag(buffer, 2, "startingColors", startingColors);  
+
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend ");
+		temp.addLine("setDisplayMode ",displayTask);
+		temp.addLine("setHistorySource ",historyTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		if (binBoundaries != null) {
+			temp.addLine("setNumBins " + (binBoundaries.length+1));
+			String s = "";
+			for (int i= 0;  i< binBoundaries.length; i++)
+				s += " " + MesquiteDouble.toString(binBoundaries[i]);
+			temp.addLine("setBins " + s);
+		}
+
+		temp.addLine("setMapping " + CharacterStates.toExternalLong(currentMapping));
+		temp.addLine("toggleShowLegend " + showLegend.toOffOnString());
+		if (showWindow.getValue())
+			temp.addLine("toggleShowWindow " + showWindow.toOffOnString(), windowBabySitter);
+			
+		temp.addLine("setColorMode " + colorMode.getValue());
+		temp.addLine("toggleWeights " + showStateWeights.toOffOnString());
+		TraceCharacterOperator tco = (TraceCharacterOperator)traces.elementAt(0);
+		if (tco!=null && tco.traceLegend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.traceLegend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.traceLegend.getOffsetY());
+			temp.addLine("setLegendWidth " + tco.traceLegend.getLegendWidth()); //Should go operator by operator!!!
+			temp.addLine("setLegendHeight " + tco.traceLegend.getLegendHeight());
+		}
+		temp.addLine("resume ");
+		if (tco!=null && tco.traceLegend!=null) {
+			temp.addLine(tco.traceLegend.getModColorsCommand());
+		}
+		return temp;
+	}
+	boolean suspendCommandReceived = false;
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to display character history", "[name of module]", commandName, "setDisplayMode")) {
+			DisplayStatesAtNodes temp=  (DisplayStatesAtNodes)replaceEmployee(DisplayStatesAtNodes.class, arguments, "Display mode", displayTask);
+			if (temp!=null) {
+				displayTask= temp;
+				displayTask.setHiringCommand(dtC);
+				displayTaskName.setValue(displayTask.getName());
+				resetFromScratchAllTraceOperators();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+			return displayTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets modified colors", "", commandName, "modifyColors")) {
+			pos.setValue(0); 
+			int i = 0; 
+			whichColorsModified = new Point[64];
+			newColors = new Color[64];
+			int count = 0;
+			while (MesquiteInteger.isCombinable(i= MesquiteInteger.fromString(arguments, pos)) && count<64){
+				int j =  MesquiteInteger.fromString(arguments, pos);
+				int red =  MesquiteInteger.fromString(arguments, pos);
+				int green =  MesquiteInteger.fromString(arguments, pos);
+				int blue =  MesquiteInteger.fromString(arguments, pos);
+				if (MesquiteInteger.isCombinable(j) && MesquiteInteger.isCombinable(red) && MesquiteInteger.isCombinable(green) && MesquiteInteger.isCombinable(blue)){
+					newColors[count] = new Color(red, green, blue);
+					whichColorsModified[count++] = new Point(i, j);
+				}
+			}
+			if (count>0){
+				revertColorsItem.setEnabled(true);
+				setColorsAsDefaultItem.setEnabled(true);
+				MesquiteTrunk.resetMenuItemEnabling();
+				notifyIncorpModColorsAllTO();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Reverts colors to defaults", "", commandName, "revertColors")) {
+			revertColorsAllTO();
+			revertColorsItem.setEnabled(false);
+			startingColors = null;
+			storePreferences();
+			setColorsAsDefaultItem.setEnabled(false);
+			MesquiteTrunk.resetMenuItemEnabling();
+			parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Remembers Modified Colors", "", commandName, "saveModColors")) {
+			if (!MesquiteThread.isScripting())
+				alert("This saves your currently modified colours as new defaults");  
+			storePreferences();
+
+			parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the legend is shown", "[on = show; off]", commandName, "toggleShowLegend")) {
+			showLegend.toggleValue(parser.getFirstToken(arguments));
+			toggleLegendAllTraceOperators();
+			if (MesquiteThread.isScripting() && !suspendCommandReceived){ //must be old script
+				suspend = false;
+				recalculateAllTraceOperators(true);  
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Exports a text file summarizing differences from one node to the next", null, commandName, "exportDifferences")) {
+			String s = getTraceTableAllOperators();
+			if (StringUtil.blank(s))
+				discreetAlert("Sorry, there are no traced histories with states");
+			else {
+				String where = MesquiteFile.saveFileAsDialog("Save table of nodes whose reconstructed state(s) differ from those of their ancestors");
+				if (!StringUtil.blank(where))
+					MesquiteFile.putFileContents(where, s, false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the trace window is shown", "[on = show; off]", commandName, "toggleShowWindow")) {
+			showWindow.toggleValue(parser.getFirstToken(arguments));
+			if (showWindow.getValue() && window == null)
+				initiateWindow();
+			else
+				resetWindow();
+			return windowBabySitter;
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the weights on states are shown (e.g. relative frequencies or likelihoods)", "[on; off]", commandName, "toggleWeights")) {
+			showStateWeights.toggleValue(parser.getFirstToken(arguments));
+			resetAllTraceOperators();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to use grayscale if continuous", "[on; off]", commandName, "toggleGray")) {
+			String arg = parser.getFirstToken(arguments);
+			if (arg != null && arg.equalsIgnoreCase("on")){
+				colorMode.setValue(1);
+				colorModeName.setValue(colorModeNames[1]);
+				resetAllTraceOperators();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets colorMode if continuous", "[on; off]", commandName, "setColorMode")) {
+			int w = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (w>=0 && w< colorModeNames.length) {
+				colorMode.setValue(w);
+				colorModeName.setValue(colorModeNames[w]);
+				resetColorsAllTraceOperators();
+				if (!MesquiteThread.isScripting()){
+					resetAllTraceOperators();
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets number of bins for continuous", "[number of bins]", commandName, "setNumBins")) {
+
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			int numBins = MesquiteInteger.unassigned;
+			if (binBoundaries != null) 
+				numBins = binBoundaries.length+1;
+			if (!MesquiteInteger.isCombinable(newNum)) {
+				MesquiteInteger io = new MesquiteInteger(numBins);
+
+				boolean b = QueryDialogs.queryInteger(containerOfModule(), "Set number of bins", "Number of bins for continuous character:\n\n(Enter \"?\" to indicate default binning)", null, true, io);
+
+				if (!b)
+					return null;
+				newNum = io.getValue();
+			}
+			if (!MesquiteInteger.isCombinable(newNum))
+				binBoundaries = null;
+			else if (newNum-1>=1 && newNum-1<50 && (newNum!=numBins || binBoundaries == null || binBoundaries.length+1 != newNum)){
+				binBoundaries = new double[newNum-1];
+				DoubleArray.deassignArray(binBoundaries);
+			}
+
+
+
+			resetAllTraceOperators();
+			parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets bins for continuous", "[vector of bins]", commandName, "setBins")) {
+			boolean set = false;
+			double binEdge = MesquiteDouble.unassigned;
+			pos.setValue(0);
+			int count = 0;
+			while (MesquiteDouble.impossible != (binEdge = MesquiteDouble.fromString(arguments, pos))){
+				if (count <binBoundaries.length)
+					binBoundaries[count++] = binEdge;
+				set = true;
+			}
+			if (set)
+				return null;
+
+			double[] qBins = queryBins(binBoundaries);
+			if (qBins != null)
+				binBoundaries = qBins;
+
+			resetAllTraceOperators();
+			parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+			suspendCommandReceived = true;
+		}
+		else if (checker.compare(this.getClass(), "Resume calculations", null, commandName, "resume")) {
+			suspend = false;
+			suspendCommandReceived = false;
+			recalculateAllTraceOperators(true);
+			parametersChanged();
+		}
+
+		/*  The following is disabled for the moment, as storing and retrieving of character histories is not yet supported */
+		else if (enableStore && checker.compare(this.getClass(), "Stores the current character history", null, commandName, "storeHistory")) {
+			//todo: if more than one traced, query user which one to store��������������������
+			TraceCharacterOperator tco = (TraceCharacterOperator)traces.elementAt(0);
+			if (tco!=null && tco.traceLegend!=null && tco.history!=null && tco.myTree!=null) {
+				CharacterHistory history = tco.history;
+				CharacterHistory cloned = history.clone(null);
+
+				Tree tree = tco.myTree.cloneTree();
+				String s = MesquiteString.queryString(containerOfModule(), "Store History" , "Name of History: ", history.getName() );
+				if (s==null)
+					return null;
+				cloned.setName(s);
+				StoredCharacterHistory sHistory = new StoredCharacterHistory(cloned, tree);
+				if (sHistory!=null) {
+					sHistory.setName(s);
+					sHistory.addToFile( getProject().getHomeFile(), getProject(), findElementManager(StoredCharacterHistory.class));  //TODO: should allow user to choose if more than one file
+					getProject().addFileElement(sHistory);
+				} //TODO: should set current tree to show this one if stored trees used
+			}
+		}
+		/*  	*/
+		else if (checker.compare(this.getClass(), "Sets initial horizontal offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetX")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+				Enumeration e = traces.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TraceCharacterOperator) {
+						TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+						if (tCO.traceLegend!=null)
+							tCO.traceLegend.setOffsetX(offset);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets initial vertical offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetY")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+				Enumeration e = traces.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TraceCharacterOperator) {
+						TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+						if (tCO.traceLegend!=null)
+							tCO.traceLegend.setOffsetY(offset);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets initial width of legend", "[width in pixels]", commandName, "setLegendWidth")) {
+			int x= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(x)) {
+				initialLegendWidth = x;
+				if (initialLegendWidth<50)
+					initialLegendWidth=50;
+				Enumeration e = traces.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TraceCharacterOperator) {
+						TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+						if (tCO.traceLegend!=null)
+							tCO.traceLegend.setLegendWidth(x);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets initial height of legend", "[height in pixels]", commandName, "setLegendHeight")) {
+			int x= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(x)) {
+				initialLegendHeight = x;
+				if (initialLegendHeight<50)
+					initialLegendHeight=50;
+				Enumeration e = traces.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TraceCharacterOperator) {
+						TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+						if (tCO.traceLegend!=null)
+							tCO.traceLegend.setLegendHeight(x);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying character histories", "[name of module]", commandName, "setHistorySource")) {
+			CharHistorySource temp =  (CharHistorySource)replaceEmployee(CharHistorySource.class, arguments, "Source of character histories", historyTask);
+			if (temp!=null) {
+				historyTask=  temp;
+				historyTask.setHiringCommand(htC);
+				historyTaskName.setValue(historyTask.getName());
+				propWeight.setEnabled(historyTask.allowsStateWeightChoice());
+				MesquiteTrunk.resetMenuItemEnabling();
+				currentChar=0;
+				resetAllTraceOperators();
+				recalculateAllTraceOperators(true);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+			return historyTask;
+		}
+		else if (checker.compare(this.getClass(), "NOT YET USED", null, commandName, "newAssistant")) {
+			/* preparing for assistants to explore character correlation etc. based on reconstruction or shown character
+    	 		incrementMenuResetSuppression();
+    	 		TraceAssistant ntt= (TraceAssistant)hireNamedEmployee(TraceAssistant.class, arguments);
+			decrementMenuResetSuppression();
+			if (ntt!=null) {
+    	 			ntt.setUseMenubar(false);
+				Enumeration e = traces.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TraceLegendOperator) {
+						TraceLegendOperator tLO = (TraceLegendOperator)obj;
+						???????
+			 		}
+				}
+				resetContainingMenuBar();
+			}
+			return ntt;
+			 */
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character history", null, commandName, "nextCharacter")) {
+			if (currentChar>=historyTask.getNumberOfHistories(currentTaxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			recalculateAllTraceOperators(true);
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character history", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=historyTask.getNumberOfHistories(currentTaxa)-1;
+			else
+				currentChar--;
+			recalculateAllTraceOperators(true);
+		}
+
+		else if (checker.compare(this.getClass(), "Queries user about which character history to use", null, commandName, "chooseCharacter")) {
+			int ic=historyTask.queryUserChoose(currentTaxa, " to trace ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				recalculateAllTraceOperators(true);
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Sets which character history to use", "[history number]", commandName, "setCharacter")) {
+			pos.setValue(0);
+
+			int icNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && (ic<=historyTask.getNumberOfHistories(currentTaxa)-1)) {
+				currentChar = ic;
+				recalculateAllTraceOperators(true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which mapping to use", "[mapping number]", commandName, "setMapping")) {
+			pos.setValue(0);
+			int icNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			currentMapping = CharacterStates.toInternalLong(icNum);
+			recalculateAllTraceOperators(false);
+		}
+		else if (checker.compare(this.getClass(), "Returns the number of character histories available in the current character history source", null, commandName, "getNumberOfHistories")) {
+			return new MesquiteInteger(historyTask.getNumberOfHistories(currentTaxa));
+		}
+		else if (checker.compare(this.getClass(), "Turns off trace character", null, commandName, "closeTrace")) {
+			iQuit();
+			resetContainingMenuBar();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	double[] queryBins(double[] bEdges){
+		int numBins = MesquiteInteger.unassigned;
+		if (bEdges != null) 
+			numBins = bEdges.length+1;
+		else
+			numBins = 11;
+		double[] qBinBoundaries = new double[numBins-1];
+		for(int i=0; i<qBinBoundaries.length; i++)
+			qBinBoundaries[i] = MesquiteDouble.unassigned;
+		if (bEdges != null && qBinBoundaries.length == bEdges.length)
+			for(int i=0; i<qBinBoundaries.length; i++)
+				qBinBoundaries[i] = bEdges[i];
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Edges of Bins",buttonPressed);
+		queryDialog.addLargeOrSmallTextLabel("Numerical values are currently in " + numBins + " bins.  Indicate the boundaries between bins.  Use \"?\" to let Mesquite choose the boundary automatically.  Current boundaries are shown at right.");
+		SingleLineTextField[] fields = new SingleLineTextField[qBinBoundaries.length];
+		for (int i = 0; i< qBinBoundaries.length; i++){
+			fields[i] = queryDialog.addTextField("Boundary after bin " + (i+1), MesquiteDouble.toString(qBinBoundaries[i]), 16);
+			if (usedBoundaries != null && i<usedBoundaries.length) {
+				queryDialog.suppressNewPanel();
+				queryDialog.addLabel(MesquiteDouble.toString(usedBoundaries[i]));
+			}
+		}
+		queryDialog.completeAndShowDialog(true);
+		for (int i = 0; i< qBinBoundaries.length; i++){
+
+			qBinBoundaries[i] = MesquiteDouble.fromString(fields[i].getText());
+		}
+		queryDialog.dispose();
+		if (buttonPressed.getValue()==0)
+			return qBinBoundaries;
+		return null;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfHistories(Tree tree) {
+		return historyTask.getNumberOfHistories(tree);
+	}
+	/*.................................................................................................................*/
+	public long getNumberOfMappings(Tree tree) {
+		return historyTask.getNumberOfMappings(tree, currentChar);
+	}
+	/*.................................................................................................................*/
+	public void prepareHistory(Tree tree) {
+		int maxnum = historyTask.getNumberOfHistories(tree);
+		currentTaxa = tree.getTaxa();
+		if (currentChar>= maxnum)
+			currentChar = maxnum-1;
+		if (currentChar<0)
+			currentChar = 0;
+		historyTask.prepareHistory(tree, currentChar);
+		long nummap = historyTask.getNumberOfMappings(tree, currentChar);
+		if (currentMapping>= nummap)
+			currentMapping = nummap-1;
+		if (currentMapping<0)
+			currentMapping = 0;
+		lastCharRetrieved = currentChar;
+	}
+	/*.................................................................................................................*/
+	public CharacterHistory getMapping(Tree tree, MesquiteString resultString) {
+		if (!MesquiteLong.isCombinable(currentMapping))
+			currentMapping = 0;
+		CharacterHistory currentHistory = historyTask.getMapping(currentMapping, null, resultString);
+		return currentHistory;
+	}
+	/*.................................................................................................................*/
+	public int getNumberCurrentHistory() {
+		return CharacterStates.toExternal(currentChar);
+	}
+	/*.................................................................................................................*/
+	public long getNumberCurrentMapping() {
+		return CharacterStates.toExternalLong(currentMapping);
+	}
+	/*.................................................................................................................*/
+	public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+		blankAllTraceOperators();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==historyTask) {
+			currentHistory = null;  // to force retrieval of new history
+			if (propWeight.isEnabled() != historyTask.allowsStateWeightChoice()){
+				propWeight.setEnabled(historyTask.allowsStateWeightChoice());
+				MesquiteTrunk.resetMenuItemEnabling();
+			}
+			recalculateAllTraceOperators(true);
+			resetAllTraceOperators();
+			parametersChanged(notification);
+		}
+		else {
+			resetAllTraceOperators();
+		}
+	}
+	/*.................................................................................................................*/
+	public void closeAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.turnOff();
+			}
+		}
+	}
+	boolean Q = true;
+	/*.................................................................................................................*/
+	public void resetColorsAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.resetColors();
+			}
+		}
+	}
+	public String getTraceTableAllOperators() {
+		if (traces==null)
+			return null;
+		Enumeration e = traces.elements();
+		StringBuffer sb = new StringBuffer();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				sb.append("\n");
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.getSummaryTable(sb);
+			}
+		}
+		return sb.toString();
+	}
+	public String getTraceHTMLAllOperators() {
+		if (traces==null)
+			return null;
+		Enumeration e = traces.elements();
+		StringBuffer sb = new StringBuffer();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.getSummaryHTML(sb);
+			}
+		}
+		return sb.toString();
+	}
+	public void resetAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(Q);
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.repaint();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetFromScratchAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				if (tCO.decorator!=null)
+					tCO.decorator.turnOff(); //why is this called?
+				tCO.decorator = null;
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(true);
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.repaint();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void blankAllTraceOperators() {
+		if (traces==null)
+			return;
+		currentHistory = null;  // to force retrieval of new observedStates
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				if (tCO.traceLegend!=null){
+					tCO.traceLegend.setMessage("");
+					tCO.traceLegend.setSpecsMessage("Calculating...");
+				}
+			}
+		}
+	}
+	public void calculationsDone(){
+		resetWindow();
+	}
+	/*.................................................................................................................*/
+	public void recalculateAllTraceOperators(boolean doPreps) {
+		if (traces==null || suspend)
+			return;
+		blankAllTraceOperators();
+		currentHistory = null;  // to force retrieval of new observedStates
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.doCalculations(doPreps);
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public void notifyIncorpModColorsAllTO() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.incorporateModColors();
+				tCO.doCalculations(true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void revertColorsAllTO() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.revertColors();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void toggleReconstructAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				tCO.toggleReconstruct();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void toggleLegendAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TraceCharacterOperator) {
+				TraceCharacterOperator tCO = (TraceCharacterOperator)obj;
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(Q);
+				if (tCO.traceLegend!=null)
+					tCO.traceLegend.setVisible(showLegend.getValue());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		closeAllTraceOperators();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Trace Character History";
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Traces a history of character evolution on the nodes of a drawn tree.";
+	}
+}
+
+
diff --git a/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterOperator.java b/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterOperator.java
new file mode 100644
index 0000000..4e2eced
--- /dev/null
+++ b/Source/mesquite/ancstates/TraceCharacterHistory/TraceCharacterOperator.java
@@ -0,0 +1,809 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ancstates.TraceCharacterHistory;
+
+import java.awt.*;
+import java.util.Vector;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.cont.lib.ContinuousState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+public class TraceCharacterOperator extends TreeDisplayDrawnExtra implements CharHistoryContainer {
+	Tree myTree;
+	TraceCharacterHistory traceModule;
+	public TraceLegend traceLegend;
+	public CharacterHistory history;
+	//private CharacterDistribution observedStates;
+	public TreeDecorator decorator;
+	private boolean holding = false;
+	boolean firstTime = true;
+	MesquiteColorTable colorTable = MesquiteColorTable.DEFAULTCOLORTABLE.cloneColorTable(); 
+	public TraceCharacterOperator (TraceCharacterHistory ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		traceModule = ownerModule;
+	}
+	public CharacterHistory getCharacterHistory(){
+		return history;
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree){
+		myTree = tree;
+		if (tree!=null && (traceModule.historyTask!=null) && (traceModule.displayTask!=null) && !traceModule.suspend) {
+			if (traceLegend != null)
+				traceLegend.setSpecsMessage("Calculating...");
+			doCalculations(true);
+		}
+	}
+	/*.................................................................................................................*/
+	public void toggleReconstruct(){
+		if (traceLegend!=null)
+			traceLegend.reviseBounds();
+	}
+	/*.................................................................................................................*/
+	public   Tree getTree(){
+		return myTree;
+	}
+	/*.................................................................................................................*/
+	public   Taxa getTaxa(){
+		if (myTree !=null)
+			return myTree.getTaxa();
+		else
+			return null;
+	}
+	CharacterState state=null;
+
+	/*
+	void fillWithObserved(Tree tree, int node, CharacterHistory history, CharacterDistribution observed){
+		if (tree.nodeIsTerminal(node)){
+			state = observed.getCharacterState(state, tree.taxonNumberOfNode(node));
+			history.setCharacterState(node, state);
+		}
+		else {
+			state = observed.getCharacterState(state, 1); //merely to get an object to fill
+			state.setToUnassigned();
+			history.setCharacterState(node, state);
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				fillWithObserved(tree, daughter, history, observed);
+	}
+	 */
+	MesquiteString resultString = new MesquiteString();
+	/*.................................................................................................................*/
+	public void doCalculations(boolean doPreps) {
+		holding = true;
+		if (myTree == null) {
+		}
+		else {
+			traceModule.displayTask.onHold();
+			if (doPreps) {
+				traceModule.prepareHistory(myTree);
+			}
+			if (traceLegend==null  && traceModule.showLegend.getValue()) {
+				traceLegend = new TraceLegend(traceModule, this);
+				traceLegend.adjustScroll(traceModule.getNumberCurrentHistory(), traceModule.getNumberOfHistories(myTree)); 
+				traceLegend.adjustMappingScroll(traceModule.getNumberCurrentMapping(), traceModule.getNumberOfMappings(myTree)); 
+				addPanelPlease(traceLegend);
+			}
+			if (traceLegend!=null && traceModule.showLegend.getValue()) {
+				traceLegend.onHold();
+				traceLegend.adjustScroll(traceModule.getNumberCurrentHistory(), traceModule.getNumberOfHistories(myTree));
+				traceLegend.adjustMappingScroll(traceModule.getNumberCurrentMapping(), traceModule.getNumberOfMappings(myTree)); 
+			}
+			resultString.setValue("");
+
+			history = traceModule.getMapping(myTree, resultString);
+			if (history == null){
+				holding = false;
+				return;
+			}
+
+			traceModule.binsMenuItem.setEnabled(history instanceof mesquite.cont.lib.ContinuousHistory);
+			traceModule.numBinsMenuItem.setEnabled(history instanceof mesquite.cont.lib.ContinuousHistory);
+			traceModule.colorSubmenu.setEnabled(history instanceof mesquite.cont.lib.ContinuousHistory);
+			MesquiteColorTable ct = colorTable;
+			colorTable = history.getColorTable(colorTable);
+			colorTable.setPreferredBinBoundaries(traceModule.binBoundaries);
+			if (history!=null) 
+				history.prepareColors(myTree, myTree.getRoot());
+			if (history instanceof mesquite.cont.lib.ContinuousHistory){
+				mesquite.cont.lib.ContinuousHistory cHistory = (mesquite.cont.lib.ContinuousHistory)history;
+				int numBoundaries = 10;
+				if (traceModule.binBoundaries != null)
+					numBoundaries = traceModule.binBoundaries.length;
+				double[] usedBoundaries = new double[numBoundaries];
+				for (int i = 0; i<numBoundaries; i++)  //starting at 1 because getBinBoundaries reports starting and ending
+					usedBoundaries[i] = cHistory.getBinBoundary( i, colorTable);
+				traceModule.usedBoundaries = usedBoundaries;
+			}
+			if (ct != colorTable && traceLegend != null)
+				for (int i = 0; i<64; i++)
+					for (int k= 0; k<64; k++)
+						traceLegend.modifiedColors[i][k] = false;
+
+			if (traceLegend != null && traceModule != null && colorTable != null && colorTable.setColorEnabled() && !modColorsIncorporated && traceModule.whichColorsModified != null){
+				if (traceModule.whichColorsModified != null && traceModule.newColors != null)
+					for (int box = 0; box<64; box++)
+						traceLegend.resetColor(traceModule.whichColorsModified[box], traceModule.newColors[box]);
+				modColorsIncorporated = true;
+				traceModule.startingColors = traceLegend.getModColorsCommand();
+			}
+			String s = "";
+			if (!traceModule.showStateWeights.getValue())
+				resultString.append(" (NOTE: the graphic display of reconstruction is NOT showing the reconstruction proportional to the weights (e.g. likelihoods) of the states)");
+			traceModule.displayTask.offHold();
+			holding = false;
+			treeDisplay.pleaseUpdate(firstTime);
+			firstTime = traceModule.Q;
+			if (traceLegend!=null && traceModule.showLegend.getValue()) {
+				traceLegend.offHold();
+				traceLegend.repaint();
+			}
+		}
+		traceModule.calculationsDone();
+	}
+	void revertColors(){
+		for (int i = 0; i<64; i++)
+			for (int k= 0; k<64; k++)
+				traceLegend.modifiedColors[i][k] = false;
+
+		resetColors();
+		modColorsIncorporated = true;
+
+	}
+	boolean modColorsIncorporated = true;
+	public void incorporateModColors(){
+		modColorsIncorporated = false;
+	}
+	public void cursorEnterBranch(Tree tree, int N, Graphics g) {
+		if (traceModule.showLegend.getValue() && traceLegend!=null && history!=null){
+			if (tree.nodeIsTerminal(N)){
+				taxonMessage( tree, tree.taxonNumberOfNode(N));
+			}
+			else {
+				String expl = history.getExplanation();
+				if (expl == null)
+					expl = "";
+				else expl += "\n";
+				traceLegend.setMessage(expl + history.toString(N, "\n"));
+			}
+		}
+		if (treeDisplay != null)
+			treeDisplay.requestFocus();
+	}
+	public void cursorExitBranch(Tree tree, int N, Graphics g) {
+		if (traceModule.showLegend.getValue() && traceLegend!=null)
+			traceLegend.setMessage("");
+		if (treeDisplay != null)
+			treeDisplay.requestFocus();
+	}
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g) {
+		taxonMessage(tree, M);
+	}
+	public void cursorExitTaxon(Tree tree, int M, Graphics g) {
+		if (traceModule.showLegend.getValue() && traceLegend!=null)
+			traceLegend.setMessage("");
+	}
+
+	private void taxonMessage(Tree tree, int it){
+		if (traceModule.showLegend.getValue() && traceLegend!=null && history!=null && history.getObservedStates()!=null){
+			if (it == -1)
+				traceLegend.setMessage("");
+			else {
+
+				String h = history.getExplanation();
+				if (h == null)
+					h = "";
+				else h += "\n";
+				int node = tree.nodeOfTaxonNumber(it);
+				h += history.toString(node, "\n");
+
+				traceLegend.setMessage("Observed states: " + history.getObservedStates().toString(it, "\n") + "\n" + h);
+			}
+		}
+	}
+	public void cursorMove(Tree tree, int x, int y, Graphics g) {
+		int boxFound = treeDisplay.getTreeDrawing().findTerminalBox(tree,  x, y);
+		taxonMessage(tree, boxFound);
+	}
+	public void resetColors(){
+		
+		if (traceModule.colorMode.getValue()==1)
+			colorTable = MesquiteColorTable.DEFAULTGRAYTABLE.cloneColorTable();
+		else if (traceModule.colorMode.getValue()==2)
+			colorTable = MesquiteColorTable.DEFAULTREDTABLE.cloneColorTable();
+		else if (traceModule.colorMode.getValue()==3)
+			colorTable = MesquiteColorTable.DEFAULTGREENTABLE.cloneColorTable();
+		else if (traceModule.colorMode.getValue()==4)
+			colorTable = MesquiteColorTable.DEFAULTBLUETABLE.cloneColorTable();
+		else
+			colorTable = MesquiteColorTable.DEFAULTCOLORTABLE.cloneColorTable();
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (!holding) {
+			if (traceModule.historyTask!=null) {
+				if (decorator==null)
+					decorator = traceModule.displayTask.createTreeDecorator(treeDisplay, this);
+				if (decorator==null)
+					return;
+				decorator.useColorTable(colorTable);
+				if (history !=null)
+					decorator.drawOnTree(tree, drawnRoot,  history, history.getObservedStates(), traceModule.showStateWeights, g); 
+				if (traceModule.showLegend.getValue()  && traceLegend!=null) {
+					if (history!=null) {
+						history.prepareColors(tree, drawnRoot);
+						traceLegend.setStates(history);
+					}
+					traceLegend.adjustLocation();
+					if (!traceLegend.isVisible())
+						traceLegend.setVisible(true);
+				}
+			}
+		}
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (history!=null)
+			return history.toString(node, ", ");
+		else
+			return null;
+	}
+	
+	CharacterState htmlNodeState, htmlAncestorState;
+	void getChangesHTML(Tree tree, int node, CharacterHistory history, StringBuffer sb){
+		if (tree.getRoot() != node){
+			htmlNodeState = history.getCharacterState(htmlNodeState, node); 
+			if (tree.nodeIsInternal(node))
+				adjustConservatism(htmlNodeState);
+			htmlAncestorState = history.getCharacterState(htmlAncestorState, tree.motherOfNode(node)); 
+			adjustConservatism(htmlAncestorState);
+			if (htmlNodeState != null && htmlAncestorState != null && !htmlNodeState.equals(htmlAncestorState)){
+				sb.append("<tr><td>" + node +"</td><td>" + htmlAncestorState.toDisplayString() +"</td><td>" + htmlNodeState.toDisplayString() + "</td>");
+				if (htmlNodeState instanceof CategoricalState){
+					sb.append("<td>");
+					CategoricalState cN = (CategoricalState)htmlNodeState;
+					CategoricalState cA = (CategoricalState)htmlAncestorState;
+					if (!CategoricalState.statesShared(cN.getValue(), cA.getValue()))
+							sb.append("*");
+					sb.append("</td>" );
+				}
+				sb.append("</tr>" );
+			}
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			getChangesHTML(tree, daughter, history, sb);
+	}
+
+	/**return a text version of information at node*/
+	public void getSummaryHTML(StringBuffer sb){
+		if (history!=null && myTree != null && sb!= null){
+			htmlNodeState = history.getCharacterState(htmlNodeState, myTree.getRoot()); 
+			sb.append("State at root: " + htmlNodeState.toDisplayString());
+			sb.append("<p>Table of nodes whose reconstructed state or state sets differ from those of their immediate ancestors:");
+			sb.append("<table border=\"1\">");
+			sb.append("<tr><td>node</td><td>state at ancestor</td><td>state at node</td>" );
+			if (htmlNodeState instanceof CategoricalState)
+				sb.append("<td>unambiguous change?</td>");
+			sb.append("</tr>");
+			getChangesHTML(myTree, myTree.getRoot(),  history, sb);
+			sb.append("</table>");
+		}
+
+	}
+	void adjustConservatism(CharacterState state){ //this is a KLUDGE!  Required because reconstruction doesn't set uncertainty bit to represent equivocal, and thus doesn't distinguish true polymorphic ancestors from uncertainty.  Here forced to be uncertain for display sake
+		if (state != null && state instanceof CategoricalState){
+			CategoricalState c = (CategoricalState)state;
+			if (CategoricalState.hasMultipleStates(c.getValue()))
+					c.setUncertainty(true);
+				
+		}
+	}
+	void getChangesAtNodes(Tree tree, int node, CharacterHistory history, StringBuffer sb){
+		if (tree.getRoot() != node){
+			htmlNodeState = history.getCharacterState(htmlNodeState, node); 
+			if (tree.nodeIsInternal(node))
+				adjustConservatism(htmlNodeState);
+			htmlAncestorState = history.getCharacterState(htmlAncestorState, tree.motherOfNode(node)); 
+			adjustConservatism(htmlAncestorState);
+			if (htmlNodeState != null && htmlAncestorState != null && !htmlNodeState.equals(htmlAncestorState)){
+				sb.append("" + node + "\t" + htmlAncestorState.toDisplayString() + "\t" + htmlNodeState.toDisplayString());
+				if (htmlNodeState instanceof CategoricalState){
+					sb.append("\t");
+					CategoricalState cN = (CategoricalState)htmlNodeState;
+					CategoricalState cA = (CategoricalState)htmlAncestorState;
+					if (!CategoricalState.statesShared(cN.getValue(), cA.getValue()))
+							sb.append("*");
+				}
+				
+				sb.append("\n");
+			}
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			getChangesAtNodes(tree, daughter, history, sb);
+	}
+
+	/**return a text version of information at node*/
+	public void getSummaryTable(StringBuffer sb){
+		if (history!=null && myTree != null && sb!= null){
+			htmlNodeState = history.getCharacterState(htmlNodeState, myTree.getRoot()); 
+			sb.append("Tree: " + myTree.getName() + "\n\n");
+			sb.append(resultString.getValue() + "\n\n");
+			sb.append("State at root: " + htmlNodeState.toDisplayString() + "\n");
+			sb.append("Table of nodes whose reconstructed state or state sets differ from those of their immediate ancestor:\n\n");
+			sb.append("node\tstate at ancestor\tstate at node" );
+			if (htmlNodeState instanceof CategoricalState)
+				sb.append("\tunambiguous change?");
+				
+			sb.append("\n");
+			getChangesAtNodes(myTree, myTree.getRoot(),  history, sb);
+		}
+
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		String s = "";
+		if (!traceModule.showStateWeights.getValue())
+			s = " (NOTE: the graphic display of reconstruction is NOT showing the reconstruction proportional to the weights (e.g. likelihoods) of the states)";
+		return resultString.getValue() + s;
+	}
+	public void turnOff(){
+		if (decorator!=null) {
+			decorator.turnOff();
+			decorator = null;
+		}
+		if (traceLegend!=null && treeDisplay!=null){
+			removePanelPlease(traceLegend);
+			traceLegend = null;
+		}
+		super.turnOff();
+	}
+}
+/* ======================================================================== */
+class TraceLegend extends TreeDisplayLegend {
+	private TraceCharacterHistory traceModule;
+	public MiniScroll characterScroll = null;
+	public MiniScroll mappingScroll = null;
+	private TraceCharacterOperator tcOp;
+	private String[] stateNames;
+	private Color[] legendColors;
+	Point[] tableMappings;
+	boolean[][] modifiedColors;
+	private static final int defaultLegendWidth=142;
+	private static final int defaultLegendHeight=120;
+	private int numBoxes=0;
+	private int oldNumChars = 0;
+	private long oldNumMappings = 0;
+	private int oldNumBoxes=0;
+	private int oldCurrentChar = -1;
+	private long oldCurrentMapping = -1;
+	private boolean resizingLegend=false;
+	private TCMPanel messageBox;
+	private SpecsPrintTextArea specsBox;
+	private boolean holding = false;
+	int scrollAreaHeight = 41;
+
+	final int charScrollAreaHeight = 41;
+	final int mapScrollAreaHeight = 0;
+	private int messageHeight = 22;
+	final int defaultSpecsHeight = (14 + MesquiteModule.textEdgeCompensationHeight) * 3;
+	private int specsHeight = defaultSpecsHeight;
+	private int e = 4;
+
+
+	public TraceLegend(TraceCharacterHistory traceModule, TraceCharacterOperator tcOp) {
+		super(tcOp.treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		setVisible(false);
+		legendWidth=defaultLegendWidth;
+		legendHeight=defaultLegendHeight;
+		if (MesquiteInteger.isCombinable(traceModule.initialLegendWidth))
+			legendWidth = traceModule.initialLegendWidth;
+		if (MesquiteInteger.isCombinable(traceModule.initialLegendHeight))
+			legendHeight = traceModule.initialLegendHeight;
+		setOffsetX(traceModule.initialOffsetX);
+		setOffsetY(traceModule.initialOffsetY);
+		this.tcOp = tcOp;
+		this.traceModule = traceModule;
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+		stateNames = new String[64];
+		legendColors = new Color[64];
+		tableMappings = new Point[64];
+		modifiedColors = new boolean[64][64];
+		for (int i=0; i<64; i++) {
+			stateNames[i] = null;
+			legendColors[i] = null;
+			tableMappings[i] = null;
+			for (int j=0; j<64; j++)
+				modifiedColors[i][j] = false;
+		}
+		specsBox = new SpecsPrintTextArea(" ", 2, 2, TextArea.SCROLLBARS_NONE);
+		specsBox.setEditable(false);
+		if (traceModule.showLegend.getValue())
+			specsBox.setVisible(false);
+		specsBox.setBounds(1,scrollAreaHeight +2,legendWidth-2, specsHeight);
+
+		messageBox = new TCMPanel();
+		int mTop = MesquiteInteger.maximum(legendHeight-messageHeight-8, scrollAreaHeight+2)+2;
+		int mHeight = MesquiteInteger.minimum(legendHeight-mTop-8, messageHeight);
+		messageBox.setBounds(2,mTop,legendWidth-6, mHeight);
+		messageBox.setText("\n");
+		try {
+			messageBox.setFocusTraversalKeysEnabled(false);
+		}
+		catch (Error e){
+		}
+		//messageBox.setColor(Color.pink);
+		//messageBox.setBackground(Color.pink);
+		add(messageBox);
+		add(specsBox);
+	}
+
+	public void adjustScroll(int currentCharExternal, int numChars) {
+		if (characterScroll == null) {
+			characterScroll = new MiniScroll( MesquiteModule.makeCommand("setCharacter",  (Commandable)traceModule), false, currentCharExternal, 1,  numChars,"character");
+			add(characterScroll);
+			characterScroll.setLocation(2,18);//18);
+			characterScroll.setColor(Color.blue);
+			repaint();
+			oldNumChars = numChars;
+			oldCurrentChar = currentCharExternal;
+		}
+		else {
+			if (oldNumChars != numChars) {
+				characterScroll.setMaximumValue(numChars);
+				oldNumChars = numChars;
+			}
+			if (oldCurrentChar != currentCharExternal) {
+				characterScroll.setCurrentValue(currentCharExternal);
+				oldCurrentChar = currentCharExternal;
+			}
+		}
+	}
+	public void adjustMappingScroll(long currentMappingExternal, long numMappings) {
+		if (mappingScroll == null) {
+			mappingScroll = new MiniScroll( MesquiteModule.makeCommand("setMapping",  (Commandable)traceModule), false, currentMappingExternal, 1,  numMappings,"mapping");
+			add(mappingScroll);
+			if (characterScroll != null)
+				mappingScroll.setLocation(characterScroll.getBounds().x + getBounds().width + 4,18 + charScrollAreaHeight);//18);
+			else
+				mappingScroll.setLocation(2,18 + charScrollAreaHeight);//18);
+			mappingScroll.setColor(Color.blue);
+			repaint();
+			oldNumMappings = numMappings;
+			oldCurrentMapping = currentMappingExternal;
+		}
+		else {
+			if (oldNumMappings != numMappings) {
+				mappingScroll.setMaximumValueLong(numMappings);
+				oldNumMappings = numMappings;
+			}
+			if (oldCurrentMapping != currentMappingExternal) {
+				mappingScroll.setCurrentValueLong(currentMappingExternal);
+				oldCurrentMapping = currentMappingExternal;
+			}
+		}
+		if (numMappings >1){
+			mappingScroll.setVisible(true);
+			scrollAreaHeight = charScrollAreaHeight + mapScrollAreaHeight;
+			checkComponentSizes();
+		}
+		else {
+			mappingScroll.setVisible(false);
+			scrollAreaHeight = charScrollAreaHeight;
+			checkComponentSizes();
+		}
+	}
+	public void checkComponentSizes(){
+		int oldWidth = legendWidth;
+		int oldHeight = legendHeight;
+		if (characterScroll != null)
+			mappingScroll.setLocation(characterScroll.getBounds().x + characterScroll.getBounds().width + 4,18);//18);
+		else
+			mappingScroll.setLocation(2,18 + charScrollAreaHeight);//18);
+		if (mappingScroll.isVisible() && legendWidth< mappingScroll.getX() + mappingScroll.getWidth())
+			legendWidth=mappingScroll.getX() + mappingScroll.getWidth()+ 4;
+		else if (legendWidth< characterScroll.getX() + characterScroll.getWidth())
+			legendWidth=characterScroll.getX() + characterScroll.getWidth()+ 4;
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		specsBox.setVisible(true);
+		messageHeight = messageBox.getHeightNeeded();
+		if (messageHeight<20)
+			messageHeight = 20;
+		legendHeight=numBoxes*16+scrollAreaHeight + specsHeight + e + messageHeight + 4;
+		int mTop = MesquiteInteger.maximum(legendHeight-messageHeight-8, scrollAreaHeight+2) +2;
+		int mHeight = MesquiteInteger.minimum(legendHeight-mTop-8, messageHeight);
+		messageBox.setBounds(2,mTop,legendWidth-6, mHeight);
+		if (oldWidth != legendWidth || oldHeight != legendHeight || getWidth() != legendWidth || getHeight() != legendHeight){
+			setSize(legendWidth, legendHeight);
+			repaint();
+		}
+	}
+
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (characterScroll !=null)
+			characterScroll.setVisible(b);
+		if (messageBox!=null)
+			messageBox.setVisible(b);
+		if (specsBox!=null)
+			specsBox.setVisible(b);
+	}
+
+	public void setLegendWidth(int w){
+		legendWidth = w;
+	}
+	public void setLegendHeight(int h){
+		legendHeight = h;
+	}
+	public int findBox(int x, int y) {
+		if (numBoxes!=0) {
+			for (int ibox=0; ibox<numBoxes; ibox++) {
+				int top = ibox*16+scrollAreaHeight + specsHeight+ e;
+				if (x >= 4 && y >= top && x <= 24 && y <= top +12)
+					return ibox;
+			}
+		}
+		return -1;
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!holding) {
+			g.setColor(Color.black);
+			if (numBoxes!=0) {
+				for (int ibox=0; ibox<numBoxes; ibox++) {
+					g.setColor(legendColors[ibox]);
+					g.fillRect(4, ibox*16+scrollAreaHeight + specsHeight+ e, 20, 12);
+					g.setColor(Color.black);
+					g.drawRect(4, ibox*16+scrollAreaHeight + specsHeight + e, 20, 12);
+					if (stateNames[ibox]!=null)
+						g.drawString(stateNames[ibox], 28, ibox*16 + specsHeight+scrollAreaHeight + 12 + e);
+				}
+			}
+			g.setColor(Color.cyan);
+			g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+			g.fillRect(legendWidth-6, legendHeight-6, 6, 6);
+			g.drawLine(0, scrollAreaHeight, legendWidth-1, scrollAreaHeight);
+			g.setColor(Color.blue);
+			g.drawString("Trace Character", 4, 14);
+			if (mappingScroll.isVisible()){
+				if (legendWidth< mappingScroll.getX() + mappingScroll.getWidth()) {
+					checkComponentSizes();
+					MesquiteWindow.uncheckDoomed(this);
+					return;
+				}
+				String mtn = "Mapping";
+				if (traceModule.historyTask != null)
+					mtn = traceModule.historyTask.getMappingTypeName();
+				if (characterScroll.isVisible())
+					g.drawString(mtn, 8 + characterScroll.getBounds().width + characterScroll.getBounds().x, 14);
+				else
+					g.drawString(mtn, 4 + 40, 14);
+			}
+			g.setColor(Color.black);
+			if (tcOp.resultString.getValue()!=null && !tcOp.resultString.getValue().equals(specsBox.getText())) {
+
+				specsBox.setText(tcOp.resultString.getValue()); 
+			}
+			if (specsBox.getBackground() != getBackground())
+				specsBox.setBackground(getBackground());
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void print(Graphics g) {
+		if (!traceModule.showLegend.getValue())
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!holding) {
+			int printHeight = legendHeight-1;
+			if (numBoxes!=0) 
+				printHeight = (numBoxes)*16+scrollAreaHeight + specsHeight + e;
+			g.setColor(Color.white);
+
+			g.fillRect(0, 0, legendWidth-1, printHeight);
+			g.setColor(Color.cyan);
+			g.drawRect(0, 0, legendWidth-1, printHeight);
+			g.setColor(Color.black);
+			String info = tcOp.resultString.getValue();
+			StringInABox sib = new StringInABox(info, g.getFont(), legendWidth);
+			sib.draw(g, 4, 4);
+			if (numBoxes!=0) {
+				for (int ibox=0; ibox<numBoxes; ibox++) {
+					g.setColor(legendColors[ibox]);
+					g.fillRect(4, ibox*16+scrollAreaHeight + specsHeight+ e, 20, 12);
+					g.setColor(Color.black);
+					g.drawRect(4, ibox*16+scrollAreaHeight + specsHeight + e, 20, 12);
+					if (stateNames[ibox]!=null)
+						g.drawString(stateNames[ibox], 28, ibox*16 + specsHeight+scrollAreaHeight + 12 + e);
+				}
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+
+	public void setStates(CharacterHistory statesAtNodes){
+		numBoxes = statesAtNodes.getLegendStates(legendColors, stateNames, tableMappings, tcOp.colorTable);
+
+		if (numBoxes!=oldNumBoxes) {
+			reviseBounds();
+			oldNumBoxes=numBoxes;
+		}
+		repaint();
+	}
+	/*-----------------------------*/
+	public String getModColorsCommand(){
+		String s = "modifyColors ";
+		boolean found = false;
+		for (int i = 0; i<64; i++){
+			for (int j = 0; j<64; j++){
+				if (modifiedColors[i][j]) {
+					Color c = tcOp.colorTable.getColorDirect(i, j);
+					if (c == null)
+						return null;
+					s += " " + i + " " + j + "  " + c.getRed() + " " + c.getGreen() + " " + c.getBlue();
+					found = true;
+				}
+			}
+		}
+		if (!found)
+			return null;
+		return s;
+	}
+	public void resetColor(Point tablePoint, Color color){
+		if (color != null && tcOp.colorTable.setColorEnabled()){
+
+			tcOp.colorTable.setColor(tablePoint.x, tablePoint.y, color);
+			modifiedColors[tablePoint.x][tablePoint.y] = true;
+			legendColors[tablePoint.y] = color;
+		}
+
+	}
+	/*-----------------------------*/
+	public void resetColor(int box){
+		if (tableMappings != null && box >= 0 && box <tableMappings.length){
+			Point tablePoint = tableMappings[box];
+			if (tablePoint != null){
+				if (!tcOp.colorTable.setColorEnabled()){
+					tcOp.ownerModule.alert("You aren't able to change the colors for this character");
+					return;
+				}
+				else if (tcOp.colorTable.getMode()==MesquiteColorTable.GRAYSCALE){
+					tcOp.ownerModule.alert("You can't change the gray scale colors");
+					return;
+				}
+				Color color = ColorDialog.queryColor(MesquiteWindow.windowOfItem(this), "Choose Color", "Color for state", tcOp.colorTable.getColor(tablePoint.x, tablePoint.y));
+				if (color != null){
+
+					tcOp.colorTable.setColor(tablePoint.x, tablePoint.y, color);
+					modifiedColors[tablePoint.x][tablePoint.y] = true;
+					legendColors[box] = color;
+					tcOp.treeDisplay.pleaseUpdate(true);
+					tcOp.traceModule.startingColors = getModColorsCommand();
+					tcOp.traceModule.revertColorsItem.setEnabled(true);
+					tcOp.traceModule.setColorsAsDefaultItem.setEnabled(true);
+					MesquiteTrunk.resetMenuItemEnabling();
+					repaint();
+				}
+			}
+		}
+	}
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		int box = findBox(x, y);
+		if (box >=0 && clickCount>=2)
+			resetColor(box);
+	}
+
+	public void legendResized(int widthChange, int heightChange){
+		if ((specsHeight + heightChange)>= defaultSpecsHeight)
+			specsHeight += heightChange;
+		else
+			specsHeight  = defaultSpecsHeight;
+		checkComponentSizes();
+	}
+	public void reviseBounds(){
+		checkComponentSizes();
+		Point where = getLocation();
+		setBounds(where.x,where.y,legendWidth, legendHeight);
+	}
+
+	public void setMessage(String s) {
+		if (s==null || s.equals("")) {
+			//messageBox.setBackground(ColorDistribution.light);
+			messageBox.setText("\n");
+			reviseBounds();
+		}
+		else {
+			//messageBox.setBackground(Color.white);
+			messageBox.setText(s);
+			reviseBounds();
+		}
+	}
+	public void setSpecsMessage(String s) {
+		if (s!=null) {
+			specsBox.setText(s);
+		}
+	}
+	public void onHold() {
+		holding = true;
+	}
+
+	public void offHold() {
+		holding = false;
+	}
+}
+
+class TCMPanel extends Panel {
+	String message = "";
+	StringInABox box;
+	public TCMPanel(){
+		super();
+		box =  new StringInABox("", null, getBounds().width);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		box.setWidth(w);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		box.setWidth(w);
+	}
+	public int getHeightNeeded(){
+		return box.getHeight() + 5;
+	}
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		box.setFont(g.getFont());
+		box.draw(g,0, 0);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setText(String s) {
+		message = s;
+		box.setString(s, getGraphics());
+		repaint();
+	}
+	public void print(Graphics g){
+	}
+	public void printAll(Graphics g){
+	}
+	public void printComponents(Graphics g){
+	}
+}
+
+class SpecsPrintTextArea extends TextArea {
+	public SpecsPrintTextArea(String s, int a, int b, int c){
+		super(s, a, b, c);
+	}
+
+	public void setText(String s){
+		super.setText(s);
+		try {
+			if (isVisible())
+				setCaretPosition(0);
+		}
+		catch (Exception e){
+		}
+	}
+
+}
diff --git a/Source/mesquite/ancstates/UnambigChangesAtNodes/UnambigChangesAtNodes.java b/Source/mesquite/ancstates/UnambigChangesAtNodes/UnambigChangesAtNodes.java
new file mode 100644
index 0000000..319f599
--- /dev/null
+++ b/Source/mesquite/ancstates/UnambigChangesAtNodes/UnambigChangesAtNodes.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.UnambigChangesAtNodes;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class UnambigChangesAtNodes extends NumbersForNodesAndHistory {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public void initialize(Tree tree, MCharactersHistory charsHistory) {
+	}
+
+	public Class getRequiredStateClass(){
+		return CategoricalState.class;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+	MesquiteTree tempTree;
+	/*.................................................................................................................*/
+	public void addToNodeValue(CharacterState cs, CharacterState parentCS, MesquiteNumber sum) {
+		if (sum==null || cs==null || parentCS == null)
+			return;
+		if (!(cs instanceof CategoricalState) || !(parentCS instanceof CategoricalState))
+			return;
+
+		if (cs.isCombinable() && parentCS.isCombinable())  // neither is a gap or missing data or other impossible state
+			if (!((CategoricalState)cs).statesShared((CategoricalState)parentCS)) // no states are shared
+				sum.add(1);
+	}
+	/*.................................................................................................................*/
+	public void visitNodes(int node, Tree tree, CharacterHistory cH, NumberArray result) {
+		if (node != tree.getRoot()){// && tree.numberOfTerminalsInClade(node)>3){
+			MesquiteNumber sum = new MesquiteNumber(0.0);
+			int[] parents = tree.parentsOfNode(node);
+			CharacterState cs = cH.getCharacterState (null, node);
+			for (int i=0;i<parents.length; i++) {
+				CharacterState parentCS = cH.getCharacterState (null, parents[i]);
+				addToNodeValue(cs, parentCS,sum);
+			}
+			result.addValue(node, sum);
+		}
+		if (tree.nodeIsInternal(node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+				visitNodes(d, tree, cH, result);
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, MCharactersHistory charsHistory, NumberArray result, MesquiteString resultString) {
+		if (tree==null || charsHistory==null)
+			return;
+		if (result==null)
+			return;
+		CharacterData data = charsHistory.getParentData();
+		if (!(data instanceof CategoricalData))
+			return;
+		clearResultAndLastResult(result);
+		result.zeroArray();
+		if (resultString!=null)
+			resultString.setValue("");
+		tempTree = new MesquiteTree(tree.getTaxa());
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		for (int ic=0; ic<charsHistory.getNumChars(); ic++) {
+			if (incl == null || incl.isBitOn(ic)) {
+				CharacterHistory cH = charsHistory.getCharacterHistory(ic);
+				visitNodes(tree.getRoot(), tree, cH, result);		
+			}
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+	public String getName() {
+		return "Unambiguous Changes";
+	}
+	public String getExplanation() {
+		return "Counts number of unambiguous changes along branch below based upon the character reconstruction.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
diff --git a/Source/mesquite/ancstates/aAncStatesIntro/aAncStatesIntro.java b/Source/mesquite/ancstates/aAncStatesIntro/aAncStatesIntro.java
new file mode 100644
index 0000000..8f50ac2
--- /dev/null
+++ b/Source/mesquite/ancstates/aAncStatesIntro/aAncStatesIntro.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.aAncStatesIntro;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class aAncStatesIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aAncStatesIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "The ancestral states reconstruction package provides modules to coordinate and display reconstruction of ancestral states on the branches of trees.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Ancestral States Reconstruction Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Ancestral States Reconstruction Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+}
+
diff --git a/Source/mesquite/ancstates/aAncStatesIntro/index.html b/Source/mesquite/ancstates/aAncStatesIntro/index.html
new file mode 100644
index 0000000..7d9b267
--- /dev/null
+++ b/Source/mesquite/ancstates/aAncStatesIntro/index.html
@@ -0,0 +1,124 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Parsimony</title>
+	</head>
+
+	<body>
+		<h2>
+		<table border="4" cellpadding="0" cellspacing="2">
+			<tr>
+				<td><img height="64" width="164" src="splash.gif"></td>
+				<td>
+					<h2>Ancestral State Reconstruction Packages for  Mesquite</h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<h4>Wayne Maddison & David Maddison</h4>
+		
+<p>January 2009.</p>
+<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#modules">Modules</a>            
+			<li><a href="#examples">Examples</a>            
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		
+<p>See the <a href="../../../docs/mesquite/CharacterEvolution/AncestralStates.html">manual
+    page on ancestral states</a> for an introduction on how to use Mesquite to
+    reconstruct ancestral states.</p>
+<p>Mesquite's standard packages include several that provide calculations to
+  reconstruct ancestral states on a phylogenetic tree. These are the "<strong>ancstates</strong>"
+  package, which coordinates the reconstruction, the "<strong>parsimony</strong>" package, which
+  reconstructs using parsimony methods, and the "<strong>stochchar</strong>" package, which reconstructs
+  using likelihood methods.</p>
+<h3><a name="modules"></a>Modules</h3>
+		<p>Some of the modules available in these packages are:</p>
+		<ul>
+			<li><strong>Ancstates package: </strong>
+			  <ul>
+			    <li><b>Trace Character History</b> -- Displays on a tree the reconstructed
+			      ancestral states at each of the nodes.
+			    </li>
+			    <li><b>Trace All Characters</b> -- Summarizes reconstructed ancestral
+			      states for a series of characters at each of many nodes. </li>
+			    <li><b>Trace Character Over Trees</b> -- Summarizes reconstructed ancestral
+		      states for a character on each of many trees.                                                                                                                                                                                                                                                                                                                                                                                                                                                        [...]
+	          </ul>
+		    <li><strong>Parsimony package</strong></li>
+		    <ul>
+		      <li><strong>Parsimony Ancestral States</strong> -- Reconstructs the
+        history of ancestral states in the character 
+        given a tree and a character distribution, so as to minimize amount of
+		        character change.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  [...]
+		      <li><strong>Parsimony Character Steps</strong> -- Calculates the parsimony
+	            steps in a character given a tree. </li>
+		      <li><strong>Treelength</strong> -- Calculates the treelength of a tree
+		        for a character matrix. The treelength is the weighted sum of
+		        parsimony steps over
+		        characters. </li>
+	          <li><strong>Parsimony Unordered</strong> --
+	            Calculates the most parsimonious ancestral states at the nodes
+	            of the tree assuming one
+      step per state change (this assumption is known as unordered or Fitch parsimony).
+	            Also calculates the number of steps in a most parsimonious reconstruction. </li>
+	          <li><strong>Parsimony Ordered</strong> - Calculates the most parsimonious
+	            ancestral states at the nodes of the tree assuming states are
+	            ordered (this assumption
+      is known as ordered, Farris or Wagner parsimony). Also calculates the number
+	            of steps in a most parsimonious reconstruction. </li>
+	          <li><strong>Parsimony Cost Matrix</strong> - Calculates the most parsimonious
+	            ancestral states assuming state changes cost the number of steps
+	            indicated
+      in the states X states matrix. Known as Stepmatrix or Cost Matrix parsimony. </li>
+	          <li><strong>Stepmatrix Curator</strong> - Provides window to edit
+	            stepmatrices. </li>
+	          <li><b>Parsimony Linear</b> -- Calculates the most parsimonious
+	            ancestral states at the nodes of the tree assuming a cost of <font size="4"><b>|x-y|</b></font><b> </b>on
+	            a branch if the branch shows a change from state x to state y
+	            (this assumption is known as linear, Farris, or Wagner parsimony).
+	            Also
+	            calculates the cost of a most parsimonious reconstruction. </li>
+	          <li><b>Parsimony Squared</b> -- Calculates the most parsimonious
+	            ancestral states at the nodes of the tree assuming a cost of <font size="4"><b>(x-y)<sup>2</sup></b></font> on
+	            a branch if the branch shows a change from state x to state y
+	            (this assumption is known as squared change or least-squares parsimony).
+	            Also calculates the cost of a most parsimonious reconstruction. </li>
+          </ul>
+		    <li><strong>Stochchar package</strong></li>
+		    <ul>
+		      <li><strong>Likelihood Ancestral States</strong><strong></strong> --
+		        Reconstructs the history of ancestral states in the character
+		        given a tree and a character distribution, so as to maximize
+	        the probability of evolving the observed states.                                                                                                                                                                                                                                                                                                                                                                                                                                                    [...]
+	          <li><strong>Likelihood in Character</strong> -- Calculates the likelihood
+	            of a tree for a single character.</li>
+	          <li><strong>Mk Model Curator</strong> -- Provides a window to edit
+	            Mk1 models of evolution.</li>
+	          <li><strong>AsymmMk Model Curator</strong> -- Provides a window to
+            edit AsymmMk models of evolution.                                                                                                                                                                                                                                                                                                                                                                                                                                                                [...]
+	          <li><strong>Mk1 Rate</strong> -- Calculates the rate of character
+	            change under an Mk1 model of evolution.</li>
+	          <li><strong>Asymmetry LR</strong> -- Calculates the test statistic
+	            for the likelihood ratio test comparing the asymmetrical and
+	            one parameter models [2ln(Likelihood(AsymmMk.)/Likelihood(Mk1)],
+	            on a tree for a given character .                                                                                                                                                                                                                                                                                                                                                                                                                                                               [...]
+	      </ul>
+		</ul>
+		
+		<h3><a name="examples"></a>Examples</h3>
+		
+<p>See the examples files in Mesquite_Folder/examples/Ancestral_States.</p>
+		<h3>
+		<p>
+		<hr>
+		</p>
+	</h3>
+		
+<p>© Wayne Maddison & David Maddison, 2002-2009
+</body>
+
+</html>
diff --git a/Source/mesquite/ancstates/aAncStatesIntro/splash.gif b/Source/mesquite/ancstates/aAncStatesIntro/splash.gif
new file mode 100644
index 0000000..25aca5b
Binary files /dev/null and b/Source/mesquite/ancstates/aAncStatesIntro/splash.gif differ
diff --git a/Source/mesquite/ancstates/explanation.txt b/Source/mesquite/ancstates/explanation.txt
new file mode 100644
index 0000000..416f6f0
--- /dev/null
+++ b/Source/mesquite/ancstates/explanation.txt
@@ -0,0 +1,2 @@
+Ancestral States Package
+One of the core Mesquite packages.  Coordinates reconstruction and display of ancestral states of characters on phylogenetic trees.  Includes "Trace Character History".  To function, requires other packages such as the parsimony or likelihood packages to perform the reconstruction.
diff --git a/Source/mesquite/ancstates/lib/ChgSummarizerMultTrees.java b/Source/mesquite/ancstates/lib/ChgSummarizerMultTrees.java
new file mode 100644
index 0000000..275f74e
--- /dev/null
+++ b/Source/mesquite/ancstates/lib/ChgSummarizerMultTrees.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ancstates.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class ChgSummarizerMultTrees extends MesquiteModule  {
+	boolean sensitiveToBranchSelection = false;
+
+   	 public Class getDutyClass() {
+   	 	return ChgSummarizerMultTrees.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Summarizer of changes over multiple trees";
+   	 }
+ 	/* this is a special duty class with only one intended subclass, designed to be used in one of two ways, to summarize
+ 	 * changes over trees without reference to a tree with selected branches, the other wiith reference to such a tree.
+ 	 * If setup() is called, it is assumed the latter is in effect.
+ 	 * if setTree(tree) is called, it is assumed the former is in effect*/
+	public abstract  void setTree(Tree tree);
+	public abstract void setup(Taxa taxa, boolean poppedOut);
+	public boolean getSensitiveToBranchSelection() {
+		return sensitiveToBranchSelection;
+	}
+	public void setSensitiveToBranchSelection(boolean sensitiveToBranchSelection) {
+		this.sensitiveToBranchSelection = sensitiveToBranchSelection;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/assoc/ContainedAssociates/ContainedAssociates.java b/Source/mesquite/assoc/ContainedAssociates/ContainedAssociates.java
new file mode 100644
index 0000000..8ed8f2d
--- /dev/null
+++ b/Source/mesquite/assoc/ContainedAssociates/ContainedAssociates.java
@@ -0,0 +1,1722 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.ContainedAssociates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public class ContainedAssociates extends AnalyticalDrawTree {
+	static int maxEdgeWidth = 499;
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+//		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + " needs a source for the contained trees (e.g. gene trees) to fit within the containing tree (e.g. a species tree).",
+//		"The source of contained trees can be chosen initially or in the Contained Tree Source submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + " needs a source for the contained trees (e.g. gene trees) to fit within the containing tree (e.g. a species tree).",
+		"The source of contained trees can be chosen initially or in the Contained Tree Source submenu");
+		EmployeeNeed e3 = registerEmployeeNeed(NodeLocsVH.class,  getName() + " uses a module to define node locations.",
+		"This is dealt with automatically.");
+		e3.setSuppressListing(true);
+		EmployeeNeed e4 = registerEmployeeNeed(AssociationSource.class,  getName() + " needs to know how contained taxa (e.g. genes) fit within containing taxa (e.g. species).",
+		"The taxa association is probably found automatcially; otherwise you can choose it initially.");
+		EmployeeNeed e5 = registerEmployeeNeed(ReconstructAssociation.class,  getName() + " needs a method to reconstruct how contained lineages (e.g. genes) fit within containing lineages (e.g. species).",
+		"The reconstruction method is chosen initially.");
+		EmployeeNeed e6 = registerEmployeeNeed(mesquite.assoc.DepContTreeWindow.DepContTreeWindow.class,  getName() + " can show the contained tree.",
+		"The contained tree can be shown by selecting Display Contained Tree.");
+
+	}
+	public String getName() {
+		return "Contained Gene (or Other) Trees";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Draws wide trees containing trees of associates (e.g., species tree containing gene tree)" ;
+	}
+	public String getKeywords(){
+		return "gene_tree species_tree coalescence coalescent";
+	}
+	/*.................................................................................................................*/
+
+//	TODO: have standard AssociateHistory (like CharacterHistory)
+	NodeLocsVH nodeLocsTask;
+	//OneTreeSource oneTreeSourceTask;
+	TreeSource treeSourceTask;
+	Tree originalContainedTree;
+	AssociationSource associationTask;
+	ReconstructAssociation reconstructTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteBoolean scale = new MesquiteBoolean(true);
+	MesquiteBoolean showContainedTaxNames = new MesquiteBoolean(true);
+	Vector drawings;
+	public int minimalEdgeWidth = 64;
+	int oldEdgeWidth =64;
+	int ornt;
+	boolean startedUnderScripting;
+	boolean usingOneTreeSource = false;//TODO: if this is ever used, need to deal with hiring comamnd and so on
+	MesquiteString treeSourceName;
+	int initialOffsetX=MesquiteInteger.unassigned;
+	int initialOffsetY= MesquiteInteger.unassigned;
+	MesquiteCommand tstC;
+	TWindowMaker depWindowMaker;
+	boolean suppressed = false;
+	boolean suppressedSet = false; //this is to handle old version files
+	
+	Color containedBranchColor;
+	MesquiteString containedBrColorName;
+	Color containingBranchColor =null; //WideTreeDrawing.defaultBranchColor;
+	MesquiteString containingBrColorName;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		startedUnderScripting = MesquiteThread.isScripting();
+		if (getProject().getNumberTaxas()<=1) {
+			return sorry("Sorry, you can't use the Contained Associates tree drawing if there is only a single set of taxa available.  It is designed to show contained trees within containing trees (e.g. genes within species)");
+		}
+		nodeLocsTask= (NodeLocsVH)hireCompatibleEmployee(NodeLocsVH.class, new boolean[]{true}, "Calculator of node locations");
+		if (nodeLocsTask == null) {
+			return sorry(getName() + " couldn't start because node locator module not obtained");
+		}
+		drawings = new Vector();
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null) {
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained");
+		}
+		//TODO: allow choice of association source, reconstruction method
+		reconstructTask = (ReconstructAssociation)hireEmployee(ReconstructAssociation.class, "Method to reconstruct association history");
+		if (reconstructTask == null) {
+			return sorry(getName() + " couldn't start because no module ot reconstruct associaton histories obtained");
+		}
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of contained trees (for Contained Associates tree drawing)");
+		if (treeSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of contained trees obtained");
+		}
+		tstC = makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		makeMenu("Contained");
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Contained Tree Source", tstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+		addCheckMenuItem(null, "Scale to depth", makeCommand("toggleScale",  this), scale);
+		addMenuItem( "Next Contained Tree", makeCommand("nextContained",  this));
+		addMenuItem( "Previous Contained Tree", makeCommand("previousContained",  this));
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		if (getEmployer() instanceof DrawTreeCoordinator && containingBranchColor!= null){
+			((DrawTreeCoordinator)getEmployer()).setBranchColor(containingBranchColor);
+		}
+		addCheckMenuItem(null, "Show Contained Names", makeCommand("toggleContainedNames",  this), showContainedTaxNames);
+		addMenuItem( "Display Contained Tree", makeCommand("showContainedTree",  this));
+		
+		/*containingBrColorName = new MesquiteString("Blue");
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Containing Branch Color", makeCommand("setContainingBranchColor",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		mmis.setSelected(containingBrColorName);
+*/
+		containedBrColorName = new MesquiteString("Green");
+		MesquiteSubmenuSpec mmis2 = addSubmenu(null, "Contained Branch Color", makeCommand("setContainedBranchColor",  this));
+		mmis2.setList(ColorDistribution.standardColorNames);
+		mmis2.setSelected(containedBrColorName);
+
+		suppressed = MesquiteThread.isScripting();
+		return true;
+	}
+	public void endJob(){
+		suppressed = true;
+		depWindowMaker = null;
+		super.endJob();
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m!=treeSourceTask)
+			iQuit();
+		else if (drawings != null && drawings.size()>0){
+			TaxaAssociation a = ((WideTreeDrawing)drawings.elementAt(0)).association;
+			if (a.getTaxa(0).isDoomed() || a.getTaxa(1).isDoomed())
+				iQuit();
+
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) { //TODO: should be passed scripting
+		if (treeDisplay.getEdgeWidth()<minimalEdgeWidth) {
+			treeDisplay.setEdgeWidth(minimalEdgeWidth);
+		}
+		treeDisplay.setOrientation(TreeDisplay.UP);
+		WideTreeDrawing treeDrawing;
+		/*	if (usingOneTreeSource && oneTreeSourceTask !=null)
+			treeDrawing =  new WideTreeDrawing (treeDisplay, numTaxa, this, associationTask, oneTreeSourceTask, reconstructTask, startedUnderScripting);
+		else */
+		CommandRecord prev = MesquiteThread.getCurrentCommandRecord();
+		MesquiteThread.setCurrentCommandRecord(new CommandRecord(startedUnderScripting));
+
+		treeDrawing =  new WideTreeDrawing (treeDisplay, numTaxa, this, associationTask, treeSourceTask, reconstructTask);
+		MesquiteThread.setCurrentCommandRecord(prev);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (MesquiteThread.isScripting())
+			return;
+		if (employee instanceof OneTreeSource || employee instanceof TreeSource) {
+			if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+					treeDrawing.currentContainedTree = null;
+					treeDrawing.containedSourceChanged();
+					if (treeDrawing.treeDisplay!=null)
+						treeDrawing.treeDisplay.pleaseUpdate(true);
+				}
+			}
+		}
+		else if (employee instanceof AssociationSource){
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.resetAssociation(treeDrawing.treeDisplay.getTree().getTaxa(), true);
+				treeDrawing.zapContained();
+				if (treeDrawing.treeDisplay!=null)
+					treeDrawing.treeDisplay.pleaseUpdate(true);
+			}
+		}
+		else if (employee instanceof ReconstructAssociation){
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.zapContained();
+				if (treeDrawing.treeDisplay!=null)
+					treeDrawing.treeDisplay.pleaseUpdate(true);
+			}
+		}
+		else {
+			super.employeeParametersChanged(employee, source, notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress "); 
+		temp.addLine("getAssociationSource ",  associationTask); 
+		temp.addLine("getReconstructor ",  reconstructTask); 
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		temp.addLine("setTreeSource ", treeSourceTask); 
+		if (depWindowMaker != null && depWindowMaker.getModuleWindow() != null && depWindowMaker.getModuleWindow().isVisible())
+			temp.addLine("showContainedTree", depWindowMaker);
+		if (treeSourceTask !=null) { //not using oneTreeSourceTask
+			if (drawings.size()>0) {
+				Object obj = drawings.elementAt(0);
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				temp.addLine("setContained " + MesquiteTree.toExternal(treeDrawing.currentContained)); 
+			}
+		}
+		temp.addLine("toggleScale " + scale.toOffOnString()); 
+		temp.addLine("toggleContainedNames " + showContainedTaxNames.toOffOnString()); 
+		WideTreeDrawing tco = (WideTreeDrawing)drawings.elementAt(0);
+		if (tco!=null && tco.legend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.legend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.legend.getOffsetY());
+		}
+		if (containedBranchColor !=null) {
+			String bName = ColorDistribution.getStandardColorName(containedBranchColor);
+			if (bName!=null)
+				temp.addLine("setContainedBranchColor " + StringUtil.tokenize(bName));//quote
+		}
+		if (containingBranchColor !=null) {
+			String bName = ColorDistribution.getStandardColorName(containingBranchColor);
+			if (bName!=null)
+				temp.addLine("setContainingBranchColor " + StringUtil.tokenize(bName));//quote
+		}
+		temp.addLine("desuppress "); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the thickness of the drawn branches", "[width in pixels]", commandName, "setEdgeWidth")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, maxEdgeWidth);
+			if (newWidth>minimalEdgeWidth && newWidth<=maxEdgeWidth && newWidth!=oldEdgeWidth) {
+				oldEdgeWidth=newWidth;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+					treeDrawing.treeDisplay.setEdgeWidth(newWidth);
+					treeDrawing.treeDisplay.setMinimumTaxonNameDistance(minimalEdgeWidth/4, 4); 
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets default color of contained branches of tree in tree display", "[name of color]", commandName, "setContainedBranchColor")) {
+			String token = ParseUtil.getFirstToken(arguments, stringPos);
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			Color bcD = ColorDistribution.getStandardColorDimmed(ColorDistribution.getStandardColorNumber(bc));
+			containedBranchColor = bc;
+			containedBrColorName.setValue(token);
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.setContainedColor(bc);
+			}
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets default color of containing branches of tree in tree display", "[name of color]", commandName, "setContainingBranchColor")) {
+			String token = ParseUtil.getFirstToken(arguments, stringPos);
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			Color bcD = ColorDistribution.getStandardColorDimmed(ColorDistribution.getStandardColorNumber(bc));
+			containingBranchColor = bc;
+			containingBrColorName.setValue(token);
+			if (getEmployer() instanceof DrawTreeCoordinator){
+				((DrawTreeCoordinator)getEmployer()).setBranchColor(containingBranchColor);
+			}
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.setContainingColor(bc);
+			}
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether contained trees are drawn to scale of their branch lengths", "[on or off to indicate whether scaled]", commandName, "toggleScale")) {
+			boolean current = scale.getValue();
+			scale.toggleValue(parser.getFirstToken(arguments));
+			if (current!=scale.getValue()) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+					treeDrawing.treeDisplay.pleaseUpdate(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether contained trees show taxon names", "[on or off to indicate whether name shown]", commandName, "toggleContainedNames")) {
+			boolean current = showContainedTaxNames.getValue();
+			showContainedTaxNames.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showContainedTaxNames.getValue()) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+					treeDrawing.treeDisplay.pleaseUpdate(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns the module supplying taxa associations", null, commandName, "getAssociationSource")) {
+			return  associationTask; 
+
+		}
+		else if (checker.compare(this.getClass(), "Returns the module reconstructing history of contained tree within containing tree", null, commandName, "getReconstructor")) {
+			return  reconstructTask; 
+
+		}
+		else if (checker.compare(this.getClass(), "Suppresses tree drawing", null, commandName, "suppress")) {
+			suppressed = true;
+			suppressedSet = true;
+		}
+		else if (checker.compare(this.getClass(), "Desuppresses tree drawing", null, commandName, "desuppress")) {
+			suppressed = false;
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.desuppress();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of contained trees", "[name of module]", commandName, "setTreeSource")) {
+
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of contained trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+					treeDrawing.setTreeSourceTask(treeSourceTask);
+					treeDrawing.treeDisplay.pleaseUpdate(false);
+				}
+				return treeSourceTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows the contained tree in a separate window", null, commandName, "showContainedTree")) {
+			if (depWindowMaker == null) {
+				depWindowMaker = (TWindowMaker)hireNamedEmployee(TWindowMaker.class, "#DepContTreeWindow");
+				if (depWindowMaker != null)
+					depWindowMaker.setTree(originalContainedTree);
+			}
+			if (depWindowMaker == null)
+				return null;
+			depWindowMaker.setWindowVisible(true);
+			return depWindowMaker;
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to the next contained tree", null, commandName, "nextContained")) {
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.nextContained();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to the previous contained tree", null, commandName, "previousContained")) {
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.previousContained();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which contained tree is shown", "[number of contained tree]", commandName, "setContained")) {
+			int ic = MesquiteTree.toInternal(MesquiteInteger.fromFirstToken(arguments, pos)); 
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+				treeDrawing.setContained(ic);
+			}
+			if (!suppressedSet && suppressed) { //for old version files
+				suppressed = false;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial x offset from base position for the legend", "[offset]", commandName, "setInitialOffsetX")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+				if (drawings!=null) {
+					Enumeration e = drawings.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+						treeDrawing.legend.setOffsetX(offset);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Sets the initial y offset from base position for the legend", "[offset]", commandName, "setInitialOffsetY")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+				if (drawings!=null) {
+					Enumeration e = drawings.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+						treeDrawing.legend.setOffsetY(offset);
+					}
+				}
+			}
+		}
+		/*
+    	 	else if (checker.compare(this.getClass(), nullxxx, null, commandName, "useOne")) { //TODO: if this is ever used, need to deal with hiring comamnd and so on
+			oneTreeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of contained tree");
+			usingOneTreeSource = true;
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				WideTreeDrawing treeDrawing = (WideTreeDrawing)obj;
+ 				treeDrawing.setTreeSourceTask(oneTreeSourceTask);
+				treeDrawing.treeDisplay.pleaseUpdate(true);
+			}
+    	 		return oneTreeSourceTask;
+    	 	}
+		 */
+		else if (checker.compare(this.getClass(), "Returns the module calculating node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (reconstructTask!=null && treeSourceTask!=null)
+			return "Contained tree source: " + treeSourceTask.getName() + "; Association reconstruced by: " + reconstructTask.getName();
+		return "";
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+/* ======================================================================== */
+
+/* ======================================================================== */
+class WideTreeDrawing extends TreeDrawing  {
+	public Polygon[] branchPoly;
+	public Polygon[] fillBranchPoly;
+
+	private int lastleft;
+	private int taxspacing;
+	public int highlightedBranch, branchFrom;
+	public int xFrom, yFrom, xTo, yTo;
+	public ContainedAssociates ownerModule;
+	Color resolvedColor = Color.magenta;
+	Color defaultContainedColor = Color.green;
+	Color containedColor = defaultContainedColor;
+	Color selectedContainedColor = Color.cyan;
+	Color migratedColor = Color.yellow;
+	static Color defaultBranchColor = Color.blue;
+	Color containingColor = defaultBranchColor;
+	AssociationSource associationTask;
+	TaxaAssociation association;
+	MesquiteModule treeSourceTask;
+	Taxa containedTaxa=null;
+	MesquiteTree containedTree;
+	MesquiteTree originalContainedTree=null;
+	public int edgeWidth = 64;
+	int oldNumTaxa = 0;
+	Polygon utilityPolygon;
+	public static final int inset=1;
+	private boolean ready=false;
+	private int boxHeight;
+	private int foundBranch;
+	NameReference triangleNameRef;
+	NameReference widthNameReference;
+	DoubleArray widths = null;
+	double maxWidth = 0;
+	//private int[][] contained;
+	private int[] miniX, miniY;
+	private boolean[] inTree;
+	private int oldNumSpaces =0;
+	TextRotator textRotator;
+	int currentContained = 0;
+	public ContainedLegend legend;
+	public Tree currentTree=null;
+	public Tree currentContainedTree = null;
+	Taxa currentContainedTaxa = null;
+	TaxaAssociation currentAssociation = null;
+	ContainedAssocExtra extra;
+	AssociationHistory history;
+	ReconstructAssociation reconstructTask;
+	
+	//MesquiteTimer firstTime, secondTime, thirdTime, d1Time, d2Time, d3Time, d4Time;
+	public WideTreeDrawing (TreeDisplay treeDisplay, int numTaxa, ContainedAssociates ownerModule, AssociationSource associationTask, MesquiteModule treeSourceTask, ReconstructAssociation reconstructTask) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		this.associationTask = associationTask;
+		this.treeSourceTask = treeSourceTask;
+		this.reconstructTask = reconstructTask;
+		edgeWidth = treeDisplay.getEdgeWidth();
+		boxHeight = ownerModule.minimalEdgeWidth/4;
+		treeDisplay.setMinimumTaxonNameDistance(boxHeight,  4); 
+		treeDisplay.setOrientation(TreeDisplay.UP);
+
+		triangleNameRef = NameReference.getNameReference("triangled");
+		widthNameReference = NameReference.getNameReference("width");
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		history = new AssociationHistory();
+
+		extra = new ContainedAssocExtra(ownerModule, treeDisplay, this);
+		treeDisplay.addExtra(extra);
+		treeDisplay.branchColor = containingColor;
+		ready = true;
+		utilityPolygon=new Polygon();
+		utilityPolygon.xpoints = new int[16];
+		utilityPolygon.ypoints = new int[16];
+		utilityPolygon.npoints=16;
+
+		legend = new ContainedLegend(ownerModule, this);
+		if (treeSourceTask !=null && treeSourceTask instanceof TreeSource && containedTaxa != null)
+			legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+		extra.addPanelPlease(legend);
+		legend.setVisible(true);
+		resetAssociation(treeDisplay.getTaxa(), true);
+		if (treeSourceTask instanceof TreeSource) 
+			((TreeSource)treeSourceTask).initialize(containedTaxa);
+		else if (treeSourceTask instanceof OneTreeSource)
+			((OneTreeSource)treeSourceTask).initialize(containedTaxa);
+	}
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new Polygon[numNodes];
+		fillBranchPoly= new Polygon[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new Polygon();
+			branchPoly[i].xpoints = new int[16];
+			branchPoly[i].ypoints = new int[16];
+			branchPoly[i].npoints=16;
+			fillBranchPoly[i] = new Polygon();
+			fillBranchPoly[i].xpoints = new int[16];
+			fillBranchPoly[i].ypoints = new int[16];
+			fillBranchPoly[i].npoints=16;
+		}
+	}
+	int branchEdgeWidth(int node){
+		if (widths !=null && maxWidth!=0 && MesquiteDouble.isCombinable(maxWidth)) {
+			double w = widths.getValue(node);
+			if (MesquiteDouble.isCombinable(w)) {
+				int ew = (int)((w/maxWidth) * edgeWidth);
+				if (ew<3)
+					ew = 3;
+				return ew;
+			}
+		}	
+		return edgeWidth;
+	}
+	
+	void setContainedColor(Color c) {
+		containedColor = c;
+	}
+	void setContainingColor(Color c) {
+		containingColor = c;
+	}
+	/*_________________________________________________*/
+	private void UPdefineFillPoly(int node, Polygon poly, boolean internalNode, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices) {
+		if (poly!=null) {
+			int sliceWidth=branchEdgeWidth(node);
+			if (numSlices>1) {
+				Nx+= (sliceNumber-1)*(branchEdgeWidth(node)-inset)/numSlices;
+				mNx+= (sliceNumber-1)*(branchEdgeWidth(node)-inset)/numSlices;
+				sliceWidth=(branchEdgeWidth(node)-inset)-((sliceNumber-1)*(branchEdgeWidth(node)-inset)/numSlices);
+			}
+			if ((internalNode) && (numSlices==1)){ 
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny);
+				poly.addPoint(Nx+sliceWidth/2, Ny-sliceWidth/2-inset);
+				poly.addPoint(Nx+sliceWidth-inset, Ny);
+				poly.addPoint(mNx+sliceWidth-inset, mNy);
+				poly.addPoint(mNx+inset, mNy);
+				poly.addPoint(Nx+inset, Ny);
+				poly.npoints=6;
+			}
+			else {
+				if (Nx==mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Ny-=(branchEdgeWidth(node)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx+inset, Ny+inset);
+					poly.addPoint(Nx+sliceWidth-inset, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx+inset, Ny+inset);
+					poly.npoints=5;
+				}
+				else if (Nx>mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Nx+=(branchEdgeWidth(node)-inset)/4;
+						Ny-=(branchEdgeWidth(node)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx, Ny+inset);
+					poly.addPoint(Nx+sliceWidth-inset-inset, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx, Ny+inset);
+					poly.npoints=5;
+				}
+				else if (Nx<mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Nx-=(branchEdgeWidth(node)-inset)/4;
+						Ny-=(branchEdgeWidth(node)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx+inset+inset, Ny+inset);
+					poly.addPoint(Nx+sliceWidth, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx+inset+inset, Ny+inset);
+					poly.npoints=5;
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void UPCalcFillBranchPolys(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			UPCalcFillBranchPolys(tree, d);
+		UPdefineFillPoly(node, fillBranchPoly[node], tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0);
+	}
+	/*_________________________________________________*/
+	private void UPdefinePoly(int node, Polygon poly, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			if (internalNode&& false) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node)/2, Ny-branchEdgeWidth(node)/2);
+				poly.addPoint(Nx+branchEdgeWidth(node), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void UPCalcBranchPolys(Tree tree, int node)
+	{
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			UPCalcBranchPolys(tree, d);
+		UPdefinePoly(node, branchPoly[node], tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+	}
+	/*_________________________________________________*/
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[tree.motherOfNode(node)];
+		lineBaseX[node]=x[tree.motherOfNode(node)];
+	}
+	/*_________________________________________________*/
+	private void calcBranchPolys(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+		edgeWidth = treeDisplay.getEdgeWidth();
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		calculateLines(tree, drawnRoot);
+		if (treeDisplay.getTaxonSpacing()<edgeWidth+2) {
+			edgeWidth= treeDisplay.getTaxonSpacing()-2;
+			if (edgeWidth<2)
+				edgeWidth=2;
+		}
+
+		UPCalcBranchPolys(tree, drawnRoot);
+		UPCalcFillBranchPolys(tree, drawnRoot);
+	}
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		tC = g.getColor();
+		if (flip)
+			g.setColor(Color.red);
+		else
+			g.setColor(containingColor);
+		if (treeDisplay.getOrientation()==TreeDisplay.DOWN || treeDisplay.getOrientation()==TreeDisplay.UP){
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node]-2 - i, y[node], x[tree.motherOfNode(node)]-2 - i, y[tree.motherOfNode(node)]);
+		}
+		else {
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node], y[node]-2 - i, x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]-2 - i);
+		}
+		g.setColor(tC);
+	}
+	Color tC;
+	/*_________________________________________________*/
+	private   void drawBranches(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			if ((tree.getRooted() || tree.getRoot()!=node) && branchPoly[node]!=null) {
+				g.drawPolygon(branchPoly[node]);
+				
+			}
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawBranches( tree, g, d);
+			
+		}
+	}
+	/*_________________________________________________*/
+	private   void whiteBranches(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			if (treeDisplay.getBranchColor(node)!=null)
+				g.setColor(treeDisplay.getBranchColor(node));
+			else
+				g.setColor(containingColor);
+			if ((tree.getRooted() || tree.getRoot()!=node)) {
+				fillBranch(tree, node, g);
+			}
+
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				whiteBranches( tree, g, d);
+			
+			if (emphasizeNodes()) {
+				Color prev = g.getColor();
+				g.setColor(Color.red);//for testing
+				g.fillPolygon(nodePoly(node));
+				g.setColor(prev);
+			}
+			
+		}
+	}
+	boolean multipleHomes = false;
+	boolean firstMultipleHomes = true;
+	/*....................................................................................................*/
+	/* returns true if at least one of the taxa is in the tree*/
+	private boolean containingInTree(Tree tree, Taxon[] containing){
+		if (containing == null)
+			return false;
+		int count = 0;
+		for (int i=0; i<containing.length; i++){
+			int w = tree.getTaxa().whichTaxonNumber(containing[i]);
+			if (w >=0 && tree.nodeOfTaxonNumber(w)>0) {
+				count++;
+			}
+		}
+		if (count == 1)
+			return true;
+		else if (count >1) {
+			if (!multipleHomes) {
+				String warning = "Terminal taxon of contained tree is associated with more than one terminal taxon in the containing tree.  This is not allowed in the current version of Contained Associates.  (This warning may be given only once during this particular calculation).";
+				if (firstMultipleHomes) {
+					MesquiteMessage.notifyUser(warning);
+				}
+				else
+					MesquiteMessage.warnUser("Terminal taxon of contained tree is associated with more than one terminal taxon in the containing tree.  This is not allowed in the current version of Contained Associates.  (This warning may be given only once during this particular calculation).");
+				firstMultipleHomes = false;
+			}
+			multipleHomes = true;
+		}	
+		return false;
+	}
+	boolean first = true;
+	/*....................................................................................................*/
+	/*goes through contained tree marking which nodes are in actually in the contained tree (some might not be if
+	terminals of the contained associates are contained in containing taxa that are not in the containing tree*/
+	private void checkInTree(Tree tree, Tree containedTree, int node) {
+		//inTree[node]=false;
+		if (containedTree.nodeIsInternal(node)) {
+			for (int d = containedTree.firstDaughterOfNode(node); containedTree.nodeExists(d); d = containedTree.nextSisterOfNode(d)) {
+				checkInTree(tree, containedTree, d);
+				if (inTree[d])
+					inTree[node]=true;
+			}
+		}
+		else {
+			Taxon t = containedTree.getTaxa().getTaxon(containedTree.taxonNumberOfNode(node));
+			Taxon[] containing = association.getAssociates(t);
+
+			if (t == null)
+				inTree[node]=false;
+			else if (containingInTree(tree, containing)) {
+				inTree[node]=true;
+			}
+			else {
+				if (first)
+					MesquiteMessage.warnUser("Terminal taxon \"" + t.getName() + "\"  of contained tree is not associated with a terminal taxon in the containing tree (this warning may be given only once during this particular calculation).");
+				first = false;
+			}
+		}
+	}
+	NameReference migrateRef = NameReference.getNameReference("Migration");
+	/*....................................................................................................*/
+	private void miniTerminals(Graphics g, Tree tree, int node, int[] terminals, int terminalY, int miniSpacing, boolean atTip, Color containedColor) {
+		boolean inA =IntegerArray.inArray(node, terminals);
+		if (tree.nodeIsInternal(node) /*&& !inA*/) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				miniTerminals(g, tree, d, terminals, terminalY, miniSpacing, atTip, containedColor);
+			}
+		}
+		if (inA && inTree[node]) { //terminal
+
+			lastleft+= miniSpacing;
+			int oldX = miniX[node];
+			int oldY = miniY[node];
+
+			if (!atTip){ //(tree.nodeIsInternal(node) ||
+				boolean useOld = false;
+				if (terminalY>= oldY || !legalY(oldY)) { //test for legalY added 9 Nov 01
+					useOld = true;
+					miniY[node] = terminalY;
+					miniX[node] = lastleft;
+				}
+				if (tree.getSelected(node))
+					g.setColor(resolvedColor);
+				else if (tree.getAssociatedBit(migrateRef, node))
+					g.setColor(migratedColor);
+				else
+					g.setColor(containedColor);
+
+				if (legalXY(oldX, oldY) && legalXY(miniX[node], miniY[node])){
+					g.drawLine(oldX, oldY, miniX[node], miniY[node]);
+					g.drawLine(oldX+1, oldY, miniX[node]+1, miniY[node]);
+				}
+				else if (legalXY(miniX[node], miniY[node])) {
+					Color cc = g.getColor();
+					g.setColor(Color.red);
+					g.fillOval(miniX[node], miniY[node], 5, 5);
+					g.setColor(Color.yellow);
+					g.drawOval(miniX[node], miniY[node], 5, 5);
+					g.setColor(cc);
+				}
+				else if (legalXY(oldX, oldY)) {
+					Color cc = g.getColor();
+					g.setColor(Color.red);
+					g.fillOval(oldX, oldY, 5, 5);
+					g.setColor(Color.yellow);
+					g.drawOval(oldX, oldY, 5, 5);
+					g.setColor(cc);
+				}
+			}
+			else if (tree.nodeIsTerminal(node)) {
+				miniY[node] = terminalY;
+				miniX[node] = lastleft;
+				if (ownerModule.showContainedTaxNames.getValue()){
+				int taxonNumber = tree.taxonNumberOfNode(node);
+				//draw only if node has associates and is part of tree
+				String s=tree.getTaxa().getName(taxonNumber);
+				if (tree.getTaxa().getSelected(taxonNumber))
+					g.setColor(selectedContainedColor);
+				else
+					g.setColor(containedColor);
+				textRotator.drawRotatedText(s, taxonNumber, g, treeDisplay, miniX[node]-2, miniY[node]-6);
+				}
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	private void miniCalcInternalLocs(Tree tree, int node, int[] terminals) {
+		if (!IntegerArray.inArray(node, terminals)) { //internal
+			int fD = 0;
+			int lD = 0;
+			boolean first=true;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					miniCalcInternalLocs(tree, d, terminals);
+					if (first) {
+						fD = d;
+						first = false;
+					}
+					lD = d;
+				}
+			}
+			if (fD!=0) {
+				//lD = fD;
+				int nFDx = miniX[fD];
+				int nFDy = miniY[fD];
+				int nLDx = miniX[lD];
+				int nLDy = miniY[lD];
+				miniY[node] = (-nFDx + nLDx+nFDy + nLDy) / 2;
+				miniX[node] =(nFDx + nLDx - nFDy + nLDy) / 2;
+			}
+		}
+
+	}
+	/*_________________________________________________*/
+	private void miniSlantInternalLocs(Tree tree, int node, int[] terminals, int yStart, int xDiff, int yDiff) {
+		if (yDiff == 0)
+			return;
+		if (!IntegerArray.inArray(node, terminals)) { //internal
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					miniSlantInternalLocs(tree, d, terminals, yStart, xDiff, yDiff);
+				}
+			}
+			miniX[node] += xDiff*(miniY[node] - yStart)/yDiff;  //(miniY[node] - yStart)/yDiff is proportion of containing branch
+		}
+
+	}
+
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to tallest terminal, with unassigned lengths given value "perUnassignedLength" */
+	public int minimumYOfContained (Tree containingTree, int node) {
+		if (containingTree.nodeIsTerminal(node)) {
+			Taxon[] t =association.getAssociates(containingTree.getTaxa().getTaxon(containingTree.taxonNumberOfNode(node)));
+			if (t==null || t.length==0)
+				return MesquiteInteger.unassigned;
+			return y[node];
+		}
+		int minimum = MesquiteInteger.unassigned;
+		for (int daughter=containingTree.firstDaughterOfNode(node); containingTree.nodeExists(daughter); daughter = containingTree.nextSisterOfNode(daughter) ) {
+			minimum = MesquiteInteger.minimum(minimumYOfContained(containingTree, daughter), minimum);
+		}
+		return minimum;
+	}
+	/*....................................................................................................*/
+	private void miniScaleInternalLocs (Tree tree, int node, int[] terminals, int top, int cladeTop, int containing, int root, double scaling) {
+		
+		if (IntegerArray.inArray(node, terminals)){ //internal
+			miniY[node]=top;
+		}
+		else  { //internal
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					miniScaleInternalLocs(tree, d, terminals, top, cladeTop, containing, root, scaling);
+				}
+			}
+			//not just branch length; need to see how much of the branch lengths already used up in descendant containing nodes
+			miniY[node]=cladeTop + (int)(tree.tallestPathAboveNode(node, 1.0)*scaling + 0.5); //0.5 to round 
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					if (miniY[node] < miniY[d]) //round-off error might cause node to be above descendants; check here
+						miniY[node]=miniY[d];
+				}
+			}
+		}
+
+	}
+	/*....................................................................................................*/
+	private void OLDminiScaleInternalLocs (Tree tree, int node, int[] terminals, int bottom, double ancH, int root, double scaling) {
+		if (!IntegerArray.inArray(node, terminals)) { //internal
+			double nH;
+			if (node==root) {
+				nH=bottom;
+			}
+			else {
+				nH=ancH - (tree.getBranchLength(node, 1.0)*scaling);
+			}
+			miniY[node]=(int)(nH);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					OLDminiScaleInternalLocs(tree, d, terminals, bottom, nH, root, scaling);
+				}
+			}
+		}
+
+	}
+	/*_________________________________________________*/
+	private double miniDepth(Tree tree, int node, int[] terminals) {
+		if (!IntegerArray.inArray(node, terminals)) { //internal
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTree[d]) {
+					return tree.getBranchLength(d, 1.0) + miniDepth(tree, d, terminals);
+				}
+			}
+		}
+		return 0;
+	}
+	boolean warned = false;
+	boolean legalXY(int x, int y){
+		boolean L = (x<treeDisplay.getBounds().width && y>treeDisplay.getBounds().height && y<300000000);
+		if (!L)
+			L = x>=0 && x<treeDisplay.getBounds().width && y>=0;
+			return L;
+
+	}
+	boolean legalX(int x){
+		return x>=0 && x<treeDisplay.getBounds().width;
+	}
+	boolean legalY(int y){
+		return y>0 && MesquiteInteger.isCombinable(y); // && y<treeDisplay.getBounds().height;
+	}
+	/*....................................................................................................*/
+	private void miniDraw(Graphics g, Tree tree, int node, int[] terminals, Color containedColor) {
+		if (!IntegerArray.inArray(node, terminals)) { //internal
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				miniDraw(g, tree, d, terminals, containedColor);
+				if (inTree[d] && inTree[node]){
+
+					if (tree.getSelected(d))
+						g.setColor(resolvedColor);
+					else
+						g.setColor(containedColor);
+
+					if (!warned && (!legalY(miniY[d]) || !legalY(miniY[node]))) {
+						warned = true;
+						ownerModule.logln("There has been an error in drawing a contained tree.  " +  
+								"This can sometimes happen if you are modeling coalescence with very short branch lengths (e.g., divergence times of one generation ). " + 
+								" Points of error will be shown by a yellow-ringed red spot.  This message will not be repeated, even when the error recurs. (" + miniY[d] + " " + miniY[node] +")");
+						ownerModule.showLogWindow();
+						treeDisplay.repaint();
+						//if (miniY[d]<=0) MesquiteMessage.warnProgrammer("miniDraw Error: miniY[d] <=0 " + d + " miniY[d] " + miniY[d]);
+						//if (miniY[node]<=0) MesquiteMessage.warnProgrammer("miniDraw Error: miniY[node] <=0 " + node + " miniY[node] " + miniY[node]);
+					}
+					if (legalXY(miniX[node], miniY[node]) && legalXY(miniX[d], miniY[d])){
+						g.drawLine(miniX[d], miniY[d], miniX[node], miniY[node]);
+						g.drawLine(miniX[d]+1, miniY[d], miniX[node]+1, miniY[node]);
+
+					}
+					g.setColor(containedColor);
+				}
+			}
+		}
+	}
+	boolean allLengthsAssigned(Tree tree, int node){
+		if (tree.nodeIsTerminal(node))
+			return !tree.branchLengthUnassigned(node);
+
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (!allLengthsAssigned(tree, d)) 
+				return false;
+		}
+		return true;
+	}
+	/*_________________________________________________*/
+	int howMany(int[] nodes){
+		if (nodes==null)
+			return 0;
+		int num=0;
+		for (int i=0; i<nodes.length; i++)
+			if (nodes[i]!=MesquiteInteger.unassigned)
+				num++;
+		return num;
+	}
+	/*_________________________________________________*/
+	int[] terminalsOnly(Tree tree, int[] nodes){
+		if (nodes==null)
+			return null;
+		int[] terms = new int[nodes.length];
+		IntegerArray.deassignArray(terms);
+		int count=0;
+		for (int a=0; a<nodes.length; a++) {
+			if (MesquiteInteger.isCombinable(nodes[a])){
+				boolean ancestor = false;
+				for (int d = 0; d<nodes.length; d++){
+					if (d!=a && tree.descendantOf(nodes[d], nodes[a]))
+						ancestor = true;
+				}
+				if (!ancestor)
+					terms[count++] = nodes[a];
+			}
+		}
+		return terms;
+	}
+
+	/*checks if a is among the descendants, or is an ancestor of them*/
+	private boolean isInOrAncestor(Tree cTree, int[] descendants, int a){
+		if (descendants==null)
+			return false;
+		for (int i=0; i<descendants.length; i++)
+			if (MesquiteInteger.isCombinable(a) && MesquiteInteger.isCombinable(descendants[i]) && (descendants[i]==a || cTree.descendantOf(descendants[i],a)))
+				return true;
+		return false;
+	}
+	int[] tempA=new int[1];
+	/*_________________________________________________*/
+	private boolean sisterAmong(Tree cTree, int[] aNodes, int i){
+		for (int j =0; j<aNodes.length; j++)
+			if (i !=j && cTree.nodesAreSisters(aNodes[i], aNodes[j]) && cTree.nodeIsFirstDaughter(aNodes[i]))
+				return true;
+		return false;
+	}
+	
+	/*private int highestContaining(Tree tree, int node){
+		if (tree.nodeIsTerminal(node))
+			return y[node];
+		int max = 0;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			int h = highestContaining( tree, d);
+			if (h>max)
+				max = h;
+		}
+		return max;
+	}*/
+	/*draws small tree at each containing node, to show coalescences within that containing branch*/
+	private   void drawMiniTrees(Tree containedTree, Tree tree, int containingNode,  Graphics g, boolean atTip) {
+		int[] cNodes = history.getContainedNodes(containingNode);
+		if (cNodes == null || cNodes.length == 0)
+			return;
+		for (int i=0; i<cNodes.length; i++) {
+			if (MesquiteInteger.isCombinable(cNodes[i]))
+				inTree[cNodes[i]]=true;
+		}
+
+		int[] terminals = cNodes; //terminalsOnly(containedTree, cNodes);
+		int[] aNodes;
+		if (tree.getRoot()==containingNode) {
+			tempA[0] = containedTree.getRoot();
+			aNodes = tempA; // aNodes = history.condenseClades(containedTree, cNodes);// 
+		}
+		else
+			aNodes = history.getContainedNodes(tree.motherOfNode(containingNode));//aNodes = history.condenseClades(containedTree, cNodes);//
+		int xC= x[containingNode];
+		int yC= y[containingNode];
+
+		int taxaSpacing = branchEdgeWidth(containingNode)/(howMany(terminals) +1);
+		lastleft = xC;
+		for (int i=0; i<aNodes.length; i++) {
+			Color cc = containedColor;  //if sister clade isn't 
+
+			if (!MesquiteInteger.isCombinable(aNodes[i]))
+				return;
+			else if (isInOrAncestor(containedTree, cNodes,aNodes[i])) {
+
+				miniTerminals(g, containedTree, aNodes[i], terminals, yC, taxaSpacing, atTip, cc);
+				miniCalcInternalLocs(containedTree, aNodes[i], terminals);
+				int ySpan = (yC-y[tree.motherOfNode(containingNode)]);
+				if (ownerModule.scale.getValue() && allLengthsAssigned(containedTree, containedTree.getRoot())){
+					double scaling = 1.0;
+					int top = yC;
+					int cladeTop = minimumYOfContained(tree, containingNode); 
+					if (tree.tallestPathAboveNode(tree.getRoot(), 1.0) ==0){ //tree.tallestPathAboveNode(tree.getRoot(), 1.0)
+						scaling = 0.1;  //this is arbitrary; scale not shown anyway
+					}
+					else
+						scaling = (Math.abs(minimumYOfContained(tree, tree.getRoot())-y[tree.getRoot()])/(tree.tallestPathAboveNode(tree.getRoot(), 1.0)));
+					
+					//if this is the root and branch lengths are not being shown for the containing tree, don't scale
+					if (tree.hasBranchLengths() && (treeDisplay.showBranchLengths || (true || containingNode!=tree.getRoot()))){
+						miniScaleInternalLocs (containedTree, aNodes[i], terminals,  top, cladeTop, containingNode, aNodes[i], scaling);
+					}
+
+				}
+				if (ySpan!=0)
+					miniSlantInternalLocs(containedTree, aNodes[i], terminals, yC, xC-x[tree.motherOfNode(containingNode)], ySpan);
+				miniDraw(g, containedTree, aNodes[i], terminals, cc);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private   void drawContained(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			//if (contained[node]!=null) {
+			if ( history.getNumberContainedNodes(node) !=0) {
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+					drawContained( tree, g, d);
+				}
+				//	if (tree.nodeIsTerminal(node))
+				g.setColor(containedColor);
+				//	else
+				//		g.setColor(Color.pink);
+				drawMiniTrees(containedTree, tree, node, g, tree.nodeIsTerminal(node));
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public void setTreeSourceTask (MesquiteModule module){
+		this.treeSourceTask = module;
+		currentContained = 0;
+		if (treeSourceTask instanceof TreeSource)
+			((TreeSource)treeSourceTask).initialize(containedTaxa);
+		else if (treeSourceTask instanceof OneTreeSource)
+			((OneTreeSource)treeSourceTask).initialize(containedTaxa);
+		if (treeSourceTask !=null && treeSourceTask instanceof TreeSource && containedTaxa != null){
+			legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+			((TreeSource)treeSourceTask).setPreferredTaxa(containedTaxa);
+		}
+		currentContainedTree=null; 
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void nextContained (){
+		if (treeSourceTask instanceof OneTreeSource)
+			return;
+		if (containedTaxa == null)
+			return;
+		if (currentContained>=((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa)-1)
+			currentContained=0;
+		else
+			currentContained++;
+		currentContainedTree = null;
+		legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void previousContained (){
+		if (treeSourceTask instanceof OneTreeSource)
+			return;
+		if (containedTaxa == null)
+			return;
+		if (currentContained<=0)
+			currentContained=((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa)-1;
+		else
+			currentContained--;
+		currentContainedTree = null;
+		legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setContained (int index){
+		if (treeSourceTask instanceof OneTreeSource)
+			return;
+		resetAssociation(treeDisplay.getTaxa(), true);
+		if (containedTaxa == null)
+			return;
+		if (index<((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa) && index>=0)
+			currentContained=index;
+		currentContainedTree = null;
+		legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+		if (!MesquiteThread.isScripting()){
+			recalculatePositions(rememberedTree);
+			treeDisplay.repaintAll();
+			treeDisplay.pleaseUpdate(true);
+		}
+	}
+	/*_________________________________________________*/
+	public void zapContained(){
+		currentContainedTree=null;
+	}
+	void containedSourceChanged(){
+		if (treeSourceTask!=null && legend!=null && treeSourceTask instanceof TreeSource) {
+			int numtrees =  ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa);
+			if (currentContained>=numtrees)
+				currentContained = numtrees-1;
+			legend.adjustScroll(currentContained, numtrees);
+			((TreeSource)treeSourceTask).setPreferredTaxa(containedTaxa);
+		}
+	}
+	/*_________________________________________________*/
+	public void resetAssociation(Taxa containingTaxa, boolean force){
+		if (ownerModule.suppressed) {
+			force = true;
+			return;
+		}
+		if (force || association == null || (association.getTaxa(0)!= containingTaxa && association.getTaxa(1)!= containingTaxa)) {
+			association = associationTask.getCurrentAssociation(containingTaxa);
+			if (association == null)
+				association = associationTask.getAssociation(containingTaxa, 0);
+			if (association == null)
+				return;
+			if (association.getTaxa(0)== containingTaxa)
+				containedTaxa = association.getTaxa(1);
+			else
+				containedTaxa = association.getTaxa(0);
+			if (treeSourceTask instanceof TreeSource) {
+				legend.adjustScroll(currentContained, ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa));
+				((TreeSource)treeSourceTask).setPreferredTaxa(containedTaxa);
+			}
+		}
+		resetContainedTree(containedTaxa); 
+	}
+	/*_________________________________________________*/
+	private void resetContainedTree(Taxa containedTaxa){
+		if (ownerModule.suppressed || ownerModule.isDoomed())
+			return;
+		Tree t;
+		if (treeSourceTask instanceof OneTreeSource)
+			t = ((OneTreeSource)treeSourceTask).getTree(containedTaxa);
+		else
+			t = ((TreeSource)treeSourceTask).getTree(containedTaxa, currentContained); 
+		if (t instanceof MesquiteTree)
+			originalContainedTree = (MesquiteTree)t;
+		else {
+			if (t == null) {
+				if (MesquiteThread.isScripting())
+					MesquiteMessage.warnUser("Error: no contained tree " + currentContained);
+					else MesquiteMessage.warnProgrammer("Error: no contained tree " + currentContained);
+			}
+			else
+				MesquiteMessage.warnProgrammer("Error: contained tree not of class MesquiteTree ");
+			originalContainedTree = null;
+		}
+		ownerModule.originalContainedTree = originalContainedTree;
+		if (ownerModule.depWindowMaker!=null)
+			ownerModule.depWindowMaker.setTree(originalContainedTree);
+	}
+	/*_________________________________________________*/
+	private double findMaxWidth(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			if (tree.nodeIsTerminal(node))
+				return widths.getValue(node);
+
+			double mw = MesquiteDouble.unassigned;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				mw = MesquiteDouble.maximum(mw, findMaxWidth(tree, d));
+			return mw;
+		}
+		return (MesquiteDouble.unassigned);
+	}
+	MesquiteNumber cost = new MesquiteNumber();
+	MesquiteString resultString = new MesquiteString();
+
+	Tree rememberedTree = null;
+	void desuppress(){
+		recalculatePositions(rememberedTree);
+		treeDisplay.pleaseUpdate(false);
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {  
+		if (ownerModule.suppressed) {
+			rememberedTree = tree;
+			return;
+		}
+		if (MesquiteTree.OK(tree)) {
+
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			widths = tree.getWhichAssociatedDouble(widthNameReference);
+			if (widths!=null)
+				maxWidth = findMaxWidth(tree, tree.getRoot());
+
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			int drawnRoot = getDrawnRoot();
+			resetAssociation(tree.getTaxa(), rememberedTree == tree);
+			rememberedTree = tree;
+			calcBranchPolys(tree, drawnRoot);
+			if (association == null) {
+				originalContainedTree = null;
+				return;
+			}
+			if (originalContainedTree== null || containedTaxa !=currentContainedTaxa || currentContainedTree==null) 
+				resetContainedTree(containedTaxa); 
+
+			if (originalContainedTree !=null){
+				if (miniX==null || oldNumSpaces != originalContainedTree.getNumNodeSpaces()){
+					miniX = new int[originalContainedTree.getNumNodeSpaces()];
+					miniY = new int[originalContainedTree.getNumNodeSpaces()];
+					inTree = new boolean[originalContainedTree.getNumNodeSpaces()];
+					oldNumSpaces = originalContainedTree.getNumNodeSpaces();
+				}
+				if (tree!=currentTree || tree.getVersionNumber()!=currentTree.getVersionNumber() || containedTaxa != currentContainedTaxa || currentContainedTree != originalContainedTree || association!= currentAssociation) {
+					cost.setToUnassigned();
+					if (originalContainedTree!=null) {
+						if (containedTree!=null && containedTree instanceof MesquiteTree && originalContainedTree instanceof MesquiteTree && containedTaxa == currentContainedTaxa)
+							containedTree.setToClone(originalContainedTree);
+						else
+							containedTree = originalContainedTree.cloneTree(); //no need to establish listener to Taxa, as will be remade when needed?
+					}
+
+					history = reconstructTask.reconstructHistory(tree, containedTree, association, cost, resultString); //TODO: pass back string describing cost (e.g. "deep coalescence cost"
+					if (history != null){
+						MesquiteInteger duplications = new MesquiteInteger(0);
+						MesquiteInteger extinctions = new MesquiteInteger(0);
+						history.countDuplicationsExtinctions(tree, containedTree, duplications, extinctions);
+						resultString.append("\nor:  " + duplications.getValue() + " Duplications, " + extinctions.getValue() + " Extinctions\n");	
+					}
+				}
+			}
+			if (originalContainedTree == null) {
+				return;
+			}
+
+			for (int i=0; i< inTree.length; i++)
+				inTree[i] = false;
+			multipleHomes = false;
+			if (association !=null)
+				checkInTree(tree, containedTree, containedTree.getRoot());
+			IntegerArray.zeroArray(miniX);
+			IntegerArray.zeroArray(miniY);
+			currentTree=tree;
+			currentContainedTree = originalContainedTree;
+
+			currentContainedTaxa = containedTaxa;
+			currentAssociation = association;
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) { //TODO: use drawnRoot
+		if (ownerModule.suppressed)
+			return;
+		if (MesquiteTree.OK(tree)) {
+
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			if (legend!=null){
+				legend.adjustLocation();
+				legend.setVisible(true);
+			}
+
+			if (textRotator == null || textRotator.getNumStrings() < containedTaxa.getNumTaxa())
+				textRotator = new TextRotator(containedTaxa.getNumTaxa()+2);
+
+			String tex = "";
+			if (originalContainedTree == null)
+				tex += "Contained tree is unavailable";
+			else 
+				tex += originalContainedTree.getName() + ParseUtil.lineEnding() + resultString;
+			tex += ParseUtil.lineEnding() +  "[" + treeSourceTask.getNameAndParameters() + "]";
+			if (legend!=null){
+				legend.setText(tex);
+				legend.repaint();
+			}
+			g.setColor(containingColor);
+			drawBranches(tree, g, drawnRoot);  
+			g.setColor(Color.white);
+			whiteBranches(tree, g, drawnRoot);  
+			if (!multipleHomes) {
+				g.setColor(resolvedColor);
+				if (association!=null && tree!=null && containedTree !=null) {
+					drawContained(tree, g, drawnRoot); 
+				} 
+			}
+			g.setColor(Color.black);
+		}
+	}
+
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		Rectangle box;
+		int ew = edgeWidth-2;
+
+		box = new Rectangle(x[node], y[node]-ew-3, ew, boxHeight);
+		g.fillRect(box.x, box.y, box.width, box.height);
+		g.setColor(Color.black);
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		Rectangle box;
+		int ew = edgeWidth-2;
+		int numColors = colors.getNumColors();
+		if (numColors == 0) numColors = 1;
+
+		box = new Rectangle(x[node], y[node]-ew-3, ew, boxHeight);
+		for (int i=0; i<colors.getNumColors(); i++) {
+			Color color;
+			if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+				g.setColor(color);
+			g.fillRect(box.x + (i*box.width/numColors), box.y, box.width-  (i*box.width/numColors), box.height);
+		}
+		g.setColor(Color.black);
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			int numColors = colors.getNumColors();
+
+			for (int i=0; i<numColors; i++) {
+				UPdefineFillPoly(node, utilityPolygon, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+				Color color;
+				if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+					g.setColor(color);
+				g.fillPolygon(utilityPolygon);
+			}
+			g.setColor(Color.black);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (fillBranchPoly[node] !=null && node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			g.fillPolygon(fillBranchPoly[node]);
+		}
+	}
+
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int halfNodeWidth = getNodeWidth()/2;
+		int startX =0;
+		int startY =0;
+		if (treeDisplay.getOrientation()==TreeDisplay.UP || treeDisplay.getOrientation()==TreeDisplay.DOWN){
+			startX = x[node]-offset;
+			startY= y[node]-offset;
+		}	else if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT){
+			startX = x[node];
+			startY= y[node]-offset;
+		}
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(startX,startY);
+		poly.addPoint(startX+getNodeWidth(),startY);
+		poly.addPoint(startX+getNodeWidth(),startY+offset*2);
+		poly.addPoint(startX,startY+offset*2);
+		poly.addPoint(startX,startY);
+		poly.npoints=5;
+		return poly;
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y, MesquiteDouble fraction){
+		if (foundBranch==0) {
+			if (branchPoly != null && branchPoly[node] != null && branchPoly[node].contains(x, y) || inNode(node,x,y)){
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) 
+							fraction.setValue(GraphicsUtil.fractionAlongLine(x, y, this.x[motherNode], this.y[motherNode], this.x[node], this.y[node],false,true));
+						}
+					}
+			}
+			if (!tree.getAssociatedBit(triangleNameRef, node)) 
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					ScanBranches(tree, d, x, y, fraction);
+
+		}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, drawnRoot, x, y, fraction);
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+	//	treeDisplay.setOrientation(orientation);
+	//	treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgeWidth = edw;
+	}
+	/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgeWidth;
+	}
+	/*End new code Feb.22.07 oliver*/
+	/*_________________________________________________*/
+	public   void dispose() { 
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = null;
+			fillBranchPoly[i] = null;
+		}
+		extra.removePanelPlease(legend);
+		super.dispose();
+	}
+
+}
+
+/* ======================================================================== */
+class ContainedLegend extends TreeDisplayLegend {
+	private ContainedAssociates ownerModule;
+	public MiniScroll treeScroll = null;
+	private TreeDrawing tcOp;
+	private static final int defaultLegendWidth=142;
+	private static final int defaultLegendHeight=160;
+	private int oldNumTrees = 0;
+	private int oldCurrentTree = -1;
+	final int scrollAreaHeight = 41;
+	String treeName = "Untitled tree";
+	TextArea text;
+	public ContainedLegend(ContainedAssociates ownerModule, TreeDrawing tcOp) {
+		super(tcOp.treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		setVisible(false);
+		this.tcOp = tcOp;
+		this.ownerModule = ownerModule;
+
+		setOffsetX(ownerModule.initialOffsetX);
+		setOffsetY(ownerModule.initialOffsetY);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+		add(text = new TextArea("", 6, 3, TextArea.SCROLLBARS_NONE));
+		text.setEditable(false);  
+		text.setBackground(Color.lightGray);
+		text.setBounds(0, scrollAreaHeight, legendWidth, legendHeight-scrollAreaHeight);
+		text.setLocation(0, scrollAreaHeight);
+		text.setVisible(true);
+
+	}
+
+	public void adjustScroll(int currentTree, int numTrees) {
+		if (treeScroll == null) {
+			treeScroll = new MiniScroll(MesquiteModule.makeCommand("setContained",  ownerModule), false, MesquiteTree.toExternal(currentTree), MesquiteTree.toExternal(0),  MesquiteTree.toExternal(numTrees-1),"tree");
+			add(treeScroll);
+			treeScroll.setLocation(2,18);
+			treeScroll.setColor(Color.blue);
+			repaint();
+			oldNumTrees = numTrees;
+			oldCurrentTree = currentTree;
+		}
+		else {
+			if (oldNumTrees != numTrees) {
+				treeScroll.setMaximumValue(MesquiteTree.toExternal(numTrees -1));
+				oldNumTrees = numTrees;
+			}
+			if (oldCurrentTree != currentTree) {
+				treeScroll.setCurrentValue(MesquiteTree.toExternal(currentTree));
+				oldCurrentTree = currentTree;
+			}
+		}
+	}
+	public void setText(String s){
+		treeName = s;
+		text.setText(s);
+	}
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (treeScroll !=null) {
+			treeScroll.setVisible(b);
+		}
+	}
+
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.setColor(Color.cyan);
+		g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+		g.drawLine(0, scrollAreaHeight, legendWidth-1, scrollAreaHeight);
+		g.setColor(Color.blue);
+		g.drawString("Contained Tree", 4, 14);
+		g.setColor(Color.black);
+		if (text.getBackground() != getBackground())
+			text.setBackground(getBackground());
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+
+}
+/* ======================================================================== */
+class ContainedAssocExtra extends TreeDisplayDrawnExtra {
+	WideTreeDrawing drawing;
+	public ContainedAssocExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay, WideTreeDrawing drawing) {
+		super(ownerModule, treeDisplay);
+		this.drawing = drawing;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+	public   void setTree(Tree tree) {
+		drawing.currentTree = null; //to indicate that association history needs recaclualting
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+	
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){
+		int numbersAtEnd = drawing.history.getNumberContainedNodes(N);
+		int numbersAtStart = -1;
+		int anc = tree.parentOfNode(N,1);
+		if (anc>=0){
+			numbersAtStart = drawing.history.getNumberContainedNodes(anc);
+			MesquiteMessage.println("Number of contained branches at start: "+numbersAtStart + ",  at end: " + numbersAtEnd);
+		}
+		else 
+			MesquiteMessage.println("Number of contained branches at end: " + numbersAtEnd);
+		super.cursorEnterBranch(tree, N, g);
+	}
+
+	
+	
+}
+
+
diff --git a/Source/mesquite/assoc/DepContTreeWindow/DepContTreeWindow.java b/Source/mesquite/assoc/DepContTreeWindow/DepContTreeWindow.java
new file mode 100644
index 0000000..44e4918
--- /dev/null
+++ b/Source/mesquite/assoc/DepContTreeWindow/DepContTreeWindow.java
@@ -0,0 +1,156 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.DepContTreeWindow;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+import mesquite.trees.lib.*;
+
+/* ======================================================================== */
+public class DepContTreeWindow extends SimpleTreeWindowMaker  {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	protected String getMenuName(){
+		return "Contained_Tree";
+	}
+	protected String getDefaultExplanation(){
+		String defaultExplanation = "This window shows the same tree as seen in ";
+		MesquiteWindow eW = getEmployer().getModuleWindow();
+		if (eW !=null)
+			defaultExplanation += eW.getTitle();
+		else
+			defaultExplanation += "a Tree Window";
+		return defaultExplanation;
+	}
+	protected SimpleTreeWindow makeTreeWindow(SimpleTreeWindowMaker stwm, DrawTreeCoordinator dtwc){
+		SimpleTreeWindow tw =  new DepCTreeWindow( this, treeDrawCoordTask);
+		tw.setWindowTitle("Contained Tree");
+		return tw;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Dependent Contained Tree Window";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Displays a single tree (the same as contained within a tree in a tree window)." ;
+	}
+
+
+}
+
+/* ======================================================================== */
+class DepCTreeWindow extends SimpleTreeWindow   {
+	Taxa taxa;
+	DepTreeExtra extra;
+	public int highlightedBranch=0;
+	public DepCTreeWindow ( SimpleTreeWindowMaker ownerModule, DrawTreeCoordinator treeDrawCoordTask){
+		super(ownerModule, treeDrawCoordTask); //infobar
+		extra = new DepTreeExtra(ownerModule, treeDisplay, this);
+		treeDisplay.addExtra(extra);
+		resetTitle();
+	}
+	/*_________________________________________________*/
+	private String findMigrationEvents(Tree tree, int node, ObjectArray array)
+	{
+		String cladeReport = "";
+		Object mig = array.getValue(node);
+		if (mig != null){
+			Vector v = (Vector)mig;
+			if (v.size() >0){
+				cladeReport += "\nMigration events on gene tree branch " + node + ":";
+				for (int i = 0; i< v.size(); i++){
+					Dimension p = (Dimension)v.elementAt(i);
+					cladeReport += ("\nTo node " + p.width + " at generation " + p.height + " from top of tree");
+				}
+			}
+		}
+
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			String s = findMigrationEvents(tree, d, array);
+			if (!StringUtil.blank(s))
+				cladeReport += "\n" + s;
+		}
+
+		return cladeReport;
+	}
+	NameReference migrRef = NameReference.getNameReference("MigrationEvents");
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+
+		String s = "";
+		if (ownerModule.isDoomed())
+			return"";
+		if (tree != null) {
+			s += "Tree: " + tree.writeTree() + "\n";
+			s += "  " + treeDisplay.getTextVersion();
+			ObjectArray migrated = ((Associable)tree).getWhichAssociatedObject(migrRef);
+			if (migrated != null)
+				s += findMigrationEvents(tree, tree.getRoot(), migrated);
+		}
+		return s;
+
+	}
+
+}
+
+/* ======================================================================== */
+class DepTreeExtra extends TreeDisplayExtra {
+	DepCTreeWindow treeWindow;
+	NameReference migrRef = NameReference.getNameReference("MigrationEvents");
+	public DepTreeExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay, DepCTreeWindow treeWindow) {
+		super(ownerModule, treeDisplay);
+		this.treeWindow = treeWindow;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		treeWindow.sizeDisplays();
+	}
+	public   void setTree(Tree tree) {
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+
+	public void cursorEnterBranch(Tree tree, int node, Graphics g){
+		if (!(tree instanceof Associable))
+			return;
+		if (ownerModule.isDoomed())
+			return;
+		ObjectArray migrated = ((Associable)tree).getWhichAssociatedObject(migrRef);
+		if (migrated != null){
+			Object mig = migrated.getValue(node);
+			if (mig != null){
+				Vector v = (Vector)mig;
+				if (v.size() ==0)
+					return;
+				ownerModule.logln("Migration events on gene tree branch " + node + ":");
+				for (int i = 0; i< v.size(); i++){
+					Dimension p = (Dimension)v.elementAt(i);
+					ownerModule.logln("To node " + p.width + " at generation " + p.height + " from top of containing branch");
+				}
+			}
+		}
+
+	}
+}
+
+
diff --git a/Source/mesquite/assoc/ManageAssociations/ManageAssociations.java b/Source/mesquite/assoc/ManageAssociations/ManageAssociations.java
new file mode 100644
index 0000000..8965e44
--- /dev/null
+++ b/Source/mesquite/assoc/ManageAssociations/ManageAssociations.java
@@ -0,0 +1,745 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.ManageAssociations;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ========================================================================  */
+public class ManageAssociations extends AssociationsManager {
+	ListableVector associationsVector; //establish listeners to all of the taxa
+	ListableVector blocks;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationsVector = new ListableVector();
+		blocks = new ListableVector();
+		return true;
+	}
+ 	public String getKeywords(){
+ 		return "genes species";
+ 	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	public void elementsReordered(ListableVector v){
+		if (v == associationsVector){
+			NexusBlock.equalizeOrdering(v, getProject().getNexusBlocks());
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "New Association...", makeCommand("newAssociation",  this));
+		MesquiteSubmenuSpec mss = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Edit Association", makeCommand("editAssociation",  this), associationsVector);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof TaxaAssociation){
+			TaxaAssociation t = (TaxaAssociation)e;
+			editInTaxonList(t, false);
+			/*
+			for (int i=0; i<blocks.size(); i++){
+				AssociationsBlock ab = (AssociationsBlock)blocks.elementAt(i);
+				if (ab.getAssociation()==t){
+					edit(ab);
+					break;
+				}
+			}*/
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void deleteElement(FileElement e){
+		if (e instanceof TaxaAssociation){
+			TaxaAssociation t = (TaxaAssociation)e;
+			t.doom();
+			getProject().removeFileElement(t);//must remove first, before disposing
+			associationsVector.removeElement(t, false);
+			for (int i=0; i<blocks.size(); i++){
+				AssociationsBlock ab = (AssociationsBlock)blocks.elementAt(i);
+				if (ab.getAssociation()==t){
+					blocks.removeElement(ab, false);
+					break;
+				}
+			}
+			t.dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfAssociations(Taxa taxaA, Taxa taxaB){
+		int count=0;
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+			if ((association.getTaxa(0) == taxaA && association.getTaxa(1) == taxaB)||(association.getTaxa(0) == taxaB && association.getTaxa(1) == taxaA)) //TODO: use looser rules of taxa being equal, using taxa.equals()
+				count++;
+		}
+		return count;
+	}
+	public int getNumberOfAssociations(Taxa taxa){
+		int count=0;
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+			if (association.getTaxa(0) == taxa || association.getTaxa(1) == taxa) //TODO: use looser rules of taxa being equal, using taxa.equals()
+				count++;
+		}
+		return count;
+	}
+	public int getNumberOfAssociations(){
+		return associationsVector.size();
+	}
+	public TaxaAssociation getAssociation(Taxa taxaA, Taxa taxaB, int index){
+		int count=0;
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+			if ((association.getTaxa(0) == taxaA && association.getTaxa(1) == taxaB)||(association.getTaxa(0) == taxaB && association.getTaxa(1) == taxaA)){ //TODO: use looser rules of taxa being equal, using taxa.equals()
+				if (count == index)
+					return association;
+				count++;
+			}
+		}
+		return null;
+	}
+	public int getWhichAssociation(Taxa taxa, TaxaAssociation assoc){
+		int count=0;
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+			if (assoc == association)
+				return count;
+			if (association.getTaxa(0) == taxa || association.getTaxa(1) == taxa) {//TODO: use looser rules of taxa being equal, using taxa.equals()
+				count++;
+			}
+		}
+		return -1;
+	}
+	public TaxaAssociation getAssociation(Taxa taxa, int index){
+		int count=0;
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+			if (association.getTaxa(0) == taxa || association.getTaxa(1) == taxa) {//TODO: use looser rules of taxa being equal, using taxa.equals()
+				if (count == index)
+					return association;
+				count++;
+			}
+		}
+		return null;
+	}
+	public TaxaAssociation getAssociation(int i){
+		return (TaxaAssociation)associationsVector.elementAt(i);
+
+	}
+	public TaxaAssociation findAssociationByID(long id, Taxa taxa){
+		for (int i=0; i<associationsVector.size(); i++){
+			TaxaAssociation association = (TaxaAssociation)associationsVector.elementAt(i);
+
+			if ((association.getTaxa(0) == taxa || association.getTaxa(1) == taxa) && association.getID() == id) {
+				return association;
+			}
+		}
+		return null;
+	}
+	public ListableVector getAssociationsVector(){
+		return associationsVector;
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		int place = associationsVector.indexOf(e);
+		if (place>=0) {
+			//review all current associations; if taxa included don't exist in project, then remove listener from taxa
+			associationsVector.removeElement(e, true);
+			blocks.removeElement(blocks.elementAt(place), false);
+		}
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof Taxa){
+			if (code==MesquiteListener.PARTS_CHANGED) {
+				for (int i = 0; i<associationsVector.size(); i++){
+					TaxaAssociation assoc = (TaxaAssociation)associationsVector.elementAt(i);
+					if (obj == assoc.getTaxa(0) || obj == assoc.getTaxa(1))
+						assoc.resetTaxaAfterChange();
+
+				}
+			}
+			else if (code==MesquiteListener.PARTS_ADDED) {
+				for (int i = 0; i<associationsVector.size(); i++){
+					TaxaAssociation assoc = (TaxaAssociation)associationsVector.elementAt(i);
+					if (obj == assoc.getTaxa(0) || obj == assoc.getTaxa(1))
+						assoc.resetTaxaAfterChange();
+
+				}
+			}
+			else if (code==MesquiteListener.PARTS_DELETED) {
+				for (int i = 0; i<associationsVector.size(); i++){
+					TaxaAssociation assoc = (TaxaAssociation)associationsVector.elementAt(i);
+					if (obj == assoc.getTaxa(0) || obj == assoc.getTaxa(1))
+						assoc.resetTaxaAfterChange();
+
+				}
+			}
+			else if (code==MesquiteListener.PARTS_MOVED) {
+			}
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa){
+			//delete associations involving those taxa
+			for (int i = 0; i<associationsVector.size(); i++){
+				TaxaAssociation assoc = (TaxaAssociation)associationsVector.elementAt(i);
+				if (obj == assoc.getTaxa(0) || obj == assoc.getTaxa(1))
+					deleteElement((FileElement)assoc);
+
+			}
+		}
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public NexusBlock elementAdded(FileElement e){
+		if (e==null || !(e instanceof TaxaAssociation))
+			return null;
+		TaxaAssociation assoc = (TaxaAssociation)e;
+		NexusBlock nb = findNEXUSBlock(assoc);
+		if (nb==null) {
+			AssociationsBlock t = new AssociationsBlock(assoc.getFile(), this);
+			Taxa tax = assoc.getTaxa(0);
+			if (tax!=null && !tax.amIListening(this))
+				tax.addListener(this);
+			tax = assoc.getTaxa(1);
+			if (tax!=null && !tax.amIListening(this))
+				tax.addListener(this);
+			t.setAssociation(assoc);
+			addNEXUSBlock(t);
+			resetAllMenuBars();
+			if (blocks.indexOf(t)<0)
+				blocks.addElement(t, false);
+			if (associationsVector.indexOf(assoc)<0)
+				associationsVector.addElement(assoc, false);
+			return t;
+		}
+		else return nb;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new AssociationBlockTest();}
+	/*.................................................................................................................*/
+	/* public Snapshot getSnapshot(MesquiteFile file) {
+   	 	if (editor!=null && blocks !=null && editor.getCurrentBlock()!=null) {
+	   	 	Snapshot temp = new Snapshot();
+	   	 	temp.addLine("editAssociation " + blocks.indexOf(editor.getCurrentBlock()), editor);
+	 	 	return temp;
+ 	 	}
+ 	 	else return null;
+  	 }*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	/*.................................................................................................................*/
+	private Object editInTaxonList(TaxaAssociation toBeEdited, boolean useFirst){
+		if (toBeEdited == null)
+			return null;
+		TaxaManager manageTaxa = (TaxaManager)findElementManager(Taxa.class);
+		int whichTaxa = 0;
+		if (!useFirst && !MesquiteThread.isScripting()){
+			String f = toBeEdited.getTaxa(0).getName();
+			String s = toBeEdited.getTaxa(1).getName();
+			String fString = f;
+			String sString = s;
+			if (fString.length()>20)
+				fString = fString.substring(0, 19);
+			if (sString.length()>20)
+				sString = sString.substring(0, 19);
+			if (fString.equalsIgnoreCase(sString)){
+				fString = "First Block";
+				sString = "Second Block";
+			}
+			
+			boolean t = AlertDialog.query(containerOfModule(), "Which taxa?", "This is an association between a first block of taxa:\n\n\"" + f + "\"\n\n and a second block of taxa:\n\n\"" + s + "\"\n\nFrom the perspective of which block of taxa do you want to edit the association?", fString, sString, -1);
+			if (t)
+				whichTaxa = 0;
+			else
+				whichTaxa = 1;
+		}
+		MesquiteModule list = manageTaxa.getListOfTaxaModule(toBeEdited.getTaxa(whichTaxa), true);
+		
+
+
+		if (list == null) 
+			return null;
+		//here ask each list imployee if they have this assocaition shown; otherwise finish script
+		EmployeeVector e = list.getEmployeeVector();
+		if (e != null){
+			for (int i = 0; i< e.size(); i++){
+				if (e.elementAt(i) instanceof mesquite.assoc.TaxonListAssoc.TaxonListAssoc){
+					mesquite.assoc.TaxonListAssoc.TaxonListAssoc t = (mesquite.assoc.TaxonListAssoc.TaxonListAssoc)e.elementAt(i);
+					if (t.isShowing(toBeEdited))
+						return toBeEdited;
+				}
+			}
+		}
+		Puppeteer p = new Puppeteer(this);
+		MesquiteInteger pos = new MesquiteInteger(0);
+
+		String commands =  "getWindow; tell It; setSize 680 400; newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc; tell It;";
+		commands +=  "getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations; tell It; setCurrentAssociationID ";
+		//here put number of this taxa assoc
+		commands +=  toBeEdited.getID();
+		commands +=  "; endTell;";
+		commands +=  "endTell; endTell;";
+		pos.setValue(0);
+		CommandRecord cRecord = new CommandRecord(true);
+		CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+		MesquiteThread.setCurrentCommandRecord(cRecord);
+		
+		p.execute(list, commands, pos, "", false);
+		MesquiteThread.setCurrentCommandRecord(prevR);
+		return toBeEdited;
+	}
+	/*.................................................................................................................*/
+	private Object edit(AssociationsBlock toBeEdited){
+		if (toBeEdited == null)
+			return null;
+		String s = toBeEdited.getText();
+		String newBlock = MesquiteString.queryMultiLineString(containerOfModule(), "Edit Assocation", "Edit TaxaAssociation block \"" + toBeEdited.getAssociation().getName() + "\"", s, 18, false, true);
+		if (newBlock!=null)
+			toBeEdited.setText(newBlock);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Calls up the association editor window", "[number of association block to edit]", commandName, "editAssociation")) {
+			//find which block first
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which) || which>= blocks.size())
+				return null;
+			AssociationsBlock toBeEdited = (AssociationsBlock)blocks.elementAt(which);
+			if (toBeEdited == null)
+				return null;
+			return editInTaxonList(toBeEdited.getAssociation(), false);
+		}
+		else if (checker.compare(this.getClass(), "Shows a dialog box with an example association block", null, commandName, "exampleAssociation")) {
+			String lin = StringUtil.lineEnding();
+			String example = "BEGIN TaxaAssociation;"+lin+"TITLE genes_in_species;"+lin+"TAXA  species ,  genes;"+lin+"ASSOCIATES"+lin+"	speciesA /  geneA1 geneA2 geneA3 , "+lin+"	speciesB /  geneB1 geneB2, "+lin+"	speciesC /  geneC1 geneC2 geneC3  geneC4, "+lin+";"+lin+"END;";
+			AlertDialog.bigNotice(containerOfModule(), "Example Association block", example);
+		}
+		else if (checker.compare(this.getClass(), "Creates a new Association block (for scripting)", "[number of taxa A][number of taxa B][name of association]", commandName, "makeAssociation")) {
+			MesquiteProject project = getProject();
+			if (project.getNumberTaxas()==1){
+				discreetAlert( "You can't create an Association between two sets of taxa if there is only one set of taxa available.  Please make a second set of taxa.");
+				return null;
+			}
+			MesquiteInteger io = new MesquiteInteger(0);
+			int a = MesquiteInteger.fromString(arguments, io);
+			int b = MesquiteInteger.fromString(arguments, io);
+			String name = ParseUtil.getToken(arguments, io);
+
+			if (!MesquiteInteger.isCombinable(a) || !MesquiteInteger.isCombinable(b))
+				return null;
+			Taxa taxaA = project.getTaxa(a);
+			if (taxaA == null)
+				return null;
+			Taxa taxaB = project.getTaxa(b);
+			if (taxaA == null)
+				return null;
+			MesquiteFile file=project.getHomeFile();
+
+			if (StringUtil.blank(name))
+				name=associationsVector.getUniqueName("Taxa Association");
+			TaxaAssociation association = new TaxaAssociation();
+			associationsVector.addElement(association, false);
+			association.setTaxa(taxaA, 0);
+			association.setTaxa(taxaB, 1);
+			association.setName(name);
+			association.setAssociation(taxaA.getTaxon(0), taxaB.getTaxon(0), true);
+			AssociationsBlock toBeEdited = (AssociationsBlock)association.addToFile(file, project, this); 
+			if (blocks.indexOf(toBeEdited)<0)
+				blocks.addElement(toBeEdited, false);
+			resetAllMenuBars();
+			return association;
+		}
+		else if (checker.compare(this.getClass(), "Creates a new Association block", null, commandName, "newAssociation")) {
+			
+			TaxaAssociation association = makeNewAssociation(null, null);
+			if (association == null)
+				return null;
+			return editInTaxonList(association, true);
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public TaxaAssociation makeNewAssociation(Taxa taxaA, Taxa taxaB){
+		/* get taxa A, taxa B */
+		MesquiteProject project = getProject();
+		if (project.getNumberTaxas()==1){
+			discreetAlert( "You can't create an Association between two sets of taxa if there is only one set of taxa available.  Please make a second set of taxa.");
+			return null;
+		}
+		ListableVector taxas = project.getTaxas();
+		String helpString = "If you are interested in building this association between two sets of  taxa to reflect an association between species trees and gene trees, host and parasite, and the like, ";
+		helpString += "then we suggest you choose the first set of taxa to be the containing taxa (e.g., species, host), and the second set to be the contained taxa (e.g., gene, parasite). ";
+		
+		helpString += "\n\nIf, on the other hand, you are building the association between sets of taxa to link two matrices (e.g., two matrices from similar taxa but for different genes), ";
+		helpString += "then we suggest you choose the first set of taxa to be the master one, containing the 'official' names for the taxa.";
+		if (taxaA == null) 
+			taxaA = (Taxa)ListDialog.queryList(containerOfModule(), "Select taxa", "Select first block of taxa for the association, e.g. the containing or master taxa.  If you are analyzing gene trees within species trees, select here the species taxa block.", helpString, taxas, 0);
+		if (taxaA == null)
+			return null;
+		if (taxaB == null){
+			if (project.getNumberTaxas()>2) {
+				Listable[] others = new Listable[project.getNumberTaxas()-1];
+				int count =0;
+				for (int i=0; i<project.getNumberTaxas(); i++){
+					Taxa t = project.getTaxa(i);
+					if (t!= taxaA)
+						others[count++] = t;
+				}
+				taxaB = (Taxa)ListDialog.queryList(containerOfModule(), "Select taxa", "Select second block of taxa for the association, e.g. the contained taxa.  If you are analyzing gene trees within species trees, select here the genes taxa block.", helpString, others, 0);
+				if (taxaB==null)
+					return null;
+			}
+			else {
+				int a = project.getTaxaNumber(taxaA);
+				if (a==0)
+					taxaB = project.getTaxa(1);
+				else
+					taxaB = project.getTaxa(0);
+			}
+		}
+		MesquiteFile file=chooseFile( taxaA,taxaB);
+
+		if (taxaA==null ||taxaB==null || file == null)
+			return null;
+		String name = MesquiteString.queryString(containerOfModule(), "Name of Association", "Association", associationsVector.getUniqueName("Taxa Association"));
+		if (name==null)
+			return null;
+		if (StringUtil.blank(name))
+			name=associationsVector.getUniqueName("Taxa Association");
+		resetAllMenuBars();
+		/* user choose title */
+		TaxaAssociation association = new TaxaAssociation();
+		associationsVector.addElement(association, false);
+		association.setTaxa(taxaA, 0);
+		association.setTaxa(taxaB, 1);
+		association.setName(name);
+		AssociationsBlock toBeEdited = (AssociationsBlock)association.addToFile(file, project, this); 
+		if (blocks.indexOf(toBeEdited)<0)
+			blocks.addElement(toBeEdited, false);
+		return association;
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile chooseFile( Taxa taxa0, Taxa taxa1){  //changed 13 Dec 01 to specify data so as to do check on which file can be
+		MesquiteFile file=null;
+		if (getProject().getNumberLinkedFiles()==1)
+			file = getProject().getHomeFile();
+		else {
+			Listable[] files = getProject().getFiles().getElementArray();
+			if (files.length >1) {
+
+				int count = 0;
+				int taxaFound = 0;
+				for (int i=0; i<files.length; i++) {
+					if (files[i] == taxa0.getFile())
+						taxaFound++;
+					if (files[i] == taxa1.getFile())
+						taxaFound++;
+					if (taxaFound==2)
+						count++;
+				}
+				if (count!=files.length){
+					Listable[] legalFiles = new Listable[count];
+					count = 0;
+					taxaFound = 0;
+					for (int i=0; i<files.length; i++) {
+						if (files[i] == taxa0.getFile())
+							taxaFound++;
+						if (files[i] == taxa1.getFile())
+							taxaFound++;
+						if (taxaFound==2) {
+							legalFiles[count] = files[i];
+							count++;
+						}
+					}
+					files = legalFiles;
+				}
+
+			}
+			if (files.length == 1 || MesquiteThread.isScripting())
+				return (MesquiteFile)files[0];
+			file = (MesquiteFile)ListDialog.queryList(containerOfModule(), "Select file", "Select file to which to add the new association",MesquiteString.helpString,  files, 0);
+		}
+		return file;
+	}
+
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+		if (fuse)
+			return null;
+		return processText(file, name, block.toString(), block, null, blockComments);
+	}
+	/*.................................................................................................................*/
+	public NexusBlock processText(MesquiteFile file, String name, String blockAsString, FileBlock block, NexusBlock current, StringBuffer blockComments){
+		Parser commandParser = new Parser();
+		commandParser.setString(blockAsString);
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		TaxaAssociation association=null;
+		Taxa taxaA=null;
+		Taxa taxaB=null;
+		String title=null;
+		String s;
+		while (!StringUtil.blank(s=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(s);
+			if (commandName.equalsIgnoreCase("TAXA")) {
+				String nameTaxaA = parser.getNextToken();
+				if ("=".equals(nameTaxaA))
+					nameTaxaA = parser.getNextToken();
+				taxaA = getProject().getTaxaLastFirst(nameTaxaA);
+				if (taxaA == null) 
+					return null;
+				parser.getNextToken(); //eating ","
+				String nameTaxaB = parser.getNextToken();
+				taxaB = getProject().getTaxaLastFirst(nameTaxaB);
+				if (taxaB == null) 
+					return null;
+
+				if (current==null){
+					association = new TaxaAssociation();
+					associationsVector.addElement(association, false);
+				}
+				else
+					association = ((AssociationsBlock)current).getAssociation();
+				association.setTaxa(taxaA, 0);
+				association.setTaxa(taxaB, 1);
+				if (title!=null)
+					association.setName(title);
+				if (current ==null) {
+					current = association.addToFile(file, getProject(), this);  
+					if (blocks.indexOf(current)<0)
+						blocks.addElement(current, false);
+				}
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				title = parser.getTokenNumber(2);
+			}
+			else if (commandName.equalsIgnoreCase("ASSOCIATES") && association!=null && taxaA!=null && taxaB!=null) {
+				String taxonName;
+				boolean doneTaxa = false;
+				int[] whichA = new int[taxaA.getNumTaxa()];
+				for (int i=0; i<whichA.length; i++)
+					whichA[i]=-1;
+				while (!doneTaxa){
+					taxonName=parser.getNextToken();
+					if (StringUtil.blank(taxonName) || ";".equals(taxonName))
+						doneTaxa = true;
+					else {
+						//find which taxon is taxonName
+						int iFound = 0;
+						int wA = -1;
+						do {
+							if ("/".equals(taxonName))
+								wA = -1;
+							else {
+								wA = taxaA.whichTaxonNumber(taxonName);
+								if (wA<0) {
+									String sw = ("Illegal taxon name in TAXAASSOCIATION block: " + taxonName + " for taxa set " + taxaA.getName());
+									if (file ==null)
+										MesquiteMessage.warnProgrammer(sw);
+									else
+										file.setOpenAsUntitled(sw);
+								}
+								else {
+									whichA[iFound] = wA;
+									iFound++;
+								}
+								taxonName = parser.getNextToken();//eating up next
+							}
+						} while (wA >=0);
+
+						String associateName;
+						boolean doneAssociates = false;
+						while (!doneAssociates){
+							associateName=parser.getNextToken();
+							if (StringUtil.blank(associateName) || ",".equals(associateName) || ";".equals(associateName)){
+								doneAssociates = true;
+								if (";".equals(associateName))
+									doneTaxa = true;
+							}
+							else {
+								int whichB = taxaB.whichTaxonNumber(associateName);
+								if (whichB<0) {
+									String sw = ("Illegal taxon name in TAXAASSOCIATIONS block: " + associateName + " for taxa set " + taxaB.getName());
+									if (file ==null)
+										MesquiteMessage.warnProgrammer(sw);
+									else
+										file.setOpenAsUntitled(sw);
+								}
+								for (int i =0; i<whichA.length && whichA[i] >= 0; i++){
+									if (whichA[i] != -1 && whichB != -1 && taxaA.getTaxon(whichA[i])!=null && taxaB.getTaxon(whichB)!=null) {
+										association.setAssociation(taxaA.getTaxon(whichA[i]), taxaB.getTaxon(whichB), true);
+									}
+								}
+							}
+						}
+					}
+					// read /
+					//read associates until comma
+				}
+			}
+			else if (current!=null && !(commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK"))) 
+				readUnrecognizedCommand(file, current, name, block, commandName, s, blockComments, null);
+		}
+		//a.setAssociation(association);
+		return current;
+	}
+	/*.................................................................................................................*/
+	public String getAssocBlock(TaxaAssociation association, AssociationsBlock aB){
+		String block = "";
+		block+="BEGIN TaxaAssociation;" + StringUtil.lineEnding() + "TITLE " + StringUtil.tokenize(association.getName()) + ";" + StringUtil.lineEnding();
+		Taxa taxaA =association.getTaxa(0);
+		Taxa taxaB =association.getTaxa(1);
+		block+="TAXA " + StringUtil.tokenize(taxaA.getName()) +  " ,  " + StringUtil.tokenize(taxaB.getName())+ ";"  + StringUtil.lineEnding();
+		block+="ASSOCIATES " + StringUtil.lineEnding();
+		String assoc = "";
+		boolean first = true;
+		for (int a=0; a<taxaA.getNumTaxa(); a++) {
+			Taxon taxonA = taxaA.getTaxon(a);
+			if (association.getNumAssociates(taxonA)>0) {
+				if (!first)
+					assoc += " , ";
+				first = false;
+				assoc += StringUtil.lineEnding();
+
+				assoc += "\t" + StringUtil.tokenize(taxonA.getName()) + " / ";
+				for (int b = 0; b<taxaB.getNumTaxa(); b++) {
+					Taxon taxonB = taxaB.getTaxon(b);
+					if (association.getAssociation(taxonA, taxonB))
+						assoc += " " + StringUtil.tokenize(taxonB.getName());
+
+				}
+			}
+		}
+		assoc += StringUtil.lineEnding();
+		if (assoc.length() == StringUtil.lineEnding().length()){
+			assoc += "[Adjust the following specification to indicate which taxa from the second block of taxa are associated which which taxa from the first block.  Note that as listed by default, all taxa from the second block are associated with the first taxon of the first block.]" + StringUtil.lineEnding() + StringUtil.lineEnding();
+			for (int a=0; a<taxaA.getNumTaxa(); a++) {
+				Taxon taxonA = taxaA.getTaxon(a);
+				if (a>0)
+					assoc += " , " + StringUtil.lineEnding() ;
+				assoc += "\t" + StringUtil.tokenize(taxonA.getName()) + " / ";
+				if (a==0) 
+					for (int b = 0; b<taxaB.getNumTaxa(); b++) {
+						Taxon taxonB = taxaB.getTaxon(b);
+						assoc += " " + StringUtil.tokenize(taxonB.getName());
+
+					}
+				//assoc +=  StringUtil.lineEnding();
+			}
+			assoc += StringUtil.lineEnding();
+		}
+
+		block += assoc;
+		block += StringUtil.lineEnding()+ ";";
+		if (aB != null) block += aB.getUnrecognizedCommands() + StringUtil.lineEnding();
+		block += StringUtil.lineEnding() + "END;" + StringUtil.lineEnding()+ StringUtil.lineEnding();
+		return block;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage TaxaAssociation blocks";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages TaxaAssociation blocks in NEXUS file." ;
+	}
+}
+
+class AssociationsBlock extends NexusBlockEditableRaw {  
+	TaxaAssociation association;
+	ManageAssociations owner;
+	public AssociationsBlock(MesquiteFile f, ManageAssociations mb){
+		super(f, mb);
+		owner = mb;
+	}
+	public void setAssociation(TaxaAssociation a) {
+		association = a;
+	}
+	public boolean contains(FileElement e) {
+		return e!=null && association == e;
+	}
+	/** DOCUMENT */
+	public String getText(){
+		return getNEXUSBlock();
+	}
+	/** DOCUMENT */
+	public void setText(String n){
+		owner.processText(getFile(), getName(), n, null, this, null);
+		association.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+
+	public TaxaAssociation getAssociation() {
+		return association;
+	}
+	public boolean mustBeAfter(NexusBlock block){ 
+		if (block==null)
+			return false;
+		if (association!=null && block instanceof TaxaBlock) {
+			return association.getTaxa(0) == ((TaxaBlock)block).getTaxa() || association.getTaxa(1) == ((TaxaBlock)block).getTaxa();
+		}
+		return (block.getBlockName().equalsIgnoreCase("TAXA"));
+
+	}
+	public String getBlockName(){
+		return "TaxaAssociation";
+	}
+	public String getName(){
+		return "Taxa associations block";
+	}
+	/** Returns the NEXUS block as a string for writing into the file*/
+	public String getNEXUSBlock(){
+		if (getEditor()!=null)
+			getEditor().recordBlock(this);
+		if (association!=null)
+			return owner.getAssocBlock(association, this);
+		else 
+			return null;
+	}
+}
+
+/* ======================================================================== */
+class AssociationBlockTest extends NexusBlockTest  {
+	public AssociationBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("ASSOCIATION") || blockName.equalsIgnoreCase("TAXAASSOCIATION");
+	}
+}
+
+
diff --git a/Source/mesquite/assoc/ManageDistributionBlock/ManageDistributionBlock.java b/Source/mesquite/assoc/ManageDistributionBlock/ManageDistributionBlock.java
new file mode 100644
index 0000000..d2f22fb
--- /dev/null
+++ b/Source/mesquite/assoc/ManageDistributionBlock/ManageDistributionBlock.java
@@ -0,0 +1,196 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.assoc.ManageDistributionBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== 
+Manage's Distribution blocks in NEXUS files  */
+public class ManageDistributionBlock extends MesquiteModule {
+	private AssociationsManager assocTask;
+	private TaxaManager taxaTask;
+	private TreesManager treesTask;
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		taxaTask = (TaxaManager)findElementManager(Taxa.class);
+		assocTask = (AssociationsManager)findElementManager(TaxaAssociation.class);
+		treesTask = (TreesManager)findElementManager(TreeVector.class);
+		return treesTask!=null  && taxaTask!=null && assocTask!=null;
+	}
+	
+	public Class getDutyClass(){
+		return ManageDistributionBlock.class;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new DistributionBlockTest();}
+	/*.................................................................................................................*
+			BEGIN DISTRIBUTION;
+				TITLE = 'Interleukine-1';
+				NTAX = 14;
+				RANGE
+					'Bovine IL-1a': Bovine,
+					'Pig IL-1a': Pig,
+					'Human IL-1a': Human,
+					'Rabbit IL-1a': Rabbit,
+					'Rat IL-1a': Rat,
+					'Mouse IL-1a': Mouse,
+					'Bovine IL-b': Bovine,
+					'Sheep IL-1b': Sheep,
+					'Mouse IL-1b': Mouse,
+					'Human IL-1b': Human,
+					'Human IL-1bm': Human,
+					'Human IL-1ra': Human,
+					'Mouse IL-1ra': Mouse,
+					'Rat IL-1ra': Rat
+					;
+				TREE * T1= ((('Rabbit IL-1a',('Human IL-1a',('Bovine IL-1a','Pig IL-1a'))),('Rat IL-1a','Mouse IL-1a')),((('Bovine IL-b','Sheep IL-1b'),('Mouse IL-1b',('Human IL-1b','Human IL-1bm'))),('Human IL-1ra',('Mouse IL-1ra','Rat IL-1ra'))));
+			ENDBLOCK;
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+	//need to register Taxa block officially as NexusBlock
+		TaxaAssociation association=null;
+		Parser commandParser = new Parser();
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		String title= "Association from DISTRIBUTION";
+		String commandString;
+		Taxa hostTaxa= getProject().getTaxa(file, 0); //get last read TAXA as base
+		Taxa associateTaxa = null;
+		TreeVector trees = null;
+		int numTaxa=0;
+		NexusBlock b = null; //this will be for association block
+		logln("Reading DISTRIBUTION block " + title);
+		while (!commandParser.blankByCurrentWhitespace(commandString=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(commandString);
+			if (commandName.equalsIgnoreCase("DIMENSIONS")) { //TODO: not a very safe way to parse!!!
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				title = parser.getTokenNumber(3);
+			}
+			else if (commandName.equalsIgnoreCase("NTAX")) {
+				//CREATE new contained taxa block here
+				numTaxa = MesquiteInteger.fromString(parser.getTokenNumber(3));
+				associateTaxa = taxaTask.makeNewTaxa(title, numTaxa, false);
+				associateTaxa.addToFile(file, getProject(), taxaTask);
+				//make new Assoc block
+				association = new TaxaAssociation();
+				association.setTaxa(hostTaxa, 0);
+				association.setTaxa(associateTaxa, 1);
+				association.setName(title);
+				association.addToFile(file, getProject(), assocTask);
+				b = assocTask.elementAdded(association);
+			}
+			else if (commandName.equalsIgnoreCase("RANGE")) {
+				if (hostTaxa!=null && associateTaxa !=null){
+					//Here read taxa and their containing taxa one after another
+					boolean done = false;
+					String associateName = parser.getNextToken();
+					int count = 0;
+					while (!done){
+						if (StringUtil.blank(associateName) || ";".equals(associateName))
+							done = true;
+						else {
+							int whichAssociate =associateTaxa.whichTaxonNumber(associateName);
+							if (whichAssociate<0) {
+								associateTaxa.setTaxonName(count, associateName);
+								whichAssociate = count++;
+							}
+							parser.getNextToken(); //eating :
+							String hostName = parser.getNextToken();
+							int whichHost = hostTaxa.whichTaxonNumber(hostName);
+							if (whichHost<0) {
+								String s =("Illegal taxon name in DISTRIBUTION block: " + hostName + " for taxa block " + hostTaxa.getName());
+									if (file ==null)
+										MesquiteMessage.warnProgrammer(s);
+									else
+										file.setOpenAsUntitled(s);
+							}
+							if (whichHost != -1 && whichAssociate != -1 && hostTaxa.getTaxon(whichHost)!=null && associateTaxa.getTaxon(whichAssociate)!=null) {
+								association.setAssociation(hostTaxa.getTaxon(whichHost), associateTaxa.getTaxon(whichAssociate), true);
+							}
+							parser.getNextToken(); //eating ,
+							associateName = parser.getNextToken();
+						}
+					}
+				}
+			}
+			else if (commandName.equalsIgnoreCase("TREE")) {
+				//here read tree description if contained taxa not null
+				//read until ( and send to make tree
+					if (associateTaxa!=null){
+						if (trees == null){
+							trees = new TreeVector( associateTaxa);
+							trees.setTaxa(associateTaxa);
+							NexusBlock t =trees.addToFile(file, getProject(), treesTask);
+						}
+						String treeDescription;
+						String treeName;
+						treeName=parser.getNextToken();
+						if (treeName.equals("*"))
+							treeName=parser.getNextToken();
+						parser.getNextToken(); //eat up "equals"
+						treeDescription=commandString.substring(parser.getPosition(), commandString.length());
+						MesquiteTree thisTree =new MesquiteTree(associateTaxa);
+						/*
+						String commentString = comment.getValue();
+						if (!StringUtil.blank(commentString)) {
+							thisTree.setAnnotation(commentString.substring(1, commentString.length()));
+						}
+						*/
+						thisTree.setTreeVector(trees);
+						trees.addElement(thisTree, false);
+						thisTree.readTree(treeDescription);
+						//warnReticulations
+						thisTree.setName(treeName);
+					}
+			}
+			else if (!(commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK"))) {
+					readUnrecognizedCommand(file,b, name, block, commandName, commandString, blockComments, null);
+			}
+		}
+		return b;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Read DISTRIBUTION blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates the reading of a DISTRIBUTION block in NEXUS file." ;
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+}
+	
+	
+/* ======================================================================== */
+class DistributionBlockTest extends NexusBlockTest  {
+	public DistributionBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("DISTRIBUTION");
+	}
+}
+
+
diff --git a/Source/mesquite/assoc/PartitionFromAssociation/PartitionFromAssociation.java b/Source/mesquite/assoc/PartitionFromAssociation/PartitionFromAssociation.java
new file mode 100644
index 0000000..78fcbea
--- /dev/null
+++ b/Source/mesquite/assoc/PartitionFromAssociation/PartitionFromAssociation.java
@@ -0,0 +1,115 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.assoc.PartitionFromAssociation;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public class PartitionFromAssociation extends TaxaPartitionSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(AssociationSource.class, getName() + " needs a source of taxa associations, from which to derive a taxa partition (grouping).",
+		"The source of assocation is chosen initially");
+	}
+	AssociationSource associationTask;
+	TaxaAssociation association = null;
+	Taxa containingTaxa;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations was found.");
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	/** returns partition for taxa */
+   	public TaxaPartition getPartition(Taxa taxa){
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa);
+        		if (association == null)
+        			association = associationTask.getAssociation(taxa, 0);
+        		if (association == null)
+        			return null;
+        		if (association.getTaxa(0)== taxa)
+        			containingTaxa = association.getTaxa(1);
+        		else
+        			containingTaxa = association.getTaxa(0);
+        	}
+        	/*go through association.  Make as many partitions as there are containing taxa.
+        	If a contained taxon has more than one associate, don't assign it to 
+        	*/
+        	TaxaPartition partition = new TaxaPartition("Partition from Association", taxa.getNumTaxa(), null, taxa);
+        	for (int i= 0; i<containingTaxa.getNumTaxa(); i++){
+        		Taxon containingTaxon = containingTaxa.getTaxon(i);
+        		Taxon[] contained = association.getAssociates(containingTaxon);
+        		if (contained !=null && contained.length>0){
+				TaxaGroup group = new TaxaGroup();
+				group.setName("In " + containingTaxon.getName());
+				for (int j = 0; j< contained.length; j++){
+					if (association.getNumAssociates(contained[j])<=1)
+						partition.setProperty(group,taxa.whichTaxonNumber(contained[j]));
+				}
+			}
+		}
+		return partition;
+   	}
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Taxa partition from Taxa associations";
+   	 }
+   	 
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Constructs a taxa partition from an association." ;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() { //getCompatibilityTest
+  	 	return new PartCompatibilityTest();
+  	 }
+}
+class PartCompatibilityTest extends CompatibilityTest{
+//should find out if available association of chosen sort
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		AssociationsManager manager = null;
+		if (prospectiveEmployer == null) {
+			if (project!=null){
+				MesquiteModule coord = project.getCoordinatorModule();
+				if (coord!=null){
+					manager = (AssociationsManager)coord.findElementManager(TaxaAssociation.class);
+				}
+			}
+		}	
+		else
+			manager = (AssociationsManager)prospectiveEmployer.findElementManager(TaxaAssociation.class);
+		if (manager==null) {
+			return true;
+		}
+		if (obj !=null && obj instanceof Taxa)
+			return (manager.getNumberOfAssociations((Taxa)obj)>0);
+		else
+			return (manager.getNumberOfAssociations()>0);
+		
+	}
+}
+
diff --git a/Source/mesquite/assoc/StoredAssociations/StoredAssociations.java b/Source/mesquite/assoc/StoredAssociations/StoredAssociations.java
new file mode 100644
index 0000000..eeb6f48
--- /dev/null
+++ b/Source/mesquite/assoc/StoredAssociations/StoredAssociations.java
@@ -0,0 +1,198 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.StoredAssociations;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public class StoredAssociations extends AssociationSource implements MesquiteListener {
+	int currentAssociationIndex=MesquiteInteger.unassigned;
+	int currentAssociationID=MesquiteInteger.unassigned;
+	AssociationsManager manager;
+	TaxaAssociation currentAssociation = null;
+	Taxa currentTaxa = null;
+	Taxa currentTaxa2 = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		manager = (AssociationsManager)findElementManager(TaxaAssociation.class);
+		if (manager==null) {
+			return sorry(getName() + " couldn't start because no associations manager was found.");
+		}
+		if (manager.getNumberOfAssociations()==0) {
+			return sorry("No stored associations between taxa are available.");
+		}
+		addMenuItem("Choose Taxa Association...", makeCommand("chooseAssociation", this));
+		return true;
+	}
+ 	public String getKeywords(){
+ 		return "genes species";
+ 	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj) {
+		if (obj == currentAssociation || obj == currentTaxa) {
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean okToDispose(Object obj, int i) {
+		//?? what to do here?
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (!MesquiteInteger.isCombinable(currentAssociationIndex))
+			return null;
+		Snapshot temp = new Snapshot();
+			temp.addLine("setCurrentAssociation " + currentAssociationIndex); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the current association number", "[number of current association]", commandName, "setCurrentAssociation")) {
+			int c= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(c)) {
+				currentAssociationIndex = c;
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the current association number by ID", "[ID of current association]", commandName, "setCurrentAssociationID")) {
+			int c= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(c)) {
+				currentAssociationID = c;
+				currentAssociationIndex = MesquiteInteger.unassigned;
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Choose the current association", null, commandName, "chooseAssociation")) {
+			if (currentTaxa !=null) {
+				TaxaAssociation t = chooseAssociation(containerOfModule(), currentTaxa);
+				if (t!=null)
+					parametersChanged();
+				return t;
+			}
+			else
+				discreetAlert( "Sorry, a taxa association cannot be chosen unless a set of taxa has been previously indicated.  The fact that you get this message probably means that there has been a programming error.");
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public int getNumberOfAssociations(Taxa taxa) {
+		currentTaxa = taxa;
+		return manager.getNumberOfAssociations(taxa);
+	}
+	/*.................................................................................................................*/
+	public TaxaAssociation getAssociation(Taxa taxa, int ic) {
+		currentAssociationIndex=ic;
+		currentTaxa = taxa;
+		return getCurrentAssociation(taxa);
+	}
+	/*.................................................................................................................*/
+	public TaxaAssociation getCurrentAssociation(Taxa taxa) { 
+		TaxaAssociation oldAssociation = currentAssociation;
+		currentTaxa = taxa;
+		boolean done = false;
+		if (MesquiteInteger.isCombinable(currentAssociationID)&& !MesquiteInteger.isCombinable(currentAssociationIndex)){
+			currentAssociation  =  manager.findAssociationByID(currentAssociationID, taxa);
+			currentAssociationIndex = manager.getWhichAssociation(taxa, currentAssociation);
+			if (currentAssociation != null){
+				done = true;
+			}
+		}
+ 		if (!done){
+			if (!MesquiteThread.isScripting() && !MesquiteInteger.isCombinable(currentAssociationIndex) && getNumberOfAssociations(taxa)>1)
+				currentAssociation  =  chooseAssociation(containerOfModule(), taxa);
+			else {
+				if (getNumberOfAssociations(taxa) ==1)
+					currentAssociationIndex = 0;
+				else if (currentAssociationIndex>=getNumberOfAssociations(taxa) || currentAssociationIndex<0)
+					return  null;
+				currentAssociation = manager.getAssociation(taxa, currentAssociationIndex);
+			}
+		}
+		if (currentAssociation!=null && currentAssociation!=oldAssociation){
+			if (oldAssociation!=null)
+				oldAssociation.removeListener(this);
+			currentAssociation.addListener(this);
+		}
+		return currentAssociation;
+	}
+	/*.................................................................................................................*/
+	public TaxaAssociation chooseAssociation(MesquiteWindow frame, Taxa taxa){
+		int numAssoc = getNumberOfAssociations(taxa);
+		String[] assocNames = new String[numAssoc];
+		currentAssociation = manager.getAssociation(taxa, currentAssociationIndex);
+		for (int i=0; i<numAssoc;i++) 
+			assocNames[i] = manager.getAssociation(taxa, i).getName();
+		int whichAssoc = ListDialog.queryList(frame, "Select Association", "Select an association between two taxa blocks", MesquiteString.helpString, assocNames, -1);
+		if (!MesquiteInteger.isCombinable(whichAssoc)) 
+			return null;
+		if (whichAssoc>=0) { 
+			currentAssociationIndex = whichAssoc;
+			return  manager.getAssociation(taxa, whichAssoc);
+		}
+		else
+			return manager.getAssociation(taxa, 0);
+	}
+
+	/*.................................................................................................................*/
+	public int getNumberOfAssociations(Taxa taxa1, Taxa taxa2) {
+		return manager.getNumberOfAssociations(taxa1, taxa2);
+	}
+	/*.................................................................................................................*/
+	public TaxaAssociation getAssociation(Taxa taxa1, Taxa taxa2, int ic) {
+		if (ic >= manager.getNumberOfAssociations(taxa1, taxa2))			return null;
+		return manager.getAssociation(taxa1, taxa2, ic);
+	}
+	/*.................................................................................................................*/
+	public String getAssociationNameString(Taxa taxa, int index) {
+		currentTaxa = taxa;
+		return manager.getAssociation(taxa, index).getName();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stored Taxa Associations";
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (currentAssociation !=null)
+			return "Current association: " + currentAssociation.getName();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies associations between taxa that are stored, for instance in a file.";
+	}
+}
+
diff --git a/Source/mesquite/assoc/TaxaAssociationSpecs.txt b/Source/mesquite/assoc/TaxaAssociationSpecs.txt
new file mode 100644
index 0000000..9a82151
--- /dev/null
+++ b/Source/mesquite/assoc/TaxaAssociationSpecs.txt
@@ -0,0 +1,97 @@
+Format Specification for TaxaAssociation block of NEXUS file
+W. Maddison January 2003
+
+BEGIN TaxaAssociation;
+[TITLE <name of this association, a token>; [optional but recommended]]
+TAXA <name of first taxa block, a token> ,  <name of second taxa block, a token>;
+ASSOCIATES 
+	<nt1> /  <nt2> [<nt2> ...] , 
+	<nt1> /  <nt2> [<nt2> ...] , 
+	.
+	.
+	.
+	<nt1> /  <nt2> [<nt2> ...] 
+
+;
+
+[ASSOCIATES ... ; may be repeated]
+
+END;
+
+
+where nt1 means name of a taxon in first block, nt2 means name of a taxon in first block (these would not, of course, all be the same).  The two taxa blocks and their contained taxa must already be defined.
+
+Items may be repeated and there may be more than one ASSOCIATES command.  Thus, the following 4 blocks are equivalent, indicating genes a1 and a2 are within species A, b1 and b2 within species B, and c1 and c2 within species C.
+
+=============================================
+BEGIN TaxaAssociation;
+TITLE species_Containing_Genes;
+TAXA species,  genes;
+ASSOCIATES 
+	A /  a1 a2, 
+	B /  b1 b2, 
+	C /  c1 c2
+;
+END;
+
+=========
+BEGIN TaxaAssociation;
+TITLE species_Containing_Genes;
+TAXA species,  genes;
+ASSOCIATES 
+	A /  a1, 
+	A /  a2
+;
+ASSOCIATES 
+	B /  b1 b2, 
+	C /  c1 c2
+;
+END;
+
+=========
+BEGIN TaxaAssociation;
+TITLE genes_In_Species;
+TAXA genes ,  species;
+ASSOCIATES 
+	a1 /  A , 
+	a2 /  A , 
+	b1 /  B ,
+	b2 /  B , 
+	c1 /  C , 
+	c2 /  C
+;
+END;
+=========
+BEGIN TaxaAssociation;
+TITLE genes_In_Species;
+TAXA genes ,  species;
+ASSOCIATES 
+	a1 a2 /  A , 
+	b1 b2 /  B , 
+	c1 c2 /  C
+;
+END;
+=============================================
+
+
+Currently Mesquite reads and writes TaxaAssociation blocks in which a contained taxon is in more than one containing taxon (e.g. same haplotype in two populations) but its calculations cannot yet handle this situation.
+
+
+Questions:
+Do we allow a command which indicates the contained/containing polarity? e.g.
+   CONTAINED genes;
+One could imagine commands more for labelling, e.g.:
+   RELATIONSHIP host, parasite; [where order is that of blocks in TAXA command]
+
+Do we allow more than two taxa blocks to be associated simultaneously? e.g.
+
+BEGIN TaxaAssociation;
+TAXA genes ,  species, areas;
+ASSOCIATES 
+	a1 a2 /  A / Africa, 
+	b1 b2 /  B / Africa, 
+	c1 c2 /  C / South_America
+;
+END;
+
+
diff --git a/Source/mesquite/assoc/TaxonListAssoc/TaxonListAssoc.java b/Source/mesquite/assoc/TaxonListAssoc/TaxonListAssoc.java
new file mode 100644
index 0000000..9982b4b
--- /dev/null
+++ b/Source/mesquite/assoc/TaxonListAssoc/TaxonListAssoc.java
@@ -0,0 +1,687 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.TaxonListAssoc;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.assoc.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonListAssoc extends TaxonListAssistant {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(AssociationSource.class, "The current taxon association is displayed and can be edited in the List of Taxa window.",
+		"The source of an association is chosen initially.");
+	}
+	public String getName() {
+		return "Associated Taxa";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Lists and edits what other taxa (e.g. contained or containing) are associated with these." ;
+	}
+	public String getKeywords(){
+		return "gene_trees species genes";
+	}
+	/*.................................................................................................................*/
+	Taxa taxa, otherTaxa;
+	MesquiteTable table=null;
+	MesquiteMenuItemSpec m0, m1, m2, m3, m4, m5;
+	AssociationSource associationTask;
+	MesquiteWindow containingWindow;
+	TaxaAssociation association;
+	AssocEditor panel;
+
+	boolean ignoreWhitespace=true;
+	boolean ignoreCase = true;
+	boolean matchNumbers=false;
+	int minDigitsToMatch = 3;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireNamedEmployee(AssociationSource.class, "#mesquite.assoc.StoredAssociations.StoredAssociations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			containingWindow = (MesquiteWindow)f;
+			containingWindow.addSidePanel(panel = new AssocEditor(this), 160);
+		}
+		return true;
+	}
+	public MesquiteWindow getContainingWindow(){
+		return containingWindow;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public MesquiteWindow getParentWindow(){
+		return containingWindow;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Auto-assign Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+
+		Checkbox ignoreWhiteCheckBox= dialog.addCheckBox("ignore whitespace (spaces, tabs, etc.)", ignoreWhitespace);
+		Checkbox ignoreCaseCheckBox= dialog.addCheckBox("ignore case", ignoreCase);
+
+		Checkbox matchNumberCheckBox= dialog.addCheckBox("match if a number in both names is the same", matchNumbers);
+		IntegerField matchDigitsField = dialog.addIntegerField("minimum number of digits in number:", minDigitsToMatch, 5, 1,50);
+
+//		SingleLineTextField clustalOptionsField = queryFilesDialog.addTextField("Clustal options:", clustalOptions, 26, true);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			ignoreCase = ignoreCaseCheckBox.getState();
+			ignoreWhitespace = ignoreWhiteCheckBox.getState();
+			matchNumbers = matchNumberCheckBox.getState();
+			minDigitsToMatch = matchDigitsField.getValue();
+			//storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public String numberSubString(String s, int minDigits){
+		StringBuffer sb = new StringBuffer();
+		boolean longEnough = false;
+		for (int i=0; i<s.length(); i++) {
+			if (Character.isDigit(s.charAt(i))){
+				sb.append(s.charAt(i));
+				if (sb.length()>=minDigits)
+					longEnough=true;
+			}
+			else if (!longEnough) {
+				sb.setLength(0);
+			} else
+				break;
+		}
+		if (longEnough)
+			return sb.toString();
+		return "";
+	}
+	/*.................................................................................................................*/
+	public boolean containsSameNumbers(String name1, String name2, int minDigits){
+		String s1 = numberSubString(name1,minDigits);
+		String s2 =  numberSubString(name2,minDigits);
+		if (!StringUtil.blank(s1) && !StringUtil.blank(s2))
+			return s1.equals(s2);
+		return false;
+	}
+	/*.................................................................................................................*/
+	private void autoAssign(boolean ignoreWhitespace, boolean ignoreCase){
+		boolean changed = false;
+		if (taxa!=null && association != null) {
+			Taxa otherTaxa = association.getOtherTaxa(taxa);
+			for (int it=0; it<taxa.getNumTaxa(); it++)
+				for (int ito = 0; ito<otherTaxa.getNumTaxa(); ito++){
+					String name = taxa.getTaxonName(it);
+					String nameOther = otherTaxa.getTaxonName(ito);
+					if (name == null || nameOther == null)
+						continue;
+					boolean matches = name.equals(nameOther);
+					if (!matches && ignoreCase)
+						matches = name.equalsIgnoreCase(nameOther);
+					if (!matches && ignoreWhitespace) {
+						String strippedName = StringUtil.removeCharacters(name, StringUtil.defaultWhitespace);
+						String strippedNameOther = StringUtil.removeCharacters(nameOther, StringUtil.defaultWhitespace);
+						matches = strippedName.equals(strippedNameOther);
+						if (!matches && ignoreCase) {
+							matches = strippedName.equalsIgnoreCase(strippedNameOther);
+						}
+					}
+					if (!matches && matchNumbers) {
+						matches = containsSameNumbers(name, nameOther,minDigitsToMatch);
+					}
+					if (matches){
+						//association.zeroAllAssociations(taxa.getTaxon(it));
+						association.setAssociation(taxa.getTaxon(it), otherTaxa.getTaxon(ito), true);
+						changed = true;
+					}
+				}
+
+			if (changed) association.notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+		}
+	}
+	/*.................................................................................................................*/
+	private void setAssociate(Taxon taxon, boolean add, boolean append){
+		if (table !=null && taxa!=null && association != null) {
+			boolean changed=false;
+			if (add){
+				Taxa otherTaxa = association.getOtherTaxa(taxa);
+				if (taxon == null)
+					taxon = otherTaxa.userChooseTaxon(containerOfModule(), "Select the taxon to be associated with the selected rows");
+				if (taxon == null)
+					return;
+			}
+			if (employer!=null && employer instanceof ListModule) {
+				int c = ((ListModule)employer).getMyColumn(this);
+				for (int i=0; i<taxa.getNumTaxa(); i++) {
+					if (table.isCellSelectedAnyWay(c, i)) {
+						Taxon t = taxa.getTaxon(i);
+						if (!append)
+							association.zeroAllAssociations(t);
+						if (add)
+							association.setAssociation(t, taxon, true);
+						changed = true;
+					}
+				}
+			}
+
+			if (changed) {
+				association.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));  
+				parametersChanged();
+			}
+		}
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getAssociationsTask " + associationTask); 
+		temp.addLine("resetAssociation"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Gets the current associations module", null, commandName, "getAssociationsTask")) {
+			return associationTask;
+		}
+		else  if (checker.compare(this.getClass(), "Resets the association", null, commandName, "resetAssociation")) {
+			resetAssociation(false);
+		}
+		else  if (checker.compare(this.getClass(), "Automatically sets associates if there is an exact match of names", null, commandName, "autoAssignExact")) {
+			if (queryOptions())
+				autoAssign(ignoreWhitespace, ignoreCase);
+		}
+		else  if (checker.compare(this.getClass(), "Sets which other taxon is associated with these; replaces existing", null, commandName, "setAssociate")) {
+			setAssociate(null, true, false);
+		}
+		else  if (checker.compare(this.getClass(), "Sets which other taxon is associated with these; replaces existing", null, commandName, "createNewTaxaFromSelected")) {
+			if (association == null)
+				return null;
+			Taxa otherTaxa = association.getOtherTaxa(taxa);
+			boolean added = false;
+			boolean[] selectedInList = panel.getSelectedInList();
+			if (selectedInList==null)
+				return null;
+			for (int it=0; it<otherTaxa.getNumTaxa(); it++) {
+				if (selectedInList[it]) {
+					taxa.addTaxa(taxa.getNumTaxa()-1, 1, false);
+					taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+					Taxon otherT = otherTaxa.getTaxon(it);
+					Taxon t = taxa.getTaxon(taxa.getNumTaxa()-1);
+					t.setName(otherT.getName());
+					added = true;
+					association.setAssociation(t, otherT, true);
+				}
+			}
+			if (added) {
+				//taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+				association.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));  
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which other taxon is associated with these; adds to existing", null, commandName, "addAssociate")) {
+			setAssociate(null, true, true);
+		}
+		else if (checker.compare(this.getClass(), "Creates a new taxon and adds to existing", null, commandName, "createAssociate")) {
+			if (association == null)
+				return null;
+			Taxa otherTaxa = association.getOtherTaxa(taxa);
+			otherTaxa.addTaxa(otherTaxa.getNumTaxa()-1, 1, false);
+			Taxon t = otherTaxa.getTaxon(otherTaxa.getNumTaxa()-1);
+			String n = MesquiteString.queryString(containerOfModule(), "Name of Taxon", "Name the new taxon", "Taxon");
+			t.setName(n);
+			otherTaxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			setAssociate(t, true, true);
+		}
+		else if (checker.compare(this.getClass(), "Deletes associations", null, commandName, "removeAssociates")) {
+			setAssociate(null, false, false);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public boolean isShowing(TaxaAssociation assoc){
+		return assoc == association;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		deleteMenuItem(m0);
+		deleteMenuItem(m1);
+		deleteMenuItem(m2);
+		deleteMenuItem(m3);
+		deleteMenuItem(m4);
+		deleteMenuItem(m5);
+		m0 = addMenuItem(null, "Auto-assign Matches...", makeCommand("autoAssignExact", this));
+		m1 = addMenuItem(null, "Assign Associate...", makeCommand("setAssociate", this));
+		m2 = addMenuItem(null, "Add Associate...", makeCommand("addAssociate", this));
+		m3 = addMenuItem(null, "Remove Associates", makeCommand("removeAssociates", this));
+		m4 = addMenuItem(null, "Create New Associated Taxon...", makeCommand("createAssociate", this));
+		m5 = addMenuItem(null, "Create New Taxa in Master Block from Selected", makeCommand("createNewTaxaFromSelected", this));
+		if (this.taxa != null)
+			taxa.removeListener(this);
+		this.taxa = taxa;
+		if (this.taxa != null)
+			taxa.addListener(this);
+		this.table = table;
+		if (!MesquiteThread.isScripting())
+			resetAssociation(false);
+	}
+	void resetAssociation(boolean doEvenIfSame){
+		Taxa oldOtherTaxa = otherTaxa;
+		TaxaAssociation oldAssociation = association;
+		association = associationTask.getCurrentAssociation(taxa); 
+		if (association == null)
+			association = associationTask.getAssociation(taxa, 0); 
+		if (this.otherTaxa != null)
+			otherTaxa.removeListener(this);
+		if (association == null)
+			otherTaxa=null; 
+		else if (association.getTaxa(0)== taxa)
+			otherTaxa = association.getTaxa(1);
+		else
+			otherTaxa = association.getTaxa(0);
+		if (this.otherTaxa != null)
+			otherTaxa.addListener(this);
+		if (!doEvenIfSame && oldAssociation == association && oldOtherTaxa == otherTaxa)
+			return;
+		panel.setAssociation(association, otherTaxa, taxa);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		resetAssociation(true);
+		parametersChanged(notification);
+	}
+
+
+
+
+
+
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification)){
+			if (panel != null)
+				panel.prepareList(false);
+			return;
+		}
+		else if (notification != null && notification.getCode()== MesquiteListener.SELECTION_CHANGED){
+			//here should behave diffently: if associated taxa, then change selection in panel (indeed panel should use natural selection
+			if (panel != null)
+				panel.prepareList(false);
+			return;
+		}
+		if (panel != null)
+			panel.prepareList(true);
+		outputInvalid();
+		parametersChanged(notification);
+		super.changed(caller, obj, notification);
+	}
+
+
+	public String getTitle() {
+		if (otherTaxa != null && otherTaxa.getName() != null && !StringUtil.startsWithIgnoreCase(otherTaxa.getName(),"Untitled") &&  !StringUtil.startsWithIgnoreCase(otherTaxa.getName(),"Taxa Association"))
+			return otherTaxa.getName();
+		return "Associates";
+	}
+	Taxon[] associates;
+	public String getStringForTaxon(int ic){
+
+		if (taxa!=null) {
+			if (association==null)
+				return "?";
+
+			if (associates==null ||  associates.length < otherTaxa.getNumTaxa())
+				associates = new Taxon[otherTaxa.getNumTaxa()];
+			associates = association.getAssociates(taxa.getTaxon(ic), associates);
+			if (associates!= null) {
+				String s = "";
+				boolean first = true;
+				for (int i=0; i<associates.length; i++)
+					if (associates[i]!=null){
+						if (!first)
+							s += ", ";
+						s += associates[i].getName();
+						first = false;
+					}
+				return s; 
+			}
+			return "-";
+		}
+		return "?";
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+	/*public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	 if (taxa==null || g==null)
+	 return;
+	 TaxaPartition part = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+	 Color c = g.getColor();
+	 boolean colored = false;
+	 if (part!=null) {
+	 TaxaGroup tg = part.getTaxaGroup(ic);
+	 if (tg!=null){
+	 Color cT = tg.getColor();
+	 if (cT!=null){
+	 g.setColor(cT);
+	 g.fillRect(x+1,y+1,w-1,h-1);
+	 colored = true;
+	 }
+	 }
+	 }
+	 if (!colored){ 
+	 if (selected)
+	 g.setColor(Color.black);
+	 else
+	 g.setColor(Color.white);
+	 g.fillRect(x+1,y+1,w-1,h-1);
+	 }
+
+	 String s = getStringForRow(ic);
+	 if (s!=null){
+	 FontMetrics fm = g.getFontMetrics(g.getFont());
+	 if (fm==null)
+	 return;
+	 int sw = fm.stringWidth(s);
+	 int sh = fm.getMaxAscent()+ fm.getMaxDescent();
+	 if (selected)
+	 g.setColor(Color.white);
+	 else
+	 g.setColor(Color.black);
+	 g.drawString(s, x+(w-sw)/2, y+h-(h-sh)/2);
+	 g.setColor(c);
+	 }
+	 }
+	 */
+	public String getWidestString(){
+		return "88888888888  ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void endJob() {
+		if (panel != null && containingWindow != null)
+			containingWindow.removeSidePanel(panel);
+		if (this.taxa != null)
+			taxa.removeListener(this);
+		if (this.otherTaxa != null)
+			otherTaxa.removeListener(this);
+		super.endJob();
+	}
+	void close(){
+		iQuit();
+	}
+}
+/*=======================================*/
+class AssocEditor extends MousePanel {
+	Font df = new Font("Dialog", Font.BOLD, 12);
+	TaxaAssociation assoc;
+	Taxa otherTaxa, taxa;
+	TaxonListAssoc ownerModule;
+	//Button button, rbutton;
+	TextArea text;
+	int titleH = 18;
+	int nameH = 30;
+	int buttonH = 25;
+	Image goaway, replace, add, subtract;
+	SimpleTaxaList taxonList;
+
+
+	public AssocEditor(TaxonListAssoc ownerModule){
+		super();
+		setLayout(null);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goaway.gif");
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "add.gif");
+		replace = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "replaceLeft.gif");
+		subtract = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "subtract.gif"); //should be subtract.gif
+		text = new TextArea(" ", 50, 50, TextArea.SCROLLBARS_NONE);
+		add(text);
+		text.setVisible(true);
+		text.setBounds(1, titleH, getBounds().width-2, nameH);
+		text.setBackground(Color.lightGray);   //lightGray
+		this.ownerModule  = ownerModule;
+
+		taxonList = new SimpleTaxaList(otherTaxa,this);
+		taxonList.setLocation(0,titleH + nameH + buttonH);
+		taxonList.setSize(getBounds().width, getBounds().height-titleH - nameH - buttonH);
+		taxonList.setVisible(true);
+		add(taxonList);		
+	}
+	void assignSelectedAssociates(){
+		if (assoc == null)
+			return;
+		boolean[] selectedInList = taxonList.getSelectedList();
+
+		if (selectedInList == null)
+			return;
+		for (int it= 0; it< taxa.getNumTaxa(); it++){
+			if (taxonSelectedInListWindow(it)){
+				assoc.zeroAllAssociations(taxa.getTaxon(it));
+				for (int ito = 0; ito<selectedInList.length; ito++)
+					if (selectedInList[ito])
+						assoc.setAssociation(taxa.getTaxon(it), otherTaxa.getTaxon(ito), true);
+
+			} 
+		}
+		assoc.notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+	}
+
+	public boolean[] getSelectedInList(){
+		return taxonList.getSelectedList();
+	}
+	boolean taxonSelectedInListWindow(int it){
+		return taxa.getSelected(it) || ((ListWindow)ownerModule.containingWindow).isRowSelected(it);
+	}
+	void addSelectedAssociates(){
+		if (assoc == null)
+			return;
+		boolean[] selectedInList = taxonList.getSelectedList();
+
+		if (selectedInList == null)
+			return;
+		for (int it= 0; it< taxa.getNumTaxa(); it++){
+			if (taxa.getSelected(it)){
+				for (int ito = 0; ito<selectedInList.length; ito++)
+					if (selectedInList[ito])
+						assoc.setAssociation(taxa.getTaxon(it), otherTaxa.getTaxon(ito), true);
+
+			} 
+		}
+		assoc.notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+	}
+	void removeSelectedAssociates(){
+		if (assoc == null)
+			return;
+		boolean[] selectedInList = taxonList.getSelectedList();
+
+		if (selectedInList == null)
+			return;
+		for (int it= 0; it< taxa.getNumTaxa(); it++){
+			if (taxonSelectedInListWindow(it)){
+				for (int ito = 0; ito<selectedInList.length; ito++)
+					if (selectedInList[ito]) {
+						assoc.setAssociation(taxa.getTaxon(it), otherTaxa.getTaxon(ito), false);
+					}
+
+			} 
+		}
+		assoc.notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+	}
+	void removeAllAssociates(){
+		if (assoc == null)
+			return;
+		for (int it= 0; it< taxa.getNumTaxa(); it++){
+			if (taxonSelectedInListWindow(it)){
+				assoc.zeroAllAssociations(taxa.getTaxon(it));
+			}
+		}
+		assoc.notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+	}
+	void setAssociation(TaxaAssociation assoc, Taxa otherTaxa, Taxa taxa){
+		this.assoc = assoc;
+		if (text!=null && assoc!=null)
+			text.setText(assoc.getName());
+		this.otherTaxa = otherTaxa;
+		this.taxa = taxa;
+		prepareList(true);
+	}
+	private void close(){
+		ownerModule.close();
+	}
+	void reset(boolean completeReset){
+		if (assoc == null)
+			return;
+		if (completeReset){
+			taxonList.deselectAll();
+			for (int it= 0; it< taxa.getNumTaxa(); it++){
+				if (taxonSelectedInListWindow(it)){
+					Taxon[] associates = assoc.getAssociates(taxa.getTaxon(it));
+					if (associates != null)
+						for (int ito = 0; ito < associates.length; ito++){
+							int i = associates[ito].getNumber();
+							taxonList.selectRow(i,true);
+						}
+				}
+			}
+		}
+		repaint();
+		taxonList.repaint();
+		//	button.repaint();
+
+	}
+	boolean isAssignedSomewhere(int ito){
+		Taxon oT = otherTaxa.getTaxon(ito);
+
+		for (int it= 0; it< taxa.getNumTaxa(); it++){
+			Taxon[] associates = assoc.getAssociates(taxa.getTaxon(it));
+			if (associates != null)
+				for (int i = 0; i < associates.length; i++)
+					if (associates[i] == oT)
+						return true;
+
+		}
+		return false;
+
+	}
+
+	void resetAssigned(){
+		if (otherTaxa != null && assoc != null){
+			for (int i= 0; i<otherTaxa.getNumTaxa(); i++){
+				taxonList.setAssigned (i,false);
+			}
+			for (int it= 0; it< taxa.getNumTaxa(); it++){
+				Taxon[] associates = assoc.getAssociates(taxa.getTaxon(it));
+				if (associates != null)
+					for (int i = 0; i < associates.length; i++)
+						if (associates[i] !=null){
+							int ito=associates[i].getNumber();
+							taxonList.setAssigned (ito,true);
+						}
+
+			}
+		}
+	}
+
+	void prepareList(boolean completeReset){
+		if (otherTaxa != null && completeReset){
+			taxonList.setTaxa(otherTaxa);
+		}
+		resetAssigned();
+		reset(completeReset);
+	}
+
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		taxonList.setSize(w, h-titleH -  nameH - buttonH);
+		text.setBounds(1, titleH, getBounds().width-2, nameH);
+		repaint();
+		text.repaint();
+		taxonList.repaint();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		taxonList.setSize(w, h-titleH - nameH - buttonH);
+		text.setBounds(1, titleH, getBounds().width-2, nameH);
+		repaint();
+		text.repaint();
+		taxonList.repaint();
+	}
+	public void paint(Graphics g){
+		g.drawImage(goaway, 2, 2, this);
+		g.drawImage(replace, 8, titleH + nameH+2, this);
+		g.drawImage(add, 32, titleH + nameH+2, this);
+		g.drawImage(subtract, 56, titleH + nameH+2, this);
+		g.setFont(df);
+
+		g.setColor(Color.black);
+		if (ownerModule!=null)
+			g.drawString(ownerModule.getTitle(), 24, 16);
+		g.drawLine(getBounds().width-1, 0, getBounds().width-1, getBounds().height);
+		g.drawLine(0, 0, 0, getBounds().height);
+		int bottom = titleH + nameH+buttonH -2;
+		g.drawLine(0, bottom, getBounds().width, bottom);
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		String message = "";
+		if (x >= 2 && x <2+16 && y>= 2 && y< 2 + 16)
+			message = "Close this Association Editor";
+		else if (x >= 8 && x <8+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			message = "For the taxa selected on the left, replaces the associated taxa with the taxa that are selected in list below";
+		else if (x >= 32 && x <32+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			message = "For the taxa selected on the left, adds to the association the taxa that are selected in list below";
+		else if (x >= 56 && x <56+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			message = "For the taxa selected on the left, removes from the association the taxa that are selected in list below";
+		if (ownerModule!=null)
+			ownerModule.getContainingWindow().setExplanation(message);
+
+	}
+	int clickCount=0;
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x >= 2 && x <2+16 && y>= 2 && y< 2 + 16)
+			close();
+		else if (x >= 8 && x <8+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			assignSelectedAssociates();
+		else if (x >= 32 && x <32+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			addSelectedAssociates();
+		else if (x >= 56 && x <56+16 && y>= titleH + nameH+2 && y< titleH + nameH+2 + 16)
+			removeSelectedAssociates();
+
+	}
+
+	/*.................................................................................................................*/
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		this.clickCount = clickCount;
+	}
+
+}
+
diff --git a/Source/mesquite/assoc/aAssocIntro/aAssocIntro.java b/Source/mesquite/assoc/aAssocIntro/aAssocIntro.java
new file mode 100644
index 0000000..eb58ee6
--- /dev/null
+++ b/Source/mesquite/assoc/aAssocIntro/aAssocIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.aAssocIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aAssocIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public Class getDutyClass(){
+		return aAssocIntro.class;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides utilities for managing taxa associations (e.g. for gene/species analyses).";
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxa Association Package Introduction";
+	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+	public String getPackageName(){
+		return "Taxa Association Package";
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+		return false; 
+	}
+}
+
diff --git a/Source/mesquite/assoc/explanation.txt b/Source/mesquite/assoc/explanation.txt
new file mode 100644
index 0000000..8a06018
--- /dev/null
+++ b/Source/mesquite/assoc/explanation.txt
@@ -0,0 +1,2 @@
+Taxa Associations Package
+Manages and does some basic calculations and graphics for associations between blocks of taxa (e.g., genes sequenced as one set of taxa; their containing species or populations as a second set of taxa).  Required for many of the Coalescence calculations.
diff --git a/Source/mesquite/assoc/lib/AssociationHistory.java b/Source/mesquite/assoc/lib/AssociationHistory.java
new file mode 100644
index 0000000..82163cb
--- /dev/null
+++ b/Source/mesquite/assoc/lib/AssociationHistory.java
@@ -0,0 +1,662 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+/*June 28 2012.  There are some methods which encounter problems when a containing tree does not 
+ * contain all nodes (internal or terminal) of the contained tree.  For example, if a containing tree
+ * does not contain all containing taxa in the given association, and there are taxa in the contained
+ * tree that are associated with those missing containing taxa, methods such as deepestNodeThatContainedEnters
+ * will end up in an infinite loop.  A conditional has been added to this method to return 0 for any of these
+ * containing nodes (by asking if locationOfContainedNode == 0).  Other similar methods (shallowestNode...) should
+ * also be investigated for this effect.
+ * 
+ * In the current version (as of October 08), some internal nodes of the contained tree that are expected to be contained 
+ * are not.  Specifically, if a node of the contained tree has:
+ *   (1) An ancestor node in the containing node j
+ *      and
+ *   (2) A descendant node in the containing node j
+ * it is not contained by any containing nodes in the containing tree.
+ * 
+ * In other words, this contained node (or, in this case it's easier to think of as a branch)
+ * neither enters the contained node, nor exits the contained node, and is thus not considered 'contained'
+ * This can be seen by calling the toString method.*/
+/*-------------------------------------*/
+/* For each node of a tree for one taxa, what are the nodes of contained tree are present and at one point in branch*/
+public class AssociationHistory {
+	/*in element i is stored an array containing a list of the branches in the containedTree (designated by their node numbers) that enter node i
+	 * of the containing tree.  "Enter" is here meant in a time-backwards sense, i.e., at the most recent tip of the node.   */
+	int[][] enteringContainedBranches;
+	/*in element i is stored the depth along the branch of the containing tree in which the contained node i is placed*/
+	//double[][] containedDepths;
+	/*in element i is stored the node number in the containing tree in which the contained node itself is present */
+	int[] locationOfContainedNode;
+	Tree containingTree, containedTree;
+	MesquiteTimer aTime, sTime;
+
+	public AssociationHistory( ){
+		aTime = new MesquiteTimer();
+		sTime = new MesquiteTimer();
+	}
+
+	public AssociationHistory(Tree containing, Tree contained, int[] locationOfContainedNode ){
+		aTime = new MesquiteTimer();
+		sTime = new MesquiteTimer();
+		setTrees(containing,  contained);
+		if (locationOfContainedNode!=null && this.locationOfContainedNode.length==locationOfContainedNode.length)
+			for (int j=0; j<locationOfContainedNode.length; j++)
+				this.locationOfContainedNode[j]=locationOfContainedNode[j];
+		calcEnteringContainedBranchesFromLocations();
+	}
+
+	public Tree getContainingTree() {
+		return containingTree;
+	}
+	public Tree getContainedTree() {
+		return containedTree;
+	}
+	public void resetArrays(){
+		if (containingTree!=null) {
+			if (enteringContainedBranches==null || enteringContainedBranches.length<containingTree.getNumNodeSpaces())
+				enteringContainedBranches = new int[containingTree.getNumNodeSpaces()][];
+			if (containedTree!=null){
+				int numContained = containedTree.getNumNodeSpaces();
+				if (locationOfContainedNode==null || locationOfContainedNode.length<numContained)
+					locationOfContainedNode = new int[numContained];
+				if (enteringContainedBranches[0]==null || enteringContainedBranches[0].length<numContained) {
+					for (int i=0; i<enteringContainedBranches.length; i++) 
+						enteringContainedBranches[i]= new int[numContained];
+				}
+				for (int i=0; i<enteringContainedBranches.length; i++) 
+					for (int j=0; j<numContained; j++)
+						enteringContainedBranches[i][j]=MesquiteInteger.unassigned;
+			}
+		}
+	}
+	public void setContainingTree(Tree tree){
+		containingTree = tree;
+		resetArrays();
+	}
+	public void setContainedTree(Tree tree){
+		//check if TAXA correct
+		containedTree = tree;
+		//should it register as listener to tree?
+		resetArrays();
+	}
+	public void setTrees(Tree containing, Tree contained){
+		//check if TAXA correct
+		containingTree = containing;
+		containedTree = contained;
+		resetArrays();
+	}
+	private boolean illegalContained(int contained){
+		return !(contained>=0 && (enteringContainedBranches.length>0 && contained<enteringContainedBranches[0].length));
+	}
+	private boolean illegalContaining(int containing){
+		return !(containing>=0 && containing< enteringContainedBranches.length);
+	}
+	public void setContainedNode(int containing, int contained){
+		if (illegalContained(contained) || illegalContaining(containing))
+			return;
+		for (int i=0; i<enteringContainedBranches[containing].length; i++)
+			if (enteringContainedBranches[containing][i] ==MesquiteInteger.unassigned) {
+				enteringContainedBranches[containing][i] = contained;
+				return;
+			}
+	}
+	public boolean isNodeContainedByAny(int contained){
+		if (illegalContained(contained))
+			return false;
+		for (int containing = 0; containing<enteringContainedBranches.length; containing++){
+			for (int i=0; i<enteringContainedBranches[containing].length; i++)
+				if (enteringContainedBranches[containing][i] ==contained) 
+					return true;
+		}
+		return false;
+	}
+	public boolean isNodeContained(int containing, int contained){
+		if (illegalContained(contained) || illegalContaining(containing))
+			return false;
+		for (int i=0; i<enteringContainedBranches[containing].length; i++)
+			if (enteringContainedBranches[containing][i] ==contained) 
+				return true;
+		return false;
+	}
+
+	public boolean isAncestorContained(int containing, int contained, Tree containedTree){
+		if (illegalContained(contained) || illegalContaining(containing))
+			return false;
+		for (int i=0; i<enteringContainedBranches[containing].length; i++)
+			if (containedTree.descendantOf(contained, enteringContainedBranches[containing][i])) 
+				return true;
+		return false;
+	}
+	public int[] getContainedNodes(int node){
+		if (illegalContaining(node))
+			return null;
+		return enteringContainedBranches[node];
+	}
+	public int getNumberContainedNodes(int node){
+		if (illegalContaining(node))
+			return 0;
+		int sum = 0;
+		for (int i=0; i<enteringContainedBranches[node].length; i++) {
+			if (enteringContainedBranches[node][i] ==MesquiteInteger.unassigned) 
+				return sum;
+			else sum++;
+		}
+		return sum;
+	}
+	public int[] getContainingNodes(int node){
+		if (illegalContained(node))
+			return null;
+		int count=0;
+		for (int k=0; k<enteringContainedBranches.length; k++)
+			for (int i=0; i<enteringContainedBranches[k].length; i++) 
+				if (enteringContainedBranches[k][i] ==node) 
+					count++;
+		if (count == 0)
+			return null;
+		int[] containing = new int[count];
+		count = 0;
+		for (int k=0; k<enteringContainedBranches.length; k++)
+			for (int i=0; i<enteringContainedBranches[k].length; i++) {
+				if (enteringContainedBranches[k][i] ==node) 
+					containing[count++] = k;
+			}
+		return containing;
+	}
+	/*_________________________________________________*/
+	/** this method recurses up the containing (species?) tree and calculates how the contained tree fits into it */
+	public void countDuplicationsExtinctions(Tree speciesTree, Tree geneTree, MesquiteInteger duplications, MesquiteInteger extinctions) {
+		boolean[] deleted = new boolean[geneTree.getNumNodeSpaces()];
+		for (int it = 0; it< geneTree.getTaxa().getNumTaxa(); it++){
+			int[] containing = getContainingNodes(geneTree.nodeOfTaxonNumber(it));
+			if (containing == null || !isContainedInTree(containing, speciesTree)){
+				geneTree.virtualDeleteTaxon(it, deleted);
+			}
+		}
+
+		recCountDuplicationsExtinctions( speciesTree,  geneTree,  deleted, speciesTree.getSubRoot(),  duplications,  extinctions);
+	}
+	private boolean isContainedInTree(int[] containing, Tree speciesTree){
+		for (int i=0; i<containing.length; i++)
+			if (speciesTree.nodeInTree(containing[i]))
+				return true;
+		return false;
+	}
+	/*_________________________________________________*/
+	/** this method recurses up the containing (species?) tree and calculates how the contained tree fits into it */
+	public void recCountDuplicationsExtinctions(Tree speciesTree, Tree geneTree, boolean[] deleted, int speciesNode, MesquiteInteger duplications, MesquiteInteger extinctions) {
+
+		int[][] genesInDaughterSpecies = new int[speciesTree.numberOfDaughtersOfNode(speciesNode)][];
+		int[] daughterSpecies = new int[speciesTree.numberOfDaughtersOfNode(speciesNode)];
+		int k =0;
+		for (int d = speciesTree.firstDaughterOfNode(speciesNode); speciesTree.nodeExists(d); d = speciesTree.nextSisterOfNode(d)){
+			daughterSpecies[k] = d;
+			genesInDaughterSpecies[k++] = getContainedNodes(d);
+			recCountDuplicationsExtinctions(speciesTree,geneTree, deleted, d, duplications, extinctions);
+		}
+		int dup = duplications.getValue();
+		int ext = extinctions.getValue();
+		int [] genesInSpecies;
+		if (speciesNode == speciesTree.getSubRoot())
+			genesInSpecies = new int[]{geneTree.getRoot(deleted)};
+		else
+			genesInSpecies = getContainedNodes(speciesNode);
+		/*for each of these contained nodes:
+		- (1) if also present in a species daughter directly, count an extinction event for each of that species daughter's daughters-1
+		- if all of its daughters are internalized, then count a duplication event
+		- if all of its duaghters are in species daughter, then count nothing
+		- if some of its daughters are internalized and some in species daughter, then count extinctions for those in species daughter and uplication for internalized
+		 */
+		for (int i = 0; i<genesInSpecies.length && MesquiteInteger.isCombinable(genesInSpecies[i]); i++){
+			int gene = genesInSpecies[i];
+			int ds = findDaughterSpeciesContainingGene(genesInDaughterSpecies, gene);
+			//(1)
+			if (ds>=0){ //also present in daughter directly
+				int numGranddaughterSpecies = speciesTree.numberOfDaughtersOfNode(daughterSpecies[ds]);
+				if (numGranddaughterSpecies>1)
+					extinctions.add(numGranddaughterSpecies-1);
+			}
+			else
+				examineInternalizedGeneNode(genesInDaughterSpecies, daughterSpecies, speciesTree, geneTree, deleted, gene, duplications, extinctions);
+		}
+	}
+
+	/*_________________________________________________*/
+	private void examineInternalizedGeneNode(int[][] genesInDaughterSpecies, int[] daughterSpecies, Tree speciesTree, Tree geneTree,  boolean[] deleted, int gene, MesquiteInteger duplications, MesquiteInteger extinctions) {
+		int numInternalized = 0;
+		int numExtinctions =  0;
+		int numInTerminalSpecies = 0;
+		boolean terminalSpecies = false;
+		for (int d = geneTree.firstDaughterOfNode(gene, deleted); geneTree.nodeExists(d); d = geneTree.nextSisterOfNode(d, deleted)){
+			int daughterSpeciesContaining = findDaughterSpeciesContainingGene(genesInDaughterSpecies, d);
+			if (daughterSpeciesContaining<0){ //internalized
+				examineInternalizedGeneNode(genesInDaughterSpecies,daughterSpecies, speciesTree, geneTree, deleted, d, duplications, extinctions);
+				numInternalized++;
+			}
+			else { // daughter gene is in daughter species
+				if (speciesTree.nodeIsTerminal(daughterSpecies[daughterSpeciesContaining]))//species node is terminal, thus count
+					numInTerminalSpecies++;
+				else {
+					int numGranddaughters = speciesTree.numberOfDaughtersOfNode(daughterSpecies[daughterSpeciesContaining]);
+					if (numGranddaughters>1)
+						numExtinctions+= numGranddaughters-1;
+				}
+			}
+
+		}
+		if (numInternalized>0){
+			duplications.increment();
+			extinctions.add(numExtinctions);
+		}
+		else if (numInTerminalSpecies>1)
+			duplications.increment();
+	}
+	/*_________________________________________________*/
+	private int findDaughterSpeciesContainingGene(int[][] genesInDaughterSpecies, int gene){
+		for (int d = 0; d< genesInDaughterSpecies.length; d++){
+			for (int c = 0; c< genesInDaughterSpecies[d].length; c++){
+				if (genesInDaughterSpecies[d][c] == gene)
+					return d;
+			}
+		}
+		return -1;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and returns whether at least one of them is represented in descendants
+	of passed node*/
+	private boolean cladeRepresented(Tree tree, int[] nodes, int node){
+		if (nodes == null)
+			return false;
+		for (int i=0; i<nodes.length; i++)
+			if (nodes[i]==node)
+				return true;
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (cladeRepresented(tree, nodes, d))
+					return true;
+			}
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and returns whether an entire clade resolvable from the immediate
+	descendants of the ancestral node is present*/
+	private boolean cladeResolvable(Tree tree, Tree containingTree, int containingNode,  boolean useDepths, int[] nodes, int node){
+		if (nodes == null || !tree.nodeIsPolytomous(node))
+			return false;
+		if (tree.nodeIsInternal(node) && cladeRepresented(tree, nodes, node)) {
+			int numD = 0;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, d, true))
+					numD++;
+			}
+			if (numD>1)
+				return true;
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and returns whether the entire clade of the ancestral node is present*/
+	private boolean cladeFullyPresent(Tree tree, Tree containingTree, int containingNode,  boolean useDepths, int[] nodes, int node, boolean countDirectInclusion){
+		if (nodes == null)
+			return false;
+		if (useDepths && containingNode!=containingTree.getRoot()){
+			//if (depth from node to tips in contained tree is greater than depth of containingNode's ancestor, then return false)
+			if (tree.tallestPathAboveNode(node) > (containingTree.tallestPathAboveNode(containingNode) +containingTree.getBranchLength(containingNode, 1.0)) )
+				return false;
+		}
+		if (countDirectInclusion) {
+			for (int i=0; i<nodes.length; i++) {
+				if (nodes[i]==node)
+					return true;
+			}
+		}
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (!cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, d, true))
+					return false;
+			}
+			return true;
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and resolves the tree to put resolvable clades together*/
+	private boolean resolveClades(AdjustableTree tree, Tree containingTree, int containingNode,  boolean useDepths,int[] nodes, int node){
+		boolean did=false;
+		if (!cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, node, true)) { //clade present, no need to resolve further
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (IntegerArray.indexOf(nodes, d)<0){ //daughter isn't in list of thosed contained in containingNode; ??must be contained higher up, so go there
+					boolean resolvd = resolveClades(tree, containingTree, containingNode,  useDepths, nodes, d);
+					did = did || resolvd;
+				}
+			}
+			if (cladeResolvable(tree,containingTree, containingNode,  useDepths,  nodes, node)) {
+				int numTogether=0;
+				int oldest = 0;
+				int[] ds = tree.daughtersOfNode(node);
+				for (int i = 0; i<ds.length; i++) {
+					if (cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, ds[i], true)) {
+						tree.setSelected(ds[i], true);
+						numTogether++;
+						if (numTogether<2) {  //this is first of sisters to be joined; remember it as a target for later joining
+							oldest = ds[i];
+						}
+						else { //at least two sisters found; join them
+							tree.moveBranch(ds[i], oldest, false);
+							if (numTogether==2) { //first joining; mark mother as result of auto-resolution
+								tree.setSelected(tree.motherOfNode(ds[i]), true);
+							}
+							else { //subsequent joining; collapse newly formed node to maintain polytomy of new sisters
+								tree.collapseBranch(tree.motherOfNode(ds[i]), false);
+							}
+							did = true;
+						}
+					}
+				}
+			}
+		}
+		return did;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and returns how many separate clades are present*/
+	private int numCladesPresent(Tree tree, Tree containingTree, int containingNode,  boolean useDepths,int[] nodes, int node){
+		if (cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, node, true))
+			return 1;
+		int sum = 0;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			sum += numCladesPresent( tree,containingTree, containingNode,  useDepths, nodes, d);
+		}
+		return sum;
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and returns a list of the contained nodes (from among "nodes") that can be placed comfortably within containingNode*/
+	private void accumulateCladesPresent(Tree tree, Tree containingTree, int containingNode,  boolean useDepths, int[] nodes, int node, int[] result, MesquiteInteger cladeCount){
+		if (cladeFullyPresent(tree, containingTree, containingNode,  useDepths, nodes, node, true)) {
+			if (cladeCount.getValue()< result.length)
+				result[cladeCount.getValue()] = node;
+			cladeCount.increment();
+			return;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			accumulateCladesPresent(tree, containingTree, containingNode,  useDepths, nodes, d, result, cladeCount);
+		}
+	}
+	/*_________________________________________________*/
+	/* takes list of nodes of given tree and finds set of clades that contain all and only those nodes, 
+	and returning list of ancestral nodes of these clades.  Intended for use in fitting a gene tree to species tree to minimize
+	deep coalescences.  If flag "allowResolve" is set, then the containing tree can
+	be resolved where polytomies present, to group all members of polytomy together and return ancestral node of new clade.
+	If useDepths is true, the relative branch lengths of the containing and contained branches are used to decide if the ancestral node is still in the branch;
+	if not the set of ancestral nodes returned are those ancestors still in the branch.  That is, if nodes A and B are sister nodes, and are included
+	in int[] nodes, then if useDepth were true AND their mother node is so deep as to be in the mother of containingNode, then A and B are
+	returned separately in the ancestral nodes returned.  If their mother node is not so deep, or useDepth is false, then the mother node
+	alone is returned in the ancestral nodes returned.*/
+	public int[] condenseClades(AdjustableTree tree, Tree containingTree, int containingNode,  int[] nodes, boolean allowResolve, boolean useDepths) {
+		if (nodes == null)
+			return null;
+
+		int numValid = 0;
+		int recall = MesquiteInteger.unassigned;
+		for (int i=0; i<nodes.length; i++) { //counting how many contained nodes here
+			if (MesquiteInteger.isCombinable(nodes[i])) {
+				numValid++;
+				recall = nodes[i];//in case only one, remember it
+			}
+		}
+		if (numValid==1) { //only a single contained node here, just return it
+			int[] temp = new int[1];
+			temp[0] = recall;
+			return temp;
+		}
+		//prepare storage for ancestral nodes to be returned
+		int[] temp = new int[numCladesPresent(tree, containingTree, containingNode,  useDepths, nodes, tree.getRoot())];
+
+		//put into temp all of the ancestors found so far
+		MesquiteInteger cladeCount = new MesquiteInteger(0);
+		accumulateCladesPresent(tree, containingTree, containingNode,  useDepths, nodes, tree.getRoot(), temp, cladeCount);
+
+		//if autoresolution is allowed, attempt to resolve polytomies to condense further by grouping potential sisters among the ancestors found so far
+		if (allowResolve){ //allowed to resolve polytomies to minimize deep coalescences
+
+			if (resolveClades(tree, containingTree, containingNode,  useDepths, temp, tree.getRoot())) {
+				//Autoresolution occurred, thus need to re-condense, this time without auto-resolution
+				return condenseClades(tree, containingTree, containingNode,  temp, false,  useDepths);
+			}
+		}
+		return temp;
+	}
+
+	/*_________________________________________________*/
+	public void findShallowest(int containing, int contained, MesquiteInteger shallowest) {
+		if (isNodeContained(containing, contained)) {
+			shallowest.setValue(containing);
+			if (containingTree.nodeIsInternal(containing)) {
+				for (int d = containingTree.firstDaughterOfNode(containing); containingTree.nodeExists(d); d = containingTree.nextSisterOfNode(d)) {
+					findShallowest(d, contained, shallowest);
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	/** Returns the node number in the containing tree in which the contained node is placed */
+	public int shallowestNodeThatContainedEnters(int contained){
+		if (illegalContained(contained)||containingTree==null ||containedTree==null)
+			return 0;
+		for (int k=0; k<enteringContainedBranches.length; k++) {   // going through nodes in containing tree
+			if (isNodeContained(k, contained)) {  // we've found one with our branch
+				MesquiteInteger shallowest = new MesquiteInteger(0);
+				findShallowest(k,contained,shallowest);
+				return shallowest.getValue();
+			}
+		}		
+		return 0;
+	}
+	/*_________________________________________________*/
+	/** Returns the node number in the containing tree in which the contained node is placed */
+	public int deepestNodeThatContainedEnters(int contained){ 
+		if (locationOfContainedNode[contained] == 0)// dJCOs Added conditional to just return 0 for any node that isn't contained by any containing nodes.  Without this conditional, some internal gene tree nodes that are not assigned to species tree nodes will result in infinite loop.  Oliver.June.28.2012.
+			return 0;
+		if (illegalContained(contained)||containingTree==null)
+			return 0;
+		for (int k=0; k<enteringContainedBranches.length; k++) {   // going through nodes in containing tree
+			if (isNodeContained(k, contained)) {  // we've found one with our branch
+				int prev = k;
+				for (int anc=k; anc!= containingTree.getRoot(); anc = containingTree.motherOfNode(anc)) {   
+					if (!isNodeContained(anc,contained))
+						return prev;
+					else
+						prev = anc;
+				}
+				if (isNodeContained(containingTree.getRoot(),contained))
+					return containingTree.getRoot();
+				else
+					return prev;
+			}
+
+		}		
+		return 0;
+	}
+	/*_________________________________________________*/
+	/** searches to see if a descendant in the contained tree of the node contained enters into the containing tree node containing; if so, returns true in found */
+	public void findDescendentThatEnters(int containing, int contained, MesquiteBoolean found) {
+		if (isNodeContained(containing, contained))
+			found.setValue(true);
+		if (found.getValue())
+			return;
+		if (containedTree.nodeIsInternal(contained)) {
+			for (int d = containedTree.firstDaughterOfNode(contained); containedTree.nodeExists(d)&&!found.getValue(); d = containedTree.nextSisterOfNode(d)) {
+				findDescendentThatEnters(containing, d, found);
+			}
+		} /*else {  // we are at a terminal in the contained tree
+			int[] nodesContainedInTerminal = getContainedNodes(containing);
+			for (int k=0; k<nodesContainedInTerminal.length; k++) {
+				if (nodesContainedInTerminal[k]!=MesquiteInteger.unassigned){
+					if (containingTree.descendantOf(nodesContainedInTerminal[k], contained)){
+						found.setValue(true);
+						return;
+					}
+				}
+			}
+
+		}
+		 */
+	}
+	/*_________________________________________________*/
+	/** does containing contain a descendant of contained */
+	public void foundDescendant(int contained, MesquiteInteger containingDescendant) {
+		int containing = deepestNodeThatContainedEnters(contained);
+		if (containing!=0)  // we've found one
+			containingDescendant.setValue(containing);
+		if (containingDescendant.isCombinable())
+			return;
+		//if (containedTree.nodeIsInternal(containing)) { // dJCOs This was original implementation. Oliver.July.04.2012
+		if (containedTree.nodeIsInternal(contained)) { // dJCOe Changed so containedTree is looking to see if contained node is internal. Oliver.July.04.2012
+			for (int d = containedTree.firstDaughterOfNode(contained); containedTree.nodeExists(d)&&!containingDescendant.isCombinable(); d = containedTree.nextSisterOfNode(d)) {
+				foundDescendant(d, containingDescendant);
+			}
+		} 
+
+	}
+	/*_________________________________________________*/
+	public void findLocationOfContainedNodesRec(int contained) {
+
+		if (containedTree.nodeIsInternal(contained)) {
+			for (int d = containedTree.firstDaughterOfNode(contained); containedTree.nodeExists(d); d = containedTree.nextSisterOfNode(d)) {
+				findLocationOfContainedNodesRec(d);
+			}
+			int shallowest = shallowestNodeThatContainedEnters(contained);
+			if (shallowest==0){// couldn't find it, so it must be buried within the clade.
+				//we need to look for descendants
+				MesquiteInteger containingDescendant =new MesquiteInteger();
+				for (int d = containedTree.firstDaughterOfNode(contained); containedTree.nodeExists(d); d = containedTree.nextSisterOfNode(d)) {
+					foundDescendant(d, containingDescendant);
+				}
+				if (containingDescendant.isCombinable())
+					locationOfContainedNode[contained] = containingDescendant.getValue();
+			} else if (containingTree.nodeIsTerminal(shallowest))
+				locationOfContainedNode[contained] = shallowest;
+			else {  // we found the shallowest (closest to terminals) containing node into which our contained node enters
+				// so we know the contained node itself is present in one of the immediate descendants of containing, but which one?
+				for (int d = containingTree.firstDaughterOfNode(shallowest); containingTree.nodeExists(d); d = containingTree.nextSisterOfNode(d)) {
+					MesquiteBoolean found = new MesquiteBoolean(false);
+					findDescendentThatEnters(d, contained, found);
+					if (found.getValue()) {
+						locationOfContainedNode[contained] = d;
+						break;
+					}
+				}
+			}
+
+		} else {  // it's a terminal node in the containedTree
+			for (int containing=0; containing<enteringContainedBranches.length; containing++) {   // going through nodes in containing tree
+				if (isNodeContained(containing, contained) && containingTree.nodeIsTerminal(containing)) {  // we've found the terminal with our branch
+					locationOfContainedNode[contained] = containing;
+					break;
+				}
+			}		
+		}
+	}
+
+	/*_________________________________________________*/
+	/* this must be called to fill in the array with the location of contained nodes */
+	public void  findLocationOfContainedNodes() {
+		if (containedTree!=null){
+			int numContained = containedTree.getNumNodeSpaces();
+			if (locationOfContainedNode==null || locationOfContainedNode.length<numContained)
+				locationOfContainedNode = new int[numContained];
+		}
+		findLocationOfContainedNodesRec(containedTree.getRoot());
+
+	}
+
+	/*_________________________________________________*/
+	private void findEnteringBranches (int contained) {
+		if (containedTree.nodeIsInternal(contained)) {
+			for (int d = containedTree.firstDaughterOfNode(contained); containedTree.nodeExists(d); d = containedTree.nextSisterOfNode(d)) {
+				findEnteringBranches(d);
+			}	
+		} else {  // it's a terminal node in the containedTree
+			setContainedNode(locationOfContainedNode[contained],  contained);
+		}
+
+		int anc = containedTree.motherOfNode(contained);
+		if (containedTree.nodeExists(anc) && anc!=containedTree.getSubRoot()) {
+			int locationOfMother = locationOfContainedNode[anc]; // so it must enter this containingNode, and any node back to it.
+			int locationOfContained = locationOfContainedNode[contained];
+			if (locationOfMother!=locationOfContained) 
+				for (int containingAnc = containingTree.motherOfNode(locationOfContained); containingAnc>0 && containingAnc!=containingTree.getSubRoot(); containingAnc = containingTree.motherOfNode(containingAnc)){
+					setContainedNode(containingAnc,  contained);
+					if (containingAnc==locationOfMother)
+						break;
+				}
+		}
+
+	}
+
+	/*_________________________________________________*/
+	private void calcEnteringContainedBranchesFromLocations() {
+		if (containedTree==null || containingTree==null || enteringContainedBranches==null || locationOfContainedNode==null)
+			return;
+		for (int i=0; i<enteringContainedBranches.length; i++) 
+			for (int j=0; j<enteringContainedBranches[i].length; j++)
+				enteringContainedBranches[i][j] = MesquiteInteger.unassigned;
+		findEnteringBranches(containedTree.getRoot());
+		//enteringContainedBranches
+		//locationOfContainedNode
+	}
+
+	/*_________________________________________________*/
+	public int  getLocationOfContainedNode(int contained) {
+		return locationOfContainedNode[contained];
+	}
+	/*_________________________________________________*/
+	public int[]  getLocationsOfContainedNodes() {
+		return locationOfContainedNode;
+	}
+
+
+	/*_________________________________________________*/
+	public String toString() {
+		String s = "Association History" + ParseUtil.lineEnding();
+		for (int i=0; i<enteringContainedBranches.length; i++) {
+			if (enteringContainedBranches[i][0]!= MesquiteInteger.unassigned) {
+				s+= "\tEntering containing node " + i + ": ";
+				for (int j=0; j<enteringContainedBranches[i].length; j++)
+					if (enteringContainedBranches[i][j] != MesquiteInteger.unassigned)
+						s += enteringContainedBranches[i][j] + "; ";
+				s += ParseUtil.lineEnding();
+			}
+		}
+		if (locationOfContainedNode!=null) {
+			s += "Locations of contained nodes" + ParseUtil.lineEnding();
+			for (int i=0; i<locationOfContainedNode.length; i++) {
+				if (locationOfContainedNode[i]!=0)
+					s+= "\tContained node " + i + " is present in containing node: "+ locationOfContainedNode[i]+ ParseUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+}
+
+/*-------------------------------------*/
+
+
+
diff --git a/Source/mesquite/assoc/lib/AssociationSource.java b/Source/mesquite/assoc/lib/AssociationSource.java
new file mode 100644
index 0000000..ec9ce37
--- /dev/null
+++ b/Source/mesquite/assoc/lib/AssociationSource.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Supplies TaxaAssociation's for instance from a file or simulated.*/
+
+public abstract class AssociationSource extends MesquiteModule  {
+	protected int numTaxaForNewBlock=0;
+	protected Taxa otherTaxa = null;
+	public Class getDutyClass() {
+   	 	return AssociationSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa Association Source";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredAssociations"};
+   	 }
+
+   	 /** THE following assume a single taxa block is used as anchor point, and looks for others.  
+   	  * These routines are independent of the two-taxa block routines, and snapshotting will only be done on the single taxa block routines */
+   	 /**Returns number of TaxaAssociation available.  If TaxaAssociation can be supplied indefinitely, returns MesquiteInteger.infinite*/
+    	public abstract int getNumberOfAssociations(Taxa taxa);
+  	 /**Returns indexth TaxaAssociation*/
+   	public abstract TaxaAssociation getAssociation(Taxa taxa, int index);
+   	
+   	 /**Returns current TaxaAssociation.*/
+   	public abstract TaxaAssociation getCurrentAssociation(Taxa taxa);
+   	/**Returns String naming list number index*/
+   	public String getAssociationNameString(Taxa taxa, int index) {
+   		return "";
+   	}
+   	
+   	public boolean requiresCreationOfTaxaA() {
+   		return false;
+   	}
+
+   	public boolean requiresCreationOfTaxaB() {
+   		return false;
+   	}
+   	
+   	public void setNumTaxaForNewBlock(int numTaxa) {
+   		numTaxaForNewBlock=numTaxa;
+   	}
+
+   	public int getNumTaxaForNewBlock() {
+   		return numTaxaForNewBlock;
+   	}
+   	
+  	 public Taxa getOtherTaxa() {
+ 		return otherTaxa;
+ 	}
+ 	public void setOtherTaxa(Taxa otherTaxa) {
+ 		this.otherTaxa = otherTaxa;
+ 	}
+
+
+ 	 /** THE following assume two taxa blocks are specified.  
+  	  * These routines are independent of the one-taxa block routines, and snapshotting will only be done on the single taxa block routines */
+  	
+ 	 /**Returns number of TaxaAssociation available.  If TaxaAssociation can be supplied indefinitely, returns MesquiteInteger.infinite*/
+   	public abstract int getNumberOfAssociations(Taxa taxa1, Taxa taxa2);
+  	 /**Returns indexth TaxaAssociation*/
+   	public abstract TaxaAssociation getAssociation(Taxa taxa1, Taxa taxa2, int index);
+    	
+}
+
+
diff --git a/Source/mesquite/assoc/lib/AssociationsManager.java b/Source/mesquite/assoc/lib/AssociationsManager.java
new file mode 100644
index 0000000..ed463bd
--- /dev/null
+++ b/Source/mesquite/assoc/lib/AssociationsManager.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** Manages Taxa Associations.  Also reads and writes ASSOCIATION block.  Example module: "Manage ASSOCIATION blocks" .*/
+
+public abstract class AssociationsManager extends FileElementManager   {
+
+   	 public Class getDutyClass() {
+   	 	return AssociationsManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of Taxa Associations, including read/write ASSOCIATION block";
+   	 }
+	
+	public abstract int getNumberOfAssociations(Taxa taxaA, Taxa taxaB);
+	public abstract int getNumberOfAssociations(Taxa taxa);
+	public abstract int getNumberOfAssociations();
+	public abstract TaxaAssociation getAssociation(Taxa taxaA, Taxa taxaB, int i);
+	public abstract TaxaAssociation getAssociation(Taxa taxa, int i);
+	public abstract int getWhichAssociation(Taxa taxa, TaxaAssociation assoc);
+	public abstract TaxaAssociation getAssociation(int i);
+	public abstract TaxaAssociation findAssociationByID(long id, Taxa taxa);
+  	 public abstract TaxaAssociation makeNewAssociation(Taxa taxaA, Taxa taxaB);
+	public abstract ListableVector getAssociationsVector();
+	public Class getElementClass(){
+		return TaxaAssociation.class;
+	}
+}
+
+
diff --git a/Source/mesquite/assoc/lib/NumberForAssocAndTree.java b/Source/mesquite/assoc/lib/NumberForAssocAndTree.java
new file mode 100644
index 0000000..e4a7dbb
--- /dev/null
+++ b/Source/mesquite/assoc/lib/NumberForAssocAndTree.java
@@ -0,0 +1,70 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.lib;
+
+import mesquite.lib.*;
+import mesquite.assoc.lib.*;
+import mesquite.lib.duties.ItemsSource;
+import mesquite.lib.duties.NumberForItem;
+
+public abstract class NumberForAssocAndTree extends MesquiteModule implements NumberForItem {
+
+	public Class getDutyClass() {
+		return NumberForAssocAndTree.class;
+	}
+
+	public String getDutyName() {
+		return "Number for Association and Tree";
+	}
+
+	public abstract void calculateNumber(Tree tree, TaxaAssociation association, MesquiteNumber result, MesquiteString resultString); 
+	
+  	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	
+  	public void initialize(){
+  	}
+
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+   	}
+   	
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Tree && object2 instanceof TaxaAssociation) {
+			calculateNumber((Tree)object1, (TaxaAssociation)object2,result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+  	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+	/** indicates default optimization, e.g. for association searchers.  If true, association search will maximize,
+	otherwise minimize.  If number has obvious optimum direction, this should be overridden to indicate
+	optimum*/
+	public boolean biggerIsBetter() {
+		return true;
+	}
+
+}
diff --git a/Source/mesquite/assoc/lib/NumberForAssociation.java b/Source/mesquite/assoc/lib/NumberForAssociation.java
new file mode 100644
index 0000000..e5d225f
--- /dev/null
+++ b/Source/mesquite/assoc/lib/NumberForAssociation.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.lib;
+
+import mesquite.lib.*;
+import mesquite.assoc.lib.*;
+import mesquite.lib.duties.ItemsSource;
+import mesquite.lib.duties.NumberForItem;
+
+public abstract class NumberForAssociation extends MesquiteModule implements NumberForItem {
+	TaxaAssociation currentAssociation=null;
+
+	public TaxaAssociation getCurrentAssociation() {
+		return currentAssociation;
+	}
+
+	public void setCurrentAssociation(TaxaAssociation currentAssociation) {
+		this.currentAssociation = currentAssociation;
+	}
+
+	public Class getDutyClass() {
+		return NumberForAssociation.class;
+	}
+
+	public String getDutyName() {
+		return "Number for Association";
+	}
+
+	public abstract void calculateNumber(TaxaAssociation association, MesquiteNumber result, MesquiteString resultString); 
+	
+  	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	
+  	public void initialize(){
+  	}
+
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+   	}
+   	
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof TaxaAssociation) {
+			calculateNumber((TaxaAssociation)object1,result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+  	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+	/** indicates default optimization, e.g. for association searchers.  If true, association search will maximize,
+	otherwise minimize.  If number has obvious optimum direction, this should be overridden to indicate
+	optimum*/
+	public boolean biggerIsBetter() {
+		return true;
+	}
+
+}
diff --git a/Source/mesquite/assoc/lib/ReconstructAssociation.java b/Source/mesquite/assoc/lib/ReconstructAssociation.java
new file mode 100644
index 0000000..c2c14be
--- /dev/null
+++ b/Source/mesquite/assoc/lib/ReconstructAssociation.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+
+public abstract class ReconstructAssociation extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return ReconstructAssociation.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Reconstructs a taxon association history";
+   	 }
+	/** reconstructs history of contained tree within containing.  Contained tree must be free to be modified; hence send in a clone instead of the original!*/
+	public abstract AssociationHistory reconstructHistory(Tree containing, MesquiteTree contained, TaxaAssociation association, MesquiteNumber cost, MesquiteString resultString);
+	/** calculates cost of fitting contained tree within containing.  Exact meaning depends on module (e.g., for RecCoalescenceHistory, cost is deep coalescences).  Contained tree must be free to be modified; hence send in a clone instead of the original!*/
+	public abstract void calculateHistoryCost(Tree containing, MesquiteTree contained, TaxaAssociation association, MesquiteNumber cost, MesquiteString resultString);
+}
+
+
diff --git a/Source/mesquite/assoc/lib/SimpleTaxaList.java b/Source/mesquite/assoc/lib/SimpleTaxaList.java
new file mode 100644
index 0000000..441f378
--- /dev/null
+++ b/Source/mesquite/assoc/lib/SimpleTaxaList.java
@@ -0,0 +1,272 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+
+
+public class SimpleTaxaList extends MesquitePanel implements AdjustmentListener {
+	Taxa taxa;
+	MousePanel homePanel;
+	boolean[] selected;
+	boolean[] assigned;
+	Scrollbar scrollBar;
+	int scrollWidth=16;
+	int topRow = 0;
+	
+	
+	public SimpleTaxaList(Taxa taxa, MousePanel homePanel) {
+		super();
+		this.homePanel = homePanel;
+		setBackground(Color.white);
+		scrollBar=new Scrollbar(Scrollbar.VERTICAL);
+		scrollBar.setVisible(true);
+		scrollBar.setValues(0,getNumRowsVisible(),0,0);
+		scrollBar.addAdjustmentListener(this);
+		scrollBar.setUnitIncrement(1);
+		scrollBar.setBlockIncrement(1);
+		add(scrollBar);
+		setTaxa(taxa);
+	}
+	
+	public void setAssigned(int i, boolean b) {
+		if (assigned!=null && i>=0 && i<assigned.length)
+			assigned[i] = b;
+	}
+	public boolean[] getSelectedList() {
+		return selected;
+	}
+
+	public boolean getSelected(int i){
+		if (i>=0 && i<selected.length)
+			return selected[i];
+		return false;
+	}
+
+	public void setSize(int width, int height) {
+		super.setSize(width,height);
+		if (scrollBar!=null) {
+			scrollBar.setSize(scrollWidth,height);
+			scrollBar.setLocation(getBounds().width-scrollWidth,0);
+			scrollBar.setVisibleAmount(getNumRowsVisible());
+			scrollBar.setBlockIncrement(getNumRowsVisible()-1);
+		}
+		
+	}
+
+	public void setLocation(int x, int y) {
+		super.setLocation(x,y);
+		if (scrollBar!=null)
+			scrollBar.setLocation(getBounds().width-scrollWidth,0);
+	}
+
+	public int getNumRowsVisible(){
+		if (taxa!=null)
+			return MesquiteInteger.minimum(taxa.getNumTaxa(), Math.round(getBounds().height/getRowHeight()));
+		return Math.round(getBounds().height/getRowHeight());
+	}
+	public void deselectAll() {
+		if (selected==null)
+			return;
+		for (int i=0; i<selected.length; i++) {
+			boolean wasSelected = selected[i];
+			selected[i]=false;
+			if (wasSelected) 
+				redrawRow(i, true);
+		}
+	}
+	public void selectRows(int row1, int row2) {
+		for (int i=row1; i<=row2; i++) {
+			if (i>=0 && i<selected.length) {
+				boolean wasSelected = selected[i];
+				selected[i]=true;
+				if (!wasSelected) 
+					redrawRow(i, true);
+			}
+		}
+	}
+	public void selectRow(int row,boolean b) {
+			if (row>=0 && row<selected.length) {
+				boolean wasSelected = selected[row];
+				selected[row]=b;
+				if (wasSelected!=b) 
+					redrawRow(row, true);
+			}
+	}
+	public void setTaxa(Taxa taxa) {
+		if (taxa!=null){//&& taxa!=this.taxa) {
+			this.taxa = taxa;
+			selected = new boolean[taxa.getNumTaxa()];
+			assigned = new boolean[taxa.getNumTaxa()];
+			for (int i=0; i<selected.length; i++){
+				selected[i]=false;
+				assigned[i]=false;
+			}
+			scrollBar.setMaximum(taxa.getNumTaxa());
+		}
+	}
+	
+	public void paint(Graphics g) {
+		if (taxa==null || g==null)
+			return;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int numParts =  taxa.getNumTaxa();
+		for (int i=0; i<numParts && i<selected.length; i++) {
+			drawRow(g, i, fm.getMaxDescent(), false);
+		}
+	}
+	
+	public void drawRow(Graphics g, int row, int maxDescent, boolean erase) {
+		if (taxa==null || row<0 || row>=selected.length || row>=taxa.getNumTaxa())
+			return;
+		if (!getRowVisible(row))
+			return;
+		if (selected[row])  {
+			g.setColor(Color.lightGray);
+			g.fillRect(0,getRowTop(row),getBounds().width, getRowHeight());		
+		}
+		else if (erase) {
+			g.setColor(Color.white);
+			g.fillRect(0,getRowTop(row),getBounds().width, getRowHeight());
+		}
+		int offset = 15;
+		if (assigned[row]) {
+			g.setColor(Color.gray);
+			offset=0;
+		}
+		else {
+			g.setColor(Color.black);
+		}
+		if (taxa.getTaxonName(row) != null)
+			g.drawString(taxa.getTaxonName(row),5+offset,getRowBottom(row)-maxDescent);
+	}
+	public void redrawRow(int row, boolean erase) {
+		if (taxa==null || row<0)
+			return;
+		Graphics g = getGraphics();
+		if (g==null)
+			return;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		drawRow(g,row,fm.getMaxDescent(), erase);
+		g.dispose();
+		
+	}
+	public int getRowHeight() {
+		Graphics g = getGraphics();
+		if (g==null)
+			return -1;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int rowHeight = (fm.getMaxAscent() + fm.getMaxDescent() + 6);
+		g.dispose();
+		return (rowHeight);
+	}
+	public int getRowTop(int row) {
+		if (taxa==null)
+			return -1;
+		Graphics g = getGraphics();
+		if (g==null)
+			return -1;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int rowHeight = (fm.getMaxAscent() + fm.getMaxDescent() + 6);
+		g.dispose();
+		return ((row-topRow)*rowHeight);
+	}
+	public int getRowBottom(int row) {
+		if (taxa==null)
+			return -1;
+		Graphics g = getGraphics();
+		if (g==null)
+			return -1;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int rowHeight = (fm.getMaxAscent() + fm.getMaxDescent() + 6);
+		g.dispose();
+		return ((row-topRow)*rowHeight+rowHeight);
+	}
+	public boolean getRowVisible(int row) {
+		return (getRowTop(row)<getBounds().height && getRowBottom(row)>=0);
+	}
+	
+	public int findRow(int y) {
+		if (taxa==null)
+			return -1;
+		int numParts =  taxa.getNumTaxa();
+		int row = -1;
+		for (int i=0; i<numParts; i++) {
+			if (y>getRowTop(i) && y<= getRowBottom(i)) {
+				row = i;
+				break;
+			}
+		}
+		return row;
+	}
+	
+	
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		int  row = findRow(y);
+		if (row>=0 && row<=selected.length && row<=taxa.getNumTaxa()) {
+			if (!selected[row] && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers))
+				deselectAll();
+			if (MesquiteEvent.shiftKeyDown(modifiers)) {
+				boolean selectionExtended = false;
+				for (int i=0; i<row; i++)
+					if (selected[i]){
+						selectRows(i,row);
+						selectionExtended=true;
+						break;
+					}
+				if (!selectionExtended)
+					for (int i=taxa.getNumTaxa()-1; i>row && i<selected.length; i--)
+						if (selected[i]){
+							selectRows(row,i);
+							selectionExtended=true;
+							break;
+						}
+				if (!selectionExtended) {
+					selected[row]= !selected[row];
+					redrawRow(row, false);
+				}
+			}
+			else {
+				if (MesquiteEvent.commandOrControlKeyDown(modifiers))
+					selected[row]= !selected[row];
+				else 
+					selected[row]= true;
+				redrawRow(row, false);
+			}
+		} else
+			deselectAll();
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+
+	public void adjustmentValueChanged(AdjustmentEvent e) {
+		if(e.getAdjustable() == scrollBar) {
+			switch(e.getAdjustmentType()) {
+			case AdjustmentEvent.UNIT_DECREMENT:
+			case AdjustmentEvent.UNIT_INCREMENT:
+			case AdjustmentEvent.BLOCK_INCREMENT:
+			case AdjustmentEvent.BLOCK_DECREMENT:
+			case AdjustmentEvent.TRACK:
+				topRow = e.getValue();
+				repaint();
+				break;
+			}
+		}
+	}
+	
+}
diff --git a/Source/mesquite/assoc/lib/TaxaAssociation.java b/Source/mesquite/assoc/lib/TaxaAssociation.java
new file mode 100644
index 0000000..4b0f29e
--- /dev/null
+++ b/Source/mesquite/assoc/lib/TaxaAssociation.java
@@ -0,0 +1,706 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.assoc.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+class TaxonWithTaxa{
+	Taxon t = null;
+	Taxa taxaB;
+	Taxon[] associates;
+	int numA = 0;
+	public TaxonWithTaxa(Taxon t, Taxa taxaB){
+		this.t = t;
+		associates= new Taxon[taxaB.getNumTaxa()];
+		this.taxaB = taxaB;
+	}
+	Taxon getTaxon(){
+		return t;
+	}
+	Taxon getAssociate(int i){
+		if (i<0 || i>=associates.length)
+			return null;
+		return associates[i];
+	}
+	void addAssociate(Taxon tB){
+		if (tB==null)
+			return;
+		for (int i=0; i<associates.length; i++){
+			if (tB == associates[i])
+				return;
+			if (associates[i] == null) {
+				associates[i] = tB;
+				return;
+			}
+		}
+	}
+	void deleteDefunct(){
+		for (int where = associates.length-1; where>=0; where--){
+			Taxon tD = associates[where];
+			if (tD!=null && taxaB.whichTaxonNumber(tD)<0)
+				deleteAssociate(tD);
+		}
+	}
+	void deleteAssociate(Taxon tB){
+		if (tB==null)
+			return;
+		int where = findAssociate(tB);
+		int last = findLastAssociate();
+		if (where>-1) { 
+			associates[where] = null;
+			if (last>-1) {
+				associates[where] = associates[last];
+				associates[last] = null;
+			}
+		}
+	}
+
+	void deleteAllAssociates(){
+		for (int i=0; i<associates.length; i++)
+			associates[i] = null;
+	}
+
+	int findAssociate(Taxon tB){
+		for (int i=0; i<associates.length; i++){
+			if (tB == associates[i])
+				return i;
+		}
+		return -1;
+	}
+	int findLastAssociate(){
+		for (int i=0; i<associates.length; i++){
+			if (associates[i] == null) {
+				return i-1;
+			}
+		}
+		return -1;
+	}
+	int length(){
+		return associates.length;
+	}
+	public String toString(){
+		String s = "With " + t.getName() + ":";
+		for (int i=0; i<associates.length; i++){
+			if (associates[i] != null) {
+				s += " \"" + associates[i].getName() + "\"";
+			}
+		}
+		return s;
+	}
+}
+/** .*/
+public class TaxaAssociation extends FileElement  {
+	//TODO: needs to listen to changes in taxa and respond to change numbers etc.
+	Taxa taxaA, taxaB;
+	TaxonWithTaxa[] associations;
+	public TaxaAssociation(){
+	}
+	/*.................................................................................................................*/
+	public void setTaxa(Taxa taxa, int index){
+		if (index==0)
+			taxaA = taxa;
+		else if (index==1)
+			taxaB = taxa;
+		else
+			MesquiteMessage.warnProgrammer("Error: Taxa association allows only two Taxa objects");
+		if (taxaA!=null && taxaB!=null) {
+			associations= new TaxonWithTaxa[taxaA.getNumTaxa()];
+			for (int i=0; i<taxaA.getNumTaxa(); i++) {
+				associations[i] = new TaxonWithTaxa(taxaA.getTaxon(i), taxaB);
+				for (int j = 0; j<taxaB.getNumTaxa(); j++){
+					setAssociated(i, j, false);
+				}
+			}
+		}
+		else
+			associations = null;
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "taxaAssocSmall.gif";
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets taxon N in block A as NOT associated with taxon M in block B", "[N][M]", commandName, "deassociate")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int a = MesquiteInteger.fromString(arguments, io);
+			int b = MesquiteInteger.fromString(arguments, io);
+			setAssociated(a, b, false);
+		}
+		else if (checker.compare(this.getClass(), "Sets taxon N in block A as associated with taxon M in block B", "[N][M]", commandName, "associate")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int a = MesquiteInteger.fromString(arguments, io);
+			int b = MesquiteInteger.fromString(arguments, io);
+			setAssociated(a, b, true);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+			return null;
+	}
+	/*.................................................................................................................*/
+	public Taxon getRandomAssociate(Taxon taxon, RandomBetween rng) {
+		if (taxon==null) return null;
+		Taxon[] associates = getAssociates(taxon);
+		if (associates==null) return null;
+		Taxon associate=null;
+		if (associates.length==1 || rng==null)
+			associate = associates[0];
+		else
+			associate = associates[rng.randomIntBetween(0, associates.length-1)];
+		return associate;
+	}
+
+	/*.................................................................................................................*/
+	private void moveAssociation(int a , int b) {
+		for (int it=0; it<taxaA.getNumTaxa(); it++)
+			setAssociated(it, b, false);
+		setAssociated(a, b, true);
+	}
+	/*.................................................................................................................*/
+	public void moveAssociation(Taxon taxonA, Taxon taxonB){
+		if (taxaA==null || taxaB == null)
+			return;
+		int a = taxaA.whichTaxonNumber(taxonA);
+		int b;
+		//enlarge matrices!
+		if (a>-1) {  // taxonA belongs to taxaA
+			b = taxaB.whichTaxonNumber(taxonB);
+			if (b!=-1)
+				moveAssociation(a, b);
+		} else
+		{ //either illegal or second taxon belongs to first Taxa
+			a = taxaB.whichTaxonNumber(taxonA);
+			b = taxaA.whichTaxonNumber(taxonB);
+			if (a!=-1 && b!=-1)
+				moveAssociation(b,a);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public TaxaAssociation cloneAssociation(){
+		TaxaAssociation newAssociation = new TaxaAssociation();
+		newAssociation.setTaxa(getTaxa(0),0);
+		newAssociation.setTaxa(getTaxa(1),1);
+		for (int a=0;a<getTaxa(0).getNumTaxa() ; a++){
+			for (int b=0;b<getTaxa(1).getNumTaxa(); b++){
+				if (areAssociated(a,b))
+					newAssociation.setAssociated(a,b,true);
+			}
+		}
+		newAssociation.setName(getName());
+		return newAssociation;
+	}
+	/*.................................................................................................................*/
+	public int getNumWithNoAssociates(Taxa taxa) {
+		int count=0;
+		for (int it=0; it<taxa.getNumTaxa(); it++)
+			if (getNumAssociates(taxa.getTaxon(it))<1) {
+				count++;
+			}
+		return count;
+	}
+	/*.................................................................................................................*/
+	/** true iff Taxon taxon is the only associate of the taxon to which it is associated */
+	public boolean onlyAssociate(Taxon taxon) {
+		if (taxaA==null || taxaB == null)
+			return false;
+		int a = taxaA.whichTaxonNumber(taxon);
+		if (a>-1) { //taxon belongs to taxaA
+			for (int it=0; it<taxaB.getNumTaxa(); it++) {
+				if (areAssociated(a,it)) {
+					Taxon associate = taxaB.getTaxon(it);
+					if (getNumAssociates(associate)==1)
+						return true;
+				}
+			}
+		}
+		else {
+			int b = taxaB.whichTaxonNumber(taxon);
+			for (int it=0; it<taxaA.getNumTaxa(); it++) {
+				if (areAssociated(it,b)) {  //  this taxon is associated with it in taxonA
+					Taxon associate = taxaA.getTaxon(it);
+					if (getNumAssociates(associate)==1)
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** true iff Taxon taxon is the only associate of the taxon to which it is associated */
+	public boolean lessThanNumberOfAssociates(Taxon taxon, int minimum) {
+		if (taxaA==null || taxaB == null)
+			return false;
+		int a = taxaA.whichTaxonNumber(taxon);
+		if (a>-1) { //taxon belongs to taxaA
+			for (int it=0; it<taxaB.getNumTaxa(); it++) {
+				if (areAssociated(a,it)) {
+					Taxon associate = taxaB.getTaxon(it);
+					int numAssoc = getNumAssociates(associate);
+					if (numAssoc>0 && numAssoc<minimum)
+						return true;
+				}
+			}
+		}
+		else {
+			int b = taxaB.whichTaxonNumber(taxon);
+			for (int it=0; it<taxaA.getNumTaxa(); it++) {
+				if (areAssociated(it,b)) {  //  this taxon is associated with it in taxonA
+					Taxon associate = taxaA.getTaxon(it);
+					int numAssoc = getNumAssociates(associate);
+					if (numAssoc>0 && numAssoc<minimum)
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Copies associations in {@code association} to this instance of {@code TaxaAssociation}.
+	 * 
+	 * <p>May lead to contained (gene) taxa being associated with multiple containing (species) 
+	 * taxons.  To avoid this, see {@link #copyAssociates(TaxaAssociation, boolean)}.</p>
+	 * 
+	 * @param	association	the association to copy.*/
+	public void copyAssociates(TaxaAssociation association){
+		copyAssociates(association, false);
+	}
+	/*.................................................................................................................*/
+	/** Copies associations in {@code association} to this instance of {@code TaxaAssociation}.
+	 * 
+	 * @param	association	the association to copy.
+	 * 
+	 * @param	zeroAll	boolean indicating whether or not to zero all current associations before copying.  If set to 
+	 * {@code false}, copying may result in contained (gene) taxa being associated with multiple containing (species) 
+	 * taxons.*/
+	public void copyAssociates (TaxaAssociation association, boolean zeroAll) {
+		if (association == null) {
+			return;
+		}
+		Taxa sourceTaxaA = association.getTaxa(0);
+		Taxa sourceTaxaB = association.getTaxa(1);
+		if (taxaA.getNumTaxa()!= sourceTaxaA.getNumTaxa() || taxaB.getNumTaxa()!= sourceTaxaB.getNumTaxa()) {
+			return;
+		}
+		if (zeroAll) {
+			zeroAllAssociations();
+		}
+		for (int a=0; a<taxaA.getNumTaxa(); a++) {
+			for (int b=0; b<taxaB.getNumTaxa(); b++) {
+				setAssociated(a,b,association.getAssociation(sourceTaxaA.getTaxon(a), sourceTaxaB.getTaxon(b)));
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private boolean areAssociated(int a, int b){
+		if (a >=0 && a < taxaA.getNumTaxa() && b >= 0 && b < taxaB.getNumTaxa()){
+			Taxon taxonA = taxaA.getTaxon(a);
+			if (taxonA == null)
+				return false;
+			for (int i= 0; i<associations.length; i++)
+				if (associations[i].t == taxonA)
+					return associations[i].findAssociate(taxaB.getTaxon(b))>=0;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean equals(TaxaAssociation association){
+		if (association==null)
+			return false;
+		Taxa otherA = association.getTaxa(0);
+		Taxa otherB = association.getTaxa(1);
+		if (taxaA.getNumTaxa() != otherA.getNumTaxa() || taxaB.getNumTaxa() != otherB.getNumTaxa())
+			return false;
+		for (int a=0;a<taxaA.getNumTaxa() ; a++){
+			for (int b=0;b<taxaB.getNumTaxa(); b++){
+				if (areAssociated(a,b) !=association.areAssociated(a,b))
+					return false;
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean hasSamePattern(TaxaAssociation association){   //taxonA can differ
+		if (association==null)
+			return false;
+		Taxa otherA = association.getTaxa(0);
+		Taxa otherB = association.getTaxa(1);
+		
+		if (taxaA.getNumTaxa() != otherA.getNumTaxa() || taxaB.getNumTaxa() != otherB.getNumTaxa())
+			return false;
+		
+
+		int[] otherEquivalentToLocal = new int[otherA.getNumTaxa()];
+		for (int a=0; a<taxaA.getNumTaxa(); a++) {
+			boolean foundOne = false;
+			otherEquivalentToLocal[a]=a;  // default set it to be the same
+			for (int b=0;b<taxaB.getNumTaxa() && !foundOne; b++){
+				if (areAssociated(a,b)){ // find something that is in this bin in taxonA
+					//now see where it is in otherA
+					for (int c=0; c<otherA.getNumTaxa()&& !foundOne; c++) {
+						if (association.areAssociated(c, b)){  // here it is
+							otherEquivalentToLocal[a]=c;
+							foundOne=true;
+						}
+					}
+
+				}
+			}
+		}
+		
+		for (int a=0;a<taxaA.getNumTaxa() ; a++){
+			for (int b=0;b<taxaB.getNumTaxa(); b++){
+				if (areAssociated(a,b) !=association.areAssociated(otherEquivalentToLocal[a],b))
+					return false;
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void setAssociated(int a, int b, boolean assoc){
+		if (a >=0 && a < taxaA.getNumTaxa() && b >= 0 && b < taxaB.getNumTaxa()) {
+			Taxon taxonA = taxaA.getTaxon(a);
+			if (taxonA == null)
+				return;
+			for (int i= 0; i<associations.length; i++)
+				if (associations[i] != null && associations[i].t == taxonA){
+
+					if (assoc){
+						associations[i].addAssociate(taxaB.getTaxon(b));
+					}
+					else {
+						associations[i].deleteAssociate(taxaB.getTaxon(b));
+					}
+				}
+		}
+	}
+	/*.................................................................................................................*/
+	public void replaceWith(TaxaAssociation source){
+
+	}
+	/*.................................................................................................................*/
+	public void zeroAllAssociations(){
+		for (int it=0; it<taxaA.getNumTaxa(); it++)
+			zeroAllAssociations(taxaA.getTaxon(it));
+	}
+
+	/*.................................................................................................................*/
+	public void zeroAllAssociations(Taxon taxon){
+		if (taxaA==null || taxaB == null)
+			return;
+
+		int a = taxaA.whichTaxonNumber(taxon);
+		if (a>-1) { //taxon belongs to taxaA
+			associations[a].deleteAllAssociates();
+		}
+		else {
+			//taxon belongs to taxaB; remove all references to it
+			for (int i = 0; i<taxaA.getNumTaxa(); i++)
+				associations[i].deleteAssociate(taxon);
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetTaxaAfterChange(){
+		//go through deleting defunct taxa
+		for (int a = 0; a < associations.length; a++) {
+			if (taxaA.whichTaxonNumber(associations[a].t)<0)
+				associations[a] = null;
+			else {
+				associations[a].deleteDefunct();
+			}	
+		}
+		//change size of arrays as needed
+		TaxonWithTaxa[] newAssociations= new TaxonWithTaxa[taxaA.getNumTaxa()];
+
+		int count = 0;
+		for (int i=0; i<associations.length; i++) {
+			if (associations[i]!=null){
+				TaxonWithTaxa oldT = associations[i];
+				newAssociations[count] = new TaxonWithTaxa(oldT.getTaxon(), taxaB);
+				for (int j = 0; j<oldT.length(); j++){
+					newAssociations[count].addAssociate(oldT.getAssociate(j));
+				}
+				count++;
+			}
+		}
+		for (int i=count; i<taxaA.getNumTaxa(); i++)
+			newAssociations[i] = new TaxonWithTaxa(taxaA.getTaxon(i), taxaB);
+		associations = newAssociations;
+	}
+	/*-----------------------------------------*/
+	public String toString(){
+		String names = "";
+		if (taxaA!=null && taxaB!=null)
+			names =  " involving " + taxaA.getName() + " and " + taxaB.getName();
+		String s = "Taxa Association " + getName() + names+  "\n";
+		for (int i=0; i<associations.length; i++) {
+			if (associations[i]!=null){
+				s += "  " + associations[i] + "\n";
+			}
+		}
+		return s;
+
+	}
+	/*-----------------------------------------*/
+	/** Returns explanation (what taxa involved)*/
+	public String getExplanation(){
+		String s ="This stores the association between taxa of ";
+		if (taxaA==null || taxaB == null)
+			s+= "two blocks";
+		else 
+			s+=  "the block \"" + taxaA.getName() + "\", having " + taxaA.getNumTaxa() + " taxa, with taxa of the block \"" + taxaB.getName() + "\", having " + taxaB.getNumTaxa() + " taxa";
+		return s;
+	}
+	/*-----------------------------------------*/
+	/** For HNode interface.  todo: this should be renamed getHNodeShow*/
+	public boolean getHShow(){
+		return true;
+	}
+
+	/*-----------------------------------------*/
+	/** For HNode interface.*/
+	public String getTypeName(){
+		return "Taxa Association";
+	}
+	/*.................................................................................................................*/
+	public Taxa getTaxa(int index){
+		if (index==0)
+			return taxaA;
+		else if (index==1)
+			return taxaB;
+		else
+			MesquiteMessage.warnProgrammer("Error: Taxa association allows only two Taxa objects *");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Taxa getOtherTaxa(Taxa taxa){
+		if (taxa==taxaB)
+			return taxaA;
+		else if (taxa == taxaA)
+			return taxaB;
+		else
+			MesquiteMessage.warnProgrammer("Error: taxa passed to getOtherTaxa not present *");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void setAssociation(Taxon taxonA, Taxon taxonB, boolean associated){
+		if (taxaA==null || taxaB == null)
+			return;
+		int a = taxaA.whichTaxonNumber(taxonA);
+		int b;
+		//enlarge matrices!
+		if (a==-1) { //either illegal or second taxon belongs to first Taxa
+			a = taxaB.whichTaxonNumber(taxonA);
+			b = taxaA.whichTaxonNumber(taxonB);
+			if (a!=-1 && b!=-1)
+				setAssociated(b,a, associated);
+		}
+		else  {
+			b = taxaB.whichTaxonNumber(taxonB);
+			if (b!=-1)
+				setAssociated(a, b, associated);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean getAssociation(Taxon taxonA, Taxon taxonB){
+		if (!includedTaxon(taxonA) || !includedTaxon(taxonA))
+			return false;
+		int a = taxaA.whichTaxonNumber(taxonA);
+		int b;
+		if (a==-1) { //either illegal or second taxon belongs to first Taxa
+			a = taxaB.whichTaxonNumber(taxonA);
+			b = taxaA.whichTaxonNumber(taxonB);
+			if (a!=-1 && b!=-1)
+				return areAssociated(b,a);
+		}
+		else  {
+			b = taxaB.whichTaxonNumber(taxonB);
+			if (b!=-1)
+				return areAssociated(a, b);
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getNumAssociates(Taxon taxon){
+		if (!includedTaxon(taxon))
+			return 0;
+		int which = taxaA.whichTaxonNumber(taxon);
+		if (which==-1) { //taxon belongs to B; need to look down matrix
+			which = taxaB.whichTaxonNumber(taxon);
+			if (which==-1)
+				return 0;
+			int num = 0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(i, which))//bug pre-1.1build62: used associates index instead of taxaA index
+					num++;
+			return num;
+		}
+		else   { //taxon belongs to A; need to look across matrix
+			int num = 0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					num++;
+			return num;
+		}
+	}
+	/*.................................................................................................................*/
+	/* this version avoids instantiation of Taxon array*/
+	public Taxon[] getAssociates(Taxon taxon, Taxon[] result){
+
+		if (!includedTaxon(taxon))
+			return null;
+		int which = taxaA.whichTaxonNumber(taxon);
+		if (which==-1) { //taxon belongs to B; need to look down matrix
+			which = taxaB.whichTaxonNumber(taxon);
+			if (which==-1)
+				return null;
+			int num = 0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //counting how many associates //bug pre-1.1build62: used associates index instead of taxaA index
+				if (areAssociated(i, which))
+					num++;
+			if (num==0)
+				return null;
+			if (result==null || result.length < num)
+				result = new Taxon[num];
+			for (int i=0; i<result.length; i++)
+				result[i] = null;
+			int count=0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //accumulating associates //bug pre-1.1build62: used associates index instead of taxaA index
+				if (areAssociated(i, which)) {
+					if (count<result.length)
+						result[count] = taxaA.getTaxon(i);
+					count++;
+				}
+			return result;
+		}
+		else   { //taxon belongs to A; need to look across matrix
+			int num = 0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					num++;
+			if (num==0)
+				return null;
+			if (result==null || result.length < num)
+				result = new Taxon[num];
+			for (int i=0; i<result.length; i++)
+				result[i] = null;
+			int count=0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++)  //accumulating associates
+				if (areAssociated(which, i)) {//bug pre-1.1build62: used associates index instead of taxaB index
+					if (count<result.length)
+						result[count] = taxaB.getTaxon(i);
+					count++;
+				}
+			return result;
+		}
+	}
+	/*.................................................................................................................*/
+	public Taxon[] getAssociates(Taxon taxon){
+		if (!includedTaxon(taxon))
+			return null;
+		int which = taxaA.whichTaxonNumber(taxon);
+		if (which==-1) { //taxon belongs to B; need to look down matrix
+			which = taxaB.whichTaxonNumber(taxon);
+			if (which==-1)
+				return null;
+			int num = 0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(i, which))//bug pre-1.1build62: used associates index instead of taxaA index
+					num++;
+			if (num==0)
+				return null;
+			Taxon[] result = new Taxon[num];
+			int count=0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //accumulating associates
+				if (areAssociated(i, which))//bug pre-1.1build62: used associates index instead of taxaA index
+					result[count++] = taxaA.getTaxon(i);
+			return result;
+		}
+		else   { //taxon belongs to A; need to look across matrix
+			int num = 0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					num++;
+			if (num==0)
+				return null;
+			Taxon[] result = new Taxon[num];
+			int count=0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++)  //accumulating associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					result[count++] = taxaB.getTaxon(i);
+			return result;
+		}
+	}
+	/*.................................................................................................................*/
+	public Bits getAssociatesAsBits(Taxa taxa, int taxonNumber){
+		Taxon taxon = taxa.getTaxon(taxonNumber);
+		if (!includedTaxon(taxon))
+			return null;
+		int which = taxaA.whichTaxonNumber(taxon);
+		if (which==-1) { //taxon belongs to B; need to look down matrix
+			which = taxaB.whichTaxonNumber(taxon);
+			if (which==-1)
+				return null;
+			int num = 0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(i, which))//bug pre-1.1build62: used associates index instead of taxaA index
+					num++;
+			if (num==0)
+				return null;
+			Bits result = new Bits(taxaA.getNumTaxa());
+			result.clearAllBits();
+			int count=0;
+			for (int i=0; i<taxaA.getNumTaxa(); i++) //accumulating associates
+				if (areAssociated(i, which)){//bug pre-1.1build62: used associates index instead of taxaA index
+					result.setBit(i);
+				}
+			return result;
+		}
+		else   { //taxon belongs to A; need to look across matrix
+			int num = 0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++) //counting how many associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					num++;
+			if (num==0)
+				return null;
+			Bits result = new Bits(taxaB.getNumTaxa());
+			result.clearAllBits();
+			int count=0;
+			for (int i=0; i<taxaB.getNumTaxa(); i++)  //accumulating associates
+				if (areAssociated(which,i))//bug pre-1.1build62: used associates index instead of taxaB index
+					result.setBit(i);
+			return result;
+		}
+	}
+	public boolean includedTaxon(Taxon taxon){
+		if (taxaA==null || taxaB == null)
+			return false;
+		int which = taxaA.whichTaxonNumber(taxon);
+		if (which==-1) { //taxon belongs to B; need to look down matrix
+			which = taxaB.whichTaxonNumber(taxon);
+			if (which==-1 || which >= taxaB.getNumTaxa())
+				return false;
+		}
+		else   { //taxon belongs to A; need to look across matrix
+			if (which >= taxaA.getNumTaxa())
+				return false;
+		}
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/assoc/macros/setupAssocMacro b/Source/mesquite/assoc/macros/setupAssocMacro
new file mode 100644
index 0000000..af7ddaa
--- /dev/null
+++ b/Source/mesquite/assoc/macros/setupAssocMacro
@@ -0,0 +1,38 @@
+telling mesquite.minimal.BasicFileCoordinator.BasicFileCoordinator  'Set up Associated Taxa block'   'Creates a block of taxa, creates an association between it and the previously existing block, and presents a way to build the associated block of taxa.  Assumes the current file has a single block of taxa'   0;
+queryYesNo 'This macro assumes there is a single block of taxa available.  It creates a second block and associates it with the first' 'Stop' 'Continue';
+Integer.answer *It;
+if *Integer.answer;
+	getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+	tell It;
+		String.existing *It;
+		newTaxa 1 'Associates';
+		tell It;
+			setTaxonName 0 'associate 1';
+		endTell;
+	endTell;
+	
+	getEmployee #mesquite.assoc.ManageAssociations.ManageAssociations;
+	tell It;
+		makeAssociation 0 1;
+	endTell;
+	
+	getEmployee  #mesquite.minimal.ManageTaxa.ManageTaxa;
+	tell It;
+		showTaxa 0 #mesquite.lists.TaxonList.TaxonList;
+		tell It;
+			getWindow;
+			tell It;
+				newAssistant  #mesquite.lists.TaxonListCurrPartition.TaxonListCurrPartition;
+				newAssistant  #mesquite.assoc.TaxonListAssoc.TaxonListAssoc;
+				tell It;
+					getEmployee #mesquite.assoc.StoredAssociations.StoredAssociations;
+					tell It;
+						setCurrentAssociation 0;
+					endTell;
+				endTell;
+			endTell;
+			showWindow;
+		endTell;
+	endTell;
+	alert 'In the List of Taxa window is now a column labelled Associates.  Select rows and then touch on this column heading to get a menu in which you can indicate what taxa in the other block are associated with the selected taxa.  You can also create new taxa in that other block using the drop down menu.  In this way you can complete the specification of what are the associated taxa'; 
+endIf;
diff --git a/Source/mesquite/basic/AddToTaxonNames/AddToTaxonNames.java b/Source/mesquite/basic/AddToTaxonNames/AddToTaxonNames.java
new file mode 100644
index 0000000..6bb026a
--- /dev/null
+++ b/Source/mesquite/basic/AddToTaxonNames/AddToTaxonNames.java
@@ -0,0 +1,102 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.AddToTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AddToTaxonNames extends TaxonNameAlterer {
+	String textToAdd="";
+	MesquiteBoolean addToEnd = new MesquiteBoolean(true);
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Add to Taxon Names",  buttonPressed);
+		queryDialog.addLabel("Add to Taxon Names", Label.CENTER);
+		SingleLineTextField prefixField = queryDialog.addTextField("Text:", textToAdd, 12);
+		Checkbox addToEndBox = queryDialog.addCheckBox("add to end of names", addToEnd.getValue());
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			textToAdd = prefixField.getText();
+			addToEnd.setValue(addToEndBox.getState());
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String s;
+			if (addToEnd.getValue())
+				s =  name + textToAdd;
+			else
+				s =  textToAdd + name;
+			taxa.setTaxonName(it, s, false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Adds text to taxon names", "[text]", commandName, "addText")) {
+	   	 		if (taxa !=null){
+	   	 			 textToAdd = parser.getFirstToken(arguments);
+    	 				addToEnd.toggleValue(parser.getNextToken());
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Add to Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add text to taxon names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Adds text to taxon names.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/AssignTaxonNames/AssignTaxonNames.java b/Source/mesquite/basic/AssignTaxonNames/AssignTaxonNames.java
new file mode 100644
index 0000000..f459423
--- /dev/null
+++ b/Source/mesquite/basic/AssignTaxonNames/AssignTaxonNames.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.AssignTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AssignTaxonNames extends TaxonNameAlterer {
+	String prefix = "taxon ";
+	int startingNumber = 0;
+	int counter = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean getOptions(Taxa taxa, int firstSelected){
+		counter=0;
+		if (MesquiteThread.isScripting())
+			return true;
+		
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Assign Taxon Names",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Assign Taxon Names");
+		
+		SingleLineTextField baseName = dialog.addTextField("Base for taxon names: ", prefix, 25);
+		IntegerField startingNumberField = dialog.addIntegerField("Starting number", firstSelected+1, 8, 0, 1000000);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			prefix = baseName.getText();
+			startingNumber = startingNumberField.getValue();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+		}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		int num = startingNumber + counter;
+		taxa.setTaxonName(it, prefix + num, false);
+		counter++;
+		return true;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Assign Taxon Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Assign taxon names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Assigns to each taxon name a string followed by a number.  For example, if the string is \"g\", then taxon 3 will be assigned the name g3.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/AuthorDefaults/AuthorDefaults.java b/Source/mesquite/basic/AuthorDefaults/AuthorDefaults.java
new file mode 100644
index 0000000..713525d
--- /dev/null
+++ b/Source/mesquite/basic/AuthorDefaults/AuthorDefaults.java
@@ -0,0 +1,233 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.AuthorDefaults;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AuthorDefaults extends DefaultsAssistant {
+	MesquiteBoolean authorBlockDefault;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		authorBlockDefault = new MesquiteBoolean(Author.addAuthorBlockByDefault);
+		loadPreferences();
+		addMenuItemToDefaults( "Set Author...", makeCommand("setAuthor",  this));
+		addCheckMenuItemToDefaults(null, "Record Authors by Default", makeCommand("recordAuthors",  this), authorBlockDefault);
+		return true;
+	}
+	public void endJob(){
+		super.endJob();
+		storePreferences();
+	}
+
+
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			if ("&".equals(prefs[0])){
+				if (prefs.length > 1){
+					authorBlockDefault.setValue("recordAuthors".equalsIgnoreCase(prefs[1]));
+					if (prefs.length >2){
+						MesquiteModule.author.setName(prefs[2]);
+						if (prefs.length>3)
+							MesquiteModule.author.setCode(prefs[3]);
+
+					}
+				}
+			}
+			else if ("-*".equals(prefs[0]))
+				;
+			else {
+				MesquiteModule.author.setName(prefs[0]);
+				if (prefs.length>1)
+					MesquiteModule.author.setCode(prefs[1]);
+			}
+		}
+	}
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("authorBlockDefault".equalsIgnoreCase(tag)){
+			authorBlockDefault.setValue(content);
+			Author.addAuthorBlockByDefault = authorBlockDefault.getValue();
+
+		}
+		else if ("authorName".equalsIgnoreCase(tag)){
+			MesquiteModule.author.setName(content);
+		}
+		else if ("authorCode".equalsIgnoreCase(tag)){
+			MesquiteModule.author.setCode(content);
+		}
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "authorBlockDefault", authorBlockDefault);  
+		StringUtil.appendXMLTag(buffer, 2, "authorName", MesquiteModule.author.getName());
+		StringUtil.appendXMLTag(buffer, 2, "authorCode", MesquiteModule.author.getCode());    
+		return buffer.toString();
+	}
+	/*.................................................................................................................*
+	public String[] preparePreferencesForFile () {
+		String authorsRecDef = "recordAuthors";
+		if (!Author.addAuthorBlockByDefault)
+			authorsRecDef = "dontrecordAuthorsbyDefault";
+		if (!StringUtil.blank(MesquiteModule.author.getName())) {
+			if (MesquiteModule.author.getCode() != null) 
+				return (new String[] {"&", authorsRecDef, MesquiteModule.author.getName(), MesquiteModule.author.getCode()});
+			else
+				return (new String[] {"&", authorsRecDef, MesquiteModule.author.getName()});
+		}
+		else
+			return (new String[] {"&", authorsRecDef});
+	}
+	/**/
+
+
+
+	/*.................................................................................................................*/
+	Author findAuthorIdentical(String name, String code){
+		if (code == null || name == null)
+			return null;
+		Projects p = MesquiteTrunk.getProjectList();
+		for (int i=0; i<p.getNumProjects(); i++){
+			MesquiteProject proj = p.getProject(i);
+			if (proj.numAuthors()>0){
+				ListableVector v = proj.getAuthors();
+				for (int k = 0; k< v.size(); k++){
+					Author a = (Author)v.elementAt(k);
+					if (a.getCode()!= null && a.getCode().equals(code) && a.getName()!= null && a.getName().equals(name))
+						return a;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	Author findAuthorByCode(String code){
+		if (code == null )
+			return null;
+		Projects p = MesquiteTrunk.getProjectList();
+		for (int i=0; i<p.getNumProjects(); i++){
+			MesquiteProject proj = p.getProject(i);
+			if (proj.numAuthors()>0){
+				ListableVector v = proj.getAuthors();
+				for (int k = 0; k< v.size(); k++){
+					Author a = (Author)v.elementAt(k);
+					if (a.getCode()!= null && a.getCode().equals(code))
+						return a;
+				}
+			}
+		}
+		return null;
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets the author for this account and machine", null, commandName, "setAuthor")) {
+			MesquiteBoolean answer = new MesquiteBoolean(false);
+			MesquiteString resp1 = new MesquiteString(MesquiteModule.author.getName());
+			MesquiteString resp2 = new MesquiteString(MesquiteModule.author.getCode());
+			MesquiteString.queryTwoStrings(containerOfModule(), "Set Author", "Author", "Author code (do not use a number!)", answer, resp1, resp2, false);
+			if (answer.getValue() && (!MesquiteModule.author.getName().equals(resp1.getValue()) || !MesquiteModule.author.getCode().equals(resp2.getValue()))){
+				//there's be a change
+				//first, is it a known author?
+				Author a = findAuthorIdentical(resp1.getValue(), resp2.getValue());
+				if (a == null){
+					a = findAuthorByCode(resp2.getValue());  //exists; just need to change names
+					if (a !=null){
+						a.setName(resp1.getValue());
+						Projects p = MesquiteTrunk.mesquiteTrunk.getProjectList();
+						for (int i=0; i<p.getNumProjects(); i++){
+							MesquiteProject proj = p.getProject(i);
+							ListableVector v = proj.getAuthors();
+							v.notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+						}
+						return null;
+					}
+				}
+				if (a == null){  //no, so make a new author
+					a = new Author();
+					a.setName(resp1.getValue());
+					a.setCode(resp2.getValue());
+					Projects p = MesquiteTrunk.mesquiteTrunk.getProjectList();
+					for (int i=0; i<p.getNumProjects(); i++){
+						MesquiteProject proj = p.getProject(i);
+						ListableVector v = proj.getAuthors();
+						v.addElement(a, false);
+					}
+				}
+
+				MesquiteModule.author.setCurrent(false);
+				a.setCurrent(true);
+				MesquiteModule.author = a;
+				storePreferences();
+				setCurrentAllProjects();
+				
+			}
+			return null;
+
+		}
+		else	if (checker.compare(this.getClass(), "Sets default to record authors", null, commandName, "recordAuthors")) {
+			authorBlockDefault.toggleValue(parser.getFirstToken(arguments));
+			Author.addAuthorBlockByDefault = authorBlockDefault.getValue();
+			storePreferences();
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	protected void setCurrentAllProjects(){
+		//go through all projects changing current author or adding current author
+		Projects p = MesquiteTrunk.mesquiteTrunk.getProjectList();
+		for (int i=0; i<p.getNumProjects(); i++){
+			MesquiteProject proj = p.getProject(i);
+			ListableVector v = proj.getAuthors();
+			boolean found = false;
+			for (int ia = 0; ia< v.size(); ia++){
+				Author au = (Author)v.elementAt(ia);
+				if (au.isCurrent()) {
+					au.setName(MesquiteModule.author.getName());
+					au.setCode(MesquiteModule.author.getCode());
+					found = true;
+				}
+			}
+			if (!found){
+				Author a = new Author();
+				a.setName(MesquiteModule.author.getName());
+				a.setCode(MesquiteModule.author.getCode());
+				a.setCurrent(true);
+				v.addElement(a, true);
+			}
+			v.notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Set Author";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Sets the author for this machine and account.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/basic/BasicParametersExplorer/32centre.gif b/Source/mesquite/basic/BasicParametersExplorer/32centre.gif
new file mode 100644
index 0000000..ab42958
Binary files /dev/null and b/Source/mesquite/basic/BasicParametersExplorer/32centre.gif differ
diff --git a/Source/mesquite/basic/BasicParametersExplorer/64centre.gif b/Source/mesquite/basic/BasicParametersExplorer/64centre.gif
new file mode 100644
index 0000000..76a9cdb
Binary files /dev/null and b/Source/mesquite/basic/BasicParametersExplorer/64centre.gif differ
diff --git a/Source/mesquite/basic/BasicParametersExplorer/BasicParametersExplorer.java b/Source/mesquite/basic/BasicParametersExplorer/BasicParametersExplorer.java
new file mode 100644
index 0000000..227b3c7
--- /dev/null
+++ b/Source/mesquite/basic/BasicParametersExplorer/BasicParametersExplorer.java
@@ -0,0 +1,611 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.BasicParametersExplorer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+import mesquite.lib.table.TableTool;
+
+public class BasicParametersExplorer extends ParametersExplorer  {
+	String title = null;
+	PEWindow npw;
+	ParametersExplorable explorable;
+	MesquiteParameter[] parameters;
+//	int[] constraints;
+	boolean[] selected;
+	MesquiteParameter xParameter, yParameter;
+	double[][] values;
+	int numDivisions = 10;  //SHOULD be user settable
+	boolean suspend = false;
+	boolean abort = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		setModuleWindow(npw = new PEWindow(this));
+
+		values = new double[numDivisions][numDivisions];
+
+		if (!MesquiteThread.isScripting()){
+			npw.setVisible(true);
+		}
+		
+		makeMenu("Parameters");
+		
+		addMenuItem("Manage Parameters...", makeCommand("chooseParameters", this));
+		addMenuItem("Recalculate", makeCommand("doCalcs", this));
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	boolean showDialog(){
+		if (parameters == null)
+			return false;
+		
+		ParametersDialog dlog = new ParametersDialog(containerOfModule(), "Parameters", "Parameters to be explored", parameters, selected, 2, 2, true);
+		IntegerField numField = dlog.addIntegerField("Number of divisions", numDivisions, 4);
+		dlog.completeAndShowDialog(true);
+
+		boolean ok = (dlog.query()==0);
+
+		if (ok) {
+			dlog.acceptParameters();
+			numDivisions = numField.getValue();
+		}
+
+		dlog.dispose();
+		return ok;
+	}
+	/*.................................................................................................................*/
+	public boolean setExplorable(ParametersExplorable explorable){
+		this.explorable = explorable;
+		askForParameters();
+		if (!MesquiteThread.isScripting()){
+			if (showDialog())
+				doCalcs();
+			else
+				return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** notifies this module that explorable's previous values are now invalid */
+	public void explorableChanged(ParametersExplorable explorable){
+		doCalcs();
+	}
+	/*.................................................................................................................*/
+	/** notifies this module that explorable's list of parameters is now invalid */
+	public void parameterSpecsChanged(ParametersExplorable explorable){
+		askForParameters();
+		doCalcs();
+	}
+	MesquiteParameter getParameterSelected(int which){
+		int count = 0;
+		for (int i=0; i<selected.length; i++)
+			if (selected[i]){
+				if (count == which)
+					return parameters[i];
+				count++;
+			}
+		return null;
+	}
+	int getWhichParameter(MesquiteParameter which){
+		for (int i=0; i<parameters.length; i++)
+			if (parameters[i] == which){
+
+					return i;
+			}
+		return -1;
+	}
+	
+	//TODO: needs to follow indirect constraints (a to b to c; therefore a to c)
+	MesquiteParameter[] getConstrainedTo(int which){
+		if (which > parameters.length)
+			return null;
+		MesquiteParameter target = parameters[which];
+		int count = 0;
+		for (int i = 0; i<parameters.length; i++)
+			if (parameters[i].getConstrainedTo() == target)
+				count++;
+		if (count == 0)
+			return null;
+		MesquiteParameter[] constrained = new MesquiteParameter[count];
+		count = 0;
+		for (int i = 0; i<parameters.length; i++)
+			if (parameters[i].getConstrainedTo() == target){
+				constrained[count++] = parameters[i];
+			}
+		
+		return constrained;
+	}
+	public void doCalcs(){
+		if (explorable == null || parameters == null || suspend)
+			return;
+		npw.setBlank(true);
+		if (values.length != numDivisions)
+			values = new double[numDivisions][numDivisions];
+
+		xParameter = getParameterSelected(0);
+		MesquiteParameter[] constrainedToX = getConstrainedTo(getWhichParameter(xParameter));
+		double xMin = xParameter.getMinimumSuggested();
+		double xMax = xParameter.getMaximumSuggested();
+		yParameter = getParameterSelected(1);
+		MesquiteParameter[] constrainedToY = getConstrainedTo(getWhichParameter(yParameter));
+	//TODO: not yet protected against stupid users: can ask to view two parameters but which are constrained
+		double origX = xParameter.getValue();
+		double origY = yParameter.getValue();
+		double yMin = yParameter.getMinimumSuggested();
+		double yMax = yParameter.getMaximumSuggested();
+		Double2DArray.deassignArray(values);
+		npw.setValues(values, xMin, xMax, yMin, yMax, numDivisions, xParameter, yParameter);
+		long start = System.currentTimeMillis();
+		for (int ix = 0; ix < numDivisions && !abort; ix++){
+			double x = xMin + (xMax-xMin)*ix/(numDivisions-1);
+			xParameter.setValue(x);
+			if (constrainedToX != null)
+				for (int i= 0; i< constrainedToX.length; i++)
+					constrainedToX[i].setValue(x);
+			for (int iy = 0; iy < numDivisions && !abort; iy++){
+				double y = yMin + (yMax-yMin)*iy/(numDivisions-1);
+				CommandRecord.tick("x: " + x + "; y: " + y);
+				yParameter.setValue(y);
+				if (constrainedToY != null)
+					for (int i= 0; i< constrainedToY.length; i++)
+						constrainedToY[i].setValue(y);
+				values[ix][iy] = explorable.calculate(null);
+				if (System.currentTimeMillis()-start>1000 && !abort){
+					npw.setBlank(false);
+					npw.paintPlease();
+					start = System.currentTimeMillis();
+			}
+			}
+		}
+		npw.setBlank(false);
+		xParameter.setValue(origX);
+		yParameter.setValue(origY);
+		if (constrainedToX != null)
+			for (int i= 0; i< constrainedToX.length; i++)
+				constrainedToX[i].setValue(origX);
+		if (constrainedToY != null)
+			for (int i= 0; i< constrainedToY.length; i++)
+				constrainedToY[i].setValue(origY);
+		npw.repaintPlease();
+		explorable.restoreAfterExploration();
+	}
+
+	void askForParameters(){
+		parameters = explorable.getExplorableParameters();
+		if (parameters == null)
+			return;
+		if (selected == null || selected.length != parameters.length){
+			selected = new boolean[parameters.length];
+			if (selected.length > 0)
+				selected[0] = true;
+			if (selected.length > 1)
+				selected[1] = true;
+		}
+/*		//TODO: constraints should be obtained from the explorable
+		if (constraints == null || constraints.length != parameters.length){
+			constraints = new int[parameters.length];
+			for (int i = 0; i< constraints.length; i++)
+				constraints[i] = -1;
+		}
+		*/
+	}
+	/*.................................................................................................................*/
+
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (npw !=null){
+			temp.addLine("suspend");
+			temp.addLine("getWindow");
+			temp.addLine("tell It");
+			Snapshot fromWindow = npw.getSnapshot(file);
+			temp.incorporate(fromWindow, true);
+			temp.addLine("endTell");
+			temp.addLine("showWindow");
+			temp.addLine("resume");
+		}
+		else {
+		}
+		/*if (!StringUtil.blank(npw.getJumpExplanation()))
+		   	 		temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+		 */
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Shows the dialog choosing parameters", null, commandName, "chooseParameters")) {
+			if (showDialog())
+				doCalcs();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			doCalcs();
+		}
+		else if (checker.compare(this.getClass(), "Does calculations", null, commandName, "doCalcs")) {
+			doCalcs();
+		}
+		else if (checker.compare(this.getClass(), "Zooms in", null, commandName, "zoomIn")) {
+	 		MesquiteInteger pos = new MesquiteInteger(0);
+	 		MesquiteInteger.fromString(arguments,pos); //eating up point
+  			int xPos= MesquiteInteger.fromString(arguments,pos);
+   			int yPos= MesquiteInteger.fromString(arguments,pos);
+   			
+  			recentre(xPos, yPos, 0.5);
+	}
+		else if (checker.compare(this.getClass(), "Zooms out", null, commandName, "zoomOut")) {
+	 		MesquiteInteger pos = new MesquiteInteger(0);
+	 		MesquiteInteger.fromString(arguments,pos); //eating up point
+   			int xPos= MesquiteInteger.fromString(arguments,pos);
+   			int yPos= MesquiteInteger.fromString(arguments,pos);
+  			recentre(xPos, yPos, 2);
+	}
+		else if (checker.compare(this.getClass(), "Centres", null, commandName, "centre")) {
+	 		MesquiteInteger pos = new MesquiteInteger(0);
+	 		MesquiteInteger.fromString(arguments,pos); //eating up point
+   			int xPos= MesquiteInteger.fromString(arguments,pos);
+   			int yPos= MesquiteInteger.fromString(arguments,pos);
+   			recentre(xPos, yPos, 1);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void recentre(int xPos, int yPos, double zoomFactor){
+			double touchedX =  (npw.findXValue(xPos));  //how many units to shift right (+ve) or left (-ve)
+			double maxX = xParameter.getMaximumSuggested();
+			double minX = xParameter.getMinimumSuggested();
+ 			double centreX = (maxX+minX)/2; 			
+
+  			double newMinX = touchedX -(centreX-minX)*zoomFactor;
+  			double newMaxX = touchedX +(maxX-centreX)*zoomFactor;
+  			if (newMinX< xParameter.getMinimumAllowed()){
+  	
+  				double offset = xParameter.getMinimumAllowed()-newMinX;
+  				newMinX = xParameter.getMinimumAllowed();
+  				newMaxX += offset;
+  				if (newMaxX > xParameter.getMaximumAllowed())
+  					newMaxX = xParameter.getMaximumAllowed();
+  			}
+  			else if (newMaxX > xParameter.getMaximumAllowed()){
+				double offset = newMaxX-xParameter.getMaximumAllowed();
+				newMaxX = xParameter.getMaximumAllowed();
+  				newMinX -= offset;
+  				if (newMinX< xParameter.getMinimumAllowed())
+  					newMinX = xParameter.getMinimumAllowed();
+ 			}
+ 			xParameter.setMinimumSuggested(newMinX);
+ 			xParameter.setMaximumSuggested(newMaxX);
+ 			
+			double touchedY =  npw.findYValue(yPos);  //how many units to shift right (+ve) or left (-ve)
+			double maxY = yParameter.getMaximumSuggested();
+			double minY = yParameter.getMinimumSuggested();
+ 			double centreY = (maxY+minY)/2; 			
+  						
+  			double newMinY = touchedY -(centreY-minY)*zoomFactor;
+  			double newMaxY = touchedY +(maxY-centreY)*zoomFactor;
+  			if (newMinY< yParameter.getMinimumAllowed()){
+  				double offset = yParameter.getMinimumAllowed()-newMinY;
+  				newMinY = yParameter.getMinimumAllowed();
+  				newMaxY += offset;
+  				if (newMaxY > yParameter.getMaximumAllowed())
+  					newMaxY = yParameter.getMaximumAllowed();
+  			}
+  			else if (newMaxY > yParameter.getMaximumAllowed()){
+				double offset = newMaxY-yParameter.getMaximumAllowed();
+				newMaxY = yParameter.getMaximumAllowed();
+  				newMinY -= offset;
+  				if (newMinY< yParameter.getMinimumAllowed())
+  					newMinY = yParameter.getMinimumAllowed();
+ 			}
+  			yParameter.setMinimumSuggested(newMinY);
+ 			yParameter.setMaximumSuggested(newMaxY);
+			doCalcs();
+	}
+	public void shutDown(){
+		if (!isDoomed() && npw!=null)
+			windowGoAway(npw);
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		abort = true;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		abort = true;
+		if (npw != null) {
+			npw.hide();
+			npw.dispose();
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Parameters Explorer";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a window to show values returned when parameter settings are varied";
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+/* ======================================================================== */
+class PEWindow extends MesquiteWindow {
+	FieldPanel field;
+	ChartTool zoomIn, zoomOut, centre, select;
+	public PEWindow(BasicParametersExplorer module) {
+		super(module, true);
+		centre = new ChartTool (this, "centre",  module.getPath(), "centre.gif", 8, 8, "Centre", "Centers chart", MesquiteModule.makeCommand("centre", module), null);
+		addTool(centre);
+		zoomIn = new ChartTool (this, "zoomIn",  MesquiteModule.getRootImageDirectoryPath(), "zoomIn.gif", 4, 4, "Zoom In", "Zooms in and centers chart", MesquiteModule.makeCommand("zoomIn", module), null);
+		addTool(zoomIn);
+		zoomOut = new ChartTool (this, "zoomOut",  MesquiteModule.getRootImageDirectoryPath(), "zoomOut.gif", 4, 4, "Zoom Out", "Zooms out and centers chart", MesquiteModule.makeCommand("zoomOut", module), null);
+		addTool(zoomOut);
+		setCurrentTool(centre);
+		setWindowSize(220, 260);
+		setBackground(ColorDistribution.straw);
+		field = new FieldPanel();
+		addToWindow(field);
+		field.setLocation(0, 0);
+		field.setVisible(true);
+		windowResized();
+		setExplanation("This is a parameters explorer; colors indicate likelihoods, with whiter being better likelihoods");
+		setShowExplanation(true);
+		resetTitle();
+
+	}
+	void setBlank(boolean blank){
+		field.blank = blank;
+		if (blank)
+			paintPlease();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Parameters Explorer");
+	}
+
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+		return "";
+	}
+	/*int findXPlace(int graphicX){
+		if (field == null)
+			return -1;
+		return field.findXPlace(graphicX);
+	}
+	int findYPlace(int graphicY){
+		if (field == null)
+			return -1;
+		return field.findYPlace(graphicY);
+	}
+	*/
+	double findXValue(int graphicX){
+		if (field == null)
+			return 0;
+		return field.findXValue(graphicX);
+	}
+	double findYValue(int graphicY){
+		if (field == null)
+			return 0;
+		return field.findYValue(graphicY);
+	}
+
+	void setValues(double[][] values, double xMin, double xMax, double yMin, double yMax, int numDivisions, MesquiteParameter xParam, MesquiteParameter yParam){
+
+
+		field.setValues(values, xMin,  xMax,  yMin,  yMax,  numDivisions, xParam, yParam);
+	}
+	void repaintPlease(){
+		field.repaint();
+		repaint();
+	}
+	void paintPlease(){
+		
+				Graphics g = field.getGraphics();
+				if (g != null){
+					field.paint(g);
+				g.dispose();
+				}
+			}
+
+	public void windowResized(){
+		if (field == null)
+			return;
+		field.setSize(getWidth(), getHeight());
+	}
+
+}
+
+class FieldPanel extends MesquitePanel {
+	double[][] values;
+	double xMin; double xMax; double yMin; double yMax; int numDivisions;
+	int border = 100;
+	TextRotator textRotator;
+	MesquiteParameter xParam, yParam;
+	boolean blank = false;
+	public FieldPanel (){
+		textRotator = new TextRotator();
+	}
+	void setValues(double[][] values, double xMin, double xMax, double yMin, double yMax, int numDivisions, MesquiteParameter xParam, MesquiteParameter yParam){
+		this.values = values;
+		this.xMin = xMin;
+		this.xMax = xMax;
+		this.yMin = yMin;
+		this.yMax = yMax;
+		this.xParam = xParam;
+		this.yParam = yParam;
+		this.numDivisions = numDivisions;
+	}
+	/*int findXPlace(int graphicX){
+		int w = getBounds().width-border;
+		for (int ic = 0; ic<numDivisions; ic++){
+			int pixelStartX = (ic*w)/numDivisions + border;
+			if (pixelStartX>graphicX)
+				return ic;
+		
+		}
+		return numDivisions-1;
+	}
+	int findYPlace(int graphicY){
+		int h = getBounds().height-border;
+		for (int it = 0; it<numDivisions; it++){
+			int pixelStartY = ((it+1)*h)/numDivisions - 6 + border;
+			if (pixelStartY>graphicY)
+				return it;
+		}
+		return numDivisions-1;
+	}
+	*/
+	double findXValue(int graphicX){
+		int w = getBounds().width-border;
+		for (int ic = 1; ic<numDivisions; ic++){
+			int pixelStartX = (ic*w)/numDivisions + border;
+			if (pixelStartX>graphicX)
+				return xMin + (xMax-xMin)*(ic-1)/(numDivisions-1);
+		
+		}
+		return xMax;
+	}
+	double findYValue(int graphicY){
+		int h = getBounds().height-border;
+		for (int it = 1; it<numDivisions; it++){
+			int pixelStartY = ((it)*h)/numDivisions - 6 + border;
+			if (pixelStartY>graphicY)
+				return yMin + (yMax-yMin)*(it-1)/(numDivisions-1);
+		}
+		return yMax;
+	}
+	StringInABox box = new StringInABox("", getFont(), border-16);
+	public void paint(Graphics g){
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+
+		if (values == null || blank){
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+		g.setColor(Color.black);
+		int w = getBounds().width-border;
+		int h = getBounds().height-border;
+		box.setStringAndFont(new StringBuffer(xParam.getName()), getFont());
+		box.draw(g, border-46, border-16, 0, border-10, this, false);
+				
+			//	textRotator.drawRotatedText(xParam.getName(), -1, g, this, border-12, border-16);
+		for (int ic = 0; ic<numDivisions; ic++){
+			double xValue = xMin + (xMax-xMin)*ic/(numDivisions-1);
+			int pixelStartX = (ic*w)/numDivisions + border;
+
+			textRotator.drawRotatedText(MesquiteDouble.toString(xValue), ic, g, this, pixelStartX, border-4);
+
+		}
+		box.setString(yParam.getName());
+		box.draw(g, 4,  - 20 + border);
+		
+		//g.drawString(yParam.getName(), 4,  - 6 + border);
+		for (int it = 0; it<numDivisions; it++){
+			double yValue = yMin + (yMax-yMin)*it/(numDivisions-1);
+
+			int pixelStartY = ((it+1)*h)/numDivisions - 6 + border;
+			g.drawString(MesquiteDouble.toString(yValue), 10, pixelStartY);
+		}
+
+
+		double min = Double2DArray.minimum(values, true);
+		double max = Double2DArray.maximum(values, true);
+		if (MesquiteDouble.isUnassigned(min) || MesquiteDouble.isUnassigned(max)){
+		}
+		else {
+
+			for (int ic = 0; ic<values.length; ic++)
+				for (int it = 0; it<values[ic].length; it++){
+					int pixelStartX = (ic*w)/values.length + border;
+					int pixelEndX = ((ic+1)*w)/values.length + border;
+					int pixelStartY = (it*h)/values[ic].length + border;
+					int pixelEndY = ((it+1)*h)/values[ic].length + border;
+					double v= values[ic][it];
+					Color c = null;
+					if (MesquiteDouble.isUnassigned(v))
+						c = Color.gray;
+					else if (!MesquiteDouble.isCombinable(v))
+						c = Color.pink;
+					else
+						c = MesquiteColorTable.getGreenScale(values[ic][it],  min,  max, false);
+					g.setColor(c);
+					g.fillRect(pixelStartX, pixelStartY, pixelEndX-pixelStartX, pixelEndY-pixelStartY);
+					g.setColor(Color.black);
+					g.drawString(MesquiteDouble.toStringDigitsSpecified(values[ic][it], 4), pixelStartX+2, pixelEndY-4);
+					if (MesquiteDouble.isCombinable(v) && (v-min)/(max - min) < 0.0001){
+						g.setColor(Color.blue);
+						g.drawRect(pixelStartX, pixelStartY, pixelEndX-pixelStartX-1, pixelEndY-pixelStartY-1);
+					}
+				}
+		}
+
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*...............................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			return;
+		((ChartTool)tool).pointTouched (-1, x, y, modifiers); 
+	}
+	/*_________________________________________________*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+
+	}
+	/*_________________________________________________*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			return;
+		((ChartTool)tool).pointDropped (-1, x, y, modifiers); 
+	}
+}
+
+
diff --git a/Source/mesquite/basic/BasicParametersExplorer/centre.gif b/Source/mesquite/basic/BasicParametersExplorer/centre.gif
new file mode 100644
index 0000000..9b0f707
Binary files /dev/null and b/Source/mesquite/basic/BasicParametersExplorer/centre.gif differ
diff --git a/Source/mesquite/basic/BasicStringMatcher/BasicStringMatcher.java b/Source/mesquite/basic/BasicStringMatcher/BasicStringMatcher.java
new file mode 100644
index 0000000..823fca8
--- /dev/null
+++ b/Source/mesquite/basic/BasicStringMatcher/BasicStringMatcher.java
@@ -0,0 +1,56 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.BasicStringMatcher;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class BasicStringMatcher extends StringMatcher {
+	 
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean stringsMatch(String s1, String s2) {
+		MesquiteMessage.warnProgrammer("WARNING: Within BasicStringMatcher.stringsMatch(): shouldn't be here!!!!");
+		return false;
+	}
+
+	public Class getDutyClass() {
+		return StringMatcher.class;
+	}
+
+	public String getName() {
+		return "Default String Matcher";
+	}
+
+	public String getExplanation() {
+		return "Uses the default string-matching mechanism of the module that is doing the calling.";
+	}
+
+	public boolean useDefaultMatching() {
+		return true;
+	}
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+}
diff --git a/Source/mesquite/basic/CondenseTaxonNames/CondenseTaxonNames.java b/Source/mesquite/basic/CondenseTaxonNames/CondenseTaxonNames.java
new file mode 100644
index 0000000..9c4b5dd
--- /dev/null
+++ b/Source/mesquite/basic/CondenseTaxonNames/CondenseTaxonNames.java
@@ -0,0 +1,132 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.CondenseTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CondenseTaxonNames extends TaxonNameAlterer {
+	int truncLength = 10;
+	boolean cleanToken = true;
+
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	/** A stub method for doing any necessary cleanup after taxon names have been altered.*/
+   	public void cleanupAfterAlterTaxonNames(){
+    	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Condense names",  buttonPressed);
+		queryDialog.addLabel("Condensation of taxon names", Label.CENTER);
+		SingleLineTextField truncationLengthField = queryDialog.addTextField("Maximum length:", ""+truncLength, 20);
+		Checkbox cleanTokenBox = queryDialog.addCheckBox("remove non-alphanumeric characters", cleanToken);
+		queryDialog.addLargeOrSmallTextLabel("Hint: before doing this, you may want to archive current names using Archive Taxon Names under Taxon Utilities in the Character Matrix Editor or the List of Taxa window" );
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			String s = truncationLengthField.getText();
+			truncLength = MesquiteInteger.fromString(s);
+			if (!MesquiteInteger.isCombinable(truncLength))
+				ok = false;
+			cleanToken = cleanTokenBox.getState();
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+//		String s=StringUtil.deletePunctuationAndSpaces(name);
+ 		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null && (cleanToken || name.length()>truncLength)){
+			String suffix;
+			if (cleanToken)
+				suffix= ""+(it+1);   //it+1 as zero-based
+			else
+				suffix = "."+(it+1);
+			int cutLength = truncLength-suffix.length();
+			String trunced=name;
+			if (cutLength>0  && name.length()>cutLength)
+				trunced =  name.substring(0, cutLength)+suffix;
+			if (cleanToken){
+				trunced =  StringUtil.cleanseStringOfFancyChars(trunced,true,false);
+			}
+			taxa.setTaxonName(it, trunced, false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Consenses taxon names", "[length]", commandName, "condense")) {
+	   	 		if (taxa !=null){
+	   	 			 truncLength = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Condense Taxon Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Condense taxon names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Condenses taxon names, for example for use by programs that cannot handle long names or names with punctuation.";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/CurrentTaxaPartition/CurrentTaxaPartition.java b/Source/mesquite/basic/CurrentTaxaPartition/CurrentTaxaPartition.java
new file mode 100644
index 0000000..58ab9c8
--- /dev/null
+++ b/Source/mesquite/basic/CurrentTaxaPartition/CurrentTaxaPartition.java
@@ -0,0 +1,89 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.CurrentTaxaPartition;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies the current partition of taxa. */
+public class CurrentTaxaPartition extends TaxaPartitionSource implements MesquiteListener {
+	Taxa currentTaxa = null;
+	TaxaPartition currentPartition = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		if (currentPartition!=null)
+			currentPartition.removeListener(this);
+		super.endJob();
+  	 }
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa || obj == currentPartition)
+			parametersChanged();
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		if (obj == currentTaxa || obj == currentPartition)
+			parametersChanged(notification);
+	}
+   	/** returns partition for taxa */
+   	public TaxaPartition getPartition(Taxa taxa){
+		if (currentTaxa != taxa) {
+			if (currentTaxa !=null)
+				currentTaxa.removeListener(this);
+			taxa.addListener(this);
+			currentTaxa = taxa;
+		}
+		TaxaPartition partition = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+		if (currentPartition != partition) {
+			if (currentPartition !=null)
+				currentPartition.removeListener(this);
+			partition.addListener(this);
+			currentPartition = partition;
+		}
+		return currentPartition;
+   	}
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Current taxa partition";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies the current taxa partition." ;
+   	 }
+}
+
diff --git a/Source/mesquite/basic/DeleteTaxonFootnotes/DeleteTaxonFootnotes.java b/Source/mesquite/basic/DeleteTaxonFootnotes/DeleteTaxonFootnotes.java
new file mode 100644
index 0000000..22df526
--- /dev/null
+++ b/Source/mesquite/basic/DeleteTaxonFootnotes/DeleteTaxonFootnotes.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.DeleteTaxonFootnotes;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.TaxonUtility;
+
+public class DeleteTaxonFootnotes extends TaxonUtility {
+
+
+	/* ................................................................................................................. */
+	public boolean startJob(String arguments, Object condition,boolean hiredByName) {
+		
+		return true;
+	}
+	
+	/* ................................................................................................................. */
+	public String getName() {
+		return "Delete Footnotes from Taxa";
+	}
+
+	/* ................................................................................................................. */
+	public String getExplanation() {
+		return "Deletes footnotes from taxa";
+	}
+
+	/* ................................................................................................................. */
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice() {
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isSubstantive() {
+		return false;
+	}
+	/* ................................................................................................................. */
+   	/** if returns true, then requests to remain on even after operateOnTaxa is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the taxa in the block.  Returns true if taxa altered*/
+   	public boolean operateOnTaxa(Taxa taxa){
+		for (int it = 0; it< taxa.getNumTaxa(); it++){
+			if (!taxa.anySelected() || taxa.getSelected(it))
+				taxa.setAnnotation(it, null);
+		}
+		taxa.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+		return true;
+  	}
+
+
+}
diff --git a/Source/mesquite/basic/DuplicateTaxa/DuplicateTaxa.java b/Source/mesquite/basic/DuplicateTaxa/DuplicateTaxa.java
new file mode 100644
index 0000000..2224a85
--- /dev/null
+++ b/Source/mesquite/basic/DuplicateTaxa/DuplicateTaxa.java
@@ -0,0 +1,118 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.DuplicateTaxa;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class DuplicateTaxa extends TaxonUtility {
+	
+		/*.................................................................................................................*/
+		public boolean startJob(String arguments, Object condition, boolean hiredByName){
+			return true;
+		}
+		
+		/*.................................................................................................................*/
+		/** if returns true, then requests to remain on even after operateOnTaxa is called.  Default is false*/
+		public boolean pleaseLeaveMeOn(){
+			return false;
+		}
+		/*.................................................................................................................*/
+		/** Called to operate on the taxa in the block.  Returns true if taxa altered*/
+		public  boolean operateOnTaxa(Taxa taxa){
+			int numSelected = taxa.numberSelected();
+			if (numSelected<1){
+				discreetAlert( "You need to select at least one taxon to be duplicated.");
+				return false;
+			}
+			boolean[] selected = new boolean[taxa.getNumTaxa()];
+
+			for (int it = 0; it<taxa.getNumTaxa(); it++) {
+				selected[it] = taxa.getSelected(it);
+			}
+			
+			
+			for (int it = taxa.getNumTaxa()-1; it>=0; it--) {
+				if (selected[it]) {
+					String s = taxa.getTaxonName(it);
+					boolean success = taxa.addTaxa(it, 1, true);
+					String provisional = s + " (duplicate)";
+					int num = 2;
+					while (taxa.whichTaxonNumber(provisional)>=0){
+						provisional = s + " (duplicate " + num + ")";
+						num++;
+					}
+					int itDup = it+1;
+					taxa.setTaxonName(itDup, provisional);
+					
+					int numMatrices = getProject().getNumberCharMatrices(taxa);
+					for (int iM = 0; iM < numMatrices; iM++){
+						CharacterData data = getProject().getCharacterMatrix(taxa, iM);
+						CharacterState cs2 = null;
+						data.incrementSuppressHistoryStamp();
+						for (int ic = 0; ic<data.getNumChars(); ic++){
+								cs2 = data.getCharacterState(cs2, ic, it);
+								if (cs2 !=null) 
+									data.setState(ic, itDup, cs2);
+						}
+						data.decrementSuppressHistoryStamp();
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					}
+				}
+			}
+			return true;
+		}
+		/*.................................................................................................................*/
+		public String getName() {
+			return "Duplicate Taxa";
+		}
+		/*.................................................................................................................*/
+		public String getNameForMenuItem() {
+			return "Duplicate Taxa";
+		}
+
+		/*.................................................................................................................*/
+		public String getExplanation() {
+			return "Duplicates selected taxa and their character states.";
+		}
+		/*.................................................................................................................*/
+		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+		public int getVersionOfFirstRelease(){
+			return 300;  
+		}
+		/*.................................................................................................................*/
+		public boolean isPrerelease(){
+			return false;
+		}
+
+	}
+
+
+
+
+
+
+
+
+
diff --git a/Source/mesquite/basic/ExamplesNavigator/ExamplesNavigator.java b/Source/mesquite/basic/ExamplesNavigator/ExamplesNavigator.java
new file mode 100644
index 0000000..0961a4d
--- /dev/null
+++ b/Source/mesquite/basic/ExamplesNavigator/ExamplesNavigator.java
@@ -0,0 +1,742 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.ExamplesNavigator;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+
+public class ExamplesNavigator extends FileAssistantN  {
+	String nextProjectName = null;
+	String prevProjectName = null;
+	String title = null;
+	ExamplesNavigatorWindow npw;
+	MesquiteFile file = null;
+	//Color bgColor;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		setModuleWindow( npw = new ExamplesNavigatorWindow(this));
+		//npw.setMinimalMenus(true);
+		if (!MesquiteThread.isScripting()){
+			getModuleWindow().setVisible(true);
+		}
+		makeMenu("Navigator");
+
+		if (MesquiteThread.isScripting() && CommandRecord.getScriptingFileS()!=null) {
+			file = CommandRecord.getScriptingFileS();
+			file.addListener(this);
+		}
+		/*
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Background Color", makeCommand("setBackground",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		 */
+		addCheckMenuItem(null, "Show filenames", makeCommand("toggleFileNames", this), npw.showFileNames);
+		addMenuItem("Add File Link", makeCommand("addFileLink", npw));
+		addMenuItem("Add Web Link", makeCommand("addWebLink", npw));
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (file == obj)
+			windowGoAway(npw);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (npw !=null){
+			if (!StringUtil.blank(npw.getNextText()))
+				temp.addLine("setNextFileName " + StringUtil.tokenize(npw.getNextText()));
+			if (!StringUtil.blank(npw.getPrevText()))
+				temp.addLine("setPrevFileName " + StringUtil.tokenize(npw.getPrevText()));
+			/*
+			if (!StringUtil.blank(npw.getJumpExplanation()))
+			   	 		temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+			if (!StringUtil.blank(npw.getExampleTitle()))
+			   	 		temp.addLine("setTitle " + StringUtil.tokenize(npw.getExampleTitle()));
+			temp.addLine("toggleFileNames " + showFileNames.toOffOnString());
+			 */
+			temp.addLine("getWindow");
+			temp.addLine("tell It");
+			Snapshot fromWindow = npw.getSnapshot(file);
+			temp.incorporate(fromWindow, true);
+			temp.addLine("endTell");
+			temp.addLine("showWindow");
+		}
+		else {
+			if (!StringUtil.blank(nextProjectName))
+				temp.addLine("setNextFileName " + StringUtil.tokenize(nextProjectName));
+		}
+		/*if (!StringUtil.blank(npw.getJumpExplanation()))
+		   	 		temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+		 */
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the file name to which to jump when the Next button is hit", "[path to file; if relative than to home file of project]", commandName, "setNextFileName")) {
+			if (npw == null)
+				return null;
+			nextProjectName =parser.getFirstToken(arguments);
+			npw.setNextText(nextProjectName);
+		}
+		else if (checker.compare(this.getClass(), "Sets the file name to which to jump when the Prev button is hit", "[path to file; if relative than to home file of project]", commandName, "setPrevFileName")) {
+			if (npw == null)
+				return null;
+			prevProjectName =parser.getFirstToken(arguments);
+			npw.setPrevText(prevProjectName);
+		}
+		else if (checker.compare(this.getClass(), "Sets the title", "[title]", commandName, "setTitle")) {
+			if (npw == null)
+				return null;
+			title =parser.getFirstToken(arguments);
+			npw.setExampleTitle(title);
+		}
+		else if (checker.compare(this.getClass(), "Sets explanation to appear in text edit area", "[explanation string]", commandName, "setExplanation")) {
+			if (npw == null)
+				return null;
+			npw.setJumpExplanation(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show file names", "[on or off]", commandName, "toggleFileNames")) {
+			boolean current = npw.showFileNames.getValue();
+			npw.showFileNames.toggleValue(parser.getFirstToken(arguments));
+			if (current!=npw.showFileNames.getValue() && npw != null) {
+				npw.showFileNames(npw.showFileNames.getValue());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Jumps to next project recorded", null, commandName, "next")) {
+			if (npw == null)
+				return null;
+			nextProjectName = npw.getNextText();
+			if (StringUtil.blank(nextProjectName))
+				return null;
+			while (getProject().developing)
+				;
+			String openCommand = "openFile ";
+			if (StringUtil.startsWithIgnoreCase(nextProjectName,"http") || !getProject().getHomeFile().isLocal())
+				openCommand = "openURL ";
+			String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; " + openCommand;
+			commands +=  StringUtil.tokenize(MesquiteFile.composePath(getProject().getHomeDirectoryName(), nextProjectName)) + "; ifNotExists It;  showAbout; endIf; windowAutoShow *String.was; endTell;";
+			Puppeteer p = new Puppeteer(this);
+			MesquiteInteger pos = new MesquiteInteger(0);
+			p.execute(getFileCoordinator(), commands, pos, "", false);
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Jumps to previous project recorded", null, commandName, "prev")) {
+			if (npw == null)
+				return null;
+			prevProjectName = npw.getPrevText();
+			if (StringUtil.blank(prevProjectName))
+				return null;
+			while (getProject().developing)
+				;
+
+
+			String openCommand = "openFile ";
+			if (StringUtil.startsWithIgnoreCase(prevProjectName,"http") || !getProject().getHomeFile().isLocal())
+				openCommand = "openURL ";
+
+			String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; " + openCommand;
+			commands +=  StringUtil.tokenize(MesquiteFile.composePath(getProject().getHomeDirectoryName(), prevProjectName)) + "; ifNotExists It;  showAbout; endIf; windowAutoShow *String.was; endTell;";
+			Puppeteer p = new Puppeteer(this);
+			MesquiteInteger pos = new MesquiteInteger(0);
+			p.execute(getFileCoordinator(), commands, pos, "", false);
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Jumps to project", null, commandName, "fileLink")) {
+			if (npw == null)
+				return null;
+			String path = parser.getFirstToken(arguments);
+			if (StringUtil.blank(path))
+				return null;
+			while (getProject().developing)
+				;
+			String openCommand = "openFile ";
+			if (StringUtil.startsWithIgnoreCase(path,"http") || !getProject().getHomeFile().isLocal())
+				openCommand = "openURL ";
+			String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; " + openCommand;
+			commands +=  StringUtil.tokenize(MesquiteFile.composePath(getProject().getHomeDirectoryName(), path)) + "; ifNotExists It;  showAbout; endIf; windowAutoShow *String.was; endTell;";
+			Puppeteer p = new Puppeteer(this);
+			MesquiteInteger pos = new MesquiteInteger(0);
+			p.execute(getFileCoordinator(), commands, pos, "", false);
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Requests web page", null, commandName, "showPage")) {
+			String targetName = parser.getFirstToken(arguments);
+			if (StringUtil.blank(targetName))
+				return null;
+			String path = null;
+			if (StringUtil.startsWithIgnoreCase(targetName,"mesquite:")) {
+				path = mesquiteDirectoryPath + targetName.substring(9, targetName.length());
+			}
+			else if (StringUtil.startsWithIgnoreCase(targetName,"project:")) {
+				path = getProject().getHomeDirectoryName() + targetName.substring(8, targetName.length());
+			}
+			else
+				path = targetName;
+			showWebPage(path, false);
+		}
+		/*else if (checker.compare(this.getClass(), "Sets background color of window", "[name of color]", commandName, "setBackground")) {
+    	 		Color bc = ColorDistribution.getStandardColor(parser.getFirstToken(arguments));
+			if (bc == null)
+				return null;
+			bgColor = bc;
+			if (npw == null)
+				return null;
+			//npw.setColor(bc);
+			if (npw.isVisible())
+				npw.repaint();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "NOT USED", null, commandName, "makeWindow")) {
+    	 	} */
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void shutDown(){
+		if (!isDoomed() && npw!=null)
+			windowGoAway(npw);
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (npw != null) {
+			npw.hide();
+			npw.dispose();
+		}
+		if (file !=null)
+			file.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Examples Navigator";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a Examples Navigator window with explanation and buttons to link to other files";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "New Examples Navigator";
+	}
+	public boolean isSubstantive(){
+		return false;
+	}
+
+}
+
+/* ======================================================================== */
+class ExamplesNavigatorWindow extends MesquiteWindow implements TextListener {
+	//TextField nextText;
+	//TextField prevText;
+	//TextField titleText;
+	String nextName = "Next";
+	String prevName = "Previous";
+	MesquiteBoolean showFileNames;
+	Parser parser = new Parser();
+	Panel contents, controls, textFields;
+	FieldPanel nextPanel, prevPanel, titlePanel;
+	TitlePanel buttons;
+	Panel extras;
+
+	//TextField prevLabel;
+	//TextField nextLabel;
+	Button prev, next;
+	TextArea explanation;
+	public ExamplesNavigatorWindow(ExamplesNavigator module) {
+		super(module, true);
+		setWindowSize(220, 260);
+		setBackground(ColorDistribution.lightGreen);
+		contents = getGraphicsArea();
+		contents.setLayout(new BorderLayout());
+
+		explanation= new TextArea("", 12, 12, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		contents.add("Center", explanation);
+		explanation.setBackground(Color.white);
+		controls = new Panel();
+		buttons = new TitlePanel(this);
+		controls.setLayout(new BorderLayout());
+		controls.setBackground(ColorDistribution.lightGreen);
+		buttons.setLayout(new BorderLayout());
+		controls.add("North", buttons);
+		buttons.add("West", prev = new WindowButton(prevName, this));
+		buttons.add("East", next = new WindowButton(nextName, this));
+		prev.setBackground(ColorDistribution.lightGreen);
+		next.setBackground(ColorDistribution.lightGreen);
+		Font df = new Font("Dialog", Font.PLAIN, 12);
+		next.setFont(df);
+		prev.setFont(df);
+
+		textFields = new Panel();
+
+		nextPanel = new FieldPanel(true, nextName, module.nextProjectName, this, null, false);
+		nextPanel.setVisible(true);
+
+		prevPanel = new FieldPanel(true, prevName, module.prevProjectName, this, null, false);
+		prevPanel.setVisible(true);
+
+		titlePanel = new FieldPanel(false, "Title", module.title, this, null, false);
+		titlePanel.setVisible(true);
+
+		textFields.setLayout(new BorderLayout());
+		textFields.add("North", titlePanel);
+		textFields.add("Center", nextPanel);
+		textFields.add("South", prevPanel);
+		controls.add("Center", textFields);
+
+		extras = new Panel();
+		extras.setLayout(extrasLayout = new GridLayout(0, 1));
+		extras.setVisible(true);
+
+		contents.add("North", controls);
+		contents.add("South", extras);
+		textValueChanged(null);
+		setWindowSize(220, 260);
+		showFileNames = new MesquiteBoolean(true);
+		showFileNames(showFileNames.getValue());
+		next.setVisible(!StringUtil.blank(nextPanel.getText()));
+		prev.setVisible(!StringUtil.blank(prevPanel.getText()));
+		resetTitle();
+
+	}
+	/*.................................................................................................................*/
+	public void setWindowFont(Font fontToSet) {
+		super.setWindowFont(fontToSet);
+		if (explanation != null && titlePanel != null && nextPanel != null && prevPanel != null){
+			explanation.setFont(fontToSet);
+			titlePanel.setFont(fontToSet);
+			nextPanel.setFont(fontToSet);
+			prevPanel.setFont(fontToSet);
+		}
+	}
+	public boolean showInfoTabs(){
+		return false;
+	}
+	public boolean permitViewMode(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Examples Navigator");
+	}
+	public void windowResized(){
+		if (contents != null){
+			explanation.setSize(getWidth(), getHeight());
+			contents.setSize(getWidth(), getHeight());
+			contents.invalidate();
+			contents.validate();
+		}
+		super.windowResized();
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+		return explanation.getText();
+	}
+	/*.................................................................................................................*/
+	/** Gets the minimum height of the content area of the window */
+	public int getMinimumContentHeight(){
+		return 100;
+	}
+	void setExampleTitle(String title){
+		buttons.setTitle(title);
+		titlePanel.setText(title);
+	}
+	String getExampleTitle(){
+		return buttons.title;
+	}
+
+	public void textValueChanged(TextEvent e){
+		next.setVisible(!StringUtil.blank(nextPanel.getText()));
+		prev.setVisible(!StringUtil.blank(prevPanel.getText()));
+		prev.setLabel(prevPanel.getLabel());
+		next.setLabel(nextPanel.getLabel());
+		nextName = nextPanel.getLabel();
+		prevName = prevPanel.getLabel();
+		buttons.invalidate();
+		buttons.validate();
+		contents.invalidate();
+		contents.validate();
+		buttons.setTitle(titlePanel.getText());
+		buttons.repaint();
+	}
+
+	private void setPrevButtonName(String s){
+		prev.setLabel(s);
+		prevPanel.setLabel(s);
+		prevName = s;
+	}
+	private void setNextButtonName(String s){
+		next.setLabel(s);
+		nextPanel.setLabel(s);
+		nextName = s;
+	}
+	void toggleShowFileNames(){
+		showFileNames.toggleValue(null);
+		showFileNames(showFileNames.getValue());
+	}
+	public void showFileNames(boolean show){
+		nextPanel.setVisible(show);
+		prevPanel.setVisible(show);
+		titlePanel.setVisible(show);
+		textFields.setVisible(show);
+		controls.invalidate();
+		controls.validate();
+		contents.invalidate();
+		contents.validate();
+	}
+	public void setNextText(String s) {
+		if (nextPanel == null)
+			return;
+
+		nextPanel.setText(s);
+		textValueChanged(null);
+		nextPanel.repaint();
+	}
+	public void setPrevText(String s) {
+		if (prevPanel == null)
+			return;
+		prevPanel.setText(s);
+		textValueChanged(null);
+		prevPanel.repaint();
+	}
+	public String getNextText() {
+		if (nextPanel == null)
+			return null;
+		return nextPanel.getText();
+	}
+	public String getPrevText() {
+		if (prevPanel == null)
+			return null;
+		return prevPanel.getText();
+	}
+	public void setJumpExplanation(String s) {
+		if (explanation == null)
+			return;
+		explanation.setText(s);
+		explanation.repaint();
+		repaint();
+	}
+	public String getJumpExplanation() {
+		if (explanation == null)
+			return null;
+		return explanation.getText();
+	}
+	public void go(String path, boolean fileLink) {
+		if (fileLink)
+			getOwnerModule().doCommand("fileLink", StringUtil.tokenize(path), CommandChecker.defaultChecker);
+		else
+			getOwnerModule().doCommand("showPage", StringUtil.tokenize(path),  CommandChecker.defaultChecker);
+	}
+	Vector links = new Vector();
+	GridLayout extrasLayout;
+	boolean editorsVisible = false;
+	void toggleShowExtrasEditors(){
+		editorsVisible = !editorsVisible;
+		for (int i=0; i<links.size(); i++){
+			LinkPanel link = (LinkPanel)links.elementAt(i);
+			link.pathField.setVisible(editorsVisible);
+			link.pathField.invalidate();
+			link.pathField.validate();
+			link.titleField.setVisible(editorsVisible);
+			link.titleField.invalidate();
+			link.titleField.validate();
+			link.invalidate();
+			link.validate();
+		}
+		extras.invalidate();
+		extras.validate();
+		contents.invalidate();
+		contents.validate();
+	}
+	void addLink(LinkPanel link){
+		links.addElement(link);
+		link.setVisible(true);
+		link.pathField.setVisible(editorsVisible);
+		link.titleField.setVisible(editorsVisible);
+		extrasLayout.setRows(extrasLayout.getRows()+1);
+		extras.add(link);
+		extras.invalidate();
+		extras.validate();
+		contents.invalidate();
+		contents.validate();
+	}
+	void removeLink(LinkPanel link){
+		links.removeElement(link);
+		link.setVisible(false);
+		extrasLayout.setRows(extrasLayout.getRows()-1);
+		extras.remove(link);
+		extras.invalidate();
+		extras.validate();
+		contents.invalidate();
+		contents.validate();
+	}
+	/*=============*/
+	public void buttonHit(String label, Button button) {
+		if (getOwnerModule()==null)
+			return;
+		if (label.equalsIgnoreCase(nextName)) {
+			getOwnerModule().doCommand("Next", null,  CommandChecker.defaultChecker);
+		}
+		else if (label.equalsIgnoreCase(prevName)) {
+			getOwnerModule().doCommand("Prev", null,  CommandChecker.defaultChecker);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		Snapshot fromWindow = super.getSnapshot(file);
+		temp.incorporate(fromWindow, true);
+		if (!StringUtil.blank(getJumpExplanation()))
+			temp.addLine("setExplanation " + StringUtil.tokenize(getJumpExplanation()));
+		if (!StringUtil.blank(getExampleTitle()))
+			temp.addLine("setTitle " + StringUtil.tokenize(getExampleTitle()));
+		temp.addLine("toggleFileNames " + showFileNames.toOffOnString());
+		if (!StringUtil.blank(prevPanel.getLabel()))
+			temp.addLine("setPrevButtonName " + StringUtil.tokenize(prevPanel.getLabel()));
+		else
+			temp.addLine("setPrevButtonName Previous");
+		if (!StringUtil.blank(nextPanel.getLabel()))
+			temp.addLine("setNextButtonName " + StringUtil.tokenize(nextPanel.getLabel()));
+		else
+			temp.addLine("setNextButtonName Next");
+		if (editorsVisible)
+			temp.addLine("setEditorsVisible");
+		for (int i=0; i<links.size(); i++){
+			LinkPanel link = (LinkPanel)links.elementAt(i);
+			if (link.fileLink)
+				temp.addLine("addFileLink " + StringUtil.tokenize(link.getTitle()) + "  " + StringUtil.tokenize(link.getPath()));
+			else
+				temp.addLine("addWebLink " + StringUtil.tokenize(link.getTitle()) + "  " + StringUtil.tokenize(link.getPath()));
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the title", "[title]", commandName, "setTitle")) {
+			setExampleTitle(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets editors to be visible", null, commandName, "setEditorsVisible")) {
+			editorsVisible = true;
+		}
+		else if (checker.compare(this.getClass(), "Sets explanation to appear in text edit area", "[explanation string]", commandName, "setExplanation")) {
+			setJumpExplanation(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets name of button that is by default 'Previous'", "[name of button]", commandName, "setPrevButtonName")) {
+			setPrevButtonName(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets name of button that is by default 'Next'", "[name of button]", commandName, "setNextButtonName")) {
+			setNextButtonName(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Adds a link to a web page", "[Title][path]", commandName, "addWebLink")) {
+			String t = parser.getFirstToken(arguments);
+			addLink(new LinkPanel("Show page", t, "URL",  parser.getNextToken(), this, false));
+		}
+		else if (checker.compare(this.getClass(), "Adds a link to a file", "[Title][path]", commandName, "addFileLink")) {
+			String t = parser.getFirstToken(arguments);
+			addLink(new LinkPanel("Go", t, "Path to file",  parser.getNextToken(), this, true));
+		}
+
+		else if (checker.compare(this.getClass(), "Sets whether or not to show file names", "[on or off]", commandName, "toggleFileNames")) {
+			boolean current = showFileNames.getValue();
+			showFileNames.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showFileNames.getValue()) {
+				showFileNames(showFileNames.getValue());
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+}
+
+class FieldPanel extends Panel implements ActionListener {
+	TextField label, text; 
+	LinkPanel linkPanel;
+	public FieldPanel (boolean labelEditable, String initialLabel, String initialText, TextListener listener, LinkPanel linkPanel, boolean removeButton){
+		setLayout(new BorderLayout());
+		this.linkPanel = linkPanel;
+		setBackground(Color.white);
+		label= new TextField(9);
+		label.setEditable(false);
+		if (!StringUtil.blank(initialLabel))
+			label.setText(initialLabel);
+		label.setEditable(labelEditable);
+		if (labelEditable && listener !=null)
+			label.addTextListener(listener);
+		text= new TextField(400);
+		if (!StringUtil.blank(initialText))
+			text.setText(initialText);
+		text.setEditable(true);
+		text.setBackground(Color.white);
+		if (listener !=null)
+			text.addTextListener(listener);
+		add("West", label);
+		add("Center", text);
+		if (removeButton){
+			Button q =new Button("Remove");
+			q.addActionListener(this);
+			add("East", q);
+		}
+		text.setVisible(true);
+	}
+	public void setText(String s){
+		text.setText(s);
+	}
+	public String getText(){
+		return text.getText();
+	}
+	public String getLabel(){
+		return label.getText();
+	}
+	public void setLabel(String s){
+		label.setText(s);
+	}
+	public void actionPerformed(ActionEvent e){
+		linkPanel.remove();
+	}
+
+}
+
+
+class LinkPanel extends Panel implements ActionListener, TextListener {
+	String title;
+	String path;
+	LinkBanner banner;
+	Button b;
+	boolean fileLink;
+	FieldPanel titleField, pathField;
+	ExamplesNavigatorWindow window;
+	public LinkPanel(String buttonLabel, String initTitle, String pathLabel, String initPath, ExamplesNavigatorWindow window, boolean fileLink){
+		super();
+		this.window = window;
+		this.fileLink = fileLink;
+		setLayout(new BorderLayout());
+		title = initTitle;
+		path = initPath;
+		titleField = new FieldPanel(false, "Title", initTitle, this, this, true);
+		titleField.setVisible(false);
+		pathField = new FieldPanel(false, pathLabel, initPath, this, this, false);
+		pathField.setVisible(false);
+
+		banner = new LinkBanner(this);
+		if (fileLink)
+			banner.setBackground(ColorDistribution.veryLightGreen);
+		else
+			banner.setBackground(Color.cyan);
+
+		b = new Button(buttonLabel);
+		banner.add("West", b);
+		b.addActionListener(this);
+
+		add("North", banner);
+		add("Center", titleField);
+		add("South", pathField);
+
+	}
+	public void actionPerformed(ActionEvent e){
+		window.go(path, fileLink);
+	}
+	void remove(){
+		window.removeLink(this);
+	}
+	public void textValueChanged(TextEvent e){
+		title = titleField.getText();
+		path = pathField.getText();
+		banner.repaint();
+	}
+	public void setTitle(String title){
+		this.title = title;
+	}
+	public String getTitle(){
+		return title;
+	}
+	public void setPath(String path){
+		this.path = path;
+	}
+	public String getPath(){
+		return path;
+	}
+	public void toggleShowEditor(){
+		window.toggleShowExtrasEditors();
+	}
+
+}
+
+class LinkBanner extends MousePanel {
+	LinkPanel parent;
+	public LinkBanner(LinkPanel parent){
+		super();
+		setLayout(new BorderLayout());
+		this.parent = parent;
+		setFont(new Font ("SanSerif", Font.PLAIN, 14));
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteEvent.commandOrControlKeyDown(modifiers))
+			parent.toggleShowEditor();
+	}
+	public void paint (Graphics g){
+		if (parent.getTitle()!=null)
+			g.drawString(parent.getTitle(), StringUtil.getStringCenterPosition(parent.getTitle(), g, 0, getBounds().width, null), getBounds().height - 8);
+	}
+}
+
+class TitlePanel extends MousePanel {
+	String title;
+	ExamplesNavigatorWindow window;
+	public TitlePanel(ExamplesNavigatorWindow window){
+		this.window = window;
+		setFont(new Font ("SanSerif", Font.PLAIN, 14));
+	}
+	void setTitle(String title){
+		this.title = title;
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteEvent.commandOrControlKeyDown(modifiers))
+			window.toggleShowFileNames();
+	}
+	public void paint (Graphics g){
+		if (title!=null)
+			g.drawString(title, StringUtil.getStringCenterPosition(title, g, 0, getBounds().width, null), getBounds().height - 8);
+	}
+}
+/*
+class FileELink extends FileElement{
+	ExamplesNavigator ownerModule;
+	public FileELink(ExamplesNavigator ownerModule){
+		this.ownerModule = ownerModule;
+	}
+	public void dispose(){
+		ownerModule.shutDown();
+		super.dispose();
+	}
+}
+ */
diff --git a/Source/mesquite/basic/GoToWebPage/GoToWebPage.java b/Source/mesquite/basic/GoToWebPage/GoToWebPage.java
new file mode 100644
index 0000000..d764641
--- /dev/null
+++ b/Source/mesquite/basic/GoToWebPage/GoToWebPage.java
@@ -0,0 +1,228 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.GoToWebPage;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+
+public class GoToWebPage extends FileAssistant {
+	public String targetName = null;
+
+	GoToWebPageWindow npw;
+
+	Color bgColor;
+
+	/*
+	 * public Class getDutyClass(){ return GoToWebPage.class; } /*.................................................................................................................
+	 */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setModuleWindow(npw = new GoToWebPageWindow(this));
+		npw.setMinimalMenus(true);
+		if (!MesquiteThread.isScripting()) {
+			getModuleWindow().setVisible(true);
+		}
+		makeMenu("Web_Page_Link");
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Background Color", makeCommand("setBackground", this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (npw != null) {
+			if (!StringUtil.blank(npw.getText()))
+				temp.addLine("setPagePath " + StringUtil.tokenize(npw.getText()));
+			if (!StringUtil.blank(npw.getJumpExplanation()))
+				temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+			// temp.addLine("makeWindow");
+			temp.addLine("getWindow");
+			temp.addLine("tell It");
+			Snapshot fromWindow = npw.getSnapshot(file);
+			temp.incorporate(fromWindow, true);
+			temp.addLine("endTell");
+			if (bgColor != null) {
+				String bName = ColorDistribution.getStandardColorName(bgColor);
+				if (bName != null)
+					temp.addLine("setBackground " + StringUtil.tokenize(bName));
+			}
+
+			temp.addLine("showWindow");
+		}
+		else {
+			if (!StringUtil.blank(targetName))
+				temp.addLine("setPagePath " + StringUtil.tokenize(targetName));
+		}
+		if (!StringUtil.blank(npw.getJumpExplanation()))
+			temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+		return temp;
+	}
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the URL of the web page to be opened when the button is hit", "[path to web page; if no http:// then relative to Mesquite]", commandName, "setPagePath")) {
+			targetName = parser.getFirstToken(arguments);
+			((GoToWebPageWindow) getModuleWindow()).setText(targetName);
+		}
+		else if (checker.compare(this.getClass(), "Sets explanation to appear in text edit area", "[explanation string]", commandName, "setExplanation")) {
+			((GoToWebPageWindow) getModuleWindow()).setJumpExplanation(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Requests web page recorded in window", null, commandName, "show")) {
+			targetName = ((GoToWebPageWindow) getModuleWindow()).getText();
+			if (StringUtil.blank(targetName))
+				return null;
+			String path = null;
+			if (targetName.startsWith("mesquite:")) {
+				path = mesquiteDirectoryPath + targetName.substring(9, targetName.length());
+			}
+			else if (targetName.startsWith("project:")) {
+				path = getProject().getHomeDirectoryName() + targetName.substring(8, targetName.length());
+			}
+			else
+				path = targetName;
+			showWebPage(path, false);
+
+		}
+		else if (checker.compare(this.getClass(), "Sets background color of window", "[name of color]", commandName, "setBackground")) {
+			Color bc = ColorDistribution.getStandardColor(parser.getFirstToken(arguments));
+			if (bc == null)
+				return null;
+			bgColor = bc;
+			npw.setColor(bc);
+			npw.repaint();
+		}
+		else if (checker.compare(this.getClass(), "NOT USED", null, commandName, "makeWindow")) {
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+
+	/* ................................................................................................................. */
+	public String getName() {
+		return "Web page link";
+	}
+
+	/* ................................................................................................................. */
+	public String getExplanation() {
+		return "Provides a window to jump to a web page";
+	}
+
+	public boolean isSubstantive() {
+		return false;
+	}
+
+}
+
+/* ======================================================================== */
+class GoToWebPageWindow extends MesquiteWindow {
+	TextField tF;
+
+	TextArea explanation;
+
+	public GoToWebPageWindow(GoToWebPage module) {
+		super(module, false);
+		setBackground(Color.cyan);
+		Panel contents = getGraphicsArea();
+		contents.setLayout(new BorderLayout());
+		contents.setBackground(Color.cyan);
+
+		explanation = new TextArea("", 8, 3, TextArea.SCROLLBARS_NONE);
+		tF = new TextField();
+		if (!StringUtil.blank(module.targetName))
+			tF.setText(module.targetName);
+		tF.setEditable(true);
+		tF.setBackground(Color.cyan);
+		tF.setVisible(true);
+		contents.add("North", tF);
+		contents.add("Center", explanation);
+		Panel buttons = new Panel();
+		Font f = explanation.getFont();
+		if (f != null) {
+			Font fontToSet = new Font(f.getName(), f.getStyle(), f.getSize() + 4);
+			if (fontToSet != null) {
+				explanation.setFont(fontToSet);
+			}
+		}
+		contents.add("South", buttons);
+		Button ok = null;
+		buttons.add("South", ok = new WindowButton("Show", this));
+		Font df = new Font("Dialog", Font.PLAIN, 12);
+		ok.setFont(df);
+
+		setWindowSize(120, 60);
+		resetTitle();
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * When called the window will determine its own title. MesquiteWindows need to be self-titling so that when things change (names of files, tree lists, etc.) they can reset their titles properly
+	 */
+	public void resetTitle() {
+		setTitle("Web page link");
+	}
+
+	public void setColor(Color c) {
+		setBackground(c);
+		tF.setBackground(c);
+		Panel contents = getGraphicsArea();
+		contents.setBackground(c);
+		repaintAll();
+	}
+
+	public void setText(String s) {
+		tF.setText(s);
+		tF.repaint();
+		repaint();
+	}
+
+	public String getText() {
+		return tF.getText();
+	}
+
+	public void setJumpExplanation(String s) {
+		explanation.setText(s);
+		explanation.repaint();
+		repaint();
+	}
+
+	public String getJumpExplanation() {
+		return explanation.getText();
+	}
+
+	/* ============= */
+	public void buttonHit(String label, Button button) {
+		if (label.equalsIgnoreCase("Show")) {
+			getOwnerModule().doCommand("show", null, CommandChecker.defaultChecker);
+		}
+	}
+}
+
diff --git a/Source/mesquite/basic/ManageArchivedTaxonNames/ManageArchivedTaxonNames.java b/Source/mesquite/basic/ManageArchivedTaxonNames/ManageArchivedTaxonNames.java
new file mode 100644
index 0000000..cab8b74
--- /dev/null
+++ b/Source/mesquite/basic/ManageArchivedTaxonNames/ManageArchivedTaxonNames.java
@@ -0,0 +1,302 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.ManageArchivedTaxonNames;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class ManageArchivedTaxonNames extends SpecsSetManager {
+	final static String listOfAlternativeNameSetsName = "List of Alternative Name Sets";
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu,listOfAlternativeNameSetsName, makeCommand("showAlternativeNamesList",  this), (ListableVector)getProject().taxas);
+		mmis.setOwnerModuleID(getID());
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals(listOfAlternativeNameSetsName)) {
+				Object o = e.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+
+				if (o !=null && o instanceof Taxa) {
+					//int wh =getProject().getTaxaReference((Taxa)o);
+					temp.addLine("showAlternativeNamesList " + getProject().getTaxaReferenceExternal((Taxa)o), e); 
+				}
+				else
+					temp.addLine("showAlternativeNamesList ", e); 
+			}
+		}
+		return temp;
+	}
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		/* this is for old files that used the SUPPLEMENTAL storage of a single archive.  Converted to SpecsSet as per 2. 0 */
+		NameReference anr = NameReference.getNameReference("ArchivedTaxonNames");
+		ListableVector taxas = getProject().getTaxas();
+		for (int i = 0; i< taxas.size(); i++){
+			Taxa taxa = (Taxa)taxas.elementAt(i);
+			TaxaStringsSet part = null;
+			boolean changed = false;
+			taxa.prepareSpecsSetVector(TaxaStringsSet.class, "Alternative Names");
+			for (int it = 0; it< taxa.getNumTaxa(); it++){
+				Object n = taxa.getAssociatedObject(anr, it);
+				if (part == null && n != null){
+						part= new TaxaStringsSet("Alternative Naming from Archived", taxa.getNumTaxa(), taxa);
+						part.setTypeName("Alternative Names");
+						part.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+						taxa.setCurrentSpecsSet(part, TaxaStringsSet.class);
+						changed = true;
+				}
+				if (n != null)
+					taxa.setAssociatedObject(anr, it, null);
+				if (part != null)
+					part.setProperty(n, it);
+			}
+			if (changed)
+				taxa.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+		}
+
+	}
+
+
+
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return TaxaStringsSet.class;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows lists of the alternative name sets", null, commandName, "showAlternativeNamesList")) {
+			if (StringUtil.blank(arguments)) {
+				for (int i = 0; i< getProject().getNumberTaxas(checker.getFile()); i++) {
+					showSpecsSets(getProject().getTaxa(checker.getFile(), i), listOfAlternativeNameSetsName);
+				}
+			}
+			else {
+				Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+				if (t!=null ) {
+					return showSpecsSets(t, listOfAlternativeNameSetsName);
+				}
+			}
+//			alert("Sorry, there are no taxa partitions");
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	String nexusStringForSpecsSet(TaxaStringsSet taxaSet, Taxa taxa, MesquiteFile file, boolean isCurrent){
+		String s= "";
+		boolean found = false;
+		if (taxaSet!=null && (taxaSet.getFile()==file || (taxaSet.getFile()==null && taxa.getFile()==file))) {
+			String sT = "";
+			for (int ic=0; ic<taxa.getNumTaxa(); ic++) {
+				if (StringUtil.blank((String)taxaSet.getProperty(ic))) 
+					sT += " _";
+				else {
+					sT += " " + StringUtil.tokenize((String)taxaSet.getProperty(ic));
+					found = true;
+				}
+			}
+			if (found) {
+				s+= "\tALTTAXNAMES " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(taxaSet.getName()) + " ";
+				if (file.getProject().getNumberTaxas()>1)
+					s+= " (TAXA = " +  StringUtil.tokenize(taxa.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			String s= "";
+			for (int ids = 0; ids<file.getProject().getNumberTaxas(); ids++) {
+
+				Taxa taxa =  file.getProject().getTaxa(ids);
+				if (taxa.getFile() == file){
+					int numSets = taxa.getNumSpecsSets(TaxaStringsSet.class);
+					SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+					if (ssv!=null){
+						TaxaStringsSet ms = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+						if (ms!=null && (ms.getNexusBlockStored()==null || blockName.equalsIgnoreCase(ms.getNexusBlockStored()))) {
+							ms.setNexusBlockStored(blockName);
+							ms.setName("UNTITLED");
+							s += nexusStringForSpecsSet(ms, taxa, file, true);
+						}
+
+
+						for (int ims = 0; ims<numSets; ims++) {
+							s += nexusStringForSpecsSet((TaxaStringsSet)taxa.getSpecsSet(ims, TaxaStringsSet.class), taxa, file, false);
+						}
+					}
+				}
+
+			}
+			return s;
+		}
+		return null;
+	}
+	int findWhichTaxon(int it, boolean fuse, Taxa taxa){
+		if (!fuse)
+			return it;
+		IntegerArray oi = (IntegerArray)taxa.getAttachment("originalIndicesDupRead", IntegerArray.class);
+		if (oi == null) //don't have translation; don't trust and indicate whichTaxon -1
+			return MesquiteInteger.unassigned;
+		int w = oi.getValue(it);
+		if (MesquiteInteger.isCombinable(w))
+			return w;
+		return MesquiteInteger.unassigned;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+
+			String commandName = ParseUtil.getToken(command, startCharT);
+			if (commandName.equalsIgnoreCase("ALTTAXNAMES")) {
+				boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+				
+				String token = ParseUtil.getToken(command, startCharT);
+				boolean isDefault = false;
+				if ("*".equals(token)) {
+					token = ParseUtil.getToken(command, startCharT);
+					isDefault = true;
+				}
+				String nameOfTypeset = StringUtil.deTokenize(token); // name of typeset 
+				token = ParseUtil.getToken(command, startCharT);
+				String paradigmString = null;
+				Taxa taxa = null;
+				if (token.equalsIgnoreCase("(")) {
+					token = ParseUtil.getToken(command, startCharT); //TAXA  //TODO: check to see what parameter is being set!
+					token = ParseUtil.getToken(command, startCharT); //=
+					token = (ParseUtil.getToken(command, startCharT)); // name of data
+					taxa = file.getProject().getTaxaLastFirst(token);
+					token = ParseUtil.getToken(command, startCharT); //)
+					token = ParseUtil.getToken(command, startCharT);  //=
+				}
+				else if (file.getProject().getNumberTaxas(file)>0){
+					taxa = file.getProject().getTaxa(file, 0);
+				}
+				else  
+					taxa = file.getProject().getTaxa(0);
+
+				if (taxa == null)
+					return false;
+
+				if (token.equals("="))
+					token = ParseUtil.getToken(command, startCharT); 
+
+				TaxaStringsSet taxaSet= new TaxaStringsSet(nameOfTypeset, taxa.getNumTaxa(), taxa);
+				taxaSet.setTypeName("Alternative Names");
+				taxaSet.setNexusBlockStored(blockName);
+
+				int lastChar = -1;
+				boolean join = false;
+				int i = -1;
+				while (!token.equals(";") && token.length()>0) {
+					i++;
+					int it = findWhichTaxon(i, fuse, taxa);
+					if (token.equals(" ")) {
+						taxaSet.setProperty("", it);
+					}
+					else {
+						taxaSet.setProperty(token, it);
+					}
+					token = ParseUtil.getToken(command, startCharT); 
+				}
+
+				if (!fuse && isDefault) {
+					if (!"UNTITLED".equals(taxaSet.getName())) {
+						taxa.storeSpecsSet(taxaSet, TaxaStringsSet.class);
+					}
+					taxaSet.addToFile(file, getProject(), this);
+					taxa.setCurrentSpecsSet(taxaSet, TaxaStringsSet.class);
+				}
+				else {
+					taxa.storeSpecsSet(taxaSet, TaxaStringsSet.class);
+					taxaSet.addToFile(file, getProject(), this);
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TSetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage Alternative Taxon Names";
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages (including NEXUS read/write) alternative taxon names." ;
+	}
+	/*.................................................................................................................*/
+
+}
+
+class TSetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("NOTES")) && (commandName.equalsIgnoreCase("ALTTAXNAMES")));
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageAuthors/ManageAuthors.java b/Source/mesquite/basic/ManageAuthors/ManageAuthors.java
new file mode 100644
index 0000000..b65f41c
--- /dev/null
+++ b/Source/mesquite/basic/ManageAuthors/ManageAuthors.java
@@ -0,0 +1,279 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.basic.ManageAuthors;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class ManageAuthors extends FileInit {
+	int numBlocks =0;
+	MesquiteMenuItemSpec addAuthMMI;
+	String noAuthorWarningNew = "The Author for this account and machine has not yet been set, but you are requesting an AUTHORS block." +
+	" You should now go to the Set Author... menu item in the Defaults submenu of the File menu to set an author name." + 
+	" For the code, please indicate a short code unique in your collaborative group.  If you do not set an author name, the AUTHORS block might not be written";
+	String noAuthorWarning = "The Author for this account and machine has not yet been set, but this file contains an AUTHORS block." +
+	" If you are going to edit and save this file, you are strongly urged to go to the Set Author... menu item in the Defaults submenu of the File menu to set an author name." + 
+	" For the code, please indicate a short code unique in your collaborative group.";
+	public Class getDutyClass(){
+		return ManageAuthors.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		addAuthMMI = getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu, "Add AUTHORS Block to File", new MesquiteCommand("addAuthorsBlock", this));
+		addAuthMMI.setEnabled(false);
+		MesquiteTrunk.resetMenuItemEnabling();
+//		getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu, "Add Last Author to Matrix Names", new MesquiteCommand("addAuthorNameToMatrices", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("addAuthorNameToMatrices");
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Adds name of author of scripting file to data matrix names", null, commandName, "addAuthorNameToMatrices")) {
+			MesquiteFile f=  checker.getFile();
+			if (f!= null &&f.getPreviousSaver() != null && f != getProject().getHomeFile()){
+				int numMatrices = getProject().getNumberCharMatrices(f);
+				for (int i= 0; i< numMatrices; i++) {
+					CharacterData data = getProject().getCharacterMatrix(f, i);
+					if (data.getLastModifiedAuthor() != null) {
+						data.setName(data.getName() + " (from " + data.getLastModifiedAuthor() + ")");
+						MesquiteWindow.resetAllTitles();
+					}	
+				}
+			}
+		}
+		else 	if (checker.compare(this.getClass(), "Adds an authors block to the file", null, commandName, "addAuthorsBlock")) {
+			MesquiteFile f=  checker.getFile();
+			if (f == null)
+				f = getProject().getHomeFile();
+			AuthorsBlock ab = new AuthorsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+			addAuthMMI.setEnabled(false);
+			MesquiteTrunk.resetMenuItemEnabling();
+			if (MesquiteModule.author.hasDefaultSettings() && !MesquiteThread.isScripting())
+				discreetAlert( noAuthorWarningNew);
+			if (MesquiteModule.author != null && !MesquiteModule.author.hasDefaultSettings()){
+
+				if (f.getProject().numAuthors() == 0) {
+					ListableVector authors = f.getProject().getAuthors();
+					Author a = new Author();
+					a.setName(MesquiteModule.author.getName());
+					a.setCode(MesquiteModule.author.getCode());
+					a.setCurrent(true);
+					authors.addElement(a, false);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		if (f== null || f.getProject() == null)
+			return;
+		NexusBlock[] bs = getProject().getNexusBlocks(AuthorsBlock.class, f); 
+		addAuthMMI.setEnabled((bs == null || bs.length ==0) && !Author.addAuthorBlockByDefault);
+		if ((bs == null || bs.length ==0) && Author.addAuthorBlockByDefault){
+			AuthorsBlock ab = new AuthorsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);  
+		}
+		MesquiteTrunk.resetMenuItemEnabling();
+		if (MesquiteModule.author != null && !MesquiteModule.author.hasDefaultSettings()){
+
+			if (f.getProject().numAuthors() == 0) {
+				ListableVector authors = f.getProject().getAuthors();
+				Author a = new Author();
+				a.setName(MesquiteModule.author.getName());
+				a.setCode(MesquiteModule.author.getCode());
+				a.setCurrent(true);
+				authors.addElement(a, false);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately before a file is to be saved.*/
+	public void fileAboutToBeWritten(MesquiteFile f) {
+		NexusBlock[] bs = getProject().getNexusBlocks(AuthorsBlock.class, f); 
+		if ((bs == null || bs.length ==0) && Author.addAuthorBlockByDefault){
+			AuthorsBlock ab = new AuthorsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);  
+		}
+	}
+	/*.................................................................................................................*/
+	Author findAuthor(Author author){
+		if (author == null)
+			return null;
+		if (getProject().numAuthors()>0){
+			ListableVector v = getProject().getAuthors();
+			for (int i = 0; i< v.size(); i++){
+				Author a = (Author)v.elementAt(i);
+				if (a.getCode()!= null && a.getCode().equals(author.getCode()) && a.getName()!= null && a.getName().equals(author.getName()))
+					return a;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new AuthorsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+
+		String commandString;
+		NexusBlock b=new AuthorsBlock(file, this);
+		ListableVector v = getProject().getAuthors();
+		MesquiteString comment = new MesquiteString();
+		boolean found = false;
+		for (int ia = 0; ia< v.size(); ia++){
+			Author au = (Author)v.elementAt(ia);
+			if (au == MesquiteModule.author) {
+				found = true;
+			}
+		}
+		if (!found)
+			v.addElement(MesquiteModule.author, false);
+		if (MesquiteModule.author.hasDefaultSettings() && !MesquiteThread.isScripting())
+			discreetAlert( noAuthorWarning);
+		while (!StringUtil.blank(commandString = block.getNextFileCommand(comment))) {
+			String commandName = parser.getFirstToken(commandString);
+
+			if (commandName.equalsIgnoreCase("AUTHOR")) {
+				String token = null;
+
+				Author a = new Author();
+				while (!StringUtil.blank(token = parser.getNextToken())){
+					if ("NAME".equalsIgnoreCase(token)){
+						parser.getNextToken(); //=
+						a.setName(parser.getNextToken());
+
+					}
+					else if ("CODE".equalsIgnoreCase(token)){
+						parser.getNextToken(); //=
+						a.setCode(parser.getNextToken());
+					}
+					else if ("LASTSAVER".equalsIgnoreCase(token)){
+						if (!a.hasDefaultSettings())
+							file.setPreviousSaver(a);
+					}
+				}
+				if (findAuthor(a) == null) //not found; add
+					v.addElement(a, false);
+
+			}
+		}
+		return b;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage AUTHORS blocks";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages AUTHORS block in NEXUS file." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+}
+
+
+
+/* ======================================================================== */
+class AuthorsBlockTest extends NexusBlockTest  {
+	public AuthorsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName != null && blockName.equalsIgnoreCase("AUTHORS");
+	}
+}
+
+/* ======================================================================== */
+class AuthorsBlock extends NexusBlock {
+
+	public AuthorsBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public boolean contains(FileElement e) {
+		return false;  
+	}
+
+	public void written() {
+	}
+	public String getName(){
+		return "AUTHORS block";
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		return false;
+	}
+	public String getBlockName(){
+		return "AUTHORS";
+	}
+	public String getNEXUSBlock(){
+		String contents = "";
+		MesquiteProject proj = getFile().getProject();
+		ListableVector v = proj.getAuthors();
+		for (int i = 0; i<v.size(); i++){
+			Author author =  (Author)v.elementAt(i);
+			if (!(author.isCurrent() && "Anonymous".equalsIgnoreCase(author.getName()))) {
+				contents += "AUTHOR  NAME = " + ParseUtil.tokenize(author.getName()) + " CODE = " + ParseUtil.tokenize(author.getCode());
+				if (author.isCurrent())
+					contents += " LASTSAVER";
+				contents += ";" +  StringUtil.lineEnding();
+			}
+			//else	MesquiteMessage.warnProgrammer("Warning: there may be a problem with Author management, for an attempt is being made to write Anonymous to the AUTHORS block.  Please report this problem immediately."); 
+
+
+		}
+		String unrec = getUnrecognizedCommands();
+		if (StringUtil.blank(contents) && StringUtil.blank(unrec))
+			return null;
+		String blocks="BEGIN AUTHORS;" + StringUtil.lineEnding();
+		blocks += contents;
+		if (!StringUtil.blank(unrec)) {
+			blocks += StringUtil.lineEnding()+ unrec + StringUtil.lineEnding();
+		}
+		blocks += "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+}
+
diff --git a/Source/mesquite/basic/ManageFileComments/ManageFileComments.java b/Source/mesquite/basic/ManageFileComments/ManageFileComments.java
new file mode 100644
index 0000000..5475231
--- /dev/null
+++ b/Source/mesquite/basic/ManageFileComments/ManageFileComments.java
@@ -0,0 +1,308 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ManageFileComments;
+
+import java.util.*;
+import java.io.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ManageFileComments extends FileInit {
+	boolean turnedOn=false;
+	Vector windows;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		windows = new Vector();
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+ 	/** A method called immediately after the file has been read in.*/
+ 	public void projectEstablished() {
+		getFileCoordinator().addSubmenu(MesquiteTrunk.editMenu, "Edit Comment", makeCommand("editFileComment", this), getProject().getFiles());
+		super.projectEstablished();
+ 	}
+  	 
+	/*.................................................................................................................*
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] blocks = getProject().getNexusBlocks(FileCommentsBlock.class, f);
+		if (blocks==null || blocks.length == 0){
+			FileCommentsBlock ab = new FileCommentsBlock(f, this);
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+ 	public void fileAboutToBeWritten(MesquiteFile f) {
+ 		MesquiteTextWindow w = findWindow(f);
+ 		if (w!=null){
+ 			f.setAnnotation(w.getText(), false);
+ 		}
+		
+	}
+	/*................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new FileCommentBlockTest();}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new FileNoteNexusCommandTest();
+	}
+
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			String annot = file.getAnnotation();
+			if (StringUtil.blank(annot))
+				return null;
+			else
+				return "\tTEXT  FILE TEXT = " + StringUtil.tokenize(file.getAnnotation()) + ";" + StringUtil.lineEnding();
+		}
+		return null;
+	}
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*...................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			if (fuse)
+				return true;
+			MesquiteProject project = file.getProject();
+			String commandName = parser.getFirstToken(command);
+			if (commandName.equalsIgnoreCase("TEXT") && "FILE".equalsIgnoreCase(parser.getNextToken()) && "TEXT".equalsIgnoreCase(parser.getNextToken()) ) {
+				parser.getNextToken(); //eating up "="
+				file.setAnnotation(parser.getNextToken(), false);
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		Parser commandParser = new Parser();
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		
+		String s =commandParser.getNextCommand(startCharC);
+		s =parser.getFirstToken(commandParser.getNextCommand(startCharC));
+		if (getModuleWindow()!=null)
+			((MesquiteTextWindow)getModuleWindow()).setText(s);
+		FileCommentsBlock commentBlock = new FileCommentsBlock(file, this);
+		
+		//TODO: if file element should attach to file
+		// is this project comment or not?
+		//what if file comment comes in via non-block -- need to add FileCommentsBlock
+		file.setAnnotation(s, false);
+		turnedOn = true;
+		return commentBlock; 
+	}
+	MesquiteTextWindow findWindow(MesquiteFile f){
+		for (int i=0; i<windows.size(); i++){
+			MesquiteTextWindow w = (MesquiteTextWindow)windows.elementAt(i);
+			if (w.getCurrentObject() == f)
+				return w;
+		}
+		return null;
+	}
+	MesquiteFile getFile(String argument){
+		int i = MesquiteInteger.fromString(argument);
+		if (!MesquiteInteger.isCombinable(i))
+			return null;
+		if (i<0 || i>= getProject().getNumberLinkedFiles())
+			return null;
+		return (MesquiteFile)getProject().getFiles().elementAt(i);
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+	   	Snapshot temp = new Snapshot();
+	   	boolean found = false;
+   	 	for (int i = 0; i< windows.size(); i++){
+   	 		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+   	 		
+	   	 	if (w!=null && w.isVisible()) {
+	   	 		int whichFile = getProject().getFileNumber(((MesquiteFile)w.getCurrentObject()));
+		   	 	temp.addLine("editFileComment " + whichFile);
+		  	 	Snapshot fromWindow = w.getSnapshot(file);
+	  	 	
+				temp.addLine("tell It");
+				temp.incorporate(fromWindow, true);
+				temp.addLine("showWindow");
+				temp.addLine("endTell");
+		 	 	found = true;
+	 	 	}
+ 	 	}
+ 	 	if (found)
+ 	 		return temp;
+ 	 	else
+ 	 		return null;
+  	 }
+  	 
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the file comment", "[file comment string]", commandName, "setFileComment")){
+			String comment =parser.getFirstToken(arguments);
+			MesquiteFile f = getFile(parser.getNextToken());
+			if (f!=null)
+				f.setAnnotation(comment, false);
+		}
+		else if (checker.compare(this.getClass(), "Brings up window in which to display and edit file comments", null, commandName, "editFileComment")){
+			MesquiteFile f = getFile(arguments);
+			if (f==null)
+				return null;
+			MesquiteTextWindow window = findWindow(f);
+			if (window == null) {
+				window = new MesquiteTextWindow(this, "Comment on file \"" + f.getName() + "\"", true); //infobar
+				window.setCurrentObject(f);
+				setModuleWindow(window);
+				window.setEditable(true);
+				window.setWindowSize(300,300);
+				windows.addElement(window);
+			}
+			if (window != null){
+				window.setText(f.getAnnotation());
+				resetAllMenuBars();
+			}
+			if (!MesquiteThread.isScripting())
+				window.setVisible(true);
+			return window;
+			
+		}
+		else if (checker.compare(this.getClass(), "Makes window in which to display and edit file comments", null, commandName, "makeWindow")){
+			MesquiteFile f = getProject().getHomeFile();
+			if (f==null)
+				return null;
+			MesquiteTextWindow window = findWindow(f);
+			if (window == null) {
+				window = new MesquiteTextWindow(this, "Comment on file \"" + f.getName() + "\"", false); //infobar
+				window.setCurrentObject(f);
+				window.setWindowSize(300,300);
+				windows.addElement(window);
+				window.setText(f.getAnnotation());
+				window.setEditable(true);
+			}
+			return window;
+			
+		}
+		else if (checker.compare(this.getClass(), "Brings up window in which to display and edit file comments", null, commandName, "showWindow")){
+			MesquiteFile f = getProject().getHomeFile();
+			if (f==null)
+				return null;
+			MesquiteTextWindow window = findWindow(f);
+			if (window != null) {
+				window.setText(f.getAnnotation());
+				window.setVisible(true);
+				resetAllMenuBars();
+			}
+			return window;
+			
+		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+  	/*public String getComments() {
+  		if (getModuleWindow()!=null)
+  			return ((MesquiteTextWindow)getModuleWindow()).getText();
+  		else if (commentBlock!=null)
+  			return commentBlock.getText();
+  		else
+  			return null;
+  	}
+  	*/
+  	 public void windowGoAway(MesquiteWindow whichWindow) {
+  		 if (whichWindow == null)
+  			 return;
+		Object obj = whichWindow.getCurrentObject();
+		if (obj instanceof MesquiteFile){
+			MesquiteFile f = (MesquiteFile)obj;
+			if (f!=null)
+	  	 		f.setAnnotation(((MesquiteTextWindow)whichWindow).getText(), false);
+  	 	}
+  	 	whichWindow.hide();
+  	 	//don't dispose since may be recalled.
+  	 	
+  	 }
+  	 public void endJob(){
+			for (int i=0; i<windows.size(); i++){
+				windowGoAway((MesquiteTextWindow)windows.elementAt(i));
+				((MesquiteTextWindow)windows.elementAt(i)).dispose();
+			}
+		super.endJob();
+	
+  	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "File Comment";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages the main file comment in a NEXUS file." ;
+   	 }
+}
+/* ======================================================================== */
+class FileCommentsBlock extends NexusBlock {  
+	public FileCommentsBlock(MesquiteFile f, ManageFileComments mb){
+		super(f,mb);
+	}
+	public void written() {
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public boolean mustBeAfter(NexusBlock block){ //� 13 Dec 01
+		return false;
+	}
+	public String getBlockName(){
+		return "FILECOMMENT";
+	}
+	public String getName(){
+		return "FileComments block";
+	}
+	public String getNEXUSBlock(){
+		return null;  //this block is read but not written!!!!!  It was used temporarily.
+	}
+}
+/* ======================================================================== */
+/** An object of this kind can be returned by getNexusCommandTest that will be stored in the modulesinfo vector and used
+to search for modules that can read a particular command in a particular block.  (Much as the NexusBlockObject.)*/
+class FileNoteNexusCommandTest extends NexusCommandTest  {
+	MesquiteInteger pos = new MesquiteInteger();
+	/**returns whether or not the module can deal with command*/
+	public boolean readsWritesCommand(String blockName, String commandName, String command){
+		boolean b = (blockName.equalsIgnoreCase("NOTES")  && commandName.equalsIgnoreCase("TEXT"));
+		if (b){
+			pos.setValue(0);
+			String firstToken = ParseUtil.getTokenNumber(command,  pos, 2);
+			if (!("FILE".equalsIgnoreCase(firstToken)))
+				return false;
+			return true;
+		}
+		return false;
+	} 
+}
+/* ======================================================================== */
+class FileCommentBlockTest extends NexusBlockTest  {
+	public FileCommentBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("FileComment");
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageLabelsBlock/ManageLabelsBlock.java b/Source/mesquite/basic/ManageLabelsBlock/ManageLabelsBlock.java
new file mode 100644
index 0000000..200ba8a
--- /dev/null
+++ b/Source/mesquite/basic/ManageLabelsBlock/ManageLabelsBlock.java
@@ -0,0 +1,169 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ManageLabelsBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages the labels block in a nexus file*/
+public class ManageLabelsBlock extends FileInit {
+	int numBlocks = 0;
+	public Class getDutyClass(){
+		return ManageLabelsBlock.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] bs = getProject().getNexusBlocks(LabelsBlock.class, f); //added Dec 01
+		if (bs == null || bs.length ==0){ 
+			LabelsBlock ab = new LabelsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new LabelsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		Parser commandParser = new Parser();
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		String s;
+ 		NexusBlock[] bs = getProject().getNexusBlocks(LabelsBlock.class, file); //added Sept 2011
+ 		LabelsBlock sB ;
+		if (bs == null || bs.length ==0)
+		 sB= new LabelsBlock(file, this); //TODO: should this store the LABELS??
+		else
+			sB = (LabelsBlock)bs[0];
+		int numChars=0;
+		while (!StringUtil.blank(s=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(s);
+			if (!commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK"))
+				if (commandName.equalsIgnoreCase("LINK")){
+					sB.processLinkCTCommand( s, getProject(), parser);
+				}
+				else
+					readUnrecognizedCommand(file, sB, "LABELS", block, commandName, s, blockComments, null);
+		}
+			numBlocks++;
+		return sB;
+	}
+/*
+	private boolean findReaderForCommand (MesquiteFile mf, String blockName, String commandName, String command, MesquiteString comment, LabelsBlock sB) {
+		Enumeration enumeration=mf.getProject().getCoordinatorModule().getEmployeeVector().elements(); // WHY ARE ONLY EMPLOYEES OF FILE COORDINATOR USED????
+		MesquiteModule employeeModule;
+		MesquiteModuleInfo mbi;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employeeModule = (MesquiteModule)obj;
+			mbi = employeeModule.getModuleInfo();
+			if (mbi==null)
+				MesquiteMessage.println("no employees of ownerModule!!!");
+			else if (mbi.nexusCommandTest!=null) {
+				if (mbi.nexusCommandTest.readsWritesCommand(blockName, commandName, command)) {
+					if (employeeModule.readNexusCommand(mf, blockName, command, comment))
+						return true;
+				}
+			}
+		}
+		sB.storeUnrecognizedCommand(command);
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getLabelsBlock(MesquiteFile file, LabelsBlock sB){
+		String contents = employeesGetCommands(getProject().ownerModule, file);
+		if (sB != null) contents += sB.getUnrecognizedCommands() + StringUtil.lineEnding();
+		if (StringUtil.blank(contents))
+			return null;
+		String blocks="BEGIN LABELS;" + StringUtil.lineEnding()+ contents+ "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+	/*.................................................................................................................*/
+	private String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "LABELS");
+			if (!StringUtil.blank(command))
+				commands+=command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage LABELS blocks";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages LABELS block in NEXUS file." ;
+   	 }
+}
+	
+/* ======================================================================== */
+class LabelsBlock extends NexusBlock {
+	public LabelsBlock(MesquiteFile f, ManageLabelsBlock mb){
+		super(f,mb);
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("written labels");
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("CHARACTERS"));
+		
+	}
+	public String getBlockName(){
+		return "LABELS";
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public String getName(){
+		return "LABELS block";
+	}
+	public String getNEXUSBlock(){
+		return ((ManageLabelsBlock)getManager()).getLabelsBlock(getFile(), this);
+	}
+}
+
+	
+/* ======================================================================== */
+class LabelsBlockTest extends NexusBlockTest  {
+	public LabelsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("LABELS");
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageNotesBlock/ManageNotesBlock.java b/Source/mesquite/basic/ManageNotesBlock/ManageNotesBlock.java
new file mode 100644
index 0000000..ff7ed07
--- /dev/null
+++ b/Source/mesquite/basic/ManageNotesBlock/ManageNotesBlock.java
@@ -0,0 +1,228 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.ManageNotesBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/** Manages the NOTES block of a NEXUS file */
+public class ManageNotesBlock extends FileInit {
+	Vector blocks;
+	int numBlocks =0;
+	public Class getDutyClass(){
+		return ManageNotesBlock.class;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new NotesBlockTest();}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		NexusBlock[] bs = getProject().getNexusBlocks(NotesBlock.class, f); //added Dec 01
+		if (bs == null || bs.length ==0){ 
+			NotesBlock ab = new NotesBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+		}
+
+	}
+
+	private NotesBlock makeBlock(MesquiteFile file) {
+		NexusBlock[] bs = getProject().getNexusBlocks(NotesBlock.class, file);//added Sept 2011
+		NotesBlock b;
+		if (bs == null || bs.length == 0){
+			b = new NotesBlock(file, this);
+			b.setName("Notes Block");
+			numBlocks++;
+			if (blocks==null)
+				blocks = new Vector();
+			blocks.addElement(b);
+		}
+		else
+			b = (NotesBlock)bs[0];
+		return b;
+	}
+	/*
+Begin Notes;
+	Text [Taxon=taxon-set] [Character=character-set]
+			[State=state-set] [Tree=tree-set]
+			Source={Inline|File|Resource} 
+			Text=text or source descriptor;
+	Picture [Taxon=taxon-set] [CHARACTER=character-set]
+			[State=state-set] [Tree=tree-set] 
+			[Format={PICT|TIFF|EPS|JPEG|GIF}] 
+			[Encode={None|UUEncode|BinHex}]
+			Source={Inline|File|Resource} 
+			Picture=picture-or-source-descriptor;
+End;
+	/*.................................................................................................................*/
+
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		NotesBlock b = makeBlock(file);
+		int c = 0;
+		String s;
+		boolean nbw = file.notesBugWarn;
+		MesquiteString comment = new MesquiteString();
+		file.notesBugVector = new Vector();
+		while (!StringUtil.blank(s=block.getNextFileCommand(comment))) {
+			String commandName = parser.getFirstToken(s);
+			CommandRecord.tick("Reading command " + commandName);
+
+			if (commandName != null && !commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK")){
+				if (commandName.equalsIgnoreCase("LINK")){
+					b.processLinkCTCommand( s, getProject(), parser);
+				}
+				else
+					readUnrecognizedCommand(file, b, "NOTES", block, commandName, s, blockComments, comment);
+			}
+		}
+		if (!nbw && file.notesBugWarn){
+			alert("A NOTES block in a linked file has overridden some notes assigned previously.  "
+					+"It is possible that this is due to a bug in versions 1.0-1.02 of Mesquite which wrote duplicate NOTES blocks in any linked files. " 
+					+ "If the linked files were disconnected from the main data file, they may have retained a relictual NOTES block that could later override the more current version. "
+					+ "Into the log will be written the characters and taxa for which notes were overridden.  Please check to see that the footnotes for these are correct. "
+					+ "If the notes appear incorrect, then we suggest you close these files WITHOUT SAVING, and contact "
+					+ "Wayne Maddison at wmaddisn at interchange.ubc.ca for assistance.");
+			logln("");
+
+			for (int i = 0; i < file.notesBugVector.size(); i++)
+				logln("Warning: Overridden note for " + (String)file.notesBugVector.elementAt(i));
+			logln("");
+			file.notesBugVector.removeAllElements();
+		}
+		return b;
+	}
+	/*.................................................................................................................*
+	public String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "NOTES");
+			if (!StringUtil.blank(command))
+				commands+=command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+	boolean employeesWriteCommands(MesquiteModule module, MesquiteFile mf, MesquiteString pending) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		boolean written = false;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			written = employee.writeNexusCommands(mf, "NOTES", pending) || written;
+			employeesWriteCommands(employee, mf, pending);
+		}
+		return written;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage NOTES blocks";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages footnotes and pictures attached to taxa, characters and data points (including read/write NOTES block in NEXUS file)." ;
+	}
+}
+
+class NotesBlock extends NexusBlock {
+	String blockContents = "";
+	public NotesBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("written Notes");
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("TREES") ||block.getBlockName().equalsIgnoreCase("CHARACTERS"));
+
+	}
+	public String getBlockName(){
+		return "NOTES";
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public void setText(String contents) {
+		blockContents = contents;
+	}
+	public String getText() {
+		return blockContents;
+	}
+	public String getName(){
+		return "NOTES block";
+	}
+	/** Writes the NEXUS block into the file  Block must override either this or getNEXUSBlock to write to file*/
+	public void writeNEXUSBlock(MesquiteFile file, ProgressIndicator progIndicator){
+		MesquiteTrunk.mesquiteTrunk.logln("      Writing " + getName());
+		MesquiteString pending = new MesquiteString("BEGIN NOTES;" + StringUtil.lineEnding());
+		boolean written = ((ManageNotesBlock)getManager()).employeesWriteCommands(getManager().getFileCoordinator(), file, pending);
+
+		String unrec =getUnrecognizedCommands();
+		if (!StringUtil.blank(unrec)){
+			if (!pending.isBlank()){
+				file.writeLine(pending.toString());
+
+			}
+			file.writeLine(unrec + StringUtil.lineEnding() + "END;" + StringUtil.lineEnding());
+
+		}
+		else if (written)
+			file.writeLine("END;" + StringUtil.lineEnding());
+	}
+	/*   *
+	public String getNEXUSBlock(){
+		String contents = ((ManageNotesBlock)getManager()).employeesGetCommands(getManager().getFileCoordinator(), getFile());
+		String unrec =getUnrecognizedCommands();
+		if (StringUtil.blank(contents) && StringUtil.blank(unrec))
+			return null;
+		String blocks="BEGIN NOTES;" + StringUtil.lineEnding()+ contents + StringUtil.lineEnding()+ unrec + StringUtil.lineEnding() + "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+	//remember to store unrecognixed commands*/
+}
+/* ======================================================================== */
+class NotesBlockTest extends NexusBlockTest  {
+	public NotesBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("NOTES");
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageSetsBlock/ManageSetsBlock.java b/Source/mesquite/basic/ManageSetsBlock/ManageSetsBlock.java
new file mode 100644
index 0000000..82b8b81
--- /dev/null
+++ b/Source/mesquite/basic/ManageSetsBlock/ManageSetsBlock.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ManageSetsBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages the SETS block of a NEXUS file.*/
+public class ManageSetsBlock extends FileInit {
+	int numBlocks =0;
+	public Class getDutyClass(){
+		return ManageSetsBlock.class;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] bs = getProject().getNexusBlocks(SETSBlock.class, f); //added Dec 01
+		if (bs == null || bs.length ==0){ 
+			SETSBlock ab = new SETSBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new SetsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		int c = 0;
+		String s;
+		NexusBlock[] bs = getProject().getNexusBlocks(SETSBlock.class, file);//added Sept 2011
+		SETSBlock sB = null;
+		if (bs == null || bs.length == 0) {
+			sB = new SETSBlock(file, this); //TODO: should this store the sets??
+			numBlocks++;
+		}
+		else
+			sB= (SETSBlock)bs[0];
+		
+		int numChars=0;
+		MesquiteString comment = new MesquiteString();
+		while (!StringUtil.blank(s=block.getNextFileCommand(comment))) {
+			String commandName = parser.getFirstToken(s);
+			if (!commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK")){
+				if (commandName.equalsIgnoreCase("LINK")){
+					sB.processLinkCTCommand( s, getProject(), parser);
+				}
+				else
+					readUnrecognizedCommand(file, sB, "SETS", block, commandName, s, blockComments, comment);
+			}
+		}
+		return sB;
+	}
+	/*.................................................................................................................*/
+	public String getSetsBlock(MesquiteFile file, SETSBlock sB){
+		String contents = employeesGetCommands(getProject().ownerModule, file);
+		String unrec = sB.getUnrecognizedCommands();
+		if (StringUtil.blank(contents) && StringUtil.blank(unrec))
+			return null;
+		String blocks="BEGIN SETS;" + StringUtil.lineEnding()+ contents;
+		if (!StringUtil.blank(unrec))
+			blocks += StringUtil.lineEnding()+ unrec + StringUtil.lineEnding();
+		blocks += "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+	/*.................................................................................................................*/
+	private String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "SETS");
+			if (!StringUtil.blank(command))
+				commands+=command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage SETS blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages character sets and other sets of various kinds (including read/write SETS block in NEXUS file)." ;
+   	 }
+}
+	
+/* ======================================================================== */
+class SETSBlock extends NexusBlock {
+	public SETSBlock(MesquiteFile f, ManageSetsBlock mb){
+		super(f,mb);
+	}
+	public void written() {
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("CHARACTERS") ||  block.getBlockName().equalsIgnoreCase("LABELS"));
+		
+	}
+	public String getBlockName(){
+		return "SETS";
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public String getName(){
+		return "SETS block";
+	}
+	public String getNEXUSBlock(){
+		return ((ManageSetsBlock)getManager()).getSetsBlock(getFile(), this);
+	}
+}
+
+	
+/* ======================================================================== */
+class SetsBlockTest extends NexusBlockTest  {
+	public SetsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("SETS");
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageTaxaPartitions/ManageTaxaPartitions.java b/Source/mesquite/basic/ManageTaxaPartitions/ManageTaxaPartitions.java
new file mode 100644
index 0000000..fd0a4a0
--- /dev/null
+++ b/Source/mesquite/basic/ManageTaxaPartitions/ManageTaxaPartitions.java
@@ -0,0 +1,542 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.ManageTaxaPartitions;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterPartition;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.GroupDialog;
+
+/** Manages specifications of partitions of taxa, including reading and writing from NEXUS file. */
+public class ManageTaxaPartitions extends SpecsSetManager {
+	final static String listOfTaxonGroupsName = "List of Taxon Group Labels";
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.TaxaPartitionList.TaxaPartitionList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	TaxaGroupVector groups; //TODO: dealing with taxa groups should probably be a separate module to allow it to be recognized as element manager
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		groups = new TaxaGroupVector();
+		getProject().addFileElement(groups);
+		return true;
+	}
+
+
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof TaxaGroup){
+			TaxaGroup group = (TaxaGroup)e;
+			GroupDialog d = new GroupDialog(getProject(),getProject().getCoordinatorModule().containerOfModule(), "Edit Taxa Group", group.getName(), group.getColor(), group.getSymbol(), group.supportsSymbols());
+			d.completeAndShowDialog();
+			String name = d.getName();
+			MesquiteSymbol symbol = d.getSymbol();
+			boolean ok = d.query()==0;
+			Color c = d.getColor();
+			d.dispose();
+			if (!ok)
+				return null;
+
+
+			if (!StringUtil.blank(name)) {
+				group.setName(name);
+			}
+			group.setColor(c);
+			group.setSymbol(symbol);
+			notifyOfGroupChange(group);
+			return null;
+		}
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	public void notifyOfGroupChange(TaxaGroup e){
+		if (e instanceof TaxaGroup){
+			e.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+			ListableVector d = getProject().getTaxas();
+			for (int im = 0; im<d.size(); im++){
+				Taxa taxa = (Taxa)d.elementAt(im);
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+				TaxaPartition cp = (TaxaPartition)ssv.getCurrentSpecsSet();
+				boolean done = false;
+				if (cp != null)
+					for (int ic = 0; ic< taxa.getNumTaxa() && ! done; ic++){
+						if (cp.getTaxaGroup(ic) == e) {
+							taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+							done = true;
+						}
+					}
+				for (int is = 0; is< ssv.size() && !done; is++){
+					cp = (TaxaPartition)ssv.elementAt(is);
+					for (int ic = 0; ic< taxa.getNumTaxa() && !done; ic++){
+						if (cp.getTaxaGroup(ic) == e) {
+							taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+							done = true;
+						}
+					}
+				}
+			}
+		}
+	}
+	public NexusBlock elementAdded(FileElement e){
+		if (e instanceof TaxaGroup){
+			
+			if (groups.indexOf(e)<0) {
+				groups.addElement(e, true);
+				e.addListener(groups);
+			}
+			e.setManager(this);
+			return null;
+		}
+		else if (e!=null && e instanceof Taxa){
+			e.prepareSpecsSetVector(TaxaPartition.class, "Taxa Partitions");
+		}
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		if (groups !=null)
+			groups.removeElement(e, true);
+	}
+	public void deleteElement(FileElement e){
+		if (e instanceof TaxaGroup){
+			ListableVector d = getProject().getTaxas();
+			for (int im = 0; im<d.size(); im++){
+				Taxa taxa = (Taxa)d.elementAt(im);
+				boolean changed = false;
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+				TaxaPartition cp = (TaxaPartition)ssv.getCurrentSpecsSet();
+				if (cp != null)
+					for (int ic = 0; ic< taxa.getNumTaxa(); ic++){
+						if (cp.getTaxaGroup(ic) == e) {
+							cp.setProperty(cp.getDefaultProperty(ic), ic);
+							changed = true;
+						}
+					}
+				for (int is = 0; is< ssv.size(); is++){
+					cp = (TaxaPartition)ssv.elementAt(is);
+					for (int ic = 0; ic< taxa.getNumTaxa(); ic++){
+						if (cp.getTaxaGroup(ic) == e) {
+							cp.setProperty(cp.getDefaultProperty(ic), ic);
+							changed = true;
+						}
+					}
+				}
+				if (changed)
+					taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+			}
+			getProject().removeFileElement(e);//must remove first, before disposing
+			groups.removeElement(e, true);
+			e.dispose();
+		}
+	}
+	public Class getElementClass(){
+		return TaxaPartition.class;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu,"List of Taxa Partitions", makeCommand("showPartitions",  this), (ListableVector)getProject().taxas);
+		mmis.setOwnerModuleID(getID());
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, listOfTaxonGroupsName, makeCommand("showTaxonGroups",  this));
+		groups.addToFile(getProject().getHomeFile(), getProject(), this);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("List of Taxa Partitions")) {
+				Object o = e.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+
+				if (o !=null && o instanceof Taxa) {
+					//int wh =getProject().getTaxaReference((Taxa)o);
+					temp.addLine("showPartitions " + getProject().getTaxaReferenceExternal((Taxa)o), e); 
+				}
+				else
+					temp.addLine("showPartitions ", e); 
+			} else if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals(listOfTaxonGroupsName)) {
+				temp.addLine("showTaxonGroups ", e); 
+			}
+		}
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	 public ManagerAssistant showTaxonGroupList(Object obj, String listerName){
+	 		//Check to see if already has lister for this
+/*	 		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(obj)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+		*/
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize(listerName));
+			if (lister!=null) {
+				lister.showListWindow(obj);
+	 			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+	 				lister.getModuleWindow().setVisible(true);
+	 		}
+		return lister;
+	 		
+}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows lists of the taxa partitions", null, commandName, "showPartitions")) {
+			if (StringUtil.blank(arguments)) {
+				for (int i = 0; i< getProject().getNumberTaxas(checker.getFile()); i++) {
+					showSpecsSets(getProject().getTaxa(checker.getFile(), i), "List of Taxa Partitions");
+				}
+			}
+			else {
+				Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+				if (t!=null ) {
+					return showSpecsSets(t, "List of Taxa Partitions");
+				}
+			}
+//			alert("Sorry, there are no taxa partitions");
+		}
+		else if (checker.compare(this.getClass(), "Shows list of the taxon groups", null, commandName, "showTaxonGroups")) {
+					return showTaxonGroupList(null, listOfTaxonGroupsName);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	private TaxaGroup findGroup(String token){ 
+		if (token ==null)
+			return null;
+		for (int i = 0; i< groups.size(); i++){
+			TaxaGroup cg = (TaxaGroup)groups.elementAt(i);
+			if (token.equalsIgnoreCase(cg.getName())){
+				return cg;
+			}
+		}
+		return null;
+	}
+
+	private TaxaGroup makeGroup(String name, Parser subcommands, MesquiteFile file){
+		TaxaGroup group = findGroup(name);
+		if (group==null) {
+			group = new TaxaGroup();
+			group.setName(name);
+			group.addToFile(file, getProject(), this);
+			if (groups.indexOf(group)<0) 
+				groups.addElement(group, false);
+		}
+		if (subcommands !=null){ //this should be passed into group to handle?
+			String token = null;
+			while ((token = subcommands.getNextToken())!=null){
+				if (token.equalsIgnoreCase("COLOR")){
+					token = subcommands.getNextToken(); //=
+					token = subcommands.getNextToken(); // (
+					token = subcommands.getNextToken(); // should be RGB
+					if (token!=null && token.equalsIgnoreCase("RGB")) {
+						double red = MesquiteDouble.fromString(subcommands.getNextToken()); //Red
+						double green = MesquiteDouble.fromString(subcommands.getNextToken()); //green
+						double blue = MesquiteDouble.fromString(subcommands.getNextToken()); //blue
+						if (MesquiteDouble.isCombinable(red) && MesquiteDouble.isCombinable(green) && MesquiteDouble.isCombinable(blue)){
+							Color c = new Color((float)red, (float)green, (float)blue);
+							group.setColor(c);
+						}
+					}
+				}
+				else if (token.equalsIgnoreCase("SYMBOL")){
+					token = subcommands.getNextToken(); //=
+					token = subcommands.getNextToken(); // (
+					token = subcommands.getNextToken(); // should be NAME					
+					if (token!=null && token.equalsIgnoreCase("NAME")) {
+						token = subcommands.getNextToken(); //=
+						token = subcommands.getNextToken(); // name of symbol
+						Listable[] list = getProject().getFileElements(SymbolsVector.class);
+						if (list != null && list.length >  0){
+							SymbolsVector symVector = (SymbolsVector)list[0];
+							MesquiteSymbol symbol = (MesquiteSymbol)symVector.elementWithName(token);
+							if (symbol!=null) {
+								MesquiteSymbol groupSymbol = symbol.cloneMethod();
+								Parser remaining = new Parser();
+								remaining.setString(subcommands.getRemainingUntilChar(')',true));
+								groupSymbol.interpretNexus(remaining);
+								group.setSymbol(groupSymbol);
+							}
+						}
+					}
+				}
+				else if (token.equalsIgnoreCase("HIDDEN")){
+					group.setVisible(false);
+				}
+			}
+		}
+		return group;
+	}
+	/*.................................................................................................................*/
+	String nexusStringForSpecsSet(TaxaPartition taxaPartition, Taxa taxa, MesquiteFile file, boolean isCurrent){
+		String s= "";
+		if (taxaPartition !=null && (taxaPartition.getFile()==file || (taxaPartition.getFile()==null && taxa.getFile()==file))) {
+			String sT = " ";
+			TaxaGroup[] parts = taxaPartition.getGroups();
+			boolean firstTime =true;
+
+			if (parts!=null)
+				for (int i=0; i<parts.length; i++) {
+					String q = ListableVector.getListOfMatches((Listable[])taxaPartition.getProperties(), parts[i], 1, false);
+					if (q != null) {
+						if (!firstTime)
+							sT += ", ";
+						firstTime = false;
+						sT += StringUtil.tokenize(parts[i].getName()) + " : " + q ;
+					}
+				}
+
+			if (!StringUtil.blank(sT)) {
+				s+= "\tTAXPARTITION " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(taxaPartition.getName()) + " ";
+				if (file.getProject().getNumberTaxas()>1)
+					s+= " (TAXA = " +  StringUtil.tokenize(taxa.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("LABELS")) {
+			String s = "";
+			for (int i = 0; i< groups.size(); i++){
+				TaxaGroup cg = (TaxaGroup)groups.elementAt(i);
+				if (cg.getFile() == file){
+					s += "\tTAXAGROUPLABEL " + ParseUtil.tokenize(cg.getName());
+					if (cg.colorSet()){
+						Color c = cg.getColor();
+						if (c!=null)
+							s += " COLOR = (RGB " + MesquiteDouble.toString(c.getRed()/255.0) + " " + MesquiteDouble.toString(c.getGreen()/255.0) + " " + MesquiteDouble.toString(c.getBlue()/255.0) + ") ";
+					}
+					if (cg.symbolSet()){
+						MesquiteSymbol symbol = cg.getSymbol();
+						if (symbol != null)
+							s += " SYMBOL = (NAME="+ParseUtil.tokenize(symbol.getName()) + " SIZE="+symbol.getSize() + " "+ symbol.getBasicNexusOptions()+ " "+ symbol.getExtraNexusOptions() + ") ";
+					}
+					if (!cg.isVisible()){
+						Color c = cg.getColor();
+						s += " HIDDEN ";
+					}
+					s += ";" + StringUtil.lineEnding();
+				}
+			}
+			if (StringUtil.blank(s))
+				return null;
+			else
+				return s;
+		}
+		else  if (blockName.equalsIgnoreCase("SETS")) {
+			String s= "";
+			for (int ids = 0; ids<file.getProject().getNumberTaxas(); ids++) {
+
+				Taxa taxa =  file.getProject().getTaxa(ids);
+				if (taxa.getFile() == file){
+					int numSets = taxa.getNumSpecsSets(TaxaPartition.class);
+					SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+					if (ssv!=null){
+						TaxaPartition ms = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+						if (ms!=null && (ms.getNexusBlockStored()==null || blockName.equalsIgnoreCase(ms.getNexusBlockStored()))) {
+							ms.setNexusBlockStored(blockName);
+							ms.setName("UNTITLED");
+							s += nexusStringForSpecsSet(ms, taxa, file, true);
+						}
+
+
+						for (int ims = 0; ims<numSets; ims++) {
+							s += nexusStringForSpecsSet((TaxaPartition)taxa.getSpecsSet(ims, TaxaPartition.class), taxa, file, false);
+						}
+					}
+				}
+
+			}
+			return s;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+		if (fuse)
+			return false;
+		if (blockName.equalsIgnoreCase("LABELS")) {
+			String commandName = parser.getFirstToken(command);
+			if ("TAXAGROUPLABEL".equalsIgnoreCase(commandName)) {
+				String name = parser.getNextToken();
+				makeGroup(name, parser, file); //pass whole command
+				return true;
+			}
+			return false;
+		}
+		else if (blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) {
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+
+			String commandName = ParseUtil.getToken(command, startCharT);
+			if (commandName.equalsIgnoreCase("TAXAPARTITION") || commandName.equalsIgnoreCase("TAXPARTITION")) {
+				String token = ParseUtil.getToken(command, startCharT);
+				boolean isDefault = false;
+				if ("*".equals(token)) {
+					token = ParseUtil.getToken(command, startCharT);
+					isDefault = true;
+				}
+				String nameOfTypeset = token; // name of typeset 
+				token = ParseUtil.getToken(command, startCharT);
+				String paradigmString = null;
+				Taxa taxa = null;
+				if (token.equalsIgnoreCase("(")) {
+					token = ParseUtil.getToken(command, startCharT); //TAXA  //TODO: check to see what parameter is being set!
+					token = ParseUtil.getToken(command, startCharT); //=
+					token = (ParseUtil.getToken(command, startCharT)); // name of data
+					taxa = file.getProject().getTaxaLastFirst(token); //taxa is named; seek without restriction to current file
+					token = ParseUtil.getToken(command, startCharT); //)
+					token = ParseUtil.getToken(command, startCharT);  //=
+				}
+				else if (file.getProject().getNumberTaxas(file)>0)//taxa not named; seek with restriction to current file
+					taxa = file.getProject().getTaxa(file, 0);
+				else  
+					taxa = file.getProject().getTaxa(0);
+
+				if (taxa == null)
+					return false;
+
+				if (token.equals("="))
+					token = ParseUtil.getToken(command, startCharT); 
+
+				TaxaGroup defaultProperty =  null;
+
+				TaxaGroup lastCM =makeGroup(token, null, file);
+				//lastCM.setGroupNumber(MesquiteInteger.fromString(token));
+				TaxaPartition taxaPartition= new TaxaPartition(nameOfTypeset, taxa.getNumTaxa(), defaultProperty, taxa);
+				taxaPartition.setNexusBlockStored(blockName);
+
+				int lastChar = -1;
+				boolean join = false;
+				boolean nextIsPart = false;
+				while (!token.equals(";") && token.length()>0) {
+					if (token.equals("-")) {
+						if (lastChar!=-1)
+							join = true;
+					}
+					else if (token!=null) {
+						if (token != null && token.equals("."))
+							token = Integer.toString(taxa.getNumTaxa());
+
+						if (token.startsWith("-")) {
+							if (lastChar!=-1)
+								join = true;
+							token = token.substring(1, token.length());
+						}
+						if (token.equals(":")) {
+							nextIsPart = true;
+						}
+						else if (token.equals(","))
+							nextIsPart=false;
+						else if (nextIsPart) {
+							//MesquiteInteger cm = new MesquiteInteger(MesquiteInteger.fromString(token));
+							int whichTaxon = Taxon.toInternal(MesquiteInteger.fromString(token, false));
+							if (MesquiteInteger.isCombinable(whichTaxon)) {
+								if (join) {
+									for (int j = lastChar; j<=whichTaxon; j++) {
+										taxaPartition.setProperty(lastCM,j);
+									}
+									join = false;
+									lastChar = -1;
+								}
+								else {
+									lastChar = whichTaxon;
+									taxaPartition.setProperty(lastCM,whichTaxon);
+								}
+							}
+						}
+						else {
+							lastCM = makeGroup(token, null, file);
+							/*int whichGroup = MesquiteInteger.fromString(token, false);
+							if (!MesquiteInteger.isCombinable(whichGroup))
+								whichGroup = ColorDistribution.getStandardColorNumber(token);
+							lastCM.setGroupNumber(whichGroup);
+							 */
+							nextIsPart = true;
+						}
+					}
+					token = ParseUtil.getToken(command, startCharT); 
+				}
+
+				if (isDefault) { //todo: OR IS FIRST
+					if (!"UNTITLED".equals(taxaPartition.getName())) {
+						taxa.storeSpecsSet(taxaPartition, TaxaPartition.class);
+					}
+					taxaPartition.addToFile(file, getProject(), this);
+					SpecsSet ss = taxaPartition.cloneSpecsSet();
+					ss.addToFile(file, getProject(), this);
+					taxa.setCurrentSpecsSet(ss, TaxaPartition.class);
+				}
+				else {
+					taxa.storeSpecsSet(taxaPartition, TaxaPartition.class);
+					taxaPartition.addToFile(file, getProject(), this);
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TPartNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage taxa partititions";
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages (including NEXUS read/write) taxa partitions." ;
+	}
+	/*.................................................................................................................*/
+
+}
+
+class TPartNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		if ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS"))  && (commandName.equalsIgnoreCase("TAXAPARTITION") ||commandName.equalsIgnoreCase("TAXPARTITION")))
+			return true;
+		if ((blockName.equalsIgnoreCase("LABELS")) && commandName.equalsIgnoreCase("TAXAGROUPLABEL"))
+			return true;
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/basic/ManageTaxaSets/ManageTaxaSets.java b/Source/mesquite/basic/ManageTaxaSets/ManageTaxaSets.java
new file mode 100644
index 0000000..e1605e2
--- /dev/null
+++ b/Source/mesquite/basic/ManageTaxaSets/ManageTaxaSets.java
@@ -0,0 +1,294 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ManageTaxaSets;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages TAXSETs (not Taxa blocks; see ManageTaxa), including reading the NEXUS command for TAXSETs */
+public class ManageTaxaSets extends SpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.TaxonSetList.TaxonSetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return TaxaSelectionSet.class;
+	}
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in.*/
+ 	public void projectEstablished() {
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu,"List of Taxon Sets", makeCommand("showSets",  this), getProject().taxas);
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		mmis.setOwnerModuleID(getID());
+		super.projectEstablished();
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("List of Taxon Sets")) {
+				Object o = e.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+				
+				if (o !=null && o instanceof Taxa) {
+					//int wh =getProject().getTaxaReference((Taxa)o);
+  	 				temp.addLine("showSets " + getProject().getTaxaReferenceExternal((Taxa)o), e); 
+  	 			}
+  	 			else
+  	 				temp.addLine("showSets ", e); 
+  	 		}
+		}
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Shows lists of the taxon sets (TAXSETS)", null, commandName, "showSets")) {
+    	 		if (StringUtil.blank(arguments)) {
+	    	 		for (int i = 0; i< getProject().getNumberTaxas(checker.getFile()); i++) {
+	    	 			showSpecsSets(getProject().getTaxa(checker.getFile(), i), "List of Taxon Sets");
+				}
+    	 		}
+    	 		else {
+    	 			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+ 	 			if (t!=null ) {
+ 	 				return showSpecsSets(t, "List of Taxon Sets");
+ 	 			}
+    	 		}
+//    	 			alert("Sorry, there are no taxon sets");
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   
+	/*.................................................................................................................*/
+	String nexusStringForSpecsSet(TaxaSelectionSet taxaSet, Taxa taxa, MesquiteFile file, boolean isCurrent){
+			String s= "";
+			if (taxaSet!=null && (taxaSet.getFile()==file || (taxaSet.getFile()==null && taxa.getFile()==file))) {
+				String sT = "";
+				int continuing = 0;
+				int lastWritten = -1;
+				for (int ic=0; ic<taxa.getNumTaxa(); ic++) {
+					if (taxaSet.isBitOn(ic)) {
+						if (continuing == 0) {
+							sT += " " + Taxon.toExternal(ic);
+							lastWritten = ic;
+							continuing = 1;
+						}
+						else if (continuing == 1) {
+							sT += " - ";
+							continuing = 2;
+						}
+					}
+					else if (continuing>0) {
+						if (lastWritten != ic-1) {
+							sT += " " + Taxon.toExternal(ic-1);
+							lastWritten = ic-1;
+						}
+						else
+							lastWritten = -1;
+						continuing = 0;
+					}
+
+				}
+				if (continuing>1)
+					sT += " " + Taxon.toExternal(taxa.getNumTaxa()-1);
+				if (!StringUtil.blank(sT)) {
+					s+= "\tTAXSET " ;
+					if (isCurrent)
+						s += "* ";
+					s+= StringUtil.tokenize(taxaSet.getName()) + " ";
+					if (file.getProject().getNumberTaxas()>1)
+						s+= " (TAXA = " +  StringUtil.tokenize(taxa.getName()) + ")";
+					s+= " = "+  sT + ";" + StringUtil.lineEnding();
+				}
+			}
+			return s;
+   	}
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("SETS")) {
+			String s= "";
+	 		for (int ids = 0; ids<file.getProject().getNumberTaxas(); ids++) {
+
+				Taxa taxa =  file.getProject().getTaxa(ids);
+				if (taxa.getFile() == file){
+					int numSets = taxa.getNumSpecsSets(TaxaSelectionSet.class);
+					SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaSelectionSet.class);
+					if (ssv!=null){
+						TaxaSelectionSet ms = (TaxaSelectionSet)taxa.getCurrentSpecsSet(TaxaSelectionSet.class);
+						if (ms!=null && (ms.getNexusBlockStored()==null || blockName.equalsIgnoreCase(ms.getNexusBlockStored()))) {
+							ms.setNexusBlockStored(blockName);
+							ms.setName("UNTITLED");
+							s += nexusStringForSpecsSet(ms, taxa, file, true);
+						}
+						
+							
+						for (int ims = 0; ims<numSets; ims++) {
+							s += nexusStringForSpecsSet((TaxaSelectionSet)taxa.getSpecsSet(ims, TaxaSelectionSet.class), taxa, file, false);
+						}
+					}
+				}
+
+			}
+			return s;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) {
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+
+			String commandName = ParseUtil.getToken(command, startCharT);
+			if (commandName.equalsIgnoreCase("TAXASET") || commandName.equalsIgnoreCase("TAXSET")) {
+				String token = ParseUtil.getToken(command, startCharT);
+				boolean isDefault = false;
+				if ("*".equals(token)) {
+					token = ParseUtil.getToken(command, startCharT);
+					isDefault = true;
+				}
+				String nameOfTypeset = StringUtil.deTokenize(token); // name of typeset 
+				token = ParseUtil.getToken(command, startCharT);
+				String paradigmString = null;
+				Taxa taxa = null;
+				if (token.equalsIgnoreCase("(")) {
+					token = ParseUtil.getToken(command, startCharT); //TAXA  //TODO: check to see what parameter is being set!
+					token = ParseUtil.getToken(command, startCharT); //=
+					token = (ParseUtil.getToken(command, startCharT)); // name of data
+					taxa = file.getProject().getTaxaLastFirst(token);
+					token = ParseUtil.getToken(command, startCharT); //)
+					token = ParseUtil.getToken(command, startCharT);  //=
+				}
+				else if (file.getProject().getNumberTaxas()>0)
+					taxa = file.getProject().getTaxa(file, 0);
+				else  
+					taxa = file.getProject().getTaxa(0);
+
+				if (taxa == null)
+					return false;
+				
+				if (token.equals("="))
+					token = ParseUtil.getToken(command, startCharT); 
+				//TaxaGroup defaultProperty =  null;
+	
+				//TaxaGroup lastCM =new TaxaGroup();
+				//lastCM.setName(token);
+				
+				//lastCM.setGroupNumber(MesquiteInteger.fromString(token));
+		 		TaxaSelectionSet taxaSet= new TaxaSelectionSet(nameOfTypeset, taxa.getNumTaxa(), taxa);
+				taxaSet.setNexusBlockStored(blockName);
+				
+				int lastChar = -1;
+				boolean join = false;
+				while (!token.equals(";") && token.length()>0) {
+					if (token.equals("-")) {
+						if (lastChar!=-1)
+							join = true;
+					}
+					else if (token!=null) {
+						if (token != null && token.equals("."))
+							token = Integer.toString(taxa.getNumTaxa());
+					
+						if (token.startsWith("-")) {
+							if (lastChar!=-1)
+								join = true;
+							token = token.substring(1, token.length());
+						}
+						int whichChar = Taxon.toInternal(MesquiteInteger.fromString(token, false));
+						if (!MesquiteInteger.isCombinable(whichChar)) {
+							whichChar = taxa.whichTaxonNumber(token);
+						}
+						if (MesquiteInteger.isCombinable(whichChar) && whichChar>=0) {
+							if (join) {
+								for (int j = lastChar; j<= whichChar; j++)
+									taxaSet.setSelected(j, true);
+								lastChar = -1;
+								join = false;
+							}
+							else {
+								taxaSet.setSelected(whichChar, true);
+								lastChar = whichChar;
+							}
+						}
+					}
+					token = ParseUtil.getToken(command, startCharT); 
+				}
+				
+				if (isDefault) {
+					if (!"UNTITLED".equals(taxaSet.getName())) {
+			 			taxa.storeSpecsSet(taxaSet, TaxaSelectionSet.class);
+			 		}
+			 		taxaSet.addToFile(file, getProject(), this);
+					taxa.setCurrentSpecsSet(taxaSet, TaxaSelectionSet.class);
+				}
+				else {
+		 			taxa.storeSpecsSet(taxaSet, TaxaSelectionSet.class);
+			 		taxaSet.addToFile(file, getProject(), this);
+			 	}
+			 	return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TSetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage taxon sets";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) taxon sets." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class TSetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && (commandName.equalsIgnoreCase("TAXASET") || commandName.equalsIgnoreCase("TAXSET")));
+	}
+}
+
+
diff --git a/Source/mesquite/basic/MergeTaxa/MergeTaxa.java b/Source/mesquite/basic/MergeTaxa/MergeTaxa.java
new file mode 100644
index 0000000..d148979
--- /dev/null
+++ b/Source/mesquite/basic/MergeTaxa/MergeTaxa.java
@@ -0,0 +1,239 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.MergeTaxa;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class MergeTaxa extends TaxonUtility {
+//	int maxNameLength=30;
+	boolean keepEntireName=true;
+	int startLengthToKeep = 10;
+	int endLengthToKeep = 4;
+	boolean preferencesSet = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("startLengthToKeep".equalsIgnoreCase(tag)) {
+			startLengthToKeep = MesquiteInteger.fromString(content);
+		} else  if ("endLengthToKeep".equalsIgnoreCase(tag)) {
+			endLengthToKeep = MesquiteInteger.fromString(content);
+		} else  if ("keepEntireName".equalsIgnoreCase(tag)) {
+			keepEntireName = MesquiteBoolean.fromOffOnString(content);
+		}  
+
+		preferencesSet = true;
+}
+/*.................................................................................................................*/
+public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "startLengthToKeep", startLengthToKeep);  
+		StringUtil.appendXMLTag(buffer, 2, "endLengthToKeep", endLengthToKeep);  
+		StringUtil.appendXMLTag(buffer, 2, "keepEntireName", keepEntireName);  
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Merge Taxa",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		queryDialog.addLabel("Merge Taxa");
+		
+		Checkbox keepEntireNameBox = queryDialog.addCheckBox("Retain full length of all names", keepEntireName);
+		queryDialog.addLabel("OR");
+		IntegerField startLengthToKeepField = queryDialog.addIntegerField("Number of characters from start of each name to retain:", startLengthToKeep, 6, 0, 200);
+		IntegerField endLengthToKeepField = queryDialog.addIntegerField("Number of characters from end of each name to retain:", endLengthToKeep, 6, 0, 200);
+		
+		queryDialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			keepEntireName = keepEntireNameBox.getState();
+			startLengthToKeep = startLengthToKeepField.getValue();
+			endLengthToKeep = endLengthToKeepField.getValue();
+			storePreferences();
+		}
+		queryDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	/** if returns true, then requests to remain on even after operateOnTaxa is called.  Default is false*/
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Called to operate on the taxa in the block.  Returns true if taxa altered*/
+	public  boolean operateOnTaxa(Taxa taxa){
+		int numSelected = taxa.numberSelected();
+		if (numSelected<2){
+			discreetAlert( "You need to select at least two taxa before merging them.");
+			return false;
+		}
+		int numMatrices = getProject().getNumberCharMatrices(taxa);
+		boolean nonCategFound = false;
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getProject().getCharacterMatrix(taxa, iM);
+			if (!(data instanceof CategoricalData)){
+				nonCategFound = true;
+			}
+		}
+		if (nonCategFound)
+			discreetAlert( "Some character matrices are neither categorical nor molecular (e.g. are continuous, meristic). For these matrices, if more than one of the merged taxa have states in some characters, only the first taxon's states will be kept.");
+
+		if (!MesquiteThread.isScripting()){
+			boolean OK = AlertDialog.query(containerOfModule(), "Merge?", "Are you sure you want to merge the selected taxa?  You will not be able to undo this.  " 
+					+ "Their character states in their character matrices will be merged.  " 
+					+ "Other associated information like footnotes, attachments, and so forth WILL NOT be merged and will be lost from all but the first taxon.");
+			if (!OK)
+				return false;
+			if (!queryOptions())
+				return false;
+		}
+		boolean[] selected = new boolean[taxa.getNumTaxa()];
+
+		for (int it = 0; it<taxa.getNumTaxa(); it++) {
+			selected[it] = taxa.getSelected(it);
+		}
+		int firstSelected = taxa.firstSelected();
+		String originalTaxonName = taxa.getTaxonName(firstSelected);
+		
+	//now let's merge the taxon names
+		StringBuffer sb = new StringBuffer();
+		int count=0;
+		for (int it = 0; it<taxa.getNumTaxa(); it++) {
+			if (selected[it]) {
+				String s = taxa.getTaxonName(it);
+				if (!keepEntireName && startLengthToKeep>0 && endLengthToKeep>0) {
+					if (s.length()>startLengthToKeep+endLengthToKeep) {
+						sb.append(s.substring(0,startLengthToKeep)+s.substring(s.length()-endLengthToKeep));
+					}
+				} else
+					sb.append(s);
+				count++;
+				if (count<numSelected)
+					sb.append("+");
+			}
+		}
+	
+/*
+ * 		if (sb.length()> maxNameLength && !keepEntireName) {
+			int indivLength = maxNameLength / numSelected-1;
+			count=0;
+			sb.setLength(0);
+			if (indivLength<=2) {  // then the pieces are too small; let's just do it based upon the first two
+				indivLength = (maxNameLength-2)/2;
+				for (int it = 0; it<taxa.getNumTaxa(); it++) {
+					if (selected[it]) {
+						String partName = taxa.getTaxonName(it);
+						if (partName.length()>indivLength)
+							sb.append(partName.substring(0, indivLength+1) + "+");
+						else
+							sb.append(partName + "+");
+						count++;
+						if (count>=2)
+							break;
+					}
+				}
+			}
+			else
+				for (int it = 0; it<taxa.getNumTaxa(); it++) {
+					if (selected[it]) {
+						String partName = taxa.getTaxonName(it);
+						if (partName.length()>indivLength)
+							sb.append(partName.substring(0, indivLength+1));
+						else
+							sb.append(partName);
+						count++;
+						if (count<numSelected)
+							sb.append("+");
+					}
+				}
+		}
+		*/
+	//	selected[firstSelected] = false;
+		String report = "";
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getProject().getCharacterMatrix(taxa, iM);
+			boolean[] ma = data.mergeTaxa(firstSelected, selected);
+			if (ma!= null){
+				if (data instanceof CategoricalData)
+					report += "For matrix " + data.getName() + ", the following taxa when merged to taxon \"" + originalTaxonName + "\" required merging of character states:\n";
+				else
+					report += "For matrix " + data.getName() + ", states of the following taxa may have been discarded when merging with taxon \"" + originalTaxonName + "\":\n";
+					
+				for (int it = 0; it< ma.length; it++){
+					if (ma[it])
+						report += "  " + taxa.getTaxonName(it) + "\n";
+				}
+			}
+		}
+		
+		taxa.setTaxonName(firstSelected, sb.toString());
+		
+		for (int it =  taxa.getNumTaxa() -1; it> firstSelected; it--){
+			if (selected[it]) {
+				taxa.deleteTaxa(it, 1, false);
+			}
+		}
+
+		if (!StringUtil.blank(report))
+			alert(report);
+		taxa.notifyListeners(this, new Notification(PARTS_DELETED));
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getProject().getCharacterMatrix(taxa, iM);
+			data.notifyListeners(this, new Notification(PARTS_DELETED));
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Merge Taxa";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Merge Taxa...";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Merges selected taxa and their character states.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/basic/NextProject/NextProject.java b/Source/mesquite/basic/NextProject/NextProject.java
new file mode 100644
index 0000000..6fa5b3d
--- /dev/null
+++ b/Source/mesquite/basic/NextProject/NextProject.java
@@ -0,0 +1,251 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.NextProject;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+
+public class NextProject extends FileAssistant  {
+	public String nextProjectName = null;
+	NextProjectWindow npw;
+	Color bgColor;
+	MesquiteFile file;
+	/*public Class getDutyClass(){
+		return NextProject.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		
+		setModuleWindow( npw = new NextProjectWindow(this));
+		npw.setMinimalMenus(true);
+		if (!MesquiteThread.isScripting()){
+			getModuleWindow().setVisible(true);
+		}
+		
+		if (MesquiteThread.isScripting() && CommandRecord.getScriptingFileS()!=null) {
+			file = CommandRecord.getScriptingFileS();
+			file.addListener(this);
+		}
+		makeMenu("Go-To-File");
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Background Color", makeCommand("setBackground",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+ 		resetContainingMenuBar();
+ 		resetAllWindowsMenus();
+ 		return true;
+ 	}
+		/*.................................................................................................................*/
+	 public String getExplanation() {
+	return "Provides a window to jump to another file";
+	 }
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (file == obj)
+			windowGoAway(npw);
+	}
+	/*.................................................................................................................*/
+ 	public void endJob() {
+			if (npw != null) {
+				npw.hide();
+				npw.dispose();
+			}
+			if (file !=null)
+				file.removeListener(this);
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	if (npw !=null){
+			if (!StringUtil.blank(npw.getText()))
+			   	 		temp.addLine("setNextFileName " + StringUtil.tokenize(npw.getText()));
+			if (!StringUtil.blank(npw.getJumpExplanation()))
+			   	 		temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+			//temp.addLine("makeWindow");
+   			temp.addLine("getWindow");
+			temp.addLine("tell It");
+	  	 	Snapshot fromWindow = npw.getSnapshot(file);
+	  	 	temp.incorporate(fromWindow, true);
+			temp.addLine("endTell");
+	  	 	if (bgColor !=null) {
+	  	 		String bName = ColorDistribution.getStandardColorName(bgColor);
+	  	 		if (bName!=null)
+	  	 			temp.addLine("setBackground " + StringUtil.tokenize(bName));
+	  	 	}
+				
+			temp.addLine("showWindow");
+		}
+    	 	else {
+    	 	if (!StringUtil.blank(nextProjectName))
+   	 		temp.addLine("setNextFileName " + StringUtil.tokenize(nextProjectName));
+   	 	}
+		if (!StringUtil.blank(npw.getJumpExplanation()))
+		   	 		temp.addLine("setExplanation " + StringUtil.tokenize(npw.getJumpExplanation()));
+	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the file name to which to jump when the button is hit", "[path to file; if relative than to home file of project]", commandName, "setNextFileName")) {
+			if (npw == null)
+				return null;
+    	 		nextProjectName =parser.getFirstToken(arguments);
+    	 		((NextProjectWindow)getModuleWindow()).setText(nextProjectName);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets explanation to appear in text edit area", "[explanation string]", commandName, "setExplanation")) {
+			if (npw == null)
+				return null;
+    	 		((NextProjectWindow)getModuleWindow()).setJumpExplanation(parser.getFirstToken(arguments));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Jumps to next project recorded", null, commandName, "go")) {
+    	 		nextProjectName = ((NextProjectWindow)getModuleWindow()).getText();
+   	 		if (StringUtil.blank(nextProjectName))
+   	 			return null;
+   	 		while (getProject().developing)
+   	 			;
+			String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; openFile ";
+			commands +=  StringUtil.tokenize(MesquiteFile.composePath(getProject().getHomeDirectoryName(), nextProjectName)) + "; ifNotExists It;  debug; showAbout; endIf; windowAutoShow *String.was; endTell;";
+			Puppeteer p = new Puppeteer(this);
+			MesquiteInteger pos = new MesquiteInteger(0);
+			p.execute(getFileCoordinator(), commands, pos, "", false);
+			iQuit();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets background color of window", "[name of color]", commandName, "setBackground")) {
+    	 		Color bc = ColorDistribution.getStandardColor(parser.getFirstToken(arguments));
+			if (bc == null)
+				return null;
+			bgColor = bc;
+			if (npw == null)
+				return null;
+			npw.setColor(bc);
+			if (npw.isVisible())
+				npw.repaint();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "NOT USED", null, commandName, "makeWindow")) {
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+			whichWindow.dispose();
+			iQuit();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Go-to Window";
+   	 }
+	public boolean isSubstantive(){
+		return false;
+	}
+   	 
+}
+
+/* ======================================================================== */
+class NextProjectWindow extends MesquiteWindow {
+	TextField tF;
+	TextArea explanation;
+	public NextProjectWindow(NextProject module) {
+		super(module, false);
+		
+		setWindowSize(120, 60);
+		setBackground(ColorDistribution.lightGreen);
+		Panel contents = getGraphicsArea();
+		contents.setLayout(new BorderLayout());
+		contents.setBackground(ColorDistribution.lightGreen);
+		
+		explanation= new TextArea("", 8, 3, TextArea.SCROLLBARS_NONE);
+		tF= new TextField();
+   	 	if (!StringUtil.blank(module.nextProjectName))
+   	 		tF.setText(module.nextProjectName);
+		tF.setEditable(true);
+		tF.setBackground(ColorDistribution.lightGreen);
+		contents.add("North", tF);
+		contents.add("Center", explanation);
+		tF.setVisible(true);
+		Panel buttons = new Panel();
+		Font f = explanation.getFont();
+ 		if (f!=null){
+	 		Font fontToSet = new Font (f.getName(), f.getStyle(), f.getSize()+4);
+	 		if (fontToSet!= null) {
+	 			explanation.setFont(fontToSet);
+	 		}
+ 		}
+		contents.add("South", buttons);
+		Button ok;
+		buttons.add("South", ok = new WindowButton("Go", this));
+		Font df = new Font("Dialog", Font.PLAIN, 12);
+		ok.setFont(df);
+		
+		setWindowSize(120, 60);
+		resetTitle();
+		
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Go To File");
+	}
+	
+	public void setColor(Color c){
+		if (tF == null)
+			return;
+		setBackground(c);
+		tF.setBackground(c);
+		Panel contents = getGraphicsArea();
+		contents.setBackground(c);
+		repaintAll();
+	}
+	public void setText(String s) {
+		if (tF == null)
+			return;
+		tF.setText(s);
+		tF.repaint();
+		repaint();
+	}
+	public String getText() {
+		if (tF == null)
+			return null;
+		return tF.getText();
+	}
+	public void setJumpExplanation(String s) {
+		if (explanation == null)
+			return;
+		explanation.setText(s);
+		explanation.repaint();
+		repaint();
+	}
+	public String getJumpExplanation() {
+		if (explanation == null)
+			return null;
+		return explanation.getText();
+	}
+	/*=============*/
+	public void buttonHit(String label, Button button) {
+		if (label.equalsIgnoreCase("Go")) {
+			getOwnerModule().doCommand("Go", null,  CommandChecker.defaultChecker);
+		}
+	}
+}
+
diff --git a/Source/mesquite/basic/PrefixTaxonNameWithGroup/PrefixTaxonNameWithGroup.java b/Source/mesquite/basic/PrefixTaxonNameWithGroup/PrefixTaxonNameWithGroup.java
new file mode 100644
index 0000000..3a557a6
--- /dev/null
+++ b/Source/mesquite/basic/PrefixTaxonNameWithGroup/PrefixTaxonNameWithGroup.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.PrefixTaxonNameWithGroup;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class PrefixTaxonNameWithGroup extends TaxonNameAlterer {
+	TaxaPartition currentPartition=null;
+	TaxaGroup tg = null;
+	Taxa currentTaxa = null;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true; 
+	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		
+    	if (taxa!=currentTaxa){
+    		currentTaxa=taxa;
+    		currentPartition=null;
+    	}
+		if (currentPartition==null)
+			currentPartition = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+		if (currentPartition!=null){
+			tg = currentPartition.getTaxaGroup(it);
+		}
+		if (tg==null) return false;
+		
+    	
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String groupName = tg.getName();
+			if (StringUtil.notEmpty(groupName)){
+					taxa.setTaxonName(it, groupName + "." + name, false);
+			}
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Appends numbers to taxon names", "[length]", commandName, "appendNumbers")) {
+	   	 		if (taxa !=null){
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Prefix with Taxon Group Name";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Prefixes the taxon name with the taxon group name.";
+   	 }
+ 	/*.................................................................................................................*/
+ 	public boolean isPrerelease(){
+ 		return false;  
+ 	}
+ 	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+ 	public int getVersionOfFirstRelease(){
+ 		return 300;  
+ 	}
+}
+
+
+	
+
diff --git a/Source/mesquite/basic/PrefixedStringMatcher/PrefixedStringMatcher.java b/Source/mesquite/basic/PrefixedStringMatcher/PrefixedStringMatcher.java
new file mode 100644
index 0000000..c82a8ed
--- /dev/null
+++ b/Source/mesquite/basic/PrefixedStringMatcher/PrefixedStringMatcher.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.PrefixedStringMatcher;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class PrefixedStringMatcher extends StringMatcher {
+	String prefix = "DNA";
+	int charAfterPrefix = 4;
+
+	public boolean loadModule() {  
+		return false;
+	}
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/** returns true if the options are set and accepted.*/
+	public  boolean queryOptions(){
+			if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying Options")) 
+				return true;
+
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Match Text After Prefix",buttonPressed); 
+
+			SingleLineTextField prefixField = dialog.addTextField("Prefix before characters to compare", prefix, 15);
+			IntegerField charAfterPrefixField = dialog.addIntegerField("Number of characters to compare after prefix", charAfterPrefix, 8, 1, MesquiteInteger.infinite);
+
+			dialog.completeAndShowDialog(true);
+
+			if (buttonPressed.getValue()==0)  {
+				charAfterPrefix=charAfterPrefixField.getValue();
+				prefix= prefixField.getText();
+			}
+			dialog.dispose();
+
+			return (buttonPressed.getValue()==0 && charAfterPrefix>0);
+	}
+	public boolean stringsMatch(String s1, String s2) {
+		if (StringUtil.blank(prefix)) 
+			return false;
+		int location1 = s1.indexOf(prefix);
+		int location2 = s2.indexOf(prefix);
+		if (location1<0 || location2 < 0)
+			return false;
+		String nextChars1 = null;
+		String nextChars2 = null;
+		try {
+			nextChars1 = s1.substring(location1+prefix.length(),location1+prefix.length()+charAfterPrefix);
+			nextChars2 = s2.substring(location2+prefix.length(),location2+prefix.length()+charAfterPrefix);
+		}
+		catch (Exception e) {
+			return false;
+		}
+		if (StringUtil.blank(nextChars1) || StringUtil.blank(nextChars2))
+			return false;
+		return nextChars1.equalsIgnoreCase(nextChars2);
+	}
+
+
+	public Class getDutyClass() {
+		return StringMatcher.class;
+	}
+
+	public String getName() {
+		return "Match Text After Prefix";
+	}
+	public String getExplanation() {
+		return "Judges two text strings to match if it finds the same text in a specified number of characters after the first occurence of a designated prefix.";
+	}
+
+}
diff --git a/Source/mesquite/basic/RawNexusBlockEditor/RawNexusBlockEditor.java b/Source/mesquite/basic/RawNexusBlockEditor/RawNexusBlockEditor.java
new file mode 100644
index 0000000..9b867a7
--- /dev/null
+++ b/Source/mesquite/basic/RawNexusBlockEditor/RawNexusBlockEditor.java
@@ -0,0 +1,102 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.RawNexusBlockEditor;
+
+import java.util.*;
+import java.io.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class RawNexusBlockEditor extends EditRawNexusBlock {
+	NexusBlockEditableRaw currentlyEdited = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	if (getModuleWindow()!=null && getModuleWindow().isVisible()) {
+	   	 	Snapshot temp = new Snapshot();
+			temp.addLine("getWindow");
+	  	 	Snapshot fromWindow = getModuleWindow().getSnapshot(file);
+			temp.addLine("tell It");
+			temp.incorporate(fromWindow, true);
+			temp.addLine("endTell");
+			temp.addLine("showWindow");
+	 	 	return temp;
+ 	 	}
+ 	 	else return null;
+  	 }
+  	
+  	 public void windowGoAway(MesquiteWindow whichWindow) {
+ 		if (whichWindow == null)
+			return;
+		if (currentlyEdited!=null) {
+  	 		currentlyEdited.setText( ((MesquiteTextWindow)getModuleWindow()).getText());
+  	 	}
+  	 	currentlyEdited = null;
+  	 	getModuleWindow().hide();
+  	 	//window.dispose();
+  	 }
+	public void recordBlock(NexusBlockEditableRaw block){
+
+		if (block == currentlyEdited && currentlyEdited!=null && getModuleWindow()!=null){
+  	 		currentlyEdited.setText( ((MesquiteTextWindow)getModuleWindow()).getText());
+  	 	}
+	}
+   	public NexusBlockEditableRaw getCurrentBlock(){
+   		return currentlyEdited;
+   	}
+	
+	public void editNexusBlock(NexusBlockEditableRaw block, boolean recordCurrent){
+			if (block==null)
+				return;
+			if (getModuleWindow()==null) {
+				setModuleWindow( new MesquiteTextWindow(this, block.getBlockName() + " Block: " + block.getName(), true)); //infobar
+				getModuleWindow().setWindowSize(300,300);
+		 		resetContainingMenuBar();
+				resetAllWindowsMenus();
+			}
+			else {
+				//if getModuleWindow() already open, then store contents and switch contents
+				if (getModuleWindow().isVisible() && recordCurrent && currentlyEdited!=null) {
+					currentlyEdited.setText(((MesquiteTextWindow)getModuleWindow()).getText());
+				}
+				getModuleWindow().setTitle(block.getName());
+			}
+			currentlyEdited=block;
+			((MesquiteTextWindow)getModuleWindow()).setText(currentlyEdited.getText());
+			((MesquiteTextWindow)getModuleWindow()).setEditable(true);
+			//getModuleWindow().setVisible(true); TODO: pass scripting
+	}
+	public String getCurrentContents(){
+		if (getModuleWindow()!=null && getModuleWindow().isVisible())
+  	 		return ((MesquiteTextWindow)getModuleWindow()).getText();
+  	 	return null;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Raw Nexus block editor";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Edits blocks in a NEXUS file." ;
+   	 }
+}
+
diff --git a/Source/mesquite/basic/RemoveFromTaxonNames/RemoveFromTaxonNames.java b/Source/mesquite/basic/RemoveFromTaxonNames/RemoveFromTaxonNames.java
new file mode 100644
index 0000000..689fb34
--- /dev/null
+++ b/Source/mesquite/basic/RemoveFromTaxonNames/RemoveFromTaxonNames.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.RemoveFromTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RemoveFromTaxonNames extends TaxonNameAlterer {
+	int truncLength = 1;
+	MesquiteBoolean removeFromEnd = new MesquiteBoolean(true);
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Remove from names",  buttonPressed);
+		queryDialog.addLabel("Remove text from taxon names", Label.CENTER);
+		SingleLineTextField truncationLengthField = queryDialog.addTextField("Number of characters to remove:", ""+truncLength, 20);
+		Checkbox removeFromEndBox = queryDialog.addCheckBox("remove from end of names", removeFromEnd.getValue());
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			String s = truncationLengthField.getText();
+			truncLength = MesquiteInteger.fromString(s);
+			if (!MesquiteInteger.isCombinable(truncLength))
+				ok = false;
+			if (truncLength<0)
+				truncLength=0;
+			removeFromEnd.setValue(removeFromEndBox.getState());
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null && name.length()>truncLength){
+			String trunced;
+			if (removeFromEnd.getValue())
+				trunced =  name.substring(0, name.length()-truncLength);
+			else
+				trunced =  name.substring(truncLength, name.length());
+			taxa.setTaxonName(it, trunced, false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Removes text from taxon names", "[length]", commandName, "removeText")) {
+	   	 		if (taxa !=null){
+	   	 			 truncLength = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+    	 				removeFromEnd.toggleValue(parser.getNextToken());
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Remove from Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Remove from Taxon Names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Removes a specified number of characters from taxon names.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/RemoveTokensTaxonNames/RemoveTokensTaxonNames.java b/Source/mesquite/basic/RemoveTokensTaxonNames/RemoveTokensTaxonNames.java
new file mode 100644
index 0000000..a0a5a14
--- /dev/null
+++ b/Source/mesquite/basic/RemoveTokensTaxonNames/RemoveTokensTaxonNames.java
@@ -0,0 +1,184 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.basic.RemoveTokensTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.JLabel;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RemoveTokensTaxonNames extends TaxonNameAlterer implements KeyListener {
+	int numStart = 0;
+	int numEnd = 0;
+	IntegerField startTokensField = null;
+	IntegerField endTokensField = null;
+	JLabel currentName, alteredName;
+	int firstTaxon = 0;
+	Taxa currentTaxa = null;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}	
+
+	/*.................................................................................................................*/
+	public void checkFields() {
+		if (currentTaxa==null)
+			return;
+		String name = currentTaxa.getName(firstTaxon);
+		MesquiteString newName = new MesquiteString();
+		numStart = startTokensField.getValue();
+		numEnd = endTokensField.getValue();
+		boolean nameChanged = getNewName(currentTaxa, firstTaxon, newName);
+		if (nameChanged)
+			name = newName.getValue();
+		alteredName.setText("Modified Name: " + name);	
+		alteredName.repaint();
+	}
+	/*.................................................................................................................*/
+	public void keyPressed(KeyEvent e) {
+	}
+
+	public void keyReleased(KeyEvent e) {
+		checkFields();
+	}
+
+	public void keyTyped(KeyEvent e) {
+		checkFields();
+	}
+
+	/*.................................................................................................................*/
+	public boolean getOptions(Taxa taxa, int firstSelected){
+		if (MesquiteThread.isScripting())
+			return true;
+		if (MesquiteInteger.isCombinable(firstSelected))
+			firstTaxon = firstSelected;
+		currentTaxa = taxa;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Remove tokens",  buttonPressed);
+		queryDialog.addLabel("Remove Tokens", Label.CENTER);
+		startTokensField = queryDialog.addIntegerField("Number of tokens to remove from start", numStart, 4,0,1000);
+		startTokensField.addKeyListener(this);
+		endTokensField = queryDialog.addIntegerField("Number of tokens to remove from end", numEnd, 4,0,1000);
+		endTokensField.addKeyListener(this);
+		queryDialog.addHorizontalLine(2);
+		queryDialog.addLabel("Preview of first taxon name to be changed:");
+		currentName = queryDialog.addLabel("");	
+		alteredName = queryDialog.addLabel("");	
+		String name = currentTaxa.getName(firstTaxon);
+		currentName.setText("Current Name: " + name);		
+		checkFields();
+		queryDialog.addHorizontalLine(2);
+		queryDialog.addLargeOrSmallTextLabel("Hint: before doing this, you may want to archive current names using Archive Taxon Names under Taxon Utilities in the Character Matrix Editor or the List of Taxa window" );
+		queryDialog.completeAndShowDialog(true);
+
+		boolean ok = (queryDialog.query()==0);
+
+		if (ok) {
+			numStart = startTokensField.getValue();
+			numEnd = endTokensField.getValue();
+		}
+
+		queryDialog.dispose();
+
+		return ok;
+	}
+	/*.................................................................................................................*/
+	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+	public boolean getNewName(Taxa taxa, int it, MesquiteString ms){
+		if (ms==null)
+			return false;
+		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			Parser parser = new Parser();
+			//	parser.setWhitespaceString("|");
+			parser.addToDefaultPunctuationString("|");
+			parser.setString(name);
+
+			for (int i=0; i<numEnd; i++) {
+				String token = parser.getLastToken();
+				if (token != null){
+					int pos = name.indexOf(token);
+					if (pos>=0) {
+						name = name.substring(0, pos);
+						nameChanged = true;
+					}
+				}
+				parser.setString(name);
+			}
+			for (int i=0; i<numStart; i++) {
+				String token = parser.getFirstToken();
+				if (token != null){
+					int pos = name.indexOf(token);
+					if (pos>=0) {
+						name = name.substring(pos+token.length());
+						nameChanged = true;
+					}
+				}
+				parser.setString(name);
+			}
+			if (nameChanged){
+				name = name.trim();
+				ms.setValue(name);
+			}
+
+		}
+		return nameChanged;
+	}
+	/*.................................................................................................................*/
+	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+	public boolean alterName(Taxa taxa, int it){
+		MesquiteString newName = new MesquiteString();
+		boolean nameChanged = getNewName(taxa, it, newName);
+		if (nameChanged)
+			taxa.setTaxonName(it, newName.getValue(), false);
+		return nameChanged;
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Remove Tokens...";
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Remove Tokens";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Removes tokens from start or end of the taxon name.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/basic/ReplaceInTaxonNames/ReplaceInTaxonNames.java b/Source/mesquite/basic/ReplaceInTaxonNames/ReplaceInTaxonNames.java
new file mode 100644
index 0000000..57e6185
--- /dev/null
+++ b/Source/mesquite/basic/ReplaceInTaxonNames/ReplaceInTaxonNames.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ReplaceInTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== 
+*new in 1.02* */
+public class ReplaceInTaxonNames extends TaxonNameAlterer {
+	String searchText="";
+	String replaceText = "";
+//	MesquiteBoolean addToEnd = new MesquiteBoolean(true);
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Replace in Taxon Names",  buttonPressed);
+		queryDialog.addLabel("Replace in Taxon Name", Label.CENTER);
+		SingleLineTextField searchField = queryDialog.addTextField("Search for:", searchText, 12, true);
+		SingleLineTextField replaceField = queryDialog.addTextField("Replace with:", replaceText, 12, true);
+	//	Checkbox addToEndBox = queryDialog.addCheckBox("add to end of names", addToEnd.getValue());
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			searchText = searchField.getText();
+			replaceText = replaceField.getText();
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String s=StringUtil.replace(name,searchText,replaceText);
+			taxa.setTaxonName(it, s, false);
+			nameChanged = !name.equals(s);
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Replaces text in taxon names", "[text]", commandName, "replaceText")) {
+	   	 		if (taxa !=null){
+	   	 			 searchText = parser.getFirstToken(arguments);
+	   	 			 replaceText = parser.getFirstToken(arguments);
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Replace in Name...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Replaces text in taxon names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Replaces text in taxon names.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/SearchNameTaxonSelector/SearchNameTaxonSelector.java b/Source/mesquite/basic/SearchNameTaxonSelector/SearchNameTaxonSelector.java
new file mode 100644
index 0000000..5b24e9c
--- /dev/null
+++ b/Source/mesquite/basic/SearchNameTaxonSelector/SearchNameTaxonSelector.java
@@ -0,0 +1,121 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.SearchNameTaxonSelector;
+
+import java.awt.Button;
+import java.awt.Checkbox;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.TaxonSelector;
+
+public class SearchNameTaxonSelector extends TaxonSelector {
+	String matchString = "";
+	boolean caseSensitive = false;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (!MesquiteThread.isScripting())
+			if (!queryOptions())
+				return false;
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("matchString".equalsIgnoreCase(tag)) 
+			matchString = StringUtil.cleanXMLEscapeCharacters(content);
+		if ("caseSensitive".equalsIgnoreCase(tag))
+			caseSensitive = MesquiteBoolean.fromTrueFalseString(content);
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "matchString", matchString);  
+		StringUtil.appendXMLTag(buffer, 2, "caseSensitive", caseSensitive);  
+		return buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Select Taxa by Name Search",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+
+		dialog.addLabel("Select Taxa by Name Search");
+
+		SingleLineTextField matchField = dialog.addTextField("Search string:", matchString, 20);
+		Checkbox caseSensitiveBox = dialog.addCheckBox("case sensitive", caseSensitive);
+
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			matchString = matchField.getText();
+			caseSensitive = caseSensitiveBox.getState();
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0) ;
+	}
+
+	public boolean match(String name, String matchString) {
+		if (StringUtil.blank(matchString) || StringUtil.blank(name))
+			return false;
+		if (!caseSensitive) {
+			return (name.toLowerCase().indexOf(matchString.toLowerCase())>=0);
+		}
+		else return (name.indexOf(matchString)>=0);
+	}
+
+	public void selectTaxa(Taxa taxa, CharacterData data) {
+		selectTaxa(taxa);
+	}
+
+	public void selectTaxa(Taxa taxa) {
+		if (taxa==null)
+			return;
+		boolean changed = false;
+		for (int it = 0; it<taxa.getNumTaxa(); it++)
+			if (match(taxa.getTaxonName(it), matchString)) {
+					taxa.setSelected(it, true);
+					changed = true;
+			}
+		if (changed)
+			taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+	}
+
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	public String getName() {
+		return "Select Taxa from Name Search";
+	}
+	public String getNameForMenuItem() {
+		return "Select Taxa from Name Search...";
+	}
+	public String getExplanation() {
+		return "Select taxa based upon a name search.";
+	}
+
+
+}
diff --git a/Source/mesquite/basic/ShowText/ShowText.java b/Source/mesquite/basic/ShowText/ShowText.java
new file mode 100644
index 0000000..6160109
--- /dev/null
+++ b/Source/mesquite/basic/ShowText/ShowText.java
@@ -0,0 +1,155 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.ShowText;
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class ShowText extends TextDisplayer {
+	boolean goAwayable;
+	boolean wrap = true;
+	boolean allowPaste = false;
+	int poppedOut = 2;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	
+	public void setWrap(boolean w){
+		this.wrap = w;
+	}
+	public void setAllowPaste(boolean w){
+		this.allowPaste = w;
+	}
+	public void showFile(String pathName, int maxCharacters, boolean goAwayable, int fontSize, boolean monospaced){
+		String s = MesquiteFile.getFileContentsAsString(pathName, maxCharacters);
+		showText(s, pathName, goAwayable, fontSize, monospaced);
+	}
+	public void showFile(String pathName, int maxCharacters, boolean goAwayable){
+		String s = MesquiteFile.getFileContentsAsString(pathName, maxCharacters);
+		showText(s, pathName, goAwayable);
+	}
+	public void showFile(MesquiteFile file, int maxCharacters, boolean goAwayable, int fontSize, boolean monospaced){
+		String s = file.getFileContentsAsString(maxCharacters);
+		showText(s, file.getFileName(), goAwayable, fontSize, monospaced);
+	}
+	public void showFile(MesquiteFile file, int maxCharacters, boolean goAwayable){
+		String s = file.getFileContentsAsString(maxCharacters);
+		showText(s, file.getFileName(), goAwayable);
+	}
+	public void showText(String s, String title, boolean goAwayable){
+		showText(s,title,goAwayable, 0, false);
+	}
+	public void setPoppedOut(int w){
+		poppedOut = w;
+	}
+	public void showText(String s, String title, boolean goAwayable, int fontSize, boolean monospaced){
+		this.goAwayable = goAwayable;
+		if (s == null)
+			s = "(No Text to show)";
+		if (getModuleWindow()==null) {
+			setModuleWindow( new MesquiteTextWindow(this, title, true, wrap, allowPaste)); 
+			((MesquiteTextWindow)getModuleWindow()).setText(s);
+			if (poppedOut > 0){
+				if (poppedOut==1)
+					getModuleWindow().setPopAsTile(true);
+				getModuleWindow().popOut(false);
+			}
+			getModuleWindow().setWindowSize(500, 500);
+			if (fontSize>0)
+				getModuleWindow().setWindowFontSize(fontSize);
+			if (monospaced) {
+				((MesquiteTextWindow)getModuleWindow()).setWindowFont("Monospaced");
+			}
+			getModuleWindow().setVisible(true);
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+		else {
+			((MesquiteTextWindow)getModuleWindow()).setText(s);
+		}
+	}
+	/*.................................................................................................................
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	if (window!= null && window.isVisible())
+  	 		temp.addLine("showScript "); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), nullxxx, null, commandName, "showScript")) {  
+    	 		MesquiteBlock b = null;
+    	 		if (blocks == null) {
+    	 			b = makeBlock(null, "BEGIN MESQUITE;\nEND;"); //TODO: into which file assigned? (dialog box if more than one file opened)
+    	 		}
+    	 		else if (StringUtil.blank(arguments)) {
+	    	 			//have dialog requesting which??
+	    	 			b = ((MesquiteBlock)blocks.elementAt(0));
+	    	 	}
+	    	 	else {
+    	 			int whichBlock = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+	    	 		if (whichBlock >=0 && whichBlock < blocks.size())
+	    	 			b = ((MesquiteBlock)blocks.elementAt(whichBlock));
+   	 		}
+    	 		if (b!=null) {
+	    			if (window==null)
+	    				window = new MesquiteTextWindow(this, "Mesquite script", false); //infobar
+	    			((MesquiteTextWindow)window).setText(b.getText());
+	    			currentBlock = b;
+	    			((MesquiteTextWindow)window).setEditable(true);
+	    			window.setVisible(true);
+	    			return window;
+    			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), nullxxx, null, commandName, "getSnapshots")) {  
+    	 		int w = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		MesquiteModule mb = MesquiteTrunk.mesquiteTrunk.findEmployeeWithIDNumber(w);
+    	 		if (mb!=null) {
+    	 			return getSnapshotCommands(mb, null, "\t");
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+   	
+ 	/*.................................................................................................................*/
+  	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+  		if (goAwayable && whichWindow == getModuleWindow()) {
+    			whichWindow.hide();
+    			whichWindow.dispose();
+    			iQuit();
+    		}
+   	}
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Show text";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shows text in a window" ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/basic/StoredTaxonPairs/StoredTaxonPairs.java b/Source/mesquite/basic/StoredTaxonPairs/StoredTaxonPairs.java
new file mode 100644
index 0000000..603c590
--- /dev/null
+++ b/Source/mesquite/basic/StoredTaxonPairs/StoredTaxonPairs.java
@@ -0,0 +1,197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.StoredTaxonPairs;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies taxa from taxa blocks stored in the project.*/
+public class StoredTaxonPairs extends TaxonPairSource implements MesquiteListener {
+	int currentTaxonPair=0;
+	Taxa currentTaxa = null;
+	TreesManager manager;
+	MesquiteSubmenuSpec listSubmenu;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because no blocks of taxa are available.");
+		//listSubmenu = addSubmenu(null, "Taxa", makeCommand("setTaxaInt",  this), getProject().getTaxas());
+		return true;
+  	 }
+	 public void resetCurrentTaxa(Taxa taxa){
+		 if (currentTaxa!=null)
+			 currentTaxa.removeListener(this);
+		 currentTaxa = taxa;
+		 if (currentTaxa!=null)
+			 currentTaxa.addListener(this);
+	 }
+ 	 public void initialize(Taxa taxa){
+	 		if (taxa !=currentTaxa || currentTaxa == null)
+	 				resetCurrentTaxa(taxa);
+  	 }
+   	public Selectionable getSelectionable(){
+   		return currentTaxa;
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(currentTaxa)); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 /*
+disabled in 1. 06 because wasn't working (too many functions made early commitment to taxa which couldn't be changed
+    	 	if (checker.compare(this.getClass(), "Sets which block of taxa to use (0 based, for internal use)", "[block number]", commandName, "setTaxaInt")) { //need separate from setTreeBlock since this is used internally with 0-based menu response
+    	 		int whichList = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (MesquiteInteger.isCombinable(whichList)) {
+	    	 		if (currentTaxa!=null)
+	    	 			currentTaxa.removeListener(this);
+	    	 		currentTaxa = getProject().getTaxa(checker.getFile(), whichList);
+	    	 		if (currentTaxa!=null)
+	    	 			currentTaxa.addListener(this);
+	    	 		parametersChanged();
+	 			return currentTaxa;
+ 			}
+    	 	}
+    	 	else */
+    	 	if (checker.compare(this.getClass(), "Sets which block of taxa to use", "[block reference, number, or name]", commandName, "setTaxa")) {
+   	 		Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+   	 		if (t!=null){
+   	 			resetCurrentTaxa(t);
+				parametersChanged();
+	   	 		return currentTaxa;
+   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+  	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	 public void endJob(){
+   		if (currentTaxa !=null)
+   			currentTaxa.removeListener(this);
+   	 	super.endJob();
+   	 }
+	/** passes which object changed, along with optional integer (e.g. for character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (!doomed && obj==currentTaxa && !(code == MesquiteListener.SELECTION_CHANGED || code == MesquiteListener.ANNOTATION_CHANGED || code == MesquiteListener.ANNOTATION_ADDED || code == MesquiteListener.ANNOTATION_DELETED))
+			parametersChanged(notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)currentTaxa == obj)
+			iQuit();
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+  	boolean first = true;
+  
+   	
+  	/*.................................................................................................................*/
+  	public int getFirstTaxonNumberOfPair(Taxa taxa, int iPair) {
+  		int count = 0;
+  		for (int first = 1; first<getNumberOfTaxonPairs(taxa); first++) {
+  			for (int second = 0; second<first; second++) {
+  				if (count==iPair)
+  					return first;
+  				count++;
+  			}
+  		}
+  		return taxa.getNumTaxa()-1;
+  	}
+	/*.................................................................................................................*/
+  	public int getSecondTaxonNumberOfPair(Taxa taxa, int iPair) {
+ 		int count = 0;
+  		for (int first = 1; first<getNumberOfTaxonPairs(taxa); first++) {
+  			for (int second = 0; second<first; second++) {
+  				if (count==iPair)
+  					return second;
+  				count++;
+  			}
+  		}
+  		return taxa.getNumTaxa()-2;
+ 	}
+ 	/*.................................................................................................................*/
+   	public TaxonPair getCurrentTaxonPair(Taxa taxa) {
+   		if (taxa==null)
+   			return null;
+ 		if (taxa !=currentTaxa || taxa == null){
+ 			resetCurrentTaxa(taxa);
+   		}
+   		if (currentTaxonPair<0 || currentTaxonPair>getNumberOfTaxonPairs(taxa))   			return null;
+   		int t1 = getFirstTaxonNumberOfPair(taxa, currentTaxonPair);
+   		int t2 = getSecondTaxonNumberOfPair(taxa,currentTaxonPair);
+   		return new TaxonPair(taxa,t1,t2);
+   	}
+	/*.................................................................................................................*/
+   	public TaxonPair getTaxonPair(Taxa taxa, int iPair) {
+   		currentTaxonPair=iPair;
+  		int t1 = getFirstTaxonNumberOfPair(taxa, currentTaxonPair);
+   		int t2 = getSecondTaxonNumberOfPair(taxa, currentTaxonPair);
+   		return new TaxonPair(taxa,t1,t2);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTaxonPairs(Taxa taxa) {
+		if (taxa==null)
+			return 0;
+		else {
+	   		 int numTaxa = taxa.getNumTaxa();
+	   		 return (numTaxa*numTaxa - numTaxa)/2;
+		}
+  	}
+   
+	/*.................................................................................................................*/
+    	 public String getTaxonPairName(Taxa taxa, int iPair) {
+		if (taxa==null)
+			return null;
+		else {
+	 		int t1 = getFirstTaxonNumberOfPair(taxa, iPair);
+	   		int t2 = getSecondTaxonNumberOfPair(taxa, iPair);
+			return taxa.getTaxonName(t1)+"/" + taxa.getTaxonName(t2);
+		}
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stored Taxon Pairs";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies taxon pairs stored, for instance in a file.";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return true;
+     	}
+
+}
+
diff --git a/Source/mesquite/basic/SuffixTaxonNames/SuffixTaxonNames.java b/Source/mesquite/basic/SuffixTaxonNames/SuffixTaxonNames.java
new file mode 100644
index 0000000..a37bfb8
--- /dev/null
+++ b/Source/mesquite/basic/SuffixTaxonNames/SuffixTaxonNames.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.SuffixTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class SuffixTaxonNames extends TaxonNameAlterer {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return false; //for scripting
+	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			name += (it+1);
+			taxa.setTaxonName(it, name, false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Appends numbers to taxon names", "[length]", commandName, "appendNumbers")) {
+	   	 		if (taxa !=null){
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Append Numbers";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Append numbers";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Appends to each taxon name the number of the taxon. This will ensure that each taxon name is unique.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/TaxaSelCoordinator/TaxaSelCoordinator.java b/Source/mesquite/basic/TaxaSelCoordinator/TaxaSelCoordinator.java
new file mode 100644
index 0000000..e5e4da7
--- /dev/null
+++ b/Source/mesquite/basic/TaxaSelCoordinator/TaxaSelCoordinator.java
@@ -0,0 +1,144 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.TaxaSelCoordinator;
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaSelCoordinator extends TaxaSelectCoordinator {
+	Taxa taxa=null;
+	MesquiteTable table = null;
+	boolean rows = true;
+	Object dataCondition;
+	MesquiteSubmenuSpec mss = null;
+	MesquiteSubmenuSpec mssc = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Select All Taxa", makeCommand("selectAll",  this));
+		addMenuItem("Deselect All Taxa", makeCommand("deselectAll",  this));
+		addMenuItem("Reverse taxon selection", makeCommand("reverse",  this));
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects all taxa", null, commandName, "selectAll")) {
+			if (taxa !=null && table!=null) {
+ 				for (int i=0; i<taxa.getNumTaxa(); i++)
+ 					taxa.setSelected(i, true);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Deselects all taxa", null, commandName, "deselectAll")) {
+			if (taxa !=null && table!=null) {
+ 				for (int i=0; i<taxa.getNumTaxa(); i++)
+ 					taxa.setSelected(i, false);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Reverses the taxon selection", null, commandName, "reverse")) {
+			if (taxa !=null && table!=null) {
+ 				for (int i=0; i<taxa.getNumTaxa(); i++)
+ 					taxa.setSelected(i, !taxa.getSelected(i));
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Selects taxa in the set", null, commandName, "selectSet")) {
+			if (taxa !=null && table!=null) {
+				int whichSet = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+	 			SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaSelectionSet.class);
+ 				if (ssv!=null) {
+ 					TaxaSelectionSet chosen;
+  	 				if (!MesquiteInteger.isCombinable(whichSet))
+	 					chosen = (TaxaSelectionSet)ListDialog.queryList(containerOfModule(), "Set taxa selection", "Select taxa of which set?", MesquiteString.helpString,ssv, 0);
+    	 				else 
+	    	 				chosen = (TaxaSelectionSet)ssv.getSpecsSet(whichSet);
+	    	 			if (chosen!=null){
+	    	 				for (int i=0; i<taxa.getNumTaxa(); i++)
+	    	 					taxa.setSelected(i, chosen.isBitOn(i));
+						taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	 					table.repaintAll();
+	    	 				return chosen;
+	    	 			}
+    	 			}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Hires taxon selection module to operate on the taxa", "[name of module]", commandName, "doSelectTaxa")) {
+   	 		if (table!=null && taxa !=null){
+	    	 		TaxonSelector tda= (TaxonSelector)hireNamedEmployee(TaxonSelector.class, arguments);
+				if (tda!=null) {
+					tda.selectTaxa(taxa);
+	 	   			table.repaintAll();
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == taxa && (code == MesquiteListener.ASSOCIATED_CHANGED || code == AssociableWithSpecs.SPECSSET_CHANGED)){
+			menuReset();
+			resetContainingMenuBar();
+		}
+	}
+	private void menuReset(){
+		if (mss!=null)
+			deleteMenuItem(mss);
+		if (mssc!=null)
+			deleteMenuItem(mssc);
+		mss = addSubmenu(null, "Taxa Set", makeCommand("selectSet",  this), taxa.getSpecSetsVector(TaxaSelectionSet.class));
+		mssc = addSubmenu(null, "Select Taxa", MesquiteModule.makeCommand("doSelectTaxa",  this));
+		mssc.setList(TaxonSelector.class);
+	}
+	/*.................................................................................................................*/
+	public void setTableAndObject(MesquiteTable table, Object obj, boolean rows){
+		if (obj==null || !(obj instanceof Taxa))
+			return;
+		if (taxa != this.taxa && this.taxa != null)
+			this.taxa.removeListener(this);
+		this.taxa = (Taxa)obj;
+		this.taxa.addListener(this);
+		
+		this.table = table;
+		this.rows = rows;
+		menuReset();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Taxon selection coordinator";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates taxon selection." ;
+   	 }
+}
+
diff --git a/Source/mesquite/basic/TextWindowMaker/TextWindowMaker.java b/Source/mesquite/basic/TextWindowMaker/TextWindowMaker.java
new file mode 100644
index 0000000..e26a31b
--- /dev/null
+++ b/Source/mesquite/basic/TextWindowMaker/TextWindowMaker.java
@@ -0,0 +1,152 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.TextWindowMaker;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class TextWindowMaker extends FileAssistantN {
+	MesquiteTextWindow textWindow;
+	String pathToPicture;
+	Color bgColor;
+	static int numMade = 0;
+	String noteTitle = "";
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { //todo: should behave differently depending on whether home file was url or not!!!
+		noteTitle = "Note " + (++numMade);
+		textWindow = new MesquiteTextWindow(this, noteTitle, true, true, true);
+		textWindow.setEditable(true);
+ 		setModuleWindow(textWindow);
+		if (!MesquiteThread.isScripting()){ //file dialog to choose picture
+			textWindow.setPopAsTile(true);
+			textWindow.popOut(true);
+			textWindow.setVisible(true);
+		}
+		makeMenu("Note");
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Background Color", makeCommand("setBackground",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		addMenuItem("Title...", makeCommand("queryTitle", this));
+		addMenuItem("Delete Note", makeCommand("deleteNote", this));
+ 		resetContainingMenuBar();
+ 		resetAllWindowsMenus();
+ 		return true;
+  	 }
+	 
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (textWindow ==null) // || !textWindow.isVisible())
+  	 		return null;
+   	 	Snapshot temp = new Snapshot();
+   	 	temp.addLine("setText " + StringUtil.tokenize(textWindow.getText()));
+   	 	temp.addLine("setTitle " + StringUtil.tokenize(noteTitle));
+  	 	temp.addLine("getWindow");
+  	 	Snapshot fromWindow = textWindow.getSnapshot(file);
+ 		
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+
+  	 	if (bgColor !=null) {
+  	 		String bName = ColorDistribution.getStandardColorName(bgColor);
+  	 		if (bName!=null)
+  	 			temp.addLine("setBackground " + StringUtil.tokenize(bName));
+  	 	}
+		if (textWindow.isVisible())
+			temp.addLine("showWindow");
+		else
+			temp.addLine("hideWindow");
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	 if (checker.compare(this.getClass(), "Sets the text in the text window", "[text]", commandName, "setText")){
+				textWindow.setText(parser.getFirstToken(arguments));
+    	 	 } 
+     	 	 else if (checker.compare(this.getClass(), "Sets the title of the text window", "[text]", commandName, "setTitle")){
+				textWindow.setTitle(parser.getFirstToken(arguments));
+    	 	 } 
+     	 	 else if (checker.compare(this.getClass(), "Queries the user for the title of the text window", "[text]", commandName, "queryTitle")){
+     	 		 MesquiteString ms = new MesquiteString(noteTitle);
+				if ( QueryDialogs.queryShortString(containerOfModule(), "Title", "Title of note:", ms)){
+					noteTitle = ms.getValue();
+					textWindow.setTitle(noteTitle);
+				}
+    	 	 } 
+    	 	 else if (checker.compare(this.getClass(), "Deletes the text window", null, commandName, "deleteNote")){
+     	 		textWindow.hide();
+     	 		textWindow.dispose();
+     			iQuit();
+     	 	 } 
+     	 	 else if (checker.compare(this.getClass(), "Hides the text window", null, commandName, "hideWindow")){
+      	 		textWindow.hide();
+      	 	 } 
+     	 	 else if (checker.compare(this.getClass(), "Sets the color of the window", "[name of color]", commandName, "setBackground")) {
+    	 		Color bc = ColorDistribution.getStandardColor(ParseUtil.getFirstToken(arguments, stringPos));
+			if (bc == null)
+				return null;
+			bgColor = bc;
+			setBackgroundAll(textWindow.getOuterContentsArea(), bc);
+			textWindow.repaintAll();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	
+     	 	 return null;
+   	 }
+	/** calls repaint of all components*/
+	void setBackgroundAll(Component c, Color col){
+		if (c==null)
+			return;
+		c.setBackground(col);
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					setBackgroundAll(cc[i], col);
+		}
+		
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Text Window";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "New Notes Window";
+   	 }
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+		//	whichWindow.dispose();
+		//	iQuit();
+	}
+	public boolean isSubstantive(){
+		return false;
+	}
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Displays Text in a window." ;
+   	 }
+}
+	
+
diff --git a/Source/mesquite/basic/TruncTaxonNames/TruncTaxonNames.java b/Source/mesquite/basic/TruncTaxonNames/TruncTaxonNames.java
new file mode 100644
index 0000000..8d6bd82
--- /dev/null
+++ b/Source/mesquite/basic/TruncTaxonNames/TruncTaxonNames.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.TruncTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TruncTaxonNames extends TaxonNameAlterer {
+	int truncLength = 10;
+	boolean stripTrailingSpaces = true;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Truncate names",  buttonPressed);
+		queryDialog.addLabel("Truncation of taxon names", Label.CENTER);
+		SingleLineTextField truncationLengthField = queryDialog.addTextField("Maximum length:", ""+truncLength, 20);
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			String s = truncationLengthField.getText();
+			truncLength = MesquiteInteger.fromString(s);
+			if (!MesquiteInteger.isCombinable(truncLength))
+				ok = false;
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null && name.length()>truncLength){
+			String trunced =  name.substring(0, truncLength);
+			if (stripTrailingSpaces){
+				while (trunced.length()>0 && trunced.charAt(trunced.length()-1)== ' ')
+					trunced =  name.substring(0, trunced.length()-1);
+			}
+			taxa.setTaxonName(it, trunced, false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Truncates taxon names", "[length]", commandName, "truncate")) {
+	   	 		if (taxa !=null){
+	   	 			 truncLength = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Truncate...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Truncate taxon names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Truncates taxon names.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/VoucherInfoCoordinator/VoucherInfoCoordinator.java b/Source/mesquite/basic/VoucherInfoCoordinator/VoucherInfoCoordinator.java
new file mode 100644
index 0000000..5f102b1
--- /dev/null
+++ b/Source/mesquite/basic/VoucherInfoCoordinator/VoucherInfoCoordinator.java
@@ -0,0 +1 @@
+/* Mesquite source code.  Copyright 2005 and onward, David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */


package mesquite.basic.VoucherInfoCoordinator; 


import mesquite.lib.*;

public class  VoucherInfoCoordinator extends OTUIDCodeInfoCoord {
	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
		EmployeeNeed e = registerEmployeeNeed(OTUIDCodeInfoSource.class, "Voucher information is obtained from a source.",
				"This is activated automatically.");
	}
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
		hireAllEmployees(OTUIDCodeInfoSource.class);
		return true;
	}
	
	
	public VoucherInfoFromOTUIDDB getVoucherInfo(String sourceID, String id){
		if (sourceID == null || id == null)
			return null;
		EmployeeVector v = getEmployeeVector();
		for (int i = 0; i<v.size(); i++){
			if (v.elementAt(i) instanceof OTUIDCodeInfoSource){
				OTUIDCodeInfoSource vis = (OTUIDCodeInfoSource)v.elementAt(i);
				if (vis.handlesDatabase(sourceID)){
					return vis.getVoucherInfo(sourceID, id);
				}
			}
		}
		return null;
	}
	/*.................................................................................................................*/
	public String getName() {
		return "Coordinator of voucher information";
	}
	/*.................................................................................................................*/
	public boolean isPrerelease(){
		return false;  
	}
	/*.................................................................................................................*/
	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
	public int getVersionOfFirstRelease(){
		return -1;  
	}
	/*.................................................................................................................*/
	/** returns whether this module is requesting to appear as a primary choice */
	public boolean requestPrimaryChoice(){
		return true;  
	}
	
	/*.................................................................................................................*/
	/** returns an explanation of what the module does.*/
	public String getExplanation() {
		return "Finds suppliers of voucher information." ;
	}
}
\ No newline at end of file
diff --git a/Source/mesquite/basic/VoucherInfoFromFlexTable/VoucherInfoFromFlexTable.java b/Source/mesquite/basic/VoucherInfoFromFlexTable/VoucherInfoFromFlexTable.java
new file mode 100644
index 0000000..b52f915
--- /dev/null
+++ b/Source/mesquite/basic/VoucherInfoFromFlexTable/VoucherInfoFromFlexTable.java
@@ -0,0 +1 @@
+/* Mesquite source code.  Copyright 2005 and onward, David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */


package mesquite.basic.VoucherInfoFromFlexTable; 


import mesquite.lib.*;
import java.util.Vector;


/* ======================================================================== */

public class  VoucherInfoFromFlexTable extends OTUIDCodeInfoSource {
	Vector tables, paths;
	boolean warned = false;
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
		paths = new Vector();
		tables = new Vector();
		return true;
	}
	
	/*.................................................................................................................*/
	private String getPath(String databaseID){
		String where = null;
		if (databaseID.indexOf(":")<0)
			where = databaseID;
		else
			where = databaseID.substring(databaseID.indexOf(":")+1, databaseID.length());
		if (!warned && StringUtil.blank(where)) {
			MesquiteMessage.warnProgrammer("Path of voucher info file is empty; databaseID = " + databaseID);
			warned = true;
		}
		return where;
	}
	/*.................................................................................................................*/
	private String getDBID(String databaseID){
		String which = null;
		if (databaseID.indexOf(":")<0)
			which = databaseID;
		else
			which = databaseID.substring(0, databaseID.indexOf(":"));
		if (!warned && StringUtil.blank(which)) {
			MesquiteMessage.warnProgrammer("DBID of voucher info file is empty; databaseID = " + databaseID);
			warned = true;
		}
		return which;
	}
	private int findPath(String path){
		if (path == null)
			return -1;
		for (int i=0; i<paths.size(); i++)
			if (path.equals(paths.elementAt(i)))
				return i;
		return -1;
	}
	private int findRow(String[][] table, String id){
		for (int i=0; i<table.length; i++){
			if (table[i] != null && table[i].length>0 && id.equalsIgnoreCase(table[i][0]))
				return i;
			
		}
		return -1;
	}
	private VoucherInfoFromOTUIDDB makeInfo(String[][] table, int row){
		
		if (table == null || row>= table.length)
			return null;

		VoucherInfoFromOTUIDDB vi = new VoucherInfoFromOTUIDDB();
		String[] line = table[0];  		// cycle through first row to get field names
		for (int i = 1; i<line.length; i++)  //start at 1 as we don't want to include the code
			vi.addElement(line[i]);
		
		line = table[row];
		if (line == null || line.length == 0)
			return null;
		for (int i = 1; i<line.length; i++)  //start at 1 as we don't want to include the code
			vi.setFieldValue(i-1, line[i]);   //index is i-1 as we skipped over the first one
		return vi;
	}
	/*.................................................................................................................*/
//	String voucherID, String species, String latLong, String locality, String note, String collectionDate
	
	public VoucherInfoFromOTUIDDB getVoucherInfo(String databaseID, String id){
		if (!handlesDatabase(databaseID))
			return null;
		String path = getPath(databaseID);
		if (path == null)
			return null;
		int i = findPath(path);
		String[][] table = null;
		if (i<0){
			table = MesquiteFile.getTabDelimitedTextFile(path, false);
			if (table != null){
				paths.addElement(path);
				tables.addElement(table);
			}
		}
		else
			table = (String[][]) tables.elementAt(i);
		if (table == null)
			return null;
		int whichRow = findRow(table, id);
		if (whichRow<0)
			return null;
		return makeInfo(table, whichRow);
	}
	/*.................................................................................................................*/
	public boolean handlesDatabase(String databaseID){
		if (databaseID == null)
			return false;
		String which = getDBID(databaseID);
		return "tdt".equalsIgnoreCase(which);
	}
	
	/*.................................................................................................................*/
	public String getName() {
		return "Voucher Info from Flexible Table";
	}
	/*.................................................................................................................*/
	public boolean isPrerelease(){
		return false;  
	}
	/*.................................................................................................................*/
	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
	public int getVersionOfFirstRelease(){
		return -1;  
	}
	/*.................................................................................................................*/
	/** returns whether this module is requesting to appear as a primary choice */
	public boolean requestPrimaryChoice(){
		return true;  
	}
	
	/*.................................................................................................................*/
	/** returns an explanation of what the module does.*/
	public String getExplanation() {
		return "Supplies voucher information from a flexible tab-delimited table in a text file." ;
	}
}


\ No newline at end of file
diff --git a/Source/mesquite/basic/aBasicIntro/aBasicIntro.java b/Source/mesquite/basic/aBasicIntro/aBasicIntro.java
new file mode 100644
index 0000000..cc562db
--- /dev/null
+++ b/Source/mesquite/basic/aBasicIntro/aBasicIntro.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.aBasicIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aBasicIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aBasicIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic utilities for Mesquite.";
+   	 }
+    /*.................................................................................................................*/
+    public boolean getHideable() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Basic Utilities Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Basic Utilities Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/basic/explanation.txt b/Source/mesquite/basic/explanation.txt
new file mode 100644
index 0000000..e65edfe
--- /dev/null
+++ b/Source/mesquite/basic/explanation.txt
@@ -0,0 +1,2 @@
+Basic Modules for Mesquite
+One of the core Mesquite packages.  A diverse collection of modules that most calculations will need.  Included are modules to manage character data and other critical parts of data files and basic calculations modules for trees
diff --git a/Source/mesquite/basic/zTokenizeTaxonNames/zTokenizeTaxonNames.java b/Source/mesquite/basic/zTokenizeTaxonNames/zTokenizeTaxonNames.java
new file mode 100644
index 0000000..f3e5a0e
--- /dev/null
+++ b/Source/mesquite/basic/zTokenizeTaxonNames/zTokenizeTaxonNames.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.zTokenizeTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class zTokenizeTaxonNames extends TaxonNameAlterer {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		return true;
+   	}
+	public boolean requestPrimaryChoice() {
+		return false;
+	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		
+		if (name!=null){
+			taxa.setTaxonName(it, StringUtil.tokenize(name), false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Tokenize Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tokenize Names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Tokenizes names.  This can be useful for reading trees produced from exported files.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/basic/zzDetokenizeTaxonNames/zzDetokenizeTaxonNames.java b/Source/mesquite/basic/zzDetokenizeTaxonNames/zzDetokenizeTaxonNames.java
new file mode 100644
index 0000000..a3569e8
--- /dev/null
+++ b/Source/mesquite/basic/zzDetokenizeTaxonNames/zzDetokenizeTaxonNames.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.basic.zzDetokenizeTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class zzDetokenizeTaxonNames extends TaxonNameAlterer {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		return true;
+   	}
+	public boolean requestPrimaryChoice() {
+		return false;
+	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			taxa.setTaxonName(it, parser.getFirstToken(name), false);
+			nameChanged = true;
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Detokenize Names...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Detokenize Names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Detokenizes names.  This can be useful for reading trees produced from exported files.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/BatchTemplateManager.java b/Source/mesquite/batchArch/BatchTemplateManager/BatchTemplateManager.java
new file mode 100644
index 0000000..cc49aa4
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/BatchTemplateManager.java
@@ -0,0 +1,1173 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.BatchTemplateManager; 
+
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+import javax.swing.JLabel;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.AssociationSource;
+import mesquite.batchArch.lib.*;
+
+/* =========================== */
+public class BatchTemplateManager extends TemplateManager {
+//	public static String defaultMatrixExportFileFormat = "NEXUS file interpeter";
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(mesquite.trees.StoredTrees.StoredTrees.class, getName() + " may need a tree, for example to simulate the matrices.",
+		"Stored trees are chosen automatically for this if needed.");
+	}
+	ListableVector templates;
+	String templateName = "Simple List";
+	TreeSource treeSourceTask;
+	ListableVector fileSpecifics;
+	ChooseTemplateDLOG chooseTemplateDialog=null;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		templates = new ListableVector();
+		fileSpecifics = new ListableVector();
+		loadTemplates();
+		return true;
+	}
+   	public String getExpectedPath(){
+		return getPath() + "templates";
+  	 }
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in.*/
+ 	public void projectEstablished() {
+		MesquiteSubmenuSpec msms = getFileCoordinator().addSubmenu(MesquiteTrunk.editMenu, "Batch File Templates");
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.editMenu, msms, "Edit Batch File Templates...", makeCommand("editTemplates", this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.editMenu, msms, "Edit Code Snippets for Batch Files...", makeCommand("editFileSpecifics", this));
+		super.projectEstablished();
+ 	}
+ 	
+	/*.................................................................................................................*/
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "templateName", templateName);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("templateName".equalsIgnoreCase(tag))
+			templateName = StringUtil.cleanXMLEscapeCharacters(content);
+	}
+
+
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0)
+			templateName = prefs[0];
+	}
+	/*.................................................................................................................*/
+	public TemplateRecord loadTemplateFile(String cPath, String fileName, boolean requiresTemplateEnding,  boolean userDef) {
+		File cFile = new File(cPath);
+		if (cFile.exists() && !cFile.isDirectory() && (!requiresTemplateEnding || fileName.endsWith("template"))) {
+			String contents = MesquiteFile.getFileContentsAsString(cPath);
+			if (!StringUtil.blank(contents)) {
+				TemplateRecord localTemplate = new TemplateRecord(userDef, this);
+				localTemplate.path = cPath;
+				if  (localTemplate.fillFromString(contents, parser)) {
+					templates.addElement(localTemplate, false);
+					return localTemplate;
+				}
+				return null;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void loadTemplates(String path, File templateDir, boolean userDef){
+		if (templateDir.exists() && templateDir.isDirectory()) {
+			String[] templatesList = templateDir.list();
+			for (int i=0; i<templatesList.length; i++) {
+				if (templatesList[i]==null )
+					;
+				else {
+					String cPath = path + MesquiteFile.fileSeparator + templatesList[i];
+					loadTemplateFile(cPath, templatesList[i], true, userDef);
+				}
+			}
+		}
+	}
+	private void loadTemplates(){
+		String path = getPath() + "templates";
+		File templateDir = new File(path);
+		loadTemplates(path, templateDir, false);
+		path = MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator + "BatchTemplates";
+		templateDir = new File(path);
+		loadTemplates(path, templateDir, true);
+	}
+	SingleLineTextField treeField;
+	/*.................................................................................................................*/
+	public TemplateRecord chooseTemplate(Taxa taxa){
+		TemplateRecord template = null;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		chooseTemplateDialog = new ChooseTemplateDLOG(this, "Choose Template", templateName, taxa, buttonPressed);
+		chooseTemplateDialog.completeAndShowDialog();
+		boolean ok = (chooseTemplateDialog.query()==0);
+		
+		if (ok) {
+			templateName = chooseTemplateDialog.templateChoiceGet.getSelectedItem();
+			int sL = templates.indexOfByName(templateName);
+	  		if (sL >=0 && sL < templates.size()) {
+	  			template = (TemplateRecord)templates.elementAt(sL);
+	  		}
+	 		storePreferences();
+		}
+		chooseTemplateDialog.dispose();
+		chooseTemplateDialog = null;
+		return template;
+	}
+	/*.................................................................................................................*/
+	public TemplateRecord getTemplate(String name){
+		int sL = templates.indexOfByNameIgnoreCase(name);
+  		if (sL >=0 && sL < templates.size())
+  			return (TemplateRecord)templates.elementAt(sL);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	void editFileSpecifics(ChooseTemplateDLOG dlog){
+		EditFileSpecificsDLOG dialog = new EditFileSpecificsDLOG(this, dlog);
+		if (dlog !=null)
+			dlog.resetSnippetList();
+		dialog.dispose();
+		dialog = null;
+	}
+	/*.................................................................................................................*/
+	public boolean getTreeHasBeenChosen(){
+		if (chooseTemplateDialog!=null)
+			return chooseTemplateDialog.getTreeHasBeenChosen();
+		else
+			return false;
+	}
+	/*.................................................................................................................*/
+	public ExtensibleDialog getChooseTemplateDLOG(Taxa taxa, String title, ObjectContainer oC, MesquiteInteger buttonPressed, boolean includeMatrices){
+		chooseTemplateDialog = new ChooseTemplateDLOG(this, title, templateName, taxa, buttonPressed);
+		chooseTemplateDialog.setChoiceContainer(oC);
+		chooseTemplateDialog.setIncludeMatrices(includeMatrices);
+		return chooseTemplateDialog;
+	}
+	/*.................................................................................................................*/
+	void editTemplates(ChooseTemplateDLOG dlog){
+		//EditTemplatesDLOG dialog = new EditTemplatesDLOG(this, templateName, dlog);
+		ManageTemplatesDLOG dialog = new ManageTemplatesDLOG(this, dlog);
+		dialog.dispose();
+		dialog = null;
+	}
+	
+	private String getTextFromArea(TextArea a){
+		int count = 0;
+		while (count++<10){
+			try {
+				String s = a.getText();
+				if (s==null)
+					return "";
+				return s;
+		        }
+		        catch (Exception e){
+		        	//MesquiteMessage.warnProgrammer("Exception in getText of SingleLineTextField");
+		        }
+	        }
+	        return "";
+	}
+	/*.................................................................................................................*/
+	public MesquiteString addFileSpecific(String name, String commands){
+		MesquiteString s = new MesquiteString();
+		s.setName(name);
+		s.setValue(commands);
+		fileSpecifics.addElement(s, false);	
+		return s;
+	}
+	public int numFileSpecifics(){
+		return fileSpecifics.size();
+	}
+	public MesquiteString getFileSpecific(String name){
+		int i = fileSpecifics.indexOfByName(name);
+		if (i<0)
+			return null;
+		return (MesquiteString)fileSpecifics.elementAt(i);	
+	}
+	public int findFileSpecific(String name){
+		return fileSpecifics.indexOfByName(name);
+	}
+	public MesquiteString getFileSpecific(int i){
+		if (i<0 || i>= fileSpecifics.size())
+			return null;
+		return (MesquiteString)fileSpecifics.elementAt(i);	
+	}
+	void renameFileSpecific(int i, String name){
+		MesquiteString s = getFileSpecific(i);
+		if (s !=null)
+			s.setName(name);	
+	}
+	void deleteFileSpecific(int i){
+		MesquiteString s = getFileSpecific(i);
+		if (s !=null)
+			fileSpecifics.removeElement(s, false);
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	for (int i=0; i<fileSpecifics.size(); i++)
+  	 		temp.addLine("fileSpecifics " + StringUtil.tokenize(getFileSpecific(i).getName()) + " " + StringUtil.tokenize(getFileSpecific(i).getValue())); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Adds a file specific set of code", "[name][code]", commandName, "fileSpecifics")) {
+			String name = parser.getFirstToken(arguments);
+			String co = parser.getNextToken();
+			return addFileSpecific(name, co);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Asks to bring up editor of batch file templates", null, commandName, "editTemplates")) {
+			editTemplates(null);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Loads template file", null, commandName, "loadTemplates")) {
+ 	 		loadTemplates(getProject().getHomeDirectoryName(), new File(getProject().getHomeDirectoryName()), true);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Asks to bring up editor of code snippets for batch file", null, commandName, "editFileSpecifics")) {
+			editFileSpecifics(null);
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Batch File Template Manager";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages templates used in saving batch files." ;
+   	 }
+   	 
+   	 Tree tree;
+	/*.................................................................................................................*/
+   	Tree getTree(Taxa taxa){
+		tree = null;
+		//if (treeSourceTask == null) Ask Wayne about this
+			treeSourceTask= (TreeSource)hireNamedEmployee(TreeSource.class, "#StoredTrees");
+		if (treeSourceTask!=null) {
+			int treeNum = treeSourceTask.queryUserChoose(taxa, "");
+			if (MesquiteInteger.isCombinable(treeNum))
+				tree = treeSourceTask.getTree(taxa, treeNum);
+		}
+		return tree;
+   	}
+   	public Tree getTree(){
+   		return tree;
+   	}
+   	public void forgetTree(){
+   		tree = null;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+}
+
+
+
+
+
+
+/*=======================================================================*/
+class ChooseTemplateDLOG extends ExtensibleExplDialog  implements ItemListener, ActionListener {//************
+	String templateName = "Simple List";
+	Taxa taxa = null;
+	Tree tree = null;
+	TemplateRecord currentTemplate;
+	FileCoordinator coord;
+	SingleLineTextField treeField;
+	Button treeButton;
+	Choice templateChoiceGet, fsChoice;
+	TextArea fsText;
+	JLabel extensionText;
+	boolean includeMatrices;
+	ObjectContainer chosen;
+	String editTempButtonString = "Edit Templates...";
+	String editSnipButtonString = "Edit Snippets...";
+	String chooseTreeButtonString = "Choose tree...";
+	BatchTemplateManager ownerModule;
+	public ChooseTemplateDLOG (BatchTemplateManager ownerModule, String title, String initialTemplateName, Taxa taxa, MesquiteInteger buttonPressed){
+		super(ownerModule.containerOfModule(), title, buttonPressed);
+		this.ownerModule = ownerModule;
+		coord = ownerModule.getFileCoordinator();
+		
+		this.taxa = taxa;
+		templateName = initialTemplateName;
+	}
+	
+	public void setIncludeMatrices(boolean includeMatrices){
+		this.includeMatrices = includeMatrices;
+	}
+	
+	public void addAuxiliaryDefaultPanels(){ //************
+		
+		Panel panel;
+		
+		if (includeMatrices) {
+			extensionText = addLabel("");
+			extensionText.setFont(defaultSmallFont);
+		}
+
+		addHorizontalLine(3);
+		addLabel("Batch File Template", Label.LEFT,true,true);
+
+		templateChoiceGet = addPopUpMenu ("Batch File Template", ownerModule.templates.getElementArray(), 0);
+		
+		boolean noChoiceItems = (templateChoiceGet.getItemCount()<=0);
+		templateChoiceGet.addItemListener(this);
+		int sL = ownerModule.templates.indexOfByName(templateName);
+		if (sL <0) {
+			sL = 0;
+		}
+		
+		if (!noChoiceItems)
+			templateChoiceGet.select(sL);   
+
+//		suppressNewPanel();
+
+		GridBagConstraints gridConstraints;
+		gridConstraints = getGridBagConstraints();
+		gridConstraints.fill = GridBagConstraints.NONE;
+		setGridBagConstraints(gridConstraints);
+
+//		fsChoice = addPopUpMenu ("CODE SNIPPETS NEEDED", (Listable[])null, 0);
+		fsText = addTextAreaSmallFontNoScroll("",4, false);
+		fsText.setBackground(fsText.getParent().getBackground());
+		fsText.setEditable(false);
+		
+		suppressNewPanel();
+		panel = addNewDialogPanel(gridConstraints);
+		Button editSnippetsButton = addAButton(editSnipButtonString, panel);
+		editSnippetsButton.addActionListener(this);
+		addBlankLine();
+		
+		
+		treeField = addTextField(" ","", 20);
+		treeField.setEditable(false);
+		treeField.setBackground(treeField.getParent().getBackground());
+		
+		suppressNewPanel();
+		gridConstraints = getGridBagConstraints();
+		gridConstraints.fill = GridBagConstraints.NONE;
+		setGridBagConstraints(gridConstraints);
+		panel = addNewDialogPanel(gridConstraints);
+		treeButton = addAButton(chooseTreeButtonString, panel);
+		gridConstraints.fill = GridBagConstraints.BOTH;
+		setGridBagConstraints(gridConstraints);
+		treeButton.addActionListener(this);
+		addBlankLine();
+		
+		setTemplate(sL);
+		//addLabel("Explanation of template:",  Label.LEFT, true,false);//************
+		super.addAuxiliaryDefaultPanels(); //************
+
+		panel = addNewDialogPanel();
+		Button editButton = addAButton(editTempButtonString, panel);
+		editButton.addActionListener(this);
+		suppressNewPanel();
+/*
+		panel = addNewDialogPanel();
+		Button editSnippetsButton = addAButton(editSnipButtonString, panel);
+		editSnippetsButton.addActionListener(this);
+*/
+		
+		addHorizontalLine(1);
+	}
+	public void actionPerformed(ActionEvent e){
+		if (editTempButtonString.equals(e.getActionCommand())) {
+			ownerModule.editTemplates(this);
+			//setTemplate();
+		}
+		else if (editSnipButtonString.equals(e.getActionCommand()))
+			ownerModule.editFileSpecifics(this);
+		else if (chooseTreeButtonString.equals(e.getActionCommand())) {
+			tree = ownerModule.getTree(taxa);
+			if (tree!=null) {
+				treeField.setForeground(treeField.getParent().getForeground());
+				treeField.setText(tree.getName());
+			}
+			else {
+				treeField.setText("TREE NEEDED");
+				treeField.setForeground(Color.red);
+				MesquiteMessage.notifyUser("No tree is available; one must be available before this template can be used.");
+			}
+		}
+		else super.actionPerformed(e);
+	}
+	/*public void dispose(){
+		if (tree != null && ownerModule!=null && !ownerModule.isDoomed())
+			ownerModule.forgetTree();
+		super.dispose();
+	}
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == templateChoiceGet){
+	  		int item = ownerModule.templates.indexOfByName((String)e.getItem());
+	  		if (item>=0) {
+	  			setTemplate(item);
+	  			prepareDialogHideFirst();
+	  		}
+  		}
+  	}
+	/*.................................................................................................................*/
+	public boolean dialogValuesAcceptable () {
+		boolean acceptable=true;
+		if (currentTemplate.needsTree() && (tree==null))
+			acceptable = false;
+		return acceptable;
+	}
+	/*.................................................................................................................*/
+	public void dialogValuesNotAcceptableWarning () {
+		MesquiteMessage.notifyUser("This template requires that a tree is chosen.");
+	}
+/*.................................................................................................................*/
+	public void setChoiceContainer(ObjectContainer oC){
+		this.chosen = oC;
+	}
+/*.................................................................................................................*/
+	void addTemplate(String name){
+		templateChoiceGet.add(name);
+	}
+/*.................................................................................................................*/
+	void renameTemplate(int item, String newName){
+		templateChoiceGet.remove(item);
+		templateChoiceGet.insert(newName,item);
+		templateName=newName;
+	}
+/*.................................................................................................................*/
+	void removeTemplate(String name){
+		templateChoiceGet.remove(name);
+	}
+/*.................................................................................................................*/
+	void selectTemplate(String name){
+		templateChoiceGet.select(name);
+	}
+/*.................................................................................................................*/
+	ListableVector getSnippetsNeeded() {
+		return currentTemplate.snippetsNeeded();
+	}
+/*.................................................................................................................*/
+	boolean getTreeHasBeenChosen() {
+		return (tree!=null);
+	}
+/*.................................................................................................................*/
+	String getNameOfFirstUnavailableSnippetNeeded() {
+		ListableVector snippets = currentTemplate.snippetsNeeded();
+		if (snippets.size()>0) {
+			for (int i=0; i<snippets.size(); i++) {
+				String s = ((Listable)snippets.elementAt(i)).getName();
+				if (ownerModule.findFileSpecific(s)<0)
+					return s;
+			}
+		}
+		return null;
+	}
+  	void setTemplate(int item){
+	  		if (item >=0 && item < ownerModule.templates.size()){
+	  			currentTemplate = (TemplateRecord)ownerModule.templates.elementAt(item);
+		  			setExplainable(currentTemplate); //************
+				if (chosen !=null)
+					chosen.setObject(currentTemplate);
+				if (currentTemplate.needsTree()) {
+					treeButton.setEnabled(true);
+					if (tree!=null) {
+						treeField.setText(tree.getName());
+						treeField.setForeground(treeField.getParent().getForeground());
+					}
+					else {
+						treeField.setText("TREE NEEDED");
+						treeField.setForeground(Color.red);
+					}
+				}
+				else {
+					treeField.setText("NO TREE NEEDED");
+					treeField.setForeground(treeField.getParent().getForeground());
+					treeButton.setEnabled(false);
+				}
+				resetTemplateItems();
+				return;
+			}
+		
+  	}
+  	public void resetExtensionText(){
+		if (includeMatrices) {
+			if (currentTemplate!=null) {
+				String s = currentTemplate.fileExtension(currentTemplate.matrixExportFormat,coord,true);
+				if (StringUtil.blank(s))
+					extensionText.setText("");		
+				else
+					extensionText.setText("The extension \"" + s + "\" will be added to the end of each matrix's file name.");		
+			}
+			else
+				extensionText.setText("");		
+			extensionText.invalidate();
+			extensionText.validate();
+		}
+  	}
+  	public void resetSnippetList(){
+		ListableVector snippets = currentTemplate.snippetsNeeded();
+		String snip = "";
+		if (snippets.size()>0) {
+			boolean snippetUnavailable = false;
+			snip = "CODE SNIPPETS NEEDED: ";
+			for (int i=0; i<snippets.size(); i++) {
+				String s = ((Listable)snippets.elementAt(i)).getName();
+				if (ownerModule.findFileSpecific(s)<0) {
+					s += " (unavailable)";
+					snippetUnavailable = true;
+				}
+				if (i>0)
+					snip += ", " + s;
+				else
+					snip += s;
+			}
+			if (snippetUnavailable)
+				fsText.setForeground(Color.red);
+			else
+				fsText.setForeground(fsText.getParent().getForeground());
+		}
+		else {
+			snip ="No Code Snippets needed.";
+			fsText.setForeground(fsText.getParent().getForeground());
+		}
+		fsText.setText(snip);		
+		fsText.invalidate();
+		fsText.validate();
+  	}
+
+	 public void resetTemplateItems(){
+	 	resetSnippetList();
+	 	resetExtensionText();
+	 }
+
+	 public void dispose(){
+		if (ownerModule.treeSourceTask != null){
+			ownerModule.fireEmployee(ownerModule.treeSourceTask);
+			ownerModule.treeSourceTask = null;
+		}
+		super.dispose();
+	  }
+}
+
+
+
+
+/*=======================================================================*/
+class ManageTemplatesDLOG extends ExtensibleListDialog {
+	BatchTemplateManager ownerModule;
+	//TemplateRecord currentTemplate;
+	ChooseTemplateDLOG chooseDLOG;
+	Button loadButton;
+	static String loadTemplateString="Load...";
+
+	public ManageTemplatesDLOG (BatchTemplateManager ownerModule,ChooseTemplateDLOG chooseDLOG){
+		super(ownerModule.containerOfModule(), "Batch File Template Manager", "Batch File Templates", ownerModule.templates);
+		this.ownerModule = ownerModule;
+		this.chooseDLOG = chooseDLOG;
+		String message = "This dialog box allows you to create and edit templates for batch files.";
+		message += "  Batch files are used, for instance, in parametric bootstrapping to instruct another program.";
+		message += " Templates you create are stored automatically in files in the Mesquite preferences folder.";
+
+		appendToHelpString(message);
+		setHelpURL(ownerModule,"");
+		
+		completeAndShowDialog("Done", null, null, null);
+	}
+/*.................................................................................................................*/
+/** this is the name of the class of objects */
+	public  String objectName(){
+		return "Template";
+	}
+/*.................................................................................................................*/
+/** this is the plural name of the class of objects */
+	public  String pluralObjectName(){
+		return "Templates";
+	}
+/*.................................................................................................................*/
+	public void addAdditionalButtonsBesideList() {
+		loadButton = addNewButtonBesideList(loadTemplateString);
+	}
+/*.................................................................................................................*/
+	public void deleteElement(int item, int newSelectedItem){
+		TemplateRecord template = (TemplateRecord)ownerModule.templates.elementAt(item);
+		String oldTemplateName = template.name;
+		File f = new File(template.path);
+		f.delete();
+		ownerModule.templates.removeElement(template, false);
+		if (chooseDLOG !=null) {
+			chooseDLOG.removeTemplate(oldTemplateName);
+			chooseDLOG.selectTemplate(ownerModule.templates.nameOfElementAt(newSelectedItem));
+			chooseDLOG.setTemplate(newSelectedItem);
+			chooseDLOG.resetTemplateItems();			
+			chooseDLOG.prepareDialogHideFirst();
+		}
+	}
+/*.................................................................................................................*/
+	private String newTemplatePath(){
+		String base = MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator +"BatchTemplates";
+		if (!MesquiteFile.fileExists(base)) {
+			File f = new File(base);
+			f.mkdir();
+		}
+		String candidate = base + "/t1.template";
+		int count = 2;
+		while (MesquiteFile.fileExists(candidate)){
+			candidate = base + "/t" + (count++) + ".template";
+		}
+		return candidate;
+	}
+/*.................................................................................................................*/
+	public Listable createNewElement(String name, MesquiteBoolean success){
+		String candidate = newTemplatePath();
+
+		MesquiteFile.putFileContents(candidate, "", true); 
+		
+		TemplateRecord localTemplate = new TemplateRecord(true, ownerModule);
+		localTemplate.path = candidate;
+		localTemplate.name = name;
+		localTemplate.explanation= "";
+		for (int i=0; i<localTemplate.getNumFiles(); i++) {
+			localTemplate.setStartText("", i);
+			localTemplate.setTextEach("", i);
+			localTemplate.setEndText("", i);
+			localTemplate.setBatchFileName("Batch File " + (i+1), i);
+		}
+		localTemplate.matrixExportFormat = TemplateRecord.defaultExportFormat;
+		ownerModule.templates.addElement(localTemplate, false);
+		if (chooseDLOG !=null) {
+			chooseDLOG.addTemplate(localTemplate.name);
+			chooseDLOG.selectTemplate(localTemplate.name);
+			chooseDLOG.setTemplate(ownerModule.templates.indexOfByName(localTemplate.name));
+			chooseDLOG.resetTemplateItems();
+		}
+		//setElement
+ 		ownerModule.storePreferences();  //storing default template
+ 		success.setValue(true);
+ 		return localTemplate;
+	}
+/*.................................................................................................................*/
+	public Listable duplicateElement(String name){
+		String candidate = newTemplatePath();
+		TemplateRecord templateToDuplicate = (TemplateRecord)currentElement;
+		
+		TemplateRecord localTemplate = new TemplateRecord(true, ownerModule);
+		localTemplate.path = candidate;
+		localTemplate.name =  name;
+		localTemplate.explanation= templateToDuplicate.explanation;
+		localTemplate.matrixExportFormat = templateToDuplicate.matrixExportFormat;
+		for (int i=0; i<localTemplate.getNumFiles(); i++) {
+			localTemplate.setStartText(templateToDuplicate.getStartText(i), i);
+			localTemplate.setTextEach(templateToDuplicate.getTextEach(i), i);
+			localTemplate.setEndText(templateToDuplicate.getEndText(i), i);
+			localTemplate.setBatchFileName(templateToDuplicate.getBatchFileName(i, null, false), i);
+		}
+
+		ownerModule.templates.addElement(localTemplate, false);
+		
+		String contents = localTemplate.toNEXUSString();
+		MesquiteFile.putFileContents(localTemplate.path, contents, true); 
+		
+		if (chooseDLOG !=null) {
+			chooseDLOG.addTemplate(localTemplate.name);
+			chooseDLOG.selectTemplate(localTemplate.name);
+			chooseDLOG.resetTemplateItems();
+		}
+ 		ownerModule.storePreferences();
+ 		return localTemplate;
+	}
+/*.................................................................................................................*/
+	public void renameElement(int item, Listable element, String newName){
+		TemplateRecord template = (TemplateRecord)element;
+		String oldName = template.name;
+		template.name = newName;
+		String contents = template.toNEXUSString();
+		MesquiteFile.putFileContents(template.path, contents, true); 
+		((TemplateRecord)ownerModule.templates.elementAt(item)).name = newName;
+		if (chooseDLOG !=null) {
+			chooseDLOG.renameTemplate(item, newName);
+			chooseDLOG.selectTemplate(newName);
+		}
+	}
+/*.................................................................................................................*/
+//	public Object duplicateElement(String name){
+		/*
+		MesquiteString s = new MesquiteString();
+		s.setName(name);
+		s.setValue(((MesquiteString)currentElement).getValue());
+		*/
+//		return null;
+//	}
+/*.................................................................................................................*/
+	public boolean getEditable(int item){
+		return ((TemplateRecord)ownerModule.templates.elementAt(item)).getUserDefined();
+	}
+/*.................................................................................................................*/
+	public void viewElement(int item){
+		EditTemplatesDLOG editDialog = new EditTemplatesDLOG(ownerModule, ((TemplateRecord)currentElement).getName(),chooseDLOG, false);
+	}
+/*.................................................................................................................*/
+	public void editElement(int item){
+		EditTemplatesDLOG editDialog = new EditTemplatesDLOG(ownerModule, ((TemplateRecord)currentElement).getName(),chooseDLOG, true);
+	}
+/*.................................................................................................................*/
+  	public void newListElementSelected(){
+  		if (currentElement!=null) {
+	  		boolean userDef = (((TemplateRecord)currentElement).getUserDefined());
+	  		setRenameButtonEnabled(userDef);
+	  		setDeleteButtonEnabled(userDef);
+	  		if (userDef)
+	  			setEditButtonLabel("Edit...");
+	  		else
+	  			setEditButtonLabel("View...");
+	  	}
+  	}
+/*.................................................................................................................*/
+	public void actionPerformed(ActionEvent e){ 
+		if (loadTemplateString.equals(e.getActionCommand())) {   // loads template from new file, saves it as user defined
+			MesquiteString directoryName= new MesquiteString();
+			MesquiteString fileName= new MesquiteString();
+			String filePath = MesquiteFile.openFileDialog("Choose Template File...", directoryName, fileName);
+			if (!StringUtil.blank(filePath)) {
+				TemplateRecord newTemplate = ownerModule.loadTemplateFile(filePath,fileName.getValue(), false,  true);
+				
+				if (newTemplate!=null) {
+					String candidate = newTemplatePath();
+					newTemplate.path = candidate;
+					String contents = newTemplate.toNEXUSString();   // check name
+					MesquiteFile.putFileContents(candidate, contents, true); 
+					if (chooseDLOG !=null) {
+						chooseDLOG.addTemplate(newTemplate.name);
+						chooseDLOG.selectTemplate(newTemplate.name);
+						chooseDLOG.setTemplate(ownerModule.templates.indexOfByName(newTemplate.name));
+						chooseDLOG.resetTemplateItems();
+					}
+					addNewElement(newTemplate, newTemplate.name);
+					
+					if (ownerModule.templates.nameAlreadyInList(newTemplate.name,getList().getSelectedIndex())) {
+						MesquiteTrunk.mesquiteTrunk.alert("This name is already used by another template; please pick a unique name.");
+						renameCurrentElement(true);
+					}
+
+				}
+			}
+
+		}
+		else
+			super.actionPerformed(e);
+	}
+}
+
+
+
+
+
+
+/*=======================================================================*/
+class EditTemplatesDLOG extends ExtensibleDialog implements ItemListener {
+	String[] startTextString;
+	String[] repeatTextString;
+	String[] endTextString;
+	String[] batchFileNameString;
+	TextArea[] startTextArea;
+	TextArea[] repeatTextArea;
+	TextArea[] endTextArea;
+	SingleLineTextField[] batchFileNameField;
+	int numFiles;
+	
+	String matrixExportFormatString = TemplateRecord.defaultExportFormat;
+	String templateExplanation;
+
+	TextArea templateExplanationArea;
+	Tree tree;
+	Taxa taxa;
+	boolean editable;
+	Choice matrixExportFormatChoice;
+	String templateName = "Simple List";
+	BatchTemplateManager ownerModule;
+	MesquiteInteger buttonPressed;
+	TemplateRecord currentTemplate;
+	ChooseTemplateDLOG chooseDLOG;
+	
+	public EditTemplatesDLOG (BatchTemplateManager ownerModule, String templateName, ChooseTemplateDLOG chooseDLOG, boolean editable){
+		super(ownerModule.containerOfModule(), "Template Editor");
+		this.ownerModule = ownerModule;
+		this.chooseDLOG = chooseDLOG;
+		this.editable = editable;
+		this.templateName = templateName;
+
+		TemplateRecord template =  (TemplateRecord)ownerModule.templates.getElement(templateName);
+		numFiles = template.getNumFiles();
+		startTextString = new String[numFiles];
+		repeatTextString = new String[numFiles];
+		endTextString = new String[numFiles];
+		batchFileNameString = new String[numFiles];
+		startTextArea = new TextArea[numFiles];
+		repeatTextArea = new TextArea[numFiles];
+		endTextArea = new TextArea[numFiles];
+		batchFileNameField = new SingleLineTextField[numFiles];
+		
+		int sL = ownerModule.templates.indexOfByName(templateName);
+		if (sL <0) {
+			sL = 0;
+		}
+		setTemplate(sL);
+
+		addBoldLabel("Batch File Template \""+ templateName + "\"");
+		getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+		addHorizontalLine(3,18);
+
+		PopUpPanelOfCards cardPanel = addPopUpPanelOfCards("");
+		Panel[] cardPanels = new Panel[numFiles];
+		for (int i=0; i<numFiles; i++) 
+			cardPanels[i] = cardPanel.addNewCard("Batch File #"+(i+1));
+		
+		getGridBagConstraints().ipadx=0;
+		getGridBagConstraints().weightx=1;
+		getGridBagConstraints().weighty=1;
+		getGridBagConstraints().fill=GridBagConstraints.NONE;
+		getGridBagConstraints().anchor=GridBagConstraints.WEST;
+		
+		for (int i=0; i<numFiles; i++)  {
+			getGridBagConstraints().fill=GridBagConstraints.NONE;
+			getGridBagConstraints().anchor=GridBagConstraints.WEST;
+			setAddPanel(cardPanels[i]);
+			
+			addLabel(" Text for start of batch file:", Label.LEFT);
+			getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+			startTextArea[i]= addTextAreaSmallFont(startTextString[i],4);
+			startTextArea[i].setEditable(editable);
+			startTextArea[i].setColumns(60);
+			if (!editable)
+				startTextArea[i].setBackground(ColorDistribution.brighter(startTextArea[i].getParent().getBackground(),0.5));
+			
+			getGridBagConstraints().anchor=GridBagConstraints.WEST;
+			addLabel(" Repeated text, written for each replicate:", Label.LEFT);
+			getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+			repeatTextArea[i] = addTextAreaSmallFont(repeatTextString[i],7);
+			repeatTextArea[i].setEditable(editable);
+			repeatTextArea[i].setColumns(60);
+			if (!editable)
+				repeatTextArea[i].setBackground(ColorDistribution.brighter(repeatTextArea[i].getParent().getBackground(),0.5));
+			
+			getGridBagConstraints().anchor=GridBagConstraints.WEST;
+			addLabel(" Text for end of batch file:", Label.LEFT);
+			getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+			endTextArea[i] = addTextAreaSmallFont(endTextString[i],4);
+			endTextArea[i].setEditable(editable);
+			endTextArea[i].setRows(4);
+			endTextArea[i].setColumns(60);
+			if (!editable)
+				endTextArea[i].setBackground(ColorDistribution.brighter(endTextArea[i].getParent().getBackground(),0.5));
+				
+			batchFileNameField[i] = addTextField("Batch File Name: ", batchFileNameString[i], 20);
+			batchFileNameField[i].setEditable(editable);
+			if (!editable)
+				batchFileNameField[i].setBackground(ColorDistribution.brighter(batchFileNameField[i].getParent().getBackground(),0.5));
+		}
+		
+		nullifyAddPanel();
+		
+		getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+		addHorizontalLine(3,18);
+		
+		cardPanel.showCard(0);
+		//((CardLayout)cardPanel.getCardLayout()).first(cardPanel.getCardPanel());
+		
+/* 
+Now find all of the fileinterpreters that can export data.
+Eventually change this so that it only lists file interpreters that can export data of the sort being generated.
+*/
+		MesquiteModule[] fInterpreters = ownerModule.getFileCoordinator().getImmediateEmployeesWithDuty(FileInterpreter.class);
+		int count=0;
+		
+		for (int i=0; i<fInterpreters.length; i++){
+
+		if (((FileInterpreter)fInterpreters[i]).canExportEver())
+				count++;
+		}
+		String [] matrixExportFormatNames = new String[count];
+		count = 0;
+		for (int i=0; i<fInterpreters.length; i++)
+			if (((FileInterpreter)fInterpreters[i]).canExportEver()) {
+				matrixExportFormatNames[count] = fInterpreters[i].getName();
+				count++;
+			}
+		matrixExportFormatChoice = addPopUpMenu ("Format of Matrices: ", matrixExportFormatNames, 0);
+		matrixExportFormatChoice.select(matrixExportFormatString);
+		matrixExportFormatChoice.addItemListener(this);
+		
+		getGridBagConstraints().fill=GridBagConstraints.NONE;
+		getGridBagConstraints().anchor=GridBagConstraints.WEST;
+		addLabel(" Explanation of template:", Label.LEFT);
+		getGridBagConstraints().anchor=GridBagConstraints.CENTER;
+		templateExplanationArea = addTextAreaSmallFont(templateExplanation, 4);
+		templateExplanationArea.setEditable(editable);
+		templateExplanationArea.setColumns(60);
+		if (!editable)
+			templateExplanationArea.setBackground(ColorDistribution.brighter(templateExplanationArea.getParent().getBackground(),0.5));
+		getGridBagConstraints().fill=GridBagConstraints.BOTH;
+		addHorizontalLine(2,18);
+		
+		String helpString;
+		
+		if (editable) {
+			helpString ="This user-defined template will be the basis of a batch file produced.  The contents of the first text field will be written at the start of the batch file.";
+			helpString +=" The second field will be written once for each replicate.  The third field will be written at the end of the batch file.  A second batch file will be written by repeating the fourth field, once for each replicate.";
+			helpString +=" Any occurrence of <name> in the repeated fields will be replaced by the base name of the matrix file, <number> by the number of the matrix file.";
+			helpString +=" <matrixFormat> will be replaced by the name of the format of exported matrices, if matrices are to be exported.";
+			helpString +=" If you wish to include other text automatically, create a code snippet and give it a name.  <snippet>code snippet name</snippet> will then be replaced by the code snippet named \"code snippet name\".";
+			helpString +=" To include the text specification of a tree within Mesquite, use <tree>.";
+			helpString +="\n\nFor more details, click on the web link button in the dialog box.";
+		}
+		else {
+			helpString ="This predefined template will be the basis of a batch file produced.  The contents of the first text field will be written at the start of the batch file.";
+			helpString +=" The second field will be written once for each replicate.  The third field will be written at the end of the batch file.  A second batch file will be written by repeating the fourth field, once for each replicate.";
+			helpString +=" Any occurrence of <name> in the repeated fields will be replaced by the base name of the matrix file, <number> by the number of the matrix file.";
+			helpString +=" <matrixFormat> will be replaced by the name of the format of exported matrices, if matrices are to be exported.";
+			helpString +=" If \"<snippet>code snippet name</snippet>\" occurs in the text, it will then be replaced by the code snippet named \"code snippet name\".";
+			helpString +=" <tree> will be replaced by the the text specification of a chosen tree within Mesquite.";
+			helpString +="\n\nThis template is not editable, as it is predefined.  However, you can duplicate it, and then edit the duplicate.";
+			helpString +="\n\nFor more details, click on the web link button in the dialog box.";
+		}
+		appendToHelpString(helpString);
+		setHelpURL(ownerModule,"");
+		
+		if (editable) {
+			completeAndShowDialog("Save", "Cancel",null,null);
+			boolean ok = (query()==0);
+			if (ok) 
+				saveCurrentTemplate();
+		}
+		else
+			completeAndShowDialog("OK", null,null,"OK");
+		
+		dispose();
+	}
+	public EditTemplatesDLOG (BatchTemplateManager ownerModule, String templateName){
+		this(ownerModule, templateName, null,((TemplateRecord)ownerModule.templates.getElement(templateName)).getUserDefined());
+	}
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == matrixExportFormatChoice && !editable){
+	  		matrixExportFormatChoice.select(matrixExportFormatString);
+  		}
+  	}
+/*.................................................................................................................*/
+	private void saveCurrentTemplate(){
+
+		TemplateRecord localTemplate = (TemplateRecord)ownerModule.templates.getElement(templateName);
+
+		localTemplate.name =  templateName;
+		localTemplate.explanation= getTextFromArea(templateExplanationArea);
+		for (int i=0; i<numFiles; i++) {
+			localTemplate.setStartText(getTextFromArea(startTextArea[i]), i);
+			localTemplate.setTextEach(getTextFromArea(repeatTextArea[i]), i);
+			localTemplate.setEndText(getTextFromArea(endTextArea[i]), i);
+			localTemplate.setBatchFileName(batchFileNameField[i].getText(),i);
+		}
+//		localTemplate.setBatchFileName(localTemplate.setBatchFileName(), 0);
+		localTemplate.matrixExportFormat = matrixExportFormatChoice.getSelectedItem();
+//		localTemplate.setBatchFileName("Batch File " + i, 1);
+//		localTemplate.setStartText(localTemplate.matrixExportFormat, 1);   // note that this is the only thing that can go into the start text of the second batch file.
+//		localTemplate.setTextEach(getTextFromArea(repeatTextArea[1]), 1);
+		
+		String contents = localTemplate.toNEXUSString();
+		MesquiteFile.putFileContents(localTemplate.path, contents, true); 
+		if (chooseDLOG !=null) {
+			chooseDLOG.selectTemplate(localTemplate.name);
+			chooseDLOG.setTemplate(ownerModule.templates.indexOfByName(templateName));
+			chooseDLOG.resetTemplateItems();
+			chooseDLOG.setDefaultComponent(null);
+			chooseDLOG.prepareDialogHideFirst();
+		}
+ 		ownerModule.storePreferences();
+	}
+	private String getTextFromArea(TextArea a){
+		int count = 0;
+		while (count++<10){
+			try {
+				String s = a.getText();
+				if (s==null)
+					return "";
+				return s;
+		        }
+		        catch (Exception e){
+		        	//MesquiteMessage.warnProgrammer("Exception in getText of SingleLineTextField");
+		        }
+	        }
+	        return "";
+	}
+/*.................................................................................................................*/
+  	private void setTemplate(int item){
+	  		if (item >=0 && item < ownerModule.templates.size()){
+	  			currentTemplate = (TemplateRecord)ownerModule.templates.elementAt(item);
+				for (int i=0; i<numFiles; i++) {
+					startTextString[i] = currentTemplate.getStartText(i);
+					repeatTextString[i] = currentTemplate.getTextEach(i);
+					endTextString[i] = currentTemplate.getEndText(i);
+					batchFileNameString[i] = currentTemplate.getBatchFileName(i, null, false);
+				}
+				matrixExportFormatString = currentTemplate.matrixExportFormat;
+				templateExplanation = currentTemplate.getExplanation();
+				if (StringUtil.blank(matrixExportFormatString))
+					matrixExportFormatString = TemplateRecord.defaultExportFormat;
+				if (startTextArea[0] !=null){
+					for (int i=0; i<numFiles; i++) {
+						startTextArea[i].setText(currentTemplate.getStartText(i));
+						repeatTextArea[i].setText(currentTemplate.getTextEach(i));
+						endTextArea[i].setText(currentTemplate.getEndText(i));
+						batchFileNameField[i].setText(currentTemplate.getBatchFileName(i, null, false));
+					}
+					templateExplanationArea.setText(currentTemplate.getExplanation());
+					matrixExportFormatChoice.select(matrixExportFormatString);
+					return;
+				}
+				return;
+			}
+			for (int i=0; i<numFiles; i++) {
+				startTextString[i] = "";
+				repeatTextString[i] = "";
+				endTextString[i] = "";
+				batchFileNameString[i] = "Batch File " + i;
+			}
+			matrixExportFormatString = TemplateRecord.defaultExportFormat;
+			templateExplanation = "";
+			if (startTextArea[0] !=null){
+				for (int i=0; i<numFiles; i++) {
+					startTextArea[i].setText("");
+					repeatTextArea[i].setText("");
+					endTextArea[i].setText("");
+					batchFileNameField[i].setText("Batch File " + i);
+				}
+				templateExplanationArea.setText("");
+				matrixExportFormatChoice.select(matrixExportFormatString);
+			}
+		
+  	}
+}
+
+
+
+
+
+/*=======================================================================*/
+class EditFileSpecificsDLOG extends ExtensibleListDialog {
+	BatchTemplateManager ownerModule;
+	ChooseTemplateDLOG chooseDLOG;
+	boolean editLastItem = false;
+	
+	public EditFileSpecificsDLOG (BatchTemplateManager ownerModule, ChooseTemplateDLOG chooseDLOG){
+		super(ownerModule.containerOfModule(), "Code Snippet Manager", "Code Snippets", ownerModule.fileSpecifics);
+		this.ownerModule = ownerModule;
+		this.chooseDLOG = chooseDLOG;
+		String message = "This dialog box allows you to create and edit snippets of code stored in the current file or project, to be inserted into batch files according to their names.";
+		message += "  They are used, for instance, in parametric bootstrapping to store commands (specific to this file) that might be placed in the batch file to instruct another program.";
+		message += " Code snippets are stored in the Mesquite file, and thus in order to save them, you need to save the Mesquite file.";
+		appendToHelpString(message);
+		setHelpURL(ownerModule,"");
+		
+		
+		if (chooseDLOG!=null) {
+			String s = chooseDLOG.getNameOfFirstUnavailableSnippetNeeded();
+			if (s!=null) {
+				if (AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Create new snippet?", "This template uses an undefined code snippet called \""+s + "\".  Do you want an empty snippet created with that name?", "Create New", "No", 1)) {
+					newElement(s);
+					editLastItem = true;
+				}
+			}
+		}
+		
+		completeAndShowDialog("Done", null, true, null);
+					
+	}
+/*.................................................................................................................*/
+ 	public void windowOpened(WindowEvent e){
+ 		if (editLastItem)
+			editNumberedElement(getLastItem());
+		editLastItem = false;
+		super.windowOpened(e);
+	}
+/*.................................................................................................................*/
+/** this is the name of the class of objects */
+	public  String objectName(){
+		return "Code Snippet";
+	}
+/*.................................................................................................................*/
+/** this is the name of the class of objects */
+	public  String pluralObjectName(){
+		return "Code Snippets";
+	}
+/*.................................................................................................................*/
+	public Listable createNewElement(String name, MesquiteBoolean success){
+		MesquiteString ms = new MesquiteString("");
+		ms.setName(name);
+		success.setValue(true);
+		return ms;
+	}
+/*.................................................................................................................*/
+	public void deleteElement(int item, int newSelectedItem){
+		ownerModule.deleteFileSpecific(item);
+	}
+/*.................................................................................................................*/
+	public void renameElement(int item, Listable element, String newName){
+		ownerModule.renameFileSpecific(item,newName);
+	}
+/*.................................................................................................................*/
+	public Listable duplicateElement(String name){
+		MesquiteString s = new MesquiteString();
+		s.setName(name);
+		s.setValue(((MesquiteString)currentElement).getValue());
+		return s;
+	}
+/*.................................................................................................................*/
+	public boolean getEditable(int item){
+		return true;
+	}
+/*.................................................................................................................*/
+	public void editElement(int item){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog editDialog = new ExtensibleDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Edit Code of Snippett",  buttonPressed);
+		editDialog.addLabel("Snippet \"" + ((MesquiteString)currentElement).getName() + "\"", Label.LEFT);
+		TextArea snippetCodeTextArea = editDialog.addTextArea(((MesquiteString)currentElement).getValue(), 3);
+		editDialog.completeAndShowDialog(true);
+		
+		boolean ok = (editDialog.query()==0);
+		if (ok) 
+			((MesquiteString)currentElement).setValue(snippetCodeTextArea.getText());
+			
+		editDialog.dispose();
+	}
+}
+
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/manual.html b/Source/mesquite/batchArch/BatchTemplateManager/manual.html
new file mode 100644
index 0000000..e475e3b
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/manual.html
@@ -0,0 +1,27 @@
+<HTML>
+<!--This file created 14/3/01 8:53 AM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Batch File Template Manager</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=42 BOTTOM=757 LEFT=4 RIGHT=534>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+</HEAD>
+<BODY>
+<H2><TABLE BORDER=4 CELLPADDING=0>
+   <TR>
+       <TD>
+         <H2>Mesquite: Batch File Template Manager</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>September 2003</P>
+
+<p> </p><P>© David Maddison & Wayne Maddison, 2003</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/templates/NONA.template b/Source/mesquite/batchArch/BatchTemplateManager/templates/NONA.template
new file mode 100644
index 0000000..ddf6943
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/templates/NONA.template
@@ -0,0 +1,8 @@
+#MESQUITEINIT BATCHFILE 1
+name = 'Basic NONA tree search'
+explanation = 'Batch file to request NONA to do basic tree search on each data matrix, saving a tree file for each'
+repeat1 = 'proc <name><number>.ss;^nh 100;^namb=;^nemp;^nsv* <name><number>.tre;^nsv/;^ndata -;^nz;'
+end1 = 'proc/;'
+repeat2 = '<name><number>.tre'
+matrixExportFormat = 'NONA, Hennig86, PiWe, WinClada'
+batchFileName1 = 'batch.ss'
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/templates/aPAUPTestConstPars.template b/Source/mesquite/batchArch/BatchTemplateManager/templates/aPAUPTestConstPars.template
new file mode 100644
index 0000000..7cc10f4
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/templates/aPAUPTestConstPars.template
@@ -0,0 +1,10 @@
+#MESQUITEINIT BATCHFILE 1
+ name = 'PAUPConstraintTestParsimony'
+ explanation = 'This template produces a batch file to request PAUP to find the most parsimonious trees that match a constraint, and the most parsimonious ones unconstrained, for each matrix.  It asks PAUP to write the results to a score file.  '
+ start1 = '#NEXUS^nbegin paup;^n	log file=''<name>.log'';^n	set autoclose nowarnreset tcompress torder=right;^n	defaults hs <snippet>search options</snippet>;'
+ repeat1 = '	execute ''<name><number>.nex'';^n	set criterion=parsimony;^n	constraint theConstraint= <tree>;^n	hs enforce noconverse constraint=theConstraint;^n 	pscore 1/scorefile=''<name>Score.scr'' append;^n	hs noenforce;^n	pscore 1/scorefile=''<name>Score.scr'' append;'
+ end1 = '	log stop;^nend;'
+ batchFileName1 = PaupCommands.nex
+ start2 = 'MesquiteInstructions^nnumVariables = 2^nnumFiles = 1^nfile1 = ''itemsPerRecord=8 v1=4 v2=8''^nrecordLabel = ''Replicates''^nformula = ''v1-v2''^nlabel1 = ''Constrained treelength''^nlabel2 = ''Unconstrained treelength'''
+ batchFileName2 = MesquiteInstructions
+ matrixExportFormat =  NEXUS_file_interpreter
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/templates/basicPAUP.template b/Source/mesquite/batchArch/BatchTemplateManager/templates/basicPAUP.template
new file mode 100644
index 0000000..e85ef8b
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/templates/basicPAUP.template
@@ -0,0 +1,8 @@
+#MESQUITEINIT BATCHFILE 1
+ name = Basic_PAUP_tree_search
+ explanation = 'Batch file to request PAUP to do basic tree search on each data matrix, saving a tree file and consensus tree for each.  It will also produce consensus trees of the consensus trees from each search.'
+ start1 = '#NEXUS^nbegin paup;^n	set autoclose nowarnreset nowarntree nowarntsave;'
+ repeat1 = 'execute ''<name><number>.nex'';^nhs;^nsavetrees file = ''<name><number>.trees'';^ncontree / strict= yes majrule=no treefile = ''CB<name>'' append = yes;'
+ end1 = 'gettrees file = ''CB<name>''  warntree = no allblocks;^nsavetrees file = ''consensus.trees'';^ncontree / strict= yes treefile = ''StrictConsCons.trees'';^ncontree / strict= no majrule=yes treefile = ''MajRuleConsCons.trees'';^nend;'
+ batchFileName1 = paupCommands.nex
+ matrixExportFormat =  NEXUS_file_interpreter
diff --git a/Source/mesquite/batchArch/BatchTemplateManager/templates/simple.template b/Source/mesquite/batchArch/BatchTemplateManager/templates/simple.template
new file mode 100644
index 0000000..e7f8d60
--- /dev/null
+++ b/Source/mesquite/batchArch/BatchTemplateManager/templates/simple.template
@@ -0,0 +1,6 @@
+#MESQUITEINIT BATCHFILE 1
+name = 'Simple List'
+explanation = 'Produces an accessory file consisting of a simple list of the data matrix files'
+repeat1 = '<name><number>.nex'
+matrixExportFormat = 'NEXUS file interpreter'
+batchFileName1 = 'commands.txt'
diff --git a/Source/mesquite/batchArch/ChartFromInstructions/ChartFromInstructions.java b/Source/mesquite/batchArch/ChartFromInstructions/ChartFromInstructions.java
new file mode 100644
index 0000000..19fdfc1
--- /dev/null
+++ b/Source/mesquite/batchArch/ChartFromInstructions/ChartFromInstructions.java
@@ -0,0 +1,810 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.ChartFromInstructions;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+public class ChartFromInstructions extends MesquiteModule implements NumberForItem  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs a module to make a chart.",
+		"The charting module is chosen automatically.");
+	}
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	ItemsCharter chartWindowTask;
+	ChartWindow cWindow;
+	//IntegerArray array1;
+	//IntegerArray array2;
+	Parser parser = new Parser();
+	private Taxa taxa;
+	static int maxNumFiles=2;
+	static int maxNumVariables = 12;
+	
+	int numItems = 0;
+	int numVariables = 0;
+	int currentVariable =-1;
+	int numFiles = 0;
+	String[] arrayPath;
+	String [] labels;
+	MesquiteFile[] arrayFile;
+	String[] files;
+	int[] itemsPerReplicate;
+	boolean[] variableDefined;
+	int[][] variablePosition;  
+	String[] operators;  // the string of operators in the formula;
+	int[] variablesInFormula;
+	NumberArray[] array;
+	int[] numItemsInFile;
+	String formula;
+	String formulaLabel;  // stores the label for the x axis
+	String yaxis;
+	String fileNames;
+	boolean useFormula=true;
+	boolean formulaDefined=false;
+	MesquiteBoolean showFormula;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showFormula = new MesquiteBoolean(false);
+//		showVariable = new MesquiteBoolean(false);
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module obtained.");
+		makeMenu("Chart");
+		addCheckMenuItem(null,"Show Formula", makeCommand("toggleFormula",  this),showFormula);
+		addMenuItem("Set Formula...", makeCommand("setFormula",  this));
+		addMenuItem("Next Variable", makeCommand("showNextVariable",  this));
+		parser.setWhitespaceString("\t");
+		parser.setPunctuationString("");
+		
+		files = new String[maxNumFiles];
+		operators = new String[maxNumFiles];
+		labels = new String[maxNumVariables];
+		variablesInFormula = new int[maxNumVariables];
+		itemsPerReplicate = new int[maxNumFiles];
+		variablePosition = new int[maxNumFiles][maxNumVariables];
+		arrayPath = new String[maxNumFiles];
+		arrayFile = new MesquiteFile[maxNumFiles];
+		numItemsInFile = new int[maxNumFiles];
+		array = new NumberArray[maxNumVariables];
+		variableDefined = new boolean [maxNumVariables];
+
+		for (int i=0; i<maxNumFiles; i++) {
+			itemsPerReplicate[i]=0;
+			for (int j=0; j<maxNumVariables; j++)
+				variablePosition[i][j]=0;
+			operators[i]="";
+		}
+		for (int j=0; j<maxNumVariables; j++){
+			variablesInFormula[j]=-1;
+			variableDefined[j]=false;
+		}
+		
+		MesquiteString directoryName = new MesquiteString("");
+		MesquiteString fileName = new MesquiteString("");
+		String instructionsPath = MesquiteFile.openFileDialog("Choose Instructions File.",  directoryName,  fileName);
+		if (instructionsPath==null)
+			return sorry(getName() + " couldn't start because the instructions file was not chosen.");
+		MesquiteFile instructionsFile =MesquiteFile.open(true, instructionsPath);
+		if (instructionsFile==null || StringUtil.blank(instructionsFile.getFileName())) 
+			return sorry(getName() + " couldn't start because the instructions file could not be found.");
+			
+		String contents = MesquiteFile.getFileContentsAsString(instructionsPath);
+		if (!StringUtil.blank(contents))
+			if (!readInstructionsFile(contents))
+				return sorry(getName() + " couldn't start because instruction file could not be read.  It may not be a valid instruction file."); //D!
+
+				
+		initCurrentVariable();
+		if (numFiles>1)
+			fileNames = "files ";
+		else
+			fileNames = "file ";
+		
+		for (int i=0; i<numFiles; i++) {
+			if (numFiles==1)
+				arrayPath[i] = MesquiteFile.openFileDialog("Choose results file",  directoryName,  fileName);
+			else
+				arrayPath[i] = MesquiteFile.openFileDialog("Choose results file #"+(i+1),  directoryName,  fileName);
+			if (arrayPath[i]==null)
+				return sorry(getName() + " couldn't start because the results file was not chosen.");
+			arrayFile[i] =MesquiteFile.open(true, arrayPath[i]);
+			if (arrayFile[i]==null || StringUtil.blank(arrayFile[i].getFileName())) 
+				return sorry(getName() + " couldn't start because the results file could not be found.");
+			if (i>0) {
+				if (i==numFiles-1)
+					fileNames += " and ";
+				else 
+					fileNames += ", ";
+			}
+			fileNames += "\"" + fileName + "\"";
+		}
+
+		for (int i=0; i<numFiles; i++) 
+			if (itemsPerReplicate[i]>0) {
+				numItemsInFile[i] = (int)numberTokensInFile(arrayFile[i])/itemsPerReplicate[i];
+			}
+		numItems = numItemsInFile[0];
+		for (int i=1; i<numFiles; i++) {
+			if (numItems < numItemsInFile[i])
+				numItems=numItemsInFile[i];
+		}
+
+		for (int i=0; i<maxNumVariables; i++) 
+			array[i] = new NumberArray(numItems);
+		
+			
+		for (int i=0; i<numFiles; i++) {
+			if (!readScoreFile(arrayFile[i],array[i], i))
+				return  sorry(getName() + " couldn't start because the results file could not be read.");
+		}
+		
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setNumberTask(this);
+		ChartInstrItemsSource chartInstructionsItemsSource= new ChartInstrItemsSource(this);
+		chartWindowTask.setItemsSource(chartInstructionsItemsSource);
+		cWindow.setChartTitle(getItemsInfo());
+		cWindow.resetTitle();
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+
+ 		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//getModuleWindow().setTitle("Trees: " + treeSourceTask.getSourceName());
+		return true;
+ 	}
+ 	//D!
+ 	public Class getDutyClass(){
+ 		return ChartFromInstructions.class;
+ 	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			chartWindowTask.incrementSuspension();
+     	 	}
+     	 	else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resumeCalculations")){
+			chartWindowTask.decrementSuspension();
+     	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the chart to visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+    	 		
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Requests that chart calculations be redone", null, commandName, "doCounts")){
+			if (cWindow!=null) {
+				chartWindowTask.doCounts();
+			}
+     	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+       			return chartWindowTask;
+    	 	}
+	       	else if (checker.compare(this.getClass(), "Shows formula", "[on = show; off]", commandName, "toggleFormula")) {
+			if (cWindow!=null) {
+	    	 		showFormula.toggleValue(parser.getFirstToken(arguments));
+				parametersChanged();
+				useFormula=showFormula.getValue();
+				chartWindowTask.doCounts();
+			}
+		}
+	       	else if (checker.compare(this.getClass(), "Sets formula", null, commandName, "setFormula")) {
+			if (cWindow!=null) {
+				if (getFormula()) {
+					chartWindowTask.doCounts();
+				}
+			}
+		}
+	       	else if (checker.compare(this.getClass(), "Shows next variable", null, commandName, "showNextVariable")) {
+			if (cWindow!=null) {
+				if (showFormula.getValue())
+					MesquiteMessage.notifyUser("In order to see individual variables, you first need to turn off Show Formula in the Histogram menu.");
+				else {
+					setCurrentVariableToNext();
+					chartWindowTask.doCounts();
+				}
+			}
+		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+   	public void calcFormulaLabel(){
+		formulaLabel = "";
+		if (variablesInFormula[0]>=0)
+			formulaLabel+=labels[variablesInFormula[0]];
+		if (variablesInFormula[1]>=0)
+			formulaLabel+=" "+operators[1]+" "+labels[variablesInFormula[1]];
+		if (operators[0].equals("-"))
+			formulaLabel = "-(" + formulaLabel+")";
+	}
+	/*.................................................................................................................*/
+   	public boolean getFormula(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Choose Formula",  buttonPressed);
+		dialog.addLabel("Choose Formula", Label.CENTER);
+		int firstVariable=0;
+		
+		Choice signChoice = dialog.addPopUpMenu("Sign: ");
+		signChoice.add(" + ");
+		signChoice.add(" - ");
+		signChoice.select(0);
+		if (!StringUtil.blank(operators[0]))
+			if (operators[0].equals("-"))
+				signChoice.select(1);
+
+
+		Choice firstVariableChoice = dialog.addPopUpMenu("First Variable: ");
+		for (int i=0; i<maxNumVariables; i++)
+			if (variableDefined[i]) {
+				firstVariableChoice.add(labels[i]);
+				if (variablesInFormula[0]==i)
+					firstVariable = i;
+			}
+		firstVariableChoice.select(firstVariable);
+		//dialog.suppressNewPanel();
+		
+		Choice operatorChoice = dialog.addPopUpMenu("Operator: ");
+		operatorChoice.add(" + ");
+		operatorChoice.add(" - ");
+		operatorChoice.add(" * ");
+		operatorChoice.add(" / ");
+		operatorChoice.select(0);
+		if (!StringUtil.blank(operators[1]))
+			if (operators[1].equals("+"))
+				operatorChoice.select(0);
+			else if (operators[1].equals("-"))
+				operatorChoice.select(1);
+			else if (operators[1].equals("*"))
+				operatorChoice.select(2);
+			else if (operators[1].equals("/"))
+				operatorChoice.select(3);
+		
+		//dialog.suppressNewPanel();
+		
+		int secondVariable=-1;
+		Choice secondVariableChoice = dialog.addPopUpMenu("Second Variable: ");
+		secondVariableChoice.add("(None)");
+		for (int i=0; i<maxNumVariables; i++)
+			if (variableDefined[i]){
+				secondVariableChoice.add(labels[i]);
+				if (variablesInFormula[1]==i)
+					secondVariable =i;
+			}
+		secondVariableChoice.select(secondVariable+1);
+		
+		String helpString = "The formula will be\n\n   value = sign (FirstVariable operator SecondVariable).\n\nThus, if you have chosen a sign of \"-\",";
+		helpString += " a first variable of x, and no second variable, the formula would be value = -x.  If you have chosen a sign of  \"-\",";
+		helpString += " a first variable of x, an operator of \"+\", and a second variable of y, the formula would be value = -(x+y).";
+		dialog.appendToHelpString(helpString);
+		
+		
+		dialog.completeAndShowDialog(true);
+			
+		boolean ok = (dialog.query()==0);
+		
+		if (ok) {
+			int count =0;
+			int variableSelected = firstVariableChoice.getSelectedIndex();
+			firstVariable=-1;
+			for (int i=0; i<maxNumVariables; i++)
+				if (variableDefined[i]) {
+					if (variableSelected==count) {
+						firstVariable=i;
+						break;
+					}
+					count++;
+				}
+			variablesInFormula[0] = firstVariable;
+			operators[0]=signChoice.getSelectedItem().substring(1,2);
+			operators[1]= operatorChoice.getSelectedItem().substring(1,2);
+			variableSelected =secondVariableChoice.getSelectedIndex();
+			secondVariable=-1;
+			count=0;
+			for (int i=0; i<maxNumVariables; i++)
+				if (variableDefined[i]) {
+					if (variableSelected==count) {
+						secondVariable=i-1;   // -1 because of the None item
+						break;
+					}
+					count++;
+				}
+			variablesInFormula[1] = secondVariable;
+			calcFormulaLabel();
+		}
+		
+		dialog.dispose();
+
+//   		operators[0]="";
+//   		variablesInFormula[0]=1;
+//   		variablesInFormula[0]=2;
+   		
+		return ok;
+	}
+	/*.................................................................................................................*/
+   	public void initCurrentVariable(){
+   		currentVariable = -1;
+   		for (int i=0; i<maxNumVariables; i++) {
+   			if (variableDefined[i]) {
+   				currentVariable=i;
+   				return;
+   			}
+   		}
+   	}
+	/*.................................................................................................................*/
+   	public void setCurrentVariableToNext(){
+   		if (currentVariable>=maxNumVariables)
+   			currentVariable=-1;
+   		for (int i=currentVariable+1; i<maxNumVariables; i++) {
+   			if (variableDefined[i]) {
+   				currentVariable=i;
+   				return;
+   			}
+   		}
+  		for (int i=0; i<maxNumVariables; i++) {
+   			if (variableDefined[i]) {
+   				currentVariable=i;
+   				return;
+   			}
+   		}
+   	}
+	/*.................................................................................................................*/
+	public boolean readInstructionsFile(String contents){
+		Parser parser = new Parser();
+		parser.setString(contents);
+		String token = parser.getNextToken(); 
+		if (!token.equalsIgnoreCase("MesquiteInstructions")) 
+			return false;
+		Arguments arguments = new Arguments(parser, true);
+		int n = arguments.getParameterValueAsInt("numVariables");
+		if (!MesquiteInteger.isCombinable(n))
+			return false;
+		numVariables = n;
+
+		n = arguments.getParameterValueAsInt("numFiles");
+		if (!MesquiteInteger.isCombinable(n))
+			return false;
+		numFiles = n;
+		formulaDefined=true;
+		formula = arguments.getParameterValue("formula");
+		if (StringUtil.blank(formula)) {
+			formula = "v1";
+			useFormula = false;
+			formulaDefined=false;
+		}
+		yaxis = arguments.getParameterValue("recordLabel");
+		formulaLabel = arguments.getParameterValue("formulaLabel");
+		for (int j=0; j<maxNumVariables; j++) 
+			labels[j]=arguments.getParameterValue("label"+(j+1));
+
+		yaxis = arguments.getParameterValue("recordLabel");
+
+		for (int i=0; i<maxNumFiles; i++) {
+			files[i] = arguments.getParameterValue("file"+(i+1));
+		}
+		for (int i=0; i<maxNumFiles; i++) {
+			if (!StringUtil.blank(files[i])){
+				parser.setString(files[i]);
+				Arguments fileParams = new Arguments(parser, true);
+				n = fileParams.getParameterValueAsInt("itemsPerRecord");
+				if (!MesquiteInteger.isCombinable(n))
+					return false;
+				itemsPerReplicate[i] = n;
+				for (int j=0; j<maxNumVariables; j++) {
+					n = fileParams.getParameterValueAsInt("v"+(j+1));
+					if (MesquiteInteger.isCombinable(n)) {
+						variablePosition[i][j] = n;
+						variableDefined[j]=true;
+					}
+				}
+			}
+		}
+		if (itemsPerReplicate[0]==0 || variablePosition[0][0] == 0 )
+			return false;
+		int variableNum = 0;
+		String s;
+		
+		try {
+			int formulaPos=0;
+			if (formula.charAt(0)=='v') {
+				operators[0]="";
+			}
+			else {
+				operators[0]=formula.substring(0,1);
+				formulaPos++;
+			}
+			formulaPos++;
+			s = formula.substring(formulaPos, formulaPos+1);
+			variableNum = MesquiteInteger.fromString(s,true);
+			if (!MesquiteInteger.isCombinable(variableNum))
+				return false;
+			variablesInFormula[0] = variableNum-1;
+			formulaPos++;
+			operators[1]=formula.substring(formulaPos, formulaPos+1);
+			formulaPos += 2;
+			s = formula.substring(formulaPos, formulaPos+1);
+			variableNum = MesquiteInteger.fromString(s,true);
+			if (!MesquiteInteger.isCombinable(variableNum))
+				return false;
+			variablesInFormula[1] = variableNum-1;
+		}
+		catch (Exception e) {}
+		showFormula.setValue(formulaDefined);
+		//parametersChanged();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public long numberTokensInFile(MesquiteFile file){
+		long count = 0;
+		if (file.openReading()) {
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+			String token;
+			while (!StringUtil.blank(line)) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				token = parser.getNextToken();  // first token in line
+
+				while(!StringUtil.blank(token)) {
+					count++;
+					token = parser.getNextToken();  // next token in line
+				}
+				file.readLine(sb);
+				line = sb.toString();
+			}
+			file.closeReading();
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int numberLinesInFile(MesquiteFile file){
+		int count = 0;
+		if (file.openReading()) {
+			StringBuffer sb = new StringBuffer(1000);
+				file.readLine(sb);
+				String line = sb.toString();		
+			boolean abort = false;
+			while (!StringUtil.blank(line)) {
+				count++;
+				file.readLine(sb);
+				line = sb.toString();		
+			}
+			file.closeReading();
+		}
+		return count;
+	}
+
+
+	/*.................................................................................................................*/
+	
+	public boolean processFileToken(String token, int elementNumber, int scoreFile, int arrayNumber, ProgressIndicator progIndicator){
+		if (elementNumber<=array[arrayNumber].getSize()) {
+			MesquiteNumber value = new MesquiteNumber();
+			value.setValue(token);
+			if (!value.isCombinable()) {
+				MesquiteMessage.notifyUser("An inappropriate entry was found for one of the numbers: \""+ token +"\". The instructions file may need to be revised.");
+				progIndicator.goAway();
+				arrayFile[scoreFile].closeReading();
+				//arrayFile[scoreFile].close();
+				decrementMenuResetSuppression();
+				return false;
+			}
+			array[arrayNumber].setValue(elementNumber,value);
+			return true;
+		}
+		return true;  // return true as don't want to abort the process just because we have found too many elements for this array.
+	}
+	/*.................................................................................................................*/
+	public boolean readScoreFile(MesquiteFile file, NumberArray array, int scoreFile){
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(getProject(),"Reading Results File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		boolean writeTokens = true;
+		if (file.openReading()) {
+			StringBuffer sb = new StringBuffer(100);
+			file.readLine(sb);
+			String line = sb.toString();		
+			//line = file.readLine();		
+			String token;
+			int count = 0;
+			int tokenCount = 0;
+			int num;
+			if (writeTokens) {
+				MesquiteTrunk.mesquiteTrunk.logln("Tokens read in from instruction file from first replicate:  ");
+			}
+			
+			boolean abort = false;
+			while (!StringUtil.blank(line) && !abort) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				
+				token = parser.getNextToken();  // first token in line
+					if (writeTokens) 
+						MesquiteTrunk.mesquiteTrunk.logln("   token " + (tokenCount+1) + ":  " + token);
+				
+				while(!StringUtil.blank(token) && !abort) {
+					tokenCount++;
+					for (int i=0;i<maxNumVariables; i++)
+						if (variablePosition[scoreFile][i] == tokenCount)  // we've found one of the tokens that we want
+							if (!processFileToken(token, count,  scoreFile, i, progIndicator))
+								return false;
+					if (tokenCount>=itemsPerReplicate[scoreFile]) {
+						tokenCount=0;
+						count++;
+						writeTokens = false;
+					}
+					token = parser.getNextToken();  // next token in line
+					if (writeTokens) 
+						MesquiteTrunk.mesquiteTrunk.logln("   token " + (tokenCount+1) + ":  " +  token);
+				}
+				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			if (progIndicator!=null)
+				progIndicator.goAway();
+			file.closeReading();
+			if (abort){ 		
+				//file.close();
+				resetAllMenuBars();
+			}
+		}
+		decrementMenuResetSuppression();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+ 	public void employeeQuit(MesquiteModule m){
+ 		if (m== chartWindowTask)
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+			whichWindow.dispose();
+			iQuit();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("suspendCalculations"); 
+  	 	temp.addLine("getCharter", chartWindowTask); 
+  	 	temp.addLine("setChartVisible"); 
+  	 	temp.addLine("doCounts"); 
+  	 	temp.addLine("resumeCalculations"); 
+  	 	temp.addLine("showWindow");
+  	 	return temp;
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Object object1, Object object2){
+   	}
+    	public void initialize(Taxa taxa){
+    	}
+  	
+	public String accumulateParameters(String spacer){
+		return null;
+	}
+	/*@@@@@@@@@@@@@@@@ These are things that need to be overridden @@@@@@@@@@@@@@@@@@@@@@@@*/
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		if (object1 instanceof MesquiteInteger){	
+			int i = (((MesquiteInteger)object1).getValue());
+			
+			if (currentVariable>=0 && !useFormula)
+				array[currentVariable].placeValue(i, result);
+			else {
+				array[variablesInFormula[0]].placeValue(i, result);
+				if (variablesInFormula[1] < 0) {  // only one value
+					if (operators[0].equals("-")) {
+						result.changeSign();
+					}
+				}
+				else {
+					MesquiteNumber n2 = new MesquiteNumber();
+					array[variablesInFormula[1]].placeValue(i, n2);
+					//array[variablesInFormula[1]].getValue(i));
+					if (operators[1].equals("*"))
+						result.multiplyBy(n2);
+					else if (operators[1].equals("-")) {
+						result.subtract(n2);
+					}
+					else if (operators[1].equals("+"))
+						result.add(n2);
+					else if (operators[1].equals("/"))
+						result.divideBy(n2);
+					if (operators[0].equals("-"))
+						result.changeSign();
+				}
+			}
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+				
+	}
+  	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public String getItemsInfo(){
+   		if (useFormula)
+   			return "Calculations from " + fileNames;
+   		else
+   			return "Values from " + fileNames;
+   	}
+   	/** returns number of items for given Taxa*/
+   	public int getNumberOfItems(){
+   		return numItems;
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Replicate";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Replicates";
+   	}
+   	public String getNameOfValueCalculated(){ 
+   		if (useFormula) {
+   			if (StringUtil.blank(formulaLabel))
+   				calcFormulaLabel();
+   			return formulaLabel;
+   		}
+   		else if (currentVariable>=0)
+   			if (StringUtil.blank(formulaLabel))
+   				return "value";
+   			else
+   				return labels[currentVariable];
+   		return "";
+   	}
+   	/** returns item numbered ic; this will be passed back above as object1*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return new MesquiteInteger(ic);
+   	}
+	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+   	/** If the items given by this source are parts of an Associable, then this method allows charts and other things to query about it,
+   	which allows coordination of item selection to work.*/
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	public void prepareItemColors(Taxa taxa){
+   	}
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+	/*.................................................................................................................*/
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+			if (cWindow!=null && !MesquiteThread.isScripting()) {
+					chartWindowTask.doCounts();
+			}
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Chart from Instruction File";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Chart from Instruction File...";
+   	 }
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Displays a chart summarizing data contained in files, as directed by an instruction file.";
+   	 }
+   	 
+}
+
+
+
+
+
+
+class ChartInstrItemsSource implements ItemsSource  {
+	ChartFromInstructions ownerModule;
+	
+	public ChartInstrItemsSource(ChartFromInstructions ownerModule){
+		this.ownerModule = ownerModule;
+	}
+	
+   	public void initialize(Taxa taxa){}
+   	
+   	public String accumulateParameters(String spacer){
+   		return getParameters();
+   	}
+   	public String getParameters(){
+   		return ownerModule.getItemsInfo(); 
+   	}
+   	public String getNameAndParameters(){
+   		return getParameters();
+   	}
+   	public String getName(){
+   		return "Chart Instructions Item Source";
+   	}
+   	
+   	/** returns number of items for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return ownerModule.getNumberOfItems();   
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Replicate";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Replicates";
+   	}
+   	public String getNameOfValueCalculated(){ 
+   		return ownerModule.getNameOfValueCalculated();  //fed from the module?
+   	}
+   	/** returns item numbered ic; this will be passed back above as object1*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return new MesquiteInteger(ic);
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	public void prepareItemColors(Taxa taxa){
+   	}
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return null;
+   	}
+}
+
+
diff --git a/Source/mesquite/batchArch/ExportMatricesBatch/ExportMatricesBatch.java b/Source/mesquite/batchArch/ExportMatricesBatch/ExportMatricesBatch.java
new file mode 100644
index 0000000..20b992b
--- /dev/null
+++ b/Source/mesquite/batchArch/ExportMatricesBatch/ExportMatricesBatch.java
@@ -0,0 +1,457 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.ExportMatricesBatch; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.batchArch.BatchTemplateManager.BatchTemplateManager;
+import mesquite.batchArch.lib.*;
+
+public class ExportMatricesBatch extends FileInit  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharMatrixSource.class, getName() + " needs a source of matrices for export.",
+		"You can choose the source of character matrices for export when Export Matrices and Batch files is requested.");
+		EmployeeNeed e = registerEmployeeNeed(mesquite.batchArch.ChartFromInstructions.ChartFromInstructions.class, getName() + " needs an assistant to draw charts.",
+		"This is arranged automatically.");
+		
+	}
+ 	ExtensibleDialog dialog = null;
+	TemplateRecord template;
+	TemplateManager templateManager;
+	MesquiteSubmenuSpec mss;//D!
+	CharMatrixSource characterSourceTask;
+	String directoryPath, baseName;
+	boolean writeOnlySelectedTaxa=false;
+
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in.*/
+ 	public void projectEstablished() {
+		//D!
+		mss = getFileCoordinator().addSubmenu(MesquiteTrunk.analysisMenu, "Batch Architect");
+		mss.setZone(2);
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.analysisMenu, mss, "Export Matrices & Batch Files...", makeCommand("exportMatrixBatch",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.analysisMenu, mss, "Export Batch Files...", makeCommand("exportBatch",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.analysisMenu, mss, "Chart Results via Instruction File...", makeCommand("chartInstructionFile",  this));
+		super.projectEstablished();
+ 	}
+ 	
+/*.................................................................................................................*/
+	private void saveFile(String matrixExportFormatName, MesquiteFile file, String fileName, String directoryPath, boolean usePrevious, FileCoordinator coord){
+		if (matrixExportFormatName.equalsIgnoreCase(TemplateRecord.defaultExportFormat) || matrixExportFormatName.equalsIgnoreCase("NEXUS file") || matrixExportFormatName.equalsIgnoreCase("NEXUS file interpreter")) {
+			coord.writeFile(file);
+		}
+		else {
+			FileInterpreterI matrixExportFormat = (FileInterpreterI)coord.findEmployeeWithName(matrixExportFormatName);
+			if (matrixExportFormat!=null) {
+				String ext = matrixExportFormat.preferredDataFileExtension();
+				if (StringUtil.blank(ext))
+					ext = "";
+				else
+					ext = "." + ext;
+				String s = "file = " + StringUtil.tokenize(fileName + ext) + " directory = " + StringUtil.tokenize(directoryPath);
+				s += " noTrees ";
+				if (usePrevious)
+					s+= " usePrevious";
+				boolean success = coord.export(matrixExportFormat, file, s);
+				if (!success)
+						MesquiteMessage.println("FILE SAVING FAILED (" + matrixExportFormatName + ") for " + file.getName());
+
+			}
+			else 
+				MesquiteMessage.println("FILE SAVING FAILED because intepreter not found (" + matrixExportFormatName + ") for " + file.getName());
+
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof mesquite.batchArch.ChartFromInstructions.ChartFromInstructions)
+				//mesquite.genesis.ChartFromInstructions employee = (mesquite.batchArch.ChartFromInstructions)obj;
+  	 			temp.suppressCommandsToEmployee( (MesquiteModule)obj); 
+		}
+ 	 	return temp;
+  	 }
+  	 
+ 	Checkbox writeOnlySelectedTaxaCheckBox = null;
+
+	/*.................................................................................................................*/
+	public Object exportMatricesAndBatchFiles (String arguments,  boolean includeMatrices) {
+ 		//ask user how which taxa, how many characters
+	 		//create chars block and add to file
+	 		//return chars
+	 		
+ 		Taxa taxa = null;
+ 		
+		if (getProject().getNumberTaxas()==0) {
+			alert("Data matrices cannot be created until taxa exist in file.");
+			return null;
+		}
+		else 
+			taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to save copies of character matrices?");
+		if (taxa == null)
+			return null;
+		
+
+		MainThread.incrementSuppressWaitWindow();
+		characterSourceTask = null;
+		if (includeMatrices) {
+			if (StringUtil.blank(arguments))
+				characterSourceTask = (CharMatrixSource)hireEmployee(CharMatrixSource.class, "Export matrices from:");
+			else
+				characterSourceTask = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, arguments);
+		}
+ 		if (characterSourceTask != null || !includeMatrices) {
+			incrementMenuResetSuppression();
+			if (templateManager == null)
+				templateManager= (TemplateManager)getFileCoordinator().findEmployeeWithName("#BatchTemplateManager");
+			if (templateManager == null)
+				return bailOut(null, characterSourceTask, null);
+			
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+ 			int num= MesquiteInteger.unassigned;
+ 			if (includeMatrices)
+ 				num = characterSourceTask.getNumberOfMatrices(taxa);
+ 			ObjectContainer templateContainer = new ObjectContainer();
+ 			
+			String message="";
+			ExtensibleDialog dialog =null;
+			if (includeMatrices) {
+				dialog = templateManager.getChooseTemplateDLOG(taxa, "Export Matrices & Batch Files", templateContainer, buttonPressed, includeMatrices);
+				message = "Export Matrices and Batch Files will save a series of files, each containing a matrix, using the matrix source \"" + characterSourceTask.getName();
+				message += "\".  In addition it will save batch files, based on the chosen template, which may serve to instruct another program (e.g., for parametric bootstrapping).";
+				message += " The format of the matrix file (e.g., NEXUS) is determined by options in the template. ";
+				message += " \n\nTo create and edit templates, or see existing ones, use the Template Manager, available by touching on the \"Edit Templates\" button. ";
+				message += " To create and edit code snippets, or see existing ones, use the Code Snippet Manager, available by touching on the \"Edit Snippets\" button. ";
+				message += " Information about where templates and code snippets are stored is available under the help facility of these managers.";
+				dialog.addLabel("Matrices", Label.LEFT,true,true);
+			}
+			else {
+				dialog = templateManager.getChooseTemplateDLOG(taxa, "Export Batch Files", templateContainer, buttonPressed, includeMatrices);
+				message = "Export Batch Files will save batch files, based on the chosen template, which may serve to instruct another program (e.g., for parametric bootstrapping).";
+				message += " \n\nTo create and edit templates, or see existing ones, use the Template Manager, available by touching on the \"Edit Templates\" button. ";
+				message += " To create and edit code snippets, or see existing ones, use the Code Snippet Manager, available by touching on the \"Edit Snippets\" button. ";
+				message += " Information about where templates and code snippets are stored is available under the help facility of these managers.";
+				dialog.addLabel("Replicates", Label.LEFT,true,true);
+			}
+			dialog.appendToHelpString(message);
+			dialog.setHelpURL(this,"");
+
+			SingleLineTextField baseNameField = dialog.addTextField("Base name:  ", "untitled",20);
+			SingleLineTextField numReps = null;
+			if (!MesquiteInteger.isCombinable(num)) {
+				numReps = dialog.addTextField("Number of replicates:  ","10",8);
+			}
+			if (taxa.anySelected()) {
+				 writeOnlySelectedTaxaCheckBox = dialog.addCheckBox("include data only for selected taxa", writeOnlySelectedTaxa);
+			}
+			dialog.completeAndShowDialog();
+			
+			
+			if (dialog.query() != 0)
+				return bailOut(null, characterSourceTask, null);
+			TemplateRecord template = (TemplateRecord)templateContainer.getObject();
+			if (template == null) 
+				return bailOut(null, characterSourceTask, null);
+			
+			String baseName = baseNameField.getText();
+			if (numReps != null)
+				num = MesquiteInteger.fromString(numReps.getText());
+			if (!MesquiteInteger.isCombinable(num)) 
+				return bailOut(null, characterSourceTask, null);
+
+			String directoryPath = MesquiteFile.chooseDirectory("Choose location for saving files:"); //MesquiteFile.saveFileAsDialog("Base name for files (files will be named <name>1.nex, <name>2.nex, etc.)", baseName);
+			if (StringUtil.blank(directoryPath))
+				return bailOut(null, characterSourceTask, null);
+
+			if (writeOnlySelectedTaxaCheckBox!=null)
+				writeOnlySelectedTaxa= writeOnlySelectedTaxaCheckBox.getState();
+
+				dialog.dispose();
+			dialog = null;
+			
+			//StringBuffer outputBuffer=null;
+			String s2 = "";
+			
+			export(template, directoryPath, baseName, taxa, includeMatrices, characterSourceTask, num);
+
+			fireEmployee(characterSourceTask);
+			resetAllMenuBars();
+			decrementMenuResetSuppression();
+ 		}
+		MainThread.decrementSuppressWaitWindow();
+		return null;
+	}
+	
+	
+	boolean saveBasisTrees = true;
+	
+	/*.................................................................................................................*/
+
+	private Object export(TemplateRecord template,String directoryPath, String baseName,Taxa taxa,  boolean includeMatrices, CharMatrixSource characterSourceTask, int num){
+			if (template == null) {
+				alert("Sorry, the batch file template was not found");
+				return null;
+			}
+			else if (includeMatrices && taxa == null) {
+				alert("Sorry, no taxa were found for Export Matrices & Batch Files");
+				return null;
+			}
+			else if (includeMatrices && characterSourceTask == null) {
+				alert("Sorry, no source of characters was found for Export Matrices & Batch Files");
+				return null;
+			}
+			getProject().incrementProjectWindowSuppression();
+			//Need block of taxa, basename, basePath, template, number of matrices, matrix source (along with its parameters), 
+    			String basePath = directoryPath + MesquiteFile.fileSeparator + baseName;
+			FileCoordinator coord = getFileCoordinator();
+			MesquiteFile tempDataFile = null;
+			if (includeMatrices) {
+				tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(basePath + ".nex"), CommandChecker.defaultChecker); //TODO: never scripting???
+				TaxaManager taxaManager = (TaxaManager)findElementManager(Taxa.class);
+				Taxa newTaxa =taxa.cloneTaxa();
+				newTaxa.addToFile(tempDataFile, null, taxaManager);
+			}
+			boolean showProgress = true;
+			ProgressIndicator progIndicator=null;
+			if (showProgress) {
+				progIndicator = new ProgressIndicator(getProject(),"Saving files", num);
+				progIndicator.start();
+				progIndicator.setCurrentValue(0);
+			}
+				
+			template.composeAccessoryFilesStart(num, baseName, basePath);
+			boolean usePrevious = false;
+			boolean logVerbose = true;
+			CharMatrixManager manager = null;
+			TreeVector trees = null;
+	 		CharacterData newMatrix=null;
+	 		MesquiteTimer timer = new MesquiteTimer();
+	 		timer.start();
+	 		
+			try {
+				for (int iMatrix = 0; iMatrix<num; iMatrix++){
+					if (progIndicator!=null)
+						if (includeMatrices)
+							progIndicator.setText("Saving file "+(iMatrix+1)+" of " + num);
+						else
+							progIndicator.setText("Processing replicate "+(iMatrix+1)+" of " + num);
+					MesquiteThread.setSuppressAllProgressIndicatorsCurrentThread(true);
+			 		MCharactersDistribution matrix = null;
+			 		if (includeMatrices) {
+						logln("Saving file " + basePath + iMatrix + template.fileExtension(template.matrixExportFormat,coord,true));	
+				 		matrix = characterSourceTask.getMatrix(taxa, iMatrix);
+						if (matrix==null)
+							return bailOut(tempDataFile, characterSourceTask, progIndicator);
+
+							CharactersManager manageCharacters = (CharactersManager)findElementManager(CharacterData.class);
+							manager = manageCharacters.getMatrixManager(matrix.getCharacterDataClass());
+					}
+					if (!includeMatrices) {
+						System.gc();
+						String matrixName = null;
+						if (matrix.getParentData()!= null)
+							matrixName = matrix.getParentData().getName();
+						else
+							matrixName = matrix.getName();
+						template.composeAccessoryFilesReplicate(iMatrix, matrixName, 0, baseName, basePath);
+					}
+					else if (manager != null){
+						logVerbose = manager.isLogVerbose();
+						manager.setLogVerbose(false);
+						if (matrix.getBasisTree()!=null && saveBasisTrees) {
+							if (trees == null)
+								trees = new TreeVector(taxa);
+							trees.addElement(matrix.getBasisTree().cloneTree(), false);//no need to establish listener to Taxa, as temporary
+						}
+						newMatrix = matrix.makeCharacterData(manager, taxa);
+						if (writeOnlySelectedTaxa) {
+							for (int it=0; it<taxa.getNumTaxa(); it++) 
+								if (!taxa.getSelected(it))
+									newMatrix.setToInapplicable(it);
+						}
+						newMatrix.setName(characterSourceTask.getMatrixName(taxa, iMatrix));
+						
+						logln(newMatrix.getExplanation() + "\n");	
+						newMatrix.addToFile(tempDataFile, getProject(), null);
+				 	 	tempDataFile.setPath(basePath + iMatrix + template.fileExtension(template.matrixExportFormat,coord, true));
+				 	 	
+				 	 	
+				 	 	saveFile(template.matrixExportFormat, tempDataFile, baseName + iMatrix,directoryPath, usePrevious, coord); 
+				 	 	newMatrix.deleteMe(false);
+						newMatrix = null;
+						if (matrix.getBasisTree()!=null) {
+							matrix.getBasisTree().dispose();
+							matrix.setBasisTree(null);
+						}
+						System.gc();
+						template.composeAccessoryFilesReplicate(iMatrix, characterSourceTask.getMatrixName(taxa, iMatrix), 0, baseName, basePath);
+						manager.setLogVerbose(logVerbose);
+					}
+					MesquiteThread.setSuppressAllProgressIndicatorsCurrentThread(false);
+					if (progIndicator!=null) {
+						progIndicator.setCurrentValue(iMatrix+1);
+						if (progIndicator.isAborted()) {
+							break;
+						}
+					}
+					usePrevious = true;
+					logln("File written by Export matrices & Batch Files: " + basePath + iMatrix + template.fileExtension(template.matrixExportFormat,coord,true) + ".\n   Time taken (ms): " + timer.timeSinceLast() + " ms");
+				}
+			}
+			catch (Exception e) {
+				// clean up anything added
+				if (manager != null){
+					logVerbose = manager.isLogVerbose();
+					manager.setLogVerbose(logVerbose);
+				}
+				MesquiteMessage.notifyUser("There was a problem with creating or exporting the files, and the process was aborted: " + e.getMessage());
+				if (newMatrix!=null) {
+					newMatrix.deleteMe(false);
+					newMatrix = null;
+				}
+			}
+			timer.end();
+			if (trees !=null){
+				if (saveBasisTrees){
+					trees.addToFile(tempDataFile, getProject(), null);
+		 	 		tempDataFile.setPath(basePath + "BasisTrees.nex");
+					 coord.writeFile(tempDataFile);
+				}
+				 trees.dispose();
+			}
+ 			if (tempDataFile !=null) 
+ 				tempDataFile.close();
+			if (progIndicator!=null)//&& outputBuffer != null) 
+				progIndicator.setText("Saving batch files");//���
+			template.composeAccessoryFilesEnd(baseName, directoryPath + MesquiteFile.fileSeparator);
+				
+			if (progIndicator!=null) 
+				progIndicator.goAway();//���
+			getProject().decrementProjectWindowSuppression();
+			return null;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Starts module to read instruction file to present results", null, commandName, "chartInstructionFile")) {
+			return (MesquiteModule)hireNamedEmployee(MesquiteModule.class, "#mesquite.batchArch.ChartFromInstructions");
+    	 	} //D! above
+    	 	else if (checker.compare(this.getClass(), "Saves copies of a series of character matrices to files along with batch files for processing (e.g., parametric bootstrapping)", "[name of module to fill the matrices]", commandName, "exportMatrixBatch")) {
+ 			return exportMatricesAndBatchFiles(arguments,  true);
+ 		}
+    	 	else if (checker.compare(this.getClass(), "Saves batch files for processing (e.g., parametric bootstrapping)", "[name of module to fill the matrices]", commandName, "exportBatch")) {
+ 			return exportMatricesAndBatchFiles(arguments,  false);
+ 		}
+    	 	else if (checker.compare(this.getClass(), "Sets the base name", "[path]", commandName, "setBaseName")) {
+			baseName =  parser.getFirstToken(arguments);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Fires character matrix module", null, commandName, "fireCharSource")) {
+			fireEmployee(characterSourceTask);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the output directory", "[path]", commandName, "setDir")) {
+			directoryPath = MesquiteFile.composePath(getProject().getHomeDirectoryName(), parser.getFirstToken(arguments));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module supplying character matrices", "[name of module]", commandName, "setCharacterSource")) {
+    	 		CharMatrixSource newCharacterSourceTask=  (CharMatrixSource)replaceEmployee(CharMatrixSource.class, arguments, "Source of characters for Export Matrices & Batch Files", characterSourceTask);
+   	 		if (newCharacterSourceTask!=null) {
+	   			characterSourceTask = newCharacterSourceTask;
+ 			}
+ 			return characterSourceTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Saves matrices & batch files for processing (e.g., parametric bootstrapping); for use in scripting.  Assumes matrix source, output directory & base name already set", "[template][taxa reference][include matrices][number of replicates]", commandName, "export")) {
+			//e.g. of arguments: "'Simple List'  'ex' 0 include 5";
+			if (characterSourceTask ==null)
+				return null;
+			String templateName = parser.getFirstToken(arguments);
+			String ct = templateName;
+			if (templateManager == null)
+				templateManager= (TemplateManager)getFileCoordinator().findEmployeeWithName("#BatchTemplateManager");
+			if (templateManager == null)
+				 return null;
+			TemplateRecord template = templateManager.getTemplate(templateName);
+   	 		Taxa taxa = getProject().getTaxaLastFirst( ct = parser.getNextToken());
+			boolean includeMatrices = "include".equalsIgnoreCase(ct = parser.getNextToken());
+			int num = MesquiteInteger.fromString(ct = parser.getNextToken());
+ 			return export(template, directoryPath, baseName, taxa, includeMatrices, characterSourceTask, num);
+ 		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	
+   	private Object bailOut(MesquiteFile tempDataFile, MesquiteModule characterSourceTask, ProgressIndicator progIndicator){
+		if (tempDataFile !=null)
+			tempDataFile.close();
+		if (progIndicator !=null)
+			progIndicator.goAway();
+		if (dialog != null) {
+			dialog.dispose();
+			dialog = null;
+		}
+		if (characterSourceTask!=null)
+			fireEmployee(characterSourceTask);
+		MesquiteThread.setSuppressAllProgressIndicatorsCurrentThread(false);
+		resetAllMenuBars();
+		decrementMenuResetSuppression();
+		MainThread.decrementSuppressWaitWindow();
+		return null;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Export Matrices & Batch Files";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Saves copies of matrices to separate files for subsequent batch analysis (e.g., parametric bootstrapping)." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false; 
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+   	 
+	/*.................................................................................................................*
+   	Tree getTree(Taxa taxa){
+		Tree tree = null;
+		if (treeSourceTask == null)
+			treeSourceTask= (TreeSource)hireNamedEmployee(TreeSource.class, "#StoredTrees");
+		if (treeSourceTask!=null) {
+			int treeNum = treeSourceTask.queryUserChoose(taxa, "Which tree?");
+			if (MesquiteInteger.isCombinable(treeNum))
+				tree = treeSourceTask.getTree(taxa, treeNum);
+		}
+		return tree;
+   	}
+   	/**/
+}
+	
+
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/aBatchArchIntro.java b/Source/mesquite/batchArch/aBatchArchIntro/aBatchArchIntro.java
new file mode 100644
index 0000000..93b3d40
--- /dev/null
+++ b/Source/mesquite/batchArch/aBatchArchIntro/aBatchArchIntro.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 2000 and onward, D. Maddison and W. Maddison.
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.aBatchArchIntro;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class aBatchArchIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aBatchArchIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides facilities to coordinate the simulation of data and generate batch files for replicated analyses.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Batch Architect Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Batch Architect Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, D.R.,  & W.P. Maddison.  2006.  Batch Architect: automation of simulations and replicated analyses.  A package of modules for Mesquite. version 1.1.";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+}
+
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/batchtemplate.gif b/Source/mesquite/batchArch/aBatchArchIntro/batchtemplate.gif
new file mode 100644
index 0000000..62d2d79
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/batchtemplate.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/batchtemplates.html b/Source/mesquite/batchArch/aBatchArchIntro/batchtemplates.html
new file mode 100644
index 0000000..ffb3d4c
--- /dev/null
+++ b/Source/mesquite/batchArch/aBatchArchIntro/batchtemplates.html
@@ -0,0 +1,107 @@
+<HTML>
+<!--This file created 14/3/01 8:53 AM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Batch Architect: Design of Batch Templates</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=42 BOTTOM=757 LEFT=4 RIGHT=534>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+<BODY bgcolor="#FFFFCC">
+<H2><TABLE BORDER=0 CELLPADDING=4>
+   <TR>
+      <TD> <P><img src="splash.gif" width="164" height="64"></P>
+      </TD>
+      <TD>
+         <H2>Batch Architect: Design of Batch Templates</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<p><a href="index.html">Return to Batch Architect Page</a></p>
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>The Template Editor for editing Batch File templates appears as follows:</P>
+<P align="center"><img src="batchtemplate.gif" width="348" height="408"></P>
+<P> </P>
+<P>The text entered into the "Text for start of batch file" field will 
+  be written once, at the start of the file; the text in "Repeated text, 
+  written for each replicate" will be written as many times as there are 
+  replicates; the text in "Text for end of batch file" will be written 
+  at the end of the file. The following codes included in these fields will be 
+  replaced in the batch file as follows:</P>
+<ul>
+  <li><name> will be replaced by the text entered in the "base name" 
+    field in the Export Matrices & Batch Files or Export Batch Files dialog 
+    boxes.</li>
+  <li><tree> will be replaced by the Newick formatted text description of 
+    the tree chosen in the Export Matrices & Batch Files or Export Batch Files 
+    dialog boxes.</li>
+  <li><snippet></snippet> surrounding the name of a code snippet will 
+    be replaced by the text of the code snippet</li>
+  <li><fileExtension> will be replaced by the extension (with dot, if present; 
+    e.g., ".nex", ".ss") that Mesquite will write based upon 
+    the matrix format. </li>
+  <li><matrixFormat> will be replaced by the name of the matrix format (e.g., 
+    "NEXUS file")</li>
+  <li><random> numValues=n lowerBound=b1 upperBound=b2 type=double|long 
+    withReplacement=yes|no </random> will be replaced by n random numbers 
+    chosen with a uniform distribution over the range b1 through b2 inclusive, 
+    with replacement or not. The numbers are either real numbers (if type=double 
+    is chosen) or integers (type=long). For example, <random>numValues=3 
+    lowerBound=1 upperBound=100 type=long withReplacement=no</random> entered 
+    in the repeated text field might be replaced by "86 42 23" in one 
+    replicate, and "5 73 31" in the next replicate. </li>
+</ul>
+<P>For the field "Repeated text, written for each replicate", the following 
+  replacement will also be made:</P>
+<ul>
+  <li><number> will be replaced by the number of the replicate</li>
+</ul>
+<P>For example, consider 5 replicates run with a base name of "matrix" 
+  for a template with the following specification:</P>
+<P align="center"><img src="templateeg.gif" width="445" height="270"></P>
+<P>A file called "commands.nex" would be created by Mesquite that would 
+  look like this:</P>
+<P> </P>
+<pre>  #NEXUS
+  begin paup;
+        set autoclose nowarnreset nowarntree nowarntsave;
+        execute 'matrix1.nex';
+        hs;
+        savetrees file = 'maxtrix1.nex';
+
+        execute 'matrix2.nex';
+        hs;
+        savetrees file = 'matrix2.nex';
+
+        execute 'matrix3.nex';
+        hs;
+        savetrees file = 'matrix3.nex';
+
+        execute 'matrix4.nex';
+        hs;
+        savetrees file = 'matrix4.nex';
+
+        execute 'matrix5.nex';
+        hs;
+        savetrees file = 'matrix5.nex';
+  end;
+</pre>
+<P> </P>
+<P>Up to five separate batch files can be specified for any one Batch File Template.</P>
+<p>The "Format of Matrices" choice will be ignored if matrices are not 
+  being exported (e.g., if Export Batch Files was chosen).</p>
+<p> </p>
+
+<P>
+
+<HR>
+
+</P>
+
+<P>© David Maddison & Wayne Maddison, 2003</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/emb1.gif b/Source/mesquite/batchArch/aBatchArchIntro/emb1.gif
new file mode 100644
index 0000000..9634df0
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/emb1.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/index.html b/Source/mesquite/batchArch/aBatchArchIntro/index.html
new file mode 100644
index 0000000..8fa17a3
--- /dev/null
+++ b/Source/mesquite/batchArch/aBatchArchIntro/index.html
@@ -0,0 +1,166 @@
+<HTML>
+<!--This file created 14/3/01 8:53 AM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Batch Architect Package</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=42 BOTTOM=757 LEFT=4 RIGHT=534>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+<BODY bgcolor="#FFFFCC">
+<H2> 
+  <TABLE BORDER=0 CELLPADDING=4>
+    <TR> 
+      <TD>
+<P><img src="splash.gif" width="164" height="64"></P></TD>
+      <TD> <H2>Batch Architect package for the Mesquite system</H2></TD>
+    </TR>
+  </TABLE>
+</H2>
+
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>August 2005</P>
+
+<P>This package of modules supplies basic importing and exporting
+services to Mesquite.</P>
+
+<UL>
+  <LI><A HREF="#overview">Overview</A></LI>
+  <LI><A HREF="#installation">Installation</A></LI>
+  <LI><A HREF="#features">Features</A>
+    <ul>
+      <li><a href="#embf">Export Matrices & Batch Files</a></li>
+      <li><a href="#ebf">Export Batch Files</a></li>
+      <li><a href="#batchtemplates">Batch Templates</a></li>
+      <li><a href="#codesnippets">Code Snippets</a></li>
+      <li><a href="#chartresults">Chart Results via Instruction File</a></li>
+    </ul>
+  </LI>
+  <LI><A HREF="#examples">Examples</A></LI>
+  <LI><A HREF="#citation">Citation</A></LI>
+</UL>
+
+<H3><A NAME=overview></A>Overview</H3>
+
+<P>This package automates the generation of files with repeated elements as well 
+  as the processing of files with repeated records.</P>
+<P>One can ask Mesquite to build a "batch" file that can serve as a 
+  command file for another program such as PAUP* that does repetitive analyses. 
+  For example, one might simulate 100 matrices under a particular model of evolution, 
+  and for each of these matrices, include an entry in a batch file that asks PAUP 
+  to analyze that matrix, saving tree files for the matrix. At the same time, 
+  another batch file might be created that could be used to ask another program 
+  to read in, sequentially, each tree file, and conduct a synthetic analysis on 
+  them. </P>
+
+<H3><A NAME=installation></A>Installation</H3>
+
+<P>To install the basic Batch Architect package, the "batchArch" directory must 
+  be installed in the "mesquite" directory within "Mesquite Folder". It should 
+  be present in a basic Mesquite installation.</P>
+
+<H3><A NAME=features id="features"></A>Features</H3>
+<h4><a name="embf"></a>Export Matrices & Batch Files</h4>
+<p>This feature, in the Batch Architect submenu in the Analysis menu, will export 
+  multiple matrices and one or more associated batch files. </p>
+<p>In choosing this feature, you will first be led through as serious of dialog 
+  boxes in which you will choose how the matrices are to be created. Following 
+  your choosing, the Export Matrices & Batch Files dialog box will be presented:</p>
+<p align="center"><img src="emb1.gif" width="336" height="356"></p>
+<p>In this dialog box you are to specify the base name to be used both for the 
+  matrices and in the batch file template system. For example, in the example 
+  shown, 10 matrices will be created, with names "SimMatrix1", "SimMatrix2", 
+  "SimMatrix3", and so on. </p>
+<p>The file names may have extensions added (e.g., ".nex"), depending 
+  upon the matrix format to be used (the matrix format is specified in the batch 
+  file template). The extension will be added automatically by Mesquite.</p>
+<p>In this dialog you will most importantly also select the batch template to 
+  use. A batch template specifies exactly how the batch file or files produced 
+  will be structured. To examine or edit the template, use the Edit Templates 
+  button. </p>
+<p>Some batch templates contain code that requires "<a href="#codesnippets">code 
+  snippets</a>" to be defined. If code snippets are needed by a template, 
+  they will be listed in the dialog box. If some are needed but unavailable, the 
+  list will appear in red and note them as unavailable:</p>
+<p align="center"><img src="snippetNeeded.gif" width="320" height="48"> </p>
+<p>You can define or edit snippets uing the Edit Snippets button.</p>
+<p>Some batch templates require a tree to be chosen by the user; if so, and you 
+  have not yet chosen a tree, "TREE NEEDED" will appear in red in the 
+  box beside the Choose Tree button:</p>
+<p align="center"><img src="treeNeeded.gif" width="248" height="24"></p>
+<p>You can then use the Choose Tree button to choose your tree.</p>
+<h4><a name="ebf"></a>Export Batch Files</h4>
+<p>This is similar to the Export Matrices & Batch Files feature expect that 
+  no matrices are exported. This can be used to generate batch files for already 
+  existing matrices, for example, or to automate processes other than the analyses 
+  of matrices.</p>
+<h4><a name="batchtemplates"></a>Batch Templates</h4>
+<P>Batch templates contain the instructions telling Mesquite how to construct 
+  the batch files. They are managed in the Batch Template Manager window, which 
+  allow ones to create, duplicate, edit, rename, or delete templates:</P>
+<P align="center"><img src="templateManager.gif" width="275" height="237"></P>
+<P>You can also load templates from template files; this allows you to move templates 
+  between copies of Mesquite. For example, if you create a template on one computer, 
+  it will be stored as a single text file in the BatchTemplates in the Mesquite_Prefs 
+  directory in the Mesquite_Support_Files directory on your disk. You can then 
+  move that file to another computer, and load it into Mesquite on that computer 
+  using the Load button. </P>
+<P>Selecting a template in the Batch File Template Manager and pressing "View" 
+  (if it is a pre-defined template) or "Edit..." (if it is a user-defined 
+  template) will bring forth the Batch Template Editor, in which the template 
+  can be viewed or edited:</P>
+<P align="center"><img src="batchtemplate.gif" width="348" height="408"></P>
+<P>See the page on <a href="batchtemplates.html">Designing Batch Templates</a> 
+  for details on the formats used. Batch templates can be edited using the submenu 
+  in Mesquite's Edit menu, or from the Export Matrices & Batch Files or Export 
+  Batch Files dialog boxes.</P>
+<P>The pre-defined templates can be viewed and duplicated, but not renamed or 
+  edited. Their duplicates can be renamed and edited.</P>
+<h4><a name="codesnippets"></a>Code Snippets</h4>
+<P>Code snippets are designed as file-specific elements that are to be used in 
+  place of tagged elements in the batch templates. For example, if in a batch 
+  template the following text appeared:</P>
+<pre>   exec setParameterValues;
+   <snippet>search command</snippet>
+   display all;</pre>
+<p>then within the Mesquite file you could store a code snippet called "search 
+  command" whose contents would be inserted in place of the above text when 
+  the batch file was created. If the text of "search command" was</p>
+<pre>   hsearch nreps=100 addseq=random swap=tbr;</pre>
+<P>then the batch file, when written, would contain</P>
+<pre>   exec setParameterValues;
+   hsearch nreps=100 addseq=random swap=tbr;
+   display all;
+
+</pre>
+<p>Batch templates can be edited using the Batch File Templates submenu in Mesquite's 
+  Edit menu, or from the Export Matrices & Batch Files or Export Batch Files 
+  dialog boxes.</p>
+<h4><a name="chartresults"></a>Chart Results via Instruction File</h4>
+<P>If you have a text file on disk containing tab-delimited data, you can design 
+  a Mesquite Instruction file that will give Mesquite enough information about 
+  the data file to allow Mesquite to read it. See <a href="instructions.html">Instructions 
+  File Format</a> for details about the way Mesquite Instruction files are to 
+  be structured.</P>
+<P>Some of the batch templates distributed with Mesquite have instruction files 
+  defined within them.</P>
+<H3><a name=examples></a>Examples</H3>
+<p>See the <a href="../../../docs/mesquite/RandomSimul/RandomSimul.html">Simulations 
+  and Randomizations</a> page of the Mesquite manual for examples.</p>
+<H3>Citation</H3>
+
+<P> Maddison, D.R., & W.P. Maddison. 2005. Batch Architect: automation of 
+  simulations and replicated analyses. A package of modules for Mesquite. Version 
+  1.06.</P>
+
+<P>
+
+<HR>
+
+</P>
+
+<P>© David Maddison & Wayne Maddison, 2005</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/instructions.html b/Source/mesquite/batchArch/aBatchArchIntro/instructions.html
new file mode 100644
index 0000000..5cd36da
--- /dev/null
+++ b/Source/mesquite/batchArch/aBatchArchIntro/instructions.html
@@ -0,0 +1,131 @@
+<HTML>
+<!--This file created 14/3/01 8:53 AM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Batch Architect: Instructions File Format</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=42 BOTTOM=757 LEFT=4 RIGHT=534>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+<BODY bgcolor="#FFFFCC">
+<H2> 
+  <TABLE BORDER=0 CELLPADDING=4>
+   <TR>
+      <TD> <P><img src="splash.gif" width="164" height="64"></P>
+      </TD>
+      <TD> <H2>Batch Architect: Instruction File Format</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<p><a href="index.html">Return to Batch Architect Page</a></p>
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>A Mesquite Instruction File is a text file describing the contents of one or 
+  more other text files containing data. The Instruction File gives enough details 
+  about the other text files to allow Mesquite to be able to read it. </P>
+<h4>Structure of the data file to be read</h4>
+<P>The data file that is to be described by the Instructions File must consist 
+  of a series of records, each record represented by the same number of elements, 
+  and each element must be separated by either a tab or a new line or carriage 
+  return. For example, you might have a file with various numbers given for each 
+  of a series of five trees. The data for each tree might be on a single line, 
+  and there might be three numbers per tree. There would thus be five records 
+  (corresponding to the five trees), and each record would have exactly three 
+  numbers. </P>
+<h4>Instruction File format</h4>
+<P>The format of the instruction file is currently very primitive and simple; 
+  eventually, it will be altered to use standard languages such as XML, and allow 
+  more flexibility, but for the moment it is formatted as follows.</P>
+<ol>
+  <li> The first line must be "MesquiteInstructions"<br>
+  </li>
+  <li>The second line gives the number of data elements to be read in and stored 
+    for each record. Currently the maximum number of elements to 
+    be stored is 12. There can be many more elements per record, but if there 
+    are more than the maximum number, some of them will not be able to be stored 
+    by Mesquite. The form of this line is<br>
+    <br>
+    numVariables = <number of elements to be read and stored><br>
+  </li>
+  <li>The third line describes how many files are to be read. The current maximum 
+    is 2. If more than one file is to be read, the two files need not have the 
+    same format.<br>
+  </li>
+  <li>The next lines specify the layout of each file to be read, using the format:<br>
+    <br>
+    file1 = 'itemsPerRecord=<number of elements total in each record> v1=<element 
+    number of first variable> v2=<element number of second variable>...'<br>
+    <br>
+    For the second file, use <br>
+    <br>
+    file2 = ...<br>
+  </li>
+  <li>An optional line can be included specifying the name to be applied to the 
+    records:<br>
+    <br>
+    recordLabel = <label for records><br>
+  </li>
+  <li>An optional line can be included specifying a simple formula to manipulate 
+    the data, of the form:<br>
+    <br>
+    formula = 'v1-v2'<br>
+    <br>
+    The formula can consist of nothing more than two variables with one of the 
+    standard four operators (+, -, *, /).<br>
+    <br>
+    If a formula is defined, you can label it with<br>
+    <br>
+    formulaLabel = <label for formula><br>
+  </li>
+  <li>Optional lines can then be give naming each of the variables that has been 
+    stored:<br>
+    <br>
+    label1 = <label for variable 1><br>
+    label2 = <label for variable 2><br>
+  </li>
+</ol>
+<p>For each of these parts of the description, the <specification> part 
+  must consist of a single token; thus, if you wish to label something with multiple 
+  words, surround them by single quotes, as in 'Gamma Shape'.</p>
+<h4>Example</h4>
+<P>Imagine that you wished to ask PAUP* to estimate the value of the gamma shape 
+  parameter and proportion of invariant characters for a series of trees. The 
+  PAUP* commands you might give are:<br>
+</P>
+<pre>   lset basefreq=empirical nst=1 pinvar=estimate rates=gamma shape=estimate;
+   lscoreall/scorefile='score';</pre>
+<P>The start of the score file that would be generated would look something like 
+  this:</P>
+<pre>   Tree -lnL p-inv gamma shape
+   1 8430.14114160 0.59050567 1.075992
+   2 8410.59386351 0.57306194 0.991805
+   3 7922.53719113 0.64386747 1.401232</pre>
+<p>The first step would be to strip the first line out of the score file, to yield:</p>
+<pre>   1 8430.14114160 0.59050567 1.075992 
+   2 8410.59386351 0.57306194 0.991805 
+   3 7922.53719113 0.64386747 1.401232</pre>
+<p>Each record has four items. If you wished Mesquite to read in only the estimate 
+  of the porportion of invariable characters and the gamma shape parameters, then 
+  you will want Mesquite to read in the third and fourth item in each record. 
+  The MesquiteInstructions file for processing this might then be:</p>
+<pre>   MesquiteInstructions
+   numVariables = 2
+   numFiles = 1
+   file1 = 'itemsPerRecord=4 v1=3 v2=4'
+   recordLabel = 'Replicates'
+   label1 = 'proportion invariable
+   label2 = 'gamma shape'</pre>
+<p> </p>
+
+<P>
+
+<HR>
+
+</P>
+
+<P>© David Maddison & Wayne Maddison, 2005</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/oneGear.psd b/Source/mesquite/batchArch/aBatchArchIntro/oneGear.psd
new file mode 100644
index 0000000..4cd6ea3
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/oneGear.psd differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/snippetNeeded.gif b/Source/mesquite/batchArch/aBatchArchIntro/snippetNeeded.gif
new file mode 100644
index 0000000..620fbd9
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/snippetNeeded.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/splash.gif b/Source/mesquite/batchArch/aBatchArchIntro/splash.gif
new file mode 100644
index 0000000..ea27b50
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/splash.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/templateManager.gif b/Source/mesquite/batchArch/aBatchArchIntro/templateManager.gif
new file mode 100644
index 0000000..5dd5294
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/templateManager.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/templateeg.gif b/Source/mesquite/batchArch/aBatchArchIntro/templateeg.gif
new file mode 100644
index 0000000..3719f1b
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/templateeg.gif differ
diff --git a/Source/mesquite/batchArch/aBatchArchIntro/treeNeeded.gif b/Source/mesquite/batchArch/aBatchArchIntro/treeNeeded.gif
new file mode 100644
index 0000000..5eebb47
Binary files /dev/null and b/Source/mesquite/batchArch/aBatchArchIntro/treeNeeded.gif differ
diff --git a/Source/mesquite/batchArch/lib/TemplateManager.java b/Source/mesquite/batchArch/lib/TemplateManager.java
new file mode 100644
index 0000000..23aef6d
--- /dev/null
+++ b/Source/mesquite/batchArch/lib/TemplateManager.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.lib; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ========== */
+public abstract class TemplateManager extends FileInit {
+	
+	public Class getDutyClass(){
+		return TemplateManager.class;
+	}
+	/*.................................................................................................................*/
+	public abstract TemplateRecord chooseTemplate(Taxa taxa);
+	public abstract TemplateRecord getTemplate(String name);
+	public abstract boolean getTreeHasBeenChosen();
+	public abstract ExtensibleDialog getChooseTemplateDLOG(Taxa taxa, String title, ObjectContainer oC, MesquiteInteger buttonPressed, boolean includeMatrices);
+	
+	public abstract MesquiteString getFileSpecific(String name);
+	public abstract Tree getTree();
+
+}
+	
+
diff --git a/Source/mesquite/batchArch/lib/TemplateRecord.java b/Source/mesquite/batchArch/lib/TemplateRecord.java
new file mode 100644
index 0000000..2c768f0
--- /dev/null
+++ b/Source/mesquite/batchArch/lib/TemplateRecord.java
@@ -0,0 +1,462 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.batchArch.lib; 
+
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+public class TemplateRecord  implements Listable, Explainable {
+	public boolean userDefined = false;
+	public static String defaultExportFormat = "NEXUS file interpeter";
+	public String name = "", explanation, matrixExportFormat=defaultExportFormat, path;
+	private String[] startText, textForEachFile, endText;
+	private String[] batchFileName;
+	TemplateManager manager;
+	RandomBetween randomBetween = new RandomBetween();
+	
+	StringBuffer[] outputBuffer;
+	int defaultNumFiles = 5;
+	int numFiles = defaultNumFiles;
+	public TemplateRecord(boolean userDefined, TemplateManager manager){
+		this.userDefined = userDefined;
+		this.manager = manager;
+		setNumFiles(defaultNumFiles);
+	}
+	public boolean batchFileHasContent(int fileNumber){
+		if (!StringUtil.blank(getStartText(fileNumber)))
+			return true;
+		if (!StringUtil.blank(getTextEach(fileNumber)))
+			return true;
+		if (!StringUtil.blank(getEndText(fileNumber)))
+			return true;
+		return false;
+	}
+	public String batchFileToString(int fileNumber, boolean isNEXUS){
+		String contents = "";
+		if (isNEXUS) {
+			if (!StringUtil.blank(getStartText(fileNumber)))
+				contents += " start" + (fileNumber+1) + " = " + StringUtil.tokenize(getStartText(fileNumber)) + StringUtil.lineEnding();
+			if (!StringUtil.blank(getTextEach(fileNumber)))
+				contents += " repeat" + (fileNumber+1) + " = " + StringUtil.tokenize(getTextEach(fileNumber)) + StringUtil.lineEnding();
+			if (!StringUtil.blank(getEndText(fileNumber)))
+				contents += " end" + (fileNumber+1) + " = " + StringUtil.tokenize(getEndText(fileNumber)) + StringUtil.lineEnding();
+			if (batchFileName!=null && fileNumber<batchFileName.length && !StringUtil.blank(batchFileName[fileNumber])) //Changed here to allow replacement of text in file names
+				contents += " batchFileName" + (fileNumber+1) + " = " + StringUtil.tokenize(batchFileName[fileNumber]) + StringUtil.lineEnding();
+		}
+		return contents;
+	}
+	public String toNEXUSString(){
+		String contents = "#MESQUITEINIT BATCHFILE 1" + StringUtil.lineEnding();
+		if (!StringUtil.blank(name))
+			contents += " name = " + StringUtil.tokenize(name) + StringUtil.lineEnding();
+		if (!StringUtil.blank(explanation))
+			contents += " explanation = " + StringUtil.tokenize(explanation) + StringUtil.lineEnding();
+			
+		for (int i=0; i<numFiles; i++)
+			contents += batchFileToString(i,true);
+						
+		if (!StringUtil.blank(matrixExportFormat))
+			contents += " matrixExportFormat =  " + StringUtil.tokenize(matrixExportFormat) + StringUtil.lineEnding();
+		return contents;
+	}
+	public boolean fillFromString(String contents, Parser parser){
+		parser.setString(contents);
+		String token = parser.getNextToken(); 
+		if (!StringUtil.blank(token))
+			if (token.equalsIgnoreCase("#MESQUITEINIT")) {
+				token = parser.getNextToken(); 
+				if (token.equalsIgnoreCase("BATCHFILE")) {
+					token = parser.getNextToken(); 
+					if (token.equalsIgnoreCase("1")) {
+						Arguments arguments = new Arguments(parser, true);
+						name = arguments.getParameterValue("name");
+						if (StringUtil.blank(name))
+							name = "untitled template";
+						explanation= arguments.getParameterValue("explanation");
+						if (StringUtil.blank(explanation))
+							explanation = "";
+						
+						for (int i=0; i<numFiles; i++) {
+							setStartText(arguments.getParameterValue("start"+(i+1)), i);
+							setTextEach(arguments.getParameterValue("repeat"+(i+1)), i);
+							setEndText(arguments.getParameterValue("end"+(i+1)), i);
+							setBatchFileName(arguments.getParameterValue("batchFileName"+(i+1)), i);
+						}
+						matrixExportFormat = arguments.getParameterValue("matrixExportFormat");
+						if (StringUtil.blank(matrixExportFormat))
+							matrixExportFormat = defaultExportFormat;
+						return true; 
+					}
+					else 
+						MesquiteMessage.warnProgrammer("Mesquite does not understand templates of this version.");
+				}
+				else 
+					MesquiteMessage.warnProgrammer("The second token in templates must be \"BATCHFILE\".");
+			}
+			else 
+				MesquiteMessage.warnProgrammer("Templates must begin with \"#MESQUITEINIT\".");
+		return false;
+	}
+	public int getNumFiles(){
+		return numFiles;
+	}
+	public String getName(){
+		return name;
+	}
+	public boolean getUserDefined(){
+		return userDefined;
+	}
+	public String getExplanation(){
+		return explanation;
+	}
+	public void setStartText(String s, int file){
+		if (startText == null || file>=startText.length)
+			return;
+		startText[file] = s;
+	}
+	public String getStartText(int file){
+		if (startText == null || file>=startText.length)
+			return null;
+		return startText[file];
+	}
+	public void setTextEach(String s, int file){
+		if (textForEachFile == null || file>=textForEachFile.length)
+			return;
+		textForEachFile[file] = s;
+	}
+	public String getTextEach(int file){
+		if (textForEachFile == null || file>=textForEachFile.length)
+			return null;
+		return textForEachFile[file];
+	}
+	public void setEndText(String s, int file){
+		if (endText == null || file>=endText.length)
+			return;
+		endText[file] = s;
+	}
+	public String getEndText(int file){
+		if (endText == null || file>=endText.length)
+			return null;
+		return endText[file];
+	}
+	public void setBatchFileName(String s, int file){
+		if (batchFileName == null || file>=batchFileName.length)
+			return;
+		batchFileName[file] = s;
+	}
+	public String getBatchFileName(int file, String baseName, boolean replace){
+		if (batchFileName == null || file>=batchFileName.length)
+			return null;
+		if (!replace)
+			return batchFileName[file];
+		return replaceUniversalCode(batchFileName[file], baseName, null);
+	}
+	/*private boolean treeInBuffer(StringBuffer sb){
+		if (sb == null)
+			return false;
+		String s = sb.toString();
+		if (s == null)
+			return false;
+		return (s.indexOf("<tree>")>=0);
+	}*/
+	private boolean treeInString(String sb){
+		if (sb == null)
+			return false;
+		return (sb.indexOf("<tree>")>=0);
+	}
+	public boolean needsTree(){
+		for (int i=0; i<numFiles; i++) {
+			if (treeInString(startText[i]))
+				return true;
+			if (treeInString(textForEachFile[i]))
+				return true;
+			if (treeInString(endText[i]))
+				return true;
+		}
+		return false;
+	}
+	private int randomIndex(String sb, MesquiteInteger from){
+		if (sb == null)
+			return -1;
+		return (sb.indexOf("<random>", from.getValue()));
+	}
+	private int randomCloseIndex(String sb, MesquiteInteger from){
+		if (sb == null)
+			return -1;
+		return (sb.indexOf("</random>", from.getValue()));
+	}
+	private int snippetIndex(String sb, MesquiteInteger from){
+		if (sb == null)
+			return -1;
+		return (sb.indexOf("<snippet>", from.getValue()));
+	}
+	private int snippetCloseIndex(String sb, MesquiteInteger from){
+		if (sb == null)
+			return -1;
+		return (sb.indexOf("</snippet>", from.getValue()));
+	}
+	private String nextSnippet(String sb, MesquiteInteger from){
+		int s = snippetIndex(sb, from);
+		if (s <0)
+			return null;
+		from.setValue(from.getValue()+6);
+		int sc = snippetCloseIndex(sb, from);
+		if (sc <0 || sc<s)
+			return null;
+		String snippet = sb.substring(s+9, sc);
+		from.setValue(sc+7);
+		return snippet;
+	}
+	private void collectSnippets(ListableVector v, String sb){
+		MesquiteInteger from = new MesquiteInteger(-1);
+		String snippet;
+		while ((snippet = nextSnippet(sb, from))!=null) {
+			if (v.indexOfByName(snippet)<0) {
+				MesquiteString ms = new MesquiteString();
+				ms.setName(snippet);
+				v.addElement(ms, false);
+			}
+		}
+	}
+	public ListableVector snippetsNeeded(){
+		ListableVector v = new ListableVector();
+		for (int i=0; i<numFiles; i++) {
+			collectSnippets(v, startText[i]);
+			collectSnippets(v, textForEachFile[i]);
+			collectSnippets(v, endText[i]);
+		}
+		return v;
+	}
+	public void setNumFiles(int num){
+		numFiles = num;
+		batchFileName = new String[numFiles];
+		startText = new String[numFiles];
+		textForEachFile = new String[numFiles];
+		endText = new String[numFiles];
+		for (int i=0; i<numFiles; i++) {
+			batchFileName[i] = "Batch File " + i;
+		}
+	}
+	String replaceSnippets(String s, ListableVector v){
+		if (v !=null && v.size()!=0) {
+			for (int i=0; i<v.size(); i++){
+				MesquiteString ms = (MesquiteString)v.elementAt(i);
+				MesquiteString snippet = manager.getFileSpecific(ms.getName());
+				String replaceString = "";
+				if (snippet !=null)
+					replaceString = snippet.getValue();
+				
+				s = StringUtil.replace(s, "<snippet>" + ms.getName() + "</snippet>", replaceString);
+			}
+			return s;
+		}
+		else
+			return s;
+	}
+	/*.................................................................................................................*/
+	String replaceTree(String s, Tree tree){
+		String replaceString = "";
+		if (tree !=null)
+			replaceString = tree.writeTree(Tree.BY_NAMES, true);
+		return StringUtil.replace(s, "<tree>", replaceString);
+	}
+	/*.................................................................................................................*/
+	public String fileExtension(String matrixExportFormatName, FileCoordinator coord, boolean includeDot){
+		String s = "";
+		if (includeDot) s = ".";
+		if (matrixExportFormatName.equals("NEXUS file interpreter")|| matrixExportFormatName.equals("NEXUS file")) {
+			return s + "nex";
+		}
+		else {
+			//arguments = "#mesquite.io.InterpretNonaHennig.InterpretNonaHennig 1 file= 'exported.ss' directory = '/Users/wmaddisn/Desktop/'";
+			FileInterpreterI matrixExportFormat = (FileInterpreterI)coord.findEmployeeWithName(matrixExportFormatName);
+			if (matrixExportFormat!=null) {
+				String ext = matrixExportFormat.preferredDataFileExtension();
+				if (!StringUtil.blank(ext))
+					return s + ext;
+			}
+		}
+		return "";
+	}
+	/*.................................................................................................................*/
+	String replaceExtension(String s){
+		FileCoordinator coord = manager.getFileCoordinator();
+		String replaceString = fileExtension(matrixExportFormat,coord,true);
+		return StringUtil.replace(s, "<fileExtension>", replaceString);
+	}
+	/*.................................................................................................................*/
+	String getRandomValues(int numValues, int type, MesquiteNumber lowerBound, MesquiteNumber upperBound, boolean withReplacement){
+		String s = "";
+		NumberArray numArray = new NumberArray(numValues);
+		int intValue;
+		double doubleValue;
+		long longValue;
+		MesquiteNumber n =new MesquiteNumber();
+		if ((type==MesquiteNumber.INT) && (upperBound.getIntValue()-lowerBound.getIntValue()<numValues-1))
+			numValues = upperBound.getIntValue()-lowerBound.getIntValue() +1;
+		else if ((type==MesquiteNumber.LONG) && (upperBound.getLongValue()-lowerBound.getLongValue()<numValues-1))
+			numValues = (int)(upperBound.getLongValue()-lowerBound.getLongValue() +1);
+		for (int i=0;i<numValues; i++){
+			if (type==MesquiteNumber.INT) {
+				intValue= randomBetween.randomIntBetween(lowerBound.getIntValue(), upperBound.getIntValue());
+				n.setValue(intValue);
+				if (!withReplacement)
+					while (numArray.findValue(n)>=0) {
+						intValue = randomBetween.randomIntBetween(lowerBound.getIntValue(), upperBound.getIntValue());
+						n.setValue(intValue);
+					}
+				s += " " + intValue;
+				numArray.setValue(i,intValue);
+			}
+			else if (type==MesquiteNumber.DOUBLE) {
+				doubleValue = randomBetween.randomDoubleBetween(lowerBound.getDoubleValue(), upperBound.getDoubleValue());
+				n.setValue(doubleValue);
+				if (!withReplacement)
+					while (numArray.findValue(n)>=0) {
+						doubleValue = randomBetween.randomDoubleBetween(lowerBound.getDoubleValue(), upperBound.getDoubleValue());
+						n.setValue(doubleValue);
+					}
+				s += " " + doubleValue;
+				numArray.setValue(i,doubleValue);
+			}
+			else if (type==MesquiteNumber.LONG) {
+				longValue = randomBetween.randomLongBetween(lowerBound.getLongValue(), upperBound.getLongValue());
+				n.setValue(longValue);
+				if (!withReplacement)
+					while (numArray.findValue(n)>=0) {
+						longValue = randomBetween.randomLongBetween(lowerBound.getLongValue(), upperBound.getLongValue());
+						n.setValue(longValue);
+					}
+				s += " " + longValue;
+				numArray.setValue(i,longValue);
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	String replaceRandom(String s){
+		String replaceString = "";
+		String randomString = "";
+		Parser parser = new Parser();
+		Arguments arguments;
+		int lastIndex = s.indexOf("<random>");
+		while (s.indexOf("</random>")>=0 && s.indexOf("<random>")>=0) {
+			randomString = StringUtil.getFirstSubString(s,"<random>", "</random>");
+			parser.setString(randomString);
+			arguments = new Arguments(parser, true);
+			int numValues = arguments.getParameterValueAsInt("numValues");
+			MesquiteNumber lowerBound = new MesquiteNumber();
+			MesquiteNumber upperBound = new MesquiteNumber();
+			String arg = arguments.getParameterValue("lowerBound");
+			if (!StringUtil.blank(arg))
+				lowerBound.setValue(arg);
+			arg = arguments.getParameterValue("upperBound");
+			if (!StringUtil.blank(arg))
+				upperBound.setValue(arg);
+			boolean withReplacement = false;
+			arg = arguments.getParameterValue("withReplacement");
+			if (!StringUtil.blank(arg))
+				if (arg.equalsIgnoreCase("yes"))
+					withReplacement = true;
+				else if (arg.equalsIgnoreCase("no"))
+					withReplacement = false;
+			String numberType = arguments.getParameterValue("type");
+			int type = MesquiteNumber.INT;
+			if (!StringUtil.blank(numberType)) {
+				if (numberType.equalsIgnoreCase("double"))
+					type = MesquiteNumber.DOUBLE;
+				else if (numberType.equalsIgnoreCase("long"))
+					type = MesquiteNumber.LONG;
+			}
+			s = StringUtil.replaceFirst(s,"<random>", "</random>", getRandomValues(numValues,type,lowerBound,upperBound, withReplacement).toString());
+			if (lastIndex== s.indexOf("<random>"))
+				return s;
+			 lastIndex = s.indexOf("<random>");
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String replaceUniversalCode(String originalString, String baseName,ListableVector v ){
+		String s = "";
+		if (!StringUtil.blank(originalString)) {
+			s = replaceSnippets(originalString, v);
+			s = StringUtil.replace(s,"<name>",baseName);
+			s = replaceExtension(s);
+			s = replaceRandom(s);
+			s = StringUtil.replace(s,"<matrixFormat>",matrixExportFormat);
+			s = replaceTree(s, manager.getTree());
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public void composeAccessoryFilesStart(int numReplicates, String baseName, String basePath){
+		ListableVector v = snippetsNeeded();
+		outputBuffer = new StringBuffer[numFiles];
+		for (int i=0; i<numFiles; i++) {
+			outputBuffer[i] = new StringBuffer(numReplicates*(200));//���
+			if (!StringUtil.blank(startText[i])) 
+				outputBuffer[i].append(replaceUniversalCode(startText[i].toString(), baseName,v));
+		}
+	}
+	/*.................................................................................................................*/
+	public void composeAccessoryFilesReplicate(int iMatrix, String matrixName, int section, String baseName, String basePath){
+		if (outputBuffer==null)
+			return;
+		ListableVector v = snippetsNeeded();
+		for (int i=0; i<numFiles; i++) {
+			if (outputBuffer[i] !=null){//���
+				if (!StringUtil.blank(textForEachFile[i])){
+					String s = StringUtil.replace(textForEachFile[i].toString(),"<number>",""+iMatrix);
+					if (matrixName != null)
+						s = StringUtil.replace(s,"<matrixName>",matrixName);
+					s = replaceUniversalCode(s,baseName,v);
+					if (outputBuffer[i].length()>0 && !StringUtil.blank(s))
+						outputBuffer[i].append(StringUtil.lineEnding()+StringUtil.lineEnding());
+					outputBuffer[i].append(s);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void composeAccessoryFilesEnd(String baseName, String directoryPath){
+		if (outputBuffer==null)
+			return;
+		ListableVector v = snippetsNeeded();
+		for (int i=0; i<numFiles; i++) {
+			if (outputBuffer[i] != null) {//���
+				if (!StringUtil.blank(endText[i])){
+					String s = replaceUniversalCode(endText[i].toString(), baseName,v);
+					if (outputBuffer[i].length()>0 && !StringUtil.blank(s))
+						outputBuffer[i].append(StringUtil.lineEnding()+StringUtil.lineEnding());
+					outputBuffer[i].append(s);
+				}
+				if (outputBuffer[i].length()>0){
+					String path; 
+					if (!StringUtil.blank(getBatchFileName(i, baseName, true)))
+						path = directoryPath + getBatchFileName(i, baseName, true);
+					else
+						path = directoryPath + "Batch File " + i;
+					MesquiteFile.putFileContents(path, outputBuffer[i].toString(), true);
+				}
+			}
+		}
+	}
+}
+
diff --git a/Source/mesquite/categ/AmbiguityToPolym/AmbiguityToPolym.java b/Source/mesquite/categ/AmbiguityToPolym/AmbiguityToPolym.java
new file mode 100644
index 0000000..55063db
--- /dev/null
+++ b/Source/mesquite/categ/AmbiguityToPolym/AmbiguityToPolym.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.AmbiguityToPolym;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AmbiguityToPolym extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Attempt to convert uncertainties (ambiguities) to polymorphisms in non-categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table, undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		long s = data.getState(ic,it);
+		if (CategoricalState.cardinality(s)<=1)
+			return;
+		if (!CategoricalState.isUncertain(s))
+			return;
+		data.setState(ic, it, CategoricalState.setUncertainty(s, false));
+		if (!MesquiteLong.isCombinable(numCellsAltered))
+			numCellsAltered = 0;
+		numCellsAltered++;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Convert Uncertainties to Polymorphisms";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Alters categorical data by converting uncertain entries to polymorphisms." ;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/CategVariable/CategVariable.java b/Source/mesquite/categ/CategVariable/CategVariable.java
new file mode 100644
index 0000000..f53270f
--- /dev/null
+++ b/Source/mesquite/categ/CategVariable/CategVariable.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.CategVariable;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.ParsimonyModelSet;
+import mesquite.categ.lib.*;
+
+public class CategVariable extends BooleanForCharacter {
+
+	public String getName() {
+		return "Variable (Mult. States)";
+	}
+	public String getExplanation() {
+		return "Indicates whether a character has multiple observed states.  If taxa are selected, only the selected taxa are examined.";
+	}
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+	public void calculateBoolean(CharacterData data, int ic, MesquiteBoolean result, MesquiteString resultString) {
+		if (data==null || result==null)
+			return;
+		result.setToUnassigned();
+		if (!(data instanceof CategoricalData))
+			return;
+		Taxa taxa = data.getTaxa();
+		CategoricalData cData = (CategoricalData)data;
+
+		result.setValue(cData.charIsVariable(ic, true));
+	}
+
+	/*.................................................................................................................*/
+	public String getTrueString(){
+		return "Multiple States";
+	}
+	/*.................................................................................................................*/
+	public String getFalseString(){
+		return "≤ 1 state";
+	}
+
+
+	public boolean isPrerelease() {
+		return false;
+	}
+
+
+}
diff --git a/Source/mesquite/categ/ConsensusSequenceStrip/ConsensusSequenceStrip.java b/Source/mesquite/categ/ConsensusSequenceStrip/ConsensusSequenceStrip.java
new file mode 100644
index 0000000..f54916e
--- /dev/null
+++ b/Source/mesquite/categ/ConsensusSequenceStrip/ConsensusSequenceStrip.java
@@ -0,0 +1,452 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.ConsensusSequenceStrip;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.charMatrices.ColorByState.ColorByState;
+import mesquite.molec.ColorByAA.ColorByAA;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+
+public class ConsensusSequenceStrip extends DataColumnNamesAssistant {
+	long[] consensusSequence = null;
+	MesquiteBoolean showSomeInapplicableAsGray = new MesquiteBoolean(false);
+	CategStateForCharacter stateTask = null;
+	MesquiteString stateTaskName;
+	MesquiteCommand stC;
+	MesquiteSubmenuSpec stSubmenu;
+	MesquiteMenuItemSpec menuItem1, menuItem2, colorByAAMenuItem, closeMenuItem, lineMenuItem, moveToMatrixItem, emphasizeLessDegenerateMenuItem;
+	MesquiteBoolean colorByAA = new MesquiteBoolean(false);
+	MesquiteBoolean emphasizeLessDegenerateAAs = new MesquiteBoolean(true);
+	
+	boolean suspend = false;
+
+	MesquiteBoolean selectedOnly = new MesquiteBoolean(true);
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setUseMenubar(false);
+		
+		stateTask = (CategStateForCharacter)hireEmployee(CategStateForCharacter.class, "Calculator of character state for each character");
+		if (stateTask == null)
+			return sorry(getName() + " couldn't start because no calculator of character state obtained");
+		stateTaskName = new MesquiteString(stateTask.getName());
+		stC = makeCommand("setStateCalculator",  this);
+		stateTask.setHiringCommand(stC);
+		if (numModulesAvailable(CategStateForCharacter.class)>1) {
+			MesquiteSubmenuSpec stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+			stSubmenu.setSelected(stateTaskName);
+		}
+		
+		return true;
+  	 }
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CategStateForCharacter.class, getName() + " needs a module to provide a character state (e.g., the consensus state) for each character.",
+		"The character state provider is chosen initially or using the State Calculator submenu");
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == stateTask)  
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void getSubfunctions(){
+		String  explanationString = "(An Info Strip of a Categorical Matrix Window) Displays a consensus sequence for categorical data, as indicated by the two arrows in the figure below. <br> <img src=\"" + MesquiteFile.massageFilePathToURL(getPath() + "consensus.gif");
+		explanationString += "\"><br>To create a consensus sequence, choose Matrix>Add Char Info Strip>Consensus Sequence.  To adjust options, use the drop-down menu that appears when you touch on the consensus sequence.<br>";
+		registerSubfunction(new FunctionExplanation("Consensus Sequence", explanationString, null, null));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public void deleteMenuItems() {
+		deleteMenuItem(stSubmenu);
+		deleteMenuItem(menuItem1);
+		deleteMenuItem(menuItem2);
+		deleteMenuItem(colorByAAMenuItem);
+		deleteMenuItem(emphasizeLessDegenerateMenuItem);
+	}
+	/*.................................................................................................................*/
+	public void checkMenuItems() {
+		colorByAAMenuItem.setEnabled((data instanceof DNAData) && ((DNAData)data).someCoding());
+		emphasizeLessDegenerateMenuItem.setEnabled((data instanceof DNAData) && ((DNAData)data).someCoding()&& colorByAA.getValue());
+	}
+	public void deleteRemoveMenuItem() {
+		deleteMenuItem(lineMenuItem);
+		deleteMenuItem(moveToMatrixItem);
+		deleteMenuItem(closeMenuItem);
+	}
+	public void addRemoveMenuItem() {
+		closeMenuItem= addMenuItem(null,"Remove Consensus Sequence", makeCommand("remove", this));
+		moveToMatrixItem= addMenuItem(null,"Move to Matrix", makeCommand("moveToMatrix", this));
+		lineMenuItem = addMenuLine();
+	}
+		
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		deleteMenuItems();
+		deleteRemoveMenuItem();
+		addRemoveMenuItem();
+		stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+		stSubmenu.setSelected(stateTaskName);
+		menuItem1= addCheckMenuItem(null,"Selected Taxa Only", makeCommand("toggleSelectedOnly", this), selectedOnly);
+		menuItem2= addCheckMenuItem(null,"Darken if Any Gaps", makeCommand("toggleGrayIfGaps", this), showSomeInapplicableAsGray);
+		colorByAAMenuItem= addCheckMenuItem(null,"Color Nucleotide by AA Color", makeCommand("toggleColorByAA", this), colorByAA);
+		emphasizeLessDegenerateMenuItem= addCheckMenuItem(null,"Emphasize Less Degenerate AAs", makeCommand("toggleEmphasizeLessDegenerateAAs", this), emphasizeLessDegenerateAAs);
+		
+		
+		if (data != null)
+			data.removeListener(this);
+		this.data = data;
+		this.table = table;
+		data.addListener(this);
+		
+		checkMenuItems();
+		calculateSequence();
+	}
+	/*.................................................................................................................*/
+	 public String getShortParameters() {
+		 String s = "(";
+		 if (stateTask!=null)
+			 s+= stateTask.getShortParameters();
+		 s += ")";
+		 return s;
+	 }
+	/*.................................................................................................................*/
+	 public void moveToMatrix() {
+		Taxa taxa = data.getTaxa();
+		taxa.addTaxa(-1,1,true);
+		String name = taxa.getUniqueName("Consensus " + getShortParameters());
+		taxa.setTaxonName(0, name);
+		 for (int ic = 0; ic<data.getNumChars(); ic++){
+			 long s= CategoricalState.inapplicable;
+			 CategoricalState resultState = new CategoricalState();
+			 MesquiteString resultString = new MesquiteString();
+			 stateTask.calculateState( (CategoricalData)data,  ic,  table,  resultState,  resultString, null);
+			 s = resultState.getValue();
+			 ((CategoricalData)data).setState(ic, 0, s);
+		 }
+	 }
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("suspend");
+		temp.addLine("setStateCalculator " , stateTask);
+		temp.addLine("toggleSelectedOnly " + selectedOnly.toOffOnString());
+		temp.addLine("toggleGrayIfGaps " + showSomeInapplicableAsGray.toOffOnString());
+		temp.addLine("toggleColorByAA " + colorByAA.toOffOnString());
+		temp.addLine("toggleEmphasizeLessDegenerateAAs " + emphasizeLessDegenerateAAs.toOffOnString());
+		temp.addLine("resume");
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not only selected taxa are included are all taxa.", "[on or off]", commandName, "toggleSelectedOnly")) {
+			boolean current = selectedOnly.getValue();
+			selectedOnly.toggleValue(parser.getFirstToken(arguments));
+			if (stateTask!=null)
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+			if (current!=selectedOnly.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				if (table !=null) {
+						table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show nucleotides by the color of their amino acid.", "[on or off]", commandName, "toggleColorByAA")) {
+			boolean current = colorByAA.getValue();
+			colorByAA.toggleValue(parser.getFirstToken(arguments));
+			if (current!=colorByAA.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				checkMenuItems();
+				if (table !=null) {
+					table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not less degenerate amino acids should be emphasized.", "[on or off]", commandName, "toggleEmphasizeLessDegenerateAAs")) {
+			boolean current = emphasizeLessDegenerateAAs.getValue();
+			emphasizeLessDegenerateAAs.toggleValue(parser.getFirstToken(arguments));
+			if (current!=emphasizeLessDegenerateAAs.getValue() && !suspend) {
+				parametersChanged();
+				checkMenuItems();
+				//calculateSequence();
+				if (table !=null) {
+					table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show the consensus cell as gray if there are any gaps in any taxon.", "[on or off]", commandName, "toggleGrayIfGaps")) {
+			boolean current = showSomeInapplicableAsGray.getValue();
+			showSomeInapplicableAsGray.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showSomeInapplicableAsGray.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				if (table !=null) {
+					table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the Consensus Strip", null, commandName, "remove")) {
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Moves consensus to be a new sequence in the matrix ", null, commandName, "moveToMatrix")) {
+			moveToMatrix();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			calculateSequence();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the calculator of a state for each character", "[name of state calculator module]", commandName, "setStateCalculator")) {
+			CategStateForCharacter temp = (CategStateForCharacter)replaceEmployee(CategStateForCharacter.class, arguments, "Calculator of character state for each character", stateTask);
+			if (temp !=null){
+				stateTask = temp;
+				stateTask.setHiringCommand(stC);
+				stateTaskName.setValue(stateTask.getName());
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+				if (!suspend) {
+					parametersChanged();
+					calculateSequence();
+					if (table !=null){
+						table.repaintAll();
+					}
+				}
+				return stateTask;
+			}
+			addRemoveMenuItem();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		calculateSequence();
+			if (table !=null)
+				table.repaintAll();
+  	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (table!=null) {
+			((ColumnNamesPanel)table.getColumnNamesPanel()).decrementInfoStrips();
+			table.resetTableSize(false);
+		}
+		super.endJob();
+	}
+
+ 
+	/*.................................................................................................................*/
+	 public boolean atLeastOneInapplicable(int ic){
+		 if (data==null || table==null)
+			 return false;
+		 //long s;
+		 int numTaxa = data.getNumTaxa();
+		 int numTaxaWithData = 0;
+		boolean noRowsSelected =  !table.anyRowSelected();
+		 for (int it=0; it<numTaxa; it++) {
+			 if (!selectedOnly.getValue() || table.isRowSelected(it) || noRowsSelected) {
+				 long s= ((CategoricalData)data).getState(ic,it);
+				 if (CategoricalState.isInapplicable(s))
+					 return true;
+			 }
+		 }
+		 return false;
+	 }
+
+		/*.................................................................................................................*/
+	 public void calculateSequence() {
+		 if (!colorByAA.getValue())
+			 return;
+		 CategoricalState resultState = new CategoricalState();
+		 MesquiteString resultString = new MesquiteString();
+		 long[] sequence = new long[data.getNumChars()];
+		 for (int i = 0; i<data.getNumChars(); i++) {
+			 stateTask.calculateState( (CategoricalData)data,  i,  table,  resultState,  resultString, null);
+			 sequence[i] = resultState.getValue();
+		 }
+		consensusSequence = sequence;
+	 }
+		/*.................................................................................................................*/
+	 public void drawInCell(int ic, Graphics g, int x, int y, int w, int h, boolean selected) {
+		 if (stateTask==null || data == null) 
+			 return;
+		 long s= CategoricalState.inapplicable;
+		 if (colorByAA.getValue()) {  // have to use precomputed sequences
+			 if (consensusSequence==null)
+				 calculateSequence();
+			 if (ic>=0 && ic<consensusSequence.length)
+				 s =consensusSequence[ic];
+		 } else {
+			 CategoricalState resultState = new CategoricalState();
+			 MesquiteString resultString = new MesquiteString();
+			 stateTask.calculateState( (CategoricalData)data,  ic,  table,  resultState,  resultString, null);
+			 s = resultState.getValue();
+		 }
+
+		 boolean colorSomeInapp = atLeastOneInapplicable(ic) && showSomeInapplicableAsGray.getValue();
+		 if (!CategoricalState.isEmpty(s) && !CategoricalState.isInapplicable(s)){
+			 boolean grayText = false;
+			 int e =  CategoricalState.getOnlyElement(s);
+			 if (colorSomeInapp) {
+				 g.setColor(Color.darkGray);
+			 }
+			 Color cellColor = null;
+			 long aa=-1;
+			 if (data instanceof DNAData){
+				 if (colorByAA.getValue()){
+					aa = ((DNAData)data).getAminoAcid(consensusSequence, ic,true);
+					 if (!CategoricalState.isImpossible(aa)) {
+						 if (emphasizeLessDegenerateAAs.getValue()) {
+							 cellColor = ProteinData.getAminoAcidColor(aa, Color.white);
+							 cellColor = ((DNAData)data).alterColorToDeemphasizeDegeneracy(ic,aa,cellColor);
+						 } else
+							 cellColor = ProteinData.getAminoAcidColor(aa, ProteinData.multistateColor);
+					 }
+					 if (cellColor==null){
+						 if (e>=0)
+							 cellColor = DNAData.getDNAColorOfState(e);
+						 else
+							 cellColor =Color.white;
+					 }
+				 }
+				 else if (e>=0)
+					 cellColor =DNAData.getDNAColorOfState(e);
+				 else {
+					 cellColor =Color.white;
+					 grayText =true;
+				 }
+			 }
+			 else if (data instanceof ProteinData){
+				 if (e>=0)
+					 cellColor =ProteinData.getProteinColorOfState(e);
+				 else {
+					 cellColor =Color.white;
+					 grayText =true;
+				 }
+			 }
+			 else 
+				 cellColor =Color.white;
+			 g.setColor(cellColor);
+			 g.fillRect(x,y,w,h);
+
+			 if (colorSomeInapp) 
+				 GraphicsUtil.darkenRectangle(g, x, y, w, h,0.6f);
+			 if (grayText) {
+				 if (colorSomeInapp) 
+					 g.setColor(Color.darkGray);
+				 else 
+					 g.setColor(Color.lightGray);
+			 }
+			 else {
+					float[] hsb = new float[3];
+					hsb[0]=hsb[1]=hsb[2]= 1;
+					Color.RGBtoHSB(cellColor.getRed(), cellColor.getGreen(), cellColor.getBlue(), hsb);
+					Color textColor = ColorDistribution.getContrasting(selected, cellColor, hsb, Color.white, Color.black);
+					g.setColor(textColor);
+			 }
+			 StringBuffer sb = new StringBuffer();
+			 ((CategoricalData)data).statesIntoStringBufferCore(ic,  s,  sb, true,false, false);
+			 FontMetrics fm = g.getFontMetrics(g.getFont());
+			 int svp = StringUtil.getStringVertPosition(fm, y, h, null);
+
+			 String cellString = sb.toString();
+			 int length = fm.stringWidth(cellString);
+			 int useX = x + (w - length) / 2;
+			 g.drawString(cellString, useX, svp);
+
+		 }
+		 else if (CategoricalState.isInapplicable(s)){
+			 g.setColor(Color.lightGray);
+			 g.fillRect(x,y,w,h);
+		}
+		else {
+			g.setColor(Color.white);
+			g.fillRect(x,y,w,h);
+		}
+	}
+
+	 /*.................................................................................................................*/
+	 /** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	 public void changed(Object caller, Object obj, Notification notification){
+		 int code = Notification.getCode(notification);
+		 if (obj instanceof Taxa &&  (Taxa)obj ==data.getTaxa()) {
+			 if (code==MesquiteListener.SELECTION_CHANGED && selectedOnly.getValue()) {
+				 calculateSequence();
+			 }
+			 else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED) {
+				 calculateSequence();
+			 }
+		 }
+		 else if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			 if (code==MesquiteListener.PARTS_DELETED || code==AssociableWithSpecs.SPECSSET_CHANGED || code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.DATA_CHANGED) {
+				 calculateSequence();
+			 }
+			 else{
+				 calculateSequence();
+			 }
+		 }
+		 super.changed(caller, obj, notification);
+	 }
+	 /*.................................................................................................................*/
+	 /** returns whether this module is requesting to appear as a primary choice */
+	 public boolean requestPrimaryChoice(){
+		 return true;  
+	 }
+	 /*.................................................................................................................*/
+	 public boolean isPrerelease(){
+		 return false;  
+	 }
+	public String getTitle() {
+		return "Consensus Sequence Strip";
+	}
+
+
+	public String getName() {
+		return "Consensus Sequence Strip";
+	}	
+	
+	
+	public String getExplanation() {
+		return "Displays a consensus sequence as in info strip in a character matrix editor.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
diff --git a/Source/mesquite/categ/ConsensusSequenceStrip/consensus.gif b/Source/mesquite/categ/ConsensusSequenceStrip/consensus.gif
new file mode 100644
index 0000000..749698a
Binary files /dev/null and b/Source/mesquite/categ/ConsensusSequenceStrip/consensus.gif differ
diff --git a/Source/mesquite/categ/ConsensusStateForChar/ConsensusStateForChar.java b/Source/mesquite/categ/ConsensusStateForChar/ConsensusStateForChar.java
new file mode 100644
index 0000000..f53de4e
--- /dev/null
+++ b/Source/mesquite/categ/ConsensusStateForChar/ConsensusStateForChar.java
@@ -0,0 +1,172 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.ConsensusStateForChar;
+
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+public class ConsensusStateForChar extends CategStateForCharacter {
+	MesquiteBoolean showOnlyModal = new MesquiteBoolean(false);
+	double nonModalThreshold = 0.2;
+
+	MesquiteMenuItemSpec menuItem1, menuItem2;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		menuItem1= addCheckMenuItem(null,"Show Modal Value Only", makeCommand("toggleShowOnlyModal", this), showOnlyModal);
+		menuItem2= addMenuItem(null,"Threshold for Non-Modal States...", makeCommand("setNonModalThreshold", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	 public String getShortParameters() {
+		 String s = "";
+		 s += nonModalThreshold;
+		 if (showOnlyModal.getValue())
+			 s+=" Modal";
+		 return s;
+	 }
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("toggleShowOnlyModal " + showOnlyModal.toOffOnString());
+		temp.addLine("setNonModalThreshold " + nonModalThreshold);
+
+		return temp;
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the minimum frequency among applicable states required to include state in consensus", "[threshold value]", commandName, "setNonModalThreshold")) {
+			double currentValue = nonModalThreshold;
+			pos.setValue(0);
+			double t = MesquiteDouble.fromString(arguments, pos);
+
+			if (!MesquiteDouble.isCombinable(t) && !MesquiteThread.isScripting()) 
+				t = MesquiteDouble.queryDouble(containerOfModule(), "Threshold for Non-Modal States", "Minimum frequency among applicable states required to include state in consensus:", nonModalThreshold);
+			if (MesquiteDouble.isCombinable(t))
+				nonModalThreshold = t;
+			if (currentValue!=nonModalThreshold)
+				parametersChanged();
+		}
+		
+		else if (checker.compare(this.getClass(), "Sets whether or not only to show only the modal value.", "[on or off]", commandName, "toggleShowOnlyModal")) {
+			boolean current = showOnlyModal.getValue();
+			showOnlyModal.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showOnlyModal.getValue()) {
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public long getConsensusState(CategoricalData data, int ic, MesquiteTable table){
+		int maxState = data.getMaxState(ic);
+		double[] freq = new double[CategoricalState.getMaxPossibleStateStatic()];
+		int numTaxa = data.getNumTaxa();
+		int numTaxaWithData = 0;
+		boolean noRowsSelected = !table.anyRowSelected();
+		for (int it=0; it<numTaxa; it++) {
+			if (!getSelectedOnly() || table!=null && (table.isRowSelected(it) || noRowsSelected)) {
+				long s= data.getState(ic,it);
+				if (CategoricalState.isInapplicable(s))
+					continue;
+				int card = CategoricalState.cardinality(s);
+				if (card==1)
+					freq[CategoricalState.getOnlyElement(s)]+=1.0;
+				else
+					for (int iState = 0; iState<=maxState; iState++){
+						if (CategoricalState.isElement(s,iState))
+							freq[iState]+=1.0/card;
+					}
+				numTaxaWithData++;
+			}
+		}
+//		now let's figure out the frequency of the most common state
+		double max = 0.0;
+		for (int iState = 0; iState<=maxState; iState++){
+			if (freq[iState]>max) {
+				max = freq[iState];
+			}
+		}
+
+//		now let's figure out which states are close enough to the most common state.
+		long consensus = CategoricalState.emptySet();
+		if (showOnlyModal.getValue()) {
+			for (int iState = 0; iState<=maxState; iState++){
+				if (freq[iState]>=max) {
+					consensus = CategoricalState.addToSet(consensus,iState);
+				}
+			}
+		}
+		else 
+			for (int iState = 0; iState<=maxState; iState++){
+				if (freq[iState]>nonModalThreshold*numTaxaWithData) {
+					consensus = CategoricalState.addToSet(consensus,iState);
+				}
+			}
+		if (CategoricalState.cardinality(consensus) > 1)
+			consensus = CategoricalState.setUncertainty(consensus,true);
+		else  if (CategoricalState.cardinality(consensus) ==0)
+			consensus = CategoricalState.inapplicable;
+		return consensus;
+	}
+
+
+	public void calculateState(CategoricalData data, int ic,MesquiteTable table, CategoricalState resultState, MesquiteString resultString, MesquiteDouble fractionMatching) {
+		if (data==null || resultState==null)
+			return;
+		long consensusState = getConsensusState(data, ic, table);
+		if (fractionMatching !=null) { 
+			int numTaxa = data.getNumTaxa();
+			boolean noRowsSelected = !table.anyRowSelected();
+			int numTaxaMatch=0;
+			int numTaxaWithData = 0;
+			for (int it=0; it<numTaxa; it++) {
+				if (!getSelectedOnly() || table!=null && (table.isRowSelected(it) || noRowsSelected)) {
+					long s= data.getState(ic,it);
+					if (CategoricalState.isInapplicable(s))
+						continue;
+					if (CategoricalState.isSubset(s, consensusState)) 
+						numTaxaMatch++;
+					numTaxaWithData++;
+				}
+			}
+			if (numTaxaWithData>0)
+				fractionMatching.setValue(numTaxaMatch*1.0/numTaxaWithData);
+			else
+				fractionMatching.setValue(0.0);
+		}
+		resultState.setValue(consensusState);
+		resultString.setValue(resultState.toString());
+	}
+
+	/*.................................................................................................................*/
+   	public int getVersionOfFirstRelease(){
+   		return 200;  
+   	}
+	 /*.................................................................................................................*/
+	 public boolean isPrerelease(){
+		 return false;  
+	 }
+
+	public String getName() {
+		return "Consensus State for Character";
+	}
+
+}
diff --git a/Source/mesquite/categ/ManageCategoricalChars/ManageCategoricalChars.java b/Source/mesquite/categ/ManageCategoricalChars/ManageCategoricalChars.java
new file mode 100644
index 0000000..fdbb70d
--- /dev/null
+++ b/Source/mesquite/categ/ManageCategoricalChars/ManageCategoricalChars.java
@@ -0,0 +1,708 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.ManageCategoricalChars;
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== 
+Manages matrices of categorical characters (excluding molecular sequences)*/
+public class ManageCategoricalChars extends CharMatrixManager {
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public Class getDataClass(){
+		return CategoricalData.class;
+	}
+	/*.................................................................................................................*/
+	public String getDataClassName(){
+		return CategoricalData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		if (taxa == null)
+			return null;
+		return new CategoricalData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == CategoricalData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("Standard");
+	}
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments) {
+	//	MesquiteProject proj=null;
+	//	if (file!=null)
+	//		proj = file.getProject();
+		CategoricalData data= null;
+		if (stringPos == null)
+			stringPos = new MesquiteInteger(0);
+		//@@@@@@@@@@@@@@@@@@@@
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+		boolean merging = false;
+		
+		if (fuse){
+			String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+			data = (CategoricalData)getProject().chooseData(containerOfModule(), null, taxa, CategoricalState.class, message,  true, "Fuse with Selected Matrix", "Add as New Matrix");
+			if (data != null && numChars > data.getNumChars())
+				data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+			if (data != null)
+				file.characterDataNameTranslationTable.addElement(new MesquiteString(title, data.getName()), false);
+			
+			
+		}
+		if (data == null) {
+			if (taxa == null)
+				return null;
+			data= new CategoricalData(this, taxa.getNumTaxa(), numChars, taxa);
+			if (fuse)
+				data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+		}
+		else {
+			if (fuse)
+				data.setSuppressSpecssetReading(true);
+			if (taxa == null)
+				taxa = data.getTaxa();
+			data.suppressChecksum = true;
+		}
+		//@@@@@@@@@@@@@@@@@@@@
+		data.interleaved = false;   //reset default in case this is fused
+		
+		String tok = ParseUtil.getToken(formatCommand, stringPos);
+		while (tok != null && !tok.equals(";")) {
+			if (tok.equalsIgnoreCase("TRANSPOSE")) {
+				alert("Sorry, Transposed matrices of categorical characters can't yet be read");
+				return null;
+			}
+		
+			else if (tok.equalsIgnoreCase("format")) { 
+			}
+			else if (tok.equalsIgnoreCase("RESPECTCASE")) {
+				//ignored for the moment 1.05 toDo
+			}
+		
+			else if (tok.equalsIgnoreCase("INTERLEAVE")) {
+				int sp = stringPos.getValue();
+				String e = ParseUtil.getToken(formatCommand, stringPos); //eating up = ?
+				if ("=".equals(e)){
+					String y = ParseUtil.getToken(formatCommand, stringPos); //yes or no ?
+					data.interleaved = ("yes".equalsIgnoreCase(y));
+						
+				}
+				else {
+					stringPos.setValue(sp);
+					data.interleaved = true;
+				}
+			}
+			else if (tok.equalsIgnoreCase("MISSING")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setUnassignedSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("DATATYPE")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				ParseUtil.getToken(formatCommand, stringPos); //eating up datatype
+				//alert("Error in NEXUS file format: DATATYPE subcommand must appear as the first item in the FORMAT command");
+				//return null;
+			}
+			else if (tok.equalsIgnoreCase("GAP")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setInapplicableSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("MATCHCHAR")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setMatchChar(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("SYMBOLS")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+				if (t!=null && t.equalsIgnoreCase("\"")){
+					t = ParseUtil.getToken(formatCommand, stringPos); //getting next token
+					int count = 0;
+					boolean rangeMode=false;
+					char prevChar = ' ';
+					while (t!=null && !t.equals("\"") &&  !t.equals(";")){ // this is the loop were we are processing the text between the quotes
+						for (int i = 0; i<t.length(); i++){ //process entire string
+							char c = t.charAt(i);
+							if (!StringUtil.whitespace(c, null)) {
+								if (c=='~') {  //I've modified this to allow for symbols statements like this:  "0~6".  This is in violation of the NEXUS standard, but
+									// apparently TNT writes files like this, and MacClade at least wil accept them, so Mesquite now accepts them.  But it will NOT accept it for letters,
+									// as the ordering of letters is not so clearly defined.  DRM Aug. 08
+									rangeMode=true;
+								}
+								else {
+									if (rangeMode) {  
+										if (Character.isDigit(prevChar) && Character.isDigit(c)) {
+											String prevS = Character.toString(prevChar);
+											String s = Character.toString(c);
+											int start = MesquiteInteger.fromString(prevS);
+											int end = MesquiteInteger.fromString(s);					
+											for (int symbolToAdd= start+1;symbolToAdd<=end && count<=CategoricalState.maxCategoricalState; symbolToAdd++) {
+												s=MesquiteInteger.toString(symbolToAdd);
+												if (s!=null && s.length()>=1)
+													data.setSymbol(count, s.charAt(0));
+												count++;
+											}
+										} 
+										rangeMode=false;
+									} else {
+										if (count<=CategoricalState.maxCategoricalState)
+											data.setSymbol(count, c);
+										/*
+								else {
+									if (!file.getOpenAsUntitled())
+										file.setOpenAsUntitled("The SYMBOLS subcommand indicated symbols for more than " + (CategoricalState.maxCategoricalState+1) + " states.  Mesquite categorical matrices can have at most " + (CategoricalState.maxCategoricalState+1) + " states. The data matrix may be incorrectly read.");
+
+								}
+										 */
+										count++;
+									}
+									prevChar=c;
+								}
+							}
+						}
+						t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+					}
+				}
+			}
+			else {
+				alert("Unrecognized token (\"" + tok+ "\") in FORMAT statement of categorical matrix; matrix will be stored as foreign, and not processed.");
+				return null;
+			}
+			tok = ParseUtil.getToken(formatCommand, stringPos);
+		}
+		return data;
+	}
+	/*.................................................................................................................*/
+	public boolean processCommand(CharacterData data, String commandName, String commandString) {
+		if (commandName == null)
+			return false;
+		if (commandName.equalsIgnoreCase("CHARSTATELABELS")){
+			String cN = parser.getFirstToken(commandString); //eating up command name
+			cN = parser.getNextToken();
+			String charName;
+			String stateName;
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+				charName = parser.getNextToken();  
+				if (charName != null &&  !charName.equals(",") && !charName.equals(";")) {
+					if (!charName.equals("/")) {   // there is a character name
+						data.setCharacterName(charNumber-1, charName);
+						stateName = parser.getNextToken(); // eating up slash
+					}
+					else   // there is no character name, only a slash
+						stateName = "";
+					int stateNumber = 0;
+					while (stateName!=null && !stateName.equals(",") && !stateName.equals(";")) {
+						stateName = parser.getNextToken();
+						if (!stateName.equals(",") && !stateName.equals(";") && data instanceof CategoricalData) 
+							((CategoricalData)data).setStateName(charNumber-1, stateNumber, stateName);
+						stateNumber++;
+					}
+				}
+				if (charName != null && charName.equals(";"))    // we've encountered the semicolon
+					cN = ";";
+				else
+					cN = parser.getNextToken();
+			}
+			return true;
+		}
+		else if (commandName.equalsIgnoreCase("STATELABELS")){
+
+			String cN = parser.getFirstToken(commandString); //eating up command name
+			cN = parser.getNextToken();
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+
+				String stateName;
+				int stateNumber = 0;
+				while ((stateName = parser.getNextToken())!=null && !stateName.equals(",") && !stateName.equals(";")) {
+					if (!stateName.equals(",")&&!stateName.equals(";") && data instanceof CategoricalData) 
+						((CategoricalData)data).setStateName(charNumber-1, stateNumber, stateName);
+					stateNumber++;
+				}
+				
+				cN = parser.getNextToken();
+			}
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getCharStateLabels(CharacterData data, MesquiteFile file) {
+		if (file.writeCharLabels){
+			String sS = "";
+			String csl = "\tCHARLABELS " + StringUtil.lineEnding() + "\t";
+			boolean found = false;
+			for (int i = 0; i<data.getNumChars(); i++) {
+				if (data.characterHasName(i)) {
+					found = true;
+					csl += " " + StringUtil.tokenize(data.getCharacterName(i));
+				}
+				else {
+					csl += " _";
+				}
+			}
+			if (found)
+				sS =  csl + " ; " + StringUtil.lineEnding();
+			String ssl = "\tSTATELABELS " + StringUtil.lineEnding();
+			found = false;
+			CategoricalData dData = (CategoricalData)data;
+			for (int i = 0; i<data.getNumChars(); i++) {
+				if (dData.hasStateNames(i)) {
+					ssl +=  "\t\t" + (i+1);
+					String spacers = "";
+					for (int s = 0; s<=CategoricalState.maxCategoricalState; s++) {
+						if (dData.hasStateName(i,s)) {
+							String sn = dData.getStateName(i, s);
+							if (sn!=null) {
+								ssl += spacers + " " + StringUtil.tokenize(sn);
+								spacers = "";
+								found = true;
+							}
+						}
+						else 
+							spacers = " _";
+					}
+					ssl += ", " + StringUtil.lineEnding();
+				}
+				
+			}
+			if (found)
+				sS += ssl + "\t; " + StringUtil.lineEnding();
+			return sS;
+		}
+		if (file.useSimplifiedNexus) //1. 12 so that MrBayes won't choke on exported file
+			return "";
+		
+		String csl = "\tCHARSTATELABELS " + StringUtil.lineEnding();
+		boolean found = false;
+		String end = " "; //StringUtil.lineEnding()
+		CategoricalData dData = (CategoricalData)data;
+		for (int i = 0; i<data.getNumChars(); i++) {
+			String cslC="";
+			if (i>0 && found)
+				cslC += "," + end;
+			else if (i ==0)
+				cslC += "\t\t";
+			cslC += Integer.toString(i+1) + " ";    //i+1 to convert to 1 based
+			boolean foundInCharacter = false;
+			if (data.characterHasName(i)) {
+				foundInCharacter = true;
+				cslC += StringUtil.tokenize(data.getCharacterName(i));
+			}
+			if (dData.hasStateNames(i)) {
+				cslC +=   " / ";
+				String spacers = "";
+				for (int s = 0; s<=CategoricalState.maxCategoricalState; s++) {
+					if (dData.hasStateName(i,s)) {
+						String sn = dData.getStateName(i, s);
+						if (sn!=null) {
+							foundInCharacter = true;
+						
+							cslC += spacers + " " + StringUtil.tokenize(sn);
+							spacers = "";
+						}
+					}
+					else 
+						spacers = " _";
+				}
+			}
+			if (foundInCharacter) {
+				csl += cslC;
+				found = true;
+			}
+		}
+		if (found)
+			return csl + " ; " + StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public void writeCharactersBlock(CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator){
+		String endLine =";" + StringUtil.lineEnding();
+		StringBuffer line = new StringBuffer(2*data.getNumChars());
+		if (file == null)
+			file = data.getFile();
+		if (file == null)
+			return;
+		if (file.useDataBlocks)
+			file.write("BEGIN DATA");
+		else
+			file.write("BEGIN CHARACTERS");
+		if (data.getAnnotation()!=null && !file.useSimplifiedNexus) {
+			file.write("[!" + StringUtil.tokenize(data.getAnnotation()) + "]");
+		}
+		file.write(endLine);
+		if (data.getName()!=null &&  (getProject().getNumberCharMatrices()>1 || ((file==null || (!file.useSimplifiedNexus &&  !file.useConservativeNexus)) && !NexusBlock.suppressTITLE))){
+			file.write("\tTITLE  ");
+			file.write( StringUtil.tokenize(data.getName()));
+			file.write(endLine);
+		}
+		//if (data.getTaxa().getName()!=null  && getProject().getNumberTaxas(cB.getFile())>1){ //before 13 Dec 01 had been this
+		if (( !file.useSimplifiedNexus && !file.useConservativeNexus) && data.getTaxa().getName()!=null  && getProject().getNumberTaxas()>1){ //��� should have an isUntitled method??
+			file.write("\tLINK TAXA = ");
+			file.write(StringUtil.tokenize(data.getTaxa().getName()));
+			file.write(endLine);
+		}
+		file.write("\tDIMENSIONS ");
+		if (file.useSimplifiedNexus && file.useDataBlocks) {
+			int numTaxaToWrite = data.getNumTaxa();
+			if (!file.writeTaxaWithAllMissing)
+				if (file.writeOnlySelectedTaxa)
+					numTaxaToWrite = data.numSelectedTaxaWithSomeApplicable(false);
+				else
+					numTaxaToWrite = data.numTaxaWithSomeApplicable(false);
+			else if (file.writeOnlySelectedTaxa)
+				numTaxaToWrite = data.numSelectedTaxa();
+
+				
+				file.write(" NTAX=" + numTaxaToWrite);
+		}
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = data.getNumChars();
+		else
+			numCharsToWrite = data.getNumCharsIncluded();
+		file.write(" NCHAR=" + numCharsToWrite);
+		file.write(endLine);
+		file.write("\tFORMAT");
+		file.write(" DATATYPE = STANDARD");
+		file.write(" GAP = " + data.getInapplicableSymbol() + " MISSING = " + data.getUnassignedSymbol());
+		file.write(" SYMBOLS = \" ");
+		int maxSt = ((CategoricalData)data).getMaxState();
+		int maxS = ((CategoricalData)data).getMaxSymbolDefined();
+		if (maxS < 1)
+			maxS = 1;
+		if (maxS <maxSt)
+			maxS = maxSt;
+		for (int i=0; i<=maxS; i++)
+			file.write(" " + ((CategoricalData)data).getSymbol(i));
+		file.write("\"");
+		file.write(endLine);
+		if (data.isLinked() && !file.useSimplifiedNexus  && !file.useConservativeNexus){
+			file.write("\tOPTIONS ");
+			Vector ds = data.getDataLinkages();
+			for (int i = 0; i<ds.size(); i++) {
+				file.write(" LINKCHARACTERS = ");
+				file.write(StringUtil.tokenize(((CharacterData)ds.elementAt(i)).getName()));
+			}
+			file.write(endLine);
+		}
+		if (progIndicator!=null) progIndicator.setText("Writing character & state names");
+		file.write(getCharStateLabels(data, file));
+		if (progIndicator!=null) progIndicator.setText("Writing character matrix");
+		file.write("\tMATRIX" + StringUtil.lineEnding());
+		int numTotal = data.getNumTaxa() * numCharsToWrite;
+		//MesquiteModule.mesquiteTrunk.mesquiteMessage("Composing categorical matrix ", numTotal, 0);
+		int numTaxa = data.getTaxa().getNumTaxa();
+		int tot = 0;
+		String taxonName="";
+		String taxonNameToWrite = "";
+		int maxNameLength = data.getTaxa().getLongestTaxonNameLength();
+		for (int it=0; it<numTaxa; it++) {
+			if ((data.someApplicableInTaxon(it, false)|| file.writeTaxaWithAllMissing) && (!file.writeOnlySelectedTaxa || data.getTaxa().getSelected(it))){
+				taxonName = data.getTaxa().getTaxon(it).getName();
+				if (taxonName!=null) {
+					if (file.useStandardizedTaxonNames)
+						taxonNameToWrite = "t" + it;
+					else
+						taxonNameToWrite = StringUtil.simplifyIfNeededForOutput(taxonName,file.simplifyNames);
+					file.write("\t"+taxonNameToWrite);
+					for (int i = 0; i<(maxNameLength-taxonNameToWrite.length()+2); i++)
+						file.write(" ");
+				}
+				int totInTax = 0;
+
+				if (progIndicator!=null) progIndicator.setText("Writing data for taxon " + taxonName);
+				line.setLength(0);
+				//USE SYMBOLS
+				for (int ic=0;  ic<data.getNumChars(); ic++) {
+					if (data.isCurrentlyIncluded(ic) || file.writeExcludedCharacters) {
+						if (file.ambiguityToMissing && ((CategoricalData)data).isAmbiguousOrPolymorphic(ic, it))
+							line.append('?');
+						else {
+							data.statesIntoNEXUSStringBuffer(ic, it, line);
+								
+						}
+						tot++;
+						totInTax++;
+						if (tot % 5000 == 0)
+							logln("Composing categorical matrix: " + tot + " of " + numTotal);
+						if (totInTax % 1000 == 0)
+							line.append(StringUtil.lineEnding()); //this is here becuase of current problem (at least on mrj 2.2) of long line slow writing
+
+					}
+				}
+				file.write(line.toString());
+				file.write(StringUtil.lineEnding());
+				//file.write(blocks.toString());
+				//blocks.setLength(0);
+			}
+		}
+		file.write(StringUtil.lineEnding());
+		file.write(endLine);
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus){
+			String idsCommand = getIDsCommand(data);
+			if (!StringUtil.blank(idsCommand))
+				file.write("\t" + idsCommand + StringUtil.lineEnding());
+		}
+		if (cB != null)
+			file.write(cB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		file.write("END;" + StringUtil.lineEnding());
+		if (progIndicator!=null) progIndicator.setText("Finished writing matrix");
+
+	//	file.write( blocks.toString());
+	}
+
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new CategNexusCommandTest();
+	}
+	/*...................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			if (fuse)
+				return true;
+			MesquiteProject project = file.getProject();
+			String commandName = parser.getFirstToken(command);
+			if  (commandName.equalsIgnoreCase("TEXT")){
+				int integer = MesquiteInteger.unassigned;
+				String name = null;
+				stringPos.setValue(parser.getPosition());
+				String[][] subcommands  = ParseUtil.getSubcommands(command, stringPos);
+				if (subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)
+					return false;
+				int whichState = MesquiteInteger.unassigned;
+				int whichCharacter = MesquiteInteger.unassigned;
+				String text = null;
+				Taxa taxa = nBlock.getDefaultTaxa();
+				CharacterData data = nBlock.getDefaultCharacters();
+				
+				for (int i=0; i<subcommands[0].length; i++){
+					String subC = subcommands[0][i];
+					if ("TAXA".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						Taxa t = getProject().getTaxaLastFirst(token);
+						if (t==null){
+							int wt = MesquiteInteger.fromString(token);
+							if (MesquiteInteger.isCombinable(wt))
+								t = getProject().getTaxa(wt-1);
+						}
+						if (t!=null)
+							taxa = t;
+						else
+							return false;
+					}
+					else if ("CHARACTERS".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						 CharacterData t = getProject().findCharacterMatrix(file, taxa, token);
+						if (t!=null)
+							data = t;
+						else
+							return false;
+					}
+					else if ("TEXT".equalsIgnoreCase(subC)) {
+						text = subcommands[1][i];
+					}
+					else if ("STATE".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichState = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichState))
+							return false;
+					}
+					else if ("INTEGER".equalsIgnoreCase(subC)) {
+						integer = MesquiteInteger.fromString(subcommands[1][i]);
+					}
+					else if ("CHARACTER".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichCharacter = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichCharacter))
+							return false;
+						whichCharacter = CharacterStates.toInternal(whichCharacter);
+					}
+				}
+				if (!MesquiteInteger.isCombinable(whichCharacter))
+					return false;
+				if (taxa !=null && text !=null && data !=null) {
+					if (MesquiteInteger.isCombinable(whichState) && (data instanceof CategoricalData)) {
+						((CategoricalData)data).setStateNote(whichCharacter, whichState, text);
+						return true;
+					}
+				}
+				
+			}
+			else if  (commandName.equalsIgnoreCase("ANS")){
+				int integer = MesquiteInteger.unassigned;
+				String name = null;
+				stringPos.setValue(parser.getPosition());
+				String[][] subcommands  = ParseUtil.getSubcommands(command, stringPos);
+				if (subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)
+					return false;
+				int whichState = MesquiteInteger.unassigned;
+				int whichCharacter = MesquiteInteger.unassigned;
+				String text = null;
+				Taxa taxa = nBlock.getDefaultTaxa();
+				CharacterData data = nBlock.getDefaultCharacters();
+				
+				for (int i=0; i<subcommands[0].length; i++){
+					String subC = subcommands[0][i];
+					if ("TAXA".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						Taxa t = getProject().getTaxa(token);
+						if (t==null){
+							int wt = MesquiteInteger.fromString(token);
+							if (MesquiteInteger.isCombinable(wt))
+								t = getProject().getTaxa(wt-1);
+						}
+						if (t!=null)
+							taxa = t;
+						else
+							return false;
+					}
+					else if ("CHARACTERS".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						 CharacterData t = getProject().findCharacterMatrix(file, taxa, token);
+						if (t!=null)
+							data = t;
+						else
+							return false;
+					}
+					else if ("TEXT".equalsIgnoreCase(subC)) {
+						text = subcommands[1][i];
+					}
+					else if ("STATE".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichState = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichState))
+							return false;
+					}
+					else if ("INTEGER".equalsIgnoreCase(subC)) {
+						integer = MesquiteInteger.fromString(subcommands[1][i]);
+					}
+					else if ("CHARACTER".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichCharacter = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichCharacter))
+							return false;
+						whichCharacter = CharacterStates.toInternal(whichCharacter);
+					}
+				}
+				if (!MesquiteInteger.isCombinable(whichCharacter))
+					return false;
+				if (taxa !=null && text !=null && data !=null) {
+					if (MesquiteInteger.isCombinable(whichState) && (data instanceof CategoricalData)) {
+						((CategoricalData)data).setStateNote(whichCharacter, whichState, text);
+						return true;
+					}
+				}
+				
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			String s ="";
+			boolean found = false;
+			MesquiteProject project = file.getProject();
+			for (int i=0; i<project.getNumberCharMatrices(); i++){
+				CharacterData d = getProject().getCharacterMatrix(i);
+				if (d instanceof CategoricalData && d.getFile() == file){
+					CategoricalData data = (CategoricalData)d;
+					String dataSpec = "";
+					if (project.getNumberTaxas()>1)
+						dataSpec = " TAXA = " +  StringUtil.tokenize(data.getTaxa().getName()) + "";
+					if (project.getNumberCharMatrices()>1 || (!file.useSimplifiedNexus&&  !file.useConservativeNexus && !data.hasDefaultName() && !NexusBlock.suppressTITLE))
+						dataSpec += " CHARACTERS = " +  StringUtil.tokenize(data.getName()) + "";
+					for (int ic = 0; ic<data.getNumChars(); ic++){
+						for (int is = 0; is<=CategoricalState.maxCategoricalState; is++){
+							String obj = data.getStateNote(ic, is);
+							if (!StringUtil.blank(obj)){
+								s += "\tTEXT  " + dataSpec + " CHARACTER = " + CharacterStates.toExternal(ic) + " STATE = " + is+ " TEXT = " + StringUtil.tokenize(obj) + ";" + StringUtil.lineEnding();
+								found = true;
+							}
+						}
+					}
+				}
+			}
+			if (found)
+				return s;
+			else
+				return null;
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage categorical character matrices";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages categorical data matrices (including read/write in NEXUS file)." ;
+   	 }
+}
+	
+/* ======================================================================== */
+/** An object of this kind can be returned by getNexusCommandTest that will be stored in the modulesinfo vector and used
+to search for modules that can read a particular command in a particular block.  (Much as the NexusBlockObject.)*/
+class CategNexusCommandTest extends NexusCommandTest  {
+	MesquiteInteger pos = new MesquiteInteger();
+	/**returns whether or not the module can deal with command*/
+	public boolean readsWritesCommand(String blockName, String commandName, String command){
+		boolean b = (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("TEXT")));
+		if (b){
+			pos.setValue(0);
+			String firstToken = ParseUtil.getFirstToken(command,  pos);
+			
+			String[][] subcommands  = ParseUtil.getSubcommands(command, pos);
+			if (subcommands == null)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "CHARACTER")<0)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "STATE")<0)
+				return false;
+			return true;
+		}
+		if (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("ANS")))
+			return true;
+		return false;
+	} 
+}
+
diff --git a/Source/mesquite/categ/ManageDNARNAChars/ManageDNARNAChars.java b/Source/mesquite/categ/ManageDNARNAChars/ManageDNARNAChars.java
new file mode 100644
index 0000000..4adf218
--- /dev/null
+++ b/Source/mesquite/categ/ManageDNARNAChars/ManageDNARNAChars.java
@@ -0,0 +1,344 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.ManageDNARNAChars;
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== 
+Manages DNA and RNA data matrices */
+public class ManageDNARNAChars extends CategMatrixManager {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public Class getDataClass(){
+		return DNAData.class;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getDataClassName(){
+		return DNAData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		return new DNAData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == DNAData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("DNA") || dataType.equalsIgnoreCase("RNA")  || dataType.equalsIgnoreCase("NUCLEOTIDE");
+	}
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments) {
+		if (taxa==null) {
+			MesquiteMessage.warnProgrammer("Error: taxa null in processFormat  in " + getName());
+			return null;
+		}
+		MesquiteProject proj=null;
+		if (file!=null)
+			proj = file.getProject();
+		else
+			proj = getProject();
+		CategoricalData data= null;
+		if (stringPos == null)
+			stringPos = new MesquiteInteger(0);
+
+		//@@@@@@@@@@@@@@@@@@@@
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+
+		if (dataType != null && dataType.equalsIgnoreCase("RNA")) {
+			if (fuse){
+				String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+				data = (DNAData)getProject().chooseData(containerOfModule(), null, taxa, RNAState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+				if (data != null && numChars > data.getNumChars())
+					data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+				if (data != null)
+					file.characterDataNameTranslationTable.addElement(new MesquiteString(title, data.getName()), false);
+			}
+			if (data == null) {
+				data= new RNAData(this, taxa.getNumTaxa(), numChars, taxa);  //RNA DATA????
+				if (fuse)
+					data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+			}
+			else {
+				if (fuse)
+					data.setSuppressSpecssetReading(true);
+				data.suppressChecksum = true;
+			}
+			((DNAData)data).setDisplayAsRNA(true);
+		}
+		else {
+			if (fuse){
+				String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+				data = (DNAData)getProject().chooseData(containerOfModule(), null, taxa, DNAState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+				if (data != null && numChars > data.getNumChars())
+					data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+				if (data != null)
+					file.characterDataNameTranslationTable.addElement(new MesquiteString(title, data.getName()), false);
+			}
+			if (data == null){
+				data= new DNAData(this, taxa.getNumTaxa(), numChars, taxa);
+				if (fuse)
+					data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+			}
+			else{
+				if (fuse)
+					data.setSuppressSpecssetReading(true);
+				data.suppressChecksum = true;
+			}
+		}
+		data.interleaved = false;   //reset default in case this is fused
+		//@@@@@@@@@@@@@@@@@@@@
+		String tok = ParseUtil.getToken(formatCommand, stringPos);
+		while (tok != null && !tok.equals(";")) {
+			if (tok.equalsIgnoreCase("TRANSPOSE")) {
+				alert("Sorry, Transposed matrices of DNA characters can't yet be read");
+				return null;
+			}
+			else if (tok.equalsIgnoreCase("interleave")) {
+				int sp = stringPos.getValue();
+				String e = ParseUtil.getToken(formatCommand, stringPos); //eating up = ?
+				if ("=".equals(e)){
+					String y = ParseUtil.getToken(formatCommand, stringPos); //yes or no ?
+					data.interleaved = ("yes".equalsIgnoreCase(y));
+
+				}
+				else {
+					stringPos.setValue(sp);
+					data.interleaved = true;
+				}
+			}
+			else if (tok.equalsIgnoreCase("MISSING")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setUnassignedSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("GAP")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setInapplicableSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("MATCHCHAR")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setMatchChar(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("DATATYPE")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				ParseUtil.getToken(formatCommand, stringPos); //eating up datatype
+				//alert("Error in NEXUS file format: DATATYPE subcommand must appear as the first item in the FORMAT command");
+				//return null;
+			}
+			else if (tok.equalsIgnoreCase("format")) { 
+			}
+			else if (tok.equalsIgnoreCase("SYMBOLS")) {  //should this be allowed?
+				logln("\n*******\nNEXUS file format warning: SYMBOLS command with DNA or RNA datatypes has undefined behavior in NEXUS format; file may not be read as you expect.\n*******\n");
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+				if (t!=null && t.equalsIgnoreCase("\"")){
+					t = ParseUtil.getToken(formatCommand, stringPos); //getting next token
+					int count = 4;   // 16 March '10 changed to 4 so that it adds these on to the end
+					while (t!=null && !t.equals("\"") &&  !t.equals(";")){
+						for (int i = 0; i<t.length(); i++){ //process entire string
+							char c = t.charAt(i);
+							if (!StringUtil.whitespace(c, null)) {
+								if (count<=CategoricalState.maxCategoricalState)
+									data.setSymbol(count, c);
+								count++;
+							}
+						}
+						t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+					}
+				}
+			}
+			else {
+				alert("Unrecognized token (\"" + tok+ "\") in FORMAT statement of DNA matrix; matrix will be stored as foreign, and not processed.");
+				return null;
+			}
+			tok = ParseUtil.getToken(formatCommand, stringPos);
+		}
+		return data;
+	}
+	/*.................................................................................................................*
+	/*.................................................................................................................*/
+	public boolean processCommand(CharacterData data, String commandName, String commandString) {
+		if (commandName.equalsIgnoreCase("CHARSTATELABELS")){
+			String cN = parser.getFirstToken(commandString); //eating up command name
+			cN = parser.getNextToken();
+			String charName;
+			String stateName;
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+				charName = parser.getNextToken();  
+				if (!charName.equals(",") && !charName.equals(";")) {
+					if (!charName.equals("/")) {   // there is a character name
+						data.setCharacterName(charNumber-1, charName);
+						stateName = parser.getNextToken(); // eating up slash
+					}
+					else   // there is no character name, only a slash
+						stateName = "";
+					while (stateName!=null && !stateName.equals(",") && !stateName.equals(";")) {
+						stateName = parser.getNextToken();
+					}
+				}
+				if (charName.equals(";"))    // we've encountered the semicolon
+					cN = ";";
+				else
+					cN = parser.getNextToken();
+			}
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getCharStateLabels(CharacterData data) {
+		String csl = "CHARSTATELABELS " + StringUtil.lineEnding();
+		boolean found = false;
+		String end = " "; //StringUtil.lineEnding()
+		for (int i = 0; i<data.getNumChars(); i++) {
+			String cslC="";
+			if (i>0 && found)
+				cslC += "," + end;
+			else if (i ==0)
+				cslC += "\t\t";
+			cslC += Integer.toString(i+1) + " ";    //i+1 to convert to 1 based
+			boolean foundInCharacter = false;
+			if (data.characterHasName(i)) {
+				foundInCharacter = true;
+				cslC += StringUtil.tokenize(data.getCharacterName(i));
+			}
+			if (foundInCharacter) {
+				csl += cslC;
+				found = true;
+			}
+		}
+		if (found)
+			return csl + " ; " + StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public void writeCharactersBlock(CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator){
+		String endLine = ";" + StringUtil.lineEnding();
+		StringBuffer blocks = new StringBuffer(5000);
+		if (file!=null && file.useDataBlocks)
+			blocks.append("BEGIN DATA");
+		else
+			blocks.append("BEGIN CHARACTERS");
+		if (data.getAnnotation()!=null && !file.useSimplifiedNexus) {
+			file.write("[!" + StringUtil.tokenize(data.getAnnotation()) + "]");
+		}
+		blocks.append(endLine);
+		if (data.getName()!=null &&  (getProject().getNumberCharMatrices()>1 || ((file==null || (!file.useSimplifiedNexus &&  !file.useConservativeNexus)) && !NexusBlock.suppressTITLE))){
+			blocks.append("\tTITLE  ");
+			blocks.append( StringUtil.tokenize(data.getName()));
+			blocks.append(endLine);
+		}
+		//if (data.getTaxa().getName()!=null  && getProject().getNumberTaxas(cB.getFile())>1){ //before 13 Dec 01 had been this
+		if ((file==null || !file.useSimplifiedNexus) && data.getTaxa().getName()!=null  && getProject().getNumberTaxas()>1){ //��� should have an isUntitled method??
+			blocks.append("\tLINK TAXA = ");
+			blocks.append(StringUtil.tokenize(data.getTaxa().getName()));
+			blocks.append(endLine);
+		}
+		blocks.append("\tDIMENSIONS ");
+		if (file!=null && file.useSimplifiedNexus && file.useDataBlocks){
+			int numTaxaToWrite = data.getNumTaxa();
+			if (!file.writeTaxaWithAllMissing)
+				if (file.writeOnlySelectedTaxa)
+					numTaxaToWrite = data.numSelectedTaxaWithSomeApplicable(false);
+				else
+					numTaxaToWrite = data.numTaxaWithSomeApplicable(false);
+			else if (file.writeOnlySelectedTaxa)
+				numTaxaToWrite = data.numSelectedTaxa();
+			blocks.append(" NTAX=" + numTaxaToWrite);
+		}
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = data.getNumChars();
+		else
+			numCharsToWrite = data.getNumCharsIncluded();
+		blocks.append(" NCHAR=" + numCharsToWrite);
+		blocks.append(endLine);
+		blocks.append("\tFORMAT");
+		if (!((DNAData)data).getDisplayAsRNA())
+			blocks.append(" DATATYPE = DNA");
+		else
+			blocks.append(" DATATYPE = RNA");
+		if (data.interleaved && file.interleaveAllowed)
+			blocks.append(" INTERLEAVE");
+		blocks.append(" GAP = " + data.getInapplicableSymbol() + " MISSING = " + data.getUnassignedSymbol());
+		blocks.append(endLine);
+		if (data.isLinked() && !file.useSimplifiedNexus){
+			blocks.append("\tOPTIONS ");
+			Vector ds = data.getDataLinkages();
+			for (int i = 0; i<ds.size(); i++) {
+				blocks.append(" LINKCHARACTERS = ");
+				blocks.append(StringUtil.tokenize(((CharacterData)ds.elementAt(i)).getName()));
+			}
+			blocks.append(endLine);
+		}
+		if (!file.useSimplifiedNexus) //1. 12 so that MrBayes won't choke on exported file
+			blocks.append(getCharStateLabels(data));
+
+		writeNexusMatrix(data, cB, blocks, file, progIndicator);
+
+		blocks.append( StringUtil.lineEnding());
+		if (!file.useSimplifiedNexus && !file.useConservativeNexus){
+			String idsCommand = null;
+			if (!StringUtil.blank(data.getUniqueID()))
+				idsCommand = "BLOCKID " + data.getUniqueID() + ";" + StringUtil.lineEnding();
+			if (!StringUtil.blank(idsCommand))
+				blocks.append("\t" + idsCommand + StringUtil.lineEnding());
+		}
+		if (cB !=null)
+			blocks.append(cB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		blocks.append("END");
+		blocks.append(";" + StringUtil.lineEnding());
+		//	MesquiteModule.mesquiteTrunk.mesquiteMessage("DNA matrix composed", 1, 0);
+
+		file.writeLine( blocks.toString());
+	}
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage DNA/RNA matrices";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages DNA/RNA data matrices (including read/write in NEXUS file)." ;
+	}
+}
+
+
+
diff --git a/Source/mesquite/categ/ManageProteinChars/ManageProteinChars.java b/Source/mesquite/categ/ManageProteinChars/ManageProteinChars.java
new file mode 100644
index 0000000..da1ed9e
--- /dev/null
+++ b/Source/mesquite/categ/ManageProteinChars/ManageProteinChars.java
@@ -0,0 +1,306 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.ManageProteinChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== 
+Manages Protein sequence data matrices  */
+public class ManageProteinChars extends CategMatrixManager {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	public Class getDataClass(){
+		return ProteinData.class;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getDataClassName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		return new ProteinData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == ProteinData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("Protein");
+	}
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments) {
+		if (taxa==null) {
+			MesquiteMessage.warnProgrammer("Error: taxa null in processFormat  in " + getName());
+			return null;
+		}
+		MesquiteProject proj=null;
+		if (file!=null)
+			proj = file.getProject();
+		CategoricalData data = null;
+		//@@@@@@@@@@@@@@@@@@@@
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+
+		if (fuse){
+			String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+			data = (ProteinData)getProject().chooseData(containerOfModule(), null, taxa, ProteinState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+			if (data != null && numChars > data.getNumChars())
+				data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+		}
+		if (data == null) {
+			data= new ProteinData(this, taxa.getNumTaxa(), numChars, taxa);
+			if (fuse)
+				data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+		}
+		else {
+			if (fuse)
+				data.setSuppressSpecssetReading(true);
+			data.suppressChecksum = true;
+		}
+		//@@@@@@@@@@@@@@@@@@@@
+		String tok = ParseUtil.getToken(formatCommand, stringPos);
+		while (!tok.equals(";")) {
+			if (tok.equalsIgnoreCase("TRANSPOSE")) {
+				alert("Sorry, Transposed matrices of protein data can't yet be read");
+				return null;
+			}
+			else if (tok.equalsIgnoreCase("interleave")) {
+				int sp = stringPos.getValue();
+				String e = ParseUtil.getToken(formatCommand, stringPos); //eating up = ?
+				if ("=".equals(e)){
+					String y = ParseUtil.getToken(formatCommand, stringPos); //yes or no ?
+					data.interleaved = ("yes".equalsIgnoreCase(y));
+						
+				}
+				else {
+					stringPos.setValue(sp);
+					data.interleaved = true;
+				}
+			}
+			else if (tok.equalsIgnoreCase("format")) { 
+			}
+			else if (tok.equalsIgnoreCase("MISSING")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setUnassignedSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("GAP")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setInapplicableSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("MATCHCHAR")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setMatchChar(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("DATATYPE")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				ParseUtil.getToken(formatCommand, stringPos); //eating up datatype
+				//alert("Error in NEXUS file format: DATATYPE subcommand must appear as the first item in the FORMAT command");
+				//return null;
+			}
+			else if (tok.equalsIgnoreCase("SYMBOLS")) { 
+				logln("\n*******\nNEXUS file format warning: SYMBOLS command with PROTEIN data has undefined behavior in NEXUS format; file may not be read as you expect.\n*******\n");
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+				if (t!=null && t.equalsIgnoreCase("\"")){
+					t = ParseUtil.getToken(formatCommand, stringPos); //getting next token
+					int count = ProteinState.maxProteinState+1;  //add them to the end
+					while (t!=null && !t.equals("\"") &&  !t.equals(";")){
+						for (int i = 0; i<t.length(); i++){ //process entire string
+							char c = t.charAt(i);
+							if (!StringUtil.whitespace(c, null)) {
+								if (count<=CategoricalState.maxCategoricalState)
+									data.setSymbol(count, c);
+								count++;
+							}
+						}
+						t = ParseUtil.getToken(formatCommand, stringPos); //eating up "
+					}
+				}
+			}
+			else {
+				alert("Unrecognized token (\"" + tok+ "\") in FORMAT statement of Protein matrix; matrix will be stored as foreign, and not processed.");
+				return null;
+			}
+			tok = ParseUtil.getToken(formatCommand, stringPos);
+		}
+		return data;
+	}
+	/*.................................................................................................................*
+	/*.................................................................................................................*/
+	public boolean processCommand(CharacterData data, String commandName, String commandString) {
+		if (commandName.equalsIgnoreCase("CHARSTATELABELS")){
+			String cN = parser.getFirstToken(commandString); //eating up command name
+			cN = parser.getNextToken();
+			String charName;
+			String stateName;
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+				charName = parser.getNextToken();  
+				if (!charName.equals(",") && !charName.equals(";")) {
+					if (!charName.equals("/")) {   // there is a character name
+						data.setCharacterName(charNumber-1, charName);
+						stateName = parser.getNextToken(); // eating up slash
+					}
+					else   // there is no character name, only a slash
+						stateName = "";
+					while (stateName!=null && !stateName.equals(",") && !stateName.equals(";")) {
+						stateName = parser.getNextToken();
+					}
+				}
+				if (charName.equals(";"))    // we've encountered the semicolon
+					cN = ";";
+				else
+					cN = parser.getNextToken();
+			}
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getCharStateLabels(CharacterData data) {
+		String csl = "CHARSTATELABELS " + StringUtil.lineEnding();
+		boolean found = false;
+		String end = " "; //
+		for (int i = 0; i<data.getNumChars(); i++) {
+			String cslC="";
+			if (i>0 && found)
+				cslC += "," + end;
+			else if (i ==0)
+				cslC += "\t\t";
+			cslC += Integer.toString(i+1) + " ";    //i+1 to convert to 1 based
+			boolean foundInCharacter = false;
+			if (data.characterHasName(i)) {
+				foundInCharacter = true;
+				cslC += StringUtil.tokenize(data.getCharacterName(i));
+			}
+			if (foundInCharacter) {
+				csl += cslC;
+				found = true;
+			}
+		}
+		if (found)
+			return csl + " ; " + StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public void writeCharactersBlock(CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator){
+		String endLine = ";" + StringUtil.lineEnding();
+		StringBuffer blocks = new StringBuffer(5000);
+		if (file!=null && file.useDataBlocks)
+			blocks.append("BEGIN DATA");
+		else
+			blocks.append("BEGIN CHARACTERS");
+		if (data.getAnnotation()!=null && !file.useSimplifiedNexus) 
+			file.write("[!" + StringUtil.tokenize(data.getAnnotation()) + "]");
+		blocks.append(endLine);
+		if (data.getName()!=null &&  (getProject().getNumberCharMatrices()>1 || ((file==null || (!file.useSimplifiedNexus &&  !file.useConservativeNexus)) && !NexusBlock.suppressTITLE))){
+			blocks.append("\tTITLE  ");
+			blocks.append( StringUtil.tokenize(data.getName()));
+			blocks.append(endLine);
+		}
+		if ((file==null || !file.useSimplifiedNexus) && data.getTaxa().getName()!=null  && (cB==null || getProject().getNumberTaxas(cB.getFile())>1)){ 
+			blocks.append("\tLINK TAXA = ");
+			blocks.append(StringUtil.tokenize(data.getTaxa().getName()));
+			blocks.append(endLine);
+		}
+		blocks.append("\tDIMENSIONS ");
+		if (file!=null && file.useSimplifiedNexus && file.useDataBlocks){
+			int numTaxaToWrite = data.getNumTaxa();
+			if (!file.writeTaxaWithAllMissing)
+				if (file.writeOnlySelectedTaxa)
+					numTaxaToWrite = data.numSelectedTaxaWithSomeApplicable(false);
+				else
+					numTaxaToWrite = data.numTaxaWithSomeApplicable(false);
+			else if (file.writeOnlySelectedTaxa)
+				numTaxaToWrite = data.numSelectedTaxa();
+			blocks.append(" NTAX=" + numTaxaToWrite);
+		}
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = data.getNumChars();
+		else
+			numCharsToWrite = data.getNumCharsIncluded();
+		blocks.append(" NCHAR=" + numCharsToWrite);
+		blocks.append(endLine);
+		blocks.append("\tFORMAT");
+		blocks.append(" DATATYPE = Protein");
+		if (data.interleaved && file.interleaveAllowed)
+			blocks.append(" INTERLEAVE");
+		blocks.append(" GAP = " + data.getInapplicableSymbol() + " MISSING = " + data.getUnassignedSymbol());
+		blocks.append(endLine);
+		if (data.isLinked() && !file.useSimplifiedNexus  && !file.useConservativeNexus){
+			blocks.append("\tOPTIONS ");
+			Vector ds = data.getDataLinkages();
+			for (int i = 0; i<ds.size(); i++) {
+				blocks.append(" LINKCHARACTERS = ");
+				blocks.append(StringUtil.tokenize(((CharacterData)ds.elementAt(i)).getName()));
+			}
+			blocks.append(endLine);
+		}
+		if (!file.useSimplifiedNexus) //1. 12 so that MrBayes won't choke on exported file
+			blocks.append(getCharStateLabels(data));
+
+		writeNexusMatrix(data, cB, blocks, file, progIndicator);
+
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus){
+			String idsCommand = getIDsCommand(data);
+			if (!StringUtil.blank(idsCommand))
+				blocks.append("\t" + idsCommand + StringUtil.lineEnding());
+		}
+		if (cB != null)
+			blocks.append(cB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		blocks.append("END");
+		
+		blocks.append(";" + StringUtil.lineEnding());
+
+		file.writeLine( blocks.toString());
+	}
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage Protein matrices";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages Protein data matrices (including read/write in NEXUS file)." ;
+   	 }
+}
+	
+	
+
diff --git a/Source/mesquite/categ/MultistateToMissing/MultistateToMissing.java b/Source/mesquite/categ/MultistateToMissing/MultistateToMissing.java
new file mode 100644
index 0000000..9ee8ff2
--- /dev/null
+++ b/Source/mesquite/categ/MultistateToMissing/MultistateToMissing.java
@@ -0,0 +1,76 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.MultistateToMissing;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MultistateToMissing extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Attempt to convert multistate characters to missing in non-categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table,undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		long s = data.getState(ic,it);
+		if (CategoricalState.cardinality(s)<=1)
+			return;
+		data.setState(ic, it, CategoricalState.unassigned);
+		if (!MesquiteLong.isCombinable(numCellsAltered))
+			numCellsAltered = 0;
+		numCellsAltered++;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Convert Uncert./Polymorph. to Missing";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Alters categorical data by converting uncertain or polymorphic entries to missing data." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/PolymToAmbiguity/PolymToAmbiguity.java b/Source/mesquite/categ/PolymToAmbiguity/PolymToAmbiguity.java
new file mode 100644
index 0000000..6e63cb5
--- /dev/null
+++ b/Source/mesquite/categ/PolymToAmbiguity/PolymToAmbiguity.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.PolymToAmbiguity;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class PolymToAmbiguity extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Attempt to convert polymorphisms to uncertainties (ambiguities) in non-categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table,undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		long s = data.getState(ic,it);
+		if (CategoricalState.cardinality(s)<=1)
+			return;
+		if (CategoricalState.isUncertain(s))
+			return;
+		data.setState(ic, it, CategoricalState.setUncertainty(s, true));
+		if (!MesquiteLong.isCombinable(numCellsAltered))
+			numCellsAltered = 0;
+		numCellsAltered++;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Convert Polymorphisms to Uncertainties";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Alters categorical data by converting polymorphic entries to uncertainties." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/ProportionUniqueStates/ProportionUniqueStates.java b/Source/mesquite/categ/ProportionUniqueStates/ProportionUniqueStates.java
new file mode 100644
index 0000000..f5eaab1
--- /dev/null
+++ b/Source/mesquite/categ/ProportionUniqueStates/ProportionUniqueStates.java
@@ -0,0 +1,204 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.ProportionUniqueStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.categ.lib.CategoricalData;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ProportionUniqueStates extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	MesquiteBoolean countExcluded;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//matrixSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of character matrix (for percent gaps)"); 
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, CategoricalState.class, "Source of character matrix (for percent gaps)"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		countExcluded = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Count Excluded Characters", makeCommand("toggleCountExcluded",  this), countExcluded);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		temp.addLine("toggleCountExcluded " + countExcluded.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		 if (checker.compare(this.getClass(), "Sets whether or not excluded characters are considered in the calculation", "[on or off]", commandName, "toggleCountExcluded")) {
+			countExcluded.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+
+	public boolean taxonIsUnique(CharacterData data, int ic, int it){
+		CategoricalState cs = null;
+		cs = (CategoricalState)observedStates.getCharacterState(cs, ic, it);   // state of original
+		if (cs.isInapplicable())
+			return false;
+		CategoricalState cs2 = null;
+		
+		for (int it2=0; it2<data.getNumTaxa(); it2++) {
+			if (it!=it2){
+				cs2 = (CategoricalState)observedStates.getCharacterState(cs2, ic, it2);  // now let's get state of other taxon
+				if (!cs2.isInapplicable()){   // only count ones with non-applicable
+					if (cs.statesShared(cs2))   // if any states shared then non unique
+						return false;
+				}
+			}
+		}
+
+		return true;
+	}
+	
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		
+		
+		if (numChars != 0) {
+			CharacterState cs = null;
+			int useNumChars = 0;
+			int numUnique = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (countExcluded.getValue() || incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable()){   // only count ones with non-applicable
+						useNumChars++;
+						if (taxonIsUnique(data,ic, it)) 
+							numUnique++;
+					}
+
+				}
+			}
+
+			if (useNumChars == 0)
+				result.setValue(0.0);
+			else
+				result.setValue(((double)numUnique)/useNumChars);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+
+		if (resultString!=null)
+			resultString.setValue("Proportion of unique states in matrix "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+			CharacterData d = observedStates.getParentData();
+			if (d != null && d.getName()!= null) {
+				String n =  d.getName();
+				if (n.length()>12)
+					n = n.substring(0, 12); 
+				return "Prop. Unique (" + n + ")";
+			}
+		}
+		return "Prop. Unique";  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion Unique States in Taxon";  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public String getParameters() {
+		return "Proportion unique states in taxon in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the proportion of unique states in a taxon for a data matrix." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 303;  
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/categ/RemoveInvariant/RemoveInvariant.java b/Source/mesquite/categ/RemoveInvariant/RemoveInvariant.java
new file mode 100644
index 0000000..f4c4057
--- /dev/null
+++ b/Source/mesquite/categ/RemoveInvariant/RemoveInvariant.java
@@ -0,0 +1,97 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.RemoveInvariant;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RemoveInvariant extends DataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+   	
+	public boolean removeCharactersThatAreInvariant(CategoricalData cData){
+		boolean removedSome = false;
+		for (int ic = cData.getNumChars()-1; ic>=0; ic--){
+			if (!cData.charIsVariable(ic, false)) {
+				cData.deleteCharacters(ic, 1, false);
+				cData.deleteInLinked(ic, 1, false);
+				removedSome=true;
+			}
+		}
+		return removedSome;
+	}
+
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+		if (!(cData instanceof CategoricalData))
+			return false;
+		CategoricalData data = (CategoricalData)cData;
+		int oldNumChars = data.getNumChars();
+		removeCharactersThatAreInvariant(data);
+		
+		logln("" + (oldNumChars-data.getNumChars()) +  " characters removed");
+		return true;
+   	}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 270;  
+     	}
+  	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Remove Invariant Characters";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+    			return "Remove Invariant Characters";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Removes all characters that have one state or fewer." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/categ/ResolveStateAmbiguity/ResolveStateAmbiguity.java b/Source/mesquite/categ/ResolveStateAmbiguity/ResolveStateAmbiguity.java
new file mode 100644
index 0000000..f989ed5
--- /dev/null
+++ b/Source/mesquite/categ/ResolveStateAmbiguity/ResolveStateAmbiguity.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.ResolveStateAmbiguity;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ResolveStateAmbiguity extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Attempt to resolve ambiguities in non-categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table, undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		long s = data.getState(ic,it);
+		if (!CategoricalState.isUncertain(s))
+			return;
+		long result = 0L;
+		int card = CategoricalState.cardinality(s);
+		if (card>1) {
+			int resolve = (int)Math.round(Math.random()*card+0.5);
+			int count=0;
+			for (int e=0; e<=data.getMaxPossibleState(); e++) {
+				if (CategoricalState.isElement(s, e)) {
+					count++;
+					if (count>=resolve) {
+						result=CategoricalState.addToSet(result,e);
+						break;
+					}
+				}
+			}
+			if (result!=0L) {
+				data.setState(ic,it, result);
+				if (!MesquiteLong.isCombinable(numCellsAltered))
+					numCellsAltered = 0;
+				numCellsAltered++;
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Arbitrarily Resolve State Ambiguities";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Alters categorical data by arbitrarily resolving ambiguous sites to one of the possible states." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/SmallStateNamesEditor/SmallStateNamesEditor.java b/Source/mesquite/categ/SmallStateNamesEditor/SmallStateNamesEditor.java
new file mode 100644
index 0000000..5882744
--- /dev/null
+++ b/Source/mesquite/categ/SmallStateNamesEditor/SmallStateNamesEditor.java
@@ -0,0 +1,409 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.categ.SmallStateNamesEditor;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.lib.table.*;
+
+public class SmallStateNamesEditor extends MatrixInfoPanelAssistantI  {
+	SStateNamesPanel panel;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*
+	public  Class getHireSubchoice(){
+		return NumberForTree.class;
+	}*/
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+		}
+
+	/*.................................................................................................................*/
+	public MatrixInfoExtraPanel getPanel(ClosablePanelContainer container){
+		panel =  new SStateNamesPanel(container, this);
+		return panel;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("panelOpen " + panel.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the panel open", null, commandName, "panelOpen")) {
+			if (panel != null)
+				panel.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Small State Names Editor";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Edits character state names within the editor info panel.";
+	}
+}
+/*===========================================*/
+class SStateNamesPanel extends MatrixInfoExtraPanel  {
+	String message = null;
+	SmallStateNamesEditor ownerModule;
+	StringInABox statesBox;
+	NameField charName;
+	StatesField statesNames;
+	CategoricalData cData;
+	ScrollPane pane;
+	public SStateNamesPanel(ClosablePanelContainer container, SmallStateNamesEditor ownerModule){
+		super(container, "State Names");
+		statesBox =  new StringInABox("", null, 50);
+		charName = new NameField(this, -1);
+		pane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+		statesNames = new StatesField(this);
+		statesNames.setBackground(getBackground());
+		currentHeight = 100 + MINHEIGHT + charNameHeight;
+		setLayout(null);
+		add(charName);
+		pane.add(statesNames);
+		add(pane);
+		resetLocs();
+		this.ownerModule = ownerModule;
+		setOpen(true);
+	}
+	public boolean userExpandable(){
+		return true;
+	}
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table){
+		super.setMatrixAndTable(data, table);
+		this.cData = (CategoricalData)data;
+		statesNames.setData(cData);
+		container.requestHeightChange(this);
+		repaint();
+	}
+	public void setCell(int ic, int it){
+		if (!isVisible())
+			return;
+		super.setCell(ic, it);
+		adjustMessage();
+			statesNames.setEditEnabled(ic >= 0 && ic< cData.getNumChars());
+			charName.setEditEnabled(ic >= 0 && ic< cData.getNumChars());
+		container.requestHeightChange(this);
+		repaint();
+	}
+	private void adjustMessage(){
+		setTitle("State Names");
+		if (data == null)
+			message = "no matrix";
+		else if (it < 0 && ic < 0) {
+			message = " ";
+			charName.setText("");
+			statesNames.setCharacter(-1);
+		}
+		else {
+			message = "";
+			if (ic >= 0 && ic < data.getNumChars()) {
+				setTitle("State Names (Char. " + (ic+1) + ")");
+				if (!charName.getText().equals(data.getCharacterName(ic)))
+					charName.setText(data.getCharacterName(ic));
+				statesNames.setCharacter(ic);
+				message = "";
+				/*if (data.characterHasName(ic))
+					message += data.getCharacterName(ic) + " (" + (ic+1) + ")";
+				else
+					message += (ic+1);
+				 */
+				if (data instanceof CategoricalData){
+					CategoricalData cData = (CategoricalData)data;
+					for (int s= 0; s<= CategoricalState.maxCategoricalState; s++){
+						if (cData.hasStateName(ic, s)){
+							message += "\n" + s + ": " + cData.getStateName(ic, s);
+						}
+					}
+				}
+			}
+			else {
+				charName.setText("");
+				statesNames.setCharacter(-1);
+			}
+			message += "\n*Under Construction*";
+		}
+	}
+	void enterName(int state, String name){
+		if (ic<0 || ic>= data.getNumChars())
+			return;
+		if (state == -1)
+			data.setCharacterName(ic, name);
+		else if (state<= CategoricalState.maxCategoricalState)
+			cData.setStateName(ic, state, name);
+	}
+	void changeFocus(int state, int change){
+		if (state+change >= 0 && state+change<= CategoricalState.maxCategoricalState)
+			statesNames.states[state+change].requestFocusInWindow();
+	}
+	boolean selectionInSingleColumn(){
+		if (table.anyRowNameSelected())
+			return false;
+		if (table.anyRowSelected())
+			return false;
+
+		Dimension fC = table.getFirstTableCellSelected();
+		Dimension LC = table.getLastTableCellSelected();
+		int f = table.firstColumnSelected();
+		int L = table.lastColumnSelected();
+		if ( fC.width<0 && LC.width<0){
+			return (f>-1 && f==L);
+		}
+		else if (f<0 && L<0){
+			return (fC.width>-1 && fC.width == LC.width);
+		}
+		return  (f>-1 && f==L && f== fC.width && fC.width == LC.width);
+	}
+	public void cellEnter(int ic, int it){
+		// if a single column or cells within a single column are selected, then cut out
+		if (selectionInSingleColumn())
+			return;
+		super.cellEnter(ic, it);
+	}
+	public void cellExit(int ic, int it){
+		if (selectionInSingleColumn())
+			return;
+		super.cellExit(ic, it);
+
+	}
+	public void setOpen(boolean open){
+		charName.setVisible(open);
+		statesNames.setVisible(open);
+		super.setOpen(open);
+	}
+	int charNameHeight = 24;
+	void resetLocs(){
+		charName.setBounds(2, MINHEIGHT + 4, getWidth()-4, charNameHeight);
+		pane.setBounds(2, MINHEIGHT + 4+charNameHeight+2, getWidth()-4, getHeight() - (MINHEIGHT + 4+charNameHeight+2));
+		statesNames.setContainingWidth(getWidth());		
+		pane.doLayout();
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+	/*public int getRequestedHeight(int width){
+		if (!open)
+			return MINHEIGHT;
+		return 100 + MINHEIGHT + charNameHeight;
+	}
+
+*/
+}
+/*-----------------------------*/
+class StatesField extends Panel {
+	NameField[] states;
+	SStateNamesPanel panel;
+	CategoricalData data;
+	int ic = -1;
+	int w = 400;
+	public StatesField(SStateNamesPanel panel){
+		this.panel = panel;
+		setLayout(null);
+		states = new NameField[CategoricalState.maxCategoricalState+1];
+
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+			states[state] = new NameField(panel, state);
+			add(states[state]);
+		}
+		resetBounds();
+	}
+	void setEditEnabled(boolean en){
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+			states[state].setEditEnabled(en);
+		}
+	}
+	void setData(CategoricalData data){
+		this.data = data;
+	}
+	public void setVisible(boolean vis){
+		super.setVisible(vis);
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++)
+			states[state].setVisible(vis);
+	}
+	void setContainingWidth(int w){
+		this.w = w-30;
+		resetSizes();
+	}
+	public Dimension getPreferredSize(){
+		
+		return new Dimension(w, getDesiredHeight());
+	}
+	int charNameHeight = 24;
+	void resetBounds(){
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+			states[state].setBounds(20, charNameHeight*state, w-4, charNameHeight);
+		}
+	}
+	void resetSizes(){
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+			states[state].setSize(w-4, charNameHeight);
+		}
+	}
+	int getDesiredHeight(){
+		return charNameHeight*(CategoricalState.maxCategoricalState+1);
+	}
+	public void paint(Graphics g){
+		super.paint(g);
+		if (!isVisible())
+			return;
+		for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+			g.drawString(data.getStateSymbol(ic, state), 2, charNameHeight*(state+1)-6);
+		}
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		this.w = w-30;
+		resetSizes();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		this.w = w-30;
+		resetSizes();
+	}
+	public void setCharacter(int ic){
+		this.ic = ic;
+		if (ic<0 || ic > data.getNumChars()){
+			String s = "";
+			for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+				if (!states[state].getText().equals(s))
+					states[state].setText(s);
+			}
+		}
+		else
+			for (int state = 0; state<=CategoricalState.maxCategoricalState; state++){
+				String s = "";
+				if (data.hasStateName(ic, state))
+					s = data.getStateName(ic, state);
+				if (!states[state].getText().equals(s))
+					states[state].setText(s);
+			}
+	}
+}
+class NameField extends TextField implements FocusListener {
+	SStateNamesPanel panel;
+	int state = -1;
+	boolean somethingTyped;
+
+	public NameField(SStateNamesPanel panel, int state){
+		this.panel = panel;
+		this.state = state;
+		setText("");
+		addKeyListener(new KListener());
+		addFocusListener(this);
+	}
+
+	public void setEditEnabled(boolean en){
+		if (en){
+			setBackground(Color.white);
+		setEditable(true);
+	}
+		else {
+			setBackground(ColorDistribution.veryLightGray);
+			setEditable(false);
+		}
+	}
+	public void focusGained(FocusEvent e){
+	}
+	public void focusLost(FocusEvent e){
+		if (somethingTyped)
+			panel.enterName(state, getText());
+	}
+	class KListener extends KeyAdapter {
+		MesquiteWindow window = null;
+		public KListener (){
+			super();
+		}
+		public void keyPressed(KeyEvent e){
+			//Event queue
+			if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+				if (somethingTyped){
+					panel.enterName(state, getText());
+					setSelectionStart(getText().length());
+					setSelectionEnd(getText().length());
+				}
+				panel.changeFocus(state, 1);
+		}
+			else if (e.getKeyCode()== KeyEvent.VK_UP) {
+				if (somethingTyped)
+					panel.enterName(state, getText());
+				panel.changeFocus(state, -1);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_DOWN || e.getKeyCode()== KeyEvent.VK_TAB){
+				if (somethingTyped)
+					panel.enterName(state, getText());
+				panel.changeFocus(state, 1);
+			}
+			else { 
+				somethingTyped=true;
+			}
+
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/categ/StateConsistencyInWindowStrip/StateConsistencyInWindowStrip.java b/Source/mesquite/categ/StateConsistencyInWindowStrip/StateConsistencyInWindowStrip.java
new file mode 100644
index 0000000..501b7f8
--- /dev/null
+++ b/Source/mesquite/categ/StateConsistencyInWindowStrip/StateConsistencyInWindowStrip.java
@@ -0,0 +1,473 @@
+/* Mesquite source code.  Copyright 1997 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.categ.StateConsistencyInWindowStrip;
+
+import java.awt.*;
+import java.util.Enumeration;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+
+public class StateConsistencyInWindowStrip extends DataColumnNamesAssistant {
+	long[] consensusSequence = null;
+	double[] fractionMatchingConsensus = null;
+	CategStateForCharacter stateTask = null;
+	MesquiteString stateTaskName;
+	MesquiteCommand stC;
+	MesquiteSubmenuSpec stSubmenu;
+	MesquiteMenuItemSpec menuItem1, menuItem2, closeMenuItem, lineMenuItem, windowSizesMenuItem, whiteThresholdItem;
+	
+	boolean suspend = false;
+
+	MesquiteBoolean selectedOnly = new MesquiteBoolean(true);
+	MesquiteBoolean useMaximumScore = new MesquiteBoolean(true);
+	int lowerWindowLength = 5;
+	int upperWindowLength = 30;
+	double whiteThreshold = 0.85;
+
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setUseMenubar(false);
+		
+		stateTask = (CategStateForCharacter)hireEmployee(CategStateForCharacter.class, "Calculator of character state for each character");
+		if (stateTask == null)
+			return sorry(getName() + " couldn't start because no calculator of character state obtained");
+		stateTaskName = new MesquiteString(stateTask.getName());
+		stC = makeCommand("setStateCalculator",  this);
+		stateTask.setHiringCommand(stC);
+		if (numModulesAvailable(CategStateForCharacter.class)>1) {
+			MesquiteSubmenuSpec stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+			stSubmenu.setSelected(stateTaskName);
+		}
+		
+		return true;
+  	 }
+	
+	public boolean loadModule(){
+		return false; // not ready
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CategStateForCharacter.class, getName() + " needs a module to provide a character state (e.g., the consensus state) for each character.",
+		"The character state provider is chosen initially or using the State Calculator submenu");
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == stateTask)  
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void getSubfunctions(){
+		String  explanationString = "(An Info Strip of a Categorical Matrix Window) Displays a consensus sequence for categorical data, as indicated by the two arrows in the figure below. <br> <img src=\"" + MesquiteFile.massageFilePathToURL(getPath() + "consensus.gif");
+		explanationString += "\"><br>To create a consensus sequence, choose Matrix>Add Char Info Strip>Consensus Sequence.  To adjust options, use the drop-down menu that appears when you touch on the consensus sequence.<br>";
+		registerSubfunction(new FunctionExplanation("Consensus Sequence", explanationString, null, null));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public void deleteMenuItems() {
+		deleteMenuItem(stSubmenu);
+		deleteMenuItem(menuItem1);
+		deleteMenuItem(menuItem2);
+		deleteMenuItem(windowSizesMenuItem);
+		deleteMenuItem(whiteThresholdItem);
+	}
+	public void deleteRemoveMenuItem() {
+		deleteMenuItem(lineMenuItem);
+		deleteMenuItem(closeMenuItem);
+	}
+	public void addRemoveMenuItem() {
+		closeMenuItem= addMenuItem(null,"Remove State Consistency Strip", makeCommand("remove", this));
+		lineMenuItem = addMenuLine();
+	}
+		
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		deleteMenuItems();
+		deleteRemoveMenuItem();
+		addRemoveMenuItem();
+		stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+		stSubmenu.setSelected(stateTaskName);
+		menuItem1= addCheckMenuItem(null,"Selected Taxa Only", makeCommand("toggleSelectedOnly", this), selectedOnly);
+		menuItem2= addCheckMenuItem(null,"Use Maximum Score", makeCommand("toggleUseMaximumScore", this), useMaximumScore);
+		windowSizesMenuItem= addMenuItem(null,"Window Sizes...", makeCommand("windowSizes", this));
+		whiteThresholdItem= addMenuItem(null,"White Threshold...", makeCommand("whiteThreshold", this));
+
+		
+		if (data != null)
+			data.removeListener(this);
+		this.data = data;
+		this.table = table;
+		data.addListener(this);
+		
+		calculateSequence();
+	}
+	/*.................................................................................................................*/
+	public void dispose() {
+		super.dispose();
+		if (data!=null)
+			data.removeListener(this);
+	}
+	/*.................................................................................................................*/
+	 public String getShortParameters() {
+		 String s = "(";
+		 if (stateTask!=null)
+			 s+= stateTask.getShortParameters();
+		 s += ")";
+		 return s;
+	 }
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("suspend");
+		temp.addLine("setStateCalculator " , stateTask);
+		temp.addLine("toggleSelectedOnly " + selectedOnly.toOffOnString());
+		temp.addLine("toggleUseMaximumScore " + useMaximumScore.toOffOnString());
+		temp.addLine("windowSizes " + MesquiteInteger.toString(lowerWindowLength) + " " + MesquiteInteger.toString(upperWindowLength));
+		temp.addLine("whiteThreshold " + MesquiteDouble.toString(whiteThreshold));
+
+		temp.addLine("resume");
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not only selected taxa are included are all taxa.", "[on or off]", commandName, "toggleSelectedOnly")) {
+			boolean current = selectedOnly.getValue();
+			selectedOnly.toggleValue(parser.getFirstToken(arguments));
+			if (stateTask!=null)
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+			if (current!=selectedOnly.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				if (table !=null) {
+						table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the maximum window score is used for a cell (as opposed to the average score).", "[on or off]", commandName, "toggleUseMaximumScore")) {
+			boolean current = useMaximumScore.getValue();
+			useMaximumScore.toggleValue(parser.getFirstToken(arguments));
+			if (current!=useMaximumScore.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				if (table !=null) {
+						table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the minimum and maximum sizes of the window.", "[minimum][maximum]", commandName, "windowSizes")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			pos.setValue(0);
+			int minimum = MesquiteInteger.fromString(arguments, pos);
+			int maximum = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(maximum)  || MesquiteInteger.isCombinable(minimum)) {
+				if (minimum>=1 && maximum<1000 && minimum<=maximum && maximum>=minimum ) {
+					lowerWindowLength = minimum;
+					upperWindowLength = maximum;
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+			else { 
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger newMinimum = new MesquiteInteger(lowerWindowLength);
+				MesquiteInteger newMaximum =new MesquiteInteger(upperWindowLength);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Minimum and Maximum Window lengths", "Minimum",  "Maximum", answer,  newMinimum, newMaximum,1,MesquiteInteger.unassigned,1, MesquiteInteger.unassigned,MesquiteString.helpString);
+				if (answer.getValue() && (newMinimum.isCombinable()&&newMinimum.getValue()>=1 && newMinimum.getValue()<=newMaximum.getValue() && (newMaximum.isCombinable() && newMaximum.getValue()>1))) {
+					lowerWindowLength = newMinimum.getValue();
+					upperWindowLength = newMaximum.getValue();
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the consistency score below which cells are colored white.", "[value]", commandName, "whiteThreshold")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			pos.setValue(0);
+			double value = MesquiteDouble.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(value)) {
+				if (value>=0.0 && value<1.0 ) {
+					whiteThreshold = value;
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+			else { 
+				double newValue = MesquiteDouble.queryDouble(containerOfModule(), "White Threshold", "White Threshold", whiteThreshold ,0.0, MesquiteDouble.infinite);
+				if (MesquiteDouble.isCombinable(newValue) && newValue>=0.0 && newValue<1.0 && newValue!=whiteThreshold) {
+					whiteThreshold = newValue;
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the Info Strip", null, commandName, "remove")) {
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			calculateSequence();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the calculator of a state for each character", "[name of state calculator module]", commandName, "setStateCalculator")) {
+			CategStateForCharacter temp = (CategStateForCharacter)replaceEmployee(CategStateForCharacter.class, arguments, "Calculator of character state for each character", stateTask);
+			if (temp !=null){
+				stateTask = temp;
+				stateTask.setHiringCommand(stC);
+				stateTaskName.setValue(stateTask.getName());
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+				if (!suspend) {
+					parametersChanged();
+					calculateSequence();
+					if (table !=null){
+						table.repaintAll();
+					}
+				}
+				return stateTask;
+			}
+			addRemoveMenuItem();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		calculateSequence();
+			if (table !=null)
+				table.repaintAll();
+  	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (table!=null) {
+			((ColumnNamesPanel)table.getColumnNamesPanel()).decrementInfoStrips();
+			table.resetTableSize(false);
+		}
+		super.endJob();
+	}
+
+ 
+	/*.................................................................................................................*/
+	 public boolean atLeastOneInapplicable(int ic){
+		 if (data==null || table==null)
+			 return false;
+		 //long s;
+		 int numTaxa = data.getNumTaxa();
+		 int numTaxaWithData = 0;
+		boolean noRowsSelected =  !table.anyRowSelected();
+		 for (int it=0; it<numTaxa; it++) {
+			 if (!selectedOnly.getValue() || table.isRowSelected(it) || noRowsSelected) {
+				 long s= ((CategoricalData)data).getState(ic,it);
+				 if (CategoricalState.isInapplicable(s))
+					 return true;
+			 }
+		 }
+		 return false;
+	 }
+
+		/*.................................................................................................................*/
+	 public void calculateSequence() {
+		 if (data == null)
+			 return;
+		 CategoricalState resultState = new CategoricalState();
+		 MesquiteString resultString = new MesquiteString();
+		 long[] sequence = new long[data.getNumChars()];
+		 double[] fractionMatch = new double[data.getNumChars()];
+		 MesquiteDouble fractionMatching = new MesquiteDouble();
+		 for (int i = 0; i<data.getNumChars(); i++) {
+			 stateTask.calculateState( (CategoricalData)data,  i,  table,  resultState,  resultString, fractionMatching);
+			 fractionMatch[i] = fractionMatching.getValue();
+			 sequence[i] = resultState.getValue();
+		 }
+		consensusSequence = sequence;
+		fractionMatchingConsensus = fractionMatch;
+	 }
+		/*.................................................................................................................*/
+	 public double scoreForPrimer ( int icStart, int icEnd) {
+		 double total = 0.0;
+		 for (int ic=icStart; ic<=icEnd; ic++) {
+			 if (fractionMatchingConsensus!=null) {
+				double card = CategoricalState.cardinality(consensusSequence[ic]);
+				if (card >=2) 
+					total +=  fractionMatchingConsensus[ic]/(card*1.0);
+				else 
+					total += fractionMatchingConsensus[ic];
+			 }
+		 }
+		total = total/(icEnd-icStart+1);
+		return total;
+	 }
+		/*.................................................................................................................*/
+	 public double scoreForCell (int ic, int numChars) {
+		 double maxScore = 0.0;
+		 double score = 0.0;
+		 double currentScore;
+		 int length;
+		 int primers = 0;
+		 for (length=lowerWindowLength; length<upperWindowLength; length++) {
+			 for (int j = 1; j<=length; j++) { 
+				 int start = ic-length+j;
+				 if (start<0) continue;
+				 int end = start+length-1;
+				 if (end>=numChars) continue;
+				 primers++;
+
+				 currentScore = scoreForPrimer(start, end);
+				 if (maxScore<currentScore) 
+					 maxScore = currentScore;
+				 score += currentScore;
+			 }
+		 }
+		if (useMaximumScore.getValue())
+			return maxScore;
+		if (primers>0)
+			return score/primers;
+		return 0.0;
+	 }
+
+		/*.................................................................................................................*/
+	 public void drawInCell(int ic, Graphics g, int x, int y, int w, int h, boolean selected) {
+		 if (stateTask==null || data == null) 
+			 return;
+		 long s= CategoricalState.inapplicable;
+		 if (consensusSequence==null)
+			 calculateSequence();
+		 if (ic>=0 && ic<consensusSequence.length)
+			 s =consensusSequence[ic];
+
+//		 boolean colorSomeInapp = atLeastOneInapplicable(ic) && showSomeInapplicableAsGray.getValue();
+		 if (!CategoricalState.isEmpty(s) && !CategoricalState.isInapplicable(s)){
+			 boolean grayText = false;
+			 int e =  CategoricalState.getOnlyElement(s);
+			 double score = scoreForCell(ic, data.getNumChars());
+			 Color cellColor = MesquiteColorTable.getGrayScale(score,whiteThreshold,1.0);
+			 g.setColor(cellColor);
+			 g.fillRect(x,y,w,h);
+
+			 if (grayText) {
+					 g.setColor(Color.lightGray);
+			 }
+			 else {
+					/* float[] hsb = new float[3];
+					hsb[0]=hsb[1]=hsb[2]= 1;
+					Color.RGBtoHSB(cellColor.getRed(), cellColor.getGreen(), cellColor.getBlue(), hsb);
+					Color textColor = ColorDistribution.getContrasting(selected, cellColor, hsb, Color.white, Color.black);
+					 */
+					g.setColor(Color.black);
+			 }
+			 StringBuffer sb = new StringBuffer();
+			 ((CategoricalData)data).statesIntoStringBufferCore(ic,  s,  sb, true,false, false);
+			 FontMetrics fm = g.getFontMetrics(g.getFont());
+			 int svp = StringUtil.getStringVertPosition(fm, y, h, null);
+
+			 String cellString = sb.toString();
+			 int length = fm.stringWidth(cellString);
+			 int useX = x + (w - length) / 2;
+			 g.drawString(cellString, useX, svp);
+
+		 }
+		 else if (CategoricalState.isInapplicable(s)){
+			 g.setColor(Color.lightGray);
+			 g.fillRect(x,y,w,h);
+		}
+		else {
+			g.setColor(Color.white);
+			g.fillRect(x,y,w,h);
+		}
+	}
+
+	 /*.................................................................................................................*/
+	 /** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	 public void changed(Object caller, Object obj, Notification notification){
+		 int code = Notification.getCode(notification);
+		 if (obj instanceof Taxa &&  (Taxa)obj ==data.getTaxa()) {
+			 if (code==MesquiteListener.SELECTION_CHANGED && selectedOnly.getValue()) {
+				 calculateSequence();
+			 }
+			 else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED) {
+				 calculateSequence();
+			 }
+		 }
+		 else if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			 if (code==MesquiteListener.PARTS_DELETED || code==AssociableWithSpecs.SPECSSET_CHANGED || code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.DATA_CHANGED) {
+				 calculateSequence();
+			 }
+			 else{
+				 calculateSequence();
+			 }
+		 }
+		 super.changed(caller, obj, notification);
+	 }
+	 /*.................................................................................................................*/
+	 /** returns whether this module is requesting to appear as a primary choice */
+	 public boolean requestPrimaryChoice(){
+		 return true;  
+	 }
+	 /*.................................................................................................................*/
+	 public boolean isPrerelease(){
+		 return true;  
+	 }
+	public String getTitle() {
+		return "State Consistency Moving Window Strip";
+	}
+
+
+	public String getName() {
+		return "State Consistency Moving Window Strip";
+	}	
+	
+	
+	public String getExplanation() {
+		return "Displays overall consistency of states in a moving window as an info strip in a character matrix editor.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return NEXTRELEASE;  //NOT YET RELEASED!!!
+	}
+
+}
diff --git a/Source/mesquite/categ/StateConsistencyStrip/StateConsistencyStrip.java b/Source/mesquite/categ/StateConsistencyStrip/StateConsistencyStrip.java
new file mode 100644
index 0000000..32db31e
--- /dev/null
+++ b/Source/mesquite/categ/StateConsistencyStrip/StateConsistencyStrip.java
@@ -0,0 +1,391 @@
+/* Mesquite source code.  Copyright 1997 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.categ.StateConsistencyStrip;
+
+import java.awt.*;
+import java.util.Enumeration;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+
+public class StateConsistencyStrip extends DataColumnNamesAssistant {
+	long[] consensusSequence = null;
+	double[] fractionMatchingConsensus = null;
+	CategStateForCharacter stateTask = null;
+	MesquiteString stateTaskName;
+	MesquiteCommand stC;
+	MesquiteSubmenuSpec stSubmenu;
+	MesquiteMenuItemSpec menuItem1, menuItem2, closeMenuItem, lineMenuItem, windowSizesMenuItem, whiteThresholdItem;
+	
+	boolean suspend = false;
+
+	MesquiteBoolean selectedOnly = new MesquiteBoolean(true);
+	double whiteThreshold = 0.99;
+
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setUseMenubar(false);
+		
+		stateTask = (CategStateForCharacter)hireEmployee(CategStateForCharacter.class, "Calculator of character state for each character");
+		if (stateTask == null)
+			return sorry(getName() + " couldn't start because no calculator of character state obtained");
+		stateTaskName = new MesquiteString(stateTask.getName());
+		stC = makeCommand("setStateCalculator",  this);
+		stateTask.setHiringCommand(stC);
+		if (numModulesAvailable(CategStateForCharacter.class)>1) {
+			MesquiteSubmenuSpec stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+			stSubmenu.setSelected(stateTaskName);
+		}
+		
+		return true;
+  	 }
+	public boolean loadModule(){
+		return false; // not ready
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CategStateForCharacter.class, getName() + " needs a module to provide a character state (e.g., the consensus state) for each character.",
+		"The character state provider is chosen initially or using the State Calculator submenu");
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == stateTask)  
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void getSubfunctions(){
+		String  explanationString = "(An Info Strip of a Categorical Matrix Window) Displays a consensus sequence for categorical data, as indicated by the two arrows in the figure below. <br> <img src=\"" + MesquiteFile.massageFilePathToURL(getPath() + "consensus.gif");
+		explanationString += "\"><br>To create a consensus sequence, choose Matrix>Add Char Info Strip>Consensus Sequence.  To adjust options, use the drop-down menu that appears when you touch on the consensus sequence.<br>";
+		registerSubfunction(new FunctionExplanation("Consensus Sequence", explanationString, null, null));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public void deleteMenuItems() {
+		deleteMenuItem(stSubmenu);
+		deleteMenuItem(menuItem1);
+		deleteMenuItem(menuItem2);
+		deleteMenuItem(windowSizesMenuItem);
+		deleteMenuItem(whiteThresholdItem);
+	}
+	public void deleteRemoveMenuItem() {
+		deleteMenuItem(lineMenuItem);
+		deleteMenuItem(closeMenuItem);
+	}
+	public void addRemoveMenuItem() {
+		closeMenuItem= addMenuItem(null,"Remove State Consistency Strip", makeCommand("remove", this));
+		lineMenuItem = addMenuLine();
+	}
+		
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		deleteMenuItems();
+		deleteRemoveMenuItem();
+		addRemoveMenuItem();
+		stSubmenu = addSubmenu(null, "State Calculator", stC, CategStateForCharacter.class);
+		stSubmenu.setSelected(stateTaskName);
+		menuItem1= addCheckMenuItem(null,"Selected Taxa Only", makeCommand("toggleSelectedOnly", this), selectedOnly);
+		whiteThresholdItem= addMenuItem(null,"White Threshold...", makeCommand("whiteThreshold", this));
+
+		
+		if (data != null)
+			data.removeListener(this);
+		this.data = data;
+		this.table = table;
+		data.addListener(this);
+		
+		calculateSequence();
+	}
+	/*.................................................................................................................*/
+	public void dispose() {
+		super.dispose();
+		if (data!=null)
+			data.removeListener(this);
+	}
+	/*.................................................................................................................*/
+	 public String getShortParameters() {
+		 String s = "(";
+		 if (stateTask!=null)
+			 s+= stateTask.getShortParameters();
+		 s += ")";
+		 return s;
+	 }
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("suspend");
+		temp.addLine("setStateCalculator " , stateTask);
+		temp.addLine("toggleSelectedOnly " + selectedOnly.toOffOnString());
+		temp.addLine("whiteThreshold " + MesquiteDouble.toString(whiteThreshold));
+
+		temp.addLine("resume");
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not only selected taxa are included are all taxa.", "[on or off]", commandName, "toggleSelectedOnly")) {
+			boolean current = selectedOnly.getValue();
+			selectedOnly.toggleValue(parser.getFirstToken(arguments));
+			if (stateTask!=null)
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+			if (current!=selectedOnly.getValue() && !suspend) {
+				parametersChanged();
+				calculateSequence();
+				if (table !=null) {
+						table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the consistency score below which cells are colored white.", "[value]", commandName, "whiteThreshold")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			pos.setValue(0);
+			double value = MesquiteDouble.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(value)) {
+				if (value>=0.0 && value<1.0 ) {
+					whiteThreshold = value;
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+			else { 
+				double newValue = MesquiteDouble.queryDouble(containerOfModule(), "White Threshold", "White Threshold", whiteThreshold ,0.0, MesquiteDouble.infinite);
+				if (MesquiteDouble.isCombinable(newValue) && newValue>=0.0 && newValue<1.0 && newValue!=whiteThreshold) {
+					whiteThreshold = newValue;
+					parametersChanged();
+					calculateSequence();
+					if (table !=null) {
+							table.repaintAll();
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the Info Strip", null, commandName, "remove")) {
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			calculateSequence();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the calculator of a state for each character", "[name of state calculator module]", commandName, "setStateCalculator")) {
+			CategStateForCharacter temp = (CategStateForCharacter)replaceEmployee(CategStateForCharacter.class, arguments, "Calculator of character state for each character", stateTask);
+			if (temp !=null){
+				stateTask = temp;
+				stateTask.setHiringCommand(stC);
+				stateTaskName.setValue(stateTask.getName());
+				stateTask.setSelectedOnly(selectedOnly.getValue());
+				if (!suspend) {
+					parametersChanged();
+					calculateSequence();
+					if (table !=null){
+						table.repaintAll();
+					}
+				}
+				return stateTask;
+			}
+			addRemoveMenuItem();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		calculateSequence();
+			if (table !=null)
+				table.repaintAll();
+  	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (table!=null) {
+			((ColumnNamesPanel)table.getColumnNamesPanel()).decrementInfoStrips();
+			table.resetTableSize(false);
+		}
+		super.endJob();
+	}
+
+ 
+	/*.................................................................................................................*/
+	 public boolean atLeastOneInapplicable(int ic){
+		 if (data==null || table==null)
+			 return false;
+		 //long s;
+		 int numTaxa = data.getNumTaxa();
+		 int numTaxaWithData = 0;
+		boolean noRowsSelected =  !table.anyRowSelected();
+		 for (int it=0; it<numTaxa; it++) {
+			 if (!selectedOnly.getValue() || table.isRowSelected(it) || noRowsSelected) {
+				 long s= ((CategoricalData)data).getState(ic,it);
+				 if (CategoricalState.isInapplicable(s))
+					 return true;
+			 }
+		 }
+		 return false;
+	 }
+
+		/*.................................................................................................................*/
+	 public void calculateSequence() {
+		 if (data == null)
+			 return;
+		 CategoricalState resultState = new CategoricalState();
+		 MesquiteString resultString = new MesquiteString();
+		 long[] sequence = new long[data.getNumChars()];
+		 double[] fractionMatch = new double[data.getNumChars()];
+		 MesquiteDouble fractionMatching = new MesquiteDouble();
+		 for (int i = 0; i<data.getNumChars(); i++) {
+			 stateTask.calculateState( (CategoricalData)data,  i,  table,  resultState,  resultString, fractionMatching);
+			 fractionMatch[i] = fractionMatching.getValue();
+			 sequence[i] = resultState.getValue();
+		 }
+		consensusSequence = sequence;
+		fractionMatchingConsensus = fractionMatch;
+	 }
+		/*.................................................................................................................*/
+	 public double scoreForCell (int ic, int numChars) {
+		 if (fractionMatchingConsensus!=null) {
+				double card = CategoricalState.cardinality(consensusSequence[ic]);
+				if (card >=2) 
+					return fractionMatchingConsensus[ic]/(card*1.0);
+				else 
+					return fractionMatchingConsensus[ic];
+			 }
+		return 0.0;
+	 }
+
+		/*.................................................................................................................*/
+	 public void drawInCell(int ic, Graphics g, int x, int y, int w, int h, boolean selected) {
+		 if (stateTask==null || data == null) 
+			 return;
+		 long s= CategoricalState.inapplicable;
+		 if (consensusSequence==null)
+			 calculateSequence();
+		 if (ic>=0 && ic<consensusSequence.length)
+			 s =consensusSequence[ic];
+
+//		 boolean colorSomeInapp = atLeastOneInapplicable(ic) && showSomeInapplicableAsGray.getValue();
+		 if (!CategoricalState.isEmpty(s) && !CategoricalState.isInapplicable(s)){
+			 boolean grayText = false;
+			 int e =  CategoricalState.getOnlyElement(s);
+			 double score = scoreForCell(ic, data.getNumChars());
+			 Color cellColor = MesquiteColorTable.getGrayScale(score,whiteThreshold,1.0);
+			 g.setColor(cellColor);
+			 g.fillRect(x,y,w,h);
+
+			 if (grayText) {
+					 g.setColor(Color.lightGray);
+			 }
+			 else {
+					/* float[] hsb = new float[3];
+					hsb[0]=hsb[1]=hsb[2]= 1;
+					Color.RGBtoHSB(cellColor.getRed(), cellColor.getGreen(), cellColor.getBlue(), hsb);
+					Color textColor = ColorDistribution.getContrasting(selected, cellColor, hsb, Color.white, Color.black);
+					 */
+					g.setColor(Color.black);
+			 }
+			 StringBuffer sb = new StringBuffer();
+			 ((CategoricalData)data).statesIntoStringBufferCore(ic,  s,  sb, true,false, false);
+			 FontMetrics fm = g.getFontMetrics(g.getFont());
+			 int svp = StringUtil.getStringVertPosition(fm, y, h, null);
+
+			 String cellString = sb.toString();
+			 int length = fm.stringWidth(cellString);
+			 int useX = x + (w - length) / 2;
+			 g.drawString(cellString, useX, svp);
+
+		 }
+		 else if (CategoricalState.isInapplicable(s)){
+			 g.setColor(Color.lightGray);
+			 g.fillRect(x,y,w,h);
+		}
+		else {
+			g.setColor(Color.white);
+			g.fillRect(x,y,w,h);
+		}
+	}
+
+	 /*.................................................................................................................*/
+	 /** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	 public void changed(Object caller, Object obj, Notification notification){
+		 int code = Notification.getCode(notification);
+		 if (obj instanceof Taxa &&  (Taxa)obj ==data.getTaxa()) {
+			 if (code==MesquiteListener.SELECTION_CHANGED && selectedOnly.getValue()) {
+				 calculateSequence();
+			 }
+			 else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED) {
+				 calculateSequence();
+			 }
+		 }
+		 else if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			 if (code==MesquiteListener.PARTS_DELETED || code==AssociableWithSpecs.SPECSSET_CHANGED || code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.DATA_CHANGED) {
+				 calculateSequence();
+			 }
+			 else{
+				 calculateSequence();
+			 }
+		 }
+		 super.changed(caller, obj, notification);
+	 }
+	 /*.................................................................................................................*/
+	 /** returns whether this module is requesting to appear as a primary choice */
+	 public boolean requestPrimaryChoice(){
+		 return true;  
+	 }
+	 /*.................................................................................................................*/
+	 public boolean isPrerelease(){
+		 return true;  
+	 }
+	public String getTitle() {
+		return "State Consistency Strip";
+	}
+
+
+	public String getName() {
+		return "State Consistency Strip";
+	}	
+	
+	
+	public String getExplanation() {
+		return "Displays overall consistency of states in each character as an info strip in a character matrix editor.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return NEXTRELEASE;   //NOT YET RELEASED!!!
+	}
+
+}
diff --git a/Source/mesquite/categ/StateFrequency/StateFrequency.java b/Source/mesquite/categ/StateFrequency/StateFrequency.java
new file mode 100644
index 0000000..aef10f8
--- /dev/null
+++ b/Source/mesquite/categ/StateFrequency/StateFrequency.java
@@ -0,0 +1,173 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+This module originally by P. Midford, based on MeanValue.
+ */
+package mesquite.categ.StateFrequency;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.duties.NumberForCharacter;
+import mesquite.lib.duties.NumberForCharacterIncr;
+
+public class StateFrequency extends NumberForCharacter {
+    boolean warnedOnce = false;
+    CategoricalDistribution cStates;
+
+    //choice of what state to check
+    int selectedState=0;
+    long selectedStates;
+    MesquiteMenuItemSpec stateItem;
+    MesquiteCommand stateChoiceCommand;
+
+    public StateFrequency() {
+    }
+
+    public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+        if (condition !=null && condition!= CategoricalData.class && condition!=CategoricalState.class) {
+            return sorry("State Frequency of Character could not start because it can be used only for categorical characters");
+        }
+        if (!(NumberForCharacterIncr.class.isAssignableFrom(getHiredAs()))){ //not hired as obedient
+            stateChoiceCommand = MesquiteModule.makeCommand("setState",  this);
+            stateItem = addMenuItem("State for State Frequency...", stateChoiceCommand);
+        }
+        return true;
+    }
+    /*.................................................................................................................*/
+    public boolean isPrerelease(){
+        return false;
+    }
+    /*.................................................................................................................*/
+    public boolean showCitation(){
+        return false;
+    }
+     
+    public void setCurrent(long i){ //SHOULD NOT notify (e.g., parametersChanged)
+        selectedState = (int)i;
+    }
+    public long getCurrent(){
+        return selectedState;
+    }
+    public String getItemTypeName(){
+        return "Item";
+    }
+    
+    public long getMin(){
+        return 0;
+    }
+    public long getMax(){
+       long max=0;
+    /*  if (cStates !=null)
+           	max = cStates.getMaxState();
+       if (max<0) max=0;
+       */
+       CategoricalData data = (CategoricalData)cStates.getParentData();
+      return data.getMaxPossibleState();
+    }
+    /*.................................................................................................................*/
+     public Snapshot getSnapshot(MesquiteFile file) {
+        Snapshot temp = new Snapshot();
+        temp.addLine("setItem " + (selectedState));
+        return temp;
+     }
+    /*.................................................................................................................*/
+     public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+         if (checker.compare(this.getClass(), "Sets the state whose frequency should be calculated.", "[state number]", commandName, "setState")) {
+             int ic = MesquiteInteger.fromString(arguments);
+             if (!MesquiteInteger.isCombinable(ic) && cStates!=null){
+                 ic = MesquiteInteger.queryInteger(null, "Select State", "State whose frequency will be calculated", "", selectedState, (int)getMin(), (int)getMax(), false);
+             }
+             if (!MesquiteInteger.isCombinable(ic))
+                 return null;
+             if (cStates==null) {
+                 selectedState = ic;
+             }
+             else if (cStates !=null && cStates instanceof CategoricalDistribution) {
+                 if ((ic>=0) && (ic<=getMax())) {
+                     selectedState = ic;
+                     parametersChanged();
+                 }
+             }
+         }
+         else
+             return  super.doCommand(commandName, arguments, checker);
+         return null;
+     }
+ 
+     
+     /*.................................................................................................................*/
+     public CompatibilityTest getCompatibilityTest() {
+       return new RequiresAnyCategoricalData();
+   }
+ 
+
+     public void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+         if (result==null)
+             return;
+         clearResultAndLastResult(result);
+         String itemName = Integer.toString(selectedState+1);
+         if (charStates!=null)
+             if  (!(charStates instanceof CategoricalDistribution)){
+                 if (!warnedOnce)
+                     discreetAlert( "Frequency of character state can be calculated only for Categorical characters");
+                 warnedOnce = true;
+                 if (resultString!=null)
+                     resultString.setValue("No frequency of character state; can be calculated only for Categorical characters");
+             }
+             else {
+                 warnedOnce = false;
+                 cStates = (CategoricalDistribution)charStates;
+                 int numtaxa = cStates.getNumNodes();
+                 int count= 0;
+                 int n=0;
+                 for (int i=0; i<numtaxa; i++){
+                     long s = cStates.getState(i);
+                     if (CategoricalState.isCombinable(s)) {
+                         if (CategoricalState.isElement(s, selectedState))
+                             count++;
+                         n++;
+                     }
+                 }
+                 if (n != 0)
+                     result.setValue((1.0*count)/n);
+                 if (resultString!=null)
+                     resultString.setValue("State Frequency: "+ result.toString() + " for State: " + itemName);
+             }
+         saveLastResult(result);
+         saveLastResultString(resultString);
+     }
+ 	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+ 	public int getVersionOfFirstRelease(){
+ 		return 200;  
+ 	}
+
+    public void initialize(CharacterDistribution charStates) {
+    }
+
+    public String getName() {
+        return "Frequency of State";
+    }
+    public String getParameters(){
+    	return "Frequency of State " + selectedState;
+    }
+
+    public String getExplanation() {
+        return "Calculates the frequency of a state for a categorical character";
+    }
+    
+
+}
diff --git a/Source/mesquite/categ/StateNamesEditor/StateNamesEditor.java b/Source/mesquite/categ/StateNamesEditor/StateNamesEditor.java
new file mode 100644
index 0000000..80682dc
--- /dev/null
+++ b/Source/mesquite/categ/StateNamesEditor/StateNamesEditor.java
@@ -0,0 +1,1281 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.StateNamesEditor;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class StateNamesEditor extends CategDataEditorInit {
+	CategoricalData data;
+	StateNamesWindow window;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getEmployer().addMenuItem("Edit State Names", makeCommand("makeWindow", this));
+		return true;
+	}
+	/** Called to alter data in all cells*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (!(data instanceof CategoricalData))
+			return;
+		//TODO: query here if state names editing allowed
+		this.data = (CategoricalData)data;
+
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void endJob(){
+		if (window != null){
+			window.hide();
+			window.dispose();
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("makeWindow"); 
+		temp.addLine("tell It"); 
+		Snapshot sn = getModuleWindow().getSnapshot(file);
+		temp.incorporate(sn, true);
+		temp.addLine("endTell"); 
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Makes the state names editor window (but doesn't display it)", null, commandName, "makeWindow")) {
+			if (data!=null ){
+				if (getModuleWindow()==null) {
+					setModuleWindow(window = new StateNamesWindow(this, data));
+					resetContainingMenuBar();
+					resetAllWindowsMenus();
+				}
+				if (!MesquiteThread.isScripting())
+					getModuleWindow().setVisible(true);
+				return getModuleWindow();
+				//set up a listener
+			}
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void panelGoAway(Panel p){
+		StateNamesWindow window = (StateNamesWindow)getModuleWindow();
+		if (window == null)
+			return;
+		if (p == window.summaryPanel){
+			window.showSummaryPanel.setValue(false);
+			window.setSummaryPanel();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Edit State Names";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Edits state names of a categorical data matrix." ;
+	}
+
+}
+
+/* ======================================================================== */
+class StateNamesWindow extends TableWindow implements MesquiteListener, AnnotPanelOwner {
+	protected StateNamesTable table;
+	private int windowWidth=360;
+	private int windowHeight=400;
+	StateNamesEditor owner;
+	ToolPalette palette = null;
+	TableTool arrowTool, ibeamTool, fillTool, dropperTool;
+	CategoricalData data;
+	String fillString;
+	boolean neverFilled = true;
+	MesquiteBoolean rowsAreCharacters;
+	MesquiteMenuItemSpec constrainMenuItem, transposeMenuItem;
+	MesquiteMenuSpec menu;
+	MesquiteBoolean constrainedCW= new MesquiteBoolean(true);
+	int constrainedColumnNum = 3;
+	MesquiteBoolean showPanel = new MesquiteBoolean(false);
+	AnnotationsPanel panel = null;
+	MesquiteBoolean showSummaryPanel = new MesquiteBoolean(false);
+	HTMLSidePanel summaryPanel = null;
+	int currentCharacter, currentState, currentNoteNumber;
+	MesquiteSubmenuSpec annotMenu;
+
+	public StateNamesWindow (StateNamesEditor ownerModule, CategoricalData data) {
+		super(ownerModule, true); //INFOBAR
+		setWindowSize(windowWidth, windowHeight);
+		ownerModule.setModuleWindow(this);
+		owner = ownerModule;
+		this.data = data;
+		rowsAreCharacters = new MesquiteBoolean(true);
+		table = new StateNamesTable (data, windowWidth, windowHeight, 130, this, rowsAreCharacters.getValue());
+		setShowAnnotation(true);
+		data.addListener(this);
+		//ownerModule.addCheckMenuItem(null, "Characters On Rows", MesquiteModule.makeCommand("rowsAreCharacters",  this), rowsAreCharacters);
+		//ownerModule.resetContainingMenuBar();
+		String selectExplanation = "This tool selects items in the matrix.  By holding down shift while clicking, the selection will be extended from the first to the last touched cell. ";
+		selectExplanation += " A block of cells can be selected either by using shift-click to extend a previous selection, or by clicking on a cell and dragging with the mouse button still down";
+		selectExplanation += " Discontinous selections are allowed, and can be obtained by a \"meta\"-click (right mouse button click, or command-click on a MacOS system). ";
+		arrowTool = new TableTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(), "arrow.gif", 4,2,"Select", selectExplanation, MesquiteModule.makeCommand("arrowTouchCell",  this) , MesquiteModule.makeCommand("arrowDragCell",  this), MesquiteModule.makeCommand("arrowDropCell",  this));
+		arrowTool.setIsArrowTool(true);
+		arrowTool.setUseTableTouchRules(true);
+		addTool(arrowTool);
+		getPalette().setFirstToolHeight(26);
+		setCurrentTool(arrowTool);
+		arrowTool.setInUse(true);
+		ibeamTool = new TableTool(this, "ibeam", MesquiteModule.getRootImageDirectoryPath(), "ibeam.gif", 7,7,"Edit", "This tool can be used to edit the contents of cells in the matrix.", MesquiteModule.makeCommand("editCell",  (Commandable)table) , null, null);
+		ibeamTool.setWorksOnRowNames(table.rowsAreCharacters); 
+		addTool(ibeamTool);
+
+		fillTool = new TableTool(this, "fill", MesquiteModule.getRootImageDirectoryPath(), "bucket.gif", 13,14,"Fill with unassigned", "This tool fills selected cells with text.  The text to be used can be determined by using the dropper tool.", MesquiteModule.makeCommand("fillTouchCell",  this) , null, null);
+		fillTool.setOptionsCommand(MesquiteModule.makeCommand("fillOptions",  this));
+		addTool(fillTool);
+		dropperTool = new TableTool(this, "dropper", MesquiteModule.getRootImageDirectoryPath(), "dropper.gif", 1,14,"Copy states", "This tool fills the paint bucket with the text in the cell touched on", MesquiteModule.makeCommand("dropperTouchCell",  this) , null, null);
+		addTool(dropperTool);
+		menu = ownerModule.makeMenu("State_Names");
+		constrainMenuItem = ownerModule.addCheckMenuItem(null, "Constrain Column Widths", ownerModule.makeCommand("toggleConstrainChar", this), constrainedCW);
+		ownerModule.addMenuItem(null, "Min. # Columns if Constrained...", ownerModule.makeCommand("toggleConstrainCharNum", this));
+		transposeMenuItem = ownerModule.addCheckMenuItem(null, "Rows Are Characters", ownerModule.makeCommand("rowsAreCharacters", this), rowsAreCharacters);
+		ownerModule.addMenuItem("-", null);
+		MesquiteMenuItemSpec mm = ownerModule.addMenuItem("Find String...", MesquiteModule.makeCommand("findString", this));
+		mm.setShortcut(KeyEvent.VK_3);
+		mm = ownerModule.addMenuItem("Find Again", MesquiteModule.makeCommand("findAgain", this));
+		mm.setShortcut(KeyEvent.VK_8);
+		ownerModule.addCheckMenuItem(null, "Show State Annotations", MesquiteModule.makeCommand("togglePanel", this), showPanel);
+		ownerModule.addCheckMenuItem(null, "Show Annotations Summary", MesquiteModule.makeCommand("toggleSummaryPanel", this), showSummaryPanel);
+
+		MesquiteSubmenuSpec annotMenu = ownerModule.addSubmenu(null, "Annotations");
+		ownerModule.addItemToSubmenu(null, annotMenu, "-", null);
+		MesquiteMenuItemSpec mmi = ownerModule.addItemToSubmenu(null, annotMenu, "Make Item Label", MesquiteModule.makeCommand("makeItemLabel", panel));
+		mmi.setShortcut(KeyEvent.VK_L);
+		ownerModule.addItemToSubmenu(null, annotMenu, "Recover Offscreen Labels", MesquiteModule.makeCommand("recoverLostLabels", panel));
+		table.setColumnWidthsUniform(100);
+		table.setConstrainMaxAutoColumn(constrainedCW.getValue());
+		table.setConstrainMaxAutoRownames(constrainedCW.getValue());
+		//table.setUserAdjust(MesquiteTable.NOADJUST, MesquiteTable.RESIZE);
+		addToWindow(table);
+		MesquiteButton annotButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("togglePanel",  this), null, true, MesquiteModule.getRootImageDirectoryPath() + "annot.gif", 12, 16);
+		annotButton.setShowBackground(false);
+		annotButton.setButtonExplanation("Show/Hide Annotations Panel");
+		table.addControlButton(annotButton);
+		table.setVisible(true);
+		table.setLocation(0,0);
+		MesquiteWindow.addKeyListener(this, table);
+		setWindowSize(windowWidth, windowHeight);
+		resetTitle();
+	}
+	public MesquiteModule getModule(){
+		return ownerModule;
+	}
+	/*.................................................................................................................*/
+	void setPanel(){
+		if (showPanel.getValue()){
+			if (panel == null) {
+				panel = new AnnotationsPanel(this);
+			}
+			addSidePanel(panel, 300);
+			panel.setVisible(true);
+
+		}
+		else {
+			if (panel != null) {
+				panel.setVisible(false);
+				removeSidePanel(panel);
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	void setSummaryPanel(){
+		if (showSummaryPanel.getValue()){
+			if (summaryPanel == null) {
+				summaryPanel = new HTMLSidePanel(ownerModule, "Annotations");
+			}
+			prevIC = -1;
+			prevST = -1;
+			addSidePanel(summaryPanel, 300);
+			summaryPanel.setVisible(true);
+
+		}
+		else {
+			prevIC = -1;
+			prevST = -1;
+			if (summaryPanel != null) {
+				summaryPanel.setVisible(false);
+				removeSidePanel(summaryPanel);
+			}
+		}
+
+	}
+	public void panelGoAway(Panel p){
+
+		showPanel.setValue(false);
+		setPanel();
+	}
+	public void showSummary(int ic, int st){
+		if (showSummaryPanel.getValue() && summaryPanel != null){
+			AttachedNotesVector anv = null;
+			if (st<0)
+				anv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+			else
+				anv = data.getStateAnnotationsVector(ic, st);
+			if (anv != null && anv.getNumNotes() > 0){
+				String notes = "";
+				if (anv != null && anv.getNumNotes()>0){
+					for (int i = 0; i< anv.getNumNotes(); i++) {
+						AttachedNote note = anv.getAttachedNote(i);
+						String c = note.getComment();
+						String cont = "";
+						if (!StringUtil.blank(note.getComment()))
+							cont += note.getComment();
+						if (!StringUtil.blank(note.getReference()))
+							cont += " (Ref: " + note.getReference() + ")";
+						if (!StringUtil.blank(note.getAuthorName()))
+							cont += " <strong>(" + note.getAuthorName() + ")</strong>";
+						if (!StringUtil.blank(cont))
+							notes += "<li>" + cont + "</li>";				
+					}
+				}
+				if (st<0){
+					if (!StringUtil.blank(notes))
+						summaryPanel.setText("<html><h3>Notes for character " + (ic+1) + "</h3><ul>" + notes + "</ul></html>");
+					else
+						summaryPanel.setText("<html><h3>No notes for character " + (ic+1) +  "</h3></html>");
+				}
+				else {
+					if (!StringUtil.blank(notes))
+						summaryPanel.setText("<html><h3>Notes for character " + (ic+1) + " state " + st + "</h3><ul>" + notes + "</ul></html>");
+					else
+						summaryPanel.setText("<html><h3>No notes for character " + (ic+1) + " state " + st + "</h3></html>");
+				}
+			}
+			else if (ic<0 || st <-1)
+				summaryPanel.setText("<html></html>");
+			else if (st<0)
+				summaryPanel.setText("<html><h3>No notes for character " + (ic+1)  + "</h3></html>");
+			else 
+				summaryPanel.setText("<html><h3>No notes for character " + (ic+1) + " state " + st + "</h3></html>");
+		}
+	}
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+	void showNote(AttachedNotesVector aim, int ic, int st, int noteNumber){
+		if (data == null || panel == null)
+			return;
+		if (ic<=-1 || st < -1 || st> CategoricalState.maxCategoricalState || ic >= data.getNumChars()){
+			panel.setNotes(null, "", "", ic, st, noteNumber);
+			panel.setAttachable(false);
+			return;
+		}
+		currentCharacter  = ic;
+		currentState = st;
+		panel.setAttachable(true);
+		String s = null;
+		if (st<0)
+			s = "Character " + (ic+1);
+		else
+			s = "State " + st + " in character " + (ic+1);
+		String loc = Integer.toString(ic+1);
+		if (st>=0)
+			loc += " (" +st + ")";
+		panel.setNotes(aim, s, loc , ic, st, noteNumber);
+	}
+	void showNote(int ic, int st, int noteNumber){
+		if (data == null || panel == null)
+			return;
+		if (ic<=-1 || st < -1 || st> CategoricalState.maxCategoricalState || ic >= data.getNumChars()){
+			showNote(null, ic, st, noteNumber);
+			return;
+		}
+		AttachedNotesVector hL = null;
+		if (st < 0)
+			hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+		else
+			hL = data.getStateAnnotationsVector(ic, st);
+		showNote(hL, ic, st, noteNumber);
+	}
+
+
+	public AttachedNotesVector makeNotesVector(AnnotationsPanel w){
+		AttachedNotesVector aiv = null;
+		if (currentState == -1) {
+			aiv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, currentCharacter);
+			if (aiv == null){
+				aiv = new AttachedNotesVector(data);
+				data.setAssociatedObject(notesNameRef, currentCharacter, aiv);
+			}
+		}
+		else {
+			aiv = data.getStateAnnotationsVector(currentCharacter, currentState);
+			if (aiv == null){
+				aiv = new AttachedNotesVector(data);
+				data.setStateAnnotationsVector(currentCharacter, currentState, aiv);
+			}
+		}
+		return aiv;
+	}
+	public void chooseAndAttachImage(AttachedNote hL, boolean local){
+		if (hL == null)
+			return;
+
+		hL.attachImage(ownerModule, local);
+		showNote(currentCharacter, currentState, currentNoteNumber);
+		if (table != null)
+			table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	int count = 0;
+	int prevIC = -1;
+	int prevST = -1;
+	public void focusInCell(int ic, int state){
+		if (data == null)
+			return;
+		if (prevIC == ic && prevST == state)
+			return;
+		prevIC = ic;
+		prevST = state;
+		showNote(ic, state, 0);
+		showSummary(ic, state);
+		return;
+	}
+
+	public boolean showFindMenuItems(){
+		return false;
+	}
+	public String getFindMessageName(){
+		return "Character or State name";
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			if (getMode()>0)
+				updateTextPage();
+			else if (code==MesquiteListener.NAMES_CHANGED) {
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_DELETED) {
+				table.resetNumChars();
+				table.checkSelection();
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_CHANGED) {
+				table.resetNumChars();
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED) {
+				table.resetNumChars();
+				table.checkSelection();
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_MOVED) {
+				table.checkSelection();
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				table.checkSelection();
+				table.repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** When called the getModuleWindow() will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+
+		if (data != null) {
+			if (data.uniquelyNamed())
+				setTitle("StateNames (" + data.getName() + ")");
+			else
+				setTitle("StateNames (" + data.getName() + " [" + data.getID() + "])");
+		}
+		else
+			setTitle("State Names");
+	}
+
+	/*.................................................................................................................*/
+	void setRowsAreCharacters(boolean rac){
+		rowsAreCharacters.setValue(rac);
+		ibeamTool.setWorksOnRowNames(rac); 
+		table.resetRowsAreCharacters(rac);
+	}
+	/*.................................................................................................................*/
+	String fillName;
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("rowsAreCharacters " + rowsAreCharacters.toOffOnString()); 
+		temp.addLine("toggleConstrainChar " + constrainedCW.toOffOnString()); 
+		temp.addLine("toggleConstrainCharNum " + constrainedColumnNum); 
+		temp.addLine("togglePanel " + showPanel.toOffOnString());
+		temp.addLine("toggleSummaryPanel " + showSummaryPanel.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hides state names editor window", null, commandName, "hideWindow")) {
+			hide();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the annotations panel is shown", "[on = shown; off]", commandName, "togglePanel")) {
+			Parser parser = new Parser();
+			showPanel.toggleValue(parser.getFirstToken(arguments));
+			setPanel();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the annotations summary panel is shown", "[on = shown; off]", commandName, "toggleSummaryPanel")) {
+			Parser parser = new Parser();
+			showSummaryPanel.toggleValue(parser.getFirstToken(arguments));
+			setSummaryPanel();
+		}
+		else if (checker.compare(this.getClass(), "Selects a row in the editor", "[row number]", commandName, "selectRow")) { //TODO: should this use internal or external character numbers???
+			selectRow(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Selects a column in the editor", "[column number]", commandName, "selectColumn")) {
+			selectColumn(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Puts characters on rows, states on columns", "[on or off]", commandName, "rowsAreCharacters")) {
+			rowsAreCharacters.toggleValue(arguments);
+			setRowsAreCharacters(rowsAreCharacters.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Constrains width of character names area", "[on or off]", commandName, "toggleConstrainChar")) {
+			constrainedCW.toggleValue(arguments);
+			table.setConstrainMaxAutoColumn(constrainedCW.getValue());
+			table.setConstrainMaxAutoRownames(constrainedCW.getValue());
+			if (!MesquiteThread.isScripting())
+				table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Constrains width of character names aresa", "[number of columns]", commandName, "toggleConstrainCharNum")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(this, "Set Min number of columns", "Minimum number of columns", constrainedColumnNum, 1, MesquiteInteger.infinite);
+			if (newNum>0  && newNum!=constrainedColumnNum) {
+				constrainedColumnNum = newNum;
+				table.setConstrainMaxAutoColumnNum(constrainedColumnNum);
+				if (!MesquiteThread.isScripting())
+					table.repaintAll();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Fills the touched cell with current paint", "[column][row]", commandName, "fillTouchCell")) {
+			if (table!=null && data !=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column= MesquiteInteger.fromString(arguments, io);
+				int row= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(row)|| !table.columnLegal(column))
+					return null;
+				if (table.anyCellSelected()) {
+					if (table.isCellSelected(column, row)) {
+						for (int i=0; i<table.getNumColumns(); i++)
+							for (int j=0; j<table.getNumRows(); j++)
+								if (table.isCellSelected(i,j))
+									table.setStateName(j,i, fillName);
+						table.repaintAll();
+					}
+				}
+				else if (table.anyRowSelected()) {
+					if (table.isRowSelected(row)) {
+						for (int j=0; j<table.getNumRows(); j++) {
+							if (table.isRowSelected(j))
+								for (int i=0; i<table.getNumColumns(); i++)
+									table.setStateName(j,i, fillName);
+						}
+						table.repaintAll();
+					}
+				}
+				else if (table.anyColumnSelected()) {
+					if (table.isColumnSelected(column)) {
+						for (int i=0; i<table.getNumColumns(); i++){
+							if (table.isColumnSelected(i))
+								for (int j=0; j<table.getNumRows(); j++) 
+									table.setStateName(j,i, fillName);
+						}
+						table.repaintAll();
+					}
+				}
+				else {
+					table.setStateName(row, column, fillName);
+					table.redrawCell(column, row);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user to fill the selected cells with text", null, commandName, "fillSelected")) {
+			fillName = MesquiteString.queryString(this, "Fill cells", "Fill cells with names:", "");
+			if (table.anyCellSelected()) {
+				for (int i=0; i<table.getNumColumns(); i++)
+					for (int j=0; j<table.getNumRows(); j++)
+						if (table.isCellSelected(i,j))
+							table.setStateName(j,i, fillName);
+				table.repaintAll();
+			}
+			else if (table.anyRowSelected()) {
+				for (int j=0; j<table.getNumRows(); j++) {
+					if (table.isRowSelected(j))
+						for (int i=0; i<table.getNumColumns(); i++)
+							table.setStateName(j,i, fillName);
+				}
+				table.repaintAll();
+			}
+			else if (table.anyColumnSelected()) {
+				for (int i=0; i<table.getNumColumns(); i++){
+					if (table.isColumnSelected(i))
+						for (int j=0; j<table.getNumRows(); j++) 
+							table.setStateName(j,i, fillName);
+				}
+				table.repaintAll();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user what paint to use", null, commandName, "fillOptions")) {
+			if (table!=null && data !=null){
+				fillName = MesquiteString.queryString(this, "Fill name", "Name with which to fill using paint bucket:", "");
+				if (StringUtil.blank(fillName))
+					return null;
+				fillTool.setDescription("Fill with \"" + fillName+ " \"");
+				dropperTool.setDescription("Copy name (current: " + fillName + ")");
+				toolTextChanged();
+			}
+
+
+		}
+		else if (checker.compare(this.getClass(), "Queries the user for the paint string", null, commandName, "touchTool")) {
+			if (table!=null && data !=null){
+				String newFillString  = MesquiteString.queryString(this, "Fill string", "String with which to fill using paint bucket:", fillString);
+				if (StringUtil.blank(newFillString))
+					return null;
+				fillString = newFillString;
+				neverFilled = false;
+				fillTool.setDescription("Fill with \"" + fillString + " \"");
+				dropperTool.setDescription("Copy string (current: " + fillString + ")");
+				this.toolTextChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Fills the paint bucket with the string of the selected cell", "[column][row]", commandName, "dropperTouchCell")) {
+			if (table!=null && data !=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column= MesquiteInteger.fromString(arguments, io);
+				int row= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(row)|| !table.columnLegal(column))
+					return null;
+				fillName = table.getText(column, row);
+				fillTool.setDescription("Fill with \"" + fillName+ " \"");
+				dropperTool.setDescription("Copy name (current: " + fillName + ")");
+				toolTextChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void selectRow(int row) {
+		table.selectRow(row);
+	}
+
+	public void selectColumn(int column) {
+		table.selectColumn(column);
+	}
+
+	/*.................................................................................................................*/
+	public void windowResized() {
+		super.windowResized();
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (table!=null && ((getHeight()!=windowHeight) || (getWidth()!=windowWidth))) {
+			windowHeight =getHeight();
+			windowWidth = getWidth();
+			table.setSize(windowWidth, windowHeight);
+		}
+		if (table!=null)
+			table.resetComponentSizes();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public MesquiteTable getTable() {
+		return table; 
+	}
+	public void dispose(){
+		if (this.data != null)
+			data.removeListener(this);
+		ownerModule.deleteMenuItem(constrainMenuItem);
+		ownerModule.deleteMenuItem(transposeMenuItem);
+		ownerModule.deleteMenuItem(menu);
+		super.dispose();
+	}
+}
+
+/* ======================================================================== */
+class StateNamesTable extends MesquiteTable {
+	StateNamesWindow window;
+	CategoricalData data;
+	StateAnnotation cellAnnotated;
+	boolean rowsAreCharacters = false;
+	Image transpose;
+
+	public StateNamesTable (CategoricalData data, int totalWidth, int totalHeight, int columnNamesWidth, StateNamesWindow window, boolean rowsAreCharacters) {
+		super(data.getNumChars(), CategoricalState.maxCategoricalState+1, totalWidth, totalHeight, columnNamesWidth, window.getColorScheme(),true,false);
+		this.rowsAreCharacters = rowsAreCharacters;
+		this.data = data;
+		if (!rowsAreCharacters){
+			setNumRows(CategoricalState.maxCategoricalState+1);
+			setNumColumns(data.getNumChars());
+		}
+		this.window = window;
+		transpose  = MesquiteImage.getImage(window.ownerModule.getPath() + "transpose.gif");
+		autosizeColumns = true;
+		cellAnnotated = new StateAnnotation(data);
+		showRowGrabbers=true;
+		showColumnGrabbers=true;
+		//setAutoEditable(false, false, false, false);
+		if (rowsAreCharacters){
+			setEditable(true, true, false, false); 
+			setShowRCNumbers(true, false);
+			setSelectable(true, true, true, true, false, false);
+			setColumnNamesCopyPaste(false);
+			setRowAssociable(data);
+		}
+		else {
+			setEditable(true, false, true, false); 
+			setSelectable(true, true, true, false, true, false);
+			setShowRCNumbers(false, true);
+			setRowNamesCopyPaste(false);
+			setColumnAssociable(data);
+		}
+	}
+
+	void resetRowsAreCharacters(boolean rac){
+		rowsAreCharacters = rac;
+		if (rowsAreCharacters){
+			setEditable(true, true, false, false); 
+			setShowRCNumbers(true, false);
+			setSelectable(true, true, true, true, false, false);
+			setColumnNamesCopyPaste(false);
+			setNumColumns(CategoricalState.maxCategoricalState+1);
+			setRowAssociable(data);
+			setNumRows(data.getNumChars());
+		}
+		else {
+			setEditable(true, false, true, false); 
+			setShowRCNumbers(false, true);
+			setSelectable(true, true, true, false, true, false);
+			setRowNamesCopyPaste(false);
+			setNumRows(CategoricalState.maxCategoricalState+1);
+			setColumnAssociable(data);
+			setNumColumns(data.getNumChars());
+		}
+		repaintAll();
+	}
+	void checkSelection(){
+		if (rowsAreCharacters){
+			for (int i=0; i< data.getNumChars(); i++){
+				if (data.getSelected(i) && !isRowSelected(i))
+					selectRow(i);
+				else if (!data.getSelected(i) && isRowSelected(i))
+					deselectRow(i);
+			}
+		}
+		else{
+			for (int i=0; i< data.getNumChars(); i++){
+				if (data.getSelected(i) && !isColumnSelected(i))
+					selectColumn(i);
+				else if (!data.getSelected(i) && isColumnSelected(i))
+					deselectColumn(i);
+			}
+
+		}
+
+	}
+	/*-------------------------------*/
+	void resetNumChars(){
+		if (rowsAreCharacters)
+			setNumRows(data.getNumChars());
+		else
+			setNumColumns(data.getNumChars());
+	}
+	/*...............................................................................................................*/
+	/** returns a tab delimited text version of the table*/
+	public String getTextVersion(){
+		int maxStateNamed = -1;
+		for (int ic=0; ic<data.getNumChars(); ic++) {
+			for (int state=0; state<=CategoricalState.maxCategoricalState; state++)
+				if (data.hasStateName(ic, state) && maxStateNamed < state)
+					maxStateNamed = state;
+		}
+		int sbsize = maxStateNamed*data.getNumChars();
+		if (sbsize<=0)
+			sbsize = 1;
+		StringBuffer outputBuffer = new StringBuffer(sbsize);
+		for (int state=0; state<=maxStateNamed;state++)
+			outputBuffer.append("\t" + getStateHeading(state));
+		outputBuffer.append("\n");
+		for (int ic=0; ic<data.getNumChars();ic++) {
+			outputBuffer.append(data.getCharacterName(ic)); 
+			for (int state=0; state<=maxStateNamed;state++)
+				outputBuffer.append("\t" + getState(state,ic));
+			outputBuffer.append("\n");
+		}
+		return outputBuffer.toString();
+
+	}
+
+	String getState(int state, int ic){
+		if (data.hasStateName(ic, state))
+			return data.getStateName(ic, state); //return state name
+		else return "";
+	}
+	String getStateHeading(int state){
+		if (state>9 ||  Integer.toString(state).charAt(0) != data.getSymbol(state))
+			return "State "  + Integer.toString(state) + " (\'" + data.getSymbol(state) + "\')";
+		return "State " + Integer.toString(state);
+	}
+
+	public void setStateName(int row, int column, String name){  
+		if (rowsAreCharacters)
+			data.setStateName( row, column, name);
+		else
+			data.setStateName( column, row, name);
+	}
+	public String getMatrixText(int column, int row){  
+		if (rowsAreCharacters)
+			return getState(column, row);
+		else
+			return getState(row, column);
+	}
+
+	/*...............................................................................................................*/
+	public String getMatrixTextForDisplay(int column, int row){
+		String s = getMatrixText(column, row);
+		if (rowsAreCharacters){
+			if (!StringUtil.blank(data.getStateNote(row, column))) 
+				s += '*';
+		}
+		else {
+			if (!StringUtil.blank(data.getStateNote(column, row))) 
+				s += '*';
+		}
+		return s;
+	}
+	public boolean useString(int column, int row){  
+		if (column<0 && row<0)
+			return false;
+		return true;
+	}
+	public String getCornerText(){
+		if (rowsAreCharacters)
+			return "Character \\ State";
+		else
+			return "State \\ Character";
+
+	}
+
+	public EditorPanel getCharNamesPanel (){
+		if (rowsAreCharacters)
+			return rowNames;
+		else
+			return columnNames;
+	}
+
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Selects all cells in the editor", null, commandName, "selectAll")) {
+			if (matrix.getEditing()|| getCharNamesPanel().getEditing()){
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (getCharNamesPanel().getEditing())
+					edit = getCharNamesPanel().getEditField();
+				if (edit!=null) {
+					edit.selectAll();
+				}
+			}
+			else {
+				boolean selectA = (!anythingSelected());
+
+				if ((selectA || anyCellSelected()))
+					selectBlock(0, 0, numColumnsTotal-1, numRowsTotal-1);
+				if ((selectA || anyRowSelected())) {
+					selectRows(0, numRowsTotal-1);
+				}
+				if ((selectA || anyColumnSelected())) {
+					selectBlock(0, 0, numColumnsTotal-1, numRowsTotal-1);
+				}
+				if (rowsAreCharacters){
+					if ((selectA || anyRowNameSelected()))
+						selectRowNames(0,numRowsTotal-1);
+				}
+				else {
+					if ((selectA || anyColumnNameSelected()))
+						selectColumnNames(0,numColumnsTotal-1);
+				}
+				repaintAll();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}	
+	/*...............................................................................................................*/
+	public void returnedMatrixText(int column, int row, String s){
+		int ic, state;
+		if (rowsAreCharacters){
+			ic = row;
+			state = column;
+		}
+		else {
+			ic = column;
+			state = row;
+		}
+
+		if (StringUtil.blank(s)) {
+			data.setStateName(ic, state,null);
+			if (data.hasStateName(ic, state))
+				repaintAll();
+			if (autoSizeColumns(getGraphics())) {
+				matrix.repaint();
+				columnNames.repaint();
+			}
+
+		}
+		else if ((s.length()>1 || s.charAt(0)!=data.getSymbol(state)) && (!s.equals(data.getStateName(ic, state)))) {
+			data.setStateName(ic, state, s);
+			repaintAll();
+
+			if (autoSizeColumns(getGraphics())) {
+				matrix.repaint();
+				columnNames.repaint();
+			}
+
+		}
+	}
+	
+	Color getCharColor(int ic){
+		CharacterPartition part = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		if (part!=null){
+			CharactersGroup mi = (CharactersGroup)part.getProperty(ic);
+			if (mi!=null)
+				return mi.getColor();
+		}
+		return null;
+	}
+	public void drawRowNameCell(Graphics g, int x, int y, int w, int h, int row) {
+		if (rowsAreCharacters){
+			Color c = getCharColor(row);
+			if (c != null){
+				Color prev = g.getColor();
+				g.setColor(c);
+				g.fillRect(x, y, w, h);
+				g.setColor(prev);
+			}
+			
+		}
+		super.drawRowNameCell(g, x, y, w, h, row);
+	}
+	public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column) {
+		if (!rowsAreCharacters){
+			Color c = getCharColor(column);
+			if (c != null){
+				Color prev = g.getColor();
+				g.setColor(c);
+				g.fillRect(x, y, w, h);
+				g.setColor(prev);
+			}
+			
+		}
+		super.drawColumnNameCell(g, x, y, w, h, column);
+	}
+	/*...............................................................................................................*/
+	public String getColumnNameText(int column){
+		if (!rowsAreCharacters)
+			return data.getCharacterName(column);
+		else
+			return getStateHeading(column);
+	}
+	/*...............................................................................................................*/
+	public String getColumnNameTextForDisplay(int column){
+		String s = getColumnNameText(column);
+		if (!rowsAreCharacters && data.getAnnotation(column) != null)
+			s += "*";
+		return s;
+
+	}
+	/*...............................................................................................................
+	 * 			CharacterPartition part = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+			if (part!=null){
+				CharactersGroup mi = (CharactersGroup)part.getProperty(row);
+				if (mi!=null) {
+					g.setColor(mi.getColor());
+					return;
+				}
+			}
+*/
+	public String getRowNameText(int row){
+		if (rowsAreCharacters)
+			return data.getCharacterName(row);
+		else
+			return getStateHeading(row);
+	}
+	/*...............................................................................................................*/
+	public String getRowNameTextForDisplay(int row){
+		String s = getRowNameText(row);
+		if (rowsAreCharacters && data.getAnnotation(row) != null)
+			s += "*";
+		return s;
+
+	}
+	/*...............................................................................................................*/
+	public void returnedRowNameText(int row, String s){
+		if (rowsAreCharacters)
+			returnedCharNameText(row, s);
+	}
+	public void returnedColumnNameText(int column, String s){
+		if (!rowsAreCharacters)
+			returnedCharNameText(column, s);
+
+	}
+
+	public void returnedCharNameText(int ic, String s){
+		if (data == null)
+			return;
+	if (StringUtil.blank(s) && data.characterHasName(ic)){
+			data.setCharacterName(ic, null);
+			repaintAll();
+
+			if (autoSizeColumns(getGraphics())) {
+				matrix.repaint();
+				columnNames.repaint();
+			}
+
+		}
+		else if (s == null)
+			return;
+		else if (!s.equals(data.getCharacterName(ic))) {
+			String warning = data.checkNameLegality(ic, s);
+			if (warning == null)
+				data.setCharacterName(ic, s);
+			else
+				window.ownerModule.discreetAlert( warning);
+			repaintAll();
+
+			if (autoSizeColumns(getGraphics())) {
+				matrix.repaint();
+				columnNames.repaint();
+			}
+
+		}
+	}
+	public void selectRow(int row) {
+		if (rowsAreCharacters)
+			super.selectRow(row);
+		else
+			selectBlock(0, row, getLastColumn(), row);
+	}
+
+	public void selectRows(int first, int last) {
+		if (!rowsAreCharacters)
+			selectBlock(0, first, getLastColumn(), last);
+		else
+			super.selectRows(first, last);
+	}
+	public void selectColumn(int column) {
+		if (rowsAreCharacters)
+			selectBlock(column, 0, column, getLastRow());
+		else
+			super.selectColumn(column);
+	}
+	public void selectColumns(int first, int last) {
+		if (rowsAreCharacters)
+			selectBlock(first, 0, last, getLastRow());
+		else
+			super.selectColumns(first, last);
+	}
+	/*.................................................................................................................*/
+	public void copyIt(StringBuffer s, boolean literal){//���may change on transpose
+		if (s==null)
+			return;
+		int count = 0;
+		boolean firstInLine = true;
+		boolean allSelected = true;
+		int numRows = numRowsTotal;
+		int maxColumn = 0;
+		boolean nothingSelected = !anythingSelected();
+
+		for (int j = 0; j<numRows; j++) {
+			boolean rowSel = nothingSelected ||  isRowSelected(j);
+			firstInLine = true;
+			if (rowSel || isRowNameSelected(j)) {
+				String t =null;
+				if (literal)
+					t = getRowNameTextForDisplay(j);
+				else 
+					t = getRowNameText(j);
+				if (!StringUtil.blank(t)) {
+					s.append(t);
+					firstInLine = false;
+				}
+			}
+
+			for (int i = 0; i<numColumnsTotal; i++) {
+				if (rowSel || isCellSelected(i, j)){
+					String t =null;
+					if (literal)
+						t = getMatrixTextForDisplay(i,j);
+					else 
+						t = getMatrixText(i,j);
+
+
+					if (!firstInLine) 
+						s.append('\t');
+					if (!StringUtil.blank(t)) 
+						s.append(t);
+					firstInLine = false;
+
+				}
+
+			}
+			if (!firstInLine)
+				s.append(StringUtil.lineEnding());
+		}
+	}
+	public void clickOutside(){
+		if ((!(matrix.getEditing()|| rowNames.getEditing() || columnNames.getEditing()) && !singleTableCellSelected())){
+			window.focusInCell(-2, -2);
+		}
+	}
+	public  void drawCornerCell(Graphics g, int x, int y,  int w, int h){
+		super.drawCornerCell(g, x, y, w, h);
+		g.drawImage(transpose, x, y, cornerCell);
+	}
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+	public boolean isAttachedNoteAvailable(int column, int row){
+		if (data == null)
+			return false;
+		AttachedNotesVector anv = null;
+		try {
+			int ic = row;
+			int st = column;
+			if (!rowsAreCharacters){
+				ic = column;
+				st = row;
+			}
+			if (st < 0)
+				anv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+			else
+				anv = data.getStateAnnotationsVector(ic, st);
+		}
+		catch(Exception e){
+		}
+		if (anv == null)
+			return false;
+		return (anv.getNumNotes()>0);
+	}
+
+	/*...............................................................................................................*/
+	public void mouseInCell(int modifiers, int column,int subColumn, int row, int subRow, MesquiteTool tool){
+		if ((!(matrix.getEditing()|| rowNames.getEditing() || columnNames.getEditing()) && !singleTableCellSelected())){
+			if (rowsAreCharacters)
+				window.focusInCell(row, column);
+			else 
+				window.focusInCell(column, row);
+		}
+		super.mouseInCell(modifiers, column, subColumn, row, subRow, tool);
+	}
+	/*...............................................................................................................*/
+	public void cornerTouched(int x, int y, int modifiers) {
+		super.cornerTouched(x, y, modifiers);
+		if (x<12 && y<12){
+			window.setRowsAreCharacters(!rowsAreCharacters);
+		}
+	}
+	/*...............................................................................................................*/
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (((TableTool)window.getCurrentTool()== (TableTool)window.arrowTool) && (clickCount>1)) {
+			window.setCurrentTool((TableTool)window.ibeamTool);
+			window.getPalette().setCurrentTool((TableTool)window.ibeamTool); 
+			((TableTool)window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		}
+		else if (((TableTool)window.getCurrentTool()).useTableTouchRules())
+			super.cellTouched(column, row, regionInCellH, regionInCellV, modifiers, clickCount);
+		else
+			((TableTool)window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		if (window.getCurrentTool()== window.arrowTool || window.getCurrentTool()== window.ibeamTool){
+			//deselectAll();
+			setFocusedCell(column, row);
+			repaintAll();
+		}
+		else
+			window.setAnnotation("", null);
+	}
+	/*...............................................................................................................*/
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (window.getCurrentTool()== window.arrowTool) 
+			super.cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+		else
+			((TableTool)window.getCurrentTool()).cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+	}
+	/*...............................................................................................................*/
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (window.getCurrentTool()== window.arrowTool) 
+			super.cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+		else
+			((TableTool)window.getCurrentTool()).cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+	}
+	public void setFocusedCell(int column, int row){
+		cellAnnotated.setCell(column, row, rowsAreCharacters);
+		window.setAnnotation(cellAnnotated);
+		if (rowsAreCharacters)
+			window.focusInCell(row, column);
+		else
+			window.focusInCell(column, row);
+		super.setFocusedCell(column, row);
+	}
+	/*...............................................................................................................*/
+	public void rowNameTouched(int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (rowsAreCharacters){
+			if ((window.getCurrentTool()==window.arrowTool) && (clickCount>1)) {
+				window.setCurrentTool((TableTool)window.ibeamTool);
+				window.getPalette().setCurrentTool((TableTool)window.ibeamTool); 
+				((TableTool)window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, clickCount);
+			}
+			else if (window.getCurrentTool()== window.arrowTool) 
+				super.rowNameTouched( row, regionInCellH, regionInCellV, modifiers, clickCount);
+			else
+				((TableTool)window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers); 
+			if (window.getCurrentTool()== window.arrowTool || window.getCurrentTool()== window.ibeamTool){
+				//deselectAll();
+				setFocusedCell(-1, row);
+				repaintAll();
+			}
+			else
+				window.setAnnotation("", null);
+		}
+	}
+	/*...............................................................................................................*/
+	public void columnNameTouched(int column, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (!rowsAreCharacters){
+			if ((window.getCurrentTool()==window.arrowTool) && (clickCount>1)) {
+				window.setCurrentTool((TableTool)window.ibeamTool);
+				window.getPalette().setCurrentTool((TableTool)window.ibeamTool); 
+				((TableTool)window.getCurrentTool()).cellTouched(column, -1, regionInCellH, regionInCellV, clickCount);
+			}
+			else if (window.getCurrentTool()== window.arrowTool) {
+				super.columnNameTouched( column, regionInCellH, regionInCellV, modifiers, clickCount);
+			}
+			else
+				((TableTool)window.getCurrentTool()).cellTouched(column, -1, regionInCellH, regionInCellV, modifiers); 
+			if (window.getCurrentTool()== window.arrowTool || window.getCurrentTool()== window.ibeamTool){
+				//deselectAll();
+				setFocusedCell(column, -1);
+				repaintAll();
+			}
+			else
+				window.setAnnotation("", null);
+		}
+	}
+}
+
+/* ======================================================================== */
+class StateAnnotation implements Annotatable {
+	String name;
+	CategoricalData data;
+	int state, character;
+	public StateAnnotation(CategoricalData data) {
+		this.data = data;
+	}
+
+	void setCell(int c, int r, boolean rowsAreCharacters){
+		if (rowsAreCharacters){
+			character = r;
+			state = c;
+		}
+		else {
+			character = c;
+			state = r;
+		}
+	}
+	public String getName(){
+		if (data == null)
+			return "";
+		if (character == -1) {
+			if (state == -1)
+				return "matrix \"" + data.getName() + "\"";
+			return null;
+		}
+		else if (state == -1) {
+			return "character \"" +data.getCharacterName(character) + "\"";
+		}
+		else {
+			return "state " + (state) + " in " +data.getCharacterName(character) ;
+		}
+	}
+	public String getAnnotation(){
+		if (data == null)
+			return null;
+		if (character == -1)
+			return null;
+		if (state == -1) {
+			return data.getAnnotation(character);
+		}
+		else if (character > -1){
+			return data.getStateNote(character, state);
+		}
+		return null;
+	}
+	public void setAnnotation(String s, boolean notify){
+		if (data == null)
+			return;
+		if ("".equals(s))
+			s = null;
+		if (state == -1) {
+			data.setAnnotation(character, s);
+		}
+		else if (character > -1){
+			data.setStateNote(character, state, s);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/categ/StateNamesEditor/transpose.gif b/Source/mesquite/categ/StateNamesEditor/transpose.gif
new file mode 100644
index 0000000..0259ac8
Binary files /dev/null and b/Source/mesquite/categ/StateNamesEditor/transpose.gif differ
diff --git a/Source/mesquite/categ/StateNamesStrip/StateNamesStrip.java b/Source/mesquite/categ/StateNamesStrip/StateNamesStrip.java
new file mode 100644
index 0000000..5f62440
--- /dev/null
+++ b/Source/mesquite/categ/StateNamesStrip/StateNamesStrip.java
@@ -0,0 +1,168 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.StateNamesStrip;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class StateNamesStrip extends CategDataEditorInitD {
+	CategoricalData data;
+	Ledge panel;
+	MesquiteBoolean showStrip;
+	boolean shown;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showStrip = new MesquiteBoolean(false);
+		shown = false;
+		addCheckMenuItem(null, "Show State Names Strip", makeCommand("showStrip", this), showStrip);
+		return true;
+	}
+   	/** Called to alter data in all cells*/
+   	public void setTableAndData(MesquiteTable table, CharacterData data){
+			this.data = (CategoricalData)data;
+			if (data.getClass() != CategoricalData.class)
+				return;
+			resetLedge();
+			
+   	}
+   	public void resetLedge(){
+   		if (showStrip.getValue() && !shown){  //need to show
+   			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = true;
+				if (panel == null)
+					panel = new Ledge(this);
+				((MesquiteWindow)f).addLedgePanel(panel, 22);
+				panel.setVisible(true);
+				panel.setMessage("");
+			}
+   		}
+   		else if (!showStrip.getValue() && shown && panel != null){ //need to hide
+   			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = false;
+				panel.setVisible(false);
+				((MesquiteWindow)f).removeLedgePanel(panel);
+   			}
+   		}
+   	}
+	/*.................................................................................................................*/
+ 	public void endJob() {
+ 		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			((MesquiteWindow)f).removeLedgePanel(panel);
+		}
+ 		super.endJob();
+   	 }
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+   	public void focusInCell(int ic, int it){
+  		if (panel == null)
+  			return;
+   		panel.setMessage(statesExplanation(ic, it));
+   	}
+	/*...............................................................................................................*/
+	private String statesExplanation(int column,int row){
+		if (data == null || column <0 || column >= data.getNumChars())
+			return "";
+		
+		String s = Integer.toString(column+1) + ". " + data.getCharacterName(column);
+		if (data.getClass() == CategoricalData.class){
+			s += ": ";
+			CategoricalData cData = (CategoricalData)data;
+			long state = cData.getState(column, row);
+			for (int i = 0; i<=CategoricalState.maxCategoricalState; i++)
+				if (cData.hasStateName(column, i)) {
+					s +=  "(" + cData.getSymbol(i) + ")";
+					if (CategoricalState.isElement(state, i))
+						s += "*";
+					s += " " + cData.getStateName(column, i);
+					s +="; ";
+				}
+		}
+		else if (data instanceof DNAData)
+			s = "  Ambiguity codes: R-AG, Y-CT, M-AC, W-AT, S-CG, Y-CT, K-GT, V-ACG, D-AGT, H-ACT, B-CGT, N-ACGT";
+		return s;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("showStrip " + showStrip.toOffOnString());
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Shows a strip with state names", null, commandName, "showStrip")) {
+     	 		showStrip.toggleValue(parser.getFirstToken(arguments));
+     	 		resetLedge();
+   	 		
+    	 	}
+
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "State Names Strip";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shows the strip at bottom of matrix with state names." ;
+   	 }
+}
+class Ledge extends MousePanel {
+	TextArea message;
+	StateNamesStrip ownerModule;
+	public Ledge(StateNamesStrip ownerModule){
+		setLayout(null);
+		this.ownerModule = ownerModule;
+		/* */
+		message = new TextArea(" ", 20, 2, TextArea.SCROLLBARS_NONE);
+		message.setVisible(true);
+		add(message);
+		message.setBounds(0,0,getBounds().width, getBounds().height);
+		message.setBackground(ColorTheme.getContentBackground());
+		message.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+		/**/
+	}
+	public void setMessage(String s){
+		if (StringUtil.stringsEqual(s, message.getText()))
+			return;
+		message.setText(s);
+		
+	}
+	public void setSize(int w, int h){
+		message.setBounds(0,0,w, h);
+		super.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		message.setBounds(0,0,w, h);
+		super.setBounds(x, y, w,h);
+	}
+}
+
+
diff --git a/Source/mesquite/categ/aCategIntro/aCategIntro.java b/Source/mesquite/categ/aCategIntro/aCategIntro.java
new file mode 100644
index 0000000..f3bdb42
--- /dev/null
+++ b/Source/mesquite/categ/aCategIntro/aCategIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.aCategIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aCategIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aCategIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic facilities for handling categorical characters.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Categorical Data Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Categorical Data Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/categ/explanation.txt b/Source/mesquite/categ/explanation.txt
new file mode 100644
index 0000000..8c7f38e
--- /dev/null
+++ b/Source/mesquite/categ/explanation.txt
@@ -0,0 +1,2 @@
+Categorical character package
+One of the core Mesquite packages.  A package of fundamental modules and libraries for categorical character data.  These define key elements of categorical data and manage categorical data matrices.
diff --git a/Source/mesquite/categ/lib/CategColorTable.java b/Source/mesquite/categ/lib/CategColorTable.java
new file mode 100644
index 0000000..6619511
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategColorTable.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+public class CategColorTable extends MesquiteColorTable  {
+   
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategDataAlterer.java b/Source/mesquite/categ/lib/CategDataAlterer.java
new file mode 100644
index 0000000..13243f2
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataAlterer.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class CategDataAlterer extends DataAlterer  {
+   	 public Class getDutyClass() {
+   	 	return CategDataAlterer.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategDataEditorInit.java b/Source/mesquite/categ/lib/CategDataEditorInit.java
new file mode 100644
index 0000000..3d5461a
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataEditorInit.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class CategDataEditorInit extends DataWindowAssistantI  {
+
+   	 public Class getDutyClass() {
+   	 	return CategDataEditorInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Categorical Data Editor Init";
+   	}
+   	
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategDataEditorInitD.java b/Source/mesquite/categ/lib/CategDataEditorInitD.java
new file mode 100644
index 0000000..85cf97a
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataEditorInitD.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class CategDataEditorInitD extends CategDataEditorInit  {
+
+   	 public Class getDutyClass() {
+   	 	return CategDataEditorInitD.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Categorical Data Editor Init (Display)";
+   	}
+   	
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategDataMatcher.java b/Source/mesquite/categ/lib/CategDataMatcher.java
new file mode 100644
index 0000000..e745403
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataMatcher.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.categ.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public abstract class CategDataMatcher extends DataMatcher {
+	
+
+	public double sequenceMatch(CharacterState[] csOriginalArray, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar) {
+		if (csOriginalArray==null || csOriginalArray.length<=0)
+			return MesquiteDouble.unassigned;
+		if (!(csOriginalArray[0] instanceof CategoricalState))
+			return MesquiteDouble.unassigned;
+		long[] longArray = new long[csOriginalArray.length];
+		for (int i=0; i<longArray.length; i++) 
+			longArray[i] = ((CategoricalState)csOriginalArray[i]).getValue();
+		return sequenceMatch(longArray,candidateTaxon, candidateStartChar, candidateEndChar);
+	}
+
+	/*.................................................................................................................*/
+   	/** Returns the match of the two CharacterState arrays*/
+	public double sequenceMatch(CharacterState[] csOriginalArray, CharacterState[] csCandidateArray){
+		if (csOriginalArray==null || csOriginalArray.length<=0)
+			return MesquiteDouble.unassigned;
+		if (csCandidateArray==null || csCandidateArray.length<=0)
+			return MesquiteDouble.unassigned;
+		if (!(csOriginalArray[0] instanceof CategoricalState) || !(csCandidateArray[0] instanceof CategoricalState))
+			return MesquiteDouble.unassigned;
+		long[] originalArray = new long[csOriginalArray.length];
+		for (int i=0; i<originalArray.length; i++) 
+			originalArray[i] = ((CategoricalState)csOriginalArray[i]).getValue();
+		long[] candidateArray = new long[csCandidateArray.length];
+		for (int i=0; i<candidateArray.length; i++) 
+			candidateArray[i] = ((CategoricalState)csCandidateArray[i]).getValue();
+		return sequenceMatch(originalArray,candidateArray);
+	}
+	
+	public double getBestMatchValue(CharacterState[] csOriginalArray){
+		if (csOriginalArray==null || csOriginalArray.length<=0)
+			return MesquiteDouble.unassigned;
+		if (!(csOriginalArray[0] instanceof CategoricalState))
+			return MesquiteDouble.unassigned;
+		long[] longArray = new long[csOriginalArray.length];
+		for (int i=0; i<longArray.length; i++) 
+			longArray[i] = ((CategoricalState)csOriginalArray[i]).getValue();
+		return getBestMatchValue(longArray);
+	}
+
+	public  double getApproximateWorstMatchValue(CharacterState[] csOriginalArray) {
+		if (csOriginalArray==null || csOriginalArray.length<=0)
+			return MesquiteDouble.unassigned;
+		if (!(csOriginalArray[0] instanceof CategoricalState))
+			return MesquiteDouble.unassigned;
+		long[] longArray = new long[csOriginalArray.length];
+		for (int i=0; i<longArray.length; i++) 
+			longArray[i] = ((CategoricalState)csOriginalArray[i]).getValue();
+		return getApproximateWorstMatchValue(longArray);
+	}
+	 
+	
+	public abstract double getBestMatchValue(long[] originalArray) ;
+
+	public abstract double getApproximateWorstMatchValue(long[] originalArray) ;
+	 	
+	public abstract double sequenceMatch(long[] originalArray, long[] candidateArray);
+
+	public abstract double sequenceMatch(long[] originalArray, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar);
+
+	public CompatibilityTest getCompatibilityTest() {
+		return new RequiresAnyCategoricalData();
+	}
+
+}
diff --git a/Source/mesquite/categ/lib/CategDataSearcher.java b/Source/mesquite/categ/lib/CategDataSearcher.java
new file mode 100644
index 0000000..b69fa8a
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataSearcher.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class CategDataSearcher extends DataSearcher  {
+   	 public Class getDutyClass() {
+   	 	return CategDataSearcher.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategDataUtility.java b/Source/mesquite/categ/lib/CategDataUtility.java
new file mode 100644
index 0000000..ba8da23
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategDataUtility.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to operate on a a data matrix.*/
+
+public abstract class CategDataUtility extends DataUtility  {
+   	 public Class getDutyClass() {
+   	 	return CategDataUtility.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+}
+
diff --git a/Source/mesquite/categ/lib/CategInternodeEvent.java b/Source/mesquite/categ/lib/CategInternodeEvent.java
new file mode 100644
index 0000000..cd4d22d
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategInternodeEvent.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+public class CategInternodeEvent  {
+	long state = 0L;
+	double position = 0;
+	boolean change = true;
+	
+	public CategInternodeEvent (long state, double position, boolean change) {
+		this.state = state;
+		this.position = position;
+		this.change = change;
+	}
+	public CategInternodeEvent cloneEvent(){
+		return new CategInternodeEvent (state, position, change);
+	}
+	public void setState(long state){
+		this.state = state;
+	}
+	public long getState(){
+		return state;
+	}
+	public void setPosition(double position){
+		this.position = position;
+	}
+	public double getPosition(){
+		return position;
+	}
+	public void setChangeVersusSample(boolean change){
+		this.change = change;
+	}
+	/** indicates whether this is a point of character state change or a sample of state at a time*/
+	public boolean getChangeVersusSample(){
+		return change;
+	}
+	public String toString(){
+		return "change " + change + "; position " + MesquiteDouble.toStringDigitsSpecified(position, 4) + "; state " + CategoricalState.toString(state);
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategMatrixManager.java b/Source/mesquite/categ/lib/CategMatrixManager.java
new file mode 100644
index 0000000..365f0f5
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategMatrixManager.java
@@ -0,0 +1,149 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+public abstract class CategMatrixManager extends CharMatrixManager   {
+	
+	public Class getDutyClass() {
+		return CategMatrixManager.class;
+	}
+	public String getDutyName() {
+		return "Manager of general categorical data matrix, including read/write CHARACTERS block";
+	}
+	
+	public Class getDataClass(){
+		return CategoricalData.class;
+	}
+	/*.................................................................................................................*/
+	private int writeCharactersBlockPart(CharacterData data, CharactersBlock cB, StringBuffer blocks, int startChar, int endChar, int tot, int numTotal, MesquiteFile file, ProgressIndicator progIndicator) {
+		if (startChar >= data.getNumChars()) {
+			file.writeLine(blocks.toString());
+			blocks.setLength(0);
+			return 0;
+		}
+		if (endChar> data.getNumChars())
+			endChar = data.getNumChars();
+
+		String taxonName="";
+		String taxonNameToWrite = "";
+		int maxNameLength = data.getTaxa().getLongestTaxonNameLength();
+		int invalidIC = -1;
+		int invalidIT = -1;
+		for (int it=0; it<data.getTaxa().getNumTaxa(); it++) {
+			if ((file.writeTaxaWithAllMissing || data.someApplicableInTaxon(it, false)) && (!file.writeOnlySelectedTaxa || data.getTaxa().getSelected(it))){
+				taxonName = data.getTaxa().getTaxon(it).getName();
+				if (taxonName!=null) {
+					if (file.useStandardizedTaxonNames)
+						taxonNameToWrite = "t" + it;
+					else
+						taxonNameToWrite = StringUtil.simplifyIfNeededForOutput(taxonName,file.simplifyNames);
+					blocks.append("\t"+taxonNameToWrite);
+					boolean spaceWritten = false;
+					for (int i = 0; i<(maxNameLength-taxonNameToWrite.length()+2); i++){
+						blocks.append(" ");
+						spaceWritten = true;
+					}
+					if (!spaceWritten)
+						blocks.append(" ");
+				}
+				if (progIndicator != null)
+					progIndicator.setText("Writing data for taxon " + taxonName);
+				int totInTax = 0;
+
+				//USE SYMBOLS
+				for (int ic=startChar;  ic<endChar; ic++) {
+					if (data.isCurrentlyIncluded(ic) || file.writeExcludedCharacters) {
+						if (!data.isValid(ic, it) && invalidIC <0){
+							invalidIC = ic;
+							invalidIT = it;
+						}
+						data.statesIntoNEXUSStringBuffer(ic, it, blocks);
+						tot++;
+						totInTax++;
+						if (numTotal>100000000) {
+							if (tot % 10000000 == 0  && isLogVerbose())
+								logln("\nComposing matrix: " + tot + " of " + numTotal);
+							else if (tot % 10000 == 0  && isLogVerbose())
+								log(".");
+						}
+						else if (numTotal>10000000) {
+							if (tot % 1000000 == 0  && isLogVerbose())
+								logln("Composing matrix: " + tot + " of " + numTotal);
+						} else if (tot % 100000 == 0  && isLogVerbose())
+							logln("Composing matrix: " + tot + " of " + numTotal);
+					//	27 July 08:  DRM commented out the following two lines.  These cannot be included, as NEXUS files are sensitive to line breaks within the MATRIX command.
+					
+						// if (totInTax % 2000 == 0)
+					//		blocks.append(StringUtil.lineEnding());//this is here because of current problem (at least on mrj 2.2) of long line slow writing
+					}
+				}
+				file.writeLine(blocks.toString());
+				blocks.setLength(0);
+			}
+		}
+		if (invalidIC >=0){
+			String s = "The matrix " + data.getName() + " has invalid characters states (e.g., character " + (invalidIC +1) + " in taxon " + (invalidIT + 1) + ")";
+			if (warnedInvalid)
+				logln(s);
+			else
+				alert(s);
+			warnedInvalid = true;
+		}
+		file.writeLine(blocks.toString());
+		blocks.setLength(0);
+		return tot;
+	}
+	boolean warnedInvalid = false;
+	/*.................................................................................................................*/
+	public void writeNexusMatrix(CharacterData data, CharactersBlock cB, StringBuffer blocks, MesquiteFile file, ProgressIndicator progIndicator){
+		warnedInvalid = false;
+		blocks.append("\tMATRIX" + StringUtil.lineEnding());
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = data.getNumChars();
+		else
+			numCharsToWrite = data.getNumCharsIncluded();
+		int numTotal = data.getNumTaxa() * numCharsToWrite;
+		//MesquiteModule.mesquiteTrunk.mesquiteMessage("Composing DNA matrix ", numTotal, 0);
+		if (data.interleaved && data.interleavedLength>0 && file.interleaveAllowed) {
+			int numBlocks = (int) (data.getNumChars() / data.interleavedLength);
+			int tot = 0;
+			for (int ib = 0; ib<=numBlocks; ib++) {
+				if (ib>0)
+					blocks.append(StringUtil.lineEnding());
+				tot = writeCharactersBlockPart(data, cB, blocks, ib*data.interleavedLength,(ib+1)*data.interleavedLength, tot, numTotal, file, progIndicator);
+			}
+		}
+		else
+			writeCharactersBlockPart(data, cB, blocks, 0,data.getNumChars(), 0, numTotal, file, progIndicator);
+		if (progIndicator !=null)
+			progIndicator.setText("Finished writing matrix");
+		blocks.append(";" + StringUtil.lineEnding());
+		file.writeLine(blocks.toString());
+		blocks.setLength(0);
+	}
+	
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategStateChanges.java b/Source/mesquite/categ/lib/CategStateChanges.java
new file mode 100644
index 0000000..a3c2a97
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategStateChanges.java
@@ -0,0 +1,386 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.CharHistorySource;
+
+public class CategStateChanges {
+	int maxChangesRecorded = 10;
+	int[][] min;
+	int[][] max;
+	double[][] avg;
+	double[][] total;
+	double[][][] fractionWithAmount;
+	double[][][] totalWithAmount;
+	double[][] totalChanges;
+	boolean [][] acceptableChange;
+
+	int numStates = 0;
+	long numMappings = 0;
+	long numHistories = 0;
+
+	public CategStateChanges(int numStates, int maxChanges) {
+		maxChangesRecorded = maxChanges;
+		this.numStates = numStates;
+		min = new int[numStates][numStates];
+		max = new int[numStates][numStates];
+		avg = new double[numStates][numStates];
+		total = new double[numStates][numStates];
+		totalChanges = new double[numStates][numStates];
+		fractionWithAmount = new double[numStates][numStates][maxChangesRecorded];
+		totalWithAmount = new double[numStates][numStates][maxChangesRecorded];
+		acceptableChange = new boolean[numStates][numStates];
+		initializeArrays();
+	}
+	/*.................................................................................................................*/
+	public int getNumStates(){
+		return numStates;
+	}
+	/*.................................................................................................................*/
+	public void adjustNumStates(int numStatesNew){
+		min =Integer2DArray.cloneIncreaseSize(min,numStatesNew, numStatesNew);
+		max =Integer2DArray.cloneIncreaseSize(max,numStatesNew, numStatesNew);
+		avg =Double2DArray.cloneIncreaseSize(avg,numStatesNew, numStatesNew);
+		total =Double2DArray.cloneIncreaseSize(total,numStatesNew, numStatesNew);
+		totalChanges =Double2DArray.cloneIncreaseSize(totalChanges,numStatesNew, numStatesNew);
+		fractionWithAmount =Double2DArray.cloneIncreaseSize(fractionWithAmount,numStatesNew, numStatesNew, maxChangesRecorded);
+		totalWithAmount =Double2DArray.cloneIncreaseSize(totalWithAmount,numStatesNew, numStatesNew, maxChangesRecorded);
+		numStates = numStatesNew;
+	}
+	/*.................................................................................................................*/
+	public void initializeArrays() {
+		for (int i=0; i<numStates; i++) 
+			for (int j=0; j<numStates; j++) {
+				min[i][j]= Integer.MAX_VALUE;
+				max[i][j]= 0;
+				avg[i][j]=0.0;
+				total[i][j]=0.0;
+				totalChanges[i][j]=0.0;
+				acceptableChange[i][j]=true;
+				for (int k=0; k<maxChangesRecorded; k++) {
+					fractionWithAmount[i][j][k] = 0.0;
+					totalWithAmount[i][j][k] = 0.0;
+				}
+			}
+	}
+	
+	/*.................................................................................................................*/
+	public void setAcceptableChange(int i, int j, boolean b) {
+		if (acceptableChange != null && i < acceptableChange.length && j < acceptableChange[i].length)		                                                                                  
+			acceptableChange[i][j]=b;
+
+	}
+
+	/*.................................................................................................................*/
+	public void zeroTotals() {
+		for (int i=0; i<numStates; i++) 
+			for (int j=0; j<numStates; j++) {
+				total[i][j]=0.0;
+				totalChanges[i][j]=0.0;
+				for (int k=0; k<maxChangesRecorded; k++) {
+					totalWithAmount[i][j][k] = 0.0;
+				}
+			}
+	}
+
+
+	/*.................................................................................................................*/
+
+	public boolean addOneMapping(Tree tree, CategoricalHistory history, int node, int whichMapping) {
+		if (!tree.nodeExists(node))
+			node = tree.getRoot();
+		int[][] array =  history.harvestStateChanges(tree, node,null);
+		if (array==null ||  array.length != numStates)
+			return false;
+		return addOneMapping(array,false);
+
+	}
+	/*.................................................................................................................*/
+	public boolean acceptableMapping(int[][] array) {
+		for (int i=0; i<numStates && i<array.length && i<acceptableChange.length; i++)
+			for (int j=0; j<numStates &&j<array[i].length && j<acceptableChange[i].length; j++)
+				if (!acceptableChange[i][j] && array[i][j]>0)
+					return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public boolean addOneMapping(int[][] array, boolean useTotal) {
+		if (array==null)
+			return false;
+		if (!acceptableMapping(array))
+			return false;
+		numMappings++;
+		if (numStates<array.length)  // added 21 September 2013  DRM
+			adjustNumStates(array.length);
+		for (int i=0; i<numStates && i<array.length; i++)
+			for (int j=0; j<numStates &&j<array[i].length; j++)
+			{
+				min[i][j] = MesquiteInteger.minimum(min[i][j],array[i][j]);
+				max[i][j] = MesquiteInteger.maximum(max[i][j],array[i][j]);
+				if (useTotal)
+					total[i][j] = total[i][j]+array[i][j];
+				else
+					avg[i][j] = ((avg[i][j]*numMappings-1)+array[i][j])/numMappings;
+				if (array[i][j]>=maxChangesRecorded)
+					totalWithAmount[i][j][maxChangesRecorded-1]++;
+				else
+					totalWithAmount[i][j][array[i][j]]++;
+				totalChanges[i][j]++;
+			}
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public void oneMappingToString (int[][] array, StringBuffer sb, String lineStart) {
+		if (array==null || sb==null)
+			return;
+		if (!acceptableMapping(array))
+			return;
+		if (StringUtil.notEmpty(lineStart))
+			sb.append(lineStart+"\t");
+		
+		for (int i=0; i<numStates && i<array.length; i++)
+			for (int j=0; j<numStates &&j<array[i].length; j++)
+				if (i!=j)
+					sb.append(""+array[i][j]+"\t");
+		sb.append("\n");
+	}
+	/*.................................................................................................................*/
+
+	public boolean mappingsAvailable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public void addOneHistory(Tree tree, CharHistorySource historySource,int ic, int node, MesquiteInteger numMappingsSampled, int samplingLimit, MesquiteInteger newSamplingLimit, boolean queryChangeSamplingLimit, StringBuffer fullDetails, String lineStart) {
+		CategoricalHistory resultStates=null;
+		CategoricalHistory history = null;
+		zeroTotals();
+		int[][] array;
+		int mappingsAdded=0;
+		if (!mappingsAvailable()) {
+			history = (CategoricalHistory)historySource.getMapping(0, history, null);
+			 if (history.getMaxState()+1>getNumStates())
+					adjustNumStates(history.getMaxState()+1);
+			history.clone(resultStates);
+			if (resultStates instanceof mesquite.categ.lib.CategoricalHistory){
+				array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node, null);
+				if (addOneMapping(array, true)) mappingsAdded++;
+				oneMappingToString(array, fullDetails, lineStart);
+			
+			}
+		}
+		else {
+			long numMappings = historySource.getNumberOfMappings(tree, ic);
+			if (queryChangeSamplingLimit && !MesquiteThread.isScripting() && newSamplingLimit!=null) {
+				int newLimit = MesquiteInteger.queryInteger(historySource.getModuleWindow(), "Maximum number of mappings to sample", "Maximum number of mappings to sample for the character on each tree",samplingLimit, 1, Integer.MAX_VALUE);
+				if (MesquiteInteger.isCombinable(newLimit))
+					newSamplingLimit.setValue(newLimit);
+			}
+			ProgressIndicator progIndicator = null;
+			if (((numMappings == MesquiteLong.infinite || !MesquiteLong.isCombinable(numMappings)) && samplingLimit>5000) || (numMappings<samplingLimit && numMappings>5000) || (samplingLimit>5000)){
+					progIndicator = new ProgressIndicator(null,"Examining mappings", samplingLimit, true);
+					progIndicator.start();
+			}
+			
+			if (numMappings == MesquiteLong.infinite || !MesquiteLong.isCombinable(numMappings)) {
+				for (int i=0; i<samplingLimit; i++) {
+					if (progIndicator!=null && i % 1000 == 0)
+						progIndicator.setCurrentValue(i);
+					if (progIndicator!=null && progIndicator.isAborted())
+						break;
+					resultStates = (CategoricalHistory)historySource.getMapping(i, resultStates, null);
+					if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+						array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node,null);
+						if (addOneMapping(array, true)) mappingsAdded++;
+						oneMappingToString(array, fullDetails,lineStart);
+					}
+				}
+
+			}
+			else 
+				if (numMappings<=samplingLimit) {
+					for (int i=0; i<numMappings; i++) {
+						resultStates = (CategoricalHistory)historySource.getMapping(i, resultStates, null);
+						if (progIndicator!=null && i % 1000 == 0)
+							progIndicator.setCurrentValue(i);
+						if (progIndicator!=null && progIndicator.isAborted())
+							break;
+						if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+							array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node,null);
+							if (addOneMapping(array, true)) mappingsAdded++;
+							oneMappingToString(array, fullDetails,lineStart);
+						}
+					}
+				}
+				else {
+					for (int i=0; i<samplingLimit; i++) {
+						resultStates = (CategoricalHistory)historySource.getMapping(RandomBetween.getLongStatic(0,numMappings-1),resultStates,null);
+						if (progIndicator!=null && i % 1000 == 0)
+							progIndicator.setCurrentValue(i);
+						if (progIndicator!=null && progIndicator.isAborted())
+							break;
+						if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+							array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node, null);
+							if (addOneMapping(array, true)) mappingsAdded++;
+							oneMappingToString(array, fullDetails,lineStart);
+						}
+					}
+				}
+			if (progIndicator!=null)
+				progIndicator.goAway();
+
+		}
+		if (mappingsAdded>0)
+			numHistories++;
+		if (numMappingsSampled!=null) numMappingsSampled.setValue(mappingsAdded);
+
+		if (mappingsAdded>0)
+			for (int i=0; i<numStates; i++)
+				for (int j=0; j<numStates; j++)
+				{
+					avg[i][j] = avg[i][j]+total[i][j]/mappingsAdded;
+					if (totalChanges[i][j]>0 && i!=j)
+						for (int k=0; k<maxChangesRecorded; k++) {
+							fractionWithAmount[i][j][k] = fractionWithAmount[i][j][k]+totalWithAmount[i][j][k]/totalChanges[i][j];
+						}
+				}
+
+	}
+	
+	/*.................................................................................................................*/
+
+	public void addOneHistory(Tree tree, CategoricalHistory history,int node, int samplingLimit) {
+		CategoricalHistory resultStates=null;
+		zeroTotals();
+		int[][] array;
+		int mappingsAdded=0;
+		if (!mappingsAvailable()) {
+			history.clone(resultStates);
+			if (resultStates instanceof mesquite.categ.lib.CategoricalHistory){
+				array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node, null);
+				if (addOneMapping(array, true)) mappingsAdded++;
+			}
+		}
+		else {
+			long numMappings = history.getNumResolutions(tree);
+			if (numMappings == MesquiteLong.infinite) {
+				for (int i=0; i<samplingLimit; i++) {
+					resultStates = (CategoricalHistory)history.getResolution(tree, resultStates, i);
+					if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+						array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node,null);
+						if (addOneMapping(array, true)) mappingsAdded++;
+					}
+				}
+			}
+			else if (MesquiteLong.isCombinable(numMappings))
+				if (numMappings<=samplingLimit) {
+					for (int i=0; i<numMappings; i++) {
+						resultStates = (CategoricalHistory)history.getResolution(tree, resultStates, i);
+						if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+							array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node,null);
+							if (addOneMapping(array, true)) mappingsAdded++;
+						}
+					}
+				}
+				else {
+					for (int i=0; i<samplingLimit; i++) {
+						resultStates = (CategoricalHistory)history.getResolution(tree, resultStates, RandomBetween.getLongStatic(0,numMappings-1));
+						if (resultStates instanceof mesquite.categ.lib.CategoricalHistory) {
+							array= ((mesquite.categ.lib.CategoricalHistory)resultStates).harvestStateChanges(tree, node, null);
+							if (addOneMapping(array, true)) mappingsAdded++;
+						}
+					}
+				}
+
+		}
+		if (mappingsAdded>0)
+			numHistories++;
+		if (mappingsAdded>0)
+			for (int i=0; i<numStates; i++)
+				for (int j=0; j<numStates; j++)
+				{
+					avg[i][j] = avg[i][j]+total[i][j]/mappingsAdded;
+					if (totalChanges[i][j]>0 && i!=j)
+						for (int k=0; k<maxChangesRecorded; k++) {
+							fractionWithAmount[i][j][k] = fractionWithAmount[i][j][k]+totalWithAmount[i][j][k]/totalChanges[i][j];
+						}
+				}
+
+	}
+
+
+	/*.................................................................................................................*/
+
+	public void cleanUp() {
+		for (int i=0; i<numStates; i++)
+			for (int j=0; j<numStates; j++) {
+				if (min[i][j]== Integer.MAX_VALUE)
+					min[i][j] = 0;
+				if (numHistories>0) {
+					avg[i][j] = avg[i][j]/numHistories;
+					if (i!=j) for (int k=0; k<maxChangesRecorded; k++) {
+						fractionWithAmount[i][j][k] = fractionWithAmount[i][j][k]/numHistories;
+					}
+				}
+			}
+	}
+
+	/*.................................................................................................................*/
+	public int[][] getMin() {
+		return min;
+	}
+	/*.................................................................................................................*/
+	public int[][] getMax() {
+		return max;
+	}
+	/*.................................................................................................................*/
+	public double[][] getAvg() {
+		return avg;
+	}
+
+	/*.................................................................................................................*/
+	public String toVerboseString(){
+		StringBuffer sb = new StringBuffer();
+		sb.append("Minimum, maximum, and average number of each kind across all mappings and trees\n");
+		sb.append("------------------------------------\n");
+		sb.append("change\tmin\tmax\tavg\n");
+		for (int i=0; i<numStates; i++)
+			for (int j=0; j<numStates; j++){
+				if (i!=j)
+					sb.append(""+i+"->"+j+" \t"+min[i][j] +"\t"+max[i][j] +"\t"+avg[i][j]+"\n"); 
+			}
+		sb.append("\n\n\nFraction of mappings on trees with specific number of changes of each kind.  Each tree is weighted equally, and within each tree, the mappings are each weighted equally. Thus, if there is only one tree then the values given are the fractions of mappings with a particular change.\n");
+		sb.append("------------------------------------\n");
+		sb.append("change\t#changes\tfraction\n");
+		for (int i=0; i<numStates; i++)
+			for (int j=0; j<numStates; j++)
+				if (i!=j) {
+					for (int k=0; k<maxChangesRecorded-1; k++) {
+						sb.append(""+i+"->"+j+" \t"+k +"\t"+fractionWithAmount[i][j][k]+"\n"); 
+					}
+					sb.append(""+i+"->"+j+" \t"+(maxChangesRecorded-1) +"+\t"+fractionWithAmount[i][j][maxChangesRecorded-1]+"\n"); 
+					sb.append("\n");
+				}
+		return sb.toString();
+	}
+
+
+
+
+
+
+}
diff --git a/Source/mesquite/categ/lib/CategStateForCharacter.java b/Source/mesquite/categ/lib/CategStateForCharacter.java
new file mode 100644
index 0000000..5c7bcb2
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategStateForCharacter.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.categ.lib;
+
+import mesquite.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+public abstract class CategStateForCharacter extends MesquiteModule {
+	boolean selectedOnly=true;
+
+	public Class getDutyClass() {
+		return CategStateForCharacter.class;
+	}
+
+	public String getDutyName() {
+ 		return "Assigns a single character state for a categorical character; e.g., for consensus sequences.";
+   	 }
+
+	public abstract void calculateState(CategoricalData data, int ic,  MesquiteTable table, CategoricalState resultState, MesquiteString resultString, MesquiteDouble fractionMatching);
+
+	/*.................................................................................................................*/
+	 public String getShortParameters() {
+		 return "";
+	 }
+
+	public boolean getSelectedOnly() {
+		return selectedOnly;
+	}
+
+	public void setSelectedOnly(boolean selectedOnly) {
+		this.selectedOnly = selectedOnly;
+	}
+
+	
+}
diff --git a/Source/mesquite/categ/lib/CategTModel.java b/Source/mesquite/categ/lib/CategTModel.java
new file mode 100644
index 0000000..05ec552
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategTModel.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**An interface for character models that contain a matrix concerning state-to-state transitions.*/
+
+public interface CategTModel extends Listenable, Listable {
+	/*.................................................................................................................*/
+	/** Returns true if size (maximum state allowed) can be set externally. */
+   	 public boolean canChangeSize();
+	/*.................................................................................................................*/
+	/** Sets maximum state allowed. */
+	public void setMaxStateDefined(int maxState);
+	/*.................................................................................................................*/
+	/** Returns maximum state allowed. */
+	public int getMaxStateDefined();
+	/*.................................................................................................................*/
+	/** Gets symbol for state. */
+	public String getStateSymbol(int state);
+	/*.................................................................................................................*/
+	/** Returns the value (cost, rate, etc.) for a transition between beginState and endState. */
+	public MesquiteNumber getTransitionValue (int beginState, int endState, MesquiteNumber result);
+	/*.................................................................................................................*/
+	/** Sets the value (cost, rate, etc.) for a transition between beginState and endState. */
+	public void setTransitionValue (int beginState, int endState, MesquiteNumber result, boolean notify);
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategTModelEditWindow.java b/Source/mesquite/categ/lib/CategTModelEditWindow.java
new file mode 100644
index 0000000..377e8f8
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategTModelEditWindow.java
@@ -0,0 +1,376 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+/*=======================================================*/
+/** A window that contains a table in which to edit a CategTModel.  Used for Stepmatrix editing, but could also be used for other similar models */
+public class CategTModelEditWindow extends TableWindow implements MesquiteListener {
+	CategTModelTable table;
+	int windowWidth = 360;
+	int windowHeight =300;
+	ToolPalette palette = null;
+	CharModelCurator curatorModule;
+	TableTool arrowTool,ibeamTool, fillTool, dropperTool;
+	MesquiteNumber fillNumber = new MesquiteNumber(0);
+	public CategTModelEditWindow (CharModelCurator curatorModule, MesquiteModule ownerModule){
+		super(ownerModule, true); 
+		this.curatorModule = curatorModule;
+		ownerModule.setModuleWindow(this);
+		setWindowSize(windowWidth, windowHeight);
+		table = new CategTModelTable(curatorModule, this, 32, 32, getBounds().width - 32, getBounds().height-32, 30);
+		getGraphicsArea().setLayout(new BorderLayout());
+		addToWindow(table);
+   	 	table.setSize(windowWidth, windowHeight);
+		String selectExplanation = "This tool selects items in the matrix.  By holding down shift while clicking, the selection will be extended from the first to the last touched cell. ";
+		selectExplanation += " A block of cells can be selected either by using shift-click to extend a previous selection, or by clicking on a cell and dragging with the mouse button still down";
+		selectExplanation += " Discontinous selections are allowed, and can be obtained by a \"meta\"-click (right mouse button click, or command-click on a MacOS system). ";
+		arrowTool = new TableTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(),"arrow.gif", 4, 2, "Select", selectExplanation, MesquiteModule.makeCommand("arrowTouchCell",  this) , MesquiteModule.makeCommand("arrowDragCell",  this), MesquiteModule.makeCommand("arrowDropCell",  this));
+		arrowTool.setIsArrowTool(true);
+		arrowTool.setUseTableTouchRules(true);
+		addTool(arrowTool);
+  	 	setCurrentTool(arrowTool);
+ 		if (arrowTool!=null)
+ 			arrowTool.setInUse(true);
+		ibeamTool = new TableTool(this, "ibeam", MesquiteModule.getRootImageDirectoryPath(),"ibeam.gif", 7,7,"Edit", "This tool can be used to edit the contents of cells in the matrix.", MesquiteModule.makeCommand("editCell",  (Commandable)table) , null, null);
+		addTool(ibeamTool);
+		ibeamTool.setWorksOnRowNames(true);
+
+		fillTool = new TableTool(this, "fill", MesquiteModule.getRootImageDirectoryPath(),"bucket.gif", 13,14,"Fill with 1", "This tool fills selected cells with text.  The text to be used can be determined by using the dropper tool.", MesquiteModule.makeCommand("fillTouchCell",  this) , null, null);
+		fillTool.setOptionsCommand(MesquiteModule.makeCommand("touchTool",  this));
+		dropperTool = new TableTool(this, "dropper", MesquiteModule.getRootImageDirectoryPath(),"dropper.gif", 1,14,"Copy value", "This tool fills the paint bucket with the text in the cell touched on", MesquiteModule.makeCommand("dropperTouchCell",  this) , null, null);
+		addTool(fillTool);
+		addTool(dropperTool);
+   	 	setShowExplanation(true);
+   	 	setShowAnnotation(true);
+		resetTitle();
+		table.setVisible(true);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Edit " + curatorModule.getNameOfModelClass()); 
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Fills the touched cell with current paint", "[column][row]", commandName, "fillTouchCell")) {
+   	 		if (table!=null && fillNumber !=null && table.getModel()!=null){
+	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   	 		String entry = fillNumber.toString();
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+	   			if (!table.rowLegal(row)|| !table.columnLegal(column))
+	   				return null;
+	   			if (table.anyCellSelected()) {
+		   			if (table.isCellSelected(column, row)) {
+						for (int i=0; i<table.getNumColumns(); i++)
+							for (int j=0; j<table.getNumRows(); j++)
+								if (table.isCellSelected(i,j)) {
+									table.returnedMatrixTextNotify(i,j, entry,false);
+								}
+		 	   			table.repaintAll();
+					}
+				}
+				else if (table.anyRowSelected()) {
+		   			if (table.isRowSelected(row)) {
+						for (int j=0; j<table.getNumRows(); j++) {
+							if (table.isRowSelected(j))
+								for (int i=0; i<table.getNumColumns(); i++)
+									table.returnedMatrixTextNotify(i,j, entry,false);
+						}
+		 	   			table.repaintAll();
+					}
+				}
+				else if (table.anyColumnSelected()) {
+		   			if (table.isColumnSelected(column)) {
+						for (int i=0; i<table.getNumColumns(); i++){
+							if (table.isColumnSelected(i))
+								for (int j=0; j<table.getNumRows(); j++) 
+									table.returnedMatrixTextNotify(i,j, entry,false);
+						}
+		 	   			table.repaintAll();
+					}
+				}
+				else {
+					table.returnedMatrixTextNotify(column, row, entry, false);
+		 	   		table.repaintAll();
+				}
+				((CharacterModel)table.getModel()).notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, true);
+				((CharacterModel)table.getModel()).notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, false);
+
+			}
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Queries the user what paint to use", null, commandName, "touchTool")) {
+   	 		if (table!=null){
+				String fillString = MesquiteString.queryString(this, "Fill value", "Value with which to fill using paint bucket:", "");
+		   		if (StringUtil.blank(fillString))
+		   			return null;
+		   		fillNumber.setValue(fillString);
+	   			fillTool.setDescription("Fill with \"" + fillNumber.toString()+ " \"");
+	   			dropperTool.setDescription("Copy value (current: " + fillNumber.toString() + ")");
+				toolTextChanged();
+			}
+    	 	}
+   	 	else if (checker.compare(this.getClass(), "Fills the paint bucket with the string of the selected cell", "[column][row]", commandName, "dropperTouchCell")) {
+   	 		if (table!=null){
+	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+	   			if (!table.rowLegal(row)|| !table.columnLegal(column))
+	   				return null;
+	   			String fillString = table.getMatrixText(column, row);
+		   		fillNumber.setValue(fillString);
+	   			fillTool.setDescription("Fill with \"" + fillNumber.toString()+ " \"");
+	   			dropperTool.setDescription("Copy value (current: " + fillNumber.toString() + ")");
+				toolTextChanged();
+			}
+    	 	}
+
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	return null;
+   	 }
+    CategTModel model = null;
+    public void dispose(){
+		if (model != null && model instanceof FileElement && ((FileElement)model).getProject() != null)
+			((FileElement)model).getProject().getCentralModelListener().removeListener(this);
+
+    	super.dispose();
+    }
+	/*.................................................................................................................*/
+	public void setModel(CategTModel model) {
+		table.setModel(model);
+		this.model= model;
+		setTitle("Edit " + curatorModule.getNameOfModelClass()+ ": " + model.getName());
+
+		if (model instanceof FileElement && ((FileElement)model).getProject() != null)
+			((FileElement)model).getProject().getCentralModelListener().addListener(this);
+		contentsChanged();
+	}
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification){
+	
+		if (obj == model)
+			contentsChanged();
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == table.getModel() && ownerModule != null)
+			ownerModule.windowGoAway(this);
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+		
+	}
+
+   	public void setMaxState(int maxState){
+   		table.setMaxState(maxState);
+   	}
+   	public void setDiagnonalEditable(boolean editable){
+   		table.setDiagnonalEditable(editable);
+   	}
+   	public boolean getDiagnonalEditable(){
+   		return table.getDiagnonalEditable();
+   	}
+	public void windowResized() {
+		super.windowResized();
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+   	 	if (table!=null && ((getHeight()!=windowHeight) || (getWidth()!=windowWidth))) {
+   	 		windowHeight =getHeight();
+   	 		windowWidth = getWidth();
+   	 		table.setSize(windowWidth, windowHeight);
+   	 	}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public MesquiteTable getTable(){
+		return table;
+	}
+}
+
+	/*=======================================================*/
+class CategTModelTable extends MesquiteTable {
+	CharModelCurator curatorModule;
+	CategTModel model;
+	MesquiteWindow window;
+	boolean diagonalEditable = true;
+	
+	public CategTModelTable (CharModelCurator curatorModule, MesquiteWindow window, int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int taxonNamesWidth) {
+		super(numRowsTotal, numColumnsTotal, totalWidth, totalHeight, taxonNamesWidth, ColorDistribution.getColorScheme(curatorModule), true, true);
+		this.window= window;
+		this.curatorModule=curatorModule;
+		frameColumnNames=false;
+		frameRowNames=false;
+
+		setEditable(true, false, false, false);
+		setSelectable(true, false, false, false, false, false);
+		setColumnWidthsUniform(48);
+	}
+   	public void setDiagnonalEditable(boolean editable){
+   		diagonalEditable = editable;
+   	}
+   	public boolean getDiagnonalEditable(){
+   		return diagonalEditable;
+   	}
+   	public void setMaxState(int maxState){
+   		model.setMaxStateDefined(maxState);
+   		setNumColumns(maxState+1);
+   		setNumRows(maxState+1);
+   		repaintAll();
+   	}
+	public CategTModel getModel() {
+		return model;
+	}
+	public void setModel(CategTModel model) {
+		this.model = model;
+		if (getNumRows() != model.getMaxStateDefined()+1)
+			setNumRows(model.getMaxStateDefined()+1);
+		if (getNumColumns() != model.getMaxStateDefined()+1)
+			setNumColumns(model.getMaxStateDefined()+1);
+		repaint();
+	}
+	/** Called after editing a cell, passing the String resulting. 
+	Can be overridden in subclasses to respond to editing.*/
+	public void returnedMatrixTextNotify(int column, int row, String s,  boolean notify){ 
+		if (column==row && !diagonalEditable)
+			return;
+		if (StringUtil.blank(s))
+			return;
+		boolean explicitlyUnassigned = ("unassigned".equalsIgnoreCase(s) || "estimate".equalsIgnoreCase(s) || "?".equalsIgnoreCase(s));
+		
+		MesquiteNumber i = new MesquiteNumber();
+		MesquiteNumber c = new MesquiteNumber();
+		i.setValue(s);
+		if (i.isCombinable() || i.isInfinite() || explicitlyUnassigned){
+			if (!i.equals(model.getTransitionValue(row,column, c))){
+				model.setTransitionValue(row,column, i, notify);
+				repaint();
+			}
+		}
+			
+	}
+	/** Called after editing a cell, passing the String resulting. 
+	Can be overridden in subclasses to respond to editing.*/
+	public void returnedMatrixText(int column, int row, String s){ 
+		if (column==row && !diagonalEditable)
+			return;
+		if (StringUtil.blank(s))
+			return;
+		boolean explicitlyUnassigned = ("unassigned".equalsIgnoreCase(s) || "estimate".equalsIgnoreCase(s) || "?".equalsIgnoreCase(s));
+		
+		MesquiteNumber i = new MesquiteNumber();
+		MesquiteNumber c = new MesquiteNumber();
+		i.setValue(s);
+		if (i.isCombinable() || i.isInfinite() || explicitlyUnassigned){
+			if (!i.equals(model.getTransitionValue(row,column, c))){
+				model.setTransitionValue(row,column, i, true);
+				repaint();
+			}
+		}
+			
+	}
+	public boolean useString(int column, int row){
+		return false;
+	}
+	
+	public void drawMatrixCell(Graphics g, int x, int y,  int w, int h, int column, int row, boolean selected){  
+		Color fontColor, bgColor;
+		if (selected)
+			fontColor = Color.white;
+		else 
+			fontColor = Color.black;
+		if (column==row) {
+			if (diagonalEditable)
+				bgColor = ColorDistribution.veryLightGray;
+			else 
+				bgColor = Color.gray;
+			g.setColor(bgColor);
+			g.fillRect(x+1,y+1,w-2,h-2);
+			g.setColor(fontColor);
+			g.drawString(model.getTransitionValue(row,column, null).toString(), x+2, y+h-2);
+			
+		}
+		else {
+			if (selected)
+				bgColor = Color.black;
+			else 
+				bgColor = Color.white;
+			g.setColor(bgColor);
+			g.fillRect(x+1,y+1,w-2,h-2);
+			g.setColor(fontColor);
+			g.drawString(model.getTransitionValue(row,column, null).toString(), x+2, y+h-2);
+		}
+	}
+	
+	/*...............................................................................................................*/
+	public  void drawCornerCell(Graphics g, int x, int y,  int w, int h){
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int lineHeight = fm.getAscent() + fm.getDescent() + 4;
+		g.drawString("From", x+3, y+h-fm.getDescent());
+		g.drawString("To", x+w -fm.stringWidth("To "), y+lineHeight);
+	}
+	public String getMatrixText(int column, int row){
+		if (column==row) {
+			return model.getTransitionValue(row,column, null).toString();
+		}
+		else  {
+			return model.getTransitionValue(row,column, null).toString();
+		}
+	}
+	public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column){
+		//g.clipRect(x,y,w,h);
+		g.drawString(model.getStateSymbol(column), x+2, y+h-2);
+		//g.clipRect();
+		
+	}
+	public void drawRowNameCell(Graphics g, int x, int y,  int w, int h, int row){
+		g.drawString(model.getStateSymbol(row), x+2, y+h-2);
+	}
+	/*...............................................................................................................*/
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (column==row && !diagonalEditable)
+			return;
+		if (window.getCurrentTool().isArrowTool()) 
+			super.cellTouched(column, row, regionInCellH, regionInCellV, modifiers, clickCount);
+		else
+			((TableTool)window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		repaintAll();
+	}
+	/*...............................................................................................................*/
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (window.getCurrentTool().isArrowTool()) 
+			super.cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+		else
+		((TableTool)window.getCurrentTool()).cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+	}
+	/*...............................................................................................................*/
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (column==row && !diagonalEditable)
+			return;
+		if (window.getCurrentTool().isArrowTool()) 
+			super.cellDropped(column, row,  regionInCellH,  regionInCellV, modifiers);
+		else
+		  ((TableTool)window.getCurrentTool()).cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategoricalAdjustable.java b/Source/mesquite/categ/lib/CategoricalAdjustable.java
new file mode 100644
index 0000000..a8353a6
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalAdjustable.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public class CategoricalAdjustable extends CategoricalDistribution  implements AdjustableDistribution {
+	public long states[];
+	private int watchPoint=-1;
+	protected int  numNodes=0;  
+	
+	public CategoricalAdjustable (Taxa taxa, int num) {
+		super(taxa);
+		this.numNodes=num;
+		states = new long[numNodes];
+		deassignStates();
+		if (watchPoint>0)
+			MesquiteMessage.println("CategoricalAdjustable:  new states while watchpoint on for " + watchPoint);
+	}
+	public CategoricalAdjustable (Taxa taxa) {
+		super(taxa);
+	}
+	
+	 
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** get number of taxa available in this categorical character.*/
+	public int getNumTaxa() {
+		return numNodes;
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** get number of nodes available in this categorical character.*/
+	public int getNumNodes() {
+		return numNodes;
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/**set all states to missing (unassigned)*/
+	public void deassignStates(){
+		for (int i=0; i<numNodes; i++)
+			states[i]=CategoricalState.unassigned;
+		frequencies = null;
+		/*if (frequencies != null)
+			for (int i=0; i<frequencies.length; i++)
+				for (int j=0; j<frequencies[i].length;j++) 
+					frequencies[i][j] = MesquiteDouble.unassigned;
+		*/	
+		if (watchPoint>0)
+			MesquiteMessage.println("CategoricalAdjustable:  zero states while watchpoint on for " + watchPoint);
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** Set states array to be one passed */
+	public void setStates (long[] sStates) {
+		states = sStates;
+		numNodes = sStates.length;
+		if (watchPoint>0)
+			MesquiteMessage.println("CategoricalAdjustable:  reset states while watchpoint on for " + watchPoint);
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** get stateset at node N */
+	public long getState (int N) {
+		if (checkIllegalNode(N, 4))
+			return CategoricalState.unassigned;
+		return CategoricalState.dataBitsMask & states[N];
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** sets state at node N to stateset passed */
+	public void setState (int N, long d) {
+		if (checkIllegalNode(N, 7))
+			return;
+		if (N==watchPoint)
+			MesquiteMessage.println("CategoricalAdjustable:  attempt to set state of watched node " + N);
+		states[N] = d;
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** sets state at node N to stateset passed */
+	public void setCharacterState (int N, CharacterState cs) {
+		if (checkIllegalNode(N, 7))
+			return;
+		if (cs == null || !(cs instanceof CategoricalState))
+			return; //TODO: warning
+		if (N==watchPoint)
+			MesquiteMessage.println("CategoricalAdjustable:  attempt to set state of watched node " + N);
+		states[N] = ((CategoricalState)cs).getValue();
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/**set watchpoint at node N.  Subsequently moniters to see if its value changed and gives notification.  May not work well (changes may not be checked in all places.*/
+	public void setWatchPoint (int N) {
+		if (checkIllegalNode(N, 6))
+			return;
+		watchPoint=N;
+		MesquiteMessage.println("Watchpoint set for node " + N);
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/**Trade states of nodes it and it2 */
+	public void tradeStatesBetweenTaxa(int it, int it2) {
+		if (checkIllegalNode(it, 9127) && checkIllegalNode(it, 9126))
+			return;
+		long temp = states[it];
+		states[it] =  states[it2];
+		states[it2] = temp;
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public AdjustableDistribution adjustSize(Taxa taxa) {
+		if (taxa.getNumTaxa() == this.getNumTaxa())
+			return this;
+		else {
+			CategoricalAdjustable soc = makeAdjustable(taxa);
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			((CharacterStates)soc).setExplanation(getExplanation());
+			return soc;
+		}
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/CategoricalData.java b/Source/mesquite/categ/lib/CategoricalData.java
new file mode 100644
index 0000000..1ee3ca7
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalData.java
@@ -0,0 +1,2589 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CharacterData for data stored as Categorical sets (e.g, "{0, 2}").  Associated with the CharacterState subclass CategoricalState.*/
+public class CategoricalData extends CharacterData {
+	private String[][] stateNames;
+	private String[][] stateNotes;
+	protected char[] symbols;
+	protected final static char[] defaultSymbols;
+	public static String DATATYPENAME = "Standard Categorical Data";
+
+	private long[][] matrix;
+	private short[][] matrixShort;
+	private static Vector defaultModels;
+	protected static char ANDseparator = '&';  //why static?
+	protected static char ORseparator = '/';
+	protected String puncString;
+	private int maxSymbolDefined = -1;
+	private static boolean permitShortMatrices = true;
+	private Object[][] stateAnnotations; //one vector (possibly) per state per character
+
+	static {
+		defaultModels= new Vector(2);
+		defaultSymbols = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p' , 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+	}
+
+	public CategoricalData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars, taxa);
+		setUseDiagonalCharacterNames(true);
+		symbols = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p' , 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+		try {
+			puncString = "" + ANDseparator + ORseparator + getUnassignedSymbol() + getInapplicableSymbol();
+			if (permitShortMatrices && CategoricalState.compressibleToShort(getDefaultState())) {
+				matrixShort = new short[ numChars][numTaxa];
+				for (int it=0; it<numTaxa; it++)
+					for (int ic=0; ic<numChars; ic++)
+						matrixShort[ic][it] = CategoricalState.compressToShort(getDefaultState());
+			}
+			else {
+				matrix = new long[ numChars][numTaxa];
+				for (int it=0; it<numTaxa; it++)
+					for (int ic=0; ic<numChars; ic++)
+						matrix[ic][it] = getDefaultState();
+			}
+		}
+		catch (OutOfMemoryError e){
+			MesquiteMessage.warnProgrammer("Sorry, the Character Matrix could not be created because of lack of memory.  See file memory.txt in the Mesquite_Folder.");
+			discreetAlert("Sorry, the Character Matrix could not be created because of lack of memory.  See file memory.txt in the Mesquite_Folder.");
+			matrix = null;
+			numChars = 0;
+			numTaxa = 0;
+		}
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixCategSmall.gif";
+	}
+
+	/** true if the matrix is a valid one */
+	public boolean isValid(){
+		return (matrix!=null || matrixShort!=null) && numTaxa>0; // && numChars>0;
+	}
+
+	public int getNumDataBlocks(int it, int icStart, int icEnd) {
+		int count=0;
+		boolean inBlock=false;
+		for (int ic = icStart; ic < getNumChars() && ic<=icEnd; ic++) {
+			if (!isInapplicable(ic, it) && !inBlock){  // start of block
+				inBlock=true;
+				count++;
+			} else if (isInapplicable(ic,it) && inBlock){  // block has ended
+				inBlock=false;
+			}
+		}
+		return count;
+	}
+	
+	public void getDataBlockBoundaries(int it, int icStart, int icEnd, int whichBlock, MesquiteInteger blockStart, MesquiteInteger blockEnd) {
+		if (blockStart==null || blockEnd==null) 
+			return;
+		int count=0;
+		boolean inBlock=false;
+		for (int ic = icStart; ic < getNumChars() && ic<=icEnd; ic++) {
+			if (!isInapplicable(ic, it) && !inBlock){  // start of block
+				inBlock=true;
+				count++;
+				if (count==whichBlock) {
+					blockStart.setValue(ic);
+				}
+			} else if (isInapplicable(ic,it) && inBlock){  // block has ended
+				inBlock=false;
+				if (count==whichBlock) {
+					blockEnd.setValue(ic);
+				}
+			}
+		}
+		if (blockStart.isCombinable()&&!blockEnd.isCombinable()) // end didn't get assigned, but start did
+			blockEnd.setValue(getNumChars()-1);
+	}
+
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		if (StringUtil.blank(s))
+			return null;
+		String list = "";
+		String fc =""; //to receive the direct command
+		int numFound = 0;
+		for (int ic=0; ic< getNumChars(); ic++){
+			String name = getCharacterName(ic);
+
+			String statesString = "";
+
+			for (int k = 0; k<= maxStateWithName(ic); k++){
+				if (hasStateName(ic, k)){
+					String stateName = getStateName(ic, k);
+					if (StringUtil.foundIgnoreCase(stateName, s)){
+						statesString += "<li>State " + k + ": <strong>" + StringUtil.protectForXML(stateName) + "</strong>. <a href=\"selectCharacter:" + ic+ " " + getID() + "\">Touch character</a></li>";
+						numFound++;
+						fc = "selectCharacter:" + ic+ " " + getID();
+					}
+				}
+			}
+			if (!StringUtil.blank(statesString))
+				statesString = "<ul>" + statesString + "</ul>";
+
+			if (name != null && StringUtil.foundIgnoreCase(name, s)){
+				list += "<li>Character " + (ic+1) + ": <strong>" + StringUtil.protectForXML(name) + "</strong>. <a href=\"selectCharacter:" + ic+ " " + getID() + "\">Touch character</a></li>";
+				numFound++;
+				fc = "selectCharacter:" + ic+ " " + getID() ;
+			}
+			else if (!StringUtil.blank(statesString)){
+				if (name != null)
+					list += "<li>Character " + (ic+1) + ": <strong>" + StringUtil.protectForXML(name) + "</strong>. " + statesString + "</li>";
+				else
+					list += "<li>Character " + (ic+1) + ". " + statesString + "</li>";
+			}
+
+		}
+
+		if (commandResult != null && numFound == 1)
+			commandResult.setValue(fc);
+		if (StringUtil.blank(list))
+			return list;
+		return "<h2>Characters of matrix <strong>" + StringUtil.protectForXML(getName()) + "</strong></h2><ul>" + list + "</ul>";
+	}
+	public boolean usingShortMatrix(){
+		return matrix == null;
+	}
+	private void upgradeToFullMatrix(){
+		matrix = new long[ numChars][numTaxa];
+		for (int ic=0; ic<numChars && ic<matrixShort.length; ic++)
+			for (int it=0; it<numTaxa && it<matrixShort[ic].length; it++)
+				matrix[ic][it] = CategoricalState.expandFromShort(matrixShort[ic][it]);
+		matrixShort = null;
+		setDirty(true);
+		incrementStatesVersion();
+	}
+	public boolean longCompressibleToShort(){
+		if (usingShortMatrix())
+			return false;
+		for (int ic=0; ic<numChars && ic<matrix.length; ic++)
+			for (int it=0; it<numTaxa && it<matrix[ic].length; it++)
+				if (!CategoricalState.compressibleToShort(matrix[ic][it]))
+					return false;
+		return true;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long getDefaultState(){
+		return CategoricalState.unassigned;
+	}
+	/** sets the state of character ic in taxon it to the default state (which in some circumstances may be inapplicable, e.g. gaps for molecular data)*/
+	public  void deassign(int ic, int it){
+		setState(ic, it, getDefaultState());
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns an array of longs for the cells in taxon it, starting at character icStart, for length "length" */
+	public long[] getLongArray(int icStart, int length, int it, boolean includeGaps) {
+		long[] array= new long[length];
+		for (int ic=0; ic<length; ic++) 
+			array[ic] = CategoricalState.inapplicable;
+		int count=0;
+		for (int ic=icStart; ic<getNumChars() && count<length; ic++)
+			if (includeGaps || !isInapplicable(ic,it)){
+				array[count] = getState(ic,it);
+				count++;
+			}
+		return array;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public void dispose(){
+		super.dispose();
+		matrix = null;
+		matrixShort = null;
+		stateNames = null;
+		stateAnnotations = null;
+		stateNotes = null;
+		symbols = null;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return CategoricalState.class;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return DATATYPENAME;
+	}
+
+	public void copyDataBlock(CharacterData sourceData, int icStart, int icEnd, int itStart, int itEnd){
+		if (sourceData == null)
+			return;
+		for (int ic=icStart; ic<=icEnd; ic++){
+			for (int it=itStart; it<=itEnd; it++) {
+				int itSource = it-itStart;
+				int icSource = ic-icStart;
+				if (itSource<sourceData.getNumTaxa() && icSource<sourceData.getNumChars())
+					setState(ic, it, ((CategoricalData)sourceData).getStateRaw(icSource, itSource)); 
+			}
+		}
+		resetCellMetadata();
+
+	}
+	/** Copies the block of data from the source to this data object */
+	public void copyDataBlock(CharacterData sourceData, int icSourceStart,  int itSourceStart, int icStart, int icEnd, int itStart, int itEnd){
+		if (sourceData == null)
+			return;
+		
+		for (int ic=icStart; ic<=icEnd; ic++){
+			for (int it=itStart; it<=itEnd; it++) {
+				int itSource = it-itStart+itSourceStart;
+				int icSource = ic-icStart+icSourceStart;
+				if (it<getNumTaxa() && ic<getNumChars() && itSource<sourceData.getNumTaxa() && icSource<sourceData.getNumChars())
+					setState(ic, it, ((CategoricalData)sourceData).getStateRaw(icSource, itSource)); 
+			}
+		}
+		resetCellMetadata();
+
+	}
+
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData, boolean allowDifferentSizes){
+		if (sourceData==null)
+			return;
+		if ((sourceData.getNumTaxa()==getNumTaxa() && sourceData.getNumChars() == getNumChars()) || allowDifferentSizes) {
+			for (int ic=0; ic<numChars; ic++){
+				for (int it=0; it<numTaxa; it++) {
+					if (it>=sourceData.getNumTaxa() || ic>=sourceData.getNumChars())
+						setState(ic, it, getDefaultState()); 
+					else
+						setState(ic, it, ((CategoricalData)sourceData).getStateRaw(ic, it)); 
+				}
+			}
+			resetCellMetadata();
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData){
+		copyData(sourceData,false);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**returns a copy of simply the data matrix with symbols */
+	public CategoricalData getDataCopy(){
+		CategoricalData data = (CategoricalData)makeCharacterData(numTaxa, numChars);
+		if (symbols!=null)
+			for (int i=0; i<=CategoricalState.maxCategoricalState && i<symbols.length; i++) {
+				data.setSymbolDirect(i, symbols[i]);
+			}
+		for (int ic=0; ic<numChars; ic++){
+			for (int it=0; it<numTaxa; it++) {
+				data.setState(ic, it, getStateRaw(ic, it)); 
+			}
+		}
+		data.resetCellMetadata();
+		return data;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**clone this CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneData(){
+		CategoricalData data = new CategoricalData(matrixManager, numTaxa, numChars, getTaxa());
+		if (symbols!=null)
+			for (int i=0; i<=CategoricalState.maxCategoricalState && i<symbols.length; i++) {
+				data.setSymbolDirect(i, symbols[i]);
+			}
+		for (int ic=0; ic<numChars; ic++){
+			if (hasStateNames() && hasStateNames(ic))
+				for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+					if (hasStateName(ic,i))
+						data.setStateName(ic,i,getStateName(ic,i));
+			if (hasStateNotes() && hasStateNotes(ic))
+				for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+					if (hasStateNote(ic,i))
+						data.setStateNote(ic,i,getStateNote(ic,i));
+			for (int it=0; it<numTaxa; it++) {
+				data.setState(ic, it, getStateRaw(ic, it)); 
+			}
+			if (getSelected(ic))
+				data.setSelected(ic, true);
+		}
+		data.resetCellMetadata();
+		return data;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**clone a portion of CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneDataBlock(int icStart, int icEnd, int itStart, int itEnd){
+		int blockChars = icEnd-icStart+1;
+		int blockTaxa = itEnd-itStart+1;
+		boolean[] taxaToClone = new boolean[getNumTaxa()];
+		for (int it=0; it<getNumTaxa(); it++) {
+			taxaToClone[it] = it>=itStart && it<=itEnd;
+		}
+		Taxa taxa = getTaxa().cloneTaxa(taxaToClone);
+
+		CategoricalData data = new CategoricalData(matrixManager, blockTaxa, blockChars, taxa);
+		if (symbols!=null)
+			for (int i=0; i<=CategoricalState.maxCategoricalState && i<symbols.length; i++) {
+				data.setSymbolDirect(i, symbols[i]);
+			}
+		for (int ic=icStart; ic<=icEnd; ic++){
+			if (hasStateNames())
+				for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+					data.setStateName(ic-icStart,i,getStateName(ic,i));
+			for (int it=itStart; it<=itEnd; it++) {
+				data.setState(ic-icStart, it-itStart, getStateRaw(ic, it)); 
+			}
+			if (getSelected(ic))
+				data.setSelected(ic-icStart, true);
+		}
+		data.resetCellMetadata();
+		return data;
+	}
+
+	public int getNumTaxa(){
+		return getNumTaxa(true);
+	}
+	public int getNumTaxa(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumTaxa(notifyIfError);
+		if (!notifyIfError)
+			return n;
+		if (matrix == null && matrixShort == null)
+			dataIntegrityAlert("Categorical data with null internal matrix. getNumTaxa() = " + n + " name " + getName() + " file " + getFile());
+		else if (MesquiteThread.isThreadBelongingToMesquite() && MesquiteThread.numFilesBeingRead==0 ){  //since files read on other thread, suppress warnings
+			if (matrix != null && matrix.length>0 && matrix[0] !=null && matrix[0].length != n)
+				dataIntegrityAlert("Categorical matrix with incorrect record of number of taxa. getNumTaxa() = " + n + " matrix[0].length " + matrix[0].length + " name " + getName() + " file " + getFile());
+			else if (matrixShort != null && matrixShort.length>0 && matrixShort[0] !=null && matrixShort[0].length != n)
+				dataIntegrityAlert("Categorical matrix with incorrect record of number of taxa. getNumTaxa() = " + n + " matrixShort[0].length " + matrixShort[0].length + " name " + getName() + " file " + getFile());
+		}
+		return n;
+	}
+	public int getNumChars(){
+		return getNumChars(true);
+	}
+	public int getNumChars(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumChars(notifyIfError);
+		if (matrix == null && matrixShort == null){
+			if (notifyIfError)
+				dataIntegrityAlert("Categorical data with null internal matrix. getNumChar() = " + n  + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove + " name " + getName() + " file " + getFile());
+			return 0;
+		}
+		else if (matrix != null && matrix.length !=n){
+			if (MesquiteThread.isThreadBelongingToMesquite() && MesquiteThread.numFilesBeingRead==0 && notifyIfError && !charNumChanging) //since files read on other thread, suppress warnings
+				dataIntegrityAlert("Categorical matrix with incorrect record of number of characters. getNumChar() = " + n + " matrix.length " + matrix.length + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove + " name " + getName() + " file " + getFile());
+			if (matrix.length>n)
+				return n;
+			else
+				return matrix.length;
+		}
+		else if (matrixShort != null && matrixShort.length !=n){
+			if (MesquiteThread.isThreadBelongingToMesquite() && MesquiteThread.numFilesBeingRead==0 && notifyIfError && !charNumChanging) //since files read on other thread, suppress warnings
+				dataIntegrityAlert("Categorical matrix with incorrect record of number of characters. getNumChar() = " + n + " matrixShort.length " + matrixShort.length + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove + " name " + getName() + " file " + getFile());
+			if (matrixShort.length>n)
+				return n;
+			else
+				return matrixShort.length;
+		}
+		return n;
+	}
+
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/**recodes stateA to stateB in character IC*/
+	public  boolean recodeStates(int ic, long[] rules, int maxState){
+		if (ic<0 || ic>= numChars)
+			return false;
+		//first, handle state names and notes
+		if (this.getClass() == CategoricalData.class) {
+			String[] oldStateNames = null;
+			String[] oldStateNotes = null;
+			AttachedNotesVector[] oldStateAnnotations = null;
+			if (stateNames != null && stateNames[ic] != null) {
+				oldStateNames = new String[stateNames[ic].length];
+				for (int is = 0; is < stateNames[ic].length; is++)
+					if (stateNames[ic][is]!=null)
+						oldStateNames[is] = new String(stateNames[ic][is]);
+				stateNames[ic] = null; //wipe out in preparation for new
+			}
+			if (stateNotes!= null && stateNotes[ic] != null) {
+				oldStateNotes = new String[stateNotes[ic].length];
+				for (int is = 0; is < stateNotes[ic].length; is++)
+					if (stateNotes[ic][is]!=null)
+						oldStateNotes[is] = new String(stateNotes[ic][is]);
+				stateNotes[ic] = null;
+			}
+			if (stateAnnotations!= null && stateAnnotations[ic] != null) {
+				oldStateAnnotations = new AttachedNotesVector[stateAnnotations[ic].length];
+				for (int is = 0; is< stateAnnotations[ic].length; is++) {
+					if (stateAnnotations[ic][is] != null)
+						oldStateAnnotations[is] =  ((AttachedNotesVector)stateAnnotations[ic][is]).cloneVector();
+					stateAnnotations[ic][is] = null;
+				}
+			}
+
+			//use rules to assign new state names and notes
+			for (int e=0; e<= CategoricalState.maxCategoricalState; e++) {
+				long recodeE = rules[e]; //this is the state set that state e would be recoded to.  It 
+				if (recodeE != CategoricalState.unassigned && recodeE != CategoricalState.inapplicable){ //recoded not to unassigned or inapp., otherwise state name and notes are lost
+					for (int e2=0; e2<= CategoricalState.maxCategoricalState; e2++) {
+						//about to recode state e2 to state recodeE
+						if (CategoricalState.isElement(recodeE, e2)){  
+							if (oldStateNames != null && e< oldStateNames.length && oldStateNames[e] != null) {
+								String name = getStateName(ic, e2, true);
+								if (name != null)
+									name += "-" + oldStateNames[e];
+								else
+									name = oldStateNames[e];
+								setStateName(ic, e2, name);
+							}
+							if (oldStateNotes != null && e< oldStateNotes.length && oldStateNotes[e] != null) {
+								String note = getStateNote(ic, e2);
+								if (note != null)
+									note += "-" + oldStateNotes[e];
+								else
+									note = oldStateNotes[e];
+								setStateNote(ic, e2, note);
+							}
+							if (oldStateAnnotations != null && e < oldStateAnnotations.length && oldStateAnnotations[e] != null){
+								AttachedNotesVector anv = getStateAnnotationsVector(ic, e2);
+								if (anv != null) {
+									anv.concatenate(oldStateAnnotations[e]);
+									anv.notifyOwner(MesquiteListener.ANNOTATION_CHANGED);
+								}
+								else 
+									setStateAnnotationsVector(ic, e2, oldStateAnnotations[e]);
+
+
+
+							}
+						}
+					}
+				}
+			}
+
+
+		}
+
+		for (int it=0; it<getNumTaxa(); it++){
+			long state = getState(ic, it);
+			if (state == CategoricalState.unassigned){
+				if (rules[maxState+1] != CategoricalState.unassigned)
+					setState(ic, it, rules[maxState+1]);
+			}
+			else if (state == CategoricalState.inapplicable){
+				if (rules[maxState+2] != CategoricalState.inapplicable)
+					setState(ic, it, rules[maxState+2]);
+			}
+			else {
+				long newCoding = (~CategoricalState.statesBitsMask) & state;  //begin with uncertain bits etc.
+				for (int e=0; e<= CategoricalState.maxCategoricalState; e++) {
+					if (((1L<<e)&state)!=0) {  //test bit
+						newCoding |= rules[e]; //add corresponding bit from rules
+					}
+				}
+				if ((newCoding & CategoricalState.statesBitsMask)== 0L) {
+					if ((newCoding & CategoricalState.unassigned) != 0L)
+						newCoding = CategoricalState.unassigned;
+					else
+						newCoding = CategoricalState.inapplicable;
+				}
+				setState(ic, it, newCoding);
+
+			}
+		}
+		return true;
+
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**swaps characters first and second*/
+	public  boolean swapAssociated(int first, int second){
+		if (first<0 || first >= numChars)
+			return false;
+		if (second<0 || second >= numChars)
+			return false;
+
+		return super.swapParts(first,second);
+
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**swaps characters first and second*/
+	public  boolean swapParts(int first, int second){
+		if (first<0 || first >= numChars)
+			return false;
+		if (second<0 || second >= numChars)
+			return false;
+		if (!usingShortMatrix())
+			Long2DArray.swapColumns(matrix, first, second);
+		else
+			Short2DArray.swapColumns(matrixShort, first, second);
+		incrementStatesVersion();
+		StringArray.swapColumns(stateNames, first, second);
+		StringArray.swapColumns(stateNotes, first, second);
+		Object2DArray.swapColumns(stateAnnotations, first, second);
+
+		return super.swapParts(first,second);
+
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**move num characters starting at first to just after character justAfter */
+	public  boolean moveParts(int first, int num, int justAfter){
+		if (justAfter<0)
+			justAfter = -1;
+		else if (justAfter>=numChars)
+			justAfter = numChars-1;
+		if (first<0 || first >= numChars)
+			return false;
+		if (num<=0)
+			return false;
+		if (first + num>numChars)
+			return false;
+		if (!usingShortMatrix())
+			Long2DArray.moveColumns(matrix, first, num, justAfter);
+		else
+			Short2DArray.moveColumns(matrixShort, first, num, justAfter);
+		incrementStatesVersion();
+		StringArray.moveColumns(stateNames, first, num, justAfter);
+		StringArray.moveColumns(stateNotes, first, num, justAfter);
+		Object2DArray.moveColumns(stateAnnotations, first, num, justAfter);
+
+		return super.moveParts(first,num,justAfter);
+
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Adds num characters after position "starting"; returns true iff successful.*/
+	public  boolean addParts(int starting, int num){
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+
+		try {
+
+			incrementStatesVersion();
+			if (!usingShortMatrix())
+				matrix = Long2DArray.addColumns(matrix, numTaxa, getDefaultState(), starting, num);
+			else
+				matrixShort = Short2DArray.addColumns(matrixShort, numTaxa, CategoricalState.compressToShort(getDefaultState()), starting, num);
+
+			//numChars = newNumChars; don't do this since addCharactersAdjust needs to remember old number
+			if (stateNames!=null){
+				String[][] newStateNames = new String[newNumChars][];
+				for (int i=0; i<=starting; i++) {
+					newStateNames[i] = stateNames[i];
+				}
+				for (int i=0; i<num; i++) {
+					newStateNames[starting + i + 1] = null;
+				}
+				for (int i=0; i<numChars-starting-1; i++) {
+					newStateNames[i +starting+num+1] = stateNames[starting + i+1];
+				}
+				stateNames = newStateNames;
+			}
+			if (stateNotes !=null){
+				String[][] newStateNotes = new String[newNumChars][];
+				for (int i=0; i<=starting; i++) {
+					newStateNotes[i] = stateNotes[i];
+				}
+				for (int i=0; i<num; i++) {
+					newStateNotes[starting + i + 1] = null;
+				}
+				for (int i=0; i<numChars-starting-1; i++) {
+					newStateNotes[i +starting+num+1] = stateNotes[starting + i+1];
+				}
+				stateNotes = newStateNotes;
+			}
+			if (stateAnnotations !=null){
+				Object[][] newStateAnnotations = new Object[newNumChars][];
+				for (int i=0; i<=starting; i++) {
+					newStateAnnotations[i] = stateAnnotations[i];
+				}
+				for (int i=0; i<num; i++) {
+					newStateAnnotations[starting + i + 1] = null;
+				}
+				for (int i=0; i<numChars-starting-1; i++) {
+					newStateAnnotations[i +starting+num+1] = stateAnnotations[starting + i+1];
+				}
+				stateAnnotations = newStateAnnotations;
+			}
+			return super.addParts(starting, num);
+		}
+		catch (OutOfMemoryError e){
+			MesquiteMessage.warnProgrammer("Sorry, characters could not be added to the Character Matrix because of lack of memory.  See file memory.txt in the Mesquite_Folder.");
+		}
+		return false;
+
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Deletes num characters from position "starting"; returns true iff successful.*/
+	public boolean deleteParts(int starting, int num){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>numChars)
+			return false;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars =numChars-num;
+		incrementStatesVersion();
+		if (!usingShortMatrix())
+			matrix = Long2DArray.deleteColumns(matrix, starting, num);
+		else
+			matrixShort = Short2DArray.deleteColumns(matrixShort, starting, num);
+
+		//numChars = newNumChars; don't do this since super.deleteCharacters needs to remember old number
+		if (stateNames!=null){
+			String[][] newStateNames = new String[newNumChars][];
+			for (int i=0; i<starting; i++) {
+				newStateNames[i] = stateNames[i];
+			}
+			for (int i=starting + num;i<numChars; i++) {
+				newStateNames[i-num] = stateNames[i];
+			}
+			stateNames = newStateNames;
+		}
+		if (stateNotes !=null){
+			String[][] newStateNotes = new String[newNumChars][];
+			for (int i=0; i<starting; i++) {
+				newStateNotes[i] = stateNotes[i];
+			}
+			for (int i=starting + num;i<numChars; i++) {
+				newStateNotes[i-num] = stateNotes[i];
+			}
+			stateNotes = newStateNotes;
+		}
+		if (stateAnnotations !=null){
+			Object[][] newStateAnnotations = new Object[newNumChars][];
+			for (int i=0; i<starting; i++) {
+				newStateAnnotations[i] = stateAnnotations[i];
+			}
+			for (int i=starting + num;i<numChars; i++) {
+				newStateAnnotations[i-num] = stateAnnotations[i];
+			}
+			stateAnnotations = newStateAnnotations;
+		}
+		return super.deleteParts(starting, num);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Adds num taxa after position "starting"; returns true iff successful.*/
+	public boolean addTaxa(int starting, int num){
+
+		setDirty(true);
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numTaxa)
+			starting = numTaxa-1;
+		int newNumTaxa = numTaxa + num;
+
+		try {
+			incrementStatesVersion();
+			if (usingShortMatrix()){
+				short shortUnassigned = CategoricalState.compressToShort(getDefaultState());
+				for (int ic=0; ic<numChars; ic++) {
+					matrixShort[ic] = ShortArray.addParts(matrixShort[ic], starting, num, CategoricalState.compressToShort(getDefaultState()));
+				}
+			}
+			else {
+				for (int ic=0; ic<numChars; ic++) {
+					matrix[ic] = LongArray.addParts(matrix[ic], starting, num, getDefaultState());
+				}
+			}
+		}
+		catch (OutOfMemoryError e){
+			MesquiteMessage.warnProgrammer("Sorry, taxa could not be added to the Character Matrix because of lack of memory.  See file memory.txt in the Mesquite_Folder.");
+		}
+		numTaxa = newNumTaxa; 
+		return super.addTaxa(starting, num);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+
+	/**Deletes num taxa from position "starting"; returns true iff successful.*/
+	public boolean deleteTaxa(int starting, int num){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		setDirty(true);
+		if (num+starting>numTaxa)
+			num = numTaxa-starting;
+		int newNumTaxa = numTaxa - num;
+
+		incrementStatesVersion();
+
+		if (usingShortMatrix()){
+			for (int ic=0; ic<numChars; ic++)
+				matrixShort[ic] = ShortArray.deleteParts(matrixShort[ic], starting, num);
+		}
+		else for (int ic=0; ic<numChars; ic++)
+			matrix[ic] = LongArray.deleteParts(matrix[ic], starting, num);
+
+
+		numTaxa = newNumTaxa; 
+		return super.deleteTaxa(starting, num);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**moves num taxa from position "starting" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveTaxa(int starting, int num, int justAfter){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		setDirty(true);
+		incrementStatesVersion();
+		if (usingShortMatrix()) {
+			for (int ic=0; ic<numChars; ic++)
+				ShortArray.moveParts(matrixShort[ic], starting, num, justAfter);
+		}
+		else for (int ic=0; ic<numChars; ic++)
+			LongArray.moveParts(matrix[ic], starting, num, justAfter);
+		return super.moveTaxa(starting, num, justAfter);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Get String[] of symbols */
+	public String[] getSymbols() {
+		//int maxSymb = getMaxSymbolDefined();
+		String[] labels = new String[symbols.length];
+		for (int i=0; i<symbols.length; i++)
+			labels[i] = ""+ getSymbol(i);
+		return labels;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Get symbol for state st. */
+	public char getSymbol(int st) {
+		if (symbols == null || st <0 || st>=symbols.length)
+			return getUnassignedSymbol();
+		return symbols[st];
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Set symbol for state st.  Does not check for duplicate symbols */
+	public void setSymbolDirect(int st, char symbol) {
+		if (symbols == null ||st <0 || st>=symbols.length)
+			return;
+		setDirty(true);
+		int current = findSymbol(symbol);
+		if (maxSymbolDefined<st)
+			maxSymbolDefined = st;
+		symbols[st] = symbol;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Set symbol for state st.  Returns whether setting implied duplicate symbol */
+	public boolean setSymbol(int st, char symbol) {
+		if (symbols == null || st <0 || st>=symbols.length)
+			return false;
+		setDirty(true);
+		int current = findSymbol(symbol);
+		if (maxSymbolDefined<st)
+			maxSymbolDefined = st;
+		if (current >=0 && current != st){ //duplicate symbol!
+			symbols[st] = symbol;
+			char unusedSymbol = findUnusedSymbol();
+			if (unusedSymbol != (char)0)
+				symbols[current] = unusedSymbol;
+			return true;
+		}
+		else {
+			symbols[st] = symbol;
+			return false;
+		}
+	}
+
+	private int findSymbol(char symbol){
+		for (int ist = 0; ist<symbols.length; ist++) {
+			if (symbols[ist]==symbol) {
+				return ist;
+			}
+		}
+		return -1;
+	}
+	private char findUnusedSymbol(){
+		for (int ist = 0; ist<defaultSymbols.length; ist++) {
+			if (findSymbol(defaultSymbols[ist])<0) {
+				return defaultSymbols[ist];
+			}
+		}
+		return (char)0;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets the symbol used for inapplicable character (e.g., gap)*/
+	public void setInapplicableSymbol(char inapp) {
+		super.setInapplicableSymbol(inapp);
+		puncString = "" + ANDseparator + ORseparator + getUnassignedSymbol() + getInapplicableSymbol();
+	}
+	/** sets the symbol used for missing data (unassigned) character*/
+	public void setUnassignedSymbol(char mc) { 
+		super.setUnassignedSymbol(mc);
+		puncString = "" + ANDseparator + ORseparator + getUnassignedSymbol() + getInapplicableSymbol();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Reverses the data from character icStart to icEnd in taxon it.  If reverseTerminalGaps
+	 * is true, then it reversed the entire stretch; if it is false, it only reverses from the first non-gap to last non-gap in the stretch. 
+	 * If adjustLinks is true, then the linked matrices will also have their cells reversed.  adjustLinks should be true
+	 * in almost all cases, as reversing without it will disrupt linkages between matrices and cause features in
+	 * Mesquite to fail (e.g., within Chromaseq). */
+	public void reverse(int icStart, int icEnd, int it, boolean reverseTerminalGaps, boolean adjustCellLinked){
+		int ic1;
+		int ic2; 
+		if (reverseTerminalGaps) {
+			ic1 = icStart;
+			ic2 = icEnd;
+		}
+		else {
+			ic1 = thisOrNextApplicableChar(icStart, it);
+			ic2 = thisOrPreviousApplicableChar(icEnd,it); 
+		}
+		int numChars = ic2-ic1+1;
+		int halfWay = numChars/2;
+		for (int ic= 0; ic<halfWay; ic++){
+			tradeStatesBetweenCharactersInternal(ic1+ic,ic2-ic,it,false, false);  // don't ask it to adjust linked as we will do it ourselves, below
+		}
+
+
+		if (adjustCellLinked){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d= (CharacterData)linkedDatas.elementAt(i);
+				for (int ic= 0; ic<halfWay; ic++){
+					if (d instanceof CategoricalData)
+						((CategoricalData)d).tradeStatesBetweenCharactersInternal(ic1+ic,ic2-ic,it,false, false);
+					else
+						d.tradeStatesBetweenCharacters(ic1+ic,ic2-ic,it,false);
+				}
+
+			}
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Reverses the metadata from character icStart to icEnd.  
+	 * If adjustLinks is true, then the linked matrices will also have their metadata reversed.  adjustLinks should be true
+	 * in almost all cases, as reversing without it will disrupt linkages between matrices and cause features in
+	 * Mesquite to fail */
+	public void reverseCharacterMetadata(int icStart, int icEnd, boolean adjustCellLinked){
+		int numChars = icEnd-icStart+1;
+		int halfWay = numChars/2;
+		for (int ic= 0; ic<halfWay; ic++){
+			swapCharacterMetadata(icStart+ic,icEnd-ic);  // don't ask it to adjust linked as we will do it ourselves, below
+		}
+
+
+		if (adjustCellLinked){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d= (CharacterData)linkedDatas.elementAt(i);
+				for (int ic= 0; ic<halfWay; ic++){
+					d.swapCharacterMetadata(icStart+ic,icEnd-ic);
+				}
+
+			}
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*
+	 * Re-enable this one, with adjustCellLinked set to true, once the code settles down
+
+	public void reverse(int icStart, int icEnd, int it, boolean reverseTerminalGaps){
+		reverse(icStart,icEnd, it, reverseTerminalGaps, true);
+	}
+	/*..........................................CategoricalData................*/
+	/** Trades the states of character ic and ic2 in taxon it.  Used for sorting by characters or reversing sequences (for example).
+	 * If adjustCellLinked is true, then linked matrices will also have their cells traded. This should generally
+	 * be set to true; if you set it to false, then you must trade states of linked matrices yourself. 
+	 * This is the public version; the internal version is used internally to distinguish between the internal call from reverse
+	 * (which will handle directions otherwise) and external calls (which should do the direction bookkeeping for the user)*/
+	public void tradeStatesBetweenCharacters(int ic, int ic2, int it, boolean adjustCellLinked) { 
+		tradeStatesBetweenCharactersInternal(ic, ic2, it, adjustCellLinked, true);
+	}
+	/*..........................................CategoricalData................*/
+	/** Trades the states of character ic and ic2 in taxon it.  Used for sorting by characters or reversing sequences (for example).
+	 * If adjustCellLinked is true, then linked matrices will also have their cells traded. This should generally
+	 * be set to true; if you set it to false, then you must trade states of linked matrices yourself. */
+	protected void tradeStatesBetweenCharactersInternal(int ic, int ic2, int it, boolean adjustCellLinked, boolean adjustDirections) { 
+		if (notInStorage(ic, it) || notInStorage(ic2, it))
+			return;
+		super.tradeStatesBetweenCharacters(ic, ic2, it,adjustCellLinked);
+		if (usingShortMatrix()){
+			short temp = matrixShort[ic][it];
+			matrixShort[ic][it] =  matrixShort[ic2][it];
+			matrixShort[ic2][it] = temp;
+		}
+		else {
+			long temp = matrix[ic][it];
+			matrix[ic][it] =  matrix[ic2][it];
+			matrix[ic2][it] = temp;
+		}
+		incrementStatesVersion();
+		setDirty(true, ic, it);
+		setDirty(true, ic2, it);
+	}
+	/*..........................................CategoricalData................*/
+	/* trades the states of character ic and ic2 in taxon it.  Used for reversing sequences (for example).*
+	 * Re-enable this version, with adjustCellLinked set to true, once the code settles down for linked matrix adjustment.
+	public void tradeStatesBetweenCharacters(int ic, int ic2, int it) { 
+		tradeStatesBetweenCharacters(ic,ic2,it,true);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** trades the states of character ic between taxa it and it2.  Used for reshuffling.*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) {
+		if (notInStorage(ic, it) || notInStorage(ic, it2))
+			return;
+		super.tradeStatesBetweenTaxa(ic, it, it2);
+		if (usingShortMatrix()){
+			short temp = matrixShort[ic][it];
+			matrixShort[ic][it] =  matrixShort[ic][it2];
+			matrixShort[ic][it2] = temp;
+		}
+		else {
+			long temp = matrix[ic][it];
+			matrix[ic][it] =  matrix[ic][it2];
+			matrix[ic][it2] = temp;
+		}
+		incrementStatesVersion();
+		setDirty(true, ic, it);
+		setDirty(true, ic, it2);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Dump matrix to log */
+	public void logMatrix(){
+		MesquiteModule.mesquiteTrunk.logln("Matrix of " + numTaxa + " taxa and " + numChars + " characters.");
+		String matrixString="";
+		for (int it=0; it<numTaxa; it++) {
+			for (int ic=0; ic<numChars; ic++) {
+				matrixString+=CategoricalState.toString(getStateRaw(ic, it));
+			}
+			matrixString+= '\r';
+		}
+		MesquiteModule.mesquiteTrunk.logln(matrixString);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Fills matrix with data from passed StsOfCharacters object.*/
+	public void setMatrix(MCharactersDistribution states){ //TODO: make this so it will change size of matrix if needed???
+		if (!(states instanceof MCategoricalDistribution))
+			return;
+		setDirty(true);
+		incrementStatesVersion();
+		MCategoricalDistribution dStates = (MCategoricalDistribution)states;
+		for (int ic = 0; ic< numChars; ic++) {
+			for (int it = 0; it< numTaxa; it++)  {
+				if (ic>dStates.getNumChars())
+					setState(ic, it, getDefaultState());
+				else
+					setState(ic, it, dStates.getStateRaw(ic, it));  //1. 06 changed from getState 
+				stampHistoryChange(ic, it);
+			}
+		}
+		calculateFirstLastApplicable();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**get matrix and return as StsOfCharacters */
+	public MCharactersDistribution getMCharactersDistribution(){
+		MCategoricalEmbedded states = new MCategoricalEmbedded(this);
+		return states;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**return a CharacterDistribution that points to character ic */
+	public CharacterDistribution getCharacterDistribution(int ic){
+		CategoricalEmbedded states = new CategoricalEmbedded(this, ic);
+		return states;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**extract character ic and return as an array of long's */
+	public long[] getCharacter(int ic){
+		if (notInStorage(ic, 0)) //illegal check
+			return null;
+		if (ic<numChars && ic>=0) {
+			long[] c = new long[getNumTaxa()];
+			for (int i=0; i<c.length; i++)
+				c[i] = getStateRaw(ic, i);
+			return c;
+		}
+		return null;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Return CharacterDistribution object with same number of taxa as this object (but not with any particular data; just so that of same data type) */
+	public CharacterDistribution makeCharacterDistribution(){
+		CategoricalAdjustable c= new CategoricalAdjustable(getTaxa(), numTaxa);
+		c.setParentData(this);
+		return c;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** creates an empty CharacterState object of the same data type as CharacterData subclass used.*/
+	public CharacterState makeCharacterState(){
+		return new CategoricalState();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Return CharacterData object with same number of taxa & characters as this object (but not with any particular data; just so that of same data type) */
+	public CharacterData makeCharacterData() {
+		return new CategoricalData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Return CharacterData object with passed number of taxa & characters (but not with any particular data; just so that of same data type) */
+	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+		return new CategoricalData(getMatrixManager(), ntaxa, nchars, getTaxa());
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){ 
+		return new CategoricalData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether a given char is acceptable as the value for a character state */
+	public boolean isAcceptableCharForState(char c){
+		long value = fromChar(c);
+		return (value == CategoricalState.unassigned || value == CategoricalState.inapplicable || CategoricalState.isCombinable(value));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns Color for state of character, scaled to maxState (e.g. for tracing to yield white/black for binary) */
+	public Color getColorOfState(int ic, int istate, int maxState, MesquiteColorTable colors){
+		if (colors == null)
+			return MesquiteColorTable.getDefaultColor(maxState,istate, MesquiteColorTable.COLORS);
+		else 
+			return colors.getColor(maxState,istate);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns Color for state of character, scaled to maxState (e.g. for tracing to yield white/black for binary) */
+	public Color getColorOfState(int ic, int istate, int maxState){
+		return MesquiteColorTable.getDefaultColor(maxState,istate, MesquiteColorTable.COLORS);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Returns the color for the given state of character ic.  Currently only returns default */
+	public Color getColorOfState(int ic, int istate){
+		return MesquiteColorTable.getDefaultColor(CategoricalState.maxCategoricalState,istate, MesquiteColorTable.COLORS);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Gets the color representing state(s) of character ic in taxon it */ 
+	public Color getColorOfStates(int ic, int it){
+		if (notInStorage(ic, it)) //illegal check
+			return ColorDistribution.unassigned;
+		long s = getStateRaw(ic, it);
+		if (CategoricalState.isCombinable(s)) {
+			int colorCount = CategoricalState.cardinality(s);
+			if (colorCount>1){
+				return Color.lightGray;
+			}
+			else {
+				return getColorOfState(ic, CategoricalState.maximum(s), getMaxState(ic));
+			}
+		}
+		else 
+			return ColorDistribution.unassigned;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Gets the color representing state(s) of character ic in taxon it */ 
+	public Color getColorOfStatesUpperLimit(int ic, int it, int maxState){
+		if (notInStorage(ic, it)) //illegal check
+			return ColorDistribution.unassigned;
+		long s = getStateRaw(ic, it);
+		if (CategoricalState.isCombinable(s)) {
+			int colorCount = CategoricalState.cardinality(s);
+			if (colorCount>1){
+				return Color.lightGray;
+			}
+			else {
+				int state = CategoricalState.maximum(s);
+				if (state>maxState)
+					state=maxState;
+				return getColorOfState(ic, state, maxState);
+			}
+		}
+		else 
+			return ColorDistribution.unassigned;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public boolean charIsVariable( int ic, boolean selectedOnly) {
+		long intersection = CategoricalState.statesBitsMask;
+		boolean anySel = getTaxa().anySelected();
+		for (int it=0; it<getNumTaxa(); it++){
+			if (!selectedOnly || !anySel || getTaxa().getSelected(it)){
+				long state = getState(ic, it);
+				if (CategoricalState.isCombinable(state)){
+					if (CategoricalState.cardinality(state)>1){ //polymorphic or uncertain
+						if (CategoricalState.isUncertain(state)){ //uncertain; ok if overlaps
+							intersection &= state;
+							if (intersection == 0L)
+								return true;
+						}
+						else
+							return true;
+					}
+					else {
+						intersection &= state;
+						if (intersection == 0L)
+							return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  boolean isValidAssignedState(int ic, int it){
+		if (ic<0 || ic>=numChars) return false;
+		long s = getStateRaw(ic,it);
+		return CategoricalState.isCombinable(s);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  int numValidAssignedState(int icStart, int icEnd, int it){
+		int count =0;
+		for (int ic=icStart; ic<=icEnd; ic++)
+			if (isValidAssignedState(ic,it))
+				count++;
+		return count;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  boolean isValidStateOrUnassigned(int ic, int it){
+		if (ic<0 || ic>=numChars) return false;
+		long s = getStateRaw(ic,it);
+		return (CategoricalState.isCombinable(s) || CategoricalState.isUnassigned(s));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  int numValidStateOrUnassigned(int icStart, int icEnd, int it){
+		int count =0;
+		for (int ic=icStart; ic<=icEnd; ic++)
+			if (isValidStateOrUnassigned(ic,it))
+				count++;
+		return count;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  boolean isInternalInapplicable(int ic, int it){
+		if (!isInapplicable(ic, it))
+			return false;
+		// it is inappllicable.  But is it internal?  
+		if (ic< getNumChars()/2){ // first half, look left first
+			boolean foundState = false;
+			for (int icc = ic-1; icc>=0 && !foundState; icc--)  //look left for state
+				foundState = !isInapplicable(icc, it);
+			if (!foundState)
+				return false;
+			foundState = false;
+			for (int icc = ic+1; icc<getNumChars() && !foundState; icc++)  //look right for state
+				foundState = !isInapplicable(icc, it);
+			if (!foundState)
+				return false;
+		}
+		else {
+			boolean foundState = false;
+			for (int icc = ic+1; icc<getNumChars() && !foundState; icc++)  //look right for state
+				foundState = !isInapplicable(icc, it);
+			if (!foundState)
+				return false;
+			foundState = false;
+			for (int icc = ic-1; icc>=0 && !foundState; icc--)  //look left for state
+				foundState = !isInapplicable(icc, it);
+			if (!foundState)
+				return false;
+		}
+		return true;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public  boolean isInapplicable(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return(s== CategoricalState.inapplicable || s==CategoricalState.impossible);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the state of character ic is missing in taxon it*/
+	public  boolean isUnassigned(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return(s== CategoricalState.unassigned || s==CategoricalState.impossible);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the state of character ic is missing in taxon it*/
+	public  boolean isValid(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return !(s== 0L || s==CategoricalState.impossible);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the state of character ic is missing in taxon it*/
+	public  boolean isAmbiguousOrPolymorphic(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return s== CategoricalState.unassigned || s==CategoricalState.impossible || (CategoricalState.hasMultipleStates(s));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns whether the state of character ic is missing in taxon it*/
+	public  boolean isMultistateUncertainty(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return (CategoricalState.isUncertain(s) && CategoricalState.hasMultipleStates(s));
+	}
+	/*..........................................    ..................................................*/
+	/** returns whether the state of character ic is missing in taxon it*/
+	public  boolean isMultistateOrUncertainty(int ic, int it){
+		long s = getStateRaw(ic,it);
+		return (CategoricalState.hasMultipleStates(s));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the maximum symbol defined*/
+	public int getMaxSymbolDefined(){
+		if (maxSymbolDefined>=0)
+			return maxSymbolDefined;
+		else
+			return getMaxState();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the maximum state in character ic*/
+	public int getMaxState(int ic){
+		if (notInStorage(ic, 0)) //illegal check
+			return -1;
+
+		long allstates = 0;
+		for (int it=0; it<numTaxa; it++)
+			allstates |= getState(ic, it);
+		return CategoricalState.maximum(allstates);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the set of states in character ic*/
+	public long getAllStates(int ic){
+		if (notInStorage(ic, 0)) //illegal check
+			return 0L;
+
+		long allstates = 0;
+		for (int it=0; it<numTaxa; it++)
+			allstates |=getState(ic, it);
+		return allstates & CategoricalState.statesBitsMask;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the maximum state in the matrix*/
+	public int getMaxState(){
+		if ((matrix == null && matrixShort == null) ) //illegal check
+			return -1;
+		long allstates = 0;
+		for (int ic=0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++)
+				allstates |=getState(ic, it);
+		return CategoricalState.maximum(allstates);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns the state of character ic in taxon it*/
+	public  CharacterState getCharacterState(CharacterState cs, int ic, int it){
+		if (notInStorage(ic, it)) //illegal check
+			return null;
+		if (cs!=null && cs.getClass()==CategoricalState.class) {
+			((CategoricalState)cs).setValue(getStateRaw(ic, it));
+			return cs;
+		}
+		return new CategoricalState(getStateRaw(ic, it));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	protected boolean notInStorage(int ic, int it) {
+		if (ic>=numChars || it>=numTaxa || ic < 0 || it < 0) {
+			return true;
+		}
+		if (matrix != null && (ic >= matrix.length || matrix.length<1 || matrix[0] == null || it >= matrix[0].length)) {
+			if (!doomed) MesquiteMessage.printStackTrace("Error: CategoricalData notInStorage #1");
+			return true;
+		}
+		if (matrixShort != null && (ic >= matrixShort.length || matrixShort.length<1 || matrixShort[0] == null || it >= matrixShort[0].length)){
+			if (!doomed) MesquiteMessage.printStackTrace("Error: CategoricalData notInStorage #2");
+			return true;
+		}
+		if (matrixShort == null && matrix == null){
+			if (!doomed) MesquiteMessage.printStackTrace("Error: CategoricalData notInStorage #3");
+			return true;
+		}
+		return false;
+	}
+	MesquiteInteger resultCode = new MesquiteInteger();
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets the state of character ic in taxon it to inapplicable*/
+	public  void setToInapplicable(int ic, int it){
+		setState(ic, it, CategoricalState.inapplicable);
+		setDirty(true, ic, it);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets the state of character ic in taxon it to unassigned*/
+	public  void setToUnassigned(int ic, int it){
+		setState(ic, it, CategoricalState.unassigned);
+		setDirty(true, ic, it);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets the state of character ic in taxon it from CharacterState cs*/
+	public  void setState(int ic, int it, CharacterState cs){
+		if (cs !=null && cs instanceof CategoricalState) {
+			setState(ic, it, ((CategoricalState)cs).getValue());
+			setDirty(true, ic, it);
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Set stateset in node it and character ic to state indicated by state symbol. */
+	public void setState(int ic, int it, char c){
+		setState(ic, it, fromChar(c));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Set stateset in node it and character ic to states. */
+	public void setState(int ic, int it, long states){
+		if (notInStorage(ic, it)) //illegal check
+			return;
+		if (usingShortMatrix()) {
+			if (!CategoricalState.compressibleToShort(states)) {
+				try {
+					upgradeToFullMatrix();
+					matrix[ic][it]= states;
+				}
+				catch (OutOfMemoryError e){
+					matrix = null;
+					MesquiteMessage.warnProgrammer("Sorry, the character state of character " + (ic+1) + " in taxon " + (it+1) + " could not be set to " + CategoricalState.toString(states) + " because of insufficient memory.  See file memory.txt in the Mesquite_Folder.");
+				}
+			}
+			else {
+				matrixShort[ic][it] = CategoricalState.compressToShort(states);
+			}
+		}
+		else
+			matrix[ic][it]= states;
+		incrementStatesVersion();
+		setDirty(true, ic, it);
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Set the state at character ic and taxon it from the string of the parser, beginning at current position of the parser.
+	If pos == null, assumes from data editor and looks for state names, treats differently*/
+	public int setStateQuickNexusReading(int ic, int it, Parser parser){ 
+		resultCode.setValue(MesquiteInteger.unassigned);
+		long v = fromStringQuickNexusReading(ic, parser, resultCode);
+		if (v==CategoricalState.impossible) {
+			//setState(ic, it, v);
+			if (resultCode.getValue() == EOL)
+				return EOL;
+			return ERROR;
+		}
+		else if (v!=getStateRaw(ic, it)) {
+			setState(ic, it, v);
+			//	setDirty(true, ic, it);
+		}
+		if (resultCode.isUnassigned())
+			return OK;
+		else
+			return resultCode.getValue();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Set the state at character ic and taxon it from the string of the parser, beginning at current position of the parser.
+	If pos == null, assumes from data editor and looks for state names, treats differently*/
+	public int setState(int ic, int it, Parser parser, boolean fromEditor, MesquiteString result){ 
+		if (notInStorage(ic, it)) {//illegal check
+			if (result!=null)
+				result.setValue("Character or taxon number out of bounds (Set state, CategoricalData)." + ic + "  " + ic);
+			MesquiteMessage.printStackTrace("out of bounds ic " + ic + " it " + it);
+			return OUTOFBOUNDS;
+		}
+		if (parser.blank()) {
+			if (result!=null)
+				result.setValue("State string is blank.");
+			return ERROR;
+		}
+		resultCode.setValue(MesquiteInteger.unassigned);
+		long v = fromString(ic, parser, fromEditor, resultCode, result);
+		if (v==CategoricalState.impossible) {
+			if (resultCode.getValue() == EOL)
+				return EOL;
+			if (result !=null) {
+				if (fromEditor)
+					result.setValue("\"" + parser.getString() + "\" cannot be translated into a state for this character");
+				else
+					result.setValue("Illegal state entry for categorical character");
+			}
+			return ERROR;
+		}
+		else if (v!=getStateRaw(ic, it)) {
+			setState(ic, it, v);
+			setDirty(true, ic, it);
+		}
+		if (resultCode.isUnassigned())
+			return OK;
+		else
+			return resultCode.getValue();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** return stateset in node it and character ic. */
+	public long getState(long[] sequence, int ic){
+		if (ic<0 ||  ic>=sequence.length)
+			return CategoricalState.impossible;
+		return CategoricalState.dataBitsMask & sequence[ic];
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** return stateset in node it and character ic. */
+	public long getState(int ic, int it){
+		if (notInStorage(ic, it)) //illegal check
+			return CategoricalState.impossible;
+		if (usingShortMatrix())
+			return CategoricalState.dataBitsMask & CategoricalState.expandFromShort(matrixShort[ic][it]);
+		else
+			return CategoricalState.dataBitsMask & matrix[ic][it];
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** return stateset in node it and character ic, raw, as in matrix. */
+	public long getStateRaw(int ic, int it){
+		if (notInStorage(ic, it)) //illegal check
+			return CategoricalState.impossible;
+		if (usingShortMatrix())
+			return CategoricalState.expandFromShort(matrixShort[ic][it]);
+		else
+			return matrix[ic][it];
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state names are available for matrix */
+	public boolean hasStateNames() {
+		return (stateNames!=null);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state names are available for character ic*/
+	public boolean hasStateNames(int ic) {
+		return (stateNames!= null && ic>=0 && ic<numChars && stateNames[ic]!=null );
+	}
+	/*.................................................................................................................*/
+	public String getChecksumSummaryString(){
+		CategoricalState state=null;
+		long allstates =0L;
+		long allData =0L;
+		double sumSquaresStatesOnly = 0;
+		double sumSquares = 0;
+		for (int ic = 0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++) {
+				state =(CategoricalState)getCharacterState(state, ic, it);
+				long st = state.getValue();
+				sumSquares += st * st;
+				if (!CategoricalState.isUnassigned(st) && !CategoricalState.isInapplicable(st)){
+					allData |= st;
+					st = st & CategoricalState.statesBitsMask;
+					sumSquaresStatesOnly += st * st;
+					allstates |= st;
+				}
+			}
+		return "getNumChars " + getNumChars()+ " numChars " + numChars  + " getNumTaxa " + getNumTaxa()  + " numTaxa " + numTaxa + "   short " + usingShortMatrix() + "   bits " + allData + "   states " + allstates + "   sumSquaresStatesOnly " +  sumSquaresStatesOnly + " sumSquares " + sumSquares + " longCompressibleToShort " + longCompressibleToShort() + " usingShortMatrix " + usingShortMatrix();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long calculateChecksum(CRC32 crc32, int version){
+		if (version == 1)
+			return calculateChecksum(crc32);
+		if (longCompressibleToShort()){
+			byte[] bytes = new byte[2];
+			crc32.reset();
+			short unc = 0;
+			if (version == 2)
+				unc = (short)(((short)1)<<CategoricalState.uncertainBit);
+			else
+				unc = CategoricalState.compressToShort(1L<<CategoricalState.uncertainBit);
+			for (int ic=0; ic<matrix.length; ic++)
+				for (int it=0; it<matrix[ic].length; it++)  {
+					long longState = matrix[ic][it];
+					short state = CategoricalState.compressToShort(longState);
+					if (CategoricalState.isUnassigned(state))
+						state = CategoricalState.unassignedShort;
+					else if (CategoricalState.isInapplicable(state))
+						state = CategoricalState.inapplicableShort;
+					else if (CategoricalState.isImpossible(state))
+						state = 0;
+					else
+						state &= CategoricalState.statesBitsMaskShort | unc;
+					bytes = MesquiteNumber.shortToBytes(state, bytes);
+					crc32.update(bytes[0]);
+					crc32.update(bytes[1]);
+				}
+
+			return crc32.getValue();
+		}
+		else if (usingShortMatrix()){
+			byte[] bytes = new byte[2];
+			crc32.reset();
+			short unc = 0;
+			if (version == 2)
+				unc = (short)(((short)1)<<CategoricalState.uncertainBit);
+			else
+				unc = CategoricalState.compressToShort(1L<<CategoricalState.uncertainBit);
+			for (int ic=0; ic<matrixShort.length; ic++)
+				for (int it=0; it<matrixShort[ic].length; it++)  {
+					short state = matrixShort[ic][it];
+					if (CategoricalState.isUnassigned(state))
+						state = CategoricalState.unassignedShort;
+					else if (CategoricalState.isInapplicable(state))
+						state = CategoricalState.inapplicableShort;
+					else if (CategoricalState.isImpossible(state))
+						state = 0;
+					else
+						state &= CategoricalState.statesBitsMaskShort | unc;
+					bytes = MesquiteNumber.shortToBytes(state, bytes);
+					crc32.update(bytes[0]);
+					crc32.update(bytes[1]);
+				}
+
+			return crc32.getValue();
+		}
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		for (int ic=0; ic<matrix.length; ic++)
+			for (int it=0; it<matrix[ic].length; it++)  {
+				long state = matrix[ic][it];
+				if (CategoricalState.isUnassigned(state))
+					state = CategoricalState.unassigned;
+				else if (CategoricalState.isInapplicable(state))
+					state = CategoricalState.inapplicable;
+				else if (CategoricalState.isImpossible(state))
+					state = 0L;
+				else
+					state &= CategoricalState.statesBitsMask | (1L<<CategoricalState.uncertainBit);
+
+				bytes = MesquiteNumber.longToBytes(state, bytes);
+				for (int i = 0; i<8; i++)
+					crc32.update(bytes[i]);
+			}
+
+		return crc32.getValue();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long calculateChecksum(CRC32 crc32){
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		for (int ic=0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++)  {
+				long state = getStateRaw(ic, it);
+				if (CategoricalState.isUnassigned(state))
+					state = CategoricalState.unassigned;
+				else if (CategoricalState.isInapplicable(state))
+					state = CategoricalState.inapplicable;
+				else if (CategoricalState.isImpossible(state))
+					state = 0L;
+				else
+					state &= CategoricalState.statesBitsMask | (1L<<CategoricalState.uncertainBit);
+
+				bytes = MesquiteNumber.longToBytes(state, bytes);
+				for (int i = 0; i<8; i++)
+					crc32.update(bytes[i]);
+			}
+
+		return crc32.getValue();
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long calculateDataChecksum(int icStart, int icEnd, int itStart, int itEnd, CRC32 crc32){
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		for (int ic=icStart; ic<=icEnd; ic++)
+			for (int it=itStart; it<=itEnd; it++)  {
+				long state = getStateRaw(ic, it);
+				if (!CategoricalState.isUnassigned(state) && !CategoricalState.isInapplicable(state) && !CategoricalState.isImpossible(state)) {
+					state &= CategoricalState.statesBitsMask | (1L<<CategoricalState.uncertainBit);
+
+					bytes = MesquiteNumber.longToBytes(state, bytes);
+					for (int i = 0; i<8; i++)
+						crc32.update(bytes[i]);
+				}
+			}
+
+		return crc32.getValue();
+	}
+	private CRC32 tempcrc32 = new CRC32();
+	/*.................................................................................................................*/
+	public long storeCheckSum (int icStart, int icEnd, int itStart, int itEnd) {
+		return calculateDataChecksum(icStart, icEnd, itStart, itEnd, tempcrc32);
+	}
+	/*.................................................................................................................*/
+	public boolean examineCheckSum (int icStart, int icEnd, int itStart, int itEnd, String warning, MesquiteBoolean warnCheckSum, long originalCheckSum) {
+		long newCheckSum = calculateDataChecksum(icStart, icEnd, itStart, itEnd, tempcrc32);
+		if (originalCheckSum != newCheckSum) {
+			if (!warnCheckSum.getValue())
+				MesquiteTrunk.mesquiteTrunk.logln(warning);
+			else if (!AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Checksum doesn't match",warning + "\n\nYou may suppress warnings of this type within this run of Mesquite.", "Continue", "Suppress warnings"))
+				warnCheckSum.setValue(false);
+			return false;
+		} 
+		else {
+			MesquiteTrunk.mesquiteTrunk.logln("Passed checksum");
+			return true;
+		}
+	}
+	/*.................................................................................................................*/
+	public long storeCheckSum (int icStart, int icEnd, Bits whichTaxa) {
+		return calculateDataChecksum(icStart, icEnd, whichTaxa, tempcrc32);
+	}
+	/*.................................................................................................................*/
+	public boolean examineCheckSum (int icStart, int icEnd, Bits whichTaxa, String warning, MesquiteBoolean warnCheckSum, long originalCheckSum) {
+		long newCheckSum = calculateDataChecksum(icStart, icEnd, whichTaxa, tempcrc32);
+		if (originalCheckSum != newCheckSum) {
+			if (!warnCheckSum.getValue())
+				MesquiteTrunk.mesquiteTrunk.logln(warning);
+			else if (!AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Checksum doesn't match",warning + "\n\nYou may suppress warnings of this type within this run of Mesquite.", "Continue", "Suppress warnings"))
+				warnCheckSum.setValue(false);
+			return false;
+		} 
+		else {
+			MesquiteTrunk.mesquiteTrunk.logln("Passed checksum");
+			return true;
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long calculateDataChecksum(int icStart, int icEnd, Bits whichTaxa, CRC32 crc32){
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		int start = whichTaxa.firstBitOn();
+		if (start<0) start=0;
+		int end = whichTaxa.lastBitOn();
+		if (end<0) end = numTaxa-1;
+		for (int ic=icStart; ic<=icEnd; ic++)
+			for (int it=start; it<=end; it++)  
+				if (whichTaxa.isBitOn(it)){
+					long state = getStateRaw(ic, it);
+					if (!CategoricalState.isUnassigned(state) && !CategoricalState.isInapplicable(state) && !CategoricalState.isImpossible(state)) {
+						state &= CategoricalState.statesBitsMask | (1L<<CategoricalState.uncertainBit);
+
+						bytes = MesquiteNumber.longToBytes(state, bytes);
+						for (int i = 0; i<8; i++)
+							crc32.update(bytes[i]);
+					}
+				}
+
+		return crc32.getValue();
+	}
+	boolean anyImpossible(MesquiteInteger icM, MesquiteInteger itM){
+		try {
+			if (usingShortMatrix()){
+				for (int ic=0; ic<matrixShort.length; ic++)
+					for (int it=0; it<matrixShort[ic].length; it++)  {
+						short state = matrixShort[ic][it];
+						if (CategoricalState.isImpossible(state)) {
+							icM.setValue(ic);
+							itM.setValue(it);
+							return true;
+						}
+					}
+			}
+			else {
+				for (int ic=0; ic<matrix.length; ic++)
+					for (int it=0; it<matrix[ic].length; it++)  {
+						long state = matrix[ic][it];
+						if (CategoricalState.isImpossible(state)) {
+							icM.setValue(ic);
+							itM.setValue(it);
+							return true;
+						}
+					}
+			}
+		}
+		catch (NullPointerException e){  //would happen if matrix being disposed of asynchronously
+		}
+		return false;
+	}
+	public String checkIntegrity(){
+		String warning = super.checkIntegrity();
+		MesquiteInteger ic = new MesquiteInteger();
+		MesquiteInteger it = new MesquiteInteger();
+		if (anyImpossible(ic, it)) {
+			String note = "Matrix has impossible states [char " + ic + " taxon " + it + "]";
+			if (warning == null)
+				warning = note;
+			else
+				warning += "\n" + note;
+		}
+		return warning;
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state name for state s is available for character ic*/
+	public boolean hasStateName(int ic, int s) {
+		return (stateNames!= null && ic>=0 && ic<numChars && stateNames[ic]!=null && s< stateNames[ic].length && stateNames[ic][s]!=null);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state name for state s is available for character ic*/
+	public boolean hasStateFootnote(int ic, int s) {
+		return (stateNotes!= null && ic>=0 && ic<numChars && stateNotes[ic]!=null && s< stateNotes[ic].length && stateNotes[ic][s]!=null);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state name for state s is available for character ic*/
+	public boolean hasStateAnnotations(int ic, int s) {
+		return (stateAnnotations!= null && ic>=0 && ic<numChars && stateAnnotations[ic]!=null && s< stateAnnotations[ic].length && stateAnnotations[ic][s]!=null && ((AttachedNotesVector)stateAnnotations[ic][s]).getNumNotes()>0);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets state name of state "state" of character ic to name */
+	public void setStateName(int ic, int state, String name) { //todo: check if in bounds
+		if (ic< 0 || ic >= numChars)
+			return;
+		setDirty(true);
+		if (StringUtil.blank(name))
+			name = null;
+		if (stateNames==null) {
+			stateNames = new String[numChars][];
+		}
+		if (stateNames[ic]==null) {
+			if (state ==0)
+				stateNames[ic] = new String[2];
+			else
+				stateNames[ic] = new String[state+1];
+		}
+		else if (state>= stateNames[ic].length) {
+			String[] newStateNames = new String[state+1];
+			for (int i=0; i<stateNames[ic].length; i++) {
+				newStateNames[i] = stateNames[ic][i];
+			}
+			stateNames[ic]=newStateNames;
+		}
+		stateNames[ic][state]=name;
+
+		notifyListeners(this, new Notification(NAMES_CHANGED, new int[] {ic}));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state name of state "state" of character ic */
+	private String getStateName(int ic, int state, boolean raw) {
+		if (ic>=0 && stateNames!= null && state>=0 && stateNames.length> ic && stateNames[ic]!=null && state< stateNames[ic].length && stateNames[ic][state]!=null) {
+			return stateNames[ic][state];
+		}
+		else if (!raw && symbols!=null && state < symbols.length)
+			return String.valueOf(symbols[state]);
+		else return null;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state name of state "state" of character ic */
+	public String getStateName(int ic, int state) {
+		return getStateName(ic, state, false);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state notes are available for matrix */
+	public boolean hasStateNotes() {
+		return (stateNotes!=null);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state note for state s is available for character ic*/
+	public boolean hasStateNote(int ic, int s) {
+		return (stateNotes!= null && ic>=0 && ic<numChars && stateNotes[ic]!=null && s< stateNotes[ic].length && stateNotes[ic][s]!=null);
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns true if state notes are available for character ic*/
+	public boolean hasStateNotes(int ic) {
+		return (stateNotes!= null && ic>=0 && ic<numChars && stateNotes[ic]!=null );
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets state name of state "state" of character ic to name */
+	public void setStateNote(int ic, int state, String name) { //todo: check if in bounds
+		setDirty(true);
+		if (StringUtil.blank(name))
+			name = null;
+		if (stateNotes==null) {
+			stateNotes = new String[numChars][];
+		}
+		if (stateNotes[ic]==null) {
+			if (state ==0)
+				stateNotes[ic] = new String[2];
+			else
+				stateNotes[ic] = new String[state+1];
+		}
+		else if (state>= stateNotes[ic].length) {
+			String[] newStateNotes = new String[state+1];
+			for (int i=0; i<stateNotes[ic].length; i++) {
+				newStateNotes[i] = stateNotes[ic][i];
+			}
+			stateNotes[ic]=newStateNotes;
+		}
+		stateNotes[ic][state]=name;
+
+		notifyListeners(this, new Notification(ANNOTATION_CHANGED, new int[] {ic}));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state name of state "state" of character ic */
+	public String getStateNote(int ic, int state) {
+		if (stateNotes!= null && stateNotes.length> ic && ic >= 0 && stateNotes[ic]!=null && state>=0 && state< stateNotes[ic].length && stateNotes[ic][state]!=null) {
+			return stateNotes[ic][state];
+		}
+		else return null;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** sets state name of state "state" of character ic to name */
+	public void setStateAnnotationsVector(int ic, int state, AttachedNotesVector v) { //todo: check if in bounds
+		setDirty(true);
+		if (stateAnnotations==null) {
+			stateAnnotations = new Object[numChars][];
+		}
+		if (stateAnnotations[ic]==null) {
+			if (state ==0)
+				stateAnnotations[ic] = new Object[2];
+			else
+				stateAnnotations[ic] = new Object[state+1];
+		}
+		else if (state>= stateAnnotations[ic].length) {
+			Object[] newStateAnnotations = new Object[state+1];
+			for (int i=0; i<stateAnnotations[ic].length; i++) {
+				newStateAnnotations[i] = stateAnnotations[ic][i];
+			}
+			stateAnnotations[ic]=newStateAnnotations;
+		}
+		stateAnnotations[ic][state]=v;
+
+		notifyListeners(this, new Notification(ANNOTATION_CHANGED, new int[] {ic}));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state name of state "state" of character ic */
+	public AttachedNotesVector getStateAnnotationsVector(int ic, int state) {
+		if (stateAnnotations!= null && stateAnnotations.length> ic && ic >= 0 && stateAnnotations[ic]!=null && state>=0 && state< stateAnnotations[ic].length && stateAnnotations[ic][state]!=null) {
+			return (AttachedNotesVector)stateAnnotations[ic][state];
+		}
+		else return null;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns state number for last state with name for character ic*/
+	public int maxStateWithName(int ic) {
+		if (ic<0 || ic>=getNumChars())
+			return -1;
+		if (stateNames == null || stateNames[ic]==null) 
+			return -1;
+		else
+			for (int state=stateNames[ic].length-1; state >= 0; state--) {
+				if (!((stateNames[ic][state] == null)||(stateNames[ic][state] == ""))){
+					return state;
+				}
+			}
+		return -1;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** returns state number for last state scored, with name, with footnote, or with annotation for character ic*/
+	public int maxStateWithDefinition(int ic) {
+		if (ic < 0 || ic>=getNumChars())
+			return -1;
+		int maxState = Math.max(getMaxState(ic), maxStateWithName(ic));
+		for (int st = maxState+1; st <= CategoricalState.maxCategoricalState; st++){
+			if (getStateNote(ic, st) != null)
+				maxState = st;
+			else {
+				AttachedNotesVector s = getStateAnnotationsVector(ic, st);
+				if (s != null && s.getNumNotes()>0)
+					maxState = st;
+			}
+
+		}
+		return maxState;
+	}
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two cells have the same states */
+	public boolean sameState(int ic1, int it1, int ic2, int it2){
+		CharacterState cs1 = getCharacterState(null, ic1, it1);
+		CharacterState cs2 = getCharacterState(null, ic2, it2);
+		return cs1.equals(cs2);
+	}
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two cells have the same states */
+	public boolean sameStateIgnoreCase(int ic1, int it1, int ic2, int it2){
+		CategoricalState cs1 = (CategoricalState)getCharacterState(null, ic1, it1);
+		CategoricalState cs2 = (CategoricalState)getCharacterState(null, ic2, it2);
+		return cs1.equalsIgnoreCase(cs2);
+	}
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two cells have the same states */
+	public boolean sameStateIgnoreCase(int ic1, int it1, int ic2, int it2, boolean allowMissing, boolean allowNearExact, boolean allowSubset){
+		CategoricalState cs1 = (CategoricalState)getCharacterState(null, ic1, it1);
+		CategoricalState cs2 = (CategoricalState)getCharacterState(null, ic2, it2);
+		return cs1.equals(cs2,allowMissing,allowNearExact,allowSubset);
+	}
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two characters have identical distributions of states */
+	public boolean samePattern(int oic, int ic){
+		
+		for (int it=0; it<numTaxa; it++) {
+			if (!sameState(oic, it, ic, it))
+				return false;
+		}
+		return true;
+	}
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two characters have identical distributions of states */
+	public void clearCharacter(int ic){
+		
+		for (int it=0; it<numTaxa; it++) {
+			setToInapplicable(ic,it);
+		}
+	}
+	/*-----------------------------------------------------------*/
+	public void equalizeCharacter(CharacterData oData, int oic, int ic){
+		//state names
+		if (oData instanceof CategoricalData){
+			CategoricalData cData = (CategoricalData)oData;
+			if (cData.stateNames == null)
+				stateNames = null;
+			else {
+				for (int is = 0; is<= CategoricalState.maxCategoricalState; is++) {
+					if (cData.hasStateName(oic, is)){
+						String s = cData.getStateName(oic, is);
+						if (!StringUtil.blank(s))
+							setStateName(ic, is, s);
+					}
+				}
+			} 
+			for (int is = 0; is<= CategoricalState.maxCategoricalState; is++) {
+				AttachedNotesVector s = cData.getStateAnnotationsVector(oic, is);
+				if (s != null) 
+					setStateAnnotationsVector(ic, is, s.cloneVector());
+			}
+		}
+		super.equalizeCharacter(oData, oic, ic);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state symbol for state "state", returned as string. */
+	public static String getDefaultStateSymbol(Class dataClass, int state) {
+		if (dataClass==DNAState.class) 
+			return DNAData.getDefaultStateSymbol(state);
+		else if (dataClass==RNAState.class) 
+			return RNAData.getDefaultStateSymbol(state);
+		else if (dataClass==ProteinState.class) 
+			return ProteinData.getDefaultStateSymbol(state);
+		else
+			return getDefaultStateSymbol(state);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state symbol for state "state", returned as string. */
+	public static String getDefaultStateSymbol( int state) {
+		if (state <0 || state>=defaultSymbols.length)
+			return String.valueOf(CharacterData.defaultInapplicableChar);
+		if (state>=0 &&  state <= CategoricalState.maxCategoricalState && defaultSymbols!=null )
+			return String.valueOf(defaultSymbols[state]);
+		else 
+			return Integer.toString(state);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** gets state symbol for state "state" of character ic, returned as string. */
+	public String getStateSymbol(int ic, int state) {
+
+		if (state <0 || symbols == null || state>=symbols.length)
+			return String.valueOf(getUnassignedSymbol());
+		if (state>=0 && symbols!=null ) {
+			return String.valueOf(symbols[state]);
+		}
+		else if (state >=0 && state <= CategoricalState.maxCategoricalState)
+			return String.valueOf(defaultSymbols[state]);
+		else 
+			return Integer.toString(state);
+	}
+	/*..........................................CategoricalData................*/
+	/** returns a long containing all of the states of a character.*/
+	public long getAllStates(int ic, boolean selectedOnly){
+		CategoricalState state=null;
+		long allstates =0L;
+		for (int it=0; it<numTaxa; it++) 
+			if (!selectedOnly || getTaxa().getSelected(it)) {
+				state =(CategoricalState)getCharacterState(state, ic, it);
+				if (!CategoricalState.isUnassigned(state.getValue()) && !CategoricalState.isInapplicable(state.getValue()))
+					allstates |= state.getValue();
+			}
+		return allstates;
+	}
+	/*..........................................CategoricalData................*/
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	public String getStatesSummary(int ic, boolean selectedOnly){
+		CategoricalState state=null;
+		long allstates =0L;
+		for (int it=0; it<numTaxa; it++) 
+			if (!selectedOnly || getTaxa().getSelected(it)) {
+				state =(CategoricalState)getCharacterState(state, ic, it);
+				if (!CategoricalState.isUnassigned(state.getValue()) && !CategoricalState.isInapplicable(state.getValue()))
+					allstates |= state.getValue();
+			}
+		return Integer.toString(CategoricalState.cardinality(allstates));
+	}
+	/*..........................................CategoricalData................*/
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	public String getStatesSummary(int ic){
+		return getStatesSummary(ic, false);
+	}
+	/*..........................................CategoricalData................*/
+	/** returns an integer array summarizing the frequencies of states of a character.*/
+	public int[] getStateFrequencyArray(int ic){
+		CategoricalState state=null;
+		int [] frequencies = new int[getTotalBitsInStateSet()];
+		IntegerArray.zeroArray(frequencies);
+		for (int it=0; it<numTaxa; it++) {
+			state =(CategoricalState)getCharacterState(state, ic, it);
+			if (state.isUnassigned())
+				frequencies[CategoricalState.unassignedBit]++;
+			else if (state.isInapplicable())
+				frequencies[CategoricalState.inapplicableBit]++;
+			else if (state.cardinality()==1){
+				frequencies[CategoricalState.getOnlyElement(state.getValue())]++;
+			}
+			else if  (state.cardinality()>1)
+				if (CategoricalState.isUncertain(state.getValue()))
+					frequencies[CategoricalState.polymorphismElement]++;
+				else
+					frequencies[CategoricalState.uncertainBit]++;
+		}
+		return frequencies;
+	}
+	/*..........................................CategoricalData................*/
+	/** returns a String summarizing the frequencies of states of a character .*/
+	public String  getStateFrequencyString(int ic){
+		int [] frequencies = getStateFrequencyArray(ic);
+		StringBuffer sb = new StringBuffer();
+		boolean first = true;
+		for (int i=0; i<=getMaxState(); i++)
+			if (frequencies[i]>0) {
+				if (!first)
+					sb.append(", ");
+				sb.append(getStateSymbol(ic,i)+ ": " + frequencies[i]);
+				first = false;
+			}
+		if (frequencies[CategoricalState.polymorphismElement]>0) {
+			if (!first)
+				sb.append(", ");
+			sb.append("Polymorphisms: "+ frequencies[CategoricalState.polymorphismElement]);
+			first = false;
+		}
+		if (frequencies[CategoricalState.uncertainBit]>0) {
+			if (!first)
+				sb.append(", ");
+			sb.append("Ambiguous: " + frequencies[CategoricalState.uncertainBit]);
+			first = false;
+		}
+		if (frequencies[CategoricalState.unassignedBit]>0) {
+			if (!first)
+				sb.append(", ");
+			sb.append(getUnassignedSymbol()+ ": " + frequencies[CategoricalState.unassignedBit]);
+			first = false;
+		}
+		if (frequencies[CategoricalState.inapplicableBit]>0) {
+			if (!first)
+				sb.append(", ");
+			sb.append(getInapplicableSymbol()+ ": " + frequencies[CategoricalState.inapplicableBit]);
+			first = false;
+		}
+		return sb.toString();
+	}
+	/*..........................................CategoricalData................*/
+	public static DefaultReference findDefaultReference(NameReference paradigm){
+		if (defaultModels == null) {
+			MesquiteMessage.warnProgrammer("findDefaultReference with null default models ");
+			MesquiteMessage.printStackTrace();
+			return null;
+		}
+		for (int i=0; i<defaultModels.size(); i++){
+			DefaultReference dR = (DefaultReference)defaultModels.elementAt(i);
+
+			if (dR.getParadigm() != null && dR.getParadigm().equals(paradigm))
+				return dR;
+		}
+		return null;
+
+	}
+	/*..........................................CategoricalData................*/
+	public static void registerDefaultModel(String paradigm, String name){
+		if (defaultModels == null)
+			return;
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR == null) {
+			dR = new DefaultReference(p);
+			defaultModels.addElement(dR);
+		}
+		dR.setDefault(name);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public CharacterModel getDefaultModel(String paradigm){
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR==null)
+			return null;
+		else {
+			CharacterModel cm = getProject().getCharacterModel(dR.getDefault());
+			if (cm==null) 
+				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+			return cm;
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) specified in the long array s.  The first element in s is presumed (for the sake of state symbols
+	 * and state names) to correspond to character ic. */
+	public void statesIntoStringBufferCore(int ic, long[] s, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		for (int i=0; i<s.length; i++) {
+			statesIntoStringBufferCore(ic+i, s[i],  sb, forDisplay, includeInapplicable, includeUnassigned);
+		}
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it. �*/
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay){
+		statesIntoStringBufferCore(ic,s,sb,forDisplay, true, true);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it. �*/
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		if (s==CategoricalState.inapplicable) {
+			if (includeInapplicable)
+				sb.append(getInapplicableSymbol());
+		}
+		else if (s==CategoricalState.unassigned) {
+			if (includeUnassigned)
+				sb.append(getUnassignedSymbol());
+		}
+		else {
+			boolean first=true;
+			char sep;
+			if (CategoricalState.isUncertain(s))
+				sep = '/';
+			else
+				sep = '&';
+			for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+				if (CategoricalState.isElement(s, e)) {
+					if (!first)
+						sb.append(sep);
+					if (forDisplay)
+						sb.append(getStateName(ic, e));
+					else
+						sb.append(getStateSymbol(ic, e));
+					first=false;
+				}
+			}
+			if (first)
+				sb.append('!'); //no state found!
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it.�*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		if (notInStorage(ic, it)) //illegal check
+			return;
+		long s = getStateRaw(ic, it);
+		statesIntoStringBufferCore(ic,s,sb, forDisplay, includeInapplicable, includeUnassigned);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it.�*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay){
+		statesIntoStringBuffer(ic,it,sb, forDisplay, true, true);
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it.�*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, String separatorForMultistate, String bracketForMultistateStart, String bracketForMultistateEnd){
+		if (notInStorage(ic, it)) //illegal check
+			return;
+		long s = getStateRaw(ic, it);
+		if (s==CategoricalState.inapplicable) {
+			sb.append(getInapplicableSymbol());
+		}
+		else if (s==CategoricalState.unassigned) {
+			sb.append(getUnassignedSymbol());
+		}
+		else {
+			boolean first=true;
+			if (CategoricalState.hasMultipleStates(s))
+				sb.append(bracketForMultistateStart);
+			for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+				if (CategoricalState.isElement(s, e)) {
+					if (!first)
+						sb.append(separatorForMultistate);
+					sb.append(getStateSymbol(ic, e));
+					first=false;
+				}
+			}
+			if (CategoricalState.hasMultipleStates(s))
+				sb.append(bracketForMultistateEnd);
+			if (first)
+				sb.append('!'); //no state found!
+		}
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** appends to buffer string describing the state(s) of character ic in taxon it. �*/
+	public void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb){
+		if (notInStorage(ic, it)) //illegal check
+			return;
+		boolean first=true;
+		long s = getStateRaw(ic, it);
+		if (s == 0L || s == CategoricalState.impossible)
+			sb.append('!');
+		else if (s==CategoricalState.inapplicable)
+			sb.append(getInapplicableSymbol());
+		else if (s==CategoricalState.unassigned)
+			sb.append(getUnassignedSymbol());
+		else {
+			int card =0;
+			int current = sb.length();
+			for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+				if (CategoricalState.isElement(s, e)) {
+					card++;
+					if (!first) {
+						sb.append(' ');
+					}
+					sb.append(getStateSymbol(ic, e));
+					first=false;
+				}
+			}
+			if (card>1) {
+				if (CategoricalState.isUncertain(s)) {
+					sb.insert(current,'{');
+					sb.append('}');
+				}
+				else {
+					sb.insert(current,'(');
+					sb.append(')');
+				}
+			}
+			if (first){ //nothing written!  Write illegal character so that change will not go unnoticed
+				sb.append('!');
+				if (ic == 0 && it == 0)
+					ecount = 0;
+				if (ecount++<100)
+					MesquiteMessage.warnProgrammer("ERROR: nothing written for character " + (ic+1) + " taxon " + (it+1) + " state as long: " + s + "  (matrix " + getName() + ")");
+			}
+		}
+	}
+	int ecount = 0;
+
+	/*..........................................  CategoricalData  ..................................................*/
+	CategoricalState tempState = (CategoricalState)makeCharacterState(); //a utility CategoricalState for the fromChar method, which isn't static
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Set the state at character ic from the string s, beginning at position pos in the string. �*/ 
+	public long fromString(int ic, Parser parser, boolean fromEditor, MesquiteInteger resultCode, MesquiteString result){
+		if (ic>=numChars || ic < 0) { //does not allow request for state for character other than those in matrix
+			if (resultCode!=null)
+				resultCode.setValue(OUTOFBOUNDS);
+			return CategoricalState.impossible;
+		}
+
+		if (parser== null || parser.blank()) { //no string passed // 
+			if (resultCode!=null)
+				resultCode.setValue(ERROR);
+			return CategoricalState.unassigned;
+		}
+		long stateSet = 0;
+		int multi = 0;
+		if (fromEditor)  { //string is from editor; thus will use /,& instead of {},() for uncertainty,polymorphism
+			parser.setPunctuationString(puncString);
+			parser.setPosition(0);
+			parser.setWhitespaceString("");  // whitespace can be present WITHIN a state name!
+			String t;
+			while (!StringUtil.blank(t = parser.getNextToken())){
+				//todo: what if linefeed comes in because parser so set?
+				if (t.length()==1) {  //single character token
+					char c = t.charAt(0) ;
+					if (c == ANDseparator || c == ',') 
+						multi = 1;
+					else if (c == ORseparator) 
+						multi = 2;
+					else if (c == getInapplicableSymbol()) {
+						multi = 0;
+						stateSet = CategoricalState.inapplicable;
+					}
+					else if (c== getUnassignedSymbol()){
+						multi = 0;
+						stateSet = CategoricalState.unassigned;
+					}
+					else if (c == getMatchChar()) {
+						stateSet = getStateRaw(ic, 0);
+					}
+					else {
+						long thisState = fromChar(c);
+						if (thisState == 0L)
+							stateSet |= CategoricalState.makeSet(MesquiteInteger.fromString(t));
+						else
+							stateSet |= thisState;
+					}
+				}
+				else { //multi character token
+					boolean found=false;
+					if (hasStateNames(ic)) { //try to interpret as state name
+						for (int i=0; i<stateNames[ic].length && !found; i++) {
+							if (t.equalsIgnoreCase(getStateName(ic, i))) {
+								stateSet |= CategoricalState.makeSet(i);
+								found = true;
+							}
+						}
+					}
+					if (!found) { //no state name; possibly several symbols without punctuation
+						for (int i=0; i<t.length(); i++){
+							long stt = fromChar(t.charAt(i));
+							if (stt == CategoricalState.impossible) {
+								if (result!=null) {
+									result.setValue("Illegal entry in cell.");
+									resultCode.setValue(ERROR);
+								}
+								return CategoricalState.impossible;
+							}
+							stateSet |= stt;
+						}
+						if (stateSet == 0L && result!=null) {
+							result.setValue("Illegal entry in cell.");
+							resultCode.setValue(ERROR);
+						}
+					}
+				}
+			}
+		}
+
+		else { //String is not from editor; assume it's from matrix in NEXUS file.  Thus, assume symbols, not names
+			boolean done = false;
+			int loc = parser.getPosition();
+			parser.setPunctuationString(null);
+			StringBuffer s = parser.getBuffer(); 
+			while (loc<s.length() && !done) {
+				char c = s.charAt(loc++); //get next dark character
+				boolean wasWhitespace = false;
+				while ((wasWhitespace=parser.whitespace(c))  && c!=0 && loc<s.length())
+					c = s.charAt(loc++);
+
+				if (!wasWhitespace){
+					if (parser.lineEndCharacter(c)) {
+						char r = parser.charOnDeck(1);
+						//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+						if (r!=c && parser.lineEndCharacter(r))
+							loc++;
+						if (resultCode!=null)
+							resultCode.setValue(EOL);
+						stateSet =CategoricalState.impossible;
+						done = true;
+					}
+					else if (c == '(') //polymorphism
+						multi = 1;
+					else if (c == '{') //uncertainty
+						multi = 2;
+					else if (c == '}' || c == ')') 
+						done = true;
+					else if (c == getInapplicableSymbol()) {
+						stateSet = CategoricalState.inapplicable;
+						multi = 0;
+						done = true;
+					}
+					else if (c== getUnassignedSymbol()) {
+						done = true;
+						multi = 0;
+						stateSet = CategoricalState.unassigned;
+					}
+					else if (c == getMatchChar()) {
+						done = true;
+						//OKKKKKK
+						stateSet = getStateRaw(ic, 0);
+					}
+					else if (multi>0) {
+						long state =  fromChar(c);
+						if (CategoricalState.isCombinable(state))
+							stateSet |=  state;
+					}
+					else {
+						stateSet =  fromChar(c);  //OKKKKKKK
+						done = true;
+					}
+				}
+			}
+			parser.setPosition(loc);
+		}
+		if (multi == 2)
+			stateSet = CategoricalState.setUncertainty(stateSet, true);
+		return stateSet;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	public long obviousFromChar(char c){
+		if (c == symbols[0])
+			return 1L;
+		else if (c == symbols[1])
+			return 2L;
+		return 0L;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/**Set the state at character ic from the string s, beginning at position pos in the string. �*/ 
+	public long fromStringQuickNexusReading(int ic, Parser parser, MesquiteInteger resultCode){
+		long stateSet = 0;
+		int multi = 0;
+		boolean done = false;
+		int loc = parser.getPosition();
+		parser.setPunctuationString(null);
+		StringBuffer s = parser.getBuffer(); 
+		while (loc<s.length() && !done) {
+			char c = s.charAt(loc++); //get next dark character
+			long obviousState = obviousFromChar(c);
+			if (obviousState != 0L && multi<1){   //  added "&& multi<1" as it couldn't process entries like "(01)" DRM 8 July '09
+				parser.setPosition(loc);
+
+				return obviousState;
+			}
+			else {
+				boolean wasWhitespace = false;
+				while ((wasWhitespace=parser.whitespace(c))  && c!=0 && loc<s.length())
+					c = s.charAt(loc++);
+
+				if (!wasWhitespace){
+					if (parser.lineEndCharacter(c)) {
+						char r = parser.charOnDeck(1);
+						//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+						if (r!=c && parser.lineEndCharacter(r))
+							loc++;
+						if (resultCode!=null)
+							resultCode.setValue(EOL);
+						stateSet =CategoricalState.impossible;
+						done = true;
+					}
+					else if (c == '(') //polymorphism
+						multi = 1;
+					else if (c == '{') //uncertainty
+						multi = 2;
+					else if (c == '}' || c == ')') 
+						done = true;
+					else if (c == getInapplicableSymbol()) {
+						stateSet = CategoricalState.inapplicable;
+						multi = 0;
+						done = true;
+					}
+					else if (c== getUnassignedSymbol()) {
+						done = true;
+						multi = 0;
+						stateSet = CategoricalState.unassigned;
+					}
+					else if (c == getMatchChar()) {
+						done = true;
+						//OKKKKKK
+						stateSet = getStateRaw(ic, 0);
+					}
+					else if (multi>0) {
+						long state =  fromChar(c);
+						if (CategoricalState.isCombinable(state))
+							stateSet |=  state;
+					}
+					else {
+						stateSet =  fromChar(c);  //OKKKKKKK
+						done = true;
+					}
+				}
+			}
+		}
+		parser.setPosition(loc);
+
+		if (multi == 2)
+			stateSet = CategoricalState.setUncertainty(stateSet, true);
+		return stateSet;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Given a character, what state set is implied.  Looks up character among current symbols. �*/
+	public long fromChar(char state){
+		if (state == getInapplicableSymbol())
+			return CategoricalState.inapplicable;
+		else if (state== getUnassignedSymbol())
+			return  CategoricalState.unassigned;
+		else if (state == getMatchChar()) {
+			return CategoricalState.unassigned; //note: this should't happen, as matchchar with no char #
+		}
+		else {
+			for (int ist = 0; ist<symbols.length; ist++) {
+				if (symbols[ist]==state) {
+					return CategoricalState.makeSet(ist);
+				}
+			}
+			return tempState.fromChar(state);
+		}
+	}
+	/*..........................................CategoricalData.....................................*/
+	/**returns the maximum possible state */
+	public int getMaxPossibleState() {
+		return CategoricalState.getMaxPossibleStateStatic();
+	}
+	/*..........................................CategoricalData.....................................*/
+	/**returns the maximum possible state */
+	public int getTotalBitsInStateSet() {
+		return CategoricalState.getTotalBitsInStateSet();
+	}
+	/*..........................................CategoricalData.....................................*/
+	/**returns the maximum possible state */
+	public double[] getFrequencies(boolean includeAmbiguous, boolean ambiguousBasedOnFreq, int it1, int it2) {
+		int max = getMaxPossibleState()+1;
+		double[] freq = new double[max];
+		long count = 0;
+		for (int e = 0; e<max; e++)
+			freq[e]=0.0;
+		for (int ic= 0; ic<numChars; ic++){
+			double[] freqIT = new double[max];;
+			if (ambiguousBasedOnFreq) {
+				long itCount = 0;
+				for (int e = 0; e<max; e++)
+					freqIT[e]=0.0;
+				for (int it=0; it<numTaxa; it++) {
+					if (it==it1 || it==it2 || it1<0 || it2<0 || !MesquiteInteger.isCombinable(it1) || !MesquiteInteger.isCombinable(it2)) {
+						long s = getState(ic,it);
+						int e = CategoricalState.getOnlyElement(s);
+						if (e>=0 && e<max) {
+							freqIT[e]+=1.0;
+							itCount++;
+						}
+					}
+				}
+				if (itCount>0)
+					for (int e = 0; e<max; e++)
+						freqIT[e]=freqIT[e]/itCount;
+			}
+			for (int it=0; it<numTaxa; it++) {
+				if (it==it1 || it==it2 || it1<0 || it2<0 || !MesquiteInteger.isCombinable(it1) || !MesquiteInteger.isCombinable(it2)) {
+					long s = getState(ic,it);
+					if (CategoricalState.isUnassigned(s)||CategoricalState.isInapplicable(s)||CategoricalState.isImpossible(s))
+						continue;
+					int e = CategoricalState.getOnlyElement(s);
+					if (e>=0 && e<max) {
+						freq[e]+=1.0;
+						count++;
+						continue;
+					}
+					int card = CategoricalState.cardinality(s);
+					if (card>0) {
+						if (!CategoricalState.isUncertain(s)) {
+
+							for (e = 0; e<max; e++) {
+								if (CategoricalState.isElement(s,e)) {
+									count++;
+									freq[e]+=1.0;
+								}
+							}
+						}
+						else if (includeAmbiguous) {
+							count++;
+							for (e = 0; e<max; e++) {
+								if (CategoricalState.isElement(s,e))
+									if (ambiguousBasedOnFreq && freqIT[e]!=0.0)
+										freq[e]+=freqIT[e];
+									else
+										freq[e]+=1.0/card;
+							}
+						}
+					}
+				}
+			}
+		}
+		if (count>0)
+			for (int e = 0; e<max; e++)
+				freq[e]=freq[e]/count;
+
+		return freq;
+	}
+
+	/*..........................................CategoricalData.....................................*/
+	/**merges the states for taxon it2 into it1  within this Data object */
+	public boolean mergeSecondTaxonIntoFirst(int it1, int it2) {
+		if ( it1<0 || it1>=getNumTaxa() || it2<0 || it2>=getNumTaxa() )
+			return false;
+
+		boolean mergedAssigned = false;
+		for (int ic=0; ic<getNumChars(); ic++) {
+			long s1 = getState(ic,it1);
+			long s2 = getState(ic,it2);
+			if ((s1& CategoricalState.statesBitsMask) != 0L && (s2& CategoricalState.statesBitsMask) != 0L)
+				mergedAssigned = true;
+
+			long sMerged = CategoricalState.mergeStates(s1,s2);
+			setState(ic,it1,sMerged);
+		}
+		return mergedAssigned;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategoricalDistribution.java b/Source/mesquite/categ/lib/CategoricalDistribution.java
new file mode 100644
index 0000000..feaa901
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalDistribution.java
@@ -0,0 +1,241 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public abstract class CategoricalDistribution extends CategoricalStates implements CharacterDistribution {
+	static long zeroOne = CategoricalState.setUncertainty(CategoricalState.addToSet(CategoricalState.makeSet(0), 1), true);
+	public CategoricalDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	public int getNumNodes(){
+		return getNumTaxa();
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		if (getMaxState()<0)
+			return zeroOne;
+		return CategoricalState.fullSet();
+	}
+	/*.................................................................................................................*/
+	/**Returns largest state value*/
+	public int getMaxState (){
+		int max = -1;
+		for (int i=0; i< getNumNodes(); i++) {
+			int ms = CategoricalState.maximum(getState(i));
+			if (ms>max)
+				max = ms;
+		}
+		return max;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has polymorphic or multstate uncertain data*/
+	public boolean hasMultipleStatesInTaxon(){
+		for (int i=0; i< getNumNodes(); i++)
+			if (CategoricalState.hasMultipleStates(getState(i)))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data*/
+	public boolean hasMissing (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isUnassigned(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps)*/
+	public boolean hasInapplicable (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isInapplicable(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has polymorphic data in the taxa of the tree*/
+	public boolean hasPolymorphicStatesInTaxon(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (!isUncertain(tree.taxonNumberOfNode(node)) && CategoricalState.hasMultipleStates(getState(tree.taxonNumberOfNode(node))))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasPolymorphicStatesInTaxon(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has polymorphic or multstate uncertain data in the taxa of the tree*/
+	public boolean hasMultipleStatesInTaxon(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (CategoricalState.hasMultipleStates(getState(tree.taxonNumberOfNode(node))))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasMultipleStatesInTaxon(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data in the taxa of the tree*/
+	public boolean hasMissing(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isUnassigned(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasMissing(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps) in the taxa of the tree*/
+	public boolean hasInapplicable(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isInapplicable(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasInapplicable(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is all binary and no missing in the taxa of the tree*/
+	public static boolean isBinaryNoMissing(CharacterDistribution dist, Tree tree){
+		if (!(dist instanceof CategoricalDistribution))
+			return false;
+		CategoricalDistribution cd = (CategoricalDistribution)dist;
+		return inIsBinary(cd, tree, tree.getRoot(), false);
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is all binary in the taxa of the tree*/
+	public static boolean isBinary(CharacterDistribution dist, Tree tree){
+		if (!(dist instanceof CategoricalDistribution))
+			return false;
+		CategoricalDistribution cd = (CategoricalDistribution)dist;
+		return inIsBinary(cd, tree, tree.getRoot(), true);
+	}
+	static boolean inIsBinary(CategoricalDistribution dist, Tree tree, int node, boolean permitMissing){
+
+		if (tree.nodeIsTerminal(node)){
+			if (permitMissing && !dist.isBinary(tree.taxonNumberOfNode(node)))
+				return false;
+			if (!permitMissing && !dist.isBinaryCombinable(tree.taxonNumberOfNode(node)))
+					return false;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (!inIsBinary(dist, tree, d, permitMissing))
+					return false;
+			}
+		}
+		return true;
+	}
+	/**Returns whether or not the character is binary*/
+	public boolean isBinary(int node){
+		return ((getState(node) & CategoricalState.statesBitsMask) | 3L) == 3L;
+	}
+	/**Returns whether or not the character is binary and with an actual state*/
+	public boolean isBinaryCombinable(int node){
+		return isBinary(node) && ((getState(node) & 3L) != 0L);
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same)*/
+	public boolean isConstant(){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = null;
+		for (int i=1; i< getNumNodes(); i++)
+			if (!cs.equals(cs2 = getCharacterState(cs2, i)))
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	private boolean isConstantRec(Tree tree, int node, CharacterState cs, CharacterState cs2){
+		if (tree.nodeIsTerminal(node)){
+			if (!cs.equals(cs2 = getCharacterState(cs2, tree.taxonNumberOfNode(node))))
+				return false;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (!isConstantRec(tree, d, cs, cs2))
+					return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	public boolean isConstant(Tree tree, int node){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = getCharacterState(null, 0);
+		return isConstantRec(tree, node, cs, cs2);
+	}
+	/*..........................................  CategoricalDistribution  ...................................................*/
+	/** returns a CharacterDistribution that is adjustable and has the same states*/
+	public AdjustableDistribution getAdjustableClone(){
+		CategoricalAdjustable soc = makeAdjustable(getTaxa());
+		for (int it=0; it<getNumTaxa(); it++)
+			soc.setState(it, getState(it));
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+	return soc;
+	}
+	/*..........................................  CategoricalDistribution  ...................................................*/
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new CategoricalAdjustable(taxa, taxa.getNumTaxa());
+	} 
+	/*..........................................  CategoricalDistribution  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == CategoricalHistory.class))
+//		if (charStates==null || ! (charStates instanceof CategoricalHistory))
+			soc = new CategoricalHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new CategoricalHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+
+}
+
diff --git a/Source/mesquite/categ/lib/CategoricalEmbedded.java b/Source/mesquite/categ/lib/CategoricalEmbedded.java
new file mode 100644
index 0000000..ee203bb
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalEmbedded.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public class CategoricalEmbedded extends CategoricalDistribution {
+	CategoricalData data;
+	public CategoricalEmbedded (CategoricalData data, int ic) {
+		super(data.getTaxa());
+		this.data = data;
+		characterNumber = ic; // check if within bounds?
+		enforcedMaxState = 0;
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return data.getStateClass();
+	}
+	public CharacterData getParentData(){
+		return data;
+	}
+	/*..........................................  CategoricalEmbedded  ...................................................*/
+	/** get number of taxa available in this categorical character.*/
+	public int getNumTaxa() {
+		return data.getNumTaxa();
+	}
+	/*..........................................  CategoricalEmbedded  ...................................................*/
+	/** get stateset at node N */
+	public long getState (int N) {
+		if (checkIllegalNode(N, 4))
+			return CategoricalState.unassigned;
+		return data.getState(characterNumber, N);
+	}
+	public String getName(){
+		return data.getCharacterName(characterNumber);
+	}
+	public String toString(){
+		return "Character " + characterNumber + " from data " + data + "   " + super.toString();
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategoricalHistory.java b/Source/mesquite/categ/lib/CategoricalHistory.java
new file mode 100644
index 0000000..ef8bf76
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalHistory.java
@@ -0,0 +1,549 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.cont.lib.ContColorTable;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class CategoricalHistory extends CategoricalAdjustable implements CharacterHistory {
+	private int watchPoint=-1;
+	Vector[] internodeHistories = null;  //for stochastic character mapping
+	long[][] conditionalStateSets = null;
+
+	public CategoricalHistory (Taxa taxa, int numNodes) {
+		super(taxa, numNodes);
+	}
+	public CategoricalHistory (Taxa taxa) {
+		super(taxa);
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	/**set all states to missing (unassigned)*/
+	public void deassignStates(){
+		super.deassignStates();
+		conditionalStateSets = null;
+		if (internodeHistories == null)
+			return;
+		for (int i = 0; i< numNodes && i <internodeHistories.length; i++)
+			if (internodeHistories[i] != null)
+				internodeHistories[i].removeAllElements();
+	}	
+
+	/*.................................................................................................................*/
+	public long getNumResolutions(Tree tree) {
+		MPRProcessor mprProcessor = new MPRProcessor(this);
+		return mprProcessor.getNumResolutions(tree);
+	}
+
+	/*.................................................................................................................*/
+	public CharacterHistory getResolution(Tree tree, CharacterHistory results, long num) {
+		MPRProcessor mprProcessor = new MPRProcessor(this);
+		return mprProcessor.getResolution(tree,results,num);
+	}
+
+	/*..........................................  CategoricalHistory  ..................................................*/
+	public boolean hasConditionalStateSets(){
+		return conditionalStateSets != null;
+	}
+	public void setConditionalStateSet(long s, int node, int stateAtAncestor){
+		if (conditionalStateSets == null){
+			conditionalStateSets = new long[numNodes][CategoricalState.maxCategoricalState+1];
+		}
+		conditionalStateSets[node][stateAtAncestor] = s;
+	}
+	public long getConditionalStateSet(int node, int stateAtAncestor){
+		if (conditionalStateSets == null)
+			return CategoricalState.unassigned;
+		return conditionalStateSets[node][stateAtAncestor];
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	public void prepareInternodeHistories(){ //for stochastic character mapping
+		internodeHistories = new Vector[numNodes];
+		for (int i = 0; i< numNodes; i++)
+			internodeHistories[i] = new Vector();
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	public Vector getInternodeHistoryVector(int node){ //for stochastic character mapping
+		if (internodeHistories == null)
+			return null;
+		if (node < 0 || node>= internodeHistories.length)
+			return null;
+		return internodeHistories[node];
+	}
+	public int getNumberOfEvents(int node){
+		if (internodeHistories == null)
+			return 0;
+		if (node < 0 || node>= internodeHistories.length)
+			return 0;
+		return internodeHistories[node].size();
+
+	}
+	public CategInternodeEvent getInternodeEvent(int node, int i){
+		if (internodeHistories == null)
+			return null;
+		if (node < 0 || node>= internodeHistories.length)
+			return null;
+		if (i<0 || i>= internodeHistories[node].size())
+			return null;
+		return (CategInternodeEvent)internodeHistories[node].elementAt(i);
+	}
+	public void addInternodeEvent(int node, CategInternodeEvent event){
+		if (internodeHistories == null)
+			prepareInternodeHistories();
+		if (node < 0 || node>= internodeHistories.length)
+			return;
+		internodeHistories[node].addElement(event);
+	}
+	/*..........................................  CategoricalHistory  ...................................................*/
+	private void harvestChanges(Tree tree,int node,  int[][] changes, int stateBelow) {
+		if (node != tree.getRoot() && tree.nodeExists(node)) {
+			if (getNumberOfEvents(node)>0){
+				for (int k = 0; k<getNumberOfEvents(node); k++) {
+					CategInternodeEvent event = getInternodeEvent(node, k);
+					long st = event.getState();
+					int stateHere = CategoricalState.getOnlyElement(st);
+					if (stateBelow >=0 && stateHere >=0 && stateBelow != stateHere)
+						changes[stateBelow][stateHere]++;						
+					stateBelow = stateHere;
+				}
+			}
+			else {
+				long st=getState(node);
+				int stateHere = CategoricalState.getOnlyElement(st);
+				if (stateBelow >=0 && stateHere >=0 && stateBelow != stateHere) {
+					changes[stateBelow][stateHere]++;
+				}
+				stateBelow = stateHere;
+			}
+		}
+		if (tree.nodeIsInternal(node)){
+			for(int d=tree.firstDaughterOfNode(node);tree.nodeExists(d);d=tree.nextSisterOfNode(d)) 
+				harvestChanges(tree,d, changes, stateBelow);
+		}
+
+	}	
+	/*..........................................   ...................................................*/
+
+	public int[][] harvestStateChanges(Tree tree, int node, int[][] results){
+		surveyStates(tree, node);
+		if (results == null || results.length < maxState+1)
+			results = new int[maxState+1][maxState+1];
+		for (int i=0; i<results.length; i++)
+			for (int k =0; k<results.length; k++)
+				results[i][k]=0;
+		harvestChanges(tree, node, results, CategoricalState.getOnlyElement(getState(node)));
+		return results;
+	}
+
+	/*..........................................  CategoricalHistory  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		String ss = super.toString(node, lineEnding);
+		int num = getNumberOfEvents(node);
+		if (num>0){
+			boolean showEvents = false;
+			String par = " (";
+			if (num>2)
+				par += (num-1) + " events: ";
+			else if (num>1)
+				par += (num-1) + " event: ";
+			for (int i= 0; i<num; i++){
+				CategInternodeEvent event = getInternodeEvent(node, i);
+				if (event.getChangeVersusSample()){
+					showEvents = true;
+					par += "\t" + CategoricalState.toString(event.getState()) + "@" + MesquiteDouble.toStringDigitsSpecified(event.getPosition(), 4);
+				}
+
+			}
+			if (showEvents)
+				ss += par + "\t)";
+		}
+		
+		return ss;
+	}
+
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/**set the passed history to be a clone of this one (should be renamed to setToClone!);
+	 *  if passed s is not null, place the clone there (so as to avoid creating new object)*/
+	public CharacterHistory clone(CharacterHistory s) {
+		CategoricalHistory snew;
+		if ((s==null) || (s.getNumNodes()!=numNodes) || (!(s instanceof CategoricalHistory)))
+			snew = new CategoricalHistory(getTaxa(), numNodes);
+		else {
+			snew = (CategoricalHistory)s;
+		}
+		for (int i=0; i<numNodes; i++) {
+			snew.setState(i, getState(i));
+		}
+		if (frequenciesExist())
+			copyFrequencies(this, snew);
+		else
+			snew.disposeFrequencies();
+		if (extraFrequenciesExist())
+			copyExtraFrequencies(this, snew);
+		else
+			snew.disposeExtraFrequencies();
+		if (hasConditionalStateSets()) {
+			for (int it = 0; it<numNodes; it++)
+				for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++)
+					snew.setConditionalStateSet(getConditionalStateSet(it, ist), it, ist);
+		}
+		else
+			snew.conditionalStateSets = null;
+		snew.data = data;
+		snew.characterNumber = characterNumber;  //setting parent character
+		if (observedStates!=null)
+			snew.setObservedStates((CharacterDistribution)observedStates.getAdjustableClone());
+		if (internodeHistories == null)
+			snew.internodeHistories = null;
+		else {
+			snew.prepareInternodeHistories();
+			for (int node = 0; node<numNodes; node++){
+				for (int i = 0; i<getNumberOfEvents(node); i++)
+					snew.addInternodeEvent(node, getInternodeEvent(node, i).cloneEvent());
+			}
+		}
+		snew.setExplanation(getExplanation());
+		return snew;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** Returns a new object indicating the states at the tips (used whether or not History is reconstruction)*/
+	public CharacterDistribution getStatesAtTips(Tree tree){
+		if (observedStates !=null)
+			return (CharacterDistribution)observedStates.getAdjustableClone();
+		else {
+			CharacterState c = getCharacterState();
+			CategoricalAdjustable d = (CategoricalAdjustable)c.makeAdjustableDistribution(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+			fillDistribution(tree, tree.getRoot(), d);
+			return d;
+		}
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	private void fillDistribution(Tree tree, int node, CategoricalAdjustable dist) {  
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			dist.setState(t, getState(node));
+		}
+		else for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			fillDistribution(tree, d, dist);
+	}
+
+	CharacterDistribution observedStates;
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** Returns the states in the terminal taxa (used if History is reconstruction)*/
+	public CharacterDistribution getObservedStates(){
+		return observedStates;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** Sets the states in the terminal taxa (used if History is reconstruction)*/
+	public void setObservedStates(CharacterDistribution observed){
+		this.observedStates = observed;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	private void surveyStates(Tree tree, int node) {  // establishes min, max, etc. for use in color returning
+		if (checkIllegalNode(node, 9))
+			return;
+		long s = 0L;
+		if (frequenciesExist())
+			s=getSetFromFrequencies(node);
+		else
+			s=getState(node);
+		if (getNumberOfEvents(node)>0){
+			for (int k = 0; k<getNumberOfEvents(node); k++) {
+				CategInternodeEvent event = getInternodeEvent(node, k);
+				long st = event.getState();
+				if (CategoricalState.isCombinable(st))
+					s |= st;
+			}
+		}
+		allStates|=s; 
+		if ((!minFound) || (CategoricalState.minimum(s)<minState)) {
+			minState=CategoricalState.minimum(s);
+			minFound=true;
+		}
+		if ((!maxFound) || (CategoricalState.maximum(s)>maxState)) {
+			maxState=CategoricalState.maximum(s);
+			maxFound=true;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			surveyStates(tree, d);
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	private void surveyTerminalStates(Tree tree, int node) {  // establishes min, max, etc. for use in color returning
+		if (tree.nodeIsTerminal(node)) {
+			checkIllegalNode(tree.taxonNumberOfNode(node), 10);
+			long s = 0L;
+			if (frequenciesExist()) 
+				s = getSetFromFrequencies(tree.taxonNumberOfNode(node));
+			else 
+				s=getState(tree.taxonNumberOfNode(node));
+			allStates|=s; 
+			if ((!minFound) || (CategoricalState.minimum(s)<minState)) {
+				minState=CategoricalState.minimum(s);
+				minFound=true;
+			}
+			if ((!maxFound) || (CategoricalState.maximum(s)>maxState)) {
+				maxState=CategoricalState.maximum(s);
+				maxFound=true;
+			}
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			surveyTerminalStates(tree, d);
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** Must be called before colors for states are used (e.g., before a tree is shaded).  Goes through all nodes to find states present, to set
+	minima and maxima and record all states present. This allows the color range to be known before
+	colors for particular states are requested by a tree shade, for example.*/
+	public void prepareColors(Tree tree, int drawnRoot) {  
+		minFound=false;
+		maxFound=false;
+		allStates=0;
+		if (tree.getNumNodeSpaces()>getNumNodes()) {
+			surveyTerminalStates(tree, drawnRoot);
+		}
+		else {
+			surveyStates(tree, drawnRoot);
+		}
+		long s = allStates;
+		if (data!=null && getParentCharacter()>=0){
+			long obsAll = ((CategoricalData)data).getAllStates(getParentCharacter());
+			s |= obsAll;
+		}
+		else if (observedStates!=null && observedStates instanceof CategoricalDistribution){
+			long obsAll = ((CategoricalDistribution)observedStates).getAllStates();
+			s |= obsAll;
+		}
+		if (enforcedMaxState == 0) {
+			maxState = CategoricalState.maximum(s);//+getExtraNumFreqCategories();
+		}
+		else
+			maxState = enforcedMaxState;
+	}
+	/*..........................................CategoricalHistory................*/
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable) {
+
+		if (colorTable == null) // || !(colorTable instanceof CategColorTable))
+			return new MesquiteColorTable();
+		   if (colorTable.getMode() == MesquiteColorTable.COLORS_NO_BW)
+			   colorTable.setMode(MesquiteColorTable.COLORS);
+		return colorTable;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** places into the already instantiated ColorDistribution the colors corresponding to the CharacterState, and returns the number of colors.  Uses default colors. 
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*/
+	public int getColorsOfState(CharacterState state, ColorDistribution colors, MesquiteColorTable colorTable) {
+		if (colors==null || state == null || ! (state instanceof CategoricalState))
+			return 0;
+		colors.initialize();
+		int colorCount=0;
+		long s = ((CategoricalState)state).getValue();
+		for (int i=0; i<=maxState; i++) {
+			if (CategoricalState.isElement (s,i)) {
+				colors.setWeight(colorCount, 1.0);
+				if (data==null) 
+					colors.setColor(colorCount++, colorTable.getColor(maxState,i));//HERE
+				else 
+					colors.setColor(colorCount++, ((CategoricalData)data).getColorOfState(characterNumber, i, maxState, colorTable));//HERE
+			}
+		}
+		return colorCount;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** places into the already instantiated ColorDistribution the colors corresponding to the CharacterState, and returns the number of colors.  Uses default colors. 
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*
+	public int getColorsAtNode(int node, ColorDistribution colors, boolean showWeights,int mode) {
+		if (checkIllegalNode(node, 11))
+			return 0;
+		return getColorsAtNode(node, colors, null, showWeights, mode);
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/** Places into ColorDistribution the colors at the node, and returns the number of colors.  Uses passed
+	stateColors as color key.  If null is passed, uses color system of parent data (using maxState of this
+	StsOfCharcter) or, if there is not parent data object, the default colors. *
+	public int getColorsAtNode(int node, ColorDistribution colors,MesquiteColorTable stateColors, boolean showWeights) {
+		return getColorsAtNode(node, colors, stateColors, showWeights, MesquiteColorTable.DEFAULT);
+	}
+	 */
+	public Color getDefaultColor(int maxState, int istate){
+		return MesquiteColorTable.getDefaultColor(maxState,istate, MesquiteColorTable.COLORS);
+	}
+	/*..........................................CategoricalHistory................*/
+	public int getColorsAtNode(int node, ColorDistribution colors, MesquiteColorTable stateColors, boolean showWeights) {
+		if (checkIllegalNode(node, 12))
+			return 0;
+		if (colors==null)
+			return 0;
+		colors.initialize();
+		int colorCount=0;
+		long s;
+		if (frequenciesExist() && showWeights)
+			s = CategoricalState.compressFromPresence(getFrequencies(node));
+		else 
+			s = states[node];
+
+		for (int i=0; i<=maxState; i++) {
+			if (CategoricalState.isElement (s,i)) {
+				if (frequenciesExist() && showWeights)
+					colors.setWeight(colorCount, getFrequency(node, i));
+				else
+					colors.setWeight(colorCount, 1.0);
+				if (stateColors==null) {
+					if (data==null) {
+						colors.setColor(colorCount++, getDefaultColor(maxState,i));
+					}
+					else {
+						colors.setColor(colorCount++, ((CategoricalData)data).getColorOfState(characterNumber, i, maxState));
+					}
+				}
+				else {
+					colors.setColor(colorCount++, stateColors.getColor(maxState,i));
+				}
+			}
+		}
+		if (extraFrequenciesExist() && showWeights)
+			for (int i=0; i<getExtraNumFreqCategories(); i++) 
+				if (getExtraFrequency(node,i)>0.0) {
+					colors.setWeight(colorCount, getExtraFrequency(node,i));
+					if (getExtraFrequencyColors()!=null)
+						colors.setColor(colorCount++, getExtraFrequencyColors().getColor(i));
+				}
+
+		if (colorCount<=0) {
+			colors.setColor(0, ColorDistribution.unassigned);
+			colorCount = 1;
+		}
+		return colorCount;
+	}
+	/*..........................................CategoricalHistory................*/
+	/** returns the vector of ColorEvents in order, e.g. for stochastic character mapping.  Return null if none */
+	public ColorEventVector getColorSequenceAtNode(int node, MesquiteColorTable colorTable){
+		if (checkIllegalNode(node, 1214))
+			return null;
+		if (getNumberOfEvents(node) <1)
+			return null;
+
+		ColorEventVector vector = new ColorEventVector();
+		for (int i=0; i< getNumberOfEvents(node); i++) {
+
+			CategInternodeEvent event = getInternodeEvent(node, i);
+			Color color = null;
+			int state = CategoricalState.minimum(event.getState());
+			if (colorTable != null)
+				color = colorTable.getColor(maxState, state);
+			else if (data==null)
+				color = getDefaultColor(maxState,state);
+			else 
+				color = ((CategoricalData)data).getColorOfState(characterNumber, state, maxState);
+
+			vector.addElement(new ColorEvent(color, event.getPosition()));
+
+		}
+		vector.sort();
+		return vector;
+	}
+	/*..........................................CategoricalHistory................*/
+	/**Get the information about states occurring in this object for a legend.  Colors and state names of states
+	are place in the passed array.  The colors for states are taken from the passed MesquiteColorTable.*/
+	public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) {
+		if (cs==null || stateNames == null)
+			return 0;
+		int colorCount=0;
+		long s = allStates;
+		int maxStateLegend = maxState;
+
+		if (data!=null && getParentCharacter()>=0){
+			long obsAll = ((CategoricalData)data).getAllStates(getParentCharacter());
+			s |= obsAll;
+			int mso = ((CategoricalData)data).getMaxState(getParentCharacter());
+			if (maxStateLegend<mso)
+				maxStateLegend = mso;
+		}
+		for (int e=0; e<=maxStateLegend && colorCount<cs.length && colorCount<stateNames.length; e++) {
+			if (CategoricalState.isElement (s,e)) {
+				/*if (stateColors==null) {
+					if (data == null)
+						cs[colorCount]= getDefaultColor(maxStateLegend,e); //HERE
+					else
+						cs[colorCount]= ((CategoricalData)data).getColorOfState(-1,e, maxStateLegend);//HERE
+				}
+				else {*/
+				if (stateColors==null)
+					cs[colorCount] = Color.gray;
+				else
+					cs[colorCount]= stateColors.getColor(maxStateLegend,e);
+				if (tableMappings != null){
+					tableMappings[colorCount] = new Point(maxStateLegend, e);
+				}
+				//}
+				if (data!=null && characterNumber>=0 && characterNumber<data.getNumChars() && data instanceof CategoricalData) {
+					stateNames[colorCount++]=((CategoricalData)data).getStateName(characterNumber, e);
+				}
+				else
+					stateNames[colorCount++]=Integer.toString(e);
+			}
+		}
+		if (extraFrequenciesExist())
+			for (int i=0; i<getExtraNumFreqCategories(); i++) {
+				if (getExtraFrequencyColors()!=null)
+					cs[colorCount] = getExtraFrequencyColors().getColor(i);
+				String [] names = getExtraFrequencyNames();
+				if (names!=null && i>=0 && i<names.length)
+					stateNames[colorCount++]=names[i];
+			}
+		/*if (colorCount<=0)
+			MesquiteMessage.println("getLegendStates: no states found");
+		 */
+		return colorCount;
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	/**Get the information about states occurring in this object for a legend.  Colors and state names of states
+	are place in the passed array.*
+	public int getLegendStates(Color[] cs, String[] stateNames, int mode) {
+		return getLegendStates(cs, stateNames, null, mode);
+	}
+	/*..........................................  CategoricalHistory  ..................................................*/
+	public CharacterHistory adjustSize(Tree tree) {
+		if (tree.getNumNodeSpaces() == this.getNumNodes())
+			return this;
+		else {
+			CategoricalHistory soc = new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			soc.setExplanation(getExplanation());
+			return soc;
+		}
+	}
+	public CharacterHistory makeHistory(Tree tree){
+		return new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+	}
+	/*................................................................................................................*/
+	public void polymorphToUncertainties(int N, Tree tree) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			polymorphToUncertainties(d, tree);
+		}
+		if (tree.nodeIsInternal(N)){
+			long s = getState(N);
+			if (CategoricalState.cardinality(s)>1)
+				setState(N, CategoricalState.setUncertainty(s, true));
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategoricalState.java b/Source/mesquite/categ/lib/CategoricalState.java
new file mode 100644
index 0000000..feb2a45
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalState.java
@@ -0,0 +1,1085 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**This class provides some basic utilities for sets of states of categorical characters.  Many of the utilities are static to be used for basic
+set calculations, but a categorical set can also be instantiated so as to have a parameter to pass by reference.
+
+In most calculates, state sets of categorical characters are NOT stored with these objects because it would be too costly.  Instead,
+they are stored as simple long variables (64 bits, 56 possible states).*/
+public class CategoricalState extends CharacterState{
+	/** The state (1L<<63) that corresponds to missing data.*/
+	public static final long unassigned = 1L<<63;  //-9223372036854775808
+	/** The state that corresponds to a gap (inapplicable)*/
+	public static final long inapplicable = 1L<<59;   //576460752303423488
+	/** The state (1L<<62) that corresponds to an invalid CategoricalState.*/
+	public static final long impossible = 1L<<62;  //4611686018427387904
+	
+	public static final short unassignedShort = compressToShort(unassigned);
+	public static final short inapplicableShort = compressToShort(inapplicable);
+	public static final short impossibleShort = compressToShort(impossible);
+
+	/** a value for arrays that store information about frequency of states; this would need to change if ever maxCategoricalState goes to 58*/
+	public static final int polymorphismElement = 58;
+	/** The bit that signals missing data */
+	public static final int unassignedBit = 63;
+	/** The bit that signals a gap (inapplicable) */
+	public static final int inapplicableBit = 59;
+	/** The bit that signals uncertainty */
+	public static final int uncertainBit = 61;
+	/** The bit that signals the symbol is to be shown lower case */
+	public static final int lowerCaseBit = 60;
+	/** The maximum allowed categorical state (55) */
+	public static  final int maxCategoricalState = 55;
+	/** The mask that preserves the high bits used for special flags*/
+	public static final long highBitsMask = (~0L)<<59;
+	/** The mask that preserves bits 0.. maxCategoricalState*/
+	public static final long statesBitsMask = (~0L)>>>8;
+	/** The mask that preserves bits 0.. maxCategoricalState and the unassigned, impossible and uncertain bits */
+	public static final long dataBitsMask = (statesBitsMask | unassigned | impossible | inapplicable | (1L<<uncertainBit));
+	public static final short highBitsMaskShort = compressToShort(highBitsMask);
+	public static final short statesBitsMaskShort = compressToShort(statesBitsMask);
+	public static final short dataBitsMaskShort = compressToShort(dataBitsMask);
+
+	/** Bits to be used if int used instead of long for state storage */
+	public static final int unassignedBitInt= 31;
+	public static final int inapplicableBitInt = 27;
+	public static final int uncertainBitInt = 29;
+	public static final int statesBitsMaskInt = (~0)>>>8;
+	
+	
+	public static final int TOTALBITS = 64;  //for use by other classes that might want to make, say, an array for the bits
+	
+	private static final int MAXBIT = 63; //MAXBIT for bitwise manipulations
+	long set; //the value stored for an instantiation of this
+	
+	public CategoricalState () {
+		set = unassigned;
+	}
+	public CategoricalState (long initial) {
+		set = initial;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return CategoricalData.DATATYPENAME;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the class of the corresponding (i.e. of same data type) CharacterData object (in this case, CategoricalData.class). */
+	public Class getCharacterDataClass() {
+		return CategoricalData.class;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the Adjustable class of the corresponding (i.e. of same data type) MCharactersDistribution object (in this case, MCategoricalAdjustable.class). */
+	public Class getMCharactersDistributionClass(){
+		return MCategoricalAdjustable.class;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the Adjustable class of the corresponding (i.e. of same data type) CharacterDistribution object (in this case, CategoricalAdjustable.class). */
+	public Class getCharacterDistributionClass() {
+		return CategoricalAdjustable.class;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the class of the corresponding (i.e. of same data type) CharacterHistory object (in this case, CategoricalHistory.class). */
+	public Class getCharacterHistoryClass() {
+		return CategoricalHistory.class;
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new CategoricalAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new CategoricalHistory(taxa, numNodes);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state set passed is unassigned (missing data) */
+	public static boolean isUnassigned(short s) {
+		return s == unassignedShort;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state set passed is unassigned (missing data) */
+	public static boolean isUnassigned(long s) {
+		return s == unassigned;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff stateset is unassigned (missing data) */
+	public boolean isUnassigned() {
+		return set == unassigned;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state set passed is inapplicable. */
+	public static boolean isInapplicable(short s) {
+		return s == inapplicableShort;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state set passed is inapplicable. */
+	public static boolean isInapplicable(long s) {
+		return s == inapplicable;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state set is inapplicable */
+	public boolean isInapplicable() {
+		return set == inapplicable;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether value is valid or not.*/
+	public boolean isImpossible(){
+		return set == impossible;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether value is valid or not.*/
+	public static boolean isImpossible(short s){
+		return s == impossibleShort;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether value is valid or not.*/
+	public static boolean isImpossible(long s){
+		return s == impossible;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether value is combinable (i.e. a valid assigned state) or not.*/
+	public boolean isCombinable(){
+		return !(set == impossible || set == inapplicable || set == unassigned || (set & statesBitsMask) == 0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether value is combinable (i.e. a valid assigned state) or not.*/
+	public static boolean isCombinable(long s){
+		return !(s == impossible || s == inapplicable || s == unassigned || (s & statesBitsMask) == 0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** returns whether state is within allowed range.*/
+	public static boolean legalState(int e){
+		return e>= 0 && e<=maxCategoricalState;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s) {
+		return equals(s, false, false);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing) {
+		return equals(s, allowMissing, false);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact) {
+		return equals(s, allowMissing, allowNearExact, false);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact, boolean allowSubset) {
+		if (s==null)
+			return false;
+		if (!(s instanceof CategoricalState))
+			return false;
+		if (allowMissing && (isUnassigned() || s.isUnassigned())) //fixed June 02
+				return true;
+		long t = getValue();
+		long tO = ((CategoricalState)s).getValue();
+		if (allowSubset) {
+			if (t == tO)
+				return true;
+			if (isUncertain(t) || isUncertain(tO)){
+				t = statesBitsMask & t;
+				tO = statesBitsMask & tO;
+				return t == (t | tO) || tO == (t | tO);
+			}
+			if (allowNearExact)
+				return (setLowerCase(tO, false) == setLowerCase(t,false));
+			return false;
+		}
+		if (allowNearExact)
+			return (setLowerCase(tO, false) == setLowerCase(t,false));
+		return t == tO;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equalsIgnoreCase(CategoricalState s) {
+		if (s==null)
+			return false;
+		long t = getValue();
+		long tO = ((CategoricalState)s).getValue();
+		return (setLowerCase(tO, false) == setLowerCase(t,false));
+	}
+	/*...............................................................................*/
+	/**returns new state  */
+	public static CategoricalState newState() {
+		return new CategoricalState();  
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns  state set */
+	public static boolean isEmpty(long s) {
+		return s==emptySet();  
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns  state set */
+	public static long emptySet() {
+		return 0L;  
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns state set consisting of all elements */
+	public static long fullSet() {
+		return statesBitsMask; //(0xFFFFFFFFFFFFFFFFL);  
+	}
+	/*.................................................................................................................*/
+	/**Returns the set that is {0,...,(numInSet-1)}  That is, the first "numInSet" bits are set.
+	This is designed for use with next set, to generate for instance all possible sets containing
+	numInSet elements*/
+	public static long firstSet(int numInSet) { 
+		if (numInSet==0)
+			return 0;
+		else
+			return span(0, numInSet-1);//fullSet()>>>(64-numInSet);
+	}
+	/*.................................................................................................................*/
+	/**When passed a set, returns the next set in sequence with the same
+	number of elements and with maximum element maxS.  This can be called
+	repeatedly (after starting with firstSet) to generate all sets with a
+	certain number of elements.  When the current set is the last one,
+	returns an empty set.*/
+	public static long nextSet(long current, int maxS) { //todo: have mask instead of just maxS
+		if (current==0)
+			return 0;
+		long result = current;
+		int max = maximum(current);
+		if (max < maxS) { //still room to move over left; do it
+			result = clearFromSet(result, max);
+			return addToSet(result, max +1);
+		}
+		else { //no; get next from all but last
+			result = clearFromSet(result, max);
+			result = nextSet(result, max-1);
+			if (result==0){ //hadn't been any more
+				return 0L;
+			}
+			else  {
+				int newMax = maximum(result);
+				return addToSet(result, newMax+1);
+			}
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff e is element in state set */
+	public boolean isElement(int e) {
+		if (!legalState(e))
+			return false;
+		else
+			return (((1L<<e)&set)!=0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff e is element in state set s */
+	public static boolean isElement(long s, int e) {
+		if (!legalState(e))
+			return false;
+		else
+			return (((1L<<e)&s)!=0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff the first long is a subset of the second */
+	public static boolean isSubset(long sub, long s) {
+		return (statesBitsMask & sub & s) == (statesBitsMask & sub);
+	}
+	
+	/*..........................................CategoricalState.....................................*/
+	/**returns minimum element in state set s */
+	public static int minimum(long s) {
+		if ((statesBitsMask & s)==0L)
+			return -1;
+		for (int e=0; e<=getMaxPossibleStateStatic(); e++) {
+			if (((1L<<e)&s)!=0L)
+				return e;
+		}
+		return -1;  
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**Returns the only element in state set s.  If more than one element, or no elements, returns -1. */
+	public static int getOnlyElement(long s) {
+		int min = minimum(s);
+		int max = maximum(s);
+		if (min==max)
+			return min;
+		return -1;  
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns number of states in state set shortS */
+	public static int cardinality(int shortS) {
+		int count =0;
+			for (int e=0; e<= getMaxPossibleStateStatic(); e++) {
+				if (((1L<<e)&shortS)!=0) {  //test bit
+					count++;
+				}
+			}
+			return count;
+
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns number of states in state set s */
+	public static int cardinality(long s) {
+		if ((statesBitsMask & s)==0L)
+		 	return 0;  
+		
+		else {
+			int count =0;
+			for (int e=0; e<= getMaxPossibleStateStatic(); e++) {
+				if (((1L<<e)&s)!=0L) {  //test bit
+					count++;
+				}
+			}
+			return count;
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns number of states in state set */
+	public  int cardinality() {
+		long s = getValue();
+		if ((statesBitsMask & s)==0L)
+		 	return 0;  
+		
+		else {
+			int count =0;
+			for (int e=0; e<= getMaxPossibleStateStatic(); e++) {
+				if (((1L<<e)&s)!=0L) {  //test bit
+					count++;
+				}
+			}
+			return count;
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns whether number of states in state set s is greater than 1 */
+	public static boolean hasMultipleStates(long s) {
+		if ((statesBitsMask & s)==0L)
+		 	return false;  
+		
+		else {
+			int count =0;
+			for (int e=0; e<= getMaxPossibleStateStatic(); e++) {
+				if (((1L<<e)&s)!=0L) {  //test bit
+					count++;
+					if (count>1)
+						return true;
+				}
+			}
+			return false;
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return maximum value of states in state set s */
+	public static int maximum(long s) {
+		if (s==0L) {
+		 	return -1;  
+		}
+		else {
+			int max = -1;
+			for (int e=0; e<= getMaxPossibleStateStatic(); e++) {
+				if (((1L<<e)&s)!=0L) {  //test bit
+					max=e;
+				}
+			}
+			return max;
+		}
+/*
+		Attempt 1 (doesn't work on IE4/W95)
+		for (int e=maxCategoricalState; e>=0; e--) {
+			if (((1L<<e)&s)!=0)
+				return e;
+		}
+		Attempt 2 (doesn't work on IE4/W95)
+			long mask = ~(0L);
+			for (int e=0; e<= maxCategoricalState; e++) {
+				mask <<= 1;
+				if ((mask & s)==0L)
+					return e;
+			}
+		Attempt 3 (doesn't work on IE4/W95)
+			for (int e=0; e<= maxCategoricalState; e++) {
+				if (((1L<<e)&s)!=0) {  //test bit
+					s &= ~(1L<<e);  //clear bit
+					if (s==0L)
+						return e;
+				}
+			}
+*/
+	//	return -1;  // should be missing!!!!
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns true if e is only state in state set s */
+	public static boolean isOnlyElement(long s, int e) {
+		if (!legalState(e))
+			return false;
+		else
+			return ((1L<<e)==s);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns a state set including only the state e */
+	public static long makeSet(int e) {
+		if (legalState(e))
+			return (1L<<e);
+		else 
+			return impossible;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns a state set including only elements in shortS; if shortS has multiple elements, the uncertainty bit is set. */
+	public static long makeSetFromLowerBits(int shortS) {
+		if (cardinality(shortS)<=1)
+			return (long)shortS;
+		else 
+			return setUncertainty((long)shortS,true);
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns a state set including only the states e1 & e2 */
+	public static long makeSet(int e1, int e2) {
+		long b = makeSet(e1);
+		return addToSet(b, e2);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns a state set including only the states e1 & e2 & e3 */
+	public static long makeSet(int e1, int e2, int e3) {
+		long b = makeSet(e1);
+		return addToSet(addToSet(b, e2), e3);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns a state set including only the states e1 & e2 & e3 & e4 */
+	public static long makeSet(int e1, int e2, int e3, int e4) {
+		long b = makeSet(e1);
+		return addToSet(addToSet(addToSet(b, e2), e3), e4);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return a state set with all states a through b inclusive. */
+	public static long span(int a, int b) {
+		if (!legalState(a) || !legalState(b))
+			return impossible;
+		else if (a>b) {
+			int c=a;
+			a = b;
+			b = c;
+		}
+		return ((~(0L)) << a) & ((~(0L)) >>> (MAXBIT-b));
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the state set spanning min to max of s */
+	public static long span(long s) {
+		if ((s & statesBitsMask) ==0L) //todo: put more queries like this
+			return 0;
+		for (int min=0; min<=maxCategoricalState; min++) {
+			if (((1L<<min)&s)!=0L) {
+				int max = -1;
+				for (int e=min; e<= maxCategoricalState; e++) {
+					if (((1L<<e)&s)!=0L) {  //test bit
+						max=e;
+					}
+				}
+				return span(min, max);
+			}
+		}
+		return 0;
+	}
+	/*..........................................CategoricalData.....................................*/
+	/**merges the states  */
+	public static long mergeStates(long s1, long s2) {
+		boolean bothHaveStates = CategoricalState.cardinality(s1) >0 && CategoricalState.cardinality(s2) >0 ;
+		long sMerged = CategoricalState.union(s1,s2);
+		if (bothHaveStates) {
+			if (CategoricalState.cardinality(sMerged)>=2) {
+				long s1StatesOnly = s1& statesBitsMask;
+				long s2StatesOnly = s2 & statesBitsMask;
+				long sMergedStatesOnly = sMerged & statesBitsMask;
+				if (((sMergedStatesOnly | s1StatesOnly)==s1StatesOnly) && !CategoricalState.isUncertain(s1)) //s1 contains all the states and it is not uncertain
+					sMerged = s1;
+				else if (((sMergedStatesOnly | s2StatesOnly)==s2StatesOnly) && !CategoricalState.isUncertain(s2)) //s2 contains all the states and it is not uncertain
+					sMerged = s2;
+				else {
+					boolean oneIsUncertain = CategoricalState.isUncertain(s1) || CategoricalState.isUncertain(s2);
+					sMerged = CategoricalState.setUncertainty(sMerged,oneIsUncertain);
+				}
+			}
+			// if the cardinality is less than 2, then they both must have the same state, and we don't do anything
+		}
+		else if (CategoricalState.cardinality(s1) >0) // s1 has values, s2 doesn't, so just use s1
+			sMerged=s1;
+		else if (CategoricalState.cardinality(s2) >0) // s2 has values, s1 doesn't, so just use s2
+			sMerged=s2;
+		else if (CategoricalState.isUnassigned(s1) || CategoricalState.isUnassigned(s2))  // neither has a state, at least one is missing
+			sMerged = CategoricalState.unassigned;
+		return sMerged;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**Adds or clears the inapplicable bit of state set s , used for merging operations*/
+	public static long setInapplicable(long s, boolean b) {
+		if (b)
+			return inapplicable | s;
+		else 
+			return (~(inapplicable))&s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**Adds or clears the unassigned bit of state set s , used for merging operations*/
+	public static long setUnassigned(long s, boolean b) {
+		if (b)
+			return unassigned | s;
+		else 
+			return (~(unassigned))&s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of setting or clearing the lowerCase flag of state set s */
+	public static long setLowerCase(long s, boolean lowerCase) {
+		if (lowerCase)
+			return (1L<<lowerCaseBit) | s;
+		else 
+			return (~(1L<<lowerCaseBit))&s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return whether lowerCase flag is set in state set s */
+	public static boolean isLowerCase(long s) {
+		return (((1L<<lowerCaseBit)&s)!=0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return whether lowerCase flag is set in state set s */
+	public boolean isLowerCase() {
+		return (((1L<<lowerCaseBit)&set)!=0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of setting or clearing the uncertainty flag of state set s */
+	public static long setUncertainty(long s, boolean uncertain) {
+		if (uncertain)
+			return (1L<<uncertainBit) | s;
+		else 
+			return (~(1L<<uncertainBit))&s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**sets or clears the uncertainty flag */
+	public void setUncertainty(boolean uncertain) {
+		set = setUncertainty(set, uncertain);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return whether uncertainty flag is set in state set s */
+	public static boolean isUncertain(long s) {
+		return (((1L<<uncertainBit)&s)!=0L);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of adding state e to state set s */
+	public static long addToSet(long s, int e) {
+		if (legalState(e))
+			return (1L<<e) | s;
+		else 
+			return s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of taking the union of two states */
+	public static long union(long s1, long s2) {
+		return s1 | s2;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of taking the intersection of two states */
+	public static long intersection(long s1, long s2) {
+		return s1 & s2;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return whether or not the two state sets share any states */
+	public static boolean statesShared(long s1, long s2) {
+		return (statesBitsMask & s1 & s2) != emptySet();
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return whether or not the two state sets share any states */
+	public boolean statesShared(CategoricalState cs) {
+		return (statesBitsMask & getValue() & cs.getValue()) != emptySet();
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of subtracting state e to state set s */
+	public static long clearFromSet(long s, long e) {
+		if (isCombinable(e))
+			return (~e)&s;
+		else 
+			return s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the result of subtracting state e to state set s */
+	public static long clearFromSet(long s, int e) {
+		if (legalState(e))
+			return (~(1L<<e))&s;
+		else 
+			return s;
+	}
+
+	/*.................................................................................................................*/
+	/* finds which states are best and returns state set */
+	public static long chooseHighestWithinFactor(double[] values, double factor) {
+		if (values == null)
+			return 0L;
+		double bestSoFar = MesquiteDouble.unassigned;
+		long resultSet = 0L;
+		for (int i=0; i< values.length; i++) {
+			if (MesquiteDouble.greaterThan(values[i], bestSoFar, 0.00000001)) {
+				if (MesquiteDouble.greaterThanByFactor(values[i], bestSoFar, factor))
+					resultSet = makeSet(i);
+				else
+					resultSet = addToSet(resultSet, i);
+				bestSoFar = values[i];
+			}
+			else if (MesquiteDouble.equalsWithinFactor(values[i], bestSoFar, factor))
+				resultSet = addToSet(resultSet, i);
+		}
+		return resultSet;
+	}
+	/*.................................................................................................................*/
+	/* finds which states are best and returns state set */
+	public static long chooseHighest(double[] values, double toleranceProportion) {
+		if (values == null)
+			return 0L;
+		double bestSoFar = MesquiteDouble.unassigned;
+		long resultSet = 0L;
+		for (int i=0; i< values.length; i++) {
+			if (MesquiteDouble.greaterThan(values[i], bestSoFar, toleranceProportion)){  
+				bestSoFar = values[i];
+				resultSet = makeSet(i);
+			}
+			else if (MesquiteDouble.equals(values[i], bestSoFar, toleranceProportion))
+				resultSet = addToSet(resultSet, i);
+		}
+		return resultSet;
+	}
+	/*.................................................................................................................*/
+	/* finds which states are best and returns state set */
+	public static long chooseLowest(double[] values, double toleranceProportion) {
+		if (values == null)
+			return 0L;
+		double bestSoFar = MesquiteDouble.unassigned;
+		long resultSet = 0;
+		for (int i=0; i< values.length; i++) {
+			if (MesquiteDouble.lessThan(values[i], bestSoFar, toleranceProportion)){  
+				bestSoFar = values[i];
+				resultSet = makeSet(i);
+			}
+			else if (MesquiteDouble.equals(values[i], bestSoFar, toleranceProportion))
+				resultSet = addToSet(resultSet, i);
+		}
+		return resultSet;
+	}
+	/** The masks that preserves bits 0.. maxCategoricalState*/
+	public static final long shortStatesBitsMaskL = (~0L)>>>53; //5 for high bits + 48 for reduction from 64 to 16
+	public static final long intStatesBitsMaskL = (~0L)>>>37; //5 for high bits + 32 for reduction from 64 to 32
+
+	/*..........................................CategoricalState.....................................*/
+	public static boolean compressibleToShort(long s){
+		return (s & shortStatesBitsMaskL) == (s & CategoricalState.statesBitsMask);
+	}
+	/*..........................................CategoricalState.....................................*/
+	public static short compressToShort(long s){
+		return (short)((s & shortStatesBitsMaskL) | ((s & CategoricalState.highBitsMask)>>>48));
+	}
+	/*..........................................CategoricalState.....................................*/
+	public static long expandFromShort(short s){
+		long LS = ((long)s);
+		return (LS & shortStatesBitsMaskL) | ((LS << 48) & CategoricalState.highBitsMask);
+	}
+	/*..........................................CategoricalState.....................................*/
+	public static boolean compressibleToInt(long s){
+		return (s & intStatesBitsMaskL) == (s & CategoricalState.statesBitsMask);
+	}
+	/*..........................................CategoricalState.....................................*/
+	public static int compressToInt(long s){
+		return (int)((s & intStatesBitsMaskL) | ((s & CategoricalState.highBitsMask)>>>32));
+	}
+	/*..........................................CategoricalState.....................................*/
+	public static long expandFromInt(int s){
+		long LS = ((long)s);
+		return (LS & intStatesBitsMaskL) | ((LS << 32) & CategoricalState.highBitsMask);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** Expands state set (passed as long) to full array of included elements. */
+	public static int[] expand(long s) {
+		int numStates = cardinality(s);
+		int count=0;
+		int[] result = new int[numStates];
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (isElement(s, e)) {
+				result[count]=e;
+				count++;
+			}
+		}
+		return result;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** Compresses array listing included elements into state set form (long, with bits set).  This is inverse of expand.*/
+	public static long compressFromList(int[] states) {
+		if (states == null) //added 20 Oct 01
+			return 0L;
+		long s=0L;
+		for (int i=0; i<states.length; i++) {
+			if (states[i]>=0 && states[i]<=maxCategoricalState)
+				s= addToSet(s, states[i]);
+		}
+		return s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** Compresses array with presence (>0) or absence (<=0) for each element into state set form (long, with bits set).*/
+	public static long compressFromPresence(double[] states) {
+		if (states == null) //added 20 Oct 01
+			return 0L;
+		long s=0L;
+		for (int i=0; i<states.length; i++) {
+			if (states[i]>0.0) 
+				s= addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** sets the value to inapplicable*/
+	public void setToInapplicable() {
+		set = inapplicable;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** sets the value to unassigned*/
+	public void setToUnassigned() {
+		set = unassigned;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**gets the value of the state set */
+	public long getValue() {
+		return set;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**sets the value of the state set to the long variable passed*/
+	public void setValue(long value) {
+		set = value;
+	}
+	
+	
+	/*..........................................CategoricalState.....................................*/
+	/**sets the value using the passed CharacterState's value if of same type */
+	public void setValue(CharacterState cs){
+		if (cs!=null && cs instanceof CategoricalState) {
+			setValue(((CategoricalState)cs).getValue());
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** sets its value to the value given by the String passed to it starting at position pos �*
+	public void setValue(String s, MesquiteInteger pos){
+		if (s==null){
+			set = unassigned;
+			return;
+		}
+		boolean polymorphOn = false;
+		boolean uncertainOn = false;
+		boolean done = false;
+		long stateSet = 0L;
+		int loc = pos.getValue();
+		while (loc<s.length() && !done) { 
+			char c = s.charAt(loc++); //get next dark character in string
+			while (ParseUtil.whitespace(c, null)  && c!=0 && loc<s.length())
+				c = s.charAt(loc++);
+				
+			if (!ParseUtil.whitespace(c, null)){
+				if (c == '(')
+					polymorphOn = true;
+				else if (c == '{')
+					uncertainOn = true;
+				else if (c == '}' || c == ')') 
+					done = true;
+				else if (polymorphOn || uncertainOn) {
+					long state =  fromChar(c);
+					if (CategoricalState.isCombinable(state))
+						stateSet |=  state;
+				}
+				else {
+					stateSet =  fromChar(c);
+					done = true;
+				}
+			}
+		}
+		pos.setValue(loc);
+		if (uncertainOn)
+			stateSet = setUncertainty(stateSet, true);
+		setValue(stateSet);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/* Sets the value of this CharacterState according to the string, assuming the parent data is as given �*/
+	public void setValue(String s, CharacterData parentData) {
+		if (s==null){
+			set = unassigned;
+			return;
+		}
+		MesquiteInteger pos = new MesquiteInteger(0);
+		boolean polymorphOn = false;
+		boolean uncertainOn = false;
+		boolean done = false;
+		set = 0L;
+		int loc = pos.getValue();
+		while (loc<s.length() && !done) {
+			char c = s.charAt(loc++);
+			while (ParseUtil.whitespace(c, null)  && c!=0 && loc<s.length())
+				c = s.charAt(loc++);
+			if (!ParseUtil.whitespace(c, null)){
+				if (c == '(')
+					polymorphOn = true;
+				else if (c == '{')
+					uncertainOn = true;
+				else if (c == '}' || c == ')') 
+					done = true;
+				else if (polymorphOn || uncertainOn) {
+					long state;
+					if (parentData == null || !(parentData instanceof CategoricalData))
+						state =  fromChar(c);
+					else
+						state = ((CategoricalData)parentData).fromChar(c);
+					if (CategoricalState.isCombinable(state))
+						set |=  state;
+				}
+				else {
+					if (parentData == null || !(parentData instanceof CategoricalData))
+						set =  fromChar(c);
+					else
+						set =  ((CategoricalData)parentData).fromChar(c);
+					done = true;
+				}
+			}
+		}
+		if (uncertainOn)
+			set = setUncertainty(set, true);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}); 
+	Used default symbols since no CharacterData is specified �*/
+	public long fromChar(char c) { //this doesn't work with symbols!
+		if (c == '?')
+			return unassigned;
+		if (c == '-')
+			return inapplicable;
+		int e=whichState(c); //find which state this character is, among default symbols
+		if (legalState(e))
+			return (1L<<e); //return set with just that element
+		else {
+			return impossible;
+		}
+	}
+	/*..........................................CategoricalState.....................................*/
+	/*find which state this character refers to, comparing against default symbols �*/
+	public int whichState(char c){
+		for (int i=0; i<CategoricalData.defaultSymbols.length; i++){
+			if (CategoricalData.defaultSymbols[i] == c)
+				return i;
+		}
+		return -1;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the String description of the state set*/
+	public String toString() {
+		return toString(set);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses braces, and does not use character state names*/
+	public static String toString(long s) {
+		return toString(s, null, 0, true);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Does not use character state names*/
+	public static String toString(long s, boolean useBraces) {
+		return toString(s, null, 0, useBraces);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses character state names if available.*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces) {
+		return toString(s, data, ic, useBraces, false);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses character state names if available. �*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces, boolean useSymbols) {
+		if (s == impossible)
+			return "impossible";
+		else if (s== unassigned) {
+			if (data == null)
+				return "?";
+			else
+				return String.valueOf(data.getUnassignedSymbol());
+		}
+		else if (s == inapplicable){
+			if (data == null)
+				return "-";
+			else
+				return String.valueOf(data.getInapplicableSymbol());
+		}
+			
+			
+		boolean first=true;
+		String temp;
+		if (useBraces) 
+			temp="{";
+		else
+			temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (isElement(s, e)) {
+				if (!first)
+					temp+=" ";
+				if (data != null) {
+					if (useSymbols)
+						temp+=data.getSymbol(e);
+					else
+						temp+=data.getStateName(ic, e);
+				}
+				else if (useSymbols)
+					temp+=CategoricalData.defaultSymbols[e];
+				else
+					temp+=Integer.toString(e);
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		if (useBraces)
+			temp+="}";
+		return temp;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  �*/
+	public  String toDisplayString(){
+		if (isInapplicable(set))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(set))
+			return "" + CharacterData.defaultMissingChar;
+		char sep = '&';
+		if (isUncertain(set))
+			sep = '/';
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&set)!=0L) {
+				if (!first)
+					temp+=sep;
+				temp+=CategoricalData.defaultSymbols[e];
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		return temp;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public static String toSimpleString(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&s)!=0L) {
+				if (!first)
+					temp+=" ";
+				temp+=CategoricalData.defaultSymbols[e];
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		if (temp.length()>1)
+			temp ="{" + temp + "}";
+		return temp;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public String toNEXUSString() {
+		return toNEXUSString(set);
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public static String toNEXUSString(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&s)!=0L) {
+				temp+=CategoricalData.defaultSymbols[e];
+			}
+		}
+		if (temp.length()>1)
+			temp ="{" + temp + "}";
+		return temp;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states.  Includes High Bits.  Used for development/debugging. �*/
+	public static String toSimpleStringHB(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&s)!=0L) {
+				if (!first)
+					temp+=",";
+				temp+=CategoricalData.defaultSymbols[e];
+				first=false;
+			}
+		}
+		for (int e=maxCategoricalState+1; e<=MAXBIT; e++) {
+			if (((1L<<e)&s)!=0L) {
+				if (!first)
+					temp+=",";
+				temp+= " " + Integer.toString(e);
+				first=false;
+			}
+		}
+		if (temp.length()>1)
+			temp ="{" + temp + "}";
+		return temp;
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/** converts passed long as bits. */
+	public static String toStringBits(long s) {
+		StringBuffer temp= new StringBuffer();
+		for (int e=63; e>=0; e--) {
+			if (((1L<<e)&s)!=0L) 
+				temp.append('1');
+			else
+				temp.append('0');
+		}
+		
+		return temp.toString();
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public static int getMaxPossibleStateStatic() {
+		return maxCategoricalState;
+	}
+	public static int getTotalBitsInStateSet() {
+		return TOTALBITS;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public int getMaxPossibleState() {
+		return maxCategoricalState;
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/**return whether uncertainty flag is set in state set s */
+	public static boolean isUnassignedInt(int s) {
+		return (((1<<unassignedBitInt)&s)!=0);
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/CategoricalStates.java b/Source/mesquite/categ/lib/CategoricalStates.java
new file mode 100644
index 0000000..475159e
--- /dev/null
+++ b/Source/mesquite/categ/lib/CategoricalStates.java
@@ -0,0 +1,467 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public abstract class CategoricalStates extends CharacterStates {
+	protected int maxState=CategoricalState.maxCategoricalState;
+	protected int minState=0;
+	protected long allStates=0;
+	protected boolean minFound=false;
+	protected boolean  maxFound=false;
+	private boolean  maxFoundInFreq=false;
+	protected double[][] frequencies;
+	protected double[][] extraFrequencies;   //for storage of information beyond the simple state frequencies
+	protected ColorDistribution extraFrequencyColors;
+	protected String[] extraFrequencyNames;
+	protected int enforcedMaxState = 0;
+	
+	public CategoricalStates (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................  CategoricalStates  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return CategoricalState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return CategoricalData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return CategoricalData.DATATYPENAME;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** return if frequencies exist for states at each node.*/
+	public boolean frequenciesExist(){
+		return (frequencies !=null);
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** return if frequencies exist for states at each node.*/
+	public boolean extraFrequenciesExist(){
+		return (extraFrequencies !=null);
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** Copy frequency information from first to second CategoricalStates.*/
+	public static void copyFrequencies(CategoricalStates source, CategoricalStates sink) {
+		if (source!=null && sink!=null && source.frequenciesExist()) {
+			for (int i=0; i<source.getNumNodes() && i<sink.getNumNodes(); i++) {
+				sink.setFrequencies(i, source.getFrequencies(i));
+			}
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** Copy extra frequency information from first to second CategoricalStates.*/
+	public static void copyExtraFrequencies(CategoricalStates source, CategoricalStates sink) {
+		if (source!=null && sink!=null && source.extraFrequenciesExist()) {
+			for (int i=0; i<source.getNumNodes() && i<sink.getNumNodes(); i++) {
+				sink.setExtraFrequencies(i, source.getExtraFrequencies(i));
+			}
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** Set extra frequency colors*/
+	public  void setExtraFrequencyColors(ColorDistribution colors) {
+		extraFrequencyColors = colors;
+	}
+
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get extra frequency colors*/
+	public  ColorDistribution getExtraFrequencyColors() {
+		return extraFrequencyColors;
+	}
+
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** Set extra frequency names*/
+	public  void setExtraFrequencyNames(String[] names) {
+		extraFrequencyNames = names;
+	}
+
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get extra frequency names*/
+	public  String[] getExtraFrequencyNames() {
+		return extraFrequencyNames;
+	}
+
+	int numFreqCategories = 0;
+	public void setNumFreqCategories(int numCategories){
+		this.numFreqCategories = numCategories;
+	}
+	public int getNumFreqCategories(){
+		return numFreqCategories;
+	}
+	private void prepareFrequencyStorage(int node, int numCategories){
+			if (frequencies == null) {
+				frequencies = new double[getNumNodes()][];
+				frequencies[node] = new double[numCategories];
+			}
+			else if (frequencies[node]== null || frequencies[node].length != numCategories) {
+				frequencies[node] = new double[numCategories];
+			}
+			numFreqCategories = numCategories;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** set freqency information*/
+	public void setFrequencies(int node, double[] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				frequencies[node][i] = freqs[i];
+			}
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** set freqency information. */
+	public void setFrequency(int node, int category, double freq) {
+		if (checkIllegalNode(node, 0))
+			return;
+		prepareFrequencyStorage(node, numFreqCategories);
+		if (frequencies != null && category< frequencies[node].length)
+			frequencies[node][category] = freq;
+	
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get freqency information at a particular node*/
+	public double[] getFrequencies(int node) {
+		if (checkIllegalNode(node, 1))
+			return null;
+		if (frequencies != null)
+			return frequencies[node];
+		return null;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get freqency of particular category at a particular node*/
+	public double getFrequency(int node, int category) {
+		if (checkIllegalNode(node, 2))
+			return 0;
+		if (frequencies == null || frequencies[node]== null)
+			return MesquiteDouble.unassigned;
+		else
+			return frequencies[node][category];
+	}
+
+	int numExtraFreqCategories = 0;
+	public void setNumExtraFreqCategories(int numExtraCategories){
+		this.numExtraFreqCategories = numExtraCategories;
+	}
+	public int getExtraNumFreqCategories(){
+		return numExtraFreqCategories;
+	}
+	private void prepareExtraFrequencyStorage(int node, int numCategories){
+			if (extraFrequencies == null) {
+				extraFrequencies = new double[getNumNodes()][];
+				extraFrequencies[node] = new double[numCategories];
+			}
+			else if (extraFrequencies[node]== null || extraFrequencies[node].length != numCategories) {
+				extraFrequencies[node] = new double[numCategories];
+			}
+			numExtraFreqCategories = numCategories;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** set extra freqency information*/
+	public void setExtraFrequencies(int node, double[] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareExtraFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				extraFrequencies[node][i] = freqs[i];
+			}
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** set extra freqency information. */
+	public void setExtraFrequency(int node, int category, double freq) {
+		if (checkIllegalNode(node, 0))
+			return;
+		prepareExtraFrequencyStorage(node, numExtraFreqCategories);
+		if (extraFrequencies != null && category< extraFrequencies[node].length)
+			extraFrequencies[node][category] = freq;
+	
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get extra freqency information at a particular node*/
+	public double[] getExtraFrequencies(int node) {
+		if (checkIllegalNode(node, 1))
+			return null;
+		if (extraFrequencies != null)
+			return extraFrequencies[node];
+		return null;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get extra freqency of particular category at a particular node*/
+	public double getExtraFrequency(int node, int category) {
+		if (checkIllegalNode(node, 2))
+			return 0;
+		if (extraFrequencies == null || extraFrequencies[node]== null)
+			return MesquiteDouble.unassigned;
+		else
+			return extraFrequencies[node][category];
+	}
+
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get state set represented by frequencies at a particular node*/
+	public long getSetFromFrequencies(int node) {
+		if (checkIllegalNode(node, 3))
+			return 0L;
+		if (frequencies == null || frequencies[node]== null)
+			return 0L;
+		else {
+			long s = 0L;
+			for (int i=0; i<frequencies[node].length; i++)
+				if (frequencies[node][i]>0.0)
+					s = CategoricalState.addToSet(s, i);
+			return s;
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** dispose frequency information (frees memory). */
+	public void disposeFrequencies() {
+		frequencies = null;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** dispose extra frequency information (frees memory). */
+	public void disposeExtraFrequencies() {
+		extraFrequencies = null;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**Get the default CharacterModel for the given paradigm (e.g., "Parsimony") */
+	public CharacterModel getDefaultModel(MesquiteProject file, String paradigm){
+   		NameReference p = NameReference.getNameReference(paradigm);
+   		DefaultReference dR = CategoricalData.findDefaultReference(p);
+   		if (dR==null) {
+   			MesquiteMessage.println("Default model not found :" + paradigm);
+   			return null;
+   		}
+   		else {
+   			CharacterModel cm = file.getCharacterModel(dR.getDefault());
+   			if (cm==null) 
+   				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+   			return cm;
+   		}
+   	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get union of all statesets, including multiple-state uncertainties (but not missing, gap) */
+	public long getAllStates (){
+		long s = 0L;
+		for (int ic=0; ic<getNumNodes(); ic++) {
+			s |= getState(ic);
+		}
+		return s & CategoricalState.statesBitsMask;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get union of all statesets, including multiple-state uncertainties (but not missing, gap), in the tree */
+	public long getAllStates (Tree tree, int node){
+		long s = 0L;
+		if (tree.nodeIsTerminal(node)){
+			s = getState(tree.taxonNumberOfNode(node));
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				s |= getAllStates(tree, d);
+		}
+		return s & CategoricalState.statesBitsMask;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** get stateset at node N */
+	public abstract long getState (int N);
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		CategoricalState c;
+		if (cs == null || !(cs instanceof CategoricalState)) {
+			c = new CategoricalState();
+		}
+		else
+			c = (CategoricalState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new CategoricalState();
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns whether state at node N is inapplicable */
+   	public  boolean isInapplicable(int N){
+   		return getState(N)== CategoricalState.inapplicable;
+   	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns whether state at node N is unassigned (missing data)( */
+   	public  boolean isUnassigned(int N){
+   		return getState(N)== CategoricalState.unassigned;
+   	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns whether state at node N is uncertain (partial missing or ambiguous data)( */
+   	public  boolean isUncertain(int N){
+   		return CategoricalState.isUncertain(getState(N));
+   	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**Dump a listing of the states to the log. */
+	public void logStates(){
+		MesquiteModule.mesquiteTrunk.logln("States");
+		String statesString="";
+		for (int ic=0; ic<getNumNodes(); ic++) {
+			statesString+=CategoricalState.toString(getState(ic));
+		}
+		statesString+= '\n';
+		MesquiteModule.mesquiteTrunk.logln(statesString);
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		if (checkIllegalNode(node, 8))
+			return "";
+		CategoricalData data = null;
+		int ic = -1;
+		if (getParentData()!=null && getParentData() instanceof CategoricalData) {
+			data = (CategoricalData)getParentData();
+			ic = getParentCharacter();
+		}
+		if (data!=null){
+			boolean first = true;
+			if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+				long stateSet = getState(node);
+				String s="";
+				boolean mismatch = false;
+				for (int i=0; i<frequencies[node].length && !mismatch; i++)
+					if (frequencies[node][i]!=0.0 && !CategoricalState.isElement(stateSet, i))
+						mismatch = true;
+				for (int i=0; i<frequencies[node].length; i++)  {
+					if (frequencies[node][i]!=0.0 || CategoricalState.isElement(stateSet, i)) {
+						if (!first)
+							s += lineEnding;
+						first = false;
+						if (StringUtil.notEmpty(data.getStateName(ic, i)))
+							s+=data.getStateName(ic,i);
+						else
+							s+= data.getSymbol(i);
+						
+						if (frequencies[node][i]!=0.0)
+							s+= ": " + MesquiteDouble.toString(frequencies[node][i]);
+						if (mismatch && CategoricalState.isElement(stateSet, i))
+							s+= "*";
+					}
+				}
+				return s;
+			}
+			else if (ic>=0 && !(this instanceof CategoricalHistory)){  // treat as if terminal, not history
+				StringBuffer sb = new StringBuffer();
+				data.statesIntoStringBufferCore(ic, getState(node), sb, true);
+				return sb.toString();
+			}
+			else if (ic>=0 && data.hasStateNames(ic)){
+				String s = "";
+				first = true;
+				long ss = getState(node);
+				for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+					if (CategoricalState.isElement(ss, e)) {
+						if (!first)
+							s+=",";
+						s+=data.getStateName(ic,  e);
+						first=false;
+					}
+				}
+				if (first)
+					s += '!'; //no state found!
+				return s;
+			}
+			else {
+				String s = "";
+				first = true;
+				long ss = getState(node);
+				for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+					if (CategoricalState.isElement(ss, e)) {
+						if (!first)
+							s+=",";
+						s+=data.getSymbol( e);
+						first=false;
+					}
+				}
+				if (first)
+					s += '!'; //no state found!
+				return s;
+			}
+		}
+		
+		//data is null
+		if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+			String s="";
+			boolean first = true;
+			for (int i=0; i<frequencies[node].length; i++) 
+				if (frequencies[node][i]!=0) {
+					if (!first)
+						s += lineEnding;
+					first = false;
+					s+= i + ":" + MesquiteDouble.toString(frequencies[node][i]);
+				}
+			return s;
+		}
+		else {
+			return CategoricalState.toString(getState(node), null, 0, false, true);
+		}
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/**returns string describing states at nodes. */
+	public String toString () {
+		String s="";
+		for (int i=0; i<getNumNodes(); i++)
+			s += CategoricalState.toString(getState(i), false);
+		return s;
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** returns true if state sets have single element each, and that at node N is greater than that at node M.  */
+	public boolean firstIsGreater (int N, int M){
+		if (isUnassigned(N) || isInapplicable(N))
+			return false;
+		if (isUnassigned(M) || isInapplicable(M))
+			return false;
+		if (CategoricalState.cardinality(getState(N)) == 1 && CategoricalState.cardinality(getState(M)) == 1) {
+			if (CategoricalState.minimum(getState(N)) > CategoricalState.minimum(getState(M)))
+				return true;
+		}
+		return false;
+		
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	/** returns true if states at nodes N and M are equal */
+	public boolean statesEqual(int N, int M) {
+		checkOutOfBounds(N, M);
+		return getState(N)==getState(M);
+	}
+	/*..........................................  CategoricalStates  ...................................................*/
+	private void checkOutOfBounds(int N, int M) {
+		if (N<0 || N> getNumNodes() || M<0 || M>getNumNodes())
+			MesquiteMessage.println("ERROR: out of bounds");
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/DNACharacterAdjustable.java b/Source/mesquite/categ/lib/DNACharacterAdjustable.java
new file mode 100644
index 0000000..743b03f
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNACharacterAdjustable.java
@@ -0,0 +1,125 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class DNACharacterAdjustable extends CategoricalAdjustable {
+	public DNACharacterAdjustable (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = 3;
+	}
+	public DNACharacterAdjustable (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = 3;
+	}
+	/*..........................................  DNACharacterAdjustable  ..................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new DNAState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return DNAState.class;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return DNAState.fullSet();
+	}
+	/*..........................................  DNAState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		DNAState c;
+		if (cs == null || !(cs instanceof DNAState))
+			c = new DNAState();
+		else
+			c = (DNAState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return DNAData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return DNAData.DATATYPENAME;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................  DNACharacterAdjustable  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == DNACharacterHistory.class))
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................  DNACharacterAdjustable  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		if (checkIllegalNode(node, 8))
+			return "";
+		if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+			String s="";
+			for (int i=0; i<frequencies[node].length; i++) 
+				if (frequencies[node][i]!=0)
+					s+= DNAState.toString(i) + ":" + MesquiteDouble.toString(frequencies[node][i]) + lineEnding;
+			return s;
+		}
+		else
+			return DNAState.toString(getState(node), null, 0, false);
+	}
+	/*..........................................  DNACharacterAdjustable  ...................................................*/
+	/**returns string describing states at nodes. */
+	public String toString () {
+		String s="";
+		for (int i=0; i<getNumNodes(); i++)
+			s += DNAState.toString(getState(i), false);
+		return s;
+	}
+	/*.........................................CategoricalAdjustable.................................................*/
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new DNACharacterAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/DNACharacterHistory.java b/Source/mesquite/categ/lib/DNACharacterHistory.java
new file mode 100644
index 0000000..6db53c7
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNACharacterHistory.java
@@ -0,0 +1,209 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.cont.lib.ContColorTable;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class DNACharacterHistory extends CategoricalHistory {
+	public DNACharacterHistory (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = 3;
+	}
+	public DNACharacterHistory (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = 3;
+		allStates=DNAState.span(0,3);
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new DNAState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return DNAState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return DNAData.class;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return DNAState.fullSet();
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return DNAData.DATATYPENAME;
+	}
+	/*..........................................  DNAState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		DNAState c;
+		if (cs == null || !(cs instanceof DNAState))
+			c = new DNAState();
+		else
+			c = (DNAState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	/**clone this; if passed s is not null, place the clone there (so as to avoid creating new object)*/
+	public CharacterHistory clone(CharacterHistory s) {
+		DNACharacterHistory snew;
+		if ((s==null) || (s.getNumNodes()!=numNodes) || (!(s instanceof DNACharacterHistory)))
+			snew = new DNACharacterHistory(getTaxa(), numNodes);
+		else {
+			snew = (DNACharacterHistory)s;
+		}
+		for (int i=0; i<numNodes; i++) {
+			snew.setState(i, getState(i));
+		}
+		if (frequenciesExist())
+			copyFrequencies(this, snew);
+		else
+			snew.disposeFrequencies();
+		if (extraFrequenciesExist())
+			copyExtraFrequencies(this, snew);
+		else
+			snew.disposeExtraFrequencies();
+		snew.data = data;
+		snew.characterNumber = characterNumber;  //setting parent character
+		snew.setExplanation(getExplanation());
+		return snew;
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	public Color getDefaultColor(int maxState, int istate){
+		return DNAData.getDNAColorOfState(istate);
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	/** Must be called before colors for states are used (e.g., before a tree is shaded).  Goes through all nodes to find states present, to set
+	minima and maxima and record all states present. This allows the color range to be known before
+	colors for particular states are requested by a tree shade, for example.*/
+	public void prepareColors(Tree tree, int drawnRoot) {  
+		allStates=DNAState.span(0,3);
+		maxState = enforcedMaxState;
+	}
+	/*..........................................DNACharacterHistory................*/
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable) {
+		
+		if (colorTable == null || !(colorTable instanceof DNAColorTable))
+			return new DNAColorTable();
+		return colorTable;
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) {
+		if (cs==null || stateNames == null)
+			return 0;
+		int colorCount=0;
+		long s = allStates;
+		for (int e=0; e<=maxState && colorCount<cs.length && colorCount<stateNames.length; e++) {
+			if (CategoricalState.isElement (s,e)) {
+				/*if (stateColors==null) {
+					if (data == null)
+						cs[colorCount]= getDefaultColor(maxState,e);
+					else
+						cs[colorCount]= ((CategoricalData)data).getColorOfState(-1,e, maxState);
+				}
+				else {*/
+					cs[colorCount]= stateColors.getColor(maxState,e);
+					if (tableMappings != null)tableMappings[colorCount] = new Point(maxState, e);
+
+				//}
+				if (data!=null && characterNumber>=0 && characterNumber<data.getNumChars() && data instanceof CategoricalData) {
+					stateNames[colorCount++]=((DNAData)data).getStateName(characterNumber, e);
+				}
+				else {
+					stateNames[colorCount++]=DNAState.toString(e);
+				}
+			}
+		}
+		/*if (colorCount<=0)
+			MesquiteMessage.println("getLegendStates: no states found");
+		*/
+		return colorCount;
+	}
+	/*..........................................  DNACharacterHistory  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		if (checkIllegalNode(node, 8))
+			return "";
+		if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+			String s="";
+			for (int i=0; i<frequencies[node].length; i++) 
+				if (frequencies[node][i]!=0)
+					s+= DNAState.toString(i) + ":" + MesquiteDouble.toString(frequencies[node][i]) + lineEnding;
+			return s;
+		}
+		else
+			return DNAState.toString(getState(node), null, 0, false);
+			//return getCharacterState(null, node).toDisplayString();
+	}
+	/*..........................................  DNACharacterHistory  ...................................................*/
+	/**returns string describing states at nodes. */
+	public String toString () {
+		String s="";
+		for (int i=0; i<getNumNodes(); i++)
+			s += DNAState.toString(getState(i), false);
+		return s;
+	}
+	/*..........................................  DNACharacterHistory  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == DNACharacterHistory.class))
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................  DNACharacterHistory  ...................................................*/
+	public CharacterHistory makeHistory(Tree tree){
+		return new DNACharacterHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+	}
+	/*..........................................  DNACharacterHistory  ...................................................*/
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new DNACharacterAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/DNAColorTable.java b/Source/mesquite/categ/lib/DNAColorTable.java
new file mode 100644
index 0000000..5e70c59
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNAColorTable.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+
+import java.awt.Color;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+public class DNAColorTable extends MesquiteColorTable  {
+	  public DNAColorTable(){
+		   super();
+			for (int i=0; i<maxNumStates; i++) {
+				for (int j=0; j<maxNumStates; j++) {
+					setColor(i, j,DNAData.getDNAColorOfState(j));
+				}
+			}
+				   
+	   }
+		/**resets to default mode*/
+		public void resetDefaultMode(){
+			   setMode(COLORS);
+		}
+		/**resets to default mode*/
+		public void resetToDefaults(){
+			super.resetToDefaults();
+			for (int i=0; i<maxNumStates; i++) {
+				for (int j=0; j<maxNumStates; j++) {
+					setColor(i, j,DNAData.getDNAColorOfState(j));
+				}
+			}
+		}
+}
+
+
diff --git a/Source/mesquite/categ/lib/DNAData.java b/Source/mesquite/categ/lib/DNAData.java
new file mode 100644
index 0000000..2013bd0
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNAData.java
@@ -0,0 +1,1540 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.ListModule;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+/** A subclass of CharacterData for DNA data stored as Categorical sets (e.g, "{A, C}" */
+public class DNAData extends MolecularData {
+	boolean displayAsRNA = false;
+	public static String DATATYPENAME="DNA Data";
+
+	boolean colorCodPosInColumnNumber = true;
+	public static final NameReference complementedRef = NameReference.getNameReference("complemented"); //long: tInfo, data(ch); MesquiteInteger: data(cells)
+
+	public static Color dnaRed, dnaGreen, dnaYellow, dnaBlue;
+	public static Color dnaRedPale, dnaGreenPale, dnaYellowPale, dnaBluePale, dnaInapplicable, dnaUnassigned;
+
+	CodonPositionsSet codonPositionsSet = null;
+
+	private static Vector defaultModels;
+
+	static String A, C, G, T;
+	static {
+		defaultModels = new Vector(2);
+		dnaRed = new Color((float) 1, (float) 0.3, (float) 0.3);
+		dnaGreen = new Color((float) 0.3, (float) 1, (float) 0.3);
+		dnaYellow = new Color((float) 1, (float) 1, (float) 0.3);
+		dnaBlue = new Color((float) 0.4, (float) 0.4, (float) 1);
+
+		dnaRedPale = new Color((float) 1, (float) 0.6, (float) 0.6);
+		dnaGreenPale = new Color((float) 0.6, (float) 1, (float) 0.6);
+		dnaYellowPale = new Color((float) 1, (float) 1, (float) 0.6);
+		dnaBluePale = new Color((float) 0.7, (float) 0.7, (float) 1);
+		dnaInapplicable = new Color((float)0.93, (float)0.90, (float)0.87);  //ColorDistribution.inapplicable
+		dnaUnassigned = new Color((float)0.92, (float)0.94, (float)0.98); //ColorDistribution.unassigned;
+		A = "A";
+		C = "C";
+		G = "G";
+		T = "T";
+	}
+
+	public DNAData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa) {
+		super(manager, numTaxa, numChars, taxa);
+		setUseDiagonalCharacterNames(false);
+
+		super.setSymbolDirect(0, 'A');
+		super.setSymbolDirect(1, 'C');
+		super.setSymbolDirect(2, 'G');
+		super.setSymbolDirect(3, 'T');
+	}
+
+
+	/* .......................................... DNAData .................................................. */
+	public void setDisplayAsRNA(boolean displayAsRNA) {
+		this.displayAsRNA = displayAsRNA;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public boolean getDisplayAsRNA() {
+		return displayAsRNA;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public long getDefaultState() {
+		return CategoricalState.inapplicable;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** Indicates the type of character stored */
+	public Class getStateClass() {
+		return DNAState.class;
+	}
+
+	/* ................................................................................................................. */
+	/** Indicates whether the data are molecular sequence data or not */
+	public boolean isMolecularSequence() {
+		return true;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public String getDataTypeName() {
+		return DNAData.DATATYPENAME;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** clone this CharacterData and return new copy. Does not clone the associated specs sets etc. */
+	public CharacterData cloneData() {
+		DNAData data = new DNAData(matrixManager, numTaxa, numChars, getTaxa());
+		if (!data.isValid())
+			return null;
+		for (int ic = 0; ic < numChars; ic++) {
+			for (int it = 0; it < numTaxa; it++) {
+				data.setState(ic, it, getStateRaw(ic, it));
+			}
+			if (getSelected(ic))
+				data.setSelected(ic, true);
+		}
+		data.resetCellMetadata();
+		return data;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** get matrix and return as StsOfCharacters */
+	public MCharactersDistribution getMCharactersDistribution() {
+		MDNAEmbedded states = new MDNAEmbedded(this);
+		return states;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** return a CharacterDistribution that points to character ic */
+	public CharacterDistribution getCharacterDistribution(int ic) {
+		DNAEmbedded states = new DNAEmbedded(this, ic);
+		return states;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** Return CharacterDistribution object with same number of taxa as this object (but not with any particular data; just so that of same data type) */
+	public CharacterDistribution makeCharacterDistribution() {
+		DNACharacterAdjustable c = new DNACharacterAdjustable(getTaxa(), numTaxa);
+		c.setParentData(this);
+		return c;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** creates an empty CharacterState object of the same data type as CharacterData subclass used. */
+	public CharacterState makeCharacterState() {
+		return new DNAState();
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** Return CharacterData object with same number of taxa & characters as this object (but not with any particular data; just so that of same data type) */
+	public CharacterData makeCharacterData() {
+		return new DNAData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** Return CharacterData object with passed number of taxa & characters (but not with any particular data; just so that of same data type) */
+	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+		return new DNAData(getMatrixManager(), ntaxa, nchars, getTaxa());
+	}
+
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa) {
+		return new DNAData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** returns whether the matrix would prefer to have columns sized individually in editors. Default is true. */
+	public boolean pleaseAutoSizeColumns() {
+		return false;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public boolean colorCellsByDefault() { // added 19Jan02
+		return true;
+	}
+
+
+
+	/* .......................................... DNAData .................................................. */
+	/** returns the state of character ic in taxon it */
+	int countWarn = 0;
+	public CharacterState getCharacterState(CharacterState cs, int ic, int it) {
+		if (notInStorage(ic, it)) {
+			String s = "character number (" + ic;
+			if (ic>=numChars|| ic < 0) 
+				s+="* [numChars " + numChars + "]";
+			s+=") or taxon number (" + it ;
+			if (it>=numTaxa || it < 0) 
+				s+="* [numTaxa " + numTaxa + "]";
+			s+=") out of bounds in getCharacterState";
+
+			if (countWarn++ < 1000)
+				MesquiteMessage.warnProgrammer(s);
+			if (countWarn<4)
+				MesquiteMessage.printStackTrace();
+			return null;
+		}
+		if (cs != null && cs.getClass() == DNAState.class) {
+			((DNAState) cs).setValue(getStateRaw(ic, it));
+			return cs;
+		}
+		return new DNAState(getStateRaw(ic, it));
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public Color getColorOfState(int ic, int istate, int maxState) {
+		return getDNAColorOfState(istate);
+	}
+
+	public Color getColorOfState(int ic, int istate) {
+		return getDNAColorOfState(istate);
+	}
+
+	/* .......................................... CategoricalData .................................................. */
+	/** Gets the color representing state(s) of character ic in taxon it */
+	public Color getColorOfStates(int ic, int it) {
+		if (notInStorage(ic, it)) // illegal check
+			return ColorDistribution.unassigned;
+		long s = getStateRaw(ic, it);
+		if (CategoricalState.isCombinable(s)) {
+			int colorCount = CategoricalState.cardinality(s);
+			if (colorCount > 1) {
+				return Color.lightGray;
+			}
+			else {
+				return getDNAColorOfState(CategoricalState.maximum(s));
+			}
+		}
+		else if (isInapplicable(ic,it))
+			return dnaInapplicable;
+		else
+			return dnaUnassigned;
+	}
+
+	public static Color getDNAColorOfState(int istate) {
+		if (istate == 0)
+			return dnaRed;
+		else if (istate == 1)
+			return dnaGreen;
+		else if (istate == 2)
+			return dnaYellow;
+		else if (istate == 3)
+			return dnaBlue;
+		else
+			return dnaUnassigned;
+	}
+
+	public static Color getDNAColorOfStatePale(int istate) {
+		if (istate == 0)
+			return dnaRedPale;
+		else if (istate == 1)
+			return dnaGreenPale;
+		else if (istate == 2)
+			return dnaYellowPale;
+		else if (istate == 3)
+			return dnaBluePale;
+		else
+			return dnaUnassigned;
+	}
+	/** returns the color of character ic; e.g., to indicate codon positions */
+	public Color getDefaultCharacterColor(int ic) {
+		if (colorCodPosInColumnNumber) {
+			int position = getCodonPosition(ic);
+			if (position >= 1 && position <= 3)
+				return ColorDistribution.codPosMedium[position - 1];
+			else
+				return null; // ColorDistribution.codPosMedium[3];
+		}
+		return super.getDefaultCharacterColor(ic);
+	}
+
+	/** returns the dark color of character ic; e.g., to indicate codon positions */
+	public Color getDarkDefaultCharacterColor(int ic) {
+		if (colorCodPosInColumnNumber) {
+			int position = getCodonPosition(ic);
+			if (position >= 1 && position <= 3)
+				return ColorDistribution.codPosDark[position - 1];
+			else
+				return ColorDistribution.codPosDark[3];
+		}
+		return null;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** returns the codon position of character ic in taxon it */
+	public int getCodonPosition(int ic) {
+		if (ic>=getNumChars(false) || ic<0)
+			return MesquiteInteger.unassigned;
+		if (codonPositionsSet == null)
+			codonPositionsSet = (CodonPositionsSet) getCurrentSpecsSet(CodonPositionsSet.class);
+		if (codonPositionsSet != null && ic < codonPositionsSet.getNumberOfParts() && ic >= 0)
+			return codonPositionsSet.getInt(ic);
+		return MesquiteInteger.unassigned;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** returns the whether character ic is in a first, second, or third position */
+	public boolean isCoding(int ic) {
+		int position = getCodonPosition(ic);
+		return  (position >= 1 && position <= 3);
+
+	}
+	/*.................................................................................................................*/
+	public void setCodonPosition(int ic,  int pos, boolean canCreateCodPosSet, boolean notify){
+		boolean changed=false;
+		CodonPositionsSet modelSet = (CodonPositionsSet) getCurrentSpecsSet(CodonPositionsSet.class);
+		if (modelSet == null && canCreateCodPosSet) {
+			modelSet= new CodonPositionsSet("Codon Positions", getNumChars(), this);
+			modelSet.addToFile(getFile(), getProject(), (CharactersManager) getMatrixManager().findElementManager(CodonPositionsSet.class)); //THIS
+			setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+		}
+		if (modelSet != null) {
+			modelSet.setValue(ic,pos);
+			changed=true;
+		}
+		if (notify) {
+			if (changed)
+				notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+		}
+	}
+	/* .......................................... DNAData .................................................. */
+	public void assignCodonPositionsToTerminalChars(int whichTermChars){
+		if (whichTermChars<0) {  //added whichTermChars to front, so we need to get info from the one just after those, which is character -whichTermChars
+			int nextChar = -whichTermChars;
+			int nextPos = getCodonPosition(nextChar);
+			if (MesquiteInteger.isCombinable(nextPos) && (nextPos>=1) && (nextPos<=3)) { // the immediately adjacent character (the previous first character) has an assigned codon position
+				for (int ic=nextChar-1; ic>=0; ic--) {
+					nextPos--;
+					if (nextPos<=0) nextPos=3;
+					setCodonPosition(ic,nextPos,false,false);
+				}
+			}
+		} else if (whichTermChars>0) {  //added whichTermChars to end, so we need to get info from the one just before then.
+				// the last character is character getNumChars()-1.  We then go back whichTermChars more to find the one we want.
+			int nextChar = getNumChars()-1-whichTermChars;
+			int nextPos = getCodonPosition(nextChar);
+			if (MesquiteInteger.isCombinable(nextPos) && (nextPos>=1) && (nextPos<=3)) { // the immediately adjacent character (the previous first character) has an assigned codon position
+				for (int ic=nextChar+1; ic<getNumChars(); ic++) {
+					nextPos++;
+					if (nextPos>3) nextPos=1;
+					setCodonPosition(ic,nextPos,false,false);
+				}
+			}
+		}
+	}
+
+
+	/* .......................................... DNAData .................................................. */
+	/** returns if there is a current codon position set */
+	public boolean isCurrentCodonPositionsSet() {
+		if (codonPositionsSet == null)
+			codonPositionsSet = (CodonPositionsSet) getCurrentSpecsSet(CodonPositionsSet.class);
+		return (codonPositionsSet != null);
+	}
+
+	/*-----------------------------------------------------------*/
+	/** checks to see if the two cells have the same states */
+	public boolean sameState(int ic1, int it1, int ic2, int it2){
+		DNAState cs1 = (DNAState)getCharacterState(null, ic1, it1);
+		DNAState  cs2 = (DNAState)getCharacterState(null, ic2, it2);
+		return DNAState.equalsIgnoreCase(cs1.getValue(), cs2.getValue());
+	}
+	/* .......................................... DNAData .................................................. */
+	/** returns if there is there is at least one base that is codon position 1, 2, or 3 */
+	public boolean someCoding() {
+		if (!isCurrentCodonPositionsSet())
+			return false;
+		for (int ic=0; ic<getNumChars(); ic ++){
+			int cp = getCodonPosition(ic);
+			if (cp>=1 && cp<=3)
+				return true;
+		}
+		return false;
+	}
+	/* .......................................... DNAData .................................................. */
+	/** returns if there is there is at least one base that is codon position specified */
+	public boolean anyCodPos(int pos, boolean considerExcluded) {
+		if (!isCurrentCodonPositionsSet())
+			return false;
+		for (int ic=0; ic<getNumChars(); ic ++){
+			if (getCodonPosition(ic)==pos && (considerExcluded || isCurrentlyIncluded(ic)))
+				return true;
+		}
+		return false;
+	}
+
+	/* .......................................... .................................................. */
+	/** Returns true if ic is the first position in a codon. */
+	public boolean isStartOfCodon(int ic) {
+		if (ic + 3 > getNumChars()) 
+			return false;
+		return (getCodonPosition(ic)==1 && getCodonPosition(ic+1)==2 && getCodonPosition(ic+2)==3);
+
+	}
+	/* .......................................... .................................................. */
+	/** Returns the character number of the start of the codon following the one in which character ic participates. */
+	public int getStartOfNextCodon(int ic) {
+		while (ic<getNumChars()){  //this was broken in 3 .03.  I added this outer while loop.  This would only look at the first candidate; if there were two 1's in a row, it would find no more codons
+			int icPos = getCodonPosition(ic);
+			int candidate = -1;
+			if (icPos==1)
+				ic++;
+			icPos = getCodonPosition(ic);
+
+
+			while (icPos!=1 && ic<getNumChars()){
+				icPos = getCodonPosition(ic);
+				if (icPos==1) {
+					candidate = ic;
+					break;
+				}
+				ic++;
+			}
+
+			int[] triplet = getCodonTriplet(candidate);   
+			if (triplet!=null)
+				return candidate;
+		}
+		return -1;
+	}
+	/* ................................................................................................................. */
+	/** Returns the codon in which character ic in taxon it participates. Returned is a long[3] containing the three DNAStates */
+	public long[] getCodon(int ic, int it) {
+		long[] codon = new long[3];
+		int[] triplet = getCodonTriplet(ic);
+
+		if (triplet != null) {
+			codon[0] = getState(triplet[0], it);
+			codon[1] = getState(triplet[1], it);
+			codon[2] = getState(triplet[2], it);
+			return codon;
+		}
+		return null;
+	}
+	/* ................................................................................................................. */
+	/** Returns the codon in which character ic in taxon it participates. Returned is a long[3] containing the three DNAStates */
+	public long[] getCodon(int[] triplet, int it) {
+		long[] codon = new long[3];
+
+		if (triplet != null) {
+			codon[0] = getState(triplet[0], it);
+			codon[1] = getState(triplet[1], it);
+			codon[2] = getState(triplet[2], it);
+			return codon;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the codon in which character ic in taxon it participates. Returned is a long[3] containing the three DNAStates */
+	public long[] getCodon(long[] sequence, int ic) {
+		long[] codon = new long[3];
+		int[] triplet = getCodonTriplet(ic);
+
+		if (triplet != null) {
+			codon[0] = getState(sequence, triplet[0]);
+			codon[1] = getState(sequence, triplet[1]);
+			codon[2] = getState(sequence, triplet[2]);
+			return codon;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the amino acid */
+	public static long getAminoAcid(long[] codon, GeneticCode geneticCode) {
+		if (codon == null || geneticCode == null)
+			return CategoricalState.inapplicable;
+		if (DNAState.isUnassigned(codon[0]) && DNAState.isUnassigned(codon[1]) && DNAState.isUnassigned(codon[2]))
+			return CategoricalState.unassigned;
+		if (DNAState.isInapplicable(codon[0]) || DNAState.isInapplicable(codon[1]) || DNAState.isInapplicable(codon[2]))
+			return CategoricalState.inapplicable;
+
+		long s = DNAState.emptySet();
+		if (DNAState.isUncertain(codon[0]) || DNAState.isUncertain(codon[1]) || DNAState.isUncertain(codon[2]))
+			s = DNAState.setUncertainty(s, true);
+		if (DNAState.isUnassigned(codon[0]) || DNAState.isUnassigned(codon[1]) || DNAState.isUnassigned(codon[2]))
+			s = DNAState.setUncertainty(s, true);
+		if (codon != null) {
+			for (int i = 0; i <= 3; i++)
+				if (DNAState.isElement(codon[0], i) || DNAState.isUnassigned(codon[0]))
+					for (int j = 0; j <= 3; j++)
+						if (DNAState.isElement(codon[1], j) || DNAState.isUnassigned(codon[1]))
+							for (int k = 0; k <= 3; k++)
+								if (DNAState.isElement(codon[2], k) || DNAState.isUnassigned(codon[2]))
+									s = DNAState.addToSet(s, geneticCode.getCode(i, j, k));
+			if (DNAState.isUncertain(s) && DNAState.cardinality(s)==1)
+				s = DNAState.setUncertainty(s, false);
+			return s;
+		}
+		return CategoricalState.inapplicable;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the amino acid that is coded for by a codon that contains character ic in taxon it */
+	public int[] getCodonTriplet(int ic) {
+		int[] triplet = new int[3];
+		triplet[0]=-1;
+		triplet[1]=-1;
+		triplet[2]=-1;
+		int icPos = getCodonPosition(ic);
+			switch (icPos) {
+			case 1:  {// we are at a first position
+				triplet[0]=ic;
+				int ic2=-1;
+				for (ic2=ic+1; ic2<numChars && triplet[1]<0; ic2++){
+					int pos = getCodonPosition(ic2);
+					if (pos==1 || pos==3)
+						return null;
+					if (pos==2){
+						triplet[1]=ic2;
+					}
+				}
+				for (int ic3=triplet[1]+1; ic3<numChars; ic3++){
+					int pos = getCodonPosition(ic3);
+					if (pos==1 || pos==2)
+						return null;
+					if (pos==3){
+						triplet[2]=ic3;
+						break;
+					}
+				}
+				break;
+			}
+			case 2: {  // we are at a second position
+				triplet[1]=ic;
+				int ic2=-1;
+				for (ic2=ic-1; ic2>=0 && triplet[0]<0; ic2--){
+					int pos = getCodonPosition(ic2);
+					if (pos==2 || pos==3)
+						return null;
+					if (pos==1){
+						triplet[0]=ic2;
+					}
+				}
+				for (int ic3=ic+1; ic3<numChars; ic3++){
+					int pos = getCodonPosition(ic3);
+					if (pos==1 || pos==2)
+						return null;
+					if (pos==3){
+						triplet[2]=ic3;
+						break;
+					}
+				}
+				break;
+			}
+			case 3:  {// we are at a third position
+				triplet[2]=ic;
+				int ic2=-1;
+				for (ic2=ic-1; ic2>=0 && triplet[1]<0; ic2--){
+					int pos = getCodonPosition(ic2);
+					if (pos==1 || pos==3)
+						return null;
+					if (pos==2){
+						triplet[1]=ic2;
+					}
+				}
+				for (int ic3=triplet[1]-1; ic3>=0; ic3--){
+					int pos = getCodonPosition(ic3);
+					if (pos==2 || pos==3)
+						return null;
+					if (pos==1){
+						triplet[0]=ic3;
+						break;
+					}
+				}
+				break;
+			}
+			default:
+				return null;
+			}
+			if (triplet[0]==-1 || triplet[1]==-1 || triplet[2]==-1 )
+				return null;
+			return triplet;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the amino acid that is coded for by a codon that contains character ic in taxon it */
+	public long getAminoAcid(int ic, int it, boolean checkForVariableCodes) {
+		int[] triplet = getCodonTriplet(ic); 
+		if (triplet!=null) {
+			GeneticCode genCode = getGeneticCode(triplet[0]);
+			if (genCode!=null && checkForVariableCodes) {
+				if (!genCode.equals(getGeneticCode(triplet[1])) || !genCode.equals(getGeneticCode(triplet[2])))
+					return CategoricalState.inapplicable;
+			}
+			return getAminoAcid(getCodon(triplet, it), genCode);
+		}
+		return CategoricalState.inapplicable;
+	}
+	/* ................................................................................................................. */
+	/** Returns the amino acid that follows the one coded for by a codon that contains character ic in taxon it */
+	public long getNextAminoAcid(MesquiteInteger currentCharacter, int it, boolean checkForVariableCodes) {
+		if (currentCharacter==null)
+			return CategoricalState.inapplicable;
+		int ic = currentCharacter.getValue();
+		int[] triplet = getCodonTriplet(ic); 
+		if (triplet!=null) {
+			triplet = getCodonTriplet(triplet[2]+1);  // go one more character along
+			if (triplet!=null) {
+				currentCharacter.setValue(triplet[0]);
+				GeneticCode genCode = getGeneticCode(triplet[0]);
+				if (genCode!=null && checkForVariableCodes) {
+					if (!genCode.equals(getGeneticCode(triplet[1])) || !genCode.equals(getGeneticCode(triplet[2])))
+						return CategoricalState.inapplicable;
+				}
+				return getAminoAcid(getCodon(triplet, it), genCode);
+			}
+		}
+		return CategoricalState.inapplicable;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns whether or not ic participates in partial coding triplet, i.e., one not containing all three nucleotides*/
+	public boolean isInPartialTriplet(int ic, int it, MesquiteInteger matchLength){
+		int[] triplet = getCodonTriplet(ic); 
+		if (triplet!=null) {
+			boolean oneInapplicable = false;
+			boolean oneApplicable = false;
+			for (int i=0; i<=2; i++) 
+				if (isInapplicable(triplet[i],it))
+					oneInapplicable = true;
+				else
+					oneApplicable = true;
+			if (oneApplicable && oneInapplicable) {
+			if (matchLength!=null)
+				matchLength.setValue(triplet[2]-triplet[0]+1);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** Returns whether or not ic is start of a partial coding triplet, i.e., one not containing all three nucleotides*/
+	public boolean isStartOfPartialTriplet(int ic, int it, MesquiteInteger matchLength){
+		if (!someCoding()) 
+			return false;
+	
+		if (getCodonPosition(ic)==1) {
+			return isInPartialTriplet(ic,it,matchLength);
+		}
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	public  Color alterColorToDeemphasizeDegeneracy(int aa, Color color){
+		int degeneracy = getAminoAcidDegeneracy(0,aa);
+		if (degeneracy==1)
+			color = ColorDistribution.darker(color, 0.3);
+		else if (degeneracy==2)
+			color = ColorDistribution.brighter(color, 0.5);
+		else if (degeneracy>2)
+			color = ColorDistribution.brighter(color, 0.1); 
+		else 
+			color = Color.white;				
+
+		return color;
+	}
+	/* ................................................................................................................. */
+	public  Color alterColorToDeemphasizeDegeneracy(int ic, long s, Color color){
+		if (!CategoricalState.hasMultipleStates(s)) {
+			int aa = CategoricalState.minimum(s);
+			int degeneracy = getAminoAcidDegeneracy(ic,aa);
+			if (degeneracy==1)
+				color = ColorDistribution.darker(color, 0.3);
+			else if (degeneracy==2)
+				color = ColorDistribution.brighter(color, 0.5);
+			else if (degeneracy>2)
+				color = ColorDistribution.brighter(color, 0.1); 
+			else 
+				color = Color.white;				
+		}
+
+		return color;
+	}
+	/* ................................................................................................................. */
+	/** Returns the amino acid that is coded for by a codon that contains character ic in taxon it */
+	public int getAminoAcidDegeneracy(int ic, int aa) {
+		GeneticCode genCode = getGeneticCode(ic);
+		if (genCode!=null)
+			return genCode.getDegeneracy(aa);
+		return 0;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the amino acid that is coded for by a codon that contains character ic in taxon it */
+	public long getAminoAcid(long[] sequence, int ic, boolean checkForVariableCodes) {
+		if (sequence==null)
+			return CategoricalState.inapplicable;
+		int icPos = getCodonPosition(ic);
+		GeneticCode genCode = getGeneticCode(ic);
+		if (checkForVariableCodes) {
+			switch (icPos) {
+			case 1:  {// we are at a first position
+				if (ic + 2 >= getNumChars())
+					return CategoricalState.inapplicable;
+				else
+					if (!genCode.equals(getGeneticCode(ic+1)) || !genCode.equals(getGeneticCode(ic+2)))
+						return CategoricalState.inapplicable;
+
+				break;
+			}
+			case 2: {
+				if (ic + 1 >= getNumChars() || ic-1<0)
+					return CategoricalState.inapplicable;
+				else
+					if (!genCode.equals(getGeneticCode(ic-1)) || !genCode.equals(getGeneticCode(ic+1)))
+						return CategoricalState.inapplicable;
+
+				break;
+			}
+			case 3: {
+				if (ic - 2 <0)
+					return CategoricalState.inapplicable;
+				else
+					if (!genCode.equals(getGeneticCode(ic-2)) || !genCode.equals(getGeneticCode(ic-1)))
+						return CategoricalState.inapplicable;
+
+				break;
+			}
+			default:
+				return CategoricalState.inapplicable;
+			}
+		}
+		return getAminoAcid(getCodon(sequence, ic), genCode);
+	}
+
+	/* ................................................................................................................. */
+	/** Returns true if there is more than one code within the current genetic code set */
+	public boolean getVariableCodes() {
+		GeneticCode genCode = getGeneticCode(0);
+		for (int ic=1;ic<getNumChars(); ic++)
+			if (!genCode.equals(getGeneticCode(ic)))
+				return true;
+		return false;
+	}
+	/* ................................................................................................................. */
+	/** Returns the number of amino acids who state value is "aa" in taxon it */
+	public int getAminoAcidNumbers(int it, int aa, boolean countEvenIfOthersInUncertain) {
+		int count = 0;
+		/*
+		 * long s = 0; int ic=0; while (ic<getNumChars()&& ic>=0) { s = getAminoAcid(ic,it); if (CategoricalState.isElement(s,aa)) count++; ic = getStartOfNextCodon(ic); //returns -1 when no more codons }
+		 */
+		boolean variableCodes = getVariableCodes();
+		if (countEvenIfOthersInUncertain) {
+			for (int ic = 0; ic < getNumChars() && ic >= 0; ic = getStartOfNextCodon(ic)) {
+				if (CategoricalState.isElement(getAminoAcid(ic, it, variableCodes), aa))
+					count++;
+			}
+		}
+		else {
+			for (int ic = 0; ic < getNumChars() && ic >= 0; ic = getStartOfNextCodon(ic)) {
+				long cellAA = getAminoAcid(ic, it, variableCodes);
+				if (CategoricalState.isOnlyElement(cellAA, aa)) {
+					count++;
+				}
+			}
+		}
+		return count;
+	}
+	/* ................................................................................................................. */
+	/** Returns the number of amino acids who state value is "aa" in taxon it */
+	public int getAminoAcidNumbers(int it, int aa) {
+		return getAminoAcidNumbers(it,aa,true);
+	}
+
+	/*.................................................................................................................*  Deleted Oct 09 in favour of method in CodonPositionsSet
+	public String getCodonsAsNexusCharSets(MesquiteInteger numberCharSets, MesquiteString charSetList){
+		return getCodonsAsNexusCharSets(0,"", numberCharSets,charSetList);
+	}
+	/*.................................................................................................................*  Didn't handle \3 properly; deleted Oct 09 in favour of method in CodonPositionsSet
+	public String getCodonsAsNexusCharSets(int startingCharNum, String startString, MesquiteInteger numberCharSets, MesquiteString charSetList){
+		String sT= "";
+		if (!someCoding())
+			return sT;
+		int numCharSets = 0;
+		int unassignedPosition=4;
+		String thisValueString = "";
+		String cslist = "";
+		int numChars = getNumChars();
+//		MesquiteNumber codPos = new MesquiteNumber();
+//		boolean firstTime = true;
+		boolean someValues=false;
+
+
+		for (int iw = 0; iw<4; iw++){
+//			codPos.setValue(iw);
+//			int continuing = 0;
+			thisValueString = "";
+			String charSetName = "";
+			if (!StringUtil.blank(startString)){
+				if (iw==0) 
+					charSetName = StringUtil.tokenize(startString+"NonCoding");
+				else 
+					charSetName = StringUtil.tokenize(startString+"CodonPos" + iw);
+			}
+			else if (iw==0) 
+				charSetName = "nonCoding";
+			else 
+				charSetName = "codonPos" + iw;
+			thisValueString += "\n\tcharset " + charSetName + " = ";
+			int lastWritten = -1;
+			int nextWritten = -1;       
+			int numInRun = 1;
+			someValues=false;
+			boolean firstOfThisSort = true;
+//			boolean skipTwo = false;
+			boolean inTripletRun = true;
+
+			int ic = 0;
+
+			while (ic<numChars) {
+				if (getCodonPosition(ic)==iw) {
+					someValues=true;
+					if (firstOfThisSort) {
+						if (numCharSets>0)
+							cslist += ",";
+						numCharSets++;
+						cslist += " " + charSetName;
+						firstOfThisSort = false;
+					}
+					lastWritten = ic;
+					numInRun = 1;
+					thisValueString += " " + CharacterStates.toExternal(ic+startingCharNum);
+					while (ic<numChars && inTripletRun) {
+						boolean nextIsNotSame = (ic+1<numChars && getCodonPosition(ic+1)!=iw) || ic + 1 >= numChars; 
+						boolean next2IsNotSame = (ic+2<numChars && getCodonPosition(ic+2)!=iw) || ic + 2 >= numChars; 
+						boolean next3IsSame = (ic+3<numChars && getCodonPosition(ic+3)==iw); 
+						if (nextIsNotSame && next2IsNotSame && next3IsSame){
+							ic += 3;
+							nextWritten = ic;
+							numInRun++;
+						} else {
+							if (numInRun>2)
+								thisValueString += "-" + CharacterStates.toExternal(nextWritten+startingCharNum) + "\\3";
+							else if (lastWritten!=nextWritten && nextWritten >= 0)  
+								thisValueString += " " + CharacterStates.toExternal(nextWritten+startingCharNum);
+							inTripletRun = false;
+							numInRun=0;
+						}
+					}
+				}
+				ic++;
+			}
+
+			/*
+			for (int ic=0; ic<getNumChars(); ic++) {
+				if (getCodonPosition(ic)==iw) {  //we've found one of this sort.
+					if (firstOfThisSort) {
+						numCharSets++;
+						if (iw == 0)
+							cslist += "nonCoding ";
+						else
+							cslist += "codonPosition"+iw + " ";
+					}
+
+					if (continuing == 0) {  // the last one found was not of this sort
+						lastWritten = ic;
+						thisValueString += " " + CharacterStates.toExternal(ic);
+						continuing = 1;
+						skipTwo = false;
+						inTripletRun = false;
+						someValues = true;
+					}
+					else if (continuing == 1) { // we are in a run of these that is longer than 
+						thisValueString += "-";
+						continuing = 2;
+						someValues = true;
+					} 
+					firstOfThisSort = false;
+				}
+				else if (continuing>0) {
+					if (lastWritten != ic-1){
+						thisValueString += " " + CharacterStates.toExternal(ic-1);
+						lastWritten = ic-1;
+						someValues = true;
+					}
+					else
+						lastWritten = -1;
+					continuing = 0;
+				}
+
+			}
+			if (continuing>1) {
+				thisValueString += " " + CharacterStates.toExternal(getNumChars()-1) + " ";
+				someValues = true;
+			}
+
+/*
+
+			thisValueString += ";";
+			if (someValues) {
+				sT += thisValueString;
+			}
+		} 
+		if (numberCharSets !=null)
+			numberCharSets.setValue(numCharSets);
+		if (charSetList!=null)
+			charSetList.setValue(cslist);
+		return sT;
+	} */	
+	/* ................................................................................................................. */
+	/** Returns a protein data object that corresponds to this nucleotide sequence */
+	public ProteinData getProteinData(ProteinData protData, boolean warn) {
+		if (!someCoding()) {
+			if (warn)
+				MesquiteMessage.discreetNotifyUser("Mesquite cannot translate DNA to Protein as codon positions have not been designated.");
+			return null;
+		}
+		ProteinData proteins = protData;
+		if (protData == null || protData.getTaxa() != getTaxa()) {
+			CharactersManager manageCharacters = (CharactersManager) getMatrixManager().findElementManager(CharacterData.class);
+			CharMatrixManager manager = manageCharacters.getMatrixManager(ProteinData.class);
+			proteins = new ProteinData(manager, getNumTaxa(), getNumChars()/3+1, getTaxa());
+		}
+		boolean variableCodes = getVariableCodes();
+
+		for (int it = 0; it < getNumTaxa(); it++) {
+			int icProt = 0;
+			for (int ic = 0; ic < getNumChars() && ic >= 0; ic = getStartOfNextCodon(ic)) {
+				proteins.setState(icProt, it, getAminoAcid(ic, it, variableCodes));
+				icProt++;
+			}
+		}
+
+		return proteins;
+	}
+
+	/* ................................................................................................................. */
+	/** gets the explanation of this matrix */
+	public String getExplanation() {
+		String extra = "This DNA character matrix for the taxa block \"" + getTaxa().getName() + "\" has " + getNumChars() + " characters for the " + getNumTaxa() + " taxa. Category of data: " + getDataTypeName() + "\n";
+		int[] freq = new int[4];
+		for (int i = 0; i < 4; i++)
+			freq[i] = 0;
+		int cg = 0;
+		for (int it = 0; it < getNumTaxa(); it++) {
+			for (int ic = 0; ic < getNumChars(); ic++) {
+				long s = getStateRaw(ic, it);
+				if (!CategoricalState.isUnassigned(s) && !CategoricalState.isInapplicable(s)) {
+					cg++;
+					for (int i = 0; i < 4; i++)
+						if (CategoricalState.isElement(s, i))
+							freq[i]++;
+				}
+			}
+		}
+		if (cg != 0) {
+			extra += "Frequency of A: " + MesquiteDouble.toString(((double) freq[0]) / cg) + " C: " + MesquiteDouble.toString(((double) freq[1]) / cg) + " G: " + MesquiteDouble.toString(((double) freq[2]) / cg) + " T: " + MesquiteDouble.toString(((double) freq[3]) / cg);
+		}
+
+		return extra;
+
+	}
+
+	/* ..........................................DNAData................ */
+	public static DefaultReference findDefaultReference(NameReference paradigm) {
+		if (defaultModels == null) {
+			MesquiteMessage.warnProgrammer("findDefaultReference with null default models ");
+			MesquiteMessage.printStackTrace();
+			return null;
+		}
+		for (int i = 0; i < defaultModels.size(); i++) {
+			DefaultReference dR = (DefaultReference) defaultModels.elementAt(i);
+
+			if (dR.getParadigm() != null && dR.getParadigm().equals(paradigm))
+				return dR;
+		}
+		return null;
+
+	}
+
+	/* ..........................................DNAData................ */
+	public static void registerDefaultModel(String paradigm, String name) {
+		if (defaultModels == null)
+			return;
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR == null) {
+			dR = new DefaultReference(p);
+			defaultModels.addElement(dR);
+		}
+		dR.setDefault(name);
+	}
+
+	/* ..........................................DNAData................ */
+	public CharacterModel getDefaultModel(String paradigm) {
+		if (paradigm == null)
+			return null;
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR == null)
+			return null;
+		else {
+			CharacterModel cm = getProject().getCharacterModel(dR.getDefault());
+			if (cm == null)
+				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+			return cm;
+		}
+	}
+
+
+
+
+	/* .......................................... DNAData .................................................. */
+	public static String collapseGaps(String seq) {
+		if (seq == null)
+			return null;
+		StringBuffer s = new StringBuffer(seq.length());
+		for (int i = 0; i < seq.length(); i++) {
+			if (seq.charAt(i) != '-')
+				s.append(seq.charAt(i));
+		}
+		return s.toString();
+	}
+	/* .......................................... DNAData .................................................. */
+	public static String collapseSymbol(String seq, char remove) {
+		if (seq == null)
+			return null;
+		StringBuffer s = new StringBuffer(seq.length());
+		for (int i = 0; i < seq.length(); i++) {
+			if (seq.charAt(i) != remove)
+				s.append(seq.charAt(i));
+		}
+		return s.toString();
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public static String reverseString(String seq) {
+		if (seq == null)
+			return null;
+		StringBuffer s = new StringBuffer(seq.length());
+		for (int i = 0; i < seq.length(); i++)
+			s.append(seq.charAt(seq.length() - i - 1));
+		return s.toString();
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public static String complementString(String seq) {
+		if (seq == null)
+			return null;
+		StringBuffer s = new StringBuffer(seq.length());
+		for (int i = 0; i < seq.length(); i++)
+			s.append(complementChar(seq.charAt(i)));
+		return s.toString();
+	}
+	/* .......................................... DNAData .................................................. */
+	public static long[] sequenceLongsFromString(String s){
+		if (s == null)
+			return null;
+		long[] sites = new long[s.length()];
+
+		for (int i = 0; i< s.length(); i++){
+			sites[i] = DNAState.fromCharStatic(s.charAt(i));
+			if (sites[i] == CategoricalState.impossible){
+				sites[i] = CategoricalState.inapplicable;
+
+			}
+		}
+		return sites;
+	}
+
+
+	/* .......................................... DNAData .................................................. */
+	public static long[] sequenceLongsFromString(String s, int length){
+		if (s == null)
+			return null;
+		int sL = s.length();
+		if (length>sL)
+			sL = length;
+		long[] sites = new long[sL];
+		for(int i=0; i<sL; i++)
+			sites[i] = CategoricalState.inapplicable;
+		for (int i = 0; i< s.length(); i++){
+			sites[i] = DNAState.fromCharStatic(s.charAt(i));
+			if (sites[i] == CategoricalState.impossible){
+				sites[i] = CategoricalState.inapplicable;
+			}
+		}
+		return sites;
+	}
+	/* .......................................... DNAData .................................................. */
+	public static String sequenceStringFromLongs(long[] s){
+		return sequenceStringFromLongs(s, false);
+	}
+	/* .......................................... DNAData .................................................. */
+	public static String sequenceStringFromLongs(long[] s, boolean stripTerminalMissingOrGap){
+		if (s == null)
+			return null;
+		StringBuffer sb = new StringBuffer(s.length);
+		int start = 0;
+		int end = s.length-1;
+		if (stripTerminalMissingOrGap){
+			boolean done = false;
+			for (int i=0; i<s.length && !done; i++){
+				if (s[i] != DNAState.inapplicable && s[i] != DNAState.unassigned){
+					start = i;
+					done = true;
+				}
+			}
+			done = false;
+			for (int i=s.length-1; i>=0 && !done; i--){
+				if (s[i] != DNAState.inapplicable && s[i] != DNAState.unassigned){
+					end = i;
+					done = true;
+				}
+			}
+		}
+
+		for (int i = start; i<= end; i++){
+			sb.append(DNAState.toCharStatic(s[i]));
+		}
+		return sb.toString();
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public static long[] convertTerminalMissingToGaps(long[] s){
+		boolean done = false;
+		for (int i=0; i<s.length && !done; i++){
+			if (s[i] != DNAState.inapplicable && s[i] != DNAState.unassigned)
+				done = true;
+			if (s[i] == DNAState.unassigned)
+				s[i] = DNAState.inapplicable;
+		}
+		done = false;
+		for (int i=s.length-1; i>=0 && !done; i--){
+			if (s[i] != DNAState.inapplicable && s[i] != DNAState.unassigned)
+				done = true;
+			if (s[i] == DNAState.unassigned)
+				s[i] = DNAState.inapplicable;
+		}
+		return s;
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public static char complementChar(char c) {
+		if (c == 'a')
+			return 't';
+		else if (c == 'A')
+			return 'T';
+		else if (c == 'c')
+			return 'g';
+		else if (c == 'C')
+			return 'G';
+		else if (c == 'g')
+			return 'c';
+		else if (c == 'G')
+			return 'C';
+		else if (c == 't')
+			return 'a';
+		else if (c == 'T')
+			return 'A';
+
+		else if (c == 'v')
+			return 'b';
+		else if (c == 'V')
+			return 'B';
+		else if (c == 'd')
+			return 'h';
+		else if (c == 'D')
+			return 'H';
+		else if (c == 'h')
+			return 'd';
+		else if (c == 'H')
+			return 'D';
+		else if (c == 'b')
+			return 'v';
+		else if (c == 'B')
+			return 'V';
+		else if (c == 'm')
+			return 'k';
+		else if (c == 'M')
+			return 'K';
+		else if (c == 'r')
+			return 'y';
+		else if (c == 'R')
+			return 'Y';
+		else if (c == 'y')
+			return 'r';
+		else if (c == 'Y')
+			return 'R';
+		else if (c == 'k')
+			return 'm';
+		else if (c == 'K')
+			return 'M';
+		else
+			return c;
+	}
+
+
+	/* .......................................... DNAData .................................................. */
+	/** Complement the stateset at ic,it */
+	public void complement(int ic, int it) {
+		long s = getStateRaw(ic, it);
+		setState(ic, it, DNAState.complement(s));
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public boolean isComplemented( int it) {
+		Associable tInfo = getTaxaInfo(false);
+		if (tInfo!=null) {
+			return tInfo.getAssociatedBit(complementedRef,it);
+		}
+		return false;
+	}
+	/* .......................................... DNAData .................................................. */
+	public void setComplemented( int it, boolean value) {
+		Associable tInfo = getTaxaInfo(false);
+		if (tInfo!=null) {
+			tInfo.setAssociatedBit(complementedRef, it, value);
+		}
+	}
+	/* .......................................... DNAData .................................................. */
+	/** Complements a stretch of DNA and complements linked data matrices too. */
+	public void complement(int icStart, int icEnd, int it, boolean adjustComplementLinked) {
+		if ((icStart==0 && icEnd==getNumChars()-1) || (!anyApplicableBefore(icStart, it)&& !anyApplicableAfter(icEnd,it))) {
+			Associable tInfo = getTaxaInfo(true);
+			if (tInfo!=null) {
+				boolean prevValue = tInfo.getAssociatedBit(complementedRef,it);
+				tInfo.setAssociatedBit(complementedRef, it, !prevValue);
+			}
+		}
+		for (int ic = icStart; ic <= icEnd; ic++)
+			complement(ic, it);
+		if (adjustComplementLinked) {
+			for (int i = 0; i < linkedDatas.size(); i++) {
+				CharacterData d = (CharacterData) linkedDatas.elementAt(i);
+				if (d instanceof DNAData)
+					for (int ic = icStart; ic <= icEnd; ic++)
+						((DNAData) d).complement(ic, it);
+			}
+		}
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/**
+	 * Does the reverse complement of the data from character icStart to icEnd in taxon it. If reverseTerminalGaps is true, then it reversed the entire stretch; if it is false, it only reverses from the first non-gap to last non-gap in the stretch.
+	 */
+	public void reverseComplement(int icStart, int icEnd, int it, boolean reverseTerminalGaps, boolean adjustCellLinked) {
+		reverse(icStart, icEnd, it, reverseTerminalGaps, adjustCellLinked);
+		complement(icStart, icEnd, it, adjustCellLinked);
+	}
+
+	
+	public void reverseComplement(int icStart, int icEnd, boolean adjustCellLinked) { //NOTE: this version reverses character metadata (codon positions, etc.)
+		reverse(icStart, icEnd, adjustCellLinked);
+		for (int it = 0; it<getNumTaxa(); it++)
+			complement(icStart, icEnd, it, adjustCellLinked);
+	}
+	/* .......................................... DNAData .................................................. */
+	/** Returns IUPAC symbol of a state */
+	public static String getIUPACSymbol(long s) {
+		boolean s0 = CategoricalState.isElement(s, 0);
+		boolean s1 = CategoricalState.isElement(s, 1);
+		boolean s2 = CategoricalState.isElement(s, 2);
+		boolean s3 = CategoricalState.isElement(s, 3);
+
+		if (s == CategoricalState.unassigned || (s0 && s1 && s2 && s3))
+			return "N";
+		else if (s0 && s1 && s2)
+			return "V";
+		else if (s0 && s2 && s3)
+			return "D";
+		else if (s0 && s1 && s3)
+			return "H";
+		else if (s1 && s2 && s3)
+			return "B";
+		else if (s0 && s1)
+			return "M";
+		else if (s0 && s2)
+			return "R";
+		else if (s0 && s3)
+			return "W";
+		else if (s1 && s2)
+			return "S";
+		else if (s1 && s3)
+			return "Y";
+		else if (s2 && s3)
+			return "K";
+		else if (s0)
+			return "A";
+		else if (s1)
+			return "C";
+		else if (s2)
+			return "G";
+		else if (s3)
+			return "T";
+		return "X";
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** Returns IUPAC symbol of a state as a char */
+	public static char getIUPACChar(long s) {
+		boolean s0 = CategoricalState.isElement(s, 0);
+		boolean s1 = CategoricalState.isElement(s, 1);
+		boolean s2 = CategoricalState.isElement(s, 2);
+		boolean s3 = CategoricalState.isElement(s, 3);
+
+		if (s0 && s1 && s2 && s3)
+			return 'N';
+		else if (s0 && s1 && s2)
+			return 'V';
+		else if (s0 && s2 && s3)
+			return 'D';
+		else if (s0 && s1 && s3)
+			return 'H';
+		else if (s1 && s2 && s3)
+			return 'B';
+		else if (s0 && s1)
+			return 'M';
+		else if (s0 && s2)
+			return 'R';
+		else if (s0 && s3)
+			return 'W';
+		else if (s1 && s2)
+			return 'S';
+		else if (s1 && s3)
+			return 'Y';
+		else if (s2 && s3)
+			return 'K';
+		else if (s0)
+			return 'A';
+		else if (s1)
+			return 'C';
+		else if (s2)
+			return 'G';
+		else if (s3)
+			return 'T';
+		return 'X';
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** appends to buffer string describing the state(s) of character ic in taxon it. */
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay) {
+		statesIntoStringBufferCore(ic, s, sb, forDisplay, true, true);
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/** appends to buffer string describing the state(s) of character ic in taxon it. */
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned) {
+		if (CategoricalState.cardinality(s) > 1 && CategoricalState.isUncertain(s))
+			sb.append(getIUPACSymbol(s));
+		else {
+			if (s == CategoricalState.inapplicable) {
+				if (includeInapplicable)
+					sb.append(getInapplicableSymbol());
+			}
+			else if (s == CategoricalState.unassigned) {
+				if (includeUnassigned) {
+					if (!forDisplay)
+						sb.append(getIUPACSymbol(s));
+					else
+						sb.append(getUnassignedSymbol());
+				}
+			}
+			else {
+				boolean first = true;
+				char sep;
+				if (CategoricalState.isUncertain(s))
+					sep = '/';
+				else
+					sep = '&';
+				boolean lowerCase = CategoricalState.isLowerCase(s);
+				for (int e = 0; e <= CategoricalState.maxCategoricalState; e++) {
+					if (CategoricalState.isElement(s, e)) {
+						if (!first)
+							sb.append(sep);
+						appendStateSymbol(e, lowerCase, sb);
+						first = false;
+					}
+				}
+				if (first)
+					sb.append('!'); // no state found!
+			}
+		}
+	}
+
+	/* ............................................................................................ */
+	/** gets default state symbol for state "state", returned as string. */
+	public static String getDefaultStateSymbol(int state) {
+		if (state == 0)
+			return "A";
+		else if (state == 1)
+			return "C";
+		else if (state == 2)
+			return "G";
+		else if (state == 3)
+			return "T";
+		else
+			return Integer.toString(state);
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/* Appends to buffer state symbol for state e � */
+	protected void appendStateSymbol(int e, boolean lowerCase, StringBuffer sb) {
+		if (lowerCase) {
+			if (e == 0)
+				sb.append('a');
+			else if (e == 1)
+				sb.append('c');
+			else if (e == 2)
+				sb.append('g');
+			else if (e == 3) {
+				if (displayAsRNA)
+					sb.append('u');
+				else
+					sb.append('t');
+			}
+		}
+		else {
+			if (e == 0)
+				sb.append('A');
+			else if (e == 1)
+				sb.append('C');
+			else if (e == 2)
+				sb.append('G');
+			else if (e == 3) {
+				if (displayAsRNA)
+					sb.append('U');
+				else
+					sb.append('T');
+			}
+		}
+	}
+
+	/* .......................................... DNAData .................................................. */
+	/* Fills buffer with string version of state in char ic and taxon it � */
+	public void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb) {
+		boolean first = true;
+		long s = getStateRaw(ic, it);
+		if (s == 0L || s == CategoricalState.impossible)
+			sb.append('!');
+		else if (s == CategoricalState.inapplicable)
+			sb.append(getInapplicableSymbol());
+		else if (s == CategoricalState.unassigned)
+			sb.append(getUnassignedSymbol());
+		else if (CategoricalState.cardinality(s) > 1 && CategoricalState.isUncertain(s))  //DavidJan07: OK?
+			sb.append(getIUPACSymbol(s));
+		else {
+			int card = 0;
+			int current = sb.length();
+			for (int e = 0; e <= DNAState.maxDNAState; e++) {
+				if (CategoricalState.isElement(s, e)) {
+					card++;
+					if (!first)
+						sb.append(' ');
+					appendStateSymbol(e, CategoricalState.isLowerCase(s), sb);
+					first = false;
+				}
+			}
+			if (card > 1) {
+				if (CategoricalState.isUncertain(s)) {
+					sb.insert(current, '{');
+					sb.append('}');
+				}
+				else {
+					sb.insert(current, '(');
+					sb.append(')');
+				}
+			}
+			if (first) { // nothing written! Write illegal character so that change will not go unnoticed
+				sb.append('!');
+				if (ic == 0 && it == 0)
+					ecount = 0;
+				if (ecount++ < 100)
+					MesquiteMessage.warnProgrammer("ERROR: nothing written for character " + (ic + 1) + " taxon " + (it + 1) + " state as long: " + s);
+			}
+		}
+	}
+
+	int ecount = 0;
+
+	/* .......................................... DNAData .................................................. */
+	public long obviousFromChar(char c){
+		if (c == symbols[0])
+			return DNAState.A;
+		if (c == symbols[1])
+			return DNAState.C;
+		if (c == symbols[2])
+			return DNAState.G;
+		if (c == symbols[3])
+			return DNAState.T;
+		switch (c) {
+		case 'A': 
+			return DNAState.A;
+		case 'C': 
+			return DNAState.C;
+		case 'G': 
+			return DNAState.G;
+		case 'T': 
+			return DNAState.T;
+		case 'a': 
+			return DNAState.a;
+		case 'c': 
+			return DNAState.c;
+		case 'g': 
+			return DNAState.g;
+		case 't': 
+			return DNAState.t;
+		case '-': 
+			return CategoricalState.inapplicable;
+		default: 
+			return 0L;
+		}
+	}
+	/* .......................................... DNAData .................................................. */
+	/* Returns state set from single state symbol � */
+	public long fromChar(char state) {
+		if (state == getInapplicableSymbol())
+			return CategoricalState.inapplicable;
+		else if (state == getUnassignedSymbol() || state == 'N')
+			return CategoricalState.unassigned;
+		else if (state == getMatchChar()) {
+			return CategoricalState.unassigned;// note: this should't happen, as matchchar with no char #
+		}
+		else {
+			long s = DNAState.fromCharStatic(state);
+			return s;
+		}
+	}
+
+	/* ..........................................DNAData..................................... */
+	/** returns the maximum possible state */
+	public int getMaxPossibleState() {
+		return DNAState.getMaxPossibleStateStatic();
+	}
+
+	/* ..........................................DNAData..................................... */
+	/** returns the name of a non-missing, applicable entry in a matrix cell; e.g. "base" for DNAData*/
+	public String getNameOfCellEntry(int number){
+		if (number==1)
+			return "base";
+		else
+			return "bases";
+	}
+
+
+}
+
diff --git a/Source/mesquite/categ/lib/DNADataAlterer.java b/Source/mesquite/categ/lib/DNADataAlterer.java
new file mode 100644
index 0000000..6c1cba3
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNADataAlterer.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class DNADataAlterer extends DataAlterer  {
+   	 public Class getDutyClass() {
+   	 	return DNADataAlterer.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/DNADataAltererCon.java b/Source/mesquite/categ/lib/DNADataAltererCon.java
new file mode 100644
index 0000000..3e0722d
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNADataAltererCon.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.categ.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public abstract class DNADataAltererCon extends DataAltererCon {
+
+ 	 public Class getDutyClass() {
+    	 	return DNADataAltererCon.class;
+    	 }
+ 	/*.................................................................................................................*/
+ 	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+ 	public CompatibilityTest getCompatibilityTest(){
+ 		return new RequiresAnyDNAData();
+ 	}
+
+}
diff --git a/Source/mesquite/categ/lib/DNADataSearcher.java b/Source/mesquite/categ/lib/DNADataSearcher.java
new file mode 100644
index 0000000..420129a
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNADataSearcher.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class DNADataSearcher extends DataSearcher  {
+   	 public Class getDutyClass() {
+   	 	return DNADataSearcher.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/DNADataUtility.java b/Source/mesquite/categ/lib/DNADataUtility.java
new file mode 100644
index 0000000..b6c03d9
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNADataUtility.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class DNADataUtility extends DataUtility  {
+   	 public Class getDutyClass() {
+   	 	return DNADataUtility.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+
+}
+
diff --git a/Source/mesquite/categ/lib/DNAEmbedded.java b/Source/mesquite/categ/lib/DNAEmbedded.java
new file mode 100644
index 0000000..ca8024d
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNAEmbedded.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public class DNAEmbedded extends CategoricalEmbedded {
+	public DNAEmbedded (DNAData data, int ic) {
+		super(data, ic);
+		enforcedMaxState = 3;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return DNAState.fullSet();
+	}
+	/*..........................................  DNAState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		DNAState c;
+		if (cs == null || !(cs instanceof DNAState))
+			c = new DNAState();
+		else
+			c = (DNAState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == DNACharacterHistory.class))
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new DNACharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new DNACharacterAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
+
diff --git a/Source/mesquite/categ/lib/DNAState.java b/Source/mesquite/categ/lib/DNAState.java
new file mode 100644
index 0000000..acd550b
--- /dev/null
+++ b/Source/mesquite/categ/lib/DNAState.java
@@ -0,0 +1,470 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CategoricalState set for DNA (max state enforced at 3). */
+public class DNAState extends MolecularState{
+	public final static long A= 1L;
+	public final static long C= 2L;
+	public final static long G= 4L;
+	public final static long T= 8L;
+	public final static long a = setLowerCase(A, true);
+	public final static long c = setLowerCase(C, true);
+	public final static long g = setLowerCase(G, true);
+	public final static long t = setLowerCase(T, true);
+	public static final int maxDNAState = 3;
+	
+	public DNAState(long initial){
+		super(initial);
+	}
+	public DNAState(){
+		super();
+	}
+	public Class getCharacterDataClass() {
+		return DNAData.class;
+	}
+	public String getDataTypeName(){
+		return DNAData.DATATYPENAME;
+	}
+	public Class getMCharactersDistributionClass(){
+		return MDNAAdjustable.class;
+	}
+	
+	public static long fullSet(){
+		return CategoricalState.span(0, maxDNAState);
+	}
+	public Class getCharacterDistributionClass() {
+		return DNACharacterAdjustable.class;
+	}
+	public Class getCharacterHistoryClass() {
+		return DNACharacterHistory.class;
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new DNACharacterAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new DNACharacterHistory(taxa, numNodes);
+	}
+	
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  �*/
+	public  String toDisplayString(){
+		if (isInapplicable(set))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(set))
+			return "" + CharacterData.defaultMissingChar;
+		char sep = '&';
+		if (isUncertain(set))
+			sep = '/';
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&set)!=0L) {
+				if (!first)
+					temp+=sep;
+				if (e<4)
+					temp += toString(e, isLowerCase(set));
+				else
+					temp+= Integer.toString(e); //there should be no such states, but just in case, show as integers
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		return temp;
+	}
+	/*..........................................DNAState.....................................*/
+	/**Returns the only element in state set s.  If more than one element, or no elements, returns -1. */
+	public static int getOnlyElement(long s) {
+		if (s == A)
+			return 0;
+		else if (s == C)
+			return 1;
+		else if (s == G)
+			return 2;
+		else if (s == T)
+			return 3;
+		return -1;  
+	}
+	/*..........................................DNAState.....................................*/
+	/**return maximum value of states in state set s */
+	public static int maximum(long s) {
+		if (s==0L) {
+		 	return -1;  
+		}
+		else {
+			int max = -1;
+			for (int e=0; e<= maxDNAState; e++) {
+				if (((1L<<e)&s)!=0L) {  //test bit
+					max=e;
+				}
+			}
+			return max;
+		}
+	}	
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equalsIgnoreCase(CategoricalState s) {
+		if (s==null)
+			return false;
+		long t = getValue();
+		long tO = ((CategoricalState)s).getValue();
+		return (setLowerCase(tO, false) == setLowerCase(t,false));
+	}
+
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns true iff state sets are same except for case */
+	public static boolean equalsIgnoreCase(long s1, long s2) {
+		return setLowerCase(s1, false) == setLowerCase(s2, false) ;
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed int (treated as DNAState) to string.  Uses character state names if available. �*/
+	public static String toString(int e, boolean isLowerCase) {
+		if (isLowerCase){
+			if (e==0)
+			return "a";
+		else if (e==1)
+			return "c";
+		else if (e==2)
+			return "g";
+		else if (e==3)
+			return "t";
+		else
+			return Integer.toString(e);
+		}
+		else {
+			if (e==0)
+				return "A";
+			else if (e==1)
+				return "C";
+			else if (e==2)
+				return "G";
+			else if (e==3)
+				return "T";
+			else
+				return Integer.toString(e);
+		}
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed int (treated as DNAState) to string.  Uses character state names if available. �*/
+	public static String toString(int e) {
+		if (e==0)
+			return "A";
+		else if (e==1)
+			return "C";
+		else if (e==2)
+			return "G";
+		else if (e==3)
+			return "T";
+		else
+			return Integer.toString(e);
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed int (treated as DNAState) to string.  Uses character state names if available. �*/
+	public static char toChar(int e, CharacterData data, boolean lowerCase) {
+		if (lowerCase){
+			if (e==0)
+				return 'a';
+			else if (e==1)
+				return 'c';
+			else if (e==2)
+				return 'g';
+			else if (e==3) {
+				if (data == null || !(data instanceof DNAData) || !((DNAData)data).displayAsRNA)
+					return 't';
+				else
+					return 'u';
+			}
+			else
+				return '!';
+		}
+		if (e==0)
+			return 'A';
+		else if (e==1)
+			return 'C';
+		else if (e==2)
+			return 'G';
+		else if (e==3) {
+			if (data == null || !(data instanceof DNAData) || !((DNAData)data).displayAsRNA)
+				return 'T';
+			else
+				return 'U';
+		}
+		else
+			return '!';
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long array (treated as DNAStates) to string.  */
+	public static String toString(long[] s) {
+		if (s == null)
+			return null;
+		String seq = "";
+		for (int i=0; i<s.length; i++)
+		 seq += toCharStatic(s[i]);
+		return seq;
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long array (treated as DNAStates) to string.  */
+	public static String toStringRow(long[][] s, int row) {
+		if (s == null || s.length == 0 || row >= s[0].length)
+			return null;
+		String seq = "";
+		for (int i=0; i<s.length; i++)
+		 seq += toCharStatic(s[i][row]);
+		return seq;
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as DNAState) to string.  Uses braces*/
+	public static String toString(long s) {
+		return toString(s, null, 0, true);
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as DNAState) to string.  */
+	public static String toString(long s, boolean useBraces) {
+		return toString(s, null, 0, useBraces);
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as DNAState) to string.  .*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces) {
+		return toString(s, data, ic, useBraces, false);
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as DNAState) to string. �*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces, boolean useSymbols) {
+		if (s == impossible)
+			return "impossible";
+		else if (s== unassigned) {
+			if (data == null)
+				return "?";
+			else
+				return String.valueOf(data.getUnassignedSymbol());
+		}
+		else if (s == inapplicable){
+			if (data == null)
+				return "-";
+			else
+				return String.valueOf(data.getInapplicableSymbol());
+		}
+		boolean first=true;
+		String temp;
+		if (useBraces) 
+			temp="{";
+		else
+			temp="";
+		for (int e=0; e<=maxDNAState; e++) {
+			if (isElement(s, e)) {
+				if (!first)
+					temp+=" ";
+				if (data != null) {
+					temp+=data.getStateName(ic, e);
+				}
+				else if (e>=0 && e<=3)
+					temp+= toChar(e, data, CategoricalState.isLowerCase(s));
+				else
+					temp+=Integer.toString(e);
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		if (useBraces)
+			temp+="}";
+		return temp;
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public String toNEXUSString() {
+		return DNAState.toNEXUSString(set);
+	}
+	/*..........................................DNAState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public static String toNEXUSString(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		return DNAData.getIUPACSymbol(s);
+	}
+	/*.................................................................................................................*/
+	/** Returns whether or not the codon has any base that is a gap (inapplicable) */
+	 		public static boolean hasInapplicable (long[] codon) {
+ 			if (codon==null && codon.length>=3)
+ 				return false;
+ 	 		return (isInapplicable(codon[0])|| isInapplicable(codon[1]) || isInapplicable(codon[2]));
+		}
+	/*.................................................................................................................*/
+  	/** Returns whether or not the codon has any base that is ambiguous or otherwise has mulitple states */
+ 		public static boolean hasMultipleStates (long[] codon) {
+ 			if (codon==null && codon.length>=3)
+ 				return false;
+ 	 		return (hasMultipleStates(codon[0])|| hasMultipleStates(codon[1]) || hasMultipleStates(codon[2]));
+		}
+ 		/* .......................................... DNAState .................................................. */
+ 		/** Returns Complement of a state */
+ 		public static long complement(long s) {
+ 			if (s == CategoricalState.unassigned || s == CategoricalState.impossible || s == CategoricalState.inapplicable)
+ 				return s;
+ 			long comp = CategoricalState.emptySet();
+
+ 			if (CategoricalState.isElement(s, 0)) // there is an A in the original
+ 				comp = CategoricalState.addToSet(comp, 3);
+ 			if (CategoricalState.isElement(s, 1)) // there is an C in the original
+ 				comp = CategoricalState.addToSet(comp, 2);
+ 			if (CategoricalState.isElement(s, 2)) // there is an G in the original
+ 				comp = CategoricalState.addToSet(comp, 1);
+ 			if (CategoricalState.isElement(s, 3)) // there is an T in the original
+ 				comp = CategoricalState.addToSet(comp, 0);
+ 			if (CategoricalState.isLowerCase(s))
+ 				comp = CategoricalState.setLowerCase(comp, true);
+ 			if (CategoricalState.isUncertain(s))
+ 				comp = CategoricalState.setUncertainty(comp, true);
+ 			return comp;
+ 		}
+	/*..........................................DNAState.....................................*/
+	/**Returns the state set contains a purine, i.e., A or G. */
+	public boolean hasPurine() {   
+		return isElement(0) || isElement (2);
+	}
+	/*..........................................DNAState.....................................*/
+	/**Static method that returns the state set contains a purine, i.e., A or G. */
+	public static boolean hasPurine(long s) {   
+		return isElement(s, 0) || isElement (s, 2);
+	}
+	/*..........................................DNAState.....................................*/
+	/**Returns the state set contains a pyrimidine, i.e., C or T. */
+	public boolean hasPyrimidine() {   
+		return isElement(1) || isElement (3);
+	}
+	/*..........................................DNAState.....................................*/
+	/**Static method that eturns the state set contains a pyrmidine, i.e., C or T. */
+	public static boolean hasPyrimidine(long s) {   
+		return isElement(s, 1) || isElement (s, 3);
+	}
+	/*..........................................DNAState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}) �*/
+	public long fromChar(char c) { 
+		return fromCharStatic(c);
+	}
+	/*..........................................DNAState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}) �*/
+	public static long fromCharStatic(char c) { 
+		if (c == '?')
+			return unassigned;
+		else if (c == '-')
+			return inapplicable;
+		else if (c == 'A') 
+			return A;
+		else if (c == 'C')
+			return C;
+		else if (c == 'G')
+			return G;
+		else if (c == 'T' || c == 'U')
+			return T;
+ 		else if (c == 'a') 
+			return CategoricalState.setLowerCase(A, true);
+		else if (c == 'c')
+			return CategoricalState.setLowerCase(C, true);
+		else if (c == 'g')
+			return CategoricalState.setLowerCase(G, true);
+		else if (c == 't' || c == 'u')
+			return CategoricalState.setLowerCase(T, true);
+		else if (c == 'R' || c == 'r') // A or G
+			return CategoricalState.setUncertainty(A | G, true);
+		else if (c == 'Y' || c == 'y') // C or T
+			return CategoricalState.setUncertainty(C | T, true);
+		else if (c == 'B' || c == 'b')  // 123
+			return CategoricalState.setUncertainty(C | G | T, true);
+		else if (c == 'D' || c == 'd')  // 023
+			return CategoricalState.setUncertainty(A | G | T, true);
+		else if (c == 'H' || c == 'h')  // 013
+			return CategoricalState.setUncertainty(A | C | T, true);
+		else if (c == 'K' || c == 'k')  // 23
+			return CategoricalState.setUncertainty(G | T, true);
+		else if (c == 'M' || c == 'm')  // 01
+			return CategoricalState.setUncertainty(A | C , true);
+		else if (c == 'S' || c == 's')  // 12
+			return CategoricalState.setUncertainty(C | G, true);
+		else if (c == 'V' || c == 'v')  // 012
+			return CategoricalState.setUncertainty(A | C | G, true);
+		else if (c == 'W' || c == 'w')  // 03
+			return CategoricalState.setUncertainty(A | T, true);
+		else if (c == 'N' || c == 'n' || c == 'X' || c == 'x')  // ?
+			return unassigned;
+		int s = Character.digit(c, 10);
+		if (s>=0 && s<= DNAState.maxDNAState)
+			return CategoricalState.makeSet(s);
+  		return CategoricalState.impossible;
+	}
+	/*..........................................DNAState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}) �*/
+	public static char toCharStatic(long c) { 
+		if (c == unassigned)
+			return '?';
+		else if (c == inapplicable)
+			return '-';
+		c = c & statesBitsMask;
+		if (c == A) //should make this more efficient by using constants!
+			return 'A';
+		else if (c == C)
+			return 'C';
+		else if (c == G)
+			return 'G';
+		else if (c == T)
+			return 'T';
+ 		else if (c == (A | C) )
+ 			return 'M';
+		else if (c == (A  | G)  )
+ 			return 'R';
+		else if (c == (A  | T)  )
+ 			return 'W';
+		else if (c ==  (C | G )  )
+ 			return 'S';
+		else if (c ==  (C |  T)  )
+ 			return 'Y';
+		else if (c ==   (G | T)  )
+ 			return 'K';
+		else if (c == (A | C | G )  )
+ 			return 'V';
+		else if (c == (A | C | T)  )
+ 			return 'H';
+		else if (c == (A |  G | T)  )
+ 			return 'D';
+		else if (c ==  (C | G | T) ) 
+ 			return 'B';
+		else if (c == (A | C | G | T)  )
+ 			return 'N';
+ 		return '!';
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public static int getMaxPossibleStateStatic() {
+		return maxDNAState;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public  int getMaxPossibleState() {
+		return maxDNAState;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MCategoricalAdjustable.java b/Source/mesquite/categ/lib/MCategoricalAdjustable.java
new file mode 100644
index 0000000..03c3d82
--- /dev/null
+++ b/Source/mesquite/categ/lib/MCategoricalAdjustable.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**A class for an array of  categorical character states for many characters, at each of the taxa  or nodes.*/
+public class MCategoricalAdjustable extends MCategoricalDistribution implements MAdjustableDistribution {
+	int numTaxa=0;
+	int numChars=0;
+	private long[][] states;
+	String annotation;
+	public MCategoricalAdjustable (Taxa taxa, int numChars, int numTaxa) {
+		super(taxa);
+		this.numTaxa=numTaxa;
+		this.numChars=numChars;
+		states = new long[numChars][numTaxa];
+	}
+	public MCategoricalAdjustable (Taxa taxa) {
+		super(taxa);
+		deassignStates();
+	}
+	public MCategoricalAdjustable () {
+		super(null);
+	}
+	public void setAnnotation(String s, boolean notify){
+		annotation = s;
+	}
+	public String getAnnotation(){
+		return annotation;
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**sets the parent CharacterData from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd){
+		data = cd;
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	public void setSize(int numChars, int numTaxa) {
+		if (numChars!= this.numChars || numTaxa !=this.numTaxa) {
+			this.numTaxa=numTaxa;
+			this.numChars=numChars;
+			states = new long[numChars][numTaxa];
+		}
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**assign missing data (unassigned) to all characters and nodes */
+	public void deassignStates(){
+		for (int j=0; j<numChars; j++)
+			for (int i=0; i<numTaxa; i++)
+				states[j][i]=CategoricalState.unassigned;
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**returns state set of character ic at node */
+	public long getState (int ic, int N) {
+		if (checkIllegalNode(N, 106))
+			return CategoricalState.unassigned;
+		return CategoricalState.dataBitsMask & states[ic][N];
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**set state set of character ic at node to d */
+	public void setState (int ic, int N, long d) {
+		if (checkIllegalNode(N, 107))
+			return;
+		states[ic][N] = d;
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**sets the character state of character ic and taxon it to that in the passed CharacterState*/
+   	public void setCharacterState(CharacterState s, int ic, int it){
+   		if (s instanceof CategoricalState){
+			if (checkIllegalNode(it, 907))
+				return;
+   			states[ic][it] = ((CategoricalState)s).getValue();
+   		}
+   	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+   	/** trades the states of character ic between taxa it and it2.  Used for reshuffling.*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) {
+		if (checkIllegalNode(it, 9123) && ic <states.length)
+			return;
+		long temp = states[ic][it];
+		states[ic][it] =  states[ic][it2];
+		states[ic][it2] = temp;
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**obtain states of character ic from passed CharacterDistribution object */
+	public void transferFrom(int ic, CharacterDistribution s) {
+		if (s instanceof CategoricalDistribution)
+			for (int j=0; j<numTaxa; j++)
+				states[ic][j]=((CategoricalDistribution)s).getState(j);
+	}
+	/*..........................................  MCategoricalAdjustable  ..................................................*/
+	/**return CharacterDistribution object for character ic */
+	public CharacterDistribution getCharacterDistribution (int ic){
+		CategoricalAdjustable soc = new CategoricalAdjustable(getTaxa(), numTaxa);
+		soc.setStates(states[ic]);
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(ic);
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	/*..........................................MCategoricalAdjustable................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		CategoricalData data = new CategoricalData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getAnnotation()!=null)
+			data.setAnnotation(getAnnotation(), false);
+		return data;
+	}
+	public int getNumTaxa(){
+		return numTaxa;
+	}
+	public int getNumChars(){
+		return numChars;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MCategoricalDistribution.java b/Source/mesquite/categ/lib/MCategoricalDistribution.java
new file mode 100644
index 0000000..150849c
--- /dev/null
+++ b/Source/mesquite/categ/lib/MCategoricalDistribution.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**A class for an array of  categorical character states for many characters, at each of the taxa  or nodes.*/
+public abstract class MCategoricalDistribution extends MCategoricalStates implements MCharactersDistribution {
+	public MCategoricalDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	
+	
+	/*..........................................MCategoricalDistribution................*/
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		return new MCategoricalAdjustable(getTaxa(), getNumChars(), getNumTaxa());
+	}
+	/*..........................................MCategoricalDistribution................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		CategoricalData data = new CategoricalData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (this instanceof Annotatable && ((Annotatable)this).getAnnotation()!=null)
+			data.setAnnotation(((Annotatable)this).getAnnotation(), false);
+		else if (getParentData()!=null && getParentData().getAnnotation()!=null)
+			data.setAnnotation(getParentData().getAnnotation(), false);
+		return data;
+	}
+	/*..........................................MCategoricalDistribution................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MCategoricalHistory.class)) 
+			soc = new MCategoricalHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MCategoricalHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+	/**returns raw state set of character ic in taxon */
+	public long getStateRaw (int ic, int it){
+		return getState(ic, it);
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MCategoricalEmbedded.java b/Source/mesquite/categ/lib/MCategoricalEmbedded.java
new file mode 100644
index 0000000..17ce26c
--- /dev/null
+++ b/Source/mesquite/categ/lib/MCategoricalEmbedded.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**A class for an array of  categorical character states for many characters, at each of the taxa  or nodes.*/
+public class MCategoricalEmbedded extends MCategoricalDistribution {
+	public MCategoricalEmbedded (CharacterData data) {
+		super(data.getTaxa());
+		this.data = data;
+	}
+	/*..........................................  MCategoricalEmbedded  ..................................................*/
+	/**returns state set of character ic in taxon */
+	public long getState (int ic, int it){
+		return CategoricalState.dataBitsMask &((CategoricalData)data).getState(ic, it);
+	}
+	/**returns raw state set of character ic in taxon */
+	public long getStateRaw (int ic, int it){
+		return ((CategoricalData)data).getStateRaw(ic, it);
+	}
+	/**return CharacterDistribution object for character ic */
+	public CharacterDistribution getCharacterDistribution (int ic){
+		return data.getCharacterDistribution(ic);
+	}
+	public int getNumTaxa(){
+		return data.getNumTaxa();
+	}
+	public int getNumChars(){
+		return data.getNumChars();
+	}
+	public String getName(){
+		return data.getName();
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MCategoricalHistory.java b/Source/mesquite/categ/lib/MCategoricalHistory.java
new file mode 100644
index 0000000..334ff67
--- /dev/null
+++ b/Source/mesquite/categ/lib/MCategoricalHistory.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**DOCUMENT*/
+public class MCategoricalHistory extends MCategoricalAdjustable implements MCharactersHistory  {
+	int numNodes;
+	public MCategoricalHistory(Taxa taxa, int numChars, int numNodes) {
+		super(taxa, numChars,  numNodes);
+		this.numNodes = numNodes;
+	}
+	public int getNumNodes(){
+		return numNodes;
+	}
+	/*..........................................  MCategoricalHistory  ..................................................*/
+	/**return CharacterHistory object for character ic */
+	/** extract the states of character ic and return as CharacterHistory*/
+	public  CharacterHistory getCharacterHistory (int ic){
+		CategoricalHistory cH = new CategoricalHistory(getTaxa(), getNumNodes());
+		if (frequenciesExist()){
+			cH.setNumFreqCategories(getNumFreqCateg());
+		}
+		if (extraFrequenciesExist()){
+			cH.setNumExtraFreqCategories(getNumExtraFreqCateg());
+		}
+		for (int j=0; j<getNumNodes(); j++){
+			cH.setState(j, getState(ic, j)); 
+			if (frequenciesExist()){
+				for (int categ = 0; categ< getNumFreqCateg(); categ++)
+					cH.setFrequency(j, categ, getFrequency(ic, j, categ));
+			}
+			if (extraFrequenciesExist()){
+				for (int categ = 0; categ< getNumExtraFreqCateg(); categ++)
+					cH.setExtraFrequency(j, categ, getExtraFrequency(ic, j, categ));
+			}
+		}
+		return cH;
+	}
+	
+	/*..........................................  MCategoricalHistory  ..................................................*/
+	/**obtain states of character ic from passed CharacterHistory object */
+	public void transferFrom(int ic, CharacterHistory s) {
+		if (s instanceof CategoricalHistory) {
+			CategoricalHistory cat = (CategoricalHistory)s;
+			for (int j=0; j<numNodes; j++) {
+				setState(ic, j, cat.getState(j));
+				if (cat.frequenciesExist()) {
+					setFrequencies(ic, j, cat.getFrequencies(j));
+				}
+				if (cat.extraFrequenciesExist()) {
+					setExtraFrequencies(ic, j, cat.getExtraFrequencies(j));
+				}
+			}
+		}
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MCategoricalStates.java b/Source/mesquite/categ/lib/MCategoricalStates.java
new file mode 100644
index 0000000..0698c14
--- /dev/null
+++ b/Source/mesquite/categ/lib/MCategoricalStates.java
@@ -0,0 +1,252 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**A class for an array of  categorical character states for many characters, at each of the taxa  or nodes.*/
+public abstract class MCategoricalStates extends MCharactersStates {
+	protected double[][][] frequencies; //[node][state][character]
+	protected double[][][] extraFrequencies; //[node][extraFreq][character]
+	
+	public MCategoricalStates (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................  MCategoricalStates  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return CategoricalState.class;
+	}
+	
+	/*..........................................  MCategoricalStates  ..................................................*
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return CategoricalData.class;
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** return if frequencies exist for states at each node.*/
+	public boolean frequenciesExist(){
+		return (frequencies !=null);
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** return if frequencies exist for states at each node.*/
+	public boolean extraFrequenciesExist(){
+		return (extraFrequencies !=null);
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** Copy frequency information from first to second CategoricalStates.*/
+	public static void copyFrequencies(CategoricalStates source, CategoricalStates sink) {
+		if (source!=null && sink!=null && source.frequenciesExist()) {
+			for (int i=0; i<source.getNumNodes() && i<sink.getNumNodes(); i++) {
+				sink.setFrequencies(i, source.getFrequencies(i));
+			}
+		}
+	}
+	
+	private void prepareFrequencyStorage(int node, int numCategories){
+		if (frequencies == null) {
+			frequencies = new double[getNumNodes()][][];
+			frequencies[node] = new double[numCategories][getNumChars()];
+		}
+		else if (frequencies[node]== null || frequencies[node].length != numCategories || (numCategories != 0 && (frequencies[node].length<=0 || frequencies[node][0].length != getNumChars()))) {
+			frequencies[node] = new double[numCategories][getNumChars()];
+		}
+	}
+	
+	protected int getNumFreqCateg(){
+		if (frequencies == null) {
+			return 0;
+		}
+		int max = 0;
+		for (int i= 0; i<frequencies.length; i++){
+			if (frequencies[i] !=null && frequencies[i].length > max)
+				max = frequencies[i].length;
+		}
+		return max;
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** set freqency information*/
+	public void setFrequencies(int node, double[][] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				for (int ic=0; ic<getNumChars(); ic++)
+					frequencies[node][i][ic] = freqs[i][ic];
+			}
+		}
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** set freqency information*/
+	public void setFrequencies(int ic, int node, double[] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				frequencies[node][i][ic] = freqs[i];
+			}
+		}
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** get freqency information at a particular node*/
+	public double[][] getFrequencies(int node) {
+		if (checkIllegalNode(node, 1))
+			return null;
+		if (frequencies != null)
+			return frequencies[node];
+		return null;
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** get freqency of particular category at a particular node*/
+	public double getFrequency(int ic, int node, int category) {
+		if (checkIllegalNode(node, 2))
+			return 0;
+		if (frequencies == null || frequencies[node]== null  || category >= frequencies[node].length || frequencies[node][category]== null)
+			return MesquiteDouble.unassigned;
+		else
+			return frequencies[node][category][ic];
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** dispose frequency information (frees memory). */
+	public void disposeFrequencies() {
+		frequencies = null;
+	}
+
+	
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** Copy extra frequency information from first to second CategoricalStates.*/
+	public static void copyExtraFrequencies(CategoricalStates source, CategoricalStates sink) {
+		if (source!=null && sink!=null && source.extraFrequenciesExist()) {
+			for (int i=0; i<source.getNumNodes() && i<sink.getNumNodes(); i++) {
+				sink.setExtraFrequencies(i, source.getExtraFrequencies(i));
+			}
+		}
+	}
+	
+	private void prepareExtraFrequencyStorage(int node, int numCategories){
+		if (extraFrequencies == null) {
+			extraFrequencies = new double[getNumNodes()][][];
+			extraFrequencies[node] = new double[numCategories][getNumChars()];
+		}
+		else if (extraFrequencies[node]== null || extraFrequencies[node].length != numCategories || (numCategories != 0 && (extraFrequencies[node].length<=0 || extraFrequencies[node][0].length != getNumChars()))) {
+			extraFrequencies[node] = new double[numCategories][getNumChars()];
+		}
+	}
+	
+	protected int getNumExtraFreqCateg(){
+		if (extraFrequencies == null) {
+			return 0;
+		}
+		int max = 0;
+		for (int i= 0; i<extraFrequencies.length; i++){
+			if (extraFrequencies[i] !=null && extraFrequencies[i].length > max)
+				max = extraFrequencies[i].length;
+		}
+		return max;
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** set extra freqency information*/
+	public void setExtraFrequencies(int node, double[][] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareExtraFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				for (int ic=0; ic<getNumChars(); ic++)
+					extraFrequencies[node][i][ic] = freqs[i][ic];
+			}
+		}
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** set extra freqency information*/
+	public void setExtraFrequencies(int ic, int node, double[] freqs) {
+		if (checkIllegalNode(node, 0))
+			return;
+		if (freqs!=null) {
+			prepareExtraFrequencyStorage(node, freqs.length);
+			for (int i=0; i<freqs.length; i++) {
+				extraFrequencies[node][i][ic] = freqs[i];
+			}
+		}
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** get extra freqency information at a particular node*/
+	public double[][] getExtraFrequencies(int node) {
+		if (checkIllegalNode(node, 1))
+			return null;
+		if (extraFrequencies != null)
+			return extraFrequencies[node];
+		return null;
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** get extra freqency of particular category at a particular node*/
+	public double getExtraFrequency(int ic, int node, int category) {
+		if (checkIllegalNode(node, 2))
+			return 0;
+		if (extraFrequencies == null || extraFrequencies[node]== null  || category >= extraFrequencies[node].length || extraFrequencies[node][category]== null)
+			return MesquiteDouble.unassigned;
+		else
+			return extraFrequencies[node][category][ic];
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** dispose extra frequency information (frees memory). */
+	public void disposeExtraFrequencies() {
+		extraFrequencies = null;
+	}
+/*..........................................  MCategoricalStates  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return CategoricalData.DATATYPENAME;
+	}
+	/*..........................................  MCategoricalStates  ..................................................*/
+	/**returns state set of character ic in taxon */
+	public abstract long getState (int ic, int it);
+
+	/*..........................................MCategoricalStates................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		if (cs !=null && cs instanceof CategoricalState) {
+			((CategoricalState)cs).setValue(getState(ic, it));
+			return cs;
+		}
+		return new CategoricalState(getState(ic, it)); 
+	}
+	/*..........................................MCategoricalStates................*/
+	/** get CharacterState at node N*/
+	public CategoricalState getCategoricalState (CategoricalState cs, int ic, int it){  
+		if (cs !=null) {
+			cs.setValue(getState(ic, it));
+			return cs;
+		}
+		return new CategoricalState(getState(ic, it)); 
+	}
+	/*..........................................  MCategoricalStates  ...................................................*/
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int it=0; it< getNumNodes(); it++)
+			for (int ic=0; ic< getNumChars(); ic++) 
+				s |= getState(ic, it);
+		
+		return CategoricalState.dataBitsMask & s;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MDNAAdjustable.java b/Source/mesquite/categ/lib/MDNAAdjustable.java
new file mode 100644
index 0000000..c84c20c
--- /dev/null
+++ b/Source/mesquite/categ/lib/MDNAAdjustable.java
@@ -0,0 +1,108 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class MDNAAdjustable extends MCategoricalAdjustable {
+	public MDNAAdjustable (Taxa taxa, int numChars, int numTaxa) {
+		super(taxa, numChars, numTaxa);
+	}
+	public MDNAAdjustable (Taxa taxa) {
+		super(taxa);
+	}
+	public MDNAAdjustable () {
+		super(null);
+	}
+	public CharacterDistribution getCharacterDistribution (int ic){
+		DNACharacterAdjustable soc = new DNACharacterAdjustable(getTaxa(), numTaxa);
+		for (int it = 0; it<numTaxa; it++)
+			soc.setState( it, getState(ic, it));
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(ic);
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	/*..........................................  MDNAAdjustable  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return DNAState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return DNAData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return DNAData.DATATYPENAME;
+	}
+	/*..........................................MDNAAdjustable................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		if (cs !=null && cs instanceof DNAState) {
+			((DNAState)cs).setValue(getState(ic, it));
+			return cs;
+		}
+		return new DNAState(getState(ic, it)); 
+	}
+	/*..........................................MDNAAdjustable................*/
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		return new MDNAAdjustable(getTaxa(), getNumChars(), getNumTaxa());
+	}
+	/*..........................................MDNAAdjustable................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		DNAData data = new DNAData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getAnnotation()!=null)
+			data.setAnnotation(getAnnotation(), false);
+		return data;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MDNAHistory.class)) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MDNAEmbedded.java b/Source/mesquite/categ/lib/MDNAEmbedded.java
new file mode 100644
index 0000000..340ac9e
--- /dev/null
+++ b/Source/mesquite/categ/lib/MDNAEmbedded.java
@@ -0,0 +1,91 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class MDNAEmbedded extends MCategoricalEmbedded {
+	public MDNAEmbedded (CharacterData data) {
+		super(data);
+	}
+	/*..........................................  MDNAEmbedded  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return DNAState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return DNAData.class;
+	}
+	/*..........................................  MDNAEmbedded  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return DNAData.DATATYPENAME;
+	}
+	/*..........................................MDNAEmbedded................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		if (cs !=null && cs instanceof DNAState) {
+			((DNAState)cs).setValue(getState(ic, it));
+			return cs;
+		}
+		return new DNAState(getState(ic, it)); 
+	}
+	/*..........................................MDNAEmbedded................*/
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		return new MDNAAdjustable(getTaxa(), getNumChars(), getNumTaxa());
+	}
+	/*..........................................MDNAEmbedded................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		DNAData data = new DNAData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getParentData()!=null && getParentData().getAnnotation()!=null)
+			data.setAnnotation(getParentData().getAnnotation(), false);
+		return data;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i< 4; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MDNAHistory.class)) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MDNAHistory.java b/Source/mesquite/categ/lib/MDNAHistory.java
new file mode 100644
index 0000000..426e3fa
--- /dev/null
+++ b/Source/mesquite/categ/lib/MDNAHistory.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**DOCUMENT*/
+public class MDNAHistory extends MCategoricalHistory  {
+	public MDNAHistory(Taxa taxa, int numChars, int numNodes) {
+		super(taxa, numChars,  numNodes);
+	}
+	/*..........................................  MDNAHistory  ..................................................*/
+	/**return CharacterHistory object for character ic */
+	/** extract the states of character ic and return as CharacterHistory*/
+	public  CharacterHistory getCharacterHistory (int ic){
+		CategoricalHistory cH = new DNACharacterHistory(getTaxa(), getNumNodes());
+		if (frequenciesExist()){
+			cH.setNumFreqCategories(getNumFreqCateg());
+		}
+		if (extraFrequenciesExist()){
+			cH.setNumExtraFreqCategories(getNumExtraFreqCateg());
+		}
+		for (int j=0; j<getNumNodes(); j++){
+			cH.setState(j, getState(ic, j)); 
+			if (frequenciesExist()){
+				for (int categ = 0; categ< getNumFreqCateg(); categ++)
+					cH.setFrequency(j, categ, getFrequency(ic, j, categ));
+			}
+			if (extraFrequenciesExist()){
+				for (int categ = 0; categ< getNumExtraFreqCateg(); categ++)
+					cH.setExtraFrequency(j, categ, getExtraFrequency(ic, j, categ));
+			}
+		}
+		return cH;
+	}
+	
+	/*..........................................    ..................................................*/
+	/**return CharacterDistribution object for character ic */
+	public CharacterDistribution getCharacterDistribution (int ic){
+		DNACharacterAdjustable soc = new DNACharacterAdjustable(getTaxa(), numTaxa);
+		for (int it = 0; it<numTaxa; it++)
+			soc.setState(it, getState(ic, it));
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(ic);
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	/*..........................................................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		DNAData data = new DNAData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getAnnotation()!=null)
+			data.setAnnotation(getAnnotation(), false);
+		return data;
+	}
+	/*..........................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MDNAHistory.class)) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MDNAHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MProteinAdjustable.java b/Source/mesquite/categ/lib/MProteinAdjustable.java
new file mode 100644
index 0000000..3eaff3b
--- /dev/null
+++ b/Source/mesquite/categ/lib/MProteinAdjustable.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class MProteinAdjustable extends MCategoricalAdjustable {
+	public MProteinAdjustable (Taxa taxa, int numChars, int numTaxa) {
+		super(taxa, numChars, numTaxa);
+	}
+	public MProteinAdjustable (Taxa taxa) {
+		super(taxa);
+	}
+	public MProteinAdjustable () {
+		super(null);
+	}
+	public CharacterDistribution getCharacterDistribution (int ic){
+		ProteinAdjustable soc = new ProteinAdjustable(getTaxa(), numTaxa);
+		for (int it = 0; it<numTaxa; it++)
+			soc.setState( it, getState(ic, it));
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(ic);
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	/*..........................................  MProteinAdjustable  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ProteinState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ProteinData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/*..........................................MProteinAdjustable................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		if (cs !=null && cs instanceof ProteinState) {
+			((ProteinState)cs).setValue(getState(ic, it));
+			return cs;
+		}
+		return new ProteinState(getState(ic, it)); 
+	}
+	/*..........................................MProteinAdjustable................*/
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		return new MProteinAdjustable(getTaxa(), getNumChars(), getNumTaxa());
+	}
+	/*..........................................MProteinAdjustable................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		ProteinData data = new ProteinData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getAnnotation()!=null)
+			data.setAnnotation(getAnnotation(), false);
+		return data;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i<= ProteinState.maxProteinState; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MProteinHistory.class)) 
+			soc = new MProteinHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MProteinHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MProteinEmbedded.java b/Source/mesquite/categ/lib/MProteinEmbedded.java
new file mode 100644
index 0000000..4d276d9
--- /dev/null
+++ b/Source/mesquite/categ/lib/MProteinEmbedded.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class MProteinEmbedded extends MCategoricalEmbedded {
+	public MProteinEmbedded (CharacterData data) {
+		super(data);
+	}
+	/*..........................................  MProteinEmbedded  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ProteinState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ProteinData.class;
+	}
+	/*..........................................  MProteinEmbedded  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/*..........................................MProteinEmbedded................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		if (cs !=null && cs instanceof ProteinState) {
+			((ProteinState)cs).setValue(getState(ic, it));
+			return cs;
+		}
+		return new ProteinState(getState(ic, it)); 
+	}
+	/*..........................................MProteinEmbedded................*/
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		return new MProteinAdjustable(getTaxa(), getNumChars(), getNumTaxa());
+	}
+	/*..........................................MProteinEmbedded................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		ProteinData data = new ProteinData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getParentData()!=null && getParentData().getAnnotation()!=null)
+			data.setAnnotation(getParentData().getAnnotation(), false);
+		return data;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i<= ProteinState.maxProteinState; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MProteinHistory.java b/Source/mesquite/categ/lib/MProteinHistory.java
new file mode 100644
index 0000000..d77b209
--- /dev/null
+++ b/Source/mesquite/categ/lib/MProteinHistory.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**DOCUMENT*/
+public class MProteinHistory extends MCategoricalHistory  {
+	public MProteinHistory(Taxa taxa, int numChars, int numNodes) {
+		super(taxa, numChars,  numNodes);
+	}
+	/*..........................................  MCategoricalHistory  ..................................................*/
+	/**return CharacterHistory object for character ic */
+	/** extract the states of character ic and return as CharacterHistory*/
+	public  CharacterHistory getCharacterHistory (int ic){
+		CategoricalHistory cH = new ProteinCharacterHistory(getTaxa(), getNumNodes());
+		if (frequenciesExist()){
+			cH.setNumFreqCategories(getNumFreqCateg());
+		}
+		if (extraFrequenciesExist()){
+			cH.setNumExtraFreqCategories(getNumExtraFreqCateg());
+		}
+		for (int j=0; j<getNumNodes(); j++){
+			cH.setState(j, getState(ic, j)); 
+			if (frequenciesExist()){
+				for (int categ = 0; categ< getNumFreqCateg(); categ++)
+					cH.setFrequency(j, categ, getFrequency(ic, j, categ));
+			}
+			if (extraFrequenciesExist()){
+				for (int categ = 0; categ< getNumExtraFreqCateg(); categ++)
+					cH.setExtraFrequency(j, categ, getExtraFrequency(ic, j, categ));
+			}
+		}
+		return cH;
+	}
+	
+	/*..........................................    ..................................................*/
+	/**return CharacterDistribution object for character ic */
+	public CharacterDistribution getCharacterDistribution (int ic){
+		ProteinAdjustable soc = new ProteinAdjustable(getTaxa(), numTaxa);
+		for (int it = 0; it<numTaxa; it++)
+			soc.setState( it, getState(ic, it));
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(ic);
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	/*..........................................................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		CategoricalData data = new ProteinData(manager, getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this);
+		if (getAnnotation()!=null)
+			data.setAnnotation(getAnnotation(), false);
+		return data;
+	}
+	/*..........................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MProteinHistory.class)) 
+			soc = new MProteinHistory(tree.getTaxa(), getNumChars(), numNodes); 
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MProteinHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/MesquiteSequence.java b/Source/mesquite/categ/lib/MesquiteSequence.java
new file mode 100644
index 0000000..b5c151a
--- /dev/null
+++ b/Source/mesquite/categ/lib/MesquiteSequence.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public interface MesquiteSequence {
+	public String getSequence();
+	public boolean isNucleotides();
+	public String getName();
+	public int getLength();
+	public int getQualityOfBase(int i);
+	public Color getStandardColorOfBase(int i);
+	public Color getQualityColorOfBase(int i);
+	public Color getHighlightColor(int sequenceBase, int contigBase);
+	public boolean sourceReadIsLowerQuality(int i, int smallConflictThreshold, MesquiteBoolean higherReadConflicts, int largeConflictThreshold, MesquiteBoolean muchHigherReadConflicts);
+}
+
+
diff --git a/Source/mesquite/categ/lib/MolecDataEditorInit.java b/Source/mesquite/categ/lib/MolecDataEditorInit.java
new file mode 100644
index 0000000..2073d68
--- /dev/null
+++ b/Source/mesquite/categ/lib/MolecDataEditorInit.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class MolecDataEditorInit extends DataWindowAssistantI  {
+
+   	 public Class getDutyClass() {
+   	 	return MolecDataEditorInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Molecular Data Editor Init";
+   	}
+   	
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MolecularData.java b/Source/mesquite/categ/lib/MolecularData.java
new file mode 100644
index 0000000..89a80aa
--- /dev/null
+++ b/Source/mesquite/categ/lib/MolecularData.java
@@ -0,0 +1,561 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.categ.lib;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterModel;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.CharacterStates;
+import mesquite.lib.characters.DefaultReference;
+import mesquite.lib.characters.ModelSet;
+import mesquite.lib.duties.*;
+import mesquite.molec.lib.*;
+
+import java.util.*;
+
+/* ======================================================================== */
+/** A subclass of CharacterData for molecular data */
+public class MolecularData extends CategoricalData {
+	public static String DATATYPENAME="Molecular Data";
+	GenCodeModelSet genCodeModelSet =null;
+	public static final NameReference reversedRef = NameReference.getNameReference("reversed"); //long: tInfo, data(ch); MesquiteInteger: data(cells)
+	public static final NameReference genBankNumberRef = NameReference.getNameReference("genBankNumber");//String: tInfo
+
+	/*vectors, one for each taxon, of 3D Points indicating inversions in sequence
+	x = site marking left boundary of inverted region
+	y = site marking right boundary of inverted region
+	z = not yet used
+	 */
+	protected Vector[] inversions;  
+	boolean trackInversions = false;
+
+	public MolecularData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars, taxa);
+		saveChangeHistory = false;//turned off for now
+		inventUniqueIDs = false; //turned off for now
+		rememberDefaultOrder = false;
+		//	nullifyBooleanArrays();
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixMolecSmall.gif";
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		if (StringUtil.blank(s))
+			return null;
+		String list = "";
+		String fc =""; //to receive the direct command
+		int numFound = 0;
+		for (int ic=0; ic< getNumChars(); ic++){
+			String name = getCharacterName(ic);
+			if (name != null && StringUtil.foundIgnoreCase(name, s)){
+				list += "<li>Site " + (ic+1) + ": <strong>" + StringUtil.protectForXML(name) + "</strong>. <a href=\"selectCharacter:" + ic + " " + getID()  + "\">Touch character</a></li>";
+				numFound++;
+				fc = "selectCharacter:" + ic+ " " + getID();
+			}
+		}
+
+		if (commandResult != null && numFound == 1)
+			commandResult.setValue(fc);
+		if (StringUtil.blank(list))
+			return list;
+		return "<h2>Characters of matrix <strong>" + StringUtil.protectForXML(getName()) + "</strong></h2><ul>" + list + "</ul>";
+	}
+	public void setInventUniqueIDs(boolean invent){
+		//inventUniqueIDs = invent; to prevent this from turning on for molecular
+	}
+	public boolean getInventUniqueIDs(){
+		return inventUniqueIDs;
+	}
+	public String getUniqueID(int ic){
+		return null;
+	}
+	public void setTrackInversions(boolean dt){
+		trackInversions = dt;
+	}
+	public boolean getTrackInversions(){
+		return trackInversions;
+	}
+	/** returns default column width in editors.  Default is 16.*/
+	public int getNarrowDefaultColumnWidth() {
+		return 12;
+	}
+
+	/*..........................................    ..................................................*/
+	public CharacterState makeCharacterState(){
+		return new MolecularState();
+	}
+	public Vector getInversions(int it){
+		if (inversions == null || it >= inversions.length)
+			return null;
+		return inversions[it];
+	}
+	//true if inverted
+	public boolean isReverseDirectionAtSite(int ic, int it){
+		if (inversions == null || it >= inversions.length)
+			return false;
+		boolean inverted = false;
+		//look for inversions containing this site, starting at last one
+		int siteEquiv = ic;
+		for (int ip = inversions[it].size()-1; ip>=0; ip--){
+			Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+			if (siteEquiv >= p.x && siteEquiv <= p.y){ //contains this site
+				inverted = !inverted;
+				siteEquiv = p.y - (siteEquiv-p.x);
+			}
+		}
+		return inverted;
+	}
+	//returns original (pre-inversion) position of current site ic, which may be within an inversion
+	public int findOriginalPositionOfInvertedSite(int ic, int it){
+		if (inversions == null || it >= inversions.length)
+			return ic;
+		//look for inversions containing this site, starting at last one
+		int siteEquiv = ic;
+		for (int ip = inversions[it].size()-1; ip>=0; ip--){
+			Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+			if (siteEquiv >= p.x && siteEquiv <= p.y){ //contains this site
+				siteEquiv = p.y - (siteEquiv-p.x);
+			}
+		}
+		return siteEquiv;
+	}
+	//returns current (post-inversion) position of an original site ic
+	public int findInvertedPositionOfOriginalSite(int ic, int it){
+		if (inversions == null || it >= inversions.length)
+			return ic;
+		//look for inversions containing this site, starting at last one
+		MesquiteMessage.warnProgrammer("findInvertedPositionOfOriginalSite THIS SHOULD NOT APPEAR");
+		int siteEquiv = ic;
+		for (int ip = 0; ip< inversions[it].size(); ip++){
+			Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+			if (siteEquiv >= p.x && siteEquiv <= p.y){ //contains this site
+				siteEquiv = p.y - (siteEquiv-p.x);
+			}
+		}
+		return siteEquiv;
+	}
+	/*-----------------------------------------------------------*/
+	/**Adds num characters after position "starting".  If "starting" = -1, then inserts at start.  If "starting" >
+	number of characters, adds to end.  Any linked CharacterDatas are
+	to be adjusted separately.  Returns true iff successful.*/
+	public boolean addParts(int starting, int num){
+		//adding characters; deal with inversions
+		if (inversions != null){
+			for (int it = 0; it<inversions.length && it< getNumTaxa(); it++){
+				for (int ip = 0; ip< inversions[it].size(); ip++){
+					Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+					if (starting < p.x) //added before x; need to push to right
+						p.x += num;
+					if (starting < p.y)//added before y; need to push to right
+						p.y += num;
+				}
+			}
+		}
+		return super.addParts(starting, num);
+	}
+	/*-----------------------------------------------------------*/
+	/** deletes num characters from (and including) position "starting"; returns true iff successful.  Should be overridden by particular subclasses, but this called via super so it can clean up.*/
+	public boolean deleteParts(int starting, int num){
+		//deleting characters; deal with inversions
+
+		if (inversions != null){
+			for (int it = 0; it<inversions.length && it< getNumTaxa(); it++){
+				for (int ip = 0; ip< inversions[it].size(); ip++){
+					Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+					if (starting <= p.x){//deletion will affect point
+						if (p.x < starting+num) //point is being deleted also
+							p.x = starting;  //snap left edge of flip to right margin of deleted area
+						else
+							p.x -= num; //push to left
+					}
+					if (starting <= p.y){//deletion will affect point
+						if (p.y < starting+num) //point is being deleted also
+							p.y = starting-1;   //snap right edge of flip to left margin of deleted area-1
+						else
+							p.y -= num; //push to left
+					}
+				}
+			}
+		}
+
+		return super.deleteParts(starting, num);
+	}
+	private int newPosAfterMove(int orig, int starting, int num, int justAfter){
+		if (starting < justAfter){ //moving forward
+			if (orig > starting){
+				if (orig <= starting + num) //will be moved forward
+					orig = orig + (justAfter-starting) - num;
+				else if (orig < justAfter) //in chunk shifted left because of move
+					orig -= num;
+			}
+		}
+		else if (orig > justAfter){
+			if (orig < starting + num) //will be moved backward
+				orig = orig + (starting-justAfter);
+			else if (orig < starting)
+				orig+= num;
+		}
+		return orig;
+	}
+	/*-----------------------------------------------------------*/
+	/**Moves num characters from position "first" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		//moving characters; deal with inversions
+		if (inversions != null){
+			for (int it = 0; it<inversions.length && it< getNumTaxa(); it++){
+				for (int ip = 0; ip< inversions[it].size(); ip++){
+					Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+					p.x = newPosAfterMove(p.x, starting, num, justAfter);
+					p.y = newPosAfterMove(p.y, starting, num, justAfter);
+				}
+			}
+		}
+		return super.moveParts(starting, num, justAfter);
+	}
+	/*-----------------------------------------------------------*/
+	/**Swaps characters first and second.*/
+	public boolean swapParts(int first, int second){
+		//swapping characters; deal with inversions
+		if (inversions != null){
+			MesquiteMessage.warnProgrammer("Swapping characters and strand inversions not yet fully supported");
+		}
+		return super.swapParts(first, second);
+	}
+	/*.................................................................................................................*/
+	protected CharacterState moveOne(int i, int distance, int it, CharacterState cs,  MesquiteBoolean dataChanged){
+		//moving contents of cells; deal with inversions
+		if (inversions != null && it < inversions.length){
+			for (int ip = 0; ip< inversions[it].size(); ip++){
+				Mesquite3DIntPoint p = (Mesquite3DIntPoint)inversions[it].elementAt(ip);
+				if (p.x == i) //this point being moved
+					p.x += distance;
+				if (p.y == i) //sister point being moved
+					p.y += distance;
+			}
+		}
+		return super.moveOne(i, distance, it, cs, dataChanged);
+	}
+	/*-----------------------------------------------------------*/
+	/**Adds num taxa after position "starting"; returns true iff successful.  Assumes details already handled in subclasses, and numTaxa reset there.*/
+	public boolean addTaxa(int starting, int num){
+		//adding taxa; deal with inversions
+		if (inversions != null && num >0){
+			if (starting<0) 
+				starting = -1;
+			if (starting>inversions.length) 
+				starting = inversions.length-1;
+			int newNumParts = inversions.length+num;
+			Vector[] newValues = new Vector[newNumParts];
+			for (int i=0; i<= starting; i++) 
+				newValues[i] = inversions[i];
+			for (int i=0; i<num ; i++) 
+				newValues[starting + i + 1] = null;
+			for (int i=0; i<inversions.length-starting-1; i++)
+				newValues[i +starting+num+1] = inversions[starting + i+1];
+			inversions = newValues;
+		}
+		return super.addTaxa(starting, num);
+	}
+	/*-----------------------------------------------------------*/
+	/**Deletes num taxa from position "starting"; returns true iff successful.  Assumes details already handled in subclasses, and numTaxa reset there.*/
+	public boolean deleteTaxa(int starting, int num){
+		//deleting taxa; deal with inversions
+		if (inversions != null && num> 0){
+			if (num+starting>inversions.length)
+				num = inversions.length-starting;
+			int newNumParts = inversions.length-num;
+			Vector[] newValues = new Vector[newNumParts];
+			for (int i=0; i<starting; i++)
+				newValues[i] = inversions[i];
+			for (int i=starting+num; i<inversions.length; i++)
+				newValues[i-num ] = inversions[i];
+			inversions = newValues;
+		}
+		return super.deleteTaxa(starting, num);
+	}
+	/**moves num taxa from position "starting" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveTaxa(int starting, int num, int justAfter){
+		//moving taxa; deal with inversions
+		if (inversions != null && num>0 && starting >=0 && starting <= inversions.length){
+			Vector[] newValues = new Vector [inversions.length];
+
+			if (starting>justAfter){
+				int count =0;
+				for (int i=0; i<=justAfter; i++)
+					newValues[count++]=inversions[i];
+
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=inversions[i];
+				for (int i=justAfter+1; i<=starting-1; i++)
+					newValues[count++]=inversions[i];
+				for (int i=starting+num; i<inversions.length; i++)
+					newValues[count++]=inversions[i];
+			}
+			else {
+				int count =0;
+				for (int i=0; i<=starting-1; i++)
+					newValues[count++]=inversions[i];
+
+				for (int i=starting+num; i<=justAfter; i++)
+					newValues[count++]=inversions[i];
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=inversions[i];
+				for (int i=justAfter+1; i<inversions.length; i++)
+					newValues[count++]=inversions[i];
+			}
+			for (int i=0; i<inversions.length; i++)
+				inversions[i]=newValues[i];
+			inversions = newValues;
+		}
+		return super.moveTaxa(starting, num, justAfter);
+	}
+	/** trades the states of character ic and ic2 in taxon it.  Used for reversing sequences (for example).*/
+	protected void tradeStatesBetweenCharactersInternal(int ic, int ic2, int it, boolean adjustCellLinked, boolean adjustDirections){
+		//trading states; deal with inversions 
+		super.tradeStatesBetweenCharactersInternal(ic, ic2, it, adjustCellLinked, adjustDirections);
+		if (adjustDirections && trackInversions)
+			MesquiteMessage.warnProgrammer("tradeStatesBetweenCharactersInternal does not yet handle direction tracking!"); //deal with inversions
+	}
+
+	/* .......................................... DNAData .................................................. */
+	public boolean isReversed( int it) {
+		Associable tInfo = getTaxaInfo(false);
+		if (tInfo!=null) {
+			return tInfo.getAssociatedBit(reversedRef,it);
+		}
+		return false;
+	}
+	/* .......................................... MolecularData .................................................. */
+	public void setReversed( int it, boolean value) {
+		Associable tInfo = getTaxaInfo(false);
+		if (tInfo!=null) {
+			tInfo.setAssociatedBit(reversedRef, it, value);
+		}
+	}
+
+	/*..........................................  MolecularData  ..................................................*/
+	/**Reverses the associated bits for all characters. */
+	public void reverseAssociated(int icStart, int icEnd){
+		for (int ic=0; ic <= (icEnd-icStart)/2 && icStart+ic< icEnd-ic; ic++)
+			swapAssociated(icStart+ic, icEnd-ic);
+		//	int numChars = getNumChars();
+		//	for (int ic = 0; ic<numChars/2; ic++)
+		//		swapAssociated(ic, numChars-ic-1);
+	}
+	/*..........................................  MolecularData  ..................................................*/
+	/**Reverses the data from character icStart to icEnd in taxon it. */  
+	public void reverse(int icStart, int icEnd, int it, boolean reverseTerminalGaps, boolean adjustCellLinked){
+		//reversing; deal with inversions
+		if (trackInversions){
+			if (inversions == null){
+				inversions = new Vector[numTaxa];
+				for (int itt = 0; itt<numTaxa; itt++)
+					inversions[itt] = new Vector();
+			}
+			//Wayne: should see if there is a matching element and simply flip it!
+			inversions[it].addElement(new Mesquite3DIntPoint(icStart, icEnd, 0));
+		}
+		if ((icStart==0 && icEnd==getNumChars()-1) || (!anyApplicableBefore(icStart, it)&& !anyApplicableAfter(icEnd,it))) {
+			Associable tInfo = getTaxaInfo(true);
+			if (tInfo!=null) {
+				boolean prevValue = tInfo.getAssociatedBit(reversedRef,it);
+				tInfo.setAssociatedBit(reversedRef, it, !prevValue);
+			}
+		}
+		super.reverse(icStart, icEnd, it, reverseTerminalGaps, adjustCellLinked);
+	}
+	/*..........................................  MolecularData  ..................................................*/
+	/**Reverses the data from character icStart to icEnd in taxon it. NOTE: this version reverses character metadata (codon positions, etc.)*/  
+	public void reverse(int icStart, int icEnd, boolean adjustCellLinked){
+		for (int it= 0; it< getNumTaxa(); it++)
+			reverse(icStart, icEnd, it, true, adjustCellLinked);
+		int numChars = icEnd-icStart+1;
+		int halfWay = numChars/2;
+		for (int ic= 0; ic<halfWay; ic++)
+			swapCharacterMetadata(icStart+ic,icEnd-ic);
+		if (adjustCellLinked && linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				for (int ic= 0; ic<halfWay; ic++)
+					d.swapCharacterMetadata(icStart+ic,icEnd-ic);
+			}
+		}
+
+	}
+	/* ..........................................MolecularData................ */
+	/** returns the appropriate genetic code models to be assigned as default ones to characters
+	 *  that might be added immediately after character ic */
+	public GenCodeModel getDefaultGenCodeModel(int ic) {
+		GenCodeModel endGenCodeModel = null;
+		if (ic< getNumChars())  
+			endGenCodeModel = getGenCodeModel(ic+1);
+		GenCodeModel startGenCodeModel = null;
+		if (ic>=0)  
+			startGenCodeModel = getGenCodeModel(ic);
+		if (endGenCodeModel !=null && startGenCodeModel ==null)  //only the end one is non-null
+			return endGenCodeModel;
+		if (endGenCodeModel ==null && startGenCodeModel !=null)  //only the start one is non-null
+			return startGenCodeModel;
+		if (endGenCodeModel ==null && startGenCodeModel ==null)  //
+			return null;
+		if (startGenCodeModel.getGeneticCode().equals(startGenCodeModel.getGeneticCode()))  
+			return startGenCodeModel;  //same, at least in terms of code, assign first one
+		return startGenCodeModel;  // here they both exist but differ; should give warning?
+	}
+	/*..........................................    ..................................................*/
+	/** returns the genetic code model of character ic in taxon it*/
+	public GenCodeModel getGenCodeModel(int ic){
+		if (genCodeModelSet==null)
+			genCodeModelSet = (GenCodeModelSet)getCurrentSpecsSet(GenCodeModelSet.class);
+		if (genCodeModelSet != null && ic<genCodeModelSet.getNumberOfParts() && ic>=0)
+			return (GenCodeModel)genCodeModelSet.getModel(ic);
+		return null;
+	}
+	/*..........................................    ..................................................*/
+	/** returns the genetic code of character ic in taxon it*/
+	public GeneticCode getGeneticCode(int ic){
+		if (genCodeModelSet==null)
+			genCodeModelSet = (GenCodeModelSet)getCurrentSpecsSet(GenCodeModelSet.class);
+		if (genCodeModelSet != null && ic<genCodeModelSet.getNumberOfParts() && ic>=0) {
+			GenCodeModel genCodeModel=  (GenCodeModel)genCodeModelSet.getModel(ic);
+			if (genCodeModel != null)
+				return genCodeModel.getGeneticCode();
+		}
+		return null;
+	}
+	/* ..........................................  .................................................. *
+	public void assignGeneticCodeToTerminalChars(int whichTermChars){
+		if (whichTermChars<0)
+			assignGeneticCodeToCharsBasedOnAdjacent(0,-whichTermChars-1);
+		else
+			assignGeneticCodeToCharsBasedOnAdjacent(getNumChars()-whichTermChars-1, getNumChars()-1);
+	}
+	/* ..........................................  .................................................. *
+	public void assignGeneticCodeToCharsBasedOnAdjacent(int startChar, int endChar){
+		ModelSet modelSet = (ModelSet) getCurrentSpecsSet(GenCodeModelSet.class);
+		if (modelSet == null) 
+			return;
+		int existingChar = 0;
+		if (startChar<=0) {  //added to front
+			existingChar = endChar+1;
+			if (existingChar>=getNumChars())
+				return;
+		} else existingChar = startChar-1;
+
+		GenCodeModel genCodeModel = getGenCodeModel(existingChar);
+		if (genCodeModel!=null) { // the immediately adjacent character (the previous first character) has an assigned codon position
+				for (int ic=startChar; ic<getNumChars(); ic++) {
+					modelSet.setModel(genCodeModel, ic);
+				}
+			}
+
+		}
+	/* ..........................................  .................................................. */
+
+	public boolean stripRightTerminalGaps(boolean notify){
+		int ic = getNumChars();
+		for (ic = getNumChars()-1; ic>=0; ic--){
+			if (!entirelyInapplicable(ic))
+				break;
+		}
+		if (ic< getNumChars()) {
+			int ncic = getNumChars()-ic;
+			deleteCharacters(ic+1, ncic, notify);
+			deleteInLinked(ic+1, ncic, notify);
+			return true;
+		}
+		return false;
+	}
+	public boolean stripLeftTerminalGaps(boolean notify){
+		int ic = -1;
+		for (ic = 0; ic<getNumChars(); ic++){
+			if (!entirelyInapplicable(ic))
+				break;
+		}
+		if (ic>=0) {
+			deleteCharacters(0, ic, notify);
+			deleteInLinked(0, ic, notify);
+			return true;
+		}
+		return false;
+	}
+
+
+
+	public void collapseGapsInCellBlock(int it, int icStart, int icEnd, boolean notify) {
+		int lastFilled = icStart-1;
+		for (int ic = icStart; ic < getNumChars() && ic<=icEnd; ic++) {
+			if (!isInapplicable(ic, it)){
+				lastFilled++;
+				if (ic!=lastFilled)
+					tradeStatesBetweenCharacters(ic, lastFilled, it,true);
+			}
+		}
+	}
+	public void collapseGapsInCellBlockRight(int it, int icStart, int icEnd, boolean notify) {
+		int lastFilled = icEnd+1;
+		for (int ic = icEnd; ic >=0 && ic>= icStart; ic--) {
+			if (!isInapplicable(ic, it)){
+				lastFilled--;
+				if (ic!=lastFilled)
+					tradeStatesBetweenCharacters(ic, lastFilled, it,true);
+			}
+		}
+	}
+
+	public  StringBuffer getSequenceAsFasta(boolean includeGaps,boolean convertMultStateToMissing, int it) {
+		Taxa taxa = getTaxa();
+
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+		boolean isProtein = this instanceof ProteinData;
+
+		int counter = 1;
+		if (hasDataForTaxon(it)){
+			counter = 1;
+			outputBuffer.append(">");
+			outputBuffer.append(taxa.getTaxonName(it));
+			outputBuffer.append(StringUtil.lineEnding());
+			for (int ic = 0; ic<numChars; ic++) {
+				int currentSize = outputBuffer.length();
+				boolean wroteMoreThanOneSymbol = false;
+				if (isUnassigned(ic, it) || (convertMultStateToMissing && isProtein && isMultistateOrUncertainty(ic, it)))
+					outputBuffer.append(getUnassignedSymbol());
+				else if (includeGaps || (!isInapplicable(ic,it))) {
+					statesIntoStringBuffer(ic, it, outputBuffer, false);
+					wroteMoreThanOneSymbol = outputBuffer.length()-currentSize>1;
+					counter ++;
+					if ((counter % 50 == 1) && (counter > 1)) {    // modulo
+						outputBuffer.append(StringUtil.lineEnding());
+					}
+				}
+				if (wroteMoreThanOneSymbol) {
+					alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+					return null;
+				}
+
+			}
+			outputBuffer.append(StringUtil.lineEnding());
+		}
+		return outputBuffer;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/MolecularDataAlterer.java b/Source/mesquite/categ/lib/MolecularDataAlterer.java
new file mode 100644
index 0000000..9e79b88
--- /dev/null
+++ b/Source/mesquite/categ/lib/MolecularDataAlterer.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class MolecularDataAlterer extends DataAlterer  {
+   	 public Class getDutyClass() {
+   	 	return MolecularDataAlterer.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+
+}
+
+
diff --git a/Source/mesquite/categ/lib/MolecularDataUtil.java b/Source/mesquite/categ/lib/MolecularDataUtil.java
new file mode 100644
index 0000000..d28f50e
--- /dev/null
+++ b/Source/mesquite/categ/lib/MolecularDataUtil.java
@@ -0,0 +1,401 @@
+package mesquite.categ.lib;
+
+import java.awt.Rectangle;
+
+import mesquite.basic.ManageSetsBlock.ManageSetsBlock;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CodonPositionsSet;
+import mesquite.lib.duties.ElementManager;
+import mesquite.lists.lib.ListModule;
+import mesquite.align.lib.*;
+
+/** This is a utility class that provides static methods to do various jobs with molecular data  */
+
+public class MolecularDataUtil {
+
+	/*.................................................................................................................*
+	private boolean alignTouchedToDropped(int rowToAlign, int recipientRow){
+		MesquiteNumber score = new MesquiteNumber();
+		if (aligner==null) {
+			aligner = new PairwiseAligner(true,allowNewGaps.getValue(), subs,gapOpen.getValue(), gapExtend.getValue(), gapOpenTerminal.getValue(), gapExtendTerminal.getValue(), alphabetLength);
+			//aligner.setUseLowMem(true);
+		}
+		if (aligner!=null){
+			//aligner.setUseLowMem(data.getNumChars()>aligner.getCharThresholdForLowMemory());
+			originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars()-1,rowToAlign, rowToAlign);
+			aligner.setAllowNewInternalGaps(allowNewGaps.getValue());
+			long[][] aligned = aligner.alignSequences((MCategoricalDistribution)data.getMCharactersDistribution(), recipientRow, rowToAlign,MesquiteInteger.unassigned,MesquiteInteger.unassigned,true,score);
+			if (aligned==null) {
+				logln("Alignment failed!");
+				return false;
+			}
+			logln("Align " + (rowToAlign+1) + " onto " + (recipientRow+1));
+			long[] newAlignment = Long2DArray.extractRow(aligned,1);
+
+			int[] newGaps = aligner.getGapInsertionArray();
+			if (newGaps!=null)
+				alignUtil.insertNewGaps((MolecularData)data, newGaps);
+			Rectangle problem = alignUtil.forceAlignment((MolecularData)data, 0, data.getNumChars()-1, rowToAlign, rowToAlign, 1, aligned);
+
+			((CategoricalData)data).examineCheckSum(0, data.getNumChars()-1,rowToAlign, rowToAlign, "Bad checksum; alignment has inappropriately altered data!", warnCheckSum, originalCheckSum);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public static void pairwiseAlignMatrix(MesquiteModule module, MolecularData data, int referenceTaxon, Bits taxaToAdjust, int comparisonTaxon, boolean allowNewInternalGaps, boolean verbose) {
+		MesquiteNumber score = new MesquiteNumber();
+		AlignUtil alignUtil = new AlignUtil();
+		PairwiseAligner aligner = PairwiseAligner.getDefaultAligner(true,data);
+		aligner.setAllowNewInternalGaps(allowNewInternalGaps);
+		int numTaxa = data.getNumTaxa();
+		boolean defaultWarnCheckSum  =true;
+		MesquiteBoolean warnCheckSum = new MesquiteBoolean(defaultWarnCheckSum);
+		long originalCheckSum;
+		for (int it=0; it<=numTaxa; it++) {
+			if (taxaToAdjust.isBitOn(it) && it!=referenceTaxon) {
+				if (verbose) 
+					module.logln("Aligning taxon " + (it+1) + " to taxon " + (referenceTaxon+1));
+				originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars()-1,it, it);
+				long[][] aligned = aligner.alignSequences((MCategoricalDistribution)data.getMCharactersDistribution(), referenceTaxon, it,MesquiteInteger.unassigned,MesquiteInteger.unassigned,true,score);
+				int[] newGaps = aligner.getGapInsertionArray();
+				if (newGaps!=null){
+					alignUtil.insertNewGaps((MolecularData)data, newGaps, aligner.getPreSequenceTerminalFlaggedGap(), aligner.getPostSequenceTerminalFlaggedGap());
+					data.notifyListeners(module, new Notification(CharacterData.PARTS_ADDED, null, null));
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+				}
+				Rectangle problem = alignUtil.forceAlignment((MolecularData)data, 0, data.getNumChars()-1, it, it, 1, aligned);
+				if (problem!=null)
+					module.logln("problem with alignment: " + problem.toString());
+				((CategoricalData)data).examineCheckSum(0, data.getNumChars()-1,it, it, "Bad checksum; alignment has inappropriately altered data!", warnCheckSum, originalCheckSum);
+			}
+		}
+
+	}
+
+	/*.................................................................................................................*/
+	public static void pairwiseAlignMatrix(MesquiteModule module, MolecularData data, int referenceTaxon, Bits taxaToAdjust, int comparisonTaxon, boolean allowNewInternalGaps) {
+		pairwiseAlignMatrix(module, data, referenceTaxon,taxaToAdjust, comparisonTaxon, allowNewInternalGaps, false);
+	}
+
+	/*.................................................................................................................*/
+	public static void pairwiseAlignMatrix(MesquiteModule module, MolecularData data, int referenceTaxon, int itStart, int itEnd, boolean allowNewInternalGaps) {
+		MesquiteNumber score = new MesquiteNumber();
+		AlignUtil alignUtil = new AlignUtil();
+		PairwiseAligner aligner = PairwiseAligner.getDefaultAligner(true,data);
+		aligner.setAllowNewInternalGaps(allowNewInternalGaps);
+//		boolean defaultWarnCheckSum  =true;
+//		MesquiteBoolean warnCheckSum = new MesquiteBoolean(defaultWarnCheckSum);
+//		long originalCheckSum;
+//		originalCheckSum = ((CategoricalData)data).storeCheckSum(0, data.getNumChars()-1,itStart, itEnd);
+		for (int it=itStart; it<=itEnd; it++) {
+			if (it!=referenceTaxon) {
+				long[][] aligned = aligner.alignSequences((MCategoricalDistribution)data.getMCharactersDistribution(), referenceTaxon, it,MesquiteInteger.unassigned,MesquiteInteger.unassigned,true,score);
+				int[] newGaps = aligner.getGapInsertionArray();
+				if (newGaps!=null){
+					alignUtil.insertNewGaps((MolecularData)data, newGaps,  aligner.getPreSequenceTerminalFlaggedGap(), aligner.getPostSequenceTerminalFlaggedGap());
+					data.notifyListeners(module, new Notification(CharacterData.PARTS_ADDED, null, null));
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+				}
+				Rectangle problem = alignUtil.forceAlignment((MolecularData)data, 0, data.getNumChars()-1, it, it, 1, aligned);
+			}
+		}
+//		((CategoricalData)data).examineCheckSum(0, data.getNumChars()-1,itStart, itEnd, "Bad checksum; alignment has inappropriately altered data!", warnCheckSum, originalCheckSum);
+		
+
+	}
+	/*.................................................................................................................*/
+	public static void pairwiseAlignMatrix(MesquiteModule module, MolecularData data, int referenceTaxon, boolean allowNewInternalGaps) {
+		pairwiseAlignMatrix(module, data,referenceTaxon, 0, data.getNumTaxa()-1, allowNewInternalGaps);
+	}
+	/*.................................................................................................................*/
+	public static void shiftAlignTaxon(MolecularData data, int referenceTaxon, int taxonToAlign) {
+		pairwiseAlignMatrix(null, data, referenceTaxon, taxonToAlign, taxonToAlign, false);
+	}
+
+	/*.................................................................................................................*/
+	public static void setCodonPositions(DNAData data, CodonPositionsSet modelSet,  int position,  boolean calc, boolean notify){
+		if (modelSet==null)
+			return;
+		MesquiteNumber num = new MesquiteNumber();
+		num.setValue(position);
+		if (modelSet != null) {
+			for (int i=0; i<data.getNumChars(); i++) {
+				modelSet.setValue(i, num);
+				if (calc) {
+					num.setValue(num.getIntValue()+1);
+					if (num.getIntValue()>3)
+						num.setValue(1);
+				}
+			}
+
+
+		}
+	}
+	/*.................................................................................................................*/
+	public static int getMinimumStops(DNAData data, int it, CodonPositionsSet modelSet){
+		int minStops = -1;
+		for (int i = 1; i<=3; i++) {
+			setCodonPositions(data,modelSet, i,true,false);  //set them temporarily
+			int totNumStops = ((DNAData)data).getAminoAcidNumbers(it,ProteinData.TER);					 
+			if (minStops<0 || totNumStops<minStops) {
+				minStops = totNumStops;
+			}
+		}
+		return minStops;
+	}
+	/*.................................................................................................................*
+	public static int getShiftForMinimumStops(DNAData data, int it, CodonPositionsSet modelSet){
+		int minStops = -1;
+		for (int i = 1; i<=3; i++) {
+			setCodonPositions(data,modelSet, i,true,false);  //set them temporarily
+			int totNumStops = ((DNAData)data).getAminoAcidNumbers(it,ProteinData.TER);					 
+			if (minStops<0 || totNumStops<minStops) {
+				minStops = totNumStops;
+			}
+		}
+		return minStops;
+	}
+
+	/*.................................................................................................................*/
+	protected static double alignmentScoreRatioToRCScore(DNAData data, MesquiteModule module, int it1, int it2, boolean verbose) {
+		PairwiseAligner aligner = PairwiseAligner.getDefaultAligner(false,data);
+		if (verbose)
+			module.logln("\nComparing " + data.getTaxa().getTaxonName(it2) + " to " + data.getTaxa().getTaxonName(it1) );
+		
+		if (aligner==null)
+			return 0.0;
+		//aligner.setGapCosts(-1, -1, 100, 100);
+		int firstSite = 0;
+		int lastSite = data.getNumChars()-1;
+		int numChars = lastSite - firstSite+1;
+		
+		long[] extracted1 = new long[numChars];
+		long[] extracted2 = new long[numChars];
+		
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted1[ic] = data.getState(ic, it1);
+			extracted2[ic] = data.getState(ic, it2);
+		}
+		MesquiteNumber alignScore = new MesquiteNumber();
+		aligner.alignSequences(extracted1, extracted2, false, alignScore);
+		if (verbose)
+			module.logln("   Alignment score: " + alignScore);
+		for (int ic = firstSite; ic<=lastSite; ic++){
+			extracted2[lastSite-ic] = DNAState.complement(data.getState(ic, it2));
+		}
+		MesquiteNumber alignRCScore = new MesquiteNumber();
+		aligner.alignSequences(extracted1, extracted2, false, alignRCScore);
+		if (verbose)
+			module.logln("   Alignment score with " + data.getTaxa().getTaxonName(it2) + " reverse complemented: " + alignRCScore);
+
+		alignScore.divideBy(alignRCScore);
+		
+		if (verbose)
+			module.logln("   Ratio: " + alignScore.getDoubleValue());
+		
+		return alignScore.getDoubleValue();
+
+   	 }
+	/*.................................................................................................................*/
+	public static void reverseComplementSequencesIfNecessary(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd, boolean baseOnStopCodons, boolean verbose) {
+		reverseComplementSequencesIfNecessary(data,  module,  taxa,  itStart,  itEnd,  baseOnStopCodons, false, verbose);
+	}
+
+	/*.................................................................................................................*/
+	public static void reverseComplementSequencesIfNecessary(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd, boolean baseOnStopCodons, boolean againstAllOthers, boolean verbose) {
+		reverseComplementSequencesIfNecessary( data,  module,  taxa,  itStart,  itEnd,  0,  baseOnStopCodons,  againstAllOthers,  verbose);
+		}
+	/*.................................................................................................................*/
+	public static void reverseComplementSequencesIfNecessary(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd, int comparisonTaxon, boolean baseOnStopCodons, boolean againstAllOthers, boolean verbose) {
+
+		if (baseOnStopCodons) {
+			CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+			if (modelSet == null) {
+				modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+				modelSet.addToFile(data.getFile(), module.getProject(), module.findElementManager(CodonPositionsSet.class)); //THIS
+				data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+			}
+			for (int it = itStart; it<taxa.getNumTaxa() && it<=itEnd; it++) {
+				int stops = getMinimumStops(data, it, modelSet);
+				data.reverseComplement(0, data.getNumChars()-1, it, false, true);
+				int stopsRC = getMinimumStops(data, it, modelSet);
+				if (stops<=stopsRC) {
+					data.reverseComplement(0, data.getNumChars(), it, false, true);  // then we need to reverse them back.
+				} else
+					module.logln("  Reverse complemented " + taxa.getTaxonName(it));
+			}
+		} else {
+			for (int it = itStart; it<taxa.getNumTaxa() && it<=itEnd; it++) {
+			   
+				double score = 0;
+/*				if (againstAllOthers && false){
+					for (int ik = itStart; ik<taxa.getNumTaxa() && ik<=itEnd; ik++)
+						if (ik != it){
+							double thisScore = alignmentScoreRatioToRCScore((DNAData)data, module, ik, it, true);
+							score += thisScore;
+						}
+					score = score/(itEnd-itStart);
+				}
+				else {
+				*/
+					score = alignmentScoreRatioToRCScore((DNAData)data, module, comparisonTaxon, it, true);
+		//		}
+				
+				if (score>1.0){
+					data.reverseComplement(0, data.getNumChars(), it, false, true);  
+					module.logln("   *** Reverse complemented " + taxa.getTaxonName(it));
+				}
+			//	else
+			//		module.logln("Sequence not reverse complemented " + (it+1));
+
+			}
+		
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public static void reverseComplementSequencesIfNecessary(DNAData data, MesquiteModule module, Taxa taxa, Bits taxaToAdjust, int comparisonTaxon, boolean baseOnStopCodons, boolean verbose) {
+
+		if (baseOnStopCodons) {
+			CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+			if (modelSet == null) {
+				modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+				modelSet.addToFile(data.getFile(), module.getProject(), module.findElementManager(CodonPositionsSet.class)); //THIS
+				data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+			}
+			for (int it = 0; it<taxa.getNumTaxa() ; it++) {
+				if (taxaToAdjust.isBitOn(it)) {
+					int stops = getMinimumStops(data, it, modelSet);
+					data.reverseComplement(0, data.getNumChars()-1, it, false, true);
+					int stopsRC = getMinimumStops(data, it, modelSet);
+					if (stops<=stopsRC) {
+						data.reverseComplement(0, data.getNumChars(), it, false, true);  // then we need to reverse them back.
+					} else
+						module.logln("  Reverse complemented " + taxa.getTaxonName(it));
+				}
+			}
+		} else {
+			for (int it = 0; it<taxa.getNumTaxa(); it++) {
+				if (taxaToAdjust.isBitOn(it)) {
+
+					double score = 0;
+					score = alignmentScoreRatioToRCScore((DNAData)data, module, comparisonTaxon, it, true);
+
+					if (score>1.0){
+						data.reverseComplement(0, data.getNumChars(), it, false, true);  // then we need to reverse them back.
+						module.logln("   *** Reverse complemented " + taxa.getTaxonName(it));
+					}
+					//	else
+					//		module.logln("Sequence not reverse complemented " + (it+1));
+
+				}
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	public static int numApplicable(long[] sequence) {
+		int count = 0;
+		for (int i=0; i<sequence.length; i++) {
+			if (!DNAState.isInapplicable(sequence[i]))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public static double numNucleotide(long[] sequence, int nucleotideState) {
+		double count = 0.0;
+		for (int i=0; i<sequence.length; i++) {
+			if (DNAState.isElement(sequence[i], nucleotideState)) {
+				count+= 1.0/DNAState.cardinality(sequence[i]);
+			}
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public static double numA(long[] sequence) {
+		return numNucleotide(sequence,0);
+	}
+	/*.................................................................................................................*/
+	public static double numC(long[] sequence) {
+		return numNucleotide(sequence,1);
+	}
+	/*.................................................................................................................*/
+	public static double numG(long[] sequence) {
+		return numNucleotide(sequence,2);
+	}
+	/*.................................................................................................................*/
+	public static double numT(long[] sequence) {
+		return numNucleotide(sequence,3);
+	}
+	/** calculates melting temperature of sequence based upon simple formula presented on
+	 * http://www.promega.com/techserv/tools/biomath/calc11.htm#disc
+	 * which is cited as being from
+	 * Rychlik, W. and Rhoads, R.E. (1989) Nucl. Acids Res. 17, 8543.
+	/*.................................................................................................................*/
+	public static double getMeltingTemperature(long[] sequence) {  
+		double tm=0.0;
+		int numSites = numApplicable(sequence);
+		if (numSites==0) return 0.0;
+		if (numSites<14) {
+			tm =  4 * (numC(sequence) + numG(sequence)) + 2 * (numA(sequence) + numT(sequence)) ;
+		} else {
+			tm =  64.9 + 41 * (numC(sequence) + numG(sequence) - 16.4)/numSites;
+		}
+		return tm;
+	}
+
+	
+	/*.................................................................................................................*/
+	public static void setCodonPositions(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd, int startPos) {
+
+		CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+		if (modelSet == null) {
+			modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+			modelSet.addToFile(data.getFile(), module.getProject(), module.findElementManager(CodonPositionsSet.class)); //THIS
+			data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+		} 
+		setCodonPositions(data,modelSet, startPos,true,false);  
+	}
+	/*.................................................................................................................*/
+	public static void setCodonPositionsToMinimizeStops(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd) {
+
+		CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+		if (modelSet == null) {
+			modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+			modelSet.addToFile(data.getFile(), module.getProject(), module.findElementManager(CodonPositionsSet.class)); //THIS
+			data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+		} 
+		int minStops = -1;
+		int minPosStart = -1;
+		for (int i = 1; i<=3; i++) {
+			setCodonPositions(data,modelSet, i,true,false);  //set them temporarily
+			int totNumStops = 0;
+			for (int it=itStart; it<=itEnd; it++)
+				totNumStops+=((DNAData)data).getAminoAcidNumbers(it,ProteinData.TER);					 
+			if (minStops<0 || totNumStops<minStops) {
+				minStops = totNumStops;
+				minPosStart=i;
+			}
+		}
+		if (minPosStart>=0)
+			setCodonPositions(data,modelSet, minPosStart,true,false);  
+	}
+	/*.................................................................................................................*/
+	public static void shiftToMinimizeStops(DNAData data, MesquiteModule module, Taxa taxa, int itStart, int itEnd) {
+
+		CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+		if (modelSet == null) {
+			modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+			modelSet.addToFile(data.getFile(), module.getProject(), module.findElementManager(CodonPositionsSet.class)); //THIS
+			data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+		}
+
+		for (int it = itStart; it<taxa.getNumTaxa() && it<itEnd; it++) {
+			int stops = getMinimumStops(data, it, modelSet);
+		}
+	}
+
+}
diff --git a/Source/mesquite/categ/lib/MolecularState.java b/Source/mesquite/categ/lib/MolecularState.java
new file mode 100644
index 0000000..7e859ae
--- /dev/null
+++ b/Source/mesquite/categ/lib/MolecularState.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CategoricalState set for molecular data. */
+public class MolecularState extends CategoricalState{
+
+	public MolecularState(long initial){
+		super(initial);
+	}
+	public MolecularState(){
+		super();
+		set = inapplicable;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/OffersCategoricalData.java b/Source/mesquite/categ/lib/OffersCategoricalData.java
new file mode 100644
index 0000000..57aa156
--- /dev/null
+++ b/Source/mesquite/categ/lib/OffersCategoricalData.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class OffersCategoricalData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof OffersCategoricalData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return  ((Class)obj).isAssignableFrom(CategoricalState.class) || ((Class)obj).isAssignableFrom(CategoricalData.class);
+	}
+	public Class getAcceptedClass(){
+		return CategoricalState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/OffersDNAData.java b/Source/mesquite/categ/lib/OffersDNAData.java
new file mode 100644
index 0000000..580192c
--- /dev/null
+++ b/Source/mesquite/categ/lib/OffersDNAData.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.
+
+*This version says "I offer to give DNA data".  This is different from RequiresDNAData, which is used for consumers to say that is what they need*/
+
+public class OffersDNAData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof OffersDNAData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return  ((Class)obj).isAssignableFrom(DNAState.class) || ((Class)obj).isAssignableFrom(DNAData.class);
+	//to pass the test, the datatype requested must be DNA, Categorical, or generic
+	}
+	public Class getAcceptedClass(){
+		return DNAState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/OffersProteinData.java b/Source/mesquite/categ/lib/OffersProteinData.java
new file mode 100644
index 0000000..a971a58
--- /dev/null
+++ b/Source/mesquite/categ/lib/OffersProteinData.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class OffersProteinData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof OffersProteinData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return  ((Class)obj).isAssignableFrom(ProteinState.class) || ((Class)obj).isAssignableFrom(ProteinData.class);
+	}
+	public Class getAcceptedClass(){
+		return ProteinState.class;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/ProteinAdjustable.java b/Source/mesquite/categ/lib/ProteinAdjustable.java
new file mode 100644
index 0000000..f62b874
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinAdjustable.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class ProteinAdjustable extends CategoricalAdjustable {
+	public ProteinAdjustable (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = ProteinState.maxProteinState;
+	}
+	public ProteinAdjustable (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = ProteinState.maxProteinState;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return ProteinState.fullSet();
+	}
+	/*..........................................  ProteinAdjustable  ..................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new ProteinState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ProteinState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ProteinData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i<= ProteinState.maxProteinState; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................  ProteinAdjustable  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		ProteinState c;
+		if (cs == null || !(cs instanceof ProteinState))
+			c = new ProteinState();
+		else
+			c = (ProteinState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/*..........................................  ProteinAdjustable  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		if (checkIllegalNode(node, 8))
+			return "";
+		if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+			String s="";
+			for (int i=0; i<frequencies[node].length; i++) 
+				if (frequencies[node][i]!=0)
+					s+= ProteinState.toString(i) + ":" + MesquiteDouble.toString(frequencies[node][i]) + lineEnding;
+			return s;
+		}
+		else
+			return ProteinState.toString(getState(node), null, 0, false);
+			//return getCharacterState(null, node).toDisplayString();
+	}
+	/*..........................................  ProteinAdjustable  ...................................................*/
+	/**returns string describing states at nodes. */
+	public String toString () {
+		String s="";
+		for (int i=0; i<getNumNodes(); i++)
+			s += ProteinState.toString(getState(i), false);
+		return s;
+	}
+	/*..........................................  ProteinAdjustable  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+			if (charStates==null || ! (charStates.getClass() == ProteinCharacterHistory.class))
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................  ProteinAdjustable  ...................................................*/
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new ProteinAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/ProteinCharacterHistory.java b/Source/mesquite/categ/lib/ProteinCharacterHistory.java
new file mode 100644
index 0000000..657c095
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinCharacterHistory.java
@@ -0,0 +1,175 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.cont.lib.ContColorTable;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class ProteinCharacterHistory extends CategoricalHistory {
+	public ProteinCharacterHistory (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = ProteinState.maxProteinState;
+	}
+	public ProteinCharacterHistory (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = ProteinState.maxProteinState;
+	}
+	/*.......................................... ProteinState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		ProteinState c;
+		if (cs == null || !(cs instanceof ProteinState))
+			c = new ProteinState();
+		else
+			c = (ProteinState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/*..........................................  ProteinCharacterHistory  ..................................................*/
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return ProteinState.fullSet();
+	}
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new ProteinState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ProteinState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ProteinData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i<= ProteinState.maxProteinState; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*..........................................  ProteinCharacterHistory  ..................................................*/
+	/**clone this; if passed s is not null, place the clone there (so as to avoid creating new object)*/
+	public CharacterHistory clone(CharacterHistory s) {
+		ProteinCharacterHistory snew;
+		if ((s==null) || (s.getNumNodes()!=numNodes) || (!(s instanceof ProteinCharacterHistory)))
+			snew = new ProteinCharacterHistory(getTaxa(), numNodes);
+		else {
+			snew = (ProteinCharacterHistory)s;
+		}
+		for (int i=0; i<numNodes; i++) {
+			snew.setState(i, getState(i));
+		}
+		if (frequenciesExist())
+			copyFrequencies(this, snew);
+		else
+			snew.disposeFrequencies();
+		if (extraFrequenciesExist())
+			copyExtraFrequencies(this, snew);
+		else
+			snew.disposeExtraFrequencies();
+		snew.data = data;
+		snew.characterNumber = characterNumber;  //setting parent character
+		snew.setExplanation(getExplanation());
+		return snew;
+	}
+	/*..........................................  ProteinCharacterHistory  ..................................................*/
+	public Color getDefaultColor(int maxState, int istate){
+		return ProteinData.getProteinColorOfState(istate);
+	}
+	/*..........................................ProteinCharacterHistory................*/
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable) {
+		
+		if (colorTable == null || !(colorTable instanceof ProteinColorTable))
+			return new ProteinColorTable();
+		return colorTable;
+	}
+	/*..........................................  ProteinCharacterHistory  ..................................................*/
+	/** Must be called before colors for states are used (e.g., before a tree is shaded).  Goes through all nodes to find states present, to set
+	minima and maxima and record all states present. This allows the color range to be known before
+	colors for particular states are requested by a tree shade, for example.*/
+	public void prepareColors(Tree tree, int drawnRoot) {  
+		allStates=ProteinState.span(0,ProteinState.maxProteinState);
+		maxState = enforcedMaxState;
+	}
+	/*..........................................  ProteinCharacterHistory  ...................................................*/
+	/**returns string describing character states at node  */
+	public String toString (int node, String lineEnding) {
+		if (checkIllegalNode(node, 8))
+			return "";
+		if (frequencies != null && frequencies[node]!=null && frequencies[node].length>0) {
+			String s="";
+			for (int i=0; i<frequencies[node].length; i++) 
+				if (frequencies[node][i]!=0)
+					s+= ProteinState.toString(i) + ":" + MesquiteDouble.toString(frequencies[node][i]) + lineEnding;
+			return s;
+		}
+		else
+			return ProteinState.toString(getState(node), null, 0, false);
+	}
+	/*..........................................  ProteinCharacterHistory  ...................................................*/
+	/**returns string describing states at nodes. */
+	public String toString () {
+		String s="";
+		for (int i=0; i<getNumNodes(); i++)
+			s += ProteinState.toString(getState(i), false);
+		return s;
+	}
+	/*..........................................  ProteinCharacterHistory  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == ProteinCharacterHistory.class))
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................  ProteinCharacterHistory  ...................................................*/
+	public CharacterHistory makeHistory(Tree tree){
+		return new ProteinCharacterHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+	}
+	/*..........................................  ProteinCharacterHistory  ...................................................*/
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new ProteinAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/ProteinColorTable.java b/Source/mesquite/categ/lib/ProteinColorTable.java
new file mode 100644
index 0000000..e0e75f9
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinColorTable.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+
+import java.awt.Color;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+public class ProteinColorTable extends MesquiteColorTable  {
+	  public ProteinColorTable(){
+		   super();
+			for (int i=0; i<maxNumStates; i++) {
+				for (int j=0; j<maxNumStates; j++) {
+					setColor(i, j,ProteinData.getProteinColorOfState(j));
+				}
+			}
+				   
+	   }
+		/**resets to default mode*/
+		public void resetDefaultMode(){
+			   setMode(COLORS);
+		}
+		/**resets to default mode*/
+		public void resetToDefaults(){
+			super.resetToDefaults();
+			for (int i=0; i<maxNumStates; i++) {
+				for (int j=0; j<maxNumStates; j++) {
+					setColor(i, j,ProteinData.getProteinColorOfState(j));
+				}
+			}
+		}
+}
+
+
diff --git a/Source/mesquite/categ/lib/ProteinData.java b/Source/mesquite/categ/lib/ProteinData.java
new file mode 100644
index 0000000..919ae4f
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinData.java
@@ -0,0 +1,417 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CharacterData for Protein data stored as Categorical sets (e.g, "{A, C}" */
+public class ProteinData extends MolecularData {
+	static char[] proteinSymbols;
+	static String[] symbolsAsStrings;
+	static String[] namesAsStrings;
+	static String[] longNamesAsStrings;
+	public static String DATATYPENAME="Protein Data";
+
+	static {
+		proteinSymbols = new char[] {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y', '*', '1', '2', '3', '4'};
+		symbolsAsStrings = new String[] {"A", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "V", "W", "Y", "*", "1", "2", "3", "4"};
+		namesAsStrings = new String[] {"Ala", "Cys", "Asp", "Glu", "Phe", "Gly", "His", "Ileu", "Lys", "Leu", "Met", "Asn", "Pro", "Gln", "Arg", "Ser", "Thr", "Val", "Trp", "Tyr", "Ter", "1", "2", "3", "4"};
+		longNamesAsStrings = new String[] {"Alanine", "Cysteine", "Aspartic acid", "Glutamic acid", "Phenylalanine", "Glycine", "Histidine", "Isoleucine", "Lysine", "Leucine", "Methionine", "Asparagine", "Proline", "Glutamine", "Arginine", "Serine", "Threonine", "Valine", "Tryptophan", "Tyrosine", "Stop", "1", "2", "3", "4"};
+	}
+
+	public static final int ALA = 0;
+	public static final int CYS = 1;
+	public static final int ASP = 2;
+	public static final int GLU = 3;
+	public static final int PHE = 4;
+	public static final int GLY = 5;
+	public static final int HIS = 6;
+	public static final int ILEU = 7;
+	public static final int LYS = 8;
+	public static final int LEU = 9;
+	public static final int MET = 10;
+	public static final int ASN = 11;
+	public static final int PRO = 12;
+	public static final int GLN = 13;
+	public static final int ARG = 14;
+	public static final int SER = 15;
+	public static final int THR = 16;
+	public static final int VAL = 17;
+	public static final int TRP = 18;
+	public static final int TYR = 19;
+	public static final int TER = 20;
+	public static final int STOP = 20;
+	public static final int EXTRA1 = 21;
+	public static final int EXTRA2 = 22;
+	public static final int EXTRA3 = 23;
+	public static final int EXTRA4 = 24;
+	public static final int ABSENT=-1;
+
+	static Color noBaseColor = new Color((float)240/255, (float)240/255, (float)240/255);
+	public static Color multistateColor = new Color((float)100/255, (float)100/255, (float)50/255);
+	static Color[] proteinColors;
+	static {
+		proteinColors = new Color[26];
+		proteinColors[0] = new Color((float)130/255, (float)233/255, (float)1.0);
+		proteinColors[1] = new Color((float)1.0, (float)171/255, (float)1.0);
+		proteinColors[2] = new Color((float)174/255, (float)168/255, (float)118/255);
+		proteinColors[3] = new Color((float)191/255, (float)185/255, (float)136/255);
+		proteinColors[4] = new Color((float)148/255, (float)182/255, (float)1.0);
+		proteinColors[5] = new Color((float)227/255, (float)6/255, (float)176/255);
+		proteinColors[6] = new Color((float)185/255, (float)20/255, (float)1.0);
+		proteinColors[7] = new Color((float)79/255, (float)155/255, (float)1.0);
+		proteinColors[8] = new Color((float)167/255, (float)13/255, (float)227/255);
+		proteinColors[9] = new Color((float)0.0, (float)18/255, (float)184/255);
+		proteinColors[10] = new Color((float)94/255, (float)181/255, (float)181/255);
+		proteinColors[11] = new Color((float)1.0, (float)0.0, (float)12/255);
+		proteinColors[12] = new Color((float)20/255, (float)184/255, (float)110/255);
+		proteinColors[13] = new Color((float)194/255, (float)1/255, (float)5/255);
+		proteinColors[14] = new Color((float)214/255, (float)138/255, (float)1.0);
+		proteinColors[15] = new Color((float)1.0, (float)223/255, (float)10/255);
+		proteinColors[16] = new Color((float)176/255, (float)21/255, (float)26/255);
+		proteinColors[17] = new Color((float)21/255, (float)255/255, (float)17/255);
+		proteinColors[18] = new Color((float)192/255, (float)1.0, (float)156/255);
+		proteinColors[19] = new Color((float)235/255, (float)144/255, (float)134/255);
+		proteinColors[20] = new Color((float)0.0, (float)0.0, (float)0.0);
+		proteinColors[21] = new Color((float)248/255, (float)170/255, (float)44/255);
+		proteinColors[22] = new Color((float)1.0, (float)192/255, (float)2/255);
+		proteinColors[23] = new Color((float)1.0, (float)238/255, (float)166/255);
+		proteinColors[24] = new Color((float)1.0, (float)227/255, (float)186/255);
+		proteinColors[25] = new Color((float)0.0, (float)0.0, (float)0.0);
+	}
+	public ProteinData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars, taxa);
+		symbols=proteinSymbols;
+		setUseDiagonalCharacterNames(false);
+
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ProteinState.class;
+	}
+	/* .......................................... ProteinData .................................................. */
+	public boolean colorCellsByDefault() { 
+		return true;
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	/** Indicates whether the data are molecular sequence data or not */ 
+	public boolean isMolecularSequence() {
+		return true;
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+	/** Get symbol for state st. */
+	public char getSymbol(int st) {
+			//TODO: check that state is legal
+		if (st<0 || st>=symbols.length)
+			return 0;
+		return symbols[st];
+	}
+	/*............................................................................................*/
+	/** Get amino acid symbol for state st. */
+	public static char getAASymbol(int st) {
+		if (st<0 || st>=proteinSymbols.length)
+			return 0;
+		return proteinSymbols[st];
+	}
+	
+	/*............................................................................................*
+
+	protected int findSymbol(char symbol){
+		for (int ist = 0; ist<symbols.length; ist++) {
+			if (symbols[ist]==symbol) {
+				return ist;
+			}
+		}
+		return -1;
+	}
+
+
+	/*............................................................................................*/
+	/** gets default state symbol for state "state" of character ic, returned as string. */
+	public String getStateSymbol(int ic, int state) {
+		if (state <0 || state>=symbols.length)
+			return String.valueOf(getUnassignedSymbol());
+		if (state>=0 && symbols!=null && state<symbols.length) {
+			return String.valueOf(symbols[state]);
+		}
+		else if (state >=0 && state <= ProteinState.maxProteinState)
+			return String.valueOf(defaultSymbols[state]);
+		else 
+			return Integer.toString(state);
+	}
+	/*............................................................................................*/
+	/** gets default state symbol for state "state", returned as string. */
+	public static String getDefaultStateSymbol(int state) {
+		if (state <0 || state>=proteinSymbols.length)
+			return String.valueOf(CharacterData.defaultInapplicableChar);
+		if (state>=0 && proteinSymbols!=null && state<proteinSymbols.length) {
+			return String.valueOf(proteinSymbols[state]);
+		}
+		else if (state >=0 && state <= ProteinState.maxProteinState)
+			return String.valueOf(defaultSymbols[state]);
+		else 
+			return Integer.toString(state);
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**clone this CharacterData and return new copy.  Does not clone the associated specs sets etc. */
+	public CharacterData cloneData(){
+		ProteinData data = new ProteinData(matrixManager, numTaxa, numChars, getTaxa());
+		for (int ic=0; ic<numChars; ic++){
+			for (int it=0; it<numTaxa; it++) {
+				data.setState(ic, it, getStateRaw(ic, it)); 
+			}
+			if (getSelected(ic))
+				data.setSelected(ic, true);
+		}
+		data.resetCellMetadata();
+		return data;
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**get matrix and return as StsOfCharacters */
+   	public MCharactersDistribution getMCharactersDistribution(){
+   		MProteinEmbedded states = new MProteinEmbedded(this);
+		return states;
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**return a CharacterDistribution that points to character ic */
+   	public CharacterDistribution getCharacterDistribution(int ic){
+   		ProteinEmbedded states = new ProteinEmbedded(this, ic);
+		 return states;
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**Return CharacterDistribution object with same number of taxa as this object (but not with any particular data; just so that of same data type) */
+   	public CharacterDistribution makeCharacterDistribution(){
+   		ProteinAdjustable c= new ProteinAdjustable(getTaxa(), numTaxa);
+   		c.setParentData(this);
+   		return c;
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+   	/** creates an empty CharacterState object of the same data type as CharacterData subclass used.*/
+   	public CharacterState makeCharacterState(){
+   		return new ProteinState();
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**Return CharacterData object with same number of taxa & characters as this object (but not with any particular data; just so that of same data type) */
+   	public CharacterData makeCharacterData() {
+   		return new ProteinData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+   	}
+   	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+   		return new ProteinData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+	/**Return CharacterData object with passed number of taxa & characters (but not with any particular data; just so that of same data type) */
+   	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+   		return new ProteinData(getMatrixManager(), ntaxa, nchars, getTaxa());
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+   	/** returns whether the matrix would prefer to have columns sized individually in editors.  Default is true.*/
+	public boolean pleaseAutoSizeColumns() {
+		return false;
+	}
+	/*..........................................  ProteinData  ..................................................*/
+   	/** returns the state of character ic in taxon it*/
+   	public  CharacterState getCharacterState(CharacterState cs, int ic, int it){
+   		if (cs!=null && cs.getClass()==ProteinState.class) {
+   			((ProteinState)cs).setValue(getStateRaw(ic, it));
+   			return cs;
+		}
+   		return new ProteinState(getStateRaw(ic, it));
+   	}
+	/*..........................................  ProteinData  ..................................................*/
+	/** gets state name of state "state" of character ic */
+	public String getStateName(int ic, int state) {
+		/*if (stateNames!= null && state>=0 && stateNames.length> ic && stateNames[ic]!=null && state< stateNames[ic].length && stateNames[ic][state]!=null) {
+			return stateNames[ic][state];
+		}
+		else */ if (symbolsAsStrings!=null && state < symbolsAsStrings.length)
+			return symbolsAsStrings[state];//Integer.toString(state)
+		else return null;
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	/** gets state name of state "state" */
+	public static String getStateFullName(int state) {
+		if (namesAsStrings!=null && state>=0 && state < namesAsStrings.length)
+			return namesAsStrings[state];//Integer.toString(state)
+		else return null;
+	}
+	/*..........................................  ProteinData  ..................................................*/
+	/** gets the long state name of state "state"*/
+	public static String getStateLongName(int state) {
+		if (longNamesAsStrings!=null && state>=0 && state < longNamesAsStrings.length)
+			return longNamesAsStrings[state];//Integer.toString(state)
+		else return null;
+	}
+	/*..........................................  DNAData  ..................................................*/
+	public Color getColorOfState(int ic, int istate, int maxState){
+		return getProteinColorOfState(istate);
+	}
+	public Color getColorOfState(int ic, int istate){
+		return getProteinColorOfState(istate);
+	}
+	public static Color getProteinColorOfState(int istate){
+		if (istate>=0 && istate<=25)
+			return proteinColors[istate];
+		else
+			return noBaseColor;
+	}
+//		return MesquiteColorTable.getDefaultColor(ProteinState.maxProteinState+1, istate, MesquiteColorTable.COLORS_NO_BW);
+	/*..........................................    ..................................................*/
+	public static Color getAminoAcidColor(long s){
+		if (CategoricalState.hasMultipleStates(s))
+			return multistateColor;
+		else {
+			int istate = CategoricalState.minimum(s);
+			return getProteinColorOfState(istate);
+		}
+}
+	/*..........................................    ..................................................*/
+	public static Color getAminoAcidColor(long s, Color multipleStateColor){
+		if (CategoricalState.hasMultipleStates(s))
+			return multipleStateColor;
+		else {
+			int istate = CategoricalState.minimum(s);
+			return getProteinColorOfState(istate);
+		}
+}
+
+	/*...............  ProteinData  ...............*/
+	public long getDefaultState(){
+  		return CategoricalState.inapplicable;
+	}
+
+	/*..........................................  ProteinData  ..................................................*/
+	/**Returns the states at character ic and taxon it as a string *
+	public String statesToStringCore(int ic, long s) {
+		if ((CategoricalState.cardinality(s) == 2) && CategoricalState.isUncertain(s)) {
+			if (CategoricalState.isElement(s,2)&&CategoricalState.isElement(s,11))
+				return "B";
+			else if (CategoricalState.isElement(s,3)&&CategoricalState.isElement(s,13))
+				return "Z";
+			else
+				return super.statesToStringCore(ic,s);
+		}
+		else
+			return super.statesToStringCore(ic,s);
+	}
+
+
+	/*..........................................  ProteinData  ..................................................*/
+   	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay){
+		statesIntoStringBufferCore(ic,s,sb,forDisplay, true, true);
+	}
+	/*..........................................  ProteinData  ..................................................*/
+   	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBufferCore(int ic, long s, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		if ((CategoricalState.cardinality(s) == 2) && CategoricalState.isUncertain(s)) {
+			if (CategoricalState.isElement(s,2)&&CategoricalState.isElement(s,11))
+				sb.append("B");
+			else if (CategoricalState.isElement(s,3)&&CategoricalState.isElement(s,13))
+				sb.append("Z");
+			else
+				super.statesIntoStringBufferCore(ic,s, sb, forDisplay,includeInapplicable, includeUnassigned);
+		}
+		else
+			super.statesIntoStringBufferCore(ic,s, sb, forDisplay,includeInapplicable, includeUnassigned);
+	}
+	/*................................................................................................*/
+	private void appendStateSymbol(int e, StringBuffer sb){
+			if (e>=0 && e<= ProteinState.maxProteinState)
+				sb.append(symbols[e]);
+	}
+	
+	/*................................................................................................*/
+	public void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb){
+		boolean first=true;
+		long s = getStateRaw(ic, it);
+		if (s == 0L || s == CategoricalState.impossible)
+			sb.append('!');
+		else if (s==CategoricalState.inapplicable)
+			sb.append(getInapplicableSymbol());
+		else if (s==CategoricalState.unassigned)
+			sb.append(getUnassignedSymbol());
+		else {
+			int card =0;
+			int current = sb.length();
+			for (int e=0; e<=ProteinState.maxProteinState; e++) {
+				if (CategoricalState.isElement(s, e)) {
+					card++;
+					if (!first)
+						sb.append(' ');
+					appendStateSymbol(e, sb);
+					first=false;
+				}
+			}
+			if (card>1) {
+				if (CategoricalState.isUncertain(s)) {
+					sb.insert(current,'{');
+					sb.append('}');
+				}
+				else {
+					sb.insert(current,'(');
+					sb.append(')');
+				}
+			}
+			if (first){ //nothing written!  Write illegal character so that change will not go unnoticed
+				sb.append('!');
+				if (ic == 0 && it == 0)
+					ecount = 0;
+				if (ecount++<100)
+					MesquiteMessage.warnProgrammer("ERROR: nothing written for character " + (ic+1) + " taxon " + (it+1)+ " state as long: " + s);
+			}
+		}
+	}
+	int ecount = 0;
+	/*..........................................  ProteinData  ..................................................*/
+	/* Returns state set from single state symbol �*/
+   	public long fromChar(char state){
+		if (state == getInapplicableSymbol())
+			return CategoricalState.inapplicable;
+		else if ((state== getUnassignedSymbol()) ||  (state == 'X')  ||  (state== 'x'))
+			return  CategoricalState.unassigned;
+		else if (state == getMatchChar()) {
+			return CategoricalState.unassigned;//note: this should't happen, as matchchar with no char #
+		}
+		else {
+   			return ProteinState.fromCharStatic(state);
+  		}
+ 	}
+	/*..........................................ProteinData.....................................*/
+	/**returns the maximum possible state */
+	public int getMaxPossibleState() {
+		return ProteinState.getMaxPossibleStateStatic();
+	}
+	/* ..........................................ProteinData..................................... */
+	/** returns the name of a non-missing, applicable entry in a matrix cell; e.g. "base" for DNAData*/
+	public String getNameOfCellEntry(int number){
+		if (number==1)
+			return "amino acid";
+		else
+			return "amino acids";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/categ/lib/ProteinEmbedded.java b/Source/mesquite/categ/lib/ProteinEmbedded.java
new file mode 100644
index 0000000..30ce51f
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinEmbedded.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A class for an array of  categorical character states for one character, at each of the taxa  or nodes*/
+public class ProteinEmbedded extends CategoricalEmbedded {
+	public ProteinEmbedded (ProteinData data, int ic) {
+		super(data, ic);
+		enforcedMaxState = ProteinState.maxProteinState;
+	}
+	/** returns the union of all state sets*/
+	public long getAllStates() {  //
+		long s=0;
+		for (int i=0; i<= ProteinState.maxProteinState; i++) {
+			s = CategoricalState.addToSet(s, i);
+		}
+		return s;
+	}
+	/*.......................................... ProteinState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		ProteinState c;
+		if (cs == null || !(cs instanceof ProteinState))
+			c = new ProteinState();
+		else
+			c = (ProteinState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return ProteinState.fullSet();
+	}
+	/*..........................................  ProteinEmbedded  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == ProteinCharacterHistory.class))
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new ProteinCharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new ProteinAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/ProteinState.java b/Source/mesquite/categ/lib/ProteinState.java
new file mode 100644
index 0000000..b2b54cc
--- /dev/null
+++ b/Source/mesquite/categ/lib/ProteinState.java
@@ -0,0 +1,208 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CategoricalState set for Protein (max state enforced at 4). */
+public class ProteinState extends MolecularState{
+	public static final int maxProteinState = ProteinData.proteinSymbols.length-1;
+	public ProteinState(long initial){
+		super(initial);
+	}
+	public ProteinState(){
+		super();
+	}
+	public Class getCharacterDataClass() {
+		return ProteinData.class;
+	}
+	public String getDataTypeName(){
+		return ProteinData.DATATYPENAME;
+	}
+	public Class getMCharactersDistributionClass(){
+		return MProteinAdjustable.class;
+	}
+	public Class getCharacterDistributionClass() {
+		return ProteinAdjustable.class;
+	}
+	public Class getCharacterHistoryClass() {
+		return ProteinCharacterHistory.class;
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new ProteinAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new ProteinCharacterHistory(taxa, numNodes);
+	}
+	/*..........................................ProteinState.....................................*/
+	public static long fullSet(){
+		return CategoricalState.span(0, maxProteinState);
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public String toNEXUSString() {
+		return ProteinState.toNEXUSString(set);
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public static String toNEXUSString(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&s)!=0L) {
+				temp+=ProteinData.getDefaultStateSymbol(e);
+			}
+		}
+		if (temp.length()>1)
+			temp ="{" + temp + "}";
+		return temp;
+	}
+	/*..........................................ProteinState.....................................*/
+
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  �*/
+	public  String toDisplayString(){
+		if (isInapplicable(set))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(set))
+			return "" + CharacterData.defaultMissingChar;
+		char sep = '&';
+		if (isUncertain(set))
+			sep = '/';
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxProteinState; e++) {
+			if (((1L<<e)&set)!=0) {
+				if (!first)
+					temp+=sep;
+				temp+=ProteinData.proteinSymbols[e];
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		return temp;
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as ProteinState) to string.  Uses character state names if available.*/
+	public static String toString(int e) {
+		if (e<0 || e>maxProteinState)
+			return "impossible";
+		return ProteinData.symbolsAsStrings[e];
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as ProteinState) to string.  .*/
+	public static String toString(long s, boolean useBraces) {
+		return toString(s, null, 0, useBraces);
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as ProteinState) to string.  .*/
+	public static String toString(long s) {
+		return toString(s, null, 0, true);
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as ProteinState) to string.  .*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces) {
+		return toString(s, data, ic, useBraces, false);
+	}
+	/*..........................................ProteinState.....................................*/
+	/** converts passed long (treated as ProteinState) to string.  Uses character state names if available.*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces, boolean useSymbols) {
+		if (s == impossible)
+			return "impossible";
+		else if (s== unassigned) {
+			if (data == null)
+				return "?";
+			else
+				return String.valueOf(data.getUnassignedSymbol());
+		}
+		else if (s == inapplicable){
+			if (data == null)
+				return "-";
+			else
+				return String.valueOf(data.getInapplicableSymbol());
+		}
+
+		boolean first=true;
+		String temp;
+		if (useBraces) 
+			temp="{";
+		else
+			temp="";
+		for (int e=0; e<=maxProteinState; e++) {
+			if (isElement(s, e)) {
+				if (!first)
+					temp+=" ";
+				temp+=ProteinData.symbolsAsStrings[e];
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		if (useBraces)
+			temp+="}";
+		return temp;
+	}
+	/*..........................................ProteinState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}) �*/
+	public long fromChar(char c) { 
+		return fromCharStatic(c);
+	}
+	/*..........................................ProteinState.....................................*/
+	/**return the state set containing the state represented by the character (e.g., '0' to {0}) �*/
+	public static long fromCharStatic(char c) { 
+		if (c == '?')
+			return unassigned;
+		if (c == '-')
+			return inapplicable;
+   		if (c == 'B' || c == 'b')  // 2, 11
+   				return CategoricalState.setUncertainty(CategoricalState.makeSet(2, 11), true);
+   		else if (c == 'Z' || c == 'z')  // 3, 13
+   				return CategoricalState.setUncertainty(CategoricalState.makeSet(3, 13), true);
+		else {
+			char C;
+			if (c == 'j' || c == 'J'){ //translate j to w
+				c = 'w';
+				C = 'W';
+			}
+			else
+				C = Character.toUpperCase(c);
+			for (int i = 0; i<=ProteinState.maxProteinState; i++) //go through all default symbols to find c
+				if (c==ProteinData.proteinSymbols[i] || C==ProteinData.proteinSymbols[i])
+					return CategoricalState.makeSet(i);
+  		}
+  		return CategoricalState.impossible;
+	}
+
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public static int getMaxPossibleStateStatic() {
+		return maxProteinState;
+	}
+	/*..........................................CategoricalState.....................................*/
+	/**returns the maximum possible state */
+	public  int getMaxPossibleState() {
+		return maxProteinState;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/RNACharacterAdjustable.java b/Source/mesquite/categ/lib/RNACharacterAdjustable.java
new file mode 100644
index 0000000..2cda026
--- /dev/null
+++ b/Source/mesquite/categ/lib/RNACharacterAdjustable.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A subclass of CharacterDistribution for DNA data.  Enforces max state at 4*/
+public class RNACharacterAdjustable extends DNACharacterAdjustable {
+	public RNACharacterAdjustable (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = 3;
+	}
+	public RNACharacterAdjustable (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = 3;
+	}
+	/*..........................................  RNACharacterAdjustable  ..................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new RNAState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return RNAState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return RNAData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return RNAData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return RNAState.fullSet();
+	}
+	/*..........................................  RNAState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		RNAState c;
+		if (cs == null || !(cs instanceof RNAState))
+			c = new RNAState();
+		else
+			c = (RNAState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+
+	/*..........................................  RNACharacterAdjustable  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == RNACharacterHistory.class))
+			soc = new RNACharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new RNACharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new RNACharacterAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/RNACharacterHistory.java b/Source/mesquite/categ/lib/RNACharacterHistory.java
new file mode 100644
index 0000000..7e9e294
--- /dev/null
+++ b/Source/mesquite/categ/lib/RNACharacterHistory.java
@@ -0,0 +1,96 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/** A subclass of CharacterHistory forRNA data.  Enforces max state at 3*/
+public class RNACharacterHistory extends DNACharacterHistory {
+	public RNACharacterHistory (Taxa taxa) {
+		super(taxa);
+		enforcedMaxState = 3;
+	}
+	public RNACharacterHistory (Taxa taxa, int num) {
+		super(taxa, num);
+		enforcedMaxState = 3;
+	}
+	/*..........................................  DNACharacterHistory  ..................................................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new RNAState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return RNAState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return RNAData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return RNAData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	/**Returns full set of allowed states*/
+	public long fullSet (){
+		return RNAState.fullSet();
+	}
+	/*..........................................  RNAState  ...................................................*/
+	/**returns CharacterState at node N */
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		if (checkIllegalNode(N, 5)) {
+			if (cs!=null)
+				cs.setToUnassigned();
+			return cs;
+		}
+		RNAState c;
+		if (cs == null || !(cs instanceof RNAState))
+			c = new RNAState();
+		else
+			c = (RNAState)cs;
+		c.setValue(getState(N));
+		return c;
+	}
+	/*..........................................  RNACharacterAdjustable  ...................................................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == RNACharacterHistory.class))
+			soc = new RNACharacterHistory(tree.getTaxa(), numNodes);
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new RNACharacterHistory(tree.getTaxa(), numNodes);
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	public CharacterHistory makeHistory(Tree tree){
+		return new RNACharacterHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+	}
+	public CategoricalAdjustable makeAdjustable(Taxa taxa){
+		return new RNACharacterAdjustable(taxa, taxa.getNumTaxa());
+	} 
+}
+
diff --git a/Source/mesquite/categ/lib/RNAData.java b/Source/mesquite/categ/lib/RNAData.java
new file mode 100644
index 0000000..895bd3e
--- /dev/null
+++ b/Source/mesquite/categ/lib/RNAData.java
@@ -0,0 +1,102 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A subclass of CharacterData for RNA data stored as Categorical sets (e.g, "{A, C}" */
+public class RNAData extends DNAData {
+	public static String DATATYPENAME="RNA Data";
+	public RNAData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars, taxa);
+		super.setSymbolDirect(3, 'U');
+	}
+   	public CharacterDistribution makeCharacterDistribution(){
+   		RNACharacterAdjustable c= new RNACharacterAdjustable(getTaxa(), numTaxa);
+   		c.setParentData(this);
+   		return c;
+   	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return RNAState.class;
+	}
+	public String getDataTypeName(){
+		return RNAData.DATATYPENAME;
+	}
+	/*..........................................    ..................................................*/
+	public CharacterState makeCharacterState(){
+  		return (CategoricalState) new RNAState(getDefaultState());
+	}
+	/*............................................................................................*/
+	/** gets default state symbol for state "state", returned as string. */
+	public static String getDefaultStateSymbol(int state) {
+		if (state==0)
+			return "A";
+		else if (state==1)
+			return "C";
+		else if (state==2)
+			return "G";
+		else if (state==3)
+			return "U";
+		else
+			return Integer.toString(state);
+	}
+	/*..........................................  RNAData  ..................................................*/
+	/* Appends to buffer state symbol for state e �*/
+	protected void appendStateSymbol(int e, boolean lowerCase, StringBuffer sb){
+		if (lowerCase){
+			if (e==0)
+				sb.append('a');
+			else if (e==1)
+				sb.append('c');
+			else if (e==2)
+				sb.append('g');
+			else if (e==3)
+				sb.append('u');
+		}
+		else {
+			if (e==0)
+				sb.append('A');
+			else if (e==1)
+				sb.append('C');
+			else if (e==2)
+				sb.append('G');
+			else if (e==3)
+				sb.append('U');
+		}
+	}
+	/*..........................................  RNAData  ..................................................*/
+	/* Returns state set from single state symbol �*/
+   	public long fromChar(char state){
+		if (state == getInapplicableSymbol())
+			return CategoricalState.inapplicable;
+		else if (state== getUnassignedSymbol())
+			return  CategoricalState.unassigned;
+		else if (state == getMatchChar()) {
+			return CategoricalState.unassigned;//note: this should't happen, as matchchar with no char #
+		}
+		else {
+   			return DNAState.fromCharStatic(state);
+  		}
+ 	}
+}
+
+
+
diff --git a/Source/mesquite/categ/lib/RNAState.java b/Source/mesquite/categ/lib/RNAState.java
new file mode 100644
index 0000000..61dd778
--- /dev/null
+++ b/Source/mesquite/categ/lib/RNAState.java
@@ -0,0 +1,196 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of CategoricalState for RNA data */
+public class RNAState extends DNAState{
+	public RNAState(long initial){
+		super(initial);
+	}
+	public RNAState(){
+		super();
+	}
+	public Class getCharacterDataClass() {
+		return RNAData.class;
+	}
+	public Class getMCharactersDistributionClass(){
+		return MCategoricalDistribution.class;
+	}
+	public Class getCharacterDistributionClass() {
+		return RNACharacterAdjustable.class;
+	}
+	public Class getCharacterHistoryClass() {
+		return RNACharacterHistory.class;
+	}
+	public String getDataTypeName(){
+		return RNAData.DATATYPENAME;
+	}
+	public static long fullSet(){
+		return CategoricalState.span(0, 3);
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new RNACharacterAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new RNACharacterHistory(taxa, numNodes);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public String toNEXUSString() {
+		return RNAState.toNEXUSString(set);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as CategoricalState) to string.  Uses default symbols for states. */
+	public static String toNEXUSString(long s) {
+		if (isInapplicable(s))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(s))
+			return "" + CharacterData.defaultMissingChar;
+		return RNAData.getIUPACSymbol(s);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed int (treated as RNAState) to string.  Uses character state names if available. �*/
+	public static String toString(int e) {
+		if (e==0)
+			return "A";
+		else if (e==1)
+			return "C";
+		else if (e==2)
+			return "G";
+		else if (e==3)
+			return "U";
+		else
+			return Integer.toString(e);
+	}
+	/*..........................................RNAState.....................................*/
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  Repeated from DNAState so it uses RNAState's toString(e) �*/
+	public  String toDisplayString(){
+		if (isInapplicable(set))
+			return "" + CharacterData.defaultInapplicableChar;
+		if (isUnassigned(set))
+			return "" + CharacterData.defaultMissingChar;
+		char sep = '&';
+		if (isUncertain(set))
+			sep = '/';
+		boolean first=true;
+		String temp="";
+		for (int e=0; e<=maxCategoricalState; e++) {
+			if (((1L<<e)&set)!=0L) {
+				if (!first)
+					temp+=sep;
+				if (e<4)
+					temp += toString(e);
+				else
+					temp+= Integer.toString(e); //there should be no such states, but just in case, show as integers
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		return temp;
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as RNAState) to string.  Uses braces*/
+	public static String toString(long s) {
+		return toString(s, null, 0, true);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as RNAState) to string.  */
+	public static String toString(long s, boolean useBraces) {
+		return toString(s, null, 0, useBraces);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as RNAState) to string.  .*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces) {
+		return toString(s, data, ic, useBraces, false);
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed long (treated as RNAState) to string.  Repeated from DNAState so that it uses RNAState's toChar. �*/
+	public static String toString(long s, CategoricalData data, int ic, boolean useBraces, boolean useSymbols) {
+		if (s == impossible)
+			return "impossible";
+		else if (s== unassigned) {
+			if (data == null)
+				return "?";
+			else
+				return String.valueOf(data.getUnassignedSymbol());
+		}
+		else if (s == inapplicable){
+			if (data == null)
+				return "-";
+			else
+				return String.valueOf(data.getInapplicableSymbol());
+		}
+		boolean first=true;
+		String temp;
+		if (useBraces) 
+			temp="{";
+		else
+			temp="";
+		for (int e=0; e<=maxDNAState; e++) {
+			if (isElement(s, e)) {
+				if (!first)
+					temp+=" ";
+				if (data != null) {
+					temp+=data.getStateName(ic, e);
+				}
+				else if (e>=0 && e<=3)
+					temp+= toChar(e, data, CategoricalState.isLowerCase(s));
+				else
+					temp+=Integer.toString(e);
+				first=false;
+			}
+		}
+		if (first)
+			temp += '!'; //no state found!
+		if (useBraces)
+			temp+="}";
+		return temp;
+	}
+	/*..........................................RNAState.....................................*/
+	/** converts passed int (treated as RNAState) to string.  Uses character state names if available. �*/
+	public static char toChar(int e, CharacterData data, boolean lowerCase) {
+		if (lowerCase){
+			if (e==0)
+				return 'a';
+			else if (e==1)
+				return 'c';
+			else if (e==2)
+				return 'g';
+			else if (e==3) 
+				return 'u';
+			else
+				return '!';
+		}
+		if (e==0)
+			return 'A';
+		else if (e==1)
+			return 'C';
+		else if (e==2)
+			return 'G';
+		else if (e==3) 
+			return 'U';
+		else
+			return '!';
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/RequiresAnyCategoricalData.java b/Source/mesquite/categ/lib/RequiresAnyCategoricalData.java
new file mode 100644
index 0000000..c436317
--- /dev/null
+++ b/Source/mesquite/categ/lib/RequiresAnyCategoricalData.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresAnyCategoricalData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresExactlyCategoricalData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return   (CategoricalState.class.isAssignableFrom((Class)obj) || CategoricalData.class.isAssignableFrom((Class)obj));
+	}
+	public Class getAcceptedClass(){
+		return CategoricalState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/RequiresAnyDNAData.java b/Source/mesquite/categ/lib/RequiresAnyDNAData.java
new file mode 100644
index 0000000..c554239
--- /dev/null
+++ b/Source/mesquite/categ/lib/RequiresAnyDNAData.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.
+
+This version says "I need to receive DNA data".  This is different from OffersDNAState, which is used for sources to say that is what they can offer*/
+public class RequiresAnyDNAData extends CompatibilityTest {  
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresAnyDNAData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+	//	return  obj == DNAData.class || obj == DNAState.class || obj == RNAData.class || obj == RNAState.class; 
+return (((DNAData.class).isAssignableFrom((Class)obj)) || ((DNAState.class).isAssignableFrom((Class)obj)));
+	//	return  (((DNAData.class).isAssignableFrom((Class)obj)) || ((DNAState.class).isAssignableFrom((Class)obj)));
+		//To pass the test, the datatype MUST be a DNA or a subclass of DNA
+	}
+	public Class getAcceptedClass(){
+		return DNAState.class;
+	}
+}
+
diff --git a/Source/mesquite/categ/lib/RequiresAnyMolecularData.java b/Source/mesquite/categ/lib/RequiresAnyMolecularData.java
new file mode 100644
index 0000000..e9c036e
--- /dev/null
+++ b/Source/mesquite/categ/lib/RequiresAnyMolecularData.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresAnyMolecularData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresAnyMolecularData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) &&  !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		//To pass the test, the datatype MUST be a molecular or a subclass of molecular
+		return  (MolecularState.class.isAssignableFrom((Class)obj) || MolecularData.class.isAssignableFrom((Class)obj));
+	}
+	public Class getAcceptedClass(){
+		return MolecularState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/RequiresExactlyCategoricalData.java b/Source/mesquite/categ/lib/RequiresExactlyCategoricalData.java
new file mode 100644
index 0000000..8927834
--- /dev/null
+++ b/Source/mesquite/categ/lib/RequiresExactlyCategoricalData.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresExactlyCategoricalData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresExactlyCategoricalData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) &&  !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return  (CategoricalState.class == obj) || CategoricalData.class == obj;
+	}
+	public Class getAcceptedClass(){
+		return CategoricalState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/categ/lib/RequiresProteinData.java b/Source/mesquite/categ/lib/RequiresProteinData.java
new file mode 100644
index 0000000..04c2d06
--- /dev/null
+++ b/Source/mesquite/categ/lib/RequiresProteinData.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.categ.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresProteinData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresProteinData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) &&  !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return (((ProteinData.class).isAssignableFrom((Class)obj))) || ((ProteinState.class).isAssignableFrom((Class)obj));
+	}
+	public Class getAcceptedClass(){
+		return ProteinState.class;
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/AddCharsFromSource/AddCharsFromSource.java b/Source/mesquite/charMatrices/AddCharsFromSource/AddCharsFromSource.java
new file mode 100644
index 0000000..8d6310d
--- /dev/null
+++ b/Source/mesquite/charMatrices/AddCharsFromSource/AddCharsFromSource.java
@@ -0,0 +1,109 @@
+package mesquite.charMatrices.AddCharsFromSource;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AddCharsFromSource extends CategDataAlterer {
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Add Characters from Source...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Add Characters from Source";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Adds characters from a source of characters." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+
+	CharSourceCoordObed characterSourceTask;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//character source %%%%%%%%
+		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters (for " + getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		
+		characterSourceTask.initialize(data.getTaxa());
+		int maxNum = characterSourceTask.getNumberOfCharacters(data.getTaxa());
+		String s = "";
+		if (!MesquiteInteger.isCombinable(maxNum))
+			maxNum = 10000;
+		else 
+			s = " (" + maxNum + " available)";
+		int numChars = MesquiteInteger.queryInteger(containerOfModule(), "Number of characters", "Number of characters to add from " + characterSourceTask.getName() + s, 1, 1, maxNum);
+		if (!MesquiteInteger.isCombinable(numChars))
+			return false;
+		CharacterState cs = null;
+		for (int i = 0; i<numChars; i++){
+			CharacterDistribution dist = characterSourceTask.getCharacter(data.getTaxa(), i);
+			if (data.getStateClass() != dist.getStateClass()){
+				discreetAlert("Sorry, the source is supplying characters of a different type, and so can't be used");
+				return false;
+			}
+			data.addCharacters(data.getNumChars(), 1, false);
+			int ic = data.getNumChars()-1;
+			for (int it = 0; it<data.getNumTaxa(); it++){
+				cs = dist.getCharacterState(cs, it);
+				data.setState(ic, it, cs);
+			}
+		}
+		return true;
+	}
+
+	//	Double d = new Double(value);
+
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/AddDeleteData/32addChars.gif b/Source/mesquite/charMatrices/AddDeleteData/32addChars.gif
new file mode 100644
index 0000000..1d0315b
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/32addChars.gif differ
diff --git a/Source/mesquite/charMatrices/AddDeleteData/32addTaxa.gif b/Source/mesquite/charMatrices/AddDeleteData/32addTaxa.gif
new file mode 100644
index 0000000..38b73b1
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/32addTaxa.gif differ
diff --git a/Source/mesquite/charMatrices/AddDeleteData/64addChars.gif b/Source/mesquite/charMatrices/AddDeleteData/64addChars.gif
new file mode 100644
index 0000000..c189b2c
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/64addChars.gif differ
diff --git a/Source/mesquite/charMatrices/AddDeleteData/64addTaxa.gif b/Source/mesquite/charMatrices/AddDeleteData/64addTaxa.gif
new file mode 100644
index 0000000..2d1fc80
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/64addTaxa.gif differ
diff --git a/Source/mesquite/charMatrices/AddDeleteData/AddDeleteData.java b/Source/mesquite/charMatrices/AddDeleteData/AddDeleteData.java
new file mode 100644
index 0000000..1dbdfa1
--- /dev/null
+++ b/Source/mesquite/charMatrices/AddDeleteData/AddDeleteData.java
@@ -0,0 +1,382 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.AddDeleteData;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/*
+ * to do: - how to add to end of matrix using this tool?
+ */
+
+/* ======================================================================== */
+public class AddDeleteData extends DataWindowAssistantI implements KeyListener {
+	MesquiteWindow window = null;
+
+	/* ................................................................................................................. */
+	public String getName() {
+		return "Add/Delete Data";
+	}
+
+	public String getExplanation() {
+		return "Adds and deletes characters and taxa in a Character Matrix editor.  This can be done through the Add characters..., Add taxa..., and Delete Selected menu items and via the tools that add taxa and characters where touched.";
+	}
+
+	/* ................................................................................................................. */
+	MesquiteTable table;
+	CharacterData data;
+	TableTool addCharsTool;
+	TableTool addTaxaTool;
+	MesquiteCommand deleteCommand;
+	MesquiteMenuItemSpec addCharsMenuItem;
+
+	/* ................................................................................................................. */
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	public String getExpectedPath() {
+		return getPath() + "addTaxa.gif";
+	}
+
+	public void getSubfunctions() {
+		registerSubfunction(new FunctionExplanation(
+				"Add Characters",
+				"(A tool in the character matrix editor) Adds characters at the column touched",
+				null, getPath() + "addChars.gif"));
+		registerSubfunction(new FunctionExplanation(
+				"Add Taxa",
+				"(A tool in the character matrix editor) Adds taxa at the row touched",
+				null, getPath() + "addTaxa.gif"));
+		super.getSubfunctions();
+	}
+
+	/* ................................................................................................................. */
+	public boolean startJob(String arguments, Object condition,
+			boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			addCharsTool = new TableTool(this, "addChars", getPath(),
+					"addChars.gif", 7, 7, "Add Characters",
+					"This tool inserts new characters", MesquiteModule
+							.makeCommand("addCharacters", this), null, null);
+			addCharsTool.setWorksOnColumnNames(true);
+			addCharsTool.setWorksBeyondLastColumn(true);
+			addCharsTool.setIsBetweenRowColumnTool(true);
+			addCharsTool.setWorksAsArrowOnRowColumnNumbers(false);
+			((MesquiteWindow) containerOfModule()).addTool(addCharsTool);
+			addTaxaTool = new TableTool(this, "addTaxa", getPath(),
+					"addTaxa.gif", 7, 7, "Add Taxa",
+					"This tool inserts new taxa", MesquiteModule.makeCommand(
+							"addTaxa", this), null, null);
+			addTaxaTool.setWorksOnRowNames(true);
+			addTaxaTool.setWorksBeyondLastRow(true);
+			addTaxaTool.setWorksAsArrowOnRowColumnNumbers(false);
+			addTaxaTool.setIsBetweenRowColumnTool(true);
+			((MesquiteWindow) containerOfModule()).addTool(addTaxaTool);
+			window = (MesquiteWindow) containerOfModule();
+		}
+
+		addCharsMenuItem = addMenuItem("Add characters...", makeCommand(
+				"addCharactersToEnd", this));
+		addMenuItem("Add taxa...", makeCommand("addTaxaToEnd", this));
+		addMenuItem("Delete Selected Chars or Taxa", deleteCommand = makeCommand("deleteSelected", this));
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isSubstantive() {
+		return true;
+	}
+
+	public void keyTyped(KeyEvent e) {
+		int mod = MesquiteEvent.getModifiers(e);
+		if (!MesquiteEvent.commandOrControlKeyDown(mod)) {
+			MesquiteWindow w = null;
+			if (containerOfModule() instanceof MesquiteWindow)
+				w = (MesquiteWindow) containerOfModule();
+			if (w.getMode() != InfoBar.GRAPHICS || w.annotationHasFocus())
+				return;
+			if ((table == null || (table.anythingSelected() && !table
+					.editingAnything()))
+					&& (e.getKeyChar() == '\b'
+							|| e.getKeyCode() == KeyEvent.VK_BACK_SPACE || e
+							.getKeyCode() == KeyEvent.VK_DELETE)) {
+				deleteCommand.doItMainThread(null, "", this);
+			}
+		}
+
+	}
+
+	public void keyPressed(KeyEvent e) {
+	}
+
+	public void keyReleased(KeyEvent e) {
+	}
+
+	/* ................................................................................................................. */
+	public void endJob() {
+		if (containerOfModule() != null
+				&& ((MesquiteWindow) containerOfModule()) != null)
+			MesquiteWindow.removeKeyListener(
+					((MesquiteWindow) containerOfModule()), this);
+		super.endJob();
+	}
+
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		this.table = table;
+		this.data = data;
+		if (containerOfModule() != null
+				&& ((MesquiteWindow) containerOfModule()) != null)
+			MesquiteWindow.addKeyListener(
+					((MesquiteWindow) containerOfModule()), this);
+		addCharsMenuItem.setEnabled(data.canAddCharacters());
+		addCharsTool.setEnabled(data.canAddCharacters());
+	}
+
+	private void deleteSelected(boolean byCommand) {
+		if (table != null && data != null) {
+			if (!byCommand
+					&& (table.editingAnything() || !(table.anyColumnSelected() || table
+							.anyRowSelected())))
+				return;
+			if (table.anyColumnSelected()) {
+				if (!MesquiteThread.isScripting()
+						&& !AlertDialog
+								.query(
+										containerOfModule(),
+										"Delete characters?",
+										"Are you sure you want to delete the selected characters?",
+										"Yes", "No"))
+					return;
+				Vector blocks = new Vector();
+				while (table.anyColumnSelected()) {
+					int lastOfBlock = table.lastColumnSelected();
+					int firstOfBlock = table.startOfLastColumnBlockSelected();
+					if (lastOfBlock >= 0) {
+						for (int i = firstOfBlock; i <= lastOfBlock; i++)
+							table.deselectColumn(i);
+						data.deleteParts(firstOfBlock, lastOfBlock
+								- firstOfBlock + 1);
+						data.deleteInLinked(firstOfBlock, lastOfBlock
+								- firstOfBlock + 1, false);
+						blocks.addElement(new int[] { firstOfBlock,
+								lastOfBlock - firstOfBlock + 1 }); // do as
+																	// series of
+																	// contiguous
+																	// blocks
+					}
+				}
+
+				if (blocks.size() == 1) {
+					data.notifyListeners(this, new Notification(
+							MesquiteListener.PARTS_DELETED, (int[]) blocks
+									.elementAt(0))); // do as series of
+														// contiguous blocks
+					data.notifyInLinked(new Notification(
+							MesquiteListener.PARTS_DELETED, (int[]) blocks
+									.elementAt(0))); // do as series of
+														// contiguous blocks
+				} else {
+					data.notifyListeners(this, new Notification(
+							MesquiteListener.PARTS_DELETED)); // do as series
+																// of contiguous
+																// blocks
+					data.notifyInLinked(new Notification(
+							MesquiteListener.PARTS_DELETED)); // do as series
+																// of contiguous
+																// blocks
+				}
+			}
+			if (table.anyRowSelected()) {
+				Bits rows = table.getRowsSelected();
+				if (rows.numBitsOn() == data.getTaxa().getNumTaxa()) {
+					discreetAlert("You cannot delete all of the taxa; the command will be ignored");
+					return;
+				}
+				if (data.getTaxa().isEditInhibited()){
+					discreetAlert("You cannot delete taxa; the taxa block is locked.");
+					return;
+				}
+				if (!MesquiteThread.isScripting()
+						&& !AlertDialog
+								.query(
+										containerOfModule(),
+										"Delete taxa?",
+										"Are you sure you want to delete the selected taxa?",
+										"Yes", "No"))
+					return;
+
+				for (int i = table.getNumRows() - 1; i >= 0; i--) {
+					if (rows.isBitOn(i)) {
+						data.getTaxa().deleteTaxa(i, 1, false);
+					}
+				}
+				Notification nn;
+
+				data.getTaxa().notifyListeners(this,
+						nn = new Notification(MesquiteListener.PARTS_DELETED));// do
+																				// as
+																				// series
+																				// of
+																				// contiguous
+																				// blocks
+				data.notifyListeners(this, new Notification(
+						MesquiteListener.PARTS_CHANGED)
+						.setNotificationNumber(nn.getNotificationNumber()));// do
+																			// as
+																			// series
+																			// of
+																			// contiguous
+																			// blocks
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments,
+			CommandChecker checker) {
+		if (checker
+				.compare(
+						this.getClass(),
+						"Adds characters to data matrix",
+						"[Character # before which new character are to be added] [row on which touched] [how many new characters]",
+						commandName, "addCharacters")) {
+			if (data != null && data.canAddCharacters()) {
+
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column = MesquiteInteger.fromString(arguments, io);
+				int row = MesquiteInteger.fromString(arguments, io);
+				if (column >= -1) {
+					// column--; //to put characters before one touched
+					int howMany = MesquiteInteger.queryInteger(
+							containerOfModule(), "Add characters",
+							"How many characters to add?", 1, 1,
+							MesquiteInteger.infinite);
+					if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+						UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED,data);
+						data.resetJustAdded();
+						UndoReference undoReference = new UndoReference(undoInstructions, null);
+						if (data.addParts(column, howMany)) {
+							data.addInLinked(column, howMany, true);
+							data.notifyListeners(this, new Notification(
+									MesquiteListener.PARTS_ADDED, new int[] {
+											column, howMany }, undoReference));
+						}
+					}
+				} else if (column == -2) {
+					int howMany = MesquiteInteger.queryInteger(
+							containerOfModule(), "Add characters",
+							"How many characters to add?", 1, 1,
+							MesquiteInteger.infinite);
+					if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+						UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED,data);
+						data.resetJustAdded();
+						UndoReference undoReference = new UndoReference(undoInstructions, null);
+						if (data.addParts(table.numColumnsTotal, howMany)) {
+							data.addInLinked(table.numColumnsTotal, howMany,
+									true);
+							data.notifyListeners(this, new Notification(
+									MesquiteListener.PARTS_ADDED, new int[] {
+											table.numColumnsTotal, howMany }, undoReference));
+						}
+					}
+				}
+			}
+		} else if (checker
+				.compare(
+						this.getClass(),
+						"Adds taxa to block of taxa",
+						"[column on which touched] [Taxon # before which new taxa are to be added] [how many new taxa]",
+						commandName, "addTaxa")) {
+			if (data != null) {
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column = MesquiteInteger.fromString(arguments, io);
+				int row = MesquiteInteger.fromString(arguments, io);
+				if (row >= -1) {
+					// row--; //to put taxa before one touched
+					int howMany = MesquiteInteger.queryInteger(
+							containerOfModule(), "Add taxa",
+							"How many taxa to add?", 1, 1, Taxa.MAXNUMTAXA
+									- data.getNumTaxa());
+					if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+						data.getTaxa().addTaxa(row, howMany, true);
+					}
+				} else if (row == -2) {
+					int howMany = MesquiteInteger.queryInteger(
+							containerOfModule(), "Add taxa",
+							"How many taxa to add?", 1, 1, Taxa.MAXNUMTAXA
+									- data.getNumTaxa());
+					if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+						data.getTaxa().addTaxa(table.numRowsTotal, howMany,
+								true);
+					}
+				}
+			}
+		} else if (checker.compare(this.getClass(),
+				"Appends new character to end of matrix", "[How many to add]",
+				commandName, "addCharactersToEnd")) {
+			if (data != null && data.canAddCharacters()) {
+				MesquiteInteger io = new MesquiteInteger(0);
+				int howMany = MesquiteInteger.fromString(arguments, io);
+				if (!MesquiteInteger.isCombinable(howMany))
+					howMany = MesquiteInteger.queryInteger(containerOfModule(),
+							"Add characters", "How many characters to add?", 1,
+							1, MesquiteInteger.infinite);
+				if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+					UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED,data);
+					data.resetJustAdded();
+					UndoReference undoReference = new UndoReference(undoInstructions, null);
+					data.addParts(data.getNumChars(), howMany);
+					data.addInLinked(data.getNumChars(), howMany, true);
+					data.notifyListeners(this, new Notification( MesquiteListener.PARTS_ADDED, new int[] {data.getNumChars(), howMany }, undoReference));
+				}
+			}
+		} else if (checker.compare(this.getClass(),
+				"Appends new taxa to end of block of taxa",
+				"[how many to add]", commandName, "addTaxaToEnd")) {
+			if (data != null) {
+				MesquiteInteger io = new MesquiteInteger(0);
+				int howMany = MesquiteInteger.fromString(arguments, io);
+				if (!MesquiteInteger.isCombinable(howMany))
+					howMany = MesquiteInteger.queryInteger(containerOfModule(),
+							"Add taxa", "How many taxa to add?", 1, 1,
+							Taxa.MAXNUMTAXA - data.getNumTaxa());
+				if (MesquiteInteger.isCombinable(howMany) && howMany > 0) {
+					int wh = data.getNumTaxa();
+					data.getTaxa().addTaxa(wh, howMany, true);
+				}
+			}
+		} else if (checker.compare(this.getClass(),
+				"Deletes seleted characters or taxa", null, commandName,
+				"deleteSelected")) {
+			deleteSelected(true);
+		} else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+}
+
diff --git a/Source/mesquite/charMatrices/AddDeleteData/addChars.gif b/Source/mesquite/charMatrices/AddDeleteData/addChars.gif
new file mode 100644
index 0000000..6cc9ad9
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/addChars.gif differ
diff --git a/Source/mesquite/charMatrices/AddDeleteData/addTaxa.gif b/Source/mesquite/charMatrices/AddDeleteData/addTaxa.gif
new file mode 100644
index 0000000..e53465b
Binary files /dev/null and b/Source/mesquite/charMatrices/AddDeleteData/addTaxa.gif differ
diff --git a/Source/mesquite/charMatrices/AlterAllMatrices/AlterAllMatrices.java b/Source/mesquite/charMatrices/AlterAllMatrices/AlterAllMatrices.java
new file mode 100644
index 0000000..a258998
--- /dev/null
+++ b/Source/mesquite/charMatrices/AlterAllMatrices/AlterAllMatrices.java
@@ -0,0 +1,140 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.AlterAllMatrices; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AlterAllMatrices extends FileProcessor {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(DataAlterer.class, getName() + " needs a particular method to alter data, e.g. in the Character Matrix Editor.",
+				null);
+		e2.setPriority(2);
+	}
+	MesquiteTable table;
+	CharacterData data;
+	MesquiteSubmenuSpec mss= null;
+	DataAlterer alterTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			alterTask = (DataAlterer)hireNamedEmployee(DataAlterer.class, arguments);
+			if (alterTask == null)
+				return sorry(getName() + " couldn't start because the requested data alterer wasn't successfully hired.");
+		}
+		else if (!MesquiteThread.isScripting()) {
+			alterTask = (DataAlterer)hireEmployee(DataAlterer.class, "Transformer of matrices");
+			if (alterTask == null)
+				return sorry(getName() + " couldn't start because no tranformer module obtained.");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+ 	public String getNameForProcessorList() {
+ 		if (alterTask != null)
+ 			return getName() + "(" + alterTask.getName() + ")";
+ 		return getName();
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true; //not really, but to force checking of prerelease
+   	 }
+ 	/*.................................................................................................................*/
+ 	public Snapshot getSnapshot(MesquiteFile file) { 
+ 		Snapshot temp = new Snapshot();
+ 		temp.addLine("setDataAlterer ", alterTask);  
+ 		return temp;
+ 	}
+ 	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+ 		if (checker.compare(this.getClass(), "Sets the module that alters data", "[name of module]", commandName, "setDataAlterer")) {
+ 			DataAlterer temp =  (DataAlterer)replaceEmployee(DataAlterer.class, arguments, "Data alterer", alterTask);
+ 			if (temp!=null) {
+				alterTask = temp;
+ 				return alterTask;
+ 			}
+ 
+ 		}
+ 		else
+ 			return  super.doCommand(commandName, arguments, checker);
+ 		return null;
+ 	}
+
+   	/** if returns true, then requests to remain on even after alterFile is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter file. */
+   	public boolean processFile(MesquiteFile file){
+   		if (alterTask == null)
+   			return false;
+   		MesquiteProject proj = file.getProject();
+   		if (proj == null)
+   			return false;
+   		boolean success = false;
+   		CompatibilityTest test = alterTask.getCompatibilityTest();
+   		for (int im = 0; im < proj.getNumberCharMatrices(file); im++){
+   			CharacterData data = proj.getCharacterMatrix(file, im);
+   			if (test.isCompatible(data.getStateClass(), getProject(), this)) {
+   				success = true;
+   				alterTask.alterData(data, null, null);  // do not measure success based upon whether data were altered.
+   			}
+   		}
+   			
+   		return success;
+   	}
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Alter All Matrices";
+	 }
+		/*.................................................................................................................*/
+	 public String getNameAndParameters() {
+		 if (alterTask==null)
+			 return "Alter All Matrices";
+		 else
+			 return "Alter All Matrices (" + alterTask.getName() + ")";
+	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages data-transforming modules to transform all matrices in a file." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/AlterData/AlterData.java b/Source/mesquite/charMatrices/AlterData/AlterData.java
new file mode 100644
index 0000000..5509628
--- /dev/null
+++ b/Source/mesquite/charMatrices/AlterData/AlterData.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.AlterData; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AlterData extends DataWindowAssistantI {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(DataAlterer.class, getName() + " needs a particular method to alter data in the Character Matrix Editor.",
+		"These options are available in the Alter/Transform submenu of the Matrix menu of the Character Matrix Editor");
+		e2.setPriority(2);
+	}
+	MesquiteTable table;
+	CharacterData data;
+	MesquiteSubmenuSpec mss= null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		mss = addSubmenu(null, "Alter/Transform", makeCommand("doAlter",  this));
+		mss.setList(DataAlterer.class);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		mss.setCompatibilityCheck(data.getStateClass());
+		resetContainingMenuBar();
+		
+	}
+	
+	/* possible alterers:
+		recode (as in MacClade)
+		reverse (sequences) �
+		shuffle �
+		random fill �
+		fill (via dialog) �
+		search and replace
+		
+	DNA only:
+		complement �
+		
+	continuous only:
+		log transform �
+		scale �
+		standardize (mean 0, variance 1)
+	*/
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Hires module to alter the data matrix", "[name of module]", commandName, "doAlter")) {
+   	 		if (table!=null && data !=null){
+	    	 	if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+	    	 		return null;
+	    	 	}
+	    	 	DataAlterer tda= (DataAlterer)hireNamedEmployee(DataAlterer.class, arguments);
+				if (tda!=null) {
+					MesquiteWindow w = table.getMesquiteWindow();
+					UndoReference undoReference = new UndoReference();
+					AlteredDataParameters alteredDataParameters = new AlteredDataParameters();
+					if (MesquiteTrunk.debugMode)
+						logln("Memory available before data alterer invoked: " + MesquiteTrunk.getMaxAvailableMemory());
+					boolean a = tda.alterData(data, table, undoReference, alteredDataParameters);
+					if (MesquiteTrunk.debugMode)
+						logln("Memory available after data alterer invoked: " + MesquiteTrunk.getMaxAvailableMemory());
+
+	 	   			if (a) {
+	 	   				table.repaintAll();
+	 	   				Notification notification = new Notification(MesquiteListener.DATA_CHANGED, alteredDataParameters.getParameters(), undoReference);
+	 	   				if (alteredDataParameters.getSubcodes()!=null)
+	 	   					notification.setSubcodes(alteredDataParameters.getSubcodes());
+						data.notifyListeners(this, notification);
+					}
+					if (!tda.pleaseLeaveMeOn()) {
+						fireEmployee(tda);
+					}
+				}
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Alter Data";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages data-transforming modules." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/AnnotPanel/AnnotPanel.java b/Source/mesquite/charMatrices/AnnotPanel/AnnotPanel.java
new file mode 100644
index 0000000..ffc6fe1
--- /dev/null
+++ b/Source/mesquite/charMatrices/AnnotPanel/AnnotPanel.java
@@ -0,0 +1,538 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.AnnotPanel; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import java.awt.image.*;
+
+
+/** ======================================================================== */
+public class AnnotPanel extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerTaxa, CellColorerMatrix, AnnotPanelOwner {
+	CharacterData data;
+	MesquiteTable table;
+	boolean defaultNewEachCell = false;
+	boolean defaultAutoAttach = false;
+	AnnotationsPanel panel = null;
+	String findString = null;
+	int findNumber = 0;
+	int currentColumn = -1;
+	int currentRow = -1;
+	int currentNoteNumber = -1;
+	MesquiteSubmenuSpec annotMenu;
+	MesquiteBoolean showPanel;
+	MesquiteButton annotButton;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		showPanel = new MesquiteBoolean(false);
+		annotButton = new MesquiteButton(this, makeCommand("togglePanel",  this), null, true, MesquiteModule.getRootImageDirectoryPath()  + "annot.gif", 12, 16);
+		annotButton.setShowBackground(false);
+		annotButton.setButtonExplanation("Show/Hide Annotations Panel");
+		addCheckMenuItem(null, "Show Annotations Panel", makeCommand("togglePanel", this), showPanel);
+
+		annotMenu = addSubmenu(null, "Annotations");
+		MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Find Annotation", MesquiteModule.makeCommand("searchAnnotations", this));
+		mmi.setShortcut(KeyEvent.VK_3);
+		mmi = addItemToSubmenu(null, annotMenu, "Find Again", MesquiteModule.makeCommand("searchAgain", this));
+		mmi.setShortcut(KeyEvent.VK_8);
+		addItemToSubmenu(null, annotMenu, "Move Footnotes to ANNOTATIONs", makeCommand("moveFootnotes",  this));
+		addItemToSubmenu(null, annotMenu, "Copy Footnotes to ANNOTATIONs", makeCommand("copyFootnotes",  this));
+		addItemToSubmenu(null, annotMenu, "Copy ANNOTATIONs to Footnotes", makeCommand("copyAnnotations",  this));
+
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		setPanel();
+	}
+	public MesquiteModule getModule(){
+		return this;
+	}
+	/*.................................................................................................................*/
+	void setPanel(){
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof TableWindow){
+			((TableWindow)f).addControlButton(annotButton);
+			if (showPanel.getValue()){
+				if (panel == null) {
+					panel = new AnnotationsPanel(this);
+					addItemToSubmenu(null, annotMenu, "-", null);
+					MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Make Item Label", MesquiteModule.makeCommand("makeItemLabel", panel));
+					mmi.setShortcut(KeyEvent.VK_L);
+					addItemToSubmenu(null, annotMenu, "Recover Offscreen Labels", MesquiteModule.makeCommand("recoverLostLabels", panel));
+					resetContainingMenuBar();
+				}
+				((TableWindow)f).addSidePanel(panel, 300);
+				panel.setVisible(true);
+				if (table.singleTableCellSelected()){
+					Dimension d = table.getFirstTableCellSelected();
+					focusInCell(d.width, d.height);
+				}
+				else 
+					focusInCell(-2,-2);
+
+			}
+			else {
+				if (panel != null)
+					((TableWindow)f).removeSidePanel(panel);
+			}
+
+		}
+	}
+	public boolean hasDisplayModifications(){
+		return false;
+	}
+	public void panelGoAway(Panel p){
+		showPanel.setValue(false);
+		setPanel();
+	}
+	/*.................................................................................................................*/
+	void showNote(AttachedNotesVector aim, int column, int row, int noteNumber){
+		if (column<-1 || row < -1 || data == null || panel == null || column>= data.getNumChars() || row >= data.getNumTaxa()){
+			if (panel != null){
+				if (panel.isAttachable()){
+					panel.setNotes(null, "", "", column, row, noteNumber);
+					panel.setAttachable(false);
+				}
+			}
+			return;
+		}
+		if (panel != null)
+			panel.setAttachable(true);
+		if (currentColumn == column && currentRow == row && noteNumber == currentNoteNumber)
+			return;
+		currentColumn  = column;
+		currentRow = row;
+		String s = null;
+		String loc = null;
+		if (column >= 0 || row >= 0){
+			if (column<0){
+				s = "taxon \"" + data.getTaxa().getTaxonName(row) + "\"";
+				loc = "t." + Integer.toString(row+1);
+			}
+			else if (row<0){
+				if (data.characterHasName(column))
+					s = "character \"" + data.getCharacterName(column) + "\"";
+				else
+					s = data.getCharacterName(column);
+				loc =  "c." + Integer.toString(column+1);
+			}
+			else {
+				if (data.characterHasName(column))
+					s = "character \"" + data.getCharacterName(column) + "\"";
+				else
+					s = data.getCharacterName(column);
+				s += " in taxon \"" + data.getTaxa().getTaxonName(row) + "\"";
+				loc = "t." + Integer.toString(row+1) + "/c." + Integer.toString(column+1);
+			}
+		}
+		if (!panel.isVisible()){
+			showPanel.setValue(true);
+			setPanel();
+		}
+		panel.setNotes(aim, s, loc, column, row, noteNumber);
+		currentNoteNumber = noteNumber;
+		/*
+		if (!table.anythingSelected() || table.singleTableCellSelected()){
+			table.deselectAll();
+			table.selectCell(column, row);
+			table.setFocusedCell(column, row);
+
+			MesquiteWindow w = MesquiteWindow.windowOfItem(table);
+			if (w !=null)
+				w.setExplanation("Annotation displayed in separate window for " + s);
+		}
+		 */
+
+	}
+	void showNote(int column, int row, int noteNumber){
+		if (column<-1 || row < -1 || data == null || panel == null || column>= data.getNumChars() || row >= data.getNumTaxa()){
+			if (panel != null){
+				if (panel.isAttachable()){
+					panel.setNotes(null, "", "", column, row, noteNumber);
+					panel.setAttachable(false);
+				}
+			}
+			return;
+		}
+		if (panel != null)
+			panel.setAttachable(true);
+		AttachedNotesVector hL = null;
+		if (column<0)  //taxon
+			hL = (AttachedNotesVector)data.getTaxa().getAssociatedObject(notesNameRef, row);
+		else if (row < 0) //character
+			hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, column);
+		else 
+			hL = (AttachedNotesVector)data.getCellObject(notesNameRef, column, row);
+		showNote(hL, column, row, noteNumber);
+	}
+
+	boolean findAndShowNote(String searchString, int i){
+		Taxa taxa = data.getTaxa();
+
+		int count = 0;
+		//search taxa
+		for (int it = 0; it<taxa.getNumTaxa(); it++) {
+			AttachedNotesVector hL = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, it);
+			if (hL != null){
+				for (int noteNum = 0; noteNum<hL.getNumNotes(); noteNum++){
+					AttachedNote note = hL.getAttachedNote(noteNum);
+					if (note.containsString(searchString)){
+						if (count == i) {
+							showNote(-1, it, noteNum);
+							return true;
+						}
+						count++;
+					}
+				}
+			}
+		}
+		//search characters
+		for (int ic = 0; ic<data.getNumChars(); ic++) {
+			AttachedNotesVector hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+			if (hL != null){
+				for (int noteNum = 0; noteNum<hL.getNumNotes(); noteNum++){
+					AttachedNote note = hL.getAttachedNote(noteNum);
+					if (note.containsString(searchString)){
+						if (count == i) {
+							showNote(ic, -1, noteNum);
+							return true;
+						}
+						count++;
+					}
+				}
+			}
+		}
+		//search cells
+		for (int ic = 0; ic<data.getNumChars(); ic++) {
+			for (int it = 0; it<taxa.getNumTaxa(); it++) {
+
+				AttachedNotesVector hL = (AttachedNotesVector)data.getCellObject(notesNameRef, ic, it);
+				if (hL != null){
+					for (int noteNum = 0; noteNum<hL.getNumNotes(); noteNum++){
+						AttachedNote note = hL.getAttachedNote(noteNum);
+						if (note.containsString(searchString)){
+							if (count == i) {
+								showNote(ic, it, noteNum);
+								return true;
+							}
+							count++;
+						}
+					}
+				}
+			}
+		}
+		MesquiteMessage.println("There are no more occurrences of \"" + searchString + "\"");
+		MesquiteMessage.beep();
+		return false;
+
+	}
+
+	void transferFootnotes(boolean move){
+		Taxa taxa = data.getTaxa();
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		for (int it = 0; it<numTaxa; it++) {  //taxa
+			String s = taxa.getAnnotation(it);
+			if (s != null){
+				CommandRecord.tick("Moving footnote for taxon " + (it+1));
+				AttachedNotesVector anv = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, it);
+				if (anv == null) {
+					anv = new AttachedNotesVector(taxa);
+					taxa.setAssociatedObject(notesNameRef, it, anv);
+				}
+				AttachedNote hL = new AttachedNote();
+				hL.setComment(new String(s), false);
+				anv.addNoteFirst(hL, false);
+				if (move)
+					taxa.setAnnotation(it, null);
+			}
+		}
+
+		for (int ic = 0; ic<numChars; ic++) { //characters
+			String s = data.getAnnotation(ic);
+			if (s != null){
+				CommandRecord.tick("Moving footnote for character " + (ic+1));
+				AttachedNotesVector anv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+				if (anv == null) {
+					anv = new AttachedNotesVector(data);
+					data.setAssociatedObject(notesNameRef, ic, anv);
+				}
+
+				AttachedNote hL = new AttachedNote();
+				hL.setComment(new String(s), false);
+				anv.addNoteFirst(hL, false);
+				if (move)
+					data.setAnnotation(ic, null);
+			}
+		}
+		for (int ic = 0; ic<numChars; ic++) { //characters
+			CommandRecord.tick("Moving footnotes for character " + (ic+1));
+			for (int it = 0; it<numTaxa; it++) {  //taxa
+				String s = data.getAnnotation(ic, it);
+				if (s != null){
+					AttachedNotesVector anv = (AttachedNotesVector)data.getCellObject(notesNameRef, ic, it);
+					if (anv == null) {
+						anv = new AttachedNotesVector(data);
+						data.setCellObject(notesNameRef, ic, it, anv);
+						data.setCellObjectDisplay(ic, it);
+					}
+					AttachedNote hL = new AttachedNote();
+					hL.setComment(new String(s), false);
+					anv.addNoteFirst(hL, false);
+					if (move)
+						data.setAnnotation(ic, it, null);
+				}
+			}
+		}
+		taxa.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_ADDED));
+		data.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_ADDED));
+
+	}
+	/*.................................................................................................................*/
+	public void transferAnnotations(){
+		Taxa taxa = data.getTaxa();
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		for (int it = 0; it<numTaxa; it++) {  //taxa
+			AttachedNotesVector anv = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, it);
+			if (anv != null && anv.getNumNotes()>0) {
+				CommandRecord.tick("Moving footnotes for taxon " + (it+1));
+				AttachedNote note = anv.getAttachedNote(0);
+				if (note.getComment()!=null)
+					taxa.setAnnotation(it, note.getComment());
+			}
+
+		}
+
+		for (int ic = 0; ic<numChars; ic++) { //characters
+			AttachedNotesVector anv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+			if (anv != null && anv.getNumNotes()>0) {
+				CommandRecord.tick("Moving annotation for character " + (ic+1));
+				AttachedNote note = anv.getAttachedNote(0);
+				if (note.getComment()!=null)
+					data.setAnnotation(ic, note.getComment());
+			}
+		}
+		for (int ic = 0; ic<numChars; ic++) { //characters
+			CommandRecord.tick("Moving annotations for character " + (ic+1));
+			for (int it = 0; it<numTaxa; it++) {  //taxa
+				AttachedNotesVector anv = (AttachedNotesVector)data.getCellObject(notesNameRef, ic, it);
+				if (anv != null && anv.getNumNotes()>0) {
+					AttachedNote note = anv.getAttachedNote(0);
+					if (note.getComment()!=null)
+						data.setAnnotation(ic, it, note.getComment());
+				}
+			}
+		}
+		taxa.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_ADDED));
+		data.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_ADDED));
+
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		//removePanel;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("togglePanel " + showPanel.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not the annotations panel is shown", "[on = shown; off]", commandName, "togglePanel")) {
+			showPanel.toggleValue(parser.getFirstToken(arguments));
+			setPanel();
+		}
+		else if (checker.compare(this.getClass(),  "Moves single footnotes to multiple note ANNOTATIONs system", null, commandName, "moveFootnotes")) {
+			if (!AlertDialog.query(containerOfModule(), "Move Notes?", "Are you sure you want to move all of the footnotes into the new multiple note ANNOTATIONs system?  The old footnotes will be deleted.  You can copy the notes back into the old footnotes system by selecting \"Copy ANNOTATIONs to Footnotes\"", "OK", "Cancel", -1))
+				return null;
+			transferFootnotes(true);
+		}
+		else if (checker.compare(this.getClass(),  "Copies single footnotes to multiple note ANNOTATIONs system", null, commandName, "copyFootnotes")) {
+			if (!AlertDialog.query(containerOfModule(), "Copy Notes?", "Are you sure you want to copy all of the footnotes into the new multiple note ANNOTATIONs system?", "OK", "Cancel", -1))
+				return null;
+			transferFootnotes(false);
+		}
+		else if (checker.compare(this.getClass(),  "Copies ANNOTATIONs into old footnotes system", null, commandName, "copyAnnotations")) {
+			if (!AlertDialog.query(containerOfModule(), "Copy Annotations?", "Are you sure you want to copy the \"Comments\" field of the first note of each cell of the matrix into the old footnotes system?  If there is a comment, then any existing footnote for that cell will be replaced by the comment.", "OK", "Cancel", -1))
+				return null;
+			transferAnnotations();
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAnnotations")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			String temp = MesquiteString.queryString(containerOfModule(), "Search annotations", "Search annotations of cells of matrix to find the following string.  Comments, references and labels of images will be searched.", findString, 2);
+			if (StringUtil.blank(temp)) {
+				return null;
+			}
+			findString = temp;
+			findNumber = 0;
+			if (!findAndShowNote(findString, findNumber))
+				findNumber = 0;
+			else
+				findNumber = 1;
+
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAgain")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			if (StringUtil.blank(findString))
+				return null;
+			if (!findAndShowNote(findString, findNumber))				findNumber = 0;
+			else
+				findNumber++;
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public AttachedNotesVector makeNotesVector(AnnotationsPanel w){
+		//attach image to window w
+		int column = currentColumn;
+		int row = currentRow;
+		AttachedNotesVector aiv = null;
+		if (column<0) {
+			//taxon
+			aiv = (AttachedNotesVector)data.getTaxa().getAssociatedObject(notesNameRef, row);
+			if (aiv == null)
+				aiv = new AttachedNotesVector(data.getTaxa());
+			data.getTaxa().setAssociatedObject(notesNameRef, row, aiv);
+		}
+		else if (row < 0){
+			//character
+			aiv = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, column);
+			if (aiv == null)
+				aiv = new AttachedNotesVector(data);
+			data.setAssociatedObject(notesNameRef, column, aiv);
+		}
+		else {
+			aiv = (AttachedNotesVector)data.getCellObject(notesNameRef, column, row);
+			if (aiv == null)
+				aiv = new AttachedNotesVector(data);
+			data.setCellObject(notesNameRef, column, row, aiv);
+			data.setCellObjectDisplay(column, row);
+		}
+		return aiv;
+	}
+	public void chooseAndAttachImage(AttachedNote hL, boolean local){
+		if (hL == null)
+			return;
+		//attach image to window w
+
+		hL.attachImage(this, local);
+		showNote(currentColumn, currentRow, currentNoteNumber);
+		if (table != null)
+			table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		if (legend == null) {
+			legend = new ColorRecord[2];
+			legend[0] = new ColorRecord(Color.white, "No Annotations");
+			legend[1] = new ColorRecord(ColorDistribution.veryLightGreen, "Annotations attached");
+		}
+		return legend;
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if (data == null)
+			return null;
+		else if (ic== -1 && data.getTaxa().getAssociatedObject(notesNameRef, it)!=null){ //taxon
+			return ColorDistribution.veryLightGreen;
+		}
+		else if (it == -1 && data.getAssociatedObject(notesNameRef, ic) !=null){ //character
+			return ColorDistribution.veryLightGreen;
+		}
+		else if (data.getCellObject(notesNameRef, ic, it) !=null)
+			return ColorDistribution.veryLightGreen;
+		else {
+			return null;
+		}
+
+	}
+	public String getCellString(int ic, int it){
+		if (data == null || !isActive())
+			return null;
+		else if (ic== -1 && data.getTaxa().getAssociatedObject(notesNameRef, it)!=null){ //taxon
+			return "Cell has annotation(s) attached";
+		}
+		else if (it == -1 && data.getAssociatedObject(notesNameRef, ic) !=null){ //character
+			return "Cell has annotation(s) attached";
+		}
+		else if (data.getCellObject(notesNameRef, ic, it) !=null)
+			return "Cell has annotation(s) attached";
+		else {
+			return "Cell lacks annotations";
+		}
+
+	}
+	int count = 0;
+	public void focusInCell(int ic, int it){
+		if (data == null)
+			return;
+		if (panel == null || panel.isVisible())
+			showNote(ic, it, 0);
+		return;
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Annotation Attached";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Annotation Panel module";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides tools with which to attach notes (including images) to cells of the matrix and show them.";
+	}
+}
+
+/* ======================================================================== */
+
+
diff --git a/Source/mesquite/charMatrices/AnnotPanel/annot.gif b/Source/mesquite/charMatrices/AnnotPanel/annot.gif
new file mode 100644
index 0000000..292ead3
Binary files /dev/null and b/Source/mesquite/charMatrices/AnnotPanel/annot.gif differ
diff --git a/Source/mesquite/charMatrices/BasicDataWindowCoord/BasicDataWindowCoord.java b/Source/mesquite/charMatrices/BasicDataWindowCoord/BasicDataWindowCoord.java
new file mode 100644
index 0000000..eadb8b2
--- /dev/null
+++ b/Source/mesquite/charMatrices/BasicDataWindowCoord/BasicDataWindowCoord.java
@@ -0,0 +1,273 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.BasicDataWindowCoord; 
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Coordinates the display of the spreadsheet editor window for character matrices.  This doesn't actually make the window (see BasicDataWindowMaker). */
+public class BasicDataWindowCoord extends FileInit {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DataWindowMaker.class, "Character Matrix Editors display character matrices to the user.", 
+		"You may request a character matrix editor by selecting the Character Matrix item under the Characters menu");
+
+		e.setAsEntryPoint("showDataWindow " + 0);
+	}
+	MesquiteSubmenuSpec elementsSubmenu, newViewSubmenu;
+	MesquiteMenuItemSpec cadw = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		elementsSubmenu = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Character Matrix Editor", makeCommand("showDataWindow",  this));
+		elementsSubmenu.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		newViewSubmenu = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Extra Matrix Editor", makeCommand("showExtraDataWindow",  this));
+		newViewSubmenu.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		cadw = getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "Close All Character Matrix Editors", makeCommand("closeAllMatrixWindows",  this));
+		cadw.setEnabled(false);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		elementsSubmenu.setList( getProject().datas);
+		newViewSubmenu.setList( getProject().datas);
+	}
+	String dataRef(CharacterData d, boolean internal){
+		if (internal)
+			return getProject().getCharMatrixReferenceInternal(d);
+		return getProject().getCharMatrixReferenceExternal(d);
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns command to hire employee if clonable*/
+	public String getClonableEmployeeCommand(MesquiteModule employee){
+		if (employee!=null && employee.getEmployer()==this) {
+			if (employee.getHiredAs()==DataWindowMaker.class) {
+				CharacterData d = (CharacterData)employee.doCommand("getDataSet", null, CommandChecker.defaultChecker);
+				if (d != null) {
+					return ("showDataWindow " + dataRef(d, true) + "  " + StringUtil.tokenize(employee.getName()) + ";");//quote
+				}
+			}
+		}
+		return null;
+	}
+	/* ................................................................................................................. */
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof DataWindowMaker){
+			if (cadw != null) cadw.setEnabled(getNumMatrixWindows()>0);
+			resetAllMenuBars();
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		Vector datasShown = new Vector();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowMaker) {
+				DataWindowMaker dwm = (DataWindowMaker)e;
+				CharacterData d = (CharacterData)dwm.doCommand("getDataSet", null, CommandChecker.defaultChecker);
+				if (d != null && (d.getWritable() || file == null)) {
+					if (datasShown.indexOf(d)>=0)
+						temp.addLine("showExtraDataWindow " + dataRef(d, false), dwm);
+					else {
+						temp.addLine("showDataWindow " + dataRef(d, false), dwm);
+						datasShown.addElement(d);
+					}
+				}
+			}
+		}
+		datasShown.removeAllElements();
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	CharacterData findData(String arguments, MesquiteFile file){
+		CharacterData data = null;
+		if (StringUtil.blank(arguments)){
+			ListableVector datas = getProject().getCharacterMatrices();
+			int numDatas = 0;
+			for (int i=0; i<datas.size(); i++)
+				if (((CharacterData)datas.elementAt(i)).isUserVisible()){
+					data = (CharacterData)datas.elementAt(i);
+					numDatas++;
+				}
+			//if only one taxa block, use it
+			if (numDatas<=0){
+				return null;
+			}
+			else if (numDatas==1){
+				return data;
+			}
+			else {
+				data =  getProject().chooseData(containerOfModule(), null, null, "Which data matrix would you like to display in an data editor window?");
+				//else, query user
+			}
+		}
+		else { 
+			// in general, will only show user visible matrices.  However, if arguments starts with #, then assume a direct, non-numbered request that will be obeyed even if not user visible
+			data =  getProject().getCharacterMatrixByReference(file, parser.getFirstToken(arguments), !arguments.startsWith("#"));
+		}
+		return data;
+	}
+
+	DataWindowMaker findEditor(CharacterData data){
+		//next, find if already has DataWindowMaker module for it
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowMaker) {
+				DataWindowMaker dwm = (DataWindowMaker)e;
+				CharacterData d = dwm.getCharacterData();
+				if (d == data) {
+					if (dwm.getModuleWindow() !=null) {
+						dwm.getModuleWindow().setVisible(true);
+						dwm.getModuleWindow().setShowExplanation(true);
+						dwm.getModuleWindow().toFront();
+					}
+					return dwm;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee instanceof DataWindowMaker) {  // character source quit and none rehired automatically
+			DataWindowMaker dwm = (DataWindowMaker)employee;
+			unlinkEditors(dwm.getCharacterData(), dwm);
+			if (cadw != null) cadw.setEnabled(getNumMatrixWindows()>0);
+			resetAllMenuBars();
+
+		}
+	}
+	
+	int getNumMatrixWindows(){
+		int count = 0;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowMaker && ((DataWindowMaker) e).getModuleWindow().isVisible()) 
+				count++;
+		}
+		return count;
+	}
+	void linkEditors(CharacterData data, DataWindowMaker newDWM){
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowMaker && e != newDWM) {
+				DataWindowMaker dwm = (DataWindowMaker)e;
+				CharacterData d = dwm.getCharacterData();
+				if (d == data) {
+					dwm.linkEditor(newDWM, true);
+					newDWM.linkEditor(dwm, false);
+				}
+			}
+		}
+	}
+	void unlinkEditors(CharacterData data, DataWindowMaker newDWM){
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowMaker && e != newDWM) {
+				DataWindowMaker dwm = (DataWindowMaker)e;
+				CharacterData d = dwm.getCharacterData();
+				if (d == data) {
+					dwm.unlinkEditor(newDWM);
+					newDWM.unlinkEditor(dwm);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows the data editor window.  If a data editor window for this matrix already exists, it is brought to the front", "[number of data matrix to be shown] [name of data matrix to be shown]", commandName, "showDataWindow")) {  //IF WINDOW ALREADY SHOWN, JUST BRING IT TO FRONT
+			//first, find the data set requested
+			CharacterData data = findData(arguments, checker.getFile());
+			if (data == null)
+				return null;
+			/**/
+			DataWindowMaker dwm = findEditor(data);
+			if (dwm!=null){
+				if (cadw != null) cadw.setEnabled(true);
+				resetAllMenuBars();
+				return dwm;
+			}
+
+			//if no data window module active, hire one
+			DataWindowMaker mb = (DataWindowMaker)hireEmployee(DataWindowMaker.class, null);
+			if (mb!=null) {
+				mb.setAsExtra(false);
+				mb.doCommand("makeWindow", getProject().getCharMatrixReferenceInternal(data), checker);
+			}
+			if (cadw != null) cadw.setEnabled(true);
+			resetAllMenuBars();
+		return mb;
+		}
+		else if (checker.compare(this.getClass(), "Shows an extra data editor window.", "[number of data matrix to be shown] [name of data matrix to be shown]", commandName, "showExtraDataWindow")) {  //IF WINDOW ALREADY SHOWN, JUST BRING IT TO FRONT
+			//first, find the data set requested
+			CharacterData data = findData(arguments, checker.getFile());
+			if (data == null)
+				return null;
+
+			//if no data window module active, hire one
+			DataWindowMaker mb = (DataWindowMaker)hireEmployee(DataWindowMaker.class, null);
+			if (mb!=null) {
+				mb.setAsExtra(true);
+				mb.doCommand("makeWindow", getProject().getCharMatrixReferenceInternal(data), checker);
+				linkEditors(data, mb);
+			}
+			if (cadw != null) cadw.setEnabled(true);
+			resetAllMenuBars();
+			return mb;
+		}
+		else if (checker.compare(this.getClass(), "Closes all character matrix editor windows", null, commandName, "closeAllMatrixWindows")) {
+			for (int i = getNumberOfEmployees()-1; i>=0; i--) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof DataWindowMaker) {
+					DataWindowMaker dwm = (DataWindowMaker)e;
+					dwm.windowGoAway(dwm.getModuleWindow());
+				}
+			}
+			if (cadw != null) cadw.setEnabled(false);
+			resetAllMenuBars();
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Data Window Coordinator";
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the creation of basic data windows." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/charMatrices/BasicDataWindowMaker/32colorWand.gif b/Source/mesquite/charMatrices/BasicDataWindowMaker/32colorWand.gif
new file mode 100644
index 0000000..625a162
Binary files /dev/null and b/Source/mesquite/charMatrices/BasicDataWindowMaker/32colorWand.gif differ
diff --git a/Source/mesquite/charMatrices/BasicDataWindowMaker/64colorWand.gif b/Source/mesquite/charMatrices/BasicDataWindowMaker/64colorWand.gif
new file mode 100644
index 0000000..1e6cd41
Binary files /dev/null and b/Source/mesquite/charMatrices/BasicDataWindowMaker/64colorWand.gif differ
diff --git a/Source/mesquite/charMatrices/BasicDataWindowMaker/BasicDataWindowMaker.java b/Source/mesquite/charMatrices/BasicDataWindowMaker/BasicDataWindowMaker.java
new file mode 100644
index 0000000..6de715a
--- /dev/null
+++ b/Source/mesquite/charMatrices/BasicDataWindowMaker/BasicDataWindowMaker.java
@@ -0,0 +1,5743 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.BasicDataWindowMaker;
+
+/*~~  */
+
+import java.util.*;
+import java.util.List;
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.text.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+import java.awt.datatransfer.*;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTarget;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import mesquite.lib.table.*;
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.ContinuousData;
+
+/** Makes and manages the spreadsheet editor for character matrices. */
+public class BasicDataWindowMaker extends DataWindowMaker implements CommandableOwner {
+	public void getEmployeeNeeds() { // This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CellColorer.class, getName() + " uses various methods to color the cells of the character matrix.", "You can request the method to color cells in the Color Cells submenu of the Matrix menu.  You can also color the text of the cell using the Color Text submenu. ");
+		EmployeeNeed e2 = registerEmployeeNeed(DataWindowAssistantI.class, getName() + " can employ various modules to add features to the Character Matrix Editor.", "The modules assisting the Character Matrix Editor are available typically in the Matrix menu of the editor window. ");
+		EmployeeNeed e3 = registerEmployeeNeed(DataWindowAssistantA.class, "Various analyses can be done within the context of the Character Matrix Editor.", "You can request such an analysis in the Analysis menu of the Character Matrix Editor. ");
+		EmployeeNeed e4 = registerEmployeeNeed(DataUtility.class, "Utilities are available to modify or summarize a matrix in the Character Matrix Editor.", "You can request such a utility in the Utilities submenu of the Matrix menu of the Character Matrix Editor. ");
+	}
+
+	public static final short cellWidth = 24;
+	public static final short cellHeight = 16;
+	CharacterData data;
+	BasicDataWindow bdw;
+	boolean isExtra = false;
+	MesquiteMenuSpec matrixMenu, displayMenu;
+	static boolean warnAgainAboutTaxonNameDuplication = true;
+	
+	/* ................................................................................................................. */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixMenu = makeMenu("Matrix");
+		displayMenu = addAuxiliaryMenu("Display");
+		resetContainingMenuBar();
+		return true;
+	}
+
+	public Commandable[] getCommandablesForAccumulation() {
+		Commandable[] cs = new Commandable[1];
+		cs[0] = new BasicDataWindow();
+		return cs;
+	}
+
+	public void setAsExtra(boolean e) {
+		isExtra = e;
+	}
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (bdw == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		Snapshot sn = bdw.getSnapshot(file);
+		temp.incorporate(sn, true);
+		temp.addLine("endTell");
+		if (bdw.isVisible())
+			temp.addLine("showWindow");
+		if (!bdw.widthsSet && !bdw.table.showBirdsEyeView.getValue() && (bdw.table.tight.getValue() || bdw.table.showStates.getValue())) { // needed to ensure appears correctly first time under some OS's
+			temp.addLine("getWindow");
+			temp.addLine("tell It");
+			temp.addLine("\tforceAutosize");
+			temp.addLine("endTell");
+		}
+		if (!bdw.isVisible())
+			temp.addLine("hideWindow");
+		return temp;
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the data matrix shown by the data window", null, commandName, "getDataSet")) {
+			return data;
+		}
+		else if (checker.compare(this.getClass(), "Hides the data matrix window", null, commandName, "hideWindow")) {
+			if (bdw != null){
+				bdw.hide();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Makes a data editor window (but doesn't display it)", "[number or reference string of data set to be shown]", commandName, "makeWindow")) {
+			if (bdw != null)
+				return bdw;
+			CharacterData data = getProject().getCharacterMatrixByReference(checker.getFile(), parser.getFirstToken(arguments));
+			if (data != null) {
+				makeDataWindow(data);
+				return bdw;
+			}
+		}
+
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public void resignCellColorer(MesquiteModule m) {
+		if (bdw != null)
+			bdw.resignCellColorer(m);
+	}
+
+	public void requestCellColorer(MesquiteModule m, int ic, int it, String message) {
+		if (bdw != null)
+			bdw.requestCellColorer(m, ic, it, message);
+		// return false;
+	}
+
+	public void demandCellColorer(MesquiteModule m, int ic, int it, String message) {
+		if (bdw != null)
+			bdw.demandCellColorer(m, ic, it, message);
+	}
+
+	public void selectSameColor(int column, int row, boolean restrictToCharacter, boolean restrictToTaxon, boolean contiguous, boolean subtractFromSelection) {
+		if (bdw != null)
+			bdw.selectSameColor(column, row, restrictToCharacter, restrictToTaxon, contiguous, subtractFromSelection);
+	}
+	
+	public void selectDataBlockInTaxon(int column, int row) {
+		if (bdw != null)
+			bdw.selectBlockInTaxon(column, row);
+
+	}
+
+	public void selectSameColorRow(int column, int row, boolean subtractFromSelection) {
+		if (bdw != null)
+			bdw.selectSameColorRow(column, row, subtractFromSelection);
+	}
+
+	/* ................................................................................................................. */
+	public void linkEditor(DataWindowMaker mb, boolean linkeeIsNew) {
+		if (bdw != null) {
+			MesquiteWindow w = mb.getModuleWindow();
+			if (w != null && w instanceof TableWindow) {
+				MatrixTable t = bdw.getMatrixTable();
+				t.linkTable(((TableWindow) w).getTable(), linkeeIsNew);
+			}
+		}
+	}
+
+	public void unlinkEditor(DataWindowMaker mb) {
+		if (bdw != null) {
+			MesquiteTable w = mb.getTable();
+			if (w != null && w instanceof MatrixTable) {
+				MatrixTable t = bdw.getMatrixTable();
+				t.unlinkTable(w);
+			}
+		}
+	}
+
+	public MesquiteTable getTable() {
+		if (bdw == null)
+			return null;
+		return bdw.getMatrixTable();
+	}
+
+	/* ................................................................................................................. */
+	public void makeDataWindow(CharacterData data) {
+		this.data = data;
+		setModuleWindow(bdw = new BasicDataWindow(this, data));
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		if (!MesquiteThread.isScripting() && bdw != null) {
+			bdw.setVisible(true);
+			bdw.contentsChanged();
+			bdw.toFront();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public CharacterData getCharacterData() {
+		if (data.isDisposed())
+			return null;
+		return data;
+	}
+
+	/* ................................................................................................................. */
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		parametersChanged();
+		if (isExtra) {
+			whichWindow.dispose();
+			iQuit();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public boolean showCitation() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	public String getName() {
+		return "Character Matrix Editor";
+	}
+
+	/* ................................................................................................................. */
+	// public BasicDataWindow getBasicDataWindow() {
+	// return bdw;
+	// }
+
+	/* ................................................................................................................. */
+
+	/** returns an explanation of what the module does. */
+	public String getExplanation() {
+		return "Makes editor windows to edit character data.";
+	}
+
+	public String getParameters() {
+		if (bdw == null)
+			return null;
+		return bdw.getParameters();
+	}
+
+	/* ................................................................................................................. */
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (bdw != null)
+			bdw.resetColorerIfNeeded(employee);
+		if (employee == bdw.table.cellColorer) {
+			bdw.table.repaintAll();
+			if (bdw.showColorLegend.getValue()) {
+				ColorRecord[] colors = ((CellColorer) bdw.table.cellColorer).getLegendColors();
+				bdw.setColorLegend(colors, ((CellColorer) bdw.table.cellColorer).getColorsExplanation(), true);
+
+			}
+		}
+		super.employeeParametersChanged(employee, source, notification);
+	}
+
+	public static boolean getWarnAgainAboutTaxonNameDuplication() {
+		return warnAgainAboutTaxonNameDuplication;
+	}
+
+	public static void setWarnAgainAboutTaxonNameDuplication(boolean warnAgainAboutTaxonNameDuplication) {
+		BasicDataWindowMaker.warnAgainAboutTaxonNameDuplication = warnAgainAboutTaxonNameDuplication;
+	}
+}
+
+/* ======================================================================== */
+class BasicDataWindow extends TableWindow implements MesquiteListener {
+	CharacterData data;
+
+	protected TableTool scrollTool;
+	MatrixTable table;
+	int windowWidth = 420;
+	int windowHeight = 280;
+	int columnWidth = 12;
+	boolean widthsSet = false;
+	TableTool arrowTool, ibeamTool;// , charWandTool;//, taxaWandTool
+	MesquiteString cellColorerName, textColorerName, rowNamesColorerName, columnNamesColorerName, bgColorName;
+	private int findNumber = 0;
+	private String findFootnoteString = "";
+	MesquiteBoolean constrainedCW = new MesquiteBoolean(true);
+	MesquiteBoolean scrollLinkedTables = new MesquiteBoolean(false);
+	MesquiteBoolean linkedScrolling = new MesquiteBoolean(true);
+	MesquiteBoolean showTaxonNames = new MesquiteBoolean(true);
+	MesquiteBoolean useDiagonal = new MesquiteBoolean(false);
+	MesquiteBoolean allowAutosize;
+	boolean oldShowStates;
+	boolean oldSuppress;
+	int oldColumnsWidths;
+	MesquiteMenuItemSpec linkedScrollingItem = null;
+	MesquiteButton colorLegendButton;
+	MesquiteButton birdsEyeButton;
+	MesquiteBoolean interleaved;
+	MatrixInfoPanel matrixInfoPanel;
+	boolean matrixInfoPanelEverShown = false;
+	MesquiteBoolean infoPanelOn;
+	MesquiteBoolean editingNotPermitted = new MesquiteBoolean(false);
+	MesquiteBoolean showPaleExcluded = new MesquiteBoolean(false);
+
+	public BasicDataWindow() {
+	}
+
+	public BasicDataWindow(BasicDataWindowMaker ownerModule, CharacterData data) {
+		super(ownerModule, true); // INFOBAR
+		this.data = data;
+		ownerModule.setModuleWindow(this);
+		ownerModule.setUndoMenuItemEnabled(false);
+		allowAutosize = new MesquiteBoolean(!(data instanceof MolecularData));
+		infoPanelOn = new MesquiteBoolean(false);
+		useDiagonal.setValue(data.useDiagonalCharacterNames());
+		// this.ownerModule = ownerModule;
+		setWindowSize(windowWidth, windowHeight);
+		if (data != null)
+			columnWidth = data.getDefaultColumnWidth();
+		MesquiteSubmenuSpec mssa = ownerModule.addSubmenu(ownerModule.addAuxiliaryMenu("Analysis:Matrix"), "Analyses for Matrix", MesquiteModule.makeCommand("newAssistant", this), DataWindowAssistantA.class);
+		mssa.setCompatibilityCheck(data.getStateClass());
+		table = new MatrixTable((BasicDataWindowMaker) ownerModule, this, data, data.getTaxa().getNumTaxa(), data.getNumChars(), windowWidth, windowHeight, 110);
+		/**/
+		/*	*/
+		table.setQuickMode(true);
+		setDefaultAnnotatable(data);
+		data.getTaxa().addListener(this);
+		data.addListener(this);
+		addToWindow(table);
+		table.setLocation(0, 0);
+		table.setVisible(true);
+		table.setColumnAssociable(data);
+		table.setRowAssociable(data.getTaxa());
+		if (data instanceof MolecularData)
+			setIcon(MesquiteModule.getRootImageDirectoryPath() + "windowIcons/matrixSequence.gif");
+		else
+			setIcon(MesquiteModule.getRootImageDirectoryPath() + "windowIcons/matrix.gif");
+
+		MesquiteButton infoButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("toggleInfoPanel", this), null, true, MesquiteModule.getRootImageDirectoryPath() + "showInfo.gif", 12, 16);
+		infoButton.setUseWaitThread(false);
+		infoButton.setShowBackground(false);
+		infoButton.setButtonExplanation("Show Matrix Info Panel");
+		// infoBar.addExtraButton(MesquiteModule.getRootImageDirectoryPath() + "showInfo.gif", MesquiteModule.makeCommand("toggleInfoPanel", this));
+		table.addControlButton(infoButton);
+		MesquiteButton listButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("showList", this), null, true, MesquiteModule.getRootImageDirectoryPath() + "listC.gif", 12, 16);
+		listButton.setShowBackground(false);
+		listButton.setButtonExplanation("Show List of Characters window");
+		listButton.setUseWaitThread(false);
+		table.addControlButton(listButton);
+		listButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("showTaxaList", this), null, true, MesquiteModule.getRootImageDirectoryPath() + "listT.gif", 12, 16);
+		listButton.setShowBackground(false);
+		listButton.setButtonExplanation("Show List of Taxa window");
+		table.addControlButton(listButton);
+		colorLegendButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("toggleColorsPanel", this), null, true, MesquiteModule.getRootImageDirectoryPath() + "colorLegend.gif", 12, 16);
+		colorLegendButton.setShowBackground(false);
+		colorLegendButton.setButtonExplanation("Show/Hide Colors Legend");
+		colorLegendButton.setUseWaitThread(false);
+
+		if (data instanceof MolecularData) {
+			birdsEyeButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("toggleBirdsEye", this), null, true, ownerModule.getPath() + "birdsEye.gif", 12, 16);
+			birdsEyeButton.setShowBackground(false);
+			birdsEyeButton.setButtonExplanation("Bird's eye view");
+			birdsEyeButton.setUseWaitThread(false);
+			table.addControlButton(birdsEyeButton);
+		}
+
+		oldShowStates = table.showStates.getValue();
+		oldColumnsWidths = table.getColumnWidthsUniform();
+		oldSuppress = table.suppressAutosize;
+		interleaved = new MesquiteBoolean(data.interleaved);
+		MesquiteSubmenuSpec cmm = ownerModule.addSubmenu(null, "Current Matrix");
+		ownerModule.addItemToSubmenu(null, cmm, "Rename Matrix...", MesquiteModule.makeCommand("renameMatrix", this));
+		ownerModule.addItemToSubmenu(null, cmm, "Delete Matrix...", MesquiteModule.makeCommand("deleteMatrix", this));
+		ownerModule.addItemToSubmenu(null, cmm, "Show Character List", MesquiteModule.makeCommand("showList", this));
+		ownerModule.addCheckMenuItemToSubmenu(null, cmm, "Write Interleaved", MesquiteModule.makeCommand("toggleInterleaved", this), interleaved);
+		ownerModule.addItemToSubmenu(null, cmm, "Missing Data Symbol...", MesquiteModule.makeCommand("setUnassignedSymbol", this));
+		ownerModule.addItemToSubmenu(null, cmm, "Inapplicable Symbol...", MesquiteModule.makeCommand("setInapplicableSymbol", this));
+		ownerModule.addCheckMenuItem(null, "Show Matrix Info Panel", ownerModule.makeCommand("toggleInfoPanel", this), infoPanelOn);
+		editingNotPermitted.setValue(data.getEditorInhibition());
+		ownerModule.addCheckMenuItemToSubmenu(null, cmm,"Editing Not Permitted", ownerModule.makeCommand("toggleEditingNotPermitted", this), editingNotPermitted);
+		ownerModule.addMenuItem("-", null);
+		
+		
+		MesquiteSubmenuSpec mCC = ownerModule.addSubmenu(ownerModule.displayMenu, "Color Matrix Cells", MesquiteModule.makeCommand("colorCells", this), ownerModule.getEmployeeVector());
+		mCC.setListableFilter(CellColorerMatrix.class);
+
+		mCC.setCompatibilityCheck(data.getStateClass());
+		cellColorerName = new MesquiteString();
+		mCC.setSelected(cellColorerName);
+		ownerModule.addCheckMenuItem(ownerModule.displayMenu, "Show Color Legend", MesquiteModule.makeCommand("toggleColorsPanel", this), showColorLegend);
+
+		MesquiteSubmenuSpec mCC3 = ownerModule.addSubmenu(ownerModule.displayMenu, "Color Taxon Names Background", MesquiteModule.makeCommand("colorRowNames", this), ownerModule.getEmployeeVector());
+		mCC3.setListableFilter(CellColorerTaxa.class);
+		mCC3.setCompatibilityCheck(data.getStateClass());
+		rowNamesColorerName = new MesquiteString();
+		mCC3.setSelected(rowNamesColorerName);
+
+		MesquiteSubmenuSpec mCC4 = ownerModule.addSubmenu(ownerModule.displayMenu, "Color Character Name Background", MesquiteModule.makeCommand("colorColumnNames", this), ownerModule.getEmployeeVector());
+		mCC4.setListableFilter(CellColorerCharacters.class);
+		mCC4.setCompatibilityCheck(data.getStateClass());
+		columnNamesColorerName = new MesquiteString();
+		mCC4.setSelected(columnNamesColorerName);
+
+		MesquiteSubmenuSpec mCC2 = ownerModule.addSubmenu(ownerModule.displayMenu, "Color Text", MesquiteModule.makeCommand("colorText", this), ownerModule.getEmployeeVector());
+		mCC2.setListableFilter(CellColorer.class);
+		mCC2.setCompatibilityCheck(data.getStateClass());
+		textColorerName = new MesquiteString();
+		mCC2.setSelected(textColorerName);
+
+
+		MesquiteSubmenuSpec mSetColor = ownerModule.addSubmenu(ownerModule.displayMenu, "Assign Color to Selected", MesquiteModule.makeCommand("assignColor", this), ColorDistribution.standardColorNames);
+		ownerModule.addMenuItem(ownerModule.displayMenu, "Remove Color from Selected", MesquiteModule.makeCommand("removeColor", this));
+
+		MesquiteSubmenuSpec mmis = ownerModule.addSubmenu(ownerModule.displayMenu, "Background Color", MesquiteModule.makeCommand("setBackground", this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		bgColorName = new MesquiteString();
+		mmis.setSelected(bgColorName);
+
+		ownerModule.addMenuItem(ownerModule.displayMenu, "-", null);
+		ownerModule.addCheckMenuItem(ownerModule.displayMenu, "Bird's Eye View", MesquiteModule.makeCommand("toggleBirdsEye", this), table.showBirdsEyeView);
+		MesquiteSubmenuSpec widthsSubmenu = ownerModule.addSubmenu(ownerModule.displayMenu, "Widths");
+		//COLUMNS&ROWS
+		table.setColumnNamesDiagonal(useDiagonal.getValue());
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Narrow Columns", MesquiteModule.makeCommand("toggleTight", this), table.tight);
+		ownerModule.addItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Bird's Eye Width...", MesquiteModule.makeCommand("birdsEyeWidth", this));
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Thin Rows", MesquiteModule.makeCommand("toggleThinRows", this), table.thinRows);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Constrain Auto Widths", MesquiteModule.makeCommand("toggleConstrainCW", this), constrainedCW);
+		table.setConstrainMaxAutoColumn(constrainedCW.getValue());
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Enable Column Auto-Size", MesquiteModule.makeCommand("toggleAllowAutosize", this), table.allowAutosize);
+		ownerModule.addItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Restore Column Auto-Size", MesquiteModule.makeCommand("forceAutosize", this));
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Auto-size includes Char. Names", MesquiteModule.makeCommand("toggleAutoWCharNames", this), table.autoWithCharNames);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, widthsSubmenu, "Auto-size Taxon Names", MesquiteModule.makeCommand("toggleAutoTaxonNames", this), table.autoRowNameWidth);
+		MesquiteSubmenuSpec namesSubmenu = ownerModule.addSubmenu(ownerModule.displayMenu, "Names");
+		//NAMES
+		if (data.getClass() == CategoricalData.class || data.getClass() == ContinuousData.class)
+			ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Diagonal Character Names", MesquiteModule.makeCommand("toggleDiagonal", this), useDiagonal);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Show Taxon Names", MesquiteModule.makeCommand("toggleShowTaxonNames", this), showTaxonNames);
+		if (data instanceof CategoricalData && !(data instanceof DNAData) && !(data instanceof ProteinData))
+			ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Show State Names", MesquiteModule.makeCommand("toggleShowNames", this), table.showNames);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Show States", MesquiteModule.makeCommand("toggleShowStates", this), table.showStates);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Show Default Char. Names", MesquiteModule.makeCommand("toggleShowDefaultCharNames", this), table.showDefaultCharNames);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, namesSubmenu, "Bold Cell Text", MesquiteModule.makeCommand("toggleShowBoldCellText", this), table.showBoldCellText);
+
+		
+		MesquiteSubmenuSpec softnessSubmenu = ownerModule.addSubmenu(ownerModule.displayMenu, "Lighten");
+		//COLORS
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, softnessSubmenu, "Lighten Grid", MesquiteModule.makeCommand("toggleShowPaleGrid", this), table.showPaleGrid);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, softnessSubmenu, "Lighten Cell Colors", MesquiteModule.makeCommand("toggleShowPaleCellColors", this), table.showPaleCellColors);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, softnessSubmenu, "Lighten Gaps/Inapplicable", MesquiteModule.makeCommand("togglePaleInapplicable", this), table.paleInapplicable);
+		ownerModule.addCheckMenuItemToSubmenu(ownerModule.displayMenu, softnessSubmenu, "Lighten Excluded Characters", MesquiteModule.makeCommand("toggleShowPaleExcluded", this), showPaleExcluded);
+		
+		//CHANGES
+		ownerModule.addCheckMenuItem(ownerModule.displayMenu, "Show Changes Since Saved", MesquiteModule.makeCommand("toggleShowChanges", this), table.showChanges);
+		if (data instanceof CategoricalData && !(data instanceof DNAData) && !(data instanceof ProteinData))
+			ownerModule.addCheckMenuItem(ownerModule.displayMenu, "Lined States Explanation", MesquiteModule.makeCommand("toggleSeparateLines", this), table.statesSeparateLines);
+		linkedScrollingItem = ownerModule.addCheckMenuItem(ownerModule.displayMenu, "Linked Scrolling", MesquiteModule.makeCommand("toggleLinkedScrolling", this), linkedScrolling);
+		linkedScrollingItem.setEnabled(false);
+
+
+		String selectExplanation = "This tool selects items in the matrix.  By holding down shift while clicking, the selection will be extended from the first to the last touched cell. ";
+		selectExplanation += " A block of cells can be selected either by using shift-click to extend a previous selection, or by clicking on a cell and dragging with the mouse button still down";
+		selectExplanation += " Discontinous selections are allowed, and can be obtained by a \"meta\"-click (right mouse button click, or command-click on a MacOS system). ";
+		MesquiteCommand dragCommand = MesquiteModule.makeCommand("arrowDragCell", this);
+		dragCommand.setSuppressLogging(true);
+		arrowTool = new TableTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(), "arrow.gif", 4, 2, "Select", selectExplanation, MesquiteModule.makeCommand("arrowTouchCell", this), dragCommand, MesquiteModule.makeCommand("arrowDropCell", this));
+		arrowTool.setIsArrowTool(true);
+		arrowTool.setUseTableTouchRules(true);
+		addTool(arrowTool);
+		setCurrentTool(arrowTool);
+		arrowTool.setInUse(true);
+		// ibeam
+		ibeamTool = new TableTool(this, "ibeam", MesquiteModule.getRootImageDirectoryPath(), "ibeam.gif", 7, 7, "Edit", "This tool can be used to edit the contents of cells in the matrix.", MesquiteModule.makeCommand("editCell", (Commandable) table), null, null);
+		ibeamTool.setWorksOnRowNames(true);
+		ibeamTool.setWorksOnColumnNames(true);
+		addTool(ibeamTool);
+		ibeamTool.setEnabled(!data.getEditorInhibition());
+
+		ListableVector v = ownerModule.getEmployeeVector();
+
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#AlterData");
+		
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#AlignSequences");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#AddDeleteData");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#SearchData");
+		// ownerModule.addMenuItem("-", null);
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#NoColor");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#ColorByState");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#ColorCells");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#CharGroupColor");
+		ownerModule.hireNamedEmployee(DataWindowAssistantI.class, "#TaxonGroupColor");
+
+		ownerModule.hireAllOtherCompatibleEmployees(DataWindowAssistantI.class, data.getStateClass());
+		Enumeration enumeration = ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof DataWindowAssistantI) {
+				DataWindowAssistantI init = (DataWindowAssistantI) obj;
+				if (init instanceof DataWindowAssistantID || init instanceof CategDataEditorInitD)
+					init.setMenuToUse(ownerModule.displayMenu);
+				
+				init.setTableAndData(table, data);
+			}
+		}
+		
+		ownerModule.hireAllCompatibleEmployees(CharTableAssistantI.class, data.getStateClass());
+		enumeration = ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof CharTableAssistantI) {
+				CharTableAssistantI init = (CharTableAssistantI) obj;
+				init.setTableAndData(table, data, false);
+			}
+		}
+		ownerModule.hireAllEmployees(TaxaTableAssistantI.class);
+		enumeration = ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TaxaTableAssistantI) {
+				TaxaTableAssistantI init = (TaxaTableAssistantI) obj;
+				init.setTableAndTaxa(table, data.getTaxa(), true);
+			}
+		}
+		if (data instanceof CategoricalData && !(data instanceof MolecularData) && ownerModule.findEmployeeWithDuty(mesquite.categ.StateNamesEditor.StateNamesEditor.class) != null) {
+			MesquiteButton statesButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("showStateNamesEditor", this), null, true, MesquiteModule.getRootImageDirectoryPath() + "listS.gif", 12, 16);
+			statesButton.setShowBackground(false);
+			statesButton.setButtonExplanation("Show State Names Editor window");
+			statesButton.setUseWaitThread(false);
+			table.addControlButton(statesButton);
+		}
+		MesquiteSubmenuSpec mss2 = ownerModule.addSubmenu(null, "Utilities", MesquiteModule.makeCommand("doUtility", this));
+		mss2.setList(DataUtility.class);
+		mss2.setCompatibilityCheck(data.getStateClass());
+
+		MesquiteMenuItemSpec msct = ownerModule.addMenuItem("Move Selected Characters To...", ownerModule.makeCommand("moveCharsTo", this));
+		msct.setShortcut(KeyEvent.VK_M);
+		ownerModule.addMenuItem("Move Selected Taxa To...", ownerModule.makeCommand("moveTaxaTo", this));
+		ownerModule.addMenuItem("Move Selected Block...", ownerModule.makeCommand("moveSelectedBlock", this));
+
+		MesquiteSubmenuSpec mss4 = ownerModule.addSubmenu(null, "Character Inclusion/Exclusion");
+		ownerModule.addItemToSubmenu(null, mss4, "Include Selected Characters", ownerModule.makeCommand("includeSelectedCharacters", this));
+		ownerModule.addItemToSubmenu(null, mss4, "Exclude Selected Characters", ownerModule.makeCommand("excludeSelectedCharacters", this));
+
+		// private, to fix frameshifted footnotes
+		// ownerModule.addMenuItem( "Move Footnotes...", ownerModule.makeCommand("moveFootnotes", this));
+
+		MesquiteSubmenuSpec mss2t = ownerModule.addSubmenu(null, "Taxon Utilities", MesquiteModule.makeCommand("doTaxonUtility", this));
+		mss2t.setList(TaxonUtility.class);
+		MesquiteSubmenuSpec mss3 = ownerModule.addSubmenu(null, "Taxon Names", MesquiteModule.makeCommand("doNames", this));
+		mss3.setList(TaxonNameAlterer.class);
+		ownerModule.addMenuItem("-", null);
+		
+	
+		MesquiteModule noColor = ownerModule.findEmployeeWithName("#NoColor", true);
+		if (data.colorCellsByDefault()) {
+			MesquiteModule mbc = ownerModule.findEmployeeWithName("#ColorByState", true);
+			setCellColorer(mbc);
+		}
+		else {
+			setCellColorer(noColor);
+		}
+		MesquiteModule groupColor = ownerModule.findEmployeeWithName("#TaxonGroupColor", true);
+		setRowNamesColorer(groupColor);
+		groupColor = ownerModule.findEmployeeWithName("#CharGroupColor", true);
+		setColumnNamesColorer(groupColor);
+		setTextColorer(noColor);
+		MesquiteSubmenuSpec mShowDataInfoStrip = ownerModule.addSubmenu(ownerModule.displayMenu, "Add Char Info Strip", ownerModule.makeCommand("hireDataInfoStrip", this), DataColumnNamesAssistant.class);
+		//ownerModule.hireAllCompatibleEmployees(DataColumnNamesAssistant.class, data.getStateClass());
+		
+	/*
+		 * TableTool colorWandTool = new TableTool(this, "colorMagicWand", ownerModule.getPath(), "colorWand.gif", 1,1,"Select same color", "This tool selects cells of the same color", MesquiteModule.makeCommand("selectSameColor", this) , null, null); colorWandTool.setWorksOnColumnNames(false); colorWandTool.setWorksOnRowNames(false); colorWandTool.setWorksOnMatrixPanel(true); colorWandTool.setWorksOnCornerPanel(false); addTool(colorWandTool); /*
+		 * 
+		 * scrollTool = new TableTool(this, "simScroller", ownerModule.getPath(), "simScrollerRight.gif", 8, 8,"Scrolls between similar items", "This tool scrolls to other similar items", MesquiteModule.makeCommand("simScroll", this) , null, null); scrollTool.setOptionImageFileName("simScrollerLeft.gif", 8, 8); scrollTool.setWorksOnColumnNames(true); scrollTool.setWorksOnRowNames(false); scrollTool.setWorksOnMatrixPanel(false); scrollTool.setWorksOnCornerPanel(false); scrollTool.setSpecialTool [...]
+		 * scrollTool.setOptionsCommand(MesquiteModule.makeCommand("scrollToolOptions", this)); addTool(scrollTool);
+		 */
+
+		// scrollTool.setPopUpOwner(ownerModule);
+		// scrollTool.setUseMenubar(false); //menu available by touching on button
+		// ownerModule.addCheckMenuItem(null, "Scroll linked windows", MesquiteModule.makeCommand("toggleScrollLinkedTables", this), scrollLinkedTables);
+
+		matrixInfoPanel = new MatrixInfoPanel(this);
+		matrixInfoPanel.setMatrix(data);
+		ownerModule.hireAllCompatibleEmployees(MatrixInfoPanelAssistantI.class, data.getStateClass());
+		enumeration = ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof MatrixInfoPanelAssistantI) {
+				MatrixInfoPanelAssistantI init = (MatrixInfoPanelAssistantI) obj;
+				matrixInfoPanel.addExtraPanel(init.getPanel(matrixInfoPanel));
+			}
+		}
+		matrixInfoPanel.startCellInfo();
+		checkSelectionMatrixInfoPanel();
+		setShowAnnotation(true);
+		table.requestFocus();
+		MesquiteWindow.addKeyListener(this, table);
+
+		MesquiteMenuItemSpec mm = ownerModule.addMenuItem(MesquiteTrunk.editMenu, "Find Footnote...", MesquiteModule.makeCommand("findFootnoteString", this));
+		mm.setShortcut(KeyEvent.VK_H);
+		checkUndoMenuStatus();
+
+		resetTitle();
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * When called the window will determine its own title. MesquiteWindows need to be self-titling so that when things change (names of files, tree blocks, etc.) they can reset their titles properly
+	 */
+	public void resetTitle() {
+		String t;
+		if (data != null && data.hasTitle()) {
+			if (data.uniquelyNamed())
+				t = data.getName();
+			else
+				t = data.getName() + " [" + data.getID() + "]";
+		}
+		else {
+			t = "Character Matrix";
+		}
+		setTitle(t);
+	}
+
+	/* ................................................................................................................. */
+	void setMatrixInfoPanel(boolean show) {
+		infoPanelOn.setValue(show);
+		if (show) {
+			matrixInfoPanelEverShown = true;
+			addSidePanel(matrixInfoPanel, MatrixInfoPanel.width);
+			matrixInfoPanel.setVisible(true);
+			String title = "Matrix Information";
+			matrixInfoPanel.repaint();
+		}
+		else {
+			if (matrixInfoPanel != null)
+				removeSidePanel(matrixInfoPanel);
+		}
+	}
+
+	/* ................................................................................................................. */
+	void matrixInfoPanelGoAway() {
+		setMatrixInfoPanel(false);
+	}
+
+	/* ................................................................................................................. */
+
+	private boolean linked = false;
+
+	void setTableLinked(boolean linked) {
+		linkedScrollingItem.setEnabled(linked);
+		if (this.linked != linked && linked) {
+			this.linked = linked; // newly linked; need to sync
+			table.setFirstColumnVisibleLinked(table.getFirstColumnVisible());
+			table.setFirstRowVisibleLinked(table.getFirstRowVisible());
+		}
+		MesquiteTrunk.resetMenuItemEnabling();
+	}
+
+	/* ................................................................................................................. */
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s) || data == null)
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String) null);
+		String cRD = null;
+		String cRT = null;
+		String listData = data.searchData(s, commandResult);
+		String listSequences = "";
+		String cRS = null;
+		if (s.length() > 2 && data instanceof MolecularData) {
+			MolecularData mData = (MolecularData) data;
+			String seq = StringUtil.delete(s, '\t');
+			long[] states = new long[seq.length()];
+			boolean goodSequence = true;
+			boolean hasGaps = false;
+			for (int i = 0; i < seq.length(); i++) {
+				states[i] = mData.fromChar(seq.charAt(i));
+				if (states[i] == CategoricalState.impossible)
+					goodSequence = false;
+				if (states[i] == CategoricalState.inapplicable)
+					hasGaps = true;
+			}
+			if (goodSequence) {
+
+				int numFound = 0;
+
+				for (int it = 0; it < mData.getNumTaxa(); it++) {
+
+					for (int ic = 0; ic < mData.getNumChars(); ic++) {
+						int ls = sequenceMatches(states, hasGaps, mData, it, ic);
+						if (ls > 0) {
+							cRS = "selectSequence:" + it + " " + ic + " " + ls + " " + getID();
+							listSequences += "<li>Subsequence in taxon " + (it + 1) + " starting at site " + (ic + 1) + ": <a href=\"" + cRS + "\">Select</a></li>";
+							numFound++;
+						}
+					}
+				}
+				if (numFound != 1)
+					cRS = null;
+			}
+		}
+
+		if (commandResult != null)
+			cRD = commandResult.getValue();
+		String listTaxa = data.getTaxa().searchData(s, commandResult);
+		if (commandResult != null)
+			cRT = commandResult.getValue();
+		if (!StringUtil.blank(cRD) && StringUtil.blank(listTaxa) && StringUtil.blank(listSequences))
+			commandResult.setValue(cRD);
+		else if (StringUtil.blank(listData) && !StringUtil.blank(cRT) && StringUtil.blank(listSequences))
+			commandResult.setValue(cRT);
+		else if (StringUtil.blank(listData) && StringUtil.blank(listTaxa) && !StringUtil.blank(cRS))
+			commandResult.setValue(cRS);
+
+		String results = "";
+		if (!StringUtil.blank(listSequences))
+			results += listSequences;
+		if (!StringUtil.blank(listData))
+			results += listData;
+		if (!StringUtil.blank(listTaxa))
+			results += listTaxa;
+		if (!StringUtil.blank(results))
+
+			return "<h2>Matches to search string: \"" + s + "\"</h2>" + results;
+		else
+			return "<h2>No matches found (searched: \"" + s + "\")</h2>";
+	}
+
+	int sequenceMatches(long[] states, boolean hasGaps, MolecularData mData, int it, int ic) {
+		boolean done = false;
+		int ik = ic;
+
+		for (int ist = 0; ist < states.length; ist++) {
+			if (ik >= mData.getNumChars())
+				return 0;
+			long state = states[ist];
+			if (hasGaps) { // compare both sequences literally
+				long compareTo = mData.getState(ik++, it);
+				if ((CategoricalState.dataBitsMask & state) != (CategoricalState.dataBitsMask & compareTo))
+					return 0;
+			}
+			else { // go to next non-gap character and compare
+				long compareTo = CategoricalState.inapplicable;
+
+				while (ik < mData.getNumChars() && (compareTo = mData.getState(ik++, it)) == CategoricalState.inapplicable) {
+				}
+
+				if ((CategoricalState.dataBitsMask & state) != (CategoricalState.dataBitsMask & compareTo))
+					return 0;
+			}
+
+		}
+		if (hasGaps)
+			return states.length;
+		else
+			return ik - ic;
+
+	}
+
+	public UndoInstructions setUndoInstructions(int changeClass, int ic, int it, Object oldState, Object newState) {
+		return new UndoInstructions(changeClass, ic, it, oldState, newState, data, table);
+	}
+
+	/* ................................................................................................................. */
+	public int numDataColumnNamesAssistants() {
+		int num = 0;
+		if (ownerModule == null)
+			return 0;
+		for (int i = 0; i < ownerModule.getNumberOfEmployees(); i++) {
+			MesquiteModule e = (MesquiteModule) ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataColumnNamesAssistant) {
+				num++;
+			}
+		}
+		return num;
+	}
+
+	/* ................................................................................................................. */
+	public DataColumnNamesAssistant getDataColumnNamesAssistant(int num) {
+		int count = 0;
+		if (ownerModule == null)
+			return null;
+		for (int i = 0; i < ownerModule.getNumberOfEmployees(); i++) {
+			MesquiteModule e = (MesquiteModule) ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataColumnNamesAssistant) {
+				if (count >= num)
+					return (DataColumnNamesAssistant) e;
+				count++;
+			}
+		}
+		return null;
+	}
+
+	public boolean showFindMenuItems() {
+		return true;
+	}
+
+	public String getFindLabel() {
+		return "Find String in Matrix...";
+	}
+
+	public String getFindMessageName() {
+		return "cell of Character Matrix";
+	}
+
+	/* ................................................................................................................. */
+	public MesquiteTable getTable() {
+		return table;
+	}
+
+	/* ................................................................................................................. */
+	private boolean containsShift(String s) {
+		if (s == null)
+			return false;
+		else
+			return (s.indexOf("shift") >= 0);
+	}
+
+	/* ................................................................................................................. */
+	/* highlights ith cell with footnote */
+	boolean highlightCellWithFootnote(String s, int i) {
+		MesquiteTable table = getTable();
+		if (table == null)
+			return false;
+		int count = 0;
+		Taxa taxa = data.getTaxa();
+		// search taxon footnotes
+		for (int it = 0; it < table.getNumRows(); it++) {
+			String c = taxa.getAnnotation(it);
+			if (StringUtil.foundIgnoreCase(c, s)) {
+				if (count == i) {
+					selectAndFocus(-1, it);
+					return true;
+				}
+				count++;
+			}
+		}
+		// search character footnotes
+		for (int ic = 0; ic < table.getNumColumns(); ic++) {
+			String c = data.getAnnotation(ic);
+			if (StringUtil.foundIgnoreCase(c, s)) {
+				if (count == i) {
+					selectAndFocus(ic, -1);
+					return true;
+				}
+				count++;
+			}
+		}
+		// search cell footnotes
+		for (int ic = 0; ic < table.getNumColumns(); ic++) {
+			for (int it = 0; it < table.getNumRows(); it++) {
+
+				String c = data.getAnnotation(ic, it);
+				if (StringUtil.foundIgnoreCase(c, s)) {
+					if (count == i) {
+						selectAndFocus(ic, it);
+						return true;
+					}
+					count++;
+				}
+			}
+		}
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	int rowFirstTouched = 0;
+
+	int columnFirstTouched = 0;
+
+	int rowLastTouched = 0;
+
+	int columnLastTouched = 0;
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.incorporate(super.getSnapshot(file), false);
+		temp.addLine("setTool " + getCurrentTool().getName());
+
+		if (table != null && table.cellColorer != null)
+			temp.addLine("colorCells ", (MesquiteModule) table.cellColorer);
+		if (table != null && table.rowNamesColorer != null)
+			temp.addLine("colorRowNames ", (MesquiteModule) table.rowNamesColorer);
+		if (table != null && table.columnNamesColorer != null)
+			temp.addLine("colorColumnNames ", (MesquiteModule) table.columnNamesColorer);
+		if (table != null && table.textColorer != null)
+			temp.addLine("colorText ", (MesquiteModule) table.textColorer);
+		if (table != null && table.bgColor != null) {
+			String bName = ColorDistribution.getStandardColorName(table.bgColor);
+			if (bName != null)
+				temp.addLine("setBackground " + StringUtil.tokenize(bName));// quote
+		}
+		temp.addLine("toggleShowNames " + table.showNames.toOffOnString());
+		temp.addLine("toggleShowTaxonNames " + showTaxonNames.toOffOnString());
+		temp.addLine("toggleTight " + table.tight.toOffOnString());
+		temp.addLine("toggleThinRows " + table.thinRows.toOffOnString());
+		temp.addLine("toggleShowChanges " + table.showChanges.toOffOnString());
+		temp.addLine("toggleSeparateLines " + table.statesSeparateLines.toOffOnString());
+		temp.addLine("toggleShowStates " + table.showStates.toOffOnString());
+		temp.addLine("toggleAutoWCharNames " + table.autoWithCharNames.toOffOnString());
+		temp.addLine("toggleAutoTaxonNames " + table.autoRowNameWidth.toOffOnString());
+		temp.addLine("toggleShowDefaultCharNames " + table.showDefaultCharNames.toOffOnString());
+		temp.addLine("toggleConstrainCW " + constrainedCW.toOffOnString());
+		if (widthsSet)
+			temp.addLine("setColumnWidth " + columnWidth);
+		temp.addLine("toggleBirdsEye " + table.showBirdsEyeView.toOffOnString());
+		temp.addLine("toggleShowPaleGrid " + table.showPaleGrid.toOffOnString());
+		temp.addLine("toggleShowPaleCellColors " + table.showPaleCellColors.toOffOnString());
+		temp.addLine("toggleShowPaleExcluded " + showPaleExcluded.toOffOnString());
+		temp.addLine("togglePaleInapplicable " + table.paleInapplicable.toOffOnString());
+		temp.addLine("toggleShowBoldCellText " + table.showBoldCellText.toOffOnString());
+		temp.addLine("toggleAllowAutosize " + table.allowAutosize.toOffOnString());
+		temp.addLine("toggleColorsPanel " + showColorLegend.toOffOnString());
+		if (data instanceof CategoricalData && !(data instanceof MolecularData)) {
+			temp.addLine("toggleDiagonal " + useDiagonal.toOffOnString());
+			temp.addLine("setDiagonalHeight " + ((ColumnNamesPanel) table.getColumnNamesPanel()).getDiagonalHeight());
+
+		}
+
+		temp.addLine("toggleLinkedScrolling " + linkedScrolling.toOffOnString());
+		temp.addLine("toggleScrollLinkedTables " + scrollLinkedTables.toOffOnString());
+
+		for (int i = 0; i < ownerModule.getNumberOfEmployees(); i++) {
+			MesquiteModule e = (MesquiteModule) ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataColumnNamesAssistant) {
+				temp.addLine("hireDataInfoStrip ", e);
+			}
+		}
+		for (int i = 0; i < ownerModule.getNumberOfEmployees(); i++) {
+			Object e = ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataWindowAssistant && !(e instanceof DataWindowAssistantI)) {
+				temp.addLine("newAssistant ", ((MesquiteModule) e));
+			}
+		}
+		if (matrixInfoPanelEverShown) {
+			if (matrixInfoPanel != null) {
+				temp.addLine("getInfoPanel");
+				temp.addLine("tell It");
+				temp.incorporate(matrixInfoPanel.getSnapshot(file), true);
+				temp.addLine("endTell");
+			}
+			temp.addLine("toggleInfoPanel " + infoPanelOn.toOffOnString());
+			temp.addLine("toggleEditingNotPermitted " + editingNotPermitted.toOffOnString());
+		}
+		return temp;
+	}
+
+	NameReference colorNameRef = NameReference.getNameReference("color");
+
+	private void setColor(int ic, int it, int c) {
+		if (data == null)
+			return;
+		if (ic < 0 && it < 0) {
+		}
+		else if (ic < 0) { // taxon
+			data.getTaxa().setAssociatedLong(colorNameRef, it, c);
+		}
+		else if (it < 0) { // character
+			data.setAssociatedLong(colorNameRef, ic, c);
+		}
+		else if (!MesquiteLong.isCombinable(c) || c < 0) {
+			data.setCellObject(colorNameRef, ic, it, null);
+		}
+		else {
+			MesquiteInteger ms = new MesquiteInteger((int) c);
+			data.setCellObject(colorNameRef, ic, it, ms);
+		}
+	}
+
+	/* ................................................................................................................. */
+	private void removeColor(int ic, int it) {
+		setColor(ic, it, -1);
+	}
+
+	void colorsPanelGoAway() {
+		if (table.cellColorer != null)
+			table.cellColorer.colorsLegendGoAway();
+		setColorLegend(null, null, false);
+	}
+
+	void goToColor(Color c) {
+		if (c == null)
+			return;
+		if ((table.cellColorer == null || ((MesquiteModule) table.cellColorer).nameMatches("#NoColor")) && (table.columnNamesColorer == null || ((MesquiteModule) table.columnNamesColorer).nameMatches("#NoColor")))
+			return;
+
+		if (!(table.cellColorer == null || ((MesquiteModule) table.cellColorer).nameMatches("#NoColor")))
+			for (int ic = 0; ic < data.getNumChars(); ic++) {
+				CommandRecord.tick("Looking for color in cells of character " + (ic + 1));
+				for (int it = 0; it < data.getNumTaxa(); it++)
+					if (c.equals(table.cellColorer.getCellColor(ic, it))) {
+						table.setFocusedCell(ic, it, true);
+						return;
+					}
+			}
+		CommandRecord.tick("Looking for color in character headings");
+		if (!(table.columnNamesColorer == null || ((MesquiteModule) table.columnNamesColorer).nameMatches("#NoColor")))
+			for (int ic = 0; ic < data.getNumChars(); ic++)
+				if (c.equals(table.columnNamesColorer.getCellColor(ic, -1))) {
+					table.setFocusedCell(ic, -1, true);
+					return;
+				}
+	}
+
+	/* ................................................................................................................. */
+	int numContigFound = 0;
+
+	boolean[][] contigSel;
+
+	void selectContiguous(int seedColumn, int seedRow, Color c, boolean subtractFromSelection, boolean horizontal, boolean forwards, int level) {
+		if (seedColumn < 0 || seedRow < 0 || seedColumn >= table.getNumColumns() || seedRow >= table.getNumRows() || contigSel[seedColumn][seedRow])
+			return;
+		level++;
+		boolean done = false;
+		if (horizontal) {
+			if (forwards) {
+				int ic;
+				for (ic = seedColumn; ic < table.getNumColumns() && !done; ic++)
+					done = contigSel[ic][seedRow] || !checkCell(ic, seedRow, c, subtractFromSelection);
+
+				int end = ic - 1;
+				for (ic = seedColumn; ic < end; ic++) {
+					selectContiguous(ic, seedRow + 1, c, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(ic, seedRow - 1, c, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+			else {
+				int ic;
+				for (ic = seedColumn; ic >= 0 && !done; ic--)
+					done = contigSel[ic][seedRow] || !checkCell(ic, seedRow, c, subtractFromSelection);
+
+				int end = ic + 1;
+				for (ic = seedColumn; ic > end; ic--) {
+					selectContiguous(ic, seedRow + 1, c, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(ic, seedRow - 1, c, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+		}
+		else {
+			if (forwards) {
+				int it;
+				for (it = seedRow; it < table.getNumRows() && !done; it++)
+					done = contigSel[seedColumn][it] || !checkCell(seedColumn, it, c, subtractFromSelection);
+				int end = it - 1;
+				for (it = seedRow; it < end; it++) {
+					selectContiguous(seedColumn + 1, it, c, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(seedColumn - 1, it, c, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+			else {
+				int it;
+				for (it = seedRow; it >= 0 && !done; it--)
+					done = contigSel[seedColumn][it] || !checkCell(seedColumn, it, c, subtractFromSelection);
+				int end = it + 1;
+				for (it = seedRow; it > end; it--) {
+					selectContiguous(seedColumn + 1, it, c, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(seedColumn - 1, it, c, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+		}
+	}
+
+	boolean checkCell(int ic, int it, Color c, boolean subtractFromSelection) {
+		if (contigSel[ic][it])
+			return false;
+		contigSel[ic][it] = true;
+		// table.selectCell(ic, it); //select cell
+		if (satisfiesCriteria(c, table.cellColorer.getCellColor(ic, it))) {
+			numContigFound++;
+			if (numContigFound % 100 == 0)
+				CommandRecord.tick(Integer.toString(numContigFound) + " cells found");
+			if (subtractFromSelection) {
+				table.deselectCell(ic, it); // deselect cell
+			}
+			else
+				table.selectCell(ic, it); // select cell
+			// table.repaintAll();
+			return true;
+		}
+		return false;
+	}
+
+	private boolean satisfiesCriteria(Color c, Color c2) {
+
+		if (c == c2)
+			return true;
+		else if (c != null && c2 != null) {
+			if (c.equals(c2))
+				return true;
+		}
+		return false;
+	}
+
+	public void selectSameColor(int column, int row, boolean restrictToCharacter, boolean restrictToTaxon, boolean contiguous, boolean subtractFromSelection) {
+		if (data == null || table == null || table.cellColorer == null || ((MesquiteModule) table.cellColorer).nameMatches("#NoColor"))
+			return;
+		Color c = table.cellColorer.getCellColor(column, row);
+		if (contiguous) {
+			if (contigSel == null || contigSel.length != table.getNumColumns() || contigSel[0].length != table.getNumRows())
+				contigSel = new boolean[table.getNumColumns()][table.getNumRows()];
+			for (int i = 0; i < contigSel.length; i++)
+				for (int k = 0; k < table.getNumRows(); k++)
+					contigSel[i][k] = false;
+			numContigFound = 0;
+			selectContiguous(column + 1, row, c, subtractFromSelection, true, true, 0);
+			selectContiguous(column - 1, row, c, subtractFromSelection, true, false, 0);
+			selectContiguous(column, row + 1, c, subtractFromSelection, false, true, 0);
+			selectContiguous(column, row - 1, c, subtractFromSelection, false, false, 0);
+			checkCell(column, row, c, subtractFromSelection);
+		}
+		else {
+			int rowStart = 0;
+			int rowEnd = data.getNumTaxa();
+			int columnStart = 0;
+			int columnEnd = data.getNumChars();
+			if (restrictToTaxon) {
+				rowStart = row;
+				rowEnd = row + 1;
+			}
+			else if (restrictToCharacter) {
+				columnStart = column;
+				columnEnd = column + 1;
+			}
+			for (int ic = columnStart; ic < columnEnd; ic++)
+				for (int it = rowStart; it < rowEnd; it++) {
+					Color c2 = table.cellColorer.getCellColor(ic, it);
+					if (satisfiesCriteria(c, c2)) {
+						if (subtractFromSelection)
+							table.deselectCell(ic, it);
+						else
+							table.selectCell(ic, it);
+					}
+				}
+			table.repaintAll();
+		}
+
+	}
+	
+	public void selectBlockInTaxon(int column, int row) {
+		if (data == null || table == null)
+			return;
+		if (!data.isInapplicable(column,  row)) {
+			for (int ic=column; ic>=0; ic--){
+				if (!data.isInapplicable(ic, row))
+					table.selectCell(ic, row);
+				else
+					break;
+			}
+			for (int ic=column+1; ic<data.getNumChars(); ic++){
+				if (!data.isInapplicable(ic, row))
+					table.selectCell(ic, row);
+				else
+					break;
+			}
+	
+		}
+
+
+	}
+
+
+	public void selectSameColorRow(int column, int row, boolean subtractFromSelection) {
+		if (data == null || table == null || table.rowNamesColorer == null || ((MesquiteModule) table.rowNamesColorer).nameMatches("#NoColor"))
+			return;
+		Color c = table.rowNamesColorer.getCellColor(column, row);
+		int rowStart = 0;
+		int rowEnd = data.getNumTaxa();
+		for (int it = rowStart; it < rowEnd; it++) {
+			Color c2 = table.rowNamesColorer.getCellColor(column, it);
+			if (satisfiesCriteria(c, c2)) {
+				if (subtractFromSelection)
+					table.deselectRow(it);
+				else
+					table.selectRow(it);
+			}
+
+			table.repaintAll();
+		}
+
+	}
+
+	/* ................................................................................................................. */
+	MesquiteModule findCellColorerMatrix(String arguments) {
+		Parser parser = new Parser();
+		String s1 = parser.getFirstToken(arguments);
+		String s2 = parser.getNextToken();
+		int index = MesquiteInteger.fromFirstToken(arguments, pos);
+		if (MesquiteInteger.isCombinable(index)) {
+			// has number, but if simplification is on then it may not be good guide.
+			ListableVector emp = ownerModule.getEmployeeVector();
+			Enumeration enumeration = emp.elements();
+			int count = 0;
+			while (enumeration.hasMoreElements()) {
+				MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+				if (mb instanceof CellColorerMatrix) {
+					if (count == index) {
+						if (!StringUtil.blank(s2)) { // name is included among arguments
+							if (s2.equals(mb.getName()) || s2.equals(mb.getNameForMenuItem()))
+								return mb;
+							else { // name doesn't match; see if there is a better match
+								MesquiteModule mb2 = (MesquiteModule) ownerModule.findEmployeeWithName(s2, true);
+								if (mb2 == null)
+									return mb;
+								else
+									return mb2;
+							}
+						}
+						else
+							return mb;
+					}
+					count++;
+				}
+			}
+		}
+		else {
+			MesquiteModule mb = (MesquiteModule) ownerModule.findEmployeeWithName(s1, true);
+			if (mb instanceof CellColorerMatrix) { // note: if by name doesn't turn off!
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	MesquiteModule findCellColorer(String arguments) {
+		Parser parser = new Parser();
+		String s1 = parser.getFirstToken(arguments);
+		String s2 = parser.getNextToken();
+		int index = MesquiteInteger.fromFirstToken(arguments, pos);
+		if (MesquiteInteger.isCombinable(index)) {
+			// has number, but if simplification is on then it may not be good guide.
+			ListableVector emp = ownerModule.getEmployeeVector();
+			Enumeration enumeration = emp.elements();
+			int count = 0;
+			while (enumeration.hasMoreElements()) {
+				MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+				if (mb instanceof CellColorer) {
+					if (count == index) {
+						if (!StringUtil.blank(s2)) { // name is included among arguments
+							if (s2.equals(mb.getName()) || s2.equals(mb.getNameForMenuItem()))
+								return mb;
+							else { // name doesn't match; see if there is a better match
+								MesquiteModule mb2 = (MesquiteModule) ownerModule.findEmployeeWithName(s2, true);
+								if (mb2 == null)
+									return mb;
+								else
+									return mb2;
+							}
+						}
+						else
+							return mb;
+					}
+					count++;
+				}
+			}
+		}
+		else {
+			MesquiteModule mb = (MesquiteModule) ownerModule.findEmployeeWithName(s1, true);
+			if (mb instanceof CellColorer) { // note: if by name doesn't turn off!
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	MesquiteModule findCellColorerTaxa(String arguments) {
+		Parser parser = new Parser();
+		String s1 = parser.getFirstToken(arguments);
+		String s2 = parser.getNextToken();
+		int index = MesquiteInteger.fromFirstToken(arguments, pos);
+		if (MesquiteInteger.isCombinable(index)) {
+			// has number, but if simplification is on then it may not be good guide.
+			ListableVector emp = ownerModule.getEmployeeVector();
+			Enumeration enumeration = emp.elements();
+			int count = 0;
+			while (enumeration.hasMoreElements()) {
+				MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+				if (mb instanceof CellColorerTaxa) {
+					if (count == index) {
+						if (!StringUtil.blank(s2)) { // name is included among arguments
+							if (s2.equals(mb.getName()) || s2.equals(mb.getNameForMenuItem()))
+								return mb;
+							else { // name doesn't match; see if there is a better match
+								MesquiteModule mb2 = (MesquiteModule) ownerModule.findEmployeeWithName(s2, true);
+								if (mb2 == null)
+									return mb;
+								else
+									return mb2;
+							}
+						}
+						else
+							return mb;
+					}
+					count++;
+				}
+			}
+		}
+		else {
+			MesquiteModule mb = (MesquiteModule) ownerModule.findEmployeeWithName(s1, true);
+			if (mb instanceof CellColorerTaxa) { // note: if by name doesn't turn off!
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	MesquiteModule findCellColorerCharacters(String arguments) {
+		Parser parser = new Parser();
+		String s1 = parser.getFirstToken(arguments);
+		String s2 = parser.getNextToken();
+		int index = MesquiteInteger.fromFirstToken(arguments, pos);
+		if (MesquiteInteger.isCombinable(index)) {
+			// has number, but if simplification is on then it may not be good guide.
+			ListableVector emp = ownerModule.getEmployeeVector();
+			Enumeration enumeration = emp.elements();
+			int count = 0;
+			while (enumeration.hasMoreElements()) {
+				MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+				if (mb instanceof CellColorerCharacters) {
+					if (count == index) {
+						if (!StringUtil.blank(s2)) { // name is included among arguments
+							if (s2.equals(mb.getName()) || s2.equals(mb.getNameForMenuItem()))
+								return mb;
+							else { // name doesn't match; see if there is a better match
+								MesquiteModule mb2 = (MesquiteModule) ownerModule.findEmployeeWithName(s2, true);
+								if (mb2 == null)
+									return mb;
+								else
+									return mb2;
+							}
+						}
+						else
+							return mb;
+					}
+					count++;
+				}
+			}
+		}
+		else {
+			MesquiteModule mb = (MesquiteModule) ownerModule.findEmployeeWithName(s1, true);
+			if (mb instanceof CellColorerCharacters) { // note: if by name doesn't turn off!
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Renames the matrix", "[name of matrix]", commandName, "renameMatrix")) {
+			String token = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+			if (StringUtil.blank(token) && !MesquiteThread.isScripting()) {
+				token = MesquiteString.queryString(this, "Rename matrix", "New Name of Matrix:", data.getName(), 2);
+				if (StringUtil.blank(token))
+					return null;
+			}
+			data.setName(token);
+			MesquiteWindow.resetAllTitles();
+			MesquiteTrunk.mesquiteTrunk.resetAllMenuBars();
+		}
+		/*
+		 * else if (checker.compare(this.getClass(), "Selects cells of same color", "[column touched][row touched]", commandName, "selectSameColor")) { if (data == null || table == null || table.cellColorer == null) return null; MesquiteInteger io = new MesquiteInteger(0); int column= MesquiteInteger.fromString(arguments, io); int row= MesquiteInteger.fromString(arguments, io); boolean shiftDown = arguments.indexOf("shift")>=0; if (MesquiteInteger.isCombinable(column)&& (MesquiteInteger.isComb [...]
+		 * row); } }
+		 */
+		else if (checker.compare(this.getClass(), "Returns the matrix info panel", null, commandName, "getInfoPanel")) {
+			return matrixInfoPanel;
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether the info panel is on", null, commandName, "toggleInfoPanel")) {
+			infoPanelOn.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			setMatrixInfoPanel(infoPanelOn.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether editing is permitted or not", null, commandName, "toggleEditingNotPermitted")) {
+			editingNotPermitted.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			data.setEditorInhibition(editingNotPermitted.getValue());
+			if (ibeamTool!=null)
+				ibeamTool.setEnabled(!editingNotPermitted.getValue());
+			//setMatrixInfoPanel(infoPanelOn.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Selects sequence", "[number of taxon][number of starting site][number of ending site]", commandName, "selectSequence")) {
+			int it = MesquiteInteger.fromFirstToken(arguments, pos);
+			int ic1 = MesquiteInteger.fromString(arguments, pos);
+			int num = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(it) && MesquiteInteger.isCombinable(ic1) && MesquiteInteger.isCombinable(num)) {
+				table.selectBlock(ic1, it, ic1 + num - 1, it);
+				if (!table.isCellVisible(ic1, it)) {
+					table.setFocusedCell(ic1, it, true);
+				}
+				table.repaintAll();
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Shows taxon", "[id of taxa block][number of taxon]", commandName, "showTaxon")) {
+			pos.setValue(0);
+			long whichTaxaBlock = MesquiteInteger.fromString(arguments, pos);
+			Taxa taxa = data.getTaxa();
+			if (whichTaxaBlock != taxa.getID())
+				return null;
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if (which >= 0 && which < taxa.getNumTaxa()) {
+				if (!table.isCellVisible(-1, which)) {
+					table.setFocusedCell(-1, which, true);
+					table.repaintAll();
+				}
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Selects taxon", "[number of taxon]", commandName, "selectTaxon")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			Taxa taxa = data.getTaxa();
+			if (which >= 0 && which < taxa.getNumTaxa()) {
+				if (!table.isCellVisible(-1, which)) {
+					table.setFocusedCell(-1, which, true);
+					table.repaintAll();
+				}
+				taxa.setSelected(which, !taxa.getSelected(which));
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Selects character", "[number of character]", commandName, "selectCharacter")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (which >= 0 && which < data.getNumChars()) {
+				if (!table.isCellVisible(which, -1)) {
+					table.setFocusedCell(which, -1, true);
+					table.repaintAll();
+				}
+				data.setSelected(which, !data.getSelected(which));
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Deletes the matrix", null, commandName, "deleteMatrix")) {
+			if (!MesquiteThread.isScripting())
+				if (!AlertDialog.query(this, "Delete matrix?", "Are you sure you want to delete the matrix?  You cannot undo this."))
+					return null;
+			data.deleteMe(false);
+
+		}
+		else if (checker.compare(this.getClass(), "Allows one to set the missing data symbol", null, commandName, "setUnassignedSymbol")) {
+			if (!MesquiteThread.isScripting()) {
+				MesquiteString ms = new MesquiteString("" + data.getUnassignedSymbol());
+				if (QueryDialogs.queryChar(this, "Missing Data Symbol", "Missing Data Symbol", ms)) {
+					String s = ms.getValue();
+					if (StringUtil.blank(s))
+						return null;
+					data.setUnassignedSymbol(s.charAt(0)); // check if editing missing data
+					table.repaintAll();
+				}
+				else
+					return null;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Allows one to set the inapplicable symbol", null, commandName, "setInapplicableSymbol")) {
+			if (!MesquiteThread.isScripting()) {
+				MesquiteString ms = new MesquiteString("" + data.getInapplicableSymbol());
+				if (QueryDialogs.queryChar(this, "Inapplicable Symbol", "Inapplicable Symbol", ms)) {
+					String s = ms.getValue();
+					data.setInapplicableSymbol(s.charAt(0)); // check if editing missing data
+					table.repaintAll();
+				}
+				else
+					return null;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows the state names editor", null, commandName, "showStateNamesEditor")) {
+			MesquiteModule mb = ownerModule.findEmployeeWithDuty(mesquite.categ.StateNamesEditor.StateNamesEditor.class);
+			if (mb != null) {
+				mb.doCommand("makeWindow", null, checker);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows the list of characters", null, commandName, "showList")) {
+			data.showList();
+		}
+		else if (checker.compare(this.getClass(), "Shows the list of taxa", null, commandName, "showTaxaList")) {
+			data.getTaxa().showMe();
+		}
+		else if (checker.compare(this.getClass(), "Sets the current tool", "[name of tool]", commandName, "setTool")) {
+			ToolPalette palette = getPalette();
+			if (palette == null)
+				return null;
+			setCurrentTool((TableTool) palette.getToolWithName(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether scroll is of linked tables or not.", "[on = linked; off]", commandName, "toggleLinkedScrolling")) {
+			boolean current = linkedScrolling.getValue();
+			linkedScrolling.toggleValue(ParseUtil.getFirstToken(arguments, new MesquiteInteger(0)));
+			if (linkedScrolling.getValue()) { // synch the two tables
+				table.setFirstColumnVisibleLinked(table.getFirstColumnVisible());
+				table.setFirstRowVisibleLinked(table.getFirstRowVisible());
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether scroll is of linked tables or not.", "[on = linked; off]", commandName, "toggleScrollLinkedTables")) {
+			boolean current = scrollLinkedTables.getValue();
+			scrollLinkedTables.toggleValue(ParseUtil.getFirstToken(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether character names are shown diagonally.", "[on = diagonal; off]", commandName, "toggleDiagonal")) {
+			useDiagonal.toggleValue(ParseUtil.getFirstToken(arguments, new MesquiteInteger(0)));
+			table.setColumnNamesDiagonal(useDiagonal.getValue());
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets height of the column names area when in diagonal mode", "[height]", commandName, "setDiagonalHeight")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int h = MesquiteInteger.fromFirstToken(arguments, io);
+			if (MesquiteInteger.isCombinable(h) && h >= 30 && h <= 500)
+				((ColumnNamesPanel) table.getColumnNamesPanel()).setDiagonalHeight(h);
+
+		}
+		else if (checker.compare(this.getClass(), "Present the popup menu to select options for scroll to similar tool", null, commandName, "scrollToolOptions")) {
+			if (scrollTool == null)
+				return null;
+			MesquiteButton button = scrollTool.getButton();
+			if (button != null) {
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x = MesquiteInteger.fromString(arguments, io); // getting x and y from arguments
+				int y = MesquiteInteger.fromString(arguments, io);
+				MesquitePopup popup = new MesquitePopup(button);
+				MesquiteCheckMenuItem scrollLinkedItems = new MesquiteCheckMenuItem("Scroll Other Matrices", ownerModule, MesquiteModule.makeCommand("toggleScrollLinkedTables", this), null, null);
+				scrollLinkedItems.set(scrollLinkedTables.getValue());
+				popup.add(scrollLinkedItems);
+				popup.showPopup(x, y + 6);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Scrolls to next similar characters", "[column touched] [row touched] [percent horizontal] [percent vertical] [modifiers]", commandName, "simScroll")) {
+			if (table != null && data != null) {
+				boolean optionDown = arguments.indexOf("option") >= 0;
+
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column = MesquiteInteger.fromString(arguments, io);
+				int subRow = MesquiteInteger.fromString(arguments, io);
+				int percentHorizontal = MesquiteInteger.fromString(arguments, io);
+				if (subRow >= 0 && column >= 0 && column <= data.getNumChars()) {
+					DataColumnNamesAssistant assistant = getDataColumnNamesAssistant(subRow);
+					if (assistant != null) {
+						MesquiteInteger startBlock = new MesquiteInteger(-1);
+						MesquiteInteger endBlock = new MesquiteInteger(-1);
+						boolean found = assistant.getNextBlock(column, !optionDown, startBlock, endBlock);
+
+						if (found && (endBlock.getValue() < table.getFirstColumnVisible() || startBlock.getValue() > table.getLastColumnVisible())) { // we now that it has been found, and is definitely off screen
+							int blockSize = endBlock.getValue() - startBlock.getValue() + 1;
+							// if (blockSize<=table.getNumColumnsVisible()) { // can get it all in at once
+							if (scrollLinkedTables.getValue()) {
+								if (optionDown) // looking left
+									table.setLastColumnVisibleLinked(endBlock.getValue());
+								else
+									table.setFirstColumnVisibleLinked(startBlock.getValue());
+							}
+							else if (optionDown) // looking left
+								table.setLastColumnVisible(endBlock.getValue());
+							else
+								table.setFirstColumnVisible(startBlock.getValue());
+							// }
+						}
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets background color of matrix", "[name of color]", commandName, "setBackground")) {
+			String token = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			table.bgColor = bc;
+			bgColorName.setValue(token);
+			if (!MesquiteThread.isScripting())
+				table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Deletes the selected rows", null, commandName, "deleteSelectedDataInfoStrips")) {
+			// deleteSelectedRows(true);
+		}
+		else if (checker.compare(this.getClass(), "Hires a DataColumnNamesAssistant module for displaying info strips", "[name of module]", commandName, "hireDataInfoStrip")) {
+			String name = ParseUtil.getToken(arguments, new MesquiteInteger(0));
+			DataColumnNamesAssistant assistant = (DataColumnNamesAssistant) ownerModule.hireNamedEmployee(DataColumnNamesAssistant.class, arguments);
+			if (assistant != null) {
+				assistant.setUseMenubar(false);
+				// addListAssistant(assistant);
+				ownerModule.resetContainingMenuBar();
+				((ColumnNamesPanel) table.getColumnNamesPanel()).appendInfoStrip();
+				assistant.setTableAndData(table, data);
+				assistant.setElement(0);
+				table.resetTableSize(true);
+				table.repaintAll();
+			}
+			else {
+				for (int i = 0; i < ownerModule.getNumberOfEmployees(); i++) { // if already hired then pass along commands
+					MesquiteModule e = (MesquiteModule) ownerModule.getEmployeeVector().elementAt(i);
+					if (e instanceof DataColumnNamesAssistant) {
+						if (e.nameMatches(arguments) && !e.canHireMoreThanOnce())
+							return assistant;
+					}
+				}
+			}
+
+			return assistant;
+		}
+		else if (checker.compare(this.getClass(), "Assigns color assigned to selected cells", "[name of color]", commandName, "assignColor")) {
+			if (table.anythingSelected()) {
+
+				int bc = ColorDistribution.standardColorNames.indexOf(ParseUtil.getFirstToken(arguments, new MesquiteInteger(0)));
+				if (bc >= 0 && MesquiteInteger.isCombinable(bc)) {
+					for (int ic = -1; ic < data.getNumChars(); ic++)
+						for (int it = -1; it < data.getNumTaxa(); it++) {
+							if (table.isCellSelectedAnyWay(ic, it))
+								setColor(ic, it, bc);
+						}
+				}
+				if (!MesquiteThread.isScripting())
+					table.repaintAll();
+			}
+			else if (!MesquiteThread.isScripting())
+				ownerModule.alert("Cells must be selected in order to assign colors");
+		}
+		else if (checker.compare(this.getClass(), "Removes color assigned from selected cells", null, commandName, "removeColor")) {
+			if (table.anythingSelected()) {
+
+				for (int ic = -1; ic < data.getNumChars(); ic++)
+					for (int it = -1; it < data.getNumTaxa(); it++) {
+						if (table.isCellSelectedAnyWay(ic, it))
+							removeColor(ic, it);
+					}
+
+				if (!MesquiteThread.isScripting())
+					table.repaintAll();
+			}
+			else if (!MesquiteThread.isScripting())
+				ownerModule.alert("Cells must be selected in order to assign colors");
+		}
+		else if (checker.compare(this.getClass(), "Finds footnote containing string, selects cell and ensures it is shown", null, commandName, "findFootnoteString")) {
+			if (MesquiteThread.isScripting()) // todo: should support argument passed
+				return null;
+			findNumber = 0;
+			String temp = MesquiteString.queryString(this, "Find cell", "Find first footnote containing the following string:", findFootnoteString, 2);
+			if (StringUtil.blank(temp)) {
+				return null;
+			}
+			findString = "";
+			findFootnoteString = temp;
+			if (!highlightCellWithFootnote(findFootnoteString, findNumber))
+				findNumber = 0;
+			else
+				findNumber = 1;
+		}
+		else if (checker.compare(this.getClass(), "Finds footnote containing string, selects cell and ensures it is shown", null, commandName, "findAgain")) {
+			if (MesquiteThread.isScripting()) // todo: should support argument passed
+				return null;
+			if (findString != null && !findString.equals("")) {
+				return super.doCommand(commandName, arguments, checker);
+			}
+			if (StringUtil.blank(findFootnoteString))
+				return null;
+			if (!highlightCellWithFootnote(findFootnoteString, findNumber))
+				findNumber = 0;
+			else
+				findNumber++;
+		}
+		else if (checker.compare(this.getClass(), "Not functioning", null, commandName, "moveSelection")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column = MesquiteInteger.fromString(arguments, io);
+			int row = MesquiteInteger.fromString(arguments, io);
+		}
+		else if (checker.compare(this.getClass(), "Adds or inserts characters into matrix", "[character number after which new characters to be inserted] [number of new characters]", commandName, "addCharacters")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int starting = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, io));
+			int number = MesquiteInteger.fromString(arguments, io);
+			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED, data);
+			data.resetJustAdded();
+			UndoReference undoReference = new UndoReference(undoInstructions, ownerModule);
+			if (data.addParts(starting, number)) {
+				table.setNumColumns(data.getNumChars());
+				data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] { starting, number }, undoReference));
+				data.addInLinked(starting, number, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deletes characters", "[first character to be deleted] [number of characters]", commandName, "deleteCharacters")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int starting = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, io));
+			int number = MesquiteInteger.fromString(arguments, io);
+			if (data.deleteCharacters(starting, number, false)) {
+				data.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED, new int[] { starting, number }));
+				data.deleteInLinked(starting, number, true);
+				table.setNumColumns(data.getNumChars());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Excludes selected characters", "[] []", commandName, "excludeSelectedCharacters")) {
+			if (data.setInclusionExclusion(ownerModule, table, false)) {
+			}
+		}
+		else if (checker.compare(this.getClass(), "Includes selected characters", "[] []", commandName, "includeSelectedCharacters")) {
+			if (data.setInclusionExclusion(ownerModule, table, true)) {
+			}
+		}
+		else if (checker.compare(this.getClass(), "Adds taxa", "[taxon number after which new taxa to be inserted] [number of new taxa]", commandName, "addTaxa")) {
+			if (data.getTaxa().isEditInhibited())
+				ownerModule.discreetAlert("You cannot add taxa; the taxa block is locked.");
+		MesquiteInteger io = new MesquiteInteger(0);
+			int starting = Taxon.toInternal(MesquiteInteger.fromString(arguments, io));
+			int number = MesquiteInteger.fromString(arguments, io);
+			if (data.getTaxa().addTaxa(starting, number, true))
+				table.setNumRows(data.getNumTaxa());
+		}
+		else if (checker.compare(this.getClass(), "Deletes taxa", "[first taxon to be deleted] [number of taxa]", commandName, "deleteTaxa")) {
+			if (data.getTaxa().isEditInhibited())
+				ownerModule.discreetAlert("You cannot delete taxa; the taxa block is locked.");
+
+			MesquiteInteger io = new MesquiteInteger(0);
+			int starting = Taxon.toInternal(MesquiteInteger.fromString(arguments, io));
+			int number = MesquiteInteger.fromString(arguments, io);
+			if (starting == 0 && number == data.getTaxa().getNumTaxa()) {
+				ownerModule.discreetAlert("You cannot delete all taxa; the command will be ignored");
+				return null;
+			}
+			if (data.getTaxa().deleteTaxa(starting, number, true))
+				table.setNumRows(data.getNumTaxa());
+		}
+		else if (checker.compare(this.getClass(), "Moves the selected characters ", "[column to move after; -1 if at start]", commandName, "moveCharsTo")) {
+			if (data.getEditorInhibition()) {
+				ownerModule.discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+				return null;
+			}
+			if (!table.anyColumnSelected()) {
+				ownerModule.discreetAlert("Sorry, to move characters they must be selected first.");
+				return null;
+			}
+			MesquiteInteger io = new MesquiteInteger(0);
+			int justAfter = MesquiteInteger.fromString(arguments, io);
+			if (!MesquiteInteger.isCombinable(justAfter))
+				justAfter = MesquiteInteger.queryInteger(this, "Move characters", "After which column should the selected characters be moved (enter 0 to move to first place)?", 0, 0, table.getNumColumns() * 10);
+			if (MesquiteInteger.isCombinable(justAfter))
+				table.selectedColumnsDropped(justAfter - 1); // -1 to convert to internal representation
+		}
+		else if (checker.compare(this.getClass(), "Moves the selected taxa ", "[row to move after; -1 if at start]", commandName, "moveTaxaTo")) {
+			if (!table.anyRowSelected()) {
+				ownerModule.discreetAlert("Sorry, to move taxa they must be selected first");
+				return null;
+			}
+			MesquiteInteger io = new MesquiteInteger(0);
+			int justAfter = MesquiteInteger.fromString(arguments, io);
+			if (!MesquiteInteger.isCombinable(justAfter))
+				justAfter = MesquiteInteger.queryInteger(this, "Move taxa", "After which row should the selected taxa be moved (enter 0 to move to first place)?", 0, 0, table.getNumRows() * 10);
+			if (MesquiteInteger.isCombinable(justAfter))
+				table.selectedRowsDropped(justAfter - 1); // -1 to convert to internal representation
+		}
+		else if (checker.compare(this.getClass(), "Moves the selected block ", "[number of characters to move]", commandName, "moveSelectedBlock")) {
+			MesquiteInteger firstRow = new MesquiteInteger();
+			MesquiteInteger lastRow = new MesquiteInteger();
+			MesquiteInteger firstColumn = new MesquiteInteger();
+			MesquiteInteger lastColumn = new MesquiteInteger();
+			if (!table.singleCellBlockSelected(firstRow, lastRow, firstColumn, lastColumn)) {
+				ownerModule.discreetAlert("Sorry, a single block of cells must be selected before it can be moved.");
+				return null;
+			}
+			
+			MesquiteInteger io = new MesquiteInteger(0);
+			int shiftAmount = MesquiteInteger.fromString(arguments, io);
+
+			if (!MesquiteInteger.isCombinable(shiftAmount) && !MesquiteThread.isScripting()) {
+				String helpString ="Enter the amount to shift the block.  If you enter a positive number, the block will be shifted through that many characters to the right; a negative number, to the left. ";
+				helpString+="The block will not be shifted over top of existing data; it will only be moved through gaps.  If you request a shift larger than can be accommodated, then ";
+				helpString += "the block will be shifted as far as possible without overwriting data.";
+			
+				shiftAmount = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Move Selected Block", "Number of characters to shift selected block", helpString, 1, MesquiteInteger.unassigned, MesquiteInteger.unassigned);
+			}
+			
+			if (MesquiteInteger.isCombinable(shiftAmount)) {
+				MesquiteBoolean dataChanged = new MesquiteBoolean();
+				MesquiteInteger charAdded = new MesquiteInteger();
+				MesquiteInteger distanceMoved = new MesquiteInteger();
+				data.moveCells(firstColumn.getValue(), lastColumn.getValue(), shiftAmount, firstRow.getValue(), lastRow.getValue(),  false, false, true, true,  dataChanged,  charAdded, distanceMoved);
+				if (distanceMoved.getValue()!=shiftAmount)
+					MesquiteMessage.println("Block could not be moved as far as request.  Request: : " + shiftAmount + ". Amount moved: " + distanceMoved.getValue());
+				table.deSelectBlock(firstColumn.getValue(), firstRow.getValue(), lastColumn.getValue(), lastRow.getValue());
+				table.selectBlock(firstColumn.getValue()+distanceMoved.getValue(), firstRow.getValue(), lastColumn.getValue()+distanceMoved.getValue(), lastRow.getValue());
+				if (dataChanged.getValue())
+					contentsChanged();
+			}
+		}
+		/* This is a hidden feature to help recover from consequences of bug of duplicate NOTES blocks in linked files in 1.0 to 1.02 */
+		else if (checker.compare(this.getClass(), "Moves the footnotes of the selected characters ", "[column to move after; -1 if at start]", commandName, "moveFootnotes")) {
+			if (!table.anyColumnSelected()) {
+				ownerModule.discreetAlert("Sorry, to move footnotes, characters must be selected first.");
+				return null;
+			}
+			MesquiteInteger io = new MesquiteInteger(0);
+			int justAfter = MesquiteInteger.fromString(arguments, io);
+			if (!MesquiteInteger.isCombinable(justAfter))
+				justAfter = MesquiteInteger.queryInteger(this, "Move footnotes", "After which column should the footnotes of the selected characters be moved (enter 0 to move to first place)?", 0, 0, table.getNumColumns() * 10);
+			if (MesquiteInteger.isCombinable(justAfter)) {
+				int after = (justAfter - 1); // -1 to convert to internal representation
+				if (after < -1)
+					return null;
+				if (after > table.getNumColumns())
+					after = table.getNumColumns();
+				int i = 0;
+				Bits sel = table.getColumnsSelected();
+				boolean asked = false;
+				ObjectArray charNotes = data.getWhichAssociatedObject(NameReference.getNameReference("comments"));
+				while (i < table.getNumColumns()) {
+					if (sel.isBitOn(i)) {
+						table.deselectColumn(i);
+						sel.clearBit(i);
+						if (i < after) {
+							for (int ic = i; ic < after; ic++) {
+								if (table.isColumnSelected(ic + 1))
+									table.selectColumn(ic);
+								else
+									table.deselectColumn(ic);
+							}
+						}
+
+						StringArray.moveColumns(data.getFootnotes(), i, 1, after);
+						if (charNotes != null)
+							charNotes.moveParts(i, 1, after);
+						sel.moveParts(i, 1, after);
+						if (i > after)
+							after++;
+						i = 0;
+					}
+					else
+						i++;
+				}
+				table.synchronizeColumnSelection(data);
+				data.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_ADDED));
+				contentsChanged();
+			}
+		}
+		/**/
+		else if (checker.compare(this.getClass(), "Hires utility module to operate on the data", "[name of module]", commandName, "doUtility")) {
+			if (table != null && data != null) {
+				if (data.getEditorInhibition()) {
+					ownerModule.discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				DataUtility tda = (DataUtility) ownerModule.hireNamedEmployee(DataUtility.class, arguments);
+				if (tda != null) {
+					boolean a = tda.operateOnData(data);
+					if (a) {
+						table.repaintAll();
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					}
+					if (!tda.pleaseLeaveMeOn())
+						ownerModule.fireEmployee(tda);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires utility module to alter names of the taxa", "[name of module]", commandName, "doNames")) {
+			if (table != null && data != null) {
+				Taxa taxa = data.getTaxa();
+				TaxonNameAlterer tda = (TaxonNameAlterer) ownerModule.hireNamedEmployee(TaxonNameAlterer.class, arguments);
+				if (tda != null) {
+					UndoReference undoReference = new UndoReference(new UndoInstructions(UndoInstructions.ALLTAXONNAMES, taxa, taxa), ownerModule);
+					boolean a = tda.alterTaxonNames(taxa, getTable());
+					ownerModule.fireEmployee(tda);
+					if (a) {
+						taxa.notifyListeners(this, new Notification(NAMES_CHANGED, undoReference));
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires utility module to operate on the taxa", "[name of module]", commandName, "doTaxonUtility")) {
+			if (table != null && data != null) {
+				Taxa taxa = data.getTaxa();
+				if (taxa != null) {
+					TaxonUtility tda = (TaxonUtility) ownerModule.hireNamedEmployee(TaxonUtility.class, arguments);
+					if (tda != null) {
+						boolean a = tda.operateOnTaxa(taxa);
+						if (!tda.pleaseLeaveMeOn())
+							ownerModule.fireEmployee(tda);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets width of columns of matrix", "[width]", commandName, "setColumnWidth")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			widthsSet = true;
+			int newWidth = MesquiteInteger.fromFirstToken(arguments, io);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(this, "Set column width", "Column Width:", columnWidth, table.getMinColumnWidth(), table.getMaxColumnWidth());
+			if (newWidth >= table.getMinColumnWidth() && newWidth <= table.getMaxColumnWidth() && newWidth != columnWidth) {
+				columnWidth = newWidth;
+				table.doAutosize = false;
+				table.suppressAutosize = true;
+				table.setColumnWidthsUniform(columnWidth);
+				table.repaintAll();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not cells of matrix are colored (no longer used)", "[on]", commandName, "toggleColorCell")) {
+			if ("on".equalsIgnoreCase(ParseUtil.getFirstToken(arguments, pos))) {
+				MesquiteModule mb = ownerModule.findEmployeeWithName("#ColorByState", true);
+				setCellColorer(mb);
+			}
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets by what the cells in the matrix are colored", "[name of module]", commandName, "colorCells")) {
+			MesquiteModule mb = findCellColorerMatrix(arguments);
+			if (mb == null)
+				return null;
+			if (mb == table.cellColorer) {
+				// setCellColorer(null);
+			}
+			else {
+				setCellColorer(mb);
+			}
+			table.repaintAll();
+			return mb;
+
+		}
+		else if (checker.compare(this.getClass(), "Sets by what the text in the matrix are colored", "[name of module]", commandName, "colorText")) {
+			MesquiteModule mb = findCellColorer(arguments);
+			if (mb == null)
+				return null;
+			if (mb == table.textColorer) {
+				// setTextColorer(null);
+			}
+			else {
+				setTextColorer(mb);
+			}
+			table.repaintAll();
+			return mb;
+
+		}
+		else if (checker.compare(this.getClass(), "Sets by what the row name cells in the matrix are colored", "[name of module]", commandName, "colorRowNames")) {
+			MesquiteModule mb = findCellColorerTaxa(arguments);
+			if (mb == null)
+				return null;
+			if (mb == table.rowNamesColorer && !MesquiteThread.isScripting()) {
+				// setRowNamesColorer(null);
+			}
+			else {
+				setRowNamesColorer(mb);
+			}
+			table.repaintAll();
+			return mb;
+
+		}
+		else if (checker.compare(this.getClass(), "Sets by what the column name cells in the matrix are colored", "[name of module]", commandName, "colorColumnNames")) {
+			MesquiteModule mb = findCellColorerCharacters(arguments);
+			if (mb == null)
+				return null;
+			if (mb == table.columnNamesColorer && !MesquiteThread.isScripting()) {
+				// setColumnNamesColorer(null);
+			}
+			else {
+				setColumnNamesColorer(mb);
+			}
+			table.repaintAll();
+			return mb;
+
+		}
+		else if (checker.compare(this.getClass(), "Forces the columns to auto-size", null, commandName, "forceAutosize")) {
+			offBirdsEye(false);
+			table.doAutosize = true;
+			table.suppressAutosize = false;
+			// table.setColumnWidthsUniform(columnWidth);
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not states are to be written into cells", "[on or off]", commandName, "toggleShowStates")) {
+			offBirdsEye(false);
+			table.showStates.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not default character names are shown", "[on or off]", commandName, "toggleShowDefaultCharNames")) {
+			table.showDefaultCharNames.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not autosize is to use character names also", "[on or off]", commandName, "toggleAutoWCharNames")) {
+			offBirdsEye(false);
+			table.autoWithCharNames.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not taxon name column is to be autosized", "[on or off]", commandName, "toggleAutoTaxonNames")) {
+			table.autoRowNameWidth.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not column widths are constrained", "[on or off]", commandName, "toggleConstrainCW")) {
+			offBirdsEye(false);
+			constrainedCW.toggleValue(arguments);
+			table.setConstrainMaxAutoColumn(constrainedCW.getValue());
+			table.doAutosize = true;
+			if (!MesquiteThread.isScripting())
+				table.repaintAll();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not columns are drawn as narrowly as possible", "[on or off]", commandName, "toggleTight")) {
+			table.tight.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.suppressAutosize = false;
+			table.doAutosize = true;
+			if (table.tight.getValue()) {
+				columnWidth = table.getNarrowDefaultColumnWidth();
+				table.setColumnWidthsUniform(columnWidth);
+			}
+			else {
+				// columnWidth = data.getDefaultColumnWidth();
+			}
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not rows are drawn as narrowly as possible", "[on or off]", commandName, "toggleThinRows")) {
+			table.thinRows.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to interleave the matrix when writing", "[on or off]", commandName, "toggleInterleaved")) {
+			interleaved.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			data.interleaved = interleaved.getValue();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not changes since last save are to be highlighted", "[on or off]", commandName, "toggleShowChanges")) {
+			table.showChanges.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not states are listed on separate lines in explanation", "[on or off]", commandName, "toggleSeparateLines")) {
+			table.statesSeparateLines.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (table.cellAnnotated != null && table.cellAnnotated.getRow() > -1 && table.cellAnnotated.getColumn() > -1)
+				setExplanation(table.getCellExplanation(table.cellAnnotated.getColumn(), table.cellAnnotated.getRow()));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not full names are shown in the cells of matrix", "[on or off]", commandName, "toggleShowNames")) {
+			offBirdsEye(false);
+			table.showNames.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not taxon names are shown", "[on or off]", commandName, "toggleShowTaxonNames")) {
+			showTaxonNames.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.setShowRowNames(showTaxonNames.getValue());
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not auto-sizing of columns occurs", "[on or off]", commandName, "toggleAllowAutosize")) {
+			allowAutosize.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.allowAutosize.setValue(allowAutosize.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not birds eye view is shown", "[on or off]", commandName, "toggleBirdsEye")) {
+			table.showBirdsEyeView.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (table.showBirdsEyeView.getValue()) {
+				oldShowStates = table.showStates.getValue();
+				oldColumnsWidths = table.getColumnWidthsUniform();
+				oldSuppress = table.suppressAutosize;
+				table.suppressAutosize = true;
+				table.setColumnWidthsUniform(table.birdsEyeWidth);
+				table.doAutosize = false;
+			}
+			else {
+				offBirdsEye(true);
+			}
+			resetSequenceLedge();
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the grid is drawn in pale gray", "[on or off]", commandName, "toggleShowPaleGrid")) {
+			table.showPaleGrid.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.paleGrid = table.showPaleGrid.getValue();
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the cell colors are pale.", "[on or off]", commandName, "toggleShowPaleCellColors")) {
+			table.showPaleCellColors.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.paleCellColors = table.showPaleCellColors.getValue();
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not excluded characters are pale.", "[on or off]", commandName, "toggleShowPaleExcluded")) {
+			showPaleExcluded.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.setShowPaleExcluded(showPaleExcluded.getValue());
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the gaps are pale.", "[on or off]", commandName, "togglePaleInapplicable")) {
+			table.paleInapplicable.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the text of cells is shown in bold face.", "[on or off]", commandName, "toggleShowBoldCellText")) {
+			table.showBoldCellText.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			table.boldCellText = table.showBoldCellText.getValue();
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets width of columns of matrix for bird's eye view", "[width]", commandName, "birdsEyeWidth")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			widthsSet = true;
+			int newWidth = MesquiteInteger.fromFirstToken(arguments, io);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(this, "Set Bird's Eye Width", "Width of columns in bird's eye view:", table.birdsEyeWidth, 1, 6);
+			if (newWidth >= 1 && newWidth <= 6 && newWidth != table.birdsEyeWidth) {
+				table.birdsEyeWidth = newWidth;
+				if (table.showBirdsEyeView.getValue()) {
+					table.setColumnWidthsUniform(table.birdsEyeWidth);
+					table.repaintAll();
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the color legend panel is shown", "[on = shown; off]", commandName, "toggleColorsPanel")) {
+			Parser parser = new Parser();
+			showColorLegend.toggleValue(parser.getFirstToken(arguments));
+			if (table.cellColorer != null && showColorLegend.getValue()) {
+				ColorRecord[] colors = ((CellColorer) table.cellColorer).getLegendColors();
+				setColorLegend(colors, ((CellColorer) table.cellColorer).getColorsExplanation(), true);
+			}
+			else
+				setColorLegend(null, null, false);
+		}
+		else if (checker.compare(this.getClass(), "Hires new data editor assistant module", "[name of module]", commandName, "newAssistant")) {
+			DataWindowAssistant dwa = (DataWindowAssistant) ownerModule.hireNamedEmployee(DataWindowAssistant.class, arguments);
+			if (dwa != null)
+				dwa.setTableAndData(table, data);
+			return dwa;
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	SequenceLedge sequenceLedge;
+
+	public void resetSequenceLedge() {
+		if (table.showBirdsEyeView.getValue()) { // need to show
+			if (sequenceLedge == null)
+				sequenceLedge = new SequenceLedge();
+			addLedgePanel(sequenceLedge, 22);
+			sequenceLedge.setVisible(true);
+
+		}
+		else if (!table.showBirdsEyeView.getValue() && sequenceLedge != null) { // need to hide
+			sequenceLedge.setVisible(false);
+			removeLedgePanel(sequenceLedge);
+
+		}
+	}
+
+	private void offBirdsEye(boolean doRegardless) {
+		if (doRegardless || table.showBirdsEyeView.getValue()) {
+			table.setColumnWidthsUniform(oldColumnsWidths);
+			table.doAutosize = true;
+			table.showStates.setValue(oldShowStates);
+			table.suppressAutosize = oldSuppress;
+			table.showBirdsEyeView.setValue(false);
+		}
+	}
+
+	private void setTextColorer(MesquiteModule mb) {
+		if (table.textColorer != null) {
+			table.textColorer.setActiveColors(false);
+			if (table.textColorer instanceof DataWindowAssistant)
+				((DataWindowAssistant) table.textColorer).setActive(false);
+		}
+		table.textColorer = (CellColorer) mb;
+		if (mb != null) {
+			textColorerName.setValue(mb.getNameForMenuItem());
+			boolean success = ((CellColorer) mb).setActiveColors(true);
+			if (success && mb instanceof DataWindowAssistant)
+				((DataWindowAssistant) mb).setActive(true);
+		}
+		else {
+			textColorerName.setValue((String) null);
+		}
+	}
+
+	private void setRowNamesColorer(MesquiteModule mb) {
+		if (table.rowNamesColorer != null) {
+			table.rowNamesColorer.setActiveColors(false);
+			if (table.rowNamesColorer instanceof DataWindowAssistant)
+				((DataWindowAssistant) table.rowNamesColorer).setActive(false);
+		}
+		table.rowNamesColorer = (CellColorer) mb;
+		if (mb != null) {
+			rowNamesColorerName.setValue(mb.getNameForMenuItem());
+			boolean success = ((CellColorer) mb).setActiveColors(true);
+			if (success && mb instanceof DataWindowAssistant)
+				((DataWindowAssistant) mb).setActive(true);
+		}
+		else {
+			rowNamesColorerName.setValue((String) null);
+		}
+	}
+
+	private void setColumnNamesColorer(MesquiteModule mb) {
+		if (table.columnNamesColorer != null) {
+			table.columnNamesColorer.setActiveColors(false);
+			if (table.columnNamesColorer instanceof DataWindowAssistant)
+				((DataWindowAssistant) table.columnNamesColorer).setActive(false);
+		}
+		table.columnNamesColorer = (CellColorer) mb;
+		if (mb != null) {
+			columnNamesColorerName.setValue(mb.getNameForMenuItem());
+			boolean success = ((CellColorer) mb).setActiveColors(true);
+			if (success && mb instanceof DataWindowAssistant)
+				((DataWindowAssistant) mb).setActive(true);
+		}
+		else {
+			columnNamesColorerName.setValue((String) null);
+		}
+	}
+
+	void resetColorerIfNeeded(MesquiteModule employee) {
+		if (table.cellColorer != null && table.cellColorer == employee) {
+			setColorLegend(table.cellColorer.getLegendColors(), table.cellColorer.getColorsExplanation(), showColorLegend.getValue());
+		}
+	}
+
+	private void setCellColorer(MesquiteModule mb) {
+		if (table.cellColorer != null) {
+			table.cellColorer.setActiveColors(false);
+			if (table.cellColorer instanceof DataWindowAssistant)
+				((DataWindowAssistant) table.cellColorer).setActive(false);
+		}
+		table.cellColorer = (CellColorer) mb;
+		if (mb != null) {
+			boolean success = ((CellColorer) mb).setActiveColors(true);
+			if (success) {
+				cellColorerName.setValue(mb.getNameForMenuItem());
+				if (mb instanceof DataWindowAssistant)
+					((DataWindowAssistant) mb).setActive(true);
+				table.addControlButton(colorLegendButton);
+				setColorLegend(((CellColorer) mb).getLegendColors(), ((CellColorer) mb).getColorsExplanation(), showColorLegend.getValue());
+			}
+		}
+		else {
+			table.removeControlButton(colorLegendButton);
+			cellColorerName.setValue((String) null);
+			setColorLegend(null, null, false);
+		}
+	}
+
+	ColorLegend panel;
+
+	MesquiteBoolean showColorLegend = new MesquiteBoolean(false);
+
+	// addCheckMenuItem(null, "Show Color Legend", makeCommand("togglePanel", this), showPanel);
+	/* ................................................................................................................. */
+	void setColorLegend(ColorRecord[] legendColors, String colorsExplanation, boolean show) {
+		if (show) {
+			if (panel == null)
+				panel = new ColorLegend(this);
+			addSidePanel(panel, ColorLegend.width);
+			panel.setVisible(true);
+			String title = "Explanation of colors";
+			if (table.cellColorer instanceof MesquiteModule)
+				title = ((MesquiteModule) table.cellColorer).getNameForMenuItem();
+			else if (table.cellColorer instanceof Listable)
+				title = ((Listable) table.cellColorer).getName();
+			panel.setLegendColors(legendColors, title, colorsExplanation);
+			panel.repaint();
+		}
+		else {
+			if (panel != null)
+				removeSidePanel(panel);
+		}
+	}
+
+	/* ................................................................................................................. */
+	public void resignCellColorer(MesquiteModule mb) {
+		if (table.cellColorer == mb)
+			setCellColorer(null);
+		table.repaintAll();
+
+	}
+
+	/* ................................................................................................................. */
+	public boolean requestCellColorer(MesquiteModule mb, int ic, int it, String message) {
+		if (ic >= 0 && it >= 0) { // matrix cells
+			if (table.cellColorer == mb)
+				return true;
+			if ((table.cellColorer == null || table.cellColorer instanceof mesquite.charMatrices.NoColor.NoColor) && (message != null && AlertDialog.query(this, "Cell colors", message, "Yes", "No"))) {
+				setCellColorer(mb);
+				table.repaintAll();
+				return true;
+			}
+		}
+		else if (ic < 0 && it >= 0) { // row names
+			if (table.rowNamesColorer == mb)
+				return true;
+			if ((table.rowNamesColorer == null || table.rowNamesColorer instanceof mesquite.charMatrices.NoColor.NoColor) && (message != null && AlertDialog.query(this, "Row name colors", message, "Yes", "No"))) {
+				setRowNamesColorer(mb);
+				table.repaintAll();
+				return true;
+			}
+		}
+		else if (ic >= 0 && it < 0) { // column names
+			if (table.columnNamesColorer == mb)
+				return true;
+			if ((table.columnNamesColorer == null || table.columnNamesColorer instanceof mesquite.charMatrices.NoColor.NoColor) && (message != null && AlertDialog.query(this, "Column name colors", message, "Yes", "No"))) {
+				setColumnNamesColorer(mb);
+				table.repaintAll();
+				return true;
+			}
+		}
+		return false;
+
+	}
+
+	/* ................................................................................................................. */
+	public void demandCellColorer(MesquiteModule mb, int ic, int it, String message) {
+		if (ic >= 0 && it >= 0) { // matrix cells
+			if (table.cellColorer == mb)
+				return;
+			setCellColorer(mb);
+			table.repaintAll();
+		}
+		else if (ic < 0 && it >= 0) { // rownames
+			if (table.rowNamesColorer == mb)
+				return;
+			setRowNamesColorer(mb);
+			table.repaintAll();
+		}
+		else if (ic >= 0 && it < 0) { // columnnames
+			if (table.columnNamesColorer == mb)
+				return;
+			setColumnNamesColorer(mb);
+			table.repaintAll();
+		}
+		if (message != null)
+			ownerModule.alert(message);
+
+	}
+
+	/* ................................................................................................................. */
+	public void pleaseUpdate() {
+		table.repaintAll();
+	}
+
+	void checkSelectionMatrixInfoPanel() {
+		if (table == null || matrixInfoPanel == null)
+			return;
+		if (table.numRowsSelected() == 1) {
+			int row = table.firstRowSelected();
+			matrixInfoPanel.cellTouch(row, -1);
+		}
+		if (table.numColumnsSelected() == 1) {
+			int column = table.firstColumnSelected();
+			matrixInfoPanel.cellTouch(column, -1);
+		}
+
+	}
+
+	/* ................................................................................................................. */
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface) */
+	public void changed(Object caller, Object obj, Notification notification) {
+		if (caller instanceof BasicDataWindow || caller instanceof MatrixTable)
+			return;
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof Taxa && (Taxa) obj == data.getTaxa()) {
+			Taxa taxa = (Taxa) obj;
+			if (code == MesquiteListener.NAMES_CHANGED) {
+				table.redrawRowNames();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.SELECTION_CHANGED) {
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+				checkSelectionMatrixInfoPanel();
+
+			}
+			else if (code == MesquiteListener.PARTS_ADDED) {
+				table.offAllEditsDontRecord();// 1. 12
+				table.setNumRows(taxa.getNumTaxa());
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.PARTS_DELETED) {
+				table.offAllEditsDontRecord();// 1. 12
+				table.setNumRows(taxa.getNumTaxa());
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+				setUndoer();
+			}
+			else if (code == MesquiteListener.PARTS_MOVED) {
+				table.offAllEditsDontRecord();// 1. 12
+				table.setNumRows(taxa.getNumTaxa());
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code != MesquiteListener.ANNOTATION_CHANGED) {
+				table.repaintAll();
+				if (caller != table) { // if object provoking notification is me, then don't repaint
+					table.refreshAnnotation();
+				}
+			}
+			if (getMode() > 0)
+				updateTextPage();
+		}
+		else if (obj instanceof CharacterData && (CharacterData) obj == data) {
+			if (getMode() > 0)
+				updateTextPage();
+			else if (code == MesquiteListener.NAMES_CHANGED) {
+				table.doAutosize = true;
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.SELECTION_CHANGED) {
+				if (caller != table) { // if object provoking notification is me, then don't repaint
+					table.synchronizeColumnSelection(data);
+					table.repaintAll();
+					checkSelectionMatrixInfoPanel();
+				}
+			}
+			else if (code == MesquiteListener.PARTS_DELETED) {
+				table.doAutosize = true;
+				table.offAllEditsDontRecord();// 1. 12
+				if (parameters != null && parameters.length > 1) {
+					int starting = parameters[0];
+					int num = parameters[1];
+					if (data.getNumChars() < table.getNumColumns()) {
+						for (int i = starting + num - 1; i >= starting; i--)
+							table.deleteColumn(i);
+					}
+				}
+				else if (table.getNumColumns() != data.getNumChars())
+					table.setNumColumns(data.getNumChars());
+				if (table.getNumRows() != data.getTaxa().getNumTaxa())
+					table.setNumRows(data.getTaxa().getNumTaxa());
+				table.synchronizeColumnSelection(data);
+				table.repaintAll();
+				setUndoer();
+			}
+			else if (code == MesquiteListener.PARTS_ADDED) {
+				table.doAutosize = true;
+				table.offAllEditsDontRecord();// 1. 12
+				if (parameters != null && parameters.length > 1) {
+					int starting = parameters[0];
+					int num = parameters[1];
+					if (data.getNumChars() > table.getNumColumns()) {
+						table.insertColumns(starting, num);
+					}
+				}
+				else if (table.getNumColumns() != data.getNumChars())
+					table.setNumColumns(data.getNumChars());
+				if (table.getNumRows() != data.getTaxa().getNumTaxa())
+					table.setNumRows(data.getTaxa().getNumTaxa());
+				table.synchronizeColumnSelection(data);
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.PARTS_MOVED) {
+				table.doAutosize = true;
+				table.offAllEditsDontRecord();// 1. 12
+				if (parameters != null && parameters.length > 1) {
+					int starting = parameters[0];
+					int num = parameters[1];
+					int justAfter = parameters[2];
+					if (data.getNumChars() == table.getNumColumns()) {
+						table.moveColumns(starting, num, justAfter);
+					}
+				}
+				if (table.getNumRows() != data.getTaxa().getNumTaxa())
+					table.setNumRows(data.getTaxa().getNumTaxa());
+				table.synchronizeColumnSelection(data);
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.DATA_CHANGED) {
+				table.doAutosize = true;
+				if (table.getNumRows() != data.getTaxa().getNumTaxa())
+					table.setNumRows(data.getTaxa().getNumTaxa());
+				if (table.getNumColumns() != data.getNumChars())
+					table.setNumColumns(data.getNumChars());
+				table.synchronizeColumnSelection(data);
+				table.repaintAll();
+				setUndoer(undoReference);
+			}
+			else if (code == MesquiteListener.ANNOTATION_CHANGED) {
+				if (caller != table) { // if object provoking notification is me, then don't repaint
+					table.refreshAnnotation();
+				}
+			}
+			else {
+				table.doAutosize = true;
+				if (table.getNumRows() != data.getTaxa().getNumTaxa()) {
+					table.offAllEditsDontRecord();// 1. 12
+					table.setNumRows(data.getTaxa().getNumTaxa());
+				}
+				if (table.getNumColumns() != data.getNumChars()) {
+					table.offAllEditsDontRecord();// 1. 12
+					table.setNumColumns(data.getNumChars());
+				}
+				table.synchronizeColumnSelection(data);
+				table.repaintAll();
+			}
+		}
+		table.setMessage(data.getCellContentsDescription());
+		super.changed(caller, obj, notification);
+	}
+
+	/* ................................................................................................................. */
+	/** passes which object is being disposed (from MesquiteListener interface) */
+	public void disposing(Object obj) {
+		if ((obj instanceof Taxa && (Taxa) obj == data.getTaxa()) || (obj instanceof CharacterData && (CharacterData) obj == data)) {
+			hide();
+			MesquiteModule mb = ownerModule;
+			dispose();
+			mb.iQuit();
+
+		}
+	}
+
+	/* ................................................................................................................. */
+	/** passes which object is being disposed (from MesquiteListener interface) */
+	public boolean okToDispose(Object obj, int queryUser) {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Query module as to whether conditions are such that it will have to quit soon -- e.g. if its taxa block has been doomed. The tree window, data window, etc. override this to return true if their object is doomed. This is useful in case MesquiteListener disposing method is not called for an employer before one of its employees discovers that it needs to quit. If the employer is going to quit anyway,there is no use to use auto rehire for the quit employee.
+	 */
+	public boolean quittingConditions() {
+		return (data.isDoomed() || data.getTaxa().isDoomed());
+	}
+
+	/** requests that a side panel be added to main graphics panel */
+	public void addSidePanel(MousePanel sp, int width) {
+		super.addSidePanel(sp, width);
+		checkSizes();
+	}
+
+	/** requests that a side panel be added to main graphics panel */
+	public void removeSidePanel(MousePanel sp) {
+		super.removeSidePanel(sp);
+		checkSizes();
+	}
+
+	/** requests that a ledge panel be added to main graphics panel */
+	public void addLedgePanel(MousePanel sp, int width) {
+		super.addLedgePanel(sp, width);
+		checkSizes();
+	}
+
+	/** requests that a side panel be added to main graphics panel */
+	public void removeLedgePanel(MousePanel sp) {
+		super.removeLedgePanel(sp);
+		checkSizes();
+	}
+
+	/* ................................................................................................................. */
+	public void setWindowSize(int width, int height) {
+		super.setWindowSize(width, height);
+		checkSizes();
+	}
+
+	void checkSizes() {
+		if (table != null) { // && ((getHeight() != windowHeight) || (getWidth() != windowWidth))) {
+			windowHeight = getHeight();
+			windowWidth = getWidth();
+			table.setSize(windowWidth, windowHeight);
+			table.doAutosize = true;
+			table.repaintAll();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public void setCurrentTool(MesquiteTool tool) {
+		super.setCurrentTool(tool);
+		if (tool != null && tool.getEnabled()) {
+			if ((getCurrentTool() != ibeamTool) && (table != null))
+				table.offAllEdits();
+			boolean myTool = (getCurrentTool() == ibeamTool || getCurrentTool() == arrowTool || (getCurrentTool() != null && getCurrentTool().getAllowAnnotate()));
+			setAEFocusSuppression(!myTool);
+			if (!myTool)
+				table.requestFocus();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public String getPrintMenuItem() {
+		return "Print Matrix...";
+	}
+
+	/* ................................................................................................................. */
+	public String getPrintToFitMenuItemName() {
+		return "Print Matrix To Fit Page...";
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * @author Peter Midford
+	 */
+	public String getPrintToPDFMenuItemName() {
+		return "Save Matrix As PDF...";
+	}
+
+	/* ................................................................................................................. */
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu) */
+	public int getShowMenuLocation() {
+		return 0;
+	}
+
+	/* ................................................................................................................. */
+	public MatrixTable getMatrixTable() {
+		return table;
+	}
+
+	/* ................................................................................................................. */
+	public void printWindow(MesquitePrintJob pjob) {
+		table.printTable(pjob, this);
+		// TODO: optionally print modelsets, etc.
+	}
+
+	/* ................................................................................................................. */
+	public void paintContents(Graphics g) {
+		table.repaintAll();
+	}
+
+	/* ................................................................................................................. */
+	public String getTextContents() {
+		String s = "Character matrix editor for matrix \"" + data.getName() + "\"\n";
+		s += "Type of matrix: " + data.getDataTypeName();
+		if (data instanceof CategoricalData) {
+			if (((CategoricalData) data).usingShortMatrix())
+				s += " (compacted)\n";
+			else
+				s += " (uncompacted)\n";
+		}
+		else
+			s += "\n";
+		s += "Number of characters: " + data.getNumChars() + "\n";
+		s += "Number of taxa: " + data.getNumTaxa() + "\n";
+		int countExcluded = 0;
+		int countInapplicable = 0;
+		int countUnassigned = 0;
+		for (int ic = 0; ic < data.getNumChars(); ic++) {
+			if (!data.isCurrentlyIncluded(ic))
+				countExcluded++;
+			for (int it = 0; it < data.getNumTaxa(); it++) {
+				if (data.isInapplicable(ic, it))
+					countInapplicable++;
+				if (data.isUnassigned(ic, it))
+					countUnassigned++;
+			}
+
+		}
+		s += "Number of characters excluded: " + countExcluded + "\n";
+		s += "Proportion of missing data: " + MesquiteDouble.toString(1.0 * countUnassigned / (data.getNumChars() * data.getNumTaxa())) + "\n";
+		s += "Proportion of inapplicable codings: " + MesquiteDouble.toString(1.0 * countInapplicable / (data.getNumChars() * data.getNumTaxa())) + "\n\n";
+		String an = data.getAnnotation();
+		if (!StringUtil.blank(an)){
+			s += "----------------\nNote about matrix:\n" + an + "\n----------------\n\n";
+		}
+		s += table.getTextVersion();
+		return s;
+	}
+
+	String getParameters() {
+		String s = "";
+		if (table.cellColorer != null) {
+			s += "Background of cells colored by: " + ((MesquiteModule) table.cellColorer).getName();
+		}
+		if (table.textColorer != null) {
+			if (table.cellColorer != null)
+				s += "; ";
+			s += "Text of cells colored by: " + ((MesquiteModule) table.textColorer).getName();
+		}
+		return s;
+	}
+
+	/* ................................................................................................................. */
+	public void windowResized() {
+		super.windowResized();
+		checkSizes();
+
+		// data.notifyListeners(this, new Notification(MesquiteListener.VIEW_CHANGED));
+	}
+
+	public void dispose() {
+		disposing = true;
+		waitUntilDisposable();
+		table.dispose();
+		if (data.getTaxa() != null)
+			data.getTaxa().removeListener(this);
+		data.removeListener(this);
+		super.dispose();
+	}
+
+}
+
+/* ======================================================================== */
+/* ======================================================================== */
+class CellAnnotation implements Annotatable {
+	String name;
+
+	CharacterData data;
+
+	int row = -1;
+
+	int column = -1;
+
+	public CellAnnotation(CharacterData data) {
+		this.data = data;
+	}
+
+	int getRow() {
+		return row;
+	}
+
+	int getColumn() {
+		return column;
+	}
+
+	void setCell(int c, int r) {
+		row = r;
+		column = c;
+	}
+
+	public String getName() {
+		if (data == null)
+			return "";
+		if (row == -1) {
+			if (column == -1)
+				return "matrix \"" + data.getName() + "\"";
+			return "character \"" + data.getCharacterName(column) + "\"";
+		}
+		else if (column == -1) {
+			return "taxon \"" + data.getTaxa().getTaxonName(row) + "\"";
+		}
+		else {
+			return "character " + (column + 1) + " of taxon " + (row + 1);
+		}
+	}
+
+	public String getAnnotation() {
+		try {
+			if (data == null)
+				return null;
+			if (row == -1) {
+				if (column == -1)
+					return data.getAnnotation();
+				return data.getAnnotation(column);
+			}
+			else if (column == -1) {
+				return data.getTaxa().getAnnotation(row);
+			}
+			else {
+				return data.getAnnotation(column, row);
+			}
+		} catch (NullPointerException e) {
+			return null;
+		}
+	}
+
+	public void setAnnotation(String s, boolean notify) {
+		if (data == null)
+			return;
+		if ("".equals(s))
+			s = null;
+		if (row == -1) {
+			if (column == -1) {
+				data.setAnnotation(s, notify);
+				return;
+			}
+			data.setAnnotation(column, s);
+		}
+		else if (column == -1) {
+			data.getTaxa().setAnnotation(row, s);
+		}
+		else {
+			data.setAnnotation(column, row, s);
+		}
+	}
+}
+
+/* ======================================================================== */
+class ColorLegend extends MousePanel {
+	static final int width = 100;
+
+	static final int height = 36;
+
+	String title = null;
+
+	String explanation = null;
+
+	ColorRecord[] colors;
+
+	StringInABox box;
+
+	int[] locs;
+
+	BasicDataWindow w;
+
+	Image goaway;
+
+	public ColorLegend(BasicDataWindow w) {
+		super();
+		this.w = w;
+		setLayout(null);
+		setBackground(Color.white);
+		setFont(new Font("SansSerif", Font.PLAIN, 10));
+		box = new StringInABox("", null, width);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goaway.gif");
+	}
+
+	public void setLegendColors(ColorRecord[] colors, String title, String explanation) {
+		this.colors = colors;
+		this.title = title;
+		this.explanation = explanation;
+		if (colors != null)
+			locs = new int[colors.length];
+	}
+
+	public void paint(Graphics g) {
+		if (colors == null && title == null)
+			return;
+		Color c = g.getColor();
+		g.drawImage(goaway, 2, 2, this);
+		box.setWidth(getBounds().width);
+
+		box.setFont(g.getFont());
+		int vertical = 2;
+		int BOXHEIGHT = 20;
+		int spaceBetweenBoxes = 3;
+		if (title != null) {
+			box.setWidth(getBounds().width - 20);
+			box.setString(title);
+			box.draw(g, 20, vertical);
+			vertical += 8 + box.getHeight();
+		}
+		box.setWidth(getBounds().width);
+		g.drawLine(0, vertical - 4, getBounds().width, vertical - 4);
+		if (explanation != null) {
+			box.setString(explanation);
+			box.draw(g, 4, vertical);
+			vertical += 8 + box.getHeight();
+		}
+		box.setWidth(getBounds().width - 36);
+		if (colors != null) {
+			int maxHeight = (getBounds().height - vertical) / colors.length - 4;
+			for (int i = 0; i < colors.length; i++) {
+				g.setColor(colors[i].getColor());
+				g.fillRect(4, vertical, 28, BOXHEIGHT);
+				g.setColor(Color.black);
+				g.drawRect(4, vertical, 28, BOXHEIGHT - 1);
+				g.setColor(Color.gray);
+				g.drawLine(5, vertical + BOXHEIGHT, 33, vertical + BOXHEIGHT);
+				g.drawLine(33, vertical + BOXHEIGHT, 33, vertical + 1);
+				g.setColor(Color.black);
+				locs[i] = vertical;
+				box.setString(colors[i].getString());
+				box.draw(g, 36, vertical - 4);
+				int h = box.getHeight();
+				if (h > maxHeight) {
+					vertical += 8 + maxHeight;
+					g.setColor(Color.white);
+					g.fillRect(1, vertical, getBounds().width, getBounds().height - vertical);
+				}
+				else
+					vertical += 8 + h;
+			}
+		}
+		g.setColor(c);
+	}
+
+	int findColor(int x, int y) {
+		if (locs == null)
+			return -1;
+		for (int i = 0; i < locs.length; i++)
+			if (y >= locs[i] && y <= locs[i] + 20 && x >= 4 && x <= 32)
+				return i;
+		return -1;
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (clickCount > 1) {
+			int c = findColor(x, y);
+			if (c >= 0) {
+				if (AlertDialog.query(this, "Find Color?", "Do you want to look for this color in the matrix?"))
+					w.goToColor(colors[c].getColor());
+			}
+		}
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x < 16 && y < 16)
+			w.colorsPanelGoAway();
+
+	}
+
+	public void setBounds(int x, int y, int w, int h) {
+		super.setBounds(x, y, w, h);
+		box.setWidth(w);
+	}
+
+	public void setSize(int w, int h) {
+		super.setSize(w, h);
+		box.setWidth(w);
+	}
+}
+
+/* ======================================================================== */
+class MatrixTable extends mesquite.lib.table.CMTable implements MesquiteDroppedFileHandler {
+	BasicDataWindowMaker editorModule;
+
+	Taxa taxa;
+
+	MesquiteBoolean showStates;
+
+	MesquiteBoolean showDefaultCharNames;
+
+	MesquiteBoolean autoWithCharNames;
+
+	MesquiteBoolean showNames;
+
+	MesquiteBoolean showBirdsEyeView;
+
+	MesquiteBoolean showChanges;
+
+	MesquiteBoolean statesSeparateLines;
+
+	MesquiteBoolean allowAutosize;
+
+	MesquiteBoolean showPaleGrid;
+
+	MesquiteBoolean showBoldCellText;
+	MesquiteBoolean showPaleCellColors;
+	MesquiteBoolean showPaleExcluded;
+	MesquiteBoolean showEmptyDataAsClear;
+	MesquiteBoolean paleInapplicable;
+
+	int birdsEyeWidth = 2;
+
+	static double showPaleExcludedValueText = 0.40;
+
+	static double showPaleExcludedValueBackground = 0.40;
+
+	boolean notifySuppressed = false;
+
+	CellAnnotation cellAnnotated;
+
+	CharacterData data;
+
+	Font oldFont = null;
+
+	Font boldFont;
+
+	Parser parser = new Parser();
+
+	BasicDataWindow window;
+
+	CellColorer rowNamesColorer = null;
+
+	CellColorer columnNamesColorer = null;
+
+	CellColorer cellColorer = null;
+
+	CellColorer textColorer = null;
+
+	Color bgColor = Color.white;
+
+	Vector linkedTables;
+
+	static int totTables = 0;
+
+	int oldFirstColumn = 0;
+
+	int oldFirstRow = 0;
+
+	int oldLastColumn = 0;
+
+	int oldLastRow = 0;
+
+	int id = 0;
+
+	// DataColumnNamesAssistant assistant1;
+
+	public MatrixTable(BasicDataWindowMaker editorModule, BasicDataWindow window, CharacterData data, int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int taxonNamesWidth) {
+		super(numRowsTotal, numColumnsTotal, totalWidth, totalHeight, taxonNamesWidth, ColorDistribution.getColorScheme(editorModule), true, true);
+		setConstrainMaxAutoRownames(true);
+		contrainedMaxColumnNum = 1;
+		this.window = window;
+		setUserMove(true, true);
+		linkedTables = new Vector();
+		this.data = data;
+		cellAnnotated = new CellAnnotation(data);
+		showStates = new MesquiteBoolean(true);
+		showDefaultCharNames = new MesquiteBoolean(false);
+		autoWithCharNames = new MesquiteBoolean(!(data instanceof MolecularData));
+		showBirdsEyeView = new MesquiteBoolean(false);
+		showPaleGrid = new MesquiteBoolean(false);
+		showPaleCellColors = new MesquiteBoolean(false);
+		showEmptyDataAsClear = new MesquiteBoolean(false);
+		showPaleExcluded = new MesquiteBoolean(false);
+		paleInapplicable = new MesquiteBoolean(true);
+		showBoldCellText = new MesquiteBoolean(false);
+		showChanges = new MesquiteBoolean(!(data instanceof MolecularData));
+		allowAutosize = new MesquiteBoolean(!(data instanceof MolecularData));
+		showNames = new MesquiteBoolean(true);
+		statesSeparateLines = new MesquiteBoolean(false);
+		setUserAdjust(MesquiteTable.NOADJUST, MesquiteTable.RESIZE);
+		showRowGrabbers = true;
+		showColumnGrabbers = true;
+		setEditable(true, true, true, false);
+		setSelectable(true, true, true, true, true, false);
+		this.editorModule = editorModule;
+		this.taxa = data.getTaxa();
+		setMessage(data.getCellContentsDescription());
+		setBackground(ColorTheme.getContentBackground());
+		// setBackground(ColorDistribution.project[ColorDistribution.getColorScheme(editorModule)]);
+		oldFont = getFont();
+		if (oldFont != null)
+			boldFont = new Font(oldFont.getName(), Font.BOLD, oldFont.getSize());
+		synchronizeRowSelection(taxa);
+		synchronizeColumnSelection(data);
+
+		dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
+
+		id = totTables++;
+	}
+
+	void linkTable(MesquiteTable table, boolean linkeeIsNew) {
+		linkedTables.addElement(table);
+		// tell window table is linked so it can coordinate scrolling if it wants
+		window.setTableLinked(true);
+		if (linkeeIsNew) {
+			for (int ic = 0; ic < table.getNumColumns(); ic++)
+				// synchronizing at start
+				for (int it = 0; it < table.getNumRows(); it++) {
+					if (isCellSelected(ic, it) && !table.isCellSelected(ic, it))
+						table.selectCell(ic, it);
+					else if (!isCellSelected(ic, it) && table.isCellSelected(ic, it))
+						table.deselectCell(ic, it);
+				}
+		}
+	}
+
+	void unlinkTable(MesquiteTable table) {
+		linkedTables.removeElement(table);
+		// tell window table is unlinked
+		window.setTableLinked(false);
+	}
+
+	public void setShowPaleExcluded(boolean showPaleExcluded) {
+		this.showPaleExcluded.setValue(showPaleExcluded);
+	}
+
+	/* ................................................................................................................. */
+	public void copyCells(StringBuffer s, boolean literal) {
+		copyIt(s, literal, !(data instanceof MolecularData), true);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * A request for the MesquiteModule to perform a command. It is passed two strings, the name of the command and the arguments. This should be overridden by any module that wants to respond to a command.
+	 */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Paste contents of clipboard into matrix", null, commandName, "paste")) {
+			if (window.annotationHasFocus()) {
+				return super.doCommand(commandName, arguments, checker);
+			}
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			Transferable t = clip.getContents(this);
+			try {
+
+				String s = (String) t.getTransferData(DataFlavor.stringFlavor);
+				if (s != null) {
+					if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+						TextField edit = null;
+						if (matrix.getEditing())
+							edit = matrix.getEditField();
+						else if (rowNames.getEditing())
+							edit = rowNames.getEditField();
+						else if (columnNames.getEditing())
+							edit = columnNames.getEditField();
+						if (edit != null && edit.hasFocus()) {
+							String text = edit.getText();
+							String newText = text.substring(0, edit.getSelectionStart()) + s + text.substring(edit.getSelectionEnd(), text.length());
+							edit.setText(newText);
+						}
+						return s;
+					}
+					else if (window.componentWithFocus() != null) {
+						Component c = window.componentWithFocus();
+						if (c instanceof TextComponent) {
+							TextComponent tc = (TextComponent) c;
+							if (tc.isEditable()) {
+								String text = tc.getText();
+								String newText = text.substring(0, tc.getSelectionStart()) + s + text.substring(tc.getSelectionEnd(), text.length());
+								tc.setText(newText);
+							}
+							return s;
+						}
+						else if (c instanceof JTextComponent) {
+							JTextComponent tc = (JTextComponent) c;
+							if (tc.isEditable()) {
+								String text = tc.getText();
+								String newText = text.substring(0, tc.getSelectionStart()) + s + text.substring(tc.getSelectionEnd(), text.length());
+								tc.setText(newText);
+							}
+							return s;
+						}
+
+					}
+					if (clipboardDimensionsFit(s)) {
+						editorModule.getProject().incrementProjectWindowSuppression();
+						data.incrementNotifySuppress();
+						UndoReference pasteUndoReference = UndoReference.getUndoReferenceForMatrixSelection(data, this, editorModule, new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});  //TODO: check to see if there can ever be changes
+						pasteIt(s);
+						// deselectAll();
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, pasteUndoReference));
+						data.decrementNotifySuppress();
+						editorModule.getProject().decrementProjectWindowSuppression();
+
+						repaintAll();
+					}
+					else {
+						int[] lines = getTabbedLines(s);
+						if (lines == null || lines.length == 0 || lines[0] == 0) {
+							editorModule.alert("Sorry, the pasted text was not appropriate for the matrix.");
+							return null;
+						}
+						if (data instanceof MolecularData) {
+
+							editorModule.getProject().incrementProjectWindowSuppression();
+							boolean success = reshapeMolecular(s, true);
+							editorModule.getProject().decrementProjectWindowSuppression();
+							if (success) {
+								data.incrementNotifySuppress();
+								UndoReference pasteUndoReference = UndoReference.getUndoReferenceForMatrixSelection(data, this, editorModule, new int[] {UndoInstructions.CHAR_ADDED_TO_END});
+								pasteIt(s);
+								// deselectAll();
+								data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, pasteUndoReference));
+								data.decrementNotifySuppress();
+							}
+							return null;
+
+						}
+						if (!IntegerArray.equalValues(lines)) {
+							if (AlertDialog
+									.query(editorModule.containerOfModule(), "Paste shape mismatch", "Sorry, the number of lines and of items pasted don't match the spaces selected to be filled.  Would you like Mesquite to attempt to adjust the selected region so that you can paste?  (Note: if you select OK, Mesquite will change the selection but will not paste. You will have to request again to paste.)", "OK", "Cancel", 1))
+								setSelectionToShape(lines);
+						}
+						else {
+							if (AlertDialog
+									.query(editorModule.containerOfModule(), "Paste shape mismatch", "Sorry, Clipboard is a different size or shape than the region selected, and thus you cannot paste.  Would you like Mesquite to attempt to adjust the selected region so that you can paste?  (Note: if you select OK, Mesquite will change the selection but will not paste. You will have to request again to paste.)", "OK", "Cancel", 1))
+								setSelectionToShape(lines);
+						}
+					}
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	boolean reshapeMolecular(String s, boolean expandRightToFit) { // return true if succeeded
+		Point p = getTopLeftSelected();
+		String[] lines = getLines(s);
+		int lineCount = 0;
+		int top = p.y;
+		boolean success = true;
+		boolean expandedChars = false;
+		boolean expandedTaxa = false;
+		if (top < 0) {
+			int numTabs = StringUtil.characterCount(lines[lineCount++], '\t');
+			if (p.x + numTabs >= numColumnsTotal && expandRightToFit) {
+				int starting = data.getNumChars();
+				int number = (p.x + numTabs) + 1 - numColumnsTotal;
+				if (data.addParts(starting + 1, number)) {
+					setNumColumns(data.getNumChars());
+					expandedChars = true;
+					data.addInLinked(starting + 1, number, true);
+				}
+			}
+			for (int ic = p.x; ic < numColumnsTotal && ic - p.x < numTabs + 1; ic++) {
+				selectColumnName(ic);
+			}
+			top = 0;
+		}
+		if (p.y + lines.length > numRowsTotal) {
+			if (AlertDialog.query(editorModule.containerOfModule(), "Add Taxa?", "To paste the clipboard you would need to expand the taxa block by adding new taxa.  Do you want to do this?", "Expand", "Cancel", 1)) {
+				int starting = numRowsTotal;
+				int number = p.y + lines.length - numRowsTotal;
+				if (data.getTaxa().addTaxa(starting, number, true)) {
+					setNumRows(data.getTaxa().getNumTaxa());
+					expandedTaxa = true;
+				}
+			}
+			else
+				return false;
+		}
+		int matrixTop = lineCount;
+		int maxNumSites = numColumnsTotal;
+		for (int it = top; it < p.y + lines.length && it < numRowsTotal && lineCount < lines.length; it++) {
+			StringBuffer sb = new StringBuffer(lines[lineCount++]);
+			String token = molecToken(sb, p.x < 0);
+			int siteCount = p.x;
+			while (!StringUtil.blank(token)) {
+				siteCount++;
+				token = molecToken(sb, false);
+			}
+			if (siteCount > maxNumSites)
+				maxNumSites = siteCount;
+		}
+		if (maxNumSites > numColumnsTotal) {
+			if (!expandRightToFit)
+				return false;
+			int starting = data.getNumChars() + 1;
+			int number = maxNumSites - numColumnsTotal;
+			if (data.addParts(starting, number)) {
+				setNumColumns(data.getNumChars());
+				expandedChars = true;
+				data.addInLinked(starting, number, true);
+			}
+		}
+		lineCount = matrixTop;
+		for (int it = top; it < p.y + lines.length && it < numRowsTotal && lineCount < lines.length; it++) {
+			StringBuffer sb = new StringBuffer(lines[lineCount++]);
+			String token = molecToken(sb, p.x < 0);
+			for (int ic = p.x; ic < numColumnsTotal && !StringUtil.blank(token); ic++) {
+				selectCell(ic, it);
+				token = molecToken(sb, false);
+			}
+			if (!expandRightToFit && !StringUtil.blank(token))
+				success = false;
+
+		}
+		if (lineCount < lines.length)
+			success = false;
+		// if (expandedTaxa)
+		// data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		if (expandedChars)
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		repaintAll();
+		return success;
+	}
+
+	boolean lineMatches(int left, int selected, String line) {
+		StringBuffer sb = new StringBuffer(line);
+		String token = molecToken(sb, left < 0);
+		int siteCount = 0;
+		while (!StringUtil.blank(token)) {
+			siteCount++;
+			token = molecToken(sb, false);
+		}
+		return (siteCount == selected);
+	}
+
+	boolean matchesMolecular(String s) {
+		Point topLeft = getTopLeftSelected();
+
+		int[] fSelected = getSelectedSpaces();
+		String[] lines = getLines(s);
+		if (fSelected == null && lines == null)
+			return false;
+		if (fSelected.length != lines.length)
+			return false;
+		int firstLine = 0;
+		if (topLeft.y < 0) { // includes character names; hence must treat these differently
+			int numTabs = StringUtil.characterCount(lines[0], '\t');
+			if (numTabs + 1 != fSelected[0])
+				return false;
+			firstLine = 1;
+		}
+		for (int i = firstLine; i < lines.length; i++) {
+			if (lines[i] == null && fSelected[i] != 0)
+				return false;
+			if (lines[i] != null) {
+				if (!lineMatches(topLeft.x, fSelected[i], lines[i]))
+					return false;
+			}
+		}
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	protected boolean clipboardDimensionsFit(String s) {
+		if (data instanceof MolecularData) {
+			return (matchesMolecular(s));
+		}
+		return super.clipboardDimensionsFit(s);
+	}
+
+	/* ................................................................................................................. */
+	public String[] getLines(String s) {
+		return StringUtil.getLines(s);
+	}
+
+	/* ................................................................................................................. */
+	public void setSelectionToShape(int[] lines) {
+		super.setSelectionToShape(lines);
+	}
+
+	/* ................................................................................................................. */
+	String molecToken(StringBuffer sb, boolean wholeEvenIfNoTab) {
+		if (sb.indexOf("\t") >= 0) {
+			String result = sb.substring(0, sb.indexOf("\t"));
+			sb.delete(0, sb.indexOf("\t") + 1);
+			return result;
+		}
+		else if (wholeEvenIfNoTab) {
+			String result = sb.toString();
+			sb.setLength(0);
+			return result;
+		}
+		if (sb.length() == 0)
+			return null;
+		String result = sb.substring(0, 1);
+		sb.delete(0, 1);
+		return result;
+
+	}
+	/* ................................................................................................................. */
+	void removeTaxonNameIfPresent(StringBuffer sb) {
+		if (sb.indexOf("\t") >= 0) {
+			String result = sb.substring(0, sb.indexOf("\t"));
+			sb.delete(0, sb.indexOf("\t") + 1);
+		}
+	}
+
+	/* ................................................................................................................. */
+	boolean pasteMolecular(String s) {
+
+		int[] fSelected = getSelectedSpaces();
+		if (fSelected == null || fSelected.length == 0)
+			return false;
+		String[] lines = getLines(s);
+
+		int lineCount = 0;
+		boolean sbUsed = false;
+		StringBuffer sb = new StringBuffer(lines[0]);
+		for (int i = 0; i < numColumnsTotal; i++) {
+			if ((isColumnNameSelected(i) || isColumnSelected(i)) && columnNamesCopyPaste) {
+				sbUsed = true;
+				returnedColumnNameText(i, molecToken(sb, true));
+			}
+		}
+		if (sbUsed)
+			lineCount++;
+		boolean taxNamesChanged = false;
+		boolean atLeastOneFullRowSelected = isAnyRowSelected();
+		for (int j = 0; j < numRowsTotal && lineCount < lines.length; j++) {
+			if (sbUsed)
+				sb = new StringBuffer(lines[lineCount]);
+			sbUsed = false;
+			if (atLeastOneFullRowSelected) {  // need to remove part before tab if a tab is there
+				removeTaxonNameIfPresent(sb);
+			} else if (rowNamesCopyPaste && (isRowNameSelected(j))) { // for name of taxon
+				returnedRowNameText(j, molecToken(sb, true));
+				taxNamesChanged = true;
+				sbUsed = true;
+			}  
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+					returnedMatrixText(i, j, molecToken(sb, false));
+					sbUsed = true;
+				}
+			}
+			if (sbUsed)
+				lineCount++;
+		}
+		if (taxNamesChanged)
+			data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	protected void pasteIt(String s) {
+		if (data instanceof MolecularData) {
+			if (pasteMolecular(s)) {
+				return;
+			}
+
+		}
+		taxNC = false; // a thread unsafe way to discover if the superclass set taxon names
+		super.pasteIt(s);
+		if (taxNC)
+			data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+		taxNC = false;
+	}
+
+	boolean taxNC = false;
+
+	public boolean autoSizeColumns(Graphics g) { // this is EXTREMELY slow for large matrices.
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		// int h = fm.getMaxAscent()+ fm.getMaxDescent() + MesquiteModule.textEdgeCompensationHeight; //2 + MesquiteString.riseOffset;
+		// setRowHeightsUniform(h);
+		// if (!columnNames.isDiagonal())
+		// setColumnNamesRowHeight(h);
+		autoSizeRows(g);
+		String s;
+		int tableWIDTHpart = getTableWidth() / 3;
+		boolean changed = false;
+		int def = fm.stringWidth("G"); // WPMMAT 12
+		if (columnNames.isDiagonal()) {
+			int def2 = fm.getAscent() + fm.getDescent();
+			if (def < def2)
+				def = def2;
+		}
+		int max = def;
+		for (int ic = 0; ic < data.getNumChars(false); ic++) {
+			if (!columnAdjusted(ic)) {
+				if (autoWithCharNames.getValue() && data.characterHasName(ic) && !columnNames.isDiagonal())
+					max = fm.stringWidth(getColumnNameTextForDisplay(ic));
+				else
+					max = def;
+				if (showStates.getValue()) {
+					for (int it = 0; it < data.getNumTaxa(false); it++) {
+						s = getMatrixTextForDisplay(ic, it);
+						int lengthString = fm.stringWidth(s);
+						if (lengthString > max)
+							max = lengthString;
+					}
+				}
+				if (getConstrainMaxAutoColumn() && max > tableWIDTHpart)
+					max = tableWIDTHpart;
+				int newCW = 0;
+				int current = getColumnWidth(ic);
+				if (tight.getValue())
+					newCW = max + 2; // WPMMAT + MesquiteModule.textEdgeCompensationHeight
+				else
+					newCW = max + 2 + MesquiteModule.textEdgeCompensationHeight;
+				if (newCW != current) {
+					setColumnWidth(ic, newCW);
+					changed = true;
+				}
+			}
+		}
+		return changed;
+
+	}
+
+	/* ............................................................................................................... */
+	public FileInterpreter findFileInterpreter(String droppedContents, String fileName) {
+		MesquiteWindow mw = getMesquiteWindow();
+		if (mw != null) {
+			FileCoordinator fileCoord = mw.getOwnerModule().getFileCoordinator();
+			FileInterpreter fileInterpreter = fileCoord.findImporter(droppedContents, fileName, 0, StringUtil.argumentMarker + "fuseTaxaCharBlocks", true, data.getStateClass());   //DRM  9 April 2014   added "fuseTaxaCharBlocks" as that is what is happening here
+			return fileInterpreter;
+		}
+		return null;
+	}
+
+	/* ............................................................................................................... */
+	public void actUponDroppedFileContents(FileInterpreter fileInterpreter, String path) {
+		if (fileInterpreter != null) {
+
+			data.setCharNumChanging(true);
+			((ReadFileFromString) fileInterpreter).readFileFromString(data, taxa, MesquiteFile.getFileContentsAsString(path), "");
+			data.setCharNumChanging(false);
+
+			taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null, null));
+			data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+			data.notifyListeners(this, new Notification(CharacterData.DATA_CHANGED, null, null));
+		}
+	}
+
+	boolean adjustNewSequences = false;
+	int referenceSequence = 0;
+
+	/* ................................................................................................................. */
+	public boolean queryDroppedFileOptions() {
+		if (!(data instanceof MolecularData))
+			return false;
+		
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(editorModule.containerOfModule(), "Adjust incoming sequences?", buttonPressed); // MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		String s="If you choose to adjust sequences on import, then Mesquite will examine each sequence it imports, and compare it against the reference sequence. ";
+		s+="It will reverse complement any DNA sequences that need to be so treated, and then do a partial pairwise alignment (no new gaps will be inserted) of that sequence to the reference sequence.";
+		dialog.appendToHelpString(s);
+	//	if (data instanceof DNAData) {
+	//		dialog.addLabel("Reverse complement a sequence (if needed)");
+	//		dialog.addBlankLine();
+	//	}
+		IntegerField referenceSequenceBox = dialog.addIntegerField("Compare to reference sequence: ", referenceSequence + 1, 8, 1, data.getNumTaxa());
+		dialog.completeAndShowDialog("Adjust Sequences", "Don't Adjust", true, null);
+
+		if (buttonPressed.getValue() == 0) {
+			referenceSequence = referenceSequenceBox.getValue() - 1;
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue() == 0);
+	}
+	
+	public int numIters (Iterator iter) {
+		int count = 0;
+		for ( ; iter.hasNext() ; ++count ) iter.next();
+		return count;
+	}
+	/* ................................................................................................................. */
+	public void processFilesDroppedOnPanel(List files) {
+		int count = 0;
+
+		FileInterpreter fileInterpreter = null;
+		int numFiles = numIters(files.iterator());
+
+		for (Iterator iter = files.iterator(); iter.hasNext();) {
+			File nextFile = (File) iter.next();
+			if (!askListenersToProcess(nextFile, true)) {
+				int originalLastTaxonNumber = data.getNumTaxa();
+				if (count == 0) {
+					fileInterpreter = findFileInterpreter(MesquiteFile.getFileContentsAsString(nextFile.getAbsolutePath()), nextFile.getName());
+					if (fileInterpreter == null)
+						return;
+					fileInterpreter.startRecordingTaxa(taxa);
+					fileInterpreter.setTotalFilesToImport(numFiles);
+					fileInterpreter.setMultiFileImport(numFiles>1);
+					fileInterpreter.setOriginalNumTaxa(data.getNumTaxa());
+					fileInterpreter.setMaximumTaxonFilled(-1);
+
+					if (!MesquiteThread.isScripting()) {
+						if (data instanceof MolecularData)
+							adjustNewSequences = queryDroppedFileOptions();
+					}
+					
+				}
+				fileInterpreter.setImportFileNumber(count);
+				// system.out.println("next file dropped is: " + nextFile);
+				MesquiteMessage.println("\n\nReading file " + nextFile.getName());
+				CommandRecord.tick("\n\nReading file " + nextFile.getName());
+				actUponDroppedFileContents(fileInterpreter, nextFile.getAbsolutePath());
+
+				count++;
+			}
+		}
+		if (fileInterpreter!=null) {
+			if (adjustNewSequences) {
+				MesquiteMessage.println("Adjusting sequences ");
+				if (!data.someApplicableInTaxon(referenceSequence, false)){  
+					MesquiteMessage.println("The reference sequence contains no data; adjustment cancelled.");
+				    adjustNewSequences = false;
+				}
+				if (adjustNewSequences) {
+					Bits newTaxa = fileInterpreter.getNewlyAddedTaxa(taxa);
+					if (data instanceof DNAData){
+						MolecularDataUtil.reverseComplementSequencesIfNecessary((DNAData) data, editorModule, taxa, newTaxa, 0, false, false);
+					}
+					MolecularDataUtil.pairwiseAlignMatrix(editorModule, (MolecularData)data, referenceSequence, newTaxa,0, false);
+					data.notifyListeners(this, new Notification(CharacterData.DATA_CHANGED, null, null));
+				}
+			}
+			fileInterpreter.setMaximumTaxonFilled(-1);
+			fileInterpreter.endRecordingTaxa(taxa);
+		}
+
+		if (fileInterpreter != null)
+			fileInterpreter.reset();
+
+	}
+
+	/* ................................................................................................................. */
+	public void processFileStringDroppedOnPanel(String path) {
+		String contents = MesquiteFile.getURLContentsAsString(path, -1);
+		FileInterpreter fileInterpreter = null;
+		fileInterpreter = findFileInterpreter(contents, "File Contents");
+		if (fileInterpreter != null)
+			actUponDroppedFileContents(fileInterpreter, path);
+
+	}
+
+	/* ............................................................................................................... */
+	public void tellCellColorerViewChanged() {
+		if (cellColorer != null)
+			cellColorer.viewChanged();
+		if (textColorer != null)
+			textColorer.viewChanged();
+	}
+
+	boolean settingColumn = false;
+
+	boolean settingRow = false;
+
+	/* ............................................................................................................... */
+	/** sets which column is the first visible. */
+	public void setFirstColumnVisible(int value, boolean repaintPlease) {
+		if (settingColumn)
+			return;
+		super.setFirstColumnVisible(value, repaintPlease);
+		if (oldFirstColumn != getFirstColumnVisible())
+			tellCellColorerViewChanged();
+		oldFirstColumn = getFirstColumnVisible();
+		if (window.linkedScrolling.getValue()) {
+			settingColumn = true;
+			setFirstColumnVisibleLinked(value);
+			settingColumn = false;
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the first visible. */
+	public void setFirstRowVisible(int value, boolean repaintPlease) {
+		if (settingRow)
+			return;
+		super.setFirstRowVisible(value, repaintPlease);
+		if (oldFirstRow != getFirstRowVisible())
+			tellCellColorerViewChanged();
+		oldFirstRow = getFirstRowVisible();
+		if (window.linkedScrolling.getValue()) {
+			settingRow = true;
+			setFirstRowVisibleLinked(value);
+			settingRow = false;
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Resets sizes of all components. */
+	public void resetComponentSizes() {
+		super.resetComponentSizes();
+		if (oldFirstColumn != getFirstColumnVisible() && oldFirstRow != getFirstRowVisible() && oldLastColumn != getLastColumnVisible() && oldLastRow != getLastRowVisible())
+			tellCellColorerViewChanged();
+		oldFirstColumn = getFirstColumnVisible();
+		oldLastColumn = getLastColumnVisible();
+		oldFirstRow = getFirstRowVisible();
+		oldLastRow = getLastRowVisible();
+	}
+
+	/* ............................................................................................................... */
+	public String getUpperCornerText() {
+	//	if (data == null)
+			return "";
+		
+//		return data.getName();
+	}
+	/* ............................................................................................................... */
+	public String getCornerText() {
+		return "Taxon  \\  Character";
+	}
+
+	/* ............................................................................................................... */
+	public BasicDataWindow getBasicDataWindow() {
+		return window;
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the first visible. */
+	public void setFirstRowVisible(int value) {
+		super.setFirstRowVisible(value);
+		window.setExplanation("Characters " + (getFirstColumnVisible() + 1) + " to " + (getLastColumnVisible() + 1) + "; Taxa " + +(getFirstRowVisible() + 1) + " to " + (getLastRowVisible() + 1));
+	}
+
+	/* ............................................................................................................... */
+	/** sets which column is the first visible. */
+	public void setFirstColumnVisible(int value) {
+		super.setFirstColumnVisible(value);
+		window.setExplanation("Characters " + (getFirstColumnVisible() + 1) + " to " + (getLastColumnVisible() + 1) + "; Taxa " + +(getFirstRowVisible() + 1) + " to " + (getLastRowVisible() + 1));
+	}
+
+	/* ............................................................................................................... */
+	/** returns color of row or number box. */
+	public Color getRCNumberBoxColor(boolean isRow, int number) {
+		Color color = null;
+		if (!isRow)
+			color = data.getDefaultCharacterColor(number);
+		if (color != null)
+			return color;
+		else if (!isRow)
+			return ColorTheme.getContentElement();
+		return ColorTheme.getContentElement();
+	}
+
+	/* ............................................................................................................... */
+	/** returns dark color of row or number box. */
+	public Color getRCNumberBoxDarkColor(boolean isRow, int number) {
+		Color color = null;
+		if (!isRow)
+			color = data.getDarkDefaultCharacterColor(number);
+		if (color != null)
+			return color;
+		// return ColorDistribution.dark[colorScheme];
+		return ColorTheme.getContentDarkElement();
+	}
+
+	/* ............................................................................................................... */
+	public DataColumnNamesAssistant getDataColumnNamesAssistant(int subRow) {
+		return window.getDataColumnNamesAssistant(subRow);
+	}
+
+	/* ............................................................................................................... */
+	public void drawColumnNamesPanelExtras(Graphics g, int left, int top, int width, int height) {
+		if (data == null)
+			return;
+		Color oldColor = g.getColor();
+		for (int extraRow = 0; extraRow < window.numDataColumnNamesAssistants(); extraRow++) {
+			DataColumnNamesAssistant assistant = window.getDataColumnNamesAssistant(extraRow);
+			for (int c = getFirstColumnVisible(); (c < numColumnsTotal) && (c <= getLastColumnVisible() + 1); c++) {
+				int leftSide = columnNames.startOfColumn(c);
+				int topSide = columnNames.extraRowTop(extraRow);
+
+				if (assistant != null)
+					assistant.drawInCell(c, g, leftSide, topSide, columnNames.columnWidth(c), columnNames.rowHeight(-1), false);
+				g.setColor(Color.gray);
+				g.drawRect(leftSide, topSide, columnNames.columnWidth(c), columnNames.rowHeight(-1));
+			}
+		}
+		g.setColor(oldColor);
+	}
+
+	/* ............................................................................................................... */
+	float[] hsb = new float[3];
+
+	/*
+	 * MesquiteTimer timer1 = new MesquiteTimer(); MesquiteTimer timer2 = new MesquiteTimer(); MesquiteTimer timer3 = new MesquiteTimer(); MesquiteTimer timer4 = new MesquiteTimer(); MesquiteTimer timer5 = new MesquiteTimer(); MesquiteTimer timer6 = new MesquiteTimer();
+	 * 
+	 * timer1.start(); //600
+	 * 
+	 * timer1.end(); timer2.start(); //648
+	 * 
+	 * timer2.end(); timer3.start(); //277
+	 * 
+	 * timer3.end(); timer4.start(); //57
+	 * 
+	 * timer4.end(); timer5.start(); //500
+	 * 
+	 * timer5.end(); timer6.start(); //270
+	 * 
+	 * timer6.end(); .println("timers 1 " + timer1.getAccumulatedTime() + " timer2 " + timer2.getAccumulatedTime() + " timer3 " + timer3.getAccumulatedTime() + " timer4 " + timer4.getAccumulatedTime() + " timer5 " + timer5.getAccumulatedTime() + " timer6 " + timer6.getAccumulatedTime());
+	 */
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+
+	public boolean isAttachedNoteAvailable(int column, int row) {
+		if (data == null)
+			return false;
+		AttachedNotesVector anv = null;
+		try {
+			if (column < 0)
+				anv = (AttachedNotesVector) data.getTaxa().getAssociatedObject(notesNameRef, row);
+			else if (row < 0)
+				anv = (AttachedNotesVector) data.getAssociatedObject(notesNameRef, column);
+			else
+				anv = (AttachedNotesVector) data.getCellObject(notesNameRef, column, row);
+		} catch (Exception e) {
+		}
+		if (anv == null)
+			return false;
+		return (anv.getNumNotes() > 0);
+	}
+
+	MesquiteBoolean overflow = new MesquiteBoolean(false);
+
+	public void drawMatrixCell(Graphics g, int x, int y, int w, int h, int column, int row, boolean selected) {
+		if (data == null)
+			return;
+		boolean writeStates = !showBirdsEyeView.getValue() && showStates.getValue();
+		boolean leaveEdges = writeStates && !tight.getValue();
+		drawMatrixCell(g, x, y, w, h, column, row, selected, writeStates, leaveEdges);
+
+	}
+
+	public CellColorer getCellColorer() {
+		return cellColorer;
+	}
+
+	public synchronized void drawMatrixCell(Graphics g, int x, int y, int w, int h, int column, int row, boolean selected, boolean writeStates, boolean leaveEdges) {
+		if (data == null)
+			return;
+		boolean changedSinceSave = showChanges.getValue() && data.getChangedSinceSave(column, row);
+
+		boolean annotationAvailable = isAttachedNoteAvailable(column, row);
+
+		Color c = g.getColor();
+		hsb[0] = hsb[1] = hsb[2] = 1;
+
+		Color fillColor = null;
+		// ColorDistribution.setTransparentGraphics(g);
+		// g.setColor(Color.gray);
+
+		if (cellColorer != null) {
+			try {
+				fillColor = cellColorer.getCellColor(column, row);
+				if (paleCellColors && fillColor != null)
+					fillColor = ColorDistribution.brighter(fillColor, 0.45);
+			} catch (Throwable e) {
+			}
+		}
+		
+/*		if (paleInapplicable.getValue() && data.isTerminalInapplicable(column, row)){
+				fillColor = Color.white;
+				//fillColor = Color.lightGray;
+				g.setColor(ColorDistribution.veryVeryLightGray);
+				g.drawRect(x, y+1, w, h-2);
+		}
+		else { */
+			if (fillColor == null)
+				fillColor = bgColor;
+			if (showPaleExcluded.getValue() && !data.isCurrentlyIncluded(column))
+				fillColor = ColorDistribution.brighter(fillColor, showPaleExcludedValueBackground);
+			Color.RGBtoHSB(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), hsb);
+		//}
+		g.setColor(fillColor);
+
+		if (leaveEdges)
+			g.fillRect(x + 1, y + 1, w - 1, h - 1);
+		else
+			g.fillRect(x, y, w, h);
+
+		if (selected) {
+			if (leaveEdges)
+				GraphicsUtil.fillTransparentSelectionRectangle(g, x + 1, y + 1, w - 1, h - 1);
+			else
+				GraphicsUtil.fillTransparentSelectionRectangle(g, x, y, w, h);
+		}
+
+		if (writeStates) {
+			if (changedSinceSave) {
+				g.setColor(ColorDistribution.getContrasting(selected, fillColor, hsb, Color.lightGray, Color.darkGray));
+				g.drawLine(x, y + 1, x + 1, y);
+				g.drawLine(x, y + 2, x + 2, y);
+				g.drawLine(x, y + 3, x + 3, y);
+			}
+			if (annotationAvailable) {
+				g.setColor(ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black));
+				g.drawLine(x + w - 2, y + 1, x + w - 2, y + 2); // left
+				g.drawLine(x + w - 2, y + 2, x + w, y + 2); // bottom
+				g.drawLine(x + w, y + 1, x + w, y + 2); // right
+				g.drawLine(x + w - 2, y, x + w, y); // top
+				if (!selected) {
+					g.setColor(Color.white);
+					g.drawLine(x + w - 1, y + 1, x + w - 1, y + 1);
+				}
+			}
+
+			try {
+				Color textColor = null;
+				if (textColorer != null && !(textColorer instanceof mesquite.charMatrices.NoColor.NoColor))
+					textColor = textColorer.getCellColor(column, row);
+
+				if (textColor == null) {
+					if (paleInapplicable.getValue() && data.isInapplicable(column, row)){
+					/*	if (data.isTerminalInapplicable(column, row))
+							textColor = Color.white;
+						else */
+							textColor = Color.lightGray;
+					}
+					else
+						textColor = ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black);
+				}
+				if (showPaleExcluded.getValue() && !data.isCurrentlyIncluded(column))
+					textColor = ColorDistribution.brighter(textColor, showPaleExcludedValueText);
+				g.setColor(textColor);
+			} catch (Exception e) {
+			}
+
+			String st = getMatrixTextForDisplay(column, row);
+			overflow.setValue(false);
+			int cent = StringUtil.getStringCenterPosition(st, g, x, w, overflow);
+			boolean useClip = overflow.getValue();
+			int vert = StringUtil.getStringVertPosition(g, y, h, overflow);
+			useClip |= overflow.getValue();
+			Shape clip = null;
+			if (useClip) {
+				clip = g.getClip();
+				g.setClip(x, y, w, h);
+			}
+			if (st != null)
+				g.drawString(st, cent, vert); // this is very time costly on OSX java 1.4!! (as of 10.3.9 on Powerbook G4)
+			if (useClip) {
+				g.setClip(clip);
+			}
+
+		}
+		if (c != null)
+			g.setColor(c);
+
+	}
+
+	/* ............................................................................................................... */
+	public boolean useString(int column, int row) {
+		return false; // (cellColorer == null && !data.getChangedSinceSave(column, row));
+	}
+
+	public Color getColumnNameFillColor(int column, Color defaultFillColor, boolean focused, boolean selected, boolean dimmed, boolean editable) {
+		Color color = null;
+		if (selected) {
+			color = Color.white;
+		}
+		else if (columnNamesColorer != null) {
+			color = columnNamesColorer.getCellColor(column, -1);
+		}
+		if (color == null)
+			color = bgColor;
+		return color;
+	}
+
+	/* ............................................................................................................... */
+	public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column) {
+
+		if (data == null)
+			return;
+		boolean annotationAvailable = isAttachedNoteAvailable(column, -1);
+		Color fillColor = null;
+		boolean selected = isColumnNameSelectedAnyWay(column);
+		fillColor = getColumnNameFillColor(column, Color.white, false, selected, false, true);
+
+		if (fillColor != null) {
+			Color c = g.getColor();
+			g.setColor(fillColor);
+			columnNames.fillCell(g, x, y, w, h, selected);
+			/*
+			 * g.fillRect(x+1,y+1,w-1,h-1); if (selected) GraphicsUtil.fillTransparentSelectionRectangle(g,x+1,y+1,w-1,h-1);
+			 */
+			if (c != null)
+				g.setColor(c);
+
+		}
+
+		hsb[0] = hsb[1] = hsb[2] = 1;
+		Color.RGBtoHSB(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), hsb);
+		Color oldColor = null;
+		if (annotationAvailable) {
+			oldColor = g.getColor();
+			g.setColor(ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black));
+			g.drawLine(x + w - 2, y + 1, x + w - 2, y + 2); // left
+			g.drawLine(x + w - 2, y + 2, x + w, y + 2); // bottom
+			g.drawLine(x + w, y + 1, x + w, y + 2); // right
+			g.drawLine(x + w - 2, y, x + w, y); // top
+			if (!selected) {
+				g.setColor(Color.white);
+				g.drawLine(x + w - 1, y + 1, x + w - 1, y + 1);
+			}
+			g.setColor(oldColor);
+		}
+		if (selected) {
+			g.setColor(Color.white);
+		}
+
+		oldColor = g.getColor();
+
+		Color textColor = null;
+		if (textColorer != null && !(textColorer instanceof mesquite.charMatrices.NoColor.NoColor))
+			textColor = textColorer.getCellColor(column, -1);
+
+		if (textColor == null) {
+			textColor = ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black);
+		}
+		g.setColor(textColor);
+
+		String name = getColumnNameTextForDisplay(column);
+		String s = data.getAnnotation(column);
+		if (!StringUtil.blank(s))
+			name = "*" + name;
+
+		g.drawString(name, x + getNameStartOffset(), StringUtil.getStringVertPosition(g, y, h, null));
+
+		g.setColor(oldColor);
+	}
+
+	/* ............................................................................................................... */
+	public void drawRowNameCell(Graphics g, int x, int y, int w, int h, int row) {
+		if (taxa == null || row >= taxa.getNumTaxa())
+			return;
+		Color fillColor = null;
+
+		boolean annotationAvailable = isAttachedNoteAvailable(-1, row);
+		boolean selected = isRowNameSelectedAnyWay(row);
+		if (selected) {
+			fillColor = Color.white;
+		}
+		else if (rowNamesColorer != null) {
+			fillColor = rowNamesColorer.getCellColor(-1, row);
+		}
+		if (fillColor == null)
+			fillColor = bgColor;
+		if (fillColor != null) {
+			Color c = g.getColor();
+			g.setColor(fillColor);
+			g.fillRect(x + 1, y + 1, w - 1, h - 1);
+			if (selected)
+				GraphicsUtil.fillTransparentSelectionRectangle(g, x + 1, y + 1, w - 1, h - 1);
+			if (c != null)
+				g.setColor(c);
+		}
+		hsb[0] = hsb[1] = hsb[2] = 1;
+		Color.RGBtoHSB(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), hsb);
+
+		Color oldColor = null;
+		if (annotationAvailable) {
+			oldColor = g.getColor();
+			g.setColor(ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black));
+			g.drawLine(x + w - 3, y + 1, x + w - 3, y + 2); // left
+			g.drawLine(x + w - 3, y + 2, x + w - 1, y + 2); // bottom
+			g.drawLine(x + w - 1, y + 1, x + w - 1, y + 2); // right
+			g.drawLine(x + w - 3, y, x + w - 1, y); // top
+			if (!selected) {
+				g.setColor(Color.white);
+				g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+			}
+			g.setColor(oldColor);
+		}
+		oldColor = g.getColor();
+		Color textColor = null;
+		if (textColorer != null && !(textColorer instanceof mesquite.charMatrices.NoColor.NoColor))
+			textColor = textColorer.getCellColor(-1, row);
+
+		if (textColor == null) {
+			textColor = ColorDistribution.getContrasting(selected, fillColor, hsb, Color.white, Color.black);
+		}
+		g.setColor(textColor);
+
+		String s = taxa.getAnnotation(row);
+
+		int svp = StringUtil.getStringVertPosition(g, y, h, null);
+		int xgnso = x + getNameStartOffset();
+
+		if (getShowRowNames())
+			if (!StringUtil.blank(s))
+				g.drawString("*" + taxa.getTaxon(row).getName(), xgnso, svp);
+			else
+				g.drawString(taxa.getTaxon(row).getName(), xgnso, svp);
+
+		g.setColor(oldColor);
+
+	}
+
+	Color distinguishTextColor(Graphics g, Color bg) {
+		Color current = g.getColor();
+		if (current.equals(bg)) {
+			if (current.equals(Color.black))
+				g.setColor(Color.white);
+			else
+				g.setColor(Color.black);
+			return current;
+		}
+		return null;
+
+	}
+
+	StringBuffer sb = new StringBuffer(50);
+
+	/* ............................................................................................................... */
+	public synchronized String getMatrixText(int column, int row) {
+		sb.setLength(0);
+		data.statesIntoStringBuffer(column, row, sb, false);
+		return sb.toString();
+	}
+
+	boolean displayModifications = false;
+
+	private boolean checkDisplayModifications() {
+		try {
+			// go through all assistants to see if they claim hasDisplayModifications
+			Enumeration enumeration = window.ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()) {
+				Object obj = enumeration.nextElement();
+				if (obj instanceof DataWindowAssistant) {
+					DataWindowAssistant init = (DataWindowAssistant) obj;
+					if (init.hasDisplayModifications()) {
+						return true;
+					}
+				}
+			}
+		} catch (Exception e) {
+		}
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	public void setLastColumnVisibleLinked(int column) {
+		for (int i = 0; i < linkedTables.size(); i++) {
+			MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+			t.setLastColumnVisible(column);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void setFirstColumnVisibleLinked(int column) {
+		for (int i = 0; i < linkedTables.size(); i++) {
+			MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+			t.setFirstColumnVisible(column);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void setLastRowVisibleLinked(int row) {
+		for (int i = 0; i < linkedTables.size(); i++) {
+			MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+			t.setLastRowVisible(row);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void setFirstRowVisibleLinked(int row) {
+		for (int i = 0; i < linkedTables.size(); i++) {
+			MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+			t.setFirstRowVisible(row);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public synchronized String getMatrixTextForDisplay(int column, int row) {
+
+		sb.setLength(0);
+		data.statesIntoStringBuffer(column, row, sb, showNames.getValue());
+		if (!StringUtil.blank(data.getAnnotation(column, row))) {
+			sb.append('*');
+		}
+		if (displayModifications) {
+			if (data.getCellObjectDisplay(column, row)) {
+				// go through assistants that claim to have modifications to see what each wants to add
+				Enumeration enumeration = window.ownerModule.getEmployeeVector().elements();
+				while (enumeration.hasMoreElements()) {
+					Object obj = enumeration.nextElement();
+					if (obj instanceof DataWindowAssistant) {
+						DataWindowAssistant init = (DataWindowAssistant) obj;
+						if (init.hasDisplayModifications()) {
+							String s = init.getDisplayModString(column, row);
+							if (s != null)
+								sb.append(s);
+						}
+					}
+				}
+			}
+		}
+		return sb.toString();
+
+	}
+
+	/* ................................................................................................................. */
+	public String getColumnComment(int column) {
+		return data.getAnnotation(column);
+	}
+
+	/* ................................................................................................................. */
+	public String getRowComment(int row) {
+		return taxa.getAnnotation(row);
+	}
+
+	/* ............................................................................................................... */
+	/** Returns text in row name. */
+	public synchronized String getRowNameText(int row) {
+		Taxon t = taxa.getTaxon(row);
+		if (t != null) {
+			return t.getName();
+		}
+		else
+			return "";
+	}
+
+	/* ............................................................................................................... */
+	/** Returns text in column name. */
+	public synchronized String getColumnNameText(int column) {
+		return data.getCharacterName(column);
+	}
+
+	/* ............................................................................................................... */
+	/** Returns text in column name. */
+	public synchronized String getColumnNameTextForDisplay(int column) {
+		if (data.characterHasName(column))
+			return data.getCharacterName(column);
+		else if (showDefaultCharNames.getValue())
+			return Integer.toString(CharacterStates.toExternal(column));
+		return "";
+	}
+
+	/* ............................................................................................................... */
+	void broadcastFocusInCell(int column, int row) {
+		if (window.sequenceLedge != null)
+			window.sequenceLedge.setFocus(this, column, row);
+		ListableVector v = null;
+		try {
+			v = window.ownerModule.getEmployeeVector();
+		} catch (Exception e) {
+		}
+		if (v != null)
+			for (int i = 0; i < v.size(); i++) {
+				Object obj = null;
+				// try {
+				obj = v.elementAt(i);
+				if (obj instanceof DataWindowAssistant) {
+					DataWindowAssistant a = (DataWindowAssistant) obj;
+					a.focusInCell(column, row);
+				}
+
+				/*
+				 * } catch(Exception e){ MesquiteMessage.warnProgrammer("exception in broadcastFocusInCell to " + obj + "   " + e); e.printStackTrace(); }
+				 */
+
+			}
+	}
+
+	/* ............................................................................................................... */
+	StringBuffer esb = new StringBuffer(100);
+
+	String getCellExplanation(int column, int row) {
+		if (data == null)
+			return null;
+		String s = "[";
+		try {
+			if (row >= 0 && row < data.getNumTaxa())
+				s += "t." + (row + 1);
+			if (column >= 0 && column < data.getNumChars())
+				s += " c." + (column + 1);
+			if (row >= 0 && row < data.getNumTaxa() && column >= 0 && column < data.getNumChars()) {
+				esb.setLength(0);
+				data.statesIntoStringBuffer(column, row, esb, false);
+				s += " s." + esb;
+			}
+			s += "] ";
+			if (column >= 0 && column < data.getNumChars())
+				s += data.getCharacterName(column) + statesExplanation(column, row);
+			if (row >= 0 && row < data.getNumTaxa() && column >= 0)
+				s += " [in taxon \"" + data.getTaxa().getTaxonName(row) + "\"]";
+
+			if (window == null || window.ownerModule == null)
+				return s;
+			ListableVector v = window.ownerModule.getEmployeeVector();
+			if (v != null)
+				for (int i = 0; i < v.size(); i++) {
+					Object obj = v.elementAt(i);
+					if (obj instanceof DataWindowAssistant) {
+						DataWindowAssistant a = (DataWindowAssistant) obj;
+						String ce = a.getCellExplanation(column, row);
+						if (!StringUtil.blank(ce))
+							s += "\n" + ce;
+						if (a == cellColorer) {
+							String colors = a.getCellString(column, row);
+							if (!StringUtil.blank(colors))
+								s += "\nColor of cell: " + colors + "\n";
+						}
+					}
+				}
+
+			AttachedNotesVector anv = null;
+			if (column < 0)
+				anv = (AttachedNotesVector) data.getTaxa().getAssociatedObject(notesNameRef, row);
+			else if (row < 0)
+				anv = (AttachedNotesVector) data.getAssociatedObject(notesNameRef, column);
+			else
+				anv = (AttachedNotesVector) data.getCellObject(notesNameRef, column, row);
+
+			if (anv != null && anv.getNumNotes() > 0) {
+				s += "\n-----------------";
+				s += "\nAnnotations:";
+				for (int i = 0; i < anv.getNumNotes(); i++) {
+					AttachedNote note = anv.getAttachedNote(i);
+					if (note != null) {
+						String c = note.getComment();
+						if (!StringUtil.blank(c)) {
+							s += "\n" + (c.replace('\n', ' ')).replace('\r', ' ');
+							if (!StringUtil.blank(note.getAuthorName()))
+								s += "  (author: " + note.getAuthorName() + ")";
+						}
+					}
+				}
+				s += "\n-----------------";
+			}
+		} catch (Throwable t) {
+			s = "";
+			MesquiteFile.throwableToLog(null, t);
+		}
+		return s;
+	}
+
+	public void setFocusedCell(int column, int row) {
+		super.setFocusedCell(column, row);
+		cellAnnotated.setCell(column, row);
+		window.setAnnotation(cellAnnotated);
+		window.setExplanation(getCellExplanation(column, row));
+		broadcastFocusInCell(column, row);
+		if ((window.getCurrentTool() == window.arrowTool) && window.ibeamTool != null && (isEditing(column, row))) {
+			window.setCurrentTool(window.ibeamTool);
+			window.getPalette().setCurrentTool(window.ibeamTool);
+		}
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(column, row);
+	}
+
+	void refreshAnnotation() {
+		window.setAnnotation(cellAnnotated);
+	}
+
+	/* ............................................................................................................... */
+	public void clickOutside() {
+		setFocusedCell(-2, -2);
+	}
+
+	boolean suppressSelect = false;
+
+	public void selectRow(int row) {
+		super.selectRow(row);
+		// data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		// notifySelectionChanged();
+	}
+
+	public void selectRows(int first, int last) {
+		super.selectRows(first, last);
+		// data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		// notifySelectionChanged();
+	}
+
+	public void selectColumn(int column) {
+		super.selectColumn(column);
+		// data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		// notifySelectionChanged();
+	}
+
+	public void selectColumns(int first, int last) {
+		super.selectColumns(first, last);
+		// data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		// notifySelectionChanged();
+	}
+
+	public void selectCell(int column, int row) {
+		if (!suppressSelect) {
+			super.selectCell(column, row);
+			suppressSelect = true;
+			for (int i = 0; i < linkedTables.size(); i++) {
+				MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+				t.selectCell(column, row);
+				t.redrawCell(column, row);
+			}
+			suppressSelect = false;
+			notifySelectionChanged();
+		}
+	}
+
+	public void deselectCell(int column, int row) {
+		if (!suppressSelect) {
+			super.deselectCell(column, row);
+			suppressSelect = true;
+			for (int i = 0; i < linkedTables.size(); i++) {
+				MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+				t.deselectCell(column, row);
+				t.redrawCell(column, row);
+			}
+			suppressSelect = false;
+			notifySelectionChanged();
+		}
+	}
+
+	public void selectBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!suppressSelect) {
+			super.selectBlock(firstColumn, firstRow, lastColumn, lastRow);
+			suppressSelect = true;
+			for (int i = 0; i < linkedTables.size(); i++) {
+				MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+				t.selectBlock(firstColumn, firstRow, lastColumn, lastRow);
+				t.redrawBlock(firstColumn, firstRow, lastColumn, lastRow);
+			}
+			suppressSelect = false;
+			notifySelectionChanged();
+		}
+	}
+	
+	public void deSelectBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!suppressSelect) {
+			super.deSelectBlock(firstColumn, firstRow, lastColumn, lastRow);
+			suppressSelect = true;
+			for (int i = 0; i < linkedTables.size(); i++) {
+				MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+				t.deSelectBlock(firstColumn, firstRow, lastColumn, lastRow);
+				t.redrawBlock(firstColumn, firstRow, lastColumn, lastRow);
+			}
+			suppressSelect = false;
+			notifySelectionChanged();
+		}
+	}
+
+	public void deselectAllCells(boolean notify) {
+		if (!suppressSelect) {
+			super.deselectAllCells(notify);
+			suppressSelect = true;
+			for (int i = 0; i < linkedTables.size(); i++) {
+				MesquiteTable t = (MesquiteTable) linkedTables.elementAt(i);
+				t.deselectAllCells(false);
+				t.repaintAll();
+			}
+			suppressSelect = false;
+			if (notify)
+				notifySelectionChanged();
+		}
+	}
+
+	public void synchronizeRowSelection(Associable a) {
+		super.synchronizeRowSelection(a);
+		notifySelectionChanged();
+	}
+
+	public void synchronizeColumnSelection(Associable a) {
+		super.synchronizeColumnSelection(a);
+		notifySelectionChanged();
+	}
+
+	void notifySelectionChanged() {
+
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+			Enumeration enumeration = window.ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()) {
+				Object obj = enumeration.nextElement();
+				if (obj instanceof DataWindowAssistantI) {
+					DataWindowAssistantI init = (DataWindowAssistantI) obj;
+					init.tableSelectionChanged();
+				}
+			}
+		} catch (Exception e) { // just in case being disposed....
+		}
+		MesquiteWindow.uncheckDoomed(this);
+
+	}
+
+	/* ............................................................................................................... */
+	/** Called if part of panel out of bounds is touched. */
+	public void outOfBoundsTouched(int modifiers, int clickCount) {
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(-2, -2);
+	}
+
+	/* ............................................................................................................... */
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+
+		if ((window.getCurrentTool() == window.arrowTool) && (clickCount > 1) && window.ibeamTool != null) {
+			window.setCurrentTool(window.ibeamTool);
+			window.getPalette().setCurrentTool(window.ibeamTool);
+			((TableTool) window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		}
+		else if (((TableTool) window.getCurrentTool()).useTableTouchRules()) {
+			super.cellTouched(column, row, regionInCellH, regionInCellV, modifiers, clickCount);
+		}
+		else {
+			((TableTool) window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		}
+		if (window.getCurrentTool() == window.arrowTool || window.getCurrentTool() == window.ibeamTool || window.getCurrentTool().getAllowAnnotate() || ((TableTool) window.getCurrentTool()).useTableTouchRules()) {
+			setFocusedCell(column, row);
+		}
+		else
+			window.setAnnotation("", null);
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(column, row);
+	}
+
+	/* ............................................................................................................... */
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (((TableTool) window.getCurrentTool()).useTableTouchRules())
+			super.cellDrag(column, row, regionInCellH, regionInCellV, modifiers);
+		else
+			((TableTool) window.getCurrentTool()).cellDrag(column, row, regionInCellH, regionInCellV, modifiers);
+	}
+
+	/* ............................................................................................................... */
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (((TableTool) window.getCurrentTool()).useTableTouchRules())
+			super.cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+		else
+			((TableTool) window.getCurrentTool()).cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+
+	}
+
+	/* ............................................................................................................... */
+	private void checkTouchCurrentCell(int oldColumn, int oldRow) {
+		if (((TableTool) window.getCurrentTool()).getTouchOnArrowKey()) {
+			if (singleTableCellSelected()) {
+				Dimension sel = getFirstTableCellSelected();
+				if (oldColumn != sel.width || oldRow != sel.height) {
+					((TableTool) window.getCurrentTool()).cellTouched(sel.width, sel.height, 50, 50, 0);
+				}
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void downArrowPressed(String arguments) {
+		Dimension sel = getFirstTableCellSelected();
+		super.downArrowPressed(arguments);
+		checkTouchCurrentCell(sel.width, sel.height);
+	}
+
+	/* ............................................................................................................... */
+	public void upArrowPressed(String arguments) {
+		Dimension sel = getFirstTableCellSelected();
+		super.upArrowPressed(arguments);
+		checkTouchCurrentCell(sel.width, sel.height);
+	}
+
+	/* ............................................................................................................... */
+	public void rightArrowPressed(String arguments) {
+		Dimension sel = getFirstTableCellSelected();
+		super.rightArrowPressed(arguments);
+		checkTouchCurrentCell(sel.width, sel.height);
+	}
+
+	/* ............................................................................................................... */
+	public void leftArrowPressed(String arguments) {
+		Dimension sel = getFirstTableCellSelected();
+		super.leftArrowPressed(arguments);
+		checkTouchCurrentCell(sel.width, sel.height);
+	}
+
+	/* ............................................................................................................... */
+	public void rowNameTouched(int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (window.getCurrentTool() == window.arrowTool || window.getCurrentTool() == window.ibeamTool || window.getCurrentTool().getAllowAnnotate()) {
+			cellAnnotated.setCell(-1, row);
+			window.setAnnotation(cellAnnotated);
+		}
+		else
+			window.setAnnotation("", null);
+
+		if (window.getCurrentTool() == window.arrowTool)
+			if (clickCount > 1 && window.ibeamTool != null) {
+				window.setCurrentTool(window.ibeamTool);
+				window.getPalette().setCurrentTool(window.ibeamTool);
+				((TableTool) window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers);
+			}
+			else
+				super.rowNameTouched(row, regionInCellH, regionInCellV, modifiers, clickCount);
+		else
+			((TableTool) window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers);
+		broadcastFocusInCell(-1, row);
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(-1, row);
+	}
+
+	/* ............................................................................................................... */
+	public void rowTouched(boolean isArrowEquivalent, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (((TableTool) window.getCurrentTool()).useTableTouchRules() || isArrowEquivalent)
+			super.rowTouched(isArrowEquivalent, row, regionInCellH, regionInCellV, modifiers);
+		else
+			((TableTool) window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers);
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(-1, row);
+	}
+
+	/* ............................................................................................................... */
+	private String statesExplanation(int column, int row) {
+		String s = "";
+		if (data.getClass() == CategoricalData.class) {
+			s += ":  ";
+			if (statesSeparateLines.getValue())
+				s += "\n";
+			long state = ((CategoricalData) data).getState(column, row);
+			CategoricalData cData = (CategoricalData) data;
+			for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+				if (cData.hasStateName(column, i)) {
+					s += "(" + cData.getSymbol(i) + ")";
+					if (CategoricalState.isElement(state, i))
+						s += "*";
+					s += " " + cData.getStateName(column, i);
+					if (statesSeparateLines.getValue())
+						s += "\n";
+					else
+						s += "; ";
+				}
+		}
+		else if (data instanceof MolecularData) {
+			int count = 0;
+			for (int ic = 0; ic <= column; ic++) {
+				CategoricalData cData = (CategoricalData) data;
+				if (!cData.isInapplicable(ic, row))
+					count++;
+			}
+			if (count > 0) {
+				s += "; Sequence site " + count;
+			}
+		}
+		return s;
+	}
+
+	public void mouseExitedCell(int modifiers, int column, int subColumn, int row, int subRow, MesquiteTool tool) {
+		super.mouseExitedCell(modifiers, column, subColumn, row, subRow, tool);
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellExit(column, row);
+	}
+
+	/* ............................................................................................................... */
+	public void mouseInCell(int modifiers, int column, int subColumn, int row, int subRow, MesquiteTool tool) {
+				
+		if (column >= 0 && column <= data.getNumChars(false)) {
+			if (subRow >= 0) {
+				DataColumnNamesAssistant assistant = window.getDataColumnNamesAssistant(subRow);
+				if (assistant != null) {
+					String s = assistant.getStringForExplanation(column);
+					window.setExplanation(s);
+				}
+			}
+			else if ((!(matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) && !singleTableCellSelected())) {
+				window.setExplanation(getCellExplanation(column, row));
+				broadcastFocusInCell(column, row);
+			}
+		}
+		else if ((!(matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) && !singleTableCellSelected())) {
+			window.setExplanation(getCellExplanation(column, row));
+			broadcastFocusInCell(column, row);
+		}
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellEnter(column, row);
+	}
+
+	/* ............................................................................................................... */
+	public void columnNameTouched(int column, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (window.getCurrentTool() == window.arrowTool || window.getCurrentTool() == window.ibeamTool || window.getCurrentTool().getAllowAnnotate()) {
+			cellAnnotated.setCell(column, -1);
+			window.setAnnotation(cellAnnotated);
+
+		}
+		else
+			window.setAnnotation("", null);
+
+		if (window.getCurrentTool() == window.arrowTool) {
+			if (clickCount > 1 && window.ibeamTool != null) {
+				window.setCurrentTool(window.ibeamTool);
+				window.getPalette().setCurrentTool(window.ibeamTool);
+				((TableTool) window.getCurrentTool()).cellTouched(column, -1, regionInCellH, regionInCellV, modifiers);
+			}
+			else
+				super.columnNameTouched(column, regionInCellH, regionInCellV, modifiers, clickCount);
+		}
+		else {
+			((TableTool) window.getCurrentTool()).cellTouched(column, -1, regionInCellH, regionInCellV, modifiers);
+		}
+		broadcastFocusInCell(column, -1);
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(column, -1);
+	}
+
+	/* ............................................................................................................... */
+	public void subRowTouched(int subRow, int column, int regionInCellH, int regionInCellV, int x, int y, int modifiers) {
+		if (!columnLegal(column))
+			return;
+		if (column >= 0) {
+			DataColumnNamesAssistant assistant = window.getDataColumnNamesAssistant(subRow);
+			if (assistant != null)
+				if (((TableTool) window.getCurrentTool()).getSpecialToolForColumnNamesInfoStrips())
+					((TableTool) window.getCurrentTool()).cellTouched(column, subRow, regionInCellH, regionInCellV, modifiers);
+				else
+					assistant.showPopUp(columnNames, x + 5, y + 5);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void columnTouched(boolean isArrowEquivalent, int column, int regionInCellH, int regionInCellV, int modifiers) {
+		if (((TableTool) window.getCurrentTool()).useTableTouchRules() || isArrowEquivalent) {
+			super.columnTouched(isArrowEquivalent, column, regionInCellH, regionInCellV, modifiers);
+		}
+		else {
+			((TableTool) window.getCurrentTool()).cellTouched(column, -1, regionInCellH, regionInCellV, modifiers);
+		}
+		if (window.matrixInfoPanel != null && window.infoPanelOn.getValue())
+			window.matrixInfoPanel.cellTouch(column, -1);
+	}
+
+	/* ............................................................................................................... */
+	public void moveOneColumn(int column, int after) {
+		
+		int width = getColumnWidth(column);
+		if (column < after) {
+			for (int i = column; i < after; i++) {
+				setColumnWidth(i, getColumnWidth(i + 1));
+				if (isColumnSelected(i + 1))
+					selectColumn(i);
+				else
+					deselectColumn(i);
+			}
+			setColumnWidth(after, width);
+		}
+		else if (column > after) {
+			for (int i = column; i > after + 1; i--)
+				setColumnWidth(i, getColumnWidth(i - 1));
+			setColumnWidth(after + 1, width);
+		}
+
+		data.moveParts(column, 1, after);// TODO: not correct! need to adjust and see what new "after" is
+		data.moveInLinked(column, 1, after, false);
+
+	}
+
+	/* ............................................................................................................... */
+	public void moveColumns(int starting, int num, int justAfter) {
+		UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED, data);
+		undoInstructions.recordPreviousOrder(data);
+		UndoReference undoReference = new UndoReference(undoInstructions, editorModule);
+		// todo: check for illegal move
+		if (justAfter < starting) { // moving columns left, closer to zero
+			for (int i = starting; i < starting + num - 1; i++)
+				moveOneColumn(i, justAfter++);// after each move, starting is now one column on
+		}
+		else {// moving columns right
+			for (int i = 0; i < num; i++)
+				moveOneColumn(starting, justAfter); // after each move, starting is now column moved up, and justafter has moved up
+		}
+
+		synchronizeColumnSelection(data);
+		data.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+		data.notifyInLinked(new Notification(MesquiteListener.PARTS_MOVED));
+
+		editorModule.getModuleWindow().contentsChanged();
+	}
+
+	/* ............................................................................................................... */
+	public void moveOneRow(int row, int after) {
+		taxa.moveParts(row, 1, after);
+	}
+
+	/* ............................................................................................................ */
+	/**
+	 * Called if row was dragged and dropped. (after = -1 if dropped above first row; -2 if below last.)
+	 */
+	public void selectedRowsDropped(int after) {
+		if (after < -1)
+			return;
+		Bits sel = getRowsSelected();
+		if (after > getNumRows())
+			after = getNumRows();
+		if (sel.numBitsOn() == 1 && sel.firstBitOn() == after) {
+			return;
+		}
+		UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED, taxa);
+		undoInstructions.recordPreviousOrder(taxa);
+		UndoReference undoReference = new UndoReference(undoInstructions, editorModule);
+		int i = 0;
+		while (i < getNumRows()) {
+			if (sel.isBitOn(i)) {
+				deselectRow(i);
+				sel.clearBit(i);
+				moveOneRow(i, after);
+				sel.moveParts(i, 1, after);
+				if (i > after)
+					after++;
+				i = 0;
+			}
+			else
+				i++;
+		}
+		synchronizeRowSelection(data);
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+
+		editorModule.getModuleWindow().contentsChanged();
+	}
+
+	/* ............................................................................................................... */
+	public void selectedColumnsDropped(int after) {
+		if (after < -1)
+			return;
+		if (after > getNumColumns())
+			after = getNumColumns();
+		int i = 0;
+		Bits sel = getColumnsSelected();
+		if (sel.numBitsOn() == 1 && sel.firstBitOn() == after) {
+			return;
+		}
+		boolean asked = false;
+		long[] fullChecksumBefore = data.getIDOrderedFullChecksum();
+		UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED, data);
+		undoInstructions.recordPreviousOrder(data);
+		UndoReference undoReference = new UndoReference(undoInstructions, editorModule);
+		while (i < getNumColumns()) {
+			if (sel.isBitOn(i)) {
+				if (!asked && data.isMolecularSequence() && i != after) {
+					if (!AlertDialog.query(window, "Move?", "These are molecular sequences.  Are you sure you want to move the sites to a different location?", "Move", "Cancel"))
+						return;
+					asked = true;
+				}
+				deselectColumn(i);
+				sel.clearBit(i);
+				moveOneColumn(i, after);
+				sel.moveParts(i, 1, after);
+				if (i > after)
+					after++;
+				i = 0;
+			}
+			else
+				i++;
+		}
+		long[] fullChecksumAfter = data.getIDOrderedFullChecksum();
+		data.compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "character moving");
+
+		synchronizeColumnSelection(data);
+		data.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+		data.notifyInLinked(new Notification(MesquiteListener.PARTS_MOVED));
+
+		editorModule.getModuleWindow().contentsChanged();
+	}
+
+	/* ............................................................................................................... */
+	boolean doAutosize = false;
+
+	boolean suppressAutosize = false;
+
+	/* ................................................................................................................. */
+	protected void clearIt(boolean cut) {
+		notifySuppressed = true;
+		boolean namesChanged = false;
+		boolean changed = false;
+		CharacterState cs = data.makeCharacterState(); // so as to get the default state
+		UndoInstructions undoInstructions;
+		if (anyCellSelected())
+			undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+		else
+			undoInstructions = new UndoInstructions(UndoInstructions.ALLCHARACTERNAMES, data, data);
+
+		UndoReference undoReference = null;
+		if (undoInstructions != null)
+			undoReference = new UndoReference(undoInstructions, editorModule);
+
+		for (int i = 0; i < numColumnsTotal; i++) {
+			if (isColumnNameSelected(i) || isColumnSelected(i)) {
+				returnedColumnNameText(i, "");
+				namesChanged = true;
+			}
+		}
+		for (int j = 0; j < numRowsTotal; j++) {
+			/*
+			 * if (isRowNameSelected(j) || isRowSelected(j)) { returnedRowNameText(j,""); }
+			 */
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+					data.setState(i, j, cs);
+					// returnedMatrixText(i,j,"?");
+					changed = true;
+				}
+			}
+		}
+		if (cut) {
+			deleteSelected();
+		}
+		notifySuppressed = false;
+		if (undoInstructions != null) {
+			undoInstructions.setNewData(data);
+			if (undoReference != null) {
+				undoReference.setUndoer(undoInstructions);
+			}
+		}
+		if (changed)
+			data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, null, undoReference));
+		else if (namesChanged)
+			data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED, null, undoReference));
+	}
+
+	private void deleteSelected() {
+		if (data != null) {
+			if (anyColumnSelected()) {
+				if (!MesquiteThread.isScripting() && !AlertDialog.query(window, "Delete characters?", "The data for the selected characters have been cleared.  Do you also want to delete the selected characters?", "Yes", "No"))
+					return;
+				Vector blocks = new Vector();
+				while (anyColumnSelected()) {
+					int lastOfBlock = lastColumnSelected();
+					int firstOfBlock = startOfLastColumnBlockSelected();
+					if (lastOfBlock >= 0) {
+						for (int i = firstOfBlock; i <= lastOfBlock; i++)
+							deselectColumn(i);
+						data.deleteParts(firstOfBlock, lastOfBlock - firstOfBlock + 1);
+						data.deleteInLinked(firstOfBlock, lastOfBlock - firstOfBlock + 1, false);
+						blocks.addElement(new int[] { firstOfBlock, lastOfBlock - firstOfBlock + 1 }); // do as series of contiguous blocks
+					}
+				}
+
+				if (blocks.size() == 1) {
+					data.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED, (int[]) blocks.elementAt(0))); // do as series of contiguous blocks
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_DELETED, (int[]) blocks.elementAt(0))); // do as series of contiguous blocks
+				}
+				else {
+					data.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED)); // do as series of contiguous blocks
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_DELETED)); // do as series of contiguous blocks
+				}
+			}
+			if (anyRowSelected()) {
+				Bits rows = getRowsSelected();
+				if (rows.numBitsOn() == data.getTaxa().getNumTaxa()) {
+					window.ownerModule.discreetAlert("You cannot delete all of the taxa; the data will be cleared but the taxa will remain.");
+					return;
+				}
+				if (data.getTaxa().isEditInhibited()){
+					window.ownerModule.discreetAlert("You cannot delete taxa; the taxa block is locked.");
+					return;
+				}
+				if (!MesquiteThread.isScripting() && !AlertDialog.query(window, "Delete taxa?", "The data for the selected taxa have been cleared.  Do you also want to delete the selected taxa?", "Yes", "No"))
+					return;
+
+				for (int i = getNumRows() - 1; i >= 0; i--) {
+					if (rows.isBitOn(i)) {
+						data.getTaxa().deleteTaxa(i, 1, false);
+					}
+				}
+				Notification nn;
+
+				data.getTaxa().notifyListeners(this, nn = new Notification(MesquiteListener.PARTS_DELETED));// do as series of contiguous blocks
+				data.notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED).setNotificationNumber(nn.getNotificationNumber()));// do as series of contiguous blocks
+			}
+		}
+	}
+
+	boolean turnOffWarnings = false;
+
+	/* ............................................................................................................... */
+	public void returnedMatrixText(int column, int row, String s) { // TODO: SHOULD CHECK FOR ERRORS
+		if (window == null || window.ownerModule == null || window.ownerModule.isDoomed() || StringUtil.blank(s))
+			return;
+
+		CharacterState csBefore = data.getCharacterState(null, column, row);
+		parser.setString(s);
+		MesquiteString result = new MesquiteString("");
+		int response = data.setState(column, row, parser, true, result); // receive errors?
+		if (response == CharacterData.OK) {
+			CharacterState csAfter = data.getCharacterState(null, column, row);
+			if (csBefore != null && !csBefore.equals(csAfter) && !notifySuppressed) {
+				int[] subcodes = new int[] { MesquiteListener.SINGLE_CELL };
+				if (csBefore.isInapplicable() == csAfter.isInapplicable())
+					subcodes = new int[] { MesquiteListener.SINGLE_CELL, MesquiteListener.CELL_SUBSTITUTION };
+				UndoInstructions undoInstructions = window.setUndoInstructions(UndoInstructions.SINGLEDATACELL, column, row, csBefore, csAfter);
+				Notification notification = new Notification(MesquiteListener.DATA_CHANGED, new int[] { column, row }, new UndoReference(undoInstructions, window.ownerModule));
+				notification.setSubcodes(subcodes);
+				data.notifyListeners(this, notification);
+				doAutosize = true;
+			}
+		}
+		else if (!result.isBlank()) {
+			String ws = "Illegal entry for character " + (column + 1) + " in taxon " + (row + 1) + ": " + result.toString();
+			if (turnOffWarnings || MesquiteThread.isScripting())
+				window.ownerModule.logln(ws);
+			else
+				turnOffWarnings = !AlertDialog.query(window, "Illegal character state", ws, "OK", "Don't warn again");
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void returnedRowNameText(int row, String s) {
+		if (data == null || taxa == null || window == null)
+			return;
+		String oldTaxonName = taxa.getTaxonName(row);
+		if (s != null && !s.equals(oldTaxonName)) {
+			String warning = taxa.checkNameLegality(row, s);
+			if (warning == null) {
+				taxa.setTaxonName(row, s);
+				taxNC = true; // for pasting, to discover if taxon names were changed (see pasteIt)
+				window.setUndoer(window.setUndoInstructions(UndoInstructions.SINGLETAXONNAME, -1, row, new MesquiteString(oldTaxonName), new MesquiteString(s)));
+			}
+			else if (window.ownerModule != null){
+				boolean giveWarning = BasicDataWindowMaker.getWarnAgainAboutTaxonNameDuplication();
+				if (giveWarning)
+					if (MesquiteThread.isScripting())
+						window.ownerModule.logln(warning);
+					else {
+						giveWarning = AlertDialog.query(window, "Duplicate taxon name", warning, "OK", "Don't warn again");
+						BasicDataWindowMaker.setWarnAgainAboutTaxonNameDuplication(giveWarning);
+					}
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void returnedColumnNameText(int column, String s) {
+		if (data == null || taxa == null || window == null)
+			return;
+		String oldCharacterName = data.getCharacterName(column);
+		if (s != null && !s.equals(oldCharacterName)) {
+			String warning = data.checkNameLegality(column, s);
+			if (warning == null) {
+				data.setCharacterName(column, s);
+				window.setUndoer(window.setUndoInstructions(UndoInstructions.SINGLECHARACTERNAME, column, -1, new MesquiteString(oldCharacterName), new MesquiteString(s)));
+			}
+			else
+				window.ownerModule.discreetAlert(warning);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public int getMinColumnWidth() {
+		return 3;
+	}
+
+	public void repaintAll() {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		displayModifications = checkDisplayModifications();
+		if (data != null) {
+			String s = data.checkIntegrity();
+			if (s != null)
+				MesquiteTrunk.mesquiteTrunk.alert(s + " (" + data + ")");
+		}
+		MesquiteWindow.uncheckDoomed(this);
+		super.repaintAll();
+	}
+
+	/* ............................................................................................................... */
+	public int getNarrowDefaultColumnWidth() {
+		return data.getNarrowDefaultColumnWidth();
+	}
+
+	/* ............................................................................................................... */
+	public int getNarrowDefaultColumnWidth(Graphics g) {
+		FontMetrics fm = g.getFontMetrics();
+		int width = fm.stringWidth("G");
+		return width + 2;
+	}
+
+	/* ............................................................................................................... */
+	public int getDefaultColumnWidth(Graphics g) {
+		FontMetrics fm = g.getFontMetrics();
+		int width = fm.stringWidth("G");
+		return width + 2 + MesquiteModule.textEdgeCompensationHeight;
+	}
+
+	/* ............................................................................................................... */
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		displayModifications = checkDisplayModifications();
+		Font gF = g.getFont();
+		boolean resized = false;
+		if (oldFont == null || !gF.equals(oldFont)) {
+			if ((data.pleaseAutoSizeColumns()) && !showBirdsEyeView.getValue() && allowAutosize.getValue()) // TODO:
+				resized = autoSizeColumns(g);
+			else {
+				if (showBirdsEyeView.getValue())
+					setColumnWidthsUniform(birdsEyeWidth);
+				else if (tight.getValue())
+					setColumnWidthsUniform(getNarrowDefaultColumnWidth(g));
+				else if (!data.pleaseAutoSizeColumns())
+					setColumnWidthsUniform(getDefaultColumnWidth(g));
+
+				autoSizeRows(g);
+			}
+			oldFont = g.getFont();
+			boldFont = new Font(oldFont.getName(), Font.BOLD, oldFont.getSize());
+		}
+		else if (doAutosize && !suppressAutosize && allowAutosize.getValue()) {
+			doAutosize = false;
+			resized = autoSizeColumns(g);
+		}
+		else {
+			if (showBirdsEyeView.getValue())
+				setColumnWidthsUniform(birdsEyeWidth);
+			else if (tight.getValue())
+				setColumnWidthsUniform(getNarrowDefaultColumnWidth(g));
+			else if (!data.pleaseAutoSizeColumns())
+				setColumnWidthsUniform(getDefaultColumnWidth(g));
+			autoSizeRows(g);
+		}
+
+		if (resized) {
+			MesquiteWindow.uncheckDoomed(this);
+			resetComponentSizes();
+			repaintAll();
+		}
+		else {
+			super.paint(g);
+			MesquiteWindow.uncheckDoomed(this);
+		}
+	}
+}
+
+/* =========================================== */
+/* =========================================== */
+
+class BasicMatrixStatisticsPanel extends MatrixInfoExtraPanel {
+	StringInABox statsBox;
+
+	String matrixStats = null;
+
+	int neededHeight = 20;
+
+	public BasicMatrixStatisticsPanel(ClosablePanelContainer container) {
+		super(container, "Basic Matrix Stats");
+		statsBox = new StringInABox("", null, 50);
+		setOpen(true);
+	}
+
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table) {
+		super.setMatrixAndTable(data, table);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+
+	public void setCell(int ic, int it) {
+		super.setCell(ic, it);
+		repaint();
+	}
+
+	void adjustMessage() {
+		if (data == null)
+			matrixStats = "no matrix";
+		else {
+			matrixStats = "Characters: " + data.getNumChars();
+		}
+		/*
+		 * int countCell = 0; int countTaxa = 0; int countChar = 0; for (int ic = 0; ic< data.getNumChars(); ic++){ if (!StringUtil.blank(data.getAnnotation(ic))) countChar++; for (int it = 0; it< data.getNumTaxa(); it++){ if (!StringUtil.blank(data.getAnnotation(ic, it))) countCell++; } } for (int it = 0; it< data.getNumTaxa(); it++) if (!StringUtil.blank(data.getTaxa().getAnnotation(it))) countTaxa++;
+		 */
+	}
+
+	public int getRequestedHeight(int width) {
+		if (!isOpen())
+			return MINHEIGHT;
+		statsBox.setFont(getFont());
+		statsBox.setString(matrixStats);
+		statsBox.setWidth(width - 4);
+		neededHeight = statsBox.getHeight();
+		return neededHeight + MINHEIGHT;
+	}
+
+	public void paint(Graphics g) {
+		super.paint(g);
+		// g.drawString("hello", 8, MINHEIGHT+20);
+		statsBox.setWidth(getBounds().width - 4);
+		statsBox.setFont(g.getFont());
+		statsBox.setString(matrixStats);
+		statsBox.draw(g, 4, MINHEIGHT);
+	}
+}
+
+/* =========================================== */
+class FootnotePanel extends MatrixInfoExtraPanel {
+	String message = null;
+
+	NoteField infoArea;
+
+	public FootnotePanel(ClosablePanelContainer container) {
+		super(container, "Footnote");
+		infoArea = new NoteField(this);
+		currentHeight = 40 + MINHEIGHT;
+		setLayout(null);
+		add(infoArea);
+		resetLocs();
+		setOpen(true);
+	}
+
+	public boolean userExpandable() {
+		return true;
+	}
+
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table) {
+		super.setMatrixAndTable(data, table);
+		container.requestHeightChange(this);
+		repaint();
+	}
+
+	public void setCell(int ic, int it) {
+		if (!isVisible())
+			return;
+		super.setCell(ic, it);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+
+	private void adjustMessage() {
+		if (data == null) {
+			setTitle("Footnote (nothing selected)");
+			infoArea.setText("", ic, it);
+			infoArea.setEditable(false);
+			infoArea.setBackground(ColorDistribution.veryLightGray);
+		}
+		else if (it < 0 && ic < 0) {
+			setTitle("Footnote (nothing selected)");
+			infoArea.setText("", ic, it);
+			infoArea.setEditable(false);
+			infoArea.setBackground(ColorDistribution.veryLightGray);
+		}
+		else {
+			infoArea.setEditable(true);
+			infoArea.setBackground(Color.white);
+			message = "";
+			if (ic < 0) {
+				setTitle("Footnote (taxon: " + data.getTaxa().getTaxonName(it) + ")");
+				if (data.getTaxa() == null)
+					infoArea.setText("", ic, it);
+				else
+					infoArea.setText(data.getTaxa().getAnnotation(it), ic, it);
+			}
+			else if (it < 0) {
+				if (data.characterHasName(ic))
+					setTitle("Footnote (character: " + data.getCharacterName(ic) + ")");
+				else
+					setTitle("Footnote (character " + (ic + 1) + ")");
+				infoArea.setText(data.getAnnotation(ic), ic, it);
+			}
+			else {
+				setTitle("Footnote (character " + (ic + 1) + ", taxon " + data.getTaxa().getTaxonName(it) + ")");
+				infoArea.setText(data.getAnnotation(ic, it), ic, it);
+			}
+		}
+	}
+
+	public void enterText(NoteField n, String text, int rIC, int rIT, boolean warn) {
+		if (data == null)
+			return;
+		else if (it < 0 && ic < 0) {
+			if (warn)
+				n.setText("A taxon, character or cell must be touched or selected first before editing a footnote");
+			return;
+		}
+		else {
+			if (rIC != ic || rIT != it) {
+				MesquiteMessage.warnProgrammer("rIC/ic or rIT/it mismatch in footnotespanel");
+				return;
+			}
+			if (ic < 0) {
+				data.getTaxa().setAnnotation(it, text);
+				// data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+			}
+			else if (it < 0) {
+				data.setAnnotation(ic, text);
+				// data.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+			}
+			else {
+				data.setAnnotation(ic, it, text);
+				// data.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+			}
+
+		}
+		((MatrixTable) table).refreshAnnotation();
+
+	}
+
+	public void setOpen(boolean open) {
+		infoArea.setVisible(open);
+		resetLocs();
+		super.setOpen(open);
+	}
+
+	void resetLocs() {
+		infoArea.setBounds(2, MINHEIGHT + 4, getWidth() - 4, currentHeight - MINHEIGHT - 4);
+	}
+
+	public void setSize(int w, int h) {
+		super.setSize(w, h);
+		resetLocs();
+	}
+
+	public void setBounds(int x, int y, int w, int h) {
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+
+	public void cellEnter(int ic, int it) {
+		// if a single column or cells within a single column are selected, then cut out
+		if (table.singleTableCellSelected() || table.editingAnything())
+			return;
+		super.cellEnter(ic, it);
+	}
+
+	public void cellExit(int ic, int it) {
+		if (table.singleTableCellSelected() || table.editingAnything())
+			return;
+		super.cellExit(ic, it);
+
+	}
+
+}
+
+class NoteField extends TextArea implements FocusListener {
+	FootnotePanel panel;
+
+	boolean somethingTyped;
+
+	int ic = -1;
+
+	int it = -1;
+
+	public NoteField(FootnotePanel panel) {
+		super("", 4, 40, TextArea.SCROLLBARS_NONE);
+		this.panel = panel;
+		setText("");
+		addKeyListener(new KListener(this));
+		addFocusListener(this);
+	}
+
+	public void setText(String s, int ic, int it) {
+		setText(s);
+		this.ic = ic;
+		this.it = it;
+	}
+
+	public void focusGained(FocusEvent e) {
+	}
+
+	public void focusLost(FocusEvent e) {
+
+		if (somethingTyped)
+			panel.enterText(this, getText(), ic, it, false);
+		somethingTyped = false;
+	}
+
+	class KListener extends KeyAdapter {
+		NoteField nf = null;
+
+		public KListener(NoteField nf) {
+			super();
+			this.nf = nf;
+		}
+
+		public void keyPressed(KeyEvent e) {
+			// Event queue
+			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+				if (somethingTyped) {
+					String s = getText();
+					panel.enterText(nf, s, ic, it, true);
+					somethingTyped = false;
+					e.consume();
+					setSelectionStart(s.length());
+					setSelectionEnd(s.length());
+				}
+			}
+			else {
+				somethingTyped = true;
+			}
+
+		}
+	}
+
+}
+
+/* =========================================== */
+class CellInfoPanel extends MatrixInfoExtraPanel {
+	StringInABox statsBox;
+
+	String message = null;
+
+	int neededHeight = 20;
+
+	String attachmentsMessage = "";
+
+	Image query;
+
+	public CellInfoPanel(ClosablePanelContainer container) {
+		super(container, "Cell Info");
+		query = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "queryGray.gif");
+		statsBox = new StringInABox("", null, 50);
+		setOpen(true);
+	}
+
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table) {
+		super.setMatrixAndTable(data, table);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+
+	public void setCell(int ic, int it) {
+		if (!isVisible())
+			return;
+		super.setCell(ic, it);
+		try {
+			adjustMessage();
+			container.requestHeightChange(this);
+			repaint();
+		} catch (Exception e) {
+		}
+	}
+
+	private void adjustMessage() {
+
+		attachmentsMessage = "";
+		if (data == null)
+			message = "no matrix";
+		else if (it < 0 && ic < 0)
+			message = " \n \n";
+		else {
+			boolean hasAnnot = table.isAttachedNoteAvailable(ic, it);
+			if (it < 0) {
+				message = "Character ";
+				if (data.characterHasName(ic))
+					message += data.getCharacterName(ic) + " (" + (ic + 1) + ")";
+				else
+					message += (ic + 1);
+				message += "\n ";
+				if (hasAnnot)
+					message += "NOTE: Character has annotations\n";
+				// character info
+				if (ic < data.getNumChars()) {
+					for (int i = 0; i < data.getNumberAssociatedDoubles(); i++) {
+						DoubleArray d = data.getAssociatedDoubles(i);
+						NameReference nr = d.getNameReference();
+						attachmentsMessage += nr.getValue();
+						attachmentsMessage += ": " + MesquiteDouble.toString(d.getValue(ic));
+						attachmentsMessage += "\n";
+					}
+					for (int i = 0; i < data.getNumberAssociatedLongs(); i++) {
+						LongArray d = data.getAssociatedLongs(i);
+						NameReference nr = d.getNameReference();
+						attachmentsMessage += nr.getValue();
+						attachmentsMessage += ": " + MesquiteLong.toString(d.getValue(ic));
+						attachmentsMessage += "\n";
+					}
+				}
+			}
+			else if (ic < 0) {
+				// taxon info
+				Taxa taxa = data.getTaxa();
+				message = " \nTaxon: ";
+				message += taxa.getTaxonName(it) + " (" + (it + 1) + ")\n";
+				if (hasAnnot)
+					message += "NOTE: Taxon has annotations\n";
+				if (it < taxa.getNumTaxa()) {
+					for (int i = 0; i < taxa.getNumberAssociatedDoubles(); i++) {
+						DoubleArray d = taxa.getAssociatedDoubles(i);
+						NameReference nr = d.getNameReference();
+						attachmentsMessage += nr.getValue();
+						attachmentsMessage += ": " + MesquiteDouble.toString(d.getValue(ic));
+						attachmentsMessage += "\n";
+					}
+					for (int i = 0; i < taxa.getNumberAssociatedLongs(); i++) {
+						LongArray d = taxa.getAssociatedLongs(i);
+						NameReference nr = d.getNameReference();
+						attachmentsMessage += nr.getValue();
+						attachmentsMessage += ": " + MesquiteLong.toString(d.getValue(ic));
+						attachmentsMessage += "\n";
+					}
+				}
+				Associable tInfo = data.getTaxaInfo(false);
+				if (tInfo != null) {
+					attachmentsMessage += tInfo.toString(it) + "\n";
+				}
+			}
+			else {
+				Taxa taxa = data.getTaxa();
+				message = "Character ";
+				if (data.characterHasName(ic))
+					message += data.getCharacterName(ic) + " (" + (ic + 1) + ")";
+				else
+					message += (ic + 1);
+				message += "\nTaxon: ";
+				message += taxa.getTaxonName(it) + " (" + (it + 1) + ")\n";
+				if (hasAnnot)
+					message += "NOTE: Cell has annotations\n";
+			}
+			if (!StringUtil.blank(attachmentsMessage))
+				message += "\n" + attachmentsMessage;
+		}
+	}
+
+	public int getRequestedHeight(int width) {
+		if (!isOpen())
+			return MINHEIGHT;
+		statsBox.setFont(getFont());
+		statsBox.setString(message);
+		statsBox.setWidth(width - 4);
+		neededHeight = statsBox.getHeight();
+		return neededHeight + MINHEIGHT;
+	}
+
+	public void paint(Graphics g) {
+		super.paint(g);
+		g.drawImage(query, getWidth() - 20, 4, this);
+		statsBox.setWidth(getBounds().width - 4);
+		statsBox.setFont(g.getFont());
+		if (!StringUtil.blank(message)) {
+			statsBox.setString(message);
+			statsBox.draw(g, 4, MINHEIGHT);
+		}
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (y < MINHEIGHT && (x > getWidth() - 20)) {
+			MesquiteTrunk.mesquiteTrunk.alert("Attachments:  Attachments to the matrix or its cells are pieces of information like annotations, assigned colors, and so on. Move cursor over cells to see information attached there."); // query button hit
+		}
+		else
+			super.mouseUp(modifiers, x, y, tool);
+	}
+}
+
+/* =========================================== */
+
+/* ======================================================================== */
+class MatrixInfoPanel extends MousePanel implements ClosablePanelContainer {
+	static final int width = 200;
+
+	// static final int height = 66;
+	String title = null;
+
+	String explanation = null;
+
+	StringInABox titleBox, explanationBox;
+
+	int[] heights;
+
+	BasicDataWindow w;
+
+	Image goaway;
+
+	CharacterData data;
+
+	Vector extras = new Vector();
+
+	Font titleFont;
+
+	String matrixName, sourceName;
+
+	Image add = null;
+
+	BasicMatrixStatisticsPanel btsp;
+
+	CellInfoPanel ap;
+
+	FootnotePanel fp;
+
+	public MatrixInfoPanel(BasicDataWindow w) {
+		super();
+		this.w = w;
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addGray.gif");
+		setLayout(null);
+		addExtraPanel(btsp = new BasicMatrixStatisticsPanel(this));
+		setBackground(ColorDistribution.veryLightGray);
+		setFont(new Font("SansSerif", Font.PLAIN, 10));
+		titleFont = new Font("SansSerif", Font.BOLD, 10);
+		titleBox = new StringInABox("", null, width);
+		explanationBox = new StringInABox("", null, width);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "minimizeTransparent.gif");
+	}
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("btspOpen " + btsp.isOpen());
+		temp.addLine("apOpen " + ap.isOpen());
+		temp.addLine("fpOpen " + fp.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m) {
+		if (m == null)
+			return;
+		// zap values panel line
+
+	}
+
+	public void startCellInfo() {
+		addExtraPanel(fp = new FootnotePanel(this));
+		addExtraPanel(ap = new CellInfoPanel(this));
+	}
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets attachment panel open", null, commandName, "apOpen")) {
+			if (ap != null)
+				ap.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else if (checker.compare(this.getClass(), "Sets the basic statistics panel open", null, commandName, "btspOpen")) {
+			btsp.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else if (checker.compare(this.getClass(), "Sets the footnotes panel open", null, commandName, "fpOpen")) {
+			fp.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel) {
+		int i = extras.indexOf(panel);
+		if (i > 0)
+			return (ClosablePanel) extras.elementAt(i - 1);
+		return null;
+	}
+
+	void addExtraPanel(MatrixInfoExtraPanel p) {
+		extras.addElement(p);
+		add(p);
+		heights = new int[extras.size()];
+		resetSizes(getWidth(), getHeight());
+		p.setVisible(true);
+		p.setMatrixAndTable(data, w.table);
+	}
+
+	void setMatrix(CharacterData data) {
+		this.data = data;
+		title = "Matrix: " + data.getName();
+		for (int i = 0; i < extras.size(); i++) {
+			MatrixInfoExtraPanel panel = ((MatrixInfoExtraPanel) extras.elementAt(i));
+			panel.setMatrixAndTable(data, w.table);
+		}
+	}
+
+	public void cellEnter(int ic, int it) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		for (int i = 0; i < extras.size(); i++) {
+			MatrixInfoExtraPanel panel = ((MatrixInfoExtraPanel) extras.elementAt(i));
+			panel.cellEnter(ic, it);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void cellExit(int ic, int it) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		for (int i = 0; i < extras.size(); i++) {
+			MatrixInfoExtraPanel panel = ((MatrixInfoExtraPanel) extras.elementAt(i));
+			panel.cellExit(ic, it);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void cellTouch(int ic, int it) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		for (int i = 0; i < extras.size(); i++) {
+			MatrixInfoExtraPanel panel = ((MatrixInfoExtraPanel) extras.elementAt(i));
+			panel.cellTouch(ic, it);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void requestHeightChange(ClosablePanel panel) {
+		int i = extras.indexOf(panel);
+		if (i >= 0 && heights[i] == panel.getRequestedHeight(getWidth()))
+			return;
+		resetSizes(getWidth(), getHeight());
+		repaint();
+	}
+
+	public void paint(Graphics g) {
+		Color c = g.getColor();
+
+		int vertical = 2;
+		if (title != null) {
+			g.setColor(ColorTheme.getInterfaceElement());
+			g.fillRect(0, 0, getBounds().width, titleBox.getHeight() + 8);
+			g.setColor(ColorTheme.getInterfaceTextContrast());
+			titleBox.draw(g, 20, vertical);
+			g.setColor(Color.black);
+			vertical += 8 + titleBox.getHeight();
+		}
+
+		g.drawImage(goaway, 2, 2, this);
+		g.drawLine(0, vertical - 4, getBounds().width, vertical - 4);
+		if (explanation != null) {
+			g.setColor(Color.white);
+			g.fillRect(0, vertical, getBounds().width, 8 + explanationBox.getHeight());
+			g.setColor(Color.black);
+			explanationBox.draw(g, 4, vertical);
+			vertical += 8 + explanationBox.getHeight();
+		}
+		g.setColor(Color.darkGray);
+		g.fillRect(0, totalVertical, getBounds().width, 2);
+
+		// WHEN CALCULATIONS CAN BE ADDED
+		// g.drawImage(add, 2, totalVertical+4, this);
+		g.setColor(c);
+
+	}
+
+	int totalVertical = 0;
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (x < 30 && y > totalVertical + 4 && y < totalVertical + 20) {
+			// WHEN CALCULATIONS CAN BE ADDED
+			// MesquiteTrunk.mesquiteTrunk.alert("Sorry, doesn't do anything yet");
+		}
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x < 16 && y < 16)
+			w.matrixInfoPanelGoAway();
+
+	}
+
+	void resetSizes(int w, int h) {
+		int vertical = 2;
+		if (title != null) {
+			titleBox.setWidth(w - 20);
+			titleBox.setFont(titleFont);
+			titleBox.setString(title);
+			vertical += 8 + titleBox.getHeight();
+		}
+		if (explanation != null) {
+			explanationBox.setWidth(w - 4);
+			explanationBox.setFont(getFont());
+			explanationBox.setString(explanation);
+			vertical += 8 + explanationBox.getHeight();
+		}
+		for (int i = 0; i < extras.size(); i++) {
+			ClosablePanel panel = ((ClosablePanel) extras.elementAt(i));
+			int requestedlHeight = panel.getRequestedHeight(w);
+			heights[i] = requestedlHeight;
+			panel.setBounds(0, vertical, w, requestedlHeight);
+			vertical += requestedlHeight;
+		}
+		totalVertical = vertical;
+	}
+
+	public void setBounds(int x, int y, int w, int h) {
+		super.setBounds(x, y, w, h);
+		resetSizes(w, h);
+	}
+
+	public void setSize(int w, int h) {
+		super.setSize(w, h);
+		resetSizes(w, h);
+	}
+}
+
+/* ============================================= */
+class SequenceLedge extends MousePanel {
+	MatrixTable table;
+
+	int focusIC;
+
+	int focusIT;
+
+	int numRowsAboveBelow = 0;
+
+	public SequenceLedge() {
+	}
+
+	public void setFocus(MatrixTable table, int ic, int it) {
+		focusIC = ic;
+		focusIT = it;
+		this.table = table;
+		repaint();
+		setBackground(Color.lightGray);
+	}
+
+	public void paint(Graphics g) {
+		if (table == null || focusIT < 0 || focusIT >= table.getNumRows())
+			return;
+		g.setColor(Color.black);
+		int cellWidth = 16;
+		int centrePoint = getBounds().width / 2;
+		int defHeight = table.getRowHeight(0); // bit kudgy
+		if (defHeight < 16)
+			defHeight = 16;
+		int numRows = getBounds().height / defHeight;
+		if (numRows / 2 * 2 == numRows) // even
+			numRows--;
+		numRowsAboveBelow = numRows / 2;
+		int rowHeight = getBounds().height / (numRowsAboveBelow * 2 + 1) - 2;
+		int height = getBounds().height;
+		// int centrePoint = table.getLeftOfColumn(focusIC) - 10;
+		// g.fillRect( centrePoint-2, 0, cellWidth + 8, height);
+
+		for (int it = focusIT - numRowsAboveBelow; it <= focusIT + numRowsAboveBelow; it++) {
+			if (it >= 0 && it < table.getNumRows()) {
+				int rowTop = (it - (focusIT - numRowsAboveBelow)) * rowHeight + 3;
+				for (int ic = focusIC; ic < table.getNumColumns() && (ic - focusIC) * (cellWidth + 1) < centrePoint; ic++)
+					table.drawMatrixCell(g, (ic - focusIC) * (cellWidth + 1) + centrePoint, rowTop, cellWidth, rowHeight - 2, ic, it, false, true, false);
+
+				for (int ic = focusIC - 1; ic >= 0 && (focusIC - ic - 2) * (cellWidth + 1) < centrePoint; ic--)
+					table.drawMatrixCell(g, (ic - focusIC) * (cellWidth + 1) + centrePoint, rowTop, cellWidth, rowHeight - 2, ic, it, false, true, false);
+				table.drawMatrixCell(g, centrePoint, rowTop, cellWidth, rowHeight - 2, focusIC, it, false, true, true);
+				if (it == focusIT) {
+					g.setColor(Color.black);
+					g.drawRect(centrePoint - 1, rowTop - 1, cellWidth + 2, rowHeight);
+					g.drawRect(centrePoint, rowTop, cellWidth, rowHeight - 2);
+				}
+			}
+		}
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/BasicDataWindowMaker/birdsEye.gif b/Source/mesquite/charMatrices/BasicDataWindowMaker/birdsEye.gif
new file mode 100644
index 0000000..6a3397b
Binary files /dev/null and b/Source/mesquite/charMatrices/BasicDataWindowMaker/birdsEye.gif differ
diff --git a/Source/mesquite/charMatrices/BasicDataWindowMaker/colorWand.gif b/Source/mesquite/charMatrices/BasicDataWindowMaker/colorWand.gif
new file mode 100644
index 0000000..1cfd3aa
Binary files /dev/null and b/Source/mesquite/charMatrices/BasicDataWindowMaker/colorWand.gif differ
diff --git a/Source/mesquite/charMatrices/BooleanForCharInfoStrip/BooleanForCharInfoStrip.java b/Source/mesquite/charMatrices/BooleanForCharInfoStrip/BooleanForCharInfoStrip.java
new file mode 100644
index 0000000..1b137d2
--- /dev/null
+++ b/Source/mesquite/charMatrices/BooleanForCharInfoStrip/BooleanForCharInfoStrip.java
@@ -0,0 +1,220 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.BooleanForCharInfoStrip;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import mesquite.lib.AssociableWithSpecs;
+import mesquite.lib.CommandChecker;
+import mesquite.lib.Debugg;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.MesquiteBoolean;
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteListener;
+import mesquite.lib.MesquiteMenuItemSpec;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteString;
+import mesquite.lib.Notification;
+import mesquite.lib.Snapshot;
+import mesquite.lib.Taxa;
+import mesquite.lib.duties.*;
+
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.DataColumnNamesAssistant;
+import mesquite.lib.table.ColumnNamesPanel;
+import mesquite.lib.table.MesquiteTable;
+
+public class BooleanForCharInfoStrip extends DataColumnNamesAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	BooleanForCharacter booleanTask;
+	MesquiteMenuItemSpec closeMenuItem, toggleDirectionItem, selectMatchesItem;
+	MesquiteBoolean standardDirection = new MesquiteBoolean(true);
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BooleanForCharacter.class, getName() + " needs a method to calculate a boolean (yes/no) value for each of the characters.",
+		"You can select a value to show in an information strip of a Data Matrix Editor. ");
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition,boolean hiredByName) {
+		if (arguments !=null) {
+			booleanTask = (BooleanForCharacter)hireNamedEmployee(BooleanForCharacter.class, arguments);
+			if (booleanTask==null) {
+				return sorry("Boolean for character (for info strip) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			booleanTask = (BooleanForCharacter)hireEmployee(BooleanForCharacter.class, "Value to calculate for character (for character list)");
+			if (booleanTask==null) {
+				return sorry("Boolean for character (for info strip) can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void drawInCell(int ic, Graphics g, int x, int y, int w, int h, boolean selected) {
+		if (data == null || booleanTask==null)
+			return;
+		MesquiteBoolean result = new MesquiteBoolean();
+		MesquiteString resultString = new MesquiteString();
+		booleanTask.calculateBoolean( data,  ic,  result,  resultString);
+
+		if (booleanTask.displayTrueAsDark()==standardDirection.getValue()) {
+			if (result.getValue())
+				g.setColor(Color.gray); 
+			else {
+				g.setColor(Color.white);
+			}		
+		}
+		else if (result.getValue())
+			g.setColor(Color.white); 
+		else {
+			g.setColor(Color.gray);
+		}
+		g.fillRect(x, y, w, h);
+	}
+	
+	/** Returns string to be displayed in explanation area on mouseover of cell */
+	public String getStringForExplanation(int ic){
+		if (data == null || booleanTask==null)
+			return null;
+		MesquiteBoolean result = new MesquiteBoolean();
+		MesquiteString resultString = new MesquiteString();
+		booleanTask.calculateBoolean( data,  ic,  result,  resultString);
+
+		return booleanTask.getValueString(result.getValue());
+	}
+
+
+	/*.................................................................................................................*/
+	public void deleteRemoveMenuItem() {
+		deleteMenuItem(closeMenuItem);
+		deleteMenuItem(toggleDirectionItem);
+		deleteMenuItem(selectMatchesItem);
+	}
+	public void addRemoveMenuItem() {
+		closeMenuItem= addMenuItem(null,"Remove Info Strip", makeCommand("remove", this));
+		toggleDirectionItem= addMenuItem(null,"Flip Dark/Light", makeCommand("toggleDirection", this));
+		selectMatchesItem= addMenuItem(null,"Select Characters Satisfying Criterion", makeCommand("selectMatches", this));
+	}
+
+
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return BooleanForCharacter.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setValueTask ", booleanTask); 
+		temp.addLine("toggleDirection " + standardDirection.toOffOnString());
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	public void selectSame(boolean selectTrue) { 
+		if (data == null || booleanTask==null || table ==null)
+			return;
+		boolean selectionChange = false;
+		for (int ic=0; ic<data.getNumChars(); ic++) {
+			MesquiteBoolean result = new MesquiteBoolean();
+			MesquiteString resultString = new MesquiteString();
+			booleanTask.calculateBoolean( data,  ic,  result,  resultString);
+			
+			if (result.getValue()==selectTrue){
+				if (!table.isColumnSelected(ic))
+					selectionChange=true;
+				table.selectColumn(ic);
+			}
+		}
+		if (selectionChange)
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a boolean for a character", "[name of module]", commandName, "setValueTask")) {
+			BooleanForCharacter temp= (BooleanForCharacter)replaceEmployee(BooleanForCharacter.class, arguments, "Boolean for a character", booleanTask);
+			if (temp!=null) {
+				booleanTask = temp;
+				parametersChanged();
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the Info Strip", null, commandName, "remove")) {
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Selects characters with a value of true for this boolean", null, commandName, "selectMatches")) {
+			selectSame(true);
+		}
+		else if (checker.compare(this.getClass(), "Toggles the dark/light display", "[on, off]", commandName, "toggleDirection")) {
+			standardDirection.toggleValue(parser.getFirstToken(arguments));
+			table.getColumnNamesPanel().repaint();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public String getTitle() {
+		return "Boolean Character Info Strip";
+	}
+
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		deleteRemoveMenuItem();
+		addRemoveMenuItem();
+		this.table = table;
+		this.data = data;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false; 
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (table!=null) {
+			((ColumnNamesPanel)table.getColumnNamesPanel()).decrementInfoStrips();
+			table.resetTableSize(false);
+		}
+		super.endJob();
+	}
+
+	public String getName() {
+		return "Boolean Info Strip";
+	}
+	public String getExplanation() {
+		return "Shows an strip of boxes near the top of each a character column that shows the value of a boolean for that character in gray or white.";
+	}
+
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+
+
+}
diff --git a/Source/mesquite/charMatrices/BootstrapResample/BootstrapResample.java b/Source/mesquite/charMatrices/BootstrapResample/BootstrapResample.java
new file mode 100644
index 0000000..1eac258
--- /dev/null
+++ b/Source/mesquite/charMatrices/BootstrapResample/BootstrapResample.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.BootstrapResample;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class BootstrapResample extends RandomMatrixModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  	 	return true; 
+  	 }
+
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+
+		for (int ic = 0; ic<numChars; ic++) {
+	   		int sh = rng.randomIntBetween(0, numChars-1);
+	   		modified.transferFrom(ic, matrix.getCharacterDistribution(sh));
+ 	 	}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		return "Bootstrap Resample Matrix";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+  	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Resamples characters from a matrix for use in bootstrap methods." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/CharGroupColor/CharGroupColor.java b/Source/mesquite/charMatrices/CharGroupColor/CharGroupColor.java
new file mode 100644
index 0000000..b526715
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharGroupColor/CharGroupColor.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharGroupColor; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class CharGroupColor extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerMatrix {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.data = data;
+		taxa = data.getTaxa();
+	}
+	CharacterData data;
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Group Color";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors by Character Group.";
+	}
+
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; 
+	}
+	public ColorRecord[] getLegendColors(){
+		return null;
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if (ic>=0) {  
+			CharacterPartition part = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+			if (part!=null){
+				CharactersGroup mi = (CharactersGroup)part.getProperty(ic);
+				if (mi!=null)
+					return mi.getColor();
+			}
+			return null;
+		}
+		return null;
+	}
+	public String getCellString(int ic, int it){
+		if (ic>=0) {  
+			CharacterPartition part = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+			if (part!=null){
+				CharactersGroup mi = (CharactersGroup)part.getProperty(ic);
+				if (mi!=null)
+					return "This character belongs to the group " + mi.getName();
+			}
+		}
+		return "";
+	}
+	public String getParameters(){
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/CharMatrixCoordIndep/CharMatrixCoordIndep.java b/Source/mesquite/charMatrices/CharMatrixCoordIndep/CharMatrixCoordIndep.java
new file mode 100644
index 0000000..403b921
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharMatrixCoordIndep/CharMatrixCoordIndep.java
@@ -0,0 +1,228 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharMatrixCoordIndep;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class CharMatrixCoordIndep extends MatrixSourceCoord  implements NameHolder {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharMatrixOneSource.class, getName() + " needs a source of matrices.",
+		"You can usually request a source of matrices when the calculation starts, or later under the submenu \"Matrix Source\" or the submenu \"Source of character matrices\".");
+		e.setAlternativeEmployerLabel("Calculations making use of character matrices.");
+		e.setSuppressListing(true);
+		/*		EmployeeNeed e = registerEmployeeNeed(CharMatrixOneSource.class, getName() + " coordinates the supply of character matrices.",
+				"You can request a source of matrices when " + getName() + " starts, or later under the submenu \"Matrix Source\" or the submenu \"Source of character matrices\".");
+		e.setSuppressListing(true);*/
+		//e.setAsEntryPoint(true);
+	}
+	public EmployeeNeed findEmployeeNeed(Class dutyClass) {
+		return getEmployer().findEmployeeNeed(MatrixSourceCoord.class);
+	}
+	CharMatrixOneSource characterSourceTask;
+	MesquiteString charSourceName;
+	MesquiteCommand cstC;
+	Object hiringCondition;
+	MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		this.hiringCondition = condition;
+//		pass in arguments the ID of taxon to be used; passed also into 
+		String exp, mexp;
+		if (getExplanationByWhichHired()!=null) {
+			exp = getExplanationByWhichHired();
+			mexp = exp;
+		}
+		else {
+			exp = "Source of character matrices  (for " + getEmployer().getName() + ")";
+			mexp = "Matrix Source  (for " + getEmployer().getName() + ")";
+		}
+		MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(mesquite.charMatrices.StoredCharacters.StoredCharacters.class);
+		if (mmi != null && !mmi.isCompatible(condition, getProject(), this)) {
+			if (!MesquiteDialog.useWizards){
+				exp += "\n\nNOTE: The choice Stored Matrices does not appear because there are no appropriate matrices currently defined and stored in the data file or project.  ";
+			}
+		}
+		else {
+			if (!MesquiteThread.isScripting() && CharacterSource.useStoredAsDefault()) //if not scripting, then use stored matrices as default
+				characterSourceTask = (CharMatrixOneSource)hireNamedEmployee(CharMatrixOneSource.class, "#mesquite.charMatrices.StoredMatrices.StoredMatrices", condition);
+		}
+		if (characterSourceTask == null){
+			if (condition!=null)
+				characterSourceTask = (CharMatrixOneSource)hireCompatibleEmployee(CharMatrixOneSource.class, condition, exp);
+			else
+				characterSourceTask = (CharMatrixOneSource)hireEmployee(CharMatrixOneSource.class, exp);
+		}
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		charSourceName = new MesquiteString(characterSourceTask.getName());
+		cstC = makeCommand("setCharacterSource",  this);
+		if (!CharacterSource.closeIfMatrixDeleted.getValue())
+			characterSourceTask.setHiringCommand(cstC);  
+		if (numModulesAvailable(CharMatrixOneSource.class)>1){
+			 mss = addSubmenu(null, mexp, cstC, CharMatrixOneSource.class);
+				mss.setNameHolder(this);
+			if (condition!=null)
+				mss.setCompatibilityCheck(hiringCondition);
+			mss.setSelected(charSourceName);
+		}
+		return true;
+	}
+	public String getMyName(Object obj){
+		if (obj == mss)
+			return "Source of Matrices (" + whatIsMyPurpose() + ")";
+		return null;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		return whatIsMyPurpose(); //transfers info to employer, as ithis is coordinator
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	public Selectionable getSelectionable() {
+		if (characterSourceTask!=null)
+			return characterSourceTask.getSelectionable();
+		else
+			return null;
+	}
+	public void setEnableWeights(boolean enable){
+		if (characterSourceTask!=null)
+			characterSourceTask.setEnableWeights(enable);
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (characterSourceTask!=null)
+			return characterSourceTask.itemsHaveWeights(taxa);
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemWeight(taxa, ic);
+		return MesquiteDouble.unassigned;
+	}
+	public void prepareItemColors(Taxa taxa){
+		if (characterSourceTask!=null)
+			characterSourceTask.prepareItemColors(taxa);
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemColor(taxa, ic);
+		return null;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		characterSourceTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	/** gets the current matrix.*/
+	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		CharMatrixOneSource oldSource = characterSourceTask;
+		MCharactersDistribution matrix = characterSourceTask.getCurrentMatrix(taxa);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return matrix;
+		return characterSourceTask.getCurrentMatrix(taxa); //try again
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getCurrentMatrix(Tree tree){
+		CharMatrixOneSource oldSource = characterSourceTask;
+		MCharactersDistribution matrix = characterSourceTask.getCurrentMatrix(tree);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return matrix;
+		return characterSourceTask.getCurrentMatrix(tree); //try again
+	}
+	/*.................................................................................................................*/
+	public String getCurrentMatrixName(Taxa taxa){
+		CharMatrixOneSource oldSource = characterSourceTask;
+		String name = characterSourceTask.getMatrixName(taxa, characterSourceTask.getNumberCurrentMatrix());
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return name;
+		return characterSourceTask.getMatrixName(taxa, characterSourceTask.getNumberCurrentMatrix()); //try again
+	}
+	public boolean usesTree(){
+		if (characterSourceTask == null)
+			return false;
+		return characterSourceTask.usesTree();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCharacterSource", characterSourceTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying character matrices", "[name of module]", commandName, "setCharacterSource")) {
+			CharMatrixOneSource newCharacterSourceTask;
+			if (hiringCondition!=null)
+				newCharacterSourceTask =  (CharMatrixOneSource)replaceCompatibleEmployee(CharMatrixOneSource.class, arguments, characterSourceTask, hiringCondition);//, "Source of characters"
+			else
+				newCharacterSourceTask =  (CharMatrixOneSource)replaceEmployee(CharMatrixOneSource.class, arguments, "Source of character matrices", characterSourceTask);
+			if (newCharacterSourceTask!=null) {
+				characterSourceTask = newCharacterSourceTask;
+				if (!CharacterSource.closeIfMatrixDeleted.getValue())
+					characterSourceTask.setHiringCommand(cstC);  
+				charSourceName.setValue(characterSourceTask.getName());
+				parametersChanged(); 
+				return characterSourceTask;
+			}
+			else {
+				discreetAlert( "Unable to activate character matrix source \"" + arguments + "\"  for use by " + employer.getName());
+			}
+		}
+		else if (characterSourceTask!=null) { //todo: temporary, for snapshot conversions
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (characterSourceTask==null)
+			return null;
+		return characterSourceTask.getName() + " (" + characterSourceTask.getParameters() +")";
+	}
+	public String getNameAndParameters() {
+		return characterSourceTask.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Matrix Source (indep.)";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Coordinates the supply of matrices to other modules.  It acts independently, in that it decides what matrix to supply (e.g., by presenting an interface to choose).";
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/CharMatrixCoordObed/CharMatrixCoordObed.java b/Source/mesquite/charMatrices/CharMatrixCoordObed/CharMatrixCoordObed.java
new file mode 100644
index 0000000..04e70c3
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharMatrixCoordObed/CharMatrixCoordObed.java
@@ -0,0 +1,227 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharMatrixCoordObed;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class CharMatrixCoordObed extends MatrixSourceCoordObed implements NameHolder {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		//EmployeeNeed e = registerEmployeeNeed(CharMatrixObedSource.class, getName() + " coordinates the supply of character matrices.",
+		//		"You can request a source of matrices when " + getName() + " starts, or later under the submenu \"Matrix Source\" or the submenu \"Source of character matrices\".");
+		//e.setSuppressListing(true);
+		EmployeeNeed e = registerEmployeeNeed(CharMatrixObedSource.class, getName() + " needs a source of matrices.",
+		"You can usually request a source of matrices when the calculation starts, or later under the submenu \"Matrix Source\" or the submenu \"Source of character matrices\".");
+		e.setAlternativeEmployerLabel("Calculations making use of character matrices.");
+		e.setSuppressListing(true);
+		//e.setAsEntryPoint(true);
+	}
+	public EmployeeNeed findEmployeeNeed(Class dutyClass) {
+		return getEmployer().findEmployeeNeed(MatrixSourceCoordObed.class);
+	}
+	CharMatrixObedSource characterSourceTask;
+	MesquiteString charSourceName;
+	MesquiteCommand cstC;
+	Object hiringCondition;
+	MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		hiringCondition = condition;
+		String exp, mexp;
+		boolean acceptStoredAsDefault = true;
+		if (arguments != null){
+			Arguments args = new Arguments(new Parser(arguments), true);
+			String argStoredAsDefault = args.getParameterValue("storedAsDefault");
+			if (argStoredAsDefault != null && argStoredAsDefault.equalsIgnoreCase("false"))
+				acceptStoredAsDefault = false;
+		}
+		if (getExplanationByWhichHired()!=null) {
+			exp = getExplanationByWhichHired();
+			mexp = exp;
+		}
+		else {
+			exp = "Source of character matrices  (for " + getEmployer().getName() + ")";
+			mexp = "Matrix Source  (for " + getEmployer().getName() + ")";
+		}
+		MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(mesquite.charMatrices.StoredCharacters.StoredCharacters.class);
+		if (mmi != null && !mmi.isCompatible(condition, getProject(), this)){
+			if (!MesquiteDialog.useWizards){
+				exp += "\n\nNOTE: The choice Stored Matrices does not appear because there are no appropriate matrices currently defined and stored in the data file or project.  ";
+			}
+		}
+		else if (CharacterSource.useStoredAsDefault() && acceptStoredAsDefault)
+			characterSourceTask = (CharMatrixObedSource)hireNamedEmployee(CharMatrixObedSource.class, "#mesquite.charMatrices.StoredMatrices.StoredMatrices", condition);
+		if (characterSourceTask == null){
+			if (condition!=null)
+				characterSourceTask = (CharMatrixObedSource)hireCompatibleEmployee(CharMatrixObedSource.class, condition, exp);
+			else
+				characterSourceTask = (CharMatrixObedSource)hireEmployee(CharMatrixObedSource.class, exp);
+		}
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		charSourceName = new MesquiteString(characterSourceTask.getName());
+		cstC = makeCommand("setCharacterSource",  this);
+		characterSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(CharMatrixObedSource.class)>1){
+			mss = addSubmenu(null, mexp, cstC, CharMatrixObedSource.class);
+			mss.setNameHolder(this);
+			if (condition!=null)
+				mss.setCompatibilityCheck(hiringCondition);
+			mss.setSelected(charSourceName);
+		}
+		return true;
+	}
+	public String getMyName(Object obj){
+		if (obj == mss)
+			return "Source of Matrices (" + whatIsMyPurpose() + ")";
+		return null;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		return whatIsMyPurpose(); //transfers info to employer, as ithis is coordinator
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		characterSourceTask.initialize(taxa);
+	}
+	public Selectionable getSelectionable() {
+		if (characterSourceTask!=null)
+			return characterSourceTask.getSelectionable();
+		else
+			return null;
+	}
+	public void setEnableWeights(boolean enable){
+		if (characterSourceTask!=null)
+			characterSourceTask.setEnableWeights(enable);
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (characterSourceTask!=null)
+			return characterSourceTask.itemsHaveWeights(taxa);
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemWeight(taxa, ic);
+		return MesquiteDouble.unassigned;
+	}
+	public void prepareItemColors(Taxa taxa){
+		if (characterSourceTask!=null)
+			characterSourceTask.prepareItemColors(taxa);
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemColor(taxa, ic);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCharacterSource", characterSourceTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying character matrices", "[name of module]", commandName, "setCharacterSource")) {
+			CharMatrixObedSource newCharacterSourceTask;
+			if (hiringCondition!=null)
+				newCharacterSourceTask =  (CharMatrixObedSource)replaceCompatibleEmployee(CharMatrixObedSource.class, arguments, characterSourceTask, hiringCondition);//, "Source of characters"
+			else
+				newCharacterSourceTask =  (CharMatrixObedSource)replaceEmployee(CharMatrixObedSource.class, arguments, "Source of character matrices", characterSourceTask);
+			if (newCharacterSourceTask!=null) {
+				characterSourceTask = newCharacterSourceTask;
+				characterSourceTask.setHiringCommand(cstC);
+				charSourceName.setValue(characterSourceTask.getName());
+				parametersChanged(); 
+				return characterSourceTask;
+			}
+			else {
+				discreetAlert( "Unable to activate character matrix source \"" + arguments + "\"  for use by " + employer.getName());
+			}
+		}
+		else if (characterSourceTask!=null) { //todo: temporary, for snapshot conversions
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Taxa taxa){
+		CharMatrixObedSource oldSource = characterSourceTask;
+		int num = characterSourceTask.getNumberOfMatrices(taxa);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return num;
+		return characterSourceTask.getNumberOfMatrices(taxa); 
+	}
+	/*.................................................................................................................*/
+	public String getMatrixName(Taxa taxa, int ic) {
+		CharMatrixObedSource oldSource = characterSourceTask;
+		String name = characterSourceTask.getMatrixName(taxa, ic);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return name;
+		return characterSourceTask.getMatrixName(taxa, ic); 
+	}
+	/*.................................................................................................................*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int ic){
+		CharMatrixObedSource oldSource = characterSourceTask;
+		MCharactersDistribution matrix = characterSourceTask.getMatrix(taxa, ic);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return matrix;
+		return characterSourceTask.getMatrix(taxa, ic); 
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Matrix Source (obed.)";  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the supply of matrices to other modules.  It acts obediently, in that it does not present an interface to choose which matrix, but relies on employer to decide." ;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (characterSourceTask==null)
+			return null;
+		return characterSourceTask.getName() + " (" + characterSourceTask.getParameters() +")";
+	}
+
+	public String getNameAndParameters() {
+		return characterSourceTask.getNameAndParameters();
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/CharReferenceStrip/CharReferenceStrip.java b/Source/mesquite/charMatrices/CharReferenceStrip/CharReferenceStrip.java
new file mode 100644
index 0000000..5135867
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharReferenceStrip/CharReferenceStrip.java
@@ -0,0 +1,296 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharReferenceStrip;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class CharReferenceStrip extends DataWindowAssistantID {
+	Ledge panel;
+	MesquiteBoolean showStrip;
+	boolean shown;
+	CharacterData data = null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showStrip = new MesquiteBoolean(false);
+		shown = false;
+		addCheckMenuItem(null, "Show Character Reference Strip", makeCommand("showStrip", this), showStrip);
+		return true;
+	}
+	/** Called to alter data in all cells*/
+	public void setTableAndData(MesquiteTable table, CharacterData cData){
+		if (data != null)
+			data.removeListener(this);
+		data = cData;
+		data.addListener(this);
+		this.table = table;
+		resetLedge();
+
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (notification == null || obj != data || caller == this)
+			return;
+		resetMessage();
+
+	}
+	public void resetLedge(){
+		if (showStrip.getValue() && !shown){  //need to show
+			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = true;
+				if (panel == null)
+					panel = new Ledge(this);
+				((MesquiteWindow)f).addLedgePanel(panel, 22);
+				panel.setVisible(true);
+				panel.setMessage("", -1);
+				lastShown = -1;
+				resetMessage();
+			}
+		}
+		else if (!showStrip.getValue() && shown && panel != null){ //need to hide
+			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = false;
+				panel.setVisible(false);
+				((MesquiteWindow)f).removeLedgePanel(panel);
+				lastShown = -1;
+			}
+		}
+	}
+	private void resetMessage(){
+		if (panel == null)
+			return;
+		if (lastShown >=0){ 
+			int sel = charSelected();
+			if (sel != lastShown){
+				if (panel!=null) {
+					setReference(lastShown, panel.getMessage());
+					panel.setMessage(getReference(sel), sel);
+				}
+				lastShown = sel;
+			}
+		}
+		else {
+			int sel = charSelected();
+			if (panel!=null) {
+				panel.setMessage(getReference(sel), sel);
+			}
+
+			lastShown = sel;
+		}
+	}
+	/*  	private void resetMessage(int ic){
+   		if (lastShown >=0){ 
+   			int sel = ic;
+   			if (sel != lastShown){
+   				setReference(lastShown, panel.getMessage());
+   		   		panel.setMessage(getReference(sel), sel);
+   		   		lastShown = sel;
+   		   	}
+   		}
+   		else {
+   			int sel = ic;
+   			panel.setMessage(getReference(sel), sel);
+   		   	lastShown = sel;
+  		}
+   	}*/
+	private int charSelected(){
+		if (table.anythingSelected()){
+			int fC = table.firstColumnSelected();
+			if (fC >=0){
+				if (table.lastColumnSelected() == fC)
+					return fC;
+				return -1;
+			}
+			else {
+				int fCC = table.firstColumnWithSelectedCell();
+				if (fCC >=0){
+					if (table.lastColumnWithSelectedCell()== fCC)
+						return fCC;
+					return -1;
+				}
+				else {
+					int fCN = -1;
+					int lCN = -1;
+
+					for (int ic = 0; ic< data.getNumChars(); ic++){
+						if (table.isColumnNameSelected(ic)){
+
+							if (fCN<0)
+								fCN = ic;
+							lCN = ic;
+						}
+					}
+					if (fCN>=0 && fCN == lCN)
+						return fCN;
+
+				}
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (data != null)
+			data.removeListener(this);
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			((MesquiteWindow)f).removeLedgePanel(panel);
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	void focusLost(){
+		resetMessage();
+	}
+	public void focusInCell(int ic, int it){
+		if (panel == null)
+			return;
+		/*if (ic >=0)
+  			resetMessage(ic);
+  		else*/
+		resetMessage();
+	}
+	NameReference refRef = NameReference.getNameReference("charReference");
+	int lastShown = -1;
+	/*...............................................................................................................*/
+	private String getReference(int column){
+		if (data == null || column <0 || column >= data.getNumChars())
+			return "";
+		lastShown = column;
+		//	String s = Integer.toString(column+1) + ". " + data.getCharacterName(column);
+//		data.setCellObject(refRef, ic, it, null);
+		Object obj  = data.getAssociatedObject(refRef, column);
+		if (obj != null && obj instanceof String)
+			return (String)obj;
+
+
+
+		return "";
+	}
+	/*...............................................................................................................*/
+	private void setReference(int column, String refString){
+		if (data == null || column <0 || column >= data.getNumChars())
+			return;
+		if (StringUtil.blank(refString))
+			refString = null;
+		data.setAssociatedObject(refRef, column, refString);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("showStrip " + showStrip.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows a strip with the reference for the character", null, commandName, "showStrip")) {
+			showStrip.toggleValue(parser.getFirstToken(arguments));
+			resetLedge();
+
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Reference Strip";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows the strip at bottom of matrix with character reference." ;
+	}
+}
+class Ledge extends MousePanel {
+	TextArea message, title;
+	CharReferenceStrip ownerModule;
+	int titleWidth = 80;
+	int ic = -1;
+	public Ledge(CharReferenceStrip ownerModule){
+		setLayout(null);
+		this.ownerModule = ownerModule;
+		/* */
+		message = new TextArea(" ", 20, 2, TextArea.SCROLLBARS_NONE);
+		message.setVisible(true);
+		add(message);
+		message.setBounds(titleWidth,0,getBounds().width-titleWidth, getBounds().height);
+		message.setBackground(Color.white);
+
+
+
+		title = new TextArea(" ", 20, 2, TextArea.SCROLLBARS_NONE);
+		title.setVisible(true);
+		add(title);
+		title.setBounds(0,0,titleWidth, getBounds().height);
+		title.setBackground(ColorDistribution.veryLightBlue);
+		title.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+		title.setText("Ref.");
+		message.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+		/**/
+	}
+	public void setMessage(String s, int ic){
+
+		if (StringUtil.stringsEqual(s, message.getText()))
+			return;
+		if (s == null)
+			s = "";
+		this.ic = ic;
+		if (ic<0)
+			title.setText("Ref.");
+		else
+			title.setText("Ref. (" + (ic+1) + ")");
+		message.setText(s);
+
+	}
+	public String getMessage(){
+		return message.getText();
+
+	}
+	public void setSize(int w, int h){
+		message.setBounds(titleWidth,0,w-titleWidth, h);
+		title.setBounds(0,0,titleWidth, h);
+		super.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		message.setBounds(titleWidth,0,w-titleWidth, h);
+		title.setBounds(0,0,titleWidth, h);
+		super.setBounds(x, y, w,h);
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/CharSelCoordinator/CharSelCoordinator.java b/Source/mesquite/charMatrices/CharSelCoordinator/CharSelCoordinator.java
new file mode 100644
index 0000000..eba29cb
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharSelCoordinator/CharSelCoordinator.java
@@ -0,0 +1,146 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.CharSelCoordinator; 
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharSelCoordinator extends CharSelectCoordinator {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	boolean rows = true;
+	Object dataCondition;
+	MesquiteSubmenuSpec mss = null;
+	MesquiteSubmenuSpec mssc = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Select All Characters", makeCommand("selectAll",  this));
+		addMenuItem("Deselect All Characters", makeCommand("deselectAll",  this));
+		addMenuItem("Reverse Character Selection", makeCommand("reverse",  this));
+		addMenuItem("Report Characters Selected...", makeCommand("report",  this));
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects all characters", null, commandName, "selectAll")) {
+			if (data !=null && table!=null) {
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					data.setSelected(i, true);
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Deselects all characters", null, commandName, "deselectAll")) {
+			if (data !=null && table!=null) {
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					data.setSelected(i, false);
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Reverses character selection", null, commandName, "reverse")) {
+			if (data !=null && table!=null) {
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					data.setSelected(i, !data.getSelected(i));
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Reports number of characters selected", null, commandName, "report")) {
+			if (data !=null && table!=null) {
+ 				int count =0;
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					if (data.getSelected(i))
+ 						count++;
+				showLogWindow(true);
+				logln("Number of characters selected: "+count+ "\nNumber of characters unselected: " + (data.getNumChars()-count));
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Selects characters in the set", null, commandName, "selectSet")) {
+			if (data !=null && table!=null) {
+				int whichSet = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+	 			SpecsSetVector ssv = data.getSpecSetsVector(CharSelectionSet.class);
+ 				if (ssv!=null) {
+ 					CharSelectionSet chosen;
+  	 				if (!MesquiteInteger.isCombinable(whichSet))
+	 					chosen = (CharSelectionSet)ListDialog.queryList(containerOfModule(), "Set character selection", "Select characters of which set?", MesquiteString.helpString,ssv, 0);
+    	 				else 
+	    	 				chosen = (CharSelectionSet)ssv.getSpecsSet(whichSet);
+	    	 			if (chosen!=null){
+	    	 				for (int i=0; i<data.getNumChars(); i++)
+	    	 					data.setSelected(i, chosen.isBitOn(i));
+						data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	 					table.repaintAll();
+	    	 				return chosen;
+	    	 			}
+    	 			}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Hires character selection module to operate on the data", "[name of module]", commandName, "doSelectChars")) {
+   	 		if (table!=null && data !=null){
+	    	 		CharacterSelector tda= (CharacterSelector)hireNamedEmployee(CharacterSelector.class, arguments);
+				if (tda!=null) {
+					tda.selectCharacters(data);
+	 	   			table.repaintAll();
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndObject(MesquiteTable table, Object obj, boolean rows){
+		if (obj==null || !(obj instanceof CharacterData))
+			return;
+		this.data = (CharacterData)obj;
+		this.table = table;
+		this.rows = rows;
+		if (mss!=null)
+			deleteMenuItem(mss);
+		if (mssc!=null)
+			deleteMenuItem(mssc);
+		mss = addSubmenu(null, "Character Set", makeCommand("selectSet",  this), data.getSpecSetsVector(CharSelectionSet.class));
+		mssc = addSubmenu(null, "Select Characters", MesquiteModule.makeCommand("doSelectChars",  this));
+		mssc.setList(CharacterSelector.class);
+		mssc.setCompatibilityCheck(data.getStateClass());
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character selection coordinator";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates character selection." ;
+   	 }
+}
+
diff --git a/Source/mesquite/charMatrices/CharSrcCoordIndep/CharSrcCoordIndep.java b/Source/mesquite/charMatrices/CharSrcCoordIndep/CharSrcCoordIndep.java
new file mode 100644
index 0000000..bec76b1
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharSrcCoordIndep/CharSrcCoordIndep.java
@@ -0,0 +1,188 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharSrcCoordIndep;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.CharacterSteps;
+
+public class CharSrcCoordIndep extends CharSourceCoord {
+
+	public String getName() {
+		return "Character Source ";  
+	}
+	public String getExplanation() {
+		return "Coordinates the supply of characters from various sources of characters." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters.",
+				"You can request a source of characters when " + getName() + " starts, or later under the Source of Characters submenu.");
+		e.setSuppressListing(true);
+		//e.setAsEntryPoint(true);
+	}
+	public EmployeeNeed findEmployeeNeed(Class dutyClass) {
+		return getEmployer().findEmployeeNeed(CharSourceCoord.class);
+	}
+	/*.................................................................................................................*/
+	CharSourceCoordObed characterSourceTask;
+	int currentChar = 0;
+	Taxa taxa;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		String exp = "Source of Characters (for " + getEmployer().getName() + ")";
+		if (!MesquiteDialog.useWizards){
+			MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(mesquite.charMatrices.StoredCharacters.StoredCharacters.class);
+			if (mmi != null && !mmi.isCompatible(condition, getProject(), this))
+				exp += "\n\nNOTE: The choice Stored Characters does not appear because there are no appropriate matrices currently defined and stored in the data file or project.  ";
+		}
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, condition, exp);
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		addMenuItem( "Choose Character", makeCommand("chooseCharacter",  this));
+		return true;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		return whatIsMyPurpose(); //transfers info to employer, as ithis is coordinator
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		this.taxa = taxa;
+		characterSourceTask.initialize(taxa);
+	}
+	public Selectionable getSelectionable() {
+		if (characterSourceTask!=null)
+			return characterSourceTask.getSelectionable();
+		else
+			return null;
+	}
+	public void setEnableWeights(boolean enable){
+		if (characterSourceTask!=null)
+			characterSourceTask.setEnableWeights(enable);
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (characterSourceTask!=null)
+			return characterSourceTask.itemsHaveWeights(taxa);
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemWeight(taxa, ic);
+		return MesquiteDouble.unassigned;
+	}
+	public void prepareItemColors(Taxa taxa){
+		if (characterSourceTask!=null)
+			characterSourceTask.prepareItemColors(taxa);
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemColor(taxa, ic);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource", characterSourceTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentChar = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfCharacters(Taxa taxa){
+		this.taxa = taxa;
+		if (null == characterSourceTask)
+			return 0;
+		return characterSourceTask.getNumberOfCharacters(taxa); 
+	}
+	/*.................................................................................................................*/
+	public String getCurrentCharacterName(Taxa taxa) {
+		this.taxa = taxa;
+		if (null == characterSourceTask)
+			return "";
+		return characterSourceTask.getCharacterName(taxa, currentChar); 
+	}
+	/*.................................................................................................................*/
+	/** gets the current matrix.*/
+	public CharacterDistribution getCurrentCharacter(Taxa taxa){
+		this.taxa = taxa;
+		if (null == characterSourceTask)
+			return null;
+		return characterSourceTask.getCharacter(taxa, currentChar); 
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	public String getParameters() {
+		if (characterSourceTask==null)
+			return null;
+		return "Char. " + (currentChar+1) + " of " + characterSourceTask.getName() + " (" + characterSourceTask.getParameters() + ")";
+	}
+	public String getNameAndParameters() {
+		return characterSourceTask.getNameAndParameters();
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/CharSrcCoordObed/CharSrcCoordObed.java b/Source/mesquite/charMatrices/CharSrcCoordObed/CharSrcCoordObed.java
new file mode 100644
index 0000000..5050e3f
--- /dev/null
+++ b/Source/mesquite/charMatrices/CharSrcCoordObed/CharSrcCoordObed.java
@@ -0,0 +1,225 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CharSrcCoordObed;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.CharacterSteps;
+
+public class CharSrcCoordObed extends CharSourceCoordObed implements NameHolder {
+	public String getName() {
+		return "Character Source";  
+	}
+	public String getExplanation() {
+		return "Coordinates the supply of characters from various sources of characters." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharacterObedSource.class, getName() + " needs a source of characters.",
+				"You can request a source of characters when " + getName() + " starts, or later under the Source of Characters submenu.");
+		e.setSuppressListing(true);
+		//e.setAsEntryPoint(true);
+	}
+	public EmployeeNeed findEmployeeNeed(Class dutyClass) {
+		return getEmployer().findEmployeeNeed(CharSourceCoordObed.class);
+	}
+
+	/*.................................................................................................................*/
+	CharacterObedSource characterSourceTask;
+	MesquiteString charSourceName;
+	MesquiteCommand cstC;
+	Object hiringCondition;
+	MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		hiringCondition = condition;
+		String exp, mexp;
+		if (getExplanationByWhichHired()!=null) {
+			exp = getExplanationByWhichHired();
+			mexp = exp;
+		}
+		else {
+			exp = "Source of Characters  (for " + getEmployer().getName() + ")";
+			mexp =  exp;
+		}
+		MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(mesquite.charMatrices.StoredCharacters.StoredCharacters.class);
+		if (mmi != null && !mmi.isCompatible(condition, getProject(), this)) {
+			if (!MesquiteDialog.useWizards){
+				exp += "\n\nNOTE: The choice Stored Characters does not appear because there are no appropriate matrices currently defined and stored in the data file or project.  ";
+			}
+		}
+		else if (CharacterSource.useStoredAsDefault()){
+			characterSourceTask = (CharacterObedSource)hireNamedEmployee(CharacterObedSource.class, "#mesquite.charMatrices.StoredCharacters.StoredCharacters", condition);
+		}
+		if (characterSourceTask == null){
+			if (arguments == null)
+				arguments = MesquiteThread.retrieveAndDeleteHint(this);
+			if (arguments != null)
+				characterSourceTask = (CharacterObedSource)hireNamedEmployee(CharacterObedSource.class, arguments, condition);
+			if (characterSourceTask == null){
+				if (condition!=null)
+					characterSourceTask = (CharacterObedSource)hireCompatibleEmployee(CharacterObedSource.class, condition, exp);
+				else
+					characterSourceTask = (CharacterObedSource)hireEmployee(CharacterObedSource.class, exp);
+			}
+		}
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		charSourceName = new MesquiteString(characterSourceTask.getName());
+		cstC = makeCommand("setCharacterSource",  this);
+		characterSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(CharacterObedSource.class)>1){
+			mss = addSubmenu(null, mexp, cstC, CharacterObedSource.class);
+			mss.setNameHolder(this);
+			if (condition!=null)
+				mss.setCompatibilityCheck(hiringCondition);
+			mss.setSelected(charSourceName);
+		}
+		return true;
+	}
+	public String getMyName(Object obj){
+		if (obj == mss)
+			return "Source of Characters (" + whatIsMyPurpose() + ")";
+		return null;
+	}
+	public void setHiringCondition(Object obj){
+		hiringCondition = obj;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		return whatIsMyPurpose(); //transfers info to employer, as ithis is coordinator
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		characterSourceTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCharacterSource", characterSourceTask);
+		return temp;
+	}
+	public Selectionable getSelectionable() {
+		if (characterSourceTask!=null)
+			return characterSourceTask.getSelectionable();
+		else
+			return null;
+	}
+	public void setEnableWeights(boolean enable){
+		if (characterSourceTask!=null)
+			characterSourceTask.setEnableWeights(enable);
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (characterSourceTask!=null)
+			return characterSourceTask.itemsHaveWeights(taxa);
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemWeight(taxa, ic);
+		return MesquiteDouble.unassigned;
+	}
+	public void prepareItemColors(Taxa taxa){
+		if (characterSourceTask!=null)
+			characterSourceTask.prepareItemColors(taxa);
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (characterSourceTask!=null)
+			return characterSourceTask.getItemColor(taxa, ic);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {
+			CharacterObedSource newCharacterSourceTask;
+			if (hiringCondition!=null)
+				newCharacterSourceTask =  (CharacterObedSource)replaceCompatibleEmployee(CharacterObedSource.class, arguments, characterSourceTask, hiringCondition);//, "Source of characters"
+			else
+				newCharacterSourceTask =  (CharacterObedSource)replaceEmployee(CharacterObedSource.class, arguments, "Source of characters", characterSourceTask);
+			if (newCharacterSourceTask!=null) {
+				characterSourceTask = newCharacterSourceTask;
+				characterSourceTask.setHiringCommand(cstC);
+				charSourceName.setValue(characterSourceTask.getName());
+				resetContainingMenuBar();
+				parametersChanged(); 
+				return characterSourceTask;
+			}
+			else {
+				discreetAlert( "Unable to activate character source \"" + arguments + "\"  for use by " + employer.getName());
+			}
+		}
+		else if (characterSourceTask!=null) { //todo: temporary, for snapshot conversions
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfCharacters(Taxa taxa){
+		CharacterObedSource oldSource = characterSourceTask;
+		int num = characterSourceTask.getNumberOfCharacters(taxa);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return num;
+		return characterSourceTask.getNumberOfCharacters(taxa); 
+	}
+	/*.................................................................................................................*/
+	public String getCharacterName(Taxa taxa, int ic) {
+		CharacterObedSource oldSource = characterSourceTask;
+		String name = characterSourceTask.getCharacterName(taxa, ic);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return name;
+		return characterSourceTask.getCharacterName(taxa, ic); 
+	}
+	/*.................................................................................................................*/
+	public  CharacterDistribution getCharacter(Taxa taxa, int ic){
+		CharacterObedSource oldSource = characterSourceTask;
+		CharacterDistribution matrix = characterSourceTask.getCharacter(taxa, ic);
+		if (oldSource == characterSourceTask) //i.e., old source hasn't quit and been replaced during above call!
+			return matrix;
+		return characterSourceTask.getCharacter(taxa, ic); 
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	public String getParameters() {
+		if (characterSourceTask==null)
+			return null;
+		return characterSourceTask.getName() + " (" + characterSourceTask.getParameters() + ")";
+	}
+	public String getNameAndParameters() {
+		return characterSourceTask.getNameAndParameters();
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ColorByCharValue/ColorByCharValue.java b/Source/mesquite/charMatrices/ColorByCharValue/ColorByCharValue.java
new file mode 100644
index 0000000..c5544d9
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByCharValue/ColorByCharValue.java
@@ -0,0 +1,333 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ColorByCharValue; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ColorByCharValue extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerMatrix {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharacter.class, getName() + " colors the columns (characters) of the matrix to reflect some value for the character.",
+				"You can request a value to calculate initially, or later under the Values for Colors submenu.");
+	}
+	MesquiteTable table;
+	CharacterData data;
+	NumberForCharacter numberTask;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	double[] values;
+	int windowWidth = 1;
+	MesquiteSubmenuSpec mss;
+	Class stateClass;
+	String ntName = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		ntC =makeCommand("setNumberTask",  this);
+ 		numberTaskName = new MesquiteString();
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+   	 	setActive(true);
+ 		if (active){
+			if (numCompatibleModulesAvailable(NumberForCharacter.class, stateClass, this)>0) {
+				mss = addSubmenu(null, "Values for Colors", ntC, NumberForCharacter.class);
+	 			mss.setSelected(numberTaskName);
+	 			mss.setCompatibilityCheck(stateClass);
+				mss.setEnabled(false);
+			}
+			addMenuItem("Moving Window (for colors)...", makeCommand("setWindowWidth", this));
+	 		if (!StringUtil.blank(ntName)) //remember last one used
+				numberTask = (NumberForCharacter)hireNamedEmployee(NumberForCharacter.class, ntName, data.getStateClass());//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+			
+			if (numberTask == null)
+				numberTask = (NumberForCharacter)hireCompatibleEmployee(NumberForCharacter.class, data.getStateClass(), "Value for coloring cells");//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+			
+	 		if (numberTask != null){
+		 		ntName = "#"+numberTask.getShortClassName();
+		 		numberTask.setHiringCommand(ntC);
+		 		numberTaskName.setValue(numberTask.getName());
+ 			} else
+ 				return false;
+ 			mss.setCompatibilityCheck(data.getStateClass());
+			mss.setEnabled(active);
+			calculateNums();
+		}
+		else {
+			fireEmployee(numberTask);
+			numberTask = null;
+			deleteMenuItem(mss);
+		}
+		resetContainingMenuBar();
+		
+		return true; //TODO: check success
+		
+	}
+	public void endJob(){
+		if (data!=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+	double minValue = 0;
+	double maxValue = 0;
+	boolean numsCalculated = false;
+	/*.................................................................................................................*/
+	void calculateNums(){
+		numsCalculated = false;
+   	 	if (data == null || !isActive())
+   	 		return;
+    	 	if (values == null || data.getNumChars() != values.length)
+   	 		values = new double[data.getNumChars()];
+   	 	if (numberTask ==null)
+   	 		return;
+   	 	MesquiteNumber result = new MesquiteNumber();
+   	 	MesquiteNumber min = new MesquiteNumber();
+   	 	MesquiteNumber max = new MesquiteNumber();
+   	 	
+   	 	for (int ic= 0; ic < data.getNumChars(); ic++) {
+ 			result.setToUnassigned();
+ 			numberTask.calculateNumber(data.getCharacterDistribution(ic), result, null);
+ 			values[ic]= result.getDoubleValue();
+ 			min.setMeIfIAmMoreThan(result);
+ 			max.setMeIfIAmLessThan(result);
+ 		}
+   	 	if (windowWidth>1){
+   	 		double[] win = new double[data.getNumChars()];
+		   	 	for (int ic= 0; ic < data.getNumChars(); ic++){
+		   	 		int left = windowWidth/2;
+		   	 		int n = 0;
+		   	 		//first go left, skipping gaps!
+		   	 		int iw = 0;
+		   	 		int is = ic; //start at current character
+		   	 		while (iw<left && is>0){
+		   	 			is--;
+   	 					if (MesquiteDouble.isCombinable(values[is])){
+		   	 				win[ic] += values[is];
+		   	 				n++;
+		   	 				iw++;
+	   	 				}
+		   	 			
+	   	 			}
+	   	 			is = ic-1;
+		   	 		while (iw<windowWidth && is<data.getNumChars()){
+		   	 			is++;
+	   	 					if ( is<data.getNumChars() && MesquiteDouble.isCombinable(values[is])){
+			   	 				win[ic] += values[is];
+			   	 				n++;
+			   	 				iw++;
+		   	 				}
+		   	 			
+	   	 			}
+	   	 			if (n!=0)
+	   	 				win[ic] /= n;
+	   	 		
+	   	 	}
+   	 		values = win;
+ 			min.setToUnassigned();
+ 			max.setToUnassigned();
+	   	 	for (int ic= 0; ic < data.getNumChars(); ic++){
+   	 			result.setValue(values[ic]);
+   	 			min.setMeIfIAmMoreThan(result);
+   	 			max.setMeIfIAmLessThan(result);
+   	 		}
+	   	 	
+ 	 	}
+   	 	minValue = min.getDoubleValue();
+   	 	maxValue = max.getDoubleValue();
+		numsCalculated = true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (this.data!=data && this.data!=null)
+			this.data.removeListener(this);
+		this.data = data;
+		data.addListener(this);
+		stateClass = data.getStateClass();
+		if (mss !=null && mss.getCompatibilityCheck() == null) {
+ 			mss.setCompatibilityCheck(data.getStateClass());
+ 			resetContainingMenuBar();
+ 		}
+		//calculateNums();
+	}
+	public void disposing(Object obj){
+		if (obj == data)
+			data = null;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+ 	 	if (numberTask ==null)
+ 	 		return null;
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setNumberTask ", numberTask);  
+  	 	temp.addLine("setWindowWidth " + windowWidth);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+   	 	if (checker.compare(this.getClass(), "Sets the module that calculates numbers by which to color the cells", "[name of module]", commandName, "setNumberTask")) {
+    	 		NumberForCharacter temp =  (NumberForCharacter)replaceCompatibleEmployee(NumberForCharacter.class, arguments, numberTask, stateClass);
+ 			if (temp!=null) {
+ 				numberTask = temp;
+		 		ntName = "#"+numberTask.getShortClassName();
+		 		numberTask.setHiringCommand(ntC);
+		 		numberTaskName.setValue(numberTask.getName());
+				calculateNums();
+				table.repaintAll();
+				parametersChanged();
+	 			return numberTask;
+	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the width of the moving window", "[width]", commandName, "setWindowWidth")) {
+    	 		int w = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteInteger.isCombinable(w) && !MesquiteThread.isScripting()){
+    	 			w = MesquiteInteger.queryInteger(containerOfModule(), "Moving Window", "Width of Moving Window", windowWidth, 1, 1000);
+    	 		}
+    	 		if (!MesquiteInteger.isCombinable(w))
+    	 			return null;
+    	 		windowWidth = w;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+				parametersChanged();
+    	 	}
+      	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+			calculateNums();
+			if (table !=null && isActive())
+				table.repaintAll();
+			parametersChanged(notification);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Color By Character Value";
+   	 }
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Character Value";
+   	 }
+  	 public String getExplanation() {
+		return "Colors the cells of a character matrix according to a value for the character or a moving window of characters.";
+   	 }
+	/*.................................................................................................................*/
+   	public void viewChanged(){
+   	}
+   	ColorRecord[] legend;
+   	
+   	public ColorRecord[] getLegendColors(){
+   		if (legend == null) 
+   			legend = new ColorRecord[11];
+   		if (minValue >= maxValue) {
+	   		return null;
+   		}
+   		double interval = (maxValue-minValue)/10;
+   		for (int i = 0; i< 10; i++){
+   			double startInterval = interval*i + minValue;
+   			legend[i] = new ColorRecord(MesquiteColorTable.getBlueScale(startInterval, minValue, maxValue, false), MesquiteDouble.toString(startInterval));
+   		}
+   		legend[10] = new ColorRecord(MesquiteColorTable.getBlueScale(maxValue, minValue, maxValue, false), MesquiteDouble.toString(maxValue));
+   		return legend;
+   	}
+   	
+   	public String getColorsExplanation(){
+		if (numberTask!= null)
+			return "Value used for coloring: " + numberTask.getNameAndParameters();
+   		return null;
+   	}
+	public Color getCellColor(int ic, int it){
+		if (ic<0 || it<-1)
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (data == null || values == null)
+			return null;
+		else {
+			
+			Color c = MesquiteColorTable.getBlueScale(values[ic], minValue, maxValue, false);
+			return c;
+		}
+	}
+   	public String getCellString(int ic, int it){
+		if (ic<0 || it<-1 || !isActive())
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (data == null || values == null || numberTask == null)
+			return "Number not calculated";
+		else
+			
+			return numberTask.getName() + ": " + values[ic];
+   	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (!isActive()) 
+			return;
+		if (obj instanceof CharacterData){
+			if (Notification.appearsCosmetic(notification))
+				return;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+			parametersChanged(notification);
+		}
+	}
+	
+	public String getParameters(){
+		if (numberTask!= null){
+			return "Value used for coloring: " + numberTask.getNameAndParameters();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	public CompatibilityTest getCompatibilityTest(){
+		return new CbNCompatibilityTest();
+	}
+}
+
+class CbNCompatibilityTest extends CharacterStateTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (!(super.isCompatible(obj, project, prospectiveEmployer)))
+			return false;
+		return (((MesquiteModule)prospectiveEmployer).numCompatibleModulesAvailable(NumberForCharacter.class, obj, (MesquiteModule)prospectiveEmployer)>0); 
+	}
+}
+
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/ColorByExcluded/ColorByExcluded.java b/Source/mesquite/charMatrices/ColorByExcluded/ColorByExcluded.java
new file mode 100644
index 0000000..be77ff5
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByExcluded/ColorByExcluded.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ColorByExcluded; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class ColorByExcluded extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Color If Excluded";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Excluded";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Colors the excluded characters gray.";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	public void viewChanged(){
+   	}
+   	 public boolean setActiveColors(boolean active){
+   	 	setActive(true);
+		return true; 
+
+   	 }
+   	ColorRecord[] legend;
+   	public ColorRecord[] getLegendColors(){
+   		if (legend == null) {
+   			legend = new ColorRecord[2];
+   			legend[0] = new ColorRecord(Color.white, "Included");
+   			legend[1] = new ColorRecord(Color.gray, "Excluded");
+  		}
+   		return legend;
+   	}
+   	public String getColorsExplanation(){
+   		return null;
+   	}
+	public Color getCellColor(int ic, int it){
+		if (data == null)
+			return null;
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		if (incl == null)
+			return Color.white;
+		if (incl.isBitOn(ic))
+			return Color.white;
+		else
+			return Color.gray;
+	}
+   	public String getCellString(int ic, int it){
+		if (ic<0 || it<0 || !isActive())
+			return null;
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		if (incl == null || incl.isBitOn(ic))
+			return "Character is included";
+		else
+			return "Character is excluded";
+   	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/ColorByFootnote/ColorByFootnote.java b/Source/mesquite/charMatrices/ColorByFootnote/ColorByFootnote.java
new file mode 100644
index 0000000..7832db6
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByFootnote/ColorByFootnote.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ColorByFootnote; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class ColorByFootnote extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerTaxa, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Color By Footnote";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Footnote Present";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Colors the cells of a character matrix by whether or not they have a footnote.";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	public void viewChanged(){
+   	}
+   	 public boolean setActiveColors(boolean active){
+   	 	setActive(true);
+		return true; 
+
+   	 }
+   	ColorRecord[] legend;
+   	public ColorRecord[] getLegendColors(){
+   		if (legend == null) {
+   			legend = new ColorRecord[2];
+   			legend[0] = new ColorRecord(Color.white, "None");
+   			legend[1] = new ColorRecord(ColorDistribution.lightGreen, "With Footnote");
+  		}
+   		return legend;
+   	}
+   	public String getColorsExplanation(){
+   		return null;
+   	}
+	public Color getCellColor(int ic, int it){
+		if (data == null)
+			return null;
+		else if (ic== -1 && data.getTaxa().getAnnotation(it)!=null){ //taxon
+			return ColorDistribution.lightGreen;
+		}
+		else if (it == -1 && data.getAnnotation(ic) !=null){ //character
+			return ColorDistribution.lightGreen;
+		}
+		else if (data.getAnnotation(ic, it) !=null)
+			return ColorDistribution.lightGreen;
+		else {
+			return null;
+		}
+	}
+   	public String getCellString(int ic, int it){
+		if (data == null || !isActive())
+			return null;
+		else if (ic== -1 && data.getTaxa().getAnnotation(it)!=null){ //taxon
+			return "Taxon has footnote";
+		}
+		else if (it == -1 && data.getAnnotation(ic) !=null){ //character
+			return "Character has footnote";
+		}
+		else if (data.getAnnotation(ic, it) !=null)
+			return "Cell corresponding to character and taxon has footnote";
+		else {
+			return null;
+		}
+   	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/ColorByMatchToFirstTaxon/ColorByMatchToFirstTaxon.java b/Source/mesquite/charMatrices/ColorByMatchToFirstTaxon/ColorByMatchToFirstTaxon.java
new file mode 100644
index 0000000..e9c1817
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByMatchToFirstTaxon/ColorByMatchToFirstTaxon.java
@@ -0,0 +1,135 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ColorByMatchToFirstTaxon; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorByMatchToFirstTaxon extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	static final int MATCH = 1;
+	static final int SILENT = 0;
+	static final int MISMATCH = 2;
+	Color[] colors;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		colors = new Color[3];
+		colors[MATCH] = ColorDistribution.lightBlue;
+		colors[SILENT] = Color.lightGray;
+		colors[MISMATCH] = ColorDistribution.lightYellow;
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; 
+
+	}
+	
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color By Match to First Taxon";
+	}
+	public String getNameForMenuItem() {
+		return "Matching First Taxon";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors the cells of a character matrix blue if they match the first taxon, yellow if different, grey if cell or first taxon has missing or inapplicable data.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+		if (!isActive())
+			return null;
+		return "Colored to show whether matches first taxon";
+	}
+	/*.................................................................................................................*/
+	int isMatch(int ic, int it){
+		if (data == null || !(data instanceof CategoricalData))
+			return SILENT;
+		CategoricalData cData = (CategoricalData)data;
+		if (cData.isUnassigned(ic,  it) || cData.isInapplicable(ic, it) || cData.isUnassigned(ic,  0) || cData.isInapplicable(ic, 0))
+			return SILENT;
+		long first = cData.getState(ic, 0);
+		long taxon = cData.getState(ic, it);
+		if ((first & taxon) > 0)
+			return MATCH;
+		return MISMATCH;
+	}
+	/*.................................................................................................................*/
+	
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		if (data == null)
+			return null;
+		legend = new ColorRecord[3];
+				legend[MATCH] = new ColorRecord(colors[MATCH], "Match");
+				legend[SILENT] = new ColorRecord(colors[SILENT], "Missing or inapplicable");
+				legend[MISMATCH] = new ColorRecord(colors[MISMATCH], "Mismatch");
+	
+
+		return legend;
+	}
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		if (data.getClass() == CategoricalData.class){
+			return "Colors show whether cell matches first taxon (blue, match; yellow, mismatch)";
+		}
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if (ic < 0 || it < 0)  
+			return null;
+		if (data == null)
+			return null;
+		else if (data instanceof CategoricalData) {
+			return (colors[isMatch(ic, it)]);
+		} else
+			return data.getColorOfStates(ic, it);
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/ColorByState/ColorByState.java b/Source/mesquite/charMatrices/ColorByState/ColorByState.java
new file mode 100644
index 0000000..3eedd65
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByState/ColorByState.java
@@ -0,0 +1,168 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ColorByState; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorByState extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	CharacterData data;
+	int stateLimit = 9;
+	MesquiteBoolean uniformMaximum = new MesquiteBoolean(true);
+	MesquiteMenuItemSpec mss, mss2;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		mss2 = addCheckMenuItem(null, "All Characters Use Same Maximum Value for Cell Coloring", MesquiteModule.makeCommand("toggleUniformMaximum", this), uniformMaximum);
+		mss = addMenuItem("Set Maximum Value for Cell Coloring...", MesquiteModule.makeCommand("setStateLimit", this));
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; 
+
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setStateLimit " + stateLimit);  
+		temp.addLine("toggleUniformMaximum " + uniformMaximum.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the maximum value for state coloring if uniform state coloring is used", "[state limit]", commandName, "setStateLimit")) {
+			int limit = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(limit) && !MesquiteThread.isScripting()){
+				limit = MesquiteInteger.queryInteger(containerOfModule(), "Maximum State Number", "Maximum State Number for Cell Coloring", stateLimit, 1, MesquiteColorTable.maxNumStates-1);
+			}
+			if (!MesquiteInteger.isCombinable(limit))
+				return null;
+			stateLimit = limit;
+			if (table!=null)
+				table.repaintAll();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not all characters are to use the same maximum value", "[on off]", commandName, "toggleUniformMaximum")) {
+			uniformMaximum.toggleValue(new Parser().getFirstToken(arguments));
+			if (table!=null)
+				table.repaintAll();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		deleteMenuItem(mss);
+		deleteMenuItem(mss2);
+		this.table = table;
+		this.data = data;
+		if (data instanceof CategoricalData && !(data instanceof MolecularData)) {
+			mss2 = addCheckMenuItem(null, "All Characters Use Same Maximum Value for Cell Coloring", MesquiteModule.makeCommand("toggleUniformMaximum", this), uniformMaximum);
+			mss = addMenuItem("Set Maximum Value for Cell Coloring...", MesquiteModule.makeCommand("setStateLimit", this));
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color By State";
+	}
+	public String getNameForMenuItem() {
+		return "Character State";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors the cells of a character matrix by their contained character states.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+		if (!isActive())
+			return null;
+		return "Colored to show state of character";
+	}
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		if (data == null)
+			return null;
+		legend = null;
+		if (data instanceof DNAData){
+			legend = new ColorRecord[DNAState.maxDNAState+1];
+			for (int is = 0; is<=DNAState.maxDNAState; is++) {
+				legend[is] = new ColorRecord(DNAData.getDNAColorOfState(is), DNAData.getDefaultStateSymbol(is));
+			}
+		}
+		else if (data instanceof ProteinData){
+			legend = new ColorRecord[ProteinState.maxProteinState+1];
+			for (int is = 0; is<=ProteinState.maxProteinState; is++) {
+				legend[is] = new ColorRecord(ProteinData.getProteinColorOfState(is), ProteinData.getDefaultStateSymbol(is) + " (" + ProteinData.getStateLongName(is)+")");
+			}
+		} else if (data instanceof CategoricalData && uniformMaximum.getValue()) {
+			legend = new ColorRecord[stateLimit+1];
+			for (int is = 0; is<stateLimit; is++) {
+				legend[is] = new ColorRecord(((CategoricalData)data).getColorOfState(0, is, stateLimit), CategoricalData.getDefaultStateSymbol(is));
+			}
+			legend[stateLimit] = new ColorRecord(((CategoricalData)data).getColorOfState(0, stateLimit, stateLimit), CategoricalData.getDefaultStateSymbol(stateLimit)+" or more");
+
+		}
+
+		return legend;
+	}
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		if (data.getClass() == CategoricalData.class && !uniformMaximum.getValue()){
+			return "Colors of states may vary from character to character";
+		}
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if (ic < 0 || it < 0)  
+			return null;
+		if (data == null)
+			return null;
+		else if (data instanceof CategoricalData && uniformMaximum.getValue() && !(data instanceof MolecularData)) {
+			return ((CategoricalData)data).getColorOfStatesUpperLimit(ic,it, stateLimit);
+		} else
+			return data.getColorOfStates(ic, it);
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/ColorByTaxonValue/ColorByTaxonValue.java b/Source/mesquite/charMatrices/ColorByTaxonValue/ColorByTaxonValue.java
new file mode 100644
index 0000000..af5f172
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorByTaxonValue/ColorByTaxonValue.java
@@ -0,0 +1,320 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ColorByTaxonValue; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ColorByTaxonValue extends DataWindowAssistantID implements CellColorer, CellColorerTaxa, CellColorerMatrix {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTaxon.class, getName() + " colors the rows (taxa) of the matrix to reflect some value for the taxa.",
+		"You can request a value to calculate initially, or later under the Values for Colors submenu.");
+	}
+	MesquiteTable table;
+	Taxa taxa;
+	NumberForTaxon numberTask;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	double[] values;
+	int windowWidth = 1;
+	MesquiteSubmenuSpec mss;
+	String ntName = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		ntC =makeCommand("setNumberTask",  this);
+		numberTaskName = new MesquiteString();
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		if (active){
+			if (numModulesAvailable(NumberForTaxon.class)>0) {
+				mss = addSubmenu(null, "Values for Colors", ntC, NumberForTaxon.class);
+				mss.setSelected(numberTaskName);
+				mss.setEnabled(false);
+			}
+			addMenuItem("Moving Window (for colors)...", makeCommand("setWindowWidth", this));
+			if (!StringUtil.blank(ntName)) //remember last one used
+				numberTask = (NumberForTaxon)hireNamedEmployee(NumberForTaxon.class, ntName);//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+
+			if (numberTask == null)
+				numberTask = (NumberForTaxon)hireEmployee(NumberForTaxon.class, "Value for coloring cells");//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+
+			if (numberTask != null){
+				ntName = "#"+numberTask.getShortClassName();
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+			} else
+				return false;
+			mss.setEnabled(active);
+			calculateNums();
+		}
+		else {
+			fireEmployee(numberTask);
+			numberTask = null;
+			deleteMenuItem(mss);
+		}
+		resetContainingMenuBar();
+
+		return true; //TODO: check success
+
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	double minValue = 0;
+	double maxValue = 0;
+	boolean numsCalculated = false;
+	/*.................................................................................................................*/
+	void calculateNums(){
+		numsCalculated = false;
+		if (taxa == null || !isActive())
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		if (values == null || numTaxa != values.length)
+			values = new double[numTaxa];
+		if (numberTask ==null)
+			return;
+		MesquiteNumber result = new MesquiteNumber();
+		MesquiteNumber min = new MesquiteNumber();
+		MesquiteNumber max = new MesquiteNumber();
+
+		for (int ic= 0; ic < numTaxa; ic++) {
+			result.setToUnassigned();
+			numberTask.calculateNumber(taxa.getTaxon(ic), result, null);
+			values[ic]= result.getDoubleValue();
+			min.setMeIfIAmMoreThan(result);
+			max.setMeIfIAmLessThan(result);
+		}
+		if (windowWidth>1){
+			double[] win = new double[numTaxa];
+			for (int ic= 0; ic < numTaxa; ic++){
+				int left = windowWidth/2;
+				int n = 0;
+				//first go left, skipping gaps!
+				int iw = 0;
+				int is = ic; //start at current character
+				while (iw<left && is>0){
+					is--;
+					if (MesquiteDouble.isCombinable(values[is])){
+						win[ic] += values[is];
+						n++;
+						iw++;
+					}
+
+				}
+				is = ic-1;
+				while (iw<windowWidth && is<numTaxa){
+					is++;
+					if ( is<numTaxa && MesquiteDouble.isCombinable(values[is])){
+						win[ic] += values[is];
+						n++;
+						iw++;
+					}
+
+				}
+				if (n!=0)
+					win[ic] /= n;
+
+			}
+			values = win;
+			min.setToUnassigned();
+			max.setToUnassigned();
+			for (int ic= 0; ic < numTaxa; ic++){
+				result.setValue(values[ic]);
+				min.setMeIfIAmMoreThan(result);
+				max.setMeIfIAmLessThan(result);
+			}
+
+		}
+		minValue = min.getDoubleValue();
+		maxValue = max.getDoubleValue();
+		numsCalculated = true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		Taxa dTaxa = null;
+		if (data != null)
+			dTaxa = data.getTaxa();
+		if (this.taxa!=dTaxa && this.taxa!=null)
+			this.taxa.removeListener(this);
+		this.taxa = dTaxa;
+		if (dTaxa != null)
+			taxa.addListener(this);
+	}
+	public void disposing(Object obj){
+		if (obj == taxa)
+			taxa = null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (numberTask ==null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		temp.addLine("setWindowWidth " + windowWidth);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers by which to color the cells", "[name of module]", commandName, "setNumberTask")) {
+			NumberForTaxon temp =  (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Module to calculate numbers by which to color cells", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				ntName = "#"+numberTask.getShortClassName();
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				calculateNums();
+				table.repaintAll();
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the width of the moving window", "[width]", commandName, "setWindowWidth")) {
+			int w = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(w) && !MesquiteThread.isScripting()){
+				w = MesquiteInteger.queryInteger(containerOfModule(), "Moving Window", "Width of Moving Window", windowWidth, 1, 1000);
+			}
+			if (!MesquiteInteger.isCombinable(w))
+				return null;
+			windowWidth = w;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		calculateNums();
+		if (table !=null && isActive())
+			table.repaintAll();
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color By Taxon Value";
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Taxon Value";
+	}
+	public String getExplanation() {
+		return "Colors the cells of a character matrix according to a value for the Taxon or a moving window of taxa.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	ColorRecord[] legend;
+
+	public ColorRecord[] getLegendColors(){
+		if (legend == null) 
+			legend = new ColorRecord[11];
+		if (minValue >= maxValue) {
+			return null;
+		}
+		double interval = (maxValue-minValue)/10;
+		for (int i = 0; i< 10; i++){
+			double startInterval = interval*i + minValue;
+			legend[i] = new ColorRecord(MesquiteColorTable.getBlueScale(startInterval, minValue, maxValue, false), MesquiteDouble.toString(startInterval));
+		}
+		legend[10] = new ColorRecord(MesquiteColorTable.getBlueScale(maxValue, minValue, maxValue, false), MesquiteDouble.toString(maxValue));
+		return legend;
+	}
+
+	public String getColorsExplanation(){
+		if (numberTask!= null)
+			return "Value used for coloring: " + numberTask.getNameAndParameters();
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if (ic<-1 || it<0)
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (taxa == null || values == null)
+			return null;
+		else {
+
+			Color c = MesquiteColorTable.getBlueScale(values[it], minValue, maxValue, false);
+			return c;
+		}
+	}
+	public String getCellString(int ic, int it){
+		if (ic<-1 || it<0 || !isActive())
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (taxa == null || values == null || numberTask == null)
+			return "Number not calculated";
+		else
+
+			return numberTask.getName() + ": " + values[it];
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (!isActive()) return;
+		if (obj instanceof Taxa){
+			if (Notification.appearsCosmetic(notification))
+				return;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+			parametersChanged(notification);
+		}
+	}
+
+	public String getParameters(){
+		if (numberTask!= null){
+			return "Value used for coloring: " + numberTask.getNameAndParameters();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return true;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/ColorCells/32color.gif b/Source/mesquite/charMatrices/ColorCells/32color.gif
new file mode 100644
index 0000000..a1a5104
Binary files /dev/null and b/Source/mesquite/charMatrices/ColorCells/32color.gif differ
diff --git a/Source/mesquite/charMatrices/ColorCells/64color.gif b/Source/mesquite/charMatrices/ColorCells/64color.gif
new file mode 100644
index 0000000..0e501e2
Binary files /dev/null and b/Source/mesquite/charMatrices/ColorCells/64color.gif differ
diff --git a/Source/mesquite/charMatrices/ColorCells/ColorCells.java b/Source/mesquite/charMatrices/ColorCells/ColorCells.java
new file mode 100644
index 0000000..e5fa542
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorCells/ColorCells.java
@@ -0,0 +1,272 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ColorCells; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+/*   to do:
+	- deal with Option cursor, Shift cursor
+
+
+ *new in 1.02*
+ */
+
+
+/* ======================================================================== */
+public class ColorCells extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerTaxa, CellColorerMatrix {
+	TableTool colorTool; 
+	MesquiteTable table;
+	long currentColor = ColorDistribution.numberOfRed;
+	String colorString = "Color Red";
+	long savedColor = currentColor;
+	MesquiteBoolean removeColor;
+	CharacterData data;
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Assign color to cell", "(A tool in the character matrix editor) Assigns color to the cell touched", null, getPath() + "color.gif"));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			colorNameRef = NameReference.getNameReference("color");
+			colorTool = new TableTool(this, "ColorCells", getPath(), "color.gif", 1,1,colorString, "This tool colors the cells of a matrix.  This has cosmetic effect only.. ", MesquiteModule.makeCommand("colorCell", this), null, null);
+			colorTool.setWorksOnColumnNames(true);
+			colorTool.setWorksOnRowNames(true);
+			((MesquiteWindow)containerOfModule()).addTool(colorTool);
+			colorTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching button
+
+		}
+		else return false;
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Cell paint color", makeCommand("setColor",  this), ColorDistribution.standardColorNames);
+		removeColor = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Remove color", makeCommand("removeColor",  this), removeColor);
+		addMenuItem(null, "Remove all color", makeCommand("removeAllColor",  this));
+		addMenuItem(null, "-", null);
+		addMenuItem(null, "Set Color of Selected", makeCommand("colorSelected",  this));
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		return true; 
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	private void removeColor(int ic, int it, boolean notify){
+		setColor(ic, it, -1);
+		if (notify)
+			table.redrawCell(ic,it);
+	}
+	private void colorSelected(){
+		if (data == null)
+			return;
+		long color = -1;
+		if (MesquiteLong.isCombinable(currentColor))
+			color = currentColor;
+		for (int ic = -1; ic<data.getNumChars(); ic++)
+			for (int it = -1; it<data.getNumTaxa(); it++)
+				if (table.isCellSelectedAnyWay(ic, it))
+					setColor(ic, it, (int)currentColor);
+	}
+	private void removeAllColor(boolean notify){
+		if (data == null)
+			return;
+		for (int ic = -1; ic<data.getNumChars(); ic++)
+			for (int it = -1; it<data.getNumTaxa(); it++)
+				setColor(ic, it, -1);
+		if (notify)
+			table.repaintAll();
+	}
+	public String getCellString(int ic, int it){
+		if (!isActive())
+			return null;
+		return "Colors assigned by user";
+	}
+	private void setColor(int ic, int it, int c){
+		if (data == null)
+			return;
+		if (ic<0 && it<0){
+		}
+		else if (ic<0) { //taxon
+			if (c == -1)
+				data.getTaxa().setAssociatedLong(colorNameRef, it, MesquiteLong.unassigned);
+			else
+				data.getTaxa().setAssociatedLong(colorNameRef, it, c);
+		}
+		else if (it < 0){ //character
+			if (c == -1)
+				data.setAssociatedLong(colorNameRef, ic, MesquiteLong.unassigned);
+			else
+				data.setAssociatedLong(colorNameRef, ic, c);
+
+		}
+		else if (!MesquiteLong.isCombinable(c) || c<0){
+			data.setCellObject(colorNameRef, ic, it, null);
+		}
+		else {
+			MesquiteInteger ms = new MesquiteInteger(c);
+			data.setCellObject(colorNameRef, ic, it, ms);
+		}
+		table.redrawCell(ic,it);
+	}
+	private long getColor(int ic, int it){
+		if (data == null)
+			return 0;
+		if (ic<0){  //taxon
+			long c = data.getTaxa().getAssociatedLong(colorNameRef, it);
+			if (MesquiteLong.isCombinable(c))
+				return c;
+		}
+		else if (it<0){ //character
+			long c = data.getAssociatedLong(colorNameRef, ic);
+			if (MesquiteLong.isCombinable(c))
+				return c;
+		}
+		else {
+			Object obj = data.getCellObject(colorNameRef, ic, it);
+			if (obj != null && obj instanceof MesquiteInteger)
+				return ((MesquiteInteger)obj).getValue();
+		}
+		return MesquiteLong.unassigned;
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public ColorRecord[] getLegendColors(){
+		return null;
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		long color = getColor(ic, it);
+		if (MesquiteLong.isCombinable(color))
+			return ColorDistribution.getStandardColor((int)color);
+		else
+			return null;
+	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setColor " + ColorDistribution.getStandardColorName(ColorDistribution.getStandardColor((int)currentColor)));
+		temp.addLine("removeColor " + removeColor.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	boolean askedAlreadyCells = false;
+	boolean askedAlreadyRowNames = false;
+	boolean askedAlreadyColumnNames = false;
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(),  "Colors cell", "[column touched][row touched]", commandName, "colorCell")) {
+			if (data == null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+
+			if (MesquiteInteger.isCombinable(column)&& (MesquiteInteger.isCombinable(row))) {
+				if (table != null && table.isCellSelectedAnyWay(column, row)){
+					colorSelected();
+				}
+				else if (!MesquiteLong.isCombinable(currentColor))
+					removeColor(column, row, true);
+				else
+					setColor(column, row, (int)currentColor);
+			}
+			if (!MesquiteThread.isScripting()){
+				MesquiteModule mb = findEmployerWithDuty(DataWindowMaker.class);
+				if (mb != null && mb instanceof DataWindowMaker) {
+					String message = null;
+
+					if (column >=0 && row >= 0) { 
+						if (!askedAlreadyCells)
+							message = "Do you want the cells to be colored using the colors you are assigning?";
+						askedAlreadyCells = true;
+					}
+					else if (column < 0 && row >= 0){
+						if (!askedAlreadyRowNames)
+							message = "Do you want the taxon name cells to be colored using the colors you are assigning?";
+						askedAlreadyRowNames = true;
+					}
+					else if (column < 0 && row >= 0){
+						if (!askedAlreadyColumnNames)
+							message = "Do you want the character name cells to be colored using the colors you are assigning?";
+						askedAlreadyColumnNames = true;
+					}
+					((DataWindowMaker)mb).requestCellColorer(this,column, row, message);
+				}
+			}
+		}
+		else	if (checker.compare(this.getClass(), "Sets the color to be used to paint cells", "[name of color]", commandName, "setColor")) {
+			int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments)); 
+			if (bc >=0 && MesquiteLong.isCombinable(bc)){
+				removeColor.setValue(false);
+				currentColor = bc;
+				savedColor = bc;
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue(bc);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes color from all the cells", null, commandName, "removeAllColor")) {
+			removeAllColor(true);
+		}
+		else if (checker.compare(this.getClass(), "Colors selected cells", null, commandName, "colorSelected")) {
+			colorSelected();
+			table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Sets the paint brush so that it removes colors from any cells touched", null, commandName, "removeColor")) {
+			if (StringUtil.blank(arguments))
+				removeColor.setValue(!removeColor.getValue());
+			else
+				removeColor.toggleValue(parser.getFirstToken(arguments));
+
+			if (removeColor.getValue()) {
+				colorString = "Remove color";
+				currentColor = MesquiteLong.unassigned;
+			}
+			else {
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue((int)currentColor);
+				currentColor = savedColor;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Assigned Colors";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to color cells of a matrix.";
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/ColorCells/color.gif b/Source/mesquite/charMatrices/ColorCells/color.gif
new file mode 100644
index 0000000..417c483
Binary files /dev/null and b/Source/mesquite/charMatrices/ColorCells/color.gif differ
diff --git a/Source/mesquite/charMatrices/ColorTInfo/ColorTInfo.java b/Source/mesquite/charMatrices/ColorTInfo/ColorTInfo.java
new file mode 100644
index 0000000..5c80f5d
--- /dev/null
+++ b/Source/mesquite/charMatrices/ColorTInfo/ColorTInfo.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+
+package mesquite.charMatrices.ColorTInfo; 
+
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+//make display of ambiguities optional!!!!!
+
+/** ======================================================================== */
+public class ColorTInfo extends DataWindowAssistantID implements CellColorer, CellColorerTaxa {
+	CharacterData data;
+	MesquiteTable table;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public void viewChanged(){
+		if (data != null)
+			tInfoData = data.getTaxaInfo(false);
+	}
+	boolean wasActive = false;
+	public boolean setActiveColors(boolean active){
+		wasActive = active;
+		if (data != null)
+			tInfoData = data.getTaxaInfo(false);
+		return true; 
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+
+	Associable tInfoData;
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		if (data != null)
+			tInfoData = data.getTaxaInfo(false);
+	}
+	/*.................................................................................................................*/
+	public boolean hasDisplayModifications(){
+		return false;
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+
+	String NOINFOSTRING = "No information attached to this taxon for this matrix";
+	String YESINFOSTRING = "Taxon has information attached for this matrix";
+	public String getCellString(int ic, int it){
+		if (it<0 || ic<0 ||  !isActive())
+			return null;
+		if (ic<0)   {
+			if (tInfoData == null)
+				return NOINFOSTRING;
+			String s = tInfoData.toString(it);
+			if (StringUtil.blank(s))
+				return NOINFOSTRING;
+			else
+				return YESINFOSTRING;
+		}
+		return null;
+	}
+
+	ColorRecord[] legend;
+	public ColorRecord[] getLegendColors(){
+		if (legend == null) {
+			legend = new ColorRecord[2];
+			legend[0] = new ColorRecord(Color.white, NOINFOSTRING);
+			legend[1] = new ColorRecord(ColorDistribution.veryLightGreen, YESINFOSTRING);
+		}
+		return legend;
+	}
+	/*.................................................................................................................*/
+	public Color getCellColor(int ic, int it){
+
+
+		if (it < 0) 
+			return Color.white;
+		if (ic<0)  {
+			String s = tInfoData.toString(it);
+			if (!StringUtil.blank(s))
+					return ColorDistribution.veryLightGreen;
+		}
+			return Color.white;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Information Attached To Matrix";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors taxon names by whether or not there is information attached to this matrix.";
+	}
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/CompareMatrices/CompareMatrices.java b/Source/mesquite/charMatrices/CompareMatrices/CompareMatrices.java
new file mode 100644
index 0000000..ef7fde7
--- /dev/null
+++ b/Source/mesquite/charMatrices/CompareMatrices/CompareMatrices.java
@@ -0,0 +1,151 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.CompareMatrices; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CompareMatrices extends DataUtility { 
+	CharacterData data;
+	TextDisplayer displayer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return true;
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public boolean operateOnData(CharacterData data){
+		this.data = data;
+		Taxa taxa = data.getTaxa();
+		int numSets = getProject().getNumberCharMatricesVisible(taxa);
+		int numSetsDiff = numSets;
+		for (int i = 0; i<numSets; i++) {
+			CharacterData pData =getProject().getCharacterMatrixVisible(taxa, i);
+			if (pData== data)
+				numSetsDiff--;
+			else if (pData.getClass() != data.getClass())
+				numSetsDiff--;
+		}
+		if (numSetsDiff<=0) {
+			alert("Sorry, there are no other compatible data matrices available for comparison.  If the other matrix is in another file, open the file as a linked file before attempting to compare.");
+			return false;
+		}
+		else {
+			Listable[] matrices = new Listable[numSetsDiff];
+			int count=0;
+			for (int i = 0; i<numSets; i++) {
+				CharacterData pData =getProject().getCharacterMatrixVisible(taxa, i);
+				if (pData!= data && (pData.getClass() == data.getClass())) {
+					matrices[count]=pData;
+					count++;
+				}
+			}
+			boolean differenceFound=false;
+			CharacterData oData = (CharacterData)ListDialog.queryList(containerOfModule(), "Compare with", "Compare data matrix with:", MesquiteString.helpString,matrices, 0);
+			if (oData==null)
+				return false;
+				
+			String result = "Comparison of matrix \"" + data.getName() + "\" with matrix \"" + oData.getName() + StringUtil.lineEnding() + StringUtil.lineEnding();
+			if (oData.getNumChars()!=data.getNumChars()) {
+				result+= "The matrices differ in number of characters. (" + data.getName() + " with " + data.getNumChars() + " and " + oData.getName() + " with " + oData.getNumChars() + ")";
+				CharacterState cs1 = null;
+				CharacterState cs2 = null;
+				for (int it = 0; it<data.getNumTaxa() && it<oData.getNumTaxa() && !differenceFound; it++){
+					for (int ic = 0; ic<data.getNumChars() && ic<oData.getNumChars() && !differenceFound; ic++){
+						cs1 = data.getCharacterState(cs1, ic, it);
+						cs2 = oData.getCharacterState(cs2, ic, it);
+						if (!cs1.equals(cs2)) {
+							differenceFound = true;
+							result+= "  The first difference of characters is in taxon " + Taxon.toExternal(it) + " (" + taxa.getTaxonName(it) +  ") and character " + CharacterStates.toExternal(ic) + " (" + data.getName() + ": " + cs1.toString() + "; " + oData.getName() + ": " + cs2.toString() + ")" + StringUtil.lineEnding();
+						}
+					}
+				}
+				differenceFound = true;
+			}
+			else {
+				
+				CharacterState cs1 = null;
+				CharacterState cs2 = null;
+				for (int it = 0; it<data.getNumTaxa() && it<oData.getNumTaxa(); it++){
+					for (int ic = 0; ic<data.getNumChars() && ic<oData.getNumChars(); ic++){
+						cs1 = data.getCharacterState(cs1, ic, it);
+						cs2 = oData.getCharacterState(cs2, ic, it);
+						if (!cs1.equals(cs2)) {
+							differenceFound = true;
+							result+= "Taxon " + Taxon.toExternal(it) + " (" + taxa.getTaxonName(it) +  "); character " + CharacterStates.toExternal(ic) + " differs (" + data.getName() + ": " + cs1.toString() + "; " + oData.getName() + " with " + cs2.toString() + ")" + StringUtil.lineEnding();
+						}
+					}
+				}
+			}
+			if (!differenceFound)
+				result+= "No differences were detected";
+	 	 	Random rn = new Random(System.currentTimeMillis());
+	 	 	String path = MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "compare" + Integer.toString(Math.abs(rn.nextInt()));
+			MesquiteFile.putFileContents(path, result, true);
+			displayFile(path);
+			return true;
+		}
+	}
+	/*.................................................................................................................*/
+ 	public TextDisplayer displayFile(String pathName) {
+		displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+		if (displayer!=null)
+			displayer.showFile(pathName, -1, true); 
+		return displayer;
+ 	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee==displayer)
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Compare Other Matrix";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Compares matrix in data editor with another.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/ConcatRespMatrices/ConcatRespMatrices.java b/Source/mesquite/charMatrices/ConcatRespMatrices/ConcatRespMatrices.java
new file mode 100644
index 0000000..b2d5a40
--- /dev/null
+++ b/Source/mesquite/charMatrices/ConcatRespMatrices/ConcatRespMatrices.java
@@ -0,0 +1,168 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ConcatRespMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ConcatRespMatrices extends CharMatrixSource {
+	MatrixSourceCoordObed dataTask1, dataTask2;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Concatenate Respective Matrices from Two Sources";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies matrices by concatenating respective matrices from two sources.  The i'th matrix supplied is the concatenation of the i'th matrix from each of the two sources.  Assumptions like weights and character models are NOT transferred.  For categorical data, state names are not included.  For continuous data, new items may need to be created to accommodate differences in items between the matrices.";
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		boolean sad = CharacterSource.storedAsDefault.getValue();
+		CharacterSource.storedAsDefault.setValue(false);
+		if (condition!=null) 
+			dataTask1 = (MatrixSourceCoordObed)hireCompatibleEmployee( MatrixSourceCoordObed.class, condition, "First source of matrices for concatenation");
+		else 
+			dataTask1 = (MatrixSourceCoordObed)hireEmployee( MatrixSourceCoordObed.class, "First source of matrices for concatenation");
+		CharacterSource.storedAsDefault.setValue(sad);
+		if (dataTask1 == null) {
+			return sorry(getName() + " can't be started because no first source of matrices was obtained");
+		}
+		CharacterSource.storedAsDefault.setValue(false);
+		if (condition!=null) 
+			dataTask2 = (MatrixSourceCoordObed)hireCompatibleEmployee( MatrixSourceCoordObed.class, condition, "Second source of matrices for concatenation");
+		else 
+			dataTask2 = (MatrixSourceCoordObed)hireEmployee( MatrixSourceCoordObed.class, "Second source of matrices for concatenation");
+		CharacterSource.storedAsDefault.setValue(sad);
+		if (dataTask2 == null) {
+			return sorry(getName() + " can't be started because no second source of matrices was obtained");
+		}
+		return true; 
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CharacterStateTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource1 ", dataTask1);
+		temp.addLine("getCharacterSource2 ", dataTask2);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource1")) {
+			return dataTask1;
+		}
+		else if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource2")) {
+			return dataTask2;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		dataTask1.initialize(taxa);
+	}
+
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Taxa taxa){
+		int num1 =  dataTask1.getNumberOfMatrices(taxa); 
+		int num2 =  dataTask2.getNumberOfMatrices(taxa); 
+		if (MesquiteInteger.isCombinable(num1) && MesquiteInteger.isCombinable(num2))
+			return MesquiteInteger.minimum(num1, num2);
+		else if (MesquiteInteger.isCombinable(num1) )
+			return num1;
+		else
+			return num2;
+	}
+	/*.................................................................................................................*/
+	public String getMatrixName(Taxa taxa, int ic) {
+		String name1 = dataTask1.getMatrixName(taxa, ic);
+		String name2 = dataTask2.getMatrixName(taxa, ic);
+		return "Concatenation of \"" + name1 + "\" and \"" + name2 +"\"";
+	}
+	/*.................................................................................................................*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+		currentMatrix = im;
+		MCharactersDistribution matrix1 = dataTask1.getMatrix(taxa, im);
+		MCharactersDistribution matrix2 = dataTask2.getMatrix(taxa, im);
+		if (matrix1 == null || matrix2 == null){
+			discreetAlert("Sorry, can't concatenate because one or the other matrix contains no information");
+			return null;
+		}
+		if (matrix1.getStateClass() == null || matrix2.getStateClass() == null){
+			discreetAlert("Sorry, can't concatenate because one or the other matrix is not of a recognized type");
+			return null;
+		}
+		if (!matrix1.getStateClass().isAssignableFrom(matrix2.getStateClass())){
+			discreetAlert("Sorry, can't concatenate because matrices are of different types");
+			return null;
+		}
+		int numChars1 = matrix1.getNumChars();
+		int numChars2 = matrix2.getNumChars();
+		MAdjustableDistribution concat = matrix1.makeBlankAdjustable();
+		concat.setSize(numChars1 + numChars2, taxa.getNumTaxa());
+		CharacterState cs = null;
+		for (int it=0; it<taxa.getNumTaxa(); it++){
+			for (int ic=0; ic< numChars1; ic++){
+				concat.setCharacterState(cs=matrix1.getCharacterState(cs, ic, it), ic, it);
+			}
+			for (int ic=0; ic< numChars2; ic++){
+				concat.setCharacterState(cs=matrix2.getCharacterState(cs, ic, it), ic+ numChars1, it);
+			}
+		}
+		String name1 = dataTask1.getMatrixName(taxa, im);
+		String name2 = dataTask2.getMatrixName(taxa, im);
+		concat.setName( "Concatenation of \"" + name1 + "\" and \"" + name2 +"\"");
+		return concat;
+	}
+int currentMatrix= 0;
+	public MCharactersDistribution getCurrentMatrix(Taxa taxa) {
+		return getMatrix(taxa, currentMatrix);
+	}
+
+	public int getNumberCurrentMatrix() {
+		return currentMatrix;
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/ConcatenateMatrices/ConcatenateMatrices.java b/Source/mesquite/charMatrices/ConcatenateMatrices/ConcatenateMatrices.java
new file mode 100644
index 0000000..459407e
--- /dev/null
+++ b/Source/mesquite/charMatrices/ConcatenateMatrices/ConcatenateMatrices.java
@@ -0,0 +1,281 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ConcatenateMatrices; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ConcatenateMatrices extends DataUtility { 
+	CharacterData data;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Concatenate Other Matrix";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Concatenates matrix onto one in data editor.  Assumptions like weights and character models are NOT transferred.  For categorical data, state names are not included.  For continuous data, new items may need to be created to accommodate differences in items between the matrices.";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed) belonging to given taxa.  If permitTaxaMatching is true, 
+	 * considers taxa equal if names coincide*/
+	private int  getNumberCharMatricesPAMT(Taxa taxa, Object dataClass) {   //MesquiteProject
+		ListableVector datas = getProject().getCharacterMatrices();
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if (!data.isDoomed() && (taxa == null || taxa.equals(data.getTaxa(), true)) && (dataClass==null || getProject().compatibleMatrix(dataClass, data)))
+				count++;
+		}
+		return count;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the jth of data sets belonging to a given file*, permitting matrices with different but equivalent taxa */
+	private mesquite.lib.characters.CharacterData getCharacterMatrixPAMT(Taxa taxa, Object dataClass, int j) {  //MesquiteProject
+		ListableVector datas = getProject().getCharacterMatrices();
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if (!data.isDoomed() && (taxa == null || taxa.equals(data.getTaxa(), true)) && (dataClass == null || getProject().compatibleMatrix(dataClass, data))) {
+				if (count==j) {
+					return data;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns a data matrix that is of the same class as that passed, but is a different one.*/  //ConcatenateMatrices
+	public mesquite.lib.characters.CharacterData getDifferentButCompatibleMatrix(mesquite.lib.characters.CharacterData data, boolean permitOtherTaxa,  String messageIfNoneFound, String messageForChoice, boolean subclassOK) {
+		if (data == null)
+			return null;
+		else {
+			Taxa taxa = data.getTaxa();
+			if (permitOtherTaxa)   // in matching methods, setting taxa to null becomes permissive
+				taxa = null; 
+			//taxa.prepareEqualTaxaMessage();
+			int numDatasTotal = getNumberCharMatricesPAMT(taxa, null);//PERMITs use of matrix with different but equivalent taxa
+			//String equalTaxaMessage = taxa.getEqualTaxaMessage();
+			//taxa.turnOffEqualTaxaMessage();		
+			String s ="";
+			boolean allDataIsCurrentData = true;
+			boolean allDataIsWrongClass = true;
+			boolean someDataAreLinked = false;
+			if (numDatasTotal==0)
+				s += " There are no matrices for these taxa.";
+			int numDiffComparable = numDatasTotal;
+			Vector v = new Vector();
+			//this seems to retain remnants of a more relaxed system that would allow matrices connected to other but equivalent Taxa
+			for (int i = 0; i<numDatasTotal; i++) {
+				mesquite.lib.characters.CharacterData pData =getCharacterMatrixPAMT(taxa, null, i); //PERMITs use of matrix with different but equivalent taxa
+
+				if (pData != null) {
+					if (pData== data) //same matrix; don't count
+						numDiffComparable--;
+					else {
+						allDataIsCurrentData = false;   // at least one data matrix with matching taxa is not the current data matrix
+						if (!((subclassOK && (data.getClass().isAssignableFrom(pData.getClass()))) || pData.getClass() == data.getClass())) //different type of data; don't count
+							numDiffComparable--;
+						else { 
+							allDataIsWrongClass = false;   // at least one novel data matrix with matching taxa is of the correct dataClass
+							if (pData.isLinked(data)){ //is linked; don't count
+								numDiffComparable--;
+								someDataAreLinked = true; 
+							}
+							else 
+								v.addElement(pData);
+						}
+
+					}
+				}
+			}		
+			if (numDiffComparable<=0) {
+				if (!MesquiteThread.isScripting() && messageIfNoneFound!=null) {
+					if (numDatasTotal>=1) {
+						if (allDataIsCurrentData) {
+							if (numDatasTotal==1) {
+								s += " There are no other matrices for these taxa. "; //+ equalTaxaMessage;
+							}
+							else
+								s += " All matrices are the same as the current one."; //one shouldn't get here!
+						}
+						else if (allDataIsWrongClass)
+							s += " All other matrices are of a different class of data.";
+						else if (someDataAreLinked)
+							s += " The only comparable matrices are linked.";
+					}
+					MesquiteTrunk.mesquiteTrunk.alert(messageIfNoneFound + "\n\nProblem: "+s);
+				}
+				return null;
+			}
+			else {
+				Listable[] matrices = new Listable[v.size()];
+				for (int i = 0; i<v.size(); i++) {
+					mesquite.lib.characters.CharacterData pData =(mesquite.lib.characters.CharacterData)v.elementAt(i);
+					matrices[i]=pData;
+				}
+				mesquite.lib.characters.CharacterData oData = (mesquite.lib.characters.CharacterData)ListDialog.queryList(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Choose matrix", messageForChoice, MesquiteString.helpString, matrices, 0);
+				return oData;
+			}
+		}
+	}
+	
+	boolean concatenate(CharacterData data, CharacterData oData, boolean notify){
+		if (oData==null)
+			return false;
+		if (oData.isLinked(data) || data.isLinked(oData)) {
+			discreetAlert( "Sorry, those two matrices cannot be concatenated because they are linked");
+			return false;
+		}
+		CommandRecord.tick("Concatenating matrices");
+		if (!oData.getTaxa().equals(data.getTaxa(), true, true)){
+			Taxa oTaxa = oData.getTaxa();
+			Taxa taxa = data.getTaxa();
+			boolean extra = false;
+			for (int oit = 0; oit<oTaxa.getNumTaxa() && !extra; oit++)
+				if (taxa.findEquivalentTaxon(oTaxa, oit)<0)
+					extra = true;
+			//different taxa block, with different names.  Offer to add names
+			if (extra){
+				if (AlertDialog.query(containerOfModule(), "Import taxa from other matrix?", "The matrix you are concatenating to this one is based on a different block of taxa, and includes taxa not in this matrix.  Do you want to add these taxa to this matrix before concatenating?")){
+					String names = "";
+					
+					for (int oit = 0; oit<oTaxa.getNumTaxa(); oit++){
+						if (taxa.findEquivalentTaxon(oTaxa, oit)<0){
+							taxa.addTaxa(taxa.getNumTaxa(), 1, false);
+							taxa.equalizeTaxon(oTaxa, oit, taxa.getNumTaxa()-1);
+							names += taxa.getTaxonName(taxa.getNumTaxa()-1) + "\n";
+							CommandRecord.tick("Added taxon " + taxa.getTaxonName(taxa.getNumTaxa()-1));
+							
+						}
+					}
+					if (!StringUtil.blank(names)){
+						logln("Added to taxa block were:\n" + names);
+						taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null,null));
+					}
+				}
+			}
+
+		}
+		int origNumChars = data.getNumChars();
+		data.addParts(data.getNumChars()+1, oData.getNumChars());
+		CharacterPartition partition = (CharacterPartition) data.getCurrentSpecsSet(CharacterPartition.class);
+		if (partition==null) // let's give the original ones a group
+			data.setToNewGroup(data.getName(), 0, origNumChars-1, this);  //set group
+		data.setToNewGroup(oData.getName(), origNumChars, data.getNumChars()-1, this);  //set group
+		data.addInLinked(data.getNumChars()+1, oData.getNumChars(), true);
+		CharacterState cs = null;
+		for (int ic = 0; ic<oData.getNumChars(); ic++){
+			CommandRecord.tick("Copying character " + (ic+1) + " in concatenation");
+			data.equalizeCharacter(oData, ic, ic+origNumChars);
+		}
+		if (notify)
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {origNumChars, oData.getNumChars()}));
+		return true;
+}
+	
+	/** Called to operate on the data in all cells.  Returns true if data altered*/
+	public boolean operateOnData(CharacterData data){ 
+		this.data = data;
+		CharacterData oData =getDifferentButCompatibleMatrix(data, true,  "Sorry, there are no other compatible data matrices available for concatenation.  If the other matrix is in another file, open the file as a linked file before attempting to concatenate.", "Concatenate which matrix?", true);
+		//modified v. 1.05 to allow matrix of a subclass to be merged into a matrix (e.g. DNA into categorical).
+		//modivied v. 1.2 to allow enlargment of taxa block from new taxa in concatenated matrix
+		if (oData==null)
+			return false;
+		boolean success = data.concatenate(oData, true, true, true);
+		/*
+		if (oData.isLinked(data) || data.isLinked(oData)) {
+			discreetAlert( "Sorry, those two matrices cannot be concatenated because they are linked");
+			return false;
+		}
+		CommandRecord.tick("Concatenating matrices");
+		if (!oData.getTaxa().equals(data.getTaxa(), true, true)){
+			Taxa oTaxa = oData.getTaxa();
+			Taxa taxa = data.getTaxa();
+			boolean extra = false;
+			for (int oit = 0; oit<oTaxa.getNumTaxa() && !extra; oit++)
+				if (taxa.findEquivalentTaxon(oTaxa, oit)<0)
+					extra = true;
+			//different taxa block, with different names.  Offer to add names
+			if (extra){
+				if (AlertDialog.query(containerOfModule(), "Import taxa from other matrix?", "The matrix you are concatenating to this one is based on a different block of taxa, and includes taxa not in this matrix.  Do you want to add these taxa to this matrix before concatenating?")){
+					String names = "";
+					
+					for (int oit = 0; oit<oTaxa.getNumTaxa(); oit++){
+						if (taxa.findEquivalentTaxon(oTaxa, oit)<0){
+							taxa.addTaxa(taxa.getNumTaxa(), 1, false);
+							taxa.equalizeTaxon(oTaxa, oit, taxa.getNumTaxa()-1);
+							names += taxa.getTaxonName(taxa.getNumTaxa()-1) + "\n";
+							CommandRecord.tick("Added taxon " + taxa.getTaxonName(taxa.getNumTaxa()-1));
+							
+						}
+					}
+					if (!StringUtil.blank(names)){
+						logln("Added to taxa block were:\n" + names);
+						taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null,null));
+					}
+				}
+			}
+
+		}
+		int origNumChars = data.getNumChars();
+		data.addParts(data.getNumChars()+1, oData.getNumChars());
+		CharacterPartition partition = (CharacterPartition) data.getCurrentSpecsSet(CharacterPartition.class);
+		if (partition==null) // let's give the origjnal ones a group
+			data.setToNewGroup(data.getName(), 0, origNumChars-1, this);  //set group
+		data.setToNewGroup(oData.getName(), origNumChars, data.getNumChars()-1, this);  //set group
+		data.addInLinked(data.getNumChars()+1, oData.getNumChars(), true);
+		CharacterState cs = null;
+		for (int ic = 0; ic<oData.getNumChars(); ic++){
+			CommandRecord.tick("Copying character " + (ic+1) + " in concatenation");
+			data.equalizeCharacter(oData, ic, ic+origNumChars);
+		}
+		*/
+		return success;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		return temp;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/CondensedPatternMatrix/CondensedPatternMatrix.java b/Source/mesquite/charMatrices/CondensedPatternMatrix/CondensedPatternMatrix.java
new file mode 100644
index 0000000..c93cc72
--- /dev/null
+++ b/Source/mesquite/charMatrices/CondensedPatternMatrix/CondensedPatternMatrix.java
@@ -0,0 +1,203 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.CondensedPatternMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.ParsimonyModelSet;
+import mesquite.categ.lib.*;
+
+/*  module initiated by David Maddison 
+ * */
+public class CondensedPatternMatrix extends CharMatrixSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.charMatrices.StoredMatrices.StoredMatrices.class, getName() + "  needs a source of categorical matrices.",
+		"The source of categorical matrices is arranged initially");
+	}
+	CharMatrixSource dataTask;
+	CharWeightSet weightSet =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		
+		dataTask = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, "#StoredMatrices", CategoricalState.class);
+		if (dataTask == null) {
+			return sorry(getName() + " can't be started because no source of matrices was obtained");
+		}
+		return true; 
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CharacterStateTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", dataTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource")) {
+			return dataTask;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		dataTask.initialize(taxa);
+	}
+	
+	/** Does the core condensation of the matrix.  Note that it makes a copy of the matrix and then condenses that.
+	  It also creates a weight set that stores in it the number of times that pattern appeared in the matrix.
+	 * */
+	private MCharactersDistribution condense(MCharactersDistribution mData){
+		if (mData != null && mData.getParentData() != null){
+			CharacterData data = mData.getParentData();
+				
+			if (data instanceof CategoricalData){
+				CategoricalData condensedData  = ((CategoricalData)data).getDataCopy();
+				int numChars = data.getNumChars();
+				CharWeightSet weightSet= new CharWeightSet("Frequency of Patterns", data.getNumChars(), data);  // making a weight set
+				weightSet.addToFile(getProject().getHomeFile(), getProject(), findElementManager(CharWeightSet.class)); //attaching the weight set to a file
+
+				for (int ic = 0; ic< numChars; ic++)
+					weightSet.setValue(ic,1);
+				
+				for (int ic = 0; ic< numChars; ic++){
+					for (int oic = ic+1; oic< numChars; oic++){
+						if (weightSet.getInt(oic)!=0 && condensedData.samePattern(oic, ic)){  //if weight zero already been here and found it
+							int curWeight = weightSet.getInt(ic);
+							weightSet.setValue(ic,curWeight+1);
+							weightSet.setValue(oic,0);
+							condensedData.clearCharacter(oic);
+						}
+					}
+				}
+
+				condensedData.removeCharactersThatAreEntirelyGaps(false);
+			
+				// delete the extra parts of the weightset
+				int i = numChars-1;
+				while (i>=0) {
+					if (weightSet.getInt(i)==0){
+						weightSet.deleteParts(i, 1);
+					}
+					i--;
+				}
+				
+				
+				// now re-sort by frequency
+				int newNumChars = condensedData.getNumChars();
+				for (int ic=-1; ic<newNumChars; ic++){
+					int bestWeight = 1;
+					int bestCharacter = -1;
+					for (int ic2=ic+1; ic2<newNumChars; ic2++){
+						int current = weightSet.getInt(ic2);
+						if (current>bestWeight){
+							bestWeight=current;
+							bestCharacter=ic2;
+						}
+					}
+					if (bestCharacter>=0 && ic<newNumChars){
+						weightSet.swapParts(ic+1, bestCharacter);
+						condensedData.swapParts(ic+1, bestCharacter);
+					}
+				}
+				condensedData.setCurrentSpecsSet(weightSet, CharWeightSet.class); 
+
+								
+				logln("\nFrequencies of commonest patterns:");
+				for (int ic = 0; ic< weightSet.getNumberOfParts() && ic<20; ic++){
+					logln(" "+(ic+1)+": " + MesquiteDouble.toStringDigitsSpecified(((1.0*weightSet.getInt(ic))/numChars), 4));
+				}
+				logln("\n[To see the frequencies of all patterns, go to the List of Characters window for this pattern matrix and choose Columns>Current Weights to see the weights applied to each character.]");
+			
+				return condensedData.getMCharactersDistribution();
+			}
+		}
+		return null;
+		
+	}
+	
+	/** returns the number of character matrices that can be supplied for the given taxa*/
+	public int getNumberOfMatrices(Taxa taxa){
+		return dataTask.getNumberOfMatrices(taxa);
+	}
+	/** gets the current matrix.*/
+	public  MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		MCharactersDistribution orig = dataTask.getCurrentMatrix(taxa);
+		MCharactersDistribution condensedData = condense(orig);
+		CharacterData data = condensedData.getParentData();
+		if (data!=null)
+			data.setName("Patterns in " + orig.getName());
+		return condensedData;
+	}
+	/** gets the indicated matrix.*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+		MCharactersDistribution orig = dataTask.getMatrix(taxa, im);
+		MCharactersDistribution condensedData = condense(orig);
+		CharacterData data = condensedData.getParentData();
+		if (data!=null)
+			data.setName("Patterns in " + orig.getName());
+		return condensedData;
+	}
+	/** gets name of the indicated matrix.*/
+	public  String getMatrixName(Taxa taxa, int im){
+		return "Patterns in " + dataTask.getMatrixName(taxa, im);
+	}
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return dataTask.getNumberCurrentMatrix();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Condense to Matrix of Patterns";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Condenses a categorical matrix to one having exactly one character of each pattern with that character weighted by the number of copies of that pattern in the original matrix." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+
+}
+
diff --git a/Source/mesquite/charMatrices/DataPainter/DataPainter.java b/Source/mesquite/charMatrices/DataPainter/DataPainter.java
new file mode 100644
index 0000000..05766d7
--- /dev/null
+++ b/Source/mesquite/charMatrices/DataPainter/DataPainter.java
@@ -0,0 +1,257 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.DataPainter; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DataPainter extends DataWindowAssistantI {
+	MesquiteTable table;
+	CharacterData data;
+	CharacterState fillState;
+	boolean neverFilled = true;
+	TableTool fillTool;
+	TableTool dropperTool;
+	int firstColumnTouched = -2;
+	int firstRowTouched = -2;
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Fill selected cells (bucket tool)", "(A tool in the character matrix editor) Fills touched or selected cells with text", null, getRootImageDirectoryPath() + "bucket.gif"));
+		registerSubfunction(new FunctionExplanation("Remember text (eyedropper tool)", "(A tool in the character matrix editor) Sets the text to be filled by the bucket to that touched", null, getRootImageDirectoryPath() + "dropper.gif"));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			MesquiteCommand dragCommand = MesquiteModule.makeCommand("fillDragCell",  this);
+			dragCommand.setSuppressLogging(true);
+			fillTool = new TableTool(this, "fill", MesquiteModule.getRootImageDirectoryPath(), "bucket.gif", 13,14,"Fill with missing data", "This tool fills selected cells with text.  The text to be used can be determined by touching the tool button and selecting the menu item, or by using the dropper tool.", MesquiteModule.makeCommand("fillTouchCell",  this) , dragCommand, MesquiteModule.makeCommand("fillDropCell",  this));
+			fillTool.setOptionsCommand(MesquiteModule.makeCommand("fillOptions",  this));
+			dropperTool = new TableTool(this, "dropper", MesquiteModule.getRootImageDirectoryPath(),"dropper.gif", 1,14,"Copy states", "This tool fills the paint bucket with the text in the cell touched on", MesquiteModule.makeCommand("dropperTouchCell",  this) , null, null);
+			((MesquiteWindow)containerOfModule()).addTool(fillTool);
+			((MesquiteWindow)containerOfModule()).addTool(dropperTool);
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		fillState = data.makeCharacterState();
+	}
+
+	/*.................................................................................................................*/
+	public void paintSelectedCells(MesquiteTable table, CharacterData data) {
+		
+		UndoReference undoReference = new UndoReference(data,this, new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+
+		if (fillState != null && !neverFilled) {
+			boolean success = false;
+			if (table.anyCellSelected()) {
+				if (table.isCellSelected(firstColumnTouched, firstRowTouched)) {
+					for (int i=0; i<table.getNumColumns(); i++)
+						for (int j=0; j<table.getNumRows(); j++)
+							if (table.isCellSelected(i,j)) {
+								data.setState(i,j, fillState);
+							}
+					success = true;
+				}
+			}
+			if (table.anyRowSelected()) {
+				if (table.isRowSelected(firstRowTouched)) {
+					for (int j=0; j<table.getNumRows(); j++) {
+						if (table.isRowSelected(j))
+							for (int i=0; i<table.getNumColumns(); i++)
+								data.setState(i,j, fillState);
+					}
+					success = true;
+				}
+			}
+			if (table.anyColumnSelected()) {
+				if (table.isColumnSelected(firstColumnTouched)) {
+					for (int i=0; i<table.getNumColumns(); i++){
+						if (table.isColumnSelected(i))
+							for (int j=0; j<table.getNumRows(); j++) 
+								data.setState(i,j, fillState);
+					}
+					success = true;
+				}
+			}
+
+			if (success){
+				table.repaintAll();
+				data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED, null, undoReference));
+			}
+
+		}
+	}
+
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Fill touched cell or selected cells with current paint states", "[column touched] [row touched]", commandName, "fillTouchCell")) {
+			if (table!=null && data !=null){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				firstColumnTouched= MesquiteInteger.fromString(arguments, io);
+				firstRowTouched= MesquiteInteger.fromString(arguments, io);
+
+				if (!table.rowLegal(firstRowTouched)|| !table.columnLegal(firstColumnTouched))
+					return null;
+				if (neverFilled){
+					String fillString = MesquiteString.queryString(containerOfModule(), "Fill cells", "Fill cells with states:", "");
+					if (StringUtil.blank(fillString))
+						return null;
+					neverFilled = false;
+					fillState = data.getCharacterState(fillState,0, 0); //just to have a template
+					fillState.setValue(fillString, data);
+					fillTool.setDescription("Fill with \"" + fillState.toString()+ " \"");
+					dropperTool.setDescription("Copy state (current: " + fillState.toString() + ")");
+					((MesquiteWindow)containerOfModule()).toolTextChanged();
+				}
+				if ((table.isCellSelected(firstColumnTouched, firstRowTouched))||(table.isRowSelected(firstRowTouched))||(table.isColumnSelected(firstColumnTouched))) {
+					paintSelectedCells(table, data); // the touched cell or column is selected; therefore, just fill the selection.
+					firstColumnTouched= -2;
+					firstRowTouched= -2;
+				}
+				else {
+					table.selectCell(firstColumnTouched, firstRowTouched);
+					table.deSelectAndRedrawOutsideBlock(firstColumnTouched, firstRowTouched, firstColumnTouched, firstRowTouched);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Tracking paint bucket as it is dragged.", "[column dragged] [row dragged]", commandName, "fillDragCell")) {
+			if (table!=null && data !=null && (firstColumnTouched>=0)&& (firstRowTouched>=0)){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDragged = MesquiteInteger.fromString(arguments, io);
+				int rowDragged= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(rowDragged)|| !table.columnLegal(columnDragged))
+					return null;
+				table.deSelectAndRedrawOutsideBlock(firstColumnTouched, firstRowTouched, columnDragged, rowDragged);
+				table.selectBlock(firstColumnTouched, firstRowTouched, columnDragged, rowDragged);
+				table.redrawBlock(firstColumnTouched, firstRowTouched, columnDragged, rowDragged);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Filling cells with paint after the paint bucket is no longer dragged.", "[column dropped] [row dropped]", commandName, "fillDropCell")) {
+			if (table!=null && data !=null && (firstColumnTouched>=0)&& (firstRowTouched>=0)){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				int columnDropped = MesquiteInteger.fromString(arguments, io);
+				int rowDropped= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(rowDropped)|| !table.columnLegal(columnDropped))
+					return null;
+				paintSelectedCells(table, data); // the touched cell or column is selected; therefore, just fill the selection.
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user for the paint states", null, commandName, "touchTool")) {
+			if (table!=null && data !=null){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				String fillString;
+				if (!fillState.isUnassigned())
+					fillString = MesquiteString.queryString(containerOfModule(), "Fill state", "State with which to fill using paint bucket:", fillState.toDisplayString());
+				else
+					fillString = MesquiteString.queryString(containerOfModule(), "Fill state", "State with which to fill using paint bucket:", "");
+				if (StringUtil.blank(fillString))
+					return null;
+				neverFilled = false;
+				fillState = data.getCharacterState(fillState,0, 0); //just to have a template
+				fillState.setValue(fillString, data);
+				fillTool.setDescription("Fill with \"" + fillState.toDisplayString()+ " \"");
+				dropperTool.setDescription("Copy state (current: " + fillState.toDisplayString() + ")");
+				((MesquiteWindow)containerOfModule()).toolTextChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user what paint to use", null, commandName, "fillOptions")) {
+			if (data.getEditorInhibition()){
+				discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+				return null;
+			}
+			MesquiteButton button = fillTool.getButton();
+			if (button!=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x= MesquiteInteger.fromString(arguments, io); //getting x and y from arguments
+				int y= MesquiteInteger.fromString(arguments, io);
+				MesquitePopup popup = new MesquitePopup(button);
+				popup.addItem("Specify Fill State...", this, MesquiteModule.makeCommand("touchTool", this));
+				popup.showPopup(x,y+6);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the paint states to those in the cell touched", "[column touched] [row touched]", commandName, "dropperTouchCell")) {
+			if (table!=null && data !=null && fillTool != null && dropperTool != null){
+				if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+					return null;
+				}
+				MesquiteInteger io = new MesquiteInteger(0);
+				int column= MesquiteInteger.fromString(arguments, io);
+				int row= MesquiteInteger.fromString(arguments, io);
+				if (!table.rowLegal(row)|| !table.columnLegal(column))
+					return null;
+				neverFilled = false;
+				fillState = data.getCharacterState(fillState,column, row);
+				if (fillState == null)
+					return null;
+				fillTool.setDescription("Fill with \"" + fillState.toString()+ " \"");
+				dropperTool.setDescription("Copy state (current: " + fillState.toString() + ")");
+				if (((MesquiteWindow)containerOfModule()) != null)
+					((MesquiteWindow)containerOfModule()).toolTextChanged();
+			}
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Data Painter";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies the paint can tool and dropper tool for filling cells in a character data editor." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/charMatrices/DataUtilityFileProcessor/DataUtilityFileProcessor.java b/Source/mesquite/charMatrices/DataUtilityFileProcessor/DataUtilityFileProcessor.java
new file mode 100644
index 0000000..33dc29f
--- /dev/null
+++ b/Source/mesquite/charMatrices/DataUtilityFileProcessor/DataUtilityFileProcessor.java
@@ -0,0 +1,133 @@
+package mesquite.charMatrices.DataUtilityFileProcessor;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DataUtilityFileProcessor extends FileProcessor {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(DataUtility.class, getName() + " needs a particular method to act upon data.", null);
+		e2.setPriority(2);
+	}
+	MesquiteTable table;
+	CharacterData data;
+	MesquiteSubmenuSpec mss= null;
+	DataUtility utilityTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			utilityTask = (DataUtility)hireNamedEmployee(DataUtility.class, arguments);
+			if (utilityTask == null)
+				return sorry(getName() + " couldn't start because the requested data utility wasn't successfully hired.");
+		}
+		else {
+			utilityTask = (DataUtility)hireEmployee(DataUtility.class, "Data utility");
+			if (utilityTask == null)
+				return sorry(getName() + " couldn't start because no utility module obtained.");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 302;  
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true; //not really, but to force checking of prerelease
+   	 }
+ 	/*.................................................................................................................*/
+ 	public Snapshot getSnapshot(MesquiteFile file) { 
+ 		Snapshot temp = new Snapshot();
+ 		temp.addLine("setDataUtility ", utilityTask);  
+ 		return temp;
+ 	}
+ 	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+ 		if (checker.compare(this.getClass(), "Sets the data utility module", "[name of module]", commandName, "setDataUtility")) {
+ 			DataUtility temp =  (DataUtility)replaceEmployee(DataUtility.class, arguments, "Data utility", utilityTask);
+ 			if (temp!=null) {
+ 				utilityTask = temp;
+ 				return utilityTask;
+ 			}
+ 
+ 		}
+ 		else
+ 			return  super.doCommand(commandName, arguments, checker);
+ 		return null;
+ 	}
+
+   	/** if returns true, then requests to remain on even after alterFile is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter file. */
+   	public boolean processFile(MesquiteFile file){
+   		MesquiteProject proj = file.getProject();
+   		if (proj == null)
+   			return false;
+   		boolean success = false;
+   		CompatibilityTest test = utilityTask.getCompatibilityTest();
+   		for (int im = 0; im < proj.getNumberCharMatrices(file); im++){
+   			CharacterData data = proj.getCharacterMatrix(file, im);
+   			if (test.isCompatible(data.getStateClass(), getProject(), this)) {
+   				success = true;
+   				utilityTask.operateOnData(data);  // do not measure success based upon whether data were altered.
+   			}
+   		}
+   			
+   		return success;
+   	}
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Process using Data Utility";
+	 }
+		/*.................................................................................................................*/
+	 public String getNameAndParameters() {
+		 if (utilityTask==null)
+			 return "Process using Data Utility";
+		 else
+			 return "Process using Data Utility (" + utilityTask.getName() + ")";
+	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages data-transforming Data Utility modules to transform all matrices in a file." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/DifferenceInNumsForChar/DifferenceInNumsForChar.java b/Source/mesquite/charMatrices/DifferenceInNumsForChar/DifferenceInNumsForChar.java
new file mode 100644
index 0000000..4b62455
--- /dev/null
+++ b/Source/mesquite/charMatrices/DifferenceInNumsForChar/DifferenceInNumsForChar.java
@@ -0,0 +1,165 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.DifferenceInNumsForChar;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DifferenceInNumsForChar extends NumberForCharacter {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharacter.class, getName() + " compares two different values for each character.",
+				"You can request what values to compare initially, or later under the First Value for Difference submenu and the Second Value for Difference submenu.");
+	}
+	NumberForCharacter numberTask1, numberTask2;
+	MesquiteString numberTask1Name, numberTask2Name;
+	MesquiteCommand ntC1, ntC2;
+	MesquiteNumber[] numbers = new MesquiteNumber[2];
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask1 = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "First value to calculate for character");
+		if (numberTask1 == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		numberTask2 = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "Second value to calculate for character");
+		if (numberTask2 == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		numbers[0] = new MesquiteNumber();
+		numbers[1] = new MesquiteNumber();
+		
+		ntC1 =makeCommand("setNumberTask1",  this);
+		ntC2 =makeCommand("setNumberTask2",  this);
+ 		numberTask1.setHiringCommand(ntC1);
+ 		numberTask1Name = new MesquiteString();
+ 		numberTask1Name.setValue(numberTask1.getName());
+ 		numberTask2.setHiringCommand(ntC2);
+ 		numberTask2Name = new MesquiteString();
+ 		numberTask2Name.setValue(numberTask2.getName());
+		if (numModulesAvailable(NumberForCharacter.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "First Value for Difference", ntC1, NumberForCharacter.class);
+ 			mss.setSelected(numberTask1Name);
+			mss = addSubmenu(null, "Second Value for Difference", ntC2, NumberForCharacter.class);
+ 			mss.setSelected(numberTask2Name);
+		}
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setNumberTask1 ", numberTask1);  
+ 	 	temp.addLine("setNumberTask2 ", numberTask2);  
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+   	 	if (checker.compare(this.getClass(), "Sets the module that calculates the first number for characters", "[name of module]", commandName, "setNumberTask1")) {
+    	 		NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Number for character (first in difference)", numberTask1);
+ 			if (temp!=null) {
+ 				numberTask1 = temp;
+		 		numberTask1.setHiringCommand(ntC1);
+		 		numberTask1Name.setValue(numberTask1.getName());
+				parametersChanged();
+	 			return numberTask1;
+	 		}
+    	 	}
+   	 	else if (checker.compare(this.getClass(), "Sets the module that calculates the second number for characters", "[name of module]", commandName, "setNumberTask2")) {
+    	 		NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Number for character (second in difference)", numberTask2);
+ 			if (temp!=null) {
+ 				numberTask2 = temp;
+		 		numberTask2.setHiringCommand(ntC2);
+		 		numberTask2Name.setValue(numberTask2.getName());
+				parametersChanged();
+	 			return numberTask2;
+	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   		if (numberTask1 !=null)
+   			numberTask1.initialize(charStates);
+   		if (numberTask2 !=null)
+   			numberTask2.initialize(charStates);
+  	}
+   	public boolean returnsMultipleValues(){
+   	return true;
+}
+    	 MesquiteString rs1 = new MesquiteString();
+    	 MesquiteString rs2 = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || charStates == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		rs1.setValue("");
+		rs2.setValue("");
+		MesquiteNumber r = new MesquiteNumber();
+		numberTask1.calculateNumber(charStates, r, rs1);
+		numberTask2.calculateNumber(charStates, result, rs2);
+		numbers[0].setName(r.getName());
+		numbers[0].setValue(r);
+		numbers[1].setName(result.getName());
+		numbers[1].setValue(result);
+		
+		result.subtract(r);
+		result.copyAuxiliaries(numbers);
+		if (resultString!=null) {
+			resultString.setValue("Difference: " + result + " [" + rs1 + "] - [" + rs2 + "]");
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Difference between: " + numberTask1.getName() + " and " + numberTask2.getName(); 
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Difference in two values for character";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+    	 	if (numberTask1 ==null | numberTask2 == null)
+			return "Difference in two values";
+		else
+			return "Difference [" + numberTask1.getVeryShortName() + "] - [" + numberTask2.getVeryShortName() + "]";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates the calculation of the difference in two numbers for a character." ;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/Fill/Fill.java b/Source/mesquite/charMatrices/Fill/Fill.java
new file mode 100644
index 0000000..68107da
--- /dev/null
+++ b/Source/mesquite/charMatrices/Fill/Fill.java
@@ -0,0 +1,89 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.Fill; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class Fill extends DataAlterer {
+	CharacterState fillState=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public void alterCell(CharacterData data, int ic, int it){
+   		if (fillState!= null)
+   			data.setState(ic,it, fillState);
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table,UndoReference undoReference){
+  		String fillString;
+		if ((table==null && data!=null)||!table.anyMainTableCellSelected())
+			fillString = MesquiteString.queryString(containerOfModule(), "Fill all cells", "Fill entire matrix with states:", "");
+		else
+			fillString = MesquiteString.queryString(containerOfModule(), "Fill selected cells", "Fill selected cells with states:", "");
+		if (StringUtil.blank(fillString))
+			return false;
+		
+   		fillState = data.getCharacterState(fillState, 0, 0); //just to have a template
+   		fillState.setValue(fillString, data);
+		if (fillState.isImpossible()) 
+			return false;
+		boolean success = alterContentOfCells(data,table, undoReference);
+		return success;
+   	}
+
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Fill";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Fill...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Fills cells with a uniform state in a character data editor." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/IncludedCharBoolean/IncludedCharBoolean.java b/Source/mesquite/charMatrices/IncludedCharBoolean/IncludedCharBoolean.java
new file mode 100644
index 0000000..23506cc
--- /dev/null
+++ b/Source/mesquite/charMatrices/IncludedCharBoolean/IncludedCharBoolean.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.IncludedCharBoolean;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class IncludedCharBoolean extends BooleanForCharacter {
+
+	public String getName() {
+		return "Character Included";
+	}
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public void calculateBoolean(CharacterData data, int ic, MesquiteBoolean result, MesquiteString resultString) {
+		if (data==null || result==null)
+			return;
+		boolean included = data.isCurrentlyIncluded(ic);
+
+		result.setValue(included);
+		resultString.setValue(getValueString(included));
+	}
+	/*.................................................................................................................*/
+	public boolean displayTrueAsDark(){
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	public String getTrueString(){
+		return "Included";
+	}
+	/*.................................................................................................................*/
+	public String getFalseString(){
+		return "Excluded";
+	}
+
+	public String getExplanation() {
+		return "A boolean that is true if a character is currently included, and false if the character is currently excluded.";
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false; 
+	}
+
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+
+
+}
diff --git a/Source/mesquite/charMatrices/ManageAssumptionsBlock/ManageAssumptionsBlock.java b/Source/mesquite/charMatrices/ManageAssumptionsBlock/ManageAssumptionsBlock.java
new file mode 100644
index 0000000..c3d0c7d
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageAssumptionsBlock/ManageAssumptionsBlock.java
@@ -0,0 +1,158 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageAssumptionsBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages the ASSUMPTIONS block of a NEXUS file.*/
+public class ManageAssumptionsBlock extends FileInit {
+	int numBlocks =0;
+	public Class getDutyClass(){
+		return ManageAssumptionsBlock.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] bs = getProject().getNexusBlocks(AssumptionsBlock.class, f); //added Dec 01
+		if (bs == null || bs.length ==0){ 
+			AssumptionsBlock ab = new AssumptionsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new AssumptionsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		int c = 0;
+		String s;
+		AssumptionsBlock ab;
+ 		NexusBlock[] bs = getProject().getNexusBlocks(AssumptionsBlock.class, file); //added Sept 2011
+		if (bs == null || bs.length ==0)
+			ab = new AssumptionsBlock(file, this);
+		else
+			ab = (AssumptionsBlock)bs[0];
+		MesquiteString comment = new MesquiteString();
+		while (!StringUtil.blank(s=block.getNextFileCommand(comment))) {
+			String commandName = parser.getFirstToken(s);
+			if (commandName != null && !commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK")) {
+				if (commandName.equalsIgnoreCase("LINK")){
+					ab.processLinkCTCommand( s, getProject(), parser);
+				}
+				else if (commandName.equalsIgnoreCase("Options")){
+					ab.setOptionsCommand(s);
+				}
+				else 
+					readUnrecognizedCommand(file, ab, "ASSUMPTIONS", block, commandName, s, blockComments, comment);
+			}
+		}
+		numBlocks++;
+		return ab; 
+	}
+
+	/*.................................................................................................................*/
+	public String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "ASSUMPTIONS");
+			if (!StringUtil.blank(command))
+				commands+="\t"+command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage ASSUMPTIONS blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages ASSUMPTIONS block in NEXUS file." ;
+   	 }
+}
+	
+	
+	
+class AssumptionsBlock extends NexusBlock {
+	String options = null;
+	public AssumptionsBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public boolean contains(FileElement e) {
+		return false;  //always false; needs to use other means to determine if need to create block
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("Assumptions clean");
+	}
+	public void setOptionsCommand(String opt){
+		options = opt;
+	}
+	public String getName(){
+		return "ASSUMPTIONS block";
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("CHARACTERS") ||  block.getBlockName().equalsIgnoreCase("SETS") ||  block.getBlockName().equalsIgnoreCase("LABELS"));
+		
+	}
+	public String getBlockName(){
+		return "ASSUMPTIONS";
+	}
+	public String getNEXUSBlock(){
+
+		String contents = ((ManageAssumptionsBlock)getManager()).employeesGetCommands(getManager().getFileCoordinator(), getFile());
+		String unrec = getUnrecognizedCommands();
+		if (StringUtil.blank(contents) && StringUtil.blank(unrec))
+			return null;
+		String blocks="BEGIN ASSUMPTIONS;" + StringUtil.lineEnding();
+		if (options!=null)
+			blocks += options + StringUtil.lineEnding();
+		blocks += contents;
+		if (!StringUtil.blank(unrec)) {
+			blocks += StringUtil.lineEnding()+ unrec + StringUtil.lineEnding();
+		}
+		blocks += "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+}/* ======================================================================== */
+class AssumptionsBlockTest extends NexusBlockTest  {
+	public AssumptionsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharInclusion/ManageCharInclusion.java b/Source/mesquite/charMatrices/ManageCharInclusion/ManageCharInclusion.java
new file mode 100644
index 0000000..e87065f
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharInclusion/ManageCharInclusion.java
@@ -0,0 +1,150 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCharInclusion;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages specification of character inclusion/exclusion, including reading/writing EXSETs in NEXUS file*/
+public class ManageCharInclusion extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.CharInclSetList.CharInclSetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	public Class getElementClass(){
+		return CharInclusionSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Character Inclusion Set";
+	}
+	public String lowerCaseTypeName(){
+		return "character inclusion set";
+	}
+	public String nexusToken(){
+		return "EXSET";
+	}
+	public Object getSpecification(String token){
+		return null;
+	}
+	public boolean hasSpecificationTokens(){
+		return false;
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CharInclusionSet))
+			return;
+		CharInclusionSet sS = (CharInclusionSet)specsSet;
+		sS.setSelected(ic, false);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+ 		CharInclusionSet inclusionSet = new CharInclusionSet(name, data.getNumChars(), data);
+		inclusionSet.selectAll(); //default is selected (EXSET deselects, i.e. excludes, some characters
+		return inclusionSet;
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+   	
+
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+			if (specsSet ==null || !(specsSet instanceof CharInclusionSet))
+				return null;
+			CharInclusionSet inclusionSet = (CharInclusionSet)specsSet;
+			String s= "";
+			if (inclusionSet!=null && (inclusionSet.getFile()==file || (inclusionSet.getFile()==null && data.getFile()==file))) {
+				String sT = "";
+				int continuing = 0;
+				int lastWritten = -1;
+				for (int ic=0; ic<data.getNumChars(); ic++) {
+					if (!inclusionSet.isBitOn(ic)) {
+						if (continuing == 0) {
+							sT += " " + CharacterStates.toExternal(ic);
+							lastWritten = ic;
+							continuing = 1;
+						}
+						else if (continuing == 1) {
+							sT += " - ";
+							continuing = 2;
+						}
+					}
+					else if (continuing>0) {
+						if (lastWritten !=ic-1){
+							sT += " " + CharacterStates.toExternal(ic-1);
+							lastWritten = ic-1;
+						}
+						else
+							lastWritten = -1;
+						continuing = 0;
+					}
+
+				}
+				if (continuing>1)
+					sT += " " + CharacterStates.toExternal(data.getNumChars()-1);
+				s += "EXSET ";
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(inclusionSet.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s += " = " + sT + ";" + StringUtil.lineEnding();
+				
+			}
+			return s;
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new CharsetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage character inclusion sets";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) character inclusion sets (EXSETS)." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class CharsetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && commandName.equalsIgnoreCase("EXSET"));
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharModels/ManageCharModels.java b/Source/mesquite/charMatrices/ManageCharModels/ManageCharModels.java
new file mode 100644
index 0000000..d46b617
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharModels/ManageCharModels.java
@@ -0,0 +1,431 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCharModels;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages models of character evolution, including coordinating file reading and writing*/
+public class ManageCharModels extends FileInit implements ElementManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharModelCurator.class, getName() + " needs curators to create and edit the various types of character models.",
+				"You can make new or edit previously made character models using the menu items in the Characters menu.");
+		e.setAlternativeEmployerLabel("Editors for character models");
+	}
+	ModelNamesLister modelNames, submodelNames;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(CharModelCurator.class);
+		
+ 		return true;
+	}
+	public void elementsReordered(ListableVector v){
+	}
+/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof CharacterModel){
+			CharacterModel t = (CharacterModel)e;
+			CharModelCurator curator = findReader(t.getClass());
+			if (curator !=null)
+		   		curator.showEditor(t);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void deleteElement(FileElement e){
+		if (e instanceof CharacterModel){
+			CharacterModel t = (CharacterModel)e;
+			t.doom();
+			getProject().removeFileElement(t);//must remove first, before disposing
+			t.dispose();
+		}
+	}
+	public void endJob(){
+		if (submodelNames !=null)
+			submodelNames.dispose();
+		submodelNames = null;
+		if (modelNames !=null)
+			modelNames.dispose();
+		modelNames = null;
+		super.endJob();
+	}
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return CharacterModel.class;
+	}
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "List of Character Models", makeCommand("showModels",  this));
+		modelNames = new ModelNamesLister(getProject(), WholeCharacterModel.class);
+		MesquiteSubmenuSpec ncm = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu,"New Character Model", makeCommand("newModel", this), WholeCharModelCurator.class);
+		ncm.setListableFilter(EditingCurator.class);
+		getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Edit Character Model", makeCommand("editModel", this), modelNames);
+		submodelNames = new ModelNamesLister(getProject(), CharacterSubmodel.class);
+		ncm = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu,"New Character Submodel", makeCommand("newSubModel", this), CharSubmodelCurator.class);
+		ncm.setListableFilter(EditingCurator.class);
+		getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Edit Character Submodel", makeCommand("editSubmodel", this), submodelNames);
+		MesquiteSubmenuSpec mset = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu,"Model Settings", makeCommand("modelSettings", this), WholeCharModelCurator.class);
+		mset.setListableFilter(CuratorWithSettings.class);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu,"-", null);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible()) {
+  	 				temp.addLine("showModels ", e); 
+  	 		}
+		}
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Edits the character model", "[name of character model]", commandName, "editModel")) {
+    	 		String name = parser.getFirstToken(arguments);
+    	 		int num = MesquiteInteger.fromString(parser.getNextToken());
+			CharacterModel model = null;
+    	 		if (MesquiteInteger.isCombinable(num))
+    	 			model = getProject().getCharacterModel(WholeCharacterModel.class, false, num);
+			if (model == null)
+				model = getProject().getCharacterModel(name);
+			if (model !=null) {
+				CharModelCurator curator = findReader(model.getClass());
+				if (curator==null)
+					alert("Sorry, no curator module was found for that sort of character model (category: " + model.getTypeName() + ")");
+				else 
+					curator.showEditor(model);
+			}
+			return model;
+		}
+    	 	else if (checker.compare(this.getClass(), "Edits the character submodel", "[name of character submodel]", commandName, "editSubmodel")) {
+    	 		String name = parser.getFirstToken(arguments);
+    	 		int num = MesquiteInteger.fromString(parser.getNextToken());
+			CharacterModel model = null;
+    	 		if (MesquiteInteger.isCombinable(num))
+    	 			model = getProject().getCharacterModel(CharacterSubmodel.class, false, num);
+			if (model == null)
+				model = getProject().getCharacterModel(name);
+			if (model !=null) {
+				CharModelCurator curator = findReader(model.getClass());
+				if (curator==null)
+					alert("Sorry, no curator module was found for that sort of character model (category: " + model.getTypeName() + ")");
+				else 
+					curator.showEditor(model);
+			}
+			return model;
+		}
+    	 	else if (checker.compare(this.getClass(), "Shows a list of the available character models", null, commandName, "showModels")) {
+    	 		//Check to see if already has lister for this
+    	 		boolean found = false;
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if (((ManagerAssistant)e).getName().equals("Character Models List")) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return e;
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Character Models List"));
+ 			if (lister==null){
+ 				alert("Sorry, no module was found to present a list of character models");
+ 				return null;
+ 			}
+ 			lister.showListWindow(null);
+ 			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+ 				lister.getModuleWindow().setVisible(true);
+ 			return lister;
+   	 	}
+    	 	else if (checker.compare(this.getClass(), "Makes a new character model", "[Class of model]", commandName, "newModel")) {
+			CharModelCurator curator= (CharModelCurator)findEmployee(parser.getFirstToken(arguments));
+			if (curator !=null) {
+				String name = MesquiteString.queryShortString(containerOfModule(), "New "+curator.getName(), "Name of new "+curator.getName()+":", getProject().getCharacterModels().getUniqueName(curator.getName()));
+				if (name==null)
+					return null;
+				CharacterModel model = curator.makeNewModel(name);
+		   		model.addToFile(null, getProject(), null); //TODO:ok to add to homefile, or query user?
+		   		curator.showEditor(model);
+		   		if (model.getEditCancel()) {
+		   			curator.disposeModel(model);
+		   			return null;
+		   		}
+				resetAllMenuBars();
+				return model;
+			}
+		}
+    	 	else if (checker.compare(this.getClass(), "Makes a new character submodel", "[Class of model]", commandName, "newSubmodel")) {
+			CharModelCurator curator= (CharModelCurator)findEmployee(parser.getFirstToken(arguments));
+			if (curator !=null) {
+				String name = MesquiteString.queryShortString(containerOfModule(), "New "+curator.getName(), "Name of new "+curator.getName()+":", getProject().getCharacterModels().getUniqueName(curator.getName()));
+				if (name==null)
+					return null;
+				CharacterModel model = curator.makeNewModel(name);
+		   		model.addToFile(null, getProject(), null); //TODO:ok to add to homefile, or query user?
+		   		curator.showEditor(model);
+		   		if (model.getEditCancel()) {
+		   			curator.disposeModel(model);
+		   			return null;
+		   		}
+				resetAllMenuBars();
+				return model;
+			}
+		}
+    	 	else if (checker.compare(this.getClass(), "Presents means to edit the universal settings for a type of model (e.g., settings for optimization)", "[Class of model]", commandName, "modelSettings")) {
+			CharModelCurator curator= (CharModelCurator)findEmployee(parser.getFirstToken(arguments));
+			if (curator !=null && curator instanceof CuratorWithSettings) {
+				((CuratorWithSettings)curator).editSettings();
+			}
+		}
+    	 	else
+ 			return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("MESQUITECHARMODELS")) {
+			String s= "";
+			Enumeration enumeration = file.getProject().getCharacterModels().elements();
+			while (enumeration.hasMoreElements()){   // write the submodels
+				Object obj = enumeration.nextElement();
+				CharacterModel cm = (CharacterModel)obj;
+				if (!cm.isBuiltIn() && !("USERTYPE".equalsIgnoreCase(cm.getNEXUSCommand())) &&cm.getFile()==file && cm instanceof CharacterSubmodel) {
+					s += "\t"+ cm.getNEXUSCommand() + " ";  
+					s += StringUtil.tokenize(cm.getName()) + " (" ;  
+					s += StringUtil.tokenize(cm.getNEXUSClassName()) + ") = " + StringUtil.lineEnding();
+					s += "\t\t"+ cm.getNexusSpecification()+";" + StringUtil.lineEnding(); 
+				}
+				//else if (!cm.isBuiltIn() && cm.getFile()!=file)
+				//	MesquiteMessage.println("Character model (" + cm.getName() + ") not in file");				
+			}
+			enumeration = file.getProject().getCharacterModels().elements();
+			while (enumeration.hasMoreElements()){   // write everything else
+				Object obj = enumeration.nextElement();
+				CharacterModel cm = (CharacterModel)obj;
+				if (!cm.isBuiltIn() && !("USERTYPE".equalsIgnoreCase(cm.getNEXUSCommand())) &&cm.getFile()==file && (!( cm instanceof CharacterSubmodel))) {
+					s += "\t"+ cm.getNEXUSCommand() + " ";  
+					s += StringUtil.tokenize(cm.getName()) + " (" ;  
+					s += StringUtil.tokenize(cm.getNEXUSClassName()) + ") = " + StringUtil.lineEnding();
+					s += "\t\t"+ cm.getNexusSpecification()+";" + StringUtil.lineEnding(); 
+				}
+				//else if (!cm.isBuiltIn() && cm.getFile()!=file)
+				//	MesquiteMessage.println("Character model (" + cm.getName() + ") not in file");				
+			}
+			return s;
+		}
+		else if (blockName.equalsIgnoreCase("ASSUMPTIONS")) {
+			String s= "";
+			Enumeration enumeration = file.getProject().getCharacterModels().elements();
+			while (enumeration.hasMoreElements()){
+				Object obj = enumeration.nextElement();
+				CharacterModel cm = (CharacterModel)obj;
+				if (!cm.isBuiltIn() && "USERTYPE".equalsIgnoreCase(cm.getNEXUSCommand()) && cm.getFile()==file) {
+					s += "\t"+ cm.getNEXUSCommand() + " ";  
+					s += StringUtil.tokenize(cm.getName()) + " (" ;  
+					s += StringUtil.tokenize(cm.getNEXUSClassName()) + ") = " + StringUtil.lineEnding();
+					s += "\t\t"+ cm.getNexusSpecification()+";" + StringUtil.lineEnding(); 
+				}
+				//else if (!cm.isBuiltIn() && cm.getFile()!=file)
+				//	MesquiteMessage.println("Character model (" + cm.getName() + ") not in file.");				
+			}
+			return s;
+		}
+		return null;
+	}
+	public CharModelCurator findReader(Class modelType) {
+		CharModelCurator readerTask=null;
+		for (int i = 0; i<getNumberOfEmployees() && readerTask==null; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharModelCurator)
+				if (((CharModelCurator)e).getModelClass().isAssignableFrom(modelType)) {
+					readerTask=(CharModelCurator)e;
+				}
+		}
+		return readerTask;
+	}
+	public CharModelCurator findReader(String modelType) {
+		CharModelCurator readerTask=null;
+		for (int i = 0; i<getNumberOfEmployees() && readerTask==null; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharModelCurator)
+				if (((CharModelCurator)e).getNEXUSNameOfModelClass().equalsIgnoreCase(modelType)) {
+					readerTask=(CharModelCurator)e;
+				}
+		}
+		return readerTask;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("ASSUMPTIONS") || blockName.equalsIgnoreCase("MESQUITECHARMODELS")) {
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			int format;
+			if (blockName.equalsIgnoreCase("MESQUITECHARMODELS"))
+				format = CharacterModel.MesquiteNEXUSFormat;
+			else
+				format = CharacterModel.NEXUSFormat;
+			String commandName = ParseUtil.getToken(command, startCharT);
+			if (commandName.equalsIgnoreCase("USERTYPE") || commandName.equalsIgnoreCase("CHARMODEL")) {
+				String token = ParseUtil.getToken(command, startCharT);
+				String nameOfModel = (token); // name of model
+				token = ParseUtil.getToken(command, startCharT); //parenthesis
+				String nameOfModelClass = "";
+				if ("(".equalsIgnoreCase(token) || commandName.equalsIgnoreCase("CHARMODEL")) {
+					nameOfModelClass = ParseUtil.getToken(command, startCharT); //name of model class
+					token = ParseUtil.getToken(command, startCharT); //parenthesis
+					token = ParseUtil.getToken(command, startCharT); //=
+				}
+				else {
+					nameOfModelClass = "Stepmatrix";
+					if (!"=".equalsIgnoreCase(token))
+						token = ParseUtil.getToken(command, startCharT); //=
+				}
+				CharModelCurator readerTask = findReader(nameOfModelClass);
+				if (readerTask!=null){
+					CharacterModel model = readerTask.readCharacterModel(nameOfModel, startCharT, command, format);
+		   			if (model!=null) {
+		   				model.addToFile(file, getProject(), this);
+		   				if (comment !=null &&  !comment.isBlank()) {
+		   					String s = comment.toString();
+		   					model.setAnnotation(s.substring(1, s.length()), false);
+		   				}
+		   				return true;
+		   			}
+		   		}
+		   		else {
+		   			
+					String specification = StringUtil.stripLeadingWhitespace(command.substring(startCharT.getValue(), command.length()-1)); //strip leading added 22 Dec 01
+		   			ForeignModel model = new ForeignModel(nameOfModel, nameOfModelClass, commandName, specification);
+		   			model.addToFile(file, getProject(), this);
+		   			return true;
+		   		}
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new CharModelsNexusCmdTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage Character Models";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages character models." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+/*======================================*/
+class CharModelsNexusCmdTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("ASSUMPTIONS")||blockName.equalsIgnoreCase("MESQUITECHARMODELS")) && (commandName.equalsIgnoreCase("USERTYPE")|| commandName.equalsIgnoreCase("CHARMODEL")));
+	}
+}
+
+/*======================================*/
+class ModelNamesLister implements StringLister{
+	MesquiteProject proj;
+	Class subclass;
+	public ModelNamesLister(MesquiteProject proj, Class subclass){
+		this.proj = proj;
+		this.subclass = subclass;
+	}
+	private boolean correctSubclass(CharacterModel c){
+		if (subclass == null)
+			return true;
+		else return (subclass == CharacterModel.class || subclass.isAssignableFrom(c.getClass()));
+	}
+	public String[] getStrings() {
+		int numModels = 0;
+		for (int i=0; i<proj.getNumModels(); i++) {
+			if (!proj.getCharacterModel(i).isBuiltIn() && correctSubclass(proj.getCharacterModel(i)))
+				numModels++;
+		}
+		String[] result = new String[numModels];
+		for (int i=0; i<numModels; i++) {
+			result[i]= "test";
+		}
+		int modelNum=0;
+		for (int i=0; i<proj.getNumModels(); i++) {
+			if (!proj.getCharacterModel(i).isBuiltIn() && correctSubclass(proj.getCharacterModel(i))) {
+				result[modelNum]=proj.getCharacterModel(i).getName();
+				modelNum++;
+			}
+		}
+		return result;
+	}
+	public void dispose(){
+		proj = null;
+	}
+}
+
+/*======================================*/
+class ForeignModel extends CharacterModel{
+	String command;
+	String commandName;
+	String NEXUSClassName;
+	public ForeignModel(String name, String NEXUSClassName, String commandName, String command){
+		super(name, CharacterState.class);
+		this.command = command;
+		this.commandName = commandName;
+		this.NEXUSClassName = NEXUSClassName;
+		setBuiltIn(false);
+	}
+	public String getNEXUSName(){
+		return getName();
+	}
+	
+	public String getNEXUSCommand() {
+		return commandName;
+	}
+	public String getModelTypeName() {
+		return "Unrecognized";
+	}
+	public String getNEXUSClassName(){
+		return NEXUSClassName;
+	}
+	public String getParadigm(){
+		return "unknown";
+	}
+	public String getNexusSpecification(){
+		return command;
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "A unidentified character model (no module available to read or process it)";
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharPartitions/ManageCharPartitions.java b/Source/mesquite/charMatrices/ManageCharPartitions/ManageCharPartitions.java
new file mode 100644
index 0000000..7340153
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharPartitions/ManageCharPartitions.java
@@ -0,0 +1,366 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCharPartitions;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.GroupDialog;
+
+/** Manages specifications of character partitions, including reading and writing from NEXUS files */
+public class ManageCharPartitions extends CharSpecsSetManager {
+	final static String listOfCharacterGroupsName = "List of Character Group Labels";
+
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.CharPartitionList.CharPartitionList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	CharactersGroupVector groups; 
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		groups = new CharactersGroupVector();
+		getProject().addFileElement(groups);
+ 		return true;
+	}
+	public void elementsReordered(ListableVector v){
+	}
+	public NexusBlock elementAdded(FileElement e){
+		if (e instanceof CharactersGroup){
+			if (groups.indexOf(e)<0) {
+				groups.addElement(e, true);
+				e.addListener(groups);
+			}
+			e.setManager(this);
+			return null;
+		}
+		else
+			return super.elementAdded(e);
+	}
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof CharactersGroup){
+			CharactersGroup group = (CharactersGroup)e;
+			GroupDialog d = new GroupDialog(getProject(),getProject().getCoordinatorModule().containerOfModule(), "Edit Character Group", group.getName(), group.getColor(), group.getSymbol(), group.supportsSymbols());
+			d.completeAndShowDialog();
+			String name = d.getName();
+			boolean ok = d.query()==0;
+			Color c = d.getColor();
+			d.dispose();
+			if (!ok)
+				return null;
+
+
+			if (!StringUtil.blank(name)) {
+				group.setName(name);
+			}
+			group.setColor(c);
+			notifyOfGroupChange(group);
+			return null;
+		}
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	public void notifyOfGroupChange(CharactersGroup e){
+		if (e instanceof CharactersGroup){
+			e.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+			ListableVector d = getProject().getCharacterMatrices();
+			for (int im = 0; im<d.size(); im++){
+				CharacterData data = (CharacterData)d.elementAt(im);
+				SpecsSetVector ssv = data.getSpecSetsVector(CharacterPartition.class);
+				CharacterPartition cp = (CharacterPartition)ssv.getCurrentSpecsSet();
+				boolean done = false;
+				if (cp != null)
+					for (int ic = 0; ic< data.getNumChars() && ! done; ic++){
+						if (cp.getCharactersGroup(ic) == e) {
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+							done = true;
+						}
+					}
+				for (int is = 0; is< ssv.size() && !done; is++){
+					cp = (CharacterPartition)ssv.elementAt(is);
+					for (int ic = 0; ic< data.getNumChars() && !done; ic++){
+						if (cp.getCharactersGroup(ic) == e) {
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+							done = true;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public void deleteElement(FileElement e){
+		if (e instanceof CharactersGroup){
+			ListableVector d = getProject().getCharacterMatrices();
+		for (int im = 0; im<d.size(); im++){
+			CharacterData data = (CharacterData)d.elementAt(im);
+			boolean changed = false;
+			SpecsSetVector ssv = data.getSpecSetsVector(CharacterPartition.class);
+			CharacterPartition cp = (CharacterPartition)ssv.getCurrentSpecsSet();
+			if (cp != null)
+				for (int ic = 0; ic< data.getNumChars(); ic++){
+				if (cp.getCharactersGroup(ic) == e) {
+					cp.setProperty(cp.getDefaultProperty(ic), ic);
+					changed = true;
+				}
+			}
+			for (int is = 0; is< ssv.size(); is++){
+				 cp = (CharacterPartition)ssv.elementAt(is);
+				for (int ic = 0; ic< data.getNumChars(); ic++){
+					if (cp.getCharactersGroup(ic) == e) {
+						cp.setProperty(cp.getDefaultProperty(ic), ic);
+						changed = true;
+					}
+				}
+			}
+			if (changed)
+				data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		}
+		getProject().removeFileElement(e);//must remove first, before disposing
+		groups.removeElement(e, true);
+		e.dispose();
+		}
+	}
+	public void elementDisposed(FileElement e){
+		if (groups!=null)
+			groups.removeElement(e, false);
+	}
+	public void projectEstablished(){
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, listOfCharacterGroupsName, makeCommand("showCharacterGroups",  this));
+//		MesquiteSubmenuSpec mmis2 = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu,"List of Character Groups", makeCommand("showCharacterGroups",  this),  (ListableVector)getProject().taxas);
+//		mmis2.setOwnerModuleID(getID());
+//		mmis2.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		groups.addToFile(getProject().getHomeFile(), getProject(), this);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			 if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals(listOfCharacterGroupsName)) {
+				temp.addLine("showCharacterGroups ", e); 
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	 public ManagerAssistant showCharacterGroupList(Object obj, String listerName){
+	 		//Check to see if already has lister for this
+/*	 		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(obj)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+		*/
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize(listerName));
+			if (lister!=null) {
+				lister.showListWindow(null);
+	 			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+	 				lister.getModuleWindow().setVisible(true);
+	 		}
+		return lister;
+	 		
+}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows list of the character groups", null, commandName, "showCharacterGroups")) {
+					return showCharacterGroupList(null, listOfCharacterGroupsName);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		//return null;
+	}
+	public Class getElementClass(){
+		return CharacterPartition.class;
+	}
+	public String upperCaseTypeName(){
+		return "Character Partition";
+	}
+	public String lowerCaseTypeName(){
+		return "character partition";
+	}
+	public String nexusToken(){
+		return "CHARPARTITION";
+	}
+	
+	private CharactersGroup makeGroup(String name, Parser subcommands, MesquiteFile file){
+			CharactersGroup group = groups.findGroup(name);
+			if (group==null) {
+				group = new CharactersGroup();
+				group.setName(name);
+				group.addToFile(file, getProject(), this);
+				if (groups.indexOf(group)<0) 
+					groups.addElement(group, false);
+			}
+			if (subcommands !=null){ //this should be passed into group to handle?
+				String token = null;
+				while ((token = subcommands.getNextToken())!=null){
+					if (token.equalsIgnoreCase("COLOR")){
+						token = subcommands.getNextToken(); //=
+						token = subcommands.getNextToken(); // (
+						token = subcommands.getNextToken(); // (
+							if (token!=null && token.equalsIgnoreCase("RGB")) {
+								double red = MesquiteDouble.fromString(subcommands.getNextToken()); //Red
+								double green = MesquiteDouble.fromString(subcommands.getNextToken()); //green
+								double blue = MesquiteDouble.fromString(subcommands.getNextToken()); //blue
+								if (MesquiteDouble.isCombinable(red) && MesquiteDouble.isCombinable(green) && MesquiteDouble.isCombinable(blue)){
+									Color c = new Color((float)red, (float)green, (float)blue);
+									group.setColor(c);
+								}
+							}
+					}
+				}
+			}
+			return group;
+	}
+	public Object getSpecification(String token){ //NEED TO PASS FILE
+		return makeGroup(token, null, getProject().getHomeFile());
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CharacterPartition) || !(specification instanceof CharactersGroup))
+			return;
+		CharacterPartition characterPartition = (CharacterPartition)specsSet;
+		characterPartition.setProperty(specification,ic);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		return new CharacterPartition(name, data.getNumChars(), null, data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof CharacterPartition))
+			return null;
+		CharacterPartition characterPartition = (CharacterPartition)specsSet;
+		String s= "";
+		if (characterPartition !=null && (characterPartition.getFile()==file || (characterPartition.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			CharactersGroup[] parts = characterPartition.getGroups();
+			boolean firstTime = true;
+			
+			if (parts!=null)
+				for (int i=0; i<parts.length; i++) {
+					String q = ListableVector.getListOfMatches((Listable[])characterPartition.getProperties(), parts[i], CharacterStates.toExternal(0));
+					if (q != null) {
+						if (!firstTime)
+							sT += ", ";
+						firstTime = false;
+						sT += StringUtil.tokenize(parts[i].getName()) + " : " + q;
+					}
+				}
+			
+			if (!StringUtil.blank(sT)) {
+				s+= "\tCHARPARTITION " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(characterPartition.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+   	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("LABELS")) {
+			String commandName = parser.getFirstToken(command);
+			if ("CHARGROUPLABEL".equalsIgnoreCase(commandName)) {
+				String name = parser.getNextToken();
+				makeGroup(name, parser, file); //pass whole command
+				return true;
+			}
+			return false;
+		}
+		else 
+			return super.readNexusCommand(file, nBlock, blockName, command, comment);
+	}
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("LABELS")) {
+			String s = "";
+			for (int i = 0; i< groups.size(); i++){
+				CharactersGroup cg = (CharactersGroup)groups.elementAt(i);
+				if (cg.getFile() == file){
+					s += "\tCHARGROUPLABEL " + ParseUtil.tokenize(cg.getName());
+					if (cg.colorSet()){
+						Color c = cg.getColor();
+						s += " COLOR = (RGB " + MesquiteDouble.toString(c.getRed()/255.0) + " " + MesquiteDouble.toString(c.getGreen()/255.0) + " " + MesquiteDouble.toString(c.getBlue()/255.0) + ") ";
+					}
+					s += ";" + StringUtil.lineEnding();
+				}
+			}
+			if (StringUtil.blank(s))
+				return null;
+			else
+				return s;
+		}
+		else  {
+			return super.getNexusCommands(file, blockName);
+		}
+		}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new PartitionNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage character partititions";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) character partitions." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class PartitionNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		if ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && commandName.equalsIgnoreCase("CHARPARTITION"))
+			return true;
+		
+		if ((blockName.equalsIgnoreCase("LABELS")) && commandName.equalsIgnoreCase("CHARGROUPLABEL"))
+			return true;
+		
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharWeights/ManageCharWeights.java b/Source/mesquite/charMatrices/ManageCharWeights/ManageCharWeights.java
new file mode 100644
index 0000000..5f1c615
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharWeights/ManageCharWeights.java
@@ -0,0 +1,165 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCharWeights;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages specifications of character weights, including reading the NEXUS command for WTSETs */
+public class ManageCharWeights extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.WeightSetList.WeightSetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public Class getElementClass(){
+		return CharWeightSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Character Weight Set";
+	}
+	public String lowerCaseTypeName(){
+		return "character weight set";
+	}
+	public String nexusToken(){
+		return "WTSET";
+	}
+	public Object getSpecification(String token){
+		MesquiteNumber num = new MesquiteNumber();
+		num.setValue(token);
+		return num;
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CharWeightSet) || !(specification instanceof MesquiteNumber))
+			return;
+		CharWeightSet characterWts = (CharWeightSet)specsSet;
+		characterWts.setValue(ic, (MesquiteNumber)specification);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		return new CharWeightSet(name, data.getNumChars(), data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof CharWeightSet))
+			return null;
+		CharWeightSet wtSet = (CharWeightSet)specsSet;
+		String s= "";
+		if (wtSet !=null && (wtSet.getFile()==file || (wtSet.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			int numChars = data.getNumChars();
+			NumberArray distinctWeights = new NumberArray(numChars);
+			distinctWeights.deassignArray();
+			MesquiteNumber weight = new MesquiteNumber();
+			MesquiteNumber secondWeight = new MesquiteNumber();
+			boolean firstTime = true;
+			for (int iw = 0; iw<numChars; iw++){
+				wtSet.placeValue(iw, weight);
+				if (distinctWeights.findValue(weight)<0){
+					int continuing = 1;
+					distinctWeights.setOpenValue(weight);
+					int lastWritten = -1;
+					if (!firstTime)
+						sT += ", ";
+					firstTime = false;
+					sT += weight.toString() + ": " + CharacterStates.toExternal(iw);
+					for (int ic=iw+1; ic<data.getNumChars(); ic++) {
+						wtSet.placeValue(ic, secondWeight);
+						if (secondWeight.equals( weight)) {
+							if (continuing == 0) {
+								sT += " " + CharacterStates.toExternal(ic);
+								lastWritten = ic;
+								continuing = 1;
+							}
+							else if (continuing == 1) {
+								sT += " - ";
+								continuing = 2;
+							}
+						}
+						else if (continuing>0) {
+							if (lastWritten!= ic-1) {
+								sT += " " + CharacterStates.toExternal(ic-1);
+								lastWritten = ic-1;
+							}
+							else
+								lastWritten = -1;
+							continuing = 0;
+						}
+
+					}
+					if (continuing>1)
+						sT += " " + CharacterStates.toExternal(data.getNumChars()-1) + " ";
+				}
+			} 
+			if (!StringUtil.blank(sT)) {
+				s+= "WTSET " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(wtSet.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new WtsetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage character weight sets";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) character weight sets." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class WtsetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && commandName.equalsIgnoreCase("WTSET"));
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharacters/ManageCharacters.java b/Source/mesquite/charMatrices/ManageCharacters/ManageCharacters.java
new file mode 100644
index 0000000..5a794c7
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharacters/ManageCharacters.java
@@ -0,0 +1,2175 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ManageCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.categ.lib.CategoricalData;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/**  Manages character matrices, including reading and writing from files (for which it relies on managers of the particular data types).
+This has some methods and classes for recording the history of changes of the cells of the matrix.  These functions are not yet publicly available. */
+public class ManageCharacters extends CharactersManager {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Matrix manager";//name must be updated in BasicFileCoord
+	}
+	public String getExplanation() {
+		return "Coordinates the management of character data matrices." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharMatrixFiller.class, "New Character matrices can be created from various sources.",
+		"You can create a new matrix from various sources by selecting items from the Make New Matrix From... submenu of the Characters menu.");
+		e.setAlternativeEmployerLabel("Create and Add Matrix to File/Project");
+		EmployeeNeed e2 = registerEmployeeNeed(CharMatrixManager.class, "Character matrices of different types (continuous, DNA, etc.) have different managing modules",
+		"These are activated automatically.");
+		EmployeeNeed e3 = registerEmployeeNeed(mesquite.lists.CharacterList.CharacterList.class, "The List of Characters window permits viewing and modifying of character properties",
+		"The List of Characters window is available in the Characters menu.");
+	}
+	public void elementsReordered(ListableVector v){
+		if (v == getProject().datas){
+			NexusBlock.equalizeOrdering(v, getProject().getNexusBlocks());
+		}
+	}
+	MesquiteMenuItemSpec calw = null;
+	/*.................................................................................................................*/
+	ListableVector taxas; //local reference to Project's vector of taxa blocks
+	MesquiteSubmenuSpec  listsSubMenu; //submenu to show list windows for character specssets
+	static boolean warnChecksum = true;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(CharMatrixManager.class);
+		setMenuToUse(MesquiteTrunk.charactersMenu);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/* ................................................................................................................. */
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof DataWindowMaker){
+			if (calw != null) calw.setEnabled(getNumListWindows()>0);
+			resetAllMenuBars();
+		}
+	}
+	int getNumListWindows(){
+		int count = 0;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).getName().equals("Character List"))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof CharacterData){
+			CharacterData t = (CharacterData)e;
+			return showMatrixEditor(t);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void deleteElement(FileElement e){
+		if (e instanceof CharacterData){
+			CharacterData t = (CharacterData)e;
+			t.doom();
+			getProject().removeFileElement(t);//must remove first, before disposing
+			t.dispose();
+		}
+	}
+	private String allValid(CharacterData data){
+		for (int ic = 0; ic < data.getNumChars(); ic++)
+			for (int it = 0; it < data.getNumTaxa(); it++){
+				if (!data.isValid(ic, it)){
+					return " char " + (ic+1) + " taxon " + (it+1);
+				}
+			}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		MesquiteProject proj = getProject();
+		for (int i= 0; i<proj.getNumberCharMatrices(); i++){
+			CharacterData data = proj.getCharacterMatrix(i);
+			if (data.getFile() == f){
+				String s = data.checkIntegrity();
+				if (s != null){
+					discreetAlert("Warning: Matrix \"" + data.getName() + "\" has a problem: " + s);
+					MesquiteTrunk.errorReportedDuringRun = true;
+				}
+				else {
+					String result = null;
+					if ((result = allValid(data))!= null){
+						discreetAlert("Warning: Matrix \"" + data.getName() + "\" has a problem: Some character states are invalid.  The file being read may have been corrupted or incorrectly formatted. First problem found:" + result);
+						MesquiteTrunk.errorReportedDuringRun = true;
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteModule showMatrixEditor(CharacterData data){
+		if (isDoomed() || getProject() == null)
+			return null;
+		Object obj = doCommand("showDataWindow", getProject().getCharMatrixReferenceInternal(data), CommandChecker.defaultChecker);
+		if (obj instanceof MesquiteModule)
+			return (MesquiteModule)obj;
+		else
+			return null;
+	}
+	public MesquiteModule getListOfCharactersModule(CharacterData data, boolean showIfClosed){
+		boolean found = false;
+		if (data == null)
+			return null;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(data)&& ((ManagerAssistant)e).getName().equals("Character List")) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					if (calw != null) calw.setEnabled(getNumListWindows()>0);
+					resetAllMenuBars();
+					return ((ManagerAssistant)e);
+				}
+		}
+		if (!showIfClosed)
+			return null;
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Character List"));
+		if (lister!=null) {
+			lister.showListWindow(data);
+			if (calw != null) calw.setEnabled(true);
+			resetAllMenuBars();
+			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+				lister.getModuleWindow().setVisible(true);
+		}
+		return lister;
+	}
+	/*.................................................................................................................*/
+	MesquiteModule showCharactersList(CharacterData data){
+		boolean found = false;
+		if (data == null)
+			MesquiteMessage.warnProgrammer("Data null in showCharactersList in ManageCharacters");
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(data)&& ((ManagerAssistant)e).getName().equals("Character List")) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					if (calw != null) calw.setEnabled(getNumListWindows()>0);
+					resetAllMenuBars();
+					return ((ManagerAssistant)e);
+				}
+		}
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Character List"));
+		if (lister!=null) {
+			lister.showListWindow(data);
+			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null){
+				lister.getModuleWindow().setVisible(true);
+			}
+				if (calw != null) calw.setEnabled(getNumListWindows()>0);
+				resetAllMenuBars();
+		}
+		return lister;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "-", null);
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "List of Characters", makeCommand("showCharacters",  this),  (ListableVector)getProject().datas);
+		calw = getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "Close All Lists of Characters", makeCommand("closeAllListWindows",  this));
+		calw.setEnabled(false);
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "-", null);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "List of Character Matrices", makeCommand("showDatasList",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "Delete Character Matrices...", makeCommand("deleteMatrices",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "New Empty Matrix...", makeCommand("newMatrix",  this));
+		getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Make New Matrix from", makeCommand("newFilledMatrix",  this), CharMatrixFiller.class);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "New Linked Matrix...", makeCommand("newLinkedMatrix",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "-", null);
+		getFileCoordinator().addModuleMenuItems( MesquiteTrunk.charactersMenu, makeCommand("newAssistant",  getFileCoordinator()), FileAssistantM.class);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.charactersMenu, "-", null);
+		taxas = getProject().getTaxas();
+		taxas.addListener(this);
+		listsSubMenu = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Lists");
+		listsSubMenu.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		super.projectEstablished();
+	}
+	public MesquiteSubmenuSpec getListsSubmenu(){
+		return listsSubMenu;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxas!=null)
+			taxas.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void exportMatrix(CharacterData data, String path) {
+		if (data==null)
+			return;
+		incrementMenuResetSuppression();
+		Taxa taxa = data.getTaxa();
+
+		FileCoordinator coord = getFileCoordinator();
+		MesquiteFile tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(path), CommandChecker.defaultChecker); //TODO: never scripting???
+		TaxaManager taxaManager = (TaxaManager)findElementManager(Taxa.class);
+		Taxa newTaxa =taxa.cloneTaxa();
+		newTaxa.addToFile(tempDataFile, null, taxaManager);
+
+		CharacterData newData = data.cloneData();
+		newData.setName(data.getName());
+		newData.addToFile(tempDataFile, getProject(), null);
+		coord.writeFile(tempDataFile);
+		tempDataFile.close();
+		decrementMenuResetSuppression();
+	}
+	/*.................................................................................................................*/
+	/** check if any adjustments are needed before writing, .e.g. resolve name conflicts.  Format is file type, e.g. NEXUS, NEXML. */
+	public void preWritingCheck(MesquiteFile file, String format){	
+		if (format.equalsIgnoreCase("NEXUS")){
+			int numSets = getProject().getNumberCharMatrices();
+			ListableVector datas = getProject().getCharacterMatrices();
+			String[] names = new String[numSets];
+			boolean changed = false;
+			String changes = "";
+			for (int i=0; i<numSets; i++) {
+				CharacterData data = getProject().getCharacterMatrix(i);
+				if (data.getFile() == file && data.getWritable()){
+					String cName = data.getName();
+					if (StringArray.indexOf(names, cName)>=0){
+						data.setName(datas.getUniqueName(cName));
+						changed = true;
+						changes += " " + cName + " renamed to " + data.getName();
+					}
+					else
+						names[i] = data.getName();
+				}
+			}
+			if (changed)
+				discreetAlert("Some character matrices had the same name (i.e., the same title).  This is not permitted in NEXUS files; some names were changed (" + changes + ")");
+		}
+	}
+	/*.................................................................................................................*/
+	void deleteTaxa(Taxa taxa){
+		if (taxa==null)
+			return;
+		boolean someDeleted = true;
+		while (someDeleted){
+			someDeleted = false;
+			int numSets = getProject().getNumberCharMatrices(taxa);
+			for (int i=numSets; i>=0 && !someDeleted ; i--) {
+				CharacterData data = getProject().getCharacterMatrix(taxa, i);
+				if (data!=null && data.getTaxa()==taxa) {
+					getProject().removeFileElement(data);//must remove first, before disposing
+					someDeleted = true;
+					data.dispose();
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	void deleteMatricesWithoutTaxa(){
+		if (taxas==null)
+			return;
+		Listable[] datas = getProject().getCharacterMatrices().getListables();
+		for (int i = 0; i<datas.length; i++) {
+			CharacterData data = (CharacterData)datas[i];
+			if (data!=null && taxas.indexOf(data.getTaxa())<0) {
+				getProject().removeFileElement(data);//must remove first, before disposing
+			}
+		}
+		for (int i = 0; i<datas.length; i++) {
+			CharacterData data = (CharacterData)datas[i];
+			if (data!=null && taxas.indexOf(data.getTaxa())<0) {
+				data.dispose();
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa) {
+			deleteTaxa((Taxa)obj);
+
+		}
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == taxas && (code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_CHANGED)) {
+			deleteMatricesWithoutTaxa();
+
+		}
+	}
+	//
+	public String[] dataClassesAvailable() {
+		int count =0;
+		for (int i = 0; i<getNumberOfEmployees() ; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager) 
+				count++;
+		}
+		String[] names = new String[count];
+		count =0;
+		for (int i = 0; i<getNumberOfEmployees() ; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager) {
+				names[count] = ((CharMatrixManager)e).getDataClassName();
+				count++;
+			}
+		}
+		return names;
+	}
+	/*.................................................................................................................*/
+	public CharacterData newCharacterData(Taxa taxa, int numChars, String dataType) {
+		CharMatrixManager manager = findCharacterTypeManager(dataType);
+		if (manager == null )
+			return null;
+		return manager.getNewData(taxa, numChars);
+	}
+	/*.................................................................................................................*/
+	public CharMatrixManager findCharacterTypeManager(String dataType) {
+		if (dataType == null)
+			return null;
+		for (int i = 0; i<getNumberOfEmployees() ; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager) {
+				if (dataType.equalsIgnoreCase(((CharMatrixManager)e).getDataClassName())) {
+					return ((CharMatrixManager)e);
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public CharMatrixManager findCharacterTypeManager(Class dataClass) {
+		if (dataClass == null)
+			return null;
+		for (int i = 0; i<getNumberOfEmployees() ; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager) {
+				if (dataClass == ((CharMatrixManager)e).getDataClass()) {
+					return ((CharMatrixManager)e);
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		NexusBlock nb = findNEXUSBlock(e);
+		if (nb!=null)
+			removeNEXUSBlock(nb);
+	}
+	/*.................................................................................................................*/
+	public NexusBlock elementAdded(FileElement data){
+		if (data == null || !(data instanceof CharacterData))
+			return null;
+		resetAllMenuBars();
+		NexusBlock nb = findNEXUSBlock(data);
+		if (nb==null) {
+			CharactersBlock cb = new CharactersBlock(data.getFile(), this);
+			cb.setData((CharacterData)data);
+			addNEXUSBlock(cb);
+			return cb;
+		}
+		else return nb;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getIDSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (file == null || file == getProject().getHomeFile()){
+			int count = 0;
+			String addendum = "";
+			if (MesquiteTrunk.errorReportedDuringRun)
+				addendum = " errorReportedDuringRun";
+			if (MainThread.emergencyCancelled)
+				addendum += " emergencyCancelDuringRun";
+
+			for (int i = 0; i< getProject().getNumberCharMatrices(); i++) {
+				CharacterData data = getProject().getCharacterMatrix(i);
+				if (data.getWritable()){
+					String dAnd = "";
+					if (data.badImport)
+						dAnd = " errorDuringImport";
+					if (StringUtil.blank(data.getUniqueID()))
+						temp.addLine("setID " + count + " " + data.getAssignedIDNumber());
+					else
+						temp.addLine("setID " + count + " " + data.getAssignedIDNumber() + " " + data.getUniqueID());
+					Snapshot fromMatrix = data.getSnapshot(file);
+					if (fromMatrix != null && fromMatrix.getNumLines() > 0) {
+						temp.addLine("tell It");
+						temp.incorporate(fromMatrix, true);
+						temp.addLine("endTell");
+					}
+
+					temp.addLine("mqVersion " + MesquiteTrunk.mesquiteTrunk.getVersionInt());
+					temp.addLine("checksumv " + count + " " + CharacterData.getCurrentChecksumVersion() + " " + data.getChecksumForFileRecord(CharacterData.getCurrentChecksumVersion()) + " " + data.getUniqueID() + "  " + data.getChecksumSummaryString() + "  " + getProjectStatus(data) + addendum + dAnd);
+					temp.addLine("mqVersion");
+					count++;
+				}
+			}
+		}
+		return temp;
+	}
+	int lastWriterVersion = MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		/*
+ 		if (file == null || file == getProject().getHomeFile()){
+	 		for (int i = 0; i< getProject().getNumberCharMatrices(); i++) {
+	 			temp.addLine("setID " + i + " " + getProject().getCharacterMatrix(i).getAssignedID());
+  	 			Snapshot fromMatrix = getProject().getCharacterMatrix(i).getSnapshot(file);
+		  	 	if (fromMatrix != null && fromMatrix.getNumLines() > 0) {
+					temp.addLine("tell It");
+					temp.incorporate(fromMatrix, true);
+					temp.addLine("endTell");
+	 			}
+	 			temp.addLine("checksum " + i + " " + getProject().getCharacterMatrix(i).getChecksum());
+	 		}
+ 		}
+		 */
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Character Matrices List")) {
+				temp.addLine("showDatasList ", e); 
+			}
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Character List")) {
+				CharacterData data = (CharacterData)e.doCommand("getData", null, CommandChecker.defaultChecker);
+				if (data != null)
+					temp.addLine("showCharacters " + getProject().getCharMatrixReferenceExternal(data), e); //getProject().getMatrixNumber(data), e); 
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public MesquiteFile chooseFile( CharacterData data){  //changed 13 Dec 01 to specify data so as to do check on which file can be
+		MesquiteFile file=null;
+		Taxa taxa = data.getTaxa();
+		if (getProject().getNumberLinkedFiles()==1)
+			file = getProject().getHomeFile();
+		else if (MesquiteThread.isScripting())
+			file = taxa.getFile();
+		else {
+			Listable[] files = getProject().getFiles().getElementArray();
+			if (files.length >1) {
+				int count = 0;
+				boolean taxaFound = false;
+				for (int i=0; i<files.length; i++) {
+					if (!taxaFound && files[i] == taxa.getFile())
+						taxaFound = true;
+					if (taxaFound)
+						count++;
+				}
+				if (count!=files.length){
+					Listable[] legalFiles = new Listable[count];
+					count = 0;
+					taxaFound = false;
+					for (int i=0; i<files.length; i++) {
+						if (!taxaFound && files[i] == taxa.getFile())
+							taxaFound = true;
+
+						if (taxaFound) {
+							legalFiles[count] = files[i];
+							count++;
+						}
+					}
+					files = legalFiles;
+				}
+
+			}
+			if (files.length == 1)
+				return (MesquiteFile)files[0];
+			file = (MesquiteFile)ListDialog.queryList(containerOfModule(), "Select file", "Select file to which to add the new character matrix",MesquiteString.helpString, files, 0);
+		}
+		return file;
+	}
+	String getProjectStatus(CharacterData data){
+		//indicate whether file is linked, number of linked files, number of matrices total in project
+		String s = "";
+		MesquiteFile f = data.getFile();
+		if (f != getProject().getHomeFile())
+			s += " InLinked ";
+		s += " NumFiles " + getProject().getNumberLinkedFiles();
+		s += " NumMatrices " + getProject().getNumberCharMatrices();
+		return s;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Creates a new empty character data matrix", "[number of characters] [title] [data type name]", commandName, "newMatrix")) {
+			//ask user how which taxa, how many characters
+			//create chars block and add to file
+			//return chars
+			incrementMenuResetSuppression();
+			CharacterData newMatrix=null;
+			Taxa taxa = null;
+			if (getProject().getNumberTaxas()==0) {
+				alert("Data matrix cannot be created until taxa exist in file.");
+				decrementMenuResetSuppression();
+				return null;
+			}
+			else {
+				String tx = parser.getFirstToken(arguments);
+				if (!StringUtil.blank(tx) && tx.equalsIgnoreCase("taxa")){
+					parser.getNextToken(); //=
+					long id = MesquiteLong.fromString(parser.getNextToken());
+					if (MesquiteLong.isCombinable(id))
+						taxa = getProject().getTaxaByID(id);
+					arguments = arguments.substring(parser.getPosition(), arguments.length());
+				}
+				if (taxa == null)
+					taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to create a new character matrix?");
+			}
+			if (taxa==null){
+				decrementMenuResetSuppression();
+				return null;
+			}
+			int numChars= 1;
+			String title= getProject().getCharacterMatrices().getUniqueName("Character Matrix");
+			String dataTypeName = CategoricalData.DATATYPENAME;
+			MesquiteBoolean answer = new MesquiteBoolean(true);
+			if (StringUtil.blank(arguments)) {
+				MesquiteInteger buttonPressed = new MesquiteInteger(1);
+				MesquiteInteger ion = new MesquiteInteger(2);
+				MesquiteString iod = new MesquiteString(dataTypeName);
+				MesquiteString ios = new MesquiteString(title);
+				String[] names = dataClassesAvailable();
+
+				String s = "Use this dialog box to create a new, named matrix of characters.  You must choose the type of data from the list.";
+				StringIntegerListDlog dialog = new StringIntegerListDlog(containerOfModule(), "New Character Matrix", "Name of character matrix", "Number of characters", "Type of Data", names,true,ios,ion, iod,1, MesquiteInteger.unassigned, buttonPressed,s);
+
+				answer.setValue((buttonPressed.getValue()==0));
+
+				numChars= ion.getValue();
+				title= ios.getValue();
+				dataTypeName = iod.getValue();
+			}
+			else {
+				MesquiteInteger io = new MesquiteInteger(0);
+				numChars= MesquiteInteger.fromString(arguments, io);
+				title= ParseUtil.getToken(arguments, io);
+				dataTypeName= ParseUtil.getToken(arguments, io);
+			}
+			if (answer.getValue() && numChars>0 && numChars< 10000000) { //TODO: put CONSTANTS here for limits???
+				CharMatrixManager manager = findCharacterTypeManager(dataTypeName);
+				if (manager == null) {
+					decrementMenuResetSuppression();
+					return null;
+				}
+				newMatrix = manager.getNewData(taxa, numChars);
+				if (newMatrix == null) {
+					alert("Sorry, a character data matrix could not be made.  There may be no data matrix types defined.");
+					decrementMenuResetSuppression();
+					return null;
+				}
+				if (title!=null)
+					newMatrix.setName(title);
+
+				MesquiteFile file=chooseFile( newMatrix);
+				newMatrix.addToFile(file, getProject(), this);  
+
+				MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+				if (mb != null)
+					mb.doCommand("showDataWindow", MesquiteInteger.toString(getProject().getNumberCharMatrices()-1), checker);
+			}
+			resetAllMenuBars();
+			decrementMenuResetSuppression();
+			return newMatrix;
+		}
+		else if (checker.compare(this.getClass(), "Shows window for last data matrix", "", commandName, "showLastMatrixWindow")) {
+			MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+			if (mb != null)
+				mb.doCommand("showDataWindow", MesquiteInteger.toString(getProject().getNumberCharMatrices()-1), checker);
+		}
+		else if (checker.compare(this.getClass(), "Saves a copy of the character data matrix to a separate file", "[id number of data matrix]", commandName, "exportMatrix")) {
+			CharacterData d =  getProject().getCharacterMatrixByReference(checker.getFile(), parser.getFirstToken(arguments), true);
+			if (d == null)
+				d =  getProject().getCharacterMatrixByReference(checker.getFile(), parser.getFirstToken(arguments));
+			if (d == null){ //probably not needed but this used to be here
+				int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+				if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberCharMatrices()) {
+					long id  = MesquiteLong.fromString(parser.getNextToken());
+					d = getProject().getCharacterMatrix(t);
+				}
+			}
+			if (d!=null) {
+				String path = MesquiteFile.saveFileAsDialog("Save copy of matrix to file");
+				if (!StringUtil.blank(path))
+					exportMatrix(d, path);
+			}
+
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the ID number of a character data matrix", "[number of matrix][id number of data matrix]", commandName, "setID")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			long id  = MesquiteLong.fromString(parser.getNextToken());
+			String blockID  = parser.getNextToken();
+			if (MesquiteInteger.isCombinable(t) || !StringUtil.blank(blockID)) {
+				if (!StringUtil.blank(blockID) && getNumberCharMatricesWithUniqueID(blockID)==1){
+					CharacterData d = getProject().getCharacterMatrixByUniqueID(blockID, 0);
+					if (d!=null) {
+						d.setAssignedIDNumber(id);
+						return d;
+					}
+				}
+				if (t< getProject().getNumberCharMatrices(CommandRecord.getScriptingFileS())) {
+					CharacterData d = getProject().getCharacterMatrix(CommandRecord.getScriptingFileS(), t);
+					if (d!=null) {
+						d.setAssignedIDNumber(id);
+
+						return d;
+					}
+				}
+				else if (t< getProject().getNumberCharMatrices()) {
+					CharacterData d = getProject().getCharacterMatrix( t);
+					if (d!=null) {
+						d.setAssignedIDNumber(id);
+
+						return d;
+					}
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Indicates version of Mesquite that had saved the file (for ID snapshot)", "[version of Mesquite saving matrix]", commandName, "mqVersion")) {
+			lastWriterVersion = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+
+		}
+		else if (checker.compare(this.getClass(), "Indicates the checksum of a matrix; new version", "[number of matrix][id number of data matrix]", commandName, "checksumv")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			int version  = MesquiteInteger.fromString(parser.getNextToken());
+			long checksumRecorded  = MesquiteLong.fromString(parser.getNextToken());
+			boolean errorReported = (arguments != null && StringUtil.indexOfIgnoreCase(arguments, "errorReportedDuringRun")>=0 || StringUtil.indexOfIgnoreCase(arguments, "emergencyCancelDuringRun")>=0);
+			boolean badImport = (arguments != null && StringUtil.indexOfIgnoreCase(arguments, "errorDuringImport")>=0);
+			String blockID  = parser.getNextToken();
+			CharacterData d = null;
+			boolean usedID = false;
+			if (!StringUtil.blank(blockID) && getNumberCharMatricesWithUniqueID(blockID)==1){
+				d = getProject().getCharacterMatrixByUniqueID(blockID, 0);
+				usedID = true;
+			}
+			else {
+				if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberCharMatrices(CommandRecord.getScriptingFileS())) 
+					d = getProject().getCharacterMatrix(CommandRecord.getScriptingFileS(), t);
+			}
+			if (d!=null) {
+				long checksumAsRead = d.getChecksumForFileRecord(version);
+				if (!d.suppressChecksum && checksumAsRead != checksumRecorded) {
+					//there appears to be a problem, but first check that the matrix wasn't misidentified because a unique ID wasn't used
+					if (!usedID){
+						for (int i = 0; i<getProject().getNumberCharMatrices(); i++){
+							CharacterData cd = getProject().getCharacterMatrix(i);
+							long checksumI = cd.getChecksumForFileRecord(version);
+							if (checksumI == checksumRecorded){  //OK, other matrix found with this checksum; assumed to be OK
+								cd.suppressChecksum = false;  //other matrix checksum found, so suppress its warnings
+								return null;
+							}
+						}
+					}
+					String warning = "Error: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  Either the matrix has been modified with a program other than Mesquite, or the file had another issue already reported to you, or there is a bug in Mesquite.  If you are unaware of an intentional change, it is recommended that you use Save As to leave the previous copy of the file intact.";
+
+
+					String diffFileSave = "";
+					double diff = 0;
+					if (getProject().timePreviouslySavedAsRecorded != 0 && getProject().timePreviouslySavedByFile != 0)
+						diff = Math.abs(getProject().timePreviouslySavedAsRecorded - getProject().timePreviouslySavedByFile)/1000.0;
+					if (diff > 0) 
+						diffFileSave = "\nFile save time difference from recorded: " + diff;
+					String remainingDetails = parser.getRemaining();
+					String dataDetails = "\nMatrix details:\nChecksumAsRead " + checksumAsRead + "   " + d.getChecksumSummaryString() + getProjectStatus(d) + "\nRecorded details:\nChecksumRecorded " + checksumRecorded + "  " + remainingDetails;
+					String details = "\n[DETAILS for data matrix " + d.getName() + " (" + d.getDataTypeName() + ")" + dataDetails + diffFileSave + "]";
+					details += "\n[recorded block id: " + blockID + "; and of compared matrix: " + d.getUniqueID() + " usedID? " + usedID + "]";
+					if (MesquiteInteger.isCombinable(lastWriterVersion))
+						details += "\n[Written by version " + MesquiteInteger.toString(lastWriterVersion) + "]";
+					else 
+						details += "\n[Written by version: Not Recorded]";
+					if (MesquiteTrunk.errorReportedDuringRun)
+						details += " [NOTE: a crash or other error occurred previously during this current run of Mesquite.  Thus, the checksum error may be a result of that crash or error.]";
+					if (errorReported)
+						details += " [NOTE: a crash or other error had been reported in the run of Mesquite in which the file had been saved.  Thus, the checksum error may be a result of that crash or error.]";
+					if (badImport)
+						details += " [NOTE: This matrix was not read successfully when originally imported.]";
+
+					String integrity = d.checkIntegrity();
+					if (integrity != null) 
+						details += "\n[NOTE: the data matrix appears corrupt; it is possible that it had been saved incorrectly in the file [" + integrity + "]]";
+					ListableVector datas = getProject().getCharacterMatrices();
+					if (datas != null && datas.size() > 1){
+						details += "\nSummary of matrices in file:";
+						for (int i=0; i<datas.size(); i++){
+							CharacterData dd = (CharacterData)datas.elementAt(i);
+							details += "\n    matrix " + dd.getName() + "  ID  " + dd.getUniqueID() + "  for taxa " + dd.getTaxa().getName();
+						}
+					}
+					if (diff>20){//assume file writing is at most 20 seconds off; anything more assumes user fiddling so don't report!!!!
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  This appears to be caused by the file having been modified by a program other than Mesquite.");
+						logln(details);
+					}
+					else if (getProject().timePreviouslySavedAsRecorded == 0){//no record of time saved; may be user fiddling so don't report!!!!
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  This may have been caused by the file having been modified by a program other than Mesquite.");
+						logln(details);
+					}
+					else if (errorReported){//assume file writing had had a problem
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  A crash or other error had been reported in the run of Mesquite in which the file had been saved.  Thus, the checksum error is probably a result of that crash or error..");
+						logln(details);
+					}
+					else if (badImport){//assume file import had had a problem
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  The matrix had not been read successfully when originally imported.  Thus, the checksum error is probably a result of that crash or error..");
+						logln(details);
+					}
+					else if (MesquiteTrunk.errorReportedDuringRun){//assume crash caused the problem
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  A crash or other error occurred previously during this current run of Mesquite.  Thus, the checksum error may be a result of that crash or error.");
+						logln(details);
+					}
+					else if (!MesquiteInteger.isCombinable(lastWriterVersion) && StringUtil.blank(remainingDetails)){
+						logln("Note: checksum on data matrix \"" + d.getName() + "\" (" + d.getDataTypeName() + ") does not match that expected and stored in file.  This file appears to be written by an old version of Mesquite, and no details to help diagnose the issue were written.  The checksum error may be innocent.");
+						logln(details);
+					}
+					else if (!warnChecksum)
+						logln(warning + " If this appears to be due to a bug in Mesquite, please report it to info at mesquiteproject.org." + details);
+					else {
+						if (d.problemReading != null){
+							details += "\n[PROBLEM READING " + d.problemReading + "]";
+							d.problemReading = null;
+						}
+						logln(warning +  details);
+						logln("checksumv arguments as written: " + arguments);
+						reportableAlert(warning, details);
+						if (!errorReported) { // && getProject().timePreviouslySavedAsRecorded != 0){
+							alert("Please send us a copy of your data file.\n\nThe checksum error that was just reported may represent a bug in Mesquite.  It would help us to diagnose this to have a copy of your data file. " +
+							"If possible, please send us a copy of this data file to info at mesquiteproject.org.  We will not release or make any use of your data file except to diagnose possible bugs in Mesquite.");
+						}
+					}
+				}
+				d.suppressChecksum = false;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Indicates the checksum of a matrix.  Old style; for reading old matrices", "[number of matrix][id number of data matrix]", commandName, "checksum")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			long cs  = MesquiteLong.fromString(parser.getNextToken());
+			String blockID  = parser.getNextToken();
+			CharacterData d = null;
+			if (!StringUtil.blank(blockID) && getNumberCharMatricesWithUniqueID(blockID)==1)
+				d = getProject().getCharacterMatrixByUniqueID(blockID, 0);
+			else if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberCharMatrices(CommandRecord.getScriptingFileS())) 
+				d = getProject().getCharacterMatrix(CommandRecord.getScriptingFileS(), t);
+			if (d!=null) {
+				if (!d.suppressChecksum && d.getChecksum() != cs) {
+					String warning = "Error: checksum on data matrix \"" + d.getName() + "\" does not match that expected and stored in file.  Either the matrix has been modified with a program other than Mesquite, or there is a bug in Mesquite.  If you are unaware of an intentional change, it is recommended that you use Save As to leave the previous copy of the file intact.  If this appears to be due to a bug in Mesquite, please report it to info at mesquiteproject.org";
+					if (!warnChecksum)
+						logln(warning);
+					else if (!AlertDialog.query(containerOfModule(), "Checksum doesn't match",warning + "\n\nYou may suppress warnings of this type within this run of Mesquite.", "Continue", "Suppress warnings"))
+						warnChecksum = false;
+				}
+				d.suppressChecksum = false;
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Creates a new character data matrix linked to an existing one (i.e. characters in the two matrixes are associated 1:1, forcing the two matrices to maintain the same number of characters).", "[number of data matrix with which to be linked] [title] [data type name]", commandName, "newLinkedMatrix")) {
+			//ask user how which taxa, how many characters
+			//create chars block and add to file
+			//return chars
+			incrementMenuResetSuppression();
+			CharacterData newMatrix=null;
+			Taxa taxa = null;
+			if (getProject().getNumberTaxas()==0) {
+				alert("Data matrix cannot be created until taxa exist in file.");
+				decrementMenuResetSuppression();
+				return null;
+			}
+
+			CharacterData other=null;
+			String title= getProject().getCharacterMatrices().getUniqueName("Character Matrix");
+			String dataTypeName = CategoricalData.DATATYPENAME;
+			MesquiteBoolean answer = new MesquiteBoolean(true);
+			if (StringUtil.blank(arguments)) {
+
+				MesquiteInteger buttonPressed = new MesquiteInteger(1);
+				ExtensibleExplDialog makeLinkedDialog = new ExtensibleExplDialog(containerOfModule(), "Make Linked Matrix",buttonPressed);
+				makeLinkedDialog.setExplainable(new MesquiteString("With this you create a new character matrix that is linked to an existing one.  By being linked, the two matrices are constrained to have the same number of characters.  If characters are deleted from or added to one matrix, the corresponding characters will be deleted from or added to the other.")); 
+				java.awt.List types = makeLinkedDialog.addList(dataClassesAvailable(), new MesquiteInteger(0), "Make new character matrix of what type?");
+				SingleLineTextField nameTaxa = makeLinkedDialog.addTextField("Name of new matrix", "Character Matrix", 30);
+				java.awt.List linkTo = makeLinkedDialog.addList(getProject().getCharacterMatrices(), new MesquiteInteger(0), "Link new matrix to which matrix?");
+
+				makeLinkedDialog.completeAndShowDialog(true);
+
+				if (buttonPressed.getValue()==0) {
+					other = getProject().getCharacterMatrix(linkTo.getSelectedIndex());
+					dataTypeName = types.getSelectedItem();
+					title = nameTaxa.getText();
+				}
+				if (other==null || dataTypeName == null){
+					decrementMenuResetSuppression();
+					return null;
+				}
+			}
+			else {
+				MesquiteInteger io = new MesquiteInteger(0);
+				int otherNum= MesquiteInteger.fromString(arguments, io);
+				if (!MesquiteInteger.isCombinable(otherNum)){
+					decrementMenuResetSuppression();
+					return null;
+				}
+				other = getProject().getCharacterMatrix(otherNum);
+				if (other==null) {
+					decrementMenuResetSuppression();
+					return null;
+				}
+				title= ParseUtil.getToken(arguments, io);
+				dataTypeName= ParseUtil.getToken(arguments, io);
+			}
+
+			newMatrix = newCharacterData(other.getTaxa(), other.getNumChars(), dataTypeName);
+			if (newMatrix == null) {
+				alert("Sorry, a character data matrix could not be made.  There may be no data matrix types defined.");
+				decrementMenuResetSuppression();
+				return null;
+			}
+			MesquiteFile file=chooseFile( newMatrix);
+			if (title!=null)
+				newMatrix.setName(title);
+			other.addToLinkageGroup(newMatrix);
+
+			newMatrix.addToFile(file, getProject(), this);  //TODO: which file to add to??  how to choose?
+
+			MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+			if (mb != null)
+				mb.doCommand("showDataWindow", MesquiteInteger.toString(getProject().getNumberCharMatrices()-1), checker);
+			newMatrix.resetCellMetadata();
+
+			resetAllMenuBars();
+			decrementMenuResetSuppression();
+			return newMatrix;
+		}
+		else if (checker.compare(this.getClass(), "Creates a new character data matrix filled as requested", "[name of module to fill the matrix]", commandName, "newFilledMatrix")) {
+			//ask user how which taxa, how many characters
+			//create chars block and add to file
+			//return chars
+			CharacterData newMatrix=null;
+			Taxa taxa = null;
+			if (getProject().getNumberTaxas()==0) {
+				alert("Data matrix cannot be created until taxa exist in file.");
+				return null;
+			}
+			else 
+				taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to create a new character matrix?");
+			if (taxa == null)
+				return null;
+
+			CharMatrixFiller characterSourceTask;
+			if (StringUtil.blank(arguments))
+				characterSourceTask = (CharMatrixFiller)hireEmployee(CharMatrixFiller.class, "Fill matrix with characters from:");
+			else
+				characterSourceTask = (CharMatrixFiller)hireNamedEmployee(CharMatrixFiller.class, arguments);
+			if (characterSourceTask != null) {
+				getProject().incrementProjectWindowSuppression();
+				int num = characterSourceTask.getNumberOfMatrices(taxa);
+				int whichMatrix;
+				if (num != 1 && MesquiteInteger.isCombinable(num)) // num != 1 added 8 Dec 01
+					whichMatrix = characterSourceTask.queryUserChoose(taxa, " to use as new stored matrix");
+				else
+					whichMatrix = 0;
+				MCharactersDistribution matrix = characterSourceTask.getMatrix(taxa, whichMatrix);
+				if (matrix==null) {
+					fireEmployee(characterSourceTask);
+					getProject().decrementProjectWindowSuppression();
+					return null;
+				}
+				CharMatrixManager manager = findCharacterTypeManager(matrix.getDataTypeName());
+				if (manager == null) {
+					fireEmployee(characterSourceTask);
+					getProject().decrementProjectWindowSuppression();
+					return null;
+				}
+				newMatrix = matrix.makeCharacterData(manager, taxa);
+				if (matrix.getParentData()!=null){
+					CharacterData parent = matrix.getParentData();
+					if (parent.characterNamesExist()){
+						for (int ic=0; ic<parent.getNumChars() && ic<matrix.getNumChars(); ic++)
+							newMatrix.setCharacterName(ic, parent.getCharacterName(ic));
+					}
+					CharWeightSet weightSet= (CharWeightSet)parent.getCurrentSpecsSet(CharWeightSet.class);  //DRM added 1 May 14
+					if (weightSet!=null) {
+						newMatrix.setCurrentSpecsSet(weightSet, CharWeightSet.class); 
+					}
+				}
+				String name = MesquiteString.queryShortString(containerOfModule(), "Name Matrix", "Name of New Matrix", getProject().getCharacterMatrices().getUniqueName(matrix.getName()));
+				if (name == null){
+					fireEmployee(characterSourceTask);
+					getProject().decrementProjectWindowSuppression();
+					return null;
+				}
+				newMatrix.setName(name);
+				MesquiteFile file=chooseFile( newMatrix);
+				newMatrix.addToFile(file, getProject(), this);  
+
+				MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+				if (mb != null)
+					mb.doCommand("showDataWindow", MesquiteInteger.toString(getProject().getNumberCharMatrices()-1), checker);
+				else
+					MesquiteMessage.warnProgrammer("NO DATA WINDOW COORDINATOR");
+				fireEmployee(characterSourceTask);
+				getProject().decrementProjectWindowSuppression();
+				resetAllMenuBars();
+				newMatrix.resetCellMetadata();
+				return newMatrix;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows list of data matrices", null, commandName, "showDatasList")) {
+			//Check to see if already has lister for this
+			boolean found = false;
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if (((ManagerAssistant)e).getName().equals("Character Matrices List")) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return e;
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Character Matrices List"));
+			if (lister==null){
+				alert("Sorry, no module was found to list the character data matrices");
+				return null;
+			}
+			lister.showListWindow(null);
+			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+				lister.getModuleWindow().setVisible(true);
+			return lister;
+		}
+		else if (checker.compare(this.getClass(), "Deletes matrices from the project", null, commandName, "deleteMatrices")) {
+			Listable[] chosen = ListDialog.queryListMultiple(containerOfModule(), "Select Matrices to Delete", "Select one or more character matrices to be deleted", (String)null, "Delete", false, getProject().getCharacterMatrices(), (boolean[])null);
+			if (chosen != null){
+				for (int i = chosen.length-1; i>=0; i--) {  
+					((FileElement)chosen[i]).doom();
+				}
+				getProject().incrementProjectWindowSuppression();
+				for (int i = chosen.length-1; i>=0; i--) {  
+					logln("Deleting " + chosen[i].getName());
+					deleteElement((FileElement)chosen[i]);
+				}
+				getProject().decrementProjectWindowSuppression();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deletes all matrices from the project", null, commandName, "deleteAllMatrices")) {
+			for (int i = getProject().getNumberCharMatrices(); i>=0; i--) {  
+				CharacterData data = getProject().getCharacterMatrixDoomedOrNot(i);
+				data.doom();
+			}
+			for (int i = getProject().getNumberCharMatrices(); i>=0; i--) {  
+				CharacterData data = getProject().getCharacterMatrixDoomedOrNot(i);
+				deleteElement(data);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Concatenates all matrices of a given type into the first matrix of that type", "[file id to move all matrices to]", commandName, "concatenateAllMatrices")) {
+			int fileID = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			MesquiteFile file = null;
+			if (MesquiteInteger.isCombinable(fileID))
+				file = getProject().getFileByID(fileID);
+
+			for (int i = getProject().getNumberCharMatrices()-1; i>=1; i--) {  
+				if (getProject().getNumberCharMatrices() == 1)
+					return null;
+				CharacterData data = getProject().getCharacterMatrix(i);
+				//now look to find previous matrix of same type and taxa, concatenate
+				for (int j = i-1; j>=0; j--) {  
+					CharacterData previous = getProject().getCharacterMatrix(j);
+
+					if (previous.getTaxa() == data.getTaxa() && data.getClass() == previous.getClass()) {
+						//concatenate matrices
+						int origNumChars = previous.getNumChars();
+						previous.addParts(previous.getNumChars()+1, data.getNumChars());
+						previous.addInLinked(previous.getNumChars()+1, data.getNumChars(), true);
+						CharacterState cs = null;
+						for (int it = 0; it<previous.getNumTaxa() && it<data.getNumTaxa(); it++){
+							for (int ic = 0; ic<data.getNumChars(); ic++){
+								cs= data.getCharacterState(cs, ic, it);
+								previous.setState(ic+origNumChars, it, cs);
+								if (data.characterHasName(ic))
+									previous.setCharacterName(ic+origNumChars, data.getCharacterName(ic));
+								//note that does not set other stuff (state names, weights, footnotes)
+							}
+						}
+						previous.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {origNumChars, data.getNumChars()}));
+						//delete second
+						deleteElement(data);
+						j = -1; //do this to pop out of the loop
+					}
+				}
+			}
+			if (file != null){
+				ElementManager em = findElementManager(Taxa.class);
+
+				int numM = getProject().getNumberCharMatrices();
+				for (int i = 0; i<numM; i++) {
+					CharacterData data = getProject().getCharacterMatrix(i);
+					CharacterData clone = data.cloneData();
+					Taxa taxaClone = data.getTaxa().cloneTaxa();
+					taxaClone.addToFile(file, getProject(), em);
+					clone.addToFile(file, getProject(), this);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows the character list window for a specified data matrix; if a list window already exists, show it", "[optional: number of matrix to show]", commandName, "showCharacters")) {
+			if (StringUtil.blank(arguments)) {
+				for (int i = 0; i< getProject().getNumberCharMatrices(); i++) {  //restriction to checker.getFile() deleted 13 Dec 01
+					CharacterData data = getProject().getCharacterMatrix(i);
+					if (data!=null && data.isUserVisible())
+						showCharactersList(data);//restriction to checker.getFile() deleted 13 Dec 01
+				}
+				return null;
+			}
+			else {
+				// in general, will only show user visible matrices.  However, if arguments starts with #, then assume a direct, non-numbered request that will be obeyed even if not user visible
+				//Check to see if already has lister for this
+				CharacterData data =  getProject().getCharacterMatrixByReference(checker.getFile(), parser.getFirstToken(arguments), !arguments.startsWith("#"));  
+				if (data != null){
+					return showCharactersList(data);
+				}
+				int t = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (MesquiteInteger.isCombinable(t) && t<getProject().getNumberCharMatrices()) {//restriction to checker.getFile() deleted 13 Dec 01
+					data = getProject().getCharacterMatrix(t, true);//restriction to checker.getFile() deleted 13 Dec 01
+					return showCharactersList(data);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes all list of characters windows", null, commandName, "closeAllListWindows")) {
+			for (int i = getNumberOfEmployees()-1; i>=0; i--) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant &&  ((ManagerAssistant)e).getName().equals("Character List")){
+					((ManagerAssistant)e).windowGoAway(((ManagerAssistant)e).getModuleWindow());
+				}
+			}
+			if (calw != null) calw.setEnabled(false);
+			resetAllMenuBars();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Shows the data editor window for a specified data matrix; if a data window already exists, show it", "[number of matrix to show]", commandName, "showDataWindow")) {
+			//Check to see if already has lister for this
+			MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+			if (mb != null)
+				return mb.doCommand("showDataWindow", arguments, checker);
+			/*	int t = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(t) && t<getProject().getNumberCharMatrices()) {
+				MesquiteModule mb = findNearestColleagueWithName("Data Window Coordinator");
+				if (mb != null)
+					return mb.doCommand("showDataWindow", MesquiteInteger.toString(t), checker);
+			}*/
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns number of data sets of given reference string (ref. number, name, number) from the project */
+	public int  getNumberCharMatricesWithUniqueID(String uniqueID) {  //ManageCharacters Only
+		ListableVector datasVector = getProject().getCharacterMatrices();
+		int count = 0;
+		for (int i=0; i<datasVector.size(); i++) {
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datasVector.elementAt(i);
+			if (!data.isDoomed() && data.getUniqueID() != null && uniqueID != null && uniqueID.equals(data.getUniqueID())) {
+				count++;
+			}
+		}
+
+		return count;  
+	}
+
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new CharactersBlockTest();}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new CHARNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public CharMatrixManager getMatrixManager(Class dataClass) {
+		CharMatrixManager readerTask=null;
+		for (int i = 0; i<getNumberOfEmployees() && readerTask==null; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager)
+				if (((CharMatrixManager)e).readsWritesDataType(dataClass)) {
+					readerTask=(CharMatrixManager)e;
+				}
+		}
+		return readerTask;
+	}
+	/*.................................................................................................................*/
+	public CharMatrixManager findReader(String dataType) {
+		CharMatrixManager readerTask=null;
+		for (int i = 0; i<getNumberOfEmployees() && readerTask==null; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof CharMatrixManager)
+				if (((CharMatrixManager)e).readsWritesDataType(dataType)) {
+					readerTask=(CharMatrixManager)e;
+				}
+		}
+		return readerTask;
+	}
+
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String formatCommand, int numChars, String title, String fileReadingArguments) {
+		CharacterData data=null;
+		MesquiteInteger startCharF = new MesquiteInteger(0);
+
+		String tok = ParseUtil.getToken(formatCommand, startCharF);
+		String dataType = "Standard";
+		//Finding datatype (done first in case datatype subcommand is illegally written other than first, as by Clustal
+		while (tok != null && !tok.equals(";")) {
+			if (tok.equalsIgnoreCase("DATATYPE")) {
+				tok = ParseUtil.getToken(formatCommand, startCharF); //eat up "="
+				dataType = ParseUtil.getToken(formatCommand, startCharF); //find datatype
+			}
+			tok = ParseUtil.getToken(formatCommand, startCharF);
+		}
+		//processing format
+		startCharF.setValue(0);
+		CharMatrixManager readerTask= findReader(dataType);
+		if (readerTask !=null)
+			data = readerTask.processFormat(file, taxa, dataType, formatCommand, startCharF, numChars, title, fileReadingArguments);
+		else 
+			return null;
+
+		/*int previousPos =0;
+		startCharF.setValue(0);
+		while (tok != null && !tok.equals(";")) {
+			if (tok.equalsIgnoreCase("DATATYPE")) {
+				tok = ParseUtil.getToken(formatCommand, startCharF); //eat up "="
+				tok = ParseUtil.getToken(formatCommand, startCharF); //find datatype
+
+				CharMatrixManager readerTask= findReader(tok);
+				if (readerTask !=null)
+					data = readerTask.processFormat(file, taxa, tok, formatCommand, startCharF, numChars, title, fileReadingArguments);
+				else 
+					return null;
+			}
+			else if (!(tok.equalsIgnoreCase("FORMAT"))) {
+				if (data==null) {
+
+					CharMatrixManager readerTask= findReader("Standard");
+					if (readerTask !=null) {
+						startCharF.setValue(previousPos);
+						data = readerTask.processFormat(file, taxa, tok, formatCommand, startCharF, numChars, title, fileReadingArguments);
+						return data;
+					}
+					else 
+						return null;
+				}
+
+			}
+			previousPos = startCharF.getValue();
+			tok = ParseUtil.getToken(formatCommand, startCharF);
+		}
+		 */
+		return data;
+	}
+
+	/*ABBREVIATIONS NEW to 1. 06:
+	SU Supplemental
+	C Character
+	T Taxon
+	N Name
+	I Integer
+	R Real
+	S String
+	 */					
+	static final String suppTokenAbbrev = "\tSU ";
+	static final String suppTMTokenAbbrev = "\tSUTM ";
+	static final String characterTokenAbbrev = " C = ";
+	static final String taxonTokenAbbrev = " T = ";
+	static final String nameTokenAbbrev = " N = ";
+	static final String intTokenAbbrev = " I = ";
+	static final String realTokenAbbrev = " R = ";
+	static final String booleanTokenAbbrev = " B = ";
+	static final String stringTokenAbbrev = " S = ";
+	static final String stringArrayTokenAbbrev = " SE = ";
+	static final String characterToken = " CHARACTER = ";
+	static final String taxonToken = " TAXON = ";
+	static final String textToken = " TEXT = ";
+	NameReference commentsRef = NameReference.getNameReference("comments");
+	/*.................................................................................................................*/
+	public boolean writeNexusCommands(MesquiteFile file, String blockName, MesquiteString pending){ 
+		boolean found = false;
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			StringBuffer s = new StringBuffer(100);
+			StringBuffer tokSB = new StringBuffer(100);
+			MesquiteProject project = file.getProject();
+			for (int i=0; i<project.getNumberCharMatrices(); i++){
+				CharacterData data = getProject().getCharacterMatrix(i);
+				if (data.getFile()==file && data.getWritable()){
+					String eL =";" + StringUtil.lineEnding();
+					if ((project.getNumberCharMatrices()>1  || (!file.useSimplifiedNexus&& !file.useConservativeNexus &&  !data.hasDefaultName() && !NexusBlock.suppressTITLE)) || project.getNumberTaxas()>1) //note shift in 1. 06 to "current matrix and taxa" to avoid having to repeat in each note
+						s.append("\tCHARACTERS = " +  StringUtil.tokenize(data.getName(), null, tokSB) +" TAXA = " +  StringUtil.tokenize(data.getTaxa().getName(), null, tokSB) + eL);
+					String textDataSpec = "\tTEXT  ";
+					Associable as = data.getTaxaInfo(false);
+
+					if (as != null){
+						for (int it = 0; it<data.getNumTaxa(); it++){
+							//look through all attached longs
+							int numLongs = as.getNumberAssociatedLongs();
+
+							for (int v = 0; v<numLongs; v++){  
+								LongArray array = as.getAssociatedLongs(v);
+								long c = array.getValue(it);
+								if (MesquiteLong.isCombinable(c)){
+									s.append(suppTMTokenAbbrev);
+									s.append(taxonTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(it)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									s.append(intTokenAbbrev);
+									s.append(Long.toString(c));
+									s.append(eL);
+									found = true;
+								}
+							}
+							//look through all attached doubles
+							int numDoubs = as.getNumberAssociatedDoubles();
+
+							for (int v = 0; v<numDoubs; v++){  
+								DoubleArray array = as.getAssociatedDoubles(v);
+								double c = array.getValue(it);
+
+								if (MesquiteDouble.isCombinable(c)){
+									s.append(suppTMTokenAbbrev);
+									s.append(taxonTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(it)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									s.append(realTokenAbbrev);
+									s.append(Double.toString(c));
+									s.append(eL);
+									found = true;
+								}
+							}
+
+							//look through all attached booleans
+							int numBools = as.getNumberAssociatedBits();
+
+							for (int v = 0; v<numBools; v++){  
+								Bits array = as.getAssociatedBits(v);
+								boolean c = array.isBitOn(it);
+
+								if (c){
+									s.append(suppTMTokenAbbrev);
+									s.append(taxonTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(it)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									s.append(booleanTokenAbbrev);
+									s.append("TRUE");
+									s.append(eL);
+									found = true;
+								}
+							}
+							//look through all attached objects
+							int numObs = as.getNumberAssociatedObjects();
+
+							for (int v = 0; v<numObs; v++){  
+								ObjectArray array = as.getAssociatedObjects(v);
+								Object c = array.getValue(it);
+
+								if (c != null && c instanceof String){
+									s.append(suppTMTokenAbbrev);
+									s.append(taxonTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(it)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									s.append(stringTokenAbbrev);
+									s.append(StringUtil.tokenize((String)c, null, tokSB));
+									s.append(eL);
+									found = true;
+								}
+								else if (c != null && c instanceof String[] && ((String[])c).length>0){
+									s.append(suppTMTokenAbbrev);
+									s.append(taxonTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(it)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									String[] strings = (String[])c;
+									for (int k = 0; k<strings.length; k++){
+										s.append(stringArrayTokenAbbrev);
+										s.append(StringUtil.tokenize(strings[k], null, tokSB));
+										s.append(' ');
+									}
+									s.append(eL);
+									found = true;
+								}
+
+							}
+
+
+
+						}
+					}
+					for (int ic = 0; ic<data.getNumChars(); ic++){
+						boolean foundForChar = false;
+						String obj = data.getAnnotation(ic);
+						if (!StringUtil.blank(obj)){ //OLD footnotes; maintain non-abbreviated
+							s.append(textDataSpec);
+							s.append(" CHARACTER = ");
+							s.append(Integer.toString(CharacterStates.toExternal(ic)));
+							s.append(" TEXT = ");
+							s.append(StringUtil.tokenize(obj, null, tokSB));
+							s.append(eL);
+							foundForChar = true;
+						}
+
+						//look through all attached longs
+						int numLongs = data.getNumberAssociatedLongs();
+
+						for (int v = 0; v<numLongs; v++){  
+							LongArray array = data.getAssociatedLongs(v);
+							long c = array.getValue(ic);
+							if (MesquiteLong.isCombinable(c)){
+								s.append(suppTokenAbbrev);
+								s.append(characterTokenAbbrev);
+								s.append(Integer.toString(CharacterStates.toExternal(ic)));
+								s.append(nameTokenAbbrev);
+								s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+								s.append(intTokenAbbrev);
+								s.append(Long.toString(c));
+								s.append(eL);
+								foundForChar = true;
+							}
+						}
+						//look through all attached doubles
+						int numDoubs = data.getNumberAssociatedDoubles();
+
+						for (int v = 0; v<numDoubs; v++){  
+							DoubleArray array = data.getAssociatedDoubles(v);
+							double c = array.getValue(ic);
+
+							if (MesquiteDouble.isCombinable(c)){
+								s.append(suppTokenAbbrev);
+								s.append(characterTokenAbbrev);
+								s.append(Integer.toString(CharacterStates.toExternal(ic)));
+								s.append(nameTokenAbbrev);
+								s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+								s.append(realTokenAbbrev);
+								s.append(Double.toString(c));
+								s.append(eL);
+								foundForChar = true;
+							}
+						}
+
+						//look through all attached booleans
+						int numBools = data.getNumberAssociatedBits();
+
+						for (int v = 0; v<numBools; v++){  
+							Bits array = data.getAssociatedBits(v);
+							boolean c = array.isBitOn(ic);
+
+							if (c){
+								s.append(suppTokenAbbrev);
+								s.append(characterTokenAbbrev);
+								s.append(Integer.toString(CharacterStates.toExternal(ic)));
+								s.append(nameTokenAbbrev);
+								s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+								s.append(booleanTokenAbbrev);
+								s.append("TRUE");
+								s.append(eL);
+								found = true;
+							}
+						}
+						//look through all attached objects
+						int numObs = data.getNumberAssociatedObjects();
+
+						for (int v = 0; v<numObs; v++){  
+							ObjectArray array = data.getAssociatedObjects(v);
+							if (!commentsRef.equals(array.getNameReference())){
+								Object c = array.getValue(ic);
+								if (c != null && c instanceof String){
+									s.append(suppTokenAbbrev);
+									s.append(characterTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(ic)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									s.append(stringTokenAbbrev);
+									s.append(StringUtil.tokenize((String)c, null, tokSB));
+									s.append(eL);
+									foundForChar = true;
+								}
+								else if (c != null && c instanceof String[] && ((String[])c).length>0){
+									s.append(suppTMTokenAbbrev);
+									s.append(characterTokenAbbrev);
+									s.append(Integer.toString(CharacterStates.toExternal(ic)));
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+									String[] strings = (String[])c;
+									for (int k = 0; k<strings.length; k++){
+										s.append(stringArrayTokenAbbrev);
+										s.append(StringUtil.tokenize(strings[k], null, tokSB));
+										s.append(' ');
+									}
+									s.append(eL);
+									foundForChar = true;
+								}
+							}
+						}
+
+
+
+						for (int it = 0; it< data.getNumTaxa(); it++){ //OLD footnotes; maintain non-abbreviated
+							String e = data.getAnnotation(ic, it);
+							if (!StringUtil.blank(e)){
+								s.append(textDataSpec);
+								s.append(taxonToken);
+								s.append(Integer.toString(Taxon.toExternal(it)));
+								s.append(characterToken);
+								s.append(Integer.toString(CharacterStates.toExternal(ic)));
+								s.append(textToken);
+								s.append(StringUtil.tokenize(e, null, tokSB));
+								s.append(eL);
+								foundForChar = true;
+							}
+							Vector vector = data.getCellObjectsVector(); 
+							if (vector !=null){
+								for (int v = 0; v<vector.size(); v++){
+									Object2DArray array = (Object2DArray)vector.elementAt(v);
+									Object c = array.getValue(ic, it);
+
+									if (c !=null){
+										if (c instanceof MesquiteInteger){
+											s.append(suppTokenAbbrev);
+											s.append(taxonTokenAbbrev);
+											s.append(Integer.toString(Taxon.toExternal(it)));
+											s.append(characterTokenAbbrev);
+											s.append(Integer.toString(CharacterStates.toExternal(ic)));
+											s.append(nameTokenAbbrev);
+											s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+											s.append(intTokenAbbrev);
+											s.append(Integer.toString(((MesquiteInteger)c).getValue()));
+											s.append(eL);
+											foundForChar = true;
+										}
+										else if ( c instanceof MesquiteDouble){
+											s.append(suppTokenAbbrev);
+											s.append(taxonTokenAbbrev);
+											s.append(Integer.toString(Taxon.toExternal(it)));
+											s.append(characterTokenAbbrev);
+											s.append(Integer.toString(CharacterStates.toExternal(ic)));
+											s.append(nameTokenAbbrev);
+											s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+											s.append(realTokenAbbrev);
+											s.append(Double.toString(((MesquiteDouble)c).getValue()));
+											s.append(eL);
+											foundForChar = true;
+										}
+										else if (c instanceof String){
+											s.append(suppTokenAbbrev);
+											s.append(taxonTokenAbbrev);
+											s.append(Integer.toString(Taxon.toExternal(it)));
+											s.append(characterTokenAbbrev);
+											s.append(Integer.toString(CharacterStates.toExternal(ic)));
+											s.append(nameTokenAbbrev);
+											s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+											s.append(stringTokenAbbrev);
+											s.append(StringUtil.tokenize((String)c, null, tokSB));
+											s.append(eL);
+											foundForChar = true;
+										}
+										else if (c != null && c instanceof String[] && ((String[])c).length>0){
+											s.append(suppTMTokenAbbrev);
+											s.append(taxonTokenAbbrev); 
+											s.append(Integer.toString(Taxon.toExternal(it)));
+											s.append(characterTokenAbbrev);
+											s.append(Integer.toString(CharacterStates.toExternal(ic)));
+											s.append(nameTokenAbbrev);
+											s.append( ParseUtil.tokenize(array.getNameReference().getValue(), null, tokSB));
+											String[] strings = (String[])c;
+											for (int k = 0; k<strings.length; k++){
+												s.append(stringArrayTokenAbbrev);
+												s.append(StringUtil.tokenize(strings[k], null, tokSB));
+												s.append(' ');
+											}
+											s.append(eL);
+											foundForChar = true;
+										}
+									}
+								}
+							}
+						}
+						if (foundForChar && s.length()>0){ //dump to file
+							if (pending != null && !pending.isBlank()){
+								file.writeLine(pending.toString());
+								pending.setValue("");
+							}
+							file.writeLine(s.toString());
+							s.setLength(0);
+						}
+						found = found || foundForChar;
+
+					}
+					Vector a = data.getAttachments();
+					if (a != null)
+						for (int ia = 0; ia<a.size(); ia++){
+							Object o = a.elementAt(ia);
+							if (o instanceof MesquiteString){
+								MesquiteString ms = (MesquiteString)o;
+								if (ms.getName() != null){
+									s.append("\tSUCM ");
+									s.append(nameTokenAbbrev);
+									s.append( ParseUtil.tokenize(ms.getName(), null, tokSB));
+									s.append(stringTokenAbbrev);
+									s.append(StringUtil.tokenize(ms.getValue(), null, tokSB));
+									s.append(eL);
+									found = true;
+								}
+							}
+						}
+					if (found == true && s.length()>0){ //dump to file
+						if (pending != null && !pending.isBlank()){
+							file.writeLine(pending.toString());
+							pending.setValue("");
+						}
+						file.writeLine(s.toString());
+						s.setLength(0);
+					}
+
+				}
+			}
+		}
+		return found;
+	}
+	/*...................................................................................................................*
+	Taxa defaultTaxa = null;
+	MesquiteFile lastFileTaxa = null;
+	Taxa getDefaultTaxa(MesquiteFile file){
+		if (lastFileTaxa == file && defaultTaxa != null){
+			return defaultTaxa;
+		}
+		if (lastFileTaxa != file)
+			lastFileTaxa = file;
+		defaultTaxa = getProject().getTaxa(0);
+		return defaultTaxa;
+	}
+	/*...................................................................................................................*
+	CharacterData defaultData = null;
+	MesquiteFile lastFileData = null;
+	CharacterData getDefaultData(MesquiteFile file){
+		if (lastFileData == file && defaultData != null){
+			return defaultData;
+		}
+		if (lastFileData != file)
+			lastFileData = file;
+		defaultData = getProject().getCharacterMatrix(defaultTaxa, 0);
+		return defaultData;
+	}
+	 */NameReference origIndexRef = NameReference.getNameReference("OrigIndex");
+	 /*...................................................................................................................*/
+	 public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		 if (blockName.equalsIgnoreCase("NOTES")) {
+			 boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			 MesquiteProject project = file.getProject();
+			 String commandName = parser.getFirstToken(command);
+			 nBlock.setDefaultTaxa(project.getTaxa(project.getNumberTaxas()-1));
+			 int code = 0;
+			 // if TAXA, CHARACTERS, SUTM then accept even if fuse
+			 if (fuse && !((commandName.equalsIgnoreCase("SUTM")) || commandName.equalsIgnoreCase("CHARACTERS")))
+				 return true;
+			 if  (commandName.equalsIgnoreCase("TEXT")) 
+				 code = 1;
+			 else if  (commandName.equalsIgnoreCase("I") || commandName.equalsIgnoreCase("INTEGER")) 
+				 code = 2;
+			 else if  (commandName.equalsIgnoreCase("SU") || commandName.equalsIgnoreCase("SUPPLEMENTAL")) 
+				 code = 3;
+			 else if  (commandName.equalsIgnoreCase("SUTM")) 
+				 code = 4;
+			 else if  (commandName.equalsIgnoreCase("SUCM")) {
+				 code = 5;
+			 }
+			 else if  (commandName.equalsIgnoreCase("B")) 
+				 code = 6;
+			 else if  (commandName.equalsIgnoreCase("CHARACTERS")) {
+				 String ctoken  = parser.getNextToken(); //=
+				 ctoken  = parser.getNextToken();
+				 String ttoken  = parser.getNextToken(); //TAXA
+				 if ("Taxa".equalsIgnoreCase(ttoken)){
+					 parser.getNextToken(); //=
+					 ttoken  = parser.getNextToken(); //TAXA block (optional)
+					 if (!StringUtil.blank(ttoken)){
+						 Taxa t = getProject().findTaxa(file, ttoken);
+/*
+						 if (t==null){
+							 int wt = MesquiteInteger.fromString(ttoken);
+							 if (MesquiteInteger.isCombinable(wt))
+								 t = getProject().getTaxa(wt-1);
+						 }
+						 if (t == null && getProject().getNumberTaxas(file)==1){
+							 t = getProject().getTaxa(file, 0);
+						 }
+						 if (t == null && getProject().getNumberTaxas()==1){
+							 t = getProject().getTaxa(0);
+						 }
+						 */
+						 if (t!=null) {
+							 nBlock.setDefaultTaxa(t);
+						 }
+						 else
+							 return false;
+					 }
+				 }
+				 if (fuse && getProject().getNumberCharacterMatricesWithName(null, null, null, ctoken) != 1){
+					 CharacterData d = getProject().chooseData(containerOfModule(), null, null, "A NOTES command refers to matrix \"" + ctoken + "\", but this is ambiguous.  Please choose a matrix to which it applies. (command: " + command  + ")");
+					 if (d!=null) {
+						 nBlock.setDefaultCharacters(d);
+						 return true;
+					 }
+				 }
+				 CharacterData d = getProject().findCharacterMatrix(file, nBlock.getDefaultTaxa(), ctoken);
+
+				 if (d!=null) {
+					 nBlock.setDefaultCharacters(d);
+					 return true;
+				 }
+				 else
+					 return false;
+			 }
+
+			 if (code >0 ) {
+				 int integer = MesquiteInteger.unassigned;
+				 double doub = MesquiteDouble.unassigned;
+				 boolean bool = false;
+				 boolean boolSet = false;
+				 String string = null;
+				 Vector strings = new Vector(); //to store string array
+				 String name = null;
+				 stringPos.setValue(parser.getPosition());
+				 String[][] subcommands  = ParseUtil.getSubcommands(command, stringPos);
+				 if (subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)
+					 return false;
+				 int whichTaxon = MesquiteInteger.unassigned;
+				 int whichCharacter = MesquiteInteger.unassigned;
+				 String text = null;
+				 Taxa taxa = nBlock.getDefaultTaxa();
+				 CharacterData data = nBlock.getDefaultCharacters();
+				// IntegerArray translationTable = (IntegerArray)taxa.getAttachment("originalIndicesDupRead");
+				 IntegerArray translationTable = null;
+				 if (taxa != null && file != null)
+					 translationTable = (IntegerArray)taxa.getAttachment("OrigIndex" + file.getFileName());
+				 if (fuse && translationTable == null)
+					 return false;
+				 for (int i=0; i<subcommands[0].length; i++){
+					 String subC = subcommands[0][i];
+					 if ("T".equalsIgnoreCase(subC) || "TAXON".equalsIgnoreCase(subC)) {
+						 String token = subcommands[1][i];
+						 whichTaxon = MesquiteInteger.fromString(token);
+
+
+						 if (!MesquiteInteger.isCombinable(whichTaxon))
+							 return false;
+						 whichTaxon = Taxon.toInternal(whichTaxon);
+
+						 if (fuse){
+							 if (translationTable != null)
+								 whichTaxon = translationTable.getValue(whichTaxon);
+							 
+							 /*
+							 MesquiteInteger oldNumTaxa = (MesquiteInteger)taxa.getAttachment("OLDNUMTAXA" + file.getFileName());
+							 IntegerArray translationTable = (IntegerArray)taxa.getAttachment("OrigIndex" + file.getFileName());
+							 if (oldNumTaxa != null && translationTable != null){
+								 whichTaxon += oldNumTaxa.getValue();
+								 whichTaxon = translationTable.getValue(whichTaxon);
+							 }
+							 */
+						 }
+
+					 }
+					 else if ( "C".equalsIgnoreCase(subC) || "CHARACTER".equalsIgnoreCase(subC)) {
+						 String token = subcommands[1][i];
+						 whichCharacter = MesquiteInteger.fromString(token);
+						 if (!MesquiteInteger.isCombinable(whichCharacter))
+							 return false;
+						 whichCharacter = CharacterStates.toInternal(whichCharacter);
+					 }
+					 else if ("N".equalsIgnoreCase(subC) || "NAME".equalsIgnoreCase(subC)) {
+						 name = subcommands[1][i];
+					 }
+					 else if ("B".equalsIgnoreCase(subC) || "BOOLEAN".equalsIgnoreCase(subC)) {
+						 if ("true".equalsIgnoreCase(subcommands[1][i]))
+							 bool = true;
+						 boolSet = true;
+					 }
+					 else if ("I".equalsIgnoreCase(subC) || "INTEGER".equalsIgnoreCase(subC)) {
+						 integer = MesquiteInteger.fromString(subcommands[1][i]);
+					 }
+					 else if ("R".equalsIgnoreCase(subC) || "REAL".equalsIgnoreCase(subC)) {
+						 doub = MesquiteDouble.fromString(subcommands[1][i]);
+					 }
+					 else if ("S".equalsIgnoreCase(subC) || "STRING".equalsIgnoreCase(subC)) {
+						 string = subcommands[1][i];
+					 }
+					 else if ("SE".equalsIgnoreCase(subC)) {
+						 strings.addElement(subcommands[1][i]);
+					 }
+					 else if ("TEXT".equalsIgnoreCase(subC)) {
+						 text = subcommands[1][i];
+					 }
+					 else if ("TAXA".equalsIgnoreCase(subC)) {
+						 String token = subcommands[1][i];
+						 Taxa t = getProject().findTaxa(file, token);
+						 /*getTaxaLastFirst(token);
+						 if (t==null){
+							 int wt = MesquiteInteger.fromString(token);
+							 if (MesquiteInteger.isCombinable(wt))
+								 t = getProject().getTaxa(wt-1);
+						 }
+						 if (t == null && getProject().getNumberTaxas(file)==1)
+							 t = getProject().getTaxa(file, 0);
+							if (t == null && getProject().getNumberTaxas()==1)
+								t = getProject().getTaxa(0);
+								*/
+						 if (t!=null) {
+							 taxa = t;
+						 }
+						 else
+							 return false;
+					 }
+					 else if ("CHARACTERS".equalsIgnoreCase(subC)) {
+						 String token = subcommands[1][i];
+						 CharacterData t = getProject().findCharacterMatrix(file, taxa, token);
+						 if (t!=null) {
+							 data = t;
+						 }
+						 else
+							 return false;
+					 }
+				 }
+
+				 if (!MesquiteInteger.isCombinable(whichCharacter) && !(code == 4 && MesquiteInteger.isCombinable(whichTaxon)) && code !=5){
+					 return false;
+				 }
+
+				 if (code ==1){ //text
+					 if (taxa !=null && text !=null && data !=null) {
+
+						 /*&&& the following is a check in place because of a bug in 1.02 and previous in which copies of NOTES blocks would be written in all linked files; 
+						this allowed overwriting by old copies of the NOTES block */
+						 if (data.getFile() != file && file != getProject().getHomeFile()){
+							 if (!MesquiteInteger.isCombinable(whichTaxon)) {
+								 String s = data.getAnnotation(whichCharacter) ;
+								 if (s != null && !s.equals(text)) {
+									 file.notesBugWarn = true;
+									 file.notesBugVector.addElement("Character " + (whichCharacter+1));
+								 }
+
+							 }
+							 else {
+								 String s = data.getAnnotation(whichCharacter, whichTaxon) ;
+								 if (s != null && !s.equals(text)) {
+									 file.notesBugWarn = true;
+									 file.notesBugVector.addElement("Character " + (whichCharacter+1) + " in taxon " + (whichTaxon+1));
+								 }
+							 }
+						 }
+						 /*&&&*/
+
+						 if (!MesquiteInteger.isCombinable(whichTaxon))
+							 data.setAnnotation(whichCharacter, text);
+						 else
+							 data.setAnnotation(whichCharacter, whichTaxon, text);
+						 return true;
+					 }
+				 }
+				 else if (code ==2){ //integer
+					 if (taxa !=null  && MesquiteInteger.isCombinable(integer) && data !=null && name !=null) {
+						 if (MesquiteInteger.isCombinable(whichTaxon))
+							 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, new MesquiteInteger(integer));
+						 else
+							 data.setAssociatedLong(NameReference.getNameReference(name), whichCharacter, integer);
+						 return true;
+					 }
+				 }
+				 else if (code ==3 || code == 4){ //supplemental
+					 if (taxa !=null && data !=null && name !=null) {
+						 if (boolSet){
+							 if (MesquiteInteger.isCombinable(whichTaxon)) {
+								 if (code == 4) {
+									 Associable as = data.getTaxaInfo(true);
+									 as.setAssociatedBit(NameReference.getNameReference(name), whichTaxon, bool);
+								 }
+								 else
+									 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, new MesquiteBoolean(bool));
+							 }
+							 else
+								 data.setAssociatedBit(NameReference.getNameReference(name), whichCharacter, bool);
+							 return true;
+						 }
+						 else if (MesquiteInteger.isCombinable(integer)){
+							 if (MesquiteInteger.isCombinable(whichTaxon)) {
+								 if (code == 4) {
+									 Associable as = data.getTaxaInfo(true);
+									 as.setAssociatedLong(NameReference.getNameReference(name), whichTaxon, integer);
+								 }
+								 else
+									 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, new MesquiteInteger(integer));
+							 }
+							 else
+								 data.setAssociatedLong(NameReference.getNameReference(name), whichCharacter, integer);
+							 return true;
+						 }
+						 else if (MesquiteDouble.isCombinable(doub)){
+							 if (MesquiteInteger.isCombinable(whichTaxon)){
+								 if (code == 4) {
+									 Associable as = data.getTaxaInfo(true);
+									 as.setAssociatedDouble(NameReference.getNameReference(name), whichTaxon, doub);
+								 }
+								 else
+									 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, new MesquiteDouble(doub));
+							 }
+							 else
+								 data.setAssociatedDouble(NameReference.getNameReference(name), whichCharacter, doub);
+							 return true;
+						 }
+						 else if (string != null){
+							 /*&&& the following is a check in place because of a bug in 1.02 and previous in which copies of NOTES blocks would be written in all linked files; 
+							this allowed overwriting by old copies of the NOTES block */
+							 if (data.getFile() != file && file != getProject().getHomeFile()){
+								 if (MesquiteInteger.isCombinable(whichTaxon)) {
+									 String s = (String)data.getCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon);
+									 if (s != null && !s.equals(string)) {
+										 file.notesBugWarn = true;
+										 file.notesBugVector.addElement("Character " + (whichCharacter+1) + "(*)");
+									 }
+								 }
+								 else {
+									 String s = (String)data.getAssociatedObject(NameReference.getNameReference(name), whichCharacter);
+									 if (s != null && !s.equals(string)) {
+										 file.notesBugWarn = true;
+										 file.notesBugVector.addElement("Character " + (whichCharacter+1) + " in taxon " + (whichTaxon+1) + "(*)");
+									 }
+								 }
+							 }
+							 /*&&&*/
+
+							 if (MesquiteInteger.isCombinable(whichTaxon)) {
+								 if (code == 4) {
+									 Associable as = data.getTaxaInfo(true);
+
+									 Object previous = as.getAssociatedObject(NameReference.getNameReference(name), whichTaxon);
+									 if (!StringUtil.blank((String)previous))
+										 string = (String)previous + "; " + string;
+									 as.setAssociatedObject(NameReference.getNameReference(name), whichTaxon, string);
+								 }
+								 else
+									 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, string);
+							 }
+							 else
+								 data.setAssociatedObject(NameReference.getNameReference(name), whichCharacter, string);
+							 return true;
+						 }
+						 else if (strings.size()>0){
+							 String[] sts = new String[strings.size()];
+							 for (int k = 0; k<strings.size(); k++)
+								 sts[k] = (String)strings.elementAt(k);
+							 if (MesquiteInteger.isCombinable(whichTaxon)) {
+								 if (code == 4) {
+									 Associable as = data.getTaxaInfo(true);
+									 as.setAssociatedObject(NameReference.getNameReference(name), whichTaxon, sts);
+								 }
+								 else
+									 data.setCellObject(NameReference.getNameReference(name), whichCharacter, whichTaxon, sts);
+							 }
+							 else
+								 data.setAssociatedObject(NameReference.getNameReference(name), whichCharacter, sts);
+							 return true;
+						 }
+					 }
+				 }
+				 else if (code == 5){
+
+					 if (string != null && name != null){
+
+						 MesquiteString ms = new MesquiteString(name, string);
+						 data.attachIfUniqueName(ms);
+						 return true;
+					 }
+				 }
+
+			 }
+		 }
+		 return false;
+	 }
+	 /*.................................................................................................................*/
+	 public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		 CharacterData data=null;
+		 Parser commandParser = new Parser();
+		 commandParser.setString(block.toString());
+		 MesquiteInteger startCharC = new MesquiteInteger(0);
+		 String title=null;
+		 //String commandString;
+		 Taxa taxa= null;
+		 if (getProject().getNumberTaxas(file)==1)
+			 taxa = getProject().getTaxa(file, 0); //as default
+		 else if (getProject().getNumberTaxas()==1)
+			 taxa = getProject().getTaxa(0); //as default
+		 NexusBlock b=null;
+		 int numChars=0;
+		 if (getProject().getNumberCharMatrices(file)>1)
+			 title = getProject().getCharacterMatrices().getUniqueName("Matrix " + (getProject().getNumberCharMatrices(file)+1) + " in file \"" + file.getName() + "\"");
+		 else
+			 title = getProject().getCharacterMatrices().getUniqueName("Matrix in file \"" + file.getName() + "\"");
+		 boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+
+		 /*Problem: for most parts of block lineends are white, even if interleaved.  But Matrix must be pulled in
+		with lineends as dark if interleave.  How to do this?  Best to remember previous stringpos, and once matrix
+		pulled in, if interleave go back and set stringpos and reread with lineends dark*/
+		 int previousPos = startCharC.getValue();
+		 boolean taxaLinkFound = false;
+		 boolean newTaxaFlag = false;
+
+		 String commandName = null;
+		 while (!commandParser.blankByCurrentWhitespace(commandName=commandParser.getNextCommandName(startCharC))) {
+			 CommandRecord.tick("Reading " + commandName);
+			 if (commandName.equalsIgnoreCase("DIMENSIONS")) {
+				 String com = commandParser.getNextCommand(startCharC);
+				 if (StringUtil.indexOfIgnoreCase(com, "newtaxa")>=0)
+					 newTaxaFlag = true;
+				 parser.setString(com); 
+				 String tk = null;
+				 boolean done = false;
+				 while (!done && !StringUtil.blank(tk = parser.getNextToken()))
+					 if (tk.equalsIgnoreCase("NCHAR"))
+						 done = true;
+				 if (done) {
+					 tk = parser.getNextToken();
+					 numChars = MesquiteInteger.fromString(parser.getNextToken());
+					 if (!MesquiteInteger.isCombinable(numChars) || numChars<0){
+						 alert("Sorry, the DIMENSIONS statement of the CHARACTERS block appears to be misformatted.  The number of characters is not validly specified.  File reading will fail.");
+						 return null;
+					 }
+				 }
+				 log("   " + MesquiteInteger.toString(numChars) + " characters");
+				 //numChars = MesquiteInteger.fromString(parser.getTokenNumber(4));
+			 }
+			 else if (commandName.equalsIgnoreCase("TITLE")) {
+				 parser.setString(commandParser.getNextCommand(startCharC)); 
+				 title = parser.getTokenNumber(2);
+				 logln("Reading CHARACTERS block " + title);
+
+			 }
+			 else if (commandName.equalsIgnoreCase("LINK")) {
+				 parser.setString(commandParser.getNextCommand(startCharC)); 
+				 if ("TAXA".equalsIgnoreCase(parser.getTokenNumber(2))) {
+					 taxaLinkFound = true;
+					 String taxaTitle = parser.getTokenNumber(4);
+					 //logln("       for taxa " + taxaTitle);
+					 taxa = getProject().getTaxaLastFirst(taxaTitle);
+					 if (taxa == null) {
+						 if (getProject().getNumberTaxas()==1)
+							 taxa = getProject().getTaxa(0);
+						 else
+							 alert("Taxa block not found for characters block (name of taxa block \"" + taxaTitle + "\")");
+					 }
+				 }
+			 }
+			 else if (commandName.equalsIgnoreCase("FORMAT")) {
+				 if (taxa == null && fuse && !MesquiteThread.isScripting()){
+					 taxa = getProject().chooseTaxa(containerOfModule(), "A characters block \"" + title + "\" is without a clear reference to a taxa block.  To which taxa block does it belong?", true);
+				 }
+				 if (taxa==null) {
+					 if (taxaLinkFound)
+						 alert("Because taxa block not found, the matrix cannot be read.  The CHARACTERS block will be treated as a foreign block in the file.");
+					 else {
+						 alert("NEXUS file format error: FORMAT statement in CHARACTERS or DATA block occurs before Taxa have been specified in file with more than one set of taxa");
+					 }
+					 return null;
+				 }
+
+				 logln(" for taxa block " + taxa.getName());
+				 data = processFormat(file, taxa, commandParser.getNextCommand(startCharC), numChars, title, fileReadingArguments);
+				 if (data==null) {
+					 alert("Sorry, the CHARACTERS block could not be read, possibly because it is of an unrecognized format.  You may need to activate or install other modules that would allow you to read the data block");
+					 return null;
+				 }
+				 if (getProject().getMatrixNumber(data)<0) { // a new block
+					 if (!fuse)
+						 data.setName(title);
+					 data.deleteUniqueIDs(); //if read from file, then use file's id's and feel free to leave some blank
+					 b = data.addToFile(file, getProject(), this); 
+				 }
+				 else
+					 b = data.getNexusBlock();
+			 }
+			 else if (commandName.equalsIgnoreCase("OPTIONS")) {
+				 stringPos.setValue(0);
+				 String commandString = commandParser.getNextCommand(startCharC);
+				 String subCommand = ParseUtil.getToken(commandString, stringPos);
+				 while ((subCommand = ParseUtil.getToken(commandString, stringPos)) !=null){
+					 if ("LINKCHARACTERS".equalsIgnoreCase(subCommand)){
+						 ParseUtil.getToken(commandString, stringPos); // =
+						 String dataTitle = ParseUtil.getToken(commandString, stringPos);
+						 CharacterData other = getProject().getCharacterMatrixReverseOrder(dataTitle);
+						 if (other != null && data!=null && other!=data) {
+							 other.addToLinkageGroup(data);
+						 }
+					 }
+				 }
+			 }
+			 else if (commandName.equalsIgnoreCase("CHARLABELS")) {
+				 if (data == null){
+					 alert("Error in NEXUS file:  CHARLABELS before FORMAT statement");
+				 }
+				 else {
+					 MesquiteInteger stc = new MesquiteInteger(startCharC.getValue());
+					 parser.setString(commandParser.getNextCommand(stc)); 
+					 parser.getNextToken();
+					 String cN = parser.getNextToken();
+					 int charNumber = 0;
+					 while (cN != null && !cN.equals(";") ) {
+						 data.setCharacterName(charNumber++, cN);
+						 cN = parser.getNextToken();
+					 }
+					 commandParser.getNextCommand(startCharC); //eating up the full command
+				 }
+			 }
+			 else if (commandName.equalsIgnoreCase("MATRIX")) {
+				 if (data==null) {
+					 alert("Error in NEXUS file:  Matrix without FORMAT statement");
+				 }
+				 else if (data.getMatrixManager()!=null) {
+					 if (data.interleaved) {    
+						 startCharC.setValue(previousPos);
+						 commandParser.setLineEndingsDark(true);
+						 commandParser.setPosition(previousPos);
+						 commandParser.getNextToken();
+					 }
+					 boolean wassave = data.saveChangeHistory;
+					 data.saveChangeHistory = false;
+					 data.getMatrixManager().processMatrix(taxa, data, commandParser, numChars, false, 0, newTaxaFlag, fuse, file);
+					 if (data.interleaved) 
+						 commandParser.setLineEndingsDark(false);
+					 startCharC.setValue(commandParser.getPosition());
+					 String token = commandParser.getNextCommand();
+					 if (token == null || !token.equals(";"))
+						 commandParser.setPosition(startCharC.getValue());
+					 data.saveChangeHistory = wassave;
+				 }
+			 }
+			 else if (commandName.equalsIgnoreCase("IDS")) {
+				 //			parser.setString(commandParser.getNextCommand(startCharC)); 
+				 MesquiteInteger stc = new MesquiteInteger(startCharC.getValue());
+				 parser.setString(commandParser.getNextCommand(stc)); 
+				 parser.getNextToken();
+				 String cN = parser.getNextToken();
+				 int charNumber = 0;
+				 while (cN != null && !cN.equals(";") ) {
+					 if (!StringUtil.blank(cN))
+						 data.setUniqueID(charNumber, cN);
+					 charNumber++;
+					 cN = parser.getNextToken();
+				 }
+
+				 commandParser.getNextCommand(startCharC); //eating up the full command
+			 }
+			 else if (commandName.equalsIgnoreCase("BLOCKID")) {
+				 MesquiteInteger stc = new MesquiteInteger(startCharC.getValue());
+				 parser.setString(commandParser.getNextCommand(stc)); 
+				 //				parser.setString(commandParser.getNextCommand(startCharC)); 
+				 parser.getNextToken();
+				 String cN = parser.getNextToken();
+				 if (cN != null && !cN.equals(";")){
+					 if (!StringUtil.blank(cN))
+						 data.setUniqueID(cN);
+					 cN = parser.getNextToken();
+				 }
+				 commandParser.getNextCommand(startCharC); //eating up the full command
+			 }
+			 else if (!(commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK"))) {
+				 boolean success = false;
+				 String commandString = commandParser.getNextCommand(startCharC);
+				 if (data !=null && data.getMatrixManager()!=null)
+					 success = data.getMatrixManager().processCommand(data, commandName, commandString);
+				 if (!success && b != null) 
+					 readUnrecognizedCommand(file,b, name, block, commandName, commandString, blockComments, null);
+			 }
+			 else
+				 commandParser.getNextCommand(startCharC); //eating up the full command
+			 previousPos = startCharC.getValue();
+		 }
+		 if (!fuse && StringUtil.blank(title))
+			 data.setName(getProject().getCharacterMatrices().getUniqueName("Untitled (" + data.getDataTypeName() + ")"));
+		 if (data != null && blockComments!=null && blockComments.length()>0)
+			 data.setAnnotation(blockComments.toString(), false);
+		 if (data !=null) {
+			 data.resetCellMetadata();
+		 }
+		 if (fuse) {
+			 data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		 }
+		 file.setCurrentData(data);
+		 return b;
+	 }
+	 /*.................................................................................................................*/
+	 public String getNameForMenuItem() {
+		 return "Character Matrix Manager";
+	 }
+
+}
+
+/* ======================================================================== */
+class CharactersBlockTest extends NexusBlockTest  {
+	public CharactersBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("CHARACTERS") || blockName.equalsIgnoreCase("CONTINUOUS") ;
+	}
+}
+
+/* ======================================================================== */
+/** An object of this kind can be returned by getNexusCommandTest that will be stored in the modulesinfo vector and used
+to search for modules that can read a particular command in a particular block.  (Much as the NexusBlockObject.)*/
+class CHARNexusCommandTest extends NexusCommandTest  {
+	MesquiteInteger pos = new MesquiteInteger();
+	/**returns whether or not the module can deal with command*/
+	public boolean readsWritesCommand(String blockName, String commandName, String command){
+		if (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("CHARACTERS") || commandName.equalsIgnoreCase("SUTM") || commandName.equalsIgnoreCase("SUCM")))
+			return true;
+		boolean b = (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("SUPPLEMENTAL") || commandName.equalsIgnoreCase("SU") || commandName.equalsIgnoreCase("TEXT") || commandName.equalsIgnoreCase("INTEGER")));
+		if (b){
+			pos.setValue(0);
+			String firstToken = ParseUtil.getFirstToken(command,  pos);
+
+			String[][] subcommands  = ParseUtil.getSubcommands(command, pos);
+			if (subcommands == null)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "CHARACTER")<0 && StringArray.indexOfIgnoreCase(subcommands, 0, "C")<0)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "STATE")>=0)
+				return false;
+			return true;
+		}
+		return false;
+	} 
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCharsets/ManageCharsets.java b/Source/mesquite/charMatrices/ManageCharsets/ManageCharsets.java
new file mode 100644
index 0000000..588db8c
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCharsets/ManageCharsets.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCharsets;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages CHARSETs (not character matrices; see ManageCharacters), including reading the NEXUS command for CHARSETs */
+public class ManageCharsets extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.CharSetList.CharSetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	public void elementsReordered(ListableVector v){
+	}
+	public Class getElementClass(){
+		return CharSelectionSet.class;
+	}
+
+	public String upperCaseTypeName(){
+		return "Character Set";
+	}
+	public String lowerCaseTypeName(){
+		return "character set";
+	}
+	public String nexusToken(){
+		return "CHARSET";
+	}
+	public Object getSpecification(String token){
+		return null;
+	}
+	public boolean hasSpecificationTokens(){
+		return false;
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CharSelectionSet))
+			return;
+		CharSelectionSet sS = (CharSelectionSet)specsSet;
+		sS.setSelected(ic, true);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+ 		CharSelectionSet selectionSet = new CharSelectionSet(name, data.getNumChars(), data);
+		selectionSet.deselectAll(); 
+		return selectionSet;
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+   	
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+			if (specsSet ==null || !(specsSet instanceof CharSelectionSet))
+				return null;
+			CharSelectionSet selectionSet = (CharSelectionSet)specsSet;
+			String s= "";
+			if (selectionSet!=null && (selectionSet.getFile()==file || (selectionSet.getFile()==null && data.getFile()==file))) {
+				String sT = "";
+				int continuing = 0;
+				int lastWritten = -1;
+				
+				for (int ic=0; ic<data.getNumChars(); ic++) {
+					if (selectionSet.isBitOn(ic)) {
+						if (continuing == 0) {
+							sT += " " + CharacterStates.toExternal(ic);
+							lastWritten = ic;
+							continuing = 1;
+						}
+						else if (continuing == 1) {
+							sT += " - ";
+							continuing = 2;
+						}
+					}
+					else if (continuing>0) {
+						if (lastWritten != ic-1) {
+							sT += " " + CharacterStates.toExternal(ic-1);
+							lastWritten = ic-1;
+						}
+						else
+							lastWritten = -1;
+						continuing = 0;
+					}
+
+				}
+				if (continuing>1)
+					sT += " " + CharacterStates.toExternal(data.getNumChars()-1);
+				if (!StringUtil.blank(sT)) {
+					s += "\tCHARSET ";
+					if (isCurrent)
+						s += "* ";
+					s+= StringUtil.tokenize(selectionSet.getName()) + " ";
+					if (writeLinkWithCharacterMatrixName(file, data))
+						s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+					s += "  =  " + sT + ";" + StringUtil.lineEnding();
+				}
+			}
+			return s;
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new CharsetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage character sets";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) character sets (CHARSETS)." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class CharsetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS"))&& commandName.equalsIgnoreCase("CHARSET"));
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCodonPositions/ManageCodonPositions.java b/Source/mesquite/charMatrices/ManageCodonPositions/ManageCodonPositions.java
new file mode 100644
index 0000000..8eba49a
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCodonPositions/ManageCodonPositions.java
@@ -0,0 +1,253 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.ManageCodonPositions;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages specifications of codon positions, including reading the NEXUS command for CODONPOSSET */
+public class ManageCodonPositions extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.CodePosSetsList.CodePosSetsList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	public void elementsReordered(ListableVector v){
+	}
+	public Class getElementClass(){
+		return CodonPositionsSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Codon Positions Set";
+	}
+	public String lowerCaseTypeName(){
+		return "codon positions";
+	}
+	public String nexusToken(){
+		return "CODONPOSSET";
+	}
+	public Object getSpecification(String token){
+		if (token == null)
+			return null;
+		MesquiteNumber num = new MesquiteNumber();
+		if (token.length() == 1 && (token.charAt(0) == 'N' || token.charAt(0) == 'n'))
+			num.setValue(0); 
+		else
+			num.setValue(token);
+		return num;
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CodonPositionsSet) || !(specification instanceof MesquiteNumber))
+			return;
+		CodonPositionsSet characterPartition = (CodonPositionsSet)specsSet;
+		characterPartition.setValue(ic, (MesquiteNumber)specification);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		return new CodonPositionsSet(name, data.getNumChars(), data);
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("CODONS");
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("CODONS");
+	}
+	int endSequenceByThree(CodonPositionsSet codSet, int targetPos, int numChars, int ic){
+		int unassignedPosition=4;
+		int previousThird = ic;
+		for (int ik = ic+1; ik< numChars; ik++){
+			int thisPos = codSet.getInt(ik);
+			if (thisPos == targetPos || (thisPos==MesquiteInteger.unassigned && (targetPos==unassignedPosition))) {
+				//is a match; if not modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 !=0)
+					return previousThird;
+				else
+					previousThird = ik;
+			}
+			else {
+				//is not a match; if modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 ==0)
+					return previousThird;
+			}
+
+		}
+		return previousThird;
+	}
+	/*.................................................................................................................*/
+	public String OLDnexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof CodonPositionsSet))
+			return null;
+		CodonPositionsSet codSet = (CodonPositionsSet)specsSet;
+		String s= "";
+		int unassignedPosition=4;
+		if (codSet !=null && (codSet.getFile()==file || (codSet.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			String thisValueString = "";
+			boolean firstTime = true;
+			int numChars = data.getNumChars();
+			MesquiteNumber position = new MesquiteNumber();
+			boolean someValues=false;
+			for (int targetPos = 0; targetPos<5; targetPos++){
+				position.setValue(targetPos);
+				int continuing = 0;
+				thisValueString = "";
+				if (!firstTime)
+					thisValueString = ", ";
+				if (targetPos == 0)
+					thisValueString += "N: ";
+				else if (targetPos == unassignedPosition)
+					thisValueString += "?: ";
+				else
+					thisValueString += targetPos + ":" ;
+				int lastWritten = -1;
+				someValues=false;
+				for (int ic=0; ic<numChars; ic++) {
+					int thisPos = codSet.getInt(ic);
+					if (thisPos == targetPos || (thisPos==MesquiteInteger.unassigned && (targetPos==unassignedPosition))) {
+						if (continuing == 0) {
+							//first, check to see if there is a series of thirds....
+							int lastThird = endSequenceByThree(codSet, targetPos, numChars, ic);
+							//if so, then go the series of thirds 
+							if (lastThird != ic){
+								thisValueString += " " + CharacterStates.toExternal(ic) + " - " +  CharacterStates.toExternal(lastThird) + "\\3";
+								ic = lastThird;
+								someValues = true;
+							}
+							else { //otherwise write as normal*/
+								lastWritten = ic;
+								thisValueString += " " + CharacterStates.toExternal(ic);
+								continuing = 1;
+								someValues = true;
+							}
+						}
+						else if (continuing == 1) {
+							thisValueString += "-";
+							continuing = 2;
+							someValues = true;
+						}
+					}
+					else if (continuing>0) {
+						if (lastWritten != ic-1){
+							thisValueString += " " + CharacterStates.toExternal(ic-1);
+							lastWritten = ic-1;
+							someValues = true;
+						}
+						else
+							lastWritten = -1;
+						continuing = 0;
+					}
+
+				}
+				if (continuing>1) {
+					thisValueString += " " + CharacterStates.toExternal(data.getNumChars()-1) + " ";
+					someValues = true;
+				}
+				if (someValues) {
+					sT += thisValueString;
+					firstTime = false;
+				}
+			} 
+			if (!StringUtil.blank(sT)) {
+				s+= "\tCODONPOSSET " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(codSet.getName()) + " ";
+				if (file.getProject().getNumberCharMatrices()>1 || (!file.useSimplifiedNexus&& !data.hasDefaultName() && !NexusBlock.suppressTITLE))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof CodonPositionsSet))
+			return null;
+		CodonPositionsSet codSet = (CodonPositionsSet)specsSet;
+		String s= "";
+		int unassignedPosition=4;
+		if (codSet !=null && (codSet.getFile()==file || (codSet.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			String thisValueString = "";
+			boolean firstTime = true;
+			MesquiteNumber position = new MesquiteNumber();
+			for (int targetPos = 0; targetPos<5; targetPos++){
+				position.setValue(targetPos);
+				thisValueString = "";
+				if (!firstTime)
+					thisValueString = ", ";
+				if (targetPos == 0)
+					thisValueString += "N: ";
+				else if (targetPos == unassignedPosition)
+					thisValueString += "?: ";
+				else
+					thisValueString += targetPos + ":" ;
+				String locs = codSet.getListOfMatches(targetPos);
+				if (!StringUtil.blank(locs)) {
+					sT += thisValueString + locs;
+					firstTime = false;
+				}
+			} 
+			if (!StringUtil.blank(sT)) {
+				s+= "\tCODONPOSSET " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(codSet.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new PosNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage codon positions";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages (including NEXUS read/write) codon position sets." ;
+	}
+	/*.................................................................................................................*/
+
+}
+
+/* ======================================================================== */
+class PosNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("CODONS")) && commandName.equalsIgnoreCase("CODONPOSSET"));
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageCodonsBlock/ManageCodonsBlock.java b/Source/mesquite/charMatrices/ManageCodonsBlock/ManageCodonsBlock.java
new file mode 100644
index 0000000..34eef91
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageCodonsBlock/ManageCodonsBlock.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageCodonsBlock;
+/*~~  */
+
+import java.util.*;
+
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages the NEXUS block specifying codon position sets*/
+public class ManageCodonsBlock extends FileInit {
+	public Class getDutyClass(){
+		return ManageCodonsBlock.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] bs = getProject().getNexusBlocks(CodonsBlock.class, f);
+		if (bs == null || bs.length ==0){ 
+			CodonsBlock ab = new CodonsBlock(f, this);
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new CodonsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		Parser commandParser = new Parser();
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		String s;
+		//CodonsBlock sB = new CodonsBlock(file, this); 
+		NexusBlock[] bs = getProject().getNexusBlocks(CodonsBlock.class, file);//added Sept 2011
+		CodonsBlock sB = null;
+		if (bs == null || bs.length == 0)
+			sB = new CodonsBlock(file, this); //TODO: should this store the sets??
+		else
+			sB= (CodonsBlock)bs[0];
+		int numChars=0;
+		while (!StringUtil.blank(s=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(s);
+			if (!commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK"))
+				if (commandName.equalsIgnoreCase("LINK")){
+					sB.processLinkCTCommand( s, getProject(), parser);
+				}
+				else
+					readUnrecognizedCommand(file, sB, "CODONS", block, commandName, s, blockComments, null);
+		}
+		return sB;
+	}
+	/*.................................................................................................................*/
+	public String getCodonsBlock(MesquiteFile file, CodonsBlock sB){
+		String contents = employeesGetCommands(getProject().ownerModule, file);
+		if (sB != null) contents += sB.getUnrecognizedCommands() + StringUtil.lineEnding();
+		if (StringUtil.blank(contents))
+			return null;
+		String blocks="BEGIN CODONS;" + StringUtil.lineEnding()+ contents+ "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+	/*.................................................................................................................*/
+	private String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "CODONS");
+			if (!StringUtil.blank(command))
+				commands+=command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage CODONS blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages CODONS block in NEXUS file." ;
+   	 }
+}
+	
+/* ======================================================================== */
+class CodonsBlock extends NexusBlock {
+	public CodonsBlock(MesquiteFile f, ManageCodonsBlock mb){
+		super(f,mb);
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("written codons");
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("CHARACTERS"));
+		
+	}
+	public String getBlockName(){
+		return "CODONS";
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public String getName(){
+		return "CODONS block";
+	}
+	public String getNEXUSBlock(){
+		return ((ManageCodonsBlock)getManager()).getCodonsBlock(getFile(), this);
+	}
+}
+
+	
+/* ======================================================================== */
+class CodonsBlockTest extends NexusBlockTest  {
+	public CodonsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("CODONS");
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/ManageDATAblock/ManageDATAblock.java b/Source/mesquite/charMatrices/ManageDATAblock/ManageDATAblock.java
new file mode 100644
index 0000000..c34fe91
--- /dev/null
+++ b/Source/mesquite/charMatrices/ManageDATAblock/ManageDATAblock.java
@@ -0,0 +1,196 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ManageDATAblock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Interprets the DATA block of a NEXUS file (this is more of an importer than manager; see ManageTaxa and ManageCharacters for the full management system for taxa and character blocks)*/
+public class ManageDATAblock extends MesquiteModule {
+	private CharactersManager charTask;
+	private TaxaManager taxaTask;
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		taxaTask = (TaxaManager)findElementManager(Taxa.class);
+		charTask = (CharactersManager)findElementManager(CharacterData.class);
+		return taxaTask!=null && charTask!=null;
+	}
+	
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public Class getDutyClass(){
+		return ManageDATAblock.class;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new DATABlockTest();}
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String formatCommand, int numChars, String title, String fileReadingArguments) {
+		return charTask.processFormat(file, taxa, formatCommand, numChars, title, fileReadingArguments);
+	}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		if (block == null || file == null)
+			return null;
+		CharacterData data=null;
+		Parser commandParser = new Parser();
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		String dataTitle=getProject().getCharacterMatrices().getUniqueName("Character Matrix");
+		String taxaTitle=getProject().getCharacterMatrices().getUniqueName("Taxa");
+		int firstTaxon = 0;
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+		
+		String commandName;
+		Taxa taxa= null;
+		int numChars=0;
+		NexusBlock b = null;
+		int previousPos = 0;
+		while (!commandParser.blankByCurrentWhitespace(commandName=commandParser.getNextCommandName(startCharC))) {
+			if (commandName.equalsIgnoreCase("DIMENSIONS")) { 
+				parser.setString(commandParser.getNextCommand(startCharC)); 
+				int numTaxa = MesquiteInteger.fromString(parser.getTokenNumber(4));
+				numChars = MesquiteInteger.fromString(parser.getTokenNumber(7));
+				logln("   " + MesquiteInteger.toString(numTaxa) + " taxa, " + MesquiteInteger.toString(numChars) + " characters.");
+				if (!MesquiteInteger.isCombinable(numTaxa) || numTaxa<0){
+					alert("Sorry, the DIMENSIONS statement of the DATA block appears to be misformatted.  The number of taxa is not validly specified. File reading will fail.");
+					return null;
+				}
+				if (!MesquiteInteger.isCombinable(numChars) || numChars<0){
+					alert("Sorry, the DIMENSIONS statement of the DATA block appears to be misformatted.  The number of characters is not validly specified. File reading will fail.");
+					return null;
+				}
+				if (fuse){
+					String message = "In the file being imported, there is a taxa block. Mesquite will either fuse this imported taxa block into the taxa block you select below, or it will import that taxa block as new, separate taxa block.";
+					taxa = getProject().chooseTaxa(containerOfModule(), message, true, "Fuse with Selected Taxa Block", "Add as New Taxa Block");
+					if (taxa != null){
+						firstTaxon = taxa.getNumTaxa();
+						taxa.addTaxa( taxa.getNumTaxa()-1, numTaxa, true);
+					}
+				}
+				if (taxa == null)
+					taxa = taxaTask.makeNewTaxa(taxaTitle, numTaxa, false);
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				parser.setString(commandParser.getNextCommand(startCharC)); 
+				dataTitle = parser.getTokenNumber(2);
+				logln("Reading CHARACTERS block " + dataTitle);
+			}
+			else if (commandName.equalsIgnoreCase("FORMAT")) {
+				data = processFormat(file, taxa, commandParser.getNextCommand(startCharC), numChars, dataTitle, fileReadingArguments);
+				if (data==null) {
+					alert("Sorry, the DATA block could not be read, possibly because it is of an unrecognized format.  You may need to activate or install other modules that would allow you to read the data block");
+					return null;
+				}
+				taxa.addToFile(file, getProject(), taxaTask);
+				if (!fuse)
+					data.setName(dataTitle);
+				b = data.addToFile(file, getProject(), null);
+				}
+			else if (commandName.equalsIgnoreCase("MATRIX")) {
+				if (data==null) {
+					alert("Error in NEXUS file:  Matrix without FORMAT statement");
+				}
+				else if (data.getMatrixManager()!=null) {
+					if (data.interleaved) {
+						startCharC.setValue(previousPos);
+						commandParser.setLineEndingsDark(true);
+						commandParser.setPosition(previousPos);
+						commandParser.getNextToken();
+					}
+					boolean wassave = data.saveChangeHistory;
+					data.saveChangeHistory = false;
+					if (data.interleaved)
+						logln("  reading interleaved DATA block");
+
+					data.getMatrixManager().processMatrix(taxa, data, commandParser, numChars, true, firstTaxon, false, fuse, file); 
+					if (data.interleaved) 
+						commandParser.setLineEndingsDark(false);
+					startCharC.setValue(commandParser.getPosition());
+					String token = commandParser.getNextCommand();
+					if (token == null || !token.equals(";"))
+						commandParser.setPosition(startCharC.getValue());
+					data.saveChangeHistory = wassave;
+				}
+				else {
+					return null;
+				}
+			}
+			else if (commandName.equalsIgnoreCase("CHARLABELS")) {
+				parser.setString(commandParser.getNextCommand(startCharC)); 
+				parser.getNextToken();
+				String cN = parser.getNextToken();
+				int charNumber = 0;
+				while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+					data.setCharacterName(charNumber++, cN);
+					cN = parser.getNextToken();
+				}
+			}
+			else if (!(commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK"))) {
+				boolean success = false;
+				String commandString = commandParser.getNextCommand(startCharC);
+				if (data !=null && data.getMatrixManager()!=null)
+					success = data.getMatrixManager().processCommand(data, commandName, commandString);
+				if (!success && b != null) 
+					readUnrecognizedCommand(file,b, name, block, commandName, commandString, blockComments, null);
+			}
+			else
+				commandParser.getNextCommand(startCharC); //eating up the full command
+			previousPos = startCharC.getValue();
+		}
+		if (!fuse && StringUtil.blank(dataTitle))
+			data.setName(getProject().getCharacterMatrices().getUniqueName("Untitled (" + data.getDataTypeName() + ")"));
+		if (data != null && blockComments!=null && blockComments.length()>0)
+			data.setAnnotation(blockComments.toString(), false);
+		if (data !=null) {
+			data.resetCellMetadata();
+		}
+		file.setCurrentTaxa(taxa);
+		file.setCurrentData(data);
+		return b;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Read DATA blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates the reading of a DATA block in NEXUS file." ;
+   	 }
+}
+	
+	
+/* ======================================================================== */
+class DATABlockTest extends NexusBlockTest  {
+	public DATABlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("DATA");
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/MatrixFromClipboard/MatrixFromClipboard.java b/Source/mesquite/charMatrices/MatrixFromClipboard/MatrixFromClipboard.java
new file mode 100644
index 0000000..ee7323f
--- /dev/null
+++ b/Source/mesquite/charMatrices/MatrixFromClipboard/MatrixFromClipboard.java
@@ -0,0 +1,231 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.MatrixFromClipboard;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.datatransfer.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.duties.*;
+
+/** Makes a character matrix from the clipboard.*/
+public class MatrixFromClipboard extends CharMatrixFiller implements MesquiteListener {
+	Taxa taxa=null;
+	CharacterData data;
+	MCharactersDistribution states;
+	Class dataClass = null;
+	MesquiteString dataName;
+	MesquiteSubmenuSpec mss;
+	boolean iveQuit = false; //need special means to quit if multiple taxa blocks, because then harder to know on startup if matrices are available
+	
+	
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	public  int getNumberOfMatrices(Taxa taxa){
+    		return 1;
+    	}
+    	private void captureClipboard(){
+    	}
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+    	 public String getMatrixName(Taxa taxa, int ic) {
+    		return "Matrix from clipboard";
+   	 }
+   	 
+   	 
+	/*.................................................................................................................*/
+   	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+   		if (im == 0) {
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			Transferable t = clip.getContents(this);
+			try {
+				String s = (String)t.getTransferData(DataFlavor.stringFlavor);
+	   			int[] lines = MesquiteTable.getTabbedLinesCount(s);
+	   			boolean columnNamesPresent = true;
+	   			boolean rowNamesPresent = false;
+	   			if (lines!=null && IntegerArray.equalValues(lines) && lines.length>0 && lines[0]>0){
+					CharactersManager charManager = (CharactersManager)findElementManager(CharacterData.class);
+					String[] names = charManager.dataClassesAvailable();
+					MesquiteString dataTypeName = new MesquiteString();
+					MesquiteBoolean cNames = new MesquiteBoolean(true);
+					MesquiteBoolean rNames = new MesquiteBoolean(false);
+					MesquiteInteger buttonPressed = new MesquiteInteger(0);
+	   				MFCDialog dialog = new MFCDialog(this, s, names, dataTypeName, cNames, rNames, buttonPressed);
+	 				if (buttonPressed.getValue() == 1) //cancel
+	 					return null;
+	   				columnNamesPresent = cNames.getValue();
+	   				rowNamesPresent = rNames.getValue();
+	   				int numTaxa = lines.length;
+	   				if (columnNamesPresent)
+	   					numTaxa = lines.length-1;
+	   				int numChars = lines[0];
+	   				if (rowNamesPresent)
+	   					numChars = lines[0]-1;
+					CharacterData data = charManager.newCharacterData(taxa, numChars, dataTypeName.toString());
+					String title= getProject().getCharacterMatrices().getUniqueName("Matrix from clipboard");
+	   				data.setName(title);
+					boolean wassave = data.saveChangeHistory;
+					data.saveChangeHistory = false;
+	   				pasteIt(s, data, columnNamesPresent, rowNamesPresent);
+					data.saveChangeHistory = wassave;
+	   				data.resetCellMetadata();
+	   				return data.getMCharactersDistribution();
+	   			}
+			}
+			catch(Exception e){
+			}
+   		}
+	   	alert("Sorry, there was a problem in making the matrix from the clipboard");
+   		return null;
+   	}
+ 	private void pasteIt(String s, CharacterData data, boolean columnNamesPresent, boolean rowNamesPresent){
+		int count = 0;
+		Parser parser = new Parser();
+		CharacterState state = data.makeCharacterState();
+		MesquiteInteger pos = new MesquiteInteger(0);
+		MesquiteInteger pos2 = new MesquiteInteger(0);
+		if (columnNamesPresent) {
+			if (rowNamesPresent)
+				MesquiteTable.getNextTabbedToken(s, pos); //eat up first tab of corner cell
+			for (int ic = 0; ic<data.getNumChars(); ic++) {
+				String t = MesquiteTable.getNextTabbedToken(s, pos);
+				data.setCharacterName(ic, t);//charactername;
+			}
+		}
+		String token = "";
+		for (int it = 0; it<data.getNumTaxa() && token !=null; it++) {
+			int taxonNumber = it;
+			if (rowNamesPresent) {
+				token = MesquiteTable.getNextTabbedToken(s, pos);
+				int tn = data.getTaxa().whichTaxonNumber(token);
+				if (tn>=0)
+					taxonNumber = tn;
+				//taxon name; skip
+			}
+			for (int ic = 0; ic<data.getNumChars() && token !=null; ic++) {
+				token = MesquiteTable.getNextTabbedToken(s, pos);
+				pos2.setValue(0);
+				state.setValue(token, data);
+				if (!state.isCombinable())
+					state.setToUnassigned();
+				data.setState(ic, taxonNumber, state);//state;
+			}
+		}
+ 	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+   	/** gets the current matrix.*/
+   	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+   		return getMatrix(taxa, 0);
+   	}
+   	/** returns the number of the current matrix*/
+   	public int getNumberCurrentMatrix(){
+   		return 0;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Matrix from Clipboard";  
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Clipboard...";  
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Makes a character matrix from text in the clipboard." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		return "";
+   	 }
+   	 
+   	 
+}
+
+class MFCDialog extends ExtensibleDialog implements ItemListener {
+	MatrixFromClipboard ownerModule;
+	Choice dataChoice;
+	MesquiteString dataChoiceName;
+	MesquiteBoolean cNames, rNames;
+	Checkbox cNamesBox, rNamesBox;
+	public MFCDialog (MatrixFromClipboard ownerModule, String clip, String[] dataTypeNames, MesquiteString dataChoiceName, MesquiteBoolean cNames, MesquiteBoolean rNames, MesquiteInteger buttonPressed){
+		super(ownerModule.containerOfModule(), "Matrix from Clipboard", buttonPressed);
+		this.dataChoiceName = dataChoiceName;
+		this.ownerModule = ownerModule;
+		this.cNames = cNames;
+		this.rNames = rNames;
+		
+		//need to choose matrix type, whether 
+		addLargeOrSmallTextLabel("If the contents of the clipboard are suitable, a new character matrix can be made from them.  The current contents of clipboard are:");
+		if (StringUtil.blank(clip))
+			clip = "Sorry, there is nothing in the clipboard.";
+		addTextAreaSmallFont(clip, 8);
+		addLargeOrSmallTextLabel("If the matrix represented in the clipboard uses special symbols (e.g., A B C D instead of 0 1 2 3), it may not be translatable.");
+		dataChoice = addPopUpMenu ("Data type", dataTypeNames, 0);
+		if (dataTypeNames.length > 0)
+			dataChoiceName.setValue(dataTypeNames[0]);
+		dataChoice.addItemListener(this);
+		cNamesBox = addCheckBox("Includes character names", cNames.getValue());
+		cNamesBox.addItemListener(this);
+		rNamesBox = addCheckBox("Includes taxon names", rNames.getValue());
+		rNamesBox.addItemListener(this);
+		completeAndShowDialog();
+		
+	}
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == dataChoice){
+	  		dataChoiceName.setValue((String)e.getItem());
+  		}
+  		else if (e.getItemSelectable() == cNamesBox){
+  			cNames.setValue(cNamesBox.getState());
+  		}
+  		else if (e.getItemSelectable() == rNamesBox){
+  			rNames.setValue(rNamesBox.getState());
+  		}
+
+  	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/MatrixInfoTool/32matrixInfo.gif b/Source/mesquite/charMatrices/MatrixInfoTool/32matrixInfo.gif
new file mode 100644
index 0000000..750db1d
Binary files /dev/null and b/Source/mesquite/charMatrices/MatrixInfoTool/32matrixInfo.gif differ
diff --git a/Source/mesquite/charMatrices/MatrixInfoTool/64matrixInfo.gif b/Source/mesquite/charMatrices/MatrixInfoTool/64matrixInfo.gif
new file mode 100644
index 0000000..75cde5a
Binary files /dev/null and b/Source/mesquite/charMatrices/MatrixInfoTool/64matrixInfo.gif differ
diff --git a/Source/mesquite/charMatrices/MatrixInfoTool/MatrixInfoTool.java b/Source/mesquite/charMatrices/MatrixInfoTool/MatrixInfoTool.java
new file mode 100644
index 0000000..acd9bac
--- /dev/null
+++ b/Source/mesquite/charMatrices/MatrixInfoTool/MatrixInfoTool.java
@@ -0,0 +1,146 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.MatrixInfoTool; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* TODO: 
+ * 	- emphasize rows and columns on mousedowns
+ * 	- convert to tool tip
+ * 	- have info for things other than data cells; e.g., for whole taxa
+ */
+/* ======================================================================== */
+public class MatrixInfoTool extends DataWindowAssistantI {
+	CMTable table;
+	CharacterData  data;
+	Taxa taxa;
+	protected TableTool matrixInfoTool;
+	MesquiteWindow window;
+	MesquitePopup popup;
+	MesquiteCommand respondCommand;
+
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (containerOfModule() instanceof MesquiteWindow) {
+			matrixInfoTool = new TableTool(this, "matrixInfo", getPath(), "matrixInfo.gif", 8, 8,"Data information", "This tool shows information about the data in each taxon", MesquiteModule.makeCommand("matrixInfo",  this) , null, null);
+			matrixInfoTool.setWorksOnColumnNames(false);
+			matrixInfoTool.setWorksOnRowNames(false);
+			matrixInfoTool.setWorksOnMatrixPanel(true);
+			matrixInfoTool.setWorksOnCornerPanel(false);
+			//matrixInfoTool.setEmphasizeRowsOnMouseDown(true);
+			window = (MesquiteWindow)containerOfModule();
+			window.addTool(matrixInfoTool);
+			respondCommand = makeCommand("respond", this);
+		}
+		else return sorry(getName() + " couldn't start because the window with which it would be associated is not a tool container.");
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = (CMTable)table;
+		this.data = data;
+		taxa = data.getTaxa();
+	}
+	/*.................................................................................................................*/
+	public int getApplicableNonMissing(int ic, int it, boolean before){
+		int count = 0;
+		if (before) {
+			for (int i = 0; i<ic; i++)
+				if (!data.isUnassigned(i, it) && !data.isInapplicable(i,it))
+					count++;
+		} else
+			for (int i = ic+1; i<data.getNumChars(); i++)
+				if (!data.isUnassigned(i, it) && !data.isInapplicable(i, it))
+					count++;
+
+		return count;
+	}
+
+	/*.................................................................................................................*/
+	void addToPopup(String s,int response){
+		if (popup==null)
+			return;
+		popup.addItem(s, this, respondCommand, Integer.toString(response));
+	}
+ 	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "move touched cell or selected cells", "[column touched] [row touched] [percent horizontal] [percent vertical] [modifiers]", commandName, "matrixInfo")) {
+ 	 		if (table!=null && data !=null && taxa!=null){
+ 	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+				int responseNumber = 0;
+				if (popup==null)
+					popup = new MesquitePopup(window.getGraphicsArea());
+				popup.removeAll();
+				addToPopup("Taxon: " + taxa.getTaxonName(row)+", character: " + (column+1), responseNumber++);
+				addToPopup("-", responseNumber++);
+
+				int applicableNonMissingBefore = getApplicableNonMissing(column, row,true);
+				int applicableNonMissingAfter = getApplicableNonMissing(column, row,false);
+				int totalApplicableNonMissing = applicableNonMissingBefore + applicableNonMissingAfter;
+				if (!data.isUnassigned(column, row) && !data.isInapplicable(column, row))
+					totalApplicableNonMissing++;
+				
+				addToPopup("Total number of " + data.getNameOfCellEntry(2)+ ": " + totalApplicableNonMissing, responseNumber++);
+				addToPopup("Number to left: " + applicableNonMissingBefore + " " + data.getNameOfCellEntry(applicableNonMissingBefore), responseNumber++);
+				addToPopup("Number to right: " + applicableNonMissingAfter + " " + data.getNameOfCellEntry(applicableNonMissingAfter), responseNumber++);
+				if (data instanceof DNAData){
+					addToPopup("-", responseNumber++);
+					addToPopup("Frequencies within character: ", responseNumber++);
+					addToPopup("   "+ ((DNAData)data).getStateFrequencyString(column), responseNumber++);
+					
+				}
+				popup.showPopup(table.getColumnX(column), table.getRowY(row));
+	   		}
+   	 	}
+    	 	else if (checker.compare(this.getClass(), "Responds to choice of popup menu", "[choice number]", commandName, "respond")) {
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Matrix Info";
+   	 }
+    		/*.................................................................................................................*/
+    		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    		public int getVersionOfFirstRelease(){
+    			return 200;  
+    		}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shows Information about the data in each taxon." ;
+   	 }
+   	 
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/MatrixInfoTool/matrixInfo.gif b/Source/mesquite/charMatrices/MatrixInfoTool/matrixInfo.gif
new file mode 100644
index 0000000..b1b4809
Binary files /dev/null and b/Source/mesquite/charMatrices/MatrixInfoTool/matrixInfo.gif differ
diff --git a/Source/mesquite/charMatrices/MatrixSelection/MatrixSelection.java b/Source/mesquite/charMatrices/MatrixSelection/MatrixSelection.java
new file mode 100644
index 0000000..9116770
--- /dev/null
+++ b/Source/mesquite/charMatrices/MatrixSelection/MatrixSelection.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.MatrixSelection; 
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MatrixSelection extends DataWindowAssistantI {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharSelectCoordinator.class, getName() + " uses a criterion to select characters in the Character Matrix Editor.",
+		"These options are available in the Select menu of the Character Matrix Editor");
+		e2.setSuppressListing(true);
+		EmployeeNeed e3 = registerEmployeeNeed(TaxaSelectCoordinator.class, getName() + " uses a criterion to select taxa in the Character Matrix Editor.",
+		"These options are available in the Select menu of the Character Matrix Editor");
+		e3.setSuppressListing(true);
+		EmployeeNeed e4 = registerEmployeeNeed(DataWSelectionAssistant.class, getName() + " uses a criterion to select taxa, characters and cells in the Character Matrix Editor.",
+		"These options are available in the Select menu of the Character Matrix Editor");
+		e4.setSuppressListing(true);
+	}
+	CharSelectCoordinator charSel;	
+	TaxaSelectCoordinator taxaSel;	
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("Select");
+		addMenuItem("Select All", makeCommand("selectAll",  this));
+		addMenuItem("Deselect All", makeCommand("deselectAll",  this));
+		addMenuItem("-", null);
+		charSel = (CharSelectCoordinator)hireEmployee(CharSelectCoordinator.class, null);
+		taxaSel = (TaxaSelectCoordinator)hireEmployee(TaxaSelectCoordinator.class, null);
+ 		addModuleMenuItems(null, makeCommand("newAssistant",  this), DataWSelectionAssistant.class);
+ 		addMenuItem("-", null);
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects all in matrix", null, commandName, "selectAll")) {
+			if (data !=null &&table!=null) { // 
+				Taxa taxa = data.getTaxa();
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					data.setSelected(i, true);
+ 				for (int i=0; i<taxa.getNumTaxa(); i++)
+ 					taxa.setSelected(i, true);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+ 				table.selectBlock(0, 0, data.getNumChars()-1, data.getNumTaxa()-1);
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Hires new data selection assistant module", "[name of module]", commandName, "newAssistant")) {
+    	 		DataWSelectionAssistant as =  (DataWSelectionAssistant)hireNamedEmployee(DataWSelectionAssistant.class, arguments);
+    	 		if (as == null)
+    	 			return null;
+    	 		as.setTableAndData(table, data);
+    	 		if (!as.pleaseLeaveMeOn())
+    	 			fireEmployee(as);
+    	 		else
+    	 			return as;
+		}
+    	 	else if (checker.compare(this.getClass(), "Deselects all in matrix", null, commandName, "deselectAll")) {
+			if (data !=null && table!=null) {  //
+ 				table.deselectAll();
+				Taxa taxa = data.getTaxa();
+ 				for (int i=0; i<data.getNumChars(); i++)
+ 					data.setSelected(i, false);
+ 				for (int i=0; i<taxa.getNumTaxa(); i++)
+ 					taxa.setSelected(i, false);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				table.repaintAll();
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (data==null)
+			return;
+		this.table = table;
+		this.data = data;
+		charSel.setTableAndObject(table, data, true);
+		taxaSel.setTableAndObject(table, data.getTaxa(), false);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character matrix selection coordinator";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates selecting taxa and characters in data matrix." ;
+   	 }
+}
+
diff --git a/Source/mesquite/charMatrices/NoColor/NoColor.java b/Source/mesquite/charMatrices/NoColor/NoColor.java
new file mode 100644
index 0000000..d48c83c
--- /dev/null
+++ b/Source/mesquite/charMatrices/NoColor/NoColor.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.NoColor; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class NoColor extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerTaxa, CellColorerMatrix {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.data = data;
+		taxa = data.getTaxa();
+	}
+	CharacterData data;
+	Taxa taxa;
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "No Color";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Turns off cell coloring.";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	public void viewChanged(){
+   	}
+   	 public boolean setActiveColors(boolean active){
+   	 	setActive(true);
+		return true; 
+  	 }
+   	public ColorRecord[] getLegendColors(){
+   		return null;
+   	}
+   	public String getColorsExplanation(){
+  		return null;
+   	}
+	public Color getCellColor(int ic, int it){
+		return null;
+	}
+   	public String getCellString(int ic, int it){
+		return "";
+   	}
+	public String getParameters(){
+		return null;
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/NumApplicableNonMissing/NumApplicableNonMissing.java b/Source/mesquite/charMatrices/NumApplicableNonMissing/NumApplicableNonMissing.java
new file mode 100644
index 0000000..9ff7803
--- /dev/null
+++ b/Source/mesquite/charMatrices/NumApplicableNonMissing/NumApplicableNonMissing.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.NumApplicableNonMissing;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumApplicableNonMissing extends NumberForCharacter  implements NumForCharTreeIndep { 
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		int numTaxa =charStates.getNumTaxa();
+		int tot = 0;
+		int count=0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (!charStates.isInapplicable(it) && !charStates.isUnassigned(it))
+				count++;
+		}
+		result.setValue(count);
+		if (resultString!=null)
+			resultString.setValue("Number of Taxa with Non-Gap, Non-Missing: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Number of Taxa with Non-Gap, Non-Missing";
+   	 }
+    		/*.................................................................................................................*/
+    		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    		public int getVersionOfFirstRelease(){
+    			return 200;  
+    		}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the number of taxa in the character that contain applicable, non-missing data." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/NumApplicableNonMissingMatrix/NumApplicableNonMissingMatrix.java b/Source/mesquite/charMatrices/NumApplicableNonMissingMatrix/NumApplicableNonMissingMatrix.java
new file mode 100644
index 0000000..3d40b54
--- /dev/null
+++ b/Source/mesquite/charMatrices/NumApplicableNonMissingMatrix/NumApplicableNonMissingMatrix.java
@@ -0,0 +1,59 @@
+package mesquite.charMatrices.NumApplicableNonMissingMatrix;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class NumApplicableNonMissingMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+
+		long valid = 0;
+		long total = 0;
+		CharacterData parentData = data.getParentData();
+		int numTaxa = parentData.getNumTaxa();
+		int numChars = parentData.getNumChars();
+
+		for (int it=0; it<numTaxa; it++)
+			for (int ic=0; ic<numChars; ic++){
+				if (!parentData.isInapplicable(ic,it) && !parentData.isUnassigned(ic,it))
+					valid++;
+				total++;
+			}
+		if (total>0) {
+			result.setValue((valid*1.0)/total); 
+		}  else
+			result.setValue(0.0); 
+
+		if (resultString!=null) {
+			resultString.setValue("Fraction Applicable and Not Missing: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+
+	public boolean isPrerelease (){
+		return false;
+	}
+
+	public String getName() {
+		return "Fraction Applicable and Not Missing";
+	} 
+
+	public String getExplanation(){
+		return "Calculates the fraction of the matrix that is applicable and not missing data.";
+	} 
+
+} 
diff --git a/Source/mesquite/charMatrices/NumForCharWithChar/NumForCharWithChar.java b/Source/mesquite/charMatrices/NumForCharWithChar/NumForCharWithChar.java
new file mode 100644
index 0000000..4c6ba93
--- /dev/null
+++ b/Source/mesquite/charMatrices/NumForCharWithChar/NumForCharWithChar.java
@@ -0,0 +1,248 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.NumForCharWithChar;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForCharWithChar extends NumberForCharacter implements Incrementable{
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2Characters.class, getName() + " needs a particular method to calculate a value pertaining to two characters (e.g., a correlation).",
+		"You can request what the value for the two characters initially, or later under the Values submenu.");
+	}
+	NumberFor2Characters numberTask;
+	CharSourceCoordObed characterSourceTask;
+	Taxa taxa;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	int currentChar = 0;
+	Class taskClass = NumberFor2Characters.class;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberFor2Characters)hireNamedEmployee(NumberFor2Characters.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumberFor2Characters)hireEmployee(NumberFor2Characters.class, "Value to calculate for character with other character");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberFor2Characters.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberFor2Characters.class);
+			mss.setSelected(numberTaskName);
+		}
+		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of other characters (for " + numberTask.getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		addMenuItem( "-", null);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask || employee == numberTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void setCurrent(long i){
+		if (characterSourceTask==null || taxa==null)
+			return;
+		if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+			currentChar = (int)i;
+		}
+	}
+	public String getItemTypeName(){
+		return "Character";
+	}
+	/*.................................................................................................................*/
+	public long toInternal(long i){
+		return(CharacterStates.toInternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long toExternal(long i){
+		return(CharacterStates.toExternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long getCurrent(){
+		return currentChar;
+	}
+	/*.................................................................................................................*/
+	public long getMin(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public long getMax(){
+		if (characterSourceTask==null || taxa==null)
+			return 0;
+		return characterSourceTask.getNumberOfCharacters(taxa)-1;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  //TODO: note not snapshotting tree task
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with another character", "[name of module]", commandName, "setNumberTask")) {
+			NumberFor2Characters temp =  (NumberFor2Characters)replaceEmployee(NumberFor2Characters.class, arguments, "Number for character with another character", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+			if (currentChar>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentChar--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentChar = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+		taxa = charStates.getTaxa();
+		CharacterDistribution otherCharStates  = characterSourceTask.getCharacter(taxa, currentChar);
+		numberTask.initialize(charStates, otherCharStates);
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || charStates == null)
+			return;
+		clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(charStates);
+		}
+		CharacterDistribution otherCharStates = characterSourceTask.getCharacter(taxa, currentChar);
+		rs.setValue("");
+		numberTask.calculateNumber(charStates, otherCharStates, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For character " + (currentChar + 1) + ", ");
+			resultString.append(rs.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			currentChar = 0;
+			parametersChanged(notification);
+		}
+		else
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Calculator: " + numberTask.getName() + " with character " + (currentChar+1); 
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character value using other character";
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Character value using other character";
+		else
+			return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Character value using other character....";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a character based on another character (e.g., a correlation between the two characters)." ;
+	}
+
+
+}
+
diff --git a/Source/mesquite/charMatrices/NumIncludedMatrix/NumIncludedMatrix.java b/Source/mesquite/charMatrices/NumIncludedMatrix/NumIncludedMatrix.java
new file mode 100644
index 0000000..7c958d3
--- /dev/null
+++ b/Source/mesquite/charMatrices/NumIncludedMatrix/NumIncludedMatrix.java
@@ -0,0 +1,76 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.NumIncludedMatrix;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class NumIncludedMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+
+		long total = 0;
+		CharacterData parentData = data.getParentData();
+		if (parentData == null){
+			total = data.getNumChars();
+		}
+		else {
+			int numChars = parentData.getNumChars();
+
+			for (int ic=0; ic<numChars; ic++)
+				if (parentData.isCurrentlyIncluded(ic))
+					total++;
+		}
+		result.setValue(total); 
+
+		if (resultString!=null) {
+			resultString.setValue("Number of characters included: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+
+	public boolean isPrerelease (){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	public String getName() {
+		return "Number of Characters Included";
+	} 
+
+	public String getExplanation(){
+		return "Calculates the number of characters in a matrix that are included.";
+	} 
+
+} 
diff --git a/Source/mesquite/charMatrices/NumTaxaWithDataInMatrix/NumTaxaWithDataInMatrix.java b/Source/mesquite/charMatrices/NumTaxaWithDataInMatrix/NumTaxaWithDataInMatrix.java
new file mode 100644
index 0000000..6dfe580
--- /dev/null
+++ b/Source/mesquite/charMatrices/NumTaxaWithDataInMatrix/NumTaxaWithDataInMatrix.java
@@ -0,0 +1,77 @@
+package mesquite.charMatrices.NumTaxaWithDataInMatrix;
+
+
+
+import mesquite.categ.lib.MolecularData;
+import mesquite.categ.lib.RequiresAnyMolecularData;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class NumTaxaWithDataInMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+		int count = 0;
+		for (int it = 0; it<data.getNumTaxa(); it++){
+			if (hasData(data, it))
+				count++;
+		}
+
+
+		if (count>0) {
+			result.setValue(count); 
+		}  else
+			result.setValue(0.0); 
+
+		if (resultString!=null) {
+			resultString.setValue("Number of taxa with data: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+	boolean hasData(MCharactersDistribution data, int it){
+		CharacterState cs = null;
+		try {
+			for (int ic=0; ic<data.getNumChars(); ic++) {
+				cs = data.getCharacterState(cs, ic, it);
+				if (cs == null)
+					return false;
+				if (!cs.isInapplicable() && !cs.isUnassigned()) 
+					return true;
+
+			}
+		}
+		catch (NullPointerException e){
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	public boolean isPrerelease (){
+		return false;
+	}
+
+	public String getName() {
+		return "Number of Taxa with Data in Matrix";
+	} 
+
+	public String getExplanation(){
+		return "Counts the number of taxa with data (not ? and not gaps) the matrix.";
+	} 
+
+} 
diff --git a/Source/mesquite/charMatrices/PercentGaps/PercentGaps.java b/Source/mesquite/charMatrices/PercentGaps/PercentGaps.java
new file mode 100644
index 0000000..02f310f
--- /dev/null
+++ b/Source/mesquite/charMatrices/PercentGaps/PercentGaps.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.PercentGaps;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PercentGaps extends NumberForCharacter  implements NumForCharTreeIndep { 
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		int numTaxa =charStates.getNumTaxa();
+		int tot = 0;
+		int count=0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (charStates.isInapplicable(it))
+				count++;
+			if (!charStates.isUnassigned(it))
+				tot++;
+		}
+		resultNum = 1.000*count/tot;
+		result.setValue(resultNum);
+		if (resultString!=null)
+			resultString.setValue("Proportion Gaps: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Proportion Gaps In Character";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the proportion of gaps (inapplicable codings) in a character across taxa.  Does not include missing (unassigned) data." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/PercentMissing/PercentMissing.java b/Source/mesquite/charMatrices/PercentMissing/PercentMissing.java
new file mode 100644
index 0000000..c70e96a
--- /dev/null
+++ b/Source/mesquite/charMatrices/PercentMissing/PercentMissing.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.PercentMissing;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PercentMissing extends NumberForCharacter implements NumForCharTreeIndep {
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+   
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		int numT = charStates.getNumTaxa();
+		int count=0;
+		for (int it = 0; it<numT; it++) {
+			if (charStates.isUnassigned(it))
+				count++;
+		}
+		resultNum = 1.000*count/numT;
+		result.setValue(resultNum);
+		if (resultString!=null)
+			resultString.setValue("Proportion missing: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Proportion Missing";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the proportion of missing data in a character across taxa." ;
+   	 }
+}
+
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyDown.gif b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyDown.gif
new file mode 100644
index 0000000..aae11b7
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyDown.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyLeft.gif b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyLeft.gif
new file mode 100644
index 0000000..02bbb79
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyLeft.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyRight.gif b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyRight.gif
new file mode 100644
index 0000000..aa0bea5
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeyRight.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector copy.gif b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector copy.gif
new file mode 100644
index 0000000..6458573
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector copy.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector.gif b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector.gif
new file mode 100644
index 0000000..98f0b4a
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/32quickKeySelector.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyDown.gif b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyDown.gif
new file mode 100644
index 0000000..e39d36f
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyDown.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyLeft.gif b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyLeft.gif
new file mode 100644
index 0000000..2bf9e40
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyLeft.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyRight.gif b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyRight.gif
new file mode 100644
index 0000000..63983c9
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeyRight.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector copy.gif b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector copy.gif
new file mode 100644
index 0000000..f0c28b9
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector copy.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector.gif b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector.gif
new file mode 100644
index 0000000..389c7bd
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/64quickKeySelector.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/QuickKeySelector.java b/Source/mesquite/charMatrices/QuickKeySelector/QuickKeySelector.java
new file mode 100644
index 0000000..4eb1710
--- /dev/null
+++ b/Source/mesquite/charMatrices/QuickKeySelector/QuickKeySelector.java
@@ -0,0 +1,252 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.QuickKeySelector; //DRM started April 02
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class QuickKeySelector extends DataWindowAssistantI implements ToolKeyListener {
+	TableTool quickKeySelectorTool;
+	CategoricalData data;
+	MesquiteTable table;
+	MesquiteBoolean autotabOff, autotabDown, autotabRight, autotabLeft;
+	MesquiteCommand keyCommand;
+	public String getFunctionIconPath(){
+		return getPath() + "quickKeySelector.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			quickKeySelectorTool = new TableTool(this, "quickKeySelector", getPath(), "quickKeySelector.gif", 4,4,"Select and type", "This tool allows you to select cells; any keystrokes will then be entered into selected cells.", null, null, null);  //MesquiteModule.makeCommand("quickKeySelectorTouch",  this) 
+			quickKeySelectorTool.setToolKeyListener(this);
+			quickKeySelectorTool.setUseTableTouchRules(true);
+			//quickKeySelectorTool.setAllowAnnotate(true);
+			((MesquiteWindow)containerOfModule()).addTool(quickKeySelectorTool);
+			autotabOff = new MesquiteBoolean(true);
+			autotabDown = new MesquiteBoolean(false);
+			autotabRight = new MesquiteBoolean(false);
+			autotabLeft = new MesquiteBoolean(false);
+			keyCommand = new MesquiteCommand("enter", this);
+			addCheckMenuItem(null, "Autotab Off", MesquiteModule.makeCommand("autotabOff", this), autotabOff);
+			addCheckMenuItem(null, "Autotab Down", MesquiteModule.makeCommand("autotabDown", this), autotabDown);
+			addCheckMenuItem(null, "Autotab Right", MesquiteModule.makeCommand("autotabRight", this), autotabRight);
+			addCheckMenuItem(null, "Autotab Left", MesquiteModule.makeCommand("autotabLeft", this), autotabLeft);
+			quickKeySelectorTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching oning button
+		}
+		else return false;
+		return true;
+	}
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (autotabDown.getValue())
+			temp.addLine("autotabDown");
+		else if (autotabRight.getValue())
+			temp.addLine("autotabRight");
+		else if (autotabLeft.getValue())
+			temp.addLine("autotabLeft");
+		else
+			temp.addLine("autotabOff");
+		return temp;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "turns off autotab", null, commandName, "autotabOff")) {
+			autotabOff.setValue(true);
+			autotabDown.setValue(false);
+			autotabRight.setValue(false);
+			autotabLeft.setValue(false);
+			quickKeySelectorTool.setImageFileName( "quickKeySelector.gif");
+			MesquiteWindow w = (MesquiteWindow)containerOfModule();
+			if (w != null && w.getCurrentTool() == quickKeySelectorTool)
+				w.resetCursor();
+		}
+		else if (checker.compare(this.getClass(), "turns on autotab down", null, commandName, "autotabDown")) {
+			autotabOff.setValue(false);
+			autotabDown.setValue(true);
+			autotabRight.setValue(false);
+			autotabLeft.setValue(false);
+			quickKeySelectorTool.setImageFileName( "quickKeyDown.gif");
+			MesquiteWindow w = (MesquiteWindow)containerOfModule();
+			if (w != null && w.getCurrentTool() == quickKeySelectorTool)
+				w.resetCursor();
+		}
+		else if (checker.compare(this.getClass(), "turns on autotab right", null, commandName, "autotabRight")) {
+			autotabOff.setValue(false);
+			autotabDown.setValue(false);
+			autotabRight.setValue(true);
+			autotabLeft.setValue(false);
+			quickKeySelectorTool.setImageFileName( "quickKeyRight.gif");
+			MesquiteWindow w = (MesquiteWindow)containerOfModule();
+			if (w != null && w.getCurrentTool() == quickKeySelectorTool)
+				w.resetCursor();
+		}
+		else if (checker.compare(this.getClass(), "turns on autotab left", null, commandName, "autotabLeft")) {
+			autotabOff.setValue(false);
+			autotabDown.setValue(false);
+			autotabRight.setValue(false);
+			autotabLeft.setValue(true);
+			quickKeySelectorTool.setImageFileName( "quickKeyLeft.gif");
+			MesquiteWindow w = (MesquiteWindow)containerOfModule();
+			if (w != null && w.getCurrentTool() == quickKeySelectorTool)
+				w.resetCursor();
+		}
+		else if (checker.compare(this.getClass(), "Enters a keyed value", null, commandName, "enter")) {
+			String value = parser.getFirstToken(arguments);
+			if (!StringUtil.blank(value))
+				enterValue(value);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data instanceof CategoricalData)
+			this.data = (CategoricalData)data;
+		else
+			this.data = null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Quick Key Entry";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to quickly enter data.  If this tool is active, then typing a key will cause that value to be entered into all selected cells.";
+	}
+	/*.................................................................................................................*/
+	public void keyTyped(KeyEvent e, MesquiteTool tool){
+	}
+	/*.................................................................................................................*/
+	public void keyPressed(KeyEvent e, MesquiteTool tool){
+	}
+	private void enterValue(String s){
+		if (s == null || s.length()==0)
+			return;
+		char c = s.charAt(0);
+		if (!data.isAcceptableCharForState(c))
+			return;
+		boolean success = false;
+		int count=0;
+		int row=0;
+		int column = 0;
+		boolean applicableBefore = false;
+		boolean applicabilitySame = false;
+		if (table.anyCellSelected()) {
+			for (int i=0; i<table.getNumColumns(); i++)
+				for (int j=0; j<table.getNumRows(); j++)
+					if (table.isCellSelected(i,j)) {
+						applicableBefore = data.isInapplicable(i, j);
+						data.setState(i,j, c);
+						applicabilitySame = applicableBefore == data.isInapplicable(i, j);
+						count++;
+						row = j;
+						column = i;
+					}
+			success = true;
+		}
+		if (table.anyRowSelected()) {
+			for (int j=0; j<table.getNumRows(); j++) {
+				if (table.isRowSelected(j))
+					for (int i=0; i<table.getNumColumns(); i++) {
+						applicableBefore = data.isInapplicable(i, j);
+						data.setState(i,j, c);
+						applicabilitySame = applicableBefore == data.isInapplicable(i, j);
+						count++;
+						row = j;
+						column = i;
+					}
+			}
+			success = true;
+		}
+		if (table.anyColumnSelected()) {
+			for (int i=0; i<table.getNumColumns(); i++){
+				if (table.isColumnSelected(i))
+					for (int j=0; j<table.getNumRows(); j++) {
+						applicableBefore = data.isInapplicable(i, j);
+						data.setState(i,j, c);
+						applicabilitySame = applicableBefore == data.isInapplicable(i, j);
+						count++;
+						row = j;
+						column = i;
+					}
+			}
+			success = true;
+		}
+		if (success){
+			table.repaintAll();
+			if (count==1) {
+				int[] subcodes = new int[] {MesquiteListener.SINGLE_CELL};
+				if (applicabilitySame)
+					subcodes = new int[] {MesquiteListener.SINGLE_CELL, MesquiteListener.CELL_SUBSTITUTION};
+				Notification notification = new Notification(MesquiteListener.DATA_CHANGED, new int[] {column, row}, null);
+				notification.setSubcodes(subcodes);
+				data.notifyListeners(this, notification);
+			}
+			else
+				data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		}
+		if (autotabDown.getValue() || autotabRight.getValue() || autotabLeft.getValue()){
+			if (table.singleTableCellSelected()){
+				if (autotabDown.getValue())
+					table.downArrowPressed(null);
+				else if (autotabRight.getValue())
+					table.rightArrowPressed(null);
+				else if (autotabLeft.getValue())
+					table.leftArrowPressed(null);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void keyReleased(KeyEvent e, MesquiteTool tool){
+		if (data == null)
+			return;
+		if (data.getEditorInhibition()){
+			discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+			return;
+		}
+		if (MesquiteEvent.commandOrControlKeyDown(MesquiteEvent.getModifiers(e)))
+			return;
+		if (!data.isAcceptableCharForState(e.getKeyChar()))
+			return;
+		keyCommand.doItMainThread("" + e.getKeyChar(), null, this); //29Mar08 put onto main thread as is standard, i.e. to avoid reentrancy issues & avoid its being treated as scripting
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/quickKeyDown.gif b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyDown.gif
new file mode 100644
index 0000000..ed5b10e
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyDown.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/quickKeyLeft.gif b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyLeft.gif
new file mode 100644
index 0000000..9e7cdf4
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyLeft.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/quickKeyRight.gif b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyRight.gif
new file mode 100644
index 0000000..72e9445
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/quickKeyRight.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector copy.gif b/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector copy.gif
new file mode 100644
index 0000000..65f2543
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector copy.gif differ
diff --git a/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector.gif b/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector.gif
new file mode 100644
index 0000000..586dc30
Binary files /dev/null and b/Source/mesquite/charMatrices/QuickKeySelector/quickKeySelector.gif differ
diff --git a/Source/mesquite/charMatrices/RandomFillCateg/RandomFillCateg.java b/Source/mesquite/charMatrices/RandomFillCateg/RandomFillCateg.java
new file mode 100644
index 0000000..a0abf40
--- /dev/null
+++ b/Source/mesquite/charMatrices/RandomFillCateg/RandomFillCateg.java
@@ -0,0 +1,146 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.RandomFillCateg;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RandomFillCateg extends CategDataAlterer {
+	CharacterState fillState;
+	int maxState = 1;
+	Random rng;
+
+	double probAlter = 1.0;
+	boolean alterOnlyNonGapCells = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random();
+		rng.setSeed(System.currentTimeMillis());
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions(boolean queryMaxState) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Random Fill",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Random Fill");
+		dialog.appendToHelpString("Each state is chosen equiprobably when filling the matrix randomly.");
+		IntegerField maximumStateField =null;
+		if (queryMaxState)
+			maximumStateField = dialog.addIntegerField("Maximum State:", maxState, 8);
+		DoubleField probAlterField = dialog.addDoubleField("Probability of altering each cell: ", probAlter, 6);
+		Checkbox alterOnlyNonGapCellsBox = dialog.addCheckBox("fill only those cells currently containing data or missing values", alterOnlyNonGapCells);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			if (queryMaxState && maximumStateField!=null)
+				maxState = maximumStateField.getValue();
+			probAlter = probAlterField.getValue();
+			alterOnlyNonGapCells = alterOnlyNonGapCellsBox.getState();
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData data, int ic, int it){
+		double alterTest = rng.nextDouble();
+		if (alterTest<=probAlter){
+			if (alterOnlyNonGapCells) {
+				if (!((CategoricalData)data).isInapplicable(ic,it))
+					((CategoricalData)data).setState(ic,it, randomState());
+			}
+			else ((CategoricalData)data).setState(ic,it, randomState());
+			if (!MesquiteLong.isCombinable(numCellsAltered))
+				numCellsAltered = 0;
+			numCellsAltered++;
+		}
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof CategoricalData))
+			return false;
+		boolean queryState=false;
+		if (data instanceof DNAData)
+			maxState = 3;
+		else if (data instanceof ProteinData)
+			maxState = 19;
+		else {	
+			maxState=1;
+			queryState = true;
+		}
+		if (!MesquiteThread.isScripting())
+			if (!queryOptions(queryState))
+				return false;
+		/*		else {
+				maxState = MesquiteInteger.queryInteger(containerOfModule(), "Maximum State", "Each state is chosen equiprobably when filling the matrix randomly.  What should be the maximum state value?", 1, 1, 50, true);
+				if (!MesquiteInteger.isCombinable(maxState))
+					return false;
+			}
+		 */
+		return alterContentOfCells(data,table, undoReference);
+	}
+
+	//	Double d = new Double(value);
+
+	/*.................................................................................................................*/
+	long randomState(){
+		double value = rng.nextDouble() * (maxState+1);
+		int e = (int)value;
+		if ((e>=0)&&(e<=CategoricalState.maxCategoricalState))
+			return CategoricalState.makeSet(e);
+		else {
+			return CategoricalState.makeSet(0);
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Random Fill (Categorical)";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Random Fill (Categorical)...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Fills cells with a randomly-chosen state. For DNA data, states A, C, G, and T are chosen with equal probability; for other data, states up to and including the maximum state value are chosen with equal probability." ;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/RandomFillWithMissing/RandomFillWithMissing.java b/Source/mesquite/charMatrices/RandomFillWithMissing/RandomFillWithMissing.java
new file mode 100644
index 0000000..c5088f7
--- /dev/null
+++ b/Source/mesquite/charMatrices/RandomFillWithMissing/RandomFillWithMissing.java
@@ -0,0 +1,111 @@
+package mesquite.charMatrices.RandomFillWithMissing;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RandomFillWithMissing extends CategDataAlterer {
+	Random rng;
+
+	double probAlter = 1.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random();
+		rng.setSeed(System.currentTimeMillis());
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Convert Some Cells to Missing",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Convert Some Cells to Missing");
+		DoubleField probAlterField = dialog.addDoubleField("Probability of converting a cell to missing data: ", probAlter, 6);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			probAlter = probAlterField.getValue();
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData data, int ic, int it){
+		double alterTest = rng.nextDouble();
+		if (alterTest<=probAlter) {
+			((CategoricalData)data).setState(ic,it,CategoricalState.unassigned);
+			if (!MesquiteLong.isCombinable(numCellsAltered))
+				numCellsAltered = 0;
+			numCellsAltered++;
+		}
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!MesquiteThread.isScripting())
+			if (!queryOptions())
+				return false;
+		return alterContentOfCells(data,table, undoReference);
+	}
+
+	//	Double d = new Double(value);
+
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Sprinkle Missing in Cells...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Sprinkle Missing in Cells";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Fills cells with a missing data with a specified probability." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/charMatrices/RandomModRespMatrices/RandomModRespMatrices.java b/Source/mesquite/charMatrices/RandomModRespMatrices/RandomModRespMatrices.java
new file mode 100644
index 0000000..28419b0
--- /dev/null
+++ b/Source/mesquite/charMatrices/RandomModRespMatrices/RandomModRespMatrices.java
@@ -0,0 +1,205 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.RandomModRespMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class RandomModRespMatrices extends SourceModRespectiveMatrix {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(RandomMatrixModifier.class, getName() + " needs a method to randomly modify the matrices.",
+				"You can request how matrices are randomly modified either initially, or later under the Random Modifier of Matrix submenu.");
+	}
+	MCharactersDistribution matrix;
+	int currentMatrix;
+	RandomBetween rng;
+	MesquiteLong seed;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	RandomMatrixModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+ 		if (!super.startJob(arguments, condition, hiredByName))
+ 			return false;
+
+		if (arguments ==null)
+ 			modifierTask = (RandomMatrixModifier)hireEmployee(RandomMatrixModifier.class, "Random modifier of matrices");
+	 	else {
+	 		modifierTask = (RandomMatrixModifier)hireNamedEmployee(RandomMatrixModifier.class, arguments);
+ 			if (modifierTask == null)
+ 				modifierTask = (RandomMatrixModifier)hireEmployee(RandomMatrixModifier.class, "Random modifier of matrices");
+ 		}
+
+ 		if (modifierTask == null) {
+ 			return sorry(getName() + " couldn't start because no random matrix modifier was obtained.");
+ 		}
+
+	 	stC = makeCommand("setModifier",  this);
+ 	 	modifierTask.setHiringCommand(stC);
+ 		modifierName = new MesquiteString();
+	 	  modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(RandomMatrixModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Random Modifier of Matrices", stC, RandomMatrixModifier.class);
+ 			mss.setSelected(modifierName);
+  		}
+ 	 	seed = new MesquiteLong(1);
+ 	 	seed.setValue(originalSeed);
+  		addMenuItem("Set Seed (Random matrix modification)...", makeCommand("setSeed",  this));
+	 	rng= new RandomBetween(originalSeed);
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return RandomMatrixModifier.class;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the matrix modifier", "[name of module]", commandName, "setModifier")) {
+				RandomMatrixModifier temp = (RandomMatrixModifier)replaceEmployee(RandomMatrixModifier.class, arguments, "Random modifier of matrices", modifierTask);
+				if (temp !=null){
+					modifierTask = temp;
+	    	 			modifierName.setValue(modifierTask.getName());
+			 	 	modifierTask.setHiringCommand(stC);
+					parametersChanged();
+	    	 			return modifierTask;
+	    	 		}
+    	 	}
+     	  	else	if (checker.compare(this.getClass(), "Sets the random number seed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for random matrix modification", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+  	 
+	/*.................................................................................................................*/
+  	private MCharactersDistribution getM(Taxa taxa, int iM){
+		rng.setSeed(originalSeed); 
+		long rnd =originalSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+   		for (int i=0; i < iM; i++)
+   			rnd = rng.nextInt();
+		rng.setSeed(rnd+1);
+ 		seed.setValue(rnd + 1);  //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+ 			
+		MCharactersDistribution matrix = getBasisMatrix(taxa, iM); //TODO: shouldn't have to do this for every matrix, just first after change of currentMatrix
+		if (matrix==null)
+			return null;
+		MAdjustableDistribution modified = matrix.makeBlankAdjustable();
+		
+	   	modifierTask.modifyMatrix(matrix, modified, rng);
+		String origName = null;
+		
+   		if (matrix.getName()!=null)
+   			origName = "matrix " + matrix.getName();
+   		else if (matrix.getParentData() != null)
+   			origName = "matrix " + matrix.getParentData().getName();
+   		else
+   			origName = "unknown matrix";
+
+   		modified.setName( "Random Modification of  " + origName + " by " + modifierTask.getName());
+  		return modified;
+   	}
+	/*.................................................................................................................*/
+    	 public String getMatrixName(Taxa taxa, int ic) {
+   		return "Random Modification of  matrix " + (ic + 1 ) + " by " + modifierTask.getName();
+   	 }
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+   		return getM(taxa, currentMatrix);
+   	}
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+   		currentMatrix = im;
+   		return getM(taxa, im);
+   	}
+	/*.................................................................................................................*/
+   	/** returns the number of the current matrix*/
+   	public int getNumberCurrentMatrix(){
+   		return (int)currentMatrix;
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		if (matrix==null) return "";
+   		String origName = "";
+   		if (matrix.getName()!=null)
+   			origName = "matrix " + matrix.getName();
+   		else if (matrix.getParentData() != null)
+   			origName = "matrix " + matrix.getParentData().getName();
+   		else
+   			origName = "unknown matrix";
+		return "Matrix modification: " + origName + ". [seed: " + originalSeed + "]";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		return "Randomly Modify Respective Matrices";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+    	/*.................................................................................................................*/
+    	public boolean isPrerelease(){
+    		return false;
+    	}
+
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies character matrices that are randomly modified from a series of existing matrices.  The i'th modified matrix is derived from the i'th original matrix." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/RandomModifMatrix/RandomModifMatrix.java b/Source/mesquite/charMatrices/RandomModifMatrix/RandomModifMatrix.java
new file mode 100644
index 0000000..0a880ce
--- /dev/null
+++ b/Source/mesquite/charMatrices/RandomModifMatrix/RandomModifMatrix.java
@@ -0,0 +1,197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.RandomModifMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class RandomModifMatrix extends SourceModifiedMatrix {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(RandomMatrixModifier.class, getName() + " needs a method to randomly modify matrices.",
+				"You can request how matrices are randomly modified either initially, or later under the Random Modifier of Matrix submenu.");
+	}
+	MCharactersDistribution matrix;
+	long currentModification;
+	RandomBetween rng;
+	MesquiteLong seed;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	RandomMatrixModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		if (!super.startJob(arguments, condition, hiredByName))
+ 			return false;
+ 		if (arguments ==null)
+ 			modifierTask = (RandomMatrixModifier)hireEmployee(RandomMatrixModifier.class, "Random modifier of matrix");
+	 	else {
+	 		modifierTask = (RandomMatrixModifier)hireNamedEmployee(RandomMatrixModifier.class, arguments);
+ 			if (modifierTask == null)
+ 				modifierTask = (RandomMatrixModifier)hireEmployee(RandomMatrixModifier.class, "Random modifier of matrix");
+ 		}
+ 		if (modifierTask == null) {
+ 			return sorry(getName() + " couldn't start because no random matrix modifier was obtained.");
+ 		}
+ 	 	stC = makeCommand("setModifier",  this);
+ 	 	modifierTask.setHiringCommand(stC);
+ 		modifierName = new MesquiteString();
+	 	  modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(RandomMatrixModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Random Modifier of Matrix", stC, RandomMatrixModifier.class);
+ 			mss.setSelected(modifierName);
+  		}
+ 	 	seed = new MesquiteLong(1);
+ 	 	seed.setValue(originalSeed);
+  		addMenuItem("Set Seed (Random matrix modification)...", makeCommand("setSeed",  this));
+	 	rng= new RandomBetween(originalSeed);
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return RandomMatrixModifier.class;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the matrix modifier", "[name of module]", commandName, "setModifier")) {
+				RandomMatrixModifier temp = (RandomMatrixModifier)replaceEmployee(RandomMatrixModifier.class, arguments, "Random modifier of matrix", modifierTask);
+				if (temp !=null){
+					modifierTask = temp;
+	    	 			modifierName.setValue(modifierTask.getName());
+			 	 	modifierTask.setHiringCommand(stC);
+					parametersChanged();
+	    	 			return modifierTask;
+	    	 		}
+    	 	}
+    	 	 else	if (checker.compare(this.getClass(), "Sets the random number seed", "[long integer seed]", commandName, "setSeed")) {
+    	 		 long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		 if (!MesquiteLong.isCombinable(s)){
+    	 			 s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for random matrix modification", originalSeed);
+    	 		 }
+    	 		 if (MesquiteLong.isCombinable(s)){
+    	 			 originalSeed = s;
+    	 			 parametersChanged(); //?
+    	 		 }
+    	 	 }
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+  	 
+	/*.................................................................................................................*/
+  	private MCharactersDistribution getM(Taxa taxa){
+		rng.setSeed(originalSeed); 
+		long rnd =originalSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+   		for (int i=0; i < currentModification; i++)
+   			rnd = rng.nextInt();
+		rng.setSeed(rnd+1);
+  		seed.setValue(rnd + 1);  //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+ 			
+		MCharactersDistribution matrix = getBasisMatrix(taxa); //TODO: shouldn't have to do this for every matrix, just first after change of currentMatrix
+		if (matrix==null)
+			return null;
+		MAdjustableDistribution modified = matrix.makeBlankAdjustable();
+		
+	   	modifierTask.modifyMatrix(matrix, modified, rng);
+		String origName = null;
+		
+   		if (matrix.getName()!=null)
+   			origName = "matrix " + matrix.getName();
+   		else if (matrix.getParentData() != null)
+   			origName = "matrix " + matrix.getParentData().getName();
+   		else
+   			origName = "unknown matrix";
+
+   		modified.setName( "Modification #" + (currentModification+1) + " of  " + origName + " by " + modifierTask.getName());
+  		return modified;
+   	}
+	/*.................................................................................................................*/
+    	 public String getMatrixName(Taxa taxa, int ic) {
+   		return "Modification #" + (ic+1) + " of  matrix by " + modifierTask.getName();
+   	 }
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+   		currentModification = im;
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+    	public  int getNumberOfMatrices(Taxa taxa){
+    		return MesquiteInteger.infinite; //TODO: convert all these to MesquiteInteger.infinite
+    	}
+	/*.................................................................................................................*/
+   	/** returns the number of the current matrix*/
+   	public int getNumberCurrentMatrix(){
+   		return (int)currentModification;
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		if (matrix==null) return "";
+   		String origName = "";
+   		if (matrix.getName()!=null)
+   			origName = "matrix " + matrix.getName();
+   		else if (matrix.getParentData() != null)
+   			origName = "matrix " + matrix.getParentData().getName();
+   		else
+   			origName = "unknown matrix";
+		return "Matrix modification: " + origName + ". [seed: " + originalSeed + "]";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		return "Randomly Modify Matrix";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies character matrices that are randomly modified from an existing matrix." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/RarefyMatrix/RarefyMatrix.java b/Source/mesquite/charMatrices/RarefyMatrix/RarefyMatrix.java
new file mode 100644
index 0000000..fd509ce
--- /dev/null
+++ b/Source/mesquite/charMatrices/RarefyMatrix/RarefyMatrix.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.RarefyMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class RarefyMatrix extends RandomMatrixModifier {
+	int numDeleted=1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		if (!MesquiteThread.isScripting()){
+    	 	int s = MesquiteInteger.queryInteger(containerOfModule(), "Number of characters to delete", "Enter the number of randomly chosen characters to delete", numDeleted);
+ 	 		if (MesquiteInteger.isCombinable(s) && s >=0)
+ 	 			numDeleted = s;
+ 	 		else
+ 				return false;
+  		}
+  		addMenuItem("Number of Characters Deleted...", makeCommand("setNumberDeleted",  this));
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setNumberDeleted " + numDeleted);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	if (checker.compare(this.getClass(), "Sets the number of randomly chosen characters to delete", "[number]", commandName, "setNumberDeleted")) {
+    	 		int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteInteger.isCombinable(s) && !MesquiteThread.isScripting()){
+    	 			s = MesquiteInteger.queryInteger(containerOfModule(), "Number of characters to delete", "Enter the number of randomly chosen characters to delete", numDeleted);
+    	 		}
+    	 		if (MesquiteInteger.isCombinable(s) && s>=0){
+    	 			numDeleted = s;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null || numDeleted < 0)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+   		int numTK = numChars-numDeleted;
+   		if (numTK<0)
+   			numTK = 0;
+   			
+		boolean[] toKeep = randomBits(numChars, numTK, rng);
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numTK)
+			modified.setSize(numTK, numTaxa);
+		int count = 0;
+		for (int ic = 0; ic<numChars; ic++) {
+	   		if (toKeep[ic])
+	   			modified.transferFrom(count++, matrix.getCharacterDistribution(ic));
+ 	 	}
+   	}
+	boolean[] randomBits(int total, int on, RandomBetween rng){
+		boolean[] bits = new boolean[total];
+   		for (int i=0; i < total; i++)
+   			bits[i] = (i<on);
+		
+   		for (int i=0; i < (total-1); i++) { //randomly scramble
+   			int sh = rng.randomIntBetween(i, total-1);
+   			if (i!=sh){
+	   			boolean bsh = bits[sh];
+	   			bits[sh] = bits[i];
+	   			bits[i]=bsh;
+   			}
+   		}
+   		return bits;
+	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Number of characters deleted randomly: " + numDeleted;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		return "Rarefy Characters";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+  	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Deletes characters randomly to rarefy matrix." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/RecodeCateg/RecodeCateg.java b/Source/mesquite/charMatrices/RecodeCateg/RecodeCateg.java
new file mode 100644
index 0000000..80bbd9d
--- /dev/null
+++ b/Source/mesquite/charMatrices/RecodeCateg/RecodeCateg.java
@@ -0,0 +1,332 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.RecodeCateg;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RecodeCateg extends CategDataAlterer {
+	long[] rules;
+	int maxState = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rules = new long[64];
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData cData, int ic, int it){
+   		if (cData instanceof CategoricalData) { //this does not do state names recoding!
+   		}
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+			
+			if (!(cData instanceof CategoricalData)){
+				discreetAlert( "Only categorical characters can be recoded by this module.");
+				return false;
+			}
+			if (!cData.anySelected()){
+				discreetAlert( "To recode characters, please select entire characters first.");
+				return false;
+			}
+			CategoricalData data = (CategoricalData)cData;
+   			if (data instanceof DNAData || data instanceof ProteinData) {
+				if (!MesquiteThread.isScripting())
+					alert("Molecular characters cannot be recoded.");
+				return false;
+			}
+			else {
+		  		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+				// first find maximum state among character selected
+				maxState = 0;
+				for (int ic = 0; ic < data.getNumChars(); ic++){
+					if (data.getSelected(ic)){
+						int icMax = data.getMaxState(ic);
+						if (icMax > maxState)
+							maxState = icMax;
+					}
+				}
+				for (int ic = 0; ic < data.getNumChars(); ic++){
+					if (data.getSelected(ic)){
+						int m = -1;
+						for (int is = maxState; is<= CategoricalState.maxCategoricalState; is++)
+							if (data.hasStateName(ic, is))
+								m = is;
+						if (m > maxState)
+							maxState = m;
+					}
+				}
+				String[] states = new String[maxState+3];
+				for (int i = 0; i< maxState +1; i++) {
+					rules[i] = CategoricalState.makeSet(i);
+					states[i] = "state " + RecodeDialog.stateToString(rules[i], data);
+				}
+				states[maxState+1] = "? (missing)";
+				rules[maxState+1] = CategoricalState.unassigned;
+				states[maxState+2] = "- (inapplicable)";
+				rules[maxState+2] = CategoricalState.inapplicable;
+				
+				
+				MesquiteInteger chosen = new MesquiteInteger();
+				RecodeDialog dialog = new RecodeDialog(this, data, states, rules, chosen, maxState);
+				dialog.dispose();
+				if (!anyChanges(maxState) || chosen.isUnassigned())
+					return false;
+				for (int ic = 0; ic< data.getNumChars(); ic++){
+					if (data.getSelected(ic))
+						data.recodeStates(ic, rules, maxState);
+				}
+				if (undoInstructions!=null) {
+					undoInstructions.setNewData(data);
+					if (undoReference!=null){
+						undoReference.setUndoer(undoInstructions);
+						undoReference.setResponsibleModule(this);
+					}
+				}
+			}
+   			return true;
+   	}
+
+   	private boolean anyChanges(int maxState){
+		for (int i = 0; i< maxState +1; i++) {
+			if (rules[i] != CategoricalState.makeSet(i))
+				return true;
+		}
+		if (rules[maxState+1] != CategoricalState.unassigned || rules[maxState+2] != CategoricalState.inapplicable)
+			return true;
+		return false;
+   	}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Recode Characters...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Recode Characters";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Recodes categorical data (e.g., state 1 to state 0)." ;
+   	 }
+   	 
+}
+
+class RecodeDialog extends ListDialog {
+	MesquiteModule ownerModule;
+	String[] states;
+	long[] rules;
+	SingleLineTextField text;
+	MesquiteInteger chosen;
+	int maxState=0;
+	CategoricalData data;
+	
+	public RecodeDialog(MesquiteModule ownerModule, CategoricalData data, String[] states, long[] rules, MesquiteInteger chosen, int maxState){
+		super(ownerModule.containerOfModule(), "Recode States", "Indicate recoding of states of selected characters", false, null, states, chosen, null, false, false); 
+
+		//parent, String title, String message, String helpString, Object names, MesquiteInteger selected, String thirdButton, boolean hasDefault, boolean multipleMode
+		this.ownerModule = ownerModule;
+		this.maxState = maxState;
+		this.chosen = chosen;
+		this.states = states;
+		this.data = data;
+		this.rules = rules;
+		text = addTextField("Recode to:", "", 3);
+		suppressNewPanel();
+
+
+		addAListenedButton("Enter",null,this);
+		suppressNewPanel();
+		addAListenedButton("Reset",null,this);
+
+		getList().setEnableDoubleClicks(false);
+		completeAndShowDialog();
+	}
+
+	private void enter(){
+		String s = text.getText();
+		if (StringUtil.blank(s)) {
+			return;
+		}
+		CategoricalState cat = stateFromString(s);
+		if (!cat.isImpossible()){
+			long recoding = cat.getValue();
+			java.awt.List list = getList();
+			for (int i=0; i<states.length; i++)
+				if (list.isIndexSelected(i)) {
+					assignRule(i, recoding);
+					//getList().replaceItem(states[i], i);
+				}
+			resetList();
+		}
+	}
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	String buttonLabel = e.getActionCommand();
+		if ("Reset".equalsIgnoreCase(buttonLabel)){  // Reset button is pressed
+			java.awt.List list = getList();
+			for (int i=0; i<states.length; i++)
+				if (list.isIndexSelected(i)) {
+					if (i<=maxState) {
+						rules[i] = CategoricalState.makeSet(i);
+						states[i] = "state " + RecodeDialog.stateToString(rules[i], data);
+					}
+					else if (i == maxState+1){
+						states[maxState+1] = "? (missing)";
+						rules[maxState+1] = CategoricalState.unassigned;
+					}
+					else if (i == maxState +2){
+						states[maxState+2] = "- (inapplicable)";
+						rules[maxState+2] = CategoricalState.inapplicable;
+					}
+				}
+			text.setText("");
+			resetList();
+		}
+		else if ("Enter".equalsIgnoreCase(buttonLabel)){   // Enter button is pressed
+			enter();
+		}
+		else if ("Cancel".equalsIgnoreCase(buttonLabel)){   // Enter button is pressed
+			dispose();
+		}
+		else
+			super.actionPerformed(e);
+	}
+		/*.................................................................................................................*/
+		public void buttonHit(String buttonLabel, Button button) {
+			if (buttonLabel!=null)
+				if (buttonLabel.equalsIgnoreCase("Reset")){
+					java.awt.List list = getList();
+					for (int i=0; i<states.length; i++)
+						if (list.isIndexSelected(i)) {
+							if (i<=maxState) {
+								rules[i] = CategoricalState.makeSet(i);
+								states[i] = "state " + RecodeDialog.stateToString(rules[i], data);
+							}
+							else if (i == maxState+1){
+								states[maxState+1] = "? (missing)";
+								rules[maxState+1] = CategoricalState.unassigned;
+							}
+							else if (i == maxState +2){
+								states[maxState+2] = "- (inapplicable)";
+								rules[maxState+2] = CategoricalState.inapplicable;
+							}
+						}
+					text.setText("");
+					resetList();
+				}
+				else if (buttonLabel.equalsIgnoreCase("Enter")){
+					enter();
+				}
+				else {
+					super.buttonHit(buttonLabel, button);
+				}
+		
+	}
+
+	public void itemStateChanged(ItemEvent e){
+		if (e.getStateChange() == ItemEvent.SELECTED && e.getItem() instanceof Integer){
+			if (super.numSelected() > 1)
+				text.setText("");
+			else {
+				int state = ((Integer)e.getItem()).intValue();
+				getList().makeVisible(state);
+				text.setText(stateToString(rules[state]));
+			}
+		}
+		else if (e.getStateChange() == ItemEvent.DESELECTED && e.getItem() instanceof Integer){
+			int state = ((Integer)e.getItem()).intValue();
+			String s = text.getText();
+			if (StringUtil.blank(s))
+				return;
+			CategoricalState cat = stateFromString(s);
+			if (cat.isImpossible())
+				return;
+			long recoding = cat.getValue();
+			assignRule(state, recoding);
+			resetList();
+			//getList().replaceItem(states[state], state);
+		}
+	}
+   	public CategoricalState stateFromString(String s){
+   		CategoricalState cs = new CategoricalState();
+   		cs.setValue(s, data);
+   		return cs;
+   	}
+	static String stateToString(long s, CategoricalData data){
+		return CategoricalState.toString(s, data, 0, false, true);
+	}
+	private String stateToString(long s){
+		return CategoricalState.toString(s, data, 0, false, true);
+	}
+	public String textForState(int state, int maxState, long recoding){
+		if (state == maxState + 1) { // unassigned
+			if (recoding == CategoricalState.unassigned)
+				return "? (missing)";
+			else
+				return  "? (missing) recode to " + stateToString(rules[state]);
+		}
+		else if (state ==  maxState + 2) { // inapplicable
+			if (recoding == CategoricalState.inapplicable)
+				return  "- (inapplicable)";
+			else
+				return  "- (inapplicable) recode to " + stateToString(rules[state]);
+		}
+		else if (state <=maxState) {
+			long orig = CategoricalState.makeSet(state);
+			if (recoding == orig)
+				return  "state " + stateToString(orig);
+			else
+				return  "state " + stateToString(orig) + " recode to " + stateToString(rules[state]);
+		}
+		return "";
+	}
+	private void assignRule(int state, long recoding){
+		if (recoding == CategoricalState.impossible)
+			return;
+		if (state>=rules.length || recoding == rules[state]) //no change
+			return;
+		rules[state] = recoding;
+		states[state] = textForState(state, maxState, recoding);
+	}
+	
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/ReshuffleCharacter/ReshuffleCharacter.java b/Source/mesquite/charMatrices/ReshuffleCharacter/ReshuffleCharacter.java
new file mode 100644
index 0000000..85d42ab
--- /dev/null
+++ b/Source/mesquite/charMatrices/ReshuffleCharacter/ReshuffleCharacter.java
@@ -0,0 +1,259 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ReshuffleCharacter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ReshuffleCharacter extends CharacterSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DataSearcher.class, getName() + " needs a source of the original character to be reshuffled.",
+				"The source of the original character is chosen initially.");
+	}
+	long currentShuffle=0;
+	int currentOriginalChar = -1;  //to force a query
+	MatrixSourceCoord dataTask;
+	MCharactersDistribution matrix;
+	CharacterDistribution states;
+	int currentDataSet = 0;
+	RandomBetween randomTaxon;
+	MesquiteLong seed;
+	Taxa oldTaxa =null;
+		long originalSeed=System.currentTimeMillis(); //0L;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		if (condition!=null)
+			dataTask = (MatrixSourceCoord)hireCompatibleEmployee( MatrixSourceCoord.class, condition, "Source of matrices for Reshuffle Character");
+ 		else
+			dataTask = (MatrixSourceCoord)hireEmployee( MatrixSourceCoord.class, "Source of matrices for Reshuffle Character");
+		if (dataTask == null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+   		currentShuffle = 0;
+	 	randomTaxon= new RandomBetween(originalSeed);
+    	 	seed = new MesquiteLong(1);
+    	 	seed.setValue(originalSeed);
+    	
+		addMenuItem("Shuffle Next Character", makeCommand("shuffleNext",  this));
+		addMenuItem("Shuffle Previous Character", makeCommand("shufflePrevious",  this));
+		addMenuItem("Choose Character to Shuffle", makeCommand("chooseCharacter",  this));
+  		addMenuItem("Set Seed (Reshuffle character)...", makeCommand("setSeed",  this));
+	 	return true;
+  	 }
+  	 
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getCharacterSource ", dataTask);
+  	 	temp.addLine("setCharacter " + CharacterStates.toExternal(currentOriginalChar));
+  	 	temp.addLine("setShuffle " + CharacterStates.toExternal((int)currentShuffle));
+   	 	temp.addLine("setSeed " + originalSeed);
+	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Does shuffle of the next character", null, commandName, "shuffleNext")) {
+    	 		if (currentOriginalChar>=matrix.getNumChars()-1)
+    	 			currentOriginalChar=0;
+    	 		else
+    	 			currentOriginalChar++;
+    	 		currentShuffle = 0;
+	 		((AdjustableDistribution)states).setParentCharacter(currentOriginalChar);
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Indicates which shuffle of the character", null, commandName, "setShuffle")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (s >= 0 && MesquiteLong.isCombinable(s) && s != currentShuffle){
+    	 			currentShuffle = s;
+				parametersChanged();
+			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the source of matrices on which to do ordinations", null, commandName, "setCharacterSource")) { //TEMPORARY for data files using old system without coordinators
+    	 		if (dataTask != null)
+    	 			return dataTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns employee that is character source", null, commandName, "getCharacterSource")) {
+    	 		return dataTask;
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character reshuffling", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries user about which character to shuffle", null, commandName, "chooseCharacter")) {
+			int ic = chooseCharacter(matrix);
+    	 		if (ic >= 0 && MesquiteInteger.isCombinable(ic)) {
+    	 			currentOriginalChar = ic;
+ 	   	 		currentShuffle = 0;
+		 		((AdjustableDistribution)states).setParentCharacter(currentOriginalChar);
+				parametersChanged();
+ 			}
+    	 	}
+  
+    	 	else if (checker.compare(this.getClass(), "Sets which character to shuffle", "[character number]", commandName, "setCharacter")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int icNum = MesquiteInteger.fromString(arguments, pos);
+ 	    	 	seed.setValue(originalSeed);
+   	 		if (!MesquiteInteger.isCombinable(icNum))
+    	 			return null;
+    	 		int ic = CharacterStates.toInternal(icNum);
+    	 		if (matrix == null || ((ic>=0) && (ic<=matrix.getNumChars()-1))) {
+    	 			currentOriginalChar = ic;
+ 	   	 		currentShuffle = 0;
+		 		if (states !=null)
+		 			((AdjustableDistribution)states).setParentCharacter(currentOriginalChar);
+				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Does shuffle of the previous character", null, commandName, "shufflePrevious")) {
+    	 		if (currentOriginalChar<=0)
+    	 			currentOriginalChar=matrix.getNumChars()-1;
+    	 		else
+    	 			currentOriginalChar--;
+    	 		currentShuffle = 0;
+	 		((AdjustableDistribution)states).setParentCharacter(currentOriginalChar);
+			parametersChanged();
+    	 	}
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+	private int chooseCharacter(MCharactersDistribution matrix){
+		if (matrix == null || matrix.getParentData()!=null) {
+	 		CharacterData data = matrix.getParentData();
+			String[] charNames = new String[data.getNumChars()];
+			for (int i=0; i<data.getNumChars(); i++)
+				charNames[i]= data.getCharacterName(i);
+ 			return ListDialog.queryList(containerOfModule(), "Choose character", "Choose character to shuffle", MesquiteString.helpString,charNames, 0);
+ 		}
+	 		
+		return MesquiteInteger.queryInteger(containerOfModule(), "Choose character", "Number of character to shuffle ", 1);
+ 	}
+	/*.................................................................................................................*/
+   	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+   		dataCheck(taxa);
+   		if (matrix == null)
+   			return null;
+   		currentShuffle = ic;
+   		if (currentOriginalChar<matrix.getNumChars()&& currentOriginalChar>=0 && currentShuffle>=0) {
+   			CharacterDistribution chs = matrix.getCharacterDistribution(currentOriginalChar);
+   			if (chs == null)
+   				return null;
+			states = (CharacterDistribution)chs.getAdjustableClone(); 
+			if (states == null)
+				return null;
+	 		((AdjustableDistribution)states).setParentCharacter(currentOriginalChar);
+			String mName = "";
+			if (matrix.getParentData() != null)
+				mName = " of " + matrix.getParentData().getName();
+   			states.setName( "Shuffle " + currentShuffle + " of character " + CharacterStates.toExternal(currentOriginalChar) + mName);  
+			
+			randomTaxon.setSeed(originalSeed); 
+	   		for (int i=0; i < currentShuffle; i++)
+	   			randomTaxon.nextInt();
+	   		randomTaxon.setSeed(randomTaxon.nextInt() + 1); //v. 1. 1 Oct 05, modified by adding 1 to prevent adjacent from simply being offsets
+	   		
+	   		int nT1 = states.getNumTaxa()-1;
+	   		for (int i=0; i < nT1; i++) {
+	   			int sh = randomTaxon.randomIntBetween(i, nT1);
+	   			if (i!=sh)
+	   				((AdjustableDistribution)states).tradeStatesBetweenTaxa(i, sh);
+	   		}
+	   		return states;
+	   	}
+   		else
+   			return null;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfCharacters(Taxa taxa) {
+   		dataCheck(taxa);
+   		if (matrix == null) 
+   			return 0;
+   		else 
+   			return MesquiteInteger.infinite;
+   	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	matrix = null;
+   	 	super.employeeParametersChanged( employee,  source, notification);
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		dataCheck(taxa);
+   	}
+	/*.................................................................................................................*/
+   	private void dataCheck(Taxa taxa) {
+   		if (matrix==null  || oldTaxa != taxa) {
+   			matrix = dataTask.getCurrentMatrix(taxa);
+   			if (matrix == null)
+   	   			currentOriginalChar = 0;  
+   			else if (currentOriginalChar<0 || currentOriginalChar>= matrix.getNumChars()) {
+	   			if (!MesquiteThread.isScripting())
+	   				currentOriginalChar = chooseCharacter(matrix);
+	   			if (!MesquiteInteger.isCombinable(currentOriginalChar) || currentOriginalChar<0 || currentOriginalChar>=matrix.getNumChars())
+	   	   			currentOriginalChar = 0;  
+			}
+   			currentShuffle = 0;
+   			oldTaxa = taxa;
+   		}
+   	}
+	/*.................................................................................................................*/
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Taxa taxa, int ic){
+      		return  "Shuffle " + ic + " of character ";
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		if (matrix==null) return "";
+		return "Character reshuffle: " + matrix.getName() + ". [seed: " + originalSeed + "]";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Reshuffle Character";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies characters that are reshufflings of an existing character." ;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+}
+
diff --git a/Source/mesquite/charMatrices/ReshuffleMatrix/ReshuffleMatrix.java b/Source/mesquite/charMatrices/ReshuffleMatrix/ReshuffleMatrix.java
new file mode 100644
index 0000000..ec45e8f
--- /dev/null
+++ b/Source/mesquite/charMatrices/ReshuffleMatrix/ReshuffleMatrix.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ReshuffleMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class ReshuffleMatrix extends RandomMatrixModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  	 	return true; 
+  	 }
+
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+
+		for (int ic = 0; ic<numChars; ic++) {
+	   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+	   		for (int i=0; i < (numTaxa-1); i++) {
+	   			int sh = rng.randomIntBetween(i, numTaxa-1);
+	   			if (sh != i)
+	   				modified.tradeStatesBetweenTaxa(ic, i, sh);
+	   		}
+ 	 	}
+   	}
+	/*.................................................................................................................*/
+    public String getName() {
+   		return "Reshuffle States Within Characters";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+ 	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shuffles (permutes) character states among taxa within each character." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/ReshuffleMatrixByPart/ReshuffleMatrixByPart.java b/Source/mesquite/charMatrices/ReshuffleMatrixByPart/ReshuffleMatrixByPart.java
new file mode 100644
index 0000000..0af9c7b
--- /dev/null
+++ b/Source/mesquite/charMatrices/ReshuffleMatrixByPart/ReshuffleMatrixByPart.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ReshuffleMatrixByPart;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.RandomMatrixModifier;
+
+/* ======================================================================== */
+public class ReshuffleMatrixByPart extends RandomMatrixModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  	 	return true; 
+  	 }
+
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+			
+		Taxa taxa = matrix.getTaxa();
+		TaxaPartition partition = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+		TaxaGroup[] groups = null;
+		if (partition != null)
+			groups = partition.getGroups();
+			
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+		if (groups == null){
+			for (int ic = 0; ic<numChars; ic++) {
+		   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+		   		for (int i=0; i < (numTaxa-1); i++) {
+		   			int sh = rng.randomIntBetween(i, numTaxa-1);
+		   			if (sh != i)
+		   				modified.tradeStatesBetweenTaxa(ic, i, sh);
+		   		}
+	 	 	}
+ 	 	}
+ 	 	else {
+			for (int ic = 0; ic<numChars; ic++) {
+		   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+		   		for (int g = 0; g< groups.length; g++){ //examining group
+		   			int numTaxaInGroup = partition.getNumberInGroup(groups[g]);
+		   			
+			   		for (int i=0; i < (numTaxaInGroup-1); i++) {
+			   			int sh = rng.randomIntBetween(i, numTaxaInGroup-1);
+			   			if (sh != i)
+			   				modified.tradeStatesBetweenTaxa(ic, getTaxonNumber(i, groups[g], taxa, partition), getTaxonNumber(sh, groups[g], taxa, partition));
+			   		}
+		   		}
+	   			int numTaxaInGroup = partition.getNumberInGroup(null);
+	   			
+		   		for (int i=0; i < (numTaxaInGroup-1); i++) {
+		   			int sh = rng.randomIntBetween(i, numTaxaInGroup-1);
+		   			if (sh != i)
+		   				modified.tradeStatesBetweenTaxa(ic, getTaxonNumber(i, null, taxa, partition), getTaxonNumber(sh, null, taxa, partition));
+		   		}
+	 	 	}
+ 	 	}
+   	}
+   	int getTaxonNumber(int numInGroup, TaxaGroup group, Taxa taxa, TaxaPartition partition){
+   		int count = 0;
+   		for (int it = 0; it<taxa.getNumTaxa(); it++){
+   			if (partition.getTaxaGroup(it) == group){
+   				if (count == numInGroup)
+   					return it;
+   				count++;
+   			}
+   		}
+   		return -1;
+   	}
+   	
+   	
+	/*.................................................................................................................*/
+   	public String getName() {
+    	   	return "Reshuffle Within Characters (Taxa Partitioned)";
+   	 }
+	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return false;
+  	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shuffles (permutes) character states among taxa of each taxa partition, within each character." ;
+		//return "Shuffles (permutes) character states among characters of each character partition, within each taxon." ;
+  	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/ReshuffleWTaxaByPart/ReshuffleWTaxaByPart.java b/Source/mesquite/charMatrices/ReshuffleWTaxaByPart/ReshuffleWTaxaByPart.java
new file mode 100644
index 0000000..c5038f0
--- /dev/null
+++ b/Source/mesquite/charMatrices/ReshuffleWTaxaByPart/ReshuffleWTaxaByPart.java
@@ -0,0 +1,171 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ReshuffleWTaxaByPart;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class ReshuffleWTaxaByPart extends RandomMatrixModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  	 	return true; 
+  	 }
+
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+  		mmByPart(matrix, modified, rng);
+   	}
+	/*.................................................................................................................*/
+  	public void mm(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+
+		for (int ic = 0; ic<numChars; ic++) {
+	   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+ 	 	}
+		CharacterState cs1 = null;
+		CharacterState cs2 = null;
+	   	for (int it=0; it < (numTaxa-1); it++) {
+	   		for (int ic = 0; ic<numChars; ic++) {
+	   			int sh = rng.randomIntBetween(ic, numChars-1);
+	   			if (sh != ic) {
+	   				cs1 = modified.getCharacterState(cs1, ic, it);
+	   				cs2 = modified.getCharacterState(cs2, sh, it);
+	   				modified.setCharacterState(cs1, sh, it);
+	   				modified.setCharacterState(cs2, ic, it);
+	   			}
+	   		}
+ 	 	}
+   	}
+	/*.................................................................................................................*/
+  	public void mmByPart(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+			
+		CharacterData data = matrix.getParentData();
+		if (data == null) {
+			mm(matrix, modified, rng);
+		return;
+  	}
+		
+		CharacterPartition partition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		if (partition == null){
+			mm(matrix, modified, rng);
+			return;
+		}
+		CharactersGroup[] groups = null;
+		if (partition != null)
+			groups = partition.getGroups();
+		if (data == null){
+			mm(matrix, modified, rng);
+			return;
+		}
+		
+		CharacterState cs1=null, cs2=null;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+		
+			for (int ic = 0; ic<numChars; ic++) 
+		   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+			for (int it = 0; it<numTaxa; it++) {
+		   		for (int g = 0; g< groups.length; g++){ //examining group
+		   			int numCharInGroup = partition.getNumberInGroup(groups[g]);
+		   			
+			   		for (int i=0; i < (numCharInGroup-1); i++) {
+			   			int sh = rng.randomIntBetween(i, numCharInGroup-1);
+			   			if (sh != i){
+			   				int ic1 = getCharacterNumber(i, groups[g], numChars, partition);
+			   				int ic2 = getCharacterNumber(sh, groups[g], numChars, partition);
+			   				cs1 = modified.getCharacterState(cs1, ic1, it);
+			   				cs2 = modified.getCharacterState(cs2, ic2, it);
+			   				modified.setCharacterState(cs1, ic2, it);
+			   				modified.setCharacterState(cs2, ic1, it);
+			   		
+			   			}
+			   		}
+		   		}
+	   			int numCharInGroup = partition.getNumberInGroup(null);
+	   			
+		   		for (int i=0; i < (numCharInGroup-1); i++) {
+		   			int sh = rng.randomIntBetween(i, numCharInGroup-1);
+		   			if (sh != i){
+		   				int ic1 = getCharacterNumber(i, null, numChars, partition);
+		   				int ic2 = getCharacterNumber(sh, null, numChars, partition);
+		   				cs1 = modified.getCharacterState(cs1, ic1, it);
+		   				cs2 = modified.getCharacterState(cs2, ic2, it);
+		   				modified.setCharacterState(cs1, ic2, it);
+		   				modified.setCharacterState(cs2, ic1, it);
+		   		
+		   			}
+		   		}
+	 	 	}
+ 	 	
+   	}
+   	int getCharacterNumber(int numInGroup, CharactersGroup group, int numChars, CharacterPartition partition){
+   		int count = 0;
+   		for (int ic = 0; ic<numChars; ic++){
+   			if (partition.getCharactersGroup(ic) == group){
+   				if (count == numInGroup)
+   					return ic;
+   				count++;
+   			}
+   		}
+   		return -1;
+   	}
+   	
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		//return "Reshuffle Matrix Within Taxa";
+   		return "Reshuffle Within Taxa (Char. Partitioned)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+    	/*.................................................................................................................*/
+    	public boolean isPrerelease(){
+    		return false;
+    	}
+
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+ 	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return false;
+  	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shuffles (permutes) character states among characters of each character partition, within each taxon." ;
+   	 }
+   	 
+}
diff --git a/Source/mesquite/charMatrices/ReshuffleWithinTaxa/ReshuffleWithinTaxa.java b/Source/mesquite/charMatrices/ReshuffleWithinTaxa/ReshuffleWithinTaxa.java
new file mode 100644
index 0000000..d19b6e3
--- /dev/null
+++ b/Source/mesquite/charMatrices/ReshuffleWithinTaxa/ReshuffleWithinTaxa.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ReshuffleWithinTaxa;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class ReshuffleWithinTaxa extends RandomMatrixModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  	 	return true; 
+  	 }
+
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		if (modified.getNumTaxa()!=numTaxa || modified.getNumChars()!=numChars)
+			modified.setSize(numChars, numTaxa);
+
+		for (int ic = 0; ic<numChars; ic++) {
+	   		modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+ 	 	}
+		CharacterState cs1 = null;
+		CharacterState cs2 = null;
+	   	for (int it=0; it < (numTaxa-1); it++) {
+	   		for (int ic = 0; ic<numChars; ic++) {
+	   			int sh = rng.randomIntBetween(ic, numChars-1);
+	   			if (sh != ic) {
+	   				cs1 = modified.getCharacterState(cs1, ic, it);
+	   				cs2 = modified.getCharacterState(cs2, sh, it);
+	   				modified.setCharacterState(cs1, sh, it);
+	   				modified.setCharacterState(cs2, ic, it);
+	   			}
+	   		}
+ 	 	}
+   	}
+	/*.................................................................................................................*/
+     public String getName() {
+  		return "Reshuffle States Within Taxa";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+ 	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return false;
+  	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shuffles (permutes) character states among characters within each taxon." ;
+   	 }
+   	 
+}
diff --git a/Source/mesquite/charMatrices/SaveMatrixCopies/SaveMatrixCopies.java b/Source/mesquite/charMatrices/SaveMatrixCopies/SaveMatrixCopies.java
new file mode 100644
index 0000000..e8af27e
--- /dev/null
+++ b/Source/mesquite/charMatrices/SaveMatrixCopies/SaveMatrixCopies.java
@@ -0,0 +1,318 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.SaveMatrixCopies; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+public class SaveMatrixCopies extends FileInit  {
+	ExtensibleDialog dialog = null;
+	String exporterString = "NEXUS file";
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0)
+			exporterString = prefs[0];
+	}
+
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "exporterString", exporterString);  
+		return buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("exporterString".equalsIgnoreCase(tag))
+			exporterString = StringUtil.cleanXMLEscapeCharacters(content);
+	}
+
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		MesquiteSubmenuSpec mmis2 = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Save Copy of Matrix", makeCommand("saveCopMatrix",  this),  (ListableVector)getProject().datas);
+		mmis2.setBehaviorIfNoChoice(MesquiteSubmenuSpec.SHOW_SUBMENU);
+		getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, "Save Multiple Matrices", makeCommand("saveCopMatrices",  this), CharMatrixSource.class);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	private void saveCopMatrix(CharacterData data, String path) {
+		if (data==null)
+			return;
+		incrementMenuResetSuppression();
+		Taxa taxa = data.getTaxa();
+
+		FileCoordinator coord = getFileCoordinator();
+		MesquiteFile tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(path), CommandChecker.defaultChecker); //TODO: never scripting???
+		TaxaManager taxaManager = (TaxaManager)findElementManager(Taxa.class);
+		Taxa newTaxa =taxa.cloneTaxa();
+		newTaxa.addToFile(tempDataFile, null, taxaManager);
+
+		CharacterData newData = data.cloneData();
+		newData.setName(data.getName());
+		newData.addToFile(tempDataFile, getProject(), null);
+		coord.writeFile(tempDataFile);
+		tempDataFile.close();
+		decrementMenuResetSuppression();
+	}
+
+	public void saveFile(String exporterName, MesquiteFile file, String fileName, String directoryPath, boolean usePrevious, FileCoordinator coord){
+		if (exporterName.equals("NEXUS file"))
+			coord.writeFile(file);
+		else {
+			FileInterpreterI exporter = (FileInterpreterI)coord.findEmployeeWithName(exporterName);
+			if (exporter!=null) {
+				String ext = exporter.preferredDataFileExtension();
+				if (StringUtil.blank(ext))
+					ext = "";
+				else
+					ext = "." + ext;
+				String s = "file = " + StringUtil.tokenize(fileName + ext) + " directory = " + StringUtil.tokenize(directoryPath) + " noTrees";
+				if (usePrevious)
+					s+= " usePrevious";
+				coord.export(exporter, file, s);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Saves a copy of the character data matrix to a separate file", "[id number of data matrix]", commandName, "saveCopMatrix")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberCharMatricesVisible()) {
+				long id  = MesquiteLong.fromString(parser.getNextToken());
+				CharacterData d = getProject().getCharacterMatrixVisible(t);
+				if (d!=null) {
+					String path = MesquiteFile.saveFileAsDialog("Save copy of matrix to file");
+					if (!StringUtil.blank(path))
+						saveCopMatrix(d, path);
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Saves copies of a series of character matrices to files", "[name of module to fill the matrix]", commandName, "saveCopMatrices")) {
+			//ask user how which taxa, how many characters
+			//create chars block and add to file
+			//return chars
+			CharacterData newMatrix=null;
+			Taxa taxa = null;
+			if (getProject().getNumberTaxas()==0) {
+				alert("Data matrices cannot be created until taxa exist in file.");
+				return null;
+			}
+			else 
+				taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to save copies of character matrices?");
+			if (taxa == null)
+				return null;
+
+			//	MesquiteFile file=chooseFile();
+			MainThread.incrementSuppressWaitWindow();
+			CharMatrixSource characterSourceTask;
+			if (StringUtil.blank(arguments))
+				characterSourceTask = (CharMatrixSource)hireEmployee(CharMatrixSource.class, "Export matrices from:");
+			else
+				characterSourceTask = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, arguments);
+			if (characterSourceTask != null) {
+				incrementMenuResetSuppression();
+				getProject().incrementProjectWindowSuppression();
+
+				MesquiteInteger buttonPressed = new MesquiteInteger(1);
+				int num = characterSourceTask.getNumberOfMatrices(taxa);
+				//ExtensibleDialog dialog = templateManger.getChooseTemplateDLOG(taxa, templateContainer, buttonPressed);
+				dialog = new ExtensibleDialog(containerOfModule(), "Save Multiple Matrices", buttonPressed);
+				String message = "This will save a series of files, each containing a matrix, using the matrix source: " + characterSourceTask.getName();
+				dialog.addLargeTextLabel(message);
+				dialog.addBlankLine();
+				dialog.addLabel("Base name for files:");
+				dialog.suppressNewPanel();
+				SingleLineTextField baseNameField = dialog.addTextField("untitled");
+				SingleLineTextField numReps = null;
+				if (!MesquiteInteger.isCombinable(num)) {
+					dialog.addBlankLine();
+					dialog.addLabel("Number of matrices:");
+					dialog.suppressNewPanel();
+					numReps = dialog.addTextField("10");
+				}
+
+				MesquiteModule[] fInterpreters = getFileCoordinator().getImmediateEmployeesWithDuty(FileInterpreterI.class);
+				int count=0;
+				for (int i=0; i<fInterpreters.length; i++) {
+					if (((FileInterpreterI)fInterpreters[i]).canExportEver())
+						count++;
+				}
+				String [] exporterNames = new String[count];
+				count = 0;
+				for (int i=0; i<fInterpreters.length; i++)
+					if (((FileInterpreterI)fInterpreters[i]).canExportEver()) {
+						exporterNames[count] = fInterpreters[i].getName();
+						count++;
+					}
+
+				Choice exporterChoice = dialog.addPopUpMenu ("File Format", exporterNames, 0);
+				exporterChoice.select(exporterString);
+				dialog.addBlankLine();
+				dialog.completeAndShowDialog();
+				if (dialog.query() != 0)
+					return bailOut(null, characterSourceTask, null);
+				String baseName = baseNameField.getText();
+				if (numReps != null)
+					num = MesquiteInteger.fromString(numReps.getText());
+				if (!MesquiteInteger.isCombinable(num)) 
+					return bailOut(null, characterSourceTask, null);
+
+				String directoryPath = MesquiteFile.chooseDirectory("Where to save files?"); //MesquiteFile.saveFileAsDialog("Base name for files (files will be named <name>1.nex, <name>2.nex, etc.)", baseName);
+				if (StringUtil.blank(directoryPath))
+					return bailOut(null, characterSourceTask, null);
+				String basePath = directoryPath + MesquiteFile.fileSeparator + baseName;
+				exporterString = exporterChoice.getSelectedItem();
+
+				dialog.dispose();
+				dialog = null;
+
+
+				StringBuffer outputBuffer=null;
+				String s2 = "";
+
+				FileCoordinator coord = getFileCoordinator();
+				MesquiteFile tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(basePath + ".nex"), CommandChecker.defaultChecker); //TODO: never scripting???
+				TaxaManager taxaManager = (TaxaManager)findElementManager(Taxa.class);
+				Taxa newTaxa =taxa.cloneTaxa();
+				newTaxa.addToFile(tempDataFile, null, taxaManager);
+
+				ProgressIndicator progIndicator = new ProgressIndicator(getProject(),"Saving files", num);
+				progIndicator.start();
+				progIndicator.setCurrentValue(0);
+				boolean usePrevious = false;
+				tempDataFile.exporting =1;
+				try {
+					for (int iMatrix = 0; iMatrix<num; iMatrix++){
+						if (progIndicator!=null)
+							progIndicator.setText("Saving file "+(iMatrix+1)+" of " + num);
+						MCharactersDistribution matrix = characterSourceTask.getMatrix(taxa, iMatrix);
+						if (matrix==null)
+							return bailOut(tempDataFile, characterSourceTask, progIndicator);
+
+						CharactersManager manageCharacters = (CharactersManager)findElementManager(CharacterData.class);
+						CharMatrixManager manager = manageCharacters.getMatrixManager(matrix.getCharacterDataClass());
+						if (manager != null){
+							newMatrix = matrix.makeCharacterData(manager, taxa);
+							newMatrix.setName(characterSourceTask.getMatrixName(taxa, iMatrix));
+
+							logln("Saving file " + basePath + (iMatrix+1) + ".nex\n" + newMatrix.getExplanation() + "\n");	
+							newMatrix.addToFile(tempDataFile, getProject(), null);
+							TreeVector trees = null;
+							if (matrix.getBasisTree()!=null) {
+								trees = new TreeVector(taxa);
+								trees.setName("Basis Tree");
+								trees.setAnnotation("Tree used a basis for character matrix.  For example the matrix may have been simulated on the tree.", false);
+								trees.addElement(matrix.getBasisTree().cloneTree(), false);//no need to establish listener to Taxa, as temporary
+								trees.addToFile(tempDataFile, getProject(), null);
+							}
+							tempDataFile.setPath(basePath +  (iMatrix+1) + ".nex");
+
+
+							//should allow choice here
+							saveFile(exporterString, tempDataFile, baseName +  (iMatrix+1), directoryPath, usePrevious, coord); 
+							tempDataFile.exporting = 2;  //to say it's the second or later export in sequence
+
+							newMatrix.deleteMe(false);
+							newMatrix = null;
+							if (trees != null)
+								trees.deleteMe(false);
+							trees = null;
+							System.gc();
+						}
+						if (progIndicator!=null) {
+							progIndicator.setCurrentValue(iMatrix+1);
+							if (progIndicator.isAborted()) {
+								break;
+							}
+						}
+						usePrevious = true;
+					}
+				}
+				catch (Exception e) {
+					// clean up anything added
+					e.printStackTrace();
+
+					MesquiteMessage.notifyUser("There was a problem with creating or saving the matrices, and the process was aborted.");
+
+					if (newMatrix!=null) {
+						newMatrix.deleteMe(false);
+						newMatrix = null;
+					}
+				}
+
+				tempDataFile.close();
+
+				if (progIndicator!=null) 
+					progIndicator.goAway();
+
+				fireEmployee(characterSourceTask);
+				resetAllMenuBars();
+				getProject().decrementProjectWindowSuppression();
+				decrementMenuResetSuppression();
+			}
+			MainThread.decrementSuppressWaitWindow();
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	private Object bailOut(MesquiteFile tempDataFile, MesquiteModule characterSourceTask, ProgressIndicator progIndicator){
+		if (tempDataFile !=null)
+			tempDataFile.close();
+		if (progIndicator !=null)
+			progIndicator.goAway();
+		if (dialog != null) {
+			dialog.dispose();
+			dialog = null;
+		}
+		fireEmployee(characterSourceTask);
+		resetAllMenuBars();
+		getProject().decrementProjectWindowSuppression();
+		decrementMenuResetSuppression();
+		MainThread.decrementSuppressWaitWindow();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Save matrix copies";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Provides for the saving of copies of matrices to separate files.  This is available under the Characters menu." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/charMatrices/SearchData/SearchData.java b/Source/mesquite/charMatrices/SearchData/SearchData.java
new file mode 100644
index 0000000..4642f76
--- /dev/null
+++ b/Source/mesquite/charMatrices/SearchData/SearchData.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SearchData; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.charMatrices.lib.RandomMatrixModifier;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class SearchData extends DataWindowAssistantI {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DataSearcher.class, getName() + " needs a method to search, for instance to find best matches in Genbank to a selected sequence.",
+				"You can request a search using the Search submenu of the Matrix menu of the Character Matrix Editor.  This menu may not be available for some data types.");
+	}
+	MesquiteTable table;
+	CharacterData data;
+	MesquiteSubmenuSpec mss= null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		 mss = addSubmenu(null, "Search", makeCommand("doSearch",  this));
+		mss.setList(DataSearcher.class);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		mss.setCompatibilityCheck(data.getStateClass());
+		resetContainingMenuBar();
+		
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Chooses the module to search the data matrix", "[name of module]", commandName, "doSearch")) {
+   	 		if (table!=null && data !=null){
+	    	 		DataSearcher tda= (DataSearcher)hireNamedEmployee(DataSearcher.class, arguments);
+				if (tda!=null) {
+					boolean a = tda.searchData(data, table);
+	 	   			if (a) {
+	 	   				table.repaintAll();
+						data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					}
+					fireEmployee(tda);
+				}
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Search Data";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages data-searching modules." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SearchSelect/SearchSelect.java b/Source/mesquite/charMatrices/SearchSelect/SearchSelect.java
new file mode 100644
index 0000000..4fc7873
--- /dev/null
+++ b/Source/mesquite/charMatrices/SearchSelect/SearchSelect.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SearchSelect;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== *
+*new in 1.02*
+/* ======================================================================== */
+public class SearchSelect extends DataWindowAssistantI { //DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		MesquiteMenuItemSpec mm = addMenuItem(MesquiteTrunk.editMenu, "Find All...", MesquiteModule.makeCommand("findAll", this));
+		return true;
+	}
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+
+
+
+   	/** Called to select characters*/
+   	public void select(){ 
+   		if (table != null && data!=null){
+   			boolean found = false;
+   			MesquiteString value = new MesquiteString("");
+   			if (!QueryDialogs.queryShortString(containerOfModule(), "Search matrix", "Select cells of matrix according to if they contain the string:", value))
+   				return;
+   			String target = value.getValue();
+   			if (StringUtil.blank(target))
+   				return;
+   			//find string in cell
+			for (int it = 0; it< table.getNumRows(); it++){
+				String name = table.getRowNameTextForDisplay(it);
+				if (name != null && StringUtil.foundIgnoreCase(name, target))
+					table.selectRowName(it);
+   				for (int ic = 0; ic< table.getNumColumns(); ic++) {
+   					
+					String s = table.getMatrixTextForDisplay(ic, it);
+					if (s != null && StringUtil.foundIgnoreCase(s, target))
+						table.selectCell(ic, it);
+   				}
+   			}
+   			for (int ic = 0; ic< table.getNumColumns(); ic++) {
+ 				String name = table.getColumnNameTextForDisplay(ic);
+				if (name != null && StringUtil.foundIgnoreCase(name, target))
+					table.selectColumnName(ic);
+ 			}
+  			
+			table.repaintAll();
+   		}
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Returns the data matrix shown by the data window", null, commandName, "findAll")) {
+    	 		select();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Select By Search (Find all)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects cells of the matrix according to whether their text contains a given string" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelSummaryStrip/SelSummaryStrip.java b/Source/mesquite/charMatrices/SelSummaryStrip/SelSummaryStrip.java
new file mode 100644
index 0000000..9a3cbe6
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelSummaryStrip/SelSummaryStrip.java
@@ -0,0 +1,267 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.SelSummaryStrip;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+public class SelSummaryStrip extends DataWindowAssistantID {
+	Ledge panel;
+	MesquiteBoolean showStrip;
+	boolean shown;
+	CharacterData data = null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showStrip = new MesquiteBoolean(false);
+		shown = false;
+		addCheckMenuItem(null, "Show Selection Summary Strip", makeCommand("showStrip", this), showStrip);
+		return true;
+	}
+	/** Called to alter data in all cells*/
+	public void setTableAndData(MesquiteTable table, CharacterData cData){
+		if (data != null)
+			data.removeListener(this);
+		data = cData;
+		data.addListener(this);
+		this.table = table;
+		resetLedge();
+
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (notification == null || obj != data || caller == this)
+			return;
+		resetMessage();
+
+	}
+	public void resetLedge(){
+		if (showStrip.getValue() && !shown){  //need to show
+			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = true;
+				if (panel == null)
+					panel = new Ledge(this);
+				((MesquiteWindow)f).addLedgePanel(panel, 22);
+				panel.setVisible(true);
+				panel.setMessage("");
+				resetMessage();
+			}
+		}
+		else if (!showStrip.getValue() && shown && panel != null){ //need to hide
+			MesquiteWindow f = containerOfModule();
+			if (f instanceof MesquiteWindow){
+				shown = false;
+				panel.setVisible(false);
+				((MesquiteWindow)f).removeLedgePanel(panel);
+			}
+		}
+	}
+	private void resetMessage(){
+		if (panel == null)
+			return;
+		panel.setMessage(getMessage());
+
+	}
+
+
+	private String getMessage(){
+		if (!table.anythingSelected())
+			return "Nothing selected";
+
+		String result = "";
+		if (table.anyRowSelected()){
+			int numRows = table.numRowsSelected();
+			if (numRows == 1)
+				result += "1 Taxon selected.  ";
+			else
+				result += numRows + " Taxa selected.  ";
+		}
+		if (table.anyRowSelected()){
+			int numColumns = table.numColumnsSelected();
+			if (numColumns == 1)
+				result += "1 Character selected.  ";
+			else
+				result += numColumns + " Characters selected.  ";
+		}
+
+		if (table.anyCellSelectedAnyWay()){
+			int numCells = table.numCellsSelectedAnyWay();
+			if (numCells == 1)
+				result += "1 Cells selected.  ";
+			else
+				result += numCells + " Cells selected.  ";
+		}
+		if (data instanceof CategoricalData){
+			
+			int[] count = new int[CategoricalState.maxCategoricalState+1];
+			CategoricalData catData = (CategoricalData)data;
+			int maxState = -1;
+			for (int ic= 0; ic< table.numColumnsTotal; ic++)
+				for (int it= 0; it< table.numRowsTotal; it++)
+					if (table.isCellSelectedAnyWay(ic, it)){
+						long state = catData.getState(ic, it);
+						state = state & CategoricalState.statesBitsMask;
+						for (int i=0; i<=CategoricalState.maxCategoricalState && state != 0L; i++)
+
+							if (CategoricalState.isElement(state, i)){
+								state = CategoricalState.clearFromSet(state, i);
+								count[i]++;
+								if (i> maxState)
+									maxState = i;
+							}
+					}
+			
+			if (maxState > -1){
+				result += "Counts of state ";
+				for (int i=0; i<=maxState; i++)
+					if (count[i]>0)
+						result += catData.getSymbol(i) + ": " + count[i] + "; ";
+			}
+
+		}
+		else if (data instanceof ContinuousData){
+			for (int ic= 0; ic< table.numColumnsTotal; ic++)
+				for (int it= 0; it< table.numRowsTotal; it++)
+					if (table.isCellSelectedAnyWay(ic, it)){
+						//
+					}
+		}
+		return result;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (data != null)
+			data.removeListener(this);
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			((MesquiteWindow)f).removeLedgePanel(panel);
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	void focusLost(){
+		resetMessage();
+	}
+	public void focusInCell(int ic, int it){
+		if (panel == null)
+			return;
+		/*if (ic >=0)
+  			resetMessage(ic);
+  		else*/
+		resetMessage();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("showStrip " + showStrip.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows a strip with the reference for the character", null, commandName, "showStrip")) {
+			showStrip.toggleValue(parser.getFirstToken(arguments));
+			resetLedge();
+
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Selection Summary Strip";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows the strip at bottom of matrix with character reference." ;
+	}
+}
+class Ledge extends MousePanel {
+	TextArea message, title;
+	SelSummaryStrip ownerModule;
+	int titleWidth = 80;
+	int ic = -1;
+	public Ledge(SelSummaryStrip ownerModule){
+		setLayout(null);
+		this.ownerModule = ownerModule;
+		/* */
+		message = new TextArea(" ", 20, 2, TextArea.SCROLLBARS_NONE);
+		message.setVisible(true);
+		add(message);
+		message.setBounds(titleWidth,0,getBounds().width-titleWidth, getBounds().height);
+		message.setBackground(Color.white);
+
+
+
+		title = new TextArea(" ", 20, 2, TextArea.SCROLLBARS_NONE);
+		title.setVisible(true);
+		add(title);
+		title.setBounds(0,0,titleWidth, getBounds().height);
+		title.setBackground(ColorDistribution.veryVeryLightGreen);
+		title.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+		title.setText("Selected:");
+		message.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+		/**/
+	}
+	public void setMessage(String s){
+
+		if (StringUtil.stringsEqual(s, message.getText()))
+			return;
+		if (s == null)
+			s = "";
+		title.setText("Selected:");
+		message.setText(s);
+		message.repaint();
+
+	}
+	public String getMessage(){
+		return message.getText();
+
+	}
+	public void setSize(int w, int h){
+		message.setBounds(titleWidth,0,w-titleWidth, h);
+		title.setBounds(0,0,titleWidth, h);
+		super.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		message.setBounds(titleWidth,0,w-titleWidth, h);
+		title.setBounds(0,0,titleWidth, h);
+		super.setBounds(x, y, w,h);
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectCharacterRanges/SelectCharacterRanges.java b/Source/mesquite/charMatrices/SelectCharacterRanges/SelectCharacterRanges.java
new file mode 100644
index 0000000..1fabb92
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectCharacterRanges/SelectCharacterRanges.java
@@ -0,0 +1,147 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectCharacterRanges;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectCharacterRanges extends CharacterSelector {
+	boolean bracketFormat = true;
+	String ranges = "";
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public void selectRange(CharacterData data, int icStart, int icEnd){
+			for (int i=icStart; i<=icEnd; i++) {
+					data.setSelected(i, true);
+			}
+   	}
+
+	boolean queryOptions(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Character Ranges to Select",  buttonPressed);
+		queryDialog.addLabel("Character Ranges to Select", Label.CENTER);
+		String help="Ranges should be specified using one of two formats:<br>";
+		help += "(1) bracketed ranges, without hyphens, of the form \"[startOfRange1 endOfRange1] [startOfRange2 endOfRange2] [startOfRange3 endOfRange3]\". This is the format used in GBlocks output.";
+		help += "<br>(2) hyphenated ranges, of the form \"startOfRange1 - endOfRange1  startOfRange2 - endOfRange2 startOfRange3 - endOfRange3\"";
+		queryDialog.appendToHelpString(help);
+
+		SingleLineTextArea rangeText = queryDialog.addSingleLineTextArea(ranges,5);
+
+		queryDialog.addLabel("Format of ranges:", Label.CENTER);
+		RadioButtons formatRadios = queryDialog.addRadioButtons (new String[]{"bracketed ranges", "hyphenated ranges"}, 0);
+
+		queryDialog.completeAndShowDialog(true);
+		boolean ok = (queryDialog.query()==0);
+
+		if (ok) {
+			ranges = rangeText.getText();
+			bracketFormat = formatRadios.getValue() ==0;
+		}
+		queryDialog.dispose();   		 
+
+		return ok;
+	}
+
+   	/** Called to select characters*/
+   	public void selectCharacters(CharacterData data){
+   		if (data!=null && data.getNumChars()>0){
+   			if (!queryOptions() || StringUtil.blank(ranges))
+   				return;
+   			Parser parser = new Parser(ranges);
+   			//parser.setPunctuationString("[]");
+   			parser.setAllowComments(false);
+   			String token = parser.getNextToken();
+   			int icStart = -2;
+   			int icEnd = -1;
+
+   			if (bracketFormat) {
+   				while (StringUtil.notEmpty(token)) {
+   					if (token.equalsIgnoreCase("[")) {  // start of range
+   						icStart = MesquiteInteger.fromString(parser);
+   						if (MesquiteInteger.isCombinable(icStart)) {
+   							icEnd = MesquiteInteger.fromString(parser);
+   							if (MesquiteInteger.isCombinable(icEnd)) {
+   								selectRange(data,icStart-1,icEnd-1);
+   							} else
+   								selectRange(data,icStart-1,icStart-1);
+   						}
+   					}
+   					token = parser.getNextToken();
+   					if (StringUtil.notEmpty(token)) {
+   						if (token.equalsIgnoreCase("]")) 
+   							token = parser.getNextToken();
+   					}
+   				}
+   			} else {
+   				parser.setHyphensArePartOfNumbers(false);
+   				while (StringUtil.notEmpty(token)) {
+   					if (token.equalsIgnoreCase("-") || token.equalsIgnoreCase("–")) {  // now get end of range
+   	   						token = parser.getNextToken();
+   							icEnd = MesquiteInteger.fromString(token);  //end of range
+   	   						if (MesquiteInteger.isCombinable(icStart) && MesquiteInteger.isCombinable(icEnd)) 
+   	   								selectRange(data,icStart-1,icEnd-1);
+   					} else {  // it should be a normal number
+   						icStart = MesquiteInteger.fromString(token);
+   						if (MesquiteInteger.isCombinable(icStart))
+   							selectRange(data,icStart-1,icStart-1);  // might as well select it right now in case we don't ever get an end of range value
+   					}
+   					token = parser.getNextToken();
+   				}
+  			}
+
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   		}
+   	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 302;  
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Ranges...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects characters that are within the ranges given in a text list of the form [start end] [start end]..." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectCharsWithProbP/SelectCharsWithProbP.java b/Source/mesquite/charMatrices/SelectCharsWithProbP/SelectCharsWithProbP.java
new file mode 100644
index 0000000..10b761a
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectCharsWithProbP/SelectCharsWithProbP.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectCharsWithProbP;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectCharsWithProbP extends CharacterSelector {
+	Random rng = new Random();
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+   	/** Called to select characters*/
+   	public void selectCharacters(CharacterData data){
+   		if (data!=null && data.getNumChars()>0){
+			double p = MesquiteDouble.queryDouble(containerOfModule(), "Selection probability", "Probability of selecting each character:", .5, 0, 1);
+	   		if (!MesquiteDouble.isCombinable(p))
+	   			return;
+   			for (int i=0; i<data.getNumChars(); i++) {
+   				if (rng.nextDouble()<p)
+   					data.setSelected(i, true);
+   			}
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   		}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "With probability p";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects characters randomly with probability p." ;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectDiffering/SelectDiffering.java b/Source/mesquite/charMatrices/SelectDiffering/SelectDiffering.java
new file mode 100644
index 0000000..3e99e4a
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectDiffering/SelectDiffering.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectDiffering;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== *
+
+*new in 1.03*
+
+/* ======================================================================== */
+public class SelectDiffering extends DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		select();
+	}
+	private void select(){
+		if (table == null || data == null)
+			return;
+		Taxa taxa = data.getTaxa();
+		int numSets = getProject().getNumberCharMatricesVisible(taxa);
+		int numSetsDiff = numSets;
+		for (int i = 0; i<numSets; i++) {
+			CharacterData pData =getProject().getCharacterMatrixVisible(taxa, i);
+			if (pData== data)
+				numSetsDiff--;
+			else if (pData.getClass() != data.getClass())
+				numSetsDiff--;
+		}
+		if (numSetsDiff<=0) {
+			alert("Sorry, there are no other compatible data matrices available for comparison.  If the other matrix is in another file, open the file as a linked file before attempting to compare.");
+			return;
+		}
+		else {
+			Listable[] matrices = new Listable[numSetsDiff];
+			int count=0;
+			for (int i = 0; i<numSets; i++) {
+				CharacterData pData =getProject().getCharacterMatrixVisible(taxa, i);
+				if (pData!= data && (pData.getClass() == data.getClass())) {
+					matrices[count]=pData;
+					count++;
+				}
+			}
+			boolean differenceFound=false;
+			CharacterData oData = (CharacterData)ListDialog.queryList(containerOfModule(), "Compare with", "Compare data matrix with:", MesquiteString.helpString,matrices, 0);
+			if (oData==null)
+				return;
+				
+			CharacterState cs1 = null;
+			CharacterState cs2 = null;
+			for (int it = 0; it<data.getNumTaxa() && it<oData.getNumTaxa(); it++){
+				for (int ic = 0; ic<data.getNumChars() && ic<oData.getNumChars(); ic++){
+					cs1 = data.getCharacterState(cs1, ic, it);
+					cs2 = oData.getCharacterState(cs2, ic, it);
+					if (!cs1.equals(cs2)) {
+						table.selectCell(ic, it);
+					}
+				}
+			}
+			for (int ic = 0; ic<data.getNumChars() && ic<oData.getNumChars(); ic++){
+				String name = data.getCharacterName(ic);
+				String oName = oData.getCharacterName(ic);
+				if (name == null){
+					if (oName != null)
+						table.selectCell(ic, -1);
+				}
+				else if (!name.equals(oName)) {
+					table.selectCell(ic, -1);
+				}
+			}
+			table.repaintAll();
+		}
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Select by Matrix Comparison";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects cells of the matrix that differ compared to another matrix" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectMatchingTaxa/SelectMatchingTaxa.java b/Source/mesquite/charMatrices/SelectMatchingTaxa/SelectMatchingTaxa.java
new file mode 100644
index 0000000..e4bd863
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectMatchingTaxa/SelectMatchingTaxa.java
@@ -0,0 +1,149 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.SelectMatchingTaxa;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== *
+
+ *new in 1.02*
+
+/* ======================================================================== */
+public class SelectMatchingTaxa extends DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		select();
+	}
+	/*.................................................................................................................*
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects",null, commandName, "selectSame")) {
+   	 		select();
+		}
+   	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+
+	}
+/**/
+
+	/*  this has been replaced by dataMatches in CharacterData
+	boolean sequencesMatch(int it, int checkChar, int taxSel, int icStart, int icEnd, CharacterState cs1, CharacterState cs2) {
+   		if (data == null)
+   			return false;
+   		if (checkChar + (icEnd-icStart)>=data.getNumChars()){ //would extend past end of sequence
+			return false;
+   		}
+   		for (int ic= 0; ic < icEnd-icStart+1; ic++){
+   			cs1 = data.getCharacterState(cs1, checkChar + ic, it);  
+   			cs2 = data.getCharacterState(cs2,icStart+ic, taxSel);  //
+   			if (!cs2.equals(cs1)) {
+   				return false;
+   			}
+   		}
+   		return true;
+
+   	}
+	 */
+	void selectCells(int ic, int it, int length){
+		if (table == null)
+			return;
+		for (int i = 0; i<length; i++)
+			table.selectCell(ic + i, it);
+	}
+
+
+
+	public void select(){ //this should be passed boolean as to whether to notify re: selection?
+		if (table != null && data!=null && data.getNumChars()>0){
+			int rowsSel = table.numRowsSelected();
+			if (rowsSel !=1){
+				discreetAlert( "You must select a single taxon (a whole row) to select consistent taxa.");
+				return;
+			}
+			int taxSel = table.firstRowSelected();
+
+			//cells in character taxSel from taxon icStart to icEnd are selecteed
+			CharacterState cs1 = data.getCharacterState(null, 0, 0); //to serve as persistent container
+			CharacterState cs2  = data.getCharacterState(null, 0, 0);
+			MesquiteInteger matchEnd =new MesquiteInteger();
+			int instancesFound = 0;
+			//find selected sequence, if only one
+			for (int it = 0; it< data.getNumTaxa(); it++){
+				boolean matches = true;
+				for (int ic = 0; ic< data.getNumChars() && matches; ic++) {
+					cs1 = data.getCharacterState(cs1, ic, taxSel);
+					cs2 = data.getCharacterState(cs2, ic, it);
+					if (!cs1.equals(cs2, true, true, true))
+						matches = false;
+				}
+				if (matches) {
+					data.getTaxa().setSelected(it, true);
+					instancesFound++;
+				}
+			}
+			data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			if (instancesFound<2)
+				discreetAlert( "Nothing selected based on current selection, because nothing else matched");
+			else
+				logln(Integer.toString(instancesFound) + " instances of sequence found, including original");
+
+			table.repaintAll();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Select Matching Taxa";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Selects taxa according to whether their sequence of states matches the sequence of states in the selected taxon" ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectRndCharacters/SelectRndCharacters.java b/Source/mesquite/charMatrices/SelectRndCharacters/SelectRndCharacters.java
new file mode 100644
index 0000000..f049eea
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectRndCharacters/SelectRndCharacters.java
@@ -0,0 +1,76 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectRndCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectRndCharacters extends CharacterSelector {
+	RandomBetween rng = new RandomBetween();
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+   	/** Called to select characters*/
+   	public void selectCharacters(CharacterData data){
+   		if (data!=null && data.getNumChars()>0){
+   			
+   			int numColumns = data.getNumChars();
+   			int[]  indices = new int[numColumns];
+   			for (int i=0; i<indices.length; i++)
+   				indices[i]=i;
+			int numToSelect = MesquiteInteger.queryInteger(containerOfModule(), "Number to select", "Number of characters to select randomly:", 1, 1, numColumns-1);
+	   		if (!MesquiteInteger.isCombinable(numToSelect))
+	   			return;
+   			for (int i=0; i<numToSelect; i++) {
+   				int r = rng.randomIntBetween(0, numColumns-1-i);
+   				int toComeForward = indices[numColumns-1-i];
+   				indices[numColumns-1-i] = indices[r];
+   				indices[r]=toComeForward;
+   			}
+   			data.deselectAll();
+   			for (int i=numColumns-numToSelect; i<numColumns; i++) {
+   				data.setSelected(indices[i], true);
+   			}
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   		}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Random n characters";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects n characters randomly." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectSame/SelectSame.java b/Source/mesquite/charMatrices/SelectSame/SelectSame.java
new file mode 100644
index 0000000..4f38a7b
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectSame/SelectSame.java
@@ -0,0 +1,164 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectSame;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== *
+
+*new in 1.02*
+
+/* ======================================================================== */
+public class SelectSame extends DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//addMenuItem("Select Same", makeCommand("selectSame", this));
+		return true;
+	}
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		select();
+	}
+	/*.................................................................................................................*
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects",null, commandName, "selectSame")) {
+   	 		select();
+		}
+   	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	
+	}
+/**/
+
+/*  this has been replaced by dataMatches in CharacterData
+	boolean sequencesMatch(int it, int checkChar, int taxSel, int icStart, int icEnd, CharacterState cs1, CharacterState cs2) {
+   		if (data == null)
+   			return false;
+   		if (checkChar + (icEnd-icStart)>=data.getNumChars()){ //would extend past end of sequence
+			return false;
+   		}
+   		for (int ic= 0; ic < icEnd-icStart+1; ic++){
+   			cs1 = data.getCharacterState(cs1, checkChar + ic, it);  
+   			cs2 = data.getCharacterState(cs2,icStart+ic, taxSel);  //
+   			if (!cs2.equals(cs1)) {
+   				return false;
+   			}
+   		}
+   		return true;
+   		
+   	}
+*/
+   	void selectCells(int ic, int it, int length){
+   		if (table == null)
+   			return;
+   		for (int i = 0; i<length; i++)
+   			table.selectCell(ic + i, it);
+   	}
+
+	
+
+   	/** Called to select characters*/
+   	public void select(){ //this should be passed boolean as to whether to notify re: selection?
+   		if (table != null && data!=null && data.getNumChars()>0){
+   			int taxSel = -1;
+   			int icStart = -1;
+   			int icEnd = -1;
+   			boolean found = false;
+   			//find selected sequence, if only one
+			for (int it = 0; it< data.getNumTaxa(); it++){
+   				for (int ic = 0; ic< data.getNumChars(); ic++) {
+   					if (table.isCellSelectedAnyWay(ic, it)) {//selected cell found
+   						if (found){  //second sequence of cells, can use only one sequence
+   							discreetAlert( "Nothing selected based on current selection, because more than one discontiguous sections of sequences currently selected.  A contiguous sequence of states within a single taxon needs to be selected to define the search string.");
+   							return;
+   						}
+   						taxSel = it;
+   						icStart = ic;
+   						int ic2;
+   						for (ic2 = ic+1; ic2< data.getNumChars() && !found; ic2++){ //go to end of first sequence of selected cells
+   							if (!table.isCellSelectedAnyWay(ic2, it)) {
+   								found= true;
+   								icEnd = ic2-1;
+   							}
+   						}
+   						if (!found)
+   							icEnd = data.getNumChars()-1;
+   						found = true;
+   						ic = ic2;
+  					}
+   				}
+   			}
+   			
+   			if (taxSel <0){
+     				discreetAlert( "Nothing selected based on current selection, because nothing is currently selected.  A contiguous sequence of states within a single taxon needs to be selected to define the search string.");
+ 				return;
+   			}
+   			//cells in character taxSel from taxon icStart to icEnd are selecteed
+   			CharacterState cs1 = data.getCharacterState(null, 0, 0); //to serve as persistent container
+   			CharacterState cs2  = data.getCharacterState(null, 0, 0);
+   			MesquiteInteger matchEnd =new MesquiteInteger();
+   			int instancesFound = 0;
+   			   			//find selected sequence, if only one
+			for (int it = 0; it< data.getNumTaxa(); it++){
+	   			for (int ic = 0; ic< data.getNumChars(); ic++) {
+ 					if (data.dataMatches(it, ic, taxSel, icStart, icEnd, matchEnd, false, true, cs1, cs2)) {
+  						selectCells(ic, it, icEnd-icStart+1);
+   						instancesFound++;
+   					}
+   				}
+   			}
+   			if (instancesFound<2)
+   				discreetAlert( "Nothing selected based on current selection, because nothing else matched");
+   			else
+   				logln(Integer.toString(instancesFound) + " instances of sequence found, including original");
+
+			table.repaintAll();
+   		}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Select Same Subsequence";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects cells of the matrix according to whether their sequence of states matches the sequence of states in the selected taxon or block of cells" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectSameVert/SelectSameVert.java b/Source/mesquite/charMatrices/SelectSameVert/SelectSameVert.java
new file mode 100644
index 0000000..58ff76c
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectSameVert/SelectSameVert.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectSameVert;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== *
+
+*new in 1.02*
+
+/* ======================================================================== */
+public class SelectSameVert extends DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//addMenuItem("Select Same", makeCommand("selectSame", this));
+		return true;
+	}
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		selectVert();
+	}
+	/*.................................................................................................................*
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Selects",null, commandName, "selectSame")) {
+   	 		select();
+		}
+   	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	
+	}
+/**/
+   	boolean sequencesMatchVert(int ic, int checkTaxon, int charSel, int itStart, int itEnd, CharacterState cs1, CharacterState cs2) {
+   		if (data == null)
+   			return false;
+   		if (checkTaxon + (itEnd-itStart)>=data.getNumTaxa()){ //would extend past end of sequence
+			return false;
+   		}
+   		for (int it= 0; it < itEnd-itStart+1; it++){
+   			cs1 = data.getCharacterState(cs1,  ic, checkTaxon + it);  
+   			cs2 = data.getCharacterState(cs2, charSel, itStart+it);  //
+   			if (!cs2.equals(cs1)) {
+   				return false;
+   			}
+   		}
+   		return true;
+   		
+   	}
+   	void selectCellsVert(int it, int ic, int length){
+   		if (table == null)
+   			return;
+   		for (int i = 0; i<length; i++)
+   			table.selectCell(ic, it+i);
+   	}
+
+
+
+   	/** Called to select characters*/
+   	public void selectVert(){ //this should be passed boolean as to whether to notify re: selection?
+   		if (table != null && data!=null && data.getNumChars()>0){
+   			int numCharsSel = table.numColumnsSelected();
+   			if (numCharsSel>1)
+   				return;
+   			int charSel = -1;
+   			int itStart = -1;
+   			int itEnd = -1;
+   			boolean found = false;
+   			//find selected sequence, if only one
+   			for (int ic = 0; ic< data.getNumChars(); ic++) {
+				for (int it = 0; it< data.getNumTaxa(); it++){
+   					if (table.isCellSelectedAnyWay(ic, it)) {//selected cell found
+   						if (found){  //second sequence of cells, can use only one sequence
+   							discreetAlert( "Nothing selected based on current selection, because more than one distribution of states currently selected. A single contiguous vertical strip of cells (i.e. states of adjacent taxa in one character) needs to be selected to define the search string.");
+   							return;
+   						}
+   						charSel = ic;
+   						itStart = it;
+   						int it2;
+   						for (it2 = it+1; it2< data.getNumTaxa() && !found; it2++){ //go to end of first sequence of selected cells
+   							if (!table.isCellSelectedAnyWay(ic, it2)) {
+   								found= true;
+   								itEnd = it2-1;
+   							}
+   						}
+   						if (!found)
+   							itEnd = data.getNumTaxa()-1;
+   						it = it2;
+   						found = true;
+  					}
+   				}
+   			}
+   			
+   			if (charSel <0){
+     				discreetAlert( "Nothing selected based on current selection, because nothing is currently selected.  A single contiguous vertical strip of cells (i.e. states of adjacent taxa in one character) needs to be selected to define the search string.");
+ 				return;
+   			}
+   			//cells in character taxSel from taxon icStart to icEnd are selecteed
+   			CharacterState cs1 = data.getCharacterState(null, 0, 0); //to serve as persistent container
+   			CharacterState cs2  = data.getCharacterState(null, 0, 0);
+   			int instancesFound = 0;
+   			   			//find selected sequence, if only one
+   			for (int ic = 0; ic< data.getNumChars(); ic++) {
+				for (int it = 0; it< data.getNumTaxa(); it++){
+   					if (sequencesMatchVert(ic, it, charSel, itStart, itEnd, cs1, cs2)) {
+  						selectCellsVert(it, ic, itEnd-itStart+1);
+   						instancesFound++;
+   					}
+   				}
+   			}
+   			if (instancesFound<2)
+   				discreetAlert( "Nothing selected based on current selection, because nothing else matched");
+   			else
+   				logln(Integer.toString(instancesFound) + " instances of distribution found, including original");
+
+			table.repaintAll();
+   		}
+   	}
+
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Select Same Distribution";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects cells of the matrix according to whether their distribution of states across taxa in a character is the same as that in the selected character or block of cells" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SelectVariableCharacters/SelectVariableCharacters.java b/Source/mesquite/charMatrices/SelectVariableCharacters/SelectVariableCharacters.java
new file mode 100644
index 0000000..08befde
--- /dev/null
+++ b/Source/mesquite/charMatrices/SelectVariableCharacters/SelectVariableCharacters.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SelectVariableCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectVariableCharacters extends CharacterSelector {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	boolean variableAmongSelectedTaxa(Taxa taxa, boolean all, CharacterData data, int ic){
+		CharacterState fcs = null;
+		CharacterState cs = null;
+		boolean first = true;
+		for (int it = 0; it<taxa.getNumTaxa(); it++) {
+			if (taxa.getSelected(it) || all)
+				if (!data.isUnassigned(ic, it)){ //only start in first assigned
+					if (first)
+						fcs =  data.getCharacterState(null, ic, it);
+					first = false;
+					cs = data.getCharacterState(cs, ic, it);
+					if (!cs.equals(fcs, true))
+						return true;
+				}
+		}
+		return false;
+	}
+	
+	
+   	/** Called to select characters*/
+   	public void selectCharacters(CharacterData data){
+   		if (data!=null && data.getNumChars()>0){
+   			Taxa taxa = data.getTaxa();
+   			boolean anyTaxaSelected = taxa.anySelected();
+   			for (int i=0; i<data.getNumChars(); i++) {
+   				if (variableAmongSelectedTaxa(taxa, !anyTaxaSelected, data, i))
+   					data.setSelected(i, true);
+   			}
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   		}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Variable among taxa";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects characters that are variable among the selected taxa" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/ShuffleStates/ShuffleStates.java b/Source/mesquite/charMatrices/ShuffleStates/ShuffleStates.java
new file mode 100644
index 0000000..832af89
--- /dev/null
+++ b/Source/mesquite/charMatrices/ShuffleStates/ShuffleStates.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.ShuffleStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ShuffleStates extends DataAlterer {
+	RandomBetween randomTaxon;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+	 	randomTaxon= new RandomBetween();
+		randomTaxon.setSeed(System.currentTimeMillis()); //TODO: allow user set seed;
+		return true;
+	}
+		
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+   			boolean did=false;
+   			if (data == null)
+   				return false;
+   			UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+   	 		if (table==null){
+					for (int i=0; i<data.getNumChars(); i++)
+						shuffleCells(data, i, 0, data.getNumTaxa()-1);
+					return true;
+   	 		}
+   			if (table.anythingSelected()) {
+				for (int i=0; i<table.getNumColumns(); i++) {
+	   				int minTax = table.getNumRows();
+	   				int maxTax = -1;
+					boolean someSelected = false;
+					for (int j=0; j<table.getNumRows(); j++) {
+						if (table.isCellSelectedAnyWay(i,j)) {
+							if (j<minTax)
+								minTax=j;
+							else if (j>maxTax)
+								maxTax = j;
+							someSelected = true;
+						}
+					}
+					if (someSelected)
+						for (int j=minTax; j<=maxTax; j++)
+							if (!table.isCellSelectedAnyWay(i,j)) {
+								alert("Sorry, can't shuffle the states when selection of taxa is discontinuous within any character");
+								return false;
+							}
+				}
+				for (int i=0; i<table.getNumColumns(); i++) {
+	   				int minTax = table.getNumRows();
+	   				int maxTax = -1;
+					boolean someSelected = false;
+					for (int j=0; j<table.getNumRows(); j++) {
+						if (table.isCellSelectedAnyWay(i,j)) {
+							if (j<minTax)
+								minTax=j;
+							else if (j>maxTax)
+								maxTax = j;
+							someSelected = true;
+							
+						}
+					}
+					if (someSelected){
+						shuffleCells(data, i, minTax, maxTax);
+						did = true;
+					}
+				}
+				
+			}
+			else {
+				for (int i=0; i<data.getNumChars(); i++)
+					shuffleCells(data, i, 0, data.getNumTaxa()-1);
+			}
+   			if (undoInstructions!=null) {
+   				undoInstructions.setNewData(data);
+   				if (undoReference!=null){
+   					undoReference.setUndoer(undoInstructions);
+   					undoReference.setResponsibleModule(this);
+   				}
+   			}
+			return did;
+			
+   	}
+
+   	
+	void shuffleCells(CharacterData data, int ic, int it, int it2){
+   		for (int i=it; i < it2; i++) {
+   			int sh = randomTaxon.randomIntBetween(i, it2);
+   			if (sh!=i)
+   				data.tradeStatesBetweenTaxa(ic, i, sh);
+   		}
+	}
+	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Shuffle states among taxa";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters data by shuffling states among taxa within a character." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charMatrices/SortChar/32charSort.gif b/Source/mesquite/charMatrices/SortChar/32charSort.gif
new file mode 100644
index 0000000..c9a5437
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/32charSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortChar/32revCharSort.gif b/Source/mesquite/charMatrices/SortChar/32revCharSort.gif
new file mode 100644
index 0000000..62d4fac
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/32revCharSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortChar/64charSort.gif b/Source/mesquite/charMatrices/SortChar/64charSort.gif
new file mode 100644
index 0000000..ee8077a
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/64charSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortChar/64revCharSort.gif b/Source/mesquite/charMatrices/SortChar/64revCharSort.gif
new file mode 100644
index 0000000..7b5f43d
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/64revCharSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortChar/SortChar.java b/Source/mesquite/charMatrices/SortChar/SortChar.java
new file mode 100644
index 0000000..c100ae0
--- /dev/null
+++ b/Source/mesquite/charMatrices/SortChar/SortChar.java
@@ -0,0 +1,157 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SortChar; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class SortChar extends DataWindowAssistantI { 
+	TableTool charSortTool;
+	CharacterData data;
+	MesquiteTable table;
+	MesquiteCollator collator;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			charSortTool = new TableTool(this, "charSort", getPath(), "charSort.gif", 2, 8,"Sorts characters", "This tool sorts characters according to row selected", MesquiteModule.makeCommand("charSortTouch",  this) , null, null);
+			charSortTool.setOptionImageFileName("revCharSort.gif", 13, 8);
+			charSortTool.setWorksOnColumnNames(true);
+			((MesquiteWindow)containerOfModule()).addTool(charSortTool);
+		}
+		else return false;
+		collator = new MesquiteCollator();
+		return true;
+	}
+ 	 public String getFunctionIconPath(){
+   		 return getPath() + "charSort.gif";
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		charSortTool.setEnabled(data.canMoveChars());
+	}
+	/*.................................................................................................................*/
+  	 boolean compare(boolean greaterThan, String one, String two){
+		int order = collator.compare(one, two);
+		if ((order == 1 && greaterThan) ||(order == -1 && !greaterThan))
+			return true;
+		return false;
+  	 }
+	/*.................................................................................................................*/
+ 	/** Swaps parts first and second*/
+	void swapParts(CharacterData data, int first, int second, String[] text){  
+  		String temp = text[first];
+  		text[first] = text[second];
+  		text[second] = temp;
+		data.swapParts(first, second); 
+		data.swapInLinked(first, second, false); 
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(),  "Touches on a cell with the sort characters tool", "[column touched][row touched]", commandName, "charSortTouch")) {
+	   	 		if (data == null)
+	   	 			return null;
+	    	 	if (data.getEditorInhibition()){
+					discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+	    	 		return null;
+	    	 	}
+//	   	 		if (data.isMolecularSequence())
+//	   	 			if (!AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Sort Sites?", "These are molecular sequences. Are you sure you want to reorder the sites?  It cannot be undone.", "Sort", "Cancel", 2))
+//	   	 				return null;
+	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+	   			boolean gT = true;
+    				if (arguments.indexOf("option")>=0)
+    					gT = false;
+	   			if (!MesquiteInteger.isCombinable(column) && !MesquiteInteger.isCombinable(row))
+	   				return null;
+
+
+	   			boolean noneSelected = !data.anySelected();
+	   			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED,data);
+	   			undoInstructions.recordPreviousOrder(data);
+	   			UndoReference undoReference = new UndoReference(undoInstructions, this);
+
+				if (column>=0 && row >=0) {
+					long[] fullChecksumBefore =data.getIDOrderedFullChecksum();
+					String[] text = new String[data.getNumChars()];
+					for (int i=0; i<data.getNumChars(); i++)
+						text[i] = table.getMatrixText(i, row);
+					for (int i=1; i<data.getNumChars(); i++) {
+							if (i % 10 == 0) CommandRecord.tick("Sorting from character " + i);
+							for (int j= i-1; j>=0 && compare(gT, text[j], text[j+1]); j--) {
+								if (noneSelected || (data.getSelected(j) && data.getSelected(j+1))){
+									swapParts(data, j, j+1, text);
+							}
+							}
+						
+					}
+					CommandRecord.tick("Sorting finished");
+					long[] fullChecksumAfter =data.getIDOrderedFullChecksum();
+					data.compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "sorting of characters");
+					data.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_MOVED, undoReference));    //TODO: will this work in linked?????
+				}
+				else if (row == -1 && column >=0) { //row names selected; sort by taxon name
+					long[] fullChecksumBefore =data.getIDOrderedFullChecksum();
+					for (int i=1; i<data.getNumChars(); i++) {
+						if (i % 10 == 0) CommandRecord.tick("Sorting from character " + i);
+						for (int j= i-1; j>=0 && compare(gT, data.getCharacterName(j), data.getCharacterName(j+1)); j--) {
+							data.swapParts(j, j+1);
+							data.swapInLinked(j, j+1, false);
+						}
+					}
+					CommandRecord.tick("Sorting finished");
+					long[] fullChecksumAfter =data.getIDOrderedFullChecksum();
+					data.compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "sorting of characters");
+					data.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+					data.notifyInLinked(new Notification(MesquiteListener.PARTS_MOVED));  
+				}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Sort (data)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Provides a tool with which to sort characters automatically.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/SortChar/charSort.gif b/Source/mesquite/charMatrices/SortChar/charSort.gif
new file mode 100644
index 0000000..af5332e
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/charSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortChar/revCharSort.gif b/Source/mesquite/charMatrices/SortChar/revCharSort.gif
new file mode 100644
index 0000000..dfe4873
Binary files /dev/null and b/Source/mesquite/charMatrices/SortChar/revCharSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/32revTaxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/32revTaxaSort.gif
new file mode 100644
index 0000000..c6c2b1c
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/32revTaxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/32taxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/32taxaSort.gif
new file mode 100644
index 0000000..5816d6a
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/32taxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/64revTaxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/64revTaxaSort.gif
new file mode 100644
index 0000000..86a5f9f
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/64revTaxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/64taxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/64taxaSort.gif
new file mode 100644
index 0000000..ed85869
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/64taxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/SortTaxa.java b/Source/mesquite/charMatrices/SortTaxa/SortTaxa.java
new file mode 100644
index 0000000..6c08c2d
--- /dev/null
+++ b/Source/mesquite/charMatrices/SortTaxa/SortTaxa.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SortTaxa; 
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+public class SortTaxa extends DataWindowAssistantI {
+	TableTool taxaSortTool; 
+	MesquiteTable table;
+	CharacterData data;
+	Taxa taxa;
+	MesquiteCollator collator;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			taxaSortTool = new TableTool(this, "taxaSort", getPath() , "taxaSort.gif", 8,2,"Sort taxa with column touched", "This tool sorts the taxa according to the column touched.", MesquiteModule.makeCommand("taxaSortTouch",  this) , null, null);
+			taxaSortTool.setOptionImageFileName("revTaxaSort.gif", 8, 13);
+			taxaSortTool.setWorksOnRowNames(true);
+			((MesquiteWindow)containerOfModule()).addTool(taxaSortTool);
+		}
+		else return false;
+		collator = new MesquiteCollator();
+		return true;
+	}
+	 public String getFunctionIconPath(){
+   		 return getPath() + "taxaSort.gif";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data !=null)
+			this.taxa = data.getTaxa();
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+  	 boolean compare(boolean greaterThan, String one, String two){
+		int order = collator.compare(one, two);
+		if ((order == 1 && greaterThan) ||(order == -1 && !greaterThan))
+			return true;
+		return false;
+  	 }
+	/*.................................................................................................................*/
+ 	/** Swaps parts first and second*/
+	void swapParts(Taxa taxa, int first, int second, String[] text){  
+  		String temp = text[first];
+  		text[first] = text[second];
+  		text[second] = temp;
+		taxa.swapParts(first, second); 
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	 
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Touches on a cell with the taxa sort tool to sort the taxa according to the values in the column touched", "[column touched][row touched]", commandName, "taxaSortTouch")) {
+	   	 		if (taxa == null)
+	   	 			return null;
+	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   			boolean gT = true;
+    				if (arguments.indexOf("option")>=0)
+    					gT = false;
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+	   			if (!MesquiteInteger.isCombinable(column) && !MesquiteInteger.isCombinable(row))
+	   				return null;
+	   			boolean noneSelected = !taxa.anySelected();
+
+	   			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED,taxa);
+	   			undoInstructions.recordPreviousOrder(taxa);
+	   			UndoReference undoReference = new UndoReference(undoInstructions, this);
+				
+				if (column>=0 && row >=0) {
+					String[] text = new String[taxa.getNumTaxa()];
+					for (int i=0; i<taxa.getNumTaxa(); i++)
+						text[i] = table.getMatrixText(column, i);
+					for (int i=1; i<taxa.getNumTaxa(); i++) {
+						if (i % 10 == 0) CommandRecord.tick("Sorting from taxon " + i);
+						for (int j= i-1; j>=0 && compare(gT, text[j], text[j+1]); j--) {
+							if (noneSelected || (taxa.getSelected(j) && taxa.getSelected(j+1)))
+								swapParts(taxa, j, j+1, text);
+						}
+					}
+					CommandRecord.tick("Sorting finished");
+					taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED,undoReference));
+				}
+				else if (column == -1 && row >=0) { //row names selected; sort by taxon name
+					for (int i=1; i<taxa.getNumTaxa(); i++) {
+						if (i % 10 == 0) CommandRecord.tick("Sorting from taxon " + i);
+						for (int j= i-1; j>=0 && compare(gT, taxa.getTaxonName(j), taxa.getTaxonName(j+1)); j--) {
+							taxa.swapTaxa(j, j+1, false);
+						}
+					}
+					CommandRecord.tick("Sorting finished");
+					taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED,undoReference));
+				}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Sort Taxa (data)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Provides a tool with which to sort taxa automatically.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/SortTaxa/revTaxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/revTaxaSort.gif
new file mode 100644
index 0000000..92ca98b
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/revTaxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortTaxa/taxaSort.gif b/Source/mesquite/charMatrices/SortTaxa/taxaSort.gif
new file mode 100644
index 0000000..d543f5d
Binary files /dev/null and b/Source/mesquite/charMatrices/SortTaxa/taxaSort.gif differ
diff --git a/Source/mesquite/charMatrices/SortsInCharList/SortsInCharList.java b/Source/mesquite/charMatrices/SortsInCharList/SortsInCharList.java
new file mode 100644
index 0000000..3cac004
--- /dev/null
+++ b/Source/mesquite/charMatrices/SortsInCharList/SortsInCharList.java
@@ -0,0 +1,162 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SortsInCharList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class SortsInCharList extends CharListAssistant {
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteMenuItemSpec mScs, mStc, mRssc;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Stores current character order (CHARSORTING)", null, commandName, "storeCurrent")) {
+    	 		if (data!=null){
+    	 			SpecsSetVector ssv = data.getSpecSetsVector(CharSort.class);
+    	 			if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+			 		CharSort sort= new CharSort("Character Order", data.getNumChars(), data);
+			 		for (int i = 0; i<data.getNumChars(); i++)
+			 			sort.setValue(i, i+1);
+			 		sort.addToFile(data.getFile(), getProject(), findElementManager(CharSort.class)); //THIS
+					data.setCurrentSpecsSet(sort, CharSort.class);
+					ssv = data.getSpecSetsVector(CharSort.class);
+    	 				sort.setName(ssv.getUniqueName("Character Order"));
+	 			}
+	 			if (ssv!= null){
+    	 				CharSort sorting =  (CharSort)ssv.storeCurrentSpecsSet();
+    					if (sorting.getFile() == null)
+    						sorting.addToFile(data.getFile(), getProject(), findElementManager(CharSort.class));
+  	 				sorting.setName(ssv.getUniqueName("Character Order"));
+		 			String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of Character order to be stored", sorting.getName());
+    	 				if (!StringUtil.blank(name))
+    	 					sorting.setName(name);
+			 		for (int i = 0; i<data.getNumChars(); i++)
+			 			sorting.setValue(i, i+1);
+    	 				ssv.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+			 	}
+   	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Replace stored Character Order (CHARSORTING) by the current one", null, commandName, "replaceWithCurrent")) {
+    	 		if (data!=null){
+    	 				SpecsSetVector ssv = data.getSpecSetsVector(CharSort.class);
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored order", "Choose stored Character Order to replace by current order", MesquiteString.helpString,ssv, 0);
+		    	 			if (chosen!=null){
+					 		CharSort sorting= new CharSort(chosen.getName(), data.getNumChars(), data);
+					 		for (int i = 0; i<data.getNumChars(); i++)
+					 			sorting.setValue(i, i+1);
+		    	 				ssv.replaceStoredSpecsSet(chosen, sorting);
+							data.setCurrentSpecsSet(sorting, CharSort.class);
+		    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+		    	 			}
+	    	 			}
+    	 			
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Loads the stored Character Order to be the current one", "[number of Character Order to load]", commandName, "loadToCurrent")) {
+ 			if (data !=null) {
+ 				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+ 				if (MesquiteInteger.isCombinable(which)){
+		 			SpecsSetVector ssv = data.getSpecSetsVector(CharSort.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+		    	 			if (chosen!=null){
+		    	 				ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+		    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+		    	 				return chosen;
+		    	 			}
+			 		}
+ 				}
+	 		}
+	    	 }
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mStc);
+		mScs = addMenuItem("Store current order", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored order by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load character order", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(CharSort.class));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Stored Order";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			CharSort sorting = (CharSort)data.getCurrentSpecsSet(CharSort.class);
+			if (sorting != null) {
+				return sorting.toString(ic);
+			}
+			else {
+				return "?";
+			}
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "888888888  ";
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stored Character Order";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Stored Order";
+   	 }
+ 	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+  	 
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies current order applied to characters for character list window." ;
+   	 }
+}
+
diff --git a/Source/mesquite/charMatrices/SortsManagerChar/SortsManagerChar.java b/Source/mesquite/charMatrices/SortsManagerChar/SortsManagerChar.java
new file mode 100644
index 0000000..315c56c
--- /dev/null
+++ b/Source/mesquite/charMatrices/SortsManagerChar/SortsManagerChar.java
@@ -0,0 +1,164 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SortsManagerChar;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Manages specifications of character sortings, including reading the NEXUS command for CHARSORTING */
+public class SortsManagerChar extends CharSpecsSetManager {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public Class getElementClass(){
+		return CharSort.class;
+	}
+	public String upperCaseTypeName(){
+		return "Character Order";
+	}
+	public String lowerCaseTypeName(){
+		return "character order";
+	}
+	public String nexusToken(){
+		return "CHARSORTING";
+	}
+	public Object getSpecification(String token){
+		MesquiteNumber num = new MesquiteNumber();
+		num.setValue(token);
+		return num;
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof CharSort) || !(specification instanceof MesquiteNumber))
+			return;
+		CharSort characterWts = (CharSort)specsSet;
+		characterWts.setValue(ic, (MesquiteNumber)specification);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		return new CharSort(name, data.getNumChars(), data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof CharSort))
+			return null;
+		CharSort sorting = (CharSort)specsSet;
+		String s= "";
+		if (sorting !=null && (sorting.getFile()==file || (sorting.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			int numChars = data.getNumChars();
+			NumberArray distinctWeights = new NumberArray(numChars);
+			distinctWeights.deassignArray();
+			MesquiteNumber weight = new MesquiteNumber();
+			MesquiteNumber secondWeight = new MesquiteNumber();
+			boolean firstTime = true;
+			for (int iw = 0; iw<numChars; iw++){
+				sorting.placeValue(iw, weight);
+				if (distinctWeights.findValue(weight)<0){
+					int continuing = 1;
+					distinctWeights.setOpenValue(weight);
+					int lastWritten = -1;
+					if (!firstTime)
+						sT += ", ";
+					firstTime = false;
+					sT += weight.toString() + ": " + CharacterStates.toExternal(iw);
+					for (int ic=iw+1; ic<data.getNumChars(); ic++) {
+						sorting.placeValue(ic, secondWeight);
+						if (secondWeight.equals( weight)) {
+							if (continuing == 0) {
+								if (lastWritten != ic) 
+									sT += "  " + CharacterStates.toExternal(ic);
+								lastWritten = ic;
+								continuing = 1;
+							}
+							else if (continuing == 1) {
+								sT += " - ";
+								continuing = 2;
+							}
+						}
+						else if (continuing>0) {
+							if (lastWritten!= ic-1) {
+								if (lastWritten != ic) 
+									sT += "  " + CharacterStates.toExternal(ic-1);
+								lastWritten = ic-1;
+							}
+							else
+								lastWritten = -1;
+							continuing = 0;
+						}
+
+					}
+					if (continuing>1)
+						sT += " " + CharacterStates.toExternal(data.getNumChars()-1) + " ";
+				}
+			} 
+			if (!StringUtil.blank(sT)) {
+				s+= "CHARSORTING " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(sorting.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= " = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new SortingNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage stored character orders";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) character orders." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class SortingNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return (blockName.equalsIgnoreCase("ASSUMPTIONS") && commandName.equalsIgnoreCase("CHARSORTING"));
+	}
+}
+
+
diff --git a/Source/mesquite/charMatrices/SprinkleMissing/SprinkleMissing.java b/Source/mesquite/charMatrices/SprinkleMissing/SprinkleMissing.java
new file mode 100644
index 0000000..a4a7b15
--- /dev/null
+++ b/Source/mesquite/charMatrices/SprinkleMissing/SprinkleMissing.java
@@ -0,0 +1,109 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.SprinkleMissing;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.charMatrices.lib.*;
+
+/* ======================================================================== */
+public class SprinkleMissing extends RandomMatrixModifier {
+	double probMissing=0.1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		if (!MesquiteThread.isScripting()){
+    	 		double s = MesquiteDouble.queryDouble(containerOfModule(), "Probability of Missing", "Enter the probability that a cell will be converted to missing data", probMissing, 0, 1);
+ 	 		if (MesquiteDouble.isCombinable(s))
+ 	 			probMissing = s;
+ 	 		else
+ 				return false;
+  		}
+  		addMenuItem("Probability of Missing Data...", makeCommand("setProb",  this));
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setProb " + probMissing);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	if (checker.compare(this.getClass(), "Sets the probability that a cell will be converted to missing data", "[number]", commandName, "setProb")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		double s = MesquiteDouble.fromString(arguments, pos);
+    	 		if (!MesquiteDouble.isCombinable(s)){
+    	 			s = MesquiteDouble.queryDouble(containerOfModule(), "Probability of Missing", "Enter the probability that a cell will be converted to missing data", probMissing, 0, 1);
+    	 		}
+    	 		if (MesquiteDouble.isCombinable(s)){
+    	 			probMissing = s;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng){
+		if (matrix==null || modified == null)
+			return;
+		int numTaxa = matrix.getNumTaxa();
+		int numChars = matrix.getNumChars();
+		int count = 0;
+		for (int ic = 0; ic<numChars; ic++) //first, make copy
+			modified.transferFrom(ic, matrix.getCharacterDistribution(ic));
+		
+		//next, sprinkle on missing data
+		CharacterState cs = matrix.getCharacterState(null, 0, 0);
+		cs.setToUnassigned();
+		for (int it = 0; it<numTaxa; it++) 
+			for (int ic = 0; ic<numChars; ic++) {
+		   		if (rng.nextDouble()<probMissing)
+		   			modified.setCharacterState(cs, ic, it);
+	 	 	}
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Probability of missing data: " + probMissing;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+   		return "Sprinkle Missing";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+  	/*.................................................................................................................*/
+ 	 public boolean requestPrimaryChoice() {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Randomly converts entries in the character matrix to missing data, with a certain probability (i.e., it \"sprinkles\" missing data around the matrix)." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/StoredCharacters/StoredCharacters.java b/Source/mesquite/charMatrices/StoredCharacters/StoredCharacters.java
new file mode 100644
index 0000000..4285a72
--- /dev/null
+++ b/Source/mesquite/charMatrices/StoredCharacters/StoredCharacters.java
@@ -0,0 +1,689 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.StoredCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Supplies characters from character matrices stored in the project.*/
+public class StoredCharacters extends CharacterSource implements MesquiteListener, Selectionable {
+	int currentChar=0;
+	Taxa taxa=null;
+	CharacterData data;
+	CharacterDistribution states;
+	Class dataClass = null;
+	MesquiteString dataName;
+	MesquiteSubmenuSpec mss;
+	boolean autoBail=false;
+	Object condition;
+	Vector indirectListeners;
+	long cmID = -1;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		dataName = new MesquiteString();
+		mss = addSubmenu(null, "Stored Matrix", makeCommand("setDataSet",  this), (ListableVector)getProject().datas);
+		mss.setSelected(dataName);
+		//can leave a hint in terms of an id of a matrix to use
+		String whichBlock = MesquiteThread.retrieveAndDeleteHint(this);
+		long wB = MesquiteLong.fromString(whichBlock);
+		if (MesquiteLong.isCombinable(wB)){
+			cmID = wB;
+		}
+		if (condition!=null ) {
+			setHiringCondition(condition);
+			if (getProject().getNumberCharMatricesVisible(dataClass)<=0 && !MesquiteThread.isScripting()) {
+				return sorry("There are no stored data matrices of the requested type available (for use by " + getEmployer().getName() + ")");
+			}
+
+
+		}
+		else {
+			if (getProject().getNumberCharMatricesVisible()<=0 && !MesquiteThread.isScripting()) {
+				return sorry("There are no stored data matrices available (for use by " + getEmployer().getName() + ")");
+			}
+		}
+		indirectListeners = new Vector();
+		return true;
+	}
+	public void setHiringCondition(Object condition){
+		data = null;
+		this.condition = condition;
+		if (condition instanceof Class)
+			dataClass = (Class)condition;
+		else if (condition instanceof CompatibilityTest)
+			dataClass = ((CompatibilityTest)condition).getAcceptedClass();
+		boolean filter = false;
+		CharacterState cs=null;
+		try {
+			cs = (CharacterState)dataClass.newInstance();
+			filter = true;
+		}
+		catch (IllegalAccessException e){alert("iae 17"); }
+		catch (InstantiationException e){alert("ie 17"); }
+		if (filter)
+			mss.setListableFilter(cs.getCharacterDataClass());
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CSMCompatibilityTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (getProject() == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		if (taxa!=null && getProject().getNumberTaxas()>1) {
+			temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa));
+		}
+		if (data != null)
+			temp.addLine("setDataSet " + getProject().getCharMatrixReferenceExternal(data));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets which stored data matrix to use", "[matrix reference]", commandName, "setDataSet")) { //list doesn't filter by taxa but this does!!
+			String dataReference =parser.getFirstToken(arguments);
+			CharacterData d = getProject().getCharacterMatrixByReference(checker.getFile(), taxa, dataClass, dataReference, true);
+			if (d == null)
+				d = getProject().getCharacterMatrixByReference(checker.getFile(), taxa, dataClass, dataReference);
+			if (d==null && CommandRecord.macro()){ //macro; at this point ask for user to choose
+				int numMatrices = getNumberOfMatrices(taxa);
+				if (numMatrices>1) {
+					int which = queryUser(taxa, numMatrices);
+					if (MesquiteInteger.isCombinable(which)) {
+						d = getProject().getCharacterMatrixVisible(which);
+						useMatrix(taxa, d);
+						dataName.setReferentID(Long.toString(d.getID()));
+						dataName.setValue(d.getName());
+						currentChar = 0;
+						parametersChanged();
+					}
+					else
+						return null;
+				}
+				else {
+					useFirstMatrix(taxa);
+					if (d == null)
+						return null;
+					dataName.setReferentID(Long.toString(d.getID()));
+					dataName.setValue(d.getName());
+					currentChar = 0;
+					parametersChanged();
+				}
+			}
+			else if (d!=null && d!= data) {
+				if (taxa == null)
+					taxa = d.getTaxa();
+				mss.setCompatibilityCheck(taxa);
+				useMatrix(taxa, d);
+				dataName.setReferentID(Long.toString(d.getID()));
+				dataName.setValue(d.getName());
+				currentChar = 0;
+				parametersChanged();
+				resetContainingMenuBar();
+			}
+			return d;
+		}
+		else if (checker.compare(this.getClass(), "Sets which taxa block to use", "[block reference, number, or name]", commandName, "setTaxa")) { 
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				mss.setCompatibilityCheck(taxa);
+				parametersChanged();
+				resetContainingMenuBar();
+				return taxa;
+			}
+			else
+				MesquiteMessage.warnProgrammer("Stored characters error: taxa reference not found");
+		}
+		else if (checker.compare(this.getClass(), "Returns number of characters available", null, commandName, "getNumberOfCharacters")) {
+			MesquiteInteger n = new MesquiteInteger();
+			n.setValue(getNumberOfCharacters(taxa));
+			return n;
+		}
+		else if (checker.compare(this.getClass(), "Sets autoBail", "[on or off]", commandName, "autoBail")) {
+			autoBail = ("on".equalsIgnoreCase(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == data && !doomed) {
+			data.removeListener(this);
+			if (taxa !=null && taxa.isDoomed()) {
+				iQuit();
+				return;
+			}
+			data = null;
+			dataName.setReferentID(null);
+			dataName.setValue("No matrix is currently in use");
+		/*
+			discreetAlert("A character data matrix in use (for " + getEmployer().getName() + " used by \"" + getEmployer().getEmployer().getName() + "\") has been deleted.  Another matrix will be sought.");
+
+			if (dataClass!=null) {
+				if (getProject().getNumberCharMatricesVisible(taxa, dataClass)<=0) {
+					iQuit();
+					return;
+				}
+				data = getProject().getCharacterMatrixVisible(taxa, 0, dataClass);
+			}
+			else if (getProject().getNumberCharMatricesVisible(taxa)>0) {
+				data = getProject().getCharacterMatrixVisible(taxa, 0);
+			}
+			else data = null;
+			if (data==null){
+				iQuit();
+				return;
+			}
+			data.addListener(this);
+			dataName.setValue(data.getName());
+			*/
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //Disposal prohibition not used in Mesquite yet; once used then this should return false if currently in use
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj==data && (code == AssociableWithSpecs.SPECSSET_CHANGED || code == MesquiteListener.VALUE_CHANGED ||code == MesquiteListener.DATA_CHANGED || code == MesquiteListener.PARTS_CHANGED || code == MesquiteListener.PARTS_ADDED || code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_MOVED)){
+			parametersChanged(notification);
+		}
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		checkMatrix(taxa, false);
+	}
+
+
+	private int queryUser(Taxa taxa, int numMatrices){
+		if (cmID >=0){
+			for (int i=0; i<numMatrices; i++) {
+				CharacterData d = retrieveDataSet(taxa, i);
+				if (d.getID() == cmID)
+					return i;
+			}
+		}
+		String[] names = new String[numMatrices];
+		for (int i=0; i<numMatrices; i++) {
+			CharacterData d = retrieveDataSet(taxa, i);
+			if (d!=null)
+				names[i]=d.getName() + " (" + d.getDataTypeName() + ")";
+		}
+		String forWhom = whatIsMyPurpose();
+
+		if (isInStartup()){
+			MesquiteInteger io = new MesquiteInteger(0);
+			ListDialog id = new ListDialog(containerOfModule(), "Select data matrix", "Use characters from which matrix? \n(" + forWhom + ")", false, MesquiteString.helpString, names, io, null,true, false);
+			id.completeDialog("OK",null, true,id);
+			id.setVisible(true);
+			id.dispose();
+			return io.getValue();
+		}
+		else
+			return ListDialog.queryList(containerOfModule(), "Select data matrix", "Use characters from which matrix? \n(" + forWhom + ")", MesquiteString.helpString,names, 0);
+	}
+
+	boolean warned = false;
+	boolean compDone = false;
+
+	private void setTaxa(Taxa taxa){
+		if (this.taxa != taxa || !compDone) {
+			compDone = true;
+			mss.setCompatibilityCheck(taxa);
+			resetContainingMenuBar();
+		}
+		this.taxa = taxa;
+	}
+	public boolean checkMatrix( Taxa taxa, boolean warn) {
+		if (taxa == null && getProject().getNumberTaxas()!=1) {
+			return false;
+		}
+		if (taxa == null)
+			taxa = getProject().getTaxa(0);
+		setTaxa(taxa);
+		if (data==null || data.getTaxa() != taxa) {
+			int numMatrices = getNumberOfMatrices(taxa);
+			if (numMatrices == 0) {
+				if (warn && !warned){
+					discreetAlert("Sorry, there are no character matrices available for the indicated block of taxa (" + taxa.getName() + ").  Stored Characters cannot be supplied.");
+					warned = true;
+					return false;
+				}
+			}
+			else if ((!MesquiteThread.isScripting())  && numMatrices>1) {
+				int which = queryUser(taxa, numMatrices);
+				if (MesquiteInteger.isCombinable(which)) {
+
+					CharacterData d = retrieveDataSet(taxa, which);
+					useMatrix(taxa, d);
+				}
+				else {
+					return false;
+				}
+			}
+			else
+				useFirstMatrix(taxa);
+			if (data == null)
+				return false;
+			return true;
+		}
+		else
+			return true;
+	}
+	/*.................................................................................................................*/
+	private CharacterDistribution getC(Taxa taxa) {
+		if (checkMatrix( taxa, true)){
+			int whichCharacter = currentChar;
+			if (respectExclusion)
+				whichCharacter = findIncludedCharacter(data, currentChar);
+			if (whichCharacter <0 && countIncludedCharacters(data)>0) {
+				MesquiteMessage.printStackTrace("Error: Character < 0 in StoredCharacters " + currentChar + " " + whichCharacter);
+			}
+			states = data.getCharacterDistribution(whichCharacter);
+			if (states == null)
+				MesquiteMessage.warnUser("Error: Data set failed to return a character distribution " + currentChar);
+			return states;
+		}
+		else {
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+		//CommandRecord.tick("Getting stored character " + (ic+1));
+		currentChar=ic;
+		return getC(taxa);
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	boolean respectExclusion = true;
+	public int countIncludedCharacters(CharacterData data){
+		if (data==null)
+			return 0;
+		if (!respectExclusion)
+			return data.getNumChars();
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return numChars;
+		int count = 0;
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i))
+				count++;
+		return count;
+
+	}
+	public int findIncludedCharacter(CharacterData data, int ic){
+		if (!respectExclusion)
+			return ic;
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return ic;
+		int count = 0;
+		for (int i=0; i<numChars; i++){
+			if (incl.isBitOn(i)){
+				if (count == ic)
+					return i;
+				count++;
+			}
+		}
+		return -1;
+
+	}
+	public Selectionable getSelectionable(){
+		return this;  //data or this
+	}
+	/** Sets whether or not the part is selected */
+	public void setSelected(int part, boolean select){
+		if (data == null)
+			return;
+		int ic = findIncludedCharacter(data, part);
+		if (ic>=0)
+			data.setSelected(ic, select);
+	}
+
+	/** Returns whether the part is selected */
+	public boolean getSelected(int part){
+		if (data == null)
+			return false;
+		int ic = findIncludedCharacter(data, part);
+		if (ic>=0)
+			return data.getSelected(ic);
+		return false;
+	}
+
+	/** Deselects all parts */
+	public void deselectAll(){
+		if (data == null)
+			return;
+		data.deselectAll();
+	}
+
+	/** Selects all parts */
+	public void selectAll(){
+		if (data == null)
+			return;
+		data.selectAll();
+	}
+
+
+
+	/** Returns whether there are any selected parts */
+	public boolean anySelected(){
+		if (data == null)
+			return false;
+		return data.anySelected();
+	}
+
+	/** Returns number of selected parts */
+	public int numberSelected(){
+		if (data == null)
+			return 0;
+
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null){
+			return data.numberSelected();
+		}
+		int count = 0;
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i) && data.getSelected(i)) //included and selected
+				count++;
+		return count;
+	}
+
+	/** Returns number of parts that can be selected*/
+	public int getNumberOfSelectableParts(){
+		if (data == null)
+			return 0;
+		return countIncludedCharacters(data);
+	}
+	private void removeIndirectListeners(CharacterData d){
+		for (int i=0; i<indirectListeners.size(); i++)
+			data.removeListener((MesquiteListener)indirectListeners.elementAt(i));
+		indirectListeners.removeAllElements();
+	}
+	/*.................................................................................................................*/
+	/** lists listeners of element*/
+	public boolean amIListening(MesquiteListener obj) {
+		if (data == null)
+			return false;
+		return data.amIListening(obj);
+	}
+	/*.................................................................................................................*/
+	/** lists listeners of element*/
+	public void listListeners() {
+		if (data == null)
+			return;
+		data.listListeners();
+	}
+	/*.................................................................................................................*/
+
+	/** notifies listeners that element has changed*/
+	public void notifyListeners(Object caller, Notification notification){
+		if (data == null)
+			return;
+		data.notifyListeners(caller, notification);
+	}
+	/** adds a listener to notify if the element changes*/
+	public void addListener(MesquiteListener listener){
+		if (data == null)
+			return;
+		if (indirectListeners.indexOf(listener)<0)
+			indirectListeners.addElement(listener);
+		data.addListener(listener);
+	}
+	/** adds a listener to notify if the element changes; add to start of listener vector so it will be notified early*/
+	public void addListenerHighPriority(MesquiteListener listener){
+		if (data == null)
+			return;
+		if (indirectListeners.indexOf(listener)<0)
+			indirectListeners.addElement(listener);
+		data.addListenerHighPriority(listener);
+	}
+	/** removes a listener*/
+	public void removeListener(MesquiteListener listener){
+		if (data == null)
+			return;
+		indirectListeners.removeElement(listener);
+		data.removeListener(listener);
+	}
+	/** Increments the suppression of listener notification*/
+	public void incrementNotifySuppress(){
+		if (data == null)
+			return;
+		data.incrementNotifySuppress();
+	}
+	/** Decrements the suppression of listener notification*/
+	public void decrementNotifySuppress(){
+		if (data == null)
+			return;
+		data.decrementNotifySuppress();
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfCharacters(Taxa taxa) {
+		if (checkMatrix( taxa, false)) {
+			if (respectExclusion)
+				return countIncludedCharacters(data);
+			return data.getNumChars();
+		}
+		else
+			return 0;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the name of character ic*/
+	public String getCharacterName(Taxa taxa, int ic){
+		if (checkMatrix( taxa, false)) {
+			if (data==null)
+				return null;
+			int whichCharacter = ic;
+			if (respectExclusion)
+				whichCharacter = findIncludedCharacter(data, ic);
+			return data.getCharacterName(whichCharacter);  
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	private  int getNumberOfMatrices(Taxa taxa){
+		if (getProject() == null)
+			return 0;
+		else
+			if (dataClass == null) {
+				return getProject().getNumberCharMatricesVisible(taxa); 
+			}
+			else {
+				return getProject().getNumberCharMatricesVisible(taxa, dataClass); 
+			}
+	}
+	/*.................................................................................................................*/
+	private  CharacterData retrieveDataSet(Taxa taxa, int index){
+		if (getNumberOfMatrices(taxa)==0 && autoBail){
+			iQuit();
+			return null;
+		}
+		return getProject().getCharacterMatrixVisible(taxa, index, dataClass);
+	}
+
+	/*.................................................................................................................*/
+	private  void useFirstMatrix(Taxa taxa){
+		setTaxa(taxa);
+		CharacterData tempData = retrieveDataSet(taxa, 0);
+		if (data!=tempData && tempData!=null) {
+			if (data!=null) 
+				data.removeListener(this);
+			removeIndirectListeners(data);
+			data = tempData;
+			dataName.setReferentID(Long.toString(data.getID()));
+			dataName.setValue(data.getName());
+			data.addListener(this);
+		}
+	}
+	private void useMatrix(Taxa taxa, CharacterData tempData){
+		setTaxa(taxa);
+		if (data!=tempData && tempData!=null) {
+			if (data!=null) 
+				data.removeListener(this);
+			removeIndirectListeners(data);
+			data = tempData;
+			dataName.setReferentID(Long.toString(data.getID()));
+			dataName.setValue(data.getName());
+			data.addListener(this);
+		}
+	}
+	CharacterPartition colorSet;
+	public void setEnableWeights(boolean enable){
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		return MesquiteDouble.unassigned;
+	}
+	/*.................................................................................................................*/
+	public void prepareItemColors(Taxa taxa){
+		if (taxa==null || data == null || data.getTaxa()!=taxa)
+			colorSet=null;
+		else
+			colorSet = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class); 
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (taxa==null || data == null || data.getTaxa()!=taxa)
+			return null;
+		
+		//DRM 9 Feb 2013   Added this section so that charts were colored correctly
+		int whichCharacter = ic;
+		if (respectExclusion)
+			whichCharacter = findIncludedCharacter(data, ic);
+		if (whichCharacter <0 && countIncludedCharacters(data)>0) {
+			MesquiteMessage.printStackTrace("Error: Character < 0 in StoredCharacters " + currentChar + " " + whichCharacter);
+		}
+		//DRM end
+		if (colorSet!=null){
+			CharactersGroup mi = (CharactersGroup)colorSet.getProperty(whichCharacter);
+			if (mi!=null && mi.getColor()!=null) {
+				return mi.getColor();
+			}
+			return null;
+		}
+		return data.getDefaultCharacterColor(whichCharacter);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stored Characters";  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies characters from data files (as opposed to simulated characters, for example)." ;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (getProject() == null)
+			return "";
+		String s = "Characters stored in: " + getProject().getName();
+		if (data!=null) {
+			s +=  " (current matrix: " + data.getName() + ")";
+			if (getHiredAs() == CharacterOneSource.class)
+				s +=  "; current character: " + data.getCharacterName(currentChar);
+			s += ")";
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getNameAndParameters() {
+		if (data!=null) {
+			String s =  "Character matrix: " + data.getName();
+			if (getHiredAs() == CharacterOneSource.class)
+				s +=  "; current character: " + data.getCharacterName(currentChar);
+			return s;
+		}
+		String s = "Characters stored in: " + getProject().getName();
+		return s;
+	}
+
+	public void endJob() {
+		if (data!=null) data.removeListener(this);
+		//if (taxa != null) taxa.removeListener(this);
+		super.endJob();
+	}
+
+}
+
+class CSMCompatibilityTest extends CompatibilityTest{
+//	should find out if available matrices of chosen sort
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj == null) {
+			boolean can = (project == null || project.getNumberCharMatricesVisible()>0);
+			if (!can && report != null)
+				report.setValue("there are no character matrices stored in the data file or project");
+			return can;
+		}
+		if (!(obj instanceof Class) || !(CharacterState.class.isAssignableFrom((Class)obj)))
+			return true;
+		if (project==null)
+			return true;
+		else {
+			boolean  matricesExist = project.getNumberCharMatricesVisible((Class)obj)>0;
+			if (!matricesExist && report != null)
+				report.setValue("there are no appropriate character matrices stored in the data file or project");
+			return matricesExist; //still not perfect, since data set might apply to other taxa
+		}
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/StoredMatrices/StoredMatrices.java b/Source/mesquite/charMatrices/StoredMatrices/StoredMatrices.java
new file mode 100644
index 0000000..44f216e
--- /dev/null
+++ b/Source/mesquite/charMatrices/StoredMatrices/StoredMatrices.java
@@ -0,0 +1,425 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.StoredMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/** Supplies character matrices stored in the project.*/
+public class StoredMatrices extends CharMatrixSource implements MesquiteListener {
+	Taxa taxa=null;
+	CharacterData data;
+	MCharactersDistribution states;
+	Class dataClass = null;
+	MesquiteString dataName;
+	MesquiteSubmenuSpec mss;
+	boolean iveQuit = false; //need special means to quit if multiple taxa blocks, because then harder to know on startup if matrices are available
+	MesquiteBoolean autoQuit;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		autoQuit = new MesquiteBoolean(true);
+		String sPurpose = whatIsMyPurpose();
+		if (!StringUtil.blank(sPurpose))
+			sPurpose = " (" + sPurpose + ")";
+		else sPurpose = "";
+		if (condition!=null) {
+			dataName = new MesquiteString();
+			if (condition instanceof Class)   //NOTE: class should be subclass of CharacterState, not CharacterData!!!
+				dataClass = (Class)condition;
+			else if (condition instanceof CompatibilityTest)
+				dataClass = ((CompatibilityTest)condition).getAcceptedClass();
+			if (getProject().getNumberCharMatricesVisible(dataClass)<=0 && !MesquiteThread.isScripting()) { //if scripting, matrix might be available later
+				return sorry("There are no stored matrices of the requested type available");
+			}
+			if (getHiredAs() != (CharMatrixObedSource.class)) {	//not hired as a obedient source 
+				mss = addSubmenu(null, "Stored Matrix" + sPurpose, makeCommand("setDataSet",  this), (ListableVector)getProject().datas);
+				mss.setSelected(dataName);
+				setDataClass(dataClass);
+			}
+			return true;
+		}
+		else {
+			if (getProject().getNumberCharMatricesVisible()<=0 && !MesquiteThread.isScripting()) {
+				return sorry("There are no stored matrices available");
+			}
+			dataName = new MesquiteString();
+			if (getHiredAs() != (CharMatrixObedSource.class)) {	//not hired as a obedient source  
+				mss = addSubmenu(null, "Stored Matrix" + sPurpose, makeCommand("setDataSet",  this), (ListableVector)getProject().datas);
+				mss.setSelected(dataName);
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void setDataClass(Class dataClass){
+		boolean filter = false;
+		CharacterState cs=null;
+		try {
+			cs = (CharacterState)dataClass.newInstance();
+
+			filter = true;
+		}
+		catch (IllegalAccessException e){alert("iae 17m"); }
+		catch (InstantiationException e){alert("ie 17m"); }
+		if (filter && mss != null)
+			mss.setListableFilter(cs.getCharacterDataClass());
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CSMCompatibilityTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (taxa!=null && getProject() != null && getProject().getNumberTaxas()>1)
+			temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa));
+		if (data !=null && getProject() != null)
+			temp.addLine("setDataSet " + getProject().getCharMatrixReferenceExternal(data));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets which stored data matrix to use", "[matrix reference]", commandName, "setDataSet")) { 
+			CharacterData d = getProject().getCharacterMatrixByReference(checker.getFile(), taxa, dataClass, parser.getFirstToken(arguments), true);  //31 jul '10 added true for visible only
+			if (d == null)
+				d = getProject().getCharacterMatrixByReference(checker.getFile(), taxa, dataClass, parser.getFirstToken(arguments));
+			if (d==null && CommandRecord.macro()){ //macro; at this point ask for user to choose
+				int which = queryUser(taxa);
+				if (MesquiteInteger.isCombinable(which)) {
+					d = getProject().getCharacterMatrixVisible(which);
+					setMatrix(taxa, d);
+					parametersChanged();
+				}
+				else
+					return null;
+			}
+			else if (d !=null && d!=data) {
+				if (taxa == null)
+					taxa = d.getTaxa();
+				setMatrix(taxa, d);
+				parametersChanged();
+				resetContainingMenuBar();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which taxa block to use", "[block reference, number, or name]", commandName, "setTaxa")) { 
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				parametersChanged();
+				resetContainingMenuBar();
+				return taxa;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to auto-quit when no matrices are available", "[on or off]", commandName, "autoQuit")) { 
+			autoQuit.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == data && !doomed) {
+			data.removeListener(this);
+			if (!autoQuit.getValue()) {
+				data = null;
+				return;
+			}
+			
+			if (taxa !=null && taxa.isDoomed()) {
+				taxa = null;
+				if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Taxa block that is in use has been deleted"))  
+					return;
+				
+				logln("Taxa null or being disposed; StoredMatrices will quit.");
+				iQuit();
+				return;
+				
+			}
+			data = null;
+			dataName.setReferentID(null);
+			dataName.setValue("No matrix is currently in use");
+			if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Character matrix that is in use has been deleted"))  
+				return;
+			
+			MesquiteModule.showLogWindow(true);
+
+			MesquiteMessage.warnUser("A character data matrix in use (" + whatIsMyPurpose() + ") has been deleted.  Another matrix will be sought.");  
+			if (dataClass!=null) {
+				if (getProject().getNumberCharMatricesVisible(taxa, dataClass)<=0) {
+					MesquiteModule.showLogWindow(true);
+					MesquiteMessage.warnUser("No compatible character matrices were found " + whatIsMyPurpose() + ", and so Stored Matrices cannot be used.");
+					iQuit(false);
+					return;
+				}
+				data = getProject().getCharacterMatrixVisible(taxa, 0, dataClass);
+			}
+			else if (getProject().getNumberCharMatricesVisible(taxa)>0)
+				data = getProject().getCharacterMatrixVisible(taxa, 0);
+			else data = null;
+			if (data==null){
+				MesquiteModule.showLogWindow(true);
+				MesquiteMessage.warnUser("No character matrices found " + whatIsMyPurpose() + ", and so Stored Matrices cannot be used.");
+				iQuit(false);
+				return;
+			}
+			data.addListener(this);
+			dataName.setReferentID(Long.toString(data.getID()));
+			dataName.setValue(data.getName());
+			
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //Disposal prohibition not used in Mesquite yet; once used then this should return false if currently in use
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj==data && (code == AssociableWithSpecs.SPECSSET_CHANGED || code == MesquiteListener.VALUE_CHANGED ||code == MesquiteListener.DATA_CHANGED || code == MesquiteListener.PARTS_CHANGED || code == MesquiteListener.PARTS_ADDED || code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_MOVED)){
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Taxa taxa){
+		if (getProject()==null)
+			return 0;
+		else if (dataClass == null)
+			return getProject().getNumberCharMatricesVisible(taxa); 
+		else
+			return getProject().getNumberCharMatricesVisible(taxa, dataClass); 
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public  void setMatrix(Taxa taxa, CharacterData d){
+		checkCurrentDataSet(taxa, d,  false, true);
+		this.taxa = taxa;
+	}
+
+	private int queryUser(Taxa taxa){
+		int nd = getProject().getNumberCharMatricesVisible(taxa, dataClass);
+		String[] list = new String[nd];
+		for (int i=0; i< nd; i++)
+			list[i]=getProject().getCharacterMatrixVisible(taxa, i, dataClass).getName();
+		String purposeString = "";
+		if (!StringUtil.blank(whatIsMyPurpose()))
+			purposeString = whatIsMyPurpose() + "; ";
+		return ListDialog.queryList(containerOfModule(), "Use which matrix?", "Use which matrix? \n(" + purposeString + "for " + employer.getName() + ")", MesquiteString.helpString,list, 0);
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		checkCurrentDataSet(taxa, null, false, getHiredAs() != (CharMatrixObedSource.class));
+	}
+
+	private void setTaxa(Taxa taxa){
+		if (this.taxa != taxa && mss != null) {
+			mss.setCompatibilityCheck(taxa);
+			resetContainingMenuBar();
+		}
+		this.taxa = taxa;
+	}
+	boolean warned = false;
+	private void checkCurrentDataSet(Taxa taxa, CharacterData proposed,  boolean warn, boolean queryIfNeeded) {
+		if (iveQuit)
+			return;
+		setTaxa(taxa);
+		if (proposed != null && proposed.getTaxa() == taxa){ //new matrix being proposed
+			if (proposed == data) 
+				return;
+			dataName.setReferentID(Long.toString(proposed.getID()));
+			dataName.setValue(proposed.getName());
+			if (data !=null)
+				data.removeListener(this);
+			proposed.addListener(this);
+
+			data = proposed;
+		}
+		if (getProject() == null)
+			return;
+		if (data == null) { // data == null && proposed == null; need to choose one
+			if (MesquiteThread.isScripting() || getHiredAs() == CharMatrixObedSource.class) 
+				data = getProject().getCharacterMatrixVisible(taxa, 0, dataClass);
+			else if (getProject().getNumberCharMatricesVisible(taxa, dataClass)<=1)
+				data = getProject().getCharacterMatrixVisible(taxa, 0, dataClass);
+			else {
+				int currentDataSet = 0;
+				if (queryIfNeeded){
+					currentDataSet = queryUser(taxa); //ListDialog.queryList(containerOfModule(), "Use which matrix?", "Use which matrix? \n(" + purposeString + "for " + employer.getName() + ")", list, 0);
+					if (!MesquiteInteger.isCombinable(currentDataSet))
+						currentDataSet = 0;
+				}
+				data = getProject().getCharacterMatrixVisible(taxa, currentDataSet, dataClass);
+			}
+			if (data !=null) {
+				if (taxa == null)
+					setTaxa(data.getTaxa());
+				data.addListener(this);
+			}
+			else {
+				if (!MesquiteThread.isScripting()){ //if scripting, hope that will soon be fired!
+					if (taxa == null)
+						alert("There are no appropriate stored character matrices available.");
+					else 
+						alert("There are no appropriate stored character matrices available for the block of taxa (" + taxa.getName() + ").");
+					iveQuit = true;
+					iQuit(false);
+				}
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	private MCharactersDistribution getM(Taxa taxa) {
+		setTaxa(taxa);
+		checkCurrentDataSet(taxa, null,  true, true); //just to insure that OK
+		if (data!=null) {
+			states = data.getMCharactersDistribution();
+			return states;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getMatrixName(Taxa taxa, int ic) {
+		CharacterData data;
+		if (!MesquiteInteger.isCombinable(ic))
+			return "";
+		if (dataClass == null)
+			data = getProject().getCharacterMatrixVisible(taxa, ic);
+		else
+			data =  getProject().getCharacterMatrixVisible(taxa, ic, dataClass);
+		if (data !=null)
+			return data.getName();
+		return "";
+	}
+	/*.................................................................................................................*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+		try {
+			checkCurrentDataSet(taxa, getProject().getCharacterMatrixVisible(taxa, im, dataClass),  false, true);
+			CommandRecord.tick("Getting stored matrix " + im);
+			return getM(taxa);
+		}
+		catch(NullPointerException e){
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** gets the current matrix.*/
+	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		if (taxa!=null && !taxa.equals(this.taxa, false)){//taxa==null || 
+			if (data!=null)
+				data.removeListener(this);
+			data = null;
+		}
+		checkCurrentDataSet(taxa, null,  false, true);
+		return getM(taxa);
+	}
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return getProject().getMatrixNumber(data);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stored Matrices";  
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies character matrices from data files (as opposed to simulated characters, for example)." ;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (data!=null && getHiredAs() == CharMatrixOneSource.class)
+			return "Current Matrix: " + data.getName();
+		else if (getProject() != null)
+			return "Character Matrices from file: " + getProject().getName();
+		else
+			return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getNameAndParameters() {
+		if (data!=null && getHiredAs() == CharMatrixOneSource.class)
+			return "Stored Matrix: " + data.getName();
+		else if (getProject() != null)
+			return "Character Matrices from file: " + getProject().getName();
+		else
+			return null;
+	}
+	public void endJob() {
+		if (data!=null) data.removeListener(this);
+		super.endJob();
+	}
+
+}
+
+class CSMCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj == null) {
+			boolean can = (project == null || project.getNumberCharMatricesVisible()>0);
+			if (!can && report != null)
+				report.setValue("there are no character matrices stored in the data file or project");
+			return can;
+		}
+		if (!(obj instanceof Class) || !(CharacterState.class.isAssignableFrom((Class)obj)))
+			return true;
+		if (project==null)
+			return true;
+		else {
+			boolean matricesExist = ( project.getNumberCharMatricesVisible((Class)obj)>0); //still not perfect, since data set might apply to other taxa
+			if (!matricesExist && report != null)
+				report.setValue("there are no appropriate character matrices stored in the data file or project");
+			return matricesExist;
+		}
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/TaxonGroupColor/TaxonGroupColor.java b/Source/mesquite/charMatrices/TaxonGroupColor/TaxonGroupColor.java
new file mode 100644
index 0000000..4815128
--- /dev/null
+++ b/Source/mesquite/charMatrices/TaxonGroupColor/TaxonGroupColor.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.TaxonGroupColor; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class TaxonGroupColor extends DataWindowAssistantI implements CellColorer, CellColorerTaxa, CellColorerMatrix {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.data = data;
+		taxa = data.getTaxa();
+	}
+	CharacterData data;
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Group Color";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors by Taxon Group.";
+	}
+
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; 
+	}
+	public ColorRecord[] getLegendColors(){
+		return null;
+	}
+	public String getColorsExplanation(){
+		return null;
+	}
+	public Color getCellColor(int ic, int it){
+		if ( it>=0)  {
+			TaxaPartition part = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+			if (part!=null){
+				TaxaGroup mi = (TaxaGroup)part.getProperty(it);
+				if (mi!=null)
+					return mi.getColor();
+			}
+			return null;
+		}
+		return null;
+	}
+	public String getCellString(int ic, int it){
+		if (it>=0)  {
+			TaxaPartition part = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+			if (part!=null){
+				TaxaGroup mi = (TaxaGroup)part.getProperty(it);
+				if (mi!=null)
+					return "This taxon belongs to the group " + mi.getName();
+			}
+		}
+		return "";
+	}
+	public String getParameters(){
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/Wand/32magicWand.gif b/Source/mesquite/charMatrices/Wand/32magicWand.gif
new file mode 100644
index 0000000..383ec70
Binary files /dev/null and b/Source/mesquite/charMatrices/Wand/32magicWand.gif differ
diff --git a/Source/mesquite/charMatrices/Wand/64magicWand.gif b/Source/mesquite/charMatrices/Wand/64magicWand.gif
new file mode 100644
index 0000000..246b6fa
Binary files /dev/null and b/Source/mesquite/charMatrices/Wand/64magicWand.gif differ
diff --git a/Source/mesquite/charMatrices/Wand/Wand.java b/Source/mesquite/charMatrices/Wand/Wand.java
new file mode 100644
index 0000000..4832fdb
--- /dev/null
+++ b/Source/mesquite/charMatrices/Wand/Wand.java
@@ -0,0 +1,381 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.Wand; //DRM started April 02
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/*   to do:
+	- deal with Option cursor, Shift cursor
+	- pass taxaAreRows into this
+ */
+
+
+/* ======================================================================== */
+public class Wand extends DataWindowAssistantI {
+	TableTool magicWandTool;
+	CharacterData data;
+	MesquiteTable table;
+	MesquiteBoolean wholeMatrix, singleTaxon, singleCharacter, contiguous, equals, greaterthan, lessthan, selectByText, selectByColor;
+	boolean defaultEquals = true;
+	boolean defaultGT = false;
+	boolean defaultLT = false;
+	boolean defaultSingleTaxon = false;
+	boolean defaultSingleCharacter = false;
+	boolean defaultWholeMatrix = true;
+	boolean defaultContiguous = false;
+	boolean taxaAreRows = true;
+	MesquiteMenuItemSpec eItem, gItem, lItem;
+	MesquiteCollator collator;
+	 public String getFunctionIconPath(){
+   		 return getPath() + "magicWand.gif";
+   	 }
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			magicWandTool = new TableTool(this, "magicWand", getPath(), "magicWand.gif", 4,4,"Select cells with same", "This tool selects cells according to criteria of being the same, greater than, or less than the value in the cell touched.  The criteria can be set using the menu that appears when you click on the tool button", MesquiteModule.makeCommand("magicWandTouch",  this) , null, null);
+			((MesquiteWindow)containerOfModule()).addTool(magicWandTool);
+			magicWandTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching oning button
+		}
+		else return false;
+		selectByText = new MesquiteBoolean(true);
+
+		selectByColor = new MesquiteBoolean(!selectByText.getValue());
+		singleTaxon = new MesquiteBoolean(defaultSingleTaxon);
+		singleCharacter = new MesquiteBoolean(defaultSingleCharacter);
+		wholeMatrix = new MesquiteBoolean(defaultWholeMatrix);
+		contiguous = new MesquiteBoolean(defaultContiguous);
+		equals = new MesquiteBoolean(defaultEquals);
+		greaterthan = new MesquiteBoolean(defaultGT);
+		lessthan = new MesquiteBoolean(defaultLT);
+		addCheckMenuItem(null, "Select by Text", makeCommand("selectByText",  this), selectByText);
+		addCheckMenuItem(null, "Select by Color", makeCommand("selectByColor",  this), selectByColor);
+		addMenuItem("-", null);
+		eItem = addCheckMenuItem(null, "Equal", makeCommand("toggleEquals",  this), equals);
+		gItem = addCheckMenuItem(null, "Greater than", makeCommand("toggleGT",  this), greaterthan);
+		lItem = addCheckMenuItem(null, "Less than", makeCommand("toggleLT",  this), lessthan);
+		addMenuItem("-", null);
+		addCheckMenuItem(null, "Whole Matrix", makeCommand("toggleWholeMatrix",  this), wholeMatrix);
+		addCheckMenuItem(null, "Restrict to single taxon", makeCommand("toggleSingleTaxon",  this), singleTaxon);
+		addCheckMenuItem(null, "Restrict to single character", makeCommand("toggleSingleCharacter",  this), singleCharacter);
+		addCheckMenuItem(null, "Contiguous", makeCommand("toggleContiguous",  this), contiguous);
+		collator = new MesquiteCollator();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (wholeMatrix.getValue()!=defaultWholeMatrix)
+			temp.addLine("toggleWholeMatrix " + wholeMatrix.toOffOnString());
+		if (singleTaxon.getValue()!=defaultSingleTaxon)
+			temp.addLine("toggleSingleTaxon " + singleTaxon.toOffOnString());
+		if (singleCharacter.getValue()!=defaultSingleCharacter)
+			temp.addLine("toggleSingleCharacter " + singleCharacter.toOffOnString());
+		if (contiguous.getValue()!=defaultContiguous)
+			temp.addLine("toggleContiguous " + contiguous.toOffOnString());
+		if (equals.getValue()!=defaultEquals)
+			temp.addLine("toggleEquals " + equals.toOffOnString());
+		if (greaterthan.getValue()!=defaultGT)
+			temp.addLine("toggleGT " + greaterthan.toOffOnString());
+		if (lessthan.getValue()!=defaultLT)
+			temp.addLine("toggleLT " + lessthan.toOffOnString());
+		if (!selectByText.getValue())
+			temp.addLine("selectByColor");
+		return temp;
+	}
+	boolean satisfiesCriteria(String one, String two){
+		if (equals.getValue() && one.equals(two))
+			return true;
+		double dOne = MesquiteDouble.fromString(one);
+		double dTwo = MesquiteDouble.fromString(two);
+		if (MesquiteDouble.isCombinable(dOne) && MesquiteDouble.isCombinable(dTwo)) {
+			if (greaterthan.getValue() && (dTwo>dOne))
+				return true;
+			if (lessthan.getValue() && (dTwo<dOne))
+				return true;
+			return false;
+		}
+		int order = collator.compare(one, two);
+		//int order =0;
+		if (greaterthan.getValue() && (order == -1))
+			return true;
+		if (lessthan.getValue() && (order == 1))
+			return true;
+		if (equals.getValue() && (order == 0))
+			return true;
+		return false;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(),  "Touches on a cell with the wand to select cells similar as defined by the options", "[column touched][row touched]", commandName, "magicWandTouch")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isNonNegative(column)&& (MesquiteInteger.isNonNegative(row))) {
+				boolean commandSelected =  (arguments.indexOf("command")>=0);
+				boolean subtractFromSelection = commandSelected && table.isCellSelected(column, row);
+				if ((arguments.indexOf("shift")<0) && !commandSelected)
+					table.deselectAll();
+				
+
+
+				table.offAllEdits();
+				if (arguments.indexOf("option")>=0 && getEmployer() instanceof mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker){
+					mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker mb = (mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker)getEmployer();
+					mb.selectDataBlockInTaxon(column, row);
+				}
+				else if (selectByText.getValue()){
+					if (contiguous.getValue()){
+						String text = table.getMatrixText(column, row);
+						if (contigSel == null || contigSel.length != table.getNumColumns() || contigSel[0].length != table.getNumRows())
+							contigSel = new boolean[table.getNumColumns()][table.getNumRows()];
+						for (int i = 0; i< contigSel.length; i++)
+							for (int k = 0; k<table.getNumRows(); k++)
+								contigSel[i][k] = false;
+						numContigFound = 0;
+						selectContiguous(column+1, row, text, subtractFromSelection, true, true, 0);
+						selectContiguous(column-1, row, text, subtractFromSelection, true, false, 0);
+						selectContiguous(column, row+1, text, subtractFromSelection, false, true, 0);
+						selectContiguous(column, row-1, text, subtractFromSelection, false, false, 0);
+						checkCell(column, row, text, subtractFromSelection);
+					} 
+					else {
+						String text = table.getMatrixText(column, row);
+						int rowStart = 0;
+						int rowEnd = table.getNumRows();
+						int columnStart = 0;
+						int columnEnd = table.getNumColumns();
+						numContigFound = 0;
+						if (singleTaxon.getValue()) {
+							if (taxaAreRows) {
+								rowStart = row;
+								rowEnd = row+1;
+							}
+							else {
+								columnStart = column;
+								columnEnd = column+1;
+							}
+						}
+						else if (singleCharacter.getValue()) {
+							if (!taxaAreRows) {
+								rowStart = row;
+								rowEnd = row+1;
+							}
+							else {
+								columnStart = column;
+								columnEnd = column+1;
+							}
+						}
+						for (int j=rowStart; j<rowEnd; j++){
+							for (int i=columnStart; i<columnEnd; i++){
+								if (satisfiesCriteria(text, table.getMatrixText(i, j))) {
+									numContigFound++;
+									if (numContigFound % 100 == 0)
+										CommandRecord.tick(Integer.toString(numContigFound) + " cells found");
+									if (subtractFromSelection)
+										table.deselectCell(i, j); //deselect cell
+									else
+										table.selectCell(i, j); //select cell
+								}
+							}
+						}
+					}
+				}
+				else {
+					if (getEmployer() instanceof mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker){
+						mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker mb = (mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker)getEmployer();
+						mb.selectSameColor(column, row, singleCharacter.getValue(), singleTaxon.getValue(), contiguous.getValue(), subtractFromSelection);
+					}
+				}
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the wand to select by text", null, commandName, "selectByText")) {
+			selectByText.setValue(true);
+			selectByColor.setValue(false);
+			eItem.setEnabled(true);
+			gItem.setEnabled(true);
+			lItem.setEnabled(true);
+		}
+		else if (checker.compare(this.getClass(), "Sets the wand to select by color", null, commandName, "selectByColor")) {
+			selectByText.setValue(false);
+			selectByColor.setValue(true);
+			eItem.setEnabled(false);
+			gItem.setEnabled(false);
+			lItem.setEnabled(false);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects through the matrix", "[on = whole matrix; off]", commandName, "toggleWholeMatrix")) {
+			boolean current = wholeMatrix.getValue();
+			if (current && StringUtil.blank(arguments)) //from menu; reselecting; don't change
+				return null;
+			wholeMatrix.toggleValue(parser.getFirstToken(arguments));
+			if (wholeMatrix.getValue()) {
+				singleTaxon.setValue(false);
+				singleCharacter.setValue(false);
+				contiguous.setValue(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects contiguously", "[on = contiguous; off]", commandName, "toggleContiguous")) {
+			boolean current = contiguous.getValue();
+			if (current && StringUtil.blank(arguments)) //from menu; reselecting; don't change
+				return null;
+			contiguous.toggleValue(parser.getFirstToken(arguments));
+			if (contiguous.getValue()) {
+				wholeMatrix.setValue(false);
+				singleTaxon.setValue(false);
+				singleCharacter.setValue(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects only cells of the taxon that was touched", "[on = single taxon; off]", commandName, "toggleSingleTaxon")) {
+			boolean current = singleTaxon.getValue();
+			if (current && StringUtil.blank(arguments)) //from menu; reselecting; don't change
+				return null;
+			singleTaxon.toggleValue(parser.getFirstToken(arguments));
+			if (singleTaxon.getValue()) {
+				wholeMatrix.setValue(false);
+				singleCharacter.setValue(false);
+				contiguous.setValue(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects only cells of the character that was touched", "[on = single character; off]", commandName, "toggleSingleCharacter")) {
+			boolean current = singleCharacter.getValue();
+			if (current && StringUtil.blank(arguments)) //from menu; reselecting; don't change
+				return null;
+			singleCharacter.toggleValue(parser.getFirstToken(arguments));
+			if (singleCharacter.getValue()) {
+				wholeMatrix.setValue(false);
+				singleTaxon.setValue(false);
+				contiguous.setValue(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects cells with value equal to that in cell touched", "[on = selects equal; off]", commandName, "toggleEquals")) {
+			boolean current = equals.getValue();
+			equals.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects cells with value greater than that in cell touched", "[on = selects greater than; off]", commandName, "toggleGT")) {
+			boolean current = greaterthan.getValue();
+			greaterthan.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects cells with value less than that in cell touched", "[on = selects less than; off]", commandName, "toggleLT")) {
+			boolean current = lessthan.getValue();
+			lessthan.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	boolean[][] contigSel;
+	int numContigFound = 0;
+	void selectContiguous(int seedColumn, int seedRow, String text, boolean subtractFromSelection, boolean horizontal, boolean forwards, int level){
+		if (seedColumn<0 || seedRow < 0 || seedColumn >= table.getNumColumns() || seedRow >= table.getNumRows() || contigSel[seedColumn][seedRow])
+			return;
+		level++;
+		boolean done = false;
+		if (horizontal){
+			if (forwards) {
+				int ic;
+				for (ic=seedColumn; ic< table.getNumColumns() && !done; ic++)
+					done = contigSel[ic][seedRow] || !checkCell(ic, seedRow, text, subtractFromSelection);
+
+				int end = ic-1;
+				for (ic=seedColumn; ic< end; ic++){
+					selectContiguous(ic, seedRow+1, text, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(ic, seedRow-1, text, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+			else {
+				int ic;
+				for (ic=seedColumn; ic>=0 && !done; ic--)
+					done = contigSel[ic][seedRow] || !checkCell(ic, seedRow, text, subtractFromSelection);
+
+				int end = ic+1;
+				for (ic=seedColumn; ic>end; ic--){
+					selectContiguous(ic, seedRow+1, text, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(ic, seedRow-1, text, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+		}
+		else {
+			if (forwards) {
+				int it;
+				for (it=seedRow; it< table.getNumRows() && !done; it++)
+					done = contigSel[seedColumn][it] || !checkCell(seedColumn, it, text, subtractFromSelection);
+				int end = it-1;
+				for (it=seedRow; it< end; it++){
+					selectContiguous(seedColumn+1, it, text, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(seedColumn-1, it, text, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+			else {
+				int it;
+				for ( it=seedRow; it>=0 && !done; it--)
+					done = contigSel[seedColumn][it] || !checkCell(seedColumn, it, text, subtractFromSelection);
+				int end = it+1;
+				for ( it=seedRow; it>end; it--){
+					selectContiguous(seedColumn+1, it, text, subtractFromSelection, !horizontal, true, level);
+					selectContiguous(seedColumn-1, it, text, subtractFromSelection, !horizontal, false, level);
+				}
+			}
+		}
+	}
+	boolean checkCell(int ic, int it, String text, boolean subtractFromSelection){
+		if (contigSel[ic][it])
+			return false;
+		contigSel[ic][it] = true;
+		//table.selectCell(ic, it); //select cell
+		if (satisfiesCriteria(text, table.getMatrixText(ic, it))) {
+			numContigFound++;
+			if (numContigFound % 100 == 0)
+				CommandRecord.tick(Integer.toString(numContigFound) + " cells found");
+			if (subtractFromSelection){
+				table.deselectCell(ic, it); //deselect cell
+			}
+			else 
+				table.selectCell(ic, it); //select cell
+			//table.repaintAll();
+			return true;
+		}   
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Cell Wand (data)";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to select cells in a matrix automatically.";
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/Wand/magicWand.gif b/Source/mesquite/charMatrices/Wand/magicWand.gif
new file mode 100644
index 0000000..73843ad
Binary files /dev/null and b/Source/mesquite/charMatrices/Wand/magicWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandChar/32charWand.gif b/Source/mesquite/charMatrices/WandChar/32charWand.gif
new file mode 100644
index 0000000..50be2c4
Binary files /dev/null and b/Source/mesquite/charMatrices/WandChar/32charWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandChar/64charWand.gif b/Source/mesquite/charMatrices/WandChar/64charWand.gif
new file mode 100644
index 0000000..7e5cf19
Binary files /dev/null and b/Source/mesquite/charMatrices/WandChar/64charWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandChar/WandChar.java b/Source/mesquite/charMatrices/WandChar/WandChar.java
new file mode 100644
index 0000000..5a882ed
--- /dev/null
+++ b/Source/mesquite/charMatrices/WandChar/WandChar.java
@@ -0,0 +1,251 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.WandChar; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/*   to do:
+	- deal with Option cursor, Shift cursor
+	- do toggleSimilarWhole  THIS IS BEGUN BUT NOT COMPLETE
+*/
+
+/* ======================================================================== */
+public class WandChar extends DataWindowAssistantI { 
+	TableTool charWandTool;
+	CharacterData data;
+	MesquiteTable table;
+	boolean charactersAreRows = false;
+	MesquiteBoolean equals, greaterthan, lessthan;
+	MesquiteBoolean toggleSameInTaxon, toggleSameWhole, toggleSimilarWhole;
+	boolean defaultEquals = true;
+	boolean defaultGT = false;
+	boolean defaultLT = false;
+	boolean defaultSameInTaxon = true;
+	boolean defaultSameWhole = false;
+	boolean defaultSimilarWhole = false;
+	MesquiteCollator collator;
+	 public String getFunctionIconPath(){
+   		 return getPath() + "charWand.gif";
+   	 }
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			charWandTool = new TableTool(this, "charWand", getPath(), "charWand.gif", 4,4,"Select characters with same", "This tool selects characters according to criteria of being the same, greater than, or less than the value in the cell touched.  The criteria can be set using the menu that appears when you click on the tool button", MesquiteModule.makeCommand("charWandTouch",  this) , null, null);
+			((MesquiteWindow)containerOfModule()).addTool(charWandTool);
+			charWandTool.setPopUpOwner(this);
+			setUseMenubar(false); //menu available by touching oning button
+		}
+		else return false;
+		equals = new MesquiteBoolean(defaultEquals);
+		greaterthan = new MesquiteBoolean(defaultGT);
+		lessthan = new MesquiteBoolean(defaultLT);
+		addCheckMenuItem(null, "Equal", makeCommand("toggleEquals",  this), equals);
+		addCheckMenuItem(null, "Greater than", makeCommand("toggleGT",  this), greaterthan);
+		addCheckMenuItem(null, "Less than", makeCommand("toggleLT",  this), lessthan);
+		addMenuItem("-", null);
+		toggleSameInTaxon = new MesquiteBoolean(defaultSameInTaxon);
+		toggleSameWhole = new MesquiteBoolean(defaultSameWhole);
+		toggleSimilarWhole = new MesquiteBoolean(defaultSimilarWhole);
+		addCheckMenuItem(null, "Same (in Taxon)", makeCommand("toggleSameInTaxon",  this), toggleSameInTaxon);
+		addCheckMenuItem(null, "Same (Whole Character)", makeCommand("toggleSameWhole",  this), toggleSameWhole);
+		//addCheckMenuItem(null, "Similar (Whole Character)", makeCommand("toggleSimilarWhole",  this), toggleSimilarWhole);
+		collator = new MesquiteCollator();
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		//this.charactersAreRows = charactersAreRows;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	Snapshot temp = new Snapshot();
+		if (equals.getValue()!=defaultEquals)
+			temp.addLine("toggleEquals " + equals.toOffOnString());
+		if (greaterthan.getValue()!=defaultGT)
+			temp.addLine("toggleGT " + greaterthan.toOffOnString());
+		if (lessthan.getValue()!=defaultLT)
+			temp.addLine("toggleLT " + lessthan.toOffOnString());
+		if (toggleSameInTaxon.getValue()!=defaultSameInTaxon)
+			temp.addLine("toggleSameInTaxon " + toggleSameInTaxon.toOffOnString());
+		if (toggleSameWhole.getValue()!=defaultSameWhole)
+			temp.addLine("toggleSameWhole " + toggleSameWhole.toOffOnString());
+		if (toggleSimilarWhole.getValue()!=defaultSimilarWhole)
+			temp.addLine("toggleSimilarWhole " + toggleSimilarWhole.toOffOnString());
+  	 	return temp;
+  	 }
+  	 boolean satisfiesCriteria(int standardChar, int comparisonChar, String one, String two){
+		if (toggleSameInTaxon.getValue()) {
+			if (equals.getValue() && one.equals(two))
+				return true;
+			double dOne = MesquiteDouble.fromString(one);
+			double dTwo = MesquiteDouble.fromString(two);
+			if (MesquiteDouble.isCombinable(dOne) && MesquiteDouble.isCombinable(dTwo)) {
+				if (greaterthan.getValue() && (dTwo>dOne))
+					return true;
+				if (lessthan.getValue() && (dTwo<dOne))
+					return true;
+				return false;
+			}
+			int order = collator.compare(one, two);
+			//int order =0;
+			if (greaterthan.getValue() && (order == -1))
+				return true;
+			if (lessthan.getValue() && (order == 1))
+				return true;
+			if (equals.getValue() && (order == 0))
+				return true;
+		}
+		else if (toggleSameWhole.getValue()) {
+			if (!charactersAreRows) {  // characters are column; normal orientation
+				for (int i=0; i<table.getNumRows(); i++){
+					if (!table.getMatrixText(standardChar, i).equals(table.getMatrixText(comparisonChar,i)))
+						return false;
+				}
+			}
+			else {
+				for (int i=0; i<table.getNumColumns(); i++){
+					if (!table.getMatrixText(i, standardChar).equals(table.getMatrixText(i, comparisonChar)))
+						return false;
+				}
+			}
+			return true;
+		}
+		else if (toggleSimilarWhole.getValue()) { //not implemented yet!!!!!!!
+			
+			if (!charactersAreRows) {  // characters are column; normal orientation
+				for (int i=0; i<table.getNumRows(); i++){
+					if (!table.getMatrixText(standardChar, i).equals(table.getMatrixText(comparisonChar,i)))
+						return false;
+				}
+			}
+			else {
+				for (int i=0; i<table.getNumColumns(); i++){
+					if (!table.getMatrixText(i, standardChar).equals(table.getMatrixText(i, comparisonChar)))
+						return false;
+				}
+			}
+			return true;
+		}
+		return false;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(),  "Touches on a cell with the characters wand to select characters similar as defined by the options", "[column touched][row touched]", commandName, "charWandTouch")) {
+	   	 		MesquiteInteger io = new MesquiteInteger(0);
+	   			int column= MesquiteInteger.fromString(arguments, io);
+	   			int row= MesquiteInteger.fromString(arguments, io);
+				if (MesquiteInteger.isNonNegative(column)&& (MesquiteInteger.isNonNegative(row))) {
+	   				boolean commandSelected =  (arguments.indexOf("command")>=0);
+	   				boolean subtractFromSelection = commandSelected && data.getSelected(column);
+		   			if ((arguments.indexOf("shift")<0) && !commandSelected) {
+		   				data.deselectAll();    
+		   				table.deselectAll();
+		   			}
+		   			table.offAllEdits();
+					String text = table.getMatrixText(column, row);
+					if (!charactersAreRows){  //each column is a char; hence go through this row to find which columns to select
+							for (int i=0; i<table.getNumColumns(); i++){  // scoot along this row, see which columns to select
+								if (satisfiesCriteria(column,i,text, table.getMatrixText(i, row))) {
+									if (subtractFromSelection) {
+											data.setSelected(i, false); //deselect whole character
+									}
+									else {
+											data.setSelected(i, true); //select whole character
+									}
+								}
+							}
+					}
+					else {
+							for (int i=0; i<table.getNumRows(); i++){
+								if (satisfiesCriteria(row,i,text, table.getMatrixText(column, i))) {
+									if (subtractFromSelection) {
+											data.setSelected(i, false); //deselect whole character
+									}
+									else {
+											data.setSelected(i, true); //select whole character
+									}
+								}
+							}
+					}
+					data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+						
+				}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters with value equal to that in cell touched", "[on = selects equal; off]", commandName, "toggleEquals")) {
+    	 		boolean current = equals.getValue();
+    	 		equals.toggleValue(parser.getFirstToken(arguments));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters with value greater than that in cell touched", "[on = selects greater than; off]", commandName, "toggleGT")) {
+    	 		boolean current = greaterthan.getValue();
+    	 		greaterthan.toggleValue(parser.getFirstToken(arguments));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters with value less than that in cell touched", "[on = selects less than; off]", commandName, "toggleLT")) {
+    	 		boolean current = lessthan.getValue();
+    	 		lessthan.toggleValue(parser.getFirstToken(arguments));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters based upon values in only the single taxon touched", "[on = selects in taxon; off]", commandName, "toggleSameInTaxon")) {
+    	 		boolean current = toggleSameInTaxon.getValue();
+    	 		toggleSameInTaxon.toggleValue(parser.getFirstToken(arguments));
+    	 		if (toggleSameInTaxon.getValue()) {
+    	 			toggleSameWhole.setValue(false);
+    	 			toggleSimilarWhole.setValue(false);
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters that exactly match the character touched", "[on = selects same as whole character; off]", commandName, "toggleSameWhole")) {
+    	 		boolean current = toggleSameWhole.getValue();
+    	 		toggleSameWhole.toggleValue(parser.getFirstToken(arguments));
+    	 		if (toggleSameWhole.getValue()) {
+    	 			toggleSameInTaxon.setValue(false);
+    	 			toggleSimilarWhole.setValue(false);
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether the wand selects characters that are similar to the character touched", "[on = selects similar to whole character; off]", commandName, "toggleSimilarWhole")) {
+    	 		boolean current = toggleSimilarWhole.getValue();
+    	 		toggleSimilarWhole.toggleValue(parser.getFirstToken(arguments));
+    	 		if (toggleSimilarWhole.getValue()) {
+    	 			toggleSameWhole.setValue(false);
+    	 			toggleSameInTaxon.setValue(false);
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Wand (data)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Provides a magic wand tool with which to select characters automatically.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/charMatrices/WandChar/charWand.gif b/Source/mesquite/charMatrices/WandChar/charWand.gif
new file mode 100644
index 0000000..30e0e51
Binary files /dev/null and b/Source/mesquite/charMatrices/WandChar/charWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandTaxon/32taxaWand.gif b/Source/mesquite/charMatrices/WandTaxon/32taxaWand.gif
new file mode 100644
index 0000000..9675856
Binary files /dev/null and b/Source/mesquite/charMatrices/WandTaxon/32taxaWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandTaxon/64taxaWand.gif b/Source/mesquite/charMatrices/WandTaxon/64taxaWand.gif
new file mode 100644
index 0000000..901d960
Binary files /dev/null and b/Source/mesquite/charMatrices/WandTaxon/64taxaWand.gif differ
diff --git a/Source/mesquite/charMatrices/WandTaxon/WandTaxon.java b/Source/mesquite/charMatrices/WandTaxon/WandTaxon.java
new file mode 100644
index 0000000..e75fd95
--- /dev/null
+++ b/Source/mesquite/charMatrices/WandTaxon/WandTaxon.java
@@ -0,0 +1,209 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.WandTaxon; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+/*   to do:
+	- deal with Option cursor, Shift cursor
+ */
+
+
+/* ======================================================================== */
+public class WandTaxon extends DataWindowAssistantI {
+	TableTool taxaWandTool; 
+	MesquiteTable table;
+	Taxa taxa;
+	MesquiteBoolean equals, greaterthan, lessthan,selectByText, selectByColor;
+	boolean defaultEquals = true;
+	boolean defaultGT = false;
+	boolean defaultLT = false;
+	boolean taxaAreRows = true;
+	MesquiteMenuItemSpec eItem, gItem, lItem;
+	MesquiteCollator collator;
+	public String getFunctionIconPath(){
+		return getPath() + "taxaWand.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (containerOfModule() instanceof MesquiteWindow) {
+			taxaWandTool = new TableTool(this, "taxaWand", getPath() , "taxaWand.gif", 4,4,"Select taxa with same", "This tool selects taxa according to criteria of being the same, greater than, or less than the value in the cell touched.  The criteria can be set using the menu that appears when you click on the tool button", MesquiteModule.makeCommand("taxaWandTouch",  this) , null, null);
+			((MesquiteWindow)containerOfModule()).addTool(taxaWandTool);
+			setUseMenubar(false); //menu available by touching  button
+			taxaWandTool.setPopUpOwner(this);
+			taxaWandTool.setWorksOnRowNames(false);
+		}
+		else return false;
+		equals = new MesquiteBoolean(defaultEquals);
+		greaterthan = new MesquiteBoolean(defaultGT);
+		lessthan = new MesquiteBoolean(defaultLT);
+		selectByText = new MesquiteBoolean(true);
+
+		selectByColor = new MesquiteBoolean(!selectByText.getValue());
+		addCheckMenuItem(null, "Select by Text", makeCommand("selectByText",  this), selectByText);
+		addCheckMenuItem(null, "Select by Color", makeCommand("selectByColor",  this), selectByColor);
+		addMenuItem("-", null);
+		eItem = addCheckMenuItem(null, "Equal", makeCommand("toggleEquals",  this), equals);
+		gItem = addCheckMenuItem(null, "Greater than", makeCommand("toggleGT",  this), greaterthan);
+		lItem = addCheckMenuItem(null, "Less than", makeCommand("toggleLT",  this), lessthan);
+		collator = new MesquiteCollator();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data !=null)
+			this.taxa = data.getTaxa();
+		this.taxaAreRows = true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (equals.getValue()!=defaultEquals)
+			temp.addLine("toggleEquals " + equals.toOffOnString());
+		if (greaterthan.getValue()!=defaultGT)
+			temp.addLine("toggleGT " + greaterthan.toOffOnString());
+		if (lessthan.getValue()!=defaultLT)
+			temp.addLine("toggleLT " + lessthan.toOffOnString());
+		if (!selectByText.getValue())
+			temp.addLine("selectByColor");
+		return temp;
+	}
+	boolean satisfiesCriteria(String one, String two){
+		if (equals.getValue() && one.equals(two))
+			return true;
+		double dOne = MesquiteDouble.fromString(one);
+		double dTwo = MesquiteDouble.fromString(two);
+		if (MesquiteDouble.isCombinable(dOne) && MesquiteDouble.isCombinable(dTwo)) {
+			if (greaterthan.getValue() && (dTwo>dOne))
+				return true;
+			if (lessthan.getValue() && (dTwo<dOne))
+				return true;
+			return false;
+		}
+		int order = collator.compare(one, two);
+		if (greaterthan.getValue() && (order == -1))
+			return true;
+		if (lessthan.getValue() && (order == 1))
+			return true;
+		if (equals.getValue() && (order == 0))
+			return true;
+		return false;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Touches on a cell with the taxon wand to select taxa similar as defined by the options", "[column touched][row touched]", commandName, "taxaWandTouch")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+			if ((selectByColor.getValue() || MesquiteInteger.isNonNegative(column)) && (MesquiteInteger.isNonNegative(row))) {
+				boolean commandSelected =  (arguments.indexOf("command")>=0);
+				boolean subtractFromSelection = commandSelected && taxa.getSelected(row);
+				if ((arguments.indexOf("shift")<0) && !commandSelected)
+					table.deselectAll();
+				table.offAllEdits();
+				if (selectByText.getValue()){
+					String text = table.getMatrixText(column, row);
+					if (!taxaAreRows){  //each row is a taxon; hence go through this column to find which rows to select
+						for (int i=0; i<table.getNumColumns(); i++){
+							if (satisfiesCriteria(text, table.getMatrixText(i, row))) {
+								if (subtractFromSelection) 
+									taxa.setSelected(i, false);
+								else 
+									taxa.setSelected(i, true);
+							}
+						}
+					}
+					else {
+						for (int i=0; i<table.getNumRows(); i++){
+							if (satisfiesCriteria(text, table.getMatrixText(column, i))) {
+								if (subtractFromSelection) {
+									taxa.setSelected(i, false);
+								}
+								else {
+									taxa.setSelected(i, true);
+								}
+							}
+						}
+					}
+				}
+				else {
+					if (getEmployer() instanceof mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker){
+						mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker mb = (mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker)getEmployer();
+						mb.selectSameColorRow(column, row, subtractFromSelection);
+					}
+				}
+
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the wand to select by text", null, commandName, "selectByText")) {
+			selectByText.setValue(true);
+			selectByColor.setValue(false);
+			if (taxaWandTool != null)
+				taxaWandTool.setWorksOnRowNames(false);
+			eItem.setEnabled(true);
+			gItem.setEnabled(true);
+			lItem.setEnabled(true);
+		}
+		else if (checker.compare(this.getClass(), "Sets the wand to select by color", null, commandName, "selectByColor")) {
+			selectByText.setValue(false);
+			selectByColor.setValue(true);
+			if (taxaWandTool != null)
+				taxaWandTool.setWorksOnRowNames(true);
+			eItem.setEnabled(false);
+			gItem.setEnabled(false);
+			lItem.setEnabled(false);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value equal to that in cell touched", "[on = selects equal; off]", commandName, "toggleEquals")) {
+			boolean current = equals.getValue();
+			equals.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value greater than that in cell touched", "[on = selects greater than; off]", commandName, "toggleGT")) {
+			boolean current = greaterthan.getValue();
+			greaterthan.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value less than that in cell touched", "[on = selects less than; off]", commandName, "toggleLT")) {
+			boolean current = lessthan.getValue();
+			lessthan.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Wand (data)";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to select taxa automatically.";
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/charMatrices/WandTaxon/taxaWand.gif b/Source/mesquite/charMatrices/WandTaxon/taxaWand.gif
new file mode 100644
index 0000000..114d806
Binary files /dev/null and b/Source/mesquite/charMatrices/WandTaxon/taxaWand.gif differ
diff --git a/Source/mesquite/charMatrices/aCharMatricesIntro/aCharMatricesIntro.java b/Source/mesquite/charMatrices/aCharMatricesIntro/aCharMatricesIntro.java
new file mode 100644
index 0000000..723c2d3
--- /dev/null
+++ b/Source/mesquite/charMatrices/aCharMatricesIntro/aCharMatricesIntro.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.aCharMatricesIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aCharMatricesIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aCharMatricesIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic management and utilities for character data matrices.";
+   	 }
+   
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+   	    /*.................................................................................................................*/
+    	    public boolean getHideable() {
+    			return false;
+    	   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Matrices Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Character Matrices Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/explanation.txt b/Source/mesquite/charMatrices/explanation.txt
new file mode 100644
index 0000000..245caaa
--- /dev/null
+++ b/Source/mesquite/charMatrices/explanation.txt
@@ -0,0 +1,2 @@
+Character Matrix Editing Package
+One of the core Mesquite packages.  Provides the spreadsheet editors for character matrices, including the standard editing tools.
diff --git a/Source/mesquite/charMatrices/lib/DataWindow.java b/Source/mesquite/charMatrices/lib/DataWindow.java
new file mode 100644
index 0000000..2371cc0
--- /dev/null
+++ b/Source/mesquite/charMatrices/lib/DataWindow.java
@@ -0,0 +1,91 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.lib; 
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import java.awt.datatransfer.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.charMatrices.lib.*;
+import mesquite.charMatrices.BasicDataWindowMaker.*;
+
+	
+/* ======================================================================== */
+public abstract class DataWindow extends TableWindow {
+	MesquiteTable mesquiteTable;
+	CharacterData data;
+	BasicDataWindowMaker ownerModule;
+
+	public DataWindow () {
+	}
+	public DataWindow (BasicDataWindowMaker ownerModule, CharacterData data) {
+		super(ownerModule, true); //INFOBAR
+		ownerModule.setModuleWindow(this);
+		this.data = data;
+		this.ownerModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+//    	 public MesquiteTable getTable() {
+//		return mesquiteTable; 
+//   	 }
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		String t;
+		if (data != null && data.hasTitle()) {
+			t = "Character Matrix \"" + data.getName() + "\"";
+		}
+		else {
+			t = "Character Matrix";
+		}
+		setTitle(t);
+	}
+	/*.................................................................................................................*/
+	public int numDataColumnNamesAssistants(){
+		int num=0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) { 
+			MesquiteModule e=(MesquiteModule)ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataColumnNamesAssistant) {
+				num++;
+			}
+		}
+		return num;
+	}
+	/*.................................................................................................................*/
+	public DataColumnNamesAssistant getDataColumnNamesAssistant(int num){
+		int count = 0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) { 
+			MesquiteModule e=(MesquiteModule)ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof DataColumnNamesAssistant) {
+				if (count>=num)
+					return (DataColumnNamesAssistant)e;
+				count++;
+			}
+		}
+		return null;
+	}
+   	 
+}
+
+
+
diff --git a/Source/mesquite/charMatrices/lib/MatrixInfoExtraPanel.java b/Source/mesquite/charMatrices/lib/MatrixInfoExtraPanel.java
new file mode 100644
index 0000000..73a430e
--- /dev/null
+++ b/Source/mesquite/charMatrices/lib/MatrixInfoExtraPanel.java
@@ -0,0 +1,62 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charMatrices.lib;
+
+
+import mesquite.lib.ClosablePanel;
+import mesquite.lib.ClosablePanelContainer;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.MesquiteTable;
+
+
+public class MatrixInfoExtraPanel extends ClosablePanel {
+	protected CharacterData data;
+	protected MesquiteTable table;
+	protected int ic = -8;
+	protected int it = -8;
+	public MatrixInfoExtraPanel(ClosablePanelContainer container, String title){
+		super(container, title);
+		setShowTriangle(true);
+	}
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table){
+		this.data = data;
+		this.table = table;
+	}
+	public void setCell(int ic, int it){
+		this.ic = ic;
+		this.it = it;
+	}
+	public void cellEnter(int ic, int it){
+		try{
+			setCell(ic, it);
+		}
+		catch (Exception e){
+		}
+	}
+	public void cellExit(int ic, int it){
+		try{
+			setCell(-1, -1);
+		}
+		catch (Exception e){
+		}
+	}
+	public void cellTouch(int ic, int it){
+		try{
+			setCell(ic, it);
+		}
+		catch (Exception e){
+		}
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/lib/RandomMatrixModifier.java b/Source/mesquite/charMatrices/lib/RandomMatrixModifier.java
new file mode 100644
index 0000000..4db2ecf
--- /dev/null
+++ b/Source/mesquite/charMatrices/lib/RandomMatrixModifier.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class RandomMatrixModifier extends MesquiteModule {
+   	 public Class getDutyClass() {
+   	 	return RandomMatrixModifier.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Random Matrix Modifier";
+   	 }
+   	 
+   	 public abstract void modifyMatrix(MCharactersDistribution matrix, MAdjustableDistribution modified, RandomBetween rng);
+   	 
+}
+
diff --git a/Source/mesquite/charMatrices/lib/SourceModRespectiveMatrix.java b/Source/mesquite/charMatrices/lib/SourceModRespectiveMatrix.java
new file mode 100644
index 0000000..7d60546
--- /dev/null
+++ b/Source/mesquite/charMatrices/lib/SourceModRespectiveMatrix.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class SourceModRespectiveMatrix extends CharMatrixSource {
+	MatrixSourceCoordObed dataTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null) 
+			dataTask = (MatrixSourceCoordObed)hireCompatibleEmployee( MatrixSourceCoordObed.class, condition, "Source of matrices to modify");
+		else 
+			dataTask = (MatrixSourceCoordObed)hireEmployee( MatrixSourceCoordObed.class, "Source of matrices to modify");
+		if (dataTask == null) {
+			return sorry(getName() + " can't be started because not source of matrices was obtained");
+		}
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getCharacterSource ", dataTask);
+	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Returns the source of matrices on which to do ordinations", null, commandName, "setCharacterSource")) { //TEMPORARY
+    	 		if (dataTask != null)
+    	 			return dataTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource")) {
+    	 		return dataTask;
+    	 	}
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		dataTask.initialize(taxa);
+   	}
+  	 
+	/*.................................................................................................................*/
+	protected MCharactersDistribution getBasisMatrix(Taxa taxa, int i){
+   		return dataTask.getMatrix(taxa, i);
+	}
+	/*.................................................................................................................*/
+    	public  int getNumberOfMatrices(Taxa taxa){
+    		return dataTask.getNumberOfMatrices(taxa);
+    	}
+	/*.................................................................................................................*/
+	protected MatrixSourceCoordObed getBasisMatrixSource(){
+   		return dataTask;
+	}
+}
+
diff --git a/Source/mesquite/charMatrices/lib/SourceModifiedMatrix.java b/Source/mesquite/charMatrices/lib/SourceModifiedMatrix.java
new file mode 100644
index 0000000..900b465
--- /dev/null
+++ b/Source/mesquite/charMatrices/lib/SourceModifiedMatrix.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charMatrices.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class SourceModifiedMatrix extends CharMatrixSource {
+	protected CharMatrixOneSource dataTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null) 
+			dataTask = (CharMatrixOneSource)hireCompatibleEmployee( CharMatrixOneSource.class, condition, "Source of matrix to modify");
+		else 
+			dataTask = (CharMatrixOneSource)hireEmployee( CharMatrixOneSource.class, "Source of matrix to modify");
+		if (dataTask == null) {
+			return sorry(getName() + " can't be started because not source of matrices was obtained");
+		}
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getCharacterSource ", dataTask);
+	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Returns the source of matrices to modify", null, commandName, "setCharacterSource")) { //TEMPORARY
+    	 		if (dataTask != null)
+    	 			return dataTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource")) {
+    	 		return dataTask;
+    	 	}
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		dataTask.initialize(taxa);
+   	}
+  	 
+	/*.................................................................................................................*/
+	protected MCharactersDistribution getBasisMatrix(Taxa taxa){
+   		return dataTask.getCurrentMatrix(taxa);
+	}
+	/*.................................................................................................................*/
+	protected CharMatrixOneSource getBasisMatrixSource(){
+   		return dataTask;
+	}
+}
+
diff --git a/Source/mesquite/charts/CharacterValuesChart/CharacterValuesChart.java b/Source/mesquite/charts/CharacterValuesChart/CharacterValuesChart.java
new file mode 100644
index 0000000..39430ea
--- /dev/null
+++ b/Source/mesquite/charts/CharacterValuesChart/CharacterValuesChart.java
@@ -0,0 +1,242 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.CharacterValuesChart;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class CharacterValuesChart.  ===*/
+
+public class CharacterValuesChart extends FileAssistantCH  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Bar & Line Chart for Characters";
+	}
+	public String getExplanation() {
+		return "Shows chart displaying values (such as likelihoods, parameter values, parsimony counts, etc.) for a series of characters." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharacter.class, getName() + " needs a method to calculate the values for the characters.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Characters item under Bar & Line Charts in the Analysis menu)");
+		e.setPriority(2);
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters.",
+		"You can select the characters to show either when the chart starts up, or later using the Source of Characters submenu of the Chart menu.  (You may request the chart itself by selecting the Characters item under Bar & Line Charts in the Analysis menu)");
+		e2.setPriority(2);
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+
+	}
+	/*.................................................................................................................*/
+	NumberForCharacter numberTask;
+	CharSourceCoordObed characterSourceTask;
+	ItemsCharter chartWindowTask;
+	private CharacterDistribution charStates;
+	private Taxa oldTaxa, taxa;
+	private CharacterData data = null;
+	ChartWindow cWindow;
+	MesquiteCommand ntC;
+	static int numMade =0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//is there a hint as to taxa
+		String whichTaxa = MesquiteThread.retrieveAndDeleteHint(this);
+		long wB = MesquiteLong.fromString(whichTaxa);
+		if (MesquiteLong.isCombinable(wB)){
+			taxa = getProject().getTaxaByID(wB);
+		}
+
+		if (taxa == null)
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of values for characters?");
+		if (taxa ==null)
+			return sorry(getName() + " couldn't start because no block of taxa available.");
+		taxa.addListener(this);
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no chart window module was obtained");
+
+		//character source %%%%%%%%
+		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters (for Character Values chart)");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		CharacterDistribution item = (CharacterDistribution)characterSourceTask.getItem(taxa, 0);
+		Class stateClass = null;
+		if (item != null)
+			stateClass = item.getStateClass();
+		//values etc. %%%%%%%%
+		numberTask=(NumberForCharacter)hireCompatibleEmployee(NumberForCharacter.class, stateClass, "Value to calculate for characters (for Character Values chart)");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module was obtained.");
+
+
+		ntC = makeCommand("setCalculator",  this);
+		numberTask.setHiringCommand(ntC);
+
+
+		makeMenu("Chart");
+		addSubmenu(null, "Values", ntC, NumberForCharacter.class);//TODO: checkmark
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource( characterSourceTask);
+		cWindow.setChartTitle("Characters Chart " + (++numMade));
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==chartWindowTask || m == characterSourceTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) { //obed should only supply window!
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		temp.addLine("setCalculator ", numberTask);
+		temp.addLine("getCharacterSource ", characterSourceTask);
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block reference, number, or name]", commandName, "setTaxa")){
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				return taxa;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Returns chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to be visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+
+		}
+		else if (checker.compare(this.getClass(), "Requests the calculations for the charts be redone", null, commandName, "doCounts")) {
+			if (cWindow!=null){
+				chartWindowTask.setTaxa(taxa);
+				chartWindowTask.setNumberTask(numberTask);
+				chartWindowTask.setItemsSource( characterSourceTask);
+				chartWindowTask.doCounts();
+			}
+		}
+		/*	else if (checker.compare(this.getClass(), "Highlights a character set", null, commandName, "highlightCharSet")) {
+			if (cWindow!=null){
+				chartWindowTask.setTaxa(taxa);
+				chartWindowTask.setNumberTask(numberTask);
+				chartWindowTask.setItemsSource( characterSourceTask);
+    	 			chartWindowTask.doCounts();
+    	 		}
+    	 	}
+		 */
+		else if (checker.compare(this.getClass(), "Returns the source of characters for the characters chart", "[name of module]", commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of characters for the characters chart", "[name of module]", commandName, "setCharacterSource")) { //Temporary
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate numbers for the characters", "[name of module]", commandName, "setCalculator")) {
+			NumberForCharacter temp = (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Value to calculate for characters", numberTask);
+			if (temp !=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				if (cWindow!=null) {
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource( characterSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null)
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == characterSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+		chartWindowTask.doCounts();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Characters";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/charts/CharsScattergram/CharsScattergram.java b/Source/mesquite/charts/CharsScattergram/CharsScattergram.java
new file mode 100644
index 0000000..eed7a67
--- /dev/null
+++ b/Source/mesquite/charts/CharsScattergram/CharsScattergram.java
@@ -0,0 +1,374 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.CharsScattergram;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class CharsScattergram.  ===*/
+
+public class CharsScattergram extends FileAssistantCS  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Characters Scattergram";
+	}
+	public String getExplanation() {
+		return "Makes a scatterplot displaying two values (such as likelihoods, parsimony scores, etc.) for a series of characters.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharacter.class, getName() + " needs methods to calculate the two values for the characters.",
+		"You can select this either when the chart starts up, or using the Values submenus of the Chart menu.  (You may request the chart itself by selecting the Characters item under New Scattergram in the Analysis menu)");
+		e.setPriority(2);
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters.",
+		"You can select the characters to show either when the chart starts up, or using the Source of Characters submenu of the Chart menu.  (You may request the chart itself by selecting the Characters item under New Scattergram in the Analysis menu)");
+		e2.setPriority(2);
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsBiplotter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForCharacter numberTaskX, numberTaskY, numberTaskZ;
+	private CharSourceCoordObed charSourceTask;
+	ItemsBiplotter chartWindowTask;
+	public Taxa taxa;
+	boolean separateAxes=false;
+	public MesquiteBoolean showColors = new MesquiteBoolean(false);
+	MesquiteString numberTaskXName, numberTaskYName, numberTaskZName;
+	MesquiteString itemSourceName;
+	MesquiteMenuItemSpec setColorsItem;
+	ChartWindow cWindow;
+	MesquiteCommand  ntxC, ntyC, ntC;
+	MesquiteMenuSpec colorsMenu;
+	static int numMade = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		makeMenu("Scattergram");
+		colorsMenu = addAuxiliaryMenu("Colors");
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because there are no blocks of taxa available");
+		chartWindowTask = (ItemsBiplotter)hireEmployee(ItemsBiplotter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+
+		//Source of characters %%%%%%%%
+		charSourceTask= (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters (Characters scattergram)");
+		if (charSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		itemSourceName = new MesquiteString();
+		itemSourceName.setValue(charSourceTask.getName());
+
+
+		//values etc.  %%%%%%%%
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow(cWindow);
+		cWindow.setChartTitle("Characters Scattergram " + (++numMade));
+		cWindow.resetTitle();
+		taxa = getProject().getTaxa(0); // as default;
+		numberTaskXName = new MesquiteString();
+		numberTaskYName = new MesquiteString();
+		numberTaskZName = new MesquiteString();
+		ntxC =makeCommand("setValuesX",  this);
+		ntyC =makeCommand("setValuesY",  this);
+		ntC =makeCommand("setValues",  this);
+		/* ---------------------------*/
+		if (!MesquiteThread.isScripting()){
+			if (getProject().getNumberTaxas()>1 && !MesquiteThread.isScripting()) {
+				Taxa t = (Taxa) ListDialog.queryList(containerOfModule(), "Taxa", "Choose set of taxa",MesquiteString.helpString,  getProject().getTaxas(), 0);
+				if (t!=null) {
+					taxa.removeListener(this);
+					taxa = t;
+					taxa.addListener(this);
+				}
+			}
+			String expl = "(For instance, the X and Y axes might show the same calculations but for different trees, or they may show two entirely different calculations.)";
+			separateAxes = (numModulesAvailable(NumberForCharacterIncr.class)==0) || !AlertDialog.query(containerOfModule(), "Axes", "Choose same or different calculations for the two axes? " + expl, "Same", "Different");
+			if (!separateAxes){
+				numberTaskX = (NumberForCharacter)hireEmployee(NumberForCharacterIncr.class, "Values for axes");
+				if (numberTaskX == null)
+					return sorry(getName() + " couldn't start because no calculator module was obtained.");
+				if (numModulesAvailable(NumberForCharacterIncr.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values for axes", ntC, NumberForCharacterIncr.class);
+					mss.setSelected(numberTaskXName);
+				}
+				numberTaskXName.setValue(numberTaskX.getName());
+				numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+			}
+			else {
+				numberTaskX = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "Values for X axis");
+				if (numberTaskX == null)
+					return sorry(getName() + " couldn't start because no calculator module was obtained for the X axis.");
+				numberTaskX.setHiringCommand(ntxC);
+				numberTaskY = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "Values for Y axis");
+				if (numberTaskY == null)
+					return sorry(getName() + " couldn't start because no calculator module was obtained for the Y axis.");
+				numberTaskY.setHiringCommand(ntyC);
+				if (numModulesAvailable(NumberForCharacter.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values on X", ntxC, NumberForCharacter.class);
+					mss.setSelected(numberTaskXName);
+					mss = addSubmenu(null, "Values on Y", ntyC, NumberForCharacter.class);
+					mss.setSelected(numberTaskYName);
+				}
+				numberTaskXName.setValue(numberTaskX.getName());
+				numberTaskYName.setValue(numberTaskY.getName());
+			}
+
+			sendParametersToCharter();
+			if (!MesquiteThread.isScripting()){
+				chartWindowTask.doCounts();
+				cWindow.setChartVisible();
+				cWindow.setVisible(true);
+			}
+		}
+		else 
+			taxa.addListener(this);
+		addCheckMenuItem(colorsMenu, "Color by third value", MesquiteModule.makeCommand("showColors",  this), showColors);
+		resetMenus();
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		/* ---------------------------*/
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	void resetMenus(){
+		if (showColors.getValue()){
+			if (setColorsItem == null) {
+				setColorsItem = addSubmenu(colorsMenu, "Values for colors", MesquiteModule.makeCommand("setColorValues",  this), NumberForCharacter.class);
+				((MesquiteSubmenuSpec)setColorsItem).setSelected(numberTaskZName);
+			}
+
+		}
+		else {
+			deleteMenuItem(setColorsItem);
+			setColorsItem = null;
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m == chartWindowTask || m== charSourceTask)
+			iQuit();
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	void sendParametersToCharter(){
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTaskX(numberTaskX);
+		chartWindowTask.setNumberTaskY(numberTaskY);
+		chartWindowTask.setNumberTaskZ(numberTaskZ); ///
+		chartWindowTask.setItemsSource(charSourceTask);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", charSourceTask); 
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		if (separateAxes){
+			temp.addLine("axesDifferent"); 
+			temp.addLine("setValuesX ", numberTaskX); 
+			temp.addLine("setValuesY ", numberTaskY); 
+		}
+		else {
+			temp.addLine("axesSame"); 
+			temp.addLine("setValues ", numberTaskX); 
+		}
+		if (showColors.getValue() && numberTaskZ!=null) {
+			temp.addLine("showColors " + showColors.toOffOnString());
+			temp.addLine("setColorValues ", numberTaskZ);
+		}
+		temp.addLine("getCharter", chartWindowTask);
+		temp.addLine("setChartVisible");
+		temp.addLine("doCounts");
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the block of taxa", "[block reference, number, or name]", commandName, "setTaxa")) {
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				return taxa;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets chart to use different calculators for x and y axes", null, commandName, "axesDifferent")){
+			separateAxes=true;
+			if (numModulesAvailable(NumberForCharacter.class)>1) {
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values on X", ntxC, NumberForCharacter.class);
+				mss.setSelected(numberTaskXName);
+				mss = addSubmenu(null, "Values on Y", ntyC, NumberForCharacter.class);
+				mss.setSelected(numberTaskYName);
+			}
+			//todo: this should shut off values-same menu items
+		}
+		else if (checker.compare(this.getClass(), "Sets chart to use same calculators for x and y axes", null, commandName, "axesSame")){
+			separateAxes=false;
+			if (numModulesAvailable(NumberForCharacterIncr.class)>1) {
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values for axes", ntC, NumberForCharacterIncr.class);
+				mss.setSelected(numberTaskXName);
+			}
+			//todo: this should shut off values-different menu items
+		}
+		else if (checker.compare(this.getClass(), "Colors the markers by a third number", "[on or off]", commandName, "showColors")) {
+			boolean wasShow = showColors.getValue();
+			showColors.toggleValue(parser.getFirstToken(arguments));
+			if (showColors.getValue() && !wasShow){
+				if (!MesquiteThread.isScripting()){
+					NumberForCharacter temp = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "Values by which to color spots in scattergram");
+					if (temp!=null) {
+						numberTaskZ = temp;
+						numberTaskZName.setValue(numberTaskZ.getName());
+						numberTaskZ.setMenuToUse(colorsMenu);
+						if (cWindow!=null){
+							sendParametersToCharter();
+							if (!MesquiteThread.isScripting())
+								chartWindowTask.doCounts();
+						}
+					}
+				}
+				resetMenus();
+				resetContainingMenuBar();
+				return numberTaskZ;
+			}
+			else if (!showColors.getValue()  && wasShow) {
+				if (numberTaskZ!=null)
+					fireEmployee(numberTaskZ);
+				numberTaskZ = null;
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+			}
+			resetMenus();
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating numbers for characters used for the colors of markers", "[name of module]", commandName, "setColorValues")) {
+			NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Values by which to color spots in scattergram", numberTaskZ);
+			if (temp!=null) {
+				numberTaskZ = temp;
+				numberTaskZName.setValue(numberTaskZ.getName());
+				numberTaskZ.setMenuToUse(colorsMenu);
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskZ;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating numbers for characters for the axes", "[name of module]", commandName, "setValues")) {
+			NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacterIncr.class, arguments, "Values for axes", numberTaskX);
+			if (temp!=null) {
+				numberTaskX = temp;
+				numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+				numberTaskXName.setValue(numberTaskX.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskX;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating numbers for characters for the X axis", "[name of module]", commandName, "setValuesX")) {
+			NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Values for X axis", numberTaskX);
+			if (temp!=null) {
+				numberTaskX = temp;
+				numberTaskX.setHiringCommand(ntxC);
+				numberTaskXName.setValue(numberTaskX.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskX;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating numbers for characters for the Y axis", "[name of module]", commandName, "setValuesY")) {
+			NumberForCharacter temp =  (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Values for Y axis", numberTaskY);
+			if (temp!=null) {
+				numberTaskY = temp;
+				numberTaskY.setHiringCommand(ntyC);
+				numberTaskYName.setValue(numberTaskY.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskY;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Recalculate values for the chart", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+		}
+		else if (checker.compare(this.getClass(), "Returns the module serving to supply characters", "[name of module]", commandName, "getCharacterSource")) {
+			return charSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module serving to supply characters", "[name of module]", commandName, "setCharacterSource")) { //temporary, for data files using old system without coordinators
+			return charSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		chartWindowTask.doCounts();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Characters";
+	}
+
+}
+
+
diff --git a/Source/mesquite/charts/Histogram/Histogram.java b/Source/mesquite/charts/Histogram/Histogram.java
new file mode 100644
index 0000000..2b2abac
--- /dev/null
+++ b/Source/mesquite/charts/Histogram/Histogram.java
@@ -0,0 +1,2518 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.Histogram;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/*TODO:
+ * 	- fix menu checking of Cumulative submenu
+ * - check code for cumulative, with examples
+ * - averageItem enabling extension fully to cumulative
+ */
+
+/* ======================================================================== */
+/* A module drawing bar charts.  The chart represents a value for each of a series of items (trees, characters, etc.).   There are two
+orientations: (1) values (y) by items (x) which shows the items in sequence along the x axis, and the value for each on the y and (2)
+number of items by values which shows the possible values on the x axis, and the frequency of occurence of the values on the y axis.
+The x axis can have a single bar for each item (native mode = no grouping) or can have each bar summarize a series of items (grouping).  When
+items are thus "grouped" or "clumped" on the x axis, the clumping may be done by number of intervals or by interval width.  
+
+The labels "x" and "y" could refer either to the horizontal and vertical pixels of the chart's field, or to the values displayed in the chart (e.g.
+treelength of 100, item number 10, etc.). To limit confusion xPixel and yPixel are used in some cases when the variables refer to the pixel values.*/
+
+public class Histogram extends DrawChart {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Bar & Line Chart";
+	}
+	public String getExplanation() {
+		return "Helps make bar & line charts." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(HistogramAssistantA.class, "Bar & Line Charts can optionally display extra information (such as means, percentiles).",
+		"You can request such extra information under the Analysis submenu of the Chart menu of a Bar & Line Chart.");
+	}
+	/*.................................................................................................................*/
+	boolean suspend = false;
+	Vector charters;
+	int oldIntervals = 20;
+	double oldIntervalSize =1.0;
+	double oldMovingWindowWidth = 5;
+	double oldMovingWindowIncrement = 1.0;
+	MesquiteMenuItemSpec averageItem, percentItem;
+	MesquiteSubmenuSpec  cumulativeSubmenu;
+	MesquiteMenuItemSpec barChartItem;
+	MesquiteBoolean showAverage; //for clumped items, show average or total?
+	int cumulativeMode;
+	MesquiteBoolean showAsBarChart;
+	MesquiteBoolean showRaw;  // in text view, show clumped data or raw data?
+	int mode = HistogramCharter.AUTO;  //native mode, or clumped, or let the module choose automatically?
+	int useMode;
+	MesquiteBoolean sizeToFit = new MesquiteBoolean(true);
+	MesquiteCommand sizeDrawingCommand;
+	MesquiteMenuItemSpec sizeItem;
+	MesquiteString modeName;
+	MesquiteString cumulativeModeName;
+	int totalFieldWidth= MesquiteInteger.unassigned;
+	int totalFieldHeight= MesquiteInteger.unassigned;
+	MesquiteBoolean showPercent = new MesquiteBoolean(false);
+	boolean noSum = false;
+
+	Vector holding;
+	boolean showMenus = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charters = new Vector();
+		holding = new Vector();
+		showAverage = new MesquiteBoolean(true);
+		cumulativeMode = HistogramCharter.NO_CUMULATIVE;
+		showRaw = new MesquiteBoolean(false);
+		showAsBarChart = new MesquiteBoolean(true);
+		if (condition instanceof MesquiteBoolean[]){
+			MesquiteBoolean[] specs = (MesquiteBoolean[])condition;
+			for (int i=0; i<specs.length; i++){
+				if ("ShowMenus".equalsIgnoreCase(specs[i].getName()))
+					showMenus = specs[i].getValue();
+				else if ("showAsBarChart".equalsIgnoreCase(specs[i].getName()))
+					showAsBarChart.setValue(specs[i].getValue());
+				else if ("showAsCumulative".equalsIgnoreCase(specs[i].getName())){
+					if (specs[i].getValue())
+						cumulativeMode = HistogramCharter.CUMULATIVE;
+				}
+				else if ("setNativeMode".equalsIgnoreCase(specs[i].getName())){
+					if (specs[i].getValue()){
+						mode = HistogramCharter.NATIVE;
+					}
+				}
+				else if ("setNoSum".equalsIgnoreCase(specs[i].getName())){
+					if (specs[i].getValue()){
+						noSum = true;
+					}
+				}
+			}
+		}
+
+		modeName = new MesquiteString(getModeName(mode));
+		cumulativeModeName = new MesquiteString(getCumulativeModeName(cumulativeMode));
+		if (showMenus){
+			MesquiteSubmenuSpec groupingSubmenu = addSubmenu(null, "Grouping on X");
+			addItemToSubmenu(null, groupingSubmenu, getModeName(HistogramCharter.AUTO), makeCommand("setAutoMode", this));
+			addItemToSubmenu(null, groupingSubmenu, getModeName(HistogramCharter.NATIVE), makeCommand("setNativeMode", this));
+			addItemToSubmenu(null, groupingSubmenu, getModeName(HistogramCharter.NUM_INTERVALS), makeCommand("setNumberIntervals", this));
+			addItemToSubmenu(null, groupingSubmenu, getModeName(HistogramCharter.WIDTH_INTERVALS), makeCommand("setIntervalSize", this));
+			addItemToSubmenu(null, groupingSubmenu, getModeName(HistogramCharter.MOVING_WINDOW), makeCommand("setMovingWindowSize", this));
+			groupingSubmenu.setSelected(modeName);
+			/*
+		REMOVED as not working well, especially axes labels and printing
+		addCheckMenuItem(null, "Size To Window", MesquiteModule.makeCommand("toggleSizeToFit",  this), sizeToFit);
+		sizeDrawingCommand = MesquiteModule.makeCommand("sizeDrawing",  this);
+		if (!sizeToFit.getValue())
+			sizeItem = addMenuItem("Drawing Size...", sizeDrawingCommand);
+			 */
+			MesquiteSubmenuSpec analysis = addSubmenu(null, "Auxiliary Analysis", makeCommand("newAssistant", this), HistogramAssistantA.class);
+			MesquiteSubmenuSpec mCloseAsst = addSubmenu(null, "Close Auxiliary Analysis");
+			addMenuItem("-", null);
+			mCloseAsst.setList(getEmployeeVector());
+			mCloseAsst.setListableFilter(HistogramAssistantA.class);
+			mCloseAsst.setCommand(makeCommand("closeAssistant",  this));
+			averageItem = addCheckMenuItem(null, "Show Average for Group", MesquiteModule.makeCommand("showAverageToggle",  this), showAverage);
+			percentItem = addCheckMenuItem(null, "Show Percentage", MesquiteModule.makeCommand("showPercentToggle",  this), showPercent);
+			cumulativeSubmenu = addSubmenu(null, "Cumulative");
+			addItemToSubmenu(null, cumulativeSubmenu, getCumulativeModeName(HistogramCharter.NO_CUMULATIVE), makeCommand("setNoCumulative", this));
+			addItemToSubmenu(null, cumulativeSubmenu, getCumulativeModeName(HistogramCharter.CUMULATIVE), makeCommand("setCumulative", this));
+			addItemToSubmenu(null, cumulativeSubmenu, getCumulativeModeName(HistogramCharter.CUMULATIVE_AVERAGE), makeCommand("setCumulativeAverage", this));
+			addItemToSubmenu(null, cumulativeSubmenu, getCumulativeModeName(HistogramCharter.CUMULATIVE_DOWN), makeCommand("setCumulativeDown", this));
+			addItemToSubmenu(null, cumulativeSubmenu, getCumulativeModeName(HistogramCharter.CUMULATIVE_AVERAGE_DOWN), makeCommand("setCumulativeAverageDown", this));
+			cumulativeSubmenu.setSelected(cumulativeModeName);
+			//			cumulativeItem = addCheckMenuItem(null, "Show Cumulative", MesquiteModule.makeCommand("showCumulativeToggle",  this), showCumulative);
+			barChartItem = addCheckMenuItem(null, "Show as Bar Chart", MesquiteModule.makeCommand("showAsBarChartToggle",  this), showAsBarChart);
+			addCheckMenuItem(null, "Show Individual Points in Text View", MesquiteModule.makeCommand("showRawToggle",  this), showRaw);
+			addMenuItem("-", null);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void addAssistantToCharter(ChartAssistant tda, HistogramCharter tCO){
+
+		if (tCO.chart!=null){
+			ChartExtra tce = tda.createExtra(tCO.chart); //HOW TO REMOVE IF QUIT???
+			tCO.chart.addExtra(tce);
+			tce.doCalculations();
+			tCO.chart.getField().repaint();
+			tCO.chart.repaint();
+		}
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void addAssistant(ChartAssistant tda) {
+		Enumeration e = charters.elements();
+		if (charters.size()==0) {
+			holding.addElement(tda);
+		}
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof HistogramCharter) {
+				HistogramCharter tCO = (HistogramCharter)obj;
+				addAssistantToCharter(tda, tCO);
+			}
+		}
+		if (!MesquiteThread.isScripting())
+			parametersChanged();
+	}
+	/*.................................................................................................................*/
+	public String getCumulativeModeName(int m){
+		if (m == HistogramCharter.NO_CUMULATIVE)
+			return "Off";
+		else if (m == HistogramCharter.CUMULATIVE)
+			return "Simple Cumulative";
+		else if (m == HistogramCharter.CUMULATIVE_AVERAGE)
+			return "Average Cumulative";
+		else if (m == HistogramCharter.CUMULATIVE_DOWN)
+			return "Reverse Simple Cumulative";
+		else if (m == HistogramCharter.CUMULATIVE_AVERAGE_DOWN)
+			return "Reverse Average Cumulative";
+		else return "";
+	}
+	/*.................................................................................................................*/
+	public String getModeName(int m){
+		if (m == HistogramCharter.AUTO)
+			return "Automatic";
+		else if (m == HistogramCharter.NATIVE)
+			return "No Grouping";
+		else if (m == HistogramCharter.NUM_INTERVALS)
+			return "Fixed number of groups...";
+		else if (m == HistogramCharter.WIDTH_INTERVALS)
+			return "Fixed group width...";
+		else if (m == HistogramCharter.MOVING_WINDOW)
+			return "Moving window...";
+		else return "";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend");
+		temp.addLine("showAverageToggle " + showAverage.toOffOnString()); 
+		temp.addLine("showPercentToggle " + showPercent.toOffOnString()); 
+		temp.addLine("setCumulativeMode " + cumulativeMode); 
+		temp.addLine("showAsBarChartToggle " + showAsBarChart.toOffOnString()); 
+		temp.addLine("showRawToggle " + showRaw.toOffOnString()); 
+		temp.addLine("setNumberIntervals " + oldIntervals);  
+		temp.addLine("setIntervalSize " + oldIntervalSize); 
+		temp.addLine("setMovingWindowSize " + oldMovingWindowWidth + " " + oldMovingWindowIncrement); 
+		temp.addLine("setMode " + mode);
+		/*
+		temp.addLine("toggleSizeToFit " + sizeToFit.toOffOnString());
+		if (!sizeToFit.getValue() && (MesquiteInteger.isCombinable(totalFieldWidth)||MesquiteInteger.isCombinable(totalFieldHeight))) {
+			temp.addLine("sizeDrawing " + MesquiteInteger.toString(totalFieldWidth) + " " + MesquiteInteger.toString(totalFieldHeight));
+		}
+		 */
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof HistogramAssistantA) {
+				temp.addLine("\tnewAssistant " , ((MesquiteModule)e));
+			}
+		}
+		temp.addLine("resume");
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	void switchCumulativeMode(int m, boolean suspend){
+		cumulativeMode = m;
+		Enumeration e = charters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof HistogramCharter) {
+				HistogramCharter tCO = (HistogramCharter)obj;
+				tCO.setCumulativeMode(cumulativeMode, suspend);
+			}
+		}
+		cumulativeModeName.setValue(getCumulativeModeName(cumulativeMode));
+		//cumulativeSubmenu.setSelected(cumulativeModeName);
+		//if (!MesquiteThread.isScripting())
+		if (!suspend)
+			parametersChanged();
+		resetContainingMenuBar();
+	}
+
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		boolean resetMode = false;
+		if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the mode of the chart", "[0 = native; 1= fixed number of groups; 2= groups of fixed width; 3= moving window]", commandName, "setMode")) {
+			int m  = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(m)) {
+				mode = m;
+				Enumeration e = charters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof HistogramCharter) {
+						HistogramCharter tCO = (HistogramCharter)obj;
+						tCO.setMode(mode, suspend);
+					}
+				}
+				modeName.setValue(getModeName(mode));
+				//if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+				resetContainingMenuBar();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the chart is sized to fit into the field", "[on= size to fit;  off]", commandName, "toggleSizeToFit")) {
+			sizeToFit.toggleValue(parser.getFirstToken(arguments));
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setSizeToFit(sizeToFit.getValue());
+
+				}
+			}
+			if (showMenus){
+				if (!sizeToFit.getValue())
+					sizeItem = addMenuItem("Drawing Size...", sizeDrawingCommand);
+				else if (sizeItem!=null)
+					deleteMenuItem(sizeItem);
+			}
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of the drawing (appropriate if not size to fit)", "[width in pixels][height in pixels]", commandName, "sizeDrawing")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			int h = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(h)  || MesquiteInteger.isCombinable(w)) {
+				if (w>10 && h>10) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof HistogramCharter) {
+							HistogramCharter tCO = (HistogramCharter)obj;
+							tCO.setTotalField(w,h);
+						}
+					}
+					totalFieldHeight = h;
+					totalFieldWidth = w;
+				}
+			}
+			else { 
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger newWidth = new MesquiteInteger(totalFieldWidth);
+				MesquiteInteger newHeight =new MesquiteInteger(totalFieldHeight);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Size of chart drawing", "Width (Pixels)",  "Height (Pixels)", answer,  newWidth, newHeight,10,MesquiteInteger.unassigned,10, MesquiteInteger.unassigned,MesquiteString.helpString);
+				if (answer.getValue() &&( (newWidth.isCombinable()&&newWidth.getValue()>10) || (newHeight.isCombinable() && newHeight.getValue()>10))) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof HistogramCharter) {
+							HistogramCharter tCO = (HistogramCharter)obj;
+							tCO.setTotalField(newWidth.getValue(),newHeight.getValue());
+						}
+					}
+					totalFieldHeight = newHeight.getValue();
+					totalFieldWidth = newWidth.getValue();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of groups (appropriate if mode is Fixed Number of Groups)", "[number of groups]", commandName, "setNumberIntervals")) {
+			int intervals  = MesquiteInteger.fromFirstToken(arguments, pos);
+			resetMode = false;
+			if (!MesquiteInteger.isCombinable(intervals)) {
+				intervals = MesquiteInteger.queryInteger(containerOfModule(), "Groups", "Number of groups on X axis:", oldIntervals, 0, 1000);
+				if (!MesquiteThread.isScripting() && mode!=HistogramCharter.NUM_INTERVALS)
+					resetMode = true;
+			}
+			if (!MesquiteInteger.isCombinable(intervals)  || intervals <= 0)
+				return null;
+
+			oldIntervals = intervals;
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setIntervals(intervals);
+					if (resetMode)
+						tCO.setMode(HistogramCharter.NUM_INTERVALS, suspend);
+				}
+			}
+			if (resetMode)
+				modeName.setValue(getModeName(HistogramCharter.NUM_INTERVALS));
+			if (showMenus){
+				averageItem.setEnabled(MesquiteInteger.isCombinable(intervals));
+				cumulativeSubmenu.setEnabled(MesquiteInteger.isCombinable(intervals));
+				percentItem.setEnabled(MesquiteInteger.isCombinable(intervals));
+
+			}
+			MesquiteTrunk.resetMenuItemEnabling();
+
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+			resetContainingMenuBar();
+
+		}
+		else if (checker.compare(this.getClass(),  "Sets the width of intervals (appropriate if mode is Fixed Group Width)", "[width of groups]", commandName, "setIntervalSize")) {
+			double s  = MesquiteDouble.fromString(ParseUtil.getFirstToken(arguments, pos));
+			resetMode = false;
+			if (!MesquiteDouble.isCombinable(s)) {
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Groups", "Width of group on X axis:", oldIntervalSize, 0, 1000);
+				if (mode!=HistogramCharter.WIDTH_INTERVALS) {
+					resetMode = true;
+					mode = HistogramCharter.WIDTH_INTERVALS;
+				}
+			}
+			if (!MesquiteDouble.isCombinable(s)  || s <= 0)
+				return null;
+			oldIntervalSize = s;
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setIntervalSize(s);
+					if (resetMode)
+						tCO.setMode(HistogramCharter.WIDTH_INTERVALS, suspend);
+				}
+			}
+			if (resetMode)
+				modeName.setValue(getModeName(HistogramCharter.WIDTH_INTERVALS));
+			if (showMenus){
+				averageItem.setEnabled(true);
+				cumulativeSubmenu.setEnabled(true);
+				percentItem.setEnabled(true);
+			}
+			MesquiteTrunk.resetMenuItemEnabling();
+			if (!MesquiteThread.isScripting())  //WAYNE:??? why is this here
+				if (!suspend)
+					parametersChanged();
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(),  "Sets the size of the moving window (appropriate if mode is Moving Window)", "[Moving window size]", commandName, "setMovingWindowSize")) {
+			pos.setValue(0);
+			double sWidth = MesquiteDouble.fromString(arguments, pos);
+			double sIncrement  = MesquiteDouble.fromString(arguments, pos);
+			resetMode = false;
+			if (!MesquiteDouble.isCombinable(sIncrement) || !MesquiteDouble.isCombinable(sWidth)) {
+				MesquiteDouble sZ = new MesquiteDouble(oldMovingWindowWidth);
+				MesquiteDouble sR = new MesquiteDouble(oldMovingWindowIncrement);
+				MesquiteBoolean answer = new  MesquiteBoolean(false);
+
+				MesquiteString str1 = new MesquiteString(sZ.toString());
+				MesquiteString str2 = new MesquiteString(sR.toString());
+				new TwoStringsDialog(containerOfModule(), "Moving Window", "Width of Moving Window (units on X axis):", "Increment of Moving Window:", answer, str1, str2,false);
+				sZ.setValue(MesquiteDouble.fromString(str1.getValue()));
+				sR.setValue(MesquiteDouble.fromString(str2.getValue())); 
+				if (answer.getValue()) {
+					if (!sZ.isCombinable() || !sR.isCombinable()) {
+						return null;
+					}
+					sIncrement = sR.getValue();
+					sWidth = sZ.getValue();
+					oldMovingWindowIncrement = sIncrement;
+					oldMovingWindowWidth = sWidth;
+					if (mode!=HistogramCharter.MOVING_WINDOW)
+						resetMode = true;
+				}
+				else
+					return null;
+			}
+
+			oldMovingWindowWidth = sWidth;
+			oldMovingWindowIncrement = sIncrement;
+
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setMovingWindowSize(sIncrement, sWidth);
+					if (resetMode)
+						tCO.setMode(HistogramCharter.MOVING_WINDOW, suspend);
+				}
+			}
+
+			if (resetMode) {
+				modeName.setValue(getModeName(HistogramCharter.MOVING_WINDOW));
+				if (!MesquiteThread.isScripting())
+					if (!suspend)
+						parametersChanged();
+				resetContainingMenuBar();
+			}
+			else
+				if (!suspend)
+					parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets to automatic grouping mode", null, commandName, "setAutoMode")) {
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setMode(HistogramCharter.AUTO, suspend);
+				}
+			}
+			if (showMenus){
+				if (averageItem.isEnabled())
+					averageItem.setEnabled(false);
+				if (cumulativeSubmenu.isEnabled())
+					cumulativeSubmenu.setEnabled(false);
+				if (percentItem.isEnabled())
+					percentItem.setEnabled(false);
+			}
+			MesquiteTrunk.resetMenuItemEnabling();
+			modeName.setValue(getModeName(HistogramCharter.AUTO));
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(), "Sets to native mode", null, commandName, "setNativeMode")) {
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setMode(HistogramCharter.NATIVE, suspend);
+				}
+			}
+			if (showMenus){
+				if (averageItem.isEnabled())
+					averageItem.setEnabled(false);
+				if (cumulativeSubmenu.isEnabled())
+					cumulativeSubmenu.setEnabled(false);
+				if (percentItem.isEnabled())
+					percentItem.setEnabled(false);
+			}
+			MesquiteTrunk.resetMenuItemEnabling();
+			modeName.setValue(getModeName(HistogramCharter.NATIVE));
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+			resetContainingMenuBar();
+		}
+
+		else if (checker.compare(this.getClass(), "For orientation 1, shows average of each category", "[on or off]", commandName, "showAverageToggle")) {
+			showAverage.toggleValue(arguments);
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setShowAverage(showAverage.getValue(), suspend);
+				}
+			}
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, shows precent of each category", "[on or off]", commandName, "showPercentToggle")) {
+			showPercent.toggleValue(arguments);
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setShowPercent(showPercent.getValue(), suspend);
+				}
+			}
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the cumulative mode of the chart", "[0 = off; 1= simple cumulative; 2= cumulative average]", commandName, "setCumulativeMode")) {
+			int m  = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(m)) {					
+				switchCumulativeMode(m, suspend);
+			}
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, turns off cumulative values", "[on or off]", commandName, "setNoCumulative")) {
+			switchCumulativeMode(HistogramCharter.NO_CUMULATIVE, suspend);
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, shows cumulative values", "[on or off]", commandName, "setCumulative")) {
+			switchCumulativeMode(HistogramCharter.CUMULATIVE, suspend);
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, shows cumulative average values", "[on or off]", commandName, "setCumulativeAverage")) {
+			switchCumulativeMode(HistogramCharter.CUMULATIVE_AVERAGE, suspend);
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, shows cumulative values in reverse", "[on or off]", commandName, "setCumulativeDown")) {
+			switchCumulativeMode(HistogramCharter.CUMULATIVE_DOWN, suspend);
+		}
+		else if (checker.compare(this.getClass(), "For orientation 1, shows cumulative average values in reverse", "[on or off]", commandName, "setCumulativeAverageDown")) {
+			switchCumulativeMode(HistogramCharter.CUMULATIVE_AVERAGE_DOWN, suspend);
+		}
+		else if (checker.compare(this.getClass(), "Show as bar chart or as line chart", "[on or off]", commandName, "showAsBarChartToggle")) {
+			showAsBarChart.toggleValue(arguments);
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof HistogramCharter) {
+					HistogramCharter tCO = (HistogramCharter)obj;
+					tCO.setShowAsBarChart(showAsBarChart.getValue());
+				}
+			}
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Shows individual points in text view", "[on or off]", commandName, "showRawToggle")) {
+			showRaw.toggleValue(arguments);
+			if (!MesquiteThread.isScripting())
+				if (!suspend)
+					parametersChanged();
+
+		}
+		/**/
+		else if (checker.compare(this.getClass(), "Hires a chart assistant module", "[name of assistant module]", commandName, "newAssistant")) {
+			incrementMenuResetSuppression();
+			HistogramAssistantA tda= (HistogramAssistantA)hireNamedEmployee(HistogramAssistantA.class, arguments);
+			if (tda!=null) {
+				addAssistant(tda);
+				if (!MesquiteThread.isScripting()) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof HistogramCharter) {
+							HistogramCharter tCO = (HistogramCharter)obj;
+							tCO.chart.munch();
+						}
+					}
+					resetContainingMenuBar();
+				}
+				decrementMenuResetSuppression();
+				return tda;
+			}
+			else {
+				decrementMenuResetSuppression();
+				return findEmployeeWithName(parser.getFirstToken(arguments));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes an assistant module", "[number of assistant module]", commandName, "closeAssistant")) {
+			EmployeeVector ev = getEmployeeVector();
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			int count =0;
+			for (int i=0; i< ev.size(); i++){
+				MesquiteModule mb = (MesquiteModule)ev.elementAt(i);
+				if (mb!=null && mb instanceof HistogramAssistantA) {
+					if (count== which) {
+						fireEmployee(mb);
+						Enumeration e = charters.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof HistogramCharter) {
+								HistogramCharter tCO = (HistogramCharter)obj;
+								tCO.chart.removeAllExtrasOwned(mb);
+								tCO.chart.getField().repaint();
+								tCO.chart.repaint();
+							}
+						}
+						return null;
+					}
+					count++;
+				}
+			}
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public   Charter createCharter(ChartListener listener) {
+		Charter c = new HistogramCharter(this, listener);
+		charters.addElement(c);
+		return c;
+	}
+
+
+	Selectionable pointsAssociable = null;
+	boolean areParts = false;
+	/* tells the module whether points are parts of an Associable object */
+	public void pointsAreSelectable(boolean areParts, Selectionable a, boolean allowSequenceOptions){
+		if (this.areParts!=areParts || pointsAssociable!=a){
+			if (pointsAssociable!=null)
+				pointsAssociable.removeListener(this);
+			this.areParts = areParts;
+			pointsAssociable =a;
+			if (!areParts)
+				pointsAssociable = null;
+			if (pointsAssociable!=null)
+				pointsAssociable.addListener(this);
+			syncSel(false);
+			resetContainingMenuBar();
+		}
+	}
+
+	/* Synchronize selection of points in chart with parts of associable*/
+	void syncSel(boolean recalc){
+		Enumeration e = charters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof HistogramCharter) {
+				HistogramCharter tCO = (HistogramCharter)obj;
+				tCO.synchronizeSelection(true);
+				if (recalc){
+					tCO.calculateChart(tCO.chart);
+					tCO.chart.calculateAllExtras();
+					tCO.chart.getField().repaint();
+				}
+			}
+		}
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if ((obj==pointsAssociable || obj instanceof Selectionable) && (code==MesquiteListener.PARTS_MOVED ||code == MesquiteListener.SELECTION_CHANGED || code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_ADDED)) {
+			syncSel(true);
+		}
+	}
+	public void endJob(){
+		if (pointsAssociable!=null)
+			pointsAssociable.removeListener(this);
+		super.endJob();
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (mode == HistogramCharter.NUM_INTERVALS)
+			return "(X axis grouped into " + oldIntervals + " intervals)"; 
+		else if (mode == HistogramCharter.WIDTH_INTERVALS)
+			return "(X axis grouped into intervals of size " + oldIntervalSize + ")"; 
+		else if (mode == HistogramCharter.MOVING_WINDOW)
+			return "(Moving window of width " + MesquiteDouble.toString(oldMovingWindowWidth) + " every " + MesquiteDouble.toString(oldMovingWindowIncrement) + " units)"; 
+		else if (mode == HistogramCharter.AUTO) {
+			if (useMode == HistogramCharter.WIDTH_INTERVALS)
+				return "(Automatic grouping; Most recently used grouping:  X axis grouped into " + oldIntervals + " intervals)"; 
+			else if (useMode == HistogramCharter.NATIVE)
+				return "(Automatic grouping; Most recently used grouping:  X axis ungrouped)"; 
+		}
+		return "";
+	}
+}
+/* ======================================================================== */
+class HistogramCharter  extends Charter{
+	MesquiteNumber valueX;
+	MesquiteNumber valueY;
+	MesquiteNumber totalY = new MesquiteNumber(0);
+	MesquiteNumber totalX = new MesquiteNumber(0);
+
+	Histogram ownerModule;
+	MesquiteMenuItemSpec intervalsItem;
+	boolean showAverage = true;
+	int cumulativeMode = NO_CUMULATIVE;
+	boolean showAsBarChart = true;
+	int mode = AUTO;
+	int useMode = mode;
+
+	public static final int AUTO = 4;
+	public static final int NATIVE = 0;
+	public static final int NUM_INTERVALS = 1;
+	public static final int WIDTH_INTERVALS = 2;
+	public static final int MOVING_WINDOW = 3;
+
+	public static final int NO_CUMULATIVE=0;
+	public static final int CUMULATIVE=1;
+	public static final int CUMULATIVE_AVERAGE=2;
+	public static final int CUMULATIVE_DOWN=3;
+	public static final int CUMULATIVE_AVERAGE_DOWN=4;
+	int numIntervalsUsed = 0;
+	int numIntervalsSet = 0;
+	double intervalSize = 0;
+	double movingWindowWidth = 1;
+	double movingWindowIncrement = 1;
+	int originalMarkerWidth = 4;
+	int minTicks = 3;
+	MesquiteNumber[] clump; //the value (height) for each of the clumps
+	int[] numInClump; //how many data points are represented in each clump
+	double[] clumpPropSel; //the portion of the clump whose items are currently selected
+	static final int MAXCLUMPCOLORS = 10;
+	Color[][] clumpColors;  //how are the items in the clump colored? (gray if mixed)
+	int[][] clumpColorNumbers;  //how are the items in the clump colored? (gray if mixed)
+	int numSelected = 0;  //how many items are selected
+	MesquiteChart chart;
+	ChartListener listener;
+	int calculated = 0;
+	boolean showPercent = true;
+
+	public HistogramCharter (Histogram ownerModule, ChartListener listener) {	
+		this.ownerModule = ownerModule;
+		showAverage = ownerModule.showAverage.getValue();
+		showPercent = ownerModule.showPercent.getValue();
+		cumulativeMode = ownerModule.cumulativeMode;
+		showAsBarChart = ownerModule.showAsBarChart.getValue();
+		this.listener = listener;
+		mode = ownerModule.mode;
+		numIntervalsSet = ownerModule.oldIntervals;
+		valueX = new MesquiteNumber();
+		valueY = new MesquiteNumber();
+		clump = new MesquiteNumber[numIntervalsSet]; //+1
+		for (int i=0; i<numIntervalsSet; i++) //+1
+			clump[i] = new MesquiteNumber(0);
+		synchronizeSelection(true);
+	}
+	public void open(MesquiteChart chart){
+		ownerModule.incrementMenuResetSuppression();
+		this.chart = chart;
+		chart.setXAxisEdge(98); //MAKE IT DEPEND ON FONT SIZE  WAS 64
+		chart.setYAxisEdge(56); //MAKE IT DEPEND ON FONT SIZE
+		chart.setXPixelBase(0);
+		chart.setYPixelBase(0);
+		chart.setSizeToFit(true);
+		for (int i = 0; i<ownerModule.holding.size(); i++)
+			addAssistant((ChartAssistant)(ownerModule.holding.elementAt(i)));
+		ownerModule.decrementMenuResetSuppression();
+	}
+	public void close(){
+	}
+	void addAssistant(ChartAssistant tda){
+		if (chart!=null){
+			ChartExtra tce = tda.createExtra(chart); //HOW TO REMOVE IF QUIT???
+			chart.addExtra(tce);
+			tce.doCalculations();
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+	public void setTotalField(int w, int h) {
+		chart.setTotalField(w,h);
+		chart.getField().repaint();
+	}
+	public void setSizeToFit(boolean b) {
+		chart.setSizeToFit(b);
+		if (!b){
+			chart.setTotalFieldHeight(ownerModule.totalFieldHeight);
+			chart.setTotalFieldWidth(ownerModule.totalFieldWidth);
+		}
+	}
+	public boolean getShowPercent(){
+		return (canShowPercentage() && chart.getCharter()!=null && ownerModule.showPercent.getValue());
+	}
+	public void setShowAverage(boolean show, boolean suspend) {
+		showAverage = show;
+		if (!suspend) {
+			calculateChart(chart);
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+	public void setShowPercent(boolean show, boolean suspend) {
+		showPercent = show;
+		if (!suspend) {
+			calculateChart(chart);
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+	public void setCumulativeMode(int m, boolean suspend) {
+		cumulativeMode = m;
+		if (!suspend) {
+			calculateChart(chart);
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+	public void setShowAsBarChart(boolean show) {
+		showAsBarChart = show;
+		chart.getField().repaint();
+		chart.repaint();
+	}
+	public void setMode(int m, boolean suspend) {
+		mode = m; 
+		ownerModule.mode = m;
+		if (!MesquiteThread.isScripting() && ! suspend){
+			calculateChart(chart);
+			chart.getField().repaint();
+			chart.repaint();
+		}
+		else calculated = 0;
+	}
+	public void setIntervals(int numIntervals) {
+		this.numIntervalsSet = numIntervals;
+		clump = new MesquiteNumber[numIntervalsSet];//+1
+		for (int i=0; i<numIntervalsSet; i++)//+1
+			clump[i] = new MesquiteNumber(0);
+		if (clumpColors!=null) {
+			clumpColors = new Color[numIntervalsSet][MAXCLUMPCOLORS];//+1
+			clumpColorNumbers = new int[numIntervalsSet][MAXCLUMPCOLORS];
+		}
+	}
+	public void setIntervalSize(double intervalSize) {
+		this.intervalSize = intervalSize;
+	}
+
+	/* ----------------------------------*/
+	public String getYAxisNameSuffix(){
+		if (cumulativeMode==NO_CUMULATIVE)
+			return "";
+		else
+			return "("+ownerModule.getCumulativeModeName(cumulativeMode) + ")";
+	}
+
+	/* ----------------------------------*/
+	public void setMovingWindowSize(double movingWindowIncrement, double movingWindowWidth) {
+		this.movingWindowWidth = movingWindowWidth;
+		this.movingWindowIncrement = movingWindowIncrement;
+	}
+	/* ----------------------------------*/
+	void select(int which){
+		if (ownerModule.pointsAssociable!=null)  
+			ownerModule.pointsAssociable.setSelected(which, true);
+		else
+			chart.selectPoint(which);
+
+	}
+	void deselect(int which){
+		if (ownerModule.pointsAssociable!=null)  
+			ownerModule.pointsAssociable.setSelected(which, false);
+		else
+			chart.deselectPoint(which);
+	}
+	void selectInterval(int interval){
+		int[] points = findPointsInInterval(interval, chart);
+		if (points !=null)
+			for (int i=0; i<points.length; i++)
+				select(points[i]);
+	}
+	void deselectAll(){
+		if (ownerModule.pointsAssociable!=null)  
+			ownerModule.pointsAssociable.deselectAll();
+		else
+			chart.deselectAllPoints(); 
+	}
+	boolean isSelected(int which){
+		if (ownerModule.pointsAssociable!=null)  
+			return ownerModule.pointsAssociable.getSelected(which);
+		else
+			return chart.getSelected().isBitOn(which);
+	}
+	boolean anySelected(){
+		if (ownerModule.pointsAssociable!=null)  
+			return ownerModule.pointsAssociable.anySelected();
+		else
+			return chart.getSelected().anyBitsOn();
+	}
+	/*	It would be nice to have shift click have contiguous selections in contrast to command/control click, but given that the
+x axis can represent different things (items, values, values by category) it is difficult to implement.  Here is a beginning.
+	void shrinkWrap(boolean byPoints){
+		if (byPoints || useMode == NATIVE){
+			int min = minSelPoint();
+			if (min>=0) {
+				int max = maxSelPoint();
+				for (int i = min; i<=max; i++) {
+					select(i);
+				}
+			}
+		}
+		else {
+			int min = minSelInterval();
+			if (min>=0) {
+				int max = maxSelInterval();
+				for (int i = min; i<=max; i++) {
+					selectInterval(i);
+				}
+			}
+		}	
+	}
+	int minSelPoint(){
+		for (int i = 0; i<chart.getNumPoints(); i++)
+			if (isSelected(i))
+				return i;
+		return -1;
+	}
+	int maxSelPoint(){
+		for (int i = chart.getNumPoints()-1; i>=0; i--)
+			if (isSelected(i))
+				return i;
+		return -1;
+	}
+	int minSelInterval(){
+		for (int interval = 0; interval<numIntervalsint[] points = findPointsInInterval(interval, chart);
+		if (points !=null)
+			for (int i=0; i<points.length; i++)
+				select(points[i]);
+		return -1;
+	}
+	int maxSelInterval(){
+		return -1;
+	}
+	 */
+	// handles cleanup after selection changed
+	void wrapUpSelection(){
+		if (ownerModule.pointsAssociable!=null)  {
+			if (!ownerModule.pointsAssociable.amIListening(ownerModule)) //in case data matrix didn't exist when connected, do this just in case
+				ownerModule.pointsAssociable.addListener(ownerModule);
+			ownerModule.pointsAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+		else {
+			calculateChart(chart);
+			chart.calculateAllExtras();//extras need to recalculate in case they depended on selection
+			chart.getField().repaint();
+		}
+	}
+	/**/
+	//for selection dragging
+	void drawVerticalLine(Graphics g, int x){
+		int y1 = 1;
+		int y2 = chart.getField().getBounds().height-1;
+		g.drawLine(x, y1, x, y2);
+	}
+	void drawRectByCorners(Graphics g, int x1, int y1, int x2, int y2){
+		if (x1>x2){
+			if (y1>y2)
+				g.drawRect(x2, y2, x1-x2, y1-y2);
+			else 
+				g.drawRect(x2, y1, x1-x2, y2-y1);
+		}
+		else {
+			if (y1>y2)
+				g.drawRect(x1, y2, x2-x1, y1-y2);
+			else 
+				g.drawRect(x1, y1, x2-x1, y2-y1);
+		}
+
+	}
+	void fillRectByCorners(Graphics g, int x1, int y1, int x2, int y2){
+		if (x1>x2){
+			if (y1>y2)
+				g.fillRect(x2, y2, x1-x2, y1-y2);
+			else 
+				g.fillRect(x2, y1, x1-x2, y2-y1);
+		}
+		else {
+			if (y1>y2)
+				g.fillRect(x1, y2, x2-x1, y1-y2);
+			else 
+				g.fillRect(x1, y1, x2-x1, y2-y1);
+		}
+	}
+	long numClicks = 0;
+	/* ---------------------------------- */
+	private int findExactXValue(int xPixel, int yPixel, MesquiteChart chart){  
+		if (xPixel<0)
+			xPixel =0;
+		return xPixel;
+	}
+	/* ----------------------------------*/
+	public boolean isNative(){
+		return useMode==NATIVE;
+	}
+	/* ---------------------------------- */
+	private int findIntervalOfX(MesquiteNumber valueX, MesquiteChart chart){
+		if (useMode == NATIVE || (useMode ==NUM_INTERVALS && numIntervalsSet == 0) || (useMode ==WIDTH_INTERVALS && intervalSize == 0)) {
+			return -1; //intervals don't exist
+		}
+		else if (useMode == NUM_INTERVALS) {//grouped into intervals
+			if (!valueX.isCombinable())
+				return -1;
+			else if (valueX.equals(chart.getAxisMaximumX())){ //maximum value would be right on edge of highest interval
+				return numIntervalsSet-1;
+			}
+			else if (valueX.isMoreThan(chart.getAxisMaximumX())){ //maximum value would be right on edge of highest interval
+				return -1;
+			}
+			int whichInterval = valueX.findInterval(chart.getMinimumX(), chart.getMaximumX(), numIntervalsSet);
+			if (whichInterval == numIntervalsSet)
+				whichInterval = numIntervalsSet-1;
+			return whichInterval;
+		}
+		else if (useMode ==WIDTH_INTERVALS) {
+			return valueX.findInterval(chart.getMinimumX(), new MesquiteNumber(intervalSize));
+		}
+		return -1;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber leftmostXDrawn(MesquiteChart chart){
+		return new MesquiteNumber(chart.getMinimumX());
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber rightmostXDrawn(MesquiteChart chart){
+		if (useMode == NATIVE) {
+			MesquiteNumber xMax= new MesquiteNumber();
+			int xPixel = xToPixel(chart.getMaximumX().getDoubleValue(), chart);
+			pixelToX(xPixel+markerWidth, chart, xMax);
+			return xMax;
+		}
+		double xMin = chart.getMinimumX().getDoubleValue();
+		double xIntervalWidth = getIntervalWidth();
+		return new MesquiteNumber(xIntervalWidth*(numIntervalsUsed) + xMin);
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber rightmostXOfInterval(MesquiteNumber x, MesquiteChart chart){
+		if (x == null)
+			return null;
+		if (useMode == NATIVE) {
+			MesquiteNumber xMax= new MesquiteNumber();
+			int xPixel = xToPixel(x.getDoubleValue(), chart);
+			pixelToX(xPixel+markerWidth, chart, xMax);
+			return xMax;
+		}
+		int i = findIntervalOfX(x, chart);
+		if (i<0)
+			return null;
+		double xMin = chart.getMinimumX().getDoubleValue();
+		double xIntervalWidth = getIntervalWidth();
+		return new MesquiteNumber(xIntervalWidth*(i+1) + xMin);
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber leftmostXOfInterval(MesquiteNumber x, MesquiteChart chart){
+		if (x == null)
+			return null;
+		if (useMode == NATIVE) {
+			MesquiteNumber xMax= new MesquiteNumber();
+			int xPixel = xToPixel(x.getDoubleValue(), chart);
+			pixelToX(xPixel, chart, xMax);
+			return xMax;
+		}
+		int i = findIntervalOfX(x, chart);
+		if (i<0)
+			return null;
+		double xMin = chart.getMinimumX().getDoubleValue();
+		double xIntervalWidth = getIntervalWidth();
+		return new MesquiteNumber(xIntervalWidth*(i) + xMin);
+	}
+	/* ----------------------------------*/
+	public boolean moreThanOneValueInInterval(MesquiteNumber x, MesquiteChart chart) {
+		if (x == null)
+			return false;
+		if (useMode == NATIVE) {
+			return false;
+		}
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items   (y by x)
+			int interval = findIntervalOfX(x, chart);
+			if (interval<0)
+				return false;
+			int[] points = findPointsInInterval (interval, chart);
+			if (points !=null) {
+				NumberArray xArray = chart.getXArray();
+				double firstValue = MesquiteDouble.unassigned;
+				for (int i=0; i<points.length; i++) {
+					if (i==0)
+						firstValue = xArray.getDouble(points[i]);
+					else if (firstValue!=MesquiteDouble.unassigned) {
+						if (firstValue != xArray.getDouble(points[i])) {
+							return true;
+						}
+					}
+				}
+			}
+		}
+		else {  // not yet allowed
+		}
+
+		return false;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber bottommostYOfInterval(MesquiteNumber y, MesquiteChart chart){
+		return y;  //eventually need to be redone for useMode!=NATIVE
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber topmostYOfInterval(MesquiteNumber y, MesquiteChart chart){
+		return y;  //eventually need to be redone for useMode!=NATIVE
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber topmostYDrawn(MesquiteChart chart){
+		if (useMode == NATIVE) {
+			return new MesquiteNumber(chart.getMaximumY());
+		}
+		else {
+			MesquiteNumber yM = new MesquiteNumber();
+
+			for (int i = 0; i<numInClump.length; i++)
+				yM.setMeIfIAmLessThan(numInClump[i]);
+			return yM;
+
+		}
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber bottommostYDrawn(MesquiteChart chart){
+		if (useMode == NATIVE) {
+			return new MesquiteNumber(chart.getMinimumY());
+		}
+		return null;
+	}
+	/* ---------------------------------- */
+	private int findIntervalOfPixel(int xPixel, MesquiteChart chart, boolean report){
+		if (xPixel<0)
+			xPixel =0;
+
+		if (useMode == NATIVE) {
+			MesquiteNumber xMin= new MesquiteNumber();
+			MesquiteNumber xMax= new MesquiteNumber();
+
+			pixelToX(xPixel-markerWidth, chart, xMin);
+			pixelToX(xPixel, chart, xMax);
+
+
+			NumberArray xArray = chart.getXArray();
+			long numFound=0;
+			int found = -1;
+			for (int i=0; i<chart.getNumPoints(); i++){
+				xArray.placeValue(i, tempNum);
+				if (tempNum!=null && tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax)) {
+					numFound++;
+					found = i;
+				}
+			}
+			if (numFound==1)
+				return found;
+			else if (numFound>0) {
+				long target = numClicks % numFound;
+				for (int i=0; i<chart.getNumPoints(); i++){
+					xArray.placeValue(i, tempNum);
+					if (tempNum!=null && tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax)) {
+						if (target<=0)
+							return i;
+						target--;
+					}
+				}
+			}
+			return -1;
+		}
+		else {
+			MesquiteNumber valueX= new MesquiteNumber();
+			pixelToX(xPixel, chart, valueX);
+			if (valueX.isCombinable()) 
+				return findIntervalOfX(valueX, chart);//covers all cases except edges, e.g. on right side valueX could be unassigned 
+
+			//check to see if in last interval
+			double xIntervalWidth = getIntervalWidth(); 
+			double leftX = xIntervalWidth*(numIntervalsUsed-1) + chart.getMinimumX().getDoubleValue();
+			int minPixel = xToPixel(leftX, chart);
+			int maxPixel = xToPixel(xIntervalWidth + leftX, chart); //minPixel+markerWidth;
+			if ((xPixel>=minPixel && xPixel<= maxPixel)) {
+				return numIntervalsUsed-1;
+			}
+			return -1;
+		}
+	}
+
+	//finds points greater than pixel x and less than pixel x2 (lessthan or equal x2 if boolean is true)
+	private int[] findXValuesWithinPixels(int x, int y, int x2, int y2, boolean includeUpperEdge, MesquiteChart chart){  
+		MesquiteNumber xMin= new MesquiteNumber();
+		MesquiteNumber xMax= new MesquiteNumber();
+		MesquiteNumber tempNum= new MesquiteNumber();
+		if (x2<x){
+			int te = x;
+			x=x2;
+			x2=te;
+		}
+		pixelToX(x, chart, xMin);
+		pixelToX(x2, chart, xMax);
+		NumberArray xArray = chart.getXArray();
+
+		int count =0;
+		for (int i=0; i<chart.getNumPoints(); i++){
+			xArray.placeValue(i, tempNum);
+			if (tempNum!=null && tempNum.isMoreThan(xMin) && ((includeUpperEdge && !tempNum.isMoreThan(xMax)) || (!includeUpperEdge && tempNum.isLessThan(xMax)))) {
+				count++;
+			}
+		}
+		if (count>0) {
+			int[] found = new int[count];
+			count = 0;
+			for (int i=0; i<chart.getNumPoints(); i++){
+				xArray.placeValue(i, tempNum);
+				if (tempNum!=null && tempNum.isMoreThan(xMin) &&  ((includeUpperEdge && !tempNum.isMoreThan(xMax)) || (!includeUpperEdge && tempNum.isLessThan(xMax)))) {
+					found[count++] = i;
+				}
+			}
+			return found;
+		}
+		return null;
+	}
+	//finds points greater than x and less than x2 (lessthan or equal x2 if boolean is true)
+	private int[] findPointsInInterval(int interval, MesquiteChart chart){  
+		NumberArray xArray = chart.getXArray();
+		MesquiteNumber valueX= new MesquiteNumber();
+
+		int count =0;
+		for (int i= 0; i<chart.getNumPoints(); i++) {
+			if (!xArray.isUnassigned(i)) {
+				chart.getXArray().placeValue(i, valueX);
+				if (findIntervalOfX(valueX, chart) == interval)
+					count++;
+			}
+		}
+
+		if (count>0) {
+			int[] found = new int[count];
+			count = 0;
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				chart.getXArray().placeValue(i, valueX);
+				int fi = findIntervalOfX(valueX, chart);
+				if (fi == interval) 
+					found[count++] = i;
+
+			}
+			return found;
+		}
+		return null;
+	}
+	/* ----------------------------------*/
+	int pointEntered = -1;
+	public void mouseMoveInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		whichDown = findIntervalOfPixel(xPixel, chart, false);
+		if (pointEntered >=0 && whichDown!=pointEntered) {  //had been in other point recently; exit it
+			ListableVector extras = chart.getExtras();
+			for (int i=0; i<extras.size(); i++) {
+				((ChartExtra)extras.elementAt(i)).cursorExitPoint(pointEntered, findExactXValue(xPixel,yPixel, chart),null);
+			}
+		}
+		if (whichDown>=0) {
+			if (whichDown!=pointEntered){
+				ListableVector extras = chart.getExtras();
+				for (int i=0; i<extras.size(); i++) {
+					((ChartExtra)extras.elementAt(i)).cursorEnterPoint(whichDown, findExactXValue(xPixel,yPixel, chart), null);
+				}
+			}
+			pointEntered = whichDown;
+		}
+		else
+			pointEntered = -1;
+	}
+	/* ----------------------------------*/
+	int whichDown = MesquiteInteger.unassigned;
+	int xDown = MesquiteInteger.unassigned;
+	int yDown = MesquiteInteger.unassigned;
+	int xDrag = MesquiteInteger.unassigned;
+	int yDrag = MesquiteInteger.unassigned;
+	/* ----------------------------------*/
+	public double totalClumpValues() {
+		if (clump!=null) {
+			MesquiteNumber count =new MesquiteNumber(0);
+			for (int i=0; i<clump.length; i++) {
+				count.add(clump[i]);
+			}
+			return count.getDoubleValue();
+		}
+		return 0.0;
+	}
+	/* ----------------------------------*/
+	public double fractionBelow(int whichDown) {
+		if (clump!=null && whichDown<clump.length) {
+			MesquiteNumber count =new MesquiteNumber(0);
+			for (int i=0; i<whichDown; i++) {
+				count.add(clump[i]);
+			}
+			return count.getDoubleValue()/totalClumpValues();
+		}
+		return 0.0;
+	}
+	/* ----------------------------------*/
+	public double fractionAbove(int whichDown) {
+		if (clump!=null && whichDown<clump.length) {
+			MesquiteNumber count =new MesquiteNumber(0);
+			for (int i=whichDown+1; i<clump.length; i++) {
+				count.add(clump[i]);
+			}
+			return count.getDoubleValue()/totalClumpValues();
+		}
+		return 0.0;
+	}
+
+	public boolean showingClumpSums(){
+		if (chart.getOrientation() == 0)
+			return false;
+		return !(chart.getUseAverage() || showAverage || (cumulativeMode>NO_CUMULATIVE) || useMode == NATIVE || useMode == MOVING_WINDOW);
+	}
+	public boolean canShowPercentage(){
+		return !((useMode == NATIVE || (useMode ==NUM_INTERVALS && numIntervalsSet == 0) || (useMode ==WIDTH_INTERVALS && intervalSize == 0)));
+	}
+	/* ----------------------------------*/
+	public void mouseDownInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		numClicks++;
+		whichDown = findIntervalOfPixel(xPixel,chart, true);
+		if (tool !=null && tool != chart.getArrowTool() && tool != chart.getInfoTool()) {
+			if (whichDown>=0){
+				tool.pointTouched(whichDown, xPixel, yPixel,modifiers);
+				return;
+			}
+		}
+
+		//arrow tool; start selection indication	
+		if (tool == chart.getArrowTool()){
+			xDown = xPixel;
+			yDown = yPixel;
+			xDrag=xPixel;
+			yDrag=yPixel;
+			ListableVector extras = chart.getExtras();
+			for (int i=0; i<extras.size(); i++) {
+				((ChartExtra)extras.elementAt(i)).cursorTouchPoint(whichDown, findExactXValue(xPixel,yPixel, chart), null);
+			}
+			return;
+		}
+
+		//info tool
+		if (whichDown>=0 && listener !=null) {
+			if (useMode == NATIVE){
+				if (chart.getYArray()!=null && chart.getXArray()!=null) {
+					NumberArray xs = chart.getXArray();
+					NumberArray ys = chart.getYArray();
+					xs.placeValue(whichDown, valueX);
+					ys.placeValue(whichDown, valueY);
+					double sum = 0;
+					if (ownerModule.noSum)
+						sum = valueY.getDoubleValue();
+					else
+						sum = sumSame(xs, ys, -1, valueX, null);
+					valueY.setValue(sum);
+					listener.pointMouseDown(chart, whichDown, valueX, valueY, xPixel, yPixel, modifiers, null);
+				}
+				else
+					listener.pointMouseDown(chart, whichDown, null, null, xPixel, yPixel, modifiers, null);
+			}
+			else if (whichDown>=0 && clump!=null && whichDown<clump.length) {
+				String message;
+				if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1)) || useMode == MOVING_WINDOW)
+					message = "Average " + clump[whichDown] + "\n (of " + numInClump[whichDown] + " items with X values ranging\n" +  describeEdges(whichDown) + ")";
+				else {
+					message = "Sum " + clump[whichDown] + "\n (of items with X values ranging\n" +  describeEdges(whichDown) + ")";
+					message += "\nFraction < this:\n" + MesquiteDouble.toString(fractionBelow(whichDown));
+					message += "\nFraction > this:\n " + MesquiteDouble.toString(fractionAbove(whichDown));
+				}
+				if (chart.getYArray()!=null) {
+					chart.getYArray().placeValue(whichDown, valueY);
+					listener.pointMouseDown(chart, MesquiteInteger.unassigned, null, valueY, xPixel, yPixel, modifiers, message);
+				}
+				else
+					listener.pointMouseDown(chart, MesquiteInteger.unassigned, null, null, xPixel, yPixel, modifiers, message);
+			}
+		}
+		ListableVector extras = chart.getExtras();
+		for (int i=0; i<extras.size(); i++) {
+			((ChartExtra)extras.elementAt(i)).cursorTouchPoint(whichDown, findExactXValue(xPixel,yPixel, chart), null);
+		}
+	}
+	/* ----------------------------------*/
+	public void mouseDragInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		if (tool == chart.getArrowTool()){ 
+			Graphics g=chart.getField().getGraphics();
+			if (g!=null){
+				g.setXORMode(Color.white);
+				g.setColor(Color.black);
+				drawVerticalLine(g, xDrag);
+				drawVerticalLine(g, xPixel);
+				xDrag=xPixel;
+				yDrag=yPixel;
+				g.dispose();
+			}
+		}
+	}
+	/* ----------------------------------*/
+	public void mouseUpInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		//if (MesquiteInteger.isNonNegative(whichDown)) { // had touched directly on point before
+		if (tool !=null && tool != chart.getArrowTool()&& tool != chart.getInfoTool()) {
+			if (whichDown>=0){
+				tool.pointDropped(whichDown, xPixel, yPixel,modifiers);
+				return;
+			}
+		}	
+		int which = findIntervalOfPixel(xPixel, chart, false); //this is interval if nonnative
+		if (listener!=null)
+			listener.pointMouseUp(chart, which, xPixel, yPixel, modifiers, null);
+		if (tool == chart.getArrowTool()){
+			Graphics g=chart.getField().getGraphics();
+			if (g!=null){
+				g.setXORMode(Color.white);
+				g.setColor(Color.black);
+				drawVerticalLine(g, xDown);
+				drawVerticalLine(g, xDrag);
+				g.dispose();
+			}
+			//single point selected
+			if (useMode == NATIVE && which == whichDown && MesquiteInteger.isNonNegative(which)) {
+				if (MesquiteEvent.commandKeyDown(modifiers) || MesquiteEvent.shiftKeyDown(modifiers)) {
+					if (isSelected(which))
+						deselect(which);
+					else
+						select(which);
+				}
+				else {
+					if (anySelected())
+						deselectAll();
+					select(which);
+				}
+				wrapUpSelection();
+
+				/**/
+			}
+			else  {
+				int[] whichPoints;
+				if (which == whichDown && MesquiteInteger.isNonNegative(which)){ //click and up on same interval
+					double xMin = chart.getMinimumX().getDoubleValue();
+					double xIntervalWidth = getIntervalWidth();
+					whichPoints = findPointsInInterval(which, chart);
+				}
+				else {
+					whichPoints = findXValuesWithinPixels(xPixel,yPixel,xDown, yDown, false, chart);
+				}
+
+				if (whichPoints!=null && whichPoints.length>0) {
+
+					if (!MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandKeyDown(modifiers))
+						deselectAll();
+					for (int i = 0; i< whichPoints.length; i++){
+						which = whichPoints[i];
+						if (MesquiteEvent.commandKeyDown(modifiers) || MesquiteEvent.shiftKeyDown(modifiers)) {
+							if (isSelected(which))
+								deselect(which);
+							else
+								select(which);
+						}
+						else if (!isSelected(which)) {
+							select(which);
+						}
+					}
+					wrapUpSelection();
+
+
+				}
+				else if (chart.getSelected().anyBitsOn()){
+
+					deselectAll();
+					wrapUpSelection();
+
+				}
+			}
+		}
+		//}
+		xDown = MesquiteInteger.unassigned;
+		yDown = MesquiteInteger.unassigned;
+		whichDown =MesquiteInteger.unassigned;
+	}
+	LittlePanel quickPanel;
+	public void showQuickMessage(MesquiteChart chart, int whichPoint,int xPixel, int yPixel,  String message){
+		int boxWidth = 96;
+		if (StringUtil.blank(message))
+			return;
+		if (quickPanel==null) {
+			chart.add(quickPanel = new LittlePanel());
+			quickPanel.setBackground(ColorDistribution.lightGreen);
+		}
+		quickPanel.setText(message, chart.getField().getFont(), boxWidth);
+		int offsetRight = 12;
+		StringInABox sb = quickPanel.getBox();
+		int xOffset = chart.getField().getBounds().x;
+		int yOffset = chart.getField().getBounds().y;
+		int xPos=0;
+		if (xPixel+boxWidth+8 + offsetRight>chart.getField().getBounds().width) 
+			xPos = xPixel-boxWidth + xOffset;
+		else
+			xPos = xPixel+4 + xOffset + offsetRight;
+		int yPos=0;
+
+		if (yPixel+sb.getHeight()>chart.getField().getBounds().height + yOffset && yPixel-sb.getHeight() + yOffset>=0)
+			yPos = yPixel-sb.getHeight() + yOffset;
+		else
+			yPos = yPixel + yOffset;
+		quickPanel.setSize(boxWidth +2, sb.getHeight() +2);
+		quickPanel.setLocation(xPos, yPos);
+		quickPanel.setVisible(true);
+		quickPanel.repaint();
+
+	}
+	/* ----------------------------------*/
+	public void hideQuickMessage(MesquiteChart chart){
+		if (quickPanel!=null)
+			quickPanel.setVisible(false);
+	}
+	/* ----------------------------------*/
+	private void findEdges(int interval, MesquiteNumber minInterval, MesquiteNumber maxInterval){ 
+		minInterval.setToUnassigned();
+		maxInterval.setToUnassigned();
+		if (chart.getMinimumX()==null || chart.getMaximumX() == null)
+			return;
+		if (useMode == NATIVE || (useMode ==NUM_INTERVALS && numIntervalsSet == 0) || (useMode ==WIDTH_INTERVALS && intervalSize == 0)) {
+		}
+		else if (useMode ==NUM_INTERVALS) {
+			tempNum.setValue(chart.getMaximumX());
+			tempNum.subtract(chart.getMinimumX());
+			tempNum.divideBy(numIntervalsSet);
+
+			minInterval.setValue(tempNum);
+			minInterval.multiplyBy(interval);
+			minInterval.add(chart.getMinimumX());
+
+			maxInterval.setValue(tempNum);
+			maxInterval.multiplyBy(interval+1);
+			maxInterval.add(chart.getMinimumX());
+		}
+		else if (useMode == WIDTH_INTERVALS) {
+			minInterval.setValue(intervalSize);
+			minInterval.multiplyBy(interval);
+			minInterval.add(chart.getMinimumX());
+
+			maxInterval.setValue(intervalSize);
+			maxInterval.multiplyBy(interval+1);
+			maxInterval.add(chart.getMinimumX());
+		}
+		else if (useMode == MOVING_WINDOW) {
+			tempNum.setValue(chart.getMaximumX());  //what about movingWindowIncrement
+			tempNum.subtract(chart.getMinimumX());
+			tempNum.divideBy(numIntervalsUsed);
+
+			minInterval.setValue(interval);
+			minInterval.multiplyBy(movingWindowIncrement);
+			minInterval.add(chart.getMinimumX());
+
+			maxInterval.setValue(minInterval);
+			maxInterval.add(movingWindowWidth);
+		}
+	}
+	/* ---------------------------------- */
+	private String describeEdges(int interval){
+		MesquiteNumber minInterval=new MesquiteNumber();
+		MesquiteNumber maxInterval=new MesquiteNumber();
+		if (useMode == NATIVE || (useMode ==NUM_INTERVALS && numIntervalsSet == 0) || (useMode ==WIDTH_INTERVALS && intervalSize == 0)) {
+			//"item " + interval
+			minInterval.setToUnassigned();
+			maxInterval.setToUnassigned();
+			return "Item " + interval;
+		}
+		else {
+			if (chart.getMinimumX()==null || chart.getMaximumX() == null)
+				return "no";
+			findEdges(interval, minInterval, maxInterval);
+			if (interval == numIntervalsUsed-1)
+				return "from " + minInterval + "\n to " + maxInterval;
+			else
+				return "from " + minInterval + "\n to less than " + maxInterval;
+		}
+	}
+	/* ----------------------------------*/
+	void processClumps(int numIntervals) {
+		if (clump!=null && clump.length>0){
+			MesquiteNumber total = new MesquiteNumber(0);
+			if (showPercent) {
+				for (int i= 0; i<numIntervals; i++)
+					total.add(clump[i]);
+			}
+			switch (cumulativeMode) {
+			case CUMULATIVE: {
+				for (int i= 1; i<numIntervals; i++)
+					clump[i].add(clump[i-1]);
+				break;
+			}
+			case CUMULATIVE_AVERAGE: {
+				for (int i= 1; i<numIntervals; i++)
+					clump[i].add(clump[i-1]);
+				int count = 0;
+				for (int i= 0; i<numIntervals; i++){
+					count++;
+					clump[i].divideBy(count);
+				}
+				break;
+			}
+			case CUMULATIVE_DOWN: {
+				for (int i= numIntervals-2; i>=0; i--)
+					clump[i].add(clump[i+1]);
+				break;
+			}
+			case CUMULATIVE_AVERAGE_DOWN: {
+				for (int i= numIntervals-2; i>=0; i--)
+					clump[i].add(clump[i+1]);
+				int count = 0;
+				for (int i= numIntervals-1; i>=0; i--) {
+					count++;
+					clump[i].divideBy(count);
+				}
+				break;
+			}
+			}
+			if (showPercent) {
+				for (int i= 0; i<numIntervals; i++) {
+					clump[i].divideBy(total);
+					clump[i].multiplyBy(100);
+				}
+			}
+			minY.setValue(clump[0]);
+			maxY.setValue(clump[0]);
+			for (int i= 0; i<numIntervals; i++) {
+				maxY.setMeIfIAmLessThan(clump[i]);
+				minY.setMeIfIAmMoreThan(clump[i]);
+			}
+		}
+	}
+	/* ----------------------------------*/
+	public  void calculateChart(MesquiteChart chart){
+		if (minY==null || maxY==null || chart==null)
+			return;
+		if (getSuspendChartCalculations())
+			return;
+		calculated = 1;
+
+		minX.setValue(chart.getAxisMinimumX()); 
+		maxX.setValue(chart.getAxisMaximumX());
+		minY.setToUnassigned();
+		maxY.setToUnassigned();
+		boolean currentAverageIsEnabled = false;
+		//	if (ownerModule.percentItem !=null)
+		//		ownerModule.percentItem.setEnabled(canShowPercentage());
+		if (ownerModule.averageItem !=null)
+			ownerModule.averageItem.isEnabled();
+		if (currentAverageIsEnabled && chart.getOrientation() == 0) {
+			if (ownerModule.averageItem !=null)
+				ownerModule.averageItem.setEnabled(false);
+			MesquiteTrunk.resetMenuItemEnabling();
+			ownerModule.resetContainingMenuBar();
+		}
+		useMode = mode;
+		if (mode == AUTO) {
+			if (chart.getOrientation() == 1) {   //orientation stored in chart as 0 = items by values; 1 = values by items
+				if (chart.getMaximumX().getDoubleValue() - chart.getMinimumX().getDoubleValue()<15)
+					useMode = NATIVE;
+				else {
+					useMode =WIDTH_INTERVALS;
+					intervalSize = 1 + (int)((chart.getMaximumX().getDoubleValue() - chart.getMinimumX().getDoubleValue())/100);
+				}
+			}
+			else {
+				if (chart.getXArray().getValueClass() == NumberArray.DOUBLE){
+					useMode =NUM_INTERVALS;
+					numIntervalsSet = 50;
+				}
+				else {
+					if (chart.getMaximumX().getDoubleValue() - chart.getMinimumX().getDoubleValue()<15)
+						useMode = NATIVE;
+					else {
+						useMode =WIDTH_INTERVALS;
+						intervalSize = 1 + (int)((chart.getMaximumX().getDoubleValue() - chart.getMinimumX().getDoubleValue())/100);
+					}
+				}
+			}
+		}
+		ownerModule.useMode = useMode;
+		boolean someSelected = anySelected();
+		if (ownerModule.percentItem !=null)
+			ownerModule.percentItem.setEnabled(canShowPercentage());
+
+		if (useMode == NATIVE || (useMode ==NUM_INTERVALS && numIntervalsSet == 0) || (useMode ==WIDTH_INTERVALS && intervalSize == 0)) {
+			if (currentAverageIsEnabled) {
+				if (ownerModule.averageItem !=null)
+					ownerModule.averageItem.setEnabled(false);
+				MesquiteTrunk.resetMenuItemEnabling();
+				ownerModule.resetContainingMenuBar();
+			}
+			minY.setValue(chart.getAxisMinimumY());
+			maxY.setValue(chart.getAxisMaximumY());
+
+			// calculate totals and divide by these for percent display
+			if (getShowPercent()) {
+				totalX.setValue(0.0);
+				totalY.setValue(0.0);
+				for (int i= 0; i<chart.getNumPoints(); i++) {   // calculate total for percentages
+					if (getSuspendChartCalculations())
+						return;
+					if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+						chart.getXArray().placeValue(i, valueX);
+						totalX.add(valueX);
+						chart.getYArray().placeValue(i, valueY);
+						totalY.add(valueY);
+					}
+				}
+				totalX.divideBy(100.0);
+				totalY.divideBy(100.0);
+				chart.getYArray().switchToDoubles();
+				for (int i= 0; i<chart.getNumPoints(); i++) {   
+					if (getSuspendChartCalculations())
+						return;
+					if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+						chart.getYArray().divideBy(i, totalY);
+					}
+				}
+			}
+
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendChartCalculations())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					NumberArray xs = chart.getXArray();
+					if (!anySameLeft(xs, i, valueX)){
+						double sum = 0;
+						if (ownerModule.noSum)
+							sum = chart.getYArray().getDouble(i);
+						else
+							sum = sumSame(xs, chart.getYArray(), i, valueX, null);
+						maxY.setMeIfIAmLessThan(sum);
+					}
+
+				}
+			}
+		}
+		else if (useMode ==NUM_INTERVALS) {
+			numIntervalsUsed = numIntervalsSet;
+			int expandedNumIntervals = numIntervalsUsed; // + 1;
+			if (!currentAverageIsEnabled && chart.getOrientation() == 1) {
+				if (ownerModule.averageItem !=null)
+					ownerModule.averageItem.setEnabled(true);
+				MesquiteTrunk.resetMenuItemEnabling();
+				ownerModule.resetContainingMenuBar();
+			}
+			if (clump ==null || chart.getXArray()==null || chart.getYArray() == null)
+				return;
+			prepareClumps(expandedNumIntervals, someSelected, (chart.getUseAverage() || (showAverage && chart.getOrientation()==1)));
+
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendChartCalculations())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+					int whichInterval;
+
+					if (valueX.equals(chart.getAxisMaximumX()))
+						whichInterval = numIntervalsUsed-1;
+					else {
+						whichInterval = valueX.findInterval(chart.getMinimumX(), chart.getMaximumX(), numIntervalsUsed);
+						if (whichInterval == numIntervalsUsed)
+							whichInterval = numIntervalsUsed-1;
+					}
+					if (whichInterval>=clump.length || whichInterval <0){
+						MesquiteMessage.warnProgrammer("Error in histogram: i " + i + " whichInterval " + whichInterval + " clump.length " + clump.length +" chart.getMinimumX() " + chart.getMinimumX()  +" chart.getMaximumY() " + chart.getMaximumY() + " valueX " + valueX);
+					}
+					else {
+						if (someSelected && clumpPropSel!=null && whichInterval<clumpPropSel.length && isSelected(i) && valueY.isCombinable())
+							clumpPropSel[whichInterval] += valueY.getDoubleValue();
+						clump[whichInterval].add(valueY);
+
+						if (chart.colorsExist() && chart.getColor(i) != null) {
+							if (clumpColors == null){
+								clumpColors = new Color[expandedNumIntervals][MAXCLUMPCOLORS];
+								clumpColorNumbers = new int[expandedNumIntervals][MAXCLUMPCOLORS];
+							}
+							Color cat = chart.getColor(i);
+							addToClumpColors(whichInterval, cat);
+						}
+						if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1)))
+							numInClump[whichInterval]++;
+					}
+				}
+			}
+			if (someSelected && clumpPropSel!=null) {
+				for (int i= 0; i<expandedNumIntervals; i++) {
+					if (clump[i].getDoubleValue()>0) {
+						clumpPropSel[i] /= clump[i].getDoubleValue();
+					}
+				}
+			}
+			if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1))) {
+				for (int i= 0; i<expandedNumIntervals; i++) {
+					if (numInClump[i]>0) {
+						clump[i].divideBy(numInClump[i]);
+					}
+				}
+			}
+			processClumps(expandedNumIntervals);
+			minY.setMeIfIAmMoreThan(chart.getAxisMinimumY()); //In case constrained
+		}
+		else if (useMode == WIDTH_INTERVALS) {
+			if (!currentAverageIsEnabled && chart.getOrientation() == 1) {
+				if (ownerModule.averageItem !=null)
+					ownerModule.averageItem.setEnabled(true);
+				MesquiteTrunk.resetMenuItemEnabling();
+				ownerModule.resetContainingMenuBar();
+			}
+			numIntervalsUsed = (int)(0.99999999999+(chart.getMaximumX().getDoubleValue()-chart.getMinimumX().getDoubleValue())/intervalSize) + 1;
+			if (numIntervalsUsed <0)
+				numIntervalsUsed = 0;
+			prepareClumps(numIntervalsUsed, someSelected, (chart.getUseAverage() || (showAverage && chart.getOrientation()==1)));
+
+			MesquiteNumber nI = new MesquiteNumber(intervalSize);
+
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendChartCalculations())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+					int whichInterval = valueX.findInterval(chart.getMinimumX(), nI);
+					if (whichInterval < 0)
+						MesquiteMessage.warnProgrammer("Negative interval in chart; min = " + chart.getMinimumX() + "  valueX = " + valueX);
+					else {
+						clump[whichInterval].add(valueY); 
+						if (someSelected && clumpPropSel!=null && whichInterval<clumpPropSel.length && isSelected(i) && valueY.isCombinable())
+							clumpPropSel[whichInterval] += valueY.getDoubleValue();
+
+						if (chart.colorsExist() && chart.getColor(i) != null) {
+							Color cat = chart.getColor(i);
+							addToClumpColors(whichInterval, cat);
+						}
+						if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1))) {
+							if (whichInterval >= numInClump.length || whichInterval < 0)
+								MesquiteMessage.warnProgrammer("Error in histogram: interval not found.  whichInterval " + whichInterval + " numInclump.length " + numInClump.length);
+							else
+								numInClump[whichInterval]++;
+						}
+					}
+				}
+			}
+			if (someSelected && clumpPropSel!=null) {
+				for (int i= 0; i<numIntervalsUsed; i++) {
+					if (clump[i].getDoubleValue()>0) {
+						clumpPropSel[i] /= clump[i].getDoubleValue();
+					}
+				}
+			}
+			if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1))) {
+				for (int i= 0; i<numIntervalsUsed; i++) {
+					if (numInClump[i]>0) {
+						clump[i].divideBy(numInClump[i]);
+					}
+				}
+			}
+			processClumps(numIntervalsUsed);
+			minY.setMeIfIAmMoreThan(chart.getAxisMinimumY()); //In case constrained
+		}
+		else if (useMode == MOVING_WINDOW) {
+			if (!currentAverageIsEnabled && chart.getOrientation() == 1) {
+				if (ownerModule.averageItem !=null)
+					ownerModule.averageItem.setEnabled(true);
+				MesquiteTrunk.resetMenuItemEnabling();
+				ownerModule.resetContainingMenuBar();
+			}
+			boolean useSum = (chart.getOrientation()==0); //don't average over moving window if items by values
+			numIntervalsUsed = (int)(0.99999999999+(chart.getMaximumX().getDoubleValue()-chart.getMinimumX().getDoubleValue())/movingWindowIncrement) +1;
+			if (numIntervalsUsed<0)
+				numIntervalsUsed = 0;
+			//preparing clumps for as many intervals as dictated by movingWindowIncrement
+			prepareClumps(numIntervalsUsed, someSelected, true);
+
+			MesquiteNumber sum  = new MesquiteNumber(0);
+			MesquiteNumber startInterval = new MesquiteNumber();
+			MesquiteNumber endInterval = new MesquiteNumber();
+			// first, go through all the intervals, in each finding who is inside its window
+			for (int whichInterval= 0; whichInterval<numIntervalsUsed; whichInterval++) { 
+				if (getSuspendChartCalculations())
+					return;
+				numInClump[whichInterval] =0;
+				if (someSelected && clumpPropSel!=null && whichInterval<clumpPropSel.length)
+					clumpPropSel[whichInterval]  = 0.0;
+				sum.setValue(0);
+				double sumSel = 0.0;
+				startInterval.setValue(chart.getAxisMinimumX().getDoubleValue());
+				startInterval.add(movingWindowIncrement * whichInterval);
+				endInterval.setValue(startInterval.getDoubleValue() + movingWindowWidth);
+				for (int i= 0; i<chart.getNumPoints(); i++) {
+					if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+						chart.getXArray().placeValue(i, valueX);
+						chart.getYArray().placeValue(i, valueY);
+
+						// this value is in the window
+						if (valueX.isLessThan(endInterval) && !valueX.isLessThan(startInterval)){
+							numInClump[whichInterval]++;
+							sum.add(valueY); 
+							if (someSelected && isSelected(i) && valueY.isCombinable())
+								sumSel += valueY.getDoubleValue();
+
+							if (chart.colorsExist() && chart.getColor(i) != null) {
+								Color cat = chart.getColor(i);
+								addToClumpColors(whichInterval, cat);
+							}
+						}
+					}
+				}
+				//the sum in the window is now stored  in sum
+				if (numInClump[whichInterval] == 0)
+					clump[whichInterval].setValue(0.0);
+				else {
+					if (useSum)
+						clump[whichInterval].setValue(numInClump[whichInterval]);
+					else
+						clump[whichInterval].setValue(sum.getDoubleValue()/numInClump[whichInterval]);
+					if (sum.getDoubleValue()!=0.0 && someSelected && clumpPropSel!=null && whichInterval<clumpPropSel.length)
+						clumpPropSel[whichInterval] = sumSel/sum.getDoubleValue();
+				}
+			}
+			processClumps(numIntervalsUsed);
+			minY.setMeIfIAmMoreThan(chart.getAxisMinimumY()); //In case constrained
+		}
+		if (maxY.isCombinable()){
+			maxY.setValue(maxY.getDoubleValue()*1.1);
+		}
+		numSelected = 0;
+		if (someSelected)
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					if (isSelected(i))
+						numSelected++;
+				}
+			}
+
+		calculated = 2;
+	}
+
+	int whichColor(Color[] colors, Color c){
+		if (c == null || colors == null)
+			return -1;
+		for (int i = 0; i< colors.length; i++)
+			if (c.equals(colors[i]))
+				return i;
+		//not found; determine next open slot, but last slot is prohibited
+		for (int i = 0; i< colors.length-1; i++)
+			if (colors[i] == null)
+				return i;
+
+		return -1;
+	}
+	void addToClumpColors(int whichInterval, Color cat){
+
+		if (cat == null){
+			return;
+		}
+		int colorFound = whichColor(clumpColors[whichInterval], cat);
+		if (colorFound == -1){
+			clumpColors[whichInterval][MAXCLUMPCOLORS-1] = Color.darkGray;
+			colorFound = MAXCLUMPCOLORS-1;
+		}
+		else if (clumpColors[whichInterval][colorFound] == null) //not yet assigned
+			clumpColors[whichInterval][colorFound] = cat;
+		clumpColorNumbers[whichInterval][colorFound]++;
+	}
+	/* ----------------------------------*/
+	void prepareClumps(int numIntervals, boolean someSelected, boolean numInClumpAlso){
+		//preparing clumps for as many intervals as dictated by movingWindowIncrement
+		if (clump == null || clump.length != numIntervals ) {
+			clump = new MesquiteNumber[numIntervals];
+			for (int i=0; i<numIntervals; i++) {
+				clump[i] = new MesquiteNumber(0);
+			}
+		}
+		for (int i= 0; i<clump.length; i++) 
+			clump[i].setValue(0);
+		if (numInClumpAlso){
+			if (numInClump == null || numInClump.length != numIntervals )
+				numInClump = new int[numIntervals];
+			for (int i=0; i<numIntervals; i++)
+				numInClump[i] = 0;
+		}
+		if (clumpColors == null || clumpColors.length != numIntervals){
+			clumpColors = new Color[numIntervals][MAXCLUMPCOLORS];
+			clumpColorNumbers = new int[numIntervals][MAXCLUMPCOLORS];
+		}
+		for (int i=0; i<numIntervals; i++)
+			for (int k = 0; k< MAXCLUMPCOLORS; k++){
+				clumpColors[i][k] = null;
+				clumpColorNumbers[i][k] = 0;
+			}
+
+		if (someSelected) {
+			if (clumpPropSel == null || clumpPropSel.length != numIntervals) {
+				clumpPropSel = new double[numIntervals];
+				for (int i=0; i<numIntervals; i++) 
+					clumpPropSel[i] = 0;
+			}
+			else
+				for (int i= 0; i<clumpPropSel.length; i++) 
+					clumpPropSel[i] = 0;
+		}
+	}
+	/* ----------------------------------*/
+	public String getYAxisName(MesquiteChart chart){
+		if (chart==null)
+			return "";
+		if ((chart.getUseAverage() || (showAverage && chart.getOrientation()==1)) && mode != NATIVE) {
+			return "(Average) " + chart.yAxisName;
+		}
+		else {
+			return chart.yAxisName;
+		}
+	}
+	/* ----------------------------------*/
+	Color bgColor = Color.white;
+	Color axisColor = Color.cyan;
+	Color gridColor = Color.cyan;
+	Color barColor = Color.green;
+
+	/*	boolean anySelected(){
+		if (ownerModule.pointsAssociable==null)
+			return false;
+		return ownerModule.pointsAssociable.anySelected();
+	}
+	boolean isSelected(int i){
+		if (ownerModule.pointsAssociable==null)
+			return false;
+		return ownerModule.pointsAssociable.getSelected(i);
+	}
+	/* ----------------------------------*/
+	public double getIntervalWidth() {
+		double xMin = chart.getMinimumX().getDoubleValue();
+		double xIntervalWidth = 0;
+		if (useMode == WIDTH_INTERVALS)
+			xIntervalWidth = intervalSize; 
+		else if (numIntervalsUsed!=0)
+			xIntervalWidth = (chart.getMaximumX().getDoubleValue() - xMin)*1.0001/numIntervalsUsed; 
+		return xIntervalWidth;
+	}
+	/* ----------------------------------*/
+
+	public void drawChartBackground(Graphics g, MesquiteChart chart){ //g is from paint from ChartField
+		//Shape clip = g.getClip();
+
+		//g.setClip(0,0,fieldWidth, fieldHeight);
+		//g.setColor(bgColor);
+		//g.fillRect(margin, margin, fieldWidth-2*margin, fieldHeight-2*margin);
+		// grid ========
+		drawGrid(g, chart);
+		//grid ===  
+
+		//axes ====	
+		/*
+		g.drawLine(zeroX, 0 , zeroX, fieldHeight);
+		g.drawLine(zeroX+1, 0 , zeroX+1, fieldHeight);
+		g.drawLine(0, zeroY, fieldWidth , zeroY);
+		g.drawLine(0, zeroY+1, fieldWidth , zeroY+1);
+		 */
+
+	}
+	/* ----------------------------------*/
+
+	public void drawChart(Graphics g, MesquiteChart chart){ //g is from paint from ChartField
+		if (chart==null || chart.getXArray()==null || chart.getYArray()==null )
+			return;
+		if (chart.getNumPoints()==0){
+			g.setColor(Color.black);
+			g.drawString("The chart does not yet have any points", 10, 70);
+			return;
+		}
+		if (calculated == 0)
+			MesquiteMessage.warnProgrammer("Error: chart drawn while calculated = 0");
+		if (getSuspendDrawing())
+			return;
+		chartDone = true;
+		int fieldWidth =  chart.getFieldWidth();
+		int fieldHeight =  chart.getFieldHeight();
+
+		int margin = chart.getMargin();
+		synchronizeSelection(false);
+		//Shape clip = g.getClip();
+
+		//g.setClip(0,0,fieldWidth, fieldHeight);
+		//g.setColor(bgColor);
+		//g.fillRect(margin, margin, fieldWidth-2*margin, fieldHeight-2*margin);
+		// grid ========
+		//		drawGrid(g, chart);
+		//grid ===  
+
+		//axes ====	
+		g.setColor(axisColor);
+
+		valueX.setValue(0);
+		valueY.setValue(0);
+		int zeroX = xToPixel(0, chart);
+		int zeroY = yToPixel(0, chart);
+
+		/*
+		g.drawLine(zeroX, 0 , zeroX, fieldHeight);
+		g.drawLine(zeroX+1, 0 , zeroX+1, fieldHeight);
+		g.drawLine(0, zeroY, fieldWidth , zeroY);
+		g.drawLine(0, zeroY+1, fieldWidth , zeroY+1);
+		 */
+		//axes ====	
+		if (chart.getField()==null)
+			return;
+		g.setColor(Color.black);
+		String problem = "";
+		g.drawRect(margin, margin, chart.getField().getBounds().width-1-2*margin, chart.getField().getBounds().height-1-2*margin);
+		boolean someSelected = anySelected();
+		int lastX=MesquiteInteger.unassigned;
+		int lastY=MesquiteInteger.unassigned;
+		if (useMode == NATIVE) {
+			markerWidth = originalMarkerWidth;
+			boolean wasGray = true;
+			MesquiteDouble sel = new MesquiteDouble(0); //to keep track of whether all selected in bar (1) all deselected (0) or mix (2)
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendDrawing())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+
+					NumberArray xs = chart.getXArray();
+					if (!anySameLeft(xs, i, valueX)){
+						double sum = 0;
+						if (ownerModule.noSum)
+							sum = chart.getYArray().getDouble(i);
+						else if (someSelected) {
+							sel.setValue(0);
+							sum = sumSame(xs, chart.getYArray(), i, valueX, sel);
+						}
+						else
+							sum = sumSame(xs, chart.getYArray(), i, valueX, null);
+						int xPixel = xToPixel(valueX.getDoubleValue(), chart);
+						int yPixel = yToPixel(sum, chart);
+						if (getSuspendDrawing())
+							return;
+						if (xPixel < 0 || xPixel > chart.getField().getBounds().width)
+							problem += "[xPixel " + xPixel + " w " + chart.getField().getBounds().width + " i " + i + "] " ;
+						if (yPixel < 0 || yPixel > chart.getField().getBounds().height)
+							problem += "[yPixel " + yPixel + " h " + chart.getField().getBounds().height + " i " + i + "] " ;
+						int selY = yPixel;
+
+						boolean dimmed = false;
+						if (someSelected && sel.getValue() != sum){
+							dimmed = true;
+							selY = yToPixel(sel.getValue(), chart);
+						}
+						Color fillStandard = Color.darkGray;
+						Color dimStandard = Color.lightGray;
+						Color line = Color.black;
+						Color fill  = fillStandard;
+						Color dim = dimStandard;
+
+						if (chart.colorsExist() && chart.getColor(i)!=null) {
+							fill = chart.getColor(i);
+							if (dimmed)
+								dim = ColorDistribution.brighter(fill, ColorDistribution.dimmingConstant);
+						}
+
+						g.setColor(fill);
+						if (showAsBarChart) {
+							if (!dimmed)
+								fillRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, zeroY);
+							else {
+								fillRectByCorners(g, xPixel, selY, xPixel + markerWidth, zeroY);
+								g.setColor(dim);
+								fillRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, selY);
+							}
+							g.setColor(line);
+							drawRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, zeroY);
+							g.setColor(Color.white);
+							if (yPixel<zeroY)
+								g.drawLine(xPixel, yPixel-1, xPixel+markerWidth, yPixel-1);
+							else 
+								g.drawLine(xPixel, yPixel+1, xPixel+markerWidth, yPixel+1);
+						}
+						else {
+							if (MesquiteInteger.isCombinable(lastX)&&MesquiteInteger.isCombinable(lastX))
+								g.drawLine(lastX,lastY,xPixel+markerWidth/2,yPixel);
+							int markerRadius = MesquiteInteger.maximum(markerWidth/4, 2);
+							g.fillOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+							if (markerRadius>2)
+								g.setColor(line);
+							g.drawOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+							lastX = xPixel+markerWidth/2;
+							lastY = yPixel;
+						}
+
+					}
+
+				}
+			}
+		}
+		else if (numIntervalsUsed !=0) {
+			double xMin = chart.getMinimumX().getDoubleValue();
+			double xIntervalWidth = getIntervalWidth();
+
+			markerWidth = xToPixel(xIntervalWidth + xMin, chart) - xToPixel(xMin, chart); 
+			if (markerWidth == 0) //���� divide by zero
+				markerWidth =1;
+
+			for (int i= 0; i<numIntervalsUsed +1; i++) {
+				if (getSuspendDrawing())
+					return;
+				if (clump!=null && i<clump.length && clump[i]!=null && !clump[i].isUnassigned()) {
+					int xPixel = xToPixel(xIntervalWidth*i + xMin, chart);
+
+					int yPixel = yToPixel(clump[i].getDoubleValue(), chart);
+					if (xPixel >= 0 && yPixel >=0) {  //can be negative in some cases of update while calculations in flux?
+						if (getSuspendDrawing())
+							return;
+						if (xPixel > chart.getField().getBounds().width)
+							problem += "[xPixel " + xPixel + " w " + chart.getField().getBounds().width + " i " + i + "] " ;
+						if (yPixel > chart.getField().getBounds().height)
+							problem += "[yPixel " + yPixel + " h " + chart.getField().getBounds().height + " i " + i + "] " ;
+						int selY = yPixel;
+
+						boolean dimmed = false;
+						if (someSelected && clumpPropSel!=null && clumpPropSel[i] < 1.0){
+							dimmed = true;
+							selY = yToPixel(clumpPropSel[i]*clump[i].getDoubleValue(), chart);
+						}
+						Color fill = Color.blue;
+						Color line = Color.black;
+						Color dim = ColorDistribution.veryLightBlue;
+						if (chart.colorsExist() && clumpColors[i][1]!=null){  //MULTICOLOR
+							if (showAsBarChart) {
+								int sum = 0;
+								int totColors = 0;
+								for (int k = 0; k < MAXCLUMPCOLORS && clumpColors[i][k]!=null; k++){
+									sum += clumpColorNumbers[i][k];
+									totColors ++;
+								}
+
+								int offset = 0;
+								for (int iColor = 0; iColor<totColors; iColor++){
+									fill = clumpColors[i][iColor];
+									if (dimmed)
+										dim = ColorDistribution.brighter(fill, ColorDistribution.dimmingConstant);
+									g.setColor(fill);
+									if (!dimmed)
+										fillRectByCorners(g, xPixel, yPixel+offset, xPixel + markerWidth, zeroY);
+									else {
+										//fillRectByCorners(g, xPixel, selY+offset, xPixel + markerWidth, zeroY);
+										g.setColor(dim);
+										fillRectByCorners(g, xPixel, yPixel+offset ,xPixel + markerWidth, zeroY);
+									}
+									offset += (zeroY-yPixel)*clumpColorNumbers[i][iColor]/sum;
+								}
+								fill = Color.darkGray;
+								if (markerWidth >2)
+									g.setColor(line);
+								drawRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, zeroY);
+								g.setColor(Color.white);
+								if (yPixel<zeroY)
+									g.drawLine(xPixel, yPixel-1, xPixel+markerWidth, yPixel-1);
+								else 
+									g.drawLine(xPixel, yPixel+1, xPixel+markerWidth, yPixel+1);
+							}
+							else {
+								fill = Color.darkGray;
+								if (MesquiteInteger.isCombinable(lastX)&&MesquiteInteger.isCombinable(lastX))
+									g.drawLine(lastX,lastY,xPixel+markerWidth/2,yPixel);
+								int markerRadius = MesquiteInteger.maximum(markerWidth/4, 2);
+								g.fillOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+								if (markerRadius>2)
+									g.setColor(line);
+								g.drawOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+								lastX = xPixel+markerWidth/2;
+								lastY = yPixel;
+							}
+						}
+						else {  //ONE COLOR
+							if (chart.colorsExist()){
+								if (clumpColors[i][0]!=null) {
+									fill = clumpColors[i][0];
+									if (dimmed)
+										dim = ColorDistribution.brighter(fill, ColorDistribution.dimmingConstant);
+								}
+								else {
+									fill = Color.darkGray;
+									dim = Color.lightGray;
+								}
+							}
+
+							g.setColor(fill);
+							if (showAsBarChart) {
+								if (!dimmed)
+									fillRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, zeroY);
+								else {
+									fillRectByCorners(g, xPixel, selY, xPixel + markerWidth, zeroY);
+									g.setColor(dim);
+									fillRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, selY);
+								}
+								if (markerWidth >2)
+									g.setColor(line);
+								drawRectByCorners(g, xPixel, yPixel, xPixel + markerWidth, zeroY);
+								g.setColor(Color.white);
+								if (yPixel<zeroY)
+									g.drawLine(xPixel, yPixel-1, xPixel+markerWidth, yPixel-1);
+								else 
+									g.drawLine(xPixel, yPixel+1, xPixel+markerWidth, yPixel+1);
+							}
+							else {
+								if (MesquiteInteger.isCombinable(lastX)&&MesquiteInteger.isCombinable(lastX))
+									g.drawLine(lastX,lastY,xPixel+markerWidth/2,yPixel);
+								int markerRadius = MesquiteInteger.maximum(markerWidth/4, 2);
+								g.fillOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+								if (markerRadius>2)
+									g.setColor(line);
+								g.drawOval(xPixel+markerWidth/2-markerRadius, yPixel-markerRadius, markerRadius*2, markerRadius*2);
+								lastX = xPixel+markerWidth/2;
+								lastY = yPixel;
+							}
+						}
+
+					}
+				}
+			}
+		}
+		else if (calculated == 2 && chart.getNumPoints()>0)
+			MesquiteMessage.warnProgrammer("Warning: numIntervals 0 with non native mode in Histogram; mode = " + mode);
+		if (problem.length() >0 && !getDrawWarningSuppressed())
+			MesquiteMessage.warnProgrammer("Error: a histogram value was drawn outside of the bounds of the chart "  + problem);
+		g.setColor(Color.black);
+		g.drawRect(margin, margin, chart.getField().getBounds().width-1-2*margin, chart.getField().getBounds().height-1-2*margin);
+		//g.setClip(clip);
+
+	}
+	public String getTextVersion(MesquiteChart chart){
+		if (chart==null || chart.getXArray()==null || chart.getYArray()==null )
+			return null;
+		StringBuffer s = new StringBuffer();
+		if (chart.getNumPoints()==0){
+			return "The chart does not yet have any points.  It may be in the process of being calculated.";
+		}
+		if (useMode == NATIVE) {
+			boolean multiFound = false;
+			int[] ord = chart.getOrderByX();
+			for (int j= 0; j<chart.getNumPoints(); j++) {
+				int i = ord[j];
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					NumberArray xs = chart.getXArray();
+					if (!anySameLeft(xs, i, valueX)){
+						double sum = 0;
+						if (ownerModule.noSum)
+							sum = chart.getYArray().getDouble(i);
+						else
+							sum = sumSame(xs, chart.getYArray(), i, valueX, null);
+						//					if (chart.getCharter()!=null && chart.getCharter().getShowPercent())
+						//						sum = sum/totalY.getDoubleValue();
+						s.append(valueX.toString()+ ": " + MesquiteDouble.toString(sum) + StringUtil.lineEnding());
+					}
+					else
+						multiFound = true;
+				}
+			}
+			if (multiFound) {
+				if (ownerModule.showRaw.getValue()) {
+					s.append( StringUtil.lineEnding() + "========================" + StringUtil.lineEnding());
+					chart.putRawTextVersion(ord, ": ", StringUtil.lineEnding(), false, false, s);
+				}
+				return s.toString();
+			}
+			else {
+				s.setLength(0);
+				chart.putRawTextVersion(ord, ": ", StringUtil.lineEnding(), false, false, s);
+				return s.toString();
+			}
+
+		}
+		else if (numIntervalsUsed !=0) {
+			double xMin = chart.getMinimumX().getDoubleValue();
+			double xIntervalWidth = getIntervalWidth();
+			for (int i= 0; i<numIntervalsUsed +1; i++) {
+				if (clump!=null && i<clump.length && clump[i]!=null && !clump[i].isUnassigned()) {
+					s.append(MesquiteDouble.toString(xIntervalWidth*i + xMin) + " to " + MesquiteDouble.toString(xIntervalWidth*(i+1)+ xMin));
+					s.append(": " + MesquiteDouble.toString(clump[i].getDoubleValue()) + StringUtil.lineEnding());
+				}
+			}
+			if (ownerModule.showRaw.getValue()) {
+				s.append( StringUtil.lineEnding() + "========================" + StringUtil.lineEnding());
+				chart.putRawTextVersion(chart.getOrderByX(), ": ", StringUtil.lineEnding(), false, false, s);
+			}
+			return s.toString();
+		}
+		return null;
+	}
+
+	boolean anySameLeft(NumberArray xs, int index, MesquiteNumber valueX){
+		for (int i=0; i < index; i++) {
+			if (xs.equal(i, index))
+				return true;
+		}
+		return false;
+	}
+
+
+	double sumSame(NumberArray xs, NumberArray ys, int index, MesquiteNumber valueX, MesquiteDouble sel){
+		if (!valueX.isCombinable())
+			return valueX.getDoubleValue();
+		double sum = 0;
+		double sumSel = 0;
+		if (index >= 0){ //use x value at index
+			for (int i=0; i < xs.getSize(); i++) {
+				if (xs.equal(i, index) && ys.isCombinable(i)) {
+					sum += ys.getDouble(i);
+					if (sel !=null && isSelected(i))
+						sumSel += ys.getDouble(i);
+				}
+			}
+		}
+		else { //use valueX
+			for (int i=0; i < xs.getSize(); i++) {
+				if (xs.equals(i, valueX) && ys.isCombinable(i)) {
+					sum += ys.getDouble(i);
+					if (sel !=null && isSelected(i))
+						sumSel += ys.getDouble(i);
+				}
+			}
+		}
+		if (sel !=null) 
+			sel.setValue(sumSel);
+		return sum;
+	}
+	/* ----------------------------------*/
+	public void drawBlank(Graphics g, MesquiteChart chart){
+		int margin = chart.getMargin();
+		Color c = g.getColor();
+		g.setColor(bgColor);
+		g.fillRect(margin, margin, chart.getFieldWidth()-2*margin, chart.getFieldHeight()-2*margin);
+		g.setColor(Color.black);
+		g.drawRect(margin, margin, chart.getFieldWidth()-2*margin, chart.getFieldHeight()-2*margin);
+		g.setColor(c);
+	}
+	/* ----------------------------------*/
+	public String getName() {
+		return "Bar  & Line Chart";
+	}
+	void synchronizeSelection(boolean reset) {
+		if (chart!=null){
+			if (ownerModule.pointsAssociable!=null)
+				chart.synchronizePointSelection(ownerModule.pointsAssociable);
+			else if (reset)
+				deselectAll();
+		}
+	}
+}
+
+
+class LittlePanel extends Panel {
+	String t;
+	StringInABox sb;
+	void setText(String s, Font f, int w){
+		t = s;
+		sb = new StringInABox(t, f, w);
+	}
+	StringInABox getBox(){
+		return sb;
+	}
+	public void paint(Graphics g){
+		if (sb == null)
+			return;
+
+		sb.drawInBox(g, getBackground(), 3, 1);
+		g.setColor(Color.black);
+		g.drawRect(0,0,getBounds().width-1, getBounds().height-1);
+	}
+}
+
diff --git a/Source/mesquite/charts/ItemValuesChart/ItemValuesChart.java b/Source/mesquite/charts/ItemValuesChart/ItemValuesChart.java
new file mode 100644
index 0000000..3e8e282
--- /dev/null
+++ b/Source/mesquite/charts/ItemValuesChart/ItemValuesChart.java
@@ -0,0 +1,1190 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.ItemValuesChart;
+
+/* ~~ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+
+public class ItemValuesChart extends ItemsCharter {
+	public void getEmployeeNeeds() { // This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.charts.Histogram.Histogram.class, getName() + " needs a module to draw the chart.", "The chart drawing module is selected automatically");
+	}
+
+	DrawChart charterTask;
+
+	ItemsChartWindow cWindow;
+
+	int suspend = 0;
+
+	boolean doCountPending = false;
+
+	boolean calculationsEnabled;
+boolean startedAsScripting = false;
+	/* ................................................................................................................. */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charterTask = (DrawChart) hireNamedEmployee(DrawChart.class, "#mesquite.charts.Histogram.Histogram");
+		if (charterTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		calculationsEnabled = !MesquiteThread.isScripting();
+		startedAsScripting = MesquiteThread.isScripting();
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public boolean isSubstantive() {
+		return true;
+	}
+
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	public boolean showCitation() {
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m) {
+		if (m == charterTask)
+			iQuit();
+	}
+
+	/* ................................................................................................................. */
+	public ChartWindow makeChartWindow(MesquiteModule requester) {
+		cWindow = new ItemsChartWindow(requester, this);
+		cWindow.setWindowSize(400, 400);
+		return cWindow;
+	}
+
+	public void incrementSuspension() {
+		suspend++;
+	}
+
+	public void decrementSuspension() {
+		suspend--;
+		if (suspend <= 0 && doCountPending && cWindow != null) {
+			suspend = 0;
+			doCountPending = false;
+			if (cWindow == null || cWindow.autoCount == null || cWindow.autoCount.getValue())
+				doCounts();
+			else
+				cWindow.showRecalcButton();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (cWindow == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		Snapshot sn = cWindow.getSnapshot(file);
+		temp.incorporate(sn, true);
+		temp.addLine("endTell");
+		temp.addLine("enableCalculations");
+		return temp;
+	}
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return charterTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart window", null, commandName, "getWindow")) {
+			return cWindow;
+		}
+		else if (checker.compare(this.getClass(), "Increments the suspension level on the calculations", null, commandName, "suspendCalculations")) {
+			incrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Decrements the suspension level on the calculations", null, commandName, "resumeCalculations")) {
+			decrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Enables the calculations", null, commandName, "enableCalculations")) {
+			calculationsEnabled = true;
+
+		}
+		else if (checker.compare(this.getClass(), "Requests that calculations be performed", null, commandName, "doCounts")) {
+			if (suspend > 0)
+				doCountPending = true;
+			else {
+				doCounts();
+				doCountPending = false;
+			}
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow == null)
+			return;
+		if (employee == charterTask)
+			((ItemsChartWindow) cWindow).recalcChart();
+		else
+			doCounts();
+	}
+
+	/* ................................................................................................................... */
+	public void doCounts(int firstItem, int lastItem, boolean fullCount) {
+		if (cWindow != null && !isDoomed()) {
+			if (!calculationsEnabled)
+				return;
+			if (suspend > 0)
+				doCountPending = true;
+			else {
+				((ItemsChartWindow) cWindow).doCounts(firstItem, lastItem, fullCount);
+				doCountPending = false;
+			}
+		}
+	}
+
+	public void setTaxa(Taxa taxa) {
+		if (cWindow != null)
+			((ItemsChartWindow) cWindow).setTaxa(taxa);
+	}
+
+	/* ................................................................................................................... */
+	public void setItemsSource(ItemsSource itemsSourceTask) {
+		if (cWindow != null)
+			((ItemsChartWindow) cWindow).setItemsSource(itemsSourceTask);
+	}
+
+	/* ................................................................................................................... */
+	public void setNumberTask(NumberForItem numberTask) {
+		if (cWindow != null)
+			((ItemsChartWindow) cWindow).setNumberTask(numberTask);
+	}
+
+	/* ................................................................................................................. */
+	public void setDefaultNumberOfItems(int def) {
+		if (cWindow != null)
+			((ItemsChartWindow) cWindow).setDefaultNumberOfItems(def);
+	}
+
+	/* ................................................................................................................... */
+	public void setAuxiliary(Object object, boolean useAsFirstParameter) {
+		if (cWindow != null)
+			((ItemsChartWindow) cWindow).setAuxiliary(object, useAsFirstParameter);
+	}
+
+	/* ................................................................................................................. */
+	public String getName() {
+		return "Item values chart";
+	}
+
+	/* ................................................................................................................. */
+	/** returns an explanation of what the module does. */
+	public String getExplanation() {
+		return "Manages chart of values for items.";
+	}
+}
+
+/* ======================================================== */
+class ItemsChartWindow extends ChartWindow implements ChartListener, ActionListener {
+	private NumberArray values, clonedValues, weights;
+
+	String averageString = "";
+
+	String explanationString = "";
+
+	private ItemValuesChart ownerModule;
+
+	NumberForItem numberTask;
+
+	ItemsSource itemsSourceTask;
+
+	private int defaultNumberOfItems = 100;
+
+	int numberOfItems = 100;
+
+	private int numberOfItemsExamined = numberOfItems;
+
+	private int numberOfItemsCounted = numberOfItems;
+
+	private MesquiteMenuItemSpec numItemsItem;
+
+	private Taxa taxa;
+
+	Object auxiliary = null;
+
+	boolean auxFirst = false;
+
+	private int windowWidth = 0;
+
+	private int windowHeight = 0;
+
+	private int chartInsetTop = 10;
+
+	private int chartInsetBottom = 65;
+
+	private int chartInsetLeft = 0; // 10;
+
+	private int chartInsetRight = 20;
+
+	boolean itemsOnX = false;
+
+	boolean firstTimeThrough = true;
+
+	private String itemsOnXString = "Value (Y) by Items (X)";
+
+	private String itemsOnYString = "Number of Items (Y) by Values (X)";
+
+	private MesquiteString orientationName = new MesquiteString();
+
+	ChartMessages messagePane;
+
+	MesquiteBoolean orient;
+
+	MesquiteNumber sum, average, med1, med2;
+
+	private boolean wasDefinite = true;
+
+	private boolean assigned = false;
+
+	Panel scrollPanel;
+
+	MesquiteBoolean colorItems;
+
+	MesquiteDouble minInclude = new MesquiteDouble();
+
+	MesquiteDouble maxInclude = new MesquiteDouble();
+
+	MesquiteCommand xCommand;// NOT YET USED
+
+	MiniScroll scrollBox;// NOT YET USED
+
+	MesquiteChart chart;
+
+	MesquiteCommand recalcCommand;
+
+	MesquiteBoolean goAhead, autoCount;
+	MesquiteBoolean writeTableFile = new MesquiteBoolean(false);
+	boolean askedWriteTable = false;
+
+	Button recalcButton;
+
+	boolean liveChart = false;  //
+
+	boolean chartBeingCalculated = false;
+
+	public ItemsChartWindow(MesquiteModule requester, ItemValuesChart ownerModule) {
+		super(requester, true);
+		chartTitle = "Chart";
+
+		sum = new MesquiteNumber();
+		average = new MesquiteNumber();
+		med1 = new MesquiteNumber();
+		med2 = new MesquiteNumber();
+		values = new NumberArray(0);
+		orient = new MesquiteBoolean(true);
+		ownerModule.addMenuItem(null, "Exclude Values...", ownerModule.makeCommand("excludeValues", this));
+		MesquiteSubmenuSpec orientationSubmenu = ownerModule.addSubmenu(null, "Orientation");
+		orientationName.setValue(itemsOnYString);
+		orientationSubmenu.setSelected(orientationName);
+		ownerModule.addItemToSubmenu(null, orientationSubmenu, itemsOnYString, ownerModule.makeCommand("itemsByValues", this));
+		ownerModule.addItemToSubmenu(null, orientationSubmenu, itemsOnXString, ownerModule.makeCommand("valuesByItems", this));
+
+		colorItems = new MesquiteBoolean(true);
+
+		ownerModule.addCheckMenuItem(ownerModule.findMenuAmongEmployers("Colors"), "Color Items by Group", ownerModule.makeCommand("toggleColorItems", this), colorItems);
+
+		xCommand = ownerModule.makeCommand("setX", this); // NOT YET USED
+		scrollBox = new MiniScroll(xCommand, false, false, 0, 0, 0, "");// NOT YET USED
+
+		this.ownerModule = ownerModule; // or should this be requester???
+		chart = new MesquiteChart(ownerModule, 100, 0, ownerModule.charterTask.createCharter(this));
+
+		addToWindow(chart);
+		chart.setLocation(0, 0);
+		setChart(chart);
+
+		goAhead = new MesquiteBoolean(false);
+		autoCount = new MesquiteBoolean(true);
+		Panel f = chart.getField();
+		if (f == null)
+			autoCount.setValue(true);
+		else {
+			f.add(recalcButton = new Button("Recalculation needed"));
+			recalcButton.setBounds(10, 10, 140, 30);
+			recalcButton.setVisible(false);
+			recalcButton.setBackground(Color.white);
+			recalcButton.invalidate();
+			recalcButton.addActionListener(this);
+		}
+		recalcCommand = ownerModule.makeCommand("recalculate", this);
+
+		chart.deassignChart();
+		if (itemsOnX)
+			chart.constrainMinimumX(new MesquiteNumber(0));
+		messagePane = new ChartMessages(this);
+		addToWindow(messagePane);
+		messagePane.setVisible(true);
+		ownerModule.addCheckMenuItem(null, "Auto-recalculate", ownerModule.makeCommand("toggleAutoRecalc", this), autoCount);
+		ownerModule.addMenuItem(null, "Force Recalculation", ownerModule.makeCommand("forceRecalculate", this));
+		ownerModule.addCheckMenuItem(null, "Record Table to File", ownerModule.makeCommand("toggleWriteTableFile", this), writeTableFile);
+		resetTitle();
+		adjustComponentSizes();
+	}
+
+	public void setDefaultNumberOfItems(int def) {
+		defaultNumberOfItems = def;
+		numberOfItems = def;
+	}
+
+	/* ................................................................................................................... */
+	public void setAverageString(String t) {
+		averageString = t;
+	}
+
+	/* ................................................................................................................... */
+	public void setExplanationString(String t) {
+		explanationString = t;
+	}
+
+	/* ................................................................................................................... */
+	public void setChartVisible() {
+		adjustComponentSizes();
+		// chart.setBackground(Color.pink);
+		chart.setVisible(true);
+		blankChart();
+	}
+
+	/* ................................................................................................................... */
+	public void setScroller(Panel panel) {
+		if (panel == null)
+			return;
+		scrollPanel = panel;
+		chart.add(panel);
+		scrollPanel.setLocation(0, windowHeight - chartInsetBottom - scrollPanel.getBounds().height - chartInsetTop);
+		scrollPanel.setVisible(true);
+	}
+
+	/* ................................................................................................................. */
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot sup = super.getSnapshot(file);
+		sup.addLine("toggleAutoRecalc " + autoCount.toOffOnString());
+		if (itemsOnX)
+			sup.addLine("valuesByItems");
+		else
+			sup.addLine("itemsByValues");
+		sup.addLine("setChartType ", ownerModule.charterTask);
+		if (minInclude.isCombinable() || maxInclude.isCombinable()) {
+			sup.addLine("excludeValues " + minInclude + "  " + maxInclude);
+		}
+		// if (highlightName !=null)
+		// sup.addLine("highlight " + StringUtil.tokenize(highlightName));
+		sup.addLine("toggleColorItems " + colorItems.toOffOnString());
+		if (MesquiteInteger.isCombinable(numberOfItems))
+			sup.addLine("setNumberItems " + numberOfItems);
+		return sup;
+	}
+
+	/* ................................................................................................................. */
+	public void setOrientation(boolean iOnX) { // orientation stored in chart as 0 = items by values; 1 = values by items
+		itemsOnX = iOnX;
+		if (itemsOnX) {
+			chart.constrainMinimumX(new MesquiteNumber(0));
+			chart.setOrientation(1);
+		}
+		else {
+			chart.deConstrainMinimumX();
+			chart.setOrientation(0);
+		}
+		if (!MesquiteThread.isScripting())
+			recalcChart();
+	}
+
+	/* ................................................................................................................. */
+	public boolean getOrientation() {
+		return itemsOnX;
+	}
+
+	/* ................................................................................................................. */
+	public void setCharter(Charter charter) {
+		chart.setCharter(charter);
+	}
+
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	/* ................................................................................................................. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the chart drawing module", "[module name]", commandName, "setChartType")) {
+			String newc = ParseUtil.getFirstToken(arguments, pos);
+			if (ownerModule.charterTask.getClass() != null && (ownerModule.charterTask.nameMatches(newc))) // already have this
+				return ownerModule.charterTask;
+
+			DrawChart temp = (DrawChart) ownerModule.replaceEmployee(DrawChart.class, arguments, "Type of chart", ownerModule.charterTask);
+			if (temp != null) {
+				ownerModule.charterTask = temp;
+
+				setCharter(ownerModule.charterTask.createCharter(this));
+				ownerModule.parametersChanged();
+				return ownerModule.charterTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns median 1", null, commandName, "getMedian1")) {
+			return med1;
+
+		}
+		else if (checker.compare(this.getClass(), "Returns median 2", null, commandName, "getMedian2")) {
+			return med2;
+
+		}
+		else if (checker.compare(this.getClass(), "Returns average", null, commandName, "getAverage")) {
+			return average;
+
+		}
+		else if (checker.compare(this.getClass(), "Returns values as tabbed line", null, commandName, "getValuesTabbed")) {
+			if (values == null)
+				return null;
+				StringBuffer s = new StringBuffer();  
+				for (int i =0; i<values.getSize(); i++){
+					if (i != 0)
+						s.append("\t");
+					s.append(values.toString(i));
+				}
+				s.append(StringUtil.lineEnding());
+			return s.toString();
+		}
+
+		else if (checker.compare(this.getClass(), "Sets whether or not to recalculate automatically when needed", "[on=auto; off]", commandName, "toggleAutoRecalc")) {
+			Parser parser = new Parser();
+			autoCount.toggleValue(parser.getFirstToken(arguments));
+			if (autoCount.getValue()) {
+				recalcButton.setVisible(false);
+				doCounts();
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to output a table during calculations", "[on=auto; off]", commandName, "toggleWriteTableFile")) {
+			Parser parser = new Parser();
+			boolean c = writeTableFile.getValue();
+			writeTableFile.toggleValue(parser.getFirstToken(arguments));
+			if (writeTableFile.getValue()) {
+				tableFile = new MesquiteFile();
+				if (MesquiteThread.isScripting()){
+					tableFile.changeLocation(ownerModule.getProject().getHomeDirectoryName(), "Table.txt");
+				}
+				else {
+					if (StringUtil.blank(tableFile.getFileName()))
+						tableFile.setFileName("Table.txt");
+					tableFile.changeLocation("Record Table to File");
+				}
+				if (!c && !MesquiteThread.isScripting())
+					doCounts();
+			}
+			else
+				tableFile = null;
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Sets the values to exclude", "[min value included][max value included]", commandName, "excludeValues")) {
+			pos.setValue(0);
+			double min = MesquiteDouble.fromString(arguments, pos);
+			double max = MesquiteDouble.fromString(arguments, pos);
+			MesquiteDouble minD = new MesquiteDouble(minInclude.getValue());
+			MesquiteDouble maxD = new MesquiteDouble(maxInclude.getValue());
+			if (!MesquiteDouble.isCombinable(min) && !MesquiteDouble.isCombinable(max)) {
+				if (MesquiteThread.isScripting())
+					return null;
+				if (!QueryDialogs.queryTwoDoubles(this, "Exclude Values", "Exclude values less than:", minD, "Exclude values greater than:", maxD)) {
+					return null;
+				}
+			}
+			else {
+				minD.setValue(min);
+				maxD.setValue(max);
+			}
+			if (minD.isCombinable() && maxD.isCombinable() && minD.getValue() > maxD.getValue()) {
+				ownerModule.discreetAlert("Sorry, minimum can't be greater than maximum");
+				return null;
+			}
+			minInclude.setValue(minD.getValue());
+			maxInclude.setValue(maxD.getValue());
+			ownerModule.parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Requests recalculation", null, commandName, "recalculate")) {
+			doCounts();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Requests recalculation", null, commandName, "forceRecalculate")) {
+			if (recalcButton.isVisible()) {
+				recalcButton.setVisible(false);
+			}
+			goAhead.setValue(true);
+			doCounts();
+			contentsChanged();
+
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Sets which of a series of items is shown (appropriate when there could be a series of alternative values, e.g. for different characters or trees)", "[item number]", commandName, "setX")) {// NOT YET USED
+			if (numberTask instanceof Incrementable) {
+				Incrementable inc = (Incrementable) numberTask;
+				int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0)) - 1; // assuming itemType is 0 based internally and 1 based to user
+				if (!MesquiteInteger.isCombinable(ic))
+					ic = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Choose ", "choose:", 1); // TODO have something more intelligent here
+				if (MesquiteInteger.isCombinable(ic) && (ic >= inc.getMin()) && (ic <= inc.getMax())) {
+					inc.setCurrent(ic);
+					if (!MesquiteThread.isScripting()) {
+						doCounts();
+						contentsChanged();
+					}
+				}
+
+			}
+		}
+		/*
+		 * else if (checker.compare(this.getClass(), "Sets whether to use any available weights for the items", "[on or off]", commandName, "toggleUseWeights")) { boolean current = useWeights.getValue(); useWeights.toggleValue(ParseUtil.getFirstToken(arguments, pos)); if (current!=useWeights.getValue() && !MesquiteThread.isScripting()) getWeights(); }
+		 */
+		else if (checker.compare(this.getClass(), "Sets whether to color the items in the chart according to any natural item colors", "[on or off]", commandName, "toggleColorItems")) {
+			boolean current = colorItems.getValue();
+			colorItems.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (current != colorItems.getValue() && !MesquiteThread.isScripting())
+				recalcChart();
+		}
+		else if (checker.compare(this.getClass(), "[no longer used]", null, commandName, "toggleOrientation")) {
+			if (StringUtil.blank(arguments))
+				orient.toggleValue();
+			else {
+				String s = ParseUtil.getFirstToken(arguments, pos);
+				if ("on".equalsIgnoreCase(s))
+					orient.setValue(true);
+				else if ("off".equalsIgnoreCase(s))
+					orient.setValue(false);
+			}
+			setOrientation(orient.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to show values on the Y axis and items (in order) on the X axis", null, commandName, "valuesByItems")) {
+			itemsOnX = true;
+			orient.setValue(itemsOnX);
+			orientationName.setValue(itemsOnXString);
+			setOrientation(itemsOnX);
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to show the number of items on the Y axis and the values on the X axis", null, commandName, "itemsByValues")) {
+			itemsOnX = false;
+			orient.setValue(itemsOnX);
+			orientationName.setValue(itemsOnYString);
+			setOrientation(itemsOnX);
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of items (appropriate when the item source has an indefinite number)", "[number of items]", commandName, "setNumberItems")) {
+			// TODO: this should first check if arguments say
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Set Number of " + itemsSourceTask.getItemTypeNamePlural(), "Number of " + itemsSourceTask.getItemTypeNamePlural(), numberOfItems, 0, MesquiteInteger.infinite);
+			if (MesquiteInteger.isCombinable(newNum) && newNum > 0) {
+				assigned = true;
+				if (newNum != numberOfItems) {
+					numberOfItems = newNum;
+					if (!MesquiteThread.isScripting()) {
+						ownerModule.doCounts();
+						contentsChanged();
+					}
+				}
+			}
+		}
+		else
+			return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* ................................................................................................................... */
+	public void pointMouseDown(MesquiteChart chart, int whichPoint, MesquiteNumber valueX, MesquiteNumber valueY, int x, int y, int modifiers, String message) {
+		/*
+		 * String name = chart.getName(whichPoint); if (name ==null){ Object item = itemsSourceTask.getItem(taxa, whichPoint, false); if (item instanceof Listable) name = ((Listable)item).getName(); } if (name==null) name = "#" + whichPoint; name += "\nx " + chart.getXArray().toString(whichPoint) + "\ny " + chart.getYArray().toString(whichPoint); if (numberTaskZ!=null) name += "\ncolor " + chart.getZArray().toString(whichPoint);
+		 */
+		String name = "";
+		if (MesquiteInteger.isCombinable(whichPoint)) {
+			if (itemsOnX) {
+				name = chart.getName(whichPoint);
+				if (name == null) {
+					Object item = itemsSourceTask.getItem(taxa, whichPoint);
+					if (item instanceof Listable)
+						name = ((Listable) item).getName();
+				}
+				if (name == null)
+					name = itemsSourceTask.getItemTypeName() + " #" + (whichPoint + 1) + "\n"; // todo: items source should have toExternal method for zero-based internal to 1-based external
+				if (valueY != null)
+					name += " with value " + valueY + "\n";
+			}
+			else {
+				name = itemsSourceTask.getItemTypeNamePlural() + "\n";
+				if (valueY != null)
+					name += "Number: " + valueY + "\n";
+				if (valueX != null)
+					name += "Value: " + valueX + "\n";
+			}
+		}
+		if (message != null)
+			name += message;
+		chart.showQuickMessage(whichPoint, x, y, name);
+	}
+
+	/* ................................................................................................................... */
+	public void pointMouseUp(MesquiteChart chart, int whichPoint, int x, int y, int modifiers, String message) {
+		chart.hideQuickMessage();
+	}
+
+	/* ................................................................................................................. */
+	public void selectAllGraphicsPanel() {
+		// this paradoxical deselection is done because chart treats all as selected if none are
+		if (itemsSourceTask.getSelectionable() != null) {
+			itemsSourceTask.getSelectionable().deselectAll();
+			itemsSourceTask.getSelectionable().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+		else {
+			chart.deselectAllPoints();
+			chart.repaint();
+			chart.getField().repaint();
+		}
+	}
+
+	/* ................................................................................................................... */
+	public void setTaxa(Taxa taxa) {
+		this.taxa = taxa;
+	}
+
+	/* ................................................................................................................... */
+	public void setItemsSource(ItemsSource itemsSourceTask) {
+		this.itemsSourceTask = itemsSourceTask;
+		if (itemsSourceTask != null)
+			itemsSourceTask.setEnableWeights(true);
+		if (ownerModule.charterTask != null && itemsSourceTask != null) {
+			ownerModule.charterTask.pointsAreSelectable(itemsSourceTask.getSelectionable() != null, itemsSourceTask.getSelectionable(), true);
+		}
+	}
+
+	MesquiteFile tableFile = null;
+	/* ................................................................................................................... */
+	public void setNumberTask(NumberForItem numberTask) {
+		if (!ownerModule.startedAsScripting) {
+			if (this.numberTask == null || (!this.numberTask.returnsMultipleValues() && numberTask.returnsMultipleValues())){
+			if (numberTask.returnsMultipleValues()) {
+				writeTableFile.setValue(AlertDialog.query(this, "Save Table?", "The calculator chosen can return multiple values for each item.  Should Mesquite save a table of the results in a file?"));
+				if (writeTableFile.getValue()){
+					tableFile = new MesquiteFile();
+					tableFile.setFileName("Table.txt");
+					tableFile.changeLocation("Record Table to File");
+				}
+
+			}
+		}
+		}
+		this.numberTask = numberTask;
+	}
+
+	/* ................................................................................................................... */
+	public void setAuxiliary(Object object, boolean useAsFirstParameter) {
+		auxiliary = object;
+		auxFirst = useAsFirstParameter;
+	}
+
+	/* ................................................................................................................... */
+	private void resetSizes(Taxa taxa) {
+		if (itemsSourceTask == null)
+			return;
+		int numItems = itemsSourceTask.getNumberOfItems(taxa);
+
+		if (!MesquiteInteger.isFinite(numItems)) {
+			if (wasDefinite && !assigned) {
+				numberOfItems = defaultNumberOfItems;
+				if (!MesquiteThread.isScripting()) {
+					numberOfItems = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Number of " + itemsSourceTask.getItemTypeNamePlural(), "Number of " + itemsSourceTask.getItemTypeNamePlural() + " for chart", numberOfItems);
+					if (!MesquiteInteger.isCombinable(numberOfItems))
+						numberOfItems = defaultNumberOfItems;
+				}
+			}
+			wasDefinite = false;
+			assigned = true;
+			if (numItemsItem == null) {
+				numItemsItem = ownerModule.addMenuItem("Number of  " + itemsSourceTask.getItemTypeNamePlural() + "...", ownerModule.makeCommand("setNumberItems", this));
+				ownerModule.resetContainingMenuBar();
+			}
+		}
+		else {
+			if (numItemsItem != null) {
+				ownerModule.deleteMenuItem(numItemsItem);
+				ownerModule.resetContainingMenuBar();
+				numItemsItem = null;
+			}
+			wasDefinite = true;
+			assigned = false;
+			numberOfItems = numItems;
+		}
+		resetSizeTo(numberOfItems);
+	}
+
+	private void resetSizeTo(int num) {
+		if (!MesquiteInteger.isCombinable(num)) { // finite but indefinite; set storage to 100
+			values.resetSize(100);
+			if (weights != null)
+				weights.resetSize(100);
+		}
+		else {
+			values.resetSize(num);
+			if (weights != null)
+				weights.resetSize(num);
+		}
+	}
+
+	private void checkSizes(int num) {
+		if (num >= values.getSize()) {
+			values.resetSize(values.getSize() + 100);
+			if (weights != null)
+				weights.resetSize(weights.getSize() + 100);
+		}
+	}
+
+	int countt = 0;
+
+	boolean weighted;
+
+	/********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** [...]
+	 * ................................................................................................................. public void getWeights() { if (itemsSourceTask == null || !useWeights.getValue()) return; MesquiteModule.incrementMenuResetSuppression(); weighted = useWeights.getValue() && itemsSourceTask.itemsHaveWeights(taxa); if (weighted) { if (weights == null) weights = new NumberArray(numberOfItems); else if (weights!=null) weights.resetSize(numberOfItems); weights.deassignArray() [...]
+	 * weights.setValue(im, itemsSourceTask.getItemWeight(taxa, im); recalcChart(); }
+	 * 
+	 * MesquiteModule.decrementMenuResetSuppression(); } /*.................................................................................................................
+	 */
+	public void actionPerformed(ActionEvent e) {
+		String buttonLabel = e.getActionCommand();
+		if ("Recalculation needed".equalsIgnoreCase(buttonLabel)) { // Recalc button is pressed
+			goAhead.setValue(true);
+			recalcCommand.doItMainThread(null, null, this); // command invoked
+		}
+	}
+
+	/* ................................................................................................................. */
+	private boolean waitOnCalculation() {
+		if (autoCount.getValue() || MesquiteThread.isScripting()) { // set to autocount; go ahead and do count
+			if (recalcButton.isVisible())
+				recalcButton.setVisible(false);
+			return false;
+		}
+		else { // counts only if goAhead flag is set, which it will be following click on button
+			if (goAhead.getValue()) {
+				goAhead.setValue(false);
+				if (recalcButton.isVisible())
+					recalcButton.setVisible(false);
+				return false;
+			}
+			else if (!recalcButton.isVisible())
+				recalcButton.setVisible(true);
+			if (chart.getNumPoints() > 0)
+				chart.deassignChart();
+			recalcButton.setSize(recalcButton.getPreferredSize());
+			recalcButton.invalidate();
+			recalcButton.doLayout();
+			recalcButton.repaint();
+		}
+		return true;
+	}
+	void showRecalcButton(){
+		if (!recalcButton.isVisible())
+			recalcButton.setVisible(true);
+		recalcButton.setSize(recalcButton.getPreferredSize());
+		recalcButton.invalidate();
+		recalcButton.doLayout();
+		recalcButton.repaint();
+	}
+	/* ................................................................................................................. */
+	public void doCounts() {
+		doCounts(MesquiteInteger.unassigned, MesquiteInteger.unassigned, true);
+	}
+
+	/* ................................................................................................................. */
+	public void doCounts(int firstItem, int lastItem, boolean fullCount) {
+		if (chartBeingCalculated)
+			return;
+		if (values == null)
+			return;
+		if (itemsSourceTask == null)
+			return;
+		if (numberTask == null)
+			return;
+		if (!ownerModule.calculationsEnabled)
+			return;
+		boolean countAll = fullCount || firstTimeThrough;
+		MesquiteModule.incrementMenuResetSuppression();
+		resetSizes(taxa);
+		if (waitOnCalculation()) {
+			blankChart();
+			MesquiteModule.decrementMenuResetSuppression();
+			return;
+		}
+		chartBeingCalculated = true;
+		Object item;
+		int startItem, endItem;
+
+		if (countAll) {
+			med1.setToUnassigned();
+			med2.setToUnassigned();
+			blankChart();
+			values.deassignArray();
+
+			weighted = itemsSourceTask.itemsHaveWeights(taxa);
+			if (weighted) {
+				if (weights == null) {
+					if (MesquiteInteger.isCombinable(numberOfItems))
+						weights = new NumberArray(numberOfItems);
+					else
+						weights = new NumberArray(100);
+				}
+				weights.deassignArray();
+			}
+			numberOfItemsCounted = 0;
+			sum.setValue(0.0);
+			average.setValue(0.0);
+		}
+
+		if (MesquiteInteger.isUnassigned(firstItem))
+			startItem = 0;
+		else
+			startItem = firstItem;
+		if (MesquiteInteger.isUnassigned(lastItem))
+			endItem = numberOfItems - 1;
+		else
+			endItem = lastItem;
+		int numberOfItemsExaminedThisTime = endItem - startItem + 1;
+		numberOfItemsExamined = numberOfItems;
+
+		resetSizeTo(numberOfItemsExamined);
+		// startProfiling();
+		int everyWhich = 50;
+		// if (everyWhich<1)
+		// everyWhich = 1;
+		MesquiteNumber cNum = new MesquiteNumber();
+
+		ProgressIndicator prog = null;
+		long startTime = System.currentTimeMillis();
+		boolean progOn = false;
+
+		int code = 0;
+		int im;
+		int lastAdded = startItem - 1;
+		if (writeTableFile != null && writeTableFile.getValue()){
+			tableFile.openWriting(true);
+		}
+		try {
+			int oldnumberOfItemsExamined = numberOfItemsExamined;
+			String numS = MesquiteInteger.toString(numberOfItemsExamined);
+			if (numberOfItemsExamined == MesquiteInteger.finite)
+				numS = "an undetermined number";
+			if (countAll)
+				recalcChartInit();
+			long lastProgressTime = System.currentTimeMillis();
+			MesquiteDialog.hideWizardForCalculation();
+			for (im = startItem; im <= endItem && (prog == null || !prog.isAborted()); im++) {
+
+				if (numberOfItemsExamined != oldnumberOfItemsExamined) {
+					numS = MesquiteInteger.toString(numberOfItemsExamined);
+					if (numberOfItemsExamined == MesquiteInteger.finite)
+						numS = "an undetermined number";
+					oldnumberOfItemsExamined = numberOfItemsExamined;
+				}
+				code = 1;
+				if (!progOn && System.currentTimeMillis() - startTime > 5000) {
+					prog = new ProgressIndicator(ownerModule.getProject(), "Calculating Chart", "Calculating value for " + itemsSourceTask.getItemTypeNamePlural(), numberOfItemsExamined, true);
+					prog.start();
+					progOn = true;
+				}
+				else if (progOn && System.currentTimeMillis()-lastProgressTime>200) {
+					prog.setCurrentValue(im);
+					prog.setText("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im + 1) + " of " + numS, false);
+					lastProgressTime = System.currentTimeMillis();
+				}
+				if (im % 5 == 0)
+					CommandRecord.tick("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im + 1) + " of " + numS);
+				item = itemsSourceTask.getItem(taxa, im);
+				code = 2;
+				if (item == null) {
+					// null item hit; source may have unexpectedly run out; reset total expected
+					assigned = false;
+					numberOfItemsExamined = im;
+					endItem = im - 1;
+
+					resetSizeTo(im);
+					if (prog != null && progOn) {
+						prog.goAway();
+					}
+				}
+				else {
+					checkSizes(im);
+					if (weighted) {
+						weights.setValue(im, itemsSourceTask.getItemWeight(taxa, im));
+					}
+					code = 3;
+					cNum.setToUnassigned();
+
+					if (auxFirst)
+						numberTask.calculateNumber(auxiliary, item, cNum, null);
+					else
+						numberTask.calculateNumber(item, auxiliary, cNum, null);
+					if (cNum.isCombinable() && minInclude.isCombinable() && cNum.isLessThan(minInclude.getValue()))
+						cNum.setToUnassigned();
+					if (cNum.isCombinable() && maxInclude.isCombinable() && cNum.isMoreThan(maxInclude.getValue()))
+						cNum.setToUnassigned();
+
+					if (writeTableFile != null && writeTableFile.getValue()){
+						tableFile.writeLine(Integer.toString(im+1) + '\t' + cNum.toStringWithDetails());
+					}
+					code = 4;
+					if (values != null)
+						values.setValue(im, cNum);
+					code = 5;
+					if (cNum.isCombinable())
+						numberOfItemsCounted++;
+
+					sum.add(cNum);
+					code = 6;
+				}
+				if (liveChart && im % everyWhich == 0 && im > startItem) {
+					addPointsToChart(lastAdded + 1, im);
+					lastAdded = im;
+				}
+			}
+			if (prog != null && prog.isAborted()) {
+				if (!AlertDialog.query(ownerModule.containerOfModule(), "Calculations Stopped", "Calculations stopped before all " + itemsSourceTask.getItemTypeNamePlural() + " were examined.  Do you want to display the results?", "Display", "Discard", 1)) {
+					// here we discard results, and display a blank chart
+					autoCount.setValue(false);
+					waitOnCalculation();
+					blankChart();
+					prog.goAway();
+					chartBeingCalculated = false;
+					MesquiteModule.decrementMenuResetSuppression();
+					return;
+				}
+				assigned = false;
+				numberOfItemsExamined = im; // reset the number of items to the actual number processed
+				endItem = im;
+				values.resetSize(numberOfItemsExamined);
+			}
+
+		} catch (OutOfMemoryError e) {
+			MesquiteMessage.println("Error in ItemValuesChart " + e + " ===== " + code + " -- insufficient memory.   See file memory.txt in the Mesquite_Folder.");
+		}
+		if (writeTableFile != null && writeTableFile.getValue())
+			tableFile.closeWriting();
+		addPointsToChart(lastAdded + 1, endItem + 1);
+
+		if (progOn)
+			prog.goAway();
+		ownerModule.charterTask.pointsAreSelectable(itemsSourceTask.getSelectionable() != null, itemsSourceTask.getSelectionable(), true);
+		if (clonedValues == null)
+			clonedValues = values.cloneArray();
+		else
+			clonedValues.setToClone(values);
+		clonedValues.sortAndPlaceMedian(med1, med2);
+		if (countAll)
+			recalcChart();
+		else {
+			resetMessagePaneText();
+			messagePane.repaint();
+		}
+		MesquiteModule.decrementMenuResetSuppression();
+		firstTimeThrough = false;
+		chartBeingCalculated = false;
+	}
+
+	/* ................................................................................................................. */
+	public String getTextContents() {
+		String s = super.getTextContents();
+		if (s == null)
+			return null;
+		String m = messagePane.getText();
+		if (m == null)
+			return s;
+		return m + StringUtil.lineEnding() + StringUtil.lineEnding() + s;
+	}
+
+	/* ................................................................................................................. */
+	public void resetMessagePaneText() {
+		average.setValue(sum);
+		average.divideBy(numberOfItemsCounted);
+		// clonedValues.sortAndPlaceMedian(med1, med2);
+		String medianString = "";
+		if (med1.isCombinable() && med2.isCombinable() && !med1.equals(med2))
+			medianString = "; Median: " + med1 + " to " + med2;
+		else if (med1.isCombinable())
+			medianString = "; Median: " + med1;
+		else if (med2.isCombinable())
+			medianString = "; Median: " + med2;
+		averageString = "Average " + numberTask.getNameOfValueCalculated() + ": " + average.toString() + medianString + "  (n=" + numberOfItemsCounted + "  " + itemsSourceTask.getItemTypeNamePlural() + ")";
+		if (minInclude.isCombinable() || maxInclude.isCombinable()) {
+			averageString += "\nValues";
+			if (minInclude.isCombinable())
+				averageString += " less than " + minInclude;
+			if (minInclude.isCombinable() && maxInclude.isCombinable())
+				averageString += " or ";
+			if (maxInclude.isCombinable())
+				averageString += " greater than " + maxInclude;
+			averageString += " are excluded ";
+		}
+		explanationString = "Source of  " + itemsSourceTask.getItemTypeNamePlural() + ": " + itemsSourceTask.getNameAndParameters();
+		if (!StringUtil.blank(ownerModule.charterTask.getParameters()))
+			explanationString += "\nChart:  " + ownerModule.charterTask.getParameters();
+		// explanationString += "\nValues calculated: " + numberTask.getNameAndParameters();
+		explanationString += "\nDetails of items plotted:\n" + itemsSourceTask.accumulateParameters("   ");
+		explanationString += "\nDetails of  calculated values:\n" + numberTask.accumulateParameters("   ");
+		messagePane.setText(averageString + "\n" + explanationString);
+	}
+
+	/* ................................................................................................................. */
+	public boolean recalcChartInit() {
+		chart.deassignChart();
+		if (numberTask == null || itemsSourceTask == null)
+			return false;
+		if (!itemsOnX) {
+			String valueString = "Number";
+			if (chart.getCharter()!= null && chart.getCharter().getShowPercent())
+				valueString = "Percent";
+			chart.setXAxisName(numberTask.getNameOfValueCalculated());
+			if (weighted)
+				chart.setYAxisName("Weighted "+valueString +" of  " + itemsSourceTask.getItemTypeNamePlural() + chart.getYAxisNameSuffix());
+			else
+				chart.setYAxisName(valueString + " of  " + itemsSourceTask.getItemTypeNamePlural()+ chart.getYAxisNameSuffix());
+		}
+		else {
+
+			if (chart.getCharter()!= null && chart.getCharter().getShowPercent())
+				chart.setYAxisName(numberTask.getNameOfValueCalculated() + " (Percentage)"+ chart.getYAxisNameSuffix());
+			else
+				chart.setYAxisName(numberTask.getNameOfValueCalculated()+ chart.getYAxisNameSuffix());
+			chart.setXAxisName(itemsSourceTask.getItemTypeName());
+		}
+
+		if (colorItems.getValue())
+			itemsSourceTask.prepareItemColors(taxa);
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	public void addPointsToChart(int startValue, int endValue) {
+		MesquiteNumber resultX = new MesquiteNumber();
+		MesquiteNumber resultY = new MesquiteNumber();
+		resultY.setValue(1);
+		/*
+		 * if (highlightsExist && hE!=null) explanationString += " [Highlighted " + hE + "]";
+		 */
+
+		chart.getCharter().setSuspendDrawing(true);
+		chart.getCharter().setSuspendChartCalculations(true);
+		for (int i = startValue; i < endValue; i++) {
+			if (i % 100 == 0)
+				CommandRecord.tick("Constructing chart; adding item " + i);
+			if (weighted && weights != null && weights.isCombinable(i))
+				weights.placeValue(i, resultY);
+			if (!itemsOnX) {
+				if (!values.isCombinable(i))
+					resultX.setToUnassigned();
+				else
+					values.placeValue(i, resultX);
+				int point = chart.addPoint(resultX, resultY);
+				if (colorItems.getValue()) {
+					Color c = itemsSourceTask.getItemColor(taxa, i);
+					if (c != null) {
+						chart.setColor(point, c);
+					}
+				}
+				
+			}
+			else {
+				int j = i + 1; // TODO: this shouldn't always bump by one (zero based internal to 1 based for user)
+				if (!values.isCombinable(i))
+					resultY.setToUnassigned();
+				else
+					values.placeValue(i, resultY);
+				resultX.setValue(j);
+				int point = chart.addPoint(resultX, resultY);
+				if (colorItems.getValue()) {
+					Color c = itemsSourceTask.getItemColor(taxa, i);
+					if (c != null) {
+						chart.setColor(point, c);
+					}
+				}
+
+			}
+		}
+		chart.getCharter().setSuspendDrawing(false);
+		chart.getCharter().setSuspendChartCalculations(false);
+		resetMessagePaneText();
+		chart.munch();
+		contentsChanged();
+		messagePane.repaint();
+	}
+
+	/* ................................................................................................................. */
+	public void recalcChart() {
+		if (!recalcChartInit())
+			return;
+		addPointsToChart(0, values.getSize());
+
+	}
+
+	/* ................................................................................................................. */
+	int counter = 0;
+
+	private void adjustComponentSizes() {
+		windowHeight = getHeight();
+		windowWidth = getWidth();
+		chart.setChartSize(windowWidth - chartInsetRight - chartInsetLeft, windowHeight - chartInsetTop - chartInsetBottom);
+		chart.setLocation(chartInsetLeft, chartInsetTop);
+		messagePane.setLocation(0, windowHeight - chartInsetBottom);
+		messagePane.setSize(windowWidth, chartInsetBottom);
+		if (scrollPanel != null)
+			scrollPanel.setLocation(0, windowHeight - chartInsetBottom - scrollPanel.getBounds().height - chartInsetTop);
+		recalcButton.setSize(recalcButton.getPreferredSize());
+	}
+
+	/* ................................................................................................................. */
+	public void windowResized() {
+		super.windowResized();
+		if (chart == null || messagePane == null)
+			return;
+		if ((getHeight() != windowHeight) || (getWidth() != windowWidth) || (chart.getChartHeight() != windowHeight - chartInsetTop - chartInsetBottom) || (chart.getChartWidth() != windowWidth - chartInsetRight - chartInsetLeft)) {
+			adjustComponentSizes();
+		}
+		recalcButton.setSize(recalcButton.getPreferredSize());
+	}
+}
+
+/* ========================================================= */
+class ChartMessages extends TextArea {
+	ItemsChartWindow window;
+
+	public ChartMessages(ItemsChartWindow window) {
+		super("", 3, 3, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		this.window = window;
+	}
+
+	public void setText(String t) {
+		super.setText(t);
+		// setSelectionStart(0);
+		// setSelectionEnd(0);
+	}
+}
+
diff --git a/Source/mesquite/charts/ItemsBiplot/ItemsBiplot.java b/Source/mesquite/charts/ItemsBiplot/ItemsBiplot.java
new file mode 100644
index 0000000..947287b
--- /dev/null
+++ b/Source/mesquite/charts/ItemsBiplot/ItemsBiplot.java
@@ -0,0 +1,1193 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.ItemsBiplot;
+/*~~  */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* A module to supervise scattergrams of items.  This coordinates calculations; Scattergram module handles most graphics.*/
+
+public class ItemsBiplot extends ItemsBiplotter    {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.charts.Scattergram.Scattergram.class, getName() + " needs a module to draw the chart.",
+		"The chart drawing module is selected automatically");
+	}
+	public DrawChart charterTask;
+	ChartWindow cWindow;
+	int suspend = 0;
+	boolean doCountPending = false;
+	boolean calculationsEnabled = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charterTask = (DrawChart)hireNamedEmployee(DrawChart.class, "#mesquite.charts.Scattergram.Scattergram");
+		if (charterTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m == charterTask)
+			iQuit();
+	}
+	
+	/*.................................................................................................................*/
+	public ChartWindow makeChartWindow(MesquiteModule requester) {
+		cWindow =  new ItemsBiplotWindow(requester, this);
+		return cWindow;
+	}
+	
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (cWindow==null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("getWindow"); 
+		temp.addLine("tell It"); 
+		Snapshot sn = cWindow.getSnapshot(file);
+		temp.incorporate(sn, true);
+		temp.addLine("endTell"); 
+		temp.addLine("enableCalculations"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return charterTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the window in which the chart appears", null, commandName, "getWindow")) {
+			return cWindow;
+		}
+		else if (checker.compare(this.getClass(), "Increments the suspension level on the calculations", null, commandName, "suspendCalculations")){
+			incrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Decrements the suspension level on the calculations", null, commandName, "resumeCalculations")){
+			decrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Enables the calculations", null, commandName, "enableCalculations")){
+			calculationsEnabled = true;
+			doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Requests that calculations be performed", null, commandName, "doCounts")){
+			if (suspend>0)
+				doCountPending=true;
+			else  {
+				doCounts();
+				doCountPending=false;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	
+	public void incrementSuspension(){
+		suspend++;
+	}
+	
+	public void decrementSuspension(){
+		suspend--;
+		if (suspend<=0 && doCountPending && cWindow!=null) {
+			suspend = 0;
+			doCountPending=false;
+			doCounts();
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if(cWindow == null)
+			return;
+		if (employee == charterTask)
+			((ItemsBiplotWindow)cWindow).recalcChart();
+		else
+			doCounts();
+		
+	}
+	/*...................................................................................................................*/
+	public void doCounts( int firstItem, int lastItem, boolean fullCount){
+		if (cWindow!=null && !isDoomed()) {
+			if (suspend>0)
+				doCountPending=true;
+			else  {
+				((ItemsBiplotWindow)cWindow).doCounts(firstItem, lastItem, fullCount);
+				doCountPending=false;
+			}
+		}
+	}
+	/*...................................................................................................................*/
+	public void doCounts(){
+		doCounts(MesquiteInteger.unassigned, MesquiteInteger.unassigned,true);
+	}
+	public void setTaxa(Taxa taxa){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setTaxa(taxa);
+	}
+	/*...................................................................................................................*/
+	public void setShowNames( boolean showNames){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setShowNames(showNames);
+	}
+	/*...................................................................................................................*/
+	public void setItemsSource( ItemsSource itemsSourceTask){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setItemsSource(itemsSourceTask);
+		
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskX(NumberForItem numberTask){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setNumberTaskX(numberTask);
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskY(NumberForItem numberTask){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setNumberTaskY(numberTask);
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskZ(NumberForItem numberTask){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setNumberTaskZ(numberTask);
+	}
+	/*...................................................................................................................*/
+	/*.................................................................................................................*/
+	public void setDefaultNumberOfItems(int def){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setDefaultNumberOfItems(def);
+	}
+	/*...................................................................................................................*/
+	public void setAuxiliary(Object object, boolean useAsFirstParameter){
+		if (cWindow!=null)
+			((ItemsBiplotWindow)cWindow).setAuxiliary(object, useAsFirstParameter);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Items bi-plot";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Makes a chart comparing two values for each of many items.";
+	}
+	
+}
+
+class ItemsBiplotWindow extends ChartWindow implements ChartListener, ActionListener {
+	private NumberArray valuesX, valuesY, valuesZ;
+	MesquiteNumber sum;
+	private boolean wasDefinite = true;
+	private boolean assigned = false;
+	public String explanationString = "";
+	NumberForItem numberTaskX, numberTaskY, numberTaskZ;
+	ItemsSource itemsSourceTask;
+	private int defaultNumberOfItems = 100;
+	int numberOfItems = 100;
+	int numberOfItemsUsed = numberOfItems;
+	private MesquiteMenuItemSpec numItemsItem;
+	private Taxa taxa;
+	Object auxiliary = null;
+	boolean auxFirst = false;
+	//MesquiteNumber constrainedMinX, constrainedMaxX, constrainedMinY, constrainedMaxY; REMOVED temporarily(?)
+	
+	public MesquiteCommand setXCommand, setYCommand;
+	public int currentX =0;
+	public int currentY= 0;
+	String xString, yString, zString;
+	
+	private int windowWidth=0;
+	private int windowHeight=0;
+	private int chartInsetTop = 10;
+	private int chartInsetBottom = 60;
+	private int chartInsetLeft = 0;
+	private int chartInsetRight = 20;
+	boolean showNames = false;
+	ItemsBiplot ownerModule;
+	MesquiteNumber utilNum;
+	//MesquiteInteger positivize;  REMOVED temporarily(?)
+	//MesquiteString positivizeName;
+	TChartMessages messagePane;
+//	MesquiteBoolean colorItems; REMOVED temporarily(?)
+	DoubleMiniScroll scrollBox;
+	boolean firstTime = true;
+	ChartTool queryTool;
+	MesquiteChart chart;
+	MesquiteCommand recalcCommand;
+	boolean firstTimeThrough = true;
+	boolean liveChart = true;
+	
+	MesquiteBoolean goAhead, autoCount;
+	Button recalcButton;
+	
+	public ItemsBiplotWindow (MesquiteModule requester, ItemsBiplot ownerModule) {
+		super(requester,true); //infobar
+		setWindowSize(400,400);
+		this.ownerModule = ownerModule;
+		firstTime=true;
+		chartTitle = "Bi-plot";
+		valuesX = new NumberArray(0);
+		valuesY = new NumberArray(0);
+		valuesZ = new NumberArray(0);
+		/*
+		 constrainedMinX = new MesquiteNumber();
+		 constrainedMaxX = new MesquiteNumber();
+		 constrainedMinY = new MesquiteNumber();
+		 constrainedMaxY = new MesquiteNumber();
+		 positivize = new MesquiteInteger();
+		 positivizeName = new MesquiteString();
+		 */
+		chart=new MesquiteChart(ownerModule, 100, 0, ownerModule.charterTask.createCharter(this));
+		setChart(chart);
+		
+		
+		goAhead = new MesquiteBoolean(false);
+		autoCount = new MesquiteBoolean(true);
+		Panel f = chart.getField();
+		if (f == null)
+			autoCount.setValue(true);
+		else {
+			f.add(recalcButton = new Button("Recalculation needed"));
+			recalcButton.setBounds(10,10, 140, 30);
+			recalcButton.setVisible(false);
+			recalcButton.setBackground(Color.white);
+			recalcButton.addActionListener(this);
+		}
+		
+		//colorItems = new MesquiteBoolean(true);REMOVED temporarily(?)
+		//ownerModule.addCheckMenuItem(ownerModule.findMenuAmongEmployers("Colors"), "Color Items by Group", ownerModule.makeCommand("toggleColorItems",  this), colorItems);
+		chart.deassignChart();
+		
+		setXCommand = ownerModule.makeCommand("setX",  this);
+		setYCommand = ownerModule.makeCommand("setY",  this);
+		recalcCommand = ownerModule.makeCommand("recalculate",  this);
+		
+		/*		MesquiteSubmenuSpec mss = ownerModule.addSubmenu(null, "Positivize");
+		 positivizeName.setValue("none");
+		 mss.setSelected(positivizeName);
+		 
+		 ownerModule.addItemToSubmenu(null, mss, "Constrain Minimum X", ownerModule.makeCommand("constrainMinX",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Constrain Maximum X", ownerModule.makeCommand("constrainMaxX",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Constrain Minimum Y", ownerModule.makeCommand("constrainMinY",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Constrain Maximum Y", ownerModule.makeCommand("constrainMaxY",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "-", null);
+		 ownerModule.addItemToSubmenu(null, mss, "Deconstrain Minimum X", ownerModule.makeCommand("deconstrainMinX",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Deconstrain Maximum X", ownerModule.makeCommand("deconstrainMaxX",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Deconstrain Minimum Y", ownerModule.makeCommand("deconstrainMinY",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "Deconstrain Maximum Y", ownerModule.makeCommand("deconstrainMaxY",  this));
+		 ownerModule.addItemToSubmenu(null, mss, "-", null);
+		 ownerModule.addCheckMenuItemToSubmenu(null, mss, "Positivize by X", ownerModule.makeCommand("positivizeX",  this), null);
+		 ownerModule.addCheckMenuItemToSubmenu(null, mss, "Positivize by Y", ownerModule.makeCommand("positivizeY",  this), null);
+		 */
+		chart.setLocation(chartInsetLeft, chartInsetTop);
+		chart.setChartSize(getWidth()-chartInsetRight - chartInsetLeft, getHeight()-chartInsetTop - chartInsetBottom);
+		messagePane = new TChartMessages(this);
+		addToWindow(messagePane);
+		messagePane.setVisible(true);
+		messagePane.setLocation(0, windowHeight- chartInsetBottom);
+		messagePane.setSize(windowWidth, chartInsetBottom);
+		scrollBox = new DoubleMiniScroll(setXCommand, setYCommand, 0,0,0,0,0,0);
+		chart.add(scrollBox);
+		scrollBox.setYTitle("Y");
+		scrollBox.setXTitle("X");
+		scrollBox.setLocation(2, getHeight()-24-chartInsetBottom- scrollBox.getBounds().height);
+		scrollBox.setVisible(true);
+		setWindowSize(400,400);
+		ownerModule.addMenuItem("-", null);
+		ownerModule.addCheckMenuItem(null, "Auto-recalculate", ownerModule.makeCommand("toggleAutoRecalc", this), autoCount);
+	}
+	public void setDefaultNumberOfItems(int def){
+		defaultNumberOfItems=def;
+		numberOfItems = def;
+	}
+	/*...................................................................................................................*/
+	public void setChartVisible(){
+		addToWindow(chart);
+		chart.setLocation(chartInsetLeft, chartInsetTop);
+		chart.setChartSize(getWidth()-chartInsetRight - chartInsetLeft, getHeight()-chartInsetTop - chartInsetBottom);
+		chart.setVisible(true);
+		scrollBox.repaint();
+		windowResized();
+		contentsChanged();
+		if (recalcButton.isVisible())
+			recalcButton.setSize(recalcButton.getPreferredSize());
+		chart.repaint();
+	}
+	/*...................................................................................................................*/
+	public void pointMouseDown(MesquiteChart chart, int whichPoint, MesquiteNumber valueX, MesquiteNumber valueY, int x, int y, int modifiers, String message){
+		if (whichPoint>=0){
+			String name = chart.getName(whichPoint);
+			if (name ==null){
+				Object item = itemsSourceTask.getItem(taxa, whichPoint);
+				if (item instanceof Listable)
+					name = ((Listable)item).getName();
+			}
+			if (name==null)
+				name = "#" + whichPoint;
+			name +=  "\nx " + chart.getXArray().toString(whichPoint) + "\ny " + chart.getYArray().toString(whichPoint);
+			if (numberTaskZ!=null)
+				name +=  "\ncolor " + chart.getZArray().toString(whichPoint);
+			if (message !=null)
+				name += "\n" + message;
+			chart.showQuickMessage(whichPoint, x, y, name);
+		}
+		else {
+			if (message !=null)
+				chart.showQuickMessage(whichPoint, x, y, message);
+		}
+	}
+	/*...................................................................................................................*/
+	public void pointMouseUp(MesquiteChart chart, int whichPoint, int x, int y, int modifiers, String message){
+		chart.hideQuickMessage();
+	}
+	/*.................................................................................................................*/
+	public void setCharter(Charter charter) {
+		chart.setCharter(charter);
+		charter.setShowNames(true);
+	}
+	public void setExplanationString(String t) {
+		explanationString=t;
+	}
+	
+	/*...................................................................................................................*/
+	public void setTaxa(Taxa taxa){
+		this.taxa = taxa;
+	}
+	/*...................................................................................................................*/
+	public void setShowNames( boolean showNames){
+		this.showNames = showNames;
+	}
+	/*...................................................................................................................*/
+	public void setItemsSource( ItemsSource itemsSourceTask){
+		this.itemsSourceTask = itemsSourceTask;
+		if (ownerModule.charterTask!=null && itemsSourceTask!=null) {
+			ownerModule.charterTask.pointsAreSelectable(itemsSourceTask.getSelectionable()!=null, itemsSourceTask.getSelectionable(), true);
+			
+		}
+	}
+	private void resetScrolls(){
+		if (numberTaskX instanceof Incrementable){
+			Incrementable inc = (Incrementable)numberTaskX;
+			scrollBox.setXTitle(inc.getItemTypeName());
+			int min = (int)inc.toExternal(inc.getMin());
+			int max = (int)inc.toExternal(inc.getMax());
+			if (currentX> (int)inc.getMax())
+				currentX = (int)inc.getMax();
+			if (currentX< (int)inc.getMin())
+				currentX = (int)inc.getMin();
+			scrollBox.setXValues(min,  (int)inc.toExternal(currentX), max);
+			scrollBox.setXVisible(true);
+		}
+		else {
+			scrollBox.setXValues(0,0,0);
+			scrollBox.setXVisible(false);
+		}
+		if (numberTaskY instanceof Incrementable){
+			Incrementable inc = (Incrementable)numberTaskY;
+			scrollBox.setYTitle(inc.getItemTypeName());
+			int min = (int)inc.toExternal(inc.getMin());
+			int max = (int)inc.toExternal(inc.getMax());
+			if (currentY>(int) inc.getMax())
+				currentY = (int)inc.getMax();
+			if (currentY< (int)inc.getMin())
+				currentY = (int)inc.getMin();
+			scrollBox.setYValues(min,  (int)inc.toExternal(currentY), max);
+			scrollBox.setYVisible(true);
+		}
+		else {
+			scrollBox.setYValues(0,0,0);
+			scrollBox.setYVisible(false);
+		}
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskX(NumberForItem numberTask){
+		this.numberTaskX = numberTask;
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskY(NumberForItem numberTask){
+		this.numberTaskY = numberTask;
+	}
+	/*...................................................................................................................*/
+	public void setNumberTaskZ(NumberForItem numberTask){
+		this.numberTaskZ = numberTask;
+	}
+	/*...................................................................................................................*/
+	public void setAuxiliary(Object object, boolean useAsFirstParameter){
+		auxiliary = object;
+		auxFirst = useAsFirstParameter;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (numberTaskX instanceof Incrementable){
+			Incrementable inc = (Incrementable)numberTaskX;
+			temp.addLine("setX " + inc.toExternal(currentX)); 
+		}
+		if (numberTaskY instanceof Incrementable){
+			Incrementable inc = (Incrementable)numberTaskY;
+			temp.addLine("setY " + inc.toExternal(currentY)); 
+		}
+		if (assigned)
+			temp.addLine("setNumberItems " + numberOfItems);
+		//NOTE: do not snapshot the auto-recalc.  It should always be on at first.
+		
+		
+		/*
+		 if (!constrainedMinX.isUnassigned())
+		 temp.addLine("constrainMinX " + constrainedMinX);
+		 if (!constrainedMaxX.isUnassigned())
+		 temp.addLine("constrainMaxX " + constrainedMaxX);
+		 if (!constrainedMinY.isUnassigned())
+		 temp.addLine("constrainMinY " + constrainedMinY);
+		 if (!constrainedMaxY.isUnassigned())
+		 temp.addLine("constrainMaxY " + constrainedMaxY);
+		 if (positivize.getValue()==0)
+		 temp.addLine("positivizeX");
+		 else if (positivize.getValue()==1)
+		 temp.addLine("positivizeY");
+		 temp.addLine("toggleColorItems " + colorItems.toOffOnString());
+		 */
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the chart drawing module", "[name of module]", commandName, "setChartType")){
+			String newc = ParseUtil.getFirstToken(arguments, pos);
+			if (ownerModule.charterTask.getClass()!=null && (ownerModule.charterTask.nameMatches(newc))) //already have this
+				return ownerModule.charterTask;
+			DrawChart temp =  (DrawChart)ownerModule.replaceEmployee(DrawChart.class, arguments, "Type of chart", ownerModule.charterTask);
+			if (temp!=null) {
+				ownerModule.charterTask=  temp;
+				if (itemsSourceTask!=null)
+					temp.pointsAreSelectable(itemsSourceTask.getSelectionable()!=null, itemsSourceTask.getSelectionable(), true);
+				else
+					temp.pointsAreSelectable(false, null, true);
+				setCharter(ownerModule.charterTask.createCharter(this));
+				ownerModule.parametersChanged();
+				return ownerModule.charterTask;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Returns values as tabbed line", null, commandName, "getValuesTabbed")) {
+			if (valuesX == null || valuesY == null)
+				return null;
+				StringBuffer s = new StringBuffer();  
+				s.append("X");
+				for (int i =0; i<valuesX.getSize(); i++)
+					s.append("\t" + valuesX.toString(i));
+				s.append(StringUtil.lineEnding());
+				s.append("Y");
+				for (int i =0; i<valuesY.getSize(); i++)
+					s.append("\t" + valuesY.toString(i));
+				s.append(StringUtil.lineEnding());
+			return s.toString();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to recalculate automatically when needed", "[on=auto; off]", commandName, "toggleAutoRecalc")) {
+			Parser parser = new Parser();
+			autoCount.toggleValue(parser.getFirstToken(arguments));
+			if (autoCount.getValue()) {
+				recalcButton.setVisible(false);
+				doCounts();
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Requests recalculation", null, commandName, "recalculate")) {
+			doCounts();
+			return null;
+		}
+		/*
+		 else if (checker.compare(this.getClass(), "Sets the minimum value on the X axis", "[x value]", commandName, "constrainMinX")) {
+		 MesquiteNumber n = new MesquiteNumber();
+		 pos.setValue(0);
+		 n.setValue(ParseUtil.getFirstToken(arguments, pos));
+		 if (!n.isCombinable() && !MesquiteThread.isScripting())
+		 n = MesquiteNumber.queryNumber(ownerModule.containerOfModule(), "Minimum X", "Constrain the minimum value shown of X to be:", constrainedMinX);
+		 if (n.isCombinable()){
+		 constrainedMinX.setValue(n);
+		 recalcChart();
+		 }
+		 }
+		 else if (checker.compare(this.getClass(), "Sets the maximum value on the X axis", "[x value]", commandName, "constrainMaxX")) {
+		 MesquiteNumber n = new MesquiteNumber();
+		 pos.setValue(0);
+		 if (StringUtil.blank(arguments))
+		 n = MesquiteNumber.queryNumber(ownerModule.containerOfModule(), "Maximum X", "Constrain the maximum value shown of X to be:", n);
+		 else
+		 n.setValue(ParseUtil.getFirstToken(arguments, pos));
+		 if (n.isCombinable()){
+		 constrainedMaxX.setValue(n);
+		 recalcChart();
+		 }
+		 }
+		 else if (checker.compare(this.getClass(), "Sets the minimum value on the Y axis", "[y value]", commandName, "constrainMinY")) {
+		 MesquiteNumber n = new MesquiteNumber();
+		 pos.setValue(0);
+		 if (StringUtil.blank(arguments))
+		 n = MesquiteNumber.queryNumber(ownerModule.containerOfModule(), "Minimum Y", "Constrain the minimum value shown of Y to be:", n);
+		 else
+		 n.setValue(ParseUtil.getFirstToken(arguments, pos));
+		 if (n.isCombinable()){
+		 constrainedMinY.setValue(n);
+		 recalcChart();
+		 }
+		 }
+		 else if (checker.compare(this.getClass(), "Sets the maximum value on the Y axis", "[y value]", commandName, "constrainMaxY")) {
+		 MesquiteNumber n = new MesquiteNumber();
+		 pos.setValue(0);
+		 if (StringUtil.blank(arguments))
+		 n = MesquiteNumber.queryNumber(ownerModule.containerOfModule(), "Maximum Y", "Constrain the maximum value shown of Y to be:", n);
+		 else
+		 n.setValue(ParseUtil.getFirstToken(arguments, pos));
+		 if (n.isCombinable()){
+		 constrainedMaxY.setValue(n);
+		 recalcChart();
+		 }
+		 }
+		 else if (checker.compare(this.getClass(), "Deconstrains the minimum value on the X axis", null, commandName, "deconstrainMinX")) {
+		 constrainedMinX.setToUnassigned();
+		 recalcChart();
+		 }
+		 else if (checker.compare(this.getClass(), "Deconstrains the maximum value on the X axis", null, commandName, "deconstrainMaxX")) {
+		 constrainedMaxX.setToUnassigned();
+		 recalcChart();
+		 }
+		 else if (checker.compare(this.getClass(), "Deconstrains the minimum value on the Y axis", null, commandName, "deconstrainMinY")) {
+		 constrainedMinY.setToUnassigned();
+		 recalcChart();
+		 }
+		 else if (checker.compare(this.getClass(), "Deconstrains the maximum value on the Y axis", null, commandName, "deconstrainMaxY")) {
+		 constrainedMaxY.setToUnassigned();
+		 recalcChart();
+		 }
+		 
+		 else if (checker.compare(this.getClass(), "Forces the X values to be positive, changing sign of other values in concert", null, commandName, "positivizeX")) {
+		 if (positivize.getValue()!=0) {
+		 positivize.setValue(0);
+		 positivizeName.setValue("Positivize by X");
+		 }
+		 else {
+		 positivize.setToUnassigned();
+		 positivizeName.setValue("none");
+		 }
+		 recalcChart();
+		 }
+		 else if (checker.compare(this.getClass(), "Forces the Y values to be positive, changing sign of other values in concert", null, commandName, "positivizeY")) {
+		 if (positivize.getValue()!=1) {
+		 positivize.setValue(1);
+		 positivizeName.setValue("Positivize by Y");
+		 }
+		 else {
+		 positivize.setToUnassigned();
+		 positivizeName.setValue("none");
+		 }
+		 recalcChart();
+		 }
+		 */
+		else if (checker.compare(this.getClass(), "Sets which of a series of items is shown on the X axis (appropriate when there could be a series of alternative values on the x axis, e.g. for different characters or trees)", "[number of item]", commandName, "setX")) {
+			if (numberTaskX instanceof Incrementable){
+				Incrementable inc = (Incrementable)numberTaskX;
+				int ic = (int)(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (!MesquiteInteger.isCombinable(ic))
+					ic = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Choose ", "choose:", 1); //TODO have something more intelligent here
+				int icInternal = (int) inc.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (MesquiteInteger.isCombinable(icInternal) && icInternal != currentX){ //will catch invalid numbers later  && (icInternal>=inc.getMin()) && (icInternal<=inc.getMax())) {
+					currentX=icInternal;
+					if (!MesquiteThread.isScripting()){
+						doCounts();
+						contentsChanged();
+					}
+				}
+				
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which of a series of items is shown on the Y axis (appropriate when there could be a series of alternative values on the y axis, e.g. for different characters or trees)", "[number of item]", commandName, "setY")) {//NOT YET USED
+			if (numberTaskY instanceof Incrementable){
+				Incrementable inc = (Incrementable)numberTaskY;
+				int ic = (int)inc.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (!MesquiteInteger.isCombinable(ic))
+					ic = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Choose ", "choose:", 1); //TODO have something more intelligent here
+				int icInternal = (int) inc.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (MesquiteInteger.isCombinable(icInternal) && icInternal != currentY){ //will catch invalid numbers later (icInternal>=inc.getMin()) && (icInternal<=inc.getMax())) {
+					currentY=icInternal;
+					
+					if (!MesquiteThread.isScripting()){
+						doCounts();
+						contentsChanged();
+					}
+				}
+				
+			}
+		}
+		/*
+		 else if (checker.compare(this.getClass(), "Sets whether to color the items in the chart according to any natural item colors", "[on or off]", commandName, "toggleColorItems")) {  
+		 boolean current = colorItems.getValue();
+		 colorItems.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+		 if (current!=colorItems.getValue())
+		 recalcChart();
+		 }
+		 */
+		else if (checker.compare(this.getClass(), "Sets the number of items plotted (appropriate if the items source has an indefinite number)", "[number of items]", commandName, "setNumberItems")) {
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum= MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Set Number of " + itemsSourceTask.getItemTypeNamePlural(), "Number of " + itemsSourceTask.getItemTypeNamePlural(), numberOfItems, 0, MesquiteInteger.infinite);
+			if (MesquiteInteger.isCombinable(newNum) && newNum>0) {
+				assigned = true;
+				if (newNum!=numberOfItems){
+					numberOfItems = newNum;
+					if (!MesquiteThread.isScripting()){
+						doCounts();
+						contentsChanged();
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	
+	/*.................................................................................................................*/
+	public void selectAllGraphicsPanel(){
+		//this paradoxical deselection is done because chart treats all as selected if none are
+		if (itemsSourceTask.getSelectionable()!=null)  {
+			itemsSourceTask.getSelectionable().deselectAll();
+			itemsSourceTask.getSelectionable().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+		else {
+			chart.deselectAllPoints(); 
+			chart.repaint();
+			chart.getField().repaint();
+		}
+	}
+	/*...................................................................................................................*/
+	private void resetArraySizes(int num){
+		valuesX.resetSize(num);  
+		valuesY.resetSize(num);  
+		if (numberTaskZ!=null)
+			valuesZ.resetSize(num);  
+	}
+	private void checkSizes(int num){
+		if (num> valuesX.getSize()){
+			resetArraySizes(valuesX.getSize()+100); 
+		}
+	}
+	/*...................................................................................................................*/
+	private void resetSizes(Taxa taxa){
+		if (itemsSourceTask==null)
+			return;
+		int numItems=itemsSourceTask.getNumberOfItems(taxa);
+		
+		if (!MesquiteInteger.isFinite(numItems)) {
+			if (wasDefinite && !assigned) {
+				if (!MesquiteThread.isScripting())
+					numberOfItems= MesquiteInteger.queryInteger(ownerModule.containerOfModule(), "Set Number of " + itemsSourceTask.getItemTypeNamePlural(), "Number of " + itemsSourceTask.getItemTypeNamePlural(), numberOfItems, 0, MesquiteInteger.infinite);
+				else
+					numberOfItems = defaultNumberOfItems;
+				if (!MesquiteInteger.isCombinable(numberOfItems)) {
+					numberOfItems = defaultNumberOfItems;
+					assigned = true;
+				}
+			}
+			wasDefinite = false;
+			if (numItemsItem == null) {
+				numItemsItem = ownerModule.addMenuItem( "Number of  " + itemsSourceTask.getItemTypeNamePlural() + "...", ownerModule.makeCommand("setNumberItems",  this));
+				ownerModule.resetContainingMenuBar();
+			}
+		}
+		else  {
+			if (numItemsItem!= null) {
+				ownerModule.deleteMenuItem(numItemsItem);
+				ownerModule.resetContainingMenuBar();
+				numItemsItem = null;
+			}
+			wasDefinite = true;
+			assigned = false;
+			numberOfItems = numItems;
+		}
+		if (!MesquiteInteger.isCombinable(numberOfItems)){ //finite but indefinite; set to 100
+			resetArraySizes(100);
+		}
+		else {
+			resetArraySizes(numberOfItems);
+		}
+	}	
+	/*.................................................................................................................*/
+	public void actionPerformed(ActionEvent e){
+		String buttonLabel = e.getActionCommand();
+		if ("Recalculation needed".equalsIgnoreCase(buttonLabel)){  // Recalc button is pressed //send command
+			goAhead.setValue(true);
+			recalcCommand.doItMainThread(null, null, this);  // command invoked
+			
+		}
+	}
+	/*.................................................................................................................*/
+	private boolean waitOnCalculation(){
+		if (autoCount.getValue() || MesquiteThread.isScripting()){  //set to autocount; go ahead and do count
+			if (recalcButton.isVisible())
+				recalcButton.setVisible(false);
+			return false;
+		}
+		else { // counts only if goAhead flag is set, which it will be following click on button
+			if (goAhead.getValue()){
+				goAhead.setValue(false);
+				if (recalcButton.isVisible())
+					recalcButton.setVisible(false);
+				return false;
+			}
+			else if (!recalcButton.isVisible())
+				recalcButton.setVisible(true);
+			if (chart.getNumPoints()>0)
+				chart.deassignChart();
+			recalcButton.setSize(recalcButton.getPreferredSize());
+			recalcButton.invalidate();
+			recalcButton.doLayout();
+			recalcButton.repaint();
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void doCounts() {
+		doCounts(MesquiteInteger.unassigned, MesquiteInteger.unassigned, true);
+	}
+	int count = 0;
+	/*.................................................................................................................*/
+	public void doCounts(int firstItem, int lastItem, boolean fullCount) {
+		count++;
+
+		if (numberTaskX==null || numberTaskY==null)
+			return;
+		if (waitOnCalculation()) {
+			blankChart();
+			return;
+		}
+		//initializing
+		MesquiteModule.incrementMenuResetSuppression();
+		Object item;
+		int startItem, endItem;
+		boolean countAll = fullCount || firstTimeThrough;
+//		boolean countAll = true;
+		
+		if (countAll) {
+			blankChart();
+			valuesX.deassignArray();
+			valuesY.deassignArray();
+			if (numberTaskZ!=null)
+				valuesZ.deassignArray();
+			int numDimensions = 2;
+			if (numberTaskZ!=null)
+				numDimensions = 3;
+		}
+		contentsChanged();
+		resetSizes(taxa);
+		if (numberTaskX instanceof Incrementable)
+			((Incrementable)numberTaskX).setCurrent(currentX); 
+		numberOfItemsUsed = numberOfItems;
+		int clockInterval = numberOfItemsUsed/100;
+		if (clockInterval <1)
+			clockInterval = 1;
+		MesquiteNumber cNum = new MesquiteNumber();
+		ProgressIndicator prog = null;
+		long startTime = System.currentTimeMillis();
+		boolean progOn = false;
+		boolean alreadyQueried = false;
+		int oldnumberOfItemsUsed = numberOfItemsUsed;
+		String numS = MesquiteInteger.toString(numberOfItemsUsed);
+		if (numberOfItemsUsed == MesquiteInteger.finite)
+			numS = "an undetermined number";
+		
+		if (MesquiteInteger.isUnassigned(firstItem) || countAll)
+			startItem = 0;
+		else
+			startItem = firstItem;
+		if (MesquiteInteger.isUnassigned(lastItem) || countAll)
+			endItem = numberOfItemsUsed-1;
+		else
+			endItem =lastItem;
+		int numberOfItemsExaminedThisTime = endItem-startItem+1;
+
+		MesquiteDialog.hideWizardForCalculation();
+		
+		//Going through items doing calculations for x axis
+		for (int im=startItem; im<=endItem && (prog==null || !prog.isAborted()); im++ ) {
+
+			if (numberOfItemsUsed != oldnumberOfItemsUsed){
+				numS = MesquiteInteger.toString(numberOfItemsUsed);
+				if (numberOfItemsUsed == MesquiteInteger.finite)
+					numS = "an undetermined number";
+				oldnumberOfItemsUsed = numberOfItemsUsed;
+			}
+			if (!progOn && System.currentTimeMillis()- startTime>5000) {
+				prog = new ProgressIndicator(ownerModule.getProject(),"Calculating Chart", "Calculating X value for " + itemsSourceTask.getItemTypeNamePlural(), numberOfItemsUsed, true);
+				prog.start();
+				progOn = true;
+			}
+			else if (progOn){
+				prog.setCurrentValue(im);
+				prog.setText("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im+1) + " of " + numS, false);
+			}
+			if (im % 10 == 0) {
+				CommandRecord.tick("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im+1) + " of " + numS + " for X value");
+			}
+			item = itemsSourceTask.getItem(taxa, im);
+			if (item == null) {
+				//null item hit; source may have unexpectedly run out; reset total expected
+				assigned = false;
+				numberOfItemsUsed = im;
+				endItem=im;
+				resetArraySizes(numberOfItemsUsed);   
+
+				
+			}
+			else {
+				checkSizes(im);
+				cNum.setToUnassigned();
+				if (auxFirst)
+					numberTaskX.calculateNumber(auxiliary, item, cNum, null);
+				else
+					numberTaskX.calculateNumber(item, auxiliary, cNum, null);
+				if (valuesX!=null){
+					if (im>= valuesX.getSize())
+						valuesX.resetSize(im+1);
+					valuesX.setValue(im, cNum);
+				}
+
+				
+				if (prog != null && prog.isAborted()){
+					
+					String s;
+					if (numberTaskZ!=null)
+						s = "Y and Z axes";
+					else
+						s = "Y axis";
+					if (!AlertDialog.query(ownerModule.containerOfModule(), "Continue with Chart?", "Calculations stopped before all " + itemsSourceTask.getItemTypeNamePlural() + " were examined.  Do you want to display the results?  If so, calculations will still need to be completed for the " + s + ".", "Display", "Discard", 1)) {
+						// here we discard results, and display a blank chart
+						autoCount.setValue(false);
+						waitOnCalculation();
+						blankChart();
+						prog.goAway();
+						MesquiteModule.decrementMenuResetSuppression();
+						return;
+					}
+					assigned = false;
+					numberOfItemsUsed = im;  // reset the number of items to the actual number processed
+					endItem=im;
+					resetArraySizes(numberOfItemsUsed);   
+					alreadyQueried = true;
+				}
+			}
+		}
+		xString = numberTaskX.getNameAndParameters();
+		
+		
+		//Going through items doing calculations for Y axis
+		if (numberTaskY instanceof Incrementable)
+			((Incrementable)numberTaskY).setCurrent(currentY);
+		
+
+		for (int im=startItem; im<=endItem; im++ ) {
+
+			if (numberOfItemsUsed != oldnumberOfItemsUsed){
+				numS = MesquiteInteger.toString(numberOfItemsUsed);
+				if (numberOfItemsUsed == MesquiteInteger.finite)
+					numS = "an undetermined number";
+				oldnumberOfItemsUsed = numberOfItemsUsed;
+			}
+			if (!progOn && System.currentTimeMillis()- startTime>5000) {
+				prog = new ProgressIndicator(ownerModule.getProject(),"Calculating Chart", "Calculating Y value for " + itemsSourceTask.getItemTypeNamePlural(), numberOfItemsUsed, true);
+				prog.start();
+				progOn = true;
+			}
+			else if (progOn){
+				prog.setCurrentValue(im);
+				prog.setText("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im+1) + " of " + numS, false);
+			}
+			if (im % 10 == 0)
+				CommandRecord.tick("Examining " + itemsSourceTask.getItemTypeName() + "  " + im + " of " + numS + " for Y value");
+			item = itemsSourceTask.getItem(taxa, im);
+			if (item == null) {
+				//null item hit; source may have unexpectedly run out; reset total expected
+				assigned = false;
+				numberOfItemsUsed = im;
+				endItem=im;
+
+				resetArraySizes(numberOfItemsUsed);   
+			}
+			else {
+				cNum.setToUnassigned();
+				if (auxFirst)
+					numberTaskY.calculateNumber(auxiliary, item, cNum, null);
+				else
+					numberTaskY.calculateNumber(item, auxiliary, cNum, null);
+				if (valuesY!=null){
+					if (im>= valuesY.getSize())
+						valuesY.resetSize(im+1);
+					valuesY.setValue(im, cNum);
+				}
+				if (prog != null && prog.isAborted()){
+					
+					String s = "";
+					if (numberTaskZ!=null)
+						s = "If so, calculations will still need to be completed for the Z axis. ";
+					if (!AlertDialog.query(ownerModule.containerOfModule(), "Continue with Chart?", "Calculations stopped before all " + itemsSourceTask.getItemTypeNamePlural() + " were examined.  Do you want to display the results? " + s, "Display", "Discard", 1)) {
+						// here we discard results, and display a blank chart
+						autoCount.setValue(false);
+						waitOnCalculation();
+						blankChart();
+						prog.goAway();
+						MesquiteModule.decrementMenuResetSuppression();
+						return;
+					}
+					assigned = false;
+					numberOfItemsUsed = im;  // reset the number of items to the actual number processed
+					endItem=im;
+					resetArraySizes(numberOfItemsUsed);   
+				}
+			}
+		}
+		yString = numberTaskY.getNameAndParameters();
+		
+		
+		//Going through items doing calculations for Z axis
+		if (numberTaskZ!=null){
+			int im;
+			for (im=startItem; im<=endItem; im++ ) {
+				if (numberOfItemsUsed != oldnumberOfItemsUsed){
+					numS = MesquiteInteger.toString(numberOfItemsUsed);
+					if (numberOfItemsUsed == MesquiteInteger.finite)
+						numS = "an undetermined number";
+					oldnumberOfItemsUsed = numberOfItemsUsed;
+				}
+				if (!progOn && System.currentTimeMillis()- startTime>5000) {
+					prog = new ProgressIndicator(ownerModule.getProject(),"Calculating Chart", "Calculating Z value for " + itemsSourceTask.getItemTypeNamePlural(), numberOfItemsUsed, true);
+					prog.start();
+					progOn = true;
+				}
+				else if (progOn){
+					prog.setCurrentValue(im);
+					prog.setText("Examining " + itemsSourceTask.getItemTypeName() + "  " + (im+1) + " of " + numS, false);
+				}
+				if (im % 10 == 0)
+					CommandRecord.tick("Examining " + itemsSourceTask.getItemTypeName() + "  " + im + " of " + numS + " for Z value");
+				item = itemsSourceTask.getItem(taxa, im);
+				if (item == null) {
+					//null item hit; source may have unexpectedly run out; reset total expected
+					assigned = false;
+					numberOfItemsUsed = im;
+					endItem=im;
+					resetArraySizes(numberOfItemsUsed);   
+				}
+				else {
+					cNum.setToUnassigned();
+					if (auxFirst)
+						numberTaskZ.calculateNumber(auxiliary, item, cNum, null);
+					else
+						numberTaskZ.calculateNumber(item, auxiliary, cNum, null);
+					if (valuesZ!=null){
+						if (im>= valuesZ.getSize())
+							valuesZ.resetSize(im+1);
+						valuesZ.setValue(im, cNum);
+					}
+				}
+			}
+			zString = numberTaskZ.getNameAndParameters();
+			if (prog != null && prog.isAborted()){
+				if (!alreadyQueried & !AlertDialog.query(ownerModule.containerOfModule(), "Continue with Chart?", "Calculations stopped before all " + itemsSourceTask.getItemTypeNamePlural() + " were examined.  Do you want to display the results?", "Display", "Discard", 1)) {
+					// here we discard results, and display a blank chart
+					autoCount.setValue(false);
+					waitOnCalculation();
+					blankChart();
+					prog.goAway();
+					MesquiteModule.decrementMenuResetSuppression();
+					return;
+				}
+				assigned = false;
+				numberOfItemsUsed = im;  // reset the number of items to the actual number processed
+				resetArraySizes(numberOfItemsUsed);   
+			}
+		}
+		ownerModule.charterTask.pointsAreSelectable(itemsSourceTask.getSelectionable()!=null, itemsSourceTask.getSelectionable(), true);
+		
+		if (prog != null)
+			prog.goAway();
+		//Asking to recalculate
+		if (countAll) 
+			recalcChart();
+		else  {
+			addPointsToChart( startItem, endItem+1);
+			setExplanationString(itemsSourceTask.getNameAndParameters());
+			resetMessagePaneText();
+			messagePane.repaint();
+		}
+		MesquiteModule.decrementMenuResetSuppression();
+		firstTimeThrough = false;
+	}
+	/*...................................................................................................................*/
+	public void resetMessagePaneText() {
+		String explanationString = "Results for  " + numberOfItemsUsed + " " + itemsSourceTask.getItemTypeNamePlural() + "\n";
+		explanationString += "Source of  " + itemsSourceTask.getItemTypeNamePlural() + ": " + itemsSourceTask.getNameAndParameters();
+		if (!StringUtil.blank(ownerModule.charterTask.getParameters()))
+			explanationString += "\nChart:  " + ownerModule.charterTask.getParameters();
+		//explanationString += "\nValues calculated:  " + numberTask.getNameAndParameters();
+		explanationString += "\nDetails of items plotted:\n" + itemsSourceTask.accumulateParameters("   ");
+		if (numberTaskX == numberTaskY){
+			String x = numberTaskX.accumulateParameters("   ");
+			explanationString += "\nDetails of values calculated: " + numberTaskX.getName() + ")\n" + x;
+		}
+		else {
+			String x = numberTaskX.accumulateParameters("   ");
+			explanationString += "\nDetails of X values calculated (" + numberTaskX.getName() + ")\n" + x;
+			String y = numberTaskY.accumulateParameters("   ");
+			explanationString += "\nDetails of Y values calculated (" + numberTaskY.getName() + ")\n" + y;
+		}
+		messagePane.setText(explanationString);
+	}
+	
+	/*...................................................................................................................*/
+	public boolean recalcChartInit() {
+		resetMessagePaneText();
+		chart.deassignChart();
+		chart.getCharter().setShowNames(true);
+		chart.setXAxisName(xString);
+		chart.setYAxisName(yString);
+		if (numberTaskZ!=null)
+			chart.setZAxisName(zString);
+		resetScrolls();
+		if (taxa==null)
+			return false;
+		itemsSourceTask.prepareItemColors(taxa);
+		return true;
+	}
+	/*...................................................................................................................*/
+	public void addPointsToChart( int startValue, int endValue) {
+		MesquiteNumber resultX = new MesquiteNumber();
+		MesquiteNumber resultY = new MesquiteNumber();
+		MesquiteNumber resultZ = new MesquiteNumber();
+		chart.getCharter().setSuspendDrawing(true);
+		chart.getCharter().setSuspendChartCalculations(true);
+		for (int i=startValue; i<endValue; i++) {
+			int point;
+			if (i % 100 == 0)
+				CommandRecord.tick("Constructing chart; adding item " + i);
+			if (!valuesX.isCombinable(i))
+				resultX.setToUnassigned();
+			else
+				valuesX.placeValue(i, resultX);
+			if (!valuesY.isCombinable(i))
+				resultY.setToUnassigned();
+			else
+				valuesY.placeValue(i, resultY);
+			if (numberTaskZ!=null) {
+				if (!valuesZ.isCombinable(i))
+					resultZ.setToUnassigned();
+				else
+					valuesZ.placeValue(i, resultZ);
+				
+				point = chart.addPoint(resultX, resultY, resultZ);
+			}
+			else {
+				point = chart.addPoint(resultX, resultY);
+			}
+			Object item = itemsSourceTask.getItem(taxa, i);
+			if (showNames && item instanceof Listable)
+				chart.setName(point, ((Listable)item).getName());
+			//if (colorItems.getValue()) {
+			Color c = itemsSourceTask.getItemColor(taxa, i);
+			if (c!=null) {
+				chart.setColor(point, c);
+			}
+			//}
+		}
+		chart.getCharter().setSuspendDrawing(false);
+		chart.getCharter().setSuspendChartCalculations(false);
+		/*
+		 if (!constrainedMinX.isUnassigned())
+		 chart.constrainMinimumX(constrainedMinX);
+		 else
+		 chart.deConstrainMinimumX();
+		 if (!constrainedMaxX.isUnassigned())
+		 chart.constrainMaximumX(constrainedMaxX);
+		 else
+		 chart.deConstrainMaximumX();
+		 if (!constrainedMinY.isUnassigned())
+		 chart.constrainMinimumY(constrainedMinY);
+		 else
+		 chart.deConstrainMinimumY();
+		 if (!constrainedMaxY.isUnassigned())
+		 chart.constrainMaximumY(constrainedMaxY);
+		 else
+		 chart.deConstrainMaximumY();
+		 */
+		resetMessagePaneText();
+		
+		chart.munch();
+		contentsChanged();
+		messagePane.repaint();
+	}
+	/*...................................................................................................................*/
+	public void recalcChart() {
+		if (!recalcChartInit())
+			return;
+		
+		addPointsToChart(0,valuesX.getSize());
+	}
+	/*...................................................................................................................*/
+	public void windowResized() {
+		super.windowResized();
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (chart==null || messagePane==null || scrollBox==null) {
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+		windowHeight =getHeight();
+		windowWidth = getWidth();
+		chart.setLocation(chartInsetLeft, chartInsetTop);
+		chart.setChartSize(windowWidth-chartInsetRight - chartInsetLeft, windowHeight-chartInsetTop - chartInsetBottom);
+		messagePane.setLocation(0, windowHeight- chartInsetBottom);
+		messagePane.setSize(windowWidth, chartInsetBottom);
+		scrollBox.setLocation(2, windowHeight-24-chartInsetBottom- scrollBox.getBounds().height);
+		recalcButton.setSize(recalcButton.getPreferredSize());
+		
+		chart.repaint();
+		messagePane.repaint();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+/*...................................................................................................................*/
+class TChartMessages extends TextArea {
+	ItemsBiplotWindow window;
+	public TChartMessages (ItemsBiplotWindow window) {
+		super("", 3, 3, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		this.window = window;
+	}
+}
+
+
diff --git a/Source/mesquite/charts/MatrixValuesChart/MatrixValuesChart.java b/Source/mesquite/charts/MatrixValuesChart/MatrixValuesChart.java
new file mode 100644
index 0000000..58f3155
--- /dev/null
+++ b/Source/mesquite/charts/MatrixValuesChart/MatrixValuesChart.java
@@ -0,0 +1,231 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.MatrixValuesChart;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class MatrixValuesChart.  ===*/
+
+public class MatrixValuesChart extends FileAssistantCH  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Bar & Line Chart for Character Matrices";
+	}
+	public String getExplanation() {
+		return "Shows chart displaying values (such as treelength, etc.) for a series of character matrices." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForMatrix.class, getName() + " needs methods to calculate the two values for the character matrices.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Character Matrices item under Bar & Line Charts in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(MatrixSourceCoordObed.class, getName() + " needs a source of character matrices.",
+		"You can select the character matrices to show either when the chart starts up, or later using the Matrix Source submenu of the Chart menu.  (You may request the chart itself by selecting the Character Matrices item under Bar & Line Charts in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	NumberForMatrix numberTask;
+	MatrixSourceCoordObed matrixSourceTask;
+	ItemsCharter chartWindowTask;
+	private Taxa oldTaxa, taxa;
+	ChartWindow cWindow;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of values for characters?");
+		if (taxa ==null)
+			return sorry(getName() + " couldn't start because no block of taxa available.");
+		taxa.addListener(this);
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no chart window module was obtained");
+
+		//Matrix source %%%%%%
+		matrixSourceTask = (MatrixSourceCoordObed)hireEmployee(MatrixSourceCoordObed.class, "Source of character matrices (for Character Matrix Values chart)");
+		if (matrixSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		MCharactersDistribution item = (MCharactersDistribution)matrixSourceTask.getItem(taxa, 0);
+		Class stateClass = null;
+		if (item != null)
+			stateClass = item.getStateClass();
+
+		//values etc. %%%%%%
+		numberTask=(NumberForMatrix)hireCompatibleEmployee(NumberForMatrix.class, stateClass,"Value to calculate for character matrices (for Character Matrix Values chart)");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module was obtained.");
+		ntC = makeCommand("setCalculator",  this);
+		numberTask.setHiringCommand(ntC);
+
+
+		makeMenu("Chart");
+		addSubmenu(null, "Values for matrices", ntC, NumberForMatrix.class);//TODO: checkmark
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource( matrixSourceTask);
+		cWindow.setChartTitle("Character Values");
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) { //obed should only supply window!
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspendCalculations"); 
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		temp.addLine("setCalculator ", numberTask);
+		temp.addLine("getMatrixSource ", matrixSourceTask);
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("resumeCalculations"); 
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block reference, number, or name]", commandName, "setTaxa")){
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				return taxa;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Returns chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to be visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+
+		}
+		else if (checker.compare(this.getClass(), "Requests the calculations for the charts be redone", null, commandName, "doCounts")) {
+			if (cWindow!=null){
+				chartWindowTask.setTaxa(taxa);
+				chartWindowTask.setNumberTask(numberTask);
+				chartWindowTask.setItemsSource( matrixSourceTask);
+				chartWindowTask.doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			chartWindowTask.incrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resumeCalculations")){
+			chartWindowTask.decrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Returns the source of matrices for the character matrices chart", null, commandName, "getMatrixSource")) {
+
+			return matrixSourceTask;
+
+		}
+		else if (checker.compare(this.getClass(), "Returns the source of matrices for the character matrices chart", null, commandName, "setMatrixSource")) { //temporary, for data files using old system without coordinators
+
+			return matrixSourceTask.doCommand(commandName, arguments, checker);
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate numbers for the character matrices", "[name of module]", commandName, "setCalculator")) {
+			NumberForMatrix temp = (NumberForMatrix)replaceEmployee(NumberForMatrix.class, arguments, "Value to calculate for character matrices", numberTask);
+			if (temp !=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				if (cWindow!=null) {
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource( matrixSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null)
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == matrixSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+			else chartWindowTask.doCounts();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Character Matrices";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/charts/NodesScattergram/NodesScattergram.java b/Source/mesquite/charts/NodesScattergram/NodesScattergram.java
new file mode 100644
index 0000000..711c006
--- /dev/null
+++ b/Source/mesquite/charts/NodesScattergram/NodesScattergram.java
@@ -0,0 +1,754 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.NodesScattergram;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class NodesScattergram.  ===*/
+
+public class NodesScattergram extends TreeWindowAssistantC implements ChartListener  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Nodes Scattergram";
+	}
+	public String getExplanation() {
+		return "Shows values for nodes of tree via a scattergram." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodes.class, getName() + " needs methods to calculate two values (such as depth, independent contrast, etc.) for a series of nodes of the tree in the tree window.",
+		"You can select this either when the chart starts up, or using the Values submenus of the Chart menu.  (You may request the chart itself by selecting the Nodes item under New Chart For Tree in the Analysis menu of the Tree Window)");
+		e.setPriority(1);
+		EmployeeNeed e3 = registerEmployeeNeed(DrawChart.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	NumbersForNodes numbersForNodesTaskX, numbersForNodesTaskY;
+	public DrawChart charterTask;
+	private Tree tree;
+	int currentX = 0;
+	int currentY = 1;
+	NodeLabeller nsLabeller;
+	boolean separateAxes = true;
+	TreeDisplay treeDisplay;
+	boolean showTreeLabels = false;
+	MesquiteString numberTaskXName, numberTaskYName;
+	MesquiteCommand setXCommand, setYCommand;
+	MesquiteCommand ntxC, ntyC, ntC;
+	NodeScattergramWindow window;
+	boolean suspend=false;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charterTask = (DrawChart)hireNamedEmployee(DrawChart.class, "Scattergram");
+		if (charterTask == null)
+			return sorry(getName() + " couldn't start because no charting module obtained.");
+		setXCommand = makeCommand("setX", this);
+		setYCommand = makeCommand("setY", this);
+		ntxC =makeCommand("setValuesX",  this);
+		ntyC =makeCommand("setValuesY",  this);
+		ntC =makeCommand("setValues",  this);
+		numberTaskXName = new MesquiteString();
+		numberTaskYName = new MesquiteString();
+
+		window =  new NodeScattergramWindow(this);
+		setModuleWindow(window);
+		window.setWindowSize(400,400);
+		if (!MesquiteThread.isScripting()) {
+			String expl = "(For instance, the X and Y axes might show the same calculations but for different characters, or they may show two entirely different calculations.)";
+			separateAxes = (numModulesAvailable(NumbersForNodesIncr.class)==0) || !AlertDialog.query(containerOfModule(), "Axes", "Choose same or different calculations for the two axes? " + expl, "Same", "Different");
+			if (!separateAxes){
+				numbersForNodesTaskX = (NumbersForNodesIncr)hireEmployee(NumbersForNodesIncr.class, "Values for axes");
+				if (numbersForNodesTaskX == null)
+					return sorry(getName() + " couldn't start because no calculating module obtained.");
+				/*if (numModulesAvailable(NumbersForNodesIncr.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumbersForNodesIncr.class);
+		 			mss.setSelected(numberTaskXName);
+				}*/
+				numberTaskXName.setValue(numbersForNodesTaskX.getName());
+				numbersForNodesTaskX.setHiringCommand(ntC);
+				numbersForNodesTaskY = numbersForNodesTaskX;
+			}
+			else {
+				/*MesquiteMenuSpec xMenu = addAuxiliaryMenu("X");
+				if (numModulesAvailable(NumbersForNodes.class)>1){ 
+					MesquiteSubmenuSpec mss = addSubmenu(xMenu, "Values on X", ntxC, NumbersForNodes.class);
+					mss.setSelected(numberTaskXName);
+				}*/
+				numbersForNodesTaskX = (NumbersForNodes)hireEmployee(NumbersForNodes.class, "Values for X axis");
+				if (numbersForNodesTaskX == null)
+					return sorry(getName() + " couldn't start because no calculating module for X axis obtained.");
+				//numbersForNodesTaskX.setMenuToUse(xMenu);
+				numbersForNodesTaskX.setHiringCommand(ntxC);
+				numberTaskXName.setValue(numbersForNodesTaskX.getName());
+
+
+				/*MesquiteMenuSpec yMenu = addAuxiliaryMenu("Y");
+				if (numModulesAvailable(NumbersForNodes.class)>1){
+					MesquiteSubmenuSpec mss = addSubmenu(yMenu, "Values on Y", ntyC, NumbersForNodes.class);
+					mss.setSelected(numberTaskYName);
+				}*/
+				numbersForNodesTaskY = (NumbersForNodes)hireEmployee(NumbersForNodes.class, "Values for Y axis");
+				if (numbersForNodesTaskY == null)
+					return sorry(getName() + " couldn't start because no calculating module for Y axis obtained.");
+				//numbersForNodesTaskY.setMenuToUse(yMenu);
+				numberTaskYName.setValue(numbersForNodesTaskY.getName());
+				numbersForNodesTaskY.setHiringCommand(ntyC);
+			}
+			setMenus();
+			window.setVisible(true);
+		}
+		if (getEmployer() instanceof TreeWindowMaker) {
+			addMenuItem( "Tree labels", makeCommand("toggleTreeLabels",  this));
+			treeDisplay = ((TreeWindowMaker)getEmployer()).getTreeDisplay();
+			nsLabeller = new NodeLabeller(this, treeDisplay, (NodeScattergramWindow)window);
+			nsLabeller.setShowLabels(showTreeLabels);
+
+			treeDisplay.addExtra(nsLabeller);
+		}
+		makeMenu("Scattergram");
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == charterTask)
+			iQuit();
+	}
+	MesquiteMenuSpec xMenu, yMenu;
+	private void setMenus(){
+		if (!separateAxes){
+			if (numModulesAvailable(NumbersForNodesIncr.class)>1) {
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumbersForNodesIncr.class);
+				mss.setSelected(numberTaskXName);
+			}
+		}
+		else {
+			xMenu = addAuxiliaryMenu("X");
+			if (numModulesAvailable(NumbersForNodes.class)>1){ 
+				MesquiteSubmenuSpec mss = addSubmenu(xMenu, "Values on X", ntxC, NumbersForNodes.class);
+				mss.setSelected(numberTaskXName);
+			}
+			if (numbersForNodesTaskX != null)
+				numbersForNodesTaskX.setMenuToUse(xMenu);
+
+
+			yMenu = addAuxiliaryMenu("Y");
+			numberTaskYName = new MesquiteString();
+			if (numModulesAvailable(NumbersForNodes.class)>1){
+				MesquiteSubmenuSpec mss = addSubmenu(yMenu, "Values on Y", ntyC, NumbersForNodes.class);
+				mss.setSelected(numberTaskYName);
+			}
+			if (numbersForNodesTaskY != null)
+				numbersForNodesTaskY.setMenuToUse(yMenu);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		if (nsLabeller != null)
+			nsLabeller.turnOff();
+		iQuit();
+	}
+	/*...................................................................................................................*/
+	public void pointMouseDown(MesquiteChart chart, int whichPoint, MesquiteNumber valueX, MesquiteNumber valueY, int x, int y, int modifiers, String message){
+		((NodeScattergramWindow)window).pointTouched(tree, whichPoint);
+	}
+	/*...................................................................................................................*/
+	public void pointMouseUp(MesquiteChart chart, int whichPoint, int x, int y, int modifiers, String message){
+		((NodeScattergramWindow)window).pointReleased(tree, whichPoint);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend");
+		temp.addLine("setChartType ", charterTask); 
+		if (separateAxes){
+			temp.addLine("differentAxes");
+			temp.addLine("setValuesX ", numbersForNodesTaskX); 
+			temp.addLine("setValuesY ", numbersForNodesTaskY); 
+			if (numbersForNodesTaskX instanceof Incrementable){
+				Incrementable inc = (Incrementable)numbersForNodesTaskX;
+				temp.addLine("setX " + inc.toExternal(currentX)); 
+			}
+			if (numbersForNodesTaskY instanceof Incrementable){
+				Incrementable inc = (Incrementable)numbersForNodesTaskY;
+				temp.addLine("setY " + inc.toExternal(currentY)); 
+			}
+		}
+		else {
+			temp.addLine("sameAxes");
+			temp.addLine("setValues ", numbersForNodesTaskX); 
+			if (numbersForNodesTaskX instanceof Incrementable){
+				Incrementable inc = (Incrementable)numbersForNodesTaskX;
+				temp.addLine("setX " + inc.toExternal(currentX)); 
+				temp.addLine("setY " + inc.toExternal(currentY)); 
+			}
+		}
+		temp.addLine("toggleTreeLabels " + MesquiteBoolean.toOffOnString(showTreeLabels)); 
+		if (window ==null)
+			return null;
+		Snapshot fromWindow = window.getSnapshot(file);
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+		temp.addLine("doCounts");
+		temp.addLine("resume");
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets chart drawing module", "[module name]", commandName, "setChartType")){
+			DrawChart temp =  (DrawChart)replaceEmployee(DrawChart.class, arguments, "Type of chart", charterTask);
+			if (temp!=null) {
+				charterTask=  temp;
+
+				if (tree instanceof Associable)
+					charterTask.pointsAreSelectable(true, (Selectionable)tree, false);
+				((NodeScattergramWindow)window).setCharter(charterTask.createCharter(this));
+				getModuleWindow().contentsChanged();
+				return temp;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Requests that calculations be redone", null, commandName, "doCounts")) { 
+			doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Sets both axes to use the same calculation", null, commandName, "sameAxes")) { //todo: let this change after the chart is established
+			separateAxes = false;
+			setMenus();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the axes to use different calculations", null, commandName, "differentAxes")) {
+			separateAxes = true;
+			setMenus();
+			/*if (numModulesAvailable(NumbersForNodes.class)>1){ 
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values on X", ntxC, NumbersForNodes.class);
+				mss.setSelected(numberTaskXName);
+			}
+
+			if (numModulesAvailable(NumbersForNodes.class)>1){
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values on Y", ntyC, NumbersForNodes.class);
+				mss.setSelected(numberTaskYName); 
+			}*/
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the nodes for both axes", "[name of module]", commandName, "setValues")) {
+			NumbersForNodes temp =  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Choose values for axes",numbersForNodesTaskX);
+			if (temp!=null) {
+				numbersForNodesTaskX=  temp;
+				numbersForNodesTaskY = temp;
+				numberTaskXName.setValue(numbersForNodesTaskX.getName());
+				numbersForNodesTaskX.setHiringCommand(ntC);
+				currentX=0;
+				currentY=1;
+				doCounts();
+				getModuleWindow().contentsChanged();
+			}
+			return numbersForNodesTaskX;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the nodes for the X axis", "[name of module]", commandName, "setValuesX")) {
+			NumbersForNodes temp =  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Choose values for X axis",numbersForNodesTaskX);
+			if (temp!=null) {
+				numbersForNodesTaskX=  temp;
+				numberTaskXName.setValue(numbersForNodesTaskX.getName());
+				numbersForNodesTaskX.setHiringCommand(ntxC);
+				currentX=0;
+				if (separateAxes && yMenu != null && numbersForNodesTaskX != null)
+					numbersForNodesTaskX.setMenuToUse(xMenu);
+				doCounts();
+				getModuleWindow().contentsChanged();
+			}
+			return numbersForNodesTaskX;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the nodes for the Y axis", "[name of module]", commandName, "setValuesY")) {
+			NumbersForNodes temp =  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Choose values for Y axis",numbersForNodesTaskY);
+			if (temp!=null) {
+				numbersForNodesTaskY=  temp;
+				numberTaskYName.setValue(numbersForNodesTaskY.getName());
+				numbersForNodesTaskY.setHiringCommand(ntyC);
+				if (separateAxes && yMenu != null && numbersForNodesTaskY != null)
+					numbersForNodesTaskY.setMenuToUse(yMenu);
+				currentY=0;
+				doCounts();
+				getModuleWindow().contentsChanged();
+			}
+			return numbersForNodesTaskY;
+		}
+		else if (checker.compare(this.getClass(), "Sets which item is shown on the x axis (appropriate where the calculator can supply a series of items, e.g. characters)", "[item number]", commandName, "setX")) {
+			if (numbersForNodesTaskX instanceof Incrementable){
+				Incrementable inc = (Incrementable)numbersForNodesTaskX;
+				int ic = (MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (!MesquiteInteger.isCombinable(ic))
+					ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose ", "choose:", 1); //TODO have something more intelligent here
+				int icInternal = (int)inc.toInternal(ic);
+				if (MesquiteInteger.isCombinable(icInternal) && (icInternal>=inc.getMin()) && (icInternal<=inc.getMax())) {
+					currentX=icInternal;
+					if (!MesquiteThread.isScripting()){
+						doCounts();
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which item is shown on the y axis (appropriate where the calculator can supply a series of items, e.g. characters)", "[item number]", commandName, "setY")) {
+			if (numbersForNodesTaskY instanceof Incrementable){
+				Incrementable inc = (Incrementable)numbersForNodesTaskY;
+				int ic = (MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+				if (!MesquiteInteger.isCombinable(ic))
+					ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose ", "choose:", 1); //TODO have something more intelligent here
+				int icInternal = (int)inc.toInternal(ic);
+				if (MesquiteInteger.isCombinable(icInternal) && (icInternal>=inc.getMin()) && (icInternal<=inc.getMax())) {
+					currentY=icInternal;
+					if (!MesquiteThread.isScripting()){
+						doCounts();
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the tree labels are shown", "[on or off]", commandName, "toggleTreeLabels")) {
+			//TODO: use MesquiteBoolean checkmark
+			if (StringUtil.blank(arguments))
+				showTreeLabels = !showTreeLabels;
+			else {
+				String s = ParseUtil.getFirstToken(arguments, pos);
+				if ("on".equalsIgnoreCase(s))
+					showTreeLabels = true;
+				else if  ("off".equalsIgnoreCase(s))
+					showTreeLabels = false;
+			}
+			nsLabeller.setShowLabels(showTreeLabels);
+
+			treeDisplay.pleaseUpdate(false);
+		} 
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	long oldTreeID = -1;
+	long oldTreeVersion = 0;
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree==null)
+			return;
+		this.tree=tree;
+		if (tree instanceof Associable)
+			charterTask.pointsAreSelectable(true, (Selectionable)tree, false);
+		if (oldTreeID==-1) {
+			if (numbersForNodesTaskX==null)
+				return;
+			numbersForNodesTaskX.initialize(tree);
+			if (numbersForNodesTaskX != numbersForNodesTaskY && numbersForNodesTaskY!=null)
+				numbersForNodesTaskY.initialize(tree);
+			doCounts();
+		}
+		else if (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion) {
+			doCounts();
+		}
+		else {
+			if (window!=null &&((NodeScattergramWindow)window).getChart()!=null ) {
+				((NodeScattergramWindow)window).getChart().getField().repaint(); //for selection Only
+				((NodeScattergramWindow)window).getChart().repaint(); //for selection Only
+			}
+		}
+		oldTreeID = tree.getID();
+		oldTreeVersion = tree.getVersionNumber();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof NumbersForNodes) {
+			if (numbersForNodesTaskX!=null && numbersForNodesTaskY!=null)
+				doCounts();
+		}
+
+	}
+	int numItemsX(){
+		if (tree==null)
+			return 0;
+		return 1;
+		//numbersForNodesTaskX.getNumberOfCharacters(tree);
+	}
+	int numItemsY(){
+		if (tree==null)
+			return 0;
+		return 1;
+		//numbersForNodesTaskY.getNumberOfCharacters(tree);
+	}
+	/*.................................................................................................................*/
+	public void doCounts() {
+		if (!suspend) {
+			((NodeScattergramWindow)window).blankChart();
+			((NodeScattergramWindow)window).setTree(tree);
+			((NodeScattergramWindow)window).recalcChart();
+		}
+	}
+	public void endJob() {
+		if (treeDisplay !=null)
+			treeDisplay.removeExtra(nsLabeller);
+		super.endJob();
+	}
+}
+
+/*========================================================*/
+class NodeLabeller extends TreeDisplayExtra {
+	LabelsAtNodes labelsAtNodes;
+	NodeScattergramWindow chartWindow;
+	Color brightGreen, brightbrightGreen;
+	boolean showLabels = true;
+	int labelDrawn = -1;
+
+	public NodeLabeller (MesquiteModule ownerModule, TreeDisplay treeDisplay, NodeScattergramWindow chartWindow) {
+		super(ownerModule, treeDisplay);
+		this.chartWindow =chartWindow;
+		brightGreen = new Color((float)0.4, (float)1.0, (float)0.4);
+		brightbrightGreen = new Color((float)0.6, (float)1.0, (float)0.6);
+	}
+	/*.................................................................................................................*/
+	public void drawOneLabel(int N, Tree tree, Graphics g) {
+		makeSureLabelsReady(tree);
+		int nodeX = treeDisplay.getTreeDrawing().x[N];
+		int nodeY = treeDisplay.getTreeDrawing().y[N];
+		MesquiteLabel c = (MesquiteLabel)labelsAtNodes.getPanel(N);
+
+		c.setColor(brightbrightGreen); 
+		c.setText("Node " + N);  
+		String[] results = chartWindow.getStrings(N);
+		for (int i = 0; i<results.length; i++)
+			c.addLine(results[i]);  
+
+		c.setVisible(true);
+		c.repaint();
+		int w = c.getWidth(g);
+		if (w+nodeX+16>treeDisplay.getBounds().width)
+			c.setLocation(treeDisplay.getBounds().width- w, nodeY + 18);
+		else
+			c.setLocation(nodeX + 16, nodeY + 18);
+		g.setColor(brightGreen);
+		g.setXORMode(Color.white);
+		g.drawLine(nodeX, nodeY, c.getBounds().x, c.getBounds().y);
+		g.drawLine(nodeX, nodeY+1, c.getBounds().x, c.getBounds().y + 1);
+		g.drawLine(nodeX, nodeY+2, c.getBounds().x, c.getBounds().y + 2);
+		g.drawLine(nodeX, nodeY+3, c.getBounds().x, c.getBounds().y + 3);
+		g.setPaintMode();
+		g.setColor(Color.black);
+		labelDrawn = N;
+	}
+	/*.................................................................................................................*/
+	public void hideOneLabel(int N, Graphics g) {
+		if (labelsAtNodes == null)
+			return;
+		MesquiteLabel c = (MesquiteLabel)labelsAtNodes.getPanel(N);
+		if (c==null)
+			return;
+		c.setVisible(false);
+		if (g==null)
+			return;
+		int nodeX = treeDisplay.getTreeDrawing().x[N];
+		int nodeY = treeDisplay.getTreeDrawing().y[N];
+		g.setColor(brightGreen);
+		g.setXORMode(Color.white);
+		g.drawLine(nodeX, nodeY, c.getBounds().x, c.getBounds().y);
+		g.drawLine(nodeX, nodeY+1, c.getBounds().x, c.getBounds().y + 1);
+		g.drawLine(nodeX, nodeY+2, c.getBounds().x, c.getBounds().y + 2);
+		g.drawLine(nodeX, nodeY+3, c.getBounds().x, c.getBounds().y + 3);
+		g.setPaintMode();
+		labelDrawn = -1;
+	}
+	/*.................................................................................................................*/
+	private void drawLabels(int N, Tree tree, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawLabels(d, tree, g);
+		drawOneLabel(N, tree, g);
+	}
+	/*.................................................................................................................*/
+	public void hideLabels() {
+		if (labelsAtNodes==null)
+			return;
+		Graphics g = treeDisplay.getGraphics();
+		for (int N = 0; N<labelsAtNodes.getNumNodes(); N++) {
+			if (N== labelDrawn)
+				hideOneLabel(N, g);
+			else
+				labelsAtNodes.getPanel(N).setVisible(false);
+		}
+		if (g!=null)
+			g.dispose();
+	}
+	public void setShowLabels(boolean show) {
+		showLabels = show;
+		if (labelsAtNodes!=null && !showLabels)
+			hideLabels();
+
+	}
+	private void makeSureLabelsReady(Tree tree){
+		if (labelsAtNodes==null) {
+			labelsAtNodes = new LabelsAtNodes(ownerModule, tree.getNumNodeSpaces(), treeDisplay);
+		}
+		else if (labelsAtNodes.getNumNodes()!=tree.getNumNodeSpaces() ) {
+			labelsAtNodes.resetNumNodes(tree.getNumNodeSpaces());
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (showLabels) {
+			makeSureLabelsReady(tree);
+			drawLabels(drawnRoot, tree, g);
+			g.setColor(Color.black);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	/*.................................................................................................................*/
+	public void turnOff() {
+		super.turnOff();
+		if (labelsAtNodes!=null)
+			labelsAtNodes.dispose();
+	}
+}
+
+/*========================================================*/
+class NodeScattergramWindow extends ChartWindow {
+	private int windowWidth=0;
+	private int windowHeight=0;
+	private NodesScattergram ownerModule;
+	private NumberArray xArray, yArray, zArray;
+	private boolean weightedBranches = true;
+	String nameA, nameB;
+	Charter charter;
+	Tree tree;
+	DoubleMiniScroll scrollBox;
+	MesquiteChart chart;
+	static int numMade = 0;
+	int thisMade;
+
+	public NodeScattergramWindow ( NodesScattergram ownerModule) {
+		super(ownerModule, true); //infobar
+		this.ownerModule = ownerModule;
+		numMade++;
+		thisMade = numMade;
+		charter = ownerModule.charterTask.createCharter(ownerModule);
+		charter.setShowNames(true);
+		chart=new MesquiteChart(ownerModule, 100, 0, charter);
+		setChart(chart);
+		xArray = new NumberArray(3);
+		yArray = new NumberArray(3);
+		zArray = new NumberArray(3);
+		chart.deassignChart();
+		addToWindow(chart);
+		chart.setVisible(true);
+		chart.setBackground(getBackground());
+		scrollBox = new DoubleMiniScroll(ownerModule.setXCommand, ownerModule.setYCommand, 0,0,0,0,0,0);
+		chart.add(scrollBox);
+		scrollBox.setYTitle("Y");
+		scrollBox.setXTitle("X");
+		//scrollBox.setLocation(10, getHeight()-10);
+		scrollBox.setLocation(2, getHeight()-24- scrollBox.getBounds().height);
+		resetTitle();
+	}
+
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Nodes Scattergram " + (thisMade));
+	}
+	/*.................................................................................................................*/
+	private void resetScrolls(){
+		if (ownerModule.numbersForNodesTaskX instanceof Incrementable){
+			Incrementable inc = (Incrementable)ownerModule.numbersForNodesTaskX;
+			scrollBox.setXTitle(inc.getItemTypeName());
+			int min = (int)inc.toExternal(inc.getMin());
+			int max = (int)inc.toExternal(inc.getMax());
+			scrollBox.setXValues(min,  (int)inc.toExternal(ownerModule.currentX), max);
+			scrollBox.setXVisible(true);
+		}
+		else {
+			scrollBox.setXValues(0,0,0);
+			scrollBox.setXVisible(false);
+		}
+		if (ownerModule.numbersForNodesTaskY instanceof Incrementable){
+			Incrementable inc = (Incrementable)ownerModule.numbersForNodesTaskY;
+			scrollBox.setYTitle(inc.getItemTypeName());
+			int min = (int)inc.toExternal(inc.getMin());
+			int max = (int)inc.toExternal(inc.getMax());
+			scrollBox.setYValues(min,  (int)inc.toExternal(ownerModule.currentY), max);
+			scrollBox.setYVisible(true);
+		}
+		else {
+			scrollBox.setYValues(0,0,0);
+			scrollBox.setYVisible(false);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setVisible(boolean vis){
+		if (vis)
+			windowResized();
+		super.setVisible(vis);
+	}
+	/*.................................................................................................................*/
+	public void setCharter(Charter charter) {
+		charter.setShowNames(true);
+		chart.setCharter(charter);
+	}
+	/*.................................................................................................................*/
+	public String[] getStrings(int index) {
+		return new String[] {"X (" + ownerModule.numbersForNodesTaskX.getName() + "): " + xArray.toString(index), "Y (" + ownerModule.numbersForNodesTaskY.getName() + "): " + yArray.toString(index)};
+	}
+	/*.................................................................................................................*/
+	public void setTree(Tree tree) {
+		this.tree = tree;
+
+	}
+	/*.................................................................................................................*/
+	public void recalcChart() {
+		chart.deassignChart();
+		if (ownerModule.numbersForNodesTaskX != null && ownerModule.numbersForNodesTaskY != null) {
+			resetScrolls();
+			int numNodes = tree.getNumNodeSpaces();
+			xArray.resetSize(numNodes);
+			yArray.resetSize(numNodes);
+			chart.deConstrainMinimumX();
+			chart.deConstrainMaximumX();
+			chart.deConstrainMinimumY();
+			chart.deConstrainMaximumY();
+			//zArray.resetSize(numNodes);
+			MesquiteNumber resultX = new MesquiteNumber();
+			MesquiteNumber resultY = new MesquiteNumber();
+			//MesquiteNumber resultZ = new MesquiteNumber();
+			if (ownerModule.numbersForNodesTaskX instanceof Incrementable)
+				((Incrementable)ownerModule.numbersForNodesTaskX).setCurrent(ownerModule.currentX); 
+			xArray.deassignArray();
+			yArray.deassignArray();
+			ownerModule.numbersForNodesTaskX.calculateNumbers(tree, xArray, null);
+			chart.setXAxisName(ownerModule.numbersForNodesTaskX.getNameAndParameters());   //set to correct name
+			if (ownerModule.numbersForNodesTaskY instanceof Incrementable)
+				((Incrementable)ownerModule.numbersForNodesTaskY).setCurrent(ownerModule.currentY);
+			ownerModule.numbersForNodesTaskY.calculateNumbers(tree, yArray, null);
+			chart.setYAxisName(ownerModule.numbersForNodesTaskY.getNameAndParameters());  //TODO: this should use string passed back from calculateNumbers
+			for (int i=0; i<numNodes; i++) {
+				if (tree.nodeInTree(i) && tree.nodeIsInternal(i)) { //todo: have toggle for internal only
+					xArray.placeValue(i, resultX);
+					yArray.placeValue(i, resultY);
+					//zArray.placeValue(i, resultZ);
+
+					int point = chart.addPoint(resultX, resultY);
+					//int point = chart.addPoint(resultX, resultY, resultZ);
+					String label = tree.getNodeLabel(i); //added 30 Oct 01
+					if (label == null)//added 30 Oct 01
+						chart.setName(point, Integer.toString(i));
+					else
+						chart.setName(point, label);//added 30 Oct 01
+					//chart.setCategory(point, nodeJustInternal(tree, i));
+				}
+				else { //these are here to ensure number of points is in parallel with numbering of nodes, for selection and other purposes
+					resultX.setToUnassigned();
+					int point = chart.addPoint(resultX, resultX);
+				}
+			}
+			contentsChanged();
+			chart.munch();
+		}
+		ownerModule.treeDisplay.pleaseUpdate(false);
+
+	}
+	/*.................................................................................................................*/
+	public void pointTouched(Tree tree, int which) {
+		if (ownerModule.nsLabeller==null)
+			return;
+		int count = 0;
+		Graphics g = ownerModule.treeDisplay.getGraphics();
+		if (g!=null) {
+			for (int i=0; i<tree.getNumNodeSpaces(); i++) {
+				if (tree.nodeInTree(i) && tree.nodeIsInternal(i)) {
+					if (count == which) {
+						ownerModule.nsLabeller.drawOneLabel(i, tree, g);
+					}
+					count++;
+				}
+			}
+			g.dispose();
+		}
+
+	}
+	/*.................................................................................................................*/
+	public void pointReleased(Tree tree, int which) {
+		if (ownerModule.nsLabeller.showLabels)
+			return;
+		int count = 0;
+		Graphics g = ownerModule.treeDisplay.getGraphics();
+		if (g!=null) {
+			for (int i=0; i<tree.getNumNodeSpaces(); i++) {
+				if (tree.nodeInTree(i) && tree.nodeIsInternal(i)) {
+					if (count == which) {
+						ownerModule.nsLabeller.hideOneLabel(i, g);
+					}
+					count++;
+				}
+			}
+			g.dispose();
+		}
+		ownerModule.nsLabeller.hideLabels();
+	}
+
+	public void windowResized() {
+		super.windowResized();
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (chart!=null && (windowWidth!=getWidth() || windowHeight!=getHeight())) {
+			windowWidth=getWidth();
+			windowHeight=getHeight();
+			chart.setLocation(0, 20);
+			chart.setChartSize(windowWidth-20, windowHeight-20);
+			scrollBox.setLocation(2, getHeight()-24- scrollBox.getBounds().height);
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+
diff --git a/Source/mesquite/charts/Notes/Chart Notes.txt b/Source/mesquite/charts/Notes/Chart Notes.txt
new file mode 100644
index 0000000..4c66ff0
--- /dev/null
+++ b/Source/mesquite/charts/Notes/Chart Notes.txt	
@@ -0,0 +1,8 @@
+Notes for mesquite.charts
+----------------------------------
+
+- rewrite entire charting undercode into separate components:
+	- generation and storage of data (one, two, three... values per item)
+	- modules for display of charts that would allow much more flexibility in presentation
+	
+-color by codon positions
\ No newline at end of file
diff --git a/Source/mesquite/charts/Scattergram/Scattergram.java b/Source/mesquite/charts/Scattergram/Scattergram.java
new file mode 100644
index 0000000..4dc28b1
--- /dev/null
+++ b/Source/mesquite/charts/Scattergram/Scattergram.java
@@ -0,0 +1,1723 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.Scattergram;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+/* A module drawing scattergrams (scatterplots).  Each data point represents an item, for instance a tree or character, and is plotted according to the item's
+values on x and y axes.   Each data point may be colored according to a third value, implicitly yielding a third (z) axis.
+
+This is designed to accommodate at least three uses:
+(1) a standard scatterplot with each point represented explicitly
+(2) a density diagram where the field is divided into blocks, and each block is grayscale shaded to indicate how many data points fall within it
+(3) a protein visualization in which the x y axes represent the position of the residue in space and the color of the point some value for the residue.  This last
+use is probably temporary until another module is tailor-made for the purpose.  
+
+The labels "x" and "y" could refer either to the horizontal and vertical pixels of the chart's field, or to the values displayed in the chart (e.g.
+treelength of 100, asymmetry of 0.83, etc.). To limit confusion xPixel and yPixel are used in some cases when the variables refer to the pixel values.
+ */
+
+public class Scattergram extends DrawChart {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Scattergram";
+	}
+	public String getExplanation() {
+		return "Helps make scattergram charts." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ScattergramAssistantA.class, getName() + " can optionally display extra information (such as regression lines).",
+				"You can request such extra information under the Analysis submenu of the Chart menu of a Scattergram.");
+	}
+	/*.................................................................................................................*/
+	Vector charters;
+	public int spotSize = 10;
+	public boolean useCircle = true;
+	public MesquiteBoolean sizeToFit = new MesquiteBoolean(true);  //currently always true; is the graph in scrollpane (false) or not (true)
+	public MesquiteBoolean joinTheDots = new MesquiteBoolean(false); //are points joined by line; used for special effects like protein visualization
+	public MesquiteBoolean joinLastToFirst = new MesquiteBoolean(true);
+	public MesquiteBoolean thickLine = new MesquiteBoolean(false);//lines between points are thick; used for special effects like protein visualization
+	public MesquiteBoolean showDots = new MesquiteBoolean(true); //points can be turned off e.g. for density view or protein visualizaiton
+	public MesquiteBoolean showLegend = new MesquiteBoolean(true); //legend for colors of points
+	public MesquiteBoolean sumByBlocks = new MesquiteBoolean(false);//is density by blocks shown?
+	int movingWindowSizeZ = 1;  //used in coloring of points, in particular for special effects like protein visualization
+	Selectionable pointsAssociable = null;
+	boolean areParts = false;
+	Vector holding;
+	boolean allowSequenceOptions;
+
+	MesquiteCommand sizeDrawingCommand;
+	MesquiteMenuItemSpec sizeItem;
+	MesquiteSubmenuSpec selectSubmenu;
+	MesquiteMenuItemSpec[] menuItems;
+	public int totalFieldWidth= MesquiteInteger.unassigned;
+	public int totalFieldHeight= MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charters = new Vector();
+		holding = new Vector();
+		/*
+		REMOVED as not working well
+		addCheckMenuItem(null, "Size To Window", MesquiteModule.makeCommand("toggleSizeToFit",  this), sizeToFit);
+		 */
+		addMenuItem("Marker size...", MesquiteModule.makeCommand("markerSize",  this));
+		selectSubmenu = addSubmenu(null, "Select");
+		addItemToSubmenu(null, selectSubmenu, "Deselect all", MesquiteModule.makeCommand("selectionOff",  this));
+		menuItems= new MesquiteMenuItemSpec[11];
+		MesquiteSubmenuSpec analysis = addSubmenu(null, "Auxiliary Analysis", makeCommand("newAssistant", this), ScattergramAssistantA.class);
+		MesquiteSubmenuSpec mCloseAsst = addSubmenu(null, "Close Auxiliary Analysis");
+		addMenuItem("-", null);
+		mCloseAsst.setList(getEmployeeVector());
+		mCloseAsst.setListableFilter(ScattergramAssistantA.class);
+		mCloseAsst.setCommand(makeCommand("closeAssistant",  this));
+
+		resetMenus();
+		/*
+		sizeDrawingCommand = MesquiteModule.makeCommand("sizeDrawing",  this);
+		if (!sizeToFit.getValue())
+			sizeItem = addMenuItem("Drawing Size...", sizeDrawingCommand);
+		 */
+		return true;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	void resetMenus(){
+		for (int i=0; i<menuItems.length; i++) {
+			if (menuItems[i]!=null)
+				deleteMenuItem(menuItems[i]);
+			menuItems[i]=null;
+		}
+		if (pointsAssociable!=null && allowSequenceOptions){
+			menuItems[0] = addItemToSubmenu(null, selectSubmenu, "Select range...", MesquiteModule.makeCommand("selectRange",  this));
+			menuItems[1] = addItemToSubmenu(null, selectSubmenu, "March selection forward", MesquiteModule.makeCommand("marchSelection",  this));
+			menuItems[1].setShortcut(KeyEvent.VK_UP); //right
+			menuItems[2] = addItemToSubmenu(null, selectSubmenu, "March selection backward", MesquiteModule.makeCommand("unmarchSelection",  this));
+			menuItems[2].setShortcut(KeyEvent.VK_DOWN);
+		}
+
+		menuItems[3] = addSubmenu(null, "Special Effects");
+
+		menuItems[9] = addCheckMenuItemToSubmenu(null, (MesquiteSubmenuSpec)menuItems[3], "Show Density", MesquiteModule.makeCommand("sumByBlocks",  this), sumByBlocks);
+
+		if (pointsAssociable!=null && allowSequenceOptions){
+			menuItems[4] = addCheckMenuItemToSubmenu(null, (MesquiteSubmenuSpec)menuItems[3], "Join the dots", MesquiteModule.makeCommand("toggleJoin",  this), joinTheDots);
+			menuItems[5] = addCheckMenuItemToSubmenu(null, (MesquiteSubmenuSpec)menuItems[3], "Join last to first", null, joinLastToFirst);
+			menuItems[6] = addCheckMenuItemToSubmenu(null, (MesquiteSubmenuSpec)menuItems[3], "Thick joints", null, thickLine);
+		}
+
+		menuItems[7] =  addCheckMenuItemToSubmenu(null, (MesquiteSubmenuSpec)menuItems[3], "Show dots", null, showDots);
+
+		if (pointsAssociable!=null && allowSequenceOptions){
+			if (joinTheDots.getValue()) {
+				menuItems[5].setCommand(MesquiteModule.makeCommand("toggleLastToFirst",  this));
+				menuItems[6].setCommand(MesquiteModule.makeCommand("toggleThickJoin",  this));
+				menuItems[7].setCommand(MesquiteModule.makeCommand("toggleShowDots",  this));
+			}
+			else {
+				menuItems[5].setCommand(null);
+				menuItems[6].setCommand(null);
+				if (!sumByBlocks.getValue())
+					menuItems[7].setCommand(null);
+				else
+					menuItems[7].setCommand(MesquiteModule.makeCommand("toggleShowDots",  this));
+			}
+		}
+		else {
+			if (!sumByBlocks.getValue())
+				menuItems[7].setCommand(null);
+			else
+				menuItems[7].setCommand(MesquiteModule.makeCommand("toggleShowDots",  this));
+		}
+
+		if (pointsAssociable!=null && allowSequenceOptions){
+			if (menuItems[8]==null) {
+				MesquiteMenuSpec mmisc = findMenuAmongEmployers("Colors");
+				if (mmisc !=null)
+					menuItems[8] = addMenuItem(mmisc, "Moving Window for Colors...", MesquiteModule.makeCommand("movingWindowSize",  this));
+			}
+			//if (menuItems[9]==null)
+			//menuItems[9] = addMenuItem(findMenuAmongEmployers("Colors"), "Animated moving window", MesquiteModule.makeCommand("animateWindow",  this));
+			if (menuItems[10]==null)
+				menuItems[10] = addMenuItem("-", null);
+		}
+		else {
+			if (joinTheDots.getValue()) {
+				joinTheDots.setValue(false);
+				setJoinTheDots();
+			}
+			if (!showDots.getValue() && !sumByBlocks.getValue()) {
+				showDots.setValue(true);
+				setShowDots();
+			}
+
+		}
+	}
+
+	public   Charter createCharter(ChartListener listener) {
+		ScattergramCharter c = new ScattergramCharter(this, listener);
+		charters.addElement(c);
+		return c;
+	}
+	/* tells the module whether points are parts of an Associable object */
+	public void pointsAreSelectable(boolean areParts, Selectionable a, boolean allowSequenceOptions){
+		if (this.areParts!=areParts || pointsAssociable!=a){
+			if (pointsAssociable!=null)
+				pointsAssociable.removeListener(this);
+			this.areParts = areParts;
+			pointsAssociable =a;
+			this.allowSequenceOptions = allowSequenceOptions;
+			if (!areParts)
+				pointsAssociable = null;
+			if (pointsAssociable!=null)
+				pointsAssociable.addListener(this);
+			syncSel();
+			resetMenus();
+			resetContainingMenuBar();
+		}
+	}
+
+	/* Synchronize selection of points in chart with parts of associable*/
+	void syncSel(){
+		Enumeration e = charters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ScattergramCharter) {
+				ScattergramCharter tCO = (ScattergramCharter)obj;
+				tCO.synchronizeSelection();
+				tCO.chart.calculateAllExtras();
+				tCO.chart.getField().repaint();
+			}
+		}
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if ((obj==pointsAssociable || obj instanceof Selectionable) && (code == MesquiteListener.SELECTION_CHANGED ||code == MesquiteListener.PARTS_MOVED ||  code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_ADDED)) {
+			syncSel();
+		}
+	}
+	public void endJob(){
+		if (pointsAssociable!=null)
+			pointsAssociable.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		/*
+		temp.addLine("toggleSizeToFit " + sizeToFit.toOffOnString());
+		if (!sizeToFit.getValue() && (MesquiteInteger.isCombinable(totalFieldWidth)||MesquiteInteger.isCombinable(totalFieldHeight))) {
+			temp.addLine("sizeDrawing " + MesquiteInteger.toString(totalFieldWidth) + " " + MesquiteInteger.toString(totalFieldHeight));
+		}
+		 */
+		temp.addLine("markerSize " + spotSize);
+
+		temp.addLine("toggleJoin " + joinTheDots.toOffOnString());
+		if (joinTheDots.getValue()) {
+			temp.addLine("toggleThickJoin " + thickLine.toOffOnString());
+			temp.addLine("toggleLastToFirst " + joinLastToFirst.toOffOnString());
+		}
+		temp.addLine("toggleShowDots " + showDots.toOffOnString());
+		temp.addLine("movingWindowSize " + movingWindowSizeZ);
+
+		temp.addLine("sumByBlocks " + sumByBlocks.toOffOnString());
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ScattergramAssistantA) {
+				temp.addLine("\tnewAssistant " , ((MesquiteModule)e));
+			}
+		}
+		return temp;
+	}
+	void addAssistantToCharter(ChartAssistant tda, ScattergramCharter tCO){
+
+		if (tCO.chart!=null){
+			ChartExtra tce = tda.createExtra(tCO.chart); //HOW TO REMOVE IF QUIT???
+			tCO.chart.addExtra(tce);
+			tce.doCalculations();
+			tCO.chart.getField().repaint();
+			tCO.chart.repaint();
+		}
+	}
+	/*.................................................................................................................*/
+	public void addAssistant(ChartAssistant tda) {
+		Enumeration e = charters.elements();
+		if (charters.size()==0) {
+			holding.addElement(tda);
+		}
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ScattergramCharter) {
+				ScattergramCharter tCO = (ScattergramCharter)obj;
+				addAssistantToCharter(tda, tCO);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Turns off selection of points", null, commandName, "selectionOff")) {
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.selectionOff();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires a chart assistant module", "[name of assistant module]", commandName, "newAssistant")) {
+			incrementMenuResetSuppression();
+			ScattergramAssistantA tda= (ScattergramAssistantA)hireNamedEmployee(ScattergramAssistantA.class, arguments);
+			if (tda!=null) {
+				addAssistant(tda);
+				if (!MesquiteThread.isScripting()) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof ScattergramCharter) {
+							ScattergramCharter tCO = (ScattergramCharter)obj;
+							tCO.chart.munch();
+						}
+					}
+					resetContainingMenuBar();
+				}
+				decrementMenuResetSuppression();
+				return tda;
+			}
+			else {
+				decrementMenuResetSuppression();
+				return findEmployeeWithName(parser.getFirstToken(arguments));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes an assistant module", "[number of assistant module]", commandName, "closeAssistant")) {
+			EmployeeVector ev = getEmployeeVector();
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			int count =0;
+			for (int i=0; i< ev.size(); i++){
+				MesquiteModule mb = (MesquiteModule)ev.elementAt(i);
+				if (mb!=null && mb instanceof ScattergramAssistantA) {
+					if (count== which) {
+						fireEmployee(mb);
+						Enumeration e = charters.elements();
+						while (e.hasMoreElements()) {
+							Object obj = e.nextElement();
+							if (obj instanceof ScattergramCharter) {
+								ScattergramCharter tCO = (ScattergramCharter)obj;
+								tCO.chart.removeAllExtrasOwned(mb);
+								tCO.chart.getField().repaint();
+								tCO.chart.repaint();
+							}
+						}
+						return null;
+					}
+					count++;
+				}
+			}
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "fireEmployee")) {
+			String name = parser.getFirstToken(arguments);
+			MesquiteModule mb = findEmployeeWithName(name);
+			if (mb!=null) {
+				fireEmployee(mb);
+				if (!MesquiteThread.isScripting()) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof ScattergramCharter) {
+							ScattergramCharter tCO = (ScattergramCharter)obj;
+							tCO.chart.munch();
+						}
+					}
+					resetContainingMenuBar();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Marches the selected points ahead one (appropriate if the points are in a relevant sequence)", null, commandName, "marchSelection")) {
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.marchSelection(true);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Marches the selected points backward one (appropriate if the points are in a relevant sequence)", null, commandName, "unmarchSelection")) {
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.marchSelection(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects a range of points", "[first point] [last point]", commandName, "selectRange")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			int h = MesquiteInteger.fromString(arguments, pos);
+			if ((MesquiteInteger.isCombinable(h)) || (MesquiteInteger.isCombinable(w))) {
+				Enumeration e = charters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof ScattergramCharter) {
+						ScattergramCharter tCO = (ScattergramCharter)obj;
+						tCO.selectRange(w-1,h-1);  //ASSUMES all will be 0 based: //todo: query about whether item is zero based??
+					}
+				}
+			}
+			else { 
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger first = new MesquiteInteger(0);
+				MesquiteInteger last =new MesquiteInteger(0);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Select range of points", "First",  "Last", answer,  first, last,MesquiteInteger.unassigned,MesquiteInteger.unassigned,MesquiteInteger.unassigned, MesquiteInteger.unassigned,MesquiteString.helpString);
+				if (answer.getValue() && first.isCombinable() && last.isCombinable()) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof ScattergramCharter) {
+							ScattergramCharter tCO = (ScattergramCharter)obj;
+							tCO.selectRange(first.getValue()-1,last.getValue()-1);   //TODO: need to convert to internal using clues from items sourcetask or associable (Associable should indicate if parts numbered extenrallay by 1
+						}
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of the moving window for coloring the markers via a third value (appropriate if there is a natural sequence to the points", null, commandName, "movingWindowSize")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(w))
+				w = MesquiteInteger.queryInteger(containerOfModule(), "Moving window", "Size of moving window for sequential coloring of markers (to turn off moving window, enter '1').", movingWindowSizeZ);
+			if (MesquiteInteger.isCombinable(w)) {
+				movingWindowSizeZ = w;
+				Enumeration e = charters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof ScattergramCharter) {
+						ScattergramCharter tCO = (ScattergramCharter)obj;
+						tCO.setMovingWindowSizeZ(movingWindowSizeZ);
+					}
+				}
+			}
+		}
+		/*	else if (checker.compare(this.getClass(), nullxxx, null, commandName, "animateWindow")) {
+  	    	 	//animated = !animated;
+			//here start up a thread that alters moving window size from 1 though numPoints
+    	 	}
+		 */
+		else if (checker.compare(this.getClass(), "Sets the use of circular spots as markers", null, commandName, "useCircle")) {
+			useCircle = true;
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setUseCircle(true);
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the use of square markers", null, commandName, "useSquare")) {
+			useCircle = false;
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setUseCircle(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of markers", "[size in pixels]", commandName, "markerSize")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(w))
+				w = MesquiteInteger.queryInteger(containerOfModule(), "Size of markers", "Size of markers.", spotSize);
+			if (MesquiteInteger.isCombinable(w)) {
+				spotSize = w;
+				Enumeration e = charters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof ScattergramCharter) {
+						ScattergramCharter tCO = (ScattergramCharter)obj;
+						tCO.setSpotSize(spotSize); 
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the chart is sized to fit within the field", "[on = constrained; off]", commandName, "toggleSizeToFit")) {
+			sizeToFit.toggleValue(parser.getFirstToken(arguments));
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setSizeToFit(sizeToFit.getValue());
+
+				}
+			}
+			if (!sizeToFit.getValue())
+				sizeItem = addMenuItem("Drawing Size...", sizeDrawingCommand);
+			else if (sizeItem!=null)
+				deleteMenuItem(sizeItem);
+			if (!sizeToFit.getValue() && !MesquiteThread.isScripting() && !MesquiteInteger.isCombinable(totalFieldWidth)&& !MesquiteInteger.isCombinable(totalFieldHeight))
+				doCommand("sizeDrawing", null, checker);
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the points are joined by lines (appropriate if there is a natural sequence to the points", "[on=joined; off]", commandName, "toggleJoin")) {
+			joinTheDots.toggleValue(parser.getFirstToken(arguments));
+			setJoinTheDots();
+			resetMenus();
+			resetContainingMenuBar();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the last point is joined to the first by a line (appropriate if there is a natural sequence to the points", "[on=joined; off]", commandName, "toggleLastToFirst")) {
+			joinLastToFirst.toggleValue(parser.getFirstToken(arguments));
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setJoinLast(joinLastToFirst.getValue());
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to shade to indicate number of points in each block", "[on=sum; off]", commandName, "sumByBlocks")) {
+			sumByBlocks.toggleValue(parser.getFirstToken(arguments));
+			resetMenus();
+			resetContainingMenuBar();
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setSumByBlocks(sumByBlocks.getValue());
+					tCO.calculateChart(tCO.chart);
+					tCO.chart.calculateAllExtras();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the lines joining the points are thick (appropriate if there is a natural sequence to the points", "[on=thick; off]", commandName, "toggleThickJoin")) {
+			thickLine.toggleValue(parser.getFirstToken(arguments));
+			Enumeration e = charters.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ScattergramCharter) {
+					ScattergramCharter tCO = (ScattergramCharter)obj;
+					tCO.setThickJoin(thickLine.getValue());
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the circular or square markers are shown at the points", "[on=show; off]", commandName, "toggleShowDots")) {
+			showDots.toggleValue(parser.getFirstToken(arguments));
+			setShowDots();
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of the chart drawing (appropriate if it is not constrained to fit in the field", "[width in pixels][height in pixels]", commandName, "sizeDrawing")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			int h = MesquiteInteger.fromString(arguments, pos);
+			if ((MesquiteInteger.isCombinable(h) &&  h>10) || (MesquiteInteger.isCombinable(w) && w>10)) {
+				Enumeration e = charters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof ScattergramCharter) {
+						ScattergramCharter tCO = (ScattergramCharter)obj;
+						tCO.setTotalField(w,h);
+					}
+				}
+				totalFieldHeight = h;
+				totalFieldWidth = w;
+
+			}
+			else { 
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger newWidth = new MesquiteInteger(totalFieldWidth);
+				MesquiteInteger newHeight =new MesquiteInteger(totalFieldHeight);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Size of scattergram chart", "Width (Pixels)",  "Height (Pixels)", answer,  newWidth, newHeight,10,MesquiteInteger.unassigned,10, MesquiteInteger.unassigned,MesquiteString.helpString);
+				if (answer.getValue() &&( (newWidth.isCombinable()&&newWidth.getValue()>10) || (newHeight.isCombinable() && newHeight.getValue()>10))) {
+					Enumeration e = charters.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof ScattergramCharter) {
+							ScattergramCharter tCO = (ScattergramCharter)obj;
+							tCO.setTotalField(newWidth.getValue(),newHeight.getValue());
+						}
+					}
+					totalFieldHeight = newHeight.getValue();
+					totalFieldWidth = newWidth.getValue();
+				}
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	void setJoinTheDots(){
+		Enumeration e = charters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ScattergramCharter) {
+				ScattergramCharter tCO = (ScattergramCharter)obj;
+				tCO.setJoin(joinTheDots.getValue());
+			}
+		}
+	}
+	void setShowDots(){
+		Enumeration e = charters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ScattergramCharter) {
+				ScattergramCharter tCO = (ScattergramCharter)obj;
+				tCO.setShowDots(showDots.getValue());
+			}
+		}
+	}
+}
+
+/* ======================================================================== */
+class ScattergramCharter extends Charter {
+	MesquiteNumber valueX;
+	MesquiteNumber valueY;
+	MesquiteNumber valueZ;
+	MesquiteNumber tempNum = new MesquiteNumber();
+	int spotSize = 10;
+	boolean useCircle = true;
+	boolean showNames=false;
+	MesquiteChart chart;
+	Scattergram ownerModule;
+	DragRectangle dragRectangle;
+	boolean showSpots = true;
+	boolean joinTheDots = false;
+	boolean joinLastToFirst = true;
+	boolean sumByBlocks = false;
+	boolean thickJoin = false;
+	int movingWindowSizeZ = 1;
+	ChartListener listener;
+	int minTicks = 3;
+	ScattergramColorLegend legend;
+	MesquiteColorTable colorTable = new ContColorTable();
+	int[][] blockSums;
+	int numBlockDivisions = 10;
+	public ScattergramCharter (Scattergram ownerModule, ChartListener listener) {
+		this.ownerModule = ownerModule;
+		this.listener = listener;
+		spotSize = ownerModule.spotSize;
+		useCircle = ownerModule.useCircle;
+		valueX = new MesquiteNumber();
+		valueY = new MesquiteNumber();
+		valueZ = new MesquiteNumber();
+		joinTheDots = ownerModule.joinTheDots.getValue();
+		joinLastToFirst = ownerModule.joinLastToFirst.getValue();
+		setSumByBlocks(ownerModule.sumByBlocks.getValue());
+	}
+	public void open(MesquiteChart chart){
+		this.chart = chart;
+		chart.setXAxisEdge(98); //MAKE IT DEPEND ON FONT SIZE
+		chart.setYAxisEdge(88); //MAKE IT DEPEND ON FONT SIZE
+		chart.setSizeToFit(ownerModule.sizeToFit.getValue());
+		ownerModule.incrementMenuResetSuppression();
+
+		for (int i = 0; i<ownerModule.holding.size(); i++)
+			addAssistant((ChartAssistant)(ownerModule.holding.elementAt(i)));
+		ownerModule.decrementMenuResetSuppression();
+		synchronizeSelection();
+	}
+	public  void calculateChart(MesquiteChart chart){
+		if (chart == null)
+			return;
+		minX.setValue(chart.getAxisMinimumX());
+		maxX.setValue(chart.getAxisMaximumX());
+		minY.setValue(chart.getAxisMinimumY());
+		maxY.setValue(chart.getAxisMaximumY());
+		if (sumByBlocks){
+			double minimumX = chart.getAxisMinimumX().getDoubleValue();
+			double maximumX = chart.getAxisMaximumX().getDoubleValue();
+			double minimumY = chart.getAxisMinimumY().getDoubleValue();
+			double maximumY = chart.getAxisMaximumY().getDoubleValue();
+			Integer2DArray.zeroArray(blockSums);
+
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendChartCalculations())
+					return;
+				if (i%100 == 0)
+					CommandRecord.tick("Sorting points into categories for density (point " + i + ")");
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+					double x = valueX.getDoubleValue();
+					double y = valueY.getDoubleValue();
+					//try {
+					blockSums[category(x, minimumX, maximumX, numBlockDivisions)][category(y, minimumY, maximumY, numBlockDivisions)]++;
+					//	}
+					//	catch (ArrayIndexOutOfBoundsException e){
+					//		MesquiteMessage.warnProgrammer(
+					//	}
+				}
+			}
+		}
+	}
+	void addAssistant(ChartAssistant tda){
+		if (chart!=null){
+			ChartExtra tce = tda.createExtra(chart); 
+			chart.addExtra(tce);
+			tce.doCalculations();
+			repaintC();
+		}
+	}
+	public void setShowNames(boolean showNames) {
+		this.showNames = showNames;
+	}
+	/*---- Methods concerning selection of points ----*/
+	void synchronizeSelection() {
+		if (chart!=null && ownerModule.pointsAssociable!=null) {
+			chart.synchronizePointSelection(ownerModule.pointsAssociable);
+		}
+	}
+	public void selectionOff() {
+		if (chart!=null) {
+			chart.deselectAllPoints();
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+	void deselectAll(){
+		if (ownerModule.pointsAssociable!=null)  
+			ownerModule.pointsAssociable.deselectAll();
+		else
+			chart.deselectAllPoints();
+	}
+	void select(int which){
+		if (ownerModule.pointsAssociable!=null)   {
+			ownerModule.pointsAssociable.setSelected(which, true);
+		}
+		else
+			chart.selectPoint(which);
+	}
+	void deselect(int which){
+		if (ownerModule.pointsAssociable!=null)  
+			ownerModule.pointsAssociable.setSelected(which, false);
+		else
+			chart.deselectPoint(which);
+	}
+	boolean isSelected(int which){
+		if (ownerModule.pointsAssociable!=null)  
+			return ownerModule.pointsAssociable.getSelected(which);
+		else
+			return chart.getSelected().isBitOn(which);
+	}
+	boolean anySelected(){
+		if (ownerModule.pointsAssociable!=null)  
+			return ownerModule.pointsAssociable.anySelected();
+		else
+			return chart.getSelected().anyBitsOn();
+	}
+	void wrapUpSelection(){
+		if (ownerModule.pointsAssociable!=null) {
+			ownerModule.pointsAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+		}
+		else {
+			repaintC();
+		}
+	}
+	public void selectRange(int first, int last) { 
+		if (chart!=null) {
+			deselectAll();
+			for (int i=first; i<=last; i++) 
+				select(i);
+			wrapUpSelection();
+		}
+	}
+	public void marchSelection(boolean forward) {
+		Graphics g = chart.getField().getGraphics();
+		if (chart!=null) {
+			if (!forward){
+				int num  = chart.getNumPoints();
+				for (int i=0; i<num; i++) {
+					int next;
+					if (i==num-1)
+						next =0;
+					else
+						next  = (i+1);
+					if (isSelected(next) != isSelected(i)){
+						if (isSelected(next))
+							select(i);
+						else
+							deselect(i);
+						if (g!=null) redrawPoint(g, chart, i);
+					}
+				}
+			}
+			else {
+				int num  = chart.getNumPoints();
+				for (int i=num-1; i>=0; i--) {
+					int next;
+					if (i==0)
+						next =num-1;
+					else
+						next  = (i-1);
+					if (isSelected(next) != isSelected(i)){ 
+						if (isSelected(next))
+							select(i);
+						else
+							deselect(i);
+						if (g!=null) redrawPoint(g, chart, i);
+					}
+				}
+			}
+			wrapUpSelection();
+		}
+		if (g!=null)
+			g.dispose();
+	}
+	/*------------viewing options ------------*/
+	public void setUseCircle(boolean useCircle) {
+		this.useCircle = useCircle;
+		repaintC();
+	}
+	public void setSpotSize(int s) {
+		this.spotSize = s;
+		repaintC();
+	}
+	public void setSizeToFit(boolean b) {
+		chart.setSizeToFit(b);
+		if (!b){
+			chart.setTotalField(ownerModule.totalFieldWidth, ownerModule.totalFieldHeight);
+		}
+	}
+	public void setJoin(boolean b) {
+		joinTheDots = b;
+		joinLastToFirst = ownerModule.joinLastToFirst.getValue();
+		showSpots = ownerModule.showDots.getValue();
+		thickJoin = ownerModule.thickLine.getValue();
+		repaintC();
+	}
+	public void setJoinLast(boolean b) {
+		joinLastToFirst = b;
+		repaintC();
+	}
+	public void setThickJoin(boolean b) {
+		thickJoin = b;
+		repaintC();
+	}
+	public void setSumByBlocks(boolean b) {
+		sumByBlocks = b;
+		if (b && blockSums==null){
+			blockSums = new int[numBlockDivisions][numBlockDivisions];
+		}
+		repaintC();
+	}
+	public void setShowDots(boolean b) {
+		showSpots = b;
+		repaintC();
+	}
+
+	public void setTotalField(int w, int h) {
+		chart.setTotalField(w,h);
+		repaintC();
+	}
+	/* ----------------------------------*/
+	public void setMovingWindowSizeZ(int s) {
+		this.movingWindowSizeZ = s;
+		repaintC();
+	}
+	/* ----------------------------------*/
+	private void repaintC(){
+		if (chart!=null && chart.getField()!=null) {
+			chart.getField().repaint();
+			chart.repaint();
+		}
+	}
+
+	/* ----------------------------------*/
+	private int findExactPoint(int xPixel, int yPixel, MesquiteChart chart){   // todo:   need to fill this in.  gives value to screen resolution
+		if (xPixel<0)
+			xPixel =0;
+		return xPixel;
+	}
+	/* ----------------------------------*/
+	/* Returns which of the data points is at the pixel point indicated; included are points within a half markerwidth of the pixel.  If more than one data point qualifies, the next one
+	in sequence is given (i.e. repeated clicks cycle through all at that location)*/
+	long numClicks = 0;
+	private int findPoint(int xPixel, int yPixel, MesquiteChart chart){
+		if (xPixel<0)
+			xPixel =0;
+		if (yPixel<0)
+			yPixel = 0;
+
+		//first, find target area in graph units, converted from pixels 
+		int halfSpot = spotSize/2;
+		if (halfSpot <1)
+			halfSpot = 1;
+		else if (spotSize/2*2 != spotSize)
+			halfSpot++;
+
+		MesquiteNumber xMin = new MesquiteNumber();
+		MesquiteNumber xMax = new MesquiteNumber();
+		MesquiteNumber yMin = new MesquiteNumber();
+		MesquiteNumber yMax = new MesquiteNumber();
+
+		pixelToX(xPixel-halfSpot, chart, xMin);
+		pixelToX(xPixel+halfSpot, chart, xMax);
+		pixelToY(yPixel+halfSpot, chart, yMin);
+		pixelToY(yPixel-halfSpot, chart, yMax);
+
+		NumberArray xArray = chart.getXArray();
+		NumberArray yArray = chart.getYArray();
+		long numFound=0;
+		int found = -1;
+		for (int i=0; i<chart.getNumPoints(); i++){
+			xArray.placeValue(i, tempNum);
+			if (tempNum!=null && tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax)) {
+				yArray.placeValue(i, tempNum);
+				if (tempNum!=null && tempNum.isMoreThan(yMin) && tempNum.isLessThan(yMax)) {
+					numFound++;
+					found = i;
+				}
+			}
+		}
+		if (numFound==1)
+			return found;
+		else if (numFound>0) {
+			long target = numClicks % numFound;
+			for (int i=0; i<chart.getNumPoints(); i++){
+				xArray.placeValue(i, tempNum);
+				if (tempNum!=null && tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax)) {
+					yArray.placeValue(i, tempNum);
+					if (tempNum!=null && tempNum.isMoreThan(yMin) && tempNum.isLessThan(yMax)) {
+						if (target<=0)
+							return i;
+						target--;
+					}
+				}
+			}
+		}
+		return -1;
+	}
+	/* ----------------------------------*/
+	/** returns an array of all data points within the pixel rectangle indicated*/
+	private int[] findPointsWithin(int x1, int y1, int x2, int y2, MesquiteChart chart){
+		if (MesquiteInteger.isCombinable(x1) && x1<0)
+			x1 =0;
+		if (MesquiteInteger.isCombinable(y1) && y1<0)
+			y1 = 0;
+		if (MesquiteInteger.isCombinable(x2) && x2<0)
+			x2 =0;
+		if (MesquiteInteger.isCombinable(y2) && y2<0)
+			y2 = 0;
+		if (MesquiteInteger.isCombinable(x1) && x1> chart.getField().getBounds().width)
+			x1 =chart.getField().getBounds().width;
+		if (MesquiteInteger.isCombinable(x2) && x2> chart.getField().getBounds().width)
+			x2 =chart.getField().getBounds().width;
+		if (MesquiteInteger.isCombinable(y1) && y1>chart.getField().getBounds().height)
+			y1 = chart.getField().getBounds().height;
+		if (MesquiteInteger.isCombinable(y2) && y2>chart.getField().getBounds().height)
+			y2 = chart.getField().getBounds().height;
+		if (!MesquiteInteger.isCombinable(x1) ||!MesquiteInteger.isCombinable(y1)) {
+			int which = findPoint(x2, y2, chart);
+			if (which>=0)
+				return new int[]{which};
+			return null;
+		}
+		else if (!MesquiteInteger.isCombinable(x2) ||!MesquiteInteger.isCombinable(y2)) {
+			int which = findPoint(x1, y1, chart);
+			if (which>=0)
+				return new int[]{which};
+			return null;
+		}
+
+		MesquiteNumber xMin= new MesquiteNumber();
+		MesquiteNumber xMax= new MesquiteNumber();
+		xMin.findWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), x1, chart.getFieldWidth());
+		xMax.findWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), x2, chart.getFieldWidth());
+
+		MesquiteNumber yMin= new MesquiteNumber();
+		MesquiteNumber yMax= new MesquiteNumber();
+		yMin.findWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), chart.getFieldHeight()-y1, chart.getFieldHeight());
+		yMax.findWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), chart.getFieldHeight()-y2, chart.getFieldHeight());
+		NumberArray xArray = chart.getXArray();
+		NumberArray yArray = chart.getYArray();
+		try{
+			int numFound=0;
+			for (int i=0; i<chart.getNumPoints(); i++){
+				xArray.placeValue(i, tempNum);
+				if (tempNum!=null && ((tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax))|| (tempNum.isLessThan(xMin) && tempNum.isMoreThan(xMax)))) {
+					yArray.placeValue(i, tempNum);
+					if (tempNum!=null && ((tempNum.isMoreThan(yMin) && tempNum.isLessThan(yMax)) || (tempNum.isLessThan(yMin) && tempNum.isMoreThan(yMax)))) {
+						numFound++;
+					}
+				}
+			}
+
+			int[] found = new int[numFound];
+			if (numFound>0) {
+				int count =0;
+				for (int i=0; i<chart.getNumPoints(); i++){
+					xArray.placeValue(i, tempNum);
+					if (tempNum!=null && ((tempNum.isMoreThan(xMin) && tempNum.isLessThan(xMax))|| (tempNum.isLessThan(xMin) && tempNum.isMoreThan(xMax)))) {
+						yArray.placeValue(i, tempNum);
+						if (tempNum!=null && ((tempNum.isMoreThan(yMin) && tempNum.isLessThan(yMax)) || (tempNum.isLessThan(yMin) && tempNum.isMoreThan(yMax)))) {
+							found[count] = i;
+							count++;
+						}
+					}
+				}
+			}
+			return found;
+		}
+		catch (Throwable t) {
+		}
+		return null;
+	}
+	/* ----------------------------------*/
+	void drawRect(Graphics g, int x1, int y1, int x2, int y2){
+		if (x1>x2){
+			if (y1>y2)
+				g.drawRect(x2, y2, x1-x2, y1-y2);
+			else 
+				g.drawRect(x2, y1, x1-x2, y2-y1);
+		}
+		else {
+			if (y1>y2)
+				g.drawRect(x1, y2, x2-x1, y1-y2);
+			else 
+				g.drawRect(x1, y1, x2-x1, y2-y1);
+		}
+	}
+	/* ----------------------------------*/
+	int pointEntered = -1;
+	public void mouseMoveInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		whichDown = findPoint(xPixel,yPixel, chart);
+		if (pointEntered >=0 && whichDown!=pointEntered) {  //had been in other point recently; exit it
+			ListableVector extras = chart.getExtras();
+			for (int i=0; i<extras.size(); i++) {
+				((ChartExtra)extras.elementAt(i)).cursorExitPoint(pointEntered,  findExactPoint(xPixel,yPixel, chart),  null);
+			}
+		}
+		if (whichDown>=0) {
+			if (whichDown!=pointEntered){
+				ListableVector extras = chart.getExtras();
+				for (int i=0; i<extras.size(); i++) {
+					((ChartExtra)extras.elementAt(i)).cursorEnterPoint(whichDown, findExactPoint(xPixel,yPixel, chart), null);
+				}
+			}
+			pointEntered = whichDown;
+		}
+		else
+			pointEntered = -1;
+	}
+	/* ----------------------------------*/
+	int whichDown = MesquiteInteger.unassigned;
+	int xDown = MesquiteInteger.unassigned;
+	int yDown = MesquiteInteger.unassigned;
+	public void mouseDownInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		numClicks++;
+		whichDown = findPoint(xPixel,yPixel, chart);
+		if (tool != chart.getArrowTool() && tool != chart.getInfoTool()) {
+			if (whichDown>=0){
+				tool.pointTouched(whichDown, xPixel, yPixel, modifiers);
+				return;
+			}
+		}	
+
+		//arrow tool; start selection rectangle
+		if (tool == chart.getArrowTool()){
+			xDown = xPixel;
+			yDown = yPixel;
+			dragRectangle = new DragRectangle(chart.getField().getGraphics(),xPixel, yPixel);
+			ListableVector extras = chart.getExtras();
+			for (int i=0; i<extras.size(); i++) {
+				((ChartExtra)extras.elementAt(i)).cursorTouchPoint(whichDown, findExactPoint(xPixel,yPixel, chart), null);
+			}
+			return;
+		}
+
+		//info tool
+		if (listener!=null && (sumByBlocks || whichDown >=0)) {
+			String message = null;
+			if (sumByBlocks){
+				double minimumX = chart.getAxisMinimumX().getDoubleValue();
+				double maximumX = chart.getAxisMaximumX().getDoubleValue();
+				double minimumY = chart.getAxisMinimumY().getDoubleValue();
+				double maximumY = chart.getAxisMaximumY().getDoubleValue();
+				double incrementX = (maximumX-minimumX)/numBlockDivisions;
+				double incrementY = (maximumY-minimumY)/numBlockDivisions;
+				MesquiteNumber xPoint = new MesquiteNumber();
+				MesquiteNumber yPoint = new MesquiteNumber();
+				pixelToX(xPixel, chart, xPoint);
+				pixelToY(yPixel, chart, yPoint);
+				int xBlock = category(xPoint.getDoubleValue(), minimumX, maximumX, numBlockDivisions);
+				int yBlock = category(yPoint.getDoubleValue(), minimumY, maximumY, numBlockDivisions);
+				if (xBlock>=0 && xBlock < blockSums.length && yBlock>=0 && yBlock < blockSums[xBlock].length) {
+					message = "Density: " + blockSums[xBlock][yBlock] + "\npoints in range\nx: " + MesquiteDouble.toStringDigitsSpecified(minimumX + xBlock*incrementX, 5) + " - " +  MesquiteDouble.toStringDigitsSpecified(minimumX + (xBlock+1)*incrementX, 5) + "\ny: " + MesquiteDouble.toStringDigitsSpecified(minimumY + yBlock*incrementY, 5) + " - " +  MesquiteDouble.toStringDigitsSpecified(minimumY + (yBlock+1)*incrementY, 5);
+				}
+			}
+			int wd = whichDown;
+			if (!showSpots)
+				wd = -1;
+			listener.pointMouseDown(chart, wd, null, null,  xPixel, yPixel, modifiers, message); //todo: send message here in last null
+		}
+		ListableVector extras = chart.getExtras();
+		for (int i=0; i<extras.size(); i++) {
+			((ChartExtra)extras.elementAt(i)).cursorTouchPoint(whichDown, findExactPoint(xPixel,yPixel, chart), null);
+		}
+
+	}
+	/* ----------------------------------*/
+	public void mouseDragInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		if (tool == chart.getArrowTool()){ 
+			if (dragRectangle!=null)
+				dragRectangle.drawRectangleDrag(xPixel, yPixel);
+		}
+	}
+	/* ----------------------------------*/
+	public void mouseUpInField(int modifiers, int xPixel, int yPixel, MesquiteChart chart, ChartTool tool) {
+		// neither arrow nor info tool
+		if (tool !=null && tool != chart.getArrowTool()&& tool != chart.getInfoTool()) {
+			if (whichDown>=0){
+				tool.pointDropped(whichDown, xPixel, yPixel,modifiers);
+				return;
+			}
+		}	
+		int which = findPoint(xPixel, yPixel, chart);
+		if (listener!=null)
+			listener.pointMouseUp(chart, which, xPixel, yPixel, modifiers, null);
+
+		//arrow tool; handle selection
+		if (tool == chart.getArrowTool()){
+			if (dragRectangle!=null)
+				dragRectangle.drawRectangleUpDown();
+			if (which == whichDown && MesquiteInteger.isNonNegative(which)) { // had touched directly on point before
+				if (MesquiteEvent.shiftKeyDown(modifiers)) {
+					if (isSelected(which))
+						deselect(which);
+					else
+						select(which);
+				}
+				else if (!isSelected(which)) {
+					if (anySelected())
+						deselectAll();
+					select(which);
+				}
+				wrapUpSelection();
+			}
+			else {
+				int[] whichPoints = findPointsWithin(xPixel,yPixel,xDown, yDown, chart);
+				if (whichPoints!=null && whichPoints.length>0) {
+					if (!MesquiteEvent.shiftKeyDown(modifiers))
+						deselectAll();
+					for (int i = 0; i< whichPoints.length; i++){
+						which = whichPoints[i];
+						if (MesquiteEvent.shiftKeyDown(modifiers)) {
+							if (isSelected(which))
+								deselect(which);
+							else
+								select(which);
+						}
+						else if (!isSelected(which)) {
+							select(which);
+						}
+					}
+					wrapUpSelection();
+				}
+				else if (chart.getSelected().anyBitsOn()){
+					deselectAll();
+					wrapUpSelection();
+				}
+			}
+		}
+		xDown = MesquiteInteger.unassigned;
+		yDown = MesquiteInteger.unassigned;
+		whichDown =MesquiteInteger.unassigned;
+	}
+	/* ----------------------------------*/
+	public void showQuickMessage(MesquiteChart chart, int whichPoint,int xO, int yO,  String message){
+		if (StringUtil.blank(message))
+			return;
+		int xPixel = xO;
+		int yPixel = yO;
+		if (whichPoint>=0){
+			chart.getXArray().placeValue(whichPoint, valueX);
+			chart.getYArray().placeValue(whichPoint, valueY);
+			markerWidth = spotSize;
+			int markerHeight = spotSize;
+			int fieldWidth = chart.getFieldWidth(); 
+			int fieldHeight = chart.getFieldHeight();
+			xPixel = chart.getMargin()+valueX.setWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), fieldWidth - 2*chart.getMargin())-markerWidth/2;
+			yPixel = fieldHeight-chart.getMargin()-valueY.setWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), fieldHeight - 2*chart.getMargin())-markerHeight/2;
+		}
+		Graphics g = chart.getField().getGraphics();
+		if (g!=null) {
+			int w = 90;
+			StringInABox sb = new StringInABox(message, chart.getField().getFont(), w);
+			int xPos=0;
+			if (xPixel+w + 32>chart.getField().getBounds().width)
+				xPos = xPixel-w;
+			else
+				xPos = xPixel+32;
+			int yPos=0;
+			if (yPixel+sb.getHeight()>chart.getField().getBounds().height)
+				yPos = yPixel-sb.getHeight();
+			else
+				yPos = yPixel;
+
+			sb.drawInBox(g, chart.getField().getBackground(), xPos, yPos);
+			g.dispose();
+		}
+	}
+	/* ----------------------------------*/
+	public void hideQuickMessage(MesquiteChart chart){
+		chart.getField().repaint();
+	}
+	/* ----------------------------------*/
+	/* returns color of ith data point */
+	Color getPointColor(MesquiteChart chart, int i){
+		if (chart.getZArray()!=null) {
+			if (movingWindowSizeZ<=1 || !MesquiteInteger.isCombinable(movingWindowSizeZ))
+				chart.getZArray().placeValue(i, valueZ);
+			else {
+				int first = 0;
+				int last = 0;
+				if (i-(movingWindowSizeZ/2)<0) {
+					first = 0;
+					last = i + (movingWindowSizeZ/2);
+				}
+				else {
+					first = i-(movingWindowSizeZ/2);
+					last = first + (movingWindowSizeZ);
+					if (last>= chart.getNumPoints())
+						last = chart.getNumPoints()-1;
+				}
+				valueZ.setToUnassigned();
+				int count =0;
+				for (int j = first; j<=last; j++) {
+					chart.getZArray().placeValue(j, tempNum);
+					if (tempNum.isCombinable()) {
+						count++;
+						valueZ.add(tempNum);
+					}
+				}
+				if (count==0)
+					valueZ.setToUnassigned(); 
+				else
+					valueZ.divideBy(count);
+			}
+			Color c= (colorTable.getColor(valueZ.getDoubleValue(), chart.getMinimumZ().getDoubleValue(), chart.getMaximumZ().getDoubleValue()));
+			if (!chart.getSelected().anyBitsOn()|| chart.getSelected().isBitOn(i))
+				return (c);
+			else
+				return (ColorDistribution.brighter(c, ColorDistribution.dimmingConstant));
+
+		}
+		else if (chart.colorsExist() && chart.getColor(i)!=null){
+			Color c = chart.getColor(i);
+			if (!chart.getSelected().anyBitsOn()|| chart.getSelected().isBitOn(i))
+				return (c);
+			else
+				return (ColorDistribution.brighter(c, ColorDistribution.dimmingConstant));
+		}
+		else {
+			//the following is not used as categories are not assigned anywhere
+			LongArray cats = chart.getCatArray();
+			if (cats==null || cats.getValue(i)==0){ //use some other coloring scheme
+				if (!chart.getSelected().anyBitsOn()|| chart.getSelected().isBitOn(i))
+					return (Color.blue);
+				else
+					return (ColorDistribution.lightBlue);
+			}
+			else{
+				if (!chart.getSelected().anyBitsOn()|| chart.getSelected().isBitOn(i))
+					return (Color.red);
+				else
+					return (Color.pink);
+			}
+		}
+	}
+	// returns outline color of ith data point
+	Color getPointFrameColor(MesquiteChart chart, int i){
+		if (!chart.getSelected().anyBitsOn() || chart.getSelected().isBitOn(i))
+			return (Color.black);
+		else
+			return (Color.gray);
+
+	}
+	// redraws data point i.  Used currently only for march selection (to avoid entire redraw)
+	void redrawPoint(Graphics g, MesquiteChart chart, int i){
+		int margin = chart.getMargin();
+		markerWidth = spotSize;
+		int markerHeight = spotSize;
+		int fieldWidth = chart.getField().getBounds().width;
+		int fieldHeight = chart.getField().getBounds().height;
+		RotatedRectangle rot = null;
+		if (thickJoin)
+			rot = new RotatedRectangle();
+		int previous;
+		if (i==0)
+			previous = chart.getNumPoints()-1;
+		else
+			previous = i-1;
+
+		if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+			chart.getXArray().placeValue(i, valueX);
+			chart.getYArray().placeValue(i, valueY);
+			int xPixel = xToPixel(valueX.getDoubleValue(), chart); //margin+valueX.setWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), coreWidth)-markerWidth/2;
+			int yPixel = yToPixel(valueY.getDoubleValue(), chart); //fieldHeight-margin-valueY.setWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), coreHeight)-markerHeight/2;
+			if (joinTheDots && (previous<i || joinLastToFirst)){
+				chart.getXArray().placeValue(previous, valueX);
+				chart.getYArray().placeValue(previous, valueY);
+				int prevX = xToPixel(valueX.getDoubleValue(), chart); //margin+valueX.setWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), coreWidth)-markerWidth/2;
+				int prevY = yToPixel(valueY.getDoubleValue(), chart); //fieldHeight-margin-valueY.setWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), coreHeight)-markerHeight/2;
+
+				if (valueX.isCombinable() && valueY.isCombinable()){
+					Color c =getPointColor(chart, i);
+					if (thickJoin) {
+						if (c!=null) g.setColor(c);
+						rot.setShape(xPixel, yPixel, prevX, prevY, markerWidth, false, RotatedRectangle.RECTANGLE);
+						rot.fill(g, false);
+						g.setColor(getPointFrameColor(chart, i));
+						rot.draw(g);
+					}
+					else {
+						g.setColor(getPointFrameColor(chart, i));
+						g.drawLine(xPixel, yPixel, prevX, prevY);
+					}
+				}
+			}
+			if (showSpots){
+				g.setColor(getPointColor(chart, i));
+				if (useCircle){
+					g.fillOval(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth, markerHeight);
+					g.setColor(getPointFrameColor(chart, i));
+					g.drawOval(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth, markerHeight);
+				}
+				else {
+					g.fillRect(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth+1, markerHeight+1);
+				}
+			}
+		}
+	}
+
+	//returns the category for density shading of a data point of value x within the range shown
+	private int category(double x, double min, double max, int numDiv){
+		int c = (int)((x-min)/(max-min)*numDiv);
+		if (c == numDiv)
+			c--;
+		return c;
+	}
+
+	//Shades by density of data points
+	private void shadeBlocks(Graphics g, MesquiteChart chart){
+		double minimumX = chart.getAxisMinimumX().getDoubleValue();
+		double maximumX = chart.getAxisMaximumX().getDoubleValue();
+		double minimumY = chart.getAxisMinimumY().getDoubleValue();
+		double maximumY = chart.getAxisMaximumY().getDoubleValue();
+		int min = Integer2DArray.minimum(blockSums);
+		int max = Integer2DArray.maximum(blockSums);
+		double incrementX = (maximumX-minimumX)/numBlockDivisions;
+		double incrementY = (maximumY-minimumY)/numBlockDivisions;
+		double xLeft = minimumX;
+		for (int i= 0; i<numBlockDivisions; i++) {
+			double yTop = minimumY;
+			int blockLeft = xToPixel(xLeft, chart);
+			int blockWidth = xToPixel(xLeft+incrementX, chart) - blockLeft;
+			for (int j= 0; j<numBlockDivisions; j++) {
+				int blockTop = yToPixel(yTop, chart);
+				int blockHeight = blockTop - yToPixel(yTop+incrementY, chart);
+				g.setColor(MesquiteColorTable.getGrayScale((double)blockSums[i][j], (double)min, (double)max));
+				g.fillRect(blockLeft, blockTop, blockWidth, blockHeight);
+				yTop += incrementY;
+			}
+			xLeft += incrementX;
+		}
+	}
+	/* ----------------------------------*/
+	public void drawBackground(Graphics g, MesquiteChart chart){
+		if (sumByBlocks)
+			shadeBlocks(g, chart);
+	}
+	/* ----------------------------------*/
+	public void drawChartBackground(Graphics g, MesquiteChart chart){
+		g.setColor(Color.black);			
+		drawGrid(g, chart);
+	}
+	/* ----------------------------------*/
+	public void drawChart(Graphics g, MesquiteChart chart){
+		if (chart==null || chart.getXArray()==null || chart.getYArray()==null )
+			return;
+		if (getSuspendDrawing())
+			return;
+		if (chart.getNumPoints()==0){
+			g.setColor(Color.black);
+			g.drawString("The chart does not yet have any points", 10, 70);
+			return;
+		}
+		chartDone = true;
+		//g.setColor(Color.white);
+		int margin = chart.getMargin();
+		markerWidth = spotSize;
+		int markerHeight = spotSize;
+		int fieldWidth = chart.getField().getBounds().width;
+		int fieldHeight = chart.getField().getBounds().height;
+		//g.fillRect(margin, margin, fieldWidth-2*margin, fieldHeight-2*margin);
+		g.setColor(Color.black);
+		g.drawRect(margin, margin, fieldWidth-2*margin, fieldHeight-2*margin);
+
+		synchronizeSelection();
+
+		if (chart.getZArray()!=null) {
+			if (legend==null) {
+				legend = new ScattergramColorLegend(ownerModule, this);
+				chart.getField().add(legend);
+			}
+			if (!legend.isVisible())
+				legend.setVisible(true);
+			String colorExplanation = "Colors: " + chart.getZAxisName();
+			if (movingWindowSizeZ>1 && MesquiteInteger.isCombinable(movingWindowSizeZ))
+				colorExplanation += " (averaged in moving window of size " + movingWindowSizeZ + ")";
+			legend.specsBox.setText(colorExplanation);
+			legend.setMinMax(chart.getMinimumZ().getDoubleValue(), chart.getMaximumZ().getDoubleValue());
+			legend.adjustLocation();
+		}
+		else if (legend!=null)
+			legend.setVisible(false);
+
+		// grid ========
+		//		drawGrid(g, chart);
+		//grid ===  
+
+		String problem = null;
+
+		g.setColor(Color.blue);
+		valueX.setValue(0);
+		valueY.setValue(0);
+		int xZero = xToPixel(valueX.getDoubleValue(), chart); 
+		int yZero =  yToPixel(valueY.getDoubleValue(), chart); 
+		g.drawLine(xZero, margin, xZero, fieldHeight - margin);
+		g.drawLine(margin, yZero, fieldWidth - margin, yZero);
+		g.setColor(Color.black);
+		if (showNames && chart.namesExist())
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendDrawing())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					String name =chart.getName(i);
+					if (name!=null) {
+						chart.getXArray().placeValue(i, valueX);
+						chart.getYArray().placeValue(i, valueY);
+						int xPixel = xToPixel(valueX.getDoubleValue(), chart)-markerWidth/2; 
+						int yPixel =  yToPixel(valueY.getDoubleValue(), chart)- markerWidth/2;
+						Color fc = getPointFrameColor(chart, i);
+						if (fc==Color.black) {
+							StringUtil.highlightString(g, name, xPixel+ markerWidth + 4, yPixel+markerHeight/2+2, Color.black, Color.white);
+						}
+						else {
+							g.setColor(fc);
+							g.drawString(name, xPixel+ markerWidth + 4, yPixel+markerHeight/2+2);
+							g.setColor(Color.black);
+						}
+					}
+				}
+			}
+		if (joinTheDots){
+			int lastX=MesquiteInteger.unassigned;
+			int lastY = MesquiteInteger.unassigned;
+			int firstX=MesquiteInteger.unassigned;
+			int firstY = MesquiteInteger.unassigned;
+			RotatedRectangle rot = null;
+			if (thickJoin)
+				rot = new RotatedRectangle();
+			boolean first = true;
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (getSuspendDrawing())
+					return;
+				if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+					int xPixel = xToPixel(valueX.getDoubleValue(), chart); //margin+valueX.setWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), coreWidth)-markerWidth/2;
+					int yPixel = yToPixel(valueY.getDoubleValue(), chart); //fieldHeight-margin-valueY.setWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), coreHeight)-markerHeight/2;
+					if (first) {
+						firstX = xPixel;
+						firstY = yPixel;
+						first = false;
+					}
+					if (!chart.isMinimumXConstrained() && !chart.isMaximumXConstrained()) {
+						if (xPixel < 0 || xPixel > chart.getField().getBounds().width && problem == null)
+							problem = "x " + valueX + " pixel " + xPixel + " field width " + chart.getField().getBounds().width + " axis Max " + chart.getAxisMaximumX();
+					}
+					if (!chart.isMinimumYConstrained() && !chart.isMaximumYConstrained()) {
+						if (yPixel < 0 || yPixel > chart.getField().getBounds().height && problem == null)
+							problem = "y " + valueY + " pixel " + yPixel + " field height " + chart.getField().getBounds().height+ " axis Max " + chart.getAxisMaximumY();
+					}
+					if (MesquiteInteger.isCombinable(lastX) && MesquiteInteger.isCombinable(lastY)){
+						Color c =getPointColor(chart, i);
+						if (thickJoin) {
+							if (c!=null) g.setColor(c);
+							rot.setShape(xPixel, yPixel, lastX, lastY, markerWidth, false, RotatedRectangle.RECTANGLE);
+							rot.fill(g, false);
+							g.setColor(getPointFrameColor(chart, i));
+							rot.draw(g);
+						}
+						else {
+							g.setColor(getPointFrameColor(chart, i));
+							g.drawLine(xPixel, yPixel, lastX, lastY);
+						}
+					}
+					lastX = xPixel;
+					lastY = yPixel;
+				}
+			}
+			if (joinLastToFirst && MesquiteInteger.isCombinable(lastX) && MesquiteInteger.isCombinable(lastY)&& MesquiteInteger.isCombinable(firstX) && MesquiteInteger.isCombinable(firstY))
+				g.drawLine(firstX, firstY, lastX, lastY);
+		}
+		if (showSpots){
+			boolean doSelected = false;
+			boolean someAreSelected= chart.getSelected().anyBitsOn();
+			for (int pass = 0; (pass<=1 && someAreSelected) || (pass<1); pass++){ // if any are selected, do two passes, first unselected ones, second selected ones so they sit on top.
+				for (int i= 0; i<chart.getNumPoints(); i++) {
+					if (getSuspendDrawing())
+						return;
+					if (!chart.getXArray().isUnassigned(i) && !chart.getYArray().isUnassigned(i)) {
+						if (!someAreSelected || (someAreSelected && doSelected && chart.getSelected().isBitOn(i)) || (someAreSelected && !doSelected && !chart.getSelected().isBitOn(i))){
+							chart.getXArray().placeValue(i, valueX);
+							chart.getYArray().placeValue(i, valueY);
+							int xPixel = xToPixel(valueX.getDoubleValue(), chart); //margin+valueX.setWithinBounds(chart.getAxisMinimumX(), chart.getAxisMaximumX(), coreWidth)-markerWidth/2;
+							int yPixel = yToPixel(valueY.getDoubleValue(), chart); //fieldHeight-margin-valueY.setWithinBounds(chart.getAxisMinimumY(), chart.getAxisMaximumY(), coreHeight)-markerHeight/2;
+							if (!chart.isMinimumXConstrained() && !chart.isMaximumXConstrained()) {
+								if (xPixel < 0 || xPixel > chart.getField().getBounds().width && problem == null)
+									problem = "x " + valueX + " pixel " + xPixel + " field width " + chart.getField().getBounds().width + " axis Max " + chart.getAxisMaximumX();
+							}
+							if (!chart.isMinimumYConstrained() && !chart.isMaximumYConstrained()) {
+								if (yPixel < 0 || yPixel > chart.getField().getBounds().height && problem == null)
+									problem = "y " + valueY + " pixel " + yPixel + " field height " + chart.getField().getBounds().height+ " axis Max " + chart.getAxisMaximumY();
+							}
+							g.setColor(getPointColor(chart, i));
+							int markerW;
+							int markerH;
+							markerW = markerWidth;
+							markerH = markerHeight;
+							if (useCircle){
+								g.fillOval(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth, markerHeight);
+								g.setColor(getPointFrameColor(chart, i));
+								g.drawOval(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth, markerHeight);
+							}
+							else {
+								g.fillRect(xPixel - markerWidth/2, yPixel - markerWidth/2, markerWidth+1, markerHeight+1);
+							}
+						}
+					}
+				}
+				doSelected = true;
+			}
+		}
+		if (problem != null)
+			MesquiteMessage.println("Error: a scattergram value was drawn outside of the bounds of the chart: " + problem);
+		g.setColor(Color.black);
+	}
+	public void drawBlank(Graphics g, MesquiteChart chart){
+		int margin = chart.getMargin();
+		g.setColor(Color.white);
+		g.fillRect(margin, margin, chart.getFieldWidth()-2*margin, chart.getFieldHeight()-2*margin);
+		g.setColor(Color.black);
+		g.drawRect(margin, margin, chart.getFieldWidth()-2*margin, chart.getFieldHeight()-2*margin);
+	}
+	public String getName() {
+		return "Scattergram";
+	}
+}
+
+/* legend for scattergrams in which the data points are colored */
+class ScattergramColorLegend extends Legend {
+	private Scattergram module;
+	private String[] stateNames;
+	private Color[] legendColors;
+	private static final int defaultLegendWidth=142;
+	private static final int defaultLegendHeight=120;
+	private int legendWidth=defaultLegendWidth;
+	private int legendHeight=defaultLegendHeight;
+	private int numBoxes=10;
+	private int oldNumChars = 0;
+	private int oldNumBoxes=0;
+	private int oldCurrentChar = -1;
+	private boolean resizingLegend=false;
+	ScattergramCharter charter;
+	TextArea specsBox;
+	private boolean holding = false;
+	final int scrollAreaHeight = 6;
+	private int messageHeight = 0;
+	final int defaultSpecsHeight = (12 + MesquiteModule.textEdgeCompensationHeight) * 3;
+	private int specsHeight = defaultSpecsHeight;
+	double previousMin =MesquiteDouble.unassigned;
+	double previousMax = MesquiteDouble.unassigned;
+	boolean collapsed = false;
+	public ScattergramColorLegend(Scattergram module, ScattergramCharter charter) {
+		super(defaultLegendWidth, defaultLegendHeight);
+		setVisible(false);
+		setOffsetX(0);
+		setOffsetY(0);
+		this.charter = charter;
+		this.module = module;
+
+		setBackground(Color.white);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+		stateNames = new String[64];
+		legendColors = new Color[64];
+		for (int i=0; i<64; i++) {
+			stateNames[i] = null;
+			legendColors[i] = null;
+		}
+		specsBox = new TextArea(" ", 2, 2, TextArea.SCROLLBARS_NONE);
+		specsBox.setEditable(false);
+		if (module.showLegend.getValue())
+			specsBox.setVisible(false);
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		add(specsBox);
+
+		defaultOffsets();
+
+		reviseBounds();
+	}
+
+
+	public void defaultOffsets() {
+		int buffer = 4;
+		setOffsetX(buffer +1000);
+		setOffsetY(buffer);
+		//setOffsetX(-(defaultWidth+buffer));
+		//setOffsetY(-(defaultHeight+buffer));
+	}
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		//if (messageBox!=null)
+		//	messageBox.setVisible(b);
+		if (specsBox!=null)
+			specsBox.setVisible(b);
+	}
+	public void setMinMax(double min, double max){
+		if (previousMin != min || previousMax!=max){
+			previousMin = min;
+			previousMax = max;
+			for (int i=0; i<10; i++)
+				legendColors[i]= (charter.colorTable.getColor(min + (i*((max-min)/10.0)), min, max));
+			if (min == max && !collapsed){
+				collapsed = true;
+				reviseBounds();
+			}
+			repaint();
+		}
+	}
+
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!holding) {
+			g.setColor(Color.black);
+			if (numBoxes!=0) {
+				for (int ibox=0; ibox<numBoxes; ibox++) {
+					g.setColor(legendColors[ibox]);
+					g.fillRect(4, ibox*16+scrollAreaHeight + specsHeight+ 2, 20, 12);
+					g.setColor(Color.black);
+					g.drawRect(4, ibox*16+scrollAreaHeight + specsHeight + 2, 20, 12);
+					g.drawString(MesquiteDouble.toString(previousMin + (ibox*((previousMax-previousMin)/10.0))), 28, ibox*16 + specsHeight+scrollAreaHeight + 14);
+				}
+			}
+			g.setColor(Color.cyan);
+			g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+			g.fillRect(0, 0, legendWidth-1, scrollAreaHeight);
+			g.setColor(Color.black);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void printAll(Graphics g) {
+		g.setColor(Color.black);
+		int QspecsHeight = 0;
+		int lastBox = scrollAreaHeight + QspecsHeight + 2 + 12;
+		if (numBoxes!=0) {
+			for (int ibox=0; ibox<numBoxes; ibox++) {
+				g.setColor(legendColors[ibox]);
+				g.fillRect(4, ibox*16+scrollAreaHeight + QspecsHeight + 2, 20, 12);
+				g.setColor(Color.black);
+				g.drawRect(4, ibox*16+scrollAreaHeight + QspecsHeight + 2, 20, 12);
+				g.drawString(stateNames[ibox], 28, ibox*16 + QspecsHeight+scrollAreaHeight + 14);
+				lastBox =ibox*16+scrollAreaHeight + QspecsHeight + 2 + 12;
+			}
+		}
+	}
+
+
+	public void reviseBounds(){
+		specsHeight  = defaultSpecsHeight;
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		specsBox.setVisible(true);
+
+		/*messageHeight = messageBox.getHeightNeeded();
+		if (messageHeight<20)
+			messageHeight = 20;
+		 */
+		if (collapsed)
+			legendHeight=scrollAreaHeight + specsHeight + 2 + messageHeight;
+		else
+			legendHeight=numBoxes*16+scrollAreaHeight + specsHeight + 2 + messageHeight;
+		Point where = getLocation();
+		setBounds(where.x,where.y,legendWidth, legendHeight);
+		//messageBox.setBounds(2,legendHeight-messageHeight-1,legendWidth-4, messageHeight);
+	}
+	public void setMessage(String s) {
+		if (s==null || s.equals("")) {
+			//messageBox.setBackground(ColorDistribution.light);
+			//messageBox.setText("\n");
+			reviseBounds();
+		}
+		else {
+			//messageBox.setBackground(Color.white);
+			//messageBox.setText(s);
+			reviseBounds();
+		}
+	}
+	public void onHold() {
+		holding = true;
+	}
+
+	public void offHold() {
+		holding = false;
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, ChartTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (clickCount>1 && y<scrollAreaHeight) {
+			collapsed = !collapsed;
+			reviseBounds();
+		}
+		super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/charts/ShowMean/ShowMean.java b/Source/mesquite/charts/ShowMean/ShowMean.java
new file mode 100644
index 0000000..da3a805
--- /dev/null
+++ b/Source/mesquite/charts/ShowMean/ShowMean.java
@@ -0,0 +1,302 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charts.ShowMean;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+public class ShowMean extends HistogramAssistantA  {
+	/*.................................................................................................................*/
+	public String getName(){
+		return "Display Mean";
+		}
+ 	public String getExplanation() {
+ 		return "Calculates and shows the mean value." ;
+   	 }
+	/*.................................................................................................................*/
+	Vector extras;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+   		extras = new Vector();
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+	public ChartExtra createExtra(MesquiteChart chart){
+		ChartExtra chartExtra = new ShowMeanExtra(this, chart);
+		extras.addElement(chartExtra);
+		return chartExtra;
+	}
+	
+	/*.................................................................................................................*/
+	public String getNameForMenuItem(){
+		return "Display Mean...";
+		}
+	/*.................................................................................................................*/
+  	 public String getAuthors() {
+		return "Wayne P. Maddison & David R. Maddison";
+   	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+
+	/*.................................................................................................................*/
+ 	public void endJob() {
+		if (extras!=null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ChartExtra) {
+					ChartExtra tCO = (ChartExtra)obj;
+		 			tCO.turnOff();
+		 			
+		 		}
+			}
+			extras.removeAllElements();
+		}
+ 		super.endJob();
+   	 }
+}
+
+
+class ShowMeanExtra extends ChartBkgdExtra {
+	MesquiteNumber valueX = new MesquiteNumber();
+	MesquiteNumber valueY = new MesquiteNumber();
+	MesquiteNumber mean = new MesquiteNumber(); //mean, or if some selected, mean of selected
+	MesquiteNumber totalMean = new MesquiteNumber(); //for total (if some selected)
+	Polygon upTriangle,rightTriangle;
+	Charter charter;
+	int trisize = 5;
+	
+	public ShowMeanExtra(MesquiteModule ownerModule, MesquiteChart chart){
+		super(ownerModule, chart);
+		upTriangle=new Polygon();
+		upTriangle.xpoints = new int[4];
+		upTriangle.ypoints = new int[4];
+		upTriangle.npoints=0;
+		upTriangle.addPoint(0, trisize);
+		upTriangle.addPoint(trisize, 0);
+		upTriangle.addPoint(trisize+trisize, trisize);
+		upTriangle.addPoint(0, trisize);
+		upTriangle.npoints=4;
+		rightTriangle=new Polygon();
+		rightTriangle.xpoints = new int[4];
+		rightTriangle.ypoints = new int[4];
+		rightTriangle.npoints=0;
+		rightTriangle.addPoint(0, 0);
+		rightTriangle.addPoint(trisize, trisize);
+		rightTriangle.addPoint(0, trisize+trisize);
+		rightTriangle.addPoint(0, 0);
+		rightTriangle.npoints=4;
+		charter = chart.getCharter();
+	}
+	/**Do any calculations needed*/
+	public boolean doCalculations(){
+		if (chart == null)
+			return false;
+		mean.setValue(0);
+		totalMean.setValue(0);
+		int n=0;
+		int nTotal = 0;
+		boolean someSelected = chart.getSelected().anyBitsOn();
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (chart.getXArray().isCombinable(i) && chart.getYArray().isCombinable(i)) {
+					chart.getXArray().placeValue(i, valueX);
+					chart.getYArray().placeValue(i, valueY);
+					valueX.multiplyBy(valueY);
+					if (someSelected){
+						if (chart.getSelected().isBitOn(i)) {
+							mean.add(valueX);
+							n++;
+						}
+						totalMean.add(valueX);
+						nTotal++;
+					}
+					else {
+						mean.add(valueX);
+						n++;
+					}
+				}
+			}
+		}
+		else {
+			for (int i= 0; i<chart.getNumPoints(); i++) {
+				if (chart.getXArray().isCombinable(i) && chart.getYArray().isCombinable(i)) {
+					chart.getYArray().placeValue(i, valueY);
+					if (someSelected){
+						if (chart.getSelected().isBitOn(i)) {
+							mean.add(valueY);
+							n++;
+						}
+						totalMean.add(valueY);
+						nTotal++;
+					}
+					else {
+						mean.add(valueY);
+						n++;
+					}
+				}
+			}
+		}
+		if (n==0)
+			mean.setToUnassigned();
+		else
+			mean.divideBy(n);
+		if (nTotal==0)
+			totalMean.setToUnassigned();
+		else
+			totalMean.divideBy(nTotal);
+		return false;
+	}
+	
+	Color mainColor = Color.green;
+	Color secondColor = ColorDistribution.lightGreen;
+	/**draw on the chart*/
+	public void drawOnChart(Graphics g){
+		if (!mean.isCombinable())
+			return;
+		Charter c = chart.getCharter();
+		Color col = g.getColor();
+		g.setColor(mainColor);
+
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+			//drawing vertical line
+			int x = c.xToPixel(mean.getDoubleValue(),chart);
+			g.drawLine(x, 0,x, chart.getFieldHeight());
+			g.drawLine(x+1, 0,x+1, chart.getFieldHeight());
+		}
+		else {  
+			//drawing horizontal line
+			int y = c.yToPixel(mean.getDoubleValue(),chart);
+			g.drawLine(0,y, chart.getFieldWidth(), y);
+			g.drawLine(0,y+1, chart.getFieldWidth(), y+1);
+		}
+		if (totalMean.isCombinable()){
+			g.setColor(secondColor);
+			if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+				int x = c.xToPixel(totalMean.getDoubleValue(),chart);
+				g.drawLine(x, 0,x, chart.getFieldHeight());
+				g.drawLine(x+1, 0,x+1, chart.getFieldHeight());
+			}
+			else {  
+				int y = c.yToPixel(totalMean.getDoubleValue(),chart);
+				g.drawLine(0,y, chart.getFieldWidth(), y);
+				g.drawLine(0,y+1, chart.getFieldWidth(), y+1);
+			}
+		}
+		g.setColor(col);
+	}
+	public void drawOnAxes(Graphics g, MesquiteChart chart){
+		if (!mean.isCombinable())
+			return;
+		Color col = g.getColor();
+		g.setColor(mainColor);
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+			int xPixel = xPixelOnAxis(mean.getDoubleValue(), chart)-trisize;
+			int yPixel = chart.getFieldHeight();
+			upTriangle.translate(xPixel,yPixel);
+			g.fillPolygon(upTriangle);
+			//g.setColor(Color.black);
+			//g.drawPolygon(upTriangle);
+			upTriangle.translate(-xPixel,-yPixel);
+		}
+		else {  
+			int xPixel = chart.getXAxisEdge()-trisize;
+			int yPixel = yPixelOnAxis(mean.getDoubleValue(), chart)-trisize;
+			rightTriangle.translate(xPixel,yPixel);
+			g.fillPolygon(rightTriangle);
+			//g.setColor(Color.black);
+			//g.drawPolygon(rightTriangle);
+			rightTriangle.translate(-xPixel,-yPixel);
+		}
+		if (totalMean.isCombinable()){
+			g.setColor(secondColor);
+			if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+				int xPixel = xPixelOnAxis(totalMean.getDoubleValue(), chart)-trisize;
+				int yPixel = chart.getFieldHeight();
+				upTriangle.translate(xPixel,yPixel);
+				g.fillPolygon(upTriangle);
+				//g.setColor(Color.black);
+				//g.drawPolygon(upTriangle);
+				upTriangle.translate(-xPixel,-yPixel);
+			}
+			else {  
+				int xPixel = chart.getXAxisEdge()-trisize;
+				int yPixel = yPixelOnAxis(totalMean.getDoubleValue(), chart)-trisize;
+				rightTriangle.translate(xPixel,yPixel);
+				g.fillPolygon(rightTriangle);
+				//g.setColor(Color.black);
+				//g.drawPolygon(rightTriangle);
+				rightTriangle.translate(-xPixel,-yPixel);
+			}
+		}
+		g.setColor(col);
+		
+	}
+
+	/**print on the chart*/
+	public void printOnChart(Graphics g){
+		drawOnChart(g);
+	}
+	
+	public String writeOnChart(){
+		if (!mean.isCombinable())
+			return "";
+		String s;
+		if (totalMean.isCombinable())
+			s = "Mean value of selection: ";
+		else
+			s = "Mean value: ";
+		s+= mean.toString();
+		if (totalMean.isCombinable())
+			s += "\nMean value of all items: " + totalMean.toString();
+		return s;
+	}
+	
+	/**to inform ChartExtra that cursor has just entered point*/
+	public void cursorEnterPoint(int point, int exactPoint, Graphics g){
+		if (chart == null || charter == null)
+			return;
+		MesquiteNumber mn;
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+			mn = new MesquiteNumber();
+			charter.pixelToX(exactPoint,chart, mn);
+		}
+		else {  
+			mn = new MesquiteNumber();
+			charter.pixelToY(exactPoint,chart, mn);
+		}
+	}
+	/**to inform ChartExtra that cursor has just exited point*/
+	public void cursorExitPoint(int point, int exactPoint, Graphics g){
+	}
+	/**to inform ChartExtra that cursor has just touched point*/
+	public void cursorTouchPoint(int point, int exactPoint, Graphics g){
+	}
+}
+
diff --git a/Source/mesquite/charts/ShowPercentile/001.gif b/Source/mesquite/charts/ShowPercentile/001.gif
new file mode 100644
index 0000000..24066f2
Binary files /dev/null and b/Source/mesquite/charts/ShowPercentile/001.gif differ
diff --git a/Source/mesquite/charts/ShowPercentile/01.gif b/Source/mesquite/charts/ShowPercentile/01.gif
new file mode 100644
index 0000000..8f788f7
Binary files /dev/null and b/Source/mesquite/charts/ShowPercentile/01.gif differ
diff --git a/Source/mesquite/charts/ShowPercentile/05.gif b/Source/mesquite/charts/ShowPercentile/05.gif
new file mode 100644
index 0000000..ef5c1d7
Binary files /dev/null and b/Source/mesquite/charts/ShowPercentile/05.gif differ
diff --git a/Source/mesquite/charts/ShowPercentile/ShowPercentile.java b/Source/mesquite/charts/ShowPercentile/ShowPercentile.java
new file mode 100644
index 0000000..d44941a
--- /dev/null
+++ b/Source/mesquite/charts/ShowPercentile/ShowPercentile.java
@@ -0,0 +1,691 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charts.ShowPercentile;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.charts.Histogram.*;
+/*
+DRM May 2003
+*/
+
+public class ShowPercentile extends HistogramAssistantA implements ActionListener  {
+	/*.................................................................................................................*/
+ 	public String getName(){
+		return "Show Percentile";
+	}
+ 	public String getExplanation() {
+ 		String s= "Calculates and shows percentile boundaries.  Finds the upper (right) or lower (left) tail of the distribution that contains the specified percentage of the distribution.";
+ 		return s + " If there is not a boundary that exactly matches the specified percentage, then the closest boundary that does not exceed the percentage is shown." ;
+   	 }
+	/*.................................................................................................................*/
+	Vector extras;
+	double percentile=0.05;
+	boolean leftTail=true;
+	boolean rightTail = true;
+
+	ExtensibleDialog dialog;
+	Choice colorChoice;
+	Checkbox leftTailCheck;
+	Checkbox rightTailCheck;
+	Color color = Color.red;
+	int colorNumber = 5;
+	DoubleField df;
+	MesquiteInteger buttonPressed;
+	boolean towardMedian=true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+   		extras = new Vector();
+   		addMenuItem("Adjust Percentile Shown...", makeCommand("setPercentile",  this));
+		if (MesquiteThread.isScripting())
+			return true;
+		return queryPercentile();
+	}
+	/*.................................................................................................................*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean queryPercentile(){
+		buttonPressed = new MesquiteInteger(1);
+		dialog = new ExtensibleDialog(containerOfModule(), "Show Percentile",  buttonPressed);
+		dialog.setAutoDispose(false);
+		df = dialog.addDoubleField("Percentile boundary",percentile,20);
+		
+		colorChoice = dialog.addPopUpMenu("Line color: ", ColorDistribution.standardColorNames.getStrings(),colorNumber);
+		
+		leftTailCheck = dialog.addCheckBox("lower (left) tail", leftTail);
+		dialog.suppressNewPanel();
+		rightTailCheck = dialog.addCheckBox("upper (right) tail", rightTail);
+		
+		String helpString = "\"Show Percentile\" will draw lines marking the specified percentile.  It will mark the percentile at both tails.  ";
+		helpString += " Thus, if you choose 0.05 as the percentile, it will draw a line marking the first 0.05 of the values, and the last 0.05 of the values.";
+		dialog.appendToHelpString(helpString);
+		
+		dialog.setHelpURL(this,"",true);
+		
+		dialog.completeAndShowDialog(true,this);
+		
+		if (dialog!=null) {
+			 if (buttonPressed.getValue()==0) {
+		 		if (checkOptions()) {
+		 			getOtherDialogValues();
+		 		}
+		 		else 
+		 			buttonPressed.setValue(1);
+			 }
+			if (dialog!=null)
+				dialog.dispose();
+		}
+		
+		return  (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void getOtherDialogValues(){
+		colorNumber = colorChoice.getSelectedIndex();
+	 	color = ColorDistribution.getStandardColor( colorNumber);
+	 	leftTail = leftTailCheck.getState();
+		rightTail = rightTailCheck.getState();
+		if (!leftTail && !rightTail) {
+			MesquiteMessage.notifyUser("At least one tail must be shown; the upper (right) will be chosen");
+			rightTail=true;
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	String s = "setPercentile " + percentile + "  " + colorNumber; 
+   	 	if (leftTail && rightTail)
+   	 		s += " 2";
+   	 	else if (rightTail)
+   	 		s += " 1";
+  	 	else 
+   	 		s += " 0";
+  	 	temp.addLine(s); 
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+  	/*.................................................................................................................*/
+  	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the percentile", "[percentile, 0 to 1]", commandName, "setPercentile")) {
+    	 		pos.setValue(0);
+ 			double s = MesquiteDouble.fromString(arguments, pos);
+    	 		int bc = MesquiteInteger.fromString(arguments, pos); 
+    	 		int tails = MesquiteInteger.fromString(arguments, pos); 
+    	 		if (MesquiteInteger.isCombinable(bc)) {
+    	 			colorNumber = bc;
+	 			color = ColorDistribution.getStandardColor( colorNumber);
+	 		}
+	 		if (MesquiteInteger.isCombinable(tails)){
+	 			leftTail=true;
+	 			rightTail=true;
+	 			if (tails==0)
+	 				rightTail=false;
+	 			else if (tails==1)
+	 				leftTail=false;
+	 		}
+	 		boolean q = true;
+	 		if (!MesquiteDouble.isCombinable(s) || s<0 || s>1)
+ 				q = queryPercentile();
+ 			else
+ 				percentile = s;
+	 		if (q) {
+				for (int i =0; i<extras.size(); i++){
+					ShowPercentileExtra e = (ShowPercentileExtra)extras.elementAt(i);
+					e.percentile = percentile;
+					e.color = color;
+					e.setShowLeftTail(leftTail);
+					e.setShowRightTail(rightTail);
+				}
+	 			parametersChanged();
+	 		}
+    		}
+   	 	else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+   	public boolean checkOptions(){
+   		double value = df.getValue();
+   		if (!MesquiteDouble.isCombinable(value))
+   			return false;
+   		if (value<0.0000000001 || value>0.999999999)
+   			return false;
+   		percentile = value;
+   		return true;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+	public ChartExtra createExtra(MesquiteChart chart){
+		ShowPercentileExtra chartExtra = new ShowPercentileExtra(this, chart, percentile, color, leftTail, rightTail);
+		extras.addElement(chartExtra);
+		return chartExtra;
+	}
+	
+	/*.................................................................................................................*/
+	public String getNameForMenuItem(){
+		return "Percentiles...";
+		}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Percentile shown: " + percentile;
+	}
+	/*.................................................................................................................*/
+  	 public String getAuthors() {
+		return "David R. Maddison & Wayne P. Maddison";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	if   (dialog.getDefaultOKLabel().equals(e.getActionCommand())) {
+	 		if (checkOptions()) {
+	 			getOtherDialogValues();
+	 			buttonPressed.setValue(0);
+	 			dialog.dispose();
+	 			dialog=null;
+	 		}
+	 		else
+	 			alert("Percentile value needs to be between 0.0 and 1.0");
+		}
+	 	else if   (dialog.getDefaultCancelLabel().equals(e.getActionCommand())) {
+	 		buttonPressed.setValue(1);
+			dialog.dispose();
+		}
+		else dialog.actionPerformed(e);
+	 }
+	 
+	/*.................................................................................................................*/
+ 	public void endJob() {
+		if (extras!=null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof ChartExtra) {
+					ChartExtra tCO = (ChartExtra)obj;
+		 			tCO.turnOff();
+		 			
+		 		}
+			}
+			extras.removeAllElements();
+		}
+ 		super.endJob();
+   	 }
+}
+
+/* =================================================================================*/
+class ShowPercentileExtra extends ChartBkgdExtra {
+	double percentile;  
+	int totalValues=0;
+	int numPercentiles=2;   // percentile 0 is left tail; percentile 1 is right tail
+	double[] actualPercentile = new double[numPercentiles];
+	boolean[] showTail = new boolean[numPercentiles];
+	int[] numValues = new int[numPercentiles];   //
+	MesquiteNumber[] percentileBoundary = new MesquiteNumber[numPercentiles];
+	MesquiteNumber[] percentileBoundaryDrawn = new MesquiteNumber[numPercentiles];
+	MesquiteBoolean[] includeEqualSign = new MesquiteBoolean[numPercentiles];
+	Charter charter;
+	Color color, useColor;
+	Polygon upTriangle,rightTriangle;
+	private boolean warnedOnce = false;
+	int trisize = 5;
+	boolean okToShowPercentile = true;
+	
+	public ShowPercentileExtra(MesquiteModule ownerModule, MesquiteChart chart, double percent, Color color, boolean leftTail, boolean rightTail){
+		super(ownerModule, chart);
+		upTriangle=new Polygon();
+		upTriangle.xpoints = new int[4];
+		upTriangle.ypoints = new int[4];
+		upTriangle.npoints=0;
+		upTriangle.addPoint(0, trisize);
+		upTriangle.addPoint(trisize, 0);
+		upTriangle.addPoint(trisize+trisize, trisize);
+		upTriangle.addPoint(0, trisize);
+		upTriangle.npoints=4;
+		rightTriangle=new Polygon();
+		rightTriangle.xpoints = new int[4];
+		rightTriangle.ypoints = new int[4];
+		rightTriangle.npoints=0;
+		rightTriangle.addPoint(0, 0);
+		rightTriangle.addPoint(trisize, trisize);
+		rightTriangle.addPoint(0, trisize+trisize);
+		rightTriangle.addPoint(0, 0);
+		rightTriangle.npoints=4;
+		percentile =percent;
+		this.color = color;
+		charter = chart.getCharter();
+		for (int i=0; i<numPercentiles; i++) {
+			percentileBoundary[i]=new MesquiteNumber(0);
+			percentileBoundaryDrawn[i]=new MesquiteNumber(0);
+			includeEqualSign[i] = new MesquiteBoolean(true);
+		}
+	
+		showTail[0] = leftTail;
+		showTail[1] = rightTail;
+		
+
+	}
+	/*.................................................................................................................*/
+	public boolean canDoShowPercentile(){
+		boolean canDo = (chart.getOrientation() == 0 || charter.isNative());
+		if (!canDo && !warnedOnce) {
+			MesquiteTrunk.mesquiteTrunk.discreetAlert( "Show Percentile is not available with this orientation if items are grouped.");
+			warnedOnce = true;
+		}
+		okToShowPercentile = canDo;
+		return canDo;
+	}
+	/*.................................................................................................................*/
+	public void setShowLeftTail (boolean show){
+		showTail[0]=show;
+	}
+	/*.................................................................................................................*/
+	public void setShowRightTail (boolean show){
+		showTail[1]=show;
+	}
+	/*.................................................................................................................*/
+	public double getPercentile (){
+		return percentile;
+	}
+	/*.................................................................................................................*/
+	public void setInitialBoundaryValues (int tail, int count, double numInPercentile, int point, int lastPoint, int i, NumberArray array, MesquiteNumber boundaryValue){
+		if (count==numInPercentile) {
+			array.placeValue(point,boundaryValue);  // we are at it, store this point
+		}
+		else {  // we've gone past it.
+			if (count>1)
+				array.placeValue(lastPoint,boundaryValue);  // as we have gone past it, now store the last point
+			else 
+				boundaryValue.setToUnassigned(); // we've gone past it just by getting to the first point; therefore, boundary is edge - indicate this by setting to unassigned.
+			numValues[tail]=count-1;
+		}
+	}
+	
+	/*.................................................................................................................*/
+	boolean pointValid(MesquiteChart chart, int point){
+		if (chart ==null)
+			return false;
+		if (!okToShowPercentile)
+			return false;
+		return (chart.getXArray().isCombinable(point) && chart.getYArray().isCombinable(point));
+	}
+	/*.................................................................................................................*/
+	/**Calculates the boundary for a particular percentile value*/
+	public void placePercentileBoundary(double percentileValue, boolean left, MesquiteNumber mnDrawn, MesquiteNumber mn, MesquiteBoolean mb){
+//		int numInPercentile = (int)java.lang.Math.round(percentileValue * totalValues-0.0000000001);  
+//		int numInPercentile = MesquiteInteger.roundUp(percentileValue * totalValues);  
+		double numInPercentile = percentileValue * totalValues;  
+		
+		MesquiteNumber previousValue = new MesquiteNumber();
+		MesquiteNumber currentValue = new MesquiteNumber();
+		MesquiteNumber nextValue = new MesquiteNumber();
+		MesquiteNumber boundaryValue = new MesquiteNumber();
+		MesquiteNumber boundaryValueDrawn = new MesquiteNumber();
+		int count=1;   
+		int lastDifferentCount=1;
+		int lastDifferentPoint=MesquiteInteger.unassigned;
+		NumberArray values = null;
+		MesquiteNumber minimumDrawn = null;
+		MesquiteNumber minimum = null;
+		MesquiteNumber maximumDrawn = null;
+		MesquiteNumber maximum = null;
+		boolean boundaryIncludeEqualSign = true;
+		int[] ord =  null;  // order of the points ordered by x coordinate.  returns integerarray.
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items   (y by x)
+			values = chart.getXArray();
+			minimum = charter.leftmostXDrawn(chart);
+			minimumDrawn = chart.getMinimumX();
+			ord =  chart.getOrderByX();  // order of the points ordered by x coordinate.  returns integerarray.
+			maximumDrawn = charter.rightmostXDrawn(chart);
+			maximum = chart.getMaximumX();
+		}
+		else if (chart.getOrientation() == 1) {  //orientation stored in chart as 0 = items by values; 1 = values by items   (y by x)
+			values = chart.getYArray();
+			minimum = chart.getMinimumY();
+			minimumDrawn = charter.bottommostYDrawn(chart);
+			ord =  chart.getOrderByY();  // order of the points ordered by y coordinate.  returns integerarray.
+			maximumDrawn = charter.topmostYDrawn(chart);
+			maximum = chart.getMaximumY();
+		}
+		if (ord !=null){
+			int point =0;
+			int lastPoint = 0;  // this keeps note of the last point encountered
+			count =1;  // this keeps count of the number of points we have gone through
+			boolean boundaryFound = false;
+// LEFT TAIL
+			if (left) {
+				for (int i= 0; i<chart.getNumPoints(); i++) {     
+					point = ord[i];   // these ordering of the points is stored in ord
+								// however, the value of "point" is not in order - that is, the values of ord[0], ord[1], ord[2] might be 23   184  99
+					if (pointValid(chart, point)) {
+						values.placeValue(point,currentValue); 
+						if (!currentValue.equals(previousValue) && previousValue.isCombinable()) {// there is a change between the last point and this one
+							lastDifferentPoint = lastPoint;
+							lastDifferentCount = count-1;
+						}
+						if (!boundaryFound &&  (count >= numInPercentile)) {  // we've found the boundary element
+								//now we have to figure out exactly what is the boundary value.
+							setInitialBoundaryValues (0,count, numInPercentile, point, lastPoint, i, values, boundaryValue);
+							boundaryFound = true;
+							if (!boundaryValue.isCombinable()){  // at the left edge
+								boundaryValue.setValue(minimum.getDoubleValue());  // set it to the minimumDrawn value
+								boundaryValueDrawn.setValue(minimumDrawn.getDoubleValue());
+							}
+							else {
+								if (i<chart.getNumPoints()-1) {  // we are not at the end
+									int nextPoint=MesquiteInteger.unassigned;
+									for (int j=i+1; j<chart.getNumPoints(); j++) {
+										nextPoint = ord[j];
+										if (pointValid(chart, nextPoint)) {
+											values.placeValue(nextPoint,nextValue);
+											break;
+										}
+									}
+									if (nextValue.equals(boundaryValue)) {// then if we include this value in it, we also need to include too large a percentile, > value desired
+																	// so we need to reset the value to that of the previous bin
+										if (!MesquiteInteger.isCombinable(lastDifferentPoint)) {  // the previous bin is the left edge of the chart
+											boundaryValue.setValue(minimum.getDoubleValue());
+											boundaryValueDrawn.setValue(minimumDrawn.getDoubleValue());
+											numValues[0]=0;
+										}
+										else {
+											values.placeValue(lastDifferentPoint,boundaryValue); 
+											numValues[0]=lastDifferentCount;
+										}
+									}
+									if (!boundaryValueDrawn.isCombinable()){  //we haven't set this yet; 
+										if (charter.moreThanOneValueInInterval(boundaryValue, chart)) // then we want to leave it where it is
+											boundaryValueDrawn.setValue(boundaryValue.getDoubleValue());
+										else if (chart.getOrientation() == 0) 
+											boundaryValueDrawn.setValue(charter.rightmostXOfInterval(boundaryValue, chart));  // we want to set it to limits of bar
+										else
+											boundaryValueDrawn.setValue(charter.topmostYOfInterval(boundaryValue, chart));  // we want to set it to limits of bar
+									}
+
+								}
+							}
+							break;						
+						}
+						values.placeValue(point,previousValue);
+						lastPoint = point;
+						count++;
+					}
+				}
+				if (!boundaryFound) {  // we didn't find it, thus needs to be end point (???)
+					values.placeValue(lastPoint,previousValue);
+					numValues[0]=count-1;
+				}
+				actualPercentile[0] = 1.0* (numValues[0])/totalValues;
+			}
+// RIGHT TAIL
+			else {  
+				for (int i= chart.getNumPoints()-1; i>=0; i--) {      // we start from the right edge of the chart, and cycle through the points going left
+					point = ord[i];
+					if (pointValid(chart, point)) {    // ok, we have a point with good values
+						values.placeValue(point,currentValue); 
+						if (!currentValue.equals(previousValue) && previousValue.isCombinable()) {// there is a change between the last point and this one
+							lastDifferentPoint = lastPoint;   // store last point that was different so we can set the boundary there if needed
+							lastDifferentCount = count-1;
+						}
+						if (!boundaryFound &&  (count >= numInPercentile)) {  // we've found the boundary element
+							setInitialBoundaryValues (1,count, numInPercentile, point, lastPoint, i, values, boundaryValue);
+							boundaryFound = true;
+							if (!boundaryValue.isCombinable() && maximumDrawn!=null) {  // the boundary is at right edge of the chart
+								boundaryValue.setValue(maximum.getDoubleValue());  
+								boundaryValueDrawn.setValue(maximumDrawn.getDoubleValue());
+							}
+							else {
+								if (i>0) {  // we are not at the end
+									int nextPoint=MesquiteInteger.unassigned;
+									for (int j=i-1; j>=0; j--) {   // we cycle through looking for the next value to the left, and place it in nextValue
+										nextPoint = ord[j];
+										if (pointValid(chart, nextPoint)) {
+											values.placeValue(nextPoint,nextValue);
+											break;
+										}
+									}
+									if (nextValue.equals(boundaryValue)) {// then if we include this value in it, we also need to include too large a percentile, > value desired
+																	// so we need to reset it to the previous bin
+										if (!MesquiteInteger.isCombinable(lastDifferentPoint)) {  // we never set lastDifferentPoint; boundary is at end
+											if (maximumDrawn!=null){
+												boundaryValue.setValue(maximum.getDoubleValue());  // set it to the right edge
+												boundaryValueDrawn.setValue(maximumDrawn.getDoubleValue());  // set it to the right edge
+											}
+											numValues[1]=0;
+										}
+										else {   // we did set lastDifferentPoint; that's were we move the boundary too
+											values.placeValue(lastDifferentPoint,boundaryValue); 
+											numValues[1]=lastDifferentCount;
+										}
+									}
+									if (!boundaryValueDrawn.isCombinable()){  //we haven't set this yet; 
+										if (charter.moreThanOneValueInInterval(boundaryValue, chart)) // then we want to leave it where it is
+											boundaryValueDrawn.setValue(boundaryValue.getDoubleValue());
+										else if (chart.getOrientation() == 0) 
+											boundaryValueDrawn.setValue(charter.leftmostXOfInterval(boundaryValue, chart));  // we want to set it to limits of bar
+										else
+											boundaryValueDrawn.setValue(charter.bottommostYOfInterval(boundaryValue, chart));  // we want to set it to limits of bar
+									}
+								}
+							}
+							break;						
+						}
+						values.placeValue(point,previousValue);
+						lastPoint = point;
+						count++;
+					}
+				}
+				if (!boundaryFound) {  // we didn't find it, thus needs to be end point (???)
+					values.placeValue(lastPoint,previousValue);
+					numValues[1]=count-1;
+				}
+				actualPercentile[1] = 1.0* (numValues[1])/totalValues;
+			}
+		}
+
+		mnDrawn.setValue(boundaryValueDrawn);
+		mn.setValue(boundaryValue);
+		
+		mb.setValue(boundaryIncludeEqualSign);
+	}
+	/*.................................................................................................................*/
+	/**Do any calculations needed*/
+	public boolean doCalculations(){
+		if (chart == null)
+			return false;
+		if (!canDoShowPercentile())
+			return false;
+		for (int i=0; i<numPercentiles; i++) {
+			percentileBoundary[i].setToUnassigned();  
+			percentileBoundaryDrawn[i].setToUnassigned();  
+			actualPercentile[i]=0.0;
+			numValues[i]=0;
+		}
+			
+		if (chart.getOrientation() == 0)
+			totalValues = chart.getYTotal().getIntValue();
+		else
+			totalValues = chart.getNumPoints();
+		if (chart.getCharter() != null){
+			if (chart.getCharter().showingClumpSums())
+				return false;
+		}
+		for (int i=0; i<numPercentiles; i++) {
+			actualPercentile[i] = percentile;
+			numValues[i]=(int)(percentile * totalValues);
+		}
+
+		if (showTail[0]) 
+			placePercentileBoundary(percentile,true,percentileBoundaryDrawn[0], percentileBoundary[0], includeEqualSign[0]);///, percentileBoundaryNext[0]);
+		if (showTail[1])
+			placePercentileBoundary(percentile,false,percentileBoundaryDrawn[1], percentileBoundary[1], includeEqualSign[1]);///, percentileBoundaryNext[1]);
+		boolean someSelected = chart.getSelected().anyBitsOn();
+		if (someSelected)
+			useColor = ColorDistribution.brighter(color, ColorDistribution.dimmingConstant*1.5);
+		else
+			useColor = color;
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	/**draw on the chart*/
+	public void drawOnChart(Graphics g){
+		if (!okToShowPercentile)
+			return;
+		Color col = g.getColor();
+		g.setColor(useColor);
+		int x;
+		int x2;
+		int y;
+		for (int i=0; i<numPercentiles; i++) {
+			if (showTail[i]) {
+				if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+					//drawing vertical line
+					if (!percentileBoundaryDrawn[i].isCombinable()) {
+						if (i==0) //left tail
+							x = charter.xToPixel(charter.leftmostXDrawn(chart).getDoubleValue(),chart);
+						else {
+							x = charter.xToPixel(charter.rightmostXDrawn(chart).getDoubleValue(),chart);
+						}
+					}
+					else {
+						x = charter.xToPixel(percentileBoundaryDrawn[i].getDoubleValue(),chart);
+						
+					}
+					g.drawLine(x, 0,x, chart.getFieldHeight());
+					g.drawLine(x+1, 0,x+1, chart.getFieldHeight());
+				}
+				else {  
+					//drawing horizontal line
+					if (!percentileBoundaryDrawn[i].isCombinable()) 
+						return;
+					y = charter.yToPixel(percentileBoundaryDrawn[i].getDoubleValue(),chart);
+					g.drawLine(0,y, chart.getFieldWidth(), y);
+					g.drawLine(0,y+1, chart.getFieldWidth(), y+1);
+				}
+			}
+		}
+		g.setColor(col);
+	}
+	public void drawOnAxes(Graphics g, MesquiteChart chart){
+		if (!okToShowPercentile)
+			return;
+		Color col = g.getColor();
+		g.setColor(useColor);
+		for (int i=0; i<numPercentiles; i++) {
+			if (showTail[i] && percentileBoundaryDrawn[i].isCombinable()) {
+				if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+					int xPixel = xPixelOnAxis(percentileBoundaryDrawn[i].getDoubleValue(), chart)-trisize;
+					int yPixel = chart.getFieldHeight();
+					upTriangle.translate(xPixel,yPixel);
+					g.fillPolygon(upTriangle);
+					upTriangle.translate(-xPixel,-yPixel);
+				}
+				else {  
+					int xPixel = chart.getXAxisEdge()-trisize;
+					int yPixel = yPixelOnAxis(percentileBoundaryDrawn[i].getDoubleValue(), chart)-trisize;
+					rightTriangle.translate(xPixel,yPixel);
+					g.fillPolygon(rightTriangle);
+					rightTriangle.translate(-xPixel,-yPixel);
+				}
+			}
+		}
+		g.setColor(col);
+		
+	}
+	/*.................................................................................................................*/
+	/**print on the chart*/
+	public void printOnChart(Graphics g){
+		drawOnChart(g);
+	}
+	/*.................................................................................................................*/
+	public String getTailNote(int i, boolean left){
+		String s = " percentile boundary ";
+		if (left) {
+			if (chart.getOrientation() == 0)
+				s += "(lower tail) <";
+			else
+				s += "(left tail) <";
+			if (numValues[i]>0 && includeEqualSign[i].getValue())
+				s += "=";
+		}
+		else {
+			if (chart.getOrientation() == 0)
+				s += "(upper tail) >";
+			else
+				s += "(right tail) >";
+			if (numValues[i]>0 && includeEqualSign[i].getValue())
+				s += "=";
+		}
+		s= "" + actualPercentile[i] + s +" " + percentileBoundary[i].getDoubleValue();
+		if (actualPercentile[i]!=percentile) {
+			s+="\n     " + actualPercentile[i] + " is the closest percentile to "+percentile + " that was found,";
+			s+="\n     and";
+		}
+		else
+			s+="\n     This";
+		s+=" corresponds to " + numValues[i] + " replicate";
+		if (numValues[i]>1 || numValues[i]==0)
+			s+="s";
+		s+=" out of "+totalValues + ".";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String writeOnChart(){
+		if (!okToShowPercentile)
+			return "";
+		String s="";
+		if (showTail[0])
+			s+= getTailNote(0,true);
+		if (showTail[1])
+			s+="\n" + getTailNote(1,false);
+		return s;
+	}
+	/*.................................................................................................................*/
+	/**to inform ChartExtra that cursor has just entered point*/
+	public void cursorEnterPoint(int point, int exactPoint, Graphics g){
+		if (chart == null || charter == null)
+			return;
+		MesquiteNumber mn;
+		if (chart.getOrientation() == 0) {  //orientation stored in chart as 0 = items by values; 1 = values by items
+			mn = new MesquiteNumber();
+			charter.pixelToX(exactPoint,chart, mn);
+		}
+		else {  
+			mn = new MesquiteNumber();
+			charter.pixelToY(exactPoint,chart, mn);
+		}
+	}
+	/*.................................................................................................................*/
+	/**to inform ChartExtra that cursor has just exited point*/
+	public void cursorExitPoint(int point, int exactPoint, Graphics g){
+	}
+	/*.................................................................................................................*/
+	/**to inform ChartExtra that cursor has just touched point*/
+	public void cursorTouchPoint(int point, int exactPoint, Graphics g){
+	}
+}
+
diff --git a/Source/mesquite/charts/ShowPercentile/manual.html b/Source/mesquite/charts/ShowPercentile/manual.html
new file mode 100644
index 0000000..e312e8c
--- /dev/null
+++ b/Source/mesquite/charts/ShowPercentile/manual.html
@@ -0,0 +1,48 @@
+<HTML>
+<!--This file created 14/3/01 8:53 AM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Show Percentile</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=42 BOTTOM=757 LEFT=4 RIGHT=534>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+</HEAD>
+<BODY>
+<H2><TABLE BORDER=4 CELLPADDING=0>
+   <TR>
+       <TD>
+         <H2>Mesquite: Show Percentile</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>August 2005</P>
+
+<P>Show Percentile calculates and displays percentile values in histograms.</P>
+<P>For example, the lower (left) tail of the following distribution has the 0.01 
+  percentile marked, as exactly 1 of the 100 values is less than or equal to the 
+  marked value. </P>
+<P><img src="01.gif" width="468" height="250"></P>
+<P>Show Percentile shows that value that corresponds to the specified percentile. 
+  However, if there is no value that exactly corresponds to a percentile, then 
+  it shows the value that corresponds most closely to the requested percentile, 
+  but that is less than the requested percentile. For example, the nearest two 
+  percentiles in this distribution to 0.001 would be either 0.0 (including 0 values) 
+  or 0.01 (including 1 value); Show Percentile chooses 0.0, as that is the nearest 
+  value that does not exceed the requested percentile:</P>
+<P><img src="001.gif" width="468" height="250"></P>
+<P>The 0.05 lower percentile for this distribution is shown below:</P>
+<P><img src="05.gif" width="468" height="250"></P>
+<P>This might also be the distribution shown if you requested 0.06, as the nearest 
+  percentiles for that value are 0.05 or 0.07, and so Show Percentile would choose 
+  0.05. <br>
+</P>
+<P>Full details of the percentiles displayed can be seen by touching the Text 
+  tab of the histogram window.</P>
+<P>© David Maddison & Wayne Maddison, 2005</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/charts/ShowYEqualsX/ShowYEqualsX.java b/Source/mesquite/charts/ShowYEqualsX/ShowYEqualsX.java
new file mode 100644
index 0000000..c5fe7ac
--- /dev/null
+++ b/Source/mesquite/charts/ShowYEqualsX/ShowYEqualsX.java
@@ -0,0 +1,111 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.ShowYEqualsX;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+public class ShowYEqualsX extends ScattergramAssistantA  {
+	/*.................................................................................................................*/
+	public String getName(){
+		return "Show Y = X";
+	}
+	public String getExplanation() {
+		return "Shows the Y=X line on a scattergram";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	public ChartExtra createExtra(MesquiteChart chart){
+		return new ShowYEqualsXExtra(this, chart);
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+
+}
+
+
+class ShowYEqualsXExtra extends ChartExtra {
+	double meanX, meanY;
+	public ShowYEqualsXExtra(MesquiteModule ownerModule, MesquiteChart chart){
+		super(ownerModule, chart);
+	}
+	/**Do any calculations needed*/
+	public boolean doCalculations(){
+		return false;
+	}
+
+	MesquiteNumber max = new MesquiteNumber();
+	MesquiteNumber temp = new MesquiteNumber();
+
+	public void drawOnChart(Graphics g){
+		Charter c = chart.getCharter();
+		max.setValue(0);
+		temp.setValue(chart.getMinimumX());
+		temp.abs();
+		max.setMeIfIAmLessThan(temp);
+		temp.setValue(chart.getMinimumY());
+		temp.abs();
+		max.setMeIfIAmLessThan(temp);
+		temp.setValue(chart.getMaximumX());
+		temp.abs();
+		max.setMeIfIAmLessThan(temp);
+		temp.setValue(chart.getMaximumY());
+		temp.abs();
+		max.setMeIfIAmLessThan(temp);
+		Color col = g.getColor();
+		g.setColor(Color.green);
+		int xMin = c.xToPixel(-max.getDoubleValue(),chart);
+		int yMin =  c.yToPixel(-max.getDoubleValue(),chart);
+		int xMax = c.xToPixel(max.getDoubleValue(),chart);
+		int yMax = c.yToPixel(max.getDoubleValue(),chart);
+		g.drawLine(xMin,yMin ,xMax, yMax);
+		g.drawLine(xMin+1,yMin+1 ,xMax+1, yMax+1);
+		g.setColor(col);
+	}
+	/**print on the chart*/
+	public void printOnChart(Graphics g){
+		drawOnChart(g);
+	}
+
+	public String writeOnChart(){
+		return null;
+	}
+
+	/**to inform ChartExtra that cursor has just entered point*/
+	public void cursorEnterPoint(int point, int exactPoint, Graphics g){
+	}
+	/**to inform ChartExtra that cursor has just exited point*/
+	public void cursorExitPoint(int point, int exactPoint, Graphics g){
+	}
+	/**to inform ChartExtra that cursor has just touched point*/
+	public void cursorTouchPoint(int point, int exactPoint, Graphics g){
+	}
+}
+
diff --git a/Source/mesquite/charts/TaxaScattergram/TaxaScattergram.java b/Source/mesquite/charts/TaxaScattergram/TaxaScattergram.java
new file mode 100644
index 0000000..3d84fc9
--- /dev/null
+++ b/Source/mesquite/charts/TaxaScattergram/TaxaScattergram.java
@@ -0,0 +1,329 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.TaxaScattergram;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TaxaScattergram.  ===*/
+
+public class TaxaScattergram extends FileAssistantCS  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxa Scattergram";
+	}
+	public String getExplanation() {
+		return "Makes a scatterplot displaying two values (such as proportion of gaps in a sequence, etc.) for a series of taxa.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTaxon.class,getName() + " needs methods to calculate the two values for the taxa.",
+		"You can select this either when the chart starts up, or using the Values submenus of the Chart menu.  (You may request the chart itself by selecting the Taxa item under New Scattergram in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TaxonSource.class, getName() + " needs a source of taxa.",
+		"You can select the taxa to show either when the chart starts up, or using the Taxon Source submenu of the Chart menu, if there is more than one source available.  (You may request the chart itself by selecting the Taxa item under New Scattergram in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsBiplotter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForTaxon numberTaskX, numberTaskY;
+	private TaxonSource taxonSourceTask;
+	ItemsBiplotter chartWindowTask;
+	public Taxa taxa;
+	boolean separateAxes=false;
+	MesquiteString numberTaskXName, numberTaskYName;
+	MesquiteString taxonSourceName;
+	ChartWindow cWindow;
+	MesquiteCommand tstC, ntC, ntxC, ntyC;
+	MesquiteMenuSpec mX;
+	MesquiteMenuSpec mY;
+	static int numMade = 0;
+	MesquiteBoolean showNames;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because no blocks of taxa are available.");
+		chartWindowTask = (ItemsBiplotter)hireEmployee(ItemsBiplotter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+
+		//Source of Taxa %%%%%%%%
+		taxonSourceTask= (TaxonSource)hireEmployee(TaxonSource.class, "Source of taxa (Taxa scattergram)");
+		if (taxonSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of taxa was obtained.");
+		//todo: doesn't use taxonSource!!!!!!!
+		tstC = makeCommand("setTaxonSource",  this);
+		taxonSourceTask.setHiringCommand(tstC);
+		taxonSourceName = new MesquiteString();
+		taxonSourceName.setValue(taxonSourceTask.getName());
+		if (numModulesAvailable(TaxonSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Taxon Source", tstC, TaxonSource.class);
+			mss.setSelected(taxonSourceName);
+		}
+		makeMenu("Scattergram");
+
+
+		//values etc.  %%%%%%%%
+		ntC = makeCommand("setValues",  this);
+		ntxC = makeCommand("setValuesX",  this);
+		ntyC = makeCommand("setValuesY",  this);
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		cWindow.setChartTitle("Taxa Scattergram " + (++numMade));
+		cWindow.resetTitle();
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a scattergram?");
+		if (taxa==null)
+			return sorry(getName() + " couldn't start because taxa block not obtained.");
+		taxa.addListener(this);
+		numberTaskXName = new MesquiteString();
+		numberTaskYName = new MesquiteString();
+		showNames = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Taxon Names", MesquiteModule.makeCommand("showNamesToggle",  this), showNames);
+		/* ---------------------------*/
+		if (!MesquiteThread.isScripting()){
+			String expl = "(For instance, the X and Y axes might show the same calculations but for different characters, or they may show two entirely different calculations.)";
+			separateAxes = (numModulesAvailable(NumberForTaxonIncr.class)==0) || !AlertDialog.query(containerOfModule(), "Axes", "Choose same or different calculations for the two axes? " + expl, "Same", "Different");
+			initMenus();
+			if (!separateAxes){
+				numberTaskX = (NumberForTaxonIncr)hireEmployee(NumberForTaxonIncr.class, "Values for axes");
+				if (numberTaskX == null)
+					return false;
+				numberTaskXName.setValue(numberTaskX.getName());
+				numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+			}
+			else {
+				numberTaskX = (NumberForTaxon)hireEmployee(NumberForTaxon.class, "Values for X axis");
+				if (numberTaskX == null)
+					return false;
+				numberTaskY = (NumberForTaxon)hireEmployee(NumberForTaxon.class, "Values for Y axis");
+				if (numberTaskY == null)
+					return false;
+				numberTaskX.setMenuToUse(mX);
+				numberTaskY.setMenuToUse(mY);
+				numberTaskX.setHiringCommand(ntxC);
+				numberTaskY.setHiringCommand(ntyC);
+				numberTaskXName.setValue(numberTaskX.getName());
+				numberTaskYName.setValue(numberTaskY.getName());
+			}
+			sendParametersToCharter();
+			if (!MesquiteThread.isScripting()){
+				chartWindowTask.doCounts();
+				cWindow.setChartVisible();
+				cWindow.setVisible(true);
+			}
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		/* ---------------------------*/
+
+		return true;
+	}
+	private void initMenus(){
+		if (!separateAxes){
+			if (numModulesAvailable(NumberForTaxonIncr.class)>1) {
+				MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberForTaxonIncr.class);
+				mss.setSelected(numberTaskXName);
+			}
+		}
+		else {
+			mX = addAuxiliaryMenu("X.Axis");
+			mY = addAuxiliaryMenu("Y.Axis");
+			if (numModulesAvailable(NumberForTaxon.class)>1) {
+				MesquiteSubmenuSpec mss = addSubmenu(mX, "Values on X", ntxC, NumberForTaxon.class);
+				mss.setSelected(numberTaskXName);
+				mss = addSubmenu(mY, "Values on Y", ntyC, NumberForTaxon.class);
+				mss.setSelected(numberTaskYName);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m == chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	void sendParametersToCharter(){
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTaskX(numberTaskX);
+		chartWindowTask.setNumberTaskY(numberTaskY);
+		chartWindowTask.setItemsSource(taxonSourceTask);
+		chartWindowTask.setShowNames(showNames.getValue());
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxonSource ", taxonSourceTask); 
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		if (separateAxes){
+			temp.addLine("axesDifferent"); 
+			temp.addLine("setValuesX ", numberTaskX); 
+			temp.addLine("setValuesY ", numberTaskY); 
+		}
+		else {
+			temp.addLine("axesSame"); 
+			temp.addLine("setValues ", numberTaskX); 
+		}
+		temp.addLine("showNamesToggle " + showNames.toOffOnString()); 
+		temp.addLine("getCharter", chartWindowTask);
+		temp.addLine("setChartVisible");
+		temp.addLine("doCounts");
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block reference, number, or name]", commandName, "setTaxa")) {
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				return taxa;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether taxon names to be shown or not", "[on or off]", commandName, "showNamesToggle")) {
+			showNames.toggleValue(arguments);
+			if (chartWindowTask!=null){
+				chartWindowTask.setShowNames(showNames.getValue());
+				if (!MesquiteThread.isScripting() && cWindow!=null)
+					cWindow.recalcChart();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the two axes as using different calculators", null, commandName, "axesDifferent")){
+			separateAxes=true;
+			initMenus();
+		}
+		else if (checker.compare(this.getClass(), "Sets the two axes as using the same calculator", null, commandName, "axesSame")){
+			separateAxes=false;
+			initMenus();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for both axes", "[name of module]", commandName, "setValues")) {
+			NumberForTaxonIncr temp =  (NumberForTaxonIncr)replaceEmployee(NumberForTaxonIncr.class, arguments, "Values for axes", numberTaskX);
+			if (temp!=null) {
+				numberTaskX = temp;
+				numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+				numberTaskXName.setValue(numberTaskX.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskX;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for the X axis", "[name of module]", commandName, "setValuesX")) {
+			NumberForTaxon temp =  (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Values for X axis", numberTaskX);
+			if (temp!=null) {
+				numberTaskX = temp;
+				numberTaskX.setHiringCommand(ntxC);
+				numberTaskXName.setValue(numberTaskX.getName());
+				if (separateAxes)
+					numberTaskX.setMenuToUse(mX);
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskX;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for the X axis", "[name of module]", commandName, "setValuesY")) {
+			NumberForTaxon temp =  (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Values for Y axis", numberTaskY);
+			if (temp!=null) {
+				numberTaskY = temp;
+				numberTaskY.setHiringCommand(ntyC);
+				if (separateAxes)
+					numberTaskY.setMenuToUse(mY);
+				numberTaskYName.setValue(numberTaskY.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return numberTaskY;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Requests that chart calculations be redone", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+		}
+		else if (checker.compare(this.getClass(),  "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart as visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module supplying taxa", "[name of module]", commandName, "setTaxonSource")) {
+			TaxonSource temp =   (TaxonSource)replaceEmployee(TaxonSource.class, arguments, "Source of taxa for chart", taxonSourceTask);
+			if (temp!=null) {
+				taxonSourceTask = temp;
+				taxonSourceTask.setHiringCommand(tstC);
+				taxonSourceName.setValue(taxonSourceTask.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+				}
+				return taxonSourceTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		chartWindowTask.doCounts();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Taxa";
+	}
+
+}
+
+
diff --git a/Source/mesquite/charts/TaxonPairValuesChart/TaxonPairValuesChart.java b/Source/mesquite/charts/TaxonPairValuesChart/TaxonPairValuesChart.java
new file mode 100644
index 0000000..3bb25b3
--- /dev/null
+++ b/Source/mesquite/charts/TaxonPairValuesChart/TaxonPairValuesChart.java
@@ -0,0 +1,247 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.TaxonPairValuesChart;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TaxonPairValuesChart.  ===*/
+
+public class TaxonPairValuesChart extends FileAssistantCH  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Pairs Histogram";
+	}
+	public String getExplanation() {
+		return "Makes a chart showing some value for each of many pairs of taxa.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2Taxa.class, getName() + " needs a method to calculate values (such as distance, etc.) for each of a series of taxon pairs.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Taxon Pairs item under New Bar & Line Chart in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TaxonPairSource.class, getName() + " needs a source of taxon pairs.",
+		"You can select the taxon pairs to show either when the chart starts up, or using the Taxon Pair Source submenu of the Chart menu, if there is more than one source available.  (You may request the chart itself by selecting the Taxon Pairs item under New Bar & Line Chart in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+
+	/*.................................................................................................................*/
+	public NumberFor2Taxa numberTask;
+	private TaxonPairSource taxonPairSourceTask;
+	ItemsCharter chartWindowTask;
+	ChartWindow cWindow;
+	private Taxa taxa;
+	MesquiteString taxonPairSourceName;
+	MesquiteString numberTaskName;
+	MesquiteSubmenuSpec msNT;
+	int suspend = 0;
+	MesquiteCommand tstC, ntC;
+	static int numMade = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		taxonPairSourceName = new MesquiteString();
+		tstC = makeCommand("setTaxonPairSource",  this);
+		ntC = makeCommand("setCalculator",  this);
+		if (numModulesAvailable(TaxonPairSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Taxon Pair Source", tstC, TaxonPairSource.class);
+			mss.setSelected(taxonPairSourceName);
+		}
+		makeMenu("Chart");
+		msNT = addSubmenu(null, "Values", ntC, NumberFor2Taxa.class);
+		return checkInitialize();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m==chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	private boolean checkInitialize(){
+
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of taxon pair values?");
+		if (taxa ==null)
+			return false;
+		taxa.addListener(this);
+		numberTask=(NumberFor2Taxa)hireEmployee(NumberFor2Taxa.class, "Value to calculate for taxon pairs");
+		if (numberTask == null)
+			return false;
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString(numberTask.getName());
+		msNT.setSelected(numberTaskName);
+
+		taxonPairSourceTask= (TaxonPairSource)hireEmployee(TaxonPairSource.class, "Source of taxa (Taxon pair values chart)");
+		if (taxonPairSourceTask == null)
+			return false;
+		taxonPairSourceTask.setHiringCommand(tstC);
+		taxonPairSourceName.setValue(taxonPairSourceTask.getName());
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource(taxonPairSourceTask);
+		cWindow.setChartTitle("Taxon Pairs Chart " + (++numMade));
+		cWindow.resetTitle();
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+	}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//window.setTitle("Trees: " + taxonPairSourceTask.getSourceName());
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxonPairSource ", taxonPairSourceTask); 
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the chart visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			suspend++;
+		}
+		else if (checker.compare(this.getClass(),  "Resumes calculations", null, commandName, "resumeCalculations")){
+			suspend--;
+		}
+		else if (checker.compare(this.getClass(), "Requests that calculations are redone", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of taxon pairs", "[name of module]", commandName, "setTaxonPairSource")) {
+			TaxonPairSource temp =   (TaxonPairSource)replaceEmployee(TaxonPairSource.class, arguments, "Source of taxa for chart", taxonPairSourceTask);
+			if (temp!=null) {
+				taxonPairSourceTask = temp;
+				taxonPairSourceTask.setHiringCommand(tstC);
+				taxonPairSourceName.setValue(taxonPairSourceTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(taxonPairSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return taxonPairSourceTask;
+			}
+			//treeValues -- resize matrix according to number of trees, or if infinite, to chosen number
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the taxon pairs", "[name of module]", commandName, "setCalculator")) {
+			NumberFor2Taxa temp =  (NumberFor2Taxa)replaceEmployee(NumberFor2Taxa.class, arguments, "Value to calculate for taxon pairs", numberTask);
+			//((TreesChartWindow)window).setNumberTask(numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(taxonPairSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null) {
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == taxonPairSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+			else chartWindowTask.doCounts();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Taxon Pairs";
+	}
+
+}
+
+
diff --git a/Source/mesquite/charts/TaxonPairsScattergram/TaxonPairsScattergram.java b/Source/mesquite/charts/TaxonPairsScattergram/TaxonPairsScattergram.java
new file mode 100644
index 0000000..9686080
--- /dev/null
+++ b/Source/mesquite/charts/TaxonPairsScattergram/TaxonPairsScattergram.java
@@ -0,0 +1,351 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charts.TaxonPairsScattergram;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+/* TODO:
+ *   - how can one change which distance measure to use if distance from character matrix chosen?
+ *   - how should selection work?
+ */
+/* ======================================================================== */
+/**=== Class TaxonPairScattergram.  ===*/
+
+public class TaxonPairsScattergram extends FileAssistantCS  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2Taxa.class, getName() + " needs methods to calculate two values (such as distance, etc.) for a series of taxon pairs.",
+		"You can select this either when the chart starts up, or using the Values submenus of the Chart menu.  (You may request the chart itself by selecting the Taxon Pairs item under New Scattergram in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TaxonPairSource.class, getName() + " needs a source of taxon pairs.",
+		"You can select the taxon pairs to show either when the chart starts up, or using the Taxon Source submenu of the Chart menu, if there is more than one source available.  (You may request the chart itself by selecting the Taxon Pairs item under New Scattergram in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsBiplotter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+		/*.................................................................................................................*/
+	public NumberFor2Taxa numberTaskX, numberTaskY;
+	private TaxonPairSource taxonPairSourceTask;
+	ItemsBiplotter chartWindowTask;
+	public Taxa taxa;
+	boolean separateAxes=false;
+	MesquiteString numberTaskXName, numberTaskYName;
+	MesquiteString taxonPairSourceName;
+	ChartWindow cWindow;
+	MesquiteCommand tstC, ntC, ntxC, ntyC;
+	MesquiteMenuSpec mX;
+	MesquiteMenuSpec mY;
+	static int numMade = 0;
+	MesquiteBoolean showNames;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because no blocks of taxa are available.");
+		chartWindowTask = (ItemsBiplotter)hireEmployee(ItemsBiplotter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		
+		//Source of Taxa %%%%%%%%
+		taxonPairSourceTask= (TaxonPairSource)hireEmployee(TaxonPairSource.class, "Source of taxa (Taxa scattergram)");
+		if (taxonPairSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of taxa was obtained.");
+			//todo: doesn't use TaxonPairSource!!!!!!!
+		tstC = makeCommand("setTaxonPairSource",  this);
+		taxonPairSourceTask.setHiringCommand(tstC);
+		taxonPairSourceName = new MesquiteString();
+		taxonPairSourceName.setValue(taxonPairSourceTask.getName());
+		if (numModulesAvailable(TaxonPairSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Taxon Pair Source", tstC, TaxonPairSource.class);
+			mss.setSelected(taxonPairSourceName);
+		}
+		makeMenu("Scattergram");
+
+		
+
+		//values etc.  %%%%%%%%
+ 		ntC = makeCommand("setValues",  this);
+ 		ntxC = makeCommand("setValuesX",  this);
+ 		ntyC = makeCommand("setValuesY",  this);
+			
+ 		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		cWindow.setChartTitle("Taxon Pair Scattergram " + (++numMade));
+		cWindow.resetTitle();
+	 	taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a scattergram?");
+	 	if (taxa==null)
+	 		return sorry(getName() + " couldn't start because taxa block not obtained.");
+	 	taxa.addListener(this);
+ 		numberTaskXName = new MesquiteString();
+ 		numberTaskYName = new MesquiteString();
+		showNames = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Show Taxon Pair Names", MesquiteModule.makeCommand("showNamesToggle",  this), showNames);
+		/* ---------------------------*/
+		if (!MesquiteThread.isScripting()){
+			String expl = "(For instance, the X and Y axes might show the same calculations but for different characters, or they may show two entirely different calculations.)";
+			separateAxes = (numModulesAvailable(NumberFor2TaxaIncr.class)==0) || !AlertDialog.query(containerOfModule(), "Axes", "Choose same or different calculations for the two axes? " + expl, "Same", "Different");
+			initMenus();
+			if (!separateAxes){
+				numberTaskX = (NumberFor2TaxaIncr)hireEmployee(NumberFor2TaxaIncr.class, "Values for axes");
+				if (numberTaskX == null)
+					return false;
+		 		numberTaskXName.setValue(numberTaskX.getName());
+				numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+			}
+			else {
+				numberTaskX = (NumberFor2Taxa)hireEmployee(NumberFor2Taxa.class, "Values for X axis");
+				if (numberTaskX == null)
+					return false;
+				numberTaskY = (NumberFor2Taxa)hireEmployee(NumberFor2Taxa.class, "Values for Y axis");
+				if (numberTaskY == null)
+					return false;
+				numberTaskX.setMenuToUse(mX);
+				numberTaskY.setMenuToUse(mY);
+				numberTaskX.setHiringCommand(ntxC);
+				numberTaskY.setHiringCommand(ntyC);
+		 		numberTaskXName.setValue(numberTaskX.getName());
+		 		numberTaskYName.setValue(numberTaskY.getName());
+			}
+			sendParametersToCharter();
+			if (!MesquiteThread.isScripting()){
+				chartWindowTask.doCounts();
+				cWindow.setChartVisible();
+				cWindow.setVisible(true);
+			}
+		}
+ 		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		/* ---------------------------*/
+		return true;
+	}
+	private void initMenus(){
+			if (!separateAxes){
+				if (numModulesAvailable(NumberFor2TaxaIncr.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberFor2TaxaIncr.class);
+			 		if (numberTaskX!=null)
+			 			numberTaskXName.setValue(numberTaskX.getName());
+		 			mss.setSelected(numberTaskXName);
+				}
+			}
+			else {
+				mX = addAuxiliaryMenu("X.Axis");
+				mY = addAuxiliaryMenu("Y.Axis");
+				if (numModulesAvailable(NumberFor2Taxa.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(mX, "Values on X", ntxC, NumberFor2Taxa.class);
+			 		if (numberTaskX!=null)
+			 			numberTaskXName.setValue(numberTaskX.getName());
+			 		mss.setSelected(numberTaskXName);
+					mss = addSubmenu(mY, "Values on Y", ntyC, NumberFor2Taxa.class);
+			 		if (numberTaskY!=null)
+			 			numberTaskYName.setValue(numberTaskY.getName());
+		 			mss.setSelected(numberTaskYName);
+				}
+			}
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+    	/*.................................................................................................................*/
+    	public boolean isPrerelease(){
+    		return true;
+    	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (taxa!=null)
+				taxa.removeListener(this);
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	void sendParametersToCharter(){
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTaskX(numberTaskX);
+		chartWindowTask.setNumberTaskY(numberTaskY);
+		chartWindowTask.setItemsSource(taxonPairSourceTask);
+		chartWindowTask.setShowNames(showNames.getValue());
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setTaxonPairSource ", taxonPairSourceTask); 
+ 	 	temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+   	 	if (separateAxes){
+   	 		temp.addLine("axesDifferent"); 
+   	 		temp.addLine("setValuesX ", numberTaskX); 
+   	 		temp.addLine("setValuesY ", numberTaskY); 
+   	 	}
+   	 	else {
+   	 		temp.addLine("axesSame"); 
+   	 		temp.addLine("setValues ", numberTaskX); 
+   	 	}
+  	 	temp.addLine("showNamesToggle " + showNames.toOffOnString()); 
+		temp.addLine("getCharter", chartWindowTask);
+		temp.addLine("setChartVisible");
+    	 	temp.addLine("doCounts");
+    	 	temp.addLine("showWindow");
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    		 if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block reference, number, or name]", commandName, "setTaxa")) {
+    			 Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+    			 if (t!=null){
+    				 if (taxa!=null)
+    					 taxa.removeListener(this);
+    				 taxa = t;
+    				 if (taxa!=null)
+    					 taxa.addListener(this);
+    				 return taxa;
+    			 }
+    		 }
+    		 else if (checker.compare(this.getClass(), "Sets whether taxon pair names to be shown or not", "[on or off]", commandName, "showNamesToggle")) {
+    			 showNames.toggleValue(arguments);
+    			 if (chartWindowTask!=null){
+    				 chartWindowTask.setShowNames(showNames.getValue());
+    				 if (!MesquiteThread.isScripting() && cWindow!=null)
+    					 cWindow.recalcChart();
+    			 }
+    			 
+    		 }
+    		 else if (checker.compare(this.getClass(), "Sets the two axes as using different calculators", null, commandName, "axesDifferent")){
+    			 separateAxes=true;
+    			 initMenus();
+    		 }
+    		 else if (checker.compare(this.getClass(), "Sets the two axes as using the same calculator", null, commandName, "axesSame")){
+    			 separateAxes=false;
+    			 initMenus();
+    		 }
+    		 else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for both axes", "[name of module]", commandName, "setValues")) {
+    			 NumberFor2TaxaIncr temp =  (NumberFor2TaxaIncr)replaceEmployee(NumberFor2TaxaIncr.class, arguments, "Values for axes", numberTaskX);
+    			 if (temp!=null) {
+    				 numberTaskX = temp;
+    				 numberTaskX.setHiringCommand(ntC);
+    				 numberTaskY = numberTaskX;
+    				 numberTaskXName.setValue(numberTaskX.getName());
+    				 if (cWindow!=null){
+    					 sendParametersToCharter();
+    					 if (!MesquiteThread.isScripting())
+    						 chartWindowTask.doCounts();
+    				 }
+    				 return numberTaskX;
+    			 }
+    		 }
+   	 	else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for the X axis", "[name of module]", commandName, "setValuesX")) {
+    	 		NumberFor2Taxa temp =  (NumberFor2Taxa)replaceEmployee(NumberFor2Taxa.class, arguments, "Values for X axis", numberTaskX);
+ 			if (temp!=null) {
+ 				numberTaskX = temp;
+				numberTaskX.setHiringCommand(ntxC);
+		 		numberTaskXName.setValue(numberTaskX.getName());
+				if (separateAxes)
+					numberTaskX.setMenuToUse(mX);
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+ 				}
+	 			return numberTaskX;
+	 		}
+    	 	}
+   	 	else if (checker.compare(this.getClass(), "Sets the module to calculate the number for taxa for the X axis", "[name of module]", commandName, "setValuesY")) {
+    	 		NumberFor2Taxa temp =  (NumberFor2Taxa)replaceEmployee(NumberFor2Taxa.class, arguments, "Values for Y axis", numberTaskY);
+ 			if (temp!=null) {
+ 				numberTaskY = temp;
+				numberTaskY.setHiringCommand(ntyC);
+				if (separateAxes)
+					numberTaskY.setMenuToUse(mY);
+		 		numberTaskYName.setValue(numberTaskY.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+ 				}
+	 			return numberTaskY;
+	 		}
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Requests that chart calculations be redone", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+     	 	}
+    	 	else if (checker.compare(this.getClass(),  "Returns the chart drawing module", null, commandName, "getCharter")) {
+       			return chartWindowTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the chart as visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module supplying taxa", "[name of module]", commandName, "setTaxonPairSource")) {
+    	 		TaxonPairSource temp =   (TaxonPairSource)replaceEmployee(TaxonPairSource.class, arguments, "Source of taxa for chart", taxonPairSourceTask);
+ 			if (temp!=null) {
+ 				taxonPairSourceTask = temp;
+				taxonPairSourceTask.setHiringCommand(tstC);
+				taxonPairSourceName.setValue(taxonPairSourceTask.getName());
+				if (cWindow!=null){
+					sendParametersToCharter();
+					if (!MesquiteThread.isScripting())
+						chartWindowTask.doCounts();
+ 				}
+	 			return taxonPairSourceTask;
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+    	 
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+			chartWindowTask.doCounts();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Taxon Pairs Scattergram";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Taxon Pairs";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Makes a chart comparing two values for each of many pairs of taxa.";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/charts/TaxonValuesChart/TaxonValuesChart.java b/Source/mesquite/charts/TaxonValuesChart/TaxonValuesChart.java
new file mode 100644
index 0000000..278c365
--- /dev/null
+++ b/Source/mesquite/charts/TaxonValuesChart/TaxonValuesChart.java
@@ -0,0 +1,245 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.TaxonValuesChart;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TaxonValuesChart.  ===*/
+
+public class TaxonValuesChart extends FileAssistantCH  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Bar & Line Chart for Taxa";
+	}
+	public String getExplanation() {
+		return "Makes a chart displaying values (such as proportion of gaps in a sequence, etc.) for each of a series of taxa.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTaxon.class, getName() + " needs a method to calculate the values for the taxa.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Taxa item under New Bar & Line Chart in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TaxonSource.class, getName() + " needs a source of taxa.",
+		"You can select the taxa to show either when the chart starts up, or using the Taxon Source submenu of the Chart menu, if there is more than one source available.  (You may request the chart itself by selecting the Taxa item under New Bar & Line Chart in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForTaxon numberTask;
+	private TaxonSource taxonSourceTask;
+	ItemsCharter chartWindowTask;
+	ChartWindow cWindow;
+	private Taxa taxa;
+	MesquiteString taxonSourceName;
+	MesquiteString numberTaskName;
+	MesquiteSubmenuSpec msNT;
+	int suspend = 0;
+	MesquiteCommand tstC, ntC;
+	static int numMade = 0;
+	long tbID = -1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		taxonSourceName = new MesquiteString();
+		tstC = makeCommand("setTaxonSource",  this);
+		ntC = makeCommand("setCalculator",  this);
+		if (numModulesAvailable(TaxonSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Taxon Source", tstC, TaxonSource.class);
+			mss.setSelected(taxonSourceName);
+		}
+		//can leave a hint in terms of an id of a treeblock to use
+		String whichBlock = MesquiteThread.retrieveAndDeleteHint(this);
+		long wB = MesquiteLong.fromString(whichBlock);
+		if (MesquiteLong.isCombinable(wB)){
+			tbID = wB;
+		}
+		makeMenu("Chart");
+		msNT = addSubmenu(null, "Values", ntC, NumberForTaxon.class);
+		return checkInitialize();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	private boolean checkInitialize(){
+		if (tbID>=0){
+			taxa = getProject().getTaxaByID(tbID);
+			tbID = -1;
+		}
+		if (taxa == null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of taxon values?");
+		if (taxa ==null)
+			return false;
+		taxa.addListener(this);
+		numberTask=(NumberForTaxon)hireEmployee(NumberForTaxon.class, "Value to calculate for taxa");
+		if (numberTask == null)
+			return false;
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString(numberTask.getName());
+		msNT.setSelected(numberTaskName);
+
+		taxonSourceTask= (TaxonSource)hireEmployee(TaxonSource.class, "Source of taxa (Taxon values chart)");
+		if (taxonSourceTask == null)
+			return false;
+		taxonSourceTask.setHiringCommand(tstC);
+		taxonSourceName.setValue(taxonSourceTask.getName());
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource(taxonSourceTask);
+		cWindow.setChartTitle("Taxa Chart " + (++numMade));
+		cWindow.resetTitle();
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//window.setTitle("Trees: " + taxonSourceTask.getSourceName());
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxonSource ", taxonSourceTask); 
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the chart visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			suspend++;
+		}
+		else if (checker.compare(this.getClass(),  "Resumes calculations", null, commandName, "resumeCalculations")){
+			suspend--;
+		}
+		else if (checker.compare(this.getClass(), "Requests that calculations are redone", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of taxa", "[name of module]", commandName, "setTaxonSource")) {
+			TaxonSource temp =   (TaxonSource)replaceEmployee(TaxonSource.class, arguments, "Source of taxa for chart", taxonSourceTask);
+			if (temp!=null) {
+				taxonSourceTask = temp;
+				taxonSourceTask.setHiringCommand(tstC);
+				taxonSourceName.setValue(taxonSourceTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(taxonSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return taxonSourceTask;
+			}
+			//treeValues -- resize matrix according to number of trees, or if infinite, to chosen number
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the taxa", "[name of module]", commandName, "setCalculator")) {
+			NumberForTaxon temp =  (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Value to calculate for taxa", numberTask);
+			//((TreesChartWindow)window).setNumberTask(numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(taxonSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null) {
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == taxonSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+			else chartWindowTask.doCounts();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Taxa";
+	}
+
+}
+
+
diff --git a/Source/mesquite/charts/TreeBlockValues/TreeBlockValues.java b/Source/mesquite/charts/TreeBlockValues/TreeBlockValues.java
new file mode 100644
index 0000000..f8050f9
--- /dev/null
+++ b/Source/mesquite/charts/TreeBlockValues/TreeBlockValues.java
@@ -0,0 +1,260 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.TreeBlockValues;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TreeBlocksChart.  ===*/
+
+public class TreeBlockValues extends FileAssistantCH {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Tree Block Values";
+	}
+	public String getExplanation() {
+		return "Makes a chart showing some value for each of many tree blocks.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTreeBlock.class, getName() + " needs a method to calculate values (such as average imbalance statistics, correlations,etc.) for a series of tree blocks.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Tree Blocks item under New Bar & Line Chart in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TreeBlockSource.class, getName() + " needs a source of tree blocks.",
+		"You can select the tree blocks to show either when the chart starts up, or using the Tree Block Source submenu of the Chart menu.  (You may request the chart itself by selecting the Tree Blocks item under New Bar & Line Chart in the Analysis menu)");
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForTreeBlock numberTask;
+	private TreeBlockSource treeBlockSourceTask;
+	private Taxa taxa;
+	MesquiteString treeBlockSourceName;
+	MesquiteString numberTaskName;
+	MesquiteSubmenuSpec msNT;
+	ChartWindow cWindow;
+	ItemsCharter chartWindowTask;
+	MesquiteBoolean live = new MesquiteBoolean(true);
+	MesquiteCommand tbstC, ntC;
+	static int numMade = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+
+		makeMenu("Chart");
+
+
+		//Tree block source %%%%%%%%
+		treeBlockSourceName = new MesquiteString();
+		tbstC =makeCommand("setTreeBlockSource",  this);
+		if (numModulesAvailable(TreeBlockSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Block Source", tbstC, TreeBlockSource.class);
+			mss.setSelected(treeBlockSourceName);
+		}
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of values for tree blocks?");
+		if (taxa ==null)
+			return sorry(getName() + " couldn't start because no taxa block was obtained.");
+		taxa.addListener(this);
+
+		treeBlockSourceTask= (TreeBlockSource)hireEmployee(TreeBlockSource.class, "Source of tree blocks");
+		if (treeBlockSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of tree blocks was obtained.");
+		treeBlockSourceTask.setHiringCommand(tbstC);
+		treeBlockSourceName.setValue(treeBlockSourceTask.getName());
+		treeBlockSourceTask.setPreferredTaxa(taxa);
+
+
+		//values etc.  %%%%%%%%
+		ntC =makeCommand("setCalculator",  this);
+		msNT = addSubmenu(null, "Values", ntC, NumberForTreeBlock.class);
+
+		numberTask=(NumberForTreeBlock)hireEmployee(NumberForTreeBlock.class, "Value to calculate for tree blocks");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module was obtained.");
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString(numberTask.getName());
+		msNT.setSelected(numberTaskName);
+
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource(treeBlockSourceTask);
+		cWindow.setChartTitle("Tree Blocks Chart " + (++numMade));
+		cWindow.resetTitle();
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//window.setTitle("Trees: " + treeSourceTask.getSourceName());
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspendCalculations"); 
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		temp.addLine("setTreeBlockSource ", treeBlockSourceTask); 
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("resumeCalculations"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets block of taxa to use", "[block reference, number, or name]", commandName, "setTaxa")){
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				if (taxa!=null && treeBlockSourceTask!=null)
+					treeBlockSourceTask.setPreferredTaxa(taxa);
+				return taxa;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Requests that chart values be recalculated", null, commandName, "doCounts")){
+			if (cWindow!=null)
+				chartWindowTask.doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			chartWindowTask.incrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resumeCalculations")){
+			chartWindowTask.decrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the chart is \"live\" (that is, whether its calculatons are updated automatically when parameters or data change)", "[on or off]", commandName, "setLive")) {
+			live.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+
+		}
+		else if (checker.compare(getClass(), "Sets the module supplying tree blocks", "[name of module]", commandName, "setTreeBlockSource")) {
+			TreeBlockSource temp =   (TreeBlockSource)replaceEmployee(TreeBlockSource.class, arguments, "Source of trees for chart", treeBlockSourceTask);
+			if (temp!=null) {
+				treeBlockSourceTask = temp;
+				treeBlockSourceTask.setHiringCommand(tbstC);
+				treeBlockSourceName.setValue(treeBlockSourceTask.getName());
+				if (taxa!=null)
+					treeBlockSourceTask.setPreferredTaxa(taxa);
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(treeBlockSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return treeBlockSourceTask;
+			}
+			//treeValues -- resize matrix according to number of trees, or if infinite, to chosen number
+		}
+		else if (checker.compare(getClass(), "Sets the module calculating numbers for the tree blocks", "[name of module]", commandName, "setCalculator")) {
+			NumberForTreeBlock temp =  (NumberForTreeBlock)replaceEmployee(NumberForTreeBlock.class, arguments, "Value to calculate for trees", numberTask);
+			//((TreeBlockValuesWindow)window).setNumberTask(numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(treeBlockSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null && !MesquiteThread.isScripting() && live.getValue())
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == treeBlockSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+			else chartWindowTask.doCounts(); //perhaps put intemschart in charge liveness and pass here whether through ePC
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Tree Blocks";
+	}
+
+}
+
+
diff --git a/Source/mesquite/charts/TreeValuesChart/TreeValuesChart.java b/Source/mesquite/charts/TreeValuesChart/TreeValuesChart.java
new file mode 100644
index 0000000..86834dd
--- /dev/null
+++ b/Source/mesquite/charts/TreeValuesChart/TreeValuesChart.java
@@ -0,0 +1,280 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.charts.TreeValuesChart;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TreeValuesChart.  ===*/
+
+public class TreeValuesChart extends FileAssistantCH  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Bar & Line Chart for Trees";
+	}
+	public String getExplanation() {
+		return "Makes a chart displaying values (such as likelihoods, parsimony scores, imbalance statistics, correlations,etc.) for a series of trees.";
+	}
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " needs a method to calculate the values for the trees.",
+		"You can select this either when the chart starts up, or using the Values submenu of the Chart menu.  (You may request the chart itself by selecting the Trees item under New Bar & Line Chart in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + " needs a source of trees.",
+		"You can select the trees to show either when the chart starts up, or using the Tree Source submenu of the Chart menu.  (You may request the chart itself by selecting the Trees item under New Bar & Line Chart in the Analysis menu)");
+		e2.setPriority(1);
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsCharter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForTree numberTask;
+	private TreeSource treeSourceTask;
+	ItemsCharter chartWindowTask;
+	ChartWindow cWindow;
+	private Taxa taxa;
+	MesquiteString treeSourceName;
+	MesquiteString numberTaskName;
+	MesquiteSubmenuSpec msNT;
+	MesquiteCommand tstC, ntC;
+	static int numMade = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module obtained.");
+		makeMenu("Chart");
+		treeSourceName = new MesquiteString();
+		tstC = makeCommand("setTreeSource",  this);
+		ntC =makeCommand("setCalculator",  this);
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+
+
+		msNT = addSubmenu(null, "Values", ntC, NumberForTree.class);
+		//is there a hint as to taxa
+		String whichTaxa = MesquiteThread.retrieveAndDeleteHint(this);
+		long wB = MesquiteLong.fromString(whichTaxa);
+		if (MesquiteLong.isCombinable(wB)){
+			taxa = getProject().getTaxaByID(wB);
+		}
+
+		if (taxa == null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a chart of values for trees?");
+		if (taxa ==null)
+			return sorry(getName() + " couldn't start because no block of taxa available.");
+		taxa.addListener(this);
+
+		//Tree source %%%%%%%%
+		if (arguments == null){
+			arguments = MesquiteThread.retrieveAndDeleteHint(this);
+		}
+		if (arguments != null)
+			treeSourceTask = (TreeSource)hireNamedEmployee(TreeSource.class, arguments);
+		if (treeSourceTask == null)
+		treeSourceTask= (TreeSource)hireEmployee(TreeSource.class, "Source of trees (Trees chart)");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		treeSourceName.setValue(treeSourceTask.getName());
+		treeSourceTask.setPreferredTaxa(taxa);
+		treeSourceTask.setHiringCommand(tstC);
+
+
+		//values etc.  %%%%%%%%
+		if (MesquiteThread.isScripting())
+			numberTask=(NumberForTree)hireNamedEmployee(NumberForTree.class, "#NumberOfTaxa");
+		if (numberTask == null)
+			numberTask=(NumberForTree)hireEmployee(NumberForTree.class, "Value to calculate for trees");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString(numberTask.getName());
+		msNT.setSelected(numberTaskName);
+
+		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTask(numberTask);
+		chartWindowTask.setItemsSource(treeSourceTask);
+		cWindow.setChartTitle("Trees Chart " + (++numMade));
+		cWindow.resetTitle();
+		if (!MesquiteThread.isScripting()){
+			cWindow.setChartVisible();
+			cWindow.setVisible(true);
+			chartWindowTask.doCounts();
+			cWindow.toFront();
+		}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//getModuleWindow().setTitle("Trees: " + treeSourceTask.getSourceName());
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m== chartWindowTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspendCalculations"); 
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		temp.addLine("setTreeSource ", treeSourceTask); 
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("resumeCalculations"); 
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block reference, number, or name]", commandName, "setTaxa")){
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				if (taxa!=null && treeSourceTask!=null)
+					treeSourceTask.setPreferredTaxa(taxa);
+				return taxa;
+			}
+		} 
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+			chartWindowTask.incrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resumeCalculations")){
+			chartWindowTask.decrementSuspension();
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+
+		}
+		else if (checker.compare(this.getClass(), "Requests that chart calculations be redone", null, commandName, "doCounts")){
+			if (cWindow!=null) {
+				chartWindowTask.doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module supplying trees", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp =   (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees for chart", treeSourceTask);
+			if (temp!=null) {
+				treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				if (taxa!=null)
+					treeSourceTask.setPreferredTaxa(taxa);
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(treeSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return treeSourceTask;
+			}
+			//treeValues -- resize matrix according to number of trees, or if infinite, to chosen number
+		}
+		else if (checker.compare(this.getClass(), "Sets the module calculating values for the trees", "[name of module]", commandName, "setCalculator")) {
+			NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Value to calculate for trees", numberTask);
+			//((TreesChartWindow)getModuleWindow()).setNumberTask(numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (cWindow!=null){
+					chartWindowTask.setTaxa(taxa);
+					chartWindowTask.setNumberTask(numberTask);
+					chartWindowTask.setItemsSource(treeSourceTask);
+					if (!MesquiteThread.isScripting()){
+						chartWindowTask.doCounts();
+					}
+				}
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (cWindow!=null && !MesquiteThread.isScripting()) {
+			if (Notification.getCode(notification) == MesquiteListener.ITEMS_ADDED && source == treeSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2) {
+					// we now have just some trees added.  The first tree added as notifParam[0]+1, and notifParam[1] trees are added.
+
+
+					chartWindowTask.doCounts( notifParam[0], MesquiteInteger.add(notifParam[0], notifParam[1]), false);
+				}
+				else
+					chartWindowTask.doCounts();
+			}
+			else if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED) {
+				chartWindowTask.doCounts();
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Trees";
+	}
+}
+
+
diff --git a/Source/mesquite/charts/TreesScattergram/TreesScattergram.java b/Source/mesquite/charts/TreesScattergram/TreesScattergram.java
new file mode 100644
index 0000000..77cc176
--- /dev/null
+++ b/Source/mesquite/charts/TreesScattergram/TreesScattergram.java
@@ -0,0 +1,342 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charts.TreesScattergram;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**=== Class TreesScattergram.  ===*/
+
+public class TreesScattergram extends FileAssistantCS  {
+	 public String getName() {
+	return "Trees Scattergram";
+	 }
+	 public String getNameForMenuItem() {
+	return "Trees";
+	 }
+	 public String getExplanation() {
+	return "Makes a scatterplot displaying two values (such as likelihoods, parsimony scores, imbalance statistics, correlations,etc.) for a series of trees.";
+	 }
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " needs methods to calculate the two values for the trees.",
+		"You can select this either when the chart starts up, or using the Values submenus of the Chart menu.  (You may request the chart itself by selecting the Trees item under New Scattergram in the Analysis menu)");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + " needs a source of trees.",
+		"You can select the trees to show either when the chart starts up, or using the Tree Source submenu of the Chart menu.  (You may request the chart itself by selecting the Trees item under New Scattergram in the Analysis menu)");
+		e2.setPriority(1);
+		EmployeeNeed e3 = registerEmployeeNeed(ItemsBiplotter.class, getName() + " needs an assistant to draw charts.",
+		"The chart drawing module is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public NumberForTree numberTaskX, numberTaskY;
+	private TreeSource treeSourceTask;
+	ItemsBiplotter chartWindowTask;
+	public Taxa taxa;
+	boolean separateAxes=false;
+	MesquiteString numberTaskXName, numberTaskYName;
+	MesquiteString treeSourceName;
+	ChartWindow cWindow;
+	MesquiteCommand ntxC, ntyC, ntC, tstC;
+	MesquiteMenuSpec mX;
+	MesquiteMenuSpec mY;
+	static int numMade = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because no blocks of taxa available.");
+		chartWindowTask = (ItemsBiplotter)hireEmployee(ItemsBiplotter.class, null);
+		if (chartWindowTask == null)
+			return sorry(getName() + " couldn't start because no charting module obtained.");
+		makeMenu("Scattergram");
+		
+		//Source of trees %%%%%%%%
+		treeSourceTask= (TreeSource)hireEmployee(TreeSource.class, "Source of trees (Trees scattergram)");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		tstC =makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString();
+		treeSourceName.setValue(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+		
+		
+		//values etc.  %%%%%%%%
+		ntC =makeCommand("setValues",  this);
+		ntxC =makeCommand("setValuesX",  this);
+		ntyC =makeCommand("setValuesY",  this);
+
+ 			
+ 		cWindow = chartWindowTask.makeChartWindow(this);
+		setModuleWindow( cWindow);
+		cWindow.setChartTitle("Trees Scattergram " + (++numMade));
+		cWindow.resetTitle();
+	 	taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a trees scattergram?"); // as default;
+	 	if (taxa==null)
+	 		return sorry(getName() + " couldn't start because block of taxa not obtained.");
+	 	taxa.addListener(this);
+ 		numberTaskXName = new MesquiteString();
+ 		numberTaskYName = new MesquiteString();
+		
+		/* ---------------------------*/
+		if (!MesquiteThread.isScripting()){
+			String expl = "(For instance, the X and Y axes might show the same calculations but for different characters, or they may show two entirely different calculations.)";
+			separateAxes = (numModulesAvailable(NumberForTreeIncr.class)==0) || !AlertDialog.query(containerOfModule(), "Axes", "Choose same or different calculations for the two axes? " + expl, "Same", "Different");
+			initMenus();
+			if (!separateAxes){
+				numberTaskX = (NumberForTreeIncr)hireEmployee(NumberForTreeIncr.class, "Values for axes");
+				if (numberTaskX == null)
+					return sorry(getName() + " couldn't start because no calculating module obtained.");
+		 		numberTaskXName.setValue(numberTaskX.getName());
+		 		numberTaskX.setHiringCommand(ntC);
+				numberTaskY = numberTaskX;
+			}
+			else {
+				numberTaskX = (NumberForTree)hireEmployee(NumberForTree.class, "Values for X axis");
+				if (numberTaskX == null)
+					return sorry(getName() + " couldn't start because no calculating module obtained for X axis.");
+				numberTaskY = (NumberForTree)hireEmployee(NumberForTree.class, "Values for Y axis");
+				if (numberTaskY == null)
+					return sorry(getName() + " couldn't start because no calculating module obtained for Y axis");
+		 		numberTaskXName.setValue(numberTaskX.getName());
+		 		numberTaskYName.setValue(numberTaskY.getName());
+		 		numberTaskX.setHiringCommand(ntxC);
+		 		numberTaskY.setHiringCommand(ntyC);
+				numberTaskX.setMenuToUse(mX);
+				numberTaskY.setMenuToUse(mY);
+			}
+			sendParametersToCharter();
+			if (!MesquiteThread.isScripting()){
+				chartWindowTask.doCounts();
+				cWindow.setChartVisible();
+				cWindow.setVisible(true);
+			}
+		}
+ 		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		/* ---------------------------*/
+		
+		return true;
+	}
+	private void initMenus(){
+			if (!separateAxes){
+				if (numModulesAvailable(NumberForTreeIncr.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberForTreeIncr.class);
+		 			mss.setSelected(numberTaskXName);
+				}
+			}
+			else {
+				mX = addAuxiliaryMenu("X.Axis");
+				mY = addAuxiliaryMenu("Y.Axis");
+				if (numModulesAvailable(NumberForTree.class)>1) {
+					MesquiteSubmenuSpec mss = addSubmenu(null, "Values on X", ntxC, NumberForTree.class);
+		 			mss.setSelected(numberTaskXName);
+					mss = addSubmenu(null, "Values on Y", ntyC, NumberForTree.class);
+		 			mss.setSelected(numberTaskYName);
+				}
+			}
+	}
+ 	public void employeeQuit(MesquiteModule m){
+ 		if (m== chartWindowTask)
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (taxa!=null)
+				taxa.removeListener(this);
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	void sendParametersToCharter(){
+		chartWindowTask.setTaxa(taxa);
+		chartWindowTask.setNumberTaskX(numberTaskX);
+		chartWindowTask.setNumberTaskY(numberTaskY);
+		chartWindowTask.setItemsSource(treeSourceTask);
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setTreeSource ", treeSourceTask); 
+ 	 	temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+   	 	if (separateAxes){
+   	 		temp.addLine("axesDifferent"); 
+   	 		temp.addLine("setValuesX ", numberTaskX); 
+   	 		temp.addLine("setValuesY ", numberTaskY); 
+   	 	}
+   	 	else {
+   	 		temp.addLine("axesSame"); 
+   	 		temp.addLine("setValues ", numberTaskX); 
+   	 	}
+		temp.addLine("getCharter", chartWindowTask);
+		temp.addLine("setChartVisible");
+    	 	temp.addLine("doCounts");
+    	 	temp.addLine("showWindow");
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+  	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+  		 if (checker.compare(this.getClass(), "Sets the taxa block to use", "[block reference, number, or name]", commandName, "setTaxa")) {
+  			 Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+  			 if (t!=null){
+  				 if (taxa!=null)
+  					 taxa.removeListener(this);
+  				 taxa = t;
+  				 if (taxa!=null)
+  					 taxa.addListener(this);
+  				 parametersChanged();
+  				 resetContainingMenuBar();
+  				 return taxa;
+  			 }
+  		 }
+  		 /*else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspendCalculations")){
+  		  chartWindowTask.incrementSuspension();
+  		  }
+  		  else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resumeCalculations")){
+  		  chartWindowTask.decrementSuspension();
+  		  }
+  		  */
+  		 else if (checker.compare(this.getClass(), "Sets the two axes as using different calculators", null, commandName, "axesDifferent")){
+  			 separateAxes=true;
+  			 initMenus();
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the two axes as using the same calculator", null, commandName, "axesSame")){
+  			 separateAxes=false;
+  			 initMenus();
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the module to calculate the number for trees for both axes", "[name of module]", commandName, "setValues")) {
+  			 NumberForTreeIncr temp =  (NumberForTreeIncr)replaceEmployee(NumberForTreeIncr.class, arguments, "Values for axes", numberTaskX);
+  			 if (temp!=null) {
+  				 numberTaskX = temp;
+  				 numberTaskX.setHiringCommand(ntC);
+  				 numberTaskY = numberTaskX;
+  				 numberTaskXName.setValue(numberTaskX.getName());
+  				 if (cWindow!=null){
+  					 if (!MesquiteThread.isScripting()) {
+  						 sendParametersToCharter();
+  						 chartWindowTask.doCounts();
+  					 }
+  				 }
+  				 return numberTaskX;
+  			 }
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the module to calculate the number for trees for the X axis", "[name of module]", commandName, "setValuesX")) {
+  			 NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Values for X axis", numberTaskX);
+  			 if (temp!=null) {
+  				 numberTaskX = temp;
+  				 numberTaskX.setHiringCommand(ntxC);
+  				 numberTaskXName.setValue(numberTaskX.getName());
+  				 if (separateAxes)
+  					 numberTaskX.setMenuToUse(mX);
+  				 if (cWindow!=null){
+  					 if (!MesquiteThread.isScripting()) {
+  						 sendParametersToCharter();
+  						 chartWindowTask.doCounts();
+  					 }
+  				 }
+  				 return numberTaskX;
+  			 }
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the module to calculate the number for trees for the Y axis", "[name of module]", commandName, "setValuesY")) {
+  			 NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Values for Y axis", numberTaskY);
+  			 if (temp!=null) {
+  				 numberTaskY = temp;
+  				 numberTaskY.setHiringCommand(ntyC);
+  				 numberTaskYName.setValue(numberTaskY.getName());
+  				 if (separateAxes)
+  					 numberTaskY.setMenuToUse(mY);
+  				 if (cWindow!=null){
+  					 if (!MesquiteThread.isScripting()) {
+  						 sendParametersToCharter();
+  						 chartWindowTask.doCounts();
+  					 }
+  				 }
+  				 return numberTaskY;
+  			 }
+  		 }
+  		 else if (checker.compare(this.getClass(),  "Requests that chart calculations be redone", null, commandName, "doCounts")){
+  			 sendParametersToCharter();
+  			 if (cWindow!=null) {
+  				 chartWindowTask.doCounts();
+  			 }
+  		 }
+  		 else if (checker.compare(this.getClass(), "Returns the chart drawing module", null, commandName, "getCharter")) {
+  			 return chartWindowTask;
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the chart as visible", null, commandName, "setChartVisible")) {
+  			 if (cWindow!=null)
+  				 cWindow.setChartVisible();
+  		 }
+  		 else if (checker.compare(this.getClass(), "Sets the module supplying trees", "[name of module]", commandName, "setTreeSource")) {
+  			 TreeSource temp =   (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees for chart", treeSourceTask);
+  			 if (temp!=null) {
+  				 treeSourceTask = temp;
+  				 treeSourceTask.setHiringCommand(tstC);
+  				 treeSourceName.setValue(treeSourceTask.getName());
+  				 if (cWindow!=null){
+  					 if (!MesquiteThread.isScripting()) {
+  						 sendParametersToCharter();
+  						 chartWindowTask.doCounts();
+  					 }
+  				 }
+  				 return treeSourceTask;
+  			 }
+  		 }
+  		 else
+  			 return  super.doCommand(commandName, arguments, checker);
+  		 return null;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!MesquiteThread.isScripting()) {
+			sendParametersToCharter();
+			if (Notification.getCode(notification) == MesquiteListener.PARTS_ADDED && source == treeSourceTask) {
+				int[] notifParam = notification.getParameters();
+				if (notifParam!=null && notifParam.length==2)
+					// we now have just some trees added.  The first tree added as notifParam[0]+1, and notifParam[1] trees are added.
+					chartWindowTask.doCounts( notifParam[0]+1, notifParam[0]+notifParam[1], false);
+				else
+					chartWindowTask.doCounts();
+			}
+ 			else if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+				chartWindowTask.doCounts();
+		}
+	}
+   	 
+}
+
+
diff --git a/Source/mesquite/charts/aChartsIntro/aChartsIntro.java b/Source/mesquite/charts/aChartsIntro/aChartsIntro.java
new file mode 100644
index 0000000..c5c7331
--- /dev/null
+++ b/Source/mesquite/charts/aChartsIntro/aChartsIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.charts.aChartsIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aChartsIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aChartsIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic charting functions.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Charting Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Charting Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/charts/explanation.txt b/Source/mesquite/charts/explanation.txt
new file mode 100644
index 0000000..c4cd5f4
--- /dev/null
+++ b/Source/mesquite/charts/explanation.txt
@@ -0,0 +1,2 @@
+Charting Package
+One of the core Mesquite packages.  Provides basic charting facilities (histograms, scatter plots) and some particular charts (histograms and scattergrams for trees, characters, taxa and other objects).
diff --git a/Source/mesquite/coalesce/AverageTreeDepth/AverageTreeDepth.java b/Source/mesquite/coalesce/AverageTreeDepth/AverageTreeDepth.java
new file mode 100644
index 0000000..ce4a89c
--- /dev/null
+++ b/Source/mesquite/coalesce/AverageTreeDepth/AverageTreeDepth.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+created:
+25 May 08 (DRM)
+ */
+
+package mesquite.coalesce.AverageTreeDepth;
+
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AverageTreeDepth extends NumberForTree {
+	double[] pathLengths = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public void treeDepth(Tree tree, int node, double depth) {
+		if (!tree.branchLengthUnassigned(node) && tree.getRoot()!=node)  //don't count the root
+			depth+= tree.getBranchLength(node);
+		if (tree.nodeIsTerminal(node)) { 
+			pathLengths[node] = depth;
+		}
+		else {
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				treeDepth(tree, daughter,depth);
+			}
+		}
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || tree==null)
+			return;
+		clearResultAndLastResult(result);
+		if (tree.hasBranchLengths()) {
+			pathLengths = new double[tree.getNumNodeSpaces()];
+			DoubleArray.deassignArray(pathLengths);
+			treeDepth(tree, tree.getRoot(),0.0);
+			int count = 0;
+			double total = 0.0;
+			for (int i=0;i<pathLengths.length; i++){
+				if (MesquiteDouble.isCombinable(pathLengths[i])) {
+					count++;
+					total += pathLengths[i];
+				}	
+			}
+			if (count==0)
+				result.setValue(0);
+			else
+				result.setValue(total/count);
+		}
+		else
+			result.setValue(0);
+		if (resultString!=null)
+			resultString.setValue("Average Tree Depth: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Average Tree Depth";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Calculates the average path length (in branch length) from terminals to the root, treating unassigned lengths as 0.  The length of the root is not counted.";
+	}
+}
diff --git a/Source/mesquite/coalesce/CoalescenceWMigration/CoalescenceWMigration.java b/Source/mesquite/coalesce/CoalescenceWMigration/CoalescenceWMigration.java
new file mode 100755
index 0000000..f17ce69
--- /dev/null
+++ b/Source/mesquite/coalesce/CoalescenceWMigration/CoalescenceWMigration.java
@@ -0,0 +1,580 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.coalesce.CoalescenceWMigration;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+//import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+/** ======================================================================== */
+public class CoalescenceWMigration extends TreeSimulate {
+	AssociationSource associationTask;
+	int oldPopulationSize = 0;
+	TaxaAssociation association;
+	OneTreeSource oneTreeSourceTask;
+	Tree speciesTree;
+	RandomBetween rNG;
+	int basePopulationSize  = 10000;
+	double migrationRate = 0.0000;
+	long initialSeed = System.currentTimeMillis(); //better rules for initial seed!!!!
+	int migrationFestival = -1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//TODO: allow choices
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon association");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+		if (oneTreeSourceTask == null) {
+			oneTreeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of containing tree");
+		}
+		rNG= new RandomBetween(initialSeed);
+		addMenuItem("Coalescence Parameters...", makeCommand("showParamsDialog", this));
+		if (!MesquiteThread.isScripting()){
+			showDialog();
+		}
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+		
+	
+	void showDialog(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog checkBoxDialog = new ExtensibleDialog(containerOfModule(), "Coalescence With Migration",buttonPressed);
+		checkBoxDialog.addLargeOrSmallTextLabel ("Parameters of coalescence simulation within species tree but with migration");
+		IntegerField ur = checkBoxDialog.addIntegerField("Effective population size", basePopulationSize, 15);
+		DoubleField mr = checkBoxDialog.addDoubleField("Migration probability per individual per generation", migrationRate, 15);
+		checkBoxDialog.addHorizontalLine(2);
+		checkBoxDialog.addLargeOrSmallTextLabel("If all migration is concentrated into a single burst a certain number of generations before the present, enter the point in time (number of generations before present) at which the burst occurred (enter -1 if not a burst but rather ongoing)");
+		IntegerField mF = checkBoxDialog.addIntegerField("Generation of burst", migrationFestival, 15);
+		//checkBoxDialog.addIntegerField("", 0, 15);
+
+		checkBoxDialog.completeAndShowDialog(true);
+
+		if (buttonPressed.getValue()==0) {
+			int bp = ur.getValue();
+			if (MesquiteInteger.isCombinable(bp))
+				basePopulationSize = bp;
+			double mrt = mr.getValue();
+			if (MesquiteDouble.isCombinable(mrt))
+				migrationRate = mrt;
+			int mFS = mF.getValue();
+			if (MesquiteInteger.isCombinable(bp))
+				migrationFestival = mFS;
+		}
+		checkBoxDialog.dispose();
+
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress "); 
+		temp.addLine("getAssociationTask ", associationTask); 
+		temp.addLine("getTreeSource ", oneTreeSourceTask); 
+		temp.addLine("setEffective " + basePopulationSize);
+		temp.addLine("setMigrationRate " + migrationRate);
+		if (migrationFestival>=0)
+			temp.addLine("setMigrationMoment " + migrationFestival);
+		temp.addLine("forgetAssociation "); 
+		temp.addLine("desuppress "); 
+	
+		return temp;
+	}
+	/*---*/
+boolean suppress = false;
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the effective population size for coalescence simulations", "[effective population size]", commandName, "setEffective")) {
+			int eff = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(eff))
+				eff = MesquiteInteger.queryInteger(containerOfModule(), "Population Size", "Set Effective population size", basePopulationSize);
+			if (!MesquiteInteger.isCombinable(eff))
+				return null;
+			if (basePopulationSize != eff) {
+				basePopulationSize = eff;
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the moment at which migration occurs (-1 if not a single moment)", "[generations before present]", commandName, "setMigrationMoment")) {
+			int eff = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(eff))
+				eff = MesquiteInteger.queryInteger(containerOfModule(), "Migration Moment", "Number of generations before present when all migration is concentrated (-1 if not concentrated)", migrationFestival);
+			if (!MesquiteInteger.isCombinable(eff))
+				return null;
+			if (migrationFestival != eff) {
+				migrationFestival = eff;
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the migration rate for coalescence simulations", "[probability of migration per individual per generation]", commandName, "setMigrationRate")) {
+			double mr = MesquiteDouble.fromString(arguments, new MesquiteInteger(0));
+			if (!MesquiteDouble.isCombinable(mr))
+				mr = MesquiteDouble.queryDouble(containerOfModule(), "Migration Rate", "Set migration probability per individual per generation", migrationRate);
+			if (!MesquiteDouble.isCombinable(mr))
+				return null;
+			if (migrationRate != mr) {
+				migrationRate = mr;
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+		}
+		else if  (checker.compare(this.getClass(), "Sets coalescence parameters by GUI", null, commandName, "showParamsDialog")) {
+			showDialog();
+			parametersChanged(); 
+		}
+		else if  (checker.compare(this.getClass(), "Returns the species tree being used for Contained With Migration", null, commandName, "getSpeciesTree")) {
+			return speciesTree;
+		}
+		else if  (checker.compare(this.getClass(), "Returns the containing tree context", null, commandName, "getTreeSource")) {
+			return oneTreeSourceTask;
+		}
+		else if  (checker.compare(this.getClass(), "Returns the module supplying associations", null, commandName, "getAssociationTask")) {
+			return associationTask;
+		}
+		else if  (checker.compare(this.getClass(), "Sets the current association to null", null, commandName, "forgetAssociation")) {
+			association = null;
+		}
+		else if  (checker.compare(this.getClass(), "Suppresses calculations", null, commandName, "suppress")) {
+			suppress = true;
+		}
+		else if  (checker.compare(this.getClass(), "Desuppresses calculations", null, commandName, "desuppress")) {
+			suppress = false;
+			if (!MesquiteThread.isScripting())
+				parametersChanged(); 
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private boolean check(Taxa taxa){
+		if (taxa!=null) {
+			if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+				association = associationTask.getCurrentAssociation(taxa);
+				if (association==null) {
+					String s = "Association null in Contained With Migration (for taxa " + taxa.getName() + ")";
+					if (MesquiteThread.isScripting())
+						MesquiteMessage.warnProgrammer(s);
+					else
+						alert(s);
+					return false;
+				}
+			}
+			if (oneTreeSourceTask == null) {
+				oneTreeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of containing tree");
+				if (oneTreeSourceTask == null) {
+					String s = "Source for containing tree null in Contained With Migration (for taxa " + taxa.getName() + ")";
+					if (MesquiteThread.isScripting())
+						MesquiteMessage.warnProgrammer(s);
+					else
+						alert(s);
+					return false;
+				}
+
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	NameReference widthNameReference = NameReference.getNameReference("width");
+	DoubleArray widths = null;
+	double maxWidth = 0;
+	/*.................................................................................................................*/
+	/* returns Ne multiplication factor for a branch, based on width stored */;
+	double branchNEAdjustment(int node){
+		if (widths !=null) {
+			double w = widths.getValue(node);
+			if (MesquiteDouble.isCombinable(w) && w>=0) {
+				return w;
+			}
+		}	
+		return 1.0;
+	}
+	public void initialize(Taxa taxa){
+		if (!check(taxa))
+			return;
+		if (oneTreeSourceTask!=null && association!=null)
+			oneTreeSourceTask.initialize(association.getOtherTaxa(taxa));
+
+	}
+	/*.................................................................................................................*/
+	boolean first = true;
+	/*.................................................................................................................*/
+	int numPopulationsFound(int[] populationsAtHeight){
+		if (populationsAtHeight == null || populationsAtHeight.length == 0)
+			return 0;
+		int count = 0;
+		for (int i=0; i<populationsAtHeight.length; i++){
+			if (populationsAtHeight[i]>=0)
+				count++;
+		}
+		return count;
+	}
+	int[] containing; //length of geneTree.getNumNodeSpaces();
+	/*.................................................................................................................*/
+	/*  coalesces the gene tree nodes contained within the populations. */
+	private void coalesceAllPopulations (MesquiteTree speciesTree, MesquiteTree geneTree, Taxa geneTaxa) {
+		if (suppress  || !speciesTree.hasBranchLengths())
+			return;
+		int numGenes = geneTree.getTaxa().getNumTaxa();
+
+		double height = speciesTree.tallestPathAboveNode(speciesTree.getRoot(), 1.0);
+
+		int[] populationsAtHeight = speciesTree.getNodesAtHeight(height, 1.0, null);
+
+		//In case there is a slight error (e.g. roundoff) in tree heights, 1 from height until populations array has at least one node in it.  
+		//Since branch lengths are measured in generations, subtracting 1 is just going generation by generation until the first branch pokes above water.
+		while (numPopulationsFound(populationsAtHeight)==0 && height > 0) {
+			height -= 1.0;
+			populationsAtHeight = speciesTree.getNodesAtHeight(height, 1.0, populationsAtHeight);
+		}
+		double top = height;
+		if (height <= 0)
+			return;
+
+		//Will store which nodes in gene tree had migration events
+		/**/
+		NameReference nr = geneTree.makeAssociatedObjects("MigrationEvents");
+		ObjectArray migrated = geneTree.getWhichAssociatedObject(nr);
+		migrated.resetSize(geneTree.getNumNodeSpaces());
+		for (int i= 0; i< migrated.getSize(); i++){
+			if (migrated.getValue(i) == null)
+				migrated.setValue(i, new Vector());
+			else
+				((Vector)migrated.getValue(i)).removeAllElements();
+		}
+
+
+		int numPopulations = 0;
+		for (int igene = 0; igene<containing.length; igene++)
+			containing[igene] =-1;
+
+		boolean[] justMigrated = new boolean[containing.length];
+		for (int igene = 0; igene<justMigrated.length; igene++)
+			justMigrated[igene] = false;
+
+
+		//initialize containing tree to put all terminal gene nodes into populations
+		for (int ipop = 0; ipop < populationsAtHeight.length; ipop++) {
+			int containingNode = populationsAtHeight[ipop];
+			if (containingNode>0){  //i.e., it's a legitimate node
+				numPopulations++;
+				int taxonNum = speciesTree.taxonNumberOfNode(containingNode);
+				Taxon species =speciesTree.getTaxa().getTaxon(taxonNum);
+				if (species !=null){
+					Taxon[] containedGenes = association.getAssociates(species); //finding all the genes contained within this species/population
+					if (containedGenes != null) { 
+						for (int i=0; i<containedGenes.length; i++)  {
+							int taxNum = geneTaxa.whichTaxonNumber(containedGenes[i]);
+							int cN = geneTree.nodeOfTaxonNumber(taxNum);
+							if (!geneTree.nodeExists(cN)) {  //error: a gene contained in the species is not represented in the gene tree
+								MesquiteMessage.warnProgrammer("contained gene not in gene tree in module " + getName() + ": containedGenes[i] " + containedGenes[i] + " taxNum " + taxNum + " cN " + cN);
+								MesquiteMessage.warnProgrammer("   " + geneTree.writeTree());
+							}
+							containing[cN] = containingNode;  //remember which species node contains this node in the gene tree
+
+						}
+					}
+				}
+			}
+		}
+
+		int[] numGenesInPop = new int[populationsAtHeight.length];
+		for (int i=0; i<numGenesInPop.length; i++)
+			numGenesInPop[i] = -1;
+		int[] commonAncestors = new int[numGenes];
+		int[] ancestors = new int[geneTree.getNumNodeSpaces()];
+		for (int i=0; i<ancestors.length; i++)
+			ancestors[i] = -1;
+		int numLeft = numGenes;
+
+
+
+		//Gene tree starts off as bush with all branch lengths 0
+
+		long generation=0;
+		//Now coalesce down
+		while (numLeft > 1){  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< GENERATIONS loop
+			generation++; //about to make next generation
+
+			//initialize how many genes are in each population
+			for (int ipop = 0; ipop < numGenesInPop.length; ipop++)
+				numGenesInPop[ipop] = 0;
+
+			for (int igene = 0; igene<containing.length; igene++)
+				if (containing[igene] >= 0) 
+					if (geneTree.motherOfNode(igene) != geneTree.getRoot()){
+						MesquiteMessage.warnProgrammer("current gene branch not daughter of root");
+					}
+
+
+			//lengthen gene tree branches to include this generation
+			for (int igene = 0; igene<containing.length; igene++)
+				if (containing[igene] >= 0) //gene is contained in some population  (???? are these just all of the daughters of the root of the gene tree
+					//lengthen branch for this generation
+					geneTree.setBranchLength(igene, geneTree.getBranchLength(igene) + 1.0, false);
+
+			//do migration & count genes in population
+			for (int igene = 0; igene<justMigrated.length; igene++)
+				justMigrated[igene] = false;
+			for (int ipop = 0; ipop < populationsAtHeight.length; ipop++) {  //=====================> migration loop start
+				int containingNode = populationsAtHeight[ipop];
+				if (containingNode>0){
+					//cycle through all contained genes in this population
+					for (int igene = 0; igene<containing.length; igene++){
+						if (containing[igene] == containingNode){ //gene is contained in this pop
+
+							//here decide whether to migrate
+							if ((migrationFestival < 0 || migrationFestival == generation) && !justMigrated[igene] && migrationRate>0.0 && rNG.nextDouble() <migrationRate){ //not already migrated and random number chooses to migrate
+								int choices = numPopulations-1;   //if there are 5 populations, then we have 4 to choose from
+								if (choices > 0){
+									int roll = rNG.randomIntBetween(0, choices-1);  //thus we can choose populations 0 through 3 inclusive
+									int ich = 0;
+									int chosen = -1;
+									//go through populations to see which species node the choice corresponds to
+									for (int ihome = 0; ihome < populationsAtHeight.length && chosen<0; ihome++){
+										if (populationsAtHeight[ihome]>0 && populationsAtHeight[ihome] != containingNode) {  //has to be at this height and not the current population
+											if (roll == ich)
+												chosen = ihome;
+											ich++;
+										}
+									}
+									if (chosen>=0){ //move to population chosen
+
+										Vector v = (Vector)migrated.getValue(igene);
+
+										if (v == null){
+											v = new Vector();
+											migrated.setValue(igene, v);
+										}
+										int pos = (int)(generation); // - geneTree.tallestPathAboveNode(igene, 1.0));  //record gen below top of branch that this happened
+										v.addElement(new Dimension(populationsAtHeight[chosen], pos));   
+										
+										justMigrated[igene] = true;
+										containing[igene] = populationsAtHeight[chosen];
+										numGenesInPop[chosen]++;//gene moves, gets credited to new population
+									}
+								}
+							}
+
+							else
+								numGenesInPop[ipop]++;  //gene stays, gets credited to original population
+						}
+					}
+
+				} 
+			} //=============================================================> migration loop end
+
+			numLeft = 0;
+
+			//coalesce: choose ancestors
+			for (int ipop = 0; ipop < populationsAtHeight.length; ipop++) { //=============> coalescing all population loop start
+				if (numGenesInPop[ipop]>1){   //this population does have genes
+					int containingNode = populationsAtHeight[ipop];  //the species tree node corresponding to this
+
+					if (containingNode>0){  //a legitimate species tree node
+						//intialize ancestors chosen
+						for (int i=0; i<ancestors.length; i++)
+							ancestors[i] = -1;
+
+						//calculate Ne as base Ne times branch width
+						int Ne = (int)( branchNEAdjustment(containingNode)*basePopulationSize);  
+
+						//cycle through all contained genes in this population, having each choose an ancestor
+						for (int igene = 0; igene<containing.length; igene++){
+							if (containing[igene] == containingNode){ //gene is contained in this pop
+								ancestors[igene] = rNG.randomIntBetween(0, Ne-1); 
+							}
+						}
+
+						//cycle through all contained genes in this population, seeing who chose the same ancestor
+						for (int igene = 0; igene<containing.length; igene++){
+							if (containing[igene] == containingNode){ //gene is contained in this pop
+								/* If ancestor chosen is -1, then skip (already dealt with)
+								otherwise get list of all genes that choose the same ancestor, 
+								make them coalesce on the gene tree, then set their chosen ancestors to -1.
+								 */
+								if (ancestors[igene] != -1) {
+									numLeft++;
+									double igeneLength = geneTree.getBranchLength(igene);
+									getGenesWithCommonAncestors(ancestors, igene, containing, containingNode, commonAncestors);
+									boolean firstCoalescence = true;
+									for (int icommon =0; icommon<commonAncestors.length; icommon++){
+										int other = commonAncestors[icommon];
+										if (other != igene && other >=0){  //found gene to coalesce
+											double otherLength = geneTree.getBranchLength(other);
+											geneTree.moveBranch(other, igene, false);
+											if (firstCoalescence){  //need to set up mother node
+												int mother = geneTree.motherOfNode(igene);
+												if (geneTree.nodeExists(mother)){
+													geneTree.setBranchLength(mother, 0, false);
+													containing[mother]=containingNode;
+												}
+											}
+											else {  //need to collapse new node to make polytomy
+												int mother = geneTree.motherOfNode(igene);
+												if (geneTree.nodeExists(mother)){
+													geneTree.collapseBranch(mother, false);
+												}
+											}
+											geneTree.setBranchLength(igene, igeneLength, false);
+											geneTree.setBranchLength(other, otherLength, false);
+											firstCoalescence = false;
+											ancestors[igene]=-1;
+											ancestors[other]=-1;
+											containing[igene] = -1;
+											containing[other] = -1;
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				else
+					numLeft += numGenesInPop[ipop];
+			}//=============================================================> coalescing all population loop start
+			height -= 1.0;
+			populationsAtHeight = speciesTree.getNodesAtHeight(height, 1.0, populationsAtHeight);
+
+			numPopulations = numPopulationsFound(populationsAtHeight);
+
+			//if we've gone to root, need to set populations as consisting of just root
+			if (numPopulations == 0) {
+				numPopulations = 1;
+				populationsAtHeight[0] = speciesTree.getRoot();
+			}
+
+			//if genes are found that are not in a current population because water level has been dropped, move the genes into their population's ancestor
+			for (int igene = 0; igene<containing.length; igene++){
+				if (containing[igene]>=0 && IntegerArray.indexOf(populationsAtHeight, containing[igene])<0){ //gene is not contained in any current pop
+					containing[igene] = speciesTree.motherOfNode(containing[igene]);
+					if (IntegerArray.indexOf(populationsAtHeight, containing[igene])<0){
+						MesquiteMessage.warnProgrammer("Error in " + getName() + ": gene not in a populations;  igene " + igene + " containing[igene] " + containing[igene] + "  ROOT " + speciesTree.getRoot());
+					}
+					}
+
+			}
+		}  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GENERATIONS loop
+
+	}
+	/*.................................................................................................................*/
+	void getGenesWithCommonAncestors(int[] ancestors,  int igene, int[] containing, int containingNode,int[] commonAncestors){
+		for (int i = 0; i < commonAncestors.length; i++)
+			commonAncestors[i]=-1;
+		int target = ancestors[igene];
+		int count = 0;
+		for (int i= 0; i<ancestors.length; i++){
+			if (containing[i] == containingNode && ancestors[i] == target)
+				commonAncestors[count++] = i;
+		}
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		return MesquiteInteger.infinite;
+	}
+	MesquiteTree savedBush;
+	/*.................................................................................................................*/
+	public Tree getSimulatedTree(Taxa taxa, Tree geneTree, int treeNumber, ObjectContainer extra, MesquiteLong seed) {
+		if (!check(taxa))			return null;
+		CommandRecord.tick("Coalescing with migration in tree " + treeNumber);
+		if (association==null) {
+			if (first)
+				discreetAlert( "No association found for use by Contained With Migration; no tree could be made");
+			first = false;
+			return null;
+		}
+		rNG.setSeed(seed.getValue());
+		speciesTree = oneTreeSourceTask.getTree(association.getOtherTaxa(taxa));
+		if (speciesTree==null) {
+			if (first)
+				discreetAlert( "No species tree found for use by Contained With Migration.  Taxa blocks: " + taxa + " AND " + association.getOtherTaxa(taxa));
+			first = false;
+			return null;
+		}
+		widths = speciesTree.getWhichAssociatedDouble(widthNameReference);
+
+		MesquiteTree t=null;
+		if (geneTree==null || !(geneTree instanceof MesquiteTree))
+			t = new MesquiteTree(taxa);
+		else
+			t = (MesquiteTree)geneTree;
+		if (savedBush==null || savedBush.getTaxa()!=t.getTaxa()) {
+			t.setToDefaultBush(t.getNumTaxa(), false);
+			savedBush = t.cloneTree();
+		}
+		else {
+			t.setToClone(savedBush);
+		}
+		if (containing ==null || containing.length!=t.getNumNodeSpaces())
+			containing = new int[t.getNumNodeSpaces()];
+		for (int i=0; i<containing.length; i++)
+			containing[i] = 0;
+		t.setAllBranchLengths(0.0, false);
+		coalesceAllPopulations((MesquiteTree)speciesTree, t, taxa);
+		seed.setValue(rNG.nextLong());
+		return t;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Coalescence in Current Tree with Migration";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is a prerelease version.  This returns "TRUE" here, forcing modules to override to claim they are not prerelease */
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Generates tree by a simple coalescence model of a neutral gene with constant population size, within a current species tree from a Tree window or other tree context. "
+		+"Branch lengths are assigned according to generation of coalescence.  The default population size is 10000. " 
+		+"The species tree used is a current tree found in a Tree Window or other tree context. " 
+		+"Migration is allowed; the default probability is 0.00001 per individual generation. " 
+		+"Migration can be isolated to a particular generation, or spread throughout the depth of the species/population history." ;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (speciesTree!=null) {
+			String s =  "Species tree: " + speciesTree.getName() + "; Ne: " + basePopulationSize + "; Migration rate: " + migrationRate;
+			if (migrationRate> 0.0 && migrationFestival>=0)
+				s += " (migration concentrated in generation " + migrationFestival + " back in past)";
+			return s;
+		}
+		return "";
+	}
+}
+
+
diff --git a/Source/mesquite/coalesce/CoalescentTrees/CoalescentTrees.java b/Source/mesquite/coalesce/CoalescentTrees/CoalescentTrees.java
new file mode 100644
index 0000000..5e2d06b
--- /dev/null
+++ b/Source/mesquite/coalesce/CoalescentTrees/CoalescentTrees.java
@@ -0,0 +1,114 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.CoalescentTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+
+/* ======================================================================== */
+public class CoalescentTrees extends TreeSimulate {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(Coalescer.class, getName() + " uses a coalescent simulator to simulate gene trees.",
+		"The coalescent simulator is either chosen automatically or you can choose it initially.");
+	}
+	Coalescer coalescenceTask;
+	CoalescedNode[] originals;
+	int[] containing;
+	int oldPopulationSize = 0;
+	int numTaxa = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//todo: eventually allow UI choice and hiringCommand
+		coalescenceTask = (Coalescer)hireEmployee(Coalescer.class, "Coalescence simulator");
+		if (coalescenceTask == null)
+			return sorry(getName() + " couldn't start because no coalescence simulator module obtained.");
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+  	 
+	/*.................................................................................................................*/
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return MesquiteInteger.infinite;
+   	}
+   	MesquiteTree savedBush;
+	/*.................................................................................................................*/
+   	public Tree getSimulatedTree(Taxa taxa, Tree tree, int treeNumber, ObjectContainer extra, MesquiteLong seed) {
+		
+		MesquiteTree t=null;
+		if (tree==null || !(tree instanceof MesquiteTree))
+			 t = new MesquiteTree(taxa);
+		else
+			t = (MesquiteTree)tree;
+		if (savedBush==null || savedBush.getTaxa()!=t.getTaxa()) {
+			t.setToDefaultBush(t.getNumTaxa(), false);
+			savedBush = t.cloneTree();//no need to establish listener to Taxa, as will be remade when needed?
+		}
+		else
+			t.setToClone(savedBush);
+		if (containing == null || containing.length<t.getNumNodeSpaces()) {
+			containing = new int [t.getNumNodeSpaces()];
+		}
+		for (int i=0; i<containing.length; i++){
+			if (t.taxonNumberOfNode(i)>=0 ) //terminal node
+				containing[i]=1;
+			else
+				containing[i]=0;
+		}
+		coalescenceTask.coalesce(t, containing, 1, 1.0, -1,  seed, true); 
+  		return t;
+   	}
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Coalescent Trees";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Generates tree by coalescence within a single panmictic population." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+		if (coalescenceTask!=null)
+			return "Coalescence simulator: " + coalescenceTask.getName();
+		return "";
+   	}
+   	
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+}
+
+
+
diff --git a/Source/mesquite/coalesce/ContainedCoalescSim/ContainedCoalescSim.java b/Source/mesquite/coalesce/ContainedCoalescSim/ContainedCoalescSim.java
new file mode 100644
index 0000000..bf77189
--- /dev/null
+++ b/Source/mesquite/coalesce/ContainedCoalescSim/ContainedCoalescSim.java
@@ -0,0 +1,234 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.ContainedCoalescSim;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+/* ======================================================================== 
+For version 1.02 this was split off from Contained Coalescence to allow alternatives to be swapped more easily in the future (e.g, with migration)*/
+public class ContainedCoalescSim extends ContainedTreeSim {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(Coalescer.class, getName() + " uses a coalescent simulator to simulate gene trees.",
+		"The coalescent simulator is either chosen automatically or you can choose it initially.");
+	}
+	Coalescer coalescenceTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		coalescenceTask = (Coalescer)hireEmployee(Coalescer.class, "Coalescence simulator");
+		if (coalescenceTask == null)
+			return sorry(getName() + " couldn't start because no coalescence module obtained.");
+ 		return true;
+  	 }
+  	 public void endJob(){
+  	 	if (savedBush!=null)
+  	 		savedBush.dispose();
+  	 	super.endJob();
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	return temp;
+  	 }
+  	 /*---*/
+  	
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if  (checker.compare(this.getClass(), "Returns the species tree being used for contained coalescence", null, commandName, "getSpeciesTree")) {
+    	 		return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+	/*.................................................................................................................*/
+	NameReference widthNameReference = NameReference.getNameReference("width");
+	DoubleArray widths = null;
+	double maxWidth = 0;
+	/*.................................................................................................................*/
+	double branchNEAdjustment(int node){
+		if (widths !=null) {
+			double w = widths.getValue(node);
+			if (MesquiteDouble.isCombinable(w) && w>=0) {
+				return w;
+			}
+		}	
+		return 1.0;
+	}
+	/*.................................................................................................................*/
+	boolean first = true;
+	/*.................................................................................................................*/
+   	int[] containing; //length of geneTree.getNumNodeSpaces();
+	/*.................................................................................................................*/
+	/*  coalesces the gene tree nodes contained within the species tree node "node". */
+	private synchronized int coalesceDown (Coalescer coalescer, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, Taxa geneTaxa, int node, int root, MesquiteLong seed) {
+		int nodeNumber = -2;
+		double br=speciesTree.getBranchLength(node);  //for calculating the number of generations in which coalescence can occur here
+		long generations=0;
+		//branch length is NOT scaled by population size; thus branch length is now treated as the number of generations to coalesce
+		if (MesquiteDouble.isCombinable(br) && (long)(br)>1) //&& node != speciesTree.getRoot() 
+			generations =  (long)(br); 
+		else 
+			generations =1;
+		if (speciesTree.nodeIsTerminal(node)) { //if terminal node, make CoalescedNode array, one element for each contained gene
+			int taxonNum = speciesTree.taxonNumberOfNode(node);
+			Taxon species =speciesTree.getTaxa().getTaxon(taxonNum);
+			nodeNumber=node;
+			Taxon[] containedGenes = association.getAssociates(species);
+			if (containedGenes != null) {
+				for (int i=0; i<containedGenes.length; i++)  {
+					int taxNum = geneTaxa.whichTaxonNumber(containedGenes[i]);
+					int cN = geneTree.nodeOfTaxonNumber(taxNum);
+					if (!geneTree.nodeExists(cN)) {
+						MesquiteMessage.warnProgrammer("GeneTree node doesn't exist ContainedCoalescence containedGenes[i] " + containedGenes[i] + " taxNum " + taxNum + " cN " + cN);
+						MesquiteMessage.warnProgrammer("   Gene tree:   " + geneTree.writeTree());
+					}
+					containing[cN] = node;  //can't use taxonNum because if 1, screws things up
+				}
+			}
+		}
+		else {
+			for (int daughter = speciesTree.firstDaughterOfNode(node); speciesTree.nodeExists(daughter); daughter = speciesTree.nextSisterOfNode(daughter)){
+				int nn = coalesceDown(coalescer, speciesTree, geneTree, association, geneTaxa, daughter, root, seed);
+				if (nodeNumber==-2)
+					nodeNumber = nn;
+				else {
+					//change all occurrences of nn in containing to nodeNumber
+					for (int i =0; i<containing.length; i++)
+						if (containing[i]== nn) {
+							if (!geneTree.nodeExists(i))
+								MesquiteMessage.warnProgrammer("GeneTree node doesn't exist ContainedCoalescence nn " + nn);
+							containing[i]=nodeNumber;
+						}
+				}
+			}
+		}
+		// now about to coalesce the gene tree nodes listed in containing as belonging to nodeNumber.
+		if (MesquiteLong.isInfinite(generations)) 
+			coalescer.coalesce(geneTree, containing, nodeNumber, branchNEAdjustment(node), 0, seed, true); //speciesTree.getRoot() == node);
+		else 
+			coalescer.coalesce(geneTree, containing, nodeNumber,  branchNEAdjustment(node), generations, seed, root == node); //speciesTree.getRoot() == node);
+		return nodeNumber;
+	}
+	/*.................................................................................................................*/
+   	MesquiteTree savedBush;
+   	long oldTaxaVersion = -1;
+   	boolean inProgress = false;
+   	TreeReference speciesTreeRef, oldSpeciesTreeRef;
+	/*.................................................................................................................*/
+	public MesquiteTree simulateContainedTree (Tree speciesTree, Tree geneTree, TaxaAssociation association, Taxa geneTaxa, MesquiteLong seed){
+   		if (speciesTree == null || association == null || geneTaxa == null)
+   			return null;
+		if (inProgress)
+			return null;
+		inProgress = true;
+		if (speciesTree instanceof MesquiteTree)
+			speciesTreeRef = ((MesquiteTree)speciesTree).getTreeReference(speciesTreeRef);
+		else
+			speciesTreeRef = null;
+		widths = speciesTree.getWhichAssociatedDouble(widthNameReference);
+		MesquiteTree t=null;
+	
+		if (geneTree==null || !(geneTree instanceof MesquiteTree)) 
+			 t = new MesquiteTree(geneTaxa);
+		else
+			t = (MesquiteTree)geneTree;
+		if ((speciesTreeRef == null || oldSpeciesTreeRef == null || !speciesTreeRef.equals(oldSpeciesTreeRef)) || savedBush==null || savedBush.getTaxa()!=t.getTaxa() || oldTaxaVersion != t.getVersionNumber()) {
+			if (savedBush != null)
+				savedBush.dispose();
+			t.setToDefaultBush(t.getNumTaxa(), false);
+
+			oldTaxaVersion = t.getVersionNumber();
+			Taxon[] assocs = null;
+				for (int i=0; i<geneTaxa.getNumTaxa(); i++){
+			
+				assocs = association.getAssociates(geneTaxa.getTaxon(i), assocs);  //get containing taxa
+
+				//if any of containing taxa in speciesTree then keep, otherwise delete contained taxon from savedbush
+				if (!inSpeciesTree(speciesTree, assocs, speciesTree.getTaxa())){
+					t.snipClade(t.nodeOfTaxonNumber(i), false);
+				}
+			}
+			savedBush = t.cloneTree();//no need to establish listener to Taxa, as will be remade when needed?
+		}
+		else {
+			t.setToClone(savedBush);
+		}
+		oldSpeciesTreeRef = speciesTreeRef;
+		if (containing ==null || containing.length!=t.getNumNodeSpaces())
+			containing = new int[t.getNumNodeSpaces()];
+		for (int i=0; i<containing.length; i++)
+			containing[i] = 0;
+		int root = speciesTree.getRoot();
+		coalesceDown(coalescenceTask, speciesTree, t, association, geneTaxa, root, root, seed);
+   		inProgress = false;
+   		return t;
+   	}
+   	public boolean inSpeciesTree(Tree speciesTree, Taxon[] assocs, Taxa taxa){
+   		if (assocs == null)
+   			return false;
+   		for (int i=0; i<assocs.length; i++){
+   			int t = taxa.whichTaxonNumber(assocs[i]);
+   			if (speciesTree.nodeOfTaxonNumber(t)>0)
+   				return true;
+   		}
+  		return false;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Coalescence Simulated within Current Tree";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Generates tree by a simple coalescence model of a neutral gene with constant population size, within species trees. "
+ 		+"Branch lengths are assigned according to generation of coalescence." 
+ 		+"The species tree used is a current tree found in a Tree Window or other tree context." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+		if (coalescenceTask!=null)
+			return "Coalescence simulated by: " + coalescenceTask.getName();
+		return "";
+   	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+   	 /**@return	<p>The base population size from {@link #coalescenceTask}, if available. Returns {@code MesquiteInteger.unassigned} 
+   	  * if {@code coalescenceTask == null}.</p>*/
+   	 public int getPopulationSize() {
+   		 if (coalescenceTask != null) {
+   			 return coalescenceTask.getPopulationSize();
+   		 } else {
+   			 return MesquiteInteger.unassigned;
+   		 }
+   	 }
+}
+
+
diff --git a/Source/mesquite/coalesce/ContainedCoalescence/ContainedCoalescence.java b/Source/mesquite/coalesce/ContainedCoalescence/ContainedCoalescence.java
new file mode 100644
index 0000000..dd23000
--- /dev/null
+++ b/Source/mesquite/coalesce/ContainedCoalescence/ContainedCoalescence.java
@@ -0,0 +1,210 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.coalesce.ContainedCoalescence;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+/* ======================================================================== 
+For version 1.02 the main calculations of this were split off as ContainedCoalescSim to allow alternatives to be swapped more easily in the future (e.g, with migration)*/
+public class ContainedCoalescence extends TreeSimulate {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ContainedTreeSim.class, getName() + " uses a coalescent simulator to simulate gene trees.",
+				"The coalescent simulator is either chosen automatically or you can choose it initially.");
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + " uses a current tree.",
+				"The source of a current tree is chosen initially.");
+		EmployeeNeed e3 = registerEmployeeNeed(AssociationSource.class, getName() + " uses a current taxon association.",
+				"The source of a taxon association is chosen initially.");
+
+	}
+	AssociationSource associationTask;
+	TaxaAssociation association;
+	OneTreeSource oneTreeSourceTask;
+	ContainedTreeSim simTask;
+	Tree speciesTree;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//TODO: allow subsequent choosing from menus
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon association (Contained Coalescence)");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+		simTask = (ContainedTreeSim)hireEmployee(ContainedTreeSim.class, "Simulator of coalescence within current tree");
+		if (simTask == null)
+			return sorry(getName() + " couldn't start because no simulation module obtained.");
+		if (oneTreeSourceTask == null) {
+			oneTreeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of containing tree");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public void initialize(Taxa taxa){
+		if (!check(taxa))
+			return;
+		if (oneTreeSourceTask!=null && association!=null)
+			oneTreeSourceTask.initialize(association.getOtherTaxa(taxa));
+
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getAssociationTask ", associationTask); 
+		temp.addLine("getTreeSource ", oneTreeSourceTask); 
+		temp.addLine("setSimulator ", simTask); 
+		temp.addLine("forgetAssociation "); 
+
+		return temp;
+	}
+	/*---*/
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if  (checker.compare(this.getClass(), "Returns the species tree being used for contained coalescence", null, commandName, "getSpeciesTree")) {
+			return speciesTree;
+		}
+		else if  (checker.compare(this.getClass(), "Returns the containing tree context", null, commandName, "getTreeSource")) {
+			return oneTreeSourceTask;
+		}
+		else if  (checker.compare(this.getClass(), "Sets the simulator", null, commandName, "setSimulator")) {
+			ContainedTreeSim temp=  (ContainedTreeSim)replaceEmployee(ContainedTreeSim.class, arguments, "Simulation method", simTask);
+			if (temp!=null) {
+				simTask= temp;
+				parametersChanged();
+			}
+			return simTask;
+		}
+		else if  (checker.compare(this.getClass(), "Returns the module supplying associations", null, commandName, "getAssociationTask")) {
+			return associationTask;
+		}
+		else if  (checker.compare(this.getClass(), "Sets the current association to null", null, commandName, "forgetAssociation")) {
+			association = null;
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	boolean warnedNull = false;
+	/*.................................................................................................................*/
+	private boolean check(Taxa taxa){
+		if (taxa!=null) {
+			if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+				association = associationTask.getCurrentAssociation(taxa);
+				/*	MesquiteModule mb = getFileCoordinator().findEmployeeWithName("#mesquite.leaves.BestSpeciesTreeForAssoc.BestSpeciesTreeForAssoc");
+	        		if (mb!=null) {
+	        			association = ((NumberForAssociation)mb).getCurrentAssociation();
+	        		}
+	        		if (association==null)
+		        		association = associationTask.getCurrentAssociation(taxa);
+				 */
+				if (association==null) {
+					String s = "Association null in Contained Coalescence (for taxa " + taxa.getName() + ")";
+					if (warnedNull)
+						MesquiteMessage.println(s);
+					else
+						discreetAlert( s);
+					warnedNull = true;
+					return false;
+				}
+			}
+			if (oneTreeSourceTask == null) {
+				oneTreeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of containing tree");
+				if (oneTreeSourceTask == null) {
+					String s = "Source for containing tree null in Contained Coalescence (for taxa " + taxa.getName() + ")";
+					if (warnedNull)
+						MesquiteMessage.println(s);
+					else
+						discreetAlert( s);
+					warnedNull = true;
+					return false;
+				}
+
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		return MesquiteInteger.infinite;
+	}
+	long oldTaxaVersion = -1;
+	boolean first = true;
+	/*.................................................................................................................*/
+	public Tree getSimulatedTree(Taxa taxa, Tree geneTree, int treeNumber, ObjectContainer extra, MesquiteLong seed) {
+		if (!check(taxa))   			return null;
+		if (association==null) {
+			if (first && !MesquiteThread.isScripting()){
+				discreetAlert("No association found for use by Contained Coalescence; no tree could be made");
+				first = false;
+			}
+			return null;
+		}
+		speciesTree = oneTreeSourceTask.getTree(association.getOtherTaxa(taxa));
+		if (speciesTree==null) {
+			if (first && !MesquiteThread.isScripting()){
+				discreetAlert("No species tree found for use by Contained Coalescence.  Taxa blocks: " + taxa + " AND " + association.getOtherTaxa(taxa));
+				first = false;
+			}
+			return null;
+		}
+
+
+		geneTree = simTask.simulateContainedTree(speciesTree, geneTree, association, taxa, seed);
+		return geneTree;
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Coalescence Contained within Current Tree";
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Generates tree by a simple coalescence model of a neutral gene with constant population size, within a current species tree from a Tree window or other tree context. "
+				+"Branch lengths are assigned according to generation of coalescence." 
+				+"The species tree used is a current tree found in a Tree Window or other tree context." ;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getNameAndParameters() {
+		if (speciesTree!=null)
+			return simTask.getNameAndParameters() + " (Species tree: " + speciesTree.getName() + ")" ;
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (speciesTree!=null)
+			return "Species tree: " + speciesTree.getName() + "; " + simTask.getParameters();
+		return "";
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+
diff --git a/Source/mesquite/coalesce/DeepCoalMultLoci/DeepCoalMultLoci.java b/Source/mesquite/coalesce/DeepCoalMultLoci/DeepCoalMultLoci.java
new file mode 100644
index 0000000..dfd4a8c
--- /dev/null
+++ b/Source/mesquite/coalesce/DeepCoalMultLoci/DeepCoalMultLoci.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.DeepCoalMultLoci;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a species tree by calculating how much lineage sorting is implied by a set of contained gene trees. */
+public class DeepCoalMultLoci extends NumberForTree implements Incrementable {
+		public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+			EmployeeNeed e2 = registerEmployeeNeed(TreeBlockSource.class, getName() + " needs a source of trees whose fit within the containing tree will be assessed.",
+			"The source of other trees can be indicated initially or later under the Gene Tree Source submenu.");
+			EmployeeNeed e3 = registerEmployeeNeed(AssociationSource.class, getName() + " needs a taxa association to indicate how contained taxa fit within containing taxa.",
+			"The source of associations may be arranged automatically or is chosen initially.");
+			EmployeeNeed e4 = registerEmployeeNeed(ReconstructAssociation.class, getName() + "needs to fit or reconstruct the contained tree within the containing tree in order to measure its fit.",
+			"The reconstruction method can be specified initially.");
+		}
+	MesquiteNumber nt;
+	TreeBlockSource treeSourceTask;
+	AssociationSource associationTask;
+	ReconstructAssociation reconstructTask;
+	MesquiteString treeSourceName;
+	TaxaAssociation association;
+	int currentContainedTreeBlock = MesquiteInteger.unassigned;
+	Taxa containedTaxa;
+	MesquiteCommand tstC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+		reconstructTask = (ReconstructAssociation)hireEmployee(ReconstructAssociation.class, "Method to reconstruct association history");
+		if (reconstructTask == null)
+			return sorry(getName() + " couldn't start because no association reconstructor module obtained.");
+		treeSourceTask = (TreeBlockSource)hireEmployee(TreeBlockSource.class, "Source of contained trees");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeBlockSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Gene Tree Source", tstC, TreeBlockSource.class);
+			mss.setSelected(treeSourceName);
+		}
+ 		addMenuItem( "Next Contained Tree block", makeCommand("nextContained",  this));
+ 		addMenuItem( "Previous Contained Tree block", makeCommand("previousContained",  this));
+ 		nt= new MesquiteNumber();
+ 		return true;
+  	 }
+  	 
+	public void employeeQuit(MesquiteModule m){
+		if (m != treeSourceTask)
+			iQuit();
+	}  	 
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", treeSourceTask); 
+  	 	temp.addLine("setContained " + MesquiteTree.toExternal(currentContainedTreeBlock));
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the source of the gene tree", "[name of module]", commandName, "setTreeSource")) {
+			TreeBlockSource temp = (TreeBlockSource)replaceEmployee(TreeBlockSource.class, arguments, "Source of trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				parametersChanged();
+    	 			return treeSourceTask;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next block of contained gene trees", null, commandName, "nextContained")) {
+    	 		if (MesquiteInteger.isUnassigned(currentContainedTreeBlock))
+    	 			currentContainedTreeBlock = -1;
+    	 		setContained(currentContainedTreeBlock+1);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous block of contained gene trees", null, commandName, "previousContained")) {
+    	 		if (MesquiteInteger.isUnassigned(currentContainedTreeBlock))
+    	 			currentContainedTreeBlock = 1;
+    	 		setContained(currentContainedTreeBlock-1);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to block of contained gene trees", "[number of tree]", commandName, "setContained")) {
+    	 		int ic = MesquiteTree.toInternal(MesquiteInteger.fromFirstToken(arguments, pos)); 
+    	 		setContained(ic);
+    	 	}
+ 		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+   	 
+	public void setContained (int index){ 
+		if (containedTaxa == null)
+			return;
+ 		if (index<((TreeBlockSource)treeSourceTask).getNumberOfTreeBlocks(containedTaxa) && index>=0){
+ 			currentContainedTreeBlock=index;
+ 			parametersChanged();
+ 		}
+	}
+	Tree lastTree;
+	MesquiteTree cTree;
+   	TreeVector trees;
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (tree ==null)
+   			return;
+   		Taxa taxa = tree.getTaxa();
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+        	}
+   	}
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		currentContainedTreeBlock = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return currentContainedTreeBlock;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Contained tree";
+ 	}
+ 	public long getMin(){
+		return 0;
+ 	}
+ 	public long getMax(){
+		int nt = ((TreeBlockSource)treeSourceTask).getNumberOfTreeBlocks(containedTaxa);
+		return nt -1;
+ 	}
+ 	public long toInternal(long i){
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+ 	MesquiteNumber cost = new MesquiteNumber();
+	MesquiteString r = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		cost.setToUnassigned();
+		lastTree = tree;
+		Taxa taxa = tree.getTaxa();
+		
+		//getting association & contained taxa
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association == null)
+        			association = associationTask.getAssociation(taxa, 0); 
+        		if (association == null){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence (Multiple loci) not calculated (no association )");
+				return;
+			}
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+        	}
+        	
+        	/* need to find out for each taxon among contained taxa if it has more than one associate.  If so, then 
+        	can't do calculations since gene copy in more than one species*/
+		for (int i=0; i< containedTaxa.getNumTaxa(); i++){
+			Taxon tax = containedTaxa.getTaxon(i);
+			if (association.getNumAssociates(tax)>1){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence (Multiple loci) not calculated (some genes in more than one species)");
+				return;
+			}
+		}
+
+        	//choosing which tree block (or other incrementable unit) from the tree block source
+        	if (MesquiteInteger.isUnassigned(currentContainedTreeBlock)){
+        		if (MesquiteThread.isScripting())
+        			currentContainedTreeBlock = 0;
+        		else {
+				int nt = ((TreeBlockSource)treeSourceTask).getNumberOfTreeBlocks(containedTaxa);
+			   	if (nt>1 && !MesquiteThread.isScripting()) {
+   					currentContainedTreeBlock = ((TreeBlockSource)treeSourceTask).queryUserChoose(containedTaxa, "Which trees to serve as source of gene trees to fit into species tree to count deep coalescences?");
+   					if (MesquiteInteger.isUnassigned(currentContainedTreeBlock))
+   						currentContainedTreeBlock = 0;
+   				}
+   				else
+   					currentContainedTreeBlock = 0;
+				
+        		}
+        	}
+        	
+        	//getting the contained trees
+		trees = ((TreeBlockSource)treeSourceTask).getBlock(containedTaxa, currentContainedTreeBlock); 
+	        if (trees==null) {
+			if (resultString!=null)
+				resultString.setValue("Deep coalescences: unassigned (no gene trees)");
+			return;
+		}
+		
+		//get each tree and calculate deep coalescence cost
+		int numTrees = trees.size();
+		MesquiteNumber sum = new MesquiteNumber(0);
+		for (int iTree = 0; iTree<numTrees; iTree++){
+			 //cloning the contained tree in case we need to change its resolution
+			Tree containedTree = trees.getTree(iTree); 
+		        if (cTree == null || cTree.getTaxa()!=containedTaxa || !(containedTree instanceof MesquiteTree))
+		        	cTree = containedTree.cloneTree();//no need to establish listener to Taxa, as will be remade when needed?
+		        else
+		        	cTree.setToClone((MesquiteTree)containedTree);
+		        reconstructTask.calculateHistoryCost(tree, cTree, association, cost, r);
+			sum.add(cost);
+		}
+		
+		result.setValue(sum);
+		if (resultString!=null)
+			resultString.setValue("Deep coalescence cost " + result + " (" + numTrees + " gene trees \"" + trees.getName() + "\" in species tree " + lastTree.getName() + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Counts W. Maddison's (1997) number of extra gene lineages (\"deep coalescences\") for species tree containing a series of gene trees.  The gene trees must be represented by a single taxa block.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Deep Coalescences Multiple Loci";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/DeepCoalescencesG/DeepCoalescencesG.java b/Source/mesquite/coalesce/DeepCoalescencesG/DeepCoalescencesG.java
new file mode 100644
index 0000000..c51f0c6
--- /dev/null
+++ b/Source/mesquite/coalesce/DeepCoalescencesG/DeepCoalescencesG.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.DeepCoalescencesG;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a gene tree by calculating how much lineage sorting is implied by a containing species tree. */
+public class DeepCoalescencesG extends GeneTreeFit {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+//		superStartJob(arguments, condition,  hiredByName);
+		return true;
+  	 }
+ 	   	/*.................................................................................................................*/
+ 	public void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r){
+	        if (result != null)
+	        	reconstructTask.reconstructHistory(speciesTree, geneTree, association, result, r);
+	}
+
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false; 
+   	}
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Counts W. Maddison's (1997) number of extra gene lineages (\"deep coalescences\") for gene tree within species tree";
+   	 }
+   
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Deep Coalescences (gene tree)";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/DeepCoalescencesSp/DeepCoalescencesSp.java b/Source/mesquite/coalesce/DeepCoalescencesSp/DeepCoalescencesSp.java
new file mode 100644
index 0000000..a593182
--- /dev/null
+++ b/Source/mesquite/coalesce/DeepCoalescencesSp/DeepCoalescencesSp.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.DeepCoalescencesSp;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a species tree by calculating how much lineage sorting is implied by a contained gene tree. */
+public class DeepCoalescencesSp extends SpeciesTreeFit  {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+//		superStartJob(arguments, condition,  hiredByName);
+		return true;
+  	 }
+ 	   	/*.................................................................................................................*/
+ 	public void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r){
+	        if (result != null){
+	        	AssociationHistory history = reconstructTask.reconstructHistory(speciesTree, geneTree, association, result, r);
+	        }
+	}
+
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Counts W. Maddison's (1997) number of extra gene lineages (\"deep coalescences\") for species tree implied by a contained gene tree";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Deep Coalescences (species tree)";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/DuplicationsExtinctionsG/DuplicationsExtinctionsG.java b/Source/mesquite/coalesce/DuplicationsExtinctionsG/DuplicationsExtinctionsG.java
new file mode 100644
index 0000000..01732b1
--- /dev/null
+++ b/Source/mesquite/coalesce/DuplicationsExtinctionsG/DuplicationsExtinctionsG.java
@@ -0,0 +1,128 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.DuplicationsExtinctionsG;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a gene tree by calculating how much lineage sorting is implied by a containing species tree. */
+public class DuplicationsExtinctionsG extends GeneTreeFit {
+	MesquiteSubmenuSpec countOptionSubmenu;
+	static int DUPSEXT = 0;
+	static int DUPSONLY = 1;
+	static int EXTONLY = 2;
+	int style = DUPSEXT;
+	MesquiteString countOptionName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		countOptionSubmenu = addSubmenu(null, "Counting Mode (Dup./Ext.)");
+		addItemToSubmenu(null, countOptionSubmenu, "Count Duplications & Extinctions", makeCommand("countDE",  this));
+ 		addItemToSubmenu(null, countOptionSubmenu, "Count Duplications Only", makeCommand("countD",  this));
+ 		addItemToSubmenu(null, countOptionSubmenu, "Count Extinctions Only", makeCommand("countE",  this));
+		countOptionName = new MesquiteString("Count Duplications & Extinctions");
+		style = DUPSEXT;
+		countOptionSubmenu.setSelected(countOptionName);
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	 public Snapshot getSnapshot(MesquiteFile file) { 
+  	 	Snapshot temp = new Snapshot();
+  	 	if (style== DUPSEXT)
+ 	 		temp.addLine("countDE"); 
+ 	 	else if (style== DUPSONLY)
+ 	 		temp.addLine("countD"); 
+ 	 	else if (style== EXTONLY)
+ 	 		temp.addLine("countE"); 
+	 	return temp;
+ 	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	   	 	 if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countDE")) {
+    	 		int current = style;
+    	 		style = DUPSEXT;
+       			countOptionName.setValue("Count Duplications & Extinctions");
+   	 		if (current!=style)
+    	 			parametersChanged();
+    	 	}
+       	 	else if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countD")) {
+    	 		int current = style;
+    	 		style = DUPSONLY;
+       			countOptionName.setValue("Count Duplications Only");
+   	 		if (current!=style)
+    	 			parametersChanged();
+    	 	}
+       	 	else if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countE")) {
+    	 		int current = style;
+    	 		style = EXTONLY;
+    			countOptionName.setValue("Count Extinctions Only");
+    			if (current!=style)
+    	 			parametersChanged();
+    	 	}
+    		else {
+     			return  super.doCommand(commandName, arguments, checker);
+    		}
+    		return null;
+       	 }
+	   	/*.................................................................................................................*/
+ 	public void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r){
+        if (result != null){
+	        	AssociationHistory history = reconstructTask.reconstructHistory(speciesTree, geneTree, association, result, r);
+	        	MesquiteInteger duplications = new MesquiteInteger(0);
+	        	MesquiteInteger extinctions = new MesquiteInteger(0);
+	        	history.countDuplicationsExtinctions(speciesTree, geneTree, duplications, extinctions);
+	        	if (r != null)
+	        		r.setValue("Duplications " + duplications.getValue() + "; Extinctions: " + extinctions.getValue());
+	        	if (style == DUPSEXT)
+	        		result.setValue(duplications.getValue() + extinctions.getValue());
+	        	else if (style == DUPSONLY)
+	        		result.setValue(duplications.getValue());
+	        	else if (style == EXTONLY)
+	        		result.setValue(extinctions.getValue());
+	        }
+	}
+
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	} 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+	 public String getExplanation() {
+	return "Counts the number of duplication and extinction events for gene tree implied by a containing species tree";
+	 }
+
+/*.................................................................................................................*/
+	 public String getName() {
+	return "Gene Duplication-Extinction (gene tree)";
+	 }
+}
+
diff --git a/Source/mesquite/coalesce/DuplicationsExtinctionsSp/DuplicationsExtinctionsSp.java b/Source/mesquite/coalesce/DuplicationsExtinctionsSp/DuplicationsExtinctionsSp.java
new file mode 100644
index 0000000..3e59cbf
--- /dev/null
+++ b/Source/mesquite/coalesce/DuplicationsExtinctionsSp/DuplicationsExtinctionsSp.java
@@ -0,0 +1,128 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.DuplicationsExtinctionsSp;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a species tree by calculating how much lineage sorting is implied by a contained gene tree. */
+public class DuplicationsExtinctionsSp extends SpeciesTreeFit  {
+	MesquiteSubmenuSpec countOptionSubmenu;
+	static int DUPSEXT = 0;
+	static int DUPSONLY = 1;
+	static int EXTONLY = 2;
+	int style = DUPSEXT;
+	MesquiteString countOptionName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		countOptionSubmenu = addSubmenu(null, "Counting Mode (Dup./Ext.)");
+		addItemToSubmenu(null, countOptionSubmenu, "Count Duplications & Extinctions", makeCommand("countDE",  this));
+ 		addItemToSubmenu(null, countOptionSubmenu, "Count Duplications Only", makeCommand("countD",  this));
+ 		addItemToSubmenu(null, countOptionSubmenu, "Count Extinctions Only", makeCommand("countE",  this));
+		countOptionName = new MesquiteString("Count Duplications & Extinctions");
+		style = DUPSEXT;
+		countOptionSubmenu.setSelected(countOptionName);
+		return true;
+  	 }
+	/*.................................................................................................................*/
+	 public Snapshot getSnapshot(MesquiteFile file) { 
+ 	 	Snapshot temp = new Snapshot();
+ 	 	if (style== DUPSEXT)
+	 		temp.addLine("countDE"); 
+	 	else if (style== DUPSONLY)
+	 		temp.addLine("countD"); 
+	 	else if (style== EXTONLY)
+	 		temp.addLine("countE"); 
+	 	return temp;
+	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	   	 	 if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countDE")) {
+   	 		int current = style;
+   	 		style = DUPSEXT;
+      			countOptionName.setValue("Count Duplications & Extinctions");
+  	 		if (current!=style)
+   	 			parametersChanged();
+   	 	}
+      	 	else if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countD")) {
+   	 		int current = style;
+   	 		style = DUPSONLY;
+      			countOptionName.setValue("Count Duplications Only");
+  	 		if (current!=style)
+   	 			parametersChanged();
+   	 	}
+      	 	else if (checker.compare(this.getClass(), "Sets counting mode", null, commandName, "countE")) {
+   	 		int current = style;
+   	 		style = EXTONLY;
+   			countOptionName.setValue("Count Extinctions Only");
+   			if (current!=style)
+   	 			parametersChanged();
+   	 	}
+   		else {
+    			return  super.doCommand(commandName, arguments, checker);
+   		}
+   		return null;
+      	 }
+	   	/*.................................................................................................................*/
+ 	public void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r){
+	        if (result != null){
+	        	AssociationHistory history = reconstructTask.reconstructHistory(speciesTree, geneTree, association, result, r);
+	        	MesquiteInteger duplications = new MesquiteInteger(0);
+	        	MesquiteInteger extinctions = new MesquiteInteger(0);
+	        	history.countDuplicationsExtinctions(speciesTree, geneTree, duplications, extinctions);
+	        	if (r != null)
+	        		r.setValue("Duplications " + duplications.getValue() + "; Extinctions: " + extinctions.getValue());
+	        	if (style == DUPSEXT)
+	        		result.setValue(duplications.getValue() + extinctions.getValue());
+	        	else if (style == DUPSONLY)
+	        		result.setValue(duplications.getValue());
+	        	else if (style == EXTONLY)
+	        		result.setValue(extinctions.getValue());
+	        }
+	}
+
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+	 public String getExplanation() {
+	return "Counts the number of duplication and extinction events for species tree implied by a contained gene tree";
+	 }
+
+/*.................................................................................................................*/
+	 public String getName() {
+	return "Gene Duplication-Extinction (species tree)";
+	 }
+}
+
diff --git a/Source/mesquite/coalesce/InsertNode/32insertNode.gif b/Source/mesquite/coalesce/InsertNode/32insertNode.gif
new file mode 100644
index 0000000..d98be0e
Binary files /dev/null and b/Source/mesquite/coalesce/InsertNode/32insertNode.gif differ
diff --git a/Source/mesquite/coalesce/InsertNode/64insertNode.gif b/Source/mesquite/coalesce/InsertNode/64insertNode.gif
new file mode 100644
index 0000000..cc7aab6
Binary files /dev/null and b/Source/mesquite/coalesce/InsertNode/64insertNode.gif differ
diff --git a/Source/mesquite/coalesce/InsertNode/InsertNode.java b/Source/mesquite/coalesce/InsertNode/InsertNode.java
new file mode 100644
index 0000000..b7038d3
--- /dev/null
+++ b/Source/mesquite/coalesce/InsertNode/InsertNode.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.InsertNode;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class InsertNode extends TreeDisplayAssistantI {
+	public Vector extras;
+	 public String getFunctionIconPath(){
+   		 return getPath() + "insertNode.gif";
+   	 }
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		InsertToolExtra newPj = new InsertToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Insert Node";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Provides a tool with which to insert nodes along a branch.";
+   	 }
+}
+
+/* ======================================================================== */
+class InsertToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool insertTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	InsertNode insertModule;
+	AdjustableTree tree;
+	
+	public InsertToolExtra (InsertNode ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		insertModule = ownerModule;
+		insertTool = new TreeTool(this, "InsertNode", ownerModule.getPath(), "insertNode.gif", 7,7,"Insert Node", "This tool is used to insert a node along a branch.  The branch collapse (polytomy) tool can be used to remove nodes.");
+		insertTool.setTouchedCommand(MesquiteModule.makeCommand("insertNode",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(insertTool);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree instanceof AdjustableTree)
+			this.tree = (AdjustableTree)tree;
+		else
+			this.tree = null;
+	}
+	
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree instanceof AdjustableTree)
+			this.tree = (AdjustableTree)tree;
+		else
+			this.tree = null;
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		
+    	 	if (checker.compare(this.getClass(), "Inserts an unbranched node along a branch", "[node below which to insert]", commandName, "insertNode")) {
+  			if (tree == null)
+  				return null;
+  			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+  			if (branchFound >0 && MesquiteInteger.isCombinable(branchFound)) {
+  				double bL = tree.getBranchLength(branchFound);
+  					
+				 int n = tree.insertNode(branchFound, false);
+				 if (n<=0)
+				 	ownerModule.alert("Sorry, the node couldn't be inserted, possibly because there are already too many nodes");
+				 else {
+	  				if (MesquiteDouble.isCombinable(bL)) {
+					 	tree.setBranchLength(branchFound, bL/2.0, false);
+					 	tree.setBranchLength(n, bL/2.0, false);
+				 	 }
+				 	if (tree instanceof Listenable)
+				 		((Listenable)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+				 	 treeDisplay.pleaseUpdate(true);
+				 }
+   			}
+ 	 	}
+ 		return null;
+ 	}
+	public void turnOff() {
+		insertModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+	
+
+
diff --git a/Source/mesquite/coalesce/InsertNode/insertNode.gif b/Source/mesquite/coalesce/InsertNode/insertNode.gif
new file mode 100644
index 0000000..41a0a07
Binary files /dev/null and b/Source/mesquite/coalesce/InsertNode/insertNode.gif differ
diff --git a/Source/mesquite/coalesce/LineageWidth/32adjustWidths.gif b/Source/mesquite/coalesce/LineageWidth/32adjustWidths.gif
new file mode 100644
index 0000000..ea902ea
Binary files /dev/null and b/Source/mesquite/coalesce/LineageWidth/32adjustWidths.gif differ
diff --git a/Source/mesquite/coalesce/LineageWidth/64adjustWidths.gif b/Source/mesquite/coalesce/LineageWidth/64adjustWidths.gif
new file mode 100644
index 0000000..c2229ab
Binary files /dev/null and b/Source/mesquite/coalesce/LineageWidth/64adjustWidths.gif differ
diff --git a/Source/mesquite/coalesce/LineageWidth/LineageWidth.java b/Source/mesquite/coalesce/LineageWidth/LineageWidth.java
new file mode 100644
index 0000000..6a3a316
--- /dev/null
+++ b/Source/mesquite/coalesce/LineageWidth/LineageWidth.java
@@ -0,0 +1,234 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.coalesce.LineageWidth;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class LineageWidth extends TreeDisplayAssistantI {
+	public Vector extras;
+	public String getFunctionIconPath(){
+		return getPath() + "adjustWidths.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		addMenuItem("Set all lineage width scaling factors...", makeCommand("setAllWidths",  this));
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public String getExpectedPath(){
+		return getPath() + "adjustWidths.gif";
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		WidthsToolExtra newPj = new WidthsToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the scaling factor of lineage widths for all branches", "[width scale]", commandName, "setAllWidths")) {
+			pos.setValue(0);
+			double w = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(w)){
+				//w = MesquiteDouble.queryDouble(containerOfModule(), "Set scaling factor of all lineages", "Set scaling factor for all lineages to", 1.0);
+				MesquiteDouble dub = new MesquiteDouble(1.0);
+				if (!QueryDialogs.queryDouble(containerOfModule(), "Set scaling factor of all lineages", "Set scaling factor for all lineages to", null, dub))
+					return null;
+				w = dub.getValue();
+			}
+			if (MesquiteDouble.isCombinable(w) || MesquiteDouble.isUnassigned(w)) {
+
+				Enumeration e = extras.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					WidthsToolExtra tCO = (WidthsToolExtra)obj;
+					tCO.setAllWidths(w);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Adjust scaling factor of lineage widths";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to adjust the scaling factor used for lineage widths in a tree window.";
+	}
+}
+
+/* ======================================================================== */
+class WidthsToolExtra extends TreeDisplayDrawnExtra implements Commandable  {
+	public TreeTool colorTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	LineageWidth widthsModule;
+	Tree tree;
+	NameReference widthNameReference = NameReference.getNameReference("width");
+	DoubleArray widths = null;
+	MiniNumberEditor miniEditor;
+	boolean editorOn = false;
+	int editorNode = -1;
+	public WidthsToolExtra (LineageWidth ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		widthsModule = ownerModule;
+		colorTool = new TreeTool(this, "LineageWidth", ownerModule.getPath(), "adjustWidths.gif", 9,7,"Adjust scaling factor of lineage widths", "This tool adjusts the scaling factor of lineage widths of a branch.  This scaling is multiplied by the designated lineage width (e.g., effective population sizes) to determine the final lineage width for that branch.  When a branch is touched, a small text editing box appears in which a new branch width scaling factor can be entered; touching the lit [...]
+		colorTool.setTouchedCommand(MesquiteModule.makeCommand("setWidths",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(colorTool);
+		}
+	}
+	/*....................................................................................................*/
+	private void drawWidths (Tree tree, int node, Graphics g) {
+		double w =widths.getValue(node);
+		if (MesquiteDouble.isCombinable(w)) {
+			int nodeX = treeDisplay.getTreeDrawing().x[node];
+			int nodeY = treeDisplay.getTreeDrawing().y[node];
+
+			g.drawString(MesquiteDouble.toString(w), nodeX,nodeY);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawWidths(tree, d, g);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		this.tree = tree;
+		if (editorOn) {
+			if (tree.nodeExists(editorNode))
+				miniEditor.setLocation(treeDisplay.getTreeDrawing().x[editorNode], treeDisplay.getTreeDrawing().y[editorNode]);
+			else hideMiniEditor();
+		}
+		if (widths!=null) {
+			Color c = g.getColor();
+			g.setColor(Color.green);
+			drawWidths(tree, drawnRoot, g);
+			if (c!=null) g.setColor(c);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+		if (tree != null)
+			widths = tree.getWhichAssociatedDouble(widthNameReference);
+	}
+
+	/*.................................................................................................................*/
+	private   void setLineageWidths(MesquiteTree tree, int node, double w) {
+		tree.setAssociatedDouble(widthNameReference, node, w, true);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			setLineageWidths(tree, d, w);
+	}
+	/*.................................................................................................................*/
+	public   void setAllWidths(double w) {
+		if (tree instanceof MesquiteTree) {
+			if (((MesquiteTree)tree).getWhichAssociatedDouble(widthNameReference)==null)
+				((MesquiteTree)tree).makeAssociatedDoubles("width");
+			setLineageWidths((MesquiteTree)tree, tree.getRoot(), w);
+			((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		//remember which colored
+		return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	private void setWidth(MesquiteTree tree, int node, double w){
+		if (tree.getWhichAssociatedDouble(widthNameReference)==null)
+			tree.makeAssociatedDoubles("width");
+		tree.setAssociatedDouble(widthNameReference, node, w, true);
+		tree.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+	/*.................................................................................................................*/
+	private void setMiniEditor(int node, int x,int y){
+		Tree t = treeDisplay.getTree();
+		if (t==null)
+			return;
+		editorNode = node;
+		if (miniEditor == null) {
+			miniEditor = new MiniNumberEditor(ownerModule, ownerModule.makeCommand("acceptWidth", this));
+			addPanelPlease(miniEditor);
+		}
+		miniEditor.setLocation(treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node]);
+		miniEditor.setNumber(tree.getAssociatedDouble(widthNameReference, node));
+		miniEditor.setVisible(true);
+		editorOn = true;
+	}
+	private void hideMiniEditor(){
+		miniEditor.setVisible(false);
+		editorOn = false;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		Tree trt = treeDisplay.getTree();
+		MesquiteTree t = null;
+		if (trt instanceof MesquiteTree)
+			t = (MesquiteTree)trt;
+
+		if (checker.compare(this.getClass(), "Sets the lineage width scaling factor (i.e., multiplier of population size) of the branch in the tree", "[lineage width scaling factor]", commandName, "acceptWidth")){
+			if (t==null)
+				return null;
+			if (editorOn) {
+				double d = MesquiteDouble.fromString(arguments);
+				if (MesquiteDouble.isCombinable(d) || d == MesquiteDouble.unassigned) {
+					setWidth(t, editorNode, d);
+					MesquiteModule mb = ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+					mb.doCommand("treeEdited", null, checker);
+				}
+			}
+			hideMiniEditor();
+		}
+		else if (checker.compare(this.getClass(), "Causes a mini text editor to appear in which lineage width scaling factor of the branch can be entered", "[branch number] [x coordinate touched] [y coordinate touched]", commandName, "setWidths")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+
+			setMiniEditor(node, x,y);
+		}
+		return null;
+	}
+	public void turnOff() {
+		widthsModule.extras.removeElement(this);
+		widthNameReference=null;
+		super.turnOff();
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/coalesce/LineageWidth/adjustWidths.gif b/Source/mesquite/coalesce/LineageWidth/adjustWidths.gif
new file mode 100644
index 0000000..6d5fab8
Binary files /dev/null and b/Source/mesquite/coalesce/LineageWidth/adjustWidths.gif differ
diff --git a/Source/mesquite/coalesce/NeutralCoalescence/NeutralCoalescence.java b/Source/mesquite/coalesce/NeutralCoalescence/NeutralCoalescence.java
new file mode 100644
index 0000000..1052b99
--- /dev/null
+++ b/Source/mesquite/coalesce/NeutralCoalescence/NeutralCoalescence.java
@@ -0,0 +1,392 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.NeutralCoalescence;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+/* ======================================================================== */
+public class NeutralCoalescence extends CoalescerObed {  //coalescer
+	RandomBetween rNG;
+	ExponentialDistribution waitingTime;
+	int basePopulationSize = 10000;
+	CoalescedNode[] thisGeneration, previousGeneration, temp;
+	long initialSeed = System.currentTimeMillis(); 
+	MesquiteBoolean exponentialApprox;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		rNG= new RandomBetween(initialSeed);
+ 		waitingTime = new ExponentialDistribution(initialSeed);
+ 		exponentialApprox = new MesquiteBoolean(true);
+ 		MesquiteSubmenuSpec csub = addSubmenu(null, "Coalescence simulation");
+ 		if (getHiredAs() != CoalescerObed.class)
+ 			addItemToSubmenu(null, csub, "Set Ne...", makeCommand("setEffective", this));
+ 		addCheckMenuItemToSubmenu(null, csub, "Exponential approximation", makeCommand("toggleExponential", this), exponentialApprox);
+ 		if (!MesquiteThread.isScripting()){
+				int eff = MesquiteInteger.queryInteger(containerOfModule(), "Population Size", "Set Effective population size", basePopulationSize, 10, 1000000000, false);
+				if (MesquiteInteger.isCombinable(eff))
+					basePopulationSize = eff;
+ 		}
+ 		return true;
+  	 }
+  	 
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+ 		if (getHiredAs() != CoalescerObed.class)
+  	 		temp.addLine("setEffective " + basePopulationSize);
+		temp.addLine("toggleExponential " + exponentialApprox.toOffOnString());
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the effective population size for coalescence simulations", "[effective population size]", commandName, "setEffective")) {
+    	 		int eff = MesquiteInteger.fromFirstToken(arguments, pos);
+    	 		if (!MesquiteInteger.isCombinable(eff))
+				eff = MesquiteInteger.queryInteger(containerOfModule(), "Population Size", "Set Effective population size", basePopulationSize);
+    	 		if (!MesquiteInteger.isCombinable(eff))
+    	 			return null;
+	    	 	if (basePopulationSize != eff) {
+	    	 		basePopulationSize = eff;
+ 				parametersChanged(); 
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether to use the exponential approximation or to simulate full population with individual genes", "[on = use exponential approximation; off]", commandName, "toggleExponential")) {
+    	 		boolean current = exponentialApprox.getValue();
+    	 		if (StringUtil.blank(arguments)) {
+    	 			exponentialApprox.setValue(!current);
+	    	 		parametersChanged();
+    	 		}
+    	 		else {
+	    	 		exponentialApprox.toggleValue(parser.getFirstToken(arguments));
+	    	 		if (current!=exponentialApprox.getValue()) {
+	    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.....................................UTILITIES.........................................................*/
+   	public int getPopulationSize(){
+   		return basePopulationSize;
+   	}
+   	public void setPopulationSize(int pS){
+   		basePopulationSize = pS;
+   	}
+	boolean warnPopSizeSmall = true;
+	boolean firstWarning = true;
+	int[] ancestorChoices;
+	int[] ancestorChoicesSummary;
+	int[] ancestorChoicesCounts;
+	
+
+	void recordChoice(int ancestorChosen){
+		int pos = -1;
+		int i;
+		for (i=0; i<ancestorChoicesSummary.length && pos<0 && ancestorChoicesSummary[i]!= MesquiteInteger.unassigned; i++)
+			if (ancestorChoicesSummary[i]==ancestorChosen)
+				pos = i;
+		if (pos <0 && i<ancestorChoicesSummary.length) {
+			ancestorChoicesSummary[i]=ancestorChosen;
+			ancestorChoicesCounts[i]=1;
+		}
+		else
+			ancestorChoicesCounts[pos]++;
+	}
+	boolean warnNoMatch = true;
+	boolean warnNoMotherError = true;
+	/*.................................................................................................................*/
+   	private void coalesceIndividualModel(MesquiteTree tree,  int[] containing, int whichContaining, int populationSize, long generations, MesquiteLong seed, boolean untilOne) {
+		
+		if (ancestorChoices==null|| ancestorChoices.length < tree.getNumNodeSpaces()) {
+			ancestorChoices = new int[tree.getNumNodeSpaces()]; 
+			ancestorChoicesSummary = new int[tree.getNumNodeSpaces()]; 
+			ancestorChoicesCounts = new int[tree.getNumNodeSpaces()]; 
+		}
+			
+		for (int i=0; i<ancestorChoicesSummary.length; i++) {
+			ancestorChoicesSummary[i]=MesquiteInteger.unassigned;
+			ancestorChoicesCounts[i] = 0;
+			ancestorChoices[i] = -1;
+		}
+		
+		int numGenerations = 0;
+		while (IntegerArray.moreThanOneOccurrence(containing, whichContaining) && (numGenerations<generations || untilOne) ) {
+			for (int i=0; i<ancestorChoicesSummary.length && ancestorChoicesSummary[i]!=MesquiteInteger.unassigned; i++) {
+				ancestorChoicesSummary[i]=MesquiteInteger.unassigned;
+				ancestorChoicesCounts[i] = 0;
+			}
+			for (int i=0; i<containing.length; i++){ //adding to branch lengths
+				if (containing[i] == whichContaining)  //this is a gene tree node contained in the populations
+					tree.setBranchLength(i, tree.getBranchLength(i, 0)+1, false);
+			}			
+			for (int i=0; i<containing.length && i<ancestorChoices.length; i++){ //choosing ancestor randomly
+				if (containing[i] == whichContaining){  //this is a gene tree node contained in the populations
+					ancestorChoices[i] = rNG.randomIntBetween(0, populationSize-1);  //choosing an ancestor
+					recordChoice(ancestorChoices[i]);
+				}
+				else
+					ancestorChoices[i]=-1;
+			}	
+			for (int c=0; c<ancestorChoicesSummary.length && ancestorChoicesSummary[c]!=MesquiteInteger.unassigned; c++){ //looking for ancestor numbers
+				int numThatChoseThis = ancestorChoicesCounts[c];
+				if (numThatChoseThis>1){
+					if (numThatChoseThis==2){
+						// coalesce two that chose this
+						int ancestorChoice = ancestorChoicesSummary[c];
+						int i = IntegerArray.indexOf(ancestorChoices, ancestorChoice);
+						int oldContaining = containing[i];
+						containing[i]=0;
+						ancestorChoices[i] = -1;
+						int j = IntegerArray.indexOf(ancestorChoices, ancestorChoice);
+						containing[j]=0;
+						ancestorChoices[j] = -1;
+						double iLength = tree.getBranchLength(i, 0);
+						double jLength = tree.getBranchLength(j, 0);
+						tree.moveBranch(i, j, false);
+						tree.setBranchLength(i, iLength, false);
+						tree.setBranchLength(j, jLength, false);
+						if (tree.nodeExists(tree.motherOfNode(i))){
+							tree.setBranchLength(tree.motherOfNode(i), 0, false);
+							containing[tree.motherOfNode(i)]=whichContaining;
+							ancestorChoices[tree.motherOfNode(i)]=-1;
+						}
+						else {
+							if (warnNoMotherError){
+								String w = "There has been an error in the Neutral Coalescence simulation.  It may be due to a contained taxon (e.g., haplotype) occurring in more than one containing taxon (e.g., species), which is not allowed in the current version of the simulation.  Details are written in the Mesquite Log file";
+								w+="  This error message will not be repeated during this calculation.";
+								discreetAlert( w);
+								logln("Details of Neutral Coalescence error: mother doesn't exist (from node " + i + " oldContaining " + oldContaining + "  whichContaining " + whichContaining + " containing.length " + containing.length + " ancestorChoices.length " + ancestorChoices.length + "  ancestorChoice " + ancestorChoice + " c " + c + ") tree " + tree.writeTreeWithNodeNumbers());
+								logln("  ancestor choices " + IntegerArray.toString(ancestorChoices));
+							}
+							warnNoMotherError = false;
+							return;
+						}
+					}
+					else {
+						// coalesce the first two that chose this
+						int ancestorChoice = ancestorChoicesSummary[c];
+						int i = IntegerArray.indexOf(ancestorChoices, ancestorChoice);
+						containing[i]=0;
+						ancestorChoices[i] = -1;
+						int j = IntegerArray.indexOf(ancestorChoices, ancestorChoice);
+						containing[j]=0;
+						ancestorChoices[j] = -1;
+						double iLength = tree.getBranchLength(i, 0);
+						double jLength = tree.getBranchLength(j, 0);
+						tree.moveBranch(i, j, false);
+						tree.setBranchLength(i, iLength, false);
+						tree.setBranchLength(j, jLength, false);
+						int newNode = tree.motherOfNode(i);
+						if (!tree.nodeExists(newNode))
+								MesquiteMessage.warnProgrammer("oops newNode doesn't exist ");
+						for (int k=2; k<numThatChoseThis;k++){
+							j = IntegerArray.indexOf(ancestorChoices, ancestorChoice);
+							if (j<0)
+								MesquiteMessage.warnProgrammer("oops index negative ");
+							else {
+								containing[j]=0;
+								ancestorChoices[j] = -1;
+								jLength = tree.getBranchLength(j, 0);
+								tree.moveBranch(j, newNode, false);
+								int new2Node = tree.motherOfNode(newNode);
+								tree.collapseBranch(newNode, false);
+								tree.setBranchLength(j, jLength, false);
+								newNode = new2Node;
+							}
+						}
+						tree.setBranchLength(newNode, 0, false);
+						containing[newNode]=whichContaining;
+						ancestorChoices[newNode]=-1;
+					}
+				}
+			}	
+			numGenerations++;
+		}
+		if (!IntegerArray.moreThanOneOccurrence(containing, whichContaining) &&  (numGenerations<generations) && MesquiteLong.isCombinable(generations)) {
+				int lone  = IntegerArray.indexOf(containing, whichContaining);
+				if (tree.nodeExists(lone))
+					tree.setBranchLength(lone, tree.getBranchLength(lone, 0) + (generations-numGenerations +1), false);
+		}
+			
+		seed.setValue(rNG.nextLong());
+   	}
+	/*.................................................................................................................*/
+   	private long nChoose2(int n){
+   		return n*(n-1)/2;
+   	}
+   	private int matchingIndex(int[] containing, int whichContaining, int iTH){
+   		int count =0;
+   		for (int i=0; i<containing.length; i++){
+   			if (containing[i]==whichContaining){
+   				if (iTH == count)
+   					return i;
+   				count++;
+   			}
+   		}
+   		return -1;
+   	}
+
+	/*.................................................................................................................*/
+   	private void coalesceQuick(MesquiteTree tree,  int[] containing, int whichContaining, int populationSize, long generations, MesquiteLong seed, boolean untilOne) {
+		int numContained = IntegerArray.countSame(containing, whichContaining); //number contained gene copies in whichContaining node
+
+		long numGenerations = 0;
+		while (IntegerArray.moreThanOneOccurrence(containing, whichContaining) && (numGenerations<generations || untilOne) ) {
+			double wait = waitingTime.nextExponential(populationSize*1.0/nChoose2(numContained));
+			if (numGenerations + (long)wait <generations || untilOne){  //next waiting time is still within range allowed
+				for (int i=0; i<containing.length; i++){ //adding to branch lengths
+					if (containing[i] == whichContaining)  //this is a gene tree node contained in the populations
+						tree.setBranchLength(i, tree.getBranchLength(i, 0)+(double)((long)wait), false);
+				}			
+				// coalesce two
+				int iTH = rNG.randomIntBetween(0, numContained-1);
+				int jTH = rNG.randomIntBetween(0, numContained-1);
+				while (jTH==iTH)
+					jTH = rNG.randomIntBetween(0, numContained-1);
+					
+				int i = matchingIndex(containing, whichContaining, iTH);
+				int j = matchingIndex(containing, whichContaining, jTH);
+				if (i<0 || j < 0) {
+					if (warnNoMatch){
+						String w = "There has been an error in the Neutral Coalescence simulation.  It may be due to a contained taxon (e.g., haplotype) occurring in more than one containing taxon (e.g., species), which is not allowed in the current version of the simulation.  Details are written in the Mesquite Log file";
+						w+="  This error message will not be repeated during this calculation.";
+						discreetAlert( w);
+						logln("Details of Neutral Coalescence error: matching index not found (from node " + i + "  whichContaining " + whichContaining + " containing.length " + containing.length + ") tree " + tree.writeTreeWithNodeNumbers());
+					}
+					warnNoMatch = false;
+					return;
+				}
+				containing[i]=0;
+				containing[j]=0;
+
+				double iLength = tree.getBranchLength(i, 0);
+				double jLength = tree.getBranchLength(j, 0);
+				tree.moveBranch(i, j, false);
+				numContained--;
+				tree.setBranchLength(i, iLength, false);
+				tree.setBranchLength(j, jLength, false);
+				if (tree.nodeExists(tree.motherOfNode(i))){
+					tree.setBranchLength(tree.motherOfNode(i), 0, false);
+					containing[tree.motherOfNode(i)]=whichContaining;
+				}
+				else {
+					if (warnNoMotherError){
+						String w = "There has been an error in the Neutral Coalescence simulation.  It may be due to a contained taxon (e.g., haplotype) occurring in more than one containing taxon (e.g., species), which is not allowed in the current version of the simulation.  Details are written in the Mesquite Log file";
+						w+="  This error message will not be repeated during this calculation.";
+						discreetAlert( w);
+						logln("Details of Neutral Coalescence error: mother doesn't exist (from node " + i  + "  whichContaining " + whichContaining + " containing.length " + containing.length + ") tree " + tree.writeTreeWithNodeNumbers());
+						logln("  ancestor choices " + IntegerArray.toString(ancestorChoices));
+					}
+					warnNoMotherError = false;
+					return;
+				}
+			}
+			else {
+				for (int i=0; i<containing.length; i++){ //adding to branch lengths
+					if (containing[i] == whichContaining)  //this is a gene tree node contained in the populations
+						tree.setBranchLength(i, tree.getBranchLength(i, 0)+(double)(generations-numGenerations), false);
+				}
+			}			
+			numGenerations+= (long)wait;
+		}
+		if (numGenerations<generations) { // didn't exceed waiting time; thus must have ended loop because it went to one
+				for (int i=0; i<containing.length; i++){ //adding to branch lengths
+					if (containing[i] == whichContaining)  //this is a gene tree node contained in the populations
+						tree.setBranchLength(i, tree.getBranchLength(i, 0)+(double)(generations-numGenerations), false);
+				}
+		}
+		seed.setValue(waitingTime.nextLong());
+   	}
+	int numWarnings =0;
+	/*.................................................................................................................*/
+	/**Passed as arguments are: 
+		- the contained tree, 
+		- an integer array indicating for each of the nodes in the tree what node in the containing tree contains it 
+		- which node of the containing tree one is coalescing within
+		- the Ne adjustment, i.e. the multiplier of the base population size (e.g., from the branch width)
+		- the number of generations allowed for coalescence.
+		- the random number seed
+		- whether coalescence is to go to completion, or merely for the specified number of generations
+		*/
+   	public void coalesce(MesquiteTree tree,  int[] containing, int whichContaining, double neAdjustment, long generations, MesquiteLong seed, boolean untilOne) {
+		if (generations ==0 && !untilOne)
+			return;
+		if (tree == null)
+			return;
+		if (containing == null)
+			return;
+		if (!MesquiteLong.isCombinable(generations))
+			untilOne = true;
+		int populationSize;
+		if (neAdjustment == 1.0)
+			populationSize = (int)basePopulationSize;
+		else
+			populationSize = (int)(basePopulationSize * neAdjustment);
+		//if populationSize is below geneCopies, use exactly the number of gene copies
+		//if ne is not combinable or not positive, use defaultPopSize
+		rNG.setSeed(seed.getValue());
+		waitingTime.setSeed(seed.getValue());
+
+		int numContained = IntegerArray.countSame(containing, whichContaining);
+		if (numContained> populationSize) {
+			if (firstWarning) {
+				firstWarning = false;
+				if (MesquiteThread.isScripting() || !AlertDialog.query(containerOfModule(), "Pop. size too small", "Population size too small for number of gene copies; will be reset (Ne = " + populationSize + ", # copies = " + numContained + ").  Do you want to continue to be warned of this in the log window?", "Yes", "No"))
+					warnPopSizeSmall = false;
+			}
+			else if (warnPopSizeSmall && numWarnings++<5)
+				MesquiteMessage.warnProgrammer("Population size too small for number of gene copies; will be reset (ne = " + populationSize + ", # copies = " + numContained + ")");
+			else if (warnPopSizeSmall && numWarnings==6)
+				MesquiteMessage.warnProgrammer("Population size too small for number of gene copies; will be reset.  Subsequent warnings will be suppressed.");
+			populationSize = numContained;
+		}
+		if (!exponentialApprox.getValue())
+			coalesceIndividualModel(tree, containing, whichContaining, populationSize, generations, seed, untilOne);
+		else
+			coalesceQuick(tree, containing, whichContaining, populationSize, generations, seed, untilOne);
+   	}
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Neutral Coalescence";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs neutral coalescence within a population by a simple model of a neutral gene with constant population size."
+ 		+"Remembers a tree of nodes, with branch lengths assigned according to generation of coalescence.  The default population size is 10000." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		return "Base population size: " + basePopulationSize;
+   	 }
+}
+
+
diff --git a/Source/mesquite/coalesce/RecCoalescenceHistory/RecCoalescenceHistory.java b/Source/mesquite/coalesce/RecCoalescenceHistory/RecCoalescenceHistory.java
new file mode 100644
index 0000000..289585b
--- /dev/null
+++ b/Source/mesquite/coalesce/RecCoalescenceHistory/RecCoalescenceHistory.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.RecCoalescenceHistory;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+/* ======================================================================== */
+public class RecCoalescenceHistory extends ReconstructAssociation {
+	MesquiteBoolean reconstruct = new MesquiteBoolean(true); //currently cannot be set false; option buggy and not available
+	MesquiteBoolean unrootedContained = new MesquiteBoolean(false);
+	MesquiteBoolean allowResolve = new MesquiteBoolean(true);
+	MesquiteBoolean  useBranchLengths = new MesquiteBoolean(true);
+	Vector rerootVectors;
+	static final int maxRerootStores = 20;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		
+ 		if (!MesquiteThread.isScripting()){
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog checkBoxDialog = new ExtensibleDialog(containerOfModule(), "Contained (gene) tree interpetation",buttonPressed);
+			checkBoxDialog.addLargeOrSmallTextLabel ("Options for interpreting contained tree (e.g., gene tree within species or population history.)");
+			Checkbox ur = checkBoxDialog.addCheckBox("Treat contained as unrooted", unrootedContained.getValue());
+			Checkbox polyAutoRes = checkBoxDialog.addCheckBox("Contained polytomies auto-resolve", allowResolve.getValue());
+			Checkbox useLen = checkBoxDialog.addCheckBox("Use Branch lengths of Contained tree", useBranchLengths.getValue());
+			
+			checkBoxDialog.completeAndShowDialog(true);
+			
+			if (buttonPressed.getValue()==0) {
+				unrootedContained.setValue(ur.getState());
+				allowResolve.setValue(polyAutoRes.getState());
+				useBranchLengths.setValue(useLen.getState());
+			}
+			checkBoxDialog.dispose();
+ 		}
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Reconstruct Coalescence");
+		addCheckMenuItemToSubmenu( null, mss, "Treat contained as unrooted", makeCommand("toggleUnrooted", this), unrootedContained);
+		addCheckMenuItemToSubmenu( null, mss, "Contained polytomies auto-resolve", makeCommand("toggleResolve", this), allowResolve);
+		addCheckMenuItemToSubmenu( null, mss, "Use Branch lengths of Contained", makeCommand("toggleUseLengths", this), useBranchLengths);
+		rerootVectors = new Vector();
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		//temp.addLine("toggleReconstruct " + reconstruct.toOffOnString()); //this is currently buggy and not available
+		temp.addLine("toggleUnrooted " + unrootedContained.toOffOnString());
+		temp.addLine("toggleResolve " + allowResolve.toOffOnString());
+		temp.addLine("toggleUseLengths " + useBranchLengths.toOffOnString());
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets whether or not the containing tree reconstructor attempts to reconstruct ancestral containing nodes, or finds containing node information already in the history", "[on = reconstruct; off]", commandName, "toggleReconstruct")) {
+    	 		boolean current = reconstruct.getValue(); //this is currently buggy and not available
+    	 		reconstruct.toggleValue(parser.getFirstToken(arguments));
+    	 		if (current!=reconstruct.getValue()) {
+    	 			discreetAlert( "There are bugs in the use of existing gene ancestor locations; reconstruction seems to be working well, but it places gene ancestors as shallowly as possible.");
+    	 			parametersChanged();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not the contained tree is treated as unrooted", "[on = unrooted; off]", commandName, "toggleUnrooted")) {
+    	 		boolean current = unrootedContained.getValue();
+    	 		if (StringUtil.blank(arguments)) {
+    	 			unrootedContained.setValue(!current);
+	    	 		parametersChanged();
+    	 		}
+    	 		else {
+	    	 		unrootedContained.toggleValue(parser.getFirstToken(arguments));
+	    	 		if (current!=unrootedContained.getValue()) {
+	    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not any branch lengths of the contained tree are used in fitting it into the containing tree", "[on = use lengths; off]", commandName, "toggleUseLengths")) {
+    	 		boolean current = useBranchLengths.getValue();
+    	 		if (StringUtil.blank(arguments)) {
+    	 			useBranchLengths.setValue(!current);
+	    	 		parametersChanged();
+    	 		}
+    	 		else {
+	    	 		useBranchLengths.toggleValue(parser.getFirstToken(arguments));
+	    	 		if (current!=useBranchLengths.getValue()) {
+	    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not polytomies in the contained tree are auto-resolved to minimize deep coalescences", "[on = auto-resolve; off]", commandName, "toggleResolve")) {
+    	 		boolean current = allowResolve.getValue();
+    	 		if (StringUtil.blank(arguments)) {
+    	 			allowResolve.setValue(!current);
+	    	 		parametersChanged();
+    	 		}
+    	 		else {
+	    	 		allowResolve.toggleValue(parser.getFirstToken(arguments));
+	    	 		if (current!=allowResolve.getValue()) {
+	    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+
+	/*_________________________________________________*/
+	public void calculateHistoryCost(Tree containing, MesquiteTree contained, TaxaAssociation association, MesquiteNumber cost, MesquiteString resultString){
+		if (cost == null)
+			return;
+		reconstructHistory(containing, contained, association, cost, resultString);
+	}
+
+	/*_________________________________________________*/
+	RerootStore getRerootings(MesquiteTree tree){
+		//go through stored rerootings to find same one
+		
+		for (int i=0; i<rerootVectors.size(); i++) {
+			RerootStore rs = (RerootStore)rerootVectors.elementAt(i);
+			if (rs.sameTree(tree))
+				return rs;
+		}
+		RerootStore rerootings = new RerootStore(tree.getTaxa(), tree.writeTree());
+		tree.makeAllRootings(tree.getRoot(), rerootings);
+		for (int i = 0; i<rerootings.size(); i++){
+			MesquiteTree cr = (MesquiteTree)rerootings.getTree(i);
+			cr.setAllBranchLengths(MesquiteDouble.unassigned, false);
+		}
+		rerootVectors.addElement(rerootings);
+		if (rerootVectors.size()>=maxRerootStores) {
+			RerootStore rerootings0 = (RerootStore)rerootVectors.elementAt(0);
+			rerootings0.dispose();
+			rerootVectors.removeElement(rerootings0);
+		}
+		return rerootings;
+		
+	}
+	/*_________________________________________________*/
+	/** reconstructs history of contained tree within containing.  Contained tree must be free to be modified; hence send in a clone instead of the original!*/
+	public AssociationHistory reconstructHistory(Tree containing, MesquiteTree contained, TaxaAssociation association, MesquiteNumber cost, MesquiteString resultString){
+		if (containing==null || contained==null || association == null) {
+			if (resultString!=null)
+				resultString.setValue("Association history not reconstructed (some information not supplied to calculating module)");
+			return null;
+		}
+		if (contained!=null)
+			contained.deselectAll();
+			
+        	/*tree coming in is gene tree, hence need to find out for each taxon in gene tree if it has more than one associate.  If so, then 
+        	can't do calculations since gene copy in more than one species*/
+		for (int i=0; i< contained.getTaxa().getNumTaxa(); i++){
+			Taxon tax = contained.getTaxa().getTaxon(i);
+			if (association.getNumAssociates(tax)>1){
+				if (resultString!=null)
+					resultString.setValue("Contained history not calculated (some contained taxa are in more than one containing taxon)");
+				if (cost !=null)
+					cost.setToUnassigned();
+				return null;
+			}
+		}
+		
+		MesquiteInteger count = new MesquiteInteger(0);  //for counting deep coalescences
+		
+		if (unrootedContained.getValue()){  //treating contained tree as unrooted
+			AssociationHistory resultHistory = null;
+			int minCount = MesquiteInteger.unassigned;
+			
+			//Get rerootings of contained tree.  If contained tree was recently seen, rerootings don't need to be recalculated.
+			RerootStore rerootings = getRerootings(contained);
+			
+			//Reconstruct History for all rerootings and choose best
+			MesquiteTree bestTree = null;
+			for (int i = 0; i<rerootings.size(); i++){
+				AssociationHistory history = new AssociationHistory();
+				MesquiteTree containedRerooted = (MesquiteTree)rerootings.getTree(i);
+				history.setTrees(containing, containedRerooted);
+				count.setValue(0);
+				if (containedRerooted!=null)
+					containedRerooted.deselectAll();
+				calcContainedNodes(history, containing, containedRerooted, association, containing.getRoot(), false, count);
+			
+				if (!MesquiteInteger.isCombinable(minCount) || count.getValue()<minCount) {
+					minCount = count.getValue();
+					resultHistory = history; //just takes first one!
+					bestTree = containedRerooted;
+					if (cost!=null)
+						cost.setValue(minCount);
+				}
+			}
+			if (bestTree!=null)
+				contained.setToClone(bestTree);
+			if (resultString!=null && cost!=null)
+				resultString.setValue("Deep coalescence cost: " + cost);
+			return resultHistory;
+		}
+		else if (reconstruct.getValue()) { //treating contained tree as rooted; reconstruct its placement in containing tree
+			if (!useBranchLengths.getValue()){
+				contained.setAllBranchLengths(MesquiteDouble.unassigned, false);
+			}
+			AssociationHistory history = new AssociationHistory();
+			history.setTrees(containing, contained);
+			calcContainedNodes(history, containing, contained, association, containing.getRoot(), containing.hasBranchLengths() && contained.hasBranchLengths() && useBranchLengths.getValue(), count);
+			if (cost!=null)
+				cost.setValue(count.getValue());
+			if (resultString!=null && cost!=null)
+				resultString.setValue("Deep coalescence cost: " + cost);
+			return history;
+		}
+		else {  //treating contained tree as rooted; look for its stored placement in containing tree (stored in "location" stored inside contained tree.  NOT AVAILABLE as option
+			AssociationHistory history = new AssociationHistory();
+			history.setTrees(containing, contained);
+			LongArray locations =contained.getWhichAssociatedLong(NameReference.getNameReference("location"));
+			if (locations!=null) {
+				recoverContainedNodes(history, locations, contained, contained.getRoot());
+				reconnect(history, containing,contained, association, containing.getRoot());
+			}
+			else {
+				calcContainedNodes(history, containing, contained, association, containing.getRoot(), containing.hasBranchLengths() && contained.hasBranchLengths() && useBranchLengths.getValue(), count);
+			}
+			if (cost!=null)
+				cost.setValue(count.getValue());
+			if (resultString!=null && cost!=null)
+				resultString.setValue("Deep coalescence cost: " + cost);
+			
+			return history;
+		}
+	}
+	/*_________________________________________________*/
+	/** this method recurses up the contained (gene?) tree to help reconnect a contained tree which already has location information, into the containing tree.  NOT AVAILABLE yet*/
+	private void recoverContainedNodes(AssociationHistory history, LongArray locations, Tree containedTree, int node) {
+				int loc = (int)locations.getValue(node);
+				if (loc>0 && MesquiteInteger.isCombinable(loc))
+					history.setContainedNode(loc, node);
+				for (int d = containedTree.firstDaughterOfNode(node); containedTree.nodeExists(d); d = containedTree.nextSisterOfNode(d)) 
+					recoverContainedNodes(history, locations,containedTree, d);
+	}
+	Taxon[] containedHere;
+	/*_________________________________________________*/
+	/** this method recurses up the containing (species?) tree and calculates how the contained tree fits into it */
+	private void calcContainedNodes(AssociationHistory history, Tree containingTree, AdjustableTree containedTree, TaxaAssociation association, int node, boolean useDepths, MesquiteInteger count) {
+		if (containingTree.nodeExists(node)) {
+		
+			if (containingTree.nodeIsTerminal(node)) { //containing node is terminal: simply set contained nodes within it
+				int taxonNum = containingTree.taxonNumberOfNode(node);
+				Taxon terminalTaxon =containingTree.getTaxa().getTaxon(taxonNum); //which containing terminal taxon are we at?
+				if (containedHere==null ||  containedHere.length < containedTree.getTaxa().getNumTaxa())
+					containedHere = new Taxon[containedTree.getTaxa().getNumTaxa()];
+				containedHere = association.getAssociates(terminalTaxon, containedHere);
+				if (containedHere != null&& containedHere.length!=0) { //there are contained-taxa contained within this containing-taxon
+					for (int i=0; i<containedHere.length && containedHere[i]!=null; i++) {  //stores in AssociationHistory fact that these genes are contained in this species
+						int containedNode = containedTree.nodeOfTaxonNumber(containedTree.getTaxa().whichTaxonNumber(containedHere[i]));
+						history.setContainedNode(node, containedNode);
+					}
+				}
+			}
+			else {//containing node is internal: recurse up the tree, and on way down ask to condense the genes within each of the daughters to the representatives of monophyletic groups
+				//first recurse up the tree
+				for (int d = containingTree.firstDaughterOfNode(node); containingTree.nodeExists(d); d = containingTree.nextSisterOfNode(d)) 
+					calcContainedNodes(history, containingTree,containedTree, association, d, useDepths, count);
+				
+				//on way down, for each of containing daughter nodes, condense contained nodes at tip of daughter so as to yield contained clades at base of daughter
+				for (int d = containingTree.firstDaughterOfNode(node); containingTree.nodeExists(d); d = containingTree.nextSisterOfNode(d)) {
+					if (history.getNumberContainedNodes(d)!=0) {
+						//most of the hard work is done by AssociationHistory's condenseClades method
+						int[] temp2 = history.condenseClades(containedTree, containingTree, d, history.getContainedNodes(d), allowResolve.getValue(), useDepths);  //this shouldn't condense if depth of node is greater than dept of containing node
+						if (temp2!= null) {
+							for (int i = 0; i<temp2.length; i++) {
+								history.setContainedNode(node, temp2[i]);
+							}
+							if (!containingTree.nodeIsUnbranchedInternal(node) && temp2.length>0) //don't add if has only a single descendant (in which case no deep coalescence suffered yet))
+								count.add(temp2.length -1);   //v. 2. 01 build j27 and before failed to have the temp2.length>0 restriction, hence added -1 to count if no lineages in population
+						}
+						
+					}
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	/** this method recurses up the containing (species?) tree reconnecting a contained tree which already has location information, into the containing tree.  NOT AVAILABLE yet*/
+	private void reconnect(AssociationHistory history, Tree containingTree, Tree containedTree, TaxaAssociation association, int node) {
+		if (containingTree.nodeIsTerminal(node)) { //terminal
+			int taxonNum = containingTree.taxonNumberOfNode(node);
+			Taxon terminalTaxon =containingTree.getTaxa().getTaxon(taxonNum); //which containing terminal taxon are we at?
+			if (containedHere==null ||  containedHere.length < containedTree.getTaxa().getNumTaxa())
+				containedHere = new Taxon[containedTree.getTaxa().getNumTaxa()];
+			containedHere = association.getAssociates(terminalTaxon, containedHere);
+			if (containedHere != null&& containedHere.length!=0) { //there are contained-taxa contained within this containing-taxon
+				for (int i=0; i<containedHere.length  && containedHere[i]!=null; i++) {  //stores in AssociationHistory fact that these genes are contained in this species
+					int containedNode = containedTree.nodeOfTaxonNumber(containedTree.getTaxa().whichTaxonNumber(containedHere[i]));
+					int anc = node;
+					while (!history.isAncestorContained(anc, containedNode, containedTree) && anc != containingTree.getSubRoot()) {
+						if (!history.isNodeContained(anc, containedNode))
+							history.setContainedNode(anc, containedNode);
+						anc = containingTree.motherOfNode(anc);
+					}
+				}
+			}
+		}
+		else {
+		 	for (int d = containingTree.firstDaughterOfNode(node); containingTree.nodeExists(d); d = containingTree.nextSisterOfNode(d)) {
+				reconnect(history, containingTree,containedTree, association, d);
+				int[] dContained = history.getContainedNodes(d);
+				if (dContained!=null)
+					for (int i=0; i<dContained.length; i++) {
+						if (!history.isNodeContained(node, dContained[i])  && !history.isAncestorContained(node, dContained[i], containedTree))
+							history.setContainedNode(node, dContained[i]);
+					}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Reconstruct Deep Coalescence";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Reconstructs a contained tree within a containing tree so as to minimize the amount of deep coalescence (failure of lineage sorting).  The contained tree is assumed to be rooted." ;
+   	 }
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
+class RerootStore extends TreeVector{
+	String desc;
+	public RerootStore(Taxa taxa, String desc){
+		super(taxa);
+		this.desc = desc;
+	}
+	boolean sameTree(MesquiteTree tree){
+		return tree.writeTree().equals(desc); //doesn't use tree reference in case original is being cloned multiply
+	}
+}
+
diff --git a/Source/mesquite/coalesce/SlatkinMaddisonS/SlatkinMaddisonS.java b/Source/mesquite/coalesce/SlatkinMaddisonS/SlatkinMaddisonS.java
new file mode 100644
index 0000000..e653aad
--- /dev/null
+++ b/Source/mesquite/coalesce/SlatkinMaddisonS/SlatkinMaddisonS.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.SlatkinMaddisonS;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.assoc.lib.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a gene tree by calculating how much lineage sorting is implied by a containing species tree. */
+public class SlatkinMaddisonS extends NumberForTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e3 = registerEmployeeNeed(AssociationSource.class, getName() + " needs a taxa association to indicate how contained taxa fit within containing taxa.",
+		"The source of associations may be arranged automatically or is chosen initially.");
+		EmployeeNeed e4 = registerEmployeeNeed(ParsAncStatesForModel.class, getName() + " uses a parsimony module to count s.",
+		"This is arranged automatically.");
+		e4.setSuppressListing(true);
+	}
+	AssociationSource associationTask; //better to use a partitionSource!
+	MesquiteString treeSourceName;
+	TaxaAssociation association;
+	Taxa containingTaxa;
+	Tree lastTree;
+	ParsAncStatesForModel countTask;
+	public String getKeywords(){
+		return "gene_tree species_tree coalescence coalescent";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations was found.");
+ 		countTask = (ParsAncStatesForModel)hireNamedEmployee(ParsAncStatesForModel.class, StringUtil.tokenize("Parsimony Unordered"));
+ 		if (countTask ==null)
+ 			return sorry(getName() + " couldn't start because the S counting module (Parsimony Unordered) was not obtained.");
+ 		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   	}
+	/*.................................................................................................................*/
+	CategoricalAdjustable locations;
+	boolean warned = false;
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		lastTree = tree;
+        	if (association == null || (association.getTaxa(0)!= tree.getTaxa() && association.getTaxa(1)!= tree.getTaxa())) {
+        		association = associationTask.getCurrentAssociation(tree.getTaxa());
+        		if (association == null){
+        			if (resultString != null)
+        				resultString.setValue("Slatkin & Maddison s not calculated; taxa association not found");
+        			return;
+        		}
+        		if (association.getTaxa(0)== tree.getTaxa())
+        			containingTaxa = association.getTaxa(1);
+        		else
+        			containingTaxa = association.getTaxa(0);
+        	}
+
+	        Taxa genes = tree.getTaxa();
+	        
+	        if (locations==null || locations.getNumTaxa()!=genes.getNumTaxa())
+	        	 locations =  new CategoricalAdjustable(genes, genes.getNumTaxa());
+	        	 
+	        locations.deassignStates();
+	        for (int i = 0; i<genes.getNumTaxa(); i++){
+	        	Taxon[] species = association.getAssociates(genes.getTaxon(i));
+	        	if (species!=null && species.length>0){
+	        		long accumulative = 0L;  //accumulate a state set of all species in which gene i occurs, and set the state of the locations characters accordingly
+	        		int card = 0;
+	        		for (int j = 0; j<species.length; j++){
+	        			int cont = containingTaxa.whichTaxonNumber(species[j]);
+	        			if (cont> CategoricalState.maxCategoricalState) {
+	        				if (!warned)
+	        					discreetAlert( "The calculation of Slatkin & Maddison's s will be inaccurate because there are more than the maximum allowed (" + (CategoricalState.maxCategoricalState+1) + ") number of containing taxa.");
+	        				warned = true;
+	        			}
+	        			else {
+		        			long set = CategoricalState.makeSet(cont);
+		        			accumulative |= set;
+		        			card++;
+	        			}
+	        		}
+	        		if (card>1)
+	        			accumulative |= CategoricalState.makeSet(CategoricalState.uncertainBit);
+	        		locations.setState(i, accumulative);
+	        	}
+	        }
+	        
+	        countTask.calculateSteps(tree, locations, null, null, result);
+		if (resultString!=null)
+			resultString.setValue("s of Slatkin & Maddison: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Calculates 's' of Slaktin & Maddison 1989 for tree of genes associated with given populations";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "s of Slatkin & Maddison";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/TreeDepth/TreeDepth.java b/Source/mesquite/coalesce/TreeDepth/TreeDepth.java
new file mode 100644
index 0000000..81224a5
--- /dev/null
+++ b/Source/mesquite/coalesce/TreeDepth/TreeDepth.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.TreeDepth;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class TreeDepth extends NumberForTree {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 
+  	 public double treeDepth(Tree tree, int node) {
+  	 	if (tree.nodeIsTerminal(node)) { 
+  	 		if (tree.branchLengthUnassigned(node))
+  	 			return 0;
+  	 		else
+  	 			return tree.getBranchLength(node);
+  	 	}
+  	 	else {
+	  	 	double tallest = 0;
+	  	 	double candidate = 0;
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			candidate = treeDepth(tree, daughter);
+	  			if (candidate > tallest)
+	  				tallest = candidate; 
+	  		}
+  	 		if (tree.branchLengthUnassigned(node) || tree.getRoot()==node)  //don't count the root
+  	 			return tallest;
+  	 		else
+	  			return tallest + tree.getBranchLength(node);
+  		}
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree.hasBranchLengths())
+			result.setValue(treeDepth(tree, tree.getRoot()));
+		else
+			result.setValue(0);
+		if (resultString!=null)
+			resultString.setValue("Tree Depth: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree Depth";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the deepest path (in branch length) from terminals to the root, treating unassigned lengths as 0.  The length of the root is not counted.";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/aCoalescencePkgIntro/aCoalescencePkgIntro.java b/Source/mesquite/coalesce/aCoalescencePkgIntro/aCoalescencePkgIntro.java
new file mode 100644
index 0000000..e96fae5
--- /dev/null
+++ b/Source/mesquite/coalesce/aCoalescencePkgIntro/aCoalescencePkgIntro.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.aCoalescencePkgIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+
+
+/* ======================================================================== */
+public class aCoalescencePkgIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aCoalescencePkgIntro.class;
+  	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides simulations and calculations for coalescence (genetic drift) within populations.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Coalescence Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, W.P. 2014.  Coalescence Package for Mesquite.  Version 3.00. http://mesquiteproject.org";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "3.00";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "W. Maddison";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean hasSplash() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Coalescence Package";
+ 	}
+}
+
diff --git a/Source/mesquite/coalesce/aCoalescencePkgIntro/index.html b/Source/mesquite/coalesce/aCoalescencePkgIntro/index.html
new file mode 100644
index 0000000..f2c61ae
--- /dev/null
+++ b/Source/mesquite/coalesce/aCoalescencePkgIntro/index.html
@@ -0,0 +1,134 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Coalescence for Mesquite</title>
+	</head>
+
+	<body bgcolor="#bbffbb">
+		<table border="0" cellpadding="0" cellspacing="0">
+			<tr>
+				<td>
+					<h2><img height="64" width="164" src="splash.gif"></h2>
+				</td>
+				<td>
+					<h2>Coalescence package for Mesquite</h2>
+				</td>
+			</tr>
+		</table>
+		<p><b>Wayne Maddison</b></p>
+		
+<p>August 2005</p>
+		
+<p>This package of modules and library classes provides a few basic calculations,
+  simulations and visualizations concerning gene tree coalescence in population
+  genetics. There is much more that can be done,
+  and opportunities for other programmers to contribute coalescence calculations
+  to Mesquite.</p>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#modules">Modules</a>
+			<li><a href="#remaining">What remains to be done</a>
+			<li><a href="#installation">Installation</a>
+			<li><a href="#examples">Examples</a>
+			<li><a href="#citation">Citation</a>
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		
+<p>Just as MacClade was designed to provide tools to ask "what if the phylogenetic 
+  history had been like this", Mesquite is designed to extend such questions 
+  to other realms such as population genetics. Using, for instance, the insert 
+  node and the lineage width tools in the Tree Window, one can construct a population 
+  history with various expansions and contractions, and explore its consequences 
+  on its contained gene trees via simulations.The best way to understand what 
+  the package can do is to look at the <strong>example files</strong> (see below)</p>
+		<p>The coalescence package currently includes:</p>
+		<ul>
+			<li>Simple neutral coalescence simulations. Coalescent gene trees are simulated either within a single population, or within a tree of populations/species. These simulate the gene tree itself (topology and branch lengths); to simulate nucleotide sequence data, you'll need to simulate character evolution on these gene trees using the stochastic character evolution package.
+			<li>Reconstruction of the history of a gene tree within a species tree so as to minimize deep coalescences, and a tree drawing routine for species trees that draws their gene trees coalescing within them.
+			<li>Counting of Slatkin & Maddison's "s" for the discord between a gene tree and the different populations from which the genes were sampled.
+			<li>Counting of "deep coalescences" in the style of Maddison 1997 (Syst. Biol.)
+			<li>Various other modules that could be used outside of the context of coalescence, but which otherwise aren't part of the basic package of Mesquite modules (e.g., insert node, tree depth).
+		</ul>
+		<p>Thus, the modules are mostly focused on the topology of the gene tree and its relationship with a species tree. As shown in the examples, the package can be used to test some basic hypotheses in population genetics, especially hypotheses of population histories.</p>
+		<h3><a name="conventions"></a>Conventions</h3>
+		<p><b>Effective population size</b> is for the genes themselves, as if the organisms were haploid. <b>Branch lengths</b> of a population or species tree are treated as measured in units of generations. When a gene tree is drawn within a species tree, its branches are drawn <b>green</b> except if polytomies were automatically resolved to optimize fit to the species tree, in which case the resolved branches are drawn in <b>magenta</b>.</p>
+		<h3><a name="modules"></a>Modules</h3>
+		<p>The modules included are:</p>
+		<p>Simulations:</p>
+		<ul>
+			<li><b>NeutralCoalescence</b> ("Neutral Coalescence") -- Simulates neutral coalescence. Employed by CoalescentTrees and ContainedCoalescence in order to simulate gene trees.
+			<li><b>CoalescentTrees</b> ("Coalescent Trees") -- Supplies trees simulated by a coalescent process. The effective population size is a parameter that can be adjusted.
+			<li><b>ContainedCoalescence</b> ("Contained Coalescence within Current Tree") -- Supplies trees simulated by a coalescent process within the branches of a species tree obtained from a Tree Window or other tree context.
+			<li>ContainedCoalescenceMult ("Contained Coalescence in Species Trees") -- not yet ready.
+		</ul>
+		<p>Calculations with gene trees:</p>
+		
+<ul>
+  <li><b>RecCoalescenceHistory</b> ("Reconstruct Deep Coalescence") 
+    -- Reconstructs the fit of a gene tree into a species tree so as to minimize 
+    deep coalescences in the sense of W. Maddison (1997, Syst. Biol.). Also counts 
+    the deep coalescence cost of such a fit. Options are (1) to treat the gene 
+    tree as rooted or unrooted and (2) to allow polytomies in the gene tree to 
+    resolve automatically to minimize deep coalescences further. 
+  <li><b>DeepCoalescencesG</b> ("Deep Coalescences (gene tree)") -- 
+    Counts the cost in deep coalescences to fit a gene tree in a species tree; 
+    treats this as a value for the gene tree. 
+  <li><b>DeepCoalescencesSp</b> ("Deep Coalescences (species tree)") 
+    -- Counts the cost in deep coalescences to fit a gene tree in a species tree; 
+    treats this as a value for the species tree. 
+  <li><b>SlatkinMaddisonS</b> ("s of Slatkin & Maddison") -- Counts 
+    the s value of Slatkin and Maddison (s is a measure of the discordance between 
+    a gene tree and a division into populations). Requires an available Association 
+    of genes into populations. 
+  <li><b>TreeDepth</b> ("Tree Depth") -- Determines the depth of the 
+    tree, measured as the sum of branch lengths from the root to the tallest terminal 
+    node. 
+</ul>
+		<p>Utilities:</p>
+		<ul>
+			<li><b>aCoalescencePkgIntro</b> ("Coalescence Package Introduction") -- Introduces the coalescence package.
+			<li><b>LineageWidth</b> ("Adjust lineage width") -- Allows the user to adjust the widths (e.g., effective population sizes) of branches of a population or species tree. This is not merely a graphical widening, but attaches a width parameter to the branches of the tree.
+			<li><b>InsertNode</b> ("Insert Node") -- Inserts a node along a branch of a tree. This creates a node with only a single descendant. It can be used to break a branch into pieces, each of which is assigned its own effective population size (lineage width) and duration of time in generations (branch length).
+		</ul>
+		<p>The coalescence package depends on modules and libraries from the more general Taxa Associations package. The Taxa Associations package is not yet a standalone package, and is included in service of the coalescence routines. These are the included modules from the Taxa Associations package:</p>
+		<p>Management and Utilities:</p>
+		<ul>
+			<li><b>ManageAssociations</b> ("Manage TaxaAssociation blocks") -- Reads and writes TaxaAssociation blocks to NEXUS files, and supervises their editing and manipulation by users.
+			<li><b>StoredAssociations</b> ("Stored Taxa Associations") -- Supplies stored TaxaAssociations to calculations that need information on which taxa from one taxa block (e.g., genes) are associated with which taxa in another block (e.g., species).
+			<li><b>ManageDistributionBlock</b> ("Read DISTRIBUTION blocks") -- Reads DISTRIBUTION blocks (e.g., used by Rod Page's GeneTree) in NEXUS files. Subsequent writing of the information is currently to separate TAXA, TREES and TaxaAssociation blocks.
+		</ul>
+		<p>Graphics and analysis:</p>
+		<ul>
+			<li><b>ContainedAssociates</b> ("Contained Associates") -- Draws a species tree with broad branches, inside which are reconstructed and drawn gene trees within them.
+		</ul>
+		<h3><a name="remaining"></a>What remains to be done</h3>
+		<p>Improvements to the existing modules remain to be made, including making
+	  them more efficient.</p>
+		<p>Many other calculations taking a gene tree perspective could be done, including
+		  those that have nucleotide sequence evolution occurring along the branches
+		  of the gene tree. This would allow direct comparison against observed
+		  sequences, without being forced to reconstruct a gene tree from the
+		  sequences before
+		  comparison with Mesquite's results. The solution to this will come
+		  from the Genesis package, which can be combined with the coalescence
+		  package to generate
+		  nucleotide sequences evolved on coalescence trees.</p>
+		<h3><a name="installation"></a>Installation</h3>
+		
+<p>There are two folders (directories) whose contents need to be in the correct 
+  place for Mesquite to be able to use them. These two directories are called 
+  (1) "coalesce" and (2) "assoc". Find where you have Mesquite 
+  installed on your hard disk. These three directories should be in the "mesquite" 
+  directory within "Mesquite Folder".</p>
+		<h3><a name="examples"></a>Examples</h3>
+		<p>There is a series of example data files in the directory "coalescence_examples". The files are self explanatory; begin with the file whose name begins with "00".</p>
+		<p>
+		<hr noshade size="2">
+		</p>
+		
+<p>© Copyright 2002-2005 W. Maddison 
+</body>
+
+</html>
diff --git a/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif b/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif
new file mode 100644
index 0000000..31db55e
Binary files /dev/null and b/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif differ
diff --git a/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif copy b/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif copy
new file mode 100644
index 0000000..1cb2231
Binary files /dev/null and b/Source/mesquite/coalesce/aCoalescencePkgIntro/splash.gif copy differ
diff --git a/Source/mesquite/coalesce/aCoalescencePkgIntro/splashSmall.gif b/Source/mesquite/coalesce/aCoalescencePkgIntro/splashSmall.gif
new file mode 100644
index 0000000..4d7f331
Binary files /dev/null and b/Source/mesquite/coalesce/aCoalescencePkgIntro/splashSmall.gif differ
diff --git a/Source/mesquite/coalesce/explanation.txt b/Source/mesquite/coalesce/explanation.txt
new file mode 100644
index 0000000..cd97477
--- /dev/null
+++ b/Source/mesquite/coalesce/explanation.txt
@@ -0,0 +1,3 @@
+Coalescence Package
+Calculations for coalescence models in population genetics.  Modules simulate gene trees within a single population or within the branches of a population/species tree.  The fit of gene trees into species trees is assessed and reconstructed.  Utility modules allow trees to be edited to specify branch widths and insert unbranched nodes.
+
diff --git a/Source/mesquite/coalesce/lib/CoalescedNode.java b/Source/mesquite/coalesce/lib/CoalescedNode.java
new file mode 100644
index 0000000..66ddc52
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/CoalescedNode.java
@@ -0,0 +1,165 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** .*/
+public class CoalescedNode {
+	public CoalescedNode firstDaughter=null;
+	public CoalescedNode nextSister=null;
+	public CoalescedNode mother=null;
+	public int name=0;
+	public int when=0;
+	public int location = MesquiteInteger.unassigned;  //can be used to indicate in which population it occurs, for instance
+	public boolean open = true;
+	
+	public boolean isTerminal() {
+		return firstDaughter==null;
+	}
+	public static CoalescedNode findOpen(CoalescedNode[] nodes){
+			/*return new CoalescedNode();*/
+	
+		if (nodes==null || nodes.length==0)
+			return null;
+		for (int i=0; i<nodes.length; i++)
+			if (nodes[i].open){
+				nodes[i].open = false;
+				return nodes[i];
+			}
+		return null;
+	}
+	public void reinitialize() {
+		firstDaughter=null;
+		nextSister=null;
+		mother=null;
+		name=0;
+		when=0;
+		open = true;
+		location = MesquiteInteger.unassigned;  
+	}
+	public int countTerminalTaxa() {
+		if (isTerminal())
+			return 1;
+		else {
+			int sum = 0;
+			for (CoalescedNode daughter = firstDaughter; daughter !=null; daughter = daughter.nextSister)
+				sum += daughter.countTerminalTaxa();
+			return sum;
+		}
+	}
+	
+	public static CoalescedNode[] findNodes (CoalescedNode[] x) {
+		CoalescedNode[] result = new CoalescedNode[countNumber(x)];
+		int count = 0;
+		for (int i=0; i<x.length; i++)
+			if (x[i]!=null)
+				result[count++] = x[i];
+		return result;
+	}
+	/*.................................................................................................................*/
+	public static int countNumber (CoalescedNode[] x) {
+		int num=0;
+		for (int i=0; i<x.length; i++)
+			if (x[i]!=null)
+				num++;
+		return num;
+	}
+	/*.................................................................................................................*/
+	public static CoalescedNode[] concatenate(CoalescedNode[] a, CoalescedNode[] b){
+		if (a == null)
+			return b;
+		else if (b == null)
+			return a;
+		else {
+			CoalescedNode[] result = new CoalescedNode[a.length + b.length];
+			int i;
+			for (i=0; i<a.length; i++)
+				result[i]=a[i];
+			for (i=0;i<b.length;i++)
+				result[i+a.length] = b[i];
+			return result;
+		}
+	}
+	/*.................................................................................................................*/
+	public static String writeCoalescedNodes(CoalescedNode[] c){
+		if (c == null)
+			return "null";
+		String s = "";
+		for (int i = 0; i<c.length; i++) {
+			if (c[i] != null)
+				s += " " +  c[i].name;
+			else
+				s += " " +  null;
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public static CoalescedNode[] cloneNodes(CoalescedNode[] c){
+		if (c == null)
+			return null;
+		CoalescedNode[] result = new CoalescedNode[c.length];
+		for (int i = 0; i<result.length; i++) {
+			result[i]=c[i];
+		}
+		return result;
+	}
+	/*.................................................................................................................*/
+	public static CoalescedNode findNode (CoalescedNode[] x) {
+		for (int i=0; i<x.length; i++)
+			if (x[i]!=null)
+				return x[i];
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String cladeToString() {
+		if (isTerminal()){  //terminal; return just  name
+			String n = String.valueOf(name);
+			String loc = "";
+			if (MesquiteInteger.isCombinable(location))
+				loc = "<location =" + location + ">";
+			if (mother==null) {
+				MesquiteMessage.warnProgrammer("Warning: mother null in terminal cladeToString in CoalescedNode");
+				return n + loc;//TODO: branch lengths all wrong
+			}
+			else 
+				return n + ":" + (mother.when-when) + " " + loc;//TODO: branch lengths all wrong
+				
+		}
+		else {  //internal; return parentheses and daughter clades
+			String s = "(";
+			boolean first = true;
+			for (CoalescedNode daughter = firstDaughter; daughter !=null; daughter = daughter.nextSister) {
+				if (!first)
+					s += ",";
+				first = false;
+				s += daughter.cladeToString();
+			}
+			s += ")";
+			if (mother!=null)
+				s += ":" + (mother.when-when); //to show branch lengths
+			if (MesquiteInteger.isCombinable(location))
+				s += "<location =" + location + ">";
+			return s;
+		}
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/coalesce/lib/Coalescer.java b/Source/mesquite/coalesce/lib/Coalescer.java
new file mode 100644
index 0000000..b392b85
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/Coalescer.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+
+public abstract class Coalescer extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return Coalescer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Coalescence simulator";
+   	 }
+   	public abstract void coalesce(MesquiteTree tree,  int[] containing, int whichContaining, double neAdjustment, long generations, MesquiteLong seed, boolean untilOne);
+	public abstract int getPopulationSize();
+   	public abstract void setPopulationSize(int pS);
+}
+
+
diff --git a/Source/mesquite/coalesce/lib/CoalescerObed.java b/Source/mesquite/coalesce/lib/CoalescerObed.java
new file mode 100644
index 0000000..08f1fca
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/CoalescerObed.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/* equivalent to Coalescer but when hired as this, it knows that it shouldn't present its own interface for setting population size*/
+public abstract class CoalescerObed extends Coalescer   {
+
+}
+
+
diff --git a/Source/mesquite/coalesce/lib/ContainedTreeSim.java b/Source/mesquite/coalesce/lib/ContainedTreeSim.java
new file mode 100644
index 0000000..7adcd40
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/ContainedTreeSim.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+/* ======================================================================== */
+public abstract class ContainedTreeSim extends MesquiteModule {
+ 	public Class getDutyClass() {
+ 		return ContainedTreeSim.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Contained Tree Simulation";
+   	 }
+	/*.................................................................................................................*/
+	/*  coalesces the gene tree nodes contained within the species tree node "node". */
+	public abstract MesquiteTree simulateContainedTree (Tree speciesTree, Tree geneTree, TaxaAssociation association, Taxa geneTaxa, MesquiteLong seed);
+}
+
+
diff --git a/Source/mesquite/coalesce/lib/GeneTreeFit.java b/Source/mesquite/coalesce/lib/GeneTreeFit.java
new file mode 100644
index 0000000..dc19646
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/GeneTreeFit.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a gene tree by calculating how much lineage sorting is implied by a containing species tree. */
+public abstract class GeneTreeFit extends NumForGeneTInSpeciesT {
+   	 
+   	MesquiteTree t;
+	MesquiteString r = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		lastTree = tree;
+		Taxa taxa = tree.getTaxa();
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association == null)
+        			association = associationTask.getAssociation(taxa, 0); 
+        		if (association == null){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence (gene tree) not calculated (no association )");
+				return;
+			}
+        		if (association.getTaxa(0)== taxa)
+        			containingTaxa = association.getTaxa(1);
+        		else
+        			containingTaxa = association.getTaxa(0);
+        	}
+        	/*tree coming in is gene tree, hence need to find out for each taxon in gene tree if it has more than one associate.  If so, then 
+        	can't do calculations since gene copy in more than one species*/
+		for (int i=0; i< taxa.getNumTaxa(); i++){
+			Taxon tax = taxa.getTaxon(i);
+			if (association.getNumAssociates(tax)>1){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence not calculated (some genes in more than one species)");
+				return;
+			}
+		}
+		
+		//get containing tree
+		Tree containingTree = ((OneTreeSource)treeSourceTask).getTree(containingTaxa); 
+		
+		//cloning the contained tree in case we need to change its resolution
+	        if (t==null || t.getTaxa()!=taxa || !(tree instanceof MesquiteTree))
+	        	t = tree.cloneTree();
+	        else
+	        	((MesquiteTree)t).setToClone((MesquiteTree)tree);
+	        	
+	        	
+		//calculate deep coalescence cost
+	    calculateCost(reconstructTask, containingTree, t, association, result, r);
+		lastContaining = containingTree;
+		if (resultString!=null)
+			resultString.setValue(r.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public abstract void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r);
+   
+	public boolean biggerIsBetter() {
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/coalesce/lib/NumForGeneTInSpeciesT.java b/Source/mesquite/coalesce/lib/NumForGeneTInSpeciesT.java
new file mode 100644
index 0000000..58184d4
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/NumForGeneTInSpeciesT.java
@@ -0,0 +1,118 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a gene tree in the context of a containing species tree. */
+public abstract class NumForGeneTInSpeciesT extends NumberForTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + " needs a source for the containing tree (e.g. a species tree) to assess the fit of contained trees (e.g. gene trees).",
+		"The source of other trees can be indicated initially or later under the Species Tree Source submenu.");
+		EmployeeNeed e3 = registerEmployeeNeed(AssociationSource.class, getName() + " needs a taxa association to indicate how contained taxa fit within containing taxa.",
+		"The source of associations may be arranged automatically or is chosen initially.");
+		EmployeeNeed e4 = registerEmployeeNeed(ReconstructAssociation.class, getName() + "needs to fit or reconstruct the contained tree within the containing tree in order to measure its fit.",
+		"The reconstruction method can be specified initially.");
+	}
+	protected OneTreeSource treeSourceTask;
+	protected AssociationSource associationTask;
+	protected ReconstructAssociation reconstructTask;
+	protected MesquiteString treeSourceName;
+	protected TaxaAssociation association;
+	protected Taxa containingTaxa;
+	protected Tree lastTree, lastContaining;
+	protected MesquiteCommand tstC;
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		//todo: allow choices && put in setHiringCommand
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associatons obtained.");
+		
+		//todo: if this is going to be for deep coalescences, should hire just that reconstructor.  Otherwise change name of this throughout to neutral
+		reconstructTask = (ReconstructAssociation)hireEmployee(ReconstructAssociation.class, "Method to reconstruct association history");
+		if (reconstructTask == null)
+			return sorry(getName() + " couldn't start because module to reconstruct association histories obtained.");
+		treeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of containing trees");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because source of containing trees obtained.");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Species Tree Source",tstC, OneTreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+ 		return true;
+  	 }
+	public void employeeQuit(MesquiteModule m){
+		if (m != treeSourceTask)
+			iQuit();
+	}  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", treeSourceTask); 
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the source of the species tree", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				parametersChanged();
+    	 			return treeSourceTask;
+    	 		}
+    	 	}
+ 		else {
+ 			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+   	 }
+   	 
+   	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (tree ==null)
+   			return;
+   		Taxa taxa = tree.getTaxa();
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association.getTaxa(0)== taxa)
+        			containingTaxa = association.getTaxa(1);
+        		else
+        			containingTaxa = association.getTaxa(0);
+        	}
+   	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (lastContaining !=null)
+			return "Species tree " + lastContaining.getName();
+		return "";
+   	 }
+   
+}
diff --git a/Source/mesquite/coalesce/lib/SpeciesTreeFit.java b/Source/mesquite/coalesce/lib/SpeciesTreeFit.java
new file mode 100644
index 0000000..d8b4882
--- /dev/null
+++ b/Source/mesquite/coalesce/lib/SpeciesTreeFit.java
@@ -0,0 +1,256 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.coalesce.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+import mesquite.assoc.lib.*;
+
+
+/* ======================================================================== */
+/** This evaluates a species tree by calculating how much lineage sorting is implied by a contained gene tree. */
+public abstract class SpeciesTreeFit extends NumberForTree implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + " needs a source for the contained tree (e.g. a gene tree) to assess the fit of containing trees (e.g. sp0ecies trees).",
+		"The source of other trees can be indicated initially or later under the Gene Tree Source submenu.");
+		EmployeeNeed e3 = registerEmployeeNeed(AssociationSource.class, getName() + " needs a taxa association to indicate how contained taxa fit within containing taxa.",
+		"The source of associations may be arranged automatically or is chosen initially.");
+		EmployeeNeed e4 = registerEmployeeNeed(ReconstructAssociation.class, getName() + "needs to fit or reconstruct the contained tree within the containing tree in order to measure its fit.",
+		"The reconstruction method can be specified initially.");
+	}
+	MesquiteNumber nt;
+	TreeSource treeSourceTask;
+	AssociationSource associationTask;
+	ReconstructAssociation reconstructTask;
+	MesquiteString treeSourceName;
+	TaxaAssociation association;
+	int currentContained = MesquiteInteger.unassigned;
+	Taxa containedTaxa;
+	MesquiteCommand tstC;
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+		reconstructTask = (ReconstructAssociation)hireEmployee(ReconstructAssociation.class, "Method to reconstruct association history");
+		if (reconstructTask == null)
+			return sorry(getName() + " couldn't start because no association reconstructor module obtained.");
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of contained trees");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Gene Tree Source", tstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+ 		addMenuItem( "Next Contained Tree", makeCommand("nextContained",  this));
+ 		addMenuItem( "Previous Contained Tree", makeCommand("previousContained",  this));
+ 		nt= new MesquiteNumber();
+ 		return true;
+  	 }
+  	 
+	public void employeeQuit(MesquiteModule m){
+		if (m != treeSourceTask)
+			iQuit();
+	}  	 
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+ 			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", treeSourceTask); 
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the source of the gene tree", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				currentContained = MesquiteInteger.unassigned;
+				parametersChanged();
+    	 			return treeSourceTask;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next contained gene tree", null, commandName, "nextContained")) {
+    	 		if (MesquiteInteger.isUnassigned(currentContained))
+    	 			currentContained = -1;
+    	 		setContained(currentContained+1);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous contained gene tree", null, commandName, "previousContained")) {
+    	 		if (MesquiteInteger.isUnassigned(currentContained))
+    	 			currentContained = 1;
+    	 		setContained(currentContained-1);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to contained gene tree", "[number of tree]", commandName, "setContained")) {
+    	 		int ic = MesquiteTree.toInternal(MesquiteInteger.fromFirstToken(arguments, pos)); //TODO: 0/1 based
+    	 		setContained(ic);
+    	 	}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+   	 
+	public void setContained (int index){ 
+		if (containedTaxa == null)
+			return;
+ 		if (index<((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa) && index>=0){
+ 			currentContained=index;
+ 			parametersChanged();
+ 		}
+	}
+   	public void initTaxa(Taxa taxa){
+   		if (taxa ==null)
+   			return;
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+			treeSourceTask.initialize(containedTaxa);
+        	}
+   	}
+	Tree lastTree;
+   	MesquiteTree cTree;
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (tree ==null)
+   			return;
+   		initTaxa(tree.getTaxa());
+   	}
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		currentContained = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return currentContained;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Contained tree";
+ 	}
+ 	public long getMin(){
+		return 0;
+ 	}
+ 	public long getMax(){
+   		//initTaxa(preferredTaxa);
+		int nt = ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa);
+		if (nt == MesquiteInteger.infinite) {
+			return MesquiteLong.infinite;
+		}
+		return nt -1;
+ 	}
+ 	public long toInternal(long i){
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+	MesquiteString r = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		lastTree = tree;
+		Taxa taxa = tree.getTaxa();
+		
+		//getting the association and contained taxa
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association == null)
+        			association = associationTask.getAssociation(taxa, 0); 
+        		if (association == null){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence (Species tree) not calculated (no association )");
+				return;
+			}
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+        	}
+        	/* need to find out for each taxon among contained taxa if it has more than one associate.  If so, then 
+        	can't do calculations since gene copy in more than one species*/
+		for (int i=0; i< containedTaxa.getNumTaxa(); i++){
+			Taxon tax = containedTaxa.getTaxon(i);
+			if (association.getNumAssociates(tax)>1){
+				if (resultString!=null)
+					resultString.setValue("Deep coalescence not calculated (some genes in more than one species)");
+				return;
+			}
+		}
+		
+        	//choosing which tree to use from the tree source
+        	if (MesquiteInteger.isUnassigned(currentContained)){
+        		if (MesquiteThread.isScripting())
+        			currentContained = 0;
+        		else {
+				int nt = ((TreeSource)treeSourceTask).getNumberOfTrees(containedTaxa);
+			   	if (nt>1) {
+   					currentContained = ((TreeSource)treeSourceTask).queryUserChoose(containedTaxa, "Which contained tree to fit into species tree to count deep coalescences?");
+   					if (MesquiteInteger.isUnassigned(currentContained))
+   						currentContained = 0;
+   				}
+   				else
+   					currentContained = 0;
+				
+        		}
+        			
+        	}
+        	
+        	//getting the contained tree & cloning it in case we need to change its resolution
+		Tree containedTree = ((TreeSource)treeSourceTask).getTree(containedTaxa, currentContained); 
+	        if (containedTree==null) {
+			if (resultString!=null)
+				resultString.setValue("Deep coalescences: unassigned (no gene tree)");
+			return;
+		}
+		
+		
+		//calculate deep coalescence cost
+	        if (cTree == null || cTree.getTaxa()!=containedTaxa || !(containedTree instanceof MesquiteTree))
+	        	cTree = containedTree.cloneTree();//no need to establish listener to Taxa, as will be remade when needed?
+	        else
+	        	cTree.setToClone((MesquiteTree)containedTree);
+	    calculateCost(reconstructTask, tree, cTree, association, result, r);
+		if (resultString!=null)
+			resultString.setValue(r.toString() + " (gene tree " + TreeVector.toExternal(currentContained) + " in species tree " + lastTree.getName() + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public abstract void calculateCost(ReconstructAssociation reconstructTask, Tree speciesTree, MesquiteTree geneTree, TaxaAssociation association, MesquiteNumber result, MesquiteString r);
+  	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (lastTree !=null)
+			return "Gene tree " + TreeVector.toExternal(currentContained);
+		return "";
+   	 }
+}
+
diff --git a/Source/mesquite/coalesce/macros/s_by_depth b/Source/mesquite/coalesce/macros/s_by_depth
new file mode 100644
index 0000000..9481ca7
--- /dev/null
+++ b/Source/mesquite/coalesce/macros/s_by_depth
@@ -0,0 +1,102 @@
+telling FileCoordinator;
+getNumberOfTaxas;
+Integer.numTaxas *It;
+decrement.numTaxas;  [if only one, don't do anything (should explain why, but doesn't yet)]
+ifNot *Integer.numTaxas;
+	alert 'Macro "s by depth" can''t be run with this file because there is only one set of taxa';
+endIf;
+if *Integer.numTaxas;
+	alert 'This macro calculates Slatkin and Maddison''s "s" value for gene trees within an available species tree, for varying branch lengths';
+	getTaxas;
+	Object.taxas *It;
+	newAssistant  'Tree values';
+	tell It;
+		suspendCalculations;
+		queryListNumber *Object.taxas 'Which set of taxa represents genes?';
+		Integer.taxa *It;
+		setTaxa *Integer.taxa; [needs to ask for taxa]
+		queryString 'Name of results file?';
+		String.fileName *It;
+		queryNumber 'Initial branch length (in generations)';
+		Number.initial *It;  
+		queryNumber 'Increment in branch length';
+		Number.lengthIncrement *It;  
+		queryInteger 'Number of different branch lengths';
+		Integer.numIncrements *It;
+		queryInteger 'Number of gene trees sampled for each species branch length';
+		Integer.sampleSize *It;
+
+
+		getCharter 'Item values chart';
+		Object.chartModule *It;
+		tell *Object.chartModule;
+			getWindow;
+			Object.chartWindow *It;
+			tell *Object.chartWindow;
+				setSize 400 400;
+				setLocation 60 10;
+				setFont SanSerif;
+				setFontSize 10;
+				onInfoBar;
+				setChartType  'Histogram';
+				tell It;
+					showAverageToggle off;
+					setMode 0;
+					toggleSizeToFit on;
+				endTell;
+				toggleOrientation off;
+				toggleColorItems off;
+				setNumberItems *Integer.sampleSize;
+			endTell;
+		endTell;
+		
+		[setNumberTrees *Integer.sampleSize;]
+		setCalculator  's of Slatkin & Maddison';
+		setTreeSource  'Simulated Trees';
+		tell It;
+			setTreeSimulator  'Contained Coalescence';
+			Object.coalescer *It;
+		endTell;
+		setChartVisible;
+		doCounts;
+		resumeCalculations;
+		showWindow;
+		tell *Object.coalescer;
+			getSpeciesTree;
+			Object.speciesTree *It;
+		endTell;
+		saveMessageToFile *String.fileName 'Results of simulations of gene tree coalescence within species';
+		appendReturnToFile *String.fileName;
+		Number.bL *Number.initial;
+		for *Integer.numIncrements;
+			Number.bL +*Number.lengthIncrement;
+		endFor;
+		appendLiteralToFile *String.fileName 'Branch lengths from ';
+		appendMessageToFile *String.fileName *Number.initial;
+		appendLiteralToFile *String.fileName ' through ';
+		appendMessageToFile *String.fileName *Number.bL;
+		appendReturnToFile *String.fileName;
+		appendMessageToFile *String.fileName '================================';
+		appendReturnToFile *String.fileName;
+		appendReturnToFile *String.fileName;
+		Number.branchLength *Number.initial;
+		for *Integer.numIncrements;
+			appendLiteralToFile *String.fileName 'Results when all branch lengths in species tree set to ';
+			appendMessageToFile *String.fileName *Number.branchLength;
+			appendReturnToFile *String.fileName;
+			appendReturnToFile *String.fileName;
+			tell *Object.speciesTree;
+				setAllBranchLengths *Number.branchLength;
+			endTell;
+			tell *Object.chartWindow;
+				appendTextToFile *String.fileName;
+			endTell;
+			Number.branchLength +*Number.lengthIncrement;
+		endFor;
+		tell *Object.chartWindow;
+			closeWindow;
+		endTell;
+	endTell;
+	showFile *String.fileName;
+endIf;
+
diff --git a/Source/mesquite/consensus/ConsensusTree/ConsensusTree.java b/Source/mesquite/consensus/ConsensusTree/ConsensusTree.java
new file mode 100644
index 0000000..dceabf9
--- /dev/null
+++ b/Source/mesquite/consensus/ConsensusTree/ConsensusTree.java
@@ -0,0 +1,317 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.consensus.ConsensusTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class ConsensusTree extends TreeSource {
+	int currentTree=0;
+	TreeSource treeSource;
+	Taxa oldTaxa=null;
+
+	Consenser consenser = null;
+
+	MesquiteString treeSourceName, consenserName; 
+	MesquiteCommand tlsC, cC;
+	int numTreesAssigned = MesquiteInteger.unassigned;
+	int defaultNumberOfItems = 100;
+	boolean assigned = false;
+	private MesquiteMenuItemSpec numTreesItem;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		startTree = 0;
+		treeSource= (TreeSource)hireEmployee(TreeSource.class, "Source of Trees for consensus");
+		tlsC = makeCommand("setTreeSource",  this);
+		cC = makeCommand("setConsenser", this);
+		if (treeSource==null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		//treeSource.setHiringCommand(tlsC);
+		treeSourceName = new MesquiteString();
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source for Consensus", tlsC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+
+		consenser= (Consenser)hireEmployee(Consenser.class, "Consensus calculator");
+		if (consenser==null)
+			return sorry(getName() + " couldn't start because no consensus module obtained.");
+		consenser.setHiringCommand(cC);
+		consenserName = new MesquiteString();
+		if (numModulesAvailable(Consenser.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Consensus module", cC, Consenser.class);
+			mss.setSelected(consenserName);
+		}
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m instanceof TreeSource)
+			iQuit();
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeSource ", treeSource); 
+		temp.addLine("setConsenser ", consenser); 
+		if (MesquiteInteger.isCombinable(numTreesAssigned))
+			temp.addLine("assignNumTrees " + numTreesAssigned);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module supplying tree blocks", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees", treeSource);
+			if (temp!=null) {
+				treeSource = temp;
+				startTree = 0;
+			//	treeSource.setHiringCommand(tlsC);
+				treeSourceName.setValue(treeSource.getName());
+				parametersChanged();
+			}
+			return temp;
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees", "[number of trees]", commandName, "assignNumTrees")) {
+			//Changed so numTreesAssigned updated if queryNumTrees is called (previous version [see below] did not update numTreesAssigned)
+			//J.C. Oliver Nov.20.2013
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum) || newNum < 0){
+				newNum = queryNumTrees();
+			}
+			if(newNum > 0){
+				numTreesAssigned = newNum;
+				assigned = true;
+				parametersChanged();
+			}
+			/*Old way:
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum)){
+				queryNumTrees();
+			}
+			else if (newNum>0 ) {
+				numTreesAssigned = newNum;
+				assigned = true;
+			}
+			parametersChanged();
+			 */
+		}
+		else
+			if (checker.compare(this.getClass(), "Sets the module doing a consensus", "[name of module]", commandName, "setConsenser")) {
+				Consenser temp = (Consenser)replaceEmployee(Consenser.class, arguments, "Consensus module", consenser);
+				if (temp!=null) {
+					consenser = temp;
+					startTree = 0;
+					consenser.setHiringCommand(cC);
+					consenserName.setValue(consenser.getName());
+					parametersChanged();
+				}
+				return temp;
+			}
+			else
+				return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa){
+		oldTaxa = taxa;
+	}
+	int queryNumTrees(){
+		return MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees from \"" + treeSource.getName() + "\" for consensus", numTreesAssigned);
+	}
+	/*.................................................................................................................*/
+	int checkNumTrees(Taxa taxa){
+		int numTrees = treeSource.getNumberOfTrees(taxa);
+		if (MesquiteInteger.isInfinite(numTrees)){
+			if (numTreesItem == null) {
+				numTreesItem = addMenuItem( "Number of  Trees for Consensus...", makeCommand("assignNumTrees",  this));
+				resetContainingMenuBar();
+			}
+			if (MesquiteInteger.isCombinable(numTreesAssigned))
+				return numTreesAssigned;
+			if (!MesquiteThread.isScripting()) 
+				numTreesAssigned = queryNumTrees();
+			if (!MesquiteInteger.isCombinable(numTreesAssigned)) 
+				numTreesAssigned = defaultNumberOfItems;
+			assigned = true;
+			return numTreesAssigned;
+		}
+		else {
+			if (numTreesItem != null) {
+				deleteMenuItem(numTreesItem);
+				numTreesItem = null;
+				resetContainingMenuBar();
+			}
+			return numTrees;
+		}
+	}
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		startTree = 0;
+		if (treeSource!=null) {
+			treeSource.initialize(taxa); //WHEN this module takes in tree from a source, should ask to initialize that source
+			checkNumTrees(taxa);
+		}
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int ic) {  
+		return getTree(taxa,ic,true);
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int ic, boolean verbose) {  
+		oldTaxa = taxa;
+
+		int numTrees = checkNumTrees(taxa);
+		Trees trees = new TSourceWrapper(treeSource, taxa);
+		Tree tree = null;
+		if (consenser instanceof IncrementalConsenser){
+			IncrementalConsenser iConsenser = (IncrementalConsenser)consenser;
+			if (startTree == 0)
+				iConsenser.reset(taxa);
+			boolean done = false;
+			int count = 0;
+			if (verbose) logln("Consensing trees ");
+			for (int i= startTree; i<numTrees && !done; i++) {
+				Tree t = trees.getTree(i);
+				if (t == null)
+					done = true;
+				else {
+					iConsenser.addTree(t);
+					CommandRecord.tick("Processing tree " + (i+1));
+					startTree++;
+					count++;
+					if (verbose) {
+						if (startTree % 1000 == 0)
+							log(" " + startTree + " ");
+						else if (count % 100==0)
+							log(".");
+					}
+				}
+			}
+			if (verbose)
+				logln("Trees consensed");
+			//			if (count>0)
+			tree = iConsenser.getConsensus();
+			if (tree instanceof MesquiteTree)
+				if (count==0)
+					((MesquiteTree)tree).setName(consenser.getName() + " of trees from " + treeSource.getNameAndParameters());
+				else
+					((MesquiteTree)tree).setName(consenser.getName() + " of " + count + " trees from " + treeSource.getNameAndParameters());
+		}
+		else {
+			tree = consenser.consense(trees);
+			if (tree instanceof MesquiteTree)
+				((MesquiteTree)tree).setName(consenser.getName() + " from " + treeSource.getNameAndParameters());
+		}
+		if (verbose)
+			logln("");
+
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		return 1;
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		return consenser.getName() + " from " + treeSource.getNameAndParameters();
+	}
+	/**Returns name to show in windows etc. for tree block or source of trees.*/
+	public String getTreesDescriptiveString(Taxa taxa){
+		return "Consensus of " + treeSource.getTreesDescriptiveString(taxa);
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return consenser.getName() + " of trees from " + treeSource.getName();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Consensus Tree";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies consensus tree from a block of trees.";
+	}
+	int startTree = 0;
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (MesquiteThread.isScripting())
+			return;
+
+		if (employee == treeSource){
+			if (notification == null){
+				startTree = 0;
+
+				parametersChanged();
+			}
+			else if (consenser instanceof IncrementalConsenser && notification.getCode() == MesquiteListener.ITEMS_ADDED){
+				parametersChanged();
+			}
+			else if (notification.getCode() != MesquiteListener.SELECTION_CHANGED){
+				startTree =  0;
+				parametersChanged(new Notification(notification.getCode()));
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ConsCompatibilityTest();
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean requestPrimaryChoice() { return true; } //WPM 06 set to true
+}
+
+class ConsCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (prospectiveEmployer != null)
+			return prospectiveEmployer.numModulesAvailable(Consenser.class)>0;
+			else
+				return MesquiteTrunk.mesquiteTrunk.numModulesAvailable(Consenser.class)>0;
+	}
+}
+
+class TSourceWrapper implements Trees {
+	TreeSource source;
+	Taxa taxa;
+	TSourceWrapper(TreeSource list, Taxa taxa){
+		this.source = list;
+		this.taxa = taxa;
+	}
+	/** Get the taxa to which the trees applies */
+	public Taxa getTaxa(){
+		return taxa;
+	}
+
+	public Tree getTree(int i){
+		return source.getTree(taxa, i);
+	}
+
+	public int size(){
+		return source.getNumberOfTrees(taxa);
+	}
+
+}
+
+
diff --git a/Source/mesquite/consensus/MajRuleTree/MajRuleTree.java b/Source/mesquite/consensus/MajRuleTree/MajRuleTree.java
new file mode 100644
index 0000000..2d1ecfa
--- /dev/null
+++ b/Source/mesquite/consensus/MajRuleTree/MajRuleTree.java
@@ -0,0 +1,167 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.consensus.MajRuleTree;
+
+
+import java.awt.Checkbox;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.consensus.lib.*;
+
+
+/* ======================================================================== */
+/** Does majority rule consensus .*/
+
+public class MajRuleTree extends BasicTreeConsenser   {
+	double frequencyLimit = 0.5;
+	MesquiteBoolean useWeights = new MesquiteBoolean(true);
+	Checkbox useWeightsBox;
+	Checkbox dumpTableBox;
+	boolean dumpTable = false;
+	DoubleField frequencyField;
+
+
+	public String getName() {
+		return "Majority-Rule Consensus";
+	}
+	public String getExplanation() {
+		return "Calculates the majority-rule consensus tree." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		bipartitions = new BipartitionVector();
+		loadPreferences();
+		if (!MesquiteThread.isScripting()) 
+			if (!queryOptions()) 
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void processMorePreferences (String tag, String content) {
+		if ("useWeights".equalsIgnoreCase(tag))
+			useWeights.setFromTrueFalseString(content);
+		else if ("frequencyLimit".equalsIgnoreCase(tag))
+			frequencyLimit = MesquiteDouble.fromString(content);
+		else if ("dumpTable".equalsIgnoreCase(tag))
+			dumpTable = MesquiteBoolean.fromTrueFalseString(content);
+	}
+	/*.................................................................................................................*/
+	public String prepareMorePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "useWeights", useWeights);  
+		StringUtil.appendXMLTag(buffer, 2, "frequencyLimit", frequencyLimit);  
+		StringUtil.appendXMLTag(buffer, 2, "dumpTable", dumpTable);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public void queryOptionsSetup(ExtensibleDialog dialog) {
+		String helpString = "\n";
+		dialog.appendToHelpString(helpString);
+
+		useWeightsBox = dialog.addCheckBox("consider tree weights", useWeights.getValue());
+		frequencyField = dialog.addDoubleField("required frequency of clades: ", frequencyLimit, 5, 0.00, 1.00);
+		dumpTableBox = dialog.addCheckBox("write group frequency list", dumpTable);
+	}
+
+	/*.................................................................................................................*/
+	public void queryOptionsProcess(ExtensibleDialog dialog) {
+		useWeights.setValue(useWeightsBox.getState());
+		double freq = frequencyField.getValue();
+		if (MesquiteDouble.isCombinable(freq))
+			if (freq<0.5) {
+				frequencyLimit=0.5;
+				logln("Required frequency must be >0.5");
+			}
+			else
+				frequencyLimit=freq;
+		dumpTable = dumpTableBox.getState();
+	}
+
+
+	public void addTree(Tree t){
+		if (t==null)
+			return;
+		if (useWeights.getValue()) {
+			bipartitions.setUseWeights(useWeights.getValue());
+			MesquiteDouble md = (MesquiteDouble)((Attachable)t).getAttachment(TreesManager.WEIGHT);
+			if (md != null) {
+				if (md.isCombinable())
+					bipartitions.setWeight(md.getValue());
+				else
+					bipartitions.setWeight(1.0);
+			} else
+				bipartitions.setWeight(1.0);
+
+		}
+		bipartitions.addTree(t);
+	}
+	/*.................................................................................................................*/
+	public void initialize() {
+		bipartitions.initialize();
+		if (bipartitions!=null) {
+			bipartitions.setMode(BipartitionVector.MAJRULEMODE);
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void afterConsensus() {
+		if (dumpTable)
+			bipartitions.dump();
+ 	}
+ 
+
+	public Tree getConsensus(){
+		Tree t = bipartitions.makeTree(consensusFrequencyLimit());
+		afterConsensus();
+		return t;
+	}
+	/*.................................................................................................................*/
+	public boolean useWeights() {
+		return useWeights.getValue();
+	}
+
+	/*.................................................................................................................*/
+	public double consensusFrequencyLimit() {
+		return frequencyLimit;
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}   	 
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	public double getFrequencyLimit() {
+		return frequencyLimit;
+	}
+	public void setFrequencyLimit(double frequencyLimit) {
+		this.frequencyLimit = frequencyLimit;
+	}
+	public boolean getUseWeights() {
+		return useWeights.getValue();
+	}
+	public void setUseWeights(boolean b) {
+		useWeights.setValue(b);
+	}
+
+}
\ No newline at end of file
diff --git a/Source/mesquite/consensus/Notes/Consensus Notes b/Source/mesquite/consensus/Notes/Consensus Notes
new file mode 100644
index 0000000..9bc4861
--- /dev/null
+++ b/Source/mesquite/consensus/Notes/Consensus Notes	
@@ -0,0 +1,38 @@
+Consensus Tree
+	snaphshots?
+	WAYNE: truly incremental with TreesDirectlyFromFile
+	WAYNE: if two tree blocks, and do ConsensusTrees>Stored Tree Blocks, doesn't query for which block
+	better storage for maj rule values on branches
+	for majrule, cycle get whole bipartition vector for each tree and compare all at once?
+	order bipartition vector based upon first integer in bits
+
+
+Add AverageStandardDeviation of split frequencies method to BipartitionVector
+
+
+
+
+===========
+Our code, using Bits
+
+Bembidion 545 trees
+	majrule:  1.641 seconds
+	strict:  1.567 seconds
+
+100RandomTrees (200 taxa)
+	majrule: 33.002 seconds
+	strict: 0.312 seconds
+
+
+============
+
+TSV code
+
+Bembidion 545 trees
+	majrule:  
+	strict:  
+
+100RandomTrees (200 taxa)
+	majrule: 
+	strict: 
+
diff --git a/Source/mesquite/consensus/Notes/Examples/BembidionWithTrees b/Source/mesquite/consensus/Notes/Examples/BembidionWithTrees
new file mode 100644
index 0000000..a3617b3
--- /dev/null
+++ b/Source/mesquite/consensus/Notes/Examples/BembidionWithTrees
@@ -0,0 +1,986 @@
+#NEXUS
+[written Fri Feb 08 07:18:57 PST 2008 by Mesquite  version 2.01+ (build j49) at Odontium.local/10.0.1.3]
+
+BEGIN TAXA;
+	TITLE Untitled_Block_of_Taxa;
+	DIMENSIONS NTAX=53;
+	TAXLABELS
+		balli foveum argenteolum alaskense semenovi stenoderum carinula velox lapponicum punctatostriatum hesperium lorquinii zephyrum l._levettei l._carrianum inaequale litorale conicolle chloropus fusiforme aeneipes sp._nr._aenulum aenulum durangoense arizonae confusum sculpturatum carinatum coxendix robusticolle persimile striatum foraminosum bowditchii americanum b._bifossulatum b._cheyennense rufotinctum integrum honestum antiquum sp._17 chalceum quadrimaculatum timidum graphicum umbratum [...]
+	;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  'Matrix in file "Bembidion"';
+	DIMENSIONS  NCHAR=85;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1 2 3 4 5 6 7 8";
+	CHARSTATELABELS 
+		1 silver_spots /  absent present, 2 interval_3_micro. /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 3 'interval 4+5 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 4 'interval 6+7 micro.' /  absent v._slight_mirrors slight_mirrors distinct_mirrors, 5 outer_mirror /  joined isolated, 6 silver_spot /  restricted_to_3rd also_on_4th, 7 elytral_microsculpture /  isodiametric slightly_trans. transverse, 8 suborbital_setae /  absent 'short_+_sparse_denser', [...]
+	MATRIX
+	balli             1110-00(1 2)1000111000000020(0 1)02(1 2)0000020300100204020-0000002021132222010023013322101002000
+	foveum            1110-00(1 2)10(0 1)1111000000020(0 1)0210000020300100204020-00000020211322230100230133220010(0 1)2???
+	argenteolum       13(2 3)(0 1)-002000211000000(0 1)020(0 1)0020000020010100202-00-00(0 1)00022(2 3 4)1??01?????????1?3?2?????????
+	alaskense         13(2 3)0-(0 1)02001011010000(0 1)0200001000002(0 1)010100202-00-00100022(3 4)1110100100023013322101000100
+	semenovi          1220-002000311000000102000020000022110100202-00-0000?????????????????????????????????
+	stenoderum        133(0 2)000(1 2)000021100000002010030001020310120001-00-0000003021???????????????????????????
+	carinula          13(0 1 2)0-00210(0 1)111100000002030(1 2)20000020300100002-00-00000013(4 5 6)0110100301121000000?01113103
+	velox             13(0 1 2)1-0021000111000000020(0 1)0(0 1)30000020300120004-00-00000020(1 2)1???????????????????????????
+	lapponicum        13(0 1 2 3)(0 2)000210(0 1)01110000000201013000002(0 1)200120004010-10000020(1 2)1130221121123010302101113002
+	punctatostriatum  13(0 1 2)1-0001002110000120200(0 1)0(0 1)300000200001(0 1)0004-00-00000020(2 3)1132031040110111312110?01000
+	hesperium         1(2 3)3(0 2)0(0 1)(0 1 2)1000011100000(0 1)020(0 1)0(1 2)100100202001(0 1)10040(0 1)0-00(0 1)0002101022021000023013322101000000
+	lorquinii         1331-(0 1)0(0 1)0000111000001020(0 1)0210000020200122004-00-00(0 1)00020(1 2)1022021000023013322101000000
+	zephyrum          133(2 3)0(0 1)02101011100002(0 1)020(0 1)021(0 1 2)000020200101004020-00(0 1)0002(0 1 2)(1 2 3)103(0 1 2)021000023013322101000000
+	l._levettei       1333010210(0 1)0111000020200(0 1)021(0 1 2)000020200103204-00-00000020(2 3)10?2021000023013322101000000
+	l._carrianum      1333010210(0 1)0111000020200(0 1)0212000020200103204-00-00000020(2 3)10(2 3)2021000023013322101000000
+	inaequale         1333(0 1)(0 1)0(0 1 2)(0 1)0(0 1)0111000020200(0 1)0(0 1 2)120(0 1)(0 1)020200103204-01000200020(1 2)1022021000023013322101000000
+	litorale          1333(0 1)(0 1)02(0 1)0(0 1)010100000102000(1 2)1(1 2)000020200103004-01000000020218??????????????????????????
+	conicolle         1333(0 1)(0 1)02000010?00002(0 1)120(0 1)0(1 2)1(0 1)000020200103004-0100000002021???????????????????????????
+	chloropus         0110--0001-011?00000002100030002020?00100202010-0000?????????????????????????????????
+	fusiforme         0220--0001-011?00000002100030002020?00100101-00-0000?????????????????????????????????
+	aeneipes          0220--0001-011?00000002100030002020200100000--100100001021???????????????????????????
+	sp._nr._aenulum   0000--2001-011100000002100030002000300100002-00-0000?????????????????????????????????
+	aenulum           0000--0001-011100000002000030001000300100104010-00000030(4 5)1111000200023013322101001000
+	durangoense       0000--0001-011?00000002010030000020200123204010-00000020(2 3)1???????????????????????????
+	arizonae          0000--2001-011101101002010030021010300100014110-00(0 1)000303111?????????????????????????
+	confusum          0000--2011-011101102020010030011010300100014110-00000030(2 3)1112023010023013322101001000
+	sculpturatum      0000--1011-01?101102002020030021020300100?14110-0000?????????????????????????????????
+	carinatum         0000--1011-011100000002010030021020200102004-00-0001?????????????????????????????????
+	coxendix          0110--00(0 1)1-0111000000010100300110202001(0 2)2104-00-00010020(1 2 3)1112023010023013322101000000
+	robusticolle      0000--(0 1 2)(0 1)11-011?00000002030030001020?00100004020-0000001231???????????????????????????
+	persimile         0111--0(0 1)11-01?1000000020100300000202001(1 2)02?4010-0010002021???????????????????????????
+	striatum          0110--0211-0111000000020(0 1)0(0 1)20000020200??0204-0??00000020(2 3 4)111?????????????????????????
+	foraminosum       0111--011(0 1)-01??00000002000(0 1)(1 2)0200020300110204010-00(0 1)00020(2 3)1??2023000023013322101000000
+	bowditchii        0110--0011-0111000000020(0 1)0(0 1)20000020300100004-01000000020(1 2)1112023000023013322101000???
+	americanum        0000--0211-01??00001002000020201020?00100204-01100(0 1)00020211??????????????????????????
+	b._bifossulatum   0221--1211-0111000000020002(1 2)0201020300200204-01100200020211??????????????????????????
+	b._cheyennense    0221--1211-0111000020220002(1 2)0201020?00200204-01100(1 2)00020(2 3)11?2023030021012312101000???
+	rufotinctum       0000--0111-01?100000002000000002020?00300003010-00000030(2 3)11??????????????????????????
+	integrum          0000--2011-01?100000002000000002020200300004020-00000030(2 3)1120023000022013322101002???
+	honestum          0000--0211-01?100000002000000002020200300004020-00200030(1 2)112?????????????????????????
+	antiquum          0000--(0 1 2)211-01?1000000020000000020202013000040(1 2)0-01100031(2 3)1120000000022012322101??3000
+	sp._17            0000--2111-01?100000002000000002020?01300203-00-01100030(3 4)161?????????????????????????
+	chalceum          0000--2(1 2)11-01?100000002000000002020201300004-00-0110003021220023000023013322101103???
+	quadrimaculatum   0000--?11(0 1)-01?010??000203100000202000010??00--0-00001020(2 3)11?001?000023013322101101???
+	timidum           0000--0(0 1)10-01?000??000203100000202020010??00--0-00000000211?0023000023013322101101???
+	graphicum         0000--2(0 1)10-01?1000?00020210000020202000???00--0-0000102021110023000023013322101002010
+	umbratum          0000--0010-01??00??20200210000020202000???00--0-0000102021110023000023013322101002010
+	concolor          0000--2111-01?100??0012021000002020?00100202-00-00001030(2 3)11(2 3)0021000023013322101112000
+	salebratum        0000--2011-01??00??00120(0 1)1010002120?00100203-00-00001020211(2 3)002200002301332210111(0 2)000
+	planatum          0000--0(1 2)11-0111000000020210000021202??100204-00-0000100101110011101123013322101102???
+	obtusum           0000--2011-01???0?000020(1 2)?0(2 3)0002120?00100?01-00-00(0 1)0110021110011000023013322101102???
+	interventor       0000--2(0 1)1(0 1)-01?0100101020(1 2)00300020200000???02020-00101000211?0021100023013322101000000
+	Asa._alaskanum    0000--221?-01?010000002000000???020000????00--0-00001100(2 3)11100211511001?3?1??00?00???
+
+;
+
+END;
+BEGIN TREES;
+	Title All_Rerootings_of_One_Tree;
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE 'Modified from island.1.1 (#1)' = ((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),(52,53));
+	TREE 'Modified from island.1.1 (#2)' = (((45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))))),(52,53)),44);
+	TREE 'Modified from island.1.1 (#3)' = ((44,(52,53)),(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))))));
+	TREE 'Modified from island.1.1 (#4)' = ((((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))),(44,(52,53))),45);
+	TREE 'Modified from island.1.1 (#5)' = ((45,(44,(52,53))),((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))));
+	TREE 'Modified from island.1.1 (#6)' = ((46,47),((((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))),(45,(44,(52,53)))));
+	TREE 'Modified from island.1.1 (#7)' = ((47,((((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))),(45,(44,(52,53))))),46);
+	TREE 'Modified from island.1.1 (#8)' = ((46,((((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))),(45,(44,(52,53))))),47);
+	TREE 'Modified from island.1.1 (#9)' = (((46,47),(45,(44,(52,53)))),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))))));
+	TREE 'Modified from island.1.1 (#10)' = (((48,49),(50,51)),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53))))));
+	TREE 'Modified from island.1.1 (#11)' = ((48,49),((50,51),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53)))))));
+	TREE 'Modified from island.1.1 (#12)' = ((49,((50,51),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53))))))),48);
+	TREE 'Modified from island.1.1 (#13)' = ((48,((50,51),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53))))))),49);
+	TREE 'Modified from island.1.1 (#14)' = (((48,49),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53)))))),(50,51));
+	TREE 'Modified from island.1.1 (#15)' = ((51,((48,49),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53))))))),50);
+	TREE 'Modified from island.1.1 (#16)' = ((50,((48,49),(((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))),((46,47),(45,(44,(52,53))))))),51);
+	TREE 'Modified from island.1.1 (#17)' = ((((48,49),(50,51)),((46,47),(45,(44,(52,53))))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))));
+	TREE 'Modified from island.1.1 (#18)' = ((((38,40),(41,(42,43))),39),(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))));
+	TREE 'Modified from island.1.1 (#19)' = (((38,40),(41,(42,43))),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))));
+	TREE 'Modified from island.1.1 (#20)' = ((38,40),((41,(42,43)),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))));
+	TREE 'Modified from island.1.1 (#21)' = ((40,((41,(42,43)),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),38);
+	TREE 'Modified from island.1.1 (#22)' = ((38,((41,(42,43)),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),40);
+	TREE 'Modified from island.1.1 (#23)' = (((38,40),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))),(41,(42,43)));
+	TREE 'Modified from island.1.1 (#24)' = (((42,43),((38,40),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),41);
+	TREE 'Modified from island.1.1 (#25)' = ((41,((38,40),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),(42,43));
+	TREE 'Modified from island.1.1 (#26)' = ((43,(41,((38,40),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),42);
+	TREE 'Modified from island.1.1 (#27)' = ((42,(41,((38,40),(39,(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),43);
+	TREE 'Modified from island.1.1 (#28)' = ((((38,40),(41,(42,43))),(((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))),39);
+	TREE 'Modified from island.1.1 (#29)' = (((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30)))));
+	TREE 'Modified from island.1.1 (#30)' = ((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))));
+	TREE 'Modified from island.1.1 (#31)' = (((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))));
+	TREE 'Modified from island.1.1 (#32)' = ((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))));
+	TREE 'Modified from island.1.1 (#33)' = (((35,(36,37)),10),(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))));
+	TREE 'Modified from island.1.1 (#34)' = ((35,(36,37)),(10,(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))));
+	TREE 'Modified from island.1.1 (#35)' = (((36,37),(10,(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),35);
+	TREE 'Modified from island.1.1 (#36)' = ((35,(10,(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),(36,37));
+	TREE 'Modified from island.1.1 (#37)' = ((37,(35,(10,(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),36);
+	TREE 'Modified from island.1.1 (#38)' = ((36,(35,(10,(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),37);
+	TREE 'Modified from island.1.1 (#39)' = (((35,(36,37)),(((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),10);
+	TREE 'Modified from island.1.1 (#40)' = ((((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13))));
+	TREE 'Modified from island.1.1 (#41)' = ((31,33),(((1,2),((11,(12,((((14,15),16),18),17))),13)),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))));
+	TREE 'Modified from island.1.1 (#42)' = ((33,(((1,2),((11,(12,((((14,15),16),18),17))),13)),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),31);
+	TREE 'Modified from island.1.1 (#43)' = ((31,(((1,2),((11,(12,((((14,15),16),18),17))),13)),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),33);
+	TREE 'Modified from island.1.1 (#44)' = (((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),((1,2),((11,(12,((((14,15),16),18),17))),13)));
+	TREE 'Modified from island.1.1 (#45)' = ((1,2),(((11,(12,((((14,15),16),18),17))),13),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))));
+	TREE 'Modified from island.1.1 (#46)' = ((2,(((11,(12,((((14,15),16),18),17))),13),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),1);
+	TREE 'Modified from island.1.1 (#47)' = ((1,(((11,(12,((((14,15),16),18),17))),13),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),2);
+	TREE 'Modified from island.1.1 (#48)' = (((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),((11,(12,((((14,15),16),18),17))),13));
+	TREE 'Modified from island.1.1 (#49)' = ((11,(12,((((14,15),16),18),17))),(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))));
+	TREE 'Modified from island.1.1 (#50)' = (((12,((((14,15),16),18),17)),(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))),11);
+	TREE 'Modified from island.1.1 (#51)' = ((11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))),(12,((((14,15),16),18),17)));
+	TREE 'Modified from island.1.1 (#52)' = ((((((14,15),16),18),17),(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),12);
+	TREE 'Modified from island.1.1 (#53)' = ((12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),((((14,15),16),18),17));
+	TREE 'Modified from island.1.1 (#54)' = ((((14,15),16),18),(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))));
+	TREE 'Modified from island.1.1 (#55)' = (((14,15),16),(18,(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))))));
+	TREE 'Modified from island.1.1 (#56)' = ((14,15),(16,(18,(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))))));
+	TREE 'Modified from island.1.1 (#57)' = ((15,(16,(18,(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))))))),14);
+	TREE 'Modified from island.1.1 (#58)' = ((14,(16,(18,(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))))))),15);
+	TREE 'Modified from island.1.1 (#59)' = (((14,15),(18,(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))))),16);
+	TREE 'Modified from island.1.1 (#60)' = ((((14,15),16),(17,(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))))),18);
+	TREE 'Modified from island.1.1 (#61)' = (((((14,15),16),18),(12,(11,(13,((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))),17);
+	TREE 'Modified from island.1.1 (#62)' = (((11,(12,((((14,15),16),18),17))),((1,2),((31,33),(((35,(36,37)),10),(32,(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),13);
+	TREE 'Modified from island.1.1 (#63)' = (((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),(34,(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),32);
+	TREE 'Modified from island.1.1 (#64)' = ((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),(((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))),34);
+	TREE 'Modified from island.1.1 (#65)' = (((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))));
+	TREE 'Modified from island.1.1 (#66)' = ((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))));
+	TREE 'Modified from island.1.1 (#67)' = (((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))));
+	TREE 'Modified from island.1.1 (#68)' = ((19,((20,21),(((3,5),4),((6,(8,9)),7)))),(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))));
+	TREE 'Modified from island.1.1 (#69)' = ((((20,21),(((3,5),4),((6,(8,9)),7))),(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),19);
+	TREE 'Modified from island.1.1 (#70)' = ((19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),((20,21),(((3,5),4),((6,(8,9)),7))));
+	TREE 'Modified from island.1.1 (#71)' = ((20,21),((((3,5),4),((6,(8,9)),7)),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))));
+	TREE 'Modified from island.1.1 (#72)' = ((21,((((3,5),4),((6,(8,9)),7)),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),20);
+	TREE 'Modified from island.1.1 (#73)' = ((20,((((3,5),4),((6,(8,9)),7)),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),21);
+	TREE 'Modified from island.1.1 (#74)' = (((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),(((3,5),4),((6,(8,9)),7)));
+	TREE 'Modified from island.1.1 (#75)' = (((3,5),4),(((6,(8,9)),7),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))));
+	TREE 'Modified from island.1.1 (#76)' = ((3,5),(4,(((6,(8,9)),7),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))));
+	TREE 'Modified from island.1.1 (#77)' = ((5,(4,(((6,(8,9)),7),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),3);
+	TREE 'Modified from island.1.1 (#78)' = ((3,(4,(((6,(8,9)),7),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),5);
+	TREE 'Modified from island.1.1 (#79)' = (((3,5),(((6,(8,9)),7),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))),4);
+	TREE 'Modified from island.1.1 (#80)' = ((((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))),((6,(8,9)),7));
+	TREE 'Modified from island.1.1 (#81)' = ((6,(8,9)),(7,(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))));
+	TREE 'Modified from island.1.1 (#82)' = (((8,9),(7,(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),6);
+	TREE 'Modified from island.1.1 (#83)' = ((6,(7,(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))))))),(8,9));
+	TREE 'Modified from island.1.1 (#84)' = ((9,(6,(7,(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))),8);
+	TREE 'Modified from island.1.1 (#85)' = ((8,(6,(7,(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))))),9);
+	TREE 'Modified from island.1.1 (#86)' = (((6,(8,9)),(((3,5),4),((20,21),(19,(22,(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))))),7);
+	TREE 'Modified from island.1.1 (#87)' = (((19,((20,21),(((3,5),4),((6,(8,9)),7)))),(23,(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),22);
+	TREE 'Modified from island.1.1 (#88)' = ((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),(((24,(28,29)),(((25,26),27),30)),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),23);
+	TREE 'Modified from island.1.1 (#89)' = (((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))),((24,(28,29)),(((25,26),27),30)));
+	TREE 'Modified from island.1.1 (#90)' = ((24,(28,29)),((((25,26),27),30),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))));
+	TREE 'Modified from island.1.1 (#91)' = (((28,29),((((25,26),27),30),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),24);
+	TREE 'Modified from island.1.1 (#92)' = ((24,((((25,26),27),30),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),(28,29));
+	TREE 'Modified from island.1.1 (#93)' = ((29,(24,((((25,26),27),30),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),28);
+	TREE 'Modified from island.1.1 (#94)' = ((28,(24,((((25,26),27),30),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),29);
+	TREE 'Modified from island.1.1 (#95)' = (((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))),(((25,26),27),30));
+	TREE 'Modified from island.1.1 (#96)' = (((25,26),27),(30,((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))));
+	TREE 'Modified from island.1.1 (#97)' = ((25,26),(27,(30,((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))));
+	TREE 'Modified from island.1.1 (#98)' = ((26,(27,(30,((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),25);
+	TREE 'Modified from island.1.1 (#99)' = ((25,(27,(30,((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))))),26);
+	TREE 'Modified from island.1.1 (#100)' = (((25,26),(30,((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53))))))))))),27);
+	TREE 'Modified from island.1.1 (#101)' = ((((25,26),27),((24,(28,29)),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((38,40),(41,(42,43))),39),(((48,49),(50,51)),((46,47),(45,(44,(52,53)))))))))),30);
+	TREE 'Modified from island.1.1 (#102)' = (((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),53),52);
+	TREE 'Modified from island.1.1 (#103)' = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+
+END;
+
+
+BEGIN TREES;
+	Title All_545_MPTs;
+	LINK Taxa = Untitled_Block_of_Taxa;
+	TRANSLATE
+		1 balli,
+		2 foveum,
+		3 argenteolum,
+		4 alaskense,
+		5 semenovi,
+		6 stenoderum,
+		7 carinula,
+		8 velox,
+		9 lapponicum,
+		10 punctatostriatum,
+		11 hesperium,
+		12 lorquinii,
+		13 zephyrum,
+		14 l._levettei,
+		15 l._carrianum,
+		16 inaequale,
+		17 litorale,
+		18 conicolle,
+		19 chloropus,
+		20 fusiforme,
+		21 aeneipes,
+		22 sp._nr._aenulum,
+		23 aenulum,
+		24 durangoense,
+		25 arizonae,
+		26 confusum,
+		27 sculpturatum,
+		28 carinatum,
+		29 coxendix,
+		30 robusticolle,
+		31 persimile,
+		32 striatum,
+		33 foraminosum,
+		34 bowditchii,
+		35 americanum,
+		36 b._bifossulatum,
+		37 b._cheyennense,
+		38 rufotinctum,
+		39 integrum,
+		40 honestum,
+		41 antiquum,
+		42 sp._17,
+		43 chalceum,
+		44 quadrimaculatum,
+		45 timidum,
+		46 graphicum,
+		47 umbratum,
+		48 concolor,
+		49 salebratum,
+		50 planatum,
+		51 obtusum,
+		52 interventor,
+		53 Asa._alaskanum;
+	TREE island.1.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),10),((31,33),((1,2),((11,(12,((((14,15),16),18),17))),13)))),32),34),((((19,((20,21),(((3,5),4),((6,(8,9)),7)))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.8.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,(((14,15),16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((((14,15),16),18),17)))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,(15,16)),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.8.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),31),(32,((1,2),((((3,5),4),((11,12),(13,((14,15,16),(17,18))))),((((6,7),8),9),10))))),34),29),((((25,26),27),28),30)),24),23),(19,(20,21))),22)))))),52));
+	TREE island.12a.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12a.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12a.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12a.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),(24,(28,29))),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,27),26)),30))))))),52));
+	TREE island.12b.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.12b.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),(25,(26,27))),30))))))),52));
+	TREE island.12b.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(19,(20,21))),29),24),28),(((22,23),((25,26),27)),30))))))),52));
+	TREE island.32.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,5),4))),22),23),24))))))),52));
+	TREE island.32.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.32.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),((3,4),5))),22),23),24))))))),52));
+	TREE island.36.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((35,(36,37)),(32,((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18)))))))),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),(((11,12),((((14,15),16),18),17)),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.36.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),32),(31,33)),34),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.40.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,5),4))),22),23))))))),52));
+	TREE island.40.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,5),4))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,5),4))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((25,26),27),(28,29)),30)),(((19,((20,21),((3,4),5))),22),23))))))),52));
+	TREE island.40.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),((((19,((20,21),((3,4),5))),22),23),((((25,26),27),(28,29)),30)))))))),52));
+	TREE island.40.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),((((25,26),27),(28,29)),30))))))),52));
+	TREE island.40.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),30),(((25,26),27),(28,29)))))))),52));
+	TREE island.40.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.40.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32),34),33),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),31),24),(((19,((20,21),((3,4),5))),22),23)),(((25,26),27),(28,29))),30)))))),52));
+	TREE island.44.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.2 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.3 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.4 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.5 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.11 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.12 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.13 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.14 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.15 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.16 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.17 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.18 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.19 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.20 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.21 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.22 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.23 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.24 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.25 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.26 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.27 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.28 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.29 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.30 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.31 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.32 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.33 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.35 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.37 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),(((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.39 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.41 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(23,((24,(28,29)),(((25,26),27),30)))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.42 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.43 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.44.44 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),(24,(28,29))),(23,(((25,26),27),30))),((19,(20,21)),22)))),(48,49)),(50,51)),52));
+	TREE island.48.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((14,(15,16)),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17))))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,16),15),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,21),(((3,5),4),6))),22),23),24))))))),52));
+	TREE island.48.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,(((14,15),16),(17,18))))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,12),(13,((((14,15),16),18),17)))))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),32),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),(((11,12),((((14,15),16),18),17)),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),33),31),(32,((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13))))),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.48.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,(20,(21,(((3,5),4),6)))),22),23),24))))))),52));
+	TREE island.48.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((1,2),(((7,(8,9)),10),((11,(12,((((14,15),16),18),17))),13)))),32),34),29),((((25,26),27),28),30)),((((19,((20,(((3,5),4),6)),21)),22),23),24))))))),52));
+	TREE island.68.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),31),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),33),31),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),((31,33),(1,2))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),(1,2)),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(31,33)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),(31,33)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.68.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),(31,33)),34),((24,(28,29)),(((25,26),27),30))),23),(19,(20,21))),22)))))),52));
+	TREE island.84.1 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.3 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.4 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.5 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.6 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.7 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.8 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.9 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.10 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.20 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.21 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.22 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.23 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.24 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.25 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.26 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.27 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.28 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.29 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.30 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.31 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.32 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.33 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.34 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.35 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.36 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.37 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.38 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.39 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.40 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.41 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),32),34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),(1,2)),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),34),(32,((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.66 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.67 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.68 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),32),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.69 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.70 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.71 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),32),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.72 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.73 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.74 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),34),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.75 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.76 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.77 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),33),((32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18))))))),34)),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.78 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.79 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.80 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),34),(1,2)),33),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.81 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.82 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.83 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),(((((((((((35,(36,37)),33),34),(32,(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),(1,2)),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.84.84 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((((((35,(36,37)),32,34),((1,2),(((3,5),4),(((((6,7),8),9),10),((11,12),(13,((14,15,16),(17,18)))))))),33),31),24),((((25,26),27),(28,29)),30)),23),(19,(20,21))),22)))))),52));
+	TREE island.160.1 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.2 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.3 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.4 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.5 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.6 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.7 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.8 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.9 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.10 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.11 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.12 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.13 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.14 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.15 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.16 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.17 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.18 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.19 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.20 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.21 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.22 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.23 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.24 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.25 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.26 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.27 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.28 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.29 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.30 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.31 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.32 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.33 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.34 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.35 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.36 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.37 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.38 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.39 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.40 = (53,((((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.41 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.42 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.43 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.44 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.45 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.46 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.47 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.48 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.49 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.50 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.51 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.52 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.53 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.54 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.55 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.56 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.57 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.58 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.59 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.60 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.61 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.62 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.63 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.64 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.65 = (53,((44,(45,((46,47),(((48,49),(50,51)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.66 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.67 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.68 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.69 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.70 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.71 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.72 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.73 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.74 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.75 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.76 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.77 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.78 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.79 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.80 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.81 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.82 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.83 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.84 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.85 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.86 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.87 = (53,(((((44,45),(46,47)),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.88 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.89 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.90 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.91 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.92 = (53,((((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.93 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.94 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.95 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.96 = (53,((((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),(48,49)),(50,51)),52));
+	TREE island.160.97 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.98 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.99 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.100 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.101 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.102 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.103 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.104 = (53,((44,(45,((46,47),(((48,49),(50,51)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.105 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.106 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.107 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.108 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.109 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.110 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.111 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.112 = (53,((44,(45,((46,47),(((48,49),(50,51)),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30))))))))),52));
+	TREE island.160.113 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.114 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.115 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.116 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.117 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.118 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.119 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.120 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.121 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.122 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.123 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.124 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.125 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.126 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.127 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.128 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.129 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.130 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.131 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,5),4))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.132 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,15),16),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.133 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.134 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.135 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.136 = (53,((((((44,45),47),46),((48,49),(50,51))),((38,((39,(41,(42,43))),40)),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.137 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.138 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.139 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.140 = (53,(((((44,45),(46,47)),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.141 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.142 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.143 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.144 = (53,(((((44,45),(46,47)),((38,(39,(41,(42,43))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),((48,49),(50,51))),52));
+	TREE island.160.145 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.146 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.147 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.148 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,40),(39,(41,(42,43)))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.149 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.150 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.151 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.152 = (53,((((((44,45),47),46),((48,49),(50,51))),(((38,(39,(41,(42,43)))),40),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.153 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.154 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.155 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.156 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),(41,(42,43))),39),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.157 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((((14,15),16),18),17)))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.158 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,(12,((((14,15),16),18),17))),13)))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.159 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,((14,(15,16)),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+	TREE island.160.160 = (53,((((((44,45),47),46),((48,49),(50,51))),((((38,40),39),(41,(42,43))),((((((35,(36,37)),32),34),(31,33)),((1,2),(((((6,7),8),9),10),((11,12),(13,(((14,16),15),(17,18))))))),((((19,((20,21),((3,4),5))),22),23),((24,(28,29)),(((25,26),27),30)))))),52));
+
+END;
+
+
+BEGIN paup;
+
+END;
+BEGIN LABELS;
+	CHARGROUPLABEL Adult_External COLOR = (RGB 0.262745098 0.38431373 0.90980392) ;
+	CHARGROUPLABEL Male_Genitalia COLOR = (RGB 1.0 0.59607843 0.03137255) ;
+	CHARGROUPLABEL Female_Genitalia COLOR = (RGB 0.85490196 0.96078431 0.05882353) ;
+	CHARGROUPLABEL Chromosomes COLOR = (RGB 0.125490196 0.72941176 0.125490196) ;
+	CHARGROUPLABEL Larval_Structure COLOR = (RGB 0.72941176 0.39607843 0.125490196) ;
+	CHARGROUPLABEL Adult COLOR = (RGB 0.72941176 0.0 0.02352941) ;
+
+
+END;
+
+BEGIN SETS;
+	CHARSET Adult_External   =   1 -  36;
+	CHARSET Male_Genitalia   =   37 -  52;
+	CHARSET Female_Genitalia   =   53 -  58;
+	CHARSET Chromosomes   =   59 -  60;
+	CHARSET Larvae   =   61 -  85;
+
+	CHARPARTITION * UNTITLED  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION body_parts  =  Adult_External :  1 -  36, Male_Genitalia :  37 -  52, Female_Genitalia :  53 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+	CHARPARTITION 'adult/larvae'  =  Adult :  1 -  58, Chromosomes :  59 -  60, Larval_Structure :  61 -  85;
+
+END;
+
+BEGIN ASSUMPTIONS;
+	OPTIONS  DEFTYPE =        unord PolyTcount =        MINSTEPS;
+	TYPESET * UNTITLED   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+TYPESET types   =  unord:  34 64, ord:  1 -  33 35 -  63 65 -  85;
+
+	EXSET larval_only  =  1 -  60;
+EXSET adult_external  =  37 -  85;
+EXSET genitalia  =  1 -  36 59 -  85;
+
+	WTSET 123polyerror  =  3: 1 -  2 12 -  14 17 -  20 22 -  24 26 30 -  31 33 -  34 39 41 -  44 47 -  50 52 -  56 58 -  59 61 -  63 65 -  69 71 -  72 74 76 -  81 84 -  85 , 2: 3 -  7 9 -  10 15 -  16 21 25 29 32 36 -  38 57 64 70 73 75 83, 1: 8 8 11 27 -  28 35 40 45 -  46 51 60 82;
+WTSET 12error_only  =  2: 1 -  7 9 -  10 12 -  14 17 -  26 29 -  31 33 -  34 39 41 -  44 47 -  50 52 -  59 61 -  63 65 -  69 71 -  72 74 -  81 84 -  85 , 1: 8 8 11 15 -  16 27 -  28 32 35 -  38 40 45 -  46 51 60 64 70 73 82 -  83;
+
+END;
+
+BEGIN MacClade;
+	Version 4.0  84;
+	LastModified -1179493078;
+	FileSettings editor '0' '0' '1' '1';
+	Singles 000;
+	Editor 0001100111111110010001001 '0' '24'         Geneva '9' '100' '1'         all;
+	EditorPosition '46' '9' '435' '411';
+	TreeWindowPosition '46' '6' '699' '1102';
+	ListWindow Characters open Geneva '9' '47' '433' '273' '434'         001;
+	ListWindow Taxa closed Geneva '9' '50' '10' '276' '490'         100000;
+	ListWindow Trees closed Geneva '9' '50' '10' '276' '490';
+	ListWindow TypeSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow ExSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharSets closed Geneva '9' '145' '278' '121' '181';
+	ListWindow TaxSets closed Geneva '9' '50' '10' '276' '490';
+	ListWindow CharPartitions open Geneva '9' '506' '205' '129' '195';
+	ListWindow CharPartNames open Geneva '9' '483' '428' '161' '216';
+	ListWindow WtSets closed Geneva '9' '50' '10' '276' '490';
+	TextWindow AboutFile '250' '481' '212' '440'         Monaco '9' (        normal )         1;
+	ChartWindowPosition '50' '30' '688' '964';
+	StateNamesSymbols closed Geneva '9' '10' '431' '726' '192' '220';
+	WindowOrder  Text AboutFile List GroupLabels List CharPartitions Data List Characters;
+	OtherSymbols & /         00 ? -;
+	Correlation '0' '0' '1000' '0' '0'         10011010;
+	Salmo 00000001;
+	EditorFile '2';
+	ExportHTML _ MOSS '100'         110000;
+	PrettyPrint 10;
+	EditorToolsPosition '507' '32' '115' '165';
+	TreeToolsPosition '607' '5' '126' '138';
+	TreeWindowProgram 10;
+	TreeWindow 0000;
+	Continuous '0' '3'         1;
+	Calculations 0000001;
+	SummaryMode '0' '0'         0;
+	Charts  Geneva '9' (        normal )         0010;
+	NexusOptions '0' '0' '50'         001011011;
+	TipLabel '1';
+	TreeFont  Geneva '9' (        normal );
+	TreeShape  1.0 1.0 0100;
+	TraceLabels 0101;
+	ChartColors '0' '0' '65535' '9' '0'         1;
+	ChartBiggestSpot 1;
+	ChartPercent 10;
+	ChartBarWidth '10'         1;
+	ChartVerticalAxis 10101;
+	ChartMinMax '0';
+	TraceAllChangesDisplay '1'         1;
+	BarsOnBranchesDisplay '0' '0' '60000' '10000' '10000' '10000' '10000' '60000' '65000' '65000' '65000' '6' '1'         0000101;
+	ContinuousBranchLabels 0;
+	AllStatesBranchLabels 1;
+	IndexNotation '2'         1;
+	PrintTree  10.00 '2' '2' '2' '2' '2' '2' '2' '2' '2' '2' '2'         Geneva '9' (        normal )         Geneva '10' (        normal )         Geneva '9' (        normal )         Geneva '9' (        normal )         Geneva '9' (        bold )         Geneva '9' (        normal )         Geneva '9' (        normal ) '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '1' '1' '1' '1' '10' '0' '-39' '4' '-40' '0' '1' '2' [...]
+	MatchChar 00 .;
+	EntryInterpretation 01;
+	ColorOptions 11;
+	TreeTools '0' '5' '4' '0' '10' '4' '0'         00100111111101110;
+	EditorTools '0' '0' '0' '1000' '0' '0' '6' '3' '0'         100000101110001;
+	PairAlign '2' '2' '3' '2' '1' '1' '2' '1' '3'         1010;
+	BothTools '1';
+
+END;
+BEGIN NOTES;
+
+	TEXT  TAXA = Untitled_Block_of_Taxa TAXON = 5 TEXT = only_known_from_one_specimen;
+
+	TEXT   TAXON = 17 CHARACTER = 59 TEXT = 'From_Nettman_(1984),_in_den_Boer_et_al._"Carabid_Beetles._Their_Adaptations_and_Dynamics."';
+
+END;
+
+BEGIN CODONS;
+	CODESET * UNTITLED   =  universal:  1 -  85;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  85;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 3878556362151982295;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 9183510547325159755;
+			checksum 0 2915397944 null;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/consensus/SemistrictConsensusTree/SemistrictConsensusTree.java b/Source/mesquite/consensus/SemistrictConsensusTree/SemistrictConsensusTree.java
new file mode 100644
index 0000000..14632d9
--- /dev/null
+++ b/Source/mesquite/consensus/SemistrictConsensusTree/SemistrictConsensusTree.java
@@ -0,0 +1,66 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.consensus.SemistrictConsensusTree;
+
+import mesquite.consensus.lib.*;
+import mesquite.lib.*;
+
+	/* ======================================================================== */
+	/** Does semistrict consensus .*/
+
+	public class SemistrictConsensusTree extends BasicTreeConsenser   {
+		public String getName() {
+			return "Semistrict Consensus";
+		}
+		
+		public String getExplanation() {
+			return "Calculates the semistrict consensus tree." ;
+		}
+	  	public void addTree(Tree t){
+	  		if (t==null)
+	  			return;
+			bipartitions.addTree(t);
+		}
+	  	
+		/*.................................................................................................................*/
+	 	public void initialize() {
+			bipartitions.initialize();
+	 		if (bipartitions!=null)
+	 			bipartitions.setMode(BipartitionVector.SEMISTRICTMODE);
+	 	}
+
+	 	public Tree getConsensus(){
+			Tree t = bipartitions.makeTree();
+			return t;
+		}
+		/*.................................................................................................................*/
+		public boolean requestPrimaryChoice(){
+			return true;  
+		}
+
+		/*.................................................................................................................*/
+	   	public boolean isPrerelease(){
+	   		return false;  
+	   	}
+		/*.................................................................................................................*/
+		public boolean isSubstantive(){
+			return true;
+		}   	 
+		/*.................................................................................................................*/
+		public int getVersionOfFirstRelease(){
+			return 250;  
+		}
+
+	}
diff --git a/Source/mesquite/consensus/StrictConsensusTree/StrictConsensusTree.java b/Source/mesquite/consensus/StrictConsensusTree/StrictConsensusTree.java
new file mode 100644
index 0000000..eb29668
--- /dev/null
+++ b/Source/mesquite/consensus/StrictConsensusTree/StrictConsensusTree.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.consensus.StrictConsensusTree;
+
+import mesquite.consensus.lib.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** Does strict consensus .*/
+
+public class StrictConsensusTree extends BasicTreeConsenser   {
+	public String getName() {
+		return "Strict Consensus";
+	}
+	
+	public String getExplanation() {
+		return "Calculates the strict consensus tree." ;
+	}
+  	public void addTree(Tree t){
+		if (t==null)
+			return;
+		bipartitions.addTree(t);
+	}
+  	
+	/*.................................................................................................................*/
+ 	public void initialize() {
+		bipartitions.initialize();
+ 		if (bipartitions!=null)
+ 			bipartitions.setMode(BipartitionVector.STRICTMODE);
+ 	}
+
+ 	public Tree getConsensus(){
+		Tree t = bipartitions.makeTree();
+		return t;
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}   	 
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+}
diff --git a/Source/mesquite/consensus/aConsensusIntro/aConsensusIntro.java b/Source/mesquite/consensus/aConsensusIntro/aConsensusIntro.java
new file mode 100644
index 0000000..2a3053c
--- /dev/null
+++ b/Source/mesquite/consensus/aConsensusIntro/aConsensusIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.consensus.aConsensusIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aConsensusIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aConsensusIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Calculations for consensus trees.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Consensus Trees Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Consensus Trees Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/consensus/lib/BasicTreeConsenser.java b/Source/mesquite/consensus/lib/BasicTreeConsenser.java
new file mode 100644
index 0000000..dbb664a
--- /dev/null
+++ b/Source/mesquite/consensus/lib/BasicTreeConsenser.java
@@ -0,0 +1,181 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.consensus.lib;
+
+
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Label;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+public abstract class BasicTreeConsenser extends IncrementalConsenser   {
+	protected static final int ASIS=0;
+	protected static final int ROOTED =1;
+	protected static final int UNROOTED=2;
+	protected int rooting = ASIS;   // controls and preferences and snapshot should be in subclass
+
+	protected BipartitionVector bipartitions=null;
+	protected int treeNumber = 0;
+	boolean preferencesSet = false;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		bipartitions = new BipartitionVector();
+		loadPreferences();
+		if (!MesquiteThread.isScripting()) 
+			if (!queryOptions())
+				return false;
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void processMorePreferences (String tag, String content) {
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("rooting".equalsIgnoreCase(tag))
+			rooting = MesquiteInteger.fromString(content);
+		processMorePreferences(tag, content);
+		preferencesSet = true;
+	}
+	/*.................................................................................................................*/
+	public String prepareMorePreferencesForXML () {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "rooting", rooting);  
+		buffer.append(prepareMorePreferencesForXML());
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	
+	public void queryOptionsSetup(ExtensibleDialog dialog) {
+	}
+	/*.................................................................................................................*/
+	public void queryOptionsProcess(ExtensibleDialog dialog) {
+	}
+
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), getName() + " Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel(getName() + " Options");
+		String helpString = "Please choose the options for consensus trees. ";
+
+		dialog.appendToHelpString(helpString);
+
+		queryOptionsSetup(dialog);
+
+		
+		String[] rootingStrings = {"As specified in first tree", "Rooted", "Unrooted"};
+		Choice rootingChoice  = dialog.addPopUpMenu("Treat trees as rooted or unrooted:", rootingStrings, 0);
+
+
+		//TextArea PAUPOptionsField = queryFilesDialog.addTextArea(PAUPOptions, 20);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			queryOptionsProcess(dialog);
+			int choiceValue = rootingChoice.getSelectedIndex();
+			if (choiceValue>=0)
+				rooting = choiceValue;
+			storePreferences();
+
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+  	public void reset(Taxa taxa){
+  		if (bipartitions==null)
+  			bipartitions = new BipartitionVector();
+  		else
+  			bipartitions.removeAllElements();		// clean bipartition table
+		bipartitions.setTaxa(taxa);
+		bipartitions.zeroFrequencies();
+		initialize();
+	}
+  	public abstract void addTree(Tree t);
+  	
+ 	public abstract Tree getConsensus();
+	/*.................................................................................................................*/
+ 	public void initialize() {
+ 		//bipartitions.initialize();
+ 	}
+	/*.................................................................................................................*/
+ 	public void afterConsensus() {
+ 	}
+
+	/*.................................................................................................................*/
+	//ASSUMES TREES HAVE ALL THE SAME TAXA
+	/*.................................................................................................................*/
+	public Tree consense(Trees list){
+		Taxa taxa = list.getTaxa();
+		
+		reset(taxa);
+		ProgressIndicator progIndicator=null;
+		//progIndicator = new ProgressIndicator(getProject(),getName(), "", list.size(), true);
+		if (progIndicator!=null){
+			progIndicator.start();
+		}
+	//	if (MesquiteTrunk.debugMode)
+	//		logln("\n Consensus Tree Calculations");
+		MesquiteTimer timer = new MesquiteTimer();
+		timer.start();
+		logln("");
+		for (treeNumber = 0; treeNumber < list.size(); treeNumber++){
+			if (treeNumber==0) {
+				switch (rooting) {
+				case ASIS: 
+					bipartitions.setRooted(list.getTree(0).getRooted());
+					break;
+				case ROOTED: 
+					bipartitions.setRooted(true);
+					break;
+				case UNROOTED: 
+					bipartitions.setRooted(false);
+					break;
+				}
+			}
+			addTree(list.getTree(treeNumber));
+			if (treeNumber%100==0)
+				log(".");
+			if (progIndicator!=null) {
+				progIndicator.setText("Processing tree " + (treeNumber+1));
+				progIndicator.spin();		
+				if (progIndicator.isAborted())
+					break;
+			}
+	//		if (MesquiteTrunk.debugMode)
+	//			logln(" tree: " + (treeNumber+1)+ ", bipartitions: " + bipartitions.size() + ", memory: " + MesquiteTrunk.getMaxAvailableMemory());
+		}
+		Tree t = getConsensus();
+		double time = 1.0*timer.timeSinceLast()/1000.0;
+		if (progIndicator!=null)
+			progIndicator.goAway();
+	//	afterConsensus();
+		logln("\n" + list.size() + " trees processed in " + time + " seconds");
+		return t;
+	}
+
+}
+
diff --git a/Source/mesquite/consensus/lib/Bipartition.java b/Source/mesquite/consensus/lib/Bipartition.java
new file mode 100644
index 0000000..065ddb0
--- /dev/null
+++ b/Source/mesquite/consensus/lib/Bipartition.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.consensus.lib;
+
+import mesquite.consensus.lib.Bipartition;
+import mesquite.lib.*;
+
+public class Bipartition {
+	Bits bits;
+	double freqDouble;
+	static final int numFreqs = 2;
+	long[] freq;   // have more than one in case want to split at things like avg std dev split frequencies
+	double splitLength;   // for storing branch lengths
+	boolean present = false;
+
+
+	public Bipartition(int numTaxa){
+		bits = new Bits(numTaxa);
+		freq = new long[numFreqs];
+		reset();
+	}
+	
+	public String toString(){
+		String s = "Bipartition ";
+		s += bits.toPlusMinusString();
+		s += "   FREQ: ";
+		for (int i = 0; i< freq.length; i++){
+			s += "  " + freq[i];
+		}
+		return s;
+	}
+	
+
+	void reset(){
+		for (int i=0;i<numFreqs; i++)
+			freq[i]=0;
+		splitLength = MesquiteDouble.unassigned;
+		freqDouble = 0.0;
+	}
+	void weightedIncrement(double weight){
+		if (MesquiteDouble.isCombinable(weight))
+			freqDouble+=weight;
+	}
+	void increment(){
+		freq[0]++;
+	}
+	void increment(int whichFreq){
+		freq[whichFreq]++;
+	}
+	public long getFreq(){
+		return freq[0];
+	}
+	public long getFreq(int whichFreq){
+		return freq[whichFreq];
+	}
+	public void setFreq(long freq){
+		this.freq[0]=freq;
+	}
+	public void setFreq(long freq, int whichFreq){
+		this.freq[whichFreq]=freq;
+	}
+	public double getSplitLength(){
+		return splitLength;
+	}
+	public void addToSplitLength(double length){
+		if (MesquiteDouble.isCombinable(length)) {
+			if (!MesquiteDouble.isCombinable(splitLength))
+				splitLength =0.0;
+			splitLength+= length;
+		}
+	}
+	public void avgSplitLength(boolean weighted){
+		if (MesquiteDouble.isCombinable(splitLength)) {
+			if (!weighted)
+				splitLength=splitLength/freq[0];
+			else
+				splitLength=splitLength/freqDouble;
+		}
+	}
+
+	public static Bipartition getBipartitionFromNode (Tree tree, int node) {
+		Bipartition bp = new Bipartition(tree.getTaxa().getNumTaxa());
+		bp.setBits(tree.getTerminalTaxaAsBits(node));
+		return bp;
+	}
+	
+	public Bits getBits(){
+		return bits;
+	}
+	/*....................................................................*/
+	public void copyIntoBits(Bits bits){
+		this.bits.setBits(bits);
+	}
+	/*....................................................................*/
+	public void setBits(Bits bits){
+		this.bits=bits;
+	}
+	/*....................................................................*/
+	void add(Bipartition b){
+		bits.orBits(b.bits);
+	}
+
+	boolean equals(Bipartition b, boolean rooted){
+		if (rooted)
+			return bits.equals(b.bits);
+		return bits.equals(b.bits) || bits.equalsComplement(b.bits);
+	}
+	boolean equals(Bits b,  boolean rooted){
+		if (rooted)
+			return bits.equals(b);
+		return bits.equals(b) || bits.equalsComplement(b);
+	}
+	public double getFreqDouble() {
+		return freqDouble;
+	}
+	public void setFreqDouble(double freqDouble) {
+		this.freqDouble = freqDouble;
+	}
+	public boolean isPresent() {
+		return present;
+	}
+	public void setPresent(boolean present) {
+		this.present = present;
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/consensus/lib/BipartitionVector.java b/Source/mesquite/consensus/lib/BipartitionVector.java
new file mode 100644
index 0000000..5609aae
--- /dev/null
+++ b/Source/mesquite/consensus/lib/BipartitionVector.java
@@ -0,0 +1,587 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.consensus.lib;
+
+import java.util.Vector;
+
+import mesquite.consensus.lib.Bipartition;
+import mesquite.lib.*;
+
+public class BipartitionVector extends Vector {
+	boolean rooted = true;
+	boolean useWeights = false;
+
+	int numTaxa =  0;
+	int numTreesTotal = 0;
+	double weightedTreesTotal = 0.0;
+	Bits[] nodes;
+	double[] branchLengths;
+	int princess = 0;
+	Taxa taxa;
+	Bits allTaxa;
+	Bits partitionPresent;
+	Bits bits1;
+	Bits bits2;
+	public static final int MAJRULEMODE = 0;
+	public static final int STRICTMODE = 1;
+	public static final int SEMISTRICTMODE = 2;
+	public static final int MATCHMODE = 3;
+	int mode = STRICTMODE;
+	double weight = 1.0;
+
+	int numBranchLengthArraySizeWarnings=0;
+	int numNodeArraySizeWarnings=0;
+
+
+	public void setTaxa(Taxa taxa){
+		numTreesTotal = 0;
+		this.taxa = taxa;
+		numTaxa = taxa.getNumTaxa();
+		nodes = new Bits[MesquiteTree.standardNumNodeSpaces(taxa)*2];  //some slack in case nonstandard tree
+		partitionPresent = new Bits(MesquiteTree.standardNumNodeSpaces(taxa)*2);
+		for (int i= 0; i<nodes.length; i++)
+			nodes[i] = new Bits(numTaxa);
+		allTaxa = new Bits(numTaxa);
+		bits1 = new Bits(numTaxa);
+		bits2 = new Bits(numTaxa);
+		branchLengths = new double[MesquiteTree.standardNumNodeSpaces(taxa)];
+		for (int i=0; i<branchLengths.length; i++){
+			branchLengths[i] = MesquiteDouble.unassigned;
+		}
+
+	}
+	public void zeroFrequencies(){
+		numTreesTotal = 0;
+		weight=1.0;
+		weightedTreesTotal=0.0;
+		if (allTaxa!=null)
+			allTaxa.clearAllBits();
+		if (partitionPresent!=null)
+			partitionPresent.clearAllBits();
+		for (int i=0; i<size(); i++){
+			Bipartition b = getBipart(i);
+			if (b!=null)
+				b.reset();
+		}
+		for (int i=0; i<branchLengths.length; i++){
+			branchLengths[i] = MesquiteDouble.unassigned;
+		}
+
+	}
+	
+	public void initialize() {
+		numBranchLengthArraySizeWarnings=0;
+		numNodeArraySizeWarnings=0;
+	}
+	
+	public String toString(){
+		String s = "BipartitionVector\n";
+		for (int i=0; i<size(); i++){
+			Bipartition b = getBipart(i);
+			s += "   " + b + "\n";
+		}
+		return s;
+	}
+	public Bipartition getBipart(int i){
+		if (i<size() && i>=0)
+			return (Bipartition)elementAt(i);
+		return null;
+	}
+
+	public double getDecimalFrequency (Bipartition bp) {
+		if (useWeights)
+			return bp.freqDouble*1.0/weightedTreesTotal;
+		else
+			return bp.getFreq()*1.0/numTreesTotal;
+	}
+
+	public void dump(){
+		sort(true);
+		MesquiteMessage.println("\nBipartition frequencies");
+		MesquiteInteger.logHorizIntegerList(numTaxa);
+		for (int i=0; i<size(); i++){
+			Bipartition stored = getBipart(i);
+			double freq = getDecimalFrequency(stored);
+			if (freq>0.05) {
+				String s = MesquiteDouble.toPrecisionSpecifiedString(freq,3);
+				MesquiteMessage.println(stored.bits.toAsteriskString() + "   " +s);
+			}
+		}
+
+	}
+	public void tradeValues(int i, int j){
+		long freq1 = ((Bipartition)elementAt(i)).getFreq();
+		double freqDouble1 = ((Bipartition)elementAt(i)).getFreqDouble();
+		Bits bits1 = ((Bipartition)elementAt(i)).getBits();
+		long freq2 = ((Bipartition)elementAt(j)).getFreq();
+		double freqDouble2 = ((Bipartition)elementAt(j)).getFreqDouble();
+		Bits bits2 = ((Bipartition)elementAt(j)).getBits();
+		((Bipartition)elementAt(i)).setFreq(freq2);
+		((Bipartition)elementAt(j)).setFreq(freq1);
+		((Bipartition)elementAt(i)).setFreqDouble(freqDouble2);
+		((Bipartition)elementAt(j)).setFreqDouble(freqDouble1);
+		((Bipartition)elementAt(i)).setBits(bits2);
+		((Bipartition)elementAt(j)).setBits(bits1);
+	}
+
+	public void sort(boolean descending){
+		for (int i=0; i<size(); i++) {
+			for (int j= i+1; j<size(); j++) {
+				if (useWeights) {
+					double freq1 = ((Bipartition)elementAt(i)).getFreqDouble();
+					double freq2 = ((Bipartition)elementAt(j)).getFreqDouble();
+					if ((freq1<freq2 && descending) || (freq1>freq2 && !descending))
+						tradeValues(i,j);
+				} else {
+					long freq1 = ((Bipartition)elementAt(i)).getFreq();
+					long freq2 = ((Bipartition)elementAt(j)).getFreq();
+					if ((freq1<freq2 && descending) || (freq1>freq2 && !descending))
+						tradeValues(i,j);
+				}
+			}
+		}
+	}
+
+	/** removes all bipartitions with frequencies lower that that specified */
+	public void removeBipartitions(double lowerFrequencyLimit) {
+		for (int i=size()-1; i>=0; i--) {
+			double freq = getDecimalFrequency((Bipartition)elementAt(i));
+			if (freq< lowerFrequencyLimit)
+				remove(i);
+		}
+
+	}
+
+	/** Returns a new BipartitionVector that contains only those Bipartitions that are in a frequency greater than or equal to the lowerFrequencyLimit */
+	public BipartitionVector getFilteredBipartitions (double lowerFrequencyLimit) {
+		BipartitionVector bpv = new BipartitionVector();
+		bpv.setTaxa(taxa);
+		for (int i=0; i<size(); i++){
+			Bipartition bp = ((Bipartition)elementAt(i));
+			double freq = getDecimalFrequency(bp);
+			if (freq >= lowerFrequencyLimit) {
+				Bipartition newbp = new Bipartition(numTaxa);
+				newbp.copyIntoBits(bp.getBits());
+				newbp.setFreq(bp.getFreq());
+				newbp.setFreqDouble(bp.getFreqDouble());
+				bpv.addElement(newbp);
+			}
+		}
+		return bpv;
+	}
+	
+	public double getDecimalFrequencyOfNode(Tree tree, int node, boolean rooted){
+		Bits bits = tree.getTerminalTaxaAsBits(node);
+		for (int i=0; i<size(); i++){
+			Bipartition bp = ((Bipartition)elementAt(i));
+			if (bp.equals(bits,rooted))
+				return getDecimalFrequency(bp);
+		}
+		return 0.0;
+	}
+
+	public boolean compatible(Bits a, Bits b){
+		bits1.setBits(a);
+		bits2.setBits(b);
+		bits1.andBits(bits2);   // intersection of bits1 and bits2
+		if (bits1.anyBitsOn()){   // intersection has something in it
+			bits1.setBits(a);
+			bits1.invertAllBits();
+			bits1.andBits(bits2);  // intersection of bits1 complement and bits2
+			if (bits1.anyBitsOn()){   
+				bits1.setBits(a);
+				bits2.invertAllBits();
+				bits1.andBits(bits2);  // intersection of bits2 complement and bits1
+				if (bits1.anyBitsOn()){   // intersection has something in it
+					if (rooted)   // if rooted we don't need to check for the last pattern
+						return false;
+					bits1.setBits(a);
+					bits1.invertAllBits();
+					bits1.andBits(bits2);  // intersection of bits2 complement and bits1 complement
+					if (bits1.anyBitsOn())  
+						return false;   // all 4 pattern exist, must be incompatible
+				}
+			}
+		}
+		return true;
+
+	}
+
+	/** creates and adds to the vector a Bipartition from the Bits */
+	private Bipartition simpleAddBipartition(Bits bits){
+		Bipartition bipart = new Bipartition(numTaxa);
+		bipart.copyIntoBits(bits);
+		addElement(bipart);
+		return bipart;
+	}
+	/** Goes through the tree and adds all a Bipartition to the vector for each split found */
+	private void simpleGetPartitions(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			nodes[node].setBit(tree.taxonNumberOfNode(node));
+			double length = tree.getBranchLength(node);
+			if (MesquiteDouble.isCombinable(length)) {
+				if (!MesquiteDouble.isCombinable(branchLengths[tree.taxonNumberOfNode(node)]))
+					branchLengths[tree.taxonNumberOfNode(node)] =0.0;
+				branchLengths[tree.taxonNumberOfNode(node)] += length;
+			}
+			return;
+		}
+		nodes[node].clearAllBits();
+		branchLengthArrayWarningForThisTree = false;
+		nodeArraySizeWarningForThisTree=false;
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			if (!getPartitions(tree, daughter))
+				return;
+			nodes[node].orBits(nodes[daughter]);
+		}
+		if (node != princess || rooted) {
+			Bipartition bp = simpleAddBipartition(nodes[node]);
+			double length = tree.getBranchLength(node);
+			if (MesquiteDouble.isCombinable(length))
+				bp.addToSplitLength(length);
+		}
+	}
+
+	private Bipartition addBipart(Bits bits){
+		if (bits == null)
+			return null;
+		switch (mode) {
+		case STRICTMODE: 
+			if (numTreesTotal==0) {  // first tree; just add it
+				Bipartition bipart = new Bipartition(numTaxa);
+				bipart.copyIntoBits(bits);
+				addElement(bipart);
+				return bipart;
+			} else {
+				boolean foundConflict = false;
+				int identical = -1;
+				for (int i=size()-1; i>=0; i--){  // going through stored ones and see whether it matches the new bits
+					Bipartition stored = getBipart(i);
+					if (stored != null){
+						if (compatible(stored.getBits(),bits)){ //the incoming is compatible with the ith stored bipartition
+						if (stored.equals(bits, rooted)){  // it's not only compatible, but they are the same
+							identical=i;
+							stored.setPresent(true);
+						}
+					} else { // 
+						foundConflict=true;
+						remove(i);
+					}
+					}
+				}
+				if (foundConflict && identical>0)
+					remove(identical);
+			}
+			return null;
+
+		case MAJRULEMODE:
+		case SEMISTRICTMODE:
+			for (int i=0; i<size(); i++){
+				Bipartition stored = getBipart(i);
+
+				if (stored != null && stored.equals(bits, rooted)){  //stored.potentialMatch(numBits, rooted)&&
+					if (useWeights && mode==MAJRULEMODE)
+						stored.weightedIncrement(weight);
+					else
+						stored.increment();
+					return stored;
+				}
+			}
+			Bipartition bipart = new Bipartition(numTaxa);
+			bipart.copyIntoBits(bits);
+			if (useWeights&& mode==MAJRULEMODE)
+				bipart.weightedIncrement(weight);
+			else
+				bipart.increment();
+			addElement(bipart);
+			return bipart;
+			
+		case MATCHMODE:
+			for (int i=0; i<size(); i++){
+				Bipartition stored = getBipart(i);
+
+				if (stored != null && stored.equals(bits, rooted)){  //stored.potentialMatch(numBits, rooted)&&
+					if (useWeights)
+						stored.weightedIncrement(weight);
+					else
+						stored.increment();
+					return stored;
+				}
+			}
+		default:
+			return null;
+		}
+	}
+	
+	boolean branchLengthArrayWarningForThisTree = false;
+	boolean nodeArraySizeWarningForThisTree = false;
+	int biggestNode =0;
+	
+	/*.................................................................................................................*/
+	private void printDiagnostics (Tree tree, int node) {
+		MesquiteMessage.println("  Diagnostics:");
+		MesquiteMessage.println("    tree name = "+ tree.getName());
+		MesquiteMessage.println("    number of taxa in taxa block = "+ tree.getTaxa().getNumTaxa());
+		MesquiteMessage.println("    number of terminal taxa in tree = "+tree.numberOfTerminalsInClade(tree.getRoot()));
+		MesquiteMessage.println("    number of nodes in tree = "+tree.numberOfNodesInClade(tree.getRoot()));
+		MesquiteMessage.println("    node = "+node);
+		if (tree.nodeIsTerminal(node)){
+			MesquiteMessage.println("    Node is terminal");
+			MesquiteMessage.println("      taxon number = "+tree.taxonNumberOfNode(node));
+		}
+		else
+			MesquiteMessage.println("    Node is internal");
+
+	}
+
+	/*.................................................................................................................*/
+	private boolean getPartitions(Tree tree, int node){
+		if (node >= nodes.length) {
+
+			if (((!nodeArraySizeWarningForThisTree && numNodeArraySizeWarnings<10)||node>biggestNode)){
+				MesquiteMessage.println("\nProblem with getPartitions: node number is larger than nodes array allocation");
+				printDiagnostics(tree,node);
+				MesquiteMessage.println("    nodes.length = "+ nodes.length);
+				numNodeArraySizeWarnings++;
+				nodeArraySizeWarningForThisTree=true;
+				if (biggestNode<node)
+					biggestNode=node;
+			}
+			return false;
+		}
+		if (tree.nodeIsTerminal(node)){     
+			int it = tree.taxonNumberOfNode(node);
+			if ((it< 0 || it >= branchLengths.length) && numBranchLengthArraySizeWarnings<10 && !branchLengthArrayWarningForThisTree){
+				MesquiteMessage.println("\nProblem with getPartitions: branchlengths array too small.");
+				printDiagnostics(tree,node);
+				MesquiteMessage.println("    branchLengths.length = "+branchLengths.length);
+				numBranchLengthArraySizeWarnings++;
+				branchLengthArrayWarningForThisTree=true;
+			}
+			
+			nodes[node].setBit(it);
+			double length = tree.getBranchLength(node);
+			if (MesquiteDouble.isCombinable(length)) {
+				if (!MesquiteDouble.isCombinable(branchLengths[it]))
+					branchLengths[it] =0.0;
+				branchLengths[it] += length;
+			}
+			return true;
+		}
+		nodes[node].clearAllBits();
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			if (!getPartitions(tree, daughter))
+				return false;
+			nodes[node].orBits(nodes[daughter]);
+		}
+		if (node != princess || rooted) {
+			Bipartition bp = addBipart(nodes[node]);
+			double length = tree.getBranchLength(node);
+			if (bp!=null && MesquiteDouble.isCombinable(length))
+				bp.addToSplitLength(length);
+
+		}
+		return true;
+	}
+
+
+	public void checkArraySizes(Tree tree){
+		//upgrading storage if not big enough
+		if (nodes.length < tree.getNumNodeSpaces()){
+			partitionPresent.resetSize(tree.getNumNodeSpaces());
+			Bits[] newNodes = new Bits[tree.getNumNodeSpaces()];
+			for (int i=0; i<newNodes.length; i++)
+				if (i<nodes.length)
+					newNodes[i] =  nodes[i];
+				else
+					newNodes[i] = new Bits(numTaxa);
+			nodes = newNodes;
+		}
+		if (branchLengths.length < tree.getNumNodeSpaces()){
+			double[] newBranchLengths = new double[tree.getNumNodeSpaces()];
+			for (int i=0; i<newBranchLengths.length; i++)
+				if (i<branchLengths.length)
+					newBranchLengths[i] =  branchLengths[i];
+				else
+					newBranchLengths[i] = MesquiteDouble.unassigned;
+			branchLengths = newBranchLengths;
+		}
+	}
+
+	
+	/*.................................................................................................................*/
+	
+	/** adds tree to existing */
+	public void addTree(Tree tree){
+		branchLengthArrayWarningForThisTree=false;
+		nodeArraySizeWarningForThisTree=false;
+		princess = tree.firstDaughterOfNode(tree.getRoot());
+		
+		checkArraySizes(tree);
+		if (tree.nodeIsPolytomous(tree.getRoot()))
+			princess=-1;  // don't worry about princess if root is a polytomy
+		for (int i= 0; i<nodes.length; i++)
+			nodes[i].clearAllBits();
+		if (numTreesTotal>0 && mode==STRICTMODE) 
+			for (int i=size()-1; i>=0; i--){ 
+				Bipartition stored = getBipart(i);
+				if (stored!=null)
+					stored.setPresent(false);
+			}
+
+		if (!getPartitions(tree, tree.getRoot()))
+			return;
+
+		if (numTreesTotal>0 && mode==STRICTMODE) 
+			for (int i=size()-1; i>=0; i--){ 
+				Bipartition stored = getBipart(i);
+				if (stored!=null && !stored.isPresent())
+					remove(i);
+			}
+
+		numTreesTotal++;
+		if (useWeights)
+			weightedTreesTotal += getWeight();
+		allTaxa.orBits(nodes[tree.getRoot()]);
+	}
+
+
+	/** returns a new bipartitionVector for just for the tree passed. */
+	public static BipartitionVector getBipartitionVector(Tree tree){
+		if (tree==null)
+			return null;
+		BipartitionVector bpv = new BipartitionVector();
+		bpv.setTaxa(tree.getTaxa());
+		bpv.setRooted(tree.getRooted());
+		int princess = tree.firstDaughterOfNode(tree.getRoot());
+		if (tree.nodeIsPolytomous(tree.getRoot()))
+			princess=-1;  // don't worry about princess if root is a polytomy
+		bpv.setPrincess(princess);
+		bpv.checkArraySizes(tree);
+		bpv.simpleGetPartitions(tree, tree.getRoot());
+		return bpv;
+	}
+
+
+	NameReference freqRef = NameReference.getNameReference("consensusFrequency");
+	private void resolveByBipartition(MesquiteTree tree, Bipartition stored){
+		int newNode = tree.makeClade(stored.bits);
+		if (mode==MAJRULEMODE) {
+			double prop = getDecimalFrequency(stored);
+			tree.setAssociatedDouble(freqRef, newNode, prop, true);
+			//	tree.setNodeLabel(MesquiteDouble.toStringDigitsSpecified(prop, 3), newNode);
+			if (tree.nodeIsInternal(newNode)){
+				double length = stored.getSplitLength();
+				if (MesquiteDouble.isCombinable(length))
+					tree.setBranchLength(newNode, length, false);
+			}
+		}
+	}
+	public Tree makeTree(double minFreq){
+		MesquiteTree tree = new MesquiteTree(taxa);
+		tree.setToDefaultBush(allTaxa, false);  //bug fixed 2. 75; had used the first taxa, not the set in the bipartition vector
+		boolean setLengths = false;
+		for (int it=0; it<numTaxa; it++)
+			if (MesquiteDouble.isCombinable(branchLengths[it])) {
+				if (useWeights)
+					branchLengths[it]=branchLengths[it]/weightedTreesTotal;
+				else
+					branchLengths[it]=branchLengths[it]/numTreesTotal;
+				setLengths = true;
+			}
+
+		if (mode==SEMISTRICTMODE){ // for this, need to go through and wipe out incompatible ones.
+			for (int i=0; i<size(); i++){
+				Bipartition stored = getBipart(i);
+				stored.setPresent(true); 
+				if (stored.getFreq()!=numTreesTotal) {
+					for (int j=0; j<size(); j++){
+						Bipartition comparison = getBipart(j);
+						if (!compatible(comparison.getBits(), stored.getBits()))
+							stored.setPresent(false);
+					}
+
+				}
+			}
+			for (int j=size()-1; j>=0; j--){
+				if (!getBipart(j).isPresent())
+					remove (j);
+			}
+
+		}
+
+		for (int i=0; i<size(); i++){
+			Bipartition stored = getBipart(i);
+			stored.avgSplitLength(useWeights);
+			//	if (!rooted)
+			//		stored.bits.standardizeComplement(0);
+			if (mode==STRICTMODE || mode==SEMISTRICTMODE) {
+				resolveByBipartition(tree, stored);
+			} else {
+				double prop = getDecimalFrequency(stored);
+				if (minFreq==0.5) {
+					if (prop>minFreq)
+						resolveByBipartition(tree, stored);
+				}
+				else	if (prop>=minFreq){
+					resolveByBipartition(tree, stored);
+				}
+			}
+		}
+		if (setLengths) {
+			for (int it=0; it<numTaxa; it++)
+				if (MesquiteDouble.isCombinable(branchLengths[it])) {
+					tree.setBranchLength(tree.nodeOfTaxonNumber(it), branchLengths[it], false);
+				}
+			tree.setBranchLength(tree.getRoot(), 0.0, false);
+		}
+		tree.standardize(tree.getRoot(), false);
+		return tree;
+	}
+	public Tree makeTree(){
+		return makeTree(0.5);
+	}
+
+	public int getMode() {
+		return mode;
+	}
+	public void setMode(int mode) {
+		this.mode = mode;
+	}
+	public double getWeight() {
+		return weight;
+	}
+	public void setWeight(double weight) {
+		this.weight = weight;
+	}
+	public boolean isUseWeights() {
+		return useWeights;
+	}
+	public void setUseWeights(boolean useWeights) {
+		this.useWeights = useWeights;
+	}
+	public boolean isRooted() {
+		return rooted;
+	}
+	public void setRooted(boolean rooted) {
+		this.rooted = rooted;
+	}
+	public int getPrincess() {
+		return princess;
+	}
+	public void setPrincess(int princess) {
+		this.princess = princess;
+	}
+}
diff --git a/Source/mesquite/consensus/lib/StrictConsenser.java b/Source/mesquite/consensus/lib/StrictConsenser.java
new file mode 100644
index 0000000..7729265
--- /dev/null
+++ b/Source/mesquite/consensus/lib/StrictConsenser.java
@@ -0,0 +1,42 @@
+package mesquite.consensus.lib;
+
+
+import mesquite.lib.Taxa;
+import mesquite.lib.Tree;
+
+/* A utility class designed to be used by modules to easily make a strict consensus of trees */
+
+public class StrictConsenser {
+	
+	protected BipartitionVector bipartitions = new BipartitionVector();
+	protected int treeNumber = 0;
+
+	/*.................................................................................................................*/
+  	public void reset(Taxa taxa){
+  		if (bipartitions==null)
+  			bipartitions = new BipartitionVector();
+  		else
+  			bipartitions.removeAllElements();		// clean bipartition table
+		bipartitions.setTaxa(taxa);
+		bipartitions.zeroFrequencies();
+		initialize();
+	}
+  	public void addTree(Tree t){
+		if (t==null)
+			return;
+		bipartitions.addTree(t);
+	}
+	/*.................................................................................................................*/
+ 	public void initialize() {
+ 		if (bipartitions!=null)
+ 			bipartitions.setMode(BipartitionVector.STRICTMODE);
+ 	}
+	/*.................................................................................................................*/
+ 	public Tree getConsensus(){
+		Tree t = bipartitions.makeTree();
+		return t;
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/cont/AddCharacter/AddCharacter.java b/Source/mesquite/cont/AddCharacter/AddCharacter.java
new file mode 100644
index 0000000..fc950b0
--- /dev/null
+++ b/Source/mesquite/cont/AddCharacter/AddCharacter.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.AddCharacter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class AddCharacter extends ContDataAlterer {
+	double scalingFactor = 1.0;
+	CharSourceCoordObed characterSourceTask;
+	int addingIC = 0;
+	ContinuousDistribution addingCharacter;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		String exp = "Source of character to add";
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, ContinuousState.class, exp);
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof ContinuousData))
+			return false;
+ 			Taxa taxa = data.getTaxa();
+   			addingIC=characterSourceTask.queryUserChoose(taxa, "from which to add states");
+   			addingCharacter = (ContinuousDistribution)characterSourceTask.getCharacter(taxa, addingIC); 
+			boolean did=false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		if (addingCharacter == null)
+   			return;
+		ContinuousData data = (ContinuousData)ddata;
+		
+		double factor = addingCharacter.getState(it, 0);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state) && MesquiteDouble.isCombinable(factor))
+				data.setState(ic,it, item, state+factor);
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  //put release version
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add Character";
+   	 }
+    		/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Add Character...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by adding a continuous character from a source of characters.  All items of the matrix are similarly modified." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/AddItem/AddItem.java b/Source/mesquite/cont/AddItem/AddItem.java
new file mode 100644
index 0000000..c1ce69c
--- /dev/null
+++ b/Source/mesquite/cont/AddItem/AddItem.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.AddItem;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class AddItem extends ContDataUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+   	/** Called to alter data in all cells*/
+   	public boolean operateOnData(CharacterData data){
+			if (!(data instanceof ContinuousData))
+				return false;
+			ContinuousData cData = (ContinuousData)data;
+			String items = "";
+			for (int i=0; i<cData.getNumItems(); i++){
+				if (StringUtil.blank(cData.getItemName(i)))
+					items += " (unnamed)";
+				else
+					items += " " + cData.getItemName(i);
+			}
+			String d = MesquiteString.queryString(containerOfModule(), "New item", "Currently the items are: " + items + "; enter name of new item", "");
+			if (StringUtil.blank(d))
+				return false;
+			else {
+				cData.addItem(d);
+				return true;
+			}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add item...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adds an item in each cell of a continuous matrix." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/AddNoise/AddNoise.java b/Source/mesquite/cont/AddNoise/AddNoise.java
new file mode 100644
index 0000000..b671b38
--- /dev/null
+++ b/Source/mesquite/cont/AddNoise/AddNoise.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.AddNoise;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+//import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class AddNoise extends ContDataAlterer {
+	CharacterState fillState;
+	Random rng;
+	double standardDeviation;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random();
+		rng.setSeed(System.currentTimeMillis());
+		return true;
+	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			standardDeviation = MesquiteDouble.queryDouble(containerOfModule(), "Add Noise", "Variance of noise", 1.0);
+			if (!MesquiteDouble.isCombinable(standardDeviation) || standardDeviation<=0)
+				return false;
+			standardDeviation = Math.sqrt(standardDeviation);
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData data, int ic, int it){
+   		((ContinuousData)data).setState(ic,it, 0, ((ContinuousData)data).getState(ic, it,0)+ standardDeviation*rng.nextGaussian());
+   	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add Noise (Gaussian)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adds normally distributed noise to existing states.  Only the first item of a continuous matrix is modified." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/AddToStates/AddToStates.java b/Source/mesquite/cont/AddToStates/AddToStates.java
new file mode 100644
index 0000000..fd1446f
--- /dev/null
+++ b/Source/mesquite/cont/AddToStates/AddToStates.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.AddToStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class AddToStates extends ContDataAlterer {
+	double translateAmount =0.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			double d = MesquiteDouble.queryDouble(containerOfModule(), "Add value", "Add to values in matrix:", translateAmount);
+			if (MesquiteDouble.isCombinable(d))
+				translateAmount = d;
+			else
+				return false;
+			return alterContentOfCells(data,table, undoReference); //todo: in future pass object here which will be passed to alterCell; avoids sloppy practice of relying on "global" variable translateAmount
+   	}
+
+   	
+   	public void alterCell(CharacterData ddata, int ic, int it){
+		ContinuousData data = (ContinuousData)ddata;
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state))
+				data.setState(ic,it, item, state+translateAmount);
+		}
+	}
+	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add value";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by adding a value.  All items of the matrix are similarly modified." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/ArcSineTransform/ArcSineTransform.java b/Source/mesquite/cont/ArcSineTransform/ArcSineTransform.java
new file mode 100644
index 0000000..8ec894a
--- /dev/null
+++ b/Source/mesquite/cont/ArcSineTransform/ArcSineTransform.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.ArcSineTransform;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ArcSineTransform extends ContDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+   	
+   	boolean firstTime = true;
+   	
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		ContinuousData data = ((ContinuousData)ddata);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state)) {
+				if (state<0 || state >1) {
+					if (firstTime)
+						discreetAlert( "Some values could not be arcsine transformed because they were outside of the range 0 to 1");
+					firstTime = false;
+				}
+				else
+					data.setState(ic,it, item, Math.asin(state));
+			}
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Arcsine transform";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by arcsine transforming values." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/cont/ContCharFrTaxonValue/ContCharFrTaxonValue.java b/Source/mesquite/cont/ContCharFrTaxonValue/ContCharFrTaxonValue.java
new file mode 100644
index 0000000..5b8474c
--- /dev/null
+++ b/Source/mesquite/cont/ContCharFrTaxonValue/ContCharFrTaxonValue.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.ContCharFrTaxonValue;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ContCharFrTaxonValue extends CharacterSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(NumberForTaxon.class, getName() + " needs a method to calculate values for the taxa.",
+		"You can select the value calculator initially, or in the Values submenu.");
+	}
+	public NumberForTaxon numberTask;
+	MesquiteString numberTaskName;
+	MesquiteSubmenuSpec msNT;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask=(NumberForTaxon)hireEmployee(NumberForTaxon.class, "Value to calculate for taxa");
+		if (numberTask == null)
+			return false;
+		ntC = makeCommand("setCalculator",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString(numberTask.getName());
+		msNT = addSubmenu(null, "Values", ntC, NumberForTaxon.class);
+		msNT.setSelected(numberTaskName);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCalculator ", numberTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the taxa", "[name of module]", commandName, "setCalculator")) {
+			NumberForTaxon temp =  (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Value to calculate for taxa", numberTask);
+			//((TreesChartWindow)window).setNumberTask(numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+				return numberTask;
+			}
+		}
+
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	/*.................................................................................................................*/
+	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+		ContinuousAdjustable states = new ContinuousAdjustable(taxa, taxa.getNumTaxa());
+		states.setName(getCharacterName(taxa, 0));
+		MesquiteNumber result = new MesquiteNumber();
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+			result.setToUnassigned();
+			numberTask.calculateNumber(taxa.getTaxon(it), result, null);
+			states.setState(it, result.getDoubleValue());
+		}
+		return states;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfCharacters(Taxa taxa) {
+		return 1;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		super.employeeParametersChanged( employee,  source, notification);
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+	/** returns the name of character ic*/
+	public String getCharacterName(Taxa taxa, int ic){
+		return  "Character from " + numberTask.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return numberTask.getNameAndParameters() + " (reinterpreted as a continous character)";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Calculated value for taxon";
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies values for taxa reinterpreted as if characters." ;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ContinuousStateTest();
+	}
+}
+
diff --git a/Source/mesquite/cont/ContinuousStatesT/ContinuousStatesT.java b/Source/mesquite/cont/ContinuousStatesT/ContinuousStatesT.java
new file mode 100644
index 0000000..04caca2
--- /dev/null
+++ b/Source/mesquite/cont/ContinuousStatesT/ContinuousStatesT.java
@@ -0,0 +1,292 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.ContinuousStatesT;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.Coalescer;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ContinuousStatesT extends NumberForTaxonIncr {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " uses a source of characters for the observed states in taxa.",
+		"You can select the source of character initially.");
+	}
+	MesquiteNumber num;
+	CharSourceCoordObed characterSourceTask;
+	Taxa currentTaxa;
+	int currentChar=0;
+	boolean characterSet = false;
+	int lastCharRetrieved = -1;
+	ContinuousDistribution observedStates =null;
+	MesquiteCommand cstC;
+	
+	//choice of what item to show
+	int currentItem=0;
+	MesquiteMenuItemSpec itemItem;
+	MesquiteCommand itemChoiceCommand;
+	String itemName=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, ContinuousState.class, "Source of characters (for Continuous States of Taxon)");
+ 		if (characterSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of characters found");
+ 		}
+		/**/
+		itemChoiceCommand = MesquiteModule.makeCommand("setItem",  this);
+		addMenuItem("Choose Character...", new MesquiteCommand("chooseCharacter", this));
+		itemItem = addMenuItem("Item of Continuous State...", itemChoiceCommand);
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == characterSourceTask)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	public long toInternal(long i){
+ 		return(CharacterStates.toInternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+ 	public long toExternal(long i){
+ 		return(CharacterStates.toExternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+   	 public void setCurrent(long i){
+ 		if (characterSourceTask==null || currentTaxa==null){
+ 			currentChar = (int)i;
+			characterSet=true;
+ 		}
+ 		else if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)) {
+ 			currentChar = (int)i;
+			characterSet=true;
+			//parametersChanged();
+		}
+   	 }
+ 	public String getItemTypeName(){
+ 		return "Character";
+ 	}
+	/*.................................................................................................................*/
+   	 public long getCurrent(){
+   	 	return currentChar;
+   	 }
+	/*.................................................................................................................*/
+ 	public long getMin(){
+ 		return 0;
+ 	}
+	/*.................................................................................................................*/
+ 	public long getMax(){
+ 		if (characterSourceTask==null || currentTaxa==null)
+ 			return 0;
+ 		return characterSourceTask.getNumberOfCharacters(currentTaxa)-1;
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine( "getCharacterSource " , characterSourceTask);
+  	 	temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+  	 	temp.addLine("setItem " + (currentItem));
+    	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+ 			return characterSourceTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+ 			return characterSourceTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to the next character", null, commandName, "nextCharacter")) {
+    	 		if (currentChar>=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)
+    	 			currentChar=0;
+    	 		else
+    	 			currentChar++;
+				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to the previous character", null, commandName, "previousCharacter")) {
+    	 		if (currentChar<=0)
+    	 			currentChar=characterSourceTask.getNumberOfCharacters(currentTaxa)-1;
+    	 		else
+    	 			currentChar--;
+				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the item to use (in a multi-item continuous data matrix)", "[item number]", commandName, "setItem")) {
+    	 		int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (!MesquiteInteger.isCombinable(ic) && observedStates!=null){
+				ic = observedStates.userQueryItem("Select item to use for Continuous State of Taxon", this);
+    	 		}
+   			if (!MesquiteInteger.isCombinable(ic))
+   				return null;
+   			if (currentTaxa==null) {
+    	 			currentItem = ic;
+   			}
+ 			else if (observedStates !=null && observedStates instanceof ContinuousDistribution) {
+	   	 		if ((ic>=0) && (ic<=observedStates.getNumItems()-1)) {
+	    	 			currentItem = ic;
+					parametersChanged();
+	 			}
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries user to choose which character to use" , null, commandName, "chooseCharacter")) {
+    	 		int ic=characterSourceTask.queryUserChoose(currentTaxa, " for " + whatIsMyPurpose());
+    	 		if (MesquiteInteger.isCombinable(ic)) {
+	   			currentChar = ic;
+	 			characterSet=true;
+	 			parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the character to use", "[number of character]", commandName, "setCharacter")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+   			if (currentTaxa==null) {
+    	 			currentChar = ic;
+	 			characterSet=true;
+   			}
+    	 		if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)) {
+    	 			currentChar = ic;
+	 			characterSet=true;
+				parametersChanged();
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		currentTaxa = taxa;
+   		characterSourceTask.initialize(currentTaxa);
+   		int nums = characterSourceTask.getNumberOfCharacters(currentTaxa);
+		if (!MesquiteThread.isScripting() && nums>1 && MesquiteInteger.isCombinable(nums) && (!characterSet || currentChar>=nums)) {
+    	 		int ic=characterSourceTask.queryUserChoose(taxa, " for " + whatIsMyPurpose());
+    	 		if (MesquiteInteger.isCombinable(ic) && (ic>=0) && (ic<=nums-1)) {
+	   			currentChar = ic;
+	 			characterSet=true;
+ 			}
+    	 	}
+   	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || currentChar != lastCharRetrieved || observedStates == null ) {
+			int maxnum = characterSourceTask.getNumberOfCharacters(taxa);
+			if (currentChar>= maxnum)
+				currentChar = maxnum-1;
+			observedStates = (ContinuousDistribution)characterSourceTask.getCharacter(taxa, currentChar);
+			currentTaxa = taxa;
+			lastCharRetrieved = currentChar;
+		}
+		if (observedStates==null)
+			return;
+
+		int numItems = observedStates.getNumItems();
+		if (numItems>1){
+			if (!itemItem.isEnabled()){
+				itemItem.setEnabled(true);
+				MesquiteTrunk.mesquiteTrunk.resetMenuItemEnabling();
+			}
+			if (currentItem>= numItems)
+				currentItem=0;
+			itemName = observedStates.getItemName(currentItem);
+			
+		}
+		else {
+			currentItem = 0;
+			if (itemItem.isEnabled()){
+				itemItem.setEnabled(false);
+				MesquiteTrunk.mesquiteTrunk.resetMenuItemEnabling();
+			}
+		} 
+			
+		
+		double state = observedStates.getState(it, currentItem); 
+		num = new MesquiteNumber(state);
+		if (result!=null)
+			result.setValue(state);
+		if (resultString!=null)
+			resultString.setValue("State of character "+ currentChar + ": " + result.toString() + itemString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	private String itemString(){
+ 		if (itemName!=null)
+			return " (item " + itemName + ")";
+ 		else
+			return "";  
+	}
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+   		if (currentTaxa != null){
+    			String name = characterSourceTask.getCharacterName(currentTaxa, currentChar);
+    			if (name != null)
+    				return "Character states of: " + name;
+    		}
+ 		return "Character states from: " + characterSourceTask.getNameAndParameters() + itemString();  
+   	 }
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+			observedStates = null;
+			parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Continuous state of taxon";  
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameAndParameters() {
+    		if (currentTaxa != null){
+    			String name = characterSourceTask.getCharacterName(currentTaxa, currentChar);
+    			if (name != null)
+    				return "Character states of: " + name;
+    		}
+ 		return "Character states from: " + characterSourceTask.getNameAndParameters() + itemString();  
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "State of a continuous character." ;
+   	 }
+   	 
+}
+
+
+
+
diff --git a/Source/mesquite/cont/DiscretizeContinuousCharacters/DiscretizeContinuousCharacters.java b/Source/mesquite/cont/DiscretizeContinuousCharacters/DiscretizeContinuousCharacters.java
new file mode 100644
index 0000000..eaf4bd1
--- /dev/null
+++ b/Source/mesquite/cont/DiscretizeContinuousCharacters/DiscretizeContinuousCharacters.java
@@ -0,0 +1,196 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.DiscretizeContinuousCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.ParsimonyModel;
+import mesquite.parsimony.lib.ParsimonyModelSet;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class DiscretizeContinuousCharacters extends ContDataUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+	/*.................................................................................................................*/
+	static String  bstring  = "";
+	double[] getBins(){
+		MesquiteString s = new MesquiteString(bstring);
+		if (!QueryDialogs.queryString(containerOfModule(), "Bins for Discretization", 
+					"Indicate boundaries of bins for discretization as a series of one or more numbers, separated by spaces.  " +
+					"For instance, if you enter simply the number 5.2, then all values below 5.2 will be given state 0, all values at or above 5.2 will be given state 1. "  +
+					"If you enter more than one number, in increasing value, then the character will be discretized as a multistate ordered character/ " +
+					"For instance, if you enter \"0.7  2.3  4.1\", then values below 0.7 will be given state 0, values at or above 0.7 and below 2.3 will be given state 1, " +
+					"values at or above 2.3 and below 4.1 will be given state 2, and values at or above 4.1 will be given state 3," , s, 5))
+			return null;
+		bstring = s.getValue();
+		if (StringUtil.blank(bstring))
+			return null;
+		MesquiteInteger pos = new MesquiteInteger(0);
+		double d = 0;
+		Vector v = new Vector();
+		while (MesquiteDouble.isCombinable(d = MesquiteDouble.fromString (bstring, pos))) {
+			v.addElement(new MesquiteDouble(d));
+		}
+		if (v.size() == 0)
+			return null;
+		double[] bins = new double[v.size()];
+		for (int i = 0; i<v.size(); i++){
+			bins[i] = ((MesquiteDouble)v.elementAt(i)).getValue();
+		}
+
+		for (int i = 1; i<bins.length; i++){
+			if (bins[i]<= bins[i-1]){
+				alert("Boundaries between bins must be listed in strictly increasing order");
+				return null;
+			}
+		}
+
+		return bins;
+	}
+
+	int findBin(double value, double[] bins){
+		for (int i= 0; i< bins.length; i++){
+			if (bins[i] > value)
+				return i;
+		}
+		return bins.length;
+	}
+	/*.................................................................................................................*/
+/** Called to alter data in all cells*/
+	public boolean operateOnData(CharacterData data){
+		if (!(data instanceof ContinuousData))
+			return false;
+		ContinuousData cont = (ContinuousData)data;
+		if (!cont.anySelected()){
+			alert("Characters to be discretized must first be selected in the matrix");
+			return false;
+		}
+
+		if (getProject().getNumberCharMatricesVisible(data.getTaxa(), CategoricalState.class)==0){
+			alert("There must be an available categorical matrix to which discretized characters can be added.");
+			return false;
+		}
+		CategoricalData cat =  (CategoricalData)getProject().chooseDataExactClass(containerOfModule(), null, data.getTaxa(), CategoricalState.class, "Choose matrix to which to add discretized character(s)", false, null, null);
+		if (cat == null)
+			return false;
+		
+		
+		//now ask for bins
+		double[] bins = getBins();
+		if (bins == null)
+			return false;
+		if (bins.length > 50){
+			alert("Sorry, at most 50 bin boundaries are allowed");
+			return false;
+		}
+		CharacterModel ordered = getProject().getCharacterModel(new ModelCompatibilityInfo(ParsimonyModel.class, CategoricalState.class), "ordered");
+		ParsimonyModelSet modelSet = (ParsimonyModelSet)cat.getCurrentSpecsSet(ParsimonyModelSet.class);
+		if (ordered!=null){
+			if (modelSet == null) {
+				CharacterModel defaultModel =  cat.getDefaultModel("Parsimony");
+				modelSet= new ParsimonyModelSet("Parsimony Model Set", cat.getNumChars(), defaultModel, cat);
+				cat.storeSpecsSet(modelSet, ParsimonyModelSet.class);
+				cat.setCurrentSpecsSet(modelSet, ParsimonyModelSet.class);
+				modelSet.addToFile(cat.getFile(), getProject(), findElementManager(ParsimonyModelSet.class)); 
+			}
+		}
+		int numAdded = cont.numberSelected();
+		int origNumCat = cat.getNumChars();
+		cat.addCharacters(origNumCat, numAdded, true);
+		
+		
+		int count = 0;
+		for (int ic = 0; ic<cont.getNumChars(); ic++){
+			if (cont.getSelected(ic)){
+				int icCat = origNumCat + count;
+				String name = "Discretized from character " + (ic+1);
+				if (cont.characterHasName(ic))
+					name += " (" + cont.getCharacterName(ic) + ")";
+				String binsString = "Bin boundaries:";
+				for (int ib = 0; ib<bins.length; ib++)
+					binsString += " " + MesquiteDouble.toStringDigitsSpecified(bins[ib], 4);
+				cat.setAnnotation(icCat, binsString);
+				
+				cat.setCharacterName(icCat, name);
+				int max = 1;
+				count++;
+				for (int it = 0; it<cont.getNumTaxa(); it++){
+					double value = cont.getState(ic, it, 0);
+					if (ContinuousState.isUnassigned(value))
+							cat.setState(icCat, it, CategoricalState.unassigned);
+					else if (ContinuousState.isInapplicable(value))
+							cat.setState(icCat, it, CategoricalState.inapplicable);
+					else {
+						int bin = findBin(value, bins);
+						if (bin > max)
+							max = bin;
+						cat.setState(icCat, it, CategoricalState.makeSet(bin));
+					}
+				}
+				if (max>1){
+					if (modelSet != null)
+						modelSet.setModel(ordered, icCat);
+				}
+			}
+		}
+		
+		cat.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null, null));
+		cat.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED, null, null));
+		cat.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+		return true;
+	}
+	
+	
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Discretize Selected Characters...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Bins the selected continuous characters to discretize them into categorical characters (ordered if more than two states), and adds them to an existing categorical matrix.  If the continuous matrix is multi-item, only the first item is used." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/cont/InverseContState/InverseContState.java b/Source/mesquite/cont/InverseContState/InverseContState.java
new file mode 100644
index 0000000..8b41d2e
--- /dev/null
+++ b/Source/mesquite/cont/InverseContState/InverseContState.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.InverseContState;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class InverseContState extends ContDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+   	
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		ContinuousData data = ((ContinuousData)ddata);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state)) {
+				if (state==0) {
+					data.setState(ic, it, item, MesquiteDouble.infinite);
+				}
+				else
+					data.setState(ic,it, item, 1.0/state);
+			}
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Inverse of Value";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by inverting values (new value = 1/(original value))." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/cont/ItemValueInTaxon/ItemValueInTaxon.java b/Source/mesquite/cont/ItemValueInTaxon/ItemValueInTaxon.java
new file mode 100644
index 0000000..c81ea1f
--- /dev/null
+++ b/Source/mesquite/cont/ItemValueInTaxon/ItemValueInTaxon.java
@@ -0,0 +1,193 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.ItemValueInTaxon; 
+/*~~  */
+import java.util.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.ancstates.TraceCharacterHistory.TraceCharacterOperator;
+import mesquite.cont.lib.*;
+
+
+public class ItemValueInTaxon extends NumberForCharacter implements NumberForCharacterIncr, NumForCharTreeIndep {   //CHANGE CLASS NAME TO WHAT YOU WANT and use same name for package (see above)
+	int item = 0;
+	int iTaxon = 0;
+	ContinuousData data = null;
+	/*.................................................................................................................*/
+	/** a method called when the module is started up.  You can put initialization stuff here*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/*if (condition !=null && condition!= ContinuousData.class && condition!=ContinuousState.class) {
+  	 		if (!MesquiteThread.isScripting()) alert("Mean Value of Character (Linked) could not start because it can be used only for continuous-valued characters");
+			return false;
+ 		}*/
+		MesquiteMenuItemSpec mm = addMenuItem( "Next Taxon", makeCommand("nextTaxon",  this));
+		mm.setShortcut(KeyEvent.VK_RIGHT); //right
+		mm = addMenuItem( "Previous Taxon", makeCommand("previousTaxon",  this));
+		mm.setShortcut(KeyEvent.VK_LEFT); //right
+		addMenuItem( "Choose Taxon", makeCommand("chooseTaxon",  this));
+		return true;
+  	 }
+  	 
+ 	public void setCurrent(long i){ //SHOULD NOT notify (e.g., parametersChanged)
+ 		item = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return item;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Item";
+ 	}
+ 	public long getMin(){
+ 		return 0;
+ 	}
+ 	public long getMax(){
+ 		if (data !=null)
+ 			return data.getNumItems();
+ 		return 0;
+ 	}
+ 	public long toInternal(long i){ //return whether 0 based or 1 based counting
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	/** the method that other modules call to tell this one to calculate the number for the character.  Note that the result is not immediately
+	returned, but rather is remembered and returned when getNumber is called (this requires care in use!; perhaps should be redesigned)*/
+	public  void calculateNumber(CharacterDistribution origStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (origStates==null ||  !(origStates instanceof ContinuousDistribution) || origStates.getParentData()==null || !MesquiteInteger.isNonNegative(origStates.getParentCharacter())){
+			data = null;
+			result.setToUnassigned();
+		}
+		else {
+			data = (ContinuousData) origStates.getParentData();
+			int ic = origStates.getParentCharacter();
+			
+				ContinuousDistribution cStates = (ContinuousDistribution)origStates;
+				double state = cStates.getState(iTaxon, item);
+					result.setValue(state);
+	
+		
+		if (resultString!=null)
+			resultString.setValue("Value of character in taxon " + (iTaxon+1) + ": "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxon " + Taxon.toExternal(iTaxon));
+		temp.addLine("setItem " + CharacterStates.toExternal(item));
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Goes to next character history", null, commandName, "nextTaxon")) {
+			if (data == null)
+				return null;
+			if (iTaxon>= data.getNumTaxa())
+				iTaxon=0;
+			else
+				iTaxon++;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character history", null, commandName, "previousTaxon")) {
+			if (data == null)
+				return null;
+			if (iTaxon<=0)
+				iTaxon= (int)data.getNumTaxa()-1;
+			else
+				iTaxon--;
+			parametersChanged();
+		}
+
+		else if (checker.compare(this.getClass(), "Queries user about which character history to use", null, commandName, "chooseTaxon")) {
+			if (data == null)
+				return null;
+			Taxa taxa = data.getTaxa();
+			Taxon taxon = taxa.userChooseTaxon(containerOfModule(), "Taxon whose values to show");
+			if (taxon == null)
+				return null;
+			iTaxon = taxa.whichTaxonNumber(taxon);
+			parametersChanged();
+		}
+
+		else if (checker.compare(this.getClass(), "Sets which character history to use", "[taxon number]", commandName, "setTaxon")) {
+			pos.setValue(0);
+
+			int itNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(itNum))
+				return null;
+			int it = Taxon.toInternal(itNum);
+				iTaxon = it;
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets which character history to use", "[item number]", commandName, "setItem")) {
+			pos.setValue(0);
+
+			int itemNum = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(itemNum))
+				return null;
+			int it = CharacterStates.toInternal(itemNum);
+			if ((it>=0) && (it<=(int)getMax())) {
+				iTaxon = it;
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** this method is called for a bit of an explanation of the number calculated*/
+    	 public String getParameters() {
+    		 if (data == null)
+    	 	return "Values for item " + (item+1) + " for taxon " + (iTaxon+1);
+    		 else
+    			 return "Values for item " + (item+1) + " for " + data.getTaxa().getTaxonName(iTaxon);
+
+
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** name of this module as it appears in menus, etc.*/
+    	 public String getName() {
+		return "Value of item in taxon";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Gives the value of an item for in a continuous character, for a specific taxon." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/cont/ItemsEditorForInfoPanel/ItemsEditorForInfoPanel.java b/Source/mesquite/cont/ItemsEditorForInfoPanel/ItemsEditorForInfoPanel.java
new file mode 100644
index 0000000..fdd2af8
--- /dev/null
+++ b/Source/mesquite/cont/ItemsEditorForInfoPanel/ItemsEditorForInfoPanel.java
@@ -0,0 +1,344 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.cont.ItemsEditorForInfoPanel;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.RequiresExactlyCategoricalData;
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.lib.table.*;
+
+public class ItemsEditorForInfoPanel extends MatrixInfoPanelAssistantI  {
+	ItemsPanel panel;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*
+	public  Class getHireSubchoice(){
+		return NumberForTree.class;
+	}
+
+	/*.................................................................................................................*/
+	public MatrixInfoExtraPanel getPanel(ClosablePanelContainer container){
+		panel =  new ItemsPanel(container, this);
+		return panel;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new ContinuousStateTest();
+		}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("panelOpen " + panel.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the panel open", null, commandName, "panelOpen")) {
+			if (panel != null)
+				panel.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Continuous Items Editor";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Edits items for continuous data matrix within the editor info panel.";
+	}
+}
+/*===========================================*/
+class ItemsPanel extends MatrixInfoExtraPanel  {
+	String message = null;
+	ItemsEditorForInfoPanel ownerModule;
+	StringInABox statesBox;
+	ItemsField itemsField;
+	ContinuousData cData;
+	Image add, subtract, query;
+	public ItemsPanel(ClosablePanelContainer container, ItemsEditorForInfoPanel ownerModule){
+		super(container, "Items");
+		statesBox =  new StringInABox("", null, 50);
+		itemsField = new ItemsField(this);
+		itemsField.setBackground(getBackground());
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addGray.gif");
+		subtract = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "subtractGray.gif");
+		query = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "queryGray.gif");
+		currentHeight = 100 + MINHEIGHT + charNameHeight;
+		setLayout(null);
+		add(itemsField);
+		resetLocs();
+		this.ownerModule = ownerModule;
+	}
+	public int getRequestedHeight(int width){
+		if (isOpen())
+			return MINHEIGHT + itemsField.getDesiredHeight() + 30;
+		else
+			return MINHEIGHT;
+	}
+
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table){
+		super.setMatrixAndTable(data, table);
+		this.cData = (ContinuousData)data;
+		itemsField.setData(cData);
+		resetLocs();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	void enterName(int item, String name){
+		if (item<0 || item>= cData.getNumItems())
+			return;
+		cData.setItemReference(item, NameReference.getNameReference(name));
+		((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+	}
+	public void setOpen(boolean open){
+		itemsField.setVisible(open);
+		resetLocs();
+		super.setOpen(open);
+	}
+	int charNameHeight = 24;
+	void resetLocs(){
+		if (itemsField == null)
+			return;
+		//itemsField.setBounds(0, 0, getWidth()-4, getHeight());
+		itemsField.setBounds(2, MINHEIGHT + 4, getWidth()-4, itemsField.getDesiredHeight());
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+	void changeFocus(int item, int change){
+		if (item+change >= 0 && item+change< cData.getNumItems())
+			itemsField.items[item+change].requestFocusInWindow();
+	}
+	public void paint(Graphics g){
+		super.paint(g);
+		int h = itemsField.getY() + itemsField.getHeight() + 4;
+		g.drawImage(add, 2, h, this);
+		g.drawImage(subtract, 24, h, this);
+		g.drawImage(query, getWidth()-20, 4, this);
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		int h = itemsField.getY() + itemsField.getHeight() + 4;
+		if (y>=h && y< h+19) {
+			if (x>=2 && x<20){
+				String d = MesquiteString.queryString(MesquiteWindow.windowOfItem(this), "New item", "Name of new item.", "");
+				if (StringUtil.blank(d))
+					return;
+				else {
+					cData.addItem(d);
+					itemsField.setData(cData);
+					((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					container.requestHeightChange(this);
+				}
+			}
+			else if (x>= 24 && x<=40){
+				String[] items = new String[cData.getNumItems()];
+				for (int i=0; i<items.length; i++){
+					items[i]= cData.getItemName(i);
+				}
+				int d = ListDialog.queryList(MesquiteWindow.windowOfItem(this), "Remove item", "Remove item:", MesquiteString.helpString, items, 0);
+				if (!MesquiteInteger.isCombinable(d) || d<0 || d>=cData.getNumItems())
+					return;
+				else {
+					cData.removeItem(d);
+					itemsField.setData(cData);
+					((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					container.requestHeightChange(this);
+				}
+			}
+		}
+		else if (y<MINHEIGHT && (x> getWidth()- 20)) {
+			MesquiteTrunk.mesquiteTrunk.alert("These are the items of the continuous matrix.  A continuous matrix can have multiple items in each cell (e.g., X, Y and Z coordinates). Here you can control how many items there are, and their names.");  //query button hit
+		}
+		else
+			super.mouseUp(modifiers,  x,  y,  tool);
+	}
+}
+/*-----------------------------*/
+class ItemsField extends Panel {
+	NameField[] items;
+	ItemsPanel panel;
+	ItemContainer data;
+	int ic = -1;
+	public ItemsField(ItemsPanel panel){
+		this.panel = panel;
+		setLayout(null);
+		resetLocs();
+	}
+	void setData(ItemContainer data){
+		this.data = data;
+		resetItems();
+		resetLocs();
+
+	}
+	public void setVisible(boolean vis){
+		super.setVisible(vis);
+		if (items == null)
+			return;
+		for (int state = 0; state<data.getNumItems(); state++)
+			items[state].setVisible(vis);
+	}
+	int w = 10;
+	void setContainingWidth(int w){
+		this.w = w-30;
+		resetLocs();
+	}
+	
+	public void resetItems(){
+		if (items == null || items.length != data.getNumItems()){
+			if (items != null)
+				for (int item = 0; item< items.length; item++){
+					remove(items[item]);
+				}
+			items = new NameField[data.getNumItems()];
+
+			for (int item = 0; item<data.getNumItems(); item++){
+				items[item] = new NameField(panel, item);
+				add(items[item]);
+				items[item].setVisible(true);
+			}
+		}
+		if (items == null)
+			return;
+		for (int item = 0; item<data.getNumItems(); item++){
+			items[item].setText(data.getItemName(item));
+		}
+	}
+	int charNameHeight = 24;
+	void resetLocs(){
+		if (items == null)
+			return;
+		for (int state = 0; state < items.length && state<data.getNumItems(); state++){
+			items[state].setBounds(2, charNameHeight*state, getWidth()-4, charNameHeight);
+		}
+	}
+	int getDesiredHeight(){
+		if (data == null)
+			return  charNameHeight*2;
+		return charNameHeight*(data.getNumItems());
+	}
+
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+}
+class NameField extends TextField implements FocusListener {
+	ItemsPanel panel;
+	int item = -1;
+	boolean somethingTyped;
+
+	public NameField(ItemsPanel panel, int item){
+		this.panel = panel;
+		this.item = item;
+		setText("");
+		addKeyListener(new KListener());
+		addFocusListener(this);
+	}
+
+	public void focusGained(FocusEvent e){
+	}
+	public void focusLost(FocusEvent e){
+		if (somethingTyped)
+			panel.enterName(item, getText());
+	}
+	class KListener extends KeyAdapter {
+		MesquiteWindow window = null;
+		public KListener (){
+			super();
+		}
+		public void keyPressed(KeyEvent e){
+			//Event queue
+			if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+				if (somethingTyped){
+					panel.enterName(item, getText());
+					setSelectionStart(getText().length());
+					setSelectionEnd(getText().length());
+				}
+				panel.changeFocus(item, 1);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_UP) {
+				if (somethingTyped)
+					panel.enterName(item, getText());
+				panel.changeFocus(item, -1);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_DOWN || e.getKeyCode()== KeyEvent.VK_TAB){
+				if (somethingTyped)
+					panel.enterName(item, getText());
+				panel.changeFocus(item, 1);
+			}
+			else { 
+				somethingTyped=true;
+			}
+
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/cont/LogTransform/LogTransform.java b/Source/mesquite/cont/LogTransform/LogTransform.java
new file mode 100644
index 0000000..1f74079
--- /dev/null
+++ b/Source/mesquite/cont/LogTransform/LogTransform.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.LogTransform;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class LogTransform extends ContDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+   	
+   	boolean firstTime = true;
+   	
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		ContinuousData data = ((ContinuousData)ddata);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state)) {
+				if (state<=0) {
+					if (firstTime)
+						discreetAlert( "Some values could not be log transformed because they were zero or negative");
+					firstTime = false;
+				}
+				else
+					data.setState(ic,it, item, Math.log(state));
+			}
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Log transform";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by log transforming values." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/cont/ManageContChars/ManageContChars.java b/Source/mesquite/cont/ManageContChars/ManageContChars.java
new file mode 100644
index 0000000..b4df74f
--- /dev/null
+++ b/Source/mesquite/cont/ManageContChars/ManageContChars.java
@@ -0,0 +1,32 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.ManageContChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== 
+Manages continuous data matrices  */
+public class ManageContChars extends ManageContCharsA {
+	
+}
+	
+	
+
diff --git a/Source/mesquite/cont/ManageGeogChars/ManageGeogChars.java b/Source/mesquite/cont/ManageGeogChars/ManageGeogChars.java
new file mode 100644
index 0000000..422eacd
--- /dev/null
+++ b/Source/mesquite/cont/ManageGeogChars/ManageGeogChars.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.ManageGeogChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== 
+Manages geographic data matrices  */
+public class ManageGeogChars extends ManageContCharsA {
+	int maxNumChars = 2;
+	
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	public Class getStateClass(){
+		return GeographicState.class;
+	}
+	/*.................................................................................................................*/
+	public Class getDataClass(){
+		return GeographicData.class;
+	}
+	/*.................................................................................................................*/
+	public  String getDataClassName(){
+		return "Geographic Data";
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		return new GeographicData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == GeographicData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("Geographic");
+	}
+	/*.................................................................................................................*/
+	public String getDataTypeString() {
+		return "GEOGRAPHIC";
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage Geographic character matrices";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages data matrices of geographic data (including read/write in NEXUS file)." ;
+   	 }
+}
+	
+	
+
diff --git a/Source/mesquite/cont/MapContinuous/MapContinuous.java b/Source/mesquite/cont/MapContinuous/MapContinuous.java
new file mode 100644
index 0000000..5183c0d
--- /dev/null
+++ b/Source/mesquite/cont/MapContinuous/MapContinuous.java
@@ -0,0 +1,301 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.MapContinuous;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class MapContinuous extends NumbersForNodesIncr implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of continuous characters whose ancestral states will be reconstructed.",
+		"The source of characters can be specified initially or later through the Source of Characters or Character Source submenus.");
+		EmployeeNeed e3 = registerEmployeeNeed(CharStatesForNodes.class, getName() + " needs a method to calculate ancestral states to map the character.",
+		"The reconstruction method is chosen automatically or can be chosen initially.");
+	}
+	CharStatesForNodes assignTask;
+	CharacterDistribution observedStates;
+	ContinuousHistory reconstructedStates, recon;
+	CharSourceCoordObed characterSourceTask;
+	NumberArray numbers;
+	Taxa currentTaxa;
+	Tree tree;
+	int currentChar=0;
+	long oldTreeVersion = 0;
+	long oldTreeID = 0;
+	boolean characterSet = false;
+	int lastCharRetrieved = -1;
+	
+	//choice of what item to show
+	int currentItem=0;
+	MesquiteMenuItemSpec itemItem;
+	MesquiteCommand itemChoiceCommand;
+	String itemName=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, ContinuousState.class, "Source of characters (for Map Continuous)");
+ 		if (characterSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of characters obtained.");
+ 		}
+		
+		//todo: allow subsequentChoice
+ 		assignTask = (CharStatesForNodes)hireNamedEmployee(CharStatesForNodes.class, StringUtil.tokenize("Parsimony Ancestral States"));
+ 		if (assignTask == null)
+			assignTask = (CharStatesForNodes)hireEmployee(CharStatesForNodes.class, "Reconstruction method");
+ 		if (assignTask == null)
+ 			return sorry(getName() + " couldn't start because no reconstructing module obtained.");
+		/**/
+		if (!(NumbersForNodesIncr.class.isAssignableFrom(getHiredAs()))){
+			addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+			addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+			addMenuItem( "Choose Character", makeCommand("chooseCharacter",  this));
+		}
+		/**/
+		itemChoiceCommand = MesquiteModule.makeCommand("setItem",  this);
+		itemItem = addMenuItem("Item to Map...", itemChoiceCommand);
+		return true;  
+ 	}
+ 	
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == characterSourceTask || employee == assignTask)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+	private String itemString(){
+ 		if (itemName!=null)
+			return " (item " + itemName + ")";
+ 		else
+			return "";  
+	}
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 			return assignTask.getName() + " of " + characterSourceTask.getNameAndParameters() + itemString();
+   	 }
+	/*.................................................................................................................*/
+   	 public void setCurrent(long i){
+ 		if (characterSourceTask==null || currentTaxa==null){
+ 			currentChar = (int)i;
+			characterSet=true;
+ 		}
+ 		else if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)) {
+ 			currentChar = (int)i;
+			characterSet=true;
+		}
+   	 }
+ 	public String getItemTypeName(){
+ 		return "Character";
+ 	}
+	/*.................................................................................................................*/
+ 	public long toInternal(long i){
+ 		return(CharacterStates.toInternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+ 	public long toExternal(long i){
+ 		return(CharacterStates.toExternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+   	 public long getCurrent(){
+   	 	return currentChar;
+   	 }
+	/*.................................................................................................................*/
+ 	public long getMin(){
+ 		return 0;
+ 	}
+	/*.................................................................................................................*/
+ 	public long getMax(){
+ 		if (characterSourceTask==null || currentTaxa==null)
+ 			return 0;
+ 		return characterSourceTask.getNumberOfCharacters(currentTaxa)-1;
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 //TODO: allow change in assignTask, etc.
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine( "getCharacterSource " , characterSourceTask);
+  	 	temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+  	 	temp.addLine("setItem " + (currentItem));
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+ 			return characterSourceTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+ 			return characterSourceTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+    	 		if (currentChar>=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)
+    	 			currentChar=0;
+    	 		else
+    	 			currentChar++;
+				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "previousCharacter")) {
+    	 		if (currentChar<=0)
+    	 			currentChar=characterSourceTask.getNumberOfCharacters(currentTaxa)-1;
+    	 		else
+    	 			currentChar--;
+				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries the user which character to use", null, commandName, "chooseCharacter")) {
+    	 		int ic=characterSourceTask.queryUserChoose(currentTaxa, " to map " + whatIsMyPurpose());
+    	 		if (MesquiteInteger.isCombinable(ic)) {
+	   			currentChar = ic;
+	 			characterSet=true;
+	 			parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the character to use", "[number of character]", commandName, "setCharacter")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+   			if (currentTaxa==null) {
+    	 			currentChar = ic;
+	 			characterSet=true;
+   			}
+    	 		if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(currentTaxa)-1)) {
+    	 			currentChar = ic;
+	 			characterSet=true;
+				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the item to use (in a multi-item continuous data matrix)", "[item number]", commandName, "setItem")) {
+    	 		int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (!MesquiteInteger.isCombinable(ic) && reconstructedStates!=null){
+				ic = reconstructedStates.userQueryItem("Select item to map", this);
+    	 		}
+   			if (!MesquiteInteger.isCombinable(ic))
+   				return null;
+   			if (currentTaxa==null) {
+    	 			currentItem = ic;
+   			}
+ 			else if (reconstructedStates !=null && reconstructedStates instanceof ContinuousHistory) {
+	   	 		if ((ic>=0) && (ic<=reconstructedStates.getNumItems()-1)) {
+	    	 			currentItem = ic;
+					parametersChanged();
+	 			}
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		observedStates = null;//to force recalculation
+ 		super.employeeParametersChanged(module, source, notification);
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		currentTaxa = tree.getTaxa();
+   		characterSourceTask.initialize(currentTaxa);
+   	}
+   int times = 0;
+	/*.................................................................................................................*/
+	public  void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString) {
+		if (tree==null)
+			return;
+		this.tree = tree;
+		itemName=null;
+		Taxa taxa = tree.getTaxa();
+	   	clearResultAndLastResult(result);
+		if (taxa != currentTaxa || (characterSourceTask.usesTree() && (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion)) || currentChar != lastCharRetrieved || observedStates == null ) { 
+			int maxnum = characterSourceTask.getNumberOfCharacters(tree);
+			if (currentChar>= maxnum)
+				currentChar = maxnum-1;
+			observedStates = characterSourceTask.getCharacter(tree, currentChar);
+			currentTaxa = taxa;
+			oldTreeVersion = tree.getVersionNumber();
+			oldTreeID = tree.getID();
+			lastCharRetrieved = currentChar;
+		}
+		if (observedStates ==null)
+			return;
+		recon = (ContinuousHistory)observedStates.adjustHistorySize(tree, recon);
+		assignTask.calculateStates(tree, observedStates, recon, null);
+		if (recon!=null)
+			reconstructedStates=(ContinuousHistory)recon.clone(reconstructedStates);
+		
+		if (reconstructedStates != null) {
+			int numItems = reconstructedStates.getNumItems();
+			if (numItems>1){
+				if (!itemItem.isEnabled()){
+					itemItem.setEnabled(true);
+					MesquiteTrunk.mesquiteTrunk.resetMenuItemEnabling();
+				}
+				if (currentItem>= numItems)
+					currentItem=0;
+				itemName = reconstructedStates.getItemName(currentItem);
+				
+			}
+			else {
+				currentItem = 0;
+				if (itemItem.isEnabled()){
+					itemItem.setEnabled(false);
+					MesquiteTrunk.mesquiteTrunk.resetMenuItemEnabling();
+				}
+			} 
+			
+		}
+		if (resultString !=null)
+			resultString.setValue(itemString());
+			
+
+		if (reconstructedStates !=null && reconstructedStates instanceof ContinuousHistory) {
+			DoubleArray dub = reconstructedStates.getItem(currentItem);
+			result.setValues(dub.getMatrix());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	 public String getNameAndParameters() {
+		 if (characterSourceTask == null)
+			 return getName();
+	return characterSourceTask.getNameAndParameters();
+	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Map Continuous";
+   	 }
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies a reconstruction of continuous-valued ancestral states on a tree." 
+ 		+ " Differs from the basic reconstruction methods in that it supplies simply numbers for nodes, instead of a CharacterHistory";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/MeanValue/MeanValue.java b/Source/mesquite/cont/MeanValue/MeanValue.java
new file mode 100644
index 0000000..952de41
--- /dev/null
+++ b/Source/mesquite/cont/MeanValue/MeanValue.java
@@ -0,0 +1,174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.MeanValue; 
+/*~~  */
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+
+public class MeanValue extends NumberForCharacter implements NumberForCharacterIncr,  NumForCharTreeIndep{ 
+	boolean warnedOnce = false;
+	ContinuousDistribution cStates;
+
+	//choice of what item to show
+	int currentItem=0;
+	MesquiteMenuItemSpec itemItem;
+	MesquiteCommand itemChoiceCommand;
+	String itemName=null;
+	/*.................................................................................................................*/
+	/** a method called when the module is started up.  You can put initialization stuff here*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition!= ContinuousData.class && condition!=ContinuousState.class) {
+  	 		return sorry("Mean Value of Character could not start because it can be used only for continuous-valued characters");
+ 		}
+		if (!(NumberForCharacterIncr.class.isAssignableFrom(getHiredAs()))){ //not hired as obedient
+			itemChoiceCommand = MesquiteModule.makeCommand("setItem",  this);
+			itemItem = addMenuItem("Item for Mean Value...", itemChoiceCommand);
+		}
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+  	 
+ 	public void setCurrent(long i){ //SHOULD NOT notify (e.g., parametersChanged)
+ 		currentItem = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return currentItem;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Item";
+ 	}
+ 	public long getMin(){
+ 		return 0;
+ 	}
+ 	public long getMax(){
+ 		if (cStates !=null)
+ 			return cStates.getNumItems();
+ 		return 0;
+ 	}
+ 	public long toInternal(long i){ //return whether 0 based or 1 based counting
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setItem " + (currentItem));
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the item to use (in a multi-item continuous data matrix)", "[item number]", commandName, "setItem")) {
+    	 		int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (!MesquiteInteger.isCombinable(ic) && cStates!=null){
+				ic = cStates.userQueryItem("Select item for Mean Value calculation", this);
+    	 		}
+   			if (!MesquiteInteger.isCombinable(ic))
+   				return null;
+   			if (cStates==null) {
+    	 			currentItem = ic;
+   			}
+ 			else if (cStates !=null && cStates instanceof ContinuousDistribution) {
+	   	 		if ((ic>=0) && (ic<=cStates.getNumItems()-1)) {
+	    	 			currentItem = ic;
+					parametersChanged();
+	 			}
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new ContinuousStateTest();
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	/** the method that other modules call to tell this one to calculate the number for the character.  Note that the result is not immediately
+	returned, but rather is remembered and returned when getNumber is called (this requires care in use!; perhaps should be redesigned)*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		String itemName = Integer.toString(currentItem+1);
+		if (charStates==null)
+			result.setToUnassigned();
+		else if  (!(charStates instanceof ContinuousDistribution)){
+			if (!warnedOnce)
+				discreetAlert( "Mean value of character can be calculated only for Continuous characters");
+			warnedOnce = true;
+			result.setToUnassigned();
+			if (resultString!=null)
+				resultString.setValue("No mean value calculated; can be calculated only for Continuous characters");
+		}
+		else {
+			warnedOnce = false;
+			cStates = (ContinuousDistribution)charStates;
+			int numtaxa = cStates.getNumNodes();
+			if (cStates.getNumItems() > 1){
+				itemName = cStates.getItemName(currentItem);
+				if (StringUtil.blank(itemName))
+					itemName = Integer.toString(currentItem+1);
+			}
+			double sum= 0.0;
+			int n=0;
+			for (int i=0; i<numtaxa; i++){
+				double s = cStates.getState (i, currentItem);
+				if (MesquiteDouble.isCombinable(s)) {
+					sum += s;
+					n++;
+				}
+			}
+			if (n==0)
+				result.setToUnassigned();
+			else
+				result.setValue(sum/n);
+			if (resultString!=null)
+				resultString.setValue("Mean value of character: "+ result.toString() + " for item " + itemName);
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** name of this module as it appears in menus, etc.*/
+    	 public String getName() {
+		return "Mean value of character";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the mean observed trait for continuous character." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/cont/MultiplyByCharacter/MultiplyByCharacter.java b/Source/mesquite/cont/MultiplyByCharacter/MultiplyByCharacter.java
new file mode 100644
index 0000000..9a0667d
--- /dev/null
+++ b/Source/mesquite/cont/MultiplyByCharacter/MultiplyByCharacter.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.MultiplyByCharacter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class MultiplyByCharacter extends ContDataAlterer {
+	double scalingFactor = 1.0;
+	CharSourceCoordObed characterSourceTask;
+	int multiplyingIC = 0;
+	ContinuousDistribution multiplyingCharacter;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		String exp = "Source of character to multiply by";
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, ContinuousState.class, exp);
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		if (!(data instanceof ContinuousData))
+			return false;
+ 			Taxa taxa = data.getTaxa();
+   			multiplyingIC=characterSourceTask.queryUserChoose(taxa, "by which to multiply states");
+   			multiplyingCharacter = (ContinuousDistribution)characterSourceTask.getCharacter(taxa, multiplyingIC); 
+			boolean did=false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		if (multiplyingCharacter == null)
+   			return;
+		ContinuousData data = (ContinuousData)ddata;
+		
+		double factor = multiplyingCharacter.getState(it, 0);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state) && MesquiteDouble.isCombinable(factor))
+				data.setState(ic,it, item, state*factor);
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  //put release version
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Multiply by character";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by multiplying by a continuous character.  All items of the matrix are similarly modified." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/MultiplyStates/MultiplyStates.java b/Source/mesquite/cont/MultiplyStates/MultiplyStates.java
new file mode 100644
index 0000000..4ee89bc
--- /dev/null
+++ b/Source/mesquite/cont/MultiplyStates/MultiplyStates.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.MultiplyStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class MultiplyStates extends ContDataAlterer {
+	double scalingFactor = 1.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+   			boolean did=false;
+			if (!(data instanceof ContinuousData))
+				return false;
+			double d = MesquiteDouble.queryDouble(containerOfModule(), "Multiply values", "Multiply values in matrix by:", scalingFactor); //todo: have dialog also ask to what item; also in other similar ContDataAlterer's
+			if (MesquiteDouble.isCombinable(d))
+				scalingFactor = d;
+			else
+				return false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+		ContinuousData data = (ContinuousData)ddata;
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state))
+				data.setState(ic,it, item, state*scalingFactor);
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Multiply by value";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by multiplying by a value.  All items of the matrix are similarly modified." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/NodeLocs2DPlot/NodeLocs2DPlot.java b/Source/mesquite/cont/NodeLocs2DPlot/NodeLocs2DPlot.java
new file mode 100644
index 0000000..e5b4247
--- /dev/null
+++ b/Source/mesquite/cont/NodeLocs2DPlot/NodeLocs2DPlot.java
@@ -0,0 +1,679 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.NodeLocs2DPlot;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodeLocs2DPlot extends NodeLocsPlot {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(NumbersForNodesIncr.class, getName() + " needs a method to calculate the X,Y values used to plot the tree.",
+		"You can choose the values to calculate either initially or in the Node Values submenu.");
+	}
+	
+	Point[] location;
+	NumbersForNodesIncr numbersForNodesTask;
+	int margin = 40;
+	MesquiteString numberTaskName;
+	MesquiteNumber tempNum;
+	boolean veryFirstTime=true;
+	int initialOffsetX = MesquiteInteger.unassigned;
+	int initialOffsetY = MesquiteInteger.unassigned;
+	Vector extras;
+	public MesquiteBoolean showLegend;
+	int currentX = 0;
+	int currentY=1;
+	String xString, yString;
+	boolean hide = false;
+	MesquiteCommand nfntC;
+	MesquiteNumber xNumber = new MesquiteNumber();
+	MesquiteNumber yNumber = new MesquiteNumber();
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+   		extras = new Vector();
+		numbersForNodesTask= (NumbersForNodesIncr)hireEmployee(NumbersForNodesIncr.class, "Values to calculate for axes for Plot Tree");
+		if (numbersForNodesTask == null )
+			return sorry(getName() + " couldn't start because no modules calculating numbers for nodes obtained.");
+		nfntC = makeCommand("setAxis",  this);
+		numbersForNodesTask.setHiringCommand(nfntC);
+		showLegend = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Plot Tree Legend", makeCommand("toggleShowLegend",  this), showLegend);
+		makeMenu("Plot");
+		numberTaskName = new MesquiteString(numbersForNodesTask.getName());
+		if (numModulesAvailable(NumbersForNodesIncr.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Values", nfntC, NumbersForNodesIncr.class);
+			mss.setSelected(numberTaskName);
+		}
+		tempNum = new MesquiteNumber();
+		MesquiteSubmenuSpec xsub = addSubmenu(null, "X Axis");
+		addItemToSubmenu(null, xsub, "Next", makeCommand("nextX",  this));
+		addItemToSubmenu(null, xsub, "Previous", makeCommand("previousX",  this));
+		addItemToSubmenu(null, xsub, "Choose", makeCommand("setX",  this));
+		
+		MesquiteSubmenuSpec ysub = addSubmenu(null, "Y Axis");
+		addItemToSubmenu(null, ysub, "Next", makeCommand("nextY",  this));
+		addItemToSubmenu(null, ysub, "Previous", makeCommand("previousY",  this));
+		addItemToSubmenu(null, ysub, "Choose", makeCommand("setY",  this));
+  		return true;
+  	 }
+  	 
+  	/*.................................................................................................................*/
+	 
+   	public void endJob(){
+   		hide = true;
+  	 	if (extras!=null) {
+	   		for (int i=0; i<extras.size(); i++){
+	   			TreeDisplayExtra extra = (TreeDisplayExtra)extras.elementAt(i);
+		   		if (extra!=null){
+		   			TreeDisplay td = extra.getTreeDisplay();
+		   			extra.turnOff();
+		   			if (td!=null)
+		   				td.removeExtra(extra);
+		   		}
+	   		}
+	   		extras.removeAllElements();
+  	 	}
+   		super.endJob();
+   	}
+   	public boolean isSubstantive(){
+   		return true;
+   	}
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+  	 	if (extras!=null) {
+	   		for (int i=0; i<extras.size(); i++){
+	   			NodeLocs2DPlotExtra extra = (NodeLocs2DPlotExtra)extras.elementAt(i);
+		   		if (extra!=null){
+ 					extra.pleaseAdjustScrolls=true;
+		   		}
+	   		}
+  	 	}
+    	 	parametersChanged(notification);
+   	 }
+   	 public NodeLocs2DPlotExtra getFirstExtra(){
+  	 	if (extras!=null) {
+	   		for (int i=0; i<extras.size(); i++){
+	   			NodeLocs2DPlotExtra extra = (NodeLocs2DPlotExtra)extras.elementAt(i);
+		   		if (extra!=null){
+ 					return extra;
+		   		}
+	   		}
+  	 	}
+  	 	return null;
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine( "hide");
+  	 	temp.addLine( "setAxis " , numbersForNodesTask);
+  	 	temp.addLine("toggleShowLegend " + showLegend.toOffOnString());
+  	 	if (getFirstExtra()!=null && getFirstExtra().legend!=null) {
+  	 		temp.addLine("setInitialOffsetX " + getFirstExtra().legend.getOffsetX()); //Should go operator by operator!!!
+  	 		temp.addLine("setInitialOffsetY " + getFirstExtra().legend.getOffsetY());
+  	 	}
+   	 	temp.addLine( "setCurrentX " + CharacterStates.toExternal(currentX));
+  	 	temp.addLine( "setCurrentY " + CharacterStates.toExternal(currentY));
+ 	 	temp.addLine( "show");
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the module that calculates coordinates for the nodes", "[name of module]", commandName, "setAxis")) {
+    	 		NumbersForNodesIncr temp =  (NumbersForNodesIncr)replaceEmployee(NumbersForNodesIncr.class, arguments, "Value for axes", numbersForNodesTask);
+ 			if (temp!=null) {
+ 				numbersForNodesTask = temp;
+				numbersForNodesTask.setHiringCommand(nfntC);
+				numberTaskName.setValue(numbersForNodesTask.getName());
+				resetContainingMenuBar();
+ 				parametersChanged();
+ 			}
+ 			return temp;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Hides the plot", null, commandName, "hide")) {
+    	 		hide = true;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Shows the plot", null, commandName, "show")) {
+    	 		hide = false;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the current item displayed on the x axis (used by scripting, before display)", "[number of item]", commandName, "setCurrentX")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 			currentX = ic;
+    	 			numbersForNodesTask.setCurrent(ic);
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the current item displayed on the y axis (used by scripting, before display)", "[number of item]", commandName, "setCurrentY")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 			currentY = ic;
+    	 			numbersForNodesTask.setCurrent(ic);
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the current item displayed on the x axis", "[number of item]", commandName, "setX")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 		if (!MesquiteInteger.isCombinable(ic))
+    	 			ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose item (X axis)", "Item to map", 1);
+    	 		if (MesquiteInteger.isCombinable(ic) && (ic>=numbersForNodesTask.getMin()) && (ic<=numbersForNodesTask.getMax())) {
+    	 			currentX = ic;
+    	 			numbersForNodesTask.setCurrent(ic);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the current item displayed on the y axis", "[number of item]", commandName, "setY")) {
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 		if (!MesquiteInteger.isCombinable(ic))
+    	 			ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose item (Y axis)", "Item to map", 1);
+    	 		if (MesquiteInteger.isCombinable(ic) && (ic>=numbersForNodesTask.getMin()) && (ic<=numbersForNodesTask.getMax())) {
+    	 			currentY = ic;
+    	 			numbersForNodesTask.setCurrent(ic);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next item for X axis", null, commandName, "nextX")) {
+    	 		if (currentX<numbersForNodesTask.getMax()) {
+    	 			currentX++;
+    	 			numbersForNodesTask.setCurrent(currentX);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next item for Y axis", null, commandName, "nextY")) {
+    	 		if (currentY<numbersForNodesTask.getMax()) {
+    	 			currentY++;
+    	 			numbersForNodesTask.setCurrent(currentY);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous item for X axis", null, commandName, "previousX")) {
+    	 		if (currentX>numbersForNodesTask.getMin()) {
+    	 			currentX--;
+    	 			numbersForNodesTask.setCurrent(currentX);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous item for Y axis", null, commandName, "previousY")) {
+    	 		if (currentY>numbersForNodesTask.getMin()) {
+    	 			currentY--;
+    	 			numbersForNodesTask.setCurrent(currentY);
+		  	 	adjustScrolls();
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the initial horizontal offset from home position for the legend", "[offset in pixels]", commandName, "setInitialOffsetX")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the initial vertical offset from home position for the legend", "[offset in pixels]", commandName, "setInitialOffsetY")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not to show the legend", "[on or off]", commandName, "toggleShowLegend")) {
+    	 		showLegend.toggleValue(parser.getFirstToken(arguments));
+	  	 	if (extras!=null) {
+		   		for (int i=0; i<extras.size(); i++){
+		   			NodeLocs2DPlotExtra extra = (NodeLocs2DPlotExtra)extras.elementAt(i);
+			   		if (extra!=null && extra.legend!=null){
+	 					extra.legend.setVisible(showLegend.getValue());
+			   		}
+		   		}
+	  	 	}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 private void adjustScrolls(){
+  	 	if (extras!=null) {
+	   		for (int i=0; i<extras.size(); i++){
+	   			NodeLocs2DPlotExtra extra = (NodeLocs2DPlotExtra)extras.elementAt(i);
+		   		if (extra!=null && extra.legend!=null){
+ 					extra.legend.adjustScrolls();
+		   		}
+	   		}
+  	 	}
+   	 }
+    	 public String getName() {
+		return "Node Locations (2D plot)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the node locations for a tree plotted in a two dimensional space." ;
+   	 }
+	/*_________________________________________________*/
+   	public boolean compatibleWithOrientation(int orientation) {
+   		return false;
+   	}
+ 	/*_________________________________________________*/
+  	boolean first=true;
+	MesquiteNumber minX, maxX, minY, maxY;
+
+	private void surveyValues (Tree tree, int node, NumberArray numbersX, NumberArray numbersY, MesquiteBoolean illegalValue){
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			surveyValues(tree, d, numbersX, numbersY, illegalValue);
+		numbersX.placeValue(node, xNumber);
+		numbersY.placeValue(node, yNumber);
+		if (!xNumber.isCombinable() || !yNumber.isCombinable())
+			illegalValue.setValue(true);
+		if (first) {
+			maxX.setValue(xNumber);
+			minX.setValue(xNumber);
+			maxY.setValue(yNumber);
+			minY.setValue(yNumber);
+			first = false;
+		}
+		else {
+			maxX.setMeIfIAmLessThan(xNumber);
+			minX.setMeIfIAmMoreThan(xNumber);
+			maxY.setMeIfIAmLessThan(yNumber);
+			minY.setMeIfIAmMoreThan(yNumber);
+		}
+	}
+	/*_________________________________________________*/
+	private void calcNodeLocs (Tree tree, int node, Rectangle rect, NumberArray numbersX, NumberArray numbersY){
+			if (location==null|| xNumber==null|| yNumber==null)
+				return;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				calcNodeLocs(tree, d, rect, numbersX, numbersY);
+			numbersX.placeValue(node, xNumber);
+			numbersY.placeValue(node, yNumber);
+			if (node>= location.length ||location[node] == null)
+				return;
+			if (!xNumber.isCombinable() || !yNumber.isCombinable()){
+				location[node].x = MesquiteInteger.unassigned;
+				location[node].y = MesquiteInteger.unassigned;
+			}
+			else {
+				location[node].x = xNumber.setWithinBounds(minX, maxX, rect.width - 2*margin) /*+ rect.x*/+ margin;
+				location[node].y = yNumber.setWithinBounds(minY, maxY, rect.height - 2*margin) /*+ rect.y*/ + margin;
+			}
+	}
+	
+ 	/*.................................................................................................................*/
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		if (employee == numbersForNodesTask)
+			return "for axes";
+		else
+			return "";
+	}
+	int rectWidth, rectHeight;
+	/*_________________________________________________*/
+	public void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect) {
+		if (hide || isDoomed())
+			return;
+		if (MesquiteTree.OK(tree)) {
+				if (treeDisplay == null || treeDisplay.getTreeDrawing() == null)
+					return;
+				if (veryFirstTime) {
+					veryFirstTime=false;
+					numbersForNodesTask.initialize(tree);
+				}
+				NodeLocs2DPlotExtra extra = null;
+				if (treeDisplay.getExtras() !=null) {
+					if (treeDisplay.getExtras().myElements(this)==null) {  
+						extra = new NodeLocs2DPlotExtra(this, treeDisplay); 
+						treeDisplay.addExtra(extra); 
+						extras.addElement(extra);
+					}
+					else {
+						Listable[] mine = treeDisplay.getExtras().myElements(this);
+						if (mine !=null && mine.length>0)
+							extra =(NodeLocs2DPlotExtra) mine[0];
+					}
+				}
+				
+				NumberArray numbersX= new NumberArray(tree.getNumNodeSpaces());
+				NumberArray numbersY=new NumberArray(tree.getNumNodeSpaces());
+				numbersForNodesTask.setCurrent(currentX);
+				numbersForNodesTask.calculateNumbers(tree, numbersX, null);
+				
+				xString = numbersForNodesTask.getNameAndParameters();
+
+				numbersForNodesTask.setCurrent(currentY);
+				numbersForNodesTask.calculateNumbers(tree, numbersY, null);
+				yString = numbersForNodesTask.getNameAndParameters();
+				extra.textPositions.setLength(0);
+				nodePositions(tree.getRoot(),  tree, extra.textPositions,  numbersX,  numbersY);
+				if (extra!=null)
+					extra.parameters = numbersForNodesTask.getParameters();
+				first = true;
+				int subRoot = tree.motherOfNode(drawnRoot);
+				location = new Point[tree.getNumNodeSpaces()];
+				for (int i=0; i<location.length; i++) {
+					location[i]= new Point();
+				}
+				minX = new MesquiteNumber();
+				maxX = new MesquiteNumber();
+				minY = new MesquiteNumber();
+				maxY = new MesquiteNumber();
+				MesquiteBoolean illegalValue = new MesquiteBoolean(false);
+				surveyValues(tree, drawnRoot, numbersX, numbersY, illegalValue); //check for illegal values added 13 Dec 01
+				if (illegalValue.getValue()) {
+					/*for (int i=0; i<tree.getNumNodeSpaces() && i<treeDisplay.getTreeDrawing().y.length; i++) {
+						treeDisplay.getTreeDrawing().y[i] = 0;
+						treeDisplay.getTreeDrawing().x[i] = 0;
+						treeDisplay.getTreeDrawing().z[i] = 0;
+					}*/
+					if (extra!=null)
+						extra.addWarning(true);
+					//return;
+				}
+				else if (extra!=null)
+					extra.addWarning(false);
+				calcNodeLocs (tree, drawnRoot, rect, numbersX, numbersY);
+				location[subRoot].x = location[drawnRoot].x;
+				location[subRoot].y = location[drawnRoot].y;
+				for (int i=0; i<tree.getNumNodeSpaces() && i<treeDisplay.getTreeDrawing().y.length; i++) {
+					treeDisplay.getTreeDrawing().y[i] = location[i].y;
+					treeDisplay.getTreeDrawing().x[i] = location[i].x;
+				}
+				this.rectWidth = rect.width;
+				this.rectHeight = rect.height;
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public void nodePositions(int N,  Tree tree, StringBuffer sb, NumberArray numbersX, NumberArray numbersY) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				nodePositions(d, tree, sb, numbersX, numbersY);
+		if (tree.nodeIsTerminal(N))
+			sb.append(tree.getTaxa().getName(tree.taxonNumberOfNode(N)) + '\t');
+		else
+			sb.append("node " + N +  '\t');
+		sb.append(numbersX.toString(N) + '\t' + numbersY.toString(N) + "\n");
+	}
+	
+	private void drawString(Graphics g, String s, int x, int y){
+		if (g == null || StringUtil.blank(s))
+			return;
+		try {
+			g.drawString(s, x, y);
+		}
+		catch (Exception e){
+		}
+	}
+	StringInABox xAxisWriter, yAxisWriter;
+	public void drawGrid (Graphics g, int x, int y, int width, int height, TreeDisplay treeDisplay) {
+		if (hide)
+			return;
+		if (minX == null || maxX == null || minY == null || maxY == null)
+			return;
+		boolean rulerOnly = false;
+		int rulerWidth = 8;
+		Color c=g.getColor();
+		g.setColor(Color.cyan);
+		int buffer = 8;
+		
+		double min, max;
+		int minTicks = 20;
+		
+		
+		//VERTICAL LINES
+		min = minX.getDoubleValue();
+		max = maxX.getDoubleValue();
+		double firstTick = MesquiteDouble.firstScaleMark(max-min, min, minTicks);
+		double tickIncrement = MesquiteDouble.scaleIncrement(max-min, min, minTicks);
+		int t = 0;
+		int bottomEdge = y+height;
+		if (tickIncrement>0 && (max-firstTick)/tickIncrement>1000)
+			tickIncrement = 0; //too dense; set this to pop out
+		for (double tick=firstTick; tick<max && tickIncrement>0; tick += tickIncrement) {
+			if (t % 10 == 0)
+				g.setColor(Color.blue);
+			else
+				g.setColor(Color.cyan);
+			tempNum.setValue(tick);
+			int xPos = x+tempNum.setWithinBounds(minX, maxX, width);
+			if (rulerOnly)
+				g.drawLine(xPos, bottomEdge,  xPos,  bottomEdge-rulerWidth);
+			else
+				g.drawLine(xPos, bottomEdge,  xPos,  y);
+
+			if (t++ % 10 == 0)
+				drawString(g, MesquiteDouble.toString(tick), xPos, bottomEdge + buffer);
+		}
+
+		
+		//HORIZONTAL LINES
+		min = minY.getDoubleValue();
+		max = maxY.getDoubleValue();
+		firstTick = MesquiteDouble.firstScaleMark(max-min, min, minTicks);
+		tickIncrement = MesquiteDouble.scaleIncrement(max-min, min, minTicks);
+		t = 0;
+		int rightEdge = x+width;
+		if (tickIncrement>0 && (max-firstTick)/tickIncrement>1000)
+			tickIncrement = 0; //too dense; set this to pop out
+		for (double tick=firstTick; tick<max && tickIncrement>0; tick += tickIncrement) {
+			if (t % 10 == 0)
+				g.setColor(Color.blue);
+			else
+				g.setColor(Color.cyan);
+			tempNum.setValue(tick);
+			int yPos = y+tempNum.setWithinBounds(minY, maxY, height);
+			if (rulerOnly)
+				g.drawLine(rightEdge,  yPos,  rightEdge-rulerWidth,yPos);
+			else
+				g.drawLine(rightEdge,  yPos,  x, yPos);
+
+			if (t++ % 10 == 0)
+				drawString(g, MesquiteDouble.toString(tick), rightEdge + buffer, yPos);
+		}
+		g.setColor(Color.blue);
+		
+		if (xAxisWriter==null)
+			xAxisWriter = new StringInABox(xString, g.getFont(), rightEdge-x);
+		else {
+			xAxisWriter.setWidth(rightEdge-x);
+			xAxisWriter.setString(xString);
+			xAxisWriter.setFont(g.getFont());
+		}
+		xAxisWriter.draw(g,x, y+height+10); 
+
+		if (yAxisWriter==null)
+			yAxisWriter = new StringInABox(yString, g.getFont(), height);
+		else {
+			yAxisWriter.setWidth(height);
+			yAxisWriter.setString(yString);
+			yAxisWriter.setFont(g.getFont());
+		}
+		yAxisWriter.draw(g,x-46, y+height, 0, rightEdge, treeDisplay, false); 
+		if (c!=null) g.setColor(c);
+	}
+}
+
+
+
+class NodeLocs2DPlotExtra extends TreeDisplayBkgdExtra {
+	public NodeLocs2DPlotLegend legend;
+	NodeLocs2DPlot locsModule;
+	public boolean pleaseAdjustScrolls = false;
+	public String parameters = "";
+	StringBuffer textPositions;
+
+	public NodeLocs2DPlotExtra (NodeLocs2DPlot ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		locsModule = ownerModule;
+		textPositions = new StringBuffer();
+	}
+	boolean doWarn = false;
+	public void addWarning(boolean warn){
+		if (legend!=null)
+			legend.addWarning(warn);
+		doWarn = warn;
+	}
+	/*.................................................................................................................*/
+	public   String infoAtNodes(Tree tree, int drawnRoot) {
+		return parameters + "\n\nNodes with X, Y positions\n\n" + textPositions.toString();
+	}
+	/*.................................................................................................................*/
+	public   String additionalText(Tree tree, int drawnRoot) {
+		return parameters;
+	}
+	/*.................................................................................................................*/
+	boolean legendMade = false;
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		locsModule.drawGrid(g, locsModule.margin/*+rect.x*/, locsModule.margin/*+rect.y*/, locsModule.rectWidth-2*locsModule.margin, locsModule.rectHeight-2*locsModule.margin, treeDisplay);
+		if (!legendMade && legend == null) {
+			legendMade= true;
+			legend = new NodeLocs2DPlotLegend(locsModule, this);
+		 	legend.adjustScrolls();
+			legend.setVisible(locsModule.showLegend.getValue());
+			legend.addWarning(doWarn);
+			addPanelPlease(legend);
+		}
+		else if (pleaseAdjustScrolls && legend!=null){
+			pleaseAdjustScrolls = false;
+		 	legend.adjustScrolls();
+		}
+		if (legend!=null)
+			legend.adjustLocation();
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	
+	public void turnOff() {
+		if (treeDisplay!=null && legend!=null)
+			removePanelPlease(legend);
+		super.turnOff();
+	}
+}
+	
+/* ======================================================================== */
+class NodeLocs2DPlotLegend extends TreeDisplayLegend {
+	private NodeLocs2DPlot ownerModule;
+	public MiniScroll xScroll = null;
+	public MiniScroll yScroll = null;
+	private NodeLocs2DPlotExtra pD;
+	private static final int defaultLegendWidth=180;
+	private static final int defaultLegendHeight=220;
+	private int oldX=-1;
+	private int oldMaxX=0;
+	private int oldY=-1;
+	private int oldMaxY=0;
+	public NodeLocs2DPlotLegend(NodeLocs2DPlot ownerModule, NodeLocs2DPlotExtra pD) {
+		super(pD.treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		this.pD = pD;
+		this.ownerModule = ownerModule;
+		setLayout(null);
+		setOffsetX(ownerModule.initialOffsetX);
+		setOffsetY(ownerModule.initialOffsetY);
+		
+		yScroll = new MiniScroll(MesquiteModule.makeCommand("setCurrentY",  ownerModule), false, false, 1, 1, 1,"");
+		add(yScroll);
+		yScroll.setLocation(2,2);
+		yScroll.setColor(Color.blue);
+		
+		xScroll = new MiniScroll(MesquiteModule.makeCommand("setCurrentX",  ownerModule), false, 1, 1, 1,"");
+		add(xScroll);
+		xScroll.setLocation(yScroll.getBounds().x+yScroll.getBounds().width, yScroll.getBounds().height-16);
+		xScroll.setColor(Color.blue);
+
+		setSize(xScroll.getBounds().x+xScroll.getBounds().width+1,xScroll.getBounds().y+xScroll.getBounds().height +8);
+	}
+	
+	public void adjustScrolls() {
+		Incrementable inc = ownerModule.numbersForNodesTask;
+		xScroll.setVisible(true);
+		int max = (int)inc.getMax();
+		if (oldMaxX != max) {
+			xScroll.setMaximumValue(CharacterStates.toExternal(max));
+			oldMaxX = max;
+		}
+		if (oldX != ownerModule.currentX) {
+			xScroll.setCurrentValue(CharacterStates.toExternal(ownerModule.currentX));
+			oldX = ownerModule.currentX;
+		}
+		yScroll.setVisible(true);
+		if (oldMaxY != max) {
+			yScroll.setMaximumValue(CharacterStates.toExternal(max));
+			oldMaxY = max;
+		}
+		if (oldY != ownerModule.currentY) {
+			yScroll.setCurrentValue(CharacterStates.toExternal(ownerModule.currentY));
+			oldY =ownerModule.currentY;
+		}
+		repaint();
+		
+	}
+	boolean doWarn = false;
+	public void addWarning(boolean warn){
+		doWarn = warn;
+	}
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (xScroll !=null)
+			xScroll.setVisible(b);
+		if (yScroll !=null)
+			yScroll.setVisible(b);
+		repaint();
+	}
+	
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		setSize(xScroll.getBounds().x+xScroll.getBounds().width+1,yScroll.getBounds().y+yScroll.getBounds().height +8);
+		Color c = g.getColor();
+		g.setColor(Color.blue);
+		g.drawString("Plot Tree", yScroll.getBounds().x+yScroll.getBounds().width+8, 20);
+		if (doWarn) 
+			g.drawString("MISSING VALUES", yScroll.getBounds().x+yScroll.getBounds().width+8, 36); //added 13 Dec 01
+		g.drawRect(0,0, getBounds().width-1, getBounds().height -1);
+		Rectangle rect = xScroll.getBounds();
+		g.drawString("X", rect.x+ (rect.width)/2, rect.y -1);
+		rect = yScroll.getBounds();
+		g.drawString("Y", rect.x+ rect.width, rect.y + rect.height/2);
+		if (c!=null) g.setColor(c);
+	   	super.paint(g);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	
+}
+
+
diff --git a/Source/mesquite/cont/PlotTree/PlotTree.java b/Source/mesquite/cont/PlotTree/PlotTree.java
new file mode 100644
index 0000000..4cfcb1c
--- /dev/null
+++ b/Source/mesquite/cont/PlotTree/PlotTree.java
@@ -0,0 +1,457 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.PlotTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+//import mesquite.rhetenor.*;
+
+/* ======================================================================== */
+public class PlotTree extends AnalyticalDrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(NodeLocsPlot.class, getName() + " uses a module to plot node locations.",
+		"The method to choose node locations is either chosen automatically or when Plot Tree is first requested.");
+	}
+
+	NodeLocsPlot nodeLocsTask;
+	Vector drawings;
+	int spotSize = 16;
+	public MesquiteBoolean showInternals, showTree, showTerminals;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsPlot)hireEmployee(NodeLocsPlot.class, "Method to choose node locations");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node location plotter module was obtained.");
+		drawings = new Vector();
+ 		addMenuItem( "Spot Size...", makeCommand("setSpotDiameter",  this));
+		showInternals = new MesquiteBoolean(true);
+		showTerminals = new MesquiteBoolean(true);
+		showTree = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Terminal Nodes", makeCommand("toggleShowTerminals",  this), showTerminals);
+		addCheckMenuItem(null, "Show Internal Nodes", makeCommand("toggleShowInternals",  this), showInternals);
+		addCheckMenuItem(null, "Show Branches", makeCommand("toggleShowTree",  this), showTree);
+ 		return true;
+ 	 }
+  	 
+/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+   	 public Dimension getPreferredSize(){
+   	 	if (nodeLocsTask == null)
+   	 		return null;
+   	 		
+   	 	return nodeLocsTask.getPreferredSize();
+   	 }
+ 	/** Returns true if it will have a preferred size of the tree drawing */
+ 	public boolean hasPreferredSize(){
+    	 	if (nodeLocsTask == null)
+    	 		return false;
+ 		return nodeLocsTask.hasPreferredSize();
+ 	}
+ 	public void employeeQuit(MesquiteModule m){
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		PlotTreeDrawing treeDrawing =  new PlotTreeDrawing (treeDisplay, numTaxa, this, spotSize);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setNodeLocs " , nodeLocsTask);
+  	 	temp.addLine("setSpotDiameter " + spotSize);
+  	 	temp.addLine("toggleShowTerminals " + showTerminals.toOffOnString());
+  	 	temp.addLine("toggleShowInternals " + showInternals.toOffOnString());
+   	 	temp.addLine("toggleShowTree " + showTree.toOffOnString());
+ 	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets diameter of spots at nodes", "[diameter]", commandName, "setSpotDiameter")) {
+			int newDiameter = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newDiameter))
+				newDiameter = MesquiteInteger.queryInteger(containerOfModule(), "Set spot diameter", "Spot Diameter:", spotSize, 0, 100);
+    	 			
+    	 		if (newDiameter>-1 && newDiameter<100 && newDiameter!=spotSize) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+		    	 			spotSize = newDiameter;
+		    	 			treeDrawing.spotsize=newDiameter;
+		    	 			treeDrawing.treeDisplay.setMinimumTaxonNameDistance(treeDrawing.spotsize/2, 4);
+		    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 		
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not internal nodes are shown", "[on = show;  off]", commandName, "toggleShowInternals")) {
+    	 		showInternals.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+   	 	else if (checker.compare(this.getClass(), "Sets whether or not terminal nodes are shown", "[on = show;  off]", commandName, "toggleShowTerminals")) {
+    	 		showTerminals.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not the tree is shown", "[on = show;  off]", commandName, "toggleShowTree")) {
+    	 		showTree.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module that calculates the node locations", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsPlot temp= (NodeLocsPlot)replaceEmployee(NodeLocsPlot.class, arguments, "Method choose node locations", nodeLocsTask);
+    	 		if (temp!=null) {
+    	 		 	nodeLocsTask=temp;
+    	 		 	parametersChanged();
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+					treeDrawing.treeDisplay.repaint();
+	    	 		}
+    	 		 }
+	    	 	return temp;
+ 		}
+    	 	else {
+ 			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Plot Tree";
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Draws trees plotted in a two dimensional space." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class PlotTreeDrawing extends TreeDrawing  {
+
+	public PlotTree ownerModule;
+	public int edgewidth = 4;
+	public int spotsize = 24;
+	int oldNumTaxa = 0;
+ 	public static final int inset=1;
+	private boolean ready=false;
+	private int foundBranch;
+	private NameReference colorNameRef;
+	public PlotTreeDrawing (TreeDisplay treeDisplay, int numTaxa, PlotTree ownerModule, int spotSize) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		this.spotsize = spotSize;
+		colorNameRef = NameReference.getNameReference("Color");
+	    	treeDisplay.setMinimumTaxonNameDistance(spotsize/2, 4);
+		treeDisplay.setOrientation(TreeDisplay.FREEFORM);
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		ready = true;
+	}
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[tree.motherOfNode(node)];
+		lineBaseX[node]=x[tree.motherOfNode(node)];
+	}
+	
+	private int getSpotSize(int node){
+			return spotsize;
+	}
+	
+	/*_________________________________________________*/
+	/** Draw highlight for branch node */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			Color tC = g.getColor();
+			if (flip)
+				g.setColor(Color.red);
+			else
+				g.setColor(Color.blue);
+			int s = getSpotSize(node);
+			for (int i=1; i<4; i++)
+				g.drawOval( x[node]- s/2 - 2 - i, y[node]- s/2 - 2 - i, s + 3 + i + i, s + 3 + i + i);
+
+			g.setColor(tC);
+		}
+	}
+	/*_________________________________________________*/
+	private   void drawLines(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(treeDisplay.getBranchColor(node));
+			Composite composite = 	treeDisplay.setBranchTransparency(g, node);
+	
+			if (node == tree.getRoot()) {
+			}
+			else if (tree.motherOfNode(node) == tree.getRoot() && !tree.getRooted() && !tree.nodeIsPolytomous( tree.getRoot() )) {
+				int sisterNode = 0;
+				if (tree.nodeExists(tree.nextSisterOfNode(node)))
+					sisterNode = tree.nextSisterOfNode(node);
+				else if (tree.nodeExists(tree.previousSisterOfNode(node)))
+					sisterNode = tree.previousSisterOfNode(node);
+				if (sisterNode !=0) {
+					if (MesquiteInteger.isCombinable(lineTipX[node]) && MesquiteInteger.isCombinable(lineTipY[node]) && MesquiteInteger.isCombinable(lineTipX[sisterNode]) && MesquiteInteger.isCombinable(lineTipY[sisterNode])) {
+						g.drawLine(lineTipX[node]+1, lineTipY[node], lineTipX[sisterNode]+1, lineTipY[sisterNode]);
+						g.drawLine(lineTipX[node], lineTipY[node], lineTipX[sisterNode], lineTipY[sisterNode]);
+						g.drawLine(lineTipX[node], lineTipY[node]+1, lineTipX[sisterNode], lineTipY[sisterNode]+1);
+						g.drawLine(lineTipX[node]+1, lineTipY[node]+1, lineTipX[sisterNode]+1, lineTipY[sisterNode]+1);
+					}
+				}
+			}
+			else  if (MesquiteInteger.isCombinable(lineTipX[node]) && MesquiteInteger.isCombinable(lineBaseX[node]) && MesquiteInteger.isCombinable(lineTipY[node]) && MesquiteInteger.isCombinable(lineBaseY[node])) {
+				g.drawLine(lineTipX[node]+1, lineTipY[node], lineBaseX[node]+1, lineBaseY[node]);
+				g.drawLine(lineTipX[node], lineTipY[node], lineBaseX[node], lineBaseY[node]);
+				g.drawLine(lineTipX[node], lineTipY[node]+1, lineBaseX[node], lineBaseY[node]+1);
+				g.drawLine(lineTipX[node]+1, lineTipY[node]+1, lineBaseX[node]+1, lineBaseY[node]+1);
+			}
+			
+			if (composite!=null)
+				ColorDistribution.setComposite(g, composite);
+			
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawLines( tree, g, thisSister);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private boolean getDrawNode(Tree tree, int node) {
+		return (tree.nodeIsTerminal(node) && ownerModule.showTerminals.getValue())|| (!tree.nodeIsTerminal(node) && ownerModule.showInternals.getValue());
+	}
+	
+	/*_________________________________________________*/
+	private   void drawSpots(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(treeDisplay.getBranchColor(node));
+			Composite composite = 	treeDisplay.setBranchTransparency(g, node);
+			if (getDrawNode(tree,node)){
+				if (node == tree.getRoot()) {
+					if (tree.getRooted()) {
+						drawSpot( g, node);
+						highlightSpot( g, node);
+					}
+				}
+				else  {
+					drawSpot( g, node);
+				}
+			}
+			if (composite!=null)
+				ColorDistribution.setComposite(g, composite);
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawSpots( tree, g, thisSister);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+		}
+	}
+	private int bumpUp(int i){
+		return i + (255-i)/4;
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+	        if (MesquiteTree.OK(tree)) {
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	g.setColor(treeDisplay.branchColor);
+			calculateLines(tree, drawnRoot);
+	       	 	if (ownerModule.showTree.getValue())
+	       	 		drawLines(tree, g, drawnRoot);  
+	       	 	drawSpots(tree, g, drawnRoot);  
+	       	 }
+	   }
+	
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+	        if (MesquiteTree.OK(tree) && !ownerModule.isDoomed()) {
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	if (!tree.nodeExists(getDrawnRoot()))
+	        		setDrawnRoot(tree.getRoot());
+			ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, getDrawnRoot(),  treeDisplay.getField()); 
+		}
+	}
+	/*_________________________________________________*/
+	private boolean inSpot(int node, int h, int v){
+		int s = getSpotSize(node);
+		if (h> x[node]+s || h < x[node] - s || v > y[node]+s || v < y[node]-s) //first test: within bounding box?
+			return false;
+		if ((h-x[node])*(h-x[node]) + (v-y[node])*(v-y[node]) < s*s/4) //use radius
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void drawSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			int s = getSpotSize(node);
+			g.fillOval( x[node]- s/2, y[node]- s/2, s, s);
+		}
+	}
+	/*_________________________________________________*/
+	private void highlightSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			int s = getSpotSize(node);
+			for (int diam = s + 12; diam> s + 8; diam --)
+				g.drawOval( x[node]- (int)((double)diam/2 + 0.5), y[node]- (int)((double)diam/2 + 0.5), diam, diam);
+		}
+	}
+	/*_________________________________________________*/
+	private void fillSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			int s = getSpotSize(node);
+			g.fillOval( x[node]- s/2 + 2, y[node]- s/2 + 2, s - 4, s - 4);
+		}
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && (getDrawNode(tree,node))) {
+			if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+				Color c = g.getColor();
+				int numColors = colors.getNumColors();
+				if (numColors==1){
+					g.setColor(colors.getColor(0, !tree.anySelected()|| tree.getSelected(node)));
+					fillSpot(g,node);
+				}
+				else if (numColors>0) {
+					int startAngle=90;
+					double totalFreq=0;
+					for (int i=0; i<numColors; i++) totalFreq += colors.getWeight(i);
+					
+					int arcAngle = 360/(numColors);
+					int s = getSpotSize(node);
+					for (int i=0; i<numColors; i++) {
+						Color color;
+						if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+							g.setColor(color);
+						
+						arcAngle = (int)((colors.getWeight(i)/totalFreq)*360);
+						g.fillArc( x[node]- s/2 + 2, y[node]- s/2 + 2, s - 4, s - 4, startAngle, arcAngle);
+						startAngle+=arcAngle;
+					}
+				}
+				if (c!=null) g.setColor(c);
+			}
+		}
+	}
+
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || node != tree.getRoot()) && (getDrawNode(tree,node))) {
+			fillSpot(g,node);
+		}
+	}
+	   
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y)
+	{
+		if (foundBranch==0) {
+			if ( inSpot(node, x, y))
+				foundBranch = node;
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				ScanBranches(tree, thisSister, x, y);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+	        if (MesquiteTree.OK(tree) && ready) {
+	        	foundBranch=0;
+	       		 ScanBranches(tree, drawnRoot, x, y);
+	       		 return foundBranch;
+	       	}
+	       	return 0;
+	}
+	
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+	}
+/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+/*End new code Feb.22.07 oliver*/
+}
+	
+
+
diff --git a/Source/mesquite/cont/RandomFillCont/RandomFillCont.java b/Source/mesquite/cont/RandomFillCont/RandomFillCont.java
new file mode 100644
index 0000000..21f5160
--- /dev/null
+++ b/Source/mesquite/cont/RandomFillCont/RandomFillCont.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.RandomFillCont;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+//import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class RandomFillCont extends ContDataAlterer {
+	CharacterState fillState;
+	Random rng;
+	MesquiteDouble mean;
+	MesquiteDouble variance;
+	double standardDeviation;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random();
+		rng.setSeed(System.currentTimeMillis());
+		mean = new MesquiteDouble(0.0);
+		variance = new MesquiteDouble(1.0);
+		standardDeviation = 1.0;
+		return true;
+	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			
+   			boolean did=false;
+			if (!(data instanceof ContinuousData))
+				return false;
+			MesquiteBoolean answer = new MesquiteBoolean(true);
+			MesquiteDouble.queryTwoDoubles(containerOfModule(), "Random fill", "Mean of filled states", "Variance of filled states", answer, mean, variance);
+			if (!answer.getValue() && variance.getValue()>=0 && (variance.isCombinable()))
+				return false;
+			standardDeviation = Math.sqrt(variance.getValue());
+			ContinuousData cData = (ContinuousData)data;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData data, int ic, int it){
+   		((ContinuousData)data).setState(ic,it, 0, standardDeviation*rng.nextGaussian()+ mean.getValue());
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Random Fill (Gaussian/Normal)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Fills cells with a random state, using a Normal distribution." ;
+   	 }
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/RandomFillUniform/RandomFillUniform.java b/Source/mesquite/cont/RandomFillUniform/RandomFillUniform.java
new file mode 100644
index 0000000..b411e3f
--- /dev/null
+++ b/Source/mesquite/cont/RandomFillUniform/RandomFillUniform.java
@@ -0,0 +1,89 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.RandomFillUniform;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+//import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class RandomFillUniform extends ContDataAlterer {
+	CharacterState fillState;
+	Random rng;
+	MesquiteDouble max;
+	MesquiteDouble min;
+	double standardDeviation;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random();
+		rng.setSeed(System.currentTimeMillis());
+		min = new MesquiteDouble(0.0);
+		max = new MesquiteDouble(1.0);
+		return true;
+	}
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+
+		boolean did=false;
+		if (!(data instanceof ContinuousData))
+			return false;
+		MesquiteBoolean answer = new MesquiteBoolean(true);
+		MesquiteDouble.queryTwoDoubles(containerOfModule(), "Random fill (Uniform)", "Minimum of filled states", "Maximum of filled states", answer, min, max);
+		if (!answer.getValue() && min.isCombinable() && (max.isCombinable()) && max.getValue()>=min.getValue())
+			return false;
+		ContinuousData cData = (ContinuousData)data;
+		return alterContentOfCells(data,table, undoReference);
+	}
+
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData data, int ic, int it){
+		((ContinuousData)data).setState(ic,it, 0, rng.nextDouble()*(max.getValue() - min.getValue())+ min.getValue());
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Random Fill (Uniform)";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Random Fill (Uniform)...";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Fills cells with a random state, uniformly." ;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/cont/RemoveItem/RemoveItem.java b/Source/mesquite/cont/RemoveItem/RemoveItem.java
new file mode 100644
index 0000000..569b069
--- /dev/null
+++ b/Source/mesquite/cont/RemoveItem/RemoveItem.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.RemoveItem;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class RemoveItem extends ContDataUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in all cells*/
+   	public boolean operateOnData(CharacterData data){
+			if (!(data instanceof ContinuousData))
+				return false;
+			ContinuousData cData = (ContinuousData)data;
+			int numItems = cData.getNumItems();
+			if (numItems<=1){
+				discreetAlert("An item cannot be removed from the matrix when there is only a single item");
+				return false;
+			}
+			String[] items = new String[numItems];
+			for (int i=0; i<items.length; i++){
+				items[i]= cData.getItemName(i);
+			}
+			int d = ListDialog.queryList(containerOfModule(), "Remove item", "Remove item:", MesquiteString.helpString, items, 0);
+			if (!MesquiteInteger.isCombinable(d) || d<0 || d>=numItems)
+				return false;
+			else {
+				cData.removeItem(d);
+				return true;
+			}
+   	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Remove item...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Removes an item in each cell of a continuous matrix." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/RenameItem/RenameItem.java b/Source/mesquite/cont/RenameItem/RenameItem.java
new file mode 100644
index 0000000..018061b
--- /dev/null
+++ b/Source/mesquite/cont/RenameItem/RenameItem.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.RenameItem;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class RenameItem extends ContDataUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in all cells*/
+   	public boolean operateOnData(CharacterData data){
+			if (!(data instanceof ContinuousData))
+				return false;
+			ContinuousData cData = (ContinuousData)data;
+			int numItems =cData.getNumItems();
+			String[] items = new String[numItems];
+			for (int i=0; i<items.length; i++){
+				if (StringUtil.blank(cData.getItemName(i)))
+					items[i] = "(unnamed)";
+				else
+					items[i]= cData.getItemName(i);
+			}
+			int d = ListDialog.queryList(containerOfModule(), "Rename item", "Rename item:", MesquiteString.helpString, items, 0);
+			if (!MesquiteInteger.isCombinable(d) || d<0 || d>=numItems)
+				return false;
+			else {
+				String s = MesquiteString.queryString(containerOfModule(), "Rename Item", "New name for " + items[d], items[d]);
+				if (StringUtil.blank(s))
+					return false;
+				cData.setItemReference(d, NameReference.getNameReference(s));
+				return true;
+			}
+   	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Rename item...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Renames an item of a continuous matrix." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/SquareRootTransform/SquareRootTransform.java b/Source/mesquite/cont/SquareRootTransform/SquareRootTransform.java
new file mode 100644
index 0000000..ef36fa7
--- /dev/null
+++ b/Source/mesquite/cont/SquareRootTransform/SquareRootTransform.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.SquareRootTransform;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class SquareRootTransform extends ContDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+			if (!(data instanceof ContinuousData))
+				return false;
+			return alterContentOfCells(data,table, undoReference);
+   	}
+
+   	
+   	boolean firstTime = true;
+   	
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		ContinuousData data = ((ContinuousData)ddata);
+		for (int item = 0; item<data.getNumItems(); item++){
+			double state = data.getState(ic,it, item);
+			if (MesquiteDouble.isCombinable(state)) {
+				if (state<0) {
+					if (firstTime)
+						discreetAlert( "Some values could not be transformed by square root because they were  negative");
+					firstTime = false;
+				}
+				else
+					data.setState(ic,it, item, Math.sqrt(state));
+			}
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Square Root transform";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by taking the square root." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/cont/Standardize/Standardize.java b/Source/mesquite/cont/Standardize/Standardize.java
new file mode 100644
index 0000000..ab5bf06
--- /dev/null
+++ b/Source/mesquite/cont/Standardize/Standardize.java
@@ -0,0 +1,138 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.Standardize;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.table.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class Standardize extends ContDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+   		boolean did=false;
+   		if (!(data instanceof ContinuousData))
+   			return false;
+   		ContinuousData cData = (ContinuousData)data;
+   		if (data !=null){
+   			UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+   			boolean sample = (AlertDialog.query(containerOfModule(), "Standardize", "Do you want to treat the taxa as a sample (i.e. use standard deviation calculated with /(n-1)) or a population (i.e., use /n)?", "Sample (n-1)", "Population (n)"));
+   			double sum;
+   			for (int i=0; i<cData.getNumChars(); i++) {
+   				sum = 0;
+   				int n = 0;
+   				for (int j=0; j<cData.getNumTaxa(); j++) {
+   					if (shouldIDoIt(i,j, table)){
+   						double s = cData.getState(i,j,0);
+   						if (MesquiteDouble.isCombinable(s)) {
+   							sum+= s;
+   							n++;
+   						}
+   					}
+   				}
+   				int nUsedForSD = n-1;
+   				if (!sample)
+   					nUsedForSD = n;
+   				if (n>1){
+   					double mean = sum/n;
+   					sum = 0;
+   					for (int j=0; j<cData.getNumTaxa(); j++) {
+   						if (shouldIDoIt(i,j, table)){
+   							double s = cData.getState(i,j,0);
+   							did = true;
+   							if (MesquiteDouble.isCombinable(s)) {
+   								sum+= (mean-s)*(mean-s);
+   							}
+   						}
+   					}
+   					double v = Math.sqrt(sum/nUsedForSD); //std dev
+   					if (v>0){
+   						for (int j=0; j<cData.getNumTaxa(); j++) {
+   							if (shouldIDoIt(i,j, table)){
+   								double s = cData.getState(i,j,0);
+   								if (MesquiteDouble.isCombinable(s))
+   									cData.setState(i,j, 0, (s-mean)/v);
+   							}
+   						}
+   					}
+   					else //no variance; just subtract mean, which should yield 0!
+   						for (int j=0; j<cData.getNumTaxa(); j++) {
+   							if (shouldIDoIt(i,j, table)){
+   								double s = cData.getState(i,j,0);
+   								if (MesquiteDouble.isCombinable(s))
+   									cData.setState(i,j, 0, (s-mean));
+   							}
+   						}
+
+
+
+
+   				}
+   			}
+   			if (undoInstructions!=null) {
+   				undoInstructions.setNewData(data);
+   				if (undoReference!=null){
+   					undoReference.setUndoer(undoInstructions);
+   					undoReference.setResponsibleModule(this);
+   				}
+   			}
+  		}
+   		return did;
+   	}
+
+   	boolean shouldIDoIt(int ic, int it, MesquiteTable table){
+   		if (table==null)
+   			return true;
+   		if (table.isColumnSelected(ic) || table.isCellSelected(ic, it) || !table.anythingSelected())
+   			return true;
+   		return false;
+   	}
+	
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Standardize";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters continuous data by standardizing to have mean = 0 and unbiased estimate of variance = 1.  Modifies only the first item of a multi-item matrix" ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/cont/XYMatrixToItems/XYMatrixToItems.java b/Source/mesquite/cont/XYMatrixToItems/XYMatrixToItems.java
new file mode 100644
index 0000000..190a237
--- /dev/null
+++ b/Source/mesquite/cont/XYMatrixToItems/XYMatrixToItems.java
@@ -0,0 +1,157 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.XYMatrixToItems;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class XYMatrixToItems extends CharMatrixSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.charMatrices.StoredMatrices.StoredMatrices.class, getName() + "  needs a source of continuous matrices.",
+		"The source of continuous matrices is arranged initially");
+	}
+	CharMatrixSource dataTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		
+		dataTask = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, "#StoredMatrices", ContinuousState.class);
+		if (dataTask == null) {
+			return sorry(getName() + " can't be started because no source of matrices was obtained");
+		}
+		return true; 
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CharacterStateTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", dataTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource")) {
+			return dataTask;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		//return null;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		dataTask.initialize(taxa);
+	}
+	NameReference xRef = NameReference.getNameReference("x");
+	NameReference yRef = NameReference.getNameReference("y");
+
+	private MCharactersDistribution translate(MCharactersDistribution mData){
+		if (mData != null && mData.getParentData() != null){
+			CharacterData data = mData.getParentData();
+			if (data instanceof ContinuousData){
+				ContinuousData dData = (ContinuousData)data;
+				if (dData.getNumItems()>1){
+					discreetAlert("Source matrix has multiple items; to convert to XY Items, the cells in the source need to each have a single item");
+					return null;
+				}
+				int numChars = dData.getNumChars();
+				MContinuousAdjustable xyMatrix = new MContinuousAdjustable (data.getTaxa(), numChars/2, data.getNumTaxa());
+				Double2DArray xMatrix = xyMatrix.establishItem(xRef);
+				Double2DArray yMatrix = xyMatrix.establishItem(yRef);
+				for (int ic = 0; ic< numChars; ic+=2){
+					int icXY = ic/2;
+					for (int it = 0; it < dData.getNumTaxa(); it++){
+						double stateX = dData.getState(ic, it, 0);
+						double stateY = dData.getState(ic+1, it, 0);
+						xMatrix.setValue(icXY, it, stateX);
+						yMatrix.setValue(icXY, it, stateY);
+
+					}
+				}
+				return xyMatrix;
+			}
+		}
+		return null;
+		
+	}
+	
+	/** returns the number of character matrices that can be supplied for the given taxa*/
+	public int getNumberOfMatrices(Taxa taxa){
+		return dataTask.getNumberOfMatrices(taxa);
+	}
+	/** gets the current matrix.*/
+	public  MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		MCharactersDistribution orig = dataTask.getCurrentMatrix(taxa);
+		MCharactersDistribution xy = translate(orig);
+		if (xy != null)
+			xy.setName("XY compaction of " + orig.getName());
+		return xy;
+	}
+	/** gets the indicated matrix.*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+		MCharactersDistribution orig = dataTask.getMatrix(taxa, im);
+		MCharactersDistribution xy = translate(orig);
+		if (xy != null)
+			xy.setName("XY compaction of " + orig.getName());
+		return xy;
+	}
+	/** gets name of the indicated matrix.*/
+	public  String getMatrixName(Taxa taxa, int im){
+		return "XY compaction of " + dataTask.getMatrixName(taxa, im);
+	}
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return dataTask.getNumberCurrentMatrix();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Compact to (X,Y) matrix";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts a matrix of alternating X and Y columns (e.g. for landmarks) to a matrix each cell of which has X,Y values." ;
+	}
+	
+}
+
diff --git a/Source/mesquite/cont/aContIntro/aContIntro.java b/Source/mesquite/cont/aContIntro/aContIntro.java
new file mode 100644
index 0000000..762a951
--- /dev/null
+++ b/Source/mesquite/cont/aContIntro/aContIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.aContIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aContIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aContIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic facilities for handling continuous-valued characters.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Continuous Data Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Continuous Data Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/cont/explanation.txt b/Source/mesquite/cont/explanation.txt
new file mode 100644
index 0000000..b35363f
--- /dev/null
+++ b/Source/mesquite/cont/explanation.txt
@@ -0,0 +1,2 @@
+Continuous Character Package
+One of the core Mesquite packages.  A package of fundamental modules and libraries for continuous-valued character data.  These define key elements of continuous data and manage continuous data matrices.  Also provides the 2-dimensional Plot Tree routine for drawing trees.
diff --git a/Source/mesquite/cont/lib/BasicStatPak.java b/Source/mesquite/cont/lib/BasicStatPak.java
new file mode 100644
index 0000000..b53cdea
--- /dev/null
+++ b/Source/mesquite/cont/lib/BasicStatPak.java
@@ -0,0 +1,484 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+This file copyright 2006 P. Midford and W. Maddison
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import JSci.maths.statistics.TDistribution;
+import mesquite.lib.MesquiteDouble;
+
+public class BasicStatPak {
+
+	private int n;
+	private int n1;
+	private int n2;
+	private double min[];
+	private double max[];
+	private double sx;
+	private double sx2;
+	private double sy;
+	private double sy2;
+	private double sxy;
+	private TDistribution tDist;
+	private boolean ordinalStats = false;
+	private boolean parametricStats = false;
+	private double[] x;
+	private double[] y;
+	
+	/**
+	 * creates a StatPak for the values x and y
+	 * @param x data values for independent variable
+	 * @param y data values for dependent variable
+	 */
+	public BasicStatPak(double[] x, double[]y) {
+		super();
+		this.x = x;
+		this.y = y;
+	}
+
+	/**
+	 * 
+	 * @return sample size (number of points) or -1 if x and y have different numbers of values
+	 */
+	public int n(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return n;
+	}
+	
+	/**
+	 * 
+	 * @return sample size for independent variable (x)
+	 */
+	public int n1(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return n1;
+	}
+
+	/**
+	 * 
+	 * @return sample size for dependent variable (y)
+	 */
+	public int n2(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return n2;
+	}
+	
+	/**
+	 * 
+	 * @return largest value in x
+	 */
+	public double maxX(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return max[0];
+	}
+
+	/**
+	 * 
+	 * @return largest value in y
+	 */
+	public double maxY(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return max[1];
+	}
+
+	/**
+	 * 
+	 * @return smallest value in x
+	 */
+	public double minX(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return min[0];
+	}
+
+	/**
+	 * 
+	 * @return smallest value in y
+	 */
+	public double minY(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		return min[1];
+	}
+	
+	/**
+	 * 
+	 * @return mean of x, or unassigned if x is empty
+	 */
+	public double meanX(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 < 1)
+			return MesquiteDouble.unassigned;
+		else
+			return sx/n1;
+	}
+
+	/**
+	 * 
+	 * @return mean of y, or unassigned if y is empty
+	 */
+	public double meanY(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n2 < 1)
+			return MesquiteDouble.unassigned;
+		else
+			return sy/n2;
+	}
+
+	/**
+	 * 
+	 * @return variance of x (n-1 weighted), or unassigned if x has less than two values
+	 */
+	public double variance1(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 < 2)
+			return MesquiteDouble.unassigned;
+		else
+			return ((sx2-(sx*sx/n1))/(n1-1));
+	}
+
+	
+	/**
+	 * 
+	 * @return variance of y (n-1 weighted), or unassigned if y has less than two values 
+	 */
+	public double variance2(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n2 < 2)
+			return MesquiteDouble.unassigned;
+		else
+			return (sy2-(sy*sy/n2))/(n2-1);
+	}
+
+	/**
+	 * 
+	 * @return covariance of x and y, or unassigned if x and y have different numbers of values
+	 */
+	public double covariance(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2)
+			return MesquiteDouble.unassigned;
+		else
+			return (sxy-(sx*sy/n));
+	}
+
+	/**
+	 * 
+	 * @return pearson correlation of x and y
+	 */
+	public double correlation(){
+		double cov = covariance();
+		if (!MesquiteDouble.isCombinable(cov))
+			return MesquiteDouble.unassigned;
+		else	{
+			double s12= sx2-(sx*sx/n);
+			double s22= sy2-(sy*sy/n);
+			return cov/Math.sqrt(s12*s22);
+		}
+	}
+	
+	/**
+	 * 
+	 * @return the slope of a least squares regression
+	 */
+	public double slope(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 1)
+			return MesquiteDouble.unassigned;
+		else		
+			return (sxy-(sx*sy/n))/(sx2-(sx*sx/n));
+	}
+	
+	/**
+	 * 
+	 * @return the y-intercept of a least squares regression
+	 */
+	public double intercept(){
+		double slope = slope();
+		if (!MesquiteDouble.isCombinable(slope))
+			return MesquiteDouble.unassigned;
+		else		
+			return meanY()-slope*meanX();
+	}
+	
+	
+	/**
+	 * 
+	 * @return the t-statistic (sqrt(F1,n-2)) for the significance of the regression
+	 */
+	public double regressionT(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 1)
+			return MesquiteDouble.unassigned;
+		double regSlope = slope();
+		double regIntercept = intercept();
+		double yhat2 = 0;
+		for(int i=0;i<n;i++){
+			double yhat = regSlope*x[i] + regIntercept;
+			yhat2 += yhat*yhat;
+		}
+		double s2YX = (sy2-yhat2)/(n-2);
+		double seSlope = Math.sqrt(s2YX/(sx2-(sx*sx/n)));
+		return regSlope/seSlope;
+	}
+	
+	/**
+	 * 
+	 * @return significance value for the regression, based on t-statistic above
+	 */
+	public double regressionPValue(){
+ 		double stat = regressionT();
+ 		if (!MesquiteDouble.isCombinable(stat))
+ 			return MesquiteDouble.unassigned;
+ 		tDist = new TDistribution(n-2);
+		double cumulative = tDist.cumulative(stat);
+		if (cumulative > 0.5)
+			return 1-cumulative;
+		else return cumulative;
+
+	}
+	
+	
+	/**
+	 * 
+	 * @return the slope of a least-squares regression through the origin (intercept = 0)
+	 */
+	public double slopeOrg(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 1)
+			return MesquiteDouble.unassigned;	
+		return sxy/sx2;
+	}
+	
+	/**
+	 * 
+	 * @return the major axis (principal component) slope
+	 */
+	public double maSlope(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 1)
+			return MesquiteDouble.unassigned;	
+		double v1 = (sx2-(sx*sx/n1))/(n-1);
+		double v2 = (sy2-(sy*sy/n2))/(n-1);
+		double cov = covariance()/(n-1);
+		double d = Math.sqrt(((v1+v2)*(v1+v2)) - 4*(v1*v2-cov*cov));
+		double lambda1 = (v1+v2+d)/2;
+		
+		// Sokal and Rolf 1981 set Y1 for vertical axis, for example on 595-596.
+		if (lambda1 == v1) {
+			if (cov >0)
+				return MesquiteDouble.infinite;
+			else return MesquiteDouble.negInfinite;
+		}
+		else return cov/(lambda1-v1);
+		
+	}
+	
+	/**
+	 * 
+	 * @return y-intercept corresponding to the major axis slope
+	 */
+	public double maIntercept(){
+		double slope = maSlope();
+		if (!MesquiteDouble.isCombinable(slope))
+			return MesquiteDouble.unassigned;
+   		return meanY()-slope*meanX();
+
+	}
+	
+	
+	/**
+	 * 
+	 * @return the reduced major axis slope
+	 */
+	public double rmaSlope(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 1)
+			return MesquiteDouble.unassigned;
+		double v1 = variance1();
+		double v2 = variance2();
+		if (MesquiteDouble.isCombinable(v1) && v1>0) 
+			if (sxy >0) // make sure the sign of the reduced major axis slope agrees with 
+				return Math.sqrt(v2/v1);
+			else return -1*Math.sqrt(v2/v1);
+		else
+			return MesquiteDouble.unassigned;
+	}
+	
+	/**
+	 * 
+	 * @return y-intercept corresponding to the reduced major axis slope
+	 */
+	public double rmaIntercept(){
+		double slope = rmaSlope();
+		if (!MesquiteDouble.isCombinable(slope))
+			return MesquiteDouble.unassigned;
+		else return meanY()-slope*meanX();
+	}
+	
+	/**
+	 * 
+	 * @return the t-statistic comparing x and y as paired values
+	 */
+	public double pairedTStat(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 != n2  || n < 2)
+			return MesquiteDouble.unassigned;
+ 		double diff;
+ 		double diffSum = 0;
+ 		double diffSumSq = 0;
+ 		for(int i=0;i<n;i++){
+ 			diff = x[i]-y[i];
+ 			diffSum += diff;
+ 			diffSumSq += diff*diff;
+ 		}
+ 		double diffMean = diffSum/n;
+ 		double diffS2 = (diffSumSq-(diffSum*diffSum/n))/(n-1);
+ 		double diffErr = Math.sqrt(diffS2)/Math.sqrt(n);
+ 		double result = diffMean/diffErr;
+ 		return result;
+	}
+
+	/**
+	 * 
+	 * @return the p-value for a t-test comparing x and y as unpaired values
+	 */
+	public double pairedTPvalue(){
+ 		double stat = pairedTStat();
+ 		if (stat == MesquiteDouble.unassigned)
+ 			return stat;
+ 		tDist = new TDistribution(n-1);
+		double cumulative = tDist.cumulative(stat);
+		if (cumulative > 0.5)
+			return 1-cumulative;
+		else return cumulative;
+	}
+	
+	
+	/**
+	 * 
+	 * @return the t-statistic comparing x and y as unpaired values
+	 */
+	public double unPairedTStat(){
+		if (!parametricStats)
+			doParametricStats();
+		if (n1 < 2 || n2 < 2)
+			return MesquiteDouble.unassigned;
+		double pooledS = Math.sqrt(((n1-1)*variance1() + (n2-1)*variance2())/(n1+n2-2));
+		return (meanX()-meanY())/(pooledS*Math.sqrt(1/(double)n1 + 1/(double)n2));
+	}
+	
+	/**
+	 * 
+	 * @return the p-value for a t-test comparing x and y as unpaired values
+	 */
+	public double unPairedTPvalue(){
+		double stat = unPairedTStat();
+		if (stat == MesquiteDouble.unassigned)
+			return stat;
+		tDist = new TDistribution(n-2);
+		double cumulative = tDist.cumulative(stat);
+		if (cumulative > 0.5)
+			return 1-cumulative;
+		else return cumulative;
+	}
+	
+	
+	private void doOrdinalStats(){
+		ordinalStats = true;
+		max = new double[2];
+		min = new double[2];
+		max[0]=MesquiteDouble.negInfinite;
+		max[1]=MesquiteDouble.negInfinite;
+		min[0]=MesquiteDouble.infinite;
+		min[1]=MesquiteDouble.infinite;
+		if (x != null){
+			for(n1=0;n1<x.length;n1++){
+				if (x[n1]==MesquiteDouble.unassigned)
+					break;
+				double curX = x[n1];
+				if (max[0]< curX)
+					max[0] = curX;
+				if (min[0] > curX)
+					min[0] = curX;
+			}
+		}
+		if (y != null){
+			for(n2=0;n2<y.length;n2++){
+				if (y[n2]==MesquiteDouble.unassigned)
+					break;
+				double curY = y[n2];
+				if (max[1]< curY)
+					max[1] = curY;
+				if (min[1] > curY)
+					min[1] = curY;
+			}
+		}
+		if (n1 == n2)
+			n = n1;
+		else
+			n = -1;
+	}
+	
+	private void doParametricStats(){
+		if (!ordinalStats)
+			doOrdinalStats();
+		parametricStats = true;
+		sx = 0;
+		sx2 = 0;
+		sy = 0;
+		sy2 = 0;
+		sxy = 0;
+		if (x != null){
+			for (int i=0;i<n1;i++){
+				double curX = x[i];
+				sx += curX;
+				sx2 += curX*curX;
+				if (y != null) {
+					if (i< n2){
+						double curY = y[i];
+						sy += curY;
+						sy2 += curY*curY;
+						sxy += curX*curY;
+					}
+				}
+			}
+		}
+		if (y != null && n2> n1){
+			for (int i=n1;i<n2;i++){
+				double curY = y[i];
+				sy += curY;
+				sy2 += curY*curY;
+			}
+		}
+	}
+	
+	
+}
diff --git a/Source/mesquite/cont/lib/ContColorTable.java b/Source/mesquite/cont/lib/ContColorTable.java
new file mode 100644
index 0000000..debfcd7
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContColorTable.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+public class ContColorTable extends MesquiteColorTable  {
+   public ContColorTable(){
+	   super();
+	   setMode(COLORS_NO_BW);
+   }
+	/**resets to default mode*/
+	public void resetDefaultMode(){
+		   setMode(COLORS_NO_BW);
+	}
+
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContDataAlterer.java b/Source/mesquite/cont/lib/ContDataAlterer.java
new file mode 100644
index 0000000..c29ff64
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContDataAlterer.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class ContDataAlterer extends DataAlterer  {
+   	 public Class getDutyClass() {
+   	 	return ContDataAlterer.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new ContinuousStateTest();
+	}
+
+}
+
diff --git a/Source/mesquite/cont/lib/ContDataSearcher.java b/Source/mesquite/cont/lib/ContDataSearcher.java
new file mode 100644
index 0000000..70bc52b
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContDataSearcher.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class ContDataSearcher extends DataSearcher  {
+   	 public Class getDutyClass() {
+   	 	return ContDataSearcher.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new ContinuousStateTest();
+	}
+
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContDataUtility.java b/Source/mesquite/cont/lib/ContDataUtility.java
new file mode 100644
index 0000000..99b5329
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContDataUtility.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class ContDataUtility extends DataUtility  {
+   	 public Class getDutyClass() {
+   	 	return ContDataUtility.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new ContinuousStateTest();
+	}
+
+}
+
diff --git a/Source/mesquite/cont/lib/ContinuousAdjustable.java b/Source/mesquite/cont/lib/ContinuousAdjustable.java
new file mode 100644
index 0000000..f8f4a2e
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousAdjustable.java
@@ -0,0 +1,288 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes */
+public class ContinuousAdjustable  extends ContinuousDistribution implements AdjustableDistribution {
+	protected DoubleArray firstItem; //other dimension for items (sample size, variance, etc., etc.)
+	protected Vector items;
+	protected int numNodes;
+	
+	public ContinuousAdjustable (Taxa taxa, int numNodes) {
+		super(taxa);
+		items = new Vector();
+		this.numNodes= numNodes;
+		firstItem = new DoubleArray(numNodes); 
+		items.addElement(firstItem);
+		deassignStates();
+	}
+	
+	/*..........................................ContinuousAdjustable................*/
+	public int getNumItems() {
+		return items.size();
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public int getNumTaxa() {
+		return numNodes;
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public int getNumNodes() {
+		return numNodes;
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	/* makes new item*/
+	public DoubleArray addItem(NameReference nr){
+			DoubleArray item = new DoubleArray(numNodes);
+			if (firstItem == null)
+				firstItem = item; 
+			if (nr!=null)
+				item.setNameReference(nr);
+			for (int it=0; it<numNodes; it++)
+					item.setValue(it, ContinuousState.unassigned);
+			items.addElement(item);
+			return item;
+	}
+	
+	/*.........................................ContinuousAdjustable...............*/
+	public DoubleArray establishItem(String name){
+		return establishItem(NameReference.getNameReference(name));
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public DoubleArray establishItem(NameReference nr){
+		if (firstItem != null && firstItem.getNameReference()==null && items.size() ==1) {
+			if (nr!=null)
+				firstItem.setNameReference(nr);
+			return firstItem;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				DoubleArray matrix = (DoubleArray)items.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(nr);
+					return matrix;
+				}
+			}
+			return addItem(nr);
+		}
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public DoubleArray addItem(String name){
+		return addItem(NameReference.getNameReference(name));
+	}
+	/*..........................................ContinuousStates................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+
+	}
+	/*..........................................ContinuousData................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		DoubleArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		items.removeElement(matrix);
+		if (item == 0) {
+			firstItem = (DoubleArray)items.elementAt(0);
+		}
+	}
+	/*..........................................ContinuousStates................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+			DoubleArray matrix =getItem(index);
+			matrix.setNameReference(nr);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public void setItems(ContinuousAdjustable s){
+		if (s==null)
+			setItems((String[])null);
+		else {
+			String[] names = new String[s.getNumItems()];
+			for (int i=0; i<s.getNumItems(); i++) {
+				NameReference nr = s.getItemReference(i);
+				if (nr==null)
+					names[i] = null;
+				else
+					names[i] = nr.getValue();
+			}
+			setItems(names);
+		}
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public void setItems(String[] names){
+		if (names == null) { //setting to a single item with null name
+			if (getNumItems() == 0) {
+				addItem((NameReference)null);
+			}
+			else if (getNumItems() == 1)
+				firstItem.setNameReference(null);
+			else {
+				items.removeAllElements();
+				firstItem = null;
+				establishItem((NameReference)null);
+			}
+		}
+		else {
+			if (getNumItems() == names.length) {
+				for (int i=0; i<getNumItems(); i++) {
+					DoubleArray item = (DoubleArray)items.elementAt(i);
+					item.setNameReference(NameReference.getNameReference(names[i])); //SHOULD pass string and change only if needed
+				}
+			}
+			else if (getNumItems()< names.length) {
+				for (int i=0; i<getNumItems(); i++) {
+					DoubleArray item = (DoubleArray)items.elementAt(i);
+					item.setNameReference(NameReference.getNameReference(names[i]));
+				}
+				for (int i=getNumItems(); i<names.length; i++)
+					addItem(names[i]);
+			}
+			else {
+				items.removeAllElements();
+				firstItem = null;
+				for (int i=getNumItems(); i<names.length; i++)
+					establishItem(names[i]);
+			}
+		}
+		
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public DoubleArray getItem(int index){
+		if (index<0 || index>= items.size())
+			return null;
+		return (DoubleArray)items.elementAt(index);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public String getItemName(int index){
+			if (items == null)
+				return null;
+			else
+				return ((DoubleArray)items.elementAt(index)).getName();
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public NameReference getItemReference(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		for (int i=0; i<getNumItems(); i++) {
+			DoubleArray item = (DoubleArray)items.elementAt(i);
+			if (nr.equals(item.getNameReference()))
+				return item.getNameReference();
+		}
+		return null;
+		
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public NameReference getItemReference(int index){
+			DoubleArray item = (DoubleArray)items.elementAt(index);
+			return item.getNameReference();
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((DoubleArray)items.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	
+	/*.........................................ContinuousAdjustable...............*/
+	public void deassignStates(){
+		for (int i=0; i<getNumItems(); i++)
+			for (int j=0; j<numNodes; j++)
+				((DoubleArray)items.elementAt(i)).setValue(j, ContinuousState.unassigned);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public double getState (int N, int item) {
+		if (item>=getNumItems()) //ERROR MESSAGE
+			return 0;
+		else if (N>=numNodes) {
+			return 0;
+		}
+		else
+			return ((DoubleArray)items.elementAt(item)).getValue(N);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public double getState (int N) {
+		return firstItem.getValue(N);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public void setState (int N, int item, double d) {
+		((DoubleArray)items.elementAt(item)).setValue(N, d);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public void setState (int N, double d) {
+		firstItem.setValue(N, d);
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	public void setCharacterState (int N, CharacterState cs) {
+		if (checkIllegalNode(N, 7))
+			return;
+		if (cs == null || !(cs instanceof ContinuousState))
+			return; 
+		for(int i=0; i<getNumItems(); i++)
+			setState(N, i, ((ContinuousState)cs).getValue(i));
+	}
+	/*..........................................  ContinuousAdjustable ..................................................*/
+	/**Trade states of nodes it and it2*/
+	public void tradeStatesBetweenTaxa(int it, int it2) {
+		if (checkIllegalNode(it, 9128) && checkIllegalNode(it, 9129))
+			return;
+		for (int item=0; item<getNumItems(); item++) {
+			DoubleArray matrix = getItem(item);
+			double temp = matrix.getValue(it);
+			matrix.setValue(it, matrix.getValue(it2));
+			matrix.setValue(it2, temp);
+		}
+	}
+	/*.........................................ContinuousAdjustable...............*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public AdjustableDistribution adjustSize(Taxa taxa) {
+		if (taxa.getNumTaxa() == this.getNumTaxa())
+			return this;
+		else {
+			ContinuousAdjustable soc = new ContinuousAdjustable(taxa, taxa.getNumTaxa());
+			soc.setItemsAs(this);
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			((CharacterStates)soc).setExplanation(getExplanation());
+			return soc;
+		}
+	}
+/**/
+}
+
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousData.java b/Source/mesquite/cont/lib/ContinuousData.java
new file mode 100644
index 0000000..eb57035
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousData.java
@@ -0,0 +1,1139 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+
+import mesquite.categ.lib.CategoricalData;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.DNAData;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** A subclass of CharacterData for continuous-valued data.  Can handle more than one item per matrix of cell
+(e.g., for mean, variance, etc.)  Each item is stored in a separate matrix; new items can be added by adding matrices.   Items are refered to by
+their name (e.g., MEAN, VARIANCE, etc.); each item has a NameReference associated to speed up queries. NOTE: At present,
+the support for multiple items is only just beginning to be implemented, and is fragmentary.  Many methods currently use just the first item.*/
+public class ContinuousData extends CharacterData implements ItemContainer {
+	private Double2DArray firstMatrix;
+	public static String DATATYPENAME="Continuous Data";
+	protected Vector matrices;
+	private static Vector defaultModels;
+	static {
+		defaultModels= new Vector(2);
+	}
+	public ContinuousData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars,taxa);
+		setUseDiagonalCharacterNames(true);
+		firstMatrix = new Double2DArray(numChars, numTaxa);
+		matrices = new Vector(1);
+		matrices.addElement(firstMatrix);
+		firstMatrix.deassignArray();
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixContSmall.gif";
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	public void dispose(){
+		super.dispose();
+		if (matrices!=null){ //update size of specification sets
+			for (int i=0; i<matrices.size(); i++) {
+				Double2DArray sv = (Double2DArray)matrices.elementAt(i);
+				sv.dispose();
+			}
+		}
+		matrices = null;
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData, boolean allowDifferentSizes){
+		if (sourceData==null)
+			return;
+		if ((sourceData.getNumTaxa()==getNumTaxa() && sourceData.getNumChars() == getNumChars()) || allowDifferentSizes) {
+			ContinuousData cD = (ContinuousData)sourceData;
+			int nItems = getNumItems();
+			setItemsAs(cD);
+			for (int i=0; i<nItems; i++){
+				Double2DArray imatrix = null;
+					imatrix = cD.getItem(i);
+				Double2DArray currentMatrix= getItem(i);
+				for (int ic = 0; ic< numChars; ic++)
+					for (int it = 0; it<numTaxa; it++)
+						if (it>=sourceData.getNumTaxa() || ic>=sourceData.getNumChars())
+							currentMatrix.setValue(ic, it, ContinuousState.unassigned); 
+						else
+							currentMatrix.setValue(ic,it,imatrix.getValue(ic,it));
+			}
+		}
+	}
+
+	public void copyDataBlock(CharacterData sourceData, int icStart, int icEnd, int itStart, int itEnd){
+		ContinuousData cD = (ContinuousData)sourceData;
+		setItemsAs(cD);
+		int nItems = getNumItems();
+		for (int i=0; i<nItems; i++){
+			Double2DArray imatrix = null;
+			imatrix = cD.getItem(i);
+			Double2DArray currentMatrix= getItem(i);
+			for (int ic=icStart; ic<=icEnd; ic++){
+				for (int it=itStart; it<=itEnd; it++) {
+					int itSource = it-itStart;
+					int icSource = ic-icStart;
+					if (itSource<sourceData.getNumTaxa() || icSource<sourceData.getNumChars())
+						currentMatrix.setValue(ic,it,imatrix.getValue(icSource,itSource));
+				}
+			}
+		}
+		resetCellMetadata();
+
+	}
+
+	/*..........................................  ContinuousData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData){
+		copyData(sourceData,false);
+	}
+	/*..........................................ContinuousData................*/
+	/** clones this ContinousData.  Does not include associated specsets etc. */
+	public CharacterData cloneData(){
+	
+		ContinuousData cD = (ContinuousData)makeCharacterData();
+		int nItems = getNumItems();
+		cD.setItemsAs(this);
+		for (int i=0; i<nItems; i++){
+			Double2DArray imatrix = null;
+			imatrix = cD.getItem(i);
+			Double2DArray oldMatrix= getItem(i);
+			for (int ic = 0; ic< numChars; ic++)
+				for (int it = 0; it<numTaxa; it++)
+					imatrix.setValue(ic,it, oldMatrix.getValue(ic,it));
+		}
+		for (int ic = 0; ic< numChars; ic++)
+			if (getSelected(ic))
+				cD.setSelected(ic, true);
+
+		return cD;
+	}
+
+	/*..........................................  CategoricalData  ..................................................*/
+	/**clone a portion of CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneDataBlock(int icStart, int icEnd, int itStart, int itEnd){
+		int blockChars = icEnd-icStart+1;
+		int blockTaxa = itEnd-itStart+1;
+		boolean[] taxaToClone = new boolean[getNumTaxa()];
+		for (int it=0; it<getNumTaxa(); it++) {
+			taxaToClone[it] = it>=itStart && it<=itEnd;
+		}
+		Taxa taxa = getTaxa().cloneTaxa(taxaToClone);
+
+		ContinuousData cD = new ContinuousData(getMatrixManager(), blockTaxa, blockChars, taxa);
+		int nItems = getNumItems();
+		cD.setItemsAs(this);
+		for (int i=0; i<nItems; i++){
+			Double2DArray imatrix = null;
+				imatrix = cD.getItem(i);
+			Double2DArray oldMatrix= getItem(i);
+			for (int ic=icStart; ic<=icEnd; ic++)
+				for (int it = itStart; it<=itEnd; it++)
+					imatrix.setValue(ic-icStart,it-itStart,oldMatrix.getValue(ic,it));
+		}
+		for (int ic = 0; ic< numChars; ic++)
+			if (getSelected(ic))
+				cD.setSelected(ic-icStart, true);
+
+		return cD;
+	}
+
+	public int getNumTaxa(){
+		return getNumTaxa(true);
+	}
+	public int getNumTaxa(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumTaxa(notifyIfError);
+		if (!notifyIfError)
+			return n;
+		if (firstMatrix == null)
+			dataIntegrityReportableAlert(getDataTypeName() + " with null internal matrix. getNumTaxa() = " + n);
+		else if (firstMatrix.getSizeT() != n)
+			dataIntegrityReportableAlert("Continuous matrix with incorrect record of number of taxa. getNumTaxa() = " + n + " firstMatrix.getSizeT() " + firstMatrix.getSizeT());
+		return n;
+	}
+	public int getNumChars(){
+		return getNumChars(true);
+	}
+	public int getNumChars(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumChars(notifyIfError);
+		if (firstMatrix == null){
+			if (notifyIfError)
+				dataIntegrityReportableAlert(getDataTypeName() + " with null internal matrix. getNumChar() = " + n  + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return 0;
+		}
+		else if (firstMatrix.getSizeC() < n){
+			if (notifyIfError)
+				dataIntegrityReportableAlert("Continuous matrix with incorrect record of number of characters. getNumChar() = " + n + " firstMatrix.getSizeC() " + firstMatrix.getSizeC() + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return firstMatrix.getSizeC();
+		}
+		else if (firstMatrix.getSizeC() > n){
+			if (notifyIfError)
+				dataIntegrityReportableAlert("Continuous matrix with incorrect record of number of characters. getNumChar() = " + n + " firstMatrix.getSizeC() " + firstMatrix.getSizeC() + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return n;
+		}
+		return n;
+	}
+	/*..........................................ContinuousData................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		Double2DArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		matrices.removeElement(matrix);
+		if (item == 0) {
+			firstMatrix = (Double2DArray)matrices.elementAt(0);
+		}
+	}
+	/*..........................................ContinuousData................*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Double2DArray establishItem(String name){
+
+		setDirty(true);
+		incrementStatesVersion();
+		if (firstMatrix != null && firstMatrix.getNameReference()==null && name!=null && matrices.size() ==1) {
+			firstMatrix.setNameReference(NameReference.getNameReference(name));
+			return firstMatrix;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				Double2DArray matrix = (Double2DArray)matrices.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(NameReference.getNameReference(name));
+					return matrix;
+				}
+			}
+
+			return addItem(name);
+		}
+	}
+	/*..........................................ContinuousData................*/
+	/** Make an item with the passed name.  If the first item already made is not yet named and if it is the only item so far,
+	then makeItem is assumed to be simply applying a name to this first item, and no new item is made.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Double2DArray addItem(String name){
+		setDirty(true);
+		incrementStatesVersion();
+		Double2DArray matrix = new Double2DArray(numChars, numTaxa);
+		if (firstMatrix == null)
+			firstMatrix = matrix;
+		matrix.setNameReference(NameReference.getNameReference(name));
+		matrix.deassignArray();
+		matrices.addElement(matrix);
+		return matrix;
+	}
+	/*..........................................ContinuousData................*/
+	/**Get the name reference for the item of name "name".  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		if (nr ==null) return null; //added 8 Dec 01
+		for (int i=0; i<getNumItems(); i++) {
+			Double2DArray matrix = (Double2DArray)matrices.elementAt(i);
+			if (nr.equals(matrix.getNameReference()))
+				return matrix.getNameReference();
+		}
+		return null;
+
+	}
+	/*..........................................ContinuousData................*/
+	/**Get the name reference for the item number "index".  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(int index){
+		Double2DArray matrix = (Double2DArray)matrices.elementAt(index);
+		if (matrix ==null) return null; //added 8 Dec 01
+		return matrix.getNameReference();
+	}
+	/*..........................................ContinuousState................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+	}
+	/*..........................................ContinuousData................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+		Double2DArray matrix = (Double2DArray)matrices.elementAt(index);
+		if (matrix ==null) return; //added 8 Dec 01
+		matrix.setNameReference(nr);
+		setDirty(true);
+	}
+	/*..........................................ContinuousData................*/
+	/**Get the name reference for the item whose name matches the name in the passed NameReference.  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(NameReference nr){
+		if (nr ==null) return null; //added 8 Dec 01
+		for (int i=0; i<getNumItems(); i++) {
+			Double2DArray matrix = (Double2DArray)matrices.elementAt(i);
+			if (matrix !=null && nr.equals(matrix.getNameReference())) //modified 8 Dec 01
+				return matrix.getNameReference();
+		}
+		return null;
+
+	}
+	/*..........................................ContinuousData................*/
+	/** Get the item name of the item number "index" */
+	public String getItemName(int index){
+		Double2DArray matrix = null;
+		if (matrices == null)
+			matrix = firstMatrix;
+		else if (index< matrices.size())
+			matrix = (Double2DArray)matrices.elementAt(index);
+		if (matrix ==null) return null; //added 8 Dec 01
+
+		if (matrix.getNameReference()==null)
+			return null;
+		else
+			return matrix.getNameReference().getValue();
+	}
+	/*..........................................ContinuousData................*/
+	/** Get which item has name matching the reference */
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((Double2DArray)matrices.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	/*..........................................ContinuousData................*/
+	/** get the number of items. */
+	public int getNumItems(){
+		if (matrices == null)
+			return 0;
+		return matrices.size();
+	}
+	public String getCellContentsDescription(){
+		boolean nameFound = false;
+		for (int i=0; i<getNumItems() && !nameFound; i++)
+			nameFound= !StringUtil.blank(getItemName(i));
+		if (!nameFound)
+			return null;
+		String descr = "(";
+		boolean first = true;
+		for (int i=0; i<getNumItems(); i++) {
+			String iN = getItemName(i);
+			if (StringUtil.blank(iN))
+				iN = "unnamed";
+			if (first) {
+				descr += iN;
+				first = false;
+			}
+			else
+				descr += ", " + iN;
+		}
+		return descr + ")";
+	}
+	/*..........................................ContinuousData................*/
+	/**Adds num characters after position "starting"; returns true iff successful.*/
+	public  boolean addParts(int starting, int num){
+		if (getMaxNumChars()!=MesquiteInteger.infinite && numChars+num>getMaxNumChars())
+			return false;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray newMatrix = new Double2DArray(newNumChars, numTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int it=0; it<numTaxa; it++) {
+				for (int ic=0; ic<=starting; ic++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+				for (int ic=0; ic<num; ic++)
+					newMatrix.setValue(ic + starting +1,it,ContinuousState.unassigned); //filling new part with missing data
+				for (int ic=0; ic<numChars - starting -1 ; ic++)
+					newMatrix.setValue(ic + starting + num + 1,it,oldMatrix.getValue(starting + ic+1,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices = newMatrices;
+		return super.addParts(starting, num);
+	}
+	/*..........................................ContinuousData................*/
+	/**Deletes num characters from position "starting"; returns true iff successful.*/
+	public boolean deleteParts(int starting, int num){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>numChars)
+			return false;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars =numChars-num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray newMatrix = new Double2DArray(newNumChars, numTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<starting; ic++){
+				for (int it=0; it<numTaxa; it++) 
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+			}
+			for (int ic=starting + num; ic<numChars ; ic++){
+				for (int it=0; it<numTaxa; it++) 
+					newMatrix.setValue(ic-num,it,oldMatrix.getValue(ic,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices.removeAllElements();
+		matrices = newMatrices;
+		return super.deleteParts(starting, num);
+	}
+	/*..........................................ContinuousData................*/
+	/**swaps characters first and second.*/
+	public boolean swapParts(int first, int second){
+		if (first<0 || first >= numChars)
+			return false;
+		if (second<0 || second >= numChars)
+			return false;
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			Double2DArray.swapColumns(oldMatrix.getMatrix(), first, second);
+		}
+		return super.swapParts(first, second);
+	}
+	/*..........................................ContinuousData................*/
+	/**moves num characters from position "first" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (!canMoveChars()) 
+			return false;
+		if (justAfter<0)
+			justAfter = -1;
+		else if (justAfter>=numChars)
+			justAfter = numChars-1;
+		if (starting<0 || starting >= numChars)
+			return false;
+		if (num<=0)
+			return false;
+		if (starting + num>numChars)
+			return false;
+
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			Double2DArray.moveColumns(oldMatrix.getMatrix(), starting, num, justAfter);
+		}
+		return super.moveParts(starting, num, justAfter);
+	}
+	/*..........................................ContinuousData................*/
+	/**Adds num taxa after position "starting"; returns true iff successful.*/
+	public boolean addTaxa(int starting, int num){
+		setDirty(true);
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numTaxa)
+			starting = numTaxa-1;
+		int newNumTaxa = numTaxa + num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray newMatrix = new Double2DArray(numChars, newNumTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<numChars; ic++){
+				for (int it=0; it<=starting; it++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+
+				for (int it=0; it<num; it++) 
+					newMatrix.setValue(ic,it + starting +1,ContinuousState.unassigned); //filling new part with missing data
+
+				for (int it=0; it<numTaxa - starting -1; it++) 
+					newMatrix.setValue(ic,it + starting + num + 1,oldMatrix.getValue(ic,starting + it+1)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		if (matrices!=null)
+			matrices.removeAllElements();
+		matrices = newMatrices;
+		numTaxa = newNumTaxa; 
+		incrementStatesVersion();
+		return super.addTaxa(starting, num);
+	}
+	/*..........................................ContinuousData................*/
+	/**Deletes num taxa from position "starting"; returns true iff successful.*/
+	public boolean deleteTaxa(int starting, int num){
+		setDirty(true);
+
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		if (num+starting>numTaxa)
+			num = numTaxa-starting;
+		int newNumTaxa = numTaxa - num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray newMatrix = new Double2DArray(numChars, newNumTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Double2DArray oldMatrix = ((Double2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<numChars; ic++){
+				for (int it=0; it<starting; it++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+
+				for (int it=starting+num; it<numTaxa; it++) 
+					newMatrix.setValue(ic,it-num,oldMatrix.getValue(ic,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices.removeAllElements();
+		matrices = newMatrices;
+		numTaxa = newNumTaxa; 
+		incrementStatesVersion();
+		return super.deleteTaxa(starting, num);
+	}
+	/*..........................................ContinuousData................*/
+	/**moves num taxa from position "starting" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveTaxa(int starting, int num, int justAfter){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		setDirty(true);
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray matrixA = ((Double2DArray)matrices.elementAt(item));
+			double[][] matrix = matrixA.getMatrix();
+			for (int ic=0; ic<numChars; ic++)
+				DoubleArray.moveParts(matrix[ic], starting, num, justAfter);
+		}
+		incrementStatesVersion();
+		return super.moveTaxa(starting, num, justAfter);
+	}
+
+	/*..........................................ContinuousData................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ContinuousState.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ContinuousData.DATATYPENAME;
+	}
+
+	/*..........................................ContinuousData................*/
+	public Double2DArray getItem(int i){
+		if (matrices !=null && i>=0 && i<matrices.size())
+			return (Double2DArray)matrices.elementAt(i);
+		return null;
+	}
+	/*..........................................ContinuousData................*/
+	private Double2DArray getItem(NameReference nr){
+		if (matrices == null)
+			return null;
+		for (int i=0; i<matrices.size(); i++) {
+			Double2DArray matrix = (Double2DArray)matrices.elementAt(i);
+			NameReference nRm = matrix.getNameReference();
+			if (nRm!=null && nRm.equals(nr))
+				return matrix;
+		}
+		return null;
+	}
+	/*..........................................ContinuousData................*/
+	/** trades the states of character ic and ic2 in taxon it.  Used for reversing sequences (for example).*/
+	public void tradeStatesBetweenCharacters(int ic, int ic2, int it, boolean adjustCellLinked) { 
+		if (ic>=numChars || it>=numTaxa || ic < 0 || it < 0)
+			return;
+		super.tradeStatesBetweenCharacters(ic, ic2, it, adjustCellLinked);
+		for (int item=0; item<getNumItems(); item++) {
+			Double2DArray matrix = getItem(item);
+			double temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic2,it));
+			matrix.setValue(ic2, it, temp);
+		}
+		incrementStatesVersion();
+		setDirty(true, ic, it);
+		setDirty(true, ic2, it);
+	}
+	/*..........................................ContinuousData................*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) { 
+		if (ic>=numChars && it>=numTaxa &&  it2 >=numTaxa) 
+			return;
+		super.tradeStatesBetweenTaxa(ic, it, it2);
+		incrementStatesVersion();
+		setDirty(true);
+		for (int item=0; item<getNumItems(); item++) {
+			Double2DArray matrix = getItem(item);
+			double temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic,it2));
+			matrix.setValue(ic, it2, temp);
+		}
+		setDirty(true, ic, it);
+		setDirty(true, ic, it2);
+	}
+	/*..........................................ContinuousData................*/
+	/** returns Color for state of character, scaled to maxState*/
+
+	public Color getColorOfState(int ic, int istate, int maxState){
+		return MesquiteColorTable.getDefaultColor(maxState,istate, MesquiteColorTable.COLORS_NO_BW); 
+	}
+	/*..........................................ContinuousData................*/
+	public Color getColorOfState(int ic, int istate){
+		return MesquiteColorTable.getDefaultColor(10, istate, MesquiteColorTable.COLORS_NO_BW);
+	}
+	/*..........................................ContinuousData................*/
+	protected String statesToString(int ic, int it, boolean forDisplay) {
+		String s = "";
+		boolean first = true;
+		for (int item = 0; item<getNumItems(); item++) {
+			if (!first)
+				s+=" ";
+			first = false;
+			double iState = getState(ic, it, item);
+			if (iState == MesquiteDouble.unassigned)
+				s += getUnassignedSymbol();
+			else if (forDisplay && iState == MesquiteDouble.inapplicable)
+				s += getInapplicableSymbol();
+			else {
+				if (forDisplay || !MesquiteDouble.isCombinable(iState))
+					s +=  MesquiteDouble.toString(iState);
+				else
+					s +=  Double.toString(iState);
+			}
+		}
+		if (getNumItems()>1)
+			return "(" + s + ")";
+		else
+			return s;
+	}
+
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay){
+		statesIntoStringBuffer(ic,it,sb,forDisplay,true,true);
+	}
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		sb.append(statesToString(ic, it, forDisplay)); //TODO: use buffer
+	}
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb){
+		sb.append(statesToString(ic, it, false));  //TODO: use buffer
+	}
+	float[] hsb = new float[3];
+	/*..........................................  ContinuousData  ..................................................*/
+	/** Gets the color representing state(s) of character ic in taxon it */ 
+	public Color getColorOfStates(int ic, int it){
+
+		double s = getState(ic, it, 0);
+		if (ContinuousState.isCombinable(s)) {
+			double minState=MesquiteDouble.unassigned;
+			double maxState=MesquiteDouble.unassigned;
+			for (int it2=0; it2<getNumTaxa(); it2++){
+				maxState = MesquiteDouble.maximum(maxState, getState(ic, it2, 0));
+				minState = MesquiteDouble.minimum(minState, getState(ic, it2, 0));
+			}
+			int place = (int)(((s-minState)/(maxState-minState))*10); 
+			return getColorOfState(ic, place, 10);
+		}
+		else 
+			return ColorDistribution.unassigned;
+	}
+
+	/*..........................................ContinuousData................*/
+	public CharacterDistribution getCharacterDistribution(int ic){
+		ContinuousEmbedded states =new ContinuousEmbedded(this, ic);
+		return states;
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	/** Fills matrix with data from passed StsOfCharacters object.*/
+	public void setMatrix(MCharactersDistribution states){ 
+		if (!(states instanceof MContinuousDistribution))
+			return;
+		setDirty(true);
+		incrementStatesVersion();
+		MContinuousDistribution cStates = (MContinuousDistribution)states;
+		setItemsAs(cStates);
+		for (int i = 0; i< getNumItems(); i++) {
+			Double2DArray matrix =getItem(i);
+			matrix.setValues(cStates.getItem(i));
+		}
+		stampHistoryChange();
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	/**get copy of matrix and return as MCharactersDistribution */
+	public MCharactersDistribution getMCharactersDistribution(){
+		MContinuousEmbedded states = new MContinuousEmbedded(this);
+		return states;
+	}
+	/*..........................................ContinuousData................*/
+	public CharacterDistribution makeCharacterDistribution(){
+		ContinuousAdjustable c = new ContinuousAdjustable(getTaxa(), numTaxa);
+		c.setItemsAs(this);
+		c.setParentData(this);
+		return c;
+	}
+	/*..........................................ContinuousData................*/
+	public CharacterState makeCharacterState() {
+		ContinuousState cs = new ContinuousState();
+		cs.setItemsAs(this);
+		return cs;
+
+	}
+	/*..........................................ContinuousData................*/
+	public CharacterData makeCharacterData() {
+		ContinuousData data = new ContinuousData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................ContinuousData................*/
+	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+		ContinuousData data = new ContinuousData(getMatrixManager(), ntaxa, nchars,  getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){ 
+		ContinuousData data =  new ContinuousData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................ContinuousData................*/
+	/** If incoming CharacterState has more items
+   	or items with names not seen in this ContinuousData, then new items are created in the ContinuousData*
+   	public  void reconcileItems(CharacterState cs){
+
+   		if (cs !=null && cs instanceof ContinuousState) {
+   			ContinuousState contS = (ContinuousState)cs;
+   			if (contS.getNumItems()==1 && getNumItems()==1 && (contS.getItemReference(0) == null || getItemReference(0) == null || contS.getItemReference(0) == getItemReference(0))){
+   			}
+   			else {
+	   			int made = 0;
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+	   					establishItem(nr.getValue());
+	   					made++;
+	   				}
+	   			}
+	   			int numToMake = contS.getNumItems() - getNumItems();
+	   			for (int i=0; i< numToMake; i++)
+	   				addItem(null);
+   			}
+  		}
+   	}
+	/*..........................................ContinuousData................*/
+	/** sets the state of character ic in taxon it from CharacterState cs.  If incoming CharacterState has more items
+   	or items with names not seen in this ContinuousData, then new items are created in the ContinuousData*/
+	public  void setState(int ic, int it, CharacterState cs){
+
+		if (cs !=null && cs instanceof ContinuousState) {
+			ContinuousState contS = (ContinuousState)cs;
+			if (contS.getNumItems()==1 && getNumItems()==1 && NameReference.equal(contS.getItemReference(0), getItemReference(0))){
+				setState(ic, it, 0, contS.getValue(0));  
+			}
+			else {
+				int made = 0;
+				for (int i=0; i<contS.getNumItems(); i++) {
+					NameReference nr = contS.getItemReference(i);
+					if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+						establishItem(nr.getValue());
+						made++;
+					}
+				}
+				int numToMake = contS.getNumItems() - getNumItems();
+				for (int i=0; i< numToMake; i++)
+					addItem(null);
+				int currentOpen = 0;
+				//unnamed items in incoming character state will be applied to first available items whose names are not in incoming character state
+				for (int i=0; i<contS.getNumItems(); i++) {
+					NameReference nr = contS.getItemReference(i);
+					if (getItemNumber(nr)>=0) {//named item found; set state
+						setState(ic, it, getItemNumber(nr), contS.getValue(i));  
+					}
+					else { //put it in next slot in this that has no corresponding in contS
+						boolean found = false;
+						for (int item = currentOpen; item<getNumItems() && !found; item++){
+							NameReference nrM = getItemReference(item);
+							if (nrM == null || contS.getItemNumber(nrM) < 0){
+								setState(ic, it, item, contS.getValue(i));
+								currentOpen = item+1;
+								found = true;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	/*..........................................ContinuousData................*/
+	public void setState(int ic, int it, int item, double states){
+		if (ic<numChars && it<numTaxa && item<getNumItems()) {
+			Double2DArray m = ((Double2DArray)matrices.elementAt(item));
+			if (m.getValue(ic, it)!= states){
+				m.setValue(ic, it, states);
+				setDirty(true, ic, it);
+				incrementStatesVersion();
+			}
+		}
+	}
+	/** sets the state of character ic in taxon it to the default state (which in some circumstances may be inapplicable, e.g. gaps for molecular data)*/
+	public  void deassign(int ic, int it){
+		setToUnassigned(ic, it);	
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	/** sets the state of character ic in taxon it to inapplicable*/
+	public  void setToInapplicable(int ic, int it){
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray matrix = ((Double2DArray)matrices.elementAt(item));
+					matrix.setValue(ic,it,ContinuousState.inapplicable); //filling with missing data
+		}	
+		setDirty(true, ic, it);
+	}
+	/*..........................................  ContinuousData  ..................................................*/
+	/** sets the state of character ic in taxon it to unassigned*/
+	public  void setToUnassigned(int ic, int it){
+		for (int item = 0; item<getNumItems(); item++){
+			Double2DArray matrix = ((Double2DArray)matrices.elementAt(item));
+					matrix.setValue(ic,it,ContinuousState.unassigned); //filling with missing data
+		}	
+		setDirty(true, ic, it);
+	}
+	/*..........................................ContinuousData................*/
+	public void setState(int ic, int it, String s){
+		MesquiteMessage.warnProgrammer("Error: simple set state used in " + getDataTypeName());
+		setState(ic, it, null, true, null);
+	}
+	/*..........................................    ..................................................*/
+	public boolean legalValue(int ic, double states){
+		return true;
+	}
+	/*..........................................ContinuousData................*/
+	/** set the state of char ic and taxon it to that in string starting at position pos.  If pos==null,
+	assume that whole string is relevant*/
+	public int setState(int ic, int it, Parser parser, boolean fromEditor, MesquiteString result){ 
+		if (ic>=numChars || ic < 0 || it>=numTaxa ||it<0) {
+			if (result!=null)
+				result.setValue("Character or taxon number out of bounds in setState " + ic + "  " + it);
+			MesquiteMessage.printStackTrace("");
+			return OUTOFBOUNDS;
+		}
+		if (parser==null)
+			return ERROR;
+		if (parser.blank()) {
+			if (result!=null)
+				result.setValue("String blank in setState");
+			return ERROR;
+		}
+		StringBuffer s = parser.getBuffer();
+		boolean dirt = false;
+		if (s.length() == 1){
+			char c= s.charAt(0);
+			if (c ==getInapplicableSymbol()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=MesquiteDouble.inapplicable) {
+						setState(ic, it, i, MesquiteDouble.inapplicable);
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+			else if (c ==getUnassignedSymbol()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=MesquiteDouble.unassigned) {
+						setState(ic, it, i, MesquiteDouble.unassigned);
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+			else if (c ==getMatchChar()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=getState(ic,  0, i)) {
+						setState(ic, it, i, getState(ic,  0, i));
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+		}
+		boolean contin = false;
+		boolean wasNull = false;
+		if (fromEditor) { 
+			parser.setPosition(0);
+			contin = true;
+			wasNull = true;
+		}
+		boolean done = false;
+		int item = 0;
+		String t = null;
+		int prev = parser.getPosition();
+		//MesquiteInteger pos = new MesquiteInteger(parser.getPosition()); //how to avoid this instantiation but be reentrant safe?
+		while (!done){
+			parser.setPosition(prev);
+			t = parser.getNextToken();
+			if ("(".equals(t)) {
+				contin = true;
+				prev = parser.getPosition();
+			}
+			if (StringUtil.blank(t)|| ")".equals(t)) {
+				done = true;
+				prev = parser.getPosition();
+			}
+			else  {
+				if (!contin)
+					done = true;
+				parser.setPosition(prev);
+				double d = MesquiteDouble.fromString(parser); 
+				prev = parser.getPosition();
+				if (d!=MesquiteDouble.impossible && legalValue(ic,d)) {
+					if (d != getState(ic, it, item)) {
+						setState(ic,it, item++,d);
+						dirt = true;
+					}
+					else
+						item++;
+				}
+				else {
+					if (result != null) {
+						result.setValue("Illegal state value for "+getDataTypeName());
+						return ERROR;
+					}
+				}
+				if (done)
+					parser.setPosition(prev);
+			}
+		}
+		if (dirt)
+			setDirty(true, ic, it);
+		return OK;
+	}
+
+	/*..........................................ContinuousData................*/
+	/** returns the state of character ic in taxon it*/
+	public  CharacterState getCharacterState(CharacterState cs, int ic, int it){
+		if (cs==null || cs.getClass()!=ContinuousState.class) {
+			cs =new ContinuousState();
+		}
+		((ContinuousState)cs).setItemsAs(this);
+		for (int i=0; i< getNumItems(); i++) {
+			((ContinuousState)cs).setValue(i, getState(ic, it, i));
+		}
+		return cs; 
+	}
+
+	/*..........................................ContinuousData................*/
+	/** returns the state of character ic in taxon it*/
+	public  double getState(int ic, int it, int item){
+		if (matrices!=null && ic<numChars && it<numTaxa && item<getNumItems()) {
+			Double2DArray da = ((Double2DArray)matrices.elementAt(item));
+			if (da!=null)
+				return da.getValue(ic, it);
+		}
+		return MesquiteDouble.unassigned;
+	}
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	/*..........................................ContinuousData................*/
+	public String getStatesSummary(int ic, boolean selectedOnly){
+		ContinuousState state=null;
+		double max = MesquiteDouble.unassigned;
+		double min = MesquiteDouble.unassigned;
+		//ITEMS: ask if more than one item, and if so list column for each
+		for (int it=0; it<numTaxa; it++) 
+			if (!selectedOnly || getTaxa().getSelected(it)) {
+				state = (ContinuousState)getCharacterState(state, ic, it);
+				if (MesquiteDouble.greaterThan(state.getValue(0), max, 0))
+					max = state.getValue(0);
+				if (MesquiteDouble.lessThan(state.getValue(0), min, 0))
+					min = state.getValue(0);
+			}
+		return MesquiteDouble.toString(min) + " - " + MesquiteDouble.toString(max);	
+	}
+	/*..........................................ContinuousData................*/
+	public String getStatesSummary(int ic){
+		return getStatesSummary(ic,false);
+	}
+	/*..........................................ContinuousData................*/
+	/** returns whether the character ic is inapplicable to taxon it.   True if inapplicable in all items.*/
+	public  boolean isInapplicable(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)== ContinuousState.inapplicable; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (!ContinuousState.isInapplicable(getState(ic, it, i)));
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................ContinuousData................*/
+	/** returns whether the state of character ic is missing in taxon it.  True if unassigned in all items.*/
+	public  boolean isUnassigned(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)== ContinuousState.unassigned; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (!ContinuousState.isUnassigned(getState(ic, it, i)));
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................ContinuousData................*/
+	/** returns whether the state of character ic is missing in taxon it.  True if unassigned in all items.*/
+	public  boolean isValid(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)!= ContinuousState.impossible; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (ContinuousState.isImpossible(getState(ic, it, i)))
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................ContinuousData................*/
+	/** dump the matrix to the log*/
+	public void logMatrix(){
+		StringBuffer matrixString= new StringBuffer();
+		for (int it=0; it<numTaxa; it++) {
+			matrixString.append(getTaxa().getTaxon(it).getName() + "  ");
+			for (int ic=0; ic<numChars; ic++)
+				statesIntoStringBuffer(ic,it, matrixString, true); 
+			matrixString.append(StringUtil.lineEnding());
+		}
+		MesquiteModule.mesquiteTrunk.logln(matrixString.toString());
+	}
+
+	/*.................................................................................................................*/
+	public String getChecksumSummaryString(){
+		ContinuousState state=null;
+		double minValue = MesquiteDouble.unassigned;
+		double maxValue = MesquiteDouble.unassigned;
+		double sumSquares = 0;
+		for (int ic = 0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++) {
+				state =(ContinuousState)getCharacterState(state, ic, it);
+				if (!state.isUnassigned() && !state.isInapplicable())
+					for (int item = 0; item <getNumItems(); item ++) {
+						double value = state.getValue(item);
+						minValue = MesquiteDouble.minimum(minValue, value);
+						maxValue = MesquiteDouble.maximum(maxValue, value);
+						if (MesquiteDouble.isCombinable(value))
+								sumSquares += value*value;
+					}
+			}
+		return "numChars " + getNumChars() + "   numItems " + getNumItems() + "   min " + minValue + "   max " + maxValue + "   sumSquares " + sumSquares;
+	}
+	/*..........................................ContinuousData................*/
+	public long calculateChecksum(CRC32 crc32){
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		int numItems = getNumItems();
+		for (int ic=0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++) 
+				for (int item=0; item<numItems; item++) {
+					bytes = MesquiteNumber.doubleToBytes(getState(ic, it, item), bytes);
+					for (int i = 0; i<8; i++)
+						crc32.update(bytes[i]);
+				}
+
+		return crc32.getValue();
+	}
+	/*..........................................ContinuousData................*/
+	/** returns default column width in editors..*/
+	public int getDefaultColumnWidth() {
+		return 70;
+	}
+	/*..........................................ContinuousData................*/
+	public static DefaultReference findDefaultReference(NameReference paradigm){
+		if (defaultModels == null) {
+			MesquiteMessage.warnProgrammer("findDefaultReference with null default models ");
+			MesquiteMessage.printStackTrace();
+			return null;
+		}
+		for (int i=0; i<defaultModels.size(); i++){
+			DefaultReference dR = (DefaultReference)defaultModels.elementAt(i);
+			if (dR.getParadigm() != null && dR.getParadigm().equals(paradigm))
+				return dR;
+		}
+		return null;
+
+	}
+	/*..........................................ContinuousData................*/
+	/** this should not be used except by modules INTENDING to steal away the defaults */
+	public static void registerDefaultModel(String paradigm, String name){
+		if (defaultModels == null)
+			return;
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR == null) {
+			dR = new DefaultReference(p);
+			defaultModels.addElement(dR);
+		}
+		dR.setDefault(name);
+	}
+	/*..........................................ContinuousData................*/
+	public CharacterModel getDefaultModel(String paradigm){
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR==null)
+			return null;
+		else {
+			CharacterModel cm = getProject().getCharacterModel(dR.getDefault());
+			if (cm==null) 
+				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+			return cm;
+		}
+	}
+	/*..........................................ContinuousData................*/
+	public String toString(){
+		return "Continuous data matrix id: " + getID() + "; chars: " + numChars + "; taxa: " + numTaxa + "; items " + getNumItems() + "; name: " + getName();
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousDistribution.java b/Source/mesquite/cont/lib/ContinuousDistribution.java
new file mode 100644
index 0000000..d4511ef
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousDistribution.java
@@ -0,0 +1,148 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes 
+ See notes under <a href = "ContinuousData.html">ContinuousData</a> regarding items */
+public abstract class ContinuousDistribution  extends ContinuousStates implements CharacterDistribution {
+	
+	public ContinuousDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................ContinuousDistribution................*/
+	public int getNumNodes(){
+		return getNumTaxa();
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data*/
+	public boolean hasMissing (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isUnassigned(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps)*/
+	public boolean hasInapplicable (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isInapplicable(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data in the taxa of the tree*/
+	public boolean hasMissing(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isUnassigned(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasMissing(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps) in the taxa of the tree*/
+	public boolean hasInapplicable(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isInapplicable(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasInapplicable(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same)*/
+	public boolean isConstant(){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = null;
+		for (int i=1; i< getNumNodes(); i++)
+			if (!cs.equals(cs2 = getCharacterState(cs2, i)))
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	private boolean isConstantRec(Tree tree, int node, CharacterState cs, CharacterState cs2){
+		if (tree.nodeIsTerminal(node)){
+			if (!cs.equals(cs2 = getCharacterState(cs2, tree.taxonNumberOfNode(node))))
+				return false;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (!isConstantRec(tree, d, cs, cs2))
+					return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	public boolean isConstant(Tree tree, int node){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = getCharacterState(null, 0);
+		return isConstantRec(tree, node, cs, cs2);
+	}
+	/*..........................................ContinuousDistribution................*/
+	/** returns a CharacterDistribution that is adjustable and has the same states*/
+	public AdjustableDistribution getAdjustableClone(){
+		ContinuousAdjustable soc = new ContinuousAdjustable(getTaxa(), getNumTaxa());
+		soc.setItemsAs(this);
+		for (int it = 0; it<getNumTaxa(); it++) {
+			for (int item = 0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(it, item)); 
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................ContinuousDistribution................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates instanceof ContinuousHistory)) 
+			soc = new ContinuousHistory(tree.getTaxa(), numNodes, (ContinuousData)getParentData()); //should keep items!!! (since StsOfChar may have different number from parent data!
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new ContinuousHistory(tree.getTaxa(), numNodes, (ContinuousData)getParentData());
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousEmbedded.java b/Source/mesquite/cont/lib/ContinuousEmbedded.java
new file mode 100644
index 0000000..6ef866a
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousEmbedded.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes */
+public class ContinuousEmbedded  extends ContinuousDistribution {
+	ContinuousData data;
+	public ContinuousEmbedded (ContinuousData data, int ic) {
+		super(data.getTaxa());
+		this.data = data;
+		this.characterNumber = ic;
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return data.getStateClass();
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public CharacterData getParentData() {
+		return data;
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public int getNumItems() {
+		return data.getNumItems();
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public NameReference getItemReference(String name){
+		return data.getItemReference(name);
+		
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public NameReference getItemReference(int index){
+		return data.getItemReference(index);
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public int getItemNumber(NameReference nr){
+		return data.getItemNumber(nr);
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public String getItemName(int index){
+			return data.getItemName(index);
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public int getNumTaxa() {
+		return data.getNumTaxa();
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public double getState (int N, int item) {
+		return data.getState(characterNumber, N, item);
+	}
+	/*..........................................ContinuousEmbedded................*/
+	public double getState (int N) {
+		return data.getState(characterNumber, N, 0);
+	}
+	public String getName(){
+		return data.getCharacterName(characterNumber);
+	}
+}
+
diff --git a/Source/mesquite/cont/lib/ContinuousHistory.java b/Source/mesquite/cont/lib/ContinuousHistory.java
new file mode 100644
index 0000000..f04d6b3
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousHistory.java
@@ -0,0 +1,420 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes. 
+ See notes under <a href = "ContinuousData.html">ContinuousData</a> regarding items */
+public class ContinuousHistory extends ContinuousAdjustable  implements CharacterHistory {
+	private double minState = 0;
+	private double maxState = 100;
+	public ContinuousHistory (Taxa taxa, int numNodes, ContinuousData data) { 
+		super(taxa, numNodes);
+		setParentData(data);
+		if (data!=null) {
+			setItemsAs(data);
+		}
+	}
+	/*..........................................ContinuousHistory................*/
+	public CharacterHistory clone(CharacterHistory s) {
+		ContinuousHistory snew;
+		if ((s==null) || (s.getNumNodes()!=numNodes) || (!(s instanceof ContinuousHistory)))
+			snew = new ContinuousHistory(getTaxa(), numNodes, (ContinuousData)data); 
+		else {
+			snew = (ContinuousHistory)s;
+			snew.data = data;
+		}
+		snew.setItemsAs(this);
+		for (int i=0; i<numNodes; i++) {
+			for (int im = 0; im<getNumItems(); im++)
+				snew.setState(i, im, getState(i, im));
+		}
+		snew.characterNumber = characterNumber;
+		if (observedStates!=null)
+			snew.setObservedStates((CharacterDistribution)observedStates.getAdjustableClone());
+		snew.setExplanation(getExplanation());
+		return snew;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** for MPRs, etc., gets the ith resolution of the history */
+	public CharacterHistory getResolution(Tree tree, CharacterHistory resultStates, long i){
+		resultStates = adjustHistorySize(tree, resultStates);
+		clone(resultStates);
+		return resultStates;
+	}
+	/** for MPRs, etc., gets the number of resolutions of the history */
+	public long getNumResolutions(Tree tree){
+		return 1;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** Returns a new object indicating the states at the tips (used whether or not History is reconstruction)*/
+	public CharacterDistribution getStatesAtTips(Tree tree){
+		if (observedStates !=null)
+			return (CharacterDistribution)observedStates.getAdjustableClone();
+		else {
+			ContinuousAdjustable d = new ContinuousAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+			d.setItemsAs(this);
+			fillDistribution(tree, tree.getRoot(), d);
+			return d;
+		}
+	}
+	/*..........................................ContinuousHistory................*/
+	private void fillDistribution(Tree tree, int node, ContinuousAdjustable dist) {  
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			for (int i =0; i<getNumItems(); i++)
+				dist.setState(t, i, getState(node, i));
+		}
+		else for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			fillDistribution(tree, d, dist);
+	}
+	/*..........................................ContinuousHistory................*/
+
+	CharacterDistribution observedStates;
+	/*..........................................ContinuousHistory................*/
+	/** Returns the states in the terminal taxa (used if History is reconstruction)*/
+	public CharacterDistribution getObservedStates(){
+		return observedStates;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** Sets the states in the terminal taxa (used if History is reconstruction)*/
+	public void setObservedStates(CharacterDistribution observed){
+		this.observedStates = observed;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustSize(Tree tree) {
+		if (tree.getNumNodeSpaces() == this.getNumNodes())
+			return this;
+		else {
+			ContinuousHistory soc = new ContinuousHistory(tree.getTaxa(), tree.getNumNodeSpaces(), (ContinuousData)getParentData());
+			soc.setItemsAs(this);
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			((CharacterStates)soc).setExplanation(getExplanation());
+			return soc;
+		}
+	}
+	/*..........................................ContinuousHistory................*/
+	public void calcMinMaxStates(Tree tree, int node) {
+		for (int i=0; i<getNumItems(); i++) {
+			double s=getState(node, i); 
+			maxState = MesquiteDouble.maximum(maxState, s);
+			minState = MesquiteDouble.minimum(minState, s);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calcMinMaxStates(tree, d);
+	}
+	/*..........................................................*/
+	public double getMinState(){
+		return minState;
+	}
+	/*..........................................................*/
+	public double getMaxState(){
+		return maxState;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** Must be called before a tree is shaded.  Goes through all nodes to find states present, to set
+	minima and maxima. */
+	public void prepareColors(Tree tree, int drawnRoot) {  
+		minState=MesquiteDouble.unassigned;
+		maxState=MesquiteDouble.unassigned;
+		calcMinMaxStates(tree, drawnRoot); 
+		if (getParentData()!=null && getParentCharacter()>=0){
+			int ic = getParentCharacter();
+			ContinuousData data  = ((ContinuousData)getParentData());
+			for (int it = 0; it<data.getNumTaxa(); it++) {
+				double s = data.getState(ic, it, 0);
+				maxState = MesquiteDouble.maximum(maxState, s);
+				minState = MesquiteDouble.minimum(minState, s);
+			}
+		}
+		else if (getObservedStates()!=null){
+			int ic = getParentCharacter();
+			ContinuousDistribution data  = (ContinuousDistribution)getObservedStates();
+			for (int it = 0; it<data.getNumNodes(); it++) {
+				double s = data.getState(it);
+				maxState = MesquiteDouble.maximum(maxState, s);
+				minState = MesquiteDouble.minimum(minState, s);
+			}
+		}
+	}
+
+	/*..........................................  ContinuousHistory  ..................................................*/
+	public double getBinBoundary(int i, MesquiteColorTable colorTable){  //the boundary after bin i
+
+		int numBinBoundaries = 10;
+		double[] binBoundaries = colorTable.getPreferredBinBoundaries();
+		if (binBoundaries != null)
+			numBinBoundaries = binBoundaries.length;
+		else
+			return minState + (i+1)*(maxState-minState)/numBinBoundaries;
+
+
+		double localMin, localMax;
+		int localE;
+
+		localMin = minState;
+		localMax = MesquiteDouble.unassigned;
+		int localNumBoundaries;
+		int localMinK= -1;
+		int localMaxK = numBinBoundaries;
+		for (int k=0; k< numBinBoundaries; k++){  //what are the defined boundaries on either side of i?
+			if (MesquiteDouble.isCombinable(binBoundaries[k])){
+				if (k<i){
+					localMin = binBoundaries[k];
+					localMinK = k;
+				}
+				else if (!MesquiteDouble.isCombinable(localMax)){
+					localMax = binBoundaries[k];
+					localMaxK = k;
+				}
+			}
+		}
+		if (!MesquiteDouble.isCombinable(localMax))
+			localMax = maxState;
+		if (localMax< localMin)
+			localMax = localMin;
+		localE = i-localMinK-1;
+		localNumBoundaries = localMaxK-localMinK;
+
+		double rangeUnit = (localMax-localMin)*1.0;
+		if (localNumBoundaries>0)
+			rangeUnit = rangeUnit/localNumBoundaries;
+
+		return localMin + rangeUnit*(localE+1);
+
+	}
+
+	/*..........................................  ContinuousHistory  ..................................................*/
+	public int getPlace(double d, MesquiteColorTable colorTable){
+
+		int numBinBoundaries = 10;
+		double[] binBoundaries = colorTable.getPreferredBinBoundaries();
+
+		if (binBoundaries != null) 
+			numBinBoundaries = binBoundaries.length;
+		else
+			return (int)(((d-minState)/(maxState-minState))*numBinBoundaries);
+
+		for (int e=0; e<=numBinBoundaries; e++) {
+			double localMin, localMax;
+			int localE;
+			int localNumBoundaries;
+
+			//here look for closest defined bin boundaries
+			localMin = minState;
+			localMax = MesquiteDouble.unassigned;
+			int localMinK= -1;
+			int localMaxK = numBinBoundaries;
+			for (int k=0; k< numBinBoundaries; k++){
+				if (MesquiteDouble.isCombinable(binBoundaries[k])){
+					if (k<e){
+						localMin = binBoundaries[k];
+						localMinK = k;
+					}
+					else if (!MesquiteDouble.isCombinable(localMax)){
+						localMax = binBoundaries[k];
+						localMaxK = k;
+					}
+				}
+			}
+			if (!MesquiteDouble.isCombinable(localMax))
+				localMax = maxState;
+			if (localMax< localMin)
+				localMax = localMin;
+			localE = e-localMinK-1;
+			localNumBoundaries = localMaxK-localMinK;
+			double rangeUnit = (localMax-localMin)*1.0;
+			if (localNumBoundaries != 0)
+				rangeUnit = rangeUnit/localNumBoundaries; 
+			if (d <=localMin + rangeUnit*(localE+1)) //d > localMin + rangeUnit*localE && 
+				return e;
+
+		}
+		return numBinBoundaries;
+
+	}
+	/*..........................................  ContinuousHistory  ..................................................*/
+	/** places into the already instantiated ColorDistribution the colors corresponding to the CharacterState, and returns the number of colors.  Uses default colors. 
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*/
+	public int getColorsOfState(CharacterState state, ColorDistribution colors, MesquiteColorTable colorTable) {
+		if (colors==null || state == null || ! (state instanceof ContinuousState))
+			return 0;
+		int numBinBoundaries = 10;
+		double[] binBoundaries = colorTable.getPreferredBinBoundaries();
+		if (binBoundaries != null)
+			numBinBoundaries = binBoundaries.length;
+		colors.initialize();
+		ContinuousState cState = (ContinuousState)state;
+		if (cState.getNumItems() == 1) {
+			double s =cState.getValue(0); 
+			colors.setWeight(0, 1.0);
+			if (!MesquiteDouble.isCombinable(s))
+				colors.setColor(0, Color.white);
+			else {
+				int place = getPlace(s, colorTable); //(int)(((s-minState)/(maxState-minState))*numBinBoundaries); 
+				colors.setColor(0, colorTable.getColor(numBinBoundaries, place));//bug fixed in 1. 12 that had been introduced in 1. 10
+				//colors.setColor(0, colorTable.getColor(s, minState, maxState));  1.10 to 1.11
+			}
+		}
+		else {
+			for (int i=0; i<cState.getNumItems() ; i++) {
+				double s = cState.getValue(i); 
+				colors.setWeight(i, 1.0/cState.getNumItems() );
+				if (!MesquiteDouble.isCombinable(s))
+					colors.setColor(0, Color.white);
+				else {
+					int place = getPlace(s, colorTable); //(int)(((s-minState)/(maxState-minState))*numBinBoundaries); 
+					colors.setColor(i, colorTable.getColor(numBinBoundaries, place)); //bug fixed in 1. 12 that had been introduced in 1. 10
+					//colors.setColor(i, colorTable.getColor(s, minState, maxState));  1.10 to 1.11
+				}
+			}
+		}
+
+		return cState.getNumItems() ;
+	}
+	/*..........................................ContinuousHistory................*/
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable) {
+
+	if (colorTable == null)
+			colorTable =  new MesquiteColorTable();
+	
+	   if (colorTable.getMode() == MesquiteColorTable.COLORS)
+		   colorTable.setMode(MesquiteColorTable.COLORS_NO_BW);
+
+		return colorTable;
+	}
+	/*..........................................ContinuousHistory................*/
+	/** Places into Color array the colors at the node, and returns the number of colors.  Uses passed
+	stateColors as color key.  If null is passed, uses color system of parent data (using maxState of this
+	StsOfCharcter) or, if there is not parent data object, the default colors. */
+	public int getColorsAtNode(int node, ColorDistribution colors, MesquiteColorTable stateColors, boolean showWeights) {
+		int numBinBoundaries = 10;
+		double[] binBoundaries = stateColors.getPreferredBinBoundaries();
+		if (binBoundaries != null)
+			numBinBoundaries = binBoundaries.length;
+		for (int i=0; i<10; i++) colors.initialize();
+		if (getNumItems() == 1) {
+			double s =firstItem.getValue(node); 
+			colors.setWeight(0, 1.0);
+			if (!MesquiteDouble.isCombinable(s))
+				colors.setColor(0, ColorDistribution.unassigned);
+			else {
+				int place = getPlace(s, stateColors); //(int)(((s-minState)/(maxState-minState))*numBinBoundaries); 
+				colors.setColor(0, stateColors.getColor(numBinBoundaries, place));  
+			}
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				double s = getState(node,i);
+				colors.setWeight(i, 1.0/getNumItems());
+				if (!MesquiteDouble.isCombinable(s))
+					colors.setColor(0, ColorDistribution.unassigned);
+				else {
+					int place = getPlace(s, stateColors); //(int)(((s-minState)/(maxState-minState))*numBinBoundaries); 
+					colors.setColor(i, stateColors.getColor(numBinBoundaries, place));
+				}
+			}
+		}
+
+		return getNumItems();
+	}
+	/*..........................................ContinuousHistory................*/
+	/** returns the vector of ColorEvents in order, e.g. for stochastic character mapping.  Return null if none.  Not yet supported for ContinuousHistory */
+	public ColorEventVector getColorSequenceAtNode(int node, MesquiteColorTable stateColors){
+		return null;
+	}
+
+	/*..........................................ContinuousHistory................*/
+	public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) {
+		int colorCount=0;
+		int numBinBoundaries = 10;
+		double[] binBoundaries = stateColors.getPreferredBinBoundaries();
+		if (binBoundaries != null) 
+			numBinBoundaries = binBoundaries.length;
+		for (int e=0; e<=numBinBoundaries; e++) {
+			if (binBoundaries == null){
+				double rangeUnit = (maxState-minState)*1.0/numBinBoundaries; 
+				cs[colorCount]= stateColors.getColor(numBinBoundaries,e);
+				if (tableMappings != null)
+					tableMappings[colorCount] = new Point(numBinBoundaries, e);
+				stateNames[colorCount++]=MesquiteDouble.toString(minState + rangeUnit*e) + " to " + MesquiteDouble.toString(minState + rangeUnit*(e+1));
+			}
+			else {
+				double localMin, localMax;
+				int localE;
+				int localNumBoundaries;
+				//here look for closest defined bin boundaries
+				localMin = minState;
+				localMax = MesquiteDouble.unassigned;
+				int localMinK= -1;
+				int localMaxK = numBinBoundaries;
+				for (int k=0; k< numBinBoundaries; k++){
+					if (MesquiteDouble.isCombinable(binBoundaries[k])){
+						if (k<e){
+							localMin = binBoundaries[k];
+							localMinK = k;
+						}
+						else if (!MesquiteDouble.isCombinable(localMax)){
+							localMax = binBoundaries[k];
+							localMaxK = k;
+						}
+					}
+				}
+				if (!MesquiteDouble.isCombinable(localMax))
+					localMax = maxState;
+				if (localMax< localMin)
+					localMax = localMin;
+				localE = e-localMinK-1;
+				localNumBoundaries = localMaxK-localMinK;
+				double rangeUnit = (localMax-localMin)*1.0;
+				if (localNumBoundaries != 0)
+					rangeUnit = rangeUnit/localNumBoundaries; 
+				cs[colorCount]= stateColors.getColor(numBinBoundaries,e);
+				if (tableMappings != null)
+					tableMappings[colorCount] = new Point(numBinBoundaries, e);
+				stateNames[colorCount++]=MesquiteDouble.toString(localMin + rangeUnit*localE) + " to " + MesquiteDouble.toString(localMin + rangeUnit*(localE+1));
+			}
+		}
+		return colorCount;
+	}
+	/*..........................................ContinuousHistory................*
+		public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) {
+		int colorCount=0;
+		int numBinBoundaries = 10;
+		double[] binBoundaries = stateColors.getPreferredBinBoundaries();
+		if (binBoundaries != null)
+			numBinBoundaries = binBoundaries.length;
+		double rangeUnit = (maxState-minState)*1.0/numBinBoundaries; 
+		for (int e=0; e<=numBinBoundaries; e++) {
+				cs[colorCount]= stateColors.getColor(numBinBoundaries,e);
+				if (tableMappings != null)
+					tableMappings[colorCount] = new Point(numBinBoundaries, e);
+			stateNames[colorCount++]=MesquiteDouble.toString(minState + rangeUnit*e) + " to " + MesquiteDouble.toString(minState + rangeUnit*(e+1));
+		}
+		return colorCount;
+	}
+
+	 */
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousState.java b/Source/mesquite/cont/lib/ContinuousState.java
new file mode 100644
index 0000000..1749f29
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousState.java
@@ -0,0 +1,450 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/**This class provides some basic utilities for Continuous characters.  It represents the entry for one character
+and one taxon.  Thus, it can contain more than one item (min, max, mean, variance, etc.).*/
+public class ContinuousState extends CharacterState implements ItemContainer {
+	/** The state (MesquiteDouble.unassigned) that corresponds to missing data.*/
+	public static final double unassigned = MesquiteDouble.unassigned; 
+	/** The state (MesquiteDouble.inapplicable) that corresponds to a gap (inapplicable data).*/
+	public static final double inapplicable = MesquiteDouble.inapplicable;
+	/** The state (MesquiteDouble.infinite) that corresponds to infinite.*/
+	public static final double infinite = MesquiteDouble.infinite;
+	/** The state (MesquiteDouble.impossible) that corresponds to an impossible value.  
+	This is returned when a value is invalid, e.g. a string is parsed for a number but no valid number is found.*/
+	public static final double impossible = MesquiteDouble.impossible;
+	/** The maximum allowed number of items*/
+	public static final int MAXITEMS = 32;
+	
+	/* the stored values (for the various items)*/
+	double[] values;
+	/* names of the items*/
+	NameReference[] names;
+	/*number of items*/
+	int numItems=0;
+	
+	public ContinuousState () {
+		numItems = MAXITEMS;
+		values = new double[MAXITEMS];
+		names = new NameReference[MAXITEMS];
+		for (int i=0; i<MAXITEMS; i++) {
+			values[i] = MesquiteDouble.unassigned;
+			names[i] = null;
+		}
+	}
+	public ContinuousState (double value) {
+		numItems = MAXITEMS;
+		values = new double[MAXITEMS];
+		names = new NameReference[MAXITEMS];
+		for (int i=0; i<MAXITEMS; i++) {
+			values[i] = MesquiteDouble.unassigned;
+			names[i] = null;
+		}
+		values[0] = value;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ContinuousData.DATATYPENAME;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns the maximum number of items (min, max, mean, variance, etc.) in this state*/
+//	public int getMaxItems(){
+//		return 32;
+//	}
+	/*..........................................ContinuousState................*/
+	/** returns the number of items (min, max, mean, variance, etc.) in this state*/
+	public int getNumItems(){
+		return numItems;
+	}
+	/*..........................................ContinuousState................*/
+	/** sets the number of items in this state*/
+	public void setNumItems(int n){
+		if (n<=MAXITEMS)
+			numItems = n;
+		else if (n>=0)
+			numItems = n;
+		for (int i=numItems; i<MAXITEMS; i++) {
+			values[i] = MesquiteDouble.unassigned;
+			names[i] = null;
+		}
+	}
+	/*..........................................ContinuousState................*/
+	/** gets name of item n*/
+	public String getItemName(int n){
+		if (names != null && n>=0 && n<numItems) {
+			NameReference nr = names[n];
+			if (nr==null)
+				return null;
+			return nr.getValue();
+		}
+		else
+			return null;
+	}
+	/*..........................................ContinuousState................*/
+	/** gets NameReferece of item n*/
+	public NameReference getItemReference(String name){
+		return NameReference.getNameReference(name);
+	}
+	/*..........................................ContinuousState................*/
+	/** gets NameReferece of item n*/
+	public NameReference getItemReference(int n){
+		if (names != null && n>=0 && n<numItems)
+			return names[n];
+		else
+			return null;
+	}
+	/*..........................................ContinuousState................*/
+	/** sets NameReference of item n*/
+	public void setItemReference(int n, NameReference nr){
+		if (n>=0 && n<numItems)
+			names[n] = nr;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns which item number has NameReference nr nr*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<numItems; i++)
+			if (nr.equals(names[i]))
+				return i;
+		return -1;
+	}
+	/*..........................................ContinuousState................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		setNumItems(iCont.getNumItems());
+		for (int i=0; i<getNumItems(); i++)
+			setItemReference(i, iCont.getItemReference(i));
+	}
+	/*..........................................ContinuousState................*/
+	public Class getCharacterDataClass() {
+		return ContinuousData.class;
+	}
+	public Class getMCharactersDistributionClass(){
+		return MContinuousAdjustable.class;
+	}
+	public Class getCharacterDistributionClass(){
+		return ContinuousAdjustable.class;
+	}
+	public Class getCharacterHistoryClass(){
+		return ContinuousHistory.class;
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new ContinuousAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new ContinuousHistory(taxa, numNodes, null);
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if missing data (unassigned)*/
+	public static boolean isUnassigned(double s) {
+		return s == unassigned;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if all items have missing data (unassigned)*/
+	public boolean isUnassigned() {
+		for (int i=0; i<numItems; i++)
+			if (values[i] != MesquiteDouble.unassigned)
+				return false;
+		return true;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if inapplicable*/
+	public static boolean isInapplicable(double s) {
+		return s == inapplicable;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if all items are inapplicable*/
+	public boolean isInapplicable() { //check all items
+		boolean inappPresent = false;
+		for (int i=0; i<numItems; i++)
+			if (values[i] == MesquiteDouble.inapplicable)
+				inappPresent = true;
+			else if (values[i] != MesquiteDouble.unassigned)
+				return false;
+		return inappPresent;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if value is invalid*/
+	public static boolean isImpossible(double s) {
+		return s == impossible;
+	}
+	/*..........................................ContinuousState................*/
+	/** returns true if at least one item is invalid*/
+	public boolean isImpossible() { //check all items
+		for (int i=0; i<numItems; i++)
+			if (values[i] == MesquiteDouble.impossible)
+				return true;
+		return false;
+	}
+	/*..........................................ContinuousState.....................................*/
+	/** returns true if at least one item is combinable (i.e. a valid assigned state).*/
+	public boolean isCombinable(){
+		for (int i=0; i<numItems; i++)
+			if (MesquiteDouble.isCombinable(values[i]))
+				return true;
+		return false;
+	}
+	/*..........................................ContinuousState.....................................*/
+	/** returns whether value is combinable (i.e. a valid assigned state) or not.*/
+	public static boolean isCombinable(double d){
+		return MesquiteDouble.isCombinable(d);
+	}
+	/*..........................................ContinuousState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s) {
+		return equals(s, false);
+	}
+	/*..........................................ContinuousState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing) {
+		if (s==null)
+			return false;
+		if (!(s instanceof ContinuousState))
+			return false;
+		if (allowMissing && (isUnassigned() || s.isUnassigned())) //fixed 13 Dec 01
+				return true;
+		ContinuousState cS = (ContinuousState)s;
+		if (cS.getNumItems()!=getNumItems())
+			return false;
+		for (int i=0; i<getNumItems(); i++)
+			if  (cS.getValue(i) != getValue(i))
+				return false;
+		return true;
+	}
+	/*..........................................ContinuousState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact) {
+		return equals(s,allowMissing);
+	}
+	/*..........................................ContinuousState................*/
+	public static double absolute(double d) {
+		if (d== unassigned || d==inapplicable || d==impossible || d==infinite)
+			return d;
+		if (d<0)
+			return -d;  
+		else
+			return d;
+	}
+	/*..........................................ContinuousState................*/
+	public static double maximum(double d1, double d2) {
+		if (d1==d2)
+			return d1;
+		if (d2==infinite)
+			return d2;
+		if (d1==infinite)
+			return d1;
+			
+		if (d1== unassigned || d1==inapplicable || d1==impossible) {
+			if (d2== unassigned || d2==inapplicable || d2==impossible)
+				return impossible;
+			else
+				return d2;
+		}
+		if (d2== unassigned || d2==inapplicable || d2==impossible)
+			return d1;
+		
+		if (d1<d2)
+			return d2;  
+		else
+			return d1;
+	}
+	/*..........................................ContinuousState................*/
+	public static double minimum(double d1, double d2) { 
+		if (d1==d2)
+			return d1;
+		if (d1== unassigned || d1==inapplicable || d1==impossible  || d1==infinite) {
+			if (d2== unassigned || d2==inapplicable || d2==impossible  || d2==infinite)
+				return impossible;
+			else
+				return d2;
+		}
+		if (d2== unassigned || d2==inapplicable || d2==impossible  || d2==infinite)
+			return d1;
+		if (d1>d2)
+			return d2;  
+		else
+			return d1;
+	}
+	/*..........................................ContinuousState................*/
+	/** sets the value to inapplicable*/
+	public void setToInapplicable() {
+			for (int i=0; i<numItems; i++) {
+				values[i] = inapplicable;
+			}
+	}
+	/*..........................................ContinuousState................*/
+	/** sets the value to unassigned*/
+	public void setToUnassigned() {
+			for (int i=0; i<numItems; i++) {
+				values[i] = unassigned;
+			}
+	}
+	/*..........................................ContinuousState................*/
+	/** sets value of item n */
+	public void setValue(int n, double d){
+		if (n>=0 && n<numItems)
+			values[n] = d;
+	}
+	/*..........................................ContinuousState................*/
+	public void setValue(CharacterState cs){
+		if (cs!=null && cs instanceof ContinuousState) {
+			ContinuousState c = (ContinuousState)cs;
+			setNumItems(c.getNumItems());
+			for (int i=0; i<numItems; i++) {
+				values[i] = c.getValue(i);
+				names[i] = c.getItemReference(i);
+			}
+		}
+	}
+	/*..........................................ContinuousState................*/
+	public void setValue(String st, CharacterData parentData) {
+		MesquiteInteger pos = new MesquiteInteger(0);
+		if (StringUtil.blank(st)){
+			setNumItems(1);
+			setValue(0, MesquiteDouble.unassigned);
+			return;
+		}
+		int n= 0;
+		String s;
+		int status = 1;
+		while (pos.getValue()<st.length() && n < 32 && status>=0) { 
+			char c = st.charAt(pos.getValue());
+			if (c == '(') {
+				status = 0;
+				pos.increment();
+			}
+			else if (c == ')')
+				status = -1;
+			else if (c == ',' || c == ' ')
+				pos.increment();
+			else {
+				if (status !=0)
+					status = -1;
+				setValue(n, MesquiteDouble.fromString(st, pos));
+				n++;
+			}
+		}
+		setNumItems(n);
+	}
+	/*..........................................ContinuousState................*/
+	/** gets the value of item # n*/
+	public double getValue(int n){
+		if (n>=0 && n<numItems)
+			return values[n];
+		else
+			return unassigned;
+	}
+	/*..........................................ContinuousState................*/
+	/** gets the name value of item with NameReference NR*/
+	public double getValue(NameReference nr){
+		if (nr==null)
+			return MesquiteDouble.unassigned;
+		for (int i=0; i<numItems; i++)
+			if (nr.equals(names[i]))
+				return values[i];
+		return MesquiteDouble.unassigned;
+	}
+	/*..........................................ContinuousState................*
+	/** sets its value to the value given by the String passed to it starting at position pos*
+	public void setValue(String st, MesquiteInteger pos){
+		if (StringUtil.blank(st)){
+			setNumItems(1);
+			setValue(0, MesquiteDouble.unassigned);
+			return;
+		}
+		int n= 0;
+		String s;
+		int status = 1;
+		while (pos.getValue()<st.length() && n < 32 && status>=0) { 
+			char c = st.charAt(pos.getValue());
+			if (c == '(') {
+				status = 0;
+				pos.increment();
+			}
+			else if (c == ')')
+				status = -1;
+			else if (c == ',' || c == ' ')
+				pos.increment();
+			else {
+				if (status !=0)
+					status = -1;
+				setValue(n, MesquiteDouble.fromString(st, pos));
+				n++;
+			}
+		}
+		setNumItems(n);
+	}
+
+	/*..........................................ContinuousState................*/
+	private String valueToString(double v){
+		if (v == MesquiteDouble.unassigned)
+			return "?";
+		else if (v == MesquiteDouble.inapplicable)
+			return "-";
+		else
+			return MesquiteDouble.toString(v);
+	}
+	public String toString() {
+		String s = "";
+		boolean first = true;
+		for (int i=0; i<numItems; i++) {
+			String name = getItemName(i);
+			if (name == null || "unnamed".equalsIgnoreCase(name)) {
+				name = "";
+				if (!first)
+					s += " " + valueToString(values[i]);
+				else
+					s += valueToString(values[i]);
+			}
+			else {
+				if (!first)
+					s += " " + name + " " + valueToString(values[i]);
+				else
+					s += name + " " + valueToString(values[i]);
+			}
+			first = false;
+		}
+		return s;
+	}
+	/*..........................................ContinuousState.....................................*/
+
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  */
+	public String toDisplayString(){
+		String s = "";
+		boolean first = true;
+		if (numItems>1)
+			s += "(";
+		for (int i=0; i<numItems; i++) {
+			if (!first)
+				s += ", " + valueToString(values[i]);
+			else
+				s +=  valueToString(values[i]);
+			first = false;
+		}
+		if (numItems>1)
+			s += ")";
+		return s;
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousStateTest.java b/Source/mesquite/cont/lib/ContinuousStateTest.java
new file mode 100644
index 0000000..f42850b
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousStateTest.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class ContinuousStateTest extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof ContinuousStateTest)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!CharacterState.class.isAssignableFrom((Class)obj))
+			return true;
+		if (!(obj instanceof Class))
+			return true;
+		return ((((Class)obj).isAssignableFrom(ContinuousData.class)) || (((Class)obj).isAssignableFrom(ContinuousState.class)));
+	}
+	public Class getAcceptedClass(){
+		return ContinuousState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/ContinuousStates.java b/Source/mesquite/cont/lib/ContinuousStates.java
new file mode 100644
index 0000000..32bf0fa
--- /dev/null
+++ b/Source/mesquite/cont/lib/ContinuousStates.java
@@ -0,0 +1,163 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes 
+ See notes under <a href = "ContinuousData.html">ContinuousData</a> regarding items */
+public abstract class ContinuousStates  extends CharacterStates implements ItemContainer {
+	
+	public ContinuousStates (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................ContinuousStates................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new ContinuousState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ContinuousState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ContinuousData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ContinuousData.DATATYPENAME;
+	}
+	/*..........................................ContinuousStates................*/
+	public abstract int getNumItems();
+	/*..........................................ContinuousStates................*/
+	public abstract String getItemName(int index);
+	/*..........................................ContinuousStates................*/
+	public abstract NameReference getItemReference(String name);
+	/*..........................................ContinuousStates................*/
+	public abstract NameReference getItemReference(int index);
+	/*..........................................ContinuousStates................*/
+	public abstract int getItemNumber(NameReference nr);
+	/*..........................................ContinuousStates................*/
+	public CharacterModel getDefaultModel(MesquiteProject file, String paradigm){
+   		NameReference p = NameReference.getNameReference(paradigm);
+   		DefaultReference dR = ContinuousData.findDefaultReference(p);
+   		if (dR==null)
+   			return null;
+   		else {
+   			CharacterModel cm = file.getCharacterModel(dR.getDefault());
+   			if (cm==null) 
+   				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+   			return cm;
+   		}
+   	}
+	/*..........................................ContinuousStates................*/
+	public void logStates(){
+		MesquiteModule.mesquiteTrunk.logln("States ");
+		String statesString="";
+		for (int ic=0; ic<getNumNodes(); ic++) {
+			for (int iitems=0; iitems<getNumItems(); iitems++)
+				statesString+=toString(ic, " ") + " ";
+		}
+		statesString+= '\r';
+		MesquiteModule.mesquiteTrunk.logln(statesString);
+	}
+	/*..........................................ContinuousStates................*/
+	public abstract double getState (int N, int item);
+	/*..........................................ContinuousStates................*/
+	public abstract double getState (int N);
+	/*..........................................ContinuousStates................*/
+	
+   	public  boolean isInapplicable(int N){
+   		for (int item = 0; item< getNumItems(); item++)
+   			if ( getState(N, item)!= ContinuousState.inapplicable)
+   				return false;
+   		return true; 
+   	}
+
+	/*..........................................ContinuousStates................*/
+   	public  boolean isUnassigned(int N){
+   		for (int item = 0; item< getNumItems(); item++)
+   			if ( getState(N, item)!= ContinuousState.unassigned)
+   				return false;
+   		return true; 
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** returns whether the state of character has uncertainty in node/taxon N*/
+   	public boolean isUncertain(int N){  //TODO: implement uncertainty for continuous data
+   		return false;
+   	}
+	/*..........................................ContinuousStates................*/
+   	public int userQueryItem(String message, MesquiteModule module){
+		int numItems =getNumItems();
+		String[] items = new String[numItems];
+		for (int i=0; i<items.length; i++){
+			if (StringUtil.blank(getItemName(i)))
+				items[i] = "(unnamed)";
+			else
+				items[i]= getItemName(i);
+		}
+		return ListDialog.queryList(module.containerOfModule(), "Select item", message, MesquiteString.helpString,  items, 0);
+   	}
+	/*..........................................ContinuousStates................*/
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		ContinuousState c;
+		if (cs==null || !(cs instanceof ContinuousState))
+			c = new ContinuousState();
+		else c = (ContinuousState)cs;
+		c.setItemsAs(this);
+		for (int i=0; i<getNumItems(); i++)
+			c.setValue(i, getState(N, i));
+		return c;
+	}
+	/*..........................................ContinuousStates................*/
+	/** Is the first state greater than second?  This uses only the first item! */
+	public boolean firstIsGreater (int N, int M){ 
+		if (isUnassigned(N) || isInapplicable(N)) //2015: fixed to return true only if neither is inapplicable or missing
+			return false;
+		if (isUnassigned(M) || isInapplicable(M))
+			return false;
+		if (getState(N) > getState(M))
+			return true;
+		return false;
+		
+	}
+	/*..........................................ContinuousStates................*/
+	public boolean statesEqual(int N, int M) {
+   		for (int item = 0; item< getNumItems(); item++)
+   			if (getState(N, item)!= getState(M, item))
+   				return false;
+   		return true; 
+	}
+	/*..........................................ContinuousStates................*/
+	public String toString (int node, String lineEnding) {
+		if (getNumItems() == 1)
+			return MesquiteDouble.toString(getState(node)); 
+		else { //if min and max do special string
+			String s="";
+			for (int i=0; i<getNumItems(); i++) {
+				s += getItemName(i) + ":" + MesquiteDouble.toString(getState(node, i)) + lineEnding;
+			}
+			return s;
+		}
+	}
+	
+}
+
+
diff --git a/Source/mesquite/cont/lib/EigenAnalysis.java b/Source/mesquite/cont/lib/EigenAnalysis.java
new file mode 100644
index 0000000..47446e4
--- /dev/null
+++ b/Source/mesquite/cont/lib/EigenAnalysis.java
@@ -0,0 +1,119 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+//import Jampack.*;  
+import Jama.*;  
+
+
+
+	public  class EigenAnalysis {
+		public double[][] eigenVectors;
+		public double[] eigenValues;
+		public double[] imagEigenValues;   //Added 4 April 2006 P. Midford
+		/*...........................................................*/
+		/** Jama version */
+		public EigenAnalysis(double[][] matrix, boolean transpose, boolean positivize, boolean sort){
+			int numRows = Double2DArray.numFullRows(matrix);
+			int numColumns = Double2DArray.numFullColumns(matrix);
+			if (numRows!=0 &&  numColumns!=0){
+				int n = numRows;
+				if (numRows!=numColumns)
+					MesquiteMessage.warnProgrammer("not same number columns & rows in eigenanalysis");
+				EigenvalueDecomposition eig = new EigenvalueDecomposition(new Matrix(matrix));      	//using Eig from Jampack 
+				eigenVectors = eig.getV().getArrayCopy();  	//eigenVectors
+		     	eigenValues = eig.getRealEigenvalues();
+		     	imagEigenValues = eig.getImagEigenvalues();
+				if (transpose)
+					eigenVectors = Double2DArray.transpose(eigenVectors);
+				if (positivize)
+					positivize(eigenValues, eigenVectors);
+				if (sort)
+					sortByEigenvalues(eigenValues, imagEigenValues, eigenVectors);
+			 }
+		}
+		/*...........................................................*/
+		/** Jampack version *
+		public EigenAnalysis(double[][] matrix){
+			int numRows = Double2DArray.numFullRows(matrix);
+			int numColumns = Double2DArray.numFullColumns(matrix);
+			if (numRows!=0 &&  numColumns!=0){
+				int n = numRows;
+				if (numRows!=numColumns)
+					MesquiteMessage.warnProgrammer("not same number columns & rows in eigenanalysis");
+				try{
+					Eig eig = new Eig(new Zmat(matrix));      	//using Eig from Jampack 
+					eigenVectors = eig.X.getRe();  	//eigenVectors
+			     		eigenValues = new double[eig.D.n]; 
+			     		for (int i=0; i<eig.D.n; i++)  //retrieving eigenValues from eig 
+						eigenValues[i]=eig.D.get0(i).re;  
+					eigenVectors = Double2DArray.transpose(eigenVectors);
+				}
+				catch(JampackException e){
+					MesquiteMessage.println("Jampack exception in EigenAnalysis; matrix:\n" + Double2DArray.toString(matrix));
+					e.printStackTrace();
+				 }
+			 }
+		}
+		/*...........................................................*/
+		// don't need to positivize any imaginary components, since the complex eigenvalues
+		// always come in conjugate pairs
+		private void positivize(double[] eigenValues, double[][] eigenVectors){
+			if (eigenValues == null)
+				return;
+			for (int i=0; i<eigenValues.length; i++)
+				if (eigenValues[i]<0) {
+					eigenValues[i] = -eigenValues[i];
+					for (int j=0; j<eigenVectors[i].length; j++)
+						eigenVectors[i][j]= -eigenVectors[i][j];
+				}
+		}
+		/*...........................................................*/
+		private void sortByEigenvalues(double[] eigenValues, double[] imagEigenValues, double[][] eigenVectors){
+			if (eigenValues == null)
+				return;
+			double[] tempVector;
+			for (int i=0; i<eigenValues.length; i++) {
+				for (int j= i-1; j>=0 && eigenValues[j]<eigenValues[j+1]; j--) {
+					double temp = eigenValues[j];
+					eigenValues[j] = eigenValues[j+1];
+					eigenValues[j+1]=temp;
+					double itemp = imagEigenValues[j];
+					imagEigenValues[j] = imagEigenValues[j+1];
+					imagEigenValues[j+1] = itemp;
+					tempVector = eigenVectors[j];
+					eigenVectors[j]= eigenVectors[j+1];
+					eigenVectors[j+1] = tempVector;
+				}
+			}
+		}
+		/*----------getEigenvalues ----------*/
+		public double[] getEigenvalues(){
+			return eigenValues;
+	  	}
+		/* ----------getEigenDiagonal  ----------*/
+		public double[] getImagEigenValues(){
+			return imagEigenValues;
+		}
+		
+		/* ----------getEigenvectors  ----------*/
+		public double[][] getEigenvectors(){
+			return eigenVectors;
+		}
+}
+
diff --git a/Source/mesquite/cont/lib/GeogDataSearcher.java b/Source/mesquite/cont/lib/GeogDataSearcher.java
new file mode 100644
index 0000000..2988807
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeogDataSearcher.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class GeogDataSearcher extends DataSearcher  {
+   	 public Class getDutyClass() {
+   	 	return GeogDataSearcher.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new GeographicStateTest();
+	}
+
+}
+
+
diff --git a/Source/mesquite/cont/lib/GeogDataUtility.java b/Source/mesquite/cont/lib/GeogDataUtility.java
new file mode 100644
index 0000000..22783a7
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeogDataUtility.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class GeogDataUtility extends DataUtility  {
+   	 public Class getDutyClass() {
+   	 	return GeogDataUtility.class;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new GeographicStateTest();
+	}
+
+}
+
diff --git a/Source/mesquite/cont/lib/GeographicAdjustable.java b/Source/mesquite/cont/lib/GeographicAdjustable.java
new file mode 100644
index 0000000..359ccfd
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeographicAdjustable.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes */
+public class GeographicAdjustable  extends ContinuousAdjustable  {
+	
+	public GeographicAdjustable (Taxa taxa, int numNodes) {
+		super(taxa,numNodes);
+	}
+	
+}
+
+
+
diff --git a/Source/mesquite/cont/lib/GeographicData.java b/Source/mesquite/cont/lib/GeographicData.java
new file mode 100644
index 0000000..4b163ca
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeographicData.java
@@ -0,0 +1,193 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** A subclass of CharacterData for Geographic data.*/
+public class GeographicData extends ContinuousData {
+	static final int DECIMAL_DEGREES = 0;
+	int valueFormat = DECIMAL_DEGREES;
+	static final int LATITUDE = 0;
+	static final int LONGITUDE=1;
+	
+	public GeographicData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, 2,taxa);
+		setCharacterName(LATITUDE, "Latitude");
+		setCharacterName(LONGITUDE, "Longitude");
+	}
+	/*..........................................GeographicData................*/
+	/** Indicates which character is latitude */
+	public static int getLatitudeCharacter(){
+		return LATITUDE;
+	}
+	/*..........................................GeographicData................*/
+	/** Indicates which character is longitude */
+	public static int getLongitudeCharacter(){
+		return LONGITUDE;
+	}
+	/*..........................................GeographicData................*/
+	/** Indicates the type of character stored */
+	public Class getStateClass(){
+		return GeographicState.class;
+	}
+	public int getMaxNumChars(){
+		return 2;
+	}
+	public boolean canMoveChars(){
+		return false;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return "Geographic Data";
+	}
+	
+	public boolean canAddCharacters() {
+		return false;
+	}
+
+	/*..........................................GeographicData................*/
+	public CharacterData makeCharacterData() {
+		GeographicData data = new GeographicData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................GeographicData................*/
+	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+		GeographicData data = new GeographicData(getMatrixManager(), ntaxa, nchars,  getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){ 
+		GeographicData data =  new GeographicData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................  GeographicData  ..................................................*/
+	/**clone a portion of CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneDataBlock(int icStart, int icEnd, int itStart, int itEnd){
+		int blockChars = icEnd-icStart+1;
+		int blockTaxa = itEnd-itStart+1;
+		boolean[] taxaToClone = new boolean[getNumTaxa()];
+		for (int it=0; it<getNumTaxa(); it++) {
+			taxaToClone[it] = it>=itStart && it<=itEnd;
+		}
+		Taxa taxa = getTaxa().cloneTaxa(taxaToClone);
+
+		ContinuousData cD = new GeographicData(getMatrixManager(), blockTaxa, blockChars, taxa);
+		int nItems = getNumItems();
+		cD.setItemsAs(this);
+		for (int i=0; i<nItems; i++){
+			Double2DArray imatrix = null;
+				imatrix = cD.getItem(i);
+			Double2DArray oldMatrix= getItem(i);
+			for (int ic=icStart; ic<=icEnd; ic++)
+				for (int it = itStart; it<=itEnd; it++)
+					imatrix.setValue(ic-icStart,it-itStart,oldMatrix.getValue(ic,it));
+		}
+		for (int ic = 0; ic< numChars; ic++)
+			if (getSelected(ic))
+				cD.setSelected(ic-icStart, true);
+
+		return cD;
+	}
+/*..........................................................*/
+   	public CharacterDistribution getCharacterDistribution(int ic){
+   		ContinuousEmbedded states =new ContinuousEmbedded(this, ic);
+		return states;
+   	}
+	/*..........................................    ..................................................*/
+	/**get copy of matrix and return as MCharactersDistribution */
+   	public MCharactersDistribution getMCharactersDistribution(){
+   		MContinuousEmbedded states = new MContinuousEmbedded(this);
+		return states;
+   	}
+	/*..........................................    ..................................................*/
+   	public boolean legalValue(int ic, double states){
+   		return !MesquiteDouble.isCombinable(states) || ((ic==LATITUDE && states>=-90.0 && states<=90.0) || (ic==LONGITUDE && states>=-180.0 && states<=180.0));
+   	}
+	/*..........................................    ..................................................*/
+   	public void setState(int ic, int it, int item, double states){
+   		if (!legalValue(ic,states)) {
+   			return;
+   		}
+   		super.setState(ic,it,item,states);
+   	}
+	/*..........................................................*/
+   	/** returns the state of character ic in taxon it*/
+   	public  CharacterState getCharacterState(CharacterState cs, int ic, int it){
+   		if (cs==null || cs.getClass()!=GeographicState.class) {
+   			cs =new GeographicState();
+		}
+   		((GeographicState)cs).setItemsAs(this);
+   		for (int i=0; i< getNumItems(); i++) {
+   			((GeographicState)cs).setValue(i, getState(ic, it, i));
+   		}
+   		return cs; 
+   	}
+	/*..........................................GeographicData................*/
+   	public String toString(){
+   		return "Geographic data matrix id: " + getID() + "; chars: " + numChars + "; taxa: " + numTaxa + "; items " + getNumItems() + "; name: " + getName();
+   	}
+
+
+
+
+	/*.................................................................................................................*/
+	public static double getPolarLatitude(double latitude){
+			return (latitude/90)*Math.PI/2;
+	}
+	/*.................................................................................................................*/
+	public static double getPolarColatitude(double latitude){   
+			return Math.PI/2 - getPolarLatitude(latitude);
+	}
+	/*.................................................................................................................*/
+	public static double getRegularLatitude(double polarLatitude){
+		double latitude = (polarLatitude/Math.PI)*2*90;
+		if (latitude<-90.0)
+			latitude = 90+latitude;
+		else if (latitude>90.0)
+			latitude = latitude-180;
+		return latitude;
+	}
+	/*.................................................................................................................*/
+	public static double getPolarLongitude(double longitude){
+		if (longitude>0)
+			return (longitude/180)*Math.PI;
+		else
+			return ((360+longitude)/180)*Math.PI;
+	}
+	/*.................................................................................................................*/
+	public static double getRegularLongitude(double polarLongitude){
+		double longitude;
+		if (polarLongitude< Math.PI)  // eastern hemisphere
+			longitude= (polarLongitude/Math.PI)*180;
+		else   // western hemisphere
+			longitude= (polarLongitude/Math.PI)*180-360;
+		if (longitude<-180.0)
+			longitude = 360+longitude;
+		else if (longitude>180.0)
+			longitude = longitude-360;
+		return longitude;
+	}
+	
+
+}
+
+
diff --git a/Source/mesquite/cont/lib/GeographicState.java b/Source/mesquite/cont/lib/GeographicState.java
new file mode 100644
index 0000000..f86658f
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeographicState.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/**This class provides some basic utilities for Geographic characters. .*/
+public class GeographicState extends ContinuousState {
+	/** The maximum allowed number of items*/
+	public static final int MAXITEMS = 1;
+	
+	int numItems=0;
+	
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return "Geographic Data";
+	}
+	/*..........................................................*/
+	public Class getCharacterDataClass() {
+		return GeographicData.class;
+	}
+	public Class getCharacterDistributionClass(){
+		return GeographicAdjustable.class;
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/GeographicStateTest.java b/Source/mesquite/cont/lib/GeographicStateTest.java
new file mode 100644
index 0000000..51ef65c
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeographicStateTest.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class GeographicStateTest extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof GeographicStateTest)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!CharacterState.class.isAssignableFrom((Class)obj))
+			return true;
+		if (!(obj instanceof Class))
+			return true;
+		return ((((Class)obj).isAssignableFrom(GeographicData.class)) || (((Class)obj).isAssignableFrom(GeographicState.class)));
+	}
+	public Class getAcceptedClass(){
+		return GeographicState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/GeographicStates.java b/Source/mesquite/cont/lib/GeographicStates.java
new file mode 100644
index 0000000..5c27b64
--- /dev/null
+++ b/Source/mesquite/cont/lib/GeographicStates.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/** Contains an array of geographic character states for one character */
+public abstract class GeographicStates  extends ContinuousStates {
+	
+	public GeographicStates (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................ContinuousStates................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new GeographicState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return GeographicState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return GeographicData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return "Geographic Data";
+	}
+	
+}
+
+
diff --git a/Source/mesquite/cont/lib/ItemContainer.java b/Source/mesquite/cont/lib/ItemContainer.java
new file mode 100644
index 0000000..2f331a4
--- /dev/null
+++ b/Source/mesquite/cont/lib/ItemContainer.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** Contains an array of  continuous character states for one character, at each of the taxa or nodes 
+ See notes under <a href = "ContinuousData.html">ContinuousData</a> regarding items */
+public interface ItemContainer  {
+	
+	/*..........................................ItemContainer................*/
+	public int getNumItems();
+	/*..........................................ItemContainer................*/
+	public String getItemName(int index);
+	/*..........................................ItemContainer................*/
+	public NameReference getItemReference(String name);
+	/*..........................................ItemContainer................*/
+	public NameReference getItemReference(int index);
+	/*..........................................ItemContainer................*/
+	//public void setItemReference(int index, NameReference nr);
+
+	/*..........................................ItemContainer................*/
+	public int getItemNumber(NameReference nr);
+	/*..........................................ItemContainer................*/
+	//public Object addItem(String nr);
+	/*..........................................ItemContainer................*/
+	//public void removeItem(int nr);
+
+}
+
+
diff --git a/Source/mesquite/cont/lib/MContinuousAdjustable.java b/Source/mesquite/cont/lib/MContinuousAdjustable.java
new file mode 100644
index 0000000..7600dd2
--- /dev/null
+++ b/Source/mesquite/cont/lib/MContinuousAdjustable.java
@@ -0,0 +1,345 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  continuous character states for many characters, at each of the taxa or nodes.*/
+public class MContinuousAdjustable  extends MContinuousDistribution implements MAdjustableDistribution {
+	int numTaxa=0;
+	int numChars=0;
+	protected Double2DArray firstMatrix; //other dimension for items (sample size, variance, etc., etc.)
+	protected Vector matrices;
+	String annotation;
+	public MContinuousAdjustable (Taxa taxa, int numChars, int numTaxa) {
+		super(taxa);
+		this.numTaxa= numTaxa;
+		this.numChars= numChars;
+		matrices = new Vector(0);
+		firstMatrix = new Double2DArray(numChars, numTaxa); //no items yet
+		matrices.addElement(firstMatrix);
+	}
+	
+	public MContinuousAdjustable (Taxa taxa) {
+		super(taxa);
+		matrices = new Vector(0);
+	}
+	public MContinuousAdjustable () {
+		super(null);
+		matrices = new Vector(0);
+	}
+	public void setAnnotation(String s, boolean notify){
+		annotation = s;
+	}
+	public String getAnnotation(){
+		return annotation;
+	}
+	/*..........................................MContinuousAdjustable................*/
+	/**sets the parent CharacterData from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd){
+		data = cd;
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setSize(int numChars, int numTaxa) {
+		if (numChars!= this.numChars || numTaxa !=this.numTaxa) {
+			this.numTaxa= numTaxa;
+			this.numChars= numChars;
+			matrices = new Vector(0);
+			firstMatrix = new Double2DArray(numChars, numTaxa); //no items yet
+			matrices.addElement(firstMatrix);
+			ContinuousData data = (ContinuousData)getParentData();
+			if (data!=null) {
+				for (int i=0; i<data.getNumItems(); i++)
+					establishItem(data.getItemReference(i));
+			}
+		}
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public Double2DArray addItem(NameReference nr){
+		Double2DArray matrix = new Double2DArray(numChars, numTaxa);
+		if (firstMatrix == null)
+			firstMatrix = matrix;
+		if (nr!=null)
+			matrix.setNameReference(nr);
+		matrix.deassignArray();
+		matrices.addElement(matrix);
+		return matrix;
+	}
+	public Double2DArray addItem(String name){
+		return addItem(NameReference.getNameReference(name));
+	}
+	public Double2DArray establishItem(String name){
+		return establishItem(NameReference.getNameReference(name));
+	}
+	/*..........................................MContinuousAdjustable................*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Double2DArray establishItem(NameReference nr){
+		if (firstMatrix != null && firstMatrix.getNameReference()==null  && matrices.size() ==1) {
+			if (nr!=null)
+				firstMatrix.setNameReference(nr);
+			return firstMatrix;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				Double2DArray matrix = (Double2DArray)matrices.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(nr);
+					return matrix;
+				}
+			}
+			return addItem(nr);
+		}
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public int getNumberOfItems(){
+		return matrices.size();
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public Double2DArray getItem(int index){
+		if (index<0 || index >= getNumItems())
+			return null;
+		return (Double2DArray)matrices.elementAt(index);
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public String getItemName(int index){
+		if (index<0 || index >= getNumItems())
+			return null;
+		return ((Double2DArray)matrices.elementAt(index)).getName();
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((Double2DArray)matrices.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+
+	}
+	/*..........................................MContinuousAdjustable................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		Double2DArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		matrices.removeElement(matrix);
+		if (item == 0) {
+			firstMatrix = (Double2DArray)matrices.elementAt(0);
+		}
+	}
+	/*..........................................MContinuousAdjustable................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+			Double2DArray matrix =getItem(index);
+			matrix.setNameReference(nr);
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void deassignStates(){
+		for (int i=0; i<getNumItems(); i++){
+			Double2DArray matrix = getItem(i);
+			if (matrix !=null)
+				for (int k=0; k<numChars; k++)
+					for (int j=0; j<numTaxa; j++)
+						matrix.setValue(k, j, ContinuousState.unassigned); 
+		}
+	}
+	
+	/*..........................................MContinuousAdjustable................*/
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public void transferFrom(int ic, CharacterDistribution s) { 
+		if (s instanceof ContinuousDistribution) {
+			setItemsAs(((ContinuousDistribution)s));
+			for (int item=0; item<((ContinuousDistribution)s).getNumItems(); item++) {
+				Double2DArray matrix = getItem(item);
+				if (matrix !=null)
+					for (int j=0; j<getNumNodes(); j++)
+						matrix.setValue(ic, j,  ((ContinuousDistribution)s).getState(j, item));
+			}
+		}
+	}
+	
+	/*..........................................MContinuousAdjustable................*/
+	public double getState (int ic, int N, int item) {
+		
+		if (getItem(item)!=null)
+			return getItem(item).getValue(ic, N);
+		else
+			return MesquiteDouble.unassigned;
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setStates (Vector matrices) {
+		if (matrices==null)
+			return;
+		this.matrices = matrices;
+		firstMatrix = (Double2DArray)matrices.elementAt(0);
+		if (firstMatrix !=null) {
+			numTaxa = firstMatrix.getSizeT();
+			numChars = firstMatrix.getSizeC();
+		}
+		
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setStates (Double2DArray matrix) {
+		if (matrix==null)
+			return;
+		matrices.removeAllElements();
+		matrices.addElement(matrix);
+		firstMatrix = matrix;
+		if (firstMatrix !=null) {
+			numTaxa = firstMatrix.getSizeT();
+			numChars = firstMatrix.getSizeC();
+		}
+		
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setState (int ic, int N,  ContinuousState cs) {  //THIS SHOULD BE ic, it not it, ic
+		if (cs.getNumItems()> matrices.size())
+			return;
+		for (int item = 0; item<cs.getNumItems() && item< matrices.size(); item++){
+			Double2DArray matrix = (Double2DArray)matrices.elementAt(item);
+			matrix.setValue(ic,N, cs.getValue(item));
+		}
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setState (int ic, int N,  int item, double d) {  //THIS SHOULD BE ic, it not it, ic
+		if (item>= matrices.size())
+			return;
+		Double2DArray matrix = (Double2DArray)matrices.elementAt(item);
+		matrix.setValue(ic,N, d);
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public double getState (int ic, int N) {
+		return firstMatrix.getValue(ic, N);
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public void setState (int ic, int N, double d) {
+		firstMatrix.setValue(ic,N, d);
+	}
+	
+	/*..........................................  MContinuousAdjustable  ..................................................*
+	/**sets the character state of character ic and taxon it to that in the passed CharacterState*
+   	public void setCharacterState(CharacterState s, int ic, int it){
+   		if (s instanceof ContinuousState){
+   			ContinuousState cs = ((ContinuousState)s);
+			for (int item=0; item<getNumItems() && item<cs.getNumItems(); item++) {
+				Double2DArray matrix = (Double2DArray)matrices.elementAt(item);
+				matrix.setValue(ic, it, cs.getValue(item));
+			}
+   		}
+   	}
+	/*..........................................MContinuousAdjustable................*/
+   	/** sets the state of character ic in taxon it from CharacterState cs.  If incoming CharacterState has more items
+   	or items with names not seen in this ContinuousData, then new items are created in the ContinuousData*/
+   	public  void setCharacterState(CharacterState cs, int ic, int it){
+   		
+   		if (cs !=null && cs instanceof ContinuousState) {
+   			ContinuousState contS = (ContinuousState)cs;
+   			if (contS.getNumItems()==1 && getNumItems()==1 && (contS.getItemReference(0) == null || getItemReference(0) == null || contS.getItemReference(0) == getItemReference(0))){
+	   			setState(ic, it, 0, contS.getValue(0));  
+   			}
+   			else {
+	   			int made = 0;
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+	   					establishItem(nr.getValue());
+	   					made++;
+	   				}
+	   			}
+	   			int numToMake = contS.getNumItems() - getNumItems();
+	   			for (int i=0; i< numToMake; i++)
+	   				addItem((NameReference)null);
+	   			int currentOpen = 0;
+	   			//unnamed items in incoming character state will be applied to first available items whose names are not in incoming character state
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (getItemNumber(nr)>=0) {//named item found; set state
+	   					setState(ic, it, getItemNumber(nr), contS.getValue(i));  
+	   				}
+	   				else { //put it in next slot in this that has no corresponding in contS
+	   					boolean found = false;
+	   					for (int item = currentOpen; item<getNumItems() && !found; item++){
+	   						NameReference nrM = getItemReference(item);
+	   						if (nrM == null || contS.getItemNumber(nrM) < 0){
+	   							setState(ic, it, item, contS.getValue(i));
+	   							currentOpen = item+1;
+	   							found = true;
+	   						}
+	   					}
+	   				}
+	   			}
+   			}
+  		}
+   	}
+	/*..........................................MContinuousAdjustable................*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) { 
+		if (checkIllegalNode(it, 9132) && checkIllegalNode(it, 9133) && ic <numChars)
+			return;
+		for (int item=0; item<getNumItems(); item++) {
+			Double2DArray matrix = (Double2DArray)matrices.elementAt(item);
+			double temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic,it2));
+			matrix.setValue(ic, it2, temp);
+		}
+	}
+	/*..........................................MContinuousAdjustable................*/
+	public CharacterDistribution getCharacterDistribution (int ic) {
+		ContinuousAdjustable soc = new ContinuousAdjustable(getTaxa(), numTaxa);
+		soc.setItemsAs(this);
+		for (int it = 0; it<numTaxa; it++) {
+			for (int item=0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(ic, it, item)); 
+		}
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	public int getNumTaxa(){
+		return numTaxa;
+	}
+	public int getNumNodes(){ //TODO: a distinction should be made in Histories between taxa and nodes
+		return numTaxa;
+	}
+	public int getNumChars(){
+		return numChars;
+	}
+}
+
+
diff --git a/Source/mesquite/cont/lib/MContinuousDistribution.java b/Source/mesquite/cont/lib/MContinuousDistribution.java
new file mode 100644
index 0000000..e5861d6
--- /dev/null
+++ b/Source/mesquite/cont/lib/MContinuousDistribution.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.categ.lib.MProteinHistory;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  continuous character states for many characters, at each of the taxa or nodes.*/
+public abstract class MContinuousDistribution  extends MContinuousStates implements MCharactersDistribution {
+	public MContinuousDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................MContinuousDistribution................*/
+	public abstract CharacterDistribution getCharacterDistribution (int ic);
+	/*-----*/
+	/*..........................................MContinuousDistribution................*/
+	public abstract Double2DArray getItem(int index);
+	/*..........................................MContinuousDistribution................*/
+	/**return blank adjustable MContinuousDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		MContinuousAdjustable mca = new MContinuousAdjustable(getTaxa(), getNumChars(), getNumNodes()); 
+		mca.setItemsAs(this);
+		return mca;
+	}
+	/*..........................................MContinuousDistribution................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		ContinuousData data = new ContinuousData(manager, taxa.getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this); 
+		if (this instanceof Annotatable && ((Annotatable)this).getAnnotation()!=null)
+			data.setAnnotation(((Annotatable)this).getAnnotation(), false);
+		else if (getParentData()!=null && getParentData().getAnnotation()!=null)
+			data.setAnnotation(getParentData().getAnnotation(), false);
+		return data;
+	}
+	/*..........................................MContinuousDistribution................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MContinuousHistory.class)) 
+			soc = new MContinuousHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MContinuousHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		((MContinuousHistory)soc).setItemsAs(this);
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
diff --git a/Source/mesquite/cont/lib/MContinuousEmbedded.java b/Source/mesquite/cont/lib/MContinuousEmbedded.java
new file mode 100644
index 0000000..aa7baf7
--- /dev/null
+++ b/Source/mesquite/cont/lib/MContinuousEmbedded.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  continuous character states for many characters, at each of the taxa or nodes.*/
+public class MContinuousEmbedded  extends MContinuousDistribution {
+	
+	public MContinuousEmbedded (CharacterData data) {
+		super(data.getTaxa());
+		this.data = data;
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public Double2DArray getItem(int index){
+		return ((ContinuousData)data).getItem(index);
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public String getItemName(int index){
+		return ((ContinuousData)data).getItemName(index);
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public int getItemNumber(NameReference nr){
+		return ((ContinuousData)data).getItemNumber(nr);
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public  int getNumberOfItems() {
+		return ((ContinuousData)data).getNumItems();
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public  double getState (int ic, int N,  int item){
+		return ((ContinuousData)data).getState(ic, N, item);
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public  double getState (int ic, int N){
+		return getState(ic, N, 0); 
+	}
+	/*..........................................MContinuousEmbedded................*/
+	public CharacterDistribution getCharacterDistribution (int ic){
+		return data.getCharacterDistribution(ic);
+	}
+	public int getNumTaxa(){
+		return data.getNumTaxa();
+	}
+	public int getNumNodes(){
+		return data.getNumTaxa();
+	}
+	public int getNumChars(){
+		return data.getNumChars();
+	}
+	public String getName(){
+		return data.getName();
+	}
+}
+
diff --git a/Source/mesquite/cont/lib/MContinuousHistory.java b/Source/mesquite/cont/lib/MContinuousHistory.java
new file mode 100644
index 0000000..bf4f74e
--- /dev/null
+++ b/Source/mesquite/cont/lib/MContinuousHistory.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+/* ======================================================================== */
+/**A class for an array of  continuous character states for many characters, at each of the nodes.*/
+public class MContinuousHistory  extends MContinuousAdjustable implements MCharactersHistory {
+	
+	public MContinuousHistory (Taxa taxa, int numChars, int numNodes) {
+		super(taxa, numChars, numNodes);
+	}
+	
+	public MContinuousHistory (Taxa taxa) {
+		super(taxa);
+	}
+	
+	/*..........................................MContinuousHistory................*/
+	/** extract the states of character ic and return as CharacterHistory*/
+	public CharacterHistory getCharacterHistory (int ic){
+		ContinuousHistory soc = new ContinuousHistory(getTaxa(), getNumNodes(), (ContinuousData)getParentData());
+		soc.setItemsAs(this);
+		for (int it = 0; it<getNumNodes(); it++) {
+			for (int item=0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(ic, it, item)); 
+		}
+		return soc;
+	}
+	/*..........................................MContinuousHistory................*/
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public void transferFrom(int ic, CharacterHistory s) { 
+		if (s instanceof ContinuousHistory) {
+			setItemsAs(((ContinuousHistory)s));
+			for (int j=0; j<getNumNodes(); j++)
+				for (int item=0; item<((ContinuousHistory)s).getNumItems(); item++) {
+					if (getItem(item)!=null)
+						getItem(item).setValue(ic, j,  ((ContinuousHistory)s).getState(j, item));
+				}
+		}
+	}
+	double minState = MesquiteDouble.unassigned;
+	double maxState = MesquiteDouble.unassigned;
+	/*..........................................MContinuousHistory................*/
+	private void calcMinMaxStates(Tree tree, int node, int item) {
+		for (int ic=0; ic<getNumChars(); ic++){
+			double s=getState(ic, node, item); 
+			minState = MesquiteDouble.minimum(s, minState);
+			maxState = MesquiteDouble.maximum(s, maxState);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				calcMinMaxStates(tree, d, item);
+	}
+	public void getMinMax(Tree tree, int root, int item, MesquiteDouble min, MesquiteDouble max){
+		if (min == null || max==null)
+			return;
+		minState = MesquiteDouble.unassigned;
+		maxState = MesquiteDouble.unassigned;
+		calcMinMaxStates(tree, root, item);
+		min.setValue(minState);
+		max.setValue(maxState);
+	}
+}
+
diff --git a/Source/mesquite/cont/lib/MContinuousStates.java b/Source/mesquite/cont/lib/MContinuousStates.java
new file mode 100644
index 0000000..6e69f24
--- /dev/null
+++ b/Source/mesquite/cont/lib/MContinuousStates.java
@@ -0,0 +1,136 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  continuous character states for many characters, at each of the taxa or nodes.*/
+public abstract class MContinuousStates extends MCharactersStates implements ItemContainer {
+	long id;
+	static long totalCreated = 0;
+	public MContinuousStates (Taxa taxa) {
+		super(taxa);
+		totalCreated++;
+		id = totalCreated;
+	}
+	
+	public long getID(){
+		return id;
+	}
+	/*..........................................  MContinuousStates  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return ContinuousState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return ContinuousData.class;
+	}
+	/*..........................................  MContinuousStates  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return ContinuousData.DATATYPENAME;
+	}
+	/*..........................................  MContinuousStates  ..................................................*/
+	/**returns state of character ic in taxon/node it */
+	public abstract double getState (int ic, int it);
+
+	/*..........................................MContinuousStates................*/
+	/**returns state of item item of character ic in taxon/node it */
+	public abstract double getState (int ic, int it, int item);
+	
+	/*..........................................MContinuousStates................*/
+	public abstract Double2DArray getItem(int index);
+	
+	/*..........................................MContinuousStates................*/
+	public double[][] getMatrix(int index){
+		Double2DArray m2da = getItem(index);
+		if (m2da==null)
+			return null;
+		return m2da.getMatrix();
+	}
+	/*..........................................MContinuousStates................*/
+   	public int userQueryItem(String message, MesquiteModule module){
+		int numItems =getNumItems();
+		String[] items = new String[numItems];
+		for (int i=0; i<items.length; i++){
+			if (StringUtil.blank(getItemName(i)))
+				items[i] = "(unnamed)";
+			else
+				items[i]= getItemName(i);
+		}
+		return ListDialog.queryList(module.containerOfModule(), "Select item", message, MesquiteString.helpString,  items, 0);
+   	}
+	/*..........................................MContinuousStates................*/
+	public abstract String getItemName(int index);
+	/*..........................................MContinuousStates................*/
+	public abstract int getItemNumber(NameReference nr);
+	/*..........................................MContinuousStates................*/
+	public abstract int getNumberOfItems();
+	/*..........................................MContinuousStates................*/
+	public int getNumItems(){
+		return getNumberOfItems();
+	}
+	/*..........................................MContinuousStates................*/
+	public boolean allCombinable(){
+		for (int item = 0; item < getNumberOfItems(); item ++)
+			for (int ic = 0; ic < getNumChars(); ic++)
+				for (int it = 0; it<getNumNodes(); it++) {
+					if (!MesquiteDouble.isCombinable(getState(ic, it, item)))
+						return false;
+				}
+		return true;
+	}
+	/*..........................................MContinuousStates................*/
+	public boolean allCombinable(int item){
+		for (int ic = 0; ic < getNumChars(); ic++)
+			for (int it = 0; it<getNumNodes(); it++) {
+				if (!MesquiteDouble.isCombinable(getState(ic, it, item)))
+					return false;
+			}
+		return true;
+	}
+	/*..........................................MContinuousStates................*/
+	public NameReference getItemReference(int n){
+		return NameReference.getNameReference(getItemName(n));
+	}
+	/*..........................................MContinuousStates................*/
+	public NameReference getItemReference(String name){
+		return NameReference.getNameReference(name);
+	}
+	/*..........................................MContinuousStates................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		ContinuousState c;
+		if (cs !=null && cs instanceof ContinuousState)
+			c = (ContinuousState)cs;
+		else
+			c = new ContinuousState(); 
+		c.setItemsAs(this);
+		for (int item = 0; item<getNumberOfItems(); item++)
+			c.setValue(item, getState(ic, it, item));
+		return c;
+	}
+	/*..........................................MContinuousDistribution................*/
+   	public String toString(){
+   		return "Continuous matrix (" + getClass().getName() + ") id: " + getID() + " chars: " + getNumChars() + " taxa: " + getNumTaxa() + " items " + getNumItems();
+   	}
+}
+
diff --git a/Source/mesquite/cont/lib/MGeographicStates.java b/Source/mesquite/cont/lib/MGeographicStates.java
new file mode 100644
index 0000000..49af5e9
--- /dev/null
+++ b/Source/mesquite/cont/lib/MGeographicStates.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  geographic character states for many characters, at each of the taxa or nodes.*/
+public abstract class MGeographicStates extends MContinuousStates {
+	public MGeographicStates (Taxa taxa) {
+		super(taxa);
+	}
+	
+	/*..........................................  MGeographicStates  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return GeographicStates.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return GeographicData.class;
+	}
+	/*..........................................  MGeographicStates  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return "Geographic Data";
+	}
+	/*.......................................................*/
+   	public String toString(){
+   		return "Geographic matrix (" + getClass().getName() + ") id: " + getID() + " chars: " + getNumChars() + " taxa: " + getNumTaxa() + " items " + getNumItems();
+   	}
+}
+
diff --git a/Source/mesquite/cont/lib/ManageContCharsA.java b/Source/mesquite/cont/lib/ManageContCharsA.java
new file mode 100644
index 0000000..a40007d
--- /dev/null
+++ b/Source/mesquite/cont/lib/ManageContCharsA.java
@@ -0,0 +1,337 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== 
+Manages continuous data matrices  */
+public abstract class ManageContCharsA extends CharMatrixManager {
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	public Class getStateClass(){
+		return ContinuousState.class;
+	}
+	/*.................................................................................................................*/
+	public Class getDataClass(){
+		return ContinuousData.class;
+	}
+	/*.................................................................................................................*/
+	public  String getDataClassName(){
+		return ContinuousData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		if (taxa == null)
+			return null;
+		return new ContinuousData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == ContinuousData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("Continuous");
+	}
+	/*.................................................................................................................*/
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments) {
+
+		ContinuousData data= null;
+		//@@@@@@@@@@@@@@@@@@@@
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+
+		if (fuse){
+			String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+			data = (ContinuousData)getProject().chooseData(containerOfModule(), null, taxa, getStateClass(), message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+			if (data != null && numChars > data.getNumChars())
+				data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+			if (data != null)
+				file.characterDataNameTranslationTable.addElement(new MesquiteString(title, data.getName()), false);
+		}
+		if (data == null){
+			data= (ContinuousData)getNewData(taxa,numChars);
+			if (fuse)
+				data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+		}
+		else {
+			if (fuse)
+				data.setSuppressSpecssetReading(true);
+			data.suppressChecksum = true;
+		}
+		data.interleaved = false;   //reset default in case this is fused
+
+		//@@@@@@@@@@@@@@@@@@@@
+		String tok = ParseUtil.getToken(formatCommand, stringPos);
+		while (!tok.equals(";")) {
+			if (tok.equalsIgnoreCase("ITEMS")) {
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting rid of "="
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting rid of "("
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting first item name
+				while (tok != null && !tok.equals(")")) {
+					if ("unnamed".equalsIgnoreCase(tok))
+						tok = null;
+					data.establishItem(tok);
+					tok = ParseUtil.getToken(formatCommand, stringPos); //getting item name
+				}
+
+			}
+			else if (tok.equalsIgnoreCase("format")) { 
+			}
+			else if (tok.equalsIgnoreCase("TRANSPOSE")) {
+				alert("Sorry, Transposed matrices of continuous characters can't yet be read");
+				return null;
+			}
+			else if (tok.equalsIgnoreCase("interleave")) {
+				int sp = stringPos.getValue();
+				String e = ParseUtil.getToken(formatCommand, stringPos); //eating up = ?
+				if ("=".equals(e)){
+					String y = ParseUtil.getToken(formatCommand, stringPos); //yes or no ?
+					data.interleaved = ("yes".equalsIgnoreCase(y));
+						
+				}
+				else {
+					stringPos.setValue(sp);
+					data.interleaved = true;
+				}
+			}
+			else if (tok.equalsIgnoreCase("MISSING")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setUnassignedSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("DATATYPE")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				ParseUtil.getToken(formatCommand, stringPos); //eating up datatype
+				//alert("Error in NEXUS file format: DATATYPE subcommand must appear as the first item in the FORMAT command");
+				//return null;
+			}
+			else if (tok.equalsIgnoreCase("GAP")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setInapplicableSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("MATCHCHAR")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setMatchChar(t.charAt(0));
+			}
+			else {
+				alert("Unrecognized token (\"" + tok+ "\") in FORMAT statement of continuous matrix; matrix will be stored as foreign, and not processed.");
+				return null;
+			}
+			tok = ParseUtil.getToken(formatCommand, stringPos);
+		}
+
+		return data;
+	}
+	/*.................................................................................................................*/
+	public boolean processCommand(CharacterData data, String commandName, String commandString) {
+		if ("CHARSTATELABELS".equalsIgnoreCase(commandName)){
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			String cN = ParseUtil.getToken(commandString, startCharT); //eating up command name
+			cN = ParseUtil.getToken(commandString, startCharT);
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+				String charName = (ParseUtil.getToken(commandString, startCharT));
+				if (!charName.equals(",")) {
+					data.setCharacterName(charNumber-1, charName);
+					String stateName = ParseUtil.getToken(commandString, startCharT); // eat up slash
+					int stateNumber = 0;
+					while (stateName!=null && !stateName.equals(",") &&!stateName.equals(";")) { //skipping state names as they don't make any sense for continuous!
+						stateName = (ParseUtil.getToken(commandString, startCharT));
+						stateNumber++;
+					}
+				}
+				cN = ParseUtil.getToken(commandString, startCharT);
+			}
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getCharStateLabels(CharacterData data, MesquiteFile file) {
+		if (file.writeCharLabels){
+			String csl = "CHARLABELS " + StringUtil.lineEnding();
+			boolean found = false;
+			for (int i = 0; i<data.getNumChars(); i++) {
+				if (data.characterHasName(i)) {
+					found = true;
+					csl += " " + StringUtil.tokenize(data.getCharacterName(i));
+				}
+				else {
+					csl += " _";
+				}
+			}
+			if (found)
+				return csl + " ; " + StringUtil.lineEnding();
+			else
+				return "";
+		}
+		if (file.useSimplifiedNexus) //1. 12 so that MrBayes won't choke on exported file
+			return "";
+		String csl = "CHARSTATELABELS " + StringUtil.lineEnding();
+		boolean found = false;
+		for (int i = 0; i<data.getNumChars(); i++) {
+			String cslC="";
+			if (i>0 && found)
+				cslC += "," + StringUtil.lineEnding();
+			cslC += "\t\t" + Integer.toString(i+1) + " ";    //i+1 to convert to 1 based
+			boolean foundInCharacter = false;
+			if (data.characterHasName(i)) {
+				foundInCharacter = true;
+				cslC += StringUtil.tokenize(data.getCharacterName(i));
+			}
+			if (foundInCharacter) {
+				csl += cslC;
+				found = true;
+			}
+		}
+		if (found)
+			return csl + " ; " + StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public String getDataTypeString() {
+		return "CONTINUOUS";
+	}
+	/*.................................................................................................................*/
+	public void writeCharactersBlock(CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator){
+		ContinuousData cData = (ContinuousData)data;
+		//StringBuffer blocks = new StringBuffer(cData.getNumChars()*cData.getNumTaxa()*10*cData.getNumItems());
+		StringBuffer line = new StringBuffer(cData.getNumChars()*10*cData.getNumItems());
+		file.write("BEGIN CHARACTERS");
+		if (data.getAnnotation()!=null && !file.useSimplifiedNexus) 
+			file.write("[!" + StringUtil.tokenize(data.getAnnotation()) + "]");
+		
+		file.write(";" + StringUtil.lineEnding());
+		if (cData.getName()!=null &&  (getProject().getNumberCharMatrices()>1 || ((file==null || (!file.useSimplifiedNexus &&  !file.useConservativeNexus)) && !NexusBlock.suppressTITLE))){
+			file.write("\tTITLE  " + StringUtil.tokenize(cData.getName()) + ";" + StringUtil.lineEnding());
+		}
+
+		if (cData.getTaxa().getName()!=null  && getProject().getNumberTaxas()>1){ //should have an isUntitled method??
+			file.write("\tLINK TAXA = " +  StringUtil.tokenize(cData.getTaxa().getName()) + ";" + StringUtil.lineEnding());
+		}
+		file.write("\tDIMENSIONS ");
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = cData.getNumChars();
+		else
+			numCharsToWrite = cData.getNumCharsIncluded();
+		file.write(" NCHAR=" + numCharsToWrite);
+		file.write(";" + StringUtil.lineEnding());
+		file.write("\tFORMAT");
+		file.write(" DATATYPE = " + getDataTypeString());
+		if (cData.getNumItems()>0 && !(cData.getNumItems()==1 && cData.getItemName(0) ==null)) {
+			file.write(" ITEMS = (");
+			for (int i=0; i<cData.getNumItems(); i++) {
+				String iName = cData.getItemName(i);
+				if (iName == null)
+					file.write("unnamed ");
+				else
+					file.write(iName + " ");
+			}
+			file.write(") ");
+		}
+		file.write(" GAP = " + data.getInapplicableSymbol() + " MISSING = " + data.getUnassignedSymbol());
+		file.write(";" + StringUtil.lineEnding());
+		if (data.isLinked() && !file.useSimplifiedNexus  && !file.useConservativeNexus){
+			file.write("\tOPTIONS ");
+			Vector ds = data.getDataLinkages();
+			for (int i = 0; i<ds.size(); i++) {
+				file.write(" LINKCHARACTERS = ");
+				file.write(StringUtil.tokenize(((CharacterData)ds.elementAt(i)).getName()));
+			}
+			file.write(";" + StringUtil.lineEnding());
+		}
+		file.write(getCharStateLabels(cData, file));
+		file.write("\tMATRIX" + StringUtil.lineEnding());
+		String taxonName="";
+		int maxNameLength = cData.getTaxa().getLongestTaxonNameLength();
+		for (int it=0; it<cData.getTaxa().getNumTaxa(); it++) {
+			if ((data.someApplicableInTaxon(it, false)|| file.writeTaxaWithAllMissing) && (!file.writeOnlySelectedTaxa || data.getTaxa().getSelected(it))){
+				taxonName = cData.getTaxa().getTaxon(it).getName();
+				if (file.useStandardizedTaxonNames)
+					taxonName = "t" + it;
+				else
+					taxonName = StringUtil.simplifyIfNeededForOutput(taxonName,file.simplifyNames);
+				if (taxonName!=null) {
+					file.write("\t"+ taxonName);
+					for (int i = 0; i<(maxNameLength-taxonName.length()+2); i++)
+						file.write(" ");
+				}
+				line.setLength(0);
+				for (int ic=0;  ic<cData.getNumChars(); ic++)  {
+					if (data.isCurrentlyIncluded(ic) || file.writeExcludedCharacters) {
+						line.append(' ');
+						cData.statesIntoNEXUSStringBuffer(ic, it, line);
+					}
+				}
+				file.write(line.toString());
+				file.write(StringUtil.lineEnding());
+			}
+		}
+		file.write(StringUtil.lineEnding()+ ";");
+		file.write( StringUtil.lineEnding());
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus){
+			String idsCommand = getIDsCommand(data);
+			if (!StringUtil.blank(idsCommand))
+				file.write("\t" + idsCommand + StringUtil.lineEnding());
+		}
+		if (cB != null) file.write(cB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		file.write("END");
+		file.write(";" + StringUtil.lineEnding());
+
+		//file.write( blocks.toString());
+	}
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage Continuous char. matrices";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages continuous data matrices (including read/write in NEXUS file)." ;
+   	 }
+}
+	
+	
+
diff --git a/Source/mesquite/cont/lib/SquaredReconstructor.java b/Source/mesquite/cont/lib/SquaredReconstructor.java
new file mode 100644
index 0000000..4391c6e
--- /dev/null
+++ b/Source/mesquite/cont/lib/SquaredReconstructor.java
@@ -0,0 +1,430 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.cont.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/*=========================================================================*/
+/** This class reconstructs ancestral states by squared change parsimony for a matrix of observed data and a tree.
+This operates on a simple double[][] instead of a MContinuousDistribution.*/
+public class SquaredReconstructor {
+	boolean rootedMode = true;
+	boolean useWeights = false;
+	double[][] observedStates;
+	ContinuousDistribution observedDistribution;
+	double[][] reconstructedStates;
+	Tree tree;
+	double[][] downA;
+	double[][] downB;
+	double[][] upA;
+	double[][] upB;
+	double[][][] finalC;
+	double[][] finalD;
+	int item = 0;
+	int alreadyWarnedZeroLength = 0;
+	MesquiteDouble temp1, temp2, temp3;
+	double[] minSQLength;
+	int numChars = 0;
+	int numItems = 1;
+	boolean reconstructed = false;
+	boolean[] deleted;
+	public SquaredReconstructor(){
+		temp1 = new MesquiteDouble(0);
+ 		temp2 = new MesquiteDouble(0);
+ 		temp3 = new MesquiteDouble(0);
+	}
+	public void reconstruct(Tree tree, double[][] observedStates, boolean weighted, boolean rootedMode, boolean[] deletedTaxa){
+		//NOTE: rootedMode == false not yet supported
+		if (!rootedMode)
+			MesquiteMessage.warnProgrammer("SquaredReconstructor error: rootedMode == false not yet supported");
+		if (observedStates!=null && tree!=null && !(tree.nodeIsPolytomous(tree.getRoot()) && !rootedMode)){
+			this.deleted = deletedTaxa;
+			this.observedStates = observedStates;
+			observedDistribution=null;
+			useWeights = weighted;
+			this.rootedMode = rootedMode;
+			this.tree = tree;
+			numChars = observedStates.length;
+			numItems =1;
+			doReconstruct();
+ 		}
+ 		else
+ 			reconstructed = false;
+	}
+	public void reconstruct(Tree tree, ContinuousDistribution observedDistribution, boolean weighted, boolean rootedMode, boolean[] deletedTaxa){
+		if (!rootedMode)
+			MesquiteMessage.warnProgrammer("SquaredReconstructor error: rootedMode == false not yet supported");
+		if (observedDistribution!=null && tree!=null && !(tree.nodeIsPolytomous(tree.getRoot()) && !rootedMode)){
+			this.deleted = deletedTaxa;
+			this.observedDistribution = observedDistribution;
+			observedStates=null;
+			useWeights = weighted;
+			this.rootedMode = rootedMode;
+			this.tree = tree;
+			numChars = 1;
+			numItems = observedDistribution.getNumItems();
+			doReconstruct();
+ 		}
+ 		else
+ 			reconstructed = false;
+	}
+	synchronized void doReconstruct(){
+		
+		
+		
+		if (downA==null || downA.length!=numChars || downA[0]==null || downA[0].length != tree.getNumNodeSpaces()){
+			downA=  new double[numChars][tree.getNumNodeSpaces()];
+			downB=  new double[numChars][tree.getNumNodeSpaces()];
+			upA= new double[numChars][tree.getNumNodeSpaces()];
+			upB= new double[numChars][tree.getNumNodeSpaces()];
+			finalD=  new double[numChars][tree.getNumNodeSpaces()];
+	 		finalC= new double[numItems][numChars][tree.getNumNodeSpaces()];
+	 		minSQLength = new double[numChars];
+ 		}
+ 		else if (finalC==null || finalC.length!=numItems){
+	 		finalC= new double[numItems][numChars][tree.getNumNodeSpaces()];
+ 		}
+ 		Double2DArray.zeroArray(downA);
+ 		Double2DArray.zeroArray(downB);
+ 		Double2DArray.zeroArray(upA);
+ 		Double2DArray.zeroArray(upB);
+ 		Double2DArray.zeroArray(finalD);
+ 		DoubleArray.zeroArray(minSQLength);
+ 
+		for (int itemT = 0; itemT<numItems; itemT++) { //NOTE THIS relies on the variable item!  reentrancy problems could arise...
+	 		item = itemT;
+	 		if (statesLegal(tree, tree.getRoot(deleted))){
+	 			Double2DArray.zeroArray(finalC[item]);
+				minSQReconstruct(tree);
+			}
+			else {
+	 			Double2DArray.deassignArray(finalC[item]);
+ 			}
+		}
+		reconstructed = true;
+	}
+	public double[][] getReconstructedStates(int item){
+		
+		if (reconstructed) {
+			if (finalC !=null && item< finalC.length)
+				return Double2DArray.clone(finalC[item]);
+			MesquiteMessage.warnProgrammer("Error: item " + item + " requested  in getReconstructedStates of SquaredReconstructor, but that item was not calculated " + finalC);
+		}
+		return null;
+	}
+	public void placeReconstructedStates(ContinuousHistory statesAtNodes){
+		if (statesAtNodes==null)
+			return;
+		if (tree == null || !reconstructed){
+			statesAtNodes.deassignStates();
+			return;
+		}
+		for (int item = 0; item<  numItems; item++) {
+			transferStatesAtNode(tree.getRoot(deleted), tree, statesAtNodes, item);
+		}
+	}
+
+	public   void transferStatesAtNode(int N, Tree tree, ContinuousHistory statesAtNodes, int item) {
+		for (int d = tree.firstDaughterOfNode(N, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted))
+			transferStatesAtNode(d, tree, statesAtNodes, item);
+		statesAtNodes.setState(N, item, finalC[item][0][N]);
+	}
+	public boolean statesLegal(Tree tree, int node) {
+		if (tree.nodeIsTerminal(node)) {
+			for (int ic = 0; ic<numChars; ic++)
+				if (!ContinuousState.isCombinable(getObservedState(item, ic, tree.taxonNumberOfNode(node))))
+					return false;
+			return true;
+		}
+		for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted))
+			if (!statesLegal(tree, d))
+				return false;
+		return true;
+	}
+	 double getObservedState(int item, int ic, int it){
+		if (observedStates==null)
+			return observedDistribution.getState(it, item);
+		else if (ic>=0 && it>= 0 && ic<observedStates.length && it< observedStates[0].length)
+			return observedStates[ic][it];
+		return 0;
+	}
+	public double[] getSumSquaredLengths(){
+		return DoubleArray.clone(minSQLength);
+	}
+   	double Sqr(double d) {
+   		return d * d;
+   	}
+	/*_____________________________________________________________________ */
+	double branchWeight (Tree tree, int N){ 
+		double weight;
+		if (useWeights) {
+			if (N == tree.getRoot(deleted)) { /*asking for weight across root for unrooted case*/
+				if (rootedMode || tree.nodeIsPolytomous(tree.getRoot(deleted)))
+					return 0;
+				int L = tree.firstDaughterOfNode(N, deleted);
+				int R = tree.lastDaughterOfNode(N, deleted);
+				if (tree.branchLengthUnassigned(L, deleted))
+					weight=branchWeight(tree,R);
+				else if (tree.branchLengthUnassigned(R, deleted))
+					weight=branchWeight(tree,L);
+				else
+					weight=tree.getBranchLength(L, deleted) +tree.getBranchLength(R, deleted);
+			}
+			else if (tree.branchLengthUnassigned(N, deleted)) 
+				weight=1.0;
+			else
+				weight=tree.getBranchLength(N, deleted) ;
+		}
+		else
+			weight=1.0;
+			
+		if (weight==0) {
+			weight=1.0;
+			if (alreadyWarnedZeroLength<5)
+				MesquiteTrunk.mesquiteTrunk.discreetAlert(MesquiteThread.isScripting() || alreadyWarnedZeroLength>0, "Branch weight of zero found in SquaredReconstructor.  Will be treated as 1");
+			alreadyWarnedZeroLength++;
+		}
+		return(weight);
+	}
+	/*.................................................................................................................*/
+	void addABCdown (Tree tree, MesquiteDouble A,  MesquiteDouble B,  MesquiteDouble C, int N, double WtdN, int ic) {
+		if (tree.nodeIsTerminal(N)){   /*terminal, add 1, -2b, c2*/
+			double ts = getObservedState(item, ic, tree.taxonNumberOfNode(N));
+			if (!MesquiteDouble.isCombinable(ts))
+				return;
+			A.add(1.0 / WtdN);
+			B.subtract( 2.0 * (ts) / WtdN);
+			C.add( ts*ts / WtdN);
+		}
+		else {   /*internal, add a/(a+1), b/(a+1), b2/(4(a+1))-c*/
+			if (!MesquiteDouble.isCombinable(downA[ic][N]) || !MesquiteDouble.isCombinable(downB[ic][N]) || !MesquiteDouble.isCombinable(finalC[item][ic][N]))
+				return;
+			A.add(downA[ic][N] / (downA[ic][N] * WtdN + 1.0));
+			B.add(downB[ic][N] / (downA[ic][N] * WtdN + 1.0));
+			C.add(finalC[item][ic][N] - (Sqr(downB[ic][N]) / 4.0 / (downA[ic][N] + 1.0 / WtdN)));
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*visits all descendants of dN, whether dN is polytomous or not, */
+	/*and accumulates three parameters of downpass for dN*/
+	void AddABCAllDescendants (Tree tree, MesquiteDouble A, MesquiteDouble B, MesquiteDouble C, int N, int ic) {
+		int sisRight, lastDone;
+		lastDone = tree.firstDaughterOfNode(N, deleted);
+		addABCdown(tree, A, B, C, lastDone, branchWeight(tree,lastDone), ic);
+		sisRight = tree.nextSisterOfNode(lastDone, deleted);
+		while (tree.nodeExists(sisRight)) {
+			addABCdown(tree, A, B, C, sisRight, branchWeight(tree,sisRight), ic);
+			lastDone = sisRight;
+			sisRight = tree.nextSisterOfNode(sisRight, deleted);
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*..................The downpass of squared parsimony...........................*/
+	void SquareDown (Tree tree, int N, int ic) {
+		downA[ic][N] = MesquiteDouble.unassigned;/*initialize three parameters to 0*/
+		downB[ic][N] = MesquiteDouble.unassigned;
+		finalC[item][ic][N] = MesquiteDouble.unassigned;
+		if (tree.nodeIsInternal(N)) {  
+			for (int daughter = tree.firstDaughterOfNode(N, deleted); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter, deleted))
+				SquareDown(tree, daughter, ic);
+			if (tree.nodeExists(N)) {
+				temp1.setToUnassigned();
+				temp2.setToUnassigned();
+				temp3.setToUnassigned();
+				AddABCAllDescendants(tree, temp1, temp2, temp3, N, ic);
+				downA[ic][N] = (temp1.getValue());/*initialize three parameters to 0*/
+				downB[ic][N] = (temp2.getValue());
+				finalC[item][ic][N] = (temp3.getValue());
+			}
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*This procedure adds downpass parameters of dN to running total of parameters A,B*/
+	void AddABDown (Tree tree, MesquiteDouble A, MesquiteDouble B, int N, double wt, int ic) {
+		if (tree.nodeIsTerminal(N))  {  /*Terminal, add 1, -2b*/
+			double ts= getObservedState(item, ic, tree.taxonNumberOfNode(N));
+			if (!MesquiteDouble.isCombinable(ts)) 
+				return;
+			A.add(1.0 / wt);
+			B.add(-2.0 * (ts) / wt);
+		}
+		else  {/*internal, add a/(a+1), b/(a+1)*/
+			double dA = downA[ic][N];
+			if (!MesquiteDouble.isCombinable(dA) || !MesquiteDouble.isCombinable(downB[ic][N]))
+				return;
+			A.add( dA/ (dA * wt + 1));
+			B.add( downB[ic][N] / (dA * wt + 1));
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*..................The uppass & final pass of squared parsimony...........................*/
+	void SquareFinal (Tree tree, int N, int ic) {
+		int sister, sisright, lastdone, Nanc;
+		if (N == tree.getRoot(deleted))  {
+			for (int daughter = tree.firstDaughterOfNode(N, deleted); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter, deleted))
+				SquareFinal(tree, daughter, ic);
+			if (!rootedMode) 
+				finalC[item][ic][N] = (MesquiteDouble.unassigned);
+			else if (downA[ic][N] == 0)  {
+				finalC[item][ic][N] = (0);
+			}
+			else if (MesquiteDouble.isCombinable(downA[ic][N]) && MesquiteDouble.isCombinable(downB[ic][N])&& MesquiteDouble.isCombinable(finalC[item][ic][N]))
+				finalC[item][ic][N] = (downB[ic][N]/(-2.0* downA[ic][N]));  /*most parsimonious at root; p. 9 of resubmission*/
+		}
+		else if (tree.nodeIsInternal(N) && MesquiteDouble.isCombinable(downA[ic][N]) && MesquiteDouble.isCombinable(downB[ic][N])){
+			/*now we need to poll descendant nodes and nodes below by adding up their contributions*/
+			/*to the first and second parameters (final) at N*/
+			/*FIRST look to contribution from ABOVE*/
+
+			finalC[item][ic][N] = (downA[ic][N]);  /*additions from above already summed in nb->downA and downB*/
+			finalD[ic][N] = (downB[ic][N]);
+
+			/*Now look to contribution from BELOW*/
+			 Nanc = tree.motherOfNode(N, deleted);
+			if (Nanc == tree.getRoot(deleted)) {  /*ancestor is root*/
+				if (rootedMode) { /*----- rooted ----*/
+					/***since just above root, uppass states from below are just sum*/
+					/*of downpass states from all sisters, which can be found by taking tree.getRoot()'s down and*/
+					/*subtracting what had been N's contribution, so as to leave contribution of sisters.*/
+					/*Unlike the case with other parsimony algorithms*/
+					/*this can be done because everything is additive*/
+					upA[ic][N] = (downA[ic][Nanc] - (downA[ic][N] / (downA[ic][N] * branchWeight(tree,N) +  1)));
+					upB[ic][N] = (downB[ic][Nanc] - (downB[ic][N] / (downA[ic][N] * branchWeight(tree,N) +  1)));
+
+					/*this calculation adds to finals the contribution from below*/
+					/*(other side of root), using a/(a+1) etc to add effect of the root node*/
+					finalC[item][ic][N] = (finalC[item][ic][N]+ upA[ic][N] / ( upA[ic][N] * branchWeight(tree,N) +  1));
+					finalD[ic][N] = (finalD[ic][N] + upB[ic][N] / ( upA[ic][N] * branchWeight(tree,N) +  1));
+				}
+				else  {/*----- unrooted -----*/
+					/*not rooted, thus use sister's downs directly, without extra calculation to add root*/
+					 sister = tree.nextSisterOfNode(N, deleted);
+					if (!tree.nodeExists(sister))
+						sister = tree.previousSisterOfNode(N, deleted);
+
+					if (tree.nodeIsTerminal(sister)) {
+						upA[ic][N] = (-2); /*send signal that sister was terminal*/
+						upB[ic][N] = getObservedState(item, ic, tree.taxonNumberOfNode(sister));/*store observed state in sister*/
+					}
+					else {
+						upA[ic][N] = (downA[ic][sister]); 
+						upB[ic][N] = (downB[ic][sister]);
+					}
+					/*now we add to finals the contribution from below*/
+					temp1.setValue(finalC[item][ic][N]);
+					temp2.setValue(finalD[ic][N]);
+					double weight;
+					if (tree.nodeIsPolytomous(tree.getRoot(deleted)))
+						weight = branchWeight(tree,N);
+					else
+						weight = branchWeight(tree,tree.getRoot(deleted));
+					AddABDown(tree, temp1, temp2, sister, weight, ic);  /*contribution across root*/
+					finalC[item][ic][N] = (temp1.getValue());
+					finalD[ic][N] = (temp2.getValue());
+				}
+			}
+			else { /*N is not Root; Nanc is not Root; internal node*/
+				if (upA[ic][Nanc] < -1.5) { /*receive signal that sister at root was terminal and unrooted*/
+					upA[ic][N] = (1 / (branchWeight(tree,tree.getRoot(deleted))));  /*contribution from Anc(N); from terminal sister across unroot*/
+					upB[ic][N] = (-2.0 * (upB[ic][Nanc]) / branchWeight(tree,tree.getRoot(deleted))); /*upB contained temporarily state in sister across unroot*/
+				}
+				else {
+					upA[ic][N] = (upA[ic][Nanc] / (upA[ic][Nanc] * branchWeight(tree,Nanc) +  1));  /*contribution from Anc(N)*/
+					upB[ic][N] = (upB[ic][Nanc] / (upA[ic][Nanc] * branchWeight(tree,Nanc) +  1) );
+				}
+
+				upA[ic][N] = (upA[ic][N] + downA[ic][Nanc] - (downA[ic][N] / (downA[ic][N]  * branchWeight(tree,N) +  1)));/*contribution from sisters*/
+				upB[ic][N] = ( upB[ic][N] + downB[ic][Nanc] - (downB[ic][N]  / (downA[ic][N]  * branchWeight(tree,N) +  1)));  /*see comments above ** */
+				finalC[item][ic][N] = (finalC[item][ic][N] + upA[ic][N] / (upA[ic][N] * branchWeight(tree,N) +  1));
+				finalD[ic][N] = (finalD[ic][N]+ upB[ic][N] / (upA[ic][N] * branchWeight(tree,N) +  1));
+			}
+
+			/*NOW we find most parsimonious state*/
+			if (finalC[item][ic][N] == 0)
+				MesquiteMessage.println("Error in squared change parsimony (downA " + downA[ic][N] + " downB " + downB[ic][N] + " upA " + upA[ic][N] + " N " + N + " branchWeight " + branchWeight(tree,N) +  ")");
+			else
+				finalC[item][ic][N] = (finalD[ic][N] / (-2.0 * finalC[item][ic][N]));
+			/*finalD = finalC[item];*/
+			for (int daughter = tree.firstDaughterOfNode(N, deleted); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter, deleted))
+				SquareFinal(tree, daughter, ic);
+		}
+		else  {/*Terminal node, assign observed state*/
+			finalC[item][ic][N] = getObservedState(item, ic, tree.taxonNumberOfNode(N));
+			/*if (finalC[item][ic][N]==MesquiteDouble.unassigned)  {
+				MesquiteMessage.println("Sorry, the squared-change parsimony algorithm can't deal with missing data.  Results will contain errors.");
+			}
+			*/
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*This procedure reconstructs continuous ancestral states using the squared-change*/
+	/*parsimony criterion (see Maddison, 1991).  There are two options; either the root is taken as*/
+	/*non-existant (unrooted) or as being a node (rooted)*/
+	synchronized void minSQReconstruct (Tree tree) {
+		
+			MesquiteDouble tA = new MesquiteDouble(0);
+			MesquiteDouble tB = new MesquiteDouble(0);
+			MesquiteDouble tC = new MesquiteDouble(0);
+			double SQlengthchecked, SQlengthcheckedWt;
+			int root =  tree.getRoot(deleted);
+			int rLeft =  tree.firstDaughterOfNode(root, deleted);
+			int rRight =  tree.lastDaughterOfNode(root, deleted);
+			for (int ic=0; ic<numChars; ic++){
+				if (rootedMode) {/*rooted*/
+					SquareDown(tree, root, ic);
+					/*now need to calculate squared length*/
+					if (downA[ic][root] == 0)
+						minSQLength[ic] = 0;
+					else
+						minSQLength[ic] = finalC[item][ic][root]- Sqr(downB[ic][root]) / 4.0 / downA[ic][root];
+				}
+				else  {/*unrooted*/
+					SquareDown(tree, rLeft, ic); /*note don't calculate down for root*/
+					SquareDown(tree, rRight, ic);
+					
+					/*now need to calculate squared length*/
+					if (tree.nodeIsInternal(rLeft)){   /*Note: Left(tree.getRoot()) can't be null with unrooted*/
+						tA.setToUnassigned();
+						tB.setToUnassigned();
+						tC.setToUnassigned();
+						AddABCAllDescendants(tree, tA, tB, tC,rLeft, ic);
+						addABCdown(tree, tA, tB, tC, rRight, branchWeight(tree,root), ic);
+						if (tA.getValue() == 0)
+							minSQLength[ic] = 0;
+						else
+							minSQLength[ic] = tC.getValue() - Sqr(tB.getValue()) / 4.0 / tA.getValue();
+					}
+					else if (tree.nodeIsInternal(rRight)) {  /*Note: Right(tree.getRoot()) can't be null with unrooted*/
+						tA.setToUnassigned();
+						tB.setToUnassigned();
+						tC.setToUnassigned();
+						AddABCAllDescendants(tree, tA, tB, tC, rRight, ic);
+						addABCdown(tree, tA, tB, tC, rLeft, branchWeight(tree,root), ic);
+						if (tA.getValue() == 0)
+							minSQLength[ic] = 0;
+						else
+							minSQLength[ic] = tC.getValue() - Sqr(tB.getValue()) / 4.0 / tA.getValue();
+					}
+					else /*Only a two taxon tree; squared length for unrooted is just square of difference*/
+						minSQLength[ic] = Sqr(finalC[item][ic][rRight] - finalC[item][ic][rLeft]);
+				}
+				SquareFinal(tree, root, ic);
+			}
+	}
+	
+}
+
diff --git a/Source/mesquite/correl/CorrelationViewer/CorrelationViewer.java b/Source/mesquite/correl/CorrelationViewer/CorrelationViewer.java
new file mode 100644
index 0000000..7bd95c3
--- /dev/null
+++ b/Source/mesquite/correl/CorrelationViewer/CorrelationViewer.java
@@ -0,0 +1,450 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.correl.CorrelationViewer;
+/*~~  */
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.characters.CharacterStates;
+import mesquite.lib.duties.*;
+import mesquite.correl.lib.*;
+
+
+public class CorrelationViewer extends TreeWindowAssistantA implements CLogger   {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2CharAndTree.class, getName() + "  needs a method to calculate correlation.",
+		"The method to calculate correlation can be selected initially or in the Correlation Test submenu");
+		EmployeeNeed ew = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	/*.................................................................................................................*/
+	int currentX = 0;
+	int currentY = 1;
+	Tree tree;
+	NumberFor2CharAndTree numberTask;
+	CharSourceCoordObed characterSourceTaskX, characterSourceTaskY;
+	Taxa taxa;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	Class stateClass;
+	MesquiteWindow containingWindow;
+	CorrelPanel panel;
+	boolean askedForXY = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask = (NumberFor2CharAndTree)hireEmployee(NumberFor2CharAndTree.class, "Correlation analysis");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		makeMenu("Correlation");
+
+		ntC =makeCommand("setCorrelationCalculator",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberFor2CharAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Correlation Test", ntC, NumberFor2CharAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+
+		characterSourceTaskX = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numberTask.getCompatibilityTest(), "Source of characters (independent variable X for correlation analysis)");
+		if (characterSourceTaskX == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+
+		characterSourceTaskY = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numberTask.getCompatibilityTest(), "Source of characters (dependent variable Y for correlation analysis)");
+		if (characterSourceTaskY == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			containingWindow = (MesquiteWindow)f;
+			containingWindow.addSidePanel(panel = new CorrelPanel(), 200);
+		}
+		
+		addMenuItem( "Choose Both Characters...", makeCommand("chooseBoth",  this));
+		addMenuItem( "Choose Character X...", makeCommand("chooseX",  this));
+		addMenuItem( "Choose Character Y...", makeCommand("chooseY",  this));
+		addMenuItem( "Re-run analysis", makeCommand("rerun",  this));
+		addMenuItem( "Close Correlation Analysis", makeCommand("close",  this));
+		addMenuItem( "-", null);
+
+		return true;
+	}
+	/* ................................................................................................................. */
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis"). */
+	public String purposeOfEmployee(MesquiteModule employee) {
+		if (employee ==  characterSourceTaskX)
+			return "for X variable, correlation analysis"; 
+		if (employee ==  characterSourceTaskY)
+			return "for Y variable, correlation analysis"; 
+		return super.purposeOfEmployee(employee);
+	}
+	public String nameForWritableResults(){
+		if (numberTask == null)
+			return null;
+		return numberTask.getName();
+	}
+	public boolean suppliesWritableResults(){
+		if (numberTask == null)
+			return false;
+		return true;
+	}
+	public Object getWritableResults(){
+		return lastResult;
+	}
+	public Object getResultsHeading(){
+		return lastResult;
+	}
+	public void fileReadIn(MesquiteFile file){
+		if (panel != null)
+			panel.resetBounds();
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	public void cwriteln(String s){
+		panel.append(s + "\n");
+	}
+	public void cwrite(String s){
+		panel.append(s);
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCorrelationCalculator ", numberTask); 
+		temp.addLine("setCharSourceX ", characterSourceTaskX); 
+		temp.addLine("setCharSourceY ", characterSourceTaskY); 
+		temp.addLine("setX " + CharacterStates.toInternal(currentX)); 
+		temp.addLine("setY " + CharacterStates.toInternal(currentY)); 
+		temp.addLine("doCounts");
+
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the module that calculates correlation", "[name of module]", commandName, "setCorrelationCalculator")) {
+			NumberFor2CharAndTree temp =  (NumberFor2CharAndTree)replaceEmployee(NumberFor2CharAndTree.class, arguments, "Correlation calculator", numberTask);
+			if (temp!=null) {
+				CompatibilityTest test = temp.getCompatibilityTest();
+				if (test != null && stateClass != null){
+					if (!test.isCompatible(stateClass, getProject(), this)){
+						discreetAlert( "The character correlation module \"" +temp.getName() + "\" is not compatible with the current data type");
+						return null;
+					}
+				}
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					doCounts();
+				return numberTask;
+			}
+		}
+		else   	if (checker.compare(this.getClass(), "Returns employee", null, commandName, "getCharSource")) {
+			return characterSourceTaskX;
+		}
+		else   	if (checker.compare(this.getClass(), "Returns employee", null, commandName, "getCharSourceX")) {
+			return characterSourceTaskX;
+		}
+		else   	if (checker.compare(this.getClass(), "Returns employee", null, commandName, "getCharSourceY")) {
+			return characterSourceTaskY;
+		}
+		else   	if (checker.compare(this.getClass(), "Sets character source", null, commandName, "setCharSource")) {
+			CharSourceCoordObed temp  = (CharSourceCoordObed)replaceCompatibleEmployee(CharSourceCoordObed.class, arguments, characterSourceTaskX, numberTask.getCompatibilityTest());
+			if (temp!=null) {
+				characterSourceTaskX = temp;
+				characterSourceTaskY = temp;  //assuming this is an old script, using the same character source for both X and Y
+			}
+			return characterSourceTaskX;
+		}
+		else   	if (checker.compare(this.getClass(), "Sets character source for X", null, commandName, "setCharSourceX")) {
+			CharSourceCoordObed temp  = (CharSourceCoordObed)replaceCompatibleEmployee(CharSourceCoordObed.class, arguments, characterSourceTaskX, numberTask.getCompatibilityTest());
+			if (temp!=null) {
+				characterSourceTaskX = temp;
+			}
+			return characterSourceTaskX;
+		}
+		else   	if (checker.compare(this.getClass(), "Sets character source for Y", null, commandName, "setCharSourceY")) {
+			CharSourceCoordObed temp  = (CharSourceCoordObed)replaceCompatibleEmployee(CharSourceCoordObed.class, arguments, characterSourceTaskY, numberTask.getCompatibilityTest());
+			if (temp!=null) {
+				characterSourceTaskY = temp;
+			}
+			return characterSourceTaskY;
+		}
+		else   	if (checker.compare(this.getClass(), "Gets text in panel", null, commandName, "getText")) {
+			if (panel == null)
+				return null;
+			else
+				return panel.getText();
+		}
+		else   	if (checker.compare(this.getClass(), "Logs text in panel", null, commandName, "logText")) {
+			if (panel != null)
+				log( panel.getText());
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what characters to use", null, commandName, "chooseBoth")) {
+			int ic=characterSourceTaskX.queryUserChoose(taxa, " (X, for Correlation analysis) ");
+			boolean redo = false;
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentX = ic;
+				redo = true;
+			}
+			ic=characterSourceTaskY.queryUserChoose(taxa, " (Y, for Correlation analysis) ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentY = ic;
+				redo = true;
+			}
+			askedForXY = true;
+			if (redo)
+				doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseX")) {
+			int ic=characterSourceTaskX.queryUserChoose(taxa, " (X, for Correlation analysis) ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentX = ic;
+				askedForXY = true;
+				doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use for X", "[character number]", commandName, "setX")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			askedForXY = true;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTaskX.getNumberOfCharacters(taxa)==0) {
+				currentX = ic;
+
+			}
+			else if ((ic>=0) && (ic<=characterSourceTaskX.getNumberOfCharacters(taxa)-1)) {
+				currentX = ic;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseY")) {
+			int ic=characterSourceTaskY.queryUserChoose(taxa, " (Y, for Correlation analysis) ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentY = ic;
+				askedForXY = true;
+				doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Forces a rerunning", null, commandName, "rerun")) {
+				doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use for X", "[character number]", commandName, "setY")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTaskY.getNumberOfCharacters(taxa)==0) {
+				currentY = ic;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTaskY.getNumberOfCharacters(taxa)-1)) {
+				currentY = ic;
+			}
+			askedForXY = true;
+		}
+		else if (checker.compare(this.getClass(), "Provokes Calculation", null, commandName, "doCounts")) {
+			doCounts();
+			if (panel != null){
+				panel.invalidate();
+				panel.validate();
+				panel.doLayout();
+				panel.repaint();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Quits", null, commandName, "close")) {
+			if (panel != null && containingWindow != null)
+				containingWindow.removeSidePanel(panel);
+			iQuit();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	long oldTreeID = -1;
+	long oldTreeVersion = 0;
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree==null)
+			return;
+		this.tree=tree;
+		taxa = tree.getTaxa();
+		if ((tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion) && !MesquiteThread.isScripting()) {
+			doCounts();  //only do counts if tree has changed
+		}
+		oldTreeID = tree.getID();
+		oldTreeVersion = tree.getVersionNumber();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (numberTask!=null && !MesquiteThread.isScripting())
+			doCounts();
+	}
+	/*.................................................................................................................*/
+	public void doCounts() {
+		if (taxa == null || panel == null)
+			return;
+		if (!askedForXY && !MesquiteThread.isScripting()){
+			int ic=characterSourceTaskX.queryUserChoose(taxa, " (X, for Correlation analysis) ");
+			if (MesquiteInteger.isCombinable(ic))
+				currentX = ic;
+			ic=characterSourceTaskY.queryUserChoose(taxa, " (Y, for Correlation analysis) ");
+			if (MesquiteInteger.isCombinable(ic))
+				currentY = ic;
+			askedForXY = true;
+		}
+
+		CharacterDistribution statesX = characterSourceTaskX.getCharacter(taxa, currentX);
+		CharacterDistribution statesY = characterSourceTaskY.getCharacter(taxa, currentY);
+		if (statesX == null || statesY == null)
+			return;
+		stateClass = statesX.getStateClass();
+		MesquiteNumber result = new MesquiteNumber();
+		MesquiteString rs = new MesquiteString();
+//		window.setText("");
+		panel.setStatus(true);
+		panel.repaint();
+		panel.setText("\nX: " + characterSourceTaskX.getCharacterName(taxa, currentX) +  "\n");
+		panel.append("Y: " + characterSourceTaskY.getCharacterName(taxa, currentY) +  "\n");
+		panel.append("Calculation: " + numberTask.getNameAndParameters() + "\n");
+		if (statesX == null || statesY == null)
+			rs.setValue("Sorry, one or both of the characters was not obtained.  The correlation analysis could not be completed.");
+		/*		else if (!(statesX instanceof CategoricalDistribution) ||!(statesY instanceof CategoricalDistribution) ||  statesX.getStateClass() != CategoricalState.class || statesY.getStateClass() != CategoricalState.class)
+			rs.setValue("Sorry, one or both of the characters is not a standard non-molecular categorical character.  The correlation analysis could not be completed.");
+		else if (((CategoricalDistribution)statesX).getMaxState() >1 || ((CategoricalDistribution)statesY).getMaxState() >1)
+			rs.setValue("Sorry, both characters need to be binary (states 0 and 1 only).  The correlation analysis could not be completed.");
+		else if (((CategoricalDistribution)statesX).getMaxState()==-1 || ((CategoricalDistribution)statesY).getMaxState() ==-1)
+			rs.setValue("Sorry, one or both of the characters seems to have no states or corresponds to a non-existent column in a character matrix.  The correlation analysis could not be completed.");
+		 */		else 
+			 numberTask.calculateNumber(tree, statesX, statesY, result, rs);
+		saveLastResult(result);
+		saveLastResultString(rs);
+		panel.setStatus(false);
+		panel.repaint();
+//		window.append("\n\n  " + rs);
+		panel.append("\n\n" + rs);
+		panel.repaint();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Correlation Analysis";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Performs a Correlation analysis for categorical characters." ;
+	}
+	public void endJob() {
+		if (panel != null && containingWindow != null)
+			containingWindow.removeSidePanel(panel);
+		super.endJob();
+	}
+}
+
+class CorrelPanel extends MousePanel{
+	TextArea text;
+	Font df = new Font("Dialog", Font.BOLD, 14);
+	boolean calculating = false;
+	public CorrelPanel(){
+		super();
+		text = new TextArea(" ", 50, 50, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		setLayout(null);
+		add(text);
+		text.setLocation(0,26);
+		text.setVisible(true);
+		text.setEditable(false);
+		setBackground(Color.darkGray);
+		text.setBackground(Color.white);
+	}
+	public void setStatus(boolean calculating){
+		this.calculating = calculating;
+	}
+	public void setText(String t){
+		text.setText(t);
+	}
+	public String getText(){
+		return text.getText();
+	}
+	public void append(String t){
+		text.append(t);
+		text.repaint();
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		text.setSize(w, h-26);
+		resetBounds();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		text.setSize(w, h-26);
+		resetBounds();
+	}
+	
+	public void doLayout(){
+		resetBounds();
+	}
+	public synchronized void resetBounds(){
+		text.setBounds(0, 26, getWidth()-1, getHeight()-26);  //just to force! workaroudn for problem on os x
+		text.invalidate();
+		text.validate();
+		text.doLayout();
+		text.setBounds(0, 26, getWidth(), getHeight()-26);
+		text.invalidate();
+		text.validate();
+		text.doLayout();
+		text.repaint();
+	}
+	public void paint(Graphics g){
+		g.setFont(df);
+
+		if (!calculating){
+			g.setColor(Color.white);
+			g.drawString("Correlation Analysis", 8, 20);
+		}
+		else{
+			g.setColor(Color.black);
+			g.fillRect(0,0, getBounds().width, 50);
+			g.setColor(Color.red);
+			g.drawString("Correlation: Calculating", 8, 20);
+		}
+	}
+}
+
diff --git a/Source/mesquite/correl/Pagel94/Pagel94.java b/Source/mesquite/correl/Pagel94/Pagel94.java
new file mode 100644
index 0000000..26cf5d7
--- /dev/null
+++ b/Source/mesquite/correl/Pagel94/Pagel94.java
@@ -0,0 +1,704 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ This module copyright 2006 P. Midford and W. Maddison
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.correl.Pagel94;
+
+import java.awt.Checkbox;
+import java.awt.Label;
+import mesquite.categ.lib.CategoricalAdjustable;
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalHistory;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.correl.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.AdjustableDistribution;
+import mesquite.lib.characters.CharacterDistribution;
+
+public class Pagel94 extends Pagel94Calculator {
+
+	private CategoricalDistribution observedStates1;
+	private CategoricalDistribution observedStates2;
+	private MesquiteLong seed;
+	private long originalSeed=System.currentTimeMillis(); //0L;
+	private CategoricalHistory[] evolvingStates;
+
+	private ProgressIndicator progress = null;
+
+	private PagelMatrixModel modelConstrained;
+	private PagelMatrixModel model8;
+	private PagelMatrixModel model4; //USED temporarily to find starting for 6 param case
+
+	private final static int INDEPENDENT4 = 0;  //used to test whether any affect of Y on X or X on Y: 4 parameter model, X and Y are independent of each other
+	private final static int XINDEPENDENTofY = 1;  //used to test whether X depends on Y:  6 parameter model, Y is contingent on X & X is independent of Y)
+	private final static int YINDEPENDENTofX = 2;  //used to test whether Y depends on X:  6 parameter model, X is contingent on Y & Y is independent of X)
+	private int currentConstrainedModel = INDEPENDENT4;
+	private StringArray constrainedModelNames;
+	private MesquiteString currentConstrainedModelName;
+
+	private int simCount = 100;
+	private int completedCount = 0;
+	private MesquiteBoolean presentPValue;
+	private CLogger logger;
+	private MesquiteBoolean resimulateConstantCharacters;
+	private int constantCharCount = 0;
+	private int numIterations = 10;
+
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		seed = new MesquiteLong(originalSeed);
+		// And here
+		constrainedModelNames = new StringArray(3);  
+		MesquiteSubmenuSpec effectSubmenu = addSubmenu(null, "Test For", makeCommand("setConstrainedModelToUse", this), constrainedModelNames);
+		constrainedModelNames.setValue(0, "Any Effect");  //the strings passed will be the menu item labels
+		constrainedModelNames.setValue(1, "X depends on Y");
+		constrainedModelNames.setValue(2, "Y depends on X");
+		currentConstrainedModelName = new MesquiteString(constrainedModelNames.getValue(currentConstrainedModel));  //this helps the menu keep track of checkmenuitems
+		effectSubmenu.setSelected(currentConstrainedModelName);
+
+		presentPValue = new MesquiteBoolean(false);
+		resimulateConstantCharacters = new MesquiteBoolean(false);  // turned off for now
+		addCheckMenuItem(null, "Present P Value", makeCommand("togglePresentPValue", this), presentPValue);
+		addMenuItem("Likelihood Iterations (Pagel 94)...", makeCommand("setNumIterations", this));
+		addMenuItem("Set Seed (Pagel 94)...", makeCommand("setSeed", this));
+		addMenuItem("Set Simulation Replicates...", makeCommand("setSimCount", this));
+		
+
+		if (getEmployer() instanceof CLogger)
+			setLogger(((CLogger)getEmployer()));
+		if (!MesquiteThread.isScripting()){
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Pagel 94 parameters",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+			dialog.addLabel("Test for:", Label.LEFT);
+			RadioButtons comparison = dialog.addRadioButtons (new String[] {"Any effect", "X depends on Y", "Y depends on X"}, 0);
+			IntegerField iterationsField = dialog.addIntegerField("Extra Iterations (intensity of likelihood search)", numIterations, 5, 0, MesquiteInteger.infinite);
+			dialog.addHorizontalLine(1);
+			Checkbox pValueBox = dialog.addCheckBox("Present p-value", presentPValue.getValue());
+			IntegerField simField = dialog.addIntegerField("Number of simulations to estimate p-value", simCount, 5, 0, MesquiteInteger.infinite);
+			
+			dialog.completeAndShowDialog(true);
+			dialog.dispose();
+			if (buttonPressed.getValue()==0)  {
+				simCount = simField.getValue();
+				numIterations = iterationsField.getValue();
+				presentPValue.setValue(pValueBox.getState());
+				currentConstrainedModel = comparison.getValue();
+
+			}
+			else
+				return false;
+
+		}
+		postBean("startJob", false);
+		if (currentConstrainedModel == INDEPENDENT4)
+			modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);
+		else {
+			model4 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);  //used merely to help 6 param
+			if (currentConstrainedModel == XINDEPENDENTofY)
+				modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTX);
+			else  //constrainedModelToUse == YINDEPENDENTofX
+				modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTY);
+		}
+		model8 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL8PARAM);
+		return true;
+	}
+	
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+
+	public void setLogger(CLogger logger){
+		this.logger = logger;
+	}
+	void writeToLogger(String s){
+		if (logger != null)
+			logger.cwrite(s);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setSeed " + originalSeed); 
+		temp.addLine("setConstrainedModelToUse " + ParseUtil.tokenize(constrainedModelNames.getValue(currentConstrainedModel)));
+		temp.addLine("setSimCount " + getSimCount()); 
+		temp.addLine("togglePresentPValue " + presentPValue.toOffOnString());
+		temp.addLine("setNumIterations " + numIterations);
+		return temp;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+			long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteLong.isCombinable(s) && !MesquiteThread.isScripting()){
+				s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+			}
+			if (MesquiteLong.isCombinable(s)){
+				originalSeed = s;
+				seed.setValue(originalSeed);
+				if (!MesquiteThread.isScripting()) parametersChanged(); //?
+			}
+			return null;
+		}
+		else if (checker.compare(getClass(), "Sets the effect to test for", null, commandName, "setConstrainedModelToUse")) {
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = constrainedModelNames.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=currentConstrainedModel){
+				currentConstrainedModel = newMode; //change mode
+				currentConstrainedModelName.setValue(constrainedModelNames.getValue(currentConstrainedModel)); //so that menu item knows to become checked
+				model8 = null; //to force redo model
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+			
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of iterations for likelihood search", "[number]", commandName, "setNumIterations")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Likelihood iterations", "Intensity of likelihood search for 8 parameter model for Pagel 94 (Number of extra iterations):", numIterations, 0, MesquiteInteger.infinite);
+			if (newNum>0  && newNum!=numIterations) {
+				numIterations = newNum;
+				if (!MesquiteThread.isScripting()){
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of simulations to run to estimate p-value of likelihood difference", "[nonnegative integer]", commandName, "setSimCount")){
+			int sCount = MesquiteInteger.fromFirstToken(arguments,stringPos);
+			if (!MesquiteInteger.isCombinable(sCount))
+				sCount = MesquiteInteger.queryInteger(containerOfModule(),"Number of simulations", "Number of simulations to estimate p-value for Pagel 94 analysis", getSimCount(),0,1000,true);
+			if (MesquiteInteger.isCombinable(sCount)){
+				setSimCount(sCount);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+			else 
+				setSimCount(0);
+			return null;
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not P values are to be presented", "[on; off]", commandName, "togglePresentPValue")) {
+			presentPValue.toggleValue(parser.getFirstToken(arguments));
+
+			if (!MesquiteThread.isScripting()) {
+
+				if (presentPValue.getValue()){
+					int sCount = MesquiteInteger.queryInteger(containerOfModule(),"Number of simulations", "Number of simulations to estimate p-value for Pagel 94 analysis", getSimCount(),0,10000,true);
+					if (MesquiteInteger.isCombinable(sCount))
+						setSimCount(sCount);
+					else
+						presentPValue.setValue(false);
+					parametersChanged();
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	public void initialize(Tree tree, CharacterDistribution charStates1, CharacterDistribution charStates2) {
+		if (!(charStates1 instanceof CategoricalDistribution ||
+				charStates2 instanceof CategoricalDistribution)) {
+			if (!(charStates1 instanceof CategoricalDistribution))
+				MesquiteMessage.warnProgrammer("Quitting because the first character is not Categorical");
+			else
+				MesquiteMessage.warnProgrammer("Quitting because the second character is not Categorical");
+			iQuit();
+			return;
+		}
+		observedStates1 = (CategoricalDistribution)charStates1;
+		observedStates2 = (CategoricalDistribution)charStates2;
+		if (observedStates1.getMaxState() > 1 ||
+				observedStates2.getMaxState() > 1) {
+			if (observedStates1.getMaxState() > 1)
+				MesquiteMessage.warnProgrammer("Quitting because the first character doesn't seem to be binary -- getMaxState() returned " + observedStates1.getMaxState());
+			else
+				MesquiteMessage.warnProgrammer("Quitting because the second character doesn't seem to be binary -- getMaxState() returned " + observedStates2.getMaxState());
+			iQuit();
+		}
+		if (model8 == null){  //note: model8==null is signal that model needs remaking, in case of change
+			if (currentConstrainedModel == INDEPENDENT4)
+				modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);
+			else {
+				model4 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);  //used merely to help 6 param
+				if (currentConstrainedModel == XINDEPENDENTofY)
+					modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTX);
+				else  //constrainedModelToUse == YINDEPENDENTofX
+					modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTY);
+			}
+			model8 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL8PARAM);
+		}
+	}
+
+	public void setSeed(long newSeed){
+		originalSeed = newSeed;
+		seed.setValue(newSeed);
+	}
+
+	public long getSeed(){
+		return seed.getValue();
+	}
+
+	public int getSimCount(){
+		return simCount;
+	}
+
+	public void setSimCount(int newCount){
+		simCount = newCount;
+	}
+
+	private boolean hasZeroOrNegLengthBranches(Tree tree, int N, boolean countRoot) {
+		if (tree.getBranchLength(N) <= 0.0 && (countRoot || tree.getRoot() != N))
+			return true;
+		if (tree.nodeIsInternal(N)){
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasZeroOrNegLengthBranches(tree, d, countRoot))
+					return true;
+		}
+		return false;
+	}
+	private boolean warnedMissing = false;
+	private boolean warnedPolymorphic = false;
+	private boolean warnedMaxState = false;
+	private boolean warnedUnbranchedInternals = false;
+	private boolean warnedReticulations = false;
+	private boolean warnedSoftPoly = false;
+	private boolean warnedZeroLength = false;
+	private boolean warn(CategoricalDistribution observedStates1, CategoricalDistribution observedStates2, Tree tree, MesquiteString resultString){
+		if (observedStates1.hasMultipleStatesInTaxon(tree, tree.getRoot()) || observedStates2.hasMultipleStatesInTaxon(tree, tree.getRoot())) {
+			String s = "Polymorphic or uncertain taxa are not currently supported in Pagel94 calculations.  Calculations were not completed.";
+			if (!warnedPolymorphic) {
+				discreetAlert( s);
+				warnedPolymorphic = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (tree.hasSoftPolytomies(tree.getRoot())) {
+			String message = "Trees with soft polytomies are not currently supported in Pagel94 calculations.  Calculations were not completed.";
+			if (!warnedSoftPoly){
+				discreetAlert( message);
+				warnedSoftPoly = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (hasZeroOrNegLengthBranches(tree, tree.getRoot(), false) ) {
+			String message = "Trees with zero or negative length branches are not currently supported in Pagel94 calculations.  Calculations were not completed.";
+			message += " TREE: " + tree.writeTree();
+
+			if (!warnedZeroLength){
+				discreetAlert( message);
+				warnedZeroLength = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		long allStates = observedStates1.getAllStates(tree, tree.getRoot()) | observedStates2.getAllStates(tree, tree.getRoot());
+		int max = CategoricalState.maximum(allStates);
+		if (max > 1) {
+			String s = "Character distibution includes state values larger than 1; this is not currently supported in Pagel94 calculations.  Calculations were not completed.";
+			if (!warnedMaxState) {
+				discreetAlert( s);
+				warnedMaxState = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String s = "Pagel94 calculations cannot be done because tree has unbranched internal nodes.";
+			if (!warnedUnbranchedInternals) {
+				discreetAlert( s);
+				warnedUnbranchedInternals = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String s = "Pagel94 calculations cannot be done because tree has reticulations.";
+			if (!warnedReticulations) {
+				discreetAlert( s);
+				warnedReticulations = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (observedStates1.hasMissing(tree, tree.getRoot()) || observedStates1.hasInapplicable(tree, tree.getRoot()) || observedStates2.hasMissing(tree, tree.getRoot()) || observedStates2.hasInapplicable(tree, tree.getRoot())) {
+			String s ="Missing data & Gaps are not currently supported by Pagel94 calculations.  Calculations were not completed.";
+			if (!warnedMissing) {
+				discreetAlert( s);
+				warnedMissing = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		return false;
+	}
+
+
+	public void calculateNumber(Tree tree, CharacterDistribution charStates1, CharacterDistribution charStates2, MesquiteNumber result, MesquiteString resultString) {
+
+		clearResultAndLastResult(result);
+		if (tree == null || charStates1 == null || charStates2 == null)
+			return;
+
+		double resultConstrained;
+		double result8;
+		double pvalue = MesquiteDouble.unassigned;
+
+		if (!(charStates1 instanceof CategoricalDistribution ||
+				charStates2 instanceof CategoricalDistribution)) {
+			result.setValue(MesquiteDouble.unassigned);  
+			if (resultString != null)
+				resultString.setValue("Character not categorical; inappropriate for Pagel94 calculations");
+			return;
+		}
+
+		observedStates1 = (CategoricalDistribution)charStates1;
+		observedStates2 = (CategoricalDistribution)charStates2;
+		if (warn(observedStates1, observedStates2, tree, resultString))
+			return;
+		logln("Pagel 94 analysis: Using characters " + observedStates1.getName() + " and " + observedStates2.getName());
+
+		if (model8 == null){  //note: model8 == null is signal that model needs remaking, in case of change
+			if (currentConstrainedModel == INDEPENDENT4)
+				modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);
+			else {
+				model4 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM);
+				if (currentConstrainedModel == XINDEPENDENTofY)
+					modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTX);
+				else  //constrainedModelToUse == YINDEPENDENTofX
+					modelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTY);
+			}
+			model8 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL8PARAM);
+		}
+
+		MesquiteInteger numIt = model8.getExtraSearch();
+		numIt.setValue(numIterations);
+		logln("Pagel 94 analysis: Calculating likelihood for 4 parameter model");
+
+		if (currentConstrainedModel != INDEPENDENT4){  //constrained is 6 param model; therefore go to 4 for starting point
+			model4.estimateParameters(tree,observedStates1,observedStates2);
+			logln("Pagel 94 analysis: Calculating likelihood for 6 parameter model");
+			modelConstrained.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM);
+		}
+
+		modelConstrained.estimateParameters(tree,observedStates1,observedStates2);
+		resultConstrained = modelConstrained.evaluate(modelConstrained.getParams(),null);
+
+		logln("Pagel 94 analysis: Calculating likelihood for 8 parameter model (" + numIterations + " iterations)");
+		if (currentConstrainedModel != INDEPENDENT4)  //4 param model to use for starting point could be either constrained or temporary one
+			model8.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM);
+		else
+			model8.setParametersFromSimplerModel(modelConstrained.getParams(),PagelMatrixModel.MODEL4PARAM);
+		model8.estimateParameters(tree,observedStates1,observedStates2);
+		result8 = model8.evaluate(model8.getParams(),null);
+
+		double score = resultConstrained-result8;
+		if (logger!= null){ 
+			writeToLogger("\nTesting: " + constrainedModelNames.getValue(currentConstrainedModel));
+			if (currentConstrainedModel == INDEPENDENT4)
+				writeToLogger("\n\nFor four parameter model (independent, no effect of X on Y or Y on X): \n");  
+			else if (currentConstrainedModel == XINDEPENDENTofY)
+				writeToLogger("\n\nFor 6 parameter model (X's evolution is independent of Y): \n");  
+			else  //constrainedModelToUse == YINDEPENDENTofX
+				writeToLogger("\n\nFor 6 parameter model (Y's evolution is independent of X): \n");  
+			writeToLogger(modelConstrained.getParameters());
+			writeToLogger("\n\nlog Likelihood is " + (-1*resultConstrained));
+			writeToLogger("\n\n\nFor eight parameter model : \n");
+			writeToLogger(model8.getParameters());
+			writeToLogger("\n\nlog Likelihood is " + (-1*result8));
+
+			writeToLogger("\n\nDifference is " + score);
+		}
+
+		if (presentPValue.getValue() && simCount>0){
+			logln("Pagel 94 analysis: Estimating p value using simulations (Generating " + simCount + " simulated data sets)");
+			// Begin Simulation
+			CategoricalAdjustable[] SimData = new CategoricalAdjustable[2];
+			double independentScore = 0;  // keep compiler happy
+			double dependentScore;
+			evolvingStates = new CategoricalHistory[2];
+			double[][] rootPriors = modelConstrained.getRootPriors();
+
+			
+			PagelMatrixModel savedModelConstrained = null;
+			if (currentConstrainedModel == INDEPENDENT4)
+				savedModelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL4PARAM); 
+			else if (currentConstrainedModel == XINDEPENDENTofY)
+				savedModelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTX); 
+			else  //constrainedModelToUse == YINDEPENDENTofX
+				savedModelConstrained = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL6PARAMINDEPENDENTY); 
+
+			modelConstrained.copyToClone(savedModelConstrained);
+			PagelMatrixModel savedModel8 = new PagelMatrixModel("",CategoricalState.class,PagelMatrixModel.MODEL8PARAM);
+			model8.copyToClone(savedModel8);
+			double diffs[] = new double[simCount];
+			DoubleArray.deassignArray(diffs);
+			constantCharCount=0;
+			boolean hasAborted = false;
+			progress = new ProgressIndicator(getProject(),"Running simulations", "Running", simCount, true);
+			progress.start();
+			try {
+				for (int simNumber = 0;(simNumber<simCount)&&!hasAborted;simNumber++){
+					progress.setCurrentValue(simNumber+1);  // so user sees 1-based count
+					progress.setText("Running simulation " + (simNumber+1) + " of " + simCount, false);
+					modelConstrained.setProgress(progress);
+					model8.setProgress(progress);
+					SimData[0] = new CategoricalAdjustable(observedStates1.getTaxa(),observedStates1.getNumNodes());
+					SimData[1] = new CategoricalAdjustable(observedStates2.getTaxa(),observedStates2.getNumNodes());
+					evolvingStates[0] = new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+					evolvingStates[1] = new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+					getSimulatedCharacters(SimData,tree, savedModelConstrained, rootPriors, seed);
+					if (!eitherCharacterConstant(tree,SimData[0],SimData[1])) {
+						if (progress.isAborted()){
+							hasAborted = true;
+						}
+						if (!hasAborted){
+							if (currentConstrainedModel != INDEPENDENT4){  //constrained is 6 param model; therefore go to 4 for starting point
+								model4.estimateParameters(tree,SimData[0],SimData[1]);
+								modelConstrained.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM);
+							}
+
+							modelConstrained.estimateParameters(tree,SimData[0],SimData[1]);
+							independentScore = modelConstrained.evaluate(modelConstrained.getParams(),null);
+						}
+						if (progress.isAborted()){
+							hasAborted = true;
+						}
+						if (!hasAborted){
+							if (currentConstrainedModel != INDEPENDENT4)  //constrained is 6 param model; therefore go to 4 for starting point
+								model8.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM); 
+							else
+								model8.setParametersFromSimplerModel(modelConstrained.getParams(),PagelMatrixModel.MODEL4PARAM); 
+							model8.estimateParameters(tree,SimData[0],SimData[1]);
+							dependentScore= model8.evaluate(model8.getParams(),null);
+							diffs[simNumber] = independentScore-dependentScore;
+						}
+						if (progress.isAborted()){
+							hasAborted = true;
+						}
+					}
+					else if(resimulateConstantCharacters.getValue()){
+						while(eitherCharacterConstant(tree,SimData[0],SimData[1])){
+							logln("Resimulating Characters");
+							SimData[0] = new CategoricalAdjustable(observedStates1.getTaxa(),observedStates1.getNumNodes());
+							SimData[1] = new CategoricalAdjustable(observedStates2.getTaxa(),observedStates2.getNumNodes());
+							evolvingStates[0] = new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+							evolvingStates[1] = new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+							getSimulatedCharacters(SimData,tree, savedModelConstrained, rootPriors, seed);
+							hasAborted = progress.isAborted();
+						}
+						if (!hasAborted){
+							if (currentConstrainedModel != INDEPENDENT4){  //constrained is 6 param model; therefore go to 4 for starting point
+								model4.estimateParameters(tree,SimData[0],SimData[1]);
+								modelConstrained.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM);
+							}
+							modelConstrained.estimateParameters(tree,SimData[0],SimData[1]);
+							independentScore = modelConstrained.evaluate(modelConstrained.getParams(),null);
+							hasAborted = progress.isAborted();
+						}
+						if (!hasAborted){
+							if (currentConstrainedModel != INDEPENDENT4)  //constrained is 6 param model; therefore go to 4 for starting point
+								model8.setParametersFromSimplerModel(model4.getParams(),PagelMatrixModel.MODEL4PARAM); 
+							else
+								model8.setParametersFromSimplerModel(modelConstrained.getParams(),PagelMatrixModel.MODEL4PARAM); 
+							model8.estimateParameters(tree,SimData[0],SimData[1]);
+							hasAborted = progress.isAborted();
+						}
+						if (!hasAborted){
+							dependentScore= model8.evaluate(model8.getParams(),null);
+							logln("Scores (indep,dep): " + independentScore + ", " + dependentScore);           	 
+							diffs[simNumber] = independentScore-dependentScore;
+							hasAborted = progress.isAborted();
+						}
+					}
+					else{
+						diffs[simNumber] = 0;   //if character is constant the 4-parameter and 8-parameter models ought to be =
+						constantCharCount++;
+					}
+				}
+			}
+			catch(PagelMatrixModel.StuckSearchException e){
+				hasAborted = true;
+			}
+			progress.goAway();
+			modelConstrained.setProgress(null);
+			model8.setProgress(null);
+			DoubleArray.sort(diffs);
+			int position;
+			for (position = 0;position<simCount;position++)
+				if (score<diffs[position])
+					break;
+			if (hasAborted){
+				int completedDiffs = countAssigned(diffs);
+				if (completedDiffs>0){
+					pvalue = 1-(1.0*position)/(1.0*completedDiffs);
+					writeToLogger("\np-value from " + completedDiffs +" simulations is " + pvalue + "\n");
+					if (constantCharCount >0)
+						writeToLogger("Simulation set includes " + constantCharCount + " sets with constant characters");
+					completedCount = completedDiffs;
+				}
+				else{
+					pvalue = MesquiteDouble.unassigned;
+					writeToLogger("\nNo simulations completed");
+					completedCount = 0;
+				}
+			}
+			else {
+				pvalue = 1-(1.0*position)/(1.0*simCount);
+				writeToLogger ("\np-value from " + simCount + " simulations is " + pvalue + "\n");
+				if (constantCharCount >0)
+					writeToLogger("Simulation set includes " + constantCharCount + " sets with constant characters");
+				completedCount = simCount;
+			}
+			result.setValue(score);
+			String message = "Difference in log likelihoods = " + result.getDoubleValue();
+			result.setValue(pvalue);
+			if (result.isUnassigned())
+				resultString.setValue(message + ". No p-value was calculated, see MesquiteLog for details");
+			else
+				resultString.setValue(message + ". p-value = " + result.getDoubleValue() + " (from " + completedCount + " simulations)" );
+		}
+		else {
+			if (result != null)
+				result.setValue(score);
+			if (result.isUnassigned())
+				resultString.setValue("No likelihood was calculated, see MesquiteLog for details");
+			else
+				resultString.setValue("Difference in log likelihoods = " + result.getDoubleValue());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+	private boolean eitherCharacterConstant(Tree tree,CategoricalAdjustable char1, CategoricalAdjustable char2) {
+		return (char1.isConstant(tree,tree.getRoot()) || char2.isConstant(tree,tree.getRoot()));
+	}
+
+
+
+	// Wayne, this might be a useful addition to DoubleArray??
+	private int countAssigned(double[] data){
+		int count = 0;
+		for(int i=0;i<data.length;i++)
+			if (!MesquiteDouble.isUnassigned(data[i]))
+				count++;
+		return count;
+	}
+
+	private CharacterDistribution[] getSimulatedCharacters(CategoricalAdjustable[] statesAtTips, Tree tree, PagelMatrixModel model, double[][] rootPriors, MesquiteLong seed){
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("tree null in Pagel94 getSimulatedCharacters ");
+			return null;
+		}
+		if (statesAtTips == null){
+			MesquiteMessage.warnProgrammer("statesAtTips is null in Pagel94 getSimulatedCharacters");
+			return null;
+		}
+		for (int i=0;i<statesAtTips.length;i++) {
+			if (!(statesAtTips[i] instanceof CategoricalAdjustable))
+				statesAtTips[i] = new CategoricalAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+			else
+				statesAtTips[i] = (CategoricalAdjustable)((AdjustableDistribution)statesAtTips[i]).adjustSize(tree.getTaxa());
+		}
+		for (int i=0;i<statesAtTips.length;i++) {
+			if (statesAtTips[i] instanceof CategoricalAdjustable)
+				((CategoricalAdjustable)statesAtTips[i]).deassignStates();
+		}
+		//probabilityModel.setMaxStateSimulatable(probabilityModel.getMaxStateDefined()); //should allow user to set # states
+		if (model == null) {
+			MesquiteMessage.warnProgrammer("Model is null in Pagel94 getSimulatedCharacters");
+			return null;
+		}
+		if (!model.isFullySpecified()) {
+			MesquiteMessage.warnProgrammer("Model was not fully specified during estimate or wrong model used ");
+			return null;
+		}	
+		//failed = false;
+		for (int i=0;i<statesAtTips.length;i++){
+			evolvingStates[i] =(CategoricalHistory) statesAtTips[i].adjustHistorySize(tree, evolvingStates[i]);
+		}
+		if (seed!=null)
+			model.setSeed(seed.getValue());
+		long[] rootstate = model.getRootStates(tree,rootPriors);
+		for (int c=0;c<rootstate.length;c++)
+			evolvingStates[c].setState(tree.getRoot(), rootstate[c]);  //starting rootCategoricalState.makeSet(0)); //
+		evolve(tree, (CategoricalAdjustable[])statesAtTips, model, tree.getRoot());
+		if (seed!=null)
+			seed.setValue(model.getSeed());
+		return statesAtTips;
+	}
+	/*.................................................................................................................*/
+
+	private void evolve(Tree tree, CategoricalAdjustable[] statesAtTips, PagelMatrixModel model, int node) {
+		if (node!=tree.getRoot()) {
+			int size = statesAtTips.length;
+			int[] stateAtAncestor = new int[size];
+			int[] stateAtNode;
+			for (int c=0;c<size;c++){
+				long states = evolvingStates[c].getState(tree.motherOfNode(node));
+				stateAtAncestor[c] = CategoricalState.minimum(states);
+			}
+			stateAtNode = model.evolveState(stateAtAncestor,tree,node);
+			for (int c=0;c<size;c++){
+				long states = CategoricalState.makeSet(stateAtNode[c]);
+				evolvingStates[c].setState(node,states);
+				if (tree.nodeIsTerminal(node)) {   				
+					statesAtTips[c].setState(tree.taxonNumberOfNode(node), states);
+				}
+			}
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			evolve(tree, statesAtTips, model, daughter);
+	}
+	/*.................................................................................................................*/
+
+
+	public String getVeryShortName() {
+		return "Test from Pagel1994";
+	}
+
+	public String getAuthors() {
+		return "Peter E. Midford & Wayne P. Maddison";
+	}
+
+	public String getVersion() {
+		return "0.1";
+	}
+
+	public String getName() {
+		return "Pagel's 1994 test of correlated (discrete) character evolution";
+	}
+
+	public String getExplanation(){
+		return "A statistical test, described in Pagel(1994), for nonindependent evolution of two discrete, binary characters";
+	}
+
+	// This isPrerelease also proxies for PagelMatrixModel in mesquite.correl.lib  
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/correl/aCorrelPackageIntro/aCorrelPackageIntro.java b/Source/mesquite/correl/aCorrelPackageIntro/aCorrelPackageIntro.java
new file mode 100644
index 0000000..ddc18f8
--- /dev/null
+++ b/Source/mesquite/correl/aCorrelPackageIntro/aCorrelPackageIntro.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.correl.aCorrelPackageIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+
+
+/* ======================================================================== */
+public class aCorrelPackageIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aCorrelPackageIntro.class;
+  	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Correl is a Mesquite package for examining character correlation.";
+   	 }
+   
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Correl Package";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Midford, P. & W.P. Maddison. 2006.  Correl Package for Mesquite.  Version 1.1. http://mesquiteproject.org";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "1.12";
+   	 }
+ 	/*.................................................................................................................*/
+  	 public int getVersionOfFirstRelease() {
+		return 110;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "P. Midford & W. Maddison";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean hasSplash() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Correl Package";
+ 	}
+}
+
diff --git a/Source/mesquite/correl/aCorrelPackageIntro/splash.gif b/Source/mesquite/correl/aCorrelPackageIntro/splash.gif
new file mode 100644
index 0000000..dc1ca28
Binary files /dev/null and b/Source/mesquite/correl/aCorrelPackageIntro/splash.gif differ
diff --git a/Source/mesquite/correl/lib/CLogger.java b/Source/mesquite/correl/lib/CLogger.java
new file mode 100644
index 0000000..a6d083b
--- /dev/null
+++ b/Source/mesquite/correl/lib/CLogger.java
@@ -0,0 +1,20 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.correl.lib;
+
+import mesquite.lib.*;
+
+public interface CLogger {
+ 	public void cwriteln(String s);
+ 	public void cwrite(String s);
+}
diff --git a/Source/mesquite/correl/lib/ComplexMatrix.java b/Source/mesquite/correl/lib/ComplexMatrix.java
new file mode 100644
index 0000000..697ba81
--- /dev/null
+++ b/Source/mesquite/correl/lib/ComplexMatrix.java
@@ -0,0 +1,268 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.correl.lib;
+
+import mesquite.lib.MesquiteDouble;
+import Jama.Matrix;
+
+// A very minimal implementation of matrices of complex numbers.  Really this
+// only implments multiplication and copying to and from real number matrices
+public class ComplexMatrix {
+	
+	// lay this out almost like the Jama Matrix class
+	private double[][][] C;
+	private int m;
+	private int n;
+
+	// simple constructor - just specify size
+	public ComplexMatrix(int m,int n){
+		this.m = m;
+		this.n = n;
+		C = new double[m][n][2];
+	}
+	
+	public double getRealValue(int m, int n) {
+		return C[m][n][0];
+	}
+	public double getImaginaryValue(int m, int n) {
+		return C[m][n][1];
+	}
+	public void setRealValue(double value, int m, int n) {
+		C[m][n][0] = value;
+	}
+	public void setImaginaryValue(double value, int m, int n) {
+		C[m][n][1] = value;
+	}
+	
+	public double[][] extractRealMatrix() {
+		double[][] result = new double[C.length][C[0].length];
+		for(int i=0;i<result.length;i++)
+			for (int j=0;j<result.length;j++)
+				result[i][j]=C[i][j][0];
+		return result;
+	}
+	
+	// construct from 2 dimensional array of real doubles; all imaginary parts set to 0
+	   public ComplexMatrix(double[][] A) {
+		      m = A.length;
+		      n = A[0].length;
+		      // keep the checking
+		      for (int i = 0; i < m; i++) {
+		         if (A[i].length != n) {
+		            throw new IllegalArgumentException("All rows must have the same length.");
+		         }
+		      }
+		      C = new double[2][m][n];
+		      // fill
+		      for (int i=0;i<m;i++)
+		    	  	for (int j=0;j<n;j++){
+		    	  		C[0][i][j]=A[i][j];
+		    	  		C[1][i][j]=0;
+		    	  	}
+	   }
+	   
+	   // returns diagonal matrix from arrays of real and imaginary parts
+	   public static ComplexMatrix makeDiagonal(double[] realParts, double[] imaginaryParts){
+		   if (realParts.length != imaginaryParts.length)
+			   throw new IllegalArgumentException("Real and imaginary parts must have same length");
+		   ComplexMatrix result = new ComplexMatrix(realParts.length,realParts.length);
+		   
+		   for (int i=0;i<realParts.length;i++)
+			   for (int j=0;j<realParts.length;j++){
+				   if (i==j) {
+					   result.C[i][j][0]= realParts[i];
+					   result.C[i][j][1] = imaginaryParts[i];
+				   }
+				   else {
+					   result.C[i][j][0] = 0;
+					   result.C[i][j][1] = 0;
+				   }
+			   }
+	   		return result;
+	   }
+	   
+	   /** Get row dimension.
+	   @return     m, the number of rows.
+	   */
+
+	   public int getRowDimension () {
+	      return m;
+	   }
+
+	   /** Get column dimension.
+	   @return     n, the number of columns.
+	   */
+
+	   public int getColumnDimension () {
+	      return n;
+	   }
+
+
+	   public double[][] realPortion(){
+		   double[][] result = new double[m][n];
+		   for (int i=0;i<m;i++)
+			   for (int j=0;j<n;j++)
+				   result[i][j] = C[i][j][0];
+		   return result;
+	   }
+	   
+
+		// multiply by a real number constant and return new matrix
+	   public ComplexMatrix times(double x){
+		   ComplexMatrix result = new ComplexMatrix(this.m,this.n);
+		   for (int i=0;i<m;i++)
+			   for (int j=0;j<m;j++){
+				   result.C[i][j][0] = this.C[i][j][0]*x;
+				   result.C[i][j][1] = this.C[i][j][1]*x;
+			   }
+		   return result;
+	   }
+	   //multiply in place by a real number constant
+	   public void timesEquals (double x){
+		   for (int i=0;i<m;i++)
+			   for (int j=0;j<m;j++){
+				   this.C[i][j][0] *= x;
+				   this.C[i][j][1] *= x;
+			   }
+	   }
+	   
+	   // Since multiplication is non-communitive this will support right and left
+	   // multiplication with real-valued matrices (avoids converting real->complex
+	   // matrix conversion).
+	   // returns C=A*B (B real)
+	   public ComplexMatrix rightMultiply (double[][] B){
+		   if (B.length != n) {
+			   throw new IllegalArgumentException("Matrix inner dimensions must agree.");
+		   }
+		   ComplexMatrix X = new ComplexMatrix(m,B.length);
+		   double[][][] XArray = X.C;
+		   double[] Bcolj = new double[n];
+		   double[][] Barray = B;
+		      for (int j = 0; j < B.length; j++) {
+		         for (int k = 0; k < n; k++) {
+		            Bcolj[k] = Barray[k][j];
+		         }
+		         for (int i = 0; i < m; i++) {
+		            double[][] Crowi = C[i];
+		            double sr = 0;
+		            double sc = 0;
+		            for (int k = 0; k < n; k++) {
+		               sr += Crowi[k][0]*Bcolj[k];
+		               sc += Crowi[k][1]*Bcolj[k];
+		            }
+		            XArray[i][j][0] = sr;
+		            XArray[i][j][1] = sc;
+		         }
+		      }
+		   return X;
+	   }
+	   
+	   /**
+	    * 
+	    * @param B Matrix of real values
+	    * @return C = B*A 
+	    */
+	   public ComplexMatrix leftMultiply(double [][] B){
+		   if (B[0].length != m) {
+			   throw new IllegalArgumentException("Matrix inner dimensions must agree.");
+		   }
+		   ComplexMatrix X = new ComplexMatrix(B[0].length,n);
+		   double[][][] XArray = X.C;
+		   double[][] Acolj = new double[m][2];
+		   for (int j = 0;j< this.getRowDimension();j++) {
+			   for (int k = 0; k< m; k++) {
+				   Acolj[k][0] = C[k][j][0];
+				   Acolj[k][1] = C[k][j][1];
+			   }
+			   for (int i = 0; i < n; i++){
+				   double[] Browi = B[i];
+				   double sr = 0;
+				   double sc = 0;
+				   for (int k = 0; k < m; k++){
+					   sr += Browi[k]*Acolj[k][0];
+					   sc += Browi[k]*Acolj[k][1];
+				   }
+				   XArray[i][j][0] = sr;
+				   XArray[i][j][1] = sc;
+			   }
+		   }
+		   return X;
+		   
+	   }
+	   
+	   
+	   // based on code from Mesquite2DArray
+	   
+		public String toString(){
+			int numRows = m;
+			int numColumns = n;
+			if (numRows==0 ||  numColumns==0)
+				return null;  
+			StringBuffer result = new StringBuffer(4*numRows*numColumns);
+			for (int j=0; j<numRows; j++) {
+				result.append('[');
+				for (int i=0; i<numColumns; i++) {
+					if (!MesquiteDouble.isCombinable(C[i][j][0]))
+						MesquiteDouble.toString(C[i][j][0], result);
+					else
+						result.append(Double.toString(C[i][j][0]));
+					if (!MesquiteDouble.isCombinable(C[i][j][1])) {
+						if (C[i][j][1] >= 0)
+							result.append('+');
+						else result.append('-');
+						MesquiteDouble.toString(Math.abs(C[i][j][1]), result);
+					}
+					else
+						result.append("+" + Double.toString(C[i][j][1]));
+					result.append("i ");
+				}
+				result.append(']');
+				result.append('\n');
+			}
+			return result.toString();
+		}
+		
+		public String toStringRC(){
+			int numRows = m;
+			int numColumns = n;
+			StringBuffer result = new StringBuffer(4*numRows*numColumns);
+			for (int i=0; i<numColumns; i++) {
+				result.append('[');
+				for (int j=0; j<numRows; j++) {
+					if (!MesquiteDouble.isCombinable(C[i][j][0]))
+						MesquiteDouble.toString(C[i][j][0], result);
+					else
+						result.append(Double.toString(C[i][j][0]));
+					result.append('+');
+					if (!MesquiteDouble.isCombinable(C[i][j][1])){
+						if (C[i][j][1] >= 0)
+							result.append('+');
+						else result.append('-');
+						MesquiteDouble.toString(C[i][j][1], result);
+					}
+					else
+						result.append(Double.toString(C[i][j][1]));
+					result.append(' ');
+				}
+				result.append(']');
+				result.append('\n');
+			}
+			return result.toString();
+		}
+	   
+	   // 
+	 //  public ComplexMatrix multiply(ComplexMatrix B){
+	//	   return X;
+	//   }
+
+}
diff --git a/Source/mesquite/correl/lib/MultipleProbCategCharModel.java b/Source/mesquite/correl/lib/MultipleProbCategCharModel.java
new file mode 100644
index 0000000..4fe3fa4
--- /dev/null
+++ b/Source/mesquite/correl/lib/MultipleProbCategCharModel.java
@@ -0,0 +1,252 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.correl.lib;
+
+import java.util.Random;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.DNAState;
+import mesquite.lib.MesquiteDouble;
+import mesquite.lib.Optimizer;
+import mesquite.lib.Tree;
+import mesquite.lib.characters.CharacterModel;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.CharacterStatesHolder;
+import mesquite.stochchar.lib.TreeDataModelBundle;
+
+/* ======================================================================== */
+/** A character model for multiple Categorical characters to be used in stochastic simulations and in 
+likelihood calculations. It must serve both for calculating probabilities (via the transitionProbability 
+method) and for simulating character evolution
+(via the evolveState method).*/
+public abstract class MultipleProbCategCharModel extends MultipleProbabilityModel {
+	protected long[] allStates;
+	protected int[] maxState;  //maximum state to be used (on a per char basis??)
+	protected int[] maxStateDefined; //maximum state for which this model is defined
+	//protected int numStates = 0;
+	protected Random randomNumGen;
+	protected int numChars;       //
+	
+	public MultipleProbCategCharModel (String name, Class dataClass, int dim) {
+		super(name, dataClass);
+ 		randomNumGen = new Random();
+ 		numChars = dim;
+ 		allStates = new long[dim];
+ 		maxState = new int[dim];
+ 		maxStateDefined = new int[dim];
+ 		for (int i=0;i<dim;i++)
+ 			allStates[i]=0L; 
+ 		for (int i=0;i<dim;i++)
+ 			maxState[i]=-1;
+ 		for (int i=0;i<dim;i++)
+ 			maxStateDefined[i]=-1;
+	}
+
+	/** Returns natural log of the transition probability from beginning to ending state in the given tree on the given node*/
+	public double transitionLnProbability (int[] beginState, int[] endState, Tree tree, int node){
+		return Math.log(transitionProbability(beginState, endState, tree, node));
+	}
+
+    /** Returns instanteous rate from beginning to ending state in given tree on the given node */
+	// Currently not supporting MultipleProbDNAModel, so this is supported PEM 22-Mar-2006
+	/** Returns transition probability from beginning to ending state in the given tree on the given node*/
+	public abstract double transitionProbability (int beginState[], int endState[], Tree tree, int node);
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	public void evolveState (CharacterState[] beginState, CharacterState[] endState, Tree tree, int node){
+		if (endState==null) {
+			return;
+		}
+		if (beginState==null || !(beginState instanceof CategoricalState[]) || !(endState instanceof CategoricalState[])){
+			for (int i=0;i<endState.length;i++)
+				endState[i].setToUnassigned();  //set all to unassigned?
+			return;
+		}
+		CategoricalState bState[] = (CategoricalState[])beginState;
+		CategoricalState eState[] = (CategoricalState[])endState;
+		int [] catStates = new int[bState.length];
+		for(int i=0;i<bState.length;i++)
+			catStates[i]=CategoricalState.minimum(bState[i].getValue());
+		int[] r = evolveState(catStates, tree, node); //todo: issue error if beginning is polymorphic?  choose randomly among beginning?
+		for(int i=0;i<r.length;i++)
+			eState[i].setValue(CategoricalState.makeSet(r[i]));
+	}
+	
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	public abstract int[] evolveState (int beginState[], Tree tree, int node);
+	
+	/** Returns instantaneous rate of change from beginState to endState along branch in tree
+	NOT READY YET
+	public abstract double instantaneousRate (int beginState, int endState, Tree tree, int node);
+	*/
+	
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public CharacterState[] getRootState (CharacterState[] state, Tree tree){
+		if (state==null || !(state instanceof CategoricalState[]))
+			state = new CategoricalState[numChars];      //TODO handle this better - this should never happen
+		for(int i=0;i<state.length;i++)
+			((CategoricalState)state[i]).setValue(getRootState(tree,i));
+		return state;
+	}
+	/** Reports current parameters*/
+	public abstract String getParameters ();
+
+	/** Randomly generates according to model an ancestral state for root of tree
+	 * @param tree
+	 * @return
+	 */
+	public long getRootState (Tree tree,int c){
+		if (maxState[c] <= 0) 
+			return (1L);  //if only state 0 allowed, return it
+		else {
+			double r = randomNumGen.nextDouble();
+			double probEach =1.0/(maxState[c]+1);
+			double accumProb = 0;
+			for (int i=0; i<maxState[c]; i++) {
+				accumProb +=  priorProbability(i,c);
+				if (r< accumProb)
+					return CategoricalState.makeSet(i);
+			}
+			return CategoricalState.makeSet(maxState[c]);
+		}
+	}
+	public double priorProbability (int state,int c){
+		if (!inStates(state,c)) 
+			return 0;
+		/* if (state == 0)
+			return 1;
+		else 
+			return 0;
+		/* */
+		
+		if (maxState[c] == 0)
+			return (0.5);  // flat prior
+		else
+			return (1.0/(maxState[c]+1));  // flat prior
+		
+	}
+	public boolean priorAlwaysFlat(){
+		return true;
+	}
+	
+	/* ---------------------------------------------*/
+	public boolean inStates(int state,int c) { //todo: these should be part of standard categ models
+		if (state>maxState[c] || state<0)
+			return false;
+		else
+			return (CategoricalState.isElement(allStates[c], state));
+	}
+	/* ---------------------------------------------*/
+	public void setMaxStateDefined(int m,int c) {  
+			maxState[c] = m;
+			maxStateDefined[c] = m;
+			allStates[c] = CategoricalState.span(0,maxState[c]);
+	}
+	/* ---------------------------------------------*/
+	public void setMaxStateSimulatable(int m,int c) {  
+			maxState[c] = m;
+			if (m>maxStateDefined[c])
+				maxState[c] = maxStateDefined[c];
+			allStates[c] = CategoricalState.span(0,maxState[c]);
+	}
+	/* ---------------------------------------------*/
+	public void setCharacterDistribution(CharacterStatesHolder[] cStates) { 
+		super.setCharacterDistribution(cStates);
+		numChars= cStates.length;
+		for (int c=0;c<numChars;c++){
+			//This expansion costs a lot of time.  Perhaps use allStates based calculations instead of states[] based calculations?
+			if (DNAState.class == cStates[c].getStateClass() || DNAState.class.isAssignableFrom(cStates[c].getStateClass())) {
+				maxState[c] = 3;
+				if (maxState[c]>maxStateDefined[c])
+					maxState[c] = maxStateDefined[c];
+				allStates[c] = CategoricalState.span(0,maxState[c]);
+			}
+			else {
+				allStates[c] = ((CategoricalDistribution)cStates[c]).getAllStates();
+				maxState[c] = CategoricalState.maximum(allStates[c]);
+				if (maxState[c]>maxStateDefined[c]) {
+					maxState[c] = maxStateDefined[c];
+					allStates[c] = allStates[c] & CategoricalState.span(0,maxState[c]);
+				}
+				else if (maxState[c] < 1) {
+					allStates[c] = CategoricalState.span(0,1);
+					maxState[c] = 1;
+				}
+			}
+		}
+	}
+	/* ---------------------------------------------*/
+	public int getMaxStateDefined(int c) {
+		return maxStateDefined[c];
+	}
+	/* ---------------------------------------------*/
+	public int getMaxState(int c) {
+		return maxState[c];
+	}
+	/* ---------------------------------------------*/
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null)
+			return;
+		super.copyToClone(md);
+		MultipleProbCategCharModel model = (MultipleProbCategCharModel)md;
+		model.allStates = allStates;
+		model.maxState = maxState;
+		model.maxStateDefined = maxStateDefined;
+	}
+	/* ---------------------------------------------*/
+	public void setSeed(long seed){
+		randomNumGen.setSeed(seed);
+	}
+	
+	/* ---------------------------------------------*/
+	public long getSeed(){
+		return randomNumGen.nextLong();
+	}
+	
+	protected double progressiveOptimize(Tree tree, TreeDataModelBundle bundle, Optimizer opt, MesquiteDouble param, double min, double optWidth){
+		double max = optWidth/tree.tallestPathAboveNode(tree.getRoot(), 1.0);
+		if (max <= min)
+			max = min + 0.1;
+ 		param.setValue((max-min)/2);
+ 		double best = opt.optimize(param, min, max, bundle);
+ 		double mult = optWidth;
+ 		if (optWidth < 2)
+ 			mult = 2;
+ 		int count = 1;
+		if (param.getValue()< min*1.00001){ //parameter very close to minimum; try narrowing the range to see if get better answer
+			while (param.getValue()< min*1.00001 && min> 0.00000001 && count<10) { 
+				double oldMin = min;
+				min = min/mult; 
+	 			best = opt.optimize(param,min, (oldMin - min)*0.5 + min, bundle);
+	 			count++;
+	 		}
+		}
+		else { 
+			double oldBest = 0;
+			
+			//check if parameter is near maximum; if near enough then expand range and try again.  Keep trying as long as -ln likelihood improves a bit
+			while (param.getValue() > max*0.999 && max<100000 && count<10 && (oldBest == 0 || (best<oldBest && Math.abs(best/oldBest)<0.999))) { //trying again in case seems to be bumping up against max
+				double oldMax = max;
+				max = max*mult; 
+				oldBest = best;
+	 			best = opt.optimize(param, (oldMax-min)*0.8 + min, max, bundle);
+	 			count++;
+	 		}
+ 		}
+ 		return best;
+	}
+
+
+}
diff --git a/Source/mesquite/correl/lib/MultipleProbabilityModel.java b/Source/mesquite/correl/lib/MultipleProbabilityModel.java
new file mode 100644
index 0000000..bdbdb0c
--- /dev/null
+++ b/Source/mesquite/correl/lib/MultipleProbabilityModel.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.correl.lib;
+
+import mesquite.lib.CommandRecord;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.Tree;
+import mesquite.lib.characters.CharacterModel;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.CharacterStatesHolder;
+import mesquite.lib.characters.MCharactersDistribution;
+import mesquite.lib.characters.MCharactersStatesHolder;
+import mesquite.lib.characters.ProbabilityModel;
+import mesquite.lib.characters.WholeCharacterModel;
+/* ======================================================================== */
+/** Sublcass of models of character evolution for likelihood and other calculations involving stochastic models of character evolution. It is expected
+that subclasses of this will be specialized for different classes of data (categorical, continuous, etc.)*/
+public abstract class MultipleProbabilityModel extends WholeCharacterModel {
+	int characterNumbers[] = null;
+	private CharacterStatesHolder[] charDistribution = null;
+	private MCharactersStatesHolder charMatrix = null;
+	int defaultNumChars = 100; //??
+
+	public MultipleProbabilityModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+
+	public abstract CharacterModel cloneModelWithMotherLink(CharacterModel formerClone);
+	
+	public void copyToClone(CharacterModel pm){
+		if (pm==null || !(pm instanceof ProbabilityModel))
+			return;
+		MultipleProbabilityModel model = (MultipleProbabilityModel)pm;
+		model.characterNumbers = characterNumbers;  //why are we not cloning these? PEM
+		model.charDistribution = charDistribution;
+		model.charMatrix = charMatrix;
+		super.copyToClone(model);
+	}
+	/** sets the seed for simulated character evolution */
+	public abstract void setSeed(long seed);
+	
+	/** returns the seed for simulated character evolution */
+	public abstract long getSeed();
+	
+	public String getTypeName(){
+		return "Probability model";
+	}
+	public String getParadigm(){
+		return "Probability";
+	}
+	
+	/** Returns a description of current parameters suitable for viewing by users */
+	public abstract String getParameters();
+	
+	/** Returns whether parameters of model are fully specified.  If so, it can be used for evolving states.*/
+	public abstract boolean isFullySpecified();
+	
+	/** Randomly generates according to model an end state on branch from beginning states*/
+	public abstract void evolveState (CharacterState[] beginState, CharacterState[] endState, Tree tree, int node);
+
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public abstract CharacterState[] getRootState (CharacterState[] state, Tree tree);
+	
+	/** Tells the model that subsequent calculations/simulations will apply to a different set of characters from
+	previous calculations.  Between calls to this, the model may assume that the same characters are being dealt with (note: initForNextCharacter
+	is called automatically by setCharacter */
+	public void initForNewCharacterSet(){
+	}
+	/** Sets the character number to which this model applies */
+	public void setCharacterNumbers(int[] ic){
+		characterNumbers = ic;
+	}
+	/** returns the character number to which this model applies */
+	public int[] getCharacterNumber(){
+		return characterNumbers;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return true if model needs an empirical matrix*/
+	public boolean needsEmpirical(){
+		return false;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return matrix if model has an empirical matrix*/
+	public MCharactersDistribution getEmpirical(){
+		return null;
+	}
+	/** Sets the character distribution or history to which this model is currently applying */
+	public void setCharacterDistribution (CharacterStatesHolder[] cd){
+		charDistribution = cd;
+	}
+	public CharacterStatesHolder[] getCharacterDistribution (){
+		return charDistribution;
+	}
+	/** To be overridden if processing needs to happen after CharMatrix is set */
+	public void recalcAfterSetMCharactersStatesHolder (){
+	}
+	/** Returns default number of characters to simulate. This can be useful if the model wants to specify whether to use an empirical number or some other number*/ 
+   	public int getDefaultNumChars(){
+		return defaultNumChars;
+   	}
+	/** sets default number of characters to simulate. */ 
+   	public void setDefaultNumChars(int numChars){
+		defaultNumChars = numChars;
+   	}
+	/** Sets the character matrix or  history to which this model is currently applying */
+	public void setMCharactersStatesHolder (MCharactersStatesHolder cd){
+		charMatrix = cd;
+		recalcAfterSetMCharactersStatesHolder();
+	}
+	public MCharactersStatesHolder getMCharactersStatesHolder (){
+		return charMatrix;
+	}
+
+
+
+}
diff --git a/Source/mesquite/correl/lib/Pagel94Calculator.java b/Source/mesquite/correl/lib/Pagel94Calculator.java
new file mode 100644
index 0000000..7df22af
--- /dev/null
+++ b/Source/mesquite/correl/lib/Pagel94Calculator.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ This module copyright 2006 P. Midford and W. Maddison
+ 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.correl.lib;
+
+import java.util.ArrayList;
+
+import mesquite.categ.lib.RequiresExactlyCategoricalData;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+public abstract class Pagel94Calculator extends NumberFor2CharAndTree {
+    
+    
+   public abstract void setLogger(CLogger logger);
+   
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+ 
+}
+
+    
diff --git a/Source/mesquite/correl/lib/PagelMatrixModel.java b/Source/mesquite/correl/lib/PagelMatrixModel.java
new file mode 100644
index 0000000..7e76378
--- /dev/null
+++ b/Source/mesquite/correl/lib/PagelMatrixModel.java
@@ -0,0 +1,1909 @@
+/* Mesquite source code.  Copyright 1997 and onward, P. Midford & W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.correl.lib;
+
+import java.util.Random;
+
+//import org.jacorb.ir.gui.typesystem.remote.IRAlias;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.cont.lib.EigenAnalysis;
+import mesquite.correl.Pagel94.Pagel94;
+import mesquite.lib.*;
+import mesquite.lib.characters.CLikelihoodCalculator;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.characters.CharacterModel;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.ProbabilityModel;
+import mesquite.stochchar.lib.MkModel;
+import Jama.Matrix;
+
+public class PagelMatrixModel extends MultipleProbCategCharModel implements Evaluator {
+
+	//protected long allStates = 0L;
+	private int assumedMaxState=1;
+	
+
+	// different model 'behaviors' here, control how parameters are constrained
+	// if qConstrained[i] is true, params[i] is set to params[qBound[i]] unless i=-1
+	// otherwise qConstrained[i] is set to paramConstant - if this is MesquiteDouble.unassigned then error
+	int [] qMapping;          // mapping from known, underparameterized models; domain is set of parameters, range is qList
+	double[] qList;           // 
+	boolean[] qConstrained;  // true if a q value has been constrained by user (currently unimplemented)
+	int [] qBound;           // qvalue bound to another qvalue (-1 = not bound) (currently unimplemented)
+	double [] qConstant;     // qvalue is set to this constant; (currently unimplemented)
+	
+	// These constants define model 'behaviors' 
+	public static final int NOMODEL = 0;       // might be useful for flagging when a simpler model isn't available
+	public static final int MODEL2PARAM = 1;
+	public static final int MODEL4PARAM = 10;  //Pagel's model with two independent characters
+    public static final int MODEL8PARAM = 20;  //Pagel's model with two dependent characters (correlated evolution)
+    public static final int INDEPENDENTCHARACTERSMODEL = MODEL4PARAM;
+    public static final int DEPENDENTCHARACTERSMODEL = MODEL8PARAM;
+    public static final int MODEL7PARAMCONTINGENTCHANGEYFORWARD = 13;
+    public static final int MODEL7PARAMCONTINGENTCHANGEYBACKWARD = 14;
+    public static final int MODEL7PARAMCONTINGENTCHANGEXFORWARD = 15;
+    public static final int MODEL7PARAMCONTINGENTCHANGEXBACKWARD = 16;
+    public static final int MODEL6PARAMINDEPENDENTX = 17;  //Peter: name changed because easier to understand (for me!)
+    public static final int MODEL6PARAMINDEPENDENTY = 18;
+    public static final int MODEL2CHARACTERUSERDEFINED = 19;
+    public static final int MODEL3CHARACTERINDEPENDENT = 100;
+    public static final int MODEL4CHARACTERINDEPENDENT = 1000;
+
+	
+    private int modelType; //behavior of current model
+    private double [] params;
+    private boolean[] paramUnassigned;
+    private double[][] probMatrix, rateMatrix, eigenVectors, inverseEigenVectors;
+    private double[] eigenValues,imagEigenValues;  //use imagEigenValues with Putzer's method
+    private boolean recalcProbsNeeded = true;
+    private boolean needToPrepareMatrices = true;
+    private Tree workingTree;
+    private CategoricalDistribution observedStatesX;
+    private CategoricalDistribution observedStatesY;
+
+	private double[][] downProbs;  // probability at node N given state s at base
+	private double[][][] downProbs2; // probabilty at node N given state s1 for charX and s2 for charY at base
+	private double[][] savedRootEstimates; // holds the estimates at the root (for simulation priors, etc.)
+	private double[] underflowCompDown;  // ln of compensation for underflow
+	//double[] empirical;       // may be implemented sometime
+	//double[][] empirical2;
+	private double[] parametersFromSimplerModel = null;  //holds values from 4 parameter model as starting values for 6 p. model
+	private PagelMatrixModel intermediate1 = null;       //holds 6 parameter models called from 8 parameter model
+	private PagelMatrixModel intermediate2 = null;
+	private int simplerModelType;
+    private int numStates;
+	private static long underflowCheckFrequency = 2; //how often to check that not about to underflow; 1 checks every time
+	private static long underflowCheck = 1;          //these are static because they are never set, though perhaps they should be setable
+	private MesquiteNumber minChecker;
+
+	private MesquiteInteger eightParameterExtraSearch = new MesquiteInteger(10);
+	
+    private double previousBranchLength = MesquiteDouble.unassigned;
+    //private boolean unassigned = true;
+ 	public static final int SIMPLER_AND_FLIP_FLOP = 2;  //conservative and slow
+ 	public static final int BASE_ON_SIMPLER= 0; 
+ 	public static final int FLIP_FLOP = 1;
+ 	
+ 	public static final double FLIP_FLOP_LOW = 0.01;
+ 	public static final double FLIP_FLOP_HIGH = 10.0;
+
+ 	int optimizationMode = BASE_ON_SIMPLER;  
+ 	
+ 	// Need to check this...
+	static final int SUM = 0;  // likelihood is just sum of likelihoods of each state at root (i.e., flat prior)
+	//static final int FIX = 1;
+	static final int SUBROOT_PRIOR = 1;  //likelihood has stated prior; this is experimental and not yet available to the user interface
+	static final int SUBROOT_EMPIRICAL = 2; //likelihood uses as prior the empirical frequencies of states in terminal taxa; this is experimental and not yet available to the user interface
+	int rootMode = SUM; //what if anything is done with prior probabilities of states at subroot?  
+
+	Random rng = new Random(System.currentTimeMillis());
+	
+	ProgressIndicator prog = null;  //when this is non-null, check for abort condition
+	
+	/**
+	 * This returns the number of characters implied by the behavior code.  It's static so it
+	 * can be used as an argument to the superconstructor.
+	 * @param behavior specifies what kind of model this will be
+	 * @return int specifies number of characters for the indicated behavior
+	 */
+	static int charsFromBehavior(int behavior){
+		return 2;  // add cases when appropriate
+	}
+
+	/**
+	 * Constructs a new model. 
+	 * @param behavior The behavior (number of parameters, constraints, etc.) the model will implement
+	 */
+    public PagelMatrixModel(String name, Class dataClass, int behavior) {
+        super(name,dataClass,charsFromBehavior(behavior)); 
+        this.modelType = behavior;
+        this.params=null;              // model's parameters
+        qConstrained=null;         // true if a parameter is somehow constrained
+        qBound=null;               // parameter bound to another parameter (-1 = not bound)
+        qConstant=null;            // parameter is set to this value; 
+        this.setConstraints(modelType);
+        needToPrepareMatrices = true;
+        recalcProbsNeeded = true;
+        minChecker = new MesquiteNumber(MesquiteDouble.unassigned);        
+        if (modelType == MODEL4PARAM)
+            optimizationMode = FLIP_FLOP;
+        else
+            optimizationMode = BASE_ON_SIMPLER;
+    }
+    
+    
+    /**
+     * 
+     * @return true if any parameters are free (not bound or assigned)
+     */
+    /* not used
+     *  boolean anyUnassigned(){
+    		boolean result = false;
+    		for(int i=0;i<qConstrained.length;i++)
+    			if(qConstrained[i])
+    				result = true;
+    		return result;
+    }
+    not used, and besides, always returns true
+    boolean allUnassigned(){
+    		boolean result = true;
+    		for(int i=0;i<qConstrained.length;i++)
+    			if(qConstrained[i])
+    				result = true;
+    		return result;
+    }
+    */
+    /**
+     * Extension of method from AsymmModel
+     * @param like likelihood estimate from p??
+     * @param p array of estimated parameters
+     * @return false if any argument is NaN
+     */
+    private boolean acceptableResults(double like, double p[]){
+    		if (Double.isNaN(like))
+    			return false;
+    		else
+    			for(int i = 0;i<p.length;i++)
+    				if (Double.isNaN(p[i]))
+    					return false;
+    		return true;
+	}
+    
+    private void reportUnacceptableValues(double like, double p[],double start[]){
+    		//MesquiteMessage.println("Likelihood is " + like);
+    		//for (int i=0;i<p.length;i++)
+    		//	MesquiteMessage.print("p [" + i + "] = " + p[i] + "; ");
+    		//if (start != null)
+    		//	MesquiteMessage.println("\n Started from " + DoubleArray.toString(start));
+    }
+    
+    private void checkQArrays(int model){
+    		if (model < MODEL3CHARACTERINDEPENDENT){
+    			if (qMapping == null || qMapping.length != 8) {
+    				qMapping = new int[8];
+    				for (int i=0;i<8;i++)
+    					qMapping[i] = i;   //default to identity mapping
+    			}
+   			if (qConstrained == null || qConstrained.length != 8){
+    				qConstrained = new boolean[8];
+    				for (int i=0;i<8;i++)
+    					qConstrained[i]=false;
+   			}
+    			if (qBound == null || qBound.length != 8)
+    				qBound = new int[8];
+    			if (qConstant == null || qConstant.length != 8)
+    				qConstant = new double[8];
+    		}
+   }
+    
+    /* following interpreted by WPM Jan 2012
+     * 
+     * joint rate matrix and naming scheme for parameters and array positions
+     * 01 = state 0 in character X, state 1 in character Y
+     * 
+     *      00    10     01   11
+     * 00  xxx  q12  q13  xxx
+     *        ---  [0]   [1]    ---
+     *       
+     * 10  q21  xxx  xxx   q24
+     *       [2]   ---    ---    [4]
+     *       
+     * 01  q31  xxx  xxx   q34
+     *       [3]   ---    ---    [5]
+     *       
+     * 11  xxx   q42  q43  xxx
+     *       ---    [6]    [7]  ---
+     *       
+      * ======4 parameter model
+     *      00    10     01   11
+     * 00  xxx  q12  q13  xxx
+     *        ---  [0]   [1]    ---
+     *       
+     * 10  q21  xxx  xxx   q24
+     *       [2]   ---    ---    [1]
+     *       
+     * 01  q31  xxx  xxx   q34
+     *       [3]   ---    ---    [0]
+     *       
+     * 11  xxx   q42  q43  xxx
+     *       ---    [3]    [2]  ---
+     *       
+      * ====== 6 param, Y independent of X (contingent X)
+     *      00    10     01   11
+     * 00  xxx  q12  q13  xxx
+     *        ---  [0]   [1]    ---
+     *       
+     * 10  q21  xxx  xxx   q24
+     *       [2]   ---    ---    [1]
+     *       
+     * 01  q31  xxx  xxx   q34
+     *       [3]   ---    ---    [5]
+     *       
+     * 11  xxx   q42  q43  xxx
+     *       ---    [3]    [7]  ---
+     *       
+      * ====== 6 param, X independent of Y (contingent Y)
+      *      00    10     01   11
+     * 00  xxx  q12  q13  xxx
+     *        ---  [0]   [1]    ---
+     *       
+     * 10  q21  xxx  xxx   q24
+     *       [2]   ---    ---    [4]
+     *       
+     * 01  q31  xxx  xxx   q34
+     *       [3]   ---    ---    [0]
+     *       
+     * 11  xxx   q42  q43  xxx
+     *       ---    [6]    [2]  ---
+     *       
+    				qMapping[5]= 0;
+    				qMapping[6]= 5;   
+    				qMapping[7]= 2;
+  * */
+    private void setConstraints(int model){
+    		checkQArrays(model);
+    		switch (model) {
+    	     	/* Initialization specific to the 4 parameter model.
+    	     	 * q12 = q34 = params[0] (forward char0)
+    	     	 * q13 = q24 = params[1] (forward char1)
+    	     	 * q21 = q43 = params[2] (backward char0)
+    	     	 * q31 = q42 = params[3] (backward char1)
+    	     	 */ 
+    			case MODEL4PARAM: {  //override defaults
+    				qMapping[4]= 1;
+    				qMapping[5]= 0;
+    				qMapping[6]= 3;
+    				qMapping[7]= 2;
+    				break;
+    			}
+    			/*
+    		     * Initialization specific to the 8 parameter model. 
+    		     * q12 = params[0] (forward char0 | char1=0)
+    		     * q13 = params[1] (forward char1 | char0=0)
+    		     * q21 = params[2] (backward char0 | char1=0)
+    		     * q31 = params[3] (backward char1 | char0=1)  //Peter: this should be (backward char1 | char0=0), correct?
+    		     * q24 = params[4] (forward char1 | char0=1)
+    		     * q34 = params[5] (forward char0 | char1=1)
+    		     * q42 = params[6] (backward char1 | char0=1)
+    		     * q43 = params[7] (backward char0 | char1=1)
+    		     * 
+    		     * The '|' indicate conditional probabilities, not arithmetic-or!
+    		     * 
+    		     * char1/char0 seem to be swapped?
+    		     */
+    			case MODEL8PARAM:{  //Pagel's model with two dependent characters (correlated evolution)
+    				// most general 2char/2state model - nothing to do here
+    				break;
+     		}
+    			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {
+    				// seven parameters, q34=q12, 
+    				qMapping[5]= 0;
+    				qMapping[6]= 5;  //shift down to close the gap
+    				qMapping[7]= 6;  
+    				break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: {
+    				// seven parameters q43=q21
+    				qMapping[7]=2;
+    				break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEXFORWARD:{
+    				// seven parameters q24=q13
+            		qMapping[4]=1;
+            		qMapping[5]=4; // shift down to close the gap
+            		qMapping[6]=5;
+            		qMapping[7]=6;
+        			break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD:{
+    				// seven parameters q42=q31
+                	qMapping[6]= 3;
+                	qMapping[7]= 6;
+            		break;
+    			}
+    			case MODEL6PARAMINDEPENDENTX:{
+    				// six parameters q34=q12,q43=q21
+    				
+    				//constraint
+    				qMapping[5]= 0;
+    				qMapping[7]= 2;
+    				//compressing to array of 6
+    				qMapping[6]= 5;   
+
+    			/*	qMapping[5]= 0;
+    				qMapping[6]= 5;   
+    				qMapping[7]= 2;
+    				*/
+    				break;
+    			}
+    			case MODEL6PARAMINDEPENDENTY:{
+    				// six parameters q24=q13,q42=q31
+    				
+    				//constraint
+    				qMapping[4]= 1;
+                	qMapping[6]= 3;
+                	
+    				//compressing to array of 6
+                	qMapping[7]= 4;  
+                	
+  				/*
+    				qMapping[4]= 1;
+                	qMapping[5]= 4;  
+                	qMapping[6]= 3;
+         //        qMapping[7]= 5;
+          * */
+    				
+    				break;
+    			}
+    			case MODEL2CHARACTERUSERDEFINED: {
+    				//TODO this for user specified models when we support them
+    				break;
+    			}
+   		}
+    }
+    
+    /*
+     * Qlist is an internal mapping from models with fewer parameters to the rate matrix
+     * for the full model.  This mapping means the optimizer only sees exactly the number of
+     * parameters in the model.
+     */
+    private double[] prepareQList(double[] values){
+    		if (qList == null || (qList.length < qMapping.length))
+    			qList = new double[qMapping.length];
+    	
+		for (int i=0;i<qMapping.length;i++) {
+			if (qMapping[i]>= values.length)
+				MesquiteMessage.println("values length " + values.length + " [qMapping[i] " + qMapping[i]);
+			qList[i] = values[qMapping[i]];
+		}
+		return qList;
+    }
+    
+    /*
+     * Initializes the appropriate rate matrix then sets up the eigenvalues and eigenvectors 
+     */
+    private void prepareMatrices(){
+        needToPrepareMatrices = false;
+        boolean changed = false;
+       // unassigned = false;
+        if (modelType < MODEL3CHARACTERINDEPENDENT){
+			if (rateMatrix == null || rateMatrix.length !=4) {
+				rateMatrix = new double[4][4];
+				changed = true;
+			}
+			changed |= fill4x4MatricesFromQList(rateMatrix, prepareQList(params));
+		
+        }
+        if (changed) {
+            recalcProbsNeeded = true;
+         //   if (unassigned) {
+         //       if (eigenVectors == null)
+         //           eigenVectors = new double[assumedMaxState+1][assumedMaxState+1];
+         //       if (eigenValues == null)
+         //           eigenValues = new double[assumedMaxState+1];
+         //       DoubleArray.deassignArray(eigenValues);
+         //       Double2DArray.deassignArray(eigenVectors);
+         //   }
+         //   else  {
+                EigenAnalysis e = new EigenAnalysis(rateMatrix, true, false, true);
+                eigenValues = e.getEigenvalues();
+                imagEigenValues = e.getImagEigenValues();  // grab in case putzer's method is necessary
+                eigenVectors = e.getEigenvectors();
+                Matrix m = new Matrix(eigenVectors);
+                inverseEigenVectors = m.inverse().getArray();  //no need to copy here, m.inverse() is a throw-away
+          //  }
+        }
+    }
+        
+    /* Initialization for 4x4 (2 character) models
+     * 
+     * Note: these matrices are indexed [column][row].  This is reflected
+     * here, in the extra transpose done in the transition probabilities, and
+     * is consistent with the comments in the Asym 2 parameter model.
+     */
+    private boolean fill4x4MatricesFromQList(double[][] matrix, double [] lParams){
+		boolean changed = false;
+		for (int i=0; i< 4; i++)
+			for (int j=0; j< 4; j++){
+				double r = MesquiteDouble.unassigned;
+				if ((i+j)==3)   // prevents simultaneous transitions
+					r=0.0;
+				else {
+					switch (i){
+						case 0: {
+							switch (j){
+								case 0:{
+									r = -(lParams[0]+lParams[1]);
+									break;
+								}
+								case 1:{
+									r = lParams[0]; 
+									break;
+								}
+								case 2:{
+									r = lParams[1]; 
+									break;
+								}
+								case 3:
+							}
+							break;
+						}
+						case 1: {
+							switch (j){
+								case 0: {
+									r = lParams[2]; 
+									break;
+								}
+								case 1:{
+									r = -(lParams[2]+lParams[4]);
+									break;
+								}
+								case 2: break;
+								case 3:{
+									r = lParams[4];
+								}
+							}
+							break;
+						}
+						case 2: {
+							switch(j){
+								case 0:{
+									r=lParams[3]; 
+									break;
+								}
+								case 1:break;
+								case 2:{
+									r= -(lParams[3]+lParams[5]);
+									break;
+								}
+								case 3:{
+									r=lParams[5];  
+									break;
+								}
+							}
+							break;
+						}
+						case 3: {
+							switch(j){
+								case 0: break;
+								case 1:{
+									r=lParams[6];  
+									break;
+								}
+								case 2:{
+									r=lParams[7];
+									break;
+								}
+								case 3:{
+									r= -(lParams[6]+lParams[7]);
+									break;
+								}
+							}
+							break;
+						}
+					} //end of switch
+					if (matrix[i][j]!= r) {
+						matrix[i][j] = r;
+						changed = true;
+					//	if (!MesquiteDouble.isCombinable(r))
+					//		unassigned = true;
+					}
+				} // else
+			}//j
+	   		// MesquiteMessage.println("Checking rate matrix: " +Double2DArray.toStringRC(rateMatrix));
+		return changed;
+    }
+    
+    
+    /*
+     * 
+     */
+	public boolean inStates(int state,int c) { 
+		if (state>maxState[c] || state<0)
+			return false;
+		else
+			return (CategoricalState.isElement(allStates[c], state));
+	}
+
+
+	/*
+	 * recodes a pair of characters into a single state for the transition matrix index
+	 */
+	private int recodeStatePair(int i, int j) {		//todo extend beyond binary characters?
+		return (2*i+j);  
+	}
+	
+	private int[] pair0 = {0,0};
+	private int[] pair1 = {0,1};
+	private int[] pair2 = {1,0};
+	private int[] pair3 = {1,1};  
+	
+	private int[] statePairFromCode(int code){
+		switch (code){
+			case 0: return pair0;
+			case 1: return pair1;
+			case 2: return pair2;
+			case 3: return pair3;
+		}
+		return null;
+	}
+	
+	public double transitionProbability (int beginState[], int endState[], Tree tree, int node){
+		if ((beginState.length != numChars) || (endState.length != numChars)){
+			MesquiteMessage.warnProgrammer("Array for beginState or endState don't match models stated number of characters");
+			return 0;
+		}
+		boolean inStateFlag = true;
+		for (int i=0;i<numChars;i++){
+			inStateFlag &= inStates(beginState[i],i);
+			inStateFlag &= inStates(endState[i],i);
+		}
+		if (!inStateFlag){
+			MesquiteMessage.warnProgrammer("An character state of either beginState or endState is not valid");
+			return 0;
+		}
+		if (tree== null){
+			MesquiteMessage.warnProgrammer("No tree specified");
+			return 0;
+		}
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		double branchLength = tree.getBranchLength(node,1.0);
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix == null)
+			return 0;
+		//TODO the following only works for two binary characters -- needs to be extended
+		// begin end reversed as in Asym2.
+		return probMatrix[recodeStatePair(endState[0],endState[1])][recodeStatePair(beginState[0],beginState[1])];
+	}
+	
+	/**
+	 * This is the private version called from probFromSection, so no checking should be required
+	 * @param beginState1 specifies the beginning state of the first character
+	 * @param endState1 specifies the ending state of the first character
+	 * @param beginState2 specifies the beginning state of the second character
+	 * @param endState2 specifies the ending state of the second character
+	 * @param tree the tree assumed for this test
+	 * @param node where we are in the tree
+	 * @return double indicating transition probability from begin1,begin2 => end1,end2
+	 */
+	private double transitionProbability (int beginState1,int endState1,int beginState2,int endState2,Tree tree, int node){
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		double branchLength = tree.getBranchLength(node,1.0);
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix ==null)
+			return 0;
+		//begin end reversed as in Asym2
+		return probMatrix[recodeStatePair(endState1,endState2)][recodeStatePair(beginState1,beginState2)];
+	}
+	
+	double[][] p, tprobMatrix;
+	/**
+	 * Updates the transition probability matrix for a branch with the specified length
+	 * @param branchLength the length of the branch
+	 */
+	public void recalcProbabilities(double branchLength){
+	//	if (unassigned)
+	//		return;
+		previousBranchLength = branchLength;
+		if (eigenValues == null)
+			return;
+		int evl = eigenValues.length;
+		if (p == null || p.length != evl || (p.length>0 && p[0].length != evl))
+			p = new double[evl][evl];
+		for(int i=0;i<evl;i++){       //here multiplying p by a diagonal matrix has been flattened to a nested pair of loops
+			double eigenExp = Math.exp(eigenValues[i]*branchLength);
+			for(int j = 0;j<evl;j++)
+				p[i][j]=eigenVectors[i][j]*eigenExp;
+		}
+		probMatrix = Double2DArray.multiply(p,inverseEigenVectors,probMatrix);
+		boolean needRecalc = false;   // set true if we need to try putzer's method, slower but less likely to break
+		for (int i=0; i<probMatrix.length;i++)         
+        		for (int j=0;j<probMatrix[0].length;j++)
+        			if (probMatrix[i][j]<= 0)
+        				if (Math.abs(probMatrix[i][j])<1E-15) 
+        					probMatrix[i][j] = 0;    //fix the problem; rows must add to one, so no relative size issue
+        				else
+        					needRecalc = true;
+		if (needRecalc){
+        		double[][] altProbMatrix = altMatrixExp(rateMatrix, eigenValues,imagEigenValues,branchLength);
+        	
+       		probMatrix = altProbMatrix;
+       		// check, just in case there is a round off error in Putzer's
+        		for (int i=0; i<probMatrix.length;i++)         
+            		for (int j=0;j<probMatrix[0].length;j++)
+            			if (probMatrix[i][j]<= 0)
+            				if (Math.abs(probMatrix[i][j])<1E-15) 
+            					probMatrix[i][j] = 0;    //fix the problem; rows must add to one, so no relative size issue
+
+		}
+         recalcProbsNeeded = false;
+	}
+	
+
+	// complex exponential
+	double[] complexExp(double re,double im){
+		double[] result = new double[2];
+		result[0]=Math.cos(im)*Math.exp(re);
+		result[1]=Math.sin(im)*Math.exp(re);
+		return result;
+	}
+	
+	// Putzer code here
+	double[][] x = null;
+	double[][] identity = null;
+	double[][] p1 = null;  // clone from identity?
+	double[][] p2 = null;
+	double[][] p3 = null;
+	double[][] p4 = null;
+	double[][] putzerT1 = null;
+	double[][] putzerT2 = null;
+	double[][] putzerT3 = null;
+	double[] workingValues = null;
+	double[] workingIValues = null;
+	
+	int eigenValueStatus = UNEQUALTRIPLE;
+	public final static int UNEQUALTRIPLE = 0;
+	public final static int COMPLEXPAIR = 1;
+	public final static int EQUALPAIR  = 2;
+	public final static int EQUALTRIPLE = 3;
+	
+	public final static double equalTol = 0.001;
+	
+	double[][] altMatrixExp(double[][] baseArray,double[] eigenValues,double[] imagEigenValues,double t){
+
+		// find the zero eigenvalue; it may only be approximately 0, but it will be the
+		// largest, since the others all have negative real parts
+		double largest = -1E99;  
+		int largestIndex = -1;
+		int evl = eigenValues.length;
+		for (int i=0;i<evl;i++)
+			if (eigenValues[i] > largest) {
+				largest = eigenValues[i];
+				largestIndex = i;
+			}
+		// check for a conjugate pair
+		int imag1 = -1;
+		int imag2 = -1;
+		int realgroup1 = -1;
+		int realgroup2 = -1;
+		int realgroup3 = -1;
+		for(int i=0;i<evl;i++){
+			if (imagEigenValues[i] != 0)
+				if (imag1 == -1)
+					imag1 = i;
+				else imag2 = i;
+		}
+		if (imag1 > -1){
+			eigenValueStatus = COMPLEXPAIR;
+			for(int i= 0; i<evl;i++)
+				if (i != imag1 && i != imag2 && i != largestIndex)
+					realgroup1 = i;   // hold lone negative real;
+		}
+		else {  // no conjugate pairs, check for multiple == reals
+			for(int i=0;i<evl-1;i++)
+				for(int j=i+1;j<evl;j++){
+					//System.out.println("Test: " + Math.abs(eigenValues[i]-eigenValues[j]));
+					if(Math.abs((eigenValues[i]-eigenValues[j])/eigenValues[i]) < equalTol){  // found a pair
+						realgroup1=i;
+						realgroup2=j;
+						break;
+					}
+				}
+				if (realgroup2 == -1)
+					eigenValueStatus = UNEQUALTRIPLE;
+				else {  //find realgroup3
+					for(int i=0;i<evl;i++){
+						if (i != largestIndex && i != realgroup1 && i != realgroup2)
+							realgroup3 = i;
+					}
+					if (Math.abs((eigenValues[realgroup1]-eigenValues[realgroup3])/eigenValues[realgroup1])<equalTol)
+						eigenValueStatus = EQUALTRIPLE;
+					else 
+						eigenValueStatus = EQUALPAIR;
+				}	
+		}
+
+		if (identity == null || identity.length != evl || identity[0].length != evl) {
+			identity = new double[evl][evl];
+			Double2DArray.setToIdentityMatrix(identity);
+		}
+		if (p1 == null || p1.length != evl || p1[0].length != evl){
+			p1 = new double[evl][evl];
+			Double2DArray.setToIdentityMatrix(p1); 
+		}
+
+		if (workingValues == null || workingValues.length != evl)
+			workingValues = new double[evl];
+		workingValues[0] = 0;      // assert that the max eigenvalue is identically zero!
+		switch (eigenValueStatus) {
+			case UNEQUALTRIPLE: {
+				int nexteigenslot=1;
+				for (int i=0;i<evl;i++){
+					if(i!=largestIndex)
+						workingValues[nexteigenslot++] = eigenValues[i];
+				}	
+				//double z = workingValues[0];
+				double k = workingValues[1];
+				double m = workingValues[2];
+				
+				
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				putzerT1 = scalarProduct(identity,m,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realR4(t,workingValues),p4));
+
+				break;
+			}
+			case COMPLEXPAIR: {
+				if (workingIValues == null || workingIValues.length != evl)
+					workingIValues = new double[evl];
+				DoubleArray.zeroArray(workingIValues);
+				workingValues[1] = eigenValues[imag1];
+				workingIValues[1] = imagEigenValues[imag1];
+				workingValues[2] = eigenValues[imag2];
+				workingIValues[2] = imagEigenValues[imag2];
+				workingValues[3] = eigenValues[realgroup1];
+
+				//double z = workingValues[0];
+				double k = workingValues[1];
+				
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				//putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,complexPairR2(t,workingValues,workingIValues),p2));
+				x = plusEquals(x,scalarProduct(p3,complexPairR3(t,workingValues,workingIValues),p3));
+				x = plusEquals(x,scalarProduct(p4,complexPairR4(t,workingValues,workingIValues),p4));
+				break;
+			}
+			case EQUALPAIR: {
+				workingValues[1] = eigenValues[realgroup1];
+				workingValues[2] = eigenValues[realgroup1];   // if they're close, force them equal
+				workingValues[3] = eigenValues[realgroup3];
+				
+				//double z = workingValues[0];
+				double k = workingValues[1];
+
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				//putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realPairR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realPairR4(t,workingValues),p4));
+				break;
+			}
+			case EQUALTRIPLE: {
+				workingValues[1] = eigenValues[realgroup1];
+				workingValues[2] = eigenValues[realgroup2];
+				workingValues[3] = eigenValues[realgroup3];
+				double k = workingValues[1];
+
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				//putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realPairR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realTripleR4(t,workingValues),p4));				
+				break;
+			}
+		}
+		return Double2DArray.transpose(x);
+	}
+	
+
+	double realR2(double t, double[] realEigenValues){
+		double k = realEigenValues[1];
+		return (Math.exp(k*t) - 1)/(k);
+	}
+	
+	double complexPairR2(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		return -((ka*(1 - Math.exp(ka*t)*Math.cos(kb*t)))/(ka*ka + kb*kb)) + 
+		  (Math.exp(ka*t)*kb*Math.sin(kb*t))/(ka*ka + kb*kb);
+	}
+	
+	
+	double realR3(double t, double[] realEigenValues){
+		//double z = realEigenValues[0];
+		double k = realEigenValues[1];
+		double m = realEigenValues[2];
+		return (Math.exp(m*t)*k - k - Math.exp(k*t)*m + m)/((-k + m)*(k)*(m)); 
+	}
+	
+	double complexPairR3(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		double expkat = Math.exp(ka*t);
+		return (2*kb - 2*expkat*kb*Math.cos(kb*t) + 2*expkat*ka*Math.sin(kb*t))/ 
+		  (2*(ka*ka*kb + kb*kb*kb));
+	}
+	
+	double realPairR3(double t, double[] values){
+		double k = values[1];
+		double expkt = Math.exp(k*t);
+		return (1 - expkt + expkt*k*t)/(k*k);
+	}
+	
+	double realR4(double t, double[] realEigenValues){
+		double k = realEigenValues[1];
+		double m = realEigenValues[2];
+		double n = realEigenValues[3];
+		double expnt = Math.exp(n*t);
+		double expmt = Math.exp(m*t);
+		double expkt = Math.exp(k*t);
+		return (-(expnt*k*k*m) + k*k*m + 
+		          expnt*k*m*m - k*m*m + expmt*k*k*n - 
+		          k*k*n - expkt*m*m*n + m*m*n - 
+		          expmt*k*n*n + k*n*n + expkt*m*n*n - 
+		          m*n*n)/((-k + m)*(-k + n)*(-m + n)*(k)*(m)*(n));
+	}
+
+	double complexPairR4(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		double n = realEigenValues[3];
+		double expkat = Math.exp(ka*t);
+		double expnt = Math.exp(n*t);
+		double coskbt = Math.cos(kb*t);
+		double sinkbt = Math.sin(kb*t);
+		return (-2*ka*ka*kb + 2*expnt*ka*ka*kb - 2*kb*kb*kb + 2*expnt*kb*kb*kb + 
+			    4*ka*kb*n - 2*kb*n*n - 4*expkat*ka*kb*n*coskbt + 
+			    2*expkat*kb*n*n*coskbt + 
+			    2*expkat*ka*ka*n*sinkbt - 
+			    2*expkat*kb*kb*n*sinkbt - 2*expkat*ka*n*n*sinkbt)/
+			    (2*kb*(ka*ka + kb*kb)*n*(ka*ka + kb*kb - 2*ka*n + n*n));
+	}
+	
+	double realPairR4(double t, double [] values){
+		double k = values[1];
+		double n = values[3];
+		double expkt = Math.exp(k*t);
+		return (-k*k + Math.exp(n*t)*k*k + 2*k*n - 2*expkt*k*n - 
+			       n*n + expkt*n*n + expkt*k*k*n*t - expkt*k*n*n*t)/(k*k*n*(n-k)*(n-k));
+	}
+	double realTripleR4(double t, double[] values){
+		double k = values[1];
+		double expkt = Math.exp(k*t);
+		return (-2 + 2*expkt - 2*expkt*k*t +  expkt*k*k*t*t)/(2*k*k*k);
+	}
+	
+	// Trying to replace Jama matrices with Double2DArrays
+	
+	double[][] plusEquals(double[][]dest, double[][]addend){
+		int numRows1 = Double2DArray.numFullRows(dest);
+		int numRows2 = Double2DArray.numFullRows(addend);
+		int numColumns1 = Double2DArray.numFullColumns(dest);
+		int numColumns2 = Double2DArray.numFullColumns(addend);
+		boolean flag = (numColumns1!= numRows2 || numColumns1!=numColumns2);
+		if (flag) MesquiteMessage.println("Trying to add matrices of differing sizes: " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  
+		             +" to a " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  ); 
+		if (flag)
+		    return null; 
+		for (int i=0; i<numColumns1; i++) 
+			for (int j=0; j<numRows1; j++) 
+				dest[i][j] += addend[i][j];
+		return dest;
+	}
+	
+	double[][]scalarProduct(double[][]source,double multiplier,double[][]result){
+		int numRows = Double2DArray.numFullRows(source);
+		int numColumns = Double2DArray.numFullColumns(source);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		if (result == null || result.length != numRows || (result.length>0 && result[0].length != numColumns))
+			result = new double[numRows][numColumns];
+		for(int i=0;i<numRows;i++)
+			for(int j=0;j<numColumns;j++)
+				result[i][j]=source[i][j]*multiplier;
+		return result;
+	}
+	
+	double[][]minus(double[][]source,double[][]subtractor,double[][]result){
+		int numRows1 = Double2DArray.numFullRows(source);
+		int numRows2 = Double2DArray.numFullRows(subtractor);
+		int numColumns1 = Double2DArray.numFullColumns(source);
+		int numColumns2 = Double2DArray.numFullColumns(subtractor);
+		boolean flag = (numColumns1!= numRows2 || numColumns1!=numColumns2);
+		if (flag) MesquiteMessage.println("Trying to subtract matrices of differing sizes: " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  
+		             +" from a " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  ); 
+		if (flag)
+		    return null; 
+		if (result == null || result.length != numRows1 || (result.length>0 && result[0].length != numColumns1))
+			result = new double[numRows1][numColumns1];
+		Double2DArray.zeroArray(result);
+		for(int i=0;i<numRows1;i++)
+			for(int j=0;j<numColumns1;j++)
+				result[i][j]=source[i][j]-subtractor[i][j];
+		return result;
+	}
+
+	
+	double[][]copy(double[][]source,double[][]result){
+		int numRows1 = Double2DArray.numFullRows(source);
+		int numColumns1 = Double2DArray.numFullColumns(source);
+		if (result == null || result.length != numRows1 || (result.length>0 && result[0].length != numColumns1))
+			result = new double[numRows1][numColumns1];
+		for(int i=0;i<numRows1;i++)
+			for(int j=0;j<numColumns1;j++)
+				result[i][j]=source[i][j];
+		return result;		
+	}
+
+
+	
+
+	double limit = 10000;
+	int beginningAllowed = 6;
+    /**
+     * This version is the main version of the evaluator
+     * @param values is the array of proposed parameter values
+     * @param obj is ignored here and should be null (maybe just pass through command record)
+     */
+	public double evaluate(double[] values, Object obj) {
+	    if (values.length >= 4) {
+	        if (prog != null)
+	            if (prog.isAborted())
+	                throw new StuckSearchException();
+	        double height = workingTree.tallestPathAboveNode(workingTree.getRoot()); // to stop the optimization from wandering if very high rates
+	        if (!sanityChecks(values,limit, height)){
+	            return MesquiteDouble.veryLargeNumber;
+	        }
+	        if (params == null || params.length != values.length)
+	            params = new double[values.length];
+	        for(int i=0;i<values.length;i++)
+	            params[i] = values[i];
+	        prepareMatrices();			
+	        double result =  -this.logLikelihoodCalc(workingTree);
+	        return result;
+	    }
+	    else
+	        return 0;
+	}
+	
+	int estCount =0;
+	boolean zeroHit = false;
+	/*.................................................................................................................*/
+	public double logLikelihoodCalc(Tree tree){
+		if (zeroHit)
+			return -0.001*(++estCount);  // to shortcircuit the optimizer wandering around zero with very high rates
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("Tree passed to logLikelihoodCalc is null");
+			return(-1*MesquiteDouble.veryLargeNumber);
+		}
+		double likelihood = 0.0;
+		double comp;
+		int root = tree.getRoot();
+		if (rootMode == SUM){
+			initProbs2(tree.getNumNodeSpaces(), observedStatesX.getMaxState()+1,observedStatesY.getMaxState()+1); 
+			estCount++;
+			downPass2(root,tree);
+			for (int i = 0; i<=maxState[0]; i++)
+				for (int j = 0; j<=maxState[1];j++) {
+					savedRootEstimates[j][i] = downProbs2[root][j][i];
+					if (savedRootEstimates[j][i] < 0){      // problem, probably due to bad matrix operation
+						likelihood = 0;
+						return(-1*MesquiteDouble.veryLargeNumber);
+					}
+					else
+						likelihood += savedRootEstimates[j][i];
+				}
+		}
+		//else 
+		//	MesquiteMessage.println("Subroot prior and subroot empirical not yet supported");
+		//}
+		//else if (rootMode == SUBROOT_PRIOR){
+		//	if (tree.getRooted())
+		//		for (int i=0; i<numStates; i++) 
+		//			empirical[i] = model.priorProbability(i);
+		//	for (int i=0;  i<=model.getMaxState(); i++) {
+		//		likelihood += downProbs[root][i]*probFromSection(tree, root, i, empirical, model, false);
+		//	}
+		//}
+		//else if (rootMode == SUBROOT_EMPIRICAL){
+		//	calculateEmpirical(tree, observedStates, empirical);
+		//	for (int i=0;  i<=model.getMaxState(); i++) {
+		//		likelihood += downProbs[root][i]*probFromSection(tree, root, i, empirical, model, false);
+		//	}
+		//}
+		comp = underflowCompDown[root];
+		double logLike = Math.log(likelihood) - comp;
+		if (Double.isNaN(logLike)){
+			// These just get too verbose
+			//MesquiteMessage.warnProgrammer("logLikelihoodCalc returned Nan from :" + DoubleArray.toString(params));
+			//if (negativeProbabilities){
+			//	MesquiteMessage.warnProgrammer("Negative transition probabilities were calculated (e.g., " + negativeProbValue + ")");
+			//}
+			return(-1*MesquiteDouble.veryLargeNumber);
+		}
+		if (logLike> -0.00001) {
+			zeroHit = true;
+		}
+		return (logLike);
+	}
+ 		
+ 	private void initProbs2(int nodes, int numStatesX, int numStatesY) {
+ 		if (numStatesX != numStatesY) {
+ 			if (numStatesX >= numStatesY)
+ 				this.numStates = numStatesX;
+ 			else
+ 				this.numStates = numStatesY;
+ 		}
+ 		else if (numStatesX == 1) 
+ 			numStates =2;
+ 			else numStates = numStatesX;
+ 		if  (downProbs2==null || downProbs2.length!=nodes || downProbs2[0].length!=numStatesX || downProbs2[0][0].length!=numStatesY){
+ 		 		downProbs2 = new double[nodes][numStates][numStates];
+ 		 		underflowCompDown = new double[nodes];
+ 		 		//empirical2 = new double[numStates][numStates];
+ 		 		savedRootEstimates = new double[numStates][numStates];
+ 		}
+ 		//Double3DArray.zeroArray(downProbs2);
+ 		for(int i=0;i<nodes;i++){
+ 			Double2DArray.zeroArray(downProbs2[i]);
+ 		}
+ 		DoubleArray.zeroArray(underflowCompDown);
+ 		//Double2DArray.zeroArray(empirical2);
+ 		Double2DArray.deassignArray(savedRootEstimates);
+ 	}
+ 		
+	// overloading for 2 characters
+ 	// This (private) version only goes down from the terminals
+	private double probFromSection(Tree tree, int d, int i, int j, double[][] ProbsD){
+		double prob=0;
+		for (int k=0;k<numStates;k++)
+			for (int l=0;l<numStates;l++){
+				prob += ProbsD[k][l]*transitionProbability(i,k,j,l,tree,d);
+			}
+		return prob;
+	}
+	
+	
+	/*.................................................................................................................*/	
+	// overloading for 2 characters
+	private double checkUnderflow(double[][] probs){
+		if (probs == null || probs.length==0)
+			return 0;
+		minChecker.setValue(MesquiteDouble.unassigned);
+		int probsDim1 = probs.length;
+		int probsDim2 = probs[0].length;
+		for (int i=0;i<probsDim1;i++)
+			for (int j=0;j<probsDim2;j++)
+				minChecker.setMeIfIAmMoreThan(probs[i][j]);
+		double q = minChecker.getDoubleValue();
+		if (q == 0)
+			return 0;
+		else {
+			for (int i=0;i<probsDim1;i++)
+				for (int j=0;j<probsDim2;j++)
+					probs[i][j] /= q;
+		}
+		return -Math.log(q);
+	}
+
+
+	/*.................................................................................................................*/
+	//can't overload since no arrays passed
+	// assumes hard polytomies
+	private void downPass2(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			long observed1 = ((CategoricalDistribution)observedStatesX).getState(tree.taxonNumberOfNode(node));
+			long observed2 = ((CategoricalDistribution)observedStatesY).getState(tree.taxonNumberOfNode(node));
+			int obs1 = CategoricalState.minimum(observed1); //NOTE: just minimum observed!
+			int obs2 = CategoricalState.minimum(observed2);
+			Double2DArray.zeroArray(downProbs2[node]);
+			if (obs1>=0 && obs1 < downProbs2[node].length && !CategoricalState.isUnassigned(observed1) && !CategoricalState.isInapplicable(observed1) &&
+				obs2>=0 && obs2 < downProbs2[node][0].length && !CategoricalState.isUnassigned(observed2) && !CategoricalState.isInapplicable(observed2)) {
+				downProbs2[node][obs1][obs2] = 1;
+			}
+		}
+		else {
+			Double2DArray.zeroArray(downProbs2[node]);
+			underflowCompDown[node]=0;
+			for (int d= tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				downPass2(d,tree);
+				underflowCompDown[node] += underflowCompDown[d];
+			}			
+			for (int i=0;i<numStates;i++)
+				for (int j=0;j<numStates;j++){
+					double prob = 1.0;
+					for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d=tree.nextSisterOfNode(d)){
+						prob *= probFromSection(tree,d,i,j,downProbs2[d]);
+					}
+					downProbs2[node][i][j] = prob;
+			}
+			if (++underflowCheck % underflowCheckFrequency == 0){
+				underflowCompDown[node] += checkUnderflow(downProbs2[node]);
+			}
+		}
+	}
+
+	int allowedEdgeHits = 0; // to stop the optimization from wandering if very high rates; edge allowed to be hit only a certain number of tiems
+	private boolean sanityChecks(double [] eParams, double limit, double height){
+		for(int i=0;i<eParams.length;i++){
+			if (eParams[i]*height>limit && allowedEdgeHits--<0) { // too big
+				return false;
+			}
+			if (eParams[i]<=0){  
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * This is really a stub that exists because there is no class for multivariate evaluators
+	 * 
+	 */
+	public double evaluate(MesquiteDouble param, Object obj) {
+		// TODO Maybe add a class for multivariate evaluators
+		return 0;
+	}
+	
+	//Wayne: this is here so you can use it in Pagel94	- feel free to change the default value
+	public MesquiteInteger getExtraSearch() {
+		return eightParameterExtraSearch;
+	}
+
+	
+	/*
+	 * This just rescales the fixed parameters (as yet unimplemented) by rescale
+	 */
+	private void rescaleFixedParameters(double rescale){
+		for(int i=0;i<qConstant.length;i++)
+			if (qConstrained[i] && qBound[i]<0 && MesquiteDouble.isCombinable(qConstant[i]))
+				qConstant[i] *= rescale;
+	}
+
+	private void rescaleAllParameters(double rescale){
+		for(int i=0;i<params.length;i++)
+			params[i] *= rescale;
+	}
+
+    static final boolean scaleRescale = true;  
+ 
+    public void estimateParameters(Tree originalTree, CategoricalDistribution observedStatesX, CategoricalDistribution observedStatesY) {
+ //   	if (observedStates1==null || observedStates2==null)
+ //   		return;
+    	
+        this.observedStatesX = observedStatesX;
+        this.observedStatesY = observedStatesY;
+    		// Special treatment for constant states just isn't working out here
+    		if (observedStatesX.getMaxState()>= 1)
+    			maxState[0] = observedStatesX.getMaxState();
+    		else
+    			maxState[0] = 1;
+    		if (observedStatesY.getMaxState()>= 1)
+        		maxState[1] = observedStatesY.getMaxState();
+    		else
+    			maxState[1] = 1;
+
+		allStates[0] = CategoricalState.span(0,maxState[0]);
+		allStates[1] = CategoricalState.span(0,maxState[1]);
+		double height = 0;
+		double invHeight = MesquiteDouble.unassigned;
+		if (scaleRescale){  //rescales tree to 1.0 height to help optimization, which takes longer with larger numbers
+			MesquiteTree mTree = originalTree.cloneTree();
+			mTree.setAllUnassignedBranchLengths(1.0, false);
+			height = mTree.tallestPathAboveNode(mTree.getRoot(), 1.0); // to adjust start point depending on how tall is tree
+			if (height != 0){
+				invHeight = 1.0/height;
+				mTree.scaleAllBranchLengths(invHeight, false);
+				rescaleFixedParameters(height);
+			}
+			workingTree= mTree;
+		}
+		else  
+			workingTree = originalTree;
+		Optimizer opt = new Optimizer(this);
+		// **** estParams is the matrix of trial values
+		double estParams[];
+		// estjust saves the starting values for error reporting
+		double backupEst[] = null;
+
+		switch (modelType) {
+			case MODEL8PARAM:{  // first try two versions of a 6-parameter model
+				estParams = new double[8];
+				double [] b = new double[8];
+				double next;
+				double best = Double.MAX_VALUE;
+				// no need to reallocate the two 6-p models everytime
+				if (intermediate1 == null)
+					intermediate1 = new PagelMatrixModel("",CategoricalState.class,MODEL6PARAMINDEPENDENTX);
+				if (intermediate2 == null)
+					intermediate2 = new PagelMatrixModel("",CategoricalState.class,MODEL6PARAMINDEPENDENTY);
+				PagelMatrixModel model6_cy = intermediate1;
+				PagelMatrixModel model6_cx = intermediate2;
+				// first a model with changes in Y contingent on changes in X
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL6PARAMINDEPENDENTX){
+				    model6_cy.setParametersFromSimplerModel(parametersFromSimplerModel,simplerModelType);
+					model6_cy.estimateParameters(workingTree,observedStatesX, observedStatesY);
+					double[] m6_1Params = model6_cy.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m6_1Params[i];
+					estParams[4]=m6_1Params[4];
+					estParams[5]=m6_1Params[0];
+					estParams[6]=m6_1Params[5];
+					estParams[7]=m6_1Params[2];
+				}
+				else { 
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					estParams[4]=parametersFromSimplerModel[4];
+					estParams[5]=parametersFromSimplerModel[0];
+					estParams[6]=parametersFromSimplerModel[5];
+					estParams[7]=parametersFromSimplerModel[2];
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				next = opt.optimize(estParams, null); // try optimizing from the contingentchangeY best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+				}
+				else {     //shouldn't need to compare best with next here
+					best = next;
+					for (int i=0; i< estParams.length; i++)
+						b[i] = estParams[i];
+				}
+				// now the other 6-parameter model (changes in X contingent on Y)
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL6PARAMINDEPENDENTY){
+				    model6_cx.setParametersFromSimplerModel(parametersFromSimplerModel,simplerModelType);
+					model6_cx.estimateParameters(workingTree,observedStatesX, observedStatesY);
+					double[] m6_2Params = model6_cx.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m6_2Params[i];
+					estParams[4]=m6_2Params[1];
+					estParams[5]=m6_2Params[4];
+					estParams[6]=m6_2Params[3];
+					estParams[7]=m6_2Params[5];
+				}
+				else { 
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					estParams[4]=parametersFromSimplerModel[1];
+					estParams[5]=parametersFromSimplerModel[4];
+					estParams[6]=parametersFromSimplerModel[3];
+					estParams[7]=parametersFromSimplerModel[5];
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+				}
+				else if (next<best) {
+					best = next;
+					for (int i=0; i< estParams.length; i++)
+						b[i] = estParams[i];
+				}
+				//PETER: added these tick notifications to keep user informed of progress of search
+				CommandRecord.tick("8 parameter model preliminary -ln likelihood: " + MesquiteDouble.toString(best));
+				if (eightParameterExtraSearch.getValue() > 0) {
+					double [] m6_cy_Params = model6_cy.getParams();
+					double [] m6_cx_Params = model6_cx.getParams();
+					for (int i = 0; i< eightParameterExtraSearch.getValue();i++){
+						for(int j=0;j<4;j++)
+							estParams[j]=Math.abs((m6_cy_Params[j]+m6_cx_Params[j])/2 + (20.0*rng.nextGaussian())*(m6_cx_Params[j]-m6_cy_Params[j]));
+						estParams[4]=Math.abs(1+20.0*rng.nextGaussian())*m6_cy_Params[4];
+						estParams[5]=Math.abs(1+20.0*rng.nextGaussian())*m6_cx_Params[4];
+						estParams[6]=Math.abs(1+20.0*rng.nextGaussian())*m6_cy_Params[5];
+						estParams[7]=Math.abs(1+20.0*rng.nextGaussian())*m6_cx_Params[5];
+						allowedEdgeHits = beginningAllowed;
+						//backupEst = (double [])estParams.clone();
+						next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+						if (!acceptableResults(next, estParams)) {
+							MesquiteMessage.warnProgrammer("Warning: NaN encountered in PagelMatrixModel optimization");
+							reportUnacceptableValues(next, estParams,backupEst);
+						}
+						else if (next<best) {
+							best = next;
+							for (int m=0; m< estParams.length; m++)
+								b[m] = estParams[m];
+						}
+						CommandRecord.tick("8 parameter model -ln likelihood after " + (i+1) + " searches: " + MesquiteDouble.toString(best));
+					}
+				}
+		 		if (params == null ||params.length != 8)
+		 			params = new double[8];
+		 		for(int i=0;i<b.length;i++)
+		 			params[i]= b[i];
+
+				break;
+			}
+			case MODEL6PARAMINDEPENDENTY:
+			case MODEL6PARAMINDEPENDENTX: {
+				estParams = new double[6];
+				if (params == null ||params.length != 6)
+					params = new double[6];
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL4PARAM) {
+					PagelMatrixModel model4 = new PagelMatrixModel("",CategoricalState.class,MODEL4PARAM);
+					model4.estimateParameters(workingTree,observedStatesX, observedStatesY);
+					double [] m4Params = model4.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m4Params[i];
+					if (modelType == MODEL6PARAMINDEPENDENTY){  
+						estParams[4]=m4Params[2];
+						estParams[5]=m4Params[3];
+					}
+					else {
+						estParams[4]=m4Params[0];
+						estParams[5]=m4Params[1];
+					}
+				}
+				else { // TODO need to get the parameters from the previous model
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					if (modelType == MODEL6PARAMINDEPENDENTY){  
+						estParams[4]=parametersFromSimplerModel[2];
+						estParams[5]=parametersFromSimplerModel[3];
+					}
+					else {
+						estParams[4]=parametersFromSimplerModel[0];
+						estParams[5]=parametersFromSimplerModel[1];
+					}
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				double next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+				}
+				else { 
+					for(int i=0;i<estParams.length;i++)
+						params[i]= estParams[i];
+				}
+				break;
+			}
+			case MODEL4PARAM: {  // for now, just use flip/flop, though we might try getting estimates from MODEL2PARAM in the future
+				estParams = new double[4];
+				double[] b = new double[4];
+				double best = Double.MAX_VALUE;
+				double next;
+				estParams[2] = FLIP_FLOP_HIGH;
+				estParams[3] = FLIP_FLOP_HIGH;
+				estParams[0] = FLIP_FLOP_HIGH;
+				estParams[1] = FLIP_FLOP_HIGH;
+				for(int i = 0;i<4;i++)
+					b[i] = estParams[i];
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.warnProgrammer("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else{
+		 			best = next;
+					for (int i=0; i< 4; i++)
+						b[i] = estParams[i];
+		 		}
+				estParams[0] = FLIP_FLOP_LOW;
+				estParams[2] = FLIP_FLOP_LOW; //
+				estParams[1] = FLIP_FLOP_HIGH;  //forward
+				estParams[3] = FLIP_FLOP_HIGH;
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else if (next<best) {
+		 			best = next;
+					for (int i=0; i< estParams.length; i++)
+						b[i] = estParams[i];
+		 		}
+		 		estParams[0] = FLIP_FLOP_HIGH;
+				estParams[2] = FLIP_FLOP_HIGH; //
+				estParams[1] = FLIP_FLOP_LOW;  //forward
+				estParams[3] = FLIP_FLOP_LOW;
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else if (next<best) {
+		 			best = next;
+					for (int i=0; i< estParams.length; i++)
+						b[i] = estParams[i];
+		 		}
+		 		if (params == null ||params.length != 4)
+		 			params = new double[4];
+		 		for(int i=0;i<b.length;i++)
+		 			params[i]= b[i];
+				CommandRecord.tick("4 parameter model -ln likelihood: " + MesquiteDouble.toString(best));
+				break;
+			}
+			case MODEL2PARAM: {  // NO-OP FOR NOW, the model exists, the framework for using it doesn't
+			 	MkModel model2 = new MkModel("asymm helper", CategoricalState.class); //used to provide preliminary guess at rate
+				MesquiteMessage.warnUser("The 2 parameter model isn't currently supported here");
+				break;
+			}
+		} // end switch (??)
+		if (scaleRescale && height != 0){ //UNDO the scaling of the tree
+			rescaleAllParameters(invHeight);
+			workingTree = originalTree;  // faster, less error prone than rescaling from mTree??
+		 }
+		//prepareMatrices();
+	}
+    
+	
+    /**
+     * 
+     * @return array of doubles containing the parameters estimated for this model
+     */
+    public double[] getParams() {
+    		return params;
+    }
+    
+    /**
+     * 
+     */
+    public double[][] getRootPriors(){
+    		double[][] rootPriors;
+    		if (savedRootEstimates == null)
+    			return null;
+    		else {
+    			double total = 0;
+    			int estimateLength = savedRootEstimates.length;  // what are these really?
+    			int estimateWidth = savedRootEstimates[0].length;
+    			rootPriors = new double[estimateLength][estimateWidth];
+    			for (int i=0;i<estimateLength;i++)
+    				for (int j=0;j<estimateWidth;j++)
+    					total += savedRootEstimates[i][j];
+    			for (int i=0;i<estimateLength;i++)
+    				for (int j=0;j<estimateWidth;j++)
+    					rootPriors[i][j] = savedRootEstimates[i][j]/total;
+    		}
+    		return rootPriors;
+    }
+    
+    /**
+     * This provides a mechanism to pass best parameter estimates from a simpler (independent/4 parameter) model
+     * @param hint array of doubles containing the parameter estimates
+     */
+    public void setParametersFromSimplerModel(double[] hint,int mtype){
+		parametersFromSimplerModel = hint;
+		simplerModelType = mtype;
+    }
+
+    
+
+	public void deassignParameters() {
+		// TODO Auto-generated method stub
+	}
+	
+	public long[] getRootStates(Tree tree, double[][] rootStatePriors){
+		long[] result = new long[charsFromBehavior(modelType)];   // always a safe choice
+		if ((rootStatePriors != null) && (modelType < MODEL3CHARACTERINDEPENDENT)){
+			double r = randomNumGen.nextDouble();
+			double accumProb = 0;
+			for (int i=0;i<rootStatePriors[0].length;i++) {
+				for (int j=0;j<rootStatePriors.length;j++) {
+					accumProb += rootStatePriors[j][i];
+					if (r<accumProb){
+						result[0]=CategoricalState.makeSet(i);
+						result[1]=CategoricalState.makeSet(j);
+						return result;
+					}
+				}
+			}
+			result[0]=rootStatePriors[0].length;
+			result[1]=rootStatePriors[1].length;
+			return result;
+		}
+		else {
+			for(int c=0;c<result.length;c++){
+				result[c]=getRootState(tree,c);
+			}
+			return result;
+		}
+	}
+	
+	public long getRootState (Tree tree,int c){
+		if (maxState[c] <= 0) 
+			return (1L);  //if only state 0 allowed, return it
+		else {
+			double r = randomNumGen.nextDouble();
+			double accumProb = 0;
+			for (int i=0; i<maxState[c]; i++) {
+				accumProb +=  priorProbability(i,c);
+				if (r< accumProb)
+					return CategoricalState.makeSet(i);
+			}
+			return CategoricalState.makeSet(maxState[c]);
+		}
+	}
+	
+	
+	/**
+	 * return a flat prior for a character estimate at the root
+	 */
+	public double flatPriorProbability (int state,int c){
+		if (!inStates(state,c)) 
+			return 0;
+		else
+			if (maxState[c] == 0)
+				return (0.5);  // flat prior
+			else
+				return (1.0/(maxState[c]+1));  // flat prior
+	}
+
+	/* ---------------------------------------------*/	
+	public int[] evolveState (int beginState[], Tree tree, int node){
+		int index = recodeStatePair(beginState[0],beginState[1]);
+		double r = randomNumGen.nextDouble();
+		double branchLength = tree.getBranchLength(node, 1.0);
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix == null)
+			return null;
+		if (index> probMatrix[0].length)  //TODO replace with appropriate test
+			return null;
+		double accumProb = 0;
+		int resultCode = recodeStatePair(maxState[0],maxState[1]);
+		for (int i=0; i<probMatrix.length; i++) {
+			accumProb +=  probMatrix[i][index];
+			if (r< accumProb){
+				resultCode = i;
+				break;
+			}
+		}
+		return statePairFromCode(resultCode);
+	}
+
+	
+	public void evolveState (CharacterState[] beginState, CharacterState[] endState, Tree tree, int node){
+		if (beginState == null || endState==null) {
+			return;
+		}
+		if (!(beginState instanceof CategoricalState[]) || !(endState instanceof CategoricalState[])){
+			for(int i=0;i<endState.length;i++)
+				endState[i].setToUnassigned();
+			return;
+		}
+		CategoricalState[] bState = (CategoricalState[])beginState;
+		CategoricalState[] eState = (CategoricalState[])endState;
+		int [] bsa = new int[bState.length];
+		for(int i=0;i<bsa.length;i++)
+			bsa[i] = CategoricalState.minimum(bState[i].getValue());
+		int []r = evolveState(bsa, tree, node); //todo: issue error if beginning is polymorphic?  choose randomly among beginning?
+		for(int i=0;i<r.length;i++)
+			eState[i].setValue(CategoricalState.makeSet(r[i]));
+	}
+
+	public String getModelTypeAsString() {
+		switch (modelType){
+			case MODEL4PARAM:{
+				return "4 Parameter model";
+			}
+			case MODEL8PARAM:{
+				return "8 parameter model";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {
+				return "7 parameter model y forward change contingent on x";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: { 
+				return "7 parameter model y backward change contigent on x";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXFORWARD: {
+				return "7 parameter model x forward change contingent on y";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD: {
+				return "7 parameter model x forward change contingent on y";
+			}
+			case MODEL6PARAMINDEPENDENTX: {
+				return "6 parameter model x change independent of y";
+			}
+			case MODEL6PARAMINDEPENDENTY:{
+				return "6 parameter model y change independent of X";
+			}
+		}
+		return null;
+	}
+	public String getParameters() {
+		switch (modelType){
+			case MODEL4PARAM:{
+				return "q12(alpha1) =" + params[1] + "\nq13(alpha2) = " 
+				             + params[0] + "\nq21(beta1) = " + params[3] + "\nq31(beta2) = " + params[2]+ "\nRATEMATRIX\n" + Double2DArray.toString(rateMatrix);  //Debugg.println
+			}
+			case MODEL8PARAM:{
+				return "q12 = " + params[0] + "\nq13 = " + params[1] + 
+				         "\nq21 = " + params[2] + "\nq31 = " + params[3] +
+				         "\nq24 = " + params[4] + "\nq34 = " + params[5] +
+				         "\nq42 = " + params[6] + "\nq43 = " + params[7];
+
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {  //ToDo check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[0] +
+		                  " q42 = " + params[5] + " q43 = " + params[6];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[5] +
+		                  " q42 = " + params[6] + " q43 = " + params[2];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXFORWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[1] + " q34 = " + params[4] +
+		                  " q42 = " + params[5] + " q43 = " + params[6];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[5] +
+		                  " q42 = " + params[3] + " q43 = " + params[6];
+			}
+			case MODEL6PARAMINDEPENDENTX: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[0] +
+		                  " q42 = " + params[5] + " q43 = " + params[2] + "\nRATEMATRIX\n" + Double2DArray.toString(rateMatrix);  //Debugg.println
+			}
+			case MODEL6PARAMINDEPENDENTY:{  //TODO trim me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[1] + " q34 = " + params[4] +
+		                  " q42 = " + params[3] + " q43 = " + params[5]+ "\nRATEMATRIX\n" + Double2DArray.toString(rateMatrix);  //Debugg.println
+			}
+		}
+		return null;
+	}
+	
+	
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof PagelMatrixModel))
+			return;
+		super.copyToClone(md);
+		PagelMatrixModel model = (PagelMatrixModel)md;
+		model.params = (double[])params.clone();
+		model.recalcProbsNeeded = true;
+		model.needToPrepareMatrices = true;
+		model.qMapping = (int [])qMapping.clone();          // mapping from known, underparameterized models
+		model.qConstrained = (boolean[]) qConstrained.clone();  // true if a q value is somehow constrained
+		model.qBound = (int []) qBound;           // qvalue bound to another qvalue (-1 = not bound)
+		model.qConstant = (double []) qConstant;     // qvalue is set to this constant; 
+		model.savedRootEstimates = (double [][])savedRootEstimates;
+		model.prepareMatrices();
+		model.notifyListeners(model, new Notification(MesquiteListener.UNKNOWN));
+	}
+	
+
+
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		PagelMatrixModel j = new PagelMatrixModel(name, getStateClass(), modelType);
+		copyToClone(j);
+		j.recalcProbsNeeded = true;
+		j.needToPrepareMatrices = true;
+		completeDaughterClone(formerClone, j);
+		j.prepareMatrices();
+		return j;			
+	}
+
+	public boolean isFullySpecified() {
+		boolean result = true;
+		for (int i = 0;i<params.length;i++)
+			if (params[i] == MesquiteDouble.unassigned)
+				result = false;
+		return result;
+	}
+
+	public String getModelTypeName() {
+		// TODO Auto-generated method stub
+		return "Stochastic matrix model as described in Pagel1994";
+	}
+
+	public String getExplanation() {
+		return "Estimates and simulates discrete characters using the matrices described in Pagel 1994";
+	}
+	
+	
+    public void showSurface(Tree tree,CategoricalDistribution dist1, CategoricalDistribution dist2, int divisions) {
+    	    Tree savedTree = workingTree;
+    	    workingTree = tree;
+    	    CategoricalDistribution savedObservedStates1 = observedStatesX;
+    	    observedStatesX = dist1;
+    	    CategoricalDistribution savedObservedStates2 = observedStatesY;
+    	    observedStatesY = dist2;
+        double [] outBounds = new double[params.length];
+        double [] upperBounds = new double[params.length];
+        for (int i = 0;i<upperBounds.length;i++)
+        		upperBounds[i] = 8.5;
+        double [] lowerBounds = new double[params.length];
+        for (int i = 0;i<lowerBounds.length;i++)
+        		lowerBounds[i] = 0.5;
+        getLikelihoodSurface(16,outBounds,upperBounds,lowerBounds);
+        // restore fields
+        workingTree = savedTree;
+        observedStatesX = savedObservedStates1;
+        observedStatesY = savedObservedStates2;
+    }
+    private void getLikelihoodSurface(int divisions,double[] outputBounds,double[]upperBounds,double[]lowerBounds){ //also pass upper & lower bounds
+        // hold paramCount-2 parameters fixed, vary pairs through fixed bounds; just call evaluate
+        // put values into surface, then write values to mesquite console
+        Optimizer opt = new Optimizer(this);
+        boolean savedUnassigned []= (boolean [])paramUnassigned.clone();
+        double savedParams[] = (double [])params.clone();
+        paramUnassigned = new boolean[params.length];       
+        double[] localParams = new double[params.length];
+       // for (int i=0;i<localParams.length;i++)
+      //	   localParams[i] = 8.0;
+        double[][] surface = new double[divisions][divisions];
+        for (int j= 0;j<divisions;j++){
+        		double x = (j*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+             for (int k=0;k<divisions;k++){
+                 double y = (k*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                 for(int l=0;l<divisions;l++){
+                	    double z = (l*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                	    for(int m=0;m<divisions;m++) {
+                	    	   double w = (m*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                	    	   localParams[0]=x;
+                	    	   localParams[1]=y;
+                	    	   localParams[2]=z;
+                	    	   localParams[3]=w;
+                	    	   //surface[j][k]=evaluate(localParams,null);
+                	    }
+                }
+            }
+//            localParams[2*i] = savedParams[2*i];
+//            localParams[2*i+1] = savedParams[2*i+1];
+        }
+        if (outputBounds == null) {
+            MesquiteMessage.warnProgrammer("No double[][] array supplied to receive output bounds or array too small");
+        }
+        if (outputBounds.length != 2) {
+            MesquiteMessage.warnProgrammer("Array supplied to receive output bounds too small");
+        }
+        //THIS DOESN'T work at present
+        //arbitrarily choose the midpoints
+        if (upperBounds != null && lowerBounds != null){
+            for(int i=0;i<params.length;i++){
+                if (MesquiteDouble.isCombinable(upperBounds[i]) &&
+                    MesquiteDouble.isCombinable(lowerBounds[i]))
+                    params[i] = (upperBounds[i]+lowerBounds[i])/2;
+                else
+                    params[i] = 0.001;  //avoid zero in case of model pathology
+                }
+            }
+            else {
+                for(int i=0;i<params.length;i++)
+                    params[i] = 0.001;
+            }
+            opt.optimize(params, null);
+            if (upperBounds == null)
+                upperBounds = opt.getUpperBoundsSearched();
+            if (lowerBounds == null)
+                lowerBounds = opt.getLowerBoundsSearched();
+            for(int i=0;i<upperBounds.length;i++){  //assumes upperBounds.length == lowerBounds.length
+                if (upperBounds[i]<0)
+                    upperBounds[i] = 0;
+                if (lowerBounds[i]<0)
+                    lowerBounds[i] = 0;
+            }
+        paramUnassigned = savedUnassigned;
+        this.params = savedParams;
+    }
+    
+    public double[][] grid(double[] params,int[]freeParams,double min1, double max1, double min2, double max2, int divisions){
+        double[][] g = new double[divisions][divisions];
+        double[] x = new double[params.length];
+        for (int i = 0;i<params.length;i++)
+            if (i!=freeParams[0] && i!=freeParams[1])
+                x[i]=params[i];
+        for (int i = 0; i<divisions; i++){
+            x[freeParams[0]] =i* (max1-min1)/divisions + min1;
+            for (int j = 0; j<divisions; j++){
+                x[freeParams[1]] =j* (max2-min2)/divisions + min2;
+                double fcn = evaluate(x, null);
+                g[i][j] = fcn;
+                //System.out.println(x[0] + "\t" + x[1] + "\t" + fcn);
+            }
+        }
+        return g;
+    }
+
+    /* All the following are useful for debugging, but shouldn't be called in released code. */
+    
+    public void setTree(Tree tree) {
+    		this.workingTree = tree;
+    }
+    
+    public void setObserved1(CategoricalDistribution dist1) {
+    		this.observedStatesX = dist1;
+    }
+    
+    // fix this
+    public void setObserved2(CategoricalDistribution dist2) {
+		this.observedStatesY = dist2;
+		maxState[0] = observedStatesX.getMaxState();    	
+		maxState[1] = observedStatesY.getMaxState();
+		allStates[0] = CategoricalState.span(0,maxState[0]);
+		allStates[1] = CategoricalState.span(0,maxState[1]);
+    }
+    
+    // end debugging methods
+    
+    public void setProgress(ProgressIndicator p){
+    		prog = p;
+    }
+    
+    public class StuckSearchException extends RuntimeException{
+    }
+
+
+}   
+
diff --git a/Source/mesquite/correl/notes/PEM Notes b/Source/mesquite/correl/notes/PEM Notes
new file mode 100644
index 0000000..d550087
--- /dev/null
+++ b/Source/mesquite/correl/notes/PEM Notes	
@@ -0,0 +1 @@
+Pagel94 hangs if character column contains all unknown values.
diff --git a/Source/mesquite/correl/notes/Pagel94Hominids.nex b/Source/mesquite/correl/notes/Pagel94Hominids.nex
new file mode 100644
index 0000000..d667ebe
--- /dev/null
+++ b/Source/mesquite/correl/notes/Pagel94Hominids.nex
@@ -0,0 +1,313 @@
+#NEXUS
+[written Wed Apr 12 20:15:39 PDT 2006 by Mesquite  version 1.06+ (build h55) at Pellenes-4.local/10.0.1.2]
+
+BEGIN TAXA;
+	TITLE Taxa_from_Pagel_format_file;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Homo_sapiens Pan_troglodytes Pan_paniscus Gorilla_gorilla Pongo_pygmaeus Hylobates_syndactylus Hylobates_sp. Colobus_guereza Colobus_badius 
+	;
+	IDS 010a627b503f49 010a627b503f50 010a627b503f51 010a627b503f52 010a627b503f53 010a627b504054 010a627b504055 010a627b504056 010a627fb2ef57 ;
+	BLOCKID 010a627b503c3;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 advertisement /  absent present, 2 mating_system /  one_male 'multi-male' ; 
+	MATRIX
+	Homo_sapiens           00
+	Pan_troglodytes        11
+	Pan_paniscus           11
+	Gorilla_gorilla        00
+	Pongo_pygmaeus         10
+	Hylobates_syndactylus  00
+	Hylobates_sp.          00
+	Colobus_guereza        00
+	Colobus_badius         11
+
+;
+	IDS 010a627b503f4 010a627b503f5 ;
+	BLOCKID 010a913a4e450;
+
+
+END;
+BEGIN TREES;
+	Title Trees_imported_from_Pagel_file;
+	LINK Taxa = Taxa_from_Pagel_format_file;
+	TRANSLATE
+		1 Homo_sapiens,
+		2 Pan_troglodytes,
+		3 Pan_paniscus,
+		4 Gorilla_gorilla,
+		5 Pongo_pygmaeus,
+		6 Hylobates_syndactylus,
+		7 Hylobates_sp.,
+		8 Colobus_guereza,
+		9 Colobus_badius;
+	TREE page_16_example = ((8:2.0,9:2.0):56.0,((5:22.0,(4:20.0,(1:29.0,(2:9.0,3:5.0):15.0):11.0):10.0):18.0,(6:3.0,7:2.0):28.0):10.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 878585605735200005 010a627b503c3;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7359026449824636807 010a913a4e450;
+			checksum 0 1601284411;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #878585605735200005  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1199.1144113549683.1862327035904205997;
+				getTreeWindow;
+				tell It;
+					setSize 633 567;
+					setLocation 518 22;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BranchLengthsAdjust.AdjustToolExtra.adjustor;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale off;
+							toggleCenter on;
+							toggleEven on;
+							namesAngle ?;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths off;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setFontSize 14;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize on;
+					toggleTextOnTree off;
+					newWindowAssistant  #mesquite.correl.Pagel94Viewer.Pagel94Viewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #7359026449824636807;
+					endTell;
+					getPagel94  #mesquite.correl.Pagel94.Pagel94;
+					tell It;
+						setSeed 1144122254599;
+						setSimCount 0;
+						togglePresentPValue off;
+						setNumIterations 2;
+					endTell;
+					setX -1;
+					setY 0;
+					doCounts;
+				endTell;
+					newWindowAssistant  #mesquite.trees.MirrorTreeWindowMaker.MirrorTreeWindowMaker;
+				tell It;
+					getWindow;
+					tell It;
+						setSize 508 441;
+						setLocation 4 24;
+						setFont SanSerif;
+						setFontSize 10;
+						onInfoBar;
+						setExplanationSize 30;
+						setAnnotationSize 0;
+						setFontIncAnnot 0;
+						setFontIncExp 0;
+						setActive;
+						newAssistantLeft #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7359026449824636807;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							endTell;
+						endTell;
+						setCharacter 1;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX 20;
+						setInitialOffsetY -171;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+						newAssistantRight #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+					tell It;
+						suspend ;
+						setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+						tell It;
+							toggleLabels off;
+						endTell;
+						setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+						tell It;
+							getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+							tell It;
+								setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+								tell It;
+									setDataSet #7359026449824636807;
+								endTell;
+							endTell;
+							setMethod  #mesquite.parsimony.ParsAncestralStates.ParsAncestralStates;
+							tell It;
+								setModelSource  #mesquite.parsimony.CurrentParsModels.CurrentParsModels;
+							endTell;
+						endTell;
+						setCharacter 2;
+						setMapping 1;
+						toggleShowLegend off;
+						toggleGray off;
+						toggleWeights on;
+						setInitialOffsetX -162;
+						setInitialOffsetY -158;
+						setLegendWidth 142;
+						setLegendHeight 158;
+						resume ;
+					endTell;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+					tell It;
+						suppress;
+						setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+						tell It;
+							setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+							tell It;
+								stretchToggle off;
+								branchLengthsToggle off;
+								toggleScale off;
+								toggleCenter on;
+								toggleEven on;
+								namesAngle ?;
+							endTell;
+							setEdgeWidth 10;
+							orientLeft;
+							toggleCorners off;
+						endTell;
+						setBackground White;
+						setBranchColor Black;
+						showNodeNumbers off;
+						labelBranchLengths off;
+						desuppress;
+						getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+						tell It;
+							setFontSize 12;
+							setColor Black;
+							toggleColorPartition on;
+							toggleShadePartition off;
+							toggleNodeLabels on;
+							toggleShowNames on;
+						endTell;
+					endTell;
+					showWindow;
+					getEmployee #mesquite.cartographer.TaxonGroupSymbols.TaxonGroupSymbols;
+					tell It;
+						showSymbols off;
+						combineColors off;
+						setColors on;
+					endTell;
+				endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.cartographer.TaxonGroupSymbols.TaxonGroupSymbols;
+				tell It;
+					showSymbols off;
+					combineColors off;
+					setColors on;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.collab.ManageAuthors.ManageAuthors;
+		tell It;
+			addAuthorNameToMatrices;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/correl/notes/Pagel94test.nex b/Source/mesquite/correl/notes/Pagel94test.nex
new file mode 100644
index 0000000..8eeb308
--- /dev/null
+++ b/Source/mesquite/correl/notes/Pagel94test.nex
@@ -0,0 +1,314 @@
+#NEXUS
+[written Mon Apr 03 21:03:36 PDT 2006 by Mesquite  version 1.06+ (build h54) at Pellenes-4.local/10.0.1.2]
+
+BEGIN TAXA;
+	TITLE Taxa_from_Pagel_format_file;
+	DIMENSIONS NTAX=9;
+	TAXLABELS
+		Homo_sapiens Pan_troglodytes Pan_paniscus Gorilla_gorilla Pongo_pygmaeus Hylobates_syndactylus Hylobates_sp. Colobus_guereza Colobus_badius 
+	;
+	IDS 010a627b503f49 010a627b503f50 010a627b503f51 010a627b503f52 010a627b503f53 010a627b504054 010a627b504055 010a627b504056 010a627fb2ef57 ;
+	BLOCKID 010a627b503c3;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	CHARSTATELABELS 
+		1 advertisement /  absent present, 2 mating_system /  one_male 'multi-male' ; 
+	MATRIX
+	Homo_sapiens           00
+	Pan_troglodytes        11
+	Pan_paniscus           11
+	Gorilla_gorilla        00
+	Pongo_pygmaeus         10
+	Hylobates_syndactylus  00
+	Hylobates_sp.          00
+	Colobus_guereza        00
+	Colobus_badius         11
+
+;
+	IDS 010a627b503f4 010a627b503f5 ;
+	BLOCKID 010a630cf9570;
+
+
+END;
+BEGIN TREES;
+	Title Trees_imported_from_Pagel_file;
+	LINK Taxa = Taxa_from_Pagel_format_file;
+	TRANSLATE
+		1 Homo_sapiens,
+		2 Pan_troglodytes,
+		3 Pan_paniscus,
+		4 Gorilla_gorilla,
+		5 Pongo_pygmaeus,
+		6 Hylobates_syndactylus,
+		7 Hylobates_sp.,
+		8 Colobus_guereza,
+		9 Colobus_badius;
+	TREE page_16_example = ((8:2.0,9:2.0):56.0,((5:22.0,(4:20.0,(1:29.0,(2:9.0,3:5.0):15.0):11.0):10.0):18.0,(6:3.0,7:2.0):28.0):10.0):1.0;
+
+END;
+
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 878585605735200005 010a627b503c3;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 7359026449824636807 010a630cf9570;
+			checksum 0 1601284411;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #7359026449824636807 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 359 409;
+					setLocation 749 26;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.ibeam;
+					endTell;
+					setActive;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.ibeam;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWithCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					setColumnWidth 16;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.collab.AnnotInfo.AnnotInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.CellImages.CellImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.ChgHistoryInfo.ChgHistoryInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.StateImages.StateImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.aaManageImageIndices.aaManageImageIndices;
+				tell It;
+					setLocal;
+					setPrevIndexBase 'http://mesquiteproject.org/mesquite/collab/indexedImages';
+					reset;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #878585605735200005  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1199.1144113549683.1862327035904205997;
+				getTreeWindow;
+				tell It;
+					setSize 731 565;
+					setLocation 4 23;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.trees.BranchLengthsAdjust.AdjustToolExtra.adjustor;
+					endTell;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.SquareTree.SquareTree;
+					tell It;
+						setNodeLocs #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale off;
+							toggleCenter on;
+							toggleEven on;
+							namesAngle ?;
+						endTell;
+						setEdgeWidth 6;
+						orientRight;
+						toggleCorners off;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths on;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize on;
+					toggleTextOnTree off;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #7359026449824636807;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 1   'Mk1 (est.)';
+							endTell;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Sum_Likelihoods;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 2;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX 291;
+					setInitialOffsetY -176;
+					setLegendWidth 142;
+					setLegendHeight 158;
+					resume ;
+				endTell;
+					newWindowAssistant  #mesquite.correl.Pagel94Viewer.Pagel94Viewer;
+				tell It;
+					getCharSource  #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+					tell It;
+						setDataSet #7359026449824636807;
+					endTell;
+					getPagel94  #mesquite.correl.Pagel94.Pagel94;
+					tell It;
+						setSeed 1144122254599;
+						setSimCount 0;
+						togglePresentPValue off;
+						setNumIterations 2;
+					endTell;
+					setX -1;
+					setY 0;
+					doCounts;
+				endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.cartographer.TaxonGroupSymbols.TaxonGroupSymbols;
+				tell It;
+					showSymbols off;
+					combineColors off;
+					setColors on;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.collab.ManageAuthors.ManageAuthors;
+		tell It;
+			addAuthorNameToMatrices;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/correl/notes/Pagel94test.ppy b/Source/mesquite/correl/notes/Pagel94test.ppy
new file mode 100644
index 0000000..0798f8c
--- /dev/null
+++ b/Source/mesquite/correl/notes/Pagel94test.ppy
@@ -0,0 +1,30 @@
+#Translated to Pagel format for Discrete from project with home file Pagel94test.nex
+# Block of taxa: Hominoidea
+# First Character: Single/Multi male of data matrix SS/oestrous
+# Second Character: oestrous swellings of data matrix SS/oestrous
+# Tree: Pagel Test Tree+
+t1,10,29.0,0,0
+t2,9,12.0,1,1
+t3,9,5.0,1,1
+t4,11,20.0,0,0
+t5,12,22.0,1,0
+t6,13,3.0,0,0
+t7,13,2.0,0,0
+t8,15,69.0,0,0
+9,10,15.0
+10,11,11.0
+11,12,10.0
+12,14,18.0
+13,14,28.0
+14,15,1.0
+
+
+#Table of equivalencies of nodes with Mesquite's node numbering system
+# node 9 = Mesquite node 8
+# node 10 = Mesquite node 6
+# node 11 = Mesquite node 5
+# node 12 = Mesquite node 4
+# node 13 = Mesquite node 13
+# node 14 = Mesquite node 3
+# node 15 = Mesquite node 2
+
diff --git a/Source/mesquite/correl/notes/Putzer method b/Source/mesquite/correl/notes/Putzer method
new file mode 100644
index 0000000..e2d46ae
--- /dev/null
+++ b/Source/mesquite/correl/notes/Putzer method	
@@ -0,0 +1,1897 @@
+//This is a version of PagelMatrixModel that uses Putzer's method for matrix exponentation.
+//It seems to work correctly but is substantially slower than the released version
+//PEM 15 May 2006
+
+package mesquite.correl.lib;
+
+import java.util.Random;
+
+//import org.jacorb.ir.gui.typesystem.remote.IRAlias;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.cont.lib.EigenAnalysis;
+import mesquite.correl.Pagel94.Pagel94;
+import mesquite.lib.*;
+import mesquite.lib.characters.CLikelihoodCalculator;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.characters.CharacterModel;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.ProbabilityModel;
+import mesquite.stochchar.lib.MkModel;
+import Jama.Matrix;
+
+public class PagelMatrixModel extends MultipleProbCategCharModel implements Evaluator {
+
+	//protected long allStates = 0L;
+	private int assumedMaxState=1;
+	
+
+	// different model 'behaviors' here, control how parameters are constrained
+	// if qConstrained[i] is true, params[i] is set to params[qBound[i]] unless i=-1
+	// otherwise qConstrained[i] is set to paramConstant - if this is MesquiteDouble.unassigned then error
+	int [] qMapping;          // mapping from known, underparameterized models; domain is set of parameters, range is qList
+	double[] qList;           // 
+	boolean[] qConstrained;  // true if a q value has been constrained by user (currently unimplemented)
+	int [] qBound;           // qvalue bound to another qvalue (-1 = not bound) (currently unimplemented)
+	double [] qConstant;     // qvalue is set to this constant; (currently unimplemented)
+	
+	// These constants define model 'behaviors' 
+	public static final int NOMODEL = 0;       // might be useful for flagging when a simpler model isn't available
+	public static final int MODEL2PARAM = 1;
+	public static final int MODEL4PARAM = 10;  //Pagel's model with two independent characters
+    public static final int MODEL8PARAM = 20;  //Pagel's model with two dependent characters (correlated evolution)
+    public static final int INDEPENDENTCHARACTERSMODEL = MODEL4PARAM;
+    public static final int DEPENDENTCHARACTERSMODEL = MODEL8PARAM;
+    public static final int MODEL7PARAMCONTINGENTCHANGEYFORWARD = 13;
+    public static final int MODEL7PARAMCONTINGENTCHANGEYBACKWARD = 14;
+    public static final int MODEL7PARAMCONTINGENTCHANGEXFORWARD = 15;
+    public static final int MODEL7PARAMCONTINGENTCHANGEXBACKWARD = 16;
+    public static final int MODEL6PARAMCONTINGENTCHANGEY = 17;
+    public static final int MODEL6PARAMCONTINGENTCHANGEX = 18;
+    public static final int MODEL2CHARACTERUSERDEFINED = 19;
+    public static final int MODEL3CHARACTERINDEPENDENT = 100;
+    public static final int MODEL4CHARACTERINDEPENDENT = 1000;
+
+	
+    private int modelType; //behavior of current model
+    private double [] params;
+    private boolean[] paramUnassigned;
+    private double[][] probMatrix, rateMatrix, eigenVectors, inverseEigenVectors;
+    private double[] eigenValues, imagEigenValues;  //may use imagEigenValues with Putzer's method
+    private double[][] tent;
+    private boolean negativeProbabilities = false;
+    private double negativeProbValue = 0.0;
+    //private MesquiteInteger pos = new MesquiteInteger(0);
+    private boolean recalcProbsNeeded = true;
+    private boolean needToPrepareMatrices = true;
+    private Tree workingTree;
+    private CategoricalDistribution observedStates1;
+    private CategoricalDistribution observedStates2;
+
+	double[][] downProbs;  // probability at node N given state s at base
+	double[][][] downProbs2; // probabilty at node N given state s1 for char1 and s2 for char2 at base
+	double[][] savedRootEstimates; // holds the estimates at the root (for simulation priors, etc.)
+	double[] underflowCompDown;  // ln of compensation for underflow
+	//double[] empirical;       // may be implemented sometime
+	//double[][] empirical2;
+	double[] parametersFromSimplerModel = null;  //holds values from 4 parameter model as starting values for 6 p. model
+	PagelMatrixModel intermediate1 = null;       //holds 6 parameter models called from 8 parameter model
+	PagelMatrixModel intermediate2 = null;
+	int simplerModelType;
+    	private int numStates;
+	long underflowCheckFrequency = 2; //how often to check that not about to underflow; 1 checks every time
+	long underflowCheck = 1;
+	MesquiteNumber minChecker;
+
+	private MesquiteInteger eightParameterExtraSearch = new MesquiteInteger(5);
+	
+    private double previousBranchLength = MesquiteDouble.unassigned;
+    //private boolean unassigned = true;
+ 	public static final int SIMPLER_AND_FLIP_FLOP = 2;  //conservative and slow
+ 	public static final int BASE_ON_SIMPLER= 0; 
+ 	public static final int FLIP_FLOP = 1;
+ 	
+ 	public static final double FLIP_FLOP_LOW = 0.01;
+ 	public static final double FLIP_FLOP_HIGH = 10.0;
+
+ 	int optimizationMode = BASE_ON_SIMPLER;  
+ 	
+ 	// Need to check this...
+	static final int SUM = 0;  // likelihood is just sum of likelihoods of each state at root (i.e., flat prior)
+	//static final int FIX = 1;
+	static final int SUBROOT_PRIOR = 1;  //likelihood has stated prior; this is experimental and not yet available to the user interface
+	static final int SUBROOT_EMPIRICAL = 2; //likelihood uses as prior the empirical frequencies of states in terminal taxa; this is experimental and not yet available to the user interface
+	int rootMode = SUM; //what if anything is done with prior probabilities of states at subroot?  
+
+	Random rng = new Random(System.currentTimeMillis());
+	
+	double[][] x = null;
+	double[][] identity = null;
+	double[][] p1 = null;  // clone from identity?
+	double[][] p2 = null;
+	double[][] p3 = null;
+	double[][] p4 = null;
+	double[][] putzerT1 = null;
+	double[][] putzerT2 = null;
+	double[][] putzerT3 = null;
+	double[] workingValues = null;
+	double[] workingIValues = null;
+
+	
+	ProgressIndicator prog = null;  //when this is non-null, check for abort condition
+	
+	/**
+	 * This returns the number of characters implied by the behavior code.  It's static so it
+	 * can be used as an argument to the superconstructor.
+	 * @param behavior specifies what kind of model this will be
+	 * @return int specifies number of characters for the indicated behavior
+	 */
+	static int charsFromBehavior(int behavior){
+		return 2;  // add cases when appropriate
+	}
+
+	/**
+	 * Constructs a new model. 
+	 * @param behavior The behavior (number of parameters, constraints, etc.) the model will implement
+	 */
+    public PagelMatrixModel(String name, Class dataClass, int behavior) {
+        super(name,dataClass,charsFromBehavior(behavior)); 
+        this.modelType = behavior;
+        this.params=null;              // model's parameters
+        qConstrained=null;         // true if a parameter is somehow constrained
+        qBound=null;               // parameter bound to another parameter (-1 = not bound)
+        qConstant=null;            // parameter is set to this value; 
+        tent= null;
+        this.setConstraints(modelType);
+        needToPrepareMatrices = true;
+        recalcProbsNeeded = true;
+        minChecker = new MesquiteNumber(MesquiteDouble.unassigned);        
+        if (modelType == MODEL4PARAM)
+            optimizationMode = FLIP_FLOP;
+        else
+            optimizationMode = BASE_ON_SIMPLER;
+    }
+    
+    
+    /**
+     * 
+     * @return true if any parameters are free (not bound or assigned)
+     */
+    boolean anyUnassigned(){
+    		boolean result = false;
+    		for(int i=0;i<qConstrained.length;i++)
+    			if(qConstrained[i])
+    				result = true;
+    		return result;
+    }
+    
+    boolean allUnassigned(){
+    		boolean result = true;
+    		for(int i=0;i<qConstrained.length;i++)
+    			if(qConstrained[i])
+    				result = true;
+    		return result;
+    }
+    
+    /**
+     * Extension of method from AsymmModel
+     * @param like likelihood estimate from p??
+     * @param p array of estimated parameters
+     * @return false if any argument is NaN
+     */
+    private boolean acceptableResults(double like, double p[]){
+    		if (Double.isNaN(like))
+    			return false;
+    		else
+    			for(int i = 0;i<p.length;i++)
+    				if (Double.isNaN(p[i]))
+    					return false;
+    		return true;
+	}
+    
+    private void reportUnacceptableValues(double like, double p[],double start[]){
+    		//MesquiteMessage.println("Likelihood is " + like);
+    		//for (int i=0;i<p.length;i++)
+    		//	MesquiteMessage.print("p [" + i + "] = " + p[i] + "; ");
+    		//if (start != null)
+    		//	MesquiteMessage.println("\n Started from " + DoubleArray.toString(start));
+    }
+    
+    private void checkQArrays(int model){
+    		if (model < MODEL3CHARACTERINDEPENDENT){
+    			if (qMapping == null || qMapping.length != 8) {
+    				qMapping = new int[8];
+    				for (int i=0;i<8;i++)
+    					qMapping[i] = i;   //default to identity mapping
+    			}
+   			if (qConstrained == null || qConstrained.length != 8){
+    				qConstrained = new boolean[8];
+    				for (int i=0;i<8;i++)
+    					qConstrained[i]=false;
+   			}
+    			if (qBound == null || qBound.length != 8)
+    				qBound = new int[8];
+    			if (qConstant == null || qConstant.length != 8)
+    				qConstant = new double[8];
+    		}
+   }
+    
+    private void setConstraints(int model){
+    		checkQArrays(model);
+    		switch (model) {
+    	     	/* Initialization specific to the 4 parameter model.
+    	     	 * q12 = q34 = params[0] (forward char0)
+    	     	 * q13 = q24 = params[1] (forward char1)
+    	     	 * q21 = q43 = params[2] (backward char0)
+    	     	 * q31 = q42 = params[3] (backward char1)
+    	     	 */ 
+    			case MODEL4PARAM: {  //override defaults
+    				qMapping[4]= 1;
+    				qMapping[5]= 0;
+    				qMapping[6]= 3;
+    				qMapping[7]= 2;
+    				break;
+    			}
+    			/*
+    		     * Initialization specific to the 8 parameter model. 
+    		     * q12 = params[0] (forward char0 | char1=0)
+    		     * q13 = params[1] (forward char1 | char0=0)
+    		     * q21 = params[2] (backward char0 | char1=0)
+    		     * q31 = params[3] (backward char1 | char0=1)
+    		     * q24 = params[4] (forward char1 | char0=1)
+    		     * q34 = params[5] (forward char0 | char1=1)
+    		     * q42 = params[6] (backward char1 | char0=1)
+    		     * q43 = params[7] (backward char0 | char1=1)
+    		     * 
+    		     * The '|' indicate conditional probabilities, not arithmetic-or!
+    		     * 
+    		     * char1/char0 seem to be swapped?
+    		     */
+    			case MODEL8PARAM:{  //Pagel's model with two dependent characters (correlated evolution)
+    				// most general 2char/2state model - nothing to do here
+    				break;
+     		}
+    			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {
+    				// seven parameters, q34=q12, 
+    				qMapping[5]= 0;
+    				qMapping[6]= 5;  //shift down to close the gap
+    				qMapping[7]= 6;  
+    				break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: {
+    				// seven parameters q43=q21
+    				qMapping[7]=2;
+    				break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEXFORWARD:{
+    				// seven parameters q24=q13
+            		qMapping[4]=1;
+            		qMapping[5]=4; // shift down to close the gap
+            		qMapping[6]=5;
+            		qMapping[7]=6;
+        			break;
+    			}
+    			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD:{
+    				// seven parameters q42=q31
+                	qMapping[6]= 3;
+                	qMapping[7]= 6;
+            		break;
+    			}
+    			case MODEL6PARAMCONTINGENTCHANGEY:{
+    				// six parameters q34=q12,q43=q21
+    				qMapping[5]= 0;
+    				qMapping[6]= 5;
+            		qMapping[7]= 2;
+    				break;
+    			}
+    			case MODEL6PARAMCONTINGENTCHANGEX:{
+    				// six parameters q24=q13,q42=q31
+                	qMapping[4]= 1;
+                	qMapping[5]= 4;
+                 qMapping[6]= 3;
+                 qMapping[7]= 5;
+    				break;
+    			}
+    			case MODEL2CHARACTERUSERDEFINED: {
+    				//TODO this for user specified models when we support them
+    				break;
+    			}
+   		}
+    }
+    
+    /*
+     * Qlist is an internal mapping from models with fewer parameters to the rate matrix
+     * for the full model.  This mapping means the optimizer only sees exactly the number of
+     * parameters in the model.
+     */
+    private double[] prepareQList(double[] values){
+    		if (qList == null || (qList.length < qMapping.length))
+    			qList = new double[qMapping.length];
+		for (int i=0;i<qMapping.length;i++) {
+			qList[i] = values[qMapping[i]];
+		}
+		return qList;
+    }
+    
+    /*
+     * Initializes the appropriate rate matrix then sets up the eigenvalues and eigenvectors 
+     */
+    private void prepareMatrices(){
+        needToPrepareMatrices = false;
+        boolean changed = false;
+       // unassigned = false;
+        if (modelType < MODEL3CHARACTERINDEPENDENT){
+			if (rateMatrix == null || rateMatrix.length !=4) {
+				rateMatrix = new double[4][4];
+				changed = true;
+			}
+			changed |= fill4x4MatricesFromQList(prepareQList(params));
+        }
+        if (changed) {
+            recalcProbsNeeded = true;
+         //   if (unassigned) {
+         //       if (eigenVectors == null)
+         //           eigenVectors = new double[assumedMaxState+1][assumedMaxState+1];
+         //       if (eigenValues == null)
+         //           eigenValues = new double[assumedMaxState+1];
+         //       DoubleArray.deassignArray(eigenValues);
+         //       Double2DArray.deassignArray(eigenVectors);
+         //   }
+         //   else  {
+                EigenAnalysis e = new EigenAnalysis(rateMatrix, true, false, true);
+                eigenValues = e.getEigenvalues();
+                imagEigenValues = e.getImagEigenValues();
+                eigenVectors = e.getEigenvectors();
+               // Matrix m = new Matrix(eigenVectors);
+               // Matrix r = m.inverse();
+               // inverseEigenVectors = r.getArrayCopy();
+          //  }
+        }
+    }
+        
+    /* Initialization for 4x4 (2 character) models
+     * 
+     * Note: these matrices are indexed [column][row].  This is reflected
+     * here, in the extra transpose done in the transition probabilities, and
+     * is consistent with the comments in the Asym 2 parameter model.
+     */
+    private boolean fill4x4MatricesFromQList(double [] lParams){
+		boolean changed = false;
+		for (int i=0; i< 4; i++)
+			for (int j=0; j< 4; j++){
+				double r = MesquiteDouble.unassigned;
+				if ((i+j)==3)   // prevents simultaneous transitions
+					r=0.0;
+				else {
+					switch (i){
+						case 0: {
+							switch (j){
+								case 0:{
+									r = -(lParams[0]+lParams[1]);
+									break;
+								}
+								case 1:{
+									r = lParams[0]; 
+									break;
+								}
+								case 2:{
+									r = lParams[1]; 
+									break;
+								}
+								case 3:
+							}
+							break;
+						}
+						case 1: {
+							switch (j){
+								case 0: {
+									r = lParams[2]; 
+									break;
+								}
+								case 1:{
+									r = -(lParams[2]+lParams[4]);
+									break;
+								}
+								case 2: break;
+								case 3:{
+									r = lParams[4];
+								}
+							}
+							break;
+						}
+						case 2: {
+							switch(j){
+								case 0:{
+									r=lParams[3]; 
+									break;
+								}
+								case 1:break;
+								case 2:{
+									r= -(lParams[3]+lParams[5]);
+									break;
+								}
+								case 3:{
+									r=lParams[5];  
+									break;
+								}
+							}
+							break;
+						}
+						case 3: {
+							switch(j){
+								case 0: break;
+								case 1:{
+									r=lParams[6];  
+									break;
+								}
+								case 2:{
+									r=lParams[7];
+									break;
+								}
+								case 3:{
+									r= -(lParams[6]+lParams[7]);
+									break;
+								}
+							}
+							break;
+						}
+					} //end of switch
+					if (rateMatrix[i][j]!= r) {
+						rateMatrix[i][j] = r;
+						changed = true;
+					//	if (!MesquiteDouble.isCombinable(r))
+					//		unassigned = true;
+					}
+				} // else
+			}//j
+	   		// MesquiteMessage.println("Checking rate matrix: " +Double2DArray.toStringRC(rateMatrix));
+		return changed;
+    }
+    
+    
+    /*
+     * 
+     */
+	public boolean inStates(int state,int c) { 
+		if (state>maxState[c] || state<0)
+			return false;
+		else
+			return (CategoricalState.isElement(allStates[c], state));
+	}
+
+
+	/*
+	 * recodes a pair of characters into a single state for the transition matrix index
+	 */
+	private int recodeStatePair(int i, int j) {		//todo extend beyond binary characters?
+		return (2*i+j);  
+	}
+	
+	private int[] pair0 = {0,0};
+	private int[] pair1 = {0,1};
+	private int[] pair2 = {1,0};
+	private int[] pair3 = {1,1};  
+	
+	private int[] statePairFromCode(int code){
+		switch (code){
+			case 0: return pair0;
+			case 1: return pair1;
+			case 2: return pair2;
+			case 3: return pair3;
+		}
+		return null;
+	}
+	
+	public double transitionProbability (int beginState[], int endState[], Tree tree, int node){
+		if ((beginState.length != numChars) || (endState.length != numChars)){
+			MesquiteMessage.warnProgrammer("Array for beginState or endState don't match models stated number of characters");
+			return 0;
+		}
+		boolean inStateFlag = true;
+		for (int i=0;i<numChars;i++){
+			inStateFlag &= inStates(beginState[i],i);
+			inStateFlag &= inStates(endState[i],i);
+		}
+		if (!inStateFlag){
+			MesquiteMessage.warnProgrammer("An character state of either beginState or endState is not valid");
+			return 0;
+		}
+		if (tree== null){
+			MesquiteMessage.warnProgrammer("No tree specified");
+			return 0;
+		}
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		double branchLength = tree.getBranchLength(node,1.0);
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix == null)
+			return 0;
+		//TODO the following only works for two binary characters -- needs to be extended
+		// begin end reversed as in Asym2.
+		return probMatrix[recodeStatePair(endState[0],endState[1])][recodeStatePair(beginState[0],beginState[1])];
+	}
+	
+	/**
+	 * This is the private version called from probFromSection, so no checking should be required
+	 * @param beginState1 specifies the beginning state of the first character
+	 * @param endState1 specifies the ending state of the first character
+	 * @param beginState2 specifies the beginning state of the second character
+	 * @param endState2 specifies the ending state of the second character
+	 * @param tree the tree assumed for this test
+	 * @param node where we are in the tree
+	 * @return double indicating transition probability from begin1,begin2 => end1,end2
+	 */
+	private double transitionProbability (int beginState1,int endState1,int beginState2,int endState2,Tree tree, int node){
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		double branchLength = tree.getBranchLength(node,1.0);
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix ==null)
+			return 0;
+		//begin end reversed as in Asym2
+		return probMatrix[recodeStatePair(endState1,endState2)][recodeStatePair(beginState1,beginState2)];
+	}
+	
+	double[][] p, tprobMatrix;
+	/**
+	 * Updates the transition probability matrix for a branch with the specified length
+	 * @param branchLength the length of the branch
+	 */
+	public void recalcProbabilities(double branchLength){
+	//	if (unassigned)
+	//		return;
+		previousBranchLength = branchLength;
+		if (eigenValues == null)
+			return;
+		int evl = eigenValues.length;
+		if (tent == null  || tent.length != evl || tent[0].length != evl) {
+			tent  =  new double[evl][evl];
+			Double2DArray.zeroArray(tent);
+		}
+		//for (int i=0;i<evl;i++)
+		//	tent[i][i] = Math.exp(eigenValues[i]*branchLength);
+		//		for (int i=0; i< evl; i++)
+		//	for (int j=0; j< evl; j++){
+		//		if (i== j)
+		//			tent[i][j] = Math.exp(eigenValues[i]*branchLength);
+		//		else
+		//			tent[i][j] = 0;
+		//	}
+					
+		//p = Double2DArray.multiply(eigenVectors, tent, p);
+		//probMatrix = Double2DArray.multiply(p,inverseEigenVectors,probMatrix);
+				
+        	//boolean negativeRoundOff = false;
+        	//for (int i=0; i<probMatrix.length;i++)         //transposition not an issue here
+        	//	for (int j=0;j<probMatrix[0].length;j++)
+        	//		if (probMatrix[i][j]<= 0)
+        	//			if (Math.abs(probMatrix[i][j])<1E-15) {
+        	//				negativeRoundOff = true;
+        	//				probMatrix[i][j] = 0;    //fix the problem; rows must add to one, so no relative size issue
+        	//			}
+        				//else{                      // no need to save the problem if we're not going to report it for now.
+        				//	negativeProbabilities= true;
+        				//	negativeProbValue = probMatrix[i][j];
+        				//}
+        	//if ()  {
+        	//	MesquiteMessage.warnProgrammer("Negative value in recalcProbabilities: " + bogusValue);
+        	    //MesquiteMessage.println("rate matrix is " + Double2DArray.toString(rateMatrix));
+        		//MesquiteMessage.println("eigenValues are                       " + DoubleArray.toString(eigenValues));
+           	//	MesquiteMessage.println("imaginary portions of eigenvalues are " + DoubleArray.toString(imagEigenValues));
+        		//MesquiteMessage.println("tent is " + Double2DArray.toString(tent));
+        		//MesquiteMessage.println("EigenVectors are " + Double2DArray.toString(eigenVectors));
+        		//MesquiteMessage.println("inverseEigenVectors are " + Double2DArray.toString(inverseEigenVectors));
+        		//MesquiteMessage.println("result is " + Double2DArray.toString(probMatrix));
+        	//}
+        	//if (negativeRoundOff)
+        //		MesquiteMessage.println("Small negative roundoff errors set to zero");
+        	
+        //	MesquiteMessage.println("Trying alternate exp");
+        	double[][] altProbMatrix = altMatrixExp(rateMatrix, eigenValues,imagEigenValues,branchLength);
+        	
+        	//MesquiteMessage.println("Original calculation: " + Double2DArray.toString(probMatrix));
+        	//MesquiteMessage.println("Alternate calculation: " + Double2DArray.toString(altProbMatrix));
+        	probMatrix = altProbMatrix;
+        	recalcProbsNeeded = false;
+	}
+
+	// complex exponential
+	double[] complexExp(double re,double im){
+		double[] result = new double[2];
+		result[0]=Math.cos(im)*Math.exp(re);
+		result[1]=Math.sin(im)*Math.exp(re);
+		return result;
+	}
+	
+	
+	int eigenValueStatus = UNEQUALTRIPLE;
+	public final static int UNEQUALTRIPLE = 0;
+	public final static int COMPLEXPAIR = 1;
+	public final static int EQUALPAIR  = 2;
+	public final static int EQUALTRIPLE = 3;
+	
+	public final static double equalTol = 0.001;
+	
+	double[][] altMatrixExp(double[][] baseArray,double[] eigenValues,double[] imagEigenValues,double t){
+
+		// find the zero eigenvalue; it may only be approximately 0, but it will be the
+		// largest, since the others all have negative real parts
+		double largest = -1E99;  
+		int largestIndex = -1;
+		int evl = eigenValues.length;
+		for (int i=0;i<evl;i++)
+			if (eigenValues[i] > largest) {
+				largest = eigenValues[i];
+				largestIndex = i;
+			}
+		// check for a conjugate pair
+		int imag1 = -1;
+		int imag2 = -1;
+		int realgroup1 = -1;
+		int realgroup2 = -1;
+		int realgroup3 = -1;
+		for(int i=0;i<evl;i++){
+			if (imagEigenValues[i] != 0)
+				if (imag1 == -1)
+					imag1 = i;
+				else imag2 = i;
+		}
+		if (imag1 > -1){
+			eigenValueStatus = COMPLEXPAIR;
+			for(int i= 0; i<evl;i++)
+				if (i != imag1 && i != imag2 && i != largestIndex)
+					realgroup1 = i;   // hold lone negative real;
+		}
+		else {  // no conjugate pairs, check for multiple == reals
+			for(int i=0;i<evl-1;i++)
+				for(int j=i+1;j<evl;j++){
+					//System.out.println("Test: " + Math.abs(eigenValues[i]-eigenValues[j]));
+					if(Math.abs((eigenValues[i]-eigenValues[j])/eigenValues[i]) < equalTol){  // found a pair
+						realgroup1=i;
+						realgroup2=j;
+						break;
+					}
+				}
+				if (realgroup2 == -1)
+					eigenValueStatus = UNEQUALTRIPLE;
+				else {  //find realgroup3
+					for(int i=0;i<evl;i++){
+						if (i != largestIndex && i != realgroup1 && i != realgroup2)
+							realgroup3 = i;
+					}
+					if (Math.abs((eigenValues[realgroup1]-eigenValues[realgroup3])/eigenValues[realgroup1])<equalTol)
+						eigenValueStatus = EQUALTRIPLE;
+					else 
+						eigenValueStatus = EQUALPAIR;
+				}	
+		}
+
+		if (identity == null || identity.length != evl || identity[0].length != evl) {
+			identity = new double[evl][evl];
+			Double2DArray.setToIdentityMatrix(identity);
+		}
+		if (p1 == null || p1.length != evl || p1[0].length != evl){
+			p1 = new double[evl][evl];
+			Double2DArray.setToIdentityMatrix(p1); 
+		}
+
+		if (workingValues == null || workingValues.length != evl)
+			workingValues = new double[evl];
+		workingValues[0] = 0;      // assert that the max eigenvalue is identically zero!
+		switch (eigenValueStatus) {
+			case UNEQUALTRIPLE: {
+				int nexteigenslot=1;
+				for (int i=0;i<evl;i++){
+					if(i!=largestIndex)
+						workingValues[nexteigenslot++] = eigenValues[i];
+				}	
+				//double z = workingValues[0];
+				double k = workingValues[1];
+				double m = workingValues[2];
+				
+				
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				putzerT1 = scalarProduct(identity,m,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realR4(t,workingValues),p4));
+
+				//p2 = (C.minus(identity.times(z))).times(p1);              
+				//p3 = (C.minus(identity.times(k))).times(p2);
+				//p4 = (C.minus(identity.times(m))).times(p3);
+				//x = p1.times(r1(t,workingValues));
+				//x.plusEquals(p2.times(realR2(t,workingValues)));
+				//x.plusEquals(p3.times(realR3(t,workingValues)));
+				//x.plusEquals(p4.times(realR4(t,workingValues)));	
+				break;
+			}
+			case COMPLEXPAIR: {
+				if (workingIValues == null || workingIValues.length != evl)
+					workingIValues = new double[evl];
+				DoubleArray.zeroArray(workingIValues);
+				workingValues[1] = eigenValues[imag1];
+				workingIValues[1] = imagEigenValues[imag1];
+				workingValues[2] = eigenValues[imag2];
+				workingIValues[2] = imagEigenValues[imag2];
+				workingValues[3] = eigenValues[realgroup1];
+
+				//double z = workingValues[0];
+				double k = workingValues[1];
+				
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,complexPairR2(t,workingValues,workingIValues),p2));
+				x = plusEquals(x,scalarProduct(p3,complexPairR3(t,workingValues,workingIValues),p3));
+				x = plusEquals(x,scalarProduct(p4,complexPairR4(t,workingValues,workingIValues),p4));
+
+				
+				//p2 = (C.minus(identity.times(z))).times(p1);
+				//p3 = (C.minus(identity.times(k))).times(p2);
+				//p4 = (C.minus(identity.times(k))).times(p3);
+				//x = p1.times(r1(t,workingValues));
+				//x.plusEquals(p2.times(complexPairR2(t,workingValues,workingIValues)));
+				//x.plusEquals(p3.times(complexPairR3(t,workingValues,workingIValues)));
+				//x.plusEquals(p4.times(complexPairR4(t,workingValues,workingIValues)));			
+				break;
+			}
+			case EQUALPAIR: {
+				workingValues[1] = eigenValues[realgroup1];
+				workingValues[2] = eigenValues[realgroup1];   // if they're close, force them equal
+				workingValues[3] = eigenValues[realgroup3];
+				
+				//double z = workingValues[0];
+				double k = workingValues[1];
+
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realPairR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realPairR4(t,workingValues),p4));
+
+				
+				
+				//p2 = (C.minus(identity.times(z))).times(p1);
+				//p3 = (C.minus(identity.times(k))).times(p2);
+				//p4 = (C.minus(identity.times(k))).times(p3);
+				//x = p1.times(r1(t,workingValues));
+				//x.plusEquals(p2.times(realR2(t,workingValues)));
+				//x.plusEquals(p3.times(realPairR3(t,workingValues)));
+				//x.plusEquals(p4.times(realPairR4(t,workingValues)));	
+
+				break;
+			}
+			case EQUALTRIPLE: {
+				workingValues[1] = eigenValues[realgroup1];
+				workingValues[2] = eigenValues[realgroup2];
+				workingValues[3] = eigenValues[realgroup3];
+				//double z = workingValues[0];
+				double k = workingValues[1];
+
+				//p2 = Double2DArray.multiply(baseArray,p1,p2);
+				//p2 = copy(baseArray,p2);
+				putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p3 = Double2DArray.multiply(putzerT2,baseArray,p3);
+				//putzerT1 = scalarProduct(identity,k,putzerT1);
+				putzerT2 = minus(baseArray,putzerT1,putzerT2);
+				p4 = Double2DArray.multiply(putzerT2,p3,p4);
+				x = copy(p1,x);
+				x = plusEquals(x,scalarProduct(baseArray,realR2(t,workingValues),p2));
+				x = plusEquals(x,scalarProduct(p3,realPairR3(t,workingValues),p3));
+				x = plusEquals(x,scalarProduct(p4,realTripleR4(t,workingValues),p4));
+				
+				
+				//p2 = (C.minus(p1.times(z))).times(p1);
+				//p3 = (C.minus(p1.times(k))).times(p2);
+				//p4 = (C.minus(p1.times(k))).times(p3);
+				
+				//x = p1.times(r1(t,workingValues));
+				//x.plusEquals(p2.times(realR2(t,workingValues)));
+				//x.plusEquals(p3.times(realPairR3(t,workingValues)));
+				//x.plusEquals(p4.times(realTripleR4(t,workingValues)));			
+				break;
+			}
+		}
+		return Double2DArray.transpose(x);
+	}
+	
+	// support functions for Putzer exponentiation
+	double r1(double t,double[] realEigenValues){
+		//double z = realEigenValues[0];
+		//return Math.exp(t*z);
+		return 1;
+	}
+
+	double realR2(double t, double[] realEigenValues){
+		double k = realEigenValues[1];
+		return (Math.exp(k*t) - 1)/(k);
+	}
+	
+	double complexPairR2(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		return -((ka*(1 - Math.exp(ka*t)*Math.cos(kb*t)))/(ka*ka + kb*kb)) + 
+		  (Math.exp(ka*t)*kb*Math.sin(kb*t))/(ka*ka + kb*kb);
+	}
+	
+	
+	
+	double realR3(double t, double[] realEigenValues){
+		//double z = realEigenValues[0];
+		double k = realEigenValues[1];
+		double m = realEigenValues[2];
+		return (Math.exp(m*t)*k - k - Math.exp(k*t)*m + m)/((-k + m)*(k)*(m)); 
+	}
+	
+	double complexPairR3(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		double expkat = Math.exp(ka*t);
+		return (2*kb - 2*expkat*kb*Math.cos(kb*t) + 2*expkat*ka*Math.sin(kb*t))/ 
+		  (2*(ka*ka*kb + kb*kb*kb));
+	}
+	
+	double realPairR3(double t, double[] values){
+		double k = values[1];
+		//(1 - E^(k*t) + E^(k*t)*k*t)/k^2
+		return (1 - Math.exp(k*t) + Math.exp(k*t)*k*t)/(k*k);
+	}
+	
+	double realR4(double t, double[] realEigenValues){
+		double k = realEigenValues[1];
+		double m = realEigenValues[2];
+		double n = realEigenValues[3];
+		double expnt = Math.exp(n*t);
+		double expmt = Math.exp(m*t);
+		double expkt = Math.exp(k*t);
+		return (-(expnt*k*k*m) + k*k*m + 
+		          expnt*k*m*m - k*m*m + expmt*k*k*n - 
+		          k*k*n - expkt*m*m*n + m*m*n - 
+		          expmt*k*n*n + k*n*n + expkt*m*n*n - 
+		          m*n*n)/((-k + m)*(-k + n)*(-m + n)*(k)*(m)*(n));
+	}
+
+	double complexPairR4(double t, double[] realEigenValues, double[] imagEigenValues){
+		double ka = realEigenValues[1];
+		double kb = imagEigenValues[1];
+		double n = realEigenValues[3];
+		return (-2*ka*ka*kb + 2*Math.exp(n*t)*ka*ka*kb - 2*kb*kb*kb + 2*Math.exp(n*t)*kb*kb*kb + 
+			    4*ka*kb*n - 2*kb*n*n - 4*Math.exp(ka*t)*ka*kb*n*Math.cos(kb*t) + 
+			    2*Math.exp(ka*t)*kb*n*n*Math.cos(kb*t) + 
+			    2*Math.exp(ka*t)*ka*ka*n*Math.sin(kb*t) - 
+			    2*Math.exp(ka*t)*kb*kb*n*Math.sin(kb*t) - 2*Math.exp(ka*t)*ka*n*n*Math.sin(kb*t))/
+			    (2*kb*(ka*ka + kb*kb)*n*(ka*ka + kb*kb - 2*ka*n + n*n));
+	}
+	
+	double realPairR4(double t, double [] values){
+		double k = values[1];
+		double n = values[3];
+		return (-k*k + Math.exp(n*t)*k*k + 2*k*n - 2*Math.exp(k*t)*k*n - 
+			       n*n + Math.exp(k*t)*n*n + Math.exp(k*t)*k*k*n*t - Math.exp(k*t)*k*n*n*t)/(k*k*n*(n-k)*(n-k));
+	}
+	double realTripleR4(double t, double[] values){
+		// TODO finish me
+		double k = values[1];
+		double expkt = Math.exp(k*t);
+		return (-2 + 2*expkt - 2*expkt*k*t +  expkt*k*k*t*t)/(2*k*k*k);
+	}
+	
+	
+	
+	// Trying to replace Jama matrices with Double2DArrays
+	
+	double[][] plusEquals(double[][]dest, double[][]addend){
+		int numRows1 = Double2DArray.numFullRows(dest);
+		int numRows2 = Double2DArray.numFullRows(addend);
+		int numColumns1 = Double2DArray.numFullColumns(dest);
+		int numColumns2 = Double2DArray.numFullColumns(addend);
+		boolean flag = (numColumns1!= numRows2 || numColumns1!=numColumns2);
+		if (flag) MesquiteMessage.println("Wow! You are trying to add a:   " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  
+		             +" to a  " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  ); 
+		if (flag)
+		    return null; 
+		for (int i=0; i<numColumns1; i++) 
+			for (int j=0; j<numRows1; j++) 
+				dest[i][j] += addend[i][j];
+		return dest;
+	}
+	
+	double[][]scalarProduct(double[][]source,double multiplier,double[][]result){
+		int numRows = Double2DArray.numFullRows(source);
+		int numColumns = Double2DArray.numFullColumns(source);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		if (result == null || result.length != numRows || (result.length>0 && result[0].length != numColumns))
+			result = new double[numRows][numColumns];
+		for(int i=0;i<numRows;i++)
+			for(int j=0;j<numRows;j++)
+				result[i][j]=source[i][j]*multiplier;
+		return result;
+	}
+	
+	double[][]minus(double[][]source,double[][]subtractor,double[][]result){
+		int numRows1 = Double2DArray.numFullRows(source);
+		int numRows2 = Double2DArray.numFullRows(subtractor);
+		int numColumns1 = Double2DArray.numFullColumns(source);
+		int numColumns2 = Double2DArray.numFullColumns(subtractor);
+		boolean flag = (numColumns1!= numRows2 || numColumns1!=numColumns2);
+		if (flag) MesquiteMessage.println("Wow! You are trying subtract a:   " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  
+		             +" from a  " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  ); 
+		if (flag)
+		    return null; 
+		if (result == null || result.length != numRows1 || (result.length>0 && result[0].length != numColumns1))
+			result = new double[numRows1][numColumns1];
+		Double2DArray.zeroArray(result);
+		for(int i=0;i<numRows1;i++)
+			for(int j=0;j<numRows1;j++)
+				result[i][j]=source[i][j]-subtractor[i][j];
+		return result;
+		
+	}
+
+	
+	double[][]copy(double[][]source,double[][]result){
+		int numRows1 = Double2DArray.numFullRows(source);
+		int numColumns1 = Double2DArray.numFullColumns(source);
+		if (result == null || result.length != numRows1 || (result.length>0 && result[0].length != numColumns1))
+			result = new double[numRows1][numColumns1];
+		for(int i=0;i<numRows1;i++)
+			for(int j=0;j<numRows1;j++)
+				result[i][j]=source[i][j];
+		return result;		
+	}
+
+
+	double limit = 10000;
+	int beginningAllowed = 6;
+    /**
+     * This version is the main version of the evaluator
+     * @param values is the array of proposed parameter values
+     * @param obj is ignored here and should be null (maybe just pass through command record)
+     */
+	public double evaluate(double[] values, Object obj) {
+		if (values.length >= 4) {
+			if (prog != null)
+				if (prog.isAborted())
+					throw new StuckSearchException();
+			double height = workingTree.tallestPathAboveNode(workingTree.getRoot()); // to stop the optimization from wandering if very high rates
+			if (!sanityChecks(values,limit, height)){
+				return MesquiteDouble.veryLargeNumber;
+			}
+        		negativeProbabilities = false;
+			params = DoubleArray.clone(values);
+			prepareMatrices();
+			double result =  -this.logLikelihoodCalc(workingTree);
+			return result;
+		}
+		else
+			return 0;
+	}
+	
+	int estCount =0;
+	boolean zeroHit = false;
+	/*.................................................................................................................*/
+	public double logLikelihoodCalc(Tree tree){
+		if (zeroHit)
+			return -0.001*(++estCount);  // to shortcircuit the optimizer wandering around zero with very high rates
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("Tree passed to logLikelihoodCalc is null");
+			return(-1*MesquiteDouble.veryLargeNumber);
+		}
+		double likelihood = 0.0;
+		double comp;
+		int root = tree.getRoot();
+		if (rootMode == SUM){
+			initProbs2(tree.getNumNodeSpaces(), observedStates1.getMaxState()+1,observedStates2.getMaxState()+1); 
+			estCount++;
+			downPass2(root,tree);
+			for (int i = 0; i<=maxState[0]; i++)
+				for (int j = 0; j<=maxState[1];j++) {
+					savedRootEstimates[j][i] = downProbs2[root][j][i];
+					if (savedRootEstimates[j][i] < 0){      // problem, probably due to bad matrix operation
+						likelihood = 0;
+						return(-1*MesquiteDouble.veryLargeNumber);
+					}
+					else
+						likelihood += savedRootEstimates[j][i];
+				}
+		}
+		//else 
+		//	MesquiteMessage.println("Subroot prior and subroot empirical not yet supported");
+		//}
+		//else if (rootMode == SUBROOT_PRIOR){
+		//	if (tree.getRooted())
+		//		for (int i=0; i<numStates; i++) 
+		//			empirical[i] = model.priorProbability(i);
+		//	for (int i=0;  i<=model.getMaxState(); i++) {
+		//		likelihood += downProbs[root][i]*probFromSection(tree, root, i, empirical, model, false);
+		//	}
+		//}
+		//else if (rootMode == SUBROOT_EMPIRICAL){
+		//	calculateEmpirical(tree, observedStates, empirical);
+		//	for (int i=0;  i<=model.getMaxState(); i++) {
+		//		likelihood += downProbs[root][i]*probFromSection(tree, root, i, empirical, model, false);
+		//	}
+		//}
+		comp = underflowCompDown[root];
+		double logLike = Math.log(likelihood) - comp;
+		if (Double.isNaN(logLike)){
+			// These just get too verbose
+			//MesquiteMessage.warnProgrammer("logLikelihoodCalc returned Nan from :" + DoubleArray.toString(params));
+			//if (negativeProbabilities){
+			//	MesquiteMessage.warnProgrammer("Negative transition probabilities were calculated (e.g., " + negativeProbValue + ")");
+			//}
+			return(-1*MesquiteDouble.veryLargeNumber);
+		}
+		if (logLike> -0.00001) {
+			zeroHit = true;
+		}
+		return (logLike);
+	}
+ 		
+ 	private void initProbs2(int nodes, int numStates1, int numStates2) {
+ 		if (numStates1 != numStates2) {
+ 			if (numStates1 >= numStates2)
+ 				this.numStates = numStates1;
+ 			else
+ 				this.numStates = numStates2;
+ 		}
+ 		else if (numStates1 == 1) 
+ 			numStates =2;
+ 			else numStates = numStates1;
+ 		if  (downProbs2==null || downProbs2.length!=nodes || downProbs2[0].length!=numStates1 || downProbs2[0][0].length!=numStates2){
+ 		 		downProbs2 = new double[nodes][numStates][numStates];
+ 		 		underflowCompDown = new double[nodes];
+ 		 		//empirical2 = new double[numStates][numStates];
+ 		 		savedRootEstimates = new double[numStates][numStates];
+ 		}
+ 		//Double3DArray.zeroArray(downProbs2);
+ 		for(int i=0;i<nodes;i++){
+ 			Double2DArray.zeroArray(downProbs2[i]);
+ 		}
+ 		DoubleArray.zeroArray(underflowCompDown);
+ 		//Double2DArray.zeroArray(empirical2);
+ 		Double2DArray.deassignArray(savedRootEstimates);
+ 	}
+ 		
+	// overloading for 2 characters
+ 	// This (private) version only goes down from the terminals
+	private double probFromSection(Tree tree, int d, int i, int j, double[][] ProbsD){
+		double prob=0;
+		for (int k=0;k<numStates;k++)
+			for (int l=0;l<numStates;l++){
+				prob += ProbsD[k][l]*transitionProbability(i,k,j,l,tree,d);
+			}
+		return prob;
+	}
+	
+	
+	/*.................................................................................................................*/	
+	// overloading for 2 characters
+	private double checkUnderflow(double[][] probs){
+		minChecker.setValue(MesquiteDouble.unassigned);
+		int probsDim1 = probs.length;
+		int probsDim2 = probs[0].length;
+		for (int i=0;i<probsDim1;i++)
+			for (int j=0;j<probsDim2;j++)
+				minChecker.setMeIfIAmMoreThan(probs[i][j]);
+		double q = minChecker.getDoubleValue();
+		if (q == 0)
+			return 0;
+		else {
+			for (int i=0;i<probsDim1;i++)
+				for (int j=0;j<probsDim2;j++)
+					probs[i][j] /= q;
+		}
+		return -Math.log(q);
+	}
+
+
+	/*.................................................................................................................*/
+	//can't overload since no arrays passed
+	// assumes hard polytomies
+	private void downPass2(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			long observed1 = ((CategoricalDistribution)observedStates1).getState(tree.taxonNumberOfNode(node));
+			long observed2 = ((CategoricalDistribution)observedStates2).getState(tree.taxonNumberOfNode(node));
+			int obs1 = CategoricalState.minimum(observed1); //NOTE: just minimum observed!
+			int obs2 = CategoricalState.minimum(observed2);
+			Double2DArray.zeroArray(downProbs2[node]);
+			if (obs1>=0 && obs1 < downProbs2[node].length && !CategoricalState.isUnassigned(observed1) && !CategoricalState.isInapplicable(observed1) &&
+				obs2>=0 && obs2 < downProbs2[node][0].length && !CategoricalState.isUnassigned(observed2) && !CategoricalState.isInapplicable(observed2)) {
+				downProbs2[node][obs1][obs2] = 1;
+			}
+		}
+		else {
+			Double2DArray.zeroArray(downProbs2[node]);
+			underflowCompDown[node]=0;
+			for (int d= tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				downPass2(d,tree);
+				underflowCompDown[node] += underflowCompDown[d];
+			}			
+			for (int i=0;i<numStates;i++)
+				for (int j=0;j<numStates;j++){
+					double prob = 1.0;
+					for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d=tree.nextSisterOfNode(d)){
+						prob *= probFromSection(tree,d,i,j,downProbs2[d]);
+					}
+					downProbs2[node][i][j] = prob;
+			}
+			if (++underflowCheck % underflowCheckFrequency == 0){
+				underflowCompDown[node] += checkUnderflow(downProbs2[node]);
+			}
+		}
+	}
+
+	int allowedEdgeHits = 0; // to stop the optimization from wandering if very high rates; edge allowed to be hit only a certain number of tiems
+	private boolean sanityChecks(double [] eParams, double limit, double height){
+		for(int i=0;i<eParams.length;i++){
+			if (eParams[i]*height>limit && allowedEdgeHits--<0) { // too big
+				return false;
+			}
+			if (eParams[i]<=0){  
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * This is really a stub that exists because there is no class for multivariate evaluators
+	 * 
+	 */
+	public double evaluate(MesquiteDouble param, Object obj) {
+		// TODO Maybe add a class for multivariate evaluators
+		return 0;
+	}
+	
+	//Wayne: this is here so you can use it in Pagel94	- feel free to change the default value
+	public MesquiteInteger getExtraSearch() {
+		return eightParameterExtraSearch;
+	}
+
+	
+	/*
+	 * This just rescales the fixed parameters (as yet unimplemented) by rescale
+	 */
+	private void rescaleFixedParameters(double rescale){
+		for(int i=0;i<qConstant.length;i++)
+			if (qConstrained[i] && qBound[i]<0 && MesquiteDouble.isCombinable(qConstant[i]))
+				qConstant[i] *= rescale;
+	}
+
+	private void rescaleAllParameters(double rescale){
+		for(int i=0;i<params.length;i++)
+			params[i] *= rescale;
+	}
+
+    static final boolean scaleRescale = true;  
+ 
+    public void estimateParameters(Tree originalTree, CategoricalDistribution observedStates1, CategoricalDistribution observedStates2, CommandRecord commandRec) {
+ //   	if (observedStates1==null || observedStates2==null)
+ //   		return;
+        this.observedStates1 = observedStates1;
+        this.observedStates2 = observedStates2;
+    		// Special treatment for constant states just isn't working out here
+    		if (observedStates1.getMaxState()>= 1)
+    			maxState[0] = observedStates1.getMaxState();
+    		else
+    			maxState[0] = 1;
+    		if (observedStates2.getMaxState()>= 1)
+        		maxState[1] = observedStates2.getMaxState();
+    		else
+    			maxState[1] = 1;
+
+		allStates[0] = CategoricalState.span(0,maxState[0]);
+		allStates[1] = CategoricalState.span(0,maxState[1]);
+		double height = 0;
+		double invHeight = MesquiteDouble.unassigned;
+		if (scaleRescale){  //rescales tree to 1.0 height to help optimization, which takes longer with larger numbers
+			MesquiteTree mTree = originalTree.cloneTree();
+			mTree.setAllUnassignedBranchLengths(1.0, false);
+			height = mTree.tallestPathAboveNode(mTree.getRoot(), 1.0); // to adjust start point depending on how tall is tree
+			if (height != 0){
+				invHeight = 1.0/height;
+				mTree.scaleAllBranchLengths(invHeight, false);
+				rescaleFixedParameters(height);
+			}
+			workingTree= mTree;
+		}
+		else  
+			workingTree = originalTree;
+		Optimizer opt = new Optimizer(this);
+		double best = Double.MAX_VALUE;
+		// **** estParams is the matrix of trial values
+		double estParams[];
+		// estjust saves the starting values for error reporting
+		double backupEst[] = null;
+		double [] b = null;
+		double next;
+		switch (modelType) {
+			case MODEL8PARAM:{  // first try two versions of a 6-parameter model
+				// no need to reallocate the two 6-p models everytime
+				if (intermediate1 == null)
+					intermediate1 = new PagelMatrixModel("",CategoricalState.class,MODEL6PARAMCONTINGENTCHANGEY);
+				if (intermediate2 == null)
+					intermediate2 = new PagelMatrixModel("",CategoricalState.class,MODEL6PARAMCONTINGENTCHANGEX);
+				PagelMatrixModel model6_cy = intermediate1;
+				PagelMatrixModel model6_cx = intermediate2;
+				estParams = new double[8];
+				// first a model with changes in Y contingent on changes in X
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL6PARAMCONTINGENTCHANGEY){
+				    model6_cy.setParametersFromSimplerModel(parametersFromSimplerModel,simplerModelType);
+					model6_cy.estimateParameters(workingTree,observedStates1, observedStates2, commandRec);
+					double[] m6_1Params = model6_cy.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m6_1Params[i];
+					estParams[4]=m6_1Params[4];
+					estParams[5]=m6_1Params[0];
+					estParams[6]=m6_1Params[5];
+					estParams[7]=m6_1Params[2];
+				}
+				else { 
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					estParams[4]=parametersFromSimplerModel[4];
+					estParams[5]=parametersFromSimplerModel[0];
+					estParams[6]=parametersFromSimplerModel[5];
+					estParams[7]=parametersFromSimplerModel[2];
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				next = opt.optimize(estParams, null); // try optimizing from the contingentchangeY best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+				}
+				else {     //shouldn't need to compare best with next here
+					best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+				}
+				// now the other 6-parameter model (changes in X contingent on Y)
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL6PARAMCONTINGENTCHANGEX){
+				    model6_cx.setParametersFromSimplerModel(parametersFromSimplerModel,simplerModelType);
+					model6_cx.estimateParameters(workingTree,observedStates1, observedStates2, commandRec);
+					double[] m6_2Params = model6_cx.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m6_2Params[i];
+					estParams[4]=m6_2Params[1];
+					estParams[5]=m6_2Params[4];
+					estParams[6]=m6_2Params[3];
+					estParams[7]=m6_2Params[5];
+				}
+				else { 
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					estParams[4]=parametersFromSimplerModel[1];
+					estParams[5]=parametersFromSimplerModel[4];
+					estParams[6]=parametersFromSimplerModel[3];
+					estParams[7]=parametersFromSimplerModel[5];
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+				}
+				else if (next<best) {
+					best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+				}
+				//PETER: added these tick notifications to keep user informed of progress of search
+				if (commandRec != null) commandRec.tick("8 parameter model preliminary -ln likelihood: " + MesquiteDouble.toString(best));
+				if (eightParameterExtraSearch.getValue() > 0) {
+					double [] m6_cy_Params = model6_cy.getParams();
+					double [] m6_cx_Params = model6_cx.getParams();
+					for (int i = 0; i< eightParameterExtraSearch.getValue();i++){
+						for(int j=0;j<4;j++)
+							estParams[j]=Math.abs((m6_cy_Params[j]+m6_cx_Params[j])/2 + (20.0*rng.nextGaussian())*(m6_cx_Params[j]-m6_cy_Params[j]));
+						estParams[4]=Math.abs(1+20.0*rng.nextGaussian())*m6_cy_Params[4];
+						estParams[5]=Math.abs(1+20.0*rng.nextGaussian())*m6_cx_Params[4];
+						estParams[6]=Math.abs(1+20.0*rng.nextGaussian())*m6_cy_Params[5];
+						estParams[7]=Math.abs(1+20.0*rng.nextGaussian())*m6_cx_Params[5];
+						allowedEdgeHits = beginningAllowed;
+						//backupEst = (double [])estParams.clone();
+						next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+						if (!acceptableResults(next, estParams)) {
+							MesquiteMessage.warnProgrammer("Warning: NaN encountered in PagelMatrixModel optimization");
+							reportUnacceptableValues(next, estParams,backupEst);
+						}
+						else if (next<best) {
+							best = next;
+							if (b == null)
+								b = DoubleArray.clone(estParams);	
+							else
+								for (int m=0; m< estParams.length; m++)
+									b[m] = estParams[m];
+						}
+						if (commandRec != null) commandRec.tick("8 parameter model -ln likelihood after " + (i+1) + " searches: " + MesquiteDouble.toString(best));
+				}
+				}
+				break;
+			}
+			case MODEL6PARAMCONTINGENTCHANGEX:
+			case MODEL6PARAMCONTINGENTCHANGEY: {
+				estParams = new double[6];
+				if (parametersFromSimplerModel == null || simplerModelType != MODEL4PARAM) {
+					PagelMatrixModel model4 = new PagelMatrixModel("",CategoricalState.class,MODEL4PARAM);
+					model4.estimateParameters(workingTree,observedStates1, observedStates2, commandRec);
+					double [] m4Params = model4.getParams();
+					for(int i=0;i<4;i++)
+						estParams[i]=m4Params[i];
+					if (modelType == MODEL6PARAMCONTINGENTCHANGEX){  
+						estParams[4]=m4Params[2];
+						estParams[5]=m4Params[3];
+					}
+					else {
+						estParams[4]=m4Params[0];
+						estParams[5]=m4Params[1];
+					}
+				}
+				else { // TODO need to get the parameters from the previous model
+					for(int i=0;i<4;i++)
+						estParams[i]=parametersFromSimplerModel[i];
+					if (modelType == MODEL6PARAMCONTINGENTCHANGEX){  
+						estParams[4]=parametersFromSimplerModel[2];
+						estParams[5]=parametersFromSimplerModel[3];
+					}
+					else {
+						estParams[4]=parametersFromSimplerModel[0];
+						estParams[5]=parametersFromSimplerModel[1];
+					}
+				}
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+				next = opt.optimize(estParams, null); // try optimizing from the contingentchangeX best parameters
+				if (!acceptableResults(next, estParams)) {
+					MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+					//if (b == null)
+					//	b = DoubleArray.clone(estParams);	//only do this to get b set to something...
+				}
+				else if (next<best) {
+					best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+				}
+				break;
+			}
+			case MODEL4PARAM: {  // for now, just use flip/flop, though we might try getting estimates from MODEL2PARAM in the future
+				estParams = new double[4];
+				estParams[2] = FLIP_FLOP_HIGH;
+				estParams[3] = FLIP_FLOP_HIGH;
+				estParams[0] = FLIP_FLOP_HIGH;
+				estParams[1] = FLIP_FLOP_HIGH;
+				if (b == null)
+					b = DoubleArray.clone(estParams);	
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.warnProgrammer("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else if (next<best) {
+		 			best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+		 		}
+				estParams[0] = FLIP_FLOP_LOW;
+				estParams[2] = FLIP_FLOP_LOW; //
+				estParams[1] = FLIP_FLOP_HIGH;  //forward
+				estParams[3] = FLIP_FLOP_HIGH;
+			 	params = DoubleArray.clone(estParams);
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else if (next<best) {
+		 			best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+		 		}
+		 		estParams[0] = FLIP_FLOP_HIGH;
+				estParams[2] = FLIP_FLOP_HIGH; //
+				estParams[1] = FLIP_FLOP_LOW;  //forward
+				estParams[3] = FLIP_FLOP_LOW;
+			 	params = DoubleArray.clone(estParams);
+				allowedEdgeHits = beginningAllowed;
+				//backupEst = (double [])estParams.clone();
+		 		next = opt.optimize(estParams, null); //bundle);
+		 		if (!acceptableResults(next, estParams)) {
+		 			MesquiteMessage.println("Warning: NaN encountered in PagelMatrixModel optimization");
+					reportUnacceptableValues(next, estParams,backupEst);
+		 		}
+		 		else if (next<best) {
+		 			best = next;
+					if (b == null)
+						b = DoubleArray.clone(estParams);	
+					else
+						for (int i=0; i< estParams.length; i++)
+							b[i] = estParams[i];
+		 		}
+				if (commandRec != null) commandRec.tick("4 parameter model -ln likelihood: " + MesquiteDouble.toString(best));
+				break;
+			}
+			case MODEL2PARAM: {  // NO-OP FOR NOW, the model exists, the framework for using it doesn't
+			 	MkModel model2 = new MkModel("asymm helper", CategoricalState.class); //used to provide preliminary guess at rate
+				MesquiteMessage.warnUser("The 2 parameter model isn't currently supported here");
+				break;
+			}
+		} // end switch (??)
+		params = DoubleArray.clone(b);
+		if (scaleRescale && height != 0){ //UNDO the scaling of the tree
+			rescaleAllParameters(invHeight);
+			workingTree = originalTree;  // faster, less error prone than rescaling from mTree??
+		 }
+		//prepareMatrices();
+	}
+    
+	
+    /**
+     * 
+     * @return array of doubles containing the parameters estimated for this model
+     */
+    public double[] getParams() {
+    		return params;
+    }
+    
+    /**
+     * 
+     */
+    public double[][] getRootPriors(){
+    		double[][] rootPriors;
+    		if (savedRootEstimates == null)
+    			return null;
+    		else {
+    			double total = 0;
+    			int estimateLength = savedRootEstimates.length;  // what are these really?
+    			int estimateWidth = savedRootEstimates[0].length;
+    			rootPriors = new double[estimateLength][estimateWidth];
+    			for (int i=0;i<estimateLength;i++)
+    				for (int j=0;j<estimateWidth;j++)
+    					total += savedRootEstimates[i][j];
+    			for (int i=0;i<estimateLength;i++)
+    				for (int j=0;j<estimateLength;j++)
+    					rootPriors[i][j] = savedRootEstimates[i][j]/total;
+    		}
+    		return rootPriors;
+    }
+    
+    /**
+     * This provides a mechanism to pass best parameter estimates from a simpler (independent/4 parameter) model
+     * @param hint array of doubles containing the parameter estimates
+     */
+    public void setParametersFromSimplerModel(double[] hint,int mtype){
+		parametersFromSimplerModel = hint;
+		simplerModelType = mtype;
+    }
+
+    
+
+	public void deassignParameters() {
+		// TODO Auto-generated method stub
+	}
+	
+	public long[] getRootStates(Tree tree, double[][] rootStatePriors){
+		long[] result = new long[charsFromBehavior(modelType)];   // always a safe choice
+		if ((rootStatePriors != null) && (modelType < MODEL3CHARACTERINDEPENDENT)){
+			double r = randomNumGen.nextDouble();
+			double accumProb = 0;
+			for (int i=0;i<rootStatePriors[0].length;i++) {
+				for (int j=0;j<rootStatePriors.length;j++) {
+					accumProb += rootStatePriors[j][i];
+					if (r<accumProb){
+						result[0]=CategoricalState.makeSet(i);
+						result[1]=CategoricalState.makeSet(j);
+						return result;
+					}
+				}
+			}
+			result[0]=rootStatePriors[0].length;
+			result[1]=rootStatePriors[1].length;
+			return result;
+		}
+		else {
+			for(int c=0;c<result.length;c++){
+				result[c]=getRootState(tree,c);
+			}
+			return result;
+		}
+	}
+	
+	public long getRootState (Tree tree,int c){
+		if (maxState[c] <= 0) 
+			return (1L);  //if only state 0 allowed, return it
+		else {
+			double r = randomNumGen.nextDouble();
+			double accumProb = 0;
+			for (int i=0; i<maxState[c]; i++) {
+				accumProb +=  priorProbability(i,c);
+				if (r< accumProb)
+					return CategoricalState.makeSet(i);
+			}
+			return CategoricalState.makeSet(maxState[c]);
+		}
+	}
+	
+	
+	/**
+	 * return a flat prior for a character estimate at the root
+	 */
+	public double flatPriorProbability (int state,int c){
+		if (!inStates(state,c)) 
+			return 0;
+		else
+			if (maxState[c] == 0)
+				return (0.5);  // flat prior
+			else
+				return (1.0/(maxState[c]+1));  // flat prior
+	}
+
+	/* ---------------------------------------------*/	
+	public int[] evolveState (int beginState[], Tree tree, int node){
+		int index = recodeStatePair(beginState[0],beginState[1]);
+		double r = randomNumGen.nextDouble();
+		double branchLength = tree.getBranchLength(node, 1.0);
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+		if (probMatrix == null)
+			return null;
+		if (index> probMatrix[0].length)  //TODO replace with appropriate test
+			return null;
+		double accumProb = 0;
+		int resultCode = recodeStatePair(maxState[0],maxState[1]);
+//		for (int i=0; i<probMatrix[index].length; i++) {
+//			accumProb +=  probMatrix[index][i];
+//			if (r< accumProb){
+//				resultCode = i;
+//				break;
+//			}
+//		}
+		for (int i=0; i<probMatrix.length; i++) {
+		accumProb +=  probMatrix[i][index];
+		if (r< accumProb){
+			resultCode = i;
+			break;
+		}
+	}
+		return statePairFromCode(resultCode);
+	}
+
+	
+	public void evolveState (CharacterState[] beginState, CharacterState[] endState, Tree tree, int node){
+		if (beginState == null || endState==null) {
+			return;
+		}
+		if (!(beginState instanceof CategoricalState[]) || !(endState instanceof CategoricalState[])){
+			for(int i=0;i<endState.length;i++)
+				endState[i].setToUnassigned();
+			return;
+		}
+		CategoricalState[] bState = (CategoricalState[])beginState;
+		CategoricalState[] eState = (CategoricalState[])endState;
+		int [] bsa = new int[bState.length];
+		for(int i=0;i<bsa.length;i++)
+			bsa[i] = CategoricalState.minimum(bState[i].getValue());
+		int []r = evolveState(bsa, tree, node); //todo: issue error if beginning is polymorphic?  choose randomly among beginning?
+		for(int i=0;i<r.length;i++)
+			eState[i].setValue(CategoricalState.makeSet(r[i]));
+	}
+
+	public String getModelTypeAsString() {
+		switch (modelType){
+			case MODEL4PARAM:{
+				return "4 Parameter model";
+			}
+			case MODEL8PARAM:{
+				return "8 parameter model";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {
+				return "7 parameter model y forward change contingent on x";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: { 
+				return "7 parameter model y backward change contigent on x";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXFORWARD: {
+				return "7 parameter model x forward change contingent on y";
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD: {
+				return "7 parameter model x forward change contingent on y";
+			}
+			case MODEL6PARAMCONTINGENTCHANGEY: {
+				return "6 parameter model y change contingent on x";
+			}
+			case MODEL6PARAMCONTINGENTCHANGEX:{
+				return "6 parameter model x forward change contingent on y";
+			}
+		}
+		return null;
+	}
+	public String getParameters() {
+		switch (modelType){
+			case MODEL4PARAM:{
+				return "q12(alpha1) =" + params[1] + "\nq13(alpha2) = " 
+				             + params[0] + "\nq21(beta1) = " + params[3] + "\nq31(beta2) = " + params[2];
+			}
+			case MODEL8PARAM:{
+				return "q12 = " + params[0] + "\nq13 = " + params[1] + 
+				         "\nq21 = " + params[2] + "\nq31 = " + params[3] +
+				         "\nq24 = " + params[4] + "\nq34 = " + params[5] +
+				         "\nq42 = " + params[6] + "\nq43 = " + params[7];
+
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYFORWARD: {  //ToDo check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[0] +
+		                  " q42 = " + params[5] + " q43 = " + params[6];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEYBACKWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[5] +
+		                  " q42 = " + params[6] + " q43 = " + params[2];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXFORWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[1] + " q34 = " + params[4] +
+		                  " q42 = " + params[5] + " q43 = " + params[6];
+			}
+			case MODEL7PARAMCONTINGENTCHANGEXBACKWARD: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[5] +
+		                  " q42 = " + params[3] + " q43 = " + params[6];
+			}
+			case MODEL6PARAMCONTINGENTCHANGEY: { //TODO check me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[4] + " q34 = " + params[0] +
+		                  " q42 = " + params[5] + " q43 = " + params[2];
+			}
+			case MODEL6PARAMCONTINGENTCHANGEX:{  //TODO trim me
+				return "q12 = " + params[0] + " q13 = " + params[1] + 
+		                  " q21 = " + params[2] + " q31 = " + params[3] +
+		                  " q24 = " + params[1] + " q34 = " + params[4] +
+		                  " q42 = " + params[3] + " q43 = " + params[5];
+			}
+		}
+		return null;
+	}
+	
+	
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof PagelMatrixModel))
+			return;
+		super.copyToClone(md);
+		PagelMatrixModel model = (PagelMatrixModel)md;
+		model.params = (double[])params.clone();
+		model.recalcProbsNeeded = true;
+		model.needToPrepareMatrices = true;
+		model.qMapping = (int [])qMapping.clone();          // mapping from known, underparameterized models
+		model.qConstrained = (boolean[]) qConstrained.clone();  // true if a q value is somehow constrained
+		model.qBound = (int []) qBound;           // qvalue bound to another qvalue (-1 = not bound)
+		model.qConstant = (double []) qConstant;     // qvalue is set to this constant; 
+		model.savedRootEstimates = (double [][])savedRootEstimates;
+		model.prepareMatrices();
+		model.notifyListeners(model, new Notification(MesquiteListener.UNKNOWN));
+	}
+	
+
+
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		PagelMatrixModel j = new PagelMatrixModel(name, getStateClass(), modelType);
+		copyToClone(j);
+		j.recalcProbsNeeded = true;
+		j.needToPrepareMatrices = true;
+		completeDaughterClone(formerClone, j);
+		j.prepareMatrices();
+		return j;			
+	}
+
+	public boolean isFullySpecified() {
+		boolean result = true;
+		for (int i = 0;i<params.length;i++)
+			if (params[i] == MesquiteDouble.unassigned)
+				result = false;
+		return result;
+	}
+
+	public String getModelTypeName() {
+		// TODO Auto-generated method stub
+		return "Stochastic matrix model as described in Pagel1994";
+	}
+
+	public String getExplanation() {
+		return "Estimates and simulates discrete characters using the matrices described in Pagel 1994";
+	}
+	
+	
+    public void showSurface(Tree tree,CategoricalDistribution dist1, CategoricalDistribution dist2, int divisions) {
+    	    Tree savedTree = workingTree;
+    	    workingTree = tree;
+    	    CategoricalDistribution savedObservedStates1 = observedStates1;
+    	    observedStates1 = dist1;
+    	    CategoricalDistribution savedObservedStates2 = observedStates2;
+    	    observedStates2 = dist2;
+        double [] outBounds = new double[params.length];
+        double [] upperBounds = new double[params.length];
+        for (int i = 0;i<upperBounds.length;i++)
+        		upperBounds[i] = 8.5;
+        double [] lowerBounds = new double[params.length];
+        for (int i = 0;i<lowerBounds.length;i++)
+        		lowerBounds[i] = 0.5;
+        getLikelihoodSurface(16,outBounds,upperBounds,lowerBounds);
+        // restore fields
+        workingTree = savedTree;
+        observedStates1 = savedObservedStates1;
+        observedStates2 = savedObservedStates2;
+    }
+    private void getLikelihoodSurface(int divisions,double[] outputBounds,double[]upperBounds,double[]lowerBounds){ //also pass upper & lower bounds
+        // hold paramCount-2 parameters fixed, vary pairs through fixed bounds; just call evaluate
+        // put values into surface, then write values to mesquite console
+        Optimizer opt = new Optimizer(this);
+        boolean savedUnassigned []= (boolean [])paramUnassigned.clone();
+        double savedParams[] = (double [])params.clone();
+        paramUnassigned = new boolean[params.length];       
+        double[] localParams = new double[params.length];
+       // for (int i=0;i<localParams.length;i++)
+      //	   localParams[i] = 8.0;
+        double[][] surface = new double[divisions][divisions];
+        for (int j= 0;j<divisions;j++){
+        		double x = (j*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+             for (int k=0;k<divisions;k++){
+                 double y = (k*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                 for(int l=0;l<divisions;l++){
+                	    double z = (l*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                	    for(int m=0;m<divisions;m++) {
+                	    	   double w = (m*(upperBounds[1]-lowerBounds[1])/divisions)+lowerBounds[1];
+                	    	   localParams[0]=x;
+                	    	   localParams[1]=y;
+                	    	   localParams[2]=z;
+                	    	   localParams[3]=w;
+                	    	   //surface[j][k]=evaluate(localParams,null);
+                	    }
+                }
+            }
+//            localParams[2*i] = savedParams[2*i];
+//            localParams[2*i+1] = savedParams[2*i+1];
+        }
+        if (outputBounds == null) {
+            MesquiteMessage.warnProgrammer("No double[][] array supplied to receive output bounds or array too small");
+        }
+        if (outputBounds.length != 2) {
+            MesquiteMessage.warnProgrammer("Array supplied to receive output bounds too small");
+        }
+        //THIS DOESN:T work at present
+        //arbitrarily choose the midpoints
+        if (upperBounds != null && lowerBounds != null){
+            for(int i=0;i<params.length;i++){
+                if (MesquiteDouble.isCombinable(upperBounds[i]) &&
+                    MesquiteDouble.isCombinable(lowerBounds[i]))
+                    params[i] = (upperBounds[i]+lowerBounds[i])/2;
+                else
+                    params[i] = 0.001;  //avoid zero in case of model pathology
+                }
+            }
+            else {
+                for(int i=0;i<params.length;i++)
+                    params[i] = 0.001;
+            }
+            opt.optimize(params, null);
+            if (upperBounds == null)
+                upperBounds = opt.getUpperBoundsSearched();
+            if (lowerBounds == null)
+                lowerBounds = opt.getLowerBoundsSearched();
+            for(int i=0;i<upperBounds.length;i++){  //assumes upperBounds.length == lowerBounds.length
+                if (upperBounds[i]<0)
+                    upperBounds[i] = 0;
+                if (lowerBounds[i]<0)
+                    lowerBounds[i] = 0;
+            }
+        paramUnassigned = savedUnassigned;
+        this.params = savedParams;
+    }
+    
+    public double[][] grid(double[] params,int[]freeParams,double min1, double max1, double min2, double max2, int divisions){
+        double[][] g = new double[divisions][divisions];
+        double[] x = new double[params.length];
+        for (int i = 0;i<params.length;i++)
+            if (i!=freeParams[0] && i!=freeParams[1])
+                x[i]=params[i];
+        for (int i = 0; i<divisions; i++){
+            x[freeParams[0]] =i* (max1-min1)/divisions + min1;
+            for (int j = 0; j<divisions; j++){
+                x[freeParams[1]] =j* (max2-min2)/divisions + min2;
+                double fcn = evaluate(x, null);
+                g[i][j] = fcn;
+                //System.out.println(x[0] + "\t" + x[1] + "\t" + fcn);
+            }
+        }
+        return g;
+    }
+
+    /* All the following are useful for debugging, but shouldn't be called in released code. */
+    
+    public void setTree(Tree tree) {
+    		this.workingTree = tree;
+    }
+    
+    public void setObserved1(CategoricalDistribution dist1) {
+    		this.observedStates1 = dist1;
+    }
+    
+    // fix this
+    public void setObserved2(CategoricalDistribution dist2) {
+		this.observedStates2 = dist2;
+		maxState[0] = observedStates1.getMaxState();    	
+		maxState[1] = observedStates2.getMaxState();
+		allStates[0] = CategoricalState.span(0,maxState[0]);
+		allStates[1] = CategoricalState.span(0,maxState[1]);
+    }
+    
+    // end debugging methods
+    
+    public void setProgress(ProgressIndicator p){
+    		prog = p;
+    }
+    
+    public class StuckSearchException extends RuntimeException{
+    }
+
+
+}   
+
diff --git a/Source/mesquite/correl/notes/disc2.nex b/Source/mesquite/correl/notes/disc2.nex
new file mode 100644
index 0000000..cb5550f
--- /dev/null
+++ b/Source/mesquite/correl/notes/disc2.nex
@@ -0,0 +1,317 @@
+#NEXUS
+[written Mon Apr 03 18:29:58 PDT 2006 by Mesquite  version 1.06+ (build h54) at Pellenes-4.local/127.0.0.1]
+
+BEGIN TAXA;
+	TITLE Taxa_from_Pagel_format_file;
+	DIMENSIONS NTAX=18;
+	TAXLABELS
+		n1 n2 n3 n4 n5 n6 n7 n8 n9 an1 an2 an3 an4 an5 an6 an7 an8 an9 
+	;
+	IDS 010a6279978b31 010a6279978b32 010a6279978f33 010a6279979934 010a6279979935 010a6279979a36 010a6279979a37 010a6279979a38 010a6279979a39 010a6279979a40 010a6279979a41 010a627997a742 010a627997a743 010a627997b144 010a627997b145 010a627997b146 010a627997b247 010a627997b248 ;
+	BLOCKID 010a6279976b2;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	n1   00
+	n2   11
+	n3   11
+	n4   00
+	n5   00
+	n6   00
+	n7   00
+	n8   00
+	n9   11
+	an1  00
+	an2  11
+	an3  11
+	an4  00
+	an5  00
+	an6  00
+	an7  00
+	an8  00
+	an9  11
+
+;
+	IDS 010a6279978b2 010a6279978b3 ;
+	BLOCKID 010a6279976b0;
+
+
+END;
+BEGIN TREES;
+	Title Trees_imported_from_Pagel_file;
+	LINK Taxa = Taxa_from_Pagel_format_file;
+	TRANSLATE
+		1 n1,
+		2 n2,
+		3 n3,
+		4 n4,
+		5 n5,
+		6 n6,
+		7 n7,
+		8 n8,
+		9 n9,
+		10 an1,
+		11 an2,
+		12 an3,
+		13 an4,
+		14 an5,
+		15 an6,
+		16 an7,
+		17 an8,
+		18 an9;
+	TREE Imported_tree = ((((5:22.0,(4:20.0,(1:29.0,(2:29.0,3:25.0):15.0):11.0):10.0):18.0,(6:3.0,7:2.0):28.0):10.0,(8:2.0,9:22.0):56.0):1.0,(((14:1.0,(13:1.0,(10:1.0,(11:1.0,12:1.0):1.0):1.0):1.0):1.0,(15:1.0,16:1.0):1.0):1.0,(17:1.0,18:1.0):1.0):1.0):1.0;
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 6027805953763960218 010a6279976b2;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 4828998278273231534 010a6279976b0;
+			checksum 0 2969446841;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #4828998278273231534 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 420 280;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWithCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getWindow;
+				tell It;
+					forceAutosize;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.collab.AnnotInfo.AnnotInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.CellImages.CellImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.ChgHistoryInfo.ChgHistoryInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.StateImages.StateImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.aaManageImageIndices.aaManageImageIndices;
+				tell It;
+					setLocal;
+					setPrevIndexBase 'http://mesquiteproject.org/mesquite/collab/indexedImages';
+					reset;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #6027805953763960218  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 1012.1144113437034.7140769181719514904;
+				getTreeWindow;
+				tell It;
+					setSize 834 473;
+					setLocation 200 60;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientUp;
+						toggleCosmic off;
+						toggleArc on;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleCenter off;
+							toggleEven off;
+							namesAngle ?;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths off;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize on;
+					toggleTextOnTree off;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #4828998278273231534;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 1   'Mk1 (est.)';
+							endTell;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Sum_Likelihoods;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -168;
+					setInitialOffsetY -390;
+					setLegendWidth 142;
+					setLegendHeight 160;
+					resume ;
+				endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.cartographer.TaxonGroupSymbols.TaxonGroupSymbols;
+				tell It;
+					showSymbols off;
+					combineColors off;
+					setColors on;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.collab.ManageAuthors.ManageAuthors;
+		tell It;
+			addAuthorNameToMatrices;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/correl/notes/disc2.ppy b/Source/mesquite/correl/notes/disc2.ppy
new file mode 100644
index 0000000..7d251a2
--- /dev/null
+++ b/Source/mesquite/correl/notes/disc2.ppy
@@ -0,0 +1,42 @@
+#data file for primates
+
+#data structure is:
+#node,ancestor,branch length,trait 1,trait 2
+
+n1,n11,29,0,0
+n2,n10,29,1,1
+n3,n10,25,1,1
+n4,n12,20,0,0
+n5,n13,22,0,0
+n6,n14,3,0,0
+n7,n14,2,0,0
+n8,n16,2,0,0
+n9,n16,22,1,1
+n10,n11,15
+n11,n12,11
+n12,n13,10
+n13,n15,18
+n14,n15,28
+n15,n17,10
+n16,n17,56
+an1,an11,1,0,0
+an2,an10,1,1,1
+an3,an10,1,1,1
+an4,an12,1,0,0
+an5,an13,1,0,0
+an6,an14,1,0,0
+an7,an14,1,0,0
+an8,an16,1,0,0
+an9,an16,1,1,1
+an10,an11,1
+an11,an12,1
+an12,an13,1
+an13,an15,1
+an14,an15,1
+an15,an17,1
+an16,an17,1
+n17,n18,1
+an17,n18,1
+
+
+
diff --git a/Source/mesquite/correl/notes/omphalina.nex b/Source/mesquite/correl/notes/omphalina.nex
new file mode 100644
index 0000000..e94636a
--- /dev/null
+++ b/Source/mesquite/correl/notes/omphalina.nex
@@ -0,0 +1,341 @@
+#NEXUS
+[written Mon Apr 03 18:30:19 PDT 2006 by Mesquite  version 1.06+ (build h54) at Pellenes-4.local/127.0.0.1]
+
+BEGIN TAXA;
+	TITLE Taxa_from_Pagel_format_file;
+	DIMENSIONS NTAX=30;
+	TAXLABELS
+		n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n15 n16 n17 n18 n19 n20 n21 n22 n23 n24 n25 n26 n27 n28 n29 n30 
+	;
+	IDS 010a62787ccd1 010a62787cd22 010a62787cd23 010a62787cd34 010a62787cd35 010a62787cd36 010a62787cd37 010a62787cd48 010a62787cd49 010a62787cd410 010a62787cd411 010a62787cd412 010a62787cd513 010a62787cd514 010a62787cd515 010a62787cd616 010a62787cd717 010a62787cd818 010a62787cd819 010a62787cd920 010a62787cd921 010a62787cd922 010a62787cde23 010a62787cde24 010a62787ce025 010a62787ce026 010a62787ce127 010a62787ce128 010a62787ce129 010a62787ce230 ;
+	BLOCKID 010a62787c211;
+
+END;
+
+
+BEGIN CHARACTERS;
+	TITLE  Untitled_Character_Matrix;
+	DIMENSIONS  NCHAR=2;
+	FORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = "  0 1";
+	MATRIX
+	n1   11
+	n2   11
+	n3   00
+	n4   11
+	n5   00
+	n6   10
+	n7   00
+	n8   00
+	n9   00
+	n10  00
+	n11  00
+	n12  00
+	n13  00
+	n14  00
+	n15  00
+	n16  00
+	n17  10
+	n18  11
+	n19  10
+	n20  11
+	n21  11
+	n22  00
+	n23  00
+	n24  00
+	n25  00
+	n26  00
+	n27  00
+	n28  00
+	n29  00
+	n30  00
+
+;
+	IDS 010a62787ccc0 010a62787ccc1 ;
+	BLOCKID 010a62787c350;
+
+
+END;
+BEGIN TREES;
+	Title Trees_imported_from_Pagel_file;
+	LINK Taxa = Taxa_from_Pagel_format_file;
+	TRANSLATE
+		1 n1,
+		2 n2,
+		3 n3,
+		4 n4,
+		5 n5,
+		6 n6,
+		7 n7,
+		8 n8,
+		9 n9,
+		10 n10,
+		11 n11,
+		12 n12,
+		13 n13,
+		14 n14,
+		15 n15,
+		16 n16,
+		17 n17,
+		18 n18,
+		19 n19,
+		20 n20,
+		21 n21,
+		22 n22,
+		23 n23,
+		24 n24,
+		25 n25,
+		26 n26,
+		27 n27,
+		28 n28,
+		29 n29,
+		30 n30;
+	TREE Imported_tree = ((((8:42.0,9:50.0):394.0,(((13:135.0,(14:135.0,(15:7.0,16:1.0):210.0):156.0):51.0,((17:244.0,((18:334.0,19:185.0):87.0,(20:106.0,21:183.0):390.0):112.0):51.0,(22:94.0,(23:75.0,((24:56.0,25:1.0):59.0,((28:181.0,(29:37.0,30:33.0):64.0):27.0,(26:92.0,27:56.0):54.0):56.0):10.0):15.0):91.0):62.0):40.0,(10:44.0,(11:120.0,12:30.0):23.0):83.0):66.0):160.0,((5:234.0,(6:67.0,7:86.0):33.0):31.0,(3:86.0,4:584.0):53.0):177.0):121.0,(1:31.0,2:85.0):683.0):1.0;
+
+END;
+
+
+BEGIN ASSUMPTIONS;
+	TYPESET * UNTITLED   =  unord:  1 -  2;
+
+END;
+
+BEGIN CODONS;
+CODESET * UNTITLED   =  universal:  1 -  2;
+
+
+END;
+
+BEGIN MESQUITECHARMODELS;
+	ProbModelSet * UNTITLED   =  'Mk1 (est.)':  1 -  2;
+END;
+
+Begin MESQUITE;
+		MESQUITESCRIPTVERSION 2;
+		TITLE AUTO;
+		tell ProjectCoordinator;
+		getEmployee #mesquite.minimal.ManageTaxa.ManageTaxa;
+		tell It;
+			setID 0 986371403473966793 010a62787c211;
+		endTell;
+		getEmployee #mesquite.charMatrices.ManageCharacters.ManageCharacters;
+		tell It;
+			setID 0 838944407393323027 010a62787c350;
+			checksum 0 2119533900;
+		endTell;
+		getEmployee  #mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord;
+		tell It;
+			showDataWindow #838944407393323027 #mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindowMaker;
+			tell It;
+				getWindow;
+				tell It;
+					setSize 420 280;
+					setLocation 60 22;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+						setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					endTell;
+					setTool mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow.arrow;
+					colorCells  #mesquite.charMatrices.NoColor.NoColor;
+					setBackground White;
+					toggleShowNames on;
+					toggleTight off;
+					toggleShowChanges on;
+					toggleSeparateLines off;
+					toggleShowStates on;
+					toggleAutoWithCharNames on;
+					toggleShowDefaultCharNames off;
+					toggleConstrainCW on;
+					toggleBirdsEye off;
+					toggleColorsPanel off;
+					birdsEyeWidth 2;
+					toggleLinkedScrolling on;
+					toggleScrollLinkedTables off;
+				endTell;
+				showWindow;
+				getWindow;
+				tell It;
+					forceAutosize;
+				endTell;
+				getEmployee #mesquite.categ.StateNamesStrip.StateNamesStrip;
+				tell It;
+					showStrip off;
+				endTell;
+				getEmployee #mesquite.charMatrices.AnnotPanel.AnnotPanel;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.charMatrices.ColorCells.ColorCells;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.charMatrices.QuickKeySelector.QuickKeySelector;
+				tell It;
+					autotabOff;
+				endTell;
+				getEmployee #mesquite.collab.AnnotInfo.AnnotInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.CellImages.CellImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.ChgHistoryInfo.ChgHistoryInfo;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.StateImages.StateImages;
+				tell It;
+					togglePanel off;
+				endTell;
+				getEmployee #mesquite.collab.aaManageImageIndices.aaManageImageIndices;
+				tell It;
+					setLocal;
+					setPrevIndexBase 'http://mesquiteproject.org/mesquite/collab/indexedImages';
+					reset;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord;
+		tell It;
+			makeTreeWindow #986371403473966793  #mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker;
+			tell It;
+				setTreeSource  #mesquite.trees.StoredTrees.StoredTrees;
+				tell It;
+					setTreeBlock 1;
+					toggleUseWeights off;
+				endTell;
+				setAssignedID 825.1144113365102.8444102935486794717;
+				getTreeWindow;
+				tell It;
+					setSize 763 519;
+					setLocation 200 60;
+					setFont SanSerif;
+					setFontSize 10;
+					onInfoBar;
+					setExplanationSize 30;
+					setAnnotationSize 20;
+					setFontIncAnnot 0;
+					setFontIncExp 0;
+					getToolPalette;
+					tell It;
+					endTell;
+					setActive;
+					getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;
+				tell It;
+					suppress;
+					setTreeDrawer  #mesquite.trees.BallsNSticks.BallsNSticks;
+					tell It;
+						setSpotDiameter 22;
+						setEdgeWidth 2;
+						orientUp;
+						toggleCosmic off;
+						toggleArc on;
+						getEmployee #mesquite.trees.NodeLocsStandard.NodeLocsStandard;
+						tell It;
+							stretchToggle off;
+							branchLengthsToggle on;
+							toggleScale on;
+							toggleCenter off;
+							toggleEven off;
+							namesAngle ?;
+						endTell;
+					endTell;
+					setBackground White;
+					setBranchColor Black;
+					showNodeNumbers off;
+					labelBranchLengths off;
+					desuppress;
+					getEmployee #mesquite.trees.BasicDrawTaxonNames.BasicDrawTaxonNames;
+					tell It;
+						setColor Black;
+						toggleColorPartition on;
+						toggleShadePartition off;
+						toggleNodeLabels on;
+						toggleShowNames on;
+					endTell;
+				endTell;
+					setTreeNumber 1;
+					useSuggestedSize on;
+					toggleTextOnTree off;
+					newAssistant  #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
+				tell It;
+					suspend ;
+					setDisplayMode  #mesquite.ancstates.ShadeStatesOnTree.ShadeStatesOnTree;
+					tell It;
+						toggleLabels off;
+					endTell;
+					setHistorySource  #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
+					tell It;
+						getCharacterSource  #mesquite.charMatrices.CharSrcCoordObed.CharSrcCoordObed;
+						tell It;
+							setCharacterSource #mesquite.charMatrices.StoredCharacters.StoredCharacters;
+							tell It;
+								setDataSet #838944407393323027;
+							endTell;
+						endTell;
+						setMethod  #mesquite.stochchar.MargProbAncStates.MargProbAncStates;
+						tell It;
+							setModelSource  #mesquite.stochchar.StoredProbModel.StoredProbModel;
+							tell It;
+								setModel 1   'Mk1 (est.)';
+							endTell;
+							getEmployee #mesquite.stochchar.zMargLikeCateg.zMargLikeCateg;
+							tell It;
+								setReportMode Proportional_Likelihoods;
+								setRootMode Sum_Likelihoods;
+								setDecision 2.0;
+								setUnderflowCheckFreq 2;
+							endTell;
+						endTell;
+					endTell;
+					setCharacter 1;
+					setMapping 1;
+					toggleShowLegend on;
+					toggleGray off;
+					toggleWeights on;
+					setInitialOffsetX -162;
+					setInitialOffsetY -175;
+					setLegendWidth 142;
+					setLegendHeight 175;
+					resume ;
+				endTell;
+				endTell;
+				showWindow;
+				getEmployee #mesquite.ornamental.BranchNotes.BranchNotes;
+				tell It;
+					setAlwaysOn off;
+				endTell;
+				getEmployee #mesquite.ornamental.ColorTreeByPartition.ColorTreeByPartition;
+				tell It;
+					colorByPartition off;
+				endTell;
+				getEmployee #mesquite.trees.ColorBranches.ColorBranches;
+				tell It;
+					setColor Red;
+					removeColor off;
+				endTell;
+				getEmployee #mesquite.cartographer.TaxonGroupSymbols.TaxonGroupSymbols;
+				tell It;
+					showSymbols off;
+					combineColors off;
+					setColors on;
+				endTell;
+			endTell;
+		endTell;
+		getEmployee  #mesquite.collab.ManageAuthors.ManageAuthors;
+		tell It;
+			addAuthorNameToMatrices;
+		endTell;
+		endTell;
+end;
+
+
diff --git a/Source/mesquite/correl/notes/omphalina.ppy b/Source/mesquite/correl/notes/omphalina.ppy
new file mode 100644
index 0000000..d496bbc
--- /dev/null
+++ b/Source/mesquite/correl/notes/omphalina.ppy
@@ -0,0 +1,67 @@
+#data file for omphalina
+
+#data structure is:
+#node,ancestor,branch length,trait 1,trait 2 
+#trait 1:  0=non mutualist 1=mutualist
+#trait 2:  0=slow 1=fast
+
+n1,n58,31,1,1
+n2,n58,85,1,1
+n3,n55,86,0,0
+n4,n55,584,1,1
+n5,n54,234,0,0
+n6,n53,67,1,0
+n7,n53,86,0,0
+n8,n31,42,0,0
+n9,n31,50,0,0
+n10,n50,44,0,0
+n11,n49,120,0,0
+n12,n49,30,0,0
+n13,n34,135,0,0
+n14,n33,135,0,0
+n15,n32,7,0,0
+n16,n32,1,0,0
+n17,n38,244,1,0
+n18,n35,334,1,1
+n19,n35,185,1,0
+n20,n36,106,1,1
+n21,n36,183,1,1
+n22,n46,94,0,0
+n23,n45,75,0,0
+n24,n39,56,0,0
+n25,n39,1,0,0
+n26,n42,92,0,0
+n27,n42,56,0,0
+n28,n41,181,0,0
+n29,n40,37,0,0
+n30,n40,33,0,0
+n31,n52,394
+n32,n33,210
+n33,n34,156
+n34,n48,51
+n35,n37,87
+n36,n37,390
+n37,n38,112
+n38,n47,51
+n39,n44,59
+n40,n41,64
+n41,n43,27
+n42,n43,54
+n43,n44,56
+n44,n45,10
+n45,n46,15
+n46,n47,91
+n47,n48,62
+n48,n51,40
+n49,n50,23
+n50,n51,83
+n51,n52,66
+n52,n57,160
+n53,n54,33
+n54,n56,31
+n55,n56,53
+n56,n57,177
+n57,n59,121
+n58,n59,683
+
+
diff --git a/Source/mesquite/distance/AbsoluteDistance/AbsoluteDistance.java b/Source/mesquite/distance/AbsoluteDistance/AbsoluteDistance.java
new file mode 100644
index 0000000..96d7826
--- /dev/null
+++ b/Source/mesquite/distance/AbsoluteDistance/AbsoluteDistance.java
@@ -0,0 +1,151 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+/* Jeff Oliver May 08
+ * 
+ * Almost identical to UncorrectedDistance, but total distance is not 
+ * divided by total number of characters.*/
+
+
+package mesquite.distance.AbsoluteDistance;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class AbsoluteDistance extends TaxaDistFromMatrix {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in Absolute Distance");
+			return null;
+		}
+		SimpleTD simpleTD = new SimpleTD( taxa, observedStates);
+		return simpleTD;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Absolute Distance (General)";  
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Absolute distance from a character matrix." ;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+ 	public int getVersionOfFirstRelease(){
+ 		return 250;  
+ 	}
+}
+
+/* ======================================================================== */
+class SimpleTD extends TaxaDistance {
+	double[][] distances;
+	int numTaxa;
+	
+	/*.................................................................................................................*/
+	public SimpleTD(Taxa taxa, MCharactersDistribution observedStates){
+		super(taxa);
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+			
+		if (observedStates instanceof MContinuousDistribution){
+			MContinuousDistribution contStates = (MContinuousDistribution)observedStates;
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			Double2DArray.deassignArray(distances);
+			for (int taxon1=0; taxon1<numTaxa; taxon1++)
+				for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+					double sumDiffs =0;
+					if (taxon1!=taxon2)
+						for (int ic=0; ic< contStates.getNumChars(); ic++) {
+							if (incl == null || incl.isBitOn(ic)){
+								double one =contStates.getState(ic, taxon1, 0);
+								double two = contStates.getState(ic, taxon2, 0);
+								if (MesquiteDouble.isCombinable(one) && MesquiteDouble.isCombinable(two))
+									sumDiffs += Math.abs(one-two); //item 0
+							}
+						}
+					distances[taxon1][taxon2]=sumDiffs;
+				}
+		}
+		else if (observedStates instanceof MCategoricalDistribution){
+			MCategoricalDistribution catStates = (MCategoricalDistribution)observedStates;
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			for (int taxon1=0; taxon1<numTaxa; taxon1++)
+				for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+					double total = 0;
+					double sumDiffs =0;
+					distances[taxon1][taxon2]=0.0;
+					if (taxon1!=taxon2){
+						for (int ic=0; ic< catStates.getNumChars(); ic++) {
+							if (incl == null || incl.isBitOn(ic)){
+								long one =catStates.getState(ic, taxon1) & CategoricalState.dataBitsMask;
+								long two = catStates.getState(ic, taxon2) & CategoricalState.dataBitsMask;
+								if (CategoricalState.cardinality(one)>0 || CategoricalState.cardinality(two)>0)
+									total+=1.0;
+								if (CategoricalState.isInapplicable(one) || CategoricalState.isInapplicable(two))  //if either inapplicable, don't count difference; should have option
+									continue;
+								if (CategoricalState.isUnassigned(one) || CategoricalState.isUnassigned(two))  //if either unassigned, don't count difference
+									continue;
+								if (one==two)  // they are the same
+									continue;
+								if (CategoricalState.statesShared(one, two) && (CategoricalState.isUncertain(one) || CategoricalState.isUncertain(two)))
+									continue;
+								sumDiffs += 1.0; 
+							}
+						}
+						distances[taxon1][taxon2]=sumDiffs;
+					}
+				}
+		}
+	}
+	/*.................................................................................................................*/
+	public double getDistance(int taxon1, int taxon2){
+		if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+			return distances[taxon1][taxon2];
+		else
+			return MesquiteDouble.unassigned;
+		
+	}
+	/*.................................................................................................................*/
+	public double[][] getMatrix(){
+		return distances;
+	}
+	/*.................................................................................................................*/
+	public boolean isSymmetrical(){
+		return true;
+	}
+}
diff --git a/Source/mesquite/distance/AverageOfDistances/AverageOfDistances.java b/Source/mesquite/distance/AverageOfDistances/AverageOfDistances.java
new file mode 100644
index 0000000..0e5c8b5
--- /dev/null
+++ b/Source/mesquite/distance/AverageOfDistances/AverageOfDistances.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.AverageOfDistances;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+public class AverageOfDistances extends TaxaDistanceSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(IncTaxaDistanceSource.class, getName() + "  needs a source of distances to average.",
+		"The source of distances can be selected initially");
+	}
+	/*.................................................................................................................*/
+	IncTaxaDistanceSource distanceTask;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		distanceTask = (IncTaxaDistanceSource)hireEmployee(IncTaxaDistanceSource.class, "Source of distances to be averaged");
+ 		if (distanceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of distances to be averaged was obtained.");
+ 		}
+ 		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		if (taxa ==null)
+   			return;
+        	distanceTask.initialize(taxa);
+   	}
+
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+		if (distanceTask instanceof Incrementable)
+			return new AvgDistances( taxa, this, distanceTask);
+		return distanceTask.getTaxaDistance(taxa);
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		temp.addLine("setDistanceSource ", distanceTask);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of distances for use in " + getName(), "[name of module]", commandName, "setDistanceSource")) { 
+    	 		IncTaxaDistanceSource temp=  (IncTaxaDistanceSource)replaceEmployee(IncTaxaDistanceSource.class, arguments, "Source of distances to be averaged", distanceTask);
+ 			if (temp!=null) {
+ 				distanceTask= temp;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+ 			return distanceTask;
+ 		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Average from " +  distanceTask.getName() + ", with parameters: " + distanceTask.getParameters();
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Average of Several Distances";  
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Average of several distances among taxa, e.g. average from several data matrices." ;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+}
+
+class AvgDistances extends TaxaDistance {
+	double[][] distances;
+	int numTaxa;
+ 	IncTaxaDistanceSource distanceTask;
+ 	
+ 	
+	public AvgDistances(Taxa taxa, MesquiteModule owner, IncTaxaDistanceSource distanceTask){
+		super(taxa);
+ 		numTaxa = taxa.getNumTaxa();
+
+		distances = new double[numTaxa][numTaxa];
+		Double2DArray.deassignArray(distances);
+		long min = distanceTask.getMin();
+		long max = distanceTask.getMax();
+		if (!MesquiteLong.isCombinable(min) || !MesquiteLong.isCombinable(max)) {
+			min = 0;
+			max = 9;
+			owner.discreetAlert( "WARNING Average of distances will use default 10 items");
+		}
+		for (long d = min; d<=max; d++) {
+			distanceTask.setCurrent(d);
+			TaxaDistance dist = distanceTask.getTaxaDistance(taxa);
+			if (dist != null) {
+				for (int i=0; i<numTaxa; i++)
+					for (int j=0; j<numTaxa; j++) {
+						double dd = dist.getDistance(i,j);
+						if (MesquiteDouble.isCombinable(dd)){
+							distances[i][j] = MesquiteDouble.add(distances[i][j], dd);
+						}
+					}
+			}
+		}
+		long n = max-min +1;
+		for (int i=0; i<numTaxa; i++)
+			for (int j=0; j<numTaxa; j++)
+					if (MesquiteDouble.isCombinable(distances[i][j]))
+						distances[i][j] /= n;
+			
+	}
+
+	public double getDistance(int taxon1, int taxon2){
+		if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+			return distances[taxon1][taxon2];
+		else
+			return MesquiteDouble.unassigned;
+		
+	}
+	public double[][] getMatrix(){
+		return distances;
+	}
+	public boolean isSymmetrical(){
+		return true;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/ClusterAnalysis/ClusterAnalysis.java b/Source/mesquite/distance/ClusterAnalysis/ClusterAnalysis.java
new file mode 100644
index 0000000..95c366c
--- /dev/null
+++ b/Source/mesquite/distance/ClusterAnalysis/ClusterAnalysis.java
@@ -0,0 +1,163 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.ClusterAnalysis;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+//eventually have DistanceTree as treeblock filler, which hires TreeClusterer and TaxaDistanceSource
+public class ClusterAnalysis extends TreeInferer implements Incrementable {  //Incrementable just in case distance task is
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaDistanceSource.class, getName() + "  needs a source of distances.",
+		"The source of distances can be selected initially");
+		EmployeeNeed ew= registerEmployeeNeed(TreeClusterer.class, getName() + "  needs a method to cluster taxa by distances..",
+		"The method to cluster taxa can be selected initially");
+	}
+	TaxaDistanceSource distanceTask;
+	TreeClusterer clusterer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		distanceTask = (TaxaDistanceSource)hireEmployee(TaxaDistanceSource.class, "Source of distance for Cluster Analysis");
+ 		if (distanceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of distances was obtained.");
+ 		}
+ 		clusterer = (TreeClusterer)hireEmployee(TreeClusterer.class, "Clustering method");
+ 		if (clusterer == null) {
+ 			return sorry(getName() + " couldn't start because no clusterer was obtained.");
+ 		}
+  		return true;
+  	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+ 	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		temp.addLine("setDistanceSource ", distanceTask);
+		temp.addLine("setClusterer ", clusterer);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of distances for use in cluster analysis", "[name of module]", commandName, "setDistanceSource")) { 
+    	 		TaxaDistanceSource temp=  (TaxaDistanceSource)replaceEmployee(TaxaDistanceSource.class, arguments, "Source of distance for cluster analysis", distanceTask);
+ 			if (temp!=null) {
+ 				distanceTask= temp;
+ 			}
+ 			return distanceTask;
+ 		}
+    	 	else if (checker.compare(this.getClass(), "Sets the clustering module for use in cluster analysis", "[name of module]", commandName, "setClusterer")) { 
+    	 		TreeClusterer temp=  (TreeClusterer)replaceEmployee(TreeClusterer.class, arguments, "Clustering routine for cluster analysis", clusterer);
+ 			if (temp!=null) {
+ 				clusterer= temp;
+ 			}
+ 			return clusterer;
+ 		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		if (distanceTask instanceof Incrementable)
+ 			((Incrementable)distanceTask).setCurrent(i);
+ 	}
+ 	public long getCurrent(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getCurrent();
+ 		return 0;
+ 	}
+ 	public String getItemTypeName(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getItemTypeName();
+ 		return "";
+ 	}
+ 	public long getMin(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getMin();
+		return 0;
+ 	}
+ 	public long getMax(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getMax();
+		return 0;
+ 	}
+ 	public long toInternal(long i){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).toInternal(i);
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).toExternal(i);
+ 		return i+1;
+ 	}
+ 	
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		distanceTask.initialize(taxa);
+
+   	}
+   	
+	/*.................................................................................................................*/
+  	public void fillTreeBlock(TreeVector treeList, int numberIfUnlimited){
+  		if (treeList==null)
+  			return;
+   		Taxa taxa = treeList.getTaxa();
+   		distanceTask.initialize(taxa);
+ 		TaxaDistance dist = distanceTask.getTaxaDistance(taxa);
+
+		clusterer.getTrees(taxa, dist, treeList);
+  		
+		treeList.setName("Trees from " + clusterer.getName() + " cluster analysis (Distance: " + distanceTask.getName() + ")");
+		treeList.setAnnotation ("Parameters: "  + getParameters() + ";  " + clusterer.getParameters() + "  Distance: " + distanceTask.getParameters(), false);
+  	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Clustering via  " + clusterer.getName() + " from " +  distanceTask.getName();
+   	}
+	/*.................................................................................................................*/
+   	 public boolean hasLimitedTrees(Taxa taxa){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Cluster analysis";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies trees obtained from cluster analysis on distance matrices.";
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
+
diff --git a/Source/mesquite/distance/DistanceContainedTaxa/DistanceContainedTaxa.java b/Source/mesquite/distance/DistanceContainedTaxa/DistanceContainedTaxa.java
new file mode 100644
index 0000000..bce11a0
--- /dev/null
+++ b/Source/mesquite/distance/DistanceContainedTaxa/DistanceContainedTaxa.java
@@ -0,0 +1,286 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.DistanceContainedTaxa;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public class DistanceContainedTaxa extends IncTaxaDistanceSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(AssociationSource.class, getName() + "  needs information about how the contained taxa (e.g. genes) are contained within the containing taxa (e.g. species).",
+		"The source of information about contained-containing taxa relationships is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(TaxaDistanceSource.class, getName() + "  needs a method to calculate distances between taxa.",
+		"The method to calculate distances can be selected initially or in the Contained Distance Calculation submenu");
+	}
+	/*.................................................................................................................*/
+	Taxa containedTaxa = null;
+	AssociationSource associationTask;
+	TaxaAssociation association;
+	TaxaDistanceSource distanceTask;
+	Class hiredAs = null;
+	ListableVector choices;
+	int mode = ContainedDistances.CLOSEST;
+	StringArray modes;
+	MesquiteString modeName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		if (associationTask == null)
+			return sorry(getName() + " couldn't start because no source of taxon associations obtained.");
+ 		hiredAs = getHiredAs();
+ 		distanceTask = (TaxaDistanceSource)hireEmployee(hiredAs, "Distance between contained taxa");
+ 		if (distanceTask == null) {
+ 			return sorry(getName() + " couldn't start because a contained taxa distance calculator was not obtained.");
+ 		}
+ 		MesquiteSubmenuSpec modeSubmenu = addSubmenu(null, "Contained Distance Calculation");
+		modes = new StringArray(2);
+		modes.setValue(ContainedDistances.CLOSEST, "Closest");
+		modes.setValue(ContainedDistances.ARITHMETIC, "Arithmetic Mean");
+		//modes.setValue(ContainedDistances.GEOMETRIC, "Geometric Mean");  not yet turned on
+		modeName = new MesquiteString(modes.getValue(mode));
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Contained Distance Calculation", makeCommand("setMode",  this), modes);
+		mss.setSelected(modeName);
+ 		if (!MesquiteThread.isScripting()){
+ 			int tempMode = ListDialog.queryList(containerOfModule(), "Contained Distance Calculation", "Counting distances among contained taxa", null, modes.getStrings(), mode);
+ 			if (MesquiteInteger.isCombinable(tempMode)) {
+ 				mode = tempMode;
+ 				logln("Use mode: " + modes.getValue(mode));
+ 			}
+ 		}
+ 		
+ 		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		if (taxa ==null)
+   			return;
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+        	}
+        	distanceTask.initialize(containedTaxa);
+   	}
+
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+        	//initialize(taxa);
+        	if (association == null || (association.getTaxa(0)!= taxa && association.getTaxa(1)!= taxa)) {
+        		association = associationTask.getCurrentAssociation(taxa); 
+        		if (association.getTaxa(0)== taxa)
+        			containedTaxa = association.getTaxa(1);
+        		else
+        			containedTaxa = association.getTaxa(0);
+        	}
+ 		TaxaDistance dist = distanceTask.getTaxaDistance(containedTaxa); //get distances among contained taxa
+ 		
+		ContainedDistances cc = new ContainedDistances(this, taxa, containedTaxa, dist, association, mode);
+		return cc;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		temp.addLine("setDistanceSource ", distanceTask);
+   	 	temp.addLine("setMode " + mode);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of distances for use in " + getName(), "[name of module]", commandName, "setDistanceSource")) { 
+    	 		TaxaDistanceSource temp=  (TaxaDistanceSource)replaceEmployee(hiredAs, arguments, "Source of distance for among contained taxa", distanceTask);
+ 			if (temp!=null) {
+ 				distanceTask= temp;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+ 			return distanceTask;
+ 		}
+    	 	else if (checker.compare(this.getClass(), "Sets how contained distances are counted", "[0 = use closest distance among contained taxa, " +
+    	 				"1 = use arithmetic mean of distances among contained taxa, 2 = use geometric mean of distances among contained taxa]", commandName, "setMode")) {
+			String name = parser.getFirstToken(arguments);
+			int newMode = modes.indexOf(name);
+			if (newMode <0)
+				newMode = MesquiteInteger.fromString(name);
+			if (newMode >=0 && newMode!=mode){
+				mode = newMode;
+	    			modeName.setValue(modes.getValue(mode));
+				logln("Mode of DistanceContainedTaxa set to " + modeName);	
+	    	 		if (!MesquiteThread.isScripting())
+	    	 			parametersChanged();
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+	}
+	/*.................................................................................................................*/
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		if (distanceTask instanceof Incrementable)
+ 			((Incrementable)distanceTask).setCurrent(i);
+ 	}
+ 	public long getCurrent(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getCurrent();
+ 		return 0;
+ 	}
+ 	public String getItemTypeName(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getItemTypeName();
+ 		return "";
+ 	}
+ 	public long getMin(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getMin();
+		return 0;
+ 	}
+ 	public long getMax(){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).getMax();
+		return 0;
+ 	}
+ 	public long toInternal(long i){
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).toInternal(i);
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		if (distanceTask instanceof Incrementable)
+ 			return ((Incrementable)distanceTask).toExternal(i);
+ 		return i+1;
+ 	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Distances of contained from " +  distanceTask.getName() + "; mode: " + modes.getValue(mode);
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Distance of Contained Taxa";  
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Distances among taxa according to distances among contained taxa (e.g., genes)." ;
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+}
+
+class ContainedDistances extends TaxaDistance {
+	double[][] distances;
+	int numTaxa;
+	static final int CLOSEST = 0;
+	static final int ARITHMETIC = 1;
+	static final int GEOMETRIC = 2;
+	DistanceContainedTaxa ownerModule;
+	public ContainedDistances(DistanceContainedTaxa ownerModule, Taxa taxa, Taxa containedTaxa, TaxaDistance containedDistances, TaxaAssociation association, int mode){
+		super(taxa);
+		this.ownerModule = ownerModule;
+		numTaxa = taxa.getNumTaxa();
+		distances = new double[numTaxa][numTaxa];
+		Double2DArray.deassignArray(distances);
+		if (association == null || containedDistances == null)
+			return;
+		for (int i=0; i<numTaxa; i++){
+			for (int j=0; j<i; j++){  //for taxa i and j, find contained taxa
+			 	Taxon[] containedI = association.getAssociates(taxa.getTaxon(i));
+			 	Taxon[] containedJ = association.getAssociates(taxa.getTaxon(j));
+				
+		 		double d = 0;
+		 		if (ownerModule.mode == CLOSEST)
+		 			d = MesquiteDouble.unassigned;
+		 		else if (ownerModule.mode == GEOMETRIC) //not yet used!
+		 			d = 1.0;
+		 			
+		 		int count = 0;
+			 	if (containedI!=null && containedJ !=null) {
+			 		for (int cI = 0; cI<containedI.length; cI++)  //survey distances among contained taxa
+				 		for (int cJ = 0; cJ<containedJ.length; cJ++) {
+				 			int taxI = containedTaxa.whichTaxonNumber(containedI[cI]);
+				 			int taxJ = containedTaxa.whichTaxonNumber(containedJ[cJ]);
+				 			double coal =containedDistances.getDistance(taxI, taxJ);
+				 			if (ownerModule.mode == CLOSEST){
+					 			if (MesquiteDouble.lessThan(coal, d, 0))  //d records closest distance among contained
+					 				d = coal;
+				 			}
+				 			else if (ownerModule.mode == GEOMETRIC){ //here we are just counting number of valid distances
+				 				if (MesquiteDouble.isCombinable(coal)) {
+				 					d *= coal;
+				 					count++;
+				 				}
+				 			}
+				 			else{
+				 				if (MesquiteDouble.isCombinable(coal)){ //d is sum of distances among contained
+				 					d += coal;
+				 					count++;
+				 				}
+				 			}
+				 		}
+			 	}
+			 	else {
+			 		MesquiteMessage.warnProgrammer("WARNING: Associates (contained taxa) null");
+			 	}
+	 			if (ownerModule.mode == GEOMETRIC){ //have product; calculate geometric mean //not yet used!
+				 	if (count>0 && containedI!=null && containedJ !=null) {
+				 		d = Math.pow(d, 1.0/count);
+				 	}
+	 			}
+	 			else if (ownerModule.mode == ARITHMETIC){  //have sum and number; calculate mean
+	 				if (MesquiteDouble.isCombinable(d) && count >0){
+	 					d  /= count;
+	 				}
+	 			}
+			 	distances[i][j] = d;
+			 	
+			}
+			
+		}
+		for (int i=0; i<numTaxa; i++){
+			for (int j=i; j<numTaxa; j++){
+			 	distances[i][j]=distances[j][i];
+			}
+			
+		}
+	}
+	public double getDistance(int taxon1, int taxon2){
+		if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+			return distances[taxon1][taxon2];
+		else
+			return MesquiteDouble.unassigned;
+		
+	}
+	public double[][] getMatrix(){
+		return distances;
+	}
+	public boolean isSymmetrical(){
+		return true;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/ExportTaxaDistances/ExportTaxaDistances.java b/Source/mesquite/distance/ExportTaxaDistances/ExportTaxaDistances.java
new file mode 100644
index 0000000..df8791d
--- /dev/null
+++ b/Source/mesquite/distance/ExportTaxaDistances/ExportTaxaDistances.java
@@ -0,0 +1,224 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.ExportTaxaDistances;
+
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+
+
+public class ExportTaxaDistances extends FileInterpreterI {
+	TaxaDistanceSource distanceTask;
+	Taxa currentTaxa = null;
+	boolean suspend = false;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "txt";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	String fileName = "distances.txt";
+	String addendum = "";
+/*
+	public boolean getExportOptions(Taxa taxa){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export distance matrix", buttonPressed);
+		exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		exportDialog.addLargeOrSmallTextLabel("Distances are to be exported from:\n\n" + distanceTask.getNameAndParameters());
+/ *		Checkbox itCheckBox = exportDialog.addCheckBox("Include Taxa Block", includeTaxaBlock);
+		exportDialog.addLabel("Addendum: ");
+
+		addendum = "";
+
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,16);
+* /
+		exportDialog.completeAndShowDialog();
+
+		boolean ok = (exportDialog.query()==0);
+
+
+		exportDialog.dispose();
+		return ok;
+	}	
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		setPreferredTaxa(taxa);
+		distanceTask = (TaxaDistanceSource)hireEmployee(TaxaDistanceSource.class, "Source of Distances among Taxa");
+		if (distanceTask == null)
+			return;
+	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		storePreferences();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			currentTaxa = null;
+		}
+	}
+
+	/*.................................................................................................................*/
+
+	public void setPreferredTaxa(Taxa taxa){
+		if (taxa !=currentTaxa) {
+			if (currentTaxa!=null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+
+	}
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+
+		Taxa taxa = 	 getProject().chooseTaxa(getModuleWindow(), "Choose taxa block"); 
+		if (taxa==null) 
+			return false;
+
+		if (distanceTask==null || taxa!=currentTaxa) {
+			initialize(taxa);
+			if (distanceTask==null)
+				return false;
+			distanceTask.initialize(currentTaxa);
+		}
+
+
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		String suggested = fileName;
+		if (file !=null) {
+			suggested = file.getFileName();
+			if (StringUtil.getLastItem(suggested, ".").equalsIgnoreCase("nex")) {
+				suggested = StringUtil.getAllButLastItem(suggested, ".") +".distances.txt";
+			}
+			else	if (StringUtil.getLastItem(suggested, ".").equalsIgnoreCase("nxs")) {
+				suggested = StringUtil.getAllButLastItem(suggested, ".") +".distances.txt";
+			}else
+				suggested = suggested +".distances.txt";
+		}
+
+		MesquiteFile f;
+		/*if (!usePrevious){
+			if (!getExportOptions(null)) {
+				distanceTask=null;
+				return false;
+			}
+		}
+		*/
+		if (!distanceTask.getDistanceOptions()) {
+			fireEmployee(distanceTask);
+			distanceTask=null;
+			return false;
+		}
+		TaxaDistance distances = distanceTask.getTaxaDistance(taxa);
+		if (distances == null){
+			return false;
+		}
+		String path = getPathForExport(arguments, suggested, dir, fn);
+		if (path != null) {
+			f = MesquiteFile.newFile(dir.getValue(), fn.getValue());
+			if (f !=null){
+				f.openWriting(true);
+				StringBuffer line = new StringBuffer(1000);
+				for (int it = 0; it<taxa.getNumTaxa(); it++){
+					line.setLength(0);
+					line.append(taxa.getTaxonName(it));
+					for (int it2 = 0; it2<taxa.getNumTaxa(); it2++){
+						line.append('\t');
+						line.append(MesquiteDouble.toString(distances.getDistance(it, it2)));
+					}
+					f.writeLine(line.toString());
+				}
+				f.closeWriting();
+				fireEmployee(distanceTask);
+				distanceTask=null;
+				return true;
+			}
+		}
+		fireEmployee(distanceTask);
+		distanceTask=null;
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Export Taxa Distance Matrix";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		String s =  "Exports a tab-delimited text file of distances among the taxa." ;
+		return s;
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/distance/F81Distance/F81Distance.java b/Source/mesquite/distance/F81Distance/F81Distance.java
new file mode 100644
index 0000000..f347555
--- /dev/null
+++ b/Source/mesquite/distance/F81Distance/F81Distance.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.F81Distance;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class F81Distance extends DNATaxaDistFromMatrixFreq {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }	 
+	/*.................................................................................................................*/
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in "+ getName());
+			return null;
+		}
+		if (!(observedStates.getParentData() instanceof DNAData)) {
+			return null;
+		}
+		F81TD taxDist = new F81TD( this,taxa, observedStates, getEstimateAmbiguityDifferences(), getCountDifferencesIfGapInPair());
+		taxDist.calculateDistances();
+		return taxDist;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "F81 distance";  
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "F81 (Felsenstein, 1981) distance from a character matrix." ;
+	}
+
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+class F81TD extends DNATaxaDistance {
+	DNATaxaDistFromMatrixFreq dnaTDMF;
+	MCharactersDistribution observedStates;
+	
+	public F81TD(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule, taxa, observedStates, estimateAmbiguityDifferences,countDifferencesIfGapInPair);
+		 dnaTDMF = (DNATaxaDistFromMatrixFreq)ownerModule;
+		 this.observedStates = observedStates;
+	}
+	public void calculateDistances(){
+		
+		MesquiteDouble N = new MesquiteDouble();
+		MesquiteDouble D = new MesquiteDouble();
+		double B=1.0;
+		double[] pi = null;
+		if (dnaTDMF.getBaseFreqEntireMatrix()) {
+			pi = dnaTDMF.getPi(observedStates, -1, -1);
+			B = 1.0-pi[0]*pi[0]-pi[1]*pi[1]-pi[2]*pi[2]-pi[3]*pi[3];
+		}
+
+
+		
+		setEstimateAmbiguityDifferences(dnaTDMF.getEstimateAmbiguityDifferences());
+		for (int taxon1=0; taxon1<getNumTaxa(); taxon1++)
+			for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++) {
+				double[][] fxy = calcPairwiseDistance(taxon1, taxon2, N, D);
+				if (D.getValue()>=0.75)  //TODO: check this
+					distances[taxon1][taxon2]= MesquiteDouble.infinite;  
+				else {
+					if (!dnaTDMF.getBaseFreqEntireMatrix()){
+						pi = dnaTDMF.getPi(observedStates, taxon1, taxon2);
+						B = 1.0-pi[0]*pi[0]-pi[1]*pi[1]-pi[2]*pi[2]-pi[3]*pi[3];
+					}
+					distances[taxon1][taxon2]=-B*(Math.log(1.0-(D.getValue()/B)));
+				}
+			}
+		copyDistanceTriangle();
+		logDistancesIfDesired(dnaTDMF.getName());	
+
+	}
+	public String getName() {
+		return dnaTDMF.getName();
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/F84Distance/F84Distance.java b/Source/mesquite/distance/F84Distance/F84Distance.java
new file mode 100644
index 0000000..dd00c94
--- /dev/null
+++ b/Source/mesquite/distance/F84Distance/F84Distance.java
@@ -0,0 +1,156 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.F84Distance;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class F84Distance extends DNATaxaDistFromMatrixFreq {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }	 
+
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in "+ getName());
+			return null;
+		}
+		if (!(observedStates.getParentData() instanceof DNAData)) {
+			return null;
+		}
+		F84TD taxDist = new F84TD( this,taxa, observedStates, getEstimateAmbiguityDifferences(), getCountDifferencesIfGapInPair());
+		taxDist.calculateDistances();
+		return taxDist;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "F84 distance";  
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "F84 (Felsenstein, 1984) distance from a DNA matrix." ;
+	}
+
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+class F84TD extends DNATaxaDistance {
+	DNATaxaDistFromMatrixFreq dnaTDMF;
+	MCharactersDistribution observedStates;
+	MesquiteModule ownerModule;
+	
+	public F84TD(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule, taxa, observedStates, estimateAmbiguityDifferences, countDifferencesIfGapInPair);
+		 dnaTDMF = (DNATaxaDistFromMatrixFreq)ownerModule;
+		 this.observedStates = observedStates;
+	}
+	public void calculateDistances(){
+		double[] pi = null;
+		MesquiteDouble N = new MesquiteDouble();
+		MesquiteDouble D = new MesquiteDouble();
+		double B=1.0;
+		double A = 1.0;
+		double C = 1.0;
+		if (dnaTDMF.getBaseFreqEntireMatrix()) {
+			pi = dnaTDMF.getPi(observedStates, -1, -1);			
+			A = pi[1]*pi[3]/(pi[1]+pi[3])+pi[0]*pi[2]/(pi[0]+pi[2]);
+			B = pi[1]*pi[3]+pi[0]*pi[2];
+			C = (pi[1]+pi[3])*(pi[0]+pi[2]);
+		}
+
+//MesquiteTimer timer = new MesquiteTimer();
+//timer.start();
+		
+		setEstimateAmbiguityDifferences(dnaTDMF.getEstimateAmbiguityDifferences());
+	//	MesquiteTimer timer = new MesquiteTimer();
+	//	timer.start();
+		int progMax = getNumTaxa()*getNumTaxa()/2;
+		ProgressIndicator progIndicator = new ProgressIndicator(dnaTDMF.getProject(),getName(), "Calculating distance matrix",progMax , true);
+		if (progIndicator!=null){
+			progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+			progIndicator.setOfferContinueMessageString("Are you sure you want to stop the alignment?");
+			progIndicator.start();
+		}
+		int count=0;
+		for (int taxon1=0; taxon1<getNumTaxa(); taxon1++)
+			for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++) {
+				double[][] fxy = calcPairwiseDistance(taxon1, taxon2, N, D);
+				if (D.getValue()>=0.75)  //TODO: check this
+					distances[taxon1][taxon2]= MesquiteDouble.infinite;  
+				else {
+					double P = fxy[0][2] + fxy[2][0] + fxy[1][3] + fxy[3][1];
+					double Q = D.getValue() - P;
+					if (!dnaTDMF.getBaseFreqEntireMatrix()) {
+						pi = dnaTDMF.getPi(observedStates, taxon1, taxon2);
+						A = pi[1]*pi[3]/(pi[1]+pi[3])+pi[0]*pi[2]/(pi[0]+pi[2]);
+						B = pi[1]*pi[3]+pi[0]*pi[2];
+						C = (pi[1]+pi[3])*(pi[0]+pi[2]);
+					}
+					distances[taxon1][taxon2]=-2*A*Math.log(1.0-P/(2*A)-(A-B)*Q/(2*A*C)) + 2*(A-B-C)*Math.log(1-Q/(2*C));
+				}
+				if (progIndicator != null) {
+					if (progIndicator.isAborted()) {
+							progIndicator.goAway();
+							return;
+					}
+					count++;
+					progIndicator.setCurrentValue(count);
+				}
+
+			}
+		if (progIndicator != null)
+			progIndicator.goAway();
+
+		copyDistanceTriangle();
+
+		logDistancesIfDesired(dnaTDMF.getName());	
+	}
+	public String getName() {
+		return dnaTDMF.getName();
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/JukesCantorDistance/JukesCantorDistance.java b/Source/mesquite/distance/JukesCantorDistance/JukesCantorDistance.java
new file mode 100644
index 0000000..437fce3
--- /dev/null
+++ b/Source/mesquite/distance/JukesCantorDistance/JukesCantorDistance.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.JukesCantorDistance;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class JukesCantorDistance extends DNATaxaDistFromMatrix {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }	 
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in "+ getName());
+			return null;
+		}
+		if (!(observedStates.getParentData() instanceof DNAData)) {
+			return null;
+		}
+		JukesCantorTD simpleTD = new JukesCantorTD( this,taxa, observedStates, getEstimateAmbiguityDifferences(), getCountDifferencesIfGapInPair());
+		return simpleTD;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Jukes Cantor distance";  
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Jukes Cantor distance from a DNA matrix." ;
+	}
+
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+class JukesCantorTD extends DNATaxaDistance {
+
+	public JukesCantorTD(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule, taxa, observedStates, estimateAmbiguityDifferences, countDifferencesIfGapInPair);
+		MesquiteDouble N = new MesquiteDouble();
+		MesquiteDouble D = new MesquiteDouble();
+
+		setEstimateAmbiguityDifferences(((DNATaxaDistFromMatrix)ownerModule).getEstimateAmbiguityDifferences());
+		for (int taxon1=0; taxon1<getNumTaxa(); taxon1++)
+			for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++) {
+				double[][] fxy = calcPairwiseDistance(taxon1, taxon2, N, D);
+				if (D.getValue()>=0.75)
+					distances[taxon1][taxon2]= MesquiteDouble.infinite;
+				else
+					distances[taxon1][taxon2]=-3.0/4.0*(Math.log(1-(D.getValue()*4.0/3.0)));
+			}
+		copyDistanceTriangle();
+
+		logDistancesIfDesired(ownerModule.getName());	}
+	public String getName() {
+		return "Jukes Cantor distance";
+		}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/K2PDistance/K2PDistance.java b/Source/mesquite/distance/K2PDistance/K2PDistance.java
new file mode 100644
index 0000000..d4b6b81
--- /dev/null
+++ b/Source/mesquite/distance/K2PDistance/K2PDistance.java
@@ -0,0 +1,110 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.K2PDistance;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class K2PDistance extends DNATaxaDistFromMatrixFreq {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }	 
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in "+ getName());
+			return null;
+		}
+		if (!(observedStates.getParentData() instanceof DNAData)) {
+			return null;
+		}
+		K2PTD taxDist = new K2PTD( this,taxa, observedStates, getEstimateAmbiguityDifferences(), getCountDifferencesIfGapInPair());
+		return taxDist;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "K2P distance";  
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "K2P (Kimura 2-parameter) distance from a character matrix." ;
+	}
+
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+class K2PTD extends DNATaxaDistance {
+
+
+	public K2PTD(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule, taxa, observedStates, estimateAmbiguityDifferences, countDifferencesIfGapInPair);
+		DNATaxaDistFromMatrixFreq dnaTDMF = (DNATaxaDistFromMatrixFreq)ownerModule;
+		MesquiteDouble N = new MesquiteDouble();
+		MesquiteDouble D = new MesquiteDouble();
+
+		setEstimateAmbiguityDifferences(((DNATaxaDistFromMatrix)ownerModule).getEstimateAmbiguityDifferences());
+		for (int taxon1=0; taxon1<getNumTaxa(); taxon1++) {
+			for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++) {
+				double[][] fxy = calcPairwiseDistance(taxon1, taxon2, N, D);
+				if (D.getValue()>=0.75)  //TODO: check this
+					distances[taxon1][taxon2]= MesquiteDouble.infinite;
+				else {
+					double P = fxy[0][2] + fxy[2][0] + fxy[1][3] + fxy[3][1];
+					double Q = D.getValue() - P;
+					distances[taxon1][taxon2]=0.5*(Math.log(1/(1-2*P-Q)))+0.25*(Math.log(1/(1-2*Q)));
+				}
+			}
+		}
+		copyDistanceTriangle();
+	}
+
+		/*.................................................................................................................*/
+		public String getName() {
+			return "Kimura 2-parameter (K2P) distance";  
+		}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/NodeCountDist/NodeCountDist.java b/Source/mesquite/distance/NodeCountDist/NodeCountDist.java
new file mode 100644
index 0000000..0e88056
--- /dev/null
+++ b/Source/mesquite/distance/NodeCountDist/NodeCountDist.java
@@ -0,0 +1,181 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.distance.NodeCountDist;
+
+import mesquite.distance.lib.IncTaxaDistanceSource;
+import mesquite.distance.lib.TaxaDistance;
+import mesquite.lib.*;
+import mesquite.lib.duties.TreeSource;
+
+public class NodeCountDist extends IncTaxaDistanceSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	/*.................................................................................................................*/
+   TreeSource treeSourceTask;
+    Taxa taxa;
+    long currentTree = 0;
+    /*.................................................................................................................*/
+    public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+        treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for node count distance for " + getEmployer().getName()  + ")");
+        if (treeSourceTask == null) {
+            return sorry(getName() + " couldn't start because no source of a tree was obtained.");
+        }
+        return true;
+    }
+    /*.................................................................................................................*/
+    public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+        if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+            super.employeeParametersChanged(employee, source, notification);
+    }
+
+    /** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+    happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+    public void initialize(Taxa taxa){
+        this.taxa = taxa;
+        treeSourceTask.initialize(taxa);
+    }
+
+    public TaxaDistance getTaxaDistance(Taxa taxa){
+        Tree tree = treeSourceTask.getTree(taxa, (int)currentTree);
+        if (tree == null) {
+            MesquiteMessage.warnProgrammer("No tree in NodeCountDist " + currentTree + "  source " + treeSourceTask.getName());
+            return null;
+        }
+        return new NodeCountTD( taxa, tree);
+    }
+
+    // according to Wayne, this should not cause parametersChanged to fire
+    public void setCurrent(long i) {
+        currentTree = i;
+    }
+
+    public long getCurrent() {
+        return currentTree;
+    }
+
+    public String getItemTypeName() {
+        return "Tree";
+    }
+
+    public long getMin() {
+        return 0;
+    }
+
+    public long getMax() {
+        long n = treeSourceTask.getNumberOfTrees(taxa)-1;
+        return n;
+    }
+
+    // these two support conversion between 1-based and 0-based counting
+    public long toInternal(long i) {
+        return i-1;
+    }
+
+    public long toExternal(long i) {
+        return i+1;
+    }
+    
+    /*.................................................................................................................*/
+    public String getName() {
+        return "Node Count (Speciation Patristic) Distances implied by Tree";  
+    }
+     
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+   public String getParameters() {
+        return "Node Count Distances among taxa implied by tree from : " + treeSourceTask.getName();
+    }
+    /*.................................................................................................................*/
+ 
+    /** returns an explanation of what the module does.*/
+    public String getExplanation() {
+        return "Distances among taxa implied by counting nodes along branches of tree from one taxon to another (Speciation Patristic distances)." ;
+    }
+     
+    public boolean isPrerelease(){
+        return false;
+    }
+    /*.................................................................................................................*/
+    public boolean showCitation(){
+        return true;
+    }
+    /*.................................................................................................................*/
+    public String getAuthors(){
+    		return "Peter Midford and Wayne Maddison";
+    }
+
+
+    /** This is similar to Patristic distance, except it counts the number of nodes between the nodes.  It does
+     * this by counting branches and subtracting one, except if node1==node2 */
+    class NodeCountTD extends TaxaDistance {
+        double[][] distances;
+        int numTaxa;
+        public NodeCountTD(Taxa taxa, Tree tree){
+            super(taxa);
+            numTaxa = taxa.getNumTaxa();
+            distances= new double[numTaxa][numTaxa];
+            Double2DArray.deassignArray(distances);
+            int root = tree.getRoot();
+            for (int taxon1=0; taxon1<numTaxa; taxon1++) {
+                int node1 = tree.nodeOfTaxonNumber(taxon1);
+                if (tree.nodeExists(node1)){
+                    for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+                        double sumPath =0;
+                        int node2 = tree.nodeOfTaxonNumber(taxon2);
+                        if (tree.nodeExists(node2)){
+                            int mrca = tree.mrca(node1, node2);
+                            int node = node1;
+                            while (node!=mrca && (node != root) && tree.nodeExists(node)){
+                                sumPath++;
+                                node = tree.motherOfNode(node);
+                            }
+                            node = node2;
+                            while (node!=mrca && node != root && tree.nodeExists(node)){
+                                sumPath++;
+                                node = tree.motherOfNode(node);
+                            }
+                            if (sumPath >0) 
+                            	sumPath--;
+                            distances[taxon1][taxon2]=sumPath;
+                        }
+                    }
+                }
+            }
+        }
+        
+        public double getDistance(int taxon1, int taxon2){
+            if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+                return distances[taxon1][taxon2];
+            else
+                return MesquiteDouble.unassigned;
+            
+        }
+        public double[][] getMatrix(){
+            return distances;
+        }
+        public boolean isSymmetrical(){
+            return true;
+        }
+        
+    }
+
+}
diff --git a/Source/mesquite/distance/Notes/Distance Notes b/Source/mesquite/distance/Notes/Distance Notes
new file mode 100644
index 0000000..abf5ec5
--- /dev/null
+++ b/Source/mesquite/distance/Notes/Distance Notes	
@@ -0,0 +1,12 @@
+Mesquite.distance notes
+-----------------------------
+
+fix so distanceTask compatibility with current matrix
+
+==========
+
+post 1.07:
+Taxon Pairs chart:
+	build TaxonPairs universal selection system, TaxonPair[] attached to TaxaBlock, etc.
+	
+Distances To Log	
\ No newline at end of file
diff --git a/Source/mesquite/distance/PDistance/PDistance.java b/Source/mesquite/distance/PDistance/PDistance.java
new file mode 100644
index 0000000..16aa370
--- /dev/null
+++ b/Source/mesquite/distance/PDistance/PDistance.java
@@ -0,0 +1,187 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.PDistance;
+/*~~  */
+
+
+import java.awt.Checkbox;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.DNAData;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class PDistance extends DNATaxaDistFromMatrix {
+	MesquiteBoolean transversionsOnly = new MesquiteBoolean(false);
+	MesquiteBoolean transitionsOnly = new MesquiteBoolean(false);
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addCheckMenuItemToSubmenu(null, distParamSubmenu, "Transversions Only", MesquiteModule.makeCommand("toggleTransversionsOnly", this), transversionsOnly);
+		addCheckMenuItemToSubmenu(null, distParamSubmenu, "Transitions Only", MesquiteModule.makeCommand("toggleTransitionsOnly", this), transitionsOnly);
+		return true;
+	}	 
+
+	public boolean optionsAdded() {
+		return true;
+	}
+	RadioButtons radios;
+	public void addOptions(ExtensibleDialog dialog) {
+		super.addOptions(dialog);
+		String[] labels =  {"all changes", "transversions only", "transitions only"};
+		int defaultValue= 0;
+		if (transversionsOnly.getValue())
+			defaultValue = 1;
+		else	if (transitionsOnly.getValue())
+			defaultValue = 2;
+		radios = dialog.addRadioButtons(labels, defaultValue);
+
+	}
+	public void processOptions(ExtensibleDialog dialog) {
+		super.processOptions(dialog);
+		if (radios.getValue()==0) {
+			transversionsOnly.setValue(false);
+			transitionsOnly.setValue(false);
+		}
+		else if (radios.getValue()==1) {
+			transversionsOnly.setValue(true);
+			transitionsOnly.setValue(false);
+		}
+		else if (radios.getValue()==2) {
+			transversionsOnly.setValue(false);
+			transitionsOnly.setValue(true);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot snapshot = new Snapshot();
+		snapshot.addLine("toggleTransversionsOnly  " + transversionsOnly.toOffOnString());
+		snapshot.addLine("toggleTransitionsOnly  " + transitionsOnly.toOffOnString());
+		return snapshot;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether only transversions are counted.", "[on; off]", commandName, "toggleTransversionsOnly")) {
+			transversionsOnly.toggleValue(new Parser().getFirstToken(arguments));
+			if (transversionsOnly.getValue())
+				transitionsOnly.setValue(false);
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether only transitions are counted.", "[on; off]", commandName, "toggleTransitionsOnly")) {
+			transitionsOnly.toggleValue(new Parser().getFirstToken(arguments));
+			if (transitionsOnly.getValue())
+				transversionsOnly.setValue(false);
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean getTransversionsOnly(){
+		return transversionsOnly.getValue();
+	}
+	/*.................................................................................................................*/
+	public boolean getTransitionsOnly(){
+		return transitionsOnly.getValue();
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		String s = super.getParameters();
+		if (getTransversionsOnly())
+			s+= " Transversions only.";
+		if (getTransitionsOnly())
+			s+= " Transitions only.";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in "+ getName());
+			return null;
+		}
+		if (!(observedStates.getParentData() instanceof DNAData)) {
+			return null;
+		}
+		PTD simpleTD = new PTD( this,taxa, observedStates,getEstimateAmbiguityDifferences(), getCountDifferencesIfGapInPair());
+		return simpleTD;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Uncorrected (p) distance (DNA)";  
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Uncorrected (p) distance from a DNA matrix." ;
+	}
+
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+class PTD extends DNATaxaDistance {
+	PDistance PD;
+	public PTD(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule, taxa, observedStates,estimateAmbiguityDifferences, countDifferencesIfGapInPair);
+		PD = (PDistance)ownerModule;
+		MesquiteDouble N = new MesquiteDouble();
+		MesquiteDouble D = new MesquiteDouble();
+		setEstimateAmbiguityDifferences(((DNATaxaDistFromMatrix)ownerModule).getEstimateAmbiguityDifferences());
+
+
+		for (int taxon1=0; taxon1<getNumTaxa(); taxon1++) {
+			for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++) {
+				double[][] fxy = calcPairwiseDistance(taxon1, taxon2, N, D);
+				if (PD.getTransversionsOnly())
+					distances[taxon1][taxon2]= fxy[0][1] + fxy[1][0] + fxy[0][3] + fxy[3][0] + fxy[1][2] + fxy[2][1] + fxy[2][3] + fxy[3][2];  //trasnversion
+				else if (PD.getTransitionsOnly())
+					distances[taxon1][taxon2]= fxy[0][2] + fxy[2][0] + fxy[1][3] + fxy[3][1];  //transitions
+				else
+					distances[taxon1][taxon2]= D.getValue();
+			}
+		}
+		copyDistanceTriangle();
+
+		logDistancesIfDesired(ownerModule.getName());	}
+	
+	public String getName() {
+		return PD.getName();
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/PatristicDistance/PatristicDistance.java b/Source/mesquite/distance/PatristicDistance/PatristicDistance.java
new file mode 100644
index 0000000..8cf10c7
--- /dev/null
+++ b/Source/mesquite/distance/PatristicDistance/PatristicDistance.java
@@ -0,0 +1,160 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.PatristicDistance;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different tree */
+public class PatristicDistance extends IncTaxaDistanceSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	TreeSource treeSourceTask;
+	Taxa taxa;
+	long currentTree = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for patristic distance for " + getEmployer().getName()  + ")");
+ 		if (treeSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of a tree was obtained.");
+ 		}
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+ 			super.employeeParametersChanged(employee, source, notification);
+	}
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		this.taxa = taxa;
+   		treeSourceTask.initialize(taxa);
+   	}
+
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+		Tree tree = treeSourceTask.getTree(taxa, (int)currentTree);
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("No tree in Patristic Distance " + currentTree + "  source " + treeSourceTask.getName());
+			return null;
+		}
+		return new PatristicTD( taxa, tree);
+	}
+	/*.................................................................................................................*/
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		currentTree = i;
+ 	}
+ 	public long getCurrent(){
+ 		return currentTree;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Tree";
+ 	}
+ 	public long getMin(){
+		return 0;
+ 	}
+ 	public long getMax(){
+ 		long n = treeSourceTask.getNumberOfTrees(taxa)-1;
+		return n;
+ 	}
+ 	public long toInternal(long i){
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Patristic Distances implied by Tree";  
+   	 }
+   	 
+ 	public String getParameters() {
+ 		return "Distances among taxa implied by tree from : " + treeSourceTask.getName();
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Distances among taxa implied by path-length distance along branches of tree from one taxon to another (Patristic distances).  Unassigned branches are treated as of length 1.0." ;
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
+class PatristicTD extends TaxaDistance {
+	double[][] distances;
+	int numTaxa;
+	public PatristicTD(Taxa taxa, Tree tree){
+		super(taxa);
+		numTaxa = taxa.getNumTaxa();
+		distances= new double[numTaxa][numTaxa];
+		Double2DArray.deassignArray(distances);
+		int root = tree.getRoot();
+		for (int taxon1=0; taxon1<numTaxa; taxon1++) {
+			int node1 = tree.nodeOfTaxonNumber(taxon1);
+			if (tree.nodeExists(node1)){
+				for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+					double sumPath =0;
+					int node2 = tree.nodeOfTaxonNumber(taxon2);
+					if (tree.nodeExists(node2)){
+						int mrca = tree.mrca(node1, node2);
+						int node = node1;
+						while (node!=mrca && (node != root) && tree.nodeExists(node)){
+							sumPath += tree.getBranchLength(node, 1.0);
+							node = tree.motherOfNode(node);
+						}
+						node = node2;
+						while (node!=mrca && node != root && tree.nodeExists(node)){
+							sumPath += tree.getBranchLength(node, 1.0);
+							node = tree.motherOfNode(node);
+						}
+						distances[taxon1][taxon2]=sumPath;
+					}
+				}
+			}
+		}
+	}
+	public double getDistance(int taxon1, int taxon2){
+		if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+			return distances[taxon1][taxon2];
+		else
+			return MesquiteDouble.unassigned;
+		
+	}
+	public double[][] getMatrix(){
+		return distances;
+	}
+	public boolean isSymmetrical(){
+		return true;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/SharedHistoryDistance/SharedHistoryDistance.java b/Source/mesquite/distance/SharedHistoryDistance/SharedHistoryDistance.java
new file mode 100644
index 0000000..2d508b8
--- /dev/null
+++ b/Source/mesquite/distance/SharedHistoryDistance/SharedHistoryDistance.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.SharedHistoryDistance;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+public class SharedHistoryDistance extends IncTaxaDistanceSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	TreeSource treeSourceTask;
+	Taxa taxa;
+	long currentTree = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+	 	treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for Shared History distance for " + getEmployer().getName()  + ")");
+	 	if (treeSourceTask == null) {
+	 		return sorry(getName() + " couldn't start because no source of a tree was obtained.");
+	 	}
+	 	return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+	 	if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+	 		super.employeeParametersChanged(employee, source, notification);
+	}
+	  	 
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	  happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		this.taxa = taxa;
+	   		treeSourceTask.initialize(taxa);
+	}
+
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+		Tree tree = treeSourceTask.getTree(taxa, (int)currentTree);
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("No tree in Shared History Distance " + currentTree + "  source " + treeSourceTask.getName());
+			return null;
+		}
+		return new SharedHistoryTD( taxa, tree);
+	}
+
+	/*.................................................................................................................*/
+	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+	 	currentTree = i;
+	}
+	public long getCurrent(){
+	 	return currentTree;
+	}
+	public String getItemTypeName(){
+	 	return "Tree";
+	}
+	public long getMin(){
+		return 0;
+	}
+	public long getMax(){
+	 	long n = treeSourceTask.getNumberOfTrees(taxa)-1;
+		return n;
+	}
+	public long toInternal(long i){
+	 	return i-1;
+	}
+	public long toExternal(long i){ //return whether 0 based or 1 based counting
+		return i+1;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Shared History Distances (Covariance matrix) from Tree";  
+	}
+	   	 
+	public String getParameters() {
+	 	return "Shared History Distances among taxa implied by tree from : " + treeSourceTask.getName();
+	}
+	/*.................................................................................................................*/
+	   	 
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Distances among taxa implied by length of shared history (distance from root to most recent ancestor). This is the most common Covariance/Variance matrix used in GLS methods. Unassigned branches are treated as of length 1.0." ;
+	}
+	/*.................................................................................................................*/
+    public String getAuthors(){
+    		return "Peter Midford and Wayne Maddison";
+    }
+ 
+    public boolean isSubstantive(){
+    		return true;
+    }
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+    /** This is returns the amount of shared history between two nodes.  It is just the distance from the root to
+     * the nodes' most recent common ancestor. */
+	class SharedHistoryTD extends TaxaDistance {
+		double[][] distances;
+		int numTaxa;
+		public SharedHistoryTD(Taxa taxa, Tree tree){
+			super(taxa);
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			Double2DArray.deassignArray(distances);
+			int root = tree.getRoot();
+			for (int taxon1=0; taxon1<numTaxa; taxon1++) {
+				int node1 = tree.nodeOfTaxonNumber(taxon1);
+				if (tree.nodeExists(node1)){
+					for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+						int node2 = tree.nodeOfTaxonNumber(taxon2);
+						if (tree.nodeExists(node2)){
+							int mrca = tree.mrca(node1, node2);
+							int node = mrca;
+							double sumPath = 0;
+							while (node != root && tree.nodeExists(node)){
+								sumPath += tree.getBranchLength(node, 1.0);
+								node = tree.motherOfNode(node);
+							}
+							distances[taxon1][taxon2] = sumPath;
+						}
+					}
+				}
+			}
+		}
+
+		public double getDistance(int taxon1, int taxon2){
+			if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+				return distances[taxon1][taxon2];
+			else
+				return MesquiteDouble.unassigned;
+			
+		}
+		public double[][] getMatrix(){
+			return distances;
+		}
+		public boolean isSymmetrical(){
+			return true;
+		}
+	
+	}
+	
+
+}
diff --git a/Source/mesquite/distance/SharedProportionalDistance/SharedProportionalDistance.java b/Source/mesquite/distance/SharedProportionalDistance/SharedProportionalDistance.java
new file mode 100644
index 0000000..d16641e
--- /dev/null
+++ b/Source/mesquite/distance/SharedProportionalDistance/SharedProportionalDistance.java
@@ -0,0 +1,186 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.SharedProportionalDistance;
+
+import mesquite.lib.CommandRecord;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.Incrementable;
+import mesquite.lib.Taxa;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+public class SharedProportionalDistance extends IncTaxaDistanceSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	TreeSource treeSourceTask;
+	Taxa taxa;
+	long currentTree = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for Proportion Shared distance for " + getEmployer().getName()  + ")");
+		if (treeSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of a tree was obtained.");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+			super.employeeParametersChanged(employee, source, notification);
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	  happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		this.taxa = taxa;
+		treeSourceTask.initialize(taxa);
+	}
+
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+		Tree tree = treeSourceTask.getTree(taxa, (int)currentTree);
+		if (tree == null) {
+			MesquiteMessage.warnProgrammer("No tree in Proportion Shared Distance " + currentTree + "  source " + treeSourceTask.getName());
+			return null;
+		}
+		return new SharedProportionTD( taxa, tree);
+	}
+
+	/*.................................................................................................................*/
+	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+		currentTree = i;
+	}
+	public long getCurrent(){
+		return currentTree;
+	}
+	public String getItemTypeName(){
+		return "Tree";
+	}
+	public long getMin(){
+		return 0;
+	}
+	public long getMax(){
+		long n = treeSourceTask.getNumberOfTrees(taxa)-1;
+		return n;
+	}
+	public long toInternal(long i){
+		return i-1;
+	}
+	public long toExternal(long i){ //return whether 0 based or 1 based counting
+		return i+1;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Shared Proportion Distances implied by Tree";  
+	}
+
+	public String getParameters() {
+		return "Distances among taxa implied by tree from : " + treeSourceTask.getName();
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Distances among taxa implied by proportion of total branchlength (root to tip) that is shared (Shared Proportion distances).  Unassigned branches are treated as of length 1.0." ;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+	public String getAuthors(){
+		return "Peter Midford and Wayne Maddison";
+	}
+
+
+	/** This calculates the proportion of the history of two nodes is shared.  It is calculated as the shared history
+	 * distance divided by the average distance of the two nodes from the root.  This works fine when comparing tips,
+	 * but could produce numbers greater than one if one node is ancestral to the other.
+	 */ 
+	class SharedProportionTD extends TaxaDistance {
+		double[][] distances;
+		int numTaxa;
+		public SharedProportionTD(Taxa taxa, Tree tree){
+			super(taxa);
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			Double2DArray.deassignArray(distances);
+			int root = tree.getRoot();
+			for (int taxon1=0; taxon1<numTaxa; taxon1++) {
+				int node1 = tree.nodeOfTaxonNumber(taxon1);
+				if (tree.nodeExists(node1)){
+					int node = node1;
+					double node1Height = 0;
+					while (node != root && tree.nodeExists(node)){
+						node1Height += tree.getBranchLength(node, 1.0);
+						node = tree.motherOfNode(node);
+					}
+					for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+						int node2 = tree.nodeOfTaxonNumber(taxon2);
+						if (tree.nodeExists(node2)){
+							node = node2;
+							double node2Height = 0;
+							while (node != root && tree.nodeExists(node)){
+								node2Height += tree.getBranchLength(node, 1.0);
+								node = tree.motherOfNode(node);
+							}
+							int mrca = tree.mrca(node1, node2);
+							node = mrca;
+							double ancestorHeight = 0;
+							while (node != root && tree.nodeExists(node)){
+								ancestorHeight += tree.getBranchLength(node, 1.0);
+								node = tree.motherOfNode(node);
+							}
+							distances[taxon1][taxon2]=(2*ancestorHeight)/(node1Height+node2Height);
+						}
+					}
+				}
+			}
+		}
+		public double getDistance(int taxon1, int taxon2){
+			if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+				return distances[taxon1][taxon2];
+			else
+				return MesquiteDouble.unassigned;
+		}
+
+		public double[][] getMatrix(){
+			return distances;
+		}
+
+		public boolean isSymmetrical(){
+			return true;
+		}
+
+
+	}
+
+}
diff --git a/Source/mesquite/distance/ShowDistance/ShowDistance.java b/Source/mesquite/distance/ShowDistance/ShowDistance.java
new file mode 100644
index 0000000..1bd1034
--- /dev/null
+++ b/Source/mesquite/distance/ShowDistance/ShowDistance.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.ShowDistance;
+
+import mesquite.distance.lib.TaxaDistance;
+import mesquite.distance.lib.TaxaDistanceSource;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteTrunk;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.MesquiteTable;
+
+public class ShowDistance extends DataWindowAssistantA {
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaDistanceSource.class, getName() + "  needs a source of distances.",
+		"The source of distances can be selected initially");
+	}
+	TaxaDistanceSource distanceTask;
+	CharacterData data;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		distanceTask = (TaxaDistanceSource)hireNamedEmployee(TaxaDistanceSource.class, "#TaxaDistFromMatrixSrc");
+ 		if (distanceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of distances was obtained.");
+ 		}
+ 		
+  		return true;
+  	 }
+
+	 public void employeeQuit(MesquiteModule m){
+	  	 	iQuit();
+	  	 }
+
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Writes distance matrix to log.";
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	public String getName() {
+		return "Show Distance Matrix";
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+
+	public void setTableAndData(MesquiteTable table, CharacterData data) {
+		if (data==null || distanceTask==null) 
+			return;
+   		distanceTask.initialize(data.getTaxa());
+ 		TaxaDistance dist = distanceTask.getTaxaDistance(data.getTaxa());
+		if (dist == null) {
+			logln("\n\nNO DISTANCE MATRIX OBTAINED");
+			return;
+		}
+		logln("\n\n=== Distance matrix for " + dist.getName() + " ===");
+
+		dist.distancesToLog();
+
+	}
+
+
+}
diff --git a/Source/mesquite/distance/SingleLinkage/SingleLinkage.java b/Source/mesquite/distance/SingleLinkage/SingleLinkage.java
new file mode 100644
index 0000000..d8261f4
--- /dev/null
+++ b/Source/mesquite/distance/SingleLinkage/SingleLinkage.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.SingleLinkage;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+//eventually have DistanceTree as treeblock filler, which hires TreeClusterer and TaxaDistanceSource
+public class SingleLinkage extends TreeClusterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+	/*.................................................................................................................*/
+   	public double getDistanceBetweenClusters(double[][] distanceMatrix, int[] clusterI, int[] clusterJ){
+   		if (clusterI == null || clusterJ == null || distanceMatrix == null)
+   			return MesquiteDouble.unassigned;
+   		double d = MesquiteDouble.unassigned;
+   		for (int i=0; i<clusterI.length; i++)
+   			for (int j=0; j<clusterJ.length; j++) {
+   				if (distanceMatrix != null && clusterI[i] < distanceMatrix.length && clusterJ[j]< distanceMatrix[clusterI[i]].length){
+   					double dist = distanceMatrix[clusterI[i]][clusterJ[j]];
+				if (MesquiteDouble.lessThan(dist, d, 0))
+					d = dist;
+   				}
+   			}
+   					
+   		return d;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Single Linkage";
+   	 }
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies trees obtained from Single Linkage clustering.";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/distance/TaxaDistFromMatrixSrc/TaxaDistFromMatrixSrc.java b/Source/mesquite/distance/TaxaDistFromMatrixSrc/TaxaDistFromMatrixSrc.java
new file mode 100644
index 0000000..6bf868c
--- /dev/null
+++ b/Source/mesquite/distance/TaxaDistFromMatrixSrc/TaxaDistFromMatrixSrc.java
@@ -0,0 +1,227 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.TaxaDistFromMatrixSrc;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class TaxaDistFromMatrixSrc extends IncTaxaDistanceSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"The source of matrices is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(MatrixSourceCoordObed.class, getName() + "  needs a source of matrices.",
+		"The source of matrices is arranged initially");
+		EmployeeNeed e3 = registerEmployeeNeed(TaxaDistFromMatrix.class, getName() + "  needs a method to calculate distances.",
+		"The method to calculate distances can be selected initially or in the Distance Calculator submenu");
+	}
+	MesquiteNumber num;
+	MatrixSourceCoord matrixSourceTask;
+	MatrixSourceCoordObed matrixSourceObedTask;
+	TaxaDistFromMatrix distanceTask;
+	Taxa currentTaxa;
+	boolean matrixSet = false;
+	int currentMatrix = 0;
+	MCharactersDistribution observedStates =null;
+	MesquiteString distanceTaskName;
+	MesquiteCommand mesqC;
+	MesquiteSubmenuSpec mss;
+	Class currentStateClass = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		distanceTask = (TaxaDistFromMatrix)hireEmployee(TaxaDistFromMatrix.class, "Distance calculator");
+		if (distanceTask == null) {
+			return sorry(getName() + " couldn't start because no distance calculator was obtained.");
+		}
+		mesqC = makeCommand("setDistanceTask",  this);
+		distanceTask.setHiringCommand(mesqC);
+		distanceTaskName = new MesquiteString(distanceTask.getName());
+		if (numModulesAvailable(TaxaDistFromMatrix.class)>1){
+			mss = addSubmenu(null, "Distance Calculator", mesqC, TaxaDistFromMatrix.class);
+			mss.setSelected(distanceTaskName);
+		}
+		Class stateClass = distanceTask.getRequiredStateClass();
+		if (stateClass == null){
+			if (getHiredAs() == IncTaxaDistanceSource.class)
+				matrixSourceObedTask = (MatrixSourceCoordObed)hireEmployee(MatrixSourceCoordObed.class, "Source of matrices (for " + getName() + ")");
+			else
+				matrixSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of matrices (for " + getName() + ")");
+		}
+		else {
+			if (getHiredAs() == IncTaxaDistanceSource.class)
+				matrixSourceObedTask = (MatrixSourceCoordObed)hireCompatibleEmployee(MatrixSourceCoordObed.class, stateClass, "Source of matrices (for " + getName() + ")");
+			else
+				matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, stateClass, "Source of matrices (for " + getName() + ")");
+		}
+
+
+		if (matrixSourceTask == null && matrixSourceObedTask == null) {
+			return sorry(getName() + " couldn't start because no source of a character matrix was obtained.");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (matrixSourceTask != null)
+			temp.addLine( "getMatrixSource " , matrixSourceTask);
+		else if (matrixSourceObedTask != null)
+			temp.addLine( "getMatrixSource " , matrixSourceObedTask);
+		temp.addLine( "setDistanceTask " , distanceTask);
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the module supplying matrices", null, commandName, "getMatrixSource")) {
+			if (matrixSourceTask !=null)
+				return matrixSourceTask;
+			return matrixSourceObedTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module doing the distance calculation from a matrix", null, commandName, "setDistanceTask")) {
+			Class currentStateClass = null;
+			if (observedStates!=null)
+				currentStateClass = observedStates.getStateClass();
+			TaxaDistFromMatrix temp=  (TaxaDistFromMatrix)replaceCompatibleEmployee(TaxaDistFromMatrix.class, arguments, distanceTask,currentStateClass);
+			if (temp!=null) {
+				distanceTask= temp;
+				distanceTask.setHiringCommand(mesqC);
+				distanceTaskName.setValue(distanceTask.getName());
+
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+			return distanceTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		if (matrixSourceTask!=null)
+			matrixSourceTask.initialize(currentTaxa);
+		else if (matrixSourceObedTask!=null)
+			matrixSourceObedTask.initialize(currentTaxa);
+	}
+
+	public boolean getDistanceOptions() {
+		if (distanceTask==null)
+			return false;
+		return distanceTask.getDistanceOptions();
+	}
+	
+	public TaxaDistance getTaxaDistance(Taxa taxa){
+		if (matrixSourceTask!=null)
+			observedStates =matrixSourceTask.getCurrentMatrix(taxa);
+		else if (matrixSourceObedTask!=null)
+			observedStates =matrixSourceObedTask.getMatrix(taxa, currentMatrix);
+		currentTaxa = taxa;
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in " + getName() + " for taxa " + taxa); 
+			return null;
+		}
+		if (observedStates.getStateClass() !=currentStateClass){
+			currentStateClass = observedStates.getStateClass();
+			mss.setListableFilter(currentStateClass);
+			//mss.setListableFilter(null);
+			resetContainingMenuBar();
+		}
+		return distanceTask.getTaxaDistance(taxa, observedStates);
+	}
+	/*.................................................................................................................*/
+	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+		currentMatrix = (int)i;
+	}
+	public long getCurrent(){
+		return currentMatrix;
+	}
+	public String getItemTypeName(){
+		return "Matrix";
+	}
+	public long getMin(){
+		return 0;
+	}
+	public long getMax(){
+		if (matrixSourceObedTask == null)
+			return 0;
+		return matrixSourceObedTask.getNumberOfMatrices(currentTaxa)-1;
+	}
+	public long toInternal(long i){
+		return i-1;
+	}
+	public long toExternal(long i){ //return whether 0 based or 1 based counting
+		return i+1;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates=null;
+		super.employeeParametersChanged(this, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Distances from Character Matrix";  
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters() {
+		String s ="Distances: " + distanceTask.getName()+ " -- Matrix: " ;  
+		if (matrixSourceTask !=null)
+			s += matrixSourceTask.getParameters();
+		else if (matrixSourceObedTask !=null)
+			s += matrixSourceObedTask.getParameters();
+		return s;
+	}
+
+	public String getParameters() {
+		String s = "";
+		if (distanceTask !=null)
+			s += "Distances calculated by " + distanceTask.getNameAndParameters();
+		if (matrixSourceTask !=null)
+			s += " Matrix source: " + matrixSourceTask.getParameters();
+		else if (matrixSourceObedTask !=null)
+			s += " Matrix source: " + matrixSourceObedTask.getParameters();
+		return s;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Distances calculated from a character matrix." ;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/distance/TaxonDistance/TaxonDistance.java b/Source/mesquite/distance/TaxonDistance/TaxonDistance.java
new file mode 100644
index 0000000..8648b2c
--- /dev/null
+++ b/Source/mesquite/distance/TaxonDistance/TaxonDistance.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.TaxonDistance;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+public class TaxonDistance extends NumberFor2Taxa {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaDistanceSource.class, getName() + "  needs a method to calculate distance between taxa.",
+		"The method to calculate distance can be selected initially or in the Source of Distance submenu");
+	}
+	MesquiteNumber nt;
+	TaxaDistanceSource distanceTask;
+	TaxaDistance taxaDistance;
+	MesquiteString distanceTaskName;
+	MesquiteCommand atC;
+	MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		distanceTask = (TaxaDistanceSource)hireEmployee(TaxaDistanceSource.class, "Source of distance");
+		if (distanceTask == null) {
+ 			return sorry("Can't start TaxonDistance because no distance source found");
+ 		}
+		nt= new MesquiteNumber();
+		atC = makeCommand("setDistanceSource",  this);
+		distanceTask.setHiringCommand(atC);
+		distanceTaskName = new MesquiteString(distanceTask.getName());
+		if (numModulesAvailable(TaxaDistanceSource.class)>1){
+			mss = addSubmenu(null, "Source of Distance", atC, TaxaDistanceSource.class);
+			mss.setSelected(distanceTaskName);
+		}
+  		return true;
+  	 }
+  	public void employeeQuit(MesquiteModule m){
+  		iQuit();
+  	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine( "setDistanceSource " , distanceTask);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the module supplying distances", "[name of module]", commandName, "setDistanceSource")) {
+    	 		TaxaDistanceSource temp =  (TaxaDistanceSource)replaceEmployee(TaxaDistanceSource.class, arguments, "Source of distances", distanceTask);
+ 			if (temp!=null) {
+	    	 	distanceTask=  temp;
+	    	 	taxaDistance = null;
+		 		distanceTask.setHiringCommand(atC);
+				distanceTaskName = new MesquiteString(distanceTask.getName());
+				if (mss!=null){
+					mss.setSelected(distanceTaskName);
+				}
+				parametersChanged();
+ 			}
+ 			return temp;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+   	public void initialize(Taxon t1, Taxon t2){
+   	}
+   	
+	public void calculateNumber(Taxon t1, Taxon t2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null || t1==null || t2==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = t1.getTaxa();
+		if (taxaDistance==null) //need to recalculate only if change in distance calculator
+			taxaDistance = distanceTask.getTaxaDistance(taxa);
+		if (taxaDistance != null)
+			result.setValue(taxaDistance.getDistance(t1.getTaxa().whichTaxonNumber(t1),t2.getTaxa().whichTaxonNumber(t2)));
+		saveLastResult(result);
+		saveLastResultString(resultString);
+		
+	}
+	
+	
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 		taxaDistance=null; //to force recalculation
+ 			super.employeeParametersChanged(this, source, notification);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameAndParameters() {
+		return distanceTask.getNameAndParameters();
+   	 }
+    		/*.................................................................................................................*/
+    	 public String getParameters() {
+		return "Distance used: " + distanceTask.getName();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Distance between taxa";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Counts the difference between two taxa." ;
+   	 }
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/distance/TaxonPairDistance/TaxonPairDistance.java b/Source/mesquite/distance/TaxonPairDistance/TaxonPairDistance.java
new file mode 100644
index 0000000..f0d8e60
--- /dev/null
+++ b/Source/mesquite/distance/TaxonPairDistance/TaxonPairDistance.java
@@ -0,0 +1,201 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+/*Oliver May 08
+ * Mostly copied from TaxonDistance*/
+package mesquite.distance.TaxonPairDistance;
+
+import mesquite.distance.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/**Supplies a number for a character matrix and a pair of taxa.  Currently, it is just a distance 
+ * calculator for a specific pair of taxa, but could be made abstract for additional uses.*/
+public class TaxonPairDistance extends NumberForMatrix{//NumberForMatrixAndTaxonPair{
+	TaxaDistance taxaDistance;
+	TaxaDistFromMatrix distFromMatrix;
+	MesquiteString distFromMatrixName;
+	MesquiteCommand dtC;
+	MesquiteSubmenuSpec msd;
+	MesquiteInteger pos = new MesquiteInteger(); //For doCommand navigation
+	Taxa taxa;
+	int t1, t2;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if(!MesquiteThread.isScripting()){
+			taxa = getProject().chooseTaxa(containerOfModule(), "Select Taxa");
+			if (taxa == null)
+				return sorry("Could not start Pairwise Taxon Distance because no taxa blocks found");
+			t1 = taxa.userChooseTaxon(containerOfModule(), "Choose Taxon 1").getNumber();
+			t2 = taxa.userChooseTaxon(containerOfModule(), "Choose Taxon 2").getNumber();
+		}
+		addMenuItem("Choose Taxon 1...", makeCommand("chooseTaxon1", this));
+		addMenuItem("Choose Taxon 2...", makeCommand("chooseTaxon2", this));
+
+		//TODO: should hiring be inside a !MesquiteThread.isScripting() conditional to prevent queries on startup?
+		distFromMatrix = (TaxaDistFromMatrix)hireEmployee(TaxaDistFromMatrix.class, "Source of distance");
+		if (distFromMatrix == null)
+			return sorry("Could not start Pairwise Taxon Distance because no distance source found");
+		dtC = makeCommand("setDistanceSource", this);
+		distFromMatrix.setHiringCommand(dtC);
+		distFromMatrixName = new MesquiteString(distFromMatrix.getName());
+		if(numModulesAvailable(TaxaDistFromMatrix.class)>1){
+			msd = addSubmenu(null, "Source of Distance", dtC, TaxaDistFromMatrix.class);
+			msd.setSelected(distFromMatrixName);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.............................................................................*/
+	public void initialize(MCharactersDistribution data){
+		if(data != null){
+			taxa = data.getTaxa();
+			distFromMatrix.initialize(taxa);
+		}
+	}
+	/*.............................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.............................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file){
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxa " + getProject().getTaxaNumber(taxa));
+		temp.addLine("setDistanceSource " , distFromMatrix);
+		temp.addLine("setTaxon1 " + t1);
+		temp.addLine("setTaxon2 " + t2);
+  	 	return temp;
+	}
+	/*.............................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Sets the module supplying distances", "[name of module]", commandName, "setDistanceSource")) {
+	 		TaxaDistFromMatrix temp =  (TaxaDistFromMatrix)replaceEmployee(TaxaDistFromMatrix.class, arguments, "Source of distances", distFromMatrix);
+	 		if (temp!=null) {
+	 			distFromMatrix = temp;
+	 			taxaDistance = null;
+	 			distFromMatrix.setHiringCommand(dtC);
+	 			distFromMatrixName = new MesquiteString(distFromMatrix.getName());
+	 			if (msd!=null){
+	 				msd.setSelected(distFromMatrixName);
+	 			}
+	 			parametersChanged();
+	 		}
+			return temp;
+	 	}
+		else if (checker.compare(this.getClass(), "Sets the block of taxa to use for comparisons", "[taxa number]", commandName, "setTaxa")){
+			int temp = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (temp >= 0 && temp <= getProject().getNumberTaxas())
+				taxa = getProject().getTaxa(temp);
+		}
+		else if (checker.compare(this.getClass(), "Sets first taxon to use for comparison", "[taxon number]", commandName, "setTaxon1")){
+			int temp = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (taxa != null && temp >= 0 && temp <= taxa.getNumTaxa())
+				t1 = temp;
+		}
+		else if (checker.compare(this.getClass(), "Sets second taxon to use for comparison", "[taxon number]", commandName, "setTaxon2")){
+			int temp = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (taxa != null && temp >= 0 && temp <= taxa.getNumTaxa())
+				t2 = temp;
+		}
+		else if (checker.compare(this.getClass(), "Prompts user to choose first taxon for comparison", "[taxon number]", commandName, "chooseTaxon1")){
+			if (taxa != null){
+			int temp = taxa.userChooseTaxon(containerOfModule(), "Choose Taxon 1").getNumber();
+				if (temp >= 0 && temp <= taxa.getNumTaxa()){
+					t1 = temp;
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Prompts user to choose second taxon for comparison", "[taxon number]", commandName, "chooseTaxon2")){
+			if (taxa != null){
+				int temp = taxa.userChooseTaxon(containerOfModule(), "Choose Taxon 2").getNumber();
+				if (temp >= 0 && temp <= taxa.getNumTaxa()){
+					t2 = temp;
+		 			parametersChanged();
+				}
+			}
+		}
+		else return super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.............................................................................*/
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString){
+		if(result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+		if (taxa == null)
+			initialize(data);
+		if(distFromMatrix != null){
+			taxaDistance = distFromMatrix.getTaxaDistance(taxa, data);
+			if (taxaDistance != null){
+				result.setValue(taxaDistance.getDistance(t1, t2));
+				if(resultString != null)
+					resultString.setValue(result.toString());
+			}
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if(employee == distFromMatrix)
+			parametersChanged(notification);
+		taxaDistance=null; //to force recalculation
+		super.employeeParametersChanged(this, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters() {
+		String s = distFromMatrix.getNameAndParameters();
+		if(taxa != null){
+			s += " using " + taxa.getName();
+			s += " comparing " + taxa.getTaxonName(t1) + " and " + taxa.getTaxonName(t2);
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		String s = "";
+		if (distFromMatrix != null){
+			s += "Distances calculated by " + distFromMatrix.getNameAndParameters();
+		}
+		if(taxa != null){
+			s += " using " + taxa.getName();
+			s += " comparing " + taxa.getTaxonName(t1) + " and " + taxa.getTaxonName(t2);
+		}
+		return s;
+  	 }
+ 	/*.............................................................................*/
+ 	public String getName() {
+ 		return "Pairwise Taxon Difference";
+ 	}
+ 	/*.............................................................................*/
+ 	public String getExplanation(){
+ 		return "Calculates distance between a specific pair of taxa based on a character matrix.  Differs from Distance Between Taxa in that" +
+ 				"it performs calculation for only a single pair of taxa.";
+ 	}
+ 	/*.............................................................................*/
+ 	public boolean isPrerelease(){
+ 		return false;
+ 	}
+ 	/*.............................................................................*/
+ 	public boolean requestPrimaryChoice(){
+ 		return false;
+ 	}
+}
+
diff --git a/Source/mesquite/distance/UPGMA/UPGMA.java b/Source/mesquite/distance/UPGMA/UPGMA.java
new file mode 100644
index 0000000..5fb08bd
--- /dev/null
+++ b/Source/mesquite/distance/UPGMA/UPGMA.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.UPGMA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+//eventually have DistanceTree as treeblock filler, which hires TreeClusterer and TaxaDistanceSource
+public class UPGMA extends TreeClusterer {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		//
+   	}
+   	
+   	public double getDistanceBetweenClusters(double[][] distanceMatrix, int[] clusterI, int[] clusterJ){
+   		if (clusterI == null || clusterJ == null || distanceMatrix == null)
+   			return MesquiteDouble.unassigned;
+  		double d = 0;
+   		int count = 0;
+   		for (int i=0; i<clusterI.length; i++)
+   			for (int j=0; j<clusterJ.length; j++) {
+   				double dist = distanceMatrix[clusterI[i]][clusterJ[j]];
+   				if (MesquiteDouble.isCombinable(dist)) {
+   					d += dist;
+   					count++;
+   				}
+   			}
+   					
+   		if (count == 0)
+   			return MesquiteDouble.impossible;
+   		return d/count;
+   	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "UPGMA";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies trees obtained from UPGMA clustering.";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/distance/UncorrectedDistance/UncorrectedDistance.java b/Source/mesquite/distance/UncorrectedDistance/UncorrectedDistance.java
new file mode 100644
index 0000000..9f01bde
--- /dev/null
+++ b/Source/mesquite/distance/UncorrectedDistance/UncorrectedDistance.java
@@ -0,0 +1,152 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.UncorrectedDistance;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public class UncorrectedDistance extends TaxaDistFromMatrix {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 
+	public TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution observedStates){
+		if (observedStates==null) {
+			MesquiteMessage.warnProgrammer("Observed states null in Uncorrected Distance");
+			return null;
+		}
+		SimpleTD simpleTD = new SimpleTD( taxa, observedStates);
+		return simpleTD;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Uncorrected Distance (General)";  
+   	 }
+   	 
+   	 /* if the distance calculator worked for only a certain class of characters, indicate that here.  
+   	 Uncorrected distance can handle several sorts, so this method is not overridden
+   	 
+	public Class getRequiredStateClass(){
+		return DNAState.class;
+	}
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Uncorrected distance from a character matrix." ;
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
+class SimpleTD extends TaxaDistance {
+	double[][] distances;
+	int numTaxa;
+	
+	public SimpleTD(Taxa taxa, MCharactersDistribution observedStates){
+		super(taxa);
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+			
+		if (observedStates instanceof MContinuousDistribution){
+			MContinuousDistribution contStates = (MContinuousDistribution)observedStates;
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			Double2DArray.deassignArray(distances);
+			for (int taxon1=0; taxon1<numTaxa; taxon1++)
+				for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+					double sumDiffs =0;
+					if (taxon1!=taxon2)
+						for (int ic=0; ic< contStates.getNumChars(); ic++) {
+							if (incl == null || incl.isBitOn(ic)){
+								double one =contStates.getState(ic, taxon1, 0);
+								double two = contStates.getState(ic, taxon2, 0);
+								if (MesquiteDouble.isCombinable(one) && MesquiteDouble.isCombinable(two))
+									sumDiffs += Math.abs(one-two); //item 0
+							}
+						}
+					distances[taxon1][taxon2]=sumDiffs/contStates.getNumChars();
+				}
+		}
+		else if (observedStates instanceof MCategoricalDistribution){
+			MCategoricalDistribution catStates = (MCategoricalDistribution)observedStates;
+			numTaxa = taxa.getNumTaxa();
+			distances= new double[numTaxa][numTaxa];
+			for (int taxon1=0; taxon1<numTaxa; taxon1++)
+				for (int taxon2=0; taxon2<numTaxa; taxon2++) {
+					double total = 0;
+					double sumDiffs =0;
+					distances[taxon1][taxon2]=0.0;
+					if (taxon1!=taxon2){
+						for (int ic=0; ic< catStates.getNumChars(); ic++) {
+							if (incl == null || incl.isBitOn(ic)){
+								long one =catStates.getState(ic, taxon1) & CategoricalState.dataBitsMask;
+								long two = catStates.getState(ic, taxon2) & CategoricalState.dataBitsMask;
+								if (CategoricalState.cardinality(one)>0 || CategoricalState.cardinality(two)>0)
+									total+=1.0;
+								if (CategoricalState.isInapplicable(one) || CategoricalState.isInapplicable(two))  //if either inapplicable, don't count difference; should have option
+									continue;
+								if (CategoricalState.isUnassigned(one) || CategoricalState.isUnassigned(two))  //if either unassigned, don't count difference
+									continue;
+								if (one==two)  // they are the same
+									continue;
+								if (CategoricalState.statesShared(one, two) && (CategoricalState.isUncertain(one) || CategoricalState.isUncertain(two)))
+									continue;
+								sumDiffs += 1.0; 
+							}
+						}
+						//distances[taxon1][taxon2]=sumDiffs/catStates.getNumChars();
+						distances[taxon1][taxon2]=sumDiffs/total;
+					}
+				}
+		}
+	}
+	public double getDistance(int taxon1, int taxon2){
+		if (taxon1>=0 && taxon1<numTaxa && taxon2>=0 && taxon2<numTaxa)
+			return distances[taxon1][taxon2];
+		else
+			return MesquiteDouble.unassigned;
+		
+	}
+	public double[][] getMatrix(){
+		return distances;
+	}
+	public boolean isSymmetrical(){
+		return true;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/aDistanceIntro/aDistanceIntro.java b/Source/mesquite/distance/aDistanceIntro/aDistanceIntro.java
new file mode 100644
index 0000000..e55c42f
--- /dev/null
+++ b/Source/mesquite/distance/aDistanceIntro/aDistanceIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.aDistanceIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aDistanceIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aDistanceIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Calculates and provides utilities for distances matrices.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Distance Matrix Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Distance Matrix Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/distance/explanation.txt b/Source/mesquite/distance/explanation.txt
new file mode 100644
index 0000000..c7c3d60
--- /dev/null
+++ b/Source/mesquite/distance/explanation.txt
@@ -0,0 +1,4 @@
+Distance Analysis Package
+Defines basic elements of taxon-to-taxon distance calculations.  
+Calculates distances from character data, and provides some simple 
+clustering methods (e.g., UPGMA).
diff --git a/Source/mesquite/distance/lib/DNATaxaDistFromMatrix.java b/Source/mesquite/distance/lib/DNATaxaDistFromMatrix.java
new file mode 100644
index 0000000..8e0a0df
--- /dev/null
+++ b/Source/mesquite/distance/lib/DNATaxaDistFromMatrix.java
@@ -0,0 +1,108 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.lib;
+/*~~  */
+
+
+import java.awt.Checkbox;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.GeographicStateTest;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public abstract class DNATaxaDistFromMatrix extends TaxaDistFromMatrix {
+	MesquiteBoolean estimateAmbiguityDifferences = new MesquiteBoolean(MolecularTaxaDistance.DEFAULTESTIMATEAMBIGUITYDIFFERENCES);
+	MesquiteBoolean countDifferencesIfGapInPair = new MesquiteBoolean(MolecularTaxaDistance.DEFAULTCOUNTDIFFERENCESIFGAPINPAIR);
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		super.superStartJob(arguments, condition, hiredByName);
+		addCheckMenuItemToSubmenu(null, distParamSubmenu, "Count Sites with Gap in Pair", MesquiteModule.makeCommand("toggleCountDifferencesIfGapInPair", this), countDifferencesIfGapInPair);
+		addCheckMenuItemToSubmenu(null, distParamSubmenu, "Estimate Ambiguity Differences", MesquiteModule.makeCommand("toggleEstimateAmbiguityDifferences", this), estimateAmbiguityDifferences);
+		return true;
+	}	 
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot snapshot = new Snapshot();
+		snapshot.addLine("toggleEstimateAmbiguityDifferences  " + estimateAmbiguityDifferences.toOffOnString());
+		snapshot.addLine("toggleCountDifferencesIfGapInPair  " + countDifferencesIfGapInPair.toOffOnString());
+		return snapshot;
+	}
+	public boolean optionsAdded() {
+		return true;
+	}
+	Checkbox estimateAmbiguityDifferencesBox;
+	Checkbox countDifferencesIfGapInPairBox;
+	public void addOptions(ExtensibleDialog dialog) {
+		estimateAmbiguityDifferencesBox = dialog.addCheckBox("estimate ambiguity differences", estimateAmbiguityDifferences.getValue());
+		countDifferencesIfGapInPairBox = dialog.addCheckBox("count as a difference one taxon having a gap and the other a non-gap", countDifferencesIfGapInPair.getValue());
+
+	}
+	public void processOptions(ExtensibleDialog dialog) {
+		estimateAmbiguityDifferences.setValue(estimateAmbiguityDifferencesBox.getState());
+		countDifferencesIfGapInPair.setValue(countDifferencesIfGapInPairBox.getState());
+	}
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether sites at which one element of the pair of sequences being compared has a gap are not excluded or are.", "[on; off]", commandName, "toggleCountDifferencesIfGapInPair")) {
+			countDifferencesIfGapInPair.toggleValue(new Parser().getFirstToken(arguments));
+			parametersChanged();
+		}
+		else	if (checker.compare(this.getClass(), "Sets whether sites with missing data, gaps, or ambiguities have differences estimated by other sites or are ignored.", "[on; off]", commandName, "toggleEstimateAmbiguityDifferences")) {
+			estimateAmbiguityDifferences.toggleValue(new Parser().getFirstToken(arguments));
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		String s = super.getParameters();
+		if (getEstimateAmbiguityDifferences())
+			s+= " Ambiguity differences estimated from patterns for non-ambiguous bases when similar patterns exist, distributed equally otherwise.";
+		if (getCountDifferencesIfGapInPair())
+			s+= " Sites at which one element of the pair of sequences being compared has a gap are not excluded .";
+		else
+			s+= " Sites at which one element of the pair of sequences being compared has a gap ARE excluded .";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public boolean getCountDifferencesIfGapInPair() {
+		return countDifferencesIfGapInPair.getValue();  
+	}
+	/*.................................................................................................................*/
+	public boolean getEstimateAmbiguityDifferences() {
+		return estimateAmbiguityDifferences.getValue();  
+	}
+	public Class getRequiredStateClass(){
+		return DNAState.class;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/lib/DNATaxaDistFromMatrixFreq.java b/Source/mesquite/distance/lib/DNATaxaDistFromMatrixFreq.java
new file mode 100644
index 0000000..65ca611
--- /dev/null
+++ b/Source/mesquite/distance/lib/DNATaxaDistFromMatrixFreq.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.distance.lib;
+
+import mesquite.distance.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+public abstract class DNATaxaDistFromMatrixFreq extends DNATaxaDistFromMatrix {
+	MesquiteBoolean baseFreqEntireMatrix = new MesquiteBoolean(true);  //note:  Swofford uses this as true in PAUP*4.0b10
+	double[] pi = new double[4];
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		super.superStartJob(arguments,  condition,  hiredByName);
+		for (int i = 0; i<4; i++)
+			pi[i]=0.25;
+		addCheckMenuItemToSubmenu(null,distParamSubmenu, "Base Freq on Entire Matrix", MesquiteModule.makeCommand("toggleBaseFreqEntireMatrix", this), baseFreqEntireMatrix);
+		return true;
+  	 }	 
+	/*.................................................................................................................*/
+	 public Snapshot getSnapshot(MesquiteFile file) {
+	 	Snapshot snapshot = new Snapshot();
+	 	snapshot.addLine("toggleBaseFreqEntireMatrix  " + baseFreqEntireMatrix.toOffOnString());
+	 	return snapshot;
+	 }
+		/*.................................................................................................................*/
+		public String getParameters(){
+			String s = super.getParameters();
+			if (getBaseFreqEntireMatrix())
+				s+= " Base frequencies estimated over entire matrix.";
+			else
+				s+= " Base frequencies estimated over each pair of sequences separately.";
+			return s;
+		}
+	 /*.................................................................................................................*/
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	 	if (checker.compare(this.getClass(), "Sets whether the base frequency values used in distance calculations are based upon the entire matrix (if on) or just the pair of sequences being compared (if off).", "[on; off]", commandName, "toggleBaseFreqEntireMatrix")) {
+	 		baseFreqEntireMatrix.toggleValue(new Parser().getFirstToken(arguments));
+	 		parametersChanged();
+	 }
+		else
+	 		return  super.doCommand(commandName, arguments, checker);
+	 	return null;
+	 }
+		/*.................................................................................................................*/
+	public double getBaseFreq(int i) {
+		if (i>=0 && i<4)
+			return pi[i];
+		else 
+			return 0.0;
+	}
+	public boolean getBaseFreqEntireMatrix() {
+		return baseFreqEntireMatrix.getValue();
+	}
+	public double[] getPi(MCharactersDistribution observedStates, int it1, int it2){
+		CharacterData data = observedStates.getParentData();
+		if (!(data instanceof DNAData))
+			return null;
+		return ((DNAData)data).getFrequencies(true, true, it1, it2);  
+	}
+}
diff --git a/Source/mesquite/distance/lib/DNATaxaDistance.java b/Source/mesquite/distance/lib/DNATaxaDistance.java
new file mode 100644
index 0000000..d720fc0
--- /dev/null
+++ b/Source/mesquite/distance/lib/DNATaxaDistance.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+public class DNATaxaDistance extends MolecularTaxaDistance {
+		
+	public DNATaxaDistance(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+		super(ownerModule,taxa,observedStates, estimateAmbiguityDifferences,countDifferencesIfGapInPair);
+	}
+		public int getMaxState(){
+			return DNAState.getMaxPossibleStateStatic();
+		}
+		public CompatibilityTest getCompatibilityTest(){
+			return new RequiresAnyDNAData();
+		}
+		/** used for debugging; turn this on and at least some of the distance calculators will stream their results to the log.  */
+		public void logDistancesIfDesired(String name){
+			if (false) {
+				MesquiteTrunk.mesquiteTrunk.logln("\n\n\n||||||||||||||  " + name);
+				distancesToLog();
+			}
+		}
+	}
diff --git a/Source/mesquite/distance/lib/GeoTaxaDistFromMatrix.java b/Source/mesquite/distance/lib/GeoTaxaDistFromMatrix.java
new file mode 100644
index 0000000..3ff192b
--- /dev/null
+++ b/Source/mesquite/distance/lib/GeoTaxaDistFromMatrix.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+/* incrementable, with each being based on a different matrix */
+public abstract class GeoTaxaDistFromMatrix extends TaxaDistFromMatrix {
+ 	public Class getRequiredStateClass(){
+		return GeographicState.class;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new GeographicStateTest();
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/distance/lib/GeoTaxaDistance.java b/Source/mesquite/distance/lib/GeoTaxaDistance.java
new file mode 100644
index 0000000..dbaf2c2
--- /dev/null
+++ b/Source/mesquite/distance/lib/GeoTaxaDistance.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.distance.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+public abstract class GeoTaxaDistance extends TaxaDistance {
+	protected MContinuousDistribution geoStates;
+	protected GeographicData data; 
+	
+	public GeoTaxaDistance(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates){
+		super(taxa);
+		if (observedStates==null)
+			return;
+		data = (GeographicData)observedStates.getParentData();
+		
+		geoStates = (MContinuousDistribution)observedStates;
+	}
+	
+	public GeoTaxaDistance(Taxa taxa){
+		super(taxa);
+	}
+		public CompatibilityTest getCompatibilityTest(){
+			return new GeographicStateTest();
+		}
+
+	}
diff --git a/Source/mesquite/distance/lib/IncTaxaDistanceSource.java b/Source/mesquite/distance/lib/IncTaxaDistanceSource.java
new file mode 100644
index 0000000..b5cd698
--- /dev/null
+++ b/Source/mesquite/distance/lib/IncTaxaDistanceSource.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** a distance source that is incrementable */
+public abstract class IncTaxaDistanceSource extends TaxaDistanceSource implements Incrementable  {
+   	 public Class getDutyClass() {
+   	 	return IncTaxaDistanceSource.class;
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TaxaDistFromMatrixSrc"};
+   	 }
+	
+}
+
diff --git a/Source/mesquite/distance/lib/MolecularTaxaDistance.java b/Source/mesquite/distance/lib/MolecularTaxaDistance.java
new file mode 100644
index 0000000..336beeb
--- /dev/null
+++ b/Source/mesquite/distance/lib/MolecularTaxaDistance.java
@@ -0,0 +1,286 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.distance.lib;
+
+import java.awt.Checkbox;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+public abstract class MolecularTaxaDistance extends TaxaDistance {
+		protected double[][] distances;
+		protected MCategoricalDistribution catStates;
+		protected CharInclusionSet incl = null;
+		int maxNumStates;
+		CategoricalData data; 
+		public static final boolean DEFAULTESTIMATEAMBIGUITYDIFFERENCES = true;
+		public static final boolean DEFAULTCOUNTDIFFERENCESIFGAPINPAIR = false;
+    	boolean estimateAmbiguityDifferences = DEFAULTESTIMATEAMBIGUITYDIFFERENCES;
+    	boolean countDifferencesIfGapInPair = DEFAULTCOUNTDIFFERENCESIFGAPINPAIR;
+    	MesquiteModule ownerModule;
+    	boolean isDNAData=false;
+    	boolean allIncluded = true;
+		
+		public MolecularTaxaDistance(MesquiteModule ownerModule, Taxa taxa, MCharactersDistribution observedStates, boolean estimateAmbiguityDifferences, boolean countDifferencesIfGapInPair){
+			super(taxa);
+			if (observedStates==null)
+				return;
+			this.ownerModule = ownerModule;
+			this.estimateAmbiguityDifferences = estimateAmbiguityDifferences;
+			this.countDifferencesIfGapInPair = countDifferencesIfGapInPair;
+			data = (CategoricalData)observedStates.getParentData();
+			isDNAData = data instanceof DNAData;
+			isDNAData = false;
+			
+			if (data !=null) {
+				incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+				if (incl!=null && !incl.allBitsOn()) 
+					allIncluded=false;
+			}
+				
+			catStates = (MCategoricalDistribution)observedStates;
+			distances= new double[getNumTaxa()][getNumTaxa()];
+		}
+
+		public void copyDistanceTriangle() {
+			for (int taxon1=0; taxon1<getNumTaxa(); taxon1++)
+				distances[taxon1][taxon1]= 0.0;  
+			for (int taxon1=0; taxon1<getNumTaxa(); taxon1++)
+				for (int taxon2=taxon1; taxon2<getNumTaxa(); taxon2++)
+					distances[taxon2][taxon1]=distances[taxon1][taxon2];
+		}
+		
+		public void setEstimateAmbiguityDifferences(boolean estimateAmbiguityDifferences){
+			this.estimateAmbiguityDifferences = estimateAmbiguityDifferences;
+		}
+		public double getDistance(int taxon1, int taxon2){
+			if (taxon1>=0 && taxon1<getNumTaxa() && taxon2>=0 && taxon2<getNumTaxa())
+				return distances[taxon1][taxon2];
+			else
+				return MesquiteDouble.unassigned;
+			
+		}
+		public abstract int getMaxState();
+		
+		public double[][] calcPairwiseDistance(int taxon1, int taxon2, MesquiteDouble N, MesquiteDouble D){
+			if (catStates==null)
+				return null;
+			int numChars = catStates.getNumChars();
+			int numStates = getMaxState()+1;
+			double[][] fxy = new double[numStates][numStates];
+			double[][] unambiguousFxy = new double[numStates][numStates];
+			for (int i=0; i<numStates;i++)
+				for (int j=0; j<numStates; j++) {
+					fxy[i][j]=0.0;
+					unambiguousFxy[i][j]=0.0;
+				}
+
+			if (estimateAmbiguityDifferences)  // calculate pairings for unambiguous
+				for (int ic=0; ic< numChars; ic++) {
+					if (allIncluded || incl.isBitOn(ic)){
+						long one =catStates.getState(ic, taxon1) & CategoricalState.dataBitsMask;
+						long two = catStates.getState(ic, taxon2) & CategoricalState.dataBitsMask;
+						int oneState;
+						int twoState;
+
+						if (isDNAData) {
+							oneState = DNAState.getOnlyElement(one);
+							twoState = DNAState.getOnlyElement(two);
+						}
+						else {
+							oneState = CategoricalState.getOnlyElement(one);
+							twoState = CategoricalState.getOnlyElement(two);
+						}
+					//	boolean oneIsMissingInapplicable = CategoricalState.isInapplicable(one) || CategoricalState.isUnassigned(one);
+					//	boolean twoIsMissingInapplicable = CategoricalState.isInapplicable(two) || CategoricalState.isUnassigned(two);
+						if (oneState>=0 && oneState<numStates && twoState>=0 && twoState<numStates){  // they have single states
+							unambiguousFxy[oneState][twoState] ++;
+							//unambiguousFxy[twoState][oneState] ++;
+						}
+						else if (CategoricalState.statesShared(one,two)) {  // states overlap !oneIsMissingInapplicable &&  !twoIsMissingInapplicable && 
+							long sharedStates = CategoricalState.intersection(one,two);
+							int card = CategoricalState.cardinality(sharedStates);
+							for (int i=0; i<numStates; i++) {
+								if (CategoricalState.isElement(sharedStates,i)) ;
+									unambiguousFxy[i][i] += 1.0/card;  
+							}
+						}
+					}
+				}
+
+			int count = 0;
+			int countTotal = 0;
+			double sumDiffs =0;
+			double gapDifferences = 0.0;
+
+					
+			for (int ic=0; ic< numChars; ic++) {
+				if (allIncluded || incl.isBitOn(ic)){
+					count++;
+					countTotal++;
+					long oneAllBits =catStates.getState(ic, taxon1);
+					long twoAllBits = catStates.getState(ic, taxon2);
+					long one = oneAllBits & CategoricalState.dataBitsMask;
+					long two = twoAllBits & CategoricalState.dataBitsMask;
+					int oneState;
+					int twoState;
+					if (isDNAData) {
+						oneState = DNAState.getOnlyElement(one);
+						twoState = DNAState.getOnlyElement(two);
+					}
+					else {
+						oneState = CategoricalState.getOnlyElement(one);
+						twoState = CategoricalState.getOnlyElement(two);
+					}
+					boolean oneIsMissingInapplicable = CategoricalState.isInapplicable(oneAllBits) || CategoricalState.isUnassigned(oneAllBits);
+					boolean twoIsMissingInapplicable = CategoricalState.isInapplicable(twoAllBits) || CategoricalState.isUnassigned(twoAllBits);
+					 if (countDifferencesIfGapInPair && (CategoricalState.isInapplicable(oneAllBits) != CategoricalState.isInapplicable(twoAllBits))) { 
+						 gapDifferences+=1.0;
+					 }
+					 else if (oneState>=0 && oneState<numStates && twoState>=0 && twoState<numStates){  // they have single states
+						fxy[oneState][twoState] ++;
+					}
+					else if (oneIsMissingInapplicable &&  twoIsMissingInapplicable) {  // both are missing or inapplicable, skip site
+						count--;
+					}
+					else if (!countDifferencesIfGapInPair && (CategoricalState.isInapplicable(oneAllBits) ||  CategoricalState.isInapplicable(twoAllBits))) { // one is inapplicable and we are not counting these sites, skip site
+						count--; //count--;
+					}
+					else if (!oneIsMissingInapplicable &&  !twoIsMissingInapplicable && CategoricalState.statesShared(one,two)) {  // states overlap   
+						long sharedStates = CategoricalState.intersection(one,two);
+						int card = CategoricalState.cardinality(sharedStates);
+						for (int i=0; i<numStates; i++) {
+							if (CategoricalState.isElement(sharedStates,i))
+								fxy[i][i] += 1.0/card;  
+						}
+					}
+					else {  //at least one is not inapplicable or missing, and they don't overlap
+						if (CategoricalState.isUnassigned(oneAllBits) || (!countDifferencesIfGapInPair && CategoricalState.isInapplicable(oneAllBits))) 
+							if (isDNAData)
+								one = DNAState.fullSet();
+							else if (isDNAData)
+								one = ProteinState.fullSet();
+						if (CategoricalState.isUnassigned(twoAllBits) || (!countDifferencesIfGapInPair && CategoricalState.isInapplicable(twoAllBits))) 
+							if (isDNAData)
+								two = DNAState.fullSet();
+							else if (isDNAData)
+								two = ProteinState.fullSet();
+						
+						
+						//TODO: deal with polymorphism
+						if (estimateAmbiguityDifferences) {// at least one of them has multiple states or is empty
+							double sum = 0.0;
+							double combinationCount = 0.0;
+							for (int i=0; i<numStates; i++) {
+								if (CategoricalState.isElement(one,i))
+									for (int j=0; j<numStates; j++) {
+										if (CategoricalState.isElement(two,j)) {  // i is in one, j is in two
+											sum += unambiguousFxy[i][j];
+											//if (i!=j) sum+= unambiguousFxy[j][i];
+											combinationCount++;
+											//if (i!=j) combinationCount++;
+										}
+									}
+							}
+							
+							if (sum>0) {   // applicable patterns occur at least once in the unambiguous
+								for (int i=0; i<numStates; i++) {
+									if (CategoricalState.isElement(one,i))
+										for (int j=0; j<numStates; j++) {
+											if (CategoricalState.isElement(two,j)) {  // i is in one, j is in two
+												fxy[i][j] += unambiguousFxy[i][j]/sum;
+												//if (i!=j) fxy[i][j] += unambiguousFxy[j][i]/sum;
+											}
+										}
+								}
+							
+							}
+							else   //at this point we could bail if estimateAmbiguityDifferences, which PAUP seems to do, and not count this site.  However, instead we will estimate the values in another way
+								if (oneIsMissingInapplicable) {  // first one is missing/inapplicable
+								int card =CategoricalState.cardinality(two);
+								for (int i=0; i<numStates; i++) {
+									if (CategoricalState.isElement(two,i))
+											fxy[i][i] += 1.0/card;
+									}
+							}
+							else if (twoIsMissingInapplicable) {
+								int card = CategoricalState.cardinality(one);
+								for (int i=0; i<numStates; i++) {
+									if (CategoricalState.isElement(one,i))
+											fxy[i][i] += 1.0/card;
+									}
+							} 
+							else {  //sum is zero, therefore other sites suggest no similarities, so cycle through and distribute fraction through all combinations
+								for (int i=0; i<numStates; i++) {
+									if (CategoricalState.isElement(one,i))
+										for (int j=0; j<numStates; j++) {
+											if (CategoricalState.isElement(two,j)) {  // i is in one, j is in two
+												fxy[i][j] += 1.0/combinationCount;
+												//if (i!=j) fxy[i][j] += 1.0/combinationCount;
+											}
+										}
+								}
+							}
+
+						}	
+					}
+				}
+			}
+
+			double sumF = gapDifferences;
+			double nonDiagonals = 0.0;
+			for (int i=0; i<numStates;i++)
+				for (int j=0; j<numStates; j++)
+					sumF += fxy[i][j];
+			for (int i=0; i<numStates;i++)
+				nonDiagonals -= fxy[i][i];
+			if (sumF==0)
+				nonDiagonals = -1.0;
+			else
+				nonDiagonals /= sumF;
+
+			//nonDiagonals = nonDiagonals*1.0*count/countTotal;
+			nonDiagonals += 1.0;
+			nonDiagonals = Math.abs(nonDiagonals);
+			for (int i=0; i<numStates;i++)
+				for (int j=0; j<numStates; j++)
+					fxy[i][j]=fxy[i][j]/sumF;
+			if (N!=null)
+				N.setValue(sumF);
+			if (D!=null)
+				D.setValue(nonDiagonals);
+			return fxy;
+		}
+		public double[][] getMatrix(){
+			return distances;
+		}
+		public void distancesToLog(){
+				for (int taxon1=0; taxon1<getNumTaxa(); taxon1++) {
+					for (int taxon2=0; taxon2<getNumTaxa(); taxon2++) {
+						if (taxon1<taxon2)
+							if (MesquiteDouble.isInfinite(distances[taxon1][taxon2]))
+								MesquiteTrunk.mesquiteTrunk.logln("" + (taxon1+1) + "-"+ (taxon2+1) + ": INFINITE");
+							else
+								MesquiteTrunk.mesquiteTrunk.logln("" + (taxon1+1) + "-"+ (taxon2+1) + ": " + distances[taxon1][taxon2]);
+					}					
+					MesquiteTrunk.mesquiteTrunk.logln("");
+				}
+		}
+		public boolean isSymmetrical(){
+			return true;
+		}
+		public CompatibilityTest getCompatibilityTest(){
+			return new RequiresAnyMolecularData();
+		}
+	}
diff --git a/Source/mesquite/distance/lib/PairsWindow.java b/Source/mesquite/distance/lib/PairsWindow.java
new file mode 100644
index 0000000..7d7311c
--- /dev/null
+++ b/Source/mesquite/distance/lib/PairsWindow.java
@@ -0,0 +1,145 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+public class PairsWindow extends ChartWindow {
+	private Number2DArray pairValues;
+	public String averageString = "";
+	public String explanationString = "";
+	private int windowWidth=0;
+	private int windowHeight=0;
+	private int chartInsetTop = 10;
+	private int chartInsetBottom = 60;
+	private int chartInsetLeft = 0;
+	private int chartInsetRight = 20;
+	MesquiteModule ownerModule;
+	MesquiteChart chart;
+	MesquiteNumber utilNum;
+	PairsChartMessages messagePane;
+	Taxa taxa;
+	MesquiteInteger numItems;
+	DrawChart charterTask;
+	String itemTypeName;
+	public PairsWindow (MesquiteModule ownerModule, Number2DArray pairValues, DrawChart charterTask, String itemTypeName, MesquiteInteger numItems) {
+		super(ownerModule,  true); //infobar
+		this.numItems = numItems;
+		this.itemTypeName = itemTypeName;
+		this.charterTask =  charterTask;
+		this.ownerModule=ownerModule;
+		//this.taxa = taxa;
+		this.pairValues = pairValues;
+		chart=new MesquiteChart(ownerModule, numItems.getValue()*numItems.getValue(), 0, charterTask.createCharter(null));
+ 		setChart(chart);
+		
+		chart.deassignChart();
+		chart.setYAxisName(itemTypeName);
+		chart.setXAxisName(itemTypeName);
+		utilNum = new MesquiteNumber(0);
+		chart.constrainMinimumY(utilNum);
+		chart.setLocation(chartInsetLeft, chartInsetTop);
+		chart.setChartSize(getWidth()-chartInsetRight - chartInsetLeft, getHeight()-chartInsetTop - chartInsetBottom);
+		messagePane = new PairsChartMessages(this);
+		addToWindow(messagePane);
+		messagePane.setVisible(true);
+		setChartVisible();
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Value for Pairs of " + itemTypeName); 
+	}
+	public void setVisible(boolean vis){
+		if (vis && chart !=null) {
+			chart.setVisible(true);
+			chart.repaint();
+		}
+		super.setVisible(vis);
+	}
+	/*.................................................................................................................*/
+	public void setCharter(Charter charter) {
+		chart.setCharter(charter);
+	}
+	public void setAverageString(String t) {
+		averageString=t;
+	}
+	public void setExplanationString(String t) {
+		explanationString=t;
+	}
+	public void setWindowSize(int width, int height){
+		super.setWindowSize(width, height);
+		checkSizes();
+	}
+
+	public void recalcChart() {
+		chart.deassignChart();
+		MesquiteNumber iValue = new MesquiteNumber();
+		MesquiteNumber jValue = new MesquiteNumber();
+		MesquiteNumber resultZ = new MesquiteNumber();
+
+		for (int i=0; i<numItems.getValue(); i++)  //TODO: update if taxa included/excluded
+			for (int j=0; j<numItems.getValue(); j++) {
+				pairValues.placeValue(i, j, resultZ);
+				iValue.setValue(i);
+				jValue.setValue(j);
+				chart.addPoint(iValue, jValue, resultZ);
+			}
+		
+		chart.munch();
+		messagePane.repaint();
+	}
+	void checkSizes(){
+   	 	if (chart==null)
+   	 		return;
+   	 	if ((getHeight()!=windowHeight) || (getWidth()!=windowWidth) || (chart.getChartHeight()!=windowHeight-chartInsetTop - chartInsetBottom) || (chart.getChartWidth()!=windowWidth-chartInsetRight - chartInsetLeft)) {
+   	 		windowHeight =getHeight();
+   	 		windowWidth = getWidth();
+			chart.setLocation(chartInsetLeft, chartInsetTop);
+			chart.setChartSize(windowWidth-chartInsetRight - chartInsetLeft, windowHeight-chartInsetTop - chartInsetBottom);
+			messagePane.setLocation(0, windowHeight- chartInsetBottom);
+			messagePane.setSize(windowWidth, chartInsetBottom);
+		}
+	}
+	
+	public void paint(Graphics g) {
+	 	checkSizes();
+	}
+}
+
+class PairsChartMessages extends MesquitePanel {
+	PairsWindow window;
+	public PairsChartMessages (PairsWindow window) {
+		super();
+		this.window = window;
+		//setBackground(window.ownerModule.getProject().getProjectColor());
+		//setBackground(Color.yellow);
+	}
+	public void paint(Graphics g) {
+	 	g.setColor(Color.black);
+		g.drawString(window.averageString, 20, 25);
+		g.drawString(window.explanationString, 20, 45);
+	}
+}
+
+
+
diff --git a/Source/mesquite/distance/lib/TaxaDistFromMatrix.java b/Source/mesquite/distance/lib/TaxaDistFromMatrix.java
new file mode 100644
index 0000000..17ca950
--- /dev/null
+++ b/Source/mesquite/distance/lib/TaxaDistFromMatrix.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.distance.lib.*;
+
+/* ======================================================================== */
+
+public abstract class TaxaDistFromMatrix extends MesquiteModule {
+	protected MesquiteSubmenuSpec distParamSubmenu;
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		distParamSubmenu = addSubmenu(null, "Distance Parameters");
+		if (!getDistanceOptions())
+			return false;
+		return true;
+  	 }	 
+  	 public Class getDutyClass() {
+   	 	return TaxaDistFromMatrix.class;
+   	 }
+	
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#UncorrectedDistance"};
+   	 }
+
+	public abstract TaxaDistance getTaxaDistance(Taxa taxa, MCharactersDistribution charMatrix);
+
+	public boolean optionsAdded() {
+		return false;
+	}
+	public void addOptions(ExtensibleDialog dialog) {
+	}
+	public void processOptions(ExtensibleDialog dialog) {
+	}
+	
+	public boolean getDistanceOptions() {
+		if (MesquiteThread.isScripting() || !optionsAdded())
+			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Distance Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Distance Options for " + getName());
+
+		addOptions(dialog);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			processOptions(dialog);
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0) ;
+
+	}
+
+	
+	 public Class getRequiredStateClass(){
+		return null;
+	}
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){}
+
+}
diff --git a/Source/mesquite/distance/lib/TaxaDistance.java b/Source/mesquite/distance/lib/TaxaDistance.java
new file mode 100644
index 0000000..a0abede
--- /dev/null
+++ b/Source/mesquite/distance/lib/TaxaDistance.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** A distance matrix for taxa.*/
+public abstract class TaxaDistance {
+	Taxa taxa;
+	public TaxaDistance(Taxa taxa){
+		this.taxa = taxa;
+	}
+	public Taxa getTaxa(){
+		return taxa;
+	}
+	public int getNumTaxa(){
+		if (taxa==null)
+			return 0;
+		else
+			return taxa.getNumTaxa();
+	}
+	public abstract double getDistance(int taxon1, int taxon2);
+	public abstract boolean isSymmetrical();
+
+	/** This method provides a mechanism, if overridden, to present the user with a dialog box to choose options
+	 */
+	public boolean getDistanceOptions() {
+		return true;
+	}
+
+	/** This method should return the array of distances between the taxa contained in Taxa taxa.  
+	 * Override this if you want a different method of calculation
+	 */
+	public double[][] getMatrix() {
+		
+		double[][] distances= new double[getNumTaxa()][getNumTaxa()];
+		for (int taxon1 = 0; taxon1<getNumTaxa(); taxon1++) 
+			for (int taxon2=0; taxon2<getNumTaxa(); taxon2++) {
+				distances[taxon1][taxon2] = getDistance(taxon1,taxon2);
+			}
+		return distances;
+	}
+	
+	public void distancesToLog(){
+		MesquiteTrunk.mesquiteTrunk.logln("Sorry, this feature isn't enabled yet for this type of distance.");
+
+	}
+
+	public String getName(){
+		return "Unnamed Distance";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/distance/lib/TaxaDistanceSource.java b/Source/mesquite/distance/lib/TaxaDistanceSource.java
new file mode 100644
index 0000000..3da65a0
--- /dev/null
+++ b/Source/mesquite/distance/lib/TaxaDistanceSource.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+
+public abstract class TaxaDistanceSource extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return TaxaDistanceSource.class;
+   	 }
+	
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TaxaDistFromMatrixSrc"};
+   	 }
+
+ 	public boolean getDistanceOptions() {
+ 		return true;
+ 	}
+
+	public abstract TaxaDistance getTaxaDistance(Taxa taxa);
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){}
+}
+
diff --git a/Source/mesquite/distance/lib/TreeClusterer.java b/Source/mesquite/distance/lib/TreeClusterer.java
new file mode 100644
index 0000000..8a7148d
--- /dev/null
+++ b/Source/mesquite/distance/lib/TreeClusterer.java
@@ -0,0 +1,318 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.distance.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Clusters to make a tree from a distance matrix for taxa.*/
+public abstract class TreeClusterer extends MesquiteModule {
+	MesquiteBoolean followTies;
+	int MAXTREES = 100; 
+   	 public Class getDutyClass() {
+   	 	return TreeClusterer.class;
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** superStartJob is called automatically when an employee is hired.  This is intended for use by superclasses of modules that need
+	their own constructor-like call, without relying on the subclass to be polite enough to call super.startJob().*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+		followTies = new MesquiteBoolean(true); //this is in preparation for UI allowing choice of whether to follow ties
+  		if (!MesquiteThread.isScripting()){
+	    	 	int s = MesquiteInteger.queryInteger(containerOfModule(), "MAXTREES", "Maximum number of equally good trees to store during clustering (MAXTREES)", MAXTREES);
+ 	 		if (MesquiteInteger.isCombinable(s))
+ 	 			MAXTREES = s;
+ 	 		else
+ 				return false;
+  		}
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setMAXTREES " + MAXTREES);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the maximum number of trees stored", "[number]", commandName, "setMAXTREES")) {
+    	 		int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteInteger.isCombinable(s)){
+    	 			s = MesquiteInteger.queryInteger(containerOfModule(), "MAXTREES", "Maximum number of equally good trees to store during clustering (MAXTREES)", MAXTREES);
+    	 		}
+    	 		if (MesquiteInteger.isCombinable(s)){
+    	 			MAXTREES = s;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+	/*.................................................................................................................*/
+	
+   	public abstract double getDistanceBetweenClusters(double[][] distanceMatrix, int[] clusterI, int[] clusterJ);
+	/*.................................................................................................................*/
+	public void getTrees(Taxa taxa, TaxaDistance distances, TreeVector trees){
+		if (followTies.getValue() && MAXTREES > 1)
+			getTreesTies(taxa, distances, trees);
+		else
+			getTreesSingle(taxa, distances, trees);
+	}
+	
+	public void getTreesSingle(Taxa taxa, TaxaDistance distances, TreeVector trees){
+  		if (taxa==null || distances==null || trees == null)
+  			return;
+   		int numTaxa = taxa.getNumTaxa();
+		MesquiteTree tree = new MesquiteTree(taxa);
+		// start with default bush
+		tree.setToDefaultBush(numTaxa, false);
+		
+		// make double[][] distanceMatrix, for each of daughters of root
+		double[][] originalMatrix = distances.getMatrix();
+		if (originalMatrix == null)
+			return;
+		// make double[][] distanceMatrix, for each of daughters of root
+		double[][] matrix = new double[originalMatrix.length][originalMatrix[0].length];
+		for (int i=0; i<numTaxa; i++){
+			for (int j=0; j<numTaxa; j++){
+				matrix[i][j] = originalMatrix[i][j];
+			}
+		}
+		
+		double bestDist;
+		boolean done = false;
+		for (int joining = 1; joining<numTaxa-1 && !done; joining++) {
+			CommandRecord.tick("Clustering by " + getName() + ": Joining taxon " + joining);
+			logln("Clustering by " + getName() + ": Joining taxon " + joining);
+			bestDist = MesquiteDouble.unassigned;
+			int pairI=MesquiteInteger.unassigned;
+			int pairJ=MesquiteInteger.unassigned;
+
+			// find two most similar daughters of root; in case of tie, first pair found is used
+			for (int i=0; i<numTaxa-joining+1; i++) //numTaxa-joining+1 is number of daughters remaining
+				for (int j=i+1; j<numTaxa-joining+1; j++) {
+					double d = matrix[i][j];
+					if (MesquiteDouble.lessThan(d, bestDist, 0)) {
+						bestDist = d;
+						pairI = i;
+						pairJ = j;
+					}
+					else if (true && MesquiteDouble.equals(d, bestDist, 0)){
+						pairI = i;
+						pairJ = j;
+					}
+				}
+			if (!MesquiteInteger.isCombinable(pairI) || !MesquiteInteger.isCombinable(pairJ))
+				done=true;
+			else {	
+				// unite two daughters
+				tree.moveBranch(tree.indexedDaughterOfNode(tree.getRoot(), pairI), tree.indexedDaughterOfNode(tree.getRoot(), pairJ), false);
+				
+				for (int i=0; i<numTaxa; i++){
+					for (int j=0; j<numTaxa; j++){
+						matrix[i][j] = MesquiteDouble.impossible;
+					}
+				}
+				int numDaughtersOfRoot = numTaxa-joining;
+				int[][] clusters = new int[numDaughtersOfRoot][];
+ 				for (int i=0; i<numDaughtersOfRoot; i++){
+					clusters[i] = tree.getTerminalTaxa(tree.indexedDaughterOfNode(tree.getRoot(), i));
+				}
+				for (int i=0; i<numDaughtersOfRoot; i++){
+					for (int j=0; j<numDaughtersOfRoot; j++){
+						matrix[i][j] = getDistanceBetweenClusters(originalMatrix, clusters[i], clusters[j]);
+					}
+				}
+
+					
+			}
+		}
+  		
+		tree.setName(getName() + " tree");
+		//tree.setAnnotation(distances.getAnnotation(), false);
+		trees.addElement(tree, false);
+  	}
+	/*.................................................................................................................*/
+	public void getTreesTies(Taxa taxa, TaxaDistance distances, TreeVector trees){
+  		if (taxa==null || distances==null || trees == null)
+  			return;
+   		int numTaxa = taxa.getNumTaxa();
+		MesquiteTree tree = new MesquiteTree(taxa);
+		// start with default bush
+		tree.setToDefaultBush(numTaxa, false);
+		
+		// make double[][] distanceMatrix, for each of daughters of root
+		double[][] originalMatrix = distances.getMatrix();
+		if (originalMatrix == null)
+			return;
+		// make double[][] distanceMatrix, for each of daughters of root
+		double[][] matrix = new double[originalMatrix.length][originalMatrix[0].length];
+		for (int i=0; i<numTaxa; i++){
+			for (int j=0; j<numTaxa; j++){
+				matrix[i][j] = originalMatrix[i][j];
+			}
+		}
+		countTrees = 0;
+		countPaths = 0;
+		warned = false;
+		ProgressIndicator progIndicator = new ProgressIndicator(getProject(),"Cluster Analysis ", "Clustering in progress", 0, "Stop Clustering");
+		progIndicator.setButtonMode(ProgressIndicator.FLAG_AND_HIDE);
+		progIndicator.setText("Cluster Analysis (" + getName() + ") in progress ");
+		progIndicator.setTertiaryMessage(getParameters());
+		progIndicator.start();
+		followTrees(tree, trees, matrix, originalMatrix, 1, numTaxa, 1, progIndicator);
+		if (progIndicator.isAborted()) {
+			trees.removeAllElements(false);
+			discreetAlert( "Cluster Analysis was stopped.  No trees will result.");
+		}
+		progIndicator.goAway();
+  	}
+	/*.................................................................................................................*/
+  	int countTrees;
+  	int countPaths;
+  	boolean warned = false;
+  	//basic approach is to start with unresolved bush, then continuing to join daughters of the root until only two remain
+  	void followTrees(MesquiteTree tree, TreeVector trees, double matrix[][], double originalMatrix[][], int joining, int numTaxa, int path, ProgressIndicator progIndicator){
+		if (joining >= numTaxa-1 || trees.size()>=MAXTREES || progIndicator.isAborted())
+			return;
+		//pass trees and initial tree to recursive prcedure that passes new matrices even deeper, cloning trees as needed
+		double bestDist = MesquiteDouble.unassigned;
+		boolean done = false;
+		progIndicator.setSecondaryMessage("Clustering by " + getName() + ": Joining taxon " + joining + "; working on cluster path #" + path);
+		
+		int[] pairI = new int[numTaxa*numTaxa];
+		int[] pairJ = new int[numTaxa*numTaxa];
+		IntegerArray.deassignArray(pairI);
+		IntegerArray.deassignArray(pairJ);
+		int countPairs = 0;
+		int numDaughtersOfRoot = numTaxa-joining + 1;
+		// find two most similar daughters of root; in case of tie, first pair found is used
+		for (int i=0; i<numDaughtersOfRoot; i++) //
+			for (int j=i+1; j<numDaughtersOfRoot; j++) {
+				double d = matrix[i][j];
+				if (MesquiteDouble.isCombinable(d)){
+					if (MesquiteDouble.lessThan(d, bestDist, 0)) {
+						countPairs = 0;
+						bestDist = d;
+						pairI[countPairs] = i;
+						pairJ[countPairs] = j;
+						countPairs++;
+					}
+					else if (MesquiteDouble.equals(d, bestDist, 0)){
+						pairI[countPairs] = i;
+						pairJ[countPairs] = j;
+						countPairs++;
+					}
+				}
+			}
+		if (countPairs == 0 || !MesquiteInteger.isCombinable(pairI[0]) || !MesquiteInteger.isCombinable(pairJ[0]))
+			return;
+		else {	
+			numDaughtersOfRoot--;  //this will be number once branch moved
+			for (int tie = 0; tie<countPairs && !progIndicator.isAborted() && !isDoomed(); tie++){
+				int thisPath = path;
+				if (tie>0) {
+					countPaths++;
+					thisPath = countPaths;
+				}
+				if (trees.size()>=MAXTREES) {
+					if (!warned){
+						discreetAlert( "MAXTREES of " + MAXTREES + " reached in Cluster Analysis");
+					}
+					warned = true;
+					return;
+				}
+				MesquiteTree tieTree = tree;
+				if (countPairs>1)
+					tieTree = tree.cloneTree(); //need to make copy of tree if search needs to fork
+				
+				// unite two daughters
+				tieTree.moveBranch(tieTree.indexedDaughterOfNode(tieTree.getRoot(), pairI[tie]), tieTree.indexedDaughterOfNode(tieTree.getRoot(), pairJ[tie]), false);
+				if (numDaughtersOfRoot== 2) {
+					tieTree.standardize(tieTree.getRoot(), false); //standardizing to make it easy to detect if duplicate
+					if (!treeAlreadyExists(tieTree, trees)){ //to make sure duplicate trees aren't added
+						tieTree.setName(getName() + " tree " + (++countTrees));
+						trees.addElement(tieTree, false);
+					
+					}
+				}
+				else {  //rebuild matrix of distances among daughters of root
+					double[][] tieMatrix = new double[numTaxa][numTaxa];
+					Double2DArray.deassignArray(tieMatrix);
+
+					int[][] clusters = new int[numDaughtersOfRoot][];
+					for (int i=0; i<numDaughtersOfRoot; i++){
+						clusters[i] = tieTree.getTerminalTaxa(tieTree.indexedDaughterOfNode(tieTree.getRoot(), i));
+					}
+					for (int i=0; i<numDaughtersOfRoot; i++){
+						for (int j=i+1; j<numDaughtersOfRoot; j++){
+							tieMatrix[i][j] = getDistanceBetweenClusters(originalMatrix, clusters[i], clusters[j]);
+						}
+					}
+					for (int i=0; i<numDaughtersOfRoot; i++){ //assumes symmetrical distances
+						for (int j=0; j<i; j++){
+							tieMatrix[i][j] = tieMatrix[j][i] ;
+						}
+					}
+					followTrees(tieTree, trees, tieMatrix, originalMatrix, joining+1, numTaxa, thisPath, progIndicator);
+				}
+			}
+				
+		}
+  	}
+  	
+	/*.................................................................................................................*/
+  	boolean treeAlreadyExists(Tree tree, TreeVector trees){
+  		for (int i=0; i<trees.size(); i++)
+  			if (treesSame(tree, (Tree)trees.elementAt(i)))
+  				return true;
+  		return false;
+  	}
+  	
+ 	/*-----------------------------------------*/
+	boolean treesSame(Tree t1, Tree t2){ //assumes order standardized
+		int node1 = t1.getRoot();
+		int node2 = t2.getRoot();
+		while (t1.nodeExists(node1) && t2.nodeExists(node1)){
+			if (t1.nodeIsTerminal(node1) && t2.nodeIsTerminal(node2)) {
+				if (t1.taxonNumberOfNode(node1) != t2.taxonNumberOfNode(node2))
+					return false;
+			}
+			else if (t1.nodeIsInternal(node1) && t2.nodeIsInternal(node2)) {
+				if (t1.numberOfDaughtersOfNode(node1) != t2.numberOfDaughtersOfNode(node2))
+					return false;
+			}
+			else
+				return false;
+			node1 = t1.nextInPreorder(node1);
+			node2 = t2.nextInPreorder(node2);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean hasLimitedTrees(Taxa taxa){
+   	 	return true;
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/diverse/BiSSELikelihood/BiSSELikelihood.java b/Source/mesquite/diverse/BiSSELikelihood/BiSSELikelihood.java
new file mode 100644
index 0000000..2e7da1e
--- /dev/null
+++ b/Source/mesquite/diverse/BiSSELikelihood/BiSSELikelihood.java
@@ -0,0 +1,281 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.BiSSELikelihood;
+
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.RequiresExactlyCategoricalData;
+import mesquite.diverse.lib.*;
+import mesquite.diverse.BiSSELikelihoodCalculator.BiSSELikelihoodCalculator;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.stochchar.lib.MargLikelihoodForModel;
+
+public class BiSSELikelihood extends NumForCharAndTreeDivers {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BiSSELikelihoodCalculator.class, getName() + "  needs a method to calculate likelihoods.",
+		"The method to calculate likelihoods is arranged initially");
+		e.setSuppressListing(true);
+	}
+
+	BiSSELikelihoodCalculator calcTask;
+
+
+	MesquiteParameter mu0;   //user specified extinction rate in state 0
+	MesquiteParameter lambda0;   //user specified speciation rate in state 0
+	MesquiteParameter mu1;   //user specified extinction rate in state 1
+	MesquiteParameter lambda1;   //user specified speciation rate in state 1
+	MesquiteParameter q01;   //user specified transition rate from state 0 to state 1
+	MesquiteParameter q10;   //user specifiedtransition rate from state 1 to state 0
+
+	MesquiteParameter[] params;
+	MesquiteParameter[] paramsCopy;
+	boolean[] selected;
+	boolean suspended = false;
+	MesquiteString reportModeName;
+	StringArray reportModes;
+	int reportMode = 0;
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		calcTask = (BiSSELikelihoodCalculator)hireEmployee(BiSSELikelihoodCalculator.class, "Calculator for BiSSE Likelihood");
+		if (calcTask == null)
+			return sorry(getName() + " couldn't start because no integrating likelihood calculator module obtained.");
+		double def = MesquiteDouble.unassigned;
+		//following is for the parameters explorer
+		lambda0 = new MesquiteParameter("lambda0", "Rate of speciation with state 0", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		lambda1 = new MesquiteParameter("lambda1", "Rate of speciation with state 1", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		mu0 = new MesquiteParameter("mu0", "Rate of extinction with state 0", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		mu1 = new MesquiteParameter("mu1", "Rate of extinction with state 1", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		q01 = new MesquiteParameter("q01", "Rate of 0->1 changes", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		q10 = new MesquiteParameter("q10", "Rate of 1->0 changes", def, 0, MesquiteDouble.infinite, 0.000, 1);
+		params = new MesquiteParameter[]{lambda0, lambda1, mu0, mu1, q01, q10};
+		reportModes = new StringArray(7);  
+		reportModes.setValue(0, "Likelihood");  //the strings passed will be the menu item labels
+		reportModes.setValue(1, lambda0.getName());  //the strings passed will be the menu item labels
+		reportModes.setValue(2, lambda1.getName());  //the strings passed will be the menu item labels
+		reportModes.setValue(3, mu0.getName());  //the strings passed will be the menu item labels
+		reportModes.setValue(4, mu1.getName());  //the strings passed will be the menu item labels
+		reportModes.setValue(5, q01.getName());  //the strings passed will be the menu item labels
+		reportModes.setValue(6, q10.getName());  //the strings passed will be the menu item labels
+		reportModeName = new MesquiteString(reportModes.getValue(reportMode));  //this helps the menu keep track of checkmenuitems
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Report BiSSE Results As", makeCommand("setReportMode", this), reportModes); 
+		mss.setSelected(reportModeName);
+
+		if (MesquiteThread.isScripting()  && !MesquiteThread.suppressInteractionAsLibrary)
+			suspended = true;
+		if (!MesquiteThread.isScripting()){
+			if (!showDialog())
+				return sorry(getName() + " couldn't start because parameters not specified.");
+		}
+		addMenuItem("Set Parameters...", makeCommand("setParameters", this));
+		addMenuItem("Recalculate", makeCommand("resume", this));
+		
+		return true;
+	}
+ 	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	boolean showDialog(){
+		if (params == null)
+			return false;
+		String s = whatIsMyPurpose();
+		if (!StringUtil.blank(s))
+			s = "BiSSE Parameters for " + s;
+		else
+			s = "BiSSE Parameters";
+		ParametersDialog dlog = new ParametersDialog(containerOfModule(), "BiSSE Parameters", s, params, null, 2, 2, false);
+		dlog.appendToHelpString("Parameters for BiSSE model.  Indicate the rates of speciation when in state 0 (lambda0), speciation when in state 1 (lambda1), ");
+		dlog.appendToHelpString("rates of extinction when in state 0 (mu0), extinction when in state 1 (mu1), ");
+		dlog.appendToHelpString("rates of character change 0 to 1(q01), and rates of character change 1 to 0 (q10). ");
+		dlog.completeAndShowDialog(true);
+
+		boolean ok = (dlog.query()==0);
+		if (ok) 
+			dlog.acceptParameters();
+		//	dlog.setInWizard(false);
+		dlog.dispose();
+
+		return ok;
+	}
+
+	public void initialize(Tree tree, CharacterDistribution charStates1) {
+		// TODO Auto-generated method stub
+
+	}
+	/*.................................................................................................................*/
+
+	public Snapshot getSnapshot(MesquiteFile file) {
+		final Snapshot temp = new Snapshot();
+		String pLine = MesquiteParameter.paramsToScriptString(params);
+		temp.addLine("suspend ");
+		if (!StringUtil.blank(pLine))
+			temp.addLine("setParameters " + pLine);
+		temp.addLine("setReportMode " + ParseUtil.tokenize(reportModes.getValue(reportMode)));
+
+		temp.addLine("getIntegTask ", calcTask);
+		temp.addLine("resume ");
+		return temp;
+	}
+	boolean setParam(MesquiteParameter p, MesquiteParameter[] params, Parser parser){
+		double newValue = MesquiteDouble.fromString(parser);
+		int loc = parser.getPosition();
+		String token = parser.getNextToken();
+		if (token != null && "=".equals(token)){
+			int con = MesquiteInteger.fromString(parser);
+			if (MesquiteInteger.isCombinable(con) && con>=0 && con < params.length)
+				p.setConstrainedTo(params[con], false);
+		}
+		else
+			parser.setPosition(loc);
+		if ((MesquiteDouble.isUnassigned(newValue) ||  newValue >=0) && newValue != p.getValue()){
+			p.setValue(newValue); //change mode
+			return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets rate parameters", "[double double double double double double]", commandName, "setParameters")) {
+			if (StringUtil.blank(arguments)){
+				if (!MesquiteThread.isScripting() && showDialog())
+					parametersChanged();
+			}
+			else {
+				parser.setString(arguments);
+				boolean changed =  setParam(lambda0, params, parser);
+				boolean more = setParam(lambda1, params, parser);
+				changed = changed || more;
+				more = setParam(mu0, params, parser);
+				changed = changed || more;
+				more = setParam(mu1, params, parser);
+				changed = changed || more;
+				more = setParam(q01, params, parser);
+				changed = changed || more;
+				more = setParam(q10, params, parser);
+				changed = changed || more;
+				if (changed && !MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the report mode", null, commandName, "setReportMode")) {
+			if (getHiredAs() == MargLikelihoodForModel.class)
+				return null;
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = reportModes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=reportMode){
+				reportMode = newMode; //change mode
+				reportModeName.setValue(reportModes.getValue(reportMode)); //so that menu item knows to become checked
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspended = true;
+		}
+		else if (checker.compare(getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspended = false;
+			parametersChanged();
+		}
+		else if (checker.compare(getClass(), "Returns integrating module", null, commandName, "getIntegTask")) {
+			return calcTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	/*------------------------------------------------------------------------------------------*/
+	public void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null)
+			return;
+		clearResultAndLastResult(result);
+		if (resultString != null)
+			resultString.setValue("Calculation not completed");
+		if (suspended)
+			return;
+		if (tree == null || charStates == null)
+			return;
+		if (!CategoricalDistribution.isBinaryNoMissing(charStates, tree)){
+			if (resultString!=null)
+	            resultString.setValue(getName() + " unassigned because the character is not binary or has missing data");
+			return;
+		}
+
+		paramsCopy = MesquiteParameter.cloneArray(params, paramsCopy);
+
+		calcTask.calculateLogProbability(tree, charStates, paramsCopy, result, resultString);
+		if (reportMode >0) {
+			result.setValue(paramsCopy[reportMode-1].getValue());
+			if (resultString != null)
+				resultString.setValue(reportModeName.getValue() + ": " + paramsCopy[reportMode-1] + "; " + resultString);
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+ 	public boolean returnsMultipleValues(){
+  		return true;
+  	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	/*------------------------------------------------------------------------------------------*/
+	public String getName() {
+		return "BiSSE Speciation/Extinction Likelihood";
+	}
+	
+	public String getVeryShortName(){
+		if (reportMode>0)
+			return "BiSSE Likelihood (" + reportModes.getValue(reportMode) + ")";
+		return "BiSSE Likelihood";
+	}
+
+	public String getAuthors() {
+		return "Peter E. Midford & Wayne P. Maddison";
+	}
+
+	public String getVersion() {
+		return "1.0";
+	}
+
+	public String getExplanation(){
+		return "Calculates likelihood with a tree of a species diversification model whose speciation and extinction rates depend on the state of a binary character (BiSSE model, Maddison, Midford & Otto, 2007).";
+	}
+
+	/*.................................................................................................................*/
+	/** returns keywords related to what the module does, for help-related searches. */ 
+	public  String getKeywords()  {
+		return "diversification birth death";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+}
+
diff --git a/Source/mesquite/diverse/BiSSELikelihoodCalculator/BiSSELikelihoodCalculator.java b/Source/mesquite/diverse/BiSSELikelihoodCalculator/BiSSELikelihoodCalculator.java
new file mode 100644
index 0000000..34a1c06
--- /dev/null
+++ b/Source/mesquite/diverse/BiSSELikelihoodCalculator/BiSSELikelihoodCalculator.java
@@ -0,0 +1,1325 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.BiSSELikelihoodCalculator;
+
+import java.util.Vector;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.diverse.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.duties.ParametersExplorer;
+
+public class BiSSELikelihoodCalculator extends MesquiteModule implements ParametersExplorable, Evaluator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ParametersExplorer.class, getName() + "  uses a Parameters Explorer to show likelihood surfaces.",
+		"The parameter explorer is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	// bunch of stuff copied from zMargLikeCateg - need to prune!!
+
+
+	DEQNumSolver solver;
+	double [][] probsExt, probsData;
+	double[] yStart;  //initial value for numerical integration
+	double[] d,e; //intermediate results
+	double[][] savedRootEstimates; // holds the estimates at the root (for simulation priors, etc.)
+	MesquiteNumber probabilityValue;
+	int numStates;
+
+	long underflowCheckFrequency = 2;   //how often to check that not about to underflow; 1 checks every time
+	long underflowCheck = 1;
+	double underflowCompensation = 1;
+	MesquiteNumber minChecker;
+	// hooks for capturing context for table dump.
+	Tree lastTree;
+	CharacterDistribution lastCharDistribution;
+
+	// Number of steps per branch, reduce for a faster, possibily sloppier result
+	double stepCount = 1000; 
+
+	//In version 1.1. the assumption about the root prior for model estimation, ancestral state reconstruction and simulation is assumed to be embedded in the model
+	//Thus, the control is removed here
+	public static final int ROOT_IGNOREPRIOR = 0;  // likelihoodignore's model's prior
+	public static final int ROOT_USEPRIOR = 1;  // calculates ancestral states imposing model's prior
+	public boolean showRootModeChoices = true;  
+	//TODO: allow user choice ������������������������
+	int rootMode = ROOT_USEPRIOR; //what if anything is done with prior probabilities of states at subroot?  
+	StringArray rootModes;
+	MesquiteString rootModeName;
+
+	MesquiteBoolean intermediatesToConsole = new MesquiteBoolean(false);
+	MesquiteBoolean getStartFromConstrainedModel = new MesquiteBoolean(false);
+
+	boolean[] deleted = null;
+	MesquiteParameter s0p;
+	MesquiteParameter s1p;
+	MesquiteParameter mu0p;
+	MesquiteParameter mu1p;
+	MesquiteParameter q01p;
+	MesquiteParameter q10p;
+	MesquiteParameter[] paramsForExploration;
+	MesquiteParameter[] previousParams;
+	ParametersExplorer explorer;
+	MesquiteBoolean conditionOnSurvival;
+	SpecExtincCategModel speciesModel;
+	RandomBetween rng;
+	int iterations = 2;
+	boolean suspended = false;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		probabilityValue = new MesquiteNumber();
+		minChecker = new MesquiteNumber(MesquiteDouble.unassigned);
+
+		solver = new RKF45Solver();
+		rng = new RandomBetween(System.currentTimeMillis());
+		//following is for the parameters explorer
+		final double def = MesquiteDouble.unassigned;
+		final double inf = MesquiteDouble.infinite;
+		s0p = new MesquiteParameter("lambda0", "Rate of speciation with state 0", 0.1, 0, inf, 0.000, 1);
+		s1p = new MesquiteParameter("lambda1", "Rate of speciation with state 1", 0.1, 0, inf, 0.000, 1);
+		mu0p = new MesquiteParameter("mu0", "Rate of extinction with state 0", 0.1, 0, inf, 0.000, 1);
+		mu1p = new MesquiteParameter("mu1", "Rate of extinction with state 1", 0.1, 0, inf, 0.000, 1);
+		q01p = new MesquiteParameter("q01", "Rate of 0->1 changes", 0.1, 0, inf, 0.000, 1);
+		q10p = new MesquiteParameter("q10", "Rate of 1->0 changes", 0.1, 0, inf, 0.000, 1);
+		if (MesquiteThread.isScripting()  && !MesquiteThread.suppressInteractionAsLibrary)
+			suspended = true;
+		paramsForExploration= new MesquiteParameter[]{s0p, s1p, mu0p, mu1p, q01p, q10p};
+		speciesModel = new SpecExtincCategModel();
+		speciesModel.setParams(paramsForExploration);
+
+		//		parameters = MesquiteParameter.cloneArray(paramsForExploration, null);
+		previousParams = new MesquiteParameter[6];
+		for (int i = 0; i<6; i++)
+			previousParams [i] = new MesquiteParameter();
+
+		conditionOnSurvival = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Condition on Survival", MesquiteModule.makeCommand("conditionOnSurvival", this), conditionOnSurvival);
+		addCheckMenuItem(null,"Get Start from Constrained Model", MesquiteModule.makeCommand("getStartFromConstrainedModel", this), getStartFromConstrainedModel);
+		MesquiteSubmenuSpec mLO = addSubmenu(null, "Likelihood Calculation", null); 
+		addItemToSubmenu(null, mLO, "Steps per Branch...", makeCommand("setStepCount", this));
+		addItemToSubmenu(null, mLO, "Optimization Iterations...", makeCommand("setIterations", this));
+		addItemToSubmenu(null, mLO, "Underflow Checking...", makeCommand("setUnderflowCheckFreq", this));
+		addMenuItem("-", null);
+		addMenuItem("Show Parameters Explorer", makeCommand("showParamExplorer",this));
+		//addCheckMenuItem(null, "Intermediates to console", makeCommand("toggleIntermediatesToConsole",this), intermediatesToConsole);
+		//		addMenuItem("-", null);
+		rootModes = new StringArray(2);  
+		rootModes.setValue(ROOT_IGNOREPRIOR, "Ignore Root State Frequencies");  //the strings passed will be the menu item labels
+		rootModes.setValue(ROOT_USEPRIOR, "Use Root State Frequencies as Prior");
+		rootModeName = new MesquiteString(rootModes.getValue(rootMode));  //this helps the menu keep track of checkmenuitems
+
+		postBean("startJob", false);
+		//	if (showRootModeChoices){
+		/*Treatment of prior at root; currently user interface hidden unless preferences file put in place*/
+		//	MesquiteSubmenuSpec mssr = addSubmenu(null, "Root Reconstruction", makeCommand("setRootMode", this), rootModes); 
+		//	mssr.setSelected(rootModeName);
+		/**/
+
+		return true;
+	}
+	boolean reportCladeValues = false;
+	public void setReportCladeLocalValues(boolean reportCladeValues){
+		this.reportCladeValues = reportCladeValues;
+	}
+	public boolean getReportCladeLocalValues(){
+		return reportCladeValues;
+	}
+	public void employeeQuit(MesquiteModule employee){
+		if (employee == explorer)
+			explorer = null;
+	}
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend ");
+		temp.addLine("setUnderflowCheckFreq " + underflowCheckFrequency);
+		temp.addLine("setStepCount " + stepCount);
+		temp.addLine("setIterations " + iterations);
+		temp.addLine("conditionOnSurvival  " + conditionOnSurvival.toOffOnString());
+		temp.addLine("getStartFromConstrainedModel " + getStartFromConstrainedModel.toOffOnString());
+		if (explorer != null)
+			temp.addLine("showParamExplorer ", explorer);
+		temp.addLine("resume ");
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets the frequency of checking for underflow", "[integer, 1 or greater]", commandName, "setUnderflowCheckFreq")) {
+			int freq = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(freq) && !MesquiteThread.isScripting())
+				freq = MesquiteInteger.queryInteger(containerOfModule(), "Checking frequency", "Frequency at which underflow checking is performed in likelihood calculations.  A value of n means checking is performed on each nth calculation; higher numbers mean the calculations go faster but are at risk of underflow problems.  Values over 10 are not recommended", (int)underflowCheckFrequency, 1, 10000);
+
+			if (MesquiteInteger.isCombinable(freq) && freq >=0 && freq!=underflowCheckFrequency){
+				underflowCheckFrequency = freq; //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspended = true;
+		}
+		else if (checker.compare(getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspended = false;
+			parametersChanged();
+		}
+		else if (checker.compare(getClass(), "Returns last result string", null, commandName, "getLastResultString")) {
+			return lastResultString;
+		}
+		else if (checker.compare(getClass(), "Sets the number of steps per branch", "[double, 1 or greater]", commandName, "setStepCount")) {
+			double steps = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(steps) && !MesquiteThread.isScripting())
+				steps = MesquiteDouble.queryDouble(containerOfModule(), "Steps per branch", "Number of divisions of each branch for numerical integration.  Higher numbers mean the calculations are more accurate but go more slowly.  Values under 100 are not recommended", stepCount, 10, 1000000);
+
+			if (MesquiteDouble.isCombinable(steps) && steps >=0 && steps!=stepCount){
+				stepCount = steps; //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the number of iterations in the likelihood optimization", "[integer, 1 or greater]", commandName, "setIterations")) {
+			int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(it) && !MesquiteThread.isScripting())
+				it = MesquiteInteger.queryInteger(containerOfModule(), "Optimization Iterations", "Number of random starting points for likelihood optimizationi.  Higher numbers mean the optimization is more thorough  but goes more slowly.", iterations, 1, 1000);
+
+			if (MesquiteInteger.isCombinable(it) && it >=0 && it!=iterations){
+				iterations = it; //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to condition by survival", "[on; off]", commandName, "conditionOnSurvival")) {
+			conditionOnSurvival.toggleValue(new Parser().getFirstToken(arguments));
+			if (!MesquiteThread.isScripting())parametersChanged();
+		}
+		else if (checker.compare(getClass(), "Shows the parameters explorer", "", commandName, "showParamExplorer")) {
+			explorer = (ParametersExplorer)hireEmployee(ParametersExplorer.class, "Parameters explorer");
+			if (explorer == null)
+				return null;
+			//	explorer.makeMenu("Parameters");
+			if (!explorer.setExplorable(this)){
+				explorer.iQuit();
+				return null;
+			}
+
+			return explorer;
+		}
+		else if (checker.compare(getClass(),"Sets whether to write intermediate branch values to console","[on; off]", commandName, "toggleIntermediatesToConsole")){
+			intermediatesToConsole.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(getClass(),"Sets whether to start searches for six parameter models from estimates of canonical five parameter models","[on; off]", commandName, "getStartFromConstrainedModel")){
+			getStartFromConstrainedModel.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void initProbs(int nodes, int numStates) {
+		this.numStates = numStates;
+		if (yStart == null || yStart.length != numStates*2 || d == null || e == null || probsData==null || probsData.length!=nodes || probsData[0].length!=numStates){
+			probsData = new double[nodes][numStates];
+			probsExt = new double[nodes][numStates];
+			yStart = new double[2*numStates];
+			d = new double[numStates];
+			e = new double[numStates];
+		}
+		Double2DArray.zeroArray(probsData);
+		Double2DArray.zeroArray(probsExt);
+	}
+
+
+	/*.................................................................................................................*/
+	private double checkUnderflow(double[] probs){
+		minChecker.setValue(MesquiteDouble.unassigned);
+		for (int i=0; i<probs.length; i++)
+			minChecker.setMeIfIAmMoreThan(probs[i]);
+		double q = minChecker.getDoubleValue();
+		if (q == 0)
+			return 0;
+		else {
+			for (int i=0; i<probs.length; i++)
+				probs[i] /= q;
+		}
+		return -Math.log(q);
+	}
+	/*.................................................................................................................*/
+	/* assess branch length variation to choose time slices */
+	private double assessBranchLengths(int node, Tree tree, MesquiteDouble min, MesquiteDouble max) {
+		double length = tree.getBranchLength(node, 1.0, deleted);
+		min.setValue(MesquiteDouble.minimum(min.getValue(), length));
+		max.setValue(MesquiteDouble.maximum(max.getValue(), length));
+		for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+			length += assessBranchLengths(nd,tree,min, max);
+		}
+		return length;
+	}
+
+
+	/* assumes hard polytomies */
+
+	// This might hold the intermediate step results if requested for debugging
+	Vector integrationResults = null;
+
+	/*.................................................................................................................*/
+	/* now returns underflow compensation */
+	private double downPass(int node, Tree tree, SpecExtincCategModel model, DEQNumSolver solver, CategoricalDistribution observedStates) {
+		double logComp;
+		int place = 0;
+		try {
+			if (tree == null || observedStates == null || e == null || d == null){
+				MesquiteMessage.printStackTrace("ERROR: downpass in BISSELikelihoodCalculator with null object: tree " + tree + " observedStates " + observedStates + " model " + model + " d " + d + " e " + e);
+				return MesquiteDouble.unassigned;
+			}
+			place = 1;
+			if (tree.nodeIsTerminal(node)) { //initial conditions from observations if terminal
+				place = 2;
+				long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node));
+				int obs = CategoricalState.minimum(observed); //NOTE: just minimum observed!
+				for (int state = 0;state < numStates;state++){
+					e[state]=0;
+					if ((state == obs))
+						d[state] = 1;
+					else
+						d[state] = 0;
+				}
+				place = 3;
+				logComp = 0.0;  // no compensation required yet
+			}
+			else { //initial conditions from daughters if internal
+				place = 4;
+				logComp = 0.0;
+				for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+					logComp += downPass(nd,tree,model,solver,observedStates);
+				}
+				place = 5;
+				for(int state = 0; state < numStates;state++){
+					d[state] = 1;  //two here to anticipate two daughters???
+					e[state] = 1;
+					//TODO: either filter to permit only ultrametric, or redo calculations to permit extinct nodes.
+					//TODO: likewise for polytomies
+					place = 6;
+					for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+						e[state] = probsExt[nd][state];
+						d[state] *= probsData[nd][state];
+					}
+
+					if (node != tree.getRoot()){  //condition on splitting at root; thus don't include rate if at root
+						d[state] *= model.getSRate(state);
+					}
+
+				}
+				place = 7;
+				if (underflowCheckFrequency>=0 && ++underflowCheck % underflowCheckFrequency == 0){
+					logComp += checkUnderflow(d);
+				}
+				place = 8;
+			}
+			if (node == tree.getRoot()){
+				place = 9;
+				for(int i=0;i<numStates;i++){
+					probsExt[node][i] = e[i];
+					probsData[node][i] = d[i];
+				}
+				place = 10;
+				return logComp;
+			}
+			else{
+				place = 11;
+				double x = 0;
+				double length = tree.getBranchLength(node,1.0,deleted);
+
+				double h = getStepSize(length);  
+
+				for(int i=0;i<numStates;i++){
+					yStart[i] = e[i];
+					yStart[i+numStates] = d[i];
+				}
+				place = 12;
+				if (intermediatesToConsole.getValue()){
+					MesquiteMessage.print("node " + node);
+					if (node == tree.getRoot())
+						MesquiteMessage.println(" is root");
+					else
+						MesquiteMessage.println("");
+					MesquiteMessage.println("At start, y is " + DoubleArray.toString(yStart));
+				}
+				place = 13;
+				integrationResults = solver.integrate(x,yStart,h,length,model,integrationResults,intermediatesToConsole.getValue());    
+				
+				double[] yEnd = null;
+				if (integrationResults != null)
+					yEnd = (double[])integrationResults.lastElement();
+				if (yEnd != null && yEnd.length == 2*numStates){
+					place = 14;
+					for(int i=0;i<numStates;i++){
+						probsExt[node][i] = yEnd[i];
+						probsData[node][i] = yEnd[i+numStates];
+					}
+				}
+				else {
+					place = 15;
+					MesquiteMessage.warnProgrammer("Vector returned by solver not the same size supplied!");
+					for(int i=0;i<numStates;i++){
+						probsExt[node][i]=0;   //is this the right thing here?
+						probsData[node][i]=0;  //this is probably the best choice here
+					}
+				}
+				place = 16;
+				if (intermediatesToConsole.getValue()){
+					place = 17;
+					MesquiteMessage.println("Intermediate values");
+					StringBuffer stateMsg = new StringBuffer(1000);
+					//stateMsg.delete(0,stateMsg.length());  //flush everything
+					x = h;
+					double [] tempResults;
+					place = 18;
+					for(int i=0;i<integrationResults.size();i++){
+						place = 19;
+						if(i%100 == 0){
+							String xString = MesquiteDouble.toFixedWidthString(x, 13, false);
+							stateMsg.append("x= "+ xString + " y =[");
+							tempResults = (double[])integrationResults.get(i);
+							for(int j=0;j<tempResults.length;j++)
+								stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+							stateMsg.append("]\n");
+							place = 20;
+						}   
+						x += h;
+					}
+					place = 21;
+					stateMsg.append("Final value; \n");
+					stateMsg.append("x= " + h*stepCount + " y =[");
+					tempResults = (double[])integrationResults.lastElement();
+					for(int j=0;j<tempResults.length;j++)
+						stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+					stateMsg.append("]\n");
+					MesquiteMessage.println(stateMsg.toString());
+					place = 22;
+				}
+				return logComp;
+			}
+		}
+		catch (NullPointerException e){
+			MesquiteMessage.println("ERROR: downpass in BISSELikelihoodCalculator with null object, place :" + place);
+			MesquiteMessage.println("      tree " + tree + " observedStates " + observedStates + " model " + model + " d " + d + " e " + e);
+			MesquiteMessage.println("      probsExt " + probsExt + " probsData " + probsData + " yStart " + yStart + " integrationResults " + integrationResults);
+			throw e;
+		}
+	}
+	/*------------------------------------------------------------------------------------------*/
+	double avgBranchLength;
+	double getStepSize(double length){		
+		//average branch will have stepCount steps; longer branches will have proportionately more steps up to a maximum of 4*stepCount, shorter to minimum of stepCount/2
+		double proposedSteps = stepCount*length/avgBranchLength;
+		if (proposedSteps < stepCount/2)
+			proposedSteps = stepCount/2;
+		else if (proposedSteps > 4* stepCount)
+			proposedSteps =4* stepCount;
+		return length/proposedSteps;       //this will need tweaking!
+	}
+	/*------------------------------------------------------------------------------------------*/
+	/** these methods for ParametersExplorable interface */
+	public MesquiteParameter[] getExplorableParameters(){
+		return paramsForExploration;
+	}
+	MesquiteNumber likelihood = new MesquiteNumber();
+	public double calculate(MesquiteString resultString){
+		if (suspended)
+			return MesquiteDouble.unassigned;
+		calculateLogProbability( lastTree,  lastCharDistribution, paramsForExploration, likelihood, resultString);
+		return likelihood.getDoubleValue();
+	}
+	public void restoreAfterExploration(){
+	}
+	/*------------------------------------------------------------------------------------------*/
+	int lastMaxState = 1;
+	long count = 0;
+
+	boolean anyNegative(double[] params){
+		if (params == null)
+			return false;
+		for (int i=0; i<params.length; i++)
+			if (params[i]<0)
+				return true;
+		return false;
+	}
+	int badCount = 1;
+	/*.................................................................................................................*/
+	public double evaluate(double[] params, Object bundle){
+		if (anyNegative(params))
+			return 1e100 + 1e99*badCount++;
+		Object[] b = ((Object[])bundle);
+		Tree tree = (Tree)b[0];
+		CategoricalDistribution states = (CategoricalDistribution)b[1];
+		SpecExtincCategModel model = (SpecExtincCategModel)b[2];
+		model.setParamValuesUsingConstraints(params);
+
+		double result =  logLike(tree, states, model);
+		if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result >= 1e100)
+			result = 1e100 + 1e99*badCount++;
+		if (count++ % 10 == 0)
+			CommandRecord.getRecSIfNull().tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " params " + MesquiteParameter.toString(params));
+		return result;
+	}
+	/*.................................................................................................................*/
+	double[] oneParam = new double[1];
+	/*.................................................................................................................*/
+	public double evaluate(MesquiteDouble param, Object bundle){
+		oneParam[0] = param.getValue();
+		if (anyNegative(oneParam))
+			return 1e100 + 1e99*badCount++;
+		Object[] b = ((Object[])bundle);
+		Tree tree = (Tree)b[0];
+		CategoricalDistribution states = (CategoricalDistribution)b[1];
+		SpecExtincCategModel model = (SpecExtincCategModel)b[2];
+		model.setParamValuesUsingConstraints(oneParam);
+		double result =  logLike(tree, states, model);
+		if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result > 1e100)
+			result = 1e100 + 1e99*badCount++;
+		if (count++ % 10 == 0)
+			CommandRecord.getRecSIfNull().tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " param " + MesquiteParameter.toString(oneParam));
+		return result;
+	}
+	double[] freq = new double[2];
+	/*.................................................................................................................*/
+	public double logLike(Tree tree, CategoricalDistribution states, SpecExtincCategModel model) {  
+		if (model==null || states == null || tree == null)
+			return MesquiteDouble.unassigned;
+		int root = tree.getRoot(deleted);
+		initProbs(tree.getNumNodeSpaces(),lastMaxState);
+		double logComp = downPass(root, tree, model, solver, states);
+		freq[0] = stationaryFreq0(model);
+		freq[1] = 1.0 - freq[0];
+		double likelihood = 0.0;
+		if (rootMode == ROOT_USEPRIOR){
+			if (conditionOnSurvival.getValue()){
+				for (int i=0;  i<lastMaxState; i++)
+					likelihood += freq[i]*probsData[root][i]/(1-probsExt[root][i])/(1-probsExt[root][i]);
+			}
+			else
+				for (int i=0;  i<lastMaxState; i++) 
+					likelihood += freq[i]*probsData[root][i];
+		}
+		else if (conditionOnSurvival.getValue()){
+			for (int i=0;  i<lastMaxState; i++)
+				likelihood += probsData[root][i]/(1-probsExt[root][i])/(1-probsExt[root][i]);
+		}
+		else
+			for (int i=0;  i<lastMaxState; i++) 
+				likelihood += probsData[root][i];
+		return (-(Math.log(likelihood) - logComp));
+	}
+	/*.................................................................................................................*/
+	public double stationaryFreq0(SpecExtincCategModel model) {  
+		if (model==null)
+			return MesquiteDouble.unassigned;
+		final double d = model.getSRate(0)-model.getSRate(1)+model.getERate(1)-model.getERate(0);
+		final double noise = (model.getSRate(0)+model.getSRate(1)+model.getERate(1)+model.getERate(0))*1E-14;
+		final double q01 = model.getCRate(0);
+		final double q10 = model.getCRate(1);
+		if (Math.abs(d ) < noise){
+			if (q01 + q10 == 0)
+				return 0.5;
+			return q10/(q01+q10);
+		}
+		double part = d - q01 - q10;
+		part = part*part + 4*d*q10;
+		if (part >=0)
+			part = Math.sqrt(part);
+		else
+			return MesquiteDouble.unassigned;
+		final double plus = (q01 + q10 - d + part) / (-2*d);
+		final double minus = (q01 + q10 - d - part) / (-2*d);
+		if (minus < 0 || minus >1)
+			return plus;
+		else if (plus < 0 || plus >1)
+			return minus;
+		else
+			return MesquiteDouble.unassigned;
+	}
+	String lastResultString;
+	/*
+	 Options:
+	 1. calculation determined entirely by params.  Constraints etc. determined within params array which is contained in species model
+	 2. predefined: constraint lambda0-mu0 = lambda1-mu1
+	 Should return estimated values in the MesquiteParameter array that was input
+	/*.................................................................................................................*/
+	public void calculateLogProbability(Tree tree, CharacterDistribution obsStates, MesquiteParameter[] params, MesquiteNumber prob, MesquiteString resultString) {  
+		if (speciesModel==null || obsStates==null || prob == null || tree == null)
+			return;
+		lastTree = tree;
+		lastCharDistribution = obsStates;
+		boolean failed = false;
+		prob.setToUnassigned();
+		if (suspended)
+			return;
+		CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+		int workingMaxState;
+		if (tree.hasReticulations() || tree.hasUnbranchedInternals(tree.getRoot())){
+			MesquiteMessage.warnProgrammer("Tree has reticulations or unbranched internal nodes; these are not allowed in BiSSE calcuclations.");
+			return;
+		}
+		else if (observedStates.getMaxState() <= 0){
+			MesquiteMessage.warnProgrammer("Character Distribution appears to be constant; cannot calculate likelihood of tree and character (Speciation/Extinction)");
+			return;
+		}
+		else if (observedStates.getMaxState() >1){
+			MesquiteMessage.warnProgrammer("Character Distribution is not binary; cannot calculate likelihood of tree and character (Speciation/Extinction)");
+			return;
+		}
+		else
+			workingMaxState = observedStates.getMaxState()+1; 
+		lastMaxState = workingMaxState;
+		speciesModel.getOriginalParams(previousParams);
+		speciesModel.setParams(params);
+		double currentStep = stepCount;
+
+		double negLogLikelihood = 0;
+		String modelString = "";
+		MesquiteDouble minBranchLength = new MesquiteDouble();
+		MesquiteDouble maxBranchLength = new MesquiteDouble();
+		avgBranchLength = assessBranchLengths(tree.getRoot(), tree, minBranchLength, maxBranchLength)/tree.numberOfNodesInClade(tree.getRoot());
+		/*to report stationary frequencies 
+		if (true){
+			negLogLikelihood = stationaryFreq0(speciesModel);
+		}
+		else 
+		 */
+		if (speciesModel.isFullySpecified()){
+			negLogLikelihood = logLike(tree, observedStates, speciesModel);
+			modelString  = speciesModel.toString();
+		}
+		else {	
+
+			logln("Estimating model with parameters " + speciesModel.toStringForScript());
+			//========================== all 6 parameters unspecified ==============================
+			if (speciesModel.numberSpecified() ==0 && speciesModel.numberEffectiveParameters() == 6){  //all unspecified
+				//some or all parameters are unassigned, and thus need to be estimated
+				//First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+				Optimizer opt = new Optimizer(this);
+				Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+				stepCount = 100;
+				double useIterations = iterations;
+				double[] suggestions1;
+				double[] suggestions2;
+				double[] suggestions3;
+				if (getStartFromConstrainedModel.getValue()){
+					suggestions1 = estimate5(tree,observedStates,1,new double[]{0.75, 0.5, 0.2, 0.05, 0.1});  
+					suggestions2 = estimate5(tree,observedStates,3,new double[]{0.5, 1, 0.35, 0.05, 0.1});
+					suggestions3 = estimate5(tree,observedStates,5,new double[]{0.5,0.3,0.5,0.4,0.075});
+				}
+				else {
+					suggestions1 = new double[]{1, 0.5, 0.5, 0.2, 0.1, 0.05};
+					suggestions2 = new double[]{0.5, 1, 0.2, 0.5, 0.05, 0.1};
+					suggestions3 = new double[]{0.5,0.3,0.5,0.4,0.05, 0.1};                    
+				}
+
+				double bestL = 1e101;
+				double[] suggestions = null;
+				int bestS = -1;
+				String attemptName = "";
+				double evs1 = MesquiteDouble.unassigned;
+				double evs2 = MesquiteDouble.unassigned;
+				double evs3 = MesquiteDouble.unassigned;
+				if (suggestions1 != null)
+					evs1 = evaluate(suggestions1,bundle);
+				if (suggestions2 != null)
+					evs2 = evaluate(suggestions2,bundle);
+				if (suggestions3 != null)
+					evs3 = evaluate(suggestions3,bundle);
+				if (MesquiteDouble.isCombinable(evs1) && evs1 < 1e99 && MesquiteDouble.isCombinable(evs2) && evs2 < 1e99 && MesquiteDouble.isCombinable(evs3) && evs3 < 1e99){
+					logln("Bisse Calculations: Tree " + tree.getName() + " and character " + obsStates.getName());
+					logln("Bisse Calculations: Estimating all 6 parameters, phase 1: step count 100");
+					double negLogLikelihood1 = opt.optimize(suggestions1, bundle);
+					logln("Bisse Calculations: neg. Log Likelihood first attempt:" + negLogLikelihood1);
+					double negLogLikelihood2 = opt.optimize(suggestions2, bundle);
+					logln("Bisse Calculations: neg. Log Likelihood second attempt:" + negLogLikelihood2);
+					double negLogLikelihood3 = opt.optimize(suggestions3, bundle);
+					logln("Bisse Calculations: neg. Log Likelihood third attempt:" + negLogLikelihood3);
+					if (negLogLikelihood1 < negLogLikelihood2 && negLogLikelihood1 < negLogLikelihood3) {
+						suggestions = suggestions1;
+						bestS = -1;
+						bestL = negLogLikelihood1;
+						attemptName = " first attempt" ;
+					}
+					else if (negLogLikelihood2 < negLogLikelihood1 && negLogLikelihood2 < negLogLikelihood3) {
+						suggestions = suggestions2;
+						bestS = -2;
+						bestL = negLogLikelihood2;
+						attemptName = " second attempt" ;
+					}
+					else {
+						suggestions = suggestions3;
+						bestS = -3;
+						bestL = negLogLikelihood3;
+						attemptName = " third attempt" ;                        
+					}
+				}
+				else{
+					useIterations = iterations + 3;
+				}
+				double[][] randomSuggestions = new double[(int)useIterations][6];
+
+				for (int i = 0; i< useIterations; i++){  
+					double max = 1.0;
+					if (i< useIterations/2){
+						max =  1.0;
+						for (int k = 0; k<6; k++){
+							randomSuggestions[i][k] = rng.randomDoubleBetween(0, max);
+						}
+						if (i % 2 == 0){ //every other one enforce e < s
+							randomSuggestions[i][3] = rng.randomDoubleBetween(0, randomSuggestions[i][1] );
+							randomSuggestions[i][4] = rng.randomDoubleBetween(0, randomSuggestions[i][2] );
+						}
+					}
+					else { //0 to 1 first then 0 to 10.0
+						max =  rng.randomDoubleBetween(0, 10.0);
+						for (int k = 0; k<6; k++){
+							randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+						}
+						if (i % 2 == 0){ //every other one enforce e < s
+							if (randomSuggestions[i][3]> randomSuggestions[i][1])
+								randomSuggestions[i][3] = rng.randomDoubleBetween(MesquiteDouble.maximum(randomSuggestions[i][1]-1.0, 0), randomSuggestions[i][1] );
+							if (randomSuggestions[i][4]> randomSuggestions[i][2])
+								randomSuggestions[i][4] = rng.randomDoubleBetween(MesquiteDouble.maximum(randomSuggestions[2][1]-1.0, 0), randomSuggestions[2][1] );
+						}
+						if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+							for (int k = 0; k<6; k++)
+								randomSuggestions[i][k] = rng.randomDoubleBetween(0, max);
+					}
+				}
+				for (int i = 0; i< useIterations; i++){ // 0 to 10
+					if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+						logln("BiSSE calculations: random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+						double nLL = opt.optimize(randomSuggestions[i], bundle);
+						stepCount = 1000;
+						nLL = evaluate(randomSuggestions[i], bundle);
+						stepCount = 100;
+						logln("BiSSE calculations: random attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+						if (nLL < bestL){
+							bestS = i;
+							bestL = nLL;
+							attemptName = "random attempt " + i ;
+						}
+					}
+					else 
+						logln("BiSSE calculations: random attempt " + i + " failed because starting position had undefined likelihood");
+				}
+				if (bestS>=0)
+					suggestions = randomSuggestions[bestS];
+				if (suggestions == null){
+					logln("BiSSE calculations: Estimating parameters failed");
+					failed = true;
+				}
+				else {
+					//logln("BiSSE calculations: Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+					stepCount = 1000;
+					logln("BiSSE calculations: Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+					logln("BiSSE calculations: Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+					negLogLikelihood = opt.optimize(suggestions, bundle);
+					logln("BiSSE calculations: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+					speciesModel.setParamValuesUsingConstraints(suggestions);
+					modelString  = speciesModel.toString() + " [est.]";
+				}
+			}
+			//========================== 2 - 5 parameters unspecified ==============================
+			else if (speciesModel.numberEffectiveParameters() > 1) {  //2 to 5 parameters unassigned; should have separate for 1!
+				//some parameters are unassigned, and thus need to be estimated
+				//First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+				Optimizer opt = new Optimizer(this);
+				Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+				stepCount = 100;
+				int looseParameter = -1;
+				int numParams = speciesModel.numberEffectiveParameters();
+				double[] suggestions1 = new double[numParams];
+				logln("BiSSE calculations: Tree " + tree.getName() + " and character " + obsStates.getName());
+				logln("BiSSE calculations: Estimating " + numParams + " free parameters");
+				for (int i=0; i < suggestions1.length; i++)
+					suggestions1[i] = 0.1*(i+1);
+				logln("BiSSE calculations: Estimating parameters, phase 1: step count 100");
+				double bestL = MesquiteDouble.unassigned;
+				int bestS = -1;
+
+				if (getStartFromConstrainedModel.getValue() && (numParams == 4)){                    
+					if (speciesModel.parameters[1].getConstrainedTo() == null)
+						looseParameter = 1;
+					else if (speciesModel.parameters[3].getConstrainedTo() == null)
+						looseParameter = 3;
+					else if (speciesModel.parameters[5].getConstrainedTo() == null)
+						looseParameter = 5;
+					for (int i=0; i < suggestions1.length; i++)
+						suggestions1[i] = 0.1*(i+1);
+					suggestions1 = estimate3(tree,observedStates,looseParameter,suggestions1);  //TODO these may need more work
+					logln("Generating starting point for 4 parameter model from canonical 3 parameter model");
+					logln("First random suggestion will be replaced by estimate from 3 parameter model");
+				}
+				else {
+					for (int i=0; i < suggestions1.length; i++)
+						suggestions1[i] = 0.1*(i+1);
+				}
+
+				String attemptName = "random attempt";
+				double[][] randomSuggestions = new double[iterations][numParams];
+				for (int i = 0; i< iterations; i++){  
+					if (i< iterations/2){//0 to 1 
+						for (int k = 0; k<numParams; k++){
+							randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+						}
+					}
+					else { //00 to 10.0
+						double max =  rng.randomDoubleBetween(0, 10.0);
+						for (int k = 0; k<numParams; k++){
+							randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+						}
+
+						if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+							for (int k = 0; k<numParams; k++)
+								randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+					}
+				}
+
+				if (getStartFromConstrainedModel.getValue() && (numParams == 4)){
+					if (looseParameter != -1){
+						logln("Setting first random suggestion to " + DoubleArray.toString(suggestions1));
+						for(int i=0;i<suggestions1.length;i++)
+							randomSuggestions[0][i]=suggestions1[i];
+					}
+				}
+
+				int totalCount = 0;
+				for (int i = 0; i< iterations; i++){ // 0 to 10
+					totalCount++;
+					if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+						logln("BiSSE calculations: random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+						double nLL = opt.optimize(randomSuggestions[i], bundle);
+						stepCount = 1000;
+						nLL = evaluate(randomSuggestions[i], bundle);
+						stepCount = 100;
+						logln("BiSSE calculations: attempt " +totalCount + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+						if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+							bestS = i;
+							bestL = nLL;
+							attemptName = "random attempt " + i ;
+						}
+					}
+					else {
+						if (totalCount-iterations < 10){
+							logln("BiSSE calculations: random attempt " + totalCount + " failed because starting position had undefined likelihood");
+							i--;  //10 extra free
+						}
+						else {
+							logln("BiSSE calculations: attempt failed because starting position had undefined likelihood");
+							i = iterations;
+						}
+					}
+				}
+				if (bestS>=0){
+					double[] suggestions = randomSuggestions[bestS];
+					//logln("BiSSE calculations: Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+					stepCount = 1000;
+					logln("BiSSE calculations: Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+					logln("BiSSE calculations: Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+					negLogLikelihood = opt.optimize(suggestions, bundle);
+					logln("BiSSE calculations: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+					speciesModel.setParamValuesUsingConstraints(suggestions);
+					modelString  = speciesModel.toString() + " [est.]";
+				}
+				else {
+					logln("BiSSE calculations: Estimating parameters failed");
+					failed = true;
+				}
+
+
+			}
+			//========================== 1 parameter unspecified ==============================
+			else  {  //1 parametersunassigned;
+				Optimizer opt = new Optimizer(this);
+				Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+				stepCount = 100;
+
+				logln("BiSSE calculations: Tree " + tree.getName() + " and character " + obsStates.getName());
+				logln("BiSSE calculations: Estimating one free parameter");
+				logln("BiSSE calculations: Estimating parameter, phase 1: step count 100");
+				MesquiteDouble suggestion = new MesquiteDouble(1);
+				negLogLikelihood = opt.optimize(suggestion, 0, 100, bundle);
+				logln("BiSSE calculations: neg. Log Likelihood first attempt:" + negLogLikelihood);
+				double bestL = negLogLikelihood;
+				double bestP = suggestion.getValue();
+				negLogLikelihood = opt.optimize(suggestion, 0.0, 10, bundle);
+				logln("BiSSE calculations: neg. Log Likelihood second attempt:" + negLogLikelihood);
+				if (bestL < negLogLikelihood)
+					suggestion.setValue(bestP);
+				else{
+					bestP = suggestion.getValue();
+					bestL = negLogLikelihood;
+				}
+				negLogLikelihood = opt.optimize(suggestion, 0.0, 1, bundle);
+				logln("BiSSE calculations: neg. Log Likelihood third attempt:" + negLogLikelihood);
+				if (bestL < negLogLikelihood)
+					suggestion.setValue(bestP);
+				else{
+					bestP = suggestion.getValue();
+					bestL = negLogLikelihood;
+				}
+				stepCount = 1000;
+				logln("BiSSE calculations: Estimating parameters, phase 2: step count 1000");
+				negLogLikelihood = opt.optimize(suggestion, suggestion.getValue() * 0.6, suggestion.getValue() * 1.4, bundle);
+				logln("BiSSE calculations: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+				oneParam[0] = suggestion.getValue();
+				speciesModel.setParamValuesUsingConstraints(oneParam);
+				modelString  = speciesModel.toString() + " [est.]";
+
+			}
+		}
+		speciesModel.getCurrentParams(params);
+		paramsForExploration[0].setValue(speciesModel.getSRate(0));
+		paramsForExploration[1].setValue(speciesModel.getSRate(1));
+		paramsForExploration[2].setValue(speciesModel.getERate(0));
+		paramsForExploration[3].setValue(speciesModel.getERate(1));
+		paramsForExploration[4].setValue(speciesModel.getCRate(0));
+		paramsForExploration[5].setValue(speciesModel.getCRate(1));
+		stepCount = currentStep;
+
+		if (prob!=null){
+			prob.setValue(negLogLikelihood);
+			prob.copyAuxiliaries(params);
+			prob.setName("BiSSE -lnLikelihood (prop.)");
+		}
+		double likelihood = Math.exp(-negLogLikelihood);
+		if (MesquiteDouble.isUnassigned(negLogLikelihood))
+			likelihood = MesquiteDouble.unassigned;
+		if (resultString!=null) {
+			if (failed){
+				resultString.setValue("Estimation of BiSSE parameters failed");
+				prob.deassignAllValues();
+			}
+			else{
+				String s = "Sp/Ext Likelihood (Char. dep.) " + modelString + ";  -log L.:"+ MesquiteDouble.toString(negLogLikelihood) + " [L. "+ MesquiteDouble.toString(likelihood) + "]";
+				s += "  " + getParameters();
+				s += "\nNOTE: reported are not likelihoods but rather values proportional to likelihoods";
+				resultString.setValue(s);
+			}
+		}
+
+		lastResultString = tree.getName() + "\t" + obsStates.getName() +"\t" + speciesModel.toStringForAnalysis() + "\t" + MesquiteDouble.toString(negLogLikelihood);
+		speciesModel.setParams(previousParams);
+	}
+
+	int quickIterations;
+	private SpecExtincCategModel localModel5 = new SpecExtincCategModel();
+	private double[] estimate5(Tree tree, CategoricalDistribution observedStates,int toConstrain,double suggestions[]){
+		//some parameters are unassigned, and thus need to be estimated
+		//First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+		final String logPrefix = "Bisse (5 parameter starting point): ";
+		quickIterations = iterations/2;
+		MesquiteParameter [] localParams = new MesquiteParameter[6]; 
+		for(int i= 0; i<6;i++){
+			localParams[i] = new MesquiteParameter();
+			if (i == toConstrain)
+				localParams[i].setConstrainedTo(localParams[i-1], false);            
+		}
+		localModel5.setParams(localParams);
+		Optimizer opt = new Optimizer(this);
+		Object[] bundle = new Object[] {tree, observedStates, localModel5};
+		stepCount = 100;
+		int numParams = 5;
+		logln(logPrefix + "constraining parameter " + toConstrain + " to generate starting point for 6 parameter estimate");
+		logln(logPrefix + "Estimating parameters, phase 1: step count 100");
+		double bestL = MesquiteDouble.unassigned;
+		double nLL = MesquiteDouble.unassigned;
+		int bestS = -2;
+		if (evaluate(suggestions,bundle)<1e99){
+			logln("Trying initial suggestion :" + DoubleArray.toString(suggestions));
+			nLL = opt.optimize(suggestions,bundle);
+			stepCount = 1000;
+			nLL = evaluate(suggestions, bundle);
+			stepCount = 100;
+			logln(logPrefix + "initial starting point suggestion neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(suggestions));
+			if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+				bestS = -1;
+				bestL = nLL;
+			}
+		}
+		String attemptName = "random attempt";
+		double[][] randomSuggestions = new double[quickIterations][numParams];
+		for (int i = 0; i< quickIterations; i++){  
+			if (i< quickIterations/2){//0 to 1 
+				for (int k = 0; k<numParams; k++){
+					randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+				}
+			}
+			else { //00 to 10.0
+				double max =  rng.randomDoubleBetween(0, 10.0);
+				for (int k = 0; k<numParams; k++){
+					randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+				}
+
+				if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+					for (int k = 0; k<numParams; k++)
+						randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+			}
+		}
+		for (int i = 0; i< quickIterations; i++){ // 0 to 10
+			if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+				nLL = opt.optimize(randomSuggestions[i], bundle);
+				stepCount = 1000;
+				nLL = evaluate(randomSuggestions[i], bundle);
+				stepCount = 100;
+				logln(logPrefix + "attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+				if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+					bestS = i;
+					bestL = nLL;
+					attemptName = "random attempt " + i ;
+				}
+			}
+			else 
+				logln(logPrefix + "random attempt " + i + " failed because starting position had undefined likelihood");
+		}
+		if (bestS>=-1){
+			if (bestS > 0)
+				suggestions = randomSuggestions[bestS];
+			//logln(logPrefix + "Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+			stepCount = 1000;
+			logln(logPrefix + "Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+			logln(logPrefix + "Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+			double negLogLikelihood = opt.optimize(suggestions, bundle);
+			logln(logPrefix + "neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+			final double [] result = new double[6];
+			for(int i= 0;i<result.length;i++){
+				if(i<toConstrain)
+					result[i] = suggestions[i];
+				else
+					result[i] = suggestions[i-1];
+			}
+			return result;
+		}
+		logln(logPrefix + "Estimating parameters failed");
+		return null;
+	}
+
+
+
+	private SpecExtincCategModel localModel3 = new SpecExtincCategModel();
+	private double[] estimate3(Tree tree, CategoricalDistribution observedStates,int looseParameter, double suggestions[]){
+		//some parameters are unassigned, and thus need to be estimated
+		//First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+		final String logPrefix = "Bisse (3 parameter starting point): ";
+		quickIterations = iterations/2;
+		MesquiteParameter [] localParams = new MesquiteParameter[6]; 
+		for(int i= 0; i<6;i++){
+			localParams[i] = new MesquiteParameter();
+			if (i % 2 == 1) // get 1,3,5
+				localParams[i].setConstrainedTo(localParams[i-1], false);            
+		}
+		localModel3.setParams(localParams);
+		double [] localSuggestions = DoubleArray.copyIntoDifferentSize(suggestions, 3, MesquiteDouble.unassigned);
+		Optimizer opt = new Optimizer(this);
+		Object[] bundle = new Object[] {tree, observedStates, localModel3};
+		stepCount = 100;
+		int numParams = 3;
+		logln("Bisse: constraining parameters 1,3,5 to generate starting point for 4 parameter estimate");
+		logln("Bisse: Estimating three free parameters");
+		logln("Bisse: Estimating parameters, phase 1: step count 100");
+		double bestL = MesquiteDouble.unassigned;
+		double nLL = MesquiteDouble.unassigned;
+		int bestS = -2;
+		if (evaluate(localSuggestions,bundle)<1e99){
+			logln(logPrefix + DoubleArray.toString(localSuggestions));
+			nLL = opt.optimize(localSuggestions,bundle);
+			stepCount = 1000;
+			nLL = evaluate(localSuggestions, bundle);
+			stepCount = 100;
+			logln(logPrefix + "initial starting point suggestion neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(suggestions));
+			if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+				bestS = -1;
+				bestL = nLL;
+			}
+		}
+
+		String attemptName = "random attempt";
+		double[][] randomSuggestions = new double[quickIterations][numParams];
+		for (int i = 0; i< quickIterations; i++){  
+			if (i< quickIterations/2){//0 to 1 
+				for (int k = 0; k<numParams; k++){
+					randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+				}
+			}
+			else { //00 to 10.0
+				double max =  rng.randomDoubleBetween(0, 10.0);
+				for (int k = 0; k<numParams; k++){
+					randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+				}
+
+				if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+					for (int k = 0; k<numParams; k++)
+						randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+			}
+		}
+		for (int i = 0; i< quickIterations; i++){ // 0 to 10
+			if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+				logln(logPrefix + "random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+				nLL = opt.optimize(randomSuggestions[i], bundle);
+				stepCount = 1000;
+				nLL = evaluate(randomSuggestions[i], bundle);
+				stepCount = 100;
+				logln(logPrefix + "attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+				if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+					bestS = i;
+					bestL = nLL;
+					attemptName = "random attempt " + i ;
+				}
+			}
+			else 
+				logln(logPrefix + "random attempt " + i + " failed because starting position had undefined likelihood");
+		}
+		if (bestS>=-1){
+			if (bestS > 0)
+				localSuggestions = randomSuggestions[bestS];
+			//logln(logPrefix + "Estimating parameters, phase 2: step count 100; best so far " + evaluate(localSuggestions, bundle));
+			stepCount = 1000;
+			logln(logPrefix + "Estimating parameters, phase 2: step count 1000; best so far " + evaluate(localSuggestions, bundle));
+			logln(logPrefix + "Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+			double negLogLikelihood = opt.optimize(localSuggestions, bundle);
+			logln(logPrefix + "neg. Log Likelihood final attempt:" + negLogLikelihood);
+			final double [] result = new double[4];
+			result[0] = localSuggestions[0];
+			if (looseParameter == 1){
+				result[1]=localSuggestions[0];
+				result[2]=localSuggestions[1];
+				result[3]=localSuggestions[2];
+			}
+			else if (looseParameter == 3){
+				result[1]=localSuggestions[1];
+				result[2]=localSuggestions[1];
+				result[3]=localSuggestions[2];
+			}
+			else if (looseParameter == 5){
+				result[1]=localSuggestions[1];
+				result[2]=localSuggestions[2];
+				result[3]=localSuggestions[2];                           
+			}
+
+			return result;
+		}
+		logln(logPrefix + "Estimating parameters failed");
+		return null;
+	}
+
+
+	public Class getDutyClass() {
+		// TODO Auto-generated method stub
+		return BiSSELikelihoodCalculator.class;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	public String getName() {
+		// TODO Auto-generated method stub
+		return "BiSSE Speciation/Extinction Likelihood Calculator";
+	}
+	public String getAuthors() {
+		return "Peter E. Midford & Wayne P. Maddison";
+	}
+
+	public String getVersion() {
+		return "1.01";
+	}
+
+	public String getExplanation(){
+		return "Calculates likelihood with a tree of a species diversification model whose speciation and extinction rates depend on the state of a binary character (BiSSE model, Maddison, Midford & Otto, 2007).";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+/*============================================================================*/
+class SpecExtincCategModel implements DESystem {
+
+	MesquiteParameter[] original, parameters;
+	int[] constraintMap, effectiveParamMapping;
+	boolean[] checked;
+	public SpecExtincCategModel(){
+		constraintMap = new int[6];
+		checked = new boolean[6];
+	}
+
+	/*
+	 *  The probability values are passed the probs array in the following order
+	 *  probs[0] = E0 = extinction probability in lineage starting at t in the past at state 0
+	 *  probs[1] = E1 = extinction probability in lineage starting at t in the past at state 1
+	 *  probs[2] = P0 = probability of explaining the data, given system is in state 0 at time t
+	 *  probs[3] = P1 = probability of explaining the data, given system in in state 1 at time t
+	 * @see mesquite.diverse.lib.DESystem#calculateDerivative(double, double[])
+	 */
+	public String toString(){
+		return MesquiteParameter.toString(parameters);
+	}
+	public String toStringForAnalysis(){
+		return MesquiteParameter.toStringForAnalysis(parameters);
+	}
+	public String toStringForScript(){
+		return MesquiteParameter.paramsToScriptString(parameters);
+	}
+	/*.................................................................................................................*/
+	public double[]calculateDerivative(double t,double probs[],double[] result){
+		// for clarity
+		final double extProb0 = probs[0];
+		final double extProb1 = probs[1];
+		final double dataProb0 = probs[2];
+		final double dataProb1 = probs[3];
+		final double lambda0 = parameters[0].getValue();
+		final double lambda1 = parameters[1].getValue();
+		final double mu0 = parameters[2].getValue();
+		final double mu1 = parameters[3].getValue();
+		final double q01 = parameters[4].getValue();
+		final double q10 = parameters[5].getValue();
+
+		result[0] = -(mu0+q01+lambda0)*extProb0 + lambda0*extProb0*extProb0 + mu0 + q01*extProb1; 
+		result[1] = -(mu1+q10+lambda1)*extProb1 + lambda1*extProb1*extProb1 + mu1 + q10*extProb0;            
+		result[2] = -(mu0+q01+lambda0)*dataProb0 + 2*lambda0*extProb0*dataProb0 + q01*dataProb1;
+		result[3] = -(mu1+q10+lambda1)*dataProb1 + 2*lambda1*extProb1*dataProb1 + q10*dataProb0;
+		return result;
+	}
+
+	public boolean isFullySpecified(){
+		return MesquiteParameter.numberSpecified(original) == 6;
+	}
+	public int numberSpecified(){
+		return MesquiteParameter.numberSpecified(original);
+	}
+	/*.................................................................................................................*/
+	public int numberEffectiveParameters(){
+		if (effectiveParamMapping == null)
+			return 0;
+		return effectiveParamMapping.length;
+	}
+
+	/*.................................................................................................................*/
+	public void setParams(MesquiteParameter[] params){
+		original = MesquiteParameter.cloneArray(params, original);
+		parameters = MesquiteParameter.cloneArray(params, parameters);
+		for (int i=0; i<6; i++){
+			int c = MesquiteParameter.getWhichConstrained(params, i);
+
+			if (c >= 0)
+				constraintMap[i] = c;
+			else
+				constraintMap[i] = i;
+			checked[i] = false;
+		}
+		int count = 0;
+		for (int i=0; i<6; i++){  //figuring out what are the unset parameters;
+			int mapee = constraintMap[i];
+			if (!checked[mapee])
+				if (!original[mapee].isCombinable())
+					count++;
+			checked[mapee] = true;
+		}
+		if (effectiveParamMapping == null || effectiveParamMapping.length != count)
+			effectiveParamMapping = new int[count];
+		count = 0;
+		for (int i=0; i<6; i++)
+			checked[i] = false;
+		for (int i=0; i<6; i++){  //figuring out what are the unset parameters;
+			int mapee = constraintMap[i];
+			if (!checked[mapee])
+				if (!original[mapee].isCombinable()){
+					effectiveParamMapping[count] = mapee;
+					count++;
+				}
+			checked[mapee] = true;
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void setParamValuesUsingConstraints(double[] params){
+		if (params == null || params.length == 0)
+			return;
+		if (params.length == 6 && effectiveParamMapping == null){
+			for (int i=0; i<6; i++)
+				parameters[i].setValue(params[i]);
+		}
+		else if (effectiveParamMapping== null){
+			MesquiteMessage.warnProgrammer("Sp/Ext setParamValuesUsingConstraints with effective params NULL");
+		}
+		else if (params.length != effectiveParamMapping.length){
+			MesquiteMessage.warnProgrammer("Sp/Ext setParamValuesUsingConstraints with effective params size mismatch " + params.length + " " + effectiveParamMapping.length);
+		}
+		else {
+			for (int i=0; i<params.length; i++) {
+				int mapee = effectiveParamMapping[i]; //find parameter representing constraint group
+				//now find all params constrained to it, and set them
+				for (int k = 0; k< parameters.length; k++){
+					if (constraintMap[k] == mapee)
+						parameters[k].setValue(params[i]);
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public MesquiteParameter[] getOriginalParams(MesquiteParameter[] params){
+		return MesquiteParameter.cloneArray(original, params);
+	}
+	/*.................................................................................................................*/
+	public MesquiteParameter[] getCurrentParams(MesquiteParameter[] params){
+		return MesquiteParameter.cloneArray(parameters, params);
+	}
+	/*.................................................................................................................*/
+	public double getSRate(int state) {
+		if (state == 0)
+			return parameters[0].getValue();
+		else if (state == 1)
+			return parameters[1].getValue();
+		else return MesquiteDouble.unassigned;
+	}
+
+	/*.................................................................................................................*/
+	public double getERate(int state) {
+		if (state == 0)
+			return parameters[2].getValue();
+		else if (state == 1)
+			return parameters[3].getValue();
+		else return MesquiteDouble.unassigned;
+	}
+	/*.................................................................................................................*/
+	public double getCRate(int state) {
+		if (state == 0)
+			return parameters[4].getValue();
+		else if (state == 1)
+			return parameters[5].getValue();
+		else return MesquiteDouble.unassigned;
+	}
+
+}
+
diff --git a/Source/mesquite/diverse/BiSSELikelihoodRatio/BiSSELikelihoodRatio.java b/Source/mesquite/diverse/BiSSELikelihoodRatio/BiSSELikelihoodRatio.java
new file mode 100644
index 0000000..12058e3
--- /dev/null
+++ b/Source/mesquite/diverse/BiSSELikelihoodRatio/BiSSELikelihoodRatio.java
@@ -0,0 +1,157 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.BiSSELikelihoodRatio;
+
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.RequiresExactlyCategoricalData;
+import mesquite.diverse.lib.*;
+import mesquite.diverse.BiSSELikelihood.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.duties.*;
+
+public class BiSSELikelihoodRatio extends NumForCharAndTreeDivers {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BiSSELikelihood.class, getName() + "  needs a method to calculate likelihoods.",
+		"The method to calculate likelihoods is arranged initially");
+		e.setSuppressListing(true);
+	}
+
+	BiSSELikelihood calcTask1, calcTask2;
+
+
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		calcTask1 = (BiSSELikelihood)hireEmployee(BiSSELikelihood.class, "Calculator for Unconstrained BiSSE Likelihood");
+		if (calcTask1 == null)
+			return sorry(getName() + " couldn't start because no likelihood calculator module obtained.");
+		calcTask2 = (BiSSELikelihood)hireEmployee(BiSSELikelihood.class, "Calculator for Constrained BiSSE Likelihood");
+		if (calcTask2 == null)
+			return sorry(getName() + " couldn't start because no likelihood calculator module obtained.");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+ 	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+ 	public String purposeOfEmployee(MesquiteModule mb){
+
+ 		if (calcTask1 == null || mb == calcTask1)  //will be null when first started
+ 			return "Unconstrained calculation of BiSSE likelihood";
+		if (calcTask2 == null || mb == calcTask2)
+ 			return "Constrained calculation of BiSSE likelihood";
+		return "";
+ 	}
+	public void initialize(Tree tree, CharacterDistribution charStates1) {
+		// TODO Auto-generated method stub
+	}
+	/*.................................................................................................................*/
+
+	public Snapshot getSnapshot(MesquiteFile file) {
+		final Snapshot temp = new Snapshot();
+		temp.addLine("getCalc1 ", calcTask1);
+		temp.addLine("getCalc2 ", calcTask2);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Returns first likelihood calculator", null, commandName, "getCalc1")) {
+			return calcTask1;
+		}
+		else if (checker.compare(getClass(), "Returns second likelihood calculator", null, commandName, "getCalc2")) {
+			return calcTask2;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+
+	/*------------------------------------------------------------------------------------------*/
+	public void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null)
+			return;
+		clearResultAndLastResult(result);
+		if (tree == null || charStates == null)
+			return;
+		if (!CategoricalDistribution.isBinaryNoMissing(charStates, tree)){
+			if (resultString!=null)
+	            resultString.setValue(getName() + " unassigned because the character is not binary or has missing data");
+			return;
+		}
+		MesquiteNumber num1 = new MesquiteNumber();
+		MesquiteNumber num2 = new MesquiteNumber();
+		calcTask1.calculateNumber(tree, charStates, num1, resultString);
+		calcTask2.calculateNumber(tree, charStates, num2, resultString);
+
+		result.setValue(num2);
+		result.subtract(num1);
+		result.setName("Ln Likelihood Difference");
+		result.copyAuxiliaries(new MesquiteNumber[]{num1, num2});
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+ 	public boolean returnsMultipleValues(){
+  		return true;
+  	}
+
+	/*------------------------------------------------------------------------------------------*/
+	public String getName() {
+		return "BiSSE Ln Likelihood Difference";
+	}
+	
+	public String getVeryShortName(){
+		return "BiSSE Ln Like. Diff.";
+	}
+
+	public String getAuthors() {
+		return "Peter E. Midford & Wayne P. Maddison";
+	}
+
+	public String getVersion() {
+		return "1.0";
+	}
+
+	public String getExplanation(){
+		return "Calculates the difference in log likelihoods between two BiSSE speciation/extinction models.";
+	}
+
+	/*.................................................................................................................*/
+	/** returns keywords related to what the module does, for help-related searches. */ 
+	public  String getKeywords()  {
+		return "diversification birth death";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+}
+
diff --git a/Source/mesquite/diverse/BiSSETreeCharSim/BiSSETreeCharSim.java b/Source/mesquite/diverse/BiSSETreeCharSim/BiSSETreeCharSim.java
new file mode 100644
index 0000000..e4a8a7f
--- /dev/null
+++ b/Source/mesquite/diverse/BiSSETreeCharSim/BiSSETreeCharSim.java
@@ -0,0 +1,757 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.BiSSETreeCharSim;
+
+
+
+import java.util.Vector;
+
+import mesquite.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.diverse.lib.*;
+
+/** ======================================================================== */
+public class BiSSETreeCharSim extends TreeCharSimulate {
+	protected RandomBetween rng;
+	protected double rateCharStateChange0 = 0.005; 
+	protected double rateCharStateChange1 = 0.005; 
+	protected double spnForState0 = 0.1;
+	protected double spnForState1 = 0.1;
+	protected double extForState0 = 0.05;
+	protected double extForState1 = 0.05;
+	private int ceilingSize = MesquiteInteger.unassigned;
+	private int treeSize = MesquiteInteger.unassigned;
+	private Vector goodTrees = new Vector();  // Don't need an actual tree vector here, since this only holds possible trees.
+	private Vector goodHistories = new Vector();  // save the history as well!
+
+	protected double prior1AtRoot = 0.5; //TODO: have toggle to set what is used
+	protected boolean keepAllExtinct = false;
+
+	//IF BOOLEAN SET THEN increment spnForState0 up by 0.01 or some such each new tree
+
+
+	protected double eventRate0;    //will be set to rateCharStateChange0+spnForState0+extForState0
+	protected double eventRate1;    //will be set to rateCharStateChange1+spnForState1+extForState1
+
+	//codes for the three types of events
+	protected static final int EXTINCTIONEVENT = 0;
+	protected static final int SPECIATIONEVENT = 1;
+	protected static final int CHANGEEVENT = 2;
+	protected static final int ERROREVENT = 3;
+
+
+	private double global0Rate;
+	private double global1Rate;
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng= new RandomBetween(1);
+
+		/*if (!MesquiteThread.isScripting()){//!
+			if (!showDialog())
+				return false;
+		}*/
+		addMenuItem("Rate of Change of Character change from state 0 to 1...", makeCommand("setCRate0",  this));
+		addMenuItem("Rate of Change of Character change from state 1 to 0...", makeCommand("setCRate1", this));
+		addMenuItem("Rate of Speciation if state 0...", makeCommand("setSRate0",  this));
+		addMenuItem("Rate of Speciation if state 1...", makeCommand("setSRate1",  this));
+		addMenuItem("Rate of Extinction if state 0...", makeCommand("setERate0",  this));
+		addMenuItem("Rate of Extinction if state 1...", makeCommand("setERate1",  this));
+	//	addMenuItem("Desired Tree size",makeCommand("setTreeSize",this));
+		addMenuItem("Maximum Tree size to search", makeCommand("setCeilingSize",this));
+	//	addMenuItem("Save Extinct lineages", makeCommand("toggleKeepAllExtinct",this));
+		addMenuItem("Prior on state at root...", makeCommand("setPrior",  this));
+		return true;
+	}
+	public boolean showDialog(Taxa taxa){
+		if (taxa != null)
+			treeSize = taxa.getNumTaxa();
+		ceilingSize = (int)(1.2*treeSize);
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dlog = new ExtensibleDialog(containerOfModule(), "Simulation Parameters",  buttonPressed);
+		dlog.defaultCancelLabel = null;
+		DoubleField[] value = new DoubleField[7];
+	//	IntegerField treeField;
+		IntegerField ceilingField;
+		//Checkbox keepExtinctBox;
+		value[0] = dlog.addDoubleField("Rate 0 -> 1: ", rateCharStateChange0, 6, 0, 100);
+		value[1] = dlog.addDoubleField("Rate 1 -> 0: ", rateCharStateChange1, 6, 0, 100);
+		value[2] = dlog.addDoubleField("Rate of Speciation with 0: ", spnForState0, 6, 0, 100);
+		value[3] = dlog.addDoubleField("Rate of Speciation with 1 :", spnForState1, 6, 0, 100);
+		value[4] = dlog.addDoubleField("Rate of Extinction with 0: ", extForState0, 6, 0, 100);
+		value[5] = dlog.addDoubleField("Rate of Extinction with 1: ", extForState1, 6, 0, 100);
+		
+		value[6] = dlog.addDoubleField("Prior probability of state 1 at root (? = use stationary freq.): ", MesquiteDouble.unassigned, 6, 0, 1.0);
+		value[6].setPermitUnassigned(true);
+		dlog.addLabel("Desired Tree Size: " + treeSize);
+		ceilingField = dlog.addIntegerField("Continue to Tree Size: ", ceilingSize,4,3,10000);
+		//keepExtinctBox = dlog.addCheckBox("Keep Extinct Lineages", keepAllExtinct);
+
+		dlog.completeAndShowDialog(true);
+
+		boolean ok = (dlog.query()==0);
+		boolean success = false;
+
+		if (ok) {
+			success = true;
+			for (int i=0; i<6; i++)
+				if (!MesquiteDouble.isCombinable(value[i].getValue()))
+					success = false;
+		//	if (!MesquiteInteger.isCombinable(treeField.getValue()))
+		//		success = false;
+			if (!MesquiteInteger.isCombinable(ceilingField.getValue()))
+				success = false;
+			if (success & (ceilingField.getValue()< treeSize))  // not necessarily best place to enforce this
+				success = false;
+			if (!success){
+				dlog.dispose();
+				return false;
+			}
+			rateCharStateChange0 = value[0].getValue();
+			rateCharStateChange1 = value[1].getValue();
+			spnForState0 = value[2].getValue();
+			spnForState1 = value[3].getValue();
+			extForState0 = value[4].getValue();
+			extForState1 = value[5].getValue();
+			prior1AtRoot = value[6].getValue();
+		//	treeSize = treeField.getValue();
+			ceilingSize = ceilingField.getValue();
+		//	keepAllExtinct = keepExtinctBox.getState();
+		}
+		else {
+			dlog.dispose();   
+			return false;
+		}
+		dlog.dispose();   
+		return true;
+	}
+	/*.................................................................................................................*/
+	public double stationaryFreq0() {  
+		double d = spnForState0-spnForState1+extForState1-extForState0;
+		double q01 = rateCharStateChange0;
+		double q10 = rateCharStateChange1;
+		if (Math.abs(d ) < 1e-100){
+			if (q01 + q10 == 0)
+				return 0.5;
+			return q10/(q01+q10);
+		}
+		double part = d - q01 - q10;
+		part = part*part + 4*d*q10;
+		if (part >=0)
+			part = Math.sqrt(part);
+		else
+			return MesquiteDouble.unassigned;
+		double plus = (q01 + q10 - d + part) / (-2*d);
+		double minus = (q01 + q10 - d - part) / (-2*d);
+		if (minus < 0 || minus >1)
+			return plus;
+		else if (plus < 0 || plus >1)
+			return minus;
+		else
+			return MesquiteDouble.unassigned;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCRate0 " + rateCharStateChange0);
+		temp.addLine("setCRate1 " + rateCharStateChange1);
+		temp.addLine("setSRate0 " + spnForState0);
+		temp.addLine("setSRate1 " + spnForState1);
+		temp.addLine("setERate0 " + extForState0);
+		temp.addLine("setERate1 " + extForState1);
+		temp.addLine("setPrior " + prior1AtRoot);
+		//temp.addLine("setTreeSize " + treeSize);
+		temp.addLine("setCeilingSize " + ceilingSize);
+		temp.addLine("toggleKeepAllExtinct " + MesquiteBoolean.toOffOnString(keepAllExtinct));
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the rate of change of the categorical character", "[number]", commandName, "setCRate0")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Evolution of Speciation Controlling Character 0 -> 1", rateCharStateChange0);
+			if (MesquiteDouble.isCombinable(s)) {
+				rateCharStateChange0 = s;
+				eventRate0 = rateCharStateChange0+spnForState0+extForState0;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the rate of change of the categorical character", "[number]", commandName, "setCRate1")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Evolution of Speciation Controlling Character 1 -> 0", rateCharStateChange1);
+			if (MesquiteDouble.isCombinable(s)) {
+				rateCharStateChange1 = s;
+				eventRate1 = rateCharStateChange1+spnForState1+extForState1;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the rate of speciation if 0", "[number]", commandName, "setSRate0")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Speciation if 0", spnForState0);
+			if (MesquiteDouble.isCombinable(s)) {
+				spnForState0 = s;
+				eventRate0 = rateCharStateChange0+spnForState0+extForState0;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the rate of speciation if 1", "[number]", commandName, "setSRate1")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Speciation if 1", spnForState1);
+			if (MesquiteDouble.isCombinable(s)) {
+				spnForState1 = s;
+				eventRate1 = rateCharStateChange1+spnForState1+extForState1;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the rate of extinction if 0", "[number]", commandName, "setERate0")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Extinction if 0", extForState0);
+			if (MesquiteDouble.isCombinable(s)) {
+				extForState0 = s;
+				eventRate0 = rateCharStateChange0+spnForState0+extForState0;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the rate of extinction if 1", "[number]", commandName, "setERate1")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Extinction if 1", extForState1);
+			if (MesquiteDouble.isCombinable(s)) {
+				extForState1 = s;
+				eventRate1 = rateCharStateChange1+spnForState1+extForState1;
+				prior1AtRoot =  1.0 - stationaryFreq0();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		/*
+		else if (checker.compare(this.getClass(), "Sets desired tree size", "[number]", commandName, "setTreeSize")) {
+			pos.setValue(0);
+			int s = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteInteger.queryInteger(containerOfModule(), "Root state", "Probability of state 1 at root", treeSize);
+			if (MesquiteInteger.isCombinable(s)) {
+				treeSize = s;
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}*/
+		else if (checker.compare(this.getClass(), "Sets tree size limit (to stop search)", "[number]", commandName, "setCeilingSize")) {
+			pos.setValue(0);
+			int s = MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteInteger.queryInteger(containerOfModule(), "Root state", "Probability of state 1 at root", ceilingSize);
+			if (MesquiteInteger.isCombinable(s) && (s >= treeSize)) {
+				ceilingSize = s;
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the prior probability of state 1 at root", "[number]", commandName, "setPrior")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Root state", "Probability of state 1 at root", prior1AtRoot);
+			if (MesquiteDouble.isCombinable(s)) {
+				prior1AtRoot = s;
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not extinct lineages are preserved", "[on or off]", commandName, "toggleKeepAllExtinct")) {
+			if (StringUtil.blank(arguments))
+				keepAllExtinct = !keepAllExtinct;
+			else {
+				String s = ParseUtil.getFirstToken(arguments, pos);
+				if ("on".equalsIgnoreCase(s))
+					keepAllExtinct = true;
+				else if  ("off".equalsIgnoreCase(s))
+					keepAllExtinct = false;
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	protected long countSpeciations = 0;
+	protected long countExtinctions = 0;
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	protected void flipState(long [] states, int index){
+		if (states[index] == 1L)
+			states[index] = 2L; //state 0 to 1
+		else
+			states[index] = 1L;//state 1 to 0
+	}
+	protected long numFlips;
+	/*.................................................................................................................*/
+	protected void addLengthToAllTerminals(MesquiteTree tree, int node, double increment, boolean[] taxaInTree){
+		if (tree.nodeIsTerminal(node)) {
+			int taxon = tree.taxonNumberOfNode(node);
+			if (taxaInTree[taxon]){    //not extinct (keepAllExtinct means save, not continue growing)
+				double current = tree.getBranchLength(node, MesquiteDouble.unassigned);
+				if (MesquiteDouble.isCombinable(current))
+					tree.setBranchLength(node, current + increment, false);
+				else
+					tree.setBranchLength(node, increment, false);  	 	
+			}
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			addLengthToAllTerminals(tree, d, increment, taxaInTree);
+		}
+	}
+	/*.................................................................................................................*/
+	// This sums all the change rates of all the active terminal nodes in the tree
+	protected double getGlobalRate(Tree tree,int node,boolean[] taxaInTree,long[] localHistory){
+		if (tree.nodeIsTerminal(node)){
+			int taxon = tree.taxonNumberOfNode(node);
+			if (taxaInTree[taxon]){   //not extinct
+				if (localHistory[node] == 1L){ //1L is state 0
+					global0Rate += eventRate0;
+					return eventRate0;
+				}
+				else{   //should be 2L, which is state 1
+					if (localHistory[node] != 2L)
+						MesquiteMessage.warnProgrammer("Character history has a bad state in getGlobalRate at " + node);
+					global1Rate += eventRate1;
+					return eventRate1;
+				}
+			}
+			else
+				return 0;
+		}
+		else {
+			double result = 0;
+			for(int d=tree.firstDaughterOfNode(node);tree.nodeExists(d);d=tree.nextSisterOfNode(d))
+				result += getGlobalRate(tree,d,taxaInTree,localHistory);
+			return result;
+		}
+	}
+	/*.................................................................................................................*/    
+	// generates the time to the next event on the tree based on a negative exponential distribution
+	protected double nextTime(double globalRate){
+		return -1*Math.log(rng.nextDouble())/globalRate; 
+	}
+
+	/*.................................................................................................................*/
+	// this picks the node where the next event is occurring; the chance of choosing a node
+	// is proportional to the sum of its rates
+	protected int nextNode(Tree tree,int node,boolean [] taxaInTree, long[] localHistory,double globalRate,double limit, MesquiteDouble sum){
+		if (tree.nodeIsTerminal(node)){
+			int taxon = tree.taxonNumberOfNode(node);
+			if (taxaInTree[taxon]){   //not extinct
+				if (localHistory[node] == 1L){ //1L is state 0
+					sum.add(eventRate0/globalRate);
+					if (sum.getValue()>limit)
+						return node;
+					else
+						return -1;
+				}
+				else{   //should be 2L, which is state 1
+					if (localHistory[node] != 2L)
+						MesquiteMessage.warnProgrammer("Character history has a bad state in nextNode at " + node);
+					sum.add(eventRate1/globalRate);
+					if (sum.getValue()>limit)
+						return node;
+					else
+						return -1;                
+				}
+			}
+			else
+				return -1;
+		}
+		else {
+			for(int d=tree.firstDaughterOfNode(node);tree.nodeExists(d);d=tree.nextSisterOfNode(d)){
+				int result = nextNode(tree,d,taxaInTree,localHistory,globalRate,limit,sum);
+				if (result>0)
+					return result;
+			}
+			return -1;
+		}
+	}
+
+	/*.................................................................................................................*/
+	//choose which of the three event types it will be
+	protected int nextChange(long [] localHistory, double limit,int node){
+		if (node<0)
+			return ERROREVENT;
+		if (localHistory[node] == 1L){ //1L is state 0
+			if (rateCharStateChange0/eventRate0 > limit)
+				return CHANGEEVENT;
+			else if (((rateCharStateChange0+spnForState0)/eventRate0) > limit)
+				return SPECIATIONEVENT;
+			else
+				return EXTINCTIONEVENT;
+		}
+		else {  //should be 2L, which is state 1
+			if (localHistory[node] != 2L)
+				MesquiteMessage.warnProgrammer("Character history has a bad state in nextChange at " + node);
+			if (rateCharStateChange1/eventRate1 > limit)
+				return CHANGEEVENT;
+			else if (((rateCharStateChange1+spnForState1)/eventRate1) > limit)
+				return SPECIATIONEVENT;                
+			else
+				return EXTINCTIONEVENT;
+		}
+	}
+
+
+	/*.................................................................................................................*/
+	protected void executeEvent(MesquiteTree tree,int eventNode,int eventChange, boolean [] taxaInTree,long [] localHistory,MesquiteInteger countOfSpecies){
+		switch (eventChange){
+		case EXTINCTIONEVENT:{
+			int it = tree.taxonNumberOfNode(eventNode);
+			if (it >= 0 && taxaInTree[it]){
+				if (!keepAllExtinct){
+					tree.deleteClade(eventNode, false);
+					countOfSpecies.decrement();
+				}
+				taxaInTree[it] = false;
+				countExtinctions++;
+				CommandRecord.tick("Went extinct at node " + eventNode + " ; total number of species " + countOfSpecies + "; total speciations: " + countSpeciations  + "; total extinctions: " + countExtinctions );
+			}
+			break;
+		}
+		case SPECIATIONEVENT:{
+			int taxon = tree.taxonNumberOfNode(eventNode);
+			if (taxon >=0 && taxaInTree[taxon]){
+				long statesAtNode = localHistory[eventNode];
+				tree.splitTerminal(taxon, -1, false);
+				countSpeciations++;
+				int firstD = tree.firstDaughterOfNode(eventNode);
+				int lastD = tree.lastDaughterOfNode(eventNode);
+				localHistory[firstD] = statesAtNode;
+				localHistory[lastD] = statesAtNode;
+				tree.setBranchLength(firstD, 0, false);
+				tree.setBranchLength(lastD, 0, false);
+				taxaInTree[tree.taxonNumberOfNode(firstD)] = true;
+				taxaInTree[tree.taxonNumberOfNode(lastD)] = true;
+				countOfSpecies.increment();
+				CommandRecord.tick("Speciated at node " + eventNode + " ; total number of species " + countOfSpecies + "; total speciations: " + countSpeciations  + "; total extinctions: " + countExtinctions );
+			}
+			else{
+				MesquiteMessage.warnProgrammer("Failed to speciate; taxon is " + taxon + "eventNode is " + eventNode);
+			}
+			break;
+		}
+		case CHANGEEVENT:{
+			flipState(localHistory, eventNode);
+			numFlips++;
+			break;
+		}
+		}
+	}
+
+
+
+	/*.................................................................................................................*/
+	public String getDataType(){
+		return CategoricalData.DATATYPENAME;
+	}
+
+	protected MesquiteInteger countOfSpecies = new MesquiteInteger(0);
+	protected MesquiteDouble accumulator = new MesquiteDouble(0.0);
+
+	/*.................................................................................................................*/
+	public  void doSimulation(Taxa taxa, int replicateNumber, ObjectContainer treeContainer, ObjectContainer characterHistoryContainer, MesquiteLong seed){
+		if (!initialized)
+			initialize(taxa);
+		//save random seed used to make tree under tree.seed for use in recovering later
+		rng.setSeed(seed.getValue());
+		int originalNumTaxa = taxa.getNumTaxa();
+		
+		if (MesquiteInteger.isUnassigned(treeSize))
+		    treeSize = originalNumTaxa;
+		if (MesquiteInteger.isUnassigned(ceilingSize))
+		    ceilingSize = (treeSize/5)*6;   //integer version of add 20%
+
+		MesquiteTree tree = null;
+		CategoricalHistory charHistory = null;
+		long [] localHistory = null;
+		
+		int numTaxa = taxa.getNumTaxa();
+		if (numTaxa < ceilingSize)
+			taxa.addTaxa(numTaxa-1, ceilingSize-numTaxa, false);  // avoid error at end?
+		numTaxa = taxa.getNumTaxa();
+		if (numTaxa < ceilingSize)
+			MesquiteMessage.warnProgrammer("Taxa block failed to grow to ceiling size; numTaxa = " + numTaxa);
+		Object t = treeContainer.getObject();
+		if (t == null || !(t instanceof MesquiteTree))
+			tree = new MesquiteTree(taxa);
+		else
+			tree = (MesquiteTree)t;
+		Object c = characterHistoryContainer.getObject();
+		if (c == null || !(c instanceof CategoricalHistory)){
+			//charHistory = new CategoricalHistory(taxa);  // remove
+			localHistory = new long[tree.getNumNodeSpaces()];
+			for(int i=0;i<localHistory.length;i++)
+				localHistory[i]= CategoricalState.unassigned;
+		}
+		else { 
+			charHistory = (CategoricalHistory)c;
+			localHistory = new long[charHistory.getNumTaxa()];
+			for(int i=0;i<localHistory.length;i++){
+				localHistory[i]= charHistory.getState(i);
+			}
+		}
+
+		int attempts = 0;
+		boolean done = false;
+		boolean wentExtinct = false;
+		int patience = 100; //TODO: make this user settable
+		boolean[] taxaInTree = new boolean[taxa.getNumTaxa()];
+		for (int i=0; i< taxaInTree.length; i++)
+			taxaInTree[i] = false;
+		long state = 1L; //state 0
+		String hitsString = "";
+		while (attempts < patience && !done){
+			countSpeciations = 0;
+			countExtinctions = 0;
+			countOfSpecies.setValue(2);
+			goodTrees.clear();
+			goodHistories.clear();
+
+			wentExtinct = false;
+			state = 1L; //state 0
+			if (rng.nextDouble()<prior1AtRoot)
+				state = 2L; //state 1
+			for (int i=0; i<tree.getNumNodeSpaces(); i++){  //state 0
+				//charHistory.setState(i, state);
+				localHistory[i] = state;
+			}
+
+			tree.setToDefaultBush(2, false);
+			for (int i=0; i< taxaInTree.length; i++)
+				taxaInTree[i] = false;
+			taxaInTree[0] = true;
+			taxaInTree[1] = true;
+			tree.setAllBranchLengths(0, false);
+
+			double generations = 0;
+			CommandRecord.tick("Attempt " + (attempts+1) + " to simulate tree ");
+			numFlips =0;
+			hitsString = "";
+			while (countOfSpecies.getValue()<numTaxa && !wentExtinct){
+				global0Rate = 0;
+				global1Rate = 0;
+				double globalRate = getGlobalRate(tree,tree.getRoot(),taxaInTree,localHistory);
+				double eventTime = nextTime(globalRate);
+				accumulator.setValue(0.0);
+				double limit = rng.nextDouble();
+				int eventNode = nextNode(tree,tree.getRoot(),taxaInTree,localHistory,globalRate,limit,accumulator);
+				limit = rng.nextDouble();
+				int eventChange = nextChange(localHistory, limit, eventNode);
+				if (eventChange == ERROREVENT)
+					discreetAlert("BiSSE simulation failed (no nextnode found).");
+				generations += eventTime;
+				addLengthToAllTerminals(tree,tree.getRoot(),eventTime,taxaInTree);
+				executeEvent(tree,eventNode,eventChange,taxaInTree,localHistory,countOfSpecies);
+				if (countOfSpecies.getValue() == 0 || tree.numberOfTerminalsInClade(tree.getRoot()) == 0){
+					wentExtinct = true;             
+					CommandRecord.tick("Extinction event (species in tree currently:  " + countOfSpecies.getValue() + ") [attempt: "+ (attempts+1) + "] ");
+				}
+				else if (eventChange == SPECIATIONEVENT){
+					if (countOfSpecies.getValue() == treeSize){   // save a copy of the tree
+						MesquiteTree ct = tree.cloneTree(); 
+						globalRate = getGlobalRate(tree,tree.getRoot(),taxaInTree,localHistory);
+						double nextTime = rng.nextDouble()*nextTime(globalRate);
+						addLengthToAllTerminals(ct,ct.getRoot(),nextTime,taxaInTree);
+						goodTrees.add(ct);
+						goodHistories.add(localHistory.clone());
+						hitsString = hitsString + "\t" + generations;
+					}
+					else if (keepAllExtinct){  // keeping extinct means numTaxa tracks countSpeciations
+						if (countSpeciations > (numTaxa - 2)){
+							taxa.addTaxa(numTaxa-1, 5, false);  //notify true or false?
+							boolean [] newTaxaInTree = new boolean[numTaxa+5];
+							int i;
+							for(i=0;i<taxaInTree.length;i++)
+								newTaxaInTree[i]=taxaInTree[i];
+							for(;i<newTaxaInTree.length;i++)
+								newTaxaInTree[i] = false;
+							taxaInTree = newTaxaInTree;
+							long[] newLocalHistory = new long[tree.getNumNodeSpaces()+20];
+							for(i=0;i<tree.getNumNodeSpaces();i++)
+								newLocalHistory[i] = localHistory[i];
+							for(;i<newLocalHistory.length;i++)
+								newLocalHistory[i] = CategoricalState.unassigned;
+						}
+					}
+
+					CommandRecord.tick("Speciation event (species in tree currently:  " + countOfSpecies.getValue()  + ") [attempt: "+ (attempts+1) + "] ");
+				}
+			}
+			if (!wentExtinct){
+				done = true;
+
+				tree.reshuffleTerminals(rng);
+			}
+			attempts++;
+		}
+		if (!done){
+			tree.setToDefaultBush(2, false);
+			tree.setAllBranchLengths(0, false);
+			for(int i=0;i<localHistory.length;i++)
+				localHistory[i]= CategoricalState.unassigned;
+			goodTrees.clear();
+			MesquiteMessage.warnUser("Attempt to simulate speciation/extinction failed because clade went entirely extinct " + patience + " times");
+		}
+		else  {
+			hitsString = "";
+			if (goodTrees.size() == 0)
+				MesquiteMessage.warnProgrammer("Problem with saving trees of predetermined size - vector is empty");
+			else if (goodTrees.size() ==1){
+				tree = (MesquiteTree)goodTrees.get(0);
+				charHistory = new CategoricalHistory(taxa);
+				charHistory.setStates((long []) goodHistories.get(0));
+			}
+			else {
+				int treeCount = goodTrees.size();
+				final double incr = 1.0/(double)treeCount;
+				final double choose = rng.nextDouble();
+				int acc = 0;
+				boolean d = false;
+				while (!d){
+					acc++;
+					if (choose < (acc*incr)){
+						d = true;
+					}
+				}
+				MesquiteMessage.println("Chose " + acc + " of " + treeCount + " trees.");
+				tree = (MesquiteTree)goodTrees.get(acc-1);
+				if (true){
+				int[] terminals = tree.getTerminalTaxa(tree.getRoot());
+				for (int i =0; i< terminals.length; i++){
+					if (terminals[i]>= treeSize){ //taxon that needs packing to lower value
+						final int k = findVacant(terminals, treeSize);
+						if (k >=0){
+							int node = tree.nodeOfTaxonNumber(terminals[i]);
+							tree.setTaxonNumber(node, k, false);
+							terminals[i] = k;
+						}
+					}
+				}
+
+				tree.reshuffleTerminals(rng);
+				}
+				charHistory = new CategoricalHistory(taxa);
+				charHistory.setStates((long []) goodHistories.get(acc-1));
+			}
+			MesquiteMessage.println("Tree and character " + (replicateNumber +1) + " successfully evolved.");
+			tree.setName("Sim. sp/ext with char. " + (replicateNumber +1) + " [#ext. " + countExtinctions + " #st.chg. " + numFlips + " root " + CategoricalState.toString(state) + "]" + hitsString);
+			if (!keepAllExtinct){
+				int taxSize = MesquiteInteger.minimum(treeSize, originalNumTaxa); 
+			    if (originalNumTaxa ==3)   //oops, originalNumTaxa was the uninformative default, trust treeSize here
+			        taxSize = treeSize; 
+				if (taxSize < taxa.getNumTaxa())
+					taxa.deleteTaxa(taxSize, taxa.getNumTaxa()-taxSize, false);
+			}
+		}
+		tree.resetTaxaInfo();
+
+		treeContainer.setObject(tree);
+		characterHistoryContainer.setObject(charHistory);
+		seed.setValue(rng.nextLong());  //see for next time
+
+	}
+	public int findVacant(int[] terminals, int targetTreeSize){
+		for (int i=0; i<targetTreeSize; i++)
+			if (IntegerArray.indexOf(terminals, i)<0)
+				return i;
+		return -1;
+	}
+	boolean initialized = false;
+	public void initialize(Taxa taxa){
+		initialized = true;
+		if (!MesquiteThread.isScripting()){
+		    showDialog(taxa);
+		}
+		eventRate0 = rateCharStateChange0+spnForState0+extForState0;
+		eventRate1 = rateCharStateChange1+spnForState1+extForState1;
+		if (prior1AtRoot == MesquiteDouble.unassigned)
+			prior1AtRoot =  1.0 - stationaryFreq0();
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "BiSSE Trees & Characters";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Generates tree by a speciation/extinction model in which a character controls rates of speciation/extinction.  Time to next event drawn from negative exponential distribution." ;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return "Rates: " + MesquiteDouble.toStringDigitsSpecified(rateCharStateChange0, 4) + "," + MesquiteDouble.toStringDigitsSpecified(rateCharStateChange1, 4) + "/" + MesquiteDouble.toStringDigitsSpecified(spnForState0, 4) + "," +MesquiteDouble.toStringDigitsSpecified(spnForState1, 4) + "/" +MesquiteDouble.toStringDigitsSpecified(extForState0, 4) + "," +MesquiteDouble.toStringDigitsSpecified(extForState1, 4);
+	}
+
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/diverse/BirthDeathTrees/BirthDeathTrees.java b/Source/mesquite/diverse/BirthDeathTrees/BirthDeathTrees.java
new file mode 100644
index 0000000..87e2641
--- /dev/null
+++ b/Source/mesquite/diverse/BirthDeathTrees/BirthDeathTrees.java
@@ -0,0 +1,279 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.BirthDeathTrees;
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class BirthDeathTrees extends TreeSimulate {
+	RandomBetween rng;
+	final double defaultIncrement = 0.001;
+	double increment = 0.001;
+	double birthRate = 0.3;
+	double birthProbPerIncrement = birthRate*increment;
+	double deathRate = 0.1;
+	double deathProbPerIncrement = deathRate*increment;
+	MesquiteDouble b, d;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng= new RandomBetween(1);
+		b = new MesquiteDouble(birthRate);
+		d = new MesquiteDouble(deathRate);
+		if (!MesquiteThread.isScripting()){
+			if (!askRates())
+				return false;
+		}
+		addMenuItem("Birth and Death Rates (simulation)...", makeCommand("setRates",  this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	private boolean askRates(){
+		boolean ok = MesquiteDouble.queryTwoDoubles(containerOfModule(), "Speciation (birth) and Extinction (death) rates", 
+				"Speciation (birth) rate", b, "Extinction (death) rate", d);
+		if (ok){
+			if (b.isCombinable())
+				birthRate = b.getValue();
+			if (d.isCombinable())
+				deathRate = d.getValue();
+		}
+		return ok;
+	}
+	void calculateRates(int numTaxa){
+		double maxRate = MesquiteDouble.maximum(birthRate, deathRate);
+		if (maxRate>1.0){
+			increment = 0.001/maxRate/Math.sqrt((double)numTaxa);  //narrow time slice as number of taxa increases
+		}
+		else
+			increment = defaultIncrement/Math.sqrt((double)numTaxa);
+		birthProbPerIncrement = birthRate*increment;
+		deathProbPerIncrement = deathRate*increment;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setRates " + MesquiteDouble.toString(birthRate) + " " + MesquiteDouble.toString(deathRate));
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the birth and death rates", "[number][number]", commandName, "setRates")) {
+			pos.setValue(0);
+			if (StringUtil.blank(arguments)){
+				if (!MesquiteThread.isScripting()){
+					askRates();
+					if (!MesquiteThread.isScripting()) {
+						parametersChanged();
+					}
+				}
+				return null;
+			}
+			double s = MesquiteDouble.fromString(arguments, pos);
+			double e = MesquiteDouble.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(s))
+				birthRate = s;
+			if (MesquiteDouble.isCombinable(e))
+				deathRate = e;
+
+			if (!MesquiteThread.isScripting()) {
+				parametersChanged();
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	long countSpeciations = 0;
+	long countExtinctions = 0;
+	/*.................................................................................................................*/
+	private boolean goExtinctIfUnlucky(Taxa taxa, boolean[] taxaInTree, MesquiteTree tree, MesquiteInteger countOfSpecies){
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+			if (taxaInTree[it]){
+				int node = tree.nodeOfTaxonNumber(it);
+				double probability = deathProbPerIncrement;
+				if (rng.nextDouble()<probability) {
+
+					tree.deleteClade(node, false);
+					countOfSpecies.decrement();
+
+					taxaInTree[it] = false;
+					countExtinctions++;
+					CommandRecord.tick("Went extinct at node " + node + " ; total number of species " + countOfSpecies + "; total speciations: " + countSpeciations  + "; total extinctions: " + countExtinctions );
+					if (countOfSpecies.getValue() == 0 || tree.numberOfTerminalsInClade(tree.getRoot()) == 0)
+						return true;
+				}
+			}
+		}
+		return false;
+
+	}
+
+	/*.................................................................................................................*/
+	private void speciateIfLucky(MesquiteTree tree, int node, boolean[] taxaInTree, MesquiteInteger countOfSpecies, int numTaxa){
+		if (tree.nodeIsTerminal(node) && MesquiteDouble.isCombinable(tree.getBranchLength(node))) {  //length will be uncombinable if this was just a daughter species
+			if (countOfSpecies.getValue()<numTaxa) {
+				int taxon = tree.taxonNumberOfNode(node);
+				if (taxaInTree[taxon]){ //not extinct
+					double probability = birthProbPerIncrement;
+
+					if (rng.nextDouble()<probability) {
+						tree.splitTerminal(taxon, -1, false);
+						countSpeciations++;
+						int firstD = tree.firstDaughterOfNode(node);
+						int lastD = tree.lastDaughterOfNode(node);
+						taxaInTree[tree.taxonNumberOfNode(firstD)] = true;
+						taxaInTree[tree.taxonNumberOfNode(lastD)] = true;
+						countOfSpecies.increment();
+						CommandRecord.tick("Speciated at node " + node + " ; total number of species " + countOfSpecies + "; total speciations: " + countSpeciations  + "; total extinctions: " + countExtinctions );
+					}
+				}
+			}
+		}
+		else
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (countOfSpecies.getValue()<numTaxa)
+					speciateIfLucky(tree, d, taxaInTree, countOfSpecies, numTaxa);
+			}
+	}
+	/*.................................................................................................................*/
+	private void addLengthToAllTerminals(MesquiteTree tree, int node, double increment){
+		if (tree.nodeIsTerminal(node)) {
+			double current = tree.getBranchLength(node, MesquiteDouble.unassigned);
+			if (MesquiteDouble.isCombinable(current))
+				tree.setBranchLength(node, current + increment, false);
+			else
+				tree.setBranchLength(node, increment, false);  	 		
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			addLengthToAllTerminals(tree, d, increment);
+		}
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		return MesquiteInteger.infinite;
+	}
+	/*.................................................................................................................*/
+	public Tree getSimulatedTree(Taxa taxa, Tree baseTree, int treeNumber, ObjectContainer extra, MesquiteLong seed) { //todo: should be two seeds passed!
+		//save random seed used to make tree under tree.seed for use in recovering later
+		if (seed != null)
+			rng.setSeed(seed.getValue());
+		if (taxa == null)
+			return null;
+		if (baseTree==null || !(baseTree instanceof MesquiteTree))
+			baseTree = new MesquiteTree(taxa);
+		MesquiteTree tree = ((MesquiteTree)baseTree);
+		
+
+		boolean[] taxaInTree = new boolean[taxa.getNumTaxa()];
+		for (int i=0; i< taxaInTree.length; i++)
+			taxaInTree[i] = false;
+		
+		int attempts = 0;
+		boolean done = false;
+		boolean wentExtinct = false;
+		int patience = 100; //TODO: make this user settable
+		int numTaxa = taxa.getNumTaxa();
+		long generations = 0;
+	
+		while (attempts < patience && !done){
+			wentExtinct = false;
+			tree.setToDefaultBush(2, false);
+			for (int i=0; i< taxaInTree.length; i++)
+				taxaInTree[i] = false;
+			taxaInTree[0] = true;
+			taxaInTree[1] = true;
+			tree.setAllBranchLengths(0, false);
+			MesquiteInteger countOfSpecies = new MesquiteInteger(2);
+			countSpeciations = 0;
+			countExtinctions = 0;
+			generations = 0;
+			CommandRecord.tick("Attempt " + (attempts+1) + " to simulate tree ");
+			increment = defaultIncrement;
+			addLengthToAllTerminals(tree, tree.getRoot(), increment);
+			calculateRates(1);
+			while (countOfSpecies.getValue()<numTaxa && !wentExtinct){
+				generations++;
+				boolean allExtinct = goExtinctIfUnlucky(taxa, taxaInTree, tree, countOfSpecies);
+
+				if (allExtinct){
+					wentExtinct = true;
+					CommandRecord.tick("All Extinct [attempt: "+ (attempts+1) + "] ");
+				}
+				else {
+					speciateIfLucky(tree, tree.getRoot(), taxaInTree, countOfSpecies, numTaxa);
+
+					addLengthToAllTerminals(tree, tree.getRoot(), increment);
+
+					CommandRecord.tick("Speciation event (species in tree currently:  " + countOfSpecies.getValue()  + ") [attempt: "+ (attempts+1) + "] ");
+				}
+				calculateRates(countOfSpecies.getValue());
+		}
+			if (!wentExtinct)
+				done = true;
+			attempts++;
+		}
+		tree.reshuffleTerminals(rng); //added after 1.03
+
+		tree.setName("Sim. sp/ext " + (treeNumber +1));// + hitsString);
+		tree.setAnnotation("(#extinctions " + countExtinctions + "; generations: " + generations + ")", false);// + hitsString);
+
+		if (seed != null)
+			seed.setValue(rng.nextLong());  //see for next time
+		return tree;
+	}
+
+	public void initialize(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Birth/Death Process Trees";
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Generates tree by simple birth/death model with a constant rate of speciation (birth) and of extinction (death).";
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return "Speciation (birth) rate: " + birthRate + "; Extinction (death) rate: " + deathRate;
+	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/diverse/CharAssocDivViewer/CharAssocDivViewer.java b/Source/mesquite/diverse/CharAssocDivViewer/CharAssocDivViewer.java
new file mode 100644
index 0000000..05459aa
--- /dev/null
+++ b/Source/mesquite/diverse/CharAssocDivViewer/CharAssocDivViewer.java
@@ -0,0 +1,326 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.CharAssocDivViewer;
+/*~~  */
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.diverse.lib.*;
+
+
+public class CharAssocDivViewer extends TreeWindowAssistantA    {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumForCharAndTreeDivers.class, getName() + "  needs a method to calculate diversification statistics.",
+		"You can choose the diversification calculation initially or under the Diversification Measure submenu.");
+		e.setPriority(2);
+		EmployeeNeed ew = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	/*.................................................................................................................*/
+	int current = 0;
+	Tree tree;
+	NumForCharAndTreeDivers numberTask;
+	CharSourceCoordObed characterSourceTask;
+	Taxa taxa;
+	Class stateClass;
+	MesquiteWindow containingWindow;
+	CADPanel panel;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	///CharSourceCoord contTask;
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask = (NumForCharAndTreeDivers)hireEmployee(NumForCharAndTreeDivers.class, "Calculator of association between character and diversification");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		makeMenu("Diversification(Ch)");
+		ntC =makeCommand("setCalculator",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumForCharAndTreeDivers.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Diversification Measure", ntC, NumForCharAndTreeDivers.class);
+			mss.setSelected(numberTaskName);
+		}
+
+		//	contTask = (CharSourceCoord)hireCompatibleEmployee(CharSourceCoord.class, ContinuousState.class, "Source of clade state frequency data");
+
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numberTask.getCompatibilityTest(), "Source of  characters (for " + getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		final MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			containingWindow = (MesquiteWindow)f;
+			containingWindow.addSidePanel(panel = new CADPanel(), 200);
+		}
+
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		addMenuItem( "Close Character-Associated Diversification Analysis", makeCommand("close",  this));
+		addMenuItem( "-", null);
+
+		return true;
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		final Snapshot temp = new Snapshot();
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("getCharSource ", characterSourceTask); 
+		temp.addLine("setCharacter " + CharacterStates.toExternal(current)); 
+		temp.addLine("doCounts");
+
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the module that calculates diversification statistics", "[name of module]", commandName, "setCalculator")) {
+			final NumForCharAndTreeDivers temp =  (NumForCharAndTreeDivers)replaceEmployee(NumForCharAndTreeDivers.class, arguments, "Diversification Measure", numberTask);
+			if (temp!=null) {
+					CompatibilityTest test = temp.getCompatibilityTest();
+				if (!MesquiteThread.isScripting()){
+					if (test != null && stateClass != null){
+						if (!test.isCompatible(stateClass, getProject(), this)){
+							discreetAlert( "The calculation module \"" +temp.getName() + "\" is not compatible with the current data type");
+							return null;
+						}
+					}
+					
+				}
+				characterSourceTask.setHiringCondition(test);
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					doCounts();
+				return numberTask;
+			}
+		}
+
+		else   	if (checker.compare(this.getClass(), "Returns employee", null, commandName, "getCharSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " Character to use for Diversification analysis ");
+			if (MesquiteInteger.isCombinable(ic) && ic != current) {
+				current = ic;
+				doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				current = ic;
+
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				current = ic;
+
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Provokes Calculation", null, commandName, "doCounts")) {
+			doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Quits", null, commandName, "close")) {
+			if (panel != null && containingWindow != null)
+				containingWindow.removeSidePanel(panel);
+			iQuit();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	long oldTreeID = -1;
+	long oldTreeVersion = 0;
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree==null)
+			return;
+		this.tree=tree;
+		taxa = tree.getTaxa();
+		if ((tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion) && !MesquiteThread.isScripting()) {
+			doCounts();  //only do counts if tree has changed
+		}
+		oldTreeID = tree.getID();
+		oldTreeVersion = tree.getVersionNumber();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (numberTask!=null && !MesquiteThread.isScripting())
+			doCounts();
+	}
+	String blankIfNull(String s){
+		if (s == null)
+			return "";
+		return s;
+	}
+
+	public String nameForWritableResults(){
+		if (numberTask == null)
+			return null;
+		return numberTask.getName();
+	}
+	public boolean suppliesWritableResults(){
+		if (numberTask == null)
+			return false;
+		return true;
+	}
+	public Object getWritableResults(){
+		return lastResult;
+	}
+	public Object getResultsHeading(){
+		return lastResult;
+	}
+	CharacterDistribution contMatrix = null;
+	/*.................................................................................................................*/
+	public void doCounts() {
+		if (taxa == null || panel == null)
+			return;
+
+		MesquiteNumber result = new MesquiteNumber();
+		MesquiteString rs = new MesquiteString();
+		CharacterDistribution states = characterSourceTask.getCharacter(taxa, current);
+		if (states == null )
+			rs.setValue("Sorry, no character was not obtained.  The diversification analysis could not be completed.");
+		stateClass = states.getStateClass();
+		//		window.setText("");
+		clearLastResult();
+		panel.setStatus(true);
+		panel.repaint();
+		panel.setText("\nAnalysis of speciation and extinction as associated with the states of a character\n");
+		panel.append("\nCalculation: " + numberTask.getNameAndParameters() + "\n");
+		panel.append("\nTree: " + tree.getName() );
+		panel.append("\nCharacter: " + characterSourceTask.getCharacterName(taxa, current) +  "\n");
+			numberTask.calculateNumber(tree, states, result, rs);
+			saveLastResult(result);
+			saveLastResultString(rs);
+		
+		panel.append("\n\n" + blankIfNull(result.getName()) + '\t' + result);
+		MesquiteNumber[] aux = result.getAuxiliaries();
+		if (aux != null){
+			panel.append("\n");
+			for (int i = 0; i< aux.length; i++){
+				panel.append('\n' + blankIfNull(aux[i].getName()) + '\t' + aux[i].toString());
+			}
+		}
+		else
+			panel.append("\n\n" + rs);
+
+		panel.append("\n\n" + rs);
+		panel.append("\n\nExplanation of calculation:\n" + numberTask.getExplanation());
+		panel.setStatus(false);
+		panel.repaint();
+		//		window.append("\n\n  " + rs);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character-Associated Diversification";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates analyses for the effect of a character on diversification (speciation/extinction)." ;
+	}
+	public void endJob() {
+		if (panel != null && containingWindow != null)
+			containingWindow.removeSidePanel(panel);
+		super.endJob();
+	}
+}
+
+class CADPanel extends MousePanel{
+	TextArea text;
+	Font df = new Font("Dialog", Font.BOLD, 14);
+	boolean calculating = false;
+	int labelHeight = 52;
+	public CADPanel(){
+		super();
+		text = new TextArea(" ", 50, 50, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		setLayout(null);
+		add(text);
+		text.setLocation(0,labelHeight);
+		text.setVisible(true);
+		text.setEditable(false);
+		setBackground(Color.darkGray);
+		text.setBackground(Color.white);
+	}
+	public void setStatus(boolean calculating){
+		this.calculating = calculating;
+	}
+	public void setText(String t){
+		text.setText(t);
+	}
+	public void append(String t){
+		text.append(t);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		text.setSize(w, h-labelHeight);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		text.setSize(w, h-labelHeight);
+	}
+	public void paint(Graphics g){
+		g.setFont(df);
+
+		if (!calculating){
+			g.setColor(Color.white);
+			g.drawString("Character-Associated", 8, 20);
+			g.drawString("Diversification Analysis", 8, 46);
+		}
+		else{
+			g.setColor(Color.black);
+			g.fillRect(0,0, getBounds().width, 50);
+			g.setColor(Color.red);
+			g.drawString("Diversification Analysis", 8, 20);
+			g.drawString("Calculating...", 8, 46);
+		}
+	}
+}
+
diff --git a/Source/mesquite/diverse/CharIndepDivViewer/CharIndepDivViewer.java b/Source/mesquite/diverse/CharIndepDivViewer/CharIndepDivViewer.java
new file mode 100644
index 0000000..6e3c4c5
--- /dev/null
+++ b/Source/mesquite/diverse/CharIndepDivViewer/CharIndepDivViewer.java
@@ -0,0 +1,243 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.CharIndepDivViewer;
+/*~~  */
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.diverse.lib.*;
+
+
+public class CharIndepDivViewer extends TreeWindowAssistantA    {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTreeDivers.class, getName() + "  needs a method to calculate diversification statistics.",
+		"The method is arranged initially");
+		e.setPriority(2);
+	}
+	/*.................................................................................................................*/
+	int current = 0;
+	Tree tree;
+	NumberForTreeDivers numberTask;
+	Taxa taxa;
+	MesquiteWindow containingWindow;
+	CADPanel panel;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask = (NumberForTreeDivers)hireEmployee(NumberForTreeDivers.class, "Calculator of diversification statistics");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		makeMenu("Diversification");
+		ntC =makeCommand("setCalculator",  this);
+ 		numberTask.setHiringCommand(ntC);
+ 		numberTaskName = new MesquiteString();
+ 		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberForTreeDivers.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Diversification Measure", ntC, NumberForTreeDivers.class);
+ 			mss.setSelected(numberTaskName);
+		}
+
+		final MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			containingWindow = (MesquiteWindow)f;
+			containingWindow.addSidePanel(panel = new CADPanel(), 200);
+		}
+
+		addMenuItem( "Close Diversification Analysis", makeCommand("close",  this));
+		addMenuItem( "-", null);
+
+		return true;
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCalculator ", numberTask); 
+		temp.addLine("doCounts");
+
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the module that calculates likelihoods", "[name of module]", commandName, "setCalculator")) {
+			NumberForTreeDivers temp =  (NumberForTreeDivers)replaceEmployee(NumberForTreeDivers.class, arguments, "Diversification Measure", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					doCounts();
+				return numberTask;
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Provokes Calculation", null, commandName, "doCounts")) {
+			doCounts();
+		}
+		else if (checker.compare(this.getClass(), "Quits", null, commandName, "close")) {
+			if (panel != null && containingWindow != null)
+				containingWindow.removeSidePanel(panel);
+			iQuit();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	long oldTreeID = -1;
+	long oldTreeVersion = 0;
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree==null)
+			return;
+		this.tree=tree;
+		taxa = tree.getTaxa();
+		if ((tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion) && !MesquiteThread.isScripting()) {
+			doCounts();  //only do counts if tree has changed
+		}
+		oldTreeID = tree.getID();
+		oldTreeVersion = tree.getVersionNumber();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (numberTask!=null && !MesquiteThread.isScripting())
+			doCounts();
+	}
+	String blankIfNull(String s){
+		if (s == null)
+			return "";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public void doCounts() {
+		if (taxa == null)
+			return;
+		final MesquiteNumber result = new MesquiteNumber();
+		final MesquiteString rs = new MesquiteString();
+//		window.setText("");
+		panel.setStatus(true);
+		panel.repaint();
+		panel.setText("\nAnalysis of speciation and extinction using a tree (character independent)\n");
+		panel.append("\nCalculation: " + numberTask.getNameAndParameters() + "\n");
+		panel.append("\nTree: " + tree.getName() );
+			numberTask.calculateNumber(tree, result, rs);
+		panel.append("\n\n" + blankIfNull(result.getName()) + '\t' + result);
+		final MesquiteNumber[] aux = result.getAuxiliaries();
+		if (aux != null){
+			panel.append("\n");
+			for (int i = 0; i< aux.length; i++){
+				panel.append('\n' + blankIfNull(aux[i].getName()) + '\t' + aux[i].toString());
+			}
+		}
+		else
+			panel.append("\n\n" + rs);
+		panel.append("\n\nExplanation of calculation:\n" + numberTask.getExplanation());
+		panel.setStatus(false);
+		panel.repaint();
+//		window.append("\n\n  " + rs);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Diversification (Char. Indep.)";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates analyses of diversification (speciation/extinction)." ;
+	}
+	public void endJob() {
+		if (panel != null && containingWindow != null)
+			containingWindow.removeSidePanel(panel);
+		super.endJob();
+	}
+}
+
+class CADPanel extends MousePanel{
+	TextArea text;
+	Font df = new Font("Dialog", Font.BOLD, 14);
+	boolean calculating = false;
+	public CADPanel(){
+		super();
+		text = new TextArea(" ", 50, 50, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		setLayout(null);
+		add(text);
+		text.setLocation(0,26);
+		text.setEditable(false);
+		text.setVisible(true);
+		setBackground(Color.darkGray);
+		text.setBackground(Color.white);
+	}
+	public void setStatus(boolean calculating){
+		this.calculating = calculating;
+	}
+	public void setText(String t){
+		text.setText(t);
+	}
+	public void append(String t){
+		text.append(t);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		text.setSize(w, h-26);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		text.setSize(w, h-26);
+	}
+	public void paint(Graphics g){
+		g.setFont(df);
+
+		if (!calculating){
+			g.setColor(Color.white);
+			g.drawString("Diversification Analysis", 8, 20);
+		}
+		else{
+			g.setColor(Color.black);
+			g.fillRect(0,0, getBounds().width, 50);
+			g.setColor(Color.red);
+			g.drawString("Diversification: Calculating...", 8, 20);
+		}
+	}
+}
+
diff --git a/Source/mesquite/diverse/ContCharSpeciation/ContCharSpeciation.java b/Source/mesquite/diverse/ContCharSpeciation/ContCharSpeciation.java
new file mode 100755
index 0000000..8bd9e90
--- /dev/null
+++ b/Source/mesquite/diverse/ContCharSpeciation/ContCharSpeciation.java
@@ -0,0 +1,210 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.ContCharSpeciation;
+
+
+import mesquite.lib.*;
+import mesquite.diverse.lib.*;
+import mesquite.categ.lib.CategoricalHistory;
+import mesquite.cont.lib.*;
+
+/** ======================================================================== */
+public class ContCharSpeciation extends TreeCharSimulate {
+	RandomBetween rng;
+	double rate = 0.1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng= new RandomBetween(1);
+		if (!MesquiteThread.isScripting())
+			rate = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Evolution of Speciation Rate", rate);
+		if (!MesquiteDouble.isCombinable(rate))
+			return false;
+		addMenuItem("Rate of Evolution of Speciation Rate...", makeCommand("setRate",  (Commandable)this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	public String getDataType(){
+		return ContinuousData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setRate " + rate);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the rate of change of the continuous character", "[number]", commandName, "setRate")) {
+			pos.setValue(0);
+			double s = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(s))
+				s = MesquiteDouble.queryDouble(containerOfModule(), "Rate", "Rate of Evolution of Speciation Rate", rate);
+			if (MesquiteDouble.isCombinable(s)) {
+				rate = s;
+				parametersChanged();
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void speciateIfLucky(MesquiteTree tree, int node, ContinuousHistory rates, MesquiteInteger countOfSpecies, int numTaxa){
+		if (tree.nodeIsTerminal(node) && MesquiteDouble.isCombinable(tree.getBranchLength(node))) {  //length will be uncombinable if this was just a daughter species
+			if (countOfSpecies.getValue()<numTaxa) {
+				int taxon = tree.taxonNumberOfNode(node);
+				double rate = rates.getState(node, 0);  //negative absolute value of rate
+				double probability = Math.exp(-Math.abs(rate));
+
+
+				if (rng.nextDouble()<probability) {
+					tree.splitTerminal(taxon, countOfSpecies.getValue(), false);
+					
+	  	 			rates.setState(tree.firstDaughterOfNode(node), rate);
+	  	 			rates.setState(tree.lastDaughterOfNode(node), rate);
+					countOfSpecies.increment();
+				}
+			}
+		}
+		else
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (countOfSpecies.getValue()<numTaxa)
+					speciateIfLucky(tree, d, rates, countOfSpecies, numTaxa);
+			}
+	}
+	/*.................................................................................................................*/
+	private void evolveRates(MesquiteTree tree, int node, ContinuousHistory rates){
+		if (tree.nodeIsTerminal(node)) {
+			double r = rates.getState(node, 0);
+				if (rng.nextDouble()>0.5)
+				r += rate;
+			else
+				r -= rate;
+			rates.setState(node, 0, r);
+
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			evolveRates(tree, d, rates);
+		}
+	}
+	/*.................................................................................................................*/
+	private void addLengthToAllTerminals(MesquiteTree tree, int node, double increment){
+		if (tree.nodeIsTerminal(node)) {
+			double current = tree.getBranchLength(node, MesquiteDouble.unassigned);
+			if (MesquiteDouble.isCombinable(current))
+				tree.setBranchLength(node, current + increment, false);
+			else
+				tree.setBranchLength(node, increment, false);  	 		
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			addLengthToAllTerminals(tree, d, increment);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public  void doSimulation(Taxa taxa, int replicateNumber, ObjectContainer treeContainer, ObjectContainer characterHistoryContainer, MesquiteLong seed){
+		//save random seed used to make tree under tree.seed for use in recovering later
+		rng.setSeed(seed.getValue());
+		MesquiteTree tree = null;
+		ContinuousHistory charHistory = null;
+
+		Object t = treeContainer.getObject();
+		if (t == null || !(t instanceof MesquiteTree))
+			tree = new MesquiteTree(taxa);
+		else
+			tree = (MesquiteTree)t;
+		Object c = characterHistoryContainer.getObject();
+		if (c == null || !(c instanceof CategoricalHistory))
+			charHistory = new ContinuousHistory(taxa, 0, null);
+		else  
+			charHistory = (ContinuousHistory)c;
+
+		charHistory = (ContinuousHistory)charHistory.adjustSize(tree);
+
+		int numTaxa = taxa.getNumTaxa();
+
+
+		double startRate = Math.log(0.001);
+		for (int i=0; i<tree.getNumNodeSpaces(); i++)
+			charHistory.setState(i, 0, startRate);
+
+
+		tree.setToDefaultBush(2, false);
+		tree.setAllBranchLengths(0, false);
+		addLengthToAllTerminals(tree, tree.getRoot(), 0.01);
+		MesquiteInteger countOfSpecies = new MesquiteInteger(2);
+		long generations = 0;
+		while (countOfSpecies.getValue()<numTaxa){
+			generations++;
+			evolveRates(tree, tree.getRoot(), charHistory);
+			speciateIfLucky(tree, tree.getRoot(), charHistory, countOfSpecies, numTaxa);
+			addLengthToAllTerminals(tree, tree.getRoot(), 0.01);
+		}
+		tree.reshuffleTerminals(rng);
+		tree.resetTaxaInfo();
+
+		treeContainer.setObject(tree);
+		characterHistoryContainer.setObject(charHistory);
+		seed.setValue(rng.nextLong());  //see for next time
+
+	}
+
+	public void initialize(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Evolving Speciation Rate (Continuous Character)";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Generates tree by a speciation model in which the speciation rate evolves by a Brownian motion model." ;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return "Rate of evolution of speciation rate: " + rate;
+	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/diverse/DivCategCharMLCalculator/DivCategCharMLCalculator.java b/Source/mesquite/diverse/DivCategCharMLCalculator/DivCategCharMLCalculator.java
new file mode 100644
index 0000000..f06dfb3
--- /dev/null
+++ b/Source/mesquite/diverse/DivCategCharMLCalculator/DivCategCharMLCalculator.java
@@ -0,0 +1,1297 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.DivCategCharMLCalculator;
+
+
+
+import java.util.Vector;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.diverse.lib.DEQNumSolver;
+import mesquite.diverse.lib.DESystem;
+import mesquite.diverse.lib.RKF45Solver;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.duties.ParametersExplorer;
+
+public class DivCategCharMLCalculator extends MesquiteModule implements ParametersExplorable, Evaluator {
+    public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+        EmployeeNeed e = registerEmployeeNeed(ParametersExplorer.class, getName() + "  uses a Parameters Explorer to show likelihood surfaces.",
+        "The parameter explorer is arranged automatically");
+    }
+
+    // bunch of stuff copied from zMargLikeCateg - need to prune!!
+
+
+    DEQNumSolver solver;
+    double [][] probsExt, probsData;
+    double[] yStart;  //initial value for numerical integration
+    double[] d,e; //intermediate results
+    double[][] savedRootEstimates; // holds the estimates at the root (for simulation priors, etc.)
+    MesquiteNumber probabilityValue;
+    int numStates;
+
+    long underflowCheckFrequency = 2; //how often to check that not about to underflow; 1 checks every time
+    long underflowCheck = 1;
+    double underflowCompensation = 1;
+    MesquiteNumber minChecker;
+    // hooks for capturing context for table dump.
+    Tree lastTree;
+    CharacterDistribution lastCharDistribution;
+
+    // Number of steps per branch, reduce for a faster, possibily sloppier result
+    double stepCount = 1000;  //default 10000
+
+    //In version 1.1. the assumption about the root prior for model estimation, ancestral state reconstruction and simulation is assumed to be embedded in the model
+    //Thus, the control is removed here
+    public static final int ROOT_IGNOREPRIOR = 0;  // likelihoodignore's model's prior
+    public static final int ROOT_USEPRIOR = 1;  // calculates ancestral states imposing model's prior
+    public boolean showRootModeChoices = true;  
+    //TODO: allow user choice ������������������������
+    int rootMode = ROOT_USEPRIOR; //what if anything is done with prior probabilities of states at subroot?  
+    StringArray rootModes;
+    MesquiteString rootModeName;
+
+    MesquiteBoolean intermediatesToConsole = new MesquiteBoolean(false);
+    MesquiteBoolean getStartFromConstrainedModel = new MesquiteBoolean(false);
+
+    boolean[] deleted = null;
+    MesquiteParameter r0p;
+    MesquiteParameter r1p;
+    MesquiteParameter a0p;
+    MesquiteParameter a1p;
+    MesquiteParameter q01p;
+    MesquiteParameter q10p;
+    MesquiteParameter[] paramsForExploration;
+    MesquiteParameter[] previousParams;
+    ParametersExplorer explorer;
+    MesquiteBoolean conditionOnSurvival;
+    DiversificationCategModel speciesModel;
+    RandomBetween rng;
+    int iterations = 2;
+    boolean suspended = false;
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+  
+    public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+        loadPreferences();
+        probabilityValue = new MesquiteNumber();
+        minChecker = new MesquiteNumber(MesquiteDouble.unassigned);
+
+        solver = new RKF45Solver();  //new RK4Solver();
+        rng = new RandomBetween(System.currentTimeMillis());
+        //following is for the parameters explorer
+        r0p = new MesquiteParameter("r0", "Rate of net diversification with state 0", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+        r1p = new MesquiteParameter("r1", "Rate of net diversifiation with state 1", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+        a0p = new MesquiteParameter("a0", "Ratio of speciation to extinction in state 0", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+        a1p = new MesquiteParameter("a1", "Rate of speciation to extinction in state 1", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+        q01p = new MesquiteParameter("q01", "Rate of 0->1 changes", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+        q10p = new MesquiteParameter("q10", "Rate of 1->0 changes", 0.1, 0, MesquiteDouble.infinite, 0.000, 1);
+
+        paramsForExploration= new MesquiteParameter[]{r0p, r1p, a0p, a1p, q01p, q10p};
+        speciesModel = new DiversificationCategModel();
+        speciesModel.setParams(paramsForExploration);
+
+//      parameters = MesquiteParameter.cloneArray(paramsForExploration, null);
+        previousParams = new MesquiteParameter[6];
+        for (int i = 0; i<6; i++)
+            previousParams [i] = new MesquiteParameter();
+
+        conditionOnSurvival = new MesquiteBoolean(false);
+        addCheckMenuItem(null, "Condition on Survival", MesquiteModule.makeCommand("conditionOnSurvival", this), conditionOnSurvival);
+        //addCheckMenuItem(null,"Get Start from Constrained Model", MesquiteModule.makeCommand("getStartFromConstrainedModel", this), getStartFromConstrainedModel);
+        MesquiteSubmenuSpec mLO = addSubmenu(null, "Likelihood Calculation", null); 
+        addItemToSubmenu(null, mLO, "Steps per Branch...", makeCommand("setStepCount", this));
+        addItemToSubmenu(null, mLO, "Optimization Iterations...", makeCommand("setIterations", this));
+        addItemToSubmenu(null, mLO, "Underflow Checking...", makeCommand("setUnderflowCheckFreq", this));
+        addMenuItem("-", null);
+        addMenuItem("Show Parameters Explorer", makeCommand("showParamExplorer",this));
+        //addCheckMenuItem(null, "Intermediates to console", makeCommand("toggleIntermediatesToConsole",this), intermediatesToConsole);
+//      addMenuItem("-", null);
+        rootModes = new StringArray(2);  
+        rootModes.setValue(ROOT_IGNOREPRIOR, "Ignore Root State Frequencies");  //the strings passed will be the menu item labels
+        rootModes.setValue(ROOT_USEPRIOR, "Use Root State Frequencies as Prior");
+        rootModeName = new MesquiteString(rootModes.getValue(rootMode));  //this helps the menu keep track of checkmenuitems
+
+    //  if (showRootModeChoices){
+        /*Treatment of prior at root; currently user interface hidden unless preferences file put in place*/
+        //  MesquiteSubmenuSpec mssr = addSubmenu(null, "Root Reconstruction", makeCommand("setRootMode", this), rootModes); 
+        //  mssr.setSelected(rootModeName);
+        /**/
+        
+        return true;
+    }
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+   boolean reportCladeValues = false;
+    public void setReportCladeLocalValues(boolean reportCladeValues){
+        this.reportCladeValues = reportCladeValues;
+    }
+    public boolean getReportCladeLocalValues(){
+        return reportCladeValues;
+    }
+    public void employeeQuit(MesquiteModule employee){
+        if (employee == explorer)
+            explorer = null;
+    }
+    public Snapshot getSnapshot(MesquiteFile file) {
+        Snapshot temp = new Snapshot();
+        temp.addLine("suspend ");
+        temp.addLine("setUnderflowCheckFreq " + underflowCheckFrequency);
+        temp.addLine("setStepCount " + stepCount);
+        temp.addLine("setIterations " + iterations);
+        temp.addLine("conditionOnSurvival  " + conditionOnSurvival.toOffOnString());
+        temp.addLine("getStartFromConstrainedModel " + getStartFromConstrainedModel.toOffOnString());
+        if (explorer != null)
+            temp.addLine("showParamExplorer ", explorer);
+        temp.addLine("resume ");
+        return temp;
+    }
+
+    String lastResultString;
+    /*.................................................................................................................*/
+    /*  the main command handling method.  */
+    public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+        if (checker.compare(getClass(), "Sets the frequency of checking for underflow", "[integer, 1 or greater]", commandName, "setUnderflowCheckFreq")) {
+            int freq = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+            if (!MesquiteInteger.isCombinable(freq) && !MesquiteThread.isScripting())
+                freq = MesquiteInteger.queryInteger(containerOfModule(), "Checking frequency", "Frequency at which underflow checking is performed in likelihood calculations.  A value of n means checking is performed on each nth calculation; higher numbers mean the calculations go faster but are at risk of underflow problems.  Values over 10 are not recommended", (int)underflowCheckFrequency, 1, 10000);
+
+            if (MesquiteInteger.isCombinable(freq) && freq >=0 && freq!=underflowCheckFrequency){
+                underflowCheckFrequency = freq; //change mode
+                if (!MesquiteThread.isScripting())
+                    parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+            }
+        }
+        else if (checker.compare(getClass(), "Suspends calculations", null, commandName, "suspend")) {
+            suspended = true;
+        }
+        else if (checker.compare(getClass(), "Resumes calculations", null, commandName, "resume")) {
+            suspended = false;
+        }
+        else if (checker.compare(getClass(), "Returns last result string", null, commandName, "getLastResultString")) {
+            return lastResultString;
+        }
+        else if (checker.compare(getClass(), "Sets the number of steps per branch", "[double, 1 or greater]", commandName, "setStepCount")) {
+            double steps = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+            if (!MesquiteDouble.isCombinable(steps) && !MesquiteThread.isScripting())
+                steps = MesquiteDouble.queryDouble(containerOfModule(), "Steps per branch", "Number of divisions of each branch for numerical integration.  Higher numbers mean the calculations are more accurate but go more slowly.  Values under 100 are not recommended", stepCount, 10, 1000000);
+
+            if (MesquiteDouble.isCombinable(steps) && steps >=0 && steps!=stepCount){
+                stepCount = steps; //change mode
+                if (!MesquiteThread.isScripting())
+                    parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+            }
+        }
+        else if (checker.compare(getClass(), "Sets the number of iterations in the likelihood optimization", "[integer, 1 or greater]", commandName, "setIterations")) {
+            int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+            if (!MesquiteInteger.isCombinable(it) && !MesquiteThread.isScripting())
+                it = MesquiteInteger.queryInteger(containerOfModule(), "Optimization Iterations", "Number of random starting points for likelihood optimizationi.  Higher numbers mean the optimization is more thorough  but goes more slowly.", iterations, 1, 1000);
+
+            if (MesquiteInteger.isCombinable(it) && it >=0 && it!=iterations){
+                iterations = it; //change mode
+                if (!MesquiteThread.isScripting())
+                    parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+            }
+        }
+        else if (checker.compare(this.getClass(), "Sets whether to condition by survival", "[on; off]", commandName, "conditionOnSurvival")) {
+            conditionOnSurvival.toggleValue(new Parser().getFirstToken(arguments));
+            if (!MesquiteThread.isScripting())parametersChanged();
+        }
+        else if (checker.compare(getClass(), "Writes table to console", "", commandName, "showParamExplorer")) {
+            explorer = (ParametersExplorer)hireEmployee(ParametersExplorer.class, "Parameters explorer");
+            if (explorer == null)
+                return null;
+           // explorer.makeMenu("Parameters");
+            explorer.setExplorable(this);
+             return explorer;
+        }
+        else if (checker.compare(getClass(),"Sets whether to write intermediate branch values to console","[on; off]", commandName, "toggleIntermediatesToConsole")){
+            intermediatesToConsole.toggleValue(parser.getFirstToken(arguments));
+        }
+        else if (checker.compare(getClass(),"Sets whether to start searches for six parameter models from estimates of canonical five parameter models (and 4 parameter from 3)","[on; off]", commandName, "getStartFromConstrainedModel")){
+            getStartFromConstrainedModel.toggleValue(parser.getFirstToken(arguments));
+        }
+        else
+            return  super.doCommand(commandName, arguments, checker);
+        return null;
+    }
+    /*.................................................................................................................*/
+    private void initProbs(int nodes, int numStates) {
+        this.numStates = numStates;
+        if (yStart == null || yStart.length != numStates*2 || d == null || e == null || probsData==null || probsData.length!=nodes || probsData[0].length!=numStates){
+            probsData = new double[nodes][numStates];
+            probsExt = new double[nodes][numStates];
+            yStart = new double[2*numStates];
+            d = new double[numStates];
+            e = new double[numStates];
+        }
+        Double2DArray.zeroArray(probsData);
+        Double2DArray.zeroArray(probsExt);
+    }
+    /*.................................................................................................................*/
+    private double checkUnderflow(double[] probs){
+        minChecker.setValue(MesquiteDouble.unassigned);
+        for (int i=0; i<probs.length; i++){
+            minChecker.setMeIfIAmMoreThan(probs[i]);
+        }
+        double q = minChecker.getDoubleValue();
+        if (q == 0)
+            return 0;
+        else {
+            for (int i=0; i<probs.length; i++)
+                probs[i] /= q;
+        }
+        return -Math.log(q);
+    }
+    /*.................................................................................................................*/
+    /* assess branch length variation to choose time slices */
+    private double assessBranchLengths(int node, Tree tree, MesquiteDouble min, MesquiteDouble max) {
+        double length = tree.getBranchLength(node, 1.0, deleted);
+        min.setValue(MesquiteDouble.minimum(min.getValue(), length));
+        max.setValue(MesquiteDouble.maximum(max.getValue(), length));
+        for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+            length += assessBranchLengths(nd,tree,min, max);
+        }
+        return length;
+    }
+    // This might hold the intermediate step results if requested for debugging
+    Vector integrationResults = null;
+
+    /* now returns underflow compensation */
+    private double downPass(int node, Tree tree, DiversificationCategModel model, DEQNumSolver solver, CategoricalDistribution observedStates) {
+        double logComp;
+        if (tree == null || observedStates == null || e == null || d == null){
+        	MesquiteMessage.printStackTrace("ERROR: downpass in DivCategCharMLCalculator with null object: tree " + tree + " observedStates " + observedStates + " d " + d + " e " + e);
+        	return MesquiteDouble.unassigned;
+       }
+        if (tree.nodeIsTerminal(node)) { //initial conditions from observations if terminal
+            long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node));
+            int obs = CategoricalState.minimum(observed); //NOTE: just minimum observed!
+            for (int state = 0;state < numStates;state++){
+                e[state]=0;
+                if ((state == obs))
+                    d[state] = 1;
+                else
+                    d[state] = 0;
+            }
+            logComp = 0.0;  // no compensation required yet
+        }
+        else { //initial conditions from daughters if internal
+            logComp = 0.0;
+            for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+                logComp += downPass(nd,tree,model,solver,observedStates);
+            }
+            for(int state = 0; state < numStates;state++){
+                d[state] = 1;  //two here to anticipate two daughters???
+                e[state] = 1;
+                //TODO: either filter to permit only ultrametric, or redo calculations to permit extinct nodes.
+                //TODO: likewise for polytomies
+                for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+                    e[state] = probsExt[nd][state];
+                    d[state] *= probsData[nd][state];
+                }
+
+                if (node != tree.getRoot()){  //condition on splitting at root; thus don't include rate if at root
+                    d[state] *= model.getSRate(state);
+                }
+
+            }
+            if (underflowCheckFrequency>=0 && ++underflowCheck % underflowCheckFrequency == 0){
+                logComp += checkUnderflow(d);
+            }
+        }
+        if (node == tree.getRoot()){
+            for(int i=0;i<numStates;i++){
+                probsExt[node][i] = e[i];
+                probsData[node][i] = d[i];
+            }
+            return logComp;
+        }
+        else{
+            double x = 0;
+            double length = tree.getBranchLength(node,1.0,deleted);
+            
+            double h = getStepSize(length);  
+            
+            for(int i=0;i<numStates;i++){
+                yStart[i] = e[i];
+                yStart[i+numStates] = d[i];
+            }
+            if (intermediatesToConsole.getValue()){
+                MesquiteMessage.print("node " + node);
+                if (node == tree.getRoot())
+                    MesquiteMessage.println(" is root");
+                else
+                    MesquiteMessage.println("");
+                MesquiteMessage.println("At start, y is " + DoubleArray.toString(yStart));
+            }
+            integrationResults = solver.integrate(x,yStart,h,length,model,integrationResults,intermediatesToConsole.getValue());        
+            double[] yEnd = (double[])integrationResults.lastElement();
+            
+            if (yEnd.length == 2*numStates){
+                for(int i=0;i<numStates;i++){
+                    probsExt[node][i] = yEnd[i];
+                    probsData[node][i] = yEnd[i+numStates];
+                }
+            }
+            else {
+                MesquiteMessage.warnProgrammer("Vector returned by solver not the same size supplied!");
+                for(int i=0;i<numStates;i++){
+                    probsExt[node][i]=0;   //is this the right thing here?
+                    probsData[node][i]=0;  //this is probably the best choice here
+                }
+            }
+            if (intermediatesToConsole.getValue()){
+                MesquiteMessage.println("Intermediate values");
+                StringBuffer stateMsg = new StringBuffer(1000);
+                //stateMsg.delete(0,stateMsg.length());  //flush everything
+                x = h;
+                double [] tempResults;
+                for(int i=0;i<integrationResults.size();i++){
+                    if(i%100 == 0){
+                        String xString = MesquiteDouble.toFixedWidthString(x, 13, false);
+                        stateMsg.append("x= "+ xString + " y =[");
+                        tempResults = (double[])integrationResults.get(i);
+                        for(int j=0;j<tempResults.length;j++)
+                            stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+                        stateMsg.append("]\n");
+                    }   
+                    x += h;
+                }
+                stateMsg.append("Final value; \n");
+                stateMsg.append("x= " + h*stepCount + " y =[");
+                tempResults = (double[])integrationResults.lastElement();
+                for(int j=0;j<tempResults.length;j++)
+                    stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+                stateMsg.append("]\n");
+                MesquiteMessage.println(stateMsg.toString());
+            }
+            return logComp;
+        }
+    }
+    /*------------------------------------------------------------------------------------------*/
+    double avgBranchLength;
+    double getStepSize(double length){      
+        //average branch will have stepCount steps; longer branches will have proportionately more steps up to a maximum of 4*stepCount, shorter to minimum of stepCount/2
+        double proposedSteps = stepCount*length/avgBranchLength;
+        if (proposedSteps < stepCount/2)
+            proposedSteps = stepCount/2;
+        else if (proposedSteps > 4* stepCount)
+            proposedSteps =4* stepCount;
+        return length/proposedSteps;       //this will need tweaking!
+    }
+
+    
+    public Class getDutyClass() {
+        return DivCategCharMLCalculator.class;
+    }
+
+    public String getName() {
+        return "BiSSE Net Diversification Likelihood (Calculator)";
+    }
+    public String getAuthors() {
+        return "Peter E. Midford & Wayne P. Maddison";
+    }
+
+    public String getVersion() {
+        return "1.0";
+    }
+
+	public String getExplanation(){
+		return "Calculates likelihood with a tree of a species diversification model whose rates (r = spec. - ext.; a = spec./ext.) depend on the state of a binary character (BiSSE model, Maddison, Midford & Otto, 2007).";
+	}
+ 
+    public boolean isPrerelease(){
+        return false;
+    }
+    
+    /*------------------------------------------------------------------------------------------*/
+    /** these methods for ParametersExplorable interface */
+    public MesquiteParameter[] getExplorableParameters(){
+        return paramsForExploration;
+    }
+    MesquiteNumber likelihood = new MesquiteNumber();
+    public double calculate(MesquiteString resultString){
+        if (suspended)
+            return MesquiteDouble.unassigned;
+        if(true){
+        }
+        calculateLogProbability( lastTree,  lastCharDistribution, paramsForExploration, likelihood, resultString);
+        return likelihood.getDoubleValue();
+    }
+
+    public void restoreAfterExploration(){
+    }
+    /*.................................................................................................................*/
+    public double stationaryFreq0(DiversificationCategModel model) {  
+        if (model==null)
+            return MesquiteDouble.unassigned;
+        final double d = model.getSRate(0)-model.getSRate(1)+model.getERate(1)-model.getERate(0);
+        final double noise = (model.getSRate(0)+model.getSRate(1)+model.getERate(1)+model.getERate(0))*1E-14;
+        final double q01 = model.getCRate(0);
+        final double q10 = model.getCRate(1);
+        if (Math.abs(d ) < noise){
+            if (q01 + q10 == 0)
+                return 0.5;
+            return q10/(q01+q10);
+        }
+        double part = d - q01 - q10;
+        part = part*part + 4*d*q10;
+        if (part >=0)
+            part = Math.sqrt(part);
+        else
+            return MesquiteDouble.unassigned;
+        final double plus = (q01 + q10 - d + part) / (-2*d);
+        final double minus = (q01 + q10 - d - part) / (-2*d);            
+        if (minus < 0 || minus >1)
+            return plus;
+        else if (plus < 0 || plus >1)
+            return minus;
+        else
+            return MesquiteDouble.unassigned;
+    }
+
+
+    /*
+     Options:
+     1. calculation determined entirely by params.  Constraints etc. determined within params array which is contained in species model
+     2. predefined: constraint lambda0-mu0 = lambda1-mu1
+    /*.................................................................................................................*/
+    public void calculateLogProbability(Tree tree, CharacterDistribution obsStates, MesquiteParameter[] params, MesquiteNumber prob, MesquiteString resultString) {  
+        if (speciesModel==null || obsStates==null || prob == null || tree == null)
+            return;
+        lastTree = tree;
+        lastCharDistribution = obsStates;
+        prob.setToUnassigned();
+        if (suspended)
+            return;
+        CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+        int workingMaxState;
+		if (tree.hasReticulations() || tree.hasUnbranchedInternals(tree.getRoot())){
+			MesquiteMessage.warnProgrammer("Tree has reticulations or unbranched internal nodes; these are not allowed in BiSSE calcuclations.");
+			return;
+		}
+		else if (observedStates.getMaxState() <= 0){
+            MesquiteMessage.warnProgrammer("Character Distribution appears to be constant; cannot calculate likelihood of tree and character (Diversification)");
+            return;
+        }
+        else if (observedStates.getMaxState() >1){
+            MesquiteMessage.warnProgrammer("Character Distribution is not binary; cannot calculate likelihood of tree and character (Diversification)");
+            return;
+        }
+        else
+            workingMaxState = observedStates.getMaxState()+1; 
+        lastMaxState = workingMaxState;
+        previousParams = speciesModel.getOriginalParams(previousParams);
+        speciesModel.setParams(params);
+        double currentStep = stepCount;
+
+        double negLogLikelihood = 0;
+        String modelString = "";
+        MesquiteDouble minBranchLength = new MesquiteDouble();
+        MesquiteDouble maxBranchLength = new MesquiteDouble();
+        avgBranchLength = assessBranchLengths(tree.getRoot(), tree, minBranchLength, maxBranchLength)/tree.numberOfNodesInClade(tree.getRoot());
+        /*to report stationary frequencies 
+        if (true){
+            negLogLikelihood = stationaryFreq0(speciesModel);
+        }
+        else 
+        */
+        if (speciesModel.isFullySpecified()){
+            negLogLikelihood = logLike(tree, observedStates, speciesModel);
+            modelString  = speciesModel.toString();
+        }
+        else {
+            logln("Estimating model with parameters " + speciesModel.toStringForScript());
+            //========================== all 6 parameters unspecified ==============================
+            if (speciesModel.numberSpecified() ==0 && speciesModel.numberEffectiveParameters() == 6){  //all unspecified
+                //some or all parameters are unassigned, and thus need to be estimated
+                //First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+                Optimizer opt = new Optimizer(this);
+                Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+                stepCount = 100;
+                double useIterations = iterations;
+                double[] suggestions1;
+                double[] suggestions2;
+                double[] suggestions3;
+                if (getStartFromConstrainedModel.getValue()){
+                    suggestions1 = estimate5(tree,observedStates,1,new double[]{0.4, 0.5, 0.4, 0.1, 0.05});  //TODO these may need more work
+                    suggestions2 = estimate5(tree,observedStates,3,new double[]{0.3, 0.5, 0.45, 0.05, 0.1});
+                    suggestions3 = estimate5(tree,observedStates,5,new double[]{0.5,0.3,0.5,0.4,0.075});
+                }
+                else {
+                    suggestions1 = new double[]{0.3, 0.4, 0.5, 0.4, 0.1, 0.05};
+                    suggestions2 = new double[]{0.3, 0.5, 0.5, 0.4, 0.05, 0.1};
+                    suggestions3 = new double[]{0.5,0.3,0.5,0.4,0.05, 0.1};                    
+                }
+                double bestL = 1e101;
+                double[] suggestions = null;
+                int bestS = -1;
+                String attemptName = "";
+                double evs1 = MesquiteDouble.unassigned;
+                double evs2 = MesquiteDouble.unassigned;
+                double evs3 = MesquiteDouble.unassigned;
+                if (suggestions1 != null)
+                    evs1 = evaluate(suggestions1,bundle);
+                if (suggestions2 != null)
+                    evs2 = evaluate(suggestions2,bundle);
+                if (suggestions3 != null)
+                    evs3 = evaluate(suggestions3,bundle);
+                if (MesquiteDouble.isCombinable(evs1) && evs1 < 1e99 && MesquiteDouble.isCombinable(evs2) && evs2 < 1e99 && MesquiteDouble.isCombinable(evs3) && evs3 < 1e99){
+                    logln("Diversification Categ Char: Tree " + tree.getName() + " and character " + obsStates.getName());
+                    logln("Diversification Categ Char: Estimating all 6 parameters, phase 1: step count 100");
+                    double negLogLikelihood1 = opt.optimize(suggestions1, bundle);
+                    logln("Diversification Categ Char: neg. Log Likelihood first attempt:" + negLogLikelihood1);
+                    double negLogLikelihood2 = opt.optimize(suggestions2, bundle);
+                    logln("Diversification Categ Char: neg. Log Likelihood second attempt:" + negLogLikelihood2);
+                    double negLogLikelihood3 = opt.optimize(suggestions3, bundle);
+                    logln("Diversification Categ Char: neg. Log Likelihood third attempt:" + negLogLikelihood3);
+                    if (negLogLikelihood1 < negLogLikelihood2 && negLogLikelihood1 < negLogLikelihood3) {
+                        suggestions = suggestions1;
+                        bestS = -1;
+                        bestL = negLogLikelihood1;
+                        attemptName = " first attempt" ;
+                    }
+                    else if (negLogLikelihood2 < negLogLikelihood1 && negLogLikelihood2 < negLogLikelihood3) {
+                        suggestions = suggestions2;
+                        bestS = -2;
+                        bestL = negLogLikelihood2;
+                        attemptName = " second attempt" ;
+                    }
+                    else {
+                        suggestions = suggestions3;
+                        bestS = -3;
+                        bestL = negLogLikelihood3;
+                        attemptName = " third attempt" ;                        
+                    }
+                }
+                else{
+                    useIterations = iterations + 3;
+                }
+                double[][] randomSuggestions = new double[(int)useIterations][6];  //prevent crash when evaluate fails?
+
+                for (int i = 0; i< useIterations; i++){  
+                    double max = 1.0;
+                    if (i< useIterations/2){
+                        max =  1.0;
+                        for (int k = 0; k<2; k++){  //better maps the space we're trying to search?
+                            double r1 = rng.randomDoubleBetween(0.001, max);  // avoid divide by zero
+                            double r2 = rng.randomDoubleBetween(0, r1);      //(always) enforce e < s, but do it differently
+                            randomSuggestions[i][k] = r1-r2;
+                            randomSuggestions[i][k+2] = r2/r1;
+                        }
+                        randomSuggestions[i][4] = rng.randomDoubleBetween(0, max);
+                        randomSuggestions[i][5] = rng.randomDoubleBetween(0, max);
+
+                    }
+                    else { //0 to 1 first then 0 to 10.0
+                        max =  rng.randomDoubleBetween(0, 10.0);
+                        for (int k = 0; k<2; k++){  //better maps the space we're trying to search?
+                            double r1 = rng.randomDoubleBetween(0.001, max);  // avoid divide by zero
+                            double r2 = rng.randomDoubleBetween(0, r1);      //(always) enforce e < s, but do it differently
+                            randomSuggestions[i][k] = r1-r2;
+                            randomSuggestions[i][k+2] = r2/r1;
+                        }
+                        randomSuggestions[i][4] = rng.randomDoubleBetween(0, max);
+                        randomSuggestions[i][5] = rng.randomDoubleBetween(0, max);
+                        if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+                            for (int k = 0; k<6; k++)
+                                randomSuggestions[i][k] = rng.randomDoubleBetween(0, max);
+                    }
+                }
+                for (int i = 0; i< useIterations; i++){ // 0 to 10
+                    if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+                        logln("Diversif Categ Char: random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+                        double nLL = opt.optimize(randomSuggestions[i], bundle);
+                        stepCount = 1000;
+                        nLL = evaluate(randomSuggestions[i], bundle);
+                        stepCount = 100;
+                        logln("Diversif Categ Char: random attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+                        if (nLL < bestL){
+                            bestS = i;
+                            bestL = nLL;
+                            attemptName = "random attempt " + i ;
+                        }
+                    }
+                    else { 
+                        logln("Diversif Categ Char: random attempt " + i + " failed because starting position had undefined likelihood");
+                        logln("Failing suggestions were: " + DoubleArray.toString(randomSuggestions[i]));
+                    }
+                }
+                if (bestS>=0)
+                    suggestions = randomSuggestions[bestS];
+                if (suggestions == null){
+                    logln("Diversif Categ Char: Estimating parameters failed");
+                }
+                else {
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+                    stepCount = 1000;
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+                    negLogLikelihood = opt.optimize(suggestions, bundle);
+                    logln("Diversif Categ Char: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+                    speciesModel.setParamValuesUsingConstraints(suggestions);
+                    modelString  = speciesModel.toString() + " [est.]";
+                }
+            }
+            //========================== 2 - 5 parameters unspecified ==============================
+            else if (speciesModel.numberEffectiveParameters() > 1) {  //2 to 5 parameters unassigned; should have separate for 1!
+                //some parameters are unassigned, and thus need to be estimated
+                //First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+                Optimizer opt = new Optimizer(this);
+                Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+                stepCount = 100;
+                int looseParameter = -1;
+                int numParams = speciesModel.numberEffectiveParameters();
+                double[] suggestions1 = new double[numParams];
+                logln("Diversif Categ Char: Tree " + tree.getName() + " and character " + obsStates.getName());
+                logln("Diversif Categ Char: Estimating " + numParams + " free parameters");
+                if (getStartFromConstrainedModel.getValue() && (numParams == 4)){                    
+                    if (speciesModel.parameters[1].getConstrainedTo() == null)
+                        looseParameter = 1;
+                    else if (speciesModel.parameters[3].getConstrainedTo() == null)
+                        looseParameter = 3;
+                    else if (speciesModel.parameters[5].getConstrainedTo() == null)
+                        looseParameter = 5;
+                    for (int i=0; i < suggestions1.length; i++)
+                        suggestions1[i] = 0.1*(i+1);
+                    suggestions1 = estimate3(tree,observedStates,looseParameter,suggestions1);  //TODO these may need more work
+                    logln("Generating starting point for 4 parameter model from canonical 3 parameter model");
+                    logln("First random suggestion will be replaced by estimate from 3 parameter model");
+                }
+                else {
+                    for (int i=0; i < suggestions1.length; i++)
+                        suggestions1[i] = 0.1*(i+1);
+                }
+                logln("Diversif Categ Char: Estimating parameters, phase 1: step count 100");
+                double bestL = MesquiteDouble.unassigned;
+                int bestS = -1;
+
+                String attemptName = "random attempt";
+                double[][] randomSuggestions = new double[iterations][numParams];
+                for (int i = 0; i< iterations; i++){  
+                    if (i< iterations/2){//0 to 1 
+                        for (int k = 0; k<numParams; k++){
+                            randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+                        }
+                    }
+                    else { //00 to 10.0
+                        double max =  rng.randomDoubleBetween(0, 10.0);
+                        for (int k = 0; k<numParams; k++){
+                            randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+                        }
+                        
+                        if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+                            for (int k = 0; k<numParams; k++)
+                                randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+
+                    }
+                }
+                if (getStartFromConstrainedModel.getValue() && (numParams == 4)){
+                    if (looseParameter != -1){
+                        logln("Setting first random suggestion to " + DoubleArray.toString(suggestions1));
+                        for(int i=0;i<suggestions1.length;i++)
+                            randomSuggestions[0][i]=suggestions1[i];
+                    }
+                }
+                for (int i = 0; i< iterations; i++){ // 0 to 10
+                    if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+                        logln("Diversif Categ Char: random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+                        double nLL = opt.optimize(randomSuggestions[i], bundle);
+                        stepCount = 1000;
+                        nLL = evaluate(randomSuggestions[i], bundle);
+                        stepCount = 100;
+                        logln("Diversif Categ Char: attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+                        if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+                            bestS = i;
+                            bestL = nLL;
+                            attemptName = "random attempt " + i ;
+                        }
+                    }
+                    else 
+                        logln("Diversif Categ Char: random attempt " + i + " failed because starting position had undefined likleihood");
+                }
+                if (bestS>=0){
+                    double[] suggestions = randomSuggestions[bestS];
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+                    stepCount = 1000;
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+                    logln("Diversif Categ Char: Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+                    negLogLikelihood = opt.optimize(suggestions, bundle);
+                    logln("Diversif Categ Char: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+                    speciesModel.setParamValuesUsingConstraints(suggestions);
+                    modelString  = speciesModel.toString() + " [est.]";
+                }
+                else 
+                    logln("Diversif Categ Char: Estimating parameters failed");
+
+
+            }
+            //========================== 1 parameter unspecified ==============================
+            else  {  //1 parametersunassigned;
+                Optimizer opt = new Optimizer(this);
+                Object[] bundle = new Object[] {tree, observedStates, speciesModel};
+                stepCount = 100;
+
+                logln("Diversif Categ Char: Tree " + tree.getName() + " and character " + obsStates.getName());
+                logln("Diversif Categ Char: Estimating one free parameter");
+                logln("Diversif Categ Char: Estimating parameter, phase 1: step count 100");
+                MesquiteDouble suggestion = new MesquiteDouble(1);
+                negLogLikelihood = opt.optimize(suggestion, 0, 100, bundle);
+                logln("Diversif Categ Char: neg. Log Likelihood first attempt:" + negLogLikelihood);
+                double bestL = negLogLikelihood;
+                double bestP = suggestion.getValue();
+                negLogLikelihood = opt.optimize(suggestion, 0.0, 10, bundle);
+                logln("Diversif Categ Char: neg. Log Likelihood second attempt:" + negLogLikelihood);
+                if (bestL < negLogLikelihood)
+                    suggestion.setValue(bestP);
+                else{
+                    bestP = suggestion.getValue();
+                    bestL = negLogLikelihood;
+                }
+                negLogLikelihood = opt.optimize(suggestion, 0.0, 1, bundle);
+                logln("Diversif Categ Char: neg. Log Likelihood third attempt:" + negLogLikelihood);
+                if (bestL < negLogLikelihood)
+                    suggestion.setValue(bestP);
+                else{
+                    bestP = suggestion.getValue();
+                    bestL = negLogLikelihood;
+                }
+                stepCount = 1000;
+                logln("Diversif Categ Char: Estimating parameters, phase 2: step count 1000");
+                negLogLikelihood = opt.optimize(suggestion, suggestion.getValue() * 0.6, suggestion.getValue() * 1.4, bundle);
+                logln("Diversif Categ Char: neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+                oneParam[0] = suggestion.getValue();
+                speciesModel.setParamValuesUsingConstraints(oneParam);
+                modelString  = speciesModel.toString() + " [est.]";
+
+            }
+        }
+        stepCount = currentStep;
+
+		if (prob!=null){
+			prob.setValue(negLogLikelihood);
+			tempParams = MesquiteParameter.cloneArray(params, tempParams);
+			tempParams = speciesModel.getCurrentParams(tempParams);
+			prob.copyAuxiliaries(tempParams);
+			prob.setName("BiSSE (Net Div) -lnLikelihood");
+		}
+
+		
+        double likelihood = Math.exp(-negLogLikelihood);
+        if (MesquiteDouble.isUnassigned(negLogLikelihood))
+            likelihood = MesquiteDouble.unassigned;
+        if (resultString!=null) {
+            String s = "Diversif Likelihood (Char. dep.) " + modelString + ";  -log L.:"+ MesquiteDouble.toString(negLogLikelihood) + " [L. "+ MesquiteDouble.toString(likelihood) + "]";
+            s += "  " + getParameters();
+            resultString.setValue(s);
+        }
+        lastResultString = tree.getName() + "\t" + obsStates.getName() +"\t" + speciesModel.toStringForAnalysis() + "\t" + MesquiteDouble.toString(negLogLikelihood);
+        speciesModel.setParams(previousParams);
+    }
+    MesquiteParameter[] tempParams;
+    int lastMaxState = 1;
+    long count = 0;
+
+    boolean anyNegative(double[] params){
+        if (params == null)
+            return false;
+        for (int i=0; i<params.length; i++)
+            if (params[i]<0)
+                return true;
+        return false;
+    }
+
+    int badCount = 1;
+    /*.................................................................................................................*/
+    public double evaluate(double[] params, Object bundle){
+        if (anyNegative(params))
+            return 1e100 + 1e99*badCount++;
+        Object[] b = ((Object[])bundle);
+        Tree tree = (Tree)b[0];
+        CategoricalDistribution states = (CategoricalDistribution)b[1];
+        DiversificationCategModel model = (DiversificationCategModel)b[2];
+        if (!model.setParamValuesUsingConstraints(params))
+            return 1e100 + 1e99*badCount++;
+        double result =  logLike(tree, states, model);
+        if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result >= 1e100)
+            result = 1e100 + 1e99*badCount++;
+        if (count++ % 10 == 0)
+            CommandRecord.tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " params " + MesquiteParameter.toString(params));
+        if (count % 1000 == 0)
+            logln("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " param " + MesquiteParameter.toString(oneParam));
+        return result;
+    }
+    /*.................................................................................................................*/
+    double[] oneParam = new double[1];
+    /*.................................................................................................................*/
+    public double evaluate(MesquiteDouble param, Object bundle){
+        oneParam[0] = param.getValue();
+        if (anyNegative(oneParam))
+            return 1e100 + 1e99*badCount++;
+        Object[] b = ((Object[])bundle);
+        Tree tree = (Tree)b[0];
+        CategoricalDistribution states = (CategoricalDistribution)b[1];
+        DiversificationCategModel model = (DiversificationCategModel)b[2];
+        model.setParamValuesUsingConstraints(oneParam);
+        double result =  logLike(tree, states, model);
+        if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result > 1e100)
+            result = 1e100 + 1e99*badCount++;
+        if (count++ % 10 == 0)
+            CommandRecord.tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " param " + MesquiteParameter.toString(oneParam));
+        if (count % 1000 == 0)
+            logln("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + " param " + MesquiteParameter.toString(oneParam));
+       return result;
+    }
+    /*.................................................................................................................*/
+    double[] freq = new double[2];
+    /*.................................................................................................................*/
+    public double logLike(Tree tree, CategoricalDistribution states, DiversificationCategModel model) {  
+        if (model==null || tree == null || states == null)
+            return MesquiteDouble.unassigned;
+        int root = tree.getRoot(deleted);
+        double f0 = stationaryFreq0(model);
+        if ((f0 <0) ||(f0 > 1))
+            return 1.0e101;
+        initProbs(tree.getNumNodeSpaces(),lastMaxState);
+        double logComp = downPass(root, tree, model, solver, states);
+        freq[0] = f0;
+        freq[1] = 1.0 - f0;
+        double likelihood = 0.0;
+        if (rootMode == ROOT_USEPRIOR){
+            if (conditionOnSurvival.getValue()){
+                for (int i=0;  i<lastMaxState; i++)
+                    likelihood += freq[i]*probsData[root][i]/(1-probsExt[root][i])/(1-probsExt[root][i]);
+            }
+            else
+                for (int i=0;  i<lastMaxState; i++) 
+                    likelihood += freq[i]*probsData[root][i];
+        }
+        else if (conditionOnSurvival.getValue()){
+            for (int i=0;  i<lastMaxState; i++)
+                likelihood += probsData[root][i]/(1-probsExt[root][i])/(1-probsExt[root][i]);
+        }
+        else
+            for (int i=0;  i<lastMaxState; i++) 
+                likelihood += probsData[root][i];
+        double negLogLikelihood = -(Math.log(likelihood) - logComp);
+        return negLogLikelihood;
+    }
+    
+    int quickIterations;
+    private DiversificationCategModel localModel5 = new DiversificationCategModel();
+    public double[] estimate5(Tree tree, CategoricalDistribution observedStates,int toConstrain,double suggestions[]){
+        //some parameters are unassigned, and thus need to be estimated
+        //First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+        final String logPrefix = "Diversif Categ Char (5 parameter starting point): ";
+        quickIterations = iterations/2;
+        MesquiteParameter [] localParams = new MesquiteParameter[6]; 
+        for(int i= 0; i<6;i++){
+            localParams[i] = new MesquiteParameter();
+            if (i == toConstrain)
+                localParams[i].setConstrainedTo(localParams[i-1], false);            
+        }
+        localModel5.setParams(localParams);
+        Optimizer opt = new Optimizer(this);
+        Object[] bundle = new Object[] {tree, observedStates, localModel5};
+        stepCount = 100;
+        int numParams = 5;
+        logln(logPrefix + "constraining parameter " + toConstrain + " to generate starting point for 6 parameter estimate");
+        logln(logPrefix + "Estimating parameters, phase 1: step count 100");
+        double bestL = MesquiteDouble.unassigned;
+        double nLL = MesquiteDouble.unassigned;
+        int bestS = -2;
+        if (evaluate(suggestions,bundle)<1e99){
+            logln("Trying initial suggestion :" + DoubleArray.toString(suggestions));
+            nLL = opt.optimize(suggestions,bundle);
+            stepCount = 1000;
+            nLL = evaluate(suggestions, bundle);
+            stepCount = 100;
+            logln("Diversif Categ Char 5 parameter reduced model starting suggestion: initial suggestion neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(suggestions));
+            if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+                bestS = -1;
+                bestL = nLL;
+            }
+        }
+        String attemptName = "random attempt";
+        double[][] randomSuggestions = new double[quickIterations][numParams];
+        for (int i = 0; i< quickIterations; i++){  
+            if (i< quickIterations/2){//0 to 1 
+                for (int k = 0; k<numParams; k++){
+                    randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+                }
+            }
+            else { //00 to 10.0
+                double max =  rng.randomDoubleBetween(0, 10.0);
+                for (int k = 0; k<numParams; k++){
+                    randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+                }
+
+                if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+                    for (int k = 0; k<numParams; k++)
+                        randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+            }
+        }
+        for (int i = 0; i< quickIterations; i++){ // 0 to 10
+            if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+                logln(logPrefix + "Diversif Categ Char (5 parameter starting point): random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+                nLL = opt.optimize(randomSuggestions[i], bundle);
+                stepCount = 1000;
+                nLL = evaluate(randomSuggestions[i], bundle);
+                stepCount = 100;
+                logln(logPrefix + "attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+                if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+                    bestS = i;
+                    bestL = nLL;
+                    attemptName = "random attempt " + i ;
+                }
+            }
+            else 
+                logln(logPrefix + "random attempt " + i + " failed because starting position had undefined likleihood");
+        }
+        if (bestS>=-1){
+            if (bestS > 0)
+                suggestions = randomSuggestions[bestS];
+            //logln("Diversif Categ Char (5 parameter starting point): Estimating parameters, phase 2: step count 100; best so far " + evaluate(suggestions, bundle));
+            stepCount = 1000;
+            logln(logPrefix + "Estimating parameters, phase 2: step count 1000; best so far " + evaluate(suggestions, bundle));
+            logln(logPrefix + "Diversif Categ Char 5 parameter starting point): Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+            double negLogLikelihood = opt.optimize(suggestions, bundle);
+            logln(logPrefix + "neg. Log Likelihood final attempt:" + negLogLikelihood);
+
+            final double [] result = new double[6];
+            for(int i= 0;i<result.length;i++){
+                if(i<toConstrain)
+                    result[i] = suggestions[i];
+                else
+                    result[i] = suggestions[i-1];
+            }
+            return result;
+        }
+        logln(logPrefix + "Estimating parameters failed");
+        return null;
+    }
+
+
+
+private DiversificationCategModel localModel3 = new DiversificationCategModel();
+public double[] estimate3(Tree tree, CategoricalDistribution observedStates,int looseParameter, double suggestions[]){
+    //some parameters are unassigned, and thus need to be estimated
+    //First, we need to go through the parameters array to construct a mapping between our local free parameters and the original
+    final String logPrefix = "Diversif Categ Char (5 parameter starting point): ";
+    quickIterations = iterations/2;
+    MesquiteParameter [] localParams = new MesquiteParameter[6]; 
+    for(int i= 0; i<6;i++){
+        localParams[i] = new MesquiteParameter();
+        if (i % 2 == 1) // get 1,3,5
+            localParams[i].setConstrainedTo(localParams[i-1], false);            
+    }
+    localModel3.setParams(localParams);
+    double [] localSuggestions = DoubleArray.copyIntoDifferentSize(suggestions, 3, MesquiteDouble.unassigned);
+    Optimizer opt = new Optimizer(this);
+    Object[] bundle = new Object[] {tree, observedStates, localModel3};
+    stepCount = 100;
+    int numParams = 3;
+    logln("Diversif Categ Char: constraining parameters 1,3,5 to generate starting point for 4 parameter estimate");
+    logln("Diversif Categ Char: Estimating three free parameters");
+    logln("Diversif Categ Char: Estimating parameters, phase 1: step count 100");
+    double bestL = MesquiteDouble.unassigned;
+    double nLL = MesquiteDouble.unassigned;
+    int bestS = -2;
+    if (evaluate(localSuggestions,bundle)<1e99){
+        nLL = opt.optimize(localSuggestions,bundle);
+        stepCount = 1000;
+        nLL = evaluate(localSuggestions, bundle);
+        stepCount = 100;
+        logln("Diversif Categ Char 3 parameter reduced model starting suggestion: initial suggestion neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(localSuggestions));
+        if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+            bestS = -1;
+            bestL = nLL;
+        }
+    }
+    String attemptName = "random attempt";
+    double[][] randomSuggestions = new double[quickIterations][numParams];
+    for (int i = 0; i< quickIterations; i++){  
+        if (i< quickIterations/2){//0 to 1 
+            for (int k = 0; k<numParams; k++){
+                randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+            }
+        }
+        else { //00 to 10.0
+            double max =  rng.randomDoubleBetween(0, 10.0);
+            for (int k = 0; k<numParams; k++){
+                randomSuggestions[i][k] = max - 0.5 + rng.randomDoubleBetween(0, 2.0);
+            }
+            
+            if (evaluate(randomSuggestions[i], bundle) > 1e99) //likelihood bad; try a 0 to 1 one instead
+                for (int k = 0; k<numParams; k++)
+                    randomSuggestions[i][k] = rng.randomDoubleBetween(0, 1.0);
+        }
+    }
+    for (int i = 0; i< quickIterations; i++){ // 0 to 10
+        if (evaluate(randomSuggestions[i], bundle) < 1e99){  //don't start if it hits surface in NaN-land
+            logln(logPrefix + "random suggestions " + i + " :" + DoubleArray.toString(randomSuggestions[i]));
+            nLL = opt.optimize(randomSuggestions[i], bundle);
+            stepCount = 1000;
+            nLL = evaluate(randomSuggestions[i], bundle);
+            stepCount = 100;
+            logln(logPrefix + "attempt " + i + " neg. Log Likelihood:" + nLL + " : " + DoubleArray.toString(randomSuggestions[i]));
+            if (nLL < bestL || MesquiteDouble.isUnassigned(bestL)){
+                bestS = i;
+                bestL = nLL;
+                attemptName = "random attempt " + i ;
+            }
+        }
+        else 
+            logln(logPrefix + "random attempt " + i + " failed because starting position had undefined likleihood");
+    }
+    if (bestS>=-1){
+        if (bestS > 0)
+            localSuggestions = randomSuggestions[bestS];
+        logln(logPrefix + "Estimating parameters, phase 2: step count 100; best so far " + evaluate(localSuggestions, bundle));
+        stepCount = 1000;
+        logln(logPrefix + "Estimating parameters, phase 2: step count 1000; best so far " + evaluate(localSuggestions, bundle));
+        logln(logPrefix + "Estimating parameters, phase 2: step count 1000 starting from results of preliminary " + attemptName);
+        double negLogLikelihood = opt.optimize(localSuggestions, bundle);
+        logln(logPrefix + "neg. Log Likelihood final attempt:" + negLogLikelihood);
+        final double [] result = new double[4];
+        result[0] = localSuggestions[0];
+        if (looseParameter == 1){
+            result[1]=localSuggestions[0];
+            result[2]=localSuggestions[1];
+            result[3]=localSuggestions[2];
+        }
+        else if (looseParameter == 3){
+            result[1]=localSuggestions[1];
+            result[2]=localSuggestions[1];
+            result[3]=localSuggestions[2];
+        }
+        else if (looseParameter == 5){
+            result[1]=localSuggestions[1];
+            result[2]=localSuggestions[2];
+            result[3]=localSuggestions[2];                           
+        }
+
+        return result;
+    }
+    logln(logPrefix + "Estimating parameters failed");
+    return null;
+    }
+}
+
+    
+/*============================================================================*/
+class DiversificationCategModel implements DESystem  {
+    
+    MesquiteParameter[] original, parameters;
+    int[] constraintMap, effectiveParamMapping;
+    boolean[] checked;
+    
+    int messageCount = 0;   //awful thing to reduce junk output
+    public DiversificationCategModel(){
+        constraintMap = new int[6];
+        checked = new boolean[6];
+    }
+
+    public String toString(){
+        return MesquiteParameter.toString(parameters);
+    }
+    public String toStringForAnalysis(){
+        return MesquiteParameter.toStringForAnalysis(parameters);
+    }
+    public String toStringForScript(){
+        return MesquiteParameter.paramsToScriptString(parameters);
+    }
+
+ /*This is based on a reparameterization to r = s - e, a = e/s (following Nee et al)
+  How to back convert?  Given r and a, what are s and e?
+  s = r + e;
+  e = s*a;
+  thus s = r + s*a
+  s-sa =r
+  so, 
+    s = r/(1-a);  
+    e = ra/(1-a)
+  when r=0, a=1 and this doesn't work, so this should be checked
+
+*/
+    public double[] calculateDerivative(double t, double[] probs, double[] result) {
+        double extProb0 = probs[0];
+        double extProb1 = probs[1];
+        double dataProb0 = probs[2];
+        double dataProb1 = probs[3];
+        
+        double r0 = parameters[0].getValue();
+        double r1 = parameters[1].getValue();
+        double a0 = parameters[2].getValue();
+        double a1 = parameters[3].getValue();
+        double q01 = parameters[4].getValue();
+        double q10 = parameters[5].getValue();
+        
+        double lambda0 = r0/(1-a0);
+        double mu0 = r0*a0/(1-a0);
+        double lambda1 = r1/(1-a1);
+        double mu1 = r1*a1/(1-a1);
+                
+        result[0] = -(mu0+q01+lambda0)*extProb0 + lambda0*extProb0*extProb0 + mu0 + q01*extProb1; 
+        result[1] = -(mu1+q10+lambda1)*extProb1 + lambda1*extProb1*extProb1 + mu1 + q10*extProb0;            
+        result[2] = -(mu0+q01+lambda0)*dataProb0 + 2*lambda0*extProb0*dataProb0 + q01*dataProb1;
+        result[3] = -(mu1+q10+lambda1)*dataProb1 + 2*lambda1*extProb1*dataProb1 + q10*dataProb0;
+        
+        return result;
+    }
+    
+    public boolean isFullySpecified(){
+        return MesquiteParameter.numberSpecified(original) == 6;
+    }
+    public int numberSpecified(){
+        return MesquiteParameter.numberSpecified(original);
+    }
+    public int numberEffectiveParameters(){
+        if (effectiveParamMapping == null)
+            return 0;
+        return effectiveParamMapping.length;
+    }
+
+    public void setParams(MesquiteParameter[] params){
+        original = MesquiteParameter.cloneArray(params, original);
+        parameters = MesquiteParameter.cloneArray(params, parameters);
+        for (int i=0; i<6; i++){
+            int c = MesquiteParameter.getWhichConstrained(params, i);
+
+            if (c >= 0)
+                constraintMap[i] = c;
+            else
+                constraintMap[i] = i;
+            checked[i] = false;
+        }
+        int count = 0;
+        for (int i=0; i<6; i++){  //figuring out what are the unset parameters;
+            int mapee = constraintMap[i];
+            if (!checked[mapee])
+                if (!original[mapee].isCombinable())
+                    count++;
+            checked[mapee] = true;
+        }
+        if (effectiveParamMapping == null || effectiveParamMapping.length != count)
+            effectiveParamMapping = new int[count];
+        count = 0;
+        for (int i=0; i<6; i++)
+            checked[i] = false;
+        for (int i=0; i<6; i++){  //figuring out what are the unset parameters;
+            int mapee = constraintMap[i];
+            if (!checked[mapee])
+                if (!original[mapee].isCombinable()){
+                    effectiveParamMapping[count] = mapee;
+                    count++;
+                }
+            checked[mapee] = true;
+        }
+    }
+    
+    public boolean setParamValuesUsingConstraints(double[] params){
+        if (params == null || params.length == 0)
+            return true;  //nothing to do, so return success?
+        if (params.length == 6 && effectiveParamMapping == null){
+            for (int i=0; i<6; i++){
+                parameters[i].setValue(params[i]);
+                if (((i == 2) || (i == 3)) && (params[i] >= 1.0))
+                    return false;
+            }
+        }
+        else if (effectiveParamMapping== null){
+            MesquiteMessage.warnProgrammer("Diversif setParamValuesUsingConstraints with effective params NULL");
+        }
+        else if (params.length != effectiveParamMapping.length){
+            MesquiteMessage.warnProgrammer("Diverse setParamValuesUsingConstraints with effective params size mismatch " + params.length + " " + effectiveParamMapping.length);
+        }
+        else {   // this should help handling constraints between parameters in the 2-5 case
+            for (int i=0; i<params.length; i++) {
+                int mapee = effectiveParamMapping[i]; //find parameter representing constraint group
+                //now find all params constrained to it, and set them
+                for (int k = 0; k< parameters.length; k++){
+                    if (constraintMap[k] == mapee){
+                        parameters[k].setValue(params[i]);
+                        if (((k == 2) || (k==3)) && (parameters[k].getValue() >= 1.0))
+                            return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    public MesquiteParameter[] getOriginalParams(MesquiteParameter[] params){
+        return MesquiteParameter.cloneArray(original, params);
+    }
+    public MesquiteParameter[] getCurrentParams(MesquiteParameter[] params){
+        return MesquiteParameter.cloneArray(parameters, params);
+    }
+   
+    
+    public double getR(int state){
+        if (state == 0)
+            return parameters[0].getValue();
+        else if (state == 1)
+            return parameters[1].getValue();
+        else return MesquiteDouble.unassigned;
+    }
+    
+    public double getA(int state){
+        if (state == 0)
+            return parameters[2].getValue();
+        else if (state == 1)
+            return parameters[3].getValue();
+        else return MesquiteDouble.unassigned;
+    }
+    
+    //s = r/(1-a);
+    public double getSRate(int state) {
+        if (state == 0)
+            return parameters[0].getValue()/(1-parameters[2].getValue());
+        else if (state == 1)
+            return parameters[1].getValue()/(1-parameters[3].getValue());
+        else return MesquiteDouble.unassigned;
+    }
+
+    //e = ra/(1-a)
+    public double getERate(int state) {
+        if (state == 0)
+            return (parameters[0].getValue()*parameters[2].getValue())/(1-parameters[2].getValue());
+        else if (state == 1)
+            return (parameters[1].getValue()*parameters[3].getValue())/(1-parameters[3].getValue());
+        else return MesquiteDouble.unassigned;
+    }
+    public double getCRate(int state) {
+        if (state == 0)
+            return parameters[4].getValue();
+        else if (state == 1)
+            return parameters[5].getValue();
+        else return MesquiteDouble.unassigned;
+    }
+
+}
+ 
diff --git a/Source/mesquite/diverse/DiversCategCharLikelihood/DiversCategCharLikelihood.java b/Source/mesquite/diverse/DiversCategCharLikelihood/DiversCategCharLikelihood.java
new file mode 100644
index 0000000..fb79f52
--- /dev/null
+++ b/Source/mesquite/diverse/DiversCategCharLikelihood/DiversCategCharLikelihood.java
@@ -0,0 +1,204 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.DiversCategCharLikelihood;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.RequiresExactlyCategoricalData;
+import mesquite.diverse.DivCategCharMLCalculator.DivCategCharMLCalculator;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.lib.duties.NumberForCharAndTree;
+import mesquite.diverse.lib.*;
+
+public class DiversCategCharLikelihood extends NumForCharAndTreeDivers {
+    public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+        EmployeeNeed e = registerEmployeeNeed(DivCategCharMLCalculator.class, getName() + "  needs a method to calculate likelihoods.",
+        "The method to calculate likelihoods is arranged initially");
+		e.setSuppressListing(true);
+   }
+
+    DivCategCharMLCalculator calcTask;
+
+
+    MesquiteParameter r0;   //user specified diversification rate in state 0
+    MesquiteParameter a0;   //user specified extinction/speciation ratio in state 0
+    MesquiteParameter r1;   //user specified diversification rate in state 1
+    MesquiteParameter a1;   //user specified extinction/speciation ratio in state 1
+    MesquiteParameter q01;   //user specified transition rate from state 0 to state 1
+    MesquiteParameter q10;   //user specifiedtransition rate from state 1 to state 0
+
+    MesquiteParameter[] params;
+    MesquiteParameter[] paramsCopy;
+    boolean[] selected;
+
+    /*.................................................................................................................*/
+    public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+        calcTask = (DivCategCharMLCalculator)hireEmployee(DivCategCharMLCalculator.class, "Integrating Likelihood");
+        if (calcTask == null)
+            return sorry(getName() + " couldn't start because no integrating likelihood calculator module obtained.");
+        final double def = MesquiteDouble.unassigned;
+        //following is for the parameters explorer
+        r0 = new MesquiteParameter("r0", "Rate of net diversification with state 0", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        r1 = new MesquiteParameter("r1", "Rate of net diversification with state 1", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        a0 = new MesquiteParameter("a0", "Extinction/Speciation ratio with state 0", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        a1 = new MesquiteParameter("a1", "Extinction/Speciation ratio with state 1", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        q01 = new MesquiteParameter("q01", "Rate of 0->1 changes", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        q10 = new MesquiteParameter("q10", "Rate of 1->0 changes", def, 0, MesquiteDouble.infinite, 0.000, 1);
+        params = new MesquiteParameter[]{r0, r1, a0, a1, q01, q10};
+        if (!MesquiteThread.isScripting()){
+			if (!showDialog())
+				return sorry(getName() + " couldn't start because parameters not specified.");
+        }
+        addMenuItem("Set Parameters...", makeCommand("setParameters", this));
+        return true;
+    }
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+  /*.................................................................................................................*/
+    boolean showDialog(){
+        if (params == null)
+            return false;
+        ParametersDialog dlog = new ParametersDialog(containerOfModule(), "Parameters", "BiSSE Parameters", params, null, 2, 2, false);
+		dlog.appendToHelpString("Parameters for BiSSE model., reparameterized as r = net diversification  (speciation-extinction) and a = speciation/extinction ratio.  Indicate the rates of net diversification when in state 0 (r0), and when in state 1 (r1), ");
+		dlog.appendToHelpString("speciation/extinction ratio when in state 0 (a0), ratio when in state 1 (a1), ");
+		dlog.appendToHelpString("rates of character change 0 to 1(q01), and rates of character change 1 to 0 (q10). ");
+      dlog.completeAndShowDialog(true);
+        boolean ok = (dlog.query()==0);
+        if (ok) 
+            dlog.acceptParameters();
+        dlog.dispose();
+        return ok;
+    }
+    /*.................................................................................................................*/
+    public void initialize(Tree tree, CharacterDistribution charStates) {
+        // TODO Auto-generated method stub
+    }
+    
+    /*.................................................................................................................*/
+    public Snapshot getSnapshot(MesquiteFile file) {
+        Snapshot temp = new Snapshot();
+
+        temp.addLine("getIntegTask ", calcTask);
+        String pLine = MesquiteParameter.paramsToScriptString(params);
+        if (!StringUtil.blank(pLine))
+            temp.addLine("setParameters " + pLine);
+        return temp;
+    }
+    boolean setParam(MesquiteParameter p, MesquiteParameter[] params, Parser parser){
+        final double newValue = MesquiteDouble.fromString(parser);
+        int loc = parser.getPosition();
+        String token = parser.getNextToken();
+        if (token != null && "=".equals(token)){
+            int con = MesquiteInteger.fromString(parser);
+            if (MesquiteInteger.isCombinable(con) && con>=0 && con < params.length)
+                p.setConstrainedTo(params[con], false);
+        }
+        else
+            parser.setPosition(loc);
+        if ((MesquiteDouble.isUnassigned(newValue) ||  newValue >=0) && newValue != p.getValue()){
+            p.setValue(newValue); //change mode
+            return true;
+        }
+        return false;
+    }
+ 	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+
+    /*.................................................................................................................*/
+    /*  the main command handling method.  */
+    public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+        if (checker.compare(getClass(), "Sets rate parameters", "[double double double double double double]", commandName, "setParameters")) {
+            if (StringUtil.blank(arguments)){
+                if (!MesquiteThread.isScripting() && showDialog())
+                    parametersChanged();
+            }
+            else {
+                parser.setString(arguments);
+                boolean changed =  setParam(r0, params, parser);
+                boolean more = setParam(r1, params, parser);
+                changed = changed || more;
+                more = setParam(a0, params, parser);
+                changed = changed || more;
+                more = setParam(a1, params, parser);
+                changed = changed || more;
+                more = setParam(q01, params, parser);
+                changed = changed || more;
+                more = setParam(q10, params, parser);
+                changed = changed || more;
+                if (changed && !MesquiteThread.isScripting())
+                    parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+            }
+        }
+        else if (checker.compare(getClass(), "Returns integrating module", null, commandName, "getIntegTask")) {
+            return calcTask;
+        }
+        else
+            return  super.doCommand(commandName, arguments, checker);
+        return null;
+    }
+
+
+    
+    public void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+        if (result == null)
+            return;
+       	clearResultAndLastResult(result);
+
+        if (tree == null || charStates == null)
+            return;
+		if (!CategoricalDistribution.isBinaryNoMissing(charStates, tree)){
+			if (resultString!=null)
+	            resultString.setValue(getName() + " unassigned because the character is not binary or has missing data");
+			return;
+		}
+      paramsCopy = MesquiteParameter.cloneArray(params, paramsCopy);
+        calcTask.calculateLogProbability(tree, charStates, paramsCopy, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+   }
+
+    /*------------------------------------------------------------------------------------------*/
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+    public String getName() {
+        return "BiSSE Net Diversification Likelihood";
+    }
+
+    public String getAuthors() {
+        return "Peter E. Midford & Wayne P. Maddison";
+    }
+
+    public String getVersion() {
+        return "1.0";
+    }
+
+    public String getExplanation(){
+		return "Calculates likelihood with a tree of a species diversification model whose rates (r = spec. - ext.; a = spec./ext.) depend on the state of a binary character (BiSSE model, Maddison, Midford & Otto, 2007).";
+    }
+
+    public boolean isPrerelease(){
+        return false;
+    }
+
+
+}
diff --git a/Source/mesquite/diverse/EvolveTreesDiversChars/EvolveTreesDiversChars.java b/Source/mesquite/diverse/EvolveTreesDiversChars/EvolveTreesDiversChars.java
new file mode 100644
index 0000000..dd5f37e
--- /dev/null
+++ b/Source/mesquite/diverse/EvolveTreesDiversChars/EvolveTreesDiversChars.java
@@ -0,0 +1,199 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.EvolveTreesDiversChars;
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+import mesquite.diverse.lib.*;
+
+/** ======================================================================== */
+public class EvolveTreesDiversChars extends FileAssistantT {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeCharSimulate.class, getName() + "  needs a particular method to simulate trees and characters.",
+		"The method to simulate trees and characters can be selected initially");
+	}
+	/*.................................................................................................................*/
+public TreeCharSimulate simulator;
+	Taxa taxa;
+	MesquiteLong seed;
+	MesquiteFile file;
+	int numTrees = 100;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		simulator = (TreeCharSimulate)hireEmployee(TreeCharSimulate.class, "Simulator of trees and characters");
+		if (simulator == null)
+			return sorry(getName() + " couldn't start because no simulating module was obtained.");
+		seed = new MesquiteLong(originalSeed);
+		if (!MesquiteThread.isScripting()){
+			taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to evolve trees and characters?");
+			if (taxa == null)
+				return sorry("A taxa block must be created first before evolving trees with characters");
+			file = getProject().chooseFile( "Select file to which to add the trees and matrix");
+			numTrees = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of Trees", 100);
+			if (numTrees <=0 || !MesquiteInteger.isCombinable(numTrees))
+				return false;
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for Tree simulation", "Set Random Number seed for tree simulation:", seed.getValue());
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+			evolve();
+			return false;
+		}
+		taxa = getProject().getTaxa(0);
+		file = getProject().getHomeFile();
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public void evolve(){
+		if (taxa == null || numTrees <=0)
+			return;
+	    incrementMenuResetSuppression();
+	    getProject().incrementProjectWindowSuppression();
+
+	    seed.setValue(originalSeed);
+	    TreeVector trees = new TreeVector(taxa);
+	    CharactersManager charManager = (CharactersManager)getFileCoordinator().findImmediateEmployeeWithDuty(CharactersManager.class);
+	    CharacterData data= (CharacterData)charManager.newCharacterData(taxa, numTrees, simulator.getDataType());
+
+	    ObjectContainer treeContainer = new ObjectContainer();
+	    ObjectContainer charHistoryContainer = new ObjectContainer();
+	    CharacterState cs = data.makeCharacterState();
+	    long timer = System.currentTimeMillis();
+
+	    for (int i=0; i<numTrees; i++){
+
+	        CommandRecord.tick("Simulating tree and character " + i);
+
+	        if (System.currentTimeMillis()- timer > 10000){
+	            timer = System.currentTimeMillis();
+	            logln("Simulating tree " + (i + 1));
+	        }
+
+	        simulator.doSimulation(taxa, i, treeContainer, charHistoryContainer, seed);
+
+	        Object t = treeContainer.getObject();
+	        if (t == null || !(t instanceof Tree))
+	            return;//TODO: insert more informative response
+	        Object c = charHistoryContainer.getObject();
+	        if (c == null || !(c instanceof CharacterHistory))
+	            return; //TODO: insert more informative response
+	        MesquiteTree tree = (MesquiteTree)t;
+	       tree.resetTaxaInfo();
+	        CharacterHistory ch = (CharacterHistory)c;
+	        harvestStates(tree, tree.getRoot(), i, ch, data, cs);
+	        if (tree instanceof Renamable && !tree.hasName())
+	            ((Renamable)tree).setName("Simulated Tree (with character) " + (i+1));
+	        MesquiteTree clone = tree.cloneTree();
+		       clone.resetTaxaInfo();
+	        trees.addElement(clone, false);
+	        clone.setName("Simulated Tree (with character) " + (i+1));
+	        data.setCharacterName(i, "Sim. with tree " + (i+1));
+	    }
+
+	    data.addToFile(file, getProject(), findElementManager(CharacterData.class));  
+	    data.setName("Evolved on Simulated Trees [" + simulator.getParameters() + "]");
+	    trees.setName("Evolved with Characters [" + simulator.getParameters() + "]");
+	    trees.addToFile(file, getProject(), findElementManager(TreeVector.class));  
+	    data.show();
+	    trees.show();
+	    getProject().decrementProjectWindowSuppression();
+	    decrementMenuResetSuppression();
+	    resetAllMenuBars();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		final Snapshot temp = new Snapshot();
+		temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setSimulator ", simulator);
+   	 	temp.addLine("setNumTrees " + numTrees);
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		return temp;
+	}
+
+	private MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	    if (checker.compare(this.getClass(), "Sets the module doing simulations", "[name of module]", commandName, "setSimulator")) {
+	        final TreeCharSimulate temp=  (TreeCharSimulate)replaceEmployee(TreeCharSimulate.class, arguments, "Tree simulator", simulator);
+	        if (temp!=null) {
+	            simulator = temp;
+	            if (!MesquiteThread.isScripting())
+	                parametersChanged(); //?
+	        }
+	        return temp;
+	    }
+	    else if (checker.compare(this.getClass(), "Sets the random number seed", null, commandName, "setSeed")) {
+	        pos.setValue(0);
+	        originalSeed = MesquiteLong.fromString(arguments, pos);
+	        if (!MesquiteThread.isScripting())
+	            parametersChanged(); //?
+	    }
+	    else if (checker.compare(this.getClass(), "Sets the number of trees", null, commandName, "setNumTrees")) {
+	        pos.setValue(0);
+	        numTrees = MesquiteInteger.fromString(arguments, pos);
+	        if (!MesquiteThread.isScripting())
+	            parametersChanged(); //?
+	    }
+	    else if (checker.compare(this.getClass(), "Sets the taxa block used", "[block reference, number, or name]", commandName, "setTaxa")) {
+	        taxa = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+
+	    }
+	    else if (checker.compare(this.getClass(), "Evolves", null, commandName, "evolve")) {
+	        evolve();
+	    }
+	    else return  super.doCommand(commandName, arguments, checker);
+	    return null;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	private void harvestStates(Tree tree, int node, int i, CharacterHistory history, CharacterData data, CharacterState cs){
+		if (tree.nodeIsTerminal(node)) {
+			cs = history.getCharacterState(cs, node);
+			data.setState(i, tree.taxonNumberOfNode(node), cs);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			harvestStates(tree, d, i, history, data, cs);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Trees & Diversification Characters";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Evolves a series of trees, each tied to a single character controlling diversification rates." ;
+	}
+}
+
+
diff --git a/Source/mesquite/diverse/LineagesThroughTime/LineagesThroughTime.java b/Source/mesquite/diverse/LineagesThroughTime/LineagesThroughTime.java
new file mode 100755
index 0000000..75e0cb6
--- /dev/null
+++ b/Source/mesquite/diverse/LineagesThroughTime/LineagesThroughTime.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.LineagesThroughTime;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** ======================================================================== */
+public class LineagesThroughTime extends TreeWindowAssistantA {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DrawChart.class, getName() + "  needs a module to draw charts.",
+		"The module to draw charts is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	LineagesWindow lineagesWindow;
+	Tree tree;
+
+	public DrawChart charterTask;
+	int numTrees = MesquiteInteger.unassigned;
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		charterTask = (DrawChart)hireNamedEmployee(DrawChart.class, "Histogram", new MesquiteBoolean[]
+		      {new MesquiteBoolean("showMenus", false), 
+			new MesquiteBoolean("showAsBarChart", false), 
+			new MesquiteBoolean("setNoSum", true), 
+			new MesquiteBoolean("setnativeMode", true)});
+		if (charterTask == null)
+			return sorry(getName() + " couldn't start because no charting module was obtained.");
+		makeMenu("Lineages");
+		lineagesWindow= new LineagesWindow( this);
+		setModuleWindow(lineagesWindow);
+		lineagesWindow.setVisible(true);
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+
+		return true;
+	}
+	public  void setTree(Tree tree){
+		this.tree = tree;
+		if (lineagesWindow != null) {
+			lineagesWindow.setTree(tree);
+			lineagesWindow.renew();
+		}
+	}
+	public String getTreeWindow(){
+		if (getEmployer() instanceof TreeWindowMaker){
+		MesquiteWindow mw = getEmployer().containerOfModule();
+		return mw.getTitle();
+		}
+		return " in tree window";
+		
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m == charterTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if ((lineagesWindow!=null) ) 
+			lineagesWindow.renew();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (lineagesWindow ==null)
+			return null;
+		Snapshot fromWindow = lineagesWindow.getSnapshot(file);
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("makeWindow");
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+		temp.addLine("showWindow");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Makes but doesn't show the window", null, commandName, "makeWindow")) {
+			if (getModuleWindow()==null) {
+				lineagesWindow= new LineagesWindow( this);
+				setModuleWindow(lineagesWindow);
+				resetContainingMenuBar();
+				resetAllWindowsMenus();
+			}
+			return lineagesWindow;
+		}
+		else if (checker.compare(this.getClass(), "Shows the window", null, commandName, "showWindow")) {
+			if (lineagesWindow!=null)
+				lineagesWindow.setVisible(true);
+			return lineagesWindow;
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+
+
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Lineages Through Time";
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Displays a window showing plot of lineages through time averaged over many trees." ;
+	}
+}
+
+/** ======================================================================== */
+class LineagesWindow extends MesquiteWindow implements ChartListener  {
+	LineagesThroughTime MTWmodule;
+
+	int totalWidth;
+	int totalHeight;
+	MessagePanel messagePanel;
+	MesquiteChart chart;
+	Tree tree;
+	private NumberArray valuesX, valuesY, valuesZ;
+	LineagesThroughTime ownerModule;
+	public LineagesWindow (LineagesThroughTime ownerModule){
+		super(ownerModule, true); //infobar
+		this.ownerModule = ownerModule;
+		setWindowSize(500,400);
+		valuesX = new NumberArray(0);
+		valuesY = new NumberArray(0);
+		MTWmodule=ownerModule;
+		
+		setBackground(Color.white);
+
+		messagePanel=new MessagePanel(getColorScheme());
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+
+		chart=new MesquiteChart(ownerModule, 100, 0, ownerModule.charterTask.createCharter(this));
+		chart.deassignChart();
+		chart.setUseAverage(true);
+		addToWindow(chart);
+		//plot.setVisible(true);
+		sizeDisplays(false);
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Lineages Through Time (from " + ownerModule.getTreeWindow() + ")"); //TODO: what tree?
+	}
+	/*...................................................................................................................*/
+	public void pointMouseUp(MesquiteChart chart, int whichPoint, int x, int y, int modifiers, String message){
+	}
+	public void pointMouseDown(MesquiteChart chart, int whichPoint, MesquiteNumber valueX, MesquiteNumber valueY, int x, int y, int modifiers, String message){
+	}
+	/*.................................................................................................................*/
+	public void setTree(Tree tree){
+		this.tree = tree;
+	}
+	public void renew() {
+		doCalcs();
+	}
+	/*.................................................................................................................*/
+	public void setWindowSize(int width, int height){
+		super.setWindowSize(width,height);
+		sizeDisplays(false);
+	}
+	/*.................................................................................................................*/
+	public void sizeDisplays(boolean hide){
+		if (messagePanel == null)
+			return;
+		totalWidth = getWidth()-16;
+		totalHeight = getHeight() - 16;
+		chart.setBounds(0,0, totalWidth, totalHeight);
+		chart.setLocation(32, 32);
+		chart.setChartSize(getWidth()-64, getHeight()-64);
+		messagePanel.setSize(totalWidth, 16);
+		messagePanel.setLocation(0, totalHeight);
+		messagePanel.repaint();
+	}
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (tree == null)
+			return;
+		final int numTaxa = tree.getTaxa().getNumTaxa();
+		valuesX.resetSize(numTaxa);  
+		valuesY.resetSize(numTaxa); 
+		valuesX.deassignArray();
+		valuesY.deassignArray();
+		MesquiteInteger count = new MesquiteInteger(0); 
+		double[] splits = new double[numTaxa];
+		double[] balances = new double[numTaxa];
+		int point = 0;
+
+		CommandRecord.tick("Assessing lineage plot for tree ");
+		if (tree!=null && tree.allLengthsAssigned(false)) {
+			count.setValue(0);
+			double height = tree.tallestPathAboveNode(tree.getRoot());
+			if (height>0){
+				DoubleArray.zeroArray(splits);
+				if (true){
+					getSplits(tree, tree.getRoot(), splits, 0.0, count);
+					DoubleArray.sort(splits);
+					int c = 1;
+					for (int i = 0; i < splits.length; i++) {
+						if (splits[i]>0){
+							c++;
+							valuesX.setValue(point, splits[i]/height);
+							valuesY.setValue(point, Math.log(c));
+							point++;
+						}
+					}
+				}
+				else {
+					DoubleArray.zeroArray(balances);
+					getSplitsAndBalances(tree, tree.getRoot(), splits, balances, 0.0, count);
+					DoubleArray.sortByFirst(splits, balances);
+					for (int i = 0; i < splits.length; i++) {
+						if (MesquiteDouble.isCombinable(balances[i])){
+							valuesX.setValue(point, splits[i]/height);
+							valuesY.setValue(point++, balances[i]);
+						}
+					}
+				}
+			}
+		}
+
+		recalcChart();
+	}
+	void getSplits(Tree tree, int node, double[] splits, double distanceFromRoot, MesquiteInteger count){
+		if (tree.nodeIsInternal(node)) { 
+			if (tree.getRoot() != node && tree.numberOfDaughtersOfNode(node)>1) {
+				distanceFromRoot += tree.getBranchLength(node);
+				splits[count.getValue()] = distanceFromRoot;
+				count.increment();
+			}
+			else if (tree.getRoot() != node)
+				distanceFromRoot += tree.getBranchLength(node);
+
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				getSplits(tree, daughter, splits, distanceFromRoot, count);
+			}
+		}
+	}
+	void getSplitsAndBalances(Tree tree, int node, double[] splits, double[] balances, double distanceFromRoot, MesquiteInteger count){
+		if (tree.nodeIsInternal(node)) { 
+			if (tree.getRoot() != node && tree.numberOfDaughtersOfNode(node)>1) {
+				distanceFromRoot += tree.getBranchLength(node, 1.0);
+				splits[count.getValue()] = distanceFromRoot;
+				balances[count.getValue()] = balance(tree, node);
+				count.increment();
+			}
+			else if (tree.numberOfDaughtersOfNode(node)>1) {
+				splits[count.getValue()] = 0;
+				balances[count.getValue()] = balance(tree, node);
+				count.increment();
+			}
+			else if (tree.getRoot() != node)
+				distanceFromRoot += tree.getBranchLength(node, 1.0);
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				getSplitsAndBalances(tree, daughter, splits, balances, distanceFromRoot, count);
+			}
+		}
+	}
+	double balance(Tree tree, int node){
+		final int numLeft =tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node));
+		final int numRight =tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node));
+		if ((numLeft+numRight)/2*2 == numLeft + numRight)
+			return MesquiteDouble.unassigned;
+		else if (numRight>numLeft)
+			return (1.0*numLeft/(numRight + numLeft));
+		else
+			return (1.0*numRight/(numRight + numLeft));
+	}
+	/*.................................................................................................................*/
+	public void recalcChart(){
+		chart.deassignChart();
+		chart.getCharter().setShowNames(true);
+		if (tree == null){
+		    chart.setXAxisName("Length from Root");
+		    chart.setYAxisName("Log of Number of Lineages");
+		}
+		else {
+			chart.setXAxisName("Length from Root (tree: " + tree.getName() + ")");
+			chart.setYAxisName("Log of Number of Lineages (tree: " + tree.getName() + ")");
+		}
+		final MesquiteNumber resultX = new MesquiteNumber();
+		final MesquiteNumber resultY = new MesquiteNumber();
+
+		for (int i=0; i<valuesX.getSize(); i++) {
+			valuesX.placeValue(i, resultX);
+			valuesY.placeValue(i, resultY);
+			chart.addPoint(resultX, resultY);
+		}
+		chart.munch();
+	}
+	/*.................................................................................................................*/
+	public void windowResized() {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		sizeDisplays(false);
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+class LinPanel extends MesquitePanel {
+	LineagesWindow window;
+	public LinPanel (LineagesWindow window) {
+		this.window = window;
+		setBackground(Color.blue);
+	}
+}
diff --git a/Source/mesquite/diverse/SisterDiversification/SisterDiversification.java b/Source/mesquite/diverse/SisterDiversification/SisterDiversification.java
new file mode 100644
index 0000000..b7c724f
--- /dev/null
+++ b/Source/mesquite/diverse/SisterDiversification/SisterDiversification.java
@@ -0,0 +1,152 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.SisterDiversification;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.diverse.lib.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public class SisterDiversification extends NumForCharAndTreeDivers  {
+	MesquiteNumber[] distrib = new MesquiteNumber[3];
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		distrib[0] = new MesquiteNumber();
+		distrib[0].setName("Sister pairs with 0 clade larger");
+		distrib[1] = new MesquiteNumber();
+		distrib[1].setName("Sister pairs with 1 clade larger");
+		distrib[2] = new MesquiteNumber();
+		distrib[2].setName("Sister pairs with 0-1 clades equal");
+		return true; 
+ 	}
+ 	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+/*.................................................................................................................*/
+	public void initialize(Tree tree, CharacterDistribution states) {
+  	 }
+	
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public long statesAbove(int node, Tree tree, CategoricalDistribution states) {
+		if (tree.nodeIsTerminal(node))
+			return states.getState(tree.taxonNumberOfNode(node));
+		long left = statesAbove(tree.firstDaughterOfNode(node), tree, states);
+		long right = statesAbove(tree.lastDaughterOfNode(node), tree, states);
+		if (CategoricalState.cardinality(left) == 1 && CategoricalState.cardinality(right) ==1 && CategoricalState.cardinality(left | right) > 1){
+			int leftState = CategoricalState.minimum(left);
+			int rightState = CategoricalState.minimum(right);
+			if (leftState == 0 && rightState == 1){
+				if (tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node)) > tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node))){ //first, left, 0 is bigger
+					win0++;
+				}
+				else if (tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node)) < tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node))){ //first, left, 1 is bigger
+					win1++;
+				}
+				else
+					balance01++;
+			}
+			else if (leftState == 1 && rightState == 0){
+				if (tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node)) > tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node))){ //first, left, 0 is bigger
+					win1++;
+				}
+				else if (tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node)) < tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node))){ //first, left, 1 is bigger
+					win0++;
+				}
+				else
+					balance01++;
+			}
+		}
+			return left | right;
+	}
+	int win1 = 0;
+	int win0 =0;
+	int balance01 = 0;
+	/*.................................................................................................................*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+	    if (result==null)
+	        return;
+
+	    clearResultAndLastResult(result);
+	    if (tree==null || observedStates==null) {
+	        if (resultString!=null)
+	            resultString.setValue("Sister diversification unassigned because no tree or no character supplied");
+	        return;
+	    }
+	    if (!CategoricalDistribution.isBinaryNoMissing(observedStates, tree)){
+	        if (resultString!=null)
+	            resultString.setValue(getName() + " unassigned because the character is not binary or has missing data");
+	        return;
+	    }
+
+	    win0 = 0;
+	    win1 = 0;
+	    balance01 = 0;
+	    statesAbove(tree.getRoot(), tree, (CategoricalDistribution)observedStates);
+	    //assumes state 1 is 
+	    int n = win0 + win1;
+	    if (n>=0){
+	        double sum = 0;
+	        for (int i=win1; i<=n; i++)
+	            sum += Binomial.probability(n, i, 0.5);
+	        result.setValue(sum);
+	        if (resultString != null)
+	            resultString.setValue("Sister Diversification Binomial P= " + sum);
+	    }
+	    else
+	        if (resultString!=null)
+	            resultString.setValue("Sister diversification unassigned because no appropriate comparisons found");
+	    result.setName("P-value");
+	    distrib[0].setValue(win0);
+	    distrib[1].setValue(win1);
+	    distrib[2].setValue(balance01);
+	    result.copyAuxiliaries(distrib);
+	    saveLastResult(result);
+	    saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+	    return "Sister Diversification";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+	    return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+	    return false;
+	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Compares sister clades and returns the P value of the one-tailed null hypothesis that uniform clades of state 1 are smaller than uniform clades of state 0 among those with different values (P value calculated by Binomial probability)." ;
+   	 }
+  	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+	 
+}
+
+
diff --git a/Source/mesquite/diverse/SpecExtincLikelihood/SpecExtincLikelihood.java b/Source/mesquite/diverse/SpecExtincLikelihood/SpecExtincLikelihood.java
new file mode 100644
index 0000000..15aab99
--- /dev/null
+++ b/Source/mesquite/diverse/SpecExtincLikelihood/SpecExtincLikelihood.java
@@ -0,0 +1,186 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.SpecExtincLikelihood;
+
+
+import mesquite.diverse.SpecExtincMLCalculator.SpecExtincMLCalculator;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+import mesquite.diverse.lib.*;
+
+public class SpecExtincLikelihood extends NumberForTreeDivers  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(SpecExtincMLCalculator.class, getName() + "  needs a method to calculate likelihoods.",
+		"The method to calculate likelihoods is arranged initially");
+	}
+	/*.................................................................................................................*/
+
+	static final double root10=Math.sqrt(10.0);
+
+	SpecExtincMLCalculator calcTask;
+
+/*	MesquiteParameter sp = new MesquiteParameter(); //used only for parameter exploration
+	MesquiteParameter ep = new MesquiteParameter();//used only for parameter exploration
+
+	MesquiteParameter[] parameters;
+	ParametersExplorer explorer;
+*/
+
+	MesquiteDouble lambda = new MesquiteDouble();   //speciation rate
+	MesquiteDouble mu = new MesquiteDouble();   //extinction rate
+
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	public boolean startJob(String arguments, Object condition,
+			boolean hiredByName) {
+		calcTask = (SpecExtincMLCalculator)hireEmployee(SpecExtincMLCalculator.class, "Integrating Likelihood");
+		if (calcTask == null)
+			return sorry(getName() + " couldn't start because no integrating likelihood calculator module obtained.");
+
+		addMenuItem("Set Speciation Rate...", makeCommand("setS", this));
+		addMenuItem("Set Extinction Rate...", makeCommand("setE", this));
+		addMenuItem("-", null);
+		addMenuItem("Write table to console", makeCommand("writeTable",this));
+		addMenuItem("Write code for R to console", makeCommand("writeForExternalApp",this));
+
+
+		/*
+		// Test model will dump values to console for fixed branch lenght and different e values
+		testModel = new SpecExtincCladeModel(1E6,0.001);
+		//testModel.setS(0.000001);
+		Vector integrationResults = null;
+		double x = 0;
+		double length = 1.0;
+		int STEP_COUNT = 1000;
+		double h = length/STEP_COUNT;       //this will need tweaking!
+		double[] yStart = new double[2];
+		yStart[0] = 0;
+		yStart[1] = 1;
+		//double [] eVals = {0, 1E-8,(root10*1E-8),1E-7,(root10*1E-7),1E-6,(root10*1E-6),1E-5,(root10*1E-5),1E-4,(root10*1E-4),1E-3,(root10*1E-3),1E-2,(root10*1E-2),1E-1,(root10*1E-1),1,root10,10};
+		//double [] sVals = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30};
+		double [] eVals = {0.3,0.6,0.9,1.2,1.5,1.8,2.1,2.4,2.7,3.0};
+		double [] sVals = {0.3,0.6,0.9,1.2,1.5,1.8,2.1,2.4,2.7,3.0};
+		//System.out.println("S is " + testModel.getSRate(0));
+		System.out.println("Test model: columns are s, e, E, D, D/1-E");
+		for (int i=0;i<sVals.length;i++){
+			testModel.setS(sVals[i]);
+			for (int j=0;j<eVals.length;j++){
+				testModel.setE(eVals[j]);
+				integrationResults = solver.integrate(x,yStart,h,length,testModel,integrationResults,false); 
+
+				double[] yEnd = (double[])integrationResults.lastElement();
+
+				System.out.println(sVals[i]+"\t" + eVals[j]+"\t" + yEnd[0] + "\t"+ yEnd[1] + "\t"+ (yEnd[1]/(1-yEnd[0])));
+			}
+		}
+		*/
+		return true;
+	}
+
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getIntegTask ", calcTask);
+		temp.addLine("setS " + MesquiteDouble.toString(lambda.getValue()));
+		temp.addLine("setE " + MesquiteDouble.toString(mu.getValue()));
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets extinction rate", "[double]", commandName, "setE")) {
+			double newE = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(newE) && !MesquiteThread.isScripting())
+				newE = MesquiteDouble.queryDouble(containerOfModule(), "mu", "Instantaneous extinction rate", mu.getValue());
+			if ((MesquiteDouble.isUnassigned(newE) ||  newE >=0) && newE != mu.getValue()){
+				mu.setValue(newE); //change mode
+				if (!MesquiteThread.isScripting())
+				parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Returns integrating module", null, commandName, "getIntegTask")) {
+			return calcTask;
+		}
+		else if (checker.compare(getClass(), "Sets speciation rate", "[double]", commandName, "setS")) {
+			double newS = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(newS) && !MesquiteThread.isScripting())
+				newS = MesquiteDouble.queryDouble(containerOfModule(), "lambda", "Instantaneous speciation rate", lambda.getValue());
+			if ((MesquiteDouble.isUnassigned(newS) || newS >=0) && newS != lambda.getValue()){
+				lambda.setValue(newS); //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	MesquiteDouble tempLambda = new MesquiteDouble();
+	MesquiteDouble tempMu = new MesquiteDouble();
+	/*---------------------------------------------------------------------------------*/
+	public void calculateNumber(Tree tree,MesquiteNumber result, MesquiteString resultString) {
+		if (result == null)
+			return;
+	   	clearResultAndLastResult(result);
+
+		if (tree == null)
+			return;
+		tempLambda.setValue(lambda.getValue());
+		tempMu.setValue(mu.getValue());
+		calcTask.calculateLogProbability(tree, result, tempLambda, tempMu, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+
+	}
+	
+	/*---------------------------------------------------------------------------------*/
+	public void initialize(Tree tree, CharacterDistribution charStates) {
+		// TODO Auto-generated method stub
+	}
+	/*---------------------------------------------------------------------------------*/
+
+	public String getName() {
+		return "Speciation/Extinction Likelihood";
+	}
+
+	public String getAuthors() {
+		return "Peter E. Midford, Wayne P. Maddison & Sarah P. Otto";
+	}
+
+	public String getVersion() {
+		return "1.0";
+	}
+
+	public String getExplanation(){
+		return "Calculates likelihoods using a speciation/extinction model reduced from the BiSSE model (Maddison, Midford & Otto 2007) ";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+
+
+}
diff --git a/Source/mesquite/diverse/SpecExtincMLCalculator/SpecExtincMLCalculator.java b/Source/mesquite/diverse/SpecExtincMLCalculator/SpecExtincMLCalculator.java
new file mode 100644
index 0000000..1d2e9ba
--- /dev/null
+++ b/Source/mesquite/diverse/SpecExtincMLCalculator/SpecExtincMLCalculator.java
@@ -0,0 +1,578 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.SpecExtincMLCalculator;
+
+import java.util.Vector;
+
+import mesquite.diverse.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.ParametersExplorer;
+
+public class SpecExtincMLCalculator extends MesquiteModule implements ParametersExplorable, Evaluator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ParametersExplorer.class, getName() + "  uses a Parameters Explorer to show likelihood surfaces.",
+		"The parameter explorer is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+	// bunch of stuff copied from zMargLikeCateg - need to prune!!
+
+	double [] probsExt, probsData;
+	double[] yStart;  //initial value for numerical integration
+
+	MesquiteNumber probabilityValue;
+
+	long underflowCheckFrequency = -1; //2;  //how often to check that not about to underflow; 1 checks every time
+	long underflowCheck = 1;
+	double underflowCompensation = 1;
+	MesquiteNumber minChecker;
+
+	// Number of steps per branch, reduce for a faster, possibily sloppier result
+	double stepCount = 1000;  //default 10000
+
+	MesquiteBoolean intermediatesToConsole = new MesquiteBoolean(false);
+	MesquiteBoolean conditionOnSurvival;
+
+	boolean[] deleted = null;
+	SpecExtincModel model;
+	DEQNumSolver solver;
+
+	MesquiteParameter sp = new MesquiteParameter(); //used only for parameter exploration
+	MesquiteParameter ep = new MesquiteParameter();//used only for parameter exploration
+	MesquiteParameter[] parameters;
+	ParametersExplorer explorer;
+	MesquiteNumber[] paramsToReport = new MesquiteNumber[2];
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		solver = new RK4Solver();
+		probabilityValue = new MesquiteNumber();
+		minChecker = new MesquiteNumber(MesquiteDouble.unassigned);
+		model = new SpecExtincModel(MesquiteDouble.unassigned, MesquiteDouble.unassigned);
+		conditionOnSurvival = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Condition on Survival", MesquiteModule.makeCommand("conditionOnSurvival", this), conditionOnSurvival);
+		addMenuItem("Show Parameters Explorer", makeCommand("showParamExplorer",this));
+		addMenuItem("Steps per Branch...", makeCommand("setStepCount", this));
+		addCheckMenuItem(null, "Intermediates to console", makeCommand("toggleIntermediatesToConsole",this), intermediatesToConsole);
+
+		MesquiteSubmenuSpec mLO = addSubmenu(null, "Likelihood Optimization", null); 
+		addItemToSubmenu(null, mLO, "Underflow Checking...", makeCommand("setUnderflowCheckFreq", this));
+		//following is for the parameters explorer
+		sp.setName("lambda");
+		sp.setExplanation("Rate of speciation");
+		sp.setMinimumAllowed(0);
+		sp.setMaximumAllowed(MesquiteDouble.infinite);
+		sp.setMinimumSuggested(0.0000);
+		sp.setMaximumSuggested(1);
+		sp.setValue(0.1);
+		ep.setName("mu");
+		ep.setExplanation("Rate of extinction");
+		ep.setMinimumSuggested(0.0000);
+		ep.setMaximumSuggested(1);
+		ep.setMinimumAllowed(0);
+		ep.setMaximumAllowed(MesquiteDouble.infinite);
+		ep.setValue(0.01);
+		parameters = new MesquiteParameter[]{sp, ep};
+		paramsToReport[0] = new MesquiteNumber();
+		paramsToReport[0].setName("lambda (sp. rate)");
+		paramsToReport[1] = new MesquiteNumber();
+		paramsToReport[1].setName("mu (ext. rate)");
+		return true;
+	}
+	public void employeeQuit(MesquiteModule employee){
+		if (employee == explorer)
+			explorer = null;
+	}
+
+
+	boolean reportCladeValues = false;
+	public void setReportCladeLocalValues(boolean reportCladeValues){
+		this.reportCladeValues = reportCladeValues;
+	}
+	public boolean getReportCladeLocalValues(){
+		return reportCladeValues;
+	}
+	public Snapshot getSnapshot(MesquiteFile file) {
+		final Snapshot temp = new Snapshot();
+		temp.addLine("setUnderflowCheckFreq " + underflowCheckFrequency);
+		temp.addLine("setStepCount " + stepCount);
+		temp.addLine("conditionOnSurvival  " + conditionOnSurvival.toOffOnString());
+		if (explorer != null)
+			temp.addLine("showParamExplorer ", explorer);
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets the frequency of checking for underflow", "[integer, 1 or greater]", commandName, "setUnderflowCheckFreq")) {
+			int freq = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(freq) && !MesquiteThread.isScripting())
+				freq = MesquiteInteger.queryInteger(containerOfModule(), "Checking frequency", "Frequency at which underflow checking is performed in likelihood calculations.  A value of n means checking is performed on each nth calculation; higher numbers mean the calculations go faster but are at risk of underflow problems.  Values over 10 are not recommended", (int)underflowCheckFrequency, 1, 10000);
+
+			if (MesquiteInteger.isCombinable(freq) && freq >=0 && freq!=underflowCheckFrequency){
+				underflowCheckFrequency = freq; //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Show Parameter Explorer", "", commandName, "showParamExplorer")) {
+			explorer = (ParametersExplorer)hireEmployee(ParametersExplorer.class, "Parameters explorer");
+			if (explorer == null)
+				return null;
+			// explorer.makeMenu("Parameters");
+			explorer.setExplorable(this);
+			return explorer;
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to condition by survival", "[on; off]", commandName, "conditionOnSurvival")) {
+			conditionOnSurvival.toggleValue(new Parser().getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(getClass(), "Sets the number of steps per branch", "[integer, 1 or greater]", commandName, "setStepCount")) {
+			double steps = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(steps) && !MesquiteThread.isScripting())
+				steps = MesquiteDouble.queryDouble(containerOfModule(), "Steps per branch", "Number of divisions of each branch for numerical integration.  Higher numbers mean the calculations are more accurate but go more slowly.  Values under 100 are not recommended", stepCount, 10, 1000000);
+
+			if (MesquiteDouble.isCombinable(steps) && steps >=0 && steps!=stepCount){
+				stepCount = steps; //change mode
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(),"Sets whether to write intermediate branch values to console","[on; off]", commandName, "toggleIntermediatesToConsole")){
+			intermediatesToConsole.toggleValue(parser.getFirstToken(arguments));
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*---------------------------------------------------------------------------------*/
+	public void parametersChangedNotifyExpl(Notification n){
+		if (!MesquiteThread.isScripting())
+			parametersChanged(n);
+
+		if (explorer != null)
+			explorer.explorableChanged(this);
+	}
+	/*.................................................................................................................*/
+	private void initProbs(int nodes) {
+		if (probsData==null || probsData.length!=nodes){
+			probsData = new double[nodes];
+			probsExt = new double[nodes];
+			yStart = new double[2];
+		}
+		DoubleArray.zeroArray(probsData);
+		DoubleArray.zeroArray(probsExt);
+		DoubleArray.zeroArray(yStart);
+	}
+
+
+	/*.................................................................................................................*/
+	/* assumes hard polytomies */
+
+	// This might hold the intermediate step results if requested for debugging
+	Vector integrationResults = null;
+
+	/* now returns underflow compensation */
+	private double downPass(int node, Tree tree, SpecExtincModel model, DEQNumSolver solver) {
+		double logComp;
+		double d = 1;
+		double e = 0;
+		if (tree.nodeIsTerminal(node)) { //initial conditions from observations if terminal
+			e = 0;
+			d = 1;
+			logComp = 0.0;  // no compensation required yet
+		}
+		else { //initial conditions from daughters if internal
+			logComp = 0.0;
+			for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+				logComp += downPass(nd,tree,model,solver);
+			}
+
+			d = 1;  //two here to anticipate two daughters???
+			e = 1;
+			//TODO: either filter to permit only ultrametric, or redo calculations to permit extinct nodes.
+			//TODO: likewise for polytomies
+			for (int nd = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(nd); nd = tree.nextSisterOfNode(nd, deleted)) {
+				e = probsExt[nd];
+				d *= probsData[nd];
+			}
+
+			if (node != tree.getRoot()){  //condition on splitting at root; thus don't include rate if at root
+				d *= model.getS();
+			}
+
+
+			if (underflowCheckFrequency>=0 && ++underflowCheck % underflowCheckFrequency == 0){
+				if (d  < 0.01) {
+					logComp +=  -Math.log(d);
+					d = 1.0;
+				}
+			}
+		}
+		if (node == tree.getRoot()){
+			probsExt[node]= e;
+			probsData[node] = d;
+
+			return logComp;
+		}
+		else{
+			double x = 0;
+			double length = tree.getBranchLength(node,1.0,deleted);
+			double h = length/stepCount;       //this will need tweaking!
+
+			yStart[0] = e;
+			yStart[1] = d;
+
+			if (intermediatesToConsole.getValue()){
+				MesquiteMessage.print("node " + node);
+				if (node == tree.getRoot())
+					MesquiteMessage.println(" is root");
+				else
+					MesquiteMessage.println("");
+				MesquiteMessage.println("At start, y is " + DoubleArray.toString(yStart));
+			}
+			integrationResults = solver.integrate(x,yStart,h,length,model,integrationResults,intermediatesToConsole.getValue());    
+			if (integrationResults == null)
+				return MesquiteDouble.unassigned;
+			double[] yEnd = (double[])integrationResults.lastElement();
+			if (yEnd.length == 2){
+
+				probsExt[node] = yEnd[0];
+				probsData[node] = yEnd[1];
+
+			}
+			else {
+				MesquiteMessage.warnProgrammer("Vector returned by solver not the same size supplied!");
+
+				probsExt[node]=0;   //is this the right thing here?
+				probsData[node]=0;  //this is probably the best choice here
+
+			}
+			if (intermediatesToConsole.getValue()){
+				MesquiteMessage.println("Intermediate values");
+				StringBuffer stateMsg = new StringBuffer(1000);
+				//stateMsg.delete(0,stateMsg.length());  //flush everything
+				x = h;
+				double [] tempResults;
+				for(int i=0;i<integrationResults.size();i++){
+					if(i%100 == 0){
+						String xString = MesquiteDouble.toFixedWidthString(x, 13, false);
+						stateMsg.append("x= "+ xString + " y =[");
+						tempResults = (double[])integrationResults.get(i);
+						for(int j=0;j<tempResults.length;j++)
+							stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+						stateMsg.append("]\n");
+					}   
+					x += h;
+				}
+				stateMsg.append("Final value; \n");
+				stateMsg.append("x= " + h*stepCount + " y =[");
+				tempResults = (double[])integrationResults.lastElement();
+				for(int j=0;j<tempResults.length;j++)
+					stateMsg.append(MesquiteDouble.toFixedWidthString(tempResults[j],13,false)+" ");
+				stateMsg.append("]\n");
+				MesquiteMessage.println(stateMsg.toString());
+			}
+			return logComp;
+		}
+	}
+
+	/*------------------------------------------------------------------------------------------*/
+	/** these methods for ParametersExplorable interface */
+	public MesquiteParameter[] getExplorableParameters(){
+		return parameters;
+	}
+	public void restoreAfterExploration(){
+	}
+	MesquiteNumber likelihood = new MesquiteNumber();
+	MesquiteDouble lamdaExp = new MesquiteDouble();
+	MesquiteDouble muExp = new MesquiteDouble();
+
+	public double calculate(MesquiteString resultString){
+		lamdaExp.setValue(sp.getValue());
+		muExp.setValue(ep.getValue());
+		calculateLogProbability( lastTree, likelihood, lamdaExp, muExp, resultString);
+		return likelihood.getDoubleValue();
+	}
+	Tree lastTree;
+
+	/*.................................................................................................................*/
+	MesquiteDouble tempLambda = new MesquiteDouble();
+	MesquiteDouble tempMu = new MesquiteDouble();
+	long count = 0;
+	/*.................................................................................................................*/
+	boolean anyNegativeOrUncombinable(double[] params){
+		if (params == null)
+			return false;
+		for (int i=0; i<params.length; i++) {
+			if (params[i]<0)
+				return true;
+			else if (!MesquiteDouble.isCombinable(params[i]))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public double evaluate(double[] params, Object bundle){
+		if (anyNegativeOrUncombinable(params))
+			return 1e100;
+		if (params.length == 2) {
+			double result = logLike((Tree)((Object[])bundle)[0], params[0], params[1]);
+			if (count++ % 10 == 0)
+				CommandRecord.tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + "  lambda " + params[0] + " mu " + params[1]);
+			return result;
+		}
+		final Object[] b = ((Object[])bundle);
+		Tree tree = (Tree)b[0];
+		MesquiteDouble lambda = (MesquiteDouble)b[1];
+		MesquiteDouble mu = (MesquiteDouble)b[2];
+
+		double result = 0;
+		if (lambda.isUnassigned())
+			result = logLike(tree, params[0], mu.getValue());
+		else if (mu.isUnassigned())
+			result = logLike(tree, lambda.getValue(), params[0]);
+		else
+			result = MesquiteDouble.unassigned;
+		if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result > 1e100)
+			result = 1e100;
+		if (count++ % 10 == 0)
+			CommandRecord.tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + "  lambda " + lambda + " mu " + mu);
+		return result;
+	}
+	/*.................................................................................................................*/
+	public double evaluate(MesquiteDouble param, Object bundle){
+		if (!param.isCombinable() || param.getValue()<0)
+			return 1e100;
+		final Object[] b = ((Object[])bundle);
+		Tree tree = (Tree)b[0];
+		MesquiteDouble lambda = (MesquiteDouble)b[1];
+		MesquiteDouble mu = (MesquiteDouble)b[2];
+		
+		double result = 0;
+		if (lambda.isUnassigned())
+			result = logLike(tree, param.getValue(), mu.getValue());
+		else if (mu.isUnassigned())
+			result = logLike(tree, lambda.getValue(), param.getValue());
+		else
+			result = MesquiteDouble.unassigned;
+		if (!MesquiteDouble.isCombinable(result) || result < -1e100 || result > 1e100)
+			result = 1e100;
+		if (count++ % 10 == 0)
+			CommandRecord.tick("Evaluating: -log likelihood " + MesquiteDouble.toStringDigitsSpecified(result, 4) + "  lambda " + lambda + " mu " + mu);
+		return result;
+	}
+
+	/*.................................................................................................................*/
+	public double logLike(Tree tree, double lambda, double mu) {  
+		if (model==null)
+			return MesquiteDouble.unassigned;
+		model.setE(mu);
+		model.setS(lambda);
+		initProbs(tree.getNumNodeSpaces());
+		final int root = tree.getRoot(deleted);
+		double  logComp = downPass(root, tree, model, solver);
+		double likelihood = 0.0;
+		if (conditionOnSurvival.getValue())
+			likelihood = probsData[root]/(1-probsExt[root])/(1-probsExt[root]);
+		else
+			likelihood = probsData[root];
+		return (-(Math.log(likelihood) - logComp));
+	}
+	/*.................................................................................................................*/
+	public void calculateLogProbability(Tree tree, MesquiteNumber prob, MesquiteDouble lambda, MesquiteDouble mu, MesquiteString resultString) {  
+		if (model==null ||  prob == null || lambda ==null || mu == null)
+			return;
+		lastTree = tree;
+		prob.setToUnassigned();
+		String estimatedLambda = "";
+		String estimatedMu = "";
+
+		double negLogLikelihood = MesquiteDouble.unassigned;
+		//if lambda and mu are not both specified, then estimate
+		if (lambda.isUnassigned() || mu.isUnassigned()){
+			double currentE = model.getE();
+			double currentS = model.getS();
+			final Optimizer opt = new Optimizer(this);
+			final Object[] bundle = new Object[] {tree, lambda, mu};
+			if (lambda.isUnassigned() && mu.isUnassigned()){ //both unassigned
+				double[] suggestions = new double[]{1, 1};
+				logln("Sp/Ext: Estimating parameters");
+				negLogLikelihood = opt.optimize(suggestions, bundle);
+				lambda.setValue(suggestions[0]);
+				mu.setValue(suggestions[1]);
+				estimatedLambda = "[est.]";
+				estimatedMu = "[est.]";
+			}
+			else { //one of two unassigned
+				/*
+					double[] suggestions = new double[]{1};
+					negLogLikelihood = opt.optimize(suggestions, bundle);
+					lambda.setValue(suggestions[0]);
+					/**/
+				/**/
+				MesquiteDouble suggestion = new MesquiteDouble(1);
+				double currentStep = stepCount;
+				stepCount = 100;
+				logln("Sp/Ext: Estimating parameters, phase 1: step count 100");
+				negLogLikelihood = opt.optimize(suggestion, 0.0, 10, bundle);
+				logln("Sp/Ext: neg. Log Likelihood first attempt:" + negLogLikelihood);
+				double best = negLogLikelihood;
+				double first = suggestion.getValue();
+				negLogLikelihood = opt.optimize(suggestion, 0.0, 100, bundle);
+				logln("Sp/Ext: neg. Log Likelihood second attempt:" + negLogLikelihood);
+				if (best < negLogLikelihood)
+					suggestion.setValue(first);
+				stepCount = 1000;
+				logln("Sp/Ext: Estimating parameters, phase 2: step count 1000");
+				negLogLikelihood = opt.optimize(suggestion, suggestion.getValue() * 0.6, suggestion.getValue() * 1.4, bundle);
+				logln("Sp/Ext: neg. Log Likelihood final attempt:" + negLogLikelihood);
+				stepCount = currentStep;
+				if (lambda.isUnassigned()){
+					lambda.setValue(suggestion.getValue());
+					/**/
+					estimatedLambda = "[est.]";
+				}
+				else {
+					mu.setValue(suggestion.getValue()); /**/
+					estimatedMu = "[est.]";
+				}
+			}
+			model.setE(currentE);
+			model.setS(currentS);
+		}
+		else 
+			negLogLikelihood = logLike(tree, lambda.getValue(), mu.getValue());
+		/*======*
+		model.setE(mu.getValue());
+		model.setS(lambda.getValue());
+        initProbs(tree.getNumNodeSpaces());
+		int root = tree.getRoot(deleted);
+		double  logComp = downPass(root, tree,model, solver);
+		double likelihood = 0.0;
+		if (conditionOnSurvival.getValue())
+			likelihood = probsData[root]/(1-probsExt[root])/(1-probsExt[root]);
+		else
+			likelihood = probsData[root];
+
+		double negLogLikelihood = -(Math.log(likelihood) - logComp);
+		/*======*/
+
+		if (prob!=null){
+			prob.setValue(negLogLikelihood);
+			paramsToReport[0].setValue(lambda.getValue());
+			paramsToReport[1].setValue(mu.getValue());
+			prob.copyAuxiliaries(paramsToReport);
+			prob.setName("Speciation/Extinction -lnLikelihood");
+	}
+	double likelihood = Math.exp(-negLogLikelihood);
+		if (MesquiteDouble.isUnassigned(negLogLikelihood))
+			likelihood = MesquiteDouble.unassigned;
+		if (resultString!=null) {
+			String s = "Sp/Ext Likelihood with spec. rate " + lambda + " " + estimatedLambda + "; ext. rate " + mu + " " + estimatedMu + ";  -log L.:"+ MesquiteDouble.toString(negLogLikelihood) + " [L. "+ MesquiteDouble.toString(likelihood) + "]";
+			s += "  " + getParameters();
+			resultString.setValue(s);
+		}
+	}
+
+
+	public Class getDutyClass() {
+		return SpecExtincMLCalculator.class;
+	}
+
+	public String getName() {
+		return "Speciation/extinction Likelihood Calculator";
+	}
+	public String getAuthors() {
+		return "Peter E. Midford & Wayne P. Maddison";
+	}
+
+	public String getVersion() {
+		return "1.0";
+	}
+
+	public String getExplanation(){
+		return "Calculates likelihoods using a speciation/extinction model reduced from the BiSSE model (Maddison, Midford & Otto 2007) ";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+}
+
+class SpecExtincModel implements DESystem {
+
+	private double e;   //extinction rate in state 0
+	private double s;   //speciation rate in state 0
+
+	public SpecExtincModel(double e, double s){
+		this.e = e;
+		this.s = s;
+	}
+
+	public boolean isFullySpecified(){
+		return MesquiteDouble.isCombinable(e) && MesquiteDouble.isCombinable(s);
+	}
+
+	/*
+	 *  The probability values are passed the probs array in the following order
+	 *  probs[0] = E0 = extinction probability in lineage starting at t in the past at state 0
+	 *  probs[1] = P0 = probability of explaining the data, given system is in state 0 at time t
+	 * @see mesquite.correl.lib.DESystem#calculateDerivative(double, double[])
+	 */
+	public String toString(){
+		return "Speciation/Extinction Model lambda=" + MesquiteDouble.toStringDigitsSpecified(s, 4) + " mu=" + MesquiteDouble.toStringDigitsSpecified(e, 4);
+	}
+
+	/*.................................................................................................................*/
+	public double[]calculateDerivative(double t,double probs[],double[] result){
+		// for clarity
+		final double extProb = probs[0];
+		final double dataProb = probs[1];
+		result[0] = -(e+s)*extProb + s*extProb*extProb + e; 
+		result[1] = -(e+s)*dataProb + 2*s*extProb*dataProb;
+		return result;
+	}
+
+	public void setE(double e){
+		this.e = e;
+	}
+
+	public void setS(double s){
+		this.s = s;
+	}
+
+
+	public double getS() {
+		return s;
+	}
+
+	public double getE() {
+		return e;
+	}
+}
+
diff --git a/Source/mesquite/diverse/aDiverseIntro/aDiverseIntro.java b/Source/mesquite/diverse/aDiverseIntro/aDiverseIntro.java
new file mode 100644
index 0000000..7839462
--- /dev/null
+++ b/Source/mesquite/diverse/aDiverseIntro/aDiverseIntro.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.aDiverseIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.coalesce.lib.*;
+
+
+/* ======================================================================== */
+public class aDiverseIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aDiverseIntro.class;
+  	 }
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Diverse is a Mesquite package for examining speciation and extinction.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Diverse Package";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Midford, P. & W.P. Maddison. 2014.  Diverse Package for Mesquite.  Version 3.00. http://mesquiteproject.org";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "3.00";
+   	 }
+ 	/*.................................................................................................................*/
+  	 public int getVersionOfFirstRelease() {
+		return 200;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "P. Midford & W. Maddison";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean hasSplash() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Diverse Package";
+ 	}
+}
+
diff --git a/Source/mesquite/diverse/aDiverseIntro/splash.gif b/Source/mesquite/diverse/aDiverseIntro/splash.gif
new file mode 100644
index 0000000..63f9a87
Binary files /dev/null and b/Source/mesquite/diverse/aDiverseIntro/splash.gif differ
diff --git a/Source/mesquite/diverse/lib/DEQNumSolver.java b/Source/mesquite/diverse/lib/DEQNumSolver.java
new file mode 100644
index 0000000..426a1d1
--- /dev/null
+++ b/Source/mesquite/diverse/lib/DEQNumSolver.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.lib;
+
+import java.util.Vector;
+
+
+public interface DEQNumSolver {
+
+	public double[] integrate(double x0, double[]y0, double h, double xend, DESystem ds,double[] results);
+
+	// Version that saves the intermediate points on the interval - 'answer' is results.lastElement()
+	public Vector integrate(double x0, double[]y0, double h, double xend, DESystem ds,Vector results,boolean saveResults);
+	
+}
diff --git a/Source/mesquite/diverse/lib/DESystem.java b/Source/mesquite/diverse/lib/DESystem.java
new file mode 100644
index 0000000..37cb496
--- /dev/null
+++ b/Source/mesquite/diverse/lib/DESystem.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.lib;
+
+public interface DESystem {
+	
+	
+	public double[]calculateDerivative(double x,double y[],double result[]);
+	
+
+}
diff --git a/Source/mesquite/diverse/lib/NumForCharAndTreeDivers.java b/Source/mesquite/diverse/lib/NumForCharAndTreeDivers.java
new file mode 100644
index 0000000..dd78623
--- /dev/null
+++ b/Source/mesquite/diverse/lib/NumForCharAndTreeDivers.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public abstract class NumForCharAndTreeDivers extends NumberForCharAndTree  {
+
+   	 public Class getDutyClass() {
+   	 	return NumForCharAndTreeDivers.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Character and Tree (Diversification)";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+  	 public String[] getDefaultModule() {
+ 		String[] s= {"#BiSSELikelihood"};
+ 		return s;
+   	 }
+ 
+}
+
+
diff --git a/Source/mesquite/diverse/lib/NumberForTreeDivers.java b/Source/mesquite/diverse/lib/NumberForTreeDivers.java
new file mode 100644
index 0000000..033c8f0
--- /dev/null
+++ b/Source/mesquite/diverse/lib/NumberForTreeDivers.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a tree that give statistics about diversification.*/
+
+public abstract class NumberForTreeDivers extends NumberForTree  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTreeDivers.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree (Diversification)";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeNumber.gif";
+   	 }
+  	 public String[] getDefaultModule() {
+ 		String[] s= {"#SpecExtincLikelihood", "#NMHBirthDeathLikelihood"};
+ 		return s;
+   	 }
+ 
+}
+
+
diff --git a/Source/mesquite/diverse/lib/RK4Solver.java b/Source/mesquite/diverse/lib/RK4Solver.java
new file mode 100644
index 0000000..fc7646d
--- /dev/null
+++ b/Source/mesquite/diverse/lib/RK4Solver.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.lib;
+
+import java.util.Vector;
+
+
+public class RK4Solver implements DEQNumSolver {
+
+	DESystem mySystem;
+	double[] nextY;
+
+    /**
+     * @arg x0 starting point
+     * @arg y0 starting values
+     * @arg step size
+     * @arg xend
+     * @arg ds system of equations to solve
+     * @arg results saves intermediate values, last element is (estimated) y at xend
+     */
+	public double[] integrate(double x0, double[] y0, double h, double xend, DESystem ds, double[] results){
+		mySystem = ds;
+		if (results == null || results.length != y0.length)
+			results = new double[y0.length];
+		nextY = results;
+		for(int i=0;i<nextY.length;i++)
+			nextY[i]=y0[i];
+		if (h>0) {   //most common case
+			if (x0 >= xend)
+				return null;
+			double x = x0;
+			while(x < xend){
+                if ((x+h) > xend)
+                    h = xend-x;
+                step(x,nextY,h);
+				x += h;
+			}
+		}
+		else {    // h<0 might be useful for seeding non-self starting methods
+			if (x0 <= xend)
+				return null;
+			double x = x0;
+			while (x> xend){
+			    if ((x-h) < xend)
+                    h = x-xend;
+				step(x,nextY,-h);
+				x -= h;
+			}
+		}
+		return results;
+	}
+
+    /**
+     * @arg x0 starting point
+     * @arg y0 starting values
+     * @arg step size
+     * @arg xend end point
+     * @arg ds system of equations to solve
+     * @arg results saves intermediate values, last element is (estimated) y at xend
+     */	
+	public Vector integrate(double x0, double[] y0, double h, double xend, DESystem ds,Vector results,boolean saveResults) {
+		mySystem = ds;
+        double[] lastResult = null;
+		if (results == null && saveResults)
+			results = new Vector();
+        if (results != null)
+            results.clear();
+		if (nextY == null || nextY.length != y0.length)
+			nextY = new double[y0.length];
+		for(int i=0;i<nextY.length;i++)
+			nextY[i]=y0[i];
+		if (h>0) {   //most common case
+			if (x0 >= xend)
+				return null;
+			double x = x0;
+			while(x < xend){
+                if ((x+h) > xend)
+                    h = xend-x;
+				step(x,nextY,h);
+                if (saveResults && results != null)
+                    results.add(nextY.clone());
+                else
+                    lastResult = nextY;
+				x += h;
+			}
+		}
+		else {    // might be useful for seeding non-self starting methods
+			if (x0 <= xend)
+				return null;
+			double x = x0;
+			while (x> xend){
+				
+			}
+		}
+        if (!saveResults){
+            if (results == null)
+                results = new Vector(1);
+            results.add(lastResult.clone());
+        }
+		return results;
+	}
+
+	
+	
+	private double[] k1 = null;
+	private double[] k2 = null;
+	private double[] k3 = null;
+	private double[] k4 = null;
+	private double[] yk1 = null;
+	private double[] yk2 = null;
+	private double[] yk3 = null;
+
+	private double[] step(double x, double [] y, double h){
+        int ylen = y.length;
+        double half_h = 0.5*h;
+		if (k1 == null || k1.length != ylen){
+			k1 = new double[ylen];
+			k2 = new double[ylen];
+			k3 = new double[ylen];
+			k4 = new double[ylen];
+			yk1 = new double[ylen];
+			yk2 = new double[ylen];
+			yk3 = new double[ylen];
+		}
+		if (y.length == 0 || k1.length == 0)
+			System.out.println("oops");
+		k1 = mySystem.calculateDerivative(x,y,k1);
+		for(int i=0;i<ylen;i++)
+			yk1[i]=y[i]+k1[i]*half_h;
+		k2 = mySystem.calculateDerivative(x+half_h,yk1,k2);
+		for(int i=0;i<ylen;i++)
+			yk2[i]=y[i]+k2[i]*half_h;
+		k3 = mySystem.calculateDerivative(x+half_h,yk2,k3);
+		for(int i=0;i<ylen;i++)
+			yk3[i]=y[i]+k3[i]*h;
+		k4 = mySystem.calculateDerivative(x+h,yk3,k4);
+		for(int i=0;i<nextY.length;i++)
+			nextY[i] = y[i] + (h/6)*(k1[i]+2*k2[i]+2*k3[i]+k4[i]);
+		return nextY;
+	}
+
+}
diff --git a/Source/mesquite/diverse/lib/RKF45Solver.java b/Source/mesquite/diverse/lib/RKF45Solver.java
new file mode 100644
index 0000000..9c31a96
--- /dev/null
+++ b/Source/mesquite/diverse/lib/RKF45Solver.java
@@ -0,0 +1,211 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.diverse.lib;
+
+import java.util.Vector;
+
+import mesquite.lib.MesquiteDouble;
+
+
+public class RKF45Solver implements DEQNumSolver {
+
+    DESystem mySystem;
+    double[] nextY;
+    double minh;
+    double maxh;
+    MesquiteDouble step = new MesquiteDouble();
+    
+    final static double fourthRootOneHalf = Math.exp(Math.log(0.5)/4);
+    final static double tol = 0.000001;
+
+    /**
+     * Solves the system specified by ds over the interval [x0,xend] with initial condition y0 using RKF45
+     * @arg x0 starting point
+     * @arg y0 starting values
+     * @arg step size
+     * @arg xend
+     * @arg ds system of equations to solve
+     * @arg results saves intermediate values, last element is (estimated) y at xend
+     */
+    public double[] integrate(double x0, double[] y0, double h, double xend, DESystem ds, double[] results){
+        mySystem = ds;
+        minh = 0.1*h;
+        maxh = 10*h;
+        step.setValue(h);
+        if (results == null || results.length != y0.length)
+            results = new double[y0.length];
+        nextY = results;
+        for(int i=0;i<nextY.length;i++)
+            nextY[i]=y0[i];
+        if (x0 >= xend)
+            return null;
+        double x = x0;
+        while(x < xend){
+            oneStep(x,nextY,step);
+            if (step.getValue()<minh)
+                step.setValue(minh);
+            if (step.getValue()>maxh)
+                step.setValue(maxh);                        
+            x += step.getValue();
+        }
+        return results;
+    }
+
+    /**
+     * Solves the system specified by ds over the interval [x0,xend] with initial condition y0 using RKF45
+     * @arg x0 starting point
+     * @arg y0 starting values
+     * @arg step size
+     * @arg xend
+     * @arg ds system of equations to solve
+     * @arg results saves intermediate values, last element is (estimated) y at xend
+     */    
+    public Vector integrate(double x0, double[] y0, double h, double xend, DESystem ds,Vector results,boolean saveResults) {
+        mySystem = ds;
+        minh = 0.1*h;
+        maxh = 10*h;
+        step.setValue(h);
+        double[] lastResult = null;
+        if (results == null && saveResults)
+            results = new Vector();
+        if (results != null)
+            results.clear();
+        if (nextY == null || nextY.length != y0.length)
+            nextY = new double[y0.length];
+        for(int i=0;i<nextY.length;i++)
+            nextY[i]=y0[i];
+        if (x0 >= xend)
+            return null;
+        double x = x0;
+        while(x<xend){
+            double oldStep = step.getValue();
+            if ((x+oldStep) > xend){
+                oldStep = xend-x;
+                step.setValue(oldStep);
+            }
+            oneStep(x,nextY,step);
+            x += oldStep;
+            if (step.getValue()<minh)
+                step.setValue(minh);
+            if (step.getValue()>maxh)
+                step.setValue(maxh);                                        
+            if (saveResults && results != null)
+                results.add(nextY.clone());
+            else
+                lastResult = nextY;
+        }        
+        if (!saveResults){
+            if (results == null)
+                results = new Vector(1);
+            results.add(lastResult.clone());
+        }
+        return results;
+    }
+
+    
+    
+    private double[] k1 = null;
+    private double[] k2 = null;
+    private double[] k3 = null;
+    private double[] k4 = null;
+    private double[] k5 = null;
+    private double[] k6 = null;
+    private double[] yk1 = null;
+    private double[] yk2 = null;
+    private double[] yk3 = null;
+    private double[] yk4 = null;
+    private double[] yk5 = null;
+    private double[] z = null;
+    private double[] err2 = null;
+    
+    private double[] oneStep(double x, double [] y, MesquiteDouble h){
+        int ylen = y.length;
+        double hval = h.getValue();
+        double quarter_h = 0.25*hval;
+        double threeEights_h = 0.375*hval;
+        double half_h = 0.5*hval;
+        double twelveThirteenths_h = 12.0*hval/13;
+        if (k1 == null || k1.length != ylen){
+            k1 = new double[ylen];
+            k2 = new double[ylen];
+            k3 = new double[ylen];
+            k4 = new double[ylen];
+            k5 = new double[ylen];
+            k6 = new double[ylen];
+            yk1 = new double[ylen];
+            yk2 = new double[ylen];
+            yk3 = new double[ylen];
+            yk4 = new double[ylen];
+            yk5 = new double[ylen];
+            z = new double[ylen];
+            err2 = new double[ylen];
+        }
+        if (y.length == 0 || k1.length == 0)
+            System.out.println("oops");
+        k1 = mySystem.calculateDerivative(x,y,k1);
+        for(int i=0;i<ylen;i++){
+            k1[i] *= hval;
+            yk1[i]=y[i]+k1[i]*0.25;
+        }
+        k2 = mySystem.calculateDerivative(x+quarter_h,yk1,k2);
+        for(int i=0;i<ylen;i++){
+            k2[i] *= hval;
+            yk2[i]=y[i]+k1[i]*3.0/32.0+k2[i]*9.0/32.0;
+        }
+        k3 = mySystem.calculateDerivative(x+threeEights_h,yk2,k3);
+        for(int i=0;i<ylen;i++){
+            k3[i] *= hval;
+            yk3[i]=y[i]+k1[i]*1932.0/2197.0 - k2[i]*7200.0/2197.0 + k3[i]*7296.0/2197.0;
+        }
+        k4 = mySystem.calculateDerivative(x+twelveThirteenths_h,yk3,k4);
+        for(int i=0;i<ylen;i++){
+            k4[i] *= hval;
+            yk4[i]= y[i]+k1[i]*(439.0/216.0)-k2[i]*8.0 + k3[i]*(3680.0/513.0) - k4[i]*(845.0/4104.0);
+        }
+        k5 = mySystem.calculateDerivative(x+hval,yk4,k5);
+        for(int i=0;i<ylen;i++){
+            k5[i] *= hval;
+            yk5[i] = y[i] -k1[i]*(8.0/27.0) + k2[i]*2 - k3[i]*(3544.0/2565.0) + k4[i]*(1859.0/4104.0) - k5[i]*(11.0/40.0);            
+        }
+        k6 = mySystem.calculateDerivative(x+half_h,yk5,k6);
+        for(int i=0;i<ylen;i++)
+            k6[i] *= hval;
+        double s=MesquiteDouble.infinite;
+        for(int i=0;i<nextY.length;i++){
+            nextY[i] = y[i] + (25.0/216.0)*k1[i]+(1408.0/2565.0)*k3[i]+(2197.0/4104.0)*k4[i]-(1.0/5.0)*k5[i];
+            z[i] = y[i] + (16.0/135.0)*k1[i] + (6656.0/12825.0)*k3[i] + (28561.0/56430.0)*k4[i] - (9.0/50.0)*k5[i] + (2.0/55.0)*k6[i];
+            err2[i] = Math.abs((1.0/360.0)*k1[i] + (-128.0/4275.0)*k3[i] + (-2197.0/75240.0)*k4[i] + (1.0/50.0)*k5[i] + (2.0/55.0)*k6[i]);
+            double part5a = (y[i] + (16.0/135.0)*k1[i] + (6656.0/12825.0)*k3[i] + (28561.0/56430.0)*k4[i] - (9.0/50.0)*k5[i] + (2.0/55.0)*k6[i]);
+            double part5b = (y[i] + (25.0/216.0)*k1[i]+(1408.0/2565.0)*k3[i]+(2197.0/4104.0)*k4[i]-(1.0/5.0)*k5[i]);
+            double part5c = part5a-part5b;
+            double part5 = (y[i] + (16.0/135.0)*k1[i] + (6656.0/12825.0)*k3[i] + (28561.0/56430.0)*k4[i] - (9.0/50.0)*k5[i] + (2.0/55.0)*k6[i]) - (y[i] + (25.0/216.0)*k1[i]+(1408.0/2565.0)*k3[i]+(2197.0/4104.0)*k4[i]-(1.0/5.0)*k5[i]);
+            double myerr = z[i]-nextY[i];
+            if (myerr != 0.0){
+                double si = fourthRootOneHalf*Math.exp(0.25*Math.log(((tol*hval)/Math.abs(part5c))));
+                if (si < s)
+                    s = si;
+            }
+        }
+        if (s != MesquiteDouble.infinite)
+            h.setValue(hval*s);
+        return nextY;
+    }
+
+    
+
+
+
+
+
+}
diff --git a/Source/mesquite/diverse/lib/TreeCharSimulate.java b/Source/mesquite/diverse/lib/TreeCharSimulate.java
new file mode 100644
index 0000000..1e2d93a
--- /dev/null
+++ b/Source/mesquite/diverse/lib/TreeCharSimulate.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.diverse.lib;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Simulates trees.*/
+
+public abstract class TreeCharSimulate extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeCharSimulate.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree/Character Simulate";
+   	 }
+   	 
+   	public abstract void initialize(Taxa taxa);
+   	public abstract void doSimulation(Taxa taxa, int replicateNumber, ObjectContainer tree, ObjectContainer characterHistory, MesquiteLong seed);
+   	public abstract String getDataType();
+}
+
+
diff --git a/Source/mesquite/dmanager/FuseTMSequences/FuseTMSequences.java b/Source/mesquite/dmanager/FuseTMSequences/FuseTMSequences.java
new file mode 100644
index 0000000..c7ed041
--- /dev/null
+++ b/Source/mesquite/dmanager/FuseTMSequences/FuseTMSequences.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.dmanager.FuseTMSequences;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class FuseTMSequences extends FileAssistantM {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		includeFuse();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Includes a file and optionally fuses taxa/characters block", null, commandName, "fuse")) {
+			includeFuse();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	private void includeFuse(){
+		String message = "You are about to read in another file, and import the taxa and characters blocks found there, with or without fusing to taxa and character blocks in "
+			+ "the current file.  This process will NOT incorporate trees, footnotes or most other auxiliary information associated "
+			+ "with those taxa and character blocks. ";
+
+		discreetAlert( message);
+		MesquiteModule fCoord = getFileCoordinator();
+		MesquiteCommand command = makeCommand("includeFile", fCoord);
+
+		command.doItMainThread(StringUtil.argumentMarker + "fuseTaxaCharBlocks", null, this);
+		getProject().showProjectWindow();
+		iQuit();
+
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() { 
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Merge Matrices from File...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Merge Matrices from File";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Includes a file and concatenates its taxa to an existing taxa block, for instance to add seqences." ;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/dmanager/FuseTaxaMatrices/FuseTaxaMatrices.java b/Source/mesquite/dmanager/FuseTaxaMatrices/FuseTaxaMatrices.java
new file mode 100644
index 0000000..1b7dd79
--- /dev/null
+++ b/Source/mesquite/dmanager/FuseTaxaMatrices/FuseTaxaMatrices.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.dmanager.FuseTaxaMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class FuseTaxaMatrices extends FileAssistantT {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		includeFuse();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Includes a file and optionally fuses taxa/characters block", null, commandName, "fuse")) {
+			includeFuse();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	private void includeFuse(){
+		String message = "You are about to read in another file, and import the taxa and characters blocks found there, with or without fusing to taxa and character blocks in "
+			+ "the current file.  This process will NOT incorporate trees, footnotes or most other auxiliary information associated "
+			+ "with those taxa and character blocks. ";
+
+		discreetAlert( message);
+		MesquiteModule fCoord = getFileCoordinator();
+		MesquiteCommand command = makeCommand("includeFileFuse", fCoord);
+		command.doItMainThread(StringUtil.argumentMarker + "fuseTaxaCharBlocks", null, this);
+		getProject().showProjectWindow();
+		iQuit();
+
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() { 
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Merge Taxa & Matrices from File...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Merge Taxa & Matrices from File";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Includes a file and concatenates its taxa to an existing taxa block, for instance to add seqences." ;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/dmanager/InterchTaxonPrefixSuffix/InterchTaxonPrefixSuffix.java b/Source/mesquite/dmanager/InterchTaxonPrefixSuffix/InterchTaxonPrefixSuffix.java
new file mode 100644
index 0000000..4ff3c74
--- /dev/null
+++ b/Source/mesquite/dmanager/InterchTaxonPrefixSuffix/InterchTaxonPrefixSuffix.java
@@ -0,0 +1,116 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.dmanager.InterchTaxonPrefixSuffix;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== 
+*new in 1.02* */
+public class InterchTaxonPrefixSuffix extends TaxonNameAlterer {
+	String searchText=".";
+	MesquiteBoolean suffix = new MesquiteBoolean(true);
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Interchange Prefix or Suffix",  buttonPressed);
+		queryDialog.addLabel("Move taxon name suffix to prefix or prefix to suffix", Label.CENTER);
+		SingleLineTextField searchField = queryDialog.addTextField("Delimiter:", searchText, 12, true);
+		Checkbox suffixBox = queryDialog.addCheckBox("Move Suffix to Prefix (otherwise Prefix to Suffix)", suffix.getValue());
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			searchText = searchField.getText();
+			suffix.setValue(suffixBox.getState());
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String s = "";
+			if (suffix.getValue()){
+				int delim = name.lastIndexOf(searchText);
+				if (delim>=0){
+					String ix = name.substring(delim+1, name.length());
+					if (StringUtil.blank(ix))
+						return false;
+					String bn = name.substring(0, delim);
+					if (StringUtil.blank(bn))
+						return false;
+					
+					taxa.setTaxonName(it, ix + searchText + bn, false);
+					nameChanged = true;
+				}
+			}
+			else {
+				int delim = name.indexOf(searchText);
+				if (delim>=0){
+					String ix = name.substring(0, delim);
+					if (StringUtil.blank(ix))
+						return false;
+					String bn = name.substring(delim+1, name.length());
+					if (StringUtil.blank(bn))
+						return false;
+					
+					taxa.setTaxonName(it, bn + searchText + ix, false);
+					nameChanged = true;
+				}
+			}
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Move Prefix/Suffix of Taxon Name...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Move Prefix/Suffix of Taxon Name";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Moves the suffix of the taxon name to be to prefix or the prefix to be the suffix";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/dmanager/KeepTaxonPrefixSuffix/KeepTaxonPrefixSuffix.java b/Source/mesquite/dmanager/KeepTaxonPrefixSuffix/KeepTaxonPrefixSuffix.java
new file mode 100644
index 0000000..7304ac5
--- /dev/null
+++ b/Source/mesquite/dmanager/KeepTaxonPrefixSuffix/KeepTaxonPrefixSuffix.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.dmanager.KeepTaxonPrefixSuffix;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== 
+*new in 1.02* */
+public class KeepTaxonPrefixSuffix extends TaxonNameAlterer {
+	String searchText=".";
+	MesquiteBoolean suffix = new MesquiteBoolean(true);
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+   	public boolean getOptions(Taxa taxa, int firstSelected){
+   		if (MesquiteThread.isScripting())
+   			return true;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Keep Only Prefix or Suffix",  buttonPressed);
+		queryDialog.addLabel("Keep only a prefix or suffix of taxon name", Label.CENTER);
+		SingleLineTextField searchField = queryDialog.addTextField("Delimiter:", searchText, 12, true);
+		Checkbox suffixBox = queryDialog.addCheckBox("Keep Suffix (otherwise Prefix)", suffix.getValue());
+		queryDialog.completeAndShowDialog(true);
+			
+		boolean ok = (queryDialog.query()==0);
+		
+		if (ok) {
+			searchText = searchField.getText();
+			suffix.setValue(suffixBox.getState());
+		}
+		
+		queryDialog.dispose();
+
+		return ok;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String s = "";
+			if (suffix.getValue()){
+				int delim = name.lastIndexOf(searchText);
+				if (delim>=0){
+					name = name.substring(delim+1, name.length());
+					taxa.setTaxonName(it, name, false);
+					nameChanged = true;
+				}
+			}
+			else {
+				int delim = name.indexOf(searchText);
+				if (delim>=0){
+					name = name.substring(0, delim);
+					taxa.setTaxonName(it, name, false);
+					nameChanged = true;
+				}
+			}
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Keep Prefix/Suffix of Taxon Name...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Keep Prefix/Suffix of Taxon Name";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Keeps only Prefix or Suffix of Taxon Name.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/dmanager/ProcessFile/ProcessFile.java b/Source/mesquite/dmanager/ProcessFile/ProcessFile.java
new file mode 100644
index 0000000..143df3a
--- /dev/null
+++ b/Source/mesquite/dmanager/ProcessFile/ProcessFile.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.dmanager.ProcessFile;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class ProcessFile extends FileInit {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu, "Process File...", new MesquiteCommand("processFile", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	boolean firstTime = true;
+	public boolean okToInteractWithUser(int howImportant, String messageToUser){
+		if (firstTime){
+			firstTime = false;
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Processes the file using a FileProcessor", null, commandName, "processFile")) {
+			firstTime = true;
+			MesquiteFile f=  checker.getFile();
+			if (f == null)
+				f = getProject().getHomeFile();
+			FileProcessor processor = (FileProcessor)hireEmployee(FileProcessor.class, "File processor ");
+			if (processor == null)
+				return null;
+			getFileCoordinator().setWhomToAskIfOKToInteractWithUser(this);
+			boolean success = true;
+			MesquiteString result = new MesquiteString();
+			result.setValue((String)null);
+			success = processor.processFile(f, result);
+			firstTime = true;
+			fireEmployee(processor);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Process File";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calls a File Processor to process the current file.  Options depend on modules installed." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 303;  
+	}
+}
+
+
diff --git a/Source/mesquite/dmanager/RandomizeTaxonOrder/RandomizeTaxonOrder.java b/Source/mesquite/dmanager/RandomizeTaxonOrder/RandomizeTaxonOrder.java
new file mode 100644
index 0000000..49181ca
--- /dev/null
+++ b/Source/mesquite/dmanager/RandomizeTaxonOrder/RandomizeTaxonOrder.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.dmanager.RandomizeTaxonOrder;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class RandomizeTaxonOrder extends TaxonUtility {
+	static Random rng = new Random(System.currentTimeMillis());
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/** if returns true, then requests to remain on even after operateOnTaxa is called.  Default is false*/
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	/** Swaps parts first and second*/
+	void swapParts(Associable assoc, int first, int second, int[] nums){  
+  		int temp = nums[first];
+  		nums[first] = nums[second];
+  		nums[second] = temp;
+		assoc.swapParts(first, second); 
+	}
+	/** Called to operate on the taxa in the block.  Returns true if taxa altered*/
+	public  boolean operateOnTaxa(Taxa taxa){
+		int[] nums = new int[taxa.getNumTaxa()];
+		for (int i=0; i<nums.length; i++) {
+			nums[i] = rng.nextInt();
+		}
+		
+		for (int i=1; i<taxa.getNumTaxa(); i++) {
+			for (int j= i-1; j>=0 && nums[j]> nums[j+1]; j--) {
+				swapParts(taxa, j, j+1, nums);
+			}
+		}
+		taxa.notifyListeners(this, new Notification(PARTS_MOVED));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Randomize Taxon Order";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Randomizes the order of taxa.";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/dmanager/TaxaListImportSource/TaxaListImportSource.java b/Source/mesquite/dmanager/TaxaListImportSource/TaxaListImportSource.java
new file mode 100644
index 0000000..89e80d7
--- /dev/null
+++ b/Source/mesquite/dmanager/TaxaListImportSource/TaxaListImportSource.java
@@ -0,0 +1,91 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.dmanager.TaxaListImportSource;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaListImportSource extends TaxonListAssistant  {
+	Taxa taxa=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.taxa = taxa;
+		//data.addListener(this);
+		this.table = table;
+	}
+	NameReference importSourceRef = NameReference.getNameReference("importsource");
+	public String getStringForTaxon(int ic){
+		String s = null;
+		if (taxa != null) {
+			Object b  = taxa.getAssociatedObject(importSourceRef, ic); //+1 because zero based
+			if (b instanceof String)
+				s = (String)b;
+		}
+		if (StringUtil.blank(s))
+			s = "?";
+		return s;
+	}
+	public String getWidestString(){
+		return "88888888888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Original File";
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Original File (import source)";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shows the orignal file from which a fuse/imported taxon came." ;
+   	 }
+   	 public void endJob() {
+		//if (data !=null)
+		//	data.removeListener(this);
+		super.endJob();
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/dmanager/TaxonNameFromSampleNamesFile/TaxonNameFromSampleNamesFile.java b/Source/mesquite/dmanager/TaxonNameFromSampleNamesFile/TaxonNameFromSampleNamesFile.java
new file mode 100644
index 0000000..15f7952
--- /dev/null
+++ b/Source/mesquite/dmanager/TaxonNameFromSampleNamesFile/TaxonNameFromSampleNamesFile.java
@@ -0,0 +1,336 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.dmanager.TaxonNameFromSampleNamesFile;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonNameFromSampleNamesFile extends TaxonNameAlterer implements ActionListener, TextListener {
+	String sampleCodeListPath = null;
+	String sampleCodeList = "";
+	Parser sampleCodeListParser = null;
+	boolean preferencesSet = false;
+	SingleLineTextField sampleCodeFilePathField = null;
+	int chosenNameCategory = -1;
+	String[] nameCategories = null;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean processNameCategories() {
+		sampleCodeListParser = new Parser(sampleCodeList);
+		Parser subParser = new Parser();
+		String line = sampleCodeListParser.getRawNextDarkLine();
+		subParser.setString(line);
+		subParser.setWhitespaceString("\t");
+		subParser.setPunctuationString("");
+		String s = subParser.getFirstToken(); // should be "code"
+		s = subParser.getNextToken(); // should be "File Name"
+		int count = 0;
+		while (!subParser.atEnd() && StringUtil.notEmpty(s)){  // let's count
+			s = subParser.getNextToken(); // should be  the category name
+			if (StringUtil.notEmpty(s))
+				count++;
+		}
+		nameCategories = new String[count];
+		subParser.setString(line);
+		s = subParser.getFirstToken(); // should be "code"
+		s = subParser.getNextToken(); // should be "File Name"
+		count = 0;
+		while (!subParser.atEnd() && StringUtil.notEmpty(s)){
+			s = subParser.getNextToken(); // should be the category name
+			if (StringUtil.notEmpty(s)){
+				nameCategories[count]=s;
+				count++;
+			}
+		}
+		return true;
+
+	}
+	/*.................................................................................................................*/
+	public boolean scanTabbedDocument() {
+		if (!StringUtil.blank(sampleCodeListPath)) {
+			sampleCodeList = MesquiteFile.getFileContentsAsString(sampleCodeListPath);
+
+			if (!StringUtil.blank(sampleCodeList)) {
+				sampleCodeListParser = new Parser(sampleCodeList);
+				return processNameCategories();
+			}
+		}	
+		return false;
+
+	}
+	/*.................................................................................................................*/
+	public boolean queryForOptionsAsNeeded() {
+		if (StringUtil.blank(sampleCodeListPath)){
+			return queryOptions();
+		}			
+		if (StringUtil.blank(sampleCodeListPath)) {
+			sampleCodeList = MesquiteFile.getFileContentsAsString(sampleCodeListPath);
+		}
+		if (!StringUtil.blank(sampleCodeList)) 
+			sampleCodeListParser = new Parser(sampleCodeList);
+		if (nameCategories==null){
+			return processNameCategories();
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+   	/** A stub method for querying the user about options. If alterIndividualTaxonNames is used to 
+   	alter the names, and options need to be specified for the operation, then optionsQuery should be overridden.*/
+ 	public  boolean getOptions(Taxa taxa, int firstSelected){
+		scanTabbedDocument();  // do this just in case there is already one there
+		if (!queryOptions())
+			return false;
+		if (!scanTabbedDocument())
+			return false;
+		return true;
+   	}
+
+	/*.................................................................................................................*
+	public void initialize() {
+		if (!StringUtil.blank(sampleCodeListPath)) {
+			sampleCodeList = MesquiteFile.getFileContentsAsString(sampleCodeListPath);
+
+			if (!StringUtil.blank(sampleCodeList)) {
+				sampleCodeListParser = new Parser(sampleCodeList);
+				processNameCategories();
+			}
+		}			
+	}
+
+	/*.................................................................................................................*/
+	public boolean optionsSpecified(){
+		return StringUtil.notEmpty(sampleCodeListPath);
+	}
+
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("sampleCodeListPath".equalsIgnoreCase(tag)){
+			sampleCodeListPath = StringUtil.cleanXMLEscapeCharacters(content);
+		}
+		if ("chosenNameCategory".equalsIgnoreCase(tag)){
+			chosenNameCategory = MesquiteInteger.fromString(content);
+		}
+		preferencesSet = true;
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "sampleCodeListPath", sampleCodeListPath);  
+		StringUtil.appendXMLTag(buffer, 2, "chosenNameCategory", chosenNameCategory);  
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	Choice categoryChoice ;
+
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Location of File with Taxon Names",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+
+		sampleCodeFilePathField = dialog.addTextField("Taxon names file:", sampleCodeListPath,26);
+		sampleCodeFilePathField.addTextListener(this);
+		final Button dnaCodesBrowseButton = dialog.addAListenedButton("Browse...",null, this);
+		dnaCodesBrowseButton.setActionCommand("TaxonNameFileBrowse");
+
+		String[] categories=null;
+
+		if (nameCategories==null) {
+			categories = new String[1];
+			categories[0]="Sample Code                  ";
+		} else
+			categories = nameCategories;
+
+		int currentCategory = chosenNameCategory;
+		if (currentCategory<0)
+			currentCategory=0;
+		categoryChoice = dialog.addPopUpMenu("Names to use:", categories, currentCategory);
+
+		String s = "This file must contain in its first line the titles of each of the columns, delimited by tabs.  The first column must be the OTU ID code, ";
+		s+= "and the second and later columns should contain naming schemes for the sequences. Each of the following lines must contain the entry for one sample.\n\n";
+		s+= "<BR><BR>For example, the file might look like this:<br><br>\n";
+		s+= "code  <tab>  Short name <tab>  Simple name  <tab>  Name with numbers  <tab>  Name with localities <br>\n";
+		s+= "001  <tab>  Bemb_quadrimaculatum_001 <tab>  Bembidion quadrimaculatum  <tab>  Bembidion quadrimaculatum 001  <tab>  Bembidion quadrimaculatum ONT <br>\n";
+		s+= "002  <tab>  Bemb_festivum_002 <tab>  Bembidion festivum  <tab>  Bembidion festivum 002  <tab>  Bembidion festivum CA:Fresno <br>\n";
+		s+= "003  <tab>  Bemb_occultator_003 <tab>  Bembidion occultator  <tab>  Bembidion occultator 003  <tab>  Bembidion occultator ON:Dwight <br>\n";
+		s+= "004  <tab>  Lion_chintimini_004 <tab>  Lionepha chintimini  <tab>  Lionepha chintimini 004  <tab>  Lionepha chintimini OR:Marys Peak <br><br>\n";
+		s+= "You will need to choose which of the later columns are to be used as the source of the new name for each taxon.\n\n";
+
+		
+		dialog.appendToHelpString(s);
+
+		dialog.completeAndShowDialog(true);
+		boolean success=(buttonPressed.getValue()== dialog.defaultOK);
+		if (success)  {
+			sampleCodeListPath = sampleCodeFilePathField.getText();
+			chosenNameCategory = categoryChoice.getSelectedIndex();
+			//	initialize();  // is this needed?
+		}
+		storePreferences();  // do this here even if Cancel pressed as the File Locations subdialog box might have been used
+		dialog.dispose();
+		return success;
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true; 
+	}
+	/*.................................................................................................................*/
+
+	public  String[] getSeqNamesFromTabDelimitedFile(MesquiteString sampleCode) {
+		queryForOptionsAsNeeded();
+		if (sampleCodeListParser==null)
+			return null;
+		String sampleCodeString  = sampleCode.getValue();
+		if (sampleCodeString==null)
+			return null;
+		sampleCodeListParser.setPosition(0);
+		Parser subParser = new Parser();
+		String line = sampleCodeListParser.getRawNextDarkLine();
+		while (StringUtil.notEmpty(line)) {
+			subParser.setString(line);
+			subParser.setWhitespaceString("\t");
+			subParser.setPunctuationString("");
+			String code = subParser.getFirstToken();
+			if (sampleCodeString.equalsIgnoreCase(code)) {
+				String fileName = subParser.getNextToken();
+				String sequenceName=subParser.getNextToken();
+				for (int i=0; i<chosenNameCategory; i++) {
+					sequenceName=subParser.getNextToken();
+				}
+				if (StringUtil.blank(sequenceName))
+					sequenceName=fileName;
+				return new String[]{fileName, sequenceName};
+			}
+			line = sampleCodeListParser.getRawNextDarkLine();
+		}
+		// got here and no match found -- log an error
+		MesquiteMessage.warnUser("No OTU ID code named '" + sampleCode + "' found in taxon names file.");
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+	public boolean alterName(Taxa taxa, int it){
+		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String vc = getVoucherCode(taxa, it);
+			String[] names = getSeqNamesFromTabDelimitedFile(new MesquiteString(vc));
+			if (names!=null && names.length>1&& StringUtil.notEmpty(names[1])){
+				taxa.setTaxonName(it, names[1], false);
+			}
+			nameChanged = true;
+		}
+		return nameChanged;
+	}
+	public String getVoucherCode(Taxa taxa, int ic){
+
+		if (taxa!=null) {
+			String s = (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, ic);
+			return s;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Alters taxon names to match those in a file", "[]", commandName, "alterNames")) {
+			if (taxa !=null){
+				alterTaxonNames(taxa,table);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public  void actionPerformed(ActionEvent e) {
+		if (e.getActionCommand().equalsIgnoreCase("TaxonNameFileBrowse")) {
+			MesquiteString dnaNumberListDir = new MesquiteString();
+			MesquiteString dnaNumberListFile = new MesquiteString();
+			String s = MesquiteFile.openFileDialog("Choose file containing OTU ID codes and names", dnaNumberListDir, dnaNumberListFile);
+			if (!StringUtil.blank(s)) {
+				sampleCodeListPath = s;
+				if (sampleCodeFilePathField!=null) 
+					sampleCodeFilePathField.setText(sampleCodeListPath);
+			}
+		}
+	}
+	public void textValueChanged(TextEvent e) {
+		if (e.getSource().equals(sampleCodeFilePathField)) {
+			sampleCodeListPath = sampleCodeFilePathField.getText();
+			if (StringUtil.notEmpty(sampleCodeListPath)) {
+				chosenNameCategory=-1;
+				scanTabbedDocument();
+				//	processNameCategories();
+				//initialize(sampleCodeListPath);
+			}	
+			categoryChoice.removeAll();
+			if (nameCategories!=null) {			
+				for (int i=0; i<nameCategories.length; i++) 
+					if (!StringUtil.blank(nameCategories[i])) {
+						categoryChoice.add(nameCategories[i]);
+					}
+			}
+			categoryChoice.repaint();
+			//				categoryChoice = dialog.addPopUpMenu("Names to use:", xmlProcessor.getNameCategoryDescriptions(), tagNumber);
+
+		}
+	}
+
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Rename Taxa Based On ID Code File...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Rename Taxa Based On ID Code File";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Renames the taxa based upon chosen columns in a tab-delimited text file, using OTU IDs to find the relevant row within that file.";
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+
+}
+
+
+
+
diff --git a/Source/mesquite/dmanager/aDmanagerIntro/aDmanagerIntro.java b/Source/mesquite/dmanager/aDmanagerIntro/aDmanagerIntro.java
new file mode 100644
index 0000000..326c6d9
--- /dev/null
+++ b/Source/mesquite/dmanager/aDmanagerIntro/aDmanagerIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.dmanager.aDmanagerIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aDmanagerIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aDmanagerIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides special tools for managing data and taxa.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "DManager Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "DManager Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/genesis/CodePosRatesCurator/CodePosRatesCurator.java b/Source/mesquite/genesis/CodePosRatesCurator/CodePosRatesCurator.java
new file mode 100644
index 0000000..e05d967
--- /dev/null
+++ b/Source/mesquite/genesis/CodePosRatesCurator/CodePosRatesCurator.java
@@ -0,0 +1,82 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.CodePosRatesCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class CodePosRatesCurator extends CharRatesCurator  implements EditingCurator {
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+		CharRatesModel charRatesInvar = new CharRatesCodePos();
+    		charRatesInvar.addToFile(null, getProject(), null);
+    		charRatesInvar.setBuiltIn(true);
+    		((CharRatesCodePos)charRatesInvar).setShape(0.5);
+    		charRatesInvar.setName("Gamma 0.5");
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return CharRatesCodePos.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Codon Position Rates";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "CodePosRates";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return CharRatesCodePos.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		CharRatesCodePos model = new CharRatesCodePos();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		CharRatesCodePos model = new CharRatesCodePos();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Codon Position Rates Model...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Codon Position Rates Model";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains models that specify rates for codon positions." ;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getHelpString() {
+		return "Enter the rates for codon positions 1, 2, and 3, as well as non-coding sites (N) and unspecified sites (?).  If you choose \"use positions in existing matrix\", the codon position of the nth character any created matrix will match that of the nth character in an existing matrix.";
+	}
+}
+
+
diff --git a/Source/mesquite/genesis/EvolveDNAChars/EvolveDNAChars.java b/Source/mesquite/genesis/EvolveDNAChars/EvolveDNAChars.java
new file mode 100644
index 0000000..c060104
--- /dev/null
+++ b/Source/mesquite/genesis/EvolveDNAChars/EvolveDNAChars.java
@@ -0,0 +1,398 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.EvolveDNAChars;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class EvolveDNAChars extends CharacterSimulator implements MesquiteListener {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ProbModelSourceSim.class, getName() + "  needs a source of a probabilistic model to use in the simulation.",
+		"The source of a probabilistic model to use in the simulation can be selected initially or in the Source of Stochastic Models submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(mesquite.charMatrices.StoredMatrices.StoredMatrices.class, getName() + "  needs a source of character matrices.",
+		"The source of character matrices is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	DNACharacterHistory evolvingStates;
+	ProbModelSourceSim modelSource; //ProbModelSourceSim
+	MesquiteString modelSourceName;
+	SimulationDNAModel  model, originalProbabilityModel;
+	CharMatrixSource matrixSource;
+	MCharactersDistribution matrix = null; //for empirical matrix
+	boolean reclone = false;
+	DNACharacterAdjustable representativeCharacter;
+	String checkString = null;
+	boolean modelChecked = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+		if (condition!=null && !(condition instanceof Class && (condition == DNAState.class || condition == DNAData.class || ((Class)condition).isAssignableFrom(DNAData.class) || ((Class)condition).isAssignableFrom(DNAState.class)) ) )
+			return sorry("Module \"Evolve DNA characters\" has been asked to simulate a sort of data it's not able to simulate (" + ((Class)condition).getName() + "; employer path: " + getEmployerPath()+ ")");
+		representativeCharacter = new DNACharacterAdjustable(null, 1);
+		
+		modelSource = (ProbModelSourceSim)hireCompatibleEmployee( ProbModelSourceSim.class, DNAState.class, "Source of stochastic model for simulation of DNA evolution");
+    	 	if (modelSource == null) {
+    	 		return sorry("Evolve DNA characters could not start because no appropriate model source module could be obtained");
+    	 	}
+	 	modelSourceName = new MesquiteString(modelSource.getName());
+		if (numCompatibleModulesAvailable(ProbModelSourceSim.class, DNAState.class, this)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Source of Stochastic Models", makeCommand("setModelSource", this), ProbModelSourceSim.class);
+ 			mss.setSelected(modelSourceName);
+ 			mss.setCompatibilityCheck(DNAState.class);
+ 		}
+ 		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+ 		MesquiteThread.setCurrentCommandRecord(CommandRecord.scriptingRecord);
+		matrixSource = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, "#StoredMatrices", DNAState.class);
+		MesquiteThread.setCurrentCommandRecord(cr);
+		getProject().getCentralModelListener().addListener(this);
+		
+		return true;
+	}
+  	 
+	/*.................................................................................................................*/
+	public void endJob() {
+  	 	if (model !=null)
+  	 		model.dispose();
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == originalProbabilityModel) {
+			originalProbabilityModel = null;
+    	 		checkString = checkModel(representativeCharacter);
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == originalProbabilityModel) {
+			reclone = true;
+    	 		checkString = checkModel(representativeCharacter);
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	if (employee==matrixSource) {
+   	 		matrix = null;  // to force retrieval of new empirical matrix
+			parametersChanged(notification);
+   	 	}
+   	 	else if (employee==modelSource) {
+   	 		originalProbabilityModel = null;
+    	 		checkString = checkModel(representativeCharacter);
+			parametersChanged(notification);
+   	 	}
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean requestPrimaryChoice(){
+  	 	return true;
+  	 }
+ 	/*.................................................................................................................*/
+ 	/** This returns just the states at the terminal **/
+	private void evolve(ProbabilityCategCharModel model, Tree tree, DNACharacterAdjustable statesAtTips, int node) {
+   		if (node!=tree.getRoot()) {
+   			long statesAtAncestor = evolvingStates.getState(tree.motherOfNode(node));
+   			int stateAtAncestor = DNAState.minimum(statesAtAncestor);
+   			long statesAtNode = DNAState.makeSet(model.evolveState(stateAtAncestor, tree, node));
+   			evolvingStates.setState(node, statesAtNode);  
+   			if (tree.nodeIsTerminal(node)) {
+   				statesAtTips.setState(tree.taxonNumberOfNode(node), statesAtNode);
+   			}
+   		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				evolve(model, tree, statesAtTips, daughter);
+	}
+ 	/*.................................................................................................................*/
+	/** This returns both the states at the terminal and at all the internal nodes **/
+	private void evolve (ProbabilityCategCharModel model, Tree tree, DNACharacterHistory statesAtNodes, int node) {
+   		if (node!=tree.getRoot()) {
+   			long statesAtAncestor = statesAtNodes.getState(tree.motherOfNode(node));
+   			int stateAtAncestor = CategoricalState.minimum(statesAtAncestor);
+   			long statesAtNode = CategoricalState.makeSet(model.evolveState(stateAtAncestor, tree, node));
+   			statesAtNodes.setState(node, statesAtNode);
+   		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				evolve(model, tree, (DNACharacterHistory)statesAtNodes, daughter);
+	}
+	/*.................................................................................................................*/
+	/** Does any needed initializations. */ 
+   	public void initialize(Taxa taxa){
+    	 	checkString = checkModel(representativeCharacter = new DNACharacterAdjustable(taxa, taxa.getNumTaxa()));
+   	}
+	/*.................................................................................................................*/
+	/** Returns maximum number of characters to simulate. */ 
+   	public int getMaximumNumChars(Taxa taxa){
+   		return MesquiteInteger.infinite;
+   	}
+	/*.................................................................................................................*/
+	/** Returns default number of characters to simulate. */ 
+   	public int getDefaultNumChars(){
+   		if (model!=null) {
+   			int numChars = model.getDefaultNumChars();
+   			if (numChars>0)
+   				return numChars;
+   		}
+   		return 100;
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setModelSource ", modelSource);
+ 	 	temp.addLine("getMatrixSource ", matrixSource);
+  	 	return temp;
+  	 }
+  	 public String purposeOfEmployee(MesquiteModule module){
+  	 	if (module  instanceof ProbModelSourceSim){
+  	 		return "for simulation";
+  	 	}
+  	 	else if (module   instanceof CharMatrixSource){
+  	 		return "empirical, for simulation";
+  	 	}
+  	 	return "";
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the module used to supply stochastic models", "[name of module]", commandName, "setModelSource")) {
+   	 		ProbModelSourceSim temp;
+    	 		temp =  (ProbModelSourceSim)replaceCompatibleEmployee(ProbModelSourceSim.class, arguments, modelSource, DNAState.class);
+	    	 	if (temp!=null) {
+	    	 		modelSource=  temp;
+	    	 		modelSourceName.setValue(modelSource.getName());
+ 				parametersChanged(); //?
+ 				return modelSource;
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the module used to supply matrix", null, commandName, "getMatrixSource")) {
+   	 		return matrixSource;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+  	 String checkModel(CategoricalDistribution statesAtNodes) {
+		ProbabilityModel cmodel = originalProbabilityModel;
+		modelChecked = true;
+    	 	if (originalProbabilityModel == null)
+    	 		cmodel = (ProbabilityModel)modelSource.getCharacterModel(statesAtNodes);
+		if (cmodel == null)
+			return "model not obtained.";
+		else if (!(cmodel instanceof ProbabilityCategCharModel))
+			return " the model of character evolution ("  + cmodel.getName() + ") isn't of the appropriate type.";
+		else if (!cmodel.isFullySpecified())
+			return " the model of character evolution ("  + cmodel.getName() + ") doesn't have all of its parameters specified.";
+
+    		if (originalProbabilityModel != cmodel) {
+	  	 	originalProbabilityModel = (SimulationDNAModel)cmodel;
+	  	 	reclone = true;
+	  	 }
+	  	 if (reclone){
+	  	 	if (model !=null)
+	  	 		model.dispose();
+	    	 	model = (SimulationDNAModel)cmodel.cloneModelWithMotherLink(model); //use a copy in case fiddled with
+	    	 	model.setUserVisible(false);
+	    	 	reclone = false;
+    	 	}
+		if (model == null)
+			return "model not obtained.";
+			
+
+		if (model.needsEmpirical()) {
+			MCharactersStatesHolder charMatrix = model.getMCharactersStatesHolder();
+			if (charMatrix==null || matrix == null){
+				MCharactersDistribution m = matrixSource.getCurrentMatrix(statesAtNodes.getTaxa());
+				if (m == null)
+					return "No matrix found";
+				matrix = m;
+				model.setMCharactersStatesHolder(matrix);
+				model.setDefaultNumChars(matrix.getNumChars());
+			}
+		}
+		return null;
+  	 }
+  	int warned = 0;
+	int warnedNoModel = 0;
+	/*.................................................................................................................*/
+   	public CharacterDistribution getSimulatedCharacter(CharacterDistribution statesAtTips, Tree tree, MesquiteLong seed){
+   		if (tree == null)
+   			return null;
+   		else if (statesAtTips == null || !(statesAtTips instanceof DNACharacterAdjustable)){
+   			statesAtTips =  new DNACharacterAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+   		}
+   		else	{
+   			statesAtTips = (CharacterDistribution)((AdjustableDistribution)statesAtTips).adjustSize(tree.getTaxa());
+   		}
+   		
+		if (!modelChecked)
+    	 		checkString = checkModel(representativeCharacter = new DNACharacterAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa()));
+				
+		if (statesAtTips instanceof CategoricalAdjustable)
+			((CategoricalAdjustable)statesAtTips).deassignStates();
+   	 	if (checkString!=null){
+    	 		if ((warned<2 && !MesquiteThread.isScripting()) || warned<1)  //not warned or previous warning was under scripting
+    	 			discreetAlert( "Sorry, the simulation cannot continue because " + checkString);
+			if (MesquiteThread.isScripting())
+				warned = 1;
+			else
+				warned = 2; 
+			return statesAtTips;
+    	 	}
+	
+		model.setMaxStateSimulatable(3); 
+
+   		evolvingStates =(DNACharacterHistory) statesAtTips.adjustHistorySize(tree, evolvingStates);
+
+/*For some reason, in some circumstances, this setSeed can use the same seed but the resulting simulation differs. This happens with composite model, and first time seed is
+set, give different result from before, but second time, gives same result*/
+   		if (seed!=null)
+   			model.setSeed(seed.getValue());
+   		model.setCharacterDistribution(statesAtTips);
+   		model.initForNextCharacter();
+   		long rootState = model.getRootState(tree);
+   		evolvingStates.setState(tree.getRoot(), rootState);  //starting root
+   		evolve(model, tree, (DNACharacterAdjustable)statesAtTips, tree.getRoot());
+   		if (seed!=null)
+   			seed.setValue(model.getSeed());
+  		return statesAtTips;
+   	}
+   	/*.................................................................................................................*/
+   	public CharacterHistory getSimulatedHistory(CharacterHistory statesAtNodes, Tree tree, MesquiteLong seed){
+   		if (tree == null) 
+   			return null;
+   		else if (statesAtNodes == null || !(statesAtNodes instanceof DNACharacterHistory))
+   			statesAtNodes =  new DNACharacterHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+   		else	
+   			statesAtNodes = statesAtNodes.adjustSize(tree);
+
+		if (!modelChecked)
+    	 		checkString = checkModel(representativeCharacter = new DNACharacterAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa()));
+
+    	 	if (checkString!=null){
+    	 		if ((warned<2 && !MesquiteThread.isScripting()) || warned<1)  //not warned or previous warning was under scripting
+    	 			discreetAlert( "Sorry, the simulation cannot continue because " + checkString);
+			if (MesquiteThread.isScripting())
+				warned = 1;
+			else
+				warned = 2; 
+			if (statesAtNodes instanceof CategoricalAdjustable)
+				((CategoricalAdjustable)statesAtNodes).deassignStates();
+			return statesAtNodes;
+    	 	}
+
+    		if (seed!=null)
+   			model.setSeed(seed.getValue());
+		model.setCharacterDistribution(statesAtNodes);
+		model.initForNextCharacter();
+   		((DNACharacterHistory)statesAtNodes).setState(tree.getRoot(), model.getRootState(tree));  //starting root at 0
+   		evolve(model, tree, (DNACharacterHistory)statesAtNodes, tree.getRoot());
+   		if (seed!=null)
+   			seed.setValue(model.getSeed());
+  		return statesAtNodes;
+   	}
+	/*.................................................................................................................*/
+	/** Indicates the type of character created */ 
+	public Class getStateClass(){
+		return DNAState.class;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Evolve DNA Characters";
+   	 }
+   	 
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (model==null)
+			return "Model NULL";
+		else if (!model.isFullySpecified()){
+			return "Simulation cannot be done because model is not fully specified";
+		}
+		String param = "Simulated evolution using model " + model.getName() + " with the following parameters:"+StringUtil.lineEnding() ;
+		param += model.getParameters();
+		return param;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public String getCitation(){
+   	 	return "(If the GTR model is used, the PAL project should also be cited:   Drummond, A. & K. Strimmer, 2001.  PAL: Phylogenetic Analysis Library, version 1.3.  http://www.cebl.auckland.ac.nz/pal-project/)";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Simulates evolution of DNA sequences on a tree." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..
+ 	public String getParameters() {
+ 		return "Probability of change: " + p ;
+   	 }
+   	 */
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new EDCCategoricalStateTest(); 
+  	 }
+}
+
+//This has been added for now since modal model editing not functioning; i.e., must be pre-existing fully-specified model
+class EDCCategoricalStateTest extends OffersDNAData{
+	ModelCompatibilityInfo mci;
+	public EDCCategoricalStateTest (){
+		super();
+		mci = new ModelCompatibilityInfo(CompositProbCategModel.class, DNAState.class);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			if (project==null){
+				return super.isCompatible(obj, project, prospectiveEmployer);
+			}
+			 Listable[] models = project.getCharacterModels(mci, DNAState.class);
+			 if (models == null || models.length == 0)
+				return false;
+			 boolean oneFound = false;
+			 for (int i=0; i<models.length; i++)
+				if (((CompositProbCategModel)models[i]).isFullySpecified()) {
+					oneFound = true;
+					break;
+				}
+			 if (oneFound){
+				boolean compatible = super.isCompatible(obj, project, prospectiveEmployer);
+				return compatible;
+			 }
+			 return false;
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/genesis/GammaCurator/GammaCurator.java b/Source/mesquite/genesis/GammaCurator/GammaCurator.java
new file mode 100644
index 0000000..1700682
--- /dev/null
+++ b/Source/mesquite/genesis/GammaCurator/GammaCurator.java
@@ -0,0 +1,72 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.GammaCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class GammaCurator extends CharRatesCurator implements EditingCurator {
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return CharRatesGamma.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Gamma";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "Gamma";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return CharRatesGamma.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		CharRatesGamma model = new CharRatesGamma();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		CharRatesGamma model = new CharRatesGamma();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Gamma Rates Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Gamma Rates Model...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains Gamma rate variation models." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/GammaInvarCurator/GammaInvarCurator.java b/Source/mesquite/genesis/GammaInvarCurator/GammaInvarCurator.java
new file mode 100644
index 0000000..9a564a0
--- /dev/null
+++ b/Source/mesquite/genesis/GammaInvarCurator/GammaInvarCurator.java
@@ -0,0 +1,72 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.GammaInvarCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class GammaInvarCurator extends CharRatesCurator implements EditingCurator {
+	/*.................................................................................................................*
+  	 public void projectEstablished(){ 
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return CharRatesGammaInvar.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "GammaInvar";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "GammaInvar";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return CharRatesGammaInvar.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		CharRatesGammaInvar model = new CharRatesGammaInvar();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		CharRatesGammaInvar model = new CharRatesGammaInvar();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Gamma Invar Rates Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Gamma Invar Rates Model...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains Gamma rate variation models with a proportion of invariant characters." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/InitDNASubmodels/InitDNASubmodels.java b/Source/mesquite/genesis/InitDNASubmodels/InitDNASubmodels.java
new file mode 100644
index 0000000..c604f0f
--- /dev/null
+++ b/Source/mesquite/genesis/InitDNASubmodels/InitDNASubmodels.java
@@ -0,0 +1,72 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.InitDNASubmodels;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+
+/* ======================================================================== */
+public class InitDNASubmodels extends FileInit {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+  	 public void projectEstablished(){
+  	 	super.projectEstablished();
+		StateFreqDNAEqual model = new StateFreqDNAEqual(null);
+    		model.addToFile(null, getProject(), null);
+    		//model.setName("equal frequencies");
+    		model.setBuiltIn(true);
+		CategoricalData.registerDefaultModel(model.getParadigm(), model.getName());
+		
+		StateFreqDNAEmpir empiricalModel = new StateFreqDNAEmpir(null);
+    		empiricalModel.addToFile(null, getProject(), null);
+    		//empiricalModel.setName("empirical frequencies");
+    		empiricalModel.setBuiltIn(true);
+		
+		RateMatrixEqualDNAModel rModel = new RateMatrixEqualDNAModel(null);
+    		rModel.addToFile(null, getProject(), null);
+    		//model.setName("one parameter");
+    		rModel.setBuiltIn(true);
+		CategoricalData.registerDefaultModel(rModel.getParadigm(), rModel.getName());
+		CharRatesModel charRates = new CharRatesEqual();
+    		charRates.addToFile(null, getProject(), null);
+    		//charRates.setName("equal rates");
+		CategoricalData.registerDefaultModel("CharRates", charRates.getName());
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Initialize DNA Submodels";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Initializes default DNA submodels." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
diff --git a/Source/mesquite/genesis/InvarCurator/InvarCurator.java b/Source/mesquite/genesis/InvarCurator/InvarCurator.java
new file mode 100644
index 0000000..e5bdb28
--- /dev/null
+++ b/Source/mesquite/genesis/InvarCurator/InvarCurator.java
@@ -0,0 +1,78 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.InvarCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class InvarCurator extends CharRatesCurator implements EditingCurator {
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+		CharRatesModel charRatesInvar = new CharRatesInvar();
+    		charRatesInvar.addToFile(null, getProject(), null);
+    		charRatesInvar.setBuiltIn(true);
+    		((CharRatesInvar)charRatesInvar).setShape(0.5);
+    		charRatesInvar.setName("Gamma 0.5");
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return CharRatesInvar.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Proportion Invariant";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "pInvar";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return CharRatesInvar.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		CharRatesInvar model = new CharRatesInvar();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		CharRatesInvar model = new CharRatesInvar();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Proportion Invariant Model...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Proportion Invariant Model";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains models that specify that a certain proportion of characters are invariant." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/RateMatrixGTRCurator/RateMatrixGTRCurator.java b/Source/mesquite/genesis/RateMatrixGTRCurator/RateMatrixGTRCurator.java
new file mode 100644
index 0000000..81cf4f4
--- /dev/null
+++ b/Source/mesquite/genesis/RateMatrixGTRCurator/RateMatrixGTRCurator.java
@@ -0,0 +1,80 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.RateMatrixGTRCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+
+/** ======================================================================== */
+public class RateMatrixGTRCurator extends RateMatrixCurator implements EditingCurator {
+	RateMatrixGTRModel modelToEdit;
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return RateMatrixGTRModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "RateMatrixGTR";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "RateMatrixGTR";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return RateMatrixGTRModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		RateMatrixGTRModel model = new RateMatrixGTRModel();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		RateMatrixGTRModel model = new RateMatrixGTRModel();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "GTR Rate Matrix Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "GTR Rate Matrix Model...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains six-parameter general time-reversible (GTR) rate matrix models." ;
+   	 }
+ 	/*.................................................................................................................*/
+	/** Returns help string. */
+	public String getHelpString (){
+		String s = "General Time Reversible model.  Enter the rate values for each kind of change.  As this is a reversible model, you only enter the rates going one way; the reverse rates are automatically presumed to be equivalent. ";
+		return s+"  For example, the rate of C to A changes will be presumed to be the same as the rate you enter for A to C changes.";
+	}
+}
+
+
diff --git a/Source/mesquite/genesis/RateMatrixTiTvCurator/RateMatrixTiTvCurator.java b/Source/mesquite/genesis/RateMatrixTiTvCurator/RateMatrixTiTvCurator.java
new file mode 100644
index 0000000..4cadf59
--- /dev/null
+++ b/Source/mesquite/genesis/RateMatrixTiTvCurator/RateMatrixTiTvCurator.java
@@ -0,0 +1,78 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.RateMatrixTiTvCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class RateMatrixTiTvCurator extends RateMatrixCurator implements EditingCurator {
+	RateMatrixTiTvModel modelToEdit;
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return RateMatrixTiTvModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "RateMatrixTiTv";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "RateMatrixTiTv";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return RateMatrixTiTvModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		RateMatrixTiTvModel model = new RateMatrixTiTvModel();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		RateMatrixTiTvModel model = new RateMatrixTiTvModel();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Ti/Tv Rate Matrix Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Ti/Tv Rate Matrix Model...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains two-parameter rate matrix models with a transition and transversion rates." ;
+   	 }
+ 	/*.................................................................................................................*/
+	/** Returns help string. */
+	public String getHelpString (){
+		return "Transition/Transversion model. Enter the ratio of transitions to transversions.";
+	}
+}
+
+
diff --git a/Source/mesquite/genesis/SimDNAModelCurator/SimDNAModelCurator.java b/Source/mesquite/genesis/SimDNAModelCurator/SimDNAModelCurator.java
new file mode 100644
index 0000000..36b3974
--- /dev/null
+++ b/Source/mesquite/genesis/SimDNAModelCurator/SimDNAModelCurator.java
@@ -0,0 +1,129 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.SimDNAModelCurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+import mesquite.stochchar.lib.*;
+/* ======================================================================== */
+public class SimDNAModelCurator extends CategProbModelCurator implements EditingCurator {
+	SimulationDNAModel modelToEdit;
+		 SimulationDNAModel defaultModel;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		defaultModel = new SimulationDNAModel("Jukes-Cantor", DNAState.class, this);
+		defaultModel.setRateMatrixModel(new RateMatrixEqualDNAModel(defaultModel));
+		defaultModel.setRootStatesModel(new StateFreqDNAEqual(defaultModel));
+		defaultModel.setEquilStatesModel(new StateFreqDNAEqual(defaultModel));
+		defaultModel.setCharRatesModel(new CharRatesEqual());
+    		defaultModel.setBuiltIn(true);
+		DNAData.registerDefaultModel("Likelihood", defaultModel.getName());
+
+
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public void projectEstablished(){
+    		defaultModel.addToFile(null, getProject(), null);
+    		super.projectEstablished();
+  	 }
+   
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	if (getModuleWindow() ==null || !getModuleWindow().isVisible())
+   	 		return null;
+   	 	Snapshot temp = new Snapshot();
+   	 	temp.addLine("editModel " + ParseUtil.tokenize(modelToEdit.getName()));
+  	 	temp.addLine("getWindow");
+  	 	temp.addLine("tell It");
+	  	temp.incorporate(getModuleWindow().getSnapshot(file), true);
+  	 	temp.addLine("endTell");
+  	 	temp.addLine("showWindow");
+  	 	
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Edits the character model", "[name of character model]", commandName, "editModel")) {
+			CharacterModel model = getProject().getCharacterModel(parser.getFirstToken(arguments));
+			if (model !=null && model instanceof SimulationDNAModel) {
+				showEditor(model);
+			}
+			return model;
+		}
+    	 	else
+ 			return  super.doCommand(commandName, arguments, checker);
+		//return null;
+   	 }
+	/*.................................................................................................................*/
+   	public MesquiteModule showEditor(CharacterModel model){
+		//may not want to do this every request, but in response to a button push in curator window
+		
+   		modelToEdit =  ((SimulationDNAModel)model);
+   		
+ 		modelToEdit.initialize("Edit model: \"" + model.getName() + "\"");
+ 		return this;
+  	}
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+ 			destroyMenu();
+			super.windowGoAway(whichWindow);
+	}
+	public boolean curatesModelClass(Class modelClass){
+		return SimulationDNAModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Composite DNA Simulation Model";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "DNASimulationModel";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return SimulationDNAModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		SimulationDNAModel model = new SimulationDNAModel(name, DNAState.class, this);
+ 		model.setProject(getProject());
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		SimulationDNAModel model = new SimulationDNAModel( name, DNAState.class,this);
+ 		model.setProject(getProject());
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Composite DNA Simulation Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Composite DNA Simulation Model...";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains simple stochastic models of DNA evolution for simulations." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/StateFreqDNAEmpCurator/StateFreqDNAEmpCurator.java b/Source/mesquite/genesis/StateFreqDNAEmpCurator/StateFreqDNAEmpCurator.java
new file mode 100644
index 0000000..50b9529
--- /dev/null
+++ b/Source/mesquite/genesis/StateFreqDNAEmpCurator/StateFreqDNAEmpCurator.java
@@ -0,0 +1,85 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.StateFreqDNAEmpCurator;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+public class StateFreqDNAEmpCurator extends StateFreqCurator {
+	StateFreqDNAEmpir modelToEdit;
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+  	 }
+   
+	/*.................................................................................................................*/
+   	public MesquiteModule showEditor(CharacterModel model){
+   		modelToEdit = (StateFreqDNAEmpir)model;
+   		//modelToEdit.resetStateFrequencies();
+		return this;
+   	}
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return StateFreqDNAEmpir.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Empirical";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "Empirical";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return StateFreqDNAEmpir.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		StateFreqDNAEmpir model = new StateFreqDNAEmpir();
+ 		model.setName(name);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		StateFreqDNAEmpir model = new StateFreqDNAEmpir();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "DNA Empirical State Frequencies Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "DNA Empirical State Frequencies Model...";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean IsBuiltIn() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains model of state frequencies that match those found in an empirical matrix." ; 
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/StateFreqUserDNACurator/StateFreqUserDNACurator.java b/Source/mesquite/genesis/StateFreqUserDNACurator/StateFreqUserDNACurator.java
new file mode 100644
index 0000000..e9b104f
--- /dev/null
+++ b/Source/mesquite/genesis/StateFreqUserDNACurator/StateFreqUserDNACurator.java
@@ -0,0 +1,74 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.StateFreqUserDNACurator;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public class StateFreqUserDNACurator extends StateFreqUserCurator {
+	StateFreqUserDNAModel modelToEdit;
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return StateFreqUserDNAModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public int getNumStates(){
+		return 4;
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "StateFrequencyUserSpecifiedDNA";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "StateFrequencyUserSpecifiedDNA";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return StateFreqUserDNAModel.class;
+	}
+	/*.................................................................................................................*/
+  	public CharacterModel makeNewModel(String name) {
+ 		StateFreqUserDNAModel model = new StateFreqUserDNAModel(null, null);
+ 		model.setName(name);
+       		return model;
+   	}
+   
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		StateFreqUserDNAModel model = new StateFreqUserDNAModel(null,null);
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "User-Specified Nucleotide Frequency Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "User-Specified Nucleotide Frequencies...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains user-specified nucleotide frequency models." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/aGenesisIntro/aGenesisIntro.java b/Source/mesquite/genesis/aGenesisIntro/aGenesisIntro.java
new file mode 100644
index 0000000..79e87b4
--- /dev/null
+++ b/Source/mesquite/genesis/aGenesisIntro/aGenesisIntro.java
@@ -0,0 +1,70 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.aGenesisIntro;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aGenesisIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aGenesisIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Implements stochastic models of molecular evolution.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Genesis Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Genesis Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, D.R.,  & W.P. Maddison.  2006.  Genesis: models of character evolution.  A package of modules for Mesquite. version 1.1.";
+ 	}
+ 	
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "1.11";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "D. & W. Maddison";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+}
+
diff --git a/Source/mesquite/genesis/aGenesisIntro/composite.gif b/Source/mesquite/genesis/aGenesisIntro/composite.gif
new file mode 100644
index 0000000..39b8576
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/composite.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/gamma.gif b/Source/mesquite/genesis/aGenesisIntro/gamma.gif
new file mode 100644
index 0000000..09ab101
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/gamma.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/genesisTest.html b/Source/mesquite/genesis/aGenesisIntro/genesisTest.html
new file mode 100644
index 0000000..043e257
--- /dev/null
+++ b/Source/mesquite/genesis/aGenesisIntro/genesisTest.html
@@ -0,0 +1,188 @@
+<HTML>
+<!--This file created 24/7/01 2:10 PM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Genesis: Models of Character Evolution</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=37 BOTTOM=708 LEFT=141 RIGHT=849>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+</HEAD>
+<BODY>
+<H2><TABLE BORDER=4 CELLPADDING=0>
+   <TR>
+      <TD width="4">
+         <P> </P>
+      </TD>
+      <TD width="454">
+         <H2>Genesis: tests of simulation modules</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<p><a href="index.html">Return to Genesis Package</a></p>
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>The quality of the simulation modules in Mesquite 1.0 were tested by simulated
+   1000 data matrices, each containing 2000 characters, up the branches of the
+  
+  following model tree:</P>
+<P align="center"><img src="testimages/tree.gif" width="388" height="343"></P>
+<p>The model used empirical base frequences (with observed base frequences being 
+  0.3 for A and T, and 0.2 for C and G); other aspects of the model varied from 
+  test to test, as described below.</p>
+<P>PAUP*4.0b10 then estimated a tree quickly using neighbor-joining (using HKY85 
+  distances), and then parameter values were estimated using maximum likelihood 
+  on that tree. </P>
+<P>This analysis was conducted using the Export Matrices & Batch facility 
+  in the Batch Architect package of Mesquite. The resulting distribution of estimated 
+  parameter values across the 1000 replicates as well as a comparison between 
+  the average estimated values and model values are shown below.</P>
+<P>Note that for most parameters the values estimated by PAUP* are slightly greater 
+  than that used in the model. It is not yet clear if this is consistent, and, 
+  if it is, the reason for it.</P>
+<h3>Test 1</h3>
+<P>This model specified that characters evolved with rates varying in accordance 
+  with a discrete gamma distribution, with shape parameter.</P>
+<P> </P>
+<table width="75%" border="1">
+  <tr> 
+    <td width="24%"> </td>
+    <td width="28%">Model Value</td>
+    <td width="48%">Average Estimated Value</td>
+  </tr>
+  <tr> 
+    <td>gamma shape parameter</td>
+    <td>0.80</td>
+    <td>0.8046</td>
+  </tr>
+</table>
+<p> </p>
+<p>Here is a histogram of the estimated value, with the model value shown by a 
+  vertical red line and the average estimated value by a green triangle:</p>
+<p><img src="testimages/gamma.gif" width="429" height="320"> </p>
+<h3></h3>
+<h3>Test 2</h3>
+<P>This model specified that characters evolved at an equal rate; the nucleotides 
+  evolved with a transition/transversion ratio of 2.0.</P>
+<P> </P>
+<table width="75%" border="1">
+  <tr> 
+    <td> </td>
+    <td>Model Value</td>
+    <td>Average Estimated Value</td>
+  </tr>
+  <tr> 
+    <td>ti/tv</td>
+    <td>2.00</td>
+    <td>2.004</td>
+  </tr>
+</table>
+<p>Here is a histogram of the estimated values, with the model value shown by 
+  a vertical red line and the average estimated value by a green triangle:</p>
+<p><img src="testimages/titv.gif" width="429" height="320"> </p>
+<h3>Test 3</h3>
+<P>This model specified that characters evolved at an equal rate; the nucleotides 
+  evolved according to a GTR model with rates (0.70, 3.0, 3.0, 0.4, 3.5).</P>
+<table width="75%" border="1">
+  <tr> 
+    <td> </td>
+    <td>Model Value</td>
+    <td>Average Estimated Value</td>
+  </tr>
+  <tr> 
+    <td>R(a)</td>
+    <td>0.70</td>
+    <td>0.7014</td>
+  </tr>
+  <tr> 
+    <td>R(b)</td>
+    <td>3.0</td>
+    <td>3.014</td>
+  </tr>
+  <tr> 
+    <td>R(c)</td>
+    <td>3.0</td>
+    <td>3.027</td>
+  </tr>
+  <tr> 
+    <td>R(d)</td>
+    <td>0.40</td>
+    <td>0.4080</td>
+  </tr>
+  <tr> 
+    <td>R(e)</td>
+    <td>3.5</td>
+    <td>3.525</td>
+  </tr>
+</table>
+<h4> </h4>
+<P>Here are histograms of the estimated values, with the model values shown by 
+  vertical red lines and the average estimated values by green triangles:</P>
+<P><img src="testimages/gtrra.gif" width="429" height="320"></P>
+<P><img src="testimages/gtrrb.gif" width="429" height="320"></P>
+<P><img src="testimages/gtrrc.gif" width="429" height="320"></P>
+<P><img src="testimages/gtrrd.gif" width="429" height="320"></P>
+<P><img src="testimages/gtrre.gif" width="429" height="320"></P>
+<h4> </h4>
+<h3>Test 4</h3>
+<P>This model specified that 0.62 of the characters are invariable and the remainder 
+  following a discrete gamma shape distribution, with 4 rate categories and shape 
+  parameter 1.3; the nucleotides evolved according to a GTR model with rates (0.56, 
+  4.5, 2.86, 1.05, and 0.95).</P>
+<h4> </h4>
+<table width="75%" border="1">
+  <tr>
+    <td> </td>
+    <td>Model Value</td>
+    <td>Average Estimated Value</td>
+  </tr>
+  <tr>
+    <td>proportion invariable</td>
+    <td>0.62</td>
+    <td>0.6161</td>
+  </tr>
+  <tr>
+    <td>gamma shape parameter</td>
+    <td>1.30</td>
+    <td>1.357</td>
+  </tr>
+  <tr>
+    <td>R(a)</td>
+    <td>0.56</td>
+    <td>0.5714</td>
+  </tr>
+  <tr>
+    <td>R(b)</td>
+    <td>4.50</td>
+    <td>4.642</td>
+  </tr>
+  <tr>
+    <td>R(c)</td>
+    <td>2.86</td>
+    <td>2.963</td>
+  </tr>
+  <tr>
+    <td>R(d)</td>
+    <td>1.05</td>
+    <td>1.069</td>
+  </tr>
+  <tr>
+    <td>R(e)</td>
+    <td>0.95</td>
+    <td>0.9723</td>
+  </tr>
+</table>
+<P> </P>
+<P> </P>
+
+<P>
+
+<HR>
+
+</P>
+
+<P>© David Maddison & Wayne Maddison, 2001-2003</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/genesis/aGenesisIntro/gtr.gif b/Source/mesquite/genesis/aGenesisIntro/gtr.gif
new file mode 100644
index 0000000..bf844ad
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/gtr.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/index.html b/Source/mesquite/genesis/aGenesisIntro/index.html
new file mode 100644
index 0000000..102f2e2
--- /dev/null
+++ b/Source/mesquite/genesis/aGenesisIntro/index.html
@@ -0,0 +1,229 @@
+<HTML>
+<!--This file created 24/7/01 2:10 PM by Claris Home Page version 3.0-->
+<HEAD>
+   <TITLE>Genesis: Models of Character Evolution</TITLE>
+   <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+   <X-CLARIS-WINDOW TOP=37 BOTTOM=708 LEFT=141 RIGHT=849>
+   <X-CLARIS-TAGVIEW MODE=minimal>
+<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+</HEAD>
+<BODY>
+<H2><TABLE BORDER=0 CELLPADDING=0>
+   <TR>
+      <TD>
+         <P><IMG SRC="splash.gif" WIDTH=164 HEIGHT=64 X-CLARIS-USEIMAGEWIDTH X-CLARIS-USEIMAGEHEIGHT ALIGN=bottom></P>
+      </TD>
+      <TD>
+         <H2>Genesis: probabilistic models of character evolution for Mesquite</H2>
+      </TD>
+   </TR>
+</TABLE>
+</H2>
+
+<H4>David Maddison & Wayne Maddison</H4>
+
+<P>August 2005</P>
+
+<P>Genesis is a Mesquite package providing models of character
+evolution. Currently these are only available for use in simulations,
+but will eventually be available for estimation methods such as
+maximum likelihood.</P>
+
+<UL>
+  <LI><A HREF="#overview">Overview</A></LI>
+  <LI><A HREF="#installation">Installation</A></LI>
+  <LI><A HREF="#creatingmodels">Creating models</A></LI>
+  <LI><A HREF="#usingmodels">Using models</A></LI>
+  <LI><A HREF="#examples">Examples</A></LI>
+  <LI><a href="#tests">Tests of Genesis's simulations</a></LI>
+</UL>
+
+<H3><A NAME=overview></A>Overview</H3>
+
+<P>The Genesis package includes models in several classes:</P>
+
+<UL>
+   <LI><B>State frequencies</B>. These are used both to specify the
+   nature of the root state and the equilibrium state
+   frequencies.</LI>
+   
+   <LI><B>Character rates</B>. These specify the variation in rate of
+   evolution from one character to the next.</LI>
+   
+   <LI><B>Rate matrices</B>. These specify the relative frequency of
+   changes between states.</LI>
+</UL>
+
+<P>Each of these model classes as one or more default models
+specified in Mesquite:</P>
+
+<UL>
+   
+  <LI><B>State frequencies</B>. There are two default state frequencies models 
+    built in, both for DNA data. Each of the four bases can either have frequencies 
+    that are equal (all 0.25), or that match the empirical frequencies of an existing 
+    matrix. The user can also create a model with specified frequencies.</LI>
+   
+   <LI><B>Character rates</B>. The one default model specifies that
+   all characters evolve at the same rate.</LI>
+   
+   <LI><B>Rate matrices</B>. The default model specifies that all
+   changes occur at equal rates, as in a Jukes Cantor model.</LI>
+</UL>
+
+<P>In addition, you can create some additional models by specifying
+parameter values of some partly-specified models:</P>
+
+<H4>Partly specified state frequency models</H4>
+<P>
+<TABLE BORDER=1>
+  <TR> 
+    <TD WIDTH=179> <P><B>Model type</B></P></TD>
+    <TD> <P><B>Parameter to specify</B></P></TD>
+  </TR>
+  <TR> 
+    <TD WIDTH=179> <P>User-defined Frequency model</P></TD>
+    <TD> <P>The frequency of A, C, G, and T</P></TD>
+  </TR>
+</TABLE>
+<H4> </H4>
+<H4>Partly specified character rate models</H4>
+
+<P>
+<TABLE BORDER=1>
+  <TR> 
+    <TD WIDTH=179> <P><B>Model type</B></P></TD>
+    <TD> <P><B>Parameter to specify</B></P></TD>
+  </TR>
+  <TR> 
+    <TD WIDTH=179> <P>Proportion Invariant models</P></TD>
+    <TD> <P>The proportion of characters that are not free to vary.</P></TD>
+  </TR>
+  <TR> 
+    <TD> <P>Gamma distribution models</P></TD>
+    <TD> <P>The shape parameter of the gamma distribution.</P></TD>
+  </TR>
+  <TR> 
+    <TD WIDTH=179> <P>Gamma distribution + Proportion invariant models</P></TD>
+    <TD> <P>The shape parameter of the gamma distribution and the proportion of 
+        characters that are not free to vary.</P></TD>
+  </TR>
+</TABLE>
+</P>
+
+<P>The Gamma distribution is implemented using
+calculations done by the <A HREF="http://jsci.sourceforge.net">JSci
+library</A> by Hale, van Kooten, and others.</P>
+
+
+<H4>Partly specified rate matrices</H4>
+
+<P><TABLE BORDER=1>
+   <TR>
+      <TD WIDTH=180>
+         <P><B>Model type</B></P>
+      </TD>
+      <TD>
+         <P><B>Parameter to specify</B></P>
+      </TD>
+   </TR>
+   <TR>
+      <TD WIDTH=180>
+         <P>TiTv models</P>
+      </TD>
+      <TD>
+         <P>The transition/transversion ratio.</P>
+      </TD>
+   </TR>
+   <TR>
+      <TD WIDTH=180>
+         <P>GTR model</P>
+      </TD>
+      <TD>
+         <P>Rates of change A-C, A-G, A-T, C-G, C-T relative to (rate
+         G-T) =1</P>
+      </TD>
+   </TR>
+</TABLE>
+</P>
+
+<P>Many more models will be added. The GTR model is implemented using calculations 
+  done by the <A HREF="http://www.cebl.auckland.ac.nz/pal-project/">PAL library</A> 
+  by Drummond and Strimmer.</P>
+
+<H3><A NAME=installation></A>Installation</H3>
+
+<P>To install the Genesis package, the "genesis" directory must be installed in 
+  the "mesquite" directory within "Mesquite Folder". The PAL library needs also 
+  to be installed; to see that it is, see that there is a "pal" directory within 
+  "Mesquite Folder". JSci should also be present, as a "JSci" directory 
+  within "Mesquite Folder". If either is not installed, then you should 
+  download the latest version of Mesquite from <A HREF="http://mesquiteproject.org">Mesquite's 
+  web site</A>, which should contain PAL and JSci.</P>
+
+<H3><A NAME=creatingmodels></A>Creating models</H3>
+
+<P>Before models can be used, they must exist. The pre-defined,
+fully-specified models already exist, but to use the partly-specified
+models (such as a gamma distribution character rate model), you will
+need to create a new character model using the submenus of the New
+Character Model item in the Character menu.</P>
+
+<P>For example, to create a model that specifies a gamma rate
+variation model with shape parameter of 0.8, choose Gamma Rate
+Variation Model from the New Character Model submenu. You will
+presented with a dialog box in which you can name your model (e.g.,
+"Gamma 0.8" or "Gamma for simulations"), and then another dialog box
+in which you can specify the value of the shape parameter:</P>
+
+<CENTER>
+  <IMG SRC="gamma.gif" WIDTH=280 HEIGHT=231 X-CLARIS-USEIMAGEWIDTH X-CLARIS-USEIMAGEHEIGHT ALIGN=bottom>
+</CENTER>
+
+<P>Once defined, this model will then be available for use in
+Mesquite. Similarly, a GTR rate matrix model may be defined in this
+dialog:</P>
+
+<CENTER>
+  <IMG SRC="gtr.gif" WIDTH=337 HEIGHT=217 ALIGN=bottom>
+</CENTER>
+
+<H3><A NAME=usingmodels></A>Using models</H3>
+
+<P>One context in which you can now use a model is to create
+simulated matrices or characters. These will be created by simulating
+evolution up the branches of a particular tree, using the models of
+evolution that you specify. You will be asked to specify a composite
+model in a dialog box that looks something like this:</P>
+
+<CENTER>
+  <IMG SRC="composite.gif" WIDTH=493 HEIGHT=417 ALIGN=bottom> 
+</CENTER>
+
+<P>Choose the relevant submodels in each of the popdown menus. Before
+a submodel can appear in the popdown menu, it must be created (see
+preceding section).</P>
+
+<P>Note the scaling factor. This allows you to scale the entire rate
+of evolution according to the tree (for instance, if the trees
+branches are measured in years, a low scaling factor would be needed
+to make a reasonable rate of substitution.</P>
+
+<H3><A NAME=examples></A>Examples</H3>
+
+<P>Some examples of Genesis's use are provided in the <a href="../../../docs/mesquite/studies/index.html">Studies</a> in the Mesquite
+  manual.</P>
+
+<H3><A NAME=citation></A>Tests of Genesis's simulations</H3>
+<P>See the page "<a href="genesisTest.html">Genesis: tests of simulation 
+  modules</a>" for some empirical studies of the quality of Genesis's simulations.</P>
+<P>
+
+<HR>
+
+</P>
+
+<P>© David Maddison & Wayne Maddison, 2001-2005</P>
+</BODY>
+</HTML>
+
diff --git a/Source/mesquite/genesis/aGenesisIntro/splash.gif b/Source/mesquite/genesis/aGenesisIntro/splash.gif
new file mode 100644
index 0000000..94a4c17
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/splash.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/splashSmall.gif b/Source/mesquite/genesis/aGenesisIntro/splashSmall.gif
new file mode 100644
index 0000000..0f537ce
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/splashSmall.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gamma.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gamma.gif
new file mode 100644
index 0000000..a7bde28
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gamma.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gtrra.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrra.gif
new file mode 100644
index 0000000..7f1a1c5
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrra.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrb.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrb.gif
new file mode 100644
index 0000000..e117a8f
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrb.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrc.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrc.gif
new file mode 100644
index 0000000..7f3704e
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrc.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrd.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrd.gif
new file mode 100644
index 0000000..e2562c3
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrrd.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/gtrre.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrre.gif
new file mode 100644
index 0000000..36f583b
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/gtrre.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/titv.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/titv.gif
new file mode 100644
index 0000000..1a8beeb
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/titv.gif differ
diff --git a/Source/mesquite/genesis/aGenesisIntro/testimages/tree.gif b/Source/mesquite/genesis/aGenesisIntro/testimages/tree.gif
new file mode 100644
index 0000000..c21f4f6
Binary files /dev/null and b/Source/mesquite/genesis/aGenesisIntro/testimages/tree.gif differ
diff --git a/Source/mesquite/genesis/explanation.txt b/Source/mesquite/genesis/explanation.txt
new file mode 100644
index 0000000..bfa3c8c
--- /dev/null
+++ b/Source/mesquite/genesis/explanation.txt
@@ -0,0 +1,2 @@
+Genesis Package for Stochastic Models of Molecular Evolution
+Provides simulations and will provide likelihood calculations for stochastic models (e.g., HKY85, GTR) of molecular sequence evolution.
diff --git a/Source/mesquite/genesis/lib/CharRateMatrixModelSet.java b/Source/mesquite/genesis/lib/CharRateMatrixModelSet.java
new file mode 100644
index 0000000..1695574
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRateMatrixModelSet.java
@@ -0,0 +1,42 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/*======================================================================== */
+/** a ModelSet for probability models. */
+public class CharRateMatrixModelSet  extends ModelSet {
+	
+	public CharRateMatrixModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Character Rate Matrix Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CharRateMatrixModelSet ms = new CharRateMatrixModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharRateMatrixModelSet("Rate Matrix Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesCodePos.java b/Source/mesquite/genesis/lib/CharRatesCodePos.java
new file mode 100644
index 0000000..bff81de
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesCodePos.java
@@ -0,0 +1,281 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import java.lang.Math.*;
+import java.awt.*;
+
+/** A class that provides for a site-to-site rate variation model. */
+/* ======================================================================== */
+public class CharRatesCodePos extends CharRatesModel {
+	double[] codePosRates;
+	double[] codePosRatesTemp;
+	String errorMessage="";
+	Random randomNumber;
+	DoubleField[] codePosRatesField;
+	int numRates = 5;
+	CodonPositionsSet modelSet = null;
+	boolean baseOnMatrix = false;
+	boolean baseOnMatrixTemp = false;
+	Checkbox baseOnMatrixCheckBox;
+	int codonPosition = 1;
+
+	public CharRatesCodePos (double[] codePosRates) {
+		super();
+		codePosRates = new double[numRates];
+		codePosRatesTemp = new double[numRates];
+		this.codePosRates = codePosRates;
+		randomNumber = new Random();
+		//setNewRate();
+ 	}
+	public CharRatesCodePos () {
+		super();
+		codePosRates = new double[numRates];
+		codePosRatesTemp = new double[numRates];
+		for (int i=0; i<numRates; i++) {
+			codePosRates[i] = MesquiteDouble.unassigned;
+			codePosRatesTemp[i] = MesquiteDouble.unassigned;
+		}
+		codePosRates[0] = 1.0;
+		codePosRatesTemp[0] = 1.0;
+		codePosRates[4] = 1.0;
+		codePosRatesTemp[4] = 1.0;
+		randomNumber = new Random();
+		codonPosition = 1;
+		//setNewRate();
+ 	}
+
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return true if submodel needs an empirical matrix*/
+	public boolean needsEmpirical(){
+		return baseOnMatrix;
+	}
+ 	/*.................................................................................................................*/
+	public void initialize() {
+		codonPosition = 1;
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		CharRatesCodePos model = new CharRatesCodePos();
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof CharRatesCodePos))
+			return;
+		CharRatesCodePos model = (CharRatesCodePos)md;
+		model.baseOnMatrixTemp = baseOnMatrixTemp;
+		model.setCodePosRates(codePosRates);
+		model.baseOnMatrix = baseOnMatrix;
+		super.copyToClone(md);
+	}
+	/*.................................................................................................................*/
+	public void setNewRate(int ic) {
+		if (baseOnMatrix) {
+			if (modelSet != null && ic<modelSet.getNumberOfParts() && ic>=0) {
+				int position = modelSet.getInt(ic);
+				if (position==MesquiteInteger.unassigned)
+					position=numRates-1;
+				if (position>=0 && position<=numRates-1 && codePosRates[position] != MesquiteDouble.unassigned) {
+					setRate(codePosRates[position]);
+				}
+				else
+					setRate(1.0);
+			}
+			else
+				setRate(1.0);
+		}
+		else {
+			setRate(codePosRates[ic]);
+		}
+/*		if (codePosRates[0] != MesquiteDouble.unassigned)
+			if (randomNumber.nextDouble()<=codePosRates)
+				setRate(0.0);
+			else
+				setRate(1.0);
+*/
+	}
+	/*.................................................................................................................*/
+	public boolean checkValidityCharRates (){  
+		MCharactersStatesHolder d = probabilityModel.getMCharactersStatesHolder();
+		if (!(DNAData.class.isAssignableFrom(d.getCharacterDataClass()))){
+			MesquiteMessage.warnProgrammer("Empirical data in model null or not DNA data; will use equal freq. (CodonRatesCodPos)");
+			return false;
+		}
+		MCategoricalStates data = (MCategoricalStates)d;
+		if (data!=null){
+			DNAData dnaData= (DNAData)data.getParentData();
+			if (dnaData==null)
+				return false;
+			modelSet = (CodonPositionsSet)dnaData.getCurrentSpecsSet(CodonPositionsSet.class);
+			return (modelSet!=null);
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		codePosRatesField = new DoubleField[numRates];
+	
+		for (int i=1; i<numRates-1; i++) {
+			codePosRatesField[i] = dialog.addDoubleField(""+i+":",codePosRates[i], 10);
+		}
+		codePosRatesField[0] = dialog.addDoubleField("N:",codePosRates[0], 10);   // this is for non-coding positions
+		codePosRatesField[numRates-1] = dialog.addDoubleField("?:",codePosRates[numRates-1], 10);  // this is for unspecified positions
+		baseOnMatrixCheckBox = dialog.addCheckBox("use positions in existing matrix", baseOnMatrix);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		for (int i=0; i<numRates; i++) {
+			codePosRatesTemp[i] = codePosRatesField[i].getValue();
+		}
+		baseOnMatrixTemp = baseOnMatrixCheckBox.getState();
+		codonPosition = 1;
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		for (int i=0; i<numRates; i++) {
+			codePosRatesTemp[i] = codePosRatesField[i].getValue();
+			if (!MesquiteDouble.isCombinable(codePosRatesTemp[i])) {
+				errorMessage = "Some fields do not have numbers entered into them.";
+				return false;
+			}
+			else if (codePosRatesTemp[i]<0.0) {
+				errorMessage = "Numbers must be greater than or equal to 0.0";
+				return false;
+			}
+				
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {
+		baseOnMatrix = baseOnMatrixTemp;
+		setCodePosRates(codePosRatesTemp);
+		codonPosition = 1;
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		for (int i=0; i<numRates; i++)
+			if (codePosRates[i]== MesquiteDouble.unassigned)
+				return false;
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public void setCodePosRates (double[] codePosRates) {
+		this.codePosRates = codePosRates;
+		codonPosition = 1;
+//		setNewRate();
+ 	}
+ 	/*.................................................................................................................*/
+	public double[] getCodePosRates () {
+		return codePosRates;
+ 	}
+
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+		if (!baseOnMatrix) {
+			if (probabilityModel.isFirstCharacter()) {
+				codonPosition = 1;
+			}
+			setNewRate(codonPosition);
+			codonPosition++;
+			if (codonPosition>3)
+				codonPosition = 1;
+		}
+		else if (checkValidityCharRates()) {
+			if (probabilityModel !=null) {
+				if (probabilityModel.getCharacterDistribution()!=null) {
+						setNewRate(probabilityModel.getCharacterDistribution().getParentCharacter());
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** returns speficiations*/
+	public String getNexusSpecification() {
+		String s = "codePosRates = (";
+		for (int i=0; i<numRates; i++) {
+			if (i>0)
+				s += " ";
+			s += MesquiteDouble.toString(codePosRates[i]);
+		}
+		if (baseOnMatrix)
+			s += " baseOnMatrix)";
+		else
+			s += " noBaseOnMatrix)";
+		return s;
+		
+	}
+	/*.................................................................................................................*/
+	/** reads parameters from string (same format as written by "toSTring"*/
+	public void fromString(String description, MesquiteInteger stringPos, int format) {
+		String s;
+		ParseUtil.getToken(description, stringPos); //codePo
+		ParseUtil.getToken(description, stringPos); // =
+		ParseUtil.getToken(description, stringPos); // (
+		for (int i=0; i<numRates; i++) {
+			s = ParseUtil.getToken(description, stringPos);
+   			codePosRates[i] = MesquiteDouble.fromString(s);
+   		}
+		s = ParseUtil.getToken(description, stringPos);
+		if ("baseOnMatrix".equalsIgnoreCase(s)) {
+			baseOnMatrix = true;
+			baseOnMatrixTemp = true;
+		}
+		else {
+			baseOnMatrix = false;
+			baseOnMatrixTemp = false;
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "codePosRates";
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		String s = "Codon Position Rates = ";
+		for (int i=1; i<=3; i++) {
+			if (i>1)
+				s += " ";
+			s += "Position "+i+": ";
+			s += MesquiteDouble.toString(codePosRates[i]);
+		}
+		s += " Non-coding: ";
+		s += MesquiteDouble.toString(codePosRates[0]);
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesCurator.java b/Source/mesquite/genesis/lib/CharRatesCurator.java
new file mode 100644
index 0000000..8a8e2e3
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesCurator.java
@@ -0,0 +1,34 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class CharRatesCurator extends ProbSubModelCurator  {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+}
+
+
diff --git a/Source/mesquite/genesis/lib/CharRatesEqual.java b/Source/mesquite/genesis/lib/CharRatesEqual.java
new file mode 100644
index 0000000..62864c9
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesEqual.java
@@ -0,0 +1,82 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides for a site-to-site rate variation model. */
+/* ======================================================================== */
+public class CharRatesEqual extends CharRatesModel {
+
+	/*.................................................................................................................*/
+	public double getRate (int ic) {
+	/*	if (ic % 3 == 0)
+			return 1.0;
+		else
+	*/		return 1.0;
+	}
+	/*.................................................................................................................*/
+	public String getNexusSpecification(){
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		CharRatesEqual model = new CharRatesEqual();
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+	}
+	public boolean isFullySpecified(){
+		return true;
+	}
+	/** returns whether model is built in*/
+	public boolean isBuiltIn() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {return true;}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {}
+ 	/*.................................................................................................................*/
+	/** returns name of model*/
+	public String getName() {
+		return "Equal Rates";
+	}
+ 	/*.................................................................................................................*/
+	/** returns name of model*/
+	public String getNEXUSName() {
+		return "equal";
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "Equal Rates";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesGamma.java b/Source/mesquite/genesis/lib/CharRatesGamma.java
new file mode 100644
index 0000000..e4eeea1
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesGamma.java
@@ -0,0 +1,244 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import java.lang.Math.*;
+import JSci.maths.statistics.*;
+import JSci.maths.*;
+
+/** A class that provides for a site-to-site rate variation model using the gamma distribution. */
+/* ======================================================================== */
+public class CharRatesGamma extends CharRatesModel {
+	Random randomNumber;
+	double shape = MesquiteDouble.unassigned;
+	double shapeTemp=MesquiteDouble.unassigned;
+	DoubleField shapeField;
+	boolean isDiscrete = true;
+	boolean isDiscreteTemp;
+	Checkbox isDiscreteCheckBox;
+	String errorMessage="";
+	int numCategories=4;  
+	int numCategoriesTemp;
+	IntegerField numCategoriesField; 
+	GammaDistribution gammaDist; 
+	double increment;
+	
+	double[] categoryBoundaries = null;
+	double[] categoryRates = null;
+		
+
+	public CharRatesGamma (double shape, boolean isDiscrete, int numCategories) {
+		super();
+		this.shape = shape;
+		this.numCategories = numCategories; 
+		increment = 1.0/numCategories;
+		this.isDiscrete = isDiscrete;
+		randomNumber = new Random();
+		gammaDist = new GammaDistribution(shape); 
+		setShape(shape);
+		setRate(sampleGamma());
+ 	}
+	public CharRatesGamma () {
+		super();
+		randomNumber = new Random();
+		gammaDist = new GammaDistribution(0.5); 
+		//setRate(RndGamma(shape));
+ 	}
+
+	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		CharRatesGamma model = new CharRatesGamma(shape, isDiscrete, numCategories);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof CharRatesGamma) {
+			CharRatesGamma gi = (CharRatesGamma) pm;
+			gi.shape = shape;
+			gi.isDiscrete = isDiscrete;
+			gi.setShape(shape);
+		}
+		super.copyToClone(pm);
+	}
+	/*.................................................................................................................*/
+	/** returns specifications*/
+	public String getNexusSpecification() {
+		String s = "shape = " + MesquiteDouble.toString(shape);
+		if (isDiscrete) {
+			s += " discrete categories = "+numCategories;
+		}
+		else
+			s += "continuous";
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+	/*.................................................................................................................*/
+	/** reads parameters from string (same format as written by "toString")*/
+	public void fromString(String description, MesquiteInteger stringPos, int format) {
+		String s = ParseUtil.getToken(description, stringPos);
+		while (!StringUtil.blank(s)) {
+			if (s.equalsIgnoreCase("shape")) {
+				ParseUtil.getToken(description, stringPos);  // =
+				s = ParseUtil.getToken(description, stringPos);
+   				shape = MesquiteDouble.fromString(s);
+			}
+			else if (s.equalsIgnoreCase("categories")) {
+				ParseUtil.getToken(description, stringPos);  // =
+				s = ParseUtil.getToken(description, stringPos);
+   				numCategories = MesquiteInteger.fromString(s);
+   				increment = 1.0/numCategories;
+			}
+			else if (s.equalsIgnoreCase("discrete")) {
+				isDiscrete = true;
+			}
+			else if (s.equalsIgnoreCase("continuous")) {
+				isDiscrete = false;
+			}
+			s = ParseUtil.getToken(description, stringPos);
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "Gamma";
+	}
+	/*.................................................................................................................*/
+	/** adds items to extensible dialog box used for setting parameter values*/
+	public void addOptions(ExtensibleDialog dialog) {
+		shapeField = dialog.addDoubleField("gamma shape parameter:",shape, 10);
+		isDiscreteCheckBox = dialog.addCheckBox("discrete gamma", isDiscrete);
+		numCategoriesField = dialog.addIntegerField("number of categories:",numCategories, 4);
+	}
+ 	/*.................................................................................................................*/
+	/** recovers values from items in extensible dialog box used for setting parameter values*/
+	public boolean recoverOptions() {
+		shapeTemp = shapeField.getValue();
+		isDiscreteTemp = isDiscreteCheckBox.getState();
+		numCategoriesTemp = numCategoriesField.getValue();
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		shapeTemp = shapeField.getValue();
+		isDiscreteTemp = isDiscreteCheckBox.getState();
+		numCategoriesTemp = numCategoriesField.getValue();
+		if (!MesquiteDouble.isCombinable(shapeTemp)) {
+			errorMessage = "The shape parameter is not valid.";
+			return false;
+		}
+		if (shapeTemp<=0.0) {
+			errorMessage = "The shape parameter must be greater than 0.0";
+			return false;
+		}
+		if (isDiscreteTemp && !MesquiteInteger.isCombinable(numCategoriesTemp)) {
+			errorMessage = "The number of categories must be entered if a discrete gamma is chosen.";
+			return false;
+		}
+		if (isDiscreteTemp && !numCategoriesField.isValidInteger()) {
+			errorMessage = "The number of categories must be an integer.";
+			return false;
+		}
+		if (isDiscreteTemp && (numCategoriesTemp<=1)) {
+			errorMessage = "The number of categories must be greater than 1";
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	/** moves parameter values from temporary storage (where they were put from dialog box) into permanent storage.*/
+	public void setOptions() {
+		isDiscrete = isDiscreteTemp;
+		numCategories = numCategoriesTemp;
+		increment = 1.0/numCategories;
+		setShape(shapeTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		return shape != MesquiteDouble.unassigned;
+	}
+ 	/*.................................................................................................................*/
+	/** Calculates mean value for a section of a gamma distribution.*/
+	public double meanRate(double lowerBoundary, double upperBoundary, double increment){
+		return (SpecialMath.incompleteGamma(shape+1,upperBoundary*shape)-SpecialMath.incompleteGamma(shape+1,lowerBoundary*shape))/increment;
+	}
+ 	/*.................................................................................................................*/
+	public void calculateDiscreteRates () {
+		categoryBoundaries = new double[numCategories+1];
+		categoryBoundaries[0]=0.0;
+		categoryBoundaries[numCategories]=100000.0;
+		for (int i=1; i<numCategories; i++) {
+			categoryBoundaries[i] = gammaDist.inverse(i*increment)/shape;
+		}
+		categoryRates = new double[numCategories];
+		for (int i=0; i<numCategories; i++) {
+			categoryRates[i] = meanRate(categoryBoundaries[i],categoryBoundaries[i+1], increment);
+		}
+ 	}
+ 	/*.................................................................................................................*/
+	public void setShape (double shape) {
+		this.shape = shape;
+		gammaDist.setShapeParameter(shape);
+		calculateDiscreteRates();
+		setRate(sampleGamma());
+ 	}
+ 	/*.................................................................................................................*/
+	public double getShape() {
+		return shape;
+ 	}
+	/*.................................................................................................................*/
+	double sampleGamma () {
+		if (isDiscrete) {
+			int category = (int)(randomNumber.nextDouble()/increment);
+			return categoryRates[category];
+		}	
+		else
+			return (gammaDist.inverse(randomNumber.nextDouble())/shape);
+	}
+
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+		double g = sampleGamma();
+		setRate(g);
+	}
+
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "Gamma distribution, shape parameter = " + shape;
+	}
+
+
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesGammaInvar.java b/Source/mesquite/genesis/lib/CharRatesGammaInvar.java
new file mode 100644
index 0000000..9ae1140
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesGammaInvar.java
@@ -0,0 +1,281 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import java.lang.Math.*;
+import JSci.maths.statistics.*;
+import JSci.maths.*;
+
+/** A class that provides for a site-to-site rate variation model using the gamma distribution. */
+/* ======================================================================== */
+public class CharRatesGammaInvar extends CharRatesModel {
+	Random randomNumber;
+
+	double pInvar = MesquiteDouble.unassigned;
+	double pInvarTemp = MesquiteDouble.unassigned;
+	DoubleField pInvarField;
+	
+	double shape = MesquiteDouble.unassigned;
+	double shapeTemp=MesquiteDouble.unassigned;
+	DoubleField shapeField;
+	boolean isDiscrete = true;
+	boolean isDiscreteTemp;
+	Checkbox isDiscreteCheckBox;
+	int numCategories=4;  
+	int numCategoriesTemp;
+	IntegerField numCategoriesField; 
+	GammaDistribution gammaDist; 
+	double increment;
+	String errorMessage="";
+	
+	double[] categoryBoundaries = null;
+	double[] categoryRates = null;
+		
+
+	public CharRatesGammaInvar (double pInvar, double shape, boolean isDiscrete, int numCategories) {
+		super();
+		this.pInvar = pInvar;
+		this.shape = shape;
+		this.numCategories = numCategories; 
+		increment = 1.0/numCategories;
+		this.isDiscrete = isDiscrete;
+		randomNumber = new Random();
+		gammaDist = new GammaDistribution(shape); 
+		setShape(shape);
+		setRate(sampleGammaInvar());
+ 	}
+	public CharRatesGammaInvar () {
+		super();
+		randomNumber = new Random();
+		gammaDist = new GammaDistribution(0.5); 
+		//setRate(RndGamma(shape));
+ 	}
+
+	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		CharRatesGammaInvar model = new CharRatesGammaInvar(pInvar, shape, isDiscrete, numCategories);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof CharRatesGammaInvar) {
+			CharRatesGammaInvar gi = (CharRatesGammaInvar) pm;
+			gi.pInvar = pInvar;
+			gi.shape = shape;
+			gi.isDiscrete = isDiscrete;
+			gi.setShape(shape);
+		}
+		super.copyToClone(pm);
+	}
+	/*.................................................................................................................*/
+	/** returns specifications*/
+	public String getNexusSpecification() {
+		String s = "pInvar = " + MesquiteDouble.toString(pInvar);
+		s += " shape = " + MesquiteDouble.toString(shape);
+		if (isDiscrete) {
+			s += " discrete categories = "+numCategories;
+		}
+		else
+			s += "continuous";
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+	/*.................................................................................................................*/
+	/** reads parameters from string (same format as written by "toString")*/
+	public void fromString(String description, MesquiteInteger stringPos, int format) {
+		String s = ParseUtil.getToken(description, stringPos);
+		while (!StringUtil.blank(s)) {
+			if (s.equalsIgnoreCase("shape")) {
+				ParseUtil.getToken(description, stringPos);  // =
+				s = ParseUtil.getToken(description, stringPos);
+   				shape = MesquiteDouble.fromString(s);
+			}
+			else if (s.equalsIgnoreCase("categories")) {
+				ParseUtil.getToken(description, stringPos);  // =
+				s = ParseUtil.getToken(description, stringPos);
+   				numCategories = MesquiteInteger.fromString(s);
+   				increment = 1.0/numCategories;
+			}
+			else if (s.equalsIgnoreCase("pInvar")) {
+				ParseUtil.getToken(description, stringPos);  // =
+				s = ParseUtil.getToken(description, stringPos);
+   				pInvar = MesquiteDouble.fromString(s);
+			}
+			else if (s.equalsIgnoreCase("discrete")) {
+				isDiscrete = true;
+			}
+			else if (s.equalsIgnoreCase("continuous")) {
+				isDiscrete = false;
+			}
+			s = ParseUtil.getToken(description, stringPos);
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "GammaInvar";
+	}
+	/*.................................................................................................................*/
+	/** adds items to extensible dialog box used for setting parameter values*/
+	public void addOptions(ExtensibleDialog dialog) {
+		pInvarField = dialog.addDoubleField("proportion invariant:",pInvar, 10);
+		shapeField = dialog.addDoubleField("gamma shape parameter:",shape, 10);
+		isDiscreteCheckBox = dialog.addCheckBox("discrete gamma", isDiscrete);
+		numCategoriesField = dialog.addIntegerField("number of categories:",numCategories, 4);
+	}
+ 	/*.................................................................................................................*/
+	/** recovers values from items in extensible dialog box used for setting parameter values*/
+	public boolean recoverOptions() {
+		pInvarTemp = pInvarField.getValue();
+		shapeTemp = shapeField.getValue();
+		isDiscreteTemp = isDiscreteCheckBox.getState();
+		numCategoriesTemp = numCategoriesField.getValue();
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		pInvarTemp = pInvarField.getValue();
+		shapeTemp = shapeField.getValue();
+		isDiscreteTemp = isDiscreteCheckBox.getState();
+		numCategoriesTemp = numCategoriesField.getValue();
+		if (!MesquiteDouble.isCombinable(pInvarTemp)) {
+			errorMessage = "The proportion of invariant characters is not valid.";
+			return false;
+		}
+		if (pInvarTemp<0.0 || pInvarTemp>1.0) {
+			errorMessage = "The proportion of invariant characters must be between 0.0 and 1.0";
+			return false;
+		}
+		if (!MesquiteDouble.isCombinable(shapeTemp)) {
+			errorMessage = "The shape parameter is not valid.";
+			return false;
+		}
+		if (shapeTemp<=0.0) {
+			errorMessage = "The shape parameter must be greater than 0.0";
+			return false;
+		}
+		if (isDiscreteTemp && !MesquiteInteger.isCombinable(numCategoriesTemp)) {
+			errorMessage = "The number of categories must be entered if a discrete gamma is chosen.";
+			return false;
+		}
+		if (isDiscreteTemp && !numCategoriesField.isValidInteger()) {
+			errorMessage = "The number of categories must be an integer.";
+			return false;
+		}
+		if (isDiscreteTemp && (numCategoriesTemp<=1)) {
+			errorMessage = "The number of categories must be greater than 1";
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	/** moves parameter values from temporary storage (where they were put from dialog box) into permanent storage.*/
+	public void setOptions() {
+		isDiscrete = isDiscreteTemp;
+		numCategories = numCategoriesTemp;
+		increment = 1.0/numCategories;
+		pInvar = pInvarTemp;
+		setShape(shapeTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		return shape != MesquiteDouble.unassigned;
+	}
+ 	/*.................................................................................................................*/
+	/** Calculates mean value for a section of a gamma distribution.*/
+	public double meanRate(double lowerBoundary, double upperBoundary, double increment){
+		return (SpecialMath.incompleteGamma(shape+1,upperBoundary*shape)-SpecialMath.incompleteGamma(shape+1,lowerBoundary*shape))/increment;
+	}
+ 	/*.................................................................................................................*/
+	public void calculateDiscreteRates () {
+		categoryBoundaries = new double[numCategories+1];
+		categoryBoundaries[0]=0.0;
+		categoryBoundaries[numCategories]=100000.0;
+		for (int i=1; i<numCategories; i++) {
+			categoryBoundaries[i] = gammaDist.inverse(i*increment)/shape;
+		}
+		categoryRates = new double[numCategories];
+		for (int i=0; i<numCategories; i++) {
+			categoryRates[i] = meanRate(categoryBoundaries[i],categoryBoundaries[i+1], increment);
+		}
+ 	}
+ 	/*.................................................................................................................*/
+	public void setShape (double shape) {
+		this.shape = shape;
+		gammaDist.setShapeParameter(shape);
+		calculateDiscreteRates();
+		setRate(sampleGammaInvar());
+ 	}
+ 	/*.................................................................................................................*/
+	public double getShape() {
+		return shape;
+ 	}
+	/*.................................................................................................................*/
+	double sampleGammaInvar () {
+		
+		if (pInvar != MesquiteDouble.unassigned)
+			if (randomNumber.nextDouble()<=pInvar)
+				return 0.0;
+			else
+				if (isDiscrete) {
+					int category = (int)(randomNumber.nextDouble()/increment);
+					return categoryRates[category]/(1-pInvar);  // divide by (1-pInvar) so that the average rate is 1.0
+				}	
+				else
+					return ((gammaDist.inverse(randomNumber.nextDouble())/shape)/(1-pInvar));// divide by (1-pInvar) so that the average rate is 1.0
+		return 1.0;
+	}
+
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+		double g = sampleGammaInvar();
+		setRate(g);
+	}
+
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		String s = "Proportion of invariant characters: "+ pInvar+"; the remainder follow a ";
+		if (isDiscrete) {
+			s += "discrete gamma distribution with shape parameter = " + shape + ", with " +numCategories + " categories.";
+		}
+		else
+			s += "continuous gamma distribution with shape parameter " + shape + ".";
+		return s;
+	}
+
+
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesInvar.java b/Source/mesquite/genesis/lib/CharRatesInvar.java
new file mode 100644
index 0000000..c19138a
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesInvar.java
@@ -0,0 +1,150 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import java.lang.Math.*;
+
+/** A class that provides for a site-to-site rate variation model. */
+/* ======================================================================== */
+public class CharRatesInvar extends CharRatesModel {
+	Random randomNumber;
+	double pInvar = MesquiteDouble.unassigned;
+	double pInvarTemp = MesquiteDouble.unassigned;
+	DoubleField pInvarField;
+	String errorMessage="";
+
+	public CharRatesInvar (double pInvar) {
+		super();
+		this.pInvar = pInvar;
+		randomNumber = new Random();
+		setNewRate();
+ 	}
+	public CharRatesInvar () {
+		super();
+		randomNumber = new Random();
+		setNewRate();
+ 	}
+
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		CharRatesInvar model = new CharRatesInvar(pInvar);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof CharRatesInvar) {
+			CharRatesInvar gi = (CharRatesInvar) pm;
+			gi.pInvar = pInvar;
+			gi.setNewRate();
+		}
+		super.copyToClone(pm);
+	}
+	/*.................................................................................................................*/
+	public void setNewRate() {
+		if (pInvar != MesquiteDouble.unassigned)
+			if (randomNumber.nextDouble()<=pInvar)
+				setRate(0.0);
+			else
+				setRate(1.0/(1-pInvar));
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		pInvarField = dialog.addDoubleField("proportion invariant:",pInvar, 10);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		pInvarTemp = pInvarField.getValue();
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		pInvarTemp = pInvarField.getValue();
+		if (!MesquiteDouble.isCombinable(pInvarTemp)) {
+			errorMessage = "The proportion of invariant characters is not valid.";
+			return false;
+		}
+		if (pInvarTemp<0.0 || pInvarTemp>1.0) {
+			errorMessage = "The proportion of invariant characters must be between 0.0 and 1.0";
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+	/*.................................................................................................................*/
+	public void setOptions() {
+		setPInvar(pInvarTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		return (pInvar != MesquiteDouble.unassigned);
+	}
+ 	/*.................................................................................................................*/
+	public void setPInvar (double pInvar) {
+		this.pInvar = pInvar;
+		setNewRate();
+ 	}
+ 	/*.................................................................................................................*/
+	public double getPInvar () {
+		return pInvar;
+ 	}
+
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+		setNewRate();
+	}
+
+	/*.................................................................................................................*/
+	/** returns speficiations*/
+	public String getNexusSpecification() {
+		return "pInvar = " + MesquiteDouble.toString(pInvar);
+	}
+	/*.................................................................................................................*/
+	/** reads parameters from string (same format as written by "toSTring"*/
+	public void fromString(String description, MesquiteInteger stringPos, int format) {
+		ParseUtil.getToken(description, stringPos);
+		ParseUtil.getToken(description, stringPos);
+		String s = ParseUtil.getToken(description, stringPos);
+   		pInvar = MesquiteDouble.fromString(s);
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "pInvar";
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "proportion of characters invariant = "+pInvar;
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesModel.java b/Source/mesquite/genesis/lib/CharRatesModel.java
new file mode 100644
index 0000000..95782eb
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesModel.java
@@ -0,0 +1,93 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import java.util.*;
+
+/** A class that provides for a site-to-site rate variation model. */
+/* ======================================================================== */
+public abstract class CharRatesModel extends ProbSubModel {
+	double siteRate = 1.0;
+	String name = "Name";
+	Class stateClass=CategoricalState.class;
+
+ 	/*.................................................................................................................*/
+	public CharRatesModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+ 	/*.................................................................................................................*/
+	public CharRatesModel () {
+		super("Name", CategoricalState.class);
+	}
+	/** Returns nexus command introducing this model.*/
+	//public String getNEXUSCommand() {
+	//	return "CharRatesModel";
+	//}
+	//public String getTypeName(){
+	//	return "Character rates model";
+	//}
+	public String getCapitalizedTypeName(){
+		return "Character Rates Model";
+	}
+ 	/*.................................................................................................................*/
+	public void initialize() {
+	}
+ 	/*.................................................................................................................*/
+	public void taxaSet() {
+	}
+	/*.................................................................................................................*/
+	public boolean checkValidityCharRates () {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public double getRate (int ic) {
+		if (!checkValidityCharRates())
+			return 1.0;
+		else
+			return siteRate;
+	}
+	/*.................................................................................................................*/
+	public double getRate () {
+		return siteRate;
+	}
+	/*.................................................................................................................*/
+	public void setRate (double newRate) {
+		if (newRate!=MesquiteDouble.unassigned)
+			siteRate = newRate;
+	}
+	/*.................................................................................................................*/
+ 	/*.................................................................................................................*/
+	public abstract void initForNextCharacter();
+ 	/*.................................................................................................................*/
+	public String getExplanation(){
+		return "This specifies the model of rate variation across characters.";
+	}
+ 	/*.................................................................................................................*/
+	public String getParadigm(){
+		return "CharRates";
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "";
+	}
+ 	public String getModelTypeName(){
+		return "Rate variation model";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesModelInfo.java b/Source/mesquite/genesis/lib/CharRatesModelInfo.java
new file mode 100644
index 0000000..9d6bce7
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesModelInfo.java
@@ -0,0 +1,28 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class holding information about a CharRatesModel. */
+/* ======================================================================== */
+public class CharRatesModelInfo extends SubmodelInfo {
+	public CharRatesModelInfo (Class c, String name, String explanation) {
+		super(c, name, explanation);
+ 	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CharRatesModelSet.java b/Source/mesquite/genesis/lib/CharRatesModelSet.java
new file mode 100644
index 0000000..86f1c52
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CharRatesModelSet.java
@@ -0,0 +1,42 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/*======================================================================== */
+/** a ModelSet for probability models. */
+public class CharRatesModelSet  extends ModelSet {
+	
+	public CharRatesModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Character Rates Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CharRatesModelSet ms = new CharRatesModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharRatesModelSet("Rates Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/CompositProbCategModel.java b/Source/mesquite/genesis/lib/CompositProbCategModel.java
new file mode 100644
index 0000000..c8934e9
--- /dev/null
+++ b/Source/mesquite/genesis/lib/CompositProbCategModel.java
@@ -0,0 +1,643 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+import java.util.*;
+
+/* ======================================================================== */
+/** A character model for Categorical characters to be used in stochastic simulations and in likelihood calculations.
+It must serve both for calculating probabilities (via the transitionProbability method) and for simulating character evolution
+(via the evolveState method).*/
+public abstract class CompositProbCategModel  extends ProbabilityCategCharModel {
+	//long allStates = 0L;
+	//protected int[] availableStates;
+	double[] rootStateFrequencies;
+	//protected Random randomNumGen;
+	CategProbModelCurator curator=null;
+	//protected CategoricalData data=null;
+	Taxa taxa = null;
+	double scalingFactor=1.0;
+	boolean notify = true;
+	
+	StateFreqModel rootStatesModel;
+	CharRatesModel charRatesModel;
+	RateMatrixCatModel rateMatrixModel;
+	StateFreqModel equilibriumStatesModel;
+
+	StateFreqModel originalRootStatesModel;
+	CharRatesModel originalCharRatesModel;
+	RateMatrixCatModel originalRateMatrixModel;
+	StateFreqModel originalEquilibriumStatesModel;
+
+	long originalSeed = System.currentTimeMillis();
+	
+	public CompositProbCategModel (String name, Class dataClass, CategProbModelCurator curator) {
+		super(name, dataClass);
+		this.curator = curator;
+ 		//randomNumGen = new Random();
+ 		//initAvailableStates();
+ 		rootStatesModel = initRootStatesModel();
+ 		charRatesModel = initCharRatesModel();
+ 		equilibriumStatesModel = initEquilStatesModel();
+ 		rateMatrixModel = initRateMatrixModel();  // this must be called after initEquilStatesModel, as it depends upon equilibriumStatesModel being set
+ 		
+ 	}
+	public CompositProbCategModel (String name, Class dataClass) {
+		super(name, dataClass);
+ 		randomNumGen = new Random();
+ 		//initAvailableStates();
+ 		rootStatesModel = initRootStatesModel();
+ 		charRatesModel = initCharRatesModel();
+ 		equilibriumStatesModel = initEquilStatesModel();
+ 		rateMatrixModel = initRateMatrixModel();  // this must be called after initEquilStatesModel, as it depends upon equilibriumStatesModel being set
+ 		
+ 	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof CompositProbCategModel))
+			return;
+		
+		CompositProbCategModel pm = (CompositProbCategModel)md;
+		pm.allStates = allStates;
+		//pm.availableStates = IntegerArray.copy(availableStates);
+		pm.rootStateFrequencies = DoubleArray.copy(rootStateFrequencies);
+		pm.curator=curator;
+		pm.taxa = taxa;
+		pm.scalingFactor=scalingFactor;
+		copySubModels(pm);
+		pm.setSeed(originalSeed);
+		super.copyToClone(pm);
+	}
+ 	/*.................................................................................................................*/
+ 	public CategProbModelCurator getCurator() {
+ 		return curator;
+ 	}
+ 	/*.................................................................................................................*/
+ 	public void setCurator(CategProbModelCurator curator) {
+ 		this.curator = curator;
+ 	}
+ 	/*.................................................................................................................*/
+ 	public double getScalingFactor() {
+		return scalingFactor;
+ 	}
+ 	/*.................................................................................................................*/
+ 	public void setScalingFactor(double scale) {
+		scalingFactor = scale;
+ 	}
+	/*.................................................................................................................*/
+	public void copySubModels(CompositProbCategModel model){
+		if (model == null)
+			return;
+		if (getRootStatesModel()!=null)
+			model.setRootStatesModel(getOriginalRootStatesModel()); 
+		if (getEquilStatesModel()!=null)
+			model.setEquilStatesModel(getOriginalEquilStatesModel());
+		if (getCharRatesModel()!=null)
+			model.setCharRatesModel(getOriginalCharRatesModel());
+		if (getRateMatrixModel()!=null)
+			model.setRateMatrixModel(getOriginalRateMatrixModel());
+	}
+	/*.................................................................................................................*/
+	public void initializeSubModels(){
+		rootStatesModel.setCompositProbCategModel(this);
+		equilibriumStatesModel.setCompositProbCategModel(this);
+		charRatesModel.setCompositProbCategModel(this);
+		rateMatrixModel.setCompositProbCategModel(this);
+		
+		setSeed(originalSeed);
+		
+		rootStatesModel.initialize();
+		equilibriumStatesModel.initialize();
+		charRatesModel.initialize();
+		rateMatrixModel.initialize();
+	}
+	/*.................................................................................................................*/
+	public void initializeRootStatesModel(){
+		rootStatesModel.setCompositProbCategModel(this);
+		rootStatesModel.initialize();
+		setSeed(originalSeed);
+	}
+	/*.................................................................................................................*/
+	public void initializeEquilStatesModel(){
+		equilibriumStatesModel.setCompositProbCategModel(this);
+		equilibriumStatesModel.initialize();
+		setSeed(originalSeed);
+	}
+	/*.................................................................................................................*/
+	public void initializeCharRatesModel(){
+		charRatesModel.setCompositProbCategModel(this);
+		charRatesModel.initialize();
+		setSeed(originalSeed);
+	}
+	/*.................................................................................................................*/
+	public void initializeRateMatrixModel(){
+		rateMatrixModel.setCompositProbCategModel(this);
+		rateMatrixModel.initialize();
+		setSeed(originalSeed);
+	}
+	/*.................................................................................................................*/
+	public void setTaxa(Taxa taxa){
+		this.taxa = taxa;
+		
+		if (rootStatesModel !=null)
+			rootStatesModel.taxaSet();
+		if (equilibriumStatesModel !=null)
+			equilibriumStatesModel.taxaSet();
+		if (charRatesModel !=null)
+			charRatesModel.taxaSet();
+		if (rateMatrixModel !=null)
+			rateMatrixModel.taxaSet();
+	}
+	/*.................................................................................................................*/
+	public boolean initialize(String message){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void resetFromOriginalSubmodels(){
+	}
+	/*.................................................................................................................*/
+	public Taxa getTaxa(){
+		return taxa;
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == rootStatesModel || obj == equilibriumStatesModel || obj == charRatesModel || obj == rateMatrixModel) {
+			if (notify) {
+				if (!Notification.appearsCosmetic(notification))
+					notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+			}
+		}
+		else if (obj == originalRootStatesModel || obj == originalEquilibriumStatesModel || obj == originalCharRatesModel || obj == originalRateMatrixModel) {
+			if (notify) {
+				if (!Notification.appearsCosmetic(notification))
+					notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == originalRootStatesModel || obj == originalEquilibriumStatesModel || obj == originalCharRatesModel || obj == originalRateMatrixModel) {
+			if (obj == originalRootStatesModel)
+		 		rootStatesModel = initRootStatesModel();
+			else if (obj == originalEquilibriumStatesModel)
+		 		equilibriumStatesModel = initEquilStatesModel();
+			else if (obj == originalCharRatesModel)
+		 		charRatesModel = initCharRatesModel();
+			else if (obj == originalRateMatrixModel)
+	 			rateMatrixModel = initRateMatrixModel(); 
+			if (notify) {
+				notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+			}
+		}
+		super.disposing(obj);
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public abstract RateMatrixCatModel initRateMatrixModel();
+ 	/*.................................................................................................................*/
+	public abstract StateFreqModel initRootStatesModel();
+ 	/*.................................................................................................................*/
+	public abstract StateFreqModel initEquilStatesModel();
+ 	/*.................................................................................................................*/
+	public abstract CharRatesModel initCharRatesModel() ;
+  	/*.................................................................................................................*/
+	public StateFreqModel getRootStatesModel() {
+		return rootStatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public StateFreqModel getEquilStatesModel() {
+		return equilibriumStatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public CharRatesModel getCharRatesModel() {
+		return charRatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public RateMatrixCatModel getRateMatrixModel() {
+		return rateMatrixModel;
+	}
+  	/*.................................................................................................................*/
+	public StateFreqModel getOriginalRootStatesModel() {
+		return originalRootStatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public StateFreqModel getOriginalEquilStatesModel() {
+		return originalEquilibriumStatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public CharRatesModel getOriginalCharRatesModel() {
+		return originalCharRatesModel;
+	}
+ 	/*.................................................................................................................*/
+	public RateMatrixCatModel getOriginalRateMatrixModel() {
+		return originalRateMatrixModel;
+	}
+	/*.................................................................................................................*/
+	public void dispose() {
+		if (rootStatesModel !=null) {
+			rootStatesModel.dispose(); //NOTE: assumes submodel is a clone of original!
+			rootStatesModel.removeListener(this); 
+		}
+		if (equilibriumStatesModel !=null) {
+			equilibriumStatesModel.dispose(); //NOTE: assumes submodel is a clone of original!
+			equilibriumStatesModel.removeListener(this); 
+		}
+		if (rateMatrixModel !=null){
+			rateMatrixModel.dispose(); //NOTE: assumes submodel is a clone of original!
+			rateMatrixModel.removeListener(this); 
+		}
+		if (charRatesModel !=null){
+			charRatesModel.dispose(); //NOTE: assumes submodel is a clone of original!
+			charRatesModel.removeListener(this); 
+		}
+		//todo: this is temporary until composite listens to its submodel disposal etc.
+		if (getOriginalRootStatesModel() != null)
+			getOriginalRootStatesModel().removeListener(this); 
+		
+		if (getOriginalEquilStatesModel() != null)
+			getOriginalEquilStatesModel().removeListener(this); 
+		
+		if (getOriginalCharRatesModel() != null)
+			getOriginalCharRatesModel().removeListener(this); 
+		
+		if (getOriginalRateMatrixModel() != null)
+			getOriginalRateMatrixModel().removeListener(this); 
+		
+		super.dispose();
+	}
+	/*.................................................................................................................*/
+	public void setRootStatesModel(StateFreqModel model) { //assumes original coming in
+		if (model == null)
+			return;
+		if (originalRootStatesModel !=null)
+			originalRootStatesModel.removeListener(this);
+		originalRootStatesModel = model;
+		if (originalRootStatesModel !=null)
+			originalRootStatesModel.addListener(this);
+		if (rootStatesModel !=null) {
+			rootStatesModel.removeListener(this);
+			rootStatesModel.dispose(); //Assumes submodel had been cloned locally && thus we're in charge of it
+		}
+		rootStatesModel = (StateFreqModel)model.cloneModelWithMotherLink(rootStatesModel);
+		if (rootStatesModel !=null) {
+			rootStatesModel.addListener(this);
+			rootStatesModel.setCompositProbCategModel(this);
+		}
+	}
+ 	/*.................................................................................................................*/
+	public void setEquilStatesModel(StateFreqModel model) {
+		if (model == null)
+			return;
+		if (originalEquilibriumStatesModel !=null)
+			originalEquilibriumStatesModel.removeListener(this);
+		originalEquilibriumStatesModel = model;
+		if (originalEquilibriumStatesModel !=null)
+			originalEquilibriumStatesModel.addListener(this);
+
+		if (equilibriumStatesModel !=null) {
+			equilibriumStatesModel.removeListener(this);
+			equilibriumStatesModel.dispose(); //Assumes submodel had been cloned locally && thus we're in charge of it
+		}
+		equilibriumStatesModel = (StateFreqModel)model.cloneModelWithMotherLink(equilibriumStatesModel);
+		if (equilibriumStatesModel !=null) {
+			equilibriumStatesModel.addListener(this);
+			equilibriumStatesModel.setCompositProbCategModel(this);
+		}
+	}
+ 	/*.................................................................................................................*/
+	public void setCharRatesModel(CharRatesModel model) {
+		if (model == null)
+			return;
+		if (originalCharRatesModel !=null)
+			originalCharRatesModel.removeListener(this);
+		originalCharRatesModel = model;
+		if (originalCharRatesModel !=null)
+			originalCharRatesModel.addListener(this);
+		if (charRatesModel !=null) {
+			charRatesModel.removeListener(this);
+			charRatesModel.dispose(); //Assumes submodel had been cloned locally && thus we're in charge of it
+		}
+		charRatesModel = (CharRatesModel)model.cloneModelWithMotherLink(charRatesModel);
+		if (charRatesModel !=null) {
+			charRatesModel.addListener(this);
+			charRatesModel.setCompositProbCategModel(this);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setRateMatrixModel(RateMatrixCatModel model) {
+		if (model == null)
+			return;
+		if (originalRateMatrixModel !=null)
+			originalRateMatrixModel.removeListener(this);
+		originalRateMatrixModel = model;
+		if (originalRateMatrixModel !=null)
+			originalRateMatrixModel.addListener(this);
+
+		if (rateMatrixModel !=null) {
+			rateMatrixModel.removeListener(this);
+			rateMatrixModel.dispose(); //Assumes submodel had been cloned locally && thus we're in charge of it
+		}
+		rateMatrixModel =  (RateMatrixCatModel)model.cloneModelWithMotherLink(rateMatrixModel);
+		if (rateMatrixModel !=null) {
+			rateMatrixModel.addListener(this);
+			rateMatrixModel.setCompositProbCategModel(this);
+		}
+	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified() {
+		if (rateMatrixModel==null || !rateMatrixModel.isFullySpecified())
+			return false;
+		if (rootStatesModel==null || !rootStatesModel.isFullySpecified())
+			return false;
+		if (equilibriumStatesModel==null || !equilibriumStatesModel.isFullySpecified())
+			return false;
+		if (charRatesModel==null || !charRatesModel.isFullySpecified())
+			return false;
+		return true;
+	}
+	public int getMaximumNumChars(){
+		return MesquiteInteger.infinite; //here put smaller number if empirical matrix is constraint
+	}
+	/*.................................................................................................................*
+	public abstract void initAvailableStates();
+	/*.................................................................................................................*/
+	/** Returns natural log of the transition probability from beginning to ending state in the given tree on the given node*/
+	public double transitionLnProbability (int beginState, int endState, Tree tree, int node){
+		return Math.log(transitionProbability(beginState, endState, tree, node));
+	}
+	/*.................................................................................................................*/
+	/** Returns transition probability from beginning to ending state in the given tree on the given node*/
+	public double transitionProbability (int beginState, int endState, Tree tree, int node){
+		if (rateMatrixModel==null) //added 21 mar 02
+			return 0;
+		return rateMatrixModel.transitionProbability(beginState,endState,tree,node);
+	}
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	/*.................................................................................................................*/
+	public void evolveState (CharacterState beginState, CharacterState endState, Tree tree, int node){
+		if (endState==null) {
+			return;
+		}
+		if (beginState==null || !(beginState instanceof CategoricalState) || !(endState instanceof CategoricalState)){
+			endState.setToUnassigned();
+			return;
+		}
+		CategoricalState bState = (CategoricalState)beginState;
+		CategoricalState eState = (CategoricalState)endState;
+		int r = evolveState(CategoricalState.minimum(bState.getValue()), tree, node);
+		eState.setValue(CategoricalState.makeSet(r));
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	public int evolveState (int beginState, Tree tree, int node) {
+		if (rateMatrixModel==null)
+			return -1;
+		return rateMatrixModel.evolveState(beginState,tree,node);
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public long getRootState (Tree tree){
+		if (rootStatesModel==null)
+			return CategoricalState.unassigned;
+		if (tree == null)
+			return rootStatesModel.getState( tree, 0);
+		else
+			return rootStatesModel.getState( tree, tree.getRoot());
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public double getRootStateFreq (int state, Tree tree){
+		if (rootStatesModel==null)
+			return 0;
+		if (tree == null)
+			return rootStatesModel.getStateFreq(state, tree, 0);
+		else
+			return rootStatesModel.getStateFreq(state, tree, tree.getRoot());
+		
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public CharacterState getRootState (CharacterState state, Tree tree){
+		if (state==null || !(state instanceof CategoricalState))
+			state = new CategoricalState();
+		((CategoricalState)state).setValue(getRootState(tree));
+		return state;
+	}
+	/*.................................................................................................................*/
+	/** returns prior probabilities for states (e.g., state frequencies)*
+	public abstract double priorProbability (int state);
+	
+ 	/*.................................................................................................................*/
+	public boolean isFirstCharacter() {
+		int ic = -1;
+		if (getCharacterDistribution()!=null)
+			ic = getCharacterDistribution().getParentCharacter();
+		return (ic==0);
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		originalSeed = seed;
+		randomNumGen.setSeed(seed);
+		if (rootStatesModel !=null)
+			rootStatesModel.setSeed(randomNumGen.nextLong());
+		if (equilibriumStatesModel !=null)
+			equilibriumStatesModel.setSeed(randomNumGen.nextLong());
+		if (charRatesModel !=null)
+			charRatesModel.setSeed(randomNumGen.nextLong());
+		if (rateMatrixModel !=null)
+			rateMatrixModel.setSeed(randomNumGen.nextLong());
+	}
+ 	/*.................................................................................................................*/
+	public long getSeed(){
+		return randomNumGen.nextLong();
+	}
+ 	/*.................................................................................................................*
+	public boolean inStates(int state) { //todo: these should be part of standard categ models
+		if (availableStates==null)
+			return false;
+		else {
+			for (int i=0; i<availableStates.length; i++)
+				if (state == availableStates[i])
+					return true;
+			return false;
+		}
+	}
+ 	/*.................................................................................................................*
+	public void setStatesSimulatable(long stateSet) {  //todo: this should check to see that not already seen!
+		if (CategoricalState.cardinality(stateSet)>1) {
+			availableStates = CategoricalState.expand(stateSet);
+			allStates = stateSet;
+		}
+	}
+	/*.................................................................................................................*
+	/** Returns the maximum state available for transitions*
+	public int getMaxState() {
+		int max = -1;
+		for (int i=0; i<availableStates.length; i++)
+			if (max < availableStates[i]) max=availableStates[i];
+		return max;
+	}
+ 	/*.................................................................................................................*/
+	public void addOptionsOnCards(ExtensibleDialog dialog) {
+		/*
+		TabbedPanelOfCards cardPanels = dialog.addTabbedPanelOfCards("Tabbed Panel");
+		if (rateMatrixModel!=null) {
+			cardPanels.newCard("Rate Matrix", "Rate Matrix", "ratematrixtab.gif", "ratematrixtabOff.gif");
+			rateMatrixModel.addModelOptions(dialog);
+		}
+		if (rootStatesModel!=null) {
+			cardPanels.newCard("Root States", "Root States", "rootstatestab.gif", "rootstatestabOff.gif");
+			rootStatesModel.addModelOptions(dialog);
+		}
+		if (equilibriumStatesModel!=null) {
+			cardPanels.newCard("Equilibrium States", "Equilibrium States","equilstatestab.gif", "equilstatestabOff.gif");
+			equilibriumStatesModel.addModelOptions(dialog);
+		}
+		if (charRatesModel!=null) {
+			cardPanels.newCard("Site-to-site Rate Variation", "Site-To-Site","sitetositetab.gif","sitetositetabOff.gif");
+			charRatesModel.addModelOptions(dialog);
+		}
+		cardPanels.finalizeCards();
+	*/
+	}
+ 	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		if (rateMatrixModel!=null) 
+			rateMatrixModel.addOptions(dialog);
+		if (rootStatesModel!=null) 
+			rootStatesModel.addOptions(dialog);
+		if (equilibriumStatesModel!=null) 
+			equilibriumStatesModel.addOptions(dialog);
+		if (charRatesModel!=null) 
+			charRatesModel.addOptions(dialog);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		boolean optionsRecovered = true;
+		if (rateMatrixModel!=null)
+			optionsRecovered = rateMatrixModel.recoverOptions();
+		if (rootStatesModel!=null)
+			if (optionsRecovered)
+				optionsRecovered = rootStatesModel.recoverOptions();
+			else
+				rootStatesModel.recoverOptions();
+		if (equilibriumStatesModel!=null)
+			if (optionsRecovered)
+				optionsRecovered = equilibriumStatesModel.recoverOptions();
+			else
+				equilibriumStatesModel.recoverOptions();
+		if (charRatesModel!=null)
+			if (optionsRecovered)
+				optionsRecovered = charRatesModel.recoverOptions();
+			else
+				charRatesModel.recoverOptions();
+		return optionsRecovered;
+	}
+  	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		boolean optionsChecked = true;
+		if (rateMatrixModel!=null)
+			optionsChecked = rateMatrixModel.checkOptions();
+		if (rootStatesModel!=null)
+			if (optionsChecked)
+				optionsChecked=rootStatesModel.checkOptions();
+			else
+				rootStatesModel.checkOptions();
+		if (equilibriumStatesModel!=null)
+			if (optionsChecked)
+				optionsChecked=equilibriumStatesModel.checkOptions();
+			else
+				equilibriumStatesModel.checkOptions();
+		if (charRatesModel!=null)
+			if (optionsChecked)
+				optionsChecked=charRatesModel.checkOptions();
+			else
+				charRatesModel.checkOptions();
+		return optionsChecked;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		String s;
+		if (rateMatrixModel!=null) {
+			 s = rateMatrixModel.checkOptionsReport();
+			 if (!StringUtil.blank(s))
+			 	return s;
+		}
+		if (rootStatesModel!=null) {
+			s = rootStatesModel.checkOptionsReport();
+			 if (!StringUtil.blank(s))
+			 	return s;
+		}
+		if (equilibriumStatesModel!=null) {
+			s = equilibriumStatesModel.checkOptionsReport();
+			 if (!StringUtil.blank(s))
+			 	return s;
+		}
+		if (charRatesModel!=null) {
+			s = charRatesModel.checkOptionsReport();
+			 if (!StringUtil.blank(s))
+			 	return s;
+		}
+		return "";
+	}
+	/*.................................................................................................................*/
+	public void setOptions() {
+		if (rateMatrixModel!=null) 
+			rateMatrixModel.setOptions();
+		if (rootStatesModel!=null) 
+			rootStatesModel.setOptions();
+		if (equilibriumStatesModel!=null)
+			equilibriumStatesModel.setOptions();
+		if (charRatesModel!=null)
+			charRatesModel.setOptions();
+	}
+ 	/*.................................................................................................................*/
+	public void queryModelOptions(String message, boolean useCardLayout) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message,buttonPressed);
+		dialog.addLabel(message);
+		if (useCardLayout)
+			addOptionsOnCards(dialog);
+		else
+			addOptions(dialog);
+		dialog.completeAndShowDialog(true);
+		recoverOptions();
+		dialog.dispose();
+		if (buttonPressed.getValue()==0)  {
+			setOptions();
+			setEditCancel(false);
+		}
+		else
+			setEditCancel(true);
+	}
+ 	/*.................................................................................................................*/
+	public void queryModelOptions(String message) {
+		queryModelOptions(message, false);
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/ProbSubModel.java b/Source/mesquite/genesis/lib/ProbSubModel.java
new file mode 100644
index 0000000..e6ca9c5
--- /dev/null
+++ b/Source/mesquite/genesis/lib/ProbSubModel.java
@@ -0,0 +1,110 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides for a site-to-site rate variation model. */
+/* ======================================================================== */
+public abstract class ProbSubModel extends CharacterSubmodel {
+	CompositProbCategModel probabilityModel;
+	int defaultNumChars = 0;
+
+	private CharacterStatesHolder charDistribution = null;
+	private MCharactersStatesHolder charMatrix = null;
+
+ 	/*.................................................................................................................*/
+	public ProbSubModel (String name, Class stateClass) {
+		super(name,stateClass);
+	}
+ 	/*.................................................................................................................*/
+	public abstract void initialize();
+ 	/*.................................................................................................................*/
+	public int getDefaultNumChars(){
+		return defaultNumChars;
+	}
+ 	/*.................................................................................................................*/
+	public void setDefaultNumChars(int numChars){
+		defaultNumChars = numChars;
+	}
+ 	/*.................................................................................................................*/
+	public abstract void taxaSet() ;
+ 	/*.................................................................................................................*/
+	public void setCompositProbCategModel (CompositProbCategModel probabilityModel) {
+		this.probabilityModel = probabilityModel;
+	}
+ 	/*.................................................................................................................*/
+	public boolean isLineageSpecific(){
+		return false;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return true if submodel needs an empirical matrix*/
+	public boolean needsEmpirical(){
+		return false;
+	}
+ 	/*.................................................................................................................*/
+	public void addModelOptions(ExtensibleDialog dialog) {
+		//PopUpPanelOfCards cardPanels = dialog.addPopUpPanelOfCards();
+
+		addOptions(dialog);
+		//cardPanels.finalizeCards();
+	}
+	/*.................................................................................................................*/
+	public abstract CharacterModel cloneModelWithMotherLink(CharacterModel formerClone);
+  	/*.................................................................................................................*/
+	public void recoverModelOptions() {
+		recoverOptions();
+	}
+	/*.................................................................................................................*/
+	public abstract void addOptions(ExtensibleDialog dialog);
+ 	/*.................................................................................................................*/
+	public abstract boolean recoverOptions();
+ 	/*.................................................................................................................*/
+	public abstract boolean checkOptions();
+ 	/*.................................................................................................................*/
+	public abstract String checkOptionsReport();
+ 	/*.................................................................................................................*/
+	public abstract void setOptions();
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+	}
+	/** Returns whether parameters of model are fully specified.  If so, it can be used for evolving states.*/
+	public abstract boolean isFullySpecified();
+	
+	/** Sets the character distribution or history to which this model is currently applying */
+	public void setCharacterDistribution (CharacterStatesHolder cd){
+		charDistribution = cd;
+	}
+	public CharacterStatesHolder getCharacterDistribution (){
+		return charDistribution;
+	}
+	/** To be overridden if processing needs to happen after CharMatrix is set */
+	public void recalcAfterSetMCharactersStatesHolder (){
+	}
+	/** Sets the character matrix or  history to which this model is currently applying */
+	public void setMCharactersStatesHolder (MCharactersStatesHolder cd){
+		charMatrix = cd;
+		recalcAfterSetMCharactersStatesHolder();
+	}
+	public MCharactersStatesHolder getMCharactersStatesHolder (){
+		return charMatrix;
+	}
+	public String toString(){
+		return super.toString() + "; Fully specified: " + isFullySpecified();
+	}
+ }
+
diff --git a/Source/mesquite/genesis/lib/ProbSubModelCurator.java b/Source/mesquite/genesis/lib/ProbSubModelCurator.java
new file mode 100644
index 0000000..581caa6
--- /dev/null
+++ b/Source/mesquite/genesis/lib/ProbSubModelCurator.java
@@ -0,0 +1,106 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class ProbSubModelCurator extends CharSubmodelCurator implements ActionListener  {
+	boolean exitLoop=false;
+	ExtensibleDialog dialog;
+	ProbSubModel model;
+	MesquiteInteger buttonPressed;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	public MesquiteModule showEditor(CharacterModel model){
+ 		if (model == null) 
+			return null;
+		this.model = (ProbSubModel)model;
+		buttonPressed = new MesquiteInteger(1);
+		dialog = new ExtensibleDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(),getName(),buttonPressed);
+		dialog.addStackedLabels(getName(),"\"" + (((ProbSubModel)model).getName()) + "\"",2);
+		dialog.setAutoDispose(false);
+		if (!StringUtil.blank(getHelpString())){
+			dialog.appendToHelpString(getHelpString());
+		}
+		if (!StringUtil.blank(getHelpURL())){
+			dialog.setHelpURL(getHelpURL());
+		}
+		
+		((ProbSubModel)model).addOptions(dialog);
+		dialog.completeAndShowDialog(true,this);
+		((ProbSubModel)model).recoverOptions();
+		if (dialog!=null)
+			dialog.dispose();
+		if (buttonPressed.getValue()==0) {
+			((ProbSubModel)model).setOptions();
+			model.setEditCancel(false);
+		}
+		else
+			model.setEditCancel(true);
+		return this;
+   	}
+   	
+	/*.................................................................................................................*/
+	 public  String getHelpString() {
+	 	return "";
+	 }   	
+	/*.................................................................................................................*/
+	 public  String getHelpURL() {
+	 	return "";
+	 }
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	if   (e.getActionCommand() == "OK") {
+	 		if ((model==null)||model.checkOptions()) {
+	 			buttonPressed.setValue(0);
+	 			dialog.dispose();
+	 			dialog=null;
+	 		}
+	 		else
+	 			alert(model.checkOptionsReport());
+	 	}
+	 	else if   (e.getActionCommand() == "Apply") {
+	 		if ((model==null)||model.checkOptions()) {
+	 			((ProbSubModel)model).setOptions();
+	 			Button cancelButton = dialog.getCancelButton();
+	 			if (cancelButton!=null)
+	 				cancelButton.setEnabled(false);
+	 		}
+	 		else
+	 			alert(model.checkOptionsReport());
+	 	}
+	 	else {
+	 		buttonPressed.setValue(1);
+	 		dialog.dispose();
+	 		dialog=null;
+	 	}
+	 }
+
+
+}
+
+
diff --git a/Source/mesquite/genesis/lib/ProbabilityDNAModel.java b/Source/mesquite/genesis/lib/ProbabilityDNAModel.java
new file mode 100644
index 0000000..d098085
--- /dev/null
+++ b/Source/mesquite/genesis/lib/ProbabilityDNAModel.java
@@ -0,0 +1,59 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+public abstract class ProbabilityDNAModel extends CompositProbCategModel {
+	
+ 	/*.................................................................................................................*/
+	public ProbabilityDNAModel (String name, Class dataClass, CategProbModelCurator curator){
+		super(name, dataClass, curator);
+		maxStateDefined = 3;
+		maxState = 3;
+ 	}
+	
+ 	/*.................................................................................................................*
+	public void initAvailableStates() {
+		availableStates = new int[4];
+		for (int i=0; i<4; i++)
+			availableStates[i]=i;
+	}
+ 	/*.................................................................................................................*
+	public void setStates(long allStates, CharacterDistribution cStates) { 
+	//This expansion costs a lot of time.  Perhaps use allStates based calculations instead of states[] based calculations?
+		if (!(DNAState.class.isAssignableFrom(cStates.getStateClass()))) {
+			this.availableStates = CategoricalState.expand(allStates);
+			if (availableStates.length <= 1) {
+				int state = availableStates[0];
+				availableStates = new int[2];
+				availableStates[0] = state;
+				if (availableStates[0]==1)
+					availableStates[1] = 0;
+				else
+					availableStates[1]=1;
+			}
+		}
+		else 
+			initAvailableStates();
+		allStates = CategoricalState.compressFromList(availableStates);
+	}*/
+}
+
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixCatModel.java b/Source/mesquite/genesis/lib/RateMatrixCatModel.java
new file mode 100644
index 0000000..5ad22cc
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixCatModel.java
@@ -0,0 +1,239 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides root states for probabilistic models, using frequencies for the root states. 
+This class must be subclassed, with the method setStateProbabilities specified. */
+/* ======================================================================== */
+public abstract class RateMatrixCatModel  extends ProbSubModel{
+	long allStates = 0L;
+	int[] availableStates;
+	int numStates;
+	CharRatesModel charRatesModel;
+	private double[][] fullRateMatrix = null;
+	
+	/*These probability matrices are numStates X numStates X numNodes, so as to maintain a separate
+	probability matrix at each node of the tree.  This is done to help minimize recalculations of probability matrices,
+	allowing a separate matrix to be stored at each node. (Note: where there is rate variation, this will help but be of less importance, since
+	other archiving systems like that in GTR model will become more important. */
+	private double[][][] changeProbabilities = null;
+	private double[][][] cumChangeProbabilities = null;
+	//private double[] rateParameters = null;
+	protected Random randomNumber;
+	
+
+	public RateMatrixCatModel (CompositProbCategModel probabilityModel, int numStates, Class stateClass) {
+		super (null, stateClass);
+		this.numStates = numStates;
+ 		fullRateMatrix = new double[numStates][numStates];
+ 		changeProbabilities = new double[numStates][numStates][1];
+ 		cumChangeProbabilities = new double[numStates][numStates][1];
+ 		randomNumber = new Random();
+ 		initAvailableStates();
+ 		zeroChangeProbabilities();
+ 		this.probabilityModel = probabilityModel;
+		
+ 		//setChangeProbabilities(branchlength);
+ 	}
+ 	/*.................................................................................................................*/
+	public void initialize() {
+	}
+ 	/*.................................................................................................................*/
+	public void taxaSet() {
+	}
+ 	public String getExplanation(){
+ 		return "Rate matrix model";
+ 	}
+ 	public String getParadigm(){
+ 		return "CharRateMatrices";
+ 	}
+	/** Returns nexus command introducing this model.*/
+//	public String getNEXUSCommand() {
+//		return "CharRateMatrix";
+//	}
+	/*.................................................................................................................*/
+	public abstract void initAvailableStates ();
+ 	/*.................................................................................................................*/
+	//public abstract CharacterModel cloneModelWithMotherLink(CharacterModel formerClone);
+  	/*.................................................................................................................*/
+	/** Sets the equilibrium change frequencies in the model. Must be specified by the subclass. */
+	protected abstract void setChangeProbabilities (double branchlength, Tree tree, int node); 
+	/*.................................................................................................................*/
+	public double getChangeProbability (int stateFrom, int stateTo, int node){
+		if (stateFrom<changeProbabilities.length && stateTo < changeProbabilities[stateFrom].length && changeProbabilities[stateFrom][stateTo]!=null && node < changeProbabilities[stateFrom][stateTo].length)
+			return changeProbabilities[stateFrom][stateTo][node];
+		else
+			return 0.0;
+	}
+	/*.................................................................................................................*/
+	public void setCharRatesModel (CharRatesModel charRatesModel){
+		this.charRatesModel = charRatesModel;
+	}
+	/*.................................................................................................................*/
+	public CharRatesModel getCharRatesModel (){
+		return charRatesModel;
+	}
+	/*.................................................................................................................*/
+	public double getStateFreq (int state, Tree tree, int node){
+		return probabilityModel.getEquilStatesModel().getStateFreq(state, tree, node);
+	}
+	/*.................................................................................................................*/
+	public int getNumStates (){
+		return numStates;
+	}
+	/*.................................................................................................................*/
+	/** Sets the state frequencies to zero.*/
+	public void zeroChangeProbabilities (){
+		for (int i=0; i<numStates; i++) 
+			for (int j=0; j<numStates; j++) 
+				for (int node =0; node<changeProbabilities[i][j].length; node++)
+					changeProbabilities[i][j][node] = 0.0;
+	}
+	/*.................................................................................................................*/
+	public void setChangeProbability (int stateFrom, int stateTo, int node, double freq){
+		if (stateFrom<changeProbabilities.length && stateTo < changeProbabilities[stateFrom].length && changeProbabilities[stateFrom][stateTo]!=null && node < changeProbabilities[stateFrom][stateTo].length){
+			changeProbabilities[stateFrom][stateTo][node] = freq;
+			calcCumChangeProbability(node);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Calculates the cumulative change frequencies.*/
+	public void calcCumChangeProbability (int node){
+		for (int i=0; i<numStates; i++)  {
+			double accumProb = 0;
+			for (int j=0; j<numStates; j++) {
+				accumProb +=  changeProbabilities[i][j][node];
+				cumChangeProbabilities[i][j][node] = accumProb;
+			}
+		}
+	}
+	
+	/*.................................................................................................................*/
+//	public abstract double[][] getProbabilityMatrix (double branchLength);
+
+
+	/** Checks to see that the node-by-node storage of change probabilities is big enough for tree;
+	if not, makes newer bigger ones and invalidates probabilities to require them to be calculated again */
+	private void checkMatrixSizes(Tree tree){
+		if (changeProbabilities[0][0].length<tree.getNumNodeSpaces()) {
+	 		changeProbabilities = new double[numStates][numStates][tree.getNumNodeSpaces()];
+	 		cumChangeProbabilities = new double[numStates][numStates][tree.getNumNodeSpaces()];
+	 		invalidateProbabilitiesAtNodes();
+		}
+			
+	}
+	public abstract void invalidateProbabilitiesAtNodes();
+ 	/*.................................................................................................................*/
+	public int evolveState (int beginState, Tree tree, int node) {
+		double r = randomNumber.nextDouble();
+		checkMatrixSizes(tree);
+		setChangeProbabilities(tree.getBranchLength(node, 1.0)*probabilityModel.getScalingFactor()*probabilityModel.getCharRatesModel().getRate(), tree, node);
+		checkProbabilitySums(node);
+
+		double accumProb = 0.0;
+		
+		for (int i=0; i<availableStates.length; i++) {
+			accumProb += changeProbabilities[beginState][i][node];
+			if (r< accumProb) {
+				return availableStates[i];
+			}
+		}
+		return availableStates[availableStates.length-1];
+
+	}
+	private void checkProbabilitySums(int node){
+	
+		double accumProb = 0.0;
+		for (int i=0; i<availableStates.length; i++) {
+			for (int j=0; j<availableStates.length;j++) {
+				accumProb += changeProbabilities[i][j][node];
+			}
+		}
+		double deviation = Math.abs(accumProb - availableStates.length);
+		if (deviation > 0.01)
+			MesquiteMessage.warnProgrammer("probability matrix rows don't add up to 1 " + deviation + " (model : " + getName() + ")");
+	}
+ 	/*.................................................................................................................*/
+	public double transitionProbability (int beginState, int endState, Tree tree, int node){
+		if (!inStates(beginState) || !inStates(endState)) {
+			return 0;
+		}
+		else {
+			checkMatrixSizes(tree);
+			setChangeProbabilities(tree.getBranchLength(node, 1.0)*probabilityModel.getCharRatesModel().getRate(),  tree,  node);
+			checkProbabilitySums(node);
+			if (beginState == endState) {
+				if (availableStates.length == 1)
+					return 1.0;
+				else
+					return changeProbabilities[beginState][endState][node];
+			}
+			else {
+				return changeProbabilities[beginState][endState][node];
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Given a random number between 0 and 1, returns the state value.*/
+	public long getRandomState (int stateFrom, double randomDouble, int node){
+		if (availableStates.length == 1)
+			return (allStates);  
+		else {
+			for (int j=0; j<numStates; j++)
+				if (randomDouble< cumChangeProbabilities[stateFrom][j][node])
+					return CategoricalState.makeSet(availableStates[j]);
+			return CategoricalState.makeSet(numStates-1);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates according to model a state.*/
+	public long getRandomState (int stateFrom, int node){
+		double r = randomNumber.nextDouble();
+		return getRandomState(stateFrom, r, node);
+	}
+ 	/*.................................................................................................................*/
+	public boolean inStates(int state) { //todo: these should be part of standard categ models
+		if (availableStates==null)
+			return false;
+		else {
+			for (int i=0; i<availableStates.length; i++)
+				if (state == availableStates[i])
+					return true;
+			return false;
+		}
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+ 	/*.................................................................................................................*/
+	public long getSeed(){
+		return randomNumber.nextLong();
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "";
+	}
+	public String getModelTypeName(){
+		return "Rate matrix model";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixCatModelInfo.java b/Source/mesquite/genesis/lib/RateMatrixCatModelInfo.java
new file mode 100644
index 0000000..f320a4f
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixCatModelInfo.java
@@ -0,0 +1,28 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class holding information about a RateMatrixCatModel. */
+/* ======================================================================== */
+public class RateMatrixCatModelInfo extends SubmodelInfo {
+	public RateMatrixCatModelInfo (Class c, String name, String explanation) {
+		super(c, name, explanation);
+ 	}
+}
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixCurator.java b/Source/mesquite/genesis/lib/RateMatrixCurator.java
new file mode 100644
index 0000000..0010f5a
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixCurator.java
@@ -0,0 +1,33 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class RateMatrixCurator extends ProbSubModelCurator  {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+}
+
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixDNAModel.java b/Source/mesquite/genesis/lib/RateMatrixDNAModel.java
new file mode 100644
index 0000000..908fb31
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixDNAModel.java
@@ -0,0 +1,92 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides root states for probabilistic models, using frequencies for the root states. 
+This class must be subclassed, with the method setStateProbabilities specified. */
+/* ======================================================================== */
+public abstract class RateMatrixDNAModel extends RateMatrixCatModel {
+
+	public RateMatrixDNAModel (CompositProbCategModel probabilityModel) {
+		super(probabilityModel,4, DNAState.class);
+ 	}
+ 	/*.................................................................................................................*/
+ 	/* Archiving system:  To speed calculations, an archive of up to 6 probability matrices can be stored at each
+ 	node.  When a calculation is requested, these matrices are perused to see if one is applicable at the node.  It is judged
+ 	applicable if the matrix had been calculated using the same branch length as before, as long as something hasn't invalidated
+ 	the matrices (this happens if the eigenvalues etc. are recalculated, or if the tree changes size).  Typically a node will
+ 	have different branch lengths in different calculations because different characters have different rates of change.  6 was chosen
+ 	as a reasonable number of recent matrices, because a discrete gamma will usually have 4 categories of character rates and
+ 	a codon position specific rates model will have 5 categories (N1243-).
+ 	
+ 	This full archiving system is built as an addition to the service provided by  RateMatrixCatModel to store probability matrices at each node.
+ 	*/
+	static final int maxArchivePlaces = 7;
+	
+	/* the archive of probability matrices.  Size is numNodes X maxArchivePlaces X num elements in prob matrix + 1.
+	Thus, stores at each node, maxArchivePlaces matrices, each of which has enough spaces for the probabilty matrix plus an extra space.
+	The extra space (element 0) is reserved for the branch length under which the matrix was calculated. */
+	double[][][] archivedProbabilities;
+	double[] previousBranchLengths;
+	
+	/** check to see that archives and prevoius branch length records still big enough for tree */
+	protected void checkMatrixSizes(Tree tree){
+		if (previousBranchLengths==null || previousBranchLengths.length<tree.getNumNodeSpaces()) {
+	 		previousBranchLengths = new double[tree.getNumNodeSpaces()];
+	 		archivedProbabilities = new double[tree.getNumNodeSpaces()][maxArchivePlaces][getNumStates()*getNumStates()+1]; //+1 to store length
+	 		invalidateProbabilitiesAtNodes();
+		}
+	}
+	/** Mark archives as invalid. */
+ 	public void invalidateProbabilitiesAtNodes(){
+ 		if (previousBranchLengths != null)
+ 			for (int i=0; i<previousBranchLengths.length; i++){
+ 				previousBranchLengths[i] = -1; //no previous branch length
+ 				for (int j=0; j< maxArchivePlaces; j++)
+ 					archivedProbabilities[i][j][0] = MesquiteDouble.unassigned;  //archive space is open
+ 			}
+ 	}
+	/** Find an archive spot that is open at the node.  Recall from above that element 0 of the prob matrix is actually the branch length.
+	Find a branch length marked as unassigned; this is the signal that the matrix is open for use.*/
+ 	protected int findOpenArchive(int node){
+		if (archivedProbabilities==null)
+			return -1;
+		for (int i=0; i<maxArchivePlaces; i++)
+			if (archivedProbabilities[node][i][0] == MesquiteDouble.unassigned)
+				return i;
+		return 0;
+ 	}
+	/** Find an archive spot with given branch length at the node.  Recall from above that element 0 of the prob matrix is actually the branch length.
+	Find a branch length same as that passed; this will indicate that matrix can be re-used.*/
+ 	protected int findMatchingArchive(int node, double branchLength){
+		if (archivedProbabilities==null || branchLength == MesquiteDouble.unassigned)
+			return -1;
+		for (int i=0; i<maxArchivePlaces; i++)
+			if (archivedProbabilities[node][i][0] == branchLength)
+				return i;
+		return -1;
+ 	}
+ 	/*.................................................................................................................*/
+	public void initAvailableStates() {
+		availableStates = new int[4];
+		for (int i=0; i<4; i++)
+			availableStates[i]=i;
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixEqualDNAModel.java b/Source/mesquite/genesis/lib/RateMatrixEqualDNAModel.java
new file mode 100644
index 0000000..eda1a90
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixEqualDNAModel.java
@@ -0,0 +1,90 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class RateMatrixEqualDNAModel extends RateMatrixDNAModel {
+	double instantaneous = 1.0;
+
+	public RateMatrixEqualDNAModel (CompositProbCategModel probabilityModel) {
+		super(probabilityModel);
+	}
+	/*.................................................................................................................*/
+	public String getNexusSpecification(){
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public  CharacterModel cloneModelWithMotherLink(CharacterModel formerClone) {
+		RateMatrixEqualDNAModel model = new RateMatrixEqualDNAModel(probabilityModel);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/*.................................................................................................................*/
+ 	public void invalidateProbabilitiesAtNodes(){
+ 	}
+  	/*.................................................................................................................*/
+	protected void setChangeProbabilities (double branchLength, Tree tree, int node) {
+		double probChangeBase =Math.exp(-instantaneous*branchLength);
+		double probChange;
+		for (int i=0; i<4; i++)
+			for (int j=0; j<4; j++) {
+				if (i!=j)
+					probChange = getStateFreq(j, tree, node) * (1- probChangeBase);
+				else
+					probChange = getStateFreq(j, tree, node) + (1 -getStateFreq(j, tree, node)) * probChangeBase;
+				setChangeProbability(i,j, node, probChange);	
+			}
+	}
+	public boolean isFullySpecified(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+			return true;
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {}
+ 	/*.................................................................................................................*/
+ 	/*.................................................................................................................*/
+	/** returns name of model*/
+	public String getName() {
+		return "Single Rate";
+	}
+ 	/*.................................................................................................................*/
+	/** returns name of model*/
+	public String getNEXUSName() {
+		return "singleRate";
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "single rate";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixGTRModel.java b/Source/mesquite/genesis/lib/RateMatrixGTRModel.java
new file mode 100644
index 0000000..c06e0e3
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixGTRModel.java
@@ -0,0 +1,274 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import pal.substmodel.*;
+
+
+/** A class that provides a General Time Reversible rate matrix. */
+/* ======================================================================== */
+public class RateMatrixGTRModel extends RateMatrixDNAModel {
+	double[][] rateMatrix;
+	double[][] rateMatrixTemp;
+	TransitionProbability transProbs = null;
+	boolean hasDefaultValues = true;
+	GTR palGTR;
+	String errorMessage="";
+
+	boolean matricesSet = false;
+	DoubleSqMatrixFields rateMatrixField;
+
+	public RateMatrixGTRModel (CompositProbCategModel probabilityModel, double[][] rateMatrix) {
+		super(probabilityModel);
+		this.rateMatrix = rateMatrix;
+		initRateMatrix();
+ 	}
+	public RateMatrixGTRModel () {
+		super(null);
+		rateMatrix = new double[4][4];
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = 0; j<getNumStates(); j++)
+				rateMatrix[i][j] =MesquiteDouble.unassigned;
+		rateMatrix[2][3] = 1.0;
+		initRateMatrix();
+ 	}
+ 	/*.................................................................................................................*/
+ 	void initRateMatrix() {
+		//eigenVectorsWrapper = new DoubleVector[getNumStates()];
+		int nStates = getNumStates();
+		rateMatrixTemp = new double[nStates][nStates];
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = 0; j<getNumStates(); j++)
+				rateMatrixTemp[i][j] = MesquiteDouble.unassigned;
+
+				
+ 	}
+	 /*.................................................................................................................*/
+	void copyUpperRightToLowerLeft(double[][] matrix) {
+		for (int i = 1; i<getNumStates(); i++) 
+			for (int j = 0; j<i; j++) 
+				matrix[i][j] =matrix[j][i];
+	}
+ 	/*.................................................................................................................*/
+ 	void calculateDiagonal(double[][] matrix) {
+		double offDiagonal;
+		for (int i = 0; i<getNumStates(); i++) {
+			offDiagonal = 0.0;
+			for (int j = 0; j<getNumStates(); j++) 
+				if (i!=j) 
+					offDiagonal += matrix[i][j];
+			matrix[i][i] = -offDiagonal;
+ 		}
+ 	}
+ 	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		return rateMatrix[0][0] != MesquiteDouble.unassigned;
+	}
+ 	/*.................................................................................................................*/
+	public  CharacterModel cloneModelWithMotherLink(CharacterModel formerClone) {
+		RateMatrixGTRModel model = new RateMatrixGTRModel(probabilityModel, rateMatrix);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof RateMatrixGTRModel) {
+			RateMatrixGTRModel gtr = (RateMatrixGTRModel)pm;
+			gtr.initRateMatrix();
+			for (int i = 0; i<rateMatrix.length; i++) 
+				for (int j = 0; j<rateMatrix[i].length; j++) 
+					gtr.rateMatrix[i][j] =rateMatrix[i][j];
+		}
+		super.copyToClone(pm);
+	}
+ 	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		rateMatrixField = new DoubleSqMatrixFields(dialog,rateMatrix,new String[]{"A", "C", "G", "T"}, true,false,9);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = 0; j<getNumStates(); j++)
+				if (j>i) 
+					rateMatrixTemp[i][j] =rateMatrixField.getValue(i,j);
+		copyUpperRightToLowerLeft(rateMatrixTemp);
+		calculateDiagonal(rateMatrixTemp);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = 0; j<getNumStates(); j++)
+				if (j>i)  {
+					rateMatrixTemp[i][j] =rateMatrixField.getValue(i,j);
+					if (!MesquiteDouble.isCombinable(rateMatrixTemp[i][j]) || !rateMatrixField.getValidDouble()) {
+						errorMessage = "At least one of the rates is not valid.";
+						return false;
+					}
+					if (rateMatrixTemp[i][j]<0.0) {
+						errorMessage = "All rates must be greater than or equal to 0.0";
+						return false;
+					}
+				}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {
+		setRateMatrix(rateMatrixTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public void setRateMatrix(double[][] rateMatrixTemp) {
+		this.rateMatrix = rateMatrixTemp;
+	}
+ 	/*.................................................................................................................*/
+	public double[][] getRateMatrix() {
+		return rateMatrix;
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "RateMatrixGTR";
+	}
+ 	/*.................................................................................................................*/
+	public String toRMatrixString() {
+		String s = "";		
+		boolean firstElement = true;
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = i+1; j<getNumStates();j++) {
+				if (!firstElement)
+					s+= " ";
+				s += MesquiteDouble.toString(rateMatrix[i][j]);
+				firstElement = false;
+			}
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public String getNexusSpecification() {
+		String s = "RMatrix = (" + toRMatrixString() +  ") ";
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+		hasDefaultValues = false;
+		ParseUtil.getToken(description, stringPos);   // RMatrix
+		ParseUtil.getToken(description, stringPos);  // =
+		ParseUtil.getToken(description, stringPos);  // (
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = i+1; j<getNumStates();j++) {
+				String s = ParseUtil.getToken(description, stringPos);
+				if (s.equalsIgnoreCase(")") || StringUtil.blank(s)) 
+					return;
+				rateMatrix[i][j] =MesquiteDouble.fromString(s);
+			}
+		copyUpperRightToLowerLeft(rateMatrix);
+		calculateDiagonal(rateMatrix);
+	}
+	/*.................................................................................................................*/
+	double[] freqs = new double[4];
+	private void resetMatrices(Tree tree, int node) {
+		for (int i = 0; i<4; i++)
+			freqs[i] = getStateFreq(i, tree, node) ;
+		palGTR = new GTR(rateMatrix[0][1], rateMatrix[0][2], rateMatrix[0][3], rateMatrix[1][2], rateMatrix[1][3], freqs);
+		invalidateProbabilitiesAtNodes();
+		matricesSet = true;
+	}
+ 	/*.................................................................................................................*/
+	final static boolean allowArchives = true;
+ 	/*.................................................................................................................*/
+	protected void setChangeProbabilities (double branchLength, Tree tree, int node) {
+	// it is in this method that one calculates the probability of change given the branch length and the rateMatrix and other parameters...
+		if (probabilityModel==null) {
+				MesquiteMessage.warnProgrammer("probabilityModel null!!!");
+			return;
+		}
+		if (probabilityModel.getEquilStatesModel()==null) {
+				MesquiteMessage.warnProgrammer("probabilityModel.getEquilStatesModel() null!!!");
+			return;
+		}
+		if (probabilityModel.getEquilStatesModel().isLineageSpecific() || !matricesSet)
+			resetMatrices(tree, node);
+		boolean useArchives = allowArchives && !probabilityModel.getEquilStatesModel().isLineageSpecific();
+		checkMatrixSizes(tree);
+
+		if (useArchives){
+			//if previous branch length was same, then don't need to recacluate since last matric stored using setChangeProbability is still good
+			if (previousBranchLengths[node] == branchLength) 
+				return;
+			previousBranchLengths[node] = branchLength; //remember current branch length
+			/**/
+			//see if branch length is found among recently seen branch lengths at node, then get probabilities form archive
+			int match = findMatchingArchive(node, branchLength);
+			if (match>-1){
+				for (int i = 0; i<getNumStates(); i++)
+					for (int j = 0; j<getNumStates();j++) {
+						setChangeProbability(i,j, node, archivedProbabilities[node][match][4*i+j+1]);
+					}
+				return;  //We reused archived probabilities; we're done!
+			}
+		}
+		/**************/
+		transProbs = palGTR.getTransitionProbability(transProbs);
+		transProbs.setTime(0.0, branchLength);
+		/**************/
+
+		int d =-1;
+		if (useArchives){
+			//prepare to archive probabilities for future
+			d= findOpenArchive(node);
+			if (d>=0) 
+				archivedProbabilities[node][d][0] = branchLength; //remember in place 0 the branch length
+		}
+		for (int i = 0; i<getNumStates(); i++)
+			for (int j = 0; j<getNumStates();j++) {
+				/**************/
+				double p = transProbs.getTransitionProbability(i, j);
+				/**************/
+				setChangeProbability(i,j, node, p);
+				if (useArchives && d>=0)  //archive the probability
+					archivedProbabilities[node][d][4*i+j+1] = p;
+			}
+		//mark the next one in the archives as available the next time archiving is needed
+		if (useArchives){
+			if (d==maxArchivePlaces-1)
+				archivedProbabilities[node][0][0] = MesquiteDouble.unassigned; //marking as open for next time
+			else
+				archivedProbabilities[node][d+1][0] = MesquiteDouble.unassigned; //marking as open for next time
+		}
+		
+	}
+
+
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "GTR rate matrix model, with rates (A<->C, A<->G, A<->T, C<->G, C<->T, G<->T): " + toRMatrixString();
+	}
+
+}
+
diff --git a/Source/mesquite/genesis/lib/RateMatrixTiTvModel.java b/Source/mesquite/genesis/lib/RateMatrixTiTvModel.java
new file mode 100644
index 0000000..2e05bfe
--- /dev/null
+++ b/Source/mesquite/genesis/lib/RateMatrixTiTvModel.java
@@ -0,0 +1,240 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides root states for probabilistic models, using frequencies for the root states. 
+This class must be subclassed, with the method setStateProbabilities specified. */
+/* ======================================================================== */
+public class  RateMatrixTiTvModel extends RateMatrixDNAModel {
+	double tratio=MesquiteDouble.unassigned;
+	double tratioTemp=MesquiteDouble.unassigned;
+	DoubleField tratioField;
+	boolean hasDefaultValues = true;
+	String errorMessage;
+	boolean alreadyWarned = false;
+
+	public RateMatrixTiTvModel (CompositProbCategModel probabilityModel, double tratio) {
+		super(probabilityModel);
+		this.tratio = tratio;
+	//	this.probabilityModel = probabilityModel;
+ 	}
+	public RateMatrixTiTvModel () {
+		super(null);
+		//this.tratio = tratio;
+ 	}
+	public boolean isFullySpecified(){
+		return tratio != MesquiteDouble.unassigned;
+	}
+ 	/*.................................................................................................................*/
+	public  CharacterModel cloneModelWithMotherLink(CharacterModel formerClone) {
+		RateMatrixTiTvModel model = new RateMatrixTiTvModel(probabilityModel, tratio);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof RateMatrixTiTvModel) {
+			RateMatrixTiTvModel gi = (RateMatrixTiTvModel) pm;
+			gi.tratio = tratio;
+		}
+		super.copyToClone(pm);
+	}
+ 	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		tratioField = dialog.addDoubleField("ti/tv ratio:",tratio, 30);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		tratioTemp = tratioField.getValue();
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		errorMessage = "";
+		tratioTemp = tratioField.getValue();
+		if (!MesquiteDouble.isCombinable(tratioTemp)) {
+			errorMessage = "The transition/transversion ratio is not valid.";
+			return false;
+		}
+		if (tratioTemp<=0.0) {
+			errorMessage = "The transition/transversion ratio must be greater than 0.0";
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		if (!checkOptions())
+			return errorMessage;
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {
+		setTRatio(tratioTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public void setTRatio(double tratio) {
+		this.tratio = tratio;
+	}
+ 	/*.................................................................................................................*/
+	public double getTRatio() {
+		return tratio;
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "RateMatrixTiTv";
+	}
+ 	/*.................................................................................................................*/
+	public String getNexusSpecification() {
+		return "tRatio = " + MesquiteDouble.toString(tratio);
+	}
+ 	/*.................................................................................................................*/
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+		hasDefaultValues = false;
+		ParseUtil.getToken(description, stringPos);   // shape
+		ParseUtil.getToken(description, stringPos);  // =
+		String s = ParseUtil.getToken(description, stringPos);
+   		tratio =  MesquiteDouble.fromString(s);
+	}
+
+	/* this part of the code corrects a problem with the old version of the code (before 10/30/96) , the old
+	code was only problematic when base frequencies were not all 1/4 */
+
+	/*--------------------------------------------------------------------------------------------------
+	|
+	|   SetBeta
+	|
+	|   Set beta parameter (and associated variables) based on a given value of kappa (HKY model)
+	|   or K (F84) model.
+	|
+	|   Note that beta is set such that mean substitution rate will be 1.  E.g., for J-C model,
+	|   beta=4/3, where 12(1/4)(1/4)(4/3) = 1.
+	*/
+	/*--------------------------------------------------------------------
+	|
+	|     HkyChangeMat
+	|
+	|     Calculates the change probabilities for the HKY 1985 model.
+	|
+	*/
+	protected void setChangeProbabilities (double branchLength, Tree tree, int node) {
+		int		i, j;
+		double	u, w, x, y, z,  pij, bigPij;
+		double[] 	bigPi_j;
+		double gBeta;
+		double prob;
+				
+		bigPi_j = new double[4];
+		double kappa = getKappaFromTRatio(tratio);
+
+		gBeta = 0.5 / ((getStateFreq(0, tree, node) + getStateFreq(2, tree, node))*(getStateFreq(1, tree, node) + getStateFreq(3, tree, node)) + kappa*((getStateFreq(0, tree, node)* getStateFreq(2, tree, node)) + (getStateFreq(1, tree, node)*getStateFreq(3, tree, node))));
+
+		bigPi_j[0] = getStateFreq(0, tree, node) + getStateFreq(2, tree, node);
+		bigPi_j[1] = getStateFreq(1, tree, node) + getStateFreq(3, tree, node);
+		bigPi_j[2] = getStateFreq(0, tree, node) + getStateFreq(2, tree, node);
+		bigPi_j[3] = getStateFreq(1, tree, node) + getStateFreq(3, tree, node);
+		
+		for (i=0; i<4; i++) {
+			if (bigPi_j[i]==0.0) {
+				if (!alreadyWarned) {
+					probabilityModel.getCurator().discreetAlert("Illegal change probablities in model of nucleotide sequence evolution, probably caused by self-contradictory model.  Results will not be valid.");
+					alreadyWarned =true;
+				}
+			}
+		}
+
+		for (i=0; i<4; i++) {
+			for (j=0; j<4; j++) {
+				bigPij = bigPi_j[j];
+				pij = getStateFreq(j, tree, node);
+				u = 1.0/bigPij - 1.0;
+				w = -gBeta * (1.0 + bigPij * (kappa - 1.0));
+				x = Math.exp(-gBeta * branchLength);
+				y = Math.exp(w * branchLength);
+				z = (bigPij - pij) / bigPij;
+				if (i == j)
+					prob = pij + pij * u * x + z * y;
+				else if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
+					prob = pij + pij * u * x - (pij/bigPij) * y;
+				else
+					prob =  pij * (1.0 - x);
+				setChangeProbability(i,j,node,prob);
+			}
+		}
+	}
+ 	/*.................................................................................................................*/
+ 	public void invalidateProbabilitiesAtNodes(){
+ 	}
+
+
+	/*--------------------------------------------------------------------------------------------------
+	|
+	|   RtoK
+	|
+	|   Converts transition/transversion ratio ('r') to transition/transversion parameter used in
+	|   Felsenstein's model ("K") or K2P/HKY models ("kappa").  The current base-frequency parameters
+	|   must also be supplied in array 'g'.
+	*/
+
+	public double getKappaFromTRatio(double r)
+	    {
+	    double      atac, gtgc, agct, ag, ct, gR, gY;
+
+	    gR = getStateFreq(0, null, 0) + getStateFreq(2, null, 0);
+	    gY = getStateFreq(1, null, 0) + getStateFreq(3, null, 0);
+	    agct = getStateFreq(0, null, 0)*getStateFreq(2, null, 0) + getStateFreq(1, null, 0)*getStateFreq(3, null, 0);
+
+
+	    return r*gR*gY/agct;
+	    }
+
+	/*--------------------------------------------------------------------------------------------------
+	|
+	|   KtoR
+	|
+	|   Converts from transition-transversion parameter used in Felsenstein's model ("K") or K2P/HKY
+	|   models (kappa) to transition/transversion ratio R.
+	*/
+
+	public double getTRatioFromKappa(double k)
+	    {
+	    double      atac, gtgc, agct, ag, ct, gR, gY;
+
+	    gR = getStateFreq(0, null, 0) + getStateFreq(2, null, 0);
+	    gY = getStateFreq(1, null, 0) + getStateFreq(3, null, 0);
+	    agct = getStateFreq(0, null, 0)*getStateFreq(2, null, 0) + getStateFreq(1, null, 0)*getStateFreq(3, null, 0);
+
+	    return k*agct/(gR*gY);
+	    
+
+	    }
+
+
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "Two parameter, with separate rates for transitions and transversions, ti/tv ratio: " + tratio;
+	}
+
+}
+
diff --git a/Source/mesquite/genesis/lib/SimulationDNAModel.java b/Source/mesquite/genesis/lib/SimulationDNAModel.java
new file mode 100644
index 0000000..a6fec98
--- /dev/null
+++ b/Source/mesquite/genesis/lib/SimulationDNAModel.java
@@ -0,0 +1,539 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+/*~~  */
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+import mesquite.stochchar.lib.*;
+
+public class SimulationDNAModel extends ProbabilityDNAModel  {
+	CategProbModelCurator curator;
+	boolean hasDefaultValues=true;
+	MesquiteInteger pos = new MesquiteInteger(0);
+	Listable[] rootStatesModelArray;
+	Listable[] equilibriumStatesModelArray;
+	Listable[] charRatesModelArray;
+	Listable[] rateMatrixModelArray;
+	ProbSubmodelEdit rootStatesEditListener;
+	ProbSubmodelEdit equilStatesEditListener;
+	ProbSubmodelEdit charRatesEditListener;
+	ProbSubmodelEdit rateMatrixEditListener ;
+	Choice rootStatesModelChoice;
+	Choice equilibriumStatesModelChoice;
+	Choice charRatesModelChoice;
+	Choice rateMatrixModelChoice;
+	Button editRootStatesButton;
+	Button editEquilStatesButton;
+	Button editCharRatesButton; 
+	Button editRateMatrixButton;
+	
+ 	/*.................................................................................................................*/
+	public SimulationDNAModel (String name, Class dataClass, CategProbModelCurator curator){
+		//
+		super(name, dataClass, curator);
+		this.curator = curator;
+	}
+	
+	public String getModelTypeName(){
+		return "Simulation DNA Model";
+	}
+ 	/*.................................................................................................................*/
+	public CharRatesModel initCharRatesModel(){
+		return null;
+	}
+ 	/*.................................................................................................................*/
+	public StateFreqModel initRootStatesModel(){
+		return null;
+	}
+ 	/*.................................................................................................................*/
+	public StateFreqModel initEquilStatesModel(){
+		return null;
+	}
+ 	/*.................................................................................................................*/
+	public RateMatrixCatModel initRateMatrixModel() {
+		return null;
+	}
+ 	/*.................................................................................................................*/
+	public void initForNextCharacter(){
+		CharRatesModel charRatesModel = getCharRatesModel();
+		if (charRatesModel!=null)
+			charRatesModel.initForNextCharacter();
+	}
+	/** Returns instantaneous rate of change from beginState to endState along branch in tree*
+	public double instantaneousRate (int beginState, int endState, Tree tree, int node){
+		return 0;  //NOT READY YET
+	}
+ 	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	if (getRootStatesModel()!= null)
+   	 		temp.addLine("setRootStatesModel " + ParseUtil.tokenize(getRootStatesModel().getName()));
+   	 	if (getEquilStatesModel()!= null)
+   	 		temp.addLine("setEquilStatesModel " + ParseUtil.tokenize(getEquilStatesModel().getName()));
+   	 	if (getCharRatesModel()!= null)
+   	 		temp.addLine("setCharRatesModel " + ParseUtil.tokenize(getCharRatesModel().getName()));
+   	 	if (getRateMatrixModel()!= null)
+   	 		temp.addLine("setRateMatrixModel " + ParseUtil.tokenize(getRateMatrixModel().getName()));
+   	 	temp.addLine("setScalingFactor " + MesquiteDouble.toString(getScalingFactor()));
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+ 	public boolean needsEmpirical(){
+		if (getRootStatesModel()!=null && getRootStatesModel().needsEmpirical())
+			return true;
+		if (getEquilStatesModel() !=null && getEquilStatesModel().needsEmpirical())
+			return true;
+		if (getCharRatesModel() != null && getCharRatesModel().needsEmpirical())
+			return true;
+		if (getRateMatrixModel() != null && getRateMatrixModel().needsEmpirical())
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	public void recalcAfterSetMCharactersStatesHolder (){
+   	 	if (getRootStatesModel()!= null)
+			getRootStatesModel().recalcAfterSetMCharactersStatesHolder();
+  	 	if (getEquilStatesModel()!= null)
+			getEquilStatesModel().recalcAfterSetMCharactersStatesHolder();
+   	 	if (getCharRatesModel()!= null)
+			getCharRatesModel().recalcAfterSetMCharactersStatesHolder();
+   	 	if (getRateMatrixModel()!= null)
+			getRateMatrixModel().recalcAfterSetMCharactersStatesHolder();
+	}
+ 	/*.................................................................................................................*/
+ 	/** Performs command (for Commandable interface) */
+   	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+    	 	if (checker.compare(this.getClass(), "Sets the root states model", "[name of model]", commandName, "setRootStatesModel")) {
+    	 		pos.setValue(0);
+    	 		String name = ParseUtil.getFirstToken(arguments, pos);
+			Listable[] rootStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+			int i = ListableVector.indexOf(rootStatesModelArray, name);
+			if (i<0)
+				return null;
+			setRootStatesModel((StateFreqModel)rootStatesModelArray[i]);
+			initializeRootStatesModel();
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the equilibrium states model", "[name of model]", commandName, "setEquilStatesModel")) {
+    	 		pos.setValue(0);
+    	 		String name = ParseUtil.getFirstToken(arguments, pos);
+			Listable[] equilibriumStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+			int i = ListableVector.indexOf(equilibriumStatesModelArray, name);
+			if (i<0)
+				return null;
+			setEquilStatesModel((StateFreqModel)equilibriumStatesModelArray[i]);
+			initializeEquilStatesModel();
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the character rates model", "[name of model]", commandName, "setCharRatesModel")) {
+    	 		pos.setValue(0);
+    	 		String name = ParseUtil.getFirstToken(arguments, pos);
+			Listable[] charRatesModelArray =  getProject().getFileElements(CharRatesModel.class);
+			int i = ListableVector.indexOf(charRatesModelArray, name);
+			if (i<0)
+				return null;
+			setCharRatesModel((CharRatesModel)charRatesModelArray[i]);
+			initializeCharRatesModel();
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the rate matrix model", "[name of model]", commandName, "setRateMatrixModel")) {
+    	 		pos.setValue(0);
+    	 		String name = ParseUtil.getFirstToken(arguments, pos);
+			rateMatrixModelArray =  getProject().getFileElements(RateMatrixCatModel.class);
+			int i = ListableVector.indexOf(rateMatrixModelArray, name);
+			if (i<0)
+				return null;
+			setRateMatrixModel((RateMatrixCatModel)rateMatrixModelArray[i]);
+			initializeRateMatrixModel();
+			
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the scaling factor (overall rate)", "[number]", commandName, "setScalingFactor")) {
+    	 		pos.setValue(0);
+    	 		double s = MesquiteDouble.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(s))
+				setScalingFactor(s);
+		}
+    	 	else
+ 			return  super.doCommand(commandName, arguments, checker);
+		return null;
+ 	}
+	
+	public String getNexusSpecification(){
+		
+		Snapshot snap = getSnapshot(getFile());
+		String spec = "";
+		for (int i=0; i<snap.getNumLines(); i++)
+			spec += snap.getLine(i) + " ";
+		return ParseUtil.tokenize(spec);
+	}
+	public void fromString(String description, MesquiteInteger stringPos, int format){
+		Puppeteer p = new Puppeteer(MesquiteTrunk.mesquiteTrunk);
+		String commands = ParseUtil.getToken(description, stringPos);
+		MesquiteInteger pos = new MesquiteInteger(0);
+		MesquiteModule.incrementMenuResetSuppression();	
+		p.sendCommands(this, commands, pos, null, false,null, CommandChecker.defaultChecker);
+		MesquiteModule.decrementMenuResetSuppression();	
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "DNASimulationModel";
+	}
+  	/*.................................................................................................................*
+	public double priorProbability (int state){
+		if (!inStates(state)) 
+			return 0;
+		else
+			return (1.0/(4));  // flat prior
+	}
+  	/*.................................................................................................................*/
+	private Listable[]  filterOutNeedingEmpirical(Listable[] array){
+		int count = 0;
+		for (int i=0; i<array.length; i++)
+			if (!((ProbSubModel)array[i]).needsEmpirical())
+				count++;
+		Listable [] filtered = new Listable[count];
+		count = 0;
+		for (int i=0; i<array.length; i++)
+			if (!((ProbSubModel)array[i]).needsEmpirical()) {
+				filtered[count] = array[i];
+				count++;
+			}
+		return filtered;
+	}
+	/*.................................................................................................................*/
+	public Choice addSubmodelPopup(ExtensibleDialog dialog, ProbSubModel probSubModel, Listable[] array, String prompt) {
+		int index  = 0;
+		if (probSubModel != null)
+			index = ListableVector.indexOf(array, probSubModel.getName());
+		if (index <0)
+			index = 0;
+		return dialog.addPopUpMenu(prompt,array,index);
+	}
+	/*.................................................................................................................*/
+	public void arrayToChoice(Choice choice, Listable[] array, int current) {
+		choice.removeAll();
+		for (int i=0; i<array.length; i++) {
+			choice.add(array[i].getName());
+			
+		}
+		if (current < array.length)
+			choice.select(current);
+	}
+	/*.................................................................................................................*/
+	public void checkEditButton(Choice choice,Listable[] modelArray, Button editButton) {
+	 		ProbSubModel model = (ProbSubModel)modelArray[choice.getSelectedIndex()];
+	 		editButton.setEnabled(!model.isBuiltIn());
+	}
+	/*.................................................................................................................*/
+	public void buildAllChoices(Class modelClass) {
+		int current = 0;
+		current = rootStatesModelChoice.getSelectedIndex();
+		rootStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+		arrayToChoice(rootStatesModelChoice,rootStatesModelArray,current);
+		rootStatesEditListener.setArray(rootStatesModelArray);
+
+		current = equilibriumStatesModelChoice.getSelectedIndex();
+		equilibriumStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+		arrayToChoice(equilibriumStatesModelChoice,equilibriumStatesModelArray,current);
+		equilStatesEditListener.setArray(equilibriumStatesModelArray);
+
+		if (modelClass==StateFreqModel.class) {
+			rootStatesModelChoice.select(rootStatesModelChoice.getItemCount()-1);
+			equilibriumStatesModelChoice.select(equilibriumStatesModelChoice.getItemCount()-1);
+		}
+		
+		current = charRatesModelChoice.getSelectedIndex();
+		charRatesModelArray =  getProject().getFileElements(CharRatesModel.class);
+		arrayToChoice(charRatesModelChoice,charRatesModelArray,current);
+		charRatesEditListener.setArray(charRatesModelArray);
+
+		if (modelClass==CharRatesModel.class) 
+			charRatesModelChoice.select(charRatesModelChoice.getItemCount()-1);
+		
+		current = rateMatrixModelChoice.getSelectedIndex();
+		rateMatrixModelArray =  getProject().getFileElements(RateMatrixCatModel.class);
+		arrayToChoice(rateMatrixModelChoice,rateMatrixModelArray,current);
+		rateMatrixEditListener.setArray(rateMatrixModelArray);
+
+		if (modelClass==RateMatrixCatModel.class) 
+			rateMatrixModelChoice.select(rateMatrixModelChoice.getItemCount()-1);
+			
+		checkEditButton(rootStatesModelChoice, rootStatesModelArray, editRootStatesButton);
+		checkEditButton(equilibriumStatesModelChoice, equilibriumStatesModelArray, editEquilStatesButton);
+		checkEditButton(charRatesModelChoice, charRatesModelArray, editCharRatesButton);
+		checkEditButton(rateMatrixModelChoice, rateMatrixModelArray, editRateMatrixButton);
+
+	}
+	/*.................................................................................................................*/
+	public Choice addSubmodelCuratorsPopup(ExtensibleDialog dialog, Class modelClass, String prompt) {
+		int index  = 0;
+	 	MesquiteModule[] curators = null;
+		curators = CharacterModel.findCurators(curator, modelClass);
+		if ((curator!=null) && (curators.length > 0)) {
+			String[] curatorsList = new String[curators.length];
+			for (int i=0; i<curators.length; i++) {
+				if (curators[i] instanceof EditingCurator)
+					curatorsList[i] = curators[i].getNameForMenuItem();
+				else
+					curatorsList[i] = "";
+			}
+			return dialog.addPopUpMenu(prompt,curatorsList,0);
+		}
+		return null;
+	}
+	/*.................................................................................................................*
+	public rebuildChoicePopup(ExtensibleDialog dialog, ProbSubModel probSubModel, Listable[] array) {
+		int index;
+		index = 0;
+		if (probSubModel != null)
+			index = ListableVector.indexOf(array, probSubModel.getName());
+		if (index <0)
+			index = 0;
+		return dialog.addPopUpMenu(prompt,array,index);
+	}
+	/*.................................................................................................................*/
+	public boolean initialize(String message) { 
+		notify = false;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message,buttonPressed);
+		//dialog.setExplainable(this);
+		dialog.addLabel(message);
+		
+		
+		rootStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+		equilibriumStatesModelArray =  getProject().getFileElements(StateFreqModel.class);
+		charRatesModelArray =  getProject().getFileElements(CharRatesModel.class);
+		rateMatrixModelArray =  getProject().getFileElements(RateMatrixCatModel.class);
+/*		if (getCharacterData()==null){
+			rootStatesModelArray =  filterOutNeedingEmpirical(rootStatesModelArray);
+			equilibriumStatesModelArray =  filterOutNeedingEmpirical(equilibriumStatesModelArray);
+			charRatesModelArray =  filterOutNeedingEmpirical(charRatesModelArray);
+			rateMatrixModelArray =  filterOutNeedingEmpirical(rateMatrixModelArray);
+			
+		}
+*/		
+
+
+		rootStatesModelChoice = addSubmodelPopup(dialog, (ProbSubModel)getRootStatesModel(), rootStatesModelArray, "root states model:");
+		dialog.suppressNewPanel();
+		Panel rootStatesButtonPanel = dialog.addNewDialogPanel();
+		editRootStatesButton = dialog.addAButton("Edit...",rootStatesButtonPanel);
+
+		equilibriumStatesModelChoice = addSubmodelPopup(dialog, (ProbSubModel)getEquilStatesModel(),equilibriumStatesModelArray,"equilibrium states model:");
+		dialog.suppressNewPanel();
+		Panel equilStatesButtonPanel = dialog.addNewDialogPanel();
+		 editEquilStatesButton = dialog.addAButton("Edit...",equilStatesButtonPanel);
+
+		equilStatesEditListener  = new ProbSubmodelEdit(this,editEquilStatesButton, equilibriumStatesModelChoice,equilibriumStatesModelArray,  getEquilStatesModel(), StateFreqModel.class,  curator);
+		rootStatesEditListener = new ProbSubmodelEdit(this,editRootStatesButton, rootStatesModelChoice, rootStatesModelArray, getRootStatesModel(), StateFreqModel.class,  curator);
+		Choice newEquilStatesModelChoice = addSubmodelCuratorsPopup(dialog, StateFreqModel.class, "New:");
+		editEquilStatesButton.addActionListener(equilStatesEditListener);
+		editEquilStatesButton.setActionCommand("EditSubModel");
+	 	StateFreqModel selectedStateFreqModel = ((StateFreqModel)equilibriumStatesModelArray[equilibriumStatesModelChoice.getSelectedIndex()]);
+	 	if (selectedStateFreqModel != null)
+	 		editEquilStatesButton.setEnabled(!selectedStateFreqModel.isBuiltIn());
+		equilibriumStatesModelChoice.addItemListener(equilStatesEditListener);
+		newEquilStatesModelChoice.addItemListener(equilStatesEditListener);
+		rootStatesModelChoice.addItemListener(rootStatesEditListener);
+
+		editRootStatesButton.addActionListener(rootStatesEditListener);
+		editRootStatesButton.setActionCommand("EditSubModel");
+	 	selectedStateFreqModel = ((StateFreqModel)rootStatesModelArray[rootStatesModelChoice.getSelectedIndex()]);
+	 	if (selectedStateFreqModel != null)
+	 		editRootStatesButton.setEnabled(!selectedStateFreqModel.isBuiltIn());
+
+
+
+		dialog.addHorizontalLine(1);
+		charRatesModelChoice = addSubmodelPopup(dialog, (ProbSubModel)getCharRatesModel(),charRatesModelArray,"character rates model:");
+		dialog.suppressNewPanel();
+		Panel charRatesButtonPanel = dialog.addNewDialogPanel();
+		editCharRatesButton = dialog.addAButton("Edit...",charRatesButtonPanel);
+		Choice newCharRatesModelChoice = addSubmodelCuratorsPopup(dialog, CharRatesModel.class, "New:");
+		charRatesEditListener = new ProbSubmodelEdit(this,editCharRatesButton, charRatesModelChoice, charRatesModelArray, getCharRatesModel(), CharRatesModel.class,  curator);
+		editCharRatesButton.addActionListener(charRatesEditListener);
+		editCharRatesButton.setActionCommand("EditSubModel");
+	 	CharRatesModel selectedCharRatesModel = ((CharRatesModel)charRatesModelArray[charRatesModelChoice.getSelectedIndex()]);
+	 	if (selectedCharRatesModel != null)
+	 		editCharRatesButton.setEnabled(!selectedCharRatesModel.isBuiltIn());
+		charRatesModelChoice.addItemListener(charRatesEditListener);
+		newCharRatesModelChoice.addItemListener(charRatesEditListener);
+		
+		dialog.addHorizontalLine(1);
+		rateMatrixModelChoice = addSubmodelPopup(dialog, (ProbSubModel)getRateMatrixModel(), rateMatrixModelArray, "rate matrix model:");
+		dialog.suppressNewPanel();
+		Panel rateMatrixButtonPanel = dialog.addNewDialogPanel();
+		editRateMatrixButton = dialog.addAButton("Edit...",rateMatrixButtonPanel);
+		Choice newRateMatrixModelChoice = addSubmodelCuratorsPopup(dialog, RateMatrixCatModel.class, "New:");
+		rateMatrixEditListener = new ProbSubmodelEdit(this,editRateMatrixButton, rateMatrixModelChoice,rateMatrixModelArray, getRateMatrixModel(), RateMatrixCatModel.class, curator);
+		editRateMatrixButton.addActionListener(rateMatrixEditListener);
+		editRateMatrixButton.setActionCommand("EditSubModel");
+	 	RateMatrixCatModel selectedRateMatrixModel = ((RateMatrixCatModel)rateMatrixModelArray[rateMatrixModelChoice.getSelectedIndex()]);
+	 	if (selectedRateMatrixModel != null)
+	 		editRateMatrixButton.setEnabled(!selectedRateMatrixModel.isBuiltIn());
+		rateMatrixModelChoice.addItemListener(rateMatrixEditListener);
+		newRateMatrixModelChoice.addItemListener(rateMatrixEditListener);
+		dialog.addHorizontalLine(1);
+
+		
+		double scale = getScalingFactor();
+		DoubleField scalingFactorField = dialog.addDoubleField("scaling factor:",scale, 8);
+
+		String s = "This is a user-defined model of nucleotide evolution.  Choose one of each of the four submodels: (1) the states at the root of the tree, (2) the equilibrium frequencies of states on other branches, (3) the relative rates of characters, and (4) the relative rates of change from state to state.";
+		s += " You can edit an existing submodel by selecting it in the drop-down menu, and then clicking on the Edit... button.";
+		s += " You can create a new submodel by choosing the appropriate type of submodel from the drop-down menu next to \"New\".";
+		dialog.appendToHelpString(s);
+
+		dialog.completeAndShowDialog(true);
+
+		if (buttonPressed.getValue()==0) {
+			setRootStatesModel((StateFreqModel)rootStatesModelArray[rootStatesModelChoice.getSelectedIndex()]);
+			setEquilStatesModel((StateFreqModel)equilibriumStatesModelArray[equilibriumStatesModelChoice.getSelectedIndex()]);
+			setCharRatesModel((CharRatesModel)charRatesModelArray[charRatesModelChoice.getSelectedIndex()]);
+			setRateMatrixModel( (RateMatrixCatModel)rateMatrixModelArray[rateMatrixModelChoice.getSelectedIndex()]);
+			
+			scale = scalingFactorField.getValue();
+			setScalingFactor(scale);
+
+			initializeSubModels();
+			setEditCancel(false);
+		}
+		else
+			setEditCancel(true);
+		setSeed(originalSeed);
+		dialog.dispose();
+		notify = true;
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+
+		return (buttonPressed.getValue()==0);
+
+	}
+	/*.................................................................................................................*/
+	public boolean isOneOfMine(ProbSubModel submodel){
+		return submodel ==getOriginalRootStatesModel() || submodel ==getOriginalEquilStatesModel() || submodel ==getOriginalCharRatesModel() || submodel ==getOriginalRateMatrixModel();
+	}
+	/*.................................................................................................................*/
+	public void resetFromOriginalSubmodels(){
+		setRootStatesModel(getOriginalRootStatesModel());
+		setEquilStatesModel(getOriginalEquilStatesModel());
+		setCharRatesModel(getOriginalCharRatesModel());
+		setRateMatrixModel(getOriginalRateMatrixModel());
+
+		initializeSubModels();
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		SimulationDNAModel model = new SimulationDNAModel(name, getStateClass(), getCurator()); 
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null || !(pm instanceof SimulationDNAModel))
+			return;
+		((SimulationDNAModel)pm).hasDefaultValues = hasDefaultValues;
+
+		super.copyToClone(pm);
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		String param = "";
+		if (getRootStatesModel()!=null)
+			param += "        Root states model (" + getRootStatesModel().getName() + "): "+ getRootStatesModel().getParameters()+StringUtil.lineEnding();
+		if (getEquilStatesModel()!=null)
+			param += "        Equilibrium states model (" + getEquilStatesModel().getName() + "): "+ getEquilStatesModel().getParameters()+StringUtil.lineEnding();
+		if (getCharRatesModel()!=null)
+			param += "        Character rates model (" + getCharRatesModel().getName() + "): "+ getCharRatesModel().getParameters()+StringUtil.lineEnding();
+		if (getRateMatrixModel()!=null)
+			param += "        Rate matrix model (" + getRateMatrixModel().getName() + "): "+ getRateMatrixModel().getParameters()+StringUtil.lineEnding();
+		return param;
+	}
+	/* --------------------------------------------- */
+	public MesquiteNumber[] getParameterValues() {  //fill in when estimation is done
+		return null;
+	}
+ 	/*.................................................................................................................*/
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "This is a user-defined model of nucleotide evolution.  It has four submodels: the states at the root of the tree, the equilibrium frequencies of states on other branches, the relative rates of characters, and the relative rates of change from state to state.";
+	}
+}
+
+ class ProbSubmodelEdit implements ActionListener, ItemListener{
+ 	Choice editChoice;
+ 	ProbSubModel subModel;
+ 	 CategProbModelCurator curator;
+ 	 Listable[] modelArray;
+ 	 Class modelClass;
+ 	 Button editButton;
+ 	 SimulationDNAModel generalModel;
+ 	
+	/*.................................................................................................................*/
+	public ProbSubmodelEdit(SimulationDNAModel generalModel, Button editButton, Choice editChoice, Listable[] modelArray, ProbSubModel subModel, Class modelClass,  CategProbModelCurator curator) {
+		this.subModel = subModel;
+		this.generalModel = generalModel;
+		this.editChoice = editChoice;
+		this.curator = curator;
+		this.modelArray = modelArray;
+		this.modelClass = modelClass;
+		this.editButton = editButton;
+	}
+	/*.................................................................................................................*/
+	 public  void setArray( Listable[] array) {
+	 	this.modelArray = array;
+	 }
+	/*.................................................................................................................*/
+	 public  void itemStateChanged(ItemEvent e) {
+	 	if (e.getItemSelectable() == editChoice) {    // the choice for choosing among existing models was chosen
+	 		ProbSubModel model = (ProbSubModel)modelArray[editChoice.getSelectedIndex()];
+	 		editButton.setEnabled(!model.isBuiltIn());
+	 	}
+	 	else if (e.getStateChange()==e.SELECTED) {   // the New model choice was chosen
+		 	MesquiteModule[] curators = null;
+			curators = CharacterModel.findCurators(curator, modelClass);
+			if ((curator!=null) && (curators.length > 0)) {
+				int modelCurator = -1;
+				for (int i = 0; i < curators.length; i++) {
+					if (curators[i].getNameForMenuItem() == e.getItem())
+						modelCurator = i;
+				}
+				if (modelCurator >=0) {
+					CharacterModel newModel = (CharacterModel)((CharModelCurator)curators[modelCurator]).doCommand("newModel", "Model", CommandChecker.defaultChecker);
+	 				if (newModel != null) {
+	 					generalModel.buildAllChoices(modelClass);
+	 				}
+	 			}
+	 		}
+	 	}
+	 }
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	ProbSubModel model = (ProbSubModel)modelArray[editChoice.getSelectedIndex()];
+	 	MesquiteModule[] curators = null;
+		curators = CharacterModel.findCurators(curator, model.getClass());
+		if ((curators!=null) && (curators.length > 0)) {
+	 		if (e.getActionCommand() == "EditSubModel") {
+				if (!model.isBuiltIn())
+					((CharModelCurator)curators[0]).showEditor(model);
+			}
+		}
+	 }
+}
+
+
diff --git a/Source/mesquite/genesis/lib/StateFreqCurator.java b/Source/mesquite/genesis/lib/StateFreqCurator.java
new file mode 100644
index 0000000..e964ff0
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqCurator.java
@@ -0,0 +1,34 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class StateFreqCurator extends ProbSubModelCurator  {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+}
+
+
diff --git a/Source/mesquite/genesis/lib/StateFreqDNAEmpir.java b/Source/mesquite/genesis/lib/StateFreqDNAEmpir.java
new file mode 100644
index 0000000..057d72d
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqDNAEmpir.java
@@ -0,0 +1,188 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class StateFreqDNAEmpir extends StateFreqDNAModel {
+	//DNAData data = null;
+	boolean specified = false;
+	
+	public StateFreqDNAEmpir (CompositProbCategModel probabilityModel) {
+		super(probabilityModel);
+	}
+	public StateFreqDNAEmpir () {
+		super(null);
+	}
+	/*.................................................................................................................*/
+	public String getNexusSpecification(){ //could indicate matrix used
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	/** Sets the state frequencies; doesn't currently have an impact, as when this is invoked the data are not present. */
+	public void setStateFrequencies (){
+	}
+	public boolean isFullySpecified(){
+		return true;
+	}
+ 	/*.................................................................................................................*/
+ 		public boolean needsEmpirical(){
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public void initialize() {
+//		if (probabilityModel!=null && probabilityModel.getData()==null)
+//			probabilityModel.acquireData();
+	}
+ 	/*.................................................................................................................*/
+	public void taxaSet() {
+//		resetStateFrequencies();
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		StateFreqDNAEmpir model = new StateFreqDNAEmpir(probabilityModel);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/*.................................................................................................................*/
+	public void recalcAfterSetMCharactersStatesHolder (){
+		MCharactersStatesHolder d = probabilityModel.getMCharactersStatesHolder();
+		if ((d==null) || !(DNAData.class.isAssignableFrom(d.getCharacterDataClass()))){
+			MesquiteMessage.warnProgrammer("Empirical data in model null or not DNA data; will use equal freq. (StateFreqDNAEmpir)");
+			return;
+		}
+		MCategoricalStates data = (MCategoricalStates)d;
+		if (data!=null){
+			specified = true;
+			long numTotal=0;
+	   		double[] stateTotal = new double[4];
+			for (int it=0; it<data.getNumTaxa(); it++)
+				for (int ic = 0; ic<data.getNumChars(); ic++) {
+					if (data.isCurrentlyIncluded(ic)) {   
+						long stateSet = data.getState(ic, it);
+						int card = CategoricalState.cardinality(stateSet);
+						if (DNAState.isCombinable(stateSet)) {
+							for (int state=0; state<4; state++)
+								if (DNAState.isElement(stateSet, state))
+									stateTotal[state]+= 1.0/card;
+							numTotal++;
+						}
+					}
+				}
+			for (int state=0; state<4; state++) {
+					setStateFreq(state,  (stateTotal[state]/numTotal));
+			}
+		}
+		else {
+			MesquiteMessage.warnProgrammer("data null; will use equal freq.");
+			for (int state=0; state<4; state++)
+				setStateFreq(state,  0.25);  // give warning!!!
+		}
+	}
+ 	/*.................................................................................................................*/
+	/** Resets the equilibrium state frequencies to be all equal. */
+	public void resetStateFrequencies (){
+		MCharactersStatesHolder d = probabilityModel.getMCharactersStatesHolder();
+		if (!(DNAData.class.isAssignableFrom(d.getCharacterDataClass()))){
+			MesquiteMessage.warnProgrammer("Empirical data in model null or not DNA data; will use equal freq. (StateFreqDNAEmpir)");
+			return;
+		}
+		MCategoricalStates data = (MCategoricalStates)d;
+		if (data!=null){
+			setDefaultNumChars(data.getNumChars());
+			specified = true;
+			long numTotal = 0;
+	   		double[] stateTotal = new double[4];
+			for (int it=0; it<data.getNumTaxa(); it++)
+				for (int ic = 0; ic<data.getNumChars(); ic++) {
+					if (data.isCurrentlyIncluded(ic)) {   
+						long stateSet = data.getState(ic, it);
+						int card = CategoricalState.cardinality(stateSet);
+						if (DNAState.isCombinable(stateSet)) {
+							for (int state=0; state<4; state++)
+								if (DNAState.isElement(stateSet, state)) {
+									stateTotal[state]+= 1.0/card;
+								}
+							numTotal++;
+						}
+					}
+				}
+			for (int state=0; state<4; state++) {
+					setStateFreq(state,  (stateTotal[state]/numTotal));
+			}
+		}
+		else {
+			MesquiteMessage.warnProgrammer("data null; will use equal freq.");
+			for (int state=0; state<4; state++)
+				setStateFreq(state,  0.25);  // give warning!!!
+		}
+	}
+	public boolean isBuiltIn() {
+		return true;
+	}
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "empirical";
+	}
+	/** returns name of model for nexus*/
+	public String getNEXUSName() {
+		return "empirical";
+	}
+	/** returns name of model*/
+	public String getName() {
+		return "Empirical Frequencies";
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+			return true;
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		String s= "Empirical Frequencies";
+		if (probabilityModel!=null) {
+			MCharactersStatesHolder d = probabilityModel.getMCharactersStatesHolder();
+			if (d!=null) {
+				CharacterData data = d.getParentData();
+				if (data!= null)
+					s += " from matrix " + data.getName();
+			}
+		}
+		if (specified) {
+			s += " (A=" + MesquiteDouble.toString(getStateFreq(0, null, 0));
+			s += " C=" + MesquiteDouble.toString(getStateFreq(1, null, 0));
+			s += " G=" + MesquiteDouble.toString(getStateFreq(2, null, 0));
+			s += " T=" + MesquiteDouble.toString(getStateFreq(3, null, 0))+")";
+		}
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqDNAEqual.java b/Source/mesquite/genesis/lib/StateFreqDNAEqual.java
new file mode 100644
index 0000000..7ccb29a
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqDNAEqual.java
@@ -0,0 +1,90 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class StateFreqDNAEqual extends StateFreqDNAModel {
+	public StateFreqDNAEqual (CompositProbCategModel probabilityModel) {
+		super(probabilityModel);
+	}
+ 	/*.................................................................................................................*/
+	/** Sets the equilibrium state frequencies to be all equal. */
+	public void setStateFrequencies (){
+		double probEach =1.0/getNumStates();
+		for (int i=0; i<getNumStates(); i++) 
+			setStateFreq(i,probEach);
+	}
+	/*.................................................................................................................*/
+	public String getNexusSpecification(){
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		StateFreqDNAEqual model = new StateFreqDNAEqual(probabilityModel);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof StateFreqDNAEqual))
+			return;
+		StateFreqDNAEqual model = (StateFreqDNAEqual)md;
+		model.setStateFrequencies();
+		super.copyToClone(md);
+	}
+	/** Returns whether parameters of model are fully specified.  If so, it can be used for evolving states.*/
+	public boolean isFullySpecified(){
+		return true;
+	}
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "equal";
+	}
+	/** returns name of model*/
+	public String getName() {
+		return "Equal Frequencies";
+	}
+	/** returns name of model*/
+	public String getNEXUSName() {
+		return "equal";
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+			return true;
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public void setOptions() {}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "Equal Frequencies";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqDNAModel.java b/Source/mesquite/genesis/lib/StateFreqDNAModel.java
new file mode 100644
index 0000000..295d0d2
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqDNAModel.java
@@ -0,0 +1,37 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides root states for probabilistic models, using frequencies for the root states. 
+This class must be subclassed, with the method setStateFrequencies specified. */
+/* ======================================================================== */
+public abstract class StateFreqDNAModel extends StateFreqModel {
+
+	public StateFreqDNAModel (CompositProbCategModel probabilityModel) {
+ 		super(probabilityModel, 4);
+ 	}
+ 	/*.................................................................................................................*/
+	public void initAvailableStates() {
+		availableStates = new int[4];
+		for (int i=0; i<4; i++)
+			availableStates[i]=i;
+	}
+
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqDNASpecif.java b/Source/mesquite/genesis/lib/StateFreqDNASpecif.java
new file mode 100644
index 0000000..248e93f
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqDNASpecif.java
@@ -0,0 +1,101 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class StateFreqDNASpecif extends StateFreqDNAModel {
+	boolean specified = false;
+	double[] frequencies;
+	DoubleField AField, CField, GField, TField;
+	double AFreq = 0.25, CFreq =0.25, GFreq=0.25, TFreq=0.25;
+	double AFreqTemp, CFreqTemp, GFreqTemp, TFreqTemp;
+	
+	public StateFreqDNASpecif (CompositProbCategModel probabilityModel) {
+		super(probabilityModel);
+		
+	}
+	/*.................................................................................................................*/
+	public String getNexusSpecification(){ //needs to return freqs
+		return "";
+	}
+	public boolean isFullySpecified(){
+		return specified;
+	}
+ 	/*.................................................................................................................*/
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		StateFreqDNASpecif model = new StateFreqDNASpecif(probabilityModel);
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof StateFreqDNASpecif))
+			return;
+		StateFreqDNASpecif model = (StateFreqDNASpecif)md;
+		model.setStateFrequencies(frequencies);
+		super.copyToClone(md);
+	}
+ 	/*.................................................................................................................*/
+	/** Sets the equilibrium state frequencies to be all equal. */
+	public void setStateFrequencies (){
+	}
+ 	/*.................................................................................................................*/
+	/** Sets the equilibrium state frequencies to be all equal. */
+	public void setStateFrequencies (double[] frequencies){
+		for (int i=0; i<frequencies.length; i++) {
+			setStateFreq(i,frequencies[i]);
+			this.frequencies[i] = frequencies[i];
+		}
+		specified = true;
+	}
+	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		AField = dialog.addDoubleField("A:",AFreq, 20);
+		CField = dialog.addDoubleField("C:",CFreq, 20);
+		GField = dialog.addDoubleField("G:",GFreq, 20);
+		TField = dialog.addDoubleField("T:",TFreq, 20);
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		AFreqTemp = AField.getValue();
+		CFreqTemp = CField.getValue();
+		GFreqTemp = GField.getValue();
+		TFreqTemp = TField.getValue();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return "";
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {
+		setStateFreq(0,AFreqTemp);
+		setStateFreq(1,CFreqTemp);
+		setStateFreq(2,GFreqTemp);
+		setStateFreq(3,TFreqTemp);
+		specified = true;
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqModel.java b/Source/mesquite/genesis/lib/StateFreqModel.java
new file mode 100644
index 0000000..6584442
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqModel.java
@@ -0,0 +1,183 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that provides root states for probabilistic models, using frequencies for the root states. 
+This class must be subclassed, with the method setStateFrequencies specified. */
+/* ======================================================================== */
+public abstract class StateFreqModel extends ProbSubModel {
+	long allStates = 0L;
+	int[] availableStates;
+	int numStates = 0;
+	private double[] stateFrequencies = null;
+	private double[] cumStateFreq = null;
+	protected Random randomNumber;
+	boolean checkForZero=false;
+	boolean nodeVariable=false;
+	
+
+	public StateFreqModel (CompositProbCategModel probabilityModel, int numStates) {
+		super(null, CategoricalState.class);
+		this.numStates = numStates;
+ 		stateFrequencies = new double[numStates];
+ 		cumStateFreq = new double[numStates];
+ 		randomNumber = new Random();
+ 		this.probabilityModel = probabilityModel;
+ 		initAvailableStates();
+ 		zeroStateFrequencies();
+ 		setStateFrequencies();
+ 	}
+ 	/*.................................................................................................................*/
+ 	public String getExplanation(){
+ 		return "Model of state frequencies";
+ 	}
+ 	public String getParadigm(){
+ 		return "StateFreqModel";
+ 	}
+	/** Returns nexus command introducing this model.*/
+/*	public String getNEXUSCommand() {
+		return "StateFreqModel";
+	}
+ 	/*.................................................................................................................*/
+	public void initialize() {
+	}
+ 	/*.................................................................................................................*/
+	public void taxaSet() {
+	}
+	/*.................................................................................................................*/
+	public abstract void initAvailableStates ();
+	/*.................................................................................................................*/
+	public int getNumStates (){
+		return stateFrequencies.length;
+	}
+	/*.................................................................................................................*/
+	public void setNumStates (int numstates){
+		this.numStates = numstates;
+	}
+	/*.................................................................................................................*/
+	/** Ask if the state frequencies are all zero.*/
+	public boolean stateFrequenciesAllZero (){
+		double freqSum = 0;
+		for (int i=0; i<stateFrequencies.length; i++) 
+			freqSum += stateFrequencies[i];
+		checkForZero = true;
+		return (freqSum<0.5);
+	}
+	/*.................................................................................................................*/
+	/** Sets the state frequencies to zero.*/
+	public void zeroStateFrequencies (){
+		for (int i=0; i<stateFrequencies.length; i++) 
+			stateFrequencies[i] = 0.0;
+	}
+  	/*.................................................................................................................*/
+	/** Sets the equilibrium state frequencies in the model. Must be specified by the subclass. */
+	public abstract void setStateFrequencies ();
+  	/*.................................................................................................................*/
+	/** Returns the state frequencies in the model.  */
+	public double[]  getStateFrequencies () {
+		return stateFrequencies;
+	}
+  	/*.................................................................................................................*/
+	/** Sets the equilibrium state frequencies in the model; used to reset them if things have changed. */
+	public void resetStateFrequencies () {
+		setStateFrequencies();
+	}
+	/*.................................................................................................................*/
+	public void setStateFreq (int state, double freq){
+		stateFrequencies[state] = freq;
+		calcCumStateFreq();
+	}
+	/*.................................................................................................................*/
+	public double getStateFreq (int state){
+		return stateFrequencies[state];
+	}
+	/*.................................................................................................................*/
+	/** Calculates the cumulative state frequencies.*/
+	public void calcCumStateFreq (){
+		double accumProb = 0;
+		for (int i=0; i<stateFrequencies.length; i++) {
+			accumProb +=  stateFrequencies[i];
+			cumStateFreq[i] = accumProb;
+		}
+	}
+	
+	/*.................................................................................................................*/
+	public boolean checkValidityStateFreq (){
+		if (!checkForZero && stateFrequenciesAllZero()) {
+			if (stateFrequenciesAllZero()) {
+				checkForZero = false;
+				return false;
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public double getStateFreq (int state, Tree tree, int node){
+		if (!checkValidityStateFreq())
+			return 0.0;
+		else
+			return stateFrequencies[state];
+	}
+	/*.................................................................................................................*/
+	public double getCumulativeStateFreq (int state, Tree tree, int node){
+		if (!checkValidityStateFreq())
+			return 0.0;
+		else
+			return cumStateFreq[state];
+	}
+	/*.................................................................................................................*/
+	/** Given a random number between 0 and 1, returns the state value.*/
+	public long getState (double randomDouble, Tree tree, int node){
+		if (availableStates.length == 1)
+			return (allStates);  
+		else {
+			if (!checkValidityStateFreq())
+				return CategoricalState.makeSet(availableStates.length-1);
+			for (int i=0; i<availableStates.length; i++)
+				if (randomDouble< getCumulativeStateFreq(i, tree, node))
+					return CategoricalState.makeSet(availableStates[i]);
+			return CategoricalState.makeSet(availableStates.length-1);
+				
+		}
+	}
+	/*.................................................................................................................*/
+	/** Randomly generates according to model a state.*/
+	public long getState (Tree tree, int node){
+		double r = randomNumber.nextDouble();
+		return getState(r, tree, node);
+	}
+ 	/*.................................................................................................................*/
+	public void setSeed(long seed){
+		randomNumber.setSeed(seed);
+	}
+ 	/*.................................................................................................................*/
+	public long getSeed(){
+		return randomNumber.nextLong();
+	}
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "";
+	}
+	public String getModelTypeName(){
+		return "State frequencies model";
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqModelSet.java b/Source/mesquite/genesis/lib/StateFreqModelSet.java
new file mode 100644
index 0000000..90794b7
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqModelSet.java
@@ -0,0 +1,42 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/*======================================================================== */
+/** a ModelSet for probability models. */
+public class StateFreqModelSet  extends ModelSet {
+	
+	public StateFreqModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "State Freq. Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		StateFreqModelSet ms = new StateFreqModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new StateFreqModelSet("State Freq. Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+}
+
diff --git a/Source/mesquite/genesis/lib/StateFreqUserCurator.java b/Source/mesquite/genesis/lib/StateFreqUserCurator.java
new file mode 100644
index 0000000..97aeeaf
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqUserCurator.java
@@ -0,0 +1,81 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.genesis.lib.*;
+/* ======================================================================== */
+public abstract class StateFreqUserCurator extends StateFreqCurator implements EditingCurator {
+	StateFreqUserModel modelToEdit;
+	/*.................................................................................................................*
+  	 public void projectEstablished(){
+  	 }
+   
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return StateFreqUserModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public abstract int getNumStates();
+	/*.................................................................................................................*/
+	public void setNumStates(int numStates){
+		if (modelToEdit!=null)
+			modelToEdit.setNumStates(numStates);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "StateFrequencyUserSpecified";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "StateFrequencyUserSpecified";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return StateFreqUserModel.class;
+	}
+	/*.................................................................................................................*
+  	public CharacterModel makeNewModel(String name) {
+ 		StateFreqUserModel model = new StateFreqUserModel(null, 4, null);
+ 		model.setName(name);
+       		return model;
+   	}
+   
+	/*.................................................................................................................*
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		StateFreqUserModel model = new StateFreqUserModel();
+ 		model.setName(name);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "User-Specified State Frequency Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "User-Specified State Frequencies...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains user-specified state frequency models." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/genesis/lib/StateFreqUserDNAModel.java b/Source/mesquite/genesis/lib/StateFreqUserDNAModel.java
new file mode 100644
index 0000000..7ac905f
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqUserDNAModel.java
@@ -0,0 +1,86 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+
+/** A class that provides a General Time Reversible rate matrix. */
+/* ======================================================================== */
+public class StateFreqUserDNAModel extends StateFreqUserModel {
+	
+//	DoubleSqMatrixFields rateMatrixField;
+
+	public StateFreqUserDNAModel (CompositProbCategModel probabilityModel, double[] stateFrequencies) {
+		super(probabilityModel,4,stateFrequencies);
+ 	}
+
+ 	/*.................................................................................................................*/
+	public  CharacterModel cloneModelWithMotherLink(CharacterModel formerClone) {
+		StateFreqUserDNAModel model = new StateFreqUserDNAModel(probabilityModel, getStateFrequencies());
+		completeDaughterClone(formerClone, model);
+		return model;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		if (pm instanceof StateFreqUserDNAModel) {
+			StateFreqUserDNAModel stateFreqUser = (StateFreqUserDNAModel)pm;
+			for (int i = 0; i<getNumStates(); i++) 
+				stateFreqUser.setStateFreq(i,getStateFreq(i));
+		}
+		super.copyToClone(pm);
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "StateFrequencyUserSpecifiedDNA";
+	}
+ 	/*.................................................................................................................*/
+	public String getNexusSpecification() {
+		String s = "frequencies = (" + toStateFreqString() +  ") ";
+		return s;
+	}
+	/*.................................................................................................................*/
+	public Class dataClass(){
+		return DNAState.class;
+	}
+ 	/*.................................................................................................................*/
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+		hasDefaultValues = false;
+		ParseUtil.getToken(description, stringPos);   // RMatrix
+		ParseUtil.getToken(description, stringPos);  // =
+		ParseUtil.getToken(description, stringPos);  // (
+		for (int i = 0; i<getNumStates(); i++) {
+				String s = ParseUtil.getToken(description, stringPos);
+				if (s.equalsIgnoreCase(")") || StringUtil.blank(s)) 
+					return;
+				setStateFreq(i,MesquiteDouble.fromString(s));
+			}
+		checkNormality(getStateFrequencies());
+	}
+  	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "User-specified state frequency model, with values (A C G T): " + toStateFreqString();
+	}
+
+}
+
+
diff --git a/Source/mesquite/genesis/lib/StateFreqUserModel.java b/Source/mesquite/genesis/lib/StateFreqUserModel.java
new file mode 100644
index 0000000..8618407
--- /dev/null
+++ b/Source/mesquite/genesis/lib/StateFreqUserModel.java
@@ -0,0 +1,209 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+
+/** A class that provides a General Time Reversible rate matrix. */
+/* ======================================================================== */
+public abstract class StateFreqUserModel extends StateFreqModel implements ActionListener {
+	boolean hasDefaultValues = true;
+	double[] stateFrequenciesTemp;
+	boolean values = false;
+	DoubleField[] stateFreqField;
+	String errorMessage="";
+	
+//	DoubleSqMatrixFields rateMatrixField;
+
+	public StateFreqUserModel (CompositProbCategModel probabilityModel, int numstates, double[] stateFrequencies) {
+		super(probabilityModel, numstates);
+		stateFrequenciesTemp = new double[getNumStates()];
+		for (int i=0; i<getNumStates(); i++) {
+			if (stateFrequencies==null)
+				setStateFreq(i,MesquiteDouble.unassigned);
+			else
+				setStateFreq(i,stateFrequencies[i]);
+		}
+ 	}
+
+ 	/*.................................................................................................................*/
+	/** Sets the state frequencies. */
+	public void setStateFrequencies (){
+	}
+ 	/*.................................................................................................................*/
+	/** Sets the state frequencies. */
+	public void setStateFrequencies (double[] freq){
+		if (freq.length>= getNumStates())
+			for (int i=0; i<getNumStates(); i++)  {
+				setStateFreq(i,freq[i]);
+				stateFreqField[i].setValue(freq[i]);
+			}
+	}
+	/*.................................................................................................................*/
+	public boolean isFullySpecified(){
+		for (int i=0; i<getNumStates(); i++) 
+			if (getStateFreq(i)== MesquiteDouble.unassigned)
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	public abstract Class dataClass();
+  	/*.................................................................................................................*/
+	public void addOptions(ExtensibleDialog dialog) {
+		stateFreqField = new DoubleField[getNumStates()];
+		for (int i=0; i<getNumStates(); i++) {
+			stateFreqField[i] = dialog.addDoubleField(""+CategoricalData.getDefaultStateSymbol(dataClass(),i)+":",getStateFreq(i), 10);
+		}
+		Panel moreButtons = new Panel();
+		dialog.addAListenedButton("Equal",moreButtons,this);
+		dialog.addAListenedButton("Norm+-",moreButtons,this);
+		dialog.addAListenedButton("Norm*/",moreButtons,this);
+		dialog.addNewDialogPanel(moreButtons);			
+	}
+	/*.................................................................................................................*/
+	public void initAvailableStates() {
+		availableStates = new int[numStates];
+		for (int i=0; i<getNumStates(); i++)
+			availableStates[i]=i;
+	}
+ 	/*.................................................................................................................*/
+	public boolean recoverOptions() {
+		for (int i = 0; i<getNumStates(); i++)
+			stateFrequenciesTemp[i] =stateFreqField[i].getValue();
+		return checkNormality(stateFrequenciesTemp);
+	}
+	/*.................................................................................................................*/
+	public boolean checkOptions() {
+		for (int i = 0; i<getNumStates(); i++)
+			stateFrequenciesTemp[i] =stateFreqField[i].getValue();
+		return checkNormality(stateFrequenciesTemp) && checkValueRange(stateFrequenciesTemp);
+	}
+	/*.................................................................................................................*/
+	public String checkOptionsReport() {
+		return errorMessage; 
+	}
+ 	/*.................................................................................................................*/
+	public void setOptions() {
+		setStateFrequencies(stateFrequenciesTemp);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkNormality(double[] frequencies) {
+		double total = 0.0;
+		for (int i = 0; i<frequencies.length; i++)
+			total += frequencies[i];
+		double tolerance = 0.001;
+		if (((total-1.0) > tolerance)|| ((1.0- total) > tolerance)) {
+			errorMessage = "Frequencies do not add up to 1.0!";
+			return false;
+		}
+		return true;
+	}
+ 	/*.................................................................................................................*/
+	public boolean checkValueRange(double[] frequencies) {
+		for (int i = 0; i<frequencies.length; i++) {
+			if (frequencies[i] < 0.0) {
+				errorMessage = "All frequencies must have positive values";
+				return false;
+			}
+			else if (frequencies[i]>1.0) {
+				errorMessage = "All frequencies must be 1.0 or less";
+				return false;
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "StateFrequencyUserSpecified";
+	}
+ 	/*.................................................................................................................*/
+	public String toStateFreqString() {
+		String s = "";		
+		boolean firstElement = true;
+		for (int i = 0; i<getNumStates(); i++) {
+			if (!firstElement)
+				s+= " ";
+			s += MesquiteDouble.toString(getStateFreq(i));
+			firstElement = false;
+		}
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public String getNexusSpecification() {
+		String s = "StateFreq = (" + toStateFreqString() +  ") ";
+		return s;
+	}
+ 	/*.................................................................................................................*/
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+		hasDefaultValues = false;
+		ParseUtil.getToken(description, stringPos);   // RMatrix
+		ParseUtil.getToken(description, stringPos);  // =
+		ParseUtil.getToken(description, stringPos);  // (
+		for (int i = 0; i<getNumStates(); i++) {
+				String s = ParseUtil.getToken(description, stringPos);
+				if (s.equalsIgnoreCase(")") || StringUtil.blank(s)) 
+					return;
+				setStateFreq(i,MesquiteDouble.fromString(s));
+			}
+		checkNormality(getStateFrequencies());
+	}
+ 	/*.................................................................................................................*/
+	final static boolean allowArchives = true;
+ 
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	if   ("Equal".equals(e.getActionCommand())) {
+			double probEach =1.0/getNumStates();
+			for (int i=0; i<getNumStates(); i++) 
+				stateFrequenciesTemp[i] = probEach;
+	 		setOptions();
+	 		//setStateFrequencies(stateFrequenciesTemp);
+	 	}
+	 	else if   ("Norm+-".equals(e.getActionCommand())) {
+			double total =0;
+			for (int i=0; i<getNumStates(); i++) 
+				total += stateFreqField[i].getValue();
+			double difference = (total - 1.0)/getNumStates();
+			for (int i=0; i<getNumStates(); i++) 
+				stateFrequenciesTemp[i] = stateFreqField[i].getValue() - difference;
+	 		setOptions();
+	 	}
+	 	else if   ("Norm*/".equals(e.getActionCommand())) {
+			double total =0;
+			for (int i=0; i<getNumStates(); i++) 
+				total += stateFreqField[i].getValue();
+			for (int i=0; i<getNumStates(); i++) 
+				stateFrequenciesTemp[i] = stateFreqField[i].getValue()/total;
+	 		setOptions();
+	 	}
+	 }
+ 	/*.................................................................................................................*/
+	/** returns parameters of the model. */
+	public String getParameters (){
+		return "User-specified state frequency model, with values (A C G T): " + toStateFreqString();
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/genesis/lib/SubmodelInfo.java b/Source/mesquite/genesis/lib/SubmodelInfo.java
new file mode 100644
index 0000000..cd6591a
--- /dev/null
+++ b/Source/mesquite/genesis/lib/SubmodelInfo.java
@@ -0,0 +1,61 @@
+/* Mesquite source code (Genesis package).  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.genesis.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** A class that contains information regarding submodels of stochastic models of character evolution . */
+/* ======================================================================== */
+public class SubmodelInfo extends FileElement {
+	Class c;
+	String explanation;
+	public SubmodelInfo (Class c, String name, String explanation) {
+		this.c = c;
+		setName(name);
+		this.explanation = explanation;
+ 	}
+ 	public String getExplanation(){
+ 		return explanation;
+ 	}
+ 	public Class getContainedClass(){
+ 		return c;
+ 	}
+ 	public boolean containsSubclassOf(Class queryClass){
+ 		if (queryClass == null)
+ 			return false;
+ 		return queryClass.isAssignableFrom(c);
+ 	}
+ 	public Object makeModel(){
+ 		if (c == null)
+ 			return null;
+		try {
+			Object s =c.newInstance();
+			return s;
+		}
+		catch (IllegalAccessException e){
+			MesquiteTrunk.mesquiteTrunk.alert("iae smi");
+			e.printStackTrace(); 
+		}
+		catch (InstantiationException e){
+			MesquiteTrunk.mesquiteTrunk.alert("ie smi");
+			e.printStackTrace(); 
+		}
+		return null;
+ 		
+ 	}
+}
+
diff --git a/Source/mesquite/iText/aiTextIntro/aiTextIntro.java b/Source/mesquite/iText/aiTextIntro/aiTextIntro.java
new file mode 100644
index 0000000..b05aa9c
--- /dev/null
+++ b/Source/mesquite/iText/aiTextIntro/aiTextIntro.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.iText.aiTextIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aiTextIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aiTextIntro.class;
+  	 }
+ 	/*.................................................................................................................*/
+ 	public String getExplanation() {
+ 		return "iText is a package for saving PDF files within Mesquite.";
+ 	}
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "iText";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "iText";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns information about a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "iText";
+ 	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+    	/*.................................................................................................................*/
+    	public boolean isPrerelease(){
+    		return true;
+    	}
+    	public boolean getHideable(){
+    		return false;
+    	}
+
+}
diff --git a/Source/mesquite/iText/aiTextIntro/index.html b/Source/mesquite/iText/aiTextIntro/index.html
new file mode 100644
index 0000000..6cb97ab
--- /dev/null
+++ b/Source/mesquite/iText/aiTextIntro/index.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="Peter E. Midford">
+   <meta name="Description" content="Info page for the iText library">
+   <title>iText</title>
+</head>
+<body bgcolor="#AFEEEE">
+ 
+<table BORDER=4 CELLSPACING=2 CELLPADDING=0 >
+<tr>
+<td><img src="splash.gif" 
+         alt="iText icon" 
+         height=64 
+         width=164>
+</td>
+
+<td BGCOLOR="#FFFFFF">
+<h2>
+<font color="#FF7700"> iText 1.24</font><font color="#FFFFFF">: 
+</font></h2>
+</td>
+</tr>
+</table>
+
+<h4>
+Bruno Lowagie and Paulo Soares</h4>
+<p>This page represents the iText Library of Lowagie and Soares, as abridged by Peter Midford and
+installed in Mesquite.  The only modification of iText for Mesquite is the removal of java classes not needed for PDF generation.  The source for the files in the abridged version is at <a href:"http://mesquiteproject.org/mesquite/iText/">Mesquite web site</a>.  For the latest and complete versions of iText, along with documentation and tutorial material, please go to <a href="http://www.lowagie.com/iText">iText's homepage</a>.  Currently iText is not running on Java 1.1 systems (e.g., M [...]
+		
+<p>iText is distributed under the terms either of the <a href="http://www.mozilla.org/MPL/">Mozilla Public License</a> or the GNU <a href="http://www.gnu.org/copyleft/lesser.html">Lesser General Public License</a>. 
+<hr>
+Last update of this file 17 June 2005 Peter E. Midford
+</body>
+
+</html>
+
+
diff --git a/Source/mesquite/iText/aiTextIntro/splash.ai b/Source/mesquite/iText/aiTextIntro/splash.ai
new file mode 100644
index 0000000..8c9c766
--- /dev/null
+++ b/Source/mesquite/iText/aiTextIntro/splash.ai
@@ -0,0 +1,1848 @@
+%PDF-1.4
+%����
+1 0 obj
+<< 
+/Type /Catalog 
+/Pages 2 0 R 
+/Metadata 61 1 R 
+>> 
+endobj
+2 0 obj
+<< 
+/Type /Pages 
+/Kids [ 5 0 R ] 
+/Count 1 
+>> 
+endobj
+3 0 obj
+<< 
+/ModDate (D:20050620110320-05'00')
+/CreationDate (D:20050620155854Z)
+/Producer (Adobe PDF library 5.00)
+/Creator (Adobe Illustrator 10)
+>> 
+endobj
+5 0 obj
+<< 
+/Type /Page 
+/MediaBox [ 0 0 792 612 ] 
+/Parent 2 0 R 
+/PieceInfo << /Illustrator 107 1 R >> 
+/LastModified (D:20050620110319-05'00')
+/ArtBox [ 213.49658 330.49756 378.50293 395.5 ] 
+/Group 52 1 R 
+/TrimBox [ 0 0 792 612 ] 
+/Thumb 53 1 R 
+/Contents 57 1 R 
+/Resources << /ColorSpace << /CS0 36 1 R /CS1 37 1 R /CS2 48 1 R >> /Pattern << /P0 29 1 R /P1 38 1 R >> 
+/XObject << /Im0 47 1 R >> /Font << /T1_0 49 1 R >> /ProcSet [ /PDF /Text /ImageC ] >> 
+>> 
+endobj
+7 1 obj
+<< /Length 1122 >> 
+stream
+%!PS-Adobe-3.0 
+%%Creator: Adobe Illustrator(R) 10.0
+%%AI8_CreatorVersion: 10.0
+%%For: (Peter E. Midford) (EEB)
+%%Title: (splash.ai)
+%%CreationDate: 6/20/05 11:03
+%%BoundingBox: 213 330 379 396
+%%HiResBoundingBox: 213.4966 330.4976 378.5029 395.5
+%%DocumentProcessColors: Cyan Magenta Yellow Black
+%AI5_FileFormat 6.0
+%AI3_ColorUsage: Color
+%AI7_ImageSettings: 0
+%%CMYKProcessColor: 1 1 1 1 ([Registration])
+%%AI6_ColorSeparationSet: 1 1 (AI6 Default Color Separation Set) 
+%%+ Options: 1 16 0 1 0 1 0 0 0 0 1 1 1 18 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 2 3 4
+%%+ PPD: 1 21 0 0 60 45 2 2 1 0 0 1 0 0 0 0 0 0 0 0 0 0 () 
+%AI3_TemplateBox: 396.5 305.5 396.5 305.5
+%AI3_TileBox: 31 30 759 582
+%AI3_DocumentPreview: None
+%AI5_ArtSize: 792 612
+%AI5_RulerUnits: 2
+%AI9_ColorModel: 2
+%AI5_ArtFlags: 1 0 0 1 0 0 1 0 0
+%AI5_TargetResolution: 800
+%AI5_NumLayers: 1
+%AI9_OpenToView: -168 659 1 1134 719 26 0 1 11 42 0 0 1 1 1 0
+%AI5_OpenViewLayers: 7
+%%PageOrigin:31 30
+%%AI3_PaperRect:-31 582 761 -30
+%%AI3_Margin:31 -30 -31 30
+%AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9
+%AI9_Flatten: 1
+%%EndComments
+endstream
+endobj
+8 1 obj
+<< /Length 8449 >> 
+stream
+%%BoundingBox: 213 330 379 396
+%%HiResBoundingBox: 213.4966 330.4976 378.5029 395.5
+%AI7_Thumbnail: 128 52 8
+%%BeginData: 8032 Hex Bytes
+%0000330000660000990000CC0033000033330033660033990033CC0033FF
+%0066000066330066660066990066CC0066FF009900009933009966009999
+%0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66
+%00FF9900FFCC3300003300333300663300993300CC3300FF333300333333
+%3333663333993333CC3333FF3366003366333366663366993366CC3366FF
+%3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99
+%33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033
+%6600666600996600CC6600FF6633006633336633666633996633CC6633FF
+%6666006666336666666666996666CC6666FF669900669933669966669999
+%6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33
+%66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF
+%9933009933339933669933999933CC9933FF996600996633996666996699
+%9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33
+%99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF
+%CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399
+%CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933
+%CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF
+%CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC
+%FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699
+%FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33
+%FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100
+%000011111111220000002200000022222222440000004400000044444444
+%550000005500000055555555770000007700000077777777880000008800
+%000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB
+%DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF
+%00FF0000FFFFFF0000FF00FFFFFF00FFFFFF
+%524C45FD2BFFCFFFFFFFCFFFFFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFF
+%CFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFF
+%CFCFCAFFCFCFCAFFCFCFCAFFCFCFCAFFCFCFCACFCFFFCFFD10FFCAFFCFFF
+%CAFFCACFCACFCACFCACFCACFC9CFCACFC9CFC9CAC9CFC9C9C9CFFD0AC9C8
+%C9C8C9C8C9C8C9C8C9C8C8C2C9C8C8C2C8C2C8C2C8C2C8C1C8C2C8C1C8C1
+%C8C1C8C1C2C1C8C1C1C1C7FD0AC1C0C1C1C1C0C1C0C1C0C1C0C1BAC1C0C0
+%BAC1BAC1C2FFCFFD0EFFCFFFCFFFCFFFCFFFCAFFCFCFCACFCACFCACFCACF
+%C9CFC9CFC9CFC9CFC9CFC9CEC9CEC9C9C9CEFD06C9C8C9C8C9C8C9C8C9C8
+%C9C8C8C8C9C8C8C2C8C8C8C2C8C2C8C1C8C2C8C1C8C1C8C1C8C1C8C1C8C1
+%C1C1C7FD0AC1C0C1C1C1C0C1C0C1C0C1C0C1C0C1C0C1BAC8CFFD08FFCFFF
+%CAFFCFFFCAFFCACFCACFCACFCACFCACFC9CFCACFC9CFC9CAC9CFC9CAC9CA
+%FD0AC9C8C9C9C9A6C9C8C9A0C9C8C9A0C9C2C8A0C8C2C8A0C8C2C89FC8C2
+%C89FC8C1C89FC8C1C29FC8FD0EC1C0C1C1C1C0C1C0C1C0C1C0C1BAC1C0C1
+%BAC1BAC0BAC0BAC0BAC1CAFD0CFFCFFFCFFFA1A8A7A8A1A8A1A8A1A8A1A7
+%A1A8A1A7A1A7A1A7A1A7A1A7A1A7A1A7A1A7A1A7A0A7A0A7A0A7A0A7A0A7
+%A0A1A0A7A0A1A0A7A0A0A0A1FD12A09FA0A0A09FA09FA09FA09FA09FA09F
+%A09FA09FA099A09FA099A09F9F999FC0C1C0C1C0C1C0C1C0C1CAFD08FFCF
+%FFCFA852272752527D527D527D527D527D527D527D527D527D527D527D52
+%7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52
+%7D527D527D527D527D527D527D527D527D527D527D527D527D527DF87D52
+%7D527D527D527D527D527D527D527D5227F827F87698C1BAC0BAC0BAC1CA
+%FD08FFCF7D277DFD51FF27FD14FFF8FFFFFF7D2775C1C0C1BAC1C0C9FD05
+%FFCAFFCF5227FD47FFF852F87D7D272752FF27527DF852F8A8F82752FFF8
+%2727FFF82752FFFF5227F87DF827FFFFFFA85227C0BAC0BAC0C0CFFD06FF
+%7C52FD48FFF8FFFFF827A8FFF8FFF8FFFFF8FFF827FFFFF8FFF8FFF8FF27
+%52FFFFFFF8FFA827F8FD06FF5251C1BAC1C0C0CFFD04FFCFA827FD49FFF8
+%FFA827F8FFFFF8FFF8FFFFF8FFF827A8FFF8FFF8FFF8FFFF5227FFFFF8FF
+%A827F8FD07FF2775C0BAC0BACFFD05FF27FD4AFFF827277D7DF85252FFF8
+%FFFF2752F87D272752FFF8FFF8FF522752FFFF5252F8A8F8FD07FFA851C0
+%C0BAC1CAFFFFCFFFA827FD4AFFF8FD29FF27C1BAC0BACFFD04FF7D7DFD4A
+%FFF8FD29FF7D75C1BAC1CFFD04FF52A8FD04FFFD3AF87DFD35FF7D76BAC0
+%BACFFD04FF7DA8FD04FFF8FD39FFA8FD35FFA851C1C0C0CAFD04FF52A8FD
+%04FFF8FD39FF7DFD0BFFF87D27F827A8FD0BFFF8FD18FF7D75BAC0BACFFD
+%04FF7DA8FD04FFF8FD0FFFB5FCB5FCB5FCB5FCB5FCB5FCFD1EFFA8FD0EFF
+%F8FD09FF27FFFFFFF8FD18FFA851C1C0C0CAFD04FF52A8FD04FFF8FD0FFF
+%FCFCFCB4FCFCFCB4FCFCFCB4FD15FF5227FD07FF7DFD0BFFF8FFFFF8FF52
+%27277D277D2752F852FFFFF827277DF8FF5252FD11FF7D76BAC0BACFFD04
+%FF7D7DFD04FFF8FD14FFB5B5FD1AFFF827A8FD06FFA8FD0BFFF8FFFFF8FF
+%F852272727F8A8FFF8FFFFFFF8FFA827277D27FD12FFA851C0BAC1CAFFFF
+%CFFF52A8FD04FFF8FD14FFB5FCFD1AFFF8F8A8FD06FF7DFD0BFFF8FFFFF8
+%FFF8FFFFFF27F8A8FFF8FFFFFFF8FFA827A82727FD12FF7D76BAC0BACFFD
+%04FF7DA8FD04FFF8FD0CFFA82727FD05FFB5B5FD07FFA8272727A8FFFFFF
+%7D52A8FD04FF527DA87DF827527DFD05FFA8FD0BFFF8FFFFF8FF5227277D
+%27A827FFF87DFFFFF852277DFF2752FD12FFA851C1BAC1CFFD04FF52A8FD
+%04FFF8FFFFFFA8FD05FF2727F826F827FD05FFB5FCFD06FF27F8F82727F8
+%52FFFF7DF8F8FFFFFF2726F8FFF826F8F8F8FD05FF7DFD21FFF8FD13FF7D
+%76BAC0BACFFD04FF7DA8FD04FFF8FD07FFA8F827F852FD08FFFCB5FD05FF
+%A8F8A8FFFFFFA1F827FFFFFF27F8FFA82752FFFFFFF827A8FD06FFA8FD20
+%FF277DFD13FFA851C1C0C0CAFD04FF52A8FD04FFF8FFA8FFA8FFA8A8F87D
+%F827A8FD08FFB58CFD05FFF8F8FD05FFF8F8FFFFFF7DF827F8F8FD04FFF8
+%F8FD07FF7DFD35FF7D75BAC0BACFFD04FF7DA8FD04FFF8FD05FF52F827FF
+%2727FFFFFF27FD05FFFCB5FD04FFA82727FD05FFF827FD04FFF827F87DFD
+%04FFF827A8FD06FFA8FD0BFFF82727FD04FFF8FD14FF27FD07FF52277DFF
+%FFFFA851C1C0C0CAFD04FF52A8FD04FFF8FFFF27F8F8F827FFFFF87DFFFF
+%F826FD05FFB5FCFD04FF7DF8F8F826F8F8F826F8FD04FF27F826FD05FFF8
+%F8FD07FF7DFD0BFFF8FFF8FD04FFF8FD1CFFF8FF27FFFFFF7D76BAC0BACF
+%FD04FF7D7DFD04FFF8FD04FFA8FFA8FFA82727FFFFA8F8FD05FFB5B5FD04
+%FF7D2727FD0BFFF827F827FD04FFF827A8FD06FFA8FD0BFFF8A827FD04FF
+%F8FFFF5227277D27FF277D5252522727FF5227F8FFF8FF522752FFFFFF27
+%F8FFA8FFFFA851C0BAC1CAFFFFCFFF52A8FD04FFF8FFA8FFA8FD05FFF827
+%FFFFA8A8FD05FFB5FCFD04FFA8F827FD0AFFF8F8A8F8F8FD04FFF8F8A8FD
+%06FF7DFD0BFFF827F87DFFFFFFF8FFFFF8FFA82727A8F852F8FF7D52F8FF
+%F8FFF8FFF8FFF827F8FFFF5227F8A827FFFF7D76BAC0BACFFD04FF7DA8FD
+%04FFF8FD09FF27F852FD08FFB5B5FD05FF52F8FD05FFF827FFFFA82752FF
+%FF2727FFFFFFF827A8FD06FFA8FD0BFFF8FFFF27FFFFFFF8FFFFF8FFFF27
+%7D277D2752FF27A8F8FFF8FFF8FFF8FF27FD04FFF8FF7DF87DFFFFA851C1
+%BAC1CFFD04FF52A8FD04FFF8FD0BFFF8272727FD05FFB5FCFD06FF26F8A8
+%A8A8F8F87DFF7DF8F8FFFFFF2726F8FFFF27F82027FD05FF7DFD0BFFF827
+%F87DF8FFFFF827275252F8A8FFF8FF2752FFF827F8FF2727F8FFF8FF5252
+%52FFFF7DF8272727FFFF7D76BAC0BACFFD04FF7DA8FD04FFF8FD0CFFA827
+%F8FD05FFFCB5FD07FF27F827F827FFFFFF27F8A8FD04FFF8277DFFFF7DF8
+%27FD05FFA8FD24FFA827FD0FFFA851C1C0C0CAFD04FF52A8FD04FFF8FD0D
+%FFA8FD10FF7D527DFD18FF7DFD23FF52277DFD0FFF7D75BAC0BACFFD04FF
+%7DA8FD04FFF8FD39FFA8FD35FFA851C1C0C0CAFD04FF52A8FD04FFF8FD39
+%FF7DFD0BFFF82727FFFFFF272752FD21FF7D76BAC0BACFFD04FF7D7DFD04
+%FFF8FD39FFA8FD0BFFF8FFF8FFFFFFF8FD23FFA851C0BAC1CAFFFFCFFF52
+%A8FD04FFF8FD39FF7DFD0BFFF8FFF8FFFFFFF852FFA8F827527D272752F8
+%27A8522727FFF852FD10FF7D76BAC0BACFFD04FF7DA8FD04FF7D527D527D
+%527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D
+%527D527D527D527D527D527D527D527D527D527D527D52FD0CFFF82752FD
+%04FF275227FFFFF8FF7D27F8F8FFFFF827F8FF27A8FD10FFA851C1BAC1CF
+%FD04FF527DFD4AFFF8FD07FFF827A8FFF82752FFF8F8FFFFF8FFFFFFA8F8
+%FD10FF7D76BAC0BACFFD04FFA852FD4AFFF8FFFFF8FFFF27F87D7D272752
+%522727F8F8FFFF522752FF5227FD10FF5275C1C0C0CAFD04FFCA27A8FD73
+%FFF8C0BAC0BACFFD05FF527DFD72FF5276BAC1C0C0CAFD04FFCFFF27A8FD
+%70FFA827BAC0BAC0BACFFD06FFA827A8FD6EFFA82799C1C0C0BAC1CFFFFF
+%CFFFCFFFCAA8277DA8FD6BFF522798C0BAC0BAC09FFD0AFF522752FD67A8
+%7D7DF87CC0C1C0C1C0C1C0FD08FFCFFFCFFFCAA8527C527D527C527D527C
+%527D5276527C5276527C5276527C5276527C5276527C5276527C5276527C
+%5276527C5276527C5276527C527652765276517652765176527651765276
+%517651765176517651765176517651765176517651765176517651765176
+%5176517675C0BAC1BAC0BAC0BAC9CAFD08FFCFFFFFFFCFFFCFFFCAFFCFCF
+%CACFCFCFCACFCACFCACFCACFC9CFC9CFC9CFC9CFC9CFC9C9C9CEFD06C9C8
+%C9C9C9C8C9C8C9C8C9C8C9C8C9C8C8C2C8C8C8C2C8C8C8C2C8C2C8C1C8C1
+%C8C1C8C1C8C1C8C1C7C1C8C1C1C1C7FD0AC1C0C1C1C1C0C1C0C1C0C1C0C1
+%BAC1C0C1BAC8CFFD06FFCFFFCFFFCAFFCAFFCAFFCACFCACFCACFCACFCACF
+%C9CFC9CFC9CFC9CAC9CFFD0EC9A6C9C8C9A6C9C8C9A0C9C8C8A0C8C2C8A0
+%C8C2C8A0C8C2C89FC8C1C89FC8C1C89FC8C1C2C1C8FD0EC1C0C1C0C1C0C1
+%C0C1BAC1C0C1BAC1BAC0BAC1BAC0BAC0BAC9CAFD0EFFCFFFCFFFCFFFCFFF
+%CAFFCFCFCACFCACFCACFCACFC9CFC9CFC9CFC9CFC9CFC9CEC9CEC9C9C9CE
+%FD06C9C8C9C8C9C8C9C8C9C8C9C8C8C8C9C8C8C2C8C8C8C2C8C2C8C1C8C2
+%C8C1C8C1C8C1C8C1C8C1C8C1C7C1C7C1C1C1C7FD0AC1C0C1C0C1C0C1C0C1
+%C0C1C8FFCFFD0EFFCFFFCAFFCFFFCAFFCACFCACFCACFCACFCACFCACFCACF
+%C9CFCACFC9CFC9CFC9CFC9CAC9CFC9C9C9CFFD0EC9C8C9C9C9C8C9C8C9C8
+%C9C8C9C8C9C8C8C2C9C8C8C2C8C2C8C2C8C2C8C2C8C2C8C1C8C2C8C1C8C1
+%C8C1C8C1C8C1C8C1C2C1C8C1C1C1C8C8CFCAFD34FFCFFFFFFFCFFFFFFFCF
+%FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCF
+%FFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCFFFCA
+%FFCFFFCFFD89FFFF
+%%EndData
+endstream
+endobj
+9 1 obj
+<< /Filter [ /FlateDecode ] /Length 10 1 R >> 
+stream
+H��W�nܺ����FkS�F�h
%��m
���4(̈��H]��|}ɹ��-�ԧ̲=�y[k�-���
.�o.�ːo���S?\�J��v
��6�ݟ^�ʯ��.�3�M�]�
{vg&3���4�s?��䬪�9���5���
?\��|�(f)����F!
+��U�W�sW7�Z�_�H�b�!�� �H����ތ���\�4������eFvHr�`Pٯ�馻�_�q,���+R����5z4�մm���V�>�
Q}7!��eht}q�otw��֘�ԯ����R5�E=���_�K��ӈU�{m���z��3M8��7���t�`}��w�f�8���ΝH����l�o�l~�:Ii���N~Mr���tn��Gr��
+���_��c�xvh��ٟc��W�:"1Y�e��J�D��Ӑ,�F�x���gv���G���&㤇%.���{��E�|��Lx"H�E��h�1_��۾3^�|�
�� IY�[���
O]cuvM³}�צ�5����k���,�x���Lpp�ΓK�,�u��7�/����n��{�q��`iFR

+�xA8$�1FщB���h;v?)�w���Ь��ʑ�|/���
�f5]]�$�B�C�
+v퇠�\�Z��<4�Ѵ<"���|������?h�&�y�W]]���h
 ����m��}�k׃��m�.��4���vk�H�zП
+aQF�1zF�����M�jZ��<�vj����}X@�#��n6�W� �<��+��?^��W�ɍP㇚���0���7>�9�i1��>����}l�b{��ه�>t>�t>��z�6��Ac�
+|�����!?
I��mk&j���~��zV�o���f��ߢܭ?LU�6=|�~��.�~��3�+z;��
��x�l�n>�_LG7�����x�<L�t�^o�[{��h߭�i6�=d����j��]�]�J�p���n�ﷱ�!���x�=O�;�� �֞|�ꕡ�#ߙm�U��z���%j6���I�7~Nwwl��u�9�v�����󠽢�yL�zq�u�rػ�sS���w��%��kk��1����
6�n:}��6	h~b���:���<=׾��Բׇ�kt�nO�۟��G<����i�|Wm�dž���bl�j���S���K
+��>��a��z�7��'�"
�Jc\�X�R��u�8�qr|��KW��n��ה+�<}7��E�
���~���?�����)�
�����X�v9M�)x1�f��&�M��ܘ^N2�r�P0�"��M�2f�?5����g�Cm�;�}=�P�8���3Ao7f�I�DBQl&8�[
��ۅ�hiZ�aEl�s.2�7ӭ
+��
+n������}�.���=�q����#�g�T�[�S�鍩�z�D���F̃Ij<4�� �D@
,�Hd� r@P�Be�2�����[ 	�
� �(�� Ŕ]َ��'@� "
e� r@P�"e�
3;�~@� 2@ y��
+�*@�ʞ�n�.m�.�'R� ��APU��j�,i��v�vi;:���@ $P %P*Q�p�Y��v�vq;:�d� r@P�Re���spfOm7nW�Xn? �
�P�V`�
'?w��Nr+�rB[�N]�t͝�VK�T��~�W.s�I�V�tbN��S�;Mr'�B9	"G~�h�
��
+�Gp�M
���S:"+G!s�-
gܱ�;�,Gʱ9^KH���

%�����C�\�,�D�g2+�2�2�D`0b
'$Ё�L�
)
+Q�J� Y���&I ϳ\�y.�"/�*W� �0P�̤��������Bv1�;���˃"+D��(���
+��c�~
�%P��Y)ʼ�eQ�eU*�%CZ���J+^e���JVEUVU���6g�c�eN��1��U����Y���b������Oڮ����.9��q�u
>mE�,}C���������Q�~Եu�G]���5!.�H^-n���^ޖx7�Ë������6`�|���^}��LJf2�
ͺE�{���
+�O�R8s��Kp �'	���Sa�@Z	�$H ����� �Ua�@z	�%De@��,�P��BA��I�(�&��	�!3+B� {	�%l `[$�G
�0��oJ�G�G~��U���C�`��0��!9����1��D�)���%�,�,��S�{�Gp{��_"$2A #8R#A��H�C�
+��o櫦�m#
���t1�\
��f�A� ?�\�{����
���a;ؿ����-6EQI�DxƚV��^W��
4jA���@�4+@�L ^#�׃�-�X���Y����A
G��[��+��
>����
B�Bj�2TP�JQ at 12h��$-���U��RS at r2
��C�ZHR
+i� Q%���de�A�VA�:�Jm��q�j�
.���ō�j.��ߠE��[fx��˗篸������91�Bw�"
+�]s�T,���1,=���kF��m�F��yV��s�r����4�؝�Sr`�zNϖ�T��c��]V8u
+�Vpg�����ݱ�-�y�N:�y�~��4茨;�K�ޞ�e��
+G�a���`�s�@��))"-Ȋ%/Rf�ɑ�#%HJ�@����%N��TIɒ�eIRff��H��&%NJ��S�y��H,�G�|��Ȳ|o
V���+K��9��� 4�G�'�VhWhR
�n�j�B�B��)�N�ۿP��,~���Q� _ O!�a��1`艎h�&е��v�ٖW
+��ނ�<����<����F4u�zq6���Ԫb���ɩ�T�z�*I=Mg����"����çl�>�[`��
+�<ѡ �:�N�;;#���>�~��x�=��f���"��O;b�^��Z�.P
+ǎ=3�8�� "��Y䧑�Gljg��F�����_�Y���f�[Ǽy��C��uYg�uA
������2K�a��9�b�j�Ɇ��Xف�rԺ�9�b�/K6O+�zYZf؜-3L�%%�b�����Jv̵=5V�wb��	wq>99�?�#�Gt��j>Z��[���	�aL�_��5�Q��T�����o�����v��`�����/�ϖ�
z��ة�S�������[��� �:zQ�������Q�7Qm��K5�j6U����Q6�Ş
mY�:��ga'�4gI}��u�XA�ϷWX8_6ǂ��V#���>���X_��5A=B1
+_�5h�����|��[�q
t~H}ĉ윹i��Z80ZR�8��9iX�`�\G�@�;�
+��&L�
7�h/P�
+���3j� upJ
ӄ��
(�D%j^�W�wm�j�b��N
��yY�P�Pa�WN˻,nZ�XX�5��$���%M
�(gZ�U%�$�L˸,bZ��~�Re���&E��=��Vf��5֖Ȭ=S�h����*Eb�fW�l`m��8���0�ڠ�\�Fr�� �
,�{����M��1����7{l
S�{�=r��lr��]�9v>��9�3��gm�s
+�Y�97�\��DU8KO�f��G��I$���9�N�y��q�K./Y}`i�F��q�1�U�}�ѯd�3��c�·y"F��V8a>�[�ĆY�f^ťs�ev,�
+3d�
� �u
cs"����tO�
+Q.\��-�lk����`�s�>�N�Hx�M�L+��oy�p+�����`SW��49�96��0��� )�q䘙,j�T4���Y=AG�p�@��J��S��iQ
+�����Pt
+�~;T�v�����ڛ��|�C|��ml>��!�1�i>����;#��pI���¥�e��	��B�M�t�HF�5
+�0 �t��
+�R�Td�2 ~�{�y|�	q�g
I����fu�QUlR
���ؘB{"l�oI�ac+�؆.�@૟���sՅE�%/b��X�u���Y�ok[ź��^d�Sdk֌3i�~
+h�lN�ә�G���Q{:�]�&�ؚ�vmf�zG�)N��(��I�>C���
fI����9��
�պ����x����4U��/UV��)
]���������ܱ�	��2�G����ͱ̙�Mn��[l{��kN[��O������o�2~z�6�;7������YТ	=~��J�, ���5���Y��l
:T,
��J��
+���~
_�~���������{���u~�����������Q�ox���=��,S3�P�j��P�ٔ���8��؏�؎
+��+�q��X �e{z)��^�-����r�`���"�{�P.��
+��c
e�
!3�{ԥP��ַ�!g�Ѝ�Gn�nxn�򨍶7���pt�c���A��n�

+�w0� �d<}M�kc�������Y�~�Tn��:
�L�
�
4KЕA,��A"HE� 
�G)�̂�T��2�Bnz�Έ�� C�.UЧ:��2C�����C�
D�B�
D���u��7Ar���(Z���H6p�
Ts�zN `55Y��W�m �
dw��N��9��@�-��A��u�
 ��q�k�����
+���{<����b at 8
����p�'�
�`�X
�A���w�<����c"�h�Q�����0���	F5�H3m#�a�5y
F߀�=������bF:��3�
��{�+�1T
+��Őu$_K��ݟxa
�1�k�
����;�m�{
������_!��t�g��⼧��X��q��
+�F�U�7dobri�[�7�o�f�X��7,�<�
+��{��Vz�{��Vz�{��Vz�{��Vz�{��Vz�{�S֤��)���
�j�3|��%��i�9�u�ӒsV�V�%�֭NK�Y�[����Z���wR�c�Ҥ��S.��K�=B����.�?	�
0^@LVr6rep�%��NG���q�P[r�qZ�͆o�+�@����l�7]���7�܇\ZpkO�L���r��="��=>�ɓ���LŔc,?�^��_=�^��_=�^��_=�^��_=�^��_�g��j�ב��}�wd�ox'�\}������
��?Y��>Ȼ���u�toW�Œ���%�b��U~��ѯ���*k��r��U~��Z�(����\����
+Ge�Ų@{��>y�VY�Z��fgv�y��j?��O�|������ݿ�=���:����}����?��8|��������
lhݓ^��.1/%�
+n�	=�]R�H�#M�9hfj+����3aI�HZO[O\O]%���'�Rؓx��3Y��l�|VFkd�Ф�Vb+��ܹ
\)�$Ht�: �2�!���ܯ�K
+�/P,c�b�	����N��霑_�@�����ղ㸍E����7
+$�)�"
%2�:�*�FUh�"�H����+ʒ�z�RL� ~H4-����>���`�@+�{@���� ~y^�q��/��y�`s��oª󻶊ՍxWh#�,
C�yNo-��(����!���@<[�h�	7!!�
+�h@��!��j�
+�*�$�Y�c
+��B�=8/��;Hy�"I4�Bc��E�{A@�w`��%�`et�	5�ŁhPN
��&a
%�I�(
�ʂ�<8,�@;�ZBEH0��P�zPb�mv2�&��o*���Z0��pl�M�J	�U`&f� ]~�����v%(\5:{�l���
+����&!�J�����>x�D�^tЍ4�����Q�3t�*�ΐ�9�/�9{�i8�3BAs�/pX)�XP����Q�
6v at U �=`q����o�������10��Fg�Ir`؁�G/t�EᒅΝ�fg�]�B-�|3hf��.A�fgP���@_���^����q�2}�8�nך
|��
�
�Ė����hm��썚Z
օ�i%�2�:��u��۝K�siy.MO�4=מ�&�g4;���%%q���ZC95
�r(ʱ�r4�)�L�L�SRU6XpZJ�;:M96�N9<���8B��c@�穊3�����cяe=��P����j;�Ӥ`��w}��A�
+�3H��o+<�>F�hT�cČF5;F�hT�cČF5�O��BWlh�ׄ�s��lނ�c���Ŧ�2b�.
� 
�)a�%
+R�Y
d�B
�%E�B4���
+}&w���Sq
�
+aoؘ���5d�!y��E%v���>�-y�Zm�Y��Ȕ|�g�>V��2�bRɄ"�H:&��i�2[hf	�����c0����7|G��
+w������h屓$
�b�1�����܈���{���﯊Zs��}�Qi��)�e����SHŔ�K��N�15�Hm���9K	b
+�J3j&��9�16�-[�Ș9��S2��Ң}��6uĝ�0+��ұ�O�,^1��Ҹ}�:���e�--
�l�6&�侗�n�Yw��\�����I<U/֝�I�
^��W�O�����w֔\Q�	��N�>���t��ay�'0��!}�7/�
�̘�Z��d�#y>ɷ�%���Z?y�&-�
���?��<{�

}j~1�����~y����w"�|��:�����o��_�xy>}-�~��S��>�gl�(��M5�W��*���)FX�6�ذy�l�5�r��;���
�g�V��슳f�{ ���h���v
���h����Lh�J:v#
+���C��l6"�
,'����)t6H�U��.U&Es,���a�#'���
:j��	�㠫���)�!�{&<����&�֟M'�}
+��fa �
�t+(��#-#�E�(GÇ
T+P��Կ]���^����,�
+���{���8H{���8H{���8H{���8H{���8Hky����O\�ט��;�Km����ч��=4�}l�#�)�2!��0����-/0�x;�N����5�hk���'t��ggu,>�:������&�}�
���;!��м�KD��� z�
�`�
+z!�Z����o
A\j����T
�����0Y��P)(�D�Kh�J�h
�f�pJ��x�!�-䰁,:�c
+�Ԑ�
+�)�&"d�u���}���z[Aw�H������]C�5��p
��!o!�
+��A�k��T_� \@7�
+<܁�K0p

+�AA�OV���h`-
,F
+��a9*������"�
+�%
��§��"�o|L?�k|�&����0=̏��0C-LQs�`�j�%�R��D<H;%�آ���X읰�
�?�N�
�p�`P<�:`�;�}�e�ZP��hZr���hZr���hZr���hZr���hZr��&�o�k��e�6-���r���~9#l�]���� ?^b��:�6pmHX^���C��v�-n��k	���p��fΥ}�����qY8\g
+>�V?`O�~:��[��A[6�F�D�!Ц�܈�	WEj�9d[�. ��}�L�I�*I��bMs�1��9�D�
tD
�i:"�4=���6���f�'/*i���qF�N��\�7�_}'y2x"��>}���s��L�H_�7�|?�Mf�
��(|�S���?5�bX=�qsh?ce
���X{���az:��P��_����
SM�omT?O��j�ތ�N�2���>5�������?�<{y��?^�~{
N�t����/�<���S'�#͝���)<�P���wQ�.
+���Nw
xG�ȩQr�Ә������Z�c�	fT�.���,���.b�l �

+�c�\�������Yb
��`],��c�֫ú%��:*��1����X���	�$�
+;b�3;�S;�a�:Ab'v�`g-v�c�v���&B�KԂBMԆE�x�J@�t��y��%��2�-�󨵀��P{���
+��Q�uc	U�Q�UۡzS��
+�Q�5*ܡ�T|�ʏ!��P�#4:�F�8tJ��i�9�M�	�R����=��k
+z�E��.E�^��Y�G
z��ѵOk���EW�̳�'~��~9#l�]���� ?^b3D.
t�Tm@��)6x�}�]��~�ƀ�V����
�
��9�����#�
m��8f�jM�
��&�q��[���
e��r?��o'�I��L���v����
n�kv~
zB�A��q�h��z@��
:"�Lc
�{�����=��CG�i��rO/�w����
�	�{O�
��Bf/9�^_�"�kJ��6ﳈ
���G>\�Z�Z���
+f�"�2�_f�V��V��k�C�7����\P�4��G8�E�hA
�+@&HE�\j���4*�����q�F�O�w�e��b��(��`��A�A���`�n
��I.��[�H��[vw�'���*��hJ�W���Ay(N
j$�J�i�Ji���jy�׊'�3	Y� o3dNC�,d�C�V<=�
�yd�F�\���頝=���	�:Cg5�Bx=x�:p��0O�B�!�V;��q4
�.��~��k(���{8�j��	k�`3�B�2,���BV
��H72����,��q� VG��I�4��fx��iY�����>S�0�	&7��4L����+�+J����ᖚ���]��qo"�,Ta�X�Y��
+�������'\n�������~;�	՗��'�G�e�(�
L��-�-a�
��[�;J[��-v��n	[�(m���Qں%l1ڕ
�gJ釈�u�i��@�C���_@��`�E��xÄ�^f��)�}���
+'�j�zS}�	[@�5فz�̜�ĸ
|��xà�ٻ��?�,���4��gd?͵Q4��J�˔�
Tq(W�aS7��C��h�����!{`
6�3�84ϸ�tE�g{�6L�3�84�
.�
+�U�#��n���L.�w�'�a}z��������_��O����~������o�� ����[\A
+�T�\L$�I�R�Y�%��
�х��/`[�g�������]�p�"�5	�G躄���Ǻ��a�
��ü��a��=,�\Bl@� *d�������
u

+K]a:���'�����7��i
dB�,��tBSI*�Ҷ�t�~�c��جР�Q��a�C%DG�3�3�E#��s�ѣ�Q���h�t�=�%�KY���0{g��D{�i�jCm��l�k���a�--g	�T�'�:ޏ�}�xO����z����m�~��o�l�~3���m�~C�]U�
�"
�\�2�ĥ��^��m����r����������f�TV��*TkT����
+�Ju�YF�jk5k�mԵ���3D��{wݻ��]��w׽��r�_?�Jj�'�v�7<^G5�A
������}x�P�f�B-8�
+��!�>qmL���4��
��dF9��>��/ܫ|������W�������>�O?������ӟ�
��������w�<=}���a�T�����KL+��
+߼j��ks�����Ô�^*���%�}�
���r%�@R_J,�,�Jh�b
�cD�Sz֋��h�
�u�4Ex�0�:��)i9V���j���,L3�8�M�dFlt��d���b�5�Zg�
+���8s�I7��)7�Ob�u�y���s/��`�3�A{�w�� َ�$m
+*�a	�lp���r
e8I9MQ��
%��RSJH(s�Q�3G�vĕS��znj|l�l�l�yce�e�M��-Boܬ�<�gc��ѕ
д�
�/&'�k�؍��@�B�D����L;UO��!$P�!?>��kH�F�	[������r(O���}���c)�Tm*�\˳EۭH5�R�Zƭ)���]�=+�&0��4�i�
j�J��]����;�x����:����W��E�5���}��׬h�{vͩa�o�i�=��>�����Ԍa�Њ�;L�`�	�
tH+.�pa�[�q+nI�k�(]@	
J����
NM�H)��H�j p%J���_�|�4Y:H�1e0��rq����oǫ'�z������/�W[��͜����1'd��=�<"u5���/�������
�|�?1��N���� ����g�إ��X��2��s��Ob�W�SX�lV��(�R�QNR!\-���V:�e���# )*
+�[ t�VVs�l�������=�=^��X��La/�=��
��K�K�/�ϩ
}9���ע_
+� ��B b CLY0�����	
+�BK��Q>�3֊�+�q_��Rޗ��v);�C�G"�I��Y2��3�:)3�a���6䒽Hu��������f�:�|�kL�f�3ι�����3j��r�
�<�G��
��B�S(zHP�1���9C+?������9
5Ya�(�̼\*'}�d"$�QQ1��=0�O��wD��j��i)�D��қ�D� ᥬgi�rN+�!	cm7�
+f�R�#�)���h�=-{�Z�+�퐄�`*�U�-U+c���`
\�/kA̐��,��1L�`�X*4֍5� ;;$�T
�I{�&)Hǂ�6��< �G����}Bt��A�"�{���F��`x��?A�fȅF`�x�D��H��#�J,��}���{*j�����
G��+!f��o��fd�H�� Y
炥`k
+L�-p����:�1c��V�r�c�}��ax!a��4Ps
�
!_'+!�Xș������uU���Y�S�d�ԊR�Ns�#&d�'���$L,b�'�I�h:�h���I3�HE��dxB~�ty�셂��%'�N���z�$=Y|�I�vt�
��{g܋���Hz�L�L'GY�D#U�(o
�>��gO-8�_�O�f�h8�G]:�=.ueB)���'��f��S�gt/
��
����qJ����.��<Ɏg����tG�������=�9��y��v���6W�۱�!�����`7���<�>�y"J�{��A
b���"$��"�U�c���|������������� ���
+�`���4�ẍ́�-`o~��L��,aY��0mڣ���*	r��en��U> 0�)$���!SpHQ�1�2
9r��bH�#)�����S&oNޞ�M
+:=EI���,�pK�!z���K���S�'�
?����J0�T^$9ﻒ��.��t�K�\HT�T�eY����p�< K��

��ހ��AwX2��;�
�
�3�s0+���Wi�]9���K$��+��E�la!F�($=!�tg�E���s���]��n!x�z}��]�[.�:ֽ�]��bT��x�
n��,j�t������h�/ɟ&�S'�;$��	��
����qevhG�='��D�>�~�#8|�G=���
�O:�,�q�Č
\�Y�+�UD��H�"�Dt)1I"f��
����
�0�92w�1I!j�~h����� K}�;4��
��4�)��On���4.�G�=�ŔsN9�}v�f�5h�	
�H�
�cJ9�SH>�d�I:i�ʓ�;�+�b�)� >�h��h\QOL�R�R��<a}|p�B
#�Yy�M$n�E4f��'�
���b!�`�o�'�������k���r�a���c!R���Dm�� [...]
+
Ow��k�Qll�8��"�� b��ؠ�
V
��S
��*�
�
+�EF8�ئӎ�f;F1¯��E�̛�ҰoR.�妖YK�&E��k�
��p�Z�B�"���|ϝ��Q/C*xa�u�4!�a0:CN�6�7jpt��&�6�����s��n�:sǓ���]���t>��\��G�P�
n.�ы����J��X
+�S'رP =�<�(�c4��]�HmՀ��� �H{�OG��3��f�x������(�
��uD�?M�
+N���JB��-P<{�����5��S@�%]F��P�l�)��/�P�!E���(�
R}�
��9���r�o��[��'>.�<
zDP�@��>����i��L�8�f�rd�B
�yId
�uhfG�;�����m*�6}.z|���	Q���9��c�"1�e��M��>?�
��ks�gi�������hg�
>���8�_��
z�օ�
M
	���m�QTO��2j�^�q2.aP�"�B�����(��[F���.���\C�#�8��n�
C��֤W�IMz��/��<�<
+z�9�13O��7��Փ�o���ի_�{����Շb�_�~s%��?����|��ٰ����o~��*�"9��]�P���Bv@�ߝ�s>'
�p���Y\���|:��
N�ӎyfb��
+fv'�j{�$Y1	�?�y�8U��c���d�a�\�*��UR� �P�L*Q�D��D�q+MTm
+[Tm
+۞�
��=Aݡ)h9�Rx\z�m]�
�����ūo,[����wo�>��z��g�j^��>��~q�/^|�p��
+e����w�3�x�*_j��8{�r�Bl9>S#��V�ǿ�����_�E����3���\���Bk�g�<]�#�
>+��T at yz��w�c
+��x�Z\^�桅
gG��4��=��K�-L��b�o4������Af�(�����:l`�2i�ƽ� [vXc��p[��`�M&��+{X�z͋�r�_2i
����Z�N�c�7�͔��+�
���������R&밡dS/�m�ޯ��R4�U��z�9!��U����5�W�4�x+Y�
+<[&��"n����m����W�ʌ�.�l��
ׯ��
G ���V�z(��:ܹ��LY|�O&�+��[�#^�{�D<�S&̓%�y.E���]Y��\��K���*��Qϋ��!�$d)6�L��"n%��lp����W�m �ڈ�i_����W��d�
�*�Ve�^�;�9����%���s}��$�gI���.���$�?�S�h��/^�)/.�~����/�(
+w������ݑf_���FǮ����K����D�Xꃠ;|
@��o���r����j���A����}����� ��O�gU�Cǔ��h��<s^��L�`�i%
h%mB*�,n���j~LM#��옳q�a{A ys�� r�P.�
+ō99i?dH���Q��ӭ����&6?�ñ�[
+o
���d��q:�h�`u��8jnðVMӘ����'�l�{�m�e	1�Q�D�خU���"1��k�E��Ԍ��֠؄k]���ct�SҦ%��4�t�-��L�MGM
�H
b�%"��<h������Ƅ=X�(�򭚭��
+�	���"ub���G�ŷ����l!B5�m���
+������|��e�5[)F��5)wꢘ�&oq���:}qb��
)���(t��D��
Y��z�E5\
+�џ�b��`�<@�@J'_`ϣ���+�B��#[�v��sS���Z��ї�!��%��[���e���l�#��;�w�T��ʎG��ph;}Q5�ƕ�cR�(�f���2�N_��f����c;}q���0���ח "�z���
+,T�bH�P�u
Q1�[4s�oB
6V��h3����8�˜�@mu�F-�9bnkK����mU�e�%�b�1���D���qF�U�Mc�DL6����h� ��
�P 8�h;�N 'i=bCI�X����mu����#6t��qn��Y�����J,s�͌��/��|4����1H����)�A6ח#"jA�� wez�~{u��˷�ћ��DOd�Z X�B������ref�}�s�[H����v6�=�m�
 ��X�
+endstream
+endobj
+10 1 obj
+13625 
+endobj
+11 1 obj
+<< /Filter [ /FlateDecode ] /Length 12 1 R >> 
+stream
+H��W�nT9}����3R����.���0�20
�-�j�6K�A!���خr�673
�jŠ(�����ʧ���)�9D���=
~N&�i
+#���m�O�]|��q���:?����|:�t?��C1ij�@���e�̀�9��mog��O4�gW!F8
�8J!56δi&m�~�i������󋻧/.N�n��?N�h�����q{�ӭ{ۋ�ox��t�����0 ������u���0�0ߘn=�8?ݾ�d����a���/���NJ(��+Ϸ�կJ�lA/
�ٖ7S��׼����;d-Ϝ\�d+���D
�x��cf���8J!5� �gg��b�闑���dS#[�9�vq昛ʸ�-H�,qe��9f�&�F����P5E��Y��"��oEքU�]�Z�A�J� k^#/d��(�N� �}�_��?[�e�!��(�.�Z���T���sH
&�@[n�zoD���b�GEI�ef��׫�ϭͳ3 ��dS�9;��K�l�qlTl���Ss�\sAѥ�o@�1�6�*,c#Z1H4%i/���ʖ'��&=N2J~1L�j.�q�GM���}�y9{,آ�BY
��4+��L
����$T�@i������r���s���
+�M�ӳb�P].!/
+��q�b��unU�kؾ߿��ARH��Vl�j'�H�Z��F�]Z�S�����̭��Ґ���z5���s >籁F�MAE�m],���8N157΍�7�ׯW�_�D���.bl�=h���
�?��h��a���[��p��6z
�m�;���@
y+6���ٹ��
+�f��~1N�Q�:w����oE��Z�1
+\�Q��� ���R����t�w��
+�׃��}�=�a�����n����ק[A���ܾ>;���w'�o
�8E#
�0{YSH���������#
�
����Oӿ�m������2�
�!���DR��>m���U
+����٨gJr� 7�����
ɭp"��l�ߝ�k�_�R������	N:yy�������v�����N�b��@4{��jg(��G�Gi���L��,nv�X��ep4B:����49f�Y*oz�P@�~FQ3���52gb�..Mhjg6�I�A-�T.�%
�NGJ�e�)mn��N̐M-�{���B�ǂ<W�T�
+&p�z����+]��bÜlsFW�Z�:�.1�@?ާ�z�'�y��6��c�*�
+��)L��
�=.Y8�vn-�T�h\�.�P�-�����b�b�H��6W0�bp�-�q=&��.J��L�Ī��ֹ�j$����y�
^}=�[ͨ��GQ(Y��mh-���=kz�B��j΋W�5rG�� mQ����
+���
+��M����$q3 at k���Y[�c��m1��+���Y�W��?�x~�9}YJ|Dq�_�}���s�Xش�b�����(�Cq�)�ZK,�×�-�ֿY9H�Ua۠}�-|���	E��5�\������]��v���]��eXm�m�oB��!�47�8��\W�PD&mfK�o��z�+4��<|y������
�r7o6��f�����Kj��9�|��s����$/8}o
�y�����ԭk�*�f��mJ�=6P(
���sg���T�Ta��)ҧnk<?����WN�$N�Z��.�KBNp���Nv�I$b��Aa{��>�I��9����;wn�xq�y��⸌
Z�b����v��G�Cx95A"�K�v@�iC]��@Q��@���،��H�߼a�.�I��m:
+
	�2�t	��F`vĕ1N
$k���./ݿ%f1`$V���)�08�U��@
l�@ �Pg8
+f$ 
+L}�����$�GYF$N=� J��.Ӥ�
+�.�6D	�Z�y�l�26G/c��b �s�Z G׺�(�D��7du��OV�CGm�ZB�w0;]��|B���VA�'ݪ��̓����
=�J�&!�� �V��^�`tvrh1�d�wA���Ԥ�Ux��ޯ3Ia�����F`��
I
)�˚�+WW�X��lu,E-F�b
+ڨ,����%�`|'���"�]m���E��� 򡅊{ j��h�)��
���
+{n�>;�'
B(��#k
%��{�Y�J�n'H����x��
4b���.�f
[K1��R"�׊,	Q�8C�j8UNt��,�l��x��K�Y
+p�L�Δsn#0w
+X�U;��y�2�c6BoZ�Ѭ4m�h�a�J
+���C�;�� �T�&�߈YҢ��ެ�Y]�u�4�[O�͖��Q4SC�z2��FBI��d�p Fc-p���hHݪ���_��"��v�֕E��[���M��%���4E�`E3�f�Ҷ�Xn}RS,��2�
+�C*���BZ)��
T�.��sNέ@G������n /��F��Qx�D�ɱP���<f
 =eLQ�DN]�zX�tU-(��I߼��Ąe���7��
��MAV��E��d�U��Fl�
;�����rK��|ט�=#j#q��8�8���۠���5	�2�^�&�b��ĊFI/��'�H�ϧ����r�j��Fo[�g=�M��L�)j�[�S���
�:a�	1�|F�
��Z��cZ%* �+�*��
+k�{�D�C��v��}�P�S�p�b��n��r(���,`.q7Q��)
ͽ��#J*j�v[�s����
+m�(�${�֢�r$~����3i	�!�f�Ǜ�
+ZVb��7ޫ%;�
���������q�ފ�?mPx+�_F�=ɩ���D� �#�>�6���zH��I��O03Sߪ坝�&m�����w&kUG���diU)��K�='��'+NW[Ɣ���W���9�|	,��1[��׬蓿V�
s�K��4��m�w^l��`At����k���ù^��h�Z<Kv�i�U�������(Jv��ܛ�����u`���>��s��9z_�Z(�Z�0�`�
�F�	�1c��^NǴvf*�% �6�LϜ���52=�Ib��c�e�z��th/�c�5�6��>Qi���B�*>�ӢَtAd�õ��[��^�\� �CL�9�y�jL��J�
���a2�~��{փ[-ݪ�}Sx���PP7��i����C��5�/�F𐡁e�z��ӝ�N�U
 �
��?���	B�Ȟ�V3 at I�`3����X�\N�O�4��U��>��*Yi'�"ku�
0v�-ay7,����p	�[֫�Y
�L�x�
k��j�![Cy���
0S~��< i‡�8P
 [...]
+��Ƽ^I�Iv�
+�P	0_�
+͘#	��ڟ������ty?���M�rM��z��W� w|�����t�=z�e�ɫ��j\jSuAZ���)j�;?����
�W{b����0�)_��틨�a�a�q�`��ܐ����-rt����e��#GK��9��┝:
�Uv˵d2�z�oo���vf�
�0��K-9��I;�kmU��� ������{_�\�.��/��4\�4 ��x�H�'Յ~/]ܺ�Z
K�N�
R��[�_?��w�\&���r�*�5Q�e��R��j���&:>�{k������#��3f��@r�.b<�v�M�+{�xI/����:�@�fm͌��	��T7^J��M� b����)��O�\R|�
�}ŵ�xQ�׹|]�=M��}�����
+��
+��B�و�����lz�S,
�S�=�G,�O�t+?���6?/��<" �n��ɧ
�,U�<
��>��v8`{���Z���e$}<��+�����(~.�
+�uKg�=�0�"'X��
��8��+��]Ɣ�X��zZ�Rh=�����tJ{�!Ʒ��xRr����L�,�4$V�#N,��ݰ�����
z�*e���f���|=f�����5���,G�j#O���)>?���TNo�qw�mOu���Vˤ>�HeM�d1[�S�"_u�ž%�\}�Vn�s�p;^@�/8V�Z��	���𣭳���@��:Xu.��	�ʥGׅ�bLW?��3-��(��qKB��|Do.�B�������*�a���TJ{�Mp]�>��2,�N�m}�
D�E�k�_��N�r
+$��^P�+o�D�^aVRI���4ٻْ��T���;�La�A*le�a���󚭇��?'�

�Ѕyq�Lq�a��|tP�2.n"�;9wU�4-��۔�Rb/0�<1���>���h�`�e��DP�h��]n
�
� �L~�[���}�������p�8��mK������W�7~
���
+�3]��n�WFP1�h,� ��������X��Hi���a�z=
+U��S��G�{WI���m,_wx�V<�c$3@�3�|����w���+<��sqpZ=�� �K�m[k�&)���U�[T�;@b�������$Gv
E�S���
+��ġn)f����-�("�ǝ<�>�*�1���
+�@N�S|�W�l��&�f.���9����`g�V�e����	��MC��
��o;�uh����Ћ�xʒt�2�O�E�W�4�v\��`�
�v
+@��OK'k��`&
ն�����2�\
+S�<Ʊ�0�H:���'�u���9^.�N	��ތ�Ǩ�
hIEu��I�
�O�HϦk�'fT
\
�aXh�j]=�5���JC� 
�['X��ö��1g���hR�:�3tU�+˽��R�E6�9d�2jB�#ػ�ߨ�,lF��3��.�x��J�[��o��N7�~#
+����8���ho�KҌ���=�)���]�ꀧ���?t�Z�`v:+�Ny�����7�:-�-����o�|�͒���K=ߛ�kW��#]��
�#����Ϡ��G���w����'�[�.d�
��	ңL�=zP@�XR�\m&}Μ6��i �rs���
���\S�Y��k�;1��6Z�����a�Ì�G��ܪ>���ޚ��Y������P$���R�g�
�y�B9�Nv�{ �&� S^$�N}�%�Ki�Z*�k���u
+A�R�9��ͣ�v'4�+� �
��F�1���|�8����Oƅ��f��bd`ǵl�R��|^��l�-ʣ���T�e� K�ĵ�}M~q�
+A
+pd�K�BsP
+� �J�
��t9r�5s�# �c�W��h4G(� ���� V���
�
+����o=
E�,���z��p�͉AJ`��	.u�{�=��I|��ņv�Yq��
oW�
 F�ɤ^9Q1
��QqK
+�A��R��:��x��v�>�e5�i�W��a;�+�[�5��F������� S�ym
�Z� �2�m���
+�
x[��e��u%����nb@,��f�r$�É�0�llp%`����fw���wV��Ԑ<|t�c]�:�,�>��
��yNS��;;����|G�{�$꺮
�q:�S;�km���
�r���h����bMw
x�y�
+�V�B�^�aq�Y�ƹz��p.p��jx���uG����~�BQD�J��
ԏ&��"،k��QE�P+���tR
�fi ��gx 
��t
��F��`�A����jED��<����
��OPk��

G]\���4�և����ž�Eߔv3�ͬ��>�Y2��*o�:+��)�2���m&�j'H�	~�P��%UXZ;����h�*Ǘ����
+)sA�,q
�m�a
+���W��ld+��-�X�s?D/\`��a;W�c�YO�A�[�+�[�R�T��K��]������Ň+�@Km1�r ���fk�a���5��W�/@-a~���B$DY�ǀ0��L
��#��Lo� �,�CQ����
��i�+��֟��LU�����Vm3�R�����{ǫ��NM���E8NW��0��G�fۓG�d	�@��{��~��gg�0��c=���
+A��f,�������uހ�%������g�͘��
Ȼ�AN,8dܵ����%nO�I �g��; ����@ ntA�N71 +�f����O�΁�*����k�ڋ���o�а���\]�]�!�_��{��9a�ٱ�) %���
 �Mٺ�j����שo��V��>N�z�]���4�"l�pi�
8 XtY��E��Y�[/���v�K��
G�-�a���UJ��L;����y���
`Dt�y��}�ת��pC�{���\!A�v���u��&^�%����U
�{|�U˶Bmv#1�9��a��̗�vo�5n � �.P

#�l��V:“7
+����U.�R��Z at aY�
+5
>fy��i�� q�4"Qj�'���G��-�\ɋ��s��?%�U���UL�7."��&��Op� g���׳��k�/ j���3�ϼq_4 �&����L�u6[�7��
+m�e#kc����F�~��DR6j>���/`�������qH�ƙ8�J���"��䱺0@��Bn�Ʃ'�PWx|�'\��9��s�7 j��ј���3S;�kM��nq HK&ʼ�b�ɐR��cm�MT����.`� �"��<{���Yǔ Q Y������T><��N���Ӄ���}�Y�F'2�R�ܭ��;�$�!�Yr3�l9��ڹ������Ju+��~�3X
9k������
aˮ�g����h��Tg�k��@n�^h��h�QR��T^K�f�ι���rd�|��֨�b���SG��^katm�]��2�����[s� �
+�+\
+�<A_,�C7n�6�8a�=@j����������IC�j/f�}]E
���5N�uIc��
�]�}����v�����b������ʧ���|]
���+�½W�?!�Mո�o�JU�X��Q��9�'���N��"2���4.0HDhh.�#"����֨^����
����a}��K ��[�[ɥ����t)�%z�ku�FnYL|
��F��C����υ�2��+�N��\���y��l�Zz.˶?�Ś�xq|l
+�
�G���,� x�z5]Z�g
]����=��
�/`��wZ4���
+�z}���&��G��5Q]*A�][�{X�P��v�&:a�2���=�����/T2��4v)��c/>�|3�Ě�m�ŗ�)&WE
��2�7����i���������
C�S�
+�k���s�6NO��DJ'(=ל��3�,*�����l��}q%�sT
+�^}�)�ahy���F|t�FJ�0�r���\3��kS�976�\Q����/0�
+�L�Г� �=�ݢ�����s�:�d��A�����g�}*�܋�4�ef� �iI:

�Ps/� �|�����BZL�^n��(�Y�r�
9]k��[����#���u�	8�
f{�)y��V����#��%;��h��=��Xĥq�]�!e�]"���
f��5d�X�^c\�7�a��n��R�&���j�d���F�9��OzW.�U���¦�({=�kE�l�4|��At4W]=�W\(��8�Ns�i� 5>ux�, �&�
+p���}G(�.�);,w�b��
�2h�7JV*m}�5;�F�P���(
���%S�4%��)��
+p%�yؘ2�Z�x��
r��?�����|����������� }����Z������������/������^����_m��/�ȿ�%vJ�7g����J;b¼����	�lP�B� ���k{y���
����(B�nl83�,�>���&�.��Q�d�
��vЙ4@�9�ݭ=��sf!����j�N�>Mur��E%C���>/Z�(�O)p������x���VU�"��k�������а
+A G=o�y��/�AҀ�=\��UK���gX-����ˬ��2��X[䬾鿖�V�
N[�YK�[��S
�V�^�
+�����
R\clw*�I�8���EaV�:����
�9��</z1V�/���A[,۳��z�.n�"���ag�j8P�X q[�mg���
�:���p�
送A�yi` K�d��˖����e��3+_Qt�����|]���j�
+������
M.�\����X����|��7��ߡ���X�i�����r��&�����1��<
��5ꪹ�@/����*�6G��YK!]a �S�M���� ~�b>�m����P
�e����!Lܘ��-`��
+�K�I��֫�U�ۈ�����B�Ѓ��$�ŽPh(�'�MIL�}�h.�������c�ǒ�4k͚5Cqע
h:�v��Lf�uA-I� ("O��%D��cx�`7��
�D���Z	-k2֩]��Y$�ӔH�t�w_�T�x7����a�^��T�v(�k�:�?��YGݦFņ%U�gɄK���5n��Q��=;8R���X��!DA��j�g
+aF�sy�/	.����v-. at XL���
�:"�puQ��B[��~*a�9����42�z �X��(�d<5&5ƒ#��Bj��:!&%�%��W�`�6۴0�{}W
� �k�Mj at xU��k��
P���P��[�A�v�%� ��q_cy�
2,(٠��)h��*�KT

+�[�J���y���
+o$e�6��
0 �n&C/�(�t�~,���U�C0�5��,�-C�F����=�ed���k�.r�����
b�$����<7ۘ
5�.����:)��"�k��"
�,%��m/�q|�'�Z��z���bK;8"R��9��t^]Lm˺0����P�a�ˍ�i
+$Քqw�N�U2IB8T�Tn���Q�b�d?|\N����^���q����jf;;98�,7ӈ NU�@����jf�We��gf}�/M���˹�67
+���Z��nBy#��M��G����	�Hƺe�/��|Z*���U�Fz��f�`�Ŧz�b�RPߕK��Q1˨�?���y֠+�<Y�6W%��M7z��>�R
+��� z�(��`#@�V�
�MDZhT_T��.o�i�[���E�Ʊ�GL�-��R0N��إ9�ɟ���RW��M��ͬ�I�8T��hh
�:��`_�=*ߔ��RkV=�H&N�4�Q]L>L=�
B��9���Ř��)ˣ�U
�Pk8J�b�Rq�J4��#�E�:�cQ�b
+hcF!�g��7���˵�|�'��?>�������Ͼ�e��/���w?���������{~��������7�~x�?
>}��
_���/?��������Ɵ����
+�������H�_?�����6���+pg�J����q�d�1[��������=���*�ŏC�⯊�ȿ_���<��ڝ�ΛE�θHj*�
+�m��gwk�=�[�nh�n;Ĉ��A��m-1x�S�r��{;
�֒�
,oD��@�0�cnI|ba焠6P8ڐd���R��<
+�<�&��
���:�L!Iʲ�A��ģƄ� ��]�Rdo����Sf�9��I��ѧB)��̈�FƄ�(�؏0��Q|��Rߜܴ�ƈ��𧻓KX�=ҊL���D�~tOz�L;Wޢ
�c���=� 
�����������dR��I�z^ ��C����',�N�d�f��O��?��+�j�V���0�h8
+2=d�5Nŗt�� �
+�Z�����YN�
+\�Т+ 8 �S^~�r���C[�7\�7\��7\�tO\�0���8���^�����cd�k��Z,iɆ�%���Z��	L2f��
n���6�mF�f@.D�h@��.�*
.'�T׵1�^M��4�(�T�V(������^��ڀ !g���^_%��RE�չ�xA�('j��ӂsŬ0^���W�L�P++��݈V�D�Y1k�X-O*�X��z�J{+xK��VG>!�ا
+8e�i��l �N����,,:���RYŠ5�1���(��ϱҎUy��c�o�p
�K���-����e�.��-�Z�lC*Mw̉��
+�S��"��
+�8��%k k���R�r�+.xP��*
��V���z��BE�F�E���S�Rt����^��������B��S.@�U���;���}Ҭs�2�'#;�Q�aD�hݍ����S?�Lч�N����d���ŖAP�N�b��0�J�2��F��m7�H��\8�
n����N|~�z�~�α�L����6���
+�Y�'98
�Qc�j�	�
+���GJ��sfّ�'枒�,�GH6�}�ãr�T���JND/�5HW�[3X+b���z��t���
+T�a��s���j���$�})�ӡ��x�-Ȕܵ]��I-B�`[�R=�B���y�?y�
V~�mL�
����
+��
��4����V�Rv�:��Q���즾��#)��yB�#-�>��Y���l��Φr����M���Y_ko���)���n	�s�P]�~��hv|� y����,�����%�5[Y�W�;�j7�}	�g��`-��T�x}Tnvf2�Y���C�R��E>� ��7���U;m�L`";j���Cs��`U�h�
7Rh�Ί�̞�X萔
���
�5���/��={�z, 

@�R��'ǣ
�+_*N�yOV���}p }���5:k�+��
Y��̖VpU	\^
�T	g�����y*�S�&;.\
+`�&�ѵrǕֶxַ���t��[��
�k�=q[cTg	d�K�$kAkY-�y�����Vo�NUM�n�.��c��e'���sAÍ
�[�j?
+��Sܒ^GN��W[7�g�'tH�{~��
��([G�;Jᦚ������Z
+���������-�&WJ	�����]
�����tR鐿g����G�Vn�K)E���
`��>{�(k����k��9���7ّ���U#˪ޤWrn.^֦؄V����ѡ
�u-͸�I��T��>�là~iK�J�3��reU�ZuF*���s�*�af�*G#��_^�ʪ�ٶ�܁�+_%W*֞hVcJ�:�
r�f}���ɋ��u7�Y)|Z#9
+13�r����F}������� X%QSe4x��e)ڋ�4��
��2�e`0☬CR��?�t�s�}cCwjWm;	.��U��F�r#�.]
	��•��
#��Z����3b%��Tg��L}���S{�wWǚ
���c
Q����g��Û�Ɔy��a+
�
q�ӂZ9.+g�%�
+$���%{�0���'��l�Y}(��|�,��=qO=���w��G���$�',
+���V�v�yO
+W��|���[����n
+V#����k�1��w�[gWzen�:'�UUn"�x�v�+�3m;��3�<i�Q�w�ޅ|R�����plː�&RBn��]J��
+�`�E�@�(�O���L#����9
+���
�;�PP�,�G3h4F	Q
Zx���Q9LI�]ك��lJ���2ce�/�=��:���XQ��
�<����V,;����/��KS��(]�`�^0
+cLK��`d
+���Q����F2�@wv�s*3#"#��]��B(
+�7���3
+ �UuۧH]U�C-r��Dt�n^#��]?uA�滍�ڥ	�5[B��%bp�Q����׉�K��aC�
��	�/
�v鋢*wA9�_�Z����`e �D�u�UVs�_(��qT�sf$Q��Z�V�ˉ���R �d�)��s=,� �JfH ���uCj>�а�_X���߃;S*��
:�u̟��}�96��6J
�&V����� ��[�(B_�o�n�$r�B��>:
��
4��=����L����h���
i}i�zPO9�
��kW�,�Yo�1S
ύ���Y���~׵�K}w�Kmp;ܿ��<e��:U_ڒ:4�CC>7����A
+^{��
+E�>�L!�-�A���%��1�4�.
="٤�)�n�c��ń%k,~�\�v�8��iOSc�~�}{��w_����~��o�_���o~����o?��Ï9�����S����|�_�>����?�>�����g�)��������_wL���{����翸���?��g���"l�$�EzF5"�Y��ɏ���+��6w�a��o����z��>l�.�^�_�],�����$�x`{�_24��%�-�0���e��u��L�B{JI2��/4N��{	::��Q_��?
+YZar;�����}r#�r)j���%꙲W��$KF���)�l����B����&KV�Z%�\�
ǟ�"�O��9���=J�냘)��A��h��h��b�����I6��yl�C�(����4rV �W�å9	h��v�pP�F	Z@c(��1N�V���4�1p�6Ξ:0�=��KcNmo̡^{chʰ\L�^Z�S
+�I��	��V�L7��z���,ɖ"�
���������Q�_+ڃQ&0�}E�W�LR�h�M�,����m
����6gW6����\%s
+]L�r-��
��$
r3<7��ڹ9v�
V�ڕ�q.-U�Z��-�Xl��dÆ�V��1�4�ARa
+��̌B�+q��(Sg�F��)f��9jeC�����॰��C��l؁�����5^+��]*��~�DZS����;��LQ���7�⯷ew�>9���ez���5�=ZIj<��@|"�?����A�I��������ώj�ʧ*5� ��7;�J7�x���1�kP��^�w��� PHG����cS�kM���8��d�����,��(��#�U�va�5�VV�|-���JX�bJ�0p�
6r���a��Q�1ּ!�&X�~KRȄ,:^Z'�t��p��Ӫ9/0DĜ�\9��RMW}��h����V�f^����C3�d�n��c�h��s(-&t�Ā�*���$�=���F	gn�Ԡ1�YA��7IA2;��]�t���$��D H��Z�~�M���u~m�W�+���?:��XI�٧]/-���ZC�[�$���*��2t�C��s_��z�ǂ��3�ɮ�t��R��|�
y��p��HX Y:a[�Z9� p��_�4�a��Y��l��)�n��K��\ [...]
+����H%�*ؽj"̍��PC�sJ�(�D�(�U6�XwۦJ���Z��bM#pR���������8�]�
+ /���B�s��c���b�4�L��c5�i�?=��&�)kd9To[8�C����'\ڊ��~��>�u$��mk��6�p>�UA+���V��.w��󶨖QԹ��t;�aA8W�wŇ,%��k[�|=H��+�D�k_�Kr!^�"�u�Kw���v���5A0�e1���kFƵ��09�q�<�(��g��y[W��
zM��.�X>j����zu��9�ٹ��BM\eL�7]^6`8�tG\e&��ez
N
a���|��
�)
��I�O!���7�E?
+o�RG
�������_��P,m
�B��V�O��
�
��)�`a4��u��o=s�$WD���eG���a�)�Q�Q���=b9����J�`,�v��փT��">�ȁۅz9������ʗ[� ���&7U�Ds
�R+S�Vhꥩ��
+��|63�-���0(dr����w�=X�kn�	�,��i�*�	m���ܷ<�/��kf�S�9i����D,���Y�
�]g6*�f�Z_���
��Xzd{:LQ�
+X�\?^{N���(�?��8H��`�m�=):�ڟ:�Kr�e�!�jX��߇'���$
+d����+^[��2��X�Ֆ
+��U�;�<��K��z�0���%�k�z9���17���G�4Z4(�=�a.�ږ�2���e�9���@�E�Y$Ȏ��´7M�R���-Sg6�����*_�2�*f~/Φ�Ƅ�b��r7
�4a8*R
+!�F��Z^=��B)]�=��ıL�������D[
r4E9�|�+9	b�ȉ=
�J�!�NF���g�~�Ě�m����X(�#�#9��(�L��@��x۲�$���q��uh�x�t8��G�W�U~��k�h��u�ދ� ץak�6��-�*cѮ�ٙ���\�
+c�oֵSQ9��I
�������A�A���+
�}h�
^��uh��erk�������V�zY���pda�n�g��V��
!�y�L���<5	mpߔ	SP,,�po3dbӵ2ܮ$;
BcbZ�����[�������ۧ�B
7��
�����oUc
+�J8�2�cIa�=��m8㪾UN���Ԇ�N���8q�JNI�
��<�u��
-<'���
)�D	�
���S�4�%�����]X`�P�7'����\u����(H�z�2�D�6��/�O
����]f�T��Mz¬aZxq���;c�6�:�%xB:~jų�Éa)�P&��R��/��K�n6�)�b,rC����e���:|9Օސ����0���1%�X
+�:6M�&�0>����ۑd
�%�"�=�!�k
+
$ܦ�6� 9jc���L��v祘eH��\L#\�Rؤ,8���rrΝU��(0�r���f�KS0Kk6aJ�
�����;W\�e`�D��{��l�۾c/{���V�X�\(If�󢏴}p,�I8�B��m����^m+r%G�
���"�����6�
c�b��j}A#�z5B�̬3�}�
ƘE�LN���DFF�@���e���PEc�E
`hL��aቨ����q�i
�m|����4��&����{*���>ք���PC��ËG1A�n�w�r�����z:|m��.��iY���K��=U����r6�|�2�n��^9�
5�����>�@ر�L�U��3�*V���؊�%�2f�e�� �H\�R�m�{���t��ҩ�gT�Q=�u�
�/kO�
+��T�^��'7k�j�zI����u_}�1�Q
â�^��;J^nT0֤h�cY�݋r�VT�����������7L.^��l���:��}h�1�Z�R� y���]־^:����_�Y
߹��t�)a�m�{"K����
��u������]0�Z���^ڣW���v�&��Q�{$.1���e��A���- .}�S�7��i24.�
+u�A�����Z�M� �yh
+׺2����F]��CГ�4��7c} ��^}��D
+�W��C�դ�)'�d�w�=��
����h���զ�N�3w��`��K�}5�Y�-f���˄�?��>���Q�G�������&73�\����*���y���2;�z���tX�������T �l(!5�>��#�ǰ$����
ꤥ��V렯�c�E-����Gs�c��
����%���y�@���Ά5.P���G\�+nL�'��(�]����j��֍�G7	�,�
�~��{Z�(cN��l���"�s�ܠ�c�zA��1r^��p��IȄ�}�l��|*ݦ+u�aO	%���U�6(�g
+�2�`���-��K[ɺ�CU�DP-D9��C�.���w=�“KF=`�=S��M37�d�xߺ<�Fsm�/T�\�u������'M>�kB��洗����0
�y���!Es
p&ܳ�pA�h�2D�2�m୒��F�_
+��Ly�S����
+��	�OX��4c[Ε��o�ٕgY�E�|�ϖ	^��R�ؒ�hqI�d{��KVX��8
�ą$u1��{
H$Hu��M��3��l� >1t�4z�bY3 �F�
�y'L���SuoE��~�BF��pQ��
ߙ
���j�Z'{@����n`�5/�Xli���j�[���iRm�AW>T���T��B�x~���˱j¥�2 g[�k������V~
D �L{����J��[�#u���
+��m�
;yV�W7K�j0ƨ�G�I�
+�B��g� ��l��j���]/F�۝&�c�]u�@�H��|���
�=59�t^�{9R$��}�;�(�
t�խF�
}�MU��|$F'�


A��׼v�۞T!���f{o/F��&:
Š9v$sY��z:L�AqV�\}
+�
��_�4�g�_K�[p⏧?����o�����~��W�/����w?}����ן���'3~��o��tg�������ȷ@�[�{��������_����Ͽ9��p��'�@��@?k���$�
���r�,�z������'u�w's%�K�\��B��kl":�
��eldH��Jf�
m�u*f)��?N��Q��=�t��Z�Ԣ��T�q�!�M!4��))ZȦpU0|\^��$
�t��bkif�ε��Vm���Օ
F���Z�_���c��p�f�%47�����sr#il1ѳ`8���/�Q08R
+��Z��jZJa�T�ԷwR7���4���}�_�Q�����0�Z��~��_d8;���/v���|����w@6l�=�hPӗ!=j
4��m�4
+c�

�C�d��)���p}�{CL�fH��l�
��.c�@�b����${��>-�
+dp�
�� �Ǒ�=�̘P`��t+Kq�$�B p�{ Di��i�}\�s��0O�f�@�0%j��~�
+/�t4�����
������a�����9�1�Чw5N%�Y�@�H�>�[)�z����B�1V��U�ū�}J3�x���󃥁��f�̶��S���
S����c�& bQ��4�}�P�m�C*���2�3��pN����E���i����1���Hs���@�lTU�����O�ba�l���T�σ�
+��&ɟ�݂Ÿ�U�!��,��)����#��=c�����
+|&�M�31$+ at ks����b�Z51���96�ŽQ1Ŏ��]��k�}��EE�ϊ*��K�n�=Ψ*� -!�Z �4eml��ʝ�vO�c��
%ᒐ=1�c��9��'
+v/��l)�I)�6Qhf�gfѹ b&D�
�A��vAA;8�p����E*5�|+{�q���kEi���=��w_E�&�gཊq�1�q��/��\˒Y�Fo
�F�Z�������u��=T�8pk����b w�S�
c$Z���߀�g������0A��PO`��7��TN�Oh�l�c�Q�b���(��B��0�"���;0Q��_�Q�������
%�(J�ٌ�6
+�mЌ%0,z���-s!��I�O┴��j̇bT���
+�>.:�t�N
+��f�V�C�>�hW�}��>�q00N��I!�)bB
��̆hB	mWb�re��FI�����	��.s2FQ4&L�H��
ED�Gx�<��Y�z,�JBMf���Q������d� aO��ͫ���
�b`:*y e#�
Vw�e�>��Q-C^a645�O�Cy�W8�#�+`Cd��^����1I�yU��*)ҥS���"ð0#F at lv0�>�O��j.X��(��N��pPD@��l~��I�.��~�A�V]��03�w��)@�yfTG��3n
f�%Q/��*nL-{q��]�d����"��!�6ܣ
+΂��c�#��҆ߧ��!cԭ9P�e��h�
�NE��}	�ptIN#�h��O�����������\Mz¦�V�@f�n� �-���
͌���ߘ1�s at u0/�Y��д�z' KQ����6����W���͸���`�h����ʗ0fS����Cv� 
��/)Ġ���ڂ,ˮF���6s�ˌ��}鯎Q�Rߙ��l5�bQ�L�C�c	I���k�7�&U,L��)`�"�p0��e�<C��mv̪vxv�;EfFb�7~�QV���sjf�ڮ�W�G�Qĺ�CH\��@�wl�` v�w
+endstream
+endobj
+12 1 obj
+17632 
+endobj
+13 1 obj
+<< /Filter [ /FlateDecode ] /Length 14 1 R >> 
+stream
+H�tWۊ]�
+����%0�0��T�R=z�<$tH�B��\�&Lf2��T��i�
��{u���K�N�I�u���n���r�6��~��r �uN3}�MOk9��<�l��5���NR�8K�d�p���mWO|�?�|J#˳v�n�O��<'3��#��æ��mx�Y�/����M��du��N�M���9�{ ��Ҷ��:�3��*at���'>
+��X����I�c���ήl�q��=�c3v>���s:l��
+?�])���������ǻ?��x�/�
���T���������/~������
�oo�z��믟?|��������駏?>������	������>~8�����
+�����3�5��
t������o��? �r��wǟ�Ҏ~᏷ody*
+�f�g�6=1t�
+/��O�1�Ui�ố��0�^����O?J�$n
F(F�i�h �����(j�����S�	��lh��!//�#`��qY���
Sky}��3ΣlF����Ũl��i�SC�ޫ!=��"-L�XEU#V����L#˿�{��� P;B|(��5�<*sȭ�f��h�+u?m�,��;[�9S��}�弲�n�,
�g�����
+� ���pj���(f��6 'Uņ�
+P%
ç���-d�}z0l̀��:;W

�'��
$g���f��Γ���T��LL�y]�$(T��(�ݗ8�`���U�4x?w�v�R΅��ω�
��dY�k���l#0[��
�Dg�tva`�[�����ta�m�Y�@�z�u��,��F'2�δ
0�jk$�֜���-CB5��DŽ���D�ee�E
`��F�Xce��gV[�ʜyR�
���
�A9h�+�yvw0E��0��Fu���"����6�TX
� �`P��z`{��؉r�窌����(n�Y����2K�vTu�k��+���lB�<G�*�r��z��p�����&W���69ω�
+����/A�"�LKч�����Q#��
+K3�O��z���P�����I�p�����lV	Q'�
+�:]��g��U�ִ��%���m��[&
�Ԯ��V�Xv��Ԝ���[۱Ǧ��xPbզ{%@W�-�h�
\{����m�6Dʬv)VQV�lͺ2�4G:����#K�
�l��u��I���M��f
�
�6�+y{�Ht�u���xvᜈZ(p�
)�2��'r�s��=
+^k��+<�k�R�?��f}
+D��"s8=�`)�X����
+e at +d��|�l�쯑���r�_'-��QGg���J�@SzI��R���RpNN��k,��T�
�u���!O�^KE�/�r��v[��*,��S�h�Z'��ț�����^��kBzD�`��(ڐ
��a�W�}���v�����Q�ϣ�I��V��H�J\�b��� �1)�Q̀�X*^ۃQ�U���t�
+��Vt���U��^,��N�Ū
���0�,Tc�.���
��}ɽ���3�����O�-�FÜ���f�;;��7��O��6[j�]��������=�
+G�"B�es�зѦ\�
$��i�_] P����������R�%V�N�	%����I�䅏�^������o��d'i���Ubg����$�N.)XM�|��p��/��J
jl�z�Kf	���bIϢ´����,-�h�gu&&����u�z�{7��h��w�m��k�WN�
��b�����ds6��H6d���.v���A�ޖ�]����B3��\;{�+
+ 4�~��B��z�����-�K�]Jٺ9����m�d� ��V�(��!�
�k��CDZ%Ųs�� �s$qxq
+�Tt���w���@՚��*4��AF{y)]��y�|z��k�5ɳ�蟀�%�2�߳h���OգSR�C_��籲l�V`�/m�X�хB&TU{i�9+2|�$�1_�-��%%�6�R�\���h�ա���{
++� ������ͬ�����4�Uz���l�F�߸2�09�S���V�1��*�XM�(
+�-����D��RҴ�K�
�I걄�Ֆ�@��
�J�
Q�C�)�..���A���uo珠)�Zd
"U.rMJ06V�G=F�-�M�m独
���y,��;��	�P�/)�,_�H��du�Jx�C祌�`�e����$��G�#<pR�e_�
� آtk��d)Z<v���
M���n�e�R�L	��,
+=�G{�}�^��x$-�
=���k��p�Z<R���%�.N0��h�_�#��ШE�V�����^��Ot��{�'
+�ޥ�A�
+�BP%��'�.$�@�SvĮs�̱���*Q�
+�WC�![�C��*�ǫ9��`ь���&�ڥ�=t����^��*�2����$@�@��X�^
���}+w|���O�㉹��2��S�m����A�y�Jݹx?�����M
��Qq	
�	�lE�t��=�u�yg����h[)��
+
-�W�*�
��]�����tVjQ�
+�^���� �*w0��lWKvd+
�JV��g���E�k��'c��tj���`lcIG�
f��U�
+��<���
Ar�#�3�>ĕ]��3��&z���E�
lmV�80[����1k��j��;��r�ΓȵF�B`�
+��ev݌�&h�i�Jfk9$Ģ)e��uc�v�v�a��U)�j��oK
��y~x�*U�V�|H$����;5R�4mЧ�韁�`�攱=���9���`jN�f��ك��
�1!GC����T��"d��VE j%�xu�%X
t5U܋��ノ�ؾY�u���
+s;�&/��Q7�
+�@5��@f.)3�W��x�g�s4u�\]'�*�� C�
Z�5n�X
�$�pgf,M�٢�\D)�`���۶}�\t���9������Q��P�;�y
�X��judu,^�LA}���Ce����c^l75q���P�l��+)���V��q�d������6��i�\��pO
P�.�>�4�QZ��XҼ�[�=E+����N��C?;������G�
���8��)��i�97\y���8�/�`

+����F��ͼC�$;�:8,�!��bb�Nj��Ms�#7;�z<[Z�1^�ooף��[�������
����O��2�N�xU��L:
U�E�۔�
9z��R�>�gؙ&��F�Z�������,\�����X-F�d~�e!�������A��?�VL
�gS�,�%xH�Q�
��;��p���a�MC3�.��Iv�3��b�CTO�kl=(�z�
�f��v��{�
+���u3�b{(fb��_g)h�z]BdF�{���I�Y���|��0�5�fi�G8����ָA�.�l�u��E��%���2f'�jj���b���
+un�uv�{!xmVl+_ZrF��o;C����b�7�an�y��&2��y]v�Vpm�q
+�}�)6��X:�8~�Y���ʜ_uU������\O+�����. <�!�qlǀ�,~�*^
���d���*@�����O �
�'��:8�&.E�	1�f�*+$�
�������%gK��^�j._[�����n#�-` 1V��|\��c���
���)��o���g��O\�)� @�	���6[a�A,��9��9V�G�%8;�ҹ�'����
+��
�h�b����Zv�V6�O�&|t��ST�{P�'�8@.
+�-���N]�1I���W8��k��>Z'���e`�`ܜ���lC�>25S��z� �q}��Y��b�
+;��9�
]J�e���x��z[�[Ǘ������ڹJ��9�ii�z"�u1Zt��c��z�h�uw���VU
��'�4��r!
��>	�r�-��g���
��d{��]S�����QLraF;��R��
�x��˟bםИ5M#��o5v�k�@�b��l7���t��{���AF�
+�f����6^��E�9Z��q
n=�<9��o���ڷL=@t7۬ϔ�Vᳰ��Qt�ʥ6Ԧ�S`��ύL��^�nd��s���Y[��d�E4ds=����m���W��M>��[e�0m�y�ݠ��Q푇U<�YU�!੔����̻���0���<�Uvp�� �v
�'AS���pXU�~$*WB�0)KX-9+=|
+_� }W��
j+A
+�
�\�v��c���{6��{�/β�ӂ�P
+	
9v�
Kp$8A�l9�����+���
+�k�=�96-"�|	ۛA�v�p%<��1���CAiXܣ�
+�e������B�M��m��W��[��@H�:H8#
S�	�J�
+0�smK������K�u�;��bk��D
�ղ��}>沈�V�h���ܥ���4� c(���2��!Z.�
2� y���Uh�Yń��s7̴�M�FMS�H���r5,FS#��U,�)�ڦm
I7��>�5��r�ͫ�z6���\@����կ�M��긶$0�`C���߫E>Q�Ӗu#�(�[p?<
0�ڋ(u б�=�iM�3^����:!f{֙
�||g���Lmx����R6�G	T��z%׶����γ���> R
+��L�^[t��L�n�ͯϫ_w�vK~L�t�;/�%��:��\ĮQٺӛ��;A�����.�^4�����v���n���`)�
�%hB���::_�s�ʹ$�B��}�]�K�
���=�(����ʥ�`�u���k�+�
���c�7��-���PpJI��i�^��5"/{\��
�6T�CŹ]���)ym����K;����]�	=t�|j��'O�O�E=��`�{�yV	 D�T���jz3`
H��d� F�Dw.L��m-��t��������~'�Y���ob~��N*�U��kN��&�������Z�zu_���vYa#V.<<?��Edw���IXN�8QLn0ö�o�o��t
+����� #��#ٴ�QJA�$�8,�;�������!g���
Z�~!n�&7X�d`J�S�=n
+躰t���~��Gz�ă���*�����}�M�&�U&��.�
P�A�)�bW��z�C�� ��|C��ݶT?>@��'!��!��Xؔir
+�L$�e��v#�[�w�}���XȾ(���ٲ��}
+��Rۆ�p����|�F�H�����e��7�m^��=sz�!S��tFI��4db���"����#����&�;}��τAC�;|���‹�;Sۤ$�J�M��
+ ċT'�:��م�i9j�F��b�ob�ޯא��2ɚ�K��Je�zʇ�k� ��v�#G�밭xS"����.n���O(:v�5�`��#� X+���L���L_NQ�V�%A���ǃ0��
+�w|�>�H����2���
+��D[��\�
 ��h��X�
-���k)���['����7ӓr�#��d
+����ғ�.ʐ1�l+�s?��5~F{Xb�� �W��L��{a�}�X��
_N6��&��T��RQ�K��vٛ0:(��T��y��((X����3+q
���o��#�K7�r
�
�����t�$��^��Z#|��xb~��ZK%8��c���f��Bp�MC����
+�����dfr4��W�l-���")���F���e��`����{5ˠ�A�4V����ۤaꐢ��<��6�MY��&?���ƠԎI��X��Olݖ�)O�ws�Z��u
e�����y=_?m+���*�k ��;
/+��C͖]\gMe<���gWH7��c���p�s���'ҙ�[�;�h�$��{<[���p���`��]ӒD��*���*[�����s�� ,�%���vԾ�6�:@������L�#[]$#�uT^�m�޴��J�
��c�s{
+�ģN�ӷ@_U�7�,sX�_���Ыƣf�6���ƿ�{|z�@[:�؞�
+��4Z;�����@(�l��%��1�2hdu�$���
[�d�@�Fr�O��0r�{���d�7Z��!&J�9�j�����������:�6�/z�
	"Xd�ǔ�
:��gň`
lnVp1>]�i��6X
6̵P
z�v���a
�V0����wD�
+L��Ӷ��Xj|�IňT;k��O�_c���
��T~7w�l
3�'u����L*54{Jv��F!];�1֎I!��L�uS�w|�'�z���@�%��
+�����*O���י����~>���DZ� Ǿ� �

Kk� �� %�I`͠9�_���
+���^�
p��X�$O�,�^��������-��-������3D���{�Q0�����$Q�78AoҎf��)��u~1n-��>[:L�}��

s��`Ҟ� ���nWQ�s���v�K��o����ca��IkG{��r�l��)G�T&�:Y}�H�"Y�����
��T+M�5��Zh�з~�3�m v�o},�{_�t>��g��b����d��m��
���
^ig�Ŏ���&��S
�m�C��9 W
+��}P��1�q�ڿR�-zf�,\�dR�e��>��'X2�����js�
�5��4��73���a�~}�<��
�_�s���q{�DaaM^p-
w�[��]�#���>�
+�c�Q��-�9���k��4
�Ιf^��9p��
�X��uB�^���V�����ݝ�.�
+�y���EÃ�X�S�5�y��i�T����ɦh�zi�g��W�&���@�E�nZ��)��2���������^
+V��woRB�<
�.�U�
A������?��)�Z)�tW���|r���Z#14
F�	x�z��m��Oۓl�l��m�
ub4�@
b�R�:�\�	p����w^z��'G�N��f�`����!Ű؋y���)�[��
���S��9����,"��c�q�'/
)�r�_�Ǫ|�#��1%h�CF_��\3�����
}qi��|nm���;x��?C_���/��g�P7c�U� �RS=ԩ��~fX�Ƴf�nv/��d�gx�P�-�����D.>��W�v�X� I����9�υbb���=��*.����=��=�wI���ۦ���t��.
 6�gY�g�Y�F�k3}��ȕc�Q|�t���n ��IP��9�T6`ݱ�?�7������=��']MF7�NV��:ER�.N�Z�����(�3?���N
+[������r��ї�S��m������T� ,N�Z��'!��{"L?T��%
��o_�O��b
-�0�`*�C���W�e���[��W��7�k�C}�	�ן�j�����
��g��>'��v�^*����s
���P�A�<0�Ky��o��n���>}Mn^12�y�罉r]�T�3H�����e�f�h?��k!R��䋰������� x�X��X��ۖ�C�����^��u�����n6V�]|W��X�*��q).����ۯ{���Q���3�~��{��
Qn��Z��_!��L�8^�f�UYn�G��o���e?O�3�ۦ��L/�ExXɀ�
�Ce�z����]=��$��vT����wW3�Q���E+��B�0������}#�f�ڷ(�����S��j�wEGo�F�=4�E���	���� ��p�L��c�+�q��
`[
+Z�ǟ	<�9��L���~�����u#�5	�%�j�p����Gg
�L��$�#͏?��|�5Ms�l�����0�"�ot�p V%���nY����ѷ�)^h?��~
�y�Q���}�n�`��߫�b���z��S�A{i����8�N�P��HŌ ��
��V���W�kk�1a��v[�T
+͉/�M���F8�
+|2n�cj7A_�iV�#�N�� ڞ?�Uob}Wƭ^5J�J�f.aeqw�� �

M~�ח�1�v�<�Ij�\b������4���v痕z�؂�����b$��*͉�lس�y�Y��v��}G	*F�ޔ��Hu�
�B0k��kZ�@���7�p�Y�q�L������x��I�c "WW{<�����\�l�L�������-��y�3�7��=���(� _z9s�Ź�ן1��3f�<����.������ˎ���%`?d����n��!!`b0!��%������g�O�*��
�4�k��%��D4��޳����bD��y����� �G��2J��`�j���w� 4�2�=���]Sm�0v�>F~��C���`
Htֆ�B�f{�Қ(��< Vy
+����fV]
+�G�V���YM�b�6]c3pq�1�"?����1Z��064�����UbQ�H]�X��Av)b�Z�^�a��9T&��g��RP�
+����}��
+>۠��6���������{O��}�����֎�?N��?����÷?�����ǟ��ӫ��~������w��?�?~x��k��?��z��ŷw�	��ЯO���O?�#<}�����w<%,e�<
+�!�{������I;���Վ�W���_����������O�A���^���Ί�KPt�'� x��5�y�M���^����gQ�c��E�<
x���l�SP����K�Q�K$����\@?Q�
+U����E?��VЂ
y=�V	�gF�
�}��UCޘ��
�.�us���O���3�	9ӕϕ8��N"n@��ê�(�ڦ�%��^�������q�!m�g��`:��
+�AV�get���v�/wivK�-��.�@�(�sFh.���ʋ���C#��J�/f�3ý)�X8�r4�Ő�4�[�}9
FiJ��� +�zЌ�	���;��-);	tS}Qn	�Ŷ�+	�
�}v)��
�"�ܓ:�-�bU�������)���b�!C�P�Ck��m�����8

+��HI�Z2��E��8m��
+(���*	$��HM�����-�G��J�k���Zu�z͖����}��s��
��t\d:���Ri� ��� v���M�+��-
+���[��sb��WiF����9 -��bS=��b��l���r
��=�Y�5Y��
��
�K�㔙[�^�R�0B▣x�.l��]R�3e���x}�"�nl�9��J[{׏��B�
������s�M--3V1k�y2oN2=e19��p{<�'FB?�	�c��
�Ez�J�K�)�O�-1�)����
^%U
+�9�ک�R
���4^6��l7CO�U�X7^���~:�6�x�ln�x���
8'�K����iӖc���Иɘh!+ֲ��4�xZ�<��ujQg���ϻ&^n8�����^��L�d~�QiEd8?��w
+
+�D��E��\��l4Z��JK�\�0m�r����c��[�w�9�Q�)��o���O��f	dz,��T��b��̯���l��l�cVVy�|��je��p���H��P7�[�&ވ3>�]�2�%rB
&��tn�Yy�D��~=�� ��h
�
+�W� ��r�8�s�
+5�z4b;�QIyl�ni9D��B/�e�U�[j��$�����ek")��?��#��)8ʗLL�hX�Y ,�ُѕYp��䤩�I6f\�V��K��YR.�lF�Y�I8�

+��'8O�*d���Ă�ML'�����?ҼU�[S��֪[�[�6U�qw�]���"s�E:_�s,�!�Uc��F�!@�7�c�&_硊���)7���B�����C[�Fܔ�b�s��:��$�Z��(1�)�nzQ:^�����"��-A
.q
�pv�"a�ը_�ЩXj�ə�vc-C��yLt�|_{�"Sn�5�s|ڤ����(���b3
��O�~�/�bK��'9(�����V�SaU�Ew�]�v�-�Ȑ��i�ڰ�\�9ՙ�:0ޞ������r��ǘ,�
y��4uX��FxT䆻b�
��1�Б���y�@N�i��d�x
+�R k�^Ph�LA�lS��3�`\wWu���/	rS�pJ��K~sS �jQOR�]��c���U��/��
�H.�v	r�\h7�Ќ��-X6�
t�B�	X"��vbj�Ży�R�F�n�צ��w�'�O��@@�Zi��b� κ�=6$
�ܺ�ݵu��`�k�DU��G�ۦ�%��r�����5m;�U�(ރ��.	r��h��g��8�h5PI���Q[<�Λ_GGF�R6S�Y,l�
+BpNq��*�&eKE�b �%d at c��œhS� ��]؍U3���nm	5�I�[&NI�E�
��v���F��TQua0���y!)�RW�PJv
+���k�Hj���*r��Ƴ�����i�Rh��r���j?�(Q�ǔH���ˡ� ��3jqjP4{:�%�x��x]︽+�R�WC������H��į(��Ίx��~���e�'
�B�M��E�.}��3K�@����&�
�:�d��0�,*+I��\�O
�	�)yC�R���k횣�GQ�x(
V�5
[0�+g�I���Y<#g!�gޭ����;K�5��풉
�\~#-qϜ��۰���YJ��2��,�x	����2�D�HKJ0��(�*հ$�6�(aՒ�ޘ���vD��L�o��-�KIϦ"�
� �/�׭�j��:���vɂ˗O-
+��!Gc�I�lvI�<)b�:���P��+:L�{�n���s�۾H��/c{nA<�`en�(A^P��	Oe��s����6�)�i�I�48��Vr
�P�V����t�ÃPmx�c��A)`����u�<�\WE<�XY��;��pW�;+�11W�پ�[�a+�ĥJ�~���
>�Ѹ��,]�p/�uN��P6{ �Tt���Վ�X
]��F֪�W�B&C�v�o��`�)��%Q ��B��m෦�Q�U*h1��3���xd\% F\4,J$zh�x���{�]f�/���+�.�=1�J�4�2v^� τ��׈�K�QM�6R���`\�gT>R�H�{�?��#���0%ᠭ�$OjK��4��d$a�c��|d�HX��i,?����#�-}n������r�E��q�]rw��g%4��`i��q���.I������h[]AZ��l+�'����Wۊ%������b�
6uͪz�F~�cc���#vW�1� k�{Gfd��t� �Yfb��3#�2#�e�xA{� [...]
+#����{�� ����d�`̥����M��Q��&�00;�Z
��\(ҹo�r�y�V�Xծ?X���5�j�U�ұ����b�!�.�SM�Ȃ��P
���c�(��vZ��NV������_�S�Vl�����i�J���6
+Q�)9�n����d����ry�ƅ���S�=��lT�l�O�_{5;�� �:w,3����%���+��[�{+k<�s:)�R$+5-���cz/�9�|�
�ݛ�In�����H���$��5U�9�c��X_�LG�@�x��e
�[Tw���cћc:��c��>�2�<�|(AK���r �܍�����7b]�	��
(J�&��꺘�`V�
�1��4�g�8���s��uf�f�,w�����t7�]��i�V�b����@$qd޴��''�9R
�Ɲ
ؼS�m���iW 2u�Oۊ���
+R��jU�e��zz��G�H(�l�9�'`m=rdQ=��!�Q�M*
;>���p����-�Fg��T�n8�x��4�, S����צ#���5YoY�&N���ף/?R7E��h{����+4�\2��/�O4�F14�=��� �{�x��cH�[s��� �+�;T�;�T�o>Z�nC
��ݓk2�e��>Qʼn��R;P���t�l�̭(>T����	S	0PL
0��_��G�c
+ݟM0���MNa�����
J�$kP�k9y�(�H�ԛ�{�2�)ʼn�G^�9�<�#3�2�,,�*!y�᪄�
:[���,2p�.��TJ�l�1���K⠫
>*p�ԣ������5�'�$��=3���a-4�Cf#*%���\:|TdGRCa>U
+�8�
Ȱ����T������wQ��e����A��"xV���7bī�%�MM,���B�������v�ǒ��Eͣ���!'q!��k�nQ+�+���-�� �:rg�����*��t���� �ڠq�y�+�?ה��� �+��2�b:�kB�r-^��sz��
E�h砳���{�N�Xrv¯XC���T�G[*�o���d_�rO>� ��
+6�(�r�(u�o�Ųj���~ &
�n�R�%����/Gj�� �B&�
���`��X���`��(.o���#1BC������w����m>�o�tt��`0 {p�XBsܙ8�^;�8��;R���|��y,ۜ�M`xS�Ǝ%:Ib�kc.^�#m��%��b
y����l=��#q�$��m���9�����Uu��Rv��m
5G	�k�G
,
�X�ݜ�K�Zs70�/!G���7*�*ݪ�KE�i灮G�|d����'������Fٳ�U�r�aOeR�b"Op+�,�f9bq���	Bk��A �D�r��` f4`�v��;���=m�|��l	q���*]pQ�*N��ځ�G�|$��o��
ᢦ��#ga�j�xg����(Um<65L�h��{�b
�>&�pYS�q�Q�_�e.(�
o�G���7*����K�,5u�����
3��W$��<2o��a;��nd�
z9*�	֛�K�t�1
+�|� ~J
��0�M�V2�ₖ3Y�ɪ 
F0�
+���b�^X�*���%g��*��d��	+j#����S
Q�"7
�ي8�qXk��HT���PfC8jj)��P��!�팣�g�c��ݰ�-��HI�X�^��K�
+G��̝��7��g;��2��uy�7<��W)��?[�+�"�*�D.W�T�6��r����F�bq-��}!�1=�n����^�S����[��p��q������
 ��u0��Bk
L��/�KY�g,���.jpV���~�������c�’��/c��|�pJ�| �l��=��:��ՠ�
�
����`y^��������w��FI�v=����
+|��z�MVGh��rzFl^혼c�C��E�
�7�@#
+p._�u�
+>���K�fT��������A�
N�+��!�Ad�7n0�����#�R�$X�cP�������aNs�;�o*��*��p;aju�����
�Z��Ԋ�5��J�k�����)"(���
+�;7�r��^��E����"
+�����S2i6E��C���5v8
+�Y�I�4~�[�Dd����w!V� �ց�:�)<E�t#�z��a�끃G)]���c/�i`�N�]R�$��eq�e\�{J͒��]�E�آ��#$;*lt<]�9��"MP�Ea�===�@
t�꽜
+�^vAr�A�6�y@ٹ��<j����~-����Z!5S�=Ӳ�k5�N|w�B����
3|���-�w��۸|������Ͼ�u��^?|������������_	~��o�x��?����ۗ�.�s��
�������K����?��7�ៀ~���o/�K�|Ч���;i���X����
�sk�7��
\G��y�;��9���s���(a.���1}LT��k�tF��
:�N
"�'lIw7_,�� ��I�=�ŪAp�J�v4
��;
��L�=�ʏ3? �WJR�!�M!��������E7#��z`h�L��u��W�i���*�-��*�</��eu�|
T�+�����)!�N���C���a%
+C
+�1T5����O�)96
+�4ai����eXS�`�|��n�S0���T55�zT�Ugn!A�0��g�������u�"�ɚ �Z�`�
-���C�@�
Q����#���AlU�`��o
�A8ڲ�g�ş26�<��c	bu<@C�/�ն��uD�@�����8�|h�l�-*))&�P��M�)�ʄ�}��Z�����Jcyi����a͚���Z
0�	��5 ���B)5FpF
+�ؖ"����/��ߙ��)�6��v��%��F"��d���g��h"~�
+��QP���둟ϣf��
�`��49�	µ{
+�^5l�Ĉ@��	�fO����$<[�a�Z�t.��O�B�����b� CIo�>
���eX�<��Ô�fס5'O��*p-u/��G�c�K�Ok�V��"��
e�e�EZ
�Lw*x65uD�	W��W��|����m�8Y�%	�'�f`eD�;�|G+}�ފl��Q�V��� J�����
�[�a;�Hq.�	^�F�7	dg���pC���
$c(Xi
�4A���JAM
�O)
+ �g����SS��ܽ%����2��
+�(R
�9y���>
�LߟP�&H��
v2ͺhZ+�U�3T(:�&f�VE&	�&}
�Qs%X훵�1ׇi��U;fmB��u\�9�͙Q�vp��m�,��9H��{
+��2���Y��HO���S|U�۵>8U������Tt�Xڜ
+�+u6��T�{
>˂�͖�y�s��Ox��yC�r�i��7V!�ˆ����sg8�L�P18��Q���N�L�3���G* �
U��A�����9�1��TJJ+5e�D��
+y����U}�E��
OK�K��OF
+�;�w<:WU�-���
)@� l�_HZ��.���T�U�,[��i���f}|��М=1z��U���]���I���R�i4�t��x�4Kꄳ��Λ `N�j�H4��`[TN��' �W��%����'��G�

ƀ �9z�D
3�͋�9֚�h	G�RPg��n���4�Sq�h5â S��>KJ$����%��-l}>fѐ:�Nz��{� ZtA�T�&)����G�8�Q�+�5�N�R�q
�jK��ʙh�x@��Lg2{x�Ŏ[���Tَ���$���>q��mM�vR=A1�@�)�
.5�X���雗w��~������ۻ�N ��k������7���p���٫W/��?�|���[�}~�=,���؞�uqh^g�0�rkZ�
9��..�>U�˝��jܪ�ʇ�X��)���G�8{/ۥ;M��\`�� okQ
X�S3c�i����+��T���kw�ԝ�T��o$�н�LѤ��KoA���j�5z	Uc06���7���V�*�j�6G�
+����,a������2,qQ XE� !l�>�
L��2��Zd��X2 ���qR��?��$ť�}�?
+�1�դ�p��`V( sq|ڭ�y�S�_����R��{��]3z~���˳�5浆��5�S�:�Y�\F��XZ�i�n2�	��T����9՚~wZ|�(j�!�a
v�3��>
˕�YQv���S,���Or��&a�QT�Q���
M��ٹ���$�Ց=EO�
QV���	k���"%��K{��|~�<-|G�{�N���ꢉIa�܁܃~��|�4�Я��I%o��M�s�4 +���3�x.u
��U+ΣQ�B�
�S�*f��6'�I����d+C_��1��X,�C[-₥{M�9�{�jA�1T�>y���ٟmtI�I�e$5x)���#�&�b�҆��$���A��Gg%��:���COq���b���^Kb�o#L�tc�ֱ����S��h�(+#�����
�j�Xi�p�x���
+�R	5�n�
eg����c�W����e˭R�V�ߤc�|P9Oșc�9G��Ɩt�Ѹ�Z��_�k�NpV.$X���r��-�>��E
�����	E�L��:6A��D�]�=��
�o��aL�씷��hz�
+������_U�:@�-��V���F(m��>To�MU�n��%��/u�zQlR,�N]lў�S����ʍ�^�|�$�\�
��0D�Y�э G�f�;�;L(�2E�7��xt�#Wm:n�/�CR|L�X��C�XJ���-����.�Oa�6�Z
oZ�is�����o�
��І��bp�ʋJ�%L+y���
+Pԁ'm1��G��i���(RgZx*vJpڪ��*�#`�>�u�y��
���Vy�mC�(����S� (>��H��Go�6�4��ߡm�ʶ���fYTOֈ�=��N� �b��L`sh4 at v�8�K2t�޹F�k������Fr-�ۓj�л��a��-&�k�1E�w�y08>�4�؝��A��}���%�L��
� �^Ќ&��6���������Y��*���m<3���d�.v�	�w�, �U�@w+2�����R
^�K
����BQ9O��nܫ4aipY�m��LR
+3���&�}G��zI�
�RG�f �yA����]�E��#�L]�S����r�)�%:�-W�/jR�=��C�|*V~}�OϞ������	��ϛ�.��w�����^?���ݫ��������߿��%����n?�����}{��ݩ>Ǖ/��ͯ�'���?�
Я�v������;�����9m}À��|X�ْ{ehu�o���/ﻺ�ug���3��o?d�Fa�%R� 7�'(G�4AL�a)#��n��`.^o�6@��칝
}����_�A]�1T[*r̷	^R�l��
�6�^�6�K[�K1�����gp���Q�s�C���a�rP�,�
+���V`����G�=?8�%w�,H�#G�e 1m�'
�OYoP���\�vhr�;���g�M��M $� ��ϲ�,�+
��q�ص��,�o�
+
��7�k���1�m��q6?���ꗶ��L�}�[G���
(�}�倴�5��%�ڑ$�q�U�^Kԏ��n_e̽��"������2!Qz"	kU3@�v�Љ���~�9�^� 8��Ǩ<nb����=,i
ؽ���a�G�
�qO뷶	B�G������K�6�4G֍Yt����X�p�H�
+
+��)�;
+�{=Dj���q�_a�j3�?��Oa���+�����_�O֖��o. �ɲ4����T�N�bsm�%PȜ�!S����R��e�������}���p�y��@+
:��t�s�4P�o�W�\x�Uc�iKk�B���^7���i��|�tkn���p���d�d?b�s
+�4
���
ɡ��� ǻ�x��yoK�
�-�g��c)���?��z��S��� 8�Ϙ?�����4�r���R�*eqj^�*��~���
���IlD�Z9�
+_�J���
`��\�W����C8^ҷ��IKp��`r���bG;��\:��[ts�r0���_�f|�R��THs
+uǹΡ�z
����g��s;��jZ
�0`����rȍ�
I��>�
C��jx��7��ٺ%��z`�_?��ypNk9I�<͓p?*iW	r"͢s �Cwn���v�B�I����~<>�����(����.� �I�w(��c.2��:0��(�yc܊5��`��)_V<C�Y���E��[l��$NRrw�3³�n�yy�.4��ve��ˢ��b
��H�-���~s9�5�������-�+�x�fod�\��g��A����L	�"?��%�=؝�6 ������s.�>UdP>ֻ(Gpt�hD�M�
�Y��`�&@H��\�8/�מ�oІ	
W�,�w�S��9�6�^Z��$�(�^�N+r��/U�$c��ݮ�ȷ8��r�|����}�����n�.<NI�KJ@��^��	�H��F�:݆�M2�B�3Uێ����;ߺ���d��P���Sx,:�i�;��5��kpe+��D��q�5��)��C����.+yK�k#8z����M
>�Gq [...]
+{f=)��!��t�?/��\t�iW����L�GMD��
J�Z��M�Bژ<
��\���ֺ�J�S�
�3���T��$��oU��;!��!�m;/�*Y���W���՛bbm�'v*S39_�?v~�"-i������g�
z��(6Z�J�_{:8��`���T�!��X
+��Fo��:׎rK�)k�9#Ei���Z���:��
6
Sv�������?����20)U�g��z��
�����
�9�>�����Ċ���38��Y5\Z��:�;�3{Bkmѱ-�Om�%�5��v��~n��u�݇ā�t⩀�e��Q�@
�����B�7�o��u�]欘�M�z�[�&�4lOz�"���5�����D9.�6��к)
+�B%\�X�
u����x��bŁ�������2o��h��6�[l��;w��'L�i��e�F��+>��t�M� ͹Ug���{k�g��M���秨��P�[JH�d%\���ȊQ�)�>l;�\
l3X��
+`{�{HX&Yj����>X�*�L�Q� U
k��*�Nپ=IP��k���>G��OŪo�'XZ5oe�<^FR�H*��$�}q�-Q)�
j��ў�C �ZVm�������l���}�o��
�2�p����^
���
0>��d�K�q}���\!b3�T>A3�G����`Kƴ�9r�|J�7���.��ک>cx���9���k
|�#F�Sk7���|�9J�9�T��ھJ+�m��~nM��Q�0�a"oS$8k[e�A'��ʰ�N �^��Y|�
m�\�<���՞�()��y�
���g`�%�
��X
b���j�JI�V:O8�rNgZ�Y�t:�~��X m������g#����|m륅<9c<�\��A[�e��T��ʠ,K�e	�V~��6�T0��} ��-%1 ~�暕�R��I������\
+�5���&/Pc�����-	��ȼ��
��X�� �^�0�	7�<uO��h���TG�lR�-���z
+�"���߄'�'�ƫ?3D�i��
+{�0�����Ԋ�t�346�[X��}pc�:�ׄ�Z�d5� Jy���|Lɉ���P.��}�&�6��h�2�9��õ�Ue�Jo+�W��e�5R�R ��\�k���%˥�\�����P dH
+W�g�Mc<������o'k��G Nq�u�+�&�Կ�ZO$���S�)�E��V
+� ���}
��w���/r0��L��
\~�A�+���)z7�.24��Qk'��
O*�w�<`�F��֦�+"!kDA���ٟ W����l��M����w
S

�NW��Z�Y�6F��mO�C��8v
����O,�$|�
�����������,�B��+�
+��ѷ����o^G< �����v��v�-��
+Y�	�mG7�?�s�yFSb.�� ..���5�H� ~����SUVg��g�
+�@ݩG�3�)
+�AϘ"�2u �i!e��Ծ1Aoe,v{��K�8�)ؘzÄ�
sG���ʁ$6��[}/ɵ���z�a�����
+�a��~r'�$/Rl
�IqF��[��v��6�F��a/qz�J�
�Pn'*���#�
۶
��sy�&}��� ��R'�

�n��n� �U녡���v��\���V����$=|]L�=�	6gv����
�+`߿@}��vB���O�i��_�.���o�T
+��akD\��U�i�i�=->�� 't�ش��5Ԡ�e�����b-���X���tW��x7��;X⧴@��%4#
+	�VM��9\
���$R 7.��6ǔa��o'�U�b��"H�
̨]�Y��)�0�]Ӿ{��sL�}��0�A
I{�mvWgӯ�F��S4&���dV�S���F��/^�Xo�uI�z�!�
+4k���w-a����0ߌV�;�`��'�8�5$���yD�f�ra@��gs�ں*�7 XP��}v/�
�KƵn�E���	������V�t�3��@�:OVoc�vgi5�:�j����i
R�:���&2,�מ�����O�[���{n��Vk<}(kԾ��na������w;9�7�*�hΆyU��\�~UL
��J�E`�rqA���v��Ȱ0��bbv�U��9�����ݨ��h���]3r$Lp�������P��eUs�ݛ`�
5�>���Y�#t������L2���<A	�PC;��r1FF��Z��I� P�e����J	�>�gmN�,.�j��q�4 ���+��'���kTb1
+�b^|i�/p졅҂��YV
��ss�a���{��
++�L��)g���#E��>~���J�[*�5jI;+�^ɗh?Φ$
+
+��#N�V�a�
'G�+U��>��MX0������+�d�+񢧜��S0��)�T� �b�?_�Qb9��i͵$$��
��-]w����|K7��>�����Ͻ
!%��ѝ��C��7�
�[��}u�R�
�R�]n�yU������yT�FPk���x�u��{�[�.����I�b���osk\FX9�m&�Mx}
+!I�VA��1�@C^i�ԩ-� ��I�����(����J�09����C4��>����~/.�8A��� �� ��i��R�
�z�(�G��Tk�[����K��#8��\���+_�Z
$�j�]}���K��b��
+���m�r�:�I�Ÿ
����DxRA}���ކ�`p{
	.ܾ�ƒ^��
~
�9oG}LAV�e� ���;��:�m�6a�A5�<�c\�
}>Aco��O]�
�
+]�S�n�.�
�P�����H��m���OwBw��-z�H±_�,*"&��ȸo9F
+��
��?^��]�G�J��4F����5+��������O�A��#
Q�9��H����Lt��t}�
(@�;������If�����a7`H9��Ӗ*4:�<"@�b\5�G��V^	�˰�b�y�;�V2a��go���1
��s��sKM}1��.`
X������A/
+
�1\o
P�����PE~�����'����g���b�B��0#w
+��%�wwWp+�v�{�n}d
�H��)��<٧�ǃ���ut���(��c�=��,ftc��8?�5N�ĕb���j�o�b�9ݝ7G�Ō�Jج�0h���ɩ
�<����k�*�5P�_��p��,4Pۓ�IR�X/�dT��ҧY3w
������
|����y�K�l	BM�=o����l�A�W�6�B8��U�<g�G'm-��W�:��
I+-�U�S�>*r/?����
��d]�A��$`e�$�J �ME<��W�������x�Y���!����p2�W��&)LW
+���
 F�
+endstream
+endobj
+14 1 obj
+20990 
+endobj
+15 1 obj
+<< /Filter [ /FlateDecode ] /Length 16 1 R >> 
+stream
+H�|W�ul��`rP����o*�����n=��[��VPU����oFF�f��>��W<6%��.�Hv�s(5�[
+\k�5 ����9*�f]����&*����8:U ���n��$`Lf�h���
+�e����
x�4�"���}l^�Z��Q���6#�㿼������ԭ�ʖU�x`*������[��nsy�<��/q�UhUZ���`�e����VawM�Z���b�Y�@�e���e��wt�W��+�V�j�9Bf�����UE7Y�B�6LP���uk�q"�Gkz���|ߢ����l:s��L�S FH��H��Ό�,�]Q\�evW󝃚m��
�����0*C~񮖣 �*-q�9v�[������]�Ê����2`Q�fǦ�>9P�s^����>
=��z��'�vg � ƒ]	R�&�,s�
�GIځ��j�:�D����ì���|/X}:Y=	�*aLt���ndf��b	s�k;�����ۦN<�
b����.�Ai4�g�^T��>J�*7q�Nd1/�AMQ�
�QᢳR��t�D1޾��9R<���n�8���޲���`��
p��w���Vz��M\Qb~{�lF1���6(��x���1]N$��Ձ�N��Rm�+
z��&���A�yZ8N�a0 [...]
+�
+�ɱ��F>��!n�;I��a]�BNi*8�E.
��R�����v_��&^����B$�M��=	�E�=�t-�� �:���۔q����<
Y0��Fq]4`�6&������줔��N�
+�������3���P�D��>٘hd
��^+@c���>`@T;c���!� �U�
��|3�\]�w!�<�������������r�����w^��&�%�ao����
�f���K/���;��:���T�aK-8nȳf[9�	��N��
�)W-Hp6Vi/�<�"��d�(72Lz���;��� ����{f�^ó/�6j��������K�

h����2��;72�㠱�(�p&���lG�y.��u�z���cy�c=�8w�꣨ժ�)��9q���B�%�0U�c�P�5�-ݩ�f?�
�A�k ���h0�`�m/Cx�m
��caGlzw�H�����<S���j�F=�k!dZVU��y�ځ�d�F����C���!
�d�l,��W�*?��x
��cF�!��>)�C at 0bg���@��m{T$��,�Ca�#M}:��w�-mz3@�ֻ&�O�F7�1�
p��j���O�vƳ��
�r�>��?�~� �N
+�k�ܩɇ^
wl?������
+u��fk�
+�� BC]���P����z���ߑC
+�����r� L��Y	j�Y���
�����7
+�ٝ�����~��tੴ��r��0�
���+�?��P��/`^X�~�@����)
�/��m�� ?���������(�����Ի��Zw`��	�u�
+Mh�'��Ko.��� �";Q���o��nXg�e��)4�� ͱ�����
g]۫�s�W�����ƻ�n�����Y�����n��KcH�T��p	J��cw+�Ч�8=��1S�i��W�{���
+f'!�
^9Wg�4AG�܉	���6pʅbU���ݮ��?ׯ?kh�u࡞��H�,��PD�'
�h����]20��
Qh�۾��>�����
.��x���{
���}�u�=Wؿ:3@��Jc�A�L at K㕰|X�N
���s�Ⰿ�r֞O��%�
�N
*
�|j����}x��<
����d^����NJާ'�
�qсKϚ��&ʯ���j�6�윐(X,��.�u3Աk�^!_��@�PJ����H ��T�t�\��`�_��h�W�d���j	�Y�3�rْ��[k��پ�O�/�g�?/��D��UӔrV��0��e��ej�ZC��L
+�|�r��tHn�5�
�acSSz�
2���|6
+V� �젞���	�I
���@Ͼ���G� t\>s_��˥
�o��E��O�8bX�,���:LLv������l������p�.��~��$���Z���v��\[�
��ð�:0��n5:{�ob����:�(�i���W��X3'�I�1�������d=��ؚ�
0�be<��٧Ã�U>_A at if(�q�����g8�v͙��%�]{�Q|�/�-5;[�;��Q�8%t�{=�d�at�r�M�l�Q火8�
+�8J��w7��Z�$�p�s�O�'v��KL��3QS
1HJ{V��
+��2�o�7�%�e����v�I��������#���U��^��i�2w
~}�d���rM��>�f7�Qo�����&�i#�GӋe0�b��+��l
B��-�
!�4[g����=$*}�N����'H-�~�[��*{��� -��j���	��s�Vc�t��A,�������˹�mn�����.��5+ª��$�S �O�v,�GQx��y��=�"�
�?�7
�h���?�*�P"++���&a�2��,��=Uu���w̕HH�������>Ή�H}�3�q]����
�V=#Xž-}�l1��;'�6��
+"ڎZl�
s����Jb٪�)r��O�G!
��L��&9u+`_�z^sv���"�AR���Ld�R�A�uu��f� �t�V���b�6Ed�ĕ��^
��;�)
�Ĥ�Ś������Qw>�n��:�(y�&>��:�=�
��-��ӣ������b(_
~I��O���#�'b�Xa�E�>S�᠖�-��*T�Y��ؚ#9�2����E����ߘE�I�]>Y�k���$w �d��Kj��@��V�|�9R�Đ#-�k
�%��(���5���r���zh��o�: �J�q�I�r�#Ȭ�$
����BQyS#
ޚ��mRΛ���T&6g�d63���3�����)ik�le#��b�n�}ݟ7M�c�\R��j؟�A���J��wP2�|���b�=�IL���c�(ꎠ�а��+�S��en��
+�rB�&�ڳ����<=�������_�V�T,�����4;�����Г瓸��e%�T�z��()N�`&��%͕*�h"Mof��%�=o�
x8����{H=��3����f����]���ҁx�w�������7�����t��hekk�N�ԧ��'�tw�@Ll+=�Ow��!����R���n����x�ç����lg9�S�ԇ����y�Rtz�������<[(3ը%3�<��
+��q��O��R�śs>M&;hB\�E�����b�O_Q���?v�r(��#K�Ng�w�]�V�8E�����Y�k�
����]z�JZ`0*)�B�t)W|��y��/� � �{�}�.	ԩ�%X]��e��SX��
n=@ޙ
+)I"襪�
+�p
W����0
qO8GKI�<bk:�Vv.p(�I_��
�l�����l��(��X�e�10	��E"*M�v
2��k�Ȅ�� У��\���U w;g�
LĹsf��9���
R�l�Яe�����!/��=��I�Y�C?�) c��~�.W��s
������
Gξ�a;m#s��=��)��zN�j,�rͷ�u��mE����p�',}��-��@�T�8�"'���h�3��А�=�����;���D�b
+V�	�Z��aoV1��qi�L0��\�����s�%:��J-N��
+��%�_�^��4 ����x����c:@q��� ���(R9�l��b�l�޴F���_�5ah C�c��yD
ׁE��3�Jí1R$3�Y*����˭b�5�
�p��PR&���i��-c�&��	��0���d�^���t
+��tѷ
Q�E�WO|���"
9�(�i���p�TcU�,��߭�Ø=�~#�
+�l�%�9�8H�,�w2lX�Vbϵ��G>�6]�$b��vP%���p�L�؋�l����V�s��Ł"
�gL�L�/[�k��
�=�J�.
z��"K��rPs�~z�|�TYdY�D	�d�
+�=^�;��
���.iQ����7ֵ_=���:={~z�����z�����
޿�����w�?�����|����yxxw����=S|��o���)���y�3����O@?��鏧��=�ޫ�7��U0�'Hr�E�9�p��@Vj������9�x=�x`x��xx��/5�*L�tS_9��
}G�JAԫ�e�[G,6�� 14�)�G j
+G֬���X�4c�WT��
�.�^RfkDps��Y5��I%�[���
+n��v &�
NE*
h^��;z�"SYgl�k��@q���'Va�����>7&w�I���{Iu<�>V�P{�gZ�.��Y����rp*���М"��N��^�
������3���
+Px:
���1�TJ�'IM�E܋ఈ�ʨ���sU~o����A����F�`J
��ˢ�if�F�`��k�Z֔��0 u���:�T���Ŕ�)W-��}K����!���Xq��K���
$W��V1��R�����$��B�&� $3�r����z%؆�eJN;��Ֆà!
�`��{'�W��
C#���p�1���U�*�7ˡb�o >�
���]��j��J8���N����
-��ɩåWN�j8�c�eN�E7�̶P�k�*�
��><���)h��k!`�A�!��aG7��p����؅�灁��N0)�r˔����r���K���j��bm6���>j
�9KrӮ�*{�#�?~_z�t��C��e��Z��vS;�M����<E �.�g�:	��
T�~��W@��s��j1�L<*6�3��n�Cp(l^��\K�_����z���� �Ki, 
+fZ�u�g�v}a���d�A�:h*y܁>���@�f&`f�*LK
���c5�ww�]�������; Wos�@�*��v�
�y�C5����g�9{ [� *-W��
+�Rx8_�
+��v��d.�A[���q����|�м��1�1��4���NAJ��md9??���l��ۃ9������s�%�L�zqШ
�g�]^f���*�*{�J�H�Y��������I�u~��w_������>���ݧ�O��
�+�<?}��ϟ>>|z���˻�����;5}~�%
��$y	$���3'� w����/��
z}s����6|����2�lq�c�`(�ʷ�3�.^�@�]�G-���.�
��$ǡz�n
���v�T��S b=6Q(����;��ȗ���}��;M�
op{�͗ڹP�YAc
O����P-g�
,�q���r$��-ʂ$�9ϵ
+�{7ƀ�~?�Rջi^L�Dw6D �H���� ���N@w�Ox�V\��ߝ;�	�^c-:�7�ގx�;�̾\Da�w҃���h(8�((��
�w獤7��Ǟ��1����߶Ǩ����E�Y��w�y0�y+s�z�F�5A����'|:�~�_g�]�
+�OhD����O
\�A� A�"��›�PXb�N2K�2S�6(�ԥ��E�Zy �a:8\��MP�;u�
��74tz��Ox��ڧ�)Y��/�($ɬ��|fݟ�n
e��ǪY��Z�U�j���|+{��X3A	�tMp��	��gyҼ�
+������_�#%k���"y?D��{�σ{ݼ�p�l�|̜�L��W����޹���_wx�ͻ.�ͯc�����U
+��n���J��I*��38�ce��z'����g�L�t��
�x�<���ܻ���A�}�u�\}�ۨ��6�
+tv���sѩ2��l;m��>x]W]���@�zkMm������e��G
|:P�vៀg��op��:����K.W]��Z����P���аX`1�ۦ�Up�ba��k
����G��'�Q�)�zI��O��IGپ��
E��C�hxb��
+cP�����M����Ix
�
�
+ʙ2
l������
毂�̖�W��/U$��ь��	n��
+�p�#LQL�<��
B�}�D_~?��
+U[��`��4
���Q��";�1�W�
�*�թ�l�䁨I܎Lj���5m��S��Zس�El߄�T= <$��O�����Y�}�����O�O8
`vc2����yx,�Y
^�
 ؗ	5�u�P|����/Ԕ��Z~ii�� �^�ft�}:]��n��r
�۹[�/�ײ��	A.pD2�;}���ع
�4/�hT��"5���C�:_�n�T6�b�u#c�0�`P
'�N������,mL���v��jI�������ͱ�W�B��,[(ߟ��� ��� ��d�A6�!�@-��v���Q30!�q	�\5�������a+m�-�I/����
���<X<[’������OA׿���g��
���`Fl�}xL
+�K݆� �8GqX�U�lh��a3 �u�h�.I�8�b^��A�q����
}����
+��hn�e�Q�q���g���y�Vd
+s)Q�E��' ��"=�X'���}0yO�+:�G��I��O�Q�-��<	[�-����k��w
��]q�
\�v
�ͭ�vġ2h�Fi��^�(Q�y*S��aXtFA��ZR�B��
����!Y /)֊]7��X�
+}~�Z
��G'w�
+�(
+��s��%AZ
+���+w�a)3�#P�*�e�a�sNG�/a��
���X��q@�Z�.�|��F���<K]]
+��z�)R�����ƪ�iv
�<���R���"OlԤ 8�(������={�QH<�V�nҪì?a�~
aq��nu�nBن��c�0��<"���U&�a'h�H�r[��o
+6�nY���p�.����	
	h{n��1�!���jI�����1�1�x�=��p�%��J
��^lSw��u��
+��F�G]ᅇ�U��V! �e���QҳZ�

�$�kO����>j0ԓ�Gڒ���]�%@lT��1m�S��xB~����i�S��CKì�=��'M��TfJ� 9�m
+�2* 
@-�<���*lv�����%�B��a��X����?��-2
+��U�
�=�����_���w^T�뵛��T���-�4�kT@���
+B6���ClP������ft;
+�:Mޚ�Q@&oٶ���*�4�LSg��f0U���XJu%R���o�
�
+��h�t?���9d�icg��i%�Q5�:�.mO���� �S{]
Eo�U~����:������^���������)uN��v�q��� �a�vπ6[��
�lU�*���u�
+��͹����h4��n�
+�
�PBGx ��8GE �)q(��4@�׊����Q
+P7>�I��a
�I�R4AkH�O$�Y�/U�s��!�CT�]ձ��k�*�K�v���8�j�O��ЯY�����Ѫ� ���B^��J�9%�f�԰wSQ���G>JҧL;e�NLL�*���\��ⵉ1�%m�c����*�~�/M�w�0W^v�ͻI��cuz7b�(��]�.
+i��N.���MN��j�I�\��-�3.+�'�z��O�^��b� ��
�c���4�~�("zh�rU� }!�i�=}=
+�����������:"d9_�P���b��:����y�B�
+��Uc�XY���_�c9W����0Sh���2 y{������ѴKkٓ�H�/
Q_�
.
OQ��b��ZCm�
+%@�Y\&���@ȎR7Ա!�6 ��P�pUٔ���-\�a���
`<<T�ɳt�ŵ
&�r�w���1�
~y
+\��WH����L��M��q�!�4�L4

��8R'�h���-NS'�b��뺰(l�u�m�e*yK���-d!�����|�>��|g�ħ?���6z�f�ו��s�Ǻ:�w�3��~�i�>լs������uy$��_�3�6g�`��R��N�E��
7��|Vi�
��Xm]�	�R�_K �6�}�F|.��5"r����3���d��}
[P#ķ����"�9��`�
+�l3[d�v�ѧ5���CDc4���s{q���R�A�g+��l�r��&�\�+�P��n[��v�F�su�qI�����-bm�l�@�^wC��V2���l��h������rJ�$�Ћ
�f���z�M%������r2{���jY��8�_0����p�����4xa��� ,a�3��w!K��}2#"�����E�e��3Y���8q�h�
+O��m��k�4���0��=��R��f�Xm�$�b�t��لļ��#��TA�
+`n˯VO�����������C`ag�!Nq닍
+�um��	ڇ�k�W!�f$<>�Y�;~��i��,x
v��;�Ű�8}jꞶΞ͗���*
��[������oԸ��v6Ωwp�-�
�������.�dL�V���!<�*޵���kn#`��������Lv����c�/�i�@��^@��CC5�C-@�Q�
+�Rte����x�!ތ�z
�=���NoF^���[�.ǒw��~�hs��Q+�z?�E��T��Jp�����ګ�����jz1���
FZH�2[^᬴�p�[Вu�=�wk�񒛷y����=�q�^!���7������Mq���T[~�l����ĝ��n��͑�%���
SIs��}<���c'Z��ݎq���Vh
+mVIT�K?�
+�-�E���8˶&I<@DQ��U!���e���5���
+&�E�JJ\_���uNi݈�M�)-�� .Ycc�R[W���ج�.�O�ἲA�P�}[���ྸ��$�*��2j��YБ�w��N���%�:VR�p��
+��C���"�J�
Ԝ,8�K�u�8N��Hq�
+%�t-Đ���s�벹�Ά̼l�
,�Yl�H����N�N�XgI=l��oE�hƘ�G :#�zTK��z�$'f׻�K���k�L��_�HN�a:oEV�����oO���@�v>2��� Mn��А:+�,V2����2����]!"��͵5п���>���m��\�=ז
+(��u8p�
|38�f��DU�n�:
��sO�O*h�[_>���z��I|�~c�:OָX�1q��8~
5(Kr���f~�Ɔ1��<��.PX�p�d���.�\��G�/w�22v7�[���=��ފڿ�$6��L�g�H�X��'�?4ErC����iW��
+�Hˬ�L���6g'���a��u������Hx̧���~��r��MD�4�`��T�L�
���s'�a�~��n�G��gG�
P����>��W,���'�{y|h9ƭ��_
+�Fp�2���xڢ~��I�5̒J��|�	h$�����������ĺ=?}�:��
�
+3b�^S[��m�l�ɏfO�K���m��;��yw 5�

�ij���
�2�������\�>�g��	�Tv���a������ɸ�z
���
�
S+llN]��\
9.�8�/�� /F�t<�uj��";�=�%�=/ݎ����ĩ���kX�J�Q���*��T>�]�nύ��:@�_�»�?��Ud��Ɨ�w�&�-
wC9�5���R�3X��j8c�˲�q*��l�����kH�6?Vl7,���xP(%jIB_a��ȩ3F|�!ĩg<��I4|�`V�i&��=Og,OcVpW+�y�c5vy���%T��d20g�M��0�8
d,?y
e`zBSwیD��\�P�0��X�bV4�GQ�M
�>w0R4�v�
eY%
\%|6��b�g3Pi�J���R2%=gU:i�M��P=�2E��Y ?�'�(�a:t����h[��D�#78ʣB�^/6���:���!��Ȁ��(�
&.�~
������d����H�Dv9K��y
���P�Ѣ7ծע�R����{� [...]
+���������?�� ��—?^���p������o+���o,�����5D�-�
+��h�.�ٳ�x�6^�o�͚nU�hb|�:Mʆn�
+��@��{g�ԭ+����K��G�v���H�
��#��kW]�R�뒸���ׄrG<��u��&����u6
�
+F#��R�� NL��>?	٠�.0��C�h
+sc;���ju�� ���h߷�
��V��y:pp��Ѐ���G��"w
s��S���Ij60�`QH}^�7�˱�Z�*�� ��ՁS�^B���s��^C�
q��b\�?��dZ�����j�W~Ğ%�2y;�h'��x����ŵ�
+�{�����
+���9<�-��9���5/�9Yd��fZ��c՞;�—~�
�`l�v���0�́R�
Q
e$�'�
D�TR��a�P��IP�Ѯ�S�cP
����h��
&�
��M�0��dvh��'r/��5$
+.d:ƵU
 �sY,��,;Y;e�U�|M�*��}�n�s�)s�e[rjz���S�
+�A|2Dp��*ܦH�8Lu\�ؤ�Bl`�JZ���L��*��eA�(M
�<�PK
+����V�<'E�T!����k��W����[��
�Ѝ�Z�&�0&
�4�їJ<��q�!͊�:G���V-��-G��}�w��l�����H�46 	iV�K�4ப�p(�
��vg�4��X@�4��}�	��r��3�-�)�Nb15]OW� r�v�$�(�ė��>5��5�۔��Z 8278�3�M�^yT�='J~��P�6�S�V[�\�Ʈ��
�ٝ2��)�ֵQ��{C�
B����GS,���?�������� J�8��-ʈM
ʥV
u�7�1��3�M��84;�%���b`)^��y3�d߯�:�������^Ĩ ��
+���Ҧ{�bۙ�UP2���U�=z?S��V )�?����1'�*zq
8O��<[��n�@�����P>٣
݃T�y���W[k�����e���;מ�����8$8l�%��ȗ8���������s$
�%	�X*�ӷ�:z0v�j#�Y���qI|;H�4��
p4�O�yƚq:��:��׷�c����.n �vG�сk��k�y,9V�_W�~��Voՠ~�i��C�T
�}����Le��wZ��pތZ3�rjtڃ�S����f�8��Z�����a�����
����
^��s��.��J9"��%�+$�� ş�ᨾ� 	�t�o���Np�P����RN�:؃����e�"�
+������[�&�U��.3U���ɑב<W @�:�>46��Z� ��Nv�Z���65Sۈ��%< ,+X�l$* �ڗM������X�%�2P���@ X�j�.��⸠hu�o�kRu+O�vm������P��9�/�i��x++�t]^<��Y���׳Q=���,&
yN���%�#͑�^
���xo�l��^c����Zg�z���/wz������l�>��j4�p�tA|�t��c�Y�!�]Q��=&c
+7��S��:�ا�h7��kr$�r�M����:��7��9{̀̐#Si~�p~
���U���M��Ff`�aL��Bԭ�
0P5,�@a�Z�)�̺.m� ��R`���%�!
��h*�7�p�d#oT듒���㨄��L
6�^�U�g����mk���(�-;9��m%ӺI�s�մ&N*D�ˣms)�Ы�p�j\6 3�D�;�J��Y�
+���6B����*[!�ݭ�u�[�
+bۗ=�"��"�
Յ-"����l#i�$h1'W��E����Y��`U؜T�
+W�%>�I�
+RU�՘ʳ�uo5��;Ђ(m/��)
�ԙ g�^<u�Tl�s��V�`Cu�z�Z#fT븗'���ڴѣ�&��L��{<�������fz ء8�S�h��
9��*A�:}�5{��nN%��U�LO�­��Y�
��������N��S����~�W��X򍦙¸q{i\�IHˆ��m	����#-���(�?oz��OS�
+��OS��V+��A�9�Q�iM[�)({"�ٷ��|Πk�|.���� P��PA�'�}z������lLg��cY�/k>����6~� ��Am
��� �z�F����TpG��(σ����v�(w`�X·�Z�#�F.u�� )��&q#x��4�ٱ�
�'���3ҷdV�Q�&窥*o�&u�o=���q=��sl/�����ߔ�eGe�V�QCUq��b�6R[�5�	N� �Z6d��l
#)�ā�!w�T��}�1��7-��
V�)����/�]|�÷�>�����͇��_�r�%�G�)�y|���7?\�?<z����姫�?ݼ�O~���1��p�Z*v͕�`.�QC�@������tgr@���
s��:R�ӴCd͐�e+:
+�0�N,��7g�=y�p��I�w�������o��ͳ��~{����O���_^�ܼ�xM�����o�����~}����ЃÏ/�����|�	��C�?���?��|h�?
���tx�_��
�����O9����x���G��5�W�|�������ۇ��<�m�]���۰ʍ�Oop��Q0�rz��yt�~w۩N���rN��\w�9����N������91<��ƶBqq�簑�SbI>���.OU��y
+�¾�~�b��A~�Q%��[�$����*f���h�M�I	!��~>
u�q�]d��
+�	Ŋ��"����/X��2H:	�
$�%��2��e���-�s�<�Ρ�,҅`E���W<��U�Qc��W I&@��J�V.����w�N�^�I��� ��5B��D7�

+.��khe?^1S�y��̐��e`�%JS��{�I&#��i!
+����F��4>��s?��nõh�J�vt�q�C���n�n�h��g
�TӜ��&�3�
+>=	�~%ؚUj([���<�pWu�_�#�fM[8���l@�T��D�a�˗RHD`���
�,�
+V��Pu��q��`�R���7/A����\.H!2����� 6c)��27�"͔\� Խj���u�V�V
+U
��{%�(�ɂ��m`,�-
��x�t�~_ޙ���p��G�^�L�i=����X���/�IƱ��o�[�s��%�Z�M�ߚ=Lk-�֚���n��I�8?��X.�X���6�eFkqb
+���1�Zd��sP[�l�}h�~�u5�C�,Ou�-��cUF��|6hY�M�����g�QQ�����C��x�����u���������{8
�v�2��G���/,��R�*�T���Y�Y���莙M�6��*s�+3�����nl� L|k��v-@�X���Z�4��XS[�����F0�T�XtS܁�@�ćX[tXM����E0��)��FP���I9v���+%{RE�
Kh�EQ�j(R�S�;�uzA�}�؉o��1,?�8��c^w�"�_���[��O�� ���\UG���W
S	�
+���
��f������U��ߐ�nò��4
+f=��U�����G+�u\�ė��p쓄�6e�P�����PQ{�
��&�
����AՔ�
�vr-�`~&�Pjl��t�Nbg
��m�qx h��峫
_
+�o^��Q�܍�r$�W
+�J�J:*�l�%��j�+h*ӽ��T���uOL�"T�K�y
�����ok��Z4�������U�1� u�F[$d[�p��fշ�X�#	KXE�ڲ�XH�;�ȉ�n�\+�@���)��E���@<��<_W�d�r�@�Dg����62S�Ui�
j3��Ǎ�{�Ȃˆ���`�lZ	�}�l�By��
+�s��\B��ي7��3�U�ב����.(�Cվ�'R� ��d��t��8�
+5��~"#����^|D�ee�i�4�j����d�
+���ŬS}�d�\��d at g;ۑ��$[���8�����_����o��~�~䦷
�����M�����o���~���?ݼ�~ĩ��o�m��퍙���U�c7��`E������i.���r�����D�IV���[S��:�|:b�lPͶ�t�([s�>/�.I��6 �T���ѐ��F�@N�{=sv�R��Eu 둪yo�h�wǤBN�9T�7�,��Z�Tr'
+�,(� ���2�)�#R�E�g�4�C7k���G
+5��$���Y��Q���^����p����u;�x�lt��s��Դ}a 
+�*�npoR�,J��y�N(Ǡ��
���ue>�u����x$�M��K'*�!��[�QU��� (�
���,K���;eS	���}�t2���	�S���HՂT�$��h��E6B����Tm����@�.�T���$cҎ�����Hy��
'l
���b�� ��@E
+k?fFD珶 "�WbS!B�� A�
-HiH\��E���
+�E
+"|�W��
	lIi�b(g�
+��ԉ���>� �=;�Qvn�8[�+ÀK�r�`�%�~�Q���,����y r�20i�'�@i
+���v��
�.�V��C�ӄ����4-�X�[�g(u�ѝ�P;5	xƭ� ���S�)j����n�c��k~,�S; �����B�>L'�w����E�:v1Fn���jwr�t�QT�A����'��OTI)�F^�.����'~H��y�oZ��{ľh[-�
p�^�Xf]}A�+������3g�~�rl�*ʘ:�=�2
��i���)5��%:��]�/x�됓�P�M�9k�!��Y�F���܏��[L�xhja
+tTn;���tR$[��W��b�
+"����R���Ԗ	*��"a��8t�E���A�Z!��rwҞn�tM�M��R&j�s�D�#:[�
TDA��
�⩶��Yҽ��P�,C����M�u]@34�Fk*	��萖��
+Q��
+
G���o"�����Y$4g]����
��
UGq��#Z���O!��7B�T��%(ܣRހAU~	��(���n�
+Ò�!Εa�G1���b|�d
p�!��o��{()0�����A c�Rg�5Q`�ō22��e�N�fn��q�@T%/�6#�Y
�!M��e
�@�T�c�*Ca:rmB7� �9
���|^���u���3m�>������3N$i��[c�~9�<x3 ��I�>I�|$G���!��p�s[N�X�N�����j���D�OKkj��g8z��A�v�
+ȝ����
�3��i.�6�
Z���1;�{
�V):�7D?l�҂ӽ
�J��C��c�-	��#'H�ҍ�*L {� ���XJ�V�.�CTǞ��ч>�`n���Y,$E���V#X���sd3
�R����xY�Wa
��բ�҂	Z�i!J"�*9;w��[�L�]����.�M��m��Fo#��������,
�
����%B>2��*�:3����e0U^1#��D	,4*�:�\ϲ< �x
`��w
�Z3'$�i
N0�eF���â`3�'\d
'��];cS�$��8��ʝ���N�1T���׻
+'��0�atZ��BC��2&���3DwTx%��GG���e�� DݯH�������+'�FY����T�W��Q�@���V��
�/����e�}�`QcQ5��wc��0�����	9�_����i� �
#�)w�E`
+��BUq�RL��������F����<���Q�|����F]le{.���[���
��s��<���{r3^��,�f��y�
 �
[�V�à�X�� (
�,��3�:�<weu�
,������]G1���2f�'���55��wG�m�[�k�x����������;����4�ݵ��z��+og��w
��(8Z����r^����
+\��
+^�yes.��壜�!\N.�^�\���
�ru1:?�����9��-l&��.�l���e�5�뫡R6��4�R8�����M?��
�
���_4hh
���uw��b�2�H�X�׏E��j>���K�A�FO�ma�ي
+��2y^�<0U�U�X�
�Qt
;gј	�\�l���S���Ei����
+ƋV:�+׋
j�﹓�;ӳ�skL�,�����9
�
*�`����&B�'�*��� D;D���#�
+:� `yf�pӃ�y5{|&q���	+�`����T�fl�:H��&b���Ğ�������,X�@ޤ���,�	U��/9st=�+8�˧��e� ��j׷6�/'&ibX���爰�p�G��c�E�Z�����
+60<A,=�d+�H cd�C�H�XE,K�"�=�Q���B܋G	
u��p��
g�WR��Ɵ1�9���r/#����V�(C8��U�X�(���@
�ԋ.�" ���,���f�mE�<�|��h��-�r��O=f��9�gtZ�G���S��)h�P-Y��{\�\5�r�̀��p)��Y�|�f�Kqش�+4:�>b�B��*�Zu(hX�bw$��˜P��2@��k���r�f�YC�-���4���c��Ҫ���B$�cx�Y�.1��J�~wf!ն1� �IZ=RG"*�cgѨ�b��%&!XMd�������^~}~��}|���}�	����Y��7�ۏ�_o��ί�.��o��>>_��7ӏ8�3�I�2́�p��	��02~h�ҕ'
���^��A�
+}X=��������xOX�$�nM�|~��`��,��
��n�����
��}�Zqi�Q�%���+
B�$1n��N'RU�(5X�]�7�
}�45҄~&��gq�r��L(�G��j6�*�0��"���_!��W�?_?�\��<|�<���
���#�}��/�U�#fN�A��
�(�'9�
��B콈K��E��yl?��KK�B�V#M�V�$����f�l�?��M��͠�6C��z�l�ʾ�&�
tz��n�u��A	�Ĕ�]ؤ�f:��]dJ$���)Y�9�X p)�0�d���%e��D�� "@_���g�	l��m�}³e���bs�c�]���ϧZ�
+�궀�ݏ5�M��� ��qGr�
u,,Pg��+(E1'o84;
���k'�̜�'� ���6�ɨ��!�JҦ���Y�.1.b�<1c=��疢�8���L4g�)'����;�P�(x.�����^�1٪��#�x�@Yv���N�>��O	$�tS�`^�kOb�#���Ș.�B
�+Q���;r����_QĂ�_*�˿�㹷Cv�am
+���@�����T��r6G	 =����t�F%2��Q�v�;�Ղ�3�f���
�ħv�u'�dSo�Q�i�����5͞����
�
@=�N�Ͻ��IJ5��~۳��ߕ���S-]�iֳ��-��EI��
N��[]!l])p|��VhږP����ș���� R�A�~fZвsb�0��u=3�j������:�Bߥe&/�Ǽz���Ha��c%A6��w�:{'�"6͵ȴ���<�
+h�]�z��3ƛW�����g
+JuӐ@���(�A�uU�D�x��D���w�cO�6��1	�a$n��0�g
����Ѩc����9
Ϲ���������}:O	�V�Y���}����w�ˁ�ގ� �NQ&�c�FVJ}־��/��I�K�D��E�u1s�p|��&h����
��9VY/
!�;�n]1��,~��XZ盋>ɣFK�����U=�*>|y���
��4���;�r�vŜ�w���C
����>����a��L��rp*G5�bM��&��[�\�l
����[�͗;���?�gA�Ǘ���%�0��	:��
;�t]p>5_�qZ* S�8{a��z�|<��V�Q���BBY��
��j��K�
+����8.�#$�]p���J��fc��X;�
+��f�ó�u��1�k���-˵�=(u� �
p�*歗K�F���`[���z���Z�1t�I���8�s~wu�퇯[���?��6����K��
�Ch+��0�x](���\��i��F�\TY����B&�"�s��[A�0e�=R1��B�˄��a�1�(m�V�xy������G@�;�
���8��w�R����:[�
��v
����M�n�go%A*�7 ��9}OBl�pFw(׎�؆X��G/�ԣ�
b��}�L{�H����H�&��b�T�x;<��i
��o)Bb*a�<�N�qd��8\�@E}
�.�\Z�����~-h�����w�
+�v�Ƣ1ݝPև�R��Vs��� ��\�]߿�#��g�_ �R$D7� ���=�W�d�
cYK��U�L�V*wV���Oe�҈a�W豨o�b�/���0��H[Ġ�d�y
+����Q���煾=w-Ѓ	�8���o�@���ܺ!�,���J��M���)G�����C޵xu�D5��1SH�N�k/F�}-!�$�N��
�&�����
+�x�FK�������O���-��W��*
���W3�uK�:8��P�֋V)�?���
8�WUjR{da�|J�a.fr-H����f5���茙z����k�>��9��J�
+��_:��?��&G��0�c�
+ �io!��fx��׍�}ό����Y�:/Y�~n5��@�|v
+D���p�LU#'|�gU������(ŋ)�s�M=��
Q (�67+1�?˲'�<Ҧ�{ 
��x
�#ʰ�xd�oP4���B���	��>K�����4>�����)�(Sښ\
��,�Mܗ��ZcÖ

n\C؅\9�)�zk4]l4Ӟߏ>�
��De˷��$��=��� n
2(g�h��J��8�{���}�����vV_�3Y
A� ��
+�}"�P
�J�lO�v%T��O߰@�2��{�xQCc��`�|���l�q��
�KNN����0�,�;�Ō��
)��ڽ��8�^3��Ao#$߫�mW��
����+�}ˍ�χ}��7W�����DGwD����=����������}l���!
+Kƃ
+Iq��c5Z����IXp��P����4��ke`x]>��MH��G#�m���
+�4������
+���
+��E�A��������b�o�E�o~+/���y�v!�
��;�H[��P�[��rƎ�n.u2��N˵�+����e���+w�4���|���t ��y��n(��
@㯰���c�2�Vw���0/��/��N^���o���B�†�
+
�{���H����l��
�\�S�e{B"���Jh�.��2n��w�ā�*��d�ߢ�l��9�f>�A�G�"��
+�?��#���*��!���3E)�o ����
+endstream
+endobj
+16 1 obj
+19217 
+endobj
+17 1 obj
+<< /Filter [ /FlateDecode ] /Length 18 1 R >> 
+stream
+H��W�n
�����y ��䉔�`g
+2�0
�Y�(҂�>���zzf�2+O�@j�����.�N����Lfzq�K��'Ӌ��|�@��n�&3G�����9�8G��TBHs))O7
+���� �e�&����G��](�o�4�9�J�-�I&��\����
�u��;�D���Ԛ�Y?W
�|��6�`�ge��5��̮�f ���K��
a:y��v��8�ןs�/8��A�/
�gR
v��~�H ,��
+����ݣ�_���}���ݛ_��O��
3��SLO�/��}sx==>??{����ٯw����7��~v����j�������������_~�����=0x~���a?~~8\�\]N
+���
p�����8��?��M���[@�0}7��.i�3���s
+��� ߬�Tg�P�	�|��A��G���C#���g�.R�Yd�U���Ԁ�9coAudTOsTsH|Mp�
+g�H)0�k+�
+J�}n��P�
�:�za�n�B�蓩�{�"Q�(V��=1�1}��LЉKM Z���
ũ4��#�"�q�nŝ��CbI|H����.^"�6��͂�
+70:���l��j�����}4��v������� "��F ؑ4�l��#ǁ��j�a[i��6��VZ���v[S8ؗ��0�
�lu�G#��)�m�a�4ժ�j8B��������I�I�Q	�"�o#Y�(1��N�&�Dt����O% D��6�V

+0���V���?	��
+qE�Ţ���Vj��ďH���ӨŁp��6���v�'wL���⍴G��n;��f�����}v̓����Qw��8��j��j�~7�p�����cte���Aa�A���=�C�oZh�
���p硓
*Є��x)��I
+��L.
+Wm	Z�Q�‎&8�Ժ���T�v��%i���t��j�KJ��Bm;�4D�6����J=��D���5%Cr����OGY�Y�Ȯ���g�7��J8�J�*��O�5ކ��U��_XY��,g��m[d���O%������s�i�����(p�Ȏ ��C�
+�{�H$F��I��
��!W�I*uA�?���TS1"x,�O;�B�<=m��ldw�>k(����u�|�J62Ϩ���R���0H�TR�N:��L
��f�5N�B8��8����^o��1����ފ�%�>Q8� a���"5�����Sa
<�`�A�I1��b��	Y��$5A��e�y����1H<�7N�iq\�v�ލ��y>7�ޟ���
+;}�;�
}�ѣ�����L0��j� �3


!�Ϣ=�D.qO�X��=l�0
h���צ9V�`����j�P!Hl� ��HirO�
��B	��zT�}�(�/���
Y(/����a�.;1	�'kkj��/F��
6��
uԾ�R
�(��Lk6���a�l5x�
�G�p�Stls����bl��Tf�AP7k�v�j�
+r-c��!�6�уQ0�_V"��J��b���X
���g��G�K�}�a���f�������

+����i�9ޔ7��
4��
��[���P��xF�.K��aӡ�&^�9A�����h��1}��k�I&� /
+'�Ch����� ]�<T���("+�
�l�__
���t
N'�jl{�V�:Zﲈ��y
P]H,��i}�H��_�.B�u
6�Fۦ���Nuk�F�|��,�����G|�G7G\k�I�r��5�P	$����	q���+w��[��)ӯN���oQn��X�>^9�yP;�RH���#o���^kW�V=��h��޵DB91ڊ�sR�	��)Y���3����USͺ�:�۴��BӵĞ~=�r�Z��*rMoUT�<)k�y�8E�Kӄ��KCG�yY��%���B���0$W�
25�G�BT�/���J�h�k�]��/����5�i��^�8�k�@o���Ї�+���;׀�M���(�P��'a
����K'�.Ylz*������
+��
+������ɪxk�>*�)�a�XQUs�IX
�$$L��dR�Dg5�
+W&[���"�f�Qզ�Bd5i� �Z���H�>�t��JU���^n��pT�~���
�
,��1Ib�5U���v��4�.�>�w�V�����'"w��V�@�j����\��+�v<R.��#(���fn���EgT%^�g{
+Rg��%إ�u��JaF����X��Tlz	�
L��d�@�~�Tk!�^���̱����q<ZՀ<(���E��š6ۂ���u��d�ߍeq�(���~�;)�8>l���.��7M��Q�n%�)�<��v�ՍԆ���Ԇ��I����	`��kK�+<.���Ț��ڝ
+�~�
���u�4�:�e���E/��~�OL�z��o58 /�WB���ITJY�r!Յt*Kئu��"��^`�U��᝔�^U78pz�	��Ob%��&�~
6�Xd��l
8^{��C
�u�D#�V�kuIT.��x�Ԙ#�5���E'�h�s��,�$�r,70'�P����j

�bm�tcw�n׎�%uX���X��0/ۗ�+KDžQ��J�N1�>V�Ko
��N�y�{t�My��������/?\��]�
<�z�氂??
.n�.��NO�	x�
?/>���j��o��-�S���~��L����N!���I�
jN��
H�>
c�~���
�1�D`*!��9�O��р�:���c���jۓ�Y2 at Z^�ށ����k}��
�^�JM�_oϾF�4�$�'��4���+��v�-�x0}� h�
}�]9#h�a��~��+�/�?�%���^�L���b;y�-�Z���[��K���I���JF*�f6C�S�:uj c��(�|� [...]
+����з�N�Y��Y��aE�G�
+_>�LfQ
�I��5�U8H?��h2�|u.�+K=�_&�<���*�HQ��$�_W⾸� �"e��Q
���J�9�� ­1���`u�
+��OZ��Uj¹��}͸* P�����@eW�A�Tԇ�lD|�ʪ� �%y°,��k�d��(g�dA��t)��+�.�G*�k�c0
+��ق���3Ã���˭��<

-�H=u��Jd��2�D�+b�v1��*�m�L=�0��>0,�iT
+
+tTG�r1
+�����b �����1eu�s�^v8�g:K�ro,��Xj�P+t���#�#`u�1��}�9�7M�
�d�J#l�~7K_X�*��媕f�������SK��媮�ڬtmA
�¯��٪:����m*+ᾑ=P�\6w�Ӎ��2������wh��6.�{U�V�@
+V�"Yp��Ū��,���qe���h�Z��<���W��	����R�gv�*y<�� ��{r��nf R
+O�
06:��#[>�
+�p�N�ש
ѼM���&䐸z)/3&-~y�/� O
+����
(x�ypFZ��
H�U
U�ٖV�QY6��"L-vsկ(�@5�j݁�yy�D���e�8
�u�N6��@�4V������a����Q+m�������=*�Z��lf�V{+�H�d�J>�Xg(Z=Lz��ɗzP�v�[����+:�
�[1�P`2�ٵ����Q9X/��]����r�
��r�Ṯ���� ���e�0���
9���ث0ڊ�د0r
���ݕ1�cn�@�(��²�1��WWkX���/��Dᗘ�)
�ON��|�~xs�_l��4���#�p̛S����7����|�(�<�狿
�NR8����i�C�v"�#f�ߎ޽y���Y��>:������*�vz��y)���i�i�
\���
,��4̿_� eQH�&�ℵ��S���i+� ;b6�R��m�A�X��$��&LppPx�,�$�c�-�`?��@s�q�i��s
+��m���{=!�*�:�$ei��c��%�&�f
�j�߭����^�r%,E)^,4=�$��^�d�`��`a3�Xؕ��+[��hL���Z��k�J��R蝐f�~�#-�~z-ȟ���,�Y�޶��p�
��/��	���c3��O_��jA��8x��^�
Yjl���o��Q�`�y�UB;�Tc�V�N/����a`���<&` �MĒ�ȄkdB"<?ib�p�9LL�����҇��01�;��i_��������Ąpb�"Y�0��l��k�#�t
9��
��K��'@1.%��>0"�x%�E
r//~;�'��fHKO&m[
Q
�5���"fF
��f-
:3zP,Пz�dE�����pM�~�-�K����
s/�aL�p������ON'>�����'�ߍewh\/0H@}n��m(�V�>sj���z����,��7;�t9��,���Nb��#�Q�ܠ#{��VQHCc��HD���e^Q��d^�h��{9��h����B>M����c]f�c [...]
+�]�
t��}%�O m at 7�0�N�^vM��]�n}�
4�����K��>����?���A��
+O�F����z�#��M�}z=؟���,]�����[簠�~a4�xH(�
+�=318����>P>Y�Y��I�����%�}xs:���#�)���5_�}S���"�ѽIz��Ub2cYb���]No׳��ۜ%M&Q���;�^�&7�
�
+l�B9X�'1c��]&k�LJ�}e�Su��r��A’<[����
�y��2t;�'Ԕh{� s�b���Ջ�ҿ\��<�E�W��L=���Á] �U�wY<�8
+�.��k�'��<&AJ�M�$��O�>X�[����^��)I�ǘ~� Ս�la�
+�uJa�����F_��`S\���,
+w�����$ߌ�R
+x$�z��K��8	蒆�5Ya�
��޺8�wؽ�+�񥿀ڻv�D�mV�/$
)�PN�|�\��
�6�:������A�
+���I�I��Z�Eģ����'�mb�c���-�$�֭�Á��ՙ���f�0zn�H�9j��k?q�T�z)�ɒ���g���3��z9	��I��"�sƹ)=�1�߻����
���՛nr���$��>0"��A����q�4QB2�P������^ �C�e���R�
�ϡ�у�
�᷉g!%]DwL��ܨ� Ȗ7+�q�Ht����f6c){0r�銓 


+���R
+
��I�h�u&Szo6�����6LX��v����{���Wa3,uȽ����<��lۋ�ߠ�qD��d϶%���g�&�'#
��^�z��ӌӰ�O�f�և~
� %�&b	O�O�>h�[�qp�Y~�$�c�-�T7V���Bb'���ly
��@��w�+,
t���.����q3�0��qP�����L��z��K��8	蒆�5Ya�
���8�w��+�񥿀ڻv�D�mW�/$
)�PN�4�ML�piî�z�I�
�ڰ�/ �hr��k�Vq�(�&��	c��d�X�C�:�
,b�m��p��hu�f��Y� ���:R��쮟8x*V���dI�Hx�3Ss��h��ٶe����u�#��.�$�]�FĿ7�@2�!���kߛ���(�n}��%y�z����!�{�;y5a��;6<��gS�N<�-� >7{�i�<>�@jBd�ta��6��K�u
��F�g������;���"��yL��.	ܻ�3���ϐ��/��M�����R�0Ɵ [...]
+I'MP�~K��J�:�8�B�Ok�_r�/�(+�䢾*�Q�L�ޠ<�
���W�M�-����P�h����2� 礆�[om�Ҩ���������PC4�����c�5�+�v�"����-L��
�K1&R���m���F	4�Ԏ�"R�M at 5
TPGm��;��h��&���PM<5�ODj���l
s�}a�xx�J�M8�%�շ��8�Q
+��X#��c"��8����Q
+�
BdY>�C@������H�C�jA�B-�4Tk�n_�J�v��V7�uZ���w������o�|Ѣ���e�ݤ(�)��}W�
5��`���hw;D at R��|�]��I#c�#�%�l4j�1���Rm����5h^Y�`�0*8�hFcl@
�x"b�L�K2���_T
�,����s���\�R?վ#�pO/��:{=���
/E4[���b+���oA��N�
W�)��Lj�4"�������Ӊ��	���^6�-����e�u;��9����vAT��z��Ma��+��->��](�t8������|��JT�}���w�
�h �����;9��-�>�D��Z��1齊g�5�Y
�َ���~�����s����g��?T[/�o�#�[Oc*k�5�N�0��Hnb���Ef���0���
i09���Ћv�i�9]r��V�� ����dt?�Jo)FQ�a���/������ƅZ����D��S	�+��i�:��~�"e�ݤ�� [...]
+/��\�E�L�
�16����<1K&�%����^S1����^Df��-.C���"R\9�&�!�8� ���Lt\)�^�h4�bWU�Vx
+>)߂���=�8��!�
�bp�au����+���|:�1�⳹I0�([�/3=��!�iD$�� 9��LK��@c(
+r���� �M�b
+endstream
+endobj
+18 1 obj
+6879 
+endobj
+19 1 obj
+<< /Filter [ /FlateDecode ] /Length 20 1 R >> 
+stream
+H��W�n�8}���o�Mm'u����xch�b��]@S��.Ej)2?}�O�
E�-���8
+ILK�p�9�h�������n�;��p%���|�v��B!���1�O�aqz,��;�����ə�
���
�?;�I�=>&�Of���|�����������;�/Ҹ��(��{�5)!ގV���γU(sN�A��H�ՅO�����p]$#H���h���
+b at 6Rɪ3M�Vs���q�o at .�E�P,tr�.�bC���qK%��2����

��ZD���[\z��W����߭;���و'���k:Z � ����,"d"yC�T��=
�( .y�/
Z��"9^��j�����`��!b+@������7�!�D��S$R�.��j?�$�A`���
���}�d�ȠO�`��z�Z6*Bb��F�W��	�nq�*#�&�I
+�_i &8sS�^[^$��\x	U��p���� TE�b��35�i��p���dJ��
+W���f�Pi"gH�>�*E��c���7R{ә�%P ��� Y����R��8.=O~��"AR�G̥F�Ԇ�g���/�D"�"���W�X��"��$tr�K��
+�+"n�=��]&S6�W�

��ZD���[��a>��RO�W$^+J�x���$�1��;�X��7B&
�!{8( �,��	�y�		�
/ ��
	�2��H��*�K�I�A�X�.-e=�v��V��x�$���&.��ŵ�}%!L�eB�i	�j^�Jf���C�q��6Z�
+a�j�5L�
�V`8Ua�����i�ft���-��C��DYMٱ���I�٥�"���5^ـ
+Sx����=櫓&Q�)�Bl+o��7�+G�h��o�v�
]�M2�����.����I�J�����X�z	�Ѯ���tP�X���Y�k <u�!���s
]�ng"k�b�a���,C��mf�ug�9ӳ&�؊�����ER��][�c�'8��A�x����c� ��U
+k�.���}.
��%71DHM2jN��^r�D����0XE�R�:$���ym�wG��
�����+e��ظ����cN䉰M��7��DYMٱ���#��!��%@�>���N�g@\���
�V����A5C*	<���Tv��)i�!��jex����a�)��T��]�K�~����
+��WU�y�k��L	��u��x�����"_�R��A�
��A	��8��{Ўjk
�v���6{��
��A�
��/���{�������^<����o�g�C	�\�C��, �H�
��.
�A
��\O���C
DR�%���0�]r�#j��Qs���C'�JE
+sr�������^w�c|�}�
"�?6�\���Z�$m:4�CbP��G�BuS���&ei�.2���Hbv��6郪��0���ohB�z�8���������~
+��<ZȦ�U~����Bu�S"�7�}�%#UD��$rJmhl��RI$fU�\b�y��JS-Xo$H�j�N�%�Yl�c&��
�Xr�e&#f��K��<�BHJS �
�������kB
+��H.$bq���ǁ����E��<�u9l��e�j����e��7
\��=
t��].��W\�d��d�qPr��$��dR��u���
+#WO�]+7�Z,��d�\VA��O�Ք
�( XX
�i��ib�Q�G�ϝ``8�r=1�p��*�^�ȝ
���$p�ެ�?5'�J/9t��ppr��pw���p�;�1>˾T*��I
+���WVO�HB J��$�����Y�M����,I�����'
l^�};i��ۼ���"��ข%���z�ߕ��r�T�l���Â��0>
�삇��w����0|}��L�3�;�oؙ|M�
).�ۭ	����gZ���i��vij��*���.M���.MO^�8ȴK¥iLl
s"O�m��!x�'�X�(�GW,'��v�iuP�L���a��6��F솓��;� ��k���3��JQm�d��~j��y���mu��uӋ+��$z���\�@��i at gB)��^�6S0UB!1�mE��ªi|/��O{� ��y*�wؙ�IE�rs���
�<tj)�T���������^ocL��]%�Aw٨�ib*;(�Tو
+Sx�[ׇ�x���\��N5�oc�����o����
+�&{?J�{@�Ы���Ø��|�\O�c�`�	��Ck�G�h��H���o���dJคmǷ7�%
$�M�H���V���	%p\G�)�KgqۧJf�	
��P�R�F%BB�A���q�n������SÜ��k%�IĨD��i
G+�	�MX�"a�
[��H��:e����p��EJ�
+R
+�Xƽ�׎��e�mb�0F*���i�ft���-��C��DYMٱ���I�٥�"���U^ـ
+Sx����=櫓&Q�)�Bl+o��7�+g�h��oc$s�	�&�� dK[�]����	�̘-A��}�ra
+��hWn�h	:(a,���,�5 ��C��Q�ș�eX�o1ʰL�-F�uG�9ӳ&�؊����� U�3s"���;Q at pT>J�Vw�+lp�O}G�~WVO�`��,��	�K�kB
+��Ug.c��Z�8QVS��
��j��P�)�ٙf���=D�}o��K	�KI��2��Mz�H"^��%6���
��T��0J�Z��T	��Ir�nW�8\�~'\�ymk����1%	��
���ͪ�[�[�S�
D(�R���8�D�� F鿡�o%[-��x#v�I�
��
D\ȵr��1�j�T�:j[m̫���j�x`�?@꽥$�A	p� ��S�5Sn��(K"U3�\����*�BN�.&�E��ᮺR�e�"��QPƫnÆ)<�}cq�<�C�URB��:���
��~B���d�\i"c�5��������?a}
2�2��')��~�8b��a���Gs�^N;i�v�Kw���:�&�g�Z{�<��/�x�D�<��^f��d�R�R�*�BUU�؎yl#ה����e_
+��)B{�gw.gΜ�EX��K�w,�ϑ�~]�ާ�Be<ޞݑH.e�Ǫ�m�o��;�Wܭ*�<=9}}�xwby�b�=y�޳だ�_���ߍX��끜�:<{~~zۢ�n~�.��������S��[^�_?_b�k�����FNV�ݗ/�F
>p�}t..nKÃ���)���e?>��|��7ۃ�����]�?ܽ
Ë��ы[���1��1�n�`��g;==8:{~W���|c�m_����d{~�Vv������{��Oph��]m�c��{i��W�?l���b�뜞�����_��>VSS˳oOO����ԃn�;<ڞ\���o_�
�_O.��?}�soQo������N�����7;��O����O�)��O/���Ï0����7��3m���v
�$Y�Ժ��Ғ����̼�Q`�c,$�l�lN)�Q��K3c_r�'{M}�o��n~/�ٶ��nk�cs��7P
v4/��Q\�����Z"/�c��-W{��-EԜ�4;�?���Ԋ�ʢwծ�"�y�H/��nn�h= [...]
+
+�NQIv�-2z
cJu���~y�P�\�1ƒ���giIc�HKn�N&��m~�恈��.���^ Hf����(�݆�����*K�CS(x+�a ���k�.�M[������Y/#w���^n��!E��%2��DF
-��ӒP��̚S��d��oݳu�w�e�ge������������"�p
�r��àFE�+B֋ua�؁�-��@&��	Z�QW?�s�0f<��y��y�����c��7wћ�{��v!
+a���#�h
+�J��Y�"n������Z����q�HI�F�qF]��$���h燝�$B�ї�N
��������D�i
纬{4��
^��*��ai5�X���
x� ��rԘ�7jt�Ȋ
^
?��{�#4
�b��(I��ӥ�S��x0�Y
���	�����,�s�~J4��4j���7o͟��+
�Z@�+rt5���
��
�y0��N9�p�&n��96jk��!��bNt
V
�\�M:�
+ܓJa'��,ጅr2Y9�9Ŏ�sˊL�ƹ�i��$C�2Qف
�W�{~&�#Fd]Y�FV�Ws�AD�8wP���>D_��<�Kv8��Y�Z��A9��8�J��)���gι�d��
�����w̴��F�T(/�i"V#�
+ܮnTv�K�֭r���4^�8�&������A:�6�	�9���$��03q0n����{N1Imଌ[�H�c���A���G*�oj
+�q�l �bvs�
:�x֘z� ȁ6�J�Q�F��@����l2�f�Z�Θ��q<"a��t
�1��"y%�|k���y��S�q�1C��TѢM8�^�Zm�J�1썧
#��6��=��{ps����}sU�]�
'��6���9�f���<� ��s�N� 0���1�:�8
���Ư޷
+[��9R2h�O��
+c��(=�y��4��N
�
+�k'�r������u���jE
��y��ű��9]��S�u
+�z`%q.a�CB�&uզ
+��ՕкwR�3S�
+�Ӎ�y�Uݿ�2TG�R�%l�F��iY���q��
+��iDW���?O��`��}�T�}>?�1V�&SZc|G��,k�k�<�H�5U���p�.�t��
+�
+I�Z�H�Fñ�(?��I�+0r%�
�T�d~�
�%�Z[�L�}�P@��%��,1�D��iAZ�
��������6:��dMdR �2΋>j���대r
+U7�H��+��r�X��Q,
����Z���T��G`
+C��H���v�éU����d�T���1-%F�_`�
+e
+T��gj��6� ;��7F�>������
Ojj�<�(s�\@�0(l�!���:��ˢ��T
P�l�s�Vb�O��t
+��@a o��,�k�l�#u�+ʕj����9��M�6��,��4��F���x�p��������������0�{�&ɂF��y���l{r��������������z���78�%�N'�-y3���:��Ȣ�ƥ�jl=�q��)hdꥒ��Q�&�@� ��
+?�$u�,w���Z�č|ŵ]�S�U�b����r
���-��x5�����n��+Pn��hf2��e�X��)����]r��<��M�`GE�!��P)?�d�����b�{�+05�;+�,3�h��4�ry��s�܄$�7�\�|�@� աmz]���i�!˧S	$�.�&��^ɹ�/@u���i�	)�\I5Ї䆸�^$����� �� v�“�Pt%j��Xy^���u�w�
�EJ�%�b�`��s!ETH5��d�1ؑ��z$�#��`�
�h����x&é�����@�Ԛ�]����J�K��z1��Y��9�c�V�[�t
�P�<�}��-O�%ׁ����Dk�Ȉ{)��
�2P�*���U�Ⱦ&�S$��X��C�z����u�mX�z�^5a�
ϡ8�iZ���4"��[�.�?�q�
S�����U��0
_�?���q��x�w �����ר��I<�;�����R�V�E>�Q.��zN���s��I.͊�	Qk8 V,��b�ԉ�� [...]
+A:sv�|�B��P�l�������O�	b�p`6���!�@��,K�ĪU�!

��rl����
��h�8��EX�eI(�E�d_�չ� �u?���@GKZW���O�
 �_��
+endstream
+endobj
+20 1 obj
+5839 
+endobj
+21 1 obj
+<< /Filter [ /FlateDecode ] /Length 22 1 R >> 
+stream
+H��Wێ��
+~�}��1`�Q�N��nӋ�	R�)j�(
{�>4^�X���C��~if��(jcO�P��P;Tje
5��O//j�˻�ߗR�)�CM!l-�z�����
+� U k
+�@h��Ĝ��S]l1a���rQ,��
+�)O�u7
�VB<�[���
+. 5�����ѺU(d�DT�
+���
+!��,�$��
�M�+��-!��SC�~U�m���k��Y^50|K�Ea
+���ɆP�.�Lhݨ�b1,�Q9H�ز�
�{��r�P��~�X�(ES�$F������%-�
�ڈ	W�"Qj�@�o��L0�
+�e�3�A�T?��//�p��"
��/�1!�W���WV�^C����r(l�4&:�9;�C6���V�hx*��R�a�*���ق:���Ytx5+=e@�8
^���`�QN�������
���N�u�[Ze̔Ҫu� ?��
q�F�T����b� �
5v���u�'
;�h���O�q�:ΩZ� Q�����{k0p\&�tk�
j����:X�� *؈�5.��k>5d��Bg�ră�o�(:�VS@��aΦQ�c:<)K����
�؛\zge��ͱ�0#����Wl�Ʈ]�go5�b��j� �'c#9'G�I�2�ܟ8=����-����_��`�BI6LAmI�Ю�
6��a�H�z��h�5�V59BZ4��2x}��Y�
����&Զ-�4w����݂r�8�)�^����i�dgB썇�X;��5��W�*�pTP>�������䜚S�(�?x������o��߼�����
=
"���������7�^

^]]^_�����3}t�
 [...]
+5I"�$U
V>�dvF���î&s(T
ҭ�6.�>K�a�Q�0:H9X�cfC����'%#�SFbTzzi&@�t/M��A}�#Kg��y{�/���W9�����ۃ�� <���?�>�����y��!�>>����f�z�+7���|�%���p�Q�oi�n����|��_��s��z����+
^t��O�C�n>�9�WH��G%J֔�?c��?����S�,R�$lIK�u�P+~�!�z� ���������a�$������~5E���gn��޼{�g����VC����Ӈ�����b?<��~��������n���[��(�:D���X��@�I'{�p���& l�dm�ܓ[lh$�AL��Ҽ-4�f�;�a���?�^���Л��I�}ѭ���m��'�w��\|)�����^����[bʕ�ԫޖ�QͶ��x1��Q����^�'u��U��5�������V�K~�r�̡��	{��
+f��VPy5�]aYC����飮d
�žl}uw�#��,����iQ:�n���a��P;�J%2�r�c#�b�$8<��q�?�6J�Q
m;�F7��z3��
�[���
�ft�
+��jj�'PYc�KߺvY��5{g
��(k�����v��%l���z��35t�svm��c�����/�#ƐRѓ�J�,��f�'�ҟF�-���Uz���7�]TX��k�9�~�3�����aR*L`��z�g).�áI�獶@u�mϼA[���ɂ@�6��9Qm���a�R*U�͔_Q��	T�XAiq��Ǫ> f��(q��X@�s��{o3�
�ukg��פ�
�
�^f�QH��5��
�
�wk�ކX;wm��	^��a�
 �,�ϒ-�E���ʚ��^�䤩B!"G���:ij�,;������HK刵�t�5���z��-��{���
+m��F��e���C�ġp��
+��).Jw��W�
'�R�*��|\?�A]7u�
NMZ�`��:�ώ��֝�ddKu�#4'
��u�%[ ��o�;�����V^A[Ŷh�@�@�s8Ά�<���m�5.
��Skg��פ�
ƞ
�����
+�xP
+�
�<��#�r=T�Mۖ���R�*{�"���4��	t
�=��Ϛ���Z���X0��^.G�ïI���XSY�Cy�,��-�UM&JF���e<j
+�_:�q�bs"��Ly�;��������PV������BQ�s���z9,�s��β�֤� cNH\�;^�Ǯ�k�0�s8l�K6%e��
�sTb�1�
+k-�d�%J:̮p��j=���P�xg)�~��
�%��]v84i=㼱v<\1��[�e�r��^:Xs��2��
i��n�&.�
�>�
T��ƍ�.�U
+�3h���MNP�u�Bf�ł򺵳��k�z�#h
��
������4�s�ѳ.S���Ӛ
+��\p��ط�]T	:͆�	�띺@֐P�IcY�l���ĩ���piRz�}%ZXgo�G/~��z�?Ww�[���̙��M^���^�h�鬬���ތ���ZgP
+�����%׎��J��
��
�ucg��֬���.��o+�:����6����ḅ�|D��
����L�D���t�EV�P���8�ΠY�o8��M���V!$b�ł:yj�,;����r`�Q<\����@?�G��̭x��JnIߟ��S�<��Cʜ
�����:�#���y ��K��<�T�8�òA`ȗ��@$�������g PG=�U��Sm{N7(]S��-fO�+���X�zU��ʂMꄶoOl�&Vn�Nw�w��n���U�g����
�
��ċ�O�.;U�&�R�~̭J@'-
_R��1|�G=�t
��.�f{5��2�td������zԝ��y����oi�z�[6y�y��
�$+N(�\��"��v����@e�)�h�g����KWp��9\�����LG
�؂	N�J=>�qv���Ͳ4�V]<�+��~��dNAvr�`2cxD
+
��N%�
+�ԅ#T�,9��91{���X.t'-���8����'gb�������S׍2��e���8�
]���:IS���f
�t������8Z߀JZ�C�
�e[��[WpZ�*�����|�ˑt����ٍ�u[�'
{i�e�넱�AU��^
Z���~J1{t
<�Uޡ9�S�����$K����r��.
��/V�~)*�l+G�OpR���ٍ���0uq�|��+��Q&k2�
+c�0�\"U���!5x�����Hc:u0m
���X�:�i�
�!�:�V�U�ӂ	*wn�������s��'?~q�������ۇ��>-��������o�^��|����ջ���o_?���ų�|��=�����v���w�}���������<�~У�ߋ;^^�N�wsQ��ϖW��xzy�����O,r��gr+ëo/���
��?�B�_ڋk�q��U
��A�?O�������~ο�t��/���v�Sg���?�g^w̶��A��aU�
ӨjP��-�6k�y��NTI
+�{
�J+:�p���4���%tt����:�>�!d�Qb	d��E�
�]��uz�
Z�˵-9�T\BQ��
��(�/$��[��2Y)�)/��)��H${�5)]�������ѰCA;�d��������w����&���`
\�#Zx�~�E�C�٘
<
 6�R���CF�9��+\`b�!|E��)�BS�@��֯3pU55PI9[�/5855�lAK��ܩ����h�I7�3�?�+>)
Z������aE�����W1��������~zxg������!O�?<|����{�3.0�}���/��Z�B�k���o�忀~[h�f�׿�r�_~'�;?Ϝ�"3Kl�g��h�Q,�M�
+Қ@�c�6|s���L52�\�
�f|=��R���KI�7�Q�3峧`���bЦ�)��]����㏱�S�RբJ�-b7 �L�
�ܝ0�I���4LP�D�
��v0�
9�Nl�yC�.ۿ��
2����l�^
+Ѣ3x��2�}��Q�Zj��6)/��^�6�2��h{eQ
,�$s��$`50
+t�kW�A5F^�+��{
7J�
+� ��
P��X=`n�Ym��m�.�}f�2�t��c�L�T�&�N0
OR�/���ŏ����B�N��$�<`�4�7M�����tm�Tsmk�p��`
+�/h5�II\�C恤9�p�*5|Eb�h��ܒ��R��5���3��W�"�
��-�(
G*ſ���5�;��������8��"a�aB���I��5Ӣ�{��s�$
�r7�{�;q��J5J�
+g�~�b�۩��bjr�_[�I����㋾��6��Pͷ<�-&�;K�NY���K�XҲ��a�匛�����e(	�D
+K�g����ڿ���͔Nn=}��k�[[�vG�IZQ�fn4zT14_>"�Ȇ��G#1B4�����2QM����TP�� U�Q�,�S��-����(Z�
+m=�x&FCA���)䄡Z������1Ҳ��a�'+Y6s�ω�-ێw�Yg��A�N�A
+��m�o5ǹ�a���)��@
+��l;!J�러�
+ܺ�mI�Hڊ
��DNŪ�Z��W�͗�mG�
+�B}���9�J�M��88[�@iV�
��])��jmb�}����A�T/jT�9�C��v�k�+��Qm}[_���
+�f at B^
�g3-Ak��Y�e��^mj��G�5�%R6
+���=��'�1�U�A=�'c��(\R�g��\v�;���3z̥
+f�6&�8i�.uK�n������6
+�w{g�G�L�F+:R� �N�Y�l�8F
�M�gV����	�`]�T���1������0"�}��D���:C{-
+�Q�rJ�����a�Tg��[�U�P
S�%ӷ��
b��t��p��0$�˱Z�M*���t�d�콿Z"�D��N���z2�"�]L�x���d�
���KYv�=�s���R���Y$�Y2�bP�=<oR��Z����r1
���sp7�)x�Zc�A�m
+
+0�h`4�I�ѳ�Cb'�l�^�W��,�y-�8y�qq
x�jgk+�#��NsF�a��k�b���K	�0e+��/��,
+V2Z��ϗ^5Y�m���Wض�%��<��Ԁ�� J{��b��[
G���Ԥ�H#暙�B۵���-J[TWG2W�~��a��
�
2��2�G׷Y:V�V�UD�m
�%琦�I�a�<�k;�q�N�m�=�4pĤ .�I��g!�k
�W�:��f^g�\��!ѱs,�cE3OAD�Z.6?����>3Nw�j�t��J�SJ���o�=˃�.yU�~����JQI�"��SDf''x�%����uD$������s��d�����P|
s��r�
+��-|ƋyՊ&o�Ʉ�K�����
�����,V���s��z,���4�Ƞ��U�ի
+�D͛�u-�i�7�0����%��$U;����A(Ф�J�1]��a|KX�<`��Ci�T�߲u��g����]u��
E�	�
����
]]�W��AAAE
=	AM�H�ۻ�jU�xB��|�]]]�~tQ�R�vv�� i�5"��+Vb�a
������a��{F���(
rpI֠`����
�
+!��{V&�ace9�޽󖻷�K��z��ܓ��&͏h�y���)�����E�羂�
��,���
+��[����}-!�� ����.�ɞ�e^���3�����V2����%9J:�0嶬'_,�@
ɯޑ;T�Y�*Ab.½�^~�%�U\_r}�ỗ}�&^�?~��g�?>�	�~�ů�������������߿���|��g���o�}���?�������?��P%e�=���ǿ�n����|��
+~��!�
���ǟ��
_�^�
0�#�������l*U�>iL@'�[�.ml�އc����Na�����i;��������
	K~~e^��ޣ�}V�����Ԗ�1;���R��T�;�
+&�'Ih��VK,+gy=�j��ƃah����5S6���Zn]iĂ@"ز�=(�ݡ��
$'43=�������:����}��4J�3�= �=�E���z
+�=����J�g3R1��ؚA��
+.M%�=��
�
�^vi��8ѝ
+jh?߀�o�V��0�4l|���
Zv��WT
r�3Scx��j���f?{�N�Y'ջ~�M�� �
+U�J��IY�d�
���R�
#��gPo��Fu�eA^�q��#
��ȌöI��W|q}L�fR�d�q�s˷l�I�28Ʃ
+� �d��NwG�F_���a���v�SA6�pYU�$Y=�NY�Ƅ�A_��aQ-�RF���L��I)�2U+w4op�Q��g����8����	�k�GA+�x�/��W���v��f�Ի�4m�*����:����8�ߢ
����(dZ�w���j9X��g�{Դ
.9���	(��C���j]�<H
����
��(A�|��c#��
U at E˫b�R�TW������О��YbsJ^�f����c2�r�|�"Z��-e�k�j4�/��웪���V�!T���R�8���ck�*5>�@���&��t2rv���V⡳�CoPd��O:���#kNp�j���!��H�:�M�
K\����J>�/-�H)��
7H��pۥ�DOn0�ԃ�~��Q�+S�6�578�[
���-{�7]c^�6�f���d��!}W�Ԓ��|�(�K��)|�~�����wZ�]��grmrmok�3"Rߊ�Qz;�_�1� �� <�9��z|slB�c�UҶH(�5xկD����� [...]
+S=)�����m+�~%
+�j�b�
	��nm~�BI�o�<-k�W�
�<���y�q�����^�� ����
����ce0��C~(B� �O�٧��̝�w� z6E:��B'�
+Ye��`�9�"&#8���@4{n�}�,\D���L�����LIM�˞˛�d�Do��n�X?7��}��b)�
��?�.�w�K'�1�v�6Y�nC��
(�AA٥��`$`��k�(}��=(i"�+�mU�q�����+�;|W޴S�a���K:�H*,F,Ǯ%�\�(�a"���Gl�J
=��|C
0+���;�jH<�^�T륧���:uNs��:i7�
Z[����搕��j%
`Ix���
ۓ0�5ȕ���u�Q�j'�{�^�VK�4�z
�����:��X� P:���H�Z/��[	����)嬆P���ZĠi�,��p��)U�s�KR$
+2OQ�A~	r��1&
�)*sS(-� �b�/B'���e��P�0�
b͕\����b&�#vv#����}d��D*g�*�����ҍ��ϺꢐƵ
�{e$${����4u
+�ǯ�&ool |;�0���`�dl�p;/b��d��jFP
+�x)cM��
�E���E�L�����F�"�4��ϳJ?c7P�_w��i��{FZ�>���ƞz�G܆��&E "�{�5��z�v��"�����CK�B^�
��R=�g�����gX���M
��J
+�6f � �FC
	�
+S
��*�?�EU��2W��`p}��O
澴-���
G��@�
��m,`Z���?ņ���<X��t�����
�hb�8 h2`�)����S:����t�lȠ�,q�HZ��hdW������dx�<Jj��N2Dt�\S��o&
�l�Y3C�Z
���)��x|�ik|j߳�.j�HuI8��޵�<>q`rB�F�B(����

9���s�9��t���l
+�9o��#�U� 
��)��R�̜Xs��ub#;�4V!���=���`?)����
��� ������U at WAz�
+�ղ��oa���Z�060IJ��o	㈐L�w�;�%ƶ7��4���)��S �a�sq}:FB,.�'���/�����෣�R�'w%���we[5,ǁ\���"|�;�;����!
+��
D��*U��]�֙{�=T���):��mTm�
���EV�蠍_8E���.F�
+��V˗峠E\nW{O͆~I�z>��U�h�N!%�lb�35c~� m,`���[a�B1;�U���(O����2ULCu�o@��c����(yg�Ӆ�>�I��
D��&0BH�U��o�˳V at s�
+Z���a=K�)��@
+S]]�ұ3xбϳ?S'X��K�w�J ��ղ��q�@�p6�==��IV��1��EvFز-+Fh��Ouw���A
ĩ33�\���*l.q����WFS�m�
;�xreS<ᢖw"�b�gp�m�{i. �#8�F���v�8��In�<y��؜�0�����F6������B��<a
��:��M�_��z8%�5V���`�X�:Ƽ_o�U$n�y\V
Zl���/�;߶XVn,K6Q�*�������{O=�n� m,��x~�I�{��9��
f�	������t%=������r��
�׮_v�T�
�-I
�ABm�`;m���\U>�
��ue3�J�a�u7����
n�X~Vca&

�
P�5X�W_���7>~�����͇O/��z����޽����~{��ۿ���������o��O�!���!�����
�W����E���6t����j/��
���~"!�J^��|�;a1!wa�2�U�Nr�{X������Rz�G��ճԬ��P [...]
+%�e�ȇ �E��R�)�D���y'�U4bf[�:}�V;�Zm���[���j>tF�\���9�p�
X�������^W��5~l���?	{dv���.
a݂;�*�N��c�R�;;ǥᮺ�(;�xB�b�.��A:�^w�L��́9���_���F�*���td��/��
+`Է�>�,)p���oB�
d��b�zc�5V�T΃h�s00��B%-G	S�]+���+MV��M�g:-�#�@;�N+�hT��J<�ܯg��j�{�	S�G��A5�U�]�-���x�,,�5h.�@hoM/�&(���˲-���
��E�i@��J�X9�[�}
1��$��&Q�yw}�����׍�_i�Ջ�p������;�� i�Ux�'�s�ӣ���z}0�y�Y�T.y���`�ל�2�*���@�=?�
+h5 `�7T�z,0�A�
`�86�W��|��t��J���b�VCr��y��nN^�}p�u���L?��~)�o��4�B/�=fi@���o�RHM�� ��?���"�,���V4*Gh���4�����W&t��d�� �
�b�ܿ��ֈ�;R������Qa�8JMi�1
y*��u�Q���N���u�X��Jl�-����Ҥ>�4>AH}�案R��KlMb�P#yqN��|Е�|���,bv�������8�c�']e���l9���}Em~ˡ��ǐ�<�-A�x
,�l�@<�k.��!�%
���v��C9<�!��Jؖ�:i��s�Բ�k>�߉�f
(s%$r�@�
5ڻޥ�΀�4��1ឯ�F�
�ɛ�ˡM�|����p>��
u��;G�
+E��S2��g�J�h*,�qx�y#'���Z ��90J�A�R��5�(p�Y#M'�ͪ0G�_��E}�Լ�qG�qhOؕ.wU���,���j��:����|RC�
�)˯�T� 
�<wOO�e5�k
�\0�?�5��0]k`��� fl��>0_vh]�ꋥj��� ��P7�:����
@
+�ò&�$l��XX�i$��!�4�ށS�
f8gv9����.�V~�s���ڹ��
���Q�C������
+�����Q̇����:�r��[e�{���}Z������M
�PI4�n�<
�,\���
 ���kq�AN�ʐ<`>
+^���p��Ȯ4�f����}o�@��$;�����U�m<N�lP
sY���:-l#z����.?�*:D_G��
+�z�Gt�f<6p����ù��wp�
+���^��ܛ�h��pa���I���
'��� Xح��� Y��v�U�I�Mw�� n�5��� �!�]��c�1m��]��
+��<�$�A�\U--��(l�n )��<&8��9�2O�����|�2խ��\E_\Twr@]��F
+�����P��[in�v���\s�
R��g���Q7V
+�	��R��,��Ĝ9��a4#���@Z�JG>V�j<m V�m���H�A���
��,��hy���í��L�e�!8�`+]��Ln���^�s���q�����`�,)�*W�e9��MX�p޵'������-���2S
'A]��~���
ʓne�CÁCXh8��/�^�I�A랿��=�����*?��*w at C��q���I)�CZ�m����`G�Qa�r<9VIp��A�cu)M���ƱA�	J:#A�l �f��Zx Ⱥ
+![
{�E�����l
�S�{1P�'��܇`�fHU��'�)��A��R��	"�R�ھ
�цЂ��T��Zx��vvSzp
����
+�>�T��o��)7��
���%
D`韀-m�4ϳ�����H(�����vƜ���Sӳz�&ի���)Y���]�����B;��<[R�G��X
��$7��
��i����� !��N�!�ͦU�P�iF�ZT��~,�5�!��$yEҪ�kq��U�yb�k�
+�q/d���	�}��kV�},�2$��S3x�bs��?9+>~a��mK,��UA�,�G�����
��O��v
�Q�:�簧6ǭ�S`�U/h�=���Ӡ�U�R�ŷ=��i��C�
$���O�O�j� �k�
+̝��]�Q
d�M7X�aJ 6'�ۿ�߸ɽz5K�=Ǻ��`�4��7�G�f4�^������X�z����寃R���,`�w�ء&H7�\{>�3���9��"ij�}�R�=sU��q��YH%`x�Q^)�U�>�R:X�cv��VEw������rV���U��l�?築��%H�>�H��.�0��'[ER,"��-�a��l'�:A/##h<� u��w	.Mor����P�\��,� �٥��+XJ at L"�M��s��q�
+rpk\�{O��`�AkC����O�3\�^�;=��	�B5�f%w�@���^ "��ؽK�NM�;�G�8���5k�J��V��:{
+E9K@<��������Y�$~�g�^�o��� �.���V�5
<%HF5HU��\l�J4&
��R�QY���
�D`�k!�[��/���S׈yQ@��K���޾**5f;�K��"���� |�X�� o���
+���Z%�
cc-3V�=H���6�x�R��]c�j0�[�Z�����0��,+�z��@��A�c��E�[j74���@i��yY�W,9��)�|G��T�ꬤ6���o����
+Ӗ^
W����1�V��{�#_���v��9���%�`�ξ��)�� ��6L E`D@��O/ػ�߳�
��
�l�튀��3R0�\�=���
+q�cg�
���~����Z������/5��޶l}d��l��
+
�b��
aI6M�x��bNM��}-�A����%�r@�~�V�g3ƅ�ev?�
ܿ�>ъ�{�[d�
�������j=�\M���E�!���sg����m�j�`��"9�[C�/C��
ǣ�bƗl[T������`���e�����wM� �j2�,�����f�/��^3ta����:
+GC=��
�W��Y���
+�4�PH����2���9��SeZ�7jɪ�$6�	>�P[wִ�
�d�x�U�!�� n�ۀ�
]�m�$m��� x�� �3
+�
+�Z�~���~-�2�o�>#
��M��*�ȫ�R8*�ދ��p)�x �PD��vTO��\�n��\S�_�;�j�àj���S�;�(����Լ����/&���o�j�����?�q�Z���=��&��:�������Y��j��O�"�t���9M�ۯ����!��f�U=U��\��!��zz�#?e�[Q��4f��+}���N{c1�r���w0���0]D�������@����� �}��zM��Қ�-��
,�i?+�z@���Vr��2��z7{x5��IH���E�Z�)
О4�A�n5��y�$�Hz�νzCX" C�4�Z�
pvF��i�3o\!�y��DT��~�#H���V]��"x��s-lC�^�� �؞� P��v<�֖�54��J�tWZ>�m�Y��x��v7��,I��
9|�O���gbm>;����B���}o�LS㎾�6�gS�Q%7� k��؀kݠ��iP�J�V��5$��V�
�� [...]
+�R�{�o�1R�����'տ�����|`���S���6����JWdž�5HK�d� ���?�Z�&�/���%�|
�-K�Ce.�����{7����*;�\G
�/������3��q����8�;�#Gm�i���~t �ֻ.����j
U8[���M4�S�*����9��#�UQ��
+ۥo��l�4�Yu{�
�Z��oluj���RB�Q��;�Yt�Ez�,-������.R8��nGLO��^&(Mcm�_P���Ҫ��Ö@��$�&B��hF�V������;`J��x?��>���K.�
gS��_�
<V�j�T��8<	�>*N-#�����m��H7�@_w�!�v��fU
�����@g7���*u�O��.�b�^�5G1M�y�*}p>Z6qUj�`�:�N���Q��p3:`��%[7X�K��6%��?
+p��l<����?��D��[��٧��,3f;�_ ��PCe�s��$�����1����O?F�
+�.5
�XK7��J�ġ���� ��o���� r�ʌ��@��*A:SP�v��K ��7A<�y�s��;[
`���&]R`C�	O����s:1.�8�vJ��n����1�����m���
�Bhcm���9���9(��>�nRb.�{
���C
��`��w���?�	�F`۴����Wmbh;	�lM� �4AT�ka
+�G��x
���<`�A��G�.��*�b���^`��8�L�S!%XU�:�
@��D��(-F-��?R��mG�W���� Tn�TP�h�qk����?C@,"Z��g/��+W��&Ao�y��&k��������H����+�^4@̒M-���
+P8g
+��s�t�q�툴ﲫ.�i�c
� ���6��!�`���
.t+Y�+K��� ��"�?��p�:��f��F��qR˨~w�w)��	l��ÉL�%3�[ۛ�;�J� �F�ƾػ,-
$h�bwo(c���g_�1�NZM��^��k���DbUu��GM�i��w�r�hyi�W��+����
��
���u@xz���
��ョ�±y�tq�qW#��v0�:`5v)
�Ώ���B��G��#�s��۶ �c� ��
'�A�-��/�
v�����E�V$����#�%0�"��k����JV�i�:�.hd
+� Ϻ����N،�C���
+(��OYU`�0�%�I-�r��njb
`[ɊAO!��(�Ѕ	�n������Q�+�����돂y��T�JyqzE I�	6L�w�H�;��|�uie
�;z/c
+6��GL36q�E�*�-%C
�$^uod��|�WR�����#Ko
���֥J�N�wW��� 6{"���5��FK�$���h�uE�m�����}��z
�e��7�
E
�7ȴ ���7���AsBA���Vl�y6
�&(�Tr�X^��j]k��O����>^vևf���f=yPL5�%��� ���$�q
af� jᚉ{�q�	]A��Jx,��f�?���lƣ�;�w��`(����1U0���+�"�
+�3�a1�6��.&�TGދ�bm��2(Tu
��D1
+5	�X)��[��)��JŽ�����&/�9]
��
#|(�%�q� �*��1�B���)Dڪ5���m��KP���#�-A̅��^�j/@�A²27 at Z<� oG�$A+A�@���&��d���GJC�ԙ��O �-Dû�����`�q���2�e�,� W=�9 ���EI~A)�J� D�'�z-�h�w�VN��_Ԁ(��U譪��GۮV	y�q� �z9�����@X]��d}���)p�ġ��8�Q��[aS+i��+�񳝽>o��S��ݵ������T�O_|nߤf/��Td�
��N
+��h4�: �b=�z9���b��,rAJ�	^�
+Z�m����üw6
�o�p<�ϯ�~!|uN��ߵ�巿�2����
w�ⱌ�Q��f~c{����-��:
&A6iụ�<�2
	�H�9t/H�>(���#����~�*�[O�6ue�C�!���md�����5��h�`�ħ�cri�I[ w^��,��
+0	��'���:nÑ-#p�
�
�h�NVL]%A��>/�:�\���}��YKh�ջ�pt�
�'��� P��	���$�_T�*4�ń�+�C�b�R)$�5���K_�j�Z��YS�2U�] 䇘�3^�#�0~�1|�1�i�W냘Geգ�`w�M�G�5��Mb�o�]𾔟�	hɮ�69��D�-
ꏟP��a�r
���@
+,&�$�b� s%��
̪
� -�VZ
+���՜��{����-B�B�5U�ON_8�ߠt�]�X�uL5z�
�G�;��g{-�.�+V
��+��}�&Ǻސ�ez>A:������a)���'ye�@�
+ A��Ɖ��@�B�-�^'(�FSr�%��:�ܷ�w���#���B���|��$_;�(UZVĠ؛邪_
}���1(?���WR|g-DFU~�?ޟ����޵�E$6�P�r_��|TQe�)R�ݑ+�j�k��մީ�+���)���4��ar;UH��
�y
��ׄ
�ǣ}B;�h;�\��ޖ��;19Q�_��%<��j[���F�$ϕJ�LI{�^�X�s~��֊� ~��A�(ay1ft����i=
N��[�/��MV-Ck�0Q�w =4�24��m_������qn�n�.
+50
�>~cF��v��X �����9)���ץ��SY
+�ߨ�4OwEp�����>���&<�$���I#P�k���	Z���\�$豎Ӯc�%GFJK�3�?^�a4҈��CƸ6�
g���{�ȲNe�Cͳ֢�2��'�N���Or��v����pN���",ekmH籲W�����r^ <�tqέ`s*Jb��4�lÓ�㱻I]WWcz�U���M`�)�����S�A��ؕ�y[�����O 1M؄l��|J*�<��{|���M�t��T={��j���y�	
���R�
+O���?�ɕo���u8�ZI���
�1\��5�E������݀�x��� ~YC��H�KI{����%�}��
��F���#�Y���ֿ�a�k���r��
����##��CT�F���$�e��z��\�d7�
p�\����+	.�"�\���;F?NP�:�J38���9|N���@xi�[m�5��6(���xP`8��]�
�ũn�e�y|f�;)'���C�����
4	U�ES�y�U̚�����e
�����1���������}�Ҝ�"j�R�����l���I�Iql��#�yF�
+ at wֶ�*�`=3� sl���ky��ŸWlς�^��M����H�BPvkw�%A�
tH�o�
���aA���[�d �G�:C
+�hh��+�M�6�;�����!ۃ�����k�U��
����0��^*�Fp��o���
~+�D�qX�������T�f/�p ��� �C��`�'8��_�� �������� ?�p�F�.����'����sT����z?Q㳿�v���-x��KZ �{�g�HG��D�L��2��ֵ��B��1PV�eg2b�I��d��wgI]x�
#���4zR�����V4�Ӳ����c��C�t�Ƀ�\D��Қͯ��
��2�E��`';�x��>��
+-�zT�j��ȅ'u�TVkN�
h|N+��
��aP�4,y���
� g.�!!
)>X{N��6t��`
+�G�#ۊ�|��Y�?$�L����\qILܪ���;| $`�pa�ǂ֒Y9�a!����b��_��UT��=���,��M��՘u--5ߵ�$�0��� Q����y�p
|�ܹ�G��>�$%ٻ��^T
촬 ?R�\/�W�U/H��e�R�0k>��
��}�r�,kFu	T����ΫA��{�
�8��L��b�\bq�e1� �Z6UӘ.��Z�a�𘉕�8x�T _u\���\%�(����/�z�5G�%|c�qr�/�@&�b1m�Y��N��ʪ��Nl�d `5�
Cv�
+�"�/ٰ�{���
W�%zj),,�G� ������p���^�����N�K���ɴI��ļ�+���jv�:���
�)�����8,��`Y�+�D�7~{����~N�"'ו9s��t��й�n��y`�k6{ɡ����.Ɲˁ!�ƼYr26H� 3�� �yL0�mK��H ��=�� ��O'�
��^,]S�X�\+
+`��`��z<�ލ�dW��
+p[�	�g��}?�5b��,����>Pi�j���dF1*�O �
�}'an��>**znj֯
�&h�7 Ws��ܯ�!�������<���R9C��`�|
��
+�;�+i��է_����^}�Xq8tt����W�
��`u����j��GKeM8��^�X`�������M���±���+C�I1}�s��i����
p�$(�#�D���^W��.�`4+�yZ�59���z7�}�,p-���+���
4V�
�I<N����<?>�Ğ3�D��� [_��V�t
$LP]	��Z� ��T1���^�}oj��%+����5�֦e����3�֢�&a�
��&���ݠ��|����
a6f
о>��Tup���f&k�]–��gUuOa/�����~��l2���DÕe�{�ҺNZK��?%�!��֚`�/O_F���#_�;FmIqQ�6[���G�ĘR�y���pو�æk�9��h*�����X�}U
����	���?>;���ݨS ���u���	z�G�Y3!���jX2v[G����᡿ʃ��h
�k
�VS�9R�v�|}���W�y��|�?�Y���
ur���!+�V+0O���a�G�
l�<)Hj&hE [...]
+�5��,خЊ��{�
+�{0�H\ѩ�Ffe��@�O^��N��jǴRL�q�5s����o����w��|z���?~~�
��������>������������������O?��o
�咿��%����X��q:G�A����Q�G�e��8�����M�������"=z��#A���&
Y�{�|�T=^d���
+��m�`�8Tzo�ЈD�1W8�p�R~4��m`Ed*V��*�w��䔭;:e����c� �3�U�A�����	K��y��z�\�	N��� �]߉��A�_�"�v�V�<kҬ��
	�SH�
��ڀ&R��{H[k�	���xR]������k#�|�!�r��|�;������8+��8t6����M)6���)�>��d�!m/����=f����c\��}�e2���.|ْh�T����
+YW��cxvb��Lٚe�M���Ek�_�J�(�#a��U$3ӊ��{��ƽIL�

ƻ�Ϗ-��e5�%R/��;������Ƨgc�]�d�I
k������wgԑk�K@�E��p���j\f�PS�lU+$	Ƕ^��=�9��1+p�R�:{
)�2!ռ�EC��y��m��[dI�om6�6���~��SΛ�:$q�ݟfj��@S�5s�b�j�3;{Y
��6��H��u��
�B��uo�@x:��-9T��݊Ig�� �:o��������D(��&e	�� "���	f�ǚn���FM�|�S
f[�ș_М+�E��F!<��[�/5��
�����'Y�&�Q�`ߧ�%���e6J_�nԹж�+x�~��g��|_��8q��d
+�g[z�M!�s�mm�	�d5A/\�P��_]�f�y
���Rr,E0��ʾ�~¸
-=K+m
+����'xE�-~>>��QG�*���ݩ������ۭs�@�	n6��8C��
b��L�7mp@<R�����ޛ��o}�[��`����#}T s}���1��}����
���ii��I^X��~j.L�^u��f�_���N�{�W���A�uI�D+kiGl�;�
�+]1����F�v��DL<��f
pX�]�/�I0�I.P�٤7e�
s�X���)OŬ�b��T\蓂5g�H��´d�J+�	%�b��ӆ]�]�9�tq��-�n���K��tP�Ⱦ�|Mxlu66��.u�+Lk���7��k��a/)suJ�r f���������_{4�۴���5�J[���y�����!�O���	��j�I��	����!��${�䯍N��R� ���T��@C�{>>tC�5]䛰�&+%
+�dT�.�p��U�
��H��I��UQc.\�f(;
+�XW�eJ6 ���v-h��9�%���3��^抗�,"�zǦR������j
k�L�Sӷ��
P�{�`�&z�B����
NC��d\��+ED9T
�(��1N�+�g���s�
+i0%�Dgq�����A� '��:!@Pg
+n����"��
���K��Ozl~�IdH\V��&}���A��I�N9��r� �q]a���5�=S��nE+��vlo;=�J�-;<2׮̮%�<w}i�Fy� �4��<��e�5aUf�"�I6u�Ҷ����b����H�̌	b���-�3�LsӶΎ.�L�P�!�e�$9�H��AC>���8��_�/4[@E7�ܳN�x�� ����<�z�I3c��Е%ŵ�nO�
����k��� %g�M��喠(��yW4%o�=�gq{č�Jɣ��*4�H_K�+�pb��u�j]�F���^v;z
E����w�Fș����#g�P��a	�ȬW�q�D���wOuw�|
qΐ������;�]��s����{�"7��k
+
Rx��!q0�H���1�:V���E�S��x���[^m�s��:Bޘ��R��}���`�ò�_�����8K�8Ǹ��|:�=Gj�0�;�o�%�� ����0;~�s���aF Q<�a@o�����Nm�xk�c���
@&�TP�4�$lb?��,��}
�c��4!
Ú�2!NY-
+�Ύ�hW��Ѿ
�����$�}u>�æ
L#���`Y!�v�M2
+�A
���
Fǃ�Is����e 3�R�w��#�@��A& -��9(�w=
�ɧ�a�<�i�Wn|G��f��V7TP�X�[��mC��΂�jBgD�+���R�%��&PtT�-c�[����v�Z�h�;��}>�eK�(AFT�FkႺ�p��}�G��h�f��^Id�HͶ�q
�\N��@�S��f<�*�
�뙼��j-��UR
���lQ� �;+�tQH�pI����㳢��M�����q����:�t.�ō �B(A��g SC�%���g'�I�i͚��Sm�Qs��������h�^��PH����&��o>{���on߿�����ߠ�����g�߿{s������/������Wy���/�x|��]��_��?��E��g�� ]���`s�J}���U��P���
ł)���R�W�6rgY�B�2F�C+��!��E�Ѓm��
�S��FQ�=°���5�I�<P�Z+5h�/ؓ�-5���r��%aS;��]�	���A��ψ�5�� [...]
+8A�����dl���b-�nKe�XF�;�i���]�t�mކlΑ�=$��c�>��U����pi��8 �!G̾��	��ֹ�HtӾ�m$��A3��I~5�w��~�I��U����6˚��o�"5���h�%
vYĒ���t�Y�K����]MEacu5xk��q�
���
÷	5ǖۄ�j
&�qͫ�g+de������fY$���W��4K|�Ԥ�����r
g��`c�	�v����"6ᨴ3��:��5j�%��0�S�n�̏���#��#2�<�H\XߨG�s
+�p���:��,2EU��~&�����4M�1���#Jf�Y���9a�	��*ym��ٳ�Q� j,#9�v�!F=�>�I�P�V�<�c�
йT�i���(�Ƕ��a��m�q��0/��H�s�S���hh�W�6�eGf��u��
۪��3{�!��ِ���rIe;r��I�c���ɾ�R�Rg��z�W&֩#)�$��F�k�� P�>�K5�
�Eѝ+
p���N=�!�'�8��8������s�XlMь=Zf�D���u�T����oc
+d)l�m�΍���
+�SC�rK}�e]r�9 at E�<��N��{���ьOb�YL�C��������Sx�K<t��řE�G�t�y��,v���>qN{�S=1����
�آ8F:��)�� �� $�s��k+v#�+U
m�R at 2[��Kᨉ��D���~��| ��r��^5���Ip� ��~
̓�]�jm�R�хm=
 kdҟ��MN+���Ր���p�R����A�*=n2�>g������
 %P&���<�%��|�On#����IKs����:�х�U��s��5-i�x��ɇ_��
��r�L!_� �%~^|�Sy��yy����o��O����ݿz������;����o�Yy�����
�Χ�y��'?�ϯ~Ŀ��G�|�����e\�t��?����W���v+���vCm��
�7��Y�!����}��,���'cB�eĨ�m�Y��]��e�3���Î��1�6
+�eQ�GY�3C�x,��8(z�rܰb�j��Y2|Y7Y���pU[�����l�j��HJ�6���C̗0z(��e��#���-K�56�
+��2ر({����
��"��`�
T Ѧ
�D�9"�ca�
^�LJ�����ĂxL�d��*��P�F����f��w���:(����$l�߳�R�v�s�v%�9�I����y���R���^��L����Z~����<6y����`�/�:w�>��-�^=�ĢV�JX���g,+� ���5�4
+�m,.�X5��Ƞ������r��E�B�z!��+w��M��Z
������W�V,
+���v�.O ��]&Njym�L�}������ձ,�	Ί��0�d8�9��� l�
ғ�>�����$ۦiz���F 
+�ْ�9(�6
��j�T�dc�"���Br�h3��o���5V^;��]��LZW
��<`�;���K��FQ�
�%y\��a�+�Y�g� �+ 
du�Q��2��^��i��
+:Ӕ]�-%�Q�.y�D]�.�+�#m%�!o�yy��r�mL>��(2et��� �%����	f�[��R=�ϑ7�n��DޏH��zr&��2�4��0x����i��(�	s�ϴ$p4D<w�*�}z#ZqQ"��G췹ߢl����Q�#��nߤg|���B�M��a�.���튭�T7çZ��Zg���r��	̜nh㵡��'t�VE��޻�ۖ�AHx�9�����
9�Q��-Т,���}+�k�����k�6�Nc�
�7���OV�GO�zu�Kg��
﵇�s�Y�tؓ�_����֌C@۷�m�8c����F���cg���e�1�x9SԠ_-j�z.+ˆ|z��ձ)jӔ.jIO#�����Z%(9�
�!���a�zk��V=Et��C8�,��;ϧn���0]mG�� ,%�
9l�'@��ߔ���<$9$�h�o�t\{�VT;1�O|��af1��	�ʤ�Q9(���t���g�m�1W�b�뢩h	>��] my	�vM��4=Ad [...]
+}�]��>.H��?s��+Og`���K����AW�
���L�F�
�#��M��;�
+[¡9
+Zs-CH�3��y|������%�$�מ�H򒷿7�ם�v�i^P��qa�v.�����)nj��=B��'�{�t^�_�EΧt�`���ت%'����0BǞ}:[$Qtb�$��4N'�^��Qz�;o
�����
+;�ax�QzL�t
Ag�m�L�ҝaǃ�e�{}��/�iʤ
�qJ^I����Q���-=E��a�Z�T
+~Y�<�E>ὖ��MVe�!�4'���_Z�@�hAŊ22�|B��\%�K�56Y���}?k��̗���]��
+��k���1��nk��ↆ��h�U�R��=eu�s�e�uv�$ư�0.��Q>�|�Ė�k88��O����˓o?A���m=܏|u�����T՚{
+�v�2��<
�:�A��y��<���A����Սb
�6\���x����[.�w7�?�qǝ)�1�	������^�����yi�������
+��A��:�7�G����okF���+d�c[1؊a07A�B�}
:��
 �e��
+endstream
+endobj
+22 1 obj
+22917 
+endobj
+23 1 obj
+<< /Filter [ /FlateDecode ] /Length 24 1 R >> 
+stream
+H��W�n
�
+����~1`Qo�uO�4r�l2� v�A��ZŖ�d���sXd�t�Z�-������L5�b��G.%
+%�2�P�p�s�0{Ce60�/
+��p���Xk�F}
v{N�p�� `}����W�c�Db��9�2�o�)�®��6T��|�6)5,�ɇ�Q7R�
+�c*΢
|U���">��)��p}���S�V��.W,A��1�
�QC�#��S�Z. #��G[Kɱ��
ٶ��
+ t1��89��
+xg0y6w���0z*A�Ɯ�@��2 at cN�-�~������`��ZWG�b
+U�����!VN���,�2��v��v	e���(t�+�\�clks����3�
+:_{�"� `B
�:�����e
+mmDr�u�]R0�BO8�@�uZmgA��Q�^�X\h;�ZʖZԥ��$�����yr�������7g���?t�����o?��8=���b�˻O�/N���
+��U�lh8��=��?���#��'��#W�\Z.KE���$�|I�9k��j0q�z��Y���j���e��W�}
����1Y�J��
(�@�,�ʞ�
0jL)A`��<pi9G�p�=�!����f��y��������py{�����n�g��b��B
\�x�83<�JY���� Ip$*��a{�� �D�S
+^���1D	��XB�PTol`����7

�jA��x���\�{�
�J������n��-*]�8J9�*�am��ݰ�����w�����
�w/.���pvw{�+�
��
�g+�����Z�@�"܏H�s|.7�e�}�R�4����c���p����U2X뜵[��ծ�D�
��5ZQ�,I�邫#��
+B��Ⱦw�<f���䢑����̉��T�\1���I5
�Uנ�b�&�+��pD!Ɩ�$*��.
Rn��Lzѱ�dDE�;�
Js�=BC�V6�n�����|�ygZɋo�Ǒ��1��/y�Z"�6�,Ԇ���<,�"�|\y�BF9�����y�����9�k�����q��mr���z¾5��N˾1��ڊ7�Xܩ��� �3L��%�qo;~V�����ٸM\un�����U|
�y5���\;��4�o��䦁	�j����Vĭ#��|Kz��$.���U�eRH
+s��$X��BuLB-�
n�Z�79M�I�i�b$;Eϱ��`G[��%���M��$f-��Ř�
���)� NV��IV1.E;�h���|����
ׁ-�c��H�Ua�x��A��K&VҁQ(8�D)���#$�����Yj����S&n�B7�I�o
�s��>���}ޒ�����9�UkH�`$���5
\�3��~HT�4��s��8
+���v"(To`�L*8Jr���s�hw at oD3�D��10�,	��W��A�L
+EU3���AasVH��ⰨVR�mI����u{��L��
+
��VRKm�л�4]<�T,]5�KE�Q�L�k���%�L6���W�.*j�ϙ�k;
R"o]�
+vDE�.�V�t�4rLf ��
��I�љ��6e����3$��,M$�:�_��T�ٟ�������N��?�@�
+���	��\y1!w��� ��>m��(��/�X@ ��I������&_m�����������{r��y�����������Ս!O�rvw��������û�g��1>��|�S
�lt�b������g�u���_��?`R��/C~��o7�+/�焆��<:�#
St���˯�ywu��ݛ���
�+�}���z��$�%��9j�^/Q���1��7^��)E�윁盇�N&�Y}�K
�<bo���4
�Un�r�������llLM��-4�hܱ�����f����˹�YB֗N&�
�0;��g�d�Z"87���l�d2ׇ�l���Hz+,
�!���l�gd�nY ��ٱO�f�>�8�>38�q�{������)��;CȐ��߻�*zǖ�X���Q
+!���ES�a-go`�2�M`˛��0Gw�b\Z���o�|-�V�xw 㮉6�!)�1
K���r
��6���_��2ss���լ�|=�\z'���ثa�)��5�IA�:�u�g�7n�h�6�:-
H��bY�Z�e��%�;@A%\hX�B���ET�i��
�m�����e��^OV�k7?��;<n7��<HT�X�gk�f^��DhSG&�
��-S��*�(`���^@���}U��z���
{�8*��
�
+F��M_�K�L��3�pXQ'�% ��MC��A�^��?պ(_�;�1���]� ��^��w�$�aMV�:
�4I����%�&e�K@Ҳ�q�݄�F��b���
+��S'%o��3/�(�TaM�n)���&˽�u�CT�1ώ|��[q�bi�8�
(�ں^o}�C,�_ك�C�ĔFC�n-�Y D�c\�}�C.*�*b�3=����Rv!���Z�
;�]kY,�:�^� �M4�6��-�:m�qF�)F�)=U�g�mvĘP��mHk�G&�h
�i�(�Ҋ{���v��m«��?Y�j�F׏�_<9}�1��j^*�v�(�����~H:����]q��U�t��%J��T
8�j�f�^�xf�/�e�k�QD�'�;��XBIwu�\%�0% ,!�,�"F�D�Q��gUժ�}���AH>���3�g�k}�ʫnf�1�/pty�<
�r6��r6���@���X�R��N刖6Fkg	��-�=������;m:՝m��%ͽ�C�
+L��b,�
��}��qJ�
|1Q����dq��˥'�~���w��Ձ ���6�E����NC�l}����9

���I��Xs	�`�9���{� K|��羼��UN-��
+Ê7l:jkL�3���u)m"^� ���rx
+�[����cy)Z�P�+�Z�7"�\�ܖ>��꫕ :Ϛ��w,eK�/?���ۯ^�x��_������
H�~����7o߼z��ۧ�|����_����o����w������v�o?z���e\�K�����mݛ��E���G=�
+/Mx2e�F��PpNMy<=Dt�9�#
G���/NM�޹xӎ�lmkR\�6����
G�
+& �(9�:��+���hyw"����c��It���}�*OduVS4�#^�Q`�w�F=�D5�r-�Ì㼫V��<���
$�#��[>x
��r���VΟ�o�>�=�sN���g?~��=o��x��V-��O��o��? �x���n�k�}k�}��Gz�c;·��#�ͣ{�G:�c��G��c{̇;�c�ˣ��Gz�c;�#�ʣ�ʣ{�������s�뭛�:�N��[vTR���7���(cB�
+�7rqVJ�{4���ql��G���i��
fZ�r�9(�(�}��d{�0��&��]�f�!��;��(�%;�"b�’m`YRvc�{@����:�;Q�cm��/*�
TU��jʇ�C��4”E��J�m�
�F
50���X�ig�]���m��φ7#����k��P�]��pG�h�t��eu��w����`/�Se��g~��1�O�:��'#���B�<��
0�������Z
�����`W��J�H�UD�E�ՒŃS�����YZ���
+)�[)�
�
�Ca�J���m�Sg�=�G=�w�e��\]@f��v�I���qO
��ͦ%m'���ʞ����N<�	���/5���[(֠�����f���o�;��/�D�R�|��A�S�kL6Ͼ:�-�).�Mn��M7��}�	
o���F���xr��hnP�T�e��Z�N�1�"��v��Z^s��)����|KRH��w����!/^�T�6G�v�Fnjqx	9T��>��DhA�5A��_�zpH�H��1sT҆y`hC�6���͕��V%�A� ���K%m
+B>��PY@Ƀ�I�T�Z��N=ޠH�<�9��|�-��m���k�
��P�6r|��ڡ�c�:H>)��13N�PbGK_�
+�8�5�=w�����=�֜l�c��AO�"V�l<nqW�;���f&�qf���iy;�Eg����,�	)GI�5a��aG�~�Ԁ�G�ZVM�9j�";e֕2���°IK����
ر�}��t��6*��{Ҩ���Y�x�U{��7QԬ8lkk+�@����	�*q-r�H��
'��H�
+�#�192�`�>��#��� ��
���g�hNGK�eel«̨�9N�1y1��)'b5���rb�G
).Yg�
xA>nc�1�o�}
C\hΌ8:�/?�;��`d"��ɗ�jB�.2Q�>Б���=5���`b�Y=�>�|v��S/E#�2������)��Y�� �;Б�C��m� �M|�
+:Cz��Z�oa��0'�)�3Em�H:�M+���E�lƷ��m:�����	Ϻ���B�:�"N����u��'
+hOl�ʺ�I9dʹ##Ҋ�<i<��f��PG2-�(;�#�`�'��\%��֡N흀�y�BmO��)�U��ׅ
d�Wg�b�AD���A�
������	�^��1�R
zyR���FK-[ɴ>=��%ȧ����&�M�U-�c��;���QH��թ�l��
��|
�ǐ�w��xZ�

KUI�Z�Z��J��h�D5��^m�Tڹ$c��
[��Q�k]���H��f-l�R[�@/��2�ad1�.�T2��#����}���ǿ�D�9Em  f0s�x�j0�$w�1��
P���i�1q
M�N�z��mx
'�j6
+��2�
+r
 ��>���c���Bm���E������}�k�EiϹ�CW��a2�3��X����Ey�i	vFk/2,
��#�$U�u���nX�5�����{ԚO]
�� kɦ)�C$s�D��s��:Z�
qh�"~���ͭ�͸-D����#�рc��aw
� .�����'�<҆�{"#�
4�Q:E7
+��׃
_!��
 k��3�����1ݎ��(��+<�FZa����!1������"�L׈���x�}�����n����Z�,B$n��K�  �<�.���8�:��:{#sJ��Rt<[5ӱm@����
��i3H�����	��[.P�x-�;(Ҝ��lbge��L/��|���v�N
+�h?igW�
PWu�����FBU�Ν���3a��d	�:���5��%gܜ�ʽyTu�q�Zx����%eE]�͡GN���k�꒪�+��;S���ư�ˇQ+aLd�t {�v9��:�~�Xy`T�LQ���e�ƪy?>�3�Z9��Yz�u\I��Us�j�P+�#
'�����u�fӋ�5[
��
9�A
5�ج{QG9��b��I�*#e�n��]a�ْsXc�΢r�y�[��T�[�8
4�?+�i��I�9U�l�{�3��
/��(JD�q4,���F��2M_fM�����v$�n�PtF�$$jg(ig�ݿ��|*/��*r�k˰X��i+;V��b��rXr�b0�M�9D�d�
+��t!b	`�
�k���h^a���Maf�M��c{�5t�]<�t ��e��A����|a��&���*8�S�B+_.�N�
SO�u��W����sv�..hlh� 
+��>�!w���XLF��f
۟�ԻF-
��W�Baa��
S�gWBGK��CPn����t���e�
mJ�N�e�K>�,gխ�2�sZD���1(��>������K�m<�"��=�s��wu7�dNF�7Mi%u�-���aǃjU^�p8 밒+�?!���E
������I���6��L,YD�h
�u�x
+ℽle���
[��{�$$�kP�w=�-I��^�#�ZC��Q��f�Fȸ�ns�f��A��x�>�
+�_}�Zb�=�cƚ����'�d�
=?�2gמɇ-%:�F*F��c`C���	hl��1�8!`��q�8{60,����y�2��ٗ��`�8zr�e�Q>�� [��g9ŋ��L��"p�ڧ9�c=u,5�o&p�u���$��y
+[ �a�,
n�<���_<�����{��*�U�Z}�`�O�����

&֊���f��h!�s�U�@���Q�:����
+S�Ex���E�;{p
��b`�ѸΝk�Bn%����s���K��
+|c���5We~�٫ˢ݇�3`��/�<�wNH��z�Q�q�?k���N[5�h�c��E�8�lY9��|(;�Z8�t��M/8����<�{-��)��RL2�۲貙��<��ս���[�RJ�}�aq;��?�*~g���z�*^=���ɲ<~78�(���4���o58�6��9��>�/F���9�ܕ�g�j��9]��=hbfK�8гt�r���g��_�Bu.ѧ&=���~8A�̼+^ ���s�k̮�j��cap��s��w߇='�Oc
+���~�S��E����V^�ǒUf��q^��?��W�1�>�Ԗ����=� ��fc�F|�<��2�[�g,N�~�3�y�3w&�nH#f� �"
+2v=��GYv�G{7� ѷ�`�rk{U���>��
+��ΒM4�S�A��
+����G��3wy߉Fwr^Y���n��%��=GcGԈ��>���EZ��U,� u.o�lH��ף���ƺ^�f`ڽ���.
�*f ��GSx�$���s굶
�s�,1�����
S�$���6v�n�_1�E�]_�ة@����!�����S{;�F8�~�{|T�4�Qsc��������o��hTw�9��
+���qzM��C�(��֛�#�.��LS+���]��y.Ŏ	�\#>�cԭ�z��_��;��Կg<Y%��m�Y��ù���Ս��Y���0L
k���s��w�
�@���X�jq�C92�:
Q�s
cq}^��#�Й͌!]������5
rf�-��jWҥ�*��&OX�����aMر.�����-
s�?E���O��H#�r�<����z�l$���#��
�g�C��[5p�ĐY�za��{6�E���k��xk57s�?�
ȯW{b�%�wqgw�抅Y7�\���s��o3�$sҨY�S����w#q��)P��P�˺��"������0|\']�_c�ؕQ2dn�N���<���������z��漄�*���hfE4T"&.%vƣɱ�^��wh��zVkhy�c:|��J�
1^`��;2�
w���K*p&O�]�7�,H����YZe]�$2�����3�z��
+Y�ڢ������!a,�z��}๷�
+��^6��w�:m?��@!�v�d5F���0g�<��
+��a'�&�KoF��._�c۶��d�[
m
+.�l���Z�ؒ����L`|�$sVz�����!G
9���0
+L�����cց�j.��ª�k�Ț�A|zԑS���^f�l�Y��
�ݑ�/?>/ȩ���
+ ��z$
�
�(�Eϼ?'�[��OsKu���7��E����|7��Ӂ��]t#��6�nP[q���A�8�J
�s9�rf1�tV":�?&t4�
d4t�
B'���s��QVv�
++j�Qn:�_�����#e+���Qb�f�պQ�#@S�v��[���m�l�7��6�X
�s����s��ͱ�/*u���YF/�Y����ĎFR�b��l�T�63��F�%�����Z�;�p�}��j���y����S��cr'=��ET����i�;��
O�Nh0+�F���=�f�"�̏��6�qε�&�r ����ؓ���V����n
��$�=��փ�=�=�
��F~��=�����j�" 1�=��Kr��
�M����O
+ 6ź鈴޲���
+
�4� �aBUoI3>�d�пYm$vZVpJ�"b�����f9�_�6��24-��Swz�KE����
+���4��r��58OrG�c�I������C{C.?�
�5����`c�a�;���̌
���-�@6Qr�|!k�����
�h�O7�:�P�p�������y
+�ɀ���"%�y|�W�+.��;]]}�Qݽ4���r3~��`��^D.)��C��dq<MA5qR=K���*�3X��������G��}r�9M�l�Ke}�=�HaBV�c�ޯu�"?B=վ}A?���~M�b�+X�ʲP�/Y
��U
+:/7G��S��I�f
+X��!�
��c�2cD
+���U�gtr-�� �}v�A��	�q�
Sy���F���>�
��-�.�*:���l�[�%)C��#�����Z�q����\e<���v;�;�iځZi��r�W+�{��j�3{{�c�e��?q��\��<1(Y�
��W9�2ʽ�W��s�?�\�f��u��Р�6=�qƺ�ECf�עW/J�9�
+(�mJ�1
g.�˞�ʥ`��Mx���\S�"��g�
�	��iZ-+�&�'��껲�H��(D���m�k�f��'\l���e�	��ٛ���_��9��0a��p�uR̪�o�epF�=�h�U�TC+�����s}��4e� ��l
�H���1�h�=��q�=��Q�پC"�I�/?���\�ME������fg�Xs�Y�~���,D\Z�	;B�QNj:3�c�_Qg���}�
�#�#tli�'![
�O�O�S�lٔLg�L�QcB7���/[������6���
+Y�>�01��-�<}E�]�-p� 	���6�;������4�lh]zΌE �w�A�v���S��5g���6Ζ)�=�q
 :�^{�|On�P�L
D��
Q\U�
+Z\�Aje8�\@��A���΍�9EC�|U�srܨ�>�ئs�yDt9f��{}�=����d`Py�0�Ġ?t���/�_�E	�}H���=�;g�,�xcTMtsc�J�e�rT�=��������l��$��-���g�7��Lf�ue�?h�YZ:�ǝ�9�o�����y��N���������eCn	��K����!1���3��BE��{W��#�.�$v��
��?&����
+;v�@uB��C�%����0Ag�Z���
+�|���s��~�U�
+� �^=;�`�
�i-�X���ۗ��zC�^�rX����zY����;�Җ˛��6�^�
+(�f�b�k
��b����D�RL�5>�
N��˸��Z XK�A�3���Ur�9ᒹ�A�v�s���u��j�C׵� ��V���(ljNl�H���^�94���vYQx��M5��oL�p�YDWt
+	9

���F#�
�v��3HZ�Ggj ���
0=�x����������
�9
����
������
��P���]���N�q�
+���@���i�	�A��ᕗ�dH�k{��3�멃�$/�7N��ȃ�]�\�>�N�[,0l��c���,
+gC1N�
�8�a���LPnrT,�,�0{�i1�?�e߶����\�E4��c�xڦ��9�喎�?+�$��~��i���0Q�q��CƘ�K�����{*��y��D[ʣ�$�F4�����ȝq�������:�;�(�A��D~���~��SV!��,�?
+5-��U�)v�&%�.��ͣ�zh���U�������\
+
^�Z~�1emkKF�m��n�!�p[_�KQ1���9M⼌�q�S2�5;��Mz
 ڥ�*�]M��A]T��F�'��

+�����/"Ͳj������
+�w
+8��O�%p���!6�ڿ
��dT� �n���o���q�K� R\\>��EL$��1�D��Y�D
V����y�)�c�
O
t`�j����{:]� ,��^5�-�	:}���H�:��ہ
.�Z�D��y������Q����ǖ3€3�'r��_H���ڠ��,|�;�sY���~�|�����x�����k�y�FQ�TJw{�_�5)�;�hc�-��.l���F
qF�*
L�`�BZt����2F�;��n$,JlsM]k�;+�Z���
"W
k|���
���׋�M�_Dî�~(�s��^}��atM��M]�k5�hȍ�d�;]��J�*8��?n��ɣ�;Z>�49�����J}u�%Wu"
��d�R15m|I�g� ����
�ٔ�>n]ڣ���0����̒�O�����;6�
_�߼�0V8E�rO��n��Q)��N���,�~;M�"� I
,�a�⾏:��3v=[�1no�/N�qǰ�A��7N��A�r⽜J_�vӼ�ڄ�[��ݿ�:�
+^n�SN�j�����h�~�O�-ȖgILn7�uMA ����H���s�F��
+
+9|\
�����ш�xp=^
C��-Q�<�i��˹P�=9O �$A^
+�
BbǤy��(�X"d��es0�ue�l��5qw*�^�8qs7�pS=��/,����7}��c٪�
+���y$��ߟ���
+yS�A$�������d�3����&�u�rܷ�����=i��	���7p�T�6���;1����X:�mK�Fy%�lWu��%+��|{���+(@
�D���W�/\��%[�Z��s���گ���
;�,��OEh����U�����!��^)?D��FDP�L�	�Q_���:����C��)�N���g
%#j��M��^����
G�H3ݭ�q�'*2y{�����s�"���<��g=A����d����0
X†�iv�n�VY*��A��#�
+�k���3
x`�F��Kbp�KIl�x�Q���N�KB�Nf��8�Xd���?E;��KB��$8^��.��9�峾��)#�ܑ��`�i�}}LB�uL���((��iQ��f|��02Z{-�(_K�
+Fcp��,�(�m�/�ʲ�bI7�x��?�3�ً�3*s����t?�DSk�<�QN���NE�LJGڙ��>���~��|�Ħ�:A����b�8��7K��t�oʱ�_ỷb�H��1�>=�
qEСQHg9�޸�=�>�Q"#`��o�w��b�����ŞK�G�aZ��Z��K�5jNfp�?�U�[�D�����Z��_v?�HТ"X�YU
+IDӒѤ(�~�x�~l�m��
+�{���̙3m�̂/�n��^ڟG#��")�ڮ�h
+*UI+e��B#�U��
n�A5�V0�f�2����d��
'�c��"A��l�@�$4��hpDR��$K	�Y�("�(ٖ0�%�oY��T�+��Ω�H
��k�U�ĸ�ˢɲ�B��>ox�F8E���CF�r5��
+��XH�X����F� �\mU���*ur����^	�L�Ʌ��
+�(��|��h�"9�z+=/j]��<�*��M� �9�JG�
�1�1
�f0T�I�VyCcc��uǰk����V�JY�@(SN{C]�K�?���Ab�䛥�+븺W�t%a�r�
+����!�:z9�\�'�B=�Hgd�P=��s����	F�u5�
��X��L
+
X/�KB�8-Z��
z����^vʸA�� M��9]�6d�S�N h��xU-Tط�N�*iJ�/j�E֮��9�'۾��H ��g!����m�ϭ���[E����鞼v��������������w@{��˳�w_�n>.{o9�|y��������//N�����w������%���w�P"������MX����7{��.Z���Kd��������9�?�F�|�'�����j?�'������x.?m�i��hy�<�_C]Y��n��*u��PpU�8���<�h�5uH�ǻ.0�X{��2XFr��/&[����B�0�Xh֠h�0,��ܫ}2��
:��
h];�
+�O�#�����pb:-�ި�0�7l�YmEy�b� &��Ts7)�zn���; Gi3��*:��(�؎�=��OI�`��].

���_���;#�.�ٹ�Nh�p���Q���+s��7+�f���
+����ZĐ�Զ8b�x�lO�c��
`�zc�
ѫ�	5����I�V�Y
+�Y
�5���Z
��K"i�Ҳ3���d
��S�}��R%��'�/�z����ۇ�������ǫA�^�}�|�����S���������
��K�L]IK��&��*-�ć_}]��j��g�\��7흈\���~B�*AI�8������j�Ѿ��4̷5���[�ю�:BN3h,:X7[xݾ�
�G_]-�^��-{�P����������w������PP1��#-�|
I2D�T�g��Ȓ� �p�̖��5�Y���X]���Э��25K�aգ��s�	��0Z���(����$�]
-�dIϦ&�X
s��l_�2`���nh'榐s"���A�Ey�ܰ0�7��24��0�c���	�O�{���|o�㔻�zo5��!e�T�-�!r`�o@��j�-k�L4�G�."�G[gmu9 17
��

+�\�d/,�=�GE?�h�$E��@�1Y�.��$
����#�
+��v�x�m{��i�u9ҡLbH�i��VM����>�7%̑V(!Y��J�k`]ovٚ
N���M;��&���S4[�x�5^�:t�NB�U�"� ;��
a2�]�Wݲ+�
+Mz� kB=lz����"�x&*�"��������V�
'@��^F����9�(uV�f��2�U�B(-%G�z�%�>�nտ��nl�u5��2�<�W�>U���Mf1ǎ̪e{{Pa����W4�o���.��T��VT��� O(a({]�LV��:Kl:8��� z!]Yg��X
$����R��
:��
+���l_k+ �^�����
+Id+L��1	.#��P�O�cǓ
.d�M��R�)�����0��$�\�
+��Ǎ`�d
5�N`n'�
��rb�Xm�6��+���ێX�@�;,1Bi%.�`�m��,��ZN����d�l��Q��
��jl��'�a�|3�th~�D
e?:�$pV��1e��z{�Q��Wv8�
+�K��-��o�K��$(���D�X]&X���~ʜ?
+$"6vX�D3��敖ʶ
�pW�XJ3�'['
+����	��
+�t�����uho&��`�����K���L^�����k��7ڂFT�6�0����� 'JgG[$��Io�i��̰0i�P�����wX]nvX�].���+
rVf��{7�s l
V��
Y<���\iE�`� �m���4���	$��ukP'ð��j)aF�n���7�R��E���k�T*��������]��X�aB�����
+
�9�e�H�b
�碣��0L
Nl-�#�_���oj�ٲ]�
��sno���
+�n������ǍZN��f��r
^_�/|X�����b��E�Q�,
o
_�z�]��u>b`{���9�,��x�p����|?��xu#���+
����>�q��ӯ�{�Q��-��>k���>��K|����-���~V��}S5Z
+�Hhw��S�&Ђ몬�@/_���`
+�D�굎"}SHQ��)�E��3ɰ�2:�6��:�}0^���#9���9-s�
+�� �)dq��Eq.�.hmˈ�gp�� ��y�
+�J�t� i�L��`a��/��I�(��ChD�(�B?Ĝ���%�W>Щ
+9�5���<
+b�r�
v�A
�:
z���쫐,��f��Gm���XT�uzk!h���B!Er%� �-���jSt�i��
��C��5��p��9��q�UN- |~j8�D=�B�*
�:PH�xr�,��
t��3ƚ/��{q����!͸��� G��a|d�	�j<Q��(�JS|�i�C��p��b�X��|�lk~��J��ժp�� ��	R�x=	���Ò*W�㯱�rL���]���OeӖC@��y�Q�qBN=\TƟ Q7�[
T&$�[�����<�+�z��&`�����^�2�R����Up
�1�l�*~��}��=�/�C��liy�={�ه����>�@9x}qD��� �Q1�JGb�]m���pNȏ� ��5�kf!����l*P����t�4P!Q+z�F4�7��A�~�Y}*���
t1�*V�?���
+���(I�aN~�b��T��!���@�d:�XqCL�ʜl�@�t,Є-
]�%�hnrj�G�"�Ҕ���s]1!v�&��c
+
��R�#��yṎs���w���d'0�Es��D�,��Y�:�g��@;~���p`�`��p�_:�U�9" 
� Պw�hVa�M���]�jr����QXw��^�ȹ�f�RE�F^�fBکM4^ݤ[��w���
+����Y����u���o0�$�G`�c]��¢p|�l�� �������,�?!R=�����X��DPus2��~svv�1J���D�t!`$+
��i��v#}��M
���u�6Y�Y9|ޠ���,#�	�*9�-�y�����d�� >�
+ �\T����װ��nuCH��Qw��gm\��x�yr�Y~�I�Mi[�;�G�T6
��n
+7��
���W:GT���|~\?=�ʮ/^�v�����t��������bT͈ɍu�Ҍ�
<�em��
+�p��-vq���+��|ê��jBx�$e�m�Tc@���/�}WN7��8l�x��}����az���ԩ�V�a�z�i��
Nj�뼱3a\���(K6���3e��=�X�Аiqa�v50p*(8\O�h�T�������|x�i�x����� e�˫���o^=�y�����ӟ =y����7�o����䛟QW��޾���?�������_?y�ۏn����ͣ�������߾v������3��ǟ�>�'�#��
}�#oK�� vw�c>��At��
+�8�����v��
+4Qco�ib݃�L�'���#�5�p��b9�,�q91@}��9��[v�3�ߞ���yΫט<�kbn�8f���5CiH�S�(z��?��?��?��?���ߺx�j��
+��e��Y� L$����F/������ۅAM��5�2a`E��XǓ��I���^?����ž�m!L�;��ܿP��2j�:���o%,�B����k�W,S��;��8���Dc!��,Ht���cp?I��K
+'k�����:0AYפ�d�γ-�Z4�]�����eцt
����qH^C殄A%q���;%cm���;��
+Qך�@Rz��0��M��Z%vr>����KW�~��R��fՀփo�U�y��Q�;��3YKB��O
J�@�Z2���Bd��B=��r�nI �a)����Qft��*��'8I�����+Q������5�N�6���t��h�$ҦKڏ{
5��T�Jh��� I��C
K`�
+�+���5z4ft���.Ș��i�m��Qج�z`���j�:K��1*����V°�X��֋f,a
�h`Qm=Ȑ��W��@���Tx
+#8�|�V)
+h�Qa��%ec���,* W��Y5������e��u��=i%����7��Pu��$�
7�R"�e.���aI� �r	E�6aj��$ij+���2��'(9C����l�|nm��5�u����eՆu��=g�*�gi4����e�������䊁�"f�\B��
+��E��g�b�9�ɝ&)
M�u�>1IhE�q;J���eԂ�~/W�U�Y�{�"ɩ�����l�	�	��A�`%���p#�
���뺳0�k^r6�&�`�}T�x0AI��з���Rva�jAぁ��˪��<{ք�F�d&k��9%����{2��;LY�՜��A�5k
��7��D
9m

P����ɘ�gi���fՂ�/o�U�y(k�u��Y
s��iֻP1A
+�a���#R��}�����x���v���nV-(�
+�($UM�)�2���s��7�Κ�+�e�<�oW��x�z�p{o��w�Dڃ����_��O������\<����?oOtʼn���)�D$�}�E„LjNN�0
�P�_��W�/���__�O
�G��ү��i��}=���_������~�Z������iOC�W4k5h�_4]N�%��9�s6��p#�~���z�	��laȜ���a��
+K���-�Z4�(���C�VY� ѬI�
]=]����S��Ǎ����9����v�*n�&���X%
+�N���𶃈g]�^qz�|
�2����i�b:����k�(���j��x51�
�0��̌�u-Z�L�PXÎz�.J�I�ɣ�~3�B
M5#�^m�hbQw+��L���*7��%��ծ�h(�XX����:��[�g�@R
jϒc�"� @��<��X�v�4M-�
6�2�=|+�Ҍ*#qp(��d�#
+�@<��خ�p8Y0�W�����B��{}��E�
K�
��*a��Z�A϶�5ZOۛ��r���`2�a�Eه p�R��or��E6 �V�*l���Ut���W��
�X�!�:?�ꈕ���t��֡����A�t��
b�H-����L���i�ʯ�8�HL9�]<M��Uw�w����Q.���m*��UjO�zY���CX_�j��>�Œ�h頬9`�K7
+�ѥ!y�U�M›2pb�y_���K<�S(꨽K�4|U��Q
�5g%�(*�,U��#ң���U�:��Fd�F���5
+v�e��K������c&g_^���Y��x.P��Е:J��y`>Ŭ*1���4=��r��QI=��
�VQ��E�������I�:�t��B��NP�4VG�
+��V�I�ƈh
\�x�S+��TŎp_
�%vi�%��<A�	�"�Z
���і�n2T�K,K�l
��d�Ȁ�YE1cS
+�mSUI
Ϋp�}��q4�λ�����yMC0
~
+��JD�����%��2��T$����mUӣ�>�~�}#$^�>Vw_��

��I�h&ы���U����g��df��}��Z��8�	;`/H�
�_c���Vt(�Rķun���!�lg������
=%���&}�s��8{��?M�5�

��K��s7L�>����a
+.**
+q5@	�P�#T
sS�ZU��TF
+5�b$(
x���/7�(�p\��%[�ިj��f����16�����-X�[�!�	3�2��>��3�
ζ�šx����!Hy����j`�9�g.P�i$J?	�"ޑX6t��>�>?�Eĵ%�=��Y 7[+Lt�{�U��b޳}�
eg�
�WSf�#X���o����>L�s�[�C�<uC�����)P����dD���
Mf�/�OwD�}��V�6`�W_��X��S�Ϫ9�h���,����j֒G�+E�I�ň��וRVd^���w�~ܿ�#-Oi��F�v�3��7�E

+�i����u�Z��h�L��ymA�0D{���m.��
���l"�1�d|P�
��8��"��`�BUk�
C�G��J����s\�+5`�
����&�k
l�#M�=�(K��5��3�]ǭ�;-\Z�"]8�U�욣Z�
+����1;�W�����=t�d�
�5�-��	�U	�i��5�h����XQ�a�zz�����Dž7#
_���PFﷵ):B�+��6��F���խ��B�J��02��� ��;q~�#��T�>����~���<���Mq�9������D��Uv>E��u_ez��&����g0�q�t��Ι�U��d�t'�g\�ub fJ�^��
T=���q�����5rk��H1�M1c�,�+���[ː���FR 0}Zd�um��߀$0eY@+�
�}Z*tq��N�/��m�{�N[QU��}��4����>�ߧ5g��6]kAs>��I�ۉ��
��S:y{�%�S�#����W���
�{J�9�y��}�n����Wg��N�S�FS�c{��B>��?�騂	���\݇*�����S��9v/����8t����.���B�����ep� 0�Vg}|��R�
]���sw������
+Gǽ��FkpL��	�/��]Y��^�}LYy��^�CO�6�eJZξ��V9�	�p4:��֣�]�n
AO
��W�0�m�g�D���f���*���=�~}��5�/׼���0�j��[4E�j�^Ih���oo�^è�l,�浅��Z�Yc�b`/�uїO�?�3>h�ۅ]���y����y��_}��Z����������{��7����|�շ�������9������'�S����=�X�[�� ��Z����/������y<����+��p�?9W�*]���:t�}��sӽU)�M�ێ�^�p��i{.�x�p�N	�
�.)�Jm�2
+�8�S�i�G@Q+!A�B���g�3�lu�C!����* ���9d16�G4w6������p���T��Yr)y'gsv�
B�{Tw!�����S�r[G���!{m*
�m�^-��"�1$N�R;��M�
+5�Us��<z�[I����5�����!�9�v�6O����3<4i�$'��k�C���U`�a͘���9����C�K]�m�A���B#�墣�Ww�'`4m0��k�>B��g��,xظ
�����sp����"���4�l� ��ӛ�>W�j!������ �^Y�9�� �{���Bx���y��� W��ۼOp<R|��r��e#j�y�x��x�Ԃ,V�A��,yk
�(���Y)�H*���� e�
7����V�IP�36�c�e��{�<�G�GU�-����uϯ �7� �,R���+:G��|��Ū�Ļj�� ��<ơz����
������1��BA׼P
Q+��RjZ�͜���R�9M��T5��8�!�>�����ծ�A8�7f����0�2 ���ke9bLe�W����U��2B���5��0�J����Y8�
+�e ��

ⷋ��aȴ�P�`-~���z�J�^.�Ҙ� 7k�H��*U��4�Y�F4��=�<���� ��hI���
+w5���`��DP1���j�^N�erVQ˻��4���җc�P�.p�"wWAt��B^���t���=��m�|�Ve�Hbt5�3���1�� ���ב�>����+K�Ĭ�3W� ����l��-�\+���l1�ɟ�� �S1/�{
��[?ȸh��xQ�� @�mk�S��Q�v(���{XQw�ѡ����W6�\�@
+Kݱ�r��
+<���&��`�ro���.z�xֳ�RT����~���뚂K��oϪ��5�
Т�Y�5��{Y�p��=\�	�'��L}����x�ʶ$
+I�ˣiB�ieʹ`=酬�ڇ�
�r�Ա��Ƈ���Gj��IՒ��׵�/�
���E�kb�=u�߹���#|�{������ma��?�f	+�#����u�	x�
����Q$�k�������
+�RM]-nH�J 37�47���A����>]
�^���A�W�� A���H�^��m�T��;���y�a@��'[D����Kq�M�'�%q����U��<��l�&$/��an�G��i�G��I�v�}-Pi�
L�t��*�a��������vP
@��&�� '�>`�
qj��{���
�o'��X ��(�E����M<�^�[
4�k�Ov �K��ʼn�V�&�i����ے �0��a6&���K\6�O����c�;'0	J/���<�^+��;��,�v���b��\�Ƴ�ԅ(��A��!�
h;����hg1�p�/׋<�]��,�Pkq�mı��^v�vK~���&��`�W��**��(�p	a5jb��;F�깖��K$��k��ٳ�j���g�+ 
WG	i���)k�)N�)��%J��@ݵ�qr��#L8�4��45�E0uS���g5�4�k��Ҭ��weE����f�)��p@��
�,b�bp��� [...]
+{��ۢעf[�A��P�\k�'�Z�d|�:�.�!�
��Dkږ��C
�PѦ2X$|Ȥ���X3B���*{�K�kl 5by��@᫋'���ư��p �UI;X�Uj�{����f�8�X9�?
:�W�c8��jHV�-4a/=���[ak鸅��a_�0M7�c i+6�V�4�S1����M�
ϯmf��e/-U4�r����o�� ��<k�.�P����u苘�j����QB\Z��
���4UR�* Gs>�m��QB�T�$����apQǤ��
�����JӤf�>c�R<�y��:��4r=j0���ɨ�Rcyw�t��Y̅���{�
+�:��:[?w���AzF�
c)��K�����9�㥪��o�w9�J��Vx��������,�MwO��ѝΙ� S�9�_̍�`p��G�K/
j�AJy7��y�yQȳl�Җ�����x#oz

=�
;`��Uz�d*]�L��-H3�nG<ļ��h�՛�]�gXj`�H~
+��tf�:Gھ�}����J,7Zk�H�Z�kL�z�2]�S�..�d'�
e���`�������
�
Mb-�J�E�Cg�$8�ɚG
-�e
��9Y��.�J
h�[����a�=�n_{���-7��ٮ�� ��&�����[���pf)ha�‘bhsH�K*�H�NHH�S/E]��w�1��݇�^����ٯ/��zs�B��pz��ׯ����t����|��/O_|�œ�?~���;\���]����O��=|��dPأϊ��$��<�ؠ�Y!�8�Q
� ��
��u6��T�@�'^B���3P��6W?3�~U�H�V������
���
�c�&��|�C�z�bEH�
}�_��7b��N� �S�s����ˆ���ip��A�,8P��3���k����i2c�ɹLk������{�K
���R���juE䟕K�J�A�Ԫ64޹&{��=\y�� o�n4���X�y+��w�CC�N`�7��
�
������о�LT�Vk����c���v���C�F� [...]
+��S�ah:�1�V��Ȑ�~�֢��A���VŘ��eQ�8c
�#�)k��+8Ug�4���9 {�F�(N��R���
+�O��$gN!�֎F	P׋5
��W�O~:���Fr������l9;n��V�AǺ� \y��hH�rI�0�s��I�!.���B}��Z_�0IE��#�S8@�_�G�6�;VʶML:E�Oڛ�I� ��b���Օ��j����O�r����� ���:�pz�߻tz�������w����woQX�����
+~�?����v���o��;~��=I��j���m�v+���h7��|v#���f7���\v3��L�'"Ku��b�Om���yn���P�uCG��㻗[p_�	t!c���g��̾�xN
'��K9���ڹ���s��
+�L�
!!��(��:g�U�<��ƻ�2��Hy
	Z����U=���*���t̘ MXS;����o�	h��F�
^J(rssß-�rt*�聹�v�f��ONjhT��
��cM�K����0���m�UVפ�"8���v��&�B��4�R��8C�� -$��
+endstream
+endobj
+24 1 obj
+21621 
+endobj
+25 1 obj
+<< /Filter [ /FlateDecode ] /Length 26 1 R >> 
+stream
+H�l�[��7�W�=xs �"E>���1��_�x�� c��vYү
Y��{�>�w����F���_�Iy_>%�u�w��=�����"a��r{
,9�.�R-p?��
��e9-�1*q���ǯR�
J��������ٽC�
+zkۥ����F�d��
�?��4[�R�Ϣ}g��=_>�u�s��������������Q��X�Cv��];
+Q���ln�ͬO/�|�H_���OŶԅ�֔n��5\�L�)x\�h����<"��xn�]�B9�~�l���h�+�ݝ�|
���7>�����
�?�#CC��h:Q�g>�'̌0Gz�"��7���
�^́��`~�?�q�
��}���
Qz����X/{Mv?�"
LVD��(w�?B<�-j#z��#��j�OYon Dl�E�˞ȻD'����E�	���}qƖ�|XDZ\�~��H�����|$�-^�������b"B�r$������s]��_�j�:y�}�wˈ�Sk�U }`)��
��>�	1�;�ݝ걮T��� ɱ���Ŋ�H��/�=�Z�Wfh�ޠB8�8
+D�
��}��d��>=tߜ��t{�DX�m#����y��^�5��@����F�g�l�ױZȧ
 V�X��bK�X
+v3
�Yx*��bo�A���g��a@��[%
�X��R����T-��!E9Z�2M�/�Y�|���������
���ש,��6UW�X1��(���XC��Xk����<�P2l`�
+��L�\�k9�-�=?C4}���ΰF]�Y6l��E�'�. C ����8�� Z>�I�DVݝŲ�7��kY����u�A���6�!:QӖy;��S$�n�6M��������|*Z_���(��Ql��пD_�,�O�8�저���� ��z�;�����
\/E�\-&
�.�Xtw��1d�
ͧ(
"����%�2
���#
��Op\ǟݩ��O(��7g{����1�V�K&A���М�Y���3;���z#�K㻞�ˮ,|��_O	�[�����Yv�HH'
+�`�
�Ζb���ߪ�����.T �˿��4q0�������e��)�J�
zdg��p�q��y~�K{[�m����3� �Y�<��<1D��تE
�5��q6��-��"NS�ʺ�9g�"X1G��㜗�@_��
�|�(��G\�ex>�|��hǽ!BuƮ���w��h��;��^�`2�����
����Y
+D���Z$��J����[���-
+B�_d�4p|� �dc�F�^�M륲9�ŕ�[#��
4
+gѨj2�QsG0
0wynm��P	w
����
g�iހ�U�F2����&.�%��wǁ
���u5Y ~�I[����������?����l�f؄T\e��J
��r�������
J�L���f0?}���� ��=U�iؠ�?#�ww�,?p�?%��7�����
 Q�~K|�:,|
d�.c�n
zd�(8+_��r�{���y��������*��(o�x����?!�\]�ŶN�e��m�֭l��
��
��vx���� �#
��5�ۅL3�KT��^����
ܗ��m�~c�!��'��r��׫o������h�F��,i��^�%w��k���d��v�������J�@�7޷������ D�꼠������rV���iݐBz�i�:��s��`��6��":R�N��Є��� v������eX��W���le���&.^g���+5*� 칷�V�?i��+��tQ����6�y�Fq��`<4�,�
}n�ꅲ���C:'K^�DO�kެBc�� [...]
+C�;e0��]���fW�1��ڞ��O!�Q�
r�j��(
�EA�w3�U�AC�Yi��A�5�f����B��w"��+�*�R��ƽ������3
�l~�h�.�W��6
��h�
!kP�^��
�E�uu
P�1���+Ow�(
+/7�I#ߧ
+��͐o�"���K��}�D$�>q��{�f�:����q��<�~ְ|���wv����� ��mQ	���i�3����jqr������;��x�*�l��գ��T���+�UGJ�bC��a	�G
+Xge��l<C�v9ʞ�Ө1��
i5j�Sr&ĈY at C�;b�E!��b��'�7_B����w$k�X ���	5�7lb��I�F�HX�V�ɶ�ߨA�֨�p�F
+6l��(���p8�,\�Y�QcU<�~`�[[xj]�훉�К�|�_9��E��gUg®;X/�h�=M��

������
�{�ퟰqɣR b��
�����Hn`�*lXх�
+��z�P�}�
5+��}���
+����N��
��E+G!��W[/j~�{<V�-� �o��d�C�f
+�}�S��k�칫���5ш
�n�&w�mΤL
+�@��}��NgW�J�Y�֐�
+�E�FŝF ��ᗷ���jb��42-�m�w����
)�#���	��'��%H��2�@�"
��!@@d��>U���1س�LM}��:�P
1���-l������Խ�E�4l�ls�u'�@��ذ9��nf�ϒ�O�|���.��1Z��@��9`v�:�ϛF��
l��ݰ��څI��JJ�q��,�Xz�~Hk��z$P!Y+(��}lm�|�%���\�
hk
���$�r��[��͂L�|�]+V�k
{��ϕ��dljIߌ�
��]�;�(E�ƾ�ep�m)��\`մ�rp�F �GʱnfP��eRa�3�aS�i��<��!^����Y�as�
+b`,.�㺶b�`Mˀ�
�9

�	���I�����B!D�pp%_���UX
�l��	���4$�⽖�{�Fq�u�YpQ�
+)96JV�_��������xZ�1J��M�
+\m�ڢ��y�8��>G2�m��B�L)l4�U�L��B��ʤ4+�9ٞ^��;�8�
�F�bs+�^�j^�) u���DuZA��г�\l�rG���KŻW��v-��Y򞠗���]7�~' i{��P_�E��&Am(�y���|��'�? ���V��
�w����y١���$
+��6�lZt�L$a�����UԲ�i��ԃ��C��u��fkp��|Zq���6�Jd%�\U��U,9��jC^G�ZetGv�@z���d��qX0�z�"��ڽ��҅V��F�G���M0k/��Pkv(|�����.SF�
*m��ƾ�R�x���
T�*J$xQ�F*[{�}[��� �Ҕ]A���P�rHK�� Co��Z*D��#���N
;ġzs��F�
+ Cm���ˆ
@�vmg��
Dۂ&� ��;��n����O__������Ǘo�<}���g��^�;�����o~>�}������o�<�����<�w�������ӻ[�
ާOI���O>�
�=?���{�'�Ow���}v{���6Ç{6-����
ԴT\\�+�4��xpm/�7��jI�u�������?<���N|�s�oG�8���x[�}~�t���:m� Ҍ�R�+���I��qD���%��k���՚�3*���O48��fE(�Nk5N*D���*-�a��tF7����
+*,�o
+𵡨Xɩ�jT}�6�B�T��/�Yz�0mlE��
�>Y}�%kO\�>�pC5����z"(l$�f��=ow�%

m���AfЏ�Aȹ��붸~�~t0�6T�+���U[s,�"��Ù
C�
+�k��){�z��H�իi�	�N�Z�K�pH�����5(d�ܾ�P�m�an�Ť�X�0��9Q���Y/L�~Y�Q�/^*h��	�J��'cm}F�T��̮[L�zJiF�[RY�R��j��E�TY�~f
���S%��_� �}�	�<?�^��PT΅��M
���K�
�
�~��t73
++Rg�����Lش=9r��=س�f�`M9��]�Tj~e�ܩ�4k��E���0-Z)֗�ŵ�0����VJT���4Ic��ܚ��р��Lр�ە`���ٙ�y)4n`�2�S����)l�������;pB��� 4����$����u�t���;P��CLdNnjr}�s���m���fڎƱ���Ig�(�d)�
+
��-s���L?��b��Io�j���
+�GE*
�`>����@�p}\�I$􅗀��ͬ"l�љT$�_q��}���"�2X�.
�+n���
&�՘�B�'B�
~BT�w�uD���D at Uc�<��VO5n�����rR� ���
����B�,�T�U���MTs*�:�%_Ѻ�E\��Rzeؕ`Ap2 6=}���ޜK�@�}���G�
��X�V��P!
��
�[c�Rv�1�R�4=�k�&��em�����*�1\�h�J5:j��,S����`v�gzz�'�4��z��V�Te3qQ at y�Aa�Ŭ��p)I�t
�7�{�&@2��m
(�c��)�*�բԝUU���|�s��:v�j% �@��
P[H��X�
+���#y�̂?�Ho�9�@�����7�N��k���0��:�e�$K�J����m-	W�h�]w 0�D��a�R~Wޜ�AZ�W
�T�:X�
���qv#��C7��+��M;cf7+��H�Bm1JiC��P�����6���&k�pN���u�ȓ*FiA�⮠=�N7T��sy[)�M'Hl��r�3��!�U��������"F��/�ws���ej����B�"��w�biD^K'����ksr� �2�� <��q~^

+�j!�B��:RYp9a9�X���SEiY����BK�΢+-	#0|�5����(����Bh�
+W��5�-��ra�����O��Wq!��X
�ެ,�AEo�w�ݭ�����B����O�JsԪ�ބ���� ����$7X��\
+W�R8�4ł`
+{RY�&ڳrg�[pCfx�
��
+T�����r%��R��I
���;���U���	]�:鉋up)�ǎm��@K�so�ʻ����)��
+�j��]������
Z�A�kO��q��t/��0�Ve�xZK*
&�5����DU��s4G"�
+%��C���BX���ZȦu 9O#}]I ެ��Yˍ�#G�8��A ��xR��td�Ӄ�"l5�Q��}cb͵{�//@����:߽w~���\}��O}��ѧ�={�ڿ߿�����}�����͋�/ߟ�nnn?|�wJ�+���r�?����
�}�
Ӡ����N�{�x�O�	_���E�s=������s��=삛4���!��cr��
�
�Wx�/ �
1�v�"�w����u�1tP��^�"��Yw�����_ٯڠ��3l���*��٣3�cfs����#DV�%kE�a�!&$Lu�k�LŖm
���� ݢ��v��v����������q����������s��@H�$[���O�����������|t*�mA��U�FW'3���c
+�� �J|&��$U�\�cP�8�8o=�w�p�x�&����������7�@� �
���+OŐA
H��d�w16Q}�>�@x-��8�dF�1�!]y��~��'�:��\˼�q]K���u-p^.���R���y�on��܎���9���XO\�XO\���ۑɺ�Z1�7�����8o�]�<s�w������G.t�U���u��W��J8�6��p^����w����J|�u��ęm�٪�L�
�.6w.�f��e�Zm�V
|s�7�������w��sY�+�3����<+�g9<�:�]o٪������s��z�Mίz���ƚ�h��D�#�a�
KA��K���,ɷ�������ҥ�ڽ��t�����o>���?=]Y�Ƴ�h��gϿ����'N��O��^�0�ſ���?���G���`K�f����˗/��װ=5�ea���^�\��ǟ��ſ�h�6������%h��^Ȇ?�t:�N��M�^�y��/��%���LLv�����)9z}�_Q�������i�2� [...]
+W۝�
;���(�s�t[m�ĭ��6���QX��Û�O߼.M�
�U��w��h��6�=>�{�V���^������Z�f6�()J,;[����٫
����>19w�
+A3R�z�
+v��
?��Q�8
%GǞ�Q�o�
����
e+(����z��q�
�=y���K5%�[���w)Xly;����M�����_L��DŽ��;{>�5kܞW�݌꛻�����+s#�c(񑧓�e���Q�
+]�5�-���n=
9X<?�6F���eO�����[���ɢmҬ���c��
��ؽyA27��;�TQ727rxǖ�Ͷ����g�7�왾ߧ�;K�B��]��^L��(u�||������53q�l���(;>>s��`Ky��~}�����}'G\��
��Ks���2c3E�r�4ѱ�&�l����ۣ��
+���
�z�@�z��ƾ�;U{�hG��{�����byw0U
�
Ӳ��m�s��3\�Wq��`���((uu\�
m�k��%�B����+ʊ
6�U���fGۓ.�|��+���+
?72�p��*����~�ǹG
�቙GSí�����?�����əG3�gk�,�m�b��90r�����s��>��!�G��//+Ns��Z��%� �fJ�-���t
v�����
a����N��l
D�a���?5�E��7�[���xMB���q˩��4��X]�4�fU�YE��&�"����تI�*�"5˺�R���"σUY��uӪ��L��k�*����ѡ~` [...]
+
��J��Q[�@3��$�.�
��g��c)T�dAcUI�F�ES���.F�*	6
+�,sZ�QSYI����Q��)$Qv���p�DŽ9�b��
+��Ax	X�B�U)���ha`5�X4
+ 
+�t�(�Qթ
�i��j����Շ���+�
���&U�#��P=ϡ�P_h0؍z�~/�
u{�Л�z
�Ķ�YQ`H
+��b�!��%���	FG�U��d�;g� \��~��و=Y��I�ړ���+C���!��փ�h�Q&I�o���6 �=��2h¨�����
��k�hZ�#}�IC��$
+;���e�I[��ˬ1���֤�&iNl���N��Sy"4���H�4���{h�PߙP ��v6��Ma_0�
��\�\������~�D�O����9s��a*u��xQMxp��k�
oy���pU�g�>�5_O����u���B�@5Q5cͪS@����$x��F��(����+��J������%��2e
��t8�q�ր�A
�g�a��f��g@�D��G\- �3����M:}U�:@5 
x�q�8�>�G-��)����p�?
+�F���Ho����Rcj�VF�+d���
+v{S"h���@2��w������Z� l�
+�

+���g^He�'��r�(�d�TW��r�=r���-�p��M�u��"��	

+
�P?����_qW|q|���U���	���dyMZ��`�/ ��r�u���%r��	"Օ�
_J��*�U$���'�մdU2$2�$���W.�����rlZ
+�	��9����!^��
+g
xq9�6��i��Ն�N^K�6�M�p�V�}�p��

(��`�����
�'28tr,�
+��î1�"\*���'�
+��pn�� .8?I�*�+T;i	{R�8$�
G6��(��)p#��?"h4
+����8�
NbУ�ų�x�\��¨l�ߌi<���(�DA�0a*u\�h�q�&E�iءSI���X�u��U�m5S7UU�����TZ�j�y�G�.��D��L��\�:)UVR�7�"� 1-�:M?�+%�4�'�D��@�T�p+F%5���ޛ���?A�ôR+"5��+])��n��.��mW�h��b<�
'M�����?��MLb I�Ǚ3�����(�nh(���[�8�Ǎ��^H�gP��@�;���?���r�!�[1BI���Uٺ-�z���6a]�A�wkD@�C#�0�kC�Yy�qJ�f�X���V�sEL��]@�3��B��HAf%�=&3ı�%&h��zS�;A�
+����Z����C~�p��lbEx�\V3U�<���9����G��*��b|,�:��iO0�v���rm�5)���(1�lg3���;q%���uC)Zhf�����)�-2����
� *ٽM��ƥC�
���O�E�g�e������G藣Ʃ��[)7zt��W���9�;1�-
+��8@�P嗼M@{�٦�J<��
�;��~�QoxNS6 uMH&,�����(�Z��8S��=��~|�
\C_�I�闁��b�c��GG�y
 K�P����G�o�se�\�
	���#��c��8ֵ�c>�3��Tʙ�����1=����+�}冺�y�-�����e:S28'�sJ�9���T�ВI�Q��-V�T��T��S*L�Q��ob��� ��bJ��	�H�K ���_Yl�]�m
7���(����]���ŦE
�4�_rUYR���+
t�)u��#�.��v���;�����욐$�̥
4�b��
��/CVK�5��
+�$쀕�k�ُ�П�`����I�-q c����F�c�F��
+I�D&vg�@@�A��rK�^�oGԣ�C\/��՜��j����E�z��
�r%_=��p�p�/���e��%q�I��ǟV�
YA���}2��Ҥ�R���'���1�� �'�{��Ghhٳ��U\�t5
{��>f���I��
��z��s�ijs�܌sۚ�/&�w�-^���Gs
h���`e��6Ug5I��Ko�OUk��=�i
+Q1�_��q8����������^���[���6���^��n`�V�%��!�^rSk�V�H��{��9ܟb�ao�'Ե��0�w�O�v�0�ݼ�#\�Ny;��
+���
�u�Ǡ
5���A
כR[�N'o�}ey����!
�*�V�ſ��A'�To��ú,w^c]l�_��>������?���K��۟���|���"����.󋩪�J:+��y�ݫ
��sdz�>���p�����xB�S�_������0����,����oh���=8���2�$[�����&
t�3�r��|��x�ҵ��x��U���2ڷ����*	s[[�޸���hJ[7��dʋiŬX�c�r��-*j
�����f$0��./&�x
�ʑ�<j��D
�����HP�YmK�H$�X �CõF#�
}�wUc�:G[�
Y�i���9�
+:?
A�}G�,�J�J�W��ϱ�f�M�+�8���x�
c�XN���S����7��V�N��U��#�#��fYs+�l�SZ*��^�8��yV�<�����K�4U�jI�������
+0��tW�֣�C\/ol$W�GJ���1��ش|o�p��ömM\���=����]C�e
.��q=���2ܩ+��*�!��OM�����0��s-g�jg����}�5>^���w(�㱀���̈́gZ#��$��&�8S�C�^H����!#�,����NRU�8{�7���A/�͊�
3(�����b��J.'O������V��s]S8��m�3v�
w��+�UGH���ܱ��%�$`�e�Y�^��+
+��ԉ(������L�n�L�H	���'z����hJR�s����
+=]�km9>��X`���u��*Ʌ�`]�B��Ă\�#c2�2&s٪� ˘�e�%����xn"�7G� ����<
;�k�nn�W5ʥ<*�	.@/
`��փ(�F׊6�{
�
0��?� ��_|��
N;��?j���
�߿�yqN�8T:_!zu��	�O�	
���
��!�
p�A��1�T/S�+�9�/4�}�
���#��6Bx���OG
�}&�j+!��2�4#�D�ɔ�N;�M
+��z$�Q�!� ����S�'Ӕ
p5~
�d�#�X�V���nb�ͯaۢ(Aq_����ԝg
+;^A�ؘ�Vvbs��y�v�1��9^����|�鳬�sB*z���=���Fba9}j9Qe��'�t
΍�P�2���� )��x���@��h��?`X
_Ӥ��>q
+�b�X�����>�9�8��m��/y�?7"t}ߙ!
h�����3��Pȩ�P��X�TI�tԺ$IKzr3��P���v]�ڢ��O��S�C����*NTqkM�u��V�kY.�dYڼ���B^=m{���o�D=
��U����뚲��
 �@~�}����j<�C�k�LRSk9�L��Kf\�t챰1�
��9(a�~w�b��˚<�I�
���<ǃ�ZY��:�M�F!<��3-�%���R"�ا�T^B�eN���Oi�b�ki�q�k����+�/
.��ҷ��B/����&����q��;'|�Q�wǁ�3Q[��

�q
+vߒH�i���4dؘm
+C��Y�E��+7�},�ڦq��J
S�=z�1}�����z��
�\�<s�
+�ؤw�L��ez�b�LJ݇��%.
�G�c�F�/f|;
&vg-Z��� D
l�mۀ7ϰݤ͆�%�q
������6�����5_�1v-C
��A
��ҁ�����X˜�N/�s�<u�x��%����:}�-grr�����ˆ�H��ߵ�X������s��;�H�F—���s_��m"A�@��JUN��&�$i�?j�I{7Q
�]t:EkXT`9XҺ��fC���5�Z������0;�	�=�Z��B�Ց�'����'u�M�F�M�F��&k�d�ch�
+dvf��_����Aǣ}�����=9l��C��P�:���Q�#��,�e�@��{p`
+���B
+��plh� F���
+u^�16h)�e���ܕ�e+e`�h�JG2T����r$<��
+��"�
82d@5ę%�*=Z�Ѵ��a���芩���
ԲY`�\5��FN
�̗�V������"�T�����U)ѧ*��q5�V򜝍�Xʷ+�,�2J`ˡ9�j@
�$
��Z̑o��1���WaIP�dž^}%%eVʮd��VW��;���U�O����QKXͦ�H3N0�em�@5՚L��d�?���4���Eg�t@$��Pǣ~����)�"��=�B��U7��(r��$$/�wk��Ena��l0�ig�54��͘��b4$�0G%����ǿH��:tx��i�9�y)���=����b�����+���as	�ɾ�ؠw�Q���)
+x����^����I1,������a�c�
+ҢF�K
��'�>'�����>�/��ni�����I'o<�]�X���.�59���8�~�O]p�X��
G�F~�2�*��� ���^�44	�Ǟ�
�Dx6�f���I�i���b�i��G7?�toa�@�)(C>Ә'	yO���ݹ�b��(��[�ѿ�V�X���g����,��Q6��
y
+��\�R�H��S��>�6�|ۅ񟼱m�$��.��>E��}v��y}�\
���@"W0g
+�L�4q�-�C��
+�M�4�������/
=��ܖ��<WM���[�0���b�P�
+�i��zl��B�A�(|�������U�%A�Iy�V�(<n%����t�=��۝A��q��V>}>0�G���	�C��4�
s��з ��T�fTx���.�/RGn�p�^���i�B�
+�����T�w�����]~��7�N��s%��z_?�K�	�y��u����@�e�Sr��Y1�u�[������ `�:@��0�F��
��9g"��g��=������;1�f�l5 �A��S�D�頮�UB��g�I|���,��״���
&�6�<x�X�l}�4(
+�tH��A
&]�v)�'Vh�r�(���`7�*]E�|nbN�����iS���*��^��e� U�'��϶&�g�/�?)d���f�.;��Jy�Jq00���crtèߙR_7nx�j,s j�]S�I�g�n�"s<:4��c�r�uU.�Vn��-UYÎ�R��\�txɖ�*��1�-o�h�yw��<a���+���,"@����WL<;����<��
1��i�}
wrK��"�Q�����]�ttx�-b&�ݾww��T��3녶�:lJ#��*�蘼M�M�}j�p랸�z]X�g���
��I����
v��{q.�t�ll�HS�o����˞N�`� u9�|
+endstream
+endobj
+26 1 obj
+12418 
+endobj
+27 1 obj
+<< /Filter [ /FlateDecode ] /Length 28 1 R >> 
+stream
+H��W�o
I�q�[�������|��}�v|Y�N�׾�5��ޝdvf���G��
��NB�	^�pH�	��g��#o�g������ٙ��d����tWUWկ��faio�y��R�\X�_tlӴ����
u�t�z
�A�Z�cX=�x<0- ���,} [7�M"K��mNn��(�W�R��&���a��Tw
��?%���
+��P+�Y7:�a[�3E�{�[{�Q7 ��+|A�
�v�o
x[��P��b�!���)��-�F�5۴
7�6E+ϗu���v���|��
+����kx}��͞��� �.`88�pp�s4rʖ$s�^:Y�3���shw��ˁ�KM
+<�I��y��sn�q��s���
�n��@O���73I���x3�c�ӝ
�ZP�@g���I�e���mH�Wp!Oz1\|�r�݃���
�Ѐy��l�޵;��8m�5M�B��5�;^�֝.�`�'2�ԓ���P�R*m{
����j2�)�J�)�J) '�MF�{�n�C
\�9��.q��b
��C}H
�
�L��$Q��nS=$�?�#�l�=���'$�Ե�Q�#k<���p���� �B�*̦��(
+���
+K�}Pf�
�nw
S���<{��T�Po�9 Wx��8>ݭC(� F[7u�3��	{䙆E�G��l����O�h�@�1�!�=��"�nK�:ԥ�!%�y3���
%.N6rLZ��G�Ҥ��
G\ �I���;�����A�v릹a�Ȼ�dmk�v��S�R�>��
��D��!3���c˱�xΦ|�7:}�2^���5�2��6�
�h��������!f;6���5����5Gwv6���N��
8�-�xFG7ż��pz���V�"(:ɳ�ҵVkҝ�����|�"�۰:�K�i�ԧ�w��M�	M.�äT
+̽=z'k�4�t�?0�^�5z}/���@��M}�3.�J��ѓ�^L�N��F/�M��j��au�#7�n�2���(lOĿ�am��~�	dnW$��eҊ�lF
��%R�\)�
I��ը�K
+�\L�P�R..�T\�SqUB�|.�
+q4#"�Jp�ithZ<I�X�!���$��M�w}*�zJ���J��D��
�L���	Y�;Oz�=���4a��i�(�
+TPr�\I�8��.
+�EW���P�$��n\�Y
+�&��Z�}O�5���	��e	\ �H��
W�"��n��������+��!y�R�(���Ћ�I��t�g+G����#M��p�xh;
�B��b;���tiwڑd��Ml��G�eGM-1,�/�]��he�}�� ����.Sx]�������!�k���X[M��:����J���h�h��l}Z,;M
m�NO��{����:����J�5l�^��a�x�m���2\l�&�
� �:̽#0�>���0�
	����N�9�����cX:"%�I
>�Hٷ
j�Z��V#jI-�UM%nM-����"�r�+R�V���ZV����D+kE���FkMX�@�­)�
+�r$=Za:���ZU��A@�_�K|F�k f|<��"
+�Y�L��=�B&�[	�[��M����/�Z��.�9z���i^
+�*�/���
+r�Bʪ�~��K,q&�*doP�J�
,L�ݪTjU�f��E�j��Ȗ@X����Մ �1��v���}r�+a?"������<����K��\�J~\�%���
j�\��p���F-K[�@P�j5Z˜ҊRY��������X[���U)�M�TU�%U�I$�Z
+�Ƨ���PG��56���Me��
���i%FW%9�4�V���Z�0•����&M���f$�$���[`�Ä�E}���ۺ�Ar_��"{�P�
wyHaey˱ӎ�.oR��#(%��=��[����h5|������@Ev�ewh�n��3��7
�T�h(��(���
5�ȒDJ~��Ϥ�q
hß*A �>C1�M�¶
�
+���^��K��s1�n^��x�׸�c��
�5.��?�������3��g��s?i���l^�z%�
�0n]_��_y��
9X�~|��
���;�[�S�
<�k\�1_c
�r��Ko|�k�����?��[�;���q�(]��KXG����|����׹�
�$���w��7o	�=�
s��U6_{��O�l|F~
��﷖]��@�i����z��w�9A8��o���Z9���
�^~�}�q��E�D�D^�3
���H�eq&�73��G
I�0
�߼��<o<�G��g��D_�To��O~�(mH���x�g�|��^x�#	��[�q`w����]���z�N�/��o��|N��}�;_�}s�&�,�c�Q�y����Y�l�4h&#�1�G���5ĂՆ���9
�ț�p��C��7j��o�?��0����=f4��ÿ`,�:�������Y�s�_.,?��A�K���`���x��q���i�|�����w>����u����~5댏�GR [...]
+�N�
8
��+��R�g
XW�\��|ߐ��>��J\��������{$
x6o�xw����q��X�
\�� ~=n�e�`#���X���~���
ij�yr~=�]'�"�|�k!ڛ��l���5���;��f
y����_����i ��h\�:�T��$�Ӥ�
+mQhK��AB����Zm�`�)?�����}�7l�B�"���3��;
�
�
����<[��y0� �?���ub^=��d�8A�y�>x���}�C�����u����j���6����8��h
o��?�;
+�ku�yg�[^��q�P
� kJ�Y���h�ܽ�9���԰G��_i����<_�:`�m�9|�P
� � O�tn
� �`�֯zú��;;��3�^t����<~p��\��v,ƣ���z
+�?�wn�N����_��) 
������b��X(�(J>����b��X�Y�b�J�7��`�mV�R>adl�U��nm����=LiC�
�nƨR�0
+\�!���F�~$`Z�ei�Z6�NF�G�$�&��פV�C�5H|��+��q�e���ՙ
/��M|d��i�q���
5MZ����u�Y�6�
YӔe㷐#9A<U�
\�!���Χ�����0ڠ��w}�&����x
�1�g\>�V�c6��(}������YR��>>w1L0b�_��)4_��"oNl�ϡ�r͌I���4��'8c�(�Z�x�!�'_T�	�)�-�cf�<�w{;[�t3�=�#}��Sq-�y>z�����Sq5�H}՝Ⱦꎥ�TJ���ڴ��g6�9�ѡ�&u$�<�$��Nty^��y��c�Im�7ˉ���A��*�}��<�L'W6	��·'����#?�)<����C��̶�w�  *u��
+endstream
+endobj
+28 1 obj
+3672 
+endobj
+29 1 obj
+<< 
+/Type /Pattern 
+/PatternType 2 
+/Shading 30 1 R 
+/Matrix [ 1 0 0 1 0 0 ] 
+>> 
+endobj
+30 1 obj
+<< 
+/ShadingType 2 
+/ColorSpace /DeviceCMYK 
+/Coords [ 213.99658 362.99902 378.00293 362.99902 ] 
+/Extend [ true true ] 
+/Function 31 1 R 
+>> 
+endobj
+31 1 obj
+<< 
+/FunctionType 3 
+/Domain [ 0 1 ] 
+/Encode 32 1 R 
+/Functions 33 1 R 
+/Bounds 34 1 R 
+>> 
+endobj
+32 1 obj
+[ 
+1 0 
+]
+endobj
+33 1 obj
+[ 
+35 1 R 
+]
+endobj
+34 1 obj
+[ 
+
+]
+endobj
+35 1 obj
+<< 
+/FunctionType 2 
+/Domain [ 0 1 ] 
+/N 1 
+/C0 [ 0 0.48999 1 0 ] 
+/C1 [ 0 0 0 0 ] 
+>> 
+endobj
+36 1 obj
+/Pattern 
+endobj
+37 1 obj
+/DeviceCMYK 
+endobj
+38 1 obj
+<< 
+/Type /Pattern 
+/PatternType 2 
+/Shading 39 1 R 
+/Matrix [ 1 0 0 1 0 0 ] 
+>> 
+endobj
+39 1 obj
+<< 
+/ShadingType 2 
+/ColorSpace /DeviceCMYK 
+/Coords [ 219.68799 362.99902 372.31201 362.99902 ] 
+/Extend [ true true ] 
+/Function 40 1 R 
+>> 
+endobj
+40 1 obj
+<< 
+/FunctionType 3 
+/Domain [ 0 1 ] 
+/Encode 41 1 R 
+/Functions 42 1 R 
+/Bounds 43 1 R 
+>> 
+endobj
+41 1 obj
+[ 
+1 0 1 0 
+]
+endobj
+42 1 obj
+[ 
+44 1 R 45 1 R 
+]
+endobj
+43 1 obj
+[ 
+1 
+]
+endobj
+44 1 obj
+<< 
+/FunctionType 2 
+/Domain [ 0 1 ] 
+/N 1 
+/C0 [ 0 0 0 0 ] 
+/C1 [ 0 0 0 0 ] 
+>> 
+endobj
+45 1 obj
+<< 
+/FunctionType 2 
+/Domain [ 0 1 ] 
+/N 1 
+/C0 [ 0 0.48999 1 0 ] 
+/C1 [ 0 0 0 0 ] 
+>> 
+endobj
+46 1 obj
+1885 
+endobj
+47 1 obj
+<< /Type /XObject /Subtype /Image /Name /X /Width 100 /Height 40 /BitsPerComponent 8 
+/Intent /Perceptual /ColorSpace /DeviceCMYK /Filter /FlateDecode 
+/DecodeParms << /Predictor 15 /Columns 100 /Colors 4 /BitsPerComponent 4 >> 
+/Length 46 1 R >> 
+stream
+H��
+Lg�[�@ÄAE�vhuh���4sfsN�sa�����$~�
+��@
Hݘ�L\0sg�M�
4n1j&�
+n���BJc�U����޻^{�ښ�O�h���������?�X$=���!�ky���Ы0�)LDh
+��D��'K$j���]mR�8���	D�
���.���UG����0��h��q-z1v�~�{��|���6m���������u�B�H���0�^	h
%
�7et[sq�A"1$�ᶲJ�u�MD!3�����Y3�S�ĩ(+
+���1�M�����bX��]L�*��GO��&��U���1��=WI��c1f�26�yWedaj��"�`֔�N��Eù�D�D�ȿ\"	����Fh�/E��ݲ�_��6o�=ҷZ����=I�eݽo���N�m,�����:���
��B��r{�Ĝ����j�I���8�}�a��
I��c�sL�C�j"pH�O5�5�����I�p[�Eǥ~
+��ҭ����Lsmb@��9 �l�
+�7�M!������VD����FN!��y�M�a�j�x@�|��5&�b���:#��Z D�����d츔�����N�&rg�4t�Ng�[���v����\6S�t��z��B�$N����#�Q���]�$�F����.
+�G0chd
��g�,F{���/�j?"�4���+ at 9ӵ��!ļ�2<b�N�9�
���'�9�U&�2��jw� d�#�M�/�x�~����p��^�D����%TL0�o�v�-��S@�/�ҵ-�?�D�EO�|/8��r��	�'?r��V��O�HzԎ���㱉D�g�L���4��5�[���~\�tZ�0�M���.ǵ�R���ǶfK�)�?D�7}����D��~�<��M�֜%��'�sN�T�u�ԩn(��u��g���l$$/X;K6��@�
�]�`�<�
n;q���@<�\�kݰ�\�
�/����
��t�!��l�� ����g����
ݣ�Ԭ��P	�ݷ]�
�L�Pf
+>^F8;�S����
�W��JL"A�,}�"�U�%��;Q�CO@��3_!}R�����r8�cet��EUH:D8e��uP$�R��5ԩ���t�$��Ԫ�X�w0Kw�J��_���H�$FO��(��
W@��QQ�rsTA�2K�J�}yV���9�G$�
.%��ҍ2�D�b5 "�z�M9�Zs�s�t������&��# 2{����'X;E1�n�;�ّ ����x�ڞ?r�gP�i�Oi��Eohl���>���ʕ�*#�bL
A��da	Ib[��B2d>}�C��OԸ�~���g�v�ˁS�M�
b��"��
7#���@�e~<P}�K':y�x1�gj�W�
�Z�W�>��l1�.���|�D���ӥHֲ
+�0�2S�\
�I1�A�g݄���q
���"Q�B�"@���)�'H�EM�
>XO�o�xh
n;W�&2o�>��h���\z)�"f:9��*(��~H!�W|�?Y���H��J���%2[�o�'A�]6S�t��}2�
W��[��7^x��۳�׊�9z�0Q"�����W��(qp��U�)��%�o�&��c�q��G��#�J]=�ւ���m����DY2u��i�Z"��9Lr9ӵ��!�sf���؈��.S��ʕ$a YK
+�%yT��%�ம�z���{J|8"�b�I��}��p�H� ��J�*��+K�?��h
��e9�JQ��J��@���Z��):�"�]�p�NzK��>���r���d����sm�����ʢ%D���T
i�).��Gh��"+�$��	�����h�^��iP��ԩr�>6Uw�+���BK�I�l�Wa"BS���&"4��Ma"BS�����S?��F�` ��C
+endstream
+endobj
+48 1 obj
+/DeviceGray 
+endobj
+49 1 obj
+<< 
+/Type /Font 
+/BaseFont /DDHXVK+Myriad-Roman 
+/Subtype /Type1 
+/Encoding 50 1 R 
+/FontDescriptor 51 1 R 
+/Widths [ 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 
+212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 
+230 337 497 513 792 605 188 284 284 415 596 207 307 207 343 513 
+513 513 513 513 513 513 513 513 513 207 207 596 596 596 406 737 
+612 542 580 666 492 487 646 652 239 370 542 472 804 658 689 532 
+689 538 493 497 647 558 846 571 541 553 284 346 284 596 500 300 
+482 569 448 564 501 292 559 555 234 243 469 234 834 555 549 569 
+563 327 396 331 551 481 736 463 471 428 284 239 284 596 212 612 
+612 585 492 658 689 647 482 482 482 482 482 482 447 501 501 501 
+501 234 234 234 234 555 549 549 549 549 549 551 551 551 551 500 
+318 513 513 519 282 512 548 510 677 802 300 300 212 788 689 212 
+596 212 212 513 551 212 212 212 212 212 346 355 212 773 549 406 
+230 596 212 513 212 212 419 419 1000 212 612 612 689 894 863 500 
+1000 354 354 207 207 596 212 471 541 418 212 255 255 523 523 500 
+207 207 356 1156 612 492 612 492 492 239 239 239 239 689 689 212 
+689 647 647 647 234 300 300 300 300 300 400 300 300 300 300 ] 
+/FirstChar 0 
+/LastChar 255 
+>> 
+endobj
+50 1 obj
+<< 
+/Type /Encoding 
+/BaseEncoding /MacRomanEncoding 
+/Differences [ 219 /Euro ] 
+>> 
+endobj
+51 1 obj
+<< 
+/Type /FontDescriptor 
+/Ascent 831 
+/CapHeight 674 
+/Descent -250 
+/Flags 32 
+/FontBBox [ -46 -250 1126 831 ] 
+/FontName /DDHXVK+Myriad-Roman 
+/ItalicAngle 0 
+/StemV 88 
+/XHeight 484 
+/FontFile3 59 1 R 
+>> 
+endobj
+52 1 obj
+<< 
+/Type /Group 
+/S /Transparency 
+/I false 
+/K false 
+/CS /DeviceCMYK 
+>> 
+endobj
+53 1 obj
+<< /Height 52 /Width 128 /BitsPerComponent 8 /ColorSpace /DeviceRGB 
+/Filter /FlateDecode /Length 54 1 R >> 
+stream
+H��{TWU��k֬i��i^k��<lz(��R�l�)&K�
�T�,MAM�B?����F�|c>"e88��b��%�����|���3�{��w������
{}�]�޻��~�>��#�G#I7%iR�n蚮�W��
+���f]��/��+��n}��j�[��:g�Ke�N�t���)�.�4�K�X'\�x�E��P�V��
+�:j���kCG

�rV�K�:�ҹ/
+
p�,�
��ә|:����R��n�W��r�_jb`��{�\����חN?U�w

�{x���~�s{��n*ͣS��d'��A��Љl:���eѷ[�xm��
+tt-}���Π#+��
+*H�C)t(�.���З����y��D-?A�7K��}>C�3M��m�d�?N-o��Y����ڮ����v���9J�����p-�
+�C��״�C�m��O#��A�'����-/i�õM}��{k{i�=�
+�����Z�4�	��OѪ�PF(���Vv��
����N�L��PJ-�@�Ӳi�)�~J�-�=-�--jG
�҂64�74����/i��)�grNk� g����k9�\1S-}�]��/�����눿�u���RƷж���K�l�>ˍK��돿��ם�
��5�Y�3��O��f���Z���F|�Jl�[�Ŗ�Ė��bs�ؔ*6-'�����KE���Xd.���źyb�\�.Q��#�$�5���bu�X'VM�����"}�H�,�'��N�C|8�лb�;�]i�D�X�:FW�(�<Z,��G��7Ų�b�0��
+��u�4T,yU,"��"�"u-
$
�/���ż~b^_]�(���/���"����H�k��bvw1�ob�3bf7������qO�O��O
+�5�q1zLL�
�u�u�;U�_θ��:�[�o���w:bCCB�����g���_��v�С�C��m
�{������P�Cz�p��
+
�Ą�AA
SSSk�j7-k׮�/��n�Z�0���sFw���~L_%�u#
�ȈA������>��
i�

�III���8
+

:t(�B#..���
+
�hKc�І3�8�^��V_�Ȉ��O[�/{ e��R�t�H�oh.
+e��caa! �$�"ͧ

�ȃ���=fҨ�nf�r�P�7o����Z���@�-XU�ߣ�r�
��z�

+y\L�T���<��-���!������w�qr���4‘��!�9
yt�c�aj
+����U�
+�ڹ��G7��&ȍb�ES�T�?5%911��� ָ��7%�ɪ�;����\���]e��߁�
:�u��ct���̿q�&�ym�Z�g,�X.o�H
B�o�7Z�����W�_���쩡�W��GFD@�T�oՄ�_�"��F�\jb:��ŧ�-��U=e�|��8�\iۮ��E
��&��9
q��85o�̞���OLL��vyk�����-^xE����x��B�m�ƾw��^^^PPH��
��N���>m'9�PAA��?:*
+m��ݶ���� �܂��^��m8p��SL��~ȣ�¿���|
����A��@�lQQ����ÿu at +
Y˖-�~�o_����)gd{v���W���70ji��[�
&_a7%�[�n��Q�??�������+��
+Nq�}h�*)AC`��K���x���q�K7|D��E�8�=�"lv�x
��C����<��8o\�>Z-��cmd
 �XE��
��e����޽{A���Ygm����k_@},3�"x�Ε�y��u�G�W�

+i ��1���v�s,9��|�kDU3�����wX�ע^�(�+��>�� y�KKJ0z������-
������R�J
^s�p+�?�X"V����"ɳ�(�p
a�6k��<�|�Z<����V���ar�:k��[��Qz�e�f;R�=b�����6��K�ꢹ�[-��y��50�
M�s��?�Y�
+�6t�d�u��X�p�����<�?�~�5�<t^/T�$���HO�9o�'�v9��9nY���eN�3�
w�V���_�'Oq�DT��3�4+
7lXϧhHw-j
 K��\��������`b�
f��?�1؁�����������Z�뜿4B�@j������2�C|�����v���X���K�k��,4��ʧ*����Q��1�� �R߫�������V
k
+����!�$�_���ZZ��_暜3�Z"�՚���_
+�������—Fy�
jT/\���䲇waj��[���^�w�UV��a�w��HA��.5:\���������:矙���;�.�jF�'B�̙W�|��ڈye�[
+�ܜ푑�޾��2�V����r�x:�h�o�a�&�ۯ���pU���+�������?��f �Fθ��N�D$���gS5�u�ޭz��ƥ��������զg@��A�_������J��?�
Y�y�� �g���+�݊��+��/���Ա#�K�Z� 0"������oa�m�C�\~���k���NG,&Btt4���f�� 
+����ϝ����ٲ�� :�4Pd�/���e�Ji���Ή�z�9q��	P���uŎsk�3�-]�Bc
����(C�.��r����b�44��0���n��
7ԭ�\���!�^q�
+v��1�nE�4z���.����[�
Ѭ~�^���P�K#_t���/���1��Ko>�VO]�{�I��<#g�k�O�K'*����_^>	O�x
��~8J���,
t� ��Og�Q�
:��J���.*�I'w�w9t"��o�cY��*�DE�p
]K߬��3��J:��
+��P
+
J��K��n��4
�q
�#:�(�(�("��""��C:袋�N�袐袋ʥ����L���rie+SӖ�&�e
+��i�ܦ��Z��w�� QP����_>���/��*^�*c�R���(?����ʎ��(�
�� �
@I����^�F�N���m�߂G��p#���`
����j�[��+��
9Kqg1L
�+���`�
C$�fS?��fN筩̘��ɼ9�i�:�7�3e
���1�:�ɣxe$/�`�p&㥡��v0��@�`\^���}ۇ1�x�'5���:���C����@{K���������I�
+_H���������3������&O�׋Pj��C@�-6aQOg��xǦ7B���
+�R�F�p)��@Иِ'trh5њ�z#�
�ճVǚ
~Hgu�S�>E�J�۠T"��+N�
+yE��� ;���B�,����
�=(�%��#���0�5�q%r�
�%0-�5M
�=?j��a�fɦ��f0s��*�$����C�Ϳ�0
�

Rm
���ڧ�U�Q��̧��Q�K�
��C�YԤ��]�ס�M��P�Fu_Tɧ�._�`�`6Q�*ק��*ի�I2�9��?�y����  A=[
+endstream
+endobj
+54 1 obj
+3418 
+endobj
+57 1 obj
+<< /Filter /FlateDecode /Length 58 1 R >> 
+stream
+H��T�n�8����
ŋx� u���`�F�KP�B�lu��r����P�%�(
+�	�!9��
��vh���7
����u�w��~�{|+*>
[7�@�:?�^��]��ư��S��Y�٫�?�;@���pq=���=����Ou>���ݧh��]�
 ��aķ�r^b��2XI)$Hڵ����j���C=��yN���f{��D���
7`����(�!���/�~�%���+��·�(�Ǩ���w�
߹i�
+
=�J�X��#��]�
+Ed�K��fD��[J��Ra��%�,�Ĺ!\Z��l���
���	�R�d<�(��+j8��"��@KJ)���8�bC�L0�-�qv�%_�%�槮��
�@�XVU��8�T�%��R��('Rqk�ME��%:����-�!@��aς�%���|?g��r��1��\Q���Z���5��BR���cLZ�)Z�`��~A����
����dآ�������������}
++pӡ�ώ���Cyh��=M�կjh�'|�R�Rà%?�q�M���}�
�\ŏ����s�7����݁
�-��R������aF�\U�e[�Ӱ��������P\�L���w�t�L�Ц�
�s�
bi�.ʫ�=���"
+����lu�Ά ��q�X�Rħ�����x�G��0^V��*��j�����U�VJ�2q���P���ii�
+���02�h	����o˒z��I&q�N�$BL�D�wI��T�v��^����i����z޾�,v�a��m��/A�udveZ�S�B�MRE�yy��B0"$_
uk�w���` 6�=
+endstream
+endobj
+58 1 obj
+804 
+endobj
+59 1 obj
+<< /Filter /FlateDecode /Length 60 1 R /Subtype /Type1C >> 
+stream
+H�|TyT�
�I�	��x̼P��f�j]�Ū����,� jQ�$D�,�$�Mx�H�Rك�*���"(�Y�+�Rqkm��xN�`O����{����~����!
��6mr۳�c�W�B&
+��G�"g�
�9���|�o6em��6�{��:��޹7�[�� 6
W�v|-�brCBU�%��•k֬�bf����R�o�R%�P
+�FJ�(�B��/
+]�Å>3YJ��T)U���_�2�P$T)D���"L(?����x!s���ȘS�E
+%R�JĬc2e�L���#���@�=�̀84�@�
+�� ;�C�,�
��Y�/
�Â�� Ć*�K�#�
+.�)�Jc�f{���,�,r,&$�B��P3g��Z3$S�E�x�S)w��$֌�S/�$���!��W���n�M^�v�t�c��di�����;*0��8��k�����
�yC�N�/�&m�'W˺/��2�8�d�%�Lk{�k}���lm(#��'
��,C��F��������S�_��L��U
+]U�=��� 
�f�[ï/?]ߠ�

+UD���GՒܳi�@� P�x����c�ͤ��Q՞ч���v�����e�K�n�B������s���1M��D�ط��ޖ�*%��
+�
M��J�����
+r=�nq
���r3x�Rǃ+Õ:C<�
+�
����f��5{�n��ۢܪ50���a�A�ffOZ= eh���J|j���RW|�_Ч�8�=Q/�<e�oޙvXD>��
+��4���V�����\�?GrS4cԅ�p�D��-5|e�h� l'����"�������������mq�%D�(b��S��?�s��������d��������=YLp�J���8
��lde���x�}�
�\�f�d�� ��
�X�
+t�C^�K�mOPH�Sۑ������
]�F� �C{�x�	6w�>�m�$
(v�m�M4�F��"�?��:R�R2S	q�X�J+/?���iF�jj�0�卙A�C�c
��c����3�(�q��G=z�Fp �}�,rxI�v����Z�k��߻�
�y�\b���҇?�t\J����{�n�O �9Y���6e�O���J�p�șbSb���stł�b@ҫ�O�h�����%`ɍ�Ƃj"�G$9,X��:w�YZR7��?�x�g�y���,�K�0�ڛ��Q�6#��e,M�G���SC���"�r<!�x.	L;H����Tnn���
n/-
����k�X^�CPaƦ�D�ݾ�;k�%�Pl:�kD�6��:അ�Kڑ��fOt׷U��](=g뾕����1[��W�.���
+[/��e&`!����ڄ�$�'�_���� }��[D���#��%'	�t)C&.� ��d�{쭨8��q
�U+5¯+�������T�������Ť�����D��1femh���H.�Q��|	�[�Չ��7�X���m�o@��ТX[�M�	5Ht�=n�f��xfh��>��?7���M��_Ыi��ˀ�������g��ּp
+��\���ެ��{D󷣦�h��ѽU=r�	!̘h��
�c�
2�P�Aq;�.�
5��}�%0�s
+��<�
2^b����?���Z����������ct�Đ^qW{&�7� �ᜋ�
+���`޹�?�y'��rH,����V��o��ǐ�(V��
�5��}\!�z� �=�M������
I�
NS�����jҳ\^�,�?󿮶��I�d 1F���
=<�v4�3��W�*�@
����(��;�5c5eg�=��E=aڶ��m�6r�����(BUR�Ԍמ>v�Hf����$��O��#A�h
��pAR�=��$;�W��k(���`��8��H@�acW�y�-�h�O�^��q:��
+VPq�
�Jg$�$�9�?/�t$u�_r��.�z:+qW�n�L<�3����@k͕|�
�
��.��ƑN���ld
pq����j�
5FE���Ұ�K�v�$#�P��	щ�D9S2����3��Zs��}�~��	j/��LI�������邴̴�TB
)S�E�"�b�J]�K���k��n� k�5xn�
]���P�ј֔'��ּ�~c�j��$���4��;v�w�i{��}�9�O�Ă)�(�
0aN�	���y8��y��q=�>7���q?��
�ݢ  fl-~
+endstream
+endobj
+60 1 obj
+2183 
+endobj
+61 1 obj
+<< /Type /Metadata /Subtype /XML /Length 818 >> 
+stream
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d' bytes='818'?>
+
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+ xmlns:iX='http://ns.adobe.com/iX/1.0/'>
+
+ <rdf:Description about=''
+  xmlns='http://ns.adobe.com/pdf/1.3/'
+  xmlns:pdf='http://ns.adobe.com/pdf/1.3/'>
+  <pdf:CreationDate>2005-06-20T15:58:54Z</pdf:CreationDate>
+  <pdf:ModDate>2005-06-20T11:03:20-05:00</pdf:ModDate>
+ </rdf:Description>
+
+ <rdf:Description about=''
+  xmlns='http://ns.adobe.com/xap/1.0/'
+  xmlns:xap='http://ns.adobe.com/xap/1.0/'>
+  <xap:CreateDate>2005-06-20T15:58:54Z</xap:CreateDate>
+  <xap:ModifyDate>2005-06-20T11:03:20-05:00</xap:ModifyDate>
+  <xap:CreatorTool>Adobe Illustrator 10</xap:CreatorTool>
+  <xap:MetadataDate>2005-06-20T11:03:20-05:00</xap:MetadataDate>
+ </rdf:Description>
+
+</rdf:RDF>
+<?xpacket end='r'?>
+endstream
+endobj
+107 1 obj
+<< 
+/Private 108 1 R 
+/LastModified (D:20050620110319-05'00')
+>> 
+endobj
+108 1 obj
+<< 
+/CreatorVersion 10 
+/ContainerVersion 9 
+/RoundtripVersion 10 
+/AIMetaData 7 1 R 
+/AIPrivateData1 8 1 R 
+/AIPrivateData2 9 1 R 
+/AIPrivateData3 11 1 R 
+/AIPrivateData4 13 1 R 
+/AIPrivateData5 15 1 R 
+/AIPrivateData6 17 1 R 
+/AIPrivateData7 19 1 R 
+/AIPrivateData8 21 1 R 
+/AIPrivateData9 23 1 R 
+/AIPrivateData10 25 1 R 
+/AIPrivateData11 27 1 R 
+/NumBlock 11 
+>> 
+endobj
+xref
+0 114 
+0000000004 65535 f 
+0000000016 00000 n 
+0000000087 00000 n 
+0000000151 00000 n 
+0000000006 00003 f 
+0000000310 00000 n 
+0000000055 00002 f 
+0000000784 00001 n 
+0000001959 00001 n 
+0000010461 00001 n 
+0000024167 00001 n 
+0000024190 00001 n 
+0000041904 00001 n 
+0000041927 00001 n 
+0000062999 00001 n 
+0000063022 00001 n 
+0000082321 00001 n 
+0000082344 00001 n 
+0000089305 00001 n 
+0000089327 00001 n 
+0000095248 00001 n 
+0000095270 00001 n 
+0000118269 00001 n 
+0000118292 00001 n 
+0000139995 00001 n 
+0000140018 00001 n 
+0000152518 00001 n 
+0000152541 00001 n 
+0000156295 00001 n 
+0000156317 00001 n 
+0000156415 00001 n 
+0000156574 00001 n 
+0000156683 00001 n 
+0000156709 00001 n 
+0000156738 00001 n 
+0000156760 00001 n 
+0000156864 00001 n 
+0000156890 00001 n 
+0000156919 00001 n 
+0000157017 00001 n 
+0000157176 00001 n 
+0000157285 00001 n 
+0000157315 00001 n 
+0000157351 00001 n 
+0000157375 00001 n 
+0000157473 00001 n 
+0000157577 00001 n 
+0000157599 00001 n 
+0000159767 00001 n 
+0000159796 00001 n 
+0000161008 00001 n 
+0000161110 00001 n 
+0000161337 00001 n 
+0000161430 00001 n 
+0000164992 00001 n 
+0000000056 00002 f 
+0000000062 00002 f 
+0000165014 00001 n 
+0000165896 00001 n 
+0000165917 00001 n 
+0000168195 00001 n 
+0000168217 00001 n 
+0000000063 00001 f 
+0000000064 00001 f 
+0000000065 00001 f 
+0000000066 00001 f 
+0000000067 00001 f 
+0000000068 00001 f 
+0000000069 00001 f 
+0000000070 00001 f 
+0000000071 00001 f 
+0000000072 00001 f 
+0000000073 00001 f 
+0000000074 00001 f 
+0000000075 00001 f 
+0000000076 00001 f 
+0000000077 00001 f 
+0000000078 00001 f 
+0000000079 00001 f 
+0000000080 00001 f 
+0000000081 00001 f 
+0000000082 00001 f 
+0000000083 00001 f 
+0000000084 00001 f 
+0000000085 00001 f 
+0000000086 00001 f 
+0000000087 00001 f 
+0000000088 00001 f 
+0000000089 00001 f 
+0000000090 00001 f 
+0000000091 00001 f 
+0000000092 00001 f 
+0000000093 00001 f 
+0000000094 00001 f 
+0000000095 00001 f 
+0000000096 00001 f 
+0000000097 00001 f 
+0000000098 00001 f 
+0000000099 00001 f 
+0000000100 00001 f 
+0000000101 00001 f 
+0000000102 00001 f 
+0000000103 00001 f 
+0000000104 00001 f 
+0000000105 00001 f 
+0000000106 00001 f 
+0000000109 00001 f 
+0000169119 00001 n 
+0000169202 00001 n 
+0000000110 00001 f 
+0000000111 00001 f 
+0000000112 00001 f 
+0000000113 00001 f 
+0000000000 00001 f 
+trailer
+<<
+/Size 114
+/Info 3 0 R 
+/Root 1 0 R 
+/ID[<8c5fe2b95e8346b3ec676adf66d760c8><8cffb2a4432730e464babdbf9e0b8cc1>]
+>>
+startxref
+169587
+%%EOF
+
diff --git a/Source/mesquite/iText/aiTextIntro/splash.gif b/Source/mesquite/iText/aiTextIntro/splash.gif
new file mode 100644
index 0000000..b077b8a
Binary files /dev/null and b/Source/mesquite/iText/aiTextIntro/splash.gif differ
diff --git a/Source/mesquite/iText/explanation.txt b/Source/mesquite/iText/explanation.txt
new file mode 100644
index 0000000..7b98a7e
--- /dev/null
+++ b/Source/mesquite/iText/explanation.txt
@@ -0,0 +1,2 @@
+Introduction to iText
+This package contains no substantive modules.  It has a single module that serves to introduce to the user the iText library for generating PDF.  If this package is deactivated, the iText package is NOT deactivated.
diff --git a/Source/mesquite/io/ExportCharStateInfo/ExportCharStateInfo.java b/Source/mesquite/io/ExportCharStateInfo/ExportCharStateInfo.java
new file mode 100644
index 0000000..930b789
--- /dev/null
+++ b/Source/mesquite/io/ExportCharStateInfo/ExportCharStateInfo.java
@@ -0,0 +1,218 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.ExportCharStateInfo;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ============  an exporter for POY files ============*/
+
+public class ExportCharStateInfo extends FileInterpreterI {
+	String[][] delimiters;
+	int A = 1;
+	int B = 2;
+	int C = 3;
+	int D = 4;
+	int E = 5;
+	int F = 6;
+	int G = 7;
+	int H = 8;
+	int I = 9;
+	int J = 10;
+	int K = 11;
+	int L = 12;
+	int M = 13;
+	int P = 14;
+	int Q = 15;
+	int R = 16;
+	int S = 17;
+	int T = 18;
+	int U = 19;
+	int V = 20;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		delimiters = new String[3][];
+		delimiters[0] = new String[]{"html", "</strong>", " (", " ", " (", ") ", "<li>", "</li>", "<ul>", "J", "</ul>", "<li>", "</li>", "<ul>", "\n", "</ul>", "<li><strong>", "</li>", "<ul>", "</ul>", ") ", "W", "X"};
+		delimiters[1] = new String[]{"txt", " ", " (", " ", " (", ") ", "\n\t\t", "\n", "", "J", "", "\t", "\n", "", "\n", "", "", "\n", "", "", ") ", " ", " "};
+		delimiters[2] = new String[]{"txt", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X"};
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() { 
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatrices( CategoricalState.class) - project.getNumberCharMatrices( MolecularState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+	/* ============================  exporting ============================*/
+	int style = 0;
+	/*.................................................................................................................*/
+
+	public boolean getExportOptions(boolean dataSelected){
+		setLineDelimiter(UNIXDELIMITER);
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export Character/State Info Options", buttonPressed);
+		Choice choice = exportDialog.addPopUpMenu("Output format", new String[]{"Web Page (HTML)", "Plain Text"}, 0);
+		exportDialog.completeAndShowDialog(dataSelected, false);
+
+		boolean ok = (exportDialog.query(dataSelected, false)==0);
+		style = choice.getSelectedIndex();
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+		CategoricalData data = (CategoricalData)getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected()))
+				return false;
+
+
+		int numChars = data.getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(20* numChars);
+		String allChars = "";
+		for (int ic = 0; ic<numChars; ic++) {
+			if (!writeOnlySelectedData || (data.getSelected(ic))){
+				String thisChar = "";
+				if (data.characterHasName(ic)) {
+					thisChar += data.getCharacterName(ic) + " " + delimiters[style][A];
+				}
+				if (!StringUtil.blank(data.getAnnotation(ic)))
+					thisChar +=   delimiters[style][B]+ data.getAnnotation(ic) + delimiters[style][V];
+				AttachedNotesVector hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+				if (hL != null){
+					String theseAnnotations = fromAnnotations(hL, style);
+					
+					if (!StringUtil.blank(theseAnnotations))
+						thisChar += delimiters[style][H] +delimiters[style][H] + theseAnnotations + delimiters[style][J] + delimiters[style][J];
+				}
+				boolean firstState = true;
+				String allStates = "";
+				for (int ik =0; ik<= data.maxStateWithName(ic); ik++){
+					String thisState = "";
+					if (data.hasStateName(ic, ik)){
+						thisState += data.getStateName(ic, ik) + " " + delimiters[style][C];
+					}
+					if (data.hasStateFootnote(ic, ik)){
+						thisState += delimiters[style][D] + data.getStateNote(ic, ik) + delimiters[style][E];
+					}
+					if (data.hasStateAnnotations(ic, ik)){
+						String theseAnnotations = fromAnnotations(data.getStateAnnotationsVector(ic, ik), style);
+						
+						if (!StringUtil.blank(theseAnnotations))
+							thisState += delimiters[style][H] + theseAnnotations + delimiters[style][J];
+					}
+					if (!StringUtil.blank(thisState)){
+						thisState =  delimiters[style][K] + Integer.toString(ik) + " " + thisState + delimiters[style][L];
+						if (firstState)
+							thisState = delimiters[style][M] + thisState;
+						firstState = false;
+						allStates += " " + thisState;
+					}
+
+				}
+				if (!StringUtil.blank(allStates)){
+					thisChar += delimiters[style][P]+  allStates + delimiters[style][Q];
+				}
+				if (!StringUtil.blank(thisChar)){
+					allChars +=  delimiters[style][R]+ Integer.toString(ic+1) + ". " + thisChar + delimiters[style][S];
+					
+				}
+			}
+		}
+		if (!StringUtil.blank(allChars))
+			outputBuffer.append(delimiters[style][T] + allChars + delimiters[style][U]);
+		else
+			return false;
+		outputBuffer.append(getLineEnding()+getLineEnding());
+
+		saveExportedFileWithExtension(outputBuffer, arguments, delimiters[style][0]);
+		return true;
+	}
+
+	String fromAnnotations(AttachedNotesVector v, int style){
+		String theseAnnotations = "";
+		for (int ink = 0; ink < v.getNumNotes(); ink++){
+			String thisAnnotation = "";
+			AttachedNote note = v.getAttachedNote(ink);
+			if (!StringUtil.blank(note.getComment()))
+				thisAnnotation += note.getComment() + " ";
+			if (!StringUtil.blank(note.getReference()))
+				thisAnnotation += delimiters[style][D] + note.getReference() + delimiters[style][E] ;
+			if (!StringUtil.blank(thisAnnotation))
+				theseAnnotations += delimiters[style][F] + thisAnnotation + delimiters[style][G];
+		}
+		return theseAnnotations;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+/*.................................................................................................................*/
+	public String getName() {
+		return "Character/State Information";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports character and state information for categorical matrix." ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/io/ExportFusedMatrixNEXUS/ExportFusedMatrixNEXUS.java b/Source/mesquite/io/ExportFusedMatrixNEXUS/ExportFusedMatrixNEXUS.java
new file mode 100644
index 0000000..372608c
--- /dev/null
+++ b/Source/mesquite/io/ExportFusedMatrixNEXUS/ExportFusedMatrixNEXUS.java
@@ -0,0 +1,513 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.ExportFusedMatrixNEXUS;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+import mesquite.basic.ManageTaxaPartitions.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+
+
+public class ExportFusedMatrixNEXUS extends FileInterpreterI {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(AssociationSource.class, getName() + "  needs information to indicate how taxa in different blocks are associated.",
+		"The source of information as to how taxa taxa in different blocks are associated is arranged on export");
+	}
+	/*.................................................................................................................*/
+	AssociationSource associationTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatricesVisible(CategoricalState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return CategoricalData.class.isAssignableFrom(dataClass);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	boolean convertAmbiguities = false;
+	boolean useData = true;
+	String addendum = "";
+	String fileName = "untitled.nex";
+	boolean permitMixed = false;
+	boolean generateMBBlock = true;
+	String lineEnding;
+	boolean simplifyNames = false;
+	
+	boolean removeExcluded = false;
+
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export Fused Matrix", buttonPressed);
+		exportDialog.setSuppressLineEndQuery(false);
+		exportDialog.setDefaultButton(null);
+		exportDialog.addLabel("Fusing matrices into a single matrix, and exporting");
+		if (getProject().getNumberTaxas()>1)
+			exportDialog.addLargeOrSmallTextLabel("This exporter uses associations between taxa to be able to blend matrices from different taxa blocks.  Ensure such associations are set up (through Taxa&Trees menu) before attempting to export.");
+		exportDialog.addHorizontalLine(1);
+		Checkbox permitMixedMatrices = exportDialog.addCheckBox("Permit fused matrix with mixed data types (e.g., DNA, protein, standard)", permitMixed);
+		Checkbox removeExcludedBox = exportDialog.addCheckBox("Remove excluded characters", removeExcluded);
+		Checkbox generateMB = exportDialog.addCheckBox("Generate MrBayes block", generateMBBlock);
+		Checkbox simplifyNamesCheckBox = exportDialog.addCheckBox("Simplify names as required for MrBayes", simplifyNames);
+		//		Checkbox convertToMissing = exportDialog.addCheckBox("convert partial ambiguities to missing", convertAmbiguities);
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+		//		convertAmbiguities = convertToMissing.getState();
+		permitMixed = permitMixedMatrices.getState();
+		generateMBBlock = generateMB.getState();
+		removeExcluded = removeExcludedBox.getState();
+		simplifyNames = simplifyNamesCheckBox.getState();
+
+		exportDialog.dispose();
+		lineEnding = getLineEnding();
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+	boolean heterogeneous = false;
+	Class previousClass = null;
+	boolean firstNEXUSpartition = true;
+
+	int addDataTypes(Taxa taxa, StringBuffer buffer, StringBuffer MBpartitionBuffer,  StringBuffer NEXUSpartitionBuffer, StringBuffer NEXUSCharSetBuffer, Vector datas, int totNumChars, Class dataSuperclass){
+		int numMatrices = getProject().getNumberCharMatrices(null, taxa, dataSuperclass, true);
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getProject().getCharacterMatrixVisible( taxa, iM, dataSuperclass);
+			if (data != null) { 
+				if (needsComma)
+					buffer.append(',');
+				needsComma = true;
+				if (data instanceof RNAData){
+					if (previousClass != null && previousClass != RNAData.class)
+						heterogeneous = true;
+					previousClass = RNAData.class;
+					buffer.append(" rna");
+				}
+				else if (data instanceof DNAData){
+					if (previousClass != null && previousClass != DNAData.class)
+						heterogeneous = true;
+					previousClass = DNAData.class;
+					buffer.append(" dna");
+				}
+				else if (data instanceof ProteinData){
+					if (previousClass != null && previousClass != ProteinData.class)
+						heterogeneous = true;
+					previousClass = ProteinData.class;
+					buffer.append(" protein");
+				}
+				else if (data instanceof CategoricalData){
+					if (previousClass != null && previousClass != CategoricalData.class)
+						heterogeneous = true;
+					previousClass = CategoricalData.class;
+					buffer.append(" standard");
+				}
+				else if (data instanceof ContinuousData){
+					if (previousClass != null && previousClass != ContinuousData.class)
+						heterogeneous = true;
+					previousClass = ContinuousData.class;
+					buffer.append(" continuous");
+				}
+				int numToAdd = data.getNumChars();
+				if (removeExcluded)
+					numToAdd = data.getNumCharsIncluded();
+				int currentTotNumChars = totNumChars + numToAdd;
+
+				buffer.append(": " + (totNumChars+1) + "-" + numToAdd);
+
+				if (simplifyNames)
+					MBpartitionBuffer.append(lineEnding + "\tcharset " + StringUtil.simplifyIfNeededForOutput(data.getName(),true) + " = " + (totNumChars+1) + "-" + (currentTotNumChars) + ";");
+				else
+					MBpartitionBuffer.append(lineEnding + "\tcharset " + StringUtil.tokenize(data.getName()) + " = " + (totNumChars+1) + "-" + (currentTotNumChars) + ";");
+
+				boolean writeCodPosPartition = false;
+				if (data instanceof DNAData)
+					writeCodPosPartition = ((DNAData)data).someCoding();
+				if (writeCodPosPartition) {
+					//codon positions if nucleotide
+					String codPos = "";
+					boolean[] include = null;
+					if (removeExcluded)
+						include = data.getBooleanArrayOfIncluded();
+
+					CodonPositionsSet codSet = (CodonPositionsSet)data.getCurrentSpecsSet(CodonPositionsSet.class);
+					for (int iw = 0; iw<4; iw++){
+						String locs = codSet.getListOfMatches(iw, totNumChars,include);
+						if (!StringUtil.blank(locs)) {
+							String charSetName = "";
+							if (iw==0) 
+								charSetName = StringUtil.tokenize("nonCoding");
+							else 
+								charSetName = StringUtil.tokenize("codonPos" + iw);
+							codPos += "\n\tcharset " + charSetName + " = " + locs + ";";
+						}
+					}
+					//String codPos = ((DNAData)data).getCodonsAsNexusCharSets(totNumChars, data.getName(), numberCharSets, charSetList);
+					if (!StringUtil.blank(codPos)) {
+						MBpartitionBuffer.append(lineEnding + codPos + lineEnding);
+					}			
+				}
+
+
+				NEXUSCharSetBuffer.append(lineEnding + "\tcharset " + StringUtil.tokenize(data.getName()) + " = " + (totNumChars+1) + "-" + (currentTotNumChars) + ";");
+				if (!firstNEXUSpartition)
+					NEXUSpartitionBuffer.append(", ");
+				NEXUSpartitionBuffer.append(StringUtil.tokenize(data.getName()) + " : " + (totNumChars+1) + "-" + (currentTotNumChars) + " ");
+				firstNEXUSpartition = false;
+				datas.addElement(data);
+				if (removeExcluded) 
+					totNumChars += data.getNumCharsIncluded();
+				else
+					totNumChars += data.getNumChars();
+				logln("Fused matrix will contain " + numToAdd + " characters from matrix " + data.getName());
+				
+			}
+		}
+		return totNumChars;
+	}
+
+	int getNumberQueuedCharMatrices(Vector datas, Taxa taxa, Class dataClass){
+		int count=0;
+		if (datas == null)
+			return 0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if ((data.isUserVisible()) && !data.isDoomed() && (taxa == null || taxa == data.getTaxa()) && (dataClass==null || getProject().compatibleMatrix(dataClass, data)))
+				count++;
+		}
+		return count;
+	}
+	CharacterData getQueuedCharMatrix(Vector datas, Taxa taxa, int j, Class dataClass){
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if ((data.isUserVisible()) && !data.isDoomed() && (taxa == null || taxa == data.getTaxa()) && (dataClass == null || getProject().compatibleMatrix(dataClass, data))) {
+				if (count==j) {
+					return data;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	void composeForTaxon(Vector datas, Taxon[] components, int iTaxaBlock, StringBuffer buffer, boolean master, Class dataSuperclass){
+		if (!master && (components == null || components.length == 0)){ //no representatives in this taxa block; write gaps for those matrices
+			Taxa taxa = getProject().getTaxa(iTaxaBlock);
+			int numMatrices = getNumberQueuedCharMatrices(datas, taxa, dataSuperclass);
+			for (int iM = 0; iM < numMatrices; iM++){
+				CharacterData data = getQueuedCharMatrix(datas, taxa, iM, dataSuperclass);
+				if (data != null){
+					for (int ic=0; ic<data.getNumChars(); ic++)
+						if (!removeExcluded || data.isCurrentlyIncluded(ic))
+							buffer.append('-');
+				}
+			}
+			return;
+		}
+		Taxon first = components[0];  //this will tell taxa block;
+		Taxa taxa = first.getTaxa();
+		int numMatrices = getNumberQueuedCharMatrices(datas, taxa, dataSuperclass);
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getQueuedCharMatrix(datas, taxa, iM, dataSuperclass);
+			CategoricalState cs = (CategoricalState)data.makeCharacterState();
+			CategoricalData categData = (CategoricalData)data;
+			if (data != null){
+				for (int ic=0; ic<data.getNumChars(); ic++){
+					if (!removeExcluded || data.isCurrentlyIncluded(ic)){
+						if (components.length == 1){
+							int it = components[0].getNumber();  
+							if (heterogeneous && !permitMixed){
+								buffer.append(CategoricalState.toNEXUSString(categData.getState(ic, it)));
+							}
+							else 
+								data.statesIntoNEXUSStringBuffer(ic, it, buffer);
+						}
+						else {
+							long fusedState = categData.getState(ic, components[0].getNumber());
+							for (int itc = 1; itc < components.length; itc++){
+								fusedState = fusedState | categData.getState(ic, components[itc].getNumber());
+							}
+							//CategoricalState.mergeStates(fusedState,categData.getState(ic, components[itc].getNumber()));
+							if (heterogeneous && !permitMixed){
+								buffer.append(CategoricalState.toNEXUSString(fusedState));
+							}
+							else {
+								cs.setValue(fusedState);
+								buffer.append(cs.toNEXUSString());
+							}
+						}
+					}
+				}
+			} 
+		}
+	}
+	/*.................................................................................................................*/
+	void composeForMasterTaxon(Vector datas, Taxa masterTaxa, int it, Taxon[][] components, StringBuffer buffer, Class dataSuperclass){
+		String taxonName = masterTaxa.getTaxonName(it);
+		if (simplifyNames)
+			buffer.append(StringUtil.simplifyIfNeededForOutput(taxonName,true)+ "   ");
+		else
+			buffer.append(StringUtil.tokenize(taxonName) + "   ");
+		composeForTaxon(datas, new Taxon[]{masterTaxa.getTaxon(it)}, -1, buffer, true, dataSuperclass);
+		if (components != null)
+			for (int iTaxaBlock = 0; iTaxaBlock<components.length; iTaxaBlock++){
+				if (iTaxaBlock != getProject().getTaxaNumber(masterTaxa))
+					composeForTaxon(datas, components[iTaxaBlock], iTaxaBlock, buffer, false, dataSuperclass);
+			}
+	}
+	/*.................................................................................................................*/
+	boolean needsComma= false;
+	String lsetStart(Class targetClass, Vector datas){
+		boolean[] matching = new boolean[datas.size()];
+		String s = "";
+		int count =0;
+		boolean first = true;
+		for (int i=0; i<datas.size(); i++){
+			matching[i] =(datas.elementAt(i).getClass() == targetClass);  // a little dicey givenpossibility of subclasses
+			if (matching[i])
+				count++;
+		}
+		if (count>0){
+			s += (lineEnding + "\tlset applyto = (");
+			for (int i=0; i<matching.length; i++){
+				if (matching[i]){
+					if (!first)
+						s += (", ");
+					first = false;
+					s +=(Integer.toString(i+1));
+				}
+			}
+			s +=(") ");
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	void fillMatrix(MesquiteFile file, Taxa masterTaxa, StringBuffer buffer, StringBuffer mrBayesBlockBuffer, Class dataSuperclass){
+		if (masterTaxa == null || buffer==null)
+			return;
+		if (mrBayesBlockBuffer == null)
+			mrBayesBlockBuffer = new StringBuffer(); //just to avoid crashes, & absorb "appends"
+		MesquiteProject project = getProject();
+		int numTaxaBlocks = project.getNumberTaxas();
+		if (associationTask == null && numTaxaBlocks>1){
+			associationTask = (AssociationSource)hireEmployee(AssociationSource.class, "Source of taxon associations");
+		}
+
+		buffer.append("#NEXUS" + lineEnding + lineEnding + "begin data;" + lineEnding);
+		StringBuffer[] taxaStrings = new StringBuffer[masterTaxa.getNumTaxa()];
+		StringBuffer dataTypesBuffer = new StringBuffer();
+		
+		ManageTaxaPartitions manageTaxaPartitions = (ManageTaxaPartitions)findNearestColleagueWithDuty(mesquite.basic.ManageTaxaPartitions.ManageTaxaPartitions.class);
+		StringBuffer labelsBuffer = null;
+		if (manageTaxaPartitions!=null) {
+			labelsBuffer = new StringBuffer(lineEnding + "BEGIN LABELS;"+lineEnding);
+			String labels = manageTaxaPartitions.getNexusCommands(file, "LABELS");
+			labelsBuffer.append(labels + lineEnding + "END;" + lineEnding);
+		}
+		
+		StringBuffer NEXUSpartitionBuffer = new StringBuffer(lineEnding + "BEGIN SETS;" + lineEnding);
+		NEXUSpartitionBuffer.append(lineEnding+ manageTaxaPartitions.getNexusCommands(file, "SETS"));
+		NEXUSpartitionBuffer.append(lineEnding+ "\tCHARPARTITION * matrices = ");
+		StringBuffer NEXUSCharSetBuffer = new StringBuffer();
+
+		Vector datas = new Vector();
+		for (int it=0; it< masterTaxa.getNumTaxa(); it++)
+			taxaStrings[it] = new StringBuffer(100);
+
+		Taxon[][][] components = new Taxon[masterTaxa.getNumTaxa()][project.getNumberTaxas()][];
+		needsComma = false;
+		heterogeneous = false;
+		firstNEXUSpartition = true;
+		previousClass = null;
+		mrBayesBlockBuffer.append(lineEnding + "begin mrbayes;");
+		int totNumChars =  addDataTypes(masterTaxa, dataTypesBuffer, mrBayesBlockBuffer, NEXUSpartitionBuffer, NEXUSCharSetBuffer, datas, 0, dataSuperclass);
+		if (associationTask != null){
+
+			for (int iTaxaBlock = 0; iTaxaBlock < project.getNumberTaxas(); iTaxaBlock++){
+				Taxa aTaxa = project.getTaxa(iTaxaBlock);
+				if (aTaxa != masterTaxa){
+					TaxaAssociation assoc = associationTask.getAssociation(masterTaxa, aTaxa, 0);  //Todo: permit choice
+					if (assoc != null){
+						totNumChars = addDataTypes(assoc.getOtherTaxa(masterTaxa), dataTypesBuffer,mrBayesBlockBuffer,  NEXUSpartitionBuffer, NEXUSCharSetBuffer, datas, totNumChars, dataSuperclass);
+						for (int it = 0; it<masterTaxa.getNumTaxa(); it++){
+							components[it][iTaxaBlock] = assoc.getAssociates(masterTaxa.getTaxon(it));
+						}
+					}
+				}
+			}
+		}
+		mrBayesBlockBuffer.append(lineEnding + "\tpartition matrices = " + datas.size() + ": ");
+		NEXUSpartitionBuffer.append(";");
+		NEXUSpartitionBuffer.append(NEXUSCharSetBuffer);
+		NEXUSpartitionBuffer.append(lineEnding + "END;"+lineEnding);
+
+		for (int i=0; i<datas.size(); i++){
+			if (i != 0)
+				mrBayesBlockBuffer.append(", ");
+			String name = ((CharacterData)datas.elementAt(i)).getName();
+			if (simplifyNames)
+				name = StringUtil.simplifyIfNeededForOutput(name,true);
+			else
+				name=StringUtil.tokenize(name);
+			mrBayesBlockBuffer.append(name);
+		}
+		mrBayesBlockBuffer.append(";");
+		mrBayesBlockBuffer.append(lineEnding +"\tset partition = matrices;");
+
+		//RNA
+		String s = lsetStart(RNAData.class, datas);
+		if (s.length()>0){
+			mrBayesBlockBuffer.append("\t");
+			mrBayesBlockBuffer.append(s);
+			mrBayesBlockBuffer.append(" nst=6 rates=invgamma;");
+		}
+		//DNA
+		s = lsetStart(DNAData.class, datas);
+		if (s != null && s.length()>0){
+			mrBayesBlockBuffer.append("\t");
+			mrBayesBlockBuffer.append(s);
+			mrBayesBlockBuffer.append(" nst=6 rates=invgamma;");
+		}
+
+		int count =0;
+		for (int i=0; i<datas.size(); i++){
+			if (datas.elementAt(i).getClass() == ProteinData.class)  
+				count++;
+		}
+		if (count > 0)
+			mrBayesBlockBuffer.append(lineEnding + "\tprset aamodelpr=mixed;");
+
+
+		mrBayesBlockBuffer.append(lineEnding + "\tunlink statefreq=(all) revmat=(all) shape=(all) pinvar=(all); " + lineEnding + "\tprset applyto=(all) ratepr=variable;" + lineEnding + "\tmcmcp ngen= 10000000 relburnin=yes burninfrac=0.5 printfreq=1000  samplefreq=1000 nchains=4 savebrlens=yes;" + lineEnding + "\tmcmc;" + lineEnding + "end;");
+
+
+		buffer.append("dimensions ntax=" + masterTaxa.getNumTaxa() + " nchar=" + totNumChars + ";" + lineEnding);
+		buffer.append("format datatype = ");
+		if (heterogeneous){
+			if (permitMixed)
+				buffer.append("mixed(" + dataTypesBuffer + ")");
+			else
+				buffer.append("standard");
+		}
+		else if (previousClass == RNAData.class)
+			buffer.append("rna");
+		else if (previousClass == DNAData.class)
+			buffer.append("dna");
+		else if (previousClass == ProteinData.class)
+			buffer.append("protein");
+		else if (previousClass == CategoricalData.class)
+			buffer.append("standard");
+		else if (previousClass == ContinuousData.class)
+			buffer.append("continuous");
+
+		buffer.append(" gap = - missing =?;" + lineEnding + "matrix" + lineEnding);
+		for (int it=0; it< masterTaxa.getNumTaxa(); it++)
+			composeForMasterTaxon(datas, masterTaxa, it, components[it], taxaStrings[it], dataSuperclass);
+		buffer.append(lineEnding);
+		for (int i=0; i< masterTaxa.getNumTaxa(); i++){
+			buffer.append(taxaStrings[i]);
+			buffer.append(lineEnding);
+			taxaStrings[i].setLength(0);
+		}
+		buffer.append(lineEnding + ";" + lineEnding + "end;" + lineEnding);
+		if (labelsBuffer!=null)
+			buffer.append(labelsBuffer);
+		buffer.append(NEXUSpartitionBuffer);
+
+		if (generateMBBlock)
+			buffer.append(mrBayesBlockBuffer);
+		datas.removeAllElements(); 
+	}
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(false, false))
+				return false;
+		Taxa masterTaxa = (Taxa)getProject().chooseTaxa(containerOfModule(), "Select master block of taxa", false);
+		StringBuffer buffer = new StringBuffer(500);
+		StringBuffer mrBayesBlockBuffer = new StringBuffer();
+		fillMatrix(file, masterTaxa, buffer, mrBayesBlockBuffer, CategoricalState.class);
+		
+
+
+		saveExportedFileWithExtension(buffer, arguments, "nex");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Fused Matrix Export (NEXUS)";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports NEXUS files with matrices fused." ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/io/ExportFusedPhylip/ExportFusedPhylip.java b/Source/mesquite/io/ExportFusedPhylip/ExportFusedPhylip.java
new file mode 100644
index 0000000..9a9f400
--- /dev/null
+++ b/Source/mesquite/io/ExportFusedPhylip/ExportFusedPhylip.java
@@ -0,0 +1,181 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.io.ExportFusedPhylip;
+
+import java.awt.Checkbox;
+
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.CharactersManager;
+
+public class ExportFusedPhylip extends InterpretPhylip {
+
+	boolean badImportWarningGiven = false;
+	boolean useTranslationTable = true;
+
+	/*.................................................................................................................*/
+	public void setPhylipState(CharacterData data, int ic, int it, char c){
+	}
+	/*.................................................................................................................*/
+	public boolean initializeExport(Taxa taxa) {  
+		if (useTranslationTable){
+			taxonNamer = new SimpleTaxonNamer();
+			taxonNamer.initialize(taxa);
+		}
+
+		return true;  
+	}
+	/*........................../*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return project.getNumberCharMatrices(CategoricalState.class) > 0;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ProteinState.class || dataClass==DNAState.class || dataClass==CategoricalState.class);
+	}
+	/*.................................................................................................................*
+	public boolean getExportTrees(){
+		return false;
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		return null;  //not needed as can't import
+	}
+	/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+	boolean exportRAxMLModelFile = true;
+	/*.................................................................................................................*/
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		PhylipExporterDialog exportDialog = new PhylipExporterDialog(this,containerOfModule(), "Export Phylip Options", buttonPressed);
+
+		Checkbox excludedCharactersCheckbox = exportDialog.addCheckBox("export excluded characters", localWriteExcludedChars);
+		Checkbox exportTreesCheckbox = exportDialog.addCheckBox("export trees if present", exportTrees);
+		Checkbox exportRAxMLModelFileCheckbox = exportDialog.addCheckBox("save RAxML model file", exportRAxMLModelFile);
+		Checkbox useTranslationTableCheckbox = exportDialog.addCheckBox("use simple taxon names (for RAxML)", useTranslationTable);
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+		if (ok) {
+			localWriteExcludedChars = excludedCharactersCheckbox.getState();
+			exportTrees = exportTreesCheckbox.getState();
+			exportRAxMLModelFile = exportRAxMLModelFileCheckbox.getState();
+			useTranslationTable = useTranslationTableCheckbox.getState();
+			userSpecifiedWriteExcludedChars = true;
+			taxonNameLength = exportDialog.getTaxonNamesLength();
+		}
+		exportDialog.dispose();
+		return ok;
+	}	
+	/*.................................................................................................................*/
+	public boolean exportMultipleMatrices(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getTranslationTablePath(){
+		return getExportedFileDirectory()+IOUtil.translationTableFileName;
+	}
+	/*.................................................................................................................*/
+	public void writeExtraFiles(Taxa taxa){
+		if (useTranslationTable) {
+			String table = ((SimpleTaxonNamer)taxonNamer).getTranslationTable(taxa);
+			if (StringUtil.notEmpty(table)) {
+				String filePath = getTranslationTablePath();
+				if (StringUtil.notEmpty(filePath))
+					MesquiteFile.putFileContents(filePath, table, true);
+			}
+		}
+		if (exportRAxMLModelFile) {
+			StringBuffer sb = new StringBuffer();
+			int numMatrices = getProject().getNumberCharMatricesVisible(CategoricalState.class);
+			CharacterData data;
+			int numCharWrite=0;
+			int totalNumCharWrite=1;
+			if (MesquiteThread.isScripting()){
+			}
+			else {
+
+				for (int im = 0; im<numMatrices; im++) {
+					data = getProject().getCharacterMatrixVisible(taxa, im, CategoricalState.class);
+					if (data==null) continue;
+
+					if (!writeExcludedCharacters){
+						numCharWrite =  data.numCharsCurrentlyIncluded(this.writeOnlySelectedData);
+					} else {
+						numCharWrite =  data.numberSelected(this.writeOnlySelectedData);
+					}
+
+					if (data!=null) {
+						String name = StringUtil.cleanseStringOfFancyChars(data.getName());
+						name = StringUtil.blanksToUnderline(name);
+						if (data instanceof DNAData) 
+							sb.append("DNA, ");
+						else if (data instanceof ProteinData) 
+							sb.append("JTT, ");
+						else if (data instanceof CategoricalData)   //TODO: check if binary or multistate
+							sb.append("MULTI, ");
+						sb.append(name+ " = " + totalNumCharWrite + "-" + (totalNumCharWrite+numCharWrite-1)+StringUtil.lineEnding());
+					}
+					totalNumCharWrite+= numCharWrite;
+				}
+				String filePath = MesquiteFile.saveFileAsDialog("Save RAxML model file");
+				if (StringUtil.blank(sb.toString()) || StringUtil.blank(filePath))
+					return;
+				MesquiteFile.putFileContents(filePath, sb.toString(), true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Fused Matrix Export (Phylip/RAxML)";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports Phylip matrices that consist of multiple matrices, preparing them for RAxML." ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+}
diff --git a/Source/mesquite/io/ExportNEXUSTreeFile/ExportNEXUSTreeFile.java b/Source/mesquite/io/ExportNEXUSTreeFile/ExportNEXUSTreeFile.java
new file mode 100644
index 0000000..2db54b6
--- /dev/null
+++ b/Source/mesquite/io/ExportNEXUSTreeFile/ExportNEXUSTreeFile.java
@@ -0,0 +1,163 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.ExportNEXUSTreeFile;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public class ExportNEXUSTreeFile extends FileInterpreterI {
+
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+ 		return "nex";
+   	 }
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return (project.getNumberOfFileElements(TreeVector.class) > 0) ;
+	}
+	
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false;
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return false;
+	}
+
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+ 	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+ 	public int getVersionOfFirstRelease(){
+		return 201;  
+ 	}
+
+
+/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	boolean includeTaxaBlock = false;
+	String fileName = "untitledTrees.nex";
+	String addendum = "";
+	
+	public boolean getExportOptions(TreeVector trees){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export NEXUS Trees file", buttonPressed);
+		exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		Checkbox itCheckBox = exportDialog.addCheckBox("Include Taxa Block", includeTaxaBlock);
+		exportDialog.addLabel("Addendum: ");
+		
+		addendum = "";
+		
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,16);
+				
+		exportDialog.completeAndShowDialog();
+			
+		boolean ok = (exportDialog.query()==0);
+		
+		includeTaxaBlock = itCheckBox.getState();
+
+		addendum = fsText.getText();
+		exportDialog.dispose();
+		return ok;
+	}	
+	
+	
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+		Listable[] blocks = getProject().getFileElements(TreeVector.class);
+		if (blocks ==null) {
+			showLogWindow(true);
+			logln("WARNING: No trees block is available for export.\n");
+			return false;
+		}
+		TreeVector trees =  (TreeVector)ListDialog.queryList(containerOfModule(), "Choose Tree Block", "Choose tree block for export", null, blocks, 0);
+		TreesManager tm =  (TreesManager)findElementManager(TreeVector.class);
+		if (trees ==null) {
+			return false;
+		}
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		String suggested = fileName;
+		if (file !=null)
+			suggested = file.getFileName();
+		MesquiteFile f;
+		if (!usePrevious){
+			if (!getExportOptions(trees))
+				return false;
+		}
+		String path = getPathForExport(arguments, suggested, dir, fn);
+		if (path != null) {
+			f = MesquiteFile.newFile(dir.getValue(), fn.getValue());
+			if (f !=null){
+				f.openWriting(true);
+				f.writeLine("#NEXUS" + StringUtil.lineEnding());
+				if (includeTaxaBlock)
+					f.writeLine(((TaxaManager)findElementManager(Taxa.class)).getTaxaBlock(trees.getTaxa(), null, file));
+				String block = tm.getTreeBlock( trees, null);
+				if (block != null)
+					f.writeLine(block);
+				if (addendum != null)
+					f.writeLine(addendum);
+				f.closeWriting();
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Export NEXUS Tree File";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Exports NEXUS file with a tree block, and optionally a taxa block." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/ExportPartitionFinderDNA/ExportPartitionFinderDNA.java b/Source/mesquite/io/ExportPartitionFinderDNA/ExportPartitionFinderDNA.java
new file mode 100644
index 0000000..b3f5431
--- /dev/null
+++ b/Source/mesquite/io/ExportPartitionFinderDNA/ExportPartitionFinderDNA.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.ExportPartitionFinderDNA;
+
+import java.awt.Checkbox;
+
+import mesquite.assoc.lib.AssociationSource;
+import mesquite.categ.lib.CategoricalData;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.DNAData;
+import mesquite.categ.lib.DNAState;
+import mesquite.lib.Arguments;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteProject;
+import mesquite.lib.MesquiteThread;
+import mesquite.lib.Parser;
+import mesquite.lib.Taxa;
+import mesquite.lib.TreeVector;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.FileInterpreterI;
+import mesquite.io.lib.*;
+
+
+
+public class ExportPartitionFinderDNA extends ExportPartitionFinder {
+	/*.................................................................................................................*/
+
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatricesVisible(DNAState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return DNAData.class.isAssignableFrom(dataClass);
+	}
+
+	/*.................................................................................................................*
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+	}
+
+
+	public String getProgramName() {
+		return "PartitionFinder";
+	}
+}
diff --git a/Source/mesquite/io/ExportPartitionFinderProtein/ExportPartitionFinderProtein.java b/Source/mesquite/io/ExportPartitionFinderProtein/ExportPartitionFinderProtein.java
new file mode 100644
index 0000000..3533298
--- /dev/null
+++ b/Source/mesquite/io/ExportPartitionFinderProtein/ExportPartitionFinderProtein.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.ExportPartitionFinderProtein;
+
+import java.awt.Checkbox;
+
+import mesquite.assoc.lib.AssociationSource;
+import mesquite.categ.lib.*;
+import mesquite.lib.Arguments;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteProject;
+import mesquite.lib.MesquiteThread;
+import mesquite.lib.Parser;
+import mesquite.lib.Taxa;
+import mesquite.lib.TreeVector;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.FileInterpreterI;
+import mesquite.io.lib.*;
+
+
+
+public class ExportPartitionFinderProtein extends ExportPartitionFinder {
+	/*.................................................................................................................*/
+
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isProtein(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatricesVisible(ProteinState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return ProteinData.class.isAssignableFrom(dataClass);
+	}
+
+	/*.................................................................................................................*
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ProteinState.class, "Select data to export");
+	}
+
+
+	public String getProgramName() {
+		return "PartitionFinderProtein";
+	}
+}
diff --git a/Source/mesquite/io/ExportTreeSourceToNEXUS/ExportTreeSourceToNEXUS.java b/Source/mesquite/io/ExportTreeSourceToNEXUS/ExportTreeSourceToNEXUS.java
new file mode 100644
index 0000000..9c036c9
--- /dev/null
+++ b/Source/mesquite/io/ExportTreeSourceToNEXUS/ExportTreeSourceToNEXUS.java
@@ -0,0 +1,295 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.ExportTreeSourceToNEXUS;
+
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public class ExportTreeSourceToNEXUS extends FileInterpreterI {
+	TreeSource treeSourceTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand tstC;
+	Taxa currentTaxa = null;
+	boolean suspend = false;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return true;
+		//return (project.getNumberOfFileElements(TreeVector.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	boolean includeTaxaBlock = false;
+	String fileName = "untitledTrees.nex";
+	String addendum = "";
+
+	public boolean getExportOptions(TreeVector trees){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export NEXUS Trees file", buttonPressed);
+		exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		Checkbox itCheckBox = exportDialog.addCheckBox("Include Taxa Block", includeTaxaBlock);
+		exportDialog.addLabel("Addendum: ");
+
+		addendum = "";
+
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,16);
+
+		exportDialog.completeAndShowDialog();
+
+		boolean ok = (exportDialog.query()==0);
+
+		includeTaxaBlock = itCheckBox.getState();
+
+		addendum = fsText.getText();
+		exportDialog.dispose();
+		return ok;
+	}	
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		setPreferredTaxa(taxa);
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Tree Source");
+		if (treeSourceTask == null)
+			return;
+	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		storePreferences();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+		}
+	}
+
+	/*.................................................................................................................*/
+
+	public void setPreferredTaxa(Taxa taxa){
+		if (taxa !=currentTaxa) {
+			if (currentTaxa!=null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+
+	}
+
+	/** Get the translation table as a string. */
+	public String getTranslationTable(Taxa taxa) {
+		if (taxa == null)
+			return null;
+		StringBuffer sb = new StringBuffer();
+		sb.append("\tTRANSLATE" + StringUtil.lineEnding());
+		for(int i=0; i<taxa.getNumTaxa(); i++) {
+			if (i>0)
+				sb.append(","+ StringUtil.lineEnding());
+			String thisLabel = "" + (i+1);
+			sb.append("\t\t" + thisLabel + " " + StringUtil.tokenize(taxa.getTaxonName(i))) ;
+		}
+		sb.append(";"+ StringUtil.lineEnding());
+
+		return sb.toString();
+	}
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		Taxa taxa = 	 getProject().chooseTaxa(getModuleWindow(), "Choose taxa block"); 
+		if (taxa==null) 
+			return false;
+
+		if (treeSourceTask==null || taxa!=currentTaxa) {
+			initialize(taxa);
+			if (treeSourceTask==null)
+				return false;
+			treeSourceTask.initialize(currentTaxa);
+		}
+
+
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		String suggested = fileName;
+		if (file !=null) {
+			suggested = file.getFileName();
+			if (StringUtil.getLastItem(suggested, ".").equalsIgnoreCase("NEX")) {
+				suggested = StringUtil.getAllButLastItem(suggested, ".") +".trees.nex";
+			} else if (StringUtil.getLastItem(suggested, ".").equalsIgnoreCase("NXS")) {
+				suggested = StringUtil.getAllButLastItem(suggested, ".") +".trees.nxs";
+			} else
+				suggested = suggested +".trees.nex";
+		}
+
+		MesquiteFile f;
+		if (!usePrevious){
+			if (!getExportOptions(null)) {
+				treeSourceTask=null;
+				return false;
+			}
+		}
+		int numOriginalTrees = treeSourceTask.getNumberOfTrees(taxa);
+		if (!treeSourceTask.hasLimitedTrees(taxa)){
+			numOriginalTrees = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees to export", 100, 1, 99999, true); 
+			if (!MesquiteInteger.isCombinable(numOriginalTrees))
+				return false;
+		}
+		
+		String path = getPathForExport(arguments, suggested, dir, fn);
+		if (path != null) {
+			f = MesquiteFile.newFile(dir.getValue(), fn.getValue());
+			if (f !=null){
+				f.openWriting(true);
+				f.writeLine("#NEXUS" + StringUtil.lineEnding());
+				if (includeTaxaBlock)
+					f.writeLine(((TaxaManager)findElementManager(Taxa.class)).getTaxaBlock(taxa, null, file));
+
+				f.writeLine("begin TREES;" + StringUtil.lineEnding());
+				f.writeLine(getTranslationTable(taxa) + StringUtil.lineEnding());
+				int count=0;
+				String name;
+
+				ProgressIndicator progIndicator = null;
+				if (MesquiteInteger.isCombinable(numOriginalTrees))
+					progIndicator = new ProgressIndicator(getProject(),getName(), "Processing trees", numOriginalTrees, true);
+				else 
+					progIndicator = new ProgressIndicator(getProject(),getName(), "Processing trees", 1, true);
+				if (progIndicator!=null){
+					progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+					progIndicator.setOfferContinueMessageString("Are you sure you want to stop the export?");
+					progIndicator.start();
+				}
+				boolean done = false;
+				for (int i=0; i<numOriginalTrees && !done; i++) {
+					Tree tree =  treeSourceTask.getTree(taxa, i);
+
+					if (progIndicator!=null) {
+						if (progIndicator.isAborted()) {
+							progIndicator.goAway();
+							break;
+						}
+						progIndicator.setText("Tree " + (i+1));
+							if (MesquiteInteger.isCombinable(numOriginalTrees))
+								progIndicator.setCurrentValue(i+1);
+							else
+								progIndicator.spin();
+					}
+					if (tree !=null) {
+						name = tree.getName();
+						if (StringUtil.notEmpty(name))
+							name = StringUtil.tokenize(name);
+						if (StringUtil.blank(name))
+							name = "tree " + (i+1);
+						f.writeLine("\tTREE "+ name +" = "+ tree.writeTree(Tree.BY_NUMBERS));
+						count++;
+						if (count %100 == 0)
+							logln("   Writing tree " + count);
+					}
+					else
+						done = true;
+				}
+				if (progIndicator != null)
+					progIndicator.goAway();
+
+				f.writeLine("end;" + StringUtil.lineEnding());
+
+
+				if (addendum != null)
+					f.writeLine(addendum);
+				f.closeWriting();
+				treeSourceTask=null;
+				logln("    " + count + " trees written");
+				return true;
+			}
+		}
+		treeSourceTask=null;
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Export NEXUS Tree File from Tree Source";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		String s =  "Exports NEXUS file with a tree block, and optionally a taxa block, based upon a source of trees.  " +
+		"One major advantage of this is that it allows a collection of trees to a file without having them all in memory at once. " +
+		"For example, if the Tree Source is \"Transform Trees From Other Source\", and the other source is "+
+		"\"Use Trees from Separate NEXUS file\", then Mesquite will read in a tree from the other NEXUS file, transform the  tree,"+
+		" and wrte it to the file, one at a tme." ;
+		return s;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
diff --git a/Source/mesquite/io/InterpretClustalDNA/InterpretClustalDNA.java b/Source/mesquite/io/InterpretClustalDNA/InterpretClustalDNA.java
new file mode 100644
index 0000000..9d91d13
--- /dev/null
+++ b/Source/mesquite/io/InterpretClustalDNA/InterpretClustalDNA.java
@@ -0,0 +1,58 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretClustalDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  Clustal files ============*/
+
+public class InterpretClustalDNA extends InterpretClustal {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return false;
+		// return getProject().getNumberCharMatrices(DNAState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		 return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Clustal (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports Clustal files that consist of DNA or RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretClustalProtein/InterpretClustalProtein.java b/Source/mesquite/io/InterpretClustalProtein/InterpretClustalProtein.java
new file mode 100644
index 0000000..4851de0
--- /dev/null
+++ b/Source/mesquite/io/InterpretClustalProtein/InterpretClustalProtein.java
@@ -0,0 +1,56 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretClustalProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+/* ============  a file interpreter for Protein  Clustal files ============*/
+
+public class InterpretClustalProtein extends InterpretClustal {
+/*.................................................................................................................*/
+	public boolean canExporEvert() {  
+		 return false;
+		 // return getProject().getNumberCharMatrices(ProteinState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		 return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Clustal (protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports Clustal files that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretFastaDNA/InterpretFastaDNA.java b/Source/mesquite/io/InterpretFastaDNA/InterpretFastaDNA.java
new file mode 100644
index 0000000..0558615
--- /dev/null
+++ b/Source/mesquite/io/InterpretFastaDNA/InterpretFastaDNA.java
@@ -0,0 +1,90 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretFastaDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  Fasta files ============*/
+
+public class InterpretFastaDNA extends InterpretFasta {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(DNAState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+	}
+	
+	boolean badImportWarningGiven = false;
+/*.................................................................................................................*/
+	public void setFastaState(CharacterData data, int ic, int it, char c) { 
+		if (!(data instanceof DNAData))
+			return;
+   		if ((c=='U')||(c=='u')) {
+   			((DNAData)data).setDisplayAsRNA(true);
+   		}
+   		((DNAData)data).setState(ic,it,c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this is a protein data file, please use the FASTA protein interpreter. " + 
+   						"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+	/*.................................................................................................................*/
+	public  String getUnassignedSymbol(){
+		return "N";
+	}
+					
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "FASTA (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports FASTA files that consist of DNA/RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretFastaProtein/InterpretFastaProtein.java b/Source/mesquite/io/InterpretFastaProtein/InterpretFastaProtein.java
new file mode 100644
index 0000000..49355e7
--- /dev/null
+++ b/Source/mesquite/io/InterpretFastaProtein/InterpretFastaProtein.java
@@ -0,0 +1,83 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretFastaProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+/* ============  a file interpreter for Protein  Fasta files ============*/
+
+public class InterpretFastaProtein extends InterpretFasta {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ProteinState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ProteinState.class);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ProteinState.class, "Select data to export");
+	}
+	boolean	badImportWarningGiven = false;
+/*.................................................................................................................*/
+	public void setFastaState(CharacterData data, int ic, int it, char c) { 
+		if (!(data instanceof ProteinData))
+			return;
+		((ProteinData)data).setState(ic, it, c);    // setting state to that specified by character c
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this is a DNA data file, please use the FASTA DNA interpreter. " + 
+   						"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+	/*.................................................................................................................*/
+	public  String getUnassignedSymbol(){
+		return "X";
+	}
+
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "FASTA (protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports FASTA files that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretGenBankDNA/InterpretGenBankDNA.java b/Source/mesquite/io/InterpretGenBankDNA/InterpretGenBankDNA.java
new file mode 100644
index 0000000..5cd5507
--- /dev/null
+++ b/Source/mesquite/io/InterpretGenBankDNA/InterpretGenBankDNA.java
@@ -0,0 +1,66 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretGenBankDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  GenBank files ============*/
+
+public class InterpretGenBankDNA extends InterpretGenBank {
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+   	boolean		badImportWarningGiven = false;
+/*.................................................................................................................*/
+	public void setGenBankState(CharacterData data, int ic, int it, char c) { 
+   		if ((c=='U')||(c=='u')) {
+   			((DNAData)data).setDisplayAsRNA(true);
+   		}
+   		((DNAData)data).setState(ic,it,c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this is a protein data file, please use the Genbank protein interpreter. " + 
+   						"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+							
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "GenBank (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports GenBank files that consist of DNA/RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretGenBankProt/InterpretGenBankProt.java b/Source/mesquite/io/InterpretGenBankProt/InterpretGenBankProt.java
new file mode 100644
index 0000000..d204c44
--- /dev/null
+++ b/Source/mesquite/io/InterpretGenBankProt/InterpretGenBankProt.java
@@ -0,0 +1,62 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretGenBankProt;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  GenBank files ============*/
+
+public class InterpretGenBankProt extends InterpretGenBank {
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+	boolean	badImportWarningGiven = false;
+/*.................................................................................................................*/
+	public void setGenBankState(CharacterData data, int ic, int it, char c) { 
+   		((ProteinData)data).setState(ic,it,c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this is a DNA data file, please use the Genbank DNA interpreter. " + 
+					"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+							
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "GenBank/GenPept (Protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports GenBank/GenPept files that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretNBRFDNA/InterpretNBRFDNA.java b/Source/mesquite/io/InterpretNBRFDNA/InterpretNBRFDNA.java
new file mode 100644
index 0000000..a14ef7a
--- /dev/null
+++ b/Source/mesquite/io/InterpretNBRFDNA/InterpretNBRFDNA.java
@@ -0,0 +1,83 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretNBRFDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  NBRF files ============*/
+
+public class InterpretNBRFDNA extends InterpretNBRF {
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(DNAState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+	}
+   	boolean		badImportWarningGiven = false;
+/*.................................................................................................................*/
+	public void setNBRFState(CharacterData data, int ic, int it, char c) { 
+   		if ((c=='U')||(c=='u')) {
+   			((DNAData)data).setDisplayAsRNA(true);
+   		}
+   		((DNAData)data).setState(ic,it,c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this is a protein data file, please use the NBRF protein interpreter. " + 
+   						"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+							
+/*.................................................................................................................*/
+	public String getLineStart(){  
+		return ">DL; ";
+	}	
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "NBRF/PIR (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports NBRF files that consist of DNA/RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretNBRFProtein/InterpretNBRFProtein.java b/Source/mesquite/io/InterpretNBRFProtein/InterpretNBRFProtein.java
new file mode 100644
index 0000000..6a30cff
--- /dev/null
+++ b/Source/mesquite/io/InterpretNBRFProtein/InterpretNBRFProtein.java
@@ -0,0 +1,82 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretNBRFProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+/* ============  a file interpreter for Protein  NBRF files ============*/
+
+public class InterpretNBRFProtein extends InterpretNBRF {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ProteinState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ProteinState.class);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ProteinState.class, "Select data to export");
+	}
+	
+	boolean	badImportWarningGiven = false;
+
+/*.................................................................................................................*/
+	public void setNBRFState(CharacterData data, int ic, int it, char c) { 
+		((ProteinData)data).setState(ic, it, c);    // setting state to that specified by character c
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+  			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this is a DNA data file, please use the NBRF DNA interpreter. " + 
+					"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+/*.................................................................................................................*/
+	public String getLineStart(){  
+		return ">P1; ";
+	}	
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "NBRF/PIR (protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports NBRF files that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretNonaHennig/InterpretNonaHennig.java b/Source/mesquite/io/InterpretNonaHennig/InterpretNonaHennig.java
new file mode 100644
index 0000000..e7eb4a2
--- /dev/null
+++ b/Source/mesquite/io/InterpretNonaHennig/InterpretNonaHennig.java
@@ -0,0 +1,57 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+28 July 01 (WPM): checked for treeVector == null on export; use getCompatibleFileElements
+ */
+package mesquite.io.InterpretNonaHennig;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.io.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+
+public class InterpretNonaHennig extends InterpretHennig86Base {
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "NONA, Hennig86, PiWe, WinClada";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports NONA/Hennig86/PiWe/WinClada files." ;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+}
+
+
+
+
+
+
diff --git a/Source/mesquite/io/InterpretPOYDNA/InterpretPOYDNA.java b/Source/mesquite/io/InterpretPOYDNA/InterpretPOYDNA.java
new file mode 100644
index 0000000..2ec03d3
--- /dev/null
+++ b/Source/mesquite/io/InterpretPOYDNA/InterpretPOYDNA.java
@@ -0,0 +1,135 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretPOYDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ============  an exporter for POY files ============*/
+
+public class InterpretPOYDNA extends FileInterpreterI {
+
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+ 		return "";
+   	 }
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return (project.getNumberCharMatrices( DNAState.class) > 0) ;
+	}
+	
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==DNAState.class);
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return false;
+	}
+
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		setLineDelimiter(UNIXDELIMITER);
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export NBRF Options", buttonPressed);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+		DNAData data = (DNAData)getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected(), taxa.anySelected()))
+				return false;
+
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+		
+		for (int it = 0; it<numTaxa; it++){
+			if (!writeOnlySelectedTaxa || (taxa.getSelected(it))){
+//				outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)) + "\t");  as in Mesquite 1. 06
+				outputBuffer.append(StringUtil.cleanseStringOfFancyChars(taxa.getTaxonName(it),true,false) +getLineEnding());  // 1. 1: hanged to this in response to Kip Will's posting
+				for (int ic = 0; ic<numChars; ic++) {
+					if (!writeOnlySelectedData || (data.getSelected(ic))){
+						int currentSize = outputBuffer.length();
+						if (!data.isInapplicable(ic,it)) {
+							data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+						}
+						if (outputBuffer.length()-currentSize>1) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return false;
+						}
+					}
+				}
+				outputBuffer.append(getLineEnding()+getLineEnding());
+			}
+		}
+		
+		saveExportedFileWithExtension(outputBuffer, arguments, "poy");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "POY  (DNA/RNA)";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Exports POY files of DNA/RNA sequence data." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretPhylipCat/InterpretPhylipCat.java b/Source/mesquite/io/InterpretPhylipCat/InterpretPhylipCat.java
new file mode 100644
index 0000000..469182d
--- /dev/null
+++ b/Source/mesquite/io/InterpretPhylipCat/InterpretPhylipCat.java
@@ -0,0 +1,103 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretPhylipCat;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for Categorical Phylip files ============*/
+
+public class InterpretPhylipCat extends InterpretPhylip {
+/*.................................................................................................................*/
+	public boolean getInterleaved(){
+		return false;
+	}	
+/*.................................................................................................................*/
+	public void setPhylipState(CharacterData data, int ic, int it, char c){
+		if ((c=='P')||(c=='p')||(c=='B')||(c=='b'))
+			((CategoricalData)data).setState(ic, it, CategoricalState.makeSet(0,1));
+		else
+			((CategoricalData)data).setState(ic, it, c);
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(CategoricalState.class) > project.getNumberCharMatrices(MolecularState.class);  //must be some categorical, and not all molecular
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, CategoricalData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		outputBuffer.append(statesToStringPolyChar((CategoricalData)data, ic, it,'P'));
+	}
+	/*..........................................  CategoricalData  ..................................................*/
+   	/** returns string describing the state(s) of character ic in taxon it.  Uses default symbols, and uses
+   		polyChar for polymorphic cells and missing for uncertainty. 
+   		USED BY PHYLIP EXPORT*/
+	public String statesToStringPolyChar(CategoricalData data, int ic,int it, char polyChar){
+		long s =data.getState(ic, it); //[ic][it];
+		String stateString="";
+		if (s==CategoricalState.inapplicable) 
+			return stateString+data.getInapplicableSymbol();
+		else if (s==CategoricalState.unassigned) 
+			return stateString+data.getUnassignedSymbol(); 
+		else if (CategoricalState.cardinality(s)>1) {
+			if (CategoricalState.isUncertain(s))
+				return stateString+data.getUnassignedSymbol(); 
+			else
+				return stateString+polyChar; 
+		}
+		else
+			return stateString+data.getDefaultStateSymbol(CategoricalState.minimum(s));
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		CharacterData dataToExport = getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+		if (dataToExport == null)
+			return null;
+		if (((CategoricalData)dataToExport).getMaxState()>2) {
+			AlertDialog.notice(containerOfModule(), "Can't export", "This matrix has some characters with states greater than 1, and thus it cannot be exported in Phylip categorical format.");
+			return null;
+		}
+		else
+			return dataToExport;
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Phylip (categorical data)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports Phylip matrices that consist of basic categorical data with just two states. Exported data will consist of default symbols (0 and 1)." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretPhylipDNA/InterpretPhylipDNA.java b/Source/mesquite/io/InterpretPhylipDNA/InterpretPhylipDNA.java
new file mode 100644
index 0000000..b4d15a4
--- /dev/null
+++ b/Source/mesquite/io/InterpretPhylipDNA/InterpretPhylipDNA.java
@@ -0,0 +1,93 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretPhylipDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  Phylip files ============*/
+
+public class InterpretPhylipDNA extends InterpretPhylip {
+/*.................................................................................................................*/
+	boolean badImportWarningGiven = false;
+	public void setPhylipState(CharacterData data, int ic, int it, char c){
+		((CategoricalData)data).setState(ic, it, c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this is a protein data file, please use the Phylip protein interpreter. " + 
+   						"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(DNAState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==DNAState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+/*.................................................................................................................*/
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		PhylipExporterDialog exportDialog = new PhylipExporterDialog(this,containerOfModule(), "Export Phylip Options", buttonPressed);
+		
+		Checkbox interleavedCheckBox = exportDialog.addCheckBox("interleave matrix", exportInterleaved);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportInterleaved = interleavedCheckBox.getState();
+		taxonNameLength = exportDialog.getTaxonNamesLength();
+		exportDialog.dispose();
+		return ok;
+	}	
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Phylip (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports Phylip matrices that consist of DNA/RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretPhylipProtein/InterpretPhylipProtein.java b/Source/mesquite/io/InterpretPhylipProtein/InterpretPhylipProtein.java
new file mode 100644
index 0000000..8872a0a
--- /dev/null
+++ b/Source/mesquite/io/InterpretPhylipProtein/InterpretPhylipProtein.java
@@ -0,0 +1,95 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretPhylipProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for protein Phylip files ============*/
+
+public class InterpretPhylipProtein extends InterpretPhylip {
+	
+		boolean badImportWarningGiven = false;
+
+/*.................................................................................................................*/
+	public void setPhylipState(CharacterData data, int ic, int it, char c){
+		((CategoricalData)data).setState(ic, it, c);
+   		if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+   			data.badImport = true;
+			MesquiteTrunk.errorReportedDuringRun = true;
+			if (!badImportWarningGiven)
+   				discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this is a DNA data file, please use the Phylip DNA interpreter. " + 
+					"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+   			badImportWarningGiven = true;
+   		}
+	}
+/*........................../*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ProteinState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+/*.................................................................................................................*/
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		PhylipExporterDialog exportDialog = new PhylipExporterDialog(this,containerOfModule(), "Export Phylip Options", buttonPressed);
+		
+		Checkbox interleavedCheckBox = exportDialog.addCheckBox("interleave matrix", exportInterleaved);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportInterleaved = interleavedCheckBox.getState();
+		taxonNameLength = exportDialog.getTaxonNamesLength();
+		exportDialog.dispose();
+		return ok;
+	}	
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ProteinState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Phylip (protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports Phylip matrices that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretPhylipTreesBasic/InterpretPhylipTreesBasic.java b/Source/mesquite/io/InterpretPhylipTreesBasic/InterpretPhylipTreesBasic.java
new file mode 100644
index 0000000..37b2e86
--- /dev/null
+++ b/Source/mesquite/io/InterpretPhylipTreesBasic/InterpretPhylipTreesBasic.java
@@ -0,0 +1,53 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretPhylipTreesBasic;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for Phylip trees ============*/
+
+public class InterpretPhylipTreesBasic extends InterpretPhylipTrees {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Phylip (trees)";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports Phylip trees." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+}
+	
+
diff --git a/Source/mesquite/io/InterpretSimpleCat/InterpretSimpleCat.java b/Source/mesquite/io/InterpretSimpleCat/InterpretSimpleCat.java
new file mode 100644
index 0000000..98c72b8
--- /dev/null
+++ b/Source/mesquite/io/InterpretSimpleCat/InterpretSimpleCat.java
@@ -0,0 +1,64 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretSimpleCat;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for Categorical Simple files ============*/
+
+public class InterpretSimpleCat extends InterpretSimple {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(CategoricalState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+	/*.................................................................................................................*/
+	public  boolean isCategorical (){
+		return true;
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, CategoricalData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simple (categorical data)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple matrices that consist of basic categorical data. Exported data will consist of default symbols (0, 1, 2, ...)." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretSimpleCont/InterpretSimpleCont.java b/Source/mesquite/io/InterpretSimpleCont/InterpretSimpleCont.java
new file mode 100644
index 0000000..0bb91c5
--- /dev/null
+++ b/Source/mesquite/io/InterpretSimpleCont/InterpretSimpleCont.java
@@ -0,0 +1,71 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretSimpleCont;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for Categorical Simple files ============*/
+
+public class InterpretSimpleCont extends InterpretSimple {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ContinuousState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ContinuousState.class);
+	}
+	/*.................................................................................................................*/
+	public  boolean isCategorical (){
+		return false;
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ContinuousData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ContinuousState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simple (continuous data)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple matrices that consist of basic continuous data." ;
+   	 }
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+}
+	
+
diff --git a/Source/mesquite/io/InterpretSimpleDNA/InterpretSimpleDNA.java b/Source/mesquite/io/InterpretSimpleDNA/InterpretSimpleDNA.java
new file mode 100644
index 0000000..bda4d5e
--- /dev/null
+++ b/Source/mesquite/io/InterpretSimpleDNA/InterpretSimpleDNA.java
@@ -0,0 +1,74 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretSimpleDNA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for DNA/RNA  Simple files ============*/
+
+public class InterpretSimpleDNA extends InterpretSimple {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(DNAState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+	/*.................................................................................................................*/
+	public  boolean isCategorical (){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		if (dataClass==null) return false;
+		return ((DNAState.class).isAssignableFrom(dataClass)); 
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, DNAState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simple (DNA/RNA)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple matrices that consist of DNA/RNA sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretSimpleGeog/InterpretSimpleGeog.java b/Source/mesquite/io/InterpretSimpleGeog/InterpretSimpleGeog.java
new file mode 100644
index 0000000..890c95c
--- /dev/null
+++ b/Source/mesquite/io/InterpretSimpleGeog/InterpretSimpleGeog.java
@@ -0,0 +1,71 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretSimpleGeog;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for Categorical Simple files ============*/
+
+public class InterpretSimpleGeog extends InterpretSimple {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(GeographicState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==GeographicState.class);
+	}
+	/*.................................................................................................................*/
+	public  boolean isCategorical (){
+		return false;
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, "Geographic Data");  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, GeographicState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simple (Geographic data)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple matrices that consist of basic geographic  data. The first character must be the latitude, and the second character the longitude." ;
+   	 }
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+}
+	
+
diff --git a/Source/mesquite/io/InterpretSimpleProtein/InterpretSimpleProtein.java b/Source/mesquite/io/InterpretSimpleProtein/InterpretSimpleProtein.java
new file mode 100644
index 0000000..e8ed40d
--- /dev/null
+++ b/Source/mesquite/io/InterpretSimpleProtein/InterpretSimpleProtein.java
@@ -0,0 +1,68 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretSimpleProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for protein  Simple files ============*/
+
+public class InterpretSimpleProtein extends InterpretSimple {
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ProteinState.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ProteinState.class);
+	}
+	/*.................................................................................................................*/
+	public  boolean isCategorical (){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return (dataClass==ProteinState.class);
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+	}
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return getProject().chooseData(containerOfModule(), file, null, ProteinState.class, "Select data to export");
+	}
+/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simple (protein)";
+   	 }
+/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple matrices that consist of amino acid sequence data." ;
+   	 }
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/InterpretTNT/InterpretTNT.java b/Source/mesquite/io/InterpretTNT/InterpretTNT.java
new file mode 100644
index 0000000..b5ec376
--- /dev/null
+++ b/Source/mesquite/io/InterpretTNT/InterpretTNT.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretTNT;
+
+import mesquite.io.lib.*;
+
+public class InterpretTNT extends InterpretHennig86Base {
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "TNT";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports TNT files." ;
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "tnt";
+	}
+	/*.................................................................................................................*/
+	public boolean isTNT() {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean additiveIsDefault() {  
+		return false;
+	}
+
+
+}
+
+
+
+
diff --git a/Source/mesquite/io/InterpretTabbedCat/InterpretTabbedCat.java b/Source/mesquite/io/InterpretTabbedCat/InterpretTabbedCat.java
new file mode 100644
index 0000000..22cd4bb
--- /dev/null
+++ b/Source/mesquite/io/InterpretTabbedCat/InterpretTabbedCat.java
@@ -0,0 +1,167 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.InterpretTabbedCat;
+/*~~  */
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ============  a file interpreter for tabbed continuous files ============*/
+
+public class InterpretTabbedCat extends FileInterpreterI {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return false; //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return false; //project.getNumberCharMatrices(CategoricalState.class) > 0; //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false; //(dataClass==CategoricalState.class);
+	}
+	boolean firstLineAreCharacterNames = false;
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+	public void getImportOptions(boolean fuse){
+		firstLineAreCharacterNames = AlertDialog.query(containerOfModule(), "Import", "Does the first line of the file contain character names?", "Yes", "No", 1);  //post-1.03
+	}
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			boolean abort = false;
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+
+			Taxa taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CharacterData data = charTask.newCharacterData(taxa, 0,CategoricalData.DATATYPENAME);
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			data.addToFile(file, getProject(), null);
+
+			int numTaxa = 0;
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+
+			String token;
+
+			//boolean firstLineAreCharacterNames = MesquiteBoolean.yesNoQuery(containerOfModule(), "Does the first line of the file contain character names?");  //post-1.03
+
+			if (firstLineAreCharacterNames) {
+				StringTokenizer st = new StringTokenizer(line, "\t", true);
+				int ic = 0;
+				if (st.hasMoreTokens()){
+					String sc = st.nextToken();  //first tab, ignore
+					while (st.hasMoreTokens()) {
+						sc = st.nextToken();  //get next token, hopefully character name
+						if ("\t".equals(sc)) //no char name; this is tab for next character
+							ic++;
+						else { //sc isn't tab; is name of ic'th character
+							if (data.getNumChars() <= ic) {
+								data.addParts(data.getNumChars()-1, 1);   // add a character if needed
+							}
+							data.setCharacterName(ic, sc);
+							if (st.hasMoreTokens())
+								sc = st.nextToken();  //this should be a tab
+							ic++;
+
+						}
+					}
+				}
+				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+
+			while (!StringUtil.blank(line)&& !abort) {
+				StringTokenizer st = new StringTokenizer(line, "\t", false);
+				if (st.hasMoreTokens()){
+					parser.setString(line);
+					String taxonName = st.nextToken();
+					taxa.addTaxa(numTaxa-1, 1, true);
+					Taxon t = taxa.getTaxon(numTaxa);
+					if (t!=null) {
+						t.setName(taxonName);
+						progIndicator.setText("Reading taxon: "+taxonName);
+						int ic = 0;
+						while (st.hasMoreTokens()) {
+							parser.setString(st.nextToken());
+							if (data.getNumChars() <= ic) {
+								data.addParts(data.getNumChars()-1, 1);   // add a character if needed
+							}
+							data.setState(ic, numTaxa, parser, true, null);
+							ic += 1;
+						}
+					}
+					numTaxa++;
+				}
+				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+
+	/** exports data to a file.*/
+	public boolean exportFile(MesquiteFile file, String arguments){
+		return false;
+	}
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Tab-delimited categorical data file";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports simple tab-delimited files of categorical data." ;
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/io/InterpretTabbedConts/InterpretTabbedConts.java b/Source/mesquite/io/InterpretTabbedConts/InterpretTabbedConts.java
new file mode 100644
index 0000000..c798254
--- /dev/null
+++ b/Source/mesquite/io/InterpretTabbedConts/InterpretTabbedConts.java
@@ -0,0 +1,212 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.InterpretTabbedConts;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+/* ============  a file interpreter for tabbed continuous files ============*/
+
+public class InterpretTabbedConts extends FileInterpreterI {
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true; //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(ContinuousState.class) > 0; //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==ContinuousState.class);
+	}
+	boolean firstLineAreCharacterNames = false;
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return true;
+	}
+	public void getImportOptions(boolean fuse){
+		firstLineAreCharacterNames = AlertDialog.query(containerOfModule(), "Import", "Does the first line of the file contain character names?", "Yes", "No", 1);  //post-1.03
+	}
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			boolean abort = false;
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			 CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+			
+			Taxa taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CharacterData data = charTask.newCharacterData(taxa, 0, ContinuousData.DATATYPENAME);
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			data.addToFile(file, getProject(), null);
+			
+			int numTaxa = 0;
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+			
+			String token;
+			
+			//boolean firstLineAreCharacterNames = MesquiteBoolean.yesNoQuery(containerOfModule(), "Does the first line of the file contain character names?");  //post-1.03
+			
+			if (firstLineAreCharacterNames) {
+				StringTokenizer st = new StringTokenizer(line, "\t", true);
+				int ic = 0;
+				if (st.hasMoreTokens()){
+					String sc = st.nextToken();  //first tab, ignore
+					while (st.hasMoreTokens()) {
+						sc = st.nextToken();  //get next token, hopefully character name
+						if ("\t".equals(sc)) //no char name; this is tab for next character
+							; //ic++;
+						else { //sc isn't tab; is name of ic'th character
+								if (data.getNumChars() <= ic) {
+									data.addParts(data.getNumChars()-1, 1);   // add a character if needed
+								}
+								data.setCharacterName(ic, sc);
+								if (st.hasMoreTokens())
+									sc = st.nextToken();  //this should be a tab
+								ic++;
+
+						}
+					}
+     				}
+     				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			
+			while (!StringUtil.blank(line)&& !abort) {
+				parser.setString(line);
+
+				token = parser.getRemainingUntilChar('\t');
+				
+//				token = parser.getNextToken();  changed post 2. 75
+				taxa.addTaxa(numTaxa-1, 1, true);
+				Taxon t = taxa.getTaxon(numTaxa);
+				if (t!=null) {
+					t.setName(token);
+					progIndicator.setText("Reading taxon: "+token);
+					int ic = 0;
+					while (parser.getPosition()<line.length()) {
+						if (data.getNumChars() <= ic) {
+							data.addParts(data.getNumChars()-1, 1);   // add a character if needed
+						}
+						data.setState(ic, numTaxa, parser, false, null);
+						ic += 1;
+					}
+				}
+				numTaxa++;
+				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+	
+
+
+/* ============================  exporting ============================*/
+	boolean includeGaps = false;
+	/*.................................................................................................................*/
+	
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export Tabbed Continuous Options", buttonPressed);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		ContinuousData data = (ContinuousData)getProject().chooseData(containerOfModule(), file, null, ContinuousState.class, "Select data to export");
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected(), taxa.anySelected()))
+				return false;
+
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+		
+		for (int it = 0; it<numTaxa; it++){
+			if (!writeOnlySelectedTaxa || (taxa.getSelected(it))){
+				outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)));
+				for (int ic = 0; ic<numChars; ic++) {
+					if (!writeOnlySelectedData || (data.getSelected(ic))){
+						outputBuffer.append(ParseUtil.tokenize("\t"));
+						data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+					}
+				}
+				outputBuffer.append(getLineEnding());
+			}
+		}
+		
+		saveExportedFileWithExtension(outputBuffer, arguments, "txt");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tab-delimited continuous data file";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports simple tab-delimited files of continuous data." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/aIOIntro/aIOIntro.java b/Source/mesquite/io/aIOIntro/aIOIntro.java
new file mode 100644
index 0000000..146de26
--- /dev/null
+++ b/Source/mesquite/io/aIOIntro/aIOIntro.java
@@ -0,0 +1,70 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.aIOIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aIOIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aIOIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides file import/export utilities.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Import and Export Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Import and Export Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, D.R. & W.P. Maddison. 2006.  Import-export package for Mesquite, version 1.1.";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "1.11";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "David R. Maddison and Wayne P. Maddison";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/io/explanation.txt b/Source/mesquite/io/explanation.txt
new file mode 100644
index 0000000..319a472
--- /dev/null
+++ b/Source/mesquite/io/explanation.txt
@@ -0,0 +1,2 @@
+File Format Translation Package
+Imports data from and exports data to various file formats.
diff --git a/Source/mesquite/io/lib/ExportPartitionFinder.java b/Source/mesquite/io/lib/ExportPartitionFinder.java
new file mode 100644
index 0000000..c6e73b9
--- /dev/null
+++ b/Source/mesquite/io/lib/ExportPartitionFinder.java
@@ -0,0 +1,408 @@
+package mesquite.io.lib;
+
+import java.awt.Checkbox;
+
+import mesquite.assoc.lib.AssociationSource;
+import mesquite.categ.lib.CategoricalData;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.DNAData;
+import mesquite.categ.lib.DNAState;
+import mesquite.lib.Arguments;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.IntegerArray;
+import mesquite.lib.Listable;
+import mesquite.lib.ListableVector;
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteProject;
+import mesquite.lib.MesquiteThread;
+import mesquite.lib.NumberArray;
+import mesquite.lib.Parser;
+import mesquite.lib.StringUtil;
+import mesquite.lib.Taxa;
+import mesquite.lib.Taxon;
+import mesquite.lib.TaxonNamer;
+import mesquite.lib.TreeVector;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterPartition;
+import mesquite.lib.characters.CharacterStates;
+import mesquite.lib.characters.CharactersGroup;
+import mesquite.lib.characters.CodonPositionsSet;
+import mesquite.lib.duties.FileInterpreterI;
+import mesquite.io.lib.*;
+
+
+
+public abstract class ExportPartitionFinder extends FileInterpreterI {
+	
+	protected int taxonNameLength = 500;
+
+	public boolean branchesLinked;
+	public boolean separateCodPos;
+	public String models;
+	public int modelSelection;
+	public int schemes;
+	
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true; 
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "phy";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean isProtein() {  
+		return false;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatricesVisible(CategoricalState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return CategoricalData.class.isAssignableFrom(dataClass);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+	/*.................................................................................................................*/
+	public abstract CharacterData findDataToExport(MesquiteFile file, String arguments);
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+	protected TaxonNamer taxonNamer = null;
+
+	public void setTaxonNamer(TaxonNamer namer) {
+		this.taxonNamer = namer;
+	}
+
+	public static final int AIC = 0;
+	public static final int AICc = 1;
+	public static final int BIC = 2;
+	
+	public static final int ALL = 0;
+	public static final int GREEDY = 1;
+	public static final int RCLUSTER = 2;
+	public static final int HCLUSTER = 3;
+	
+	/*.................................................................................................................*/
+	boolean hasSomeCodPos(Listable[] listArray, Object obj, NumberArray numberArray){
+		for (int i=0; i<listArray.length && i<numberArray.getNumParts(); i++) {
+			if (listArray[i]==obj && (numberArray.getInt(i)>=1 && numberArray.getInt(i)<=3)) {
+				return true;
+			}
+
+		}
+		return false;
+	}
+	boolean hasSomeCodPos(NumberArray numberArray){
+		for (int i=0;  i<numberArray.getNumParts(); i++) {
+			if ((numberArray.getInt(i)>=1 && numberArray.getInt(i)<=3)) {
+				return true;
+			}
+
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getPartitionList(CharacterData data, CharacterPartition charPartition, boolean separateCodePos){
+		boolean subdivideByCodPos = false;
+		CodonPositionsSet codPosSet=null;
+		if (separateCodePos && data instanceof DNAData) {
+			codPosSet = (CodonPositionsSet)data.getCurrentSpecsSet(CodonPositionsSet.class);
+			if (codPosSet!=null)
+				subdivideByCodPos=true;
+		}
+
+		StringBuffer sb = new StringBuffer();
+		if (charPartition == null){
+			boolean hasCodPos = subdivideByCodPos && hasSomeCodPos(codPosSet.getNumberArray());
+			if (!separateCodePos || !hasCodPos)
+				return null;
+			String s = "";
+			String q = IntegerArray.getListOfMatches(codPosSet.getNumberArray(), 0,1);  //noncoding
+			if (q != null) {
+				sb.append(s+"nonCoding" + " = ");
+				sb.append(q + ";\n");
+			}
+			for (int codpos = 1; codpos<=3; codpos++) {
+				q = IntegerArray.getListOfMatches(codPosSet.getNumberArray(), codpos,1);
+				if (q != null) {
+					sb.append(s+"pos"+codpos + " = ");
+					sb.append(q + ";\n");
+				}
+			}
+		}
+		else {
+		CharactersGroup[] parts = charPartition.getGroups();
+		if (parts!=null)
+			for (int i=0; i<parts.length; i++) {
+				String s = parts[i].getName();
+				s = StringUtil.cleanseStringOfFancyChars(s, false, true);
+				s = StringUtil.blanksToUnderline(s);
+				String q = null;
+				Listable[] partition = (Listable[])charPartition.getProperties();
+				if (!writeExcludedCharacters)
+					partition = data.removeExcludedFromListable(partition);
+				boolean hasCodPos = subdivideByCodPos && hasSomeCodPos(partition, parts[i], codPosSet.getNumberArray());
+
+				if (subdivideByCodPos && hasCodPos) {
+					q = ListableVector.getListOfMatches(partition, parts[i], codPosSet.getNumberArray(), 0,1, true);  //noncoding
+					if (q != null) {
+						sb.append(s+"_nonCoding" + " = ");
+						sb.append(q + ";\n");
+					}
+					for (int codpos = 1; codpos<=3; codpos++) {
+						q = ListableVector.getListOfMatches(partition, parts[i], codPosSet.getNumberArray(), codpos,1, true);
+						if (q != null) {
+							sb.append(s+"_pos"+codpos + " = ");
+							sb.append(q + ";\n");
+						}
+					}
+				}
+				else {
+					q = ListableVector.getListOfMatches(partition, parts[i], 1, false);
+					if (q != null) {
+						sb.append(s + " = ");
+						sb.append(q + ";\n");
+					}
+				}
+			}
+		}
+		return sb.toString();
+	}
+
+	/*.................................................................................................................*/
+	public String getPartitionFinderCFGText(CharacterData data, CharacterPartition partition, String fileName){
+		StringBuffer sb = new StringBuffer();
+
+		sb.append("## ALIGNMENT FILE ##\n");
+		sb.append("alignment = "+ fileName+";\n\n");
+
+		sb.append("## BRANCHLENGTHS: linked | unlinked ##\n");
+		if (branchesLinked)
+			sb.append("branchlengths = linked;\n\n");
+		else
+			sb.append("branchlengths = unlinked;\n\n");
+
+		if (isProtein())
+			sb.append("## MODELS OF EVOLUTION for PartitionFinderProtein: all_protein | <list> ##\n");
+		else 
+			sb.append("## MODELS OF EVOLUTION for PartitionFinder: all | raxml | mrbayes | beast | <list> ##\n");
+		sb.append("models = "+ models+";\n\n");
+
+		sb.append("## MODEL SELECTION: AIC | AICc | BIC ##\n");
+		switch (modelSelection) {
+		case AIC: 
+			sb.append("model_selection = AIC;\n\n");
+			break;
+		case AICc: 
+			sb.append("model_selection = AICc;\n\n");
+			break;
+		case BIC: 
+			sb.append("model_selection = BIC;\n\n");
+			break;
+		default:
+			sb.append("model_selection = BIC;\n\n");
+			break;
+		}
+
+		sb.append("## DATA BLOCKS ##\n");
+		sb.append("[data_blocks]\n");
+		String s = getPartitionList(data, partition, separateCodPos);
+		sb.append(s);
+		sb.append("\n");
+
+
+		sb.append("## SCHEMES, search: all | greedy | rcluster | hcluster | user ##\n");
+		sb.append("[schemes]\n");
+		switch (schemes) {
+		case ALL: 
+			sb.append("search = all;\n\n");
+			break;
+		case GREEDY: 
+			sb.append("search = greedy;\n\n");
+			break;
+		case RCLUSTER: 
+			sb.append("search = rcluster;\n\n");
+			break;
+		case HCLUSTER: 
+			sb.append("search = hcluster;\n\n");
+			break;
+		default:
+			sb.append("search = greedy;\n\n");
+			break;
+		}
+
+
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+	}
+	/*.................................................................................................................*/
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		PartitionFinderDialog exportDialog = new PartitionFinderDialog(this,containerOfModule(), "Export PartitionFinder Options", buttonPressed,isProtein());
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportDialog.dispose();
+		models = exportDialog.getModels();
+		branchesLinked = exportDialog.getLinked();
+		separateCodPos = exportDialog.getSeparateCodPos();
+		modelSelection = exportDialog.getModelSelection();
+		schemes = exportDialog.getScheme();
+
+		
+		
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+	public void exportBlock(Taxa taxa, CharacterData data, StringBuffer outputBuffer, int startChar, int endChar) { 
+		int numTaxa = taxa.getNumTaxa();
+		int maxNameLength = taxa.getLongestTaxonNameLength()+1;
+		int numChars = data.getNumChars();
+		int counter;
+		String pad = "          ";
+		while (pad.length() < maxNameLength)
+			pad += "  ";
+
+		for (int it = 0; it<numTaxa; it++){
+			if ((!writeOnlySelectedTaxa || taxa.getSelected(it)) && (writeTaxaWithAllMissing || data.hasDataForTaxon(it))){
+				if (startChar==0) {   // first block
+					String name = "";
+					if (taxonNamer!=null)
+						name = taxonNamer.getNameToUse(taxa,it)+pad;
+					else
+						name = (taxa.getTaxonName(it)+ pad);
+					name = name.substring(0,maxNameLength);
+					name = StringUtil.cleanseStringOfFancyChars(name, false, true);
+					name = StringUtil.underlineToBlanks(name);
+					name = StringUtil.blanksToUnderline(StringUtil.stripTrailingWhitespace(name));
+
+					outputBuffer.append(name);
+					//	if (taxonNameLength>name.length())
+					for (int i=0;i<maxNameLength-name.length()+1; i++)
+						outputBuffer.append(" ");
+				}
+				//outputBuffer.append(" ");
+				counter = startChar;
+				for (int ic = startChar; ic<numChars; ic++) {
+					if ((!writeOnlySelectedData || (data.getSelected(ic))) && (writeExcludedCharacters || data.isCurrentlyIncluded(ic))){
+						int currentSize = outputBuffer.length();
+						appendPhylipStateToBuffer(data, ic, it, outputBuffer);
+						if (outputBuffer.length()-currentSize>1) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return;
+						}
+						counter++;
+						if (counter>endChar)
+							break;
+					}
+				}
+				outputBuffer.append(getLineEnding());
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		writeTaxaWithAllMissing = false;
+		
+		CharacterData data = findDataToExport(file, arguments);
+		Taxa t = null;
+		if (data != null)
+			t = data.getTaxa();
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		CharacterPartition partition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		Taxa taxa = data.getTaxa();
+		boolean dataAnySelected = false;
+		if (data != null)
+			dataAnySelected =data.anySelected();
+		if (!MesquiteThread.isScripting())
+			if (!getExportOptions(dataAnySelected, taxa.anySelected()))
+				return false;
+		if (partition==null && !separateCodPos) {
+			discreetAlert("The data cannot be exported because partitions (character groups) are not assigned, and use of codon positions is not requested.");
+			return false;
+		}
+
+		int numTaxa = taxa.getNumTaxa();
+
+		int numTaxaWrite;
+		int countTaxa = 0;
+		for (int it = 0; it<numTaxa; it++)
+			if ((!writeOnlySelectedTaxa || taxa.getSelected(it)) && (writeTaxaWithAllMissing || data.hasDataForTaxon(it)))
+				countTaxa++;
+		numTaxaWrite = countTaxa;
+
+		int numChars = 0;
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+
+
+		if (data != null){
+			numChars = data.getNumChars();
+			int numCharWrite = data.numberSelected(this.writeOnlySelectedData); 
+			outputBuffer.append(Integer.toString(numTaxaWrite)+" ");
+			outputBuffer.append(Integer.toString(numCharWrite)+this.getLineEnding());
+			int blockSize=50;
+
+			exportBlock(taxa, data, outputBuffer, 0, numChars);
+		}
+
+		saveExportedFileWithExtension(outputBuffer, arguments, "phy");
+		
+
+		String cfgString = getPartitionFinderCFGText(data, partition, getExportedFileName());
+		String cfgFilePath = getExportedFilePath();
+		cfgFilePath=StringUtil.getAllButLastItem(cfgFilePath, MesquiteFile.fileSeparator)+MesquiteFile.fileSeparator+"partition_finder.cfg";
+		MesquiteFile.putFileContents(cfgFilePath, cfgString, true);
+
+		
+		return true;
+	}
+
+	public String getName() {
+		return "Export for " + getProgramName();
+	}
+	public String getProgramName() {
+		return "PartitionFinder";
+	}
+	public String getExplanation() {
+		return "Exports a .phy file containing your data prepared for " + getProgramName() +" and creates a .cfg file.";
+	}
+}
diff --git a/Source/mesquite/io/lib/IOUtil.java b/Source/mesquite/io/lib/IOUtil.java
new file mode 100644
index 0000000..fbbee10
--- /dev/null
+++ b/Source/mesquite/io/lib/IOUtil.java
@@ -0,0 +1,273 @@
+package mesquite.io.lib;
+
+import mesquite.categ.lib.DNAData;
+import mesquite.categ.lib.MolecularData;
+import mesquite.categ.lib.ProteinData;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterPartition;
+import mesquite.lib.characters.CharacterStates;
+import mesquite.lib.characters.CharactersGroup;
+import mesquite.lib.characters.CodonPositionsSet;
+import mesquite.lib.duties.TreesManager;
+
+public class IOUtil {
+
+	public static String translationTableFileName = "taxonNamesTranslationTable.txt";
+	public static final String RAXMLSCORENAME = "RAxMLScore";
+	public static final String RAXMLFINALSCORENAME = "RAxMLScore (Final Gamma-based)";
+	/*.................................................................................................................*/
+
+	public static String[] getRAxMLRateModels(MesquiteModule mb, CharactersGroup[] parts){
+		if (parts==null || parts.length==0 || parts.length>20)
+			return null;
+		String[] rateModels = new String[parts.length];
+		for (int i=0; i<rateModels.length; i++)
+			rateModels[i] = "JTT";
+
+		if (!MesquiteThread.isScripting()) {
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog dialog = new ExtensibleDialog(mb.containerOfModule(), "Protein Rate Models",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+			dialog.addLabel("Protein Rate Models");
+
+			SingleLineTextField[] modelFields = new SingleLineTextField[parts.length];
+			for (int i=0; i<rateModels.length; i++)
+				modelFields[i] = dialog.addTextField(parts[i].getName()+":", rateModels[i], 20);
+
+			dialog.completeAndShowDialog(true);
+			if (buttonPressed.getValue()==0)  {
+				for (int i=0; i<rateModels.length; i++)
+					rateModels[i] = modelFields[i].getText();
+			}
+			dialog.dispose();
+			if (buttonPressed.getValue()==0)
+				return rateModels;
+			return null;
+		}
+		return rateModels;
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+
+	public static String getMultipleModelRAxMLString(MesquiteModule mb, CharacterData data, boolean partByCodPos){
+		boolean writeCodPosPartition = false;
+		boolean writeStandardPartition = false;
+		CharactersGroup[] parts =null;
+		if (data instanceof DNAData)
+			writeCodPosPartition = ((DNAData)data).someCoding();
+		CharacterPartition characterPartition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		if (characterPartition == null && !writeCodPosPartition)
+			return null;
+		if (characterPartition!=null) {
+			parts = characterPartition.getGroups();
+			writeStandardPartition = parts!=null;
+		}
+
+		if (!writeStandardPartition && !writeCodPosPartition) {
+			return null;
+		}
+		StringBuffer sb = new StringBuffer();
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+
+		String codPosPart = "";
+		boolean molecular = (data instanceof MolecularData);
+		boolean nucleotides = (data instanceof DNAData);
+		boolean protein = (data instanceof ProteinData);
+		String standardPart = "";
+		if (writeStandardPartition) {
+			Listable[] partition = (Listable[])characterPartition.getProperties();
+			partition = data.removeExcludedFromListable(partition);
+			if (nucleotides) {
+				String q;
+				for (int i=0; i<parts.length; i++) {
+					q = ListableVector.getListOfMatches(partition, parts[i], CharacterStates.toExternal(0), true, ",");
+					if (q != null) {
+						if (nucleotides)
+							sb.append("DNA, " + StringUtil.simplifyIfNeededForOutput(data.getName()+"_"+parts[i].getName(), true) + " = " +  q + "\n");
+					}
+				}
+				q = ListableVector.getListOfMatches(partition, null, CharacterStates.toExternal(0), true, ",");
+				if (q != null) {
+					if (nucleotides)
+						sb.append("DNA, " + StringUtil.simplifyIfNeededForOutput(data.getName()+"_unassigned", true) + " = " +  q + "\n");
+				}
+			} else if (protein) {
+				String[] rateModels = getRAxMLRateModels(mb, parts);
+				String q;
+				if (rateModels!=null) {
+					for (int i=0; i<parts.length; i++) {
+						q = ListableVector.getListOfMatches(partition, parts[i], CharacterStates.toExternal(0), true, ",");
+						if (q != null && i<rateModels.length) {
+							sb.append(rateModels[i]+", " + StringUtil.simplifyIfNeededForOutput(data.getName()+"_"+parts[i].getName(), true) + " = " +  q + "\n");
+						}
+					}
+				}
+			} else {  // non molecular
+				for (int i=0; i<parts.length; i++) {
+					String q = ListableVector.getListOfMatches(partition, parts[i], CharacterStates.toExternal(0), true, ",");
+					if (q != null) {
+						if (nucleotides)
+							sb.append("MULTI, " + StringUtil.simplifyIfNeededForOutput(data.getName()+"_"+parts[i].getName(), true) + " = " +  q + "\n");
+					}
+				}
+			} 
+		} else if (writeCodPosPartition && partByCodPos) {//TODO: never accessed because in the only call of this method, partByCodPos is false.
+			//codon positions if nucleotide
+			int numberCharSets = 0;
+			boolean[] include = data.getBooleanArrayOfIncluded();
+			CodonPositionsSet codSet = (CodonPositionsSet)data.getCurrentSpecsSet(CodonPositionsSet.class);
+			for (int iw = 0; iw<4; iw++){
+				String locs = codSet.getListOfMatches(iw,0, include);
+				if (!StringUtil.blank(locs)) {
+					String charSetName = "";
+					if (iw==0) 
+						charSetName = StringUtil.tokenize("nonCoding");
+					else 
+						charSetName = StringUtil.tokenize("codonPos" + iw);			
+					numberCharSets++;
+					sb.append( "DNA, " + StringUtil.simplifyIfNeededForOutput(data.getName()+"_"+charSetName,true) + " = " +  locs + "\n");
+				}
+			}
+			//	String codPos = ((DNAData)data).getCodonsAsNexusCharSets(numberCharSets, charSetList); // equivalent to list
+		}
+
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public static TreeVector readPhylipTrees (MesquiteModule mb, MesquiteProject mf, MesquiteFile file, String line, ProgressIndicator progIndicator, Taxa taxa, boolean permitTaxaBlockEnlarge, TaxonNamer namer, String treeNameBase, boolean addTreesToFile) {
+		Parser treeParser = new Parser();
+		treeParser.setQuoteCharacter((char)0);
+		int numTrees = MesquiteInteger.infinite;
+		if (line != null){
+			treeParser.setString(line); 
+			String token = treeParser.getNextToken();  // numTaxa
+			numTrees = MesquiteInteger.fromString(token);
+		}
+		int iTree = 0;
+		TreeVector trees = null;
+		boolean abort = false;
+		line = file.readNextDarkLine();		
+		while (!StringUtil.blank(line) && !abort && (iTree<numTrees)) {
+			treeParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+
+			if (trees == null) {
+				trees = new TreeVector(taxa);
+				trees.setName("Imported trees");
+			}
+			MesquiteTree t = new MesquiteTree(taxa);
+			t.setPermitTaxaBlockEnlargement(permitTaxaBlockEnlarge);
+			//t.setTreeVector(treeVector);
+			t.readTree(line,namer, null, "():;,[]\'");  //tree reading adjusted to use Newick punctuation rather than NEXUS
+			/*MesquiteInteger pos = new MesquiteInteger(0);
+			treeParser.setString(line);
+			readClade(t, t.getRoot());
+			t.setAsDefined(true);*/
+			t.setName(treeNameBase + (iTree+1));
+			trees.addElement(t, false);
+
+
+			iTree++;
+			line = file.readNextDarkLine();		
+			if (file.getFileAborted())
+				abort = true;
+		}
+		if (trees != null && addTreesToFile)
+			trees.addToFile(file,mf,(TreesManager)mb.findElementManager(TreeVector.class));
+		return trees;
+		
+	}
+
+	/*.................................................................................................................*/
+
+	public static void readRAxMLInfoFile(MesquiteModule mb, String fileContents, boolean verbose, TreeVector trees, DoubleArray finalValues, DoubleArray optimizedValues) {
+		if (finalValues==null) return;
+		Parser parser = new Parser(fileContents);
+		parser.setAllowComments(false);
+		parser.allowComments = false;
+		int count =0;
+
+		String line = parser.getRawNextDarkLine();
+		if (verbose)
+			mb.logln("\nSummary of RAxML Search");
+
+		while (!StringUtil.blank(line) && count < finalValues.getSize()) {
+			if (line.startsWith("Inference[")) {
+				Parser subParser = new Parser();
+				subParser.setString(line);
+				String token = subParser.getFirstToken();
+				while (!StringUtil.blank(token) && ! subParser.atEnd()){
+					if (token.indexOf("likelihood")>=0) {
+						token = subParser.getNextToken();
+						finalValues.setValue(count,-MesquiteDouble.fromString(token));
+						//	finalScore[count].setValue(finalValues[count]);
+						mb.logln("RAxML Run " + (count+1) + " ln L = -" + finalValues.getValue(count));
+					}
+					token = subParser.getNextToken();
+				}
+				count++;
+			}
+			parser.setAllowComments(false);
+			line = parser.getRawNextDarkLine();
+		}
+		
+		count =0;
+
+		if (optimizedValues!=null) {
+			while (!StringUtil.blank(line) && count < optimizedValues.getSize()) {
+				if (line.startsWith("Inference[")) {
+					Parser subParser = new Parser();
+					subParser.setString(line);
+					String token = subParser.getFirstToken();   // should be "Inference"
+					while (!StringUtil.blank(token) && ! subParser.atEnd()){
+						if (token.indexOf("Likelihood")>=0) {
+							token = subParser.getNextToken(); // :
+							token = subParser.getNextToken(); // -
+							optimizedValues.setValue(count,-MesquiteDouble.fromString(token));
+						}
+						token = subParser.getNextToken();
+					}
+					count++;
+				}
+				parser.setAllowComments(false);
+				line = parser.getRawNextDarkLine();
+			}
+		}
+
+
+		double bestScore =MesquiteDouble.unassigned;
+		int bestRun = MesquiteInteger.unassigned;
+		for (int i=0; i<trees.getNumberOfTrees(); i++) {
+			Tree newTree = trees.getTree(i);
+			if (MesquiteDouble.isCombinable(finalValues.getValue(i))){
+				MesquiteDouble s = new MesquiteDouble(-finalValues.getValue(i));
+				s.setName(RAXMLSCORENAME);
+				((Attachable)newTree).attachIfUniqueName(s);
+			}
+			if (MesquiteDouble.isCombinable(optimizedValues.getValue(i))){
+				MesquiteDouble s = new MesquiteDouble(-optimizedValues.getValue(i));
+				s.setName(IOUtil.RAXMLFINALSCORENAME);
+				((Attachable)newTree).attachIfUniqueName(s);
+			}
+
+			if (MesquiteDouble.isCombinable(finalValues.getValue(i)))
+				if (MesquiteDouble.isUnassigned(bestScore)) {
+					bestScore = finalValues.getValue(i);
+					bestRun = i;
+				}
+				else if (bestScore>finalValues.getValue(i)) {
+					bestScore = finalValues.getValue(i);
+					bestRun = i;
+				}
+		}
+		if (MesquiteInteger.isCombinable(bestRun)) {
+			Tree t = trees.getTree(bestRun);
+
+			String newName = t.getName() + " BEST";
+			if (t instanceof AdjustableTree )
+				((AdjustableTree)t).setName(newName);
+		}
+
+	}
+}
diff --git a/Source/mesquite/io/lib/InterpretClustal.java b/Source/mesquite/io/lib/InterpretClustal.java
new file mode 100644
index 0000000..dcb8d81
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretClustal.java
@@ -0,0 +1,198 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ============  a file interpreter for Clustal files ============*/
+
+public abstract class InterpretClustal extends FileInterpreterI {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return false;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+	/*.................................................................................................................*/
+	StringBuffer sb = new StringBuffer(1000);
+	public String skipBlankLines(MesquiteFile file, Parser parser, String line){
+		while ((line!=null) && StringUtil.blank(line,"*.:")) {
+			if (!file.readLine(sb))
+				break; 
+			line = sb.toString();
+		}
+		return line;
+	}
+
+	boolean badImportWarningGiven = false;
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		progIndicator.setTextRefreshInterval(200);
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+
+			Taxa taxa = taxaTask.makeNewTaxa("Taxa", 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CategoricalData data = (CategoricalData)createData(charTask,taxa);
+
+			data.addToFile(file, getProject(), null);
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+
+			boolean firstBlock=true;
+			String token;
+			char c;
+
+			int numTaxa = 0;
+			int it = 0;
+			int startChars=0;
+			int maxChars = 0;
+			int block = 1;
+			int ic = 0;
+			String line = null;
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);   // reads first line
+			file.readLine(sb);   // reads first line of data
+			line = sb.toString();
+			parser.setString(line);
+			line = skipBlankLines(file, parser,line);
+			parser.setString(line);
+
+			boolean abort = false;
+			while (!StringUtil.blank(line) && !abort) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				parser.setPunctuationString("");
+
+				token = parser.getFirstToken();  //taxon Name
+				if (firstBlock) 
+					taxa.addTaxa(numTaxa-1, 1, true);
+				Taxon t = taxa.getTaxon(it);
+
+				if (t!=null) {
+					if (firstBlock)
+						t.setName(token);
+					progIndicator.setText("Reading block " + block + ", taxon: "+token );
+					ic = startChars;
+					while (parser.getPosition()<line.length()) {
+						c=parser.nextDarkChar();
+						if (c=='\0') break;
+						if (data.getNumChars() <= ic) {
+							data.addCharacters(data.getNumChars()-1, 1, false);   // add a character if needed
+						}
+						if (c=='~')
+							data.setState(ic,it,CategoricalState.inapplicable);
+						else
+							data.setState(ic, it, c);    // setting state to that specified by character c
+						if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,it))){
+							data.badImport = true;
+							MesquiteTrunk.errorReportedDuringRun = true;
+							if (!badImportWarningGiven) {
+								if (data instanceof DNAData)
+									discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this file is a protein data file, please use the Clustal protein interpreter. " + 
+									"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+								else
+									discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this file is a DNA data file, please use the Clustal DNA interpreter. " + 
+									"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+							}
+							badImportWarningGiven = true;
+						}
+
+						ic += 1;        					
+					}
+				}
+				if (firstBlock)
+					numTaxa++;
+				if (ic > maxChars)
+					maxChars = ic;
+				it ++;
+				file.readLine(sb);
+				line = sb.toString();		
+
+				if (StringUtil.blank(line,"*.:")) {  // at end of block
+					line = skipBlankLines(file, parser,line);
+					parser.setString(line);
+					firstBlock=false;
+					block++;
+					startChars=maxChars;
+					it = 0;
+				}
+
+				if (file.getFileAborted()) {
+					abort = true;
+
+				}
+			}
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Clustal file";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports Clustal files that consist of molecular sequence data." ;
+	}
+	/*.................................................................................................................*/
+
+
+
+}
+
+
diff --git a/Source/mesquite/io/lib/InterpretFasta.java b/Source/mesquite/io/lib/InterpretFasta.java
new file mode 100644
index 0000000..4292e26
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretFasta.java
@@ -0,0 +1,627 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.ContinuousData;
+
+
+/* ============  a file interpreter for FASTA files ============*/
+/** This is the class for interpreting FASTA files.  It is subclassed to make interpreters specifically for
+DNA and Protein files. */
+public abstract class InterpretFasta extends FileInterpreterI implements ReadFileFromString {
+	StringMatcher nameMatcherTask = null;
+	Class[] acceptedClasses;
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e1 = registerEmployeeNeed(StringMatcher.class, "FASTA file import needs a way to determine if the taxon in a ; choose the one that appropriately determines the sequence names from the sample codes.", "This is activated automatically.");
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		acceptedClasses = new Class[] {ProteinState.class, DNAState.class};
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	public void getImportOptions(boolean fuse){
+		if (fuse) {
+			if (nameMatcherTask==null) 
+				nameMatcherTask = (StringMatcher)hireEmployee(StringMatcher.class,  "Module to determine whether a taxon name in the incoming FASTA file matches that in an existing matrix.");
+			if (nameMatcherTask==null) 
+				return;
+			else {
+				if (!nameMatcherTask.optionsSpecified())
+					if (!MesquiteThread.isScripting())
+						if (!nameMatcherTask.queryOptions())
+							return;
+			}
+		}
+}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return project.getNumberCharMatrices(acceptedClasses) > 0;  //
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		for (int i = 0; i<acceptedClasses.length; i++)
+			if (dataClass==acceptedClasses[i])
+				return true;
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public abstract void setFastaState(CharacterData data, int ic, int it, char c);
+	/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+	/*.................................................................................................................*/
+	//NOTE: it is the responsibility of the caller to notify listeners of taxa and data that taxa & possibly characters have been added!
+	public void readString(CharacterData data, String s, int insertAfterTaxon, String appendToTaxonName) {
+		Taxa taxa = data.getTaxa();
+		//int numTaxa = taxa.getNumTaxa();
+		int newTaxon = insertAfterTaxon+1;
+		Parser parser = new Parser(s);
+		parser.setPunctuationString(">");
+		String line = parser.getRawNextLine();
+		Parser firstLineParser = new Parser(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+		firstLineParser.setPunctuationString(">");
+		String token = firstLineParser.getFirstToken(line); //should be >
+		
+		int numCharToAdd = 10;  // DRM June '14  to increase speed
+		int warnCount = 0;
+		
+		while (!StringUtil.blank(line)) {
+
+			token = firstLineParser.getRemaining();  //taxon Name
+			taxa.addTaxa(newTaxon-1, 1, false);
+			taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED), CharacterData.class, true); //notifying only matrices
+			Taxon t = taxa.getTaxon(newTaxon);
+
+			if (t!=null) {
+				t.setName(token+appendToTaxonName);
+				line = parser.getRemainingUntilChar('>');
+				line=StringUtil.stripWhitespace(line);
+				if (line==null) break;
+				int ic = 0;
+				int added = 0;
+				for (int i=0; i<line.length(); i++) {
+					char c=line.charAt(i);
+					if (c!= '\0') {
+						if (data.getNumChars() <= i) {
+							warnCount++;
+							data.addCharacters(data.getNumChars()-1, numCharToAdd, false);   // add a character if needed
+							data.addInLinked(data.getNumChars()-1, numCharToAdd, false);
+							if (warnCount % 50 ==0)
+								CommandRecord.tick("Importing, character " + ic);
+						
+							added++;
+						}
+						setFastaState(data,ic, newTaxon, c);    // setting state to that specified by character c
+					}
+					ic++;
+				}
+//				data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {data.getNumChars(), added}));
+			}
+			newTaxon++;
+			line = parser.getRawNextLine();
+			firstLineParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+			if (StringUtil.notEmpty(line))
+				token = firstLineParser.getFirstToken(line); //should be >
+		}
+	}
+	
+	
+	public int[] getNewTaxaAdded(){
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void readFileCore(Parser parser, MesquiteFile file, CharacterData data, Taxa taxa, ProgressIndicator progIndicator, String arguments) {
+		readFileCore(parser, file, data, taxa, 0, progIndicator, arguments, true);
+	}
+	public int queryOptionsDuplicate() {
+		String helpString = "If you choose Don't Add, then any incoming sequence with the same name as an existing sequence will be ignored. ";
+		helpString += "If you choose Replace Data, then the incoming sequence will replace any existing sequence for that taxon.  ";
+		helpString += "If you choose Replace If Empty, Otherwise Add, then the incoming sequence will be put into the existing spot for that taxon ONLY if that taxon has no previous data there; if there is already a sequence there, then the incoming sequence will be added as a new taxon. ";
+		helpString += "If you choose Replace If Empty, Otherwise Ignore, then the incoming sequence will be put into the existing spot for that taxon ONLY if that taxon has no previous data there; if there is already a sequence there, then the incoming sequence with the same name as an existing taxon will be ignored. ";
+		helpString+= "If you choose Add As New Taxa then all incoming sequences will be added as new taxa, even if there already exist taxa in the matrix with identical names.";
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(containerOfModule(), "Incoming taxa match existing taxa",buttonPressed);
+		id.addLargeTextLabel("Some of the taxa already in the matrix have the same name as incoming taxa.  Please choose how incoming sequences with the same name as exising taxa will be treated.");
+		if (StringUtil.blank(helpString) && id.isInWizard())
+			helpString = "<h3>" + StringUtil.protectForXML("Incoming taxa match existing taxa") + "</h3>Please choose.";
+		id.appendToHelpString(helpString);
+		
+		
+		
+		RadioButtons radio = id.addRadioButtons(new String[] {"Don't Add", "Replace Data","Replace If Empty, Otherwise Add","Replace If Empty, Otherwise Ignore","Add As New Taxa"},treatmentOfIncomingDuplicates);
+		
+		id.completeAndShowDialog(true);
+		
+		int value = -1;
+		if (buttonPressed.getValue()==0)  {
+			value = radio.getValue();
+			treatmentOfIncomingDuplicates = value;
+		}
+		id.dispose();
+		return value;
+	}
+
+	/*.................................................................................................................*/
+	public void readFileCore(Parser parser, MesquiteFile file, CharacterData data, Taxa taxa, int lastTaxonNumber, ProgressIndicator progIndicator, String arguments, boolean newFile) {
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			Parser subParser = new Parser();
+			long pos = 0;
+
+			StringBuffer sb = new StringBuffer(1000);
+			if (file!=null)
+				file.readLine(sb);
+			else
+				sb.append(parser.getRawNextLine());
+			String line = sb.toString();
+			int taxonNumber = -1;
+
+			boolean abort = false;
+			subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+			subParser.setPunctuationString(">");
+			parser.setPunctuationString(">");
+			String token = subParser.getFirstToken(line); //should be >
+			int numFilledChars = data.getNumChars();
+			boolean added = false;
+			//StringMatcher nameMatcher = null;
+		//	if (MesquiteTrunk.debugMode)
+		//		nameMatcher = (MesquiteStringMatcher)hireNamedEmployee(MesquiteStringMatcher.class, "#PrefixedStringMatcher"); //TEMP
+
+			
+			while (!StringUtil.blank(line) && !abort) {
+
+				//parser.setPunctuationString(null);
+
+				token = subParser.getRemaining();  //taxon Name
+				taxonNumber = taxa.whichTaxonNumber(nameMatcherTask, token, false, false);   // checking to see if a taxon of that name already exists in the file
+
+				if (!hasQueriedAboutSameNameTaxa && taxonNumber >= 0) {
+					if (!MesquiteThread.isScripting()){
+						replaceDataOfTaxonWithSameNameInt = queryOptionsDuplicate();
+					}
+					hasQueriedAboutSameNameTaxa= true;
+				}
+				if (replaceDataOfTaxonWithSameNameInt==STOPIMPORT){
+					abort=true;
+					break;
+				}
+				boolean replace = false;
+				boolean skipThisSequence = false;
+				
+				if (taxonNumber>=0) {   // a taxon number of the same name exists
+					if (replaceDataOfTaxonWithSameNameInt==DONTADD) {
+						skipThisSequence = true;
+
+					}  else if (replaceDataOfTaxonWithSameNameInt==REPLACEDATA) 
+						replace=true;
+					else if (replaceDataOfTaxonWithSameNameInt==REPLACEIFEMPTYOTHERWISEADD && !data.hasDataForTaxon(taxonNumber)) 
+						replace=true;
+					else if (replaceDataOfTaxonWithSameNameInt==REPLACEIFEMPTYOTHERWISEIGNORE) {
+						if (!data.hasDataForTaxon(taxonNumber))   // empty
+							replace=true;
+						else   // not empty, so need to ignore this incoming sequence
+							skipThisSequence = true;
+					}
+				}
+				added=false;
+
+				
+				if (true) {
+					if (replace) {
+						CharacterState cs = data.makeCharacterState(); //so as to get the default state
+						int numChars = data.getNumChars();
+						if (taxonNumber<lastTaxonNumber)
+							for (int ic=0; ic<numChars; ic++)
+								data.setState(ic, taxonNumber, cs);
+						added=false;
+					} else if (!skipThisSequence) {  // adding to end, not replacing an existing one
+						if (getLastNewTaxonFilled()>-1 && getMultiFileImport()) {
+							taxonNumber = getLastNewTaxonFilled()+1;
+							if (taxonNumber>taxa.getNumTaxa())
+								taxonNumber=taxa.getNumTaxa();
+							setLastNewTaxonFilled(taxonNumber);
+							if (data.hasDataForTaxa(taxonNumber, taxonNumber)) {
+								MesquiteMessage.discreetNotifyUser("Warning: InterpretFASTA attempted to overwrite existing data, and so failed.");
+								taxonNumber = -1;
+							}
+						}
+						else 
+							taxonNumber = taxa.getNumTaxa();
+
+
+
+						setLastNewTaxonFilled(taxonNumber);
+
+						if (data.getNumTaxa()<=taxonNumber) {
+							int numTaxaAdded = getTotalFilesToImport();  // we may not need all of those, as some of them might be placed in existing taxa.
+							if (numTaxaAdded<1) numTaxaAdded =1;
+							taxa.addTaxa(taxonNumber-1, numTaxaAdded, false);
+							added=true;
+							if (newFile)
+								data.addTaxa(taxonNumber-1, numTaxaAdded);
+							else {
+								taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED), CharacterData.class, true);
+							}
+						}
+					}
+
+					Taxon t = null;
+
+					if (taxonNumber>=0)
+						t = taxa.getTaxon(taxonNumber);
+
+					if (t!=null) {
+						recordAsNewlyAddedTaxon(taxa,taxonNumber);
+
+						checkMaximumTaxonFilled(taxonNumber);  // record this taxonNumber to see if it is the biggest yet.
+						t.setName(token);
+						if (progIndicator!=null) {
+							progIndicator.setText("Reading taxon " + taxonNumber+": "+token);
+							CommandRecord.tick("Reading taxon " + taxonNumber+": "+token);
+							progIndicator.setCurrentValue(pos);
+						}
+						if (file!=null)
+							line = file.readLine(">");  // pull in sequence up until next >
+						else
+							line = parser.getRemainingUntilChar('>', true);
+						if (line==null) break;
+						subParser.setString(line); 
+						int ic = 0;
+						progIndicator.setSecondaryMessage("Reading character 1");
+
+						while (subParser.getPosition()<line.length()) {
+							char c=subParser.nextDarkChar();
+							if (c!= '\0') {
+								if (data.getNumChars() <= ic) {
+									int numChars = data.getNumChars();
+									int numToAdd = 1;
+									if (numChars>10000) {
+										numToAdd=1000;
+									} else	if (numChars>5000) {
+										numToAdd=500;
+									} else if (numChars>2000) {
+										numToAdd=100;
+									} else if (numChars>200) {
+										numToAdd=10;
+									} 								
+									data.addCharacters(numChars-1, numToAdd, false);   // add characters
+									data.addInLinked(numChars-1, numToAdd, false);
+								}
+								if (!skipThisSequence)
+									setFastaState(data,ic, taxonNumber, c);    // setting state to that specified by character c
+							}
+							if (numFilledChars<ic) 
+								numFilledChars=ic;
+							ic += 1;
+							if (ic % 100==0)//== 0 && timer.timeSinceVeryStartInSeconds() % 1.0 <0.001)
+								progIndicator.setSecondaryMessage("Reading character " + ic);
+
+						}
+
+					}
+				}
+				if (added) 
+					lastTaxonNumber++;
+				//			file.readLine(sb);
+				if (file!=null) {
+					line = file.readNextDarkLine();		// added 1.01
+					pos = file.getFilePosition();
+				}
+				else {
+					line = parser.getRawNextDarkLine();
+					pos = parser.getPosition();
+				}
+				subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				if (file !=null && file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			if (getMultiFileImport() && getImportFileNumber()>=getTotalFilesToImport()-1)  // last import
+				if (getOriginalNumTaxa()>0 && getMaximumTaxonFilled()>=getOriginalNumTaxa() && getMaximumTaxonFilled()<taxa.getNumTaxa()-1)    
+					if (!taxa.taxaHaveAnyData(getMaximumTaxonFilled()+1, taxa.getNumTaxa()-1))
+						taxa.deleteTaxa(getMaximumTaxonFilled()+1, taxa.getNumTaxa()-getMaximumTaxonFilled(), true);   // delete a character if needed
+
+			Debugg.println("numChars: " + data.getNumChars() + ", numFilledChars: " + numFilledChars);
+			
+			
+			if (numFilledChars<data.getNumChars())
+				if (data.hasDataForCharacters(numFilledChars, data.getNumChars()-1))
+					MesquiteMessage.discreetNotifyUser("Warning: InterpretFASTA attempted to delete extra characters, but these contained data, and so were not deleted");
+				else
+					data.deleteCharacters(numFilledChars, data.getNumChars()-numFilledChars, true);   // delete a character if needed
+
+/*		
+	 		if (charAdded>0) {
+				data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+				data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED));
+			}
+*/
+
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+		
+
+			finishImport(progIndicator, file, abort);
+
+	}
+
+	/** readFileFromString takes the FASTA-formated string "contents" and pumps it into the CharacterData data.  This method is required for the ReadFileFromString interface */
+	/*.................................................................................................................*/
+	public void readFileFromString(CharacterData data, Taxa taxa, String contents, String arguments) {
+		MesquiteProject mf = getProject();
+		if (taxa == null || StringUtil.blank(contents))
+			return;
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing Sequences ", contents.length());
+		progIndicator.start();
+		String fRA = parser.getFirstToken(arguments);
+		while (!StringUtil.blank(fRA)) {
+			fRA = parser.getNextToken();
+		}
+		int numTaxa = taxa.getNumTaxa();
+		parser.setString(contents);
+		readFileCore(parser, null, data,  taxa, numTaxa, progIndicator, arguments, false);	
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+
+		decrementMenuResetSuppression();
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		boolean fuse = parser.hasFileReadingArgument(arguments, "fuseTaxaCharBlocks");
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+			Taxa taxa = null;
+			if (fuse){
+				String message = "There is a taxa block in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this imported taxa block into the taxa block you select below, or it will import that taxa block as new, separate taxa block.";
+				taxa = getProject().chooseTaxa(containerOfModule(), message, true, "Fuse with Selected Taxa Block", "Add as New Taxa Block");
+			}
+
+			if (taxa == null){
+				taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+				taxa.addToFile(file, getProject(), taxaTask);
+			}
+			CategoricalData data = null;
+			if (fuse){
+				String message = "There is a matrix in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+				data = (CategoricalData)getProject().chooseData(containerOfModule(), null, taxa, CategoricalState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+		//		data = (CategoricalData)getProject().chooseData(containerOfModule(), null, taxa, CategoricalState.class, "Select matrix with which to fuse the matrix from the file \"" + file.getName() + "  being read.   If you choose cancel, a new matrix will be created instead.",  true);
+			}
+			if (data == null){
+				data =(CategoricalData)createData(charTask,taxa);
+				data.addToFile(file, getProject(), null);
+			}
+			
+			int numTaxa = 0;
+			if (fuse)
+				numTaxa = taxa.getNumTaxa();
+			
+			readFileCore(parser, file, data,  taxa, numTaxa, progIndicator, arguments, !fuse);	
+			
+		}
+		decrementMenuResetSuppression();
+	}
+
+
+
+	/* ============================  exporting ============================*/
+	protected boolean includeGaps = false;
+	protected boolean simplifyTaxonName = false;
+	protected String uniqueSuffix = "";
+	protected boolean convertMultStateToMissing = true;
+
+	/*.................................................................................................................*/
+
+	public boolean getExportOptions(CharacterData data, boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export FASTA Options", buttonPressed);
+		exportDialog.appendToHelpString("Choose the options for exporting the matrix as FASTA file.");
+		exportDialog.appendToHelpString(" The Taxon Name Suffix, if present, will be appended to each taxon name.");
+		exportDialog.appendToHelpString(" Some systems (e.g., GenBank) require simple taxon names, and these will be used if you check 'simplify taxon names'");
+		SingleLineTextField uniqueSuffixField = exportDialog.addTextField("Taxon Name Suffix", "", 20);
+		Checkbox simpleTaxonNamesCheckBox = exportDialog.addCheckBox("simplify taxon names", simplifyTaxonName);
+		Checkbox includeGapsCheckBox = exportDialog.addCheckBox("include gaps", includeGaps);  
+		Checkbox converMultiStateToMissingCheckBox = exportDialog.addCheckBox("convert multistate to missing for protein data", convertMultStateToMissing);
+
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+		uniqueSuffix = uniqueSuffixField.getText();
+		if (uniqueSuffix==null)
+			uniqueSuffix="";
+
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+		includeGaps = includeGapsCheckBox.getState();
+		simplifyTaxonName=simpleTaxonNamesCheckBox.getState();
+		convertMultStateToMissing=converMultiStateToMissingCheckBox.getState();
+		
+		exportDialog.dispose();
+		return ok;
+	}	
+	/*.................................................................................................................*/
+
+	public boolean getExportOptionsSimple(boolean dataSelected, boolean taxaSelected){   // an example of a simple query, that only proved line delimiter choice; not used here
+		return (ExporterDialog.query(this,containerOfModule(), "Export FASTA Options")==0);
+	}	
+
+	/*.................................................................................................................*/
+	public abstract CharacterData findDataToExport(MesquiteFile file, String arguments);
+	/*.................................................................................................................*/
+	public abstract String getUnassignedSymbol();
+
+	protected String getSupplementForTaxon(Taxa taxa, int it){
+		return "";
+	}
+	protected String getTaxonName(Taxa taxa, int it){
+		if (simplifyTaxonName)
+			return StringUtil.cleanseStringOfFancyChars(taxa.getTaxonName(it)+uniqueSuffix,false,true);
+		else 
+			return taxa.getTaxonName(it)+uniqueSuffix;
+			//return ParseUtil.tokenize(taxa.getTaxonName(it)+uniqueSuffix);
+	}
+	protected void saveExtraFiles(CharacterData data){
+	}
+	
+	protected boolean taxonHasData(CharacterData data, int it){
+		for (int ic = 0; ic<data.getNumChars(); ic++) {
+			if (!writeOnlySelectedData || (data.getSelected(ic))){
+				if (!data.isUnassigned(ic, it) && !data.isInapplicable(ic, it) && (writeExcludedCharacters || data.isCurrentlyIncluded(ic)))
+					return true;
+			}
+		}
+		return false;
+	}
+	protected boolean includeOnlyTaxaWithData = true;// TO DO: also have the option of only writing taxa with data in them
+	
+ 	public  StringBuffer getDataAsFileText(MesquiteFile file, CharacterData data) {
+		Taxa taxa = data.getTaxa();
+
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+		boolean isProtein = data instanceof ProteinData;
+		ProteinData pData =null;
+		if (isProtein)
+			pData = (ProteinData)data;
+
+		int counter = 1;
+		for (int it = 0; it<numTaxa; it++){
+			if ((!writeOnlySelectedTaxa || (taxa.getSelected(it))) && (!includeOnlyTaxaWithData || taxonHasData(data, it))){
+				
+				
+				counter = 1;
+				outputBuffer.append(">");
+				outputBuffer.append(getTaxonName(taxa,it));
+				String sup = getSupplementForTaxon(taxa, it);
+				if (StringUtil.notEmpty(sup))
+					outputBuffer.append(sup);
+				outputBuffer.append(getLineEnding());
+				
+				for (int ic = 0; ic<numChars; ic++) {
+					if (!writeOnlySelectedData || (data.getSelected(ic))){
+						int currentSize = outputBuffer.length();
+						boolean wroteMoreThanOneSymbol = false;
+						boolean wroteSymbol = false;
+						if (data.isUnassigned(ic, it) || (convertMultStateToMissing && isProtein && pData.isMultistateOrUncertainty(ic, it))){
+							outputBuffer.append(getUnassignedSymbol());
+	                        counter ++;
+	                        wroteSymbol = true;
+						}
+						else if (includeGaps || (!data.isInapplicable(ic,it))) {
+							data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+							counter ++;
+							wroteSymbol = true;
+                        }
+						wroteMoreThanOneSymbol = outputBuffer.length()-currentSize>1;
+                        if ((counter % 50 == 1) && (counter > 1) && wroteSymbol) {    // modulo
+                            outputBuffer.append(getLineEnding());
+                        }
+
+						if (wroteMoreThanOneSymbol) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return null;
+						}
+					}
+				}
+				outputBuffer.append(getLineEnding());
+			}
+		}
+		return outputBuffer;
+ 	}
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		CharacterData data = findDataToExport(file, arguments);
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data, data.anySelected(), taxa.anySelected()))
+				return false;
+
+		StringBuffer outputBuffer = getDataAsFileText(file, data);
+
+		if (outputBuffer!=null) {
+			saveExportedFileWithExtension(outputBuffer, arguments, "fas");
+			saveExtraFiles(data);  
+			return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "FASTA file";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports FASTA files that consist of molecular sequence data." ;
+	}
+	/*.................................................................................................................*/
+
+	public boolean getConvertMultStateToMissing() {
+		return convertMultStateToMissing;
+	}
+
+	public void setConvertMultStateToMissing(boolean convertMultStateToMissing) {
+		this.convertMultStateToMissing = convertMultStateToMissing;
+	}
+
+
+
+}
+
+
diff --git a/Source/mesquite/io/lib/InterpretGenBank.java b/Source/mesquite/io/lib/InterpretGenBank.java
new file mode 100644
index 0000000..e75d567
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretGenBank.java
@@ -0,0 +1,306 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* 
+
+- make more things protected
+- document classes, add doc target to project (use mesquite.lib for example).
+- scripting
+
+general exporting stuff:
+	- tokenize properly
+
+general importing stuff
+	- set punctuation on read in, including single quotes
+	- set reading to not consider [ ], or to consider different comment tokens
+*/
+
+/* 
+Post version 1.0:
+	- verbose file reading
+	- on reading, store comment line as footnote
+*/
+
+/* ============  a file interpreter for GenBank files ============*/
+/** This is the class for interpreting GenBank files.  It is subclassed to make interpreters specifically for
+DNA and Protein files. */
+public abstract class InterpretGenBank extends FileInterpreterI implements ReadFileFromString {
+	Class[] acceptedClasses;
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		acceptedClasses = new Class[] {ProteinState.class, DNAState.class};
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return false;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return false;  //
+	}
+	
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		 return false; 
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return true;
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments){
+		return true;
+	}
+
+/*.................................................................................................................*/
+	public abstract void setGenBankState(CharacterData data, int ic, int it, char c);
+/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+
+	/*...............................................................................................................*/
+	/** for those permitting editing, indicates user has edited to incoming string.*/
+	public void setGenBankNumber(CharacterData data, Taxa taxa, int it, String s){
+		if (data==null || taxa==null)
+			return;
+		Taxon taxon = data.getTaxa().getTaxon(it);
+		Associable tInfo = data.getTaxaInfo(true);
+		if (tInfo != null && taxon != null) {
+			tInfo.setAssociatedObject(MolecularData.genBankNumberRef, it, s);
+		}
+	}
+	/*.................................................................................................................*/
+	public void readFileCore(Parser parser, MesquiteFile file, CharacterData data, Taxa taxa, int numTaxa, ProgressIndicator progIndicator, String arguments) {
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			Parser subParser = new Parser();
+
+			StringBuffer sb = new StringBuffer(1000);
+			if (file!=null)
+				file.readLine(sb);
+			else
+				sb.append(parser.getRawNextLine());
+			String line = sb.toString();
+			
+			boolean abort = false;
+
+			String taxonName = "";
+			String definitionString = "";
+			String organismString = "";
+			String sourceString = "";
+			String locusString = "";
+			String accession = "";
+			boolean charAdded = false;
+
+			while (!StringUtil.blank(line) && !abort) {
+				subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				
+				//subParser.setPunctuationString(";");
+				String token = subParser.getFirstToken(); 
+				
+				if (token.equalsIgnoreCase("DEFINITION")){
+					definitionString=StringUtil.stripBoundingWhitespace(subParser.getRemaining());
+				} 
+				else if (token.equalsIgnoreCase("LOCUS")){
+					locusString=StringUtil.stripBoundingWhitespace(subParser.getRemaining());
+				} 
+				else if (token.equalsIgnoreCase("ORGANISM")){
+					organismString=StringUtil.stripBoundingWhitespace(subParser.getRemaining());
+				} 
+				else if (token.equalsIgnoreCase("SOURCE")){
+					sourceString=StringUtil.stripBoundingWhitespace(subParser.getRemaining());
+				} 
+				else if (token.equalsIgnoreCase("ACCESSION")){
+					accession=StringUtil.stripBoundingWhitespace(subParser.getRemaining());
+				} 
+				else if (token.equalsIgnoreCase("ORIGIN")){
+					if (!StringUtil.blank(definitionString))
+						taxonName=definitionString;
+					else if (!StringUtil.blank(organismString))
+						taxonName=organismString;
+					else if (!StringUtil.blank(sourceString))
+						taxonName=sourceString;
+					else if (!StringUtil.blank(locusString))
+						taxonName=locusString;
+					taxa.addTaxa(numTaxa-1, 1, false);
+					taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED), CharacterData.class, true);
+					Taxon t = taxa.getTaxon(numTaxa);
+					if (!StringUtil.blank(accession)) {
+						setGenBankNumber(data, taxa, numTaxa,accession);
+					}
+					parser.setPunctuationString(null);
+					
+					if (t!=null) {
+						t.setName(taxonName);
+						if (file!=null)
+							progIndicator.setText(file.getName() + " [Reading sequence: "+taxonName + "]");
+						else
+							progIndicator.setText(" [Reading sequence: "+taxonName + "]");
+						log("[Reading sequence: "+taxonName + "]");
+						CommandRecord.tick("[Reading sequence: "+taxonName + "]");
+						if (file!=null)
+							line = file.readLine("//");  // pull in sequence
+						else
+							line = parser.getRemainingUntilChar('/', true);
+						if (line==null) break;
+						subParser.setString(line); 
+						int ic = 0;
+						char c;
+						while (subParser.getPosition()<line.length()) {
+							c=subParser.nextDarkChar();
+							if (c!='/' && c!= '\0'){
+								if (!Character.isDigit(c)) {
+									if (data.getNumChars() <= ic) {
+										data.addCharacters(data.getNumChars()-1, 20, false);   // add characters if needed
+										data.addInLinked(data.getNumChars()-1, 20, false);
+										charAdded = true;
+									}
+									setGenBankState(data,ic, numTaxa, c);    // setting state to that specified by character c
+									ic += 1;
+									if (ic%100==0) log(".");
+								}
+							}
+						}
+						logln("");
+
+					}
+					numTaxa++;
+			
+				} 
+				else if (token.equalsIgnoreCase("//")){
+				} 
+				if (charAdded)
+					data.notifyListeners(this, new Notification(CharacterData.PARTS_ADDED, null, null));
+				
+				if (file!=null)
+					line = file.readNextDarkLine();		// added 1.01
+				else
+					line = parser.getRawNextDarkLine();
+				if (file !=null && file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+	}
+	
+	/** readFileFromString takes the NBRF-formated string "contents" and pumps it into the CharacterData data.  This method is required for the ReadFileFromString interface */
+	/*.................................................................................................................*/
+	public void readFileFromString(CharacterData data, Taxa taxa, String contents, String arguments) {
+		MesquiteProject mf = getProject();
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing Sequences ", contents.length());
+		progIndicator.start();
+		String fRA = parser.getFirstToken(arguments);
+		while (!StringUtil.blank(fRA)) {
+			fRA = parser.getNextToken();
+		}
+		int numTaxa = taxa.getNumTaxa();
+		parser.setString(contents);
+		readFileCore(parser, null, data,  taxa, numTaxa, progIndicator, arguments);	
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+
+		decrementMenuResetSuppression();
+	}
+
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		boolean fuse = parser.hasFileReadingArgument(arguments, "fuseTaxaCharBlocks");
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			 CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+
+			Taxa taxa = null;
+			if (fuse){
+				String message = "There is a taxa block in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this imported taxa block into the taxa block you select below, or it will import that taxa block as new, separate taxa block.";
+				taxa = getProject().chooseTaxa(containerOfModule(), message, true, "Fuse with Selected Taxa Block", "Add as New Taxa Block");
+			}
+			
+			if (taxa == null){
+				taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+				taxa.addToFile(file, getProject(), taxaTask);
+			}
+			CategoricalData data = null;
+			if (fuse){
+				String message = "There is a matrix in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+				data = (CategoricalData)getProject().chooseData(containerOfModule(), null, taxa, CategoricalState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+			}
+			if (data == null){
+				data =(CategoricalData)createData(charTask,taxa);
+				data.addToFile(file, getProject(), null);
+			}
+
+			int numTaxa = 0;
+			if (fuse)
+				numTaxa = taxa.getNumTaxa();
+
+			readFileCore(parser, file, data,  taxa, numTaxa, progIndicator, arguments);
+		}
+		decrementMenuResetSuppression();
+	}
+	
+	public boolean exportFile(MesquiteFile file, String arguments) {
+		return true;
+		
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "GenBank file";
+	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports GenBank  files that consist of molecular sequence data." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/lib/InterpretHennig86Base.java b/Source/mesquite/io/lib/InterpretHennig86Base.java
new file mode 100644
index 0000000..48129bc
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretHennig86Base.java
@@ -0,0 +1,1684 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+28 July 01 (WPM): checked for treeVector == null on export; use getCompatibleFileElements
+ */
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.io.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+
+/* 
+
+
+
+- export trees
+
+- quote within XREAD, DREAD
+- tread   : check to see if format allows named taxa in tree description
+
+- handle abbreviations
+
+ */
+/*==================================================*/
+/* ============  a file interpreter for NONA files ============*/
+
+public abstract class InterpretHennig86Base extends FileInterpreterITree {
+	ProgressIndicator progIndicator;
+	Class[] acceptedClasses;
+	HennigNonaCommand[] availableCommands;
+	int treeNumber = 0;
+	boolean convertGapsToMissing = false;
+	boolean includeQuotes = true;
+	Class futureDataClass = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		availableCommands = new HennigNonaCommand[numCommands];
+		acceptedClasses = new Class[] {CategoricalState.class,ProteinState.class, DNAState.class};
+		initializeCommands();
+		return true;  //make this depend on taxa reader being found?)
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "ss";
+	}
+	/*.................................................................................................................*/
+	public void resetTreeNumber() {
+		treeNumber=0;
+	}
+	/*.................................................................................................................*/
+	public boolean isTNT() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Class getFutureDataClass() {
+		return futureDataClass;
+	}
+	/*.................................................................................................................*/
+	public void setFutureDataClass(Class futureDataClass) {
+		this.futureDataClass = futureDataClass;
+	}
+
+	/*.................................................................................................................*/
+	public int getTreeNumber() {
+		return treeNumber;
+	}
+	/*.................................................................................................................*/
+	public void incrementTreeNumber() {
+		treeNumber++;
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean additiveIsDefault() {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return project.getNumberCharMatrices(acceptedClasses) > 0;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		for (int i = 0; i<acceptedClasses.length; i++)
+			if (dataClass==acceptedClasses[i])
+				return true;
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void setConvertGapsToMissing(boolean convertGapsToMissing) {  
+		this.convertGapsToMissing = convertGapsToMissing;
+	}
+	/*.................................................................................................................*/
+	public boolean getConvertGapsToMissing() {  
+		return convertGapsToMissing;
+	}
+
+	/*.................................................................................................................*/
+	static final int numCommands = 8;   // number of available commands
+	static final int cnamesElement = 7;
+	/*.................................................................................................................*/
+	public void initializeCommands() {  
+		for (int j = 0; j<numCommands; j++) {
+			availableCommands[j] = null;
+		}
+
+		availableCommands[0] = new HennigDREAD(this, parser);
+		availableCommands[1] = new HennigXREAD(this, parser);
+		availableCommands[2] = new HennigCCODE(this, parser);
+		availableCommands[3] = new HennigQUOTE(this, parser);
+		availableCommands[4] = new HennigTREAD(this, parser);
+		availableCommands[5] = new HennigCOMMENTS(this, parser);
+		availableCommands[6] = new HennigNSTATES(this, parser);
+		availableCommands[cnamesElement] = new HennigCNAMES(this, parser);
+	}
+	
+	/*...............................................  read tree ....................................................*/
+	/** Continues reading a tree description, starting at node "node" and the given location on the string*/
+	public boolean readClade(MesquiteTree tree, int node, Parser treeParser, NameReference valuesAtNodes) {
+		return readClade( tree,  node,  treeParser,  valuesAtNodes, null);
+
+	}
+
+	/*...............................................  read tree ....................................................*/
+	/** Continues reading a tree description, starting at node "node" and the given location on the string*/
+	public boolean readClade(MesquiteTree tree, int node, Parser treeParser, NameReference valuesAtNodes, int[] taxonNumberTranslation) {
+
+		// from BasicTreeWindowMaker in Minimal
+
+		String c = treeParser.getNextToken();
+		if ("(".equals(c)){  //internal node
+			int sprouted = tree.sproutDaughter(node, false);
+			readClade(tree, sprouted, treeParser, valuesAtNodes, taxonNumberTranslation);
+			boolean keepGoing = true;
+			while (keepGoing) {
+				int loc = treeParser.getPosition();
+				String next = treeParser.getNextToken();
+				if (")".equals(next)) {  
+					keepGoing = false;
+					loc = treeParser.getPosition();
+					next = treeParser.getNextToken();
+					 if ("=".equals(next)) {
+						next = treeParser.getNextToken();
+						int value = MesquiteInteger.fromString(next);
+						tree.setAssociatedDouble(valuesAtNodes, node, 0.01*value, true);  // value will be a percentage
+
+					} else
+						treeParser.setPosition(loc);
+				}
+				else {
+					treeParser.setPosition(loc);
+					sprouted = tree.sproutDaughter(node, false);
+					keepGoing = readClade(tree, sprouted, treeParser, valuesAtNodes, taxonNumberTranslation);
+				}
+			}
+			return true;
+		}
+		else if (")".equals(c)) {
+			return false;
+		}
+		else {
+			int taxonNumber = MesquiteInteger.fromString(c);
+			if (taxonNumber <0 || !MesquiteInteger.isCombinable(taxonNumber)) 
+				taxonNumber = tree.getTaxa().whichTaxonNumber(c); 
+			if (taxonNumber >=0 && MesquiteInteger.isCombinable(taxonNumber)){ //taxon specifier is a number
+				if (taxonNumberTranslation!=null && taxonNumber<taxonNumberTranslation.length) {  // better push it through the translation array
+					int newNumber = taxonNumberTranslation[taxonNumber];
+					if (newNumber >=0 && MesquiteInteger.isCombinable(newNumber))
+						taxonNumber = newNumber;
+				}
+				if (tree.nodeOfTaxonNumber(taxonNumber)<=0){  // first time taxon encountered
+					tree.setTaxonNumber(node, taxonNumber, false);
+					return true;
+				}
+			}
+			return false;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public MesquiteTree readTREAD(ProgressIndicator progIndicator, Taxa taxa, String line, boolean firstTree, MesquiteString quoteString, NameReference valuesAtNodes){
+		return  readTREAD( progIndicator,  taxa,  line,  firstTree,  quoteString,  valuesAtNodes, null);
+	}
+	/*.................................................................................................................*/
+	public MesquiteTree readTREAD(ProgressIndicator progIndicator, Taxa taxa, String line, boolean firstTree, MesquiteString quoteString, NameReference valuesAtNodes, int[] taxonNumberTranslation){
+		if (StringUtil.blank(line))
+			return null;
+		Parser treeParser;
+		treeParser =  new Parser();
+		line = line.trim();
+		treeParser.setQuoteCharacter((char)0);
+		treeParser.setPunctuationString("():[];, at +=");
+		String lowerLine = line.toLowerCase();
+		int treadpos = lowerLine.indexOf("tread");   // check to see it is at start
+		if (treadpos>=0){
+			line = line.substring(treadpos+5, line.length());
+		}
+		String token;
+		String quote = null;
+		char c;
+		int linePos;
+		parser.setString(line);
+		Tree tree = null;
+		long totalLength = line.length();
+
+
+		while (!StringUtil.blank(line)) {
+			parser.setString(line);
+			c = parser.nextDarkChar();
+			if ((treeNumber==0) && (c=='\'' && c!='\0'))  {   // we have a leading quote in the TREAD command
+				linePos = parser.getPosition();
+				c = parser.nextDarkChar();
+				while (c!='\'' && c!='\0') {
+					c = parser.nextDarkChar();
+				}
+				quote = line.substring(linePos,parser.getPosition()-1);  // saving entire quoted section  TODO: place in trees block
+				if (quoteString!=null && StringUtil.notEmpty(quote))
+					quoteString.setValue(line.substring(linePos,parser.getPosition()-1));
+				int startPos = linePos-1;
+				int endPos = parser.getPosition()-1;
+				if (endPos>line.length())
+					endPos=line.length()-1;
+				if (startPos<= endPos && startPos>=0 && endPos<=line.length())
+					line = StringUtil.removePiece(line, startPos, endPos);  // removing first quote
+				parser.setString(line);
+				//parser.setPosition(0);
+			}	
+			if (StringUtil.blank(line)) {
+				return null;
+			}
+			treeNumber++;
+			if (progIndicator!=null) {
+				progIndicator.setCurrentValue(totalLength-line.length());
+				progIndicator.setText("Reading tree " + treeNumber);
+			}
+
+			if (c==';' || c=='\0') {
+				return null;
+			}
+			else {    // info for this tree
+				int star = line.indexOf("*");
+				String treeDescription = null;
+				if (star>0) {
+					treeDescription = line.substring(0, star);
+					line = line.substring(star+1, line.length());
+				}
+				else  {
+					treeDescription = line;
+					line = null;
+				}
+				if (!StringUtil.blank(treeDescription) && treeDescription.indexOf("(")>=0){
+					MesquiteTree t = new MesquiteTree(taxa);
+					MesquiteInteger pos = new MesquiteInteger(0);
+					treeParser.setString(treeDescription);
+					readClade(t, t.getRoot(), treeParser, valuesAtNodes, taxonNumberTranslation);
+					t.setAsDefined(true);
+					t.setName("Imported tree " + treeNumber);
+					return t;
+					//trees.addElement(t, false);
+					//	if (counter==1 && firstTree)
+					//	return trees;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void readTreeFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		Taxa taxa = getProject().chooseTaxa(containerOfModule(), "Of what taxa are these trees composed?");
+		if (taxa== null) 
+			return;
+		incrementMenuResetSuppression();
+		//file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+
+			parser.setPunctuationString(";");
+			parser.setQuoteCharacter((char)0);
+			String line = file.readLine(";");   // reads first line
+			String command;
+
+			boolean abort = false;
+			while (!StringUtil.blank(line) && !abort) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				command = parser.getFirstToken(line); //command name
+				if ((availableCommands[4] != null) && availableCommands[4].canRead(command)) {
+					availableCommands[4].readCommand(mf,file,null,null,taxa,line);
+				}
+				line = file.readLine(";");		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			finishImport(null, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+
+			parser.setPunctuationString(";");
+			parser.setQuoteCharacter((char)0);
+			String line = file.readLine(";");   // reads first line
+			String command;
+
+			CategoricalData data = null;
+			Taxa taxa = null;
+
+			boolean abort = false;
+			progIndicator.setText("Reading commands in file of format " + getName());					
+			while (!StringUtil.blank(line) && !abort) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				command = parser.getFirstToken(line); //command name
+				progIndicator.setText("Reading command " + command);					
+				for (int j = 0; j<numCommands; j++) {
+					if ((availableCommands[j] != null) && availableCommands[j].canRead(command)) {
+						if (availableCommands[j].returnData()) {
+							data = availableCommands[j].readCommandReturnData(mf, file,progIndicator);
+							if (data == null) {
+
+								discreetAlert( "Sorry, the file could not be read.  The log file may indicate reasons.");
+								abort = true;
+							}
+						}
+						else if (data != null)
+							availableCommands[j].readCommand(mf,file,progIndicator,data,data.getTaxa(),line);
+						else
+							availableCommands[j].readCommand(mf,file,progIndicator,null,null,line);
+					}
+				}
+				line = file.readLine(";");		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			progIndicator.setText("Finishing import of file of format " + getName());					
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		setLineDelimiter(WINDOWSDELIMITER);
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export TNT/Nona/Hennig86 Options", buttonPressed);
+		
+		Checkbox convertGapsBox = exportDialog.addCheckBox("convert gaps to missing", convertGapsToMissing);
+
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		if (ok)  {
+			convertGapsToMissing = convertGapsBox.getState();
+			//storePreferences();
+		}
+
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+	public boolean characterShouldBeIncluded(CharacterData data, int ic) {
+		return (!writeOnlySelectedData || (data.getSelected(ic)));
+		//return ((!writeOnlySelectedData || (data.getSelected(ic))) && (writeExcludedCharacters || data.isCurrentlyIncluded(ic)));
+	}
+	/*.................................................................................................................*/
+	public int getLastCharacterToBeIncluded(CharacterData data) {
+		if (writeOnlySelectedData)
+			return data.lastSelected();
+	/*	if (!writeExcludedCharacters) {
+			for (int ic=data.getNumChars()-1; ic>=0; ic--) {
+				if (data.isCurrentlyIncluded(ic)) {
+					if (!writeOnlySelectedData || data.getSelected(ic))
+						return ic;
+				}
+			}
+		}
+		*/
+		return data.getNumChars()-1;
+	}
+	/*.................................................................................................................*/
+
+	public boolean getExportOptionsSimple(boolean dataSelected, boolean taxaSelected){   // an example of a simple query, that only proved line delimiter choice; not used here
+		return (ExporterDialog.query(this,containerOfModule(), "Export TNT/Nona/Hennig86 Options")==0);
+	}	
+
+	/*.................................................................................................................*/
+	public CategoricalData findDataToExport(MesquiteFile file, String arguments) { 
+		return (CategoricalData)getProject().chooseData(containerOfModule(), file, null, acceptedClasses, "Select data to export");
+	}
+	/*.................................................................................................................*/
+	public int getNumExportTotal(Taxa taxa, CategoricalData data) {  
+		int exportTotalElements = 0;
+		exportTotalElements+= taxa.getNumTaxa();   // for XREAD
+		if (data.hasStateNames()|| data.characterNamesExist()) {
+			exportTotalElements+= data.getNumChars();   // for CNAMES
+		}
+		return exportTotalElements;
+	}
+	/*.................................................................................................................*/
+	public StringBuffer getDataAsFileText(MesquiteFile file, CharacterData data) {
+		Taxa taxa = data.getTaxa();
+		CategoricalData catData = (CategoricalData)data;
+		HennigXDREAD dread = (HennigXDREAD)availableCommands[0];
+		HennigXDREAD xread = (HennigXDREAD)availableCommands[1];
+		
+		if (file != null){
+			writeTaxaWithAllMissing = file.writeTaxaWithAllMissing;
+			writeExcludedCharacters = file.writeExcludedCharacters;
+		}
+
+
+		StringBuffer outputBuffer = new StringBuffer(taxa.getNumTaxa()*(20 + data.getNumChars()));
+		if (getIncludeQuotes())
+			availableCommands[3].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);  //quote
+		if (data.getStateClass()==DNAData.class && !isTNT())
+			dread.appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);
+		else
+			xread.appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);
+		if (catData.hasStateNames()|| data.characterNamesExist())
+			availableCommands[cnamesElement].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);
+
+		availableCommands[2].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);  //ccode
+		return outputBuffer;
+	}
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		CategoricalData  data = findDataToExport(file, arguments);
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected(), taxa.anySelected())) {
+				return false;
+			}
+		int totalProgressElements = getNumExportTotal(taxa, data);
+		progIndicator = new ProgressIndicator(getProject(),"Exporting File ", totalProgressElements, false);
+		progIndicator.start();
+
+
+		StringBuffer outputBuffer = getDataAsFileText(file, data);  //ccode
+		if (outputBuffer==null)
+			return false;
+
+		if (!args.parameterExists("noTrees"))
+			availableCommands[4].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);  //trees
+
+		outputBuffer.append(getLineEnding()+ "proc /;");
+
+		//	outputBuffer.append(getLineEnding());
+		//	availableCommands[cnamesElement].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);  //character names
+		outputBuffer.append(getLineEnding());
+		availableCommands[5].appendCommandToStringBuffer(outputBuffer, taxa, data, progIndicator);  //comments
+		outputBuffer.append(getLineEnding());
+
+
+
+
+		progIndicator.goAway();
+
+		saveExportedFileWithExtension(outputBuffer, arguments, preferredDataFileExtension());
+		return true;
+	}
+
+
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "TNT, NONA, Hennig86, PiWe, WinClada";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports TNT/NONA/Hennig86/PiWe/WinClada files." ;
+	}
+	public boolean getIncludeQuotes() {
+		return includeQuotes;
+	}
+	public void setIncludeQuotes(boolean includeQuotes) {
+		this.includeQuotes = includeQuotes;
+	}
+
+
+
+
+}
+
+
+
+
+/*========================================================*/
+abstract class HennigNonaCommand {
+	protected  InterpretHennig86Base ownerModule;
+	public FileInterpreterI fileInterpreter;
+	public Parser parser;
+
+
+	public HennigNonaCommand(InterpretHennig86Base ownerModule, Parser parser){
+		fileInterpreter = (FileInterpreterI)ownerModule;
+		this.ownerModule = ownerModule;
+		this.parser = parser;
+	}
+	/*.................................................................................................................*/
+	public abstract String getCommandName();   // returns the command name
+	/*.................................................................................................................*/
+	public  boolean canRead(String s){
+		boolean can;
+		if (s.length()<getCommandName().length()) {
+			String shortCommandName = getCommandName().substring(0,s.length());
+			can = getCommandName().equalsIgnoreCase(s) || shortCommandName.equalsIgnoreCase(s);
+		}
+		else
+			can = getCommandName().equalsIgnoreCase(s);
+		return can;
+	}
+	/*.................................................................................................................*/
+	public abstract boolean returnData();
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public CategoricalData readCommandReturnData(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator){
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void incrementAndUpdateProgIndicator(ProgressIndicator progIndicator, String s){
+		if (progIndicator!=null) {
+			progIndicator.setCurrentValue(progIndicator.getCurrentValue()+1);
+			progIndicator.setText(s);
+		}
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+	}
+}
+/*========================================================*/
+
+/*.................................................................................................................*/
+class HennigCCODE extends HennigNonaCommand {
+	CharWeightSet weightSet = null;
+	CharacterModel additive = null;
+	CharacterModel nonadditive = null;
+	ParsimonyModelSet modelSet= null;
+	CharInclusionSet inclusionSet = null;
+
+	public HennigCCODE (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "ccode";
+	}
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		if (data == null || taxa == null)
+			return false;
+		/*		[ 	make following characters active   
+		]	make following characters inactive;  i.e., exclude
+		- 	make following characters nonadditive;  i.e., unordered
+		+	make following characters additive;   i.e., ordered
+		/N	set weight to number N, then apply to following characters
+		 *     discard all previous specifiers
+	        =N	set internal steps to number N, then apply to following characters, not supported by Mesquite
+		 */     
+		/*    	scopes work as follows:  character numbers are used, with a . representing "to".  
+		if . is used, without a number on one side, represents end of matrix
+
+		zero based.
+		e.g.,
+		3	character 3 
+		.3	characters 0-3
+		3.	characters 3 to the end of the matrix
+		3.7	characters 3 through 7 inclusive
+		 */ 		
+
+		//weights
+		if (weightSet ==null) {
+			weightSet= new CharWeightSet("Imported Weight Set", data.getNumChars(), data);  // making a weight set
+			weightSet.addToFile(ownerModule.getProject().getHomeFile(), ownerModule.getProject(), ownerModule.findElementManager(CharWeightSet.class)); //attaching the weight set to a file
+			data.setCurrentSpecsSet(weightSet, CharWeightSet.class); 
+
+			//types
+			additive = ownerModule.getProject().getCharacterModel("ord");
+			nonadditive = ownerModule.getProject().getCharacterModel("unord");
+			if (ownerModule.additiveIsDefault())
+				modelSet= new ParsimonyModelSet("Imported Model Set", data.getNumChars(), nonadditive,data);  // making a parsimony set
+			else
+				modelSet= new ParsimonyModelSet("Imported Model Set", data.getNumChars(), additive,data);  // making a parsimony set
+			modelSet.addToFile(ownerModule.getProject().getHomeFile(), ownerModule.getProject(), ownerModule.findElementManager(ParsimonyModelSet.class)); //attaching the type set to a file
+			data.setCurrentSpecsSet(modelSet, ParsimonyModelSet.class);  
+
+			//inclusion exclusion
+			inclusionSet= new CharInclusionSet("Imported Inclusion Set", data.getNumChars(), data);  // making an inclusion set
+			inclusionSet.addToFile(ownerModule.getProject().getHomeFile(), ownerModule.getProject(), ownerModule.findElementManager(CharInclusionSet.class)); //attaching the inclusion set to a file
+			data.setCurrentSpecsSet(inclusionSet, CharInclusionSet.class);  
+			inclusionSet.selectAll();
+		}
+
+
+
+
+		boolean makeActive = true;
+		boolean makeInactive = false;
+		boolean makeNonAdditive = false;
+		boolean makeAdditive = true;
+		boolean setWeight = false;
+		int weightToSet = 1;
+		int scopeStart = 0;
+		int scopeEnd = data.getNumChars()-1;
+
+		parser.setPunctuationString("*-+[]/");
+		String token;
+		progIndicator.setText("Reading CCODE");
+		token = parser.getNextToken();
+
+		while (!StringUtil.blank(token)) {
+			if ("[".equals(token)) makeActive = true;
+			else if ("]".equals(token)) makeInactive = true;
+			else if ("-".equals(token)) makeNonAdditive = true;
+			else if ("+".equals(token)) makeAdditive = true;
+			else if ("*".equals(token)) {
+				makeActive = true;
+				makeInactive = false;
+				makeNonAdditive = false;
+				makeAdditive = true;
+				setWeight = false;
+			}
+			else if ("/".equals(token)) {
+				token = parser.getNextToken();
+				weightToSet = MesquiteInteger.fromString(token);
+				setWeight=true;
+			}
+			else if ("=".equals(token)) {
+				token = parser.getNextToken();
+				MesquiteTrunk.mesquiteTrunk.alert("Sorry, Mesquite does not support setting of internal steps in NONA files.");
+			}
+			else  { // it is a scope, we need to process it
+				scopeStart = 0;
+				scopeEnd = data.getNumChars()-1;
+				if (token.indexOf(".")<0) {// it's just a single character
+					scopeStart = MesquiteInteger.fromString(token);
+					scopeEnd = scopeStart;
+				}
+				else if (".".equals(token)) {  // it's just at dot
+					scopeStart = 0;
+					scopeEnd = data.getNumChars()-1;
+				}
+				else if (token.charAt(0) =='.') {  // it's at the start
+					scopeStart = 0;
+					scopeEnd = MesquiteInteger.fromString(token.substring(1, token.length()));
+				}
+				else if (token.charAt(token.length()-1) =='.') {  // it's at the end
+					scopeStart = MesquiteInteger.fromString(token.substring(0, token.length()-1));
+					scopeEnd = data.getNumChars()-1;
+				}
+				else  {  // it's in the middle
+					scopeStart = MesquiteInteger.fromString(token.substring(0, token.indexOf(".")));
+					scopeEnd = MesquiteInteger.fromString(token.substring(token.indexOf(".")+1, token.length()));
+				}
+				for (int ic=scopeStart; ic<=scopeEnd; ic++) {   // setting the values of each character in the scope
+					if (makeAdditive) modelSet.setModel(additive, ic);
+					if (makeNonAdditive) modelSet.setModel(nonadditive, ic);
+					if (setWeight) weightSet.setValue(ic, weightToSet);
+					if (makeActive) inclusionSet.setSelected(ic, true);
+					if (makeInactive) inclusionSet.setSelected(ic, false);
+				}
+
+			}
+			token = parser.getNextToken();
+		}
+		parser.setPunctuationString(";");
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	private String scopeToString(int scopeStart, int scopeEnd) {
+		String s =" "+scopeStart;
+		if (scopeEnd==scopeStart+1)
+			s+=" "+scopeEnd;
+		else if (scopeEnd>scopeStart+1)
+			s+="."+scopeEnd;
+		return s;
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		CategoricalData data = (CategoricalData)charData;
+		int numChars = data.getNumChars();
+		String ccode="";
+
+//		writing the character weights
+		CharWeightSet weightSet = (CharWeightSet) data.getCurrentSpecsSet(CharWeightSet.class);
+		CharInclusionSet processedSet= new CharInclusionSet("", data.getNumChars(), data); // temporary specset
+		for (int ic=0; ic<numChars; ic++) 
+			processedSet.setSelected(ic, false);
+
+		int ic = 0;
+		int scopeStart;
+		int icWeight = 1;
+		String ccodePart = "";
+		int counter = 0;
+		int outerLoopCharNumber = -1;
+		int innerLoopCharNumber = 0;
+		
+		int lastCharIncluded = ownerModule.getLastCharacterToBeIncluded(data);
+
+		if (weightSet != null)
+			while (ic< numChars) {
+				if (ownerModule.characterShouldBeIncluded(data, ic)){
+					outerLoopCharNumber++;
+					if (weightSet.isUnassigned(ic))
+						icWeight = 1;  //unassigned treated as 1
+					else if (weightSet.isDouble())
+						icWeight = (int)(0.5 + weightSet.getDouble(ic));
+					else 
+						icWeight = weightSet.getInt(ic);
+					if (icWeight!=1 && !processedSet.isBitOn(ic)) {
+						processedSet.setSelected(ic, true);   // marks this one as already chosen
+						ccodePart+=" /"+icWeight + " ";
+						scopeStart= counter;
+						boolean foundFirstBreak = false;
+						innerLoopCharNumber = outerLoopCharNumber;
+						for (int icFollow=ic+1; icFollow<numChars; icFollow++) {
+							if (ownerModule.characterShouldBeIncluded(data, icFollow)){
+								innerLoopCharNumber++;
+								int icFollowWeight = 0;
+								if (weightSet.isUnassigned(icFollow))
+									icFollowWeight = 1;
+								else if (weightSet.isDouble())
+									icFollowWeight = (int)(0.5 + weightSet.getDouble(icFollow));
+								else 
+									icFollowWeight = weightSet.getInt(icFollow);
+								if (icFollowWeight==icWeight && !processedSet.isBitOn(icFollow))  {  //it's a weight I've seen before
+									processedSet.setSelected(icFollow, true);
+									if (scopeStart==-1) {
+										scopeStart=innerLoopCharNumber; 
+									}
+									if ((icFollow==lastCharIncluded)) {   // deal with excluded characters
+										ccodePart += scopeToString(scopeStart, innerLoopCharNumber);
+										if (!foundFirstBreak)
+											ic=numChars;
+									}
+								}
+								else if (scopeStart>=0) {   // we've found a break, write previous scope
+									ccodePart += scopeToString(scopeStart, innerLoopCharNumber-1);
+									scopeStart=-1;
+									if (!foundFirstBreak) {
+										foundFirstBreak = true;
+									}
+
+								}
+							}
+						}
+					
+					}
+					counter++;
+				}
+				ic ++;
+			}
+
+		if (ccodePart!="")
+			ccode += ccodePart+" *";
+		ccodePart = "";
+
+//		now to write which characters are unordered (non-additive)
+		ParsimonyModelSet modelSet= (ParsimonyModelSet)data.getCurrentSpecsSet(ParsimonyModelSet.class);
+
+		String nonDefaultName = "ordered";
+		if (ownerModule.additiveIsDefault())
+			nonDefaultName="unordered";
+		boolean firstTime=true;
+		ic = 0;
+		counter = 0;
+		if (modelSet!=null)
+			while (ic<numChars) {
+				if (ownerModule.characterShouldBeIncluded(data, ic)) {
+					if (nonDefaultName.equalsIgnoreCase(modelSet.getModel(ic).getName())) {
+						if (firstTime) {
+							if (ownerModule.additiveIsDefault())
+								ccodePart+=" - ";
+							else
+								ccodePart+=" + ";
+							firstTime=false;
+						}
+						scopeStart=counter;
+						while (ic<numChars && ((nonDefaultName.equalsIgnoreCase(modelSet.getModel(ic).getName())) ||  !ownerModule.characterShouldBeIncluded(data,ic)  )) {
+							ic++;
+							if (ownerModule.characterShouldBeIncluded(data, ic))
+								counter++;
+						}
+						if (ic>=lastCharIncluded)
+							ccodePart += scopeToString(scopeStart, lastCharIncluded);
+						else
+							ccodePart += scopeToString(scopeStart, counter-1);
+					}
+					counter++;
+				}
+				ic++;
+			}
+
+//		now to write which characters are excluded (inactive)
+		if (ccodePart!="")
+			ccode += ccodePart+" *";
+		ccodePart = "";
+
+		CharInclusionSet inclusionSet= (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+
+		firstTime=true;
+		ic = 0;
+		counter = 0;
+		if (inclusionSet!=null)
+			while (ic<numChars) {
+				if (ownerModule.characterShouldBeIncluded(data, ic)) {
+					if (!inclusionSet.isBitOn(ic)) {   // i.e, bit is off
+						if (firstTime) {
+							ccodePart+=" ] ";
+							firstTime=false;
+						}
+						scopeStart=counter;
+						while (ic<numChars && ((!inclusionSet.isBitOn(ic)) ||  !ownerModule.characterShouldBeIncluded(data,ic)  )) {
+							ic++;
+							if (ownerModule.characterShouldBeIncluded(data, ic))
+								counter++;
+						}
+						if (ic>=lastCharIncluded)
+							ccodePart += scopeToString(scopeStart, lastCharIncluded);
+						else
+							ccodePart += scopeToString(scopeStart, counter-1);
+					}
+					counter++;
+				}
+				ic++;
+			}
+
+		ccode += ccodePart;
+
+		if (!StringUtil.blank(ccode)) {
+			outputBuffer.append(getCommandName()+"\t");
+			outputBuffer.append(ccode);
+			outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+		}
+	}
+}
+/*========================================================*/
+
+/*.................................................................................................................*/
+class HennigQUOTE extends HennigNonaCommand {
+	public HennigQUOTE (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "quote";
+	}
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+
+		int pos = firstLine.indexOf("quote");
+		if (pos>=0) {
+			firstLine = firstLine.substring(pos+6, firstLine.length());
+		}
+		file.setAnnotation(firstLine, false);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		CategoricalData data = (CategoricalData)charData;
+		if (!StringUtil.blank(data.getAnnotation())) {
+			outputBuffer.append(getCommandName()+" ");
+			outputBuffer.append(data.getAnnotation());
+			outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+		}
+	}
+}
+/*========================================================*/
+
+/*.................................................................................................................*/
+class HennigNSTATES extends HennigNonaCommand {
+	public HennigNSTATES (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "nstates";
+	}
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		Parser parser = new Parser(firstLine);
+		parser.getFirstToken();
+		String datatype = parser.getNextToken();
+		if ("dna".equalsIgnoreCase(datatype)) {
+			ownerModule.setFutureDataClass(DNAData.class);
+		}
+		else	if ("prot".equalsIgnoreCase(datatype)) {
+			ownerModule.setFutureDataClass(ProteinData.class);
+		}
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		outputBuffer.append(getCommandName()+" ");
+		if (charData instanceof DNAData) 
+			outputBuffer.append("dna");
+		else if (charData instanceof ProteinData) 
+			outputBuffer.append("prot");
+		outputBuffer.append(";"+ fileInterpreter.getLineEnding());
+	}
+}
+/*========================================================*/
+/*.................................................................................................................*/
+class HennigCNAMES extends HennigNonaCommand {
+	public HennigCNAMES (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "cnames";
+	}
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		if (parser == null || taxa == null || data == null)
+			return false;
+		parser.setPunctuationString("{;");
+		int charNumber = 0;
+		String line = firstLine;
+		String token;
+
+		progIndicator.setText("Reading character and state names");
+		while (!StringUtil.blank(line)) {
+			token = parser.getNextToken();
+			if (token==";") 
+				return true;
+			else {    // info for this character
+				token = parser.getNextToken();
+				if (token=="+")
+					charNumber++;
+				else {
+					charNumber = MesquiteInteger.fromString(token);
+					if ((charNumber>=0)&&(charNumber<=data.getNumChars())) {
+						token = parser.getNextToken();
+						if (token != "_")
+							data.setCharacterName(charNumber,token);
+						if ((token !=";") && (token != null)) {
+							token = parser.getNextToken();
+							if ((token !=";") && (token != null)) {
+								int stateNumber = 0;
+								while ((token !=";") && (token != null)) {
+									if (token != "_") 
+										((CategoricalData)data).setStateName(charNumber, stateNumber, token);
+									token = parser.getNextToken();
+									stateNumber ++;
+								}
+							}
+						}
+
+
+					}
+				}
+			}
+			line = file.readLine(";");
+			parser.setString(line);
+		}
+		parser.setPunctuationString(";");
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		CategoricalData data = (CategoricalData)charData;
+		outputBuffer.append(getCommandName()+fileInterpreter.getLineEnding());
+		int numChars = data.getNumChars();
+		int counter = 0;
+
+		for (int ic = 0; ic<numChars; ic++) {
+
+			if (ownerModule.characterShouldBeIncluded(data, ic) &&(data.characterHasName(ic)||data.hasStateNames(ic))) {
+				incrementAndUpdateProgIndicator(progIndicator,"Exporting character and state names");
+				outputBuffer.append("{"+counter+" ");
+				if (data.characterHasName(ic))
+					outputBuffer.append(StringUtil.tokenize(data.getCharacterName(ic),";"));
+				else if (data.hasStateNames(ic))
+					outputBuffer.append(StringUtil.tokenize("Character_" + (ic+1),";"));
+
+				if (data.hasStateNames(ic)) {
+					for (int stateNumber = 0; stateNumber<=data.maxStateWithName(ic); stateNumber++) {
+						if (data.hasStateName(ic,stateNumber))
+							outputBuffer.append(" " + StringUtil.tokenize(data.getStateName(ic,stateNumber),";"));
+						else
+							outputBuffer.append(" " + "_");
+					}
+				}
+				outputBuffer.append(";" + fileInterpreter.getLineEnding());
+			}
+			if (ownerModule.characterShouldBeIncluded(data,ic))
+				counter++;
+		}
+
+		outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+	}
+}
+/*========================================================*/
+/*.................................................................................................................*/
+class HennigCOMMENTS extends HennigNonaCommand {
+	public HennigCOMMENTS (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "comments";
+	}
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		if (parser == null || taxa == null || data == null)
+			return false;
+		parser.setPunctuationString("{;");
+
+		String line = firstLine;
+		String token;
+
+		if (progIndicator != null)
+			progIndicator.setText("Reading comments");
+		while (!StringUtil.blank(line)) {
+			token = parser.getNextToken(); //getting
+			if (token==";") 
+				return true;
+			else {    // info for this character
+				if (token == null || !("{".equals(token))){
+					token = parser.getNextToken(); //getting
+				}						
+				token = parser.getNextToken();
+				int taxonNumber = MesquiteInteger.fromString(token);
+				if (taxa != null && (taxonNumber>=0)&&(taxonNumber<=taxa.getNumTaxa())) {
+					token = parser.getNextToken(); //taxon number
+					int charNumber = MesquiteInteger.fromString(token);
+					if ((charNumber>=0)&&(charNumber<=data.getNumChars())) {
+						token = parser.getRemaining(); 
+						if (data != null && (token !=";") && (token != null)) {
+							data.setAnnotation(charNumber, taxonNumber, token);
+						}
+					}
+
+				}
+
+			}
+			line = file.readLine(";");
+			parser.setString(line);
+		}
+		parser.setPunctuationString(";");
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		CategoricalData data = (CategoricalData)charData;
+		int numChars = data.getNumChars();
+		int numTaxa = taxa.getNumTaxa();
+		int charCounter = 0;
+		int totalCounter = 0;
+		int startPos = outputBuffer.length();
+
+		incrementAndUpdateProgIndicator(progIndicator,"Exporting comments");
+		for (int it = 0; it<numTaxa; it++){
+			charCounter = 0;
+			for (int ic = 0; ic<numChars; ic++) {
+				if (ownerModule.characterShouldBeIncluded(data, ic)) {
+					String note = data.getAnnotation(ic, it);
+					if (note !=null){
+						outputBuffer.append("{"+it+" " + charCounter + " ");
+						outputBuffer.append(note);
+						outputBuffer.append(";" + fileInterpreter.getLineEnding());
+						totalCounter++;
+					}							
+					charCounter++;
+				}
+			}
+		}
+
+		outputBuffer.insert(startPos, getCommandName()+ " " + totalCounter + fileInterpreter.getLineEnding());
+		outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+	}
+}
+/*========================================================*/
+
+
+
+
+/*.................................................................................................................*/
+abstract class HennigXDREAD extends HennigNonaCommand {
+	public HennigXDREAD (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+	/*.................................................................................................................*/
+	public abstract boolean readStartXDREAD(Parser parser);
+	/*.................................................................................................................*/
+	public CategoricalData readCommandReturnData(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator){
+		TaxaManager taxaTask = (TaxaManager)ownerModule.findElementManager(Taxa.class);
+		CharactersManager charTask = (CharactersManager)ownerModule.findElementManager(CharacterData.class);
+
+		Taxa taxa = taxaTask.makeNewTaxa("Taxa", 0, false);
+		taxa.addToFile(file, ownerModule.getProject(), taxaTask);
+
+		InterpretHennig86Base interpretHN = (InterpretHennig86Base)ownerModule;
+		CategoricalData newData = (CategoricalData)createData(charTask,taxa);
+
+		if (newData==null) 
+			return null;
+
+		newData.saveChangeHistory = false;
+
+		newData.addToFile(file, ownerModule.getProject(), null);
+
+		if (! readStartXDREAD(parser))
+			return null;
+		String token;
+		char c;
+
+		c = parser.nextDarkChar();
+		if (c=='\'')  {   // we have a leading quote in the XREAD command
+			int linePos = parser.getPosition();
+			c = parser.nextDarkChar();
+			while (c!='\'' && c!='\0') {   // TODO: check if at end
+				c = parser.nextDarkChar();
+			}
+			String quote = parser.getString().substring(linePos,parser.getPosition()-1);  // saving entire quoted section  TODO: place in appropriate place
+			newData.setAnnotation(quote, false);
+		}
+		else {   //need to backtrack
+			parser.setPosition(parser.getPosition()-1);
+		}
+
+		int numTaxa = 0;
+		int numChars = 0;
+		token = parser.getNextToken();  // numchars
+		numChars = MesquiteInteger.fromString(token);
+		token = parser.getNextToken();  // numTaxa
+		numTaxa = MesquiteInteger.fromString(token);
+		boolean wassave = newData.saveChangeHistory;
+		newData.saveChangeHistory = false;
+		try {
+			taxa.addTaxa(-1, numTaxa, true);
+			newData.addParts(-1, numChars);
+		}
+		catch (OutOfMemoryError e){
+			MesquiteMessage.warnProgrammer("Sorry, the file could not be read (OutOfMemoryError).  See file memory.txt in the Mesquite_Folder.");
+			return null;
+		}
+
+		for (int it=0; it<numTaxa; it++) {
+			token = parser.getNextToken();
+			if (token == ";") 
+				return newData;
+			Taxon t = taxa.getTaxon(it);
+			if (t!=null) {
+				t.setName(token);
+				progIndicator.setText("Reading taxon: "+token);
+				for (int ic=0; ic<numChars; ic++) {
+					c=parser.nextDarkChar();
+					if (c==';' || c=='\0') 
+						return newData;
+					else {
+						if (c=='[') {
+							long set = 0;
+							c=parser.nextDarkChar();
+							while ((c!=']' && c!='\0')) {
+								long newSet;
+								if (newData instanceof DNAData || newData instanceof ProteinData)
+									newSet= newData.fromChar(c); 
+								else
+									newSet= newData.fromChar(TNTtoMesquite(c)); 
+								set |= newSet;
+								c=parser.nextDarkChar();
+						//		if (c=='[')  give warning
+									
+							}
+							newData.setState(ic, it, set);
+						}
+						else {
+							if (newData instanceof DNAData || newData instanceof ProteinData)
+								newData.setState(ic, it, c);     // setting state to that specified by character c
+							else
+								newData.setState(ic, it, TNTtoMesquite(c));     // setting state to that specified by character c
+						}
+					}
+				}
+			}
+		}
+		newData.saveChangeHistory = wassave;
+		newData.resetCellMetadata();
+		return newData;
+	}
+	/*As of 2. 73 recognizing different default symbol lists to eliminate different step counting when ordered and states span I and O.
+	 * */
+	static char TNTtoMesquite(char tnt){
+		if (tnt == 'I') return 'J';
+		if (tnt == 'J') return 'K';
+		if (tnt == 'K') return 'M';
+		if (tnt == 'L') return 'N';
+		if (tnt == 'M') return 'P';
+		if (tnt == 'N') return 'Q';
+		if (tnt == 'O') return 'R';
+		if (tnt == 'P') return 'S';
+		if (tnt == 'Q') return 'T';
+		if (tnt == 'R') return 'U';
+		if (tnt == 'S') return 'V';
+		if (tnt == 'T') return 'W';
+		if (tnt == 'U') return 'X';
+		if (tnt == 'V') return 'Y';
+		if (tnt == 'W') return 'Z';
+		if (tnt == 'X') return 'a';
+		if (tnt == 'Y') return 'b';
+		if (tnt == 'Z') return 'c';
+		if (tnt == 'a') return 'd';
+		if (tnt == 'b') return 'e';
+		if (tnt == 'c') return 'f';
+		if (tnt == 'd') return 'g';
+		if (tnt == 'e') return 'h';
+		if (tnt == 'f') return 'j';
+		if (tnt == 'g') return 'k';
+		if (tnt == 'h') return 'm';
+		if (tnt == 'i') return 'n';
+		if (tnt == 'j') return 'p';
+		if (tnt == 'k') return 'q';
+		if (tnt == 'l') return 'r';
+		if (tnt == 'm') return 's';
+		if (tnt == 'n') return 't';
+		if (tnt == 'o') return 'u';
+		if (tnt == 'p') return 'v';
+		if (tnt == 'q') return 'w';
+		if (tnt == 'r') return 'x';
+		if (tnt == 's') return 'y';
+		if (tnt == 't') return 'z';
+		return tnt;
+	}
+	
+	//takes state integer and yields TNT symbol
+	static char standardTNTSymbolForState(int s){
+		if (s == 0) return '0';
+		if (s == 1) return '1';
+		if (s == 2) return '2';
+		if (s == 3) return '3';
+		if (s == 4) return '4';
+		if (s == 5) return '5';
+		if (s == 6) return '6';
+		if (s == 7) return '7';
+		if (s == 8) return '8';
+		if (s == 9) return '9';
+		if (s == 10) return 'A';
+		if (s == 11) return 'B';
+		if (s == 12) return 'C';
+		if (s == 13) return 'D';
+		if (s == 14) return 'E';
+		if (s == 15) return 'F';
+		if (s == 16) return 'G';
+		if (s == 17) return 'H';
+		if (s == 18) return 'I';
+		if (s == 19) return 'J';
+		if (s == 20) return 'K';
+		if (s == 21) return 'L';
+		if (s == 22) return 'M';
+		if (s == 23) return 'N';
+		if (s == 24) return 'O';
+		if (s == 25) return 'P';
+		if (s == 26) return 'Q';
+		if (s == 27) return 'R';
+		if (s == 28) return 'S';
+		if (s == 29) return 'T';
+		if (s == 30) return 'U';
+		if (s == 31) return 'V';
+		if (s == 32) return 'W';
+		if (s == 33) return 'X';
+		if (s == 34) return 'Y';
+		if (s == 35) return 'Z';
+		if (s == 36) return 'a';
+		if (s == 37) return 'b';
+		if (s == 38) return 'c';
+		if (s == 39) return 'd';
+		if (s == 40) return 'e';
+		if (s == 41) return 'f';
+		if (s == 42) return 'g';
+		if (s == 43) return 'h';
+		if (s == 44) return 'i';
+		if (s == 45) return 'j';
+		if (s == 46) return 'k';
+		if (s == 47) return 'l';
+		if (s == 48) return 'm';
+		if (s == 49) return 'n';
+		if (s == 50) return 'o';
+		if (s == 51) return 'p';
+		if (s == 52) return 'q';
+		if (s == 53) return 'r';
+		if (s == 54) return 's';
+		if (s == 55) return 't';
+		return '?';
+	}
+	/*..........................................   ..................................................*/
+	/** returns string describing the state(s) of character ic in taxon it.  Uses default symbols, and uses separators 
+   		between states in polymorphic (andSep) or partially uncertain (orSep) taxa.  
+   		Uses leftBracket and rightBracket to bound entries with multiple symbols */
+	String statesToStringDefaultSymbols(CategoricalData data, int ic,int it, char leftBracket, char rightBracket, char andSep, char orSep){
+		long s =data.getState(ic, it);
+		char INAPPLICABLE = '-';
+		char UNASSIGNED = '?';
+		boolean first=true;
+		char sep = andSep;
+		if (CategoricalState.isUncertain(s))
+			sep = orSep;
+		String stateString="";
+		if (s==CategoricalState.inapplicable) 
+			return stateString+ INAPPLICABLE;
+		else if (s==CategoricalState.unassigned) 
+			return stateString+ UNASSIGNED; 
+		else if (CategoricalState.cardinality(s)>1) {
+			stateString = "" + leftBracket;
+			for (int e=0; e<=CategoricalState.maxCategoricalState; e++) {
+				if (CategoricalState.isElement(s,e)) {
+					if ((!first) && (sep!=Character.UNASSIGNED))
+						stateString+=sep;
+					stateString += standardTNTSymbolForState(e);
+					first = false;
+				}
+			}
+			stateString += rightBracket;
+			return stateString;
+		}
+		else
+			return stateString+standardTNTSymbolForState(CategoricalState.minimum(s));
+	}
+	/*.................................................................................................................*/
+	public void appendStateToBuffer(int ic, int it, StringBuffer outputBuffer, CategoricalData data){
+		if (ownerModule.isTNT()){
+			if (data instanceof MolecularData)
+				data.statesIntoStringBuffer(ic, it, outputBuffer, " ", "[", "]");
+			else 
+				outputBuffer.append(statesToStringDefaultSymbols(data, ic,it,'[',']', ' ', ' '));
+		}
+		else
+			outputBuffer.append(statesToStringDefaultSymbols(data, ic,it,'[',']',(char)Character.UNASSIGNED, (char)Character.UNASSIGNED));
+	}
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		CategoricalData data = (CategoricalData)charData;
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+
+		if (ownerModule.isTNT())
+			if (charData instanceof DNAData) 
+				outputBuffer.append("nstates dna;"+fileInterpreter.getLineEnding());
+			else if (charData instanceof ProteinData) 
+				outputBuffer.append("nstates prot;"+fileInterpreter.getLineEnding());
+		outputBuffer.append(getCommandName()+fileInterpreter.getLineEnding());
+		
+		
+		int numCharWrite = 0;
+/*		if (!fileInterpreter.writeExcludedCharacters)
+			numCharWrite =data.numCharsCurrentlyIncluded(fileInterpreter.writeOnlySelectedData);
+		else
+*/			numCharWrite = data.numberSelected(fileInterpreter.writeOnlySelectedData);
+		
+		
+		int countTaxa = 0;
+		for (int it = 0; it<numTaxa; it++)
+			if ((!fileInterpreter.writeOnlySelectedTaxa || taxa.getSelected(it)) && (fileInterpreter.writeTaxaWithAllMissing || data.hasDataForTaxon(it, fileInterpreter.writeExcludedCharacters)))
+				countTaxa++;
+		int numTaxaWrite = countTaxa;
+
+		outputBuffer.append(Integer.toString(numCharWrite)+" ");
+		outputBuffer.append(Integer.toString(numTaxaWrite)+fileInterpreter.getLineEnding());
+
+		for (int it = 0; it<numTaxa; it++){
+			if ((!fileInterpreter.writeOnlySelectedTaxa || taxa.getSelected(it)) && (fileInterpreter.writeTaxaWithAllMissing || data.hasDataForTaxon(it, fileInterpreter.writeExcludedCharacters))){
+				incrementAndUpdateProgIndicator(progIndicator,"Exporting data matrix");
+				outputBuffer.append(StringUtil.tokenize(taxa.getTaxonName(it),";") + "\t");
+				for (int ic = 0; ic<numChars; ic++) {
+					if (ownerModule.characterShouldBeIncluded(data, ic)){
+						if (ownerModule.getConvertGapsToMissing() && data.isInapplicable(ic, it))
+							outputBuffer.append("?");
+						else
+							appendStateToBuffer(ic, it, outputBuffer, data);
+					}
+				}
+				outputBuffer.append(fileInterpreter.getLineEnding());
+			}
+		}
+		outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+	}
+}
+/*========================================================*/
+
+
+/*.................................................................................................................*/
+class HennigDREAD extends HennigXDREAD {
+	public HennigDREAD (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "dread";
+	}
+	/*.................................................................................................................*/
+	public boolean readStartXDREAD(Parser parser){
+		String token = parser.getNextToken();
+		if (token==null || !token.equalsIgnoreCase("GAP")) {
+			ownerModule.logln("GAP subcommand could not be found.");
+			return false;
+		}
+		char c = parser.nextDarkChar();  // ? if treat gap as missing, or ; if treat as fifth base
+		token = parser.getNextToken();
+		if (token==null || !token.equalsIgnoreCase("MATCH")) {
+			ownerModule.logln("MATCH subcommand could not be found.");
+			return false;
+		}
+		c = parser.nextDarkChar();  //�� set matchchar to this, set matchcharon;
+		return true;
+	}
+	/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+	}
+}
+/*========================================================*/
+
+
+/*.................................................................................................................*/
+class HennigXREAD extends HennigXDREAD {
+	public HennigXREAD (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "xread";
+	}
+	/*.................................................................................................................*/
+	public boolean readStartXDREAD(Parser parser){
+		return true;
+	}
+	
+
+	/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		if (ownerModule.getFutureDataClass()==DNAData.class)
+			return charTask.newCharacterData(taxa, 0, DNAData.DATATYPENAME);  //
+		if (ownerModule.getFutureDataClass()==ProteinData.class)
+			return charTask.newCharacterData(taxa, 0, ProteinData.DATATYPENAME);  //
+		return charTask.newCharacterData(taxa, 0, CategoricalData.DATATYPENAME);  //
+	}
+
+}
+
+
+/*========================================================*/
+
+/*.................................................................................................................*/
+class HennigTREAD extends HennigNonaCommand {
+	public HennigTREAD (InterpretHennig86Base ownerModule, Parser parser){
+		super(ownerModule, parser);
+	}
+	/*.................................................................................................................*/
+	public boolean returnData(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  String getCommandName(){
+		return "tread";
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean readCommand(MesquiteProject mp, MesquiteFile file, ProgressIndicator progIndicator, CategoricalData data, Taxa taxa, String firstLine){
+		if (taxa == null)
+			taxa = mp.chooseTaxa(ownerModule.containerOfModule(), "Of what taxa are these trees composed?");
+		if (taxa == null){
+			ownerModule.discreetAlert("Sorry, you cannot read the tree block in this file because no corresponding block of taxa can be found.  Make sure you are linking or including this with a file that includes the block of taxa");
+			return false;
+		}
+
+		String content = firstLine.trim();
+		long totalLength = content.length();
+		String lowerLine = content.toLowerCase();
+		int treadpos = lowerLine.indexOf("tread"); //TODO: this is case sensitive!!!!
+		boolean startOfCommand = (treadpos>=0) ;
+		//line = line.substring(treadpos+5, line.length());
+		TreeVector trees = new TreeVector(taxa);
+		ProgressIndicator progress = null;
+		if (progIndicator==null) {
+			progress=new ProgressIndicator(mp,"Importing Trees "+ file.getName(), totalLength);
+			progress.start();
+		}
+
+
+		MesquiteTree tree = null;
+		MesquiteString quote = new MesquiteString();
+
+		Parser parser = new Parser();
+		parser.setString(content);
+		parser.setLineEndString("*");
+		String line = "";
+
+		((InterpretHennig86Base)ownerModule).resetTreeNumber();
+
+		while (!parser.atEnd()) {
+			line = parser.getRawNextDarkLine();
+			tree = null;
+			if (progIndicator==null) {
+				tree = ((InterpretHennig86Base)ownerModule).readTREAD(progress, taxa, line, false, quote, null, null);
+			}
+			else 
+				tree = ((InterpretHennig86Base)ownerModule).readTREAD(progIndicator, taxa, line, false, quote, null, null);
+			if (tree!=null)
+				trees.addElement(tree, false);
+		}
+
+
+		/*		Parser treeParser;
+		treeParser =  new Parser();
+		treeParser.setQuoteCharacter((char)0);
+		String token;
+		String quote = null;
+		char c;
+		int linePos;
+		parser.setString(line);
+		int counter = 0;
+
+
+		while (!StringUtil.blank(line)) {
+			parser.setString(line);
+			c = parser.nextDarkChar();
+			if ((counter==0) && (c=='\'' && c!='\0'))  {   // we have a leading quote in the TREAD command
+				linePos = parser.getPosition();
+				c = parser.nextDarkChar();
+				while (c!='\'' && c!='\0') {
+					c = parser.nextDarkChar();
+				}
+				quote = line.substring(linePos,parser.getPosition()-1);  // saving entire quoted section  TODO: place in trees block
+				line = line.substring(parser.getPosition()+1, line.length());  // removing first quote
+				parser.setString(line);
+				//parser.setPosition(0);
+			}	
+			if (progIndicator==null) {
+				progress.setCurrentValue(totalLength-line.length());
+				progress.setText("Reading tree " + (++counter));
+			}
+			else
+				progIndicator.setText("Reading tree " + (++counter));
+
+			if (c==';' || c=='\0') {
+				return true;
+			}
+			else {    // info for this tree
+				int star = line.indexOf("*");
+				String treeDescription = null;
+				if (star>0) {
+					treeDescription = line.substring(0, star);
+					line = line.substring(star+1, line.length());
+				}
+				else  {
+					treeDescription = line;
+					line = null;
+				}
+				if (!StringUtil.blank(treeDescription) && treeDescription.indexOf("(")>=0){
+					if (trees == null) {
+						trees = new TreeVector(taxa);
+						trees.setName("Imported trees");
+						if (quote != null)
+							trees.setAnnotation(quote, false);
+					}
+					MesquiteTree t = new MesquiteTree(taxa);
+					MesquiteInteger pos = new MesquiteInteger(0);
+					treeParser.setString(treeDescription);
+					((InterpretNonaHennig)ownerModule).readClade(t, t.getRoot(), treeParser);
+					t.setAsDefined(true);
+					t.setName("Imported tree " + counter);
+					trees.addElement(t, false);
+				}
+			}
+		}
+		 */
+
+		if (trees != null) {
+			trees.setName("Imported trees");
+			if (quote != null)
+				trees.setAnnotation(quote.getValue(), false);
+		}
+
+		if (trees!=null)
+			trees.addToFile(file,file.getProject(),ownerModule.findElementManager(TreeVector.class));
+		if (progress!=null) 
+			progress.goAway();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void appendCommandToStringBuffer(StringBuffer outputBuffer, Taxa taxa, CharacterData charData, ProgressIndicator progIndicator){
+		Listable[] treeVectors = fileInterpreter.getProject().getCompatibleFileElements(TreeVector.class, taxa);
+		TreeVector treeVector;
+		if (treeVectors.length==0)
+			return;
+		if (treeVectors.length==1)
+			treeVector = (TreeVector)treeVectors[0];
+		else
+			treeVector = (TreeVector)ListDialog.queryList(fileInterpreter.containerOfModule(), "Include trees in file?", "Include trees in file?", MesquiteString.helpString, treeVectors, 0);
+		Tree tree;
+		if (treeVector !=null && treeVector.size()>0) {
+			outputBuffer.append(getCommandName()+fileInterpreter.getLineEnding());
+			for (int iTree = 0; iTree < treeVector.size(); iTree++) {
+				tree = (Tree)treeVector.elementAt(iTree);
+				outputBuffer.append(tree.writeTreeSimple(Tree.BY_NUMBERS, false, false, false, true, null));  //or Tree.BY_NUMBERS  or Tree.BY_NAMES
+				// if do it BY_NAMES, make sure you truncate the taxon names to 10 characters!!
+				outputBuffer.append("*"+fileInterpreter.getLineEnding());
+			}
+			outputBuffer.append(";"+ fileInterpreter.getLineEnding()+ fileInterpreter.getLineEnding());
+		}
+
+	}
+}
+
+
+
diff --git a/Source/mesquite/io/lib/InterpretNBRF.java b/Source/mesquite/io/lib/InterpretNBRF.java
new file mode 100644
index 0000000..d502245
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretNBRF.java
@@ -0,0 +1,358 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* 
+
+- make more things protected
+- document classes, add doc target to project (use mesquite.lib for example).
+- scripting
+
+general exporting stuff:
+	- tokenize properly
+
+general importing stuff
+	- set punctuation on read in, including single quotes
+	- set reading to not consider [ ], or to consider different comment tokens
+*/
+
+/* 
+Post version 1.0:
+	- verbose file reading
+	- on reading, store comment line as footnote
+*/
+
+/* ============  a file interpreter for NBRF files ============*/
+/** This is the class for interpreting NBRF/PIR files.  It is subclassed to make interpreters specifically for
+DNA and Protein files. */
+public abstract class InterpretNBRF extends FileInterpreterI implements ReadFileFromString {
+	Class[] acceptedClasses;
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		acceptedClasses = new Class[] {ProteinState.class, DNAState.class};
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(acceptedClasses) > 0;  //
+	}
+	
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		 for (int i = 0; i<acceptedClasses.length; i++)
+		 	if (dataClass==acceptedClasses[i])
+		 		return true;
+		 return false; 
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return true;
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments){
+		return true;
+	}
+
+/*.................................................................................................................*/
+	public abstract void setNBRFState(CharacterData data, int ic, int it, char c);
+/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+
+	/*.................................................................................................................*/
+	public void readFileCore(Parser parser, MesquiteFile file, CharacterData data, Taxa taxa, int numTaxa, ProgressIndicator progIndicator, String arguments) {
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			Parser subParser = new Parser();
+
+			StringBuffer sb = new StringBuffer(1000);
+			if (file!=null)
+				file.readLine(sb);
+			else
+				sb.append(parser.getRawNextLine());
+			String line = sb.toString();
+			
+			boolean abort = false;
+			while (!StringUtil.blank(line) && !abort) {
+				subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				
+				subParser.setPunctuationString(";");
+				String token = subParser.getFirstToken(line); //should be >DL
+				char c = subParser.nextDarkChar();      // should be a semicolon
+				subParser.setPunctuationString(null);
+				parser.setPunctuationString(null);
+				
+				token = subParser.getNextToken();  //taxon Name
+				taxa.addTaxa(numTaxa-1, 1, false);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED), CharacterData.class, true);
+				Taxon t = taxa.getTaxon(numTaxa);
+				
+				if (t!=null) {
+					t.setName(token);
+					progIndicator.setText("Reading taxon: "+token);
+					if (file!=null)
+						file.readLine(sb);  // skip over comment line
+					else {
+						sb.setLength(0);
+						sb.append(parser.getRawNextLine());
+					}
+					line = sb.toString();
+					if (line==null) break;
+					if (file!=null)
+						line = file.readLine("*");  // pull in sequence
+					else
+						line = parser.getRemainingUntilChar('*', true);
+					if (line==null) break;
+					subParser.setString(line); 
+					int ic = 0;
+					while (subParser.getPosition()<line.length()) {
+						c=subParser.nextDarkChar();
+						if (c!='*' && c!= '\0') {
+							if (data.getNumChars() <= ic) {
+								data.addCharacters(data.getNumChars()-1, 1, false);   // add a character if needed
+								data.addInLinked(data.getNumChars()-1, 1, false);
+							}
+							//data.setState(ic, numTaxa, c);    // setting state to that specified by character c
+							setNBRFState(data,ic, numTaxa, c);    // setting state to that specified by character c
+						}
+						ic += 1;
+					}
+				}
+				numTaxa++;
+				if (file!=null)
+					line = file.readNextDarkLine();		// added 1.01
+				else
+					line = parser.getRawNextDarkLine();
+				if (file !=null && file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+	}
+	
+	/** readFileFromString takes the NBRF-formated string "contents" and pumps it into the CharacterData data.  This method is required for the ReadFileFromString interface */
+	/*.................................................................................................................*/
+	public void readFileFromString(CharacterData data, Taxa taxa, String contents, String arguments) {
+		MesquiteProject mf = getProject();
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing Sequences ", contents.length());
+		progIndicator.start();
+		String fRA = parser.getFirstToken(arguments);
+		while (!StringUtil.blank(fRA)) {
+			fRA = parser.getNextToken();
+		}
+		int numTaxa = taxa.getNumTaxa();
+		parser.setString(contents);
+		readFileCore(parser, null, data,  taxa, numTaxa, progIndicator, arguments);	
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+
+		decrementMenuResetSuppression();
+	}
+
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		boolean fuse = parser.hasFileReadingArgument(arguments, "fuseTaxaCharBlocks");
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			 CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+
+			Taxa taxa = null;
+			if (fuse){
+				String message = "There is a taxa block in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this imported taxa block into the taxa block you select below, or it will import that taxa block as new, separate taxa block.";
+				taxa = getProject().chooseTaxa(containerOfModule(), message, true, "Fuse with Selected Taxa Block", "Add as New Taxa Block");
+			}
+			
+			if (taxa == null){
+				taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+				taxa.addToFile(file, getProject(), taxaTask);
+			}
+			CategoricalData data = null;
+			if (fuse){
+				String message = "There is a matrix in the file \"" + file.getName() + "\" being imported. Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+				data = (CategoricalData)getProject().chooseData(containerOfModule(), null, taxa, CategoricalState.class, message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+			}
+			if (data == null){
+				data =(CategoricalData)createData(charTask,taxa);
+				data.addToFile(file, getProject(), null);
+			}
+
+			int numTaxa = 0;
+			if (fuse)
+				numTaxa = taxa.getNumTaxa();
+
+			readFileCore(parser, file, data,  taxa, numTaxa, progIndicator, arguments);
+		}
+		decrementMenuResetSuppression();
+	}
+	
+
+
+/* ============================  exporting ============================*/
+	boolean includeGaps = false;
+	boolean excludeEmpty = false;
+	/*.................................................................................................................*/
+	
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export NBRF Options", buttonPressed);
+		
+		Checkbox includeGapsCheckBox = exportDialog.addCheckBox("include gaps", includeGaps);
+		Checkbox excludeEmptyCheckBox = exportDialog.addCheckBox("exclude empty sequences", suppressAllGapTaxa);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		suppressAllGapTaxa = excludeEmptyCheckBox.getState();
+		
+		includeGaps = includeGapsCheckBox.getState();
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+	
+	public boolean getExportOptionsSimple(boolean dataSelected, boolean taxaSelected){   // an example of a simple query, that only proved line delimiter choice; not used here
+		return (ExporterDialog.query(this,containerOfModule(), "Export NBRF Options")==0);
+	}	
+	
+	/*.................................................................................................................*/
+	public String getLineStart(){  
+		return ">DL; ";
+	}	
+	/*.................................................................................................................*/
+	public abstract CharacterData findDataToExport(MesquiteFile file, String arguments);
+	/*.................................................................................................................*/
+	public StringBuffer getDataAsFileText(MesquiteFile file, CharacterData data) {
+		if (data==null)
+			return null;
+		Taxa taxa = data.getTaxa();
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+		boolean wroteMoreThanOneSymbol = false;
+		
+		int counter = 1;
+		for (int it = 0; it<numTaxa; it++){
+			if ((!writeOnlySelectedTaxa || (taxa.getSelected(it))) && (!suppressAllGapTaxa || !taxonEntirelyInapplicable(it, data))) {
+			// TO DO: also have the option of only writing taxa with data in them
+				counter = 1;
+				outputBuffer.append(getLineStart());
+				outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)) + getLineEnding());
+				outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)) + getLineEnding());
+				for (int ic = 0; ic<numChars; ic++) {
+					if (!writeOnlySelectedData || (data.getSelected(ic))){
+						int currentSize = outputBuffer.length();
+
+						wroteMoreThanOneSymbol = false;
+						if (includeGaps || (!data.isInapplicable(ic,it))) {
+								if (data.isUnassigned(ic,it))
+									outputBuffer.append("X");
+								else
+									data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+								wroteMoreThanOneSymbol = outputBuffer.length()-currentSize>1;
+								counter ++;
+								if ((counter % 50 == 1) && (counter > 1)) {    // modulo
+									outputBuffer.append(getLineEnding());
+								}
+						}
+						if (wroteMoreThanOneSymbol) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return null;
+						}
+					}
+				}
+				outputBuffer.append("*" + getLineEnding());
+			}
+		}
+		return outputBuffer;
+	}
+   	/** returns whether the character ic is entirely inapplicable codings*/
+   	public boolean taxonEntirelyInapplicable(int it, CharacterData data){
+   		for (int ic = 0; ic< data.getNumChars(); ic++)
+   			if (!data.isInapplicable(ic, it))
+   				return false;
+   		return true;
+   	}
+	boolean suppressAllGapTaxa = false;
+	boolean oldIncludeGaps = false;
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+		oldIncludeGaps = includeGaps;
+		suppressAllGapTaxa = args.parameterExists("suppressAllGapTaxa");
+
+		CharacterData data = findDataToExport(file, arguments);
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		writeOnlySelectedData = args.parameterExists("writeOnlySelectedData");
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected(), taxa.anySelected()))
+				return false;
+		
+		if (args.parameterExists("includeGaps"))
+			includeGaps = true;
+
+		StringBuffer outputBuffer = getDataAsFileText(file, data);
+		includeGaps = oldIncludeGaps;
+		
+		if (outputBuffer==null) {
+			return false;
+		}
+		
+		saveExportedFileWithExtension(outputBuffer, arguments, "nbrf");
+		suppressAllGapTaxa = false;
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "NBRF/PIR file";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports NBRF files that consist of molecular sequence data." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+
+   	 
+}
+	
+
diff --git a/Source/mesquite/io/lib/InterpretPhylip.java b/Source/mesquite/io/lib/InterpretPhylip.java
new file mode 100644
index 0000000..8a3507c
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretPhylip.java
@@ -0,0 +1,606 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modifications:
+28 July 01 (WPM): checked for treeVector == null on export & used getCompatibleFileElements
+*/
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+//TODO:   have option to not write empty taxa?
+
+/* ============  a file interpreter for Phylip files ============*/
+
+public abstract class InterpretPhylip extends FileInterpreterITree {
+	Class[] acceptedClasses;
+	TreeVector treeVector = null;
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		acceptedClasses = new Class[] {ProteinState.class, DNAState.class, CategoricalState.class};
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public boolean initializeExport(Taxa taxa) {  
+		 return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean initializeTreeImport(MesquiteFile file, Taxa taxa) {  
+		 return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberCharMatrices(acceptedClasses) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		 for (int i = 0; i<acceptedClasses.length; i++)
+		 	if (dataClass==acceptedClasses[i])
+		 		return true;
+		 return false; 
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return true;
+	}
+/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+/*.................................................................................................................*/
+	boolean previousInterleaved = false;
+	public boolean getInterleaved(){
+		if (okToInteractWithUser(CAN_PROCEED_ANYWAY, "Asking about interleave")){
+			previousInterleaved = AlertDialog.query(module.containerOfModule(), "Interleaved or sequential?", "Is the matrix interleaved or sequential?", "Interleaved", "Sequential");
+		}
+		return previousInterleaved;
+	}	
+/*.................................................................................................................*/
+	public abstract void setPhylipState(CharacterData data, int ic, int it, char c);
+/*...............................................  read tree ....................................................*
+	/** Continues reading a tree description, starting at node "node" and the given location on the string*
+	private boolean readClade(MesquiteTree tree, int node) {
+			
+		String c = treeParser.getNextToken();
+		c = c.trim();
+		if (",".equals(c)) {
+			c = treeParser.getNextToken();
+			c = c.trim();
+		}
+		if ("(".equals(c)){  //internal node
+			int sprouted = tree.sproutDaughter(node, false);
+			readClade(tree, sprouted);
+			boolean keepGoing = true;
+			while (keepGoing) {
+				int loc = treeParser.getPosition();
+				String next = treeParser.getNextToken();
+				if (",".equals(next)) 
+					next = treeParser.getNextToken();
+				if (")".equals(next))
+					keepGoing = false;
+				else {
+					treeParser.setPosition(loc);
+					sprouted = tree.sproutDaughter(node, false);
+					keepGoing = readClade(tree, sprouted);
+				}
+			}
+			return true;
+		}
+		else if (")".equals(c)) {
+			return false;
+		}
+	  	else {
+			int taxonNumber = tree.getTaxa().whichTaxonNumber(c);
+			if (taxonNumber >=0){ //taxon successfully found
+				if (tree.nodeOfTaxonNumber(taxonNumber)<=0){  // first time taxon encountered
+					tree.setTaxonNumber(node, taxonNumber, false);
+				 	return true;
+				 }
+			 }
+			return false;
+	  	}
+	  	
+	}
+	
+	
+	
+/*.................................................................................................................*/
+	public TreeVector readPhylipTrees (MesquiteProject mf, MesquiteFile file, String line, ProgressIndicator progIndicator, Taxa taxa) {
+		return IOUtil.readPhylipTrees(this,mf, file, line, progIndicator, taxa, false, null, getTreeNameBase(), true);
+	}	
+	
+	public void setTaxonNameLength(int value) {
+		taxonNameLength = value;
+	}
+	
+	public String getTreeNameBase () {
+		return "Imported tree ";
+	}
+/*.................................................................................................................*/
+	public void readTreeFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		Taxa taxa = getProject().chooseTaxa(containerOfModule(), "Of what taxa are these trees composed?");
+		if (taxa== null) 
+			return;
+/*
+		treeVector = new TreeVector(taxa);
+		String name;
+		for (int it=0; it<taxa.getNumTaxa(); it++) {
+			name = taxa.getTaxonName(it);
+			if (name.length()>10)
+				treeVector.setTranslationLabel(name.substring(0,9), name, false);
+			else
+				treeVector.setTranslationLabel(name, name, false);
+		}
+*/
+		incrementMenuResetSuppression();
+		//file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			String line = file.readNextDarkLine();		
+			readPhylipTrees(mf, file, line, null, taxa);
+			finishImport(null, file, false );
+		}
+		decrementMenuResetSuppression();
+	}
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		boolean interleaved = getInterleaved();
+		
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			 CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+			
+			Taxa taxa = taxaTask.makeNewTaxa("Taxa", 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CategoricalData data = (CategoricalData)createData(charTask,taxa);
+			data.addToFile(file, getProject(), null);
+			
+			String token;
+			char c;
+			int numTaxa = 0;
+			int numChars = 0;
+
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+			parser.setString(line); 
+
+			token = parser.getNextToken();  // numTaxa
+			numTaxa = MesquiteInteger.fromString(token, "Mesquite does not currently accept PHYLIP files with options included at the top of the file", false,true);
+			if (numTaxa==MesquiteInteger.impossible) {
+				progIndicator.goAway();
+				file.close();
+				decrementMenuResetSuppression();
+				return;
+			}
+
+			token = parser.getNextToken();  // numchars
+			numChars = MesquiteInteger.fromString(token, "Mesquite does not currently accept PHYLIP files with options included at the top of the file", false,true);
+			if (numChars==MesquiteInteger.impossible) {
+				progIndicator.goAway();
+				file.close();
+				decrementMenuResetSuppression();
+				return;
+			}
+
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+			taxa.addTaxa(-1, numTaxa, true);
+			data.addCharacters(-1, numChars, false);
+			line = file.readNextDarkLine();   // reads first data line
+			
+			boolean abort = false;
+			int block = 1;
+			int it=0;
+			int nextCharToRead = 0;
+	// first block
+			while (!StringUtil.blank(line) && !abort && (it<numTaxa)) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+				token = "";
+				for (int taxonNameChar=0; taxonNameChar<120; taxonNameChar++) {  //no longer assumes standard 10-character taxon names; uses whitespace to find name
+					c=parser.getNextChar();
+					if (c=='\0' || StringUtil.whitespace(c, null))
+						break;
+					token+=c;
+				}
+				Taxon t = taxa.getTaxon(it);
+				if (t!=null) {
+					if (interleaved)
+						progIndicator.setText("Reading block " + block + ", taxon "+it );
+					else
+						progIndicator.setText("Reading taxon "+it );
+					t.setName(StringUtil.deTokenize(token).trim());
+					for (int ic=0; ic<numChars; ic++) {
+						c=parser.nextDarkChar();
+						if (c=='\0') {
+							if ((!interleaved) && (ic<numChars)){
+								line = file.readNextDarkLine();	
+								parser.setString(line);
+							}
+							else
+								break;
+						}
+						setPhylipState(data, ic, it, c);
+						if (it==0)
+							nextCharToRead++;
+					}
+				}
+				it++;
+				line = file.readNextDarkLine();		
+				if (file.getFileAborted())
+					abort = true;
+			}
+
+// later blocks
+			if ((interleaved) && (!abort)) {
+				int startChar;
+				while (!StringUtil.blank(line) && !abort && (nextCharToRead<=numChars)) {
+					block++;
+					startChar=nextCharToRead;
+					it=0;
+					while (!StringUtil.blank(line) && !abort && (it<numTaxa)) {
+						parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+						Taxon t = taxa.getTaxon(it);
+						if (t!=null) {
+							progIndicator.setText("Reading block " + block + ", taxon "+it );
+							for (int ic=startChar; ic<numChars; ic++) {
+								c=parser.nextDarkChar();
+								if (c=='\0')
+									break;
+								setPhylipState(data,ic, it, c);
+								if (it==0)
+									nextCharToRead++;
+							}
+						}
+						it++;
+						line = file.readNextDarkLine();		
+						if (file.getFileAborted())
+							abort = true;
+					}
+				}
+			}
+			
+			if (!StringUtil.blank(line)) // then we have trees
+				readPhylipTrees(mf, file, line, progIndicator, taxa);
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+	
+
+
+/* ============================  exporting ============================*/
+	public boolean exportInterleaved=false;
+	public boolean exportTrees=true;
+	public boolean localWriteExcludedChars = true;
+	public boolean userSpecifiedWriteExcludedChars = false;
+	
+	/*.................................................................................................................*/
+	protected int taxonNameLength = 10;
+	protected TaxonNamer taxonNamer = null;
+	
+	public void setTaxonNamer(TaxonNamer namer) {
+		this.taxonNamer = namer;
+	}
+
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		PhylipExporterDialog exportDialog = new PhylipExporterDialog(this,containerOfModule(), "Export Phylip Options", buttonPressed);
+		
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		if (ok)
+			taxonNameLength = exportDialog.getTaxonNamesLength();
+		exportDialog.dispose();
+		return ok;
+	}	
+	TreeVector previousVector;
+	/*.................................................................................................................*/
+	public abstract CharacterData findDataToExport(MesquiteFile file, String arguments);
+	/*.................................................................................................................*/
+	public TreeVector findTreesToExport(MesquiteFile file, Taxa taxa, String arguments, boolean usePrevious){
+		if (usePrevious)
+			return previousVector;
+		Listable[] treeVectors = getProject().getCompatibleFileElements(TreeVector.class, taxa);
+		TreeVector treeVector;
+		if (treeVectors.length==0)
+			return null;
+		if (treeVectors.length==1)
+			treeVector = (TreeVector)treeVectors[0];
+		else
+			treeVector = (TreeVector)ListDialog.queryList(containerOfModule(), "Include trees in file?", "Include trees in file?", MesquiteString.helpString, treeVectors, 0);
+		previousVector = treeVector;
+		return treeVector;
+	}
+	/*.................................................................................................................*/
+	public abstract void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer) ;
+	/*.................................................................................................................*/
+	protected void exportTrees(Taxa taxa, TreeVector treeVector, StringBuffer outputBuffer) { 
+		Tree tree;
+		if (treeVector !=null && treeVector.size()>0) {
+			outputBuffer.append(""+treeVector.size() + getLineEnding());
+			for (int iTree = 0; iTree < treeVector.size(); iTree++) {
+				tree = (Tree)treeVector.elementAt(iTree);
+				outputBuffer.append(tree.writeTree(Tree.BY_NUMBERS));  //or Tree.BY_NUMBERS  or Tree.BY_NAMES
+				// if do it BY_NAMES, make sure you truncate the taxon names to 10 characters!!
+				outputBuffer.append(getLineEnding());
+			}
+		}
+	}
+	int charWritten = 0;
+	/*.................................................................................................................*/
+	public void exportBlock(Taxa taxa, CharacterData data, StringBuffer outputBuffer, int startChar, int blockSize, boolean writeTaxonNames) { 
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		int counter;
+		String pad = "          ";
+		while (pad.length() < taxonNameLength)
+			pad += "  ";
+		
+		for (int it = 0; it<numTaxa; it++){
+			if ((!writeOnlySelectedTaxa || taxa.getSelected(it)) && (writeTaxaWithAllMissing || data.hasDataForTaxon(it, writeExcludedCharacters))){
+				if (writeTaxonNames) {   // first block
+					String name = "";
+					if (taxonNamer!=null)
+						name = taxonNamer.getNameToUse(taxa,it)+pad;
+					else
+						name = (taxa.getTaxonName(it)+ pad);
+					name = name.substring(0,taxonNameLength);
+					name = StringUtil.blanksToUnderline(StringUtil.stripTrailingWhitespace(name));
+					
+					outputBuffer.append(name);
+				//	if (taxonNameLength>name.length())
+						for (int i=0;i<taxonNameLength-name.length()+1; i++)
+						outputBuffer.append(" ");
+				}
+				//outputBuffer.append(" ");
+				counter = 1;
+				for (int ic = startChar; ic<numChars; ic++) {
+					if ((!writeOnlySelectedData || (data.getSelected(ic))) && (writeExcludedCharacters || data.isCurrentlyIncluded(ic))){
+						int currentSize = outputBuffer.length();
+						appendPhylipStateToBuffer(data, ic, it, outputBuffer);
+						if (it==0)
+							charWritten++;
+						if (outputBuffer.length()-currentSize>1) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return;
+						}
+						if (counter>=blockSize)
+							break;
+						counter++;
+					}
+				}
+				outputBuffer.append(getLineEnding());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+ 	public  StringBuffer getDataAsFileText(MesquiteFile file, CharacterData data) {
+		if (data==null)
+			return null;
+		Taxa taxa = data.getTaxa();
+		initializeExport(taxa);
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		if (file != null){
+			writeTaxaWithAllMissing = file.writeTaxaWithAllMissing;
+			writeExcludedCharacters = file.writeExcludedCharacters;
+		}
+		int countTaxa = 0;
+		for (int it = 0; it<numTaxa; it++)
+			if ((!writeOnlySelectedTaxa || taxa.getSelected(it)) && (writeTaxaWithAllMissing || data.hasDataForTaxon(it, writeExcludedCharacters)))
+				countTaxa++;
+		numTaxa = countTaxa;
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+
+		outputBuffer.append(Integer.toString(numTaxa)+" ");
+
+		if (!writeExcludedCharacters)
+			outputBuffer.append(Integer.toString(data.getNumCharsIncluded())+this.getLineEnding());		
+		else
+			outputBuffer.append(Integer.toString(numChars)+this.getLineEnding());		
+
+		exportBlock(taxa, data, outputBuffer, 0, numChars, true);
+		return outputBuffer;
+	}
+	/*.................................................................................................................*/
+ 	public boolean exportMultipleMatrices(){
+ 		return false;
+ 	}
+	/*.................................................................................................................*/
+ 	public void setExportTrees(boolean exportTrees){
+ 		this.exportTrees = exportTrees;
+ 	}
+	/*.................................................................................................................*/
+ 	public boolean getExportTrees(){
+ 		return exportTrees;
+ 	}
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		CharacterData data = null;
+		int numMatrices =1;
+		
+		Taxa t = null;
+		Taxa taxa = null;
+		if (exportMultipleMatrices()) {
+			//data = findDataToExport(file, arguments);
+			t = getProject().chooseTaxa(containerOfModule(), "Select taxa to export", false);
+			numMatrices = getProject().getNumberCharMatricesVisible(CategoricalState.class);
+			data = getProject().getCharacterMatrixVisible(t, 0, CategoricalState.class);
+			taxa = data.getTaxa();
+		} else {
+			data = findDataToExport(file, arguments);
+			if (data != null){
+				t = data.getTaxa();
+				taxa = data.getTaxa();
+			}
+
+		}
+		boolean dataAnySelected = false;
+		if (data != null)
+			dataAnySelected =data.anySelected();
+		boolean taxaAnySelected = false;
+		if (taxa !=null)
+			taxaAnySelected= taxa.anySelected();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(dataAnySelected, taxaAnySelected))  // querying about options
+				return false;
+
+		if (userSpecifiedWriteExcludedChars) {
+			file.writeExcludedCharacters= localWriteExcludedChars;
+			writeExcludedCharacters = localWriteExcludedChars;
+		}
+		userSpecifiedWriteExcludedChars= false;
+
+		TreeVector trees = null;
+		if (getExportTrees()) {
+			trees = findTreesToExport(file, t, arguments, usePrevious);
+		}
+		if (data ==null && trees == null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data or trees available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		StringBuffer outputBuffer = new StringBuffer(100);
+		int numCharWrite=0;
+		boolean firstTimeThrough = true;
+		initializeExport(taxa);
+
+		if (data!=null) {
+			for (int im = 0; im<numMatrices; im++) {
+				if (exportMultipleMatrices()) {
+					data = getProject().getCharacterMatrixVisible(t, im, CategoricalState.class);
+					if (data==null) continue;
+				} 
+				if (!writeExcludedCharacters){
+					numCharWrite +=  data.numCharsCurrentlyIncluded(this.writeOnlySelectedData);
+				} else {
+					numCharWrite +=  data.numberSelected(this.writeOnlySelectedData);
+				}
+			}
+		}
+		charWritten=0;
+
+		for (int im = 0; im<numMatrices; im++) {
+			if (exportMultipleMatrices()) {
+				data = getProject().getCharacterMatrixVisible(t, im, CategoricalState.class);
+				if (data==null) continue;
+			}
+			if (data == null && getExportTrees())
+				taxa = trees.getTaxa();
+			int numTaxa = taxa.getNumTaxa();
+
+			int numTaxaWrite;
+			int countTaxa = 0;
+			for (int it = 0; it<numTaxa; it++)
+				if ((!writeOnlySelectedTaxa || taxa.getSelected(it)) && (writeTaxaWithAllMissing || (data!=null && data.hasDataForTaxon(it))))
+					countTaxa++;
+			numTaxaWrite = countTaxa;
+
+			int numChars = 0;
+
+			
+			if (data != null){
+				numChars = data.getNumChars();
+				if (firstTimeThrough) {
+					outputBuffer.append(Integer.toString(numTaxaWrite)+" ");
+					outputBuffer.append(Integer.toString(numCharWrite)+this.getLineEnding());
+				}
+				int blockSize=50;
+
+				if (exportInterleaved || exportMultipleMatrices()){
+					int ic = 0;
+					while (ic<numChars) {
+						int endChar = ic+blockSize;
+						int count=0;
+						boolean blockWritten = false;
+						for (int ic2=ic; ic2<numChars && !blockWritten; ic2++) {
+							if ((this.writeExcludedCharacters || data.isCurrentlyIncluded(ic2)) && (!this.writeOnlySelectedData || data.getSelected(ic2))){  // this character needs to be written
+								count++;
+								if (count==blockSize || ic2==numChars-1){
+									endChar = ic2;
+									exportBlock(taxa, data, outputBuffer, ic, blockSize, firstTimeThrough);
+									outputBuffer.append(getLineEnding());
+									ic=endChar+1;
+									blockWritten=true;
+									firstTimeThrough = false;
+								}
+							} else {
+								if (ic2==numChars-1 && !blockWritten){  //at end
+									endChar = ic2;
+									if (count>0){  //only write if there is something to write
+										exportBlock(taxa, data, outputBuffer, ic, blockSize, firstTimeThrough);
+										outputBuffer.append(getLineEnding());
+										firstTimeThrough = false;
+									}
+									ic=endChar+1;
+									blockWritten=true;
+								}
+							}
+						}
+					}
+				}
+				else
+					exportBlock(taxa, data, outputBuffer, 0, numChars, true);
+			}
+		}
+		if (charWritten!=numCharWrite)
+			MesquiteMessage.warnProgrammer("Warning: the number of characters written does not match expectation.");
+		
+
+		
+		if (trees!=null)
+			exportTrees(taxa, trees, outputBuffer);
+		
+		saveExportedFileWithExtension(outputBuffer, arguments, "phy");
+		writeExtraFiles(taxa);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void writeExtraFiles(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Phylip file";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports Phylip files." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+
diff --git a/Source/mesquite/io/lib/InterpretPhylipTrees.java b/Source/mesquite/io/lib/InterpretPhylipTrees.java
new file mode 100644
index 0000000..7fd257f
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretPhylipTrees.java
@@ -0,0 +1,109 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.io.lib.*;
+
+
+/* ============  a file interpreter for phylip trees ============*/
+
+public abstract class InterpretPhylipTrees extends InterpretPhylip {
+/*.................................................................................................................*/
+	public void setPhylipState(CharacterData data, int ic, int it, char c){
+		//only deals with trees
+	}
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		readTreeFile( mf,  file,  arguments);
+	}
+/*........................../*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		 return project.getNumberOfFileElements(TreeVector.class) > 0;  //
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return false;
+	}
+/*.................................................................................................................*/
+	public CharacterData createData(CharactersManager charTask, Taxa taxa) {  
+		 return null;  //
+	}
+/*.................................................................................................................*/
+	public void appendPhylipStateToBuffer(CharacterData data, int ic, int it, StringBuffer outputBuffer){
+		//
+	}
+/*.................................................................................................................*/
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		return true;
+	}	
+/*.................................................................................................................*/
+	public CharacterData findDataToExport(MesquiteFile file, String arguments) { 
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean importExtraFiles(MesquiteFile file, Taxa taxa, TreeVector trees) {  
+		 return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+/*.................................................................................................................*/
+	public void readTreeFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		boolean enlargeTaxaBlock = false;
+		Taxa taxa = getProject().chooseTaxa(containerOfModule(), "From what taxa are these trees composed?");
+		if (taxa== null) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			taxa = taxaTask.makeNewTaxa("Taxa", 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			enlargeTaxaBlock = true;
+		}
+		incrementMenuResetSuppression();
+		if (file.openReading()) {
+			initializeTreeImport(file, taxa);
+			TreeVector trees = IOUtil.readPhylipTrees(this,mf, file, null, null, taxa, enlargeTaxaBlock, taxonNamer,getTreeNameBase(), true);
+			importExtraFiles(file,taxa, trees);
+			finishImport(null, file, false );
+		}
+		decrementMenuResetSuppression();
+	}
+	/*.................................................................................................................*/
+	protected void exportTrees(Taxa taxa, TreeVector treeVector, StringBuffer outputBuffer) { 
+		Tree tree;
+		if (treeVector !=null && treeVector.size()>0) {
+			for (int iTree = 0; iTree < treeVector.size(); iTree++) {
+				tree = (Tree)treeVector.elementAt(iTree);
+				outputBuffer.append(tree.writeTreeSimpleByNames());  //or Tree.BY_NUMBERS  or Tree.BY_NAMES
+				// if do it BY_NAMES, make sure you truncate the taxon names to 10 characters!!
+				outputBuffer.append(getLineEnding());
+			}
+		}
+	}
+
+ 	 
+}
+	
+
diff --git a/Source/mesquite/io/lib/InterpretSimple.java b/Source/mesquite/io/lib/InterpretSimple.java
new file mode 100644
index 0000000..f4944fa
--- /dev/null
+++ b/Source/mesquite/io/lib/InterpretSimple.java
@@ -0,0 +1,254 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+/* ============  a file interpreter for Simple Text files ============*/
+
+public abstract class InterpretSimple extends FileInterpreterI {
+	Class[] acceptedClasses;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		acceptedClasses = new Class[] {ProteinState.class, DNAState.class, CategoricalState.class, ContinuousState.class, GeographicState.class};
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return project.getNumberCharMatrices(acceptedClasses) > 0;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		for (int i = 0; i<acceptedClasses.length; i++)
+			if (dataClass==acceptedClasses[i])
+				return true;
+		return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+
+	public abstract boolean isCategorical ();
+	/*.................................................................................................................*/
+	public abstract CharacterData createData(CharactersManager charTask, Taxa taxa);
+	/*.................................................................................................................*/
+	boolean badImportWarningGiven = false;
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+
+			Taxa taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa"), 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CharacterData data = (CharacterData)createData(charTask,taxa);
+			data.addToFile(file, getProject(), null);
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+
+			int numTaxa = 0;
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+			String token;
+			MesquiteString result = new MesquiteString();
+			char c;
+
+			boolean abort = false;
+			while (!StringUtil.blank(line) && !abort) {
+				parser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+
+				token = parser.getNextToken();  //taxon Name
+				if (!StringUtil.blank(token)) {
+					taxa.addTaxa(numTaxa-1, 1, true);
+					Taxon t = taxa.getTaxon(numTaxa);
+
+					if (t!=null) {
+						t.setName(token);
+						progIndicator.setText("Reading taxon: "+token);
+						int ic = 0;
+
+						if (isCategorical()) {
+							while (parser.getPosition()<line.length()) {
+								c=parser.nextDarkChar();
+								if (c=='\0')
+									break;
+								if (data.getNumChars() <= ic) {
+									data.addCharacters(data.getNumChars()-1, 1, false);   // add a character if needed
+								}
+								((CategoricalData)data).setState(ic, numTaxa, c);    // setting state to that specified by character c
+								if (CategoricalState.isImpossible(((CategoricalData)data).getState(ic,numTaxa))){
+						   			data.badImport = true;
+									MesquiteTrunk.errorReportedDuringRun = true;
+									if (!badImportWarningGiven) {
+										if (data instanceof DNAData)
+											discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as DNA sequence data.  If this file is a protein data file, please use the protein interpreter. " + 
+											"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+										else
+											discreetAlert("THE DATA WILL BE INCORRECTLY IMPORTED.  The imported sequence includes symbols not interpretable as Protein sequence data.  If this file is a DNA data file, please use the DNA interpreter. " + 
+											"Also, please ensure this is not an rtf or zip file or other format that is not simple text.  This warning may not be given again, but you may see subsequent warnings about impossible states.");
+									}
+									badImportWarningGiven = true;
+								}
+								ic += 1;
+							}
+						} else {  // continuous data
+							while (parser.getPosition()<line.length()) {
+								token = parser.getNextToken();
+								if (StringUtil.blank(token))
+									break;
+								if (data.getNumChars() <= ic) {
+									data.addCharacters(data.getNumChars()-1, 1, false);   // add a character if needed
+								}
+								double value = MesquiteDouble.fromString(token);
+								if (MesquiteDouble.isCombinable(value))
+									((ContinuousData)data).setState(ic, numTaxa, 0, value);
+								ic += 1;
+							}
+						}
+
+					}
+					numTaxa++;
+				}
+				file.readLine(sb);
+				line = sb.toString();		
+				if (file.getFileAborted()) {
+					abort = true;
+				}
+			}
+			data.saveChangeHistory = wassave;
+			data.resetCellMetadata();
+			finishImport(progIndicator, file, abort);
+		}
+		decrementMenuResetSuppression();
+	}
+
+
+
+	/* ============================  exporting ============================*/
+	boolean includeGaps = false;
+	boolean includeTabs = false;
+	boolean mesquiteReadable = false;
+
+
+	/*.................................................................................................................*/
+
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export Simple Table Options", buttonPressed);
+
+		Checkbox includeGapsCheckBox = exportDialog.addCheckBox("include gaps", includeGaps);
+		Checkbox includeTabsCheckBox = exportDialog.addCheckBox("tab-delimited", includeTabs);
+		Checkbox mesquiteReadableCheckBox = exportDialog.addCheckBox("Mesquite readable", mesquiteReadable);
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+		includeGaps = includeGapsCheckBox.getState();
+		includeTabs = includeTabsCheckBox.getState();
+		mesquiteReadable = mesquiteReadableCheckBox.getState();
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	/*.................................................................................................................*/
+
+	public boolean getExportOptionsSimple(boolean dataSelected, boolean taxaSelected){   // an example of a simple query, that only proved line delimiter choice; not used here
+		return (ExporterDialog.query(this,containerOfModule(), "Export Simple Table Options")==0);
+	}	
+	/*.................................................................................................................*/
+	public abstract CharacterData findDataToExport(MesquiteFile file, String arguments);
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+
+		CharacterData data = findDataToExport(file, arguments);
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		Taxa taxa = data.getTaxa();
+		if (!MesquiteThread.isScripting() && !usePrevious)
+			if (!getExportOptions(data.anySelected(), taxa.anySelected()))
+				return false;
+
+		int expectedIncrement = 1;
+		if (includeTabs)
+			expectedIncrement++;
+		int numTaxa = taxa.getNumTaxa();
+		int numChars = data.getNumChars();
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*(20 + numChars));
+
+		for (int it = 0; it<numTaxa; it++){
+			if (!writeOnlySelectedTaxa || (taxa.getSelected(it))){
+				if (includeTabs) 
+					outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)));
+				else
+					outputBuffer.append(ParseUtil.tokenize(taxa.getTaxonName(it)) + "\t");
+				for (int ic = 0; ic<numChars; ic++) {
+					if (!writeOnlySelectedData || (data.getSelected(ic))){
+						int currentSize = outputBuffer.length();
+						if (includeGaps || (!data.isInapplicable(ic,it))) {
+							if (includeTabs) outputBuffer.append("\t");
+							data.statesIntoStringBuffer(ic, it, outputBuffer, false);
+						}
+						if ((outputBuffer.length()-currentSize>expectedIncrement)&& mesquiteReadable && isCategorical()) {
+							alert("Sorry, this data matrix can't be exported to this format (some character states aren't represented by a single symbol [char. " + CharacterStates.toExternal(ic) + ", taxon " + Taxon.toExternal(it) + "])");
+							return false;
+						}
+					}
+				}
+				outputBuffer.append(getLineEnding());
+			}
+		}
+
+		saveExportedFileWithExtension(outputBuffer, arguments, "txt");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Simple table file";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Imports and exports simple files of tab-delimited data." ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/io/lib/PartitionFinderDialog.java b/Source/mesquite/io/lib/PartitionFinderDialog.java
new file mode 100644
index 0000000..7dd4c8a
--- /dev/null
+++ b/Source/mesquite/io/lib/PartitionFinderDialog.java
@@ -0,0 +1,89 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.io.lib;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+	
+public class PartitionFinderDialog extends ExporterDialog {
+//	int tnl = 200;
+//	IntegerField f;
+	boolean linked = true;
+	boolean separateCodPos = true;
+	Checkbox linkedBox;
+	Checkbox separateCodePosBox;
+	String models;
+	SingleLineTextField modelsListField;
+	Choice modelsChoice;
+	Choice modelSelectionChoice;
+	Choice schemeChoice;
+	boolean isProtein;
+	
+	public PartitionFinderDialog (ExportPartitionFinder module, MesquiteWindow parent, String title, MesquiteInteger buttonPressed, boolean isProtein) {
+		super(module, parent, title, buttonPressed);
+//		this.tnl = module.taxonNameLength;
+		this.linked = module.branchesLinked;
+		this.isProtein = isProtein;
+		
+	}
+			
+	static final String LISTMODELS="<list>";
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean dataSelected, boolean taxaSelected) {
+//		 f = addIntegerField ("Maximum length of taxon names", tnl, 4, 1, 40);
+		 linkedBox = addCheckBox("branch lengths linked", linked);
+		if (isProtein)
+			modelsChoice = addPopUpMenu ("models", new String[] {"all_protein", LISTMODELS}, 0);
+		else
+			modelsChoice = addPopUpMenu ("models", new String[] {"all", "raxml", "mrbayes", "beast", LISTMODELS}, 0);
+		 modelsListField = addTextField ("model list: ", "",40);
+		 modelSelectionChoice = addPopUpMenu ("model selection", new String[] {"AIC", "AICc", "BIC"}, 2);
+		 schemeChoice = addPopUpMenu ("scheme", new String[] {"all", "greedy", "rcluster", "hcluster"}, 1);
+		if (!isProtein)
+			separateCodePosBox = addCheckBox("separate by codon positions", separateCodPos);
+		super.completeAndShowDialog(dataSelected, taxaSelected);
+	}
+	public boolean getLinked(){
+		return linkedBox.getState();
+	}
+	public boolean getSeparateCodPos(){
+		if (isProtein)
+			return false;
+		return separateCodePosBox.getState();
+	}
+	public String getModels(){
+		String modelsSelected = modelsChoice.getSelectedItem();
+		if (StringUtil.notEmpty(modelsSelected)){
+			if (modelsSelected.equalsIgnoreCase(LISTMODELS)) {
+				String list = modelsListField.getText();
+				if (StringUtil.notEmpty(list))
+					return list;
+			}
+			else
+				return modelsSelected;
+		}
+		if (isProtein)
+			return "all_protein";
+		else
+			return "all";
+	}
+	public int getModelSelection(){
+		return modelSelectionChoice.getSelectedIndex();
+	}
+	public int getScheme(){
+		return schemeChoice.getSelectedIndex();
+	}
+
+}
\ No newline at end of file
diff --git a/Source/mesquite/io/lib/PhylipExporterDialog.java b/Source/mesquite/io/lib/PhylipExporterDialog.java
new file mode 100644
index 0000000..b3eb791
--- /dev/null
+++ b/Source/mesquite/io/lib/PhylipExporterDialog.java
@@ -0,0 +1,35 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.io.lib;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+	
+public class PhylipExporterDialog extends ExporterDialog {
+	int tnl = 10;
+	IntegerField f;
+	public PhylipExporterDialog (InterpretPhylip module, MesquiteWindow parent, String title, MesquiteInteger buttonPressed) {
+		super(module, parent, title, buttonPressed);
+		this.tnl = module.taxonNameLength;
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean dataSelected, boolean taxaSelected) {
+		 f = addIntegerField ("Maximum length of taxon names", tnl, 4, 1, 1000);
+		super.completeAndShowDialog(dataSelected, taxaSelected);
+	}
+	public int getTaxonNamesLength(){
+		return f.getValue();
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/io/xExportConservativeNexus/xExportConservativeNexus.java b/Source/mesquite/io/xExportConservativeNexus/xExportConservativeNexus.java
new file mode 100644
index 0000000..5e9e587
--- /dev/null
+++ b/Source/mesquite/io/xExportConservativeNexus/xExportConservativeNexus.java
@@ -0,0 +1,117 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.xExportConservativeNexus;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public class xExportConservativeNexus extends FileInterpreterI {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	String fileName = "untitled.nex";
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		NexusFileInterpreter writer = (NexusFileInterpreter)getFileCoordinator().findEmployeeWithDuty(NexusFileInterpreter.class);
+		if (writer == null){
+			discreetAlert("Sorry, no NEXUS file writer found");
+			return false;
+		}
+		String path = null;
+		String oldDir = file.getDirectoryName();
+		String oldName = file.getFileName();
+		boolean wasConservative = file.useConservativeNexus;
+		
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		boolean scripting = args.parameterExists("script");
+		if (MesquiteThread.isScripting() || scripting){
+			dir.setValue(args.getParameterValue("directory"));
+			if (dir.getValue() == null)
+				dir.setValue(getProject().getHomeDirectoryName());
+			fn.setValue(args.getParameterValue("file"));
+			path = dir.getValue() + fn.getValue();
+		}
+		else {
+			String suggested = fileName;
+			if (file !=null)
+				suggested = file.getFileName();
+			path = getPathForExport(arguments, suggested, dir, fn);
+		}
+		if (path != null) {
+			file.setLocs(true, null, fn.getValue(), dir.getValue());
+				file.useConservativeNexus = true;
+				writer.writeFile(getProject(), file);
+				file.setLocs(true, null, oldName, oldDir);
+				file.useConservativeNexus = wasConservative;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Conservative NEXUS";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports NEXUS files that avoid TITLE, LINK, IDS, the MESQUITE block, and other commands used mostly by Mesquite" ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/io/xExportPartitionsNEXUS/xExportPartitionsNEXUS.java b/Source/mesquite/io/xExportPartitionsNEXUS/xExportPartitionsNEXUS.java
new file mode 100644
index 0000000..c2569a1
--- /dev/null
+++ b/Source/mesquite/io/xExportPartitionsNEXUS/xExportPartitionsNEXUS.java
@@ -0,0 +1,189 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.xExportPartitionsNEXUS;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+
+
+
+public class xExportPartitionsNEXUS extends FileInterpreterI {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatricesVisible(CategoricalState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return CategoricalData.class.isAssignableFrom(dataClass);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	String fileName = "untitled.nex";
+	String lineEnding = getLineEnding();
+
+	public CategoricalData findDataToExport(MesquiteFile file, String arguments) { 
+		return (CategoricalData)getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+	}
+
+
+	boolean saveFile(CategoricalData data, CharacterPartition partition, CharactersGroup group, String path){
+		Taxa taxa = data.getTaxa();
+		StringBuffer obuffer = new StringBuffer(500);
+		obuffer.append("#NEXUS" + lineEnding + lineEnding + "begin data;" + lineEnding);
+		StringBuffer buffer = new StringBuffer(500);
+		buffer.append("format datatype = ");
+		if (data.getClass() == RNAData.class)
+			buffer.append("rna");
+		else if (data.getClass() == DNAData.class)
+			buffer.append("dna");
+		else if (data.getClass() == ProteinData.class)
+			buffer.append("protein");
+		else if (data.getClass() == CategoricalData.class)
+			buffer.append("standard");
+
+		int found = 0;
+		buffer.append(" gap = - missing =?;" + lineEnding + "matrix" + lineEnding);
+		StringBuffer forTaxon = new StringBuffer(100);
+		int numTaxa = 0;
+		for (int it=0; it< taxa.getNumTaxa(); it++) {
+			forTaxon.setLength(0);
+			forTaxon.append(StringUtil.tokenize(taxa.getTaxonName(it)));
+			forTaxon.append('\t');
+			found = 0;
+			boolean hasSite = false;
+			for (int ic=0; ic<data.getNumChars(); ic++) {
+				if (partition.getProperty(ic) == group) {
+					if (!hasSite){
+						if (!data.isUnassigned(ic, it) && !data.isInapplicable(ic, it))
+							hasSite = true;
+					}
+					if (data instanceof MolecularData)
+						data.statesIntoNEXUSStringBuffer(ic, it, forTaxon);
+					else
+						forTaxon.append(CategoricalState.toNEXUSString(data.getState(ic, it)));
+					found++;
+				}
+			}
+			if (found == 0){
+				return false;
+			}
+
+			if (hasSite){
+				numTaxa++;
+				buffer.append(forTaxon);
+				buffer.append(lineEnding);
+			}
+		}
+		buffer.append(lineEnding + ";" + lineEnding + "end;" + lineEnding);
+		obuffer.append("dimensions ntax=" + numTaxa + " nchar=" + found + ";" + lineEnding);
+		obuffer.append(buffer);
+		String name = null;
+		if (group == null)
+			name = "NO_GROUP";
+		else
+			name = group.getName();
+
+		MesquiteFile.putFileContents(path  + MesquiteFile.fileSeparator + name + ".nex", obuffer.toString(), true);
+		return true;
+
+	}
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+
+		CategoricalData data = findDataToExport(file, arguments);
+		if (data == null)
+			return false;
+		String path = MesquiteFile.chooseDirectory("Directory in which to write files from partitions", getProject().getHomeDirectoryName());
+		Taxa taxa = data.getTaxa();
+		StringBuffer buffer = new StringBuffer(500);
+		CharacterPartition partition = (CharacterPartition) data.getCurrentSpecsSet(CharacterPartition.class);
+		boolean found = false;
+		if (partition != null){
+			CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+			if (groups != null)
+				for (int i=0; i< groups.size(); i++){
+					CharactersGroup group = (CharactersGroup)groups.elementAt(i);
+					boolean tF = saveFile(data, partition, group, path);
+					found = found || tF;
+				}
+			boolean tF = saveFile(data, partition, null, path);
+			found = found || tF;
+		}
+		if (!found)
+			discreetAlert("The matrix being exported is not partitioned or has no data in those partitions, and so no files were written");
+
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Export Partitions as Separate NEXUS files";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports character partitions in a matrix as Separate NEXUS files." ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/io/xExportSimpleNexus/xExportSimpleNexus.java b/Source/mesquite/io/xExportSimpleNexus/xExportSimpleNexus.java
new file mode 100644
index 0000000..b1f27de
--- /dev/null
+++ b/Source/mesquite/io/xExportSimpleNexus/xExportSimpleNexus.java
@@ -0,0 +1,185 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.io.xExportSimpleNexus;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public class xExportSimpleNexus extends FileInterpreterI {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  //make this depend on taxa reader being found?)
+	}
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatrices( CategoricalState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	boolean convertAmbiguities = false;
+	boolean interleaveAllowed = false;
+	boolean writeCharLabels = false;
+	boolean useData = true;
+	String addendum = "";
+	String fileName = "untitled.nex";
+	public boolean getExportOptions(CharacterData data, boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export NEXUS Options", buttonPressed);
+		exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		Checkbox useDataBlock = exportDialog.addCheckBox("use DATA instead of TAXA/CHARACTERS blocks", useData);
+		Checkbox charLabelsBox = exportDialog.addCheckBox("write CharLabels", writeCharLabels);
+		Checkbox interleaveBox = exportDialog.addCheckBox("allow interleaved matrix", interleaveAllowed);
+		Checkbox convertToMissing = exportDialog.addCheckBox("convert partial ambiguities to missing", convertAmbiguities);
+		exportDialog.addLabel("Addendum to file: ");
+
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,8);
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+		convertAmbiguities = convertToMissing.getState();
+		useData = useDataBlock.getState();
+		interleaveAllowed = interleaveBox.getState();
+		writeCharLabels = charLabelsBox.getState();
+		addendum = fsText.getText();
+		exportDialog.dispose();
+		return ok;
+	}	
+
+
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+
+		CategoricalData data = null;
+		String path = null;
+		MesquiteFile f;
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		boolean scripting = args.parameterExists("script");
+		if (MesquiteThread.isScripting() || scripting){
+			int im = args.getParameterValueAsInt("matrix");
+			dir.setValue(args.getParameterValue("directory"));
+			if (dir.getValue() == null)
+				dir.setValue(getProject().getHomeDirectoryName());
+			fn.setValue(args.getParameterValue("file"));
+			path = dir.getValue() + fn.getValue();
+			data = (CategoricalData)getProject().getCharacterMatrix(im, CategoricalState.class);
+			if (data ==null) {
+				showLogWindow(true);
+				logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+				return false;
+			}
+			useData = args.parameterExists("useData");
+			convertAmbiguities = args.parameterExists("convertAmbiguities");
+			interleaveAllowed = args.parameterExists("interleaveAllowed");
+			writeCharLabels = args.parameterExists("writeCharLabels");
+			writeOnlySelectedTaxa = args.parameterExists("writeOnlySelectedTaxa");
+			
+		}
+		else {
+			boolean usePrevious = args.parameterExists("usePrevious");
+			if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying about options"))
+				usePrevious = true;
+			data = (CategoricalData)getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+			if (data ==null) {
+				showLogWindow(true);
+				logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+				return false;
+			}
+			String suggested = fileName;
+			if (file !=null)
+				suggested = file.getFileName();
+			if (!usePrevious){
+				if (!getExportOptions(data, data.anySelected(), data.getTaxa().anySelected()))
+					return false;
+			}
+			path = getPathForExport(arguments, suggested, dir, fn);
+		}
+		if (path != null) {
+			f = MesquiteFile.newFile(dir.getValue(), fn.getValue());
+			if (f !=null){
+				f.useSimplifiedNexus = true;
+				f.useDataBlocks = useData;
+				f.ambiguityToMissing = convertAmbiguities;
+				f.interleaveAllowed = interleaveAllowed;
+				f.writeCharLabels = writeCharLabels;
+				//  writeOnlySelectedData ;
+				// writeOnlyIncludedData ;
+				f.writeOnlySelectedTaxa = writeOnlySelectedTaxa ;
+
+				f.openWriting(true);
+				f.writeLine("#NEXUS" + StringUtil.lineEnding());
+				if (!useData)
+					f.writeLine(((TaxaManager)findElementManager(Taxa.class)).getTaxaBlock(data.getTaxa(), null, f));
+				data.getMatrixManager().writeCharactersBlock(data, null, f, null);
+				if (addendum != null)
+					f.writeLine(addendum);
+				f.closeWriting();
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Simplified NEXUS";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Exports NEXUS files, for instance of old fashioned style (using DATA block)." ;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/jama/aJamaIntro/aJamaIntro.java b/Source/mesquite/jama/aJamaIntro/aJamaIntro.java
new file mode 100644
index 0000000..89ebfe2
--- /dev/null
+++ b/Source/mesquite/jama/aJamaIntro/aJamaIntro.java
@@ -0,0 +1,66 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.jama.aJamaIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aJamaIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aJamaIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Introduces the JAMA library.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "JAMA Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "JAMA";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns information about a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "JAMA";
+ 	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+	
+	public boolean getHideable(){
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/jama/aJamaIntro/index.html b/Source/mesquite/jama/aJamaIntro/index.html
new file mode 100644
index 0000000..8a75025
--- /dev/null
+++ b/Source/mesquite/jama/aJamaIntro/index.html
@@ -0,0 +1,40 @@
+<html>
+
+	<!--This file created 14/3/01 9:48 AM by Claris Home Page version 3.0-->
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Jama</title>
+		<x-claris-window top="34" bottom="717" left="63" right="559"><x-claris-tagview mode="minimal">
+	</head>
+
+	<body bgcolor="#ffcc99">
+		<h2>
+		<table border="4" cellpadding="0">
+			<tr>
+				<td width="165"><img src="splash.gif" width="164" height="64" x-claris-useimagewidth x-claris-useimageheight align="bottom"></td>
+				<td>
+					<h2>JAMA: Java Matrix Package</h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#installation">Installation</a>
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		<p>This page represents the JAMA package, as installed for use in Mesquite. When installed, various modules in Mesquite have the option of using JAMA methods for calculations. To find out what modules might be using JAMA, look through their documentation.</p>
+		<p>For more information about JAMA see <a href="http://math.nist.gov/javanumerics/jama/">http://math.nist.gov/javanumerics/jama/</a></p>
+		<p>JAMA was developed by Joe Hicklin, Cleve Moler, Peter Webb from The MathWorks and Ronald F. Boisvert, Bruce Miller, Roldan Pozo, Karin Remington from National Institutes of Standards and Technology.</p>
+		<p>The JAMA web page contains this Copyright Notice: This software is a cooperative product of The MathWorks and the National Institute of Standards and Technology (NIST) which has been released to the public domain. Neither The MathWorks nor NIST assumes any responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. </p>
+		<p></p>
+		<h3><a name="installation"></a>Installation</h3>
+		<p>To install Jama, the "Jama" directory must be installed within "Mesquite_Folder" directory.</p>
+		<p>
+		<hr>
+	</body>
+
+</html>
+
diff --git a/Source/mesquite/jama/aJamaIntro/splash.gif b/Source/mesquite/jama/aJamaIntro/splash.gif
new file mode 100644
index 0000000..2303b4d
Binary files /dev/null and b/Source/mesquite/jama/aJamaIntro/splash.gif differ
diff --git a/Source/mesquite/jama/explanation.txt b/Source/mesquite/jama/explanation.txt
new file mode 100644
index 0000000..41d9c87
--- /dev/null
+++ b/Source/mesquite/jama/explanation.txt
@@ -0,0 +1,2 @@
+Introduction to JAMA
+This package contains no substantive modules.  It has a single module that serves to introduce to the user the JAMA package of matrix manipulation routines.  If this package is deactivated, the JAMA package is NOT deactivated.
diff --git a/Source/mesquite/jsci/aJSciIntro/aJSciIntro.java b/Source/mesquite/jsci/aJSciIntro/aJSciIntro.java
new file mode 100644
index 0000000..9a414f6
--- /dev/null
+++ b/Source/mesquite/jsci/aJSciIntro/aJSciIntro.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.jsci.aJSciIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aJSciIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aJSciIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Introduces the JSci library.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "mesquite.jsci Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "JSci";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns information about a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Hale, M. & J. van Kooten.  JSci - A science API for Java, version 0.89 (14 April 2003)";
+ 	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+	
+	public boolean getHideable(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/jsci/aJSciIntro/index.html b/Source/mesquite/jsci/aJSciIntro/index.html
new file mode 100644
index 0000000..8f1c639
--- /dev/null
+++ b/Source/mesquite/jsci/aJSciIntro/index.html
@@ -0,0 +1,50 @@
+<html>
+
+	<!--This file created 14/3/01 9:48 AM by Claris Home Page version 3.0-->
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>JSci.math</title>
+		<x-claris-window top="34" bottom="717" left="63" right="559"><x-claris-tagview mode="minimal">
+	</head>
+
+	<body bgcolor="#ffcc99">
+		<h2>
+		<table border="4" cellpadding="0">
+			<tr>
+				<td width="165"><img src="splash.gif" width="164" height="64" x-claris-useimagewidth x-claris-useimageheight align="bottom"></td>
+				<td>
+					<h2>JSci.maths</h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<h4>Mark Hale and Jaco van Kooten</h4>
+		
+<p>September 2003</p>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#installation">Installation</a>
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		
+<p>This package is composed of some portions of the maths package of the JSci 
+  Java library, created by Mark Hale with Jaco van Kooten and other collaborators. 
+  This package is used by other packages in the Mesquite system.</p>
+		
+<p>The URL for JSci is <a href="http://jsci.sourceforge.net">http://jsci.sourceforge.net</a>.</p>
+		<p>The JSci package is necessary for some of the other packages available with Mesquite, including the Genesis package of character evolution models.</p>
+		<h3><a name="installation"></a>Installation</h3>
+		
+<p>To install the JSci package, the "JSci" directory must be installed 
+  within "Mesquite Folder".</p>
+		<p>
+		<hr>
+		</p>
+		
+<p>© Mark Hale and Jaco van Kooten, 2003
+</body>
+
+</html>
+
diff --git a/Source/mesquite/jsci/aJSciIntro/splash.gif b/Source/mesquite/jsci/aJSciIntro/splash.gif
new file mode 100644
index 0000000..e980b24
Binary files /dev/null and b/Source/mesquite/jsci/aJSciIntro/splash.gif differ
diff --git a/Source/mesquite/jsci/explanation.txt b/Source/mesquite/jsci/explanation.txt
new file mode 100644
index 0000000..ef64323
--- /dev/null
+++ b/Source/mesquite/jsci/explanation.txt
@@ -0,0 +1,2 @@
+JSCI Package for matrix and statistical routines
+Incorporates the JSci package by Hale & van Kooten.  Required by some other packages, such as the Genesis package for molecular evolution.
diff --git a/Source/mesquite/lib/Abortable.java b/Source/mesquite/lib/Abortable.java
new file mode 100644
index 0000000..63aa32c
--- /dev/null
+++ b/Source/mesquite/lib/Abortable.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+public interface Abortable {
+	public boolean isAborted ();
+	
+
+}
+
+
diff --git a/Source/mesquite/lib/AdjustableTree.java b/Source/mesquite/lib/AdjustableTree.java
new file mode 100644
index 0000000..13ccfe5
--- /dev/null
+++ b/Source/mesquite/lib/AdjustableTree.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.math.*;
+
+/** This interface matches some of the basic tree changing methods of MesquiteTree.  It was
+created (Aug. 2000) to allow methods to use the interface, in case tree structures from other 
+programs needed to be used.  Currently, though, AdjustableTree is not much used directly in
+Mesquite.*/
+public interface AdjustableTree extends Tree {
+	
+	/** Sets the name of the tree.*/
+	public void setName(String name) ;
+	
+	public void setSelected(int node, boolean selected);
+	
+	/** Sets the  tree vector to which the tree belongs.*/
+	public void setTreeVector(TreeVector treeVector) ;
+	/** Sets whether tree is rooted.*/
+	public void setRooted(boolean rooted, boolean notify) ;
+	/** Sets whether polytomies are to be assumed soft; 0= hard; 1 = soft; 2 = use default.*/
+	public void setPolytomiesAssumption(int assumption, boolean notify);
+	/** Sets par to be an additional parent of node.  Used to make reticulations.  Currently there
+	is no way to subtract parents, nor to rearrange trees that contain reticulations.*/
+	public void setParentOfNode(int node, int par, boolean notify) ;
+	/** An indelicate quick way to delete all reticulations (extra parents) from a node.*/
+	public void snipReticulations(int node);
+	/** Sets the branch length of node.*/
+	public  void setAllBranchLengths(double length, boolean notify) ; 
+	/** Sets the branch length of node (stored as a double internally).*/
+	public  void setBranchLength(int node, int length, boolean notify) ; 
+	/** Sets the taxon number for the node.  If the node is internal, the number should
+	be set to -1.  Otherwise it should be set to the taxon corresponding to the node.
+	NOTE: this should be used with caution, since it doesn't check for tree integrity.  Intended primarily
+	for internal use (with MesquiteTree).*/
+	public void setTaxonNumber(int node, int num, boolean notify);
+	/** Sets the branch length of node.*/
+	public  void setBranchLength(int node, double length, boolean notify) ; 
+	/** Sets the tree to be a default bush.*/
+	public void setToDefaultBush(int numTaxa, boolean notify) ;
+	/** Sets the tree to be a default ladder.*/
+	public void setToDefaultLadder(int numTaxa, boolean notify) ;
+	/** Returns the first tree in the sequence of all possible trees (polytomies are set to first resolution)*/
+	//public void setToFirstInSequence();
+	/** Returns the next tree in the sequence of all possible trees (polytomies are set to first resolution)*/
+	//public boolean setToNextInSequence();
+	/** Sets the node label to the passed string (doesn't copy string; just uses reference) */
+	public void setNodeLabel(String s, int node);
+	/** Branches a terminal node off taxon number taxonNum, and assigns it taxon newNumber  */
+	public void splitTerminal(int taxonNum, int newNumber, boolean notify) ;
+	/** Sprouts a new daughter from node and returns it. */
+	public int sproutDaughter(int node, boolean notify) ;
+	/** Interchanges two branches of tree.*/
+	public boolean interchangeBranches(int node, int otherNode, boolean notify) ;   
+	/** Randomly rotate branches of tree.*/
+ 	public boolean randomlyRotateDescendants(int node, Random rng, boolean notify);
+	/** reroots tree at taxonSet, if non null, otherwise reroots at first taxon in tree, and right-ladderizes tree.*/
+ 	public boolean standardize(TaxaSelectionSet taxonSet, boolean notify);
+
+	/** Collapses branch to yield polytomy.*/
+	public boolean collapseBranch(int node, boolean notify) ;   
+	/** Collapses all internal branches within clade above node, to yield bush.*/
+	public boolean collapseAllBranches(int node, boolean below, boolean notify) ;   
+	/** Excise node and clade above it from tree, zeroing information at each node in clade.*/
+	public boolean deleteClade(int node, boolean notify);
+	/** Excise node and clade above it from tree but leave the clade intact, in case it is to be attached elsewhere.*/
+	public boolean snipClade(int node, boolean notify) ;   
+	/** Attach terminal taxon to tree along given branch.*/
+	public boolean graftTaxon(int taxon, int toN, boolean notify) ;   
+	/** Attach node fromN (and any clade to attached to it) along node toN.  Returns the new node created to attach fromN*/
+	public int graftClade(int fromN, int toN, boolean notify) ;   
+	
+	public boolean graftCladeFromDescription(String TreeDescription, int node, MesquiteInteger stringLoc, TaxonNamer namer);
+	/** Move branch so as to excise branchFrom from its current position, and attach it to branch beneath
+	node branchTo.  If successful, rename as given (to ensure renamed before notified).*/
+	public boolean moveBranch(int branchFrom, int branchTo, boolean notify) ;
+	/** Inserts a new node on the branch represented by "node", and returns the number of the inserted node */
+	public int insertNode(int node, boolean notify);
+	/** reroot the clade below node atNode.*/
+	public boolean reroot(int atNode, int cladeRoot, boolean notify) ;
+	/** ultrametricizes the tree.*/
+	public void arbitrarilyUltrametricize();
+}
+
+
diff --git a/Source/mesquite/lib/AlertDialog.java b/Source/mesquite/lib/AlertDialog.java
new file mode 100644
index 0000000..6d5c58c
--- /dev/null
+++ b/Source/mesquite/lib/AlertDialog.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.event.*;
+import java.awt.*;
+/*===============================================*/
+
+
+
+public class AlertDialog  {
+	static String okString = "OK";
+	static String cancelString = "Cancel";
+	static String noString = "No";
+
+
+	public static void setButtonNames (String string1, String string2, String string3) {
+		if (string1!=null)
+			okString = string1;
+		if (string2!=null)
+			cancelString = string2;
+		if (string3 !=null)
+			noString = string3;
+	}
+
+	public static int query(Object parent, String title, String message, String string1, String string2, String string3, String helpString) {
+		return query(parent, title, message, string1, string2, string3, 1, helpString);
+	}
+	public static int query(Object parent, String title, String message, String string1, String string2, String string3) {
+		return query(parent, title, message, string1, string2, string3, 1, "");
+	}
+	public static int query(Object parent, String title, String message, String string1, String string2, String string3, int whichIsDefault) {
+		return query(parent, title, message, string1, string2, string3, whichIsDefault, "");
+	}
+	public static int query(Object parent, String title, String message, String string1, String string2, String string3, int whichIsDefault, String helpString) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed);
+		id.addLargeTextLabel(message);
+		if (StringUtil.blank(helpString) && id.isInWizard())
+			helpString = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please choose.";
+		id.appendToHelpString(helpString);
+		String defaultButton="";
+		if (whichIsDefault == 1)
+			defaultButton=string1;
+		else if (whichIsDefault == 2)
+			defaultButton=string2;
+		else if (whichIsDefault == 3)
+			defaultButton=string3;
+		id.completeAndShowDialog(string1,string2,string3,defaultButton);
+		id.dispose();
+		return buttonPressed.getValue();
+	}
+	public static boolean query(Object parent, String title, String message, String okString, String cancelString, int whichIsDefault, String helpString) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>");
+		if (!StringUtil.blank(helpString))
+			id.appendToHelpString(helpString);
+		if (id.isInWizard())
+			id.appendToHelpString("Please choose.");
+		id.addLargeTextLabel(message);
+		String defaultButton="";
+		if (whichIsDefault == 1)
+			defaultButton=okString;
+		else if (whichIsDefault == 2)
+			defaultButton=cancelString;
+		id.completeAndShowDialog(okString,cancelString,null,defaultButton);
+		id.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	public static boolean query(Object parent, String title, String message, String okString, String cancelString, int whichIsDefault) {
+		return query(parent, title, message, okString, cancelString, whichIsDefault, null);
+	}
+	public static boolean query(Object parent, String title, String message, String okString, String cancelString) {
+		return query(parent, title, message, okString, cancelString, 1);
+	}
+	public static boolean query(Object parent, String title, String message) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please choose.");
+		id.addLargeTextLabel(message);
+		id.completeAndShowDialog();
+		id.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	public static void noticeHTML(Object parent, String title, String message, int w, int h, MesquiteCommand linkTouchedCommand) {
+		noticeHTML(parent, title, message, w, h, linkTouchedCommand, false);
+	}
+	public static void noticeHTML(Object parent, String title, String message, int w, int h, MesquiteCommand linkTouchedCommand, boolean checkTextEdge) {
+
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed, true);
+		id.setCheckTextEdge(checkTextEdge);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>Notice</h3>");
+		id.addHTMLPanel(message, w, h, linkTouchedCommand);
+		id.completeAndShowDialog(okString,null,null,okString);
+		id.dispose();
+	}
+	public static void notice(Object parent, String title, String message) {
+		if (message!=null && message.length()>800){
+			verboseNotice(parent, title, message);
+			return;
+		}
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed, true);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>Notice</h3>");
+		id.addLargeTextLabel(message);
+		id.completeAndShowDialog(okString,null,null,okString);
+		id.dispose();
+	}
+	public static void bigNotice(Object parent, String title, String message) {
+		if (message!=null && message.length()>800){
+			verboseNotice(parent, title, message);
+			return;
+		}
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed, true);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>Notice</h3>");
+		id.addLargeTextLabel(message);
+		id.completeAndShowDialog(okString,null,null,okString);
+		id.dispose();
+	}
+	public static void verboseNotice(Object parent, String title, String message) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog id = new ExtensibleDialog(parent, title,buttonPressed, true);
+		if (id.isInWizard())
+			id.appendToHelpString("<h3>Notice</h3>");
+		id.addTextAreaSmallFont(message, 20, 76);
+		id.completeAndShowDialog(okString,null,null,okString);
+		id.dispose();
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/AnnotPanelOwner.java b/Source/mesquite/lib/AnnotPanelOwner.java
new file mode 100644
index 0000000..d077fef
--- /dev/null
+++ b/Source/mesquite/lib/AnnotPanelOwner.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib; 
+import java.awt.*;
+/* ======================================================================== */
+public interface AnnotPanelOwner {
+	/* make a notes vector (or return the one that exists) for the noteswindow*/
+    	public AttachedNotesVector makeNotesVector(AnnotationsPanel w);
+	/* select and attach an image to the given NotesWindow*/
+	public void chooseAndAttachImage(AttachedNote note, boolean local);
+	public void panelGoAway(Panel p);
+	public MesquiteModule getModule();
+
+}
+
diff --git a/Source/mesquite/lib/Annotatable.java b/Source/mesquite/lib/Annotatable.java
new file mode 100644
index 0000000..8192c0d
--- /dev/null
+++ b/Source/mesquite/lib/Annotatable.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it can be annotated*/
+public interface Annotatable extends Listable  {
+ 	public String getAnnotation();
+ 	public void setAnnotation(String note, boolean notify);
+}
+
diff --git a/Source/mesquite/lib/AnnotationsPanel.java b/Source/mesquite/lib/AnnotationsPanel.java
new file mode 100644
index 0000000..96e3309
--- /dev/null
+++ b/Source/mesquite/lib/AnnotationsPanel.java
@@ -0,0 +1,1608 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib; 
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import java.awt.image.*;
+
+/*
+/** ======================================================================== */
+public class AnnotationsPanel extends MesquitePanel implements Commandable, TextListener {
+	AttachedNotesVector aim;
+	HeaderPanel infoHeader;
+	InfoPanel infoPanel;
+	HeaderPanel commentHeader;
+	TextArea commentPanel;
+	HeaderPanel refHeader;
+	TextArea refPanel;
+	HeaderPanel imageHeader;
+	AImagePanel imagePanel;
+	boolean attachable = true;
+	String where = "";
+	String location = "";
+	int currentNoteNumber = 0;
+	MiniScroll scroll;
+	ControlP controls;
+	static AttachedNotesVector clipboardVector;
+	static AttachedNote clipboardNote;
+	MesquiteMenuItemSpec[]  m = new MesquiteMenuItemSpec[5];
+	int controlsWidth = 100;
+	int controlsHeight = 32;
+	int textHeight = 60;
+	int infoHeight = 50;
+	int refHeight = 40;
+	int imageHeight = 40;
+	int windowWidth = 400;
+	int currentColumn = -1;
+	int currentRow = -1;
+	int headerHeight = 20;
+	int numHeaders = 4;
+	TableTool pointerTool;
+	AnnotPanelOwner annotOwner;
+	public AnnotationsPanel (AnnotPanelOwner annotOwner){
+		//setMinimalMenus(true);
+		this.annotOwner =annotOwner;
+		setLayout(null);
+		pointerTool = new TableTool(this, "pointer", MesquiteModule.getRootImageDirectoryPath(), "pointer.gif", 4, 2, "Adjust Pointer", "Sets the destination of the pointer in an Image label.  Click on the label, then drag to put the pointer in the desired position.", null, null, null);
+		pointerTool.setWorksOnMatrixPanel(false);
+		setBackground(ColorTheme.getContentBackground());
+		MesquiteModule mb = annotOwner.getModule();
+		if (mb != null){
+			m[0] = mb.addMenuItem("-", null);
+			m[1] = mb.addMenuItem("Copy One Note", new MesquiteCommand("copyOne", this));
+			m[2] = mb.addMenuItem("Copy All Notes", new MesquiteCommand("copyAll", this));
+			m[3] = mb.addMenuItem("Paste (Add) Note(s)", new MesquiteCommand("paste", this));
+			m[4] = mb.addMenuItem("-", null);
+			mb.resetContainingMenuBar();
+		}
+		add(controls = new ControlP(this));
+		scroll = controls.getScroll();
+		controls.setVisible(true);
+		//	add(titleHeader = new HeaderPanel(this, "Title"));
+		//	titleHeader.setVisible(true);
+
+		add(infoHeader = new HeaderPanel(this, "Author & Modification Dates"));
+		infoHeader.setVisible(true);
+
+		add(infoPanel = new InfoPanel(this));
+		infoPanel.setVisible(true);
+
+
+		add(commentHeader = new HeaderPanel(this, "Comment"));
+		commentHeader.setVisible(true);
+
+		add(commentPanel = new TextArea("",50,50, TextArea.SCROLLBARS_VERTICAL_ONLY));
+		commentPanel.setEditable(true);
+		commentPanel.setBackground(Color.white);
+		commentPanel.setVisible(true);
+
+
+		add(refHeader = new HeaderPanel(this, "Reference"));
+		refHeader.setVisible(true);
+
+		add(refPanel = new TextArea("",50,50, TextArea.SCROLLBARS_VERTICAL_ONLY));
+		refPanel.setEditable(true);
+		refPanel.setBackground(Color.white);
+		refPanel.setVisible(true);
+
+		add(imageHeader = new ImageHeaderPanel(this, "Image"));
+		imageHeader.setVisible(true);
+
+		add(imagePanel = new AImagePanel(this));
+		imagePanel.setVisible(true);
+
+		setSize(windowWidth, controlsHeight +  numHeaders*headerHeight + imageHeight + refHeight +textHeight + infoHeight);
+		setLocation(100,100);
+		commentPanel.addTextListener(this);
+		refPanel.addTextListener(this);
+
+		imagePanel.setVisible(aim != null);
+		infoPanel.setVisible(aim != null);
+		refPanel.setVisible(aim != null);
+		commentPanel.setVisible(aim != null);
+		
+		
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** Gets the minimum size of the window */
+	public Dimension getMinimumSize(){
+		Dimension dim = super.getMinimumSize();
+		if (dim.width< ControlP.spacing*2 + 200)
+			dim.width = ControlP.spacing*2 + 200;
+		return dim;
+	}
+	public void setAttachable(boolean a){
+		if (a == attachable)
+			return;
+		attachable = a;
+		controls.setAttachable(a);
+	}
+	public boolean isAttachable(){
+		return attachable;
+	}
+
+	public void textValueChanged(TextEvent e){
+		if (e.getSource() == commentPanel){
+			if (commentPanel !=null) {
+				String s = commentPanel.getText();
+				if ("".equals(s))
+					s = null;
+				if (aim != null) {
+					AttachedNote note = aim.getAttachedNote(currentNoteNumber);
+					if (note !=null) {
+						note.setComment(s, true);
+						infoPanel.updateInfo();
+					}
+				}
+
+				commentHeader.repaint();
+			}
+		}
+		else if (e.getSource() == refPanel){
+			if (refPanel !=null) {
+				String s = refPanel.getText();
+				if ("".equals(s))
+					s = null;
+				if (aim != null) {
+					AttachedNote note = aim.getAttachedNote(currentNoteNumber);
+					if (note !=null) {
+						note.setReference(s, true);
+						infoPanel.updateInfo();
+					}
+				}
+				refHeader.repaint();
+
+			}
+		}
+	}
+	boolean active = false;
+	public void setActive(boolean a){
+		active = a;
+		controls.repaint();
+		//windowMessage.repaint();
+	}
+	/*.................................................................................................................*/
+	public void toggleImagePresence( HeaderPanel panel, int modifiers, boolean local){
+		if (panel == imageHeader && aim != null){
+			AttachedNote an = aim.getAttachedNote(currentNoteNumber);
+			if (an == null)
+				return;
+			if (an.getImagePath()!=null){ //image is present
+				if (!MesquiteEvent.optionKeyDown(modifiers) && !AlertDialog.query(MesquiteWindow.windowOfItem(this), "Remove Image?", "Are you sure you want to remove the image from this note? (This will not delete the image file itself)", "OK", "Cancel", -1))
+					return;
+				an.deleteImage(true);
+			}
+			else
+				annotOwner.chooseAndAttachImage(an, local);
+			imagePanel.setImage(an.getImage());
+			infoPanel.updateInfo();
+			imageHeader.repaint();
+			imagePanel.repaint();
+		}
+	}
+	public AttachedNote getCurrentNote(){
+		if (aim == null || aim.getAttachedNote(currentNoteNumber)== null) 
+			return null;
+		else 
+			return aim.getAttachedNote(currentNoteNumber);
+	}
+
+	public String getTextContents() {
+		AttachedNote note = getCurrentNote();
+		if (note != null) {
+			String s = "";
+			if (note.getComment() != null)
+				s += "Comment: " + note.getComment() + '\n';
+			if (note.getReference() != null)
+				s += "Reference: " + note.getReference() + '\n';
+			if (note.getAuthorName() != null)
+				s += "Created by Author(s): " + note.getAuthorName() + '\n';
+			if (note.getDateCreated() != null)
+				s += "Time Created: " + note.getDateCreated() + '\n';
+			if (note.getAuthorModifiedName() != null)
+				s += "Modified by Author(s): " + note.getAuthorModifiedName() + '\n';
+			if (note.getDateModified() != null)
+				s += "Time Modified: " + note.getDateModified() + '\n';
+			return s;
+		}
+		return null;
+
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (temp !=null)  {
+			if (aim != null) 
+				temp.addLine("goToNoteNumber " + (currentNoteNumber));
+			//temp.addLine("resetAll");
+			temp.incorporate(super.getSnapshot(file), false);
+		}
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	NameReference imageNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(),  "Makes a label for current item", null, commandName, "makeItemLabel")) {
+			AttachedNote note =	getCurrentNote();
+			if (note == null)
+				return null;
+			if (note.getImage() == null)
+				return null;
+			ImageLabel label = new ImageLabel();
+
+			label.setText("label");
+			label.setShowPointer(false);
+			note.addLabel(label);
+			repaintImage();
+
+
+		}
+		else if (checker.compare(this.getClass(),  "Copies one note to notes clipboard", null, commandName, "copyOne")) {
+			if (aim != null){
+				if (currentNoteNumber >=0 && currentNoteNumber< aim.getNumNotes()){
+					AttachedNote note = aim.getAttachedNote(currentNoteNumber);
+					clipboardNote = note.cloneNote();
+					clipboardVector = null;
+				}
+			}
+			
+		}
+		else if (checker.compare(this.getClass(),  "Copies notes to notes clipboard", null, commandName, "copyAll")) {
+			if (aim != null){
+					clipboardVector = aim.cloneVector();
+					clipboardNote = null;
+			}
+			
+		}
+		else if (checker.compare(this.getClass(),  "Paste notes here", null, commandName, "paste")) {
+			if (clipboardNote == null && (clipboardVector == null || clipboardVector.getNumNotes()==0))return null;
+			if (aim ==null){
+				aim = annotOwner.makeNotesVector(this);
+				if (aim == null)
+					return null;
+			}
+			if (clipboardNote == null){
+				aim.concatenate(clipboardVector);
+				aim.notifyOwner(MesquiteListener.ANNOTATION_ADDED);
+			}
+			else {
+				aim.addNote(clipboardNote, true);
+			}
+			setNote(aim.getNumNotes()-1);
+			
+		}
+		else if (checker.compare(this.getClass(),  "Indicates which in a series of notes to show", "[note number (1 based)]", commandName, "goToNoteNumber")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int i= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(i)) {
+				if (aim !=null) {
+					i = i-1;
+					setNote(i);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Recovers labels lost offscreen", null, commandName, "recoverLostLabels")) {
+			imagePanel.recoverLostLabels();
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*_________________________________________________*/
+	void requestAttachNote(){
+		if (!attachable)
+			return;
+		if (aim ==null){
+			aim = annotOwner.makeNotesVector(this);
+			if (aim == null)
+				return;
+		}
+		AttachedNote hL = new AttachedNote();
+		hL.setAuthor(MesquiteModule.author);
+		aim.addNote(hL, true);
+		setNotes(aim, aim.getNumNotes()-1);
+
+	}
+	void panelGoAway(Panel p){
+		annotOwner.panelGoAway(p);
+	}
+	public int getCurrentNoteNumber(){
+		return currentNoteNumber;
+	}
+	public void setExplanation(String e){
+		MesquiteWindow  pw = MesquiteWindow.windowOfItem(this);
+		if (pw != null)
+			pw.setExplanation(e);
+	}
+	public void setDefaultExplanation(){
+		String s = "";
+		//	if (where !=null)
+		//		s = where + ": ";
+		if (aim == null || aim.getNumNotes()<1) {
+			if (where == null)
+				setExplanation(s += "There are no notes");
+			else
+				setExplanation(s += "No notes are currently attached to "  + where + ". To attach a note, use the (+) at the top of the window.");
+		}
+		else {
+
+			s += "Note " + (currentNoteNumber+1) + " of " + aim.getNumNotes();
+			if (where != null)
+				s += " attached to " + where;
+			AttachedNote note = aim.getAttachedNote(currentNoteNumber);
+			if (note != null){
+				if (!StringUtil.blank(note.getAbsoluteImagePath()))
+					s += " (Image at " + note.getAbsoluteImagePath() + ")";
+			}
+			setExplanation(s);
+		}
+	}
+	public boolean doIHaveContent( HeaderPanel panel){
+		if (panel == commentHeader){
+			String s = commentPanel.getText();
+			if (s==null || s.equals(""))
+				return false;
+			return true;
+		}
+		else if (panel == refHeader){
+			String s = refPanel.getText();
+			if (s==null || s.equals(""))
+				return false;
+			return true;
+		}
+		else if (panel == imageHeader){
+			if (aim == null || aim.getAttachedNote(currentNoteNumber)== null) {
+				return false;
+			}
+			else {
+				AttachedNote note = aim.getAttachedNote(currentNoteNumber);
+				if (note == null || note.getImage() == null)
+					return false;
+				return true;
+			}
+		}
+		else if (panel == infoHeader){
+			return true;
+		}
+		return false;
+	}
+	public void setNotes(AttachedNotesVector aim, String where, String location, int column, int row, int noteNumber){
+		currentColumn = column;
+		currentRow = row;
+		this.aim = aim;
+		this.where = where;
+		this.location = location;
+		//	if (where != null) {
+		setDefaultExplanation();
+		//	titleHeader.setTitle("Notes for " + where);
+		//	titleHeader.repaint();
+		//	}
+		setNotes(aim, noteNumber);
+	}	
+	public void setNotes(AttachedNotesVector aim, int noteNumber){
+		if (aim == null) {
+			commentPanel.setText("");
+			controls.setMaximumValue(0);
+			imagePanel.setVisible(aim != null);
+			infoPanel.setVisible(aim != null);
+			refPanel.setVisible(aim != null);
+			commentPanel.setVisible(aim != null);
+			imagePanel.setImage(null);
+			currentNoteNumber = 0;
+			refPanel.setText("");
+			controls.repaint();
+			refHeader.repaint();
+			imageHeader.repaint();
+			commentHeader.repaint();
+			infoHeader.repaint();
+	//	controls.setBackground(null);
+			return;
+		}
+		else {
+			controls.setMaximumValue(aim.getNumNotes());
+			setNote(noteNumber);
+		}
+	}
+	public void setNote(int noteNumber){
+		if (MesquiteInteger.isCombinable(noteNumber) && noteNumber>=0) {
+			currentNoteNumber = noteNumber;
+		}
+		else 
+			currentNoteNumber = 0;
+		AttachedNote hL = null;
+		if (aim.getNumNotes() < 1) { //automatically make one note if there is none
+			hL = new AttachedNote();
+			aim.addNote(hL, true);
+			infoPanel.setNote(hL);
+			currentNoteNumber = 0;
+		}
+		else {
+			hL = aim.getAttachedNote(currentNoteNumber);
+			if (hL == null)
+				hL = aim.getAttachedNote(currentNoteNumber = 0);
+		}
+
+		hL.incrementStampSuppress();
+		Image image = hL.getImage();
+		String comment = hL.getComment();
+
+		if (comment == null)
+			comment = "";
+		commentPanel.setText(comment);
+
+		if (aim ==null || aim.getNumNotes()<1){
+			controls.setMaximumValue(0);
+		}
+		else {
+			controls.setMaximumValue(aim.getNumNotes());
+		}
+
+		String ref = hL.getReference();
+		if (ref == null)
+			ref = "";
+		refPanel.setText(ref);
+
+		controls.setCurrentValue(currentNoteNumber+1);
+		imagePanel.setVisible(aim != null);
+		infoPanel.setVisible(aim != null);
+		refPanel.setVisible(aim != null);
+		commentPanel.setVisible(aim != null);
+		imagePanel.setImage(image);
+		imageHeader.repaint();
+		imagePanel.repaint();
+		infoPanel.setNote(hL);
+	//	controls.setBackground(null);
+		controls.repaint();
+		setDefaultExplanation();
+		hL.decrementStampSuppress();
+		//windowMessage.repaint();
+	}
+	public void repaintImage(){
+		imagePanel.repaint();
+	}
+	public void deleteCurrentNote(int modifiers){
+		if (!MesquiteEvent.optionKeyDown(modifiers) &&!AlertDialog.query(MesquiteWindow.windowOfItem(this), "Remove Note?", "Are you sure you want to remove this note and the file's reference to the current image (if any)? (This will not delete the image file itself)", "OK", "Cancel", -1))
+			return;
+		if (aim!=null) {
+			aim.deleteNote(currentNoteNumber);
+			if (aim.getNumNotes()==0)
+			aim = null;
+		}
+		setNotes(aim, -1);
+	}
+
+	public void setSize(int width, int height){
+		int hmi = controlsHeight +  numHeaders*headerHeight + infoHeight+ textHeight+ refHeight;
+		imageHeight = height - hmi;
+		if (imageHeight<40)
+			imageHeight = 40;
+		int vertical = 0;
+		controls.setSize(width, controlsHeight);
+		commentHeader.setSize(width, headerHeight);
+		commentPanel.setSize(width, textHeight);
+		refHeader.setSize(width, headerHeight);
+		refPanel.setSize(width, refHeight);
+		imageHeader.setSize(width, headerHeight);
+		imagePanel.setSize(width, imageHeight);
+		infoHeader.setSize(width, headerHeight);
+		infoPanel.setSize(width, infoHeight);
+		super.setSize(width, height);
+	}
+	public void setBounds(int x, int y, int width, int height){
+		int hmi = controlsHeight +  numHeaders*headerHeight + infoHeight+ textHeight+ refHeight;
+		imageHeight = height - hmi;
+		if (imageHeight<40)
+			imageHeight = 40;
+		int vertical = 0;
+		controls.setBounds(0, 0, width, controlsHeight);
+		vertical += controlsHeight;
+		commentHeader.setBounds(0, vertical,width, headerHeight);
+		vertical += headerHeight;
+		commentPanel.setBounds(0, vertical,width, textHeight);
+		vertical += textHeight;
+		refHeader.setBounds(0, vertical,width, headerHeight);
+		vertical += headerHeight;
+		refPanel.setBounds(0, vertical,width, refHeight);
+		vertical += refHeight;
+		imageHeader.setBounds(0, vertical,width, headerHeight);
+		vertical += headerHeight;
+		imagePanel.setBounds(0, vertical,width, imageHeight);
+		vertical += imageHeight;
+		infoHeader.setBounds(0, vertical,width, headerHeight);
+		vertical += headerHeight;
+		infoPanel.setBounds(0, vertical,width, infoHeight);
+		super.setBounds(x, y, width, height);
+	}
+	boolean toolsPresent = false;
+	public void setVisible(boolean vis){
+		//pointer tool to redo pointer
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null){
+			if (vis && !toolsPresent) {
+				w.addTool(pointerTool);
+				toolsPresent = true;
+			}
+			else if (!vis && toolsPresent) {
+				w.removeTool(pointerTool);
+				toolsPresent = false;
+			}
+		}
+		if (m[0] != null){
+			for (int i = 0; i< 5; i++)
+				m[i].setEnabled(vis);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+		
+		super.setVisible(vis);
+	}
+}
+/* ======================================================================== */
+class AImagePanel extends MesquitePanel {
+	Image pic;
+	AnnotationsPanel pw;
+	int w =0;
+	int h = 0;
+	static int growboxSize = 8;
+	public AImagePanel (AnnotationsPanel pw) {
+		this.pw = pw;
+	}
+	int picX = 0;
+	int picY = 0;
+	int picWidth = 0;
+	int picHeight = 0;
+	double scale = 1.0;
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		picX = 0;
+		picY = 0;
+		if (pic != null){
+			g.setColor(Color.white);
+			g.fillRect(0,0,w, h);
+			g.setColor(Color.black);
+			picWidth = pic.getWidth(this);
+			picHeight = pic.getHeight(this);
+			scale = MesquiteImage.getScaleToReduce(picWidth, picHeight, w, h);
+			if (scale<1.0){
+				picWidth *= scale;
+				picHeight *= scale;
+			}
+			else
+				scale = 1.0;
+			picX = (w-picWidth)/2;
+			picY = (h-picHeight)/2;
+			g.drawImage(pic,picX, picY, picWidth, picHeight, (ImageObserver)this);
+		}
+		AttachedNote note = pw.getCurrentNote();
+		if (note != null){
+			Color c = g.getColor();
+			for (int i=0; i<note.getNumLabels(); i++){
+				Font f = g.getFont();
+				ImageLabel label = note.getLabel(i);
+				int labelX = label.getX();
+				int labelY = label.getY();
+				if (label.getFixedToImage()) {
+					labelX += picX;
+					labelY += picY;
+				}
+				if (label.getShowShadow()){
+					g.setColor(Color.white);
+					drawLabel(g, label, labelX, labelY, 1, 0);
+					drawLabel(g, label, labelX, labelY, 1, 1);
+					drawLabel(g, label, labelX, labelY, 0, 1);
+					drawLabel(g, label, labelX, labelY, -1, 0);
+					drawLabel(g, label, labelX, labelY, -1, -1);
+					drawLabel(g, label, labelX, labelY, 0, -1);
+					drawLabel(g, label, labelX, labelY, 1, -1);
+					drawLabel(g, label, labelX, labelY, -1, 1);
+				}
+
+				Color cL = ColorDistribution.getStandardColor(label.getFontColor());
+				if (cL != null)
+					g.setColor(cL);
+				else
+					g.setColor(Color.black);
+				drawLabel(g, label, labelX, labelY, 0, 0);
+
+				g.setColor(c);
+				g.setFont(f);
+				if (highlightedLabel == label && filled && GraphicsUtil.useXORMode(g, false)){
+					g.setXORMode(Color.white);
+					g.fillRect(labelX, labelY, label.getWidth(), label.getHeight());
+					if (squared) g.fillRect(labelX+label.getWidth()-growboxSize -2, labelY + label.getHeight()-growboxSize -2, growboxSize, growboxSize);
+					g.setPaintMode();
+				}
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	void drawLabel(Graphics g, ImageLabel label, int labelX, int labelY, int offX, int offY){
+		StringInABox textBox = label.getTextBox();
+		textBox.draw(g,labelX+offX+4, labelY+offY-4);
+		if (label.getShowPointer()){
+			drawPointerToClosestCorner(g, offX, offY, label);
+		}
+		g.drawRect(labelX+offX, labelY+offY, label.getWidth(), label.getHeight());
+	}
+
+	void drawPointerToClosestCorner(Graphics g, int offX, int offY, ImageLabel label){
+		int pointerX = (int)(picX + scale*label.getPointerX()); //inverse recordedPointerX = (pointerX-picX)/scale;
+		int pointerY = (int)(picY + scale*label.getPointerY());
+		drawPointerToClosestCorner(g, pointerX, pointerY, offX, offY, label);
+	}
+
+	void drawPointerToClosestCorner(Graphics g, int pointerX, int pointerY, int offX, int offY, ImageLabel label){
+		//first, get top left of label
+		int labelX = label.getX();
+		int labelY = label.getY();
+		if (label.getFixedToImage()) {
+			labelX += picX;
+			labelY += picY;
+		}
+		pointerX += offX;
+		pointerY += offY;
+		labelX += offX;
+		labelY+= offY;
+
+		int sqDist =sqDistance(pointerX, pointerY, labelX, labelY); //top left
+		int cornerX = labelX;
+		int cornerY = labelY;
+
+		int sqDist2 = sqDistance(pointerX, pointerY, labelX+label.getWidth(), labelY + label.getHeight()); //lower right
+		if (sqDist>sqDist2) {
+			sqDist = sqDist2;
+			cornerX = labelX+label.getWidth();
+			cornerY = labelY + label.getHeight();
+		}
+		sqDist2 = sqDistance(pointerX, pointerY, labelX+label.getWidth(), labelY); //top right
+		if (sqDist>sqDist2) {
+			sqDist = sqDist2;
+			cornerX = labelX+label.getWidth();
+			cornerY = labelY;
+		}
+		sqDist2 = sqDistance(pointerX, pointerY, labelX, labelY + label.getHeight()); //lower left
+		if (sqDist>sqDist2) {
+			sqDist = sqDist2;
+			cornerX = labelX;
+			cornerY = labelY + label.getHeight();
+		}
+
+
+		//picX + label.getPointerX()
+		//int dTopLeft = 
+
+		g.drawLine(pointerX, pointerY, cornerX, cornerY);
+		g.fillOval(pointerX-1, pointerY-1, 2, 2);
+	}
+	int sqDistance(int x, int y, int x2, int y2){
+		return (x-x2)*(x-x2) + (y-y2)*(y-y2);
+	}
+	/*.................................................................................................................*/
+	public void recoverLostLabels() {
+		AttachedNote note = pw.getCurrentNote();
+		if (note != null){
+			for (int i=0; i<note.getNumLabels(); i++){
+				ImageLabel label = note.getLabel(i);
+				recoverLostLabel(label);
+
+			}
+		}
+		repaint();
+	}
+	/*.................................................................................................................*/
+	void recoverLostLabel(ImageLabel label) {
+		int labelX = label.getX();
+		int labelY = label.getY();
+		if (label.getFixedToImage()) {
+			labelX += picX;
+			labelY += picY;
+			if (labelX < 0)
+				label.setX(-picX);
+			else if (labelX + label.getWidth()>w)
+				label.setX(w-label.getWidth()-picX);
+
+			if (labelY < 0)
+				label.setY(-picY);
+			else if (labelY + label.getHeight()>h)
+				label.setY(h-label.getHeight()-picY);
+		} 
+		else {
+			if (labelX < 0)
+				label.setX(0);
+			else if (labelX + label.getWidth()>w)
+				label.setX(w-label.getWidth());
+
+			if (labelY < 0)
+				label.setY(0);
+			else if (labelY + label.getHeight()>h)
+				label.setY(h-label.getHeight());
+		}
+	}
+	/*.................................................................................................................*/
+	public void setBounds(int x, int y, int width, int height){
+		w = width;
+		h = height;
+		super.setBounds(x, y, width, height);
+	}
+	/*.................................................................................................................*/
+	public void setSize(int width, int height){
+		w = width;
+		h = height;
+		super.setSize(width, height);
+	}
+	/*.................................................................................................................*/
+	public void setImage(Image i){
+		pic = i;
+	}
+	/*.................................................................................................................*/
+	ImageLabel findLabel(int x, int y){
+		AttachedNote note = pw.getCurrentNote();
+		if (note == null)
+			return null;
+
+		for (int i=0; i<note.getNumLabels(); i++){
+			ImageLabel label = note.getLabel(i);
+			int labelX = label.getX();
+			int labelY = label.getY();
+			if (label.getFixedToImage()) {
+				labelX += picX;
+				labelY += picY;
+			}
+			if (x>=labelX && y >= labelY && x<= labelX+label.getWidth() && y<= labelY + label.getHeight())
+				return label;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	boolean inLabelCorner(ImageLabel label, int x, int y){
+		int labelX = label.getX();
+		int labelY = label.getY();
+		if (label.getFixedToImage()) {
+			labelX += picX;
+			labelY += picY;
+		}
+		return (x>=labelX+label.getWidth()-growboxSize && y >= labelY + label.getHeight()-growboxSize && x<= labelX+label.getWidth() && y<= labelY + label.getHeight()) ;
+	}
+	boolean editLabel(ImageLabel label){
+		String s = label.getText();
+		if (s == null)
+			s = "";
+
+		String edited = MesquiteString.queryMultiLineString(MesquiteWindow.windowOfItem(pw), "Label", "Label:", s, 8, false, false);
+		if (edited!=null)
+			label.setText(edited);
+		return (edited!=null && edited.length() > 0);
+	}
+	/*.................................................................................................................*/
+	int prevPointX = MesquiteInteger.unassigned;
+	int prevPointY = MesquiteInteger.unassigned;
+
+	/*.................................................................................................................*/
+	void drawPointerXOR(ImageLabel label, int pointX, int pointY, boolean undoOld, boolean drawNew){
+		if (!GraphicsUtil.useXORMode(null, false))
+			return;
+		Graphics g=getGraphics();
+		if (g==null)
+			return;
+		g.setXORMode(Color.white);
+		g.setColor(Color.black);
+		if (undoOld && MesquiteInteger.isCombinable(prevPointX)){
+			//undo previous
+			drawPointerToClosestCorner(g, prevPointX, prevPointY, 0, 0, label);
+		}
+		if (drawNew) {
+			drawPointerToClosestCorner(g,  pointX, pointY, 0, 0, label);
+			prevPointX = pointX;
+			prevPointY = pointY;
+		}
+		else {
+			prevPointX = MesquiteInteger.unassigned;
+			prevPointY = MesquiteInteger.unassigned;
+		}
+		g.setPaintMode();
+		g.dispose();
+	}
+	/*.................................................................................................................*/
+	int touchedXImage = -1;
+	int touchedYImage = -1;
+	int prevX = MesquiteInteger.unassigned;
+	int prevY = MesquiteInteger.unassigned;
+	ImageLabel touchedLabel = null;
+	boolean adjustingSize = false;
+	boolean filled = false;
+	boolean squared = false;
+	/*.................................................................................................................*/
+	void drawXOR(ImageLabel label, int offX, int offY, boolean undoOld, boolean drawNew){
+		if (!GraphicsUtil.useXORMode(null, false))
+			return;
+		Graphics g=getGraphics();
+		if (g==null)
+			return;
+		g.setXORMode(Color.white);
+		g.setColor(Color.black);
+		int labelX = label.getX();
+		int labelY = label.getY();
+		if (label.getFixedToImage()) {
+			labelX += picX;
+			labelY += picY;
+		}
+		if (adjustingSize){
+			if (undoOld && MesquiteInteger.isCombinable(prevX)){
+				//undo previous
+				g.drawRect(labelX, labelY, prevX, prevY);
+			}
+			if (drawNew) {
+				g.drawRect(labelX, labelY, label.getWidth()+offX, label.getHeight()+offY);
+				prevX = label.getWidth()+offX;
+				prevY = label.getHeight()+offY;
+			}
+			else {
+				prevX = MesquiteInteger.unassigned;
+				prevY = MesquiteInteger.unassigned;
+			}
+		}
+		else {
+			if (undoOld && MesquiteInteger.isCombinable(prevX)){
+				//undo previous
+				g.drawRect(prevX, prevY, label.getWidth(), label.getHeight());
+			}
+			if (drawNew) {
+				g.drawRect(labelX+offX, labelY + offY, label.getWidth(), label.getHeight());
+				prevX = labelX+offX;
+				prevY = labelY+offY;
+			}
+			else {
+				prevX = MesquiteInteger.unassigned;
+				prevY = MesquiteInteger.unassigned;
+			}
+		}
+		g.setPaintMode();
+		g.dispose();
+	}
+	/*.................................................................................................................*/
+	void fillXOR(ImageLabel label, boolean undo, boolean showSquare){
+		if (!GraphicsUtil.useXORMode(null, false))
+			return;
+		Graphics g=getGraphics();
+		if (g==null)
+			return;
+		g.setXORMode(Color.white);
+		g.setColor(Color.black);
+		int labelX = label.getX();
+		int labelY = label.getY();
+		if (label.getFixedToImage()) {
+			labelX += picX;
+			labelY += picY;
+		}
+		if (adjustingSize){
+			if (undo){
+				if (MesquiteInteger.isCombinable(prevX)){
+					//undo previous
+					g.fillRect(labelX, labelY, prevX, prevY);
+					filled = !filled;
+					if (squared) {
+						g.fillRect(labelX + prevX -growboxSize - 2, labelY+ prevY -growboxSize - 2, growboxSize, growboxSize);
+						squared = false;
+					}
+					prevX = MesquiteInteger.unassigned;
+					prevY = MesquiteInteger.unassigned;
+				}
+			}
+			else {
+				g.fillRect(labelX, labelY, label.getWidth(), label.getHeight());
+				filled = !filled;
+				if (showSquare) {
+					g.fillRect(labelX + label.getWidth() - growboxSize - 2, labelY + label.getHeight() - growboxSize - 2, growboxSize, growboxSize);
+					squared = true;
+				}
+				else
+					squared = false;
+				prevX = label.getWidth();
+				prevY = label.getHeight();
+			}
+		}
+		else {
+			if (undo) {
+				if (MesquiteInteger.isCombinable(prevX)){
+					//undo previous
+					g.fillRect(prevX, prevY, label.getWidth(), label.getHeight());
+					filled = !filled;
+					if (squared) g.fillRect(prevX+label.getWidth()-growboxSize - 2, prevY+label.getHeight()-growboxSize - 2, growboxSize, growboxSize);
+					squared = false;
+				}
+				prevX = MesquiteInteger.unassigned;
+				prevY = MesquiteInteger.unassigned;
+			}
+			else {
+				g.fillRect(labelX, labelY, label.getWidth(), label.getHeight());
+				filled = !filled;
+				if (showSquare) {
+					g.fillRect(labelX + label.getWidth() - growboxSize - 2, labelY + label.getHeight() - growboxSize - 2, growboxSize, growboxSize);
+					squared = true;
+				}
+				else
+					squared = false;
+				prevX = labelX;
+				prevY = labelY;
+			}
+		}
+		g.setPaintMode();
+		g.dispose();
+	}
+	/*_________________________________________________*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		/*
+		if click is with arrow tool:
+
+		 */
+		if (tool.getName().endsWith(".arrow")){
+			//if in current label, then prepare to drag or drop down menu if 
+			//otherwise ignore
+			touchedLabel = findLabel(x,y);
+			if (touchedLabel !=null) {
+				if (MesquiteEvent.controlKeyDown(modifiers)) {
+					redoTheMenu();
+					popup.show(this, x+8,y+8);
+				}
+				else {
+					touchedXImage = x;
+					touchedYImage = y;
+					adjustingSize = inLabelCorner(touchedLabel, x, y);
+					drawXOR(touchedLabel, 0, 0, false, true);
+				}
+			}
+		}
+		else if (tool == pw.pointerTool){
+			touchedLabel = findLabel(x,y);
+			if (touchedLabel !=null) {
+				drawPointerXOR(touchedLabel, x, y, false, true);
+			}
+		}
+		else if (tool.getName().endsWith(".ibeam")){
+			//if in current label, then edit label
+			//if not in current label, then make new label
+			touchedLabel = findLabel(x,y);
+			if (touchedLabel !=null) {
+				editLabel(touchedLabel);
+			}
+			else {
+				AttachedNote note = pw.getCurrentNote();
+				if (note == null || StringUtil.blank(note.getImagePath()))
+					return;
+				ImageLabel label = new ImageLabel();
+				if (scale != 0)
+					label.setLocation(x-picX, y-picY);
+				else
+					label.setLocation(x,y);
+				label.setPointerX((int)((picWidth/2.0)/scale));
+				label.setPointerY((int)((picHeight/2.0)/scale));
+				if (editLabel(label))
+					note.addLabel(label);
+			}
+			touchedLabel = null;
+			repaint();
+
+		}
+	}
+
+	/*_________________________________________________*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		//pw.mouseDown(modifiers, x, y, tool);
+		if (tool.getName().endsWith(".arrow")){
+			//if in current label, then prepare to drag or drop down menu if 
+			//otherwise ignore
+			if (touchedLabel !=null) {
+				drawXOR(touchedLabel, x-touchedXImage, y-touchedYImage, true, true);
+			}
+		}
+		else if (tool == pw.pointerTool){
+			if (touchedLabel !=null) {
+				drawPointerXOR(touchedLabel, x, y, true, true);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		//if arrow and not moved, then select label
+		if (tool.getName().endsWith(".arrow")){
+			//if in current label, then prepare to drag or drop down menu if 
+			//otherwise ignore
+			if (touchedLabel !=null) {
+				if (adjustingSize) {
+					//drawXOR(touchedLabel,  x-touchedXImage, y-touchedYImage, true, false);
+					int w = (x-touchedXImage+touchedLabel.getWidth());
+					if (w <32)
+						w = 32;
+					touchedLabel.setWidth(w);
+					fillXOR(touchedLabel,  true, true); //dehighlight
+
+					adjustingSize = false;
+					if (findLabel(x,y)==touchedLabel){ //need to rehighlight
+						fillXOR(touchedLabel,  false, true);
+					}
+					else
+						highlightedLabel = null;
+				}
+				else {
+					//drawXOR(touchedLabel,  x-touchedXImage, y-touchedYImage, true, false);
+					touchedLabel.setX(x-touchedXImage+touchedLabel.getX());
+					touchedLabel.setY(y-touchedYImage+touchedLabel.getY());
+					highlightedLabel = touchedLabel; //should sstill be highlighted
+					filled = true;
+				}
+				touchedLabel = null;
+				touchedXImage = -1;
+				touchedYImage = -1;
+
+				repaint();
+			}
+		}
+		else if (tool == pw.pointerTool){
+			if (touchedLabel !=null) {
+				drawPointerXOR(touchedLabel, x, y, true, false);
+				if (scale != 0){
+					touchedLabel.setPointerX((int)((x-picX)*1.0/scale));
+					touchedLabel.setPointerY((int)((y-picY)*1.0/scale));
+				}
+				//if x, y are in label, then leave highlight on
+				if (findLabel(x,y)!=touchedLabel){
+					fillXOR(touchedLabel,  true, false);
+					highlightedLabel = null;
+				}
+				touchedLabel = null;
+				repaint();
+			}
+		}
+	}
+	/*_________________________________________________*/
+	ImageLabel highlightedLabel = null;
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		//if (tool == pw.arrowTool){
+		ImageLabel current = findLabel(x,y);
+		if (current != highlightedLabel){
+			if (highlightedLabel!= null)
+				fillXOR(highlightedLabel,  true, tool.getName().endsWith(".arrow"));
+			if (current!= null)
+				fillXOR(current,  false, tool.getName().endsWith(".arrow"));
+			highlightedLabel = current;
+		}
+		//}
+	}
+	/*_________________________________________________*/
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		//if (tool == pw.arrowTool){
+		ImageLabel current = findLabel(x,y);
+		if (current != highlightedLabel){
+			if (highlightedLabel!= null)
+				fillXOR(highlightedLabel,  true, tool.getName().endsWith(".arrow"));
+			if (current!= null)
+				fillXOR(current,  false, tool.getName().endsWith(".arrow"));
+			highlightedLabel = current;
+		}
+		//}
+	}
+	/*_________________________________________________*/
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		//if (tool == pw.arrowTool){
+		if (highlightedLabel!= null)
+			fillXOR(highlightedLabel,  true, tool.getName().endsWith(".arrow"));
+		highlightedLabel = null;
+		//}
+	}
+	/*_________________________________________________*/
+	MesquitePopup popup=null;
+	MesquiteCommand setFontCommand =MesquiteModule.makeCommand("setFont",  this);
+	MesquiteCommand setFontSizeCommand =MesquiteModule.makeCommand("setFontSize",  this);
+	MesquiteCommand setColorCommand =MesquiteModule.makeCommand("setColor",  this);
+	MesquiteCommand fixToWindowCommand=MesquiteModule.makeCommand("fixToWindow",  this);
+	MesquiteCommand fixToImageCommand=MesquiteModule.makeCommand("fixToImage",  this);
+	MesquiteCommand hidePointerCommand=MesquiteModule.makeCommand("hidePointer",  this);
+	MesquiteCommand showPointerCommand=MesquiteModule.makeCommand("showPointer",  this);
+	MesquiteCommand hideShadowCommand=MesquiteModule.makeCommand("hideShadow",  this);
+	MesquiteCommand showShadowCommand=MesquiteModule.makeCommand("showShadow",  this);
+	MesquiteCommand bringToFrontCommand=MesquiteModule.makeCommand("bringToFront",  this);
+	MesquiteCommand deleteLabelCommand=MesquiteModule.makeCommand("deleteLabel",  this);
+
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (touchedLabel == null)
+			return  super.doCommand(commandName, arguments, checker);
+		if (checker.compare(this.getClass(), "Sets the font", "[font name]", commandName, "setFont")) {
+			touchedLabel.setFontName(ParseUtil.getFirstToken(arguments, pos));
+			repaint();
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the font size", "[font size]", commandName, "setFontSize")) {
+			int siz = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			touchedLabel.setFontSize(siz);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Sets the color", "[color]", commandName, "setColor")) {
+			touchedLabel.setFontColor(ParseUtil.getFirstToken(arguments, pos));
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Fixes label to window", null, commandName, "fixToWindow")) {
+			touchedLabel.setFixedToImage(false);
+			recoverLostLabel(touchedLabel);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Fixes label to image", null, commandName, "fixToImage")) {
+			touchedLabel.setFixedToImage(true);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Hides the pointer", null, commandName, "hidePointer")) {
+			touchedLabel.setShowPointer(false);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Shows the pointer", null, commandName, "showPointer")) {
+			touchedLabel.setShowPointer(true);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Hides the shadow", null, commandName, "hideShadow")) {
+			touchedLabel.setShowShadow(false);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Shows the shadow", null, commandName, "showShadow")) {
+			touchedLabel.setShowShadow(true);
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Deletes the label", null, commandName, "deleteLabel")) {
+			AttachedNote note = pw.getCurrentNote();
+			note.deleteLabel(touchedLabel);
+			touchedLabel = null;
+			highlightedLabel = null;
+			repaint();
+		}
+		else if (checker.compare(this.getClass(), "Brings label to front", null, commandName, "bringToFront")) {
+			AttachedNote note = pw.getCurrentNote();
+			note.bringToFront(touchedLabel);
+			repaint();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void redoTheMenu() {
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		else
+			popup.removeAll();
+		MesquiteSubmenu submenuFont=MesquiteSubmenu.getFontSubmenu("Font", popup, null, setFontCommand);
+		popup.add(submenuFont);
+		MesquiteSubmenu submenuSize=MesquiteSubmenu.getFontSizeSubmenu("Font Size", popup, null, setFontSizeCommand);
+		popup.add(submenuSize);
+		MesquiteSubmenu submenuColor=MesquiteSubmenu.getSubmenu("Color", popup, null);
+		for (int i=0; i<ColorDistribution.standardColorNames.getSize(); i++) {
+			String s =ColorDistribution.standardColorNames.getValue(i);
+			if (s!=null)
+				submenuColor.add(new MesquiteMenuItem(s,  null, setColorCommand, StringUtil.tokenize(s)));
+		}
+		popup.add(submenuColor);
+		if (touchedLabel!= null){
+			if (touchedLabel.getFixedToImage())
+				popup.add(new MesquiteMenuItem("Fix Label to Window",  null, fixToWindowCommand));
+			else
+				popup.add(new MesquiteMenuItem("Fix Label to Image",  null, fixToImageCommand));
+			if (touchedLabel.getShowPointer())
+				popup.add(new MesquiteMenuItem("Hide Pointer",  null, hidePointerCommand));
+			else
+				popup.add(new MesquiteMenuItem("Show Pointer",  null, showPointerCommand));
+			if (touchedLabel.getShowShadow())
+				popup.add(new MesquiteMenuItem("Hide Shadow",  null, hideShadowCommand));
+			else
+				popup.add(new MesquiteMenuItem("Use White Shadow",  null, showShadowCommand));
+			popup.add(new MesquiteMenuItem("Bring to Front",  null, bringToFrontCommand));
+			popup.add(new MesquiteMenuItem("Delete Label",  null, deleteLabelCommand));
+
+		}
+
+		add(popup);
+	}
+}
+/*drop down menu:
+      		bring to front
+      		shadow
+      			white shadow
+      		use note style as default
+ */
+/* ======================================================================== */
+class ControlP extends MesquitePanel {
+	AnnotationsPanel pw;
+	MiniScroll scroll;
+	Image trash, addPic, goaway;
+	int maxValue;
+	boolean allowNewWindow;
+	int numicons = 3;
+	boolean attachable = true;
+	Font veryBigFont = new Font("SanSerif", Font.BOLD, 18);
+	Font bigFont = new Font("SanSerif", Font.PLAIN, 14);
+	Font smallFont = new Font("SanSerif", Font.PLAIN, 10);
+
+	public ControlP (AnnotationsPanel pw) {
+		this.pw = pw;
+		setFont(smallFont);
+		setBackground(ColorDistribution.brown);
+		add(scroll = new MiniScroll(MesquiteModule.makeCommand("goToNoteNumber", pw), false, 1, 1, 1,"image"));
+		scroll.setLocation(spacing*(numicons+1) + closeLeft, 6);
+		scroll.setSize(pw.controlsWidth, pw.textHeight);
+		scroll.setVisible(true);
+		trash = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "trashcan.gif");
+		addPic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "add.gif");
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goaway.gif");
+		/*
+		newPic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "new.gif");
+		spotPic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "spot.gif");
+		spotGreenPic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "spotgreen.gif");
+		 */
+	}
+	void setAttachable(boolean a){
+		attachable = a;
+		if (!attachable)
+			pw.setExplanation("There is no item selected to which annotations can be attached");
+		scroll.setVisible(a);
+	}
+	MiniScroll getScroll(){
+		return scroll;
+	}
+
+	int addLeft = 8;
+	int closeLeft = 2;
+	int iconTop = -1;
+	static int spacing = 22;
+	public void setCurrentValue(int i){
+		scroll.setCurrentValue(i);
+	}
+	public void setMaximumValue(int i){
+		maxValue = i;
+		if (i == 0)
+			scroll.setMinimumValue(0);
+		else
+			scroll.setMinimumValue(1);
+		if (scroll.getCurrentValue()>i)
+			scroll.setCurrentValue(i);
+		scroll.setMaximumValue(i);
+		scroll.setEnableEnter(i>1);
+	}
+	/*
+	public void setBackground(Color c){
+
+		Color q = ColorDistribution.medium[pw.getColorScheme()];
+		if (q == null)
+			super.setBackground(c);
+		else
+			super.setBackground(q);
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		int width = getBounds().width;
+		int height = getBounds().height;
+		g.setColor(Color.black);
+		g.drawRect(0, 0, width,height-1);
+		int miniscrollRight = scroll.getBounds().x + scroll.getBounds().width;
+		addLeft = closeLeft + spacing;
+		iconTop = height - 24;
+		int num = maxValue;
+		if (!attachable){
+			//g.drawString(s, miniscrollRight+4, height-12);
+			if (goaway != null)
+				g.drawImage(goaway, closeLeft, iconTop, this);
+		}
+		else {
+			g.setFont(veryBigFont);
+			g.setColor(Color.white);
+			int offset = 6;
+			if (pw.location != null) {
+				g.drawString(pw.location, miniscrollRight+4, height-12);
+				offset += StringUtil.getStringDrawLength(g, pw.location);
+			}
+			g.setFont(smallFont);
+			g.setColor(Color.black);
+			if (pw.where != null)
+				g.drawString(pw.where, miniscrollRight+4 + offset, height-12);
+
+			g.setColor(Color.black);
+			g.drawLine(spacing*numicons, 0, spacing*numicons,height);
+			g.setFont(bigFont);
+			g.drawString(Integer.toString(num), spacing*numicons+4, height-12);
+			g.setFont(smallFont);
+			if (goaway != null)
+				g.drawImage(goaway, closeLeft, iconTop, this);
+			if (addPic != null)
+				g.drawImage(addPic, addLeft, iconTop, this);
+			if (num >0 && trash != null)
+				g.drawImage(trash, addLeft+spacing, iconTop, this);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	static final int TRASH = 0;
+	static final int ADD = 1;
+	static final int CLOSE = 3;
+
+	int buttonFound(int x, int y){
+		if (x >= closeLeft && x< closeLeft + 16 && y >= iconTop && y< iconTop+16) 
+			return CLOSE;
+		else if (x >= addLeft && x< addLeft + 16 && y >= iconTop && y< iconTop+16) 
+			return ADD;
+		else if (x >= addLeft + spacing && x< addLeft + 16 + spacing && y >= iconTop && y< iconTop+16) 
+			return TRASH;
+		else
+			return -1;
+	}
+
+	private void explainButton(int b){
+		if (b==TRASH) 
+			pw.setExplanation("Trash can: delete the current note");
+		else if (b==ADD)
+			pw.setExplanation("(+) button: add a new note at this location");
+		else if (b==CLOSE) {
+			pw.setExplanation("Close: closes the annotations panel");
+		}
+		else
+			pw.setDefaultExplanation();
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (!attachable && b != CLOSE)
+			return;
+		explainButton(b);
+
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (!attachable && b != CLOSE)
+			return;
+		explainButton(b);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!attachable)
+			return;
+		pw.setDefaultExplanation();
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (!attachable && b != CLOSE)
+			return;
+		if (b==TRASH) 
+			pw.deleteCurrentNote(modifiers);
+		else if (b==ADD)
+			pw.requestAttachNote();
+		else if (b==CLOSE)
+			pw.panelGoAway(this);
+
+	}
+}
+/* ======================================================================== */
+class HeaderPanel extends MesquitePanel {
+	protected AnnotationsPanel pw;
+	String title;
+	Image triangle, triangleDown;
+	Image triangleRightOn, triangleDownOn;
+	static Image checkMark;
+
+	static {
+		checkMark = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "checkMark.gif");
+	}
+	public HeaderPanel (AnnotationsPanel pw, String title) {
+		this.pw = pw;
+		this.title = title;
+	}
+
+	int buttonFound(int x, int y){
+		return -1;
+	}
+	public void setTitle(String s){
+		title = s;
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		//if (pw.aim != null){
+		int width = getBounds().width;
+		int height = getBounds().height;
+		g.setColor(Color.black);
+		g.drawString(title, 4, height-6);
+		//}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+}
+/* ======================================================================== */
+class ImageHeaderPanel extends HeaderPanel {
+	String title;
+	Image trash, addPic, addRemotePic;
+	boolean hasPic = false;
+	int spacing = 22;
+
+	public ImageHeaderPanel (AnnotationsPanel pw, String title) {
+		super(pw, title);
+		trash = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "trashcan.gif");
+		addPic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "add.gif");
+		addRemotePic = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addRemote.gif");
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		super.paint(g);
+		if (pw.aim!=null){
+			if (pw.doIHaveContent(this))
+				g.drawImage(trash, addLeft, 2, this); 
+			else {
+				g.drawImage(addPic, addLeft, 2, this); 
+				g.drawImage(addRemotePic, addLeft + spacing, 2, this);
+			}
+
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	static final int ASIMAGE = 0;
+	static final int ASIMAGEREMOTE = 1;
+	static final int addLeft = 64;
+	int buttonFound(int x, int y){
+		if (x>addLeft && x< addLeft+16)
+			return ASIMAGE;
+		else if (!pw.doIHaveContent(this) && (x>addLeft + spacing && x< addLeft + spacing +16))
+			return ASIMAGEREMOTE;
+		else 
+			return super.buttonFound(x,y);
+	}
+
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (b==ASIMAGE) {
+			if (pw.doIHaveContent(this))
+				pw.setExplanation("Trash can: delete the image from this note.  This will not delete the image from its original location; it will delete only this note's reference to the image");
+			else
+				pw.setExplanation("(+) button: add a local image to this note. ");
+		}
+		else if (b==ASIMAGEREMOTE && !pw.doIHaveContent(this))
+			pw.setExplanation("(+') button: add a remote image (at a URL) to this note.");
+		else
+			pw.setDefaultExplanation();
+
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (b==ASIMAGE) {
+			if (pw.doIHaveContent(this))
+				pw.setExplanation("Trash can: delete the image from this note.  This will not delete the image from its original location; it will delete only this note's reference to the image");
+			else
+				pw.setExplanation("(+) button: add a local image to this note. ");
+		}
+		else if (b==ASIMAGEREMOTE && !pw.doIHaveContent(this))
+			pw.setExplanation("(+') button: add a remote image (at a URL) to this note.");
+		else
+			pw.setDefaultExplanation();
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		pw.setDefaultExplanation();
+	}
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		int b = buttonFound(x,y);
+		if (b==ASIMAGE)
+			pw.toggleImagePresence(this, modifiers, true);
+		else if (b==ASIMAGEREMOTE)
+			pw.toggleImagePresence(this, modifiers, false);
+		else
+			super.mouseUp(modifiers, x, y, tool);
+	}
+}
+
+/* ======================================================================== */
+class InfoPanel extends MesquitePanel implements TextListener {
+	AttachedNote note;
+	AnnotationsPanel pw;
+	int w =0;
+	int h = 0;
+	TextField authorLabel;
+	Label createdLabel, modLabel;
+	int labelWidth = 4;
+	String previousAuthor = null;
+	public InfoPanel (AnnotationsPanel pw) {
+		this.pw = pw;
+
+		//If there is a user's default author name, use it.  Otherwise copy from previous
+		Author auth = MesquiteModule.author;
+		String aName = null;
+
+		if (auth != null)
+			aName = auth.getName();
+		if (aName == null)
+			aName = previousAuthor;
+		add(authorLabel = new TextField(aName));
+
+		authorLabel.setEditable(true);
+		authorLabel.setBackground(Color.white);
+		authorLabel.addTextListener(this);
+		add(createdLabel = new Label());
+		add(modLabel =new Label());
+		//	modLabel.setBackground(Color.pink);
+		//	setBackground(Color.yellow);
+		setNote(null);
+	}
+	public void textValueChanged(TextEvent e){ //ONLY if 
+
+		if (e.getSource() == authorLabel){
+			String s = authorLabel.getText();
+			if ("".equals(s))
+				s = null;
+			if (note != null) {
+				if (s != null && note.getAuthor()!= null && s.equals(note.getAuthor().getName()))
+					return;
+				note.setAuthor(s);
+				previousAuthor = s;
+				modLabel.setText(note.getDateModified());
+			}
+		}
+	}
+	public void setBounds(int x, int y, int width, int height){
+		w = width;
+		h = height;
+		authorLabel.setBounds(0,0,width-0, height/2);
+		createdLabel.setBounds(labelWidth,height/2 +4,width/2-labelWidth, height/2-2);
+		modLabel.setBounds(labelWidth + width/2,height/2 +4,width/2-labelWidth, height/2-2);
+		super.setBounds(x, y, width, height);
+	}
+	public void setSize(int width, int height){
+		w = width;
+		h = height;
+		authorLabel.setBounds(4,0,width-labelWidth, height/2);
+		createdLabel.setBounds(4,height/2 +4,width/2-labelWidth, height/2-2);
+		modLabel.setBounds(labelWidth + width/2,height/2 +4,width/2-labelWidth, height/2-2);
+		super.setSize(width, height);
+	}
+	public void setNote(AttachedNote i){
+		note = i;
+		updateInfo();
+	}
+	public void updateInfo(){
+		if (note != null){
+			note.incrementStampSuppress();
+			authorLabel.setText(note.getAuthorName());
+			createdLabel.setText("Created " + note.getDateCreated());
+			modLabel.setText("Modified " + note.getDateModified());
+			note.decrementStampSuppress();
+		}
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawLine(0,0,w, 0);
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/lib/Arguments.java b/Source/mesquite/lib/Arguments.java
new file mode 100644
index 0000000..40b9c03
--- /dev/null
+++ b/Source/mesquite/lib/Arguments.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls */
+
+public class Arguments {
+	private Vector parameters;
+	private Vector values;
+	MesquiteInteger pos = new MesquiteInteger();
+	
+	//currently handles only simple arguments of form "token1 token 2 token3 = value3 token 4 = value4"
+	public Arguments(Parser parser, boolean hyphenIsNegative) { 
+		parameters = new Vector();
+		values = new Vector();
+		String token = parser.getNextToken();
+		
+		while (!StringUtil.blank(token) && !";".equalsIgnoreCase(token)){
+			if (hyphenIsNegative && "-".equalsIgnoreCase(token)) {
+				parameters.addElement(handleNegativeNumber(parser));
+				token = parser.getNextToken();
+				values.addElement("");
+			}
+			else {
+				parameters.addElement(token);
+				token = parser.getNextToken();
+				if (StringUtil.blank(token) || ";".equalsIgnoreCase(token))
+					values.addElement("");
+				else if ("=".equalsIgnoreCase(token)) {
+					token = parser.getNextToken();
+					if (hyphenIsNegative && "-".equalsIgnoreCase(token))
+						values.addElement(handleNegativeNumber(parser));
+					else
+						values.addElement(convertNull(token));
+					token = parser.getNextToken();
+				}
+				else
+					values.addElement("");
+			}
+				
+		}
+	}
+	public String toString() {
+		String s = "";
+		for (int i=0; i<parameters.size(); i++) {
+			s += "parameter [" + parameters.elementAt(i) + "]";
+			if (i<values.size() && !StringUtil.blank((String)values.elementAt(i)))
+				s += "  values [" + values.elementAt(i) + "]\n";
+			else
+				s += "\n";
+		}
+		return s;
+	}
+	private String handleNegativeNumber(Parser parser){
+		pos.setValue(parser.getPosition());
+		String s = parser.getString();
+		double i  = MesquiteDouble.fromString(s, pos);
+		parser.setPosition(pos.getValue());
+		return MesquiteDouble.toString(-i);
+	}
+	private String convertNull(String n){
+		if (n == null)
+			return "";
+		else
+			return n;
+	}
+	
+	public int getNumArguments(){
+		if (parameters == null )
+			return 0;
+		return parameters.size();
+	}
+	public boolean parameterExists(String arg){
+		if (parameters == null || arg == null)
+			return false;
+		for (int i=0; i<parameters.size(); i++) {
+			if (arg.equalsIgnoreCase((String)parameters.elementAt(i)))
+				return true;
+		}
+		return false;
+	}
+	public String getParameterValue(String arg){
+		if (parameters == null || arg == null)
+			return null;
+		for (int i=0; i<parameters.size(); i++) {
+			if (arg.equalsIgnoreCase((String)parameters.elementAt(i))) {
+				if (values == null || i>= values.size())
+					return null;
+				return (String)values.elementAt(i);
+			}
+		}
+		return null;
+	}
+	public int getParameterValueAsInt(String arg){
+		if (parameters == null || arg == null)
+			return MesquiteInteger.unassigned;
+		for (int i=0; i<parameters.size(); i++) {
+			if (arg.equalsIgnoreCase((String)parameters.elementAt(i))) {
+				if (values == null || i>= values.size())
+					return MesquiteInteger.unassigned;
+				String s = (String)values.elementAt(i);
+				return MesquiteInteger.fromString(s);
+			}
+		}
+		return MesquiteInteger.unassigned;
+	}
+	public String getParameter(int i){
+		if (parameters == null || i>= parameters.size())
+			return null;
+		return (String)parameters.elementAt(i);
+	}
+	public String getValue(int i){
+		if (values == null || i>= values.size())
+			return null;
+		return (String)values.elementAt(i);
+	}
+}
+
diff --git a/Source/mesquite/lib/Associable.java b/Source/mesquite/lib/Associable.java
new file mode 100644
index 0000000..72a3afe
--- /dev/null
+++ b/Source/mesquite/lib/Associable.java
@@ -0,0 +1,1706 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/*.................................................................................................................*/
+/** A class that contains serially repeated parts, to each of which may be attached information.
+For example, a Tree contains many nodes, and information might be attached to each node.  A Taxa contains taxons,
+a CharacterData contains characters, and so on.  The purpose of this class is to coordinate
+this attached ("associated") information.  Subclasses include FileElement (and thus CharacterData
+and Taxa) and Tree.  */
+public abstract class Associable extends Attachable implements Commandable, Annotatable, Selectionable {
+	Vector bits;
+	Vector longs;
+	Vector doubles;
+	Vector objects;
+	int[] defaultOrder;
+	int[] currentOrder;
+	int[] previousOrder;
+	Bits justAdded;
+	protected int numParts;
+	boolean dirty = false;
+	protected boolean rememberDefaultOrder = false;
+	public static int totalCreatedA=0;
+	public static int totalDisposedA=0;
+	public static int totalFinalizedA=0;
+
+
+	/** A number recording the version number.  With every change of the object, the version number is incremented. Used now for trees and taxa.*/
+	protected long versionNumber = 0;
+
+	protected String comment = null;
+
+	/** The bit field indicating which parts are selected currently.  This is instantiated only if needed.*/
+	protected Bits selected;
+
+	/** The object array storing comments (e.g. footnotes) for each of the parts.  This is instantiated only if needed.*/
+	protected ObjectArray comments;
+
+	public Associable (int numParts){
+		super();
+		totalCreatedA++;
+		this.numParts = numParts;
+		bits = new Vector();
+		longs = new Vector();
+		doubles = new Vector();
+		objects = new Vector();
+	}
+	public Associable (){
+		super();
+		totalCreatedA++;
+		//TODO: if comes this way, need to make vectors later when needed?
+	}
+	public void finalize() throws Throwable {
+		totalFinalizedA++;
+		super.finalize();
+	}
+	/** Disposes this associable */
+	public void dispose(){
+		totalDisposedA++;
+		if (bits!=null)
+			bits.removeAllElements();
+		if (longs!=null)
+			longs.removeAllElements();
+		if (doubles!=null)
+			doubles.removeAllElements();
+		if (objects!=null)
+			objects.removeAllElements();
+		bits = null;
+		longs = null;
+		doubles = null;
+		objects = null;
+		defaultOrder = null;
+		numParts = 0;
+		super.dispose();
+	}
+	public String toHTMLStringDescription(){
+		String sT = super.toHTMLStringDescription();
+		if (bits == null && longs == null && doubles == null && objects == null)
+			return sT;
+		String s = "";
+		if (bits!=null) {
+			for (int i=0; i<bits.size(); i++) {
+				Listable b = (Listable)bits.elementAt(i);
+				s += "<li>Bit array: " + b.getName()+ "</li>";	
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i<longs.size(); i++) {
+				Object obj = longs.elementAt(i);
+				Listable b = (Listable)longs.elementAt(i);
+				s += "<li>Long array: " + b.getName()+  "</li>";	
+			}
+		}
+		if (doubles!=null){
+			for (int i=0; i<doubles.size(); i++) {
+				Listable b = (Listable)doubles.elementAt(i);
+				s += "<li>Double array: " + b.getName()+  "</li>";	
+			}
+		}
+		if (objects!=null) {
+			for (int i=0; i<objects.size(); i++) {
+				Object obj = objects.elementAt(i);
+				if (obj instanceof Listable){
+					Listable b = (Listable)obj;
+					s += "<li>Object: " + b.getName()+ "</li>";	
+				}
+				else if (obj instanceof String){
+					s += "<li>String:  " + obj+ " </li>";	
+				}
+				else if (obj instanceof String[]){
+					s += "<li>String array</li>";	
+				}
+				else
+					s += "<li>Object of class " + obj.getClass().getName()+ "</li>";	
+			}
+		}
+		if (StringUtil.blank(s))
+			return sT;
+		sT += "<li>Associated: <ul>" + s + "</ul></li>";
+		return sT;
+	}
+	public String toString(int part){
+		String s = "";
+		String add = "";
+		if (bits == null && longs == null && doubles == null && objects == null)
+			return s;
+		if (bits!=null) {
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				s += add + "Bit \"" + b.getName()+ "\": ";	
+				if (((Bits)b).isBitOn(part))
+					s += " ON" ;
+				else
+					s += " OFF";
+				add = "; ";
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i<longs.size(); i++) {
+				Object obj = longs.elementAt(i);
+				LongArray b = (LongArray)longs.elementAt(i);
+				s += add + "\"" + b.getName()+ "\": " + b.getValue(part);	
+				add = "; ";
+			}
+		}
+		if (doubles!=null){
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				s += add + "\"" + b.getName()+ "\": " + b.getValue(part);	
+				add = "; ";
+			}
+		}
+		if (objects!=null) {
+			for (int i=0; i<objects.size(); i++) {
+				boolean changeAdd = true;
+				Object obja = objects.elementAt(i);
+				if (obja instanceof ObjectArray){
+					Object obj = ((ObjectArray)obja).getValue(part);
+					if (obj instanceof MesquiteString){
+						MesquiteString b = (MesquiteString)obj;
+						s += add + "\"" + b.getName()+ "\": " + b.getValue();	
+					}
+					else if (obj instanceof Listable){
+						Listable b = (Listable)obj;
+						s += add + "Object \"" + b.getName()+ "\"" + "  " + obj.getClass().getName();	
+					}
+					else if (obj instanceof String){
+						s += add + ((ObjectArray)obja).getName() + ": " + obj;	
+					}
+					else if (obj != null)
+						s += add +  "Object of class " + obj.getClass().getName();	
+					else
+						changeAdd = false;
+				}
+				else if (obja instanceof MesquiteString){
+					MesquiteString b = (MesquiteString)obja;
+					s += add + "\"" + b.getName()+ "\": " + b.getValue();	
+				}
+				else if (obja instanceof Listable){
+					Listable b = (Listable)obja;
+					s += add + "Object \"" + b.getName()+ "\"" + "  " + obja.getClass().getName();	
+				}
+				else if (obja instanceof String){
+					s += add + "String: " + obja + add;	
+				}
+				else 
+					s += add + "Object of class " + obja.getClass().getName();	
+				if (changeAdd)
+					add = "; ";
+			}
+		}
+		return s + ".  ";
+	}
+	public void equalizeParts(Associable other, int otherPart, int part){
+		if (other==null || part >= getNumberOfParts() || otherPart >= other.getNumberOfParts())
+			return;
+		if (other.bits!=null)
+			for (int i=0; i<other.bits.size(); i++) {
+				Bits b1 = (Bits)other.bits.elementAt(i);
+				NameReference nr = makeAssociatedBits(b1.getNameReference().getValue());
+				Bits b = getWhichAssociatedBits(nr);
+				b.setBit(part, b1.isBitOn(otherPart));
+			}
+		if (other.longs!=null)
+			for (int i=0; i<other.longs.size(); i++) {
+				LongArray b1 = (LongArray)other.longs.elementAt(i);
+				NameReference nr = makeAssociatedLongs(b1.getNameReference().getValue());
+				LongArray b = getWhichAssociatedLong(nr);
+				b.setValue(part, b1.getValue(otherPart));
+			}
+		if (other.doubles!=null)
+			for (int i=0; i<other.doubles.size(); i++) {
+				DoubleArray b1 = (DoubleArray)other.doubles.elementAt(i);
+				NameReference nr = makeAssociatedDoubles(b1.getNameReference().getValue());
+				DoubleArray b = getWhichAssociatedDouble(nr);
+				b.setValue(part, b1.getValue(otherPart));
+			}
+		if (other.objects!=null)
+			for (int i=0; i<other.objects.size(); i++) {
+
+				ObjectArray b1 = (ObjectArray)other.objects.elementAt(i);
+				NameReference nr = makeAssociatedObjects(b1.getNameReference().getValue());
+				ObjectArray b = getWhichAssociatedObject(nr);
+				b.setValue(part, b1.getValue(otherPart));
+			}
+	}
+	public void setJustAdded(int part, boolean b){
+		if (part<0 || part>=numParts)
+			return;
+		if (justAdded == null || justAdded.getSize()!=numParts) {
+			justAdded = new Bits(numParts);
+		}
+		justAdded.setBit(part,b);
+	}
+	public boolean getJustAdded(int part) {
+		if (part<0 || part>=numParts || justAdded==null)
+			return false;
+		return justAdded.isBitOn(part);
+	}
+	public void resetJustAdded(){
+		justAdded=null;
+	}
+	public void deleteJustAdded(){
+		if (justAdded != null) {
+			for (int i=numParts-1; i>0; i--)
+				if (justAdded.isBitOn(i))
+					deleteParts(i,1);
+		}
+	}
+	protected void recordDefaultOrder(){
+		rememberDefaultOrder = true;
+		if (defaultOrder == null)
+			defaultOrder = new int[numParts];
+		for (int i=0; i<numParts; i++)
+			defaultOrder[i] = i;
+	}
+	public void recordCurrentOrder(){
+		if (currentOrder == null)
+			currentOrder = new int[numParts];
+		for (int i=0; i<numParts; i++)
+			currentOrder[i] = i;
+	}
+	public void recordPreviousOrder(){
+		if (previousOrder == null)
+			previousOrder = new int[numParts];
+		for (int i=0; i<numParts; i++)
+			previousOrder[i] = i;
+	}
+	public void copyCurrentToPreviousOrder(){
+		if (previousOrder == null || currentOrder==null)
+			return;
+		for (int i=0; i<previousOrder.length && i<currentOrder.length; i++)
+			previousOrder[i] = currentOrder[i];
+	}
+	/*-----------------------------------------*/
+	/** Returns version number of Associable.  Version number should be incremented with each change.*/
+	public long getVersionNumber(){
+		return versionNumber;
+	}
+	public int getNumberOfParts() {
+		return numParts;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		boolean saveSnapOrd = rememberDefaultOrder && !orderMonotonic();
+		boolean saveSnapSel = anySelected();
+		boolean saveSnapAttach = anyAttachments();
+		String list = null;
+		if (saveSnapSel){
+			list = selected.getListOfBitsOn(1);
+			saveSnapSel = !StringUtil.blank(list);
+		}
+
+		if (saveSnapSel || saveSnapOrd || saveSnapAttach) {
+			Snapshot temp = new Snapshot();
+			if (saveSnapSel)
+				temp.addLine("setSelected " + list);
+			if (saveSnapOrd)
+				temp.addLine("setDefaultOrder " + getDefaultOrderNEXUS());
+			temp.addLine("attachments "+ writeAttachments(false));
+			return temp;
+		}
+		return null;
+	}
+	/*-----------------------------------------*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/** For Commandable interface.  TODO:  have setDouble and pass part; have getDouble and pass part.  Likewise for long, etc. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Sets the value of an associated double", "[name of double][value]", commandName, "setDoubleOfSelected")) {
+			String name = ParseUtil.getFirstToken(arguments, pos);
+			if (StringUtil.blank(name))
+				return null;
+			double bL = MesquiteDouble.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(bL)|| MesquiteDouble.isUnassigned(bL)){
+				NameReference nr = NameReference.getNameReference(name);
+				boolean c = false;
+				for (int i = 0; i<numParts; i++)
+					if (getSelected(i)) {
+						setAssociatedDouble(nr, i, bL);
+						c = true;
+					}
+				if (c)
+					notifyListeners(this, new Notification(MesquiteListener.ASSOCIATED_CHANGED));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Stores attachments", null, commandName, "attachments")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			ParseUtil.getToken(arguments, pos);
+			readAttachments(arguments, pos);
+		}
+		else if (checker.compare(this.getClass(), "Sets what parts are selected", "[list of parts]", commandName, "setSelected")) {
+			int lastPart = -1;
+			boolean join = false;
+			MesquiteInteger pos = new MesquiteInteger(0);
+			String token =  ParseUtil.getToken(arguments, pos); 
+			boolean some = false;
+			if (selected!=null)
+				selected.clearAllBits();
+			while (!StringUtil.blank(token) && !token.equals(";")) {
+				if (token.equals(",") || token.equals(";")){
+				}
+				else	if (token.equals("-")) {
+					if (lastPart!=-1)
+						join = true;
+				}
+				else {
+					int whichPart = MesquiteInteger.fromString(token, false);
+					if (MesquiteInteger.isCombinable(whichPart)) {
+						whichPart--; //to reset to 0 based
+						if (join) {
+							for (int j = lastPart; j<=whichPart; j ++)
+								setSelected(j, true);
+							join = false;
+							lastPart = -1;
+						}
+						else {
+							lastPart = whichPart;
+							setSelected(whichPart, true);
+							some = true;
+						}
+					}
+				}
+				token = ParseUtil.getToken(arguments, pos); 
+			}
+
+			if (some && !MesquiteThread.isScripting())
+				notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+		else if (checker.compare(this.getClass(), "Sets default order of parts", "[list of positions]", commandName, "setDefaultOrder")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			String token =  ParseUtil.getToken(arguments, pos); 
+			int part = -1;
+			while (!StringUtil.blank(token) && !token.equals(";")) {
+				int position = MesquiteInteger.fromString(token, false);
+				part++;
+				if (MesquiteInteger.isCombinable(position)) {
+					setDefaultPosition(part, position);
+				}
+				token = ParseUtil.getToken(arguments, pos); 
+			}
+
+		}
+		return null;
+	}
+	/** Sets the comment (e.g., footnote) of this element */
+	public void setAnnotation(String e, boolean notify){
+		comment = e;
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+	}
+	/** Returns the comment (e.g., footnote) of this element */
+	public String getAnnotation(){
+		return comment;
+	}
+	/*.................................................................................................................*/
+	/** Sets the element as dirty (changed since last file save) or not */
+	public void setDirty(boolean d){
+
+		if (d == true){
+			versionNumber++;
+		}
+		dirty = d;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether the element is dirty (changed since last file save) or not */
+	public boolean getDirty(){
+		return dirty;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if part is within bounds.*/
+	protected  boolean inBounds(int part) {
+		return part>=0 && part<numParts; 
+	}
+	public String listAssociates(){ //changed May 02
+		String s = " Associates of ";
+		if (this instanceof Listable)
+			s =  getName() + "\n";
+		else
+			s = "object of class " + getClass().getName() + "\n";
+		if (bits!=null) {
+			s += "Bits " + '\n';
+			for (int i=0; i<bits.size(); i++) {
+				Listable b = (Listable)bits.elementAt(i);
+				s += "   " + b.getName()+ "\n";	
+			}
+		}
+		if (longs!=null) {
+			s += "Longs " + '\n';
+			for (int i=0; i<longs.size(); i++) {
+				Object obj = longs.elementAt(i);
+				Listable b = (Listable)longs.elementAt(i);
+				s += "   " + b.getName()+ "\n";	
+			}
+		}
+		if (doubles!=null){
+			s += "Doubles " + '\n';
+			for (int i=0; i<doubles.size(); i++) {
+				Listable b = (Listable)doubles.elementAt(i);
+				s += "   " + b.getName()+ "\n";	
+			}
+		}
+		if (objects!=null) {
+			s += "Objects " + '\n';
+			for (int i=0; i<objects.size(); i++) {
+				Object obj = objects.elementAt(i);
+				if (obj instanceof Listable){
+					Listable b = (Listable)obj;
+					s += "   " + b.getName()+ "\n";	
+				}
+				else if (obj instanceof String){
+					s += "  string:  " + obj+ "\n";	
+				}
+				else if (obj instanceof String[]){
+					s += "  strings:  ";
+					String[] st = (String[])obj;
+					for (int k = 0; k<st.length; k++)
+						s += " [" + st[k] + "]";
+					s += "\n";	
+				}
+				else
+					s += "   Object of class " + obj.getClass().getName()+ "\n";	
+			}
+		}
+		return s;
+	}
+	public String writeAssociated(int node, boolean associatedUseComments){
+		String s = null;
+		if (associatedUseComments)
+			s = "[%";
+		else
+			s = "<";
+		boolean first = true;
+		boolean biton = false;
+		if (bits!=null)
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b.isBitOn(node)) {
+					if (!first)
+						s += " , ";
+					first = false;
+					s+= StringUtil.tokenize(b.getName()) + " = on ";
+					biton = true;
+				}
+			}
+		if (longs!=null)
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+
+				if (b.getValue(node)!=MesquiteLong.unassigned) {
+					if (!first)
+						s += " , ";
+					first = false;
+					s+= StringUtil.tokenize(b.getName()) + " = " + MesquiteLong.toString(b.getValue(node)) + " ";
+				}
+			}
+		if (doubles!=null)
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b.getValue(node)!=MesquiteDouble.unassigned){
+					if (!first)
+						s += " , ";
+					first = false;
+					s+= StringUtil.tokenize(b.getName()) + " = " + MesquiteDouble.toString(b.getValue(node)) + " ";
+				}
+			}
+		if (objects!=null)
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				Object obj = b.getValue(node);
+				if (obj!=null && (obj instanceof Listable || obj instanceof String)){
+					if (!first)
+						s += " , ";
+					first = false;
+					if (obj instanceof Listable)
+						s+= StringUtil.tokenize(b.getName()) + " = " + ParseUtil.tokenize(((Listable)obj).getName()) + " ";
+					else if (obj instanceof String){
+						s+= StringUtil.tokenize(b.getName()) + " = " + ParseUtil.tokenize("string:" + (String)obj) + " ";
+					}
+					else if (obj instanceof String[] && ((String[])obj).length>0){
+						MesquiteMessage.warnProgrammer("String[] saving in associables not yet working!");
+						/*s += b.getName() + " = strings ( ";
+						String[] st = (String[])obj;
+						for (int k = 0; k<st.length; k++)
+							s += " " + ParseUtil.tokenize(st[k]);
+						s += ") ";*/	
+					}
+				}
+			}
+		if ((associatedUseComments && s.equals("[%")) || (!associatedUseComments && s.equals("<")))
+			return "";
+		else if (associatedUseComments)
+			return s+ "]";
+		else
+			return s + ">";
+	}
+	public void readAssociated(String assocString, int node, MesquiteInteger pos){
+		if (pos==null || node>numParts || node<0 || StringUtil.blank(assocString))
+			return;
+		String s=ParseUtil.getToken(assocString, pos);
+		while (!">".equals(s)) {
+			if (StringUtil.blank(s))
+				return;
+			ParseUtil.getToken(assocString, pos); //eating up equals
+			int oldPos = pos.getValue();
+			String value = ParseUtil.getToken(assocString, pos); //finding value
+			if (StringUtil.blank(value))
+				return;
+			if (value.equalsIgnoreCase("on")) {
+				NameReference nr = makeAssociatedBits(s);
+				Bits bb = getWhichAssociatedBits(nr);
+				bb.setBit(node, true);
+			}
+			else if (value.equalsIgnoreCase("off")) {
+				NameReference nr = makeAssociatedBits(s);
+				Bits bb = getWhichAssociatedBits(nr);
+				bb.setBit(node, false);
+			}
+			else if (value.indexOf("string:") == 0) { //treat as String 
+
+				NameReference nr = makeAssociatedObjects(s);
+				ObjectArray bb = getWhichAssociatedObject(nr);
+				bb.setValue(node, value.substring(7, value.length()));
+			}
+			else if (value.indexOf("strings") == 0) { //treat as String[] 
+
+				NameReference nr = makeAssociatedObjects(s);
+				ObjectArray bb = getWhichAssociatedObject(nr);		
+				//	bb.setValue(node, value.substring(7, value.length()));
+			}
+			else if (value.indexOf("{") == 0) { //treat as String bounded by {}; added to read BEAST results
+				String stored = "";
+				String name = s;
+				while (!">".equals(s) && !"}".equals(s)) {
+					s=ParseUtil.getToken(assocString, pos);
+					if ((!">".equals(s) && !"}".equals(s)))
+						stored += s;
+				}
+				NameReference nr = makeAssociatedObjects(name);
+				ObjectArray bb = getWhichAssociatedObject(nr);
+				bb.setValue(node, stored);
+			}
+			else if (value.indexOf(".")>=0 && MesquiteDouble.interpretableAsDouble(assocString, pos, oldPos)) { //treat as double 
+				NameReference nrEx= NameReference.getNameReference(s);   // fixed in 3.01
+				DoubleArray bb = getWhichAssociatedDouble(nrEx);       //Finding doubles if they exist
+				if (bb == null) {
+					//Making doubles to be filled
+					NameReference nr = makeAssociatedDoubles(s);
+					bb = getWhichAssociatedDouble(nr);
+
+					//but first check to see if there are longs.  If so, and if doubles hadn't existed before, then transfer
+					NameReference nrExL= NameReference.getNameReference(s);
+					LongArray longs = getWhichAssociatedLong(nrExL);
+					if (longs != null){
+						//There is an array of longs of the same name.  It's therefore assumed that they should all be upgraded to doubles!
+						longs.copyTo(bb);
+						removeAssociatedLongs(nrExL);   //delete longs as no longer needed
+					}
+
+				}
+				pos.setValue(oldPos);
+				bb.setValue(node, MesquiteDouble.fromString(assocString, pos));
+			}
+			//at this point there are just two alternatives left that are recognized: an undeclared string, and an integer
+			//first check to see if it could be a number
+			else if ("0123456789-".indexOf(value.charAt(0))<0 || !MesquiteLong.interpretableAsLong(assocString, pos, oldPos)) {  //doesn't start as number or starts as number but not interpretable as long
+				NameReference nr = makeAssociatedObjects(s);
+				ObjectArray bb = getWhichAssociatedObject(nr);
+				bb.setValue(node, value);
+			}
+			else {  //treat as long, unless (fixed in 3.01) same name exists as DoubleArray in which case put there
+				NameReference nrEx= NameReference.getNameReference(s);   // 
+				DoubleArray bbd = getWhichAssociatedDouble(nrEx);       //Finding doubles if they exist; if so, use as doubles instead!!!!!
+				if (bbd != null){
+					pos.setValue(oldPos);
+					bbd.setValue(node, MesquiteInteger.fromString(assocString, pos));
+				} 
+				else {
+					NameReference nr = makeAssociatedLongs(s);
+					LongArray bb = getWhichAssociatedLong(nr);
+					pos.setValue(oldPos);
+					bb.setValue(node, MesquiteInteger.fromString(assocString, pos));
+				}
+			}
+			s=ParseUtil.getToken(assocString, pos);
+			if (",".equals(s)) //eating up "," separating subcommands
+				s=ParseUtil.getToken(assocString, pos);
+		}
+	}
+	public void setAssociateds(Associable a){
+		if (a==null)
+			return;
+		setNumberOfParts(a.getNumberOfParts());
+		bits.removeAllElements();
+		longs.removeAllElements();
+		//xxxxx
+		doubles.removeAllElements();
+		objects.removeAllElements();
+		if (a.bits!=null)
+			for (int i=0; i<a.bits.size(); i++) {
+				Bits b1 = (Bits)a.bits.elementAt(i);
+				NameReference nr = makeAssociatedBits(b1.getNameReference().getValue());
+				Bits b = getWhichAssociatedBits(nr);
+				b1.copyBits(b);
+				b.setBetweenness(b1.isBetween());
+			}
+		if (a.longs!=null)
+			for (int i=0; i<a.longs.size(); i++) {
+				LongArray b1 = (LongArray)a.longs.elementAt(i);
+				NameReference nr = makeAssociatedLongs(b1.getNameReference().getValue());
+				LongArray b = getWhichAssociatedLong(nr);
+				b1.copyTo(b);
+				b.setBetweenness(b1.isBetween());
+			}
+		if (a.doubles!=null)
+			for (int i=0; i<a.doubles.size(); i++) {
+				DoubleArray b1 = (DoubleArray)a.doubles.elementAt(i);
+				NameReference nr = makeAssociatedDoubles(b1.getNameReference().getValue());
+				DoubleArray b = getWhichAssociatedDouble(nr);
+				b1.copyTo(b);
+				b.setBetweenness(b1.isBetween());
+			}
+		if (a.objects!=null)
+			for (int i=0; i<a.objects.size(); i++) {
+
+				ObjectArray b1 = (ObjectArray)a.objects.elementAt(i);
+				NameReference nr = makeAssociatedObjects(b1.getNameReference().getValue());
+				ObjectArray b = getWhichAssociatedObject(nr);
+				b1.copyTo(b);
+				b.setBetweenness(b1.isBetween());
+			}
+	}
+	public void transferAssociated(int fromNode, int toNode){
+		//setDirty???
+		if (bits!=null)
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.setBit(toNode, b.isBitOn(fromNode));
+			}
+		if (longs!=null)
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.setValue(toNode, b.getValue(fromNode));
+			}
+		if (doubles!=null)
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.setValue(toNode, b.getValue(fromNode));
+			}
+		if (objects!=null)
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.setValue(toNode, b.getValue(fromNode));
+			}
+	}
+
+	public void exchangeAssociated(int node1, int  node2){
+		if (bits!=null)
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				boolean n1 = b.isBitOn(node1);
+				b.setBit(node1, b.isBitOn(node2));
+				b.setBit(node2, n1);
+			}
+		if (longs!=null)
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				long n1 = b.getValue(node1);
+				b.setValue(node1, b.getValue(node2));
+				b.setValue(node2, n1);
+			}
+		if (doubles!=null)
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				double n1 = b.getValue(node1);
+				b.setValue(node1, b.getValue(node2));
+				b.setValue(node2, n1);
+			}
+		if (objects!=null)
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				Object n1 = b.getValue(node1);
+				b.setValue(node1, b.getValue(node2));
+				b.setValue(node2, n1);
+			}
+	}
+	public void deassignAssociated(int node){
+		if (bits!=null)
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.clearBit(node);	
+			}
+		if (longs!=null)
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.setValue(node, MesquiteLong.unassigned);
+			}
+		if (doubles!=null)
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.setValue(node, MesquiteDouble.unassigned);
+			}
+		if (objects!=null)
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.setValue(node, null);
+			}
+	}
+	public void deassignAssociated(){
+		if (bits!=null)
+			bits.removeAllElements();
+		if (longs!=null)
+			longs.removeAllElements();
+		if (doubles!=null)
+			doubles.removeAllElements();
+		if (objects!=null)
+			objects.removeAllElements();
+	}
+
+	/** Set the number of parts to given number.  THIS MUST BE CALLED whenever the number of
+	parts (characters, nodes, etc.) changes.*/
+	public void setNumberOfParts(int num){
+		//TODO: adjust all associated information for newNum
+		if (numParts==num)
+			return;
+		numParts = num;
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.resetSize(numParts);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.resetSize(numParts);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.resetSize(numParts);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.resetSize(numParts);
+			}
+		setDirty(true);
+	}
+	/*-----------------------------------------*/
+	private int[] addToOrder(int[] order, int starting, int num) {
+		//if adding to end, then put after maximum
+		//if adding to middle, then give new parts their native numbers and shift any above their range upward, even if currently in front of new parts
+		if (defaultOrder==null) {
+			int[] newValues = new int[numParts+num];
+			for (int i=0; i<numParts+num; i++) { 
+				newValues[i]=i;
+			}
+			return newValues;
+		}
+
+		boolean addToEnd = false;
+		int maxValue = numParts-1;
+		if (starting == numParts) {
+			starting = numParts-1;
+			addToEnd = true;
+			maxValue = IntegerArray.maximum(defaultOrder);
+		}
+		int newNum = numParts + num;
+		int[] newValues = new int[newNum];
+		//if before point of insertion, just copy default order
+		for (int i=0; i<=starting; i++) { 
+			newValues[i]=defaultOrder[i];
+			if (!addToEnd && newValues[i]>starting) {
+				newValues[i] += num+1;
+			}
+		}
+		//for inserted ones, give new numbers bigger than previous
+		for (int i=0; i<num ; i++) {
+			if (addToEnd)
+				newValues[starting + i + 1]= ++maxValue;
+			else
+				newValues[starting + i + 1]= starting + i + 1;
+		}
+		//after insertion, give new numbers bigger than previous
+		for (int i=0; i<numParts-starting-1; i++) {
+			if (starting+i+1>=defaultOrder.length)
+				newValues[i +starting+num+1]=starting + i + 1;
+			else
+				newValues[i +starting+num+1]=defaultOrder[starting + i + 1];
+			if (!addToEnd && newValues[i +starting+num+1]>=starting) {
+				newValues[i +starting+num+1] += num;
+			}
+		}
+		return newValues;
+	}
+	/*-----------------------------------------*/
+	public String report(){
+		String r = "class " + getClass().getName() + "\n";
+		r += " numParts " + numParts + "\n";
+		r += " defaultOrder " + defaultOrder + "\n";
+		r += " currentOrder " + currentOrder + "\n";
+		r += " previousOrder " + previousOrder + "\n";
+		return r;
+	}
+	public static long totalPartsAdded = 0;
+	public boolean addParts(int starting, int num){
+		if (num==0)
+			return false;
+		try {
+			totalPartsAdded+=num;
+			if (starting<0) starting = -1;
+			if (starting>numParts) starting = numParts;
+			if (bits!=null) {
+				for (int i=0; i< bits.size(); i++) {
+					Bits b = (Bits)bits.elementAt(i);
+					b.addParts(starting, num);
+				}
+			}
+			if (longs!=null) {
+				for (int i=0; i< longs.size(); i++) {
+					LongArray b = (LongArray)longs.elementAt(i);
+					b.addParts(starting, num, MesquiteLong.unassigned);
+				}
+			}
+			if (doubles!=null)
+				for (int i=0; i< doubles.size(); i++) {
+					DoubleArray b = (DoubleArray)doubles.elementAt(i);
+					b.addParts(starting, num);
+				}
+			if (objects!=null)
+				for (int i=0; i< objects.size(); i++) {
+					ObjectArray b = (ObjectArray)objects.elementAt(i);
+					b.addParts(starting, num); //comments handled here
+				}
+			if (defaultOrder != null){
+				defaultOrder = addToOrder(defaultOrder,starting,num);
+			}
+			if (currentOrder != null){
+				currentOrder = addToOrder(currentOrder,starting,num);
+			}
+			if (previousOrder != null){
+				previousOrder = addToOrder(previousOrder,starting,num);
+			}
+			if (justAdded!=null) {
+				justAdded.addParts(starting, num);
+			}
+			numParts = numParts+num;
+			for (int i=0;i<num; i++)
+				setJustAdded(starting+i+1, true);
+		}
+		catch (Exception e){
+		}
+
+		setDirty(true);
+		return true;
+	}
+	/*-----------------------------------------*/
+	public boolean deleteParts(int starting, int num){
+
+		if (num==0)
+			return false;
+		if (starting>numParts || starting<0) 
+			return false;
+
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.deleteParts(starting, num);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.deleteParts(starting, num);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.deleteParts(starting, num);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.deleteParts(starting, num); //comments handled here
+			}
+		if (defaultOrder != null){
+			defaultOrder = IntegerArray.deleteParts(defaultOrder, starting, num);
+		}
+		if (currentOrder != null){
+			currentOrder = IntegerArray.deleteParts(currentOrder, starting, num);
+		}
+		if (previousOrder != null){
+			previousOrder = IntegerArray.deleteParts(previousOrder, starting, num);
+		}
+		numParts = numParts-num;
+		setDirty(true);
+		return true;
+	}
+	/*-----------------------------------------*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (num==0)
+			return false;
+		if (starting>numParts || starting<0) 
+			return false;
+		if ((justAfter>=starting && justAfter<=starting+num-1))
+			return false;
+
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.moveParts(starting, num, justAfter);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.moveParts(starting, num, justAfter);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.moveParts(starting, num, justAfter);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.moveParts(starting, num, justAfter); //comments handled here
+			}
+		if (defaultOrder != null){
+			defaultOrder = IntegerArray.moveParts(defaultOrder, starting, num, justAfter);
+		}
+		if (currentOrder != null){
+			currentOrder = IntegerArray.moveParts(currentOrder, starting, num, justAfter);
+		}
+		if (previousOrder != null){
+			previousOrder = IntegerArray.moveParts(previousOrder, starting, num, justAfter);
+		}
+
+
+		setDirty(true);
+		return true;
+	}
+	public void restoreToPreviousOrder(){
+		if (previousOrder == null)
+			return;
+		for (int current = 0; current<numParts; current++) {
+			int i = 0;
+			boolean found = false;
+			while (i<numParts && !found) {
+				if (previousOrder[i] == current) {// we've found the next one
+					moveParts(i,1,current-1);
+					found = true;
+				}
+				i++;
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	public boolean swapParts(int first, int second){
+		if (first>numParts || first<0) 
+			return false;
+		if (second>numParts || second<0) 
+			return false;
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				b.swapParts(first, second);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				b.swapParts(first, second);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				b.swapParts(first, second);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				b.swapParts(first, second); //comments handled here
+			}
+		if (defaultOrder != null){
+			IntegerArray.swapParts(defaultOrder, first, second);
+		}
+		if (currentOrder != null){
+			IntegerArray.swapParts(currentOrder, first, second);
+		}
+		if (previousOrder != null){
+			IntegerArray.swapParts(previousOrder, first, second);
+		}
+
+		setDirty(true);
+		return true;
+	}
+	/* ---------------------Default Order -----------------------*/
+	public int getDefaultPosition(int part){
+		if (!inBounds(part) || defaultOrder == null)
+			return -1;
+		return defaultOrder[part];
+	}
+	public void setDefaultPosition(int part, int position){
+		if (!inBounds(part) || defaultOrder == null)
+			return;
+		defaultOrder[part] = position;
+	}
+	public void resetDefaultOrderToCurrent(){
+		if (defaultOrder != null){
+			for (int i=0; i<numParts; i++)
+				defaultOrder[i] = i;
+		}
+	}
+
+	private boolean orderMonotonic(){
+		if (defaultOrder ==null)
+			return true;
+		for (int i=1; i<defaultOrder.length; i++){
+			if (defaultOrder[i] <= defaultOrder[i-1])
+				return false;
+		}
+		return true;
+	}
+
+	private String getDefaultOrderNEXUS(){
+		StringBuffer sb = new StringBuffer(50);
+		for (int i = 0; i< defaultOrder.length; i++) {
+			sb.append(' ');
+			sb.append(Integer.toString(defaultOrder[i]));
+		}
+		return sb.toString();
+	}
+
+
+	/* ---------------------COMMENTS -----------------------*/
+	/*-----------------------------------------*/
+	/** Sets the comment for a part */
+	public void setAnnotation(int part, String comment) {
+		if (!inBounds(part))
+			return;
+		if (comments==null) {
+			NameReference sN = makeAssociatedObjects("comments");
+			comments = getWhichAssociatedObject(sN);
+		}
+		comments.setValue(part, comment);
+		setDirty(true);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether the part is selected */
+	public String getAnnotation(int part) {
+		if (!inBounds(part))
+			return null;
+		if (comments==null)
+			return null;
+		return (String)comments.getValue(part);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any selected parts *
+	public boolean anyComments() {
+		if (comments!=null)
+			return comments.anyBitsOn();
+		else
+			return false;
+	}
+	/* ---------------------SELECTION -----------------------*/
+	/** Returns number of parts that can be selected*/
+	public int getNumberOfSelectableParts(){
+		return getNumberOfParts();
+	}
+	/*-----------------------------------------*/
+	/** Sets whether or not the part is selected */
+	public void setSelected(int part, boolean select) {
+		if (!inBounds(part))
+			return;
+		if (selected==null) {
+			NameReference sN = makeAssociatedBits("selected");
+			selected = getWhichAssociatedBits(sN);
+		}
+		if (select)
+			selected.setBit(part);
+		else
+			selected.clearBit(part);
+		setDirty(true);
+	}
+	/*-----------------------------------------*/
+	/** Sets whether or not the part is selected */
+	public void setSelected(int partStart, int partEnd, boolean select) {
+		for (int i=partStart; i<=partEnd; i++)
+			setSelected(i,select);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether the part is selected */
+	public boolean getSelected(int part) {
+		if (!inBounds(part))
+			return false;
+		if (selected==null)
+			return false;
+		return selected.isBitOn(part);
+	}
+	/*-----------------------------------------*/
+	/** Deselects all parts */
+	public void deselectAll(){
+		if (selected!=null)
+			selected.clearAllBits();
+		setDirty(true);
+	}
+	/*-----------------------------------------*/
+	/** Selects all parts */
+	public void selectAll(){
+		if (selected==null) {
+			NameReference sN = makeAssociatedBits("selected");
+			selected = getWhichAssociatedBits(sN);
+		}
+		if (selected!=null)
+			selected.setAllBits();
+		setDirty(true);
+	}
+	/*-----------------------------------------*/
+	/** Returns index of first selected part */
+	public int firstSelected() {
+		if (!anySelected())
+			return -1;
+		for (int i = 0; i<getNumberOfParts(); i++) {
+			if (selected.isBitOn(i))
+				return i;
+		}
+		return -1;
+	}
+	/*-----------------------------------------*/
+	/** Returns index of last selected part */
+	public int lastSelected() {
+		if (!anySelected())
+			return -1;
+		for (int i = getNumberOfParts()-1; i>=0; i--) {
+			if (selected.isBitOn(i)) {
+				return i;
+
+			}
+		}
+		return -1;
+	}
+	/*-----------------------------------------*/
+	/** Returns selected directly */
+	public Bits getSelectedBits() {
+		return selected;
+	}
+
+	/*-----------------------------------------*/
+	/** Returns whether there are selected parts that form a contiguous selection */
+	public boolean contiguousSelection() {
+		if (!anySelected())
+			return false;
+		int firstSelected = selected.nextBit(0, true);
+		if (firstSelected<0)  // none is selected
+			return false;
+		int nextNotSelected = selected.nextBit(firstSelected+1,false);  // first one, after the block, that is not selected
+		if (nextNotSelected>0) {
+			return (selected.nextBit(nextNotSelected+1,true)==-1);  //no more have been found
+		}
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any selected parts */
+	public boolean anySelected() {
+		if (selected!=null)
+			return selected.anyBitsOn();
+		else
+			return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns number of selected parts */
+	public int numberSelected() {
+		if (selected!=null)
+			return selected.numBitsOn();
+		else
+			return 0;
+	}
+	/*-----------------------------------------*/
+	/** returns number of parts that are selected or, if onlyCountSelected is false, all parts*/
+	public int numberSelected(boolean onlyCountSelected) {
+		if (onlyCountSelected)
+			return numberSelected();
+		else
+			return getNumberOfParts();
+	}
+	/* ---------------------BITS------------------------*/
+	public int getNumberAssociatedBits(){
+		if (bits==null)
+			return 0;
+		else
+			return bits.size();
+	}
+	public Bits getAssociatedBits(int index){
+		if (bits!=null && index>=0 && index<bits.size()) {
+			return (Bits)bits.elementAt(index);
+		}
+		return null;
+	}
+	public NameReference makeAssociatedBits(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		Bits b = (getWhichAssociatedBits(nr));
+		if (b==null) {
+			b = new Bits(numParts);
+			b.setNameReference(nr);
+			bits.addElement(b);
+		}
+		setDirty(true);
+		return nr;
+	}
+	public void removeAssociatedBits(NameReference nRef){
+		boolean found = false;
+		if (bits!=null && nRef!=null) {
+			for (int i=0; i<bits.size() && !found; i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					bits.removeElement(b);
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public Bits getWhichAssociatedBits(NameReference nRef){
+		if (bits!=null && nRef!=null) {
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					return b; 
+				}
+			}
+		}
+		return null;
+	}
+	public void clearAllAssociatedBits(NameReference nRef){
+		boolean found = false;
+		if (bits!=null && nRef!=null) {
+			for (int i=0; i<bits.size() && !found; i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.clearAllBits(); 
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public void setAssociatedBit(NameReference nRef, int index, boolean value){
+		setAssociatedBit(nRef, index, value, false);
+	}
+
+	/*generally not used directly, as setAsBetween is rarely true.  When setAsBetween is true the betweenness is set to true;
+	 * otherwise it is untouched.  Betweenness is used in MesquiteTree, for example, to indicate whether an associated is tied to branches or nodes */
+	public void setAssociatedBit(NameReference nRef, int index, boolean value, boolean setAsBetween){
+		if (bits!=null && nRef!=null) {
+			for (int i=0; i<bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					if (value)
+						b.setBit(index); 
+					else
+						b.clearBit(index);
+					if (setAsBetween)
+						b.setBetweenness(true);
+					setDirty(true);
+					return;
+				}
+			}
+			makeAssociatedBits(nRef.getValue());
+			Bits b = getWhichAssociatedBits(nRef);
+			if (b==null)
+				return;
+			if (value)
+				b.setBit(index);
+			else
+				b.clearBit(index);
+			if (setAsBetween)
+				b.setBetweenness(true);
+			setDirty(true);
+		}
+	}
+	public boolean getAssociatedBit(NameReference nRef, int index){
+		if (bits==null || nRef==null) {
+			return false;
+		}
+		for (int i=0; i<bits.size(); i++) {
+			Bits b = (Bits)bits.elementAt(i);
+			if (b !=null && nRef.equals(b.getNameReference())) {
+				return b.isBitOn(index); 
+			}
+		}
+		return false;
+	}
+	/* ---------------------LONG------------------------*/
+	public int getNumberAssociatedLongs(){
+		if (longs==null)
+			return 0;
+		else
+			return longs.size();
+	}
+	public LongArray getAssociatedLongs(int index){
+		if (longs!=null && index>=0 && index<longs.size()) {
+			return (LongArray)longs.elementAt(index);
+		}
+		return null;
+	}
+	public NameReference makeAssociatedLongs(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		LongArray d = getWhichAssociatedLong(nr);
+		if (d==null){
+			d = new LongArray(numParts);
+			d.setNameReference(nr);
+			longs.addElement(d);
+		}
+		setDirty(true);
+		return nr;
+	}
+	public void removeAssociatedLongs(NameReference nRef){
+		boolean found = false;
+		if (longs!=null && nRef!=null) {
+			for (int i=0; i<longs.size() && !found; i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					longs.removeElement(b);
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public LongArray getWhichAssociatedLong(NameReference nRef){
+		if (longs!=null && nRef!=null) {
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					return b; 
+				}
+			}
+		}
+		return null;
+	}
+	public void deassignAllAssociatedLongs(NameReference nRef){
+		boolean found = false;
+		if (longs!=null && nRef!=null) {
+			for (int i=0; i<longs.size() && !found; i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.deassignArray(); 
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public void zeroAllAssociatedLongs(NameReference nRef){
+		boolean found = false;
+		if (longs!=null && nRef!=null) {
+			for (int i=0; i<longs.size() && !found; i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.zeroArray(); 
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public void setAssociatedLong(NameReference nRef, int index, long value){
+		setAssociatedLong(nRef, index, value, false);
+	}
+	/*generally not used directly, as setAsBetween is rarely true.  When setAsBetween is true the betweenness is set to true;
+	 * otherwise it is untouched.  Betweenness is used in MesquiteTree, for example, to indicate whether an associated is tied to branches or nodes */
+	public void setAssociatedLong(NameReference nRef, int index, long value, boolean setAsBetween){
+		if (longs!=null && nRef!=null) {
+			for (int i=0; i<longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					if (setAsBetween) 
+						b.setBetweenness(true);
+					b.setValue(index, value); 
+					setDirty(true);
+					return;
+				}
+			}
+			makeAssociatedLongs(nRef.getValue());
+			LongArray b = getWhichAssociatedLong(nRef);
+			if (b==null)
+				return;
+			if (setAsBetween) 
+				b.setBetweenness(true);
+			b.setValue(index, value);
+			setDirty(true);
+		}
+	}
+	public long getAssociatedLong(NameReference nRef, int index){
+		if (longs==null || nRef==null)
+			return MesquiteLong.unassigned;
+		for (int i=0; i<longs.size(); i++) {
+			LongArray b = (LongArray)longs.elementAt(i);
+			if (b !=null && nRef.equals(b.getNameReference())) {
+				return b.getValue(index); 
+			}
+		}
+		return MesquiteLong.unassigned;
+	}
+	/* ---------------------DOUBLE------------------------*/
+	public int getNumberAssociatedDoubles(){
+		if (doubles==null)
+			return 0;
+		else
+			return doubles.size();
+	}
+	public DoubleArray getAssociatedDoubles(int index){
+		if (doubles!=null && index>=0 && index<doubles.size()) {
+			return (DoubleArray)doubles.elementAt(index);
+		}
+		return null;
+	}
+	public NameReference makeAssociatedDoubles(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		DoubleArray d = getWhichAssociatedDouble(nr);
+		if (d==null){
+			d = new DoubleArray(numParts);
+			d.setNameReference(nr);
+			doubles.addElement(d);
+		}
+		setDirty(true);
+		return nr;
+	}
+	public void removeAssociatedDoubles(NameReference nRef){
+		boolean found = false;
+		if (doubles!=null && nRef!=null) {
+			for (int i=0; i<doubles.size() && !found; i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					doubles.removeElement(b);
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public DoubleArray getWhichAssociatedDouble(NameReference nRef){
+		if (doubles!=null && nRef!=null) {
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					return b; 
+				}
+			}
+		}
+		return null;
+	}
+	public void zeroAllAssociatedDoubles(NameReference nRef){
+		boolean found = false;
+		if (doubles!=null && nRef!=null) {
+			for (int i=0; i<doubles.size() && !found; i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.zeroArray(); 
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public void setAssociatedDouble(NameReference nRef, int index, double value){
+		setAssociatedDouble(nRef, index, value, false);
+	}
+	/*generally not used directly, as setAsBetween is rarely true.  When setAsBetween is true the betweenness is set to true;
+	 * otherwise it is untouched.  Betweenness is used in MesquiteTree, for example, to indicate whether an associated is tied to branches or nodes */
+	public void setAssociatedDouble(NameReference nRef, int index, double value, boolean setAsBetween){
+		if (doubles!=null && nRef!=null) {
+			for (int i=0; i<doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.setValue(index, value); 
+					if (setAsBetween)
+						b.setBetweenness(true);
+					setDirty(true);
+					return;
+				}
+			}
+			makeAssociatedDoubles(nRef.getValue());
+			DoubleArray b = getWhichAssociatedDouble(nRef);
+			if (b==null)
+				return;
+			if (setAsBetween)
+				b.setBetweenness(true);
+			b.setValue(index, value);
+			setDirty(true);
+		}
+	}
+	public double getAssociatedDouble(NameReference nRef, int index){
+		if (doubles==null || nRef==null)
+			return MesquiteDouble.unassigned;
+		for (int i=0; i<doubles.size(); i++) {
+			DoubleArray b = (DoubleArray)doubles.elementAt(i);
+			if (b !=null && nRef.equals(b.getNameReference())) {
+				return b.getValue(index); 
+			}
+		}
+		return MesquiteDouble.unassigned;
+	}
+	/* ---------------------OBJECT------------------------*/
+	public int getNumberAssociatedObjects(){
+		if (objects==null)
+			return 0;
+		else
+			return objects.size();
+	}
+	public ObjectArray getAssociatedObjects(int index){
+		if (objects!=null && index>=0 && index<objects.size()) {
+			return (ObjectArray)objects.elementAt(index);
+		}
+		return null;
+	}
+	public NameReference makeAssociatedObjects(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		ObjectArray d = getWhichAssociatedObject(nr);
+		if (d==null){
+			d = new ObjectArray(numParts);
+			d.setNameReference(nr);
+			objects.addElement(d);
+			setDirty(true);
+		}
+		return nr;
+	}
+	public void removeAssociatedObjects(NameReference nRef){
+		boolean found = false;
+		if (objects!=null && nRef!=null) {
+			for (int i=0; i<objects.size() && !found; i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					objects.removeElement(b);
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public ObjectArray getWhichAssociatedObject(NameReference nRef){
+		if (objects!=null && nRef!=null) {
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					return b; 
+				}
+			}
+		}
+		return null;
+	}
+
+	public void zeroAllAssociatedObjects(NameReference nRef){
+		boolean found = false;
+		if (objects!=null && nRef!=null) {
+			for (int i=0; i<objects.size() && !found; i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.zeroArray(); 
+					found = true;
+				}
+			}
+		}
+		setDirty(true);
+	}
+	public void setAssociatedObject(NameReference nRef, int index, Object value){
+		setAssociatedObject(nRef, index, value, false);
+	}
+
+
+	/*generally not used directly, as setAsBetween is rarely true.  When setAsBetween is true the betweenness is set to true;
+	 * otherwise it is untouched.  Betweenness is used in MesquiteTree, for example, to indicate whether an associated is tied to branches or nodes */
+	public void setAssociatedObject(NameReference nRef, int index, Object value, boolean setAsBetween){
+		if (value instanceof String && value != null && ((String)value).equals(""))  // a filter so a blank string is not saved
+			value = null;
+		if (objects!=null && nRef!=null) {
+			for (int i=0; i<objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					b.setValue(index, value); 
+					if (setAsBetween)
+						b.setBetweenness(true);
+					setDirty(true);
+					return;
+				}
+			}
+			makeAssociatedObjects(nRef.getValue());
+			ObjectArray b = getWhichAssociatedObject(nRef);
+			if (b==null)
+				return;
+			if (setAsBetween)
+				b.setBetweenness(true);
+			b.setValue(index, value); 
+			setDirty(true);
+		}
+	}
+	public Object getAssociatedObject(NameReference nRef, int index){
+		if (objects==null || nRef==null)
+			return null;
+		for (int i=0; i<objects.size(); i++) {
+			ObjectArray b = (ObjectArray)objects.elementAt(i);
+			if (b !=null && nRef.equals(b.getNameReference())) {
+				return b.getValue(index); 
+			}
+		}
+		return null;
+	}
+
+	/** Returns true iff there is at least one associate object of type nRef */
+	public boolean anyAssociatedObject(NameReference nRef){
+		if (objects==null || nRef==null)
+			return false;
+		for (int i=0; i<objects.size(); i++) {
+			ObjectArray b = (ObjectArray)objects.elementAt(i);
+			if (b !=null && nRef.equals(b.getNameReference())) {
+				return true; 
+			}
+		}
+		return false;
+	}
+
+	public void setAssociatedBitsBetweenness(NameReference nref, boolean between){
+		Bits b = getWhichAssociatedBits(nref);
+		if (b != null)
+			b.setBetweenness(between);
+	}
+	public void setAssociatedLongBetweenness(NameReference nref, boolean between){
+		LongArray b = getWhichAssociatedLong(nref);
+		if (b != null)
+			b.setBetweenness(between);
+	}
+	public void setAssociatedDoubleBetweenness(NameReference nref, boolean between){
+		DoubleArray b = getWhichAssociatedDouble(nref);
+		if (b != null)
+			b.setBetweenness(between);
+	}
+	public void setAssociatedObjectBetweenness(NameReference nref, boolean between){
+		ObjectArray b = getWhichAssociatedObject(nref);
+		if (b != null)
+			b.setBetweenness(between);
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/lib/AssociableWithSpecs.java b/Source/mesquite/lib/AssociableWithSpecs.java
new file mode 100644
index 0000000..1744fc4
--- /dev/null
+++ b/Source/mesquite/lib/AssociableWithSpecs.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+
+/* ======================================================================== */
+/*.................................................................................................................*/
+/** A class that contains serially repeated parts, to each of which may be attached information.
+For example, a Tree contains many nodes, and information might be attached to each node.  A Taxa contains taxons,
+a CharacterData contains characters, and so on.  The purpose of this class is to coordinate
+this attached ("associated") information.  Subclasses include FileElement (and thus CharacterData
+and Taxa) and Tree.  */
+public abstract class AssociableWithSpecs extends Associable {
+	/**Vector of vectors of sets specifying values for elements*/
+	private Vector specsVectors = new Vector();
+	public static final int SPECSSET_CHANGED = 200;
+
+	public AssociableWithSpecs (int numParts){
+		super(numParts);
+	}
+	public AssociableWithSpecs (){
+		super();
+	}
+	public String toHTMLStringDescription(){
+		String s = super.toHTMLStringDescription();
+			String sT = "";
+		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			sT += sv.toHTMLStringDescription();
+	  		}
+	  		
+  		}
+ 		if (!StringUtil.blank(sT))
+			s += "<li>Specification Sets<ul>" +sT + "</ul></li>";
+		
+		return s;
+	}
+	public String listAssociates(){
+		String s = super.listAssociates();
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			s += "Specs sets of class " + sv.getClass() + "\n";
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				s+= "   " + css.getName() + "\n";
+	  			}
+	  		}
+  		}
+  		return s;
+	}
+	public void disposing(Object obj){
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			SpecsSet s = sv.getCurrentSpecsSet();
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				css.disposing(obj);
+	  			}
+	  			SpecsSet currentSS = sv.getCurrentSpecsSet();
+	  			if (currentSS!=null) {
+	  				currentSS.disposing(obj);
+				}
+	  		}
+  		}
+	}
+	public void dispose(){
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			SpecsSet s = sv.getCurrentSpecsSet();
+	  			if (s!=null)
+	  				s.dispose();
+	  			sv.dispose();
+	  		}
+	  		if (specsVectors!=null)
+	  			specsVectors.removeAllElements();
+  		}
+  		specsVectors = null;
+ 		super.dispose();
+	}
+	public void equalizeParts(AssociableWithSpecs other, int otherPart, int part){
+  		if (otherPart>=other.getNumberOfParts() && part >= getNumberOfParts())
+  			return;
+  		if (other.specsVectors!=null){ 
+  		//should do reverse; come from other into one to force creation as needed
+	  		for (int i=0; i<other.specsVectors.size(); i++) { 
+	  			SpecsSetVector otherSV = (SpecsSetVector)other.specsVectors.elementAt(i);
+	  			SpecsSet otherCurrentSS = otherSV.getCurrentSpecsSet();
+	  			if (otherCurrentSS!=null) {
+	  				Class specsClass = otherSV.getType();
+	  				SpecsSet thisSS = getCurrentSpecsSet(specsClass);
+	  				if (thisSS == null){
+	  					thisSS = otherCurrentSS.makeSpecsSet(this, getNumberOfParts());
+				 		if (thisSS != null){
+				 			if (this instanceof FileElement){
+				 				thisSS.addToFile(((FileElement)this).getFile(), ((FileElement)this).getProject(), ((FileElement)this).getProject().getCoordinatorModule().findElementManager(specsClass)); 
+							}
+							setCurrentSpecsSet(thisSS, specsClass);
+						}
+	  				}
+	  				if (thisSS != null)
+	  					thisSS.equalizeSpecs(otherCurrentSS, otherPart, part);
+				}
+	  		}
+  		}
+  		super.equalizeParts(other, otherPart, part);
+	}
+	public boolean addParts(int starting, int num){
+		if (!super.addParts(starting, num))
+			return false;
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				css.addParts(starting, num);
+  			}
+	  			SpecsSet currentSS = sv.getCurrentSpecsSet();
+	  			if (currentSS!=null) {
+	  				currentSS.addParts(starting,num);
+				}
+	  		}
+  		}
+  		return true;
+	}
+	public boolean deleteParts(int starting, int num){
+		if (!super.deleteParts(starting, num))
+			return false;
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				css.deleteParts(starting, num);
+	  			}
+	  			SpecsSet currentSS = sv.getCurrentSpecsSet();
+	  			if (currentSS!=null)
+	  				currentSS.deleteParts(starting,num);
+	  		}
+  		}
+  		return true;
+	}
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (!super.moveParts(starting, num, justAfter))
+			return false;
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				css.moveParts(starting, num, justAfter);
+	  			}
+	  			SpecsSet currentSS = sv.getCurrentSpecsSet();
+	  			if (currentSS!=null)
+	  				currentSS.moveParts(starting,num,justAfter);
+	  		}
+  		}
+		return true;
+	}
+	public boolean swapParts(int first, int second){
+		if (!super.swapParts(first, second))
+			return false;
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			for (int j=0; j<sv.size(); j++) {
+	  				SpecsSet css = (SpecsSet)sv.elementAt(j);
+	  				css.swapParts(first, second);
+	  			}
+	  			SpecsSet currentSS = sv.getCurrentSpecsSet();
+	  			if (currentSS!=null)
+	  				currentSS.swapParts(first, second);
+	  		}
+  		}
+		return true;
+	}
+   	public Vector getSpecSetsVectorVector() {
+   		return specsVectors;
+   	}
+   	public SpecsSetVector getSpecSetsVector(Class type) {
+  		if (type==null || specsVectors == null) 
+  			return null;
+
+  		for (int i=0; specsVectors != null && i<specsVectors.size(); i++) {
+  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+  			if (sv!=null && rightType(type, sv)) {
+  				return sv;
+  			}
+  		}
+		//MesquiteMessage.warnUser("specs set vector not found; type= " + type);
+		return null;
+   	}
+   	private boolean rightType(Class type, SpecsSetVector sv){
+	  	return (sv!=null && type == sv.getType());
+   	}
+ 	/*.................................................................................................................*/
+ 	/** */
+  	public void prepareSpecsSetVector(Class type, String typeName){  
+  		//go through specsVectors finding the right one, add it to it
+  		if (type!=null) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (rightType(type, sv))
+	  				return;
+	  		}
+	  		//not found; need to make new one
+  			SpecsSetVector sv = new SpecsSetVector(typeName); 
+  			sv.setType(type);
+  			specsVectors.addElement(sv);
+  		}
+  		else MesquiteMessage.warnUser("Attempt to add specs set with no type specified");
+	}
+	/*.................................................................................................................*/
+ 	/** stores the given specifications set in the list of specs sets.  If an appropriate specs set vector is not found,
+ 	a new one is made.*/
+  	public void storeSpecsSet(SpecsSet specsSet, Class type){  
+ 		setDirty(true);
+  		//go through specsVectors finding the right one, add it to it
+  		if (type!=null && specsSet!=null) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (rightType(type, sv)) {
+	  					
+	  				sv.addSpecSet(specsSet);  
+	  				specsSet.setParent(this);
+	  				return;
+	  			}
+	  		}
+	  		//not found; need to make new one
+			String typeName = specsSet.getTypeName() + "s";
+			SpecsSetVector sv = new SpecsSetVector(typeName); 
+  			sv.setType(type);
+  			specsVectors.addElement(sv);
+  			sv.addSpecSet(specsSet);
+	  		specsSet.setParent(this);
+  			
+  		}
+  		else MesquiteMessage.warnUser("Attempt to add specs set with no type specified");
+	}
+ 	/*.................................................................................................................*/
+ 	/** removes the given specifications set from the list of specs sets*/
+  	public void removeSpecsSet(SpecsSet specsSet, Class type){  
+ 		setDirty(true);
+  		//go through specsVectors finding the right one, add it to it
+  		if (type!=null && specsSet!=null && specsVectors!=null) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (rightType(type, sv)) {
+	  				sv.removeSpecSet(specsSet);  
+	  				specsSet.setParent(null);
+	  				
+	  				return;
+	  			}
+	  		}
+  		}
+	}
+ 	/*.................................................................................................................*/
+ 	/** returns the number of specs sets*/
+  	public int getNumSpecsSets(Class type){  
+  		if (type==null || specsVectors==null )
+  			return 0;
+  		for (int i=0; i<specsVectors.size(); i++) {
+  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+  			if (rightType(type, sv)) {
+  				return sv.getNumSpecsSets();  
+  			}
+  		}
+  		return 0;
+  	}
+ 	/*.................................................................................................................*/
+ 	/** returns the given specs set from the list of specs sets*/
+  	public SpecsSet getCurrentSpecsSet(Class type){  
+  		if (type!=null && specsVectors!=null) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (sv!=null && rightType(type, sv)) {
+	  				return sv.getCurrentSpecsSet();
+	  			}
+	  		}
+  		}
+  		return null;
+	}
+	public void setCurrentSpecsSet(SpecsSet specsSet, Class type){
+  		if (type!=null && specsVectors!=null &&specsSet!=null ) {
+	 		setDirty(true);
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (sv!=null && rightType(type, sv)) {
+	  				sv.setCurrentSpecsSet(specsSet);
+			  		specsSet.setParent(this);
+	  				return;
+	  			}
+	  		}
+	  		//not found; need to make new one
+			String typeName = specsSet.getTypeName() + "s";
+ 			SpecsSetVector sv = new SpecsSetVector(typeName); 
+  			sv.setType(type);
+  			specsVectors.addElement(sv);
+	  		sv.setCurrentSpecsSet(specsSet);
+	  		specsSet.setParent(this);
+			notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+ 		}
+	}
+ 	/*.................................................................................................................*/
+ 	/** returns the given specs set from the list of specs sets*/
+  	public SpecsSet getSpecsSet(String name, Class type){  
+  		if (type!=null && specsVectors!=null && name !=null) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (rightType(type, sv)) {
+			  		for (int j=0; j<sv.getNumSpecsSets(); j++) {
+			  			SpecsSet temp = (SpecsSet)sv.elementAt(j);
+			  			if (name.equalsIgnoreCase(temp.getName()))
+			  				return temp;
+			  		}
+	  			}
+	  		}
+  		}
+  		return null;
+	}
+ 	/*.................................................................................................................*/
+ 	/** returns the given specs set from the list of specs sets*/
+  	public SpecsSet getSpecsSet(int index, Class type){  
+ 		if (type!=null && specsVectors!=null ) {
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			if (index < sv.size() && rightType(type, sv)) {
+			  		return (SpecsSet)sv.elementAt(index);
+	  			}
+	  		}
+  		}
+  		return null;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/Attachable.java b/Source/mesquite/lib/Attachable.java
new file mode 100644
index 0000000..a41e0a3
--- /dev/null
+++ b/Source/mesquite/lib/Attachable.java
@@ -0,0 +1,268 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*.................................................................................................................*/
+/** A class to which objects can be attached.  May 2002*/
+public abstract class Attachable extends Listened implements HTMLDescribable { 
+	Vector attachments;
+	//this should separately accept longs, doubles, & objects (e.g. strings) and be made more parallel to the associable system
+	
+	public Attachable (){
+		super();
+	}
+  	/** Disposes this attachable */
+	public void dispose(){
+		if (attachments!=null)
+			attachments.removeAllElements();
+		super.dispose();
+	}
+	
+	public String toHTMLStringDescription(){
+		if (!anyAttachments())
+			return "";
+		String s = "<li>Attachments: <ul>";
+		if (attachments!=null){
+			for (int i=0; i<attachments.size(); i++) {
+				s += "<li>";
+				Object obj = attachments.elementAt(i);
+				if (obj instanceof Listable){
+					if (obj instanceof MesquiteBoolean)
+						s += "Boolean: ";
+					else if (obj instanceof MesquiteLong)
+						s += "Long: ";
+					else if (obj instanceof MesquiteDouble)
+						s += "Double: ";
+					else if (obj instanceof MesquiteString)
+						s += "String: ";
+					Listable b = (Listable)obj;
+					s += "   " + b.getName();	
+				}
+				else
+					s += "Object of class " + obj.getClass().getName();	
+				s += "</li>";
+			}
+		}
+		s += "</ul></li>";
+		return s;
+	}
+	public void attach(Object obj){
+		if (obj == null)
+			return;
+		if (attachments==null)
+			attachments = new Vector();
+		attachments.addElement(obj);
+	}
+	public void attachIfUniqueName(Object obj){
+		if (obj == null)
+			return;
+		if (attachments==null)
+			attachments = new Vector();
+		if (ListableVector.indexOfByName(attachments, obj)>=0)
+			return;
+		attachments.addElement(obj);
+	}
+	public void detach(Object obj){
+		if (obj == null)
+			return;
+		if (attachments==null)
+			return;
+		attachments.removeElement(obj);
+	}
+	public void detachObjectOfName(String name){
+		if (name == null || attachments==null)
+			return;
+		int index = ListableVector.indexOfByName(attachments, name);
+		if (index <0)
+			return;
+		attachments.removeElementAt(index);
+	}
+	public void detachAllObjectsOfName(String name){
+		if (name == null || attachments==null)
+			return;
+		int index=0;
+		while (index>=0) {
+			index = ListableVector.indexOfByName(attachments, name);
+			if (index <0)
+				return;
+			attachments.removeElementAt(index);
+		}
+	}
+	public void setAttachments(Attachable at){
+		Vector atat = at.attachments;
+		
+		if (attachments !=null)
+			attachments.removeAllElements();
+		if (atat == null)
+			return;
+		for (int i=0; i<atat.size(); i++) {
+			Object obj = atat.elementAt(i);
+			if (obj instanceof MesquiteDouble){ //todo: add attachments of other sorts also
+				MesquiteDouble b = (MesquiteDouble)obj;
+				MesquiteDouble md = new MesquiteDouble(b.getValue());
+				md.setName(b.getName());
+				attach(md);
+			}
+			else if (obj instanceof MesquiteLong){ //todo: add attachments of other sorts also
+				MesquiteLong b = (MesquiteLong)obj;
+				MesquiteLong md = new MesquiteLong(b.getValue());
+				md.setName(b.getName());
+				attach(md);
+			}
+			else if (obj instanceof MesquiteString){ //todo: add attachments of other sorts also
+				MesquiteString b = (MesquiteString)obj;
+				MesquiteString md = new MesquiteString(b.getValue());
+				md.setName(b.getName());
+				attach(md);
+			}
+			else {
+				MesquiteMessage.warnProgrammer("ERROR: setAttachments encountered attachment of unknown type.  This is not handled yet. " + obj.getClass() + "  " + obj);
+			}
+		}
+	}
+	public boolean anyAttachments(){
+		return attachments != null && attachments.size()>0;
+	}
+	public Vector getAttachments(){
+		return attachments;
+	}
+	public Object getAttachment(String name){
+		return getAttachment(name, null);
+	}
+	public Object getAttachment(String name, Class c){
+		if (attachments==null || name == null)
+			return null;
+		for (int i=0; i<attachments.size(); i++) {
+			Object obj = attachments.elementAt(i);
+			if (obj instanceof Listable && (c == null || c.isAssignableFrom(obj.getClass()))){
+				Listable b = (Listable)obj;
+				if (name.equalsIgnoreCase(b.getName()))
+					return b;	
+			}
+		}
+		return null;
+	}
+	public String listAttachments(){
+		String s = " Attachments of ";
+		if (this instanceof Listable)
+			s =  ((Listable)this).getName() + "\n";
+		else
+			s = getClass() + "\n";
+		if (attachments!=null){
+			for (int i=0; i<attachments.size(); i++) {
+				Object obj = attachments.elementAt(i);
+				if (obj instanceof Listable){
+					Listable b = (Listable)obj;
+					s += "   " + b.getName()+ "\n";	
+				}
+				else
+					s += "   Object of class " + obj.getClass().getName()+ "\n";	
+			}
+		}
+		return s;
+	}
+	public String writeAttachments(boolean useComments){
+		String s = null;
+		if (useComments)
+			s = "[%";
+		else
+			s = "<";
+		if (attachments!=null)
+			for (int i=0; i<attachments.size(); i++) {
+				Object obj = attachments.elementAt(i);
+				if (obj instanceof Listable && ((Listable)obj).getName()!=null){
+					if (obj instanceof MesquiteDouble){
+						s += ParseUtil.tokenize(((Listable)obj).getName()) + " = " + ((MesquiteDouble)obj).getValue() + " ";
+					}
+					else if (obj instanceof MesquiteLong){
+						s += ParseUtil.tokenize(((Listable)obj).getName()) + " = " + obj + " ";
+					}
+					else if (obj instanceof MesquiteBoolean){
+						s += ParseUtil.tokenize(((MesquiteBoolean)obj).getName()) + " = " + ((MesquiteBoolean)obj).toOffOnString() + " ";
+					}
+					else if (obj instanceof MesquiteString){
+						s += ParseUtil.tokenize(((MesquiteString)obj).getName()) + " = " + ParseUtil.tokenize("string:" + ((MesquiteString)obj).getValue())+ " ";
+					}
+				}
+			}
+		if ((useComments && s.equals("[%")) || (!useComments && s.equals("<")))
+			return "";
+		else if (useComments)
+			return s+ "]";
+		else
+			return s + ">";
+	}
+	/** Reading and writing of attachments is not fully supported.  Below are the methods for comment-saving, e.g. for trees.
+	 * Other classes such as CharacterData may have their managing modules store the attachments as supplemental notes (see SUCM
+	 * in ManageCharacters).
+	 */
+	public void readAttachments(String assocString, MesquiteInteger pos){
+		//assumes already past "<";
+		String s=ParseUtil.getToken(assocString, pos);
+		while (!">".equals(s)) {
+			if (StringUtil.blank(s))
+				return;
+			String tok = ParseUtil.getToken(assocString, pos); //eating up equals
+			int oldPos = pos.getValue();
+			String value = ParseUtil.getToken(assocString, pos); //finding value
+			if (StringUtil.blank(value))
+				return;
+			if (value.equalsIgnoreCase("on")) {
+				MesquiteBoolean mb = new MesquiteBoolean(true);
+				mb.setName(s);
+				attachIfUniqueName(mb);
+			}
+			else if (value.equalsIgnoreCase("off")) {
+				MesquiteBoolean mb = new MesquiteBoolean(false);
+				mb.setName(s);
+				attachIfUniqueName(mb);
+			}
+			else if (value.indexOf("string:") == 0) { //treat as String 
+				MesquiteString mb = new MesquiteString();
+				mb.setValue(value.substring(7, value.length()));
+				mb.setName(s);
+				attachIfUniqueName(mb);
+			}
+			else if (value.indexOf(".")>=0) { //treat as double 
+				//TODO:  there is a problem here; if some cases use ., others not, should be double; but will be treated as mixed
+				MesquiteDouble mb = new MesquiteDouble();
+				pos.setValue(oldPos);
+				mb.setValue(MesquiteDouble.fromString(assocString, pos));
+				mb.setName(s);
+				attachIfUniqueName(mb);
+			}
+			else {  //treat as long
+				MesquiteLong mb = new MesquiteLong();
+				pos.setValue(oldPos);
+				mb.setValue(MesquiteLong.fromString(assocString, pos));
+				mb.setName(s);
+				attachIfUniqueName(mb);
+			}
+			s=ParseUtil.getToken(assocString, pos);
+			if (",".equals(s)) //eating up "," separating subcommands
+				s=ParseUtil.getToken(assocString, pos);
+		}
+	}
+	
+
+	
+}
+
+
+
+
diff --git a/Source/mesquite/lib/AttachedNote.java b/Source/mesquite/lib/AttachedNote.java
new file mode 100644
index 0000000..a10bf0f
--- /dev/null
+++ b/Source/mesquite/lib/AttachedNote.java
@@ -0,0 +1,619 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/*
+time mod and created should not be allowed to be 0!
+/* ======================================================================== */
+public class AttachedNote  implements NexusWritable {
+	private String loc, comment, imPath, reference, extras;
+	private long timeModified;
+	private long timeCreated;
+	private String timeCreatedString = null;
+	Author author, authorModified;
+	
+	String authorLiteral, authorModifiedLiteral;
+	String authorCodeLiteral, authorModifiedCodeLiteral;
+	private String IDString; // possibly uniqueID string
+	private Image im;
+	AttachedNotesVector vector;
+	Vector imageLabelsVector;
+	Vector textFieldsVector;
+	static int numCreated = 0;
+	
+	public AttachedNote(){
+		stampDateCreated();
+		imageLabelsVector = new Vector();
+		textFieldsVector = new Vector();
+		extras = "";
+		numCreated++;
+		IDString = MesquiteTrunk.getUniqueIDBase() + numCreated;
+	}
+	public String toString(){
+		String s = "Comment: " + comment;
+		s += "\nImage: " + imPath;
+		s += "\nAuthor: " + getAuthorName();
+		s += "\nCreated: " + getDateCreated();
+		s += "\nModified by: " + getAuthorModifiedName();
+		s += "\nModified: " + getDateModified();
+		s += "\nReference: " + reference;
+		return s;		
+	}
+	public void describeDifferences(AttachedNote other, StringBuffer sb){
+		if (other == null || sb == null)
+			return;
+		if (!StringUtil.stringsEqual(comment, other.comment))
+			sb.append("\nComment different: " + comment + " \nversus other\n " + other.comment);
+		if (!StringUtil.stringsEqual(imPath, other.imPath))
+			sb.append("\nImage paths different: " + imPath + " \nversus other\n " + other.imPath);
+		if (!StringUtil.stringsEqual(getAuthorName(), other.getAuthorName()))
+			sb.append("\nAuthors different: " + getAuthorName() + " \nversus other\n " + other.getAuthorName());
+		if (timeCreated != other.timeCreated)
+			sb.append("\nTime created different: " + getDateCreated() + " \nversus other\n " + other.getDateCreated());
+		if (!StringUtil.stringsEqual(getAuthorModifiedName(), other.getAuthorModifiedName()))
+			sb.append("\nLast Modified Authors different: " + getAuthorModifiedName() + " \nversus other\n " + other.getAuthorModifiedName());
+		if (timeModified != other.timeModified)
+			sb.append("\nTime modified different: " + getDateModified() + " \nversus other\n " + other.getDateModified());
+		if (!StringUtil.stringsEqual(reference, other.reference))
+			sb.append("\nReference different: " + reference + " \nversus other\n " + other.reference);
+	}
+	public boolean sameContents(AttachedNote other, boolean excludeDateCreated, boolean excludeDateModified){
+		if (other == null)
+			return false;
+		if (!excludeDateCreated && timeCreated != other.timeCreated)
+			return false;
+		if (!excludeDateModified && timeModified != other.timeModified)
+			return false;
+		if (!excludeDateCreated && !StringUtil.stringsEqual(timeCreatedString, other.timeCreatedString))
+			return false;
+		if (!StringUtil.stringsEqual(loc, other.loc) || !StringUtil.stringsEqual(comment, other.comment) || !StringUtil.stringsEqual(extras, other.extras) || !StringUtil.stringsEqual(imPath, other.imPath) || !StringUtil.stringsEqual(reference, other.reference))
+			return false;
+		if (!labelsSame(imageLabelsVector, other.imageLabelsVector) || !labelsSame(other.imageLabelsVector, imageLabelsVector))
+			return false;
+		if (!textFieldsSame(textFieldsVector, other.textFieldsVector) || !textFieldsSame(other.textFieldsVector, textFieldsVector))
+			return false;
+
+		return true;
+	}
+	public boolean descendant(AttachedNote other){
+		if (other == null)
+			return false;
+		return StringUtil.stringsEqual(other.IDString, IDString);
+	}
+	public AttachedNote cloneNote(){
+		AttachedNote a = new AttachedNote();
+		a.loc = loc;
+		a.comment = (comment);
+		a.imPath = (imPath);
+		a.reference = (reference);
+		a.extras = (extras);
+		a.timeModified = timeModified;
+		a.timeCreated = timeCreated;
+		a.timeCreatedString = timeCreatedString;
+		a.authorModified = authorModified;
+		a.author = author;
+		a.authorLiteral = authorLiteral;
+		a.authorModifiedLiteral = authorModifiedLiteral;
+		a.authorCodeLiteral = authorCodeLiteral;
+		a.authorModifiedCodeLiteral = authorModifiedCodeLiteral;
+		a.IDString = IDString;
+		for (int i=0; i<getNumTextFields(); i++)
+			a.textFieldsVector.addElement(new ANTextField(getTextField(i).getName(), getTextField(i).getString()));
+		for (int i=0; i<getNumLabels(); i++)
+			a.addLabel(getLabel(i).cloneLabel());
+		return a;
+	}
+	public void setToClone(AttachedNote an){
+		loc = an.loc;
+		comment = an.comment;
+		imPath = (an.imPath);
+		reference = (an.reference);
+		extras = (an.extras);
+		timeModified = an.timeModified;
+		timeCreated = an.timeCreated;
+		timeCreatedString = an.timeCreatedString;
+		authorModified = an.authorModified;
+		author = an.author;
+		authorLiteral = an.authorLiteral;
+		authorModifiedLiteral = an.authorModifiedLiteral;
+		authorCodeLiteral = an.authorCodeLiteral;
+		authorModifiedCodeLiteral = an.authorModifiedCodeLiteral;
+		IDString = an.IDString;
+		for (int i=0; i<getNumTextFields(); i++)
+			textFieldsVector.addElement(new ANTextField(an.getTextField(i).getName(), an.getTextField(i).getString()));
+		for (int i=0; i<getNumLabels(); i++)
+			addLabel(an.getLabel(i).cloneLabel());
+	}
+	public void setID(String s){
+		IDString = s;
+	}
+	public String getID(){
+		return IDString;
+	}
+	
+	private boolean labelsSame(Vector v, Vector u){  
+		if (v.size() !=u.size())
+			 return false;
+		for (int i= 0; i< u.size(); i++){
+			ImageLabel label = (ImageLabel)u.elementAt(i);
+			boolean matchFound = false;
+			for (int j= 0; j< v.size();j++){
+				ImageLabel otherLabel = (ImageLabel)v.elementAt(j);
+				if (label.equals(otherLabel))
+					matchFound = true;
+			}
+			if (!matchFound)
+				return false;
+		}
+		return true;
+	}
+	private boolean textFieldsSame(Vector v, Vector u){  
+		if (v.size() !=u.size())
+			 return false;
+		for (int i= 0; i< u.size(); i++){
+			ANTextField label = (ANTextField)u.elementAt(i);
+			boolean matchFound = false;
+			for (int j= 0; j< v.size();j++){
+				ANTextField otherLabel = (ANTextField)v.elementAt(j);
+				if (label.equals(otherLabel))
+					matchFound = true;
+			}
+			if (!matchFound)
+				return false;
+		}
+		return true;
+	}
+	
+	public boolean containsString(String s){
+		if (StringUtil.foundIgnoreCase(reference, s))
+			return true;
+		else if (StringUtil.foundIgnoreCase(comment, s))
+			return true;
+		else if (author != null && StringUtil.foundIgnoreCase(author.getName(), s))
+			return true;
+		else if (authorModified != null && StringUtil.foundIgnoreCase(authorModified.getName(), s))
+			return true;
+		else if (StringUtil.foundIgnoreCase(authorLiteral, s))
+			return true;
+		else if (StringUtil.foundIgnoreCase(authorModifiedLiteral, s))
+			return true;
+		for (int i=0; i< getNumTextFields(); i++) {
+			ANTextField tf = getTextField(i);
+			if (tf != null) {
+				if (StringUtil.foundIgnoreCase(tf.getString(), s))
+					return true;
+			}
+		}
+		for (int i=0; i< getNumLabels(); i++)
+			if (StringUtil.foundIgnoreCase(getLabel(i).getText(), s))
+				return true;
+		return false;
+	}
+	
+	public void setVector(AttachedNotesVector v){
+		vector = v;
+	}
+	public String getComment(){
+		return comment;
+	}
+	public void addExtraSubcommand(String s, boolean notify){
+		extras += s;
+		stampDateModified(notify);
+	}
+	public void setComment(String s, boolean notify){
+		if (s == comment || (s!=null && comment!=null && s.equals(comment)))
+			return;
+		comment = s;
+		stampDateModified(notify);
+	}
+	private ANTextField findTextField(String name){
+		for (int i=0; i< textFieldsVector.size(); i++){
+			ANTextField tf = (ANTextField)textFieldsVector.elementAt(i);
+			if (tf.getName().equalsIgnoreCase(name))
+				return tf;
+		}
+		return null;
+		
+	}
+	
+	public void setTextField(String name, String s, boolean notify){
+		if (StringUtil.blank(name) || StringUtil.blank(s) || ";".equals(name)){
+			MesquiteMessage.warnProgrammer("Warning: text field illegal in attached note (" + name + ") [" + s + "]");
+		}
+		ANTextField tf = findTextField(name);
+		if (tf == null)
+			textFieldsVector.addElement(new ANTextField(name, s));
+		else 
+			tf.setString(s);
+		stampDateModified(notify);
+	}
+	public ANTextField getTextField(int i){
+		if (i >=0 && i< textFieldsVector.size())
+			return (ANTextField)textFieldsVector.elementAt(i);
+		return null;
+	}
+	public int getNumTextFields(){
+		return textFieldsVector.size();
+	}
+	//returns relative path of image
+	public String getImagePath(){
+		return loc;
+	}
+	//returns absolute path of image
+	public String getAbsoluteImagePath(){
+		return imPath;
+	}
+	public void setImage(Image s, boolean notify){
+		im = s;
+	}
+	public void setImagePath(String path, String fullPath, boolean notify){
+		loc = path;
+		imPath = fullPath;
+		if (StringUtil.blank(loc))
+			loc = null;
+		if (StringUtil.blank(imPath))
+			imPath = null;
+		stampDateModified(notify);
+	}
+	
+   	public void attachImage(MesquiteModule module, boolean local){
+   			if (module == null || module.getProject() == null)
+   				return;
+   			MesquiteProject proj = module.getProject();
+			String relPath = null;
+			String loc = null;
+			Image im = null;
+			if (local){
+				MesquiteString dir = new MesquiteString();
+				MesquiteString f = new MesquiteString();
+				loc = MesquiteFile.openFileDialog("Image to attach", dir, f);
+	   	 		if (StringUtil.blank(loc))
+	   	 			return;
+
+				relPath = MesquiteFile.decomposePath(proj.getHomeDirectoryName(), loc);
+				module.logln("Attaching image at " + loc + " (path " + relPath + "  relative to " + proj.getHomeDirectoryName() + ")");
+	   	 		im = MesquiteImage.getImage(relPath, proj);
+				if (!MesquiteImage.waitForImageToLoad(im)) {
+					String ext = StringUtil.getLastItem(loc, ".");
+					if (ext == null || !(ext.equalsIgnoreCase("gif") || ext.equalsIgnoreCase("jpg") || ext.equalsIgnoreCase("jpeg")))
+						module.alert("The image failed to load.  Currently, only gif and jpeg images can be attached to files");
+					else
+						MesquiteMessage.warnProgrammer("Image failed to load!");
+					return;
+				}
+			}
+			else {
+				relPath = MesquiteString.queryString(module.containerOfModule(), "URL of image", "URL of the image to attach to this note", "");
+				loc = "";
+	   	 		if (StringUtil.blank(relPath))
+					return;
+				im = MesquiteImage.getImage(relPath);
+
+			}
+   	 		setImagePath(relPath, loc, false);
+   	 		setImage(im, true);
+   	 }
+	public ImageLabel getLabel(int i){
+		if (i>=0 && i<imageLabelsVector.size())
+			return (ImageLabel)imageLabelsVector.elementAt(i);
+		return null;
+	}
+	public int getNumLabels(){
+		return imageLabelsVector.size();
+	}
+	public int addLabel(ImageLabel label){
+		imageLabelsVector.addElement(label);
+		return imageLabelsVector.size()-1;
+	}
+	public void deleteLabel(ImageLabel label){
+		imageLabelsVector.remove(label);
+	}
+	public void bringToFront(ImageLabel label){
+		if (imageLabelsVector.indexOf(label)>=0){
+			imageLabelsVector.remove(label);
+			imageLabelsVector.addElement(label);
+		}
+	}
+	
+	public String getReference(){
+		return reference;
+	}
+	public void setReference(String s, boolean notify){
+		if (s == reference || (s!=null && reference!=null && s.equals(reference)))
+			return;
+		reference = s;
+		stampDateModified(notify);
+	}
+	public Author getAuthor(){
+		return author;
+	}
+	public String getAuthorName(){
+		if (author != null)
+			return author.getName();
+		return authorLiteral;
+	}
+	public void setAuthorCode(String s){
+		authorCodeLiteral =s ;
+	}
+	public void setAuthorModifiedCode(String s){
+		authorModifiedCodeLiteral =s ;
+	}
+	public void setAuthor(String s){
+		authorLiteral = s;
+		author = null;
+	}
+	public void setAuthor(Author s){
+		authorLiteral = null;
+		author = s;
+	}
+	public Author getAuthorModified(){
+		return authorModified;
+	}
+	public String getAuthorModifiedName(){
+		if (authorModified != null)
+			return authorModified.getName();
+		if (authorModifiedLiteral != null)
+			return authorModifiedLiteral;
+		return authorModifiedCodeLiteral;
+	}
+	public void setAuthorModified(String s){
+		authorModifiedLiteral = s;
+		authorModified = null;
+	}
+	public void setAuthorModified(Author s){
+		authorModifiedLiteral = null;
+		authorModified = s;
+	}
+	public void setDateCreated(long s){
+		timeCreated = s;
+		if (!MesquiteLong.isCombinable(s))
+			MesquiteMessage.warnProgrammer("Warning: Date of note at uncombinable time " + this);
+	}
+	public void setDateCreatedString(String s){
+		timeCreatedString = s;
+	}
+	public void stampDateCreated(){
+		timeCreated = System.currentTimeMillis();
+		timeModified = timeCreated;
+		author = MesquiteModule.author;
+	}
+	public long getDateCreatedInMillis(){
+		return timeCreated;
+	}
+	public String getDateCreated(){
+		if (timeCreated == 0) {
+			if (StringUtil.blank(timeCreatedString))
+				return "No Time Recorded";
+			return timeCreatedString;
+		}
+		Date dnow = new Date(timeCreated);
+		return dnow.toString();
+	}
+	public void setDateModified(String s){
+		timeModified = NexusBlock.getTimeFromNEXUS(s);
+	}
+	public void setDateModified(long s){
+		timeModified = s;
+		if (!MesquiteLong.isCombinable(s))
+			MesquiteMessage.warnProgrammer("Warning: Date mod. of note at uncombinable time " + this);
+	}
+	int stampSuppress=0;
+	public void incrementStampSuppress(){
+		stampSuppress++;
+	}
+	public void decrementStampSuppress(){
+		stampSuppress--;
+	}
+	public void stampDateModified(boolean notify){
+		if (stampSuppress<=0){
+			timeModified = System.currentTimeMillis();
+			if (notify && vector != null)
+				vector.notifyOwner(MesquiteListener.ANNOTATION_CHANGED);
+		}
+	}
+	public String getDateModified(){
+		if (timeModified == 0)
+			return "No Time Recorded";
+		Date dnow = new Date(timeModified);
+		return dnow.toString();
+	}
+	public long getDateModifiedInMillis(){
+		return timeModified;
+	}
+	public void deleteImage(boolean notify){
+		imPath = null;
+		loc = null;
+		im = null;
+		stampDateModified(notify);
+	}
+	public Image getImage(){
+ 		if (im == null && imPath !=null) {
+	 		im = MesquiteImage.getImage(imPath);
+			if (!MesquiteImage.waitForImageToLoad(im)) {
+				MesquiteTrunk.mesquiteTrunk.logln("Error in loading image; location: " + imPath);
+			}
+		}
+
+		return im;
+	}
+	String prepareString(String s, boolean useUnderscore){
+		if (s == null || s.length() == 0) {
+			if (!useUnderscore)
+				return "";
+			s = " ";
+		}
+		return StringUtil.tokenize(s);
+	}
+	public static final String ANNOTATION = "AN";
+	public static final String TAXON = "T";
+	public static final String TAXA = "TS";
+	public static final String CHARACTERS = "CS";
+	public static final String CHARACTER = "C";
+	public static final String STATE = "ST";
+	public static final String COMMENT = "CM"; 
+	public static final String REFERENCE = "R"; 
+	public static final String TEXTFIELD = "TF"; 
+	public static final String AUTHOR = "AU"; 
+	public static final String AUTHORCODE = "A"; 
+	public static final String DATEMOD = "DM"; 
+	public static final String DATECREATED = "DC"; 
+	public static final String IMAGELOC = "I"; 
+	public static final String IMAGELABEL = "L"; 
+	public static final String WIDTH = "W"; 
+	public static final String FIXEDTOIMAGE = "F"; 
+	public static final String SHOWPOINTER = "SP"; 
+	public static final String POINTERY = "PY"; 
+	public static final String POINTERX = "PX"; 
+	public static final String SIZE = "S"; 
+	public static final String COLOR = "CO"; 
+	public static final String COLORNUMBER = "CN"; 
+	public static final String FONT = "F"; 
+	public static final String TEXT = "TX"; 
+	public static final String ID = "ID"; 
+	
+	public boolean anythingNEXUStoWrite(){
+		if (!StringUtil.blank(getImagePath()))
+				return true;
+		if (!StringUtil.blank(getComment()))
+				return true;
+		if (!StringUtil.blank(getReference()))
+				return true;
+		for (int i=0; i< getNumTextFields(); i++) {
+			ANTextField tf = getTextField(i);
+			if (tf != null) {
+				if (!StringUtil.blank(tf.getString()))
+					return true;
+			}
+		}
+		if (getNumLabels()>0)
+			return true;
+		if (extras != null)
+			return true;
+		return false;
+	}
+	public void getNexusString(StringBuffer s){
+		s.append(" ");
+		if (author ==null){
+			if (authorLiteral != null){
+				s.append(AUTHOR);
+				s.append(" = ");
+				s.append(prepareString(authorLiteral, true));
+			}
+			else if (authorCodeLiteral != null){
+				s.append(AUTHORCODE);
+				s.append(" = ");
+				s.append(prepareString(authorCodeLiteral, true));
+			}
+		}
+		else {
+			s.append(AUTHORCODE);
+			s.append(" = ");
+			s.append(prepareString(author.getCode(), true));
+		}
+		s.append(" ");
+		if (timeCreated != 0){
+				s.append(DATECREATED);
+				s.append(" = ");
+				s.append(prepareString(NexusBlock.getNEXUSTime(timeCreated), true));
+				s.append(" ");
+		}
+		else if (!StringUtil.blank(timeCreatedString)){ //only explicit string
+				s.append("DATECREATED");
+				s.append(" = ");
+				s.append(prepareString(timeCreatedString, true));
+				s.append(" ");
+		}
+		if (timeModified != 0){
+			s.append(DATEMOD);
+			s.append(" = ");
+			s.append(prepareString(NexusBlock.getNEXUSTime(timeModified), true));
+			s.append(" ");
+		}
+		s.append(ID);
+		s.append(" = ");
+		s.append(prepareString(getID(), true));
+		s.append(" ");
+		s.append(IMAGELOC);
+		s.append(" = ");
+		s.append(prepareString(getImagePath(), true));
+		s.append(" ");
+		s.append(TEXTFIELD);
+		s.append(" = (");
+		s.append(COMMENT);
+		s.append(" ");
+		s.append(prepareString(getComment(), false));
+		s.append(")");
+		s.append(" ");
+		if (!StringUtil.blank(getReference())){
+			s.append(TEXTFIELD);
+			s.append(" = (");
+			s.append(REFERENCE);
+			s.append(" ");
+			s.append(prepareString(getReference(), false));
+			s.append(")");
+		}
+		for (int i=0; i< getNumTextFields(); i++) {
+			ANTextField tf = getTextField(i);
+			if (tf != null) {
+				s.append(" ");
+				s.append(TEXTFIELD);
+				s.append(" = (");
+				s.append(tf.getName());
+				s.append(" ");
+				s.append(prepareString(tf.getString(), false));
+				s.append(")");
+			}
+		}
+		for (int i=0; i< getNumLabels(); i++) {
+			s.append(" ");
+			s.append(IMAGELABEL);
+			s.append(" = ");
+			s.append(getLabel(i).getNexusString());
+		}
+		if (extras != null)
+			s.append(extras);
+	}
+	public String getNexusString(){
+		StringBuffer s = new StringBuffer(50);
+		getNexusString(s);
+		return s.toString();
+	}
+	
+}
+	
+class ANTextField implements Listable {
+	String name, s;
+	public ANTextField(String name, String s){
+		this.name = name;
+		this.s = s;
+	}
+	
+	public boolean equals(ANTextField other){
+		return (StringUtil.stringsEqual(name, other.name) && StringUtil.stringsEqual(s, other.s));
+	}
+	public String getName(){
+		return name;
+	}
+	public String getString(){
+		return s;
+	}
+	public void setString(String s){
+		this.s = s;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/AttachedNotesVector.java b/Source/mesquite/lib/AttachedNotesVector.java
new file mode 100644
index 0000000..3feb92c
--- /dev/null
+++ b/Source/mesquite/lib/AttachedNotesVector.java
@@ -0,0 +1,274 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/* ======================================================================== */
+public class AttachedNotesVector {
+	private Vector notes;
+	int currentNote = 0;
+	Listened owner;
+	
+	public AttachedNotesVector(Listened owner){
+		this.owner = owner;
+		notes = new Vector();
+	}
+	public void notifyOwner(int event){
+		if (owner !=null)
+			owner.notifyListeners(this, new Notification(event));
+	}
+	
+	public static final int NOTCONTAINED = 3;
+	public static final int SUBSET = 2;
+	public static final int SUPERSET = 1;
+	public static final int EQUAL = 0;
+	public static final int EQUALBUTMODIFIED = 4;
+	
+	public int compareNotesByDescent(AttachedNotesVector other){
+		boolean thisIsSubset = firstFoundInSecond(this, other);
+		boolean thisIsSuperset = firstFoundInSecond(other, this);
+		if (thisIsSubset && thisIsSuperset) {  //same annotation IDs
+			if (firstFoundInSecond(this, other, false, false) &&  firstFoundInSecond(other, this, false, false))
+				return EQUAL;
+			else
+				return EQUALBUTMODIFIED;
+		}
+		if (thisIsSubset)
+			return SUBSET;
+		if (thisIsSuperset)
+			return SUPERSET;
+		return NOTCONTAINED;
+	}
+	private boolean firstFoundInSecond(AttachedNotesVector u, AttachedNotesVector v){
+		if (u == null)
+			return false;
+		for (int i= 0; i< u.getNumNotes(); i++){
+			AttachedNote note = u.getAttachedNote(i);
+			if (sameNoteFound(note, v) == null)
+				return false;
+		}
+		return true;
+	}
+	private AttachedNote sameNoteFound(AttachedNote e, AttachedNotesVector v){
+		if (v == null)
+			return null;
+		for (int j= 0; j< v.getNumNotes();j++){
+			AttachedNote otherE = v.getAttachedNote(j);
+			if (e.descendant(otherE))
+				return otherE;
+		}
+		return null;
+	}
+	public int compareNotesByContent(AttachedNotesVector other, boolean excludeDateCreated, boolean excludeDateModified){
+		boolean thisIsSubset = firstFoundInSecond(this, other, excludeDateCreated, excludeDateModified);
+		boolean thisIsSuperset = firstFoundInSecond(other, this, excludeDateCreated, excludeDateModified);
+		if (thisIsSubset && thisIsSuperset)
+			return EQUAL;
+		if (thisIsSubset)
+			return SUBSET;
+		if (thisIsSuperset)
+			return SUPERSET;
+		return NOTCONTAINED;
+	}
+	private boolean firstFoundInSecond(AttachedNotesVector u, AttachedNotesVector v, boolean excludeDateCreated, boolean excludeDateModified){
+		if (u == null)
+			return false;
+		for (int i= 0; i< u.getNumNotes(); i++){
+			AttachedNote note = u.getAttachedNote(i);
+			if (!matchingNoteFound(note, v, excludeDateCreated, excludeDateModified))
+				return false;
+		}
+		return true;
+	}
+	private boolean matchingNoteFound(AttachedNote e, AttachedNotesVector v, boolean excludeDateCreated, boolean excludeDateModified){
+		if (v == null)
+			return false;
+		for (int j= 0; j< v.getNumNotes();j++){
+			AttachedNote otherE = v.getAttachedNote(j);
+			if (e.sameContents(otherE, excludeDateCreated, excludeDateModified))
+				return true;
+		}
+		return false;
+	}
+	public AttachedNotesVector cloneVector(){
+		return cloneVector(owner);
+	}
+	public AttachedNotesVector cloneVector(Listened owner){
+		AttachedNotesVector ch = new AttachedNotesVector(owner);
+		for (int i= 0; i< getNumNotes(); i++){
+			AttachedNote ce = getAttachedNote(i);
+			ch.addNote(ce.cloneNote(), false);
+		}
+		return ch;
+	}
+	public void concatenate(AttachedNotesVector ch){
+		if (ch == null)
+			return;
+		for (int i= 0; i< ch.getNumNotes(); i++){
+			AttachedNote ce = ch.getAttachedNote(i);
+			addNote(ce.cloneNote(), false);
+		}
+	}
+	public void incorporateByContent(AttachedNotesVector v){
+		if (v == null)
+			return;
+		for (int i= 0; i< v.getNumNotes(); i++){
+			AttachedNote ce = v.getAttachedNote(i);
+			if (!matchingNoteFound(ce, this, true, true))
+				addNote(ce.cloneNote(), false);
+		}
+	}
+	public void incorporateByDescent(AttachedNotesVector v, boolean useLastModified){
+		if (v == null)
+			return;
+		for (int i= 0; i< v.getNumNotes(); i++){
+			AttachedNote ce = v.getAttachedNote(i);
+			AttachedNote foundHere = sameNoteFound(ce, this);
+			if (foundHere==null)
+				addNote(ce.cloneNote(), false);
+			else if (!foundHere.equals(ce)){
+				if (useLastModified){
+					if (ce.getDateModifiedInMillis() > foundHere.getDateModifiedInMillis()) {
+						foundHere.setToClone(ce);
+					}
+				}
+				else
+					foundHere.setToClone(ce);
+			}
+			
+		}
+	}
+	public void describeDifferencesByDescent(AttachedNotesVector v, boolean useLastModified, StringBuffer sb){
+		if (sb == null || v == null)
+			return;
+		for (int i= 0; i< v.getNumNotes(); i++){
+			AttachedNote ce = v.getAttachedNote(i);
+			AttachedNote foundHere = sameNoteFound(ce, this);
+			if (foundHere==null)
+				sb.append("Note not present: " + ce);
+			else if (!foundHere.equals(ce)){
+				foundHere.describeDifferences(ce, sb);
+			}
+			
+		}
+	}
+	public int addNote(AttachedNote s, boolean notify){
+		s.setVector(this);
+		notes.addElement(s);
+		if (notify) notifyOwner(MesquiteListener.ANNOTATION_ADDED);
+		return notes.size()-1;
+	}
+	public int addNoteFirst(AttachedNote s, boolean notify){
+		s.setVector(this);
+		notes.insertElementAt(s, 0);
+		if (notify) notifyOwner(MesquiteListener.ANNOTATION_ADDED);
+		return notes.size()-1;
+	}
+	public AttachedNote getAttachedNote(int i){
+		if (i>=0 && i< notes.size())
+			return (AttachedNote)notes.elementAt(i);
+		return null;
+	}
+	public int getNumNotes(){
+		return notes.size();
+	}
+	public void deleteNote(int i){
+		if (i>=0 && i< notes.size()) {
+			notes.removeElementAt(i);
+			if (currentNote>= i)
+				currentNote--;
+			if (currentNote>= notes.size())
+				currentNote = notes.size()-1;
+			if (currentNote<0)
+				currentNote = 0;
+			notifyOwner(MesquiteListener.ANNOTATION_DELETED);
+		}
+	}
+	public void deleteAllNotes(){
+			notes.removeAllElements();
+			notifyOwner(MesquiteListener.ANNOTATION_DELETED);
+	}
+	/*
+	public int getCurrent(){
+		return currentNote;
+	}
+	public void setCurrent(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return;
+		currentNote = i;
+		if (currentNote>= notes.size())
+			currentNote = notes.size()-1;
+		if (currentNote<0)
+			currentNote = 0;
+	}
+	public AttachedNote getCurrentAttachedNote(){
+		if (currentNote < 0 || currentNote>=notes.size())
+			return null;
+		AttachedNote aim = (AttachedNote)notes.elementAt(currentNote);
+		return aim;
+	}
+	public void setCurrentComment(String s){
+		if (currentNote < 0 || currentNote>=notes.size())
+			return;
+		AttachedNote aim = (AttachedNote)notes.elementAt(currentNote);
+		aim.setComment(s);
+	}
+	public void setCurrentAuthor(String s){
+		if (currentNote < 0 || currentNote>=notes.size())
+			return;
+		AttachedNote aim = (AttachedNote)notes.elementAt(currentNote);
+		aim.setAuthor(s);
+	}
+	*/
+	public String getImagePath(int i){
+		if (i < 0 || i>=notes.size())
+			return null;
+		AttachedNote aim = (AttachedNote)notes.elementAt(i);
+		
+		return aim.getImagePath();
+	}
+	public Image getImage(int i){
+		if (i < 0 || i>=notes.size())
+			return null;
+		AttachedNote aim = (AttachedNote)notes.elementAt(i);
+		return aim.getImage();
+	}
+	public String getComment(int i){
+		if (i < 0 || i>=notes.size())
+			return null;
+		AttachedNote aim = (AttachedNote)notes.elementAt(i);
+		return aim.getComment();
+	}
+	public String getReference(int i){
+		if (i < 0 || i>=notes.size())
+			return null;
+		AttachedNote aim = (AttachedNote)notes.elementAt(i);
+		return aim.getReference();
+	}
+	
+	public String toString(){
+		String s = "";
+		for (int i=0; i<notes.size(); i++){
+			AttachedNote aim = (AttachedNote)notes.elementAt(i);
+			s += "  " + aim.getComment() + " " + aim.getDateModified();
+		}
+		return s;
+	}
+	
+}
+	
+
+
diff --git a/Source/mesquite/lib/Author.java b/Source/mesquite/lib/Author.java
new file mode 100644
index 0000000..ac25814
--- /dev/null
+++ b/Source/mesquite/lib/Author.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+/* ======================================================================== */
+public class Author implements Listable  {
+	private String name = "Anonymous";
+	private String code = "0";
+	private boolean current = false;
+	private boolean defaultSettings = true;
+	public static boolean addAuthorBlockByDefault = false;
+	
+	public Author(){
+		super();
+	}
+ 	public static boolean authorsEqual(Author a, Author b){
+ 		if (a == b)
+ 			return true;
+ 		if (a == null || b == null)
+ 			return false;
+ 		return (StringUtil.stringsEqual(a.name, b.name) && StringUtil.stringsEqual(a.code, b.code));
+ 	}
+ 	public String getName(){
+ 		return name;
+ 	}
+ 	public void setCurrent(boolean c){
+ 		current = c;
+ 	}
+ 	public boolean isCurrent(){
+ 		return current;
+ 	}
+ 	public void setName(String name){
+ 		defaultSettings = false;
+ 		this.name = name;
+ 	}
+ 	public String getCode(){
+ 		return code;
+ 	}
+ 	public void setCode(String code){
+ 		defaultSettings = false;
+ 		this.code = code;
+ 	}
+ 	public boolean hasDefaultSettings(){	
+ 		return defaultSettings || (name !=null && "Anonymous".equals(name));
+ 	}
+ 	
+ 	public String toString(){
+ 		if (code != null)
+ 			return code;
+ 		return name;
+ 	}
+}
+
diff --git a/Source/mesquite/lib/BayesianAnalysis.java b/Source/mesquite/lib/BayesianAnalysis.java
new file mode 100644
index 0000000..29ea1c0
--- /dev/null
+++ b/Source/mesquite/lib/BayesianAnalysis.java
@@ -0,0 +1,5 @@
+package mesquite.lib;
+
+public interface BayesianAnalysis {
+
+}
diff --git a/Source/mesquite/lib/Binomial.java b/Source/mesquite/lib/Binomial.java
new file mode 100644
index 0000000..c45eb05
--- /dev/null
+++ b/Source/mesquite/lib/Binomial.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class Binomial {
+	public static double power (double p, int r) {
+		if (r==0)
+			return 1;
+		double result = p;
+		for (int i=2; i<=r; i++)
+			result *= p;
+		return result;
+	}
+	
+	public static double probability(int n, int heads, double p) {
+		if (n>1000) {
+			MesquiteMessage.println("Error: binomial probability can't be calculated for n greater than 1000");
+			return 0;
+		}
+		if (heads>n)
+			return 0;
+		else if (heads == n)
+			return power(p, n);
+		else if (heads == 0)
+			return power((1-p), n);
+		else {
+			double c = 1;
+			for (double i= 1; i<= heads; i++)
+				c *= (n-i+1)*p/i;
+			for (double i= 1; i<= n- heads; i++)
+				c *= (1.0-p);
+			return c;
+		}
+	}
+	public static double bestTail(int n, int heads, double p) {
+		if (n>1000) {
+			MesquiteMessage.println("Error: binomial probability can't be calculated for n greater than 1000");
+			return 0;
+		}
+		double c=0;
+		int t;
+		double q;
+		if (heads< n-heads) {
+			t = heads;
+			q = p;
+		}
+		else {
+			q = 1-p;
+			t = n-heads;
+		}
+		for (int i = 0; i<=t; i++){
+			c += probability(n, i, q);
+		}
+		return c;
+	}
+	public static double rightTail(int n, int heads, double p) {
+		if (n>1000) {
+			 MesquiteMessage.println("Error: binomial probability can't be calculated for n greater than 1000");
+			return 0;
+		}
+		double c=0;
+		for (int i = heads; i<=n; i++){
+			c += probability(n, i, p);
+		}
+		return c;
+	}
+	public static double leftTail(int n, int heads, double p) {
+		if (n>1000) {
+			MesquiteMessage.println("Error: binomial probability can't be calculated for n greater than 1000");
+			return 0;
+		}
+		double c=0;
+		for (int i = 0; i<=heads; i++){
+			c += probability(n, i, p);
+		}
+		return c;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/Bits.java b/Source/mesquite/lib/Bits.java
new file mode 100644
index 0000000..b98157b
--- /dev/null
+++ b/Source/mesquite/lib/Bits.java
@@ -0,0 +1,955 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.Random;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/**  Bits - an object to contain and manage a field of booleans.  This was invented before the Java Bitfield
+was discovered.  Perhaps not needed. */
+public class Bits implements Listable{
+	int[] array;
+	int numBits;
+	int numInts;
+	NameReference nr;
+	static final int SIZECHUNK = 32;
+	static final int SIZECHUNKMINUS1 = 31;
+	public Bits (int numBits) {
+ 		this.numBits = numBits;
+ 		numInts = numBits/SIZECHUNK + 1;
+ 		if (numInts/2*2!=numInts)
+ 			numInts++;
+ 		array = new int[numInts];
+ 		for (int i=0; i<numInts; i++) {
+ 			array[i]=0;
+ 		}
+ 	}
+	//used for Associables that might need to record whether reference is to part or in between part
+	//intially for MesquiteTree to know if info applies to node or branch ancestral to node
+	boolean between = false;
+	public void setBetweenness(boolean b){
+		between = true;  
+	}
+	public boolean isBetween(){
+		return between;
+	}
+	public int getSize(){
+ 		return numBits;
+ 	}
+ 	public int getNumInts(){
+ 		return numInts;
+ 	}
+ 	public Bits cloneBits(){
+ 		Bits b = new Bits(numBits);
+ 		for (int i=0; i<numInts; i++)
+ 			b.array[i]=array[i];
+ 		return b;
+ 	}
+ 	public void copyBits(Bits b){
+ 		if (b==null)
+ 			return;
+ 		for (int i=0; i<b.getNumInts(); i++)
+ 			b.array[i]=0;
+		for (int i=0; i<numInts && i<b.getNumInts(); i++)
+ 			b.array[i]=array[i];
+ 	}
+ 	public void setBits(Bits b){
+ 		if (b==null)
+ 			return;
+ 		for (int i=0; i<getNumInts(); i++)
+ 			array[i]=0;
+		for (int i=0; i<numInts && i<b.getNumInts(); i++)
+ 			array[i]=b.array[i];
+ 	}
+ 	public void standardizeComplement( int standard){
+ 		if (isBitOn(standard))
+ 			return;
+ 		invertAllBits();
+ 	}
+	public void setNameReference(NameReference nr){
+ 		this.nr = nr;
+ 	}
+ 	public NameReference getNameReference(){
+ 		return nr;
+ 	}
+	public String getName(){
+		if (nr!=null)
+			return nr.getValue();
+		else
+			return "";
+	}
+ 	/*------------------------------------------*/
+ 	public void resetSize (int newNumBits) {  //TODO: should be setNumberOfParts
+ 		if (numBits==newNumBits)
+ 			return;
+ 		int[] newArray;
+ 		int newNumInts = newNumBits/SIZECHUNK + 1;
+ 		if (newNumInts/2*2!=newNumInts)
+ 			newNumInts++;
+ 		newArray = new int[newNumInts];
+ 		for (int i=0; i<newNumInts; i++) {
+ 			if (i< numInts)
+ 				newArray[i]=array[i];
+ 			else
+ 				newArray[i]=0;
+ 		}
+ 		numInts = newNumInts;
+  		numBits = newNumBits;
+		array=newArray;
+ 	}
+ 	/*------------------------------------------*/
+ 	/**Inserts num (cleared) bits just after bit "starting"*/
+ 	public void addParts (int starting, int num) {
+		if (num==0)
+			return;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numBits)
+			starting = numBits-1;
+		int newNumBits = numBits + num;
+
+ 		int startingInt = inWhichInteger(starting);
+  		int newNumInts = newNumBits/SIZECHUNK + 1;
+		
+ 		if (newNumInts/2*2!=newNumInts) //odd; add 1 to make even
+ 			newNumInts++;
+ 		
+  		int[] newArray = new int[newNumInts];
+    	for (int i=0; i< newNumInts; i++) 
+ 			newArray[i]=0;
+ 		
+ 		//first, put integers up to start of insertion
+  		for (int ibit=0; ibit<=starting; ibit++) 
+ 			if (isBitOn(ibit))
+ 				setBit(newArray, ibit);
+		
+  		//next, go bitwise from there
+  		for (int ibit=starting+1; ibit<numBits; ibit++) {
+ 			if (isBitOn(ibit))
+ 				setBit(newArray, ibit+num);
+ 		}
+
+  		/*
+ 		//first, put integers up to start of insertion
+  	  	for (int i=0; i<=startingInt; i++) 
+  	 			newArray[i]=array[i];
+  	    	for (int i=startingInt+1; i< newNumInts; i++) 
+  	 			newArray[i]=0;
+  			
+  	  		//next, go bitwise from there
+  	  		for (int ibit=starting; ibit<numBits; ibit++) {
+  	 			if (isBitOn(ibit))
+  	 				setBit(newArray, ibit+num);
+  	 		}
+*/
+  		numBits = newNumBits;
+  		numInts = newNumInts;
+		array=newArray;
+ 	}
+ 	
+ 	/*------------------------------------------*/
+ 	/**Removes num bits starting with and incuding bit "starting"*/
+ 	public void deleteParts (int starting, int num) {
+		if (num<=0)
+			return;
+		if (starting<0)
+			return;
+		else if (starting>numBits)
+			return;
+		if (num+starting>numBits)
+			num = numBits-starting;
+
+		int newNumBits = numBits - num;
+ 		int startingInt = inWhichInteger(starting);
+  		int newNumInts = newNumBits/SIZECHUNK + 1;
+		
+ 		if (newNumInts/2*2!=newNumInts) //odd; add 1 to make even
+ 			newNumInts++;
+ 		
+ 		//first, put integers up to start of deletion
+  		int[] newArray = new int[newNumInts];
+
+    		for (int i=0; i<startingInt; i++) 
+ 			newArray[i]=array[i];
+    		for (int i=startingInt; i< newNumInts; i++) 
+ 			newArray[i]=0;
+		
+  		//next, go bitwise from there
+  		for (int ibit=startingInt*SIZECHUNK; ibit<starting; ibit++) {
+ 			if (isBitOn(ibit))
+ 				setBit(newArray, ibit);
+ 		}
+  		for (int ibit=starting + num; ibit<numBits; ibit++) {
+ 			if (isBitOn(ibit))
+ 				setBit(newArray, ibit-num);
+ 		}
+
+  		numBits = newNumBits;
+ 		numInts = newNumInts;
+		array=newArray;
+ 	}
+	/*...........................................................*/
+	public void swapParts(int first, int second) {
+		if (first<0 || first>=numBits || second<0 || second>=numBits) 
+			return;
+		boolean firstOn = isBitOn(first);
+		setBit(first, isBitOn(second));
+		setBit(second, firstOn);
+	}
+	/*...........................................................*/
+	public void moveParts(int starting, int num, int justAfter) {
+		if (num<=0 || starting>=numBits || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=numBits)
+			justAfter = numBits-1;
+		if (justAfter<0)
+			justAfter = -1;
+		Bits newBits = new Bits(numBits);
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newBits.setBit(count++, isBitOn(i));
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newBits.setBit(count++, isBitOn(i));
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newBits.setBit(count++, isBitOn(i));
+			for (int i=starting+num; i<numBits; i++)
+				newBits.setBit(count++, isBitOn(i));
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newBits.setBit(count++, isBitOn(i));
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newBits.setBit(count++, isBitOn(i));
+			for (int i=starting; i<=starting+num-1; i++)
+				newBits.setBit(count++, isBitOn(i));
+			for (int i=justAfter+1; i<numBits; i++)
+				newBits.setBit(count++, isBitOn(i));
+		}
+		for (int i=0; i<numBits; i++)
+			setBit(i, newBits.isBitOn(i));
+	}
+ 	/*------------------------------------------*/
+ 	private String showBits(int s) {
+ 		String sr = "";
+ 		 for (int i=0; i<SIZECHUNK; i++)
+ 		 	if ((s & (1<< (SIZECHUNKMINUS1- (i % SIZECHUNK)))) == 0)
+ 		 		sr += "0";
+ 		 	else
+ 		 		sr += "1";
+ 		 return sr;
+ 	}
+ 	
+ 	/*------------------------------------------*/
+ 	public int numBitsOn (int bitInteger) {
+ 		int count = 0;
+ 		for (int i=0; i<SIZECHUNK; i++)
+ 			if (isBitOn(bitInteger,i))
+ 				count++;
+ 		return count;
+ 	}
+	/*------------------------------------------*/
+ 	public int numBitsOn () {
+ 		int count = 0;
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=0) {
+ 				count += numBitsOn(array[i]);
+ 			}
+ 		return count;
+ 	}
+
+ 	/*Returns 0 if no bits on, 1 if exactly one, 2 if more than 1*/
+ 	public int numBitsOnPlural () {
+ 		int count = 0;
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=0) {
+ 				count += numBitsOn(array[i]);
+ 	 			if (count>1)
+ 	 				return 2;
+ 			}
+ 		return count;
+ 	}
+ 	/*------------------------------------------*/
+ 	public boolean single () {
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=0)
+ 				return true;
+ 		return false;
+ 	}
+ 	
+ 	/*------------------------------------------*/
+ 	public int setNewRandomBit (Random rng) {
+ 		int available = numBits - numBitsOn();
+ 		if (available<1)
+ 			return -1;
+ 		if (available==1){
+ 			int bit = firstBitOff();
+ 			setBit(bit,true);
+ 			return bit;
+ 		}
+ 		int bitToSet = (int)(rng.nextDouble()*available);
+ 		int count=0;
+ 		for (int i=0; i<numBits; i++) {
+ 			if (!isBitOn(i)) {
+ 				if (bitToSet==count){
+ 					setBit(i,true);
+ 					return i;
+ 				}
+ 				count++;
+ 			}
+ 		}
+ 		return -1;
+	}
+ 	/*------------------------------------------*/
+ 	public int unsetNewRandomBit (Random rng) {
+ 		int available = numBitsOn();
+ 		if (available<1)
+ 			return -1;
+ 		if (available==1){
+ 			int bit = firstBitOn();
+ 			setBit(bit,false);
+ 			return bit;
+ 		}
+ 		int bitToSet = (int)(rng.nextDouble()*available);
+ 		int count=0;
+ 		for (int i=0; i<numBits; i++) {
+ 			if (isBitOn(i)) {
+ 				if (bitToSet==count){
+ 					setBit(i,false);
+ 					return i;
+ 				}
+ 				count++;
+ 			}
+ 		}
+ 		return -1;
+	}
+
+ 	
+ 	public void invertAllBits () {
+ 		for (int i=0; i<numInts; i++)
+ 			array[i]=~array[i];
+ 		cleanEnd();
+ 	}
+	public void clearAllBits () {
+ 		for (int i=0; i<numInts; i++)
+ 			array[i]=0;
+ 	}
+ 	public void setAllBits () {
+ 		for (int i=0; i<numInts; i++)
+ 			array[i]=~0;
+ 		cleanEnd();
+ 	}
+ 	private void cleanEnd(){
+ 		for (int i=numBits; i<numInts*SIZECHUNK; i++)
+ 			clearBit(i);
+ 	}
+ 	public void clearBit (int whichBit) {
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=array.length)
+  			return;
+  		int theInt = array[whichInt];
+		theInt &= ~(1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		array[whichInt] = theInt;
+ 	}
+ 	public int clearBit (int chunk, int whichBit) {
+  		int theInt = chunk;
+		theInt &= ~(1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		return theInt;
+ 	}
+	public void setBit (int[]a, int whichBit) {
+  		if (a==null)
+  			return;
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=a.length)
+  			return;
+  		int theInt = a[whichInt];
+		theInt |= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		a[whichInt] = theInt;
+ 	}
+ 	public void setBit (int whichBit) {
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=array.length)
+  			return;
+  		int theInt = array[whichInt];
+		theInt |= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		array[whichInt] = theInt;
+ 	}
+ 	public void setBit (int whichBit, boolean on) {
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=array.length)
+  			return;
+  		int theInt = array[whichInt];
+		if (on)
+			theInt |= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		else
+			theInt &= ~(1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		array[whichInt] = theInt;
+ 	}
+ 	public void swapValues (int i, int j) {
+  		if ((inWhichInteger(i)<0 || inWhichInteger(i)>=array.length) ||(inWhichInteger(j)<0 || inWhichInteger(j)>=array.length))
+  			return;
+  		boolean temp = isBitOn(i);
+  		setBit(i, isBitOn(j));
+  		setBit(j, temp);
+ 	}
+ 	private int inWhichInteger (int whichBit) {
+  		return whichBit/SIZECHUNK;
+ 	}
+ 	public void orBits (Bits other) {
+ 		for (int i=0; i< numInts && i< other.numInts; i++) 
+ 				array[i] = array[i] | other.array[i];
+ 	}
+ 	public void andBits (Bits other) {
+ 		for (int i=0; i< numInts && i< other.numInts; i++) 
+ 				array[i] = array[i] & other.array[i];
+ 	}
+	public boolean equals (Bits other) {
+ 		int max = MesquiteInteger.maximum(numInts, other.numInts);
+ 		for (int i=0; i<max; i++) {
+ 			if (i>= numInts) {
+ 				if (other.array[i] != 0)
+ 					return false;
+ 			}
+ 			else if (i>= other.numInts) {
+ 				if (array[i] != 0)
+ 					return false;
+ 			}
+ 			else {
+ 				if (array[i] != other.array[i])
+ 					return false;
+ 			}
+ 		}
+ 		return true;
+ 	}
+
+ 	public boolean equalsComplement (Bits other) {
+ 		int max = MesquiteInteger.maximum(numInts, other.numInts);
+ 		for (int i=0; i<max; i++) {
+ 			if (i>= numInts) {
+ 				if (other.array[i] != ~0)
+ 					return false;
+ 			}
+ 			else if (i>= other.numInts) {
+ 				if (array[i] != ~0)
+ 					return false;
+ 			}
+ 			else {
+ 				int chunk = ~array[i];
+				if (i==numInts-1){//at last chunk; need to clear last bits
+					//clear last numInts*SIZECHUNK - numBits
+					for (int k = 32-(numInts*SIZECHUNK - numBits); k<32; k++)
+			  			chunk = clearBit(chunk, k);
+				}
+ 				if (chunk != other.array[i])
+ 					return false;
+ 			}
+ 		}
+ 		return true;
+ 	}
+	public boolean isBitOn (int whichBit) {
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=array.length)
+  			return false;
+  		int theInt = array[whichInt];
+  		theInt &= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		return (theInt != 0);
+ 	}
+ 	public static boolean isBitOn (int[] bits, int whichBit) {
+  		int whichInt = whichBit/SIZECHUNK;
+  		if (whichInt<0 || whichInt>=bits.length)
+  			return false;
+  		int theInt = bits[whichInt];
+  		theInt &= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		return (theInt != 0);
+ 	}
+ 	public static boolean isBitOn (int bitInteger, int whichBit) {
+  		int theInt = bitInteger;
+  		theInt &= (1<< (SIZECHUNKMINUS1- (whichBit % SIZECHUNK)));
+		return (theInt != 0);
+ 	}
+	/*------------------------------------------*/
+ 	/** returns the next bit, starting a startBit, that has the same value as "on" */
+ 	public int nextBit (int startBit, boolean on) {
+//first, see if there are any bits remaining in the current Int that are the same value as "on";
+  		int whichInt = startBit/SIZECHUNK;
+ 		for (int i=startBit; i<(whichInt+1)*SIZECHUNK && i < numBits; i++)  // check to see if it is in the first int
+ 			if (isBitOn(i)==on)   // then we've found a bit that has the same value as "on"
+ 				return i;
+//now let's check later Ints
+ 		whichInt ++;
+ 		for (int i=whichInt; i<numInts; i++) {
+// if array[i] == 0, then they are all off; if it is ==-1, then they are all on (that is, there are non off)
+ 			if (((array[i]!=0)&&on) || ((array[i]!=-1)&&!on)) {  // then we've found a block that has the same value as on
+//now look to see which bit in the block has the correct value
+		 		for (int j=i*SIZECHUNK; j<(i+1)*SIZECHUNK && j< numBits; j++)
+		 			if (isBitOn(j)==on)   // then we've found the bit that has the same value as "on"
+		 				return j;
+ 			}
+ 		}
+ 		return -1;  //didn't find any, return signal that none found
+ 	}
+ 	/*------------------------------------------*/
+ 	public boolean allBitsOn () {
+ 		for (int i=0; i<numBits; i++)
+ 			if (!isBitOn(i))
+ 				return false;
+ 		return true;
+ 	}
+ 	/*------------------------------------------*/
+ 	public boolean anyBitsOn () {
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=0)
+ 				return true;
+ 		return false;
+ 	}
+ 	/*------------------------------------------*
+ 	public boolean anyBitsOff () {
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=~0)
+ 				return true;
+ 		return false;
+ 	}
+ 	/*------------------------------------------*/
+ 	public int firstBitOn (int bitInteger) {
+ 		for (int i=0; i<SIZECHUNK; i++)
+ 			if (isBitOn(bitInteger,i))
+ 				return i;
+ 		return -1;
+ 	}
+ 	/*------------------------------------------*/
+
+ 	public int firstBitOn () {
+ 		for (int i=0; i<numInts; i++)
+ 			if (array[i]!=0) {
+ 				return 32*i+firstBitOn(array[i]);
+ 			}
+ 		return -1;
+ 	}
+ 	/*------------------------------------------*
+ 	public int firstBitOff (int bitInteger) {
+ 		for (int i=0; i<SIZECHUNK; i++)
+ 			if (!isBitOn(bitInteger,i))
+ 				return i;
+ 		return -1;
+ 	}
+
+ 	/*------------------------------------------*/
+	public int firstBitOff () {
+ 		for (int i=0; i<numBits; i++)
+ 			if (!isBitOn(i)) {
+ 				return i;
+ 			}
+ 		return -1;
+ 	}
+
+ 	/*------------------------------------------*/
+ 	public int lastBitOn (int bitInteger) {
+ 		for (int i=SIZECHUNK-1; i>=0; i--)
+ 			if (isBitOn(bitInteger,i))
+ 				return i;
+ 		return -1;
+ 	}
+
+ 	public int lastBitOn () {
+ 		for (int i=numInts-1; i>=0; i--)
+ 			if (array[i]!=0) {
+ 				return 32*i+lastBitOn(array[i]);
+ 			}
+ 		return -1;
+ 	}
+
+ 	/** Returns true iff exactly one bit is on.   If one bit is on, it returns in "single" the single bit that is on.  */ 
+ 	public boolean oneBitOn (MesquiteInteger single) {
+ 		boolean foundOne = false;
+ 		for (int i=0; i<numBits; i++)
+ 			if (isBitOn(i))
+ 				if (!foundOne) {
+ 					foundOne = true;
+ 					single.setValue(i);
+ 				}
+ 				else  // we've already found one, so there is more than one bit on
+ 					return false;
+ 		return foundOne;
+ 	}
+ 	
+
+
+ 	public String toString () {
+ 		String s = "";
+ 		for (int i=0; i<numBits; i++)
+ 			if (isBitOn(i))
+ 				s+= '1';
+ 			else
+ 				s+= '0';
+ 		return s;
+ 	}
+ 	public String toAsteriskString () {
+ 		String s = "";
+ 		for (int i=0; i<numBits; i++)
+ 			if (isBitOn(i))
+ 				s+= '*';
+ 			else
+ 				s+= '.';
+ 		return s;
+ 	}
+
+ 	public String toPlusMinusString () {
+ 		String s = "";
+ 		for (int i=0; i<numBits; i++)
+ 			if (isBitOn(i))
+ 				s+= '+';
+ 			else
+ 				s+= '-';
+ 		return s;
+ 	}
+
+	/** returns a string listing the bits on.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public String getListOfBitsOn(int offset) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		int lastWritten = -1;
+		for (int i=0; i<numBits; i++) {
+			if (isBitOn(i)) {
+				found=true;
+				if (continuing == 0) {
+					s += " " + (i + offset);
+					lastWritten = i;
+					continuing = 1;
+				}
+				else if (continuing == 1) {
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {
+				if (lastWritten != i-1) {
+					s += " " + (i-1 + offset);
+					lastWritten = i-1;
+				}
+				else
+					lastWritten = -1;
+				continuing = 0;
+			}
+		}
+		if (continuing>1)
+			s += " " + (numBits-1 + offset);
+		if (found)
+			return s;
+		else
+			return "None";
+	}
+	/*...........................................................*/
+	public static void moveColumns(boolean[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		boolean[][] newValues = new boolean[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {   // (starting<=justAfter)
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public static void swapColumns(boolean[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		boolean[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void swapCell(boolean[][] d, int first, int second, int k) {
+		if (k<0)
+			return;
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		if (d[first] == null || k>= d[first].length || d[second] == null || k>= d[second].length)
+			return;
+		boolean temp = d[first][k];
+		d[first][k]=d[second][k];
+		d[second][k] = temp;
+	}
+	/*...........................................................*/
+	public static void moveParts(short[] d, int starting, int num, int justAfter) {   //DRM new 7 March 08
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		short[] newValues = new short[d.length];
+		if (starting>justAfter){
+			int count =justAfter+1;
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=justAfter+1; i<=starting+num-1; i++)
+				d[i]=newValues[i];
+
+		}
+		else {  // moving down			
+			int count =starting;
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=justAfter; i++)
+				d[i]=newValues[i];
+		}
+	}
+	/*...........................................................*/
+	public static void moveRows(boolean[][] d, int starting, int num, int justAfter) {  //DRM: new
+		if (num<=0 || d==null || d.length == 0)
+			return;
+		int numRows = d[0].length;
+		if (starting>=numRows || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=numRows)
+			justAfter = numRows-1;
+		if (justAfter<0)
+			justAfter = -1;
+		boolean[] newValues = new boolean[numRows];
+		for (int column = 0; column<d.length; column++){
+			if (starting>justAfter){
+				int count =justAfter+1;
+				
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=justAfter+1; i<=starting+num-1; i++)
+					d[column][i]=newValues[i];
+			}
+			else {
+				int count =starting;
+				
+				for (int i=starting+num; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting; i<=justAfter; i++)
+					d[column][i]=newValues[i];
+		}
+		}
+	}
+	/*...........................................................*/
+	public static void moveRowsOriginal(boolean[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || d.length == 0)
+			return;
+		int numRows = d[0].length;
+		if (starting>=numRows || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=numRows)
+			justAfter = numRows-1;
+		if (justAfter<0)
+			justAfter = -1;
+		boolean[] newValues = new boolean[numRows];
+		for (int column = 0; column<d.length; column++){
+			if (starting>justAfter){
+				int count =0;
+				for (int i=0; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting+num; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			else {
+				int count =0;
+				for (int i=0; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting+num; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			for (int i=0; i<numRows; i++)
+				d[column][i]=newValues[i];
+		}
+	}
+	public static boolean[][] addRows(boolean[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		for (int column = 0; column<d.length; column++){
+			d[column]=addParts(d[column], starting, num);
+		}
+		return d;
+	}
+	public static boolean[][] deleteRows(boolean[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		for (int column = 0; column<d.length; column++){
+			d[column]=deleteParts(d[column], starting, num);
+		}
+		return d;
+	}
+ 	/*------------------------------------------*/
+ 	/**Inserts num (cleared) bits just after bit "starting"*/
+ 	public static boolean[] addParts (boolean[] d, int starting, int num) {
+		if (num==0 || d == null)
+			return d;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=d.length)
+			starting = d.length-1;
+		int newNum = d.length + num;
+		boolean[] newValues = new boolean[newNum];
+		for (int i=0; i<=starting; i++)
+			newValues[i]=d[i];
+		for (int i=0; i<num ; i++)
+			newValues[starting + i + 1]=false;
+		for (int i=0; i<d.length-starting-1; i++) 
+			newValues[i +starting+num+1]=d[starting + i + 1];
+		return newValues;
+ 	}
+	/*...........................................................*/
+	public static boolean[] deleteParts(boolean[] values, int starting, int num){
+		if (num<=0 || values == null)
+			return values;
+		if (num+starting>values.length)
+			num = values.length-starting;
+		int newNumParts = values.length-num;
+		boolean[] newValues = new boolean[newNumParts];
+		
+		for (int i=0; i<starting; i++) {
+			newValues[i] = values[i];
+		}
+		for (int i=starting+num; i<values.length; i++) {
+			newValues[i-num ] = values[i];
+		}
+		return newValues;
+	}
+
+	/*------------------------------------------*/
+ 	public static String toString (int[] bits) {
+ 		if (bits==null)
+ 			return null;
+ 		String s = "";
+ 		for (int i=0; i<bits.length*SIZECHUNK; i++) {
+ 			if (isBitOn(bits, i))
+ 				s+= '1';
+ 			else
+ 				s+= '0';
+ 		}
+ 		return s;
+ 	}
+ 	/*------------------------------------------*/
+ 	public static String toString (boolean[] bits) {
+ 		if (bits==null)
+ 			return null;
+ 		String s = "";
+ 		for (int i=0; i<bits.length; i++) {
+ 			if (bits[i])
+ 				s+= '1';
+ 			else
+ 				s+= '0';
+ 		}
+ 		return s;
+ 	}
+
+	/*..........................................Bits.....................................*/
+	/** converts passed int  to string, as its bits representation.  Used for development/debugging. �*/
+	public static String toString(byte s) {
+		String temp="";
+		for (int e=7; e>=0; e--) {
+			if (((((byte)1)<<e)&s)!=((byte)0)) 
+				temp+="1";
+			else
+				temp+="0";
+		}
+		return temp;
+	}
+	/*..........................................Bits.....................................*/
+	/** converts passed int  to string, as its bits representation.  Used for development/debugging. �*/
+	public static String toString(short s) {
+		String temp="";
+		for (int e=15; e>=0; e--) {
+			if (((((short)1)<<e)&s)!=((short)0)) 
+				temp+="1";
+			else
+				temp+="0";
+		}
+		return temp;
+	}
+	/*..........................................Bits.....................................*/
+	/** converts passed int  to string, as its bits representation.  Used for development/debugging. �*/
+	public static String toString(int s) {
+		String temp="";
+		for (int e=SIZECHUNKMINUS1; e>=0; e--) {
+			if (((((int)1)<<e)&s)!=((int)0)) 
+				temp+="1";
+			else
+				temp+="0";
+		}
+		return temp;
+	}
+	/*..........................................Bits.....................................*/
+	/** converts passed long  to string, as its bits representation.  Used for development/debugging. �*/
+	public static String toString(long s) {
+		String temp="";
+		for (int e=63; e>=0; e--) {
+			if (((1L<<e)&s)!=0L) 
+				temp+="1";
+			else
+				temp+="0";
+		}
+		return temp;
+	}
+ 	/*------------------------------------------*/
+}
+
+
diff --git a/Source/mesquite/lib/BitsSpecsSet.java b/Source/mesquite/lib/BitsSpecsSet.java
new file mode 100644
index 0000000..3a20fff
--- /dev/null
+++ b/Source/mesquite/lib/BitsSpecsSet.java
@@ -0,0 +1,208 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+
+/* ======================================================================== */
+/** A specset with bit information.*/
+public abstract class BitsSpecsSet extends SpecsSet  {
+	Bits myBits;
+	public BitsSpecsSet(String name, int numParts){
+		super(name, numParts);
+		myBits = new Bits(numParts);
+	}
+	public String getTypeName(){
+		return "Bits specificaton set";
+	}
+	
+	public String toString(int ic){
+		if (isBitOn(ic))
+			return "true";
+		else
+			return "false";
+	}
+ 	/*.................................................................................................................*/
+ 	/** Sets the value for part "part" to be the same as that at part "otherPart" in the incoming specsSet*/
+	public void equalizeSpecs(SpecsSet other, int otherPart, int part){
+		if (other instanceof BitsSpecsSet){
+			setSelected(part, ((BitsSpecsSet)other).isBitOn(otherPart));
+		}
+	}
+ 	/*.................................................................................................................*/
+	/** Returns a string that simply lists the on bits, NOT zero-based. */
+	public String getListOfOnBits(String delimiter){
+		StringBuffer sb= new StringBuffer();
+		boolean first = true;
+		for (int i=0; i<getNumberOfParts(); i++)
+			if (isPresent(i))
+				if (first){
+					sb.append("" + (i+1));
+					first = false;
+				}
+				else
+					sb.append(delimiter + (i+1));
+		return sb.toString();
+	}
+ 	/*.................................................................................................................*/
+	//We can't remember why this doesn't use the selected field already within the superclass Associable
+	/** Returns bits. */
+	public Bits getBits(){
+		return myBits;
+	}
+	/*.................................................................................................................*/
+	/** Returns first part on. */
+	public int firstBitOn() {
+		return myBits.firstBitOn();
+	}
+	/*.................................................................................................................*/
+	/** Returns if part ic is on. */
+	public boolean isBitOn(int ic){
+		return myBits.isBitOn(ic);
+	}
+	/*.................................................................................................................*/
+	/** Returns number of bits on. */
+	public int numBitsOn(){
+		return myBits.numBitsOn();
+	}
+ 	/*------------------------------------------*/
+ 	public boolean allBitsOn () {
+		return myBits.allBitsOn();
+ 	}
+
+	/*.................................................................................................................*/
+	/** Returns if part ic is on. */
+	public boolean isPresent(int ic){
+		return myBits.isBitOn(ic);
+	}
+	/** Returns if any part are on */
+	public boolean anySelected(){
+		return myBits.anyBitsOn();
+		
+	}
+	/** Returns how many are on */
+	public int numberSelected(){
+		return myBits.numBitsOn();
+		
+	}
+	/** Set bits of this to be the same as passed bits */
+	public void setBits(Bits bits){
+		setDirty(true);
+		if (bits!=null)
+			bits.copyBits(myBits);
+	}
+	/** Set part ic to either on or not according to boolean */
+	public void setSelected(int ic, boolean select){
+		setDirty(true);
+		if (select)
+			myBits.setBit(ic);
+		else
+			myBits.clearBit(ic);
+	}
+	/** Deselect all part */
+	public void deselectAll(){
+		setDirty(true);
+		myBits.clearAllBits();
+	}
+	/** Select all parts */
+	public void selectAll(){
+		setDirty(true);
+		myBits.setAllBits();
+	}
+	/*-----------------------------------------*/
+	/** Returns index of first selected part */
+	public int firstSelected() {
+		if (!anySelected())
+			return -1;
+		for (int i = 0; i<getNumberOfParts(); i++) {
+			if (myBits.isBitOn(i))
+				return i;
+		}
+		return -1;
+	}
+	/*-----------------------------------------*/
+	/** Returns index of last selected part */
+	public int lastSelected() {
+		if (!anySelected())
+			return -1;
+		for (int i = getNumberOfParts()-1; i>=0; i--) {
+			if (myBits.isBitOn(i)) {
+				return i;
+				
+			}
+		}
+		return -1;
+	}
+	/*-----------------------------------------*/
+	/** Returns selected directly */
+	public Bits getSelectedBits() {
+		return myBits;
+	}
+	/*-----------------------------------------*/
+	/** returns number of parts that are selected or, if onlyCountSelected is false, all parts*/
+	public int numberSelected(boolean onlyCountSelected) {
+		if (onlyCountSelected)
+			return numberSelected();
+		else
+			return getNumberOfParts();
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are selected parts that form a contiguous selection */
+	public boolean contiguousSelection() {
+		if (!anySelected())
+			return false;
+		int firstSelected = myBits.nextBit(0, true);
+		if (firstSelected<0)  // none is selected
+			return false;
+		int nextNotSelected = myBits.nextBit(firstSelected+1,false);  // first one, after the block, that is not selected
+		if (nextNotSelected>0) {
+			return (myBits.nextBit(nextNotSelected+1,true)==-1);  //no more have been found
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		setDirty(true);
+ 		myBits.addParts(starting, num); //TODO: set default (for inclusion, set to on!!!)
+ 		numParts = myBits.getSize();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Delete num parts from and including "starting"  */
+	public boolean deleteParts(int starting, int num){ 
+		setDirty(true);
+ 		myBits.deleteParts(starting, num);
+ 		numParts = myBits.getSize();
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** */
+	public boolean moveParts(int starting, int num, int justAfter){  
+		setDirty(true);
+ 		myBits.moveParts(starting, num, justAfter);
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** */
+	public boolean swapParts(int first, int second){  
+		setDirty(true);
+ 		myBits.swapParts(first, second);
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/lib/BooleanUtil.java b/Source/mesquite/lib/BooleanUtil.java
new file mode 100644
index 0000000..261f65a
--- /dev/null
+++ b/Source/mesquite/lib/BooleanUtil.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+public class BooleanUtil {
+
+	/*-----------------------------------------*/
+	public static boolean anyValuesTrue(boolean[] booleanArray) {
+		for (int i=0; i<booleanArray.length; i++) {
+			if (booleanArray[i])
+				return true;
+		}
+		return false;
+	}
+
+	/*-----------------------------------------*/
+	public static boolean[]  copyBooleanArray(boolean[] booleanArray) {
+		boolean[] newArray = new boolean[booleanArray.length];
+		for (int i=0;i<newArray.length; i++)
+			newArray[i]=booleanArray[i];
+		return newArray;
+	}
+
+	
+	/*------------------------------------------*/
+ 	/**Reverses the elements of a boolean array*/
+ 	public static boolean[] reverseBooleanArray (boolean[] d) {
+		if (d==null)
+			return null;
+		boolean[] values = new boolean[d.length];
+		for (int i=0; i<values.length; i++)
+			values[values.length-1-i] =  d[i];
+		return values;
+ 	}
+
+}
diff --git a/Source/mesquite/lib/CanRetrieveTreeBlock.java b/Source/mesquite/lib/CanRetrieveTreeBlock.java
new file mode 100644
index 0000000..e71a499
--- /dev/null
+++ b/Source/mesquite/lib/CanRetrieveTreeBlock.java
@@ -0,0 +1,21 @@
+/* Mesquite source code.  Copyright 2013 W. Maddison and D. Maddison.
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+/* ======================================================================== */
+/**Interface for object to claim it is reconnectable, for processes that need to be re-established*/
+public interface CanRetrieveTreeBlock {
+   	public void retrieveTreeBlock(TreeVector treeList);
+}
+
diff --git a/Source/mesquite/lib/CardPanel.java b/Source/mesquite/lib/CardPanel.java
new file mode 100644
index 0000000..efaab76
--- /dev/null
+++ b/Source/mesquite/lib/CardPanel.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/*===============================================*/
+/** The panel making up one card of a PanelOfCards */
+public class CardPanel extends Panel  {
+	public Image tabImageOn = null;
+	public Image tabImageOff = null;
+	
+	CardPanel (String tabImageOnFile, String tabImageOffFile) {
+		super();
+		if (tabImageOnFile != null)
+			tabImageOn = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + tabImageOnFile);
+		if (tabImageOffFile != null)
+			tabImageOff = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + tabImageOffFile);
+	}
+
+	CardPanel () {
+		super();
+	}
+	/*.................................................................................................................*/
+	public Image getTabImageOn(){
+		return tabImageOn;
+	}
+	/*.................................................................................................................*/
+	public Image getTabImageOff(){
+		return tabImageOff;
+	}
+}
+
diff --git a/Source/mesquite/lib/ChangeAuthority.java b/Source/mesquite/lib/ChangeAuthority.java
new file mode 100644
index 0000000..c04d09d
--- /dev/null
+++ b/Source/mesquite/lib/ChangeAuthority.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/* ======================================================================== */
+/**  Make this abstract and have subclasses (literature citation, observation (specimen voucher number, image number))*/
+public class ChangeAuthority {
+	String au = "I said so";
+	public ChangeAuthority(){
+	}
+	public String toString(){
+		return au;
+	}
+	public void set(String s){
+		au = s;
+	}
+	public String getNexusString(){
+		return ParseUtil.tokenize(toString());
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/ChangeEvent.java b/Source/mesquite/lib/ChangeEvent.java
new file mode 100644
index 0000000..896559d
--- /dev/null
+++ b/Source/mesquite/lib/ChangeEvent.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+public class ChangeEvent {
+	Author author;
+	long time;
+	String change;
+	ChangeAuthority authority;
+	
+	public ChangeEvent(Author author, long time, String change){
+		this.author = author;
+		this.time = time;
+		this.change = change;
+	}
+	public ChangeEvent cloneEvent(){
+		ChangeEvent ce = new ChangeEvent(author, time, new String(change));
+		ce.authority = authority;
+		return ce;
+	}
+	public void exchangeData(ChangeEvent other){
+		Author tempA = author;
+		author = other.author;
+		other.author = tempA;
+		long tempT = time;
+		time = other.time;
+		other.time = tempT;
+		String tempC = change;
+		change = other.change;
+		other.change = tempC;
+		ChangeAuthority tempU = authority;
+		authority = other.authority;
+		other.authority = tempU;
+	}
+	public boolean equals(ChangeEvent other){
+		return Author.authorsEqual(author, other.author) && time == other.time && StringUtil.stringsEqual(change, other.change);
+	}
+	public void setAuthority(ChangeAuthority authority){
+		this.authority = authority;
+	}
+	public ChangeAuthority getAuthority(){
+		return authority;
+	}
+	
+	public String getChange(){
+		return change;
+	}
+	public Author getAuthor(){
+		return author;
+	}
+	public long getTime(){
+		return time;
+	}
+	public String toString(){
+		StringBuffer sb = new StringBuffer(1000);
+		sb.append( "Changed to: " + change);
+		sb.append(" by author: " );
+		if (!StringUtil.blank(author.getName()))
+			sb.append(author.getName());
+		else
+			sb.append(author.getCode());
+		sb.append( " at time " + new Date(time));
+		return sb.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/ChangeHistory.java b/Source/mesquite/lib/ChangeHistory.java
new file mode 100644
index 0000000..9d4dc75
--- /dev/null
+++ b/Source/mesquite/lib/ChangeHistory.java
@@ -0,0 +1,205 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/* ======================================================================== */
+/**  */
+public class ChangeHistory {
+	Vector events;
+	
+	public ChangeHistory(){
+		events = new Vector();
+	}
+	public ChangeEvent addEvent(Author author, long time, String change){
+		ChangeEvent e = null;
+		events.addElement(e = new ChangeEvent(author, time, change));
+		sortByReverseTime();
+		return e;
+	}
+	
+	public void sortByReverseTime(){
+		for (int i= 0; i< getNumEvents(); i++){
+			ChangeEvent e = getEvent(i);
+			for (int j= i-1; j>=0 && getEvent(j).time<getEvent(j+1).time; j--) {
+				ChangeEvent tempJ = getEvent(j);
+				ChangeEvent tempJ1 = getEvent(j+1);
+				tempJ.exchangeData(tempJ1);				
+			}
+		}
+	}
+	public void addEvent(ChangeEvent e){
+		events.addElement(e);
+	}
+	public static final int NOHISTORY = 4;
+	public static final int NOTCONTAINED = 3;
+	public static final int SUBSET = 2;
+	public static final int SUPERSET = 1;
+	public static final int EQUAL = 0;
+	
+	public int compareHistories(ChangeHistory other){
+		boolean thisIsSubset = firstFoundInSecond(this, other);
+		boolean thisIsSuperset = firstFoundInSecond(other, this);
+		if (thisIsSubset && thisIsSuperset)
+			return EQUAL;
+		if (thisIsSubset)
+			return SUBSET;
+		if (thisIsSuperset)
+			return SUPERSET;
+		return NOTCONTAINED;
+	}
+	private boolean firstFoundInSecond(ChangeHistory u, ChangeHistory v){
+		for (int i= 0; i< u.getNumEvents(); i++){
+			ChangeEvent e = u.getEvent(i);
+			if (!matchingEventFound(e, v))
+				return false;
+		}
+		return true;
+	}
+	private boolean matchingEventFound(ChangeEvent e, ChangeHistory v){
+		boolean matchFound = false;
+		for (int j= 0; j< v.getNumEvents();j++){
+			ChangeEvent otherE = v.getEvent(j);
+			if (e.equals(otherE))
+				matchFound = true;
+		}
+		return matchFound;
+	}
+	public ChangeHistory cloneHistory(){
+		ChangeHistory ch = new ChangeHistory();
+		for (int i= 0; i< getNumEvents(); i++){
+			ChangeEvent ce = getEvent(i);
+			ch.addEvent(ce.cloneEvent());
+		}
+		ch.sortByReverseTime();
+		return ch;
+	}
+	public void incorporate(ChangeHistory v){
+		for (int i= 0; i< v.getNumEvents(); i++){
+			ChangeEvent ce = v.getEvent(i);
+			if (!matchingEventFound(ce, this))
+				addEvent(ce.cloneEvent());
+		}
+		sortByReverseTime();
+	}
+	public int getNumEvents(){
+		return events.size();
+	}
+	public ChangeEvent getEvent(int i){
+		if (i<0 || i>= events.size())
+			return null;
+		if (events.size()==0)
+			return null;
+		return (ChangeEvent)events.elementAt(i);
+	}
+	public long lastModified(){
+		if (events.size()==0)
+			return 0;
+		long max = 0;
+		for (int i=events.size()-1; i>=0;i--) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			if (ce.time > max)
+				max = ce.time;
+		}
+		return max;
+	}
+	public ChangeEvent getLastEvent(){
+		if (events.size()==0)
+			return null;
+		long max = 0;
+		ChangeEvent last = null;
+		for (int i=events.size()-1; i>=0;i--) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			if (ce.time > max) {
+				max = ce.time;
+				last = ce;
+			}
+		}
+		return last;
+	}
+	public boolean timeExists(long time){
+		if (events.size()==0)
+			return false;
+		for (int i=events.size()-1; i>=0;i--) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			if (ce.time == time)
+				return true;
+		}
+		return false;
+	}
+	public ChangeEvent updateEvent(Author author, long time, String change){
+		if (events.size()==0)
+			return null;
+		for (int i=events.size()-1; i>=0;i--) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			if (ce.time == time) {
+				ce.change = change;
+				return ce;
+			}
+		}
+		sortByReverseTime();
+		return null;
+	}
+	public String toString(){
+		if (events.size()==0)
+			return null;
+		StringBuffer sb = new StringBuffer(1000);
+		for (int i=0; i<events.size();i++) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			sb.append("Author: " );
+			if (!StringUtil.blank(ce.author.getName()))
+				sb.append(ce.author.getName());
+			else
+				sb.append(ce.author.getCode());
+			sb.append( "; Time " + new Date(ce.time) + " Changed to: " + ce.change);
+			ChangeAuthority ca = ce.getAuthority();
+			if (ca !=null) {
+				sb.append("; Authority: ");
+				sb.append(ca.toString());
+			}
+			sb.append('\n');
+		}
+		return sb.toString();
+	}
+	public String getNexusString(){
+		if (events.size()==0)
+			return null;
+		StringBuffer sb = new StringBuffer(1000);
+		getNexusString(sb);
+		return sb.toString();
+	}
+
+	public void getNexusString(StringBuffer sb){
+		if (events.size()==0 || sb == null)
+			return;
+		for (int i=0; i<events.size();i++) {
+			ChangeEvent ce = (ChangeEvent)events.elementAt(i);
+			sb.append("( ");
+			sb.append(ce.author.getCode());
+			sb.append(" " + ParseUtil.tokenize(NexusBlock.getNEXUSTime(ce.time)) + " " + ParseUtil.tokenize(ce.change));
+			ChangeAuthority ca = ce.getAuthority();
+			if (ca !=null) {
+				sb.append(' ');
+				sb.append(ca.getNexusString());
+			}
+			sb.append(" ) ");
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ChartBkgdExtra.java b/Source/mesquite/lib/ChartBkgdExtra.java
new file mode 100644
index 0000000..754217f
--- /dev/null
+++ b/Source/mesquite/lib/ChartBkgdExtra.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of ChartExtra.  Used only so that chart drawing knows to call these before the chart
+is drawn.. */
+public abstract class ChartBkgdExtra extends ChartExtra {
+	public ChartBkgdExtra (MesquiteModule ownerModule, MesquiteChart chart) {
+		super(ownerModule, chart);
+	}
+}
+
diff --git a/Source/mesquite/lib/ChartExtra.java b/Source/mesquite/lib/ChartExtra.java
new file mode 100644
index 0000000..65415dc
--- /dev/null
+++ b/Source/mesquite/lib/ChartExtra.java
@@ -0,0 +1,124 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/** A class used for additional graphical and calculations elements to be drawn and calculated within 
+charts -- legends, regression lines, etc. The ChartTextra is notified when the cursor 
+is moved over a point and so on, and when the chart is drawn the extra is notified via drawOnChart so that
+it can add its items to the graphic.*/
+public abstract class ChartExtra implements Listable, OwnedByModule {
+	protected MesquiteChart chart;
+	protected MesquiteModule ownerModule;
+	public static long totalCreated = 0;
+	private Vector panels = new Vector();
+	public ChartExtra (MesquiteModule ownerModule, MesquiteChart chart) {
+		this.chart = chart;
+		this.ownerModule=ownerModule;
+		totalCreated++;
+	}
+	
+	public MesquiteModule getOwnerModule(){
+		return ownerModule;
+	}
+	
+	public String getName(){
+		if (ownerModule !=null)
+			return ownerModule.getName();
+		else
+			return getClass().getName();
+	}
+	
+	public MesquiteChart getChart(){
+		return chart;
+	}
+	public void dispose(){
+		ownerModule =null;
+		chart=null;
+	}
+	/**Do any calculations needed.  If chart needs to be re-munched, pass back true*/
+	public abstract boolean doCalculations();
+	/**draw on the chart*/
+	public abstract void drawOnChart(Graphics g);
+	/**print on the chart*/
+	public abstract void printOnChart(Graphics g);
+	/**draw on the axis*/
+	public void drawOnAxes(Graphics g, MesquiteChart chart){
+	}
+	
+	protected int xPixelOnAxis(double x, MesquiteChart chart){
+		if (chart != null && chart.getCharter() != null)
+			return chart.getCharter().xToPixel(x,chart) + chart.getXAxisEdge() - chart.scrollXOffset();
+		return -1;
+	}
+	protected int yPixelOnAxis(double y, MesquiteChart chart){
+		if (chart != null && chart.getCharter() != null)
+			return chart.getCharter().yToPixel(y,chart) - chart.scrollXOffset();
+		return -1;
+	}
+	
+	/**return true if any notes at point in chart*/
+	private boolean anyText(int point){
+		return false;
+	}
+	/**return a text version of information on chart*/
+	public String writeOnChart(){
+		return "";
+			
+	}
+	/**return a text version of information at node*/
+	public String textAtPoint(int node){
+		return "";
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		return "";
+	}
+
+	/**to inform ChartExtra that cursor has just entered point*/
+	public void cursorEnterPoint(int point, int exactPoint, Graphics g){}
+	/**to inform ChartExtra that cursor has just exited point*/
+	public void cursorExitPoint(int point, int exactPoint, Graphics g){}
+	/**to inform ChartExtra that cursor has just touched point*/
+	public void cursorTouchPoint(int point, int exactPoint, Graphics g){}
+	
+	public void addPanelPlease(Panel p){
+		panels.addElement(p);
+		chart.addPanelPlease(p);
+	}
+	public void removePanelPlease(Panel p){
+		panels.addElement(p);
+		chart.removePanelPlease(p);
+	}
+	protected Vector getPanels(){
+		return panels;
+	}
+
+	public void turnOff() {
+		if (chart==null)
+			return;
+		chart.removeExtra(this);
+		chart.repaint();
+	}
+	
+}
+
+
+
+
diff --git a/Source/mesquite/lib/ChartField.java b/Source/mesquite/lib/ChartField.java
new file mode 100644
index 0000000..3bdf4ed
--- /dev/null
+++ b/Source/mesquite/lib/ChartField.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ======================================================================== */
+public class ChartField extends MesquitePanel {
+
+	private MesquiteChart chart;
+	private MesquiteNumber valueX, valueY;
+	private Menu chartTypeSubmenu;
+	boolean suppressBlank = false;
+	public ChartField( MesquiteChart chart){
+		this.chart = chart;
+		valueX = new MesquiteNumber();
+		valueY = new MesquiteNumber();
+		setLayout(null);
+		//setBackground(Color.green);
+	}
+	public void print(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this)) {
+	   		return;
+	   	}
+		g.setColor(Color.black);
+		if (chart.getCharter()!=null)
+			chart.getCharter().drawChartBackground(g, chart);
+		chart.drawAllBackgroundExtras(g);
+		if (chart.getCharter()!=null)
+			chart.getCharter().drawChart(g, chart);
+		chart.drawAllExtras(g);
+		chart.drawAxes(true);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this)) {
+	   		return;
+	   	}
+		if (chart.getCharter() != null){
+			g.setColor(Color.black);
+			chart.getCharter().drawBlank( g, chart);
+			chart.getCharter().drawChartBackground(g, chart);
+			chart.drawAllBackgroundExtras(g);
+			chart.getCharter().drawChart(g, chart);
+			chart.drawAllExtras(g);
+			chart.drawAxes(false);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+
+	}
+	public void drawBlank() {   
+		if (suppressBlank)
+			return;
+		
+		Graphics g = this.getGraphics();
+		if (g!=null) {
+			int fieldWidth= getBounds().width; //chart.getChartWidth()-chart.getXAxisEdge();
+			int fieldHeight= getBounds().height; //chart.getChartHeight()-chart.getYAxisEdge();
+			g.setColor(Color.lightGray);
+			g.fillRoundRect(0,0,fieldWidth,fieldHeight, 5, 5);
+			g.setColor(Color.black);
+			g.drawRoundRect(0,0,fieldWidth,fieldHeight, 5, 5);
+			g.setColor(Color.white);
+			g.drawRoundRect(1,1,fieldWidth-2,fieldHeight-2, 5, 5);
+			g.setColor(Color.gray);
+			g.drawRoundRect(1,1,fieldWidth-1,fieldHeight-1, 5, 5);
+			g.setColor(Color.black);
+			int margin = chart.getMargin();
+			if (chart.getCharter()!=null)
+				chart.getCharter().drawBlank(g, chart);
+			g.dispose();
+		}
+	}
+	/*_________________________________________________*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			tool = null;
+		if (chart.getCharter()!=null)
+			chart.getCharter().mouseMoveInField(modifiers,x,y, chart, (ChartTool)tool);
+	}
+	/*_________________________________________________*/
+	   public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			tool = null;
+		if (chart.getCharter()!=null)
+			chart.getCharter().mouseDownInField(modifiers,x,y, chart, (ChartTool)tool);
+	   }
+
+	/*_________________________________________________*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			tool = null;
+		if (chart.getCharter()!=null)
+			chart.getCharter().mouseDragInField(modifiers,x,y, chart, (ChartTool)tool);
+	}
+	/*_________________________________________________*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof ChartTool))
+			tool = null;
+		if (chart.getCharter()!=null)
+			chart.getCharter().mouseUpInField(modifiers,x,y, chart, (ChartTool)tool);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ChartListener.java b/Source/mesquite/lib/ChartListener.java
new file mode 100644
index 0000000..ef489d6
--- /dev/null
+++ b/Source/mesquite/lib/ChartListener.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+public interface ChartListener  {
+	public void pointMouseDown(MesquiteChart chart, int whichPoint, MesquiteNumber valueX, MesquiteNumber valueY, int x, int y, int modifiers, String message);
+	public void pointMouseUp(MesquiteChart chart, int whichPoint, int x, int y, int modifiers, String message);
+}
+
+
diff --git a/Source/mesquite/lib/ChartTool.java b/Source/mesquite/lib/ChartTool.java
new file mode 100644
index 0000000..5cd123d
--- /dev/null
+++ b/Source/mesquite/lib/ChartTool.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+	/** This subclass of MesquiteTool is used in charts.
+	*/
+public class ChartTool extends MesquiteTool {
+	MesquiteCommand touchedCommand;
+	MesquiteCommand droppedCommand;
+	
+	public ChartTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand droppedCommand) {
+		super(initiator, name, imageDirectoryPath,  imageFileName, hotX, hotY, fullDescription, explanation);
+		this.touchedCommand = touchedCommand;
+		this.droppedCommand = droppedCommand;
+	}
+	
+	public void setTouchedCommand(MesquiteCommand touchedCommand){
+		this.touchedCommand = touchedCommand;
+	}
+	public void setDroppedCommand(MesquiteCommand droppedCommand){
+		this.droppedCommand = droppedCommand;
+	}
+	public void dispose(){ 
+		if (touchedCommand!=null) 
+			touchedCommand.dispose();
+		else if (droppedCommand!=null) 
+			droppedCommand.dispose();
+		touchedCommand=null;
+		droppedCommand=null;
+		super.dispose();
+	}
+	
+	public void pointTouched (int point, int x, int y, int modifiers) {
+		if (touchedCommand!=null)
+			touchedCommand.doItMainThread(Integer.toString(point) + " " + x + " " +  y + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", touchedCommand, this), false, false);  
+	}
+	public void pointDropped (int point, int x, int y, int modifiers) {
+		if (droppedCommand!=null)
+			droppedCommand.doItMainThread(Integer.toString(point) + " " + x + " " +  y + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", droppedCommand, this), false, false);  
+	}
+	}
+
diff --git a/Source/mesquite/lib/ChartWindow.java b/Source/mesquite/lib/ChartWindow.java
new file mode 100644
index 0000000..bc0e5fb
--- /dev/null
+++ b/Source/mesquite/lib/ChartWindow.java
@@ -0,0 +1,180 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** Chart windows can subclass this. Provides standard versions of some methods.. */
+public abstract class ChartWindow extends MesquiteWindow {
+	private MesquiteChart chart;
+
+	protected String chartTitle = "Chart";
+
+	protected ChartTool arrowTool, infoTool;
+
+	public ChartWindow(MesquiteModule ownerModule, boolean showInfoBar) {
+		super(ownerModule, showInfoBar);
+		arrowTool = new ChartTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(), "arrow.gif", 4, 2, "Select", null, null, null);
+		arrowTool.setIsArrowTool(true);
+		addTool(arrowTool);
+		setCurrentTool(arrowTool);
+		if (arrowTool != null)
+			arrowTool.setInUse(true);
+		infoTool = new ChartTool(this, "info", MesquiteModule.getRootImageDirectoryPath(), "info.gif", 1, 1, "Show Information", null, null, null);
+		addTool(infoTool);
+		setShowExplanation(true);
+		setShowAnnotation(true);
+		if (getPalette() != null)
+			getPalette().setNumColumns(1);
+		resetTitle();
+	}
+
+	public void contentsChanged() {
+		if (chart != null) {
+			chart.repaint();
+			if (chart.getField() != null)
+				chart.getField().repaint();
+		}
+		super.contentsChanged();
+	}
+
+	/* ................................................................................................................. */
+	public void copyGraphicsPanel() {
+		if (getChart() == null || getChart().getCopyCommand() == null)
+			return;
+		getChart().getCopyCommand().doItMainThread("", null, this); // command invoked
+	}
+
+	/* ................................................................................................................. */
+	public int getMinimumContentHeight() {
+		return 200; // ideally do this more sensibly
+	}
+
+	/* ................................................................................................................. */
+	public String getTextContents() {
+		if (chart != null && infoBar != null) {
+			String s = StringUtil.lineEnding() + chart.getTextVersion() + StringUtil.lineEnding() + StringUtil.lineEnding() + "-----------------";
+			s += StringUtil.lineEnding() + "Parameters of modules: " + StringUtil.lineEnding() + infoBar.getText(InfoBar.TEXT_PARAMETERS);
+			s += StringUtil.lineEnding() + "====================" + StringUtil.lineEnding();
+			return s;
+		}
+		else
+			return null;
+	}
+
+	public void printWindow(MesquitePrintJob pjob) {
+		if (pjob != null) {
+			int mode = infoBar.getMode();
+			if (mode > 0) { // text mode
+				super.printWindow(pjob);
+			}
+			else {// graphical mode
+				chart.printChart(pjob, this);
+			}
+		}
+	}
+
+	public String getPrintMenuItem() {
+		return "Print Chart...";
+	}
+
+	/* ................................................................................................................. */
+	public String getPrintToFitMenuItemName() {
+		return "Print Chart To Fit Page...";
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * @author Peter Midford
+	 */
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			if (infoBar.getMode() > 0)
+				super.windowToPDF(pdfFile, fitToPage);
+			else
+				chart.chartToPDF(pdfFile, this, fitToPage);
+		}
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * @author Peter Midford
+	 * @return String
+	 */
+	public String getPrintToPDFMenuItemName() {
+		return "Save Chart as PDF...";
+	}
+
+	public void setScroller(Panel panel) {
+		MesquiteMessage.println("sorry, this chart window doesn't accommodate a scroller");
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * When called the window will determine its own title. MesquiteWindows need to be self-titling so that when things change (names of files, tree blocks, etc.) they can reset their titles properly
+	 */
+	public void resetTitle() {
+		setTitle(chartTitle);
+	}
+
+	/* ................................................................................................................... */
+	public void setChartTitle(String title) {
+		this.chartTitle = title;
+	}
+
+	public MesquiteChart getChart() {
+		return chart;
+	}
+
+	public void setChart(MesquiteChart chart) {
+		this.chart = chart;
+		if (chart != null) {
+			chart.setArrowTool(arrowTool);
+			infoTool.setTouchedCommand(MesquiteModule.makeCommand("infoTouch", chart));
+			chart.setInfoTool(infoTool);
+		}
+
+	}
+
+	protected void setContentsCursor(Cursor c) {
+		if (c == null)
+			MesquiteMessage.printStackTrace("Error: cursor of chart window null");
+		else if (chart != null)
+			chart.setCursor(c);
+	}
+
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu) */
+	public int getShowMenuLocation() {
+		return 0;
+	}
+
+	public void setChartVisible() {
+		addToWindow(chart);
+		windowResized();
+		chart.setVisible(true);
+	}
+
+	/* ................................................................................................................. */
+	public abstract void recalcChart();
+
+	/* ................................................................................................................. */
+	public void blankChart() {
+		chart.drawBlank();
+	}
+	/* ................................................................................................................. */
+}
+
diff --git a/Source/mesquite/lib/Charter.java b/Source/mesquite/lib/Charter.java
new file mode 100644
index 0000000..7af827f
--- /dev/null
+++ b/Source/mesquite/lib/Charter.java
@@ -0,0 +1,306 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ======================================================================== */
+/** Charters draw the charts.  The available charters are stored in a vector in MesquiteTrunk (to which they can be added by
+addCharter() which is passed the Class).  Charters must have constructor with no arguments because they are instantiated using
+newInstance. */
+public abstract class Charter  {
+	protected MesquiteNumber maxX =new MesquiteNumber();
+	protected MesquiteNumber minX=new MesquiteNumber();
+	protected MesquiteNumber maxY =new MesquiteNumber();
+	protected MesquiteNumber minY=new MesquiteNumber();
+	protected MesquiteNumber tempNum=new MesquiteNumber();
+	protected boolean chartDone = false;
+	protected int minTicks = 3;
+	protected int maxTicks =1000;
+	protected int markerWidth = 4;
+	protected Color bgColor = Color.white;
+	protected Color axisColor = Color.blue;
+	protected Color gridColor = Color.cyan;
+	protected boolean drawWarningSuppressed = false;
+	protected boolean suspendDrawing = false;
+	protected boolean suspendChartCalculations = false;
+	
+	public abstract void calculateChart(MesquiteChart chart);
+	public  abstract void drawChartBackground(Graphics g, MesquiteChart chart);
+	public  abstract void drawChart(Graphics g, MesquiteChart chart);
+	public  abstract void drawBlank(Graphics g, MesquiteChart chart);
+	public void setShowNames(boolean showNames) {}
+	
+	public String getTextVersion(MesquiteChart chart){
+		if (chart==null)
+			return null;
+		StringBuffer s = new StringBuffer();
+		chart.putRawTextVersion(null, ": ", StringUtil.lineEnding(), false, false, s);
+		return s.toString();
+	}
+	StringInABox xAxisWriter;
+	MesquiteNumber minVisX = new MesquiteNumber();
+	MesquiteNumber minVisY = new MesquiteNumber();
+	public void drawAxes(Graphics g, boolean printing, int chartWidth, int chartHeight, MesquiteChart chart){
+		//currently does not pay attention to whether printing
+		MesquiteNumber tickNumber = new MesquiteNumber();
+		MesquiteNumber tickIncrementNumber = new MesquiteNumber();
+		MesquiteNumber firstTick = new MesquiteNumber();
+		g.setColor(chart.getBackground());
+		g.fillRect(0,0,chartWidth, chartHeight);
+		int fieldWidth = chart.getFieldWidth();
+		int fieldHeight = chart.getFieldHeight();
+		int margin = chart.getMargin();
+		g.setColor(Color.black);
+		if (chart.xAxisName!=null && chart.getXAxisEdge()>0) {
+			if (xAxisWriter==null)
+				xAxisWriter = new StringInABox(chart.xAxisName, g.getFont(), chartWidth - chart.getXAxisEdge() - 16);
+			else {
+				xAxisWriter.setWidth(chartWidth - chart.getXAxisEdge() - 16);
+				xAxisWriter.setString(chart.xAxisName);
+				xAxisWriter.setFont(g.getFont());
+			}
+			xAxisWriter.draw(g,chart.getXAxisEdge()+30, chartHeight-chart.getYAxisEdge() +36); //had been 48
+		}
+		int leftMost = chart.getXAxisEdge()-20;
+		if (chartDone){
+			Font font = g.getFont();
+			FontMetrics fontMet = g.getFontMetrics(font);
+			int textOffset = (fontMet.getMaxAscent() + fontMet.getMaxDescent())/2;
+			if (chart.getYAxisEdge()>0) {
+				
+				// scale ======== on X axis
+				chart.putVisMinimumX(minVisX);
+				chart.putVisMinimumY(minVisY);
+				double min = chart.getAxisMinimumX().getDoubleValue(); //should be able to find out leftmost visible
+				double max = chart.getAxisMaximumX().getDoubleValue();
+				
+				firstTick.setToFirstScaleMark(chart.getAxisMinimumX(), chart.getAxisMaximumX(), minTicks);
+				tickNumber.setValue(firstTick);
+				tickIncrementNumber.setToScaleIncrement(chart.getAxisMinimumX(), chart.getAxisMaximumX(), minTicks);
+				//g.setColor(gridColor);
+				int i =1;
+				
+				if (!tickIncrementNumber.isNegative() && (max-tickNumber.getDoubleValue())/tickIncrementNumber.getDoubleValue()<maxTicks) 
+					for (int count = 0; tickNumber.getDoubleValue()<max; count++) {
+						i++;
+						int x = xToPixel(tickNumber.getDoubleValue(),chart) + chart.getXAxisEdge() - chart.scrollXOffset();
+						if ((x>=chart.getXAxisEdge() && tickNumber.getDoubleValue()>= minVisX.getDoubleValue())){
+							String t =tickNumber.toString(Math.abs(max-min));
+							//g.setColor(axisColor);
+							chart.textRotator.drawRotatedText(t, i, g, chart, x - textOffset, chartHeight-chart.getYAxisEdge()+32);
+						}
+						tickNumber.setValue(tickIncrementNumber);
+						tickNumber.multiplyBy(count);
+						tickNumber.add(firstTick);
+					}
+			}
+			if (chart.getXAxisEdge()>0) {
+				// scale ======== on Y axis
+				double min = minY.getDoubleValue();
+				double max = maxY.getDoubleValue();
+				tickNumber.setToFirstScaleMark(minY, maxY, minTicks);
+				tickIncrementNumber.setToScaleIncrement(minY, maxY, minTicks);
+				//g.setColor(gridColor);
+				int hPos = 0;
+				if (!tickIncrementNumber.isNegative() && (max-tickNumber.getDoubleValue())/tickIncrementNumber.getDoubleValue()<maxTicks) {
+					for (; tickNumber.getDoubleValue()<max; tickNumber.add(tickIncrementNumber)) {
+						int y = yToPixel(tickNumber.getDoubleValue(), chart) - chart.scrollYOffset();
+						if ((y<chart.getChartHeight()-chart.getYAxisEdge() && tickNumber.getDoubleValue()> minVisY.getDoubleValue())){
+							String t =tickNumber.toString(Math.abs(max-min));
+							hPos = chart.getXAxisEdge() - 8 - fontMet.stringWidth(t);
+							leftMost = MesquiteInteger.minimum(hPos, leftMost);
+							g.drawString(t, hPos, y + textOffset);
+						}
+					}
+				}
+			}
+		}
+			
+		g.setColor(Color.black);
+		if (chart.yAxisName!=null && chart.yAxisWriter!=null && chart.getYAxisEdge()>0 && chart.textRotator!=null && chartDone) {
+			chart.yAxisWriter.setWidth( chartHeight-chart.getYAxisEdge()-20);
+			chart.yAxisWriter.setFont(g.getFont());
+			chart.yAxisWriter.setString(getYAxisName(chart));
+			chart.yAxisWriter.draw(g, leftMost - chart.yAxisWriter.getHeight()-16, chartHeight-chart.getYAxisEdge()-24, 0,chart.getBounds().width, chart, false);
+		}
+
+	}
+   	public boolean getShowPercent() {
+   		return true;
+   	}
+   	public void setDrawWarningSuppressed(boolean drawWarningSuppressed) {
+   		this.drawWarningSuppressed = drawWarningSuppressed;
+   	}
+   	public boolean getDrawWarningSuppressed() {
+   		return drawWarningSuppressed;
+   	}
+   	public void setSuspendDrawing(boolean suspendDrawing) {
+   		this.suspendDrawing = suspendDrawing;
+   	}
+   	public boolean getSuspendDrawing() {
+   		return suspendDrawing;
+   	}
+   	public void setSuspendChartCalculations(boolean suspendChartCalculations) {
+   		this.suspendChartCalculations = suspendChartCalculations;
+   	}
+   	public boolean getSuspendChartCalculations() {
+   		return suspendChartCalculations;
+   	}
+	/* ----------------------------------*/
+	public void pixelToY(int y, MesquiteChart chart, MesquiteNumber yValue){
+		if (yValue==null)
+			return;
+		yValue.findWithinBounds(minY, maxY, chart.getFieldHeight()-y, chart.getFieldHeight());
+	}
+	/* ----------------------------------*/
+	public int yToPixel(double y, MesquiteChart chart){
+		tempNum.setValue(y);
+		int fieldHeight =chart.getFieldHeight();
+		int margin =chart.getMargin();
+		return fieldHeight-margin-tempNum.setWithinBounds(minY, maxY, fieldHeight- 2*margin) - chart.getYPixelBase();
+	}
+	/* ----------------------------------*/
+	public void pixelToX(int x,  MesquiteChart chart, MesquiteNumber xValue){
+		if (xValue==null)
+			return;
+		int fieldWidth =chart.getFieldWidth();
+		int margin =chart.getMargin();
+		
+		xValue.findWithinBounds(minX, maxX, x- margin + chart.getXPixelBase(), fieldWidth - 2*margin-markerWidth);
+		//xValue.findWithinBounds(minX, maxX, x, chart.getFieldWidth());
+	}
+	/* ----------------------------------*/
+	public int xToPixel(double x,  MesquiteChart chart){
+		tempNum.setValue(x);
+		int fieldWidth =chart.getFieldWidth();
+		int margin =chart.getMargin();
+		return   margin+tempNum.setWithinBounds(minX, maxX, fieldWidth - 2*margin-markerWidth) - chart.getXPixelBase();
+	}
+	
+	/* ----------------------------------*/
+	public boolean isNative(){
+		return true;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber leftmostXDrawn(MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber rightmostXDrawn(MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber topmostYDrawn(MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber bottommostYDrawn(MesquiteChart chart){  
+		return null; 
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber rightmostXOfInterval(MesquiteNumber x, MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber leftmostXOfInterval(MesquiteNumber x, MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber bottommostYOfInterval(MesquiteNumber y, MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public MesquiteNumber topmostYOfInterval(MesquiteNumber y, MesquiteChart chart){
+		return null;
+	}
+	/* ----------------------------------*/
+	public boolean moreThanOneValueInInterval(MesquiteNumber x, MesquiteChart chart) {
+		return false;
+	}
+	/* ----------------------------------*/
+	public boolean showingClumpSums(){
+		return false;
+	}
+	/* ----------------------------------*/
+	public String getYAxisNameSuffix(){
+		return "";
+	}
+	/* ----------------------------------*/
+	public String getYAxisName(MesquiteChart chart){
+		if (chart==null)
+			return "";
+		else
+			return chart.yAxisName;
+	}
+	public void drawBackground(Graphics g, MesquiteChart chart){
+	}
+	public void drawGrid(Graphics g, MesquiteChart chart){
+		if (!minX.isCombinable())
+			minX.setValue(chart.getAxisMinimumX());
+		if (!maxX.isCombinable())
+			maxX.setValue(chart.getAxisMaximumX());
+		if (!minY.isCombinable())
+			minY.setValue(chart.getAxisMinimumY());
+		if (!maxY.isCombinable()) {
+			maxY.setValue(chart.getAxisMaximumY());
+		}
+		drawBackground(g, chart);
+		int fieldWidth = chart.getFieldWidth();
+		int fieldHeight = chart.getFieldHeight();
+		int margin = chart.getMargin();
+		double min = minX.getDoubleValue();
+		double max = maxX.getDoubleValue();
+		g.setColor(gridColor);
+		
+		/**/
+		double firstTick = MesquiteDouble.firstScaleMark(max-min, min, minTicks);
+		double tickIncrement = MesquiteDouble.scaleIncrement(max-min, min, minTicks);
+		if (tickIncrement>0 && (max-firstTick)/tickIncrement<maxTicks) {
+			double tick = firstTick;
+			for (int count = 0;  tick<max; count++) {
+			//for (double tick=firstTick; tick<max; tick += tickIncrement)
+				drawXLine(tick, g, fieldHeight, chart);
+				tick = tickIncrement*count + firstTick;
+			}
+		}
+		min = minY.getDoubleValue();
+		max = maxY.getDoubleValue();
+		firstTick = MesquiteDouble.firstScaleMark(max-min, min, minTicks);
+		tickIncrement = MesquiteDouble.scaleIncrement(max-min, min, minTicks);
+		if (tickIncrement>0 && (max-firstTick)/tickIncrement<maxTicks)
+			for (double tick=firstTick; tick<max; tick += tickIncrement)
+				drawYLine(tick, g, fieldWidth, chart);
+	}
+	/* ----------------------------------*/
+	protected void drawXLine(double x, Graphics g, int fieldHeight, MesquiteChart chart){
+		int lineX = xToPixel(x, chart);
+		g.drawLine(lineX, 0 , lineX, fieldHeight);
+	}
+	/* ----------------------------------*/
+	protected void drawYLine(double y, Graphics g, int fieldWidth, MesquiteChart chart){
+		int lineY =yToPixel(y, chart);
+		g.drawLine(0, lineY,fieldWidth, lineY);
+	}
+	public abstract void open(MesquiteChart chart);
+	public void close(){}
+	public void mouseMoveInField(int modifiers, int x, int y, MesquiteChart chart, ChartTool tool) {}
+	public void mouseDownInField(int modifiers, int x, int y, MesquiteChart chart, ChartTool tool) {}
+	public void mouseDragInField(int modifiers, int x, int y, MesquiteChart chart, ChartTool tool) {}
+	public void mouseUpInField(int modifiers, int x, int y, MesquiteChart chart, ChartTool tool) {}
+	public void showQuickMessage(MesquiteChart chart, int whichPoint, int x, int y, String message){}//TODO: should be abstract to force inclusion!
+	public void hideQuickMessage(MesquiteChart chart){}
+}
+
diff --git a/Source/mesquite/lib/ChecklistDialog.java b/Source/mesquite/lib/ChecklistDialog.java
new file mode 100644
index 0000000..ceac73b
--- /dev/null
+++ b/Source/mesquite/lib/ChecklistDialog.java
@@ -0,0 +1,265 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+public class ChecklistDialog extends MesquiteDialog implements ActionListener{
+	ChecklistScrollPane pane;
+	Panel boxPanel;
+	MesquiteInteger selected;
+	IntegerArray indicesSelected = new IntegerArray(0);
+	String[] strings = null;
+	Listable[] listables = null;
+	TextArea explanation = null;
+	Button cancel,ok;
+	int numItems = 0;
+	ChecklistBox[] boxes;
+	
+	public ChecklistDialog (MesquiteWindow parent, String title, String message, Object names, boolean doShow) {
+		super(parent, title);
+		setLayout(new GridBagLayout());
+		if (names instanceof Listable[]) {
+			listables = (Listable[])names;
+			numItems = listables.length;
+		}
+		else if (names instanceof String[]) {
+			strings = (String[])names;
+			numItems = strings.length;
+		}
+	//	this.selected = selected;
+		Font f = new Font ("Dialog", Font.PLAIN, 12);
+		TextArea lab = new TextArea (message,3, 6, TextArea.SCROLLBARS_NONE);
+		addComponent(this, lab, 0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.BOTH, GridBagConstraints.CENTER);
+		lab.setEditable(false);
+		
+		pane = new ChecklistScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
+		boxPanel = new Panel();
+		boxPanel.setLayout(new GridLayout(numItems, 1));
+		addComponent(this, pane, 0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.BOTH, GridBagConstraints.CENTER);
+		//pane.setBackground(Color.red);
+		//boxPanel.setBackground(Color.blue);
+		if (anyDocumentables(listables)){
+			explanation = new TextArea ("",3, 6, TextArea.SCROLLBARS_VERTICAL_ONLY);
+			explanation.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+
+			addComponent(this, explanation, 0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.BOTH, GridBagConstraints.CENTER);
+		}
+		Panel buttons = new Panel();
+		Button sho=null;
+		buttons.add("West", cancel = new Button("Cancel"));
+		if (doShow)
+			buttons.add("Center", sho = new Button("Show")); //NOTE about a kludge: the name of this button needs to remain "show".  See buttonHit in ListDialog
+		buttons.add("East", ok = new Button("OK"));
+		//cancel.setBackground(Color.white);
+		if (doShow)
+			sho.setBackground(Color.white);
+		//ok.setBackground(Color.white);
+		cancel.setFont(f);
+		ok.setFont(f);
+		if (doShow)
+			sho.setFont(f);
+		lab.setFont(f);
+		
+		
+		pane.addChecks(boxPanel);
+		pane.setVisible(true);
+		boxPanel.setVisible(true);
+		boxes = new ChecklistBox[numItems];
+		if (listables!=null){
+			numItems = listables.length;
+			//add checkbox
+			for (int i=0; i<listables.length; i++) {
+				if (listables[i]!=null){
+					String name = null;
+					if (listables[i] instanceof SpecialListName && ((SpecialListName)listables[i]).getListName()!=null)
+						name = ((SpecialListName)listables[i]).getListName();
+					else if (listables[i].getName()!=null)
+						name = listables[i].getName();
+					boxes[i] = new ChecklistBox(name, this);
+					boxPanel.add(boxes[i]);
+					boxes[i].setVisible(true);
+				}
+			}
+		}
+		else if (strings!=null){
+			for (int i=0; i<strings.length; i++)
+				if (strings[i]!=null) {
+					boxes[i] = new ChecklistBox(strings[i], this);
+					boxPanel.add(boxes[i]);
+					boxes[i].setVisible(true);
+				}
+		}
+		
+		addComponent(this, buttons, 0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.BOTH, GridBagConstraints.CENTER);
+		setSize(460, 440);
+		setDefaultButton("OK");
+		MesquiteWindow.centerWindow(this);
+	}
+	private boolean anyDocumentables(Listable[] L){
+		if (L==null)
+			return false;
+		for (int i=0; i<L.length; i++)
+			if (L[i] instanceof Explainable)
+				return true;
+		return false;
+	}
+	private int getIndex(ChecklistBox c){
+		for (int i=0; i<numItems; i++)
+			if (boxes[i] == c)
+				return i;
+		return -1;
+	}
+	private int numSelected(){
+		int count = 0;
+		for (int i=0; i<numItems; i++)
+			if (boxes[i].getState())
+				count++;
+		return count;
+	}
+	private int[] getSelectedIndexes(){
+		int[] s = new int[numSelected()];
+		int count = 0;
+		for (int i=0; i<numItems; i++)
+			if (boxes[i].getState()) {
+				s[count++] = i;
+			}
+		return s;
+	}
+	
+	private void setSelected(boolean[] selected){
+		if (selected == null)
+			return;
+		for (int i=0; i<numItems && i<selected.length; i++)
+			boxes[i].setState(selected[i]);
+	}
+	private void setStyle(Component c, int style){
+		if (c==null)
+			return;
+		Font fontToSet = new Font ("Dialog", style, 12);
+ 		if (fontToSet!= null)
+ 			c.setFont(fontToSet);
+	}
+	private void setHighlighted(boolean[] highlighted){
+		if (highlighted == null)
+			return;
+		for (int i=0; i<numItems && i<highlighted.length; i++) {
+			if (highlighted[i])
+				setStyle(boxes[i], Font.BOLD);
+			else
+				setStyle(boxes[i], Font.PLAIN);
+		}
+	}
+	private void showExplanation(int selected){
+		if (selected <0) {
+			if (explanation !=null) {
+				explanation.setText("");
+				return;
+			}
+		}
+		else if (listables !=null && selected < listables.length && listables[selected] instanceof Explainable) {
+			if (explanation !=null) {
+				String exp = ((Explainable)listables[selected]).getExplanation();
+				if (exp == null)
+					exp = "";
+				explanation.setText(exp);
+				return;
+			}
+		}
+		if (explanation !=null) 
+			explanation.setText("");
+	}
+	public void boxSelected(ChecklistBox c){
+		if (listables==null)
+			return;
+		int whichBox = getIndex(c);
+		if (whichBox>=0)
+			showExplanation(whichBox);
+	}
+	public void actionPerformed(ActionEvent e){
+		if (defaultButtonString!=null) {
+			buttonHit(defaultButtonString, null);
+			dispose();
+		}
+	}
+	public static Listable[] queryListMultiple(MesquiteWindow parent, String title, String message, ListableVector vector, boolean[] selected) {
+		return queryListMultiple(parent, title, message, null, true, vector, selected);
+	}
+	public static Listable[] queryListMultiple(MesquiteWindow parent, String title, String message, String okButton, boolean hasDefault, ListableVector vector, boolean[] selected) {
+		if (vector==null) 
+			return null;
+		Listable[] names = vector.getListables();
+		if (names==null)
+			return null;
+		ChecklistDialog id = new ChecklistDialog(parent, title, message, names, false);
+		if (okButton!=null)
+			id.ok.setLabel(okButton);
+		if (hasDefault)
+			id.setDefaultButton(id.ok.getLabel());
+		else
+			id.setDefaultButton(null);
+		id.setSelected(selected);
+		id.setHighlighted(selected);
+		id.setVisible(true);
+		IntegerArray result = id.indicesSelected;
+		if (result==null || result.getSize()==0) {
+			id.dispose();
+			return null;
+		}
+		Listable[] L = new Listable[result.getSize()];
+		for (int i=0; i<result.getSize(); i++)
+			L[i] = (Listable)vector.elementAt(result.getValue(i));
+		id.dispose();
+		return L;
+	}
+	public void buttonHit(String buttonLabel, Button button) {
+		if (buttonLabel.equalsIgnoreCase(ok.getLabel())){
+			indicesSelected.setValues(getSelectedIndexes());
+		}
+		else {
+			indicesSelected.setValues(null);
+		}
+	}
+}
+/* ======================================================================== */
+class ChecklistScrollPane extends ScrollPane{
+	public ChecklistScrollPane () {
+		super();
+	}
+	public ChecklistScrollPane (int scrollPolicy) {
+		super(scrollPolicy);
+	}
+	public void addChecks(Component c){
+		addImpl(c, null, 0);
+	}
+}
+
+class ChecklistBox extends Checkbox implements ItemListener {
+	ChecklistDialog dlog;
+	public ChecklistBox(String name, ChecklistDialog dlog){
+		super(name);
+		this.dlog = dlog;
+		addItemListener(this);
+	}
+	public void itemStateChanged(ItemEvent e){
+		//if (e.getStateChange() == ItemEvent.SELECTED){
+				dlog.boxSelected(this);
+		//}
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/CircleSymbol.java b/Source/mesquite/lib/CircleSymbol.java
new file mode 100644
index 0000000..9f773ec
--- /dev/null
+++ b/Source/mesquite/lib/CircleSymbol.java
@@ -0,0 +1,112 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CircleSymbol extends FillableMesquiteSymbol  {
+	public CircleSymbol() {
+	}
+	public CircleSymbol(int size) {
+		super();
+		setSize(size);
+	}
+	/**gets the name of the symbol*/
+	public String getName(){
+		return "Circle";
+	}
+	/*.................................................................................................................*/
+	public  MesquiteSymbol  cloneMethod(){
+		CircleSymbol newSymbol = new CircleSymbol();
+		newSymbol.setToCloned(this);
+		return  newSymbol;
+	}
+	/*.................................................................................................................*/
+	public void addDialogElements(ExtensibleDialog dialog, boolean includeSize){
+		super.addDialogElements(dialog,includeSize);
+	}
+	/*.................................................................................................................*/
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2, int bound){
+		int symSize = size;
+		if (size>bound && bound>0)
+			symSize = bound;
+		Rectangle rect = new Rectangle(symbolX-symSize,symbolY-symSize, symSize+symSize,symSize+symSize);
+		return rect.intersects(new Rectangle(x1,y1,x2,y2));
+	}
+	/*.................................................................................................................*/
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2, int maxWidth, int maxHeight){
+		int symSize = size;
+		if (size>maxWidth && maxWidth>0)
+			symSize = maxWidth;
+		if (size>maxHeight && maxHeight>0)
+			symSize = maxHeight;
+		Rectangle rect = new Rectangle(symbolX-symSize,symbolY-symSize, symSize+symSize,symSize+symSize);
+		return rect.intersects(new Rectangle(x1,y1,x2-x1,y2-y1));
+	}
+	/*.................................................................................................................*/
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y, int bound){
+		int symSize = size;
+		if (size>bound && bound>0)
+			symSize = bound;
+		Rectangle rect = new Rectangle(symbolX-symSize,symbolY-symSize, symSize+symSize,symSize+symSize);
+		return rect.contains(x,y);
+	}
+	/*.................................................................................................................*/
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y, int maxWidth, int maxHeight){
+		int symSize = size;
+		if (size>maxWidth && maxWidth>0)
+			symSize = maxWidth;
+		if (size>maxHeight && maxHeight>0)
+			symSize = maxHeight;
+		Rectangle rect = new Rectangle(symbolX-symSize,symbolY-symSize, symSize+symSize,symSize+symSize);
+		return rect.contains(x,y);
+	}
+	/*.................................................................................................................*/
+	public void fillSymbol(Graphics g, int x, int y,  int maxWidth, int maxHeight){
+		int symSize = size;
+		if (size>maxWidth && maxWidth>0)
+			symSize = maxWidth;
+		if (size>maxHeight && maxHeight>0)
+			symSize = maxHeight;
+		g.fillOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+	}
+	/*.................................................................................................................*/
+	public void drawSymbol(Graphics g, int x, int y,  int maxWidth, int maxHeight, boolean fillBlack){
+		int symSize = size;
+		if (size>maxWidth && maxWidth>0)
+			symSize = maxWidth;
+		if (size>maxHeight && maxHeight>0)
+			symSize = maxHeight;
+		if (fillBlack) {
+			g.setColor(Color.black);
+			g.fillOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+		}
+		else if (getFill()) {
+			g.setColor(fillColor);
+			g.fillOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+		}
+		g.setColor(color);
+		g.drawOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+	}
+	/*.................................................................................................................*/
+	public static void drawBlackCircle(Graphics g, int x, int y, int size){
+		int symSize = size;
+		g.setColor(Color.black);
+		g.fillOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+		g.drawOval(x-symSize,y-symSize, symSize+symSize,symSize+symSize);
+	}
+}
+
diff --git a/Source/mesquite/lib/Clade.java b/Source/mesquite/lib/Clade.java
new file mode 100644
index 0000000..c7fc20e
--- /dev/null
+++ b/Source/mesquite/lib/Clade.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+/** A clade.  This doesn't mean a set of terminal taxa in tree so much as simply a named entity.  
+Used by modules to tie information such as hypertext links and images to labels at nodes in tree.*/
+public class Clade {
+	private String name;
+	private Image illustration;
+	private String illustrationPath;
+	public static int totalCreated = 0;
+	private String link;
+	//need footnotes etc.
+	
+	public Clade(String name){
+		this.name = name;
+		totalCreated++;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setLink(String link) {
+		this.link = link;
+	}
+	public String getLink() {
+		return link;
+	}
+	public void setIllustration(Image illustration, String path) {
+		this.illustration = illustration;
+		this.illustrationPath = path;
+	}
+	public String getIllustrationPath() {
+		return illustrationPath;
+	}
+	public Image getIllustration() {
+		return illustration;
+	}
+}
+
diff --git a/Source/mesquite/lib/Clades.java b/Source/mesquite/lib/Clades.java
new file mode 100644
index 0000000..680a891
--- /dev/null
+++ b/Source/mesquite/lib/Clades.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+import java.util.*;
+
+/* ======================================================================== */
+/** A set of clades.  This doesn't mean a set of actual clades in tree so much as simply a series of named entities.  
+Used by modules to tie information such as hypertext links and images to labels at nodes in tree.*/
+public class Clades {
+	private Vector clades;
+	public static int totalCreated = 0;
+	
+	public Clades(){
+		clades = new Vector();
+		totalCreated++;
+	}
+	public Clade findClade(String name){
+		if (StringUtil.blank(name))
+			return null;
+		Enumeration e = clades.elements();
+		while (e.hasMoreElements()) {
+			Clade c = (Clade)e.nextElement();
+			if (name.equalsIgnoreCase(c.getName()))
+				return c;
+	 	}
+		return null;
+	}
+	public Clade getClade(int ic){
+		if (ic<0 || ic>=getNumClades())
+			return null;
+		return (Clade)clades.elementAt(ic);
+	}
+	public int getNumClades(){
+		return clades.size();
+	}
+	public Clade addClade(String name) {
+		Clade c = findClade(name);
+		if (c==null) {
+			c = new Clade(name);
+			clades.addElement(c);
+		}
+		return c;
+	}
+	public void removeClade(String name) {
+		Clade clade =findClade(name);
+		if (clade!=null) {
+			clades.removeElement(clade);
+		}
+	}
+	public void setLink(String name, String link) {
+		Clade clade = findClade(name);
+		if (clade!=null)
+			clade.setLink(link);
+	}
+	public String getLink(String name) {
+		Clade clade = findClade(name);
+		if (clade!=null)
+			return clade.getLink();
+		return null;
+	}
+	public void setIllustration(String name, Image illustration, String path) {
+		Clade clade = findClade(name);
+		if (clade!=null)
+			clade.setIllustration(illustration, path);
+	}
+	public String getIllustrationPath(String name) {
+		Clade clade = findClade(name);
+		if (clade!=null)
+			return clade.getIllustrationPath();
+		return null;
+	}
+	public Image getIllustration(String name) {
+		Clade clade = findClade(name);
+		if (clade!=null)
+			return clade.getIllustration();
+		return null;
+	}
+}
+
diff --git a/Source/mesquite/lib/ClassVector.java b/Source/mesquite/lib/ClassVector.java
new file mode 100644
index 0000000..c5f4f62
--- /dev/null
+++ b/Source/mesquite/lib/ClassVector.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+
+/* ======================================================================== */
+/*To keep track of classes used*/
+public class ClassVector extends ListableVector {
+	public ClassVector(){
+		super();
+	}
+	public void record(Class c){
+		if (c==null)
+			return;
+		CRecord cr = (CRecord)elementWithName(c.getName());
+		if (cr == null)
+			addElement(new CRecord(c), false);
+		else
+			cr.increment();
+	}
+	public void recordWithTime(Class c){
+		if (c==null)
+			return;
+		CRecord cr = (CRecord)elementWithName(c.getName());
+		if (cr == null)
+			addElement(cr = new CRecord(c), false);
+		else
+			cr.increment();
+		cr.startTime();
+	}
+	public void stopTime(Class c){
+		if (c==null)
+			return;
+		CRecord cr = (CRecord)elementWithName(c.getName());
+		if (cr == null)
+			return;
+		cr.stopTime();
+	}
+	public String recordsToString(){
+		Listable[] array = getElementArray(); //firstSort
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && ((CRecord)array[j]).count>((CRecord)array[j+1]).count; j--) {
+				Listable temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		String s = "";
+		for (int i=0; i<array.length; i++){
+			CRecord cr = (CRecord)array[i];
+			s += "   " + cr + "\n";
+		}
+		return s;
+	}
+}
+
+class CRecord implements Listable{
+	long count;
+	long times = 0;
+	String name;
+	MesquiteTimer timer;
+	public CRecord(Class c) {
+		name = c.getName();
+		count = 1;
+	}
+	public void increment(){	
+		count++;
+	}
+	public void startTime(){
+		if (timer == null)
+			timer = new MesquiteTimer();
+		times++;
+		timer.start();
+	}
+	public void stopTime(){
+		if (timer == null)
+			timer = new MesquiteTimer();
+		times--;
+		timer.end();
+	}
+	public String toString(){
+		if (timer == null)
+			return name + "  " + count;
+		else if (times !=0)
+			return name + "  " + count + " (time: " + timer.getAccumulatedTime() + " ERROR: times = " + times + ")";
+		else
+			return name + "  " + count + " (time: " + timer.getAccumulatedTime() + ")";
+	}
+	public String getName(){
+		return name;
+	}
+}
+
diff --git a/Source/mesquite/lib/CleanUpJob.java b/Source/mesquite/lib/CleanUpJob.java
new file mode 100644
index 0000000..e037fd8
--- /dev/null
+++ b/Source/mesquite/lib/CleanUpJob.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+public interface CleanUpJob {
+	public void cleanUp();
+
+}
+
+
diff --git a/Source/mesquite/lib/ClockPanel.java b/Source/mesquite/lib/ClockPanel.java
new file mode 100644
index 0000000..51a8951
--- /dev/null
+++ b/Source/mesquite/lib/ClockPanel.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/** A little panel placed within a container to indicate an ongoing calculations.  Serves like a 
+thermometer window, but embedded in relevant container since there may be several ongoing
+at once.*/
+public class ClockPanel extends Panel {
+	int current=0;
+	int total = 0;
+	public void setTime(int total, int current) {
+		this.current = current;
+		this.total = total;
+		if (total<=0)
+			total = 1;
+		if (current> total)
+			current = total;
+		Graphics g = getGraphics();
+		if (g!=null)  {
+			paint(g);
+			g.dispose();
+		}
+		/*{
+			if (current == 0) {
+				g.setColor(Color.white);
+				g.fillOval(0,0, getBounds().width, getBounds().height);
+			}
+			g.setColor(Color.black);
+			g.drawOval(0,0, getBounds().width, getBounds().height);
+			g.drawOval(1,1, getBounds().width-2, getBounds().height-2);
+			g.fillArc(4,4, getBounds().width-8, getBounds().height-8, 90, -current * 360 /total);
+		}*/
+	}
+	public void paint (Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		g.setColor(Color.white);
+		g.fillOval(0,0, getBounds().width, getBounds().height);
+		g.setColor(Color.black);
+		g.drawOval(0,0, getBounds().width, getBounds().height);
+		g.drawOval(1,1, getBounds().width-2, getBounds().height-2);
+		if (total!=0)
+			g.fillArc(4,4, getBounds().width-8, getBounds().height-8, 90, -current * 360 /total);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/lib/ClosablePanel.java b/Source/mesquite/lib/ClosablePanel.java
new file mode 100644
index 0000000..610b670
--- /dev/null
+++ b/Source/mesquite/lib/ClosablePanel.java
@@ -0,0 +1,242 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ======================================================================== */
+public class ClosablePanel extends MousePanel {
+	public static final int MINHEIGHT = 20;
+	protected int height = MINHEIGHT;
+	protected int currentHeight = 60;
+	private boolean open = false;
+	private boolean wholeOpen = false;
+	private boolean showTriangle = false;
+	protected ClosablePanelContainer container;
+	protected String title = "";
+	protected Color bgTopColor = Color.white;
+	protected Color bgBottomColor = ColorDistribution.veryVeryVeryLightGray;
+	protected Color barColor = ColorDistribution.veryLightGray;
+	protected Color textColor = Color.darkGray;
+	protected boolean hover = false;  //if true, then mouse is hovering over it
+	/*
+	 * 	Color bgTopColor = Color.lightGray;
+	Color bgBottomColor = ColorDistribution.veryVeryLightGray;
+	Color barColor = Color.darkGray;
+	Color textColor = Color.black;
+	 */
+
+	public ClosablePanel(ClosablePanelContainer container, String title){
+		super();
+		this.container = container;
+		this.title = title;
+		if (getBold())
+			setFont(new Font("SansSerif", Font.BOLD, getFontSize()));
+		else
+			setFont(new Font("SansSerif", Font.PLAIN, getFontSize()));
+		setBackground(bgBottomColor);
+	}
+	public void setContainer(ClosablePanelContainer container){
+		this.container = container;
+	}
+	protected int getFontSize(){
+		return 10;
+	}
+	public boolean getBold(){
+		return false;
+	}
+	public void setTitle(String title){
+		if (title == null)
+			title = "";
+		this.title = title;
+	}
+	public String getTitle(){
+		return title;
+	}
+	public void setWholeOpen(boolean b){
+		wholeOpen = b;
+	}
+	public void setOpen(boolean b){
+		open = b;
+		if (container != null)
+			container.requestHeightChange(this);
+	}
+	public boolean isOpen(){
+		return open;
+	}
+	public void setShowTriangle(boolean b){
+		showTriangle = b;
+	}
+	public boolean getShowTriangle(){
+		return showTriangle;
+	}
+	public void setColors(Color bgTopColor, Color bgBottomColor, Color barColor, Color textColor){
+		this.bgTopColor = bgTopColor;
+		this.bgBottomColor = bgBottomColor;
+		setBackground(bgBottomColor);
+		this.barColor = barColor;
+		this.textColor = textColor;
+	}
+	public Color getBgTopColor(){
+		return bgTopColor;
+	}
+	public Color getBgBottomColor(){
+		return bgBottomColor;
+	}
+	public Color getBarColor(){
+		return barColor;
+	}
+	public Color getTextColor(){
+		return textColor;
+	}
+	public void setBgTopColor(Color c){
+		bgTopColor= c;
+	}
+	public void setBgBottomColor(Color c){
+		bgBottomColor= c;
+	}
+	public void setBarColor(Color c){
+		barColor= c;
+	}
+	public void setTextColor(Color c){
+		textColor= c;
+	}
+	int tightness = 8;
+	public void setTightness(int tightness){
+		this.tightness = tightness;
+	}
+	public Image getIcon(){ //for small 16 pixel icon at left of main bar
+		return null;
+	}
+	protected int triangleOffset = 0;
+	public void paint(Graphics g){
+		g.setColor(bgTopColor);
+		g.fillRect(0,0,getWidth(), MINHEIGHT);
+		g.setColor(barColor);
+		g.fillRect(0,0,getWidth(), 4);
+		triangleOffset = 0;
+		Image im = getIcon();
+		if (im != null){
+			triangleOffset = 16;
+			g.drawImage(im, 0, 4, this);
+		}
+		if (showTriangle){
+			if (open)
+				g.drawImage(InfoBar.triangleImageDown, 0 + triangleOffset, 0, this);
+			else
+				g.drawImage(InfoBar.triangleImage, -4 + triangleOffset, 2, this);
+			triangleOffset += 10;
+		}
+		g.setColor(textColor);
+		if (getTitle() != null){
+			g.drawString(getTitle(), tightness + triangleOffset, MINHEIGHT-4);
+		}
+		if (hover){
+			g.setColor(Color.lightGray);
+			g.drawRect(0, 4, getWidth()-2, MINHEIGHT-6);
+		}
+
+	}
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		ClosablePanel prev = container.getPrecedingPanel(this);
+		if (prev != null && prev.userExpandable() && prev.getTouchExpand() != MesquiteInteger.unassigned){
+			prev.incrementExpectedCurrentHeight(y-prev.getTouchExpand());
+			prev.setTouchExpand(MesquiteInteger.unassigned);
+			container.requestHeightChange(prev);
+		}
+		else if (showTriangle && (wholeOpen || (x< triangleOffset + 8 && x >= triangleOffset - 16)) && y<MINHEIGHT){
+			setOpen(!open);
+			repaint();
+		}
+	}
+	int touchExpand = MesquiteInteger.unassigned;
+	public int getTouchExpand(){
+		return touchExpand;
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		super.mouseDown(modifiers, clickCount, when, x, y, tool);
+
+		ClosablePanel prev = container.getPrecedingPanel(this);
+		if (prev != null && prev.userExpandable()){
+			if (y < 4){
+				prev.setTouchExpand( y);
+				return;
+			}
+			else 
+				prev.setTouchExpand(MesquiteInteger.unassigned);
+
+		}
+	}
+	Cursor rC = new Cursor(Cursor.S_RESIZE_CURSOR);
+	Cursor dC = new Cursor(Cursor.DEFAULT_CURSOR);
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseEntered(modifiers, x, y, tool);
+		hover = true;
+		ClosablePanel prev = container.getPrecedingPanel(this);
+		if (prev != null && prev.userExpandable()){
+			if (y < 4){
+				setCursor(rC);
+			}
+			else 
+				setCursor(dC);
+
+		}
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseMoved(modifiers, x, y, tool);
+		hover = true;
+		ClosablePanel prev = container.getPrecedingPanel(this);
+		if (prev != null && prev.userExpandable()){
+			if (y < 4){
+				setCursor(rC);
+			}
+			else 
+				setCursor(dC);
+
+		}
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseExited(modifiers, x, y, tool);
+		hover = false;
+		ClosablePanel prev = container.getPrecedingPanel(this);
+		if (prev != null && prev.userExpandable()){
+
+			setCursor(dC);
+
+		}
+	}
+	public void setTouchExpand(int c){
+		touchExpand = c;
+	}
+	public boolean userExpandable(){
+		return false;
+	}
+	public int getExpectedCurrentHeight(){
+		return currentHeight;
+	}
+	public void incrementExpectedCurrentHeight(int c){
+		currentHeight += c;
+		if (currentHeight< MINHEIGHT)
+			currentHeight = MINHEIGHT;
+	}
+	public int getRequestedHeight(int width){
+		if (open)
+			return currentHeight;
+		else
+			return MINHEIGHT;
+	}
+}
+
diff --git a/Source/mesquite/lib/ClosablePanelContainer.java b/Source/mesquite/lib/ClosablePanelContainer.java
new file mode 100644
index 0000000..a6f2f9e
--- /dev/null
+++ b/Source/mesquite/lib/ClosablePanelContainer.java
@@ -0,0 +1,21 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+/* ======================================================================== */
+public interface ClosablePanelContainer {
+	public void requestHeightChange(ClosablePanel panel);
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel);
+}
+
diff --git a/Source/mesquite/lib/ColorDialog.java b/Source/mesquite/lib/ColorDialog.java
new file mode 100644
index 0000000..8a50743
--- /dev/null
+++ b/Source/mesquite/lib/ColorDialog.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** DOCUMENT */
+public class ColorDialog extends ExtensibleDialog implements Colorable  {
+	Color color = null;
+	//float[] initialColor = null;
+	private	Color initC = null;
+	ColorPickerPanel field;
+	Panel cPanel;
+	Panel buttons;
+	public ColorDialog(MesquiteWindow parent, String title, String message) {
+		super(parent, title);
+		field = new ColorPickerPanel (this, Color.white, 50);
+		addNewDialogPanel(field);
+
+		/*
+		
+		Font f = new Font ("Dialog", Font.PLAIN, 12);
+		add("Center", field = new ColorPickerPanel (this, Color.white, 50));
+		buttons = new Panel();
+		Button cancel = new Button("Cancel");
+		Button ok= new Button("OK");
+		cPanel = new Panel();
+		//cPanel.setBackground(Color.white);
+		buttons.add("West", cPanel);
+		buttons.add("Center", cancel);
+		buttons.add("East", ok );
+		setDefaultButton("OK");
+		//cancel.setBackground(Color.white);
+		//ok.setBackground(Color.white);
+		cancel.setFont(f);
+		ok.setFont(f);
+		add("South", buttons);
+		setSize(360, 360);
+		
+		MesquiteWindow.centerWindow(this);
+		*/
+	}
+	public void setInitialColor(Color current){
+		initC = current;
+		if (field == null)
+			return;
+	//initialColor =  Color.RGBtoHSB(current.getRed(), current.getGreen(), current.getBlue(), null);
+		field.setInitialColor(current);
+	}
+	/*
+	 * public void buttonHit(String buttonLabel, Button button) {
+		if (buttonLabel.equalsIgnoreCase("OK")) {
+				cPanel.getBackground();
+				dispose();
+		}
+		else
+			dispose();
+	}
+	*/
+	public void setColor(Color c){
+		setInitialColor(c);
+	}
+	
+	public Color getColor(){
+
+		return field.getColor();
+	}
+	public static Color queryColor(MesquiteWindow parent, String title, String message, Color current){
+		ColorDialog cd = new ColorDialog(parent, title, message);
+		cd.color = null;
+		if (current!=null) {
+			cd.setInitialColor(current);
+		}
+	 		cd.completeAndShowDialog();
+			boolean ok = cd.query()==0;
+			Color c = cd.getColor();
+			cd.dispose();
+			if (!ok)
+				return null;
+
+		return c;
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/ColorDistribution.java b/Source/mesquite/lib/ColorDistribution.java
new file mode 100644
index 0000000..6a517a8
--- /dev/null
+++ b/Source/mesquite/lib/ColorDistribution.java
@@ -0,0 +1,424 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**A class to indicate how something is to be colored, either an array of colors to be shown in equal pieces, or 
+same with distribution of weights for pie slices.  A maximum number of MAXCOLORS colors may be shown.*/
+public class ColorDistribution {
+	Color[] colors, colorsDimmed;
+	int numColors=0;
+	double[] weights;
+	boolean sequential = false;
+	static final int MAXCOLORS = 64;
+	
+	public static int numberOfRed = 5;
+	public static int numberOfGreen = 11;
+	public static int numberOfBlue = 14;
+	public static Color lightGreen, veryLightGreen, darkGreen, lightGreenYellow, lightGreenYellowish, lightBlue, veryLightBlue, violetBlue, veryLightGray, veryVeryLightGray, veryVeryVeryLightGray, lightRed, darkRed, veryVeryLightGreen;
+	public static Color darkBrown, brown, lightOrange, lightPurple, orange, straw, lightYellow, veryLightYellow, tabLineBrown, mesquiteBrown, darkMesquiteBrown, veryDarkMesquiteBrown, lightMesquiteBrown, brightMesquiteBrown;
+	public static Color uneditable;
+	public static Color unassigned;
+	public static Color inapplicable;
+	
+	public static Color [] codPosMedium, codPosDark;
+	public static Color spinDark, spinLight;
+//	public static Color[] projectLight, projectDark; //pale, light, medium, dark, project, 
+	public final static int numColorSchemes = 4;
+	public static Color burlyWood, navajoWhite, bisque, sienna, paleGoldenRod, veryPaleGoldenRod;
+	public static NameReference colorNameReference;
+	public static StringArray standardColorNames;
+	static ObjectArray standardColors, standardColorsDimmed;
+	public static double dimmingConstant = 0.3;
+	public static int NO_COLOR = 18;
+	static {
+		spinLight = new Color((float)0.3, (float)0.6, (float)0.99);
+		spinDark = new Color((float)0.1, (float)0.1, (float)0.70);
+		veryLightGray = brighter(Color.lightGray, 0.5);
+		veryVeryLightGray = brighter(veryLightGray, 0.5);
+
+		//inapplicable = veryLightGray;
+		inapplicable =  new Color((float)0.93, (float)0.90, (float)0.87);  //ColorDistribution.inapplicable;
+
+		//unassigned = new Color(230, 230, 230);
+		unassigned = new Color((float)0.92, (float)0.94, (float)0.98); //ColorDistribution.unassigned;
+		
+		veryVeryVeryLightGray = new Color((float)0.98, (float)0.98, (float)0.98);
+		darkRed = new Color((float)0.5, (float)0.2, (float)0.1);
+		lightRed = new Color((float)0.9, (float)0.48, (float)0.35);
+		darkGreen = new Color((float)0.1, (float)0.5, (float)0.2);
+		lightGreen = new Color((float)0.35, (float)0.9, (float)0.48);
+		lightGreenYellowish =  new Color((float)0.50, (float)0.99, (float)0.46);  
+		lightGreenYellow =  new Color((float)0.46, (float)0.99, (float)0.25);  
+		veryLightGreen = new Color((float)0.55, (float)0.99, (float)0.68);
+		veryVeryLightGreen = new Color((float)0.70, (float)0.99, (float)0.83);
+		lightBlue = new Color((float)0.35, (float)0.48, (float)0.9);
+		veryLightBlue = new Color((float)0.55, (float)0.68, (float)0.99);
+		lightOrange = new Color((float)1, (float)0.8, (float)0);
+		orange = new Color((float)1, (float)0.5, (float)0);
+
+		lightPurple = new Color((float)0.7, (float)0.40, (float)0.7);
+		violetBlue = new Color((float)0.55, (float)0.40, (float)0.89);
+		tabLineBrown = new Color((float)0.47, (float)0.41, (float)0.26);
+
+		darkBrown = new Color((float)0.45, (float)0.40, (float)0.15);
+		brown = new Color((float)0.65, (float)0.58, (float)0.25);
+		straw = new Color((float)0.85, (float)0.80, (float)0.38);
+		lightYellow = new Color((float)0.95, (float)0.95, (float)0.64);
+		veryLightYellow = new Color((float)0.99, (float)0.99, (float)0.78);
+		
+		burlyWood = new Color((float)0.87, (float)0.7216, (float)0.5294); //222, 184, 135  DEB887; medium  SHOULD BE 0.87, (float)0.7216, (float)0.5294
+		navajoWhite =  new Color((float)1.0, (float)0.87, (float)0.6784); //FFDEAD; light
+		bisque =  new Color((float)1.0, (float)0.894, (float)0.7686); // FFE4C4; pale
+		sienna =  new Color((float)0.6275, (float)0.3216, (float)0.1765); // A0522D; dark
+		paleGoldenRod = new Color((float)0.9333, (float)0.9398, (float)0.6667); //EEE8AA  green should be 0.9333, 0.9098, 0.66667
+		veryPaleGoldenRod = brighter(paleGoldenRod,0.5);
+
+		lightMesquiteBrown = new Color(188, 168, 122);
+		brightMesquiteBrown = new Color(228, 200, 132);
+		mesquiteBrown = new Color(108, 98, 82);
+		darkMesquiteBrown = new Color(92, 82, 70);
+		veryDarkMesquiteBrown = new Color(78, 68, 55);
+		//spinLight = new Color((float)0.6, (float)0.9, (float)0.6);
+		//spinDark = new Color((float)0.05, (float)0.5, (float)0.05);
+//		darkMesquiteBrown = new Color(82, 72, 60);
+		//mesquiteBrown = new Color(88, 78, 62);
+		//mesquiteBrown = new Color(77, 65, 47);
+
+		codPosMedium = new Color[4];
+		codPosDark = new Color[4];
+		codPosDark[0] = new Color((float)0.1, (float)0.2, (float)0.5);   // first positions, blue
+		//codPosMedium[0] = new Color((float)0.35, (float)0.48, (float)0.9);
+		codPosMedium[0] = new Color((float)0.45, (float)0.55, (float)0.94);
+		codPosDark[1] = new Color((float)0.1, (float)0.5, (float)0.2);   // second positions, green
+		codPosMedium[1] = new Color((float)0.35, (float)0.9, (float)0.48);
+		codPosDark[2] = new Color((float)0.5, (float)0.2, (float)0.1);   // third positions, red
+		codPosMedium[2] = new Color((float)0.9, (float)0.48, (float)0.35);
+		codPosDark[3] = Color.gray;       // noncoding, unspecified
+		codPosMedium[3] = Color.lightGray;
+
+
+		uneditable = lightYellow;
+		colorNameReference = NameReference.getNameReference("Color");
+		standardColors = new ObjectArray(18);
+		standardColors.setValue(0, Color.black);
+		standardColors.setValue(1, Color.darkGray);
+		standardColors.setValue(2, Color.gray);
+		standardColors.setValue(3, Color.lightGray);
+		standardColors.setValue(4, Color.white);
+		standardColors.setValue(5, Color.red); //	public static int numberOfRed = 5;
+
+		standardColors.setValue(6, Color.orange);
+		standardColors.setValue(7, Color.yellow);
+		standardColors.setValue(8, paleGoldenRod);
+		standardColors.setValue(9, burlyWood);
+		standardColors.setValue(10, sienna);
+		standardColors.setValue(11, Color.green);//	public static int numberOfGreen = 11;
+		standardColors.setValue(12, lightGreen);
+		standardColors.setValue(13, Color.cyan);
+		standardColors.setValue(14, Color.blue); // public static int numberOfBlue = 14;
+		standardColors.setValue(15, lightBlue);
+		standardColors.setValue(16, Color.magenta);
+		standardColors.setValue(17, Color.pink);
+		//DO NOT ASSIGN A COLOR TO 18
+		standardColorNames = new StringArray(18);
+		standardColorNames.setValue(0, "Black");
+		standardColorNames.setValue(1, "Dark Gray");
+		standardColorNames.setValue(2, "Gray");
+		standardColorNames.setValue(3, "Light Gray");
+		standardColorNames.setValue(4, "White");
+		standardColorNames.setValue(5, "Red");
+		standardColorNames.setValue(6, "Orange");
+		standardColorNames.setValue(7, "Yellow");
+		standardColorNames.setValue(8, "Goldenrod");
+		standardColorNames.setValue(9, "Wood");
+		standardColorNames.setValue(10, "Sienna");
+		standardColorNames.setValue(11, "Green");
+		standardColorNames.setValue(12, "Light Green");
+		standardColorNames.setValue(13, "Cyan");
+		standardColorNames.setValue(14, "Blue");
+		standardColorNames.setValue(15, "Light Blue");
+		standardColorNames.setValue(16, "Magenta");
+		standardColorNames.setValue(17, "Pink");
+		//DO NOT ASSIGN A COLOR TO 18
+		standardColorsDimmed = new ObjectArray(18);
+		standardColorsDimmed.setValue(0, Color.gray);
+		standardColorsDimmed.setValue(1, brighter(Color.darkGray, dimmingConstant));
+		standardColorsDimmed.setValue(2, brighter(Color.gray, dimmingConstant));
+		standardColorsDimmed.setValue(3, brighter(Color.lightGray, dimmingConstant));
+		standardColorsDimmed.setValue(4, Color.white);
+		standardColorsDimmed.setValue(5, brighter(Color.red, dimmingConstant));
+		standardColorsDimmed.setValue(6, brighter(Color.orange, dimmingConstant));
+		standardColorsDimmed.setValue(7, brighter(Color.yellow, dimmingConstant));
+		standardColorsDimmed.setValue(8, brighter(paleGoldenRod, dimmingConstant));
+		standardColorsDimmed.setValue(9, brighter(burlyWood, dimmingConstant));
+		standardColorsDimmed.setValue(10, brighter(sienna, dimmingConstant));
+		standardColorsDimmed.setValue(11, brighter(Color.green, dimmingConstant));
+		standardColorsDimmed.setValue(12, brighter(lightGreen, dimmingConstant));
+		standardColorsDimmed.setValue(13, brighter(Color.cyan, dimmingConstant));
+		standardColorsDimmed.setValue(14, brighter(Color.blue, dimmingConstant));
+		standardColorsDimmed.setValue(15, brighter(lightBlue, dimmingConstant));
+		standardColorsDimmed.setValue(16, brighter(Color.magenta, dimmingConstant));
+		standardColorsDimmed.setValue(17, brighter(Color.pink, dimmingConstant));
+		//DO NOT ASSIGN A COLOR TO 18
+	}
+	public ColorDistribution( Color c) {
+		this();
+		setColor(0, c);
+	}
+	public ColorDistribution() {
+		colors = new Color[MAXCOLORS];
+		colorsDimmed = new Color[MAXCOLORS];
+		weights = new double[MAXCOLORS];
+		
+	}
+
+
+	
+	private static float brighten(int v, double percent){
+		float b = (float)((255-(255-v)*percent)/255);
+		if (b<0)
+			b=0;
+		else if (b>1)
+			b=1;
+		return b;
+	}
+	
+	public static Composite getComposite(Graphics g) {
+		if (g!=null && (g instanceof Graphics2D)) {
+			return ((Graphics2D)g).getComposite(); 
+		}
+		return null;
+	}
+	
+	public static void setComposite(Graphics g, Composite composite) {
+		if (g!=null && composite!=null && (g instanceof Graphics2D)) {
+			((Graphics2D)g).setComposite(composite); 
+		}
+	}
+
+
+	
+	public static void setTransparentGraphics(Graphics g, float f) {
+		if (g!=null && (g instanceof Graphics2D)) {
+			if (f>0.0f && f<1.0f)
+				((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, f)); 
+//			else if (f==0.0f)
+//				((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.00001f)); 
+		}
+	}
+	public static void setTransparentGraphics(Graphics g) {
+		setTransparentGraphics(g,0.5f); 
+	}
+	public static void setOpaqueGraphics(Graphics g) {
+		if (g!=null  && (g instanceof Graphics2D))
+			((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1));   
+	}
+	public static Color brighter(Color c, double percent){
+		if (c==null)
+			return null;
+		int green = c.getGreen();
+		int red = c.getRed();
+		int blue = c.getBlue();
+		return new Color(brighten(red, percent), brighten(green, percent), brighten(blue, percent));
+	}
+	private static float darken(int v, double percent){
+		float b = (float)((v*percent)/255);
+		if (b<0)
+			b=0;
+		else if (b>1)
+			b=1;
+		return b;
+	}
+	
+	public static Color darker(Color c, double percent){
+		if (c==null)
+			return null;
+		int green = c.getGreen();
+		int red = c.getRed();
+		int blue = c.getBlue();
+		return new Color(darken(red, percent), darken(green, percent), darken(blue, percent));
+	}
+	public static Color getContrasting(boolean selected, Color background, float[] hsbBackground, Color light, Color dark){
+		if (selected){
+			if (background != null && background.equals(light)){
+				return dark;
+			}
+			return light;
+		}
+		else if (hsbBackground[2]>0.5)
+			return dark;
+		else
+			return light;
+	}
+	public static Color getContrasting(Color c){
+		if (c==null){
+			return Color.black;
+		}
+		int red = (255-c.getRed());
+		int green = (255-c.getGreen());
+		int blue = (255-c.getBlue());
+		return new Color(red,green,blue);
+	}
+	public static int getStandardColorNumber(String name){
+		int ci = standardColorNames.indexOf(name);
+		return ci;
+	}
+	public static int getStandardColorNumber(Color color){
+		int ci = standardColors.indexOf(color);
+		return ci;
+	}
+	public static Color getStandardColor(String name){
+		int ci = standardColorNames.indexOf(name);
+		if (ci<0)
+			return null;
+		return (Color)standardColors.getValue(ci);
+	}
+	public static String getStandardColorName(Color color){
+		if (color==null)
+			return null;
+		int ic = standardColors.indexOf(color);
+		if (ic>=0)
+			return standardColorNames.getValue(ic);
+		else
+			return null;
+	}
+	public static String getStandardColorName(int ci){
+		if (ci<0)
+			return null;
+		return (String)standardColorNames.getValue(ci);
+	}
+	public static Color getStandardColor(int ci){
+		if (ci<0)
+			return null;
+		return (Color)standardColors.getValue(ci);
+	}
+	public static Color getStandardColorDimmed(int ci){
+		if (ci<0)
+			return null;
+		return (Color)standardColorsDimmed.getValue(ci);
+	}
+	public static boolean equalColors(Color color1, Color color2) {
+		if (color1==null || color2==null)
+			return false;
+		return (color1.getBlue()==color2.getBlue()&&color1.getRed()==color2.getRed()&&color1.getGreen()==color2.getGreen());
+	}
+	/** Initialize colors by setting the number of colors to 0, the weights to 0, and the colors to null*/
+	public void initialize() {
+		numColors=0;
+		for (int i=0; i<MAXCOLORS; i++) {
+			colors[i]=null;
+			colorsDimmed[i]=null;
+			weights[i]=0;
+		}
+	}
+	/** set color for state (or other unit) i to the given color.*/
+	public void setColor(int i, Color color) {
+		if (i>=0 && i<MAXCOLORS) {
+			if (colors[i]==null)
+				numColors++;
+			else if (color==null)
+				numColors--;
+			colors[i]=color;
+			Color dimmed = color;
+			if (color !=null){
+				if ( color.getGreen()==0 && color.getRed() ==0 && color.getBlue()==0)
+					dimmed = Color.gray;
+				else
+					dimmed = ColorDistribution.brighter(color, dimmingConstant);
+			}
+			colorsDimmed[i] = dimmed;
+		}
+	}
+	/** finds index of color.*/
+	public int indexOf(Color color) {
+		if (color == null)
+			return -1;
+		for (int i=0; i<colors.length; i++)
+			if (colors[i] != null && color.equals(colors[i])) 
+				return i;
+		return -1;
+	}
+	
+	public static Color getColorFromArguments(String arguments, MesquiteInteger pos) {
+		int red =  MesquiteInteger.fromString(arguments, pos);
+		int green =  MesquiteInteger.fromString(arguments, pos);
+		int blue =  MesquiteInteger.fromString(arguments, pos);
+		return new Color(red,green,blue);
+	}
+	
+	public static String getColorStringForSnapshot(Color color) {
+		return color.getRed() + " " + color.getGreen() + " " + color.getBlue();
+	}
+
+	/** gets the color for unit i*/
+	public Color getColor(int i) {
+		return colors[i];
+	}
+	/** gets the color for unit i*/
+	public Color getColor(int i, boolean regularStrength) {
+		if (regularStrength)
+			return colors[i];
+		else
+			return colorsDimmed[i];
+	}
+	/** sets the weight (for pie charts) for unit i*/
+	public void setWeight(int i, double weight) {
+		if (i>=0 && i<MAXCOLORS) {
+			weights[i]=weight;
+		}
+	}
+	/** get the weight for state (or other unit) i*/
+	public double getWeight(int i) {
+		return weights[i];
+	}
+	/** sets whether or not the colors are sequential, e.g. as for stochastic character mapping. 
+	 In this case the weights are the point at which the change occurs, e.g. proportional position on branch*/
+	public void setSequential(boolean s){
+		sequential = s;
+	}
+	/** returns whether the colors are to be considered sequential */
+	public boolean getSequential(){
+		return sequential;
+	}
+	/** get the total number of colors assigned*/
+	public int getNumColors() {
+		return numColors;
+	}
+	public static int getColorScheme(MesquiteModule mod){
+		if (mod == null || mod.getProject()==null)
+			return 0;
+		else
+			return mod.getProject().getProjectColor();
+	}
+	public static int getColorScheme(MesquiteProject mp){
+		if (mp == null)
+			return 0;
+		else
+			return mp.getProjectColor();
+	}
+	public String toString(){
+		String s = "ColorDistribution: ";
+		if (colors == null)
+			return s + " NO COLORS";
+		for (int i=0; i <colors.length && i<numColors; i++)
+			s += " " + i + ": " + colors[i] + " (weight " + weights[i] + ");";
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/lib/ColorEvent.java b/Source/mesquite/lib/ColorEvent.java
new file mode 100644
index 0000000..e27086b
--- /dev/null
+++ b/Source/mesquite/lib/ColorEvent.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+public class ColorEvent {
+	Color color;
+	double position;
+	
+	public ColorEvent(Color color, double position){
+		this.color = color;
+		this.position = position;
+	}
+	public Color getColor(){
+		return color;
+	}
+	public double getPosition(){
+		return position;
+	}
+	public void tradeValues(ColorEvent e){
+		Color tempC = e.color;
+		e.color = color;
+		color = tempC;
+		double tempD = e.position;
+		e.position = position;
+		position = tempD;
+	}
+}
+
diff --git a/Source/mesquite/lib/ColorEventVector.java b/Source/mesquite/lib/ColorEventVector.java
new file mode 100644
index 0000000..aaae7ff
--- /dev/null
+++ b/Source/mesquite/lib/ColorEventVector.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/* ======================================================================== */
+public class ColorEventVector extends Vector {
+	
+	public ColorEventVector(int num){
+		super(num);
+	}
+	public ColorEventVector(){
+		super();
+	}
+	public void sort(){
+		for (int i=1; i<size(); i++) {
+			boolean done = false;
+			for (int j= i-1; j>=0 && !done; j--) {
+				ColorEvent ej = (ColorEvent)elementAt(j);
+				ColorEvent ej1 = (ColorEvent)elementAt(j+1);
+				if (ej.getPosition()<=ej1.getPosition())
+					done = true;
+				else 
+					ej.tradeValues(ej1);
+			}
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/ColorPickerPanel.java b/Source/mesquite/lib/ColorPickerPanel.java
new file mode 100644
index 0000000..f363402
--- /dev/null
+++ b/Source/mesquite/lib/ColorPickerPanel.java
@@ -0,0 +1,248 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+public class ColorPickerPanel extends Panel implements MouseListener {
+	int hues = 50;
+	int saturations = 50;
+	int brightnesses = 50;
+	double brightness = 1.0;
+	Color[][] colors;
+	float[] colorLoc = null;
+	CurrentColorPanel indicator;
+	Colorable dialog;
+	private Color currentColor = Color.white;
+	int currentI = 0;
+	int currentJ = 0;
+	int boxSizeX;
+	int boxSizeY;
+	int offsetX;
+	int offsetY;
+	int touchedX = -1;
+	int touchedY = -1;
+	int indicatorX = -1;
+	int indicatorY = -1;
+	int colorEdge = 50;
+	public ColorPickerPanel(Colorable d, Color initColor, int divisions){
+		this.dialog = d;
+		addMouseListener(this);
+		if (divisions>0) {
+			hues = divisions;
+			saturations = divisions;
+		}
+		colors = new Color[hues][saturations];
+		for (int i=0; i<hues-1; i++){
+			for (int j=0; j<saturations; j++){
+				colors[i][j] = new Color(Color.HSBtoRGB((float)(i*1.0/hues),(float)(j*1.0/saturations),(float)brightness));
+			}
+		}
+		/**/
+		for (int j=0; j<saturations; j++){
+			float f = (float)(j*1.0/saturations);
+			colors[hues-1][j] = new Color(f, f, f);
+		}
+		/**/
+	  	add(indicator = new CurrentColorPanel(this));
+		setSize(200,200);
+		int w =  getBounds().width - colorEdge;
+		int h = getBounds().height;
+		 boxSizeX = w/hues;
+		 boxSizeY = h/saturations;
+		indicator.setBounds(-50,-50, boxSizeX+2, boxSizeY+2);
+	  	setInitialColor(initColor);
+	}
+	public void setInitialColor(Color current){
+		if (current == null)
+			return;
+		currentColor = current;
+		brightness = Color.RGBtoHSB(current.getRed(), current.getGreen(), current.getBlue(), null)[2];
+			for (int ki=0; ki<hues-1; ki++){
+  				for (int kj=0; kj<saturations; kj++){
+  					colors[ki][kj] = new Color(Color.HSBtoRGB((float)(ki*1.0/hues),(float)(kj*1.0/saturations),(float)brightness));
+  				}
+  			}
+
+		checkBounds();
+		setColorFromXY(indicatorX, indicatorY);
+		/*float hu = colorLoc[0];
+		float sa = colorLoc[1];
+		indicatorX = (int)(offsetX + hu*hues*boxSizeX-1);
+		indicatorY = (int)(offsetY+ sa*saturations*boxSizeY-1);
+		indicator.setLocation(indicatorX,indicatorY);
+		*/
+		indicator.repaint();
+	}
+	
+	private void checkBounds(){
+		int red = currentColor.getRed();
+		int green = currentColor.getGreen();
+		int blue = currentColor.getBlue();
+		int w =  getBounds().width - colorEdge;
+		int h = getBounds().height;
+		 boxSizeX = w/hues;
+		 boxSizeY = h/saturations;
+		 offsetX = (w-hues*boxSizeX)/2;
+		 offsetY = (h-saturations*boxSizeY)/2;
+		if (red == green && red == blue){
+			indicatorX = (int)(offsetX + (hues-1)*boxSizeX-1);
+			indicatorY = (int)(offsetY+ (1.0*red)/255*saturations*boxSizeY-1);
+		}
+		else {
+			colorLoc =  Color.RGBtoHSB(red, green, blue, null);
+			if (colorLoc==null)
+				return;
+			float hu = colorLoc[0];
+			float sa = colorLoc[1];
+			brightness = colorLoc[2];
+			indicatorX = (int)(offsetX + hu*hues*boxSizeX-1);
+			indicatorY = (int)(offsetY+ sa*saturations*boxSizeY-1);
+		}
+		Rectangle d = indicator.getBounds();
+		if (d.x != indicatorX || d.y != indicatorY || d.width != boxSizeX+2 || d.height != boxSizeY+2)
+			indicator.setBounds(indicatorX,indicatorY, boxSizeX+2, boxSizeY+2);
+	}
+	public Dimension getPreferredSize() {
+		return new Dimension(400, 200);
+	}
+	public void paint(Graphics g){
+		g.setClip(0, 0, getBounds().width, getBounds().height);
+		checkBounds();
+		/* boxSizeX = w/hues;
+		 boxSizeY = h/saturations;
+		*/
+		int w =  getBounds().width - colorEdge;
+		int h = getBounds().height;
+		 offsetX = (w-hues*boxSizeX)/2;
+		 offsetY = (h-saturations*boxSizeY)/2;
+		for (int x = 0; x < hues ; x++){
+			for (int y = 0; y<saturations; y++){
+				g.setColor(colors[x][y]);
+				g.fillRect(offsetX + x*boxSizeX,offsetY+ y*boxSizeY,boxSizeX,boxSizeY);
+			}
+		}
+		
+		/*
+		g.setColor(currentColor);
+		g.fillRect(w,0,colorEdge,h);
+		*/
+		float[] f = new float[3];
+		Color.RGBtoHSB(currentColor.getRed(), currentColor.getGreen(), currentColor.getBlue(), f);
+		
+		for (int b = 0; b < brightnesses ; b++){
+			float br = (float)(1.0-(b*1.0/brightnesses));
+			g.setColor(new Color(Color.HSBtoRGB(f[0],f[1],br)));
+				g.fillRect(w, b*h/brightnesses,colorEdge,(h/brightnesses));
+		}
+
+  		
+  		
+  		g.setColor(Color.black);
+		g.drawRect(w,0,colorEdge-1,h-1);
+		g.drawRect(offsetX, offsetY, hues*boxSizeX-1, saturations*boxSizeY-1);
+
+		g.drawRect(w + colorEdge/2-1, 0, 2, h-1);
+		g.setColor(Color.white);
+		g.drawLine(w + colorEdge/2, 0, w + colorEdge/2, h-1);
+		g.setColor(Color.black);
+		g.fillRoundRect(w + colorEdge/2-6, h-(int)(h * brightness + 4), 12, 8, 4, 4);
+		g.setColor(Color.white);
+		g.drawRoundRect(w + colorEdge/2-6, h-(int)(h * brightness + 4), 12, 8, 4, 4);
+		//g.drawRect(indicatorX, indicatorY, boxSizeX, boxSizeY);
+		/*
+		indicator.setSize(boxSizeX+2, boxSizeY+2);
+		
+		if (touchedX<0 && touchedY<0 && colorLoc!=null){
+			float hu = colorLoc[0];
+			float sa = colorLoc[1];
+			indicatorX = (int)(offsetX + hu*hues*boxSizeX-1);
+			indicatorY = (int)(offsetY+ sa*saturations*boxSizeY-1);
+			indicator.setLocation((int)(offsetX + hu*hues*boxSizeX-1),(int)(offsetY+ sa*saturations*boxSizeY-1));
+		}
+		*/
+		
+	}
+	private void setColorFromXY(int x, int y){
+		if (boxSizeX>0 && boxSizeY>0){
+	  		int i =(x-offsetX)/boxSizeX;
+	  		int j =(y-offsetY)/boxSizeY;
+	  		if (i>=0 && i<hues && j >=0 && j<saturations) {
+	  			currentColor = colors[i][j];
+	  			currentI = i;
+	  			currentJ = j;
+				checkBounds();
+				/*float hu = colorLoc[0];
+				float sa = colorLoc[1];
+				indicatorX = (int)(offsetX + hu*hues*boxSizeX-1);
+				indicatorY = (int)(offsetY+ sa*saturations*boxSizeY-1);
+	  			*/
+	  			//dialog.setColor(colors[i][j]);
+	  			touchedX = x;
+	  			touchedY = y;
+				//indicator.setLocation(indicatorX, indicatorY);
+				indicator.repaint();
+	  		}
+	  		else if (j >=0 && j<saturations && i >= hues){
+	  			brightness = (saturations - j)*1.0/saturations;
+	  			for (int ki=0; ki<hues-1; ki++){
+	  				for (int kj=0; kj<saturations; kj++){
+	  					colors[ki][kj] = new Color(Color.HSBtoRGB((float)(ki*1.0/hues),(float)(kj*1.0/saturations),(float)brightness));
+	  				}
+	  			}
+	  			currentColor = colors[currentI][currentJ];
+	  			repaint();
+	  			indicator.repaint();
+	  		}
+  		}
+	}
+   	public void mouseClicked(MouseEvent e) {
+  		int x = e.getX();
+  		int y = e.getY();
+		setColorFromXY(x, y);
+  	}
+
+   	public void mouseEntered(MouseEvent e) {
+   	}
+   	public void mouseExited(MouseEvent e) {
+   	}
+   	public void mousePressed(MouseEvent e) {
+   	}
+   	public void mouseReleased(MouseEvent e) {
+   	}
+   	
+   	public Color getColor(){
+   		return currentColor;
+   	}
+}
+
+class CurrentColorPanel extends Panel {
+	ColorPickerPanel colorPanel;
+	public CurrentColorPanel(ColorPickerPanel cp){
+		colorPanel = cp;
+	}
+	public void paint(Graphics g){
+		g.setColor(colorPanel.getColor());
+		int w = getBounds().width;
+		int h = getBounds().height;
+		g.fillRect(0,0, w-1, h -1);
+		g.setColor(Color.black);
+		g.drawRect(0,0, w-1, h -1);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ColorRecord.java b/Source/mesquite/lib/ColorRecord.java
new file mode 100644
index 0000000..bf7f785
--- /dev/null
+++ b/Source/mesquite/lib/ColorRecord.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+public class ColorRecord {
+	Color color;
+	String s;
+	
+	public ColorRecord(Color color, String s){
+		this.color = color;
+		this.s = s;
+	}
+	public ColorRecord(){
+	}
+	public Color getColor(){
+		return color;
+	}
+	public String getString(){
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/lib/ColorTheme.java b/Source/mesquite/lib/ColorTheme.java
new file mode 100644
index 0000000..8752930
--- /dev/null
+++ b/Source/mesquite/lib/ColorTheme.java
@@ -0,0 +1,381 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.Color;
+import mesquite.lib.simplicity.*;
+
+/* ======================================================================== */
+/**A class to deal with color themes of windows.*/
+public class ColorTheme {
+	public static final int ORIGINAL = 0;
+	public static final int PAPER = 1;
+	public static final int MILKCHOCOLATE = 2;
+	public static final int SLATE = 3;
+	public static final int DARKCHOCOLATE = 4;
+
+	public static int THEME = PAPER;
+	public static int THEME_FOR_NEXT_STARTUP = PAPER;
+
+
+	public static StringArray getColorThemes(){
+		StringArray themes = new StringArray(5);
+		themes.setValue(ORIGINAL, "Original");
+		themes.setValue(DARKCHOCOLATE, "Dark Chocolate");
+		themes.setValue(MILKCHOCOLATE, "Milk Chocolate");
+		themes.setValue(SLATE, "Slate");
+		themes.setValue(PAPER, "Paper");
+		return themes;
+	}
+	static Color ContentBackground = new Color(235,235,235);
+	static Color ContentBackgroundPale = new Color(240,240,240);
+	static Color ContentElement = new Color(225,225,225);
+	static Color ContentDarkElement = new Color(150,150,150);
+	static Color ContentEdgePale = new Color(240,240,240);
+	static Color ContentEdgeDark = new Color(150,150,150);
+	static Color ContentFrame = new Color(88, 88, 88);
+
+	public static Color getContentBackground(){
+		return ContentBackground;
+	}
+	public static Color getContentBackgroundPale(){
+		return ContentBackgroundPale;
+	}
+	public static Color getContentElement(){
+		return ContentElement;
+	}
+	public static Color getContentDarkElement(){
+		return ContentDarkElement;
+	}
+	public static Color getContentEdgePale(){
+		return ContentEdgePale;
+	}
+	public static Color getContentEdgeDark(){
+		return ContentEdgeDark;
+	}
+
+	public static Color getContentFrame(){
+		return ContentFrame;
+	}
+
+	//background of EXTERNAL INTERFACE AREA (main tab panel, project resources panel)
+	static Color[] ExtInterfaceBackground = new Color[5];
+	static {
+		ExtInterfaceBackground[ORIGINAL] = ColorDistribution.paleGoldenRod;
+		ExtInterfaceBackground[DARKCHOCOLATE] = new Color(74, 68, 59);
+		ExtInterfaceBackground[SLATE] = new Color(168,168,179); //slate theme
+		ExtInterfaceBackground[MILKCHOCOLATE] = new Color(88, 82, 74);
+		ExtInterfaceBackground[PAPER] = new Color(237, 232, 220); // lightening of tool palette background color
+		//ExtInterfaceBackground[PAPER] = new Color(230, 234, 210); // pale greenish yellow new Color(249, 255, 237);;  greenish: new Color(236, 249, 244)
+	}
+	public static Color getExtInterfaceBackground(){  //general background to main tabs and project panel
+		return ExtInterfaceBackground[THEME];
+
+	}
+	public static Color getExtInterfaceBackground(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow) //main mesquite window with log etc. has chocolate color scheme
+			return ExtInterfaceBackground[MILKCHOCOLATE];
+		else
+			return ExtInterfaceBackground[THEME];
+
+	}
+	/*-------------background of unselected outer tabs*/
+	static Color[] ExtInterfaceElement = new Color[5];
+	static {
+		ExtInterfaceElement[ORIGINAL] = ColorDistribution.veryPaleGoldenRod; 
+		ExtInterfaceElement[DARKCHOCOLATE] = new Color(88, 82, 74);//chocolate theme
+		ExtInterfaceElement[SLATE] = new Color(188,188,200);//slate theme
+		ExtInterfaceElement[MILKCHOCOLATE] = new Color(88, 82, 74);
+		ExtInterfaceElement[PAPER] = new Color(237, 232, 220); // lightening of tool palette background color
+		//ExtInterfaceBackground[PAPER] = new Color(230, 234, 210); // pale greenish yellow new Color(249, 255, 237);;  greenish: new Color(236, 249, 244)
+	}
+	public static Color getExtInterfaceElement(){ // slightly contrasting color for unselected main tabs and some parts of project panel
+		return ExtInterfaceElement[THEME];
+	}
+	public static Color getExtInterfaceElement(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceElement[MILKCHOCOLATE];
+		else
+			return ExtInterfaceElement[THEME];
+
+	}
+	/*-------------background of selected outer tabs (pale top color)*/
+	static Color[] ExtInterfaceElementContrast = new Color[5];
+	static {
+		ExtInterfaceElementContrast[ORIGINAL] = ColorDistribution.bisque;
+		ExtInterfaceElementContrast[DARKCHOCOLATE] = new Color(113, 108, 96); //chocolate theme   //formerly new Color(102, 98, 86); //chocolate theme
+		ExtInterfaceElementContrast[SLATE] = new Color(221,221,232);//slate theme
+		ExtInterfaceElementContrast[MILKCHOCOLATE] = new Color(102, 98, 86); //chocolate theme
+		ExtInterfaceElementContrast[PAPER] = Color.white;
+	}
+	public static Color getExtInterfaceElementContrast(){   //element that is contrasted, e.g. the highlighted one, in the main tabs/project area
+		return ExtInterfaceElementContrast[THEME];
+	}
+	public static Color getExtInterfaceElementContrast(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceElementContrast[MILKCHOCOLATE];
+		else
+			return ExtInterfaceElementContrast[THEME];
+
+	}
+	/*-------------background of selected but NOT FOREMOST outer tabs (pale top color)*/
+	static Color[] ExtInterfaceElementContrast2 = new Color[5];
+	static {
+		ExtInterfaceElementContrast2[ORIGINAL] = ColorDistribution.bisque;
+		ExtInterfaceElementContrast2[DARKCHOCOLATE] = new Color(113, 108, 96); //chocolate theme   //formerly new Color(102, 98, 86); //chocolate theme
+		ExtInterfaceElementContrast2[SLATE] = new Color(221,221,232);//slate theme
+		ExtInterfaceElementContrast2[MILKCHOCOLATE] = new Color(102, 98, 86); //chocolate theme
+		ExtInterfaceElementContrast2[PAPER] =new Color(242, 237, 225); // lightening of tool palette background color
+		// ExtInterfaceElementContrast2[PAPER] = new Color(234, 239, 215);  //greenish new Color(242, 255, 250)
+	}
+	public static Color getExtInterfaceElementContrast2(){   //element that is contrasted, e.g. the highlighted one, in the main tabs/project area
+		return ExtInterfaceElementContrast2[THEME];
+	}
+	public static Color getExtInterfaceElementContrast2(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceElementContrast2[MILKCHOCOLATE];
+		else
+			return ExtInterfaceElementContrast2[THEME];
+
+	}
+	/*------------- edge highlight of selected outer tabs*/
+	static Color[] ExtInterfaceEdgeContrast = new Color[5];
+	static {
+		ExtInterfaceEdgeContrast[ORIGINAL] = ColorDistribution.sienna;
+		ExtInterfaceEdgeContrast[DARKCHOCOLATE] = new Color(210,205,195);//chocolate theme  //formerly new Color(190,185,175);//chocolate theme
+		ExtInterfaceEdgeContrast[SLATE] = new Color(80,80,90);//slate theme
+		ExtInterfaceEdgeContrast[MILKCHOCOLATE] = new Color(190,185,175);//chocolate theme
+		ExtInterfaceEdgeContrast[PAPER] = ColorDistribution.veryDarkMesquiteBrown;
+	}
+	public static Color getExtInterfaceEdgeContrast(){
+		return ExtInterfaceEdgeContrast[THEME];
+	}
+	public static Color getExtInterfaceEdgeContrast(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceEdgeContrast[MILKCHOCOLATE];
+		else
+			return ExtInterfaceEdgeContrast[THEME];
+
+	}
+	/*-------------edge of unselected outer tabs*/
+	static Color[] ExtInterfaceEdgeMuted = new Color[5];
+	static {
+		ExtInterfaceEdgeMuted[ORIGINAL] = ColorDistribution.sienna;
+		ExtInterfaceEdgeMuted[DARKCHOCOLATE] = new Color(190,178,130);//chocolate theme
+		ExtInterfaceEdgeMuted[SLATE] = new Color(68,68,78);//slate theme
+		ExtInterfaceEdgeMuted[MILKCHOCOLATE] = new Color(190,178,130);//chocolate theme
+		ExtInterfaceEdgeMuted[PAPER] = new Color(176,162,150);  // to go with pale brown color
+		//ExtInterfaceEdgeMuted[PAPER] = new Color(176,176,150);  // to go with greenish color
+	}
+	public static Color getExtInterfaceEdgeMuted(){  //muted text in external interface area,e.g. unselected tabs
+		return ExtInterfaceEdgeMuted[THEME];
+	}
+	public static Color getExtInterfaceEdgeMuted(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceEdgeMuted[MILKCHOCOLATE];
+		else
+			return ExtInterfaceEdgeMuted[THEME];
+
+	}
+	/*-------------text of selected outer tabs*/
+	static Color[] ExtInterfaceTextContrast = new Color[5];
+	static {
+		ExtInterfaceTextContrast[ORIGINAL] = Color.black;
+		ExtInterfaceTextContrast[DARKCHOCOLATE] = new Color(238,224,210);//chocolate theme
+		ExtInterfaceTextContrast[SLATE] = new Color(28,28,33); //slate theme
+		ExtInterfaceTextContrast[MILKCHOCOLATE] = new Color(244,234,218);//chocolate theme
+		ExtInterfaceTextContrast[PAPER] = Color.black;
+	}
+	public static Color getExtInterfaceTextContrast(){  //high contrast text in external interface area, e.g. highlighted tab
+		return ExtInterfaceTextContrast[THEME];
+	}
+	public static Color getExtInterfaceTextContrast(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceTextContrast[MILKCHOCOLATE];
+		else
+			return ExtInterfaceTextContrast[THEME];
+
+	}
+	/*-------------text of unselected outer tabs*/
+	static Color[] ExtInterfaceTextMuted = new Color[5];
+	static {
+		ExtInterfaceTextMuted[ORIGINAL] = ColorDistribution.sienna;
+		ExtInterfaceTextMuted[DARKCHOCOLATE] = new Color(190,178,130);//chocolate theme
+		ExtInterfaceTextMuted[SLATE] = new Color(68,68,78);//slate theme
+		ExtInterfaceTextMuted[MILKCHOCOLATE] = new Color(190,178,130);//chocolate theme
+		ExtInterfaceTextMuted[PAPER] = new Color(106,98,80);  // to go with pale brown color
+//		ExtInterfaceTextMuted[PAPER] = new Color(106,106,80);  // to go with greenish color
+	}
+	public static Color getExtInterfaceTextMuted(){  //muted text in external interface area,e.g. unselected tabs
+		return ExtInterfaceTextMuted[THEME];
+	}
+	public static Color getExtInterfaceTextMuted(boolean isMesquiteWindow){  //general background to main tabs and project panel
+		if (isMesquiteWindow)
+			return ExtInterfaceTextMuted[MILKCHOCOLATE];
+		else
+			return ExtInterfaceTextMuted[THEME];
+
+	}
+	/*-------------text of project panel*/
+	static Color[] ExtInterfaceTextMedium = new Color[5];
+	static {
+		ExtInterfaceTextMedium[ORIGINAL] = ColorDistribution.sienna;
+		ExtInterfaceTextMedium[DARKCHOCOLATE] = new Color(210,190,154);//chocolate theme
+		ExtInterfaceTextMedium[SLATE] = new Color(48,48,56); //slate theme
+		ExtInterfaceTextMedium[MILKCHOCOLATE] = new Color(219,199,164); //chocolate theme
+		ExtInterfaceTextMedium[PAPER] = new Color(106,98,80);  // to go with pale brown color
+//		ExtInterfaceTextMedium[PAPER] = new Color(106,106,80);  // to go with greenish color
+	}
+	public static Color getExtInterfaceTextMedium(){ //medium contrast text in external interface area, e.g. project resources text
+		return ExtInterfaceTextMedium[THEME];
+	}
+	/*-------------link text of project panel*/
+	static Color[] ExtInterfaceTextLink = new Color[5];
+	static {
+		ExtInterfaceTextLink[ORIGINAL] =  Color.blue;
+		ExtInterfaceTextLink[DARKCHOCOLATE] = Color.cyan;
+		ExtInterfaceTextLink[SLATE]  = Color.blue;
+		ExtInterfaceTextLink[MILKCHOCOLATE]  = Color.cyan;
+		ExtInterfaceTextLink[PAPER] = Color.gray;
+	}
+	public static Color getExtInterfaceTextLink(){ //medium contrast text in external interface area, e.g. project resources text
+		return ExtInterfaceTextLink[THEME];
+	}
+	
+	/*-------------------------*/
+	//INTERNAL INTERFACE AREA (tool palettes, graphics/text/etc tabs)
+	static Color[] InterfaceBackground = new Color[5];
+	static {
+		InterfaceBackground[ORIGINAL] = ColorDistribution.paleGoldenRod;
+		InterfaceBackground[DARKCHOCOLATE] = new Color(216,204,172);  // chocolate theme
+		InterfaceBackground[SLATE] = new Color(224,229,244);  // slate theme
+		InterfaceBackground[MILKCHOCOLATE] = new Color(216,204,172);  // chocolate theme
+		InterfaceBackground[PAPER] = InterfaceBackground[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceBackground(){  //background of tool palettes and small tabs bar
+		return InterfaceBackground[THEME];
+	}
+	/*-------------*/
+	static Color[] InterfaceBackgroundPale = new Color[5];
+	static {
+		InterfaceBackgroundPale[ORIGINAL] = ColorDistribution.veryPaleGoldenRod;
+		InterfaceBackgroundPale[DARKCHOCOLATE] = new Color(234, 228,212); // chocolate theme
+		InterfaceBackgroundPale[SLATE] = new Color(234,239,249);  // slate theme
+		InterfaceBackgroundPale[MILKCHOCOLATE] = new Color(234, 228,212); // chocolate theme
+		InterfaceBackgroundPale[PAPER] = InterfaceBackgroundPale[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceBackgroundPale(){
+		return InterfaceBackgroundPale[THEME];
+	}
+	/*-------------Unselected tools; unselected inner tabs*/
+	static Color[] InterfaceElement = new Color[5];
+	static {
+		InterfaceElement[ORIGINAL] = ColorDistribution.bisque;
+		InterfaceElement[DARKCHOCOLATE] = new Color(234, 228,212); // chocolate theme
+		InterfaceElement[SLATE] = new Color(216,212,212);  // slate theme
+		InterfaceElement[MILKCHOCOLATE] = new Color(234, 228,212); // chocolate theme
+		InterfaceElement[PAPER] = InterfaceElement[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceElement(){ //unselected tool buttons and small tab
+		return InterfaceElement[THEME];
+	}
+	/*-------------selected inner tab */
+	static Color[] InterfaceElementContrast = new Color[5];
+	static {
+		InterfaceElementContrast[ORIGINAL] = ColorDistribution.lightMesquiteBrown;
+		InterfaceElementContrast[DARKCHOCOLATE] = new Color(236,230,222); // chocolate theme
+		InterfaceElementContrast[SLATE] = new Color(228,228,228);  // slate theme
+		InterfaceElementContrast[MILKCHOCOLATE] = new Color(236,230,222); // chocolate theme
+		InterfaceElementContrast[PAPER] = InterfaceElementContrast[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceElementContrast(){ //selected small tab
+		return InterfaceElementContrast[THEME];
+
+	}
+	/*-------------*/
+	static Color[] InterfaceEdgeNegative = new Color[5];
+	static {
+		InterfaceEdgeNegative[ORIGINAL] = ColorDistribution.sienna;
+		InterfaceEdgeNegative[DARKCHOCOLATE] = new Color(226,222,222); // chocolate theme
+		InterfaceEdgeNegative[SLATE] = new Color(142,142,146); // slate theme
+		InterfaceEdgeNegative[MILKCHOCOLATE] = new Color(226,222,222); // chocolate theme
+		InterfaceEdgeNegative[PAPER] = InterfaceEdgeNegative[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceEdgeNegative(){  //edge to unselected small tab and tool button
+		return InterfaceEdgeNegative[THEME];
+	}
+	/*-------------*/
+	static Color[] InterfaceEdgePositive = new Color[5];
+	static {
+		InterfaceEdgePositive[ORIGINAL] = ColorDistribution.straw;
+		InterfaceEdgePositive[DARKCHOCOLATE] = new Color(114,100,90); // chocolate theme
+		InterfaceEdgePositive[SLATE] = new Color(70,80,104);  // slate theme
+		InterfaceEdgePositive[MILKCHOCOLATE] = new Color(114,100,90); // chocolate theme
+		InterfaceEdgePositive[PAPER] = InterfaceEdgePositive[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceEdgePositive(){  //edge to selected small tab
+		return InterfaceEdgePositive[THEME];
+	}
+	/*-------------*/
+	static Color[] InterfaceTextContrast = new Color[5];
+	static {
+		InterfaceTextContrast[ORIGINAL] = Color.black;
+		InterfaceTextContrast[DARKCHOCOLATE] = new Color(44,40,40);  //chocolate theme
+		InterfaceTextContrast[SLATE] = new Color(40,40,44);  // slate theme
+		InterfaceTextContrast[MILKCHOCOLATE] = new Color(44,40,40);  //chocolate theme
+		InterfaceTextContrast[PAPER] = InterfaceTextContrast[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceTextContrast(){  //contrasting text; must be opposite to element contrast; e.g. for selected tab
+		return InterfaceTextContrast[THEME];
+	}
+	/*-------------*/
+	static Color[] InterfaceTextMuted = new Color[5];
+	static {
+		InterfaceTextMuted[ORIGINAL] = ColorDistribution.sienna;
+		InterfaceTextMuted[DARKCHOCOLATE] = new Color(64,60,60); // chocolate theme
+		InterfaceTextMuted[SLATE] = new Color(60,60,64);  // slate theme
+		InterfaceTextMuted[MILKCHOCOLATE] = new Color(64,60,60); // chocolate theme
+		InterfaceTextMuted[PAPER] = InterfaceTextMuted[DARKCHOCOLATE];
+	}
+	public static Color getInterfaceTextMuted(){  //muted text; e.g. for unselected tabs
+		return InterfaceTextMuted[THEME];
+	}
+
+
+	/*-------------*/
+	static Color[] ActiveLight = new Color[5];
+	static {
+		ActiveLight[ORIGINAL] = ColorDistribution.lightMesquiteBrown;
+		ActiveLight[DARKCHOCOLATE] = new Color(252, 239, 170);  // chocolate theme
+		ActiveLight[SLATE] = new Color(185, 214, 252);  // slate theme
+		ActiveLight[MILKCHOCOLATE] = new Color(242, 224, 185);  // chocolate theme
+		ActiveLight[PAPER] = ActiveLight[DARKCHOCOLATE];
+	}
+	public static Color getActiveLight(){  //currently used for selected tool button
+		return ActiveLight[THEME];
+	}
+	/*-------------*/
+	static Color[] ActiveDark = new Color[5];
+	static {
+		ActiveDark[ORIGINAL] = ColorDistribution.mesquiteBrown;
+		ActiveDark[DARKCHOCOLATE] = new Color(160, 82, 45);  // chocolate theme
+		ActiveDark[SLATE] = new Color(45, 82, 190);  // slate theme
+		ActiveDark[MILKCHOCOLATE] = new Color(160, 82, 45);  // chocolate theme
+		ActiveDark[PAPER] = ActiveDark[DARKCHOCOLATE];
+	}
+	public static Color getActiveDark(){ //currently used for selected tool button edge
+		return ActiveDark[THEME];
+	}
+
+}
diff --git a/Source/mesquite/lib/Colorable.java b/Source/mesquite/lib/Colorable.java
new file mode 100644
index 0000000..c57ca44
--- /dev/null
+++ b/Source/mesquite/lib/Colorable.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** DOCUMENT */
+public interface Colorable  {
+	public void setColor(Color c);
+	public Color getColor();
+}
+
+
+
+
diff --git a/Source/mesquite/lib/CommandChecker.java b/Source/mesquite/lib/CommandChecker.java
new file mode 100644
index 0000000..b8ee25c
--- /dev/null
+++ b/Source/mesquite/lib/CommandChecker.java
@@ -0,0 +1,1036 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/*
+ * includes commands, buttons, miniscrolls
+ *  /* ========================================================================
+ */
+/* ======================================================================== */
+/**
+ * An object designed primarily to allow Mesquite, at startup, to harvest a list
+ * of available commands. In its default mode, it is nothing but a string
+ * comparer (using equalsIgnoresCase or startsWidth), in that its 'compare' and
+ * 'compareStart' methods are used in the doCommand methods of Commandable
+ * objects to see what command was passed (it is also used in Puppeteer's
+ * sendCommands method). However, when in accumulateMode, a CommandChecker
+ * always returns false to the query of whether the strings are the same, but in
+ * the process accumulates information on what commands are being sought by the
+ * Commandable. This means that one call to the doCommand method of the
+ * Commandable, passing an accumulating checker, will cause the checker to
+ * acquire a list of all the commands sought by the commandable. This system was
+ * designed so that the available commands would be harvested automatically at
+ * startup, and wouldn't depend on the programmer keeping a separate manual page
+ * of commands up to date.
+ */
+public class CommandChecker {
+	boolean accumulateMode = false;
+
+	boolean includeParameters = true;
+	
+	boolean warnIfNoResponse = true;
+
+	boolean LIMode = false;
+
+	boolean HTMLmode = true;
+
+	boolean skip = false;
+
+	boolean sparse = false; // should be renamed; not just sparse
+
+	Vector explanationStrings, commandNameStrings, menuStrings;
+
+	public static Vector registeredClasses, representingClasses;
+
+	Class classLimited = null;
+
+	/** The file (if any) in which resides the script being executed */
+	MesquiteFile file = null;
+
+	public static CommandChecker defaultChecker;
+	public static CommandChecker quietDefaultChecker;
+
+	static CommandChecker defaultSkipChecker;
+	static {
+		registeredClasses = new Vector();
+		representingClasses = new Vector();
+		defaultChecker = new CommandChecker();
+		quietDefaultChecker = new CommandChecker();
+		quietDefaultChecker.warnIfNoResponse = false;
+		defaultSkipChecker = new CommandChecker();
+		defaultSkipChecker.skip = true;
+		defaultSkipChecker.accumulateMode = true;
+		defaultSkipChecker.includeParameters = true;
+	}
+
+	public CommandChecker() {
+		explanationStrings = new Vector();
+		commandNameStrings = new Vector();
+		menuStrings = new Vector();
+	}
+
+	private void reinitialize() {
+		explanationStrings.removeAllElements();
+		commandNameStrings.removeAllElements();
+		menuStrings.removeAllElements();
+		accumulateMode = false;
+		includeParameters = true;
+		LIMode = false;
+		skip = false;
+		classLimited = null;
+	}
+
+	/** Sets the file of the script being executed via this checker. */
+	public void setFile(MesquiteFile f) {
+		file = f;
+	}
+
+	/** Returns the file of the script being executed via this checker. */
+	public MesquiteFile getFile() {
+		return file;
+	}
+
+	/**
+	 * Sets the mode of the checker: if true is passed, it accumulates a list of
+	 * commands instead of comparing a commandname to a target
+	 */
+	public void setAccumulateMode(boolean mode) {
+		accumulateMode = mode;
+	}
+
+	/** Returns whether the checker is an accumulator (or comparer). */
+	public boolean getAccumulateMode() {
+		return accumulateMode;
+	}
+
+	/**
+	 * Sets whether an accumulating checker is to put '
+	 * <li>' at the start of each line of the accumulated commands.
+	 */
+	public void setLIMode(boolean mode) {
+		LIMode = mode;
+	}
+
+	/**
+	 * Sets whether an accumulating checker is to put HTML codes in the
+	 * explanations of commands.
+	 */
+	public void setHTMLMode(boolean mode) {
+		HTMLmode = mode;
+	}
+
+	/** Sets checker as sparse in accumulated text. */
+	public void setSparseMode() {
+		HTMLmode = false;
+		LIMode = false;
+		sparse = true;
+	}
+
+	/**
+	 * Sets what exact class the checker is to accumulate commands from (will
+	 * not accumulate from super or subclasses).
+	 */
+	public void accumulateOnlyFrom(Class c) {
+		classLimited = c;
+	}
+
+	/**
+	 * Accumulates (menus and ) commands from the given commandable and passes
+	 * back a vector of strings describing the (menus and ) commands.
+	 */
+	public static CommandChecker accumulate(Commandable c,
+			CommandChecker checker) {
+		if (c == null)
+			return null;
+		if (checker == null)
+			checker = new CommandChecker();
+		else
+			checker.reinitialize();
+		checker.setAccumulateMode(true);
+		if (!checker.sparse)
+			checker.accumulateOnlyFrom(c.getClass());
+
+
+		c.doCommand(null, null, checker);// �
+		if (c instanceof MesquiteModule) {
+			MesquiteModule mb = (MesquiteModule) c;
+			MesquiteMenuItemSpec.checkerMMI = checker;
+			MesquiteCMenuItemSpec.checkerMCMI = checker;
+			MesquiteSubmenuSpec.checkerMS = checker;
+			mb.defineMenus(true);
+			MesquiteMenuItemSpec.checkerMMI = null;
+			MesquiteCMenuItemSpec.checkerMCMI = null;
+			MesquiteSubmenuSpec.checkerMS = null;
+		}
+		return checker;
+	}
+
+	/**
+	 * Returns string explaining the operation of the widget (menu item, tool,
+	 * button, etc.) that uses the given command; for use in query mode and in
+	 * commands pending list
+	 */
+	public static String getQueryModeString(String item,
+			MesquiteCommand command, Object widget) {
+		String s = item
+		+ " "
+		+ CommandChecker.getCommandExplanation(command, null, false,
+				false) + "\n";
+		Object ref = null;
+		if (widget instanceof MesquiteMenuItem)
+			ref = ((MesquiteMenuItem) widget).getReferent();
+		else if (widget instanceof MesquiteCheckMenuItem)
+			ref = ((MesquiteCheckMenuItem) widget).getReferent();
+		else if (widget instanceof MesquiteSubmenu)
+			ref = ((MesquiteSubmenu) widget).getReferent();
+		if (ref != null) {
+			String e = "";
+			if (ref instanceof MesquiteModuleInfo)
+				e += "Class: " + ((MesquiteModuleInfo)ref).getClassName()+"\n";
+			if (ref instanceof Listable && ref instanceof Explainable)
+				e += "Uses: " + ((Listable) ref).getName() + " ("
+				+ ((Explainable) ref).getExplanation() + ")";
+			else if (ref instanceof Listable)
+				e += "Uses: " + ((Listable) ref).getName();
+			else if (ref instanceof Explainable)
+				e += "(" + ((Explainable) ref).getExplanation() + ")";
+			if (e.length() > 0)
+				s += e + '\n';
+		}
+		if (command != null && command.getOwner() instanceof Listable) {
+			s += "Command handled by: "
+				+ ((Listable) command.getOwner()).getName() + "\n";
+		}
+		return s;
+
+	}
+
+	/**
+	 * Accumulates (menus and ) commands from the given commandable and passes
+	 * back a vector of strings describing the (menus and ) commands.
+	 */
+	public static String getCommandExplanation(MesquiteCommand command,
+			CommandChecker checker, boolean includeParameters) {
+		return getCommandExplanation(command, checker, includeParameters, true);
+	}
+
+	/**
+	 * Accumulates (menus and ) commands from the given commandable and passes
+	 * back a vector of strings describing the (menus and ) commands.
+	 */
+	public static String getCommandExplanation(MesquiteCommand command,
+			CommandChecker checker, boolean includeParameters,
+			boolean useHTMLmode) {
+		if (command == null || command.getOwner() == null)
+			return null;
+		if (checker == null)
+			checker = new CommandChecker();
+		else
+			checker.reinitialize();
+		checker.setAccumulateMode(true);
+		checker.setHTMLMode(useHTMLmode);
+		checker.includeParameters = includeParameters;
+		command.getOwner().doCommand(command.getName(), null,
+				checker);// �
+		Vector exp = checker.getAccumulatedExplanations();
+		if (exp == null || exp.size() == 0)
+			return null;
+		else
+			return (String) exp.elementAt(0);
+	}
+
+	/** Adds a string to the vector of strings being accumulated by the checker. */
+	public void addString(String s) {
+		explanationStrings.addElement(s);
+		commandNameStrings.addElement("");
+	}
+
+	public void registerMenuItem(MesquiteModule ownerModule, String itemName,
+			MesquiteCommand command) {
+		if (accumulateMode) {
+			String s = "";
+			if (LIMode)
+				s += "<li>";
+			s += "<strong>" + itemName + "</strong>";
+			if (command != null) {
+				String commandName = command.getName();
+				boolean found = false;
+				for (int i = 0; i < commandNameStrings.size() && !found; i++) {
+					if (commandName.equals((String) commandNameStrings
+							.elementAt(i))) {
+						s += (String) explanationStrings.elementAt(i);
+						found = true;
+					}
+				}
+			}
+			menuStrings.addElement(s);
+		}
+	}
+
+	/*------------------------*/
+	StringBuffer sb = new StringBuffer(300);
+
+	private String getEString(String explanation, String parameters,
+			String targetCommand) {
+		sb.setLength(0);
+		if (HTMLmode) {
+			if (LIMode) {
+				sb.append("<li>");
+				sb.append("<strong>" + targetCommand + "</strong>");
+			}
+			if ((includeParameters && !StringUtil.blank(parameters))
+					|| !StringUtil.blank(explanation)) {
+				sb.append(" " + "<ul>");
+				if (!StringUtil.blank(explanation))
+					sb.append(" <li><u>Explanation:</u> " + explanation);
+				if (includeParameters && !StringUtil.blank(parameters))
+					sb.append(" <li><u>Parameters:</u> " + parameters);
+				sb.append("</ul>");
+			}
+			return sb.toString();
+		} else {
+			if (LIMode) {
+				sb.append(targetCommand);
+			}
+			if ((includeParameters && !StringUtil.blank(parameters))
+					|| !StringUtil.blank(explanation)) {
+				if (!StringUtil.blank(explanation))
+					sb.append("\nExplanation: " + explanation);
+				if (includeParameters && !StringUtil.blank(parameters))
+					sb.append("\nParameters:> " + parameters);
+			}
+			return sb.toString();
+		}
+	}
+
+	boolean verbose = false;
+
+	/*------------------------*/
+	/**
+	 * This method either (1) compares the command parameter to the
+	 * targetCommand parameter and returns true if they are the same or (2)
+	 * accumulates the targetCommand and associated explanations and parameters
+	 * strings into a description of the command. Whether it does (1) or (2)
+	 * depends on whether it is set to be in accumulateMode. This method is used
+	 * typically in the doCommand methods of Commandables.
+	 */
+	static int mess = 0;
+
+	public boolean compare(Class classCommanded, String explanation,
+			String parameters, String command, String targetCommand) {
+		if (classLimited != null && classLimited != classCommanded)
+			return false;
+		else if (accumulateMode) {
+			if (targetCommand != null && command != null
+					&& !command.equals("null")
+					&& !command.equalsIgnoreCase(targetCommand))
+				return false;
+			String s = null;
+			if (sparse) {
+				s = explanation + "  Parameters: " + parameters;
+				if (explanation == null)
+					s = "[No Explanation] ";
+				else
+					s = explanation;
+				if (parameters != null)
+					s += "  Parameters: " + parameters;
+			} else
+				s = getEString(explanation, parameters, targetCommand);
+			explanationStrings.addElement(s);
+			commandNameStrings.addElement(targetCommand);
+			return false;
+		}
+		boolean targetHit = (targetCommand != null && command != null && command
+				.equalsIgnoreCase(targetCommand));
+		if (verbose && targetHit)
+			MesquiteMessage.println("> " + command + " <to> " + classCommanded);
+		return targetHit;
+	}
+
+	/**
+	 * This method is the same as compare except that when in comparing mode (1)
+	 * it returns true of the command starts with the targetCommand as a
+	 * substring.
+	 */
+	public boolean compareStart(Class classCommanded, String explanation,
+			String parameters, String command, String targetCommand) {
+		if (classLimited != null && classLimited != classCommanded)
+			return false;
+		else if (accumulateMode) {
+			if (targetCommand != null && command != null
+					&& !command.equalsIgnoreCase(targetCommand))
+				return false;
+			String s = null;
+			if (sparse) {
+				s = explanation + "  Parameters: " + parameters;
+				if (explanation == null)
+					s = "[No Explanation] ";
+				else
+					s = explanation;
+				if (parameters != null)
+					s += "  Parameters: " + parameters;
+			} else
+				s = getEString(explanation, parameters, targetCommand);
+			explanationStrings.addElement(s);
+			commandNameStrings.addElement(targetCommand); // targetCommand
+
+			return false;
+		}
+		boolean targetHit = (targetCommand != null && command != null && StringUtil
+				.startsWithIgnoreCase(command, targetCommand));
+		if (verbose && targetHit)
+			MesquiteMessage.println("> " + command + " <to> " + classCommanded);
+		return targetHit;
+	}
+
+	/**
+	 * returns the vector of strings for commands accumulated by the checker
+	 * when in accumulateMode
+	 */
+	public Vector getAccumulatedCommands() {
+		return (Vector) commandNameStrings.clone();
+	}
+
+	/**
+	 * returns the vector of strings for commands accumulated by the checker
+	 * when in accumulateMode
+	 */
+	public Vector getAccumulatedExplanations() {
+		return (Vector) explanationStrings.clone();
+	}
+
+	/**
+	 * returns the vector of strings for menus accumulated by the checker when
+	 * in accumulateMode
+	 */
+	public Vector getAccumulatedMenus() {
+		return (Vector) menuStrings.clone();
+	}
+
+	/**
+	 * This static method registers a class for inclusion in the list of
+	 * commands available (under 'other' in the Scripting Commands page
+	 * available from the Help menu in Mesquite). This must be done early in
+	 * startup to be useful (e.g., in a module's mesquiteStartup() method). The
+	 * first class passed must be instantiable (i.e. Not abstract) and have at
+	 * least one constructor without arguments. This first class is the class to
+	 * be registered, or a subclass of it. The second class passed is the actual
+	 * class whose commands are to be documented. (This second class may be
+	 * abstract, which is the reason two classes need to be passed.) See the
+	 * documentation for the method commandsFromRegisteredClasses for
+	 * information on how the two classes are used.
+	 */
+	public static void registerClass(Class c, Class representing) {
+		registeredClasses.addElement(c);
+		representingClasses.addElement(representing);
+	}
+
+	/**
+	 * Returns a vector of strings showing the classes that were registered with
+	 * registerClass and their available commands. As noted under the method
+	 * registerClass, two classes are registered at a time: a first class (which
+	 * must be instantiable) and a second class (which may be abstract and must
+	 * be the same as or a superclass of the first class). The method
+	 * commandsFromRegisteredClasses makes an accumulating CommandChecker and
+	 * then examines each of the registered pair of classes. For each pair, the
+	 * CommandChecker's accumulateOnlyFrom method is the second class, (the
+	 * 'representing' parameter in registerClass) to restrict the class from
+	 * which commands are to be accumulated to the second (possibly abstract)
+	 * class. Then, it instantiates the first class passed, and (if it's
+	 * appropriately a Commandable) passes it the CommandChecker to its
+	 * doCommand method to accumulate the commands.
+	 */
+	public static Vector commandsFromRegisteredClasses() {
+		CommandChecker checker = new CommandChecker();
+		checker.setLIMode(true);
+		checker.setAccumulateMode(true);
+		for (int i = 0; i < registeredClasses.size(); i++) {
+			Class c = (Class) registeredClasses.elementAt(i);
+			Class representing = (Class) representingClasses.elementAt(i);
+			if (Commandable.class.isAssignableFrom(c)){
+				try {
+					checker.accumulateOnlyFrom(representing);
+					Commandable instance = (Commandable) c.newInstance();
+					checker.addString("<li>"
+							+ MesquiteModule.getShortClassName(representing)
+							+ "<ul>");
+					instance.doCommand(null, null,checker);// �
+					checker.addString("</ul>");
+				} catch (Exception e) {
+					if (c != null)
+						MesquiteMessage.println("Error getting command from " + c.getName());
+					MesquiteDialog.closeWizard();
+					MesquiteFile.throwableToLog(null, e);
+				} catch (Error e) {
+					if (c != null)
+						MesquiteMessage.println("Error getting command from " + c.getName());
+					MesquiteDialog.closeWizard();
+					MesquiteFile.throwableToLog(null, e);
+					throw e;
+				}
+			}
+		}
+		return checker.getAccumulatedExplanations();
+	}
+
+	/* ...................................................... */
+	File commandsDirectory;
+
+	String commandsPath;
+
+	Vector dutyClasses;
+
+	private boolean writeCommands = true;
+
+	public static boolean documentationComposed = false;
+
+	long progress = 0;
+
+	ProgressIndicator omp = null;
+
+	/* ...................................................... */
+	/**
+	 * Composes documentation about modules and scripting. This is done once per
+	 * run of Mesquite, the first time a call is made to show a web page.
+	 */
+	public void composeDocumentation() {
+		omp = new ProgressIndicator(null, "Composing web pages... ",
+				MesquiteTrunk.mesquiteModulesInfoVector.size(), false);
+		omp.start();
+		progress = 0;
+		omp.setCurrentValue(0);
+		documentationComposed = true;
+		commandsPath = MesquiteModule.prefsDirectory
+		+ MesquiteFile.fileSeparator + "commands"
+		+ MesquiteFile.fileSeparator;
+		commandsDirectory = new File(commandsPath);
+		if (!commandsDirectory.exists())
+			commandsDirectory.mkdir();
+
+		composeModuleListing();
+		composePuppeteerWebPage();
+
+		Vector special = CommandChecker.commandsFromRegisteredClasses();
+		String registeredHTML = " <title>Commands for other objects</title>";
+		registeredHTML += "<body bgcolor=\"#ffffcc\">";
+		registeredHTML += getNavBar("");
+		registeredHTML += "<hr><h1>Commands for other classes</h1>";
+		registeredHTML += ("<ul>");
+		for (int i = 0; i < special.size(); i++)
+			registeredHTML += ((String) special.elementAt(i));
+		registeredHTML += ("</ul>");
+		registeredHTML += ("</body>");
+		MesquiteFile.putFileContents(MesquiteModule.prefsDirectory
+				+ MesquiteFile.fileSeparator + "registered.html",
+				registeredHTML, true);
+		omp.goAway();
+		omp = null;
+
+	}
+
+	/* ...................................................... */
+	static String getNavBar(String leader) {
+		String s = "<table  width=\"137\"><tr><td><img src=\""
+			+ MesquiteFile.massageFilePathToURL(MesquiteModule
+					.getRootPath() 
+					+ "images/mesquiteIcon.gif")
+					+ "\"></td><td><table width=\"450\" border=\"1\"  cellspacing=\"1\"><tr>";
+		s += "<td align=\"center\" bgcolor=\"#f0e68c\"><a href=\""
+			+ MesquiteModule
+					.mesquiteWebSite + "\">Manual</a></td>";
+		s += "<td align=\"center\" bgcolor=\"#f0e68c\"><a href=\""
+			+ (leader + "modules.html") + "\">Modules Loaded</a></td>";
+		s += "<td align=\"center\" bgcolor=\"#f0e68c\"><a href=\""
+			+ (leader + "commands.html")
+			+ "\">Module scripting commands</a></td>";
+		s += "<td align=\"center\" bgcolor=\"#f0e68c\"><a href=\""
+			+ (leader + "puppeteer.html")
+			+ "\">General scripting commands</a></td>";
+		s += "<td align=\"center\" bgcolor=\"#f0e68c\"><a href=\""
+			+ MesquiteModule
+					.mesquiteWebSite 
+					+ "//Scripts+%26+Macros" + "\">Scripting</a></td>";
+		s += "</tr></table></td></tr></table>";
+		return s;
+	}
+
+	/* ...................................................... */
+	void composePuppeteerWebPage() {
+		CommandChecker checker = new CommandChecker();
+		checker.setAccumulateMode(true);
+		checker.setLIMode(true);
+		Puppeteer p = new Puppeteer(MesquiteTrunk.mesquiteTrunk);
+		MesquiteInteger pos = new MesquiteInteger(0);
+		p.sendCommands(null, "null", pos, ";", false, null, checker);
+		Vector commands = checker.getAccumulatedCommands();
+		Vector explanations = checker.getAccumulatedExplanations();
+		// Vector explan = checker.getAccumulatedExplanations();
+		String puppetHTML = " <title>Universal Mesquite scripting commands</title>";
+		puppetHTML += "<body bgcolor=\"#ffffcc\">";
+		puppetHTML += getNavBar("");
+		puppetHTML += "<hr><h1>Universal Mesquite scripting commands</h1>";
+		puppetHTML += ("<ul>");
+		for (int i = 0; i < explanations.size(); i++) {
+			// puppetHTML+=((String)commands.elementAt(i));
+			if (!StringUtil.blank((String) explanations.elementAt(i)))
+				puppetHTML += ((String) explanations.elementAt(i));
+		}
+		puppetHTML += ("</ul>");
+
+		puppetHTML += ("</body>");
+		MesquiteFile.putFileContents(MesquiteModule.prefsDirectory
+				+ MesquiteFile.fileSeparator + "puppeteer.html", puppetHTML,
+				true);
+	}
+
+	/* ................................................................................................................. */
+	void addToDutyClasses(Class duty) {
+		int numDuties = dutyClasses.size();
+		int found = -1;
+		for (int d = 0; d < numDuties && found != -2; d++) {
+			Class storedDuty = (Class) dutyClasses.elementAt(d);
+			if (duty == storedDuty)
+				found = -2;
+			else if (storedDuty.isAssignableFrom(duty))
+				found = d;
+			else if (duty.isAssignableFrom(storedDuty))
+				found = d - 1;
+		}
+
+		if (found == -1) // not found; add
+			dutyClasses.addElement(duty);
+		else if (found != -2) // subclass/superclass of existing
+			dutyClasses.insertElementAt(duty, found + 1);
+
+	}
+
+	/* ................................................................................................................. */
+	void composeModuleListing() {
+		dutyClasses = new Vector(50);
+		addToDutyClasses(MesquiteTrunk.class);
+		addToDutyClasses(CharacterSource.class);
+		addToDutyClasses(CharacterModelSource.class);
+		addToDutyClasses(TreeSource.class);
+
+		addToDutyClasses(FileCoordinator.class);
+		addToDutyClasses(FileInit.class);
+		addToDutyClasses(FileInterpreter.class);
+		addToDutyClasses(FileElementManager.class);
+		addToDutyClasses(ManagerAssistant.class);
+		addToDutyClasses(FileAssistant.class);
+
+		addToDutyClasses(BooleanForTree.class);
+
+		addToDutyClasses(NumberForTree.class);
+		addToDutyClasses(NumberForCharacter.class);
+		addToDutyClasses(NumberForCharAndTree.class);
+		addToDutyClasses(NumberForMatrix.class);
+		addToDutyClasses(NumberForMatrixAndTree.class);
+		addToDutyClasses(NumbersForNodes.class);
+
+		addToDutyClasses(TreeWindowMaker.class);
+		addToDutyClasses(TreeDisplayAssistant.class);
+		addToDutyClasses(TreeWindowAssistant.class);
+		addToDutyClasses(DrawTreeCoordinator.class);
+		addToDutyClasses(DrawTree.class);
+
+		addToDutyClasses(NodeLocs.class);
+		addToDutyClasses(DrawNamesTreeDisplay.class);
+
+		addToDutyClasses(TaxaWindowMaker.class);
+		addToDutyClasses(TaxaDisplayAssistant.class);
+		addToDutyClasses(TaxaWindowAssistant.class);
+		addToDutyClasses(DrawTaxaCoordinator.class);
+		addToDutyClasses(DrawTaxa.class);
+		addToDutyClasses(DrawNamesTaxaDisplay.class);
+
+		addToDutyClasses(DataWindowMaker.class);
+		addToDutyClasses(DataWindowAssistant.class);
+
+		addToDutyClasses(DrawChart.class);
+		Vector moduleListing = new Vector(300);
+		String zero = "<title>Available modules</title><body bgcolor=\"#ffffcc\">";
+		zero += getNavBar("");
+		zero += "<h2>Modules currently available in Mesquite</h2>";
+		moduleListing.addElement(zero);
+		String one = "The following modules are currently available.  Links are given to the module's manual, if one is available, and to a listing of commands the module understands. (This list is updated every time Mesquite is run.)";
+		moduleListing.addElement(one);
+
+		Vector commandsListing = new Vector(300);
+		commandsListing
+		.addElement("<title>Commands available for scripting</title><body bgcolor=\"#ffffcc\">");
+		commandsListing.addElement(getNavBar("")
+				+ "<hr><h1>Commands available for scripting</h1>");
+		commandsListing
+		.addElement("<h2>Scripting language</h2>Mesquite uses a scripting language whose specifications may be found in the <a href=\""
+				+ MesquiteModule
+						.mesquiteWebSite  
+						+ "/Scripts+%26+Macros" + "\">manual</a>.");
+		commandsListing
+		.addElement("<p>There are some <a href = puppeteer.html>universal commands</a> that can be used in the scripting language.");
+		commandsListing
+		.addElement("<p>Various objects can be scripted in Mesquite.  These include modules (whose scripting commands can be found via the list below),");
+		commandsListing
+		.addElement("and <a href = registered.html>other objects</a>.");
+		commandsListing.addElement("<h2>Commands of modules</h2><ul>");
+		commandsListing
+		.addElement("<li><a href = \"commands/mesquite.html\">Mesquite trunk module</a>");
+		ModulesInfoVector mods = MesquiteModule.mesquiteTrunk.mesquiteModulesInfoVector;
+		for (int i = 0; i < mods.size(); i++) {
+			addToDutyClasses(((MesquiteModuleInfo) mods.elementAt(i))
+					.getDutyClass());
+		}
+
+		int numDuties = dutyClasses.size();
+		Class previousDuty = null;
+		for (int d = 0; d < numDuties; d++) {
+			Class duty = (Class) dutyClasses.elementAt(d);
+			if (previousDuty == null || !previousDuty.isAssignableFrom(duty)) {
+				moduleListing.addElement("<hr><h3>"
+						+ MesquiteModule.getShortClassName(duty) + "</h3>\n");
+				previousDuty = duty;
+			} else
+				moduleListing.addElement("<h4>"
+						+ MesquiteModule.getShortClassName(duty) + "</h4>\n");
+
+			int num = mods.size();
+			MesquiteModuleInfo mbi;
+			boolean first = true;
+			for (int i = 0; i < num; i++) {
+				mbi = (MesquiteModuleInfo) mods.elementAt(i);
+				if (mbi.getDutyClass() == duty) {
+					if (first) {
+						moduleListing.addElement("Duty performed:  "
+								+ mbi.getDutyName() + "<p><ul>");
+						first = false;
+					}
+					addToManual(mbi, moduleListing, commandsListing);
+				}
+			}
+			moduleListing.addElement("</ul>");
+		}
+
+		commandsListing.addElement("</ul></body>");
+
+		MesquiteFile.putFileContents(MesquiteModule.prefsDirectory
+				+ MesquiteFile.fileSeparator + "commands.html",
+				commandsListing, true);
+		/*--------------------------------------*/
+
+		moduleListing.addElement("</ul></body>");
+		MesquiteFile.putFileContents(MesquiteModule.prefsDirectory
+				+ MesquiteFile.fileSeparator + "modules.html", moduleListing,
+				true);
+
+	}
+
+	/* ................................................................................................................. */
+	void addToManual(MesquiteModuleInfo mBI, Vector moduleListing,
+			Vector commandsListing) {
+		String gmp = (mBI.getManualPath());
+
+		Vector commands = mBI.getCommands();
+		Vector explanations = mBI.getExplanations();
+		Vector menus = mBI.getMenus();
+
+		StringBuffer commandHtml = new StringBuffer(500);
+		commandHtml.append(" <title>Module: " + mBI.getName() + "</title>");
+		commandHtml.append("<body bgcolor=\"#ffffcc\">");
+		commandHtml.append(getNavBar("../"));
+		commandHtml.append(" <h1>Module: " + mBI.getName());
+		if (gmp != null)
+			commandHtml.append(" (<a href = \""
+					+ MesquiteFile.massageFilePathToURL(mBI.getDirectoryPath()
+							+ "manual.html") + "\">manual</a>)");
+		commandHtml.append(" </h1>");
+		commandHtml.append("Full package name: "
+				+ mBI.getModuleClass().getName() + "<br>");
+		commandHtml.append("Duty: " + mBI.getDutyName() + " ("
+				+ mBI.getDutyClass().getName() + ")");
+		commandHtml.append("<hr>");
+		commandHtml.append("<h3>Module Explanation</h3>");
+		commandHtml.append(mBI.getExplanation());
+
+		commandHtml.append("<ul>");
+		if (!StringUtil.blank(mBI.getAuthors()))
+			commandHtml.append("<li>Author(s): " + mBI.getAuthors());
+		if (!StringUtil.blank(mBI.getVersion()))
+			commandHtml.append("<li>Version " + mBI.getVersion());
+		commandHtml.append("</ul>");
+		if (menus != null && menus.size() > 0) {
+			commandHtml.append("<hr><h2>Menu items of " + mBI.getName()
+					+ "</h2>");
+			commandHtml.append(("<ul>"));
+			for (int i = 0; i < menus.size(); i++)
+				commandHtml.append(("<li>" + (String) menus.elementAt(i)));
+			commandHtml.append(("</ul>"));
+		}
+		if (commands != null && commands.size() > 0) {
+			commandHtml
+			.append("<hr><h2>Commands of " + mBI.getName() + "</h2>");
+			commandHtml.append(("<ul>"));
+			for (int i = 0; i < commands.size(); i++)
+				if (!StringUtil.blank((String) commands.elementAt(i))) {
+					commandHtml
+					.append(("<li><strong>"
+							+ (String) commands.elementAt(i)
+							+ "</strong>" + (String) explanations
+							.elementAt(i)));
+				}
+			commandHtml.append(("</ul>"));
+		}
+		commandHtml.append(("</body>"));
+		MesquiteFile.putFileContents(commandsPath + mBI.getShortClassName()
+				+ ".html", commandHtml.toString(), true);
+
+		StringBuffer s = new StringBuffer(300);
+		s.append("<li><strong><font color=\"#009900\">" + mBI.getName()
+				+ "</font></strong>\n");
+		if (gmp != null)
+			s.append(" <img src = \""
+					+ MesquiteFile.massageFilePathToURL(MesquiteModule
+							.getRootPath()
+							+ "images/green-ball-small.gif") 
+							+ "\"> <a href = \""
+							+ MesquiteFile.massageFilePathToURL(mBI.getDirectoryPath()
+									+ "manual.html") + "\"> Manual </a>\n");
+
+		s.append(" <img src = \""
+				+ MesquiteFile.massageFilePathToURL(MesquiteModule
+						.getRootPath()
+						+ "images/blue-ball-small.gif")  
+						+ "\"> <a href = \""
+						+ MesquiteFile.massageFilePathToURL(commandsPath
+								+ mBI.getShortClassName() + ".html")
+								+ "\"> Information</a>\n");
+		commandsListing.addElement(" <li><a href = \""
+				+ MesquiteFile.massageFilePathToURL(commandsPath
+						+ mBI.getShortClassName() + ".html") + "\">"
+						+ mBI.getName() + "</a>\n");
+		s.append("<ul><li>" + mBI.getExplanation() + "</ul>");
+
+		moduleListing.addElement(s);
+		if (omp != null)
+			omp.setCurrentValue(++progress);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Shows the explanations of menu items and controls (Explainable Components
+	 * including tools of tool palettes) for a window. Must be passed the
+	 * parental component (typically graphics[0] of the window) and the menu bar
+	 * of the window
+	 */
+	public static void showExplanations(Component c, MenuBar mBar, String name) {
+		prepareExplanations(c, mBar, name);
+		MesquiteModule.showWebPage(MesquiteModule.prefsDirectory
+				+ MesquiteFile.fileSeparator + "tempExplanations.html", true);
+	}
+
+	private static boolean prepareExplanations(Component c, MenuBar mBar,
+			String name) {
+		String content = null;
+		CommandChecker checker = new CommandChecker();
+		if (mBar != null || c != null) {
+			if (mBar == null) {
+				content = "<title>Controls for "
+					+ name
+					+ "</title><body bgcolor=\"#ffffff\"><a name=\"top\"></a>"
+					+ getNavBar("") + "<h2>Controls for " + name + "</h2>";
+				content += "Below are listed the current controls (such as buttons) pertaining to the window "
+					+ name;
+			} else if (c == null) {
+				content = "<title>Menus for "
+					+ name
+					+ "</title><body bgcolor=\"#ffffff\"><a name=\"top\"></a>"
+					+ getNavBar("") + "<h2>Menus for " + name + "</h2>";
+				content += "Below are listed the current menus pertaining to the window "
+					+ name;
+			} else {
+				content = "<title>Menus and Controls for "
+					+ name
+					+ "</title><body bgcolor=\"#ffffff\"><a name=\"top\"></a>"
+					+ getNavBar("") + "<h2>Menus and Controls for " + name
+					+ "</h2>";
+				content += "Below are listed the current menus and controls (such as buttons) pertaining to the window "
+					+ name;
+			}
+			content += "<ul>";
+			if (c != null)
+				content += "<li><a href=\"#controls\">Controls (including buttons and tools)</a>";
+			if (mBar != null)
+				content += "<li><a href=\"#menus\">Menus</a>";
+			content += "</ul>";
+		}
+		if (c != null) {
+			content += "<hr><h2><a href=\"#top\"><img src=\""
+				+ MesquiteFile.massageFilePathToURL(MesquiteModule
+						.getRootPath() 
+						+ "images/small.top.arrow.gif")
+						+ "\"</a> <a name=\"controls\"></a>Controls (including buttons and tools)</h2>";//
+			content += getComponentExplanation(c);
+
+			content += "</ul><hr>";
+		}
+		if (mBar != null) {
+
+			// MENUS
+			content += "<hr><h2><a href=\"#top\"><img src=\""
+				+ MesquiteFile.massageFilePathToURL(MesquiteModule
+						.getRootPath() 
+						+ "images/small.top.arrow.gif")
+						+ "\"</a> <a name=\"menus\"></a>Menus</h2>";//
+			for (int i = 0; i < mBar.getMenuCount(); i++) {
+				Menu menu = mBar.getMenu(i);
+				content += "<hr><h4>" + menu.getLabel() + "</h4>"
+				+ StringUtil.lineEnding()
+				+ getItemExplanation(mBar.getMenu(i), checker, false, false);
+			}
+		}
+		if (content != null) {
+			content += "</body>";
+			MesquiteFile.putFileContents(MesquiteModule.prefsDirectory
+					+ MesquiteFile.fileSeparator + "tempExplanations.html",
+					content, true);
+			return true;
+		}
+		return false;
+	}
+
+	private static String getComponentExplanation(Component c) {
+		String s = "";
+		if (c instanceof Explainable && c instanceof ImageOwner) {
+			s += "<li><img src = \""
+				+ MesquiteFile.massageFilePathToURL(((ImageOwner) c)
+						.getImagePath()) + "\"> ";
+			s += ((Explainable) c).getExplanation();
+		}
+		if (c instanceof Container) {
+			Component[] cs = ((Container) c).getComponents();
+			if (cs != null)
+				for (int i = 0; i < cs.length; i++)
+					s += getComponentExplanation(cs[i]);
+		}
+		return s;
+	}
+
+	private static String getModuleReference(long id) {
+		if (id == 0)
+			return "";
+		String ex = "<font color=\"#808080\"> (for module ";
+		MesquiteModule mb = MesquiteTrunk.mesquiteTrunk
+		.findEmployeeWithIDNumber(id);
+		if (mb == null)
+			ex += "id#" + id + ")</font>";
+		else {
+			String gmp = MesquiteFile.massageFilePathToURL(mb.getManualPath());
+			if (gmp == null)
+				gmp = "";
+			else
+				gmp = " (<a href = \"" + gmp + "\">[manual]</a>)";
+			String gcp = MesquiteFile.massageFilePathToURL(mb
+					.getCommandPagePath());
+			if (StringUtil.blank(gcp))
+				ex += "\'" + mb.getName() + "\'" + gmp + ")</font>";
+			else
+				ex += "\'<a href =\"" + gcp + "\">" + mb.getName() + "</a>\'"
+				+ gmp + ")</font>";
+
+		}
+		return ex;
+	}
+
+	public static String getItemExplanation(MenuItem item,
+			CommandChecker checker, boolean label, boolean suppressCommandName) {
+		if (item == null)
+			return null;
+		if (item instanceof MesquiteMenuItem
+				&& !((MesquiteMenuItem) item).getDocument())
+			return null;
+		String ex = "";
+		if (item instanceof MesquiteMenuItem) {
+			MesquiteMenuItem mmi = (MesquiteMenuItem) item;
+			if (mmi.getCommand() != null) {
+				if (label)
+					ex += "<li><b>" + item.getLabel() + "</b>";
+				long id = mmi.getOwnerModuleID();
+				ex += getModuleReference(id);
+				if (!suppressCommandName){
+					ex += " <font color=\"#808080\">(command: "
+					+ mmi.getCommand().getName() + ")</font>";
+				}
+				String expl = CommandChecker.getCommandExplanation(mmi
+						.getCommand(), checker, false);
+				Object ref = null;
+				if ((ref = mmi.getReferent()) != null) {
+					String e = "";
+					if (ref instanceof Listable && ref instanceof Explainable)
+						e += ".  Uses: " + ((Listable) ref).getName() + " ("
+						+ ((Explainable) ref).getExplanation() + ")";
+					else if (ref instanceof Listable)
+						e += ".  Uses: " + ((Listable) ref).getName();
+					else if (ref instanceof Explainable)
+						e += "(" + ((Explainable) ref).getExplanation() + ")";
+					if (e.length() > 0) {
+						if (expl == null)
+							expl = e;
+						else if (expl.endsWith("</ul>")) {
+							StringBuffer sp = new StringBuffer(expl);
+							sp.insert(expl.length() - 5, e);
+							expl = sp.toString();
+						} else {
+							expl += e;
+						}
+					}
+
+				}
+				if (!StringUtil.blank(expl))
+					ex += "<font color=\"#FF0000\">" + expl + "</font>";
+			}
+		} else if (item instanceof MesquiteSubmenu) {
+			if (label)
+				ex += "<li><b>" + item.getLabel() + "</b>";
+			MesquiteSubmenu mmi = (MesquiteSubmenu) item;
+			long id = mmi.getOwnerModuleID();
+			ex += getModuleReference(id);
+			if (mmi.getCommand() != null)
+				ex += "<font color=\"#808080\"> (command: "
+					+ mmi.getCommand().getName() + ")</font>";
+		} else if (label) {
+			if (!("-".equals(item.getLabel())))
+				ex += "<li><b>" + item.getLabel() + "</b>";
+		}
+		ex += StringUtil.lineEnding();
+		if (item instanceof Menu) {
+			Menu menu = ((Menu) item);
+			String iex = "";
+			for (int i = 0; i < menu.getItemCount(); i++) {
+				String ix = getItemExplanation(menu.getItem(i), checker, true, false);
+				if (!StringUtil.blank(ix))
+					iex += ix;
+			}
+			if (!StringUtil.blank(iex))
+				ex += "<ul>" + StringUtil.lineEnding() + iex + "</ul>"
+				+ StringUtil.lineEnding();
+		}
+		return ex;
+	}
+}
+
diff --git a/Source/mesquite/lib/CommandCommunicator.java b/Source/mesquite/lib/CommandCommunicator.java
new file mode 100644
index 0000000..8716f66
--- /dev/null
+++ b/Source/mesquite/lib/CommandCommunicator.java
@@ -0,0 +1,592 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import java.io.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** An object that sends commands; for use in console input (e.g., ConsoleWindow, ConsoleThread). */
+public class CommandCommunicator {
+	Puppeteer puppeteer;
+	Object objectCommanded = null;
+	File currentDirectory = null;
+	//Object previousObject = null;
+	Vector previousObjects = new Vector();
+	Vector previousUseQueues = new Vector();
+
+	Object result;
+	boolean echoToSystemOut;
+	boolean done = false;
+	boolean captureLog = false;
+	boolean suppressPrompt = false;
+	//boolean previousUseQueue = true;
+	boolean useQueue = true;
+
+	public CommandCommunicator(MesquiteModule module, Object initCommanded, boolean echoToSystemOut){
+		puppeteer = new Puppeteer(module);
+		setObjectCommanded(initCommanded, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+		this.echoToSystemOut = echoToSystemOut;
+		if (MesquiteTrunk.suggestedDirectory!=null)
+			currentDirectory = new File(MesquiteTrunk.suggestedDirectory);
+	}
+	public void setObjectCommanded(Object obj, boolean useQueue, boolean showPrompt){
+		if (obj == null)
+			return;
+		previousObjects.addElement(objectCommanded);
+		previousUseQueues.addElement(new MesquiteBoolean(useQueue));
+		//previousObject = objectCommanded;
+		objectCommanded = obj;
+		//previousUseQueue = this.useQueue;
+		this.useQueue = useQueue;
+		
+		if (showPrompt)
+			showPrompt();
+
+	}
+	public void releaseObjectCommanded(Object objectReleased, boolean showPrompt){
+		int num = previousObjects.size();
+
+		int i = previousObjects.indexOf(objectReleased);
+		if (i>=0){
+			previousObjects.removeElement(objectReleased);
+			previousUseQueues.removeElementAt(i);
+			num = previousObjects.size();
+			objectCommanded = previousObjects.elementAt(num-1);
+			useQueue = ((MesquiteBoolean)previousUseQueues.elementAt(num-1)).getValue();
+		}
+		else {
+			objectCommanded = MesquiteTrunk.mesquiteTrunk;
+			useQueue = true;
+		}
+
+		if (showPrompt)
+			showPrompt();
+	}
+	private void revertToPreviousObjectCommanded(boolean showPrompt){
+		int num = previousObjects.size();
+		if (num>0){
+			objectCommanded = previousObjects.elementAt(num-1);
+			useQueue = ((MesquiteBoolean)previousUseQueues.elementAt(num-1)).getValue();
+			previousObjects.removeElementAt(num-1);
+			previousUseQueues.removeElementAt(num-1);
+		}
+		else {
+			objectCommanded = MesquiteTrunk.mesquiteTrunk;
+			useQueue = true;
+		}
+
+		if (showPrompt)
+			showPrompt();
+	}
+	public void setCaptureLog(boolean capt){
+		captureLog = capt;
+	}
+	public void setSuppressPrompt(boolean s){
+		suppressPrompt = s;
+	}
+	String objectName(Object obj){
+		if (obj == null)
+			return "no object";
+		else if (obj instanceof Listable) {
+			if (obj instanceof MesquiteWindow)
+				return "Window: " + ((Listable)obj).getName();
+			else
+				return ((Listable)obj).getName();
+		}
+		else
+			return obj.getClass().getName();
+	}
+	private void write(String s){
+		if (echoToSystemOut)
+			MesquiteTrunk.mesquiteTrunk.log(s);
+		else
+			MesquiteTrunk.mesquiteTrunk.logNoEcho(s); //here use nonechoversion
+	}
+	private String append(String s, String t){
+		if (s == null)
+			return t;
+		if (t == null)
+			return s;
+		return s + t;
+	}
+	//THIS SHOULD NOT BE CALLED ON MAIN EVENT THREAD, as it sleeps until answer returned
+	public void enterTyped(String commandLine){
+		write(enterInput(commandLine));
+	}
+
+	//THIS SHOULD NOT BE CALLED ON MAIN EVENT THREAD, as it sleeps until answer returned
+	public String enterInput(String commandLine){
+		String output = "\n";
+		if (commandLine == null) {
+			output += getPrompt();
+			return output;
+		}
+		MesquiteInteger pos = new MesquiteInteger(0);
+		String command = ParseUtil.getToken(commandLine, pos);
+		String arguments = commandLine.substring(pos.getValue(), commandLine.length());
+		if (arguments !=null){
+			arguments = StringUtil.stripTrailingWhitespace(arguments);
+			if (arguments.length() == 0)
+				arguments = null;
+			else if (arguments.charAt(arguments.length()-1) == ';')
+				arguments = arguments.substring(0, arguments.length()-1);
+			if (arguments !=null && ";".equals(arguments))
+				arguments = null;
+			if (arguments !=null && arguments.length() == 0)
+				arguments = null;
+		}
+		if ("who".equalsIgnoreCase(command)) {
+			output += ("Object being commanded: " + objectName(objectCommanded) + "\n");
+		}
+		else if ("help".equalsIgnoreCase(command)) { //console help
+//			*****put all of these here at this level as asynchronous
+//			***** make commands to window and module different (window:)
+//			***** put console window listing on other thread
+//			***** single line commands send to command, not puppetter
+			output += ("\nConsole mode commands:\n");
+			output += ("who  - indicates what is currently commanded object\n");
+			output += ("?    -show commands of currently commanded object (equivalently, sc)\n");
+			output += ("??    -show commands of currently commanded object, with explanations\n");
+			output += ("? <name of command>    -show explanation for that command of currently commanded object\n");
+			output += ("..    - if MesquiteModule, command employer module instead; if window, command its owner module instead\n");
+			output += (">    - command the returned object\n");
+			output += ("<    - command the previously commanded object\n");
+			output += ("mesquite  - command root module of Mesquite\n");
+			output += ("ssf <filename>    - send script file to object commanded\n");
+			output += ("se    - show immediate employee modules (command to be given to module)\n");
+			output += ("ge  <number>  - shift command to employee module, numbered as from command se\n");
+			output += ("gr  - shift command to employer module\n");
+			output += ("etree    - show employee tree (command to be given to module)\n");
+			output += ("jet  <number>  - jump to employee module, numbered as from command etree\n");
+			output += ("gm  - shift command to module owning the window (command to be given to window)\n");
+			output += ("gw  - shift command to window belonging to module (command to be given to module)\n");
+			output += ("sw  - list current windows\n");
+			output += ("jw  <number> - jump to window, numbered as from command sw\n");
+			output += ("menus - show menus of current window (window related to object commanded)\n");
+			output += ("menu <number> - command given menu of current window (window related to object commanded)\n");
+			output += ("text  - show text version of window (command to be given to window)\n");
+			output += ("sb  - show buttons of any dialog up front\n");
+			output += ("press <buttonName>  - press buttons of any dialog up front\n");
+			output += ("cd  - show current directory.  The current directory is to explore contents of disk, and as default for openFile command.\n");
+			output += ("cd ..  - change directory to parent\n");
+			output += ("cd <directoryPath>  - change directory to path\n");
+			output += ("ls  - list contents of current directory\n");
+			output += ("po  - list previous objects commanded\n");
+			//ALSO needed: "tell"
+		} 
+		else if ("ssf".equalsIgnoreCase(command)) {
+			MesquiteProject project = null;
+			MesquiteModule module = MesquiteTrunk.mesquiteTrunk;
+
+			if (objectCommanded instanceof MesquiteModule) 
+				project = ((MesquiteModule)objectCommanded).getProject();
+			else if (objectCommanded instanceof FileElement)
+				project = ((FileElement)objectCommanded).getProject();
+			else if (objectCommanded instanceof Component) {
+				MesquiteWindow w= MesquiteWindow.windowOfItem((Component)objectCommanded);
+				if (w != null && w.getOwnerModule() != null)
+					project = w.getOwnerModule().getProject();
+			}
+			else if (objectCommanded instanceof MesquiteWindow) {
+				MesquiteWindow w= (MesquiteWindow)objectCommanded;
+				if (w != null && w.getOwnerModule() != null)
+					project = w.getOwnerModule().getProject();
+			}
+			String script = null;
+			if (project != null) {
+				script = MesquiteFile.getFileContentsAsString(MesquiteFile.composePath(project.getHomeDirectoryName(), arguments));
+				module = project.getCoordinatorModule();
+			}
+			else
+				script = MesquiteFile.getFileContentsAsString(arguments);
+			if (!StringUtil.blank(script)){
+				Puppeteer puppeteer = new Puppeteer(module);
+				puppeteer.execute(objectCommanded, script, new MesquiteInteger(0), null, false);
+			}
+
+
+		}
+		else if ("po".equalsIgnoreCase(command)) {
+
+			for (int i=0; i<previousObjects.size(); i++) {
+				output += ("  " + i + "  --  " + previousObjects.elementAt(i) +"\n");
+			}
+		}
+		else if ("se".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+				output += ("Employee Modules of " + mb.getName() +"\n");
+				for (int i=0; i<mb.getEmployeeVector().size(); i++) {
+					MesquiteModule mbb = (MesquiteModule)mb.getEmployeeVector().elementAt(i);
+					output += ("  " + i + "  --  " + mbb.getName() +"\n");
+				}
+			}
+			else
+				output += ("The se command can be given only to modules");
+		}
+		else if ("cd".equalsIgnoreCase(command)) {
+			if (MesquiteTrunk.suggestedDirectory!=null)
+				currentDirectory = new File(MesquiteTrunk.suggestedDirectory);
+
+			if ("..".equals(arguments)) {
+				if (currentDirectory !=null) {
+					currentDirectory = new File(currentDirectory.getParent());
+					MesquiteTrunk.suggestedDirectory = currentDirectory.toString();
+				}
+			}
+			else if (!StringUtil.blank(arguments)){
+				File cd = new File(arguments);
+				if (cd.exists() && cd.isDirectory())
+					currentDirectory = cd;
+				else if (currentDirectory !=null) {
+					cd = new File(currentDirectory + MesquiteFile.fileSeparator + arguments);
+					if (cd.exists() && cd.isDirectory())
+						currentDirectory = cd;
+				}
+				MesquiteTrunk.suggestedDirectory = currentDirectory.toString();
+			}
+
+			output += ("Current directory: " + currentDirectory);
+			if (MesquiteFileDialog.currentFileDialog != null)
+				MesquiteFileDialog.currentFileDialog.setDirectory(currentDirectory.toString());
+		}
+		else if ("ls".equalsIgnoreCase(command)) {
+			if (MesquiteTrunk.suggestedDirectory!=null && currentDirectory == null)
+				currentDirectory = new File(MesquiteTrunk.suggestedDirectory);
+			if (currentDirectory !=null && currentDirectory.exists() && currentDirectory.isDirectory()){
+				String[] list = currentDirectory.list();
+				for (int i=0; i<list.length; i++) {
+					if (i % 3 == 1)
+						output += (list[i] +"\n");
+					else if (i % 3 == 0)
+						output += ("\t" + list[i] +"\n");
+					else
+						output += ("\t" + list[i]);
+				}
+			}
+		}
+		else if ("sw".equalsIgnoreCase(command)) {
+			ListableVector w = MesquiteTrunk.windowVector;
+			if (w == null || w.size() == 0)
+				output += ("There are no windows showing");
+			else {
+				output += ("Current Windows:\n");
+				for (int i=0; i<w.size(); i++) {
+					MesquiteWindow mbb = (MesquiteWindow)w.elementAt(i);
+					output += ("  " + i + "  --  " + mbb.getName() +"\n");
+				}
+			}
+		}
+		else if ("mesquite".equalsIgnoreCase(command)) {
+			setObjectCommanded(MesquiteTrunk.mesquiteTrunk, useQueue, false);
+		}
+		else if ("tellIt".equalsIgnoreCase(command)) {
+			setObjectCommanded(result, useQueue, false);
+		}
+		else if ("jw".equalsIgnoreCase(command)) {
+			int i = MesquiteInteger.fromString(arguments);
+			ListableVector w = MesquiteTrunk.windowVector;
+			if (w == null || w.size() == 0)
+				output += ("There are no windows showing");
+			else if (i< w.size() && MesquiteInteger.isCombinable(i)){
+				setObjectCommanded(w.elementAt(i), useQueue, false);
+			}
+			else {
+				output += "To jump to a window, you need to enter its number\n(see numbers by entering sw)";
+			}
+		}
+		else if ("menus".equalsIgnoreCase(command)) {
+			MenuBar menus = getMenuBar(objectCommanded);
+			if (menus !=null){
+				for (int i= 0; i<menus.getMenuCount(); i++){
+					Menu menu = menus.getMenu(i);
+					output += ("  " + (i+1) + "  --  " + menu.getLabel() +"\n");
+				}
+				output += "\nEnter  \"menu i\" to select the i'th menu\n";
+			}
+
+		}
+		else if ("menu".equalsIgnoreCase(command)) {
+			MenuBar menus = getMenuBar(objectCommanded);
+			if (menus !=null){
+				MesquiteInteger poss = new MesquiteInteger();
+				int i = MesquiteInteger.fromFirstToken(arguments, poss);
+				if (MesquiteInteger.isCombinable(i))
+					i--;
+				if (i>=0 && i<menus.getMenuCount() && menus.getMenu(i) instanceof MesquiteMenu){
+					((MesquiteMenu)menus.getMenu(i)).listItems();
+					setObjectCommanded(menus.getMenu(i), MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+				}
+
+			}
+
+		}
+		else if ("sb".equalsIgnoreCase(command)) {
+			ListableVector d = MesquiteModule.mesquiteTrunk.dialogVector;
+
+			if (d!=null && d.size()>0) {
+				Object obj = d.elementAt(d.size()-1);
+				if (obj !=null && obj instanceof MesquiteDialog){
+					MesquiteDialog dlog = (MesquiteDialog)obj;
+					Vector v = new Vector();
+					dlog.getButtons(dlog,  v);
+					if (v.size()==0)
+						output += ("There are no buttons");
+					else {
+						output += ("Buttons of dialog (to use type \"press buttonName\"):\n");
+						for (int i= 0; i< v.size(); i++){
+							output += ("(" + (String)v.elementAt(i) + ") ");
+						}
+						output += ("\n");
+					}
+				}
+			}
+			else
+				output += ("There are no dialog boxes being shown at the moment.\n");
+		}
+		else if ("press".equalsIgnoreCase(command)) {
+			ListableVector d = MesquiteModule.mesquiteTrunk.dialogVector;
+
+			if (d!=null && d.size()>0) {
+				Object obj = d.elementAt(d.size()-1);
+				if (obj !=null && obj instanceof MesquiteDialog){
+					MesquiteDialog dlog = (MesquiteDialog)obj;
+					dlog.selectButton(arguments);
+				}
+			}
+			else
+				output += ("There are no dialog boxes being shown at the moment.\n");
+		}
+		else if ("etree".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+				output += ("Employee Tree of " + mb.getName() + "  use jet <number> to jump to command that employee\n" + mb.listEmployees("  ", new MesquiteInteger(0)) + "\n");
+			}
+			else
+				output += ("The etree command can be given only to modules");
+		}
+		else if ("jet".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+				int i = MesquiteInteger.fromString(arguments);
+				if (MesquiteInteger.isCombinable(i)) {
+					Object r = mb.getDeepEmployee(i, new MesquiteInteger(0));
+					if (r !=null) {
+						setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+					}
+				}
+			}
+			else
+				output += ("The jet command can be given only to modules");
+		}
+		else if ("ge".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+				int i = MesquiteInteger.fromString(arguments);
+				if (MesquiteInteger.isCombinable(i) && i>=0 && i<mb.getEmployeeVector().size()) {
+					Object r = mb.getEmployeeVector().elementAt(i);
+					if (r !=null) {
+						setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+					}
+				}
+			}
+			else
+				output += ("The ge command can be given only to modules");
+		}
+		else if ("gr".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+						setObjectCommanded(mb.getEmployer(), MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+			}
+			else
+				output += ("The gr command can be given only to modules");
+		}
+		else if ("gw".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteModule){
+				MesquiteModule mb = (MesquiteModule)objectCommanded;
+				Object r = mb.getModuleWindow();
+				if (r !=null) {
+					setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+				}
+
+			}
+			else
+				output += ("The gw command can be given only to modules");
+		}
+		else if ("gm".equalsIgnoreCase(command)) {
+			if (objectCommanded instanceof MesquiteWindow){
+				MesquiteWindow w = (MesquiteWindow)objectCommanded;
+				MesquiteModule r = w.getOwnerModule();
+				if (r !=null) {
+					setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+				}
+
+			}
+			else
+				output += ("The gm command can be given only to windows");
+		}
+		else if (">".equalsIgnoreCase(command)) { 
+			if (result != null) {
+				setObjectCommanded(result, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+
+			}
+		}
+		else if ("<".equalsIgnoreCase(command)) { 
+			revertToPreviousObjectCommanded(false);
+		}
+		else if ("..".equalsIgnoreCase(command)) { 
+			Object r = null;
+			if (objectCommanded instanceof MesquiteModule) {
+				r = ((MesquiteModule)objectCommanded).getEmployer();
+				if (r !=null){
+					setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+				}
+			}
+			else if (objectCommanded instanceof MesquiteWindow){
+				r = ((MesquiteWindow)objectCommanded).getOwnerModule();
+				if (r !=null){
+					setObjectCommanded(r, MesquiteWindow.GUIavailable && !MesquiteWindow.suppressAllWindows, false);
+				}
+			}
+		}
+		else if ("reportCrash".equalsIgnoreCase(command)) {
+		//	MesquiteTrunk.mesquiteTrunk.reportCrashToHome(new NullPointerException(),  "Reporting to home");
+			MesquiteCommand c = new MesquiteCommand("crash", MesquiteTrunk.mesquiteTrunk);
+			c.doItMainThread(null, null, null);
+		//	PendingCommand pc = new PendingCommand(this,  puppeteer, MesquiteTrunk.mesquiteTrunk, "crash", false);
+		//	MainThread.pendingCommands.addElement(pc, false);
+		}
+		else if (!StringUtil.blank(commandLine)) {
+			boolean useQueueHere = useQueue;
+			boolean dontSleep = false;
+			if ("exit".equalsIgnoreCase(command) || "quit".equalsIgnoreCase(command)){
+				setObjectCommanded(MesquiteTrunk.mesquiteTrunk, useQueue, false);
+				dontSleep = true;
+				useQueueHere = true;
+				
+		}
+			String c = StringUtil.stripTrailingWhitespace(commandLine);
+			if (c.length()>0 && c.charAt(c.length()-1) != ';')
+				c += ";";
+			done = false;
+			if (useQueueHere){
+
+				//HERE set up Pending command and put it on command queue
+				PendingCommand pc = new PendingCommand(this,  puppeteer, objectCommanded, c, false);
+				pc.logRequestFocus = true;
+				pc.setFromCommandLine(true);
+				if (captureLog) {
+					resultBuffer.setLength(0);
+					pc.setEchoToCommunicator(true);
+				}
+				MainThread.pendingCommands.addElement(pc, false);
+				//then sleep inutil Pending command calls back commandDone method of this CommandCommunicator with an object reutrned;
+				if (!dontSleep){
+					try {
+					while (!done)
+						Thread.sleep(20);
+				}
+				catch (InterruptedException e){
+				}
+				}
+			}
+			else {				
+				if (objectCommanded instanceof Commandable){
+					Puppeteer p = new Puppeteer(MesquiteTrunk.mesquiteTrunk);
+					CommandRecord prev = MesquiteThread.getCurrentCommandRecord();
+					CommandRecord cRec = new CommandRecord(false);
+					MesquiteThread.setCurrentCommandRecord(cRec);
+					p.execute(objectCommanded, c, new MesquiteInteger(0), null, false, null, null);
+					MesquiteThread.setCurrentCommandRecord(prev);
+					MesquiteTrunk.requestLogFocus();
+				}
+				done = true;
+			}
+			if (result instanceof Commandable)
+				output += ("    [> " + objectName(result) + " ]");
+			else {
+				if (result instanceof String)
+					output += ("    [ result: " + result + " ]");
+				else 
+					output += ("    [ result: " + result + " ]");
+				result = null;
+			}
+			if (captureLog) {
+				output += resultBuffer.toString();
+				resultBuffer.setLength(0);
+			}
+		}
+		output += getPrompt();
+		return output;
+
+	}
+	/*------------*/
+	StringBuffer resultBuffer = new StringBuffer(100);
+	public void log(String s){
+		if (s != null)
+			resultBuffer.append(s);
+	}
+	public void logln(String s){
+		if (s != null)
+			resultBuffer.append(s);
+		resultBuffer.append('\n');
+	}
+	private MenuBar getMenuBar(Object objectCommanded){
+		MesquiteWindow w= null;
+		if (objectCommanded instanceof MesquiteWindow)
+			w = (MesquiteWindow)objectCommanded;
+		else if (objectCommanded instanceof MesquiteModule) {
+			MesquiteWindow f = ((MesquiteModule)objectCommanded).containerOfModule();
+			if (f instanceof MesquiteWindow)
+				w = (MesquiteWindow)f;
+		}
+		else if (objectCommanded instanceof OwnedByModule){
+			MesquiteModule mb = ((OwnedByModule)objectCommanded).getOwnerModule();
+			if (mb !=null) {
+				MesquiteWindow f = mb.containerOfModule();
+				if (f instanceof MesquiteWindow)
+					w = (MesquiteWindow)f;
+			}
+		}
+		if (w == null)
+			return null;
+		MenuBar menus = w.getMenuBar();
+		return menus;
+	}
+	public void commandDone(Object returned){
+		result = returned;
+		done = true;
+	}
+	public String getPrompt(){
+
+		if (suppressPrompt)
+			return "\n";
+		return ("\n(" + objectName(objectCommanded) + ") # ");
+	}
+	public void showPrompt(){
+		write(getPrompt());
+	}
+}
+
diff --git a/Source/mesquite/lib/CommandRecord.java b/Source/mesquite/lib/CommandRecord.java
new file mode 100644
index 0000000..918b528
--- /dev/null
+++ b/Source/mesquite/lib/CommandRecord.java
@@ -0,0 +1,389 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls */
+
+public class CommandRecord extends Listened {
+	public static CommandRecord nonscriptingRecord;
+	public static CommandRecord scriptingRecord;
+	public static CommandRecord macroRecord; 
+	public static CommandRecord dialogRecord;
+	private static boolean checkThread = false;
+	Listable canceller = null;
+	Thread thread;
+	public static long numInstances =0; 
+	long id = 0; 
+	private boolean warnModuleNotFound = true;  
+	private boolean warnObjectToldNull = true;
+	private boolean emergencyRehire = false;
+	private boolean cancelled = false;
+	private boolean errorFound = false;
+	private boolean isScripting = false;
+	private MesquiteFile scriptingFile = null;
+	private boolean isMacro = false;
+	private long clock = 0;
+	ProgressIndicator progressIndicator;
+	String progressNote = "";
+	private boolean fromCommandLine = false;
+	MesquiteDialogParent wizard;
+	boolean wizEstablish = false;
+	Vector hiringPath = null;
+	public static CommandRecord nr = null;
+	static {
+		dialogRecord = new CommandRecord((MesquiteThread)null, false);
+		//dialogRecord.requestEstablishWizard(MesquiteDialog.useWizards);
+		nonscriptingRecord = new CommandRecord((MesquiteThread)null, false);
+		scriptingRecord = new CommandRecord((MesquiteThread)null, true);
+		macroRecord = new CommandRecord((MesquiteThread)null, true);
+		macroRecord.isMacro = true;
+	}
+
+	public CommandRecord(boolean scripting) { 
+		id = numInstances++; 
+		this.isScripting = scripting;
+	}
+	public CommandRecord(Thread thread, boolean scripting) {
+		id = numInstances++; 
+		this.isScripting = scripting;
+		this.thread = thread;
+	}
+	public static CommandRecord getRecNSIfNull(){
+		return MesquiteThread.getCurrentCommandRecordDefIfNull(CommandRecord.nonscriptingRecord);
+	}
+	public static CommandRecord getRecSIfNull(){
+		return MesquiteThread.getCurrentCommandRecordDefIfNull(CommandRecord.scriptingRecord);
+	}
+	public static CommandRecord getRecDIfNull(){
+		return MesquiteThread.getCurrentCommandRecordDefIfNull(CommandRecord.dialogRecord);
+	}
+	public String toString(){
+		String s = "Command Record " + getID();
+		s += " (scripting: " + isScripting + ") ";
+		if (thread != null){
+			s += " for thread " + thread;
+			if (thread instanceof MesquiteThread)
+				s +=  " id " +  ((MesquiteThread)thread).getID();
+		}
+		s += " [establish wizard " + wizEstablish + "]";
+		return s;
+	}
+	public static boolean wizardInEffect(){
+		CommandRecord rec =  getRecDIfNull();
+		return (rec.getWizard() != null || rec.establishWizard());
+
+	}
+	/*boolean commandInProgress = false;
+	public void setInScriptingCommand(boolean i){
+		commandInProgress = i;
+	}
+	public boolean inScriptingCommand(){
+		if (!recordIsScripting())
+			return false;
+		return commandInProgress;
+	}
+*/
+	public MesquiteDialogParent getWizard(){
+		if (wizard != null && wizard.alreadyDisposed)  //just in case no one told me
+			wizard = null;
+		return wizard;
+	}
+	public void setWizard(MesquiteDialogParent w){
+		MesquiteDialog.currentWizard = w;
+		wizard = w;
+	}
+	
+	public boolean establishWizard(){
+		return wizEstablish;
+	}
+
+	public void requestEstablishWizard(boolean e){
+		wizEstablish = e;
+	}
+	boolean tempWizEstablish = false;
+	//called if wizard requested until PendingCommand done
+	public void requestEstablishWizardTemp(boolean e){
+		wizEstablish = e;
+		tempWizEstablish = e;
+	}
+	public boolean tempWizardWasEstablished(){
+		return tempWizEstablish;
+	}
+
+	public long getTicks(){
+		return clock;
+	}
+	public static void setHiringPathS(Vector path){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null){
+			if (MesquiteTrunk.debugMode)
+			MesquiteMessage.println("setHiringPath when no commandrecord attached to thread");
+		}
+		else
+			cr.setHiringPath(path);
+	}
+	public void setHiringPath(Vector path){
+		hiringPath = path;
+	}
+	public static Vector getHiringPathS(){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null){
+			if (MesquiteTrunk.debugMode && MesquiteTrunk.startupShutdownThread != Thread.currentThread())
+			MesquiteMessage.println("getHiringPath when no commandrecord attached to thread");
+			return null;
+		}
+		else
+			return cr.getHiringPath();
+	}
+	private Vector getHiringPath(){
+		return hiringPath;
+	}
+	public static void dumpHiringPathS(String s){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null){
+			if (MesquiteTrunk.debugMode)
+			MesquiteMessage.println("dumpHiringPathS when no commandrecord attached to thread");
+		}
+		else
+			cr.dumpHiringPath(s);
+	}
+	private void dumpHiringPath(String s){
+		if (hiringPath ==null){
+			System.out.println(s + "NO HIRING PATH WITH CommandRecord");
+			return;
+		}
+		System.out.println(s + "HIRING PATH WITH CommandRecord");
+		String space = "<<==  ";
+		for (int i= 0; i<hiringPath.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)hiringPath.elementAt(i);
+			System.out.println(space + mmi.getClassName());
+			space += "  ";
+		}
+	}
+
+	CommandCommunicator echoComm = null;
+	public void setEchoCommunicator(CommandCommunicator c){
+		echoComm = c;
+	}
+	public CommandCommunicator getEchoCommunicator(){
+		return echoComm;
+	}
+	public void tickThisRecord(String progressNote){
+		
+		clock++;
+		this.progressNote = progressNote;
+		MesquiteWindow.tickClock(progressNote);
+		if (thread !=null && thread instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)thread;
+			ProgressIndicator pi = mt.getProgressIndicator();
+			if (pi !=null) {
+				String commandNote = "";
+				if (!StringUtil.blank(progressNote))
+					commandNote = progressNote + "\n";
+				else
+					commandNote = "";
+				pi.setSecondaryMessage(commandNote);
+				pi.setText(commandNote, false);
+			}
+		}
+	}
+	public static void tick(String progressNote){
+		
+	
+		MesquiteWindow.tickClock(progressNote);
+		Thread thread = Thread.currentThread();
+		if (thread.isInterrupted()){
+//			MesquiteMessage.println("\n\nThe following exception is thrown intentionally to show where the thread was interrupted; it does not mean necessarily there "
+//					+ " a bug in the code.");
+			//MesquiteInteger i = null;
+			//i.setValue("0"); // to generate a null pointer exception
+		}
+		if (thread !=null && thread instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)thread;
+			ProgressIndicator pi = mt.getProgressIndicator();
+			if (pi !=null) {
+				String commandNote = "";
+				if (!StringUtil.blank(progressNote))
+					commandNote = progressNote + "\n";
+				else
+					commandNote = "";
+				pi.setSecondaryMessage(commandNote);
+				pi.setText(commandNote, false);
+			}
+		}
+	}
+	public static void incrementProgress(){
+		
+		
+		Thread thread = Thread.currentThread();
+		if (thread.isInterrupted()){
+//			MesquiteMessage.println("\n\nThe following exception is thrown intentionally to show where the thread was interrupted; it does not mean necessarily there "
+//					+ " a bug in the code.");
+			MesquiteInteger i = null;
+			i.setValue("0"); // to generate a null pointer exception
+		}
+		if (thread !=null && thread instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)thread;
+			ProgressIndicator pi = mt.getProgressIndicator();
+			if (pi !=null) {
+				pi.increment();
+			}
+		}
+	}
+
+	public void setProgressIndicator(ProgressIndicator pi){
+		this.progressIndicator = pi;
+	}
+	public ProgressIndicator getProgressIndicator(){
+		return progressIndicator;
+	}
+
+	
+	public String getProgressNote(){
+		return progressNote;
+	}
+
+	public long getID(){
+		return id;
+	}
+
+
+	public void setScriptingFile(MesquiteFile file){
+		scriptingFile = file;
+	}
+	public  MesquiteFile getScriptingFile(){
+		return scriptingFile;
+	}
+	
+	public static void setScriptingFileS(MesquiteFile file){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null){
+			if (MesquiteTrunk.debugMode)
+			MesquiteMessage.printStackTrace("setScriptingFileS when no commandrecord attached to thread");
+		}
+		else
+			cr.scriptingFile = file;
+	}
+
+	public static MesquiteFile getScriptingFileS(){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null){
+			if (MesquiteTrunk.debugMode)
+			MesquiteMessage.printStackTrace("getScriptingFileS when no commandrecord attached to thread");
+		}
+		else
+			return cr.scriptingFile;
+		return null;
+	}
+	
+	public boolean recordIsScripting(){
+		return isScripting;
+	}
+	/*
+	public static boolean threadIsScripting(){
+		Thread mt = Thread.currentThread();
+		if (mt instanceof MesquiteThread) {
+			CommandRecord pi = ((MesquiteThread)mt).getCommandRecord();
+			if (pi !=null)
+				return pi.scripting();
+		}
+		return false;
+	}
+	*/
+	public void setScripting(boolean s){
+		isScripting = s;
+	}
+
+	public void setFromCommandLine(boolean s){
+		fromCommandLine = s;
+	}
+	public boolean isFromCommandLine(){
+		return fromCommandLine;
+	}
+	/*&& clean out non-static references &&*/
+	public void setMacro(boolean m){ 
+		if (this == scriptingRecord || this == nonscriptingRecord)
+			return;
+		isMacro = m;
+	}
+	/*&& clean out non-static references &&*/
+	public static boolean macro(){ 
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr == null)
+			return false;
+		return cr.isMacro;
+	}
+	/*&& clean out non-static references &&*/
+	public void setErrorFound(){ 
+		if (this == scriptingRecord || this == nonscriptingRecord)
+			return;
+		errorFound = true;
+	}
+	/*&& clean out non-static references &&*/
+	public boolean getErrorFound(){ 
+		return errorFound;
+	}
+	/*&& clean out non-static references &&*/
+	public void setObjectToldNullWarning(){ 
+		if (this == scriptingRecord || this == nonscriptingRecord)
+			return;
+		warnObjectToldNull = true;
+	}
+	/*&& clean out non-static references &&*/
+	public boolean getObjectToldNullWarning(){ 
+		return warnObjectToldNull;
+	}
+	/*&& clean out non-static references &&*/
+	public void setModuleNotFoundWarning(boolean m){ 
+		if (this == scriptingRecord || this == nonscriptingRecord)
+			return;
+		warnModuleNotFound = m;
+	}
+	/*&& clean out non-static references &&*/
+	public boolean getModuleNotFoundWarning(){ 
+		return warnModuleNotFound;
+	}
+	/*&& clean out non-static references &&*/
+	public void setEmergencyRehire(boolean m){ 
+		if (this == scriptingRecord || this == nonscriptingRecord)
+			return;
+		emergencyRehire = m;
+	}
+	/*&& clean out non-static references &&*/
+	public boolean getEmergencyRehire(){ 
+		return emergencyRehire;
+	}
+	/*&& clean out non-static references &&*/
+	public void cancelCommand(Listable canceller){
+		this.canceller = canceller;
+		if (this == scriptingRecord)
+			MesquiteMessage.warnProgrammer("attempt to cancel scripting Record");
+		else if (this == nonscriptingRecord) 
+			MesquiteMessage.warnProgrammer("attempt to cancel nonScripting Record");
+		cancelled = true;
+		if (thread==null)
+			notifyListeners(thread, new Notification(MesquiteListener.COMMAND_CANCELLED));
+	}
+	/*&& clean out non-static references &&*/
+	public boolean isCancelled(){
+		return cancelled;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/CommandRecordHolder.java b/Source/mesquite/lib/CommandRecordHolder.java
new file mode 100644
index 0000000..fe8cc21
--- /dev/null
+++ b/Source/mesquite/lib/CommandRecordHolder.java
@@ -0,0 +1,23 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+
+
+public interface CommandRecordHolder {
+
+	public CommandRecord getCommandRecord();
+	public void setCommandRecord(CommandRecord c);
+}
+
diff --git a/Source/mesquite/lib/CommandThread.java b/Source/mesquite/lib/CommandThread.java
new file mode 100644
index 0000000..17fedc3
--- /dev/null
+++ b/Source/mesquite/lib/CommandThread.java
@@ -0,0 +1,164 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.io.*;
+
+public class CommandThread extends MesquiteThread implements SpecialListName, Explainable {
+	MesquiteCommand command;
+	String arguments;
+	String uiCallInformation;
+	boolean logCommand;
+	static int waitCursorDepth =0;
+	boolean showWaitCursor;
+	boolean running = false;
+	boolean crashed = false;
+	CommandRecord record;
+	public CommandThread (MesquiteCommand command, String arguments, String uiCallInformation, boolean showWaitCursor, boolean logCommand) {
+		super();
+		this.command = command;
+		this.arguments = arguments;
+		this.uiCallInformation = uiCallInformation;
+		this.logCommand = logCommand;
+		this.showWaitCursor = showWaitCursor;
+		setCurrent(1);
+		if (showWaitCursor)
+			waitCursorDepth++;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+	
+	public boolean hasCrashed(){
+		return crashed;
+	}
+	public String getListName(){
+		String s;
+		if (command.getOwner() instanceof Listable)
+			s= "Command: " + command.getName() + " to " + ((Listable)command.getOwner()).getName();
+		else
+			s= "Command: " + command.getName() + " to unknown object";
+		if (running)
+			return "(IN PROGRESS) " + s;
+		return s;
+	}
+	/**/
+	public String getExplanation(){
+		if (running)
+			return "(IN PROGRESS) " + uiCallInformation;
+		return uiCallInformation;
+	}
+	public CommandRecord getCommandRecord(){
+		return record;
+	}
+	public void setCommandRecord(CommandRecord c){
+		 record = c;
+	}
+	public String getCurrentCommandName(){
+		if (command !=null)
+			return command.getName();
+		return null;
+	}
+	public String getCurrentCommandExplanation(){
+		if (command !=null)
+			return "?";
+		return null;
+	}
+	/** DOCUMENT */
+	public void run() {
+		try {
+			int count = 0;
+			while (!(MesquiteCommand.currentThreads.size()==0 || MesquiteCommand.currentThreads.elementAt(0) == this)) { 
+				Thread.sleep(10);
+				count ++;
+			}
+			//execute command here
+			if (command.disposed) {
+				finishUp();
+				return;
+			}
+			if (command.getOwner() == null) {
+				MesquiteMessage.warnProgrammer("Warning: Command given to null object (" + command.getName() + "  " + arguments + ") CommandThread");
+				finishUp();
+				return;
+			}
+			if (logCommand){
+				String logString = " > " + command.getName();
+				if (arguments!=null && !arguments.equals(""))
+					logString +=  " \"" + arguments + "\"";
+				if (command.getOwner() instanceof Listable)
+					logString = ((Listable)command.getOwner()).getName() + logString;
+				else
+					logString = "[" + command.getOwner().getClass().getName() + "]"  + logString;
+				if (command.getOwner() instanceof Logger)
+					((Logger)command.getOwner()).logln(logString);
+				else
+					MesquiteModule.mesquiteTrunk.logln(logString);
+			}
+			running = true;
+			record = new CommandRecord(this, false);
+			CommandRecord previous = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(record);
+			record.addListener(command);
+			Object returned = command.getOwner().doCommand(command.getName(), arguments,CommandChecker.defaultChecker);  //if a command is executed in this way, assumed that not scripting
+			MesquiteThread.setCurrentCommandRecord(previous);
+			finishUp();
+		}
+		catch (InterruptedException e){
+			Thread.currentThread().interrupt();
+		}
+		catch (Exception e){
+				crashed = true;
+				MesquiteFile.throwableToLog(this, e);
+				//corruption warning
+				MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "A command could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + "). WARNING: there is a chance this crash could have corrupted your data.  Please check your data carefully.  If you save any files, you might best use Save As... in case file saving doesn't work properly.");
+				MesquiteDialog.closeWizard();
+				//TODO: should have flag in modules and windows that successfully completed startup; if not, then zap them
+				finishUp();
+			
+		}
+		catch (Error e){
+			if (e instanceof OutOfMemoryError){
+				MesquiteTrunk.mesquiteTrunk.discreetAlert("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+			}
+			else if (!(e instanceof ThreadDeath)){
+				crashed = true;
+				MesquiteFile.throwableToLog(this, e);
+				MesquiteDialog.closeWizard();
+				//corruption warning
+				MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "A command could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + " " + MesquiteException.lastLocMessage() + "). WARNING: there is a chance this crash could have corrupted your data.  Please check your data carefully.  If you save any files, you might best use Save As... in case file saving doesn't work properly.");
+				//TODO: should have flag in modules and windows that successfully completed startup; if not, then zap them
+				finishUp();
+			}
+   	 		throw e;
+		}
+	}
+	
+	private void finishUp(){
+		running = false;
+		if (command.getOwner() instanceof FileDirtier)
+			((FileDirtier)command.getOwner()).fileDirtiedByCommand(command);
+		
+		MesquiteCommand.currentThreads.removeElement(this, false);
+		if (showWaitCursor) {
+			--waitCursorDepth;
+			if (waitCursorDepth<1) //MesquiteCommand.currentThreads.size()==1 && 
+				MesquiteWindow.restoreAllCursors();
+		}
+		interrupt();
+	}
+}
+
diff --git a/Source/mesquite/lib/Commandable.java b/Source/mesquite/lib/Commandable.java
new file mode 100644
index 0000000..6ad7cf9
--- /dev/null
+++ b/Source/mesquite/lib/Commandable.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+
+/* ======================================================================== */
+/**Interface for object to claim it is commandable.  MesquiteModules, MesquiteWindows and other classes are Commandable.*/
+public interface Commandable {
+	/** This method sends two strings to the Commandable: the command name, and the arguments.  In order to support the 
+	command documentation system, a non-null CommandChecker must be passed to the command.  The scripting parameter indicates
+	whether the command comes from a script (e.g., saved in the Mesquite block of a NEXUS file, or in a macro file) or is attached to
+	a direct user-interface action (e.g. selecting a menu or hitting a button).  In the former, the commanded object should avoid interaction with the user
+	to make decisions about parameters; in the latter, it is appropriate for the object to query the user for informations as needed. */
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker);
+}
+
diff --git a/Source/mesquite/lib/CommandableOwner.java b/Source/mesquite/lib/CommandableOwner.java
new file mode 100644
index 0000000..568cd5e
--- /dev/null
+++ b/Source/mesquite/lib/CommandableOwner.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/* ======================================================================== */
+/** Interfact designed for modules so that they can claim to own or be associated with other Commandables.  When queried the module should
+return an array of instantiated Commandables, from each of which can be accumulated its commands.  The purpose of this is for the automatic
+accumulation of documentation of commands (see CommandChecker) to have access to Commandables other than the modules themselves.  Thus,
+if a module uses the interface CommandableOwner and returns an array containing an instantiated copy of its special window type, the accumulator of
+of command documentation can include the documentation for commands of that special window type within the documentation for the module itself.    */
+public interface CommandableOwner {
+	/** return an array of instantiated Commandables from which commands can be accumulated.  These Commandables will typically be
+	temporary copies instantiated for this purpose alone, because this method gets called during Mesquite startup, before the modules have actually started up. */
+ 	public Commandable[] getCommandablesForAccumulation();
+ }
+
+
diff --git a/Source/mesquite/lib/CompatibilityChecker.java b/Source/mesquite/lib/CompatibilityChecker.java
new file mode 100644
index 0000000..2dc2430
--- /dev/null
+++ b/Source/mesquite/lib/CompatibilityChecker.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+/**Interface for object to claim it is will check if it is compatible with some object*/
+public interface CompatibilityChecker {
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer);
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report);
+}
+
diff --git a/Source/mesquite/lib/CompatibilityTest.java b/Source/mesquite/lib/CompatibilityTest.java
new file mode 100644
index 0000000..ff8f908
--- /dev/null
+++ b/Source/mesquite/lib/CompatibilityTest.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public abstract class CompatibilityTest implements CompatibilityChecker {
+	public abstract  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer);
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		return isCompatible(obj, project, prospectiveEmployer);
+	}
+	/*----*/
+	public Class getAcceptedClass() {
+		return null;
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ConsoleThread.java b/Source/mesquite/lib/ConsoleThread.java
new file mode 100644
index 0000000..2dcf974
--- /dev/null
+++ b/Source/mesquite/lib/ConsoleThread.java
@@ -0,0 +1,92 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ConsoleThread extends Thread {
+	CommandCommunicator communicator;
+	boolean useSystemIn;
+	MesquiteModule module;
+	Vector commands;
+	public ConsoleThread (MesquiteModule module, Object objectCommanded, boolean useSystemIn) {
+		this.module = module;
+		setPriority(Thread.MIN_PRIORITY);
+		this.useSystemIn = useSystemIn;
+		communicator = new CommandCommunicator(module, objectCommanded, true);
+		commands = new Vector();
+	}
+	public void run() {
+			String input;
+			int count =0;
+			byte[] bytes = new byte[1000];
+			// fix for windows hanging issue, since System.in.read
+			// was preventing file opening on windows
+			String noConsoleProperty = System.getProperty("mesquite.lib.noconsoleinput");
+			if (!StringUtil.blank(noConsoleProperty)) {
+				useSystemIn = false;
+			}
+			while (!MesquiteTrunk.mesquiteTrunk.mesquiteExiting) { 
+				try {
+
+					if (useSystemIn){
+						Thread.sleep(20);
+						int n = System.in.read(bytes);
+						count++;
+						if (n>0) {
+							communicator.enterTyped(new String(bytes,0, n-1));
+						}
+					}
+					else {
+
+						Thread.sleep(20);
+						count++;
+						if (commands.size() !=0) {
+							String c = (String)commands.elementAt(0);
+							commands.removeElementAt(0);
+							communicator.enterTyped(c);
+						}
+					}
+				}
+				catch (IOException e){
+				}
+				catch (InterruptedException e){
+				}
+			}
+	}
+	public void enterCommand(String c){
+		commands.addElement(c);
+	}
+	public CommandCommunicator getCommunicator(){
+		return communicator;
+	}
+	public static void setConsoleObjectCommanded(Object obj, boolean useQueue, boolean showPrompt){
+	if (MesquiteTrunk.consoleThread !=null && MesquiteTrunk.consoleThread.getCommunicator() != null)
+		MesquiteTrunk.consoleThread.getCommunicator().setObjectCommanded(obj, useQueue, showPrompt);
+	}
+	public static void releaseConsoleObjectCommanded(Object objectReleasing, boolean showPrompt){
+		if (MesquiteTrunk.consoleThread !=null && MesquiteTrunk.consoleThread.getCommunicator() != null)
+			MesquiteTrunk.consoleThread.getCommunicator().releaseObjectCommanded(objectReleasing, showPrompt);
+		}
+}
+
+
+
diff --git a/Source/mesquite/lib/ConsoleWindow.java b/Source/mesquite/lib/ConsoleWindow.java
new file mode 100644
index 0000000..1a2ddd1
--- /dev/null
+++ b/Source/mesquite/lib/ConsoleWindow.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A Text window that serves as a console. */
+public class ConsoleWindow extends MesquiteTextWindow implements KeyListener {
+	String typed = "";
+	boolean consoleMode = true;
+	ConsoleThread thread;
+	public static boolean suppressConsoleInput = false;
+	
+	public ConsoleWindow(MesquiteModule module, String assignedTitle, boolean showInfoBar) {
+		super(module, assignedTitle, showInfoBar); //infobar
+		setBackground(Color.white);
+		addKeyListener(this, (KeyListener)this, false);
+		if (!suppressConsoleInput){
+			thread = new ConsoleThread(module, MesquiteTrunk.mesquiteTrunk, false);
+			thread.start();
+		}
+		else consoleMode = false;
+	}
+	
+	public void setConsoleMode(boolean console){
+		if (!suppressConsoleInput)
+		consoleMode = console;
+		
+	}
+	public boolean isConsoleMode(){
+		return consoleMode;
+	}
+	private void write(String s){
+		if (consoleMode){
+			if (this instanceof LogWindow)
+				MesquiteTrunk.mesquiteTrunk.log(s);
+			else
+				super.append(s);
+		}
+	}
+	public void showPrompt(){
+		if (consoleMode)
+			thread.getCommunicator().showPrompt();
+	}
+	
+	public void keyTyped(KeyEvent e){
+		if (!consoleMode)
+			return;
+		if (!tA.hasFocus())
+			return;
+		int mod = MesquiteEvent.getModifiers(e);
+		if (!MesquiteEvent.commandOrControlKeyDown(mod)) {
+			if (e.getKeyChar()== '\n' || e.getKeyChar()== '\r' || e.getKeyCode()== KeyEvent.VK_ENTER) {
+				thread.enterCommand(typed);
+				tA.requestFocus();
+				tA.requestFocusInWindow();
+				typed = "";
+			}
+			else if ((new Character(e.getKeyChar()).hashCode())==8) {
+				typed = typed.substring(0, typed.length()-1);
+				consume(1);
+				tA.requestFocus();
+				tA.requestFocusInWindow();
+			}
+			else {
+				write("" + e.getKeyChar());
+				typed += e.getKeyChar();
+			}
+		}
+		
+	}
+	
+	public void keyPressed(KeyEvent e){
+	}
+	
+	public void keyReleased(KeyEvent e){
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ContentArea.java b/Source/mesquite/lib/ContentArea.java
new file mode 100644
index 0000000..36a75d8
--- /dev/null
+++ b/Source/mesquite/lib/ContentArea.java
@@ -0,0 +1,415 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+/** A container fitting within the InterContentArea, below the information bar.  It is within the ContentArea that
+modules draw their stuff.*/
+public class ContentArea extends MousePanel {
+	protected ToolPalette palette;
+	protected MousePanel mainPanel;
+
+	protected ContentSideContainer sidePanelContainer;
+	Vector sidePanels;
+	static int sideSpacer = 3;
+	protected int sidePanelWidth = 0;
+
+	protected ContentLedgeContainer ledgePanelContainer;
+	Vector ledgePanels;
+	static int ledgeSpacer = 3;
+	protected int ledgePanelHeight = 0;
+	MesquiteWindow window;
+	
+	public ContentArea (MesquiteWindow w) {
+		this(w, false);
+	}
+	public ContentArea (MesquiteWindow w, boolean makePalette) {
+		setLayout(null);
+		if (makePalette){
+			w.setPalette(palette = w.makeToolPalette());
+			setPalette(palette); //setting palette into main graphics page
+			w.addKeyListenerToAll(this, palette, true);
+		}
+		mainPanel = new MousePanel();
+		mainPanel.setLayout(null);
+		mainPanel.setBounds(0,0,getBounds().width, getBounds().height);
+		//mainPanel.setBackground(Color.green);
+		super.add(mainPanel);
+		mainPanel.requestFocus(); //this may address a MRJ 2.2.3 bug
+
+		sidePanels = new Vector();
+		sidePanelContainer = new ContentSideContainer(this);
+		super.add(sidePanelContainer);
+		sidePanelContainer.setBackground(Color.lightGray);
+		sidePanelContainer.setBounds(getBounds().width, 0,0,getBounds().height);
+		sidePanelContainer.setVisible(true);
+
+		ledgePanels = new Vector();
+		ledgePanelContainer = new ContentLedgeContainer(this);
+		super.add(ledgePanelContainer);
+		ledgePanelContainer.setBackground(Color.lightGray);
+		ledgePanelContainer.setBounds(0, getBounds().height,getBounds().width,0);
+		ledgePanelContainer.setVisible(true);
+		window = w;
+	}
+	public void setPalette(ToolPalette palette){
+		if (palette== null) {
+			super.remove(this.palette);
+			this.palette = null;
+			resetBounds();
+		}
+		else {
+			this.palette = palette;
+			super.add(palette);
+			resetBounds();
+			palette.setVisible(true);
+			palette.repaint(); //attempt to deal with bug in OS X 10.2
+		}
+	}
+	public ToolPalette getPalette(){
+		return palette;
+	}
+	public void setCursor(Cursor c){
+		for (int i = 0; i<sidePanels.size(); i++){
+			Panel p = (Panel)sidePanels.elementAt(i);
+			p.setCursor(c);
+		}
+		for (int i = 0; i<ledgePanels.size(); i++){
+			Panel p = (Panel)ledgePanels.elementAt(i);
+			p.setCursor(c);
+		}
+		super.setCursor(c);
+	}
+	public void addSidePanel(MousePanel p, int width){
+		if (p!= null && sidePanels.indexOf(p)<0) {
+
+			sidePanels.addElement(p);
+			//p.setCursor(Cursor.getDefaultCursor());
+			//this.sidePanel = p;
+			sidePanelWidth += width+sideSpacer;
+			p.ps = width;
+			sidePanelContainer.add(p);
+			p.setVisible(true);
+			resetBounds();
+			p.repaint();
+		}
+	}
+	public boolean hasSidePanel(MousePanel p){
+		return (p!= null && sidePanels.indexOf(p)>=0);
+	}
+	public void removeSidePanel(MousePanel p){
+		if (p!= null && sidePanels.indexOf(p)>=0) {
+			p.setVisible(false);
+			sidePanelWidth -= p.ps + sideSpacer;
+			sidePanelContainer.remove(p);
+			sidePanels.removeElement(p);
+			resetBounds();
+		}
+	}
+	public int getSidePanelWidth(){
+		return sidePanelWidth;
+	}
+	public void addLedgePanel(MousePanel p, int height){
+		if (p!= null && ledgePanels.indexOf(p)<0) {
+			ledgePanels.addElement(p);
+			//p.setCursor(Cursor.getDefaultCursor());
+			//this.sidePanel = p;
+			ledgePanelHeight += height+ledgeSpacer;
+			p.ps = height;
+			ledgePanelContainer.add(p);
+			p.setVisible(true);
+			resetBounds();
+			p.repaint();
+		}
+	}
+	public void removeLedgePanel(MousePanel p){
+		if (p!= null && ledgePanels.indexOf(p)>=0) {
+			p.setVisible(false);
+			ledgePanelHeight -= p.ps + ledgeSpacer;
+			ledgePanelContainer.remove(p);
+			ledgePanels.removeElement(p);
+			resetBounds();
+		}
+	}
+	public int getLedgePanelHeight(){
+		return ledgePanelHeight;
+	}
+
+	public Panel getMainPanel(){
+		return mainPanel;
+	}
+	void rFocus(){
+		javax.swing.SwingUtilities.invokeLater(new Runnable() {
+		    public void run() {			
+		    	mainPanel.requestFocusInWindow();
+		    }
+		});    
+	}
+	public Component add(Component comp, int i){
+		if (comp==null)
+			return null;
+		Component c = mainPanel.add(comp,  i);
+		rFocus();
+
+		return c;
+	}
+	public void add(Component comp, Object s, int i){
+		if (comp==null)
+			return;
+		mainPanel.add(comp, s, i);
+		rFocus();
+	}
+	public void add(Component comp, Object s){
+		if (comp==null)
+			return;
+		mainPanel.add(comp, s);
+		rFocus();
+	}
+	public Component add(Component comp){
+		if (comp==null)
+			return null;
+		Component c = mainPanel.add(comp);
+		rFocus();
+		return c;
+	}
+	public Component add(String name, Component comp){
+		if (comp==null)
+			return null;
+		Component c = mainPanel.add(name, comp);
+		rFocus();
+		return c;
+	}
+	public void remove(Component comp){
+		if (comp==null)
+			return;
+		mainPanel.remove(comp);
+		rFocus();
+	}
+	public void update (Graphics g) {
+		try {
+			super.update(g);
+		}
+		catch (OutOfMemoryError e){
+			MesquiteMessage.println("Sorry, insufficient memory.   See file memory.txt in the Mesquite_Folder.");
+		}
+	}
+	public void setBounds(int x, int y, int w, int h){
+		int paletteWidth = 0;
+		if (palette!=null && palette.getNumTools()>0) {
+			palette.setVisible(true);
+			palette.setSize(palette.getWidth(),h);
+			palette.recheckSize();
+			palette.setSize(palette.getWidth(),h);
+			paletteWidth = palette.getWidth();
+			mainPanel.setBounds(paletteWidth, 0, w-paletteWidth-sidePanelWidth,h - ledgePanelHeight);
+		}
+		else {
+			if (palette != null){
+				palette.setSize(0,0);
+				palette.setVisible(false);
+			}
+			mainPanel.setBounds(0,0,w-sidePanelWidth,h - ledgePanelHeight);
+		}
+		if (sidePanels.size()>0) {
+			sidePanelContainer.setBounds(w- sidePanelWidth, 0, sidePanelWidth, h);
+			int edge = sideSpacer;
+			for (int i=0; i<sidePanels.size(); i++){
+				MousePanel sidePanel = (MousePanel)sidePanels.elementAt(i);
+				sidePanel.setBounds(edge ,0,sidePanel.ps,h );
+				edge += sidePanel.ps +sideSpacer;
+			}
+		}
+		else
+			sidePanelContainer.setBounds(w, h, 0, 0);
+		if (ledgePanels.size()>0) {
+			ledgePanelContainer.setBounds(paletteWidth, h-ledgePanelHeight, w-paletteWidth, ledgePanelHeight);
+			int edge = ledgeSpacer;
+			for (int i=0; i<ledgePanels.size(); i++){
+				MousePanel ledgePanel = (MousePanel)ledgePanels.elementAt(i);
+				ledgePanel.setBounds(0, edge ,w-paletteWidth-sidePanelWidth, ledgePanel.ps);
+				edge += ledgePanel.ps +ledgeSpacer;
+			}
+		}
+		else
+			ledgePanelContainer.setBounds(w, h, 0, 0);
+		super.setBounds(x,y,w,h);
+	}
+	public void setSize(int w, int h){
+		int paletteWidth = 0;
+		if (palette!=null && palette.getNumTools()>0) {
+			palette.setVisible(true);
+			palette.setSize(palette.getWidth(),h);
+			palette.recheckSize();
+			palette.setSize(palette.getWidth(),h);
+			paletteWidth = palette.getWidth();
+			mainPanel.setSize(w-paletteWidth-sidePanelWidth,h - ledgePanelHeight);
+		}
+		else {
+			if (palette != null){
+				palette.setSize(0,0);
+				palette.setVisible(false);
+			}
+			mainPanel.setSize(w-sidePanelWidth,h - ledgePanelHeight);
+		}
+		if (sidePanels.size()>0) {
+			sidePanelContainer.setSize(sidePanelWidth, h);
+			for (int i=0; i<sidePanels.size(); i++){
+				MousePanel sidePanel = (MousePanel)sidePanels.elementAt(i);
+				sidePanel.setSize(sidePanel.ps,h );
+			}
+		}
+		else
+			sidePanelContainer.setSize(0, 0);
+		if (ledgePanels.size()>0) {
+			ledgePanelContainer.setSize(w-paletteWidth, ledgePanelHeight);
+			for (int i=0; i<ledgePanels.size(); i++){
+				MousePanel ledgePanel = (MousePanel)ledgePanels.elementAt(i);
+				ledgePanel.setSize(w-paletteWidth-sidePanelWidth, ledgePanel.ps);
+			}
+		}
+		else
+			ledgePanelContainer.setSize(0, 0);
+		super.setSize(w,h);
+	}
+	void resetBounds(){
+		if (getBounds() == null || mainPanel == null)
+			return;
+		setBounds(0,0,getBounds().width, getBounds().height);
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null)
+			w.windowResized();
+	}
+}
+
+/*=====================================*/
+class ContentSideContainer extends MousePanel {
+	int xTouched = -1;
+	MousePanel panelFollowing = null;
+	ContentArea parent;
+	public ContentSideContainer(ContentArea parent){
+		this.parent = parent;
+		setLayout(null);
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));  //set just edge to this so rest retains
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		setCursor(null);
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null)
+			w.resetCursor();  //set just edge to this so rest retains
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		xTouched = x;
+		if (x>0) {
+			GraphicsUtil.shimmerVerticalOn(null,this,0,getBounds().height,x);
+		}
+		int edge = parent.sideSpacer;
+		for (int i=0; i<parent.sidePanels.size(); i++){
+			MousePanel sidePanel = (MousePanel)parent.sidePanels.elementAt(i);
+			if (x < edge) {
+				panelFollowing =sidePanel;
+				return;
+			}
+			edge += sidePanel.ps + parent.sideSpacer;
+		}
+
+
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x>0)
+			GraphicsUtil.shimmerVerticalOn(null,this,0,getBounds().height,x);
+		if (panelFollowing != null) {
+			int distance = x - xTouched;
+			if (distance + 16 > panelFollowing.ps)
+				distance = panelFollowing.ps - 16; //minimum
+			panelFollowing.ps -= distance;
+			parent.sidePanelWidth -= distance;
+			parent.resetBounds();
+		}
+		xTouched = -1;
+		panelFollowing = null;
+
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x>0) {
+			GraphicsUtil.shimmerVerticalOn(null,this,0,getBounds().height,x);
+			GraphicsUtil.shimmerVerticalOn(null,this,0,getBounds().height,x);
+		}
+		else {
+			GraphicsUtil.shimmerVerticalOn(null,parent,0,getBounds().height,parent.getBounds().width-getBounds().width+x);
+			GraphicsUtil.shimmerVerticalOn(null,parent,0,getBounds().height,parent.getBounds().width-getBounds().width+x);
+		}
+	}
+	public void paint(Graphics g){
+		g.setColor(Color.darkGray);
+		g.fillRect(0,0,2, getBounds().height);
+	}
+}
+
+class ContentLedgeContainer extends MousePanel {
+	int yTouched = -1;
+	MousePanel panelFollowing = null;
+	ContentArea parent;
+	public ContentLedgeContainer(ContentArea parent){
+		this.parent = parent;
+		setLayout(null);
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));  //set just edge to this so rest retains
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		setCursor(null);
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null)
+			w.resetCursor();  //set just edge to this so rest retains
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		yTouched = y;
+		int edge = parent.ledgeSpacer;
+		for (int i=0; i<parent.ledgePanels.size(); i++){
+			MousePanel ledgePanel = (MousePanel)parent.ledgePanels.elementAt(i);
+			if (y < edge) {
+				panelFollowing =ledgePanel;
+				return;
+			}
+			edge += ledgePanel.ps + parent.ledgeSpacer;
+		}
+
+
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (panelFollowing != null) {
+			int distance = y - yTouched;
+			if (distance + 16 > panelFollowing.ps)
+				distance = panelFollowing.ps - 16; //minimum
+			panelFollowing.ps -= distance;
+			parent.ledgePanelHeight -= distance;
+			parent.resetBounds();
+		}
+		yTouched = -1;
+		panelFollowing = null;
+
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void paint(Graphics g){
+		g.setColor(Color.darkGray);
+		g.fillRect(0,0,getBounds().width, 2);
+	}
+}
diff --git a/Source/mesquite/lib/Context.java b/Source/mesquite/lib/Context.java
new file mode 100644
index 0000000..0d802bb
--- /dev/null
+++ b/Source/mesquite/lib/Context.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is a context, e.g. for Tree Context*/
+public interface Context {
+ 	public String getContextName();
+}
+
+
diff --git a/Source/mesquite/lib/DatabaseURLSource.java b/Source/mesquite/lib/DatabaseURLSource.java
new file mode 100644
index 0000000..318c5bd
--- /dev/null
+++ b/Source/mesquite/lib/DatabaseURLSource.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.util.*;
+
+
+public abstract class DatabaseURLSource extends MesquiteModule {
+	Vector keyValuePairs;
+	static final String COUNT = "count";
+	
+  	 public Class getDutyClass() {
+    	 	return DatabaseURLSource.class;
+    	 }
+  	public String getDutyName() {
+  		return "Database URL Source";
+    	 }
+  	
+  	public void addKeyValuePair(String key, String value){
+  		if (keyValuePairs==null)
+  			keyValuePairs = new Vector();
+  		String[] pair = new String[2];
+  		pair[0] = key;
+  		pair[1] = value;
+  		keyValuePairs.addElement(pair);
+  	}
+  	
+	public void addKeyValuePair(int key, String value) {
+		addKeyValuePair(getKeyString(key), value);
+	}
+
+  	public void removeKeyValuePair(String key){
+  		for (int i=0; i<keyValuePairs.size(); i++) {
+  			String[] pair= (String[])keyValuePairs.get(i);
+  			if (pair!=null && pair[0].equalsIgnoreCase(key))
+  				keyValuePairs.remove(i);
+  		}
+  	}
+
+	public boolean needsKeyValuePairAuthorization() {
+		return false;
+	}
+
+  	
+	public abstract String getBaseURL();
+	
+	public abstract String getPage(int whichPage);
+
+	public abstract String getKeyString(int key) ;
+
+	public abstract String getElementName(int elementID);
+
+	public  String getKey() {
+		return "";
+	}
+
+}
diff --git a/Source/mesquite/lib/Debugg.java b/Source/mesquite/lib/Debugg.java
new file mode 100644
index 0000000..1f01759
--- /dev/null
+++ b/Source/mesquite/lib/Debugg.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.io.*;
+ 
+/*=======================*/
+/** A utility class with method to duplicate System.out.println, but can be searched for.  
+ * Intended for temporary use.  Do not leave in released code. */
+public class Debugg {
+	public static int count = 0;
+	public static void print(String s) {
+		System.out.print(s);
+		MesquiteThread.suspendThreadLogging();
+		if (MesquiteTrunk.mesquiteTrunk != null)
+		MesquiteTrunk.mesquiteTrunk.log(s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void println(String s) {
+		System.out.println(s);
+		MesquiteThread.suspendThreadLogging();
+		if (MesquiteTrunk.mesquiteTrunk != null)
+			MesquiteTrunk.mesquiteTrunk.logln(s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void printLogln(String s) {
+		MesquiteMessage.warnUser(s);
+	}
+	public static void printHandle(Object obj) {
+		if (obj == null)
+			System.out.println(" request for handle of null object");
+		/*else if (obj instanceof Listable)
+			System.out.println("Handle: " + Integer.toHexString(obj.hashCode()<<3) + "  " + obj + "     " + ((Listable)obj).getName());*/
+		else
+			System.out.println("Handle: " + Integer.toHexString(obj.hashCode()<<3) + "  " + obj);
+	}
+	public static void printStackTrace(String message) {
+		printLogln(message);
+		printStackTrace();
+	}
+	public static void printStackTrace() {
+		printLogln("An exception was generated intentionally to show a stack trace.  It is used for debugging purposes.");
+		Exception e = new Exception();
+		printStackTrace(e);
+	}
+	public static void printStackTrace(Throwable e) {
+		if (e!=null){
+			MesquiteFile.throwableToLog(null, e);
+			
+		}
+	}
+	public static void printStackTrace(Exception e) {
+		if (e!=null){
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+	public static void printStackTrace(Error e) {
+		if (e!=null){
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/DialogGraphicsPanel.java b/Source/mesquite/lib/DialogGraphicsPanel.java
new file mode 100644
index 0000000..3f74d36
--- /dev/null
+++ b/Source/mesquite/lib/DialogGraphicsPanel.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+public class DialogGraphicsPanel extends Panel {
+	ExtensibleDialog dialog;
+	
+	public DialogGraphicsPanel(ExtensibleDialog dialog){
+		super();
+		this.dialog = dialog;
+//		setBackground(Color.blue);
+	}
+	/*.................................................................................................................*/
+	public Dimension getPreferredSize () {
+		return new Dimension(50,50);
+	}
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		g.setColor(Color.black);
+		g.drawLine(0,0,50,50);
+		g.drawLine(getLocation().x, getLocation().y, getLocation().x+getBounds().width, getLocation().y+getBounds().height);
+	}
+   	
+}
+
+
diff --git a/Source/mesquite/lib/DialogListener.java b/Source/mesquite/lib/DialogListener.java
new file mode 100644
index 0000000..de2bc41
--- /dev/null
+++ b/Source/mesquite/lib/DialogListener.java
@@ -0,0 +1,20 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+public interface DialogListener {
+	public void dialogShown(MesquiteDialog dlog);
+}
+
diff --git a/Source/mesquite/lib/DistanceAnalysis.java b/Source/mesquite/lib/DistanceAnalysis.java
new file mode 100644
index 0000000..329ca28
--- /dev/null
+++ b/Source/mesquite/lib/DistanceAnalysis.java
@@ -0,0 +1,5 @@
+package mesquite.lib;
+
+public interface DistanceAnalysis {
+
+}
diff --git a/Source/mesquite/lib/Doomable.java b/Source/mesquite/lib/Doomable.java
new file mode 100644
index 0000000..37f4e5a
--- /dev/null
+++ b/Source/mesquite/lib/Doomable.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+/* ======================================================================== */
+/**Interface for object to claim it might or might not be doomed*/
+public interface Doomable {
+	/**returns whether or not object is about to be disposed*/
+ 	public boolean isDoomed(); 
+}
+
diff --git a/Source/mesquite/lib/Double2DArray.java b/Source/mesquite/lib/Double2DArray.java
new file mode 100644
index 0000000..40a784f
--- /dev/null
+++ b/Source/mesquite/lib/Double2DArray.java
@@ -0,0 +1,436 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class Double2DArray {
+	double[][] values;
+	int numC;
+	int numT;
+	NameReference name=null;
+	public Double2DArray(int numC, int numT){
+		this.numC = numC;
+		this.numT = numT;	
+		values = new double[numC][numT];
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  MesquiteDouble.unassigned;
+	}
+	public Double2DArray(double[][] input){
+		this(numFullColumns(input), numFullRows(input));
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  input[i][j];
+	}
+	/*...........................................................*/
+	public static double[][] clone(double[][] d){
+		if (d==null || d.length==0)
+			return d;
+		double[][] q = new double[d.length][d[0].length];
+		for (int i=0; i< d.length; i++)
+			for (int j=0; j< d[i].length;j++)
+				q[i][j] = d[i][j];
+		return q;
+	}
+	/*...........................................................*/
+	public static double[][] cloneIncreaseSize(double[][] d, int first, int second){
+		if (d==null || d.length==0)
+			return d;
+		first = MesquiteInteger.maximum(first, d.length);
+		second= MesquiteInteger.maximum(second, d[0].length);
+		double[][]  q = new double[first][second];
+		for (int i=0; i< q.length; i++)
+			for (int j=0; j< q[i].length;j++)
+				if (i>=d.length || j>=d[i].length)
+					q[i][j] = 0.0;
+				else
+					q[i][j] = d[i][j];
+		return q;
+	}
+	/*...........................................................*/
+	public static double[][][] cloneIncreaseSize(double[][][] d, int first, int second, int third){
+		if (d==null || d.length==0)
+			return d;
+		first = MesquiteInteger.maximum(first, d.length);
+		second= MesquiteInteger.maximum(second, d[0].length);
+		third= MesquiteInteger.maximum(third, d[0][0].length);
+		double[][][]  q = new double[first][second][third];
+		for (int i=0; i< q.length; i++)
+			for (int j=0; j< q[i].length;j++)
+				for (int k=0; k< q[i][j].length;k++)
+				if (i>=d.length || j>=d[i].length || k>=d[i][j].length)
+					q[i][j][k]= 0.0;
+				else
+					q[i][j][k] = d[i][j][k];
+		return q;
+	}
+	/*...........................................................*/
+	public void dispose(){
+		values = null;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(double[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public static int numFullRows(double[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public double getValue(int ic, int it){
+		if (values==null || (ic <0 || ic >= values.length) || (it <0 || it >= values[ic].length))
+			return MesquiteDouble.unassigned;
+		else
+			return values[ic][it];
+	}
+	/*...........................................................*/
+	public double[] getValues(int ic) {
+		if (values == null || ic <0 || ic >= values.length)
+			return null;
+		else
+			return values[ic];
+	}
+	/*...........................................................*/
+	public double[][] getMatrix() {
+		return values;
+	}
+	/*...........................................................*/
+	public void setValue(int ic, int it, double value) {
+		if (values!=null && ic >=0 && ic < values.length)
+			if (it >=0 && it < values[ic].length)
+				values[ic][it] = value;
+	}
+	/*...........................................................*/
+	public void setValues(Double2DArray incoming) {
+		if (incoming !=null) {
+			resetSize(incoming.getSizeC(), incoming.getSizeT());
+			for (int it=0; it < getSizeT(); it++) {
+				for (int ic=0; ic < getSizeC(); ic++) {
+					setValue(ic, it, incoming.getValue(ic, it));
+				}
+			}
+		}
+	}
+	/*...........................................................*/
+	public void setValues(double[][] matrix) {
+		if (matrix !=null) {
+			numC = matrix.length;
+			if (numC>0)
+				numT = matrix[0].length;	
+			else
+				numT=0;
+			values = matrix;
+		}
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+				values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public static void zeroArray(double[][] values){
+		if (values==null)
+			return;
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+				values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+				values[ic][it] =  MesquiteDouble.unassigned;
+	}
+	/*...........................................................*/
+	public static void deassignArray(double[][] values){
+		if (values==null)
+			return;
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+				values[ic][it] =  MesquiteDouble.unassigned;
+	}
+	/*...........................................................*/
+	public static void setToIdentityMatrix(double[][] values){
+		if (values==null)
+			return;
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+				if (it==ic)
+					values[ic][it] =  1;
+				else
+					values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	/** Changes the array size to the new dimensions*/
+	public void resetSize(int newNumC, int newNumT) {
+		if (newNumC == numC && newNumT == numT)
+			return;
+		double[][] newDoubleValues = new double[newNumC][newNumT];
+		for (int i=0; i<newNumC; i++)
+			for (int j=0; j<newNumT; j++) {
+				if (i<numC && j<numT)
+					newDoubleValues[i][j]=values[i][j];
+				else
+					newDoubleValues[i][j]=0;
+			}
+		values=newDoubleValues;
+
+		numC=newNumC;
+		numT=newNumT;
+	}
+	/*...........................................................*/
+	public static double maximum(double[][] values, boolean ignoreUncombinable){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int ic = 0; ic<values.length; ic++)
+			for (int i=0; i<values[ic].length; i++) {
+				if (!ignoreUncombinable || MesquiteDouble.isCombinable(values[ic][i]))
+					d.setMeIfIAmLessThan(values[ic][i]);
+			}
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public static double minimum(double[][] values, boolean ignoreUncombinable){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int ic = 0; ic<values.length; ic++)
+			for (int i=0; i<values[ic].length; i++){
+				if (!ignoreUncombinable || MesquiteDouble.isCombinable(values[ic][i]))
+					d.setMeIfIAmMoreThan(values[ic][i]);
+			}
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public static double maximumInColumn(double[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmLessThan(values[column][i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public static double minimumInColumn(double[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmMoreThan(values[column][i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	/** borrowed from rhetenor.MatrixUtil*/
+	public static double[][] multiply(double[][] matrix1, double[][] matrix2, double[][] result){
+		int numRows1 = numFullRows(matrix1);
+		int numRows2 = numFullRows(matrix2);
+		int numColumns1 = numFullColumns(matrix1);
+		int numColumns2 = numFullColumns(matrix2);
+		boolean flag = (numColumns1!= numRows2 || numRows1*numRows2*numColumns1*numColumns2 ==0);
+		if (flag) MesquiteMessage.println("Wow! You are trying to multiply a:   " 
+				+Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  
+				+" by a  " 
+				+Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  ); 
+		if (flag)
+			return null; 
+		if (result == null || result.length != numColumns2 || (result.length>0 && result[0].length != numRows1))
+			result = new double[numColumns2][numRows1];
+		zeroArray(result);
+		for (int i=0; i<numColumns2; i++) {
+			for (int j=0; j<numRows1; j++) {
+				double sum =0;
+				for (int k=0; k<numColumns1; k++) {
+					sum += matrix1[k][j]* matrix2[i][k];
+				}
+				result[i][j]=sum;
+			}
+		}
+		return result;
+	}
+	/*...........................................................*/
+	/** borrowed from rhetenor.MatrixUtil*/
+	public static double[][] transpose(double[][] matrix){
+		return transpose(matrix, null);
+	}
+	/*...........................................................*/
+	/** borrowed from rhetenor.MatrixUtil*/
+	public static double[][] transpose(double[][] matrix, double[][] result){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		if (result == null || result.length != numRows || (result.length>0 && result[0].length != numColumns))
+			result = new double[numRows][numColumns];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[j][i]=matrix[i][j];
+			}
+		}
+		return result;
+	}
+	/*...........................................................*/
+	/** flip matrix both ways*/
+	public static double[][] squnch(double[][] matrix, double[][] result){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		if (result == null || result.length != numRows || (result.length>0 && result[0].length != numColumns))
+			result = new double[numRows][numColumns];
+		zeroArray(result);
+		//flip columns
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][numRows - j - 1]=matrix[i][j];
+			}
+		}
+		//flip rows
+		for (int i=0; i<numColumns/2; i++) {
+			for (int j=0; j<numRows; j++) {
+				double t = result[numColumns-i-1][j];
+				result[numColumns-i-1][j]=result[i][j];
+				result[i][j] = t;
+			}
+		}
+		return result;
+	}
+	/*...........................................................*/
+	public int getSizeC() {
+		return numC;
+	}
+	/*...........................................................*/
+	public int getSizeT() {
+		return numT;
+	}
+	/*...........................................................*/
+	public static void swapColumns(double[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		double[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveColumns(double[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		double[][] newValues = new double[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	public static String toString(double[][] matrix){
+		if (matrix == null)
+			return "Matrix null";
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		for (int j=0; j<numRows; j++) {
+			result.append('[');
+			for (int i=0; i<numColumns; i++) {
+				if (!MesquiteDouble.isCombinable(matrix[i][j]))
+					MesquiteDouble.toString(matrix[i][j], result);
+				else
+					result.append(Double.toString(matrix[i][j]));
+				result.append(' ');
+			}
+			result.append(']');
+			result.append('\n');
+		}
+		return result.toString();
+	}
+	public static String toStringRC(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		for (int i=0; i<matrix.length; i++) {
+			result.append('[');
+			for (int j=0; j<matrix[i].length; j++) {
+				if (!MesquiteDouble.isCombinable(matrix[i][j]))
+					MesquiteDouble.toString(matrix[i][j], result);
+				else
+					result.append(Double.toString(matrix[i][j]));
+				result.append(' ');
+			}
+			result.append(']');
+			result.append('\n');
+		}
+		return result.toString();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/DoubleArray.java b/Source/mesquite/lib/DoubleArray.java
new file mode 100644
index 0000000..7107abd
--- /dev/null
+++ b/Source/mesquite/lib/DoubleArray.java
@@ -0,0 +1,432 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class DoubleArray implements Listable  {
+	double[] values;
+	NameReference name=null;
+	int autoExpandAmount = 0;
+	public DoubleArray(int num, int autoExpandAmount){	
+		values = new double[num];
+		for (int i=0; i<num; i++)
+			values[i] =  MesquiteDouble.unassigned;
+		this.autoExpandAmount = autoExpandAmount;
+	}
+	public DoubleArray(int num){	
+		this(num, 0);
+	}
+	//used for Associables that might need to record whether reference is to part or in between part
+	//intially for MesquiteTree to know if info applies to node or branch ancestral to node
+	boolean between = false;
+	public void setBetweenness(boolean b){
+		between = true;  
+	}
+	public boolean isBetween(){
+		return between;
+	}
+	/*...........................................................*/
+	public static double[] clone(double[] d){
+		if (d==null)
+			return d;
+		double[] q = new double[d.length];
+		for (int i=0; i< d.length; i++)
+			q[i] = d[i];
+		return q;
+	}
+	/*...........................................................*/
+	public static double[] copyIntoDifferentSize(double[] d, int newLength, double defaultValue){
+		if (d==null)
+			return null;
+		double[] values = new double[newLength];
+		for (int i=0; i<values.length; i++)
+			if (i<d.length)
+				values[i] =  d[i];
+			else
+				values[i] = defaultValue;
+		return values;
+	}
+	/*...........................................................*/
+	public boolean legalIndex(int i){
+		return (values!=null && i>=0 && i<values.length);
+	}
+	/*...........................................................*/
+	public double[] getMatrix(){
+		return values;
+	}
+	/*...........................................................*/
+	public double getValue(int index){
+		if (!legalIndex(index))
+			return MesquiteDouble.unassigned;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public void setValue(int index, double value) {
+		if (legalIndex(index))
+			values[index] = value;
+		else if (autoExpandAmount>0){
+			if (index >= values.length){
+				int newSize = 0;
+				if (index-values.length+1 < autoExpandAmount)
+					newSize = values.length + autoExpandAmount;
+				else
+					newSize = index + autoExpandAmount;
+				resetSize(newSize);
+				if (legalIndex(index))
+					values[index] = value;
+			}
+		}
+	}
+	/*...........................................................*/
+	public void setValues(double[] values) {
+		if (values==null)
+			this.values = new double[0];
+		else
+			this.values= values;
+	}
+	/*...........................................................*/
+	public void copyTo(DoubleArray d){
+		if (d==null || d.values.length!=values.length)
+			return;
+		for (int i=0; i<values.length; i++)
+			d.values[i] =  values[i];
+	}
+	/*...........................................................*/
+	public static double[] copy(double[] d){
+		if (d==null)
+			return null;
+		double[] values = new double[d.length];
+		for (int i=0; i<values.length; i++)
+			d[i] =  values[i];
+		return values;
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	public static void zeroArray(double[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteDouble.unassigned;
+	}
+	/*...........................................................*/
+	public static void deassignArray(double[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteDouble.unassigned;
+	}
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		double[] newValues = new double[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newValues[i]=values[i];
+		if (newNum>getSize())
+			for (int i=getSize(); i<newNum; i++)
+				newValues[i]=MesquiteDouble.unassigned;
+		values=newValues;
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num) {
+		values=addParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static double[] addParts(double[] d, int starting, int num) {
+		if (num<=0 || d==null)
+			return d;
+		/*#
+		if (d.length <= 0) {
+			double[] newMatrix=new double[num];
+			for (int ic=0; ic<num; ic++){
+					newMatrix[ic]= defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+		*/
+		if (starting<0) 
+			starting = -1;
+		if (starting>d.length) 
+			starting = d.length-1;
+		int newNum = d.length + num;
+		double[] newValues = new double[newNum];
+		for (int i=0; i<=starting; i++)
+			newValues[i]=d[i];
+		for (int i=0; i<num ; i++)
+			newValues[starting + i + 1]=MesquiteDouble.unassigned;
+		for (int i=0; i<d.length-starting-1; i++)
+			newValues[i +starting+num+1]=d[starting + i + 1];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0 || starting<0 || starting>=getSize())
+			return;
+		values = deleteParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static double[] deleteParts(double[] d, int starting, int num) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		if (num+starting>d.length)
+			num = d.length-starting;
+		int newNum =d.length - num;
+		double[] newValues = new double[newNum];
+		for (int i=0; i<starting; i++)
+			newValues[i]=d[i];
+		for (int i=starting+num; i<d.length; i++)
+			newValues[i-num]=d[i];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void moveParts(int starting, int num, int justAfter) {
+		moveParts(values, starting, num, justAfter);
+	}
+	/*...........................................................*/
+	public static void moveParts(double[] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		double[] newValues = new double[d.length];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public static void swapParts(double[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		double temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public boolean swapParts(int first, int second) {
+		if (first<0 || first>=values.length || second<0 || second>=values.length) 
+			return false;
+		double temp = values[first];
+		values[first] = values[second];
+		values[second] = temp;
+		return true;
+	}
+	/*...........................................................*/
+	public static double[] getMoveParts(double[] d, int starting, int num, int justAfter) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		double[] newValues = new double[d.length];
+
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+
+		return newValues;
+	}
+	/*...........................................................*/
+	public int indexOf(double match){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(double[] values, double match){
+		if (values==null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int countSame(double[] a, double match){
+		if (a==null)
+			return 0;
+		int count= 0;
+		for (int i=0; i<a.length; i++)
+			if (a[i]== match)
+				count++;
+		return count;
+	}
+	/*...........................................................*/
+	public static double maximum(double[] values){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values.length; i++)
+			d.setMeIfIAmLessThan(values[i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public double maximum(){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values.length; i++)
+			d.setMeIfIAmLessThan(values[i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public static double minimum(double[] values){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values.length; i++)
+			d.setMeIfIAmMoreThan(values[i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public double minimum(){
+		if (values==null)
+			return MesquiteDouble.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteDouble.unassigned);
+		for (int i=0; i<values.length; i++)
+			d.setMeIfIAmMoreThan(values[i]);
+		return d.getDoubleValue();
+	}
+	/*...........................................................*/
+	public boolean fillNextUnassigned(double v){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== MesquiteDouble.unassigned) {
+				values[i] = v;
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	public static void sort(double[] array){
+		if (array==null || array.length<=1)
+			return;
+		
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				double temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		
+	}
+	/*...........................................................*/
+	public static void sortByFirst(double[] array, double[] other){
+		if (array==null || array.length<=1 || other==null || other.length<=1 || array.length !=other.length)
+			return;
+		
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				double temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+				temp = other[j];
+				other[j] = other[j+1];
+				other[j+1]=temp;
+			}
+		}
+		
+	}
+	/*...........................................................*/
+	public int getSize() {
+		if (values==null)
+			return 0;
+		return values.length;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/** DOCUMENT */
+	public String toString() {
+		String s = "[ ";
+		for (int i=0; i<values.length; i++)
+			s +=  MesquiteDouble.toString(values[i]) + " ";
+		s += "]";
+		return s;
+	}
+	public static String toString(double[] values) {
+		if (values==null)
+			return "";
+		String s = "[ ";
+		for (int i=0; i<values.length; i++)
+			s += values[i] + "  ";//s +=  MesquiteDouble.toString(values[i]) + " ";
+		s += "]";
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/lib/DoubleClickList.java b/Source/mesquite/lib/DoubleClickList.java
new file mode 100644
index 0000000..dae73f5
--- /dev/null
+++ b/Source/mesquite/lib/DoubleClickList.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib; 
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+
+
+/*===============================================*/
+/** An list that records if it has been double-clicked */
+public class DoubleClickList extends List implements MouseListener {
+	boolean doubleClick=false;
+	DoubleClickListener obj;
+	boolean forceSize = true;
+	boolean acceptsDoubleClicks = !MesquiteTrunk.isMacOSXAfterJaguarRunning33();
+	
+	/*.................................................................................................................*/
+	public DoubleClickList (int numRows, boolean multipleMode) {
+		super(numRows, multipleMode);
+		addMouseListener(this);
+	}
+	/*.................................................................................................................*/
+	public DoubleClickList (int numRows) {
+		super(numRows);
+		addMouseListener(this);
+	}
+	/*.................................................................................................................*/
+	public DoubleClickList () {
+		super();
+		addMouseListener(this);
+	}
+	/*...............................................................................................................*/
+	public void setEnableDoubleClicks(boolean enabled) {
+		if (MesquiteTrunk.isMacOSXAfterJaguarRunning33())
+			acceptsDoubleClicks= false;
+		else
+			acceptsDoubleClicks= enabled;
+	}
+	/*...............................................................................................................*/
+	public boolean getAcceptsDoubleClicks() {
+		return acceptsDoubleClicks;
+	}
+	/*...............................................................................................................*/
+	public boolean getDoubleClick() {
+		return doubleClick;
+	}
+	/*...............................................................................................................*/
+	public void setDoubleClickListener(DoubleClickListener obj) {
+		this.obj = obj;
+	}
+	/*...............................................................................................................*/
+	public Dimension getPreferredSize() {
+		if (forceSize) {
+			int width = (int)super.getPreferredSize().width;
+			return new Dimension(MesquiteInteger.maximum(width,360), (int)super.getPreferredSize().height);
+		}
+		else
+			return super.getPreferredSize();
+		
+	}
+	/*...............................................................................................................*/
+	public void setForceSize(boolean forceSize) {
+		this.forceSize = forceSize;
+	}
+ 	/*...............................................................................................................*/
+	public void  mousePressed(MouseEvent e)   {
+		if (e.getClickCount()>1 && acceptsDoubleClicks) {
+			doubleClick=true;
+			if (obj!=null)
+				obj.doubleClicked(this);
+		}
+		else {
+			doubleClick=false;
+		}
+	}
+	/*...............................................................................................................*/
+	 public void mouseClicked(MouseEvent e) {}
+	/*...............................................................................................................*/
+	 public void mouseReleased(MouseEvent e) {}
+	/*...............................................................................................................*/
+	 public void mouseEntered(MouseEvent e) {}
+	/*...............................................................................................................*/
+	 public void mouseExited(MouseEvent e) {}
+	/**/
+
+}
+
diff --git a/Source/mesquite/lib/DoubleClickListener.java b/Source/mesquite/lib/DoubleClickListener.java
new file mode 100644
index 0000000..635673b
--- /dev/null
+++ b/Source/mesquite/lib/DoubleClickListener.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib; 
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+public interface DoubleClickListener  {
+	public void doubleClicked(Component c);
+}
+
+
diff --git a/Source/mesquite/lib/DoubleField.java b/Source/mesquite/lib/DoubleField.java
new file mode 100644
index 0000000..7060358
--- /dev/null
+++ b/Source/mesquite/lib/DoubleField.java
@@ -0,0 +1,125 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+
+/*===============================================*/
+/** a field for doubles */
+public class DoubleField  {
+	ExtensibleDialog dialog;
+	SingleLineTextField textField;
+	double initialValue=MesquiteDouble.unassigned;
+	double min = MesquiteDouble.unassigned;
+	double max = MesquiteDouble.unassigned;
+	boolean permitUnassigned = false;
+	int digits = 8;
+	double currentValue = initialValue;  //used only for resetting digits
+	
+	/*.................................................................................................................*/
+	public DoubleField (ExtensibleDialog dialog, String message, double initialValue, int fieldLength, double min, double max) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = initialValue;
+		if (initialValue==MesquiteDouble.unassigned)
+			textField = dialog.addTextField (message, "", fieldLength);
+		else
+			textField = dialog.addTextField (message, MesquiteDouble.toStringDigitsSpecified(initialValue, digits), fieldLength);
+		this.min = min;
+		this.max = max;
+		dialog.focalComponent = textField;
+		currentValue = initialValue;
+	}
+	/*.................................................................................................................*/
+	public DoubleField (ExtensibleDialog dialog, String message, double initialValue, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = initialValue;
+		if (initialValue==MesquiteDouble.unassigned)
+			textField = dialog.addTextField (message, "", fieldLength);
+		else
+			textField = dialog.addTextField (message, MesquiteDouble.toStringDigitsSpecified(initialValue, digits), fieldLength);
+		dialog.focalComponent = textField;
+		currentValue = initialValue;
+	}
+	/*.................................................................................................................*/
+	public DoubleField (ExtensibleDialog dialog, String message, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = 0.0;
+		textField = dialog.addTextField (message, "", fieldLength);
+		dialog.focalComponent = textField;
+	}
+	
+	/*.................................................................................................................*/
+	public void setDigits(int d){
+		digits = d;
+		textField.setText(MesquiteDouble.toStringDigitsSpecified(currentValue, digits));
+	}
+	/*.................................................................................................................*/
+	public void setPermitUnassigned(boolean permit){
+		permitUnassigned = permit;
+		if (initialValue == MesquiteDouble.unassigned && StringUtil.blank(textField.getText()))
+			textField.setText("?");
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField getTextField() {
+		return textField;
+	}
+	/*.................................................................................................................*/
+	public double getValue () {
+		String s = textField.getText();
+		double value = MesquiteDouble.fromString(s);
+		if (!MesquiteDouble.isCombinable(value)) {
+			if (!(permitUnassigned && value == MesquiteDouble.unassigned))
+				value=initialValue;
+		} else if (value< min && MesquiteDouble.isCombinable(min))
+			value = min;
+		else if (value>max && MesquiteDouble.isCombinable(max)) 
+			value = max;
+		return value;
+	}
+	/*.................................................................................................................*/
+	/** This method returns the value as the initial value if it is out of bounds, otherwise return the value in the field.
+	It also sets the value of "success" to false if the value is out of bounds, but it does NOT set the value to true if it is in bounds.*/
+	public double getValue (MesquiteBoolean success) {  // 
+		String s = textField.getText();
+		double value = MesquiteDouble.fromString(s);
+		if (!MesquiteDouble.isCombinable(value)) {
+			if (!(permitUnassigned && value == MesquiteDouble.unassigned)){
+				value=initialValue;
+				
+				success.setValue(false);
+			}
+		}
+		else if (value< min) {
+			value = initialValue;
+			success.setValue(false);
+		}
+		else if (value>max){
+			value = initialValue;
+			success.setValue(false);
+		}
+	       	return value;
+	}
+	/*.................................................................................................................*/
+	public void setValue (double value) {
+		textField.setText(MesquiteDouble.toStringDigitsSpecified(value, digits));
+		currentValue = value;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/DoubleMiniScroll.java b/Source/mesquite/lib/DoubleMiniScroll.java
new file mode 100644
index 0000000..716c211
--- /dev/null
+++ b/Source/mesquite/lib/DoubleMiniScroll.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A miniature scroller containing two MiniScrolls. */
+public class DoubleMiniScroll extends Panel  {
+	MiniScroll xScroll, yScroll;
+	String xTitle, yTitle;
+	MesquiteLabel yTitlePanel;
+	Color bg;
+	public DoubleMiniScroll(MesquiteCommand setXCommand, MesquiteCommand setYCommand, int minX, int currentX, int maxX, int minY, int currentY, int maxY) {
+		setLayout(null);
+		setCursor(Cursor.getDefaultCursor());
+		
+		yScroll = new MiniScroll(setYCommand, false, false, minY, minY, maxY,"");
+		yScroll.setLocation(0, 0);
+		yScroll.setVisible(true);
+		xScroll = new MiniScroll(setXCommand, false, true, minX, minX, maxX,"");
+		xScroll.setLocation(20, 46);
+		xScroll.setVisible(true);
+		yTitlePanel = new MesquiteLabel(null);
+		yTitlePanel.setColor(null);
+		yTitlePanel.setLocation(16, 0);
+		setSize(20+xScroll.getTotalWidth(), yScroll.getTotalHeight());
+		add(yTitlePanel);
+		add(xScroll);
+		add(yScroll);
+	}
+	public void setVisible(boolean b){
+		if (b)
+			checkBackground();
+		super.setVisible(b);
+	}
+	
+	private boolean checkBackground(){
+		if (getParent() !=null && getBackground()!=null && !getBackground().equals(getParent().getBackground())) {
+			bg =getParent().getBackground();
+			setBackground(bg);
+			return true;
+		}
+		else return false;
+	}
+	public void setXVisible(boolean vis){
+		xScroll.setVisible(vis);
+	}
+	public void setYVisible(boolean vis){
+		yScroll.setVisible(vis);
+		yTitlePanel.setVisible(vis);
+	}
+	public void setXValues(int min, int current, int max){
+		xScroll.setMinimumValue(min);
+		xScroll.setMaximumValue(max);
+		xScroll.setCurrentValue(current);
+	}
+	public void setYValues(int min, int current, int max){
+		yScroll.setMinimumValue(min);
+		yScroll.setMaximumValue(max);
+		yScroll.setCurrentValue(current);
+	}
+	public void setXTitle(String s){
+		xTitle = s;
+	}
+	public void setYTitle(String s){
+		yTitle = s;
+		yTitlePanel.setText(yTitle);
+	}
+	public void paint(Graphics g){
+		if (g instanceof PrintGraphics)
+			return;
+		if (xScroll.isVisible() && !StringUtil.blank(xTitle))
+			g.drawString(xTitle, 42, 42);
+	//	if (!StringUtil.blank(yTitle))
+		//	g.drawString(yTitle, 36, 18);
+	}
+	public void printAll(Graphics g) { 
+	}
+	public void paintComponents(Graphics g) { 
+		if (g instanceof PrintGraphics)
+			return;
+		else
+			super.paintComponents(g);
+	}
+	public void printComponents(Graphics g) { 
+	}
+	public void print(Graphics g) { 
+	}
+}
+
diff --git a/Source/mesquite/lib/DoubleSliderWindow.java b/Source/mesquite/lib/DoubleSliderWindow.java
new file mode 100644
index 0000000..43cbe2d
--- /dev/null
+++ b/Source/mesquite/lib/DoubleSliderWindow.java
@@ -0,0 +1,197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+public class DoubleSliderWindow extends MesquiteWindow {
+	TextField tF1,tF2;
+	Label label1, label2;
+	MiniSliderWithText slider1, slider2;
+	MesquiteMenuItemSpec minItem, maxItem;
+	GridBagLayout gridBag;
+	GridBagConstraints constraints;
+	String title ="Slider";
+	static int insetFromWindow = 40;
+	static int minWindowWidth = 360;
+	boolean allowEstimation=false;
+	protected Panel sliderArea;
+
+	public DoubleSliderWindow(MesquiteModule module, String title, String name1, MesquiteCommand command1, double initialValue1, double min1, double max1,  double minSweet1, double maxSweet1, String name2, MesquiteCommand command2, double initialValue2, double min2, double max2, double minSweet2, double maxSweet2) {
+		super(module, false);
+		setVisible(false);
+		setPreferredPopoutWidth(300);
+		setWindowSize(minWindowWidth, 240);
+
+		this.title = title;
+
+		//Panel contents = getGraphicsArea();
+		sliderArea = new Panel();
+		addToWindow(sliderArea);
+		sliderArea.setVisible(true);
+		sliderArea.setBounds(0, 0, minWindowWidth, 220);
+	        gridBag = new GridBagLayout();
+	        constraints = new GridBagConstraints();
+	        constraints.gridx=1;
+	       	constraints.gridy = 1;
+	        constraints.weightx=1;
+	        constraints.weighty=1;
+	        constraints.ipadx=1;
+	        constraints.ipady=1;
+	        constraints.insets=new Insets(0,8,0,8);
+	        constraints.fill=GridBagConstraints.BOTH;
+	     	constraints.anchor=GridBagConstraints.CENTER;
+		sliderArea.setLayout(gridBag);
+		
+		label1 = new Label();
+   	 	if (!StringUtil.blank(name1))
+   	 		label1.setText(name1);
+		sliderArea.add(label1,constraints);
+
+		slider1 = new MiniSliderWithText(command1, initialValue1, min1, max1, minSweet1, maxSweet1);
+	       	constraints.gridy ++;
+		sliderArea.add(slider1,constraints);
+		slider1.setWidth(getBounds().width-insetFromWindow);
+		slider1.setVisible(true);
+
+		label2 = new Label();
+   	 	if (!StringUtil.blank(name2))
+   	 		label2.setText(name2);
+		constraints.gridy ++;
+		sliderArea.add(label2,constraints);
+
+		slider2 = new MiniSliderWithText(command2, initialValue2, min2, max2, minSweet2, maxSweet2);
+		constraints.gridy ++;
+		sliderArea.add(slider2, constraints);
+		slider2.setWidth(getBounds().width-insetFromWindow);
+		slider2.setVisible(true);
+		//ok.setBackground(Color.white);
+		/* *
+		Panel buttons = new Panel();
+		buttons.setBackground(Color.green);
+		sliderArea.add(buttons);
+		Checkbox ok;
+		buttons.add("South", ok = new Checkbox("Flat Prior", false));
+		Font df = new Font("Dialog", Font.PLAIN, 12);
+		ok.setFont(df);
+	/**/
+	
+		//setVisible(true);  Windows should set themselves visible!!!!
+		resetTitle();
+		slider1.getEnterButton().setEnabled(false);
+		slider2.getEnterButton().setEnabled(false);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(title);
+	}
+	
+	/*.................................................................................................................*/
+  	 public void useExponentialScale(boolean exp) {
+  	 	slider1.useExponentialScale(exp);
+  	 	slider2.useExponentialScale(exp);
+  	 }
+	/*.................................................................................................................*/
+  	 public void setAllowEstimation(boolean allow) {
+  	 	allowEstimation = allow;
+  	 	if (slider1!=null) 
+  	 		slider1.setAllowEstimation(allow);
+	 	if (slider2!=null) 
+  	 		slider2.setAllowEstimation(allow);
+  	 }
+	/*.................................................................................................................*/
+  	 public Dimension getMinimumSize() {
+  	 	return new Dimension(minWindowWidth,getWindowHeight());
+  	 }
+	/*.................................................................................................................*/
+  	 public Dimension getMaximumSize() {
+  	 	return new Dimension(super.getMaximumSize().width, getWindowHeight());  // forces height to not change
+  	 }
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		int toFitWidth = getBounds().width-insetFromWindow;
+		if (toFitWidth > 400)
+			toFitWidth = 400;
+		if (sliderArea != null)
+			sliderArea.setBounds(0, 0, toFitWidth, getBounds().height);
+		if (slider1!= null)
+			slider1.setWidth(toFitWidth);
+		if (slider2!= null)
+			slider2.setWidth(toFitWidth);
+	}
+	/*.................................................................................................................*/
+	public void setColor(Color c){
+		setBackground(c);
+		label1.setBackground(c);
+		label2.setBackground(c);
+		Panel contents = getGraphicsArea();
+		contents.setBackground(c);
+		repaintAll();
+	}
+	public void setText(int which, String s) {
+		if (which==1){
+			label1.setText(s);
+			label1.repaint();
+		}
+		else if (which ==2){
+			label2.setText(s);
+			label2.repaint();
+		}
+		repaint();
+	}
+	public String getText(int which) {
+		if (which==1)
+			return label1.getText();
+		else if (which ==2)
+			return label2.getText();
+		return null;
+	}
+	
+	public void setValue(int which, double d) {
+		if (which==1){
+			slider1.setCurrentValue(d);
+			slider1.repaint();
+		}
+		else if (which ==2){
+			slider2.setCurrentValue(d);
+			slider2.repaint();
+		}
+		repaint();
+	}
+	public double getCurrentValue(int which) {
+		if (which==1)
+			return slider1.getCurrentValue().getDoubleValue();
+		else if (which ==2)
+			return slider2.getCurrentValue().getDoubleValue();
+		return 0;
+	}
+	public void dispose(){
+		//getOwnerModule().deleteMenuItem(minItem);
+		//getOwnerModule().deleteMenuItem(maxItem);
+		super.dispose();
+	}
+	/*=============*/
+	public void buttonHit(String label, Button button) {
+		if (label.equalsIgnoreCase("Close")) {
+			getOwnerModule().windowGoAway(this);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/DoubleSqMatrixFields.java b/Source/mesquite/lib/DoubleSqMatrixFields.java
new file mode 100644
index 0000000..a546a06
--- /dev/null
+++ b/Source/mesquite/lib/DoubleSqMatrixFields.java
@@ -0,0 +1,174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+/*===============================================*/
+/** a collection of fields for doubles */
+public class DoubleSqMatrixFields  {
+	ExtensibleDialog dialog;
+	SingleLineTextField [][] textFields;
+	double[][] matrix;
+	String[] labels;
+	boolean onlyUpperRight;
+	boolean editDiagonal;
+	boolean valid=false;
+	boolean lastValueEditable = false;
+	SingleLineTextField lastField = null;
+	/*.................................................................................................................*/
+	public DoubleSqMatrixFields (ExtensibleDialog dialog, double[][] matrix, String[] labels, boolean onlyUpperRight, boolean editDiagonal, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.labels =labels;
+		this.matrix = matrix;
+		initSqMatrixFields(matrix,onlyUpperRight,editDiagonal, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public DoubleSqMatrixFields (ExtensibleDialog dialog, int matrixSize, boolean onlyUpperRight, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		matrix = new double[matrixSize][matrixSize];
+		for (int i = 0; i<matrixSize; i++)
+			for (int j = 0; j<matrixSize; j++) 
+				matrix[i][j] = MesquiteDouble.unassigned;
+		initSqMatrixFields(matrix,onlyUpperRight,editDiagonal, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public void initSqMatrixFields (double[][]  matrix, boolean onlyUpperRight, boolean editDiagonal, int fieldLength) {
+		this.onlyUpperRight = onlyUpperRight;
+		this.editDiagonal = editDiagonal;
+		textFields = new SingleLineTextField [matrix.length][matrix.length]; //protect against non-square or null matrices!
+		
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+		int adj = 0;
+		if (!onlyUpperRight)
+			adj = 1;
+	        
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+		constraints.gridx=3;
+		newPanel.add(new Label("To:"),constraints);
+		
+		constraints.gridy = 2;
+		if (!onlyUpperRight) {
+			constraints.gridx=3;
+			if (labels!=null)
+				newPanel.add(new Label("" +labels[0]+ "  "),constraints);
+		}
+			
+		for (int i = 1; i<matrix.length; i++) {
+			constraints.gridx=i+2+adj;
+			if (labels!=null)
+				newPanel.add(new Label("" +labels[i]+ "  "),constraints);
+		}
+		
+		constraints.gridx=1;
+		constraints.gridy = 3;
+		newPanel.add(new Label("From: "),constraints);
+		
+		int numRows = matrix.length;
+		if (onlyUpperRight)
+			numRows --;
+
+		for (int i = 0; i<numRows; i++)  { //cycle through rows 
+			constraints.gridy=i+3;
+			constraints.gridx=2;
+			if (labels!=null)
+				newPanel.add(new Label("  " + labels[i] + "  "),constraints);
+			for (int j = 0; j<matrix[0].length; j++) {
+				constraints.gridx=j+2+adj;
+				if (j>i || i==j && editDiagonal || i>j && !onlyUpperRight) {   
+					if (matrix[i][j]==MesquiteDouble.unassigned)
+						textFields[i][j] = new SingleLineTextField("",fieldLength);
+					else
+						textFields[i][j] = new SingleLineTextField(MesquiteDouble.toString(matrix[i][j]),fieldLength);
+					textFields[i][j].setBackground(Color.white);
+					lastField = textFields[i][j];
+					newPanel.add(textFields[i][j],constraints);					
+				}
+			}
+		}
+		if (!lastValueEditable && lastField!=null) {
+			lastField.setEditable(false);
+			lastField.setBackground(dialog.getBackground());
+		}
+		dialog.addNewDialogPanel(newPanel);
+	}
+	/*.................................................................................................................*/
+	public boolean getValidDouble () {
+		return valid;
+	}
+	/*.................................................................................................................*/
+	public void setLastValueEditable (boolean editable) {
+		lastValueEditable = editable;
+		if (lastField!=null) {
+			if (lastValueEditable) {
+				lastField.setEditable(true);
+				lastField.setBackground(Color.white);
+		}
+			else {
+				lastField.setEditable(false);
+				lastField.setBackground(dialog.getBackground());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean getLastValueEditable () {
+		return lastValueEditable;
+	}
+	/*.................................................................................................................*/
+	public double getValue (int row, int column) {
+		if (row>=textFields.length)
+			return MesquiteDouble.unassigned;
+		if (column>=textFields[0].length)
+			return MesquiteDouble.unassigned;
+		SingleLineTextField SLTF = textFields[row][column];
+		if (SLTF==null)
+			return MesquiteDouble.unassigned;
+		String s = SLTF.getText();
+		double value = MesquiteDouble.fromString(s);
+		valid=true;
+		if (!MesquiteDouble.isCombinable(value)) {
+			valid = false;
+			value=matrix[row][column];
+		}
+		return value;
+	}
+	
+	/*.................................................................................................................*/
+	public Double2DArray getDouble2DArray () {
+		Double2DArray newArray = new Double2DArray(matrix);
+		int numRows = matrix.length;
+		for (int row= 0; row<numRows; row++)  { //cycle through rows 
+			for (int column= 0; column<matrix[0].length; column++) {
+				newArray.setValue(row, column, getValue(row,column));
+			}
+		}
+		return  newArray;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/DragRectangle.java b/Source/mesquite/lib/DragRectangle.java
new file mode 100644
index 0000000..4094bff
--- /dev/null
+++ b/Source/mesquite/lib/DragRectangle.java
@@ -0,0 +1,88 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+/**A class to indicate how something is to be colored, either an array of colors to be shown in equal pieces, or 
+same with distribution of weights for pie slices.  A maximum number of 64 colors may be shown.*/
+public class DragRectangle {
+	int whichDown = MesquiteInteger.unassigned;
+	int xDown = MesquiteInteger.unassigned;
+	int yDown = MesquiteInteger.unassigned;
+	int xDrag = MesquiteInteger.unassigned;
+	int yDrag = MesquiteInteger.unassigned;
+	Graphics g;
+	
+	public DragRectangle(Graphics g, int xDown, int yDown){
+		this.g = g;
+		this.xDown=xDown;
+		this.yDown = yDown;
+		xDrag = xDown;
+		yDrag= yDown;
+		drawRectangleUpDown();
+	}
+	public DragRectangle(){
+	}
+	public void drawFirstRectangle(Graphics g, int xDown, int yDown){
+		this.g = g;
+		this.xDown=xDown;
+		this.yDown = yDown;
+		xDrag = xDown;
+		yDrag= yDown;
+		drawRectangleUpDown();
+	}
+	/* ----------------------------------*/
+	void drawRect(Graphics g, int x1, int y1, int x2, int y2){
+		if (x1>x2){
+			if (y1>y2)
+				g.drawRect(x2, y2, x1-x2, y1-y2);
+			else 
+				g.drawRect(x2, y1, x1-x2, y2-y1);
+		}
+		else {
+			if (y1>y2)
+				g.drawRect(x1, y2, x2-x1, y1-y2);
+			else 
+				g.drawRect(x1, y1, x2-x1, y2-y1);
+		}
+	}
+	/* ----------------------------------*/
+	public void drawRectangleUpDown(){
+    		if (g!=null && GraphicsUtil.useXORMode(g, false)){
+	    		g.setXORMode(Color.white);
+	   		g.setColor(Color.black);
+			drawRect(g, xDown, yDown,  xDrag, yDrag);
+		}
+	}
+	/* ----------------------------------*/
+	public void drawRectangleDrag(int xPixel, int yPixel){
+    		if (g!=null&& GraphicsUtil.useXORMode(g, false)){
+	    		g.setXORMode(Color.white);
+	   		g.setColor(Color.black);
+			drawRect(g, xDown, yDown,  xDrag, yDrag);
+			drawRect(g, xDown, yDown,  xPixel, yPixel);
+			xDrag=xPixel;
+			yDrag=yPixel;
+		}
+	}
+	/* ----------------------------------*/
+	public void dispose(){
+    		if (g!=null){
+	    		g.dispose();
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/ETContentArea.java b/Source/mesquite/lib/ETContentArea.java
new file mode 100644
index 0000000..3fc0760
--- /dev/null
+++ b/Source/mesquite/lib/ETContentArea.java
@@ -0,0 +1,62 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+/** The ContentArea specifically to show the tree of EmployeeModules.*/
+class ETContentArea extends ContentArea {
+	MesquiteModule focalModule;
+	HPanel browser;
+	public ETContentArea(MesquiteModule focalModule){
+		super(null);
+		mainPanel.setLayout(new CardLayout());
+		
+		this.focalModule = focalModule;
+		if (focalModule!=null){
+			browser = focalModule.getBrowserPanel();
+			if (browser !=null){
+				browser.setTitle("Employees of \"" + focalModule.getName() + "\"");
+				add(browser, "browser");
+				browser.setVisible(true);
+				browser.setBackground(ColorDistribution.lightYellow);
+				browser.setRootNode(focalModule);
+				browser.renew();
+			}
+		}
+	}
+	/** Gets the browser panel used to show the tree of employee modules */
+	public HPanel getBrowser(){
+		return browser;
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		if (browser !=null)
+			browser.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w,h);
+		if (browser !=null)
+			browser.setSize(w,h);
+	}
+
+	public void dispose(){
+		focalModule=null;
+		if (browser !=null)
+			browser.dispose();
+	}
+}
+
diff --git a/Source/mesquite/lib/EmployeeNeed.java b/Source/mesquite/lib/EmployeeNeed.java
new file mode 100644
index 0000000..53ff97f
--- /dev/null
+++ b/Source/mesquite/lib/EmployeeNeed.java
@@ -0,0 +1,139 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+
+public class EmployeeNeed  {
+	public static int REQUIRED = 0;
+	public static int THISOROTHERREQUIRED = 1;
+	public static int OPTIONAL = 2; 
+	
+	int requiredStatus = REQUIRED;
+	EmployeeNeed alternativeRequired = null; //when THISOROTHERREQUIRED, please indicate which is other that can substitute
+	Class dutyClass = null;
+	String explanation = null;
+	String accessPoint = null;
+	String alternativeEmployerLabel = null;
+	int priority = 0;
+	boolean suppressListing = false;
+	boolean emphasize = false;
+	int whichOne = 0;  //use to distinguish if more than one of same duty class
+	MesquiteModuleInfo requestor;
+	boolean isEntryPoint = false;
+	
+	public EmployeeNeed(Class dutyClass, String explanation, String accessPoint){  //Todo: should also store how this is accessed by the employer (e.g. entry points)
+		this.dutyClass = dutyClass;
+		this.explanation = explanation;
+		this.accessPoint = accessPoint;
+	}
+	/*------------------------------*/
+	public MesquiteModuleInfo getRequestor(){
+		return requestor;
+	}
+	public void setRequestor(MesquiteModuleInfo r){
+		requestor = r;
+	}
+	/*------------------------------*/
+	public String getAlternativeEmployerLabel(){
+		return alternativeEmployerLabel;
+	}
+	public void setAlternativeEmployerLabel(String r){
+		alternativeEmployerLabel = r;
+	}
+	/*------------------------------*/
+	public int getPriority(){
+		return priority;
+	}
+	public void setPriority(int r){
+		priority = r;
+	}
+	/*------------------------------*/
+	public boolean getSuppressListing(){
+		return suppressListing;
+	}
+	public void setSuppressListing(boolean r){
+		suppressListing = r;
+	}
+	/*------------------------------*/
+	public boolean getEmphasize(){
+		return emphasize;
+	}
+	public void setEmphasize(boolean r){
+		emphasize = r;
+	}
+		
+	/*------------------------------*/
+	public Class getDutyClass(){
+		return dutyClass;
+	}
+	public void setDutyClass(Class d){
+		 dutyClass = d;
+	}
+	/*------------------------------*/
+	public String getExplanation(){
+		return explanation;
+	}
+	public void setExplanation(String e){
+		 explanation = e;
+	}
+	/*------------------------------*/
+	public String getAccessPoint(){
+		return accessPoint;
+	}
+	public void setAccessPoint(String e){
+		accessPoint = e;
+	}
+	/*------------------------------*/
+	public void setAlternative(EmployeeNeed e){
+		alternativeRequired = e;
+	}
+	public EmployeeNeed getAlternative(){
+		return alternativeRequired;
+	}
+	/*------------------------------*/
+	public void setRequiredStatus(int status){
+		requiredStatus = status;
+	}
+	public int getRequiredStatus(){
+		return requiredStatus;
+	}
+	/*------------------------------*/
+	public void setWhichOne(int w){
+		whichOne = w;
+	}
+	public int getWhichOne(){
+		return whichOne;
+	}
+	/*------------------------------*/
+	String entryCommand = null;
+	/*------------------------------*/
+	public void setAsEntryPoint(String command){
+		isEntryPoint = true;
+		entryCommand = command;
+	}
+	public boolean isEntryPoint(){
+		return isEntryPoint;
+	}
+	public String getEntryCommand(){
+		return entryCommand;
+	}
+	public void setEntryCommand(String command){
+		entryCommand = command;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/EmployeeVector.java b/Source/mesquite/lib/EmployeeVector.java
new file mode 100644
index 0000000..0508854
--- /dev/null
+++ b/Source/mesquite/lib/EmployeeVector.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** Vector of employee tasks (MesquiteModule objects).  Each MesquiteModule keeps such a list.*/
+public class EmployeeVector extends ListableVector {
+	public  EmployeeVector () {
+		super();
+		notifyOfChanges = false;
+	}
+	public void dispose(){
+		removeAllElements(false);
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+	 				listener.disposing(this);
+				}
+		}
+		disposed = true;
+		super.dispose();
+	}
+}
+
diff --git a/Source/mesquite/lib/EmployerEmployee.java b/Source/mesquite/lib/EmployerEmployee.java
new file mode 100644
index 0000000..f20d35e
--- /dev/null
+++ b/Source/mesquite/lib/EmployerEmployee.java
@@ -0,0 +1,2076 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** This is a superclass of MesquiteModule that handles the employee-employer relations. It is intended to be used only as a superclass of MesquiteModule */
+public abstract class EmployerEmployee extends MenuOwner implements HNode, Listable {
+	/** The Class the module was hired as; i.e., the duty is was hired to fulfill */
+	Class hiredAs = null;
+
+
+	/** Stored here by the employer so that Mesquite can use it to hire a replacement if this module quits */
+	MesquiteCommand hiringCommand = null;
+
+	/** The condition under which this module was hired */
+	Object hiringCondition = null;
+
+	/** The employee tasks (employee MesquiteModule objects) of this task (module) */
+	protected EmployeeVector employees = null; // TODO: make private and force MesquiteModule to use method????
+
+	/** The employer task (i.e., the MesquiteModule that hired this module) */
+	protected MesquiteModule employer = null;
+
+	/** Suppresses the dialogs to choose alternative employees on hiring; acts as if */
+	public static boolean suppressHireQueries = false;
+
+	/** Divide menu choices into primary and secondary */
+	public static boolean useOtherChoices = false;
+
+	/** Whether secondary choices are shown by default in dialog boxes */
+	public static boolean secondaryChoicesOnInDialogs = true;
+
+	/** Whether subchoices are shown in module choice dialog boxes */
+	public static boolean subChoicesOnInDialogs = true;
+
+	private static boolean showHiringPath = false;
+
+	private boolean fixedPriority = false;
+
+	private String explanationByWhichHired;
+
+	boolean inStartup = false;
+
+	protected boolean startupBailOut = false; // used if startup process cancelled, so that "sorry" and attempted rehires don't appear
+
+	Vector employeeNeedsVector; // a vector of registered employee needs, used for documentation/searches of how to do analyses, but perhaps eventually also used in hiring
+
+	static MesquiteTimer moduleStartupTime;
+
+	public static int totalCreated = 0;
+
+	public static int totalDisposed = 0;
+
+	protected MesquiteInteger stringPos = new MesquiteInteger(0);
+	static {
+		moduleStartupTime = new MesquiteTimer();
+	}
+	public EmployerEmployee() {
+		totalCreated++;
+	}
+	public boolean isInStartup(){
+		return inStartup;
+	}
+	public void setEmployeesInStartup(boolean i){
+		setInStartup(i);
+		if (employees == null)
+			return;
+		for (int k = 0; k< employees.size(); k++){
+			MesquiteModule mb = (MesquiteModule)employees.elementAt(k);
+			mb.setEmployeesInStartup(i);
+		}
+	}
+	public void setInStartup(boolean i){
+		inStartup = i;
+	}
+	public static void setShowHiringPath(boolean show) {
+		showHiringPath = show;
+	}
+
+	protected Vector getEmployeeNeedsVector() { // This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		return employeeNeedsVector;
+	}
+
+	protected void getEmployeeNeeds() { // This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		/*
+		 * EmployeeNeed e = registerEmployeeNeed(DUTYCLASS.class, getName() + " needs XXXX.", "You can request xxxxx when " + getName() + " starts, or later under xxxxx."); //e.setAsEntryPoint(true);
+		 */
+	}
+
+	public EmployeeNeed findEmployeeNeed(Class employeeClass) {
+		Vector v = module.getModuleInfo().getEmployeeNeedsVector();
+		if (v == null)
+			return null;
+		for (int i=0; i< v.size(); i++){
+			EmployeeNeed need = (EmployeeNeed)v.elementAt(i);
+			if (need.getDutyClass().isAssignableFrom(employeeClass))
+				return need;
+		}
+		return null;
+	}
+	protected String listNeeds() {
+		Vector v = module.getModuleInfo().getEmployeeNeedsVector();
+		if (v == null)
+			return "";
+		String s = "";
+		for (int i=0; i< v.size(); i++){
+			EmployeeNeed need = (EmployeeNeed)v.elementAt(i);
+			s += "   " + need.getDutyClass().getName() + "\n";
+		}
+		return s;
+	}
+	protected EmployeeNeed registerEmployeeNeed(Class dutyClass, String whatINeed, String entryPoint) {
+		EmployeeNeed e = new EmployeeNeed(dutyClass, whatINeed, entryPoint);
+		if (employeeNeedsVector == null)
+			employeeNeedsVector = new Vector();
+		employeeNeedsVector.addElement(e);
+		return e;
+	}
+
+	protected EmployeeNeed registerEmployeeNeed(Class dutyClass, int whichOne, String whatINeed, String entryPoint) {
+		EmployeeNeed e = new EmployeeNeed(dutyClass, whatINeed, entryPoint);
+		e.setWhichOne(whichOne);
+		if (employeeNeedsVector == null)
+			employeeNeedsVector = new Vector();
+		employeeNeedsVector.addElement(e);
+		return e;
+	}
+
+	public boolean getSearchableAsModule() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public HNode[] getHDaughters() {
+		if (employees == null || employees.size() == 0)
+			return null;
+		int num = employees.size();
+		HNode[] daughters = new HNode[num];
+		for (int i = 0; i < num; i++)
+			daughters[i] = (HNode) employees.elementAt(i);
+		return daughters;
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public HNode getHMother() {
+		return employer;
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public int getNumSupplements() {
+		int numSupp = 0;
+		if (module.getManualPath() != null)
+			numSupp++;
+		if (module.getModuleWindow() != null)
+			numSupp++;
+		// if (module.getCommandPagePath()!= null)
+		// numSupp++;
+		return numSupp;
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public String getSupplementName(int index) {
+		// if (module.getManualPath()!= null && index == 0)
+		if (index == 0) {
+			if (module.getManualPath() != null)
+				return "Manual";
+			else
+				return "Window";
+		}
+		else if (index == 1)
+			return "Window";
+		else
+			return "";
+		// else if (module.getCommandPagePath()!= null)
+		// return "Menus & Commands";
+		// else
+		// return "";
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public void hNodeAction(Container c, int x, int y, int action) {
+		if (c == null)
+			return;
+		if (action == HNode.MOUSEMOVE) {
+			MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+			if (f != null && f instanceof MesquiteWindow) {
+				String versionString = module.getVersion();
+				if (versionString == null)
+					versionString = "?";
+				String t = "Module: " + module.getName() + "     Version: " + versionString + "     Author(s): " + module.getAuthors() + "\nClass: " + module.getClass().getName() + "\nExplanation: " + module.getExplanation() + "\n" + "Current Parameters: " + module
+						.getParameters() + "\n" + "[id: " + module.getID() + "]";
+				((MesquiteWindow) f).setExplanation(t);
+			}
+		}
+		else if (action == HNode.MOUSEEXIT) {
+			/*
+			 * Frame f = module.containerOfModule(); if (f != null && f instanceof MesquiteWindow){ ((MesquiteWindow)f).setExplanation(""); }
+			 */
+		}
+		else if (action == HNode.MOUSEDOWN) {
+			MesquitePopup popup = new MesquitePopup(c);
+			popup.addItem("Show Information page", module, module.makeCommand("showCommandPage", module));
+			popup.addItem("Show Mini Info Window", module, module.makeCommand("showMiniInfoWindow", module));
+			// Danny's code for eclipse integration. I don't know if it should be on by default so
+			// I'm commenting it out for now.
+			// popup.addItem("Open source in Eclipse", module, module.makeCommand("openSourceInEclipse", module));
+			popup.showPopup(x, y);
+		}
+	}
+
+	/** for HNode interface */
+	public String getTypeName() {
+		return "Module";
+	}
+
+	/* ................................................................................................................. */
+	/** for HNode interface */
+	public void hSupplementTouched(int index) {
+		// if (module.getManualPath()!= null)
+		module.showManual();
+		// else if (module.getCommandPagePath()!= null)
+		// module.showWebPage(module.getCommandPagePath());
+	}
+
+	/* ---------------- for HNode interface ---------------------- */
+	public Image getHImage() {
+		if (module.isPrerelease() && module.isSubstantive())
+			return InfoBar.prereleaseImage;
+		return null;
+	}
+
+	/* ---------------- for HNode interface ---------------------- */
+	public Color getHColor() {
+		if (!module.isSubstantive())
+			return ColorDistribution.lightGreen;
+		if (module.isPrerelease())
+			return Color.red;
+		else
+			return Color.green;
+	}
+
+	/* ---------------- for HNode interface ---------------------- */
+	public boolean getHShow() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns Class the module was hired as, thus implicitly the duty it is to perform */
+	public Class getHiredAs() {
+		return hiredAs;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns object passed as a condition to hiring */
+	public Object getHiringCondition() {
+		return hiringCondition;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns whether or not it's appropriate for an employer to hire more than one instance of this module. If false then is hired only once; second attempt fails.
+	 */
+	public boolean canHireMoreThanOnce() {
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the purpose for which this module was hired (response comes from employer). */
+	public final String whatIsMyPurpose() {
+		if (employer == null)
+			return "";
+		else
+			return employer.purposeOfEmployee(module);
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis"). */
+	public String purposeOfEmployee(MesquiteModule employee) {
+		return "for " + getName(); // to be overridden
+	}
+
+	/* ................................................................................................................. */
+	void setExplanationByWhichHired(String exp) {
+		explanationByWhichHired = exp;
+	}
+
+	/* ................................................................................................................. */
+	public String getExplanationByWhichHired() {
+		return explanationByWhichHired;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns vector of employees. */
+	public void moveEmployeeToFront(MesquiteModule employee) {
+		if (employee == null || employees.indexOf(employee) < 0)
+			return;
+		employees.removeElement(employee, false);
+		employees.insertElementAt(employee, 0, false);
+	}
+
+	/* ................................................................................................................. */
+	/** Returns vector of employees. */
+	public EmployeeVector getEmployeeVector() {
+		return employees;
+	}
+
+	/* ................................................................................................................. */
+	/** Makes vector of employees. */
+	protected void makeEmployeeVector() {
+		employees = new EmployeeVector();
+	}
+
+	/* ................................................................................................................. */
+	/** Returns number of employees modules of the MesquiteModule. */
+	public int getNumberOfEmployees() {
+		if (employees == null)
+			return 0;
+		else
+			return employees.size();
+	}
+
+	/* ................................................................................................................. */
+	/** returns true if this an employer of the passed MesquiteModule. */
+	public boolean isEmployerOf(MesquiteModule mb) {
+		if (this == mb || mb == null)
+			return false;
+		MesquiteModule mT = mb;
+		while (mT != null) {
+			if (mT == this)
+				return true;
+			else
+				mT = mT.employer;
+		}
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	/** returns the immediate employee of which given module is an eventual employee. */
+	public MesquiteModule employeeOfWhichEmployee(MesquiteModule mb) {
+		if (mb == this)
+			return null;
+		else if (mb.employer == this) {
+			return mb;
+		}
+		else {
+			MesquiteModule lastMt = mb;
+			MesquiteModule mT = mb;
+			while (mT != this && mT != null) {
+				lastMt = mT;
+				mT = mT.employer;
+			}
+			if (mT != null)
+				return lastMt;
+			else
+				return null;
+		}
+	}
+
+	/* ................................................................................................................. */
+	/** Lists the employees of this MesquiteModule. */
+	// TODO: use stringbuffer here (pass it)
+	public String listEmployees(String spacer) {
+		String thisBranch = "";
+
+		int num = employees.size();
+		spacer += "  ";
+		for (int i = 0; i < num; i++) {
+			Object obj = employees.elementAt(i);
+			MesquiteModule mb = (MesquiteModule) obj;
+			thisBranch += spacer + mb.getName() + StringUtil.lineEnding();
+			thisBranch += mb.listEmployees(spacer);
+		}
+		/*
+		 * Enumeration e = employees.elements(); spacer +=" "; while (e.hasMoreElements()) { Object obj = e.nextElement(); MesquiteModule mb = (MesquiteModule)obj; thisBranch += spacer + mb.getName() + StringUtil.lineEnding(); thisBranch += mb.listEmployees(spacer); }
+		 */
+		return thisBranch;
+		// don't need to trim spacer since not returned by reference
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Return the name of a given employee as known to the module. This name is the one to be used by the doCommand "getEmployee". It is used to allow modules to override it so as to give their own reference name to an employee. Thus, if an employer has several employees that are instantiations of the same module, "getEmployee 'employee name' would be ambiguous, but the employer can return separate names e.g., 'emp1', 'emp2' and then the command "getEmployee 'emp1'" would be unambiguous. Se [...]
+	 */
+	public String getEmployeeReference(MesquiteModule employee) {
+		if (employee == null)
+			return null;
+		else
+			return "#" + employee.getClass().getName();
+	}
+
+	/* ................................................................................................................. */
+	/** Find the first employee of given name. */
+	public MesquiteModule findEmployee(String name) {
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mb = (MesquiteModule) obj;
+			if (mb.getName().equals(name))
+				return mb;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Find the first employee of given class. */
+	public MesquiteModule findEmployee(Class dutyClass) {
+		if (dutyClass != null) {
+			Enumeration e = employees.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteModule mb = (MesquiteModule) obj;
+				if (dutyClass.isInstance(mb))
+					return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the module's employer. */
+	public String getEmployerPath() {
+		if (employer == null)
+			return getName();
+		else
+			return getEmployer().getEmployerPath() + ":" + getName();
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the module's employer. */
+	public MesquiteModule getEmployer() {
+		return employer;
+	}
+	/* ................................................................................................................. */
+	/** Returns whether the given module is employer OR higher. */
+	public boolean isEmployerOrHigher(EmployerEmployee e) {
+		if (e == employer)
+			return true;
+		EmployerEmployee empr = getEmployer();
+		while (empr != null){
+			if (empr == e)
+				return true;
+			empr = empr.getEmployer();
+		}
+		return false;
+	}
+	/* ................................................................................................................. */
+	/** Returns whether the given module is employer OR higher. */
+	public String dumpEmployers() {
+		String s = "";
+		EmployerEmployee empr = getEmployer();
+		while (empr != null){
+			s += empr.getClass().getName() + "  " + empr.module.getID() + "\n";
+			empr = empr.getEmployer();
+		}
+		return s;
+	}
+
+	/* ................................................................................................................. */
+	/** Sets whether module's order in employee rank is allowed to be changed. */
+	public void setPriorityFixed(boolean fixed) {
+		fixedPriority = fixed;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns whether module's order in employee rank is allowed to be changed. */
+	public boolean isPriorityFixed() {
+		return fixedPriority;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds most recent common employer between this and mb, and if needed swaps the positions of the two branches from this employer to ensure that mb's branch comes first in the employer list as opposed to this. Used, for instance, by modules requiring .
+	 */
+	public void deferBranchPriority(MesquiteModule mb) {
+		MesquiteModule mrce = getEmployer();
+		MesquiteModule thisBranch = mrce;
+		while (mrce != null) { // first, find mrce
+			if (mrce.isEmployerOf(mb)) { // mrce found
+				MesquiteModule otherBranch = mrce.employeeOfWhichEmployee(mb);
+				if (otherBranch.isPriorityFixed() || thisBranch.isPriorityFixed())
+					return;
+				int indexOfOther = mrce.employees.indexOf(otherBranch);
+				int indexOfThis = mrce.employees.indexOf(thisBranch);
+				if (indexOfOther > indexOfThis) {
+					mrce.employees.removeElement(otherBranch, false);
+					mrce.employees.insertElementAt(otherBranch, indexOfThis, false);
+					mrce.employees.removeElement(thisBranch, false);
+					mrce.employees.insertElementAt(thisBranch, indexOfOther, false);
+				}
+				return;
+			}
+			else {
+				thisBranch = mrce;
+				mrce = mrce.getEmployer();
+			}
+
+		}
+	}
+
+	/* ................................................................................................................. */
+	void doomAll() {
+		doomed = true;
+		if (employees == null)
+			return;
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			MesquiteModule mbe = (MesquiteModule) e.nextElement();
+			if (mbe != null) {
+				mbe.doomAll();
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	/** Closes all windows. */
+	public boolean closeEmployeeWindows(MesquiteModule butNotThis) {
+		boolean closed = false;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			closed = mb.closeEmployeeWindows(butNotThis) || closed;
+		}
+		if (this != butNotThis){
+			MesquiteWindow win = getModuleWindow();
+			if (win != null && win.isVisible()){
+				module.windowGoAway(win);
+				return true;
+			}
+		}
+		return closed;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first more senior employer in the heirarchy that belongs to a particular subclass. */
+	public MesquiteModule findEmployerWithDuty(Class dutyClass) {
+		if (employer == null)
+			return null;
+		else if (dutyClass.isInstance(employer))
+			return employer;
+		else
+			return employer.findEmployerWithDuty(dutyClass);
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first employee in the heirarchy that belongs to a particular subclass. */
+	public MesquiteModule findEmployeeWithDuty(Class dutyClass) {
+		return findEmployeeWithDuty(dutyClass, null);
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first immediate employee that belongs to a particular subclass. */
+	public MesquiteModule findImmediateEmployeeWithDuty(Class dutyClass) {
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (dutyClass.isInstance(mb) && mb != null && !mb.isDoomed()) {
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns an array of the immediate employees that belong to a particular subclass. */
+	public MesquiteModule[] getImmediateEmployeesWithDuty(Class dutyClass) {
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		int count = 0;
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (dutyClass.isInstance(mb) && mb != null && !mb.isDoomed()) {
+				count++;
+			}
+		}
+		if (count == 0)
+			return null;
+		MesquiteModule[] mods = new MesquiteModule[count];
+		count = 0;
+		enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (dutyClass.isInstance(mb) && mb != null && !mb.isDoomed()) {
+				mods[count++] = mb;
+			}
+		}
+		return mods;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the first employee in the heirarchy that belongs to a particular subclass. Doesn't return or pursue employees of the module "excluding"
+	 */
+	public MesquiteModule findEmployeeWithDuty(Class dutyClass, MesquiteModule excluding) {
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (dutyClass.isInstance(mb) && mb != excluding && mb != null && !mb.isDoomed()) {
+				return mb;
+			}
+		}
+		// not found among immediate employees; look deeper
+		if (employees == null)
+			return null;
+		enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != excluding && mb != null) {
+				MesquiteModule result = mb.findEmployeeWithDuty(dutyClass, excluding);
+				if (result != null)
+					return result;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the first employee in the heirarchy that belongs to a particular subclass. Doesn't return or pursue employees of the module "excluding"
+	 */
+	public MesquiteModule findNextEmployeeWithDuty(Class dutyClass, MesquiteModule excluding, MesquiteModule current, MesquiteBoolean found) {
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (dutyClass.isInstance(mb) && mb != excluding && mb != null && !mb.isDoomed()) {
+				if (mb != current)
+					found.setValue(true);
+				else if (found.getValue())
+					return mb;
+			}
+		}
+		// not found among immediate employees; look deeper
+		enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != excluding) {
+				MesquiteModule result;
+				if (found.getValue())
+					result = mb.findEmployeeWithDuty(dutyClass, excluding);
+				else
+					result = mb.findNextEmployeeWithDuty(dutyClass, excluding, current, found);
+				if (result != null)
+					return result;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first employee in the heirarchy that has a particular name. */
+	public MesquiteModule findEmployeeWithName(String name) {
+		return findEmployeeWithName(name, false);
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first employee in the heirarchy that has a particular name. */
+	public MesquiteModule findEmployeeWithName(String name, boolean immediate) {
+		if (StringUtil.blank(name))
+			return null;
+		if (employees == null)
+			return null;
+		boolean className = (name.charAt(0) == '#');
+		String useName;
+		if (className)
+			useName = name.substring(1, name.length());
+		else
+			useName = name;
+
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != null && !mb.isDoomed() && mb.nameMatches(useName)) {
+				return mb;
+			}
+		}
+		if (!immediate) {
+			// not found among immediate employees; look deeper
+			enumeration = employees.elements();
+			while (enumeration.hasMoreElements()) {
+				MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+				MesquiteModule result = mb.findEmployeeWithName(name);
+				if (result != null)
+					return result;
+			}
+		}
+		enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != null && !mb.isDoomed() && mb.getNameForMenuItem().equalsIgnoreCase(useName)) {
+				return mb;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the first employee in the heirarchy that has a particular name. Doesn't return or pursue employees of the module "excluding"
+	 */
+	public MesquiteModule findEmployeeWithName(String name, MesquiteModule excluding) {
+		if (StringUtil.blank(name))
+			return null;
+		if (employees == null)
+			return null;
+		boolean className = (name.charAt(0) == '#');
+		String useName;
+		if (className)
+			useName = name.substring(1, name.length());
+		else
+			useName = name;
+
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != null && mb != excluding && !mb.isDoomed() && mb.nameMatches(useName)) {
+				return mb;
+			}
+		}
+		// not found among immediate employees; look deeper
+		enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb != excluding) {
+				MesquiteModule result = mb.findEmployeeWithName(name, excluding);
+				if (result != null)
+					return result;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the employee with given idNumber */
+	public MesquiteModule findEmployeeWithIDNumber(long id) {
+		if (id < 0)
+			return null;
+		if (employees == null)
+			return null;
+		if (module.getID() == id)
+			return module;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			MesquiteModule result = mb.findEmployeeWithIDNumber(id);
+			if (result != null)
+				return result;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Find the employee with given permanent IDString. */
+	public MesquiteModule findEmployeeWithPermanentID(String id) {
+		if (id == null)
+			return null;
+		if (employees == null)
+			return null;
+		if (id.equalsIgnoreCase(module.getPermanentIDString())) // had been getAssignedIDString
+			return module;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			MesquiteModule result = mb.findEmployeeWithPermanentID(id);
+			if (result != null)
+				return result;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first colleague among employers & employers other employees that belongs to a particular subclass. */
+	public void findModules(Class dutyClass, ListableVector found) {
+		if (dutyClass.isInstance(this) && module != null && !module.isDoomed())
+			found.addElement(this, false);
+		if (employees == null)
+			return;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			mb.findModules(dutyClass, found);
+		}
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the first colleague among employers & employers other employees that belongs to a particular subclass, after the current. This searches only within this module's project.
+	 */
+	public ListableVector findModulesWithDuty(Class dutyClass) {
+		ListableVector found = new ListableVector();
+		FileCoordinator fc = getFileCoordinator();
+		if (fc == null) {
+			MesquiteMessage.println("oops, no file coordinator found in findModulesWithDuty");
+			return null;
+		}
+		fc.findModules(dutyClass, found);
+		return found;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the nearest module that belongs to a particular subclass. Searches first among employees, then among colleagues, then among modules of this project, then among modules across Mesquite.
+	 */
+	public MesquiteModule findNearestModuleWithDuty(Class dutyClass) {
+		MesquiteModule mb = findEmployeeWithDuty(dutyClass);
+		if (mb == null)
+			mb = findNearestColleagueWithDuty(dutyClass);
+		if (mb == null && getFileCoordinator() != null)
+			mb = getFileCoordinator().findEmployeeWithDuty(dutyClass);
+		if (mb == null)
+			mb = MesquiteTrunk.mesquiteTrunk.findEmployeeWithDuty(dutyClass);
+
+		return mb;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds the first colleague among employers & employers other employees that belongs to a particular subclass. Searches only within project of module.
+	 */
+	public MesquiteModule findNearestColleagueWithDuty(Class dutyClass) {
+		if (employer == null) // no employer, only employees; "colleagues" defined to exclude employees EXCEPT at root
+			return null;
+		else if (dutyClass.isInstance(employer) && employer != null && !employer.isDoomed()) // immediate employer suits
+			return employer;
+		else if (this != getFileCoordinator()) {
+			MesquiteModule sisterWithDuty = employer.findEmployeeWithDuty(dutyClass, module); // ask for employee excluding current
+			if (sisterWithDuty != null)// check sisters
+				return sisterWithDuty;
+			else
+				// sisters don't satisfy, thus find nearest colleague at employer's level, requesting it doesn't include current
+				return employer.findNearestColleagueWithDuty(dutyClass);
+		}
+		else
+			return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the first colleague among employers & employers other employees that belongs to a particular subclass. */
+	// TODO: this should probably be avoided, since names may change. In most cases in which it is used, it may be better to define a specific duty class
+	// TODO: check for # and classname
+	public MesquiteModule findNearestColleagueWithName(String name) {
+		if (employer == null || name == null) // no employer, only employees; "colleagues" defined to exclude employees
+			return null;
+		else if (name.equals(employer.getName()) && employer != null && !employer.isDoomed()) // immediate employer suits
+			return employer;
+		else if (this != getFileCoordinator()) {
+			MesquiteModule sisterWithDuty = employer.findEmployeeWithName(name, module); // ask for employee excluding current
+			if (sisterWithDuty != null)// check sisters
+				return sisterWithDuty;
+			else
+				// sisters don't satisfy, thus find nearest colleague at employer's level, requesting it doesn't include current
+				return employer.findNearestColleagueWithName(name);
+		}
+		else
+			return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the employee module of the file coordinator module that manages FileElements of the class passed. Used, for instance, to find the TreeManager */
+	public ElementManager findElementManager(Class fileElementClass) {
+		FileCoordinator fCoord = getFileCoordinator();
+		if (fCoord == null)
+			return null;
+		return fCoord.findManager(fCoord, fileElementClass);
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the module in charge of showing the data editor for a CharacterData object, if any */
+	public DataWindowMaker findCharacterDataEditorRec(mesquite.lib.characters.CharacterData data) {
+		if (this instanceof DataWindowMaker && ((DataWindowMaker) this).getCharacterData() == data)
+			return (DataWindowMaker) module;
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			DataWindowMaker mbc = mb.findCharacterDataEditorRec(data);
+			if (mbc != null)
+				return mbc;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the module in charge of showing the data editor for a CharacterData object, if any */
+	public DataWindowMaker findCharacterDataEditor(mesquite.lib.characters.CharacterData data) {
+		FileCoordinator fCoord = getFileCoordinator();
+		if (fCoord == null)
+			return null;
+		return fCoord.findCharacterDataEditorRec(data);
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the employee that curates a given class of characterModels */
+	public CharModelCurator findModelCuratorRec(Class modelClass) {
+		if (this instanceof CharModelCurator && ((CharModelCurator) this).curatesModelClass(modelClass))
+			return (CharModelCurator) module;
+		if (employees == null)
+			return null;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			CharModelCurator mbc = mb.findModelCuratorRec(modelClass);
+			if (mbc != null)
+				return mbc;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Finds the employee that curates a given class of characterModels */
+	public CharModelCurator findModelCurator(Class modelClass) {
+		FileCoordinator fCoord = getFileCoordinator();
+		if (fCoord == null)
+			return null;
+		return fCoord.findModelCuratorRec(modelClass);
+	}
+
+	/* ................................................................................................................. */
+	/** returns the file coordinator module for the project of this module */
+	public FileCoordinator getFileCoordinator() {
+		if (this instanceof FileCoordinator)
+			return (FileCoordinator) this;
+		else
+			return (FileCoordinator) findEmployerWithDuty(FileCoordinator.class);
+	}
+
+	/* ................................................................................................................. */
+	private boolean queryAbortFromInitiator(String explanation) {
+		// find initator of hire sequence. If this is not in startup, then don't do anything. If employer module is not in startup, then this is initiator and don't touch
+		// otherwise initiator is among employers; query use if want to stop, and if so go to initiator and mark all of its descendants as bail out
+		// bail out should cause startupEmployee to return null
+		// if (inStartup){
+		EmployerEmployee initiator = this;
+		while (initiator != null && initiator.employer != null && initiator.employer.inStartup) {
+			initiator = initiator.employer;
+		}
+		if (initiator != null) {
+
+			if (initiator != this) {
+				module.discreetAlert( "The request for " + initiator.getName() + " failed or was cancelled.");
+				markBailOut(initiator);
+			}
+			return true;
+		}
+		// }
+		return false;
+
+	}
+
+	private void markBailOut(EmployerEmployee ee) {
+		if (ee == null)
+			return;
+		ee.startupBailOut = true;
+		Enumeration e = ee.employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mb = (MesquiteModule) obj;
+			markBailOut(mb);
+		}
+	}
+
+	/* ................................................................................................................. */
+	/** This is the word to be used to describe the module as "active". You might wish to override this and replace it with "shown", or something like that. */
+	public String moduleActiveWord() {
+		return "active";
+	}
+
+	/* ................................................................................................................. */
+	public static String nameOfModuleBeingStarted = null;
+	/** Start up employee, with a given condition as a startup condition */
+	private boolean startupEmployee(MesquiteModule mb, Class dutyClass, Object condition, String arguments) {
+		if (mb == null)
+			return false;
+		//CommandRecord.tick("Starting module \"" + mb.getName() + "\"");
+		nameOfModuleBeingStarted = mb.getClass().getName();
+		int mreset = getMenuResetSuppression();
+		mb.inStartup = true;
+		if (!mb.canHireMoreThanOnce()) {
+			if (findImmediateEmployeeWithDuty(mb.getClass()) != null) {
+				if (!MesquiteThread.isScripting())
+					module.alert("\"" + mb.getName() + "\" is already " + mb.moduleActiveWord() + ".  Only one instance is allowed in this context.");
+				mb.inStartup = false;
+				mb.endJob();
+				mb.dispose();
+				nameOfModuleBeingStarted = null;
+				return false;
+			}
+		}
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.3) starting up conditionally " + mb.getName());
+		if (MesquiteTrunk.debugMode){
+			EmployeeNeed need = findEmployeeNeed(mb.getClass());
+			if (need == null) {
+				MesquiteMessage.println("@@@@@@@@@@@@@@@@@@@@");
+				MesquiteMessage.println("UNREGISTERED NEED: " + dutyClass.getName() + " for " + module.getModuleInfo().getClassName() + " (hiring " + mb.getModuleInfo().getClassName() + ")");
+				String ln = listNeeds();
+				if (!StringUtil.blank(ln))
+					MesquiteMessage.println(ln);
+			}
+		}
+		incrementMenuResetSuppression();
+		incrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+		refreshBrowser(MesquiteModule.class);
+		mb.resetContainingMenuBar(); // added Oct 99
+		mb.makeEmployeeVector();
+		mb.employer = module;
+		mb.proj = module.getProject();
+		mb.hiredAs = dutyClass;
+
+		int index = -1;
+		if (employees == null)
+			return false;
+		for (int i = this.employees.size() - 1; i >= 0; i--) {
+			MesquiteModule emb = (MesquiteModule) this.employees.elementAt(i);
+			if (emb.getIfLastEmployee()) {
+				index = i;
+			}
+		}
+		if (index >= 0) {
+			this.employees.insertElementAt(mb, index, false);
+		}
+		else
+			this.employees.addElement(mb, false);
+
+		boolean started = false;
+		Error errorToThrow = null;
+		try {
+			moduleStartupTime.start();
+			if (condition == null && StringUtil.blank(arguments)) {
+				started = mb.superStartJob(null, null, false);
+				if (started)
+					started = mb.startJob(null, null, false);
+				if (started)
+					mb.incrementNumStarts();
+			}
+			else {
+				started = mb.superStartJob(arguments, condition, false);
+				if (started)
+					started = mb.startJob(arguments, condition, false);
+				if (started)
+					mb.incrementNumStarts();
+			}
+		} 
+		catch (Exception e) {
+			started = false;
+			moduleStartupTime.end();
+			MesquiteDialog.closeWizard();
+			if (Thread.currentThread() instanceof MesquiteThread && ((MesquiteThread)Thread.currentThread()).dead()) {
+
+			}
+			else {
+				MesquiteFile.throwableToLog(this, e);
+				module.exceptionAlert(e, "There has been a problem starting a module (" + e.getClass() + ").  (module: " + mb.getName() + "; arguments: " + arguments  + "; module being started: " + nameOfModuleBeingStarted + "; EXCEPTION: " + e.getMessage() + "; exception class " + e.getClass() +  " [1])");
+			}
+			MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+			MesquiteTrunk.resetAllMenuBars();
+
+		} 
+		catch (Error e) {
+			started = false;
+			moduleStartupTime.end();
+			if (e instanceof OutOfMemoryError)
+				MesquiteTrunk.mesquiteTrunk.discreetAlert("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+
+			else if (!(e instanceof ThreadDeath)) {
+				MesquiteFile.throwableToLog(this, e);
+				errorToThrow = e;
+				if (e instanceof AbstractMethodError || e instanceof NoSuchMethodError ){
+					module.alert("There has been a problem starting a module (" + e.getClass() + ").  It appears that you have installed a package that is old or otherwise incompatible with this version of Mesquite.  The incompatible package is probably listed under Extra Packages Installed at the start of the log.  (module: " + mb.getName() + "; arguments: " + arguments + "; module being started: " + nameOfModuleBeingStarted + "; ERROR: " + e.getMessage() + "; error class " + e.getClass() + " [2'])");
+					errorToThrow = null;
+				}
+				else if (e instanceof NoClassDefFoundError )
+					module.alert("There has been a problem starting a module (" + e.getClass() + ").  It appears that a component of Mesquite or a required library is missing; this probably means that something was installed correctly.  (module: " + mb.getName() + "; arguments: " + arguments + "; module being started: " + nameOfModuleBeingStarted + "; ERROR: " + e.getMessage() + "; error class " + e.getClass() + " [2'])");
+				else
+					module.exceptionAlert(e, "There has been a problem starting a module (" + e.getClass() + ").  This may be the result of an old, incompatible package being used, or part of Mesquite was accidentally deleted.  (module: " + mb.getName() + "; arguments: " + arguments  + "; module being started: " + nameOfModuleBeingStarted + "; ERROR: " + e.getMessage() + "; error class " + e.getClass() + " [2])");
+			}
+			MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+			MesquiteTrunk.resetAllMenuBars();
+		}
+
+		if (!started) {
+			if (showHiringPath)
+				MesquiteMessage.warnProgrammer("(HIRING.4) FAILED TO START " + mb.getName());
+			mb.inStartup = false;
+			mb.endJob();
+			mb.dispose();
+			/*
+			 * mb.dispose(); this.employees.removeElement(mb);
+			 */
+			// MesquiteMessage.warnUser("Module \"" + mb.getName() + "\" unable to start.");
+			if (errorToThrow != null) {
+				setMenuResetSuppression(mreset);
+				nameOfModuleBeingStarted = null;
+				throw errorToThrow;
+			}
+			else {
+				setMenuResetSuppression(mreset);
+				decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+				nameOfModuleBeingStarted = null;
+				return false;
+			}
+		}
+		mb.internalStartUp();
+		decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+		decrementMenuResetSuppression();
+		mb.inStartup = false;
+		nameOfModuleBeingStarted = null;
+		return !mb.startupBailOut;
+	}
+
+	/* ................................................................................................................. */
+	/** calls c.newInstance() to instantiate a module. Catches exceptions and errors and records & reports them */
+	public MesquiteModule instantiateModule(Class c) {
+		if (c == null)
+			return null;
+		try {
+			return (MesquiteModule) c.newInstance();
+		} catch (Exception e) {
+			if (Thread.currentThread() instanceof MesquiteThread && ((MesquiteThread)Thread.currentThread()).dead()) {
+			}
+			else {
+				MesquiteFile.throwableToLog(this, e);
+				module.exceptionAlert(e, "There has been a problem starting a module (" + e.getClass() + ").  This may be the result of an old, incompatible module being used.  The calling module is " + module.getName() + " and the module being started is of class " + c + ".  Error: " + e.getMessage() + "");
+			}
+		} catch (Error e) {
+			MesquiteFile.throwableToLog(this, e);
+			if (e instanceof NoSuchMethodError)
+				module.exceptionAlert(e, "There has been a problem starting a module (NoSuchMethodError).  This may be the result of an old, incompatible module being used.  The calling module is " + module.getName() + " and the module being started is of class: " + c + "");
+			else
+				module.exceptionAlert(e, "There has been a problem starting a module (" + e.getClass() + ").  This may be the result of an old, incompatible module being used.  The calling module is " + module.getName() + " and the module being started is of class " + c + ".  Error: " + e.getMessage() + "");
+			throw e;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Instantiate an employee and sets a few of its critical fields (employer, moduleInfo) */
+	public MesquiteModule instantiateEmployee(MesquiteModuleInfo mbi) {
+		if (mbi == null)
+			return null;
+		MesquiteModule mb = instantiateModule(mbi.mbClass);
+		if (mb != null) {
+			mb.employer = module;
+			mb.moduleInfo = mbi;
+			if (module == null)
+				MesquiteMessage.warnProgrammer("employer null in instantiateEmployee " + this);
+		}
+		return mb;
+	}
+
+	/* ................................................................................................................. */
+	/** hires an employee, perhaps with the passed supplementary string and condition */
+	private MesquiteModule hire(MesquiteModuleInfo mbi, Class dutyClass, Object condition, String arguments, String explByWhichHired) {
+		if (mbi == null)
+			return null;
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.8) hire(MesquiteModule mb, Class dutyClass, String supplementary, Object condition)");
+		Vector hiringPath = CommandRecord.getHiringPathS();
+		if (hiringPath != null && hiringPath.size()>0){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)hiringPath.lastElement();
+			if (mbi == mmi){
+				hiringPath.removeElementAt(hiringPath.size()-1);
+			}
+		}
+		incrementMenuResetSuppression();
+		try {
+			MesquiteModule mb = instantiateEmployee(mbi);
+			mb.setExplanationByWhichHired(explByWhichHired);
+
+			if (startupEmployee(mb, dutyClass, condition, arguments)) {
+				if (getMenuResetSuppression() == 0) {
+					MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteModule.class);
+				}
+				decrementMenuResetSuppression();
+				if (mb != null)
+					mb.hiringCondition = condition;
+				return mb;
+			}
+		}
+		catch (AbstractMethodError e){
+			module.exceptionAlert(e, "There has been a problem starting a module (" + e.getClass() + ").  It appears that you have installed a package that is old or otherwise incompatible with this version of Mesquite.  (module: " + mbi.getName() + "; arguments: " + arguments + "; ERROR: " + e.getMessage() + "; error class " + e.getClass() + " [h'])");
+			throw e;
+		}
+		decrementMenuResetSuppression();
+
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that has given name (name should be first token of arguments. If name is null, first MesquiteModule found of the class is employeed.
+	 */
+	public MesquiteModule hireNamedEmployee(Class dutyClass, String arguments) {
+		return hireNamedEmployee(dutyClass, arguments, null, false);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that has given name. If name is null, first MesquiteModule found of the class is employeed.
+	 */
+	public MesquiteModule hireNamedEmployee(Class dutyClass, String arguments, Object condition) {
+		return hireNamedEmployee(dutyClass, arguments, condition, false);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that has given name. If name is null, first MesquiteModule found of the class is employeed.
+	 * <p><p>To pass multiple module names in arguments (i.e. for subsequent hiring instructions), use the format:
+	 * <br><br>"$ #NameOfFirstModule supplementaryArguments" <br><br>For example, to hire a TreeSource that is a ConsensusTreesFromBlocks AND
+	 * upon hiring, pass the arguments for the source of trees to consense to be SimulatedTreeBlocks, then the  
+	 * arguments String would be: "$ #ConsensusTreesFromBlocks #SimulatedTreeBlocks"
+	 */
+	public MesquiteModule hireNamedEmployee(Class dutyClass, String arguments, Object condition, boolean warnIfNotFound) {
+		if (startupBailOut)
+			return null;
+		if (arguments == null)
+			return null;
+		incrementMenuResetSuppression();
+		String moduleName;
+		String supplementary = null;
+		if (ParseUtil.firstDarkChar(arguments) == '$') { // name is quoted; try to find actual name of module
+			moduleName = parser.getTokenNumber(arguments, 2);
+			supplementary = StringUtil.tokenize(parser.getNextToken()); // if second token after module name, pass to module via the arguments of startJob as hiring subchoice
+		}
+		else
+			moduleName = parser.getFirstToken(arguments);
+		if (StringUtil.blank(arguments)) {
+			decrementMenuResetSuppression();
+			return null;
+		}
+		if ("?".equals(moduleName)) {
+			boolean wasScrip = MesquiteThread.isScripting();
+			CommandRecord rec = MesquiteThread.getCurrentCommandRecord();
+			if (rec != null)
+				rec.setScripting(false);
+			MesquiteModule mm = hireEmployee(dutyClass, "Choose Module");
+			if (rec != null)
+				rec.setScripting(wasScrip);
+			decrementMenuResetSuppression();
+			return null;
+		}
+		MesquiteModuleInfo c = MesquiteTrunk.mesquiteModulesInfoVector.findModule(dutyClass, moduleName);
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.12) named is sought " + whichModInfo(c));
+
+		MesquiteModule mb = null;
+		if (c != null) { // module info for that name was found; try to hire the module
+			if (showHiringPath)
+				MesquiteMessage.warnProgrammer("(HIRING.14) module about to be hired " + whichModInfo(c));
+			mb = hire(c, dutyClass, condition, supplementary, null);
+		}
+		else if (warnIfNotFound) { // module info for that name was not found !MesquiteThread.isScripting() &&
+
+			warnUserModuleNotFound(moduleName);
+			// MesquiteMessage.warnUser("Named module not found for duty " + dutyClass.getName() + "; Modules sought: " + arguments);
+		}
+		decrementMenuResetSuppression();
+		return mb;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class. If explanation is given and scripting is false, will query user first if more than one.
+	 */
+	public MesquiteModule hireEmployee(Class dutyClass, String explanation) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.5) hireEmployee ( Class dutyClass, String explanation)");
+		return findAndHire(dutyClass, null, explanation);
+	}
+	/* ................................................................................................................. */
+	protected Listable[] prioritize(Listable[] moduleInfos, Class dutyClass){
+		if (moduleInfos == null)
+			return null;
+		boolean secondaryExist = false;
+		Listable[] p = new Listable[moduleInfos.length];
+		int count = 0;
+		for (int i= 0; i< moduleInfos.length; i++){
+			if (((Prioritizable)moduleInfos[i]).isFirstPriority(dutyClass))
+				p[count++] = moduleInfos[i];
+			else
+				secondaryExist = true;
+		}
+		for (int i= 0; i< moduleInfos.length; i++)
+			if (!((Prioritizable)moduleInfos[i]).isFirstPriority(dutyClass))
+				p[count++] = moduleInfos[i];
+		return p;
+	}
+	/* ................................................................................................................. */
+	protected MesquiteModule[] prioritize(MesquiteModule[] modules, Class dutyClass){
+		if (modules == null)
+			return null;
+		boolean secondaryExist = false;
+		MesquiteModule[] p = new MesquiteModule[modules.length];
+		int count = 0;
+		for (int i= 0; i< modules.length; i++){
+			MesquiteModuleInfo mmi = modules[i].getModuleInfo();
+			if (((Prioritizable)mmi).isFirstPriority(dutyClass))
+				p[count++] = modules[i];
+			else
+				secondaryExist = true;
+		}
+		for (int i= 0; i< modules.length; i++){
+			MesquiteModuleInfo mmi = modules[i].getModuleInfo();
+			if (!((Prioritizable)mmi).isFirstPriority(dutyClass))
+				p[count++] = modules[i];
+		}
+		return p;
+	}
+
+	protected Listable queryChooseModule(String message, Class dutyClass, Object condition, MesquiteString arguments, Listable[] names, int current, StringBuffer compatibilityReport) {
+		//		MesquiteInteger io = new MesquiteInteger(current);
+		Vector hiringPath = CommandRecord.getHiringPathS();
+		if (hiringPath != null && hiringPath.size()>0){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)hiringPath.lastElement();
+			if (dutyClass.isAssignableFrom(mmi.getModuleClass()) && (condition == null || mmi.isCompatible(condition, module.getProject(), this))){
+				return mmi;
+			}
+		}
+		String s = MesquiteString.helpString;
+		if (StringUtil.blank(s)) {
+			String duty = MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.getDutyName(dutyClass);
+
+			s = "<h3>" + duty + "</h3>";
+			EmployeeNeed need = findEmployeeNeed(dutyClass);
+			if (need != null)
+				s += need.getExplanation();
+			else {
+				s += "<p>(Needed by " + getName() + ")";
+				if (MesquiteTrunk.debugMode)
+					s += "<br>" + module.getModuleInfo().getShortClassName();
+			}
+
+		}
+		if (!StringUtil.blank(compatibilityReport))
+			s += "<hr><h4>Note</h4>" +compatibilityReport.toString();
+		names = prioritize(names, dutyClass);
+		if (subChoicesOnInDialogs){
+			//embedding hiring subchoices (new to 2. 01)
+			int countExtras = 0;
+			for (int i=0; i< names.length; i++){
+				MesquiteModuleInfo mci = (MesquiteModuleInfo)names[i];
+				if (mci.getHireSubchoice()!= null){
+					Listable[] sub = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(mci.getHireSubchoice(), condition, null, null);
+					if (sub != null)
+						countExtras += sub.length;
+				}
+			}
+			if (countExtras > 0){
+				boolean[] isSubchoice = new boolean[countExtras + names.length];
+				Listable[] newList = new Listable[countExtras + names.length];
+				int count = 0;
+				for (int i=0; i< names.length; i++){
+					MesquiteModuleInfo mci = (MesquiteModuleInfo)names[i];
+					newList[count] = mci;
+					isSubchoice[count++] = false;
+					if (mci.getHireSubchoice()!= null){  
+						Listable[] sub = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(mci.getHireSubchoice(), condition, null, null);
+						sub = prioritize(sub, mci.getHireSubchoice());
+						if (sub != null){
+							for (int k = 0; k< sub.length; k++){
+								isSubchoice[count] = true;
+								newList[count++] = sub[k];
+							}
+						}
+					}
+				}
+
+				int chosen =   ListDialog.queryModuleList(module, "Select", message, s, newList, isSubchoice, true, dutyClass, 0);
+
+				if (!MesquiteInteger.isCombinable(chosen))
+					return null;
+				if (isSubchoice[chosen]){
+
+					if (arguments != null){
+						MesquiteModuleInfo mci = (MesquiteModuleInfo)newList[chosen];
+						arguments.setValue("#" + mci.getClassName()); 
+					}
+					for (int k = chosen-1; k>=0; k--){
+						if (!isSubchoice[k])
+							return newList[k];
+					}
+					if (arguments != null)
+						arguments.setValue((String)null);
+					return null;
+				}
+				else
+					return newList[chosen];
+			}
+		}
+		return (MesquiteModuleInfo) ListDialog.queryModuleList(module, "Select", message, s, names, true, dutyClass, 0);
+	}
+	protected boolean acceptCancelInHireEmployee = true;
+	protected void acceptEmployeeHireCancel(boolean accept){
+		this.acceptCancelInHireEmployee = accept;
+	}
+	/* ................................................................................................................. */
+	/** Looks for (perhaps asking the user) and hires a compatible MesquiteModule that is instance of the given class */
+	private MesquiteModule findAndHire(Class dutyClass, Object condition, String explanation) {
+		if (startupBailOut)
+			return null;
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.9) findAndHire ( Class dutyClass, Object condition, String explanation)");
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return null;
+		incrementMenuResetSuppression();
+		int numAvailable = numCompatibleModulesAvailable(dutyClass, condition, module);
+
+		// ask user for name if not scripting and explanation available
+		if (!suppressHireQueries && !MesquiteThread.isScripting() && explanation != null && numAvailable > 1) {
+			MesquiteModule mb = null;
+			StringBuffer compatibilityReport = new StringBuffer();
+			String prefix = "";
+			Listable[] list = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(dutyClass, condition, module, compatibilityReport);
+			while (mb == null && !startupBailOut) {
+				MesquiteString args = new MesquiteString();
+				MesquiteModuleInfo c = (MesquiteModuleInfo) queryChooseModule(prefix + explanation, dutyClass, condition, args, list, 0, compatibilityReport);
+				String subchoice = null;
+				if (!args.isBlank())
+					subchoice = args.toString();
+				if (c == null) {
+					if (!acceptCancelInHireEmployee) 
+						queryAbortFromInitiator(explanation);
+					decrementMenuResetSuppression();
+					return null;
+
+				}
+				if (c != null) {
+					mb = hire(c, dutyClass, condition, subchoice, explanation);
+					if (mb == null && !startupBailOut) {
+						if (queryAbortFromInitiator(explanation)) {
+							decrementMenuResetSuppression();
+							return null;
+						}
+
+					}
+					if (mb == null && !startupBailOut)
+						prefix = "Attempt to start module \"" + c.getName() + "\" failed.  Choose an alternative module if desired:\n";
+				}
+			}
+			decrementMenuResetSuppression();
+			return mb;
+		}
+		else { // otherwise just hire first one you can
+			MesquiteModuleInfo c = MesquiteTrunk.mesquiteModulesInfoVector.findModule(dutyClass, condition, module.getProject(), this);
+			if (c == null || c.getModuleClass() == getClass()) // not allowed to hire oneself by default
+				c = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, c, condition, module.getProject(), this);
+			MesquiteModule mb = null;
+
+			if (c != null) // trying to get first module that will work (default if possible);
+				mb = hire(c, dutyClass, condition, null, explanation);
+			if (mb == null && !startupBailOut) {
+				if (queryAbortFromInitiator(explanation)) {
+					decrementMenuResetSuppression();
+					return null;
+				}
+			}
+
+			while (c != null && mb == null && !startupBailOut) { // if wasn't successful, find first that works.
+				c = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, c, condition, module.getProject(), this);
+				if (c != null) {
+					mb = hire(c, dutyClass, condition, null, explanation);
+					if (mb != null && MesquiteThread.isScripting())
+						mb.hiredAsDefaultInScripting = true;
+				}
+			}
+
+			decrementMenuResetSuppression();
+
+			return mb;
+		}
+	}
+
+	/* ................................................................................................................. */
+	/** Hires as employee the particular MesquiteModule corresponding to the MesquiteModuleInfo. */
+	public MesquiteModule hireEmployeeFromModuleInfo(MesquiteModuleInfo mbi, Class dutyClass) {
+		if (startupBailOut)
+			return null;
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.16) hireEmployee ( MesquiteModuleInfo mbi, Class dutyClass");
+		incrementMenuResetSuppression();
+		MesquiteModule mb = hire(mbi, dutyClass, null, null, null);
+		decrementMenuResetSuppression();
+		return mb;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that claims compatibility with given condition.
+	 */
+	public MesquiteModule hireCompatibleEmployee(Class dutyClass, Object condition, String explanation) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.19) hireCompatibleEmployee dutyClass (" + dutyClass + ") (" + condition + ")");
+		return findAndHire(dutyClass, condition, explanation);
+	}
+
+	/* ................................................................................................................. */
+	/** Hires as employees all MesquiteModules found of given class */
+	public void hireAllEmployees(Class dutyClass) {
+		hireAllCompatibleEmployees(dutyClass, null);
+		/*
+		 * if (startupBailOut) return; incrementMenuResetSuppression(); if (MesquiteTrunk.mesquiteModulesInfoVector==null) return; Enumeration enumeration=MesquiteTrunk.mesquiteModulesInfoVector.elements(); MesquiteModuleInfo mbi; while (enumeration.hasMoreElements()){ Object obj = enumeration.nextElement(); mbi = (MesquiteModuleInfo)obj; if (mbi.doesDuty(dutyClass)) { MesquiteModule mb = hireEmployeeFromModuleInfo( mbi, dutyClass); } } decrementMenuResetSuppression();
+		 */
+	}
+
+	/* ................................................................................................................. */
+	/** Hires as employees all MesquiteModules found of given class */
+	public void hireAllCompatibleEmployees(Class dutyClass, Object comp) {
+		if (startupBailOut)
+			return;
+		incrementMenuResetSuppression();
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return;
+		Enumeration enumeration = MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		MesquiteModuleInfo mbi;
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			mbi = (MesquiteModuleInfo) obj;
+			if (mbi.doesDuty(dutyClass) && mbi.isCompatible(comp, module.getProject(), module)) {
+				MesquiteModule mb = hireEmployeeFromModuleInfo(mbi, dutyClass);
+			}
+		}
+		decrementMenuResetSuppression();
+	}
+
+	/* ................................................................................................................. */
+	/** Hires as employees all MesquiteModules found of given class */
+	public void hireAllOtherCompatibleEmployees(Class dutyClass, Object comp) {
+		if (startupBailOut)
+			return;
+		incrementMenuResetSuppression();
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return;
+		Enumeration enumeration = MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		MesquiteModuleInfo mbi;
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			mbi = (MesquiteModuleInfo) obj;
+			if (mbi.doesDuty(dutyClass) && mbi.isCompatible(comp, module.getProject(), module) && (!employeeExists(mbi, dutyClass))) {
+				MesquiteModule mb = hireEmployeeFromModuleInfo(mbi, dutyClass);
+			}
+		}
+		decrementMenuResetSuppression();
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employees all MesquiteModules found of given class except those already hired of same class. Note: currently does this by checking name and duty class of existing employees
+	 */
+	public final void hireAllOtherEmployees(Class dutyClass) {
+		if (startupBailOut)
+			return;
+		incrementMenuResetSuppression();
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return;
+		Enumeration enumeration = MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		MesquiteModuleInfo mbi;
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			mbi = (MesquiteModuleInfo) obj;
+			if (mbi.doesDuty(dutyClass) && (!employeeExists(mbi, dutyClass))) {
+				MesquiteModule mb = hireEmployeeFromModuleInfo(mbi, dutyClass);
+			}
+		}
+		decrementMenuResetSuppression();
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Attempts to hire the module of the name indicated by the first token of arguments passed. Condition passed is a condition of hiring (e.g. for compatibility); "Explanation" can be used to query user if arguments passed is blank or null. If a successful hiring is done, the old employee is fired.
+	 */
+	private MesquiteModule replace(Class dutyClass, String arguments, String explanation, Object condition, MesquiteModule oldEmployee) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.24X) replaceEmployee ( Class dutyClass, String arguments, String explanation, Object condition, MesquiteModule oldEmployee)");
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null || dutyClass == null)
+			return null;
+		incrementMenuResetSuppression();
+
+		if (!StringUtil.blank(arguments)) {
+			String supplementary = null;
+			String moduleName = null;
+			if (ParseUtil.firstDarkChar(arguments) == '$') { // $ signals two arguments, second being probably subemployee; try to find actual name of module to be hired
+				moduleName = parser.getTokenNumber(arguments, 2);
+				supplementary = StringUtil.tokenize(parser.getNextToken());// if second token after module name, pass to module via arguments of startJob
+			}
+			else
+				moduleName = parser.getFirstToken(arguments);
+			if (StringUtil.blank(arguments)) {
+				decrementMenuResetSuppression();
+				return null;
+			}
+			if ("?".equals(moduleName)) {
+				boolean wasScrip = MesquiteThread.isScripting();
+				CommandRecord rec = MesquiteThread.getCurrentCommandRecord();
+				if (rec != null)
+					rec.setScripting(false);
+				MesquiteModule mb = hireEmployee(dutyClass, explanation);
+				if (rec != null)
+					rec.setScripting(wasScrip);
+				if (mb != null) {
+					if (oldEmployee != null)
+						fireEmployee(oldEmployee);
+					resetContainingMenuBar();
+					MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteModule.class);
+				}
+				decrementMenuResetSuppression();
+				return mb;
+			}
+			MesquiteModuleInfo c = MesquiteTrunk.mesquiteModulesInfoVector.findModule(dutyClass, moduleName);
+			if (c != null) {
+				MesquiteModule mb = hire(c, dutyClass, condition, supplementary, explanation);
+				if (mb != null) {
+					if (oldEmployee != null)
+						fireEmployee(oldEmployee);
+					resetContainingMenuBar();
+					MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteModule.class);
+				}
+				decrementMenuResetSuppression();
+				return mb;
+			}
+			else {
+				warnUserModuleNotFound(moduleName);
+				decrementMenuResetSuppression();
+				return null;
+			}
+		}
+		else {
+			MesquiteModule mb = findAndHire(dutyClass, condition, explanation);
+			if (mb != null) {
+				if (oldEmployee != null)
+					fireEmployee(oldEmployee);
+				resetContainingMenuBar();
+				MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteModule.class);
+			}
+			decrementMenuResetSuppression();
+			return mb;
+		}
+	}
+
+	/* ................................................................................................................. */
+	private void warnUserModuleNotFound(String moduleName) {
+		CommandRecord rec = MesquiteThread.getCurrentCommandRecord();
+		if (rec != null)
+			rec.setErrorFound();
+		if (moduleName == null)
+			return;
+		String message = "The module \"" + StringUtil.getLastItem(moduleName, ".") + "\", named in a command, was not found.";
+		boolean compoundClassName = (moduleName.charAt(0) == '#' && moduleName.indexOf(".") >= 0);
+		if (moduleName.charAt(0) == '#' && moduleName.indexOf(".") >= 0) { // compound class name
+			String useName = moduleName.substring(1, moduleName.length());
+			message = "The module \"" + StringUtil.getLastItem(useName, ".") + "\", named in a command, was not found.";
+			if (MesquiteThread.isScripting())
+				message += "\nThe script or macro being executed may not execute properly.";
+			String s = StringUtil.getAllButLastItem(useName, ".");
+			while (s != null && StringUtil.characterCount(s, '.') > 1) {
+				s = StringUtil.getAllButLastItem(s, ".");
+			}
+			if (s != null && StringUtil.characterCount(s, '.') == 1) {
+				// s is now package name; find package and diagnose
+				MesquitePackageRecord mpr = MesquitePackageRecord.findPackage(s);
+				if (mpr == null)
+					message += "\nThe package in which this module resides (" + s + ") appears not to be installed.";
+				else if (mpr.loaded)
+					message += "\nThe package in which this module resides (" + mpr.getName() + ") is installed and activated (loaded).  Perhaps the package has changed, or the command contains a misspelled name.";
+				else
+					message += "\nThe package in which this module resides (" + mpr.getName() + ") is installed but is not activated (loaded).  To use this module, change the activation/deactivation status of the package using the menu items in the File menu, and restart Mesquite.";
+			}
+
+		}
+		else {
+			String useName = moduleName;
+			if (moduleName.charAt(0) == '#')
+				useName = moduleName.substring(1, moduleName.length());
+			message = "The module \"" + useName + "\", named in a command, was not found.";
+			if (MesquiteThread.isScripting())
+				message += "\nThe script or macro being executed may not execute properly.";
+			if (!MesquitePackageRecord.allPackagesActivated())
+				message += "\nSome packages of modules appear to be installed but not activated (loaded). Check and perhaps change the activation/deactivation status of packages using the menu items in the File menu.";
+		}
+		if (rec != null)
+
+			if (rec.getModuleNotFoundWarning()) {
+				if (!AlertDialog.query(module.containerOfModule(), "Module not found", message, "OK", "Suppress similar warnings")){
+					rec.setModuleNotFoundWarning(false);
+				}
+			}
+		module.logln("\nMODULE REQUESTED BY COMMAND NOT FOUND\n" + message + "\n");
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that has given name (name should be first token of arguments passed!). If name passed is null then: if scripting, the first MesquiteModule found of the class is employed; if not, and an explanation is given, the user is queried; if no explanation is given, the first MesquiteModule found of the class is employed. Once the employement is done, the previous employee is fired.
+	 */
+	public MesquiteModule replaceEmployee(Class dutyClass, String arguments, String explanation, MesquiteModule oldEmployee) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.24) replaceEmployee ( Class dutyClass, String arguments, String explanation, MesquiteModule oldEmployee)");
+		return replace(dutyClass, arguments, explanation, null, oldEmployee);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the first MesquiteModule found that is instance of the given class and that claims compatibility with given object. First token of arguments is name of module. If name is null, first MesquiteModule found of the class is employeed. Once the employement is done, the previous employee is fired.
+	 */
+	public MesquiteModule replaceCompatibleEmployee(Class dutyClass, String arguments, MesquiteModule oldEmployee, Object obj) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.32) replaceCompatibleEmployee ( Class dutyClass, String arguments, MesquiteModule oldEmployee, Object obj)");
+		return replace(dutyClass, arguments, null, obj, oldEmployee);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Hires as employee the next MesquiteModule beyond the current that is instance of the given class. Once the employement is done, the previous employee is fired.
+	 */
+	public MesquiteModule replaceEmployeeWithNext(Class dutyClass, MesquiteModule oldEmployee) {
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.30) replaceEmployeeWithNext( Class dutyClass, MesquiteModule oldEmployee)");
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return null;
+		MesquiteModuleInfo c = null;
+		if (oldEmployee != null)
+			c = oldEmployee.moduleInfo;
+		c = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, c);
+		if (showHiringPath)
+			MesquiteMessage.warnProgrammer("(HIRING.31) module found " + whichModInfo(c));
+
+		if (c != null) {
+			incrementMenuResetSuppression();
+			MesquiteModule mb = hire(c, dutyClass, null, null, null);
+			if (mb == null) {
+				decrementMenuResetSuppression();
+				return null; // should get next module with dutyclass
+			}
+			if (oldEmployee != null)
+				fireEmployee(oldEmployee);
+			resetContainingMenuBar();
+			MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteModule.class);
+			decrementMenuResetSuppression();
+			return mb;
+		}
+		else {
+			return null;
+		}
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Intended to be used by the employer to pass its command for hiring a replacement to this module, so that Mesquite can use it to hire a replacement if this module quits
+	 */
+	public final void setHiringCommand(MesquiteCommand hc) {
+		hiringCommand = hc;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns the command for hiring a replacement to this module */
+	public final MesquiteCommand getHiringCommand() {
+		if (doesAnEmployerSuppressAutoRehiring())
+			return null;
+		return hiringCommand;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Before rehiring done, look into employer chain to seed if any request no rehiring
+	 */
+	boolean suppressAutoRehireInEmployeeTree = false;
+	public final void setSuppressEmployeeAutoRehiring(boolean s) {
+		suppressAutoRehireInEmployeeTree = s;
+	}
+	public final boolean getSuppressEmployeeAutoRehiring() {
+		return suppressAutoRehireInEmployeeTree;
+	}
+	public final boolean doesAnEmployerSuppressAutoRehiring() {
+		if (employer != null){
+			if (employer.suppressAutoRehireInEmployeeTree)
+				return true;
+			return employer.doesAnEmployerSuppressAutoRehiring();
+		}
+		return false;
+	}
+	/* ................................................................................................................. */
+	/**
+	 * returns whether this module has an employee hired for the given dutyClass and having the given MesquiteModuleInfo. For use by hireAllOtherEmployees
+	 */
+	private boolean employeeExists(MesquiteModuleInfo mbi, Class dutyClass) {
+		if (employees == null)
+			return false;
+		Enumeration enumeration = employees.elements();
+		while (enumeration.hasMoreElements()) {
+			MesquiteModule mb = (MesquiteModule) enumeration.nextElement();
+			if (mb.getHiredAs() == dutyClass && mb.getName().equals(mbi.getName())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	/** Returns command to hire employee if clonable */
+	public String getClonableEmployeeCommand(MesquiteModule employee) {
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Clones employee if possible */
+	public  Object cloneEmployee(MesquiteModule employee) {
+		if (employee == null)
+			return null;
+		String cloneCommand = getClonableEmployeeCommand(employee);
+		if (!StringUtil.blank(cloneCommand)){
+			cloneCommand += "\ntell It;\n";
+			cloneCommand += Snapshot.getSnapshotCommands(employee, null, "");
+			cloneCommand += "\nendTell;";
+			Puppeteer p = new Puppeteer(module);
+			MesquiteInteger pos = new MesquiteInteger(0);
+			CommandRecord previous = MesquiteThread.getCurrentCommandRecord();
+			CommandRecord record = new CommandRecord(true);
+			MesquiteThread.setCurrentCommandRecord(record);
+			MesquiteModule.incrementMenuResetSuppression();	
+			Object obj = p.sendCommands(this, cloneCommand, pos, "", false, null,CommandChecker.defaultChecker);
+			MesquiteModule.decrementMenuResetSuppression();	
+			MesquiteModule cloned = null;
+			if (obj != null){
+				MesquiteWindow w = null;
+				if (obj instanceof MesquiteWindow){
+					w = (MesquiteWindow)obj;
+					cloned = w.getOwnerModule();
+				}
+				else if (obj instanceof MesquiteModule){
+					w = ((MesquiteModule)obj).getModuleWindow(); // Not all employees may have a window, so this may return null
+					cloned = ((MesquiteModule)obj);
+				}
+				if (w!=null) {
+					w.doCommand("setLocation", Integer.toString(w.getLocation().x + 20) + " " + (w.getLocation().y + 20),CommandChecker.defaultChecker);
+					w.getParentFrame().showPage(Integer.toString(w.getID())); // Only do this if w != null
+				}
+
+			}
+			MesquiteThread.setCurrentCommandRecord(previous);
+			return cloned;
+		}
+		return null;
+	}
+	
+	/* ................................................................................................................. */
+	/** Clones employee if possible */
+	public synchronized Object synchronizedCloneEmployee(MesquiteModule employee) {
+		synchronized(this) {
+			return cloneEmployee(employee);
+		}
+	}
+	
+	private String whichModInfo(MesquiteModuleInfo mbi) {
+		if (mbi == null)
+			return "NULL";
+		else
+			return mbi.getName();
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns whether or not in creating macros automatically, this module is an anchor to which macros by default will be inherited. At present (April 02) this will probably include only the tree window module and the project coordinator module.
+	 */
+	public boolean isMacroAnchor() {
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns whether or not in creating macros automatically, this module is an anchor to which macros by default will be inherited. At present (April 02) this will probably include only the tree window module and the project coordinator module.* public MesquiteModule getMacroAnchor(){ return false; } /*.................................................................................................................
+	 */
+	/** Returns number of different MesquiteModule classes (modules) that serve given duty (i.e., instances of given class). */
+	public int numModulesAvailable(Class dutyClass) {
+		return numCompatibleModulesAvailable(dutyClass, null, module);
+		/*
+		 * if (MesquiteTrunk.mesquiteModulesInfoVector==null) return 0; int count=0; Enumeration enumeration=MesquiteTrunk.mesquiteModulesInfoVector.elements(); MesquiteModuleInfo mbi; while (enumeration.hasMoreElements()){ Object obj = enumeration.nextElement(); mbi = (MesquiteModuleInfo)obj; if (mbi.doesDuty(dutyClass)) { count++; } } return count;
+		 */
+	}
+
+	/* ................................................................................................................. */
+	/** Returns number of different MesquiteModule classes (modules) that serve given duty (i.e., instances of given class). */
+	public int numCompatibleModulesAvailable(Class dutyClass, Object obj, MesquiteModule prospectiveEmployer) {
+		if (MesquiteTrunk.mesquiteModulesInfoVector == null)
+			return 0;
+		int count = 0;
+		MesquiteProject proj = null;
+		if (prospectiveEmployer != null)
+			proj = prospectiveEmployer.getProject();
+		Enumeration enumeration = MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		MesquiteModuleInfo mbi;
+		while (enumeration.hasMoreElements()) {
+			mbi = (MesquiteModuleInfo) enumeration.nextElement();
+			if (mbi.doesDuty(dutyClass) && mbi.isCompatible(obj, proj, prospectiveEmployer)) {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Finds next employee of this MesquiteModule that is an instance of given class. Passed the previous employee found; if passed null then looks for first such employee.
+	 */
+	public MesquiteModule getNextEmployeeWithDuty(MesquiteModule last, Class dutyClass) {
+		boolean found = (last == null);
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule) obj;
+			if (!found) {
+				if (mbe == last)
+					found = true;
+			}
+			else if (dutyClass.isInstance(mbe))
+				return mbe;
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** Fires given employee. */
+	public void fireEmployee(MesquiteModule mb) {
+		if (mb != null) {
+			mb.doomAll();
+			mb.endJob();
+			mb.dispose();
+		}
+		// mb.employer.employees.removeElement(mb);
+	}
+	/* ................................................................................................................. */
+	/** Moves first employee to be just after second; if second is null, moves to start. */
+	public void moveEmployeeAfter(MesquiteModule toBeMoved, MesquiteModule targetBefore) {
+		if (toBeMoved == null)
+			return;
+		int mover = employees.indexOf(toBeMoved);
+		if (mover <0)
+			return;
+
+		int target = 0;
+		if (targetBefore != null) {
+			target = employees.indexOf(targetBefore);
+			if (target <0)
+				return;
+			target++; //to come after
+		}
+		employees.removeElement(toBeMoved, false);
+		if (mover < target)
+			target--;
+		employees.insertElementAt(toBeMoved, target, false);
+	}
+
+	/* ................................................................................................................. */
+	/** Fires all employees. */
+	public void closeDownAllEmployees(MesquiteModule mb) {
+		if (employees == null)
+			return;
+
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule) obj;
+			if (mbe != null) {
+				try {
+					mbe.endJob();
+				} catch (Throwable t) {
+					module.logln("Error or exception in closing down employee (endJob) " + mbe.getName());
+					t.printStackTrace();
+					MesquiteFile.throwableToLog(this, t);
+				}
+				try {
+					mbe.dispose();
+				} catch (Throwable t) {
+					module.logln("Error or exception in closing down employee (dispose) " + mbe.getName());
+					MesquiteFile.throwableToLog(this, t);
+				}
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	protected void internalStartUp() {
+	}
+
+	/* ................................................................................................................. */
+	/** refreshes and employee tree window -- used both for the Active Module Tree and in each window */
+	public void refreshBrowser(Class c) {
+		if (module == null || doomed || !(MesquiteModule.class == c || MesquiteModule.class.isAssignableFrom(c))) {
+			return;
+		}
+		if (employeeBrowserSuppression > 0) {
+			employeeBrowserRefreshPending = true;
+		}
+		else {
+			if (module.getModuleWindow() != null) {
+				MesquiteWindow w = module.getModuleWindow();
+				if (w.getMode() == InfoBar.EMPLOYEE_TREE) {
+					w.updateEmployeeTree();
+				}
+			}
+		}
+		if (employees == null)
+			return;
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule) obj;
+			mbe.refreshBrowser(c);
+		}
+	}
+
+	int employeeBrowserSuppression = 0;
+
+	boolean employeeBrowserRefreshPending = false;
+
+	/* ................................................................................................................. */
+	/** Indicates whether any employers have browser refresh suspended. */
+	private final boolean employerBrowserRefreshSuspended() {
+		return false;
+		/*
+		 * if (employer == null) return false; if (employer.employeeBrowserSuppression>0 || employer.isDoomed()) return true; return employer.employerBrowserRefreshSuspended();
+		 */
+	}
+
+	/* ................................................................................................................. */
+	/** Increments suppression level of hierarchy views (e.g., employee tree); if 0 then can be repainted. */
+	public final void incrementEmployeeBrowserRefreshSuppression(Class c) {
+		employeeBrowserSuppression++;
+	}
+
+	/* ................................................................................................................. */
+	/** Decrements suppression level of hierarchy views (e.g., employee tree); if 0 then can be repainted. */
+	public final void decrementEmployeeBrowserRefreshSuppression(Class c) {
+		if (employeeBrowserSuppression == 0) {
+			MesquiteMessage.warnProgrammer("decrementBrowserResetSuppression when already zero");
+			return;
+		}
+
+		employeeBrowserSuppression--;
+		if (employeeBrowserSuppression < 0)
+			employeeBrowserSuppression = 0;
+		if (employeeBrowserSuppression == 0) { // menu suppression just removed and requests pending; reset menus
+			if (employeeBrowserRefreshPending && !employerBrowserRefreshSuspended()) {
+				refreshBrowser(c);
+			}
+			employeeBrowserRefreshPending = false;
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/EnglishDecimalFormatSymbols.java b/Source/mesquite/lib/EnglishDecimalFormatSymbols.java
new file mode 100644
index 0000000..cbf2c01
--- /dev/null
+++ b/Source/mesquite/lib/EnglishDecimalFormatSymbols.java
@@ -0,0 +1,15 @@
+package mesquite.lib;
+
+import java.text.DecimalFormatSymbols;
+
+public class EnglishDecimalFormatSymbols extends DecimalFormatSymbols {
+	
+	public EnglishDecimalFormatSymbols() {
+		setDecimalSeparator('.');
+		setExponentSeparator("E");
+		setMinusSign('-');
+		setGroupingSeparator(',');
+		setZeroDigit('0');
+	}
+
+}
diff --git a/Source/mesquite/lib/EnterButton.java b/Source/mesquite/lib/EnterButton.java
new file mode 100644
index 0000000..8d7e7d7
--- /dev/null
+++ b/Source/mesquite/lib/EnterButton.java
@@ -0,0 +1,119 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+/** enter button for MiniScroll & MiniTextEditor*/
+public class EnterButton extends MousePanel {
+	public MiniControl miniControl;
+	public static Image enterVerticalDisabled, enterHorizontalDisabled;
+	public static Image enterVertical, enterHorizontal;
+	public static Image enterVerticalPressed, enterHorizontalPressed;
+	private Image enter;
+	private Image enterDisabled;
+	private Image enterPressed;
+	private boolean firsttime=true;
+	private boolean pressed = false;
+	private boolean disabled = false;
+	public static final int MIN_DIMENSION = 13;
+	
+	static {
+		enterVerticalDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterVertDisabled.gif");
+		enterHorizontalDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterHorizDisabled.gif");
+		enterVertical = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterVert.gif");
+		enterHorizontal = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterHoriz.gif");
+		enterVerticalPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterVertPressed.gif");
+		enterHorizontalPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "enterHorizPressed.gif");
+	}
+	public EnterButton (MiniControl miniControl, boolean vertical) {
+		this.miniControl = miniControl;
+		if (vertical) {
+			enter = enterVertical;
+			enterDisabled = enterVerticalDisabled;
+			enterPressed = enterVerticalPressed;
+			setBounds(0,0,MIN_DIMENSION,16);
+		}
+		else {
+			enter = enterHorizontal;
+			enterDisabled = enterHorizontalDisabled;
+			enter = enterHorizontalPressed;
+			setBounds(0,0,16,MIN_DIMENSION);
+		}
+	}
+	public EnterButton (MiniControl miniControl) {
+		this(miniControl, true);
+	}
+	
+	public  void setEnabled(boolean b) {
+		disabled = !b;
+		repaint();
+	}
+	public void print (Graphics g) {
+	}
+	public void paint (Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (getBackground() != null && getParent() != null && !getBackground().equals(getParent().getBackground()))
+			setBackground(getParent().getBackground());
+		if (pressed)
+			g.drawImage(enterPressed,0,0,this);
+		else if (disabled)
+			g.drawImage(enterDisabled,0,0,this);
+		else
+			g.drawImage(enter,0,0,this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (!disabled) {
+			Graphics g=getGraphics();
+			if (g == null)
+				return;
+			pressed = true;
+			g.drawImage(enterPressed,0,0,this);
+			g.dispose();
+		}
+		//super.mouseDown(modifiers,x,y,tool);
+	}
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!disabled) {
+			Graphics g=getGraphics();
+			if (g == null)
+				return;
+			pressed=false;
+			miniControl.acceptText();
+			paint(g);
+			g.dispose();
+		}
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.windowOfItem(this)!=null) {
+			String s="Values in the associated text field will be entered if this button is pressed. ";
+	 		if (disabled) 
+	 			s += "It is disabled as the value entered is identical to the current value, too small or too large, or otherwise invalid.";
+			MesquiteWindow.windowOfItem(this).setExplanation(s);
+		}
+		super.mouseEntered(modifiers,x,y, tool);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.windowOfItem(this)!=null) 
+			MesquiteWindow.windowOfItem(this).setExplanation("");
+		super.mouseExited(modifiers,x,y, tool);
+	}
+}
+
diff --git a/Source/mesquite/lib/Evaluator.java b/Source/mesquite/lib/Evaluator.java
new file mode 100644
index 0000000..7ffd467
--- /dev/null
+++ b/Source/mesquite/lib/Evaluator.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+/* ======================================================================== */
+public interface Evaluator {
+	public double evaluate(double[] params, Object obj);   
+	public double evaluate(MesquiteDouble param, Object obj);
+}
+
+
diff --git a/Source/mesquite/lib/Explainable.java b/Source/mesquite/lib/Explainable.java
new file mode 100644
index 0000000..04136d7
--- /dev/null
+++ b/Source/mesquite/lib/Explainable.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it can be explained in documentation*/
+public interface Explainable extends Listable {
+ 	public String getExplanation();
+}
+
diff --git a/Source/mesquite/lib/ExplanationArea.java b/Source/mesquite/lib/ExplanationArea.java
new file mode 100644
index 0000000..0441452
--- /dev/null
+++ b/Source/mesquite/lib/ExplanationArea.java
@@ -0,0 +1,507 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+/* ======================================================================== */
+/** A panel at the bottom of windows in which explanations and footnotes can be displayed and edited.*/
+public class ExplanationArea extends MousePanel implements TextListener, MesquiteListener, FocusListener {
+	private ExplTextArea explTextArea;
+	ExplanationControl control;
+	static final int grabberHeight = 0;
+	Annotatable annotatable = null;
+	MesquiteWindow window;
+	int suppressNotify = 0;
+	int controlWidth = 36;
+	static final int increment = 20;
+	static final int minimumHeightExplanation = 30;
+	static final int minimumHeightAnnotation = 20;
+	boolean focusSuppressed = false;
+	boolean hasFocus = false;
+	int fontIncrement = 0;
+	public static Image plusImage, minusImage, minusOffImage;
+	boolean isAnnotation = false;
+	public ExplanationArea (MesquiteWindow window, boolean isAnnotation) {
+		super();
+
+		setLayout(null);
+		this.isAnnotation = isAnnotation;
+		this.window = window;
+
+
+		explTextArea = new ExplTextArea("", 2, 8, TextArea.SCROLLBARS_VERTICAL_ONLY, this); 
+		add(explTextArea);
+		explTextArea.setBounds(controlWidth, 0, getBounds().width-controlWidth, getBounds().height - grabberHeight);
+		explTextArea.setVisible(true);
+		explTextArea.addFocusListener(this);
+
+
+		control = new ExplanationControl(this);
+		controlWidth= control.getMinimumWidth();
+		add(control);
+		control.setBounds(0, 0, controlWidth, getBounds().height);
+
+		control.setVisible(true);
+		control.repaint(); //attempt to deal with bug in OS X 10.2
+		explTextArea.addTextListener(this);
+
+		control.setBackground(ColorTheme.getInterfaceBackground());
+		requestFocusInWindow();
+	}
+	public void dispose(){
+		if (control !=null)
+			control.dispose();
+		annotatable = null;
+		super.dispose();
+	}
+	public TextArea getTextArea(){
+		return explTextArea;
+	}
+	String name;
+	public void setName(String name){  //for Debugging 
+		this.name = name;
+	}
+	public void focusGained(FocusEvent e){
+		if (e.getSource() == this)
+			hasFocus = true;
+	}
+	public void focusLost(FocusEvent e){
+		if (e.getSource() == this)
+			hasFocus = false;
+	}
+	long lastTick = -1;
+	boolean showClock = false;
+	String explanationSet = "";
+	String tickString = null;
+	public void tickClock(String tickString){
+		if (tickString == null)
+			tickString = "";
+		this.tickString = tickString;
+
+		control.showClock = true;
+		if (lastTick < 0 || (lastTick > 0 && System.currentTimeMillis() - lastTick > 200)){
+
+			if (explTextArea != null)
+					explTextArea.setText(tickString);
+			
+			if (lastTick < 0)
+				control.clockCount = 0;
+			else
+				control.clockCount++;
+			control.repaint();
+			lastTick = System.currentTimeMillis();
+		}
+
+	}
+	public void hideClock(){
+		this.tickString = null;
+		control.showClock = false;
+		
+		if (explTextArea != null){
+			if (annotatable == null)
+				explTextArea.setText(explanationSet);
+			else
+				explTextArea.setText(annotatable.getAnnotation());
+
+		}
+
+		lastTick = -1;
+		control.repaint();
+	}
+	void resetFont(){
+		Font currentFont = window.getCurrentFont();
+		if (currentFont != null){
+			Font fontToSet = new Font (currentFont.getName(), currentFont.getStyle(), currentFont.getSize() + fontIncrement);
+			setFont(fontToSet);
+			repaint();
+		}
+	}
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.setColor(Color.black);
+		int middle = getBounds().width/2;
+		int grabberTop = getBounds().height - grabberHeight;
+		if (lastTouched>=0)
+			g.fillRect(middle-10, grabberTop-8,20, 20);
+		g.drawLine(0, 0,getBounds().width, 0);
+		g.setColor(Color.darkGray);
+		g.drawLine(middle-8, grabberTop,middle + 8, grabberTop);
+		g.drawLine(middle-8, grabberTop + 2,middle + 8, grabberTop + 2);
+		//g.drawLine(middle-8, 2,middle + 8, 2);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void setBackground(Color c){
+		explTextArea.setBackground(c);  
+		super.setBackground(c);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		explTextArea.setBounds(controlWidth, 0, w-controlWidth, h - grabberHeight);
+		control.setBounds(0, 0, controlWidth, h);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		explTextArea.setSize(w-controlWidth, h - grabberHeight);
+		control.setSize(controlWidth, h);
+	}
+	public boolean getIsAnnotation(){
+		return isAnnotation;
+	}
+	public boolean isMinimumHeight(){
+		if (!isAnnotation)
+			return (window.explanationHeight <=  minimumHeightExplanation);
+		else 
+			return (window.annotationHeight <=  minimumHeightAnnotation);
+	}
+	public void plus(){
+		if (!isAnnotation){
+			int willBe = window.explanationHeight + increment;
+			if (willBe < minimumHeightExplanation)
+				willBe = minimumHeightExplanation;
+			window.setShowExplanation(true, willBe);
+		}
+		else {
+			int willBe = window.annotationHeight + increment;
+			if (willBe < minimumHeightAnnotation)
+				willBe = minimumHeightAnnotation;
+			window.setShowAnnotation(true, willBe);
+		}
+	}
+	public void minus(){
+		if (!isAnnotation){
+			int willBe = window.explanationHeight - increment;
+			if (willBe < minimumHeightExplanation)
+				willBe = minimumHeightExplanation;
+			window.setShowExplanation(true, willBe);
+		}
+		else {
+			int willBe = window.annotationHeight - increment;
+			if (willBe < minimumHeightAnnotation)
+				willBe = minimumHeightAnnotation;
+			window.setShowAnnotation(true, willBe);
+		}
+	}
+	public void textValueChanged(TextEvent e){
+		if (explTextArea !=null && annotatable != null) {
+			if (suppressNotify>0){
+				suppressNotify--;
+			}
+			else {
+
+				String s = explTextArea.getText();
+				int start = explTextArea.getSelectionStart();
+				int end = explTextArea.getSelectionEnd();
+				if ("".equals(s))
+					s = null;
+				annotatable.setAnnotation(s, suppressNotify == 0);
+				explTextArea.setSelectionStart(start);
+				explTextArea.setSelectionEnd(end);
+			}
+
+		}
+	}
+	public void setFocusSuppression(boolean suppress){
+		this.focusSuppressed = suppress;
+		if (suppress && explTextArea.isEditable()){
+			explTextArea.setEditable(false);
+			control.setEditable(false);
+		}
+	}
+	public boolean getFocusSuppression(){
+		return focusSuppressed;
+	}
+	public void setExplanation(String text){
+		if (text == null)  
+			text = "";
+		annotatable = null;
+		String current = explTextArea.getText();
+		explanationSet = text;
+		if (text!=null && current!=null && !text.equals(current)){
+			explTextArea.setText(text);
+		}
+		if (explTextArea.isEditable()){
+			explTextArea.setEditable(false);
+			control.setEditable(false);
+		}
+
+	}
+
+	public void setExplanation(Annotatable annotatable){
+		String current = explTextArea.getText();
+		if (annotatable != this.annotatable){
+			if (this.annotatable!=null && this.annotatable instanceof Listened)
+				((Listened)this.annotatable).removeListener(this);
+			this.annotatable = annotatable;
+			if (annotatable !=null && annotatable instanceof Listened)
+				((Listened)annotatable).addListener(this);
+		}
+
+		if (annotatable == null) {
+			setExplanation("");
+			return;
+		}
+
+		String newText = annotatable.getAnnotation();
+		if (newText == null)
+			newText = "";
+		if (current!=null && !newText.equals(current))
+			explTextArea.setText(newText);
+		if (explTextArea.isEditable() != (isAnnotation && !focusSuppressed)){
+			explTextArea.setEditable(isAnnotation && !focusSuppressed);
+			control.setEditable(isAnnotation && !focusSuppressed);
+		}
+		/*
+		if (current!=null && !newText.equals(current))
+			debuggingPanel.setText(newText);
+		if (debuggingPanel.isEditable() != (isAnnotation && !focusSuppressed)){
+			debuggingPanel.setEditable(isAnnotation && !focusSuppressed);
+			control.setEditable(isAnnotation && !focusSuppressed);
+		}
+		 */
+
+	}
+	public Annotatable getAnnotatable(){
+		return annotatable;
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == annotatable && Notification.getCode(notification) == MesquiteListener.ANNOTATION_CHANGED){
+			suppressNotify++;
+			if (explTextArea != null && annotatable != null)
+				explTextArea.setText(annotatable.getAnnotation());
+			/*	if (debuggingPanel != null && annotatable != null)
+				debuggingPanel.setText(annotatable.getAnnotation());
+			 */
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	public String getExplanation(){
+		return explTextArea.getText();
+	}
+
+	int lastTouched = -1;
+	/*.................................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		int middle = getBounds().width/2;
+		if (x>middle-8 && x<middle+8 && y>getBounds().height - grabberHeight-8){
+			lastTouched = y;
+			repaint();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (lastTouched>=0) {
+			if (window.explanationHeight - (lastTouched-y) > 24)
+				window.setShowExplanation(true, window.explanationHeight- (lastTouched-y));
+			else
+				window.setShowExplanation(true, 24);
+			repaint();
+		}
+		lastTouched = -1;
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+class ExplanationControl extends MousePanel {
+	ExplanationArea area;
+	static int buttonHeight = 13;
+	static int buttonWidth = 16;
+	static int buttonSidePadding = 3;
+	static int buttonMiddlePadding = 2;
+	boolean showClock = false;
+	int clockCount=0;
+	int roundClock = 16;
+	int clockRadius = 8;
+	double clockMult = Math.PI *2.0/ roundClock;
+	//int plusTop = 4;
+	//int minusTop = 20;
+	boolean editable = false;
+	public ExplanationControl (ExplanationArea area){
+		this.area = area;
+	}
+	public void dispose(){
+		super.dispose();
+	}
+	public void paint(Graphics g){
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.setColor(Color.black);
+		g.drawRect(0,0,getBounds().width-1, getBounds().height -1);
+		if (editable){
+			g.setColor(Color.green);
+			g.drawRect(1,1,getBounds().width-3, getBounds().height -3);
+			g.drawRect(2,2,getBounds().width-5, getBounds().height -5);
+		}
+		if (showClock){
+			clockRadius = 6;
+			if (clockCount > roundClock)
+				clockCount = 0;
+			g.setColor(Color.white);
+			g.fillOval(minusLeft(), minusTop(), clockRadius+clockRadius, clockRadius+clockRadius);
+			g.setColor(Color.black);
+			g.drawOval(minusLeft(), minusTop(), clockRadius+clockRadius, clockRadius+clockRadius);
+			g.drawOval(minusLeft()+1, minusTop()+1, clockRadius+clockRadius-2, clockRadius+clockRadius-2);
+			g.fillArc(minusLeft()+1, minusTop()+1, clockRadius+clockRadius-2, clockRadius+clockRadius-2, 360 -  clockCount*360/roundClock, 30);
+		}
+		else {
+			if (ExplanationArea.plusImage !=null)
+				g.drawImage(ExplanationArea.plusImage,plusLeft(),plusTop(), this);
+			if (!area.isMinimumHeight()) {
+				if (ExplanationArea.minusImage!=null)
+					g.drawImage(ExplanationArea.minusImage,minusLeft(),minusTop(), this);
+			}
+			else {
+				if (ExplanationArea.minusOffImage!=null)
+					g.drawImage(ExplanationArea.minusOffImage,minusLeft(),minusTop(), this);
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public static int getMinimumWidth(){
+		return (buttonSidePadding+buttonWidth)*2; //buttonSidePadding*2+buttonWidth*2+buttonMiddlePadding;
+	}
+	/*.................................................................................................................*/
+	public int minusLeft(){
+		return buttonSidePadding;
+	}
+	/*.................................................................................................................*/
+	public int plusLeft(){
+		return buttonSidePadding+(buttonWidth); //buttonSidePadding+buttonWidth+buttonMiddlePadding;
+	}
+	/*.................................................................................................................*/
+	public int plusTop(){
+		return buttonSidePadding; //getBounds().height - buttonHeight-buttonSidePadding;
+	}
+	/*.................................................................................................................*/
+	public int minusTop(){
+		return buttonSidePadding; //getBounds().height - buttonHeight-buttonSidePadding;
+	}
+	/*.................................................................................................................*/
+	public boolean inPlusButton(int x, int y) {
+		return (x>=plusLeft() && x<plusLeft()+buttonWidth && y>=plusTop() &&  y<=plusTop() + buttonHeight);
+	}
+	/*.................................................................................................................*/
+	public boolean inMinusButton(int x, int y) {
+		return  (x>=minusLeft() && x<minusLeft()+buttonWidth && y>=minusTop() &&  y<=minusTop() + buttonHeight);
+	}
+	private void font(int inc){
+		area.fontIncrement += inc;
+		area.resetFont();
+	}
+	/*.................................................................................................................*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		String s="";
+		String name="";
+		if (area.getIsAnnotation())
+			name ="the annotation area above";
+		else
+			name="this explanation area";
+		if (area.tickString != null){
+			s = area.tickString;
+		}
+		else if (inPlusButton(x,y)) {
+			s += "This button will increase the height of "+name+".   (With modifier keys or right click, will increase font size.)";
+		}
+		else if (inMinusButton(x,y)) {
+			s += "This button will decrease the height of "+name+". ";
+			if (area.isMinimumHeight())
+				s+= "It is disabled as the area is already at its minimum height.";
+			s += "  (With modifier keys or right click, will decrease font size.)";	
+		}
+		MesquiteWindow.windowOfItem(this).setExplanation(s);
+		super.mouseMoved(modifiers,x,y,tool);
+	}
+	/*.................................................................................................................*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (inPlusButton(x,y)) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers) || MesquiteEvent.optionKeyDown(modifiers))
+				font(1);
+			else
+				area.plus();
+		}
+		else if (inMinusButton(x,y)) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers) || MesquiteEvent.optionKeyDown(modifiers))
+				font(-1);
+			else
+				area.minus();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void setEditable(boolean b){
+		boolean changed = (b!=editable);
+		repaint();
+		this.editable = b;
+		if (changed)
+			repaint();
+	}
+}
+
+class ExplTextArea extends TextArea {
+	ExplanationArea explArea;
+	public ExplTextArea(String text, int rows,  int columns, int scrollbars, ExplanationArea explArea){
+		super(text, rows, columns, scrollbars);
+		setSelectionStart(0);
+		setSelectionEnd(0);
+		this.explArea = explArea;
+	}
+	public void gotFocus(){
+		if (explArea.getFocusSuppression()){
+			explArea.window.requestFocus();
+		}
+		else
+			explArea.hasFocus = true;
+	}
+
+	public void setText(String t){  // and possibly others
+		
+		if (MesquiteTrunk.isMacOSX()){  //this had been a workaround to bug in OS X Snow Leopard, but it slowed alignment too much
+			setSelectionStart(0);
+			setSelectionEnd(0);
+		}
+		super.setText(t);
+		if (MesquiteTrunk.isMacOSX()){
+			setSelectionStart(0);
+			setSelectionEnd(0);
+		}
+	}
+
+	public void processFocusEvent(FocusEvent e) {
+		super.processFocusEvent(e);
+		if (e.getID() == FocusEvent.FOCUS_GAINED && explArea.getFocusSuppression())
+			explArea.window.graphicsRequestFocus();
+		else if (e.getID() == FocusEvent.FOCUS_GAINED)
+			explArea.hasFocus = true;
+		if (e.getID() == FocusEvent.FOCUS_LOST)
+			explArea.hasFocus = false;
+	}
+}
diff --git a/Source/mesquite/lib/ExponentialDistribution.java b/Source/mesquite/lib/ExponentialDistribution.java
new file mode 100644
index 0000000..1458d99
--- /dev/null
+++ b/Source/mesquite/lib/ExponentialDistribution.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/** subclass of Random to return exponentially distributed numbers.*/
+public class ExponentialDistribution extends Random {
+	public ExponentialDistribution() {
+		super();
+	}
+	public ExponentialDistribution(long seed) {
+		super(seed);
+	}
+	/*.................................................................................................................*/
+	/** Returns a random number exponentially distributed with mean.*/
+  	public double nextExponential(double mean){
+  		return -mean * Math.log(nextDouble());
+  	}
+}
+
+
diff --git a/Source/mesquite/lib/ExporterDialog.java b/Source/mesquite/lib/ExporterDialog.java
new file mode 100644
index 0000000..0ea521d
--- /dev/null
+++ b/Source/mesquite/lib/ExporterDialog.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+
+/*===============================================*/
+/** Export Options dialog box class*/
+public class ExporterDialog extends ExtensibleDialog {
+	FileInterpreter fileInterpreter;
+	static final String exportString = "Export";
+	static final String cancelString = "Cancel";
+	Choice exportDelimiter;
+	Checkbox writeOnlySelectedDataCheckBox;
+	Checkbox writeOnlySelectedTaxaCheckBox;
+	boolean suppressLineEndQuery = false;
+	public ExporterDialog (FileInterpreterI fileInterpreter, MesquiteWindow parent, String title, MesquiteInteger buttonPressed) {
+		this((FileInterpreter)fileInterpreter, parent, title, buttonPressed);
+	}
+	public ExporterDialog (FileInterpreter fileInterpreter, MesquiteWindow parent, String title, MesquiteInteger buttonPressed) {
+		super(parent, title, buttonPressed);
+		this.fileInterpreter = fileInterpreter;
+		setDefaultButton("Export");
+	}
+	/*.................................................................................................................*/
+	public void addLineEndPopUpPanel () {
+		exportDelimiter = addPopUpMenu("End of line character:", "Current System Default","MacOS (CR)","Windows (CR+LF)","UNIX (LF)",fileInterpreter.lineDelimiter);
+	}
+	/*.................................................................................................................*/
+	public void setSuppressLineEndQuery(boolean su){
+		suppressLineEndQuery = su;
+	}
+	
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean dataSelected, boolean taxaSelected) {
+		fileInterpreter.writeOnlySelectedTaxa = false;
+		fileInterpreter.writeOnlySelectedData = false;
+		if (dataSelected) 
+			 writeOnlySelectedDataCheckBox = this.addCheckBox("write only selected data", fileInterpreter.writeOnlySelectedData);
+		else
+			writeOnlySelectedDataCheckBox = new Checkbox();
+			
+		if (taxaSelected) 
+			 writeOnlySelectedTaxaCheckBox = this.addCheckBox("write only selected taxa", fileInterpreter.writeOnlySelectedTaxa);
+		else
+			writeOnlySelectedTaxaCheckBox = new Checkbox();
+		if (!suppressLineEndQuery)
+			addLineEndPopUpPanel();
+		addPrimaryButtonRow(exportString, cancelString);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog () {
+		if (!suppressLineEndQuery)
+			addLineEndPopUpPanel();
+		addPrimaryButtonRow(exportString, cancelString);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void buttonHit(String buttonLabel, Button button) {
+		super.buttonHit(buttonLabel, button);
+		if (buttonLabel.equalsIgnoreCase(exportString) && exportDelimiter != null) {
+			fileInterpreter.lineDelimiter = exportDelimiter.getSelectedIndex();
+		}
+	}
+	/*.................................................................................................................*/
+	public static int query(FileInterpreterI fileInterpreter, MesquiteWindow parent, String title) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(fileInterpreter, parent, title,buttonPressed);
+
+		exportDialog.completeAndShowDialog();
+		exportDialog.dispose();
+		return buttonPressed.getValue();
+	}
+	/*.................................................................................................................*/
+	public int query() {
+		return buttonPressed.getValue();
+	}
+	/*.................................................................................................................*/
+	public int query(boolean dataSelected, boolean taxaSelected) {
+		if (dataSelected) 
+			fileInterpreter.writeOnlySelectedData = writeOnlySelectedDataCheckBox.getState();
+		if (taxaSelected) 
+			fileInterpreter.writeOnlySelectedTaxa = writeOnlySelectedTaxaCheckBox.getState();
+		
+		return buttonPressed.getValue();
+	}
+}
+
diff --git a/Source/mesquite/lib/ExtensibleDialog.java b/Source/mesquite/lib/ExtensibleDialog.java
new file mode 100644
index 0000000..203b4bf
--- /dev/null
+++ b/Source/mesquite/lib/ExtensibleDialog.java
@@ -0,0 +1,2125 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+import javax.swing.*;
+import javax.swing.text.*;
+
+import mesquite.lib.simplicity.InterfaceManager;
+import mesquite.lib.table.EditorTextField;
+
+import java.awt.event.*;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Vector;
+
+/*
+	To do:
+		- add ability to set radio buttons so that they are in a row
+		- clean up event handling
+
+ */
+
+/*===============================================*/
+/** An extensible dialog box.  */
+public class ExtensibleDialog extends MesquiteDialog implements ActionListener, WindowListener, DoubleClickListener, ImagePanelListener, ComponentListener {
+	public static final int defaultCANCEL = 1;
+	public static final int defaultOK = 0;
+	ImagePanel helpURLPanel;
+	ImagePanel helpStringPanel;
+	public MesquiteInteger buttonPressed;
+	String buttonLabel0;
+	String buttonLabel1;
+	String buttonLabel2;
+	String[] buttonLabels= new String[10];
+
+	MesquiteModule helpURLOwnerModule=null;
+	Button button0, button1, button2;
+	Button[] buttons = new Button[10];
+	Image helpImage;
+	boolean useManualPage = false;
+	public String defaultOKLabel = "OK";
+	public String defaultLabel = defaultOKLabel;
+	public String defaultCancelLabel="Cancel";
+	String helpString = "";
+	String helpURL = "";
+	int numButtons = 0;
+	int numExtraButtons = 5;
+	int currentExtraButton = -1;
+	String[] extraButtonLabels = new String[numExtraButtons];
+	//	CardPanels cardPanels = null;
+	//	Panel cardPanel = null;
+	Panel addPanel=null;
+	JPanel addJPanel = null;
+	int cardPanelNumber = 0;
+	Panel lastPanel;
+	int defaultButtonNumber = 0;
+	int dialogWidth=20;
+	//	public static final int checkBoxHeight = 24;
+	//	public static final int buttonHeight = 30;
+	//	public static final int popUpHeight = 30;
+	//	public static final int textFieldHeight = 30;
+	//	public static final int labelHeight = 24;
+	int dialogHeight=50;	
+	static final int minDialogWidthWithCanvas=240;
+	int minDialogWidth=200;
+	int minDialogHeight=120;
+	Dimension d;
+
+	static final int maxDialogWidthWithCanvas=840;
+	int maxDialogWidth=820;
+	boolean samePanelAsLast = false;
+	boolean wasSamePanelAsLast = false;
+	GridBagLayout gridBag;
+	GridBagLayout currentGridBag=null;
+	GridBagConstraints constraints;
+	Object customConstraints=null;
+	Component focalComponent=null;
+	Component defaultTextComponent=null;
+
+
+	public int sideBuffer = 12;
+
+	public static Font defaultBigFont = new Font ("Dialog", Font.PLAIN, 12);
+	public static Font boldFont = new Font ("Dialog", Font.BOLD, 12);
+	public static Font defaultSmallFont = new Font ("SanSerif", Font.PLAIN, 10);
+	public static Font defaultVerySmallFont = new Font ("SanSerif", Font.PLAIN, 9);
+
+	/*.................................................................................................................*/
+	public ExtensibleDialog (Object parent, String title, MesquiteInteger buttonPressed, boolean suppressWizardIfFirst) {
+		super(parent, title, suppressWizardIfFirst);
+		setFont(defaultBigFont);
+		intializeDialog(title,buttonPressed);
+		addWindowListener(this);
+	}
+	/*.................................................................................................................*/
+	public ExtensibleDialog (Object parent, String title, MesquiteInteger buttonPressed) {
+		super(parent, title);
+		setFont(defaultBigFont);
+		intializeDialog(title,buttonPressed);
+		addWindowListener(this);
+	}
+	/*.................................................................................................................*/
+	public ExtensibleDialog (Object parent, String title) {
+		super(parent, title);
+		setFont(defaultBigFont);
+		buttonPressed = new MesquiteInteger(1);
+		intializeDialog(title,buttonPressed);
+		addWindowListener(this);
+	}
+	int itemCount = 0;
+	/*.................................................................................................................*/
+	private GridBagConstraints createGridBagConstraints() {
+		GridBagConstraints c = new GridBagConstraints();
+		c.gridx=0;
+		c.gridy = GridBagConstraints.RELATIVE;
+		c.gridwidth=1;
+		c.gridheight=1;
+		c.fill=GridBagConstraints.BOTH;
+		c.anchor=GridBagConstraints.WEST;
+		return c;
+	}
+	/*.................................................................................................................*/
+	private GridBagConstraints adjustGridBagConstraints() {
+		return constraints;
+	}
+	/*.................................................................................................................*/
+	void intializeDialog (String title, MesquiteInteger buttonPressed) {
+		d = new Dimension(minDialogWidth, minDialogHeight);
+		gridBag = new GridBagLayout();
+		constraints = createGridBagConstraints();
+		setLayout(gridBag);
+		this.buttonPressed = buttonPressed;
+		this.setResizable(false);
+
+	}
+	public void setContentPane(JPanel panel) {
+		parentDialog.setContentPane(panel);
+	}
+
+	/*.................................................................................................................*/
+	public void setAddPanel (Panel addPanel, LayoutManager layout) {
+		this.addPanel = addPanel;
+		//setContentPane(addPanel);
+		if (layout==null){   // in this case, inherit the basic layout structure from dialog
+			currentGridBag = new GridBagLayout();
+			addPanel.setLayout(currentGridBag);
+		}
+		else {
+			addPanel.setLayout(layout);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setAddJPanel (JPanel addPanel, LayoutManager layout) {
+		this.addJPanel = addPanel;
+		//setContentPane(addPanel);
+		if (layout==null){   // in this case, inherit the basic layout structure from dialog
+			currentGridBag = new GridBagLayout();
+			addPanel.setLayout(currentGridBag);
+		}
+		else {
+			addPanel.setLayout(layout);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setAddPanel (Panel addPanel) {
+		setAddPanel(addPanel,null);
+	}
+	/*.................................................................................................................*/
+	public void setAddJPanel (JPanel addPanel) {
+		setAddJPanel(addPanel,null);
+	}
+	/*.................................................................................................................*/
+	public Panel getAddPanel () {
+		return addPanel;
+	}
+	/*.................................................................................................................*/
+	public JPanel getAddJPanel () {
+		return addJPanel;
+	}
+	/*.................................................................................................................*/
+	public void nullifyAddPanel () {
+		addPanel = null;
+		addJPanel=null;
+		//setContentPane(null);
+		//  	lastPanel = addPanel;
+	}
+	/*.................................................................................................................*/
+	public void suppressNewPanel () {
+		samePanelAsLast = true;
+	}
+	/*.................................................................................................................*/
+	public void forceNewPanel () {
+		samePanelAsLast = false;
+	}
+	/*.................................................................................................................*/
+	public Panel addNewDialogPanel (Panel panel,GridBagConstraints c) {
+		wasSamePanelAsLast = samePanelAsLast;
+		if (!samePanelAsLast) {
+			Panel newPanel;
+			if (panel != null)
+				newPanel = panel;
+			else
+				newPanel = new Panel();
+			addToDialog(newPanel, c);
+			newPanel.setVisible(true);
+			if (currentGridBag!=null && (addPanel!=null || addJPanel!=null))
+				currentGridBag.setConstraints(newPanel,createGridBagConstraints());
+			else
+				gridBag.setConstraints(newPanel,constraints);
+			lastPanel = newPanel;
+			return newPanel;
+		}
+		samePanelAsLast = false;
+		return lastPanel;
+	}
+	/*.................................................................................................................*
+	public void setAlignmentOfLastPanel (int alignment) {
+		if (lastPanel!=null) {
+			GridBagConstraints constraints = null;
+			if (currentGridBag!=null) {
+				constraints = currentGridBag.getConstraints(lastPanel);
+				if (constraints!=null) {
+					constraints.anchor = alignment;
+					currentGridBag.setConstraints(lastPanel,constraints);
+				}
+			}
+			else {
+				constraints = gridBag.getConstraints(lastPanel);
+				if (constraints!=null) {
+					constraints.anchor = alignment;
+					gridBag.setConstraints(lastPanel,constraints);
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public Panel addNewDialogPanel () {
+		return addNewDialogPanel(null,null);
+	}
+	/*.................................................................................................................*/
+	public Panel addNewDialogPanel (Panel panel) {
+		return addNewDialogPanel(panel, null);
+	}
+	/*.................................................................................................................*/
+	public Panel addNewDialogPanel (GridBagConstraints c) {
+		return addNewDialogPanel(null, c);
+	}
+	/*.................................................................................................................*/
+	public Panel getLastPanel () {
+		return lastPanel;
+	}
+	/*.................................................................................................................*/
+	public void addToDialog (Component component, Object c) {
+		if (component!=null) {
+			if (addPanel!=null && component !=addPanel) {
+				if (customConstraints!=null)
+					addPanel.add(component,(String)customConstraints);
+				else
+					addPanel.add(component, adjustGridBagConstraints());
+				component.setBackground(addPanel.getBackground());
+			} else if (addJPanel!=null && component !=addJPanel) {
+				if (customConstraints!=null)
+					addJPanel.add(component,(String)customConstraints);
+				else
+					addJPanel.add(component, adjustGridBagConstraints());
+				//addJPanel.add(component);
+
+
+				component.setBackground(addJPanel.getBackground());
+			}
+			else {
+				//if (c==null)
+				add(component);
+				//else 
+				//	add(component, c);
+				component.setBackground(getBackground());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void addToDialog (Component component) {
+		addToDialog(component, null);
+	}
+	/*.................................................................................................................*/
+	public GridBagLayout getGridBagLayout () {
+		return gridBag;
+	}
+	/*.................................................................................................................*/
+	public GridBagConstraints getGridBagConstraints () {
+		return constraints;
+	}
+	/*.................................................................................................................*/
+	public void setCustomConstraints (Object customConstraints) {
+		this.customConstraints = customConstraints;
+	}
+	/*.................................................................................................................*/
+	public void nullifyCustomConstraints () {
+		customConstraints = null;
+	}
+	/*.................................................................................................................*/
+	public Object getCustomConstraints () {
+		return customConstraints;
+	}
+	/*.................................................................................................................*/
+	public void setGridBagConstraints (GridBagConstraints constraints) {
+		this.constraints = constraints;
+	}
+	/*.................................................................................................................*/
+	public void setDefaultTextComponent (Component textComponent) {
+		defaultTextComponent = textComponent;
+	}
+	/*.................................................................................................................*/
+	public void appendToHelpString (String s) {
+		helpString += s + " ";
+	}
+	/*.................................................................................................................*/
+	public String getHelpString () {
+		return helpString;
+	}
+
+	/*.................................................................................................................*/
+	public boolean hasHelpURL () {
+		return (!StringUtil.blank(getHelpURL()) || (helpURLOwnerModule!=null));
+	}
+
+	/*.................................................................................................................*/
+	private boolean getUseManualPage () {
+		return useManualPage;
+	}
+	/*.................................................................................................................*/
+	private void setUseManualPage (boolean useManual) {
+		useManualPage = useManual;
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule getHelpURLOwnerModule () {
+		return helpURLOwnerModule;
+	}
+	/*.................................................................................................................*/
+	public void setHelpURLOwnerModule (MesquiteModule ownerModule) {
+		helpURLOwnerModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+	public void showManual(){
+		if (getHelpURLOwnerModule()!=null) {
+			if (!StringUtil.blank(helpURL)) {
+				String s = getHelpURLOwnerModule().getPackageIntroModule().getDirectoryPath() + getHelpURL();
+				MesquiteModule.showWebPage(s, false);
+			}
+			else if (useManualPage)
+				getHelpURLOwnerModule().showManual();
+			else
+				MesquiteModule.showWebPage(getHelpURLOwnerModule().getPackageIntroModule().getSplashURL(), false);
+		}
+		else if (!StringUtil.blank(helpURL)) 
+			MesquiteModule.showWebPage(getHelpURL(), false);
+	}
+	/*.................................................................................................................*/
+	public void setHelpURL (MesquiteModule ownerModule, String s) {
+		setHelpURL(ownerModule,s,false);
+	}
+	/*.................................................................................................................*/
+	public void setHelpURL (MesquiteModule ownerModule, String s, boolean useManual) {
+		helpURLOwnerModule = ownerModule;
+		helpURL = s;
+		useManualPage = useManual;
+	}
+	/*.................................................................................................................*/
+	public void setHelpURL (String s) {
+		helpURL = s;
+	}
+	/*.................................................................................................................*/
+	public String getHelpURL () {
+		return helpURL;
+	}
+	/*.................................................................................................................*/
+	public String getDefaultOKLabel () {
+		return defaultLabel;
+	}
+	/*.................................................................................................................*/
+	public String getDefaultCancelLabel () {
+		return defaultCancelLabel;
+	}
+	/*.................................................................................................................*/
+	public Button getMainButton () {
+		return button0;
+	}
+	/*.................................................................................................................*/
+	public Button getCancelButton () {
+		int cancel = getButtonNumber(getDefaultCancelLabel());
+		if (cancel==0)
+			return button0;
+		else if (cancel==1)
+			return button1;
+		else if (cancel==2)
+			return button2;
+		return null;
+	}
+	/*.................................................................................................................*/
+	void drawLine(int x1, int y1, int x2, int y2, Color color) {
+		Graphics g = getGraphics();
+		if (g!=null) {
+			g.setColor(color);
+			g.drawLine(x1,y1,x2, y2);
+		}
+	}
+	/*.................................................................................................................*/
+	public int getButtonNumber (String buttonLabel) {
+		if (buttonLabel == null)
+			return -1;
+		else if (buttonLabel.equalsIgnoreCase(buttonLabel0))
+			return 0;
+		else if (buttonLabel.equalsIgnoreCase(buttonLabel1))
+			return 1;
+		else if (buttonLabel.equalsIgnoreCase(buttonLabel2))
+			return 2;
+		else
+			return -1; 
+	}
+	/*.................................................................................................................*/
+	public boolean hasDefaultButton(){
+		return !StringUtil.blank(defaultLabel);
+	}
+	/*.................................................................................................................*/
+	public void setDefaultButton (String defaultLabel) {
+		super.setDefaultButton(defaultLabel);
+		if (defaultLabel != null)
+			this.defaultLabel = defaultLabel;
+		this.defaultButtonNumber = getButtonNumber(defaultLabel);		
+	}
+	/*.................................................................................................................*/
+	void setPrimaryButtonConstraints(Panel buttons) {
+		gridBag.setConstraints(buttons,constraints);
+	}
+	/*.................................................................................................................*/
+
+	public boolean addExtraButtons (Panel panel, ActionListener actionListener) {
+		boolean buttonAdded=false;
+		for (int i=0; i<numExtraButtons; i++) {
+			if (!StringUtil.blank(extraButtonLabels[i])) {
+				if (actionListener!=null)
+					addAListenedButton(extraButtonLabels[i],panel, actionListener);
+				else
+					addAButton(extraButtonLabels[i],panel);
+				buttonAdded = true;
+			}
+		}
+		if (buttonAdded)
+			addAnEmptyImage(panel);
+		return buttonAdded;
+	}
+	/*.................................................................................................................*/
+
+	public boolean addExtraButtons (Panel panel) {
+		return addExtraButtons(panel, null);
+	}
+	/*.................................................................................................................*/
+
+	public void setExtraButton (String s) {
+		currentExtraButton++;
+		if (currentExtraButton<numExtraButtons)
+			extraButtonLabels[currentExtraButton]=s;
+	}
+	/*.................................................................................................................*/
+
+	public void addHelpButtons (Panel panel) {
+		boolean buttonAdded=false;
+		if (hasHelpURL()) {
+			helpURLPanel = addAListenedImage("manual", "manual.gif","manualPressed.gif",true,panel, this);
+			helpURLPanel.setVisible(true);
+			buttonAdded = true;
+		}
+		if (!isInWizard() && !StringUtil.blank(getHelpString())) {
+			//addAListenedButton("?",buttons,this);
+			helpStringPanel = addAListenedImage("?", "help.gif","helpPressed.gif",true,panel, this);
+			helpStringPanel.setVisible(true);
+			buttonAdded = true;
+		}
+		if (buttonAdded) {
+			addAnEmptyImage(panel);
+		}
+	}
+	/*.................................................................................................................*/
+	TextField textEdgeCompensationDetector; //shown only once; to help detect text edge compenstation factors;
+	boolean checkTextEdge = false;
+	public void setCheckTextEdge(boolean cte){
+		checkTextEdge = cte;
+	}
+	/*.................................................................................................................*/
+	public void addPrimaryButtonRow (String buttonLabel0, String buttonLabel1, String buttonLabel2) {
+		Panel buttons = new Panel();
+		//		buttons.setSize(dialogWidth, buttonHeight);
+		String singleButton = null;
+		boolean noButtons=true;
+		if (hasHelpURL())
+			noButtons=false;
+		if (!isInWizard() && !StringUtil.blank(getHelpString()))
+			noButtons=false;
+		addHelpButtons(buttons);
+		if (addExtraButtons(buttons))
+			noButtons=false;
+		if (buttonLabel2!=null) {
+			button2=addAButton(buttonLabel2,buttons);
+			this.buttonLabel2 = buttonLabel2;
+			if (noButtons) {
+				singleButton = buttonLabel2;
+				noButtons = false;
+			}
+		}
+		if (buttonLabel1!=null) {
+			button1=addAButton(buttonLabel1,buttons);
+			this.buttonLabel1 = buttonLabel1;
+			if (noButtons) {
+				singleButton = buttonLabel1;
+				noButtons = false;
+			}
+			else if (!noButtons)
+				singleButton = null;
+		}
+		if (buttonLabel0!=null) {
+			button0=addAButton(buttonLabel0,buttons);
+			this.buttonLabel0 = buttonLabel0;
+			if (noButtons) {
+				singleButton = buttonLabel0;
+				noButtons = false;
+			}
+			else if (!noButtons)
+				singleButton = null;
+		}
+		if (!MesquiteModule.textEdgeRemembered || checkTextEdge)
+			buttons.add("West", textEdgeCompensationDetector = new TextField(" "));
+		addToDialog(buttons);	
+		setPrimaryButtonConstraints(buttons);	
+		if (singleButton!=null)
+			setDefaultButton(singleButton);	
+	}	/*.................................................................................................................*/
+	public void addPrimaryButtonRow (String[] buttonLabels) {
+		if (buttonLabels==null)
+			return;
+		Panel buttons = new Panel();
+		//		buttons.setSize(dialogWidth, buttonHeight);
+		String singleButton = null;
+		boolean noButtons=true;
+		if (hasHelpURL())
+			noButtons=false;
+		if (!isInWizard() && !StringUtil.blank(getHelpString()))
+			noButtons=false;
+		addHelpButtons(buttons);
+		if (addExtraButtons(buttons))
+			noButtons=false;
+		for (int i=buttonLabels.length-1; i>=0; i--) {
+			if (buttonLabels[i]!=null) {
+				button2=addAButton(buttonLabels[i],buttons);
+				this.buttonLabels[i] = buttonLabels[i];
+				if (noButtons) {
+					singleButton = buttonLabels[i];
+					noButtons = false;
+				}
+			}
+		}
+		if (!MesquiteModule.textEdgeRemembered || checkTextEdge)
+			buttons.add("West", textEdgeCompensationDetector = new TextField(" "));
+		addToDialog(buttons);	
+		setPrimaryButtonConstraints(buttons);	
+		if (singleButton!=null)
+			setDefaultButton(singleButton);	
+	}
+	/*.................................................................................................................*/
+	public void addPrimaryButtonRowListener (String buttonLabel0, String buttonLabel1, ActionListener actionListener) {
+		Panel buttons = new Panel();
+		//		buttons.setSize(dialogWidth, buttonHeight);
+		addHelpButtons(buttons);
+		addExtraButtons(buttons, actionListener);
+		button1=addAListenedButton(buttonLabel1,buttons,actionListener);
+		this.buttonLabel1 = buttonLabel1;
+		button0=addAListenedButton(buttonLabel0,buttons,actionListener);
+		this.buttonLabel0 = buttonLabel0;
+		addToDialog(buttons);			
+		setPrimaryButtonConstraints(buttons);
+		addBlankLine();
+	}
+	/*.................................................................................................................*/
+	public void addPrimaryButtonRow (String buttonLabel0, String buttonLabel1) {
+		addPrimaryButtonRowListener(buttonLabel0,buttonLabel1,null);
+	}
+	/*.................................................................................................................*/
+	public void addPrimaryButtonRow (String buttonLabel0) {
+		Panel buttons = new Panel();
+		//		buttons.setSize(dialogWidth, buttonHeight);
+		addHelpButtons(buttons);
+		addExtraButtons(buttons);
+		button0=addAButton(buttonLabel0,buttons);
+		this.buttonLabel0 = buttonLabel0;
+		addToDialog(buttons);	
+		setPrimaryButtonConstraints(buttons);	
+		setDefaultButton(buttonLabel0);	
+		addBlankLine();
+	}
+	/*.................................................................................................................*/
+	public Button addAButton (String s, Panel buttons) { 
+		return addAButton(s,buttons,null);
+	}
+	/*.................................................................................................................*/
+	public Button addAButton (String s, Panel buttons, GridBagConstraints c) { 
+		Button button;
+		if (buttons==null && lastPanel!=null)
+			buttons = lastPanel;
+		if (buttons == null)
+			return null;
+		if (c==null)
+			buttons.add(button = new Button(s));
+		else
+			buttons.add(button = new Button(s),c);
+		numButtons++;
+		return button;
+	}
+	/*.................................................................................................................*
+	public Button addAListenedButton (String s, Panel buttons, ActionListener actionListener) { //David: modified to return button
+		if (StringUtil.blank(s))
+			return null;
+		Button button=null;
+		if (buttons==null) {
+			if (lastPanel!=null) {
+				lastPanel.add(button = new Button(s));
+				numButtons++;
+			}
+		}
+		else 	{
+			buttons.add(button = new Button(s));
+			numButtons++;
+		}
+		if ((actionListener!=null) && (button!=null))
+			button.addActionListener(actionListener);
+		return button;
+	}
+	/*.................................................................................................................*/
+	public Button addAListenedButton (String s, Panel buttons, ActionListener actionListener) { //David: modified to return button
+		return addAListenedButton(s,buttons,actionListener,null);
+	}
+	/*.................................................................................................................*/
+	public Button addAListenedButton (String s, Panel buttons, ActionListener actionListener, GridBagConstraints c) { 
+		if (StringUtil.blank(s))
+			return null;
+		Button button=addAButton(s,buttons,c);
+		if ((actionListener!=null) && (button!=null))
+			button.addActionListener(actionListener);
+		return button;
+	}
+
+	/*.................................................................................................................*/
+	public TextCanvasWithButtons addATextCanvasWithButtons(String s, String button1Name, String button1Command, String button2Name, String button2Command, ActionListener actionListener){
+        Panel newPanel = addNewDialogPanel();
+        GridBagLayout gridbag = new GridBagLayout();
+		GridBagConstraints gridConstraints = new GridBagConstraints();
+		gridConstraints.gridwidth=1;
+		gridConstraints.gridheight=2;
+		gridConstraints.gridy = 1;
+		gridConstraints.gridx = 1;
+		gridConstraints.weighty=1.0;
+
+		newPanel.setLayout(gridbag);
+
+		TextCanvasWithButtons textCanvasWithButtons = new TextCanvasWithButtons();
+
+		pack();
+		Dimension d = getPreferredSize();
+		dialogWidth = d.width;
+		if (dialogWidth<minDialogWidthWithCanvas) //this had been hardcoded at 240
+			dialogWidth = minDialogWidthWithCanvas;
+		else if (dialogWidth> maxDialogWidthWithCanvas) 
+			dialogWidth =maxDialogWidthWithCanvas;
+		MesquiteTextCanvas textCanvas = MesquiteTextCanvas.getTextCanvas(dialogWidth-sideBuffer*2, defaultSmallFont, s);
+        gridbag.setConstraints(textCanvas, gridConstraints);
+        newPanel.add(textCanvas);
+		textCanvasWithButtons.setTextCanvas(textCanvas);
+		
+		gridConstraints.weighty = 0.0;		   //reset to the default
+		gridConstraints.gridwidth = GridBagConstraints.REMAINDER; //end row
+		gridConstraints.gridheight = 1;		   //reset to the default
+		gridConstraints.gridy = 1;
+		gridConstraints.gridx = 3;
+
+        Button button = new Button(button1Name);
+        gridbag.setConstraints(button, gridConstraints);
+        newPanel. add(button);
+		button.addActionListener(actionListener);
+		button.setActionCommand(button1Command);
+		textCanvasWithButtons.setButton(button);
+
+		if (StringUtil.notEmpty(button2Name)) {
+			gridConstraints.gridy = 2;
+	        Button button2 = new Button(button2Name);
+	        gridbag.setConstraints(button2, gridConstraints);
+	        newPanel.add(button2);
+			button2.addActionListener(actionListener);
+			button2.setActionCommand(button2Command);
+			textCanvasWithButtons.setButton2(button2);
+		}
+		
+		lastPanel=null;
+		return textCanvasWithButtons;
+	}
+	/*.................................................................................................................*/
+	public TextCanvasWithButtons addATextCanvasWithButtons(String s, String button1Name, String button1Command, ActionListener actionListener){
+		return addATextCanvasWithButtons(s,button1Name, button1Command, null,null, actionListener);
+	}
+	/*.................................................................................................................*/
+	public ImagePanel addAListenedImage (String imageCommandName, String imageName, String imagePressedName, boolean inRoot, Panel panel, ImagePanelListener imageListener) {
+		ImagePanel imagePanel = null;
+		Image image=null;
+		Image imagePressed=null;
+		if (inRoot) {
+			image = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + imageName);
+			imagePressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + imagePressedName);
+		}
+		imagePanel = new ImagePanel(image,imagePressed, imageCommandName, imageListener);
+		if (panel==null) {
+			if (lastPanel!=null) 
+				lastPanel.add(imagePanel);
+		}
+		else 	
+			panel.add(imagePanel);
+		return imagePanel;
+	}
+	/*.................................................................................................................*/
+	public ImagePanel addAnEmptyImage (Panel panel) {
+		Image image = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "empty.gif");
+		ImagePanel imagePanel = new ImagePanel(image);
+
+		if (panel==null) {
+			if (lastPanel!=null) 
+				lastPanel.add(imagePanel);
+		}
+		else 	
+			panel.add(imagePanel);
+		return imagePanel;
+	}
+	/*.................................................................................................................*/
+	public Button addButton (String s) {
+		Panel newPanel = addNewDialogPanel();
+		Button button = new Button(s);
+		newPanel.add(button);
+		numButtons++;
+		return button;
+	}
+	/*.................................................................................................................*/
+	int currentWidth=0;
+
+	/*.................................................................................................................*/
+	public MesquiteTabbedPanel addMesquiteTabbedPanel() {
+		MesquiteTabbedPanel tabbedPanel = new MesquiteTabbedPanel(this);
+		add(tabbedPanel);
+		return tabbedPanel;
+	}
+	/*.................................................................................................................*/
+	public PopUpPanelOfCards addPopUpPanelOfCards (String name) {
+		PopUpPanelOfCards panelOfCards = new PopUpPanelOfCards(this,name);
+		addNewDialogPanel(panelOfCards);
+		return panelOfCards;
+	}
+	/*.................................................................................................................*/
+	private void resetTextCanvasSizes(Component c){
+		if (c==null)
+			return;
+		if (c instanceof MesquiteTextCanvas) {
+
+			minDialogWidth = minDialogWidthWithCanvas;
+			maxDialogWidth = maxDialogWidthWithCanvas;
+			if (currentWidth>maxDialogWidth)
+				currentWidth = maxDialogWidth;
+			else if (currentWidth<minDialogWidth)
+				currentWidth = minDialogWidth;
+			((MesquiteTextCanvas)c).setCanvasRows(currentWidth);
+
+		}
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					resetTextCanvasSizes(cc[i]);
+		}
+	}
+	/*.................................................................................................................*/
+	public void report(Component c, String spacer){
+		if (c==null)
+			return;
+		System.out.println(spacer + "x " + c.getX() + " y " + c.getY() + " w " + c.getWidth() + " h " + c.getHeight() + " vis " + c.isVisible() + " " + c);
+		spacer += "  ";
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					report(cc[i], spacer);
+		}
+	}
+	/*.................................................................................................................*/
+	private void doLayouts(Component c){
+		if (c==null)
+			return;
+		try {
+			if (c instanceof Container){
+				if (((Container)c).getLayout() != null)
+					c.doLayout();
+				Component[] cc = ((Container)c).getComponents();
+				if (cc!=null && cc.length>0)
+					for (int i=0; i<cc.length; i++)
+						doLayouts(cc[i]);
+			}
+		}
+		catch(Exception e){
+			MesquiteMessage.println("exception in doLayouts of ExtensibleDialog");
+		}
+	}
+	/*.................................................................................................................*/
+	private void makeAllVisible(Component c){
+		if (c==null)
+			return;
+		c.setVisible(true);
+		if (c instanceof Container && !(c instanceof JTabbedPane)){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					makeAllVisible(cc[i]);
+		}
+	}
+	/*
+	static void resetCardLayouts(Component c){  //a workaround for apparent OS X bug
+ 		if (c instanceof Container){
+ 			Component[] comps = ((Container)c).getComponents();
+ 			if (comps != null)
+ 				for (int i=0; i<comps.length; i++)
+ 				resetCardLayouts(comps[i]);
+ 		}
+ 		if (c instanceof PanelOfCards){
+ 			((PopUpPanelOfCards)c).reset();
+ 		}
+ 	}
+	/*.................................................................................................................*/
+	public void prepareDialog () {
+
+
+		pack();
+		d = getPreferredSize(true);
+		/*if (isInWizard()){
+			d.width -= MesquiteDialogParent.infoWidth;
+		}
+		 */
+		if (MesquiteTrunk.isMacOSXJaguar()){
+			//		int targetWidth = 300;
+			//		int targetHeight = 160;
+			int targetWidth = d.width;
+			int targetHeight = d.height;
+			int h, v;
+			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+			h = (screenSize.width-targetWidth)/2;
+			int menuBarHeight = 0;
+			if (!StringUtil.blank(System.getProperty("mrj.version")))
+				menuBarHeight = 32;
+			v = (screenSize.height-targetHeight - menuBarHeight)/2 + menuBarHeight;
+			if (v < menuBarHeight)
+				v = menuBarHeight;
+			setDialogLocation(h, v);
+		}
+
+		//	pack();
+		//	d = getPreferredSize();
+		currentWidth = d.width;
+		if (currentWidth < 240) {
+			currentWidth = 240;
+		}
+		if (currentWidth >600) {
+			currentWidth = 600;
+		}
+		resetTextCanvasSizes(parentDialog);
+		pack();
+		d = getPreferredSize(true);
+		if (d.width<minDialogWidth) {
+			d.width = minDialogWidth;
+		}
+		else if (d.width> maxDialogWidth) {
+			d.width = maxDialogWidth;
+		}
+
+		if (d.height<minDialogHeight) {
+			d.height = minDialogHeight;
+		}
+		pack();
+		if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>=1.4)
+			d.height +=25;
+		doLayouts(outerContents);
+		makeAllVisible(outerContents);
+
+		if (isInWizard()){
+			d.width += MesquiteDialogParent.infoWidth;
+			d.width += 100;
+		}
+		else
+			d.width += 20;
+
+
+		setDialogSize(d);
+		try {
+			outerContents.invalidate();
+			outerContents.validate();
+			doLayout();
+		}
+		catch (Throwable t){
+		}
+		MesquiteWindow.centerWindow(getParentDialog());
+		if (MesquiteTrunk.isMacOSXJaguar())
+			pack(); //add for Jaguar bug, possibly also linux
+		if (helpURLPanel!=null)  // for reasons that are unclear, these often aren't drawn.
+			helpURLPanel.repaint();
+		if (helpStringPanel!=null) // for reasons that are unclear, these often aren't drawn.
+			helpStringPanel.repaint();
+		setFoci();
+		//resetCardLayouts(outerContents);
+
+
+	}
+
+
+	/*.................................................................................................................*/
+	public void setFoci () {
+		boolean success=false;
+		if (focalComponent!=null)
+			success = focalComponent.requestFocusInWindow();
+		if (defaultTextComponent!=null) {
+			if (defaultTextComponent instanceof TextComponent)
+				((TextComponent)defaultTextComponent).selectAll();
+			else if (defaultTextComponent instanceof JTextComponent)
+				((JTextComponent)defaultTextComponent).selectAll();
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void prepareDialogHideFirst () {
+		boolean wasVisible = isVisible();
+		//if (wasVisible && MesquiteTrunk.isMacOSXJaguar())
+		//	setVisible(false);
+		prepareDialog();
+		if (focalComponent!=null)
+			focalComponent.requestFocusInWindow();
+		//if (wasVisible && MesquiteTrunk.isMacOSXJaguar())
+		//	setVisible(true);
+	}
+	/*.................................................................................................................*/
+	void prepareAndDisplayDialogForAWTThread () {
+		prepareDialog();
+		setVisible(true);
+		setFoci();
+	}
+	/*.................................................................................................................*/
+	public void prepareAndDisplayDialog (boolean onAWTThreadOnly) {
+		if (onAWTThreadOnly){
+			try {
+				SwingUtilities.invokeAndWait(new PADDThread(this, true));
+			} catch (InterruptedException e) {
+				prepareDialog();
+				setVisible(true);
+				setFoci();
+			} catch (InvocationTargetException e) {
+				prepareDialog();
+				setVisible(true);
+				setFoci();
+			}
+		}
+		else {
+			prepareDialog();
+			setVisible(true);
+			setFoci();
+		}
+	}
+	class PADDThread implements Runnable {
+		ExtensibleDialog parent;
+		public PADDThread(ExtensibleDialog parent, boolean vis){
+			this.parent = parent;
+		}
+		public void run(){
+			parent.prepareAndDisplayDialogForAWTThread();
+		}
+	}
+	/*.................................................................................................................*/
+	public void prepareAndDisplayDialog () {
+		prepareAndDisplayDialog(false);
+	}
+
+	/*.................................................................................................................*/
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+	}
+	/*.................................................................................................................*/
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w,h);
+	}
+	/*.................................................................................................................*/
+	public void componentResized(ComponentEvent e){
+		if (e==null || e.getComponent()!= getParentDialog())
+			return;
+		if (d == null){
+		}
+		else if (getBounds().width< d.width || getBounds().height<d.height) {
+			setSize(d);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setDefaultComponent (Component component) {
+		focalComponent = component;
+	}
+	/*.................................................................................................................*/
+	/**Can be overrided to provide extra panels above button row*/
+	public void addAuxiliaryDefaultPanels(){//************
+	}
+	/*.................................................................................................................*/
+	public void completeDialog () {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRow(defaultLabel, defaultCancelLabel);
+		prepareDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog () {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRow(defaultLabel, defaultCancelLabel);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean setDefaultToOK) {
+		addDefaultPanelsListener(setDefaultToOK, null);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean setDefaultToOK, ActionListener actionListener) {
+		addDefaultPanelsListener(setDefaultToOK, actionListener);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (boolean setDefaultToOK, ActionListener actionListener, boolean onAWTThreadOnly) {
+		addDefaultPanelsListener(setDefaultToOK, actionListener);
+		prepareAndDisplayDialog(onAWTThreadOnly);
+	}
+	/*.................................................................................................................*/
+	private void addDefaultPanelsListener (boolean setDefaultToOK, ActionListener actionListener) {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRowListener(defaultLabel, defaultCancelLabel, actionListener);
+		if (setDefaultToOK)
+			setDefaultButton(defaultLabel);
+		else 
+			setDefaultButton(defaultCancelLabel);
+	}
+	/*.................................................................................................................*/
+	public void completeDialog (String buttonLabel0, String buttonLabel1, boolean setDefaultToOK, ActionListener actionListener) {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRowListener(buttonLabel0, buttonLabel1,actionListener);
+		if (setDefaultToOK)
+			setDefaultButton(buttonLabel0);
+		prepareDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (String buttonLabel0, String buttonLabel1, boolean setDefaultToOK, ActionListener actionListener) {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRowListener(buttonLabel0, buttonLabel1,actionListener);
+		if (setDefaultToOK)
+			setDefaultButton(buttonLabel0);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeDialog (String buttonLabel0, String buttonLabel1, String buttonLabel2, String defaultButton) {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRow(buttonLabel0, buttonLabel1,buttonLabel2);
+		//if (defaultButton!=null)  //David: why is this here? If not here, how do we disable default buttons?
+		setDefaultButton(defaultButton);
+		prepareDialog();
+	}
+	/*.................................................................................................................*/
+	public void completeAndShowDialog (String buttonLabel0, String buttonLabel1, String buttonLabel2, String defaultButton) {
+		addAuxiliaryDefaultPanels();//************
+		addPrimaryButtonRow(buttonLabel0, buttonLabel1,buttonLabel2);
+		//if (defaultButton!=null)  //David: why is this here? If not here, how do we disable default buttons?
+		setDefaultButton(defaultButton);
+		prepareAndDisplayDialog();
+	}
+	/*.................................................................................................................*/
+	void addListableToList(Listable[] listables, boolean[] isSubchoice, DoubleClickList list, int priorityLevel) {
+		for (int i=0; i<listables.length; i++) {
+			if (listables[i]!=null){
+				if (!MenuOwner.considerPriorities || ((listables[i] instanceof Priority && ((Priority)listables[i]).getPriority()==priorityLevel) || (!(listables[i] instanceof Priority) && priorityLevel==0))) {
+					String name = "";
+					if (listables[i] instanceof SpecialListName && ((SpecialListName)listables[i]).getListName()!=null)
+						name = ((SpecialListName)listables[i]).getListName();
+					else if (listables[i].getName()!=null)
+						name = listables[i].getName();
+					if (isSubchoice != null && isSubchoice[i])
+						name = "  - " + name;
+					list.add(StringUtil.truncateIfLonger(name, maxLengthInList), -1);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	static int maxLengthInList = 80;
+	public DoubleClickList createListenedList (Object names, MesquiteInteger selected, int numElements, ActionListener actionListener, ItemListener itemListener, boolean multipleMode) {
+		return createListenedList (names, null, selected, numElements, actionListener, itemListener, multipleMode);
+	}
+	public DoubleClickList createListenedList (Object names, boolean[] isSubchoice, MesquiteInteger selected, int numElements, ActionListener actionListener, ItemListener itemListener, boolean multipleMode) {
+		String[] strings = null;
+		Listable[] listables = null;
+		if (names != null)
+			if (names instanceof Listable[])
+				listables = (Listable[])names;
+			else if (names instanceof String[])
+				strings = (String[])names;
+		DoubleClickList list = new DoubleClickList (numElements, multipleMode); 
+		list.setDoubleClickListener(this);
+		list.setBackground(Color.white);
+		list.addItemListener(itemListener);
+		list.addActionListener(actionListener);
+		if (listables!=null){
+			if (MenuOwner.considerPriorities)
+				for (int i=1; i<MenuOwner.MAXPRIORITY; i++)
+					addListableToList(listables, isSubchoice, list, i);
+			addListableToList(listables, isSubchoice, list, 0);
+			if (selected!=null && selected.getValue()>=0 && selected.getValue()<listables.length)
+				list.select(selected.getValue());
+		}
+		else if (strings!=null){
+			for (int i=0; i<strings.length; i++)
+				if (strings[i]!=null)
+					list.add(StringUtil.truncateIfLonger(strings[i], maxLengthInList), -1);
+			if (selected!=null && selected.getValue()>=0 && selected.getValue()<strings.length)
+				list.select(selected.getValue());
+		}
+		return list;
+	}
+	/*.................................................................................................................*/
+	/**Adds a panel with three labels closely stacked, one on top of the other. */
+	public Panel addStackedLabels (String s1, String s2, String s3, int boldString) {  
+		Panel newPanel = addNewDialogPanel();
+		GridBagConstraints gridConstraints=null;
+		GridBagLayout gridBagLabels = new GridBagLayout();
+		gridConstraints = new GridBagConstraints();
+		gridConstraints.gridwidth=1;
+		gridConstraints.gridheight=1;
+		/*  enable these if you want it left-justified
+	       gridConstraints.ipadx=1;
+	       gridConstraints.ipady=1;
+	        gridConstraints.weightx=1;
+	       gridConstraints.weighty=1;
+		 */
+		/* enable this if you want them in the center, but left-justified with respect to each other
+	        gridConstraints.fill=GridBagConstraints.HORIZONTAL;
+		 */
+
+		newPanel.setLayout(gridBagLabels);
+		gridBagLabels.setConstraints(newPanel,gridConstraints);
+		gridConstraints.gridy = 0;
+		gridConstraints.gridx=1; 
+		/*
+	        if (StringUtil.blank(s3))
+	        	newPanel.setLayout(new GridLayout(2,1));
+	        else
+	        	newPanel.setLayout(new GridLayout(3,1));
+		 */
+		Label label;
+		if (!StringUtil.blank(s1)) {
+			gridConstraints.gridy++;
+			label = new Label(s1);
+			if (boldString==1)
+				label.setFont(boldFont);
+			newPanel.add(label,gridConstraints);
+		}
+		if (!StringUtil.blank(s2)) {
+			gridConstraints.gridy++;
+			label = new Label(s2);
+			if (boldString==2)
+				label.setFont(boldFont);
+			newPanel.add(label,gridConstraints);
+		}
+		if (!StringUtil.blank(s3)) {
+			gridConstraints.gridy++;
+			label = new Label(s3);
+			if (boldString==3)
+				label.setFont(boldFont);
+			newPanel.add(label);
+		}
+		return newPanel;
+	}
+	/*.................................................................................................................*/
+	/**Adds a panel with two labels closely stacked, one on top of the other. */
+	public Panel addStackedLabels (String s1, String s2, int boldString) {
+		return addStackedLabels(s1,s2,null,boldString);
+	}
+	/*.................................................................................................................*/
+	/**Adds a panel with two labels closely stacked, one on top of the other, with the second on in a smaller font. */
+	public void addStackedLabelsBottomSmall (String s1, String s2) {  
+		Panel newPanel = addNewDialogPanel();
+		//		newPanel.setLayout(new GridLayout(1,1));
+		GridBagLayout gridBagLabels = new GridBagLayout();
+		GridBagConstraints gridConstraints = new GridBagConstraints();
+		gridConstraints.gridwidth=1;
+		gridConstraints.gridheight=1;
+		gridConstraints.fill=GridBagConstraints.BOTH;
+		gridConstraints.anchor = GridBagConstraints.WEST;
+
+		newPanel.setLayout(gridBagLabels);
+		gridBagLabels.setConstraints(newPanel,gridConstraints);
+		gridConstraints.gridy = 0;
+		gridConstraints.gridx=1;
+		newPanel.setLayout(new GridLayout(2,1));
+		Label label;
+		if (!StringUtil.blank(s1)) {
+			gridConstraints.gridy++;
+			label = new Label(s1);
+			newPanel.add(label);
+		}
+		if (!StringUtil.blank(s2)) {
+			gridConstraints.gridy++;
+			label = new Label(s2);
+			label.setFont(defaultSmallFont);
+			newPanel.add(label);
+		}
+	}
+	/*.................................................................................................................*/
+	public JLabel addLabelSmallText (String s) {
+
+		Panel newPanel;
+		JLabel label = new JLabel(s);
+
+		label = new JLabel(s);
+		newPanel = addNewDialogPanel();
+		newPanel.add(label);
+		label.setFont(defaultSmallFont);
+
+		return label;
+	}
+	/*.................................................................................................................*/
+	public JLabel addLabel (String s, int alignment, boolean doAlignment, boolean isBold) {
+
+		Panel newPanel;
+		JLabel label = new JLabel(s);
+
+		if (doAlignment && alignment == Label.LEFT) {
+			newPanel = addNewDialogPanel();
+			newPanel.add(label);
+			newPanel.setLayout(new GridLayout(1,1));
+			label.setHorizontalAlignment(JLabel.LEFT);
+			if (isBold)
+				label.setFont(boldFont);
+		}
+		else {
+			label = new JLabel(s);
+			newPanel = addNewDialogPanel();
+			newPanel.add(label);
+			if (isBold)
+				label.setFont(boldFont);
+		}
+		return label;
+	}
+	/*.................................................................................................................*/
+	public JLabel addLabel (String s, int alignment, boolean doAlignment) {
+		return addLabel(s,alignment,doAlignment, false);
+	}
+	/*.................................................................................................................*/
+	public JLabel addBoldLabel (String s) {
+		return addLabel(s,0,false,true);
+	}
+	/*.................................................................................................................*/
+	public JLabel addLabel (String s) {
+		return addLabel(s,0,false,false);
+	}
+	/*.................................................................................................................*/
+	public JLabel addLabel (String s, int alignment) {
+		return addLabel(s,alignment,true,false);
+	}
+	/*.................................................................................................................*/
+	public void addLargeOrSmallTextLabel (String message) {
+		if (message!=null) {
+			int totalLength = StringUtil.getStringDrawLength(getParentDialog(), message);
+			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+			if (totalLength>(screenSize.width/4) || message.indexOf("\n")>=0 || message.indexOf("\r")>=0)
+				addLargeTextLabel(message); // can be way too wide
+			else
+				addLabel(message);
+		}
+	}
+	public Choice addPopUpMenu (JLabel messageLabel, String[] choices, int defaultChoice) {
+		Panel newPanel = addNewDialogPanel();
+		newPanel.add(messageLabel);
+
+		Choice choice = new Choice();
+		if (choices!=null){
+			int numChoices=0;
+			for (int i=0; i<choices.length; i++) 
+				if (!StringUtil.blank(choices[i])) {
+					choice.add(choices[i]);
+					numChoices++;
+				}
+			if ((numChoices>0) && (defaultChoice<numChoices))
+				choice.select(defaultChoice);
+		}
+		newPanel.add(choice);
+		return choice;
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, String[] choices, int defaultChoice) {
+		JLabel label = new JLabel (message);
+		return addPopUpMenu(label, choices, defaultChoice);
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, String string1, String string2, String string3, String string4, int defaultChoice) {
+		Panel newPanel = addNewDialogPanel();
+		Label label = new Label (message);
+		newPanel.add(label);
+
+		Choice choice = new Choice();
+		if (string1!=null)
+			choice.add(string1);
+		if (string2!=null)
+			choice.add(string2);
+		if (string3!=null)
+			choice.add(string3);
+		if (string4!=null)
+			choice.add(string4);
+		if (choice.getItemCount()>0)
+			choice.select(defaultChoice);
+		newPanel.add(choice);
+		return choice;
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, ListableVector choices, int defaultChoice) {
+		Panel newPanel = addNewDialogPanel();
+		Label label = new Label (message);
+		newPanel.add(label);
+
+		Choice choice = new Choice();
+		if (choices!=null)
+			for (int i=0; i<choices.size(); i++) {
+				if (choices.elementAt(i).getName()!=null)
+					choice.add(choices.elementAt(i).getName());
+			}
+		if (choice.getItemCount()>0)
+			choice.select(defaultChoice);
+		newPanel.add(choice);
+		return choice;
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, Listable[] choices, int defaultChoice) {
+		Panel newPanel = addNewDialogPanel();
+		Label label = new Label (message);
+		newPanel.add(label);
+
+		Choice choice = new Choice();
+		if (choices!=null)
+			for (int i=0; i<choices.length; i++) {
+				if (choices[i].getName()!=null)
+					choice.add(choices[i].getName());
+			}
+		if (choice.getItemCount()>0)
+			choice.select(defaultChoice);
+		newPanel.add(choice);
+		return choice;
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, String string1, String string2, String string3, int defaultChoice) {
+		return addPopUpMenu(message, string1, string2, string3, null, defaultChoice);
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, String string1, String string2, int defaultChoice) {
+		return addPopUpMenu(message, string1, string2, null, null, defaultChoice);
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message) {
+		Panel newPanel = addNewDialogPanel();
+		Label label = new Label (message);
+		newPanel.add(label);
+
+		Choice choice = new Choice();
+		newPanel.add(choice);
+		return choice;
+	}
+	/*.................................................................................................................*/
+	public Choice addPopUpMenu (String message, Class dutyClass, int defaultChoice) {
+		String[] choices = getModuleList(dutyClass);
+		JLabel label = new JLabel (message);
+		return addPopUpMenu(label, choices, defaultChoice);
+	}
+	/*.................................................................................................................*/
+	public String[] getModuleList(Class dutyClass) {
+		StringArray stringArray = new StringArray(5);
+		if (dutyClass!=null) {  //module dutyClass specified; need to create list of modules to choose
+			MesquiteModuleInfo mbi=null;
+			int count = 0;
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, mbi))!=null) {
+				if (mbi.getUserChooseable()) {
+					stringArray.addAndFillNextUnassigned(mbi.getName());
+				}
+			}
+			return stringArray.getFilledStrings();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getModuleClassName(Class dutyClass, int index) {
+		if (dutyClass!=null) { 
+			MesquiteModuleInfo mbi=null;
+			int count = -1;
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, mbi))!=null) {
+				if (mbi.getUserChooseable()) {
+					if (count==index)
+						return mbi.getClassName();
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public int getModuleClassNumber(Class dutyClass, String className) {
+		if (dutyClass!=null) { 
+			MesquiteModuleInfo mbi=null;
+			int count = -1;
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(dutyClass, mbi))!=null) {
+				if (mbi.getUserChooseable()) {
+					if (className.equalsIgnoreCase(mbi.getClassName()))
+						return count;
+				}
+			}
+		}
+		return 0;
+	}
+
+	/*.................................................................................................................*/
+	public void addBlankLine () {
+		Panel newPanel = addNewDialogPanel();
+	}
+	/*.................................................................................................................*/
+	public void addHorizontalLine (int thickness) {
+		addHorizontalLine(thickness,0);
+	}
+	/*.................................................................................................................*/
+	public void addHorizontalLine (int thickness, int startx) {
+		forceNewPanel();
+		Panel newPanel = addNewDialogPanel();
+		newPanel.add(new HorizontalLine(this, thickness,startx));
+	}
+	/*.................................................................................................................*/
+	public void addNormalHorizontalLine (int thickness) {
+		Panel newPanel = addNewDialogPanel();
+		//addABlackImage(newPanel,thickness);
+		//newPanel.setLayout(gridBag);
+		newPanel.add(new HorizontalLine(this, thickness));
+	}
+	/*.................................................................................................................*
+	public ImagePanel addABlackImage (Panel panel,int height) {
+		Image image = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "blackPixel.gif");
+		ImagePanel imagePanel = new ImagePanel(image);
+		imagePanel.setForcedImageHeight(height);
+		imagePanel.setForcedImageWidth(20);
+
+		if (panel==null) {
+			if (lastPanel!=null) 
+				lastPanel.add(imagePanel);
+		}
+		else 	
+			panel.add(imagePanel);
+		return imagePanel;
+	}
+	/*.................................................................................................................*/
+	public Checkbox addCheckBox (String s, boolean value) {
+		Panel newPanel = addNewDialogPanel();
+		Checkbox checkbox =new Checkbox(s, null, value);
+		newPanel.add(checkbox);
+		return checkbox;
+	}
+	/*.................................................................................................................*/
+	public void addGraphicsPanel (DialogGraphicsPanel panel) {
+		Panel newPanel = addNewDialogPanel();
+		newPanel.add(panel);
+	}
+
+	/*.................................................................................................................*/
+	public List addList (Object names, MesquiteInteger selected, String message) {
+		return addList(names, selected, message, 4);
+	}
+	/*.................................................................................................................*/
+	public List addList (Object names, MesquiteInteger selected, String message, int numLines) {
+		if (message!=null)
+			constraints.fill=GridBagConstraints.NONE;
+		Panel newPanel = addNewDialogPanel();
+		if (message!=null) {
+			newPanel.add(new Label(message));
+		}
+		List list = new List(numLines,false);
+
+		newPanel.setLayout(new GridLayout(1,1));
+		newPanel.add(list);
+		focalComponent = list;
+		constraints.fill=GridBagConstraints.BOTH;
+
+		String[] strings = null;
+		Listable[] listables = null;
+		if (names != null)
+			if (names instanceof Listable[])
+				listables = (Listable[])names;
+			else if (names instanceof ListableVector)
+				listables = ((ListableVector)names).getListables();
+			else if (names instanceof String[])
+				strings = (String[])names;
+		list.setBackground(Color.white);
+		if (listables!=null){
+			for (int i=0; i<listables.length; i++) {
+				if (listables[i]!=null){
+					if (listables[i] instanceof SpecialListName && ((SpecialListName)listables[i]).getListName()!=null)
+						list.add(StringUtil.truncateIfLonger(((SpecialListName)listables[i]).getListName(), maxLengthInList), -1);
+					else if (listables[i].getName()!=null)
+						list.add(StringUtil.truncateIfLonger(listables[i].getName(), maxLengthInList), -1);
+				}
+			}
+			if (selected!=null && selected.getValue()>=0 && selected.getValue()<listables.length)
+				list.select(selected.getValue());
+		}
+		else if (strings!=null){
+			for (int i=0; i<strings.length; i++)
+				if (strings[i]!=null)
+					list.add(StringUtil.truncateIfLonger(strings[i], maxLengthInList), -1);
+			if (selected!=null && selected.getValue()>=0 && selected.getValue()<strings.length)
+				list.select(selected.getValue());
+		}
+		return list;
+	}
+	/*.................................................................................................................*/
+	public MesquitePasswordField addPasswordField (String message, String initialString, int fieldLength) {
+		if (message!=null)
+			constraints.fill=GridBagConstraints.NONE;
+		Panel newPanel = addNewDialogPanel();
+		Label fieldLabel = null;
+		if (message!=null) {
+			newPanel.add(fieldLabel = new Label(message));
+		}
+		MesquitePasswordField textField;
+		if (initialString == null)
+			initialString = "";
+		if (fieldLength>=1) {
+			textField =new MesquitePasswordField(initialString,fieldLength);
+		}
+		else {
+			newPanel.setLayout(new GridLayout(1,1));
+			textField =new MesquitePasswordField(initialString);
+			textField.setSize(new Dimension(dialogWidth-sideBuffer*2, textField.getSize().height));
+			newPanel.setSize(textField.getSize());
+		}
+		textField.setBackground(Color.white);
+		textField.setLabel(fieldLabel);
+		newPanel.add(textField);
+		focalComponent = textField;
+		textField.selectAll();
+		try {
+			if (MesquiteTrunk.getJavaVersionAsDouble() >= 1.5)
+				textField.setCaretPosition(0);
+		}
+		catch (Exception e){
+		}
+		constraints.fill=GridBagConstraints.BOTH;
+		return textField;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField addTextField (String message, String initialString, int fieldLength, boolean preserveBlanks) {
+		if (message!=null)
+			constraints.fill=GridBagConstraints.NONE;
+		Panel newPanel = addNewDialogPanel();
+		Label fieldLabel = null;
+		if (message!=null) {
+			newPanel.add(fieldLabel = new Label(message));
+		}
+		SingleLineTextField textField;
+		if (initialString == null)
+			initialString = "";
+		if (fieldLength>=1) {
+			textField =new SingleLineTextField(initialString,fieldLength, preserveBlanks);
+		}
+		else {
+			newPanel.setLayout(new GridLayout(1,1));
+			textField =new SingleLineTextField(initialString, preserveBlanks);
+			textField.setSize(new Dimension(dialogWidth-sideBuffer*2, textField.getSize().height));
+			newPanel.setSize(textField.getSize());
+		}
+		textField.setBackground(Color.white);
+		textField.setLabel(fieldLabel);
+		newPanel.add(textField);
+		focalComponent = textField;
+		textField.selectAll();
+		try {
+			if (MesquiteTrunk.getJavaVersionAsDouble() >= 1.5)
+				textField.setCaretPosition(0);
+		}
+		catch (Exception e){
+		}
+		constraints.fill=GridBagConstraints.BOTH;
+		return textField;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField addTextField (String message, String initialString, int fieldLength) {
+		return addTextField(message, initialString, fieldLength, false);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField addTextField (String initialString, int fieldLength) {
+		return addTextField(null, initialString, fieldLength, false);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField addTextField (String initialString) {
+		return addTextField(null, initialString, -1, false);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextArea addSingleLineTextArea (String initialString, int numRows) {
+		forceNewPanel();
+		if (initialString == null)
+			initialString = "";
+		Panel newPanel = addNewDialogPanel();
+		newPanel.setLayout(new GridLayout(1,1));
+		SingleLineTextArea textArea = new SingleLineTextArea(initialString,numRows,40,TextArea.SCROLLBARS_VERTICAL_ONLY, !hasDefaultButton());
+		//		Dimension d = textArea.getPreferredSize();
+		textArea.setSize(new Dimension(dialogWidth-sideBuffer*2, textArea.getSize().height));
+		textArea.setBackground(Color.white);
+		newPanel.add(textArea);
+		focalComponent = textArea;
+		return textArea;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField[] addNameFieldsRow (int numFields, String[] labels, int[] widths) {
+
+		SingleLineTextField[] textFields = new SingleLineTextField [numFields]; 
+
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+
+		if (labels!=null){
+			for (int i = 0; i<numFields && i<labels.length; i++) {
+				constraints.gridx=i+1;
+				newPanel.add(new Label(labels[i]),constraints);
+			}
+		}
+
+		constraints.gridy=2;
+		for (int i = 0; i<numFields && i<labels.length; i++) {
+			constraints.gridx=i+1;
+			if (widths!=null && i<widths.length)
+				textFields[i] = new SingleLineTextField("",widths[i]);
+			else
+				textFields[i] = new SingleLineTextField("",10);
+			newPanel.add(textFields[i],constraints);					
+		}
+
+		addNewDialogPanel(newPanel);
+		return textFields;
+	}
+
+	/*.................................................................................................................*/
+	public SingleLineTextField[][] addNameFieldsMatrix(int numFields, int numRows, String[] labels, int[] widths) {
+
+		SingleLineTextField[][] textFields = new SingleLineTextField [numFields][numRows]; 
+
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+
+		if (labels!=null){
+			for (int i = 0; i<numFields && i<labels.length; i++) {
+				constraints.gridx=i+1;
+				newPanel.add(new Label(labels[i]),constraints);
+			}
+		}
+
+		for (int j = 0; j<numRows; j++) {
+			constraints.gridy=j+2;
+			for (int i = 0; i<numFields && i<labels.length; i++) {
+				constraints.gridx=i+1;
+				if (widths!=null && i<widths.length)
+					textFields[i][j] = new SingleLineTextField("",widths[i]);
+				else
+					textFields[i][j] = new SingleLineTextField("",10);
+				newPanel.add(textFields[i][j],constraints);		
+			}
+		}
+
+		addNewDialogPanel(newPanel);
+		return textFields;
+	}
+	/*.................................................................................................................*/
+	public SimpleIntegerField[][] addIntegerFieldsMatrix(int numFields, int numRows, String[] rowLabels, String[] columnLabels, int[] widths, int[][] initialValues, int min, int max) {
+
+		SimpleIntegerField[][] textFields = new SimpleIntegerField [numFields][numRows]; 
+
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+
+		if (columnLabels!=null){
+			constraints.gridx=1;
+			if (rowLabels!=null)
+				newPanel.add(new Label(""),constraints);
+
+			for (int i = 0; i<numFields && i<columnLabels.length; i++) {
+				constraints.gridx=i+2;
+				newPanel.add(new Label(columnLabels[i]),constraints);
+			}
+		}
+
+		//	public IntegerField (ExtensibleDialog dialog, String message, int initialValue, int fieldLength, int min, int max) {
+
+		for (int j = 0; j<numRows; j++) {
+			constraints.gridy=j+2;
+			constraints.gridx=1;
+			if (rowLabels!=null)
+				if (j>=rowLabels.length || rowLabels[j]==null)
+					newPanel.add(new Label(""),constraints);
+				else
+					newPanel.add(new Label(rowLabels[j]),constraints);
+
+			for (int i = 0; i<numFields && i<columnLabels.length; i++) {
+				constraints.gridx=i+2;
+				int initValue = 1;
+				if (i<initialValues.length && j<initialValues[i].length)
+					initValue = initialValues[i][j];
+				if (widths!=null && i<widths.length)
+					textFields[i][j] = new SimpleIntegerField(initValue, widths[i],min,max);
+				else
+					textFields[i][j] = new SimpleIntegerField(initValue, 3,min,max);
+				newPanel.add(textFields[i][j],constraints);		
+			}
+		}
+
+		addNewDialogPanel(newPanel);
+		return textFields;
+	}
+
+
+	/*.................................................................................................................*/
+	public Checkbox[][] addCheckboxMatrix(int numColumns, int numRows, String[] columnLabels, String[] rowLabels) {
+
+		Checkbox[][] textFields = new Checkbox [numColumns][numRows]; 
+
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+
+		if (columnLabels!=null){
+			for (int i = 0; i<numColumns && i<columnLabels.length; i++) {
+				constraints.gridx=i+2;
+				newPanel.add(new Label(columnLabels[i]),constraints);
+			}
+		}
+
+		for (int j = 0; j<numRows; j++) {
+			constraints.gridy=j+2;
+			constraints.gridx=1;
+
+			newPanel.add(new Label(rowLabels[j]),constraints);
+			for (int i = 0; i<numColumns; i++) {
+				constraints.gridx=i+2;
+				textFields[i][j] = new Checkbox("",null, true);
+				newPanel.add(textFields[i][j],constraints);		
+			}
+		}
+
+		addNewDialogPanel(newPanel);
+		return textFields;
+	}
+
+
+
+	/*.................................................................................................................*/
+	public TextArea addTextArea (String initialString, int numRows, Font font) {
+		return addTextArea(initialString, numRows, 40, font);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextArea (String initialString, int numRows, int numColumns, Font font, int scrollbars, boolean textAreaFullDialogWidth) {
+		forceNewPanel();
+		if (initialString == null)
+			initialString = "";
+		Panel newPanel = addNewDialogPanel();
+		if (textAreaFullDialogWidth)
+			newPanel.setLayout(new GridLayout(1,1)); 
+		TextArea textArea = new TextArea(initialString,numRows,numColumns,scrollbars);
+		//textArea.setSize(new Dimension(dialogWidth-sideBuffer*2, textArea.getSize().height));
+		textArea.setBackground(Color.white);
+		if (font !=null)
+			textArea.setFont(font);
+		newPanel.add(textArea);
+		//lastTextPanel = newPanel;
+		focalComponent = textArea;
+		return textArea;
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextArea (String initialString, int numRows, int numColumns, Font font) {
+		return addTextArea(initialString, numRows, numColumns, font, TextArea.SCROLLBARS_VERTICAL_ONLY, true);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextArea (String initialString, int numRows) {
+		return addTextArea(initialString,numRows,null);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextAreaVerySmallFont (String initialString, int numRows, int numColumns, int scrollbars) {
+		return addTextArea(initialString,numRows,numColumns, defaultVerySmallFont, scrollbars,true);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextAreaSmallFont (String initialString, int numRows, int numColumns) {
+		return addTextArea(initialString,numRows,numColumns, defaultSmallFont);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextAreaSmallFontNoScroll (String initialString, int numRows, boolean textAreaFullDialogWidth) {
+		return addTextArea(initialString,numRows,40, defaultSmallFont, TextArea.SCROLLBARS_NONE, textAreaFullDialogWidth);
+	}
+	/*.................................................................................................................*/
+	public TextArea addTextAreaSmallFont (String initialString, int numRows) {
+		return addTextArea(initialString,numRows, defaultSmallFont);
+	}
+	/*.................................................................................................................*/
+	public TextArea addLargeTextLabel (String message, Font font) {
+		if (message!=null) {
+			Panel newPanel = addNewDialogPanel();
+
+			/*	        GridBagLayout panelGrid = new GridBagLayout();
+	        GridBagConstraints panelGridConstraints = new GridBagConstraints();
+	        panelGridConstraints.gridx=0;
+	       	panelGridConstraints.gridy = 0;
+	        panelGridConstraints.gridwidth=1;
+	        panelGridConstraints.gridheight=1;
+	        panelGridConstraints.fill=GridBagConstraints.HORIZONTAL;
+	        panelGridConstraints.anchor=GridBagConstraints.CENTER;
+	       	panelGridConstraints.weightx = 1.0;
+
+
+			newPanel.setLayout(panelGrid);
+
+			 */
+			newPanel.setLayout(new GridLayout(1,1));
+			pack();
+			Dimension d = getPreferredSize();
+			dialogWidth = d.width;
+			if (dialogWidth<minDialogWidthWithCanvas) //this had been hardcoded at 240
+				dialogWidth = minDialogWidthWithCanvas;
+			else if (dialogWidth> maxDialogWidthWithCanvas) 
+				dialogWidth =maxDialogWidthWithCanvas;
+			if (font==null)
+				font = getFont();
+			MesquiteTextCanvas textCanvas = MesquiteTextCanvas.getTextCanvas(dialogWidth-sideBuffer*2, font, message);
+			newPanel.add(textCanvas);
+			return textCanvas;
+			//newPanel.setSize(textCanvas.getPreferredSize());
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public TextArea addLargeTextLabel (String message) {
+		return addLargeTextLabel(message, null);
+	}
+	/*.................................................................................................................*/
+	public LongField addLongField (String message, long initialValue, int fieldLength) {
+		return new LongField(this,message,initialValue, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public IntegerField addIntegerField (String message, int initialValue, int fieldLength, int min, int max) {
+		return new IntegerField(this,message,initialValue, fieldLength, min, max);
+	}
+	/*.................................................................................................................*/
+	public IntegerField addIntegerField (String message, int initialValue, int fieldLength) {
+		return new IntegerField(this,message,initialValue, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public IntegerField addIntegerField (String message, int fieldLength) {
+		return new IntegerField(this,message, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public DoubleField addDoubleField (String message, double initialValue, int fieldLength, double min, double max) {
+		return new DoubleField(this,message,initialValue, fieldLength, min, max);
+	}
+	/*.................................................................................................................*/
+	public DoubleField addDoubleField (String message, double initialValue, int fieldLength) {
+		return new DoubleField(this,message,initialValue, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public DoubleField addDoubleField (String message, int fieldLength) {
+		return new DoubleField(this,message, fieldLength);
+	}
+	public JEditorPane addHTMLPanel(String message, int w, int h, MesquiteCommand linkTouchedCommand){
+		JEditorPane tA= new MesqJEditorPane("text/html","<html></html>");
+		tA.setBackground(Color.white);
+		tA.setForeground(Color.black);
+		tA.setVisible(true);
+		if (message == null)
+			message = "";
+		tA.setText(message);
+		tA.setEditable(false);
+		ConstrJEP scrollPane;
+		scrollPane = new  ConstrJEP(w, h, linkTouchedCommand); 
+		tA.addHyperlinkListener(scrollPane);
+		scrollPane.getViewport().add( tA,  BorderLayout.CENTER ); 
+
+		addToDialog(scrollPane);
+
+		return tA;
+	}
+	class ConstrJEP extends JScrollPane implements javax.swing.event.HyperlinkListener {
+		int w, h;
+		MesquiteCommand linkTouchedCommand;
+		ConstrJEP(int w, int h, MesquiteCommand linkTouchedCommand){
+			this.w = w; this.h = h; this.linkTouchedCommand = linkTouchedCommand;
+		}
+		public Dimension getPreferredSize(){
+			return new Dimension(w, h);
+		}
+		public Dimension getMinimumSize(){
+			return new Dimension(w, h);
+		}
+		public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent e) {
+			if (e.getEventType() == javax.swing.event.HyperlinkEvent.EventType.ACTIVATED) {
+				String link = e.getDescription();
+				if (link != null && StringUtil.startsWithIgnoreCase(link, "http"))
+					MesquiteTrunk.showWebPage(e.getURL().toString(), false);
+				else  if (linkTouchedCommand != null)
+					linkTouchedCommand.doItNewThread(ParseUtil.tokenize(e.getDescription()), null);
+
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	public RadioButtons addRadioButtons (String[] labels, int defaultBox) {
+		return new RadioButtons(this,labels, defaultBox);
+	}
+	/*.................................................................................................................*/
+	public int getDialogWidth() {
+		return dialogWidth;
+	}
+	/*.................................................................................................................*/
+	public void setDialogWidth(int width) {
+		dialogWidth = width;
+	}
+	/*.................................................................................................................*/
+	public void buttonHit(String buttonLabel, Button button) {
+		if (buttonPressed!=null) {
+			buttonPressed.setValue(getButtonNumber(buttonLabel));
+
+		}
+		if (textEdgeCompensationDetector!= null){
+			Dimension d = textEdgeCompensationDetector.getSize();
+			Graphics g = getGraphics();
+			FontMetrics fm = g.getFontMetrics(g.getFont());
+			g.dispose();
+			int sw = fm.stringWidth(" ");
+			int ma = fm.getMaxAscent();
+			int md = fm.getMaxDescent();
+			MesquiteModule.textEdgeCompensationHeight = d.height-ma-md;
+			MesquiteModule.textEdgeCompensationWidth = d.width-sw;
+		}
+	}
+	/*.................................................................................................................*/
+	/* Override this to provide a check on whether the dialog box should be dismissed or not in response to hitting OK. 
+	 */
+	public boolean dialogValuesAcceptable () {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/* Override this to change the button that will be affected by the dialogValuesAcceptable check
+	 */
+	public int checkValuesAcceptableButton () {
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/* Override this to change the message that will be presented if the dialogValuesAcceptable check fails
+	 */
+	public void dialogValuesNotAcceptableWarning () {
+		MesquiteMessage.notifyUser("Values unacceptable.");
+	}
+	/*.................................................................................................................*/
+	public void checkForButtonHit(MouseEvent e){
+		if (e.getComponent() instanceof Button) {
+			if (e.getComponent().getBounds().contains(e.getComponent().getBounds().x+e.getX(),e.getComponent().getBounds().y+e.getY())) {
+				String label = ((Button)e.getComponent()).getLabel();
+				if (getButtonNumber(label)>=0) {
+					if ((getButtonNumber(label)==checkValuesAcceptableButton()) && !dialogValuesAcceptable())
+						dialogValuesNotAcceptableWarning();
+					else {
+						buttonHit(label, (Button)e.getComponent());
+						if (autoDispose)
+							dispose();
+					}
+				}
+				else 
+					buttonHit(label, (Button)e.getComponent());  //this added 1. 12 because buttons other than primary ones were being ignored
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	/* David: this overridden here because dlog was getting disposed for any button, even if not primary.  Might be 
+	good to store Buttons directly and not just strings; that way to know easily if button hit was button desired */
+	public void mouseReleased(MouseEvent e){
+		checkForButtonHit(e);
+	}
+	/*.................................................................................................................*/
+	public void mousePressed(MouseEvent e){
+		if (MesquiteTrunk.isMacOSXYosemite() && MesquiteTrunk.isJavaVersionLessThan(1.7))  // workaround because of bug in Yosemite Java 1.6
+			checkForButtonHit(e);
+	}
+
+	public void selectButton(String label){ //for use by scripting & console
+		buttonHit(label, null);
+		if (autoDispose)
+			dispose();
+	}
+	/*.................................................................................................................*/
+	public static int query(MesquiteWindow parent, String title) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog extensibleDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		extensibleDialog.completeAndShowDialog();
+		extensibleDialog.dispose();
+		return buttonPressed.getValue();
+	}
+	/*.................................................................................................................*/
+	public void resetButtonPressed() {
+		buttonPressed.setValue(1);
+	}
+	/*.................................................................................................................*/
+	public int query() {
+		return buttonPressed.getValue();
+	}
+
+	/*.................................................................................................................*/
+	public void windowOpened(WindowEvent e){ }
+	/*.................................................................................................................*/
+	public void windowClosing(WindowEvent e){
+		if (getButtonNumber(defaultCancelLabel)>=0) {
+			buttonHit(defaultCancelLabel,null);
+			dispose();
+		}
+		else if (getButtonNumber("Done")>=0) {
+			buttonHit("Done",null);
+			dispose();
+		}
+		else if (numButtons==1) {
+			buttonPressed.setValue(0);
+			dispose();
+		}
+	} 	
+	/*.................................................................................................................*/
+	public void windowClosed(WindowEvent e){}
+	/*.................................................................................................................*/
+	public void windowIconified(WindowEvent e){}
+	/*.................................................................................................................*/
+	public void windowDeiconified(WindowEvent e){}
+	/*.................................................................................................................*/
+	public void windowActivated(WindowEvent e){
+	}
+	/*.................................................................................................................*/
+	public void windowDeactivated(WindowEvent e){}
+	/*.................................................................................................................*/
+	/** This displays the help note.  If you override this, make sure you call super.actionPerformed(e) at the end of your method so that the help system still works */
+	public  void actionPerformed(ActionEvent e) {
+		if   ("?".equals(e.getActionCommand())) {
+			MesquiteTrunk.mesquiteTrunk.alertHTML(getHelpString(),"Mesquite Help", "NOTE");
+			toFront();
+		}
+
+		//		else
+		//		super.actionPerformed(e);
+	}
+	/*.................................................................................................................*/
+	public void mouseOnImage(String imageName) {
+		if   ("?".equals(imageName)) {
+			MesquiteTrunk.mesquiteTrunk.alertHTML(getHelpString(),"Mesquite Help", "NOTE");
+			toFront();
+		}
+		else if (imageName =="manual")
+			showManual();
+	}
+	/*.................................................................................................................*/
+	/** This should be overridden to process double-click events, if you have added this as a DoubleClickListener to some component */
+	public void doubleClicked(Component c){
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/ExtensibleExplDialog.java b/Source/mesquite/lib/ExtensibleExplDialog.java
new file mode 100644
index 0000000..e94c560
--- /dev/null
+++ b/Source/mesquite/lib/ExtensibleExplDialog.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+/** An extensible dialog box with an explanation.  */
+public class ExtensibleExplDialog extends ExtensibleDialog {
+	TextArea explanationArea;
+	Explainable explainable;
+	/*.................................................................................................................*/
+	public ExtensibleExplDialog (MesquiteWindow parent, String title, MesquiteInteger buttonPressed) {
+		super(parent, title, buttonPressed);
+	}
+	/*.................................................................................................................*/
+	public ExtensibleExplDialog (MesquiteWindow parent, String title) {
+		super(parent, title);
+	}
+	public void setExplainable(Explainable e){
+		this.explainable = e;
+		if (explanationArea!=null && explainable!=null) {
+			explanationArea.setText(explainable.getExplanation());
+		}
+	}
+	/*.................................................................................................................*/
+	/**Can be overrided to provide extra panels above button row*/
+	public void addAuxiliaryDefaultPanels(){
+		explanationArea = addTextAreaSmallFont("", 6);
+		explanationArea.setEditable(false);
+		if (explainable!=null) {
+			explanationArea.setText(explainable.getExplanation());
+			explanationArea.setBackground(explanationArea.getParent().getBackground());
+		}
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/ExtensibleListDialog.java b/Source/mesquite/lib/ExtensibleListDialog.java
new file mode 100644
index 0000000..ba35092
--- /dev/null
+++ b/Source/mesquite/lib/ExtensibleListDialog.java
@@ -0,0 +1,378 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*  To Do:
+	- double click on list, brings up Edit
+	
+*/
+
+/*===============================================*/
+/** An extensible dialog box containing a list with standard buttons.  */
+public abstract class ExtensibleListDialog extends ExtensibleDialog implements ItemListener {
+	DoubleClickList list = null;
+	Button editButton;
+	Button newButton;
+	Button renameButton;
+	Button deleteButton;
+	Button duplicateButton;
+	Object names;
+	ListableVector listableVector;
+	protected Listable currentElement;
+	protected int currentItem=0;
+	String blankName = "Untitled";
+	String message;
+	boolean namesMustBeUnique = true;
+	boolean allowMultipleSelections = false;
+	Panel mainPanel;
+	GridBagConstraints gridConstraints;
+
+	/*.................................................................................................................*/
+	public ExtensibleListDialog (MesquiteWindow parent, String title, String message, MesquiteInteger buttonPressed, ListableVector listableVector) {
+		super(parent, title, buttonPressed);
+		this.listableVector = listableVector;
+		this.message = message;
+		addListAndButtons();
+	}
+	/*.................................................................................................................*/
+	public ExtensibleListDialog (MesquiteWindow parent, String title, String message, ListableVector listableVector) {
+		super(parent,title);
+		this.listableVector = listableVector;
+		this.message = message;
+		addListAndButtons();
+	}
+	/*.................................................................................................................*/
+	public void addListAndButtons(){
+		addLabel(message);
+
+		GridBagConstraints c = getGridBagConstraints();
+		c.fill=GridBagConstraints.BOTH;
+		c.weightx=1;
+		c.insets=new Insets(0,8,0,8);
+		mainPanel = addNewDialogPanel(c);
+		GridBagLayout gridBackButtons = new GridBagLayout();
+		gridConstraints = new GridBagConstraints();
+		gridConstraints.gridwidth=1;
+		gridConstraints.gridheight=GridBagConstraints.REMAINDER;
+		gridConstraints.fill=GridBagConstraints.BOTH;
+		gridConstraints.anchor = GridBagConstraints.CENTER;	        
+		mainPanel.setLayout(gridBackButtons);
+		gridBackButtons.setConstraints(mainPanel,gridConstraints);
+
+		gridConstraints.gridy = 1;
+		gridConstraints.gridx=1;
+		gridConstraints.ipadx = 2;
+		gridConstraints.weightx=2;
+		gridConstraints.weighty=1;
+		MesquiteInteger selected = new MesquiteInteger(0);
+		list = createListenedList(listableVector.getElementArray(),selected,8,this,this, getAllowMultipleSelections());  //getAllowMultipleSelections() put here because setMultipleMode not working
+
+		mainPanel.add(list,gridConstraints);
+		setAllowMultipleSelections(getAllowMultipleSelections());
+
+		gridConstraints.gridy = 1;
+		gridConstraints.gridx=2;
+		addAnEmptyImage(mainPanel);
+
+		gridConstraints.weightx=0;
+		gridConstraints.weighty=1;
+		gridConstraints.gridheight=1;
+		gridConstraints.gridx=3;
+		gridConstraints.gridy = 0;
+		gridConstraints.ipady = 4;
+		gridConstraints.fill=GridBagConstraints.NONE;
+		newButton = addNewButtonBesideList("New...");
+		editButton = addNewButtonBesideList("Edit...");
+		renameButton = addNewButtonBesideList("Rename...");
+		duplicateButton = addNewButtonBesideList("Duplicate");
+		deleteButton = addNewButtonBesideList("Delete...");
+
+		addAdditionalButtonsBesideList();
+
+		gridConstraints.gridy ++;
+		mainPanel.add(new Label(" "), gridConstraints);  // just to fill up space
+
+		resetCurrent();
+
+		if (!allNamesUnique()) {
+			AlertDialog.notice(MesquiteModule.mesquiteTrunk.containerOfModule(), "Alert", "Two or more " + pluralObjectName() + " share the same name.");
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean allNamesUnique() {
+		if (listableVector==null)
+			return true;
+		else
+			return listableVector.allNamesUnique();
+	}
+/*.................................................................................................................*/
+/** override this to to add new buttons beside list; use addNewButtonBesideList to add them */
+	public void addAdditionalButtonsBesideList() {   }
+/*.................................................................................................................*/
+	public Button addNewButtonBesideList(String s) {  
+	     	gridConstraints.gridy ++;
+		Button button = addAButton(s, mainPanel, gridConstraints);
+		button.addActionListener(this);
+		return button;
+	}
+	/*.................................................................................................................*/
+	public List getList(){
+		return list;
+	}
+/*.................................................................................................................*/
+	public void setNamesMustBeUnique(boolean unique) {
+		namesMustBeUnique = unique;
+	}
+/*.................................................................................................................*/
+	public boolean getNamesMustBeUnique() {
+		return namesMustBeUnique;
+	}
+/*.................................................................................................................*/
+	public void setAllowMultipleSelections(boolean multipleSelections) {   // NOTE: this is not working yet!!!!
+		allowMultipleSelections = multipleSelections;
+		if (list!=null)
+			list.setMultipleMode(multipleSelections);
+	}
+/*.................................................................................................................*/
+	public boolean getAllowMultipleSelections() {
+		return allowMultipleSelections;
+	}
+/*.................................................................................................................*/
+	public void setEditButtonLabel(String s) {
+		editButton.setLabel(s);
+	}
+/*.................................................................................................................*/
+	public String getEditButtonLabel() {
+		return editButton.getLabel();
+	}
+/*.................................................................................................................*/
+	public void setEditButtonEnabled(boolean enabled) {
+		editButton.setEnabled(enabled);
+	}
+/*.................................................................................................................*/
+	public void setRenameButtonEnabled(boolean enabled) {
+		renameButton.setEnabled(enabled);
+	}
+/*.................................................................................................................*/
+	public void setDeleteButtonEnabled(boolean enabled) {
+		deleteButton.setEnabled(enabled);
+	}
+/*.................................................................................................................*/
+	public void setDuplicateButtonEnabled(boolean enabled) {
+		duplicateButton.setEnabled(enabled);
+	}
+/*.................................................................................................................*/
+	public void enableButtons(){
+		setEditButtonEnabled(true);
+		setRenameButtonEnabled(true);
+		setDeleteButtonEnabled(true);
+		setDuplicateButtonEnabled(true);
+	}
+/*.................................................................................................................*/
+	public void disableButtons(){
+		setEditButtonEnabled(false);
+		setRenameButtonEnabled(false);
+		setDeleteButtonEnabled(false);
+		setDuplicateButtonEnabled(false);
+	}
+/*.................................................................................................................*/
+	public int getLastItem(){
+		return list.getItemCount()-1;
+	}
+/*.................................................................................................................*/
+	void resizeDialog() {
+		list.invalidate();
+		list.doLayout();
+		invalidate();
+		validate();
+		prepareDialogHideFirst();
+	}
+/*.................................................................................................................*/
+	public void resetCurrent(){
+		if (listableVector.size()>0) {
+			currentElement = listableVector.elementAt(0);
+			enableButtons();
+			newListElementSelected();
+		}
+		else {
+			currentElement = null; 
+			disableButtons();
+		}
+	}
+/*.................................................................................................................*/
+  	private void setElement(int item){
+  		if (item >=0 && item < listableVector.size()){
+  			currentElement = listableVector.elementAt(item);
+  			if (currentElement==null)
+  				return;
+			currentItem=item;
+  			list.select(item);
+			enableButtons();
+			newListElementSelected();
+			return;
+		}
+  	}
+/*.................................................................................................................*/
+/** Can be overridden if needed */
+  	public void newListElementSelected(){
+  	}
+/*.................................................................................................................*/
+	public String untitledElementName(){
+		return "untitled";
+	}
+/*.................................................................................................................*/
+/** this is the name of the class of objects */
+	public abstract String objectName();
+/*.................................................................................................................*/
+/** this is the name of the class of objects */
+	public abstract String pluralObjectName();
+/*.................................................................................................................*/
+	public abstract Listable createNewElement(String name, MesquiteBoolean success);
+/*.................................................................................................................*/
+	public void addNewElement(Listable obj, String s) {
+		listableVector.addElement(obj, false);
+		list.add(s);
+		resizeDialog();
+		setElement(listableVector.indexOf(obj));
+	}
+/*.................................................................................................................*/
+	protected void newElement(String s){
+		MesquiteBoolean success = new MesquiteBoolean (false);
+		Listable obj = createNewElement(s, success);
+		 
+		if (success.getValue())
+			addNewElement(obj, s);
+	}
+/*.................................................................................................................*/
+	private void newElement(){
+		MesquiteString io = new MesquiteString(untitledElementName());
+		if  (QueryDialogs.queryShortString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Name of New " + objectName(),  "Name of New " + objectName(), io)) {
+
+			if (namesMustBeUnique && listableVector.nameAlreadyInList(io.getValue())) {
+				MesquiteTrunk.mesquiteTrunk.alert("This name is already used by another " + objectName() + "; please pick a unique name.");
+				return;
+			}
+			newElement(io.getValue());
+		}
+	}
+/*.................................................................................................................*/
+	public void editNumberedElement(int item){	
+		if (getEditable(item))
+			editElement(item);
+		else if (getViewable(item))
+			viewElement(item);
+	}
+/*.................................................................................................................*/
+	public abstract boolean getEditable(int item);
+/*.................................................................................................................*/
+	public abstract void editElement(int item);
+/*.................................................................................................................*/
+	public boolean getViewable(int item){
+		return true;
+	}
+/*.................................................................................................................*/
+	public void viewElement(int item){
+	}
+/*.................................................................................................................*/
+/**  This method should return an object that is a duplicate of currentElement  */
+	public abstract Listable duplicateElement(String name);
+/*.................................................................................................................*/
+	public abstract void renameElement(int item, Listable element, String newName);
+/*.................................................................................................................*/
+	protected void renameCurrentElement(boolean forceRenameIfNotUnique){
+		if (currentElement==null)
+			return;
+
+		MesquiteString io = new MesquiteString(((Listable)currentElement).getName());
+		if  (QueryDialogs.queryShortString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Name of " + objectName(),  "Name of " + objectName(), io)) {
+
+			int currentItem = list.getSelectedIndex();
+			if (namesMustBeUnique && listableVector.nameAlreadyInList(io.getValue(),currentItem)) {
+				MesquiteTrunk.mesquiteTrunk.alert("This name is already used by another " + objectName() + "; please pick a unique name.");
+				if (forceRenameIfNotUnique)
+					renameCurrentElement(true);
+				return;
+			}
+
+			//MesquiteString ms = new MesquiteString("");
+			//ms.setName(io.getValue());
+			
+			renameElement(currentItem, currentElement, io.getValue());
+			//list.remove(currentItem);
+			list.replaceItem(io.getValue(),currentItem);
+			resizeDialog();
+			setElement(currentItem);
+		}
+	}
+/*.................................................................................................................*/
+	public abstract void deleteElement(int item, int newSelectedItem);
+/*.................................................................................................................*/
+	private void deleteCurrentElement(){
+		if (currentElement==null)
+			return;
+		if (AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Delete", "Are you sure you want to delete the "+objectName()+"?", "Delete", "Cancel", 2)){
+			int item= list.getSelectedIndex();
+			int newSelectedItem=item-1;
+			if (newSelectedItem<0)
+				newSelectedItem=0;
+			list.remove(item);
+			deleteElement(item, newSelectedItem);
+			resetCurrent();
+			resizeDialog();
+			setElement(newSelectedItem);
+		}
+	}
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == list){
+	  		if (list.getSelectedIndex()>=0) {
+	  			setElement(list.getSelectedIndex());
+	  		}
+  		}
+  	}
+/*.................................................................................................................*/
+	public void doubleClicked(Component c){
+	  	if (c==list) {
+	  		currentItem=list.getSelectedIndex();
+	  		editNumberedElement(list.getSelectedIndex());
+	  	}
+	}
+/*.................................................................................................................*/
+/**  If you override this to add more buttons, make sure you call super.actonPerformed()  */
+	public void actionPerformed(ActionEvent e){
+		currentItem =list.getSelectedIndex();
+		if (getEditButtonLabel().equals(e.getActionCommand()))
+			editNumberedElement(list.getSelectedIndex());
+		else if ("New...".equals(e.getActionCommand()))
+			newElement();
+		else if ("Rename...".equals(e.getActionCommand())) 
+			renameCurrentElement(false);
+		else if ("Delete...".equals(e.getActionCommand()))
+			deleteCurrentElement();
+		else if ("Duplicate".equals(e.getActionCommand())) {
+			String name = listableVector.getUniqueName(((Listable)currentElement).getName());
+			Listable obj = duplicateElement(name);
+			addNewElement(obj,name);
+		}
+		else
+			super.actionPerformed(e);
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/FileBlock.java b/Source/mesquite/lib/FileBlock.java
new file mode 100644
index 0000000..4df2cb3
--- /dev/null
+++ b/Source/mesquite/lib/FileBlock.java
@@ -0,0 +1,182 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/* ======================================================================== */
+/**Represents a raw block of command strings from a NEXUS file.  Temporarily created in file reading.
+ */
+public class FileBlock {
+	Vector commands;
+	Vector commandComments;
+	MesquiteFile f;
+	long countRequested; //count of number of instances of target command
+	int currentCommand;
+	boolean directFromFile;
+	boolean empty = false;
+	String firstCommand = null;
+	boolean readOnce = false;
+	static int total = 0;
+	long id;
+	public FileBlock(){
+		id = total++;
+		commands = new Vector();
+		commandComments = new Vector();
+		directFromFile = false;
+		reset();
+	}
+	
+	//##########################
+	MesquiteFile file;
+	MesquiteString blockName;
+	StringBuffer fileComments;
+	StringBuffer blockComments;
+	MesquiteInteger status;
+	StringBuffer withinCommandComments;
+	StringBuffer betweenCommandComments;
+
+	public FileBlock(MesquiteFile file, MesquiteString blockName, StringBuffer fileComments, StringBuffer blockComments){
+		this();
+		this.file = file;
+		directFromFile = true;
+		this.blockName = blockName;
+		this.fileComments = fileComments;
+		this.blockComments = blockComments;
+		if (blockComments!=null)
+			blockComments.setLength(0);
+		betweenCommandComments = new StringBuffer(10);
+		status = new MesquiteInteger(0);
+		withinCommandComments = new StringBuffer(10);
+		reset();
+		
+	
+		String command = file.getNextCommand(status, withinCommandComments);
+		String wcc = withinCommandComments.toString();
+		if (!StringUtil.blank(wcc)){
+			wcc = wcc.substring(1, wcc.length()-2);
+			wcc = new Parser().getFirstToken(wcc);
+			blockComments.append(wcc);
+		}
+		if (StringUtil.blank(command))
+			empty = true;
+		if (betweenCommandComments.length()>0 && fileComments!=null) {
+			String bcc = betweenCommandComments.toString();
+			if (ParseUtil.darkBeginsWithIgnoreCase(bcc, "!"))
+				fileComments.append(bcc.substring(bcc.indexOf('!')+1, bcc.length())+ StringUtil.lineEnding());
+		}
+		Parser nameParser = new Parser();
+		String bName =nameParser.getTokenNumber(command.toString(), 2); //resets string!
+		blockName.setValue(bName);
+		firstCommand = command;
+	}
+	
+	public void setFile(MesquiteFile f){
+		this.f = f;
+	}
+	public MesquiteFile getFile(){
+		return f;
+	}
+	public void addCommand(String c, String comment){
+		commands.addElement(c);
+		if (comment ==null)
+			commandComments.addElement(new String(""));
+		else
+			commandComments.addElement(comment);
+	}
+	public void reset(){
+		currentCommand = 0;
+	}
+	public int getCurrentCommandNumber(){
+		return currentCommand;
+		
+	}
+	public String getNextFileCommand(MesquiteString comment){
+		if (!directFromFile)
+			return getNextFileCommandStored(comment);
+		if (empty)
+			return null;
+		if (firstCommand!=null) {
+			String q = firstCommand;
+			firstCommand = null;
+			return q;
+		}
+		withinCommandComments.setLength(0);
+		betweenCommandComments.setLength(0);
+		//##########################
+		String command = file.getNextCommand(status, withinCommandComments, true);
+		if (betweenCommandComments.length()>0 && fileComments!=null) {
+			String bcc = betweenCommandComments.toString();
+			if (ParseUtil.darkBeginsWithIgnoreCase(bcc, "!"))
+				fileComments.append(bcc.substring(bcc.indexOf('!')+1, bcc.length())+ StringUtil.lineEnding());
+		}
+		//##########################
+		currentCommand++;
+		if (StringUtil.blank(command) || status.getValue() == 2) {
+			readOnce = true;
+			return null;
+		}
+
+		return command;
+	}
+	public boolean isEmpty(){
+		if (directFromFile){
+			return empty;
+		}
+		else
+			return commands.size()==0;
+	}
+	public String getNextFileCommandStored(MesquiteString comment){
+		if (currentCommand>=0 && currentCommand< commands.size()){
+			if (comment !=null)
+				comment.setValue((String)commandComments.elementAt(currentCommand));
+			return (String)commands.elementAt(currentCommand++);
+		}
+		return null;
+	}
+	/*
+	public String getCommand(int ic, MesquiteString comment){
+		if (ic>=0 && ic< commands.size()){
+			if (comment !=null)
+				comment.setValue((String)commandComments.elementAt(ic));
+			return (String)commands.elementAt(ic);
+		}
+		return null;
+	}
+	*/
+	public int getNumCommands(){
+		if (directFromFile)
+			return MesquiteInteger.unassigned;
+		return commands.size();
+	}
+	public String toString(){
+		if (readOnce && directFromFile)
+			MesquiteMessage.warnUser("FileBlock toString() used even though directFromFile and already read: " + blockName);
+		StringBuffer sb = new StringBuffer(1000);
+		MesquiteString comment = new MesquiteString();
+		reset();
+		String command = null;
+		while ((command = getNextFileCommand(comment)) != null){
+			sb.append(command + StringUtil.lineEnding());
+		}
+		readOnce = true;
+		return sb.toString();
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/FileDirtier.java b/Source/mesquite/lib/FileDirtier.java
new file mode 100644
index 0000000..ea39883
--- /dev/null
+++ b/Source/mesquite/lib/FileDirtier.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/** An interface for objects who, if commanded, "dirty" a file in that the file is considered possibly altered,
+and thus the user should be queried before it is closed.*/
+public interface FileDirtier  {
+	public void fileDirtiedByCommand(MesquiteCommand command);
+}
+
diff --git a/Source/mesquite/lib/FileElement.java b/Source/mesquite/lib/FileElement.java
new file mode 100644
index 0000000..4d10f96
--- /dev/null
+++ b/Source/mesquite/lib/FileElement.java
@@ -0,0 +1,646 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Image;
+import java.util.Enumeration;
+import java.util.Random;
+import java.util.Vector;
+
+import mesquite.lib.duties.ElementManager;
+import mesquite.lib.duties.FileCoordinator;
+
+
+
+/* ======================================================================== */
+/** A class for file elements.  It must remember the file to which it is associated.*/
+public class FileElement extends AssociableWithSpecs implements Identifiable, Listable, Renamable, FileDirtier, HNode, Explainable, Annotatable, Doomable, Showable  {
+	/** Element was disposed (returned by close()).*/
+	public static final int OK = 0;
+	/** Element is in use (returned by close()).*/
+	public static final int IN_USE = 1;
+	/** Element is dirty (returned by close()).*/
+	public static final int DIRTY = 2;
+	
+	public static long totalCreated = 0;
+	public static long totalDisposed = 0;
+	public static long totalFinalized  = 0;
+	public static Vector classesCreated, classesFinalized, countsOfClasses, countsOfClassesDisposed; //to detect memory leaks
+	private long idNumber;
+	protected long assignedIDNumber = MesquiteLong.unassigned;
+	protected String assignedIDString = Long.toString(MesquiteLong.unassigned);
+	private String cipresIDString = null;
+	private NexusBlock nexusBlock = null;
+	private MesquiteFile file;
+	private MesquiteProject project = null;
+	private ElementManager elementManager = null;
+	protected String name = null;
+
+	/** project is closing so don't bother to notify listeners */
+	boolean projectClosing = false;
+
+	protected boolean disposed = false;
+	protected boolean doomed = false;
+	
+	protected boolean writable = true;  //should this be written to files?
+
+	public static Random randomNumberGenerator;
+	static {
+		randomNumberGenerator = new Random(System.currentTimeMillis());
+		if (MesquiteTrunk.checkMemory){
+			classesCreated = new Vector();
+			classesFinalized = new Vector();
+			countsOfClasses = new Vector();
+			countsOfClassesDisposed = new Vector();
+		}
+	}
+
+	public FileElement(int numParts) {
+		super(numParts); //for Associable
+		listeners = new Vector();
+		FileElement.totalCreated++;
+		if (MesquiteTrunk.checkMemory)
+			countCreated();
+		idNumber = FileElement.totalCreated;
+		while (!MesquiteLong.isCombinable(assignedIDNumber))
+			assignedIDNumber = Math.abs(randomNumberGenerator.nextLong());
+		assignedIDString = Long.toString(assignedIDNumber);
+		if (file != null)
+			assignedIDString += "." + file.getID();
+
+	}
+	public FileElement() {
+		super();
+		FileElement.totalCreated++;
+		if (MesquiteTrunk.checkMemory)
+			countCreated();
+		idNumber = FileElement.totalCreated;
+	}
+	public void setWritable(boolean writable){
+		this.writable = writable;
+	}
+	public boolean getWritable(){
+		return writable;
+	}
+	public String getAssignedID(){
+
+		return assignedIDString;
+	}
+	public long getAssignedIDNumber(){
+		return assignedIDNumber;
+	}
+
+	public void setAssignedIDNumber(long i){
+		assignedIDNumber = i;
+		assignedIDString = Long.toString(assignedIDNumber);  
+		if (file != null)
+			assignedIDString += "." + file.getID();
+	}
+	boolean resourcePanelIsOpen = false;
+	public boolean getResourcePanelIsOpen(){
+		return resourcePanelIsOpen;
+	}
+	public void setResourcePanelIsOpen(boolean i){
+		resourcePanelIsOpen = i;
+	}
+	/*-----------------------------------------------------------*/
+	/* the following are methods used for error checking related to threading, especially in CharacterData and Taxa */
+	private Thread modifyingThread = null;
+	public boolean checkIfSomebodyElseModifying(Thread thread){
+		if (!doomed && (getProject() != null && !getProject().isDoomed) && modifyingThread != null && thread != modifyingThread){
+			MesquiteTrunk.mesquiteTrunk.logln("Problem: two threads modifying " + getTypeName() + " \"" + getName() + "\": Previous: " + modifyingThread + " New: " + thread);
+			MesquiteTrunk.mesquiteTrunk.reportableProblemAlert("Two threads modifying " + getTypeName() + " \"" + getName() + "\"");
+			return true;
+		}
+		return false;
+	}
+	protected boolean checkThread(boolean okIfNotStandardThread){
+		Thread current = Thread.currentThread();
+		if (checkIfSomebodyElseModifying(current))
+			return false;
+		if (!MesquiteTrunk.debugMode)  //report non-standard only if in debugmode
+			return true;
+		if (!doomed && !okIfNotStandardThread && (!(current.getClass().getName().startsWith("mesquite")))){
+			MesquiteTrunk.mesquiteTrunk.logln("Problem: unexpected thread modifying " + getTypeName() + " \"" + getName() + "\": Thread: " + current);
+			MesquiteTrunk.mesquiteTrunk.reportableProblemAlert("Unexpected thread modifying " + getTypeName() + " \"" + getName() + "\"");
+		}
+		modifyingThread = current;
+		return true;
+	}
+	protected void uncheckThread(){
+		modifyingThread = null;
+	}
+	/* A serious warning (also see exceptionAlert and related in MesquiteModule).  This is to be used for core memory structures
+	 * like Taxa and CharacterData in connection to a data integrity problem.  Since these could be transient if graphics threads access the memory,
+	 * the reporting is triggered only if the problem is detected on a "substantial" thread */
+	public static void dataIntegrityReportableAlert(String s) {
+		Thread current = Thread.currentThread();
+		if ((current instanceof MesquiteThread) && !MesquiteThread.isScripting())
+			MesquiteTrunk.mesquiteTrunk.reportableProblemAlert(s);
+		else
+			MesquiteMessage.warnProgrammer(s);
+		MesquiteMessage.printStackTrace();
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	void countCreated(){
+		if (classesCreated.indexOf(getClass())<0) {
+			classesCreated.addElement(getClass());
+			countsOfClasses.addElement(new MesquiteInteger(1));
+			countsOfClassesDisposed.addElement(new MesquiteInteger(0));
+		}
+		else {
+			MesquiteInteger c = (MesquiteInteger)countsOfClasses.elementAt(classesCreated.indexOf(getClass()));
+			if (c!=null)
+				c.increment();
+		}
+	}
+	public long getID(){
+		return idNumber;
+	}
+	public String getCIPResIDString(){
+		return cipresIDString;
+	}
+	public void setCIPResIDString(String s){
+		cipresIDString = s;
+	}
+	public void stampLastModifiedAuthor(){
+		MesquiteString aut = (MesquiteString)getAttachment("lastModifiedAuthor", MesquiteString.class);
+		if (aut == null){
+			aut = new MesquiteString();
+			aut.setName("lastModifiedAuthor");
+			attach(aut);
+		}
+		aut.setValue(MesquiteModule.author.getName());
+	}
+	public String getLastModifiedAuthor(){
+		MesquiteString aut = (MesquiteString)getAttachment("lastModifiedAuthor", MesquiteString.class);
+		if (aut != null && !("Anonymous".equalsIgnoreCase(aut.getValue())))
+			return aut.getValue();
+		return null;
+	}
+	/** Returns the type of this element (e.g., "Continuous Data Matrix") */
+	public String getTypeName(){
+		return "Generic file element";
+	}
+	/** Returns name of this element */
+	public String getName(){
+		return name;
+	}
+	/** Sets the name of this element */
+	public void setName(String name){
+		this.name = name;
+
+		if (getHShow()) {
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		}
+	}
+	/** Returns the explanation (e.g., footnote with additional information) of this element */
+	public String getExplanation(){
+		return getAnnotation();
+	}
+	public String getDefaultIconFileName(){
+		return null;
+	}
+	
+	String iconFileName = getDefaultIconFileName();
+	public String getIconFileName(){
+		return iconFileName;
+	}
+	public void setIconFileName(String d){
+		iconFileName = d;
+	}
+	public void refreshInProjectPanel(){
+		if (getProject() == null)
+			MesquiteMessage.printStackTrace("null project of " + this);
+		else if (getProject().getCoordinatorModule() == null)
+			MesquiteMessage.printStackTrace("null file coord module of " + this);
+		else
+			getProject().getCoordinatorModule().refreshInProjectWindow(this);
+	}
+	public void showMe(){
+		show();
+	}
+	public MesquiteModule show(){
+		ElementManager manager = getManager();
+		
+		if (manager!=null)
+			return manager.showElement(this);
+		return null;
+	}
+	/*.................................................................................................................*
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+  	 	return super.getSnapshot(file); //here to remind to call super's version if anything added here
+  	 }
+ 	/*.................................................................................................................*/
+	/** Performs command (for Commandable interface) */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Deletes the file element", null, commandName, "deleteMe")) {
+			deleteMe(!MesquiteThread.isScripting());
+			if (!MesquiteThread.isScripting())
+				MesquiteTrunk.resetAllMenuBars();
+		}
+		else if (checker.compare(this.getClass(), "Shows the file element", null, commandName, "showMe")) {
+			return show();
+		}
+		else if (checker.compare(this.getClass(), "Renames the file element", null, commandName, "renameMe")) {
+			if (getProject() == null)
+				return null;
+			
+			String s = MesquiteString.queryString(getProject().getCoordinatorModule().containerOfModule(), "Rename " + getTypeName(), "Rename " + getTypeName() +" \"" + getName() + "\"", getName());
+			if (s!=null) {
+				setName(s);
+				notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+				MesquiteWindow.resetAllTitles();
+				ElementManager manager = getManager();
+
+				if (manager!=null && manager instanceof MesquiteModule)
+					((MesquiteModule)manager).resetAllMenuBars();
+				else
+					MesquiteTrunk.mesquiteTrunk.resetAllMenuBars();
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Edits the comment for this file element", null, commandName, "editComment")) {
+			String s = MesquiteString.queryString(getProject().getCoordinatorModule().containerOfModule(), "Edit comment", "Edit comment for " + getTypeName() +" \"" + getName() + "\"", getAnnotation(), 6);
+			if (s!=null) {
+				setAnnotation(s, true);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+
+		return null;
+	}
+	public void deleteMe(boolean queryUser){
+		MesquiteProject tempProjRef = getProject();
+		MesquiteWindow container = MesquiteTrunk.mesquiteTrunk.containerOfModule();
+		if (tempProjRef != null){
+			tempProjRef.incrementProjectWindowSuppression();
+			if (tempProjRef.getCoordinatorModule() != null)
+				container = tempProjRef.getCoordinatorModule().containerOfModule();
+	}
+		ElementManager manager = getManager();
+		if (manager!=null) {
+			if (!queryUser || AlertDialog.query(container, "Delete?", "Are you sure you want to delete " + getTypeName() +" \"" + getName() + "\"?", "Yes", "Cancel")){
+				manager.deleteElement(this);
+				dispose(); //needs to remove from place (e.g., specs set connected to data; tree in tree vector; tree vector or data matrix in project/file
+				if (tempProjRef != null)
+					tempProjRef.refreshProjectWindow();
+			}
+		}
+
+		if (tempProjRef != null)
+			tempProjRef.decrementProjectWindowSuppression();
+	}
+	/*.................................................................................................................*/
+	/** Adds the element to the given file and project, and assigns it the given manager.  Also takes care of 
+ 	notifying the manager that it has been added using elementAdded(). */
+	public NexusBlock addToFile(MesquiteFile f, MesquiteProject proj, ElementManager manager){
+
+		//check that file belongs to project
+		elementManager = manager;  //IF MANAGER NULL then find one
+
+		if (proj == null && f == null) {
+			MesquiteMessage.warnProgrammer("WARNING: addToFile called with null file and project");
+			return null;
+		}
+		else if ((proj != null && f != null && f.getProject()!=proj)) {
+			MesquiteMessage.warnProgrammer("WARNING: addToFile called with file (" + f.getName()+ ") not belonging to project (" + proj.getName() + ")");
+			return null;
+		}
+		this.file=f; //IF FILE NULL THEN USE home of proj
+		if (file==null)
+			file = proj.getHomeFile();
+		assignedIDString = Long.toString(assignedIDNumber);
+		if (file != null)
+			assignedIDString += "." + file.getID();
+		project = proj;  //if proj null then use proj of file
+		if (project == null)
+			project =file.getProject();
+		if (elementManager==null){//IF MANAGER NULL then find one
+			elementManager = project.getCoordinatorModule().findElementManager(getClass());
+			/*
+			if (elementManager==null)
+				MesquiteMessage.warnProgrammer("Element manager not found for " + this.getName() + " of class " + getClass());
+			 */
+		}
+		project.incrementProjectWindowSuppression();
+		project.addFileElement(this);
+		file.addFileElement(this);
+		if (elementManager!=null)
+			nexusBlock = elementManager.elementAdded(this);
+		broadCastElementAdded(project.getCoordinatorModule(), elementManager);
+		project.refreshProjectWindow();
+		project.decrementProjectWindowSuppression();
+
+		return nexusBlock;
+	}
+
+	/*.................................................................................................................*/
+	/** Broadcasts that an id has been assigned to a module.  This is used for scripting, in which a module assigns itself
+	an id string in a snapshot (e.g., a TreeContext) that an interested module can clue in to (e.g., TreeOfContext).  This
+	allows the interested module to hook up to the assigning module even if the former was script-created before the latter
+	(see interaction between BasicTreeWindow and TreeOfContext)*/
+	private void broadCastElementAdded(MesquiteModule module, ElementManager excluding){
+		if (module == null)
+			return;
+		EmployeeVector employees = module.getEmployeeVector();
+		if (employees ==null)
+			return;
+		Enumeration enumeration=employees.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			broadCastElementAdded(mb, excluding);
+			if (mb instanceof ElementManager && mb !=excluding)
+				((ElementManager)mb).elementAdded(this);
+		}
+		FileCoordinator coord = module.getFileCoordinator();
+		if (coord != null)
+			coord.elementAdded(this);
+	}
+	/*.................................................................................................................*/
+	/** Gets the associated NexusBlock of the FileElement */
+	public NexusBlock getNexusBlock(){
+		return nexusBlock;
+	}
+	/*.................................................................................................................*/
+	/** for FileDirtier interface */
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (file!=null)
+			file.setDirtiedByCommand(true);
+	}
+	
+	/*.................................................................................................................*/
+	public void logln(String s){
+		if (project != null)
+			project.getCoordinatorModule().logln(s);
+		else
+			MesquiteTrunk.mesquiteTrunk.logln(s);
+	}
+	public void alert(String s){
+		if (project != null)
+			project.getCoordinatorModule().alert(s);
+		else
+			MesquiteTrunk.mesquiteTrunk.alert(s);
+	}
+	public void discreetAlert(String s){
+		if (project != null)
+			project.getCoordinatorModule().discreetAlert(s);
+		else
+			MesquiteTrunk.mesquiteTrunk.discreetAlert(s);
+	}
+	/*.................................................................................................................*/
+	/** Gets project to which the FileElement belongs */
+	public MesquiteProject getProject(){
+		return project;
+	}
+	/*.................................................................................................................*/
+	/** Sets project to which the FileElement belongs */
+	public void setProject(MesquiteProject project){
+		this.project = project;
+	}
+	/*.................................................................................................................*/
+	/** Gets file to which the FileElement belongs */
+	public MesquiteFile getFile(){
+		return file;
+	}
+	/*.................................................................................................................*/
+	/** Sets the file to which the FileElement belongs */
+	public void setFile(MesquiteFile f, boolean resetID){
+		file = f;
+		if (nexusBlock!=null)
+			nexusBlock.setFile(f);
+		if (resetID){
+			assignedIDString = Long.toString(assignedIDNumber);
+			if (file != null)
+				assignedIDString += "." + file.getID();
+		}
+	}
+	/*.................................................................................................................*/
+	/** Gets name of the file to which the element belongs */
+	public String getFileName(){
+		if (file!=null)
+			return file.getName();
+		else
+			return "[not in file]";
+	}
+	/*.................................................................................................................*/
+	/** Sets the FileElement's managing module */
+	public void setManager(ElementManager e){
+		elementManager = e;
+	}
+	/*.................................................................................................................*/
+	/** Returns the FileElement's managing module */
+	public ElementManager getManager(){
+
+		if (elementManager==null){//IF MANAGER NULL then find one
+			if (file != null && project == null)
+				project = file.getProject();
+			if (project == null)
+				return null;
+			if (project.getCoordinatorModule()==null)
+				return null;
+			elementManager = project.getCoordinatorModule().findElementManager(getClass());
+		}
+		return elementManager;
+	}
+	public boolean isDoomed(){
+		return doomed;
+	}
+	public void doom(){
+		doomed = true;
+		Vector specsVectors = getSpecSetsVectorVector();
+  		if (specsVectors!=null){ //update size of specification sets
+	  		for (int i=0; i<specsVectors.size(); i++) {
+	  			SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(i);
+	  			SpecsSet s = sv.getCurrentSpecsSet();
+	  			if (s!=null)
+	  				s.doom();
+	  			sv.doom();
+	  		}
+  		}
+	}
+	/*-------------------------------------------------------*/
+	/** Deletes the file element. Should typically be called via close()  to make sure that the file element is not in use etc. */
+	public void dispose() {
+		/* Subrclasses: should deassign storage to help catch post-deletion use */
+		doomed = true;
+
+		/*if (projectClosing){
+			incrementNotifySuppression();
+			super.dispose();
+			return;
+		}
+		 */
+		//Notify file
+		if (file != null) 
+			file.removeFileElement(this);
+		//Notify project
+		if (project !=null) {
+			project.removeFileElement(this);
+			if (nexusBlock !=null)
+				project.removeNexusBlock(nexusBlock);
+		}
+		if (nexusBlock !=null)
+			nexusBlock.dispose();
+		//Notify manager (which could then remove from its lists, delete NEXUS blocks, etc.)
+		if (getManager()!=null) {
+			getManager().elementDisposed(this);
+			FileCoordinator coord = ((MesquiteModule)getManager()).getFileCoordinator();
+			if (coord != null)
+				coord.elementDisposed(this);
+		}
+			
+		if (!projectClosing)
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		disposed = true;
+		if (MesquiteTrunk.checkMemory && classesCreated.indexOf(getClass())>=0) {
+			MesquiteInteger c = (MesquiteInteger)countsOfClassesDisposed.elementAt(classesCreated.indexOf(getClass()));
+			if (c!=null)
+				c.increment();
+		}
+		FileElement.totalDisposed++;
+		project = null;
+		file = null;
+		super.dispose();
+	}
+	/*-------------------------------------------------------*/
+	public void finalize() throws Throwable {
+		FileElement.totalFinalized++;
+		if (MesquiteTrunk.checkMemory && classesFinalized.indexOf(getClass())<0)
+			classesFinalized.addElement(getClass());
+		/*
+		if (!disposed) {
+
+			MesquiteMessage.warnProgrammer("Error: file element finalized without being disposed; class \"" + getClass() + "\"  " + getName() + "  id "  + getID() + " getTypeName " + getTypeName());
+		}
+		 */
+		super.finalize();
+	}
+	/*-------------------------------------------------------*/
+	public boolean isDisposed(){
+		return disposed;
+	}
+	/*-------------------------------------------------------*/
+	/** NOT YET FUNCTIONING   If queryUser is true, then
+	if there is a problem with deletion the user will be queried.  Otherwise, the deletion is done or not
+	according to whether there are problems with deletion, and the method returns whether the deletion
+	was successful */
+	public int okToClose(int queryUser) {
+		/* If in use: should ask listeners if OK to delete; listener should have method okToDispose, which is passed 
+		a parameter helping the listener to know what message to display (delete? close?) in querying the user, 
+		and  whether to query the user.   okToDispose would return whether the listener accepted the deletion.
+		If a listener didn't accept the deletion, should return FileElement.IN_USE */
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+				if (!listener.okToDispose(this, queryUser))
+					return FileElement.IN_USE;
+			}
+		}
+		/* If dirty: return FileElement.DIRTY */
+		if (getDirty())
+			return FileElement.DIRTY;
+		return FileElement.OK;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public HNode[] getHDaughters(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public HNode getHMother(){
+		return null; //TODO: pass first MesquiteFile???
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public int getNumSupplements(){
+		return 0;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public String getSupplementName(int index){
+		return "";
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public void hNodeAction(Container c, int x, int y, int action){ 
+		if (action == HNode.MOUSEDOWN) {
+			ElementManager manager = getManager();
+			if (manager!=null) {
+				if (c==null)
+					return;
+				MesquitePopup popup = new MesquitePopup(c);//best to accumulate popup
+				addToBrowserPopup(popup);
+				popup.showPopup(x,y);
+			}
+		}
+		else if (action == HNode.MOUSEMOVE){
+			MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+			if (f != null && f instanceof MesquiteWindow){
+				String e = getExplanation();
+				if (e == null)
+					e = "";
+				((MesquiteWindow)f).setExplanation(e);
+				e = getAnnotation();
+				if (e == null)
+					e = "";
+				if (StringUtil.blank(e))
+					((MesquiteWindow)f).setAnnotation(e, getExplanation());
+				else
+					((MesquiteWindow)f).setAnnotation(e, "Footnote above refers to " + getTypeName() + " \"" + getName() + "\"\n" + getExplanation());
+			}
+		}
+		else if (action == HNode.MOUSEEXIT){
+			/*
+			Frame f = MesquiteTrunk.mesquiteTrunk.containerOfModule();
+			if (f != null && f instanceof MesquiteWindow){
+				((MesquiteWindow)f).setExplanation("");
+			}
+			 */
+		}
+	}
+	/* ---------------- for use with touched from HNode interface ----------------------*/
+	public void addToBrowserPopup(MesquitePopup popup){
+		popup.addItem(getTypeName() +" \"" + getName() + "\"", MesquiteTrunk.mesquiteTrunk, null);
+		popup.addItem("Show", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("showMe", this));
+		popup.addItem("Rename", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("renameMe", this));
+		popup.addItem("Edit Comment", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("editComment", this));
+		popup.addItem("Delete", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("deleteMe", this));
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public void hSupplementTouched(int index){}
+	/* ---------------- for HNode interface ----------------------*/
+	public Image getHImage(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Color getHColor(){
+		return ColorTheme.getActiveLight();
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public boolean getHShow(){
+		return false; 
+	}
+}
+
diff --git a/Source/mesquite/lib/FillableMesquiteSymbol.java b/Source/mesquite/lib/FillableMesquiteSymbol.java
new file mode 100644
index 0000000..25a76b5
--- /dev/null
+++ b/Source/mesquite/lib/FillableMesquiteSymbol.java
@@ -0,0 +1,205 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class FillableMesquiteSymbol extends MesquiteSymbol {
+	Checkbox fillBox = null;
+	protected boolean fill=true;
+	Color fillColor = Color.black;
+	Color rimColor = Color.black;
+	/**sets whether to fill the symbol or not*/
+	public void setFill(boolean fill){
+		this.fill = fill;
+	}
+	/**gets whether to fill the symbol or not*/
+	public boolean getFill(){
+		return fill;
+	}
+	/**gets the NEXUS commands to specify the options specific to this tool*/
+	public String getBasicNexusOptions(){
+		if (getFill())
+			return " FILL ";
+		else
+			return " OPEN ";
+	}
+	/*.................................................................................................................*/
+	public void  setToCloned(MesquiteSymbol cloned){
+		super.setToCloned(cloned);
+		setFill(((FillableMesquiteSymbol)cloned).getFill());
+	}
+	/*.................................................................................................................*/
+	public void addDialogElements(ExtensibleDialog dialog, boolean includeSize){
+		super.addDialogElements(dialog, includeSize);
+		fillBox = dialog.addCheckBox("filled", fill);
+	}
+	/*.................................................................................................................*/
+	public void getDialogOptions(){
+		super.getDialogOptions();
+		fill = fillBox.getState();
+	}
+	/*.................................................................................................................*/
+	public void processSubcommand(String token, Parser subcommands){
+		super.processSubcommand(token, subcommands);
+		if (token.equalsIgnoreCase("FILL"))
+			setFill(true);
+		else if (token.equalsIgnoreCase("OPEN"))
+			setFill(false);
+	}
+	/**sets fill color*/
+	public void setFillColor(Color color){
+		this.fillColor = color;
+	}
+	/**sets fill color*/
+	public void setColor(Color color){
+		this.fillColor = color;
+		this.color = color;
+	}
+	/**gets whether the symbol is drawn via a Polygon*/
+	public boolean getIsPolygon(){
+		return true;
+	}
+	/**gets the Polygon*/
+	public Polygon getPolygon(){
+		return getPolygon(0);
+	}
+	/**gets the Polygon*/
+	public Polygon getPolygon(int maxSize){
+		return null;
+	}
+	/**draws shape if non-Polygon*/
+	public void drawShape(Graphics g){
+		drawShape(g,0,false);
+	}
+	/**draws shape if non-Polygon*/
+	public void drawShape(Graphics g, int maxSize, boolean fillBlack){
+	}
+
+	/**fills shape if non-Polygon*/
+	public void fillShape(Graphics g, int maxSize){
+	}
+
+	/**inSymbols if non-Polygon*/
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y, int maxSize){
+		return false;
+	}
+	/**inSymbols if non-Polygon*/
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2, int bound){
+		return false;
+	}
+
+	/**draws the Symbol*/
+	public void drawSymbol(Graphics g, int x, int y, int maxWidth, int maxHeight, boolean fillBlack){
+		int bound = 0;
+		if (maxWidth > 0)
+			bound = maxWidth;
+		if (maxHeight>0 && maxHeight<maxWidth)
+			bound = maxHeight;
+
+		if (getIsPolygon()) {
+			Polygon poly = getPolygon(bound);
+			if (poly!=null) {
+				poly.translate(x, y);
+				if (fillBlack) {
+					g.setColor(Color.black);
+					g.fillPolygon(poly);
+				}
+				else if (getFill()) {
+					g.setColor(fillColor);
+					g.fillPolygon(poly);
+				}
+				g.setColor(rimColor);
+				g.drawPolygon(poly);
+				poly.translate(-x, -y);
+			}
+		}
+		else
+			drawShape(g, bound, fillBlack);
+	}
+
+	/**fills the Symbol*/
+	public void fillSymbol(Graphics g, int x, int y, int maxWidth, int maxHeight){
+		int bound = 0;
+		if (maxWidth > 0)
+			bound = maxWidth;
+		if (maxHeight>0 && maxHeight<maxWidth)
+			bound = maxHeight;
+
+		if (getIsPolygon()) {
+			Polygon poly = getPolygon(bound);
+			if (poly!=null) {
+				poly.translate(x, y);
+				g.fillPolygon(poly);
+				poly.translate(-x, -y);
+			}
+		}
+		else
+			fillShape(g, bound);
+	}
+
+
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y, int maxWidth, int maxHeight){
+		int bound = 0;
+		if (maxWidth > 0)
+			bound = maxWidth;
+		if (maxHeight>0 && maxHeight<maxWidth)
+			bound = maxHeight;
+
+		if (getIsPolygon()) {
+			Polygon poly = getPolygon(bound);
+			if (poly!=null) {
+				poly.translate(symbolX, symbolY);
+				boolean in = poly.contains(x,y);
+				poly.translate(-symbolX, -symbolY);
+				return in;
+			}
+		}
+		else  {
+			return inSymbol(symbolX, symbolY,x,y,bound);
+		}
+		return false;
+	}
+
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2, int maxWidth, int maxHeight){
+		if (x1==x2 && y1==y2)
+			return inSymbol(symbolX, symbolY, x1,y1,maxWidth,maxHeight);
+		int bound = 0;
+		if (maxWidth > 0)
+			bound = maxWidth;
+		if (maxHeight>0 && maxHeight<maxWidth)
+			bound = maxHeight;
+
+		if (getIsPolygon()) {
+			Polygon poly = getPolygon(bound);
+			if (poly!=null) {
+				poly.translate(symbolX, symbolY);
+				Rectangle bounds = poly.getBounds();
+				boolean in = bounds.intersects(new Rectangle(x1,y1,x2-x1,y2-y1));
+				poly.translate(-symbolX, -symbolY);
+				return in;
+			}
+		}
+		else {
+			return inRect(symbolX, symbolY,x1,y1,x2,y2,bound);
+		}
+		return false;
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/Fittable.java b/Source/mesquite/lib/Fittable.java
new file mode 100644
index 0000000..b022d5e
--- /dev/null
+++ b/Source/mesquite/lib/Fittable.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/* used for java 1.1 printing, for fit to page.  (see TreeDisplay) */
+public interface Fittable   {
+
+	public Object fit(Dimension dim);
+	public void unfit(Object o);
+}
+
+
diff --git a/Source/mesquite/lib/FunctionExplainable.java b/Source/mesquite/lib/FunctionExplainable.java
new file mode 100644
index 0000000..73d09ea
--- /dev/null
+++ b/Source/mesquite/lib/FunctionExplainable.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it can be explained in documentation*/
+public interface FunctionExplainable extends Explainable {
+ 	public String getFunctionIconPath();  //path to icon explaining function, e.g. a tool
+	public String getKeywords();  //path to icon explaining function, e.g. a tool
+	public String getURLString();  //URL explaining function
+	public boolean URLinPackageIntro();
+	public String getHTMLExplanation();
+}
+
diff --git a/Source/mesquite/lib/FunctionExplanation.java b/Source/mesquite/lib/FunctionExplanation.java
new file mode 100644
index 0000000..85d289a
--- /dev/null
+++ b/Source/mesquite/lib/FunctionExplanation.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+
+public class FunctionExplanation implements Listable, FunctionExplainable {
+	String  name;
+	String explanation;
+	String iconPath;
+	String keywords;
+	String URL =null;
+	boolean URLinPackageIntroDirectory = false;
+	public FunctionExplanation(String name, String explanation, String keywords, String iconPath, String URL, boolean URLinPackageIntroDirectory){
+		this.name = name;
+		this.explanation = explanation;
+		this.iconPath = iconPath;
+		this.keywords = keywords;
+		this.URL = URL;
+		this.URLinPackageIntroDirectory = URLinPackageIntroDirectory;
+	}
+	public FunctionExplanation(String name, String explanation, String keywords, String iconPath){
+		this.name = name;
+		this.explanation = explanation;
+		this.iconPath = iconPath;
+		this.keywords = keywords;
+	}
+	public String getName(){
+		return name;
+	}
+	public String getURLString(){
+		return URL;
+	}
+ 	/** Returns whether or not the URL for this module is a relative reference from the PackageIntro directory */
+	public boolean URLinPackageIntro(){
+		return URLinPackageIntroDirectory;
+	}
+	public String getExplanation(){
+		return explanation;
+	}
+	public String getHTMLExplanation(){
+		return explanation;
+	}
+ 	public String getFunctionIconPath(){  //path to icon explaining function, e.g. a tool
+ 		return iconPath;
+ 	}
+ 	public String getKeywords(){
+ 		return keywords;
+ 	}
+}
+
diff --git a/Source/mesquite/lib/GraphicsUtil.java b/Source/mesquite/lib/GraphicsUtil.java
new file mode 100644
index 0000000..d6c67fc
--- /dev/null
+++ b/Source/mesquite/lib/GraphicsUtil.java
@@ -0,0 +1,463 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+
+
+
+/* ======================================================================== */
+/** This class provides general graphics utilities */
+public class GraphicsUtil {
+	public static TexturePaint missingDataTexture = null;
+	/*_________________________________________________*/
+	public static void drawArrow(Graphics2D g2, int fromX, int fromY, int toX, int toY, int thickness) {
+		// based on Vincent Reig's stackoverflow answer http://stackoverflow.com/a/3094933
+		// create an AffineTransform 
+		// and a triangle centered on (0,0) and pointing downward
+		// somewhere outside Swing's paint loop
+		Stroke stroke = g2.getStroke();
+		g2.setStroke(new BasicStroke(thickness));
+		g2.drawLine(fromX, fromY, toX, toY);
+		g2.setStroke(stroke);
+		AffineTransform tx = new AffineTransform();
+		Line2D.Double line = new Line2D.Double(fromX, fromY, toX, toY);
+
+		Polygon arrowHead = new Polygon();  
+		int size = thickness*3;
+		arrowHead.addPoint( 0,size);
+		arrowHead.addPoint( -size, -size);
+		arrowHead.addPoint( size,-size);
+
+		// [...]
+		tx.setToIdentity();
+		double angle = Math.atan2(line.y2-line.y1, line.x2-line.x1);
+		tx.translate(line.x2, line.y2);
+		tx.rotate((angle-Math.PI/2d));  
+
+		Graphics2D g = (Graphics2D) g2.create();
+		g.setTransform(tx);   
+		g.fill(arrowHead);
+		g.dispose();
+	}
+	/*_________________________________________________*/
+	public static void drawCross(Graphics g, int x, int y, int size) {
+		Shape oldClip = g.getClip();
+		g.setClip(x-size, y-size, size*2, size*2);
+		g.drawLine(x, y-size, x, y+size);
+		g.drawLine(x-size, y, x+size, y);
+		g.setClip(oldClip);
+	}
+
+	/* ............................................................................................................... */
+	/** Given the coordinates of the start and end of a line, returns how far along the line (x,y) is */
+	public static double fractionAlongLine(int x, int y, int xStart, int yStart, int xEnd, int yEnd, boolean xBias, boolean yBias) {
+		if (xStart==xEnd)  //it's a vertical line or a single point
+			if (y<=yStart)
+				return 0.0;
+			else if (y>=yEnd)
+				return 1.0;
+		if (yStart==yEnd)  //it's a vertical line or a single point
+			if (x<=xStart)
+				return 0.0;
+			else if (x>=xEnd)
+				return 1.0;
+
+		if (!MesquiteInteger.contains(x, xStart, xEnd) && !MesquiteInteger.contains(y, yStart, yEnd)) {   //outside the bounds
+			if ((yEnd>=yStart && y>yEnd) || (yEnd<yStart && y<yEnd))
+				return 1.0;
+			if ((xEnd>=xStart && x>xEnd) || (xEnd<xStart && x<xEnd))
+				return 1.0;
+			else
+				return 0.0;
+		}
+
+		if (!MesquiteInteger.contains(y, yStart, yEnd)) // we are not in y range, must use x
+			return Math.abs(1.0*(x-xStart)/(xEnd-xStart));
+		if (!MesquiteInteger.contains(x, xStart, xEnd)) // we are not in x range, must use y
+			return Math.abs(1.0*(y-yStart)/(yEnd-yStart));
+		if (xBias)
+			return Math.abs(1.0*(x-xStart)/(xEnd-xStart));
+		if (yBias)
+			return Math.abs(1.0*(y-yStart)/(yEnd-yStart));
+		if (Math.abs(yEnd-yStart) > Math.abs(xEnd-xStart))  // y range larger
+			return Math.abs(1.0*(y-yStart)/(yEnd-yStart));
+		return Math.abs(1.0*(x-xStart)/(xEnd-xStart));
+	}
+
+	/* ............................................................................................................... */
+	/** Returns the width of string in the current Graphics */
+	public static int stringWidth(Graphics g, String s) {
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		if (fm==null)
+			return -1;
+		return fm.stringWidth(s);
+	}
+	/* ............................................................................................................... */
+	/** Returns the width of string in the current Graphics */
+	public static int stringHeight(Graphics g, String s) {
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		if (fm==null)
+			return -1;
+		return fm.getMaxAscent()+ fm.getMaxDescent();
+	}
+
+	/* ............................................................................................................... */
+	/** Given the coordinates of the start and end of a line, returns the value of x at the middle of the line */
+	public static int xCenterOfLine(int x1, int y1, int x2, int y2) {
+		if (x1==x2)  //it's a vertical line or a single point
+			return x1;
+		return (Math.min(x1, x2) + Math.abs(x1-x2)/2);
+	}
+	/* ............................................................................................................... */
+	/** Given the coordinates of the start and end of a line, returns the value of y at the middle of the line */
+	public static int yCenterOfLine(int x1, int y1, int x2, int y2) {
+		if (y1==y2)  //it's a horizontal line or a single point
+			return y1;
+		return (Math.min(y1, y2) + Math.abs(y1-y2)/2);
+	}
+	/* ............................................................................................................... */
+	/** Given the coordinates of the start and end of a line, returns the angle in radians of the line */
+	public static double angleOfLine(int x1, int y1, int x2, int y2) {
+		if (y1==y2)  //it's a horizontal line or a single point
+			if (x2>=x1)
+				return 0.0;
+			else
+				return Math.PI;
+		if (x1==x2)  //it's a vertical line or a single point
+			if (y2>=y1)
+				return Math.PI/2.0;
+			else
+				return -Math.PI/2.0;
+		double a = Math.PI -Math.atan(-(y2-y1)*1.0/(x2-x1));  
+		if (x2>x1)
+			a = Math.PI+a;
+		return a;
+	}
+	/* ............................................................................................................... */
+	/** draws a line starting at x,y, and going in the direction of the angle */
+	public static void drawAngledLine(Graphics g, int x, int y, double angle, int length) {
+		int endX= (int)(Math.cos(angle)*length)+x;
+		int endY =(int)(Math.sin(angle)*length)+y;
+		g.drawLine(x,y,endX, endY);
+	}
+	/*
+	 * 		Graphics2D g2 = (Graphics2D)g;
+		g2.rotate(-Math.PI/4, x, y);
+		g2.translate(x, y);
+		g2.setColor(Color.blue);
+		g2.fillRect(0, 0, 30, 40);
+		g2.translate(-x, -y);
+		g2.rotate(Math.PI/4, x, y);
+
+
+	/* ............................................................................................................... */
+	/** creates a square beginning at x,y and tilted in the direction of the angle. */
+	public static void translateAlongAngle(MesquiteInteger x, MesquiteInteger y, double angle, int length) {
+		int adj= -(int)(Math.cos(angle)*length);
+		int opp =-(int)(Math.sin(angle)*length);
+		x.add(adj);
+		y.add(opp);  
+	}
+	/* ............................................................................................................... */
+	/** creates a square beginning at x,y and tilted in the direction of the angle. */
+	public static Polygon createAngledSquare(int x, int y, double angle, int length) {
+		int adj= -(int)(Math.cos(angle)*length);
+		int opp =-(int)(Math.sin(angle)*length);
+		x -=opp/2;
+		y-=adj/2;
+
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(x,y);
+		poly.addPoint(x+opp,y+adj);
+		poly.addPoint(x+opp-adj,y+adj+opp);
+		poly.addPoint(x-adj,y+opp);
+		poly.addPoint(x,y);
+		poly.npoints=5;
+		return poly;
+
+	}
+	/* ............................................................................................................... */
+	public static void shimmerVerticalOn(Graphics g, Panel panel, int top, int bottom, int x) {
+		if (g==null && panel==null)
+			if (!MesquiteInteger.isCombinable(x))
+				return;
+		Graphics mg = g;
+		if (mg==null)
+			mg = panel.getGraphics();
+		if (mg == null)
+			return;
+//		mg.setColor(Color.black);
+		if (GraphicsUtil.useXORMode(g, false)){
+			mg.setXORMode(Color.white);
+			mg.drawLine(x, top, x, bottom);
+		}
+//		mg.drawLine(x+1, top, x+1, bottom);
+		if (g==null)
+			mg.dispose();
+	}
+	/* ............................................................................................................... */
+	public static void shimmerHorizontalOn(Graphics g, Panel panel, int left, int right, int y) {
+		if (g==null && panel==null)
+			if (!MesquiteInteger.isCombinable(y))
+				return;
+		Graphics mg = g;
+		if (mg==null)
+			mg = panel.getGraphics();
+		if (mg == null)
+			return;
+		if (GraphicsUtil.useXORMode(g, false)){
+			mg.setXORMode(Color.white);
+			mg.drawLine(left, y, right, y);
+		}
+		if (g==null)
+			mg.dispose();
+	}
+	/* -------------------------------------------------*/
+	public static boolean useXOR = true;
+	/*Bugs is os x Tiger ca. 10.4.8 can cause crashes with XORMode.  With OS X Tiger, it does not do XORMode with printing or if senstive is on */
+	public static boolean useXORMode(Graphics g, boolean sensitive){
+		if (sensitive || g instanceof PrintGraphics){
+			//if (MesquiteTrunk.isMacOSX()  && System.getProperty("os.version").indexOf("10.4")>=0)
+			//	return false;
+			return useXOR;
+		}
+		return true;
+	}
+	/* -------------------------------------------------*/
+	public static void drawXORLine (Graphics g, int xFrom, int yFrom, int xTo, int yTo, int thickness, Color color) {
+		Graphics2D g2 = (Graphics2D)g;
+		g2.setXORMode(Color.white);
+		g2.setColor(color); 
+		
+		Stroke st = g2.getStroke();
+		g2.setStroke(new BasicStroke(thickness));
+		
+		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+		g2.drawLine(xFrom,yFrom,xTo,yTo);
+		g2.setStroke(st);
+
+	}
+	/* -------------------------------------------------*/
+	public static void fillTransparentSelectionRectangle (Graphics g, int x, int y, int w, int h) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.3f);		
+		g.setColor(Color.gray);
+		g.fillRect(x,y,w, h);
+		ColorDistribution.setComposite(g, composite);		
+	}
+	/* -------------------------------------------------*/
+	public static void fillTransparentSelectionPolygon (Graphics g, Polygon poly) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.3f);		
+		g.setColor(Color.gray);
+		g.fillPolygon(poly);
+		ColorDistribution.setComposite(g, composite);		
+	}
+	/* -------------------------------------------------*/
+	public static void fillTransparentSelectionArea (Graphics2D g, Area area) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.3f);		
+		g.setColor(Color.gray);
+		g.fill(area);
+		ColorDistribution.setComposite(g, composite);		
+	}
+	/* -------------------------------------------------*/
+	public static void fillTransparentBorderedSelectionRectangle (Graphics g, int x, int y, int w, int h) {
+		if (w < 0){
+			int nx = x + w;
+			x = nx;
+			w = -w;
+		}
+		if (h < 0){
+			int ny = y + h;
+			y = ny;
+			h = -h;
+		}
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.3f);		
+		g.setColor(Color.gray);
+		g.fillRect(x,y,w,h);
+		ColorDistribution.setComposite(g, composite);		
+		g.setColor(Color.gray);
+		g.drawRect(x,y,w,h);
+	}
+	/* -------------------------------------------------*/
+	public static void fillTransparentBorderedSelectionPolygon (Graphics g, Polygon poly) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.3f);		
+		g.setColor(Color.gray);
+		g.fillPolygon(poly);
+		ColorDistribution.setComposite(g, composite);		
+		g.setColor(Color.gray);
+		g.drawPolygon(poly);
+	}
+	/* -------------------------------------------------*/
+	public static void shadeRectangle (Graphics g, int x, int y, int w, int h, Color color) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,0.2f);		
+		g.setColor(color);
+		g.fillRect(x,y,w, h);
+		ColorDistribution.setComposite(g, composite);		
+	}
+	/* -------------------------------------------------*/
+	public static void darkenRectangle (Graphics g, int x, int y, int w, int h, float f) {
+		Composite composite = ColorDistribution.getComposite(g);
+		ColorDistribution.setTransparentGraphics(g,f);		
+		g.setColor(Color.black);
+		g.fillRect(x,y,w, h);
+		ColorDistribution.setComposite(g, composite);		
+	}
+	/* -------------------------------------------------*/
+	public static void darkenRectangle (Graphics g, int x, int y, int w, int h) {
+		darkenRectangle(g,x,y,w,h,0.2f);
+	}
+	/* -------------------------------------------------*/
+	public static void fixRectangle (Rectangle rect) {
+		if (rect.width < 0){
+			int nx = rect.x + rect.width;
+			rect.x = nx;
+			rect.width = -rect.width;
+		}
+		if (rect.height < 0){
+			int ny = rect.y + rect.height;
+			rect.y = ny;
+			rect.height = -rect.height;
+		}
+	}
+
+	/* -------------------------------------------------*/
+	public static void drawRect (Graphics g, int x, int y, int w, int h) {
+		if (w < 0){
+			int nx = x + w;
+			x = nx;
+			w = -w;
+		}
+		if (h < 0){
+			int ny = y + h;
+			y = ny;
+			h = -h;
+		}
+		g.drawRect(x, y, w, h);
+	}
+	/* -------------------------------------------------*/
+	public static void setFontName (String name, Graphics g) {
+		Font curFont = g.getFont();
+		Font fontToSet = new Font (name, curFont.getStyle(), curFont.getSize());
+		if (fontToSet!= null) {
+			curFont = fontToSet;
+			g.setFont(curFont);
+		}
+	}
+	/* -------------------------------------------------*/
+	public static void setFontStyle (int style, Graphics g) {
+		Font curFont = g.getFont();
+		Font fontToSet = new Font (curFont.getName(), style, curFont.getSize());
+		if (fontToSet!= null) {
+			curFont = fontToSet;
+			g.setFont(curFont);
+		}
+	}
+	/* -------------------------------------------------*/
+	public static void setFontSize (int size, Graphics g) {
+		Font curFont = g.getFont();
+		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), size);
+		if (fontToSet!= null) {
+			curFont = fontToSet;
+			g.setFont(curFont);
+		}
+	}
+	/* -------------------------------------------------*/
+	public static void drawOval(Graphics g, int x, int y, int w, int h){
+		try {
+			Graphics2D g2 = (Graphics2D)g;
+			Stroke st = g2.getStroke();
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+			g2.drawOval(x,y,w,h); 
+			g2.setStroke(st);
+		}
+		catch(NullPointerException e){
+			MesquiteMessage.warnProgrammer("npe in draw oval x " + x + " y " + y + " w " + w + " h " + h);
+		}
+	}
+	/* -------------------------------------------------*/
+	public static void fillOval(Graphics g, int x, int y, int w, int h, boolean threeD){
+		try {
+			Graphics2D g2 = (Graphics2D)g;
+			Stroke st = g2.getStroke();
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+			if (threeD){
+				Color c = g.getColor();
+				Color current = c;
+				current = ColorDistribution.darker(current, 0.75);
+				while (w>0) {
+					g.setColor(current);
+					g.fillOval(x,y,w,h);
+					x++;
+					y++;
+					w-=4;
+					h-=4;
+					current = ColorDistribution.brighter(current, 0.75);
+				}
+				if (c!=null) g.setColor(c);
+			}
+			else
+				g2.fillOval(x,y,w,h); 
+			g2.setStroke(st);
+
+		}
+		catch(NullPointerException e){
+			MesquiteMessage.warnProgrammer("npe in fill oval x " + x + " y " + y + " w " + w + " h " + h);
+		}
+	}
+	/* -------------------------------------------------*/
+	public static void fillArc(Graphics g, int x, int y, int w, int h, int startAngle, int arcAngle, boolean threeD){
+		if (arcAngle < 1)
+			return;
+		if (MesquiteTrunk.isWindows()){ //this is workaround to Windows problem by which goes all black if too close to 0 or 360
+			int spotsize = MesquiteInteger.maximum(w, h);
+			if (3.14*spotsize*(360-arcAngle)/360<1){
+				fillOval(g, x, y, w, h, threeD);
+				return;
+			}
+			if (3.14*spotsize*arcAngle/360<1)
+				return;
+		}
+		if (threeD){
+			Color c = g.getColor();
+			Color current = c;
+//			TODO: needs to define a polygon that clips to prevent upward curved edges on left side
+			current = ColorDistribution.darker(current, 0.75);
+			while (w>0) {
+				g.setColor(current);
+				g.fillArc(x,y,w,h, startAngle, arcAngle);
+				x++;
+				y++;
+				w-=4;
+				h-=4;
+				current = ColorDistribution.brighter(current, 0.75);
+			}
+			if (c!=null) g.setColor(c);
+		}
+		else
+			g.fillArc(x,y,w,h, startAngle, arcAngle); 
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/GroupLabel.java b/Source/mesquite/lib/GroupLabel.java
new file mode 100644
index 0000000..b150d79
--- /dev/null
+++ b/Source/mesquite/lib/GroupLabel.java
@@ -0,0 +1,108 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+
+	
+/* ======================================================================== */
+/** DOCUMENT.*/
+public class GroupLabel extends FileElement {
+	Color color = null;
+	MesquiteSymbol symbol = null;
+	int id;
+	boolean colorWasSet = false;
+	boolean symbolWasSet = false;
+	boolean recentlyModified = false;
+	boolean visible = true;
+	static int numLabels;
+	static {
+		numLabels = 0;
+	}
+	public GroupLabel() {
+		//this.taxa = taxa; //TODO: should listen to changes in the taxa!!!
+		id = numLabels++;
+		/*int tS;
+		if (id /2 * 2 == id)
+			tS = 25 - id;
+		else
+			tS = id;
+		if (tS<0)
+			tS = -tS;
+		tS = tS % 25;
+		color = new Color(Color.HSBtoRGB((float)((25-tS) * 0.8 /25),(float)1.0,(float)1.0));
+		*/
+		color = null;
+	}
+	public static boolean supportsSymbols() {
+		return false;
+	}
+	public String getTypeName(){
+		return "Group Label";
+	}
+	public boolean isVisible() {
+		return visible;
+	}
+	public void setVisible(boolean visible) {
+		this.visible = visible;
+	}
+	/** Sets the name of this element */
+	public void setName(String name){
+		super.setName(name);
+		notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+
+	}
+	/*.................................................................................................................*/
+	public void setColor(Color color){
+		this.color = color;
+		colorWasSet = true;
+		notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+	}
+	/*.................................................................................................................*/
+	public Color getColor(){
+		return color;
+	}
+	/*.................................................................................................................*/
+	public boolean colorSet(){
+		return colorWasSet;
+	}
+	/*.................................................................................................................*/
+	public void setSymbol(MesquiteSymbol symbol){
+		this.symbol = symbol;
+		symbol.setColor(getColor());
+		this.symbol.setColor(getColor());
+		symbolWasSet = true;
+		notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+	}
+	/*.................................................................................................................*/
+	public MesquiteSymbol getSymbol(){
+		return symbol;
+	}
+	/*.................................................................................................................*/
+	public boolean symbolSet(){
+		return symbolWasSet;
+	}
+	public boolean isRecentlyModified() {
+		return recentlyModified;
+	}
+	public void setRecentlyModified(boolean recentlyModified) {
+		this.recentlyModified = recentlyModified;
+	}
+	
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/lib/HNode.java b/Source/mesquite/lib/HNode.java
new file mode 100644
index 0000000..a79367e
--- /dev/null
+++ b/Source/mesquite/lib/HNode.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+public interface HNode {
+	public static int MOUSEDOWN = 0;
+	public static int MOUSEMOVE = 1;
+	public static int MOUSEEXIT = 2;
+	public HNode[] getHDaughters();
+	public HNode getHMother();
+	public String getName();
+	public String getTypeName();
+	public int getNumSupplements();
+	public String getSupplementName(int index);
+	public void hNodeAction(Container c, int x, int y, int action);
+	public void hSupplementTouched(int index);
+	public Color getHColor();
+	public Image getHImage();
+	public boolean getHShow();
+}
+
+
diff --git a/Source/mesquite/lib/HPanel.java b/Source/mesquite/lib/HPanel.java
new file mode 100644
index 0000000..434227f
--- /dev/null
+++ b/Source/mesquite/lib/HPanel.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+public abstract class HPanel extends ScrollPane{
+	public HPanel () {
+	}
+	public abstract void setRootNode(HNode node);
+	public abstract void setTitle(String title);
+	public abstract void renew();
+	public abstract void disposeReferences();
+	public abstract void dispose();
+	public abstract void highlightNode(HNode node);
+	public abstract void setBackground(Color color);
+	public abstract void setDefaultDepth(int depth);
+	public abstract void showTypes(boolean s);
+}
+
diff --git a/Source/mesquite/lib/HTMLDescribable.java b/Source/mesquite/lib/HTMLDescribable.java
new file mode 100644
index 0000000..b77808e
--- /dev/null
+++ b/Source/mesquite/lib/HTMLDescribable.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it can give an html description*/
+public interface HTMLDescribable  {
+	public static boolean verbose = false;
+ 	public String toHTMLStringDescription();
+}
+
diff --git a/Source/mesquite/lib/HTMLSidePanel.java b/Source/mesquite/lib/HTMLSidePanel.java
new file mode 100644
index 0000000..f45956f
--- /dev/null
+++ b/Source/mesquite/lib/HTMLSidePanel.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+
+/* ======================================================================== */
+
+public class HTMLSidePanel extends MousePanel{
+	public static final int width = 300;
+	public static final int height = 36;
+	JEditorPane panel;
+	JScrollPane scrollPane;
+	Image goaway;
+	MesquiteModule pw;
+	String title;
+	public HTMLSidePanel (MesquiteModule pw, String title){
+		super();
+		this.pw = pw;
+		this.title = title;
+		panel = new MesqJEditorPane("text/html","<html></html>");
+		setLayout(null);
+		panel.setVisible(true);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goaway.gif");
+        scrollPane = new  JScrollPane(); 
+        scrollPane.getViewport().add( panel,  BorderLayout.CENTER ); 
+		add(scrollPane);
+		setBackground(ColorDistribution.brown);
+		setForeground(Color.white);
+		panel.setBackground(Color.white);
+		setSize(width, 500);
+		scrollPane.setBounds(0, height, width, getBounds().height-height);
+	}
+	public void setTitle(String s){
+		this.title = s;
+	}
+	public void setSize(int w, int h){
+		scrollPane.setSize(w, h-height);
+		super.setSize(w, h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		scrollPane.setBounds(0, height, w, h-height);
+		super.setBounds(x, y, w, h);
+	}
+	public void setText(String s){
+		if (s == null)
+			s = "";
+		panel.setText(s);
+	}
+	/* to be used by subclasses to tell that panel touched */
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (y> 2 && y< 2 + 16 && x >= 2 && x <= 2 + 16) 
+			pw.panelGoAway(this);
+		
+	}
+	public void paint(Graphics g){
+  		if (title != null)
+  			g.drawString(title, 20, height - 22);
+	   	g.drawImage(goaway, 2, 2, this);
+		g.fillRect(0, height-2, getBounds().width, 2);
+	}
+
+	
+}
+
diff --git a/Source/mesquite/lib/HelpSearchManager.java b/Source/mesquite/lib/HelpSearchManager.java
new file mode 100644
index 0000000..a4b2e95
--- /dev/null
+++ b/Source/mesquite/lib/HelpSearchManager.java
@@ -0,0 +1,1053 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+
+import java.util.Vector;
+import java.awt.*;
+
+
+import mesquite.lib.duties.WindowHolder;
+
+/* acts on Mesquite trunk's behalf to manage searchable help system */
+public class HelpSearchManager implements Commandable {
+	MesquiteModule searchWindowBabysitter;
+	boolean showExplanation = false;
+	MesquiteModuleInfo currentModule;
+	MesquiteCommand selectionCommand = new MesquiteCommand(null, null);
+	public static String searchColoursString = "<body bgcolor=\"#FFFFDF\"><font color =\"#4B2211\">"; //FFFFDF
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hypertext link has been touched", "[link text]", commandName, "linkTouched")) {
+			linkTouched(searchParser.getFirstToken(arguments));
+		}
+		return null;
+	}
+	public void makeWindow(){
+		if (searchWindowBabysitter != null)
+			return;
+		searchWindowBabysitter = MesquiteTrunk.mesquiteTrunk.hireNamedEmployee (WindowHolder.class, "#WindowBabysitter");
+		HSWindow ww = new HSWindow(searchWindowBabysitter, new MesquiteCommand("linkTouched", this), "Search", true);
+		if (searchWindowBabysitter != null)
+			searchWindowBabysitter.setModuleWindow(ww);
+		//	ww.setWindowSize(620, 400, false);
+	}
+
+	public void showHTML(String s){
+		if (searchWindowBabysitter== null)
+			makeWindow();
+		if (searchWindowBabysitter != null && searchWindowBabysitter.getModuleWindow()!= null){
+			MesquiteHTMLWindow w = (MesquiteHTMLWindow)searchWindowBabysitter.getModuleWindow();
+			if (w != null){
+				w.setText(s);
+				w.setVisible(true);
+				w.show();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void searchData(String s, MesquiteWindow window){
+		if (window == null)
+			return;
+		MesquiteString commandResult = new MesquiteString();
+		/*if (searchWindowBabysitter == null) {
+			String results = window.searchData(s, commandResult);
+			if (results != null){
+				searchWindowBabysitter = MesquiteTrunk.mesquiteTrunk.hireNamedEmployee ( WindowHolder.class, "#WindowBabysitter");
+				MesquiteHTMLWindow ww = new MesquiteHTMLWindow(searchWindowBabysitter, new MesquiteCommand("linkTouched", this), "Search results", true);
+				searchWindowBabysitter.setModuleWindow(ww);
+				searchWindowBabysitter.resetContainingMenuBar();
+				MesquiteTrunk.resetAllWindowsMenus();
+
+				ww.setWindowSize(620, 400);
+				ww.setDataWindow(window);
+				ww.setText(results);
+				if (commandResult.isBlank()){
+					ww.setVisible(true);
+				}
+
+			}
+			if (!commandResult.isBlank()){
+				String description = commandResult.getValue();
+				selectionCommand.setOwner(window);
+				selectionCommand.setCommandName(description.substring(0, description.indexOf(":")));
+				selectionCommand.doIt(description.substring(description.indexOf(":")+1, description.length()));
+
+			}
+		}
+		else */ if (searchWindowBabysitter.getModuleWindow()!= null){
+			MesquiteHTMLWindow w = (MesquiteHTMLWindow)searchWindowBabysitter.getModuleWindow();
+			String results = null;
+
+			if (w == window && w.getDataWindow() != null) //another query in results window
+				results = w.getDataWindow().searchData(s, commandResult);
+			else
+				results = window.searchData(s, commandResult);
+			if (window != w)
+				w.setDataWindow(window);
+			if (results != null){
+				w.setText(results);
+
+				if (commandResult.isBlank())
+					w.show();
+			}
+			if (!commandResult.isBlank()){
+				if (w.getDataWindow() != null){
+					String description = commandResult.getValue();
+					selectionCommand.setOwner(w.getDataWindow());
+					selectionCommand.setCommandName(description.substring(0, description.indexOf(":")));
+					selectionCommand.doIt(description.substring(description.indexOf(":")+1, description.length()));
+				}
+			}
+		}
+	}
+	String whereInMenus(String s, Object item, String soFar){
+		if (item instanceof MesquiteWindow){
+			String result = "";
+			MesquiteWindow f = ((MesquiteWindow)item);
+			MenuBar bar = f.getMenuBar();
+			if (bar != null){
+				for (int i = 0; i<bar.getMenuCount(); i++){
+					Menu m = bar.getMenu(i);
+					String rm = whereInMenus(s, m, f.getTitle());
+					if (!StringUtil.blank(rm))
+						result += rm;
+				}
+			}
+			return result;
+		}
+		else if (item instanceof Menu){
+			String result = "";
+			Menu m = ((Menu)item);
+			String label = m.getLabel();
+			if (stringsFound(label, s))
+				result += "<li>" + StringUtil.protectForXML(soFar + ">" + label) + "</li>";
+			for (int i = 0; i<m.getItemCount(); i++){
+				MenuItem mi = m.getItem(i);
+				String rm = whereInMenus(s, mi, soFar + ">" + label);
+				if (!StringUtil.blank(rm))
+					result += rm;
+			}
+			return result;
+		}
+		else if (item instanceof MenuItem){
+			String label = ((MenuItem)item).getLabel();
+			if (!stringsFound(label, s))
+				return "";
+			return "<li>" + StringUtil.protectForXML(soFar + ">" + label) + CommandChecker.getItemExplanation((MenuItem)item,
+					CommandChecker.defaultSkipChecker, false, true) + "</li>";
+		}
+		return "";
+	}
+	String searchMenus(String s, boolean useBrowser){
+		String result = "";
+		for (int i = 0; i<MesquiteTrunk.windowVector.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)MesquiteTrunk.windowVector.elementAt(i);
+			String rm = whereInMenus(s, w, "");
+			if (!StringUtil.blank(rm))
+				result += rm;
+		}
+		return result;
+	}
+	String searchControls(String s){
+		String result = "";
+		for (int i = 0; i<MesquiteTrunk.windowVector.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)MesquiteTrunk.windowVector.elementAt(i);
+			String rm = searchComponents(s, w.getGraphicsZero());
+			if (!StringUtil.blank(rm)) {
+				result += "<li>In Window: <strong>" + StringUtil.protectForXML(w.getTitle()) + "</strong><ul>" + rm + "</ul></li>";
+			}
+		}
+		return result;
+	}
+	private String searchComponents(String s, Component c) {
+		String result = "";
+		if (c instanceof Explainable && c instanceof ImageOwner) {
+			String expl = ((Explainable) c).getExplanation();
+			if (stringsFound(expl, s)) {
+				result += "<li><img src = \""
+						+ MesquiteFile.massageFilePathToURL(((ImageOwner) c)
+								.getImagePath()) + "\"> ";
+				result += expl+ "</li>";
+			}
+		}
+		if (c instanceof Container) {
+			Component[] cs = ((Container) c).getComponents();
+			if (cs != null)
+				for (int i = 0; i < cs.length; i++)
+					result += searchComponents(s, cs[i]);
+		}
+		return result;
+	}
+	/*
+
+	String searchManual(String s, boolean useBrowser){
+		String results = "";
+		String arefStart = "showPage:";
+		if (useBrowser)
+			arefStart = "file://";
+		for (int i = 0; i<manualPages.size(); i++) {
+			ManualPage page = (ManualPage)manualPages.elementAt(i);
+			int loc = stringsLoc(page.contents, s);
+			if (loc>=0){
+				loc -= 40;
+				if (loc <0)
+					loc = 0;
+				int end = loc + 90;
+				if (end >= page.contents.length())
+					end =page.contents.length()-1;
+				if (end<loc)
+					end = loc;
+				String excerpt = page.contents.substring(loc, end);
+				results += "<li><img src =\"" + MesquiteFile.massageFilePathToURL(MesquiteModule.getRootImageDirectoryPath() + "mesquiteIcon16.gif") + "\"> <a href = \"" + arefStart +page.path + "\">" + page.title + "</a> ..." + excerpt + "... </li>";
+			}
+
+		}
+		return results;
+	}
+	class ManualPage{
+		String path;
+		String title;
+		String contents;
+	}
+	Vector manualPages;
+	void loadManual(String path){
+		java.io.File f = new java.io.File(path);
+		if (f.isDirectory()){
+			String[] files = f.list();
+			for (int i=0; i<files.length; i++) {
+				String subPath = path + files[i];
+				java.io.File f2 = new java.io.File(subPath);
+				if (f2.isDirectory())
+					subPath += MesquiteFile.fileSeparator;
+				loadManual(subPath);
+			}
+		}
+		else {
+			if (path.endsWith(".html") && !(path.endsWith("moduleIndex.html"))){
+				ManualPage page = new ManualPage();
+				StringBuffer sb = new StringBuffer(MesquiteFile.getFileContentsAsString(path));
+				int start;
+				page.title = sb.substring(sb.indexOf("<title>") + 7, sb.indexOf("</title>"));
+				while ((start = sb.indexOf("<!--")) >=0){
+					int end = sb.indexOf("-->") +3;
+					if (end >=0 && end >= start)
+						sb.delete(start, end);
+					else
+						sb.delete(start, start+1);
+				}
+				while ((start = sb.indexOf("<")) >=0){
+					int end = sb.indexOf(">") +1;
+					if (end >=0 && end >= start)
+						sb.delete(start, end);
+					else
+						sb.delete(start, start+1);
+
+				}
+				page.contents = sb.toString();
+
+				page.path = path;
+				manualPages.addElement(page);
+			}
+		}
+	}
+
+	int manualLoading = 2;
+	public void loadManual(){
+		manualLoading =1;
+		manualPages = new Vector();
+		CommandRecord.tick("Loading manual for searching");
+		MesquiteTrunk.mesquiteTrunk.log("Loading manual for searching...");
+		loadManual(MesquiteModule.getDocsPath());
+		MesquiteTrunk.mesquiteTrunk.logln(".. manual ready.");
+		manualLoading = 0;
+	}
+	 */
+	String menuResults = null;
+	String controlResults = null;
+
+	String searchModules(String s, boolean useBrowser){
+		String results = "";
+		MesquiteModuleInfo mbi = null;
+		MesquiteInteger lastIndex =  new MesquiteInteger(-1);
+		MesquiteInteger category = new MesquiteInteger(0);
+		while ((mbi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteModulesInfoVector.getNextModule(lastIndex, category))!=null){
+			if (mbi.getSearchableAsModule() && (stringsFound(mbi.getName(), s) || stringsFound(mbi.getExplanation(), s) || stringsFound(mbi.getKeywords(), s))) // || stringFound(mbi.getCitation())
+				results += keywordInfo(mbi, mbi, -1, s, useBrowser); 
+			Vector subfunctions = mbi.getSubfunctionsVector();
+			for (int i=0; i<subfunctions.size(); i++){
+				FunctionExplainable fe = (FunctionExplainable)subfunctions.elementAt(i);
+				if ((stringsFound(fe.getName(), s) || stringsFound(fe.getExplanation(), s) || stringsFound(fe.getKeywords(), s))) // || stringFound(mbi.getCitation())
+					results += keywordInfo(mbi, fe, i, s, useBrowser); 
+			}
+
+		}
+		return results;
+	}
+	/*.................................................................................................................*/
+	public void searchKeyword(String s, boolean useBrowser){
+		String results = "";
+		if (!useBrowser){
+			//ADDING RESULTS FROM CURRENT MENUS
+			menuResults = searchMenus(s, useBrowser);
+
+			//ADDING RESULTS FROM CURRENT Controls
+			controlResults = searchControls(s);
+
+			if (!StringUtil.blank(menuResults) || !StringUtil.blank(controlResults)){
+				results += "<h3>Menu items and controls in current windows matching search criteria</strong></h3><ul>";
+				if (!StringUtil.blank(menuResults))
+					results += "<li><a href = \"showMenuResults:\"><img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "menus.gif") + "\"> <strong>Menu items</strong></a> in current windows</li>";
+				if (!StringUtil.blank(controlResults))
+					results += "<li><a href = \"showControlResults:\"><img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "buttons.gif") + "\"> <strong>Buttons and tools</strong></a> in current windows</li>";
+				results += "</ul>";
+			}
+		}
+		//ADDING RESULTS FROM MODULE INFORMATION
+		String smod = searchModules(s, useBrowser);
+		if (!StringUtil.blank(smod))
+			results += "<h3><strong>Modules</strong><ul>" + smod + "</ul></h3>";
+
+		//ADDING RESULTS FROM MANUAL
+		/*
+		 * if (manualLoading == 1){
+			try {
+				while (manualLoading >0)
+					Thread.sleep(20);
+			}
+			catch (InterruptedException e){
+			}
+		}
+		else if (manualLoading == 2){
+			loadManual();
+		}
+		String sman = searchManual(s, useBrowser);
+		if (!StringUtil.blank(sman))
+			results += "<h3>Manual Pages</h3><ul>" + sman + "</ul>";
+		 */
+
+
+		if (StringUtil.blank(results))
+			results = ("<html>" + searchColoursString + "<h2>No features with keywords found (searched: \"" + stringsSearched(s) + "\")</h2></font></body></html>");
+		else 
+			results = "<html>" + searchColoursString + "<h2>Features found (searched: \"" + stringsSearched(s) + "\")</h2>Click the links to see how these functions may be accessed and other details." + results + "</font></body></html>";
+		if (useBrowser){
+			MesquiteFile.putFileContents(MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "tempKeywordSearch.html", results, true);
+			MesquiteModule.showWebPage(MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "tempKeywordSearch.html", true);
+		}
+		else {
+			/*if (searchWindowBabysitter == null) {
+				searchWindowBabysitter = MesquiteTrunk.mesquiteTrunk.hireNamedEmployee ( WindowHolder.class, "#WindowBabysitter");
+				MesquiteHTMLWindow ww = new MesquiteHTMLWindow(searchWindowBabysitter, new MesquiteCommand("linkTouched", this), "Search results", true);
+				searchWindowBabysitter.setModuleWindow(ww);
+				searchWindowBabysitter.resetContainingMenuBar();
+				MesquiteTrunk.resetAllWindowsMenus();
+
+				ww.setDataWindow(null);
+				ww.setWindowSize(620, 400);
+				ww.setText(results);
+				ww.setVisible(true);
+			}
+			else*/ if (searchWindowBabysitter.getModuleWindow()!= null){
+				MesquiteHTMLWindow w = (MesquiteHTMLWindow)searchWindowBabysitter.getModuleWindow();
+				w.setDataWindow(null);
+				w.setText(results);
+				w.setVisible(true);
+			}
+		}
+
+	}
+	public void employeeQuit(MesquiteModule mb){
+		if (mb == searchWindowBabysitter)
+			searchWindowBabysitter = null;
+	}
+	private boolean isNeeded(MesquiteModuleInfo mmi){
+		Vector v = MesquiteTrunk.mesquiteModulesInfoVector.whoUsesMe(mmi);
+		return !(v == null || v.size() == 0);
+	}
+	String howRef = null;
+	Vector toc = new Vector();
+	boolean showTOC = false;
+	/*------------------------------------------------------------------------------------------------*/
+	private void countChainUserForward(MesquiteModuleInfo mmi, boolean mmiListingSuppressed, Vector moduleChain, Vector dutyChain, int depth, int maxDepth){
+		if (moduleChain.indexOf(mmi)>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			return;
+		}
+		if (dutyChain.indexOf(mmi.getDutyClass())>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			return;
+		}
+		if (maxDepth > 0 && depth > maxDepth){
+			return;
+		}
+		Vector v = MesquiteTrunk.mesquiteModulesInfoVector.whoUsesMe(mmi);
+		if (v == null || v.size() == 0){
+			return;
+		}
+
+		moduleChain.addElement(mmi);
+		dutyChain.addElement(mmi.getDutyClass());
+		for (int i = 0; i< v.size() && countUses<maxCount; i++){
+			EmployeeNeed en = (EmployeeNeed)v.elementAt(i);
+			if (en.getSuppressListing()){
+
+				if (en.isEntryPoint()){
+					countUses++;
+					if (countUses % 1000 == 0)
+						System.out.println("uses " + countUses);
+				}
+				else
+					countChainUserForward(en.getRequestor(), true, moduleChain, dutyChain, depth, maxDepth);
+			}
+			else {
+				if (en.isEntryPoint()){
+					countUses++;
+					if (countUses % 1000 == 0)
+						System.out.println("uses " + countUses);
+				}
+				else
+					countChainUserForward(en.getRequestor(), false, moduleChain, dutyChain, depth+1, maxDepth);
+
+			}
+		}
+		dutyChain.removeElement(mmi.getDutyClass());
+		moduleChain.removeElement(mmi);
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	String indexString(){
+		return "(" + (maxCount*paths.size() + countUses) + ")";
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	String doItString(String note, EmployeeNeed need){
+		if (!StringUtil.blank(need.getEntryCommand())){
+			if (MesquiteTrunk.mesquiteTrunk.findEmployeeWithName("#" + need.getRequestor().getClassName()) != null){
+				tryItShown = true;
+				return "<a href = \"doIt: " + need.isEntryPoint() + " " + need.getSuppressListing() + " " + need.getRequestor().getClassName() + " " + StringUtil.tokenize(need.getEntryCommand()) + " " + path(countPath) + "\">Try it!</a>";
+			}
+			return "";
+		}
+		return "";
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	private String needChainUserForward(MesquiteModuleInfo mmi, boolean mmiListingSuppressed, boolean emph,  MesquiteBoolean status, int depth, String spacer, Vector moduleChain, Vector dutyChain, int maxDepth){
+		if (moduleChain.indexOf(mmi)>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			countUses++;
+			status.setValue(false);
+			if (MesquiteTrunk.debugMode)
+				return "<strong><font color = 0000FF>" + indexString() + " </font></strong> <strong><font color = 00FF00>MODULE LOOP (Debugging)</font></strong>";
+			else
+				return "";
+		}
+		if (dutyChain.indexOf(mmi.getDutyClass())>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			countUses++;
+			status.setValue(false);
+			if (MesquiteTrunk.debugMode)
+				return "<strong><font color = 0000FF>" + indexString() + " </font></strong> <strong><font color = FF0000>DUTY LOOP (Debugging)</font></strong>";
+			else
+				return "";
+		}
+		if (maxDepth > 0 && depth > maxDepth){
+			status.setValue(true);
+			if (MesquiteTrunk.debugMode)
+				return "<strong><font color = 0000FF>MAX DEPTH HIT (Debugging)</font></strong>";
+			else
+				return "";
+		}
+		status.setValue(true);
+		Vector v = MesquiteTrunk.mesquiteModulesInfoVector.whoUsesMe(mmi);
+		if (v == null || v.size() == 0)
+			return "";
+		String s = "";
+		moduleChain.addElement(mmi);
+		dutyChain.addElement(mmi.getDutyClass());
+		int startingPoint = 0;
+		if (depth < targetPath.getSize() && MesquiteInteger.isCombinable(targetPath.getValue(depth)))
+			startingPoint= targetPath.getValue(depth);
+		MesquiteBoolean statusOfRequest = new MesquiteBoolean(true);
+		for (int i = startingPoint; i< v.size() && countUses<maxCount; i++){
+			countPath.setValue(depth, i);
+			statusOfRequest.setValue(true);
+			EmployeeNeed en = (EmployeeNeed)v.elementAt(i);
+			String sc = "";
+			if (en.getSuppressListing()){
+				if (en.isEntryPoint()){
+					countUses++;
+					if (MesquiteTrunk.debugMode)
+						sc = "<strong><font color = 0000FF>" + indexString() + " </font></strong> ";// + path(countPath);
+					status.setValue(false);
+					statusOfRequest.setValue(false);
+					//sc = en.getAccessPoint();
+				}
+				else
+					sc =  needChainUserForward(en.getRequestor(), true, depth == 0 && en.getEmphasize(), statusOfRequest, depth, spacer, moduleChain, dutyChain, maxDepth);
+				s += sc;
+			}
+			else {
+				if (en.isEntryPoint()){
+					countUses++;
+					sc = " " + en.getAccessPoint();
+					if (MesquiteTrunk.debugMode)
+						sc += " <strong><font color = 0000FF>" + indexString() + " </font></strong> ";
+					status.setValue(false);
+					statusOfRequest.setValue(false);
+				}
+				else
+					sc =  needChainUserForward(en.getRequestor(), false, depth == 0 && en.getEmphasize(), statusOfRequest, depth +1, spacer + "  ", moduleChain, dutyChain, maxDepth);
+
+				if (StringUtil.blank(sc)){
+					countUses++;
+					if (MesquiteTrunk.debugMode)
+						sc = "<strong><font color = FF00FF>" + indexString() + " </font></strong> " ;
+					else 
+						sc = "";
+					sc += doItString("1", en);// + path(countPath);
+					status.setValue(true);
+				}
+				else if (!en.isEntryPoint() && statusOfRequest.getValue())
+					sc =  "<ul>" + sc + doItString("2", en) + "</ul>";
+				else if (!sc.endsWith("Try it!</a>"))
+					sc = sc + doItString("3 " + en.getSuppressListing() + " " + en.isEntryPoint(), en);
+				if (!en.isEntryPoint()){
+					if (depth >0){
+						if (i == 0){
+							if (mmiListingSuppressed)
+								s += "<li>This is available through ";
+							else
+								s += "<li>" + getImage(mmi) + " " + mmi.getName() + " is available through ";
+						}
+						else {
+							if (mmiListingSuppressed)
+								s += "<li>This is also available through ";
+							else
+								s += "<li>" + getImage(mmi) + " " + mmi.getName() + " is also available through ";
+						}
+					}
+
+					else {
+						if (i != 0)
+							s += "<br>";
+						s += "<li>Via ";
+					}
+					String requestorName = en.getRequestor().getName();
+					if (en.getAlternativeEmployerLabel() != null)
+						requestorName = en.getAlternativeEmployerLabel();
+					if (depth == 0  || emph){
+						if (depth ==0){
+							if (showTOC)
+								s += "<a name = \"" + toc.size() + "\"></a>";
+							toc.addElement("<li>" + requestorName+ "</li>");
+						}
+						s+= "<font size = +1>";
+					}
+
+					s +=  "<strong>" +requestorName + ".</strong> ";
+
+					if (depth ==0 || emph)
+						s+= "</font>";
+					if (showExplanation)
+						s += en.getExplanation();
+					if (mmiListingSuppressed)
+						s +=" " + howRef + "  " /*<strong>How to access this:</strong> "*/ + en.getAccessPoint() ;
+					else
+						s += " " + howRef + "  " /*<strong>How to access " + mmi.getName() + ":</strong> " */ + en.getAccessPoint() ;
+					s += " " + sc + "</li>";
+				}
+				else
+					s += sc;
+			}
+			if (countUses<maxCount)
+				countPath.setValue(depth, MesquiteInteger.unassigned);
+		}
+		dutyChain.removeElement(mmi.getDutyClass());
+		moduleChain.removeElement(mmi);
+
+		return s;
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	IntegerArray countPath = new IntegerArray(100, 10);
+	IntegerArray targetPath = new IntegerArray(100, 10);
+	IntegerArray previousPath = new IntegerArray(100, 10);
+	Vector paths = new Vector();
+	boolean tryItShown = false;
+	int maxCount = 10;
+	int countUses= 0;
+	/*------*/
+	private void showModuleUse(MesquiteHTMLWindow w, MesquiteModuleInfo mmi, int whichFunction, boolean resetPath){
+		toc.setSize(0);
+		Vector moduleChain = new Vector();
+		Vector dutyChain = new Vector();
+		if (resetPath) {
+			targetPath.deassignArray();
+			w.setBackEnabled(true);
+			paths.removeAllElements();
+		}
+		String nextPrevString = "";
+		String pageString = "Page " + (paths.size() + 1);
+		countPath.deassignArray();
+		targetPath.copyTo(previousPath);
+
+		if (paths.size() > 0)
+			nextPrevString =" <a href = \"previous:" + paths.size() + "\"><img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "leftarrow.gif") + "\"></a>";
+
+		else
+			nextPrevString =" <img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "leftarrowDisabled.gif") + "\">";
+		/*
+		 countUses = 0;
+		maxCount = 10000000;
+		countChainUserForward(mmi, false, moduleChain, dutyChain, 0, 9999999);
+
+		moduleChain.removeAllElements();
+		dutyChain.removeAllElements();
+		 */
+		countUses = 0;
+		maxCount = 10;
+		MesquiteBoolean statusOfRequest = new MesquiteBoolean(true);
+		tryItShown = false;
+		String userChain = needChainUserForward(mmi, false, false, statusOfRequest, 0, "", moduleChain, dutyChain, -1);
+		targetPath.deassignArray();
+
+		if (moduleChain.size() > 0)
+			MesquiteMessage.warnProgrammer("MODULE CHAIN WITH LEFTOVERS " + moduleChain.size());
+		String name = mmi.getName();
+		String explanation = mmi.getExplanation();
+		if (whichFunction == 0 || MesquiteInteger.isPositive(whichFunction)){
+			Vector subfunctions = mmi.getSubfunctionsVector();
+			if (whichFunction < subfunctions.size()){
+				FunctionExplanation fe = (FunctionExplanation)subfunctions.elementAt(whichFunction);
+				name = fe.getName();
+				explanation = fe.getExplanation() + " (a function of the module \"" + mmi.getName() + "\")";
+			}
+		}
+		String intro = "<html>" + searchColoursString + "<table width=\"100%\" height=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">" +
+				"<tr><td height=\"80\" bgcolor=\"#6C6252\"><h1><font color=\"#FFFAAD\">" + name + "</h1></font><font size = +1 color=\"#FFFAAD\">" + explanation + "</font>" +
+				"<p>" + mmi.getClassName() + "<br>";
+		if (countUses < maxCount){
+			if (paths.size() > 0)
+				nextPrevString = pageString + "[Last page] " + nextPrevString + " <img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "rightarrowDisabled.gif") + "\">";
+			else
+				nextPrevString = "";
+		}
+		else
+			nextPrevString = pageString + nextPrevString +" <a href = \"next:" + paths.size() + "\"><img border = 0 src = \"" +MesquiteFile.massageFilePathToURL(MesquiteTrunk.getRootImageDirectoryPath() +  "rightarrow.gif") + "\"></a>";
+
+		String needs = "";
+		if (toc.size()>0){
+			if (showTOC){
+				intro  += "<p><a name = \"#top\"></a><strong>" + name + "</strong> can be accessed here:<ul>";
+				for (int i = 0; i<toc.size(); i++){
+					intro += (String)toc.elementAt(i);
+				}
+				intro += "</ul>";
+			}
+			if (mmi.hasNeeds())
+				needs = "<h3>" + mmi.getName() + " <a href = \"moduleNeeds:" +mmi.getClassName()+ "\">makes use of other modules or functions</a></h3>";
+			intro += "<br></td></tr><hr><tr><td>";
+			if (showExplanation)
+				intro += "<a href = \"hideExplanation:\">Hide explanations</a>";
+			else
+				intro += "<a href = \"showExplanation:\">Show explanations</a>";
+			intro += "<h2>How To Access <i>" +mmi.getName() +  "</i>:</h2>" + nextPrevString;
+		}
+		else
+			intro += "<p></td></tr><hr><tr><td>" + nextPrevString;
+		String caveat = "";
+		if (tryItShown)
+			caveat = "<p><strong>NOTE:</strong>  \"Try It!\" links are experimental and may not succeed.  It is best to use them for learning, and not to use them for important analyses or on the only copy of your data file<br>";
+		w.setText(intro + "<ul>" + userChain + "</ul>" + caveat + "<hr>" + needs + "</td></tr></table></font></body></html>");
+		w.setVisible(true);
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	String path(IntegerArray array){
+		String s = "";
+		for (int i=0; i<array.getSize() && MesquiteInteger.isCombinable(array.getValue(i)); i++)
+			s += array.getValue(i) + "_";
+		return s;
+	}
+	/*------------------------------------------------------------------------------------------------*/
+
+	private void makeChoiceChain(MesquiteModuleInfo mmi, boolean mmiListingSuppressed, IntegerArray targetPath, Vector moduleChain, Vector dutyChain, int depth, int maxDepth){
+		if (moduleChain.indexOf(mmi)>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			return;
+		}
+		if (dutyChain.indexOf(mmi.getDutyClass())>=0) { //to prevent infinite recursion, e.g. for random tree modifiers
+			return;
+		}
+		if (maxDepth > 0 && depth > maxDepth){
+			return;
+		}
+		Vector v = MesquiteTrunk.mesquiteModulesInfoVector.whoUsesMe(mmi);
+		if (v == null || v.size() == 0){
+			return;
+		}
+
+		moduleChain.addElement(mmi);
+		dutyChain.addElement(mmi.getDutyClass());
+		int choice = targetPath.getValue(depth);
+		if (MesquiteInteger.isCombinable(choice) && choice < v.size()){
+			EmployeeNeed en = (EmployeeNeed)v.elementAt(choice);
+			if (en.getSuppressListing()){
+				if (en.isEntryPoint()){
+					countUses++;
+				}
+				else
+					makeChoiceChain(en.getRequestor(), true, targetPath, moduleChain, dutyChain, depth, maxDepth);
+			}
+			else {
+				if (en.isEntryPoint()){
+					countUses++;
+				}
+				else
+					makeChoiceChain(en.getRequestor(), false, targetPath, moduleChain, dutyChain, depth+1, maxDepth);
+			}
+
+		}
+		dutyChain.removeElement(mmi.getDutyClass());
+		//moduleChain.removeElement(mmi);
+	}
+	/*------------------------------------------------------------------------------------------------*/
+	private void showModuleNeeds(MesquiteHTMLWindow w, MesquiteModuleInfo mmi){
+		toc.setSize(0);
+		String intro = "<html>" + searchColoursString + "<h2>Other modules or functions used by " + mmi.getName() + "</h2>" + mmi.getExplanation();
+		String needs = "<ul>";
+		if (mmi.hasNeeds()){
+			Vector v = mmi.getEmployeeNeedsVector();
+			for (int i = 0; i<v.size(); i++){
+				EmployeeNeed e = (EmployeeNeed)v.elementAt(i);
+				needs += "<li>" + e.getExplanation() + e.getAccessPoint() + " The available modules to serve this need are as follows.  (NOTE: some of these might be unavailable in certain contexts, for instance if incompatible with a particular sort of data):<ul>";
+				MesquiteModuleInfo possibleEmployee = null;
+				boolean start = true;
+				while (start || possibleEmployee != null){
+					possibleEmployee = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(e.getDutyClass(), possibleEmployee, null, null, null);
+					start = false;
+					if (possibleEmployee != null) {
+						if (possibleEmployee.hasNeeds())
+							needs += "<li><a href = \"moduleNeeds:" + possibleEmployee.getClassName() + "\"><strong>"+ possibleEmployee.getName() + "</strong></a> " + possibleEmployee.getExplanation() + "</li>";
+						else
+							needs += "<li><strong>"+ possibleEmployee.getName() + "</strong> " + possibleEmployee.getExplanation() + "</li>";
+
+					}
+				}
+
+				needs += "</ul></li>";
+			}
+		}
+		/*
+		if (toc.size()>0){
+			intro  += " <a name = \"#top\"></a>This function can be accessed in the following places:<ul>";
+			for (int i = 0; i<toc.size(); i++){
+				intro += (String)toc.elementAt(i);
+			}
+			intro += "</ul>";
+			if (mmi.hasNeeds())
+				intro += "This function in turn <a href = \"moduleNeeds:" +mmi.getClassName()+ "\">makes use of various other functions</a>";
+				if (showExplanation)
+					intro += "<a href = \"hideExplanation:\">Hide explanations</a>";
+				else
+		intro += "<a href = \"showExplanation:\">Show explanations</a>";
+				intro += "<hr><h3>Access:</hr>";
+		}
+		w.setText(intro + "<ul>" + userChain + "</ul></html>");
+		 */
+		w.setText(intro + needs + "</font></body></html>");
+		w.setVisible(true);
+	}
+	private void linkTouched(String description){
+		if (searchWindowBabysitter != null && searchWindowBabysitter.getModuleWindow() != null && description != null){
+			if (howRef == null)
+				howRef = "<img src = \"" + MesquiteFile.massageFilePathToURL(MesquiteModule.getRootImageDirectoryPath() + "how.gif") + "\">";
+
+			MesquiteHTMLWindow w = (MesquiteHTMLWindow)searchWindowBabysitter.getModuleWindow();
+			if (description.startsWith("moduleUse:")){
+				String mName = description.substring(description.indexOf(":")+1, description.length());
+				MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(MesquiteModule.class, mName);
+				if (mmi != null){
+					currentModule = mmi;
+					showModuleUse(w, mmi, -1, true);
+				}
+			}
+			else	if (description.startsWith("functionUse:")){
+				String descriptor = description.substring(description.indexOf(":")+1, description.length());
+				String mName = descriptor.substring(0, descriptor.indexOf(":"));
+				String whichFunction = descriptor.substring(descriptor.indexOf(":")+1, descriptor.length());
+				MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(MesquiteModule.class, mName);
+				if (mmi != null){
+					currentModule = mmi;
+					showModuleUse(w, mmi, MesquiteInteger.fromString(whichFunction), true);
+				}
+			}
+			else if (description.startsWith("doIt:")){
+				Parser parser = new Parser();
+				parser.setString(description.substring(description.indexOf(":")+1, description.length()));
+				String isEntry = parser.getNextToken();
+				String isSuppressed = parser.getNextToken();
+				String recipient = parser.getNextToken();
+				String com = parser.getNextToken();
+				String chain = parser.getNextToken();
+				parser.setString(com);
+				String commandName  = parser.getNextToken();
+				String arguments = parser.getNextToken();
+				parser.setString(chain);
+				IntegerArray a = new IntegerArray(100, 10);
+				String token = null;
+				int count = 0;
+				MesquiteModule recipientModule = MesquiteTrunk.mesquiteTrunk.findEmployeeWithName("#" + recipient);
+				while(!StringUtil.blank(token = parser.getNextToken())){
+					int i = MesquiteInteger.fromString(token);
+					a.setValue(count++, i);
+				}
+				Vector moduleChain = new Vector();
+				Vector dutyChain = new Vector();
+
+				countUses = 0;
+				maxCount = 10;
+				makeChoiceChain(currentModule, false, a, moduleChain, dutyChain, 0, -1);
+
+				if (!"true".equalsIgnoreCase(isEntry)){
+					moduleChain.removeElementAt(moduleChain.size()-1);
+
+				}
+				MesquiteModuleInfo toBeHired = (MesquiteModuleInfo)moduleChain.lastElement();
+				if (arguments == null)
+					arguments = toBeHired.getClassName();
+				else
+					arguments +=  " #" + toBeHired.getClassName();
+
+				MesquiteCommand command = new MesquiteCommand(commandName, recipientModule);
+				CommandRecord rec = MesquiteThread.getCurrentCommandRecord();
+				CommandRecord thisRec = new CommandRecord(false);
+				thisRec.requestEstablishWizard(true);
+				thisRec.setHiringPath(moduleChain);
+				command.doIt(arguments);
+				MesquiteThread.setCurrentCommandRecord(rec);
+				thisRec.requestEstablishWizard(false);
+				MesquiteDialogParent wizard = thisRec.getWizard();
+				thisRec.setWizard(null);
+				if (wizard != null)
+					wizard.dispose();
+				if (moduleChain.size()>0)
+					MesquiteTrunk.mesquiteTrunk.discreetAlert("Sorry, the \"Try It!\" button apparently didn\'t work");
+
+
+			}
+			else if (description.startsWith("showPage:")){
+				String url = description.substring(description.indexOf(":")+1, description.length());
+				MesquiteTrunk.showWebPage(url, false, true);
+			}
+			else if (description.startsWith("showMenuResults:")){
+
+				w.setText("<html><body><h2>Menu items in current windows</h2>Format is <strong>Window Name>Menu Name>Submenus and menu items</strong><ul>" + menuResults + "</ul></body></html>");
+				w.setVisible(true);
+			}
+			else if (description.startsWith("showControlResults:")){
+
+				w.setText("<html><body><h2>Buttons, tools and controls in current windows</h2><ul>" + controlResults + "</ul></body></html>");
+				w.setVisible(true);
+			}
+			else if (description.startsWith("next:")){
+				String level = description.substring(description.indexOf(":")+1, description.length());
+
+
+				countPath.copyTo(targetPath);
+				IntegerArray a = new IntegerArray(100, 10);
+				previousPath.copyTo(a);
+				paths.addElement(a);
+				w.setBackEnabled(false);
+				showModuleUse(w, currentModule, -1,false);
+			}
+			else if (description.startsWith("previous:")){
+				if (paths.size() ==0)
+					return;
+				String level = description.substring(description.indexOf(":")+1, description.length());
+
+				IntegerArray a = (IntegerArray)paths.lastElement();
+				a.copyTo(targetPath);
+				paths.removeElement(a);
+				showModuleUse(w, currentModule, -1,false);
+				if (paths.size() == 0)
+					w.setBackEnabled(true);
+			}
+			else if (description.startsWith("hideExplanation:")){
+				showExplanation = false;
+				showModuleUse(w, currentModule, -1,false);
+			}
+			else if (description.startsWith("showExplanation:")){
+				showExplanation = true;
+				showModuleUse(w, currentModule, -1,false);
+			}
+			else if (description.startsWith("moduleNeeds:")){
+				String mName = description.substring(description.indexOf(":")+1, description.length());
+				MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(MesquiteModule.class, mName);
+				if (mmi != null){
+					currentModule = mmi;
+					showModuleNeeds(w, mmi);
+				}
+			}
+			else if (searchWindowBabysitter.getModuleWindow()!= null) {
+				MesquiteHTMLWindow ww = (MesquiteHTMLWindow)searchWindowBabysitter.getModuleWindow();
+				if (ww.getDataWindow() != null){
+					selectionCommand.setOwner(ww.getDataWindow());
+					selectionCommand.setCommandName(description.substring(0, description.indexOf(":")));
+					selectionCommand.doIt(description.substring(description.indexOf(":")+1, description.length()));
+				}
+			}
+		}
+
+	}
+	/*
+	private boolean stringFound(String s, Pattern pattern){
+		Matcher matcher =   pattern.matcher(s);	
+		return matcher.find();
+	}
+	 */
+	/*.................................................................................................................*/
+	Parser searchParser = new Parser();
+	private String stringsSearched(String targets){
+		if (StringUtil.blank(targets))
+			return "";
+		String conjunction = " OR ";
+		if (HelpSearchStrip.searchMODE == HelpSearchStrip.searchAND)
+			conjunction = " AND ";
+
+		String token = searchParser.getFirstToken(targets);
+		boolean first = true;
+		String result = "";
+		while (!StringUtil.blank(token)){
+			if (!first)
+				result += conjunction;
+			result += token;
+			first = false;
+			token = searchParser.getNextToken();
+		}
+
+		return result;
+
+
+	}
+
+	/*.................................................................................................................*/
+	private boolean stringsFound(String s, String targets){
+		return stringsLoc(s, targets)>=0;
+	}
+	/*.................................................................................................................*/
+	private int stringsLoc(String s, String targets){
+		if (s == null || StringUtil.blank(targets))
+			return -1;
+		int place = -1;
+		String lcS = s.toLowerCase();
+		if (HelpSearchStrip.searchMODE == HelpSearchStrip.searchAND){
+			String token = searchParser.getFirstToken(targets);
+			while (!StringUtil.blank(token)){
+				if ((place = stringFound(lcS, token)) <0)
+					return -1;
+				token = searchParser.getNextToken();
+			}
+			return place;
+
+		}
+		else {
+			String token = searchParser.getFirstToken(targets);
+			while (!StringUtil.blank(token)){
+				if ((place = stringFound(lcS, token))>=0)
+					return place;
+				token = searchParser.getNextToken();
+			}
+			return -1;
+		}
+	}
+	/*.................................................................................................................*/
+	private int stringFound(String s, String target){  // s is already lower case, as it is converted in stringsFound, above
+		if (s == null || target == null)
+			return -1;
+		String lcTarget = target.toLowerCase();  // target might not be lower case; convert it
+		return s.indexOf(lcTarget);
+	}
+	private String getImage(FunctionExplainable func){
+		if (!StringUtil.blank(func.getFunctionIconPath()))
+			return "<font color = \"#FFFFFF\"><img border = 4 src = \"" + MesquiteFile.massageFilePathToURL(func.getFunctionIconPath()) + "\" ></font>";
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	private String keywordInfo(MesquiteModuleInfo mmi, FunctionExplainable func, int whichFunction, String target, boolean forBrowser){
+		String nameString = "<li><strong>";
+		//String iconString = "";
+		if (!StringUtil.blank(func.getFunctionIconPath()))
+			nameString += getImage(func);
+		if (!forBrowser) {
+			if (isNeeded(mmi)){
+				if (mmi == func)
+					nameString += "<a href =\"moduleUse:" + mmi.getClassName() + "\">" + func.getName() + "</a>";
+				else
+					nameString += "<a href =\"functionUse:" + mmi.getClassName() + ":" + whichFunction + "\">" + func.getName() + "</a>";
+			}
+			else
+				nameString += func.getName();
+			nameString += "</strong>:  " + func.getHTMLExplanation() + StringUtil.lineEnding();
+			if (!StringUtil.blank(func.getURLString()))
+				if (func.URLinPackageIntro())
+					nameString += "<a href=\"showPage:" + MesquiteFile.massageFilePathToURL(mmi.getPackageIntroModule().getDirectoryPath() +func.getURLString())+ "\">More Information</a>.";
+			//			nameString += "<a href=\"showPage:" + MesquiteFile.massageFilePathToURL(mmi.getPackageIntroModule().getDirectoryPath() +func.getURLString())+ "\" userinfo=\"browser\">More Information</a>.";
+				else
+					nameString += "<a href=\"showPage:" +func.getURLString() + "\">More Information</a>.";
+			return nameString+StringUtil.lineEnding(); 
+		}
+		else {
+			String gcp = MesquiteFile.massageFilePathToURL(MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "commands" + MesquiteFile.fileSeparator + mmi.getShortClassName() + ".html");
+			if (StringUtil.blank(gcp))
+				nameString += func.getName();
+			else
+				nameString += "<a href =\"" + gcp + "\">" + func.getName() + "</a>";
+			nameString += "</strong>:  " + func.getHTMLExplanation() + StringUtil.lineEnding(); 
+			if (!StringUtil.blank(func.getURLString()))
+				if (func.URLinPackageIntro())
+					nameString += "<a href = \"" + MesquiteFile.massageFilePathToURL(mmi.getPackageIntroModule().getDirectoryPath() +func.getURLString())+ "\">More Information</a>.";
+				else
+					nameString += "<a href=\"" + func.getURLString() + "\">More Information</a>.";
+			return nameString+StringUtil.lineEnding(); 
+		}
+
+
+	}
+	/*
+	 * if (!forBrowser) {
+	String linkString = "";
+	if (isNeeded(mbi))
+		linkString += "  <a href =\"moduleUse:" + mbi.getClassName() + "\">How to access</a>";
+
+	return "<li><strong>" + mbi.getName() + "</strong>:  " + mbi.getExplanation() + linkString + StringUtil.lineEnding() + StringUtil.lineEnding(); 
+}
+else {
+	String nameString = "<li>";
+	String gcp = MesquiteFile.massageFilePathToURL(MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "commands" + MesquiteFile.fileSeparator + mbi.getShortClassName() + ".html");
+	if (StringUtil.blank(gcp))
+		nameString += mbi.getName();
+	else
+		nameString += "<a href =\"" + gcp + "\">" + mbi.getName() + "</a>";
+	return nameString + ":  " + mbi.getExplanation() + StringUtil.lineEnding() + StringUtil.lineEnding(); 
+}
+	 */
+
+
+}
+class HSWindow extends MesquiteHTMLWindow implements SystemWindow {
+
+	public HSWindow(MesquiteModule module, MesquiteCommand linkTouchedCommand, String assignedTitle, boolean showInfoBar) {
+		super(module, linkTouchedCommand, assignedTitle, showInfoBar);
+	}
+	public boolean permitViewMode(){
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/HelpSearchStrip.java b/Source/mesquite/lib/HelpSearchStrip.java
new file mode 100644
index 0000000..e423368
--- /dev/null
+++ b/Source/mesquite/lib/HelpSearchStrip.java
@@ -0,0 +1,173 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+modified 26 July 01: protected against NullPointerException if null images in paint
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+/* ======================================================================== */
+
+public class HelpSearchStrip extends MousePanel implements Commandable {
+	TextArea searchBox;
+	int searchBoxAndX, searchBoxAndY;
+	public static final int searchAND = 0;
+	public static final int searchOR = 1;
+	public static final int searchDATA = 2;
+	public static int searchMODE = searchAND;
+	static Image andImage, orImage, dataImage;
+	boolean searchDataOnly = false;
+	Font smallFont = new Font("SanSerif", Font.PLAIN, 10);
+	MesquiteWindow window;
+	static String[] searchModeExplanation;
+	MesquiteCommand searchCommand = MesquiteTrunk.makeCommand("searchKeywords", this);
+	static {
+		searchModeExplanation = new String[]{"Search Mesquite features; match all terms", "Search Mesquite features; match at least one term", "Search Data in window; match string"};
+	}
+	public HelpSearchStrip(MesquiteWindow window, boolean data) {
+		super();
+		this.window = window;
+		setLayout(null);
+		searchDataOnly = data;
+		searchBox = new TextArea("", 1, 8, TextArea.SCROLLBARS_NONE);
+		add(searchBox);
+		searchBox.setBounds(0, 1, 130, 14);
+		searchBox.setVisible(true);
+		searchBox.setFont(smallFont);
+		searchBox.addKeyListener(new KIListener(this));
+		if (andImage==null && MesquiteModule.getRootPath()!=null){ //done here instead of static in case root path not yet defined when static run
+			andImage=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "and.gif");  
+			orImage=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "or.gif");  
+			dataImage=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "dataSearch.gif");  
+		}
+		setFont(smallFont);
+		setBackground(ColorTheme.getInterfaceBackground());
+		setCursor(Cursor.getDefaultCursor());
+	}
+	public void setText(String t){
+		searchBox.setText(t);
+	}
+	public void search(){
+		enterPressed();
+	}
+	void enterPressed(){
+		String string = searchBox.getText();
+		if (!StringUtil.blank(string)) {
+			string = StringUtil.stripTrailingWhitespace(string);
+			string = StringUtil.replace(string, '"', '\'');
+			searchCommand.doItMainThread(ParseUtil.tokenize(string), null, false, false);
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Searches for keywords", "[keywords]", commandName, "searchKeywords")) {
+			String string = new Parser().getFirstToken(arguments);
+			if (!StringUtil.blank(string)) {
+				string = StringUtil.stripTrailingWhitespace(string);
+				searchBox.setText(string);
+				searchBox.selectAll();
+				if (searchDataOnly || searchMODE == searchDATA)
+					MesquiteTrunk.mesquiteTrunk.searchData(string, window);
+				else
+					MesquiteTrunk.mesquiteTrunk.searchKeyword(string, false);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		if (searchDataOnly)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+
+		Rectangle searchBoxRect = searchBox.getBounds();
+		searchBoxAndX = searchBoxRect.x+searchBoxRect.width+2;
+		searchBoxAndY = searchBoxRect.y + 2;
+		if (searchMODE != searchDATA)
+			g.setColor(ColorDistribution.brown);
+		else
+			g.setColor(ColorDistribution.violetBlue);
+		g.fillRect(searchBoxAndX-2, searchBoxRect.y, 12, searchBoxRect.height);
+		g.setColor(Color.black);
+		if (searchMODE == searchAND){
+			g.drawImage(andImage, searchBoxAndX, searchBoxAndY, this);
+			g.drawString("Search Features", searchBoxAndX+12, searchBoxAndY+10);
+		}
+		else if (searchMODE == searchOR) {
+			g.drawImage(orImage, searchBoxAndX, searchBoxAndY, this);
+			g.drawString("Search Features", searchBoxAndX+12, searchBoxAndY+10);
+		}
+		else if (searchMODE == searchDATA){
+			g.drawImage(dataImage, searchBoxAndX, searchBoxAndY, this);
+			g.drawString("Search Data", searchBoxAndX+12, searchBoxAndY+10);
+	}
+		
+	for (int i=0; i<2000; i+=15)
+			g.drawString(Integer.toString(i), i, i);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	int count = 0;
+	/*.................................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (searchDataOnly)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (x> searchBoxAndX && x< searchBoxAndX+12  && y > searchBoxAndY && y< searchBoxAndY +12) {
+				searchMODE++;
+				searchMODE = searchMODE % 3;
+				window.setExplanation(searchModeExplanation[searchMODE]);
+				MesquiteTrunk.mesquiteTrunk.storePreferences();
+				MesquiteWindow.repaintAllSearchStrips();
+			}
+		else if (x> searchBoxAndX + 12 && x< searchBoxAndX+50  && y > searchBoxAndY && y< searchBoxAndY +12) {
+			enterPressed();
+		}
+		
+		
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseMoved(modifiers, x, y, tool);
+		if (searchDataOnly)
+			return;
+		window.setExplanation(searchModeExplanation[searchMODE]);
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseEntered(modifiers, x, y, tool);
+		if (searchDataOnly)
+			return;
+		window.setExplanation(searchModeExplanation[searchMODE]);
+	}
+}
+
+class KIListener extends KeyAdapter {
+	HelpSearchStrip infoBar;
+	public KIListener(HelpSearchStrip bar){
+		infoBar = bar;
+	}
+	public void keyPressed(KeyEvent e){
+		//Event queue
+		super.keyPressed(e);
+		if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+			infoBar.enterPressed();
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/HorizontalLine.java b/Source/mesquite/lib/HorizontalLine.java
new file mode 100644
index 0000000..5378678
--- /dev/null
+++ b/Source/mesquite/lib/HorizontalLine.java
@@ -0,0 +1,51 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+/** Draws a horizontal line */
+public class HorizontalLine extends Component  {
+	int thickness;
+	ExtensibleDialog dialog;
+	int startx=0;
+	
+	HorizontalLine(ExtensibleDialog dialog, int thickness, int startx){
+		this.thickness = thickness;
+		this.dialog = dialog;
+		this.startx = startx;
+	}
+	HorizontalLine(ExtensibleDialog dialog, int thickness){
+		this.thickness = thickness;
+		this.dialog = dialog;
+		startx=0;
+	}
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		Dimension d = dialog.getPreferredSize();
+		int length = d.width;
+		setSize(new Dimension(length,thickness));
+		setLocation(0,getLocation().y);
+		g.setClip(0,0,getBounds().width, getBounds().height);
+//		length=dialog.getBounds().width - 2*inset;
+		g.setColor(Color.black);
+		for (int i=0; i< thickness; i++)
+			g.drawLine(startx,i,length,i);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/Hyperlink.java b/Source/mesquite/lib/Hyperlink.java
new file mode 100644
index 0000000..3f8dcbb
--- /dev/null
+++ b/Source/mesquite/lib/Hyperlink.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+
+/* ======================================================================== */
+public class Hyperlink implements NexusWritable {
+	private String url;
+	public Hyperlink(String path){
+		url = path;
+	}
+	public String getNexusString(){
+		return url;
+	}
+	public String getURL(){
+		return url;
+	}
+	public void setURL(String s){
+		url = s;
+	}
+}
+	
+
+
diff --git a/Source/mesquite/lib/Identifiable.java b/Source/mesquite/lib/Identifiable.java
new file mode 100644
index 0000000..2abfd52
--- /dev/null
+++ b/Source/mesquite/lib/Identifiable.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it has ID*/
+public interface Identifiable {
+ 	public long getID();
+}
+
diff --git a/Source/mesquite/lib/Illustratable.java b/Source/mesquite/lib/Illustratable.java
new file mode 100644
index 0000000..09806f2
--- /dev/null
+++ b/Source/mesquite/lib/Illustratable.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+
+/* ======================================================================== */
+/** indicates an illustration can be attached to given sort of object.*/
+public interface Illustratable {
+	public void setIllustration(Image illustration, String path);
+	public Image getIllustration();
+}
+
+
diff --git a/Source/mesquite/lib/ImageLabel.java b/Source/mesquite/lib/ImageLabel.java
new file mode 100644
index 0000000..ee85bb9
--- /dev/null
+++ b/Source/mesquite/lib/ImageLabel.java
@@ -0,0 +1,200 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/* ======================================================================== */
+public class ImageLabel implements NexusWritable {
+	private String text;
+	private int x, y, pointX, pointY;
+	private int fontSize = 12;
+	private int width = 100;
+	private int height = 30;
+	private int color = -1;
+	private String colorName = " ";
+	private String font = "SanSerif";
+	String extras = "";
+	Font f;
+	StringInABox textBox;
+	
+	boolean showPointer = true;
+	boolean showShadow = true;
+	boolean fixedToImage = true;
+	public ImageLabel(){
+		textBox = new StringInABox("", new Font (font, Font.PLAIN, fontSize), 100);
+	}
+	public ImageLabel cloneLabel(){
+		ImageLabel label = new ImageLabel();
+		label.text = text;
+		label.font = font;
+		label.extras = extras;
+		label.x = x;
+		label.y = y;
+		label.pointX = pointX;
+		label.pointY = pointY;
+		label.fontSize = fontSize;
+		label.width = width;
+		label.height = height;
+		label.color = color;
+		label.showPointer = showPointer;
+		label.showShadow = showShadow;
+		label.fixedToImage = fixedToImage;
+		return label;
+	}
+	public boolean equals(ImageLabel other){
+		if (!StringUtil.stringsEqual(text, other.text))
+			return false;
+		if (!StringUtil.stringsEqual(font, other.font))
+			return false;
+		if (!StringUtil.stringsEqual(extras, other.extras))
+			return false;
+			
+		if (x != other.x || y != other.y  || pointX != other.pointX || fontSize != other.fontSize  || pointY != other.pointY ||width != other.width || height != other.height || color != other.color)
+			return false;
+		if (showPointer != other.showPointer || showShadow != other.showShadow || fixedToImage != other.fixedToImage)
+			return false;
+		return true;
+	}
+	public String getNexusString(){
+		if (text == null || text.equals(""))
+			text = " ";
+		String c =  "";
+		if (colorName!=null)
+			c = " COLOR = " + StringUtil.tokenize(colorName);
+		else
+			c = " COLORNUMBER = " + color;
+		String s = "(TEXT = " + StringUtil.tokenize(text) + " FONT = " + StringUtil.tokenize(font) + c + " SIZE = " + fontSize;
+		s += " x = " + x + " y = " + y + " fixedToImage = " + fixedToImage + " pointerX = " + pointX + " pointerY = " + pointY + " showpointer = " + showPointer + " width = " + width + " " + extras + " )";
+		return s;
+	}
+	public Font getFont(){
+		return f;
+	}
+	public void setText(String t){
+		text = t;
+		textBox.setString(t);
+		setHeight(textBox.getHeight());
+	}
+	public String getText(){
+		return text;
+	}
+	public void setWidth(int i){
+		width = i;
+		textBox.setWidth(width);
+		setHeight(textBox.getHeight());
+	}
+	public int getWidth(){
+		return width;
+	}
+	public void setHeight(int i){ //not stored in file; calculated when drawing
+		height = i;
+	}
+	public int getHeight(){
+		return height;
+	}
+	public StringInABox getTextBox(){
+		return textBox;
+	}
+	
+	public void setFontSize(int i){
+		fontSize = i;
+		f = new Font (font, Font.PLAIN, fontSize);
+		textBox.setFont(f);
+		setHeight(textBox.getHeight());
+	}
+	public int getFontSize(){
+		return fontSize;
+	}
+	public void setFontColor(int i){
+		color = i;
+		colorName = ColorDistribution.getStandardColorName(i);
+	}
+	public void setFontColor(String name){
+		colorName = name;
+		color = ColorDistribution.getStandardColorNumber(name);
+	}
+	public int getFontColor(){
+		return color;
+	}
+	public void setFontName(String s){
+		font = s;
+		f = new Font (font, Font.PLAIN, fontSize);
+		textBox.setFont(f);
+		setHeight(textBox.getHeight());
+	}
+	public String getFontName(){
+		return font;
+	}
+	public void setLocation(int x, int y){
+		this.x = x;
+		this.y = y;
+	}
+	public void setX(int x){
+		this.x = x;
+	}
+	public void setY(int y){
+		this.y = y;
+	}
+	public int getX(){
+		return x;
+	}
+	public int getY(){
+		return y;
+	}
+	public void setFixedToImage(boolean sh){
+		fixedToImage = sh;
+	}
+	public boolean getFixedToImage(){
+		return fixedToImage;
+	}
+	
+	public void setPointerLocation(int x, int y){
+		pointX = x;
+		pointY = y;
+	}
+	public void setPointerX(int x){
+		pointX = x;
+	}
+	public void setPointerY(int y){
+		pointY = y;
+	}
+	public int getPointerX(){
+		return pointX;
+	}
+	public int getPointerY(){
+		return pointY;
+	}
+	public void setShowPointer(boolean sh){
+		showPointer = sh;
+	}
+	public boolean getShowPointer(){
+		return showPointer;
+	}
+	public void setShowShadow(boolean sh){
+		showShadow = sh;
+	}
+	public boolean getShowShadow(){
+		return showShadow;
+	}
+	
+	public void addExtraSubcommand(String s){
+		extras += s;
+	}
+	
+}
+	
+
+
diff --git a/Source/mesquite/lib/ImageOwner.java b/Source/mesquite/lib/ImageOwner.java
new file mode 100644
index 0000000..674ab16
--- /dev/null
+++ b/Source/mesquite/lib/ImageOwner.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it refers to an image at a path (for documentation building)*/
+public interface ImageOwner {
+ 	public String getImagePath();
+}
+
diff --git a/Source/mesquite/lib/ImagePanel.java b/Source/mesquite/lib/ImagePanel.java
new file mode 100644
index 0000000..504ccf8
--- /dev/null
+++ b/Source/mesquite/lib/ImagePanel.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+
+
+/*===============================================*/
+/** A panel containing and image */
+public class ImagePanel extends Panel implements MouseListener  {
+	Image image;
+	Image imagePressed;
+	ImagePanelListener imageListener;
+	 String imageName;
+	 boolean mouseIsDown = false;
+	 int forcedImageHeight=0;
+	 int forcedImageWidth = 0;
+	
+	public ImagePanel (Image image, Image imagePressed, String imageName, ImagePanelListener imageListener) {
+		super();
+		this.image = image;
+		this.imagePressed = imagePressed;
+		this.imageListener = imageListener;
+		this.imageName = imageName;
+		setVisible(true);
+		setSize(getWidth(), getHeight());
+		addMouseListener(this);
+	}
+	public ImagePanel (Image image) {
+		super();
+		this.image = image;
+		setVisible(true);
+		setSize(getWidth(), getHeight());
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (mouseIsDown && imagePressed !=null)
+			g.drawImage(imagePressed,0,0,(ImageObserver)this);
+		else
+			g.drawImage(image,0,0,(ImageObserver)this);
+	}
+	/*.................................................................................................................*/
+	public void setForcedImageHeight(int height) {
+		forcedImageHeight = height;
+	}
+	/*.................................................................................................................*/
+	public void setForcedImageWidth(int width) {
+		forcedImageWidth = width;
+	}
+	/*.................................................................................................................*/
+	public Dimension getPreferredSize() {
+		return new Dimension(getWidth(), getHeight());
+	}
+	/*.................................................................................................................*/
+	public Dimension getMinimumSize() {
+		return new Dimension(getWidth(), getHeight());
+	}
+	/*.................................................................................................................*/
+	public int getWidth() {
+		if (image!=null) {
+			if (forcedImageWidth==0)
+				return image.getWidth((ImageObserver)this);
+			else
+				return forcedImageWidth;
+		}
+		else
+			return 0;
+	}
+	/*.................................................................................................................*/
+	public int getHeight() {
+		if (image!=null) {
+			if (forcedImageHeight==0)
+				return image.getHeight((ImageObserver)this);
+			else
+				return forcedImageHeight;
+		}
+		else
+			return 0;
+	}
+	/*.................................................................................................................*/
+	public Image getImage(){
+		return image;
+	}
+	/*.................................................................................................................*/
+	public void mouseClicked(MouseEvent e) { }
+	/*.................................................................................................................*/
+	public void mouseEntered(MouseEvent e) { }
+	/*.................................................................................................................*/
+	public void mouseExited(MouseEvent e) { } 
+	/*.................................................................................................................*/
+	public void mousePressed(MouseEvent e) {
+		mouseIsDown = true;
+		if (imagePressed!=null) {
+			Graphics g = this.getGraphics();
+			if (g!=null) {
+				g.drawImage(imagePressed,0,0,(ImageObserver)this);
+			}
+		}
+	} 
+	/*.................................................................................................................*/
+	public void mouseReleased(MouseEvent e) {
+		mouseIsDown = false;
+		if (imagePressed!=null) {
+			Graphics g = this.getGraphics();
+			if (g!=null) 
+				g.drawImage(image,0,0,(ImageObserver)this);
+		}
+		if (imageListener!=null)
+			imageListener.mouseOnImage(imageName);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ImagePanelListener.java b/Source/mesquite/lib/ImagePanelListener.java
new file mode 100644
index 0000000..2b310a4
--- /dev/null
+++ b/Source/mesquite/lib/ImagePanelListener.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib; 
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+public interface ImagePanelListener  {
+	public void mouseOnImage(String imageName);
+}
+
+
diff --git a/Source/mesquite/lib/Incrementable.java b/Source/mesquite/lib/Incrementable.java
new file mode 100644
index 0000000..72dd827
--- /dev/null
+++ b/Source/mesquite/lib/Incrementable.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is incrementable, e.g. chooses different characters, and will accept command to change to different one*/
+public interface Incrementable {
+ 	public void setCurrent(long i);  //SHOULD NOT notify (e.g., parametersChanged)
+ 	public long getCurrent();
+ 	public String getItemTypeName();
+ 	public long getMin();
+ 	public long getMax();
+ 	public long toInternal(long i); //return whether 0 based or 1 based counting
+ 	public long toExternal(long i); //return whether 0 based or 1 based counting
+}
+
diff --git a/Source/mesquite/lib/InfoBar.java b/Source/mesquite/lib/InfoBar.java
new file mode 100644
index 0000000..579166e
--- /dev/null
+++ b/Source/mesquite/lib/InfoBar.java
@@ -0,0 +1,725 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+modified 26 July 01: protected against NullPointerException if null images in paint
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.Path2D;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+import mesquite.lib.simplicity.SimplicityStrip;
+/* ======================================================================== */
+/** The information bar just above the window contents.  This has icon-buttons to choose graphics versus various text modes.
+For the most part the InfoBar is responsible for controlling the display of the window itself. There are 9 modes: 
+Two represent the output of the modules controlling the window (the standard graphics output and a text version).
+The other seven modes are informational modes that Mesquite composes and controls to inform the user about 
+the modules currently contributing to the window and their parameters, explanations, and citations.*/
+public class InfoBar extends MousePanel implements Commandable {
+	MesquiteWindow window;
+	MesquiteInteger which;
+	int defaultMenuBase = 40;
+	int menuBase = defaultMenuBase;
+	//	int[] tabOffsets = new int[] {54, 92, 162, 213, 272};
+	int triangleWidth = 4;
+	final boolean showTabs = false;  //turning off post-2.75
+	final int numSpecialButtons =0;
+	public static final int numModes = 5;
+	static final int CLOSEINFOBAR = -1;
+	Color bgColor = Color.white;
+	int rightBracketMenu = -1;
+	int leftBracketX = -1;
+	MesquitePopup leftNotice, rightNotice;
+	//	Following are modes
+	int mode = 0; 
+	/** The standard graphics mode by which modules display their results in the window. */
+	public static final int GRAPHICS = 0;
+	/** The standard text mode showing the modules' results. */
+	public static final int TEXT_CONTENTS = 1;
+	/** Displays the parameter Strings returned by the modules participating in the window. */
+	public static final int TEXT_PARAMETERS = 2;
+	/** Displays the citations for the modules. */
+	public static final int TEXT_CITATIONS = 4;
+	/** Displays the tree of employees currently involved in the window. */
+	public static final int EMPLOYEE_TREE = 3;
+
+	/* the following modes/constants are defunct (perhaps permanently)*/
+	/** Turns on Query Mode for the window. */
+	public static final int QUERYMODE = 22;
+	/** Displays the log of commands sent to the modules involved in the window (currently excluding those in a MesquiteBlock of a NEXUS file) */
+	public static final int TEXT_LOG = 25;
+	/** Displays the explanations provide by the modules involved in the window as to what they do. */
+	public static final int TEXT_EXPLANATIONS = 26;
+
+	int[] menuOffsets;
+	ContentArea[] graphics;
+	TextContentArea[] text;
+	InterContentArea iC;
+	//HelpSearchStrip searchStrip;
+	SimplicityStrip simplicityStrip;
+	static Image iconImages;  
+	public static Image triangleImage, triangleImageDown, popIn;
+	public static Image releaseImage, prereleaseImage;
+	//	public static Image[] graphicsTab, textTab, parametersTab, modulesTab, citationsTab;
+	//	public static Image[] baseImage;  
+	Font smallFont = new Font("SanSerif", Font.PLAIN, 12);
+	MesquiteCommand searchCommand = MesquiteTrunk.makeCommand("searchKeywords", this);
+	static {
+		/*	baseImage=  new Image[ColorDistribution.numColorSchemes];
+		graphicsTab=  new Image[ColorDistribution.numColorSchemes];
+		textTab=  new Image[ColorDistribution.numColorSchemes];
+		parametersTab=  new Image[ColorDistribution.numColorSchemes];
+		modulesTab=  new Image[ColorDistribution.numColorSchemes];
+		citationsTab=  new Image[ColorDistribution.numColorSchemes];
+		//	iconImages=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "infoBarIcons.gif");  */
+	}
+
+	public InfoBar(MesquiteWindow window) {
+		super();
+		this.window = window;
+		//showTabs = window.showInfoTabs();
+		setLayout(null);
+		menuOffsets = new int[20];
+
+		/*
+		 * searchStrip = new HelpSearchStrip(window, false);
+		add(searchStrip);
+		searchStrip.setSize(230, 15);
+		int searchLeft = tabBase ; //+ tabOffsets[numModes-1]+40;
+		if (!showTabs)
+			searchLeft = tabBase;
+		searchStrip.setLocation(searchLeft, 0);
+		searchStrip.setVisible(true);
+		 */
+		if (InterfaceManager.enabled && !(window instanceof SystemWindow) && !(window instanceof mesquite.trunk.AboutWindow)){
+			simplicityStrip = new SimplicityStrip(window, false);
+			add(simplicityStrip);
+			simplicityStrip.setSize(120, 16);
+			simplicityStrip.setLocation(getWidth()-24, 1);
+			simplicityStrip.setBackground(ColorDistribution.veryVeryLightGray);
+			simplicityStrip.setVisible(true);
+		}
+		if (iconImages==null && MesquiteModule.getRootPath()!=null){ //done here instead of static in case root path not yet defined when static run
+			iconImages=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "infoBarIcons.gif");  
+			popIn = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "compactTransparent.gif");  
+		}
+		which = new MesquiteInteger(0);
+		setFont(smallFont);
+		setBackground(bgColor = ColorDistribution.veryVeryLightGray);
+		leftNotice =  new MesquitePopup(this);
+		leftNotice.add(new MesquiteMenuItem("Menus between " + MenuOwner.leftBracket + " " + MenuOwner.rightBracket, null, null, null));
+		leftNotice.add(new MesquiteMenuItem("   are specific to current window", null, null, null));
+		rightNotice =  new MesquitePopup(this);
+		rightNotice.add(new MesquiteMenuItem("Menus between " + MenuOwner.leftBracket + " " + MenuOwner.rightBracket, null, null, null));
+		rightNotice.add(new MesquiteMenuItem("   are specific to current window", null, null, null));
+
+		//	searchStrip.setBackground(ColorTheme.getInterfaceBackground());
+		//simplicityStrip.setBackground(ColorTheme.getInterfaceBackground());
+
+		setCursor(Cursor.getDefaultCursor());
+	}
+	/*.................................................................................................................*/
+	/** . */
+	public void dispose(){
+		window=null;
+
+		for (int i=0; i < graphics.length; i++) 
+			graphics[i]=null;
+		for (int i=0; i < text.length; i++) 
+			text[i]=null;
+		iC = null;
+		super.dispose();
+	}
+	/*.................................................................................................................*/
+	/** Registers the content areas with the InfoBar. */
+	public void setContentsArea(ContentArea[] graphics, TextContentArea[] text, InterContentArea iC){
+		this.graphics=graphics;
+		this.iC = iC;
+		this.text = text;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows the status window for an employee module", "[employee number]", commandName, "showStatus")) {
+			which.setValue(0);
+			MesquiteModule module =findNthEmployee(window.getOwnerModule(), which, Integer.parseInt(arguments));
+			if (module!=null)
+				new ModuleInfoWindow(module);
+		}
+		else if (checker.compare(this.getClass(), "Shows the manual web page for an employee module", "[employee number]", commandName, "showManual")) {
+			which.setValue(0);
+			MesquiteModule module =findNthEmployee(window.getOwnerModule(), which, Integer.parseInt(arguments));
+			if (module!=null)
+				module.showManual();
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public int getInfoBarWidth() {
+		int width = menuBase + 20; //  +  tabOffsets[numModes-1]  + 20;
+		width += 12;  // to accommodate release/nonrelease icon
+		return width;
+	}
+	/*.................................................................................................................*/
+	String[] label = new String[]{"Graphics", "Text", "Parameters", "Modules", "Citations"};
+	public void paint (Graphics g) {
+		if (window == null || MesquiteWindow.checkDoomed(this))
+			return;
+		/*if (InterfaceManager.isEditingMode()){
+			Color co = g.getColor();
+			g.setColor(Color.cyan);
+			g.fillRect(0, 0, getWidth(), getHeight());
+			g.setColor(co);
+		}*/
+		int colo = window.getColorScheme();
+		FontMetrics fm = g.getFontMetrics();
+		if (popIn!=null && window.isPoppedOut()) g.drawImage(popIn,0,0, this);
+		int height = getHeight();
+		int top = 2;
+		int round = 6;
+		MesquiteModule mod = window.getOwnerModule() ;
+		/*if (mod != null){
+			MesquiteModule fc = mod.getFileCoordinator();
+			if (mod.getProject() != null){
+				if (MesquiteTrunk.getProjectList().g etNumProjects()>1){
+					g.setColor(ColorTheme.getInterfaceBackground());
+					g.fillOval(left + 7, 4, 8, 8);
+				}
+				g.setColor(ColorTheme.getInterfaceEdgePositive());
+				g.drawOval(left + 7, 4, 8, 8);
+			}
+		}
+		 */
+
+		g.setColor(ColorTheme.getContentFrame());  //rounded upper left corner to feel like a screen corner, to make it easer to sense the menu
+		//g.setColor(Color.green);
+		if (g instanceof Graphics2D) {
+			Graphics2D g2 = (Graphics2D)g;
+			Stroke st = g2.getStroke();
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+
+			MesquitePath2DFloat path = new MesquitePath2DFloat();
+			if (path.OK()){
+				int adjust = 0;
+				int pathLeft = 0;
+				int pathRight = 14;
+				int pathTop = 0;
+				int pathBottom = 10;
+				path.moveTo(adjust+pathRight, adjust+pathTop);
+				path.lineTo(adjust+pathLeft, adjust+pathTop);
+				path.lineTo(adjust+pathLeft,adjust+pathBottom);
+				path.curveTo(adjust+pathLeft, adjust+pathTop+(pathBottom-pathTop)/3, adjust+pathLeft+(pathRight-pathLeft)/3, adjust+pathTop, adjust+pathRight, adjust+pathTop);
+				path.closePath();
+				path.fill(g2);
+			}
+			else {
+				g2.setStroke(new BasicStroke(4));
+				g2.drawArc(-2,-2, 20, 20, -180, -90);
+				//	g2.drawArc(10,10, 8, 8, -180, -90);
+			}
+
+			g2.setStroke(st);
+		} 
+		else {
+			g.fillRect(0,0,2,2);
+			g.fillRect(0,0,4,1);
+			g.fillRect(0,0,1,4);
+		}
+		g.setColor(Color.black);
+
+		// MENUS ================
+		menuBase = defaultMenuBase;
+		ToolPalette palette = window.getPalette();
+		if (palette != null && palette.getWidth()>defaultMenuBase/2){
+			menuBase = defaultMenuBase/2 + palette.getWidth();
+		}
+		int left=menuBase ; //+ tabOffsets[numModes-1];
+		Vector menus = mod.getEmbeddedMenusVector();
+		int count = 0;
+		if (menus != null){
+			g.drawString(MenuOwner.leftBracket, left-20, 16);
+			leftBracketX = left-20;
+			//g.fillRect(left-12, 2, 8, 8);
+			menuOffsets = new int[menus.size()];
+			for (int i=0; i< menuOffsets.length; i++) menuOffsets[i] = 12;
+			for (int i=0; i< menus.size(); i++){
+				Object m = menus.elementAt(i);
+				if (m instanceof MesquitePopup){
+					MesquitePopup menu = (MesquitePopup)menus.elementAt(i);
+
+					if (menu.getItemCount()>0){
+						String label = menu.getLabel();
+						if (i == menus.size()-1 && label.equals("Window") && mod != MesquiteTrunk.mesquiteTrunk){
+							rightBracketMenu = i;
+							g.drawString(MenuOwner.rightBracket, left , 16);
+							left += 26;
+							//menuOffsets[count] += 26;
+						}
+						if (menuWithSameLabelExists(label, i, menus))
+							label = label + ".";
+						g.drawString(label, left, 16);
+						left += fm.stringWidth(label) + 16;
+						if (count< menuOffsets.length)
+							menuOffsets[count++] = left - 12;
+
+					}
+				}
+				else {
+					MesquiteMenu menu = (MesquiteMenu)menus.elementAt(i);
+					//if (menu.getItemCount()>0))
+					MesquiteMessage.warnProgrammer("MENU PROBLEM: MesquiteMenu where popup should be " + menu.getLabel());
+				}
+			}
+			//	for (int i=0; i< menuOffsets.length; i++) g.drawRect(menuOffsets[i], 0, 6, 16);
+
+		}
+
+		int preReleaseLoc = 36;
+
+		String title = window.title;
+		g.setColor(Color.gray);
+		int leftStart = getWidth()-GraphicsUtil.stringWidth(g, title)-10;
+		if (mod!=null)
+			leftStart=leftStart-preReleaseLoc;
+		if (leftStart<left)
+			leftStart=left;
+		g.drawString(title, leftStart, GraphicsUtil.stringHeight(g, title));
+		g.setColor(Color.black);
+
+		int rel = getWidth()  - preReleaseLoc;
+		if (mod != null) {
+
+			if (prereleaseImage !=null && releaseImage!=null){
+				if (mod.anySubstantivePrereleases())
+					g.drawImage(prereleaseImage,rel,1, this);
+				//else
+				//	g.drawImage(releaseImage,rel,1, this);
+			}
+		}
+		/*if (window.queryMode)
+			g.setColor(Color.red);
+		else
+			g.setColor(ColorTheme.getInterfaceBackground());
+		g.fillRect(0,262, getBounds().width-262, getBounds().height-1);
+		 */
+		g.setColor(Color.black);
+		//if (window.queryMode)
+		//	g.drawString("QUERY MODE ON (\"?\" button turns off)",270,12);
+		g.drawLine(0,getBounds().height-1, getBounds().width, getBounds().height-1);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	boolean menuWithSameLabelExists(String label, int position, Vector menus){
+		for (int i=0; i< menus.size() && i<position; i++){
+			Object m = menus.elementAt(i);
+			if (m instanceof MesquitePopup){
+				MesquitePopup menu = (MesquitePopup)menus.elementAt(i);
+
+				if (menu.getItemCount()>0){
+					String menuLabel = menu.getLabel();
+					if (menuLabel.equals(label))
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	private String listSubstantivePrereleases(MesquiteModule module, String spacer) {
+		if (!module.anySubstantivePrereleases())
+			return "";
+		String thisBranch = "";
+		if (module.isSubstantive() && module.isPrerelease())
+			thisBranch =spacer + module.getName() + ":  " + module.getExplanation() + StringUtil.lineEnding();
+
+		int num = module.getEmployeeVector().size();
+		spacer +="    ";
+		for (int i=0; i<num; i++) {
+			Object obj = module.getEmployeeVector().elementAt(i);
+			MesquiteModule mb = (MesquiteModule)obj;
+			thisBranch += listSubstantivePrereleases(mb, spacer);
+		}
+		return thisBranch;
+	}
+	/*.................................................................................................................*/
+	private String listExplanations(MesquiteModule module, String spacer) {
+		String thisBranch=spacer + module.getName() + ":  " + module.getExplanation() + StringUtil.lineEnding();
+
+		int num = module.getEmployeeVector().size();
+		spacer +="    ";
+		for (int i=0; i<num; i++) {
+			Object obj = module.getEmployeeVector().elementAt(i);
+			MesquiteModule mb = (MesquiteModule)obj;
+			thisBranch += listExplanations(mb, spacer);
+		}
+		return thisBranch;
+	}
+	/*.................................................................................................................*/
+	private boolean citationsInPath(MesquiteModule module) {
+		if  (!StringUtil.blank(module.getCitation()) || module.showCitation() || (module.isSubstantive() && module.isPrerelease())) {
+			return true;
+		}
+		else  {
+			int num = module.getEmployeeVector().size();
+			for (int i=0; i<num; i++) {
+				Object obj = module.getEmployeeVector().elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (citationsInPath(mb))
+					return true;
+			}
+		}
+		return false;
+	}
+	ListableVector citations = new ListableVector(); //reentrancy problems!
+	boolean warnPrerelease = false;
+	/*.................................................................................................................*/
+	private String listCitations(MesquiteModule module, String spacer) {
+		if (citationsInPath(module)){
+			String thisBranch = "";
+			String citation = module.getCitation();
+			String asterisk;
+			if (module.isPrerelease() && module.isSubstantive()){
+				warnPrerelease = true;
+				asterisk = " * ";
+			}
+			else asterisk = "";
+			if (!module.showCitation())
+				thisBranch += spacer + module.getName()+ asterisk + "\n";
+			else {
+				if (!StringUtil.blank(citation)) {
+					int which = citations.indexOfByName(citation);
+					MesquiteString ms = null;
+					if (which<0) {
+						ms = new MesquiteString();
+						ms.setName(citation);
+						ms.setValue("(" + (citations.size()+1) + ")");
+						citations.addElement(ms, false);
+					}
+					else
+						ms = (MesquiteString)citations.elementAt(which);
+					thisBranch +=spacer + module.getName() + ":  " + ms.getValue() + asterisk +  "\n"; //spacer + module.getAuthors() + " " + module.getDateReleased() + ". " + module.getName() + " (version " + versionString + ")" + StringUtil.lineEnding();
+				}
+				else //asks to show citation but none is supplied!
+					thisBranch += spacer + module.getName()+ asterisk + "\n";
+			}
+
+			int num = module.getEmployeeVector().size();
+			spacer +="    ";
+			for (int i=0; i<num; i++) {
+				Object obj = module.getEmployeeVector().elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				thisBranch += listCitations(mb, spacer);
+			}
+			return thisBranch;
+		}
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	private MesquiteModule findNthEmployee(MesquiteModule mb, MesquiteInteger which, int n){
+		if (mb==null)
+			return null;
+		if (which.getValue()==n)
+			return mb;
+		int num = mb.employees.size();
+		which.increment();
+		for (int i=0; i<num; i++) {
+			Object obj = mb.employees.elementAt(i);
+			MesquiteModule mbq = (MesquiteModule)obj;
+			MesquiteModule mfound = findNthEmployee(mbq, which, n);
+			if (mfound!=null) 
+				return mfound;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Get the current mode (i.e. which page is currently being shown) */
+	public int getMode(){
+		return mode;
+	}
+	private String getWindowStamp(){
+		Date d = new Date(System.currentTimeMillis());
+		String t = "Mesquite version " + MesquiteModule.getMesquiteVersion() + MesquiteModule.getBuildVersion() + "   Date: " + d.toString()  +StringUtil.lineEnding();
+		MesquiteModule mod = window.getOwnerModule() ;
+		if (mod != null){
+			MesquiteProject p = mod.getProject();
+			if (p!=null){
+				t+= "Window refers to project with home file " + p.getHomeFileName() + StringUtil.lineEnding();
+				t+="File path: " + p.getHomeDirectoryName() + StringUtil.lineEnding();
+			}
+		}
+		t +="=======================" +StringUtil.lineEnding();
+		return t;
+	}
+	/*.................................................................................................................*/
+	/** Gets the text for mode m */
+	public String getText(int m){
+		if (window == null)
+			return null;
+		if (m== TEXT_CONTENTS){ //text version of contents
+			return getWindowStamp() +  StringUtil.lineEnding() + window.getTextContents();
+		}
+		else if (m== QUERYMODE){ //window info
+			MesquiteModule mod = window.getOwnerModule() ;
+			if (mod == null)
+				return "There is no information available for this window";
+			else {
+				String t = getWindowStamp();
+				t += "This window is owned by the module " + mod + StringUtil.lineEnding() + "Employer path " + mod.getEmployerPath();
+				return t;
+			}
+		}
+		else if (m== TEXT_PARAMETERS){
+			return  getWindowStamp() +  StringUtil.lineEnding() +"Parameters of modules participating in window: " + StringUtil.lineEnding() + StringUtil.lineEnding() + window.getOwnerModule().accumulateParameters("  ");
+		}
+		else if (m== TEXT_LOG){ //log
+			return window.getLogText();
+		}
+		else if (m== TEXT_EXPLANATIONS){
+			return getWindowStamp() +  StringUtil.lineEnding() +"Explanations of functions of modules participating in window: " + StringUtil.lineEnding() + StringUtil.lineEnding() + listExplanations(window.getOwnerModule(),"  ");
+		}
+		else if (m== TEXT_CITATIONS){ //citations
+			citations.removeAllElements(false);
+			warnPrerelease = false;
+			MesquiteString msm = new MesquiteString();
+			msm.setName(MesquiteTrunk.mesquiteTrunk.getCitation());
+			msm.setValue("(1)");
+			citations.addElement(msm, false);
+			String cit = getWindowStamp() +  StringUtil.lineEnding() +"Citations of modules participating in window: " + StringUtil.lineEnding() + StringUtil.lineEnding() + listCitations(window.getOwnerModule(),"  ");
+			if (warnPrerelease)
+				cit += "* NOTE: these modules are indicated to be prerelease.  Read their documentation or contact their authors to determine if they are considered ready for publishable results." + StringUtil.lineEnding();
+			for (int i = 0; i<citations.size(); i++) {
+				MesquiteString ms = (MesquiteString)citations.elementAt(i);
+				cit +=  StringUtil.lineEnding() + ms.getValue() + " " + ms.getName();
+			}
+			return cit;
+		}
+		else 
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Refresh the text for mode */
+	public void refreshText(int mode){
+		if (text!=null && mode>0 && mode<numModes && mode<text.length && text[mode]!=null){ //text versions
+			text[mode].setText(getText(mode));
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the text content area */
+	public TextArea getTextArea(int mode){
+		if (text!=null && mode>0 && mode<numModes && mode<text.length && text[mode] != null){ //text versions
+			return text[mode].getTextArea();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Sets the mode (i.e. the page to show) */
+	public void setMode(int mode){
+		window.setExplanation("");
+		if (mode == QUERYMODE){
+			window.queryMode = !window.queryMode;
+			if (window.queryMode) {
+				MesquiteTrunk.mesquiteTrunk.showLogWindow(true);
+				MesquiteTrunk.mesquiteTrunk.logln("\nNOTE: You have just turned on query mode.  While query mode is active for the window, the info bar will be red, and when you select menu items or buttons, explanations for them will appear in the log window.  The menu items and buttons in the window will be otherwise inactive until you hit the \"?\" again to turn query mode off.\n");
+				setBackground(Color.red);
+			}
+			else
+				setBackground(bgColor = ColorDistribution.veryVeryLightGray);
+			repaint();
+		}
+		else if (!window.queryMode) {
+			window.setGraphicsWaitCursor();
+			this.mode = mode;
+			refreshText(mode);
+			if (mode == EMPLOYEE_TREE)
+				window.updateEmployeeTree();
+			window.showPage(mode);
+			repaint();
+			window.setGraphicsDefaultCursor();
+		}
+	}
+	/*.................................................................................................................*/
+	private void respondToButton(int m, int x, int y){
+		if (m==CLOSEINFOBAR) { //close infobar
+			//if (mode == GRAPHICS) //can close infobar only if graphics mode
+			//	window.setShowInfoBar(false);
+		}
+		else if (m<numModes && m>=0) { 
+			setMode(m);
+		}
+	}
+	Vector extraButtons = new Vector();
+	public MesquiteButton addExtraButton(String imagePath, MesquiteCommand command){
+		MesquiteButton b;
+		extraButtons.addElement(b = new MesquiteButton (window.ownerModule, command, null, true, imagePath, 14, 16));
+		add(b);
+		b.setVisible(true);
+		b.setShowBackground(false);
+		return b;
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		for (int i=0; i<extraButtons.size(); i++){
+			MesquiteButton b = (MesquiteButton)extraButtons.elementAt(i);
+			b.setLocation(w- ( i+1)*20, 2);
+
+		}
+		if (simplicityStrip != null)
+			simplicityStrip.setLocation(w - 20, 1);
+
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		for (int i=0; i<extraButtons.size(); i++){
+			MesquiteButton b = (MesquiteButton)extraButtons.elementAt(i);
+			b.setLocation(w- ( i+1)*20, 2);
+		}
+		if (simplicityStrip != null)
+			simplicityStrip.setLocation(w - 20, 1);
+
+	}
+	/*.................................................................................................................*/
+	int whichButton(int x, int y){
+		return -2;	
+	}
+	/*.................................................................................................................*
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		String s="";
+		int theButton = whichButton(x,y);
+		if (theButton==CLOSEINFOBAR)
+			s ="This button will hide the information bar.";
+		else {
+			if (theButton==GRAPHICS)
+				s = "This tab will display a graphical view of the contents of this window. ";
+			else if (theButton==TEXT_CONTENTS)
+				s = "This tab will display a text view of the contents of this window. ";
+			else if (theButton==TEXT_PARAMETERS)
+				s = "This tab will display the parameters of the contents of this window. ";
+			else if (theButton==TEXT_CITATIONS)
+				s = "This tab will display information about how to cite the modules used in this window. ";
+			else if (theButton==EMPLOYEE_TREE)
+				s = "This tab will display the modules used in this window. ";
+			if (theButton==mode)
+				s+="This is the current view.";
+		}
+		if (window!=null)
+			window.setExplanation(s);
+		super.mouseMoved(modifiers,x,y,tool);
+	}
+	 */
+	/*.................................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		menuBase = defaultMenuBase;
+		ToolPalette palette = window.getPalette();
+		if (palette != null && palette.getWidth()>defaultMenuBase/2){
+			menuBase = defaultMenuBase/2 + palette.getWidth();
+		}
+		if (x> leftBracketX -10 && x < leftBracketX + 20){
+			leftNotice.showPopup(x, 24);
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+		int rel = menuBase ; //  + tabOffsets[numModes-1] ;
+		for (int i=0; i< menuOffsets.length; i++) 
+			if (x > menuBase -2 && x < menuOffsets[i]){
+				if (i == rightBracketMenu -1 && i > 0 && x < menuOffsets[i-1] + 26){
+					rightNotice.showPopup(x, 24);
+					MesquiteWindow.uncheckDoomed(this);
+					return;
+				}
+
+				MesquiteModule mod = window.getOwnerModule() ;
+				Vector menus = mod.getEmbeddedMenusVector();
+				if (menus != null){
+					int count = 0;
+					for (int k=0; k< menus.size(); k++){
+
+						Object m = menus.elementAt(k);
+						if (m instanceof MesquitePopup){
+							MesquitePopup menu = (MesquitePopup)menus.elementAt(k);
+							if (menu.getItemCount()>0){
+								if (count == i){
+									int showX = 0;
+									if (i ==0)
+										showX = menuBase;
+									else
+										showX = menuOffsets[i-1];
+									if (menu.getComponent() == null)
+										menu.setComponent(this);
+									menu.showPopup(showX, 24);
+								}
+								count++;
+
+							}
+						}
+					}
+				}
+				MesquiteWindow.uncheckDoomed(this);
+				return;
+			}
+
+		if (x< menuBase){
+			if (MesquiteWindow.compactWindows && window.isPoppedOut())
+				window.getOwnerModule().getFileCoordinator().getModuleWindow().getParentFrame().popIn(window);
+		}
+		/*else if (x>=rel+7 && x <= rel+7+8){
+			MesquiteModule mod = window.getOwnerModule() ;
+			if (mod != null){
+				MesquiteModule fc = mod.getFileCoordinator();
+				if (fc != null){
+					MesquiteCommand mc = fc.makeCommand("allToFront", fc);
+					mc.doIt("");
+					window.toFront();
+				}
+			}
+		}*/
+		else if (x>=rel + 20 && x<=rel+20 + 16) {
+			MesquiteModule mb = window.getOwnerModule();
+			if (mb!=null){
+				if (mb.anySubstantivePrereleases()) {
+					mb.alert("Among the modules participating in this window are some that are pre-release versions and that claim are involved in calculating substantive results.  To see which ones, use the Modules tab of the window.  Modules listed in orange, with an alert symbol, are prerelease and claim to be involved in substantive calculations");
+					/*
+					if (AlertDialog.query(mb.containerOfModule(), "Prerelease modules", "Among the modules participating in this window are some that are pre-release versions and that claim are involved in calculating substantive results.  Do you want to see a list?")){
+						String intro = "These are the modules participating in this window are some that are pre-release versions and that claim are involved in calculating substantive results\n";
+						AlertDialog.verboseNotice(mb.containerOfModule(), "Prerelease modules", intro + listSubstantivePrereleases(mb, "  "));
+					}
+					 */
+				}
+				//else
+				//	mb.alert("All of the modules participating in this window that claim to be involved in calculating substantive results are release versions.  None is listed as a pre-release version.");
+			}
+		}
+		else if (window!=null) {
+			MesquiteModule mod = window.getOwnerModule() ;
+			int b = whichButton(x,y);
+			if (b>=-1 && b!=mode) {
+				respondToButton(b,x,y);
+			}
+
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/Integer2DArray.java b/Source/mesquite/lib/Integer2DArray.java
new file mode 100644
index 0000000..775de7a
--- /dev/null
+++ b/Source/mesquite/lib/Integer2DArray.java
@@ -0,0 +1,316 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class Integer2DArray {
+	int[][] values;
+	int numC;
+	 int numT;
+	NameReference name=null;
+	public Integer2DArray(int numC, int numT){
+		this.numC = numC;
+		this.numT = numT;	
+		values = new int[numC][numT];
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  MesquiteInteger.unassigned;
+	}
+	public Integer2DArray(int[][] input){
+		this(numFullColumns(input), numFullRows(input));
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  input[i][j];
+	}
+	/*...........................................................*/
+	public void dispose(){
+		values = null;
+	}
+	/*...........................................................*/
+	public static int[][] clone(int[][] d){
+		if (d==null || d.length==0)
+			return d;
+		int[][] q = new int[d.length][d[0].length];
+		for (int i=0; i< d.length; i++)
+			for (int j=0; j< d[i].length;j++)
+				q[i][j] = d[i][j];
+		return q;
+	}
+	/*...........................................................*/
+	public static int[][] cloneIncreaseSize(int[][] d, int first, int second){
+		if (d==null || d.length==0)
+			return d;
+		first = MesquiteInteger.maximum(first, d.length);
+		second= MesquiteInteger.maximum(second, d[0].length);
+		int[][]  q = new int[first][second];
+		for (int i=0; i< q.length; i++)
+			for (int j=0; j< q[i].length;j++)
+				if (i>=d.length || j>=d[i].length)
+					q[i][j] = 0;
+				else
+					q[i][j] = d[i][j];
+		return q;
+	}
+
+	/*...........................................................*/
+	public static void swapColumns(int[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		int[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveColumns(int[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		int[][] newValues = new int[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public static int numFullRows(int[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(int[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public int getValue(int ic, int it){
+		if (values==null || (ic <0 || ic >= values.length) || (it <0 || it >= values[ic].length))
+			return MesquiteInteger.unassigned;
+		else
+			return values[ic][it];
+	}
+	/*...........................................................*/
+	public int[] getValues(int ic) {
+		if (values==null || ic <0 || ic >= values.length)
+			return null;
+		else
+			return values[ic];
+	}
+	/*...........................................................*/
+	public int[][] getMatrix() {
+		return values;
+	}
+	/*...........................................................*/
+	public void setValue(int ic, int it, int value) {
+		if (values!=null && ic >=0 && ic < values.length)
+		 	if (it >=0 && it < values[ic].length)
+				values[ic][it] = value;
+	}
+	/*...........................................................*/
+	public void setValues(Integer2DArray incoming) {
+		if (incoming !=null) {
+			resetSize(incoming.getSizeC(), incoming.getSizeT());
+			for (int it=0; it<incoming.getSizeT() && it < getSizeT(); it++) {
+				for (int ic=0; ic<incoming.getSizeC() && ic < getSizeC(); ic++) {
+					setValue(ic, it, incoming.getValue(ic, it));
+				}
+			}
+		}
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public static void zeroArray(int[][] values){
+		if (values==null)
+			return;
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public static void deassignArray(int[][] values){
+		if (values==null)
+			return;
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  MesquiteInteger.unassigned;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  MesquiteInteger.unassigned;
+	}
+	/*...........................................................*/
+	public int getSizeC() {
+		return numC;
+	}
+	/*...........................................................*/
+	public int getSizeT() {
+		return numT;
+	}
+	/*...........................................................*/
+	/** Changes the array size to the new dimensions*/
+	public void resetSize(int newNumC, int newNumT) {
+		if (newNumC == numC && newNumT == numT)
+			return;
+		int[][] newIntValues = new int[newNumC][newNumT];
+		for (int i=0; i<newNumC; i++)
+			for (int j=0; j<newNumT; j++) {
+				if (i<numC && j<numT)
+					newIntValues[i][j]=values[i][j];
+				else
+					newIntValues[i][j]=0;
+			}
+		values=newIntValues;
+		
+		numC=newNumC;
+		numT=newNumT;
+	}
+	/*...........................................................*/
+	public static int minimum(int[][] values){
+		if (values==null)
+			return MesquiteInteger.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteInteger.unassigned);
+		for (int i=0; i<values.length; i++)
+			if (values[i]!=null)
+				for (int j=0; j<values[i].length; j++)
+					d.setMeIfIAmMoreThan(values[i][j]);
+		return d.getIntValue();
+	}
+	/*...........................................................*/
+	public static int maximum(int[][] values){
+		if (values==null)
+			return MesquiteInteger.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteInteger.unassigned);
+		for (int i=0; i<values.length; i++)
+			if (values[i]!=null)
+				for (int j=0; j<values[i].length; j++)
+					d.setMeIfIAmLessThan(values[i][j]);
+		return d.getIntValue();
+	}
+	/*...........................................................*/
+	public static int maximumInColumn(int[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteInteger.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteInteger.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmLessThan(values[column][i]);
+		return d.getIntValue();
+	}
+	/*...........................................................*/
+	public static int minimumInColumn(int[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteInteger.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteInteger.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmMoreThan(values[column][i]);
+		return d.getIntValue();
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	public static String toString(int[][] matrix){
+		return toString(matrix, false);
+	}
+
+	public static String toString(int[][] matrix, boolean showAsTranspose){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		if (showAsTranspose){
+			for (int j=0; j<numColumns; j++) {
+				result.append('[');
+				for (int i=0; i<numRows; i++) {
+					
+					result.append(MesquiteInteger.toString(matrix[j][i]));
+					result.append('\t');
+				}
+				result.append(']');
+				result.append('\n');
+			}
+		}
+		else {
+			for (int j=0; j<numRows; j++) {
+				result.append('[');
+				for (int i=0; i<numColumns; i++) {
+					
+					result.append(MesquiteInteger.toString(matrix[i][j]));
+					result.append('\t');
+				}
+				result.append(']');
+				result.append('\n');
+			}
+		}
+		return result.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/IntegerArray.java b/Source/mesquite/lib/IntegerArray.java
new file mode 100644
index 0000000..5d2bda3
--- /dev/null
+++ b/Source/mesquite/lib/IntegerArray.java
@@ -0,0 +1,578 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.Random;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class IntegerArray  implements Listable  {
+	int[] values;
+	NameReference name=null;
+	int autoExpandAmount = 0;
+	
+	public IntegerArray(int num){	
+		this(num, 0);
+	}
+	public IntegerArray(int num, int autoExpandAmount){
+		values = new int[num];
+		for (int i=0; i<num; i++)
+			values[i] =  MesquiteInteger.unassigned;
+		this.autoExpandAmount = autoExpandAmount;
+	}
+	/*...........................................................*/
+	public boolean legalIndex(int i){
+		return (values!=null && i>=0 && i<values.length);
+	}
+	/*...........................................................*/
+	public int[] getMatrix(){
+		return values;
+	}
+	/*...........................................................*/
+	public void copyTo(IntegerArray d){
+		if (d==null)
+			return;
+		if (d.values.length!=values.length)
+			d.resetSize(values.length);
+		for (int i=0; i<values.length; i++)
+			d.values[i] =  values[i];
+	}
+	/*...........................................................*/
+	public static int[] reverse(int[] d){
+		if (d==null)
+			return null;
+		int[] values = new int[d.length];
+		for (int i=0; i<values.length; i++)
+			values[values.length-1-i] =  d[i];
+		return values;
+	}
+	/*...........................................................*/
+	public static int[] copy(int[] d){
+		if (d==null)
+			return null;
+		int[] values = new int[d.length];
+		for (int i=0; i<values.length; i++)
+			values[i] =  d[i];
+		return values;
+	}
+	/*...........................................................*/
+	public static int[] copyIntoDifferentSize(int[] d, int newLength, int defaultValue){
+		if (d==null)
+			return null;
+		int[] values = new int[newLength];
+		for (int i=0; i<values.length; i++)
+			if (i<d.length)
+				values[i] =  d[i];
+			else
+				values[i] = defaultValue;
+		return values;
+	}
+	/*...........................................................*/
+	public int getValue(int index){
+		if (!legalIndex(index))
+			return MesquiteInteger.unassigned;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public void setValue(int index, int value) {
+		if (legalIndex(index))
+			values[index] = value;
+		else if (autoExpandAmount>0){
+			if (index >= values.length){
+				int newSize = 0;
+				if (index-values.length+1 < autoExpandAmount)
+					newSize = values.length + autoExpandAmount;
+				else
+					newSize = index + autoExpandAmount;
+				resetSize(newSize);
+				if (legalIndex(index))
+					values[index] = value;
+			}
+		}
+	}
+	/*...........................................................*/
+	public void setValues(int[] values) {
+		if (values==null)
+			this.values = new int[0];
+		else
+			this.values= values;
+	}
+	public static boolean blank(int[] values){
+		if (values == null)
+			return true;
+		for (int i = 0; i<values.length; i++)
+			if (values[i] != 0)
+				return false;
+		return true;
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	public static void zeroArray(int[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteInteger.unassigned;
+	}
+	/*...........................................................*/
+	public static void deassignArray(int[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteInteger.unassigned;
+	}
+	/*...........................................................*/
+	/** Fills array values with random numbers (integers from 0 to length, randomly ordered) */
+	public static void fillWithRandomOrderValues(int[] values, Random rng){
+		if (values==null)
+			return;
+		deassignArray(values);
+		int candidate;
+		int value = 0;
+		for (int bins=values.length; bins>0; bins--) {
+			candidate= (int)(rng.nextDouble()*(bins)-Double.MIN_VALUE)+1;  //casting as (int) will truncate
+			int count = 1;
+			for (int i = 0; i<values.length; i++) {
+				if (!MesquiteInteger.isCombinable(values[i])) {
+						if (candidate==count){
+							values[i] = value;
+							break;
+						}
+						count++;
+				}
+			}
+			value++;
+		}
+		for (int i = 0; i<values.length; i++) {
+			if (!MesquiteInteger.isCombinable(values[i])) {
+					MesquiteMessage.warnProgrammer("Some values in int[] not filled with random order values");
+					return;
+			}
+		}
+	}
+	/*...........................................................*/
+	public static boolean equalValues(int[] arr){
+		if (arr==null)
+			return false;
+		if (arr.length==0)
+			return true;
+		int first = arr[0];
+		for (int i=0; i<arr.length; i++)
+			if (arr[i] != first)
+				return false;
+		return true;
+	}
+	/*...........................................................*/
+	public int indexOf(int match){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(int[] a, int match){
+		if (a==null)
+			return -1;
+		for (int i=0; i<a.length; i++)
+			if (a[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int countSame(int[] a, int match){
+		if (a==null)
+			return 0;
+		int count= 0;
+		for (int i=0; i<a.length; i++)
+			if (a[i]== match)
+				count++;
+		return count;
+	}
+	/*...........................................................*/
+	public static boolean moreThanOneOccurrence(int[] a, int match){
+		if (a==null)
+			return false;
+		boolean alreadyFound = false;
+		for (int i=0; i<a.length; i++) {
+			if (a[i]== match) {
+				if (alreadyFound)
+					return true;
+				alreadyFound = true;
+			}
+		}
+		return false;
+	}
+	/*...........................................................*/
+	public int getSize() {
+		if (values==null)
+			return 0;
+		return values.length;
+	}
+	/*...........................................................*/
+	public boolean anyAssigned(){
+		for (int i=0; i<values.length; i++)
+			if (values[i] != MesquiteInteger.unassigned) {
+
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	public boolean fillNextUnassigned(int v){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== MesquiteInteger.unassigned) {
+				values[i] = v;
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	/** Returns the index of the maximum value within the integer array */
+	public static int indexOfMaximum(int[] values){
+		if (values==null)
+			return MesquiteInteger.unassigned;
+		int index = 0;
+		for (int i=0; i<values.length; i++) {
+			if (MesquiteInteger.whichIsGreater(values[i],values[index])>0)  // then the first one is greater
+					index=i;
+		}
+		return index;
+	}
+	/*...........................................................*/
+	public static int maximum(int[] values){
+		if (values==null)
+			return MesquiteInteger.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteInteger.unassigned);
+		for (int i=0; i<values.length; i++)
+			d.setMeIfIAmLessThan(values[i]);
+		return d.getIntValue();
+	}
+	/*...........................................................*/
+	public static void sort(int[] array){
+		if (array==null || array.length<=1)
+			return;
+		
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				int temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		
+	}
+	/*...........................................................*/
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		int[] newIntValues = new int[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newIntValues[i]=values[i];
+		if (newNum>getSize())
+			for (int i=getSize(); i<newNum; i++)
+				newIntValues[i]=MesquiteInteger.unassigned;
+		values=newIntValues;
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num) {
+		values=addParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static int[] addParts(int[] d, int starting, int num) {
+		if (num<=0 || d==null)
+			return d;
+		/*#
+		if (d.length <= 0) {
+			int[] newMatrix=new int[num];
+			for (int ic=0; ic<num; ic++){
+					newMatrix[ic]= defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+		*/
+		if (starting<0) 
+			starting = -1;
+		if (starting>=d.length) 
+			starting = d.length-1;
+		int newNum = d.length + num;
+		int[] newValues = new int[newNum];
+		for (int i=0; i<=starting; i++)
+			newValues[i]=d[i];
+		for (int i=0; i<num ; i++)
+			newValues[starting + i + 1]=MesquiteInteger.unassigned;
+		for (int i=0; i<d.length-starting-1; i++) 
+			newValues[i +starting+num+1]=d[starting + i + 1];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0 || starting<0 || starting>=getSize())
+			return;
+		values = deleteParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static int[] deleteParts(int[] d, int starting, int num) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		if (num+starting>d.length)
+			num = d.length-starting;
+		int newNum =d.length - num;
+		int[] newValues = new int[newNum];
+		for (int i=0; i<starting; i++)
+			newValues[i]=d[i];
+		for (int i=starting+num; i<d.length; i++)
+			newValues[i-num]=d[i];
+		return newValues;
+	}
+	/*...........................................................*/
+	public static void swapParts(int[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		int temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static int[] moveParts(int[] d, int starting, int num, int justAfter) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		int[] newValues = new int[d.length];
+
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+
+		return newValues;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public String toString(){
+		return "IntegerArray " + toString(values);
+	}
+	/*...........................................................*/
+	public static String toString(int[] vector){
+		if (vector==null ||  vector.length==0)
+			return null;  
+		StringBuffer result = new StringBuffer(vector.length*2);
+		result.append('[');
+		for (int i=0; i<vector.length; i++) {
+			if (vector[i] == MesquiteInteger.unassigned)
+				result.append('?');
+			else
+				result.append(Integer.toString(vector[i]));
+			result.append(' ');
+		}
+		result.append(']');
+		return result.toString();
+	}
+	/** returns a string listing the elements of the array that are equal to the passed number.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static String getListOfMatches(NumberArray values, int target, int offset) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		int lastWritten = -1;
+		for (int i=0; i<values.getSize(); i++) {
+			if (values.getInt(i)==target) {
+				found=true;
+				if (continuing == 0) {
+					s += " " + (i + offset);
+					lastWritten = i;
+					continuing = 1;
+				}
+				else if (continuing == 1) {
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {
+				if (lastWritten != i-1) {
+					s += " " + (i-1 + offset);
+					lastWritten = i-1;
+				}
+				else
+					lastWritten = -1;
+				continuing = 0;
+			}
+		}
+		if (continuing>1)
+			s += " " + (values.getSize()-1 + offset);
+		if (found)
+			return s;
+		else
+			return null;
+	}
+	/** returns a string listing the elements of the array that are equal to the passed number.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static String getListOfMatches(int[] values, int target, int offset) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		int lastWritten = -1;
+		for (int i=0; i<values.length; i++) {
+			if (values[i]==target) {
+				found=true;
+				if (continuing == 0) {
+					s += " " + (i + offset);
+					lastWritten = i;
+					continuing = 1;
+				}
+				else if (continuing == 1) {
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {
+				if (lastWritten != i-1) {
+					s += " " + (i-1 + offset);
+					lastWritten = i-1;
+				}
+				else
+					lastWritten = -1;
+				continuing = 0;
+			}
+		}
+		if (continuing>1)
+			s += " " + (values.length-1 + offset);
+		if (found)
+			return s;
+		else
+			return null;
+	}
+	/** returns a string listing the elements of the array that are equal to the passed number.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static String getListOfMatches(MesquiteInteger[] values, int target, int offset) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		int lastWritten = -1;
+		for (int i=0; i<values.length; i++) {
+			if (values[i]!=null && values[i].getValue()==target) {
+				found=true;
+				if (continuing == 0) {
+					s += " " + (i + offset);
+					lastWritten = i;
+					continuing = 1;
+				}
+				else if (continuing == 1) {
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {
+				if (lastWritten != i-1) {
+					s += " " + (i-1 + offset);
+					lastWritten = i-1;
+				}
+				else
+					lastWritten = -1;
+				continuing = 0;
+			}
+		}
+		if (continuing>1)
+			s += " " + (values.length-1 + offset);
+		if (found)
+			return s;
+		else
+			return null;
+	}
+	/*-----------------------------------------*/
+	public static int[] subtractArrays(int[] firstArray, int[] secondArray){  
+		int count = 0;
+		for (int i=0; i<firstArray.length; i++) {
+			if (inArray(firstArray[i],secondArray))  { // element is in firstArray, therefore will be subtracted
+				count ++;
+			}
+		}
+		int[] subtraction = new int[firstArray.length-count];
+		if (subtraction.length==0)  // empty array
+			return null;
+		count = 0;
+		for (int i=0; i<firstArray.length; i++) {
+			if (!inArray(firstArray[i],secondArray))  { // keep this one
+				subtraction[count] = firstArray[i];
+				count ++;
+			}
+		}
+		return subtraction;
+	}
+	/*-----------------------------------------*/
+  	 public static boolean inArray(int n, int[] a){
+  	 	if (a==null)
+  	 		return false;
+  	 	for (int i = 0; i<a.length; i++)
+  	 		if (a[i] == n)
+  	 			return true;
+  	 	return false;
+  	 }
+	/*-----------------------------------------*/
+   	 public static boolean arraysSame(int[]a, int[] b){ //assumes numbers not duplicated
+  	 	if (a==null || b == null)
+  	 		return false;
+		if (a.length != b.length)
+			return false;
+		
+		for (int i = 0; i<a.length; i++) {
+			if (!inArray(a[i],b))
+				return false;
+		}
+		return true;
+  	 }
+}
+
diff --git a/Source/mesquite/lib/IntegerField.java b/Source/mesquite/lib/IntegerField.java
new file mode 100644
index 0000000..9f52043
--- /dev/null
+++ b/Source/mesquite/lib/IntegerField.java
@@ -0,0 +1,112 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyListener;
+
+
+
+/*===============================================*/
+/** a field for ints */
+public class IntegerField  {
+	ExtensibleDialog dialog;
+	SingleLineTextField textField;
+	boolean isInteger=true;
+	int initialValue=0;
+	int min=MesquiteInteger.unassigned;
+	int max=MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public IntegerField (ExtensibleDialog dialog, String message, int initialValue, int fieldLength, int min, int max) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = initialValue;
+		if (initialValue==MesquiteInteger.unassigned)
+			textField = dialog.addTextField (message, "", fieldLength);
+		else
+			textField = dialog.addTextField (message, MesquiteInteger.toString(initialValue), fieldLength);
+		this.min = min;
+		this.max = max;
+		dialog.focalComponent = textField;
+		
+	}
+	/*.................................................................................................................*/
+	public IntegerField (ExtensibleDialog dialog, String message, int initialValue, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = initialValue;
+		if (initialValue==MesquiteInteger.unassigned)
+			textField = dialog.addTextField (message, "", fieldLength);
+		else
+			textField = dialog.addTextField (message, MesquiteInteger.toString(initialValue), fieldLength);
+		dialog.focalComponent = textField;
+
+	}
+	/*.................................................................................................................*/
+	public IntegerField (ExtensibleDialog dialog, String message, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = 0;
+		textField = dialog.addTextField (message, "", fieldLength);
+		dialog.focalComponent = textField;
+	}
+
+	/*.................................................................................................................*/
+	public void setLabelText(String s) {
+		if (textField!=null)
+			textField.setLabelText(s);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField getTextField() {
+		return textField;
+	}
+	/*.................................................................................................................*/
+	public void addActionListener(ActionListener actionListener) {
+		textField.addActionListener(actionListener);
+	}
+	/*.................................................................................................................*/
+	public void addKeyListener(KeyListener keyListener) {
+		textField.addKeyListener(keyListener);
+	}
+
+	/*.................................................................................................................*/
+	public boolean isValidInteger() {
+		return isInteger;
+	}
+	/*.................................................................................................................*/
+	public void setValue (int value) {
+		textField.setText(MesquiteInteger.toString(value));
+	}
+	/*.................................................................................................................*/
+	public int getValue () {
+		String s = textField.getText();
+		if (s != null && s.equals("?"))
+			return MesquiteInteger.unassigned;
+		if (s != null && (s.equalsIgnoreCase("infinite") ||  s.equalsIgnoreCase("infinity")) && !MesquiteInteger.isCombinable(max))
+			return MesquiteInteger.infinite;
+		int value = MesquiteInteger.fromString(s);
+		isInteger=true;
+		if (!MesquiteInteger.isCombinable(value)) {
+			value=initialValue;
+			isInteger=false;
+		} else if (value< min && MesquiteInteger.isCombinable(min))
+			value = min;
+		else if (value>max && MesquiteInteger.isCombinable(max)) 
+			value = max;
+		return value;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/IntegerSqMatrixFields.java b/Source/mesquite/lib/IntegerSqMatrixFields.java
new file mode 100644
index 0000000..f12db7e
--- /dev/null
+++ b/Source/mesquite/lib/IntegerSqMatrixFields.java
@@ -0,0 +1,174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+/*===============================================*/
+/** a collection of fields for ints */
+public class IntegerSqMatrixFields  {
+	ExtensibleDialog dialog;
+	SingleLineTextField [][] textFields;
+	int[][] matrix;
+	String[] labels;
+	boolean onlyUpperRight;
+	boolean editDiagonal;
+	boolean valid=false;
+	boolean lastValueEditable = false;
+	SingleLineTextField lastField = null;
+	/*.................................................................................................................*/
+	public IntegerSqMatrixFields (ExtensibleDialog dialog, int[][] matrix, String[] labels, boolean onlyUpperRight, boolean editDiagonal, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.labels =labels;
+		this.matrix = matrix;
+		initSqMatrixFields(matrix,onlyUpperRight,editDiagonal, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public IntegerSqMatrixFields (ExtensibleDialog dialog, int matrixSize, boolean onlyUpperRight, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		matrix = new int[matrixSize][matrixSize];
+		for (int i = 0; i<matrixSize; i++)
+			for (int j = 0; j<matrixSize; j++) 
+				matrix[i][j] = MesquiteInteger.unassigned;
+		initSqMatrixFields(matrix,onlyUpperRight,editDiagonal, fieldLength);
+	}
+	/*.................................................................................................................*/
+	public void initSqMatrixFields (int[][]  matrix, boolean onlyUpperRight, boolean editDiagonal, int fieldLength) {
+		this.onlyUpperRight = onlyUpperRight;
+		this.editDiagonal = editDiagonal;
+		textFields = new SingleLineTextField [matrix.length][matrix.length]; //protect against non-square or null matrices!
+		
+		GridBagLayout gridBag = new GridBagLayout();
+		GridBagConstraints constraints = new GridBagConstraints();
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+		int adj = 0;
+		if (!onlyUpperRight)
+			adj = 1;
+		
+		Panel newPanel = new Panel();
+		newPanel.setLayout(gridBag);
+		gridBag.setConstraints(newPanel,constraints);
+		constraints.gridy = 1;
+		constraints.gridx=3;
+		newPanel.add(new Label("To:"),constraints);
+		
+		constraints.gridy = 2;
+		if (!onlyUpperRight) {
+			constraints.gridx=3;
+			if (labels!=null)
+				newPanel.add(new Label("" +labels[0]+ "  "),constraints);
+		}
+			
+		for (int i = 1; i<matrix.length; i++) {
+			constraints.gridx=i+2+adj;
+			if (labels!=null)
+				newPanel.add(new Label("" +labels[i]+ "  "),constraints);
+		}
+		
+		constraints.gridx=1;
+		constraints.gridy = 3;
+		newPanel.add(new Label("From: "),constraints);
+		
+		int numRows = matrix.length;
+		if (onlyUpperRight)
+			numRows --;
+
+		for (int i = 0; i<numRows; i++)  { //cycle through rows 
+			constraints.gridy=i+3;
+			constraints.gridx=2;
+			if (labels!=null)
+				newPanel.add(new Label("  " + labels[i] + "  "),constraints);
+			for (int j = 0; j<matrix[0].length; j++) {
+				constraints.gridx=j+2+adj;
+				if (j>i || i==j && editDiagonal || i>j && !onlyUpperRight) {   
+					if (matrix[i][j]==MesquiteDouble.unassigned)
+						textFields[i][j] = new SingleLineTextField("",fieldLength);
+					else
+						textFields[i][j] = new SingleLineTextField(MesquiteInteger.toString(matrix[i][j]),fieldLength);
+					textFields[i][j].setBackground(Color.white);
+					lastField = textFields[i][j];
+					newPanel.add(textFields[i][j],constraints);					
+				}
+			}
+		}
+		if (!lastValueEditable && lastField!=null) {
+			lastField.setEditable(false);
+			lastField.setBackground(dialog.getBackground());
+		}
+		dialog.addNewDialogPanel(newPanel);
+	}
+	/*.................................................................................................................*/
+	public boolean getValidDouble () {
+		return valid;
+	}
+	/*.................................................................................................................*/
+	public void setLastValueEditable (boolean editable) {
+		lastValueEditable = editable;
+		if (lastField!=null) {
+			if (lastValueEditable) {
+				lastField.setEditable(true);
+				lastField.setBackground(Color.white);
+		}
+			else {
+				lastField.setEditable(false);
+				lastField.setBackground(dialog.getBackground());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean getLastValueEditable () {
+		return lastValueEditable;
+	}
+	/*.................................................................................................................*/
+	public int getValue (int row, int column) {
+		if (row>=textFields.length)
+			return MesquiteInteger.unassigned;
+		if (column>=textFields[0].length)
+			return MesquiteInteger.unassigned;
+		SingleLineTextField SLTF = textFields[row][column];
+		if (SLTF==null)
+			return MesquiteInteger.unassigned;
+		String s = SLTF.getText();
+		int value = MesquiteInteger.fromString(s);
+		valid=true;
+		if (!MesquiteInteger.isCombinable(value)) {
+			valid = false;
+			value=matrix[row][column];
+		}
+		return value;
+	}
+	
+	/*.................................................................................................................*/
+	public Integer2DArray getInteger2DArray () {
+		Integer2DArray newArray = new Integer2DArray(matrix);
+		int numRows = matrix.length;
+		for (int row= 0; row<numRows; row++)  { //cycle through rows 
+			for (int column= 0; column<matrix[0].length; column++) {
+				newArray.setValue(row, column, getValue(row,column));
+			}
+		}
+		return  newArray;
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/InterContentArea.java b/Source/mesquite/lib/InterContentArea.java
new file mode 100644
index 0000000..d5e2179
--- /dev/null
+++ b/Source/mesquite/lib/InterContentArea.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+/** The container fitting within the OuterContentArea, excluding the information bar.  The InterContentArea contains
+the components (ContentAreas) in which the modules actually draw their stuff.  The ContentArea's added to this are alternative
+pages that can be displayed (the primary graphics page, the primary text page, then a series of other pages to give the user
+information.*/
+class InterContentArea extends Panel {
+	CardLayout layout;
+	
+	public InterContentArea () {
+		setLayout(layout = new CardLayout());
+	}
+	/*.................................................................................................................*/
+	/** Shows the page (ContentArea) requested.  The integer passed is the mode parameter from InfoBar (e.g., InfoBar.GRAPHICS) */
+	public void showPage(int i) {
+		 layout.show(this, Integer.toString(i));
+	}
+	/*.................................................................................................................*/
+	/** Add the given page to the InterContentArea */
+	public void addPage(Component c, String which) {
+		 add(c, which);
+		 layout.addLayoutComponent(c, which);
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/Journal.java b/Source/mesquite/lib/Journal.java
new file mode 100644
index 0000000..ed369d5
--- /dev/null
+++ b/Source/mesquite/lib/Journal.java
@@ -0,0 +1,94 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/** 
+*/
+public class Journal {
+	private String buttons  = "";
+	private String[] journalTarget = null;
+	private String targetArgs = "";
+	static Journal j;
+	
+	public Journal() {
+	}
+	public void initialize(){
+		buttons  = "";
+		journalTarget = null;
+		targetArgs = "";
+	}
+	public void  setJournalTarget(MenuItem item){
+		if (item==null)
+			return;
+		String s = item.getLabel();
+		MenuContainer cont = item.getParent();
+		int count = 1;
+		while (cont!= null && !(cont instanceof MenuBar) && !(cont instanceof MesquitePopup)&& cont instanceof MenuComponent) {
+			if (cont instanceof MenuItem)
+				count++;
+			cont =  ((MenuComponent)cont).getParent();
+		}
+		journalTarget = new String[count];
+		cont =item.getParent();
+		journalTarget[0] = item.getLabel();
+		count = 1;
+		while (cont!= null && !(cont instanceof MenuBar) && !(cont instanceof MesquitePopup)&& cont instanceof MenuComponent) {
+			if (cont instanceof MenuItem)
+				journalTarget[count++]= ((MenuItem)cont).getLabel();
+			cont =  ((MenuComponent)cont).getParent();
+		}
+	}
+	public void  setJournalTarget(MenuItem item, String arg){
+		setJournalTarget(item);
+		targetArgs = arg;
+	}
+	public void  addToJournal(String s){
+			buttons += s + '\n';
+	}
+	public String toString(){
+		return "Target: " + StringArray.toString(journalTarget) + '\n' + "Args: " + targetArgs + '\n' + buttons;
+	}
+	public static void setStandardJournal(Journal jo){
+		j = jo;
+	}
+	public void runJournal(MesquiteWindow window){
+		//find menu item
+		//set journal in dialog default
+		//choose it, sending args
+	}
+	/*public static void startJournalling(){
+		journalingOn = true;
+	}
+	public static void  addToJournal(MenuItem item){
+		if (journalingOn)
+			journal.setJournalTarget(item);
+	}
+	public static void  addToJournal(String s){
+		if (journalingOn)
+			journal.addStringToJournal(s);
+	}
+	*/
+	public void stopJournalling(){
+		MesquiteMessage.warnProgrammer("====JOURNAL====\n" + this);
+		j = null;
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/KeyAdapterToConsumeKeys.java b/Source/mesquite/lib/KeyAdapterToConsumeKeys.java
new file mode 100644
index 0000000..e183b0a
--- /dev/null
+++ b/Source/mesquite/lib/KeyAdapterToConsumeKeys.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+class KeyAdapterToConsumeKeys extends KeyAdapter {
+	boolean allowReturn = false;
+	
+	public KeyAdapterToConsumeKeys (boolean allowReturn){
+		super();
+		this.allowReturn=allowReturn;
+	}
+	public void keyPressed(KeyEvent e){
+		if (e.getKeyCode()== KeyEvent.VK_ENTER && !allowReturn) {
+			e.consume();
+		}
+		else {  
+		}
+
+	}
+}
+
diff --git a/Source/mesquite/lib/LabelsAtNodes.java b/Source/mesquite/lib/LabelsAtNodes.java
new file mode 100644
index 0000000..a29826d
--- /dev/null
+++ b/Source/mesquite/lib/LabelsAtNodes.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A class to hold an array of charts for the nodes of a tree. */
+public class LabelsAtNodes extends PanelsAtNodes  {
+	
+	public LabelsAtNodes(MesquiteModule ownerModule, int numNodes, TreeDisplay treeDisplay){
+		super(ownerModule, numNodes, treeDisplay);
+	}
+	public Panel makePanel(int i){
+		MesquiteLabel c = new MesquiteLabel(ownerModule, i);
+		return c;
+	}
+	
+	public void setColor(Color c){
+		if (c==null)
+			return;
+		for (int i=0; i<numNodes; i++){
+			Panel p = getPanel(i);
+			if (p !=null && p instanceof MesquiteLabel){
+				((MesquiteLabel)p).setColor(c);
+			}
+		}
+	}
+	
+}
+
+
diff --git a/Source/mesquite/lib/LeakFinder.java b/Source/mesquite/lib/LeakFinder.java
new file mode 100644
index 0000000..49736b4
--- /dev/null
+++ b/Source/mesquite/lib/LeakFinder.java
@@ -0,0 +1,21 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+ 
+/*=======================*/
+/** This exists merely to help find memory leaks.*/
+public class LeakFinder {
+}
+
diff --git a/Source/mesquite/lib/Legend.java b/Source/mesquite/lib/Legend.java
new file mode 100644
index 0000000..7ec53ea
--- /dev/null
+++ b/Source/mesquite/lib/Legend.java
@@ -0,0 +1,231 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+
+/* ======================================================================== */
+/** Legends for TreeDisplays and Charts, e.g. the TraceCharacter Legend. */
+public abstract class Legend extends MesquitePanel implements Commandable {
+	protected int offsetX = 0;
+	protected int offsetY=0;
+	protected int origTouchX, origTouchY, dragOffsetX, dragOffsetY;
+	protected int defaultWidth, defaultHeight;
+	protected Container constrainingContainer = null;
+	protected Rectangle constrainingRectangle = null;
+	public static long totalCreated = 0;
+	MesquiteInteger pos = new MesquiteInteger();
+
+	public Legend (int defaultWidth, int defaultHeight) {
+		super();
+		origTouchX = -1;
+		origTouchY = -1;
+		setMoveFrequency(4);
+		this.defaultWidth = defaultWidth;
+		this.defaultHeight = defaultHeight;
+		totalCreated++;
+		setCursor(Cursor.getDefaultCursor());
+		defaultOffsets();
+	}
+
+	public void setConstrainingRectangle(Rectangle c){
+		constrainingRectangle = c;
+	}
+	public void setConstrainingContainer(Container c){
+		constrainingContainer = c;
+	}
+	public int getOffsetX() {
+		return offsetX;
+	}
+
+	public int getOffsetY() {
+		return offsetY;
+	}
+
+	public void setOffsetX(int newOffsetX) {
+		if (newOffsetX != MesquiteInteger.unassigned)
+			offsetX=newOffsetX;
+	}
+
+	public void setOffsetY(int newOffsetY) {
+		if (newOffsetY != MesquiteInteger.unassigned)
+			offsetY=newOffsetY;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setOffsetX " +  offsetX);
+		temp.addLine("setOffsetY " +  offsetY);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+
+		if (checker.compare(this.getClass(), "Sets the x offset of the legend from home position", "[x offset in pixels]", commandName, "setOffsetX")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				setOffsetX(offset);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the y offset of the legend from home position", "[y offset in pixels]", commandName, "setOffsetY")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				setOffsetY(offset);
+			}
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+
+	}
+	/*.................................................................................................................*/
+
+	int buffer = 4;
+	public void defaultOffsets() {
+		setOffsetX(buffer);
+		setOffsetY(buffer);
+		//setOffsetX(-(defaultWidth+buffer));
+		//setOffsetY(-(defaultHeight+buffer));
+	}
+	public void adjustLocation() {
+		int legendX = 0;
+		int legendY =0;
+		int baseX;
+		int baseY;
+		int conWidth=0;
+		int conHeight=0;
+		if (constrainingContainer !=null ) {
+			conWidth = constrainingContainer.getBounds().width;
+		conHeight = constrainingContainer.getBounds().height;
+		}
+		else if (constrainingRectangle != null){
+			conWidth = constrainingRectangle.width;
+			conHeight = constrainingRectangle.height;
+		}
+		baseX = 0; //getParent().getBounds().width;
+		baseY =0; // getParent().getBounds().height;
+
+		legendX = baseX+getOffsetX();
+		legendY = baseY+getOffsetY();
+
+		if (constrainingRectangle == null && constrainingContainer == null)	 {
+		}
+		else {
+		if (legendX > (conWidth + buffer)) {
+			setOffsetX(conWidth-baseX-getBounds().width-buffer);
+			legendX = baseX+getOffsetX();
+		}
+		if (legendX<0) {
+			setOffsetX(-baseX+4);
+			legendX = baseX+getOffsetX();
+		}
+
+		if (legendY>conHeight + buffer) {
+			setOffsetY(conHeight-baseY-getBounds().height-buffer);
+			legendY = baseY+getOffsetY();
+		}
+		if (legendY<0) {
+			setOffsetY(-baseY+4);
+			legendY = baseY+getOffsetY();
+		}
+		}
+		if ((legendX!=getBounds().x) || (legendY!=getBounds().y)) {
+			setLocation(legendX, legendY);
+			repaint();
+		}
+	}
+
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (MesquiteEvent.controlKeyDown(modifiers)){
+			super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+		else {
+			origTouchX=x;
+			origTouchY=y;
+			dragOffsetX=0;
+			dragOffsetY=0;
+			if (GraphicsUtil.useXORMode(null, false)){
+				Graphics g=getParent().getGraphics();
+				if (g!=null){
+					g.setClip(null);
+					g.setXORMode(Color.white);
+					g.setColor(Color.black);
+					g.drawRect(getBounds().x, getBounds().y,  getBounds().width-1,  getBounds().height-1);
+					g.dispose();
+				}
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseDrag (int modifiers, int x, int y, MesquiteTool tool) {
+		if (origTouchX < 0)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g=getParent().getGraphics();
+			if (g!=null){
+				g.setClip(null);
+				g.setXORMode(Color.white);
+				g.setColor(Color.black);
+				g.drawRect(getBounds().x + dragOffsetX, getBounds().y + dragOffsetY, getBounds().width-1,  getBounds().height-1);
+				dragOffsetX=x-origTouchX;
+				dragOffsetY=y-origTouchY;
+				g.drawRect(getBounds().x + dragOffsetX, getBounds().y + dragOffsetY,  getBounds().width-1,  getBounds().height-1);
+				g.dispose();
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseUp (int modifiers, int x, int y, MesquiteTool tool) {
+		if (origTouchX < 0)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		boolean doAdjust = false;
+		if (dragOffsetX==0 && dragOffsetY ==0)
+			panelTouched(modifiers, x,y, true);
+		else doAdjust = true;
+		offsetX=offsetX + dragOffsetX;
+		offsetY=offsetY + dragOffsetY;
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g=getParent().getGraphics();
+			if (g!=null){
+				g.setClip(null);
+				g.setXORMode(Color.white);
+				g.setColor(Color.black);
+				g.drawRect(getBounds().x + dragOffsetX, getBounds().y + dragOffsetY,  getBounds().width-1,  getBounds().height-1);
+				g.dispose();
+			}
+		}
+		dragOffsetX=0;
+		dragOffsetY=0;
+		if (doAdjust) {
+			adjustLocation();
+		}
+
+		origTouchX=-1;
+		origTouchY=-1;
+		repaint();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/lib/LegendHolder.java b/Source/mesquite/lib/LegendHolder.java
new file mode 100644
index 0000000..dcda7b7
--- /dev/null
+++ b/Source/mesquite/lib/LegendHolder.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+public interface LegendHolder extends Commandable {
+	public int getInitialOffsetX();
+	public int getInitialOffsetY();
+	public boolean showLegend();
+}
+
diff --git a/Source/mesquite/lib/LightLabel.java b/Source/mesquite/lib/LightLabel.java
new file mode 100644
index 0000000..b169838
--- /dev/null
+++ b/Source/mesquite/lib/LightLabel.java
@@ -0,0 +1,275 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/** A small label that automatically resizes itself that is NOT a panel.
+Handles up to MAXLINES lines.*/
+public class LightLabel {
+	String[] s;
+	private int myWidth = 5;
+	private int width = 0;
+	private int height = 0;
+	private int x = 0; 
+	private int y = 0;
+	private boolean visible = false;
+	//private MesquiteModule ownerModule;
+	int idNumber=0;
+	boolean recheckSize = false;
+	int numLines = 0;
+	Font curFont;
+	int oldLineHeight = 16;
+	Color color, dark, darkdark;
+	MesquiteCommand command = null;
+	static final int MAXLINES = 32;
+	String arguments = null;
+
+	public LightLabel(int idNumber){ //TODO: get rid of ownerModule
+		//this.ownerModule = ownerModule;
+		this.idNumber=idNumber;
+		//setBackground(Color.green);
+		setSize(1, 1);
+		setVisible(false);
+		this.color = Color.lightGray;
+		s = new String[MAXLINES];
+		for (int i=0; i<MAXLINES; i++)
+			s[i]=null;
+	}
+	public LightLabel(){
+		this(0);
+	}
+	void setSize(int w, int h){
+		width = w;
+		height = h;
+	}
+	void setLocation(int x, int y){
+		this.x = x;
+		this.y = y;
+	}
+	Point getLocation(){
+		return new Point(x,y);
+	}
+	public void setVisible(boolean vis){
+		visible = vis;
+	}
+	public boolean isVisible(){
+		return visible;
+	}
+	public void dispose(){
+		//ownerModule = null;
+		//super.dispose();
+	}
+	public void setText(String st) {  
+		if ((st==null) || (st.equals(""))) {
+			numLines = 0;
+			setSize(1, 1);
+			setVisible(false);
+		}
+		else  {
+			if (st.indexOf('\n')<0) {
+				this.s[0]=st;
+				numLines = 1;
+			}
+			else {
+				numLines = 0;
+				while(st.indexOf('\n')>=0){
+					String firstLine = st.substring(0, st.indexOf('\n'));
+					s[numLines]=firstLine;
+					if (numLines<MAXLINES)
+						numLines++;
+					st = st.substring(st.indexOf('\n')+1, st.length());
+				}
+				if (!StringUtil.blank(st)){
+					addLine(st);
+					setVisible(true);
+					recheckSize = true;
+					//repaint();
+					return;
+				}
+			}
+			setVisible(true);
+			recheckSize = true;
+			//repaint();
+		}
+	}
+	public void setCommand(MesquiteCommand command) {  
+		this.command = command;
+	}
+	public void setArguments(String arguments) {  
+		this.arguments = arguments;
+	}
+	public String getText(int line) {  
+		if (line<numLines)
+			return s[line];
+		else
+			return "";
+	}
+	public void addLine(String st) {  
+		if ((st==null) || (st.equals(""))) {
+		}
+		else {
+			setVisible(true);
+			s[numLines]=st;
+			if (numLines<MAXLINES)
+				numLines++;
+			recheckSize = true;
+			//repaint();
+		}
+	}
+	/*
+	public void setFontName (String name) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (name, curFont.getStyle(), curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+	public void setFontStyle (int style) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), style, curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+    	 public void setFontSize (int size) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), size);
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+    	 */
+	public void setFontName (String name, Graphics g) {
+		Font curFont = g.getFont();
+ 		Font fontToSet = new Font (name, curFont.getStyle(), curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			g.setFont(curFont);
+ 		}
+    	 }
+	public void setFontStyle (int style, Graphics g) {
+		Font curFont = g.getFont();
+ 		Font fontToSet = new Font (curFont.getName(), style, curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			g.setFont(curFont);
+ 		}
+    	 }
+    	 public void setFontSize (int size, Graphics g) {
+		Font curFont = g.getFont();
+ 		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), size);
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			g.setFont(curFont);
+ 		}
+    	 }
+    	 
+    	 public void setColor (Color color) {
+		this.color = color;
+		if (color != null) {
+			dark = color.darker();
+			darkdark = dark.darker();
+		}
+    	 }
+    	public int getWidth(Graphics g){
+    		if (g==null)
+    			return 0;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int maxWidth = 0;
+		for (int i=0; i<numLines; i++){
+			int thisWidth =fm.stringWidth(s[i]);
+			if (thisWidth>maxWidth)
+				maxWidth = thisWidth;
+		}
+		g.dispose();
+		if (myWidth!=maxWidth+10) 
+			return maxWidth+10;
+		else
+			return myWidth;
+    	}
+	public void paint(Graphics g) {
+		
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int lineHeight = fm.getAscent() + fm.getDescent() + 4;
+		
+		if (recheckSize || lineHeight!=oldLineHeight) {
+			recheckSize = false;
+			int maxWidth = 0;
+			for (int i=0; i<numLines; i++){
+				int thisWidth =fm.stringWidth(s[i]);
+				if (thisWidth>maxWidth)
+					maxWidth = thisWidth;
+			}
+			if (myWidth!=maxWidth+10 || lineHeight!=oldLineHeight) {
+				oldLineHeight = lineHeight;
+				myWidth = maxWidth+10;
+				setSize(myWidth, lineHeight*numLines);
+			}
+			oldLineHeight = lineHeight;
+		} 
+		int w =width;
+		int h = height;
+		if (color != null) {
+			g.setColor(color);
+			g.fillRoundRect(x,y,w,h, 5, 5);
+			g.setColor(Color.darkGray);
+			g.drawRoundRect(x,y,w-1,h-1, 5, 5);
+			g.setColor(Color.white);
+			g.drawRoundRect(x+1,y+1,w-3,h-3, 5, 5);
+			//g.setColor(dark);
+			//g.drawRoundRect(1,1,w-1,h-1, 5, 5);
+		}
+		g.setColor(Color.black);
+		for (int i=0; i<numLines; i++){
+			if (s[i].charAt(0) == '\2') {
+				setFontStyle(Font.BOLD, g);
+				g.drawString(s[i].substring(1),x+ 4,y+(i+1)*lineHeight-fm.getDescent()-2);
+				setFontStyle(Font.PLAIN, g);
+			}
+			else if (s[i].charAt(0) == '\1') {
+				setFontStyle(Font.ITALIC, g);
+				g.drawString(s[i].substring(1), x+4,y+(i+1)*lineHeight-fm.getDescent()-2);
+				setFontStyle(Font.PLAIN, g);
+			}
+			else
+				g.drawString(s[i], x+4,y+(i+1)*lineHeight-fm.getDescent()-2);
+		}
+	}
+	
+  	/*public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Label", command, this);
+			return;
+		}
+		else if (command == null)
+ 			MesquiteModule.mesquiteTrunk.logln("Label touched with ID number " + Integer.toString(idNumber));
+ 		else
+ 			command.doItMainThread(arguments, CommandChecker.getQueryModeString("Label", command, this));
+ 		return;
+	}
+	*/
+}
+
+
diff --git a/Source/mesquite/lib/LightLabelsAtNodes.java b/Source/mesquite/lib/LightLabelsAtNodes.java
new file mode 100644
index 0000000..1c1dbf2
--- /dev/null
+++ b/Source/mesquite/lib/LightLabelsAtNodes.java
@@ -0,0 +1,191 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class LightLabelsAtNodes  {
+	protected int numNodes;
+	protected LightLabel[] labels;
+	protected TreeDisplay treeDisplay;
+	private boolean[] inTree;
+	private boolean[] shown;
+	
+	public LightLabelsAtNodes(int numNodes, TreeDisplay treeDisplay){
+		this.numNodes = numNodes;
+		this.treeDisplay = treeDisplay;
+		labels=new LightLabel[numNodes];
+		shown=new boolean[numNodes];
+		inTree=new boolean[numNodes];
+
+		for (int i=0; i<numNodes; i++) {
+			labels[i]=new LightLabel();
+			shown[i]=true;
+			inTree[i]=false;
+			labels[i].setVisible(false);
+		}
+	}
+	
+	public TreeDisplay getTreeDisplay(){
+		return treeDisplay;
+	}
+	public void setTreeDisplay(TreeDisplay treeDisplay){
+		this.treeDisplay = treeDisplay;
+	}
+	
+	public void resetNumNodes(int numNodes){
+	//save old text???
+		this.numNodes = numNodes;
+		for (int i=0; i<numNodes; i++) {
+			labels[i]=new LightLabel();
+			shown[i]=true;
+			inTree[i]=false;
+			labels[i].setVisible(false);
+		}
+	}
+ 	public void toggleShowLightLabel(int i){
+ 		//check if legal!!!
+ 		LightLabel p =getLabel(i);
+		if (p!=null) {
+			shown[i]=!shown[i];
+			p.setVisible(shown[i]);
+		}
+ 	}
+ 	public void showLightLabel(int i){
+ 		//check if legal!!!
+ 		LightLabel p =getLabel(i);
+		if (p!=null) {
+			p.setVisible(true);
+			shown[i]=true;
+		}
+ 	}
+ 	public void hideLightLabel(int i){
+ 		LightLabel p =getLabel(i);
+		if (p!=null) {
+			shown[i]=false;
+			p.setVisible(false);
+		}
+ 	}
+ 	public void toggleShowLightLabel(LightLabel label){
+ 		for (int i=0; i<numNodes; i++) {
+ 			LightLabel p =getLabel(i);
+ 			if (p == label) {
+				shown[i]=!shown[i];
+				p.setVisible(shown[i]);
+				return;
+			}
+			
+		}
+ 	}
+ 	public void hideLightLabel(LightLabel label){
+ 		for (int i=0; i<numNodes; i++) {
+ 			LightLabel p =getLabel(i);
+ 			if (p == label) {
+				shown[i]=false;
+				p.setVisible(false);
+				return;
+			}
+			
+		}
+ 	}
+ 	public void showLightLabel(LightLabel label){
+ 		for (int i=0; i<numNodes; i++) {
+ 			LightLabel p =getLabel(i);
+ 			if (p == label) {
+				shown[i]=true;
+				p.setVisible(true);
+				return;
+			}
+			
+		}
+ 	}
+	/*.................................................................................................................*/
+	public   void paintLabels(Tree tree, int node, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				paintLabels(tree, d, g);
+				
+		int nodeX = treeDisplay.getTreeDrawing().x[node];
+		int nodeY = treeDisplay.getTreeDrawing().y[node];
+		LightLabel p = getLabel(node);
+		if (p!=null) {
+			p.paint(g); 
+		}
+		
+	}
+	/*.................................................................................................................*/
+	private void recShowLightLabels(Tree tree, int N) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				recShowLightLabels(tree, d);
+		inTree[N]=true;
+	}
+	/*.................................................................................................................*/
+	public void showLightLabels(Tree tree, int drawnRoot) {
+		for (int i=0; i<inTree.length; i++)
+			inTree[i]=false;
+		recShowLightLabels(tree, drawnRoot);
+		int count =0;
+		for (int i=0; i<inTree.length; i++) {
+			if (!inTree[i] || !shown[i]) {
+		 		LightLabel p =getLabel(i);
+				if (p!=null && p.isVisible()) 
+					p.setVisible(false);
+			}
+			else {
+		 		LightLabel p =getLabel(i);
+				if (p!=null && !p.isVisible()) 
+					p.setVisible(true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void locateLightLabels(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				locateLightLabels(tree, d);
+				
+		int nodeX = treeDisplay.getTreeDrawing().x[node];
+		int nodeY = treeDisplay.getTreeDrawing().y[node];
+		LightLabel p = getLabel(node);
+		if (p!=null){
+			if  ((p.getLocation()==null) || ((p.getLocation().x!=nodeX) || (p.getLocation().y!=nodeY)))
+				p.setLocation(nodeX, nodeY);  //only do if moved
+		}
+		
+	}
+	public void dispose() {
+		for (int i=0; i<numNodes; i++) {
+			labels[i] = null;
+		}
+	}
+	public LightLabel getLabel(int N) {
+		if (N<0 || N>= labels.length)
+			return null;
+		return labels[N];
+	}
+	public void setColor(Color c){
+		if (c==null)
+			return;
+		for (int i=0; i<numNodes; i++){
+			LightLabel p = getLabel(i);
+			if (p !=null && p instanceof LightLabel){
+				((LightLabel)p).setColor(c);
+			}
+		}
+	}
+	public int getNumNodes() {
+		return numNodes;
+	}
+}
+
diff --git a/Source/mesquite/lib/LikelihoodAnalysis.java b/Source/mesquite/lib/LikelihoodAnalysis.java
new file mode 100644
index 0000000..c04ac3b
--- /dev/null
+++ b/Source/mesquite/lib/LikelihoodAnalysis.java
@@ -0,0 +1,5 @@
+package mesquite.lib;
+
+public interface LikelihoodAnalysis {
+
+}
diff --git a/Source/mesquite/lib/LinearValueToPixel.java b/Source/mesquite/lib/LinearValueToPixel.java
new file mode 100644
index 0000000..f32fe47
--- /dev/null
+++ b/Source/mesquite/lib/LinearValueToPixel.java
@@ -0,0 +1,94 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.*;
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/*=================*/
+public class LinearValueToPixel extends ValueToPixel {
+	public LinearValueToPixel (double minValue, double maxValue, double minSweetSpotValue, double maxSweetSpotValue, int totalPixels) {
+		super(minValue, maxValue, minSweetSpotValue,maxSweetSpotValue,totalPixels);
+	}
+	public double getValue(int pixel){
+		if (pixel< startSweetPixels)
+			if (minValue==MesquiteDouble.negInfinite)  // it's logarithmic below
+				if (pixel==0)
+					return effectiveMinValue;
+				else {
+					double preSweetPixelFraction =1.0*(startSweetPixels-pixel)/startSweetPixels;
+					double exp0to1 =  (Math.exp(preSweetPixelFraction) -1)/(Math.exp(1)-1);
+					double value = minSweetSpotValue - exp0to1 * (minSweetSpotValue-effectiveMinValue); 
+					return value; 
+				}
+			else 
+				return minValue + (minSweetSpotValue-minValue)*((1.0* pixel)/(startSweetPixels));
+		else if (pixel> endSweetPixels)
+			if (maxValue==MesquiteDouble.infinite)  // it's logarithmic above
+				if (pixel==totalPixels)
+					return effectiveMaxValue;
+				else {
+					
+					double postSweetPixelFraction =1.0*(pixel-endSweetPixels)/getPostSweetPixels();
+					double exp0to1 =  (Math.exp(postSweetPixelFraction) -1)/(Math.exp(1)-1);
+					double value = maxSweetSpotValue + exp0to1 * (effectiveMaxValue-maxSweetSpotValue); 
+					return value; 
+				}
+			else 
+				return maxSweetSpotValue + (maxValue-maxSweetSpotValue)*((1.0* (pixel-endSweetPixels))/(totalPixels-endSweetPixels));
+		else
+			return minSweetSpotValue + (maxSweetSpotValue-minSweetSpotValue)*((1.0* (pixel-startSweetPixels))/(totalSweetPixels));
+	}
+	public double getPixelPercent(double value){
+		if (MesquiteDouble.isUnassigned(value))
+			return startSweetPixelFraction;
+		else if (value>=minSweetSpotValue && value <= maxSweetSpotValue) 
+			return  startSweetPixelFraction + ((value-minSweetSpotValue)/(maxSweetSpotValue-minSweetSpotValue)) * sweetPixelFraction;
+		else if (value<minSweetSpotValue) 
+			if (minValue==MesquiteDouble.negInfinite) // it is logarithmic below
+				if (value<=effectiveMinValue || value == MesquiteDouble.negInfinite)
+					return 0.0;
+				else { // it is logarithmic below; just do the reverse of what's above
+					double exp0to1 = (minSweetSpotValue-value)/(minSweetSpotValue-effectiveMinValue);  
+					double preSweetPixelFraction = Math.log((exp0to1 * (Math.exp(1)-1)) +1);
+					if (preSweetPixelFraction>1.0)
+						preSweetPixelFraction=1.0;
+					if (preSweetPixelFraction<0.0)
+						preSweetPixelFraction=0.0;
+					double pixelPercent =  (1.0-preSweetPixelFraction)*startSweetPixelFraction;   
+					return pixelPercent; 
+				}
+			else  // it is linear below
+				return  ((value-minValue)/(minSweetSpotValue-minValue)) * startSweetPixelFraction;
+		else 
+			if (value>=effectiveMaxValue || value == MesquiteDouble.infinite)
+				return 1.0;
+			else if (maxValue==MesquiteDouble.infinite) {  // it is logarithmic above; just do the reverse of what's above
+				double exp0to1 = (value-maxSweetSpotValue)/(effectiveMaxValue-maxSweetSpotValue);  
+				double postSweetPixelFraction = Math.log((exp0to1 * (Math.exp(1)-1)) +1);
+				if (postSweetPixelFraction>1.0)
+					postSweetPixelFraction=1.0;
+				if (postSweetPixelFraction<0.0)
+					postSweetPixelFraction=0.0;
+				double pixelPercent =  startSweetPixelFraction+sweetPixelFraction + postSweetPixelFraction*endSweetPixelFraction;   
+				return pixelPercent; 
+			}
+			else  //  it is linear above
+				return  startSweetPixelFraction+sweetPixelFraction+((value-maxSweetSpotValue)/(maxValue-maxSweetSpotValue))*endSweetPixelFraction;
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ListDialog.java b/Source/mesquite/lib/ListDialog.java
new file mode 100644
index 0000000..52c4965
--- /dev/null
+++ b/Source/mesquite/lib/ListDialog.java
@@ -0,0 +1,831 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.simplicity.*;
+
+/*===============================================*/
+/** A little dialog box with a list.*/
+public class ListDialog extends ExtensibleDialog implements ItemListener{
+	DoubleClickList list;
+	MesquiteInteger selected;
+	IntegerArray indicesSelected = new IntegerArray(0);
+	String[] strings = null;
+	Listable[] listables = null;
+	boolean[] isSubchoice = null;
+	Listable[] listablesUsed = null;
+	Listable[] originalListables = null;
+	boolean[] isSubchoiceUsed = null;
+	TextArea explanation = null;
+	//Button ok;
+	String thirdButton = null;
+	Checkbox hideSecondaryCheckbox;
+	
+	boolean hideSecondary;
+	Class priorityClass;
+	String hideSecString = "Hide Secondary Choices";
+	boolean prioritize = false;
+	boolean hasDefault=true;
+	WorkaroundThread thread;
+	boolean requiresResetWorkaround = true;
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, boolean[] isSubchoice, MesquiteInteger selected, String okButton, String cancelButton, String thirdButton, boolean prioritize, Class priorityClass, boolean hasDefault, boolean multipleMode) {
+		super(parent,title);
+		if (names instanceof Listable[]){
+			this.listables = (Listable[])names;
+		}
+		else if (names instanceof String[])
+			strings = (String[])names;
+		originalListables = listables;
+		listables = filterHiddenListables(listables);
+		listablesUsed = listables; 
+		this.selected = selected;
+		this.thirdButton =thirdButton;
+		this.prioritize = prioritize;
+		this.priorityClass=priorityClass;
+		this.hasDefault=hasDefault;
+		this.isSubchoice = isSubchoice;
+		this.isSubchoiceUsed = isSubchoice;
+		this.hideSecondary = !EmployerEmployee.secondaryChoicesOnInDialogs;
+		if (!priorityDifferenceExists()){
+			this.prioritize = false;
+			this.hideSecondary = false;
+		}
+
+		if (helpString!=null)
+			appendToHelpString(helpString);
+
+		if (message!= null) {
+			addLargeOrSmallTextLabel(message);
+		}
+
+		Panel mainPanel = addNewDialogPanel();
+		list = createListenedList (names, isSubchoice, selected, 16, this,this, multipleMode);
+		list.setForceSize(true);
+		mainPanel.add(list);
+
+		if (anyDocumentables(listables)){
+			explanation = addTextAreaSmallFont("", 4);
+			if (explanation.getParent() != null)
+				explanation.setBackground(ColorDistribution.brighter(explanation.getParent().getBackground(),0.5));
+			explanation.setEditable(false);
+		}
+
+
+		if (this.prioritize){
+			hideSecondaryCheckbox = addCheckBox(hideSecString, false);
+			hideSecondaryCheckbox.setState(hideSecondary);
+			hideSecondaryCheckbox.addItemListener(this);
+			requiresResetWorkaround = MesquiteTrunk.isMacOSX() && !MesquiteTrunk.isJavaVersionLessThan(1.5);
+			if (requiresResetWorkaround)
+				thread = new WorkaroundThread(this);
+			resetShowSecondary(hideSecondary);
+			if (requiresResetWorkaround)
+				thread.start();
+		}
+		else {
+			hideSecondaryCheckbox = null;
+			resetShowSecondary(false);
+		}
+
+
+		if (!StringUtil.blank(thirdButton)) 
+			setExtraButton(thirdButton);
+
+		setAutoDispose(false);
+
+		list.requestFocus();
+		list.requestFocusInWindow();
+		if (numSelected() == 1)
+			showExplanation(list.getSelectedIndex());
+
+		if (autoComplete){
+			String OK = defaultOKLabel;
+			if (!StringUtil.blank(okButton))
+				OK = okButton;
+			String cancel = defaultCancelLabel;
+			if (!StringUtil.blank(cancelButton))
+				cancel = cancelButton;
+			completeDialog(OK,cancel, hasDefault,this);
+		}
+		//ok = getMainButton();
+
+	}
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, MesquiteInteger selected, String okButton, String thirdButton, boolean prioritize, Class priorityClass, boolean hasDefault, boolean multipleMode) {
+		this(parent,title,message, autoComplete, helpString, names, null, selected,okButton,null, thirdButton,prioritize,priorityClass,hasDefault, multipleMode);
+	}
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, MesquiteInteger selected, String okButton, String cancelButton, String thirdButton, boolean prioritize, Class priorityClass, boolean hasDefault, boolean multipleMode) {
+		this(parent,title,message, autoComplete, helpString, names, null, selected,okButton,cancelButton, thirdButton,prioritize,priorityClass,hasDefault, multipleMode);
+	}
+
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, MesquiteInteger selected, String okButton,String thirdButton, boolean hasDefault, boolean multipleMode) {
+		this(parent,title,message, autoComplete, helpString, names,selected,okButton,thirdButton,false,null,hasDefault, multipleMode);
+	}
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, MesquiteInteger selected, String thirdButton, boolean hasDefault, boolean multipleMode) {
+		this(parent,title,message, autoComplete, helpString, names,selected,"OK",thirdButton,false,null,hasDefault, multipleMode);
+	}
+	public ListDialog (MesquiteWindow parent, String title, String message, boolean autoComplete, String helpString, Object names, MesquiteInteger selected, String thirdButton, boolean hasDefault, boolean multipleMode, String okButton, String cancelButton) {
+		this(parent,title,message, autoComplete, helpString, names,selected,okButton,cancelButton, thirdButton,false,null,hasDefault, multipleMode);
+	}
+	private Listable[] filterHiddenListables(Listable[] L){
+		Listable[] list = L;
+		if (list == null)
+			return null;
+		int count = 0;
+		for (int i=0; i< list.length; i++){
+			Listable item = list[i];
+			if (item != null)
+				if (item instanceof Listened && !((Listened)item).isUserVisible()){
+				}
+				else
+					count++;
+		}
+		Listable[] result = new Listable[count];
+		count = 0;
+		for (int i=0; i< list.length; i++){
+			Listable item = list[i];
+			if (item != null)
+				if (item instanceof Listened && !((Listened)item).isUserVisible()){
+				}
+				else {
+					result[count++] = item;
+				}
+		}
+		return result;
+	}
+	private void filterHiddenListablesForSimplicity(){
+		Listable[] list = listablesUsed;
+		if (list == null)
+			return;
+		if (!InterfaceManager.isSimpleMode())
+			return;
+		Listable[] v = new Listable[list.length];
+		int count = 0;
+		Vector sc = new Vector();
+		for (int i=0; i< list.length; i++){
+			Listable item = list[i];
+			if (item != null && item instanceof MesquiteModuleInfo){
+				if (!InterfaceManager.onHiddenClassList(((MesquiteModuleInfo)item).getClassName())){
+					v[count++] = item;
+					if (isSubchoiceUsed != null)
+						sc.addElement(new MesquiteBoolean(isSubchoiceUsed[i]));
+				}
+				else if (isSubchoiceUsed!= null && i<isSubchoiceUsed.length) {
+					if (!isSubchoiceUsed[i]){  //to be deleted, and not a subchoice.  Hence look for subchoices and delete them
+						for (int k = i+1; k<list.length && k<isSubchoiceUsed.length && isSubchoiceUsed[k]; k++){
+							list[k] = null; //zapping
+						}
+					}
+				}
+			}
+			else if (item != null)
+				if (!InterfaceManager.onHiddenClassList(item.getClass())){
+					v[count++] = item;
+					if (isSubchoiceUsed != null)
+						sc.addElement(new MesquiteBoolean(isSubchoiceUsed[i]));
+				}
+				else if (isSubchoiceUsed!= null && i<isSubchoiceUsed.length) {
+					if (!isSubchoiceUsed[i]){  //to be deleted, and not a subchoice.  Hence look for subchoices and delete them
+						for (int k = i+1; k< list.length && k<isSubchoiceUsed.length && isSubchoiceUsed[k]; k++){
+							list[k] = null; //zapping
+						}
+					}
+				}
+		}
+		Listable[] result = new Listable[count];
+		for (int i=0; i< count; i++)
+			result[i] = v[i];
+
+		if (isSubchoiceUsed != null){
+			boolean[] s = new boolean[count];
+			for (int i=0; i< count; i++)
+				s[i] = ((MesquiteBoolean)sc.elementAt(i)).getValue();
+			isSubchoiceUsed = s;
+		}
+		listablesUsed = result;
+	}
+	private boolean priorityDifferenceExists(){
+
+		if (listables!=null){
+			boolean secondPriorityFound = false;
+			boolean firstPriorityFound = false;
+			for (int i=0; i<listables.length; i++) {
+				if (listables[i]!=null){
+					if (listables[i] instanceof Prioritizable && !((Prioritizable)listables[i]).isFirstPriority(priorityClass)){
+						secondPriorityFound = true;
+						if (firstPriorityFound)
+							return true;
+					}
+					else {
+						firstPriorityFound = true;
+						if (secondPriorityFound)
+							return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+	public void setVisible(boolean vis){
+		if (!vis && requiresResetWorkaround && thread !=null)
+			thread.done = true;
+		super.setVisible(vis);
+	}
+	public void dispose(){
+		if (requiresResetWorkaround && thread !=null)
+			thread.done = true;
+		super.dispose();
+	}
+	boolean firstTouchWorkaround = false;
+	boolean redoResetWorkaround = false;
+
+	public synchronized void resetWorkaround(){
+		if (redoResetWorkaround){
+
+			list.setVisible(false);
+			list.setVisible(true);
+
+			list.requestFocus();
+			list.requestFocusInWindow();
+			list.invalidate();
+			list.validate();
+			invalidate();
+			validate();
+			list.repaint();
+			repaint();
+		}
+		//	else
+		//		resetShowSecondary(showSecondary);
+		redoResetWorkaround = false;
+
+	}
+	private boolean isPrimary(Listable[] listables, boolean[] isSubchoice, int i, Listable previousChoice){
+		if ((isSubchoice == null || isSubchoice[i]) && previousChoice != null && previousChoice instanceof MesquiteModuleInfo){
+			Class dutyClass = ((MesquiteModuleInfo)previousChoice).getHireSubchoice();
+			if (dutyClass != null)
+				return !(listables[i] instanceof Prioritizable) || ((Prioritizable)listables[i]).isFirstPriority(dutyClass);
+
+
+		}
+		return !(listables[i] instanceof Prioritizable) || ((Prioritizable)listables[i]).isFirstPriority(priorityClass);
+	}
+	private synchronized void resetShowSecondary(boolean hideSec){
+		if (listables!=null){
+
+			list.setVisible(false);
+			list.removeAll();
+			Listable previousChoice = null;
+			if (!hideSec && priorityDifferenceExists()) {
+				listablesUsed = listables;
+				isSubchoiceUsed = isSubchoice;
+			}
+			else {
+				int count = 0;
+				boolean previousChoiceShown = isSubchoice == null;
+				if (listables.length > 0)
+					previousChoice = listables[0];
+				for (int i=0; i<listables.length; i++) {
+					if (listables[i]!=null && (!hideSec || isPrimary(listables, isSubchoice, i, previousChoice))){
+						if (! (isSubchoice != null && isSubchoice[i] && !previousChoiceShown)){  //don't show if subchoice and previous not shown
+							count++;
+							if (isSubchoice != null && !isSubchoice[i]) {
+								previousChoiceShown = true;
+								previousChoice = listables[i];
+							}
+						}
+					}
+					else if (isSubchoice != null && !isSubchoice[i])
+						previousChoiceShown = false;
+				}
+				listablesUsed = new Listable[count];
+				if (isSubchoice != null)
+					isSubchoiceUsed = new boolean[count];
+				count = 0;
+				previousChoiceShown = isSubchoice == null;
+				if (listables.length > 0)
+					previousChoice = listables[0];
+
+				for (int i=0; i<listables.length; i++) {
+					if (listables[i]!=null && (!hideSec || isPrimary(listables, isSubchoice, i, previousChoice))){
+						if (! (isSubchoice != null && isSubchoice[i] && !previousChoiceShown)){  //don't show if subchoice and previous not shown
+							if (isSubchoice != null)
+								isSubchoiceUsed[count] = isSubchoice[i];
+							listablesUsed[count++] = listables[i];
+							if (isSubchoice != null && !isSubchoice[i]){
+								previousChoiceShown = true;
+								previousChoice = listables[i];
+							}
+						}
+					}
+					else if (isSubchoice != null && !isSubchoice[i])
+						previousChoiceShown = false;
+				}
+			}
+			int wasLength = listablesUsed.length;
+			filterHiddenListablesForSimplicity();
+			if (listablesUsed.length == 0 && wasLength > 0){
+				list.add("(No choices are available.");
+				list.add("     All choices are hidden because");
+				list.add("     a simplified interface is in use.");
+				list.add("     Please go to the Simplification tab");
+				list.add("     of log window to adjust interface.)");
+			}
+			else {
+				for (int i=0; i<listablesUsed.length; i++) {
+					String name = "";
+					if (listablesUsed[i] instanceof SpecialListName && ((SpecialListName)listablesUsed[i]).getListName()!=null)
+						name = ((SpecialListName)listablesUsed[i]).getListName();
+					else if (listablesUsed[i].getName()!=null)
+						name = listablesUsed[i].getName();
+					if (isSubchoiceUsed != null && isSubchoiceUsed[i])
+						name = "  - " + name;
+					list.add(StringUtil.truncateIfLonger(name, maxLengthInList), -1);
+				}
+				if (selected!=null && selected.getValue()>=0 && selected.getValue()<listables.length)
+					list.select(selected.getValue());
+				if (numSelected() == 1)
+					showExplanation(list.getSelectedIndex());
+			}
+
+
+			list.setVisible(true);
+			list.requestFocus();
+			list.invalidate();
+			list.validate();
+			invalidate();
+			validate();
+			list.repaint();
+			repaint();
+
+		}
+	}
+	protected void resetList(){
+		if (listables!=null){
+			resetShowSecondary(hideSecondary);
+		}
+		else if (strings!=null){
+			list.setVisible(false);
+			int vis = list.getVisibleIndex();
+			boolean[] sel = new boolean[list.getItemCount()];
+			for (int i = 0; i<list.getItemCount(); i++){
+				sel[i] = list.isIndexSelected(i);
+			}
+			list.removeAll();
+			for (int i=0; i<strings.length; i++)
+				if (strings[i]!=null)
+					list.add(strings[i], -1);
+			for (int i = 0; i<sel.length && i < list.getItemCount(); i++){
+				if (sel[i])
+					list.select(i);
+			}
+			if (selected!=null && selected.getValue()>=0 && selected.getValue()<strings.length)
+				list.select(selected.getValue());
+			if (numSelected() == 1)
+				showExplanation(list.getSelectedIndex());
+			list.makeVisible(vis);
+			list.setVisible(true);
+			list.invalidate();
+			list.validate();
+			invalidate();
+			validate();
+			list.repaint();
+		}
+	}
+
+	private boolean anyDocumentables(Listable[] L){
+		if (L==null)
+			return false;
+		for (int i=0; i<L.length; i++)
+			if (L[i] instanceof Explainable)
+				return true;
+		return false;
+	}
+	protected int numSelected(){
+		int count = 0;
+		for (int i=0; i<list.getItemCount(); i++)
+			if (list.isIndexSelected(i))
+				count++;
+		return count;
+	}
+	private void setSelected(boolean[] selected){
+		if (selected == null)
+			return;
+		for (int i=0; i<list.getItemCount(); i++)
+			list.deselect(i);
+
+		for (int i=0; i<list.getItemCount() && i<selected.length; i++)
+			if (selected[i])
+				list.select(i);
+	}
+	private void showExplanation(int selected){
+		if (selected <0) {
+			if (explanation !=null) {
+				explanation.setText("");
+				return;
+			}
+		}
+		else if (listablesUsed !=null && selected < listablesUsed.length && listablesUsed[selected] instanceof Explainable) {
+			if (explanation !=null) {
+				String exp = ((Explainable)listablesUsed[selected]).getExplanation();
+				if (exp == null)
+					exp = "";
+				explanation.setText(exp);
+				return;
+			}
+		}
+		if (explanation !=null) 
+			explanation.setText("");
+	}
+	public void itemStateChanged(ItemEvent e){
+		if (listablesUsed==null)
+			return;
+		if (e.getItem() instanceof String && hideSecString.equals((String)e.getItem())){
+			hideSecondary = hideSecondaryCheckbox.getState();
+			resetShowSecondary(hideSecondary);
+			redoResetWorkaround = true;
+		}
+		else if (e.getStateChange() == ItemEvent.SELECTED && e.getItem() instanceof Integer){
+			if (numSelected() > 1)
+				showExplanation(-1);
+			else {
+				showExplanation(((Integer)e.getItem()).intValue());
+			}
+		}
+	}
+	/*	public void actionPerformed(ActionEvent e){
+		if (defaultButtonString!=null) {
+			buttonHit(defaultButtonString, null);
+			dispose();
+		}
+	}
+	 */
+	public static Listable queryList(MesquiteWindow parent, String title, String message, String helpString, ListableVector vector, int current, boolean doShow) {
+		if (vector==null) 
+			return null;
+		MesquiteInteger io = new MesquiteInteger(current);
+		Listable[] names = vector.getListables();
+		String thirdButton = null;
+		if (doShow)
+			thirdButton = " Show ";
+		while (true) {
+			ListDialog id = new ListDialog(parent, title, message, true, helpString, names, io, thirdButton,true, false);
+
+			id.setVisible(true);
+			if (io.isUnassigned()) {
+				id.dispose();
+				return null;
+			}
+			int result = io.getValue();
+			if (result <0) { //negative value; must be asking to show
+				result = - result - 1;  
+				if (result>=0 && result<vector.size()) {
+					Listable li =  (Listable)vector.elementAt(result);
+					if (li instanceof Showable) {
+						((Showable)li).showMe();
+					}
+					io.setValue(result);
+				}
+			}
+			else if (result>=0 && result<vector.size()) {
+				id.dispose();
+				MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + ((Listable)vector.elementAt(result)).getName());
+				return (Listable)vector.elementAt(result);
+			}
+			else {
+				id.dispose();
+				return null;
+			}
+		}
+	}
+	//TODO: probably better if all of these return array of selected!
+	public static Listable queryList(MesquiteWindow parent, String title, String message, String helpString, ListableVector vector, int current) {
+		if (vector==null) 
+			return null;
+		MesquiteInteger io = new MesquiteInteger(current);
+		Listable[] names = vector.getListables();
+		if (names==null)
+			return null;
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, names, io, null,true, false);
+		id.setVisible(true);
+		if (id!=null)
+			id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return null;
+		if (result>=0 && result<vector.size()){
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + ((Listable)vector.elementAt(result)).getName());
+			return (Listable)vector.elementAt(result);
+		}
+		else return null;
+	}
+	public static Listable[] queryListMultiple(MesquiteWindow parent, String title, String message, String helpString, ListableVector vector, boolean[] selected) {
+		return queryListMultiple(parent, title, message, helpString, null, true, vector, selected);
+	}
+	public static Listable[] queryListMultiple(MesquiteWindow parent, String title, String message, String helpString, String okButton, boolean hasDefault, ListableVector vector, boolean[] selected) {
+		if (vector==null) 
+			return null;
+		Listable[] names = vector.getListables();
+		if (names==null)
+			return null;
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, names, null, okButton,null,hasDefault, true);
+		//		if (okButton!=null)
+		//		id.ok.setLabel(okButton);
+		id.list.setMultipleMode(true);
+		id.setSelected(selected);
+		id.setVisible(true);
+		IntegerArray result = id.indicesSelected;
+		if (result==null || result.getSize()==0) {
+			id.dispose();
+			return null;
+		}
+		Listable[] L = new Listable[result.getSize()];
+		for (int i=0; i<result.getSize(); i++)
+			L[i] = (Listable)vector.elementAt(result.getValue(i));
+		id.dispose();
+		return L;
+	}
+	public static int queryModuleList(MesquiteModule employer, String title, String message, String helpString, Listable[] objects, boolean[] isSubchoice, boolean prioritize, Class priorityClass, int current) {
+		if (objects==null) 
+			return MesquiteInteger.unassigned;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(employer.containerOfModule(), title, message, true,helpString, objects, isSubchoice, io, null, null,null,prioritize, priorityClass, true, false);
+
+		id.setVisible(true);
+		id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return MesquiteInteger.unassigned;
+		if (result>=0 && result<objects.length) ///ERROR here it's returning item in original list even if prioritized!!!!!!!!!!
+			return result;
+		else return MesquiteInteger.unassigned;
+	}
+	public static int queryList(MesquiteWindow parent, String title, String message, String helpString, Listable[] objects, boolean[] isSubchoice, boolean prioritize, Class priorityClass, int current) {
+		if (objects==null) 
+			return MesquiteInteger.unassigned;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, objects, isSubchoice, io, null,null,null,prioritize, priorityClass, true, false);
+		id.setVisible(true);
+		id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return MesquiteInteger.unassigned;
+		if (result>=0 && result<objects.length){ ///ERROR here it's returning item in original list even if prioritized!!!!!!!!!!
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + objects[result].getName());
+			return result;
+		}
+		else return MesquiteInteger.unassigned;
+	}
+	public static Listable queryModuleList(MesquiteModule employer, String title, String message, String helpString, Listable[] objects, boolean prioritize, Class priorityClass, int current) {
+		if (objects==null) 
+			return null;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(employer.containerOfModule(), title, message, true,helpString, objects, io, null,null,prioritize, priorityClass, true, false);
+
+		id.setVisible(true);
+		id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return null;
+		if (result>=0 && result<objects.length){ ///ERROR here it's returning item in original list even if prioritized!!!!!!!!!!
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + objects[result].getName());
+			return objects[result];
+		}
+		else return null;
+	}
+	public static Listable queryList(MesquiteWindow parent, String title, String message, String helpString, Listable[] objects, boolean prioritize, Class priorityClass, int current) {
+		if (objects==null) 
+			return null;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, objects, io, null,null,prioritize, priorityClass, true, false);
+		id.setVisible(true);
+		id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return null;
+		if (result>=0 && result<objects.length){ ///ERROR here it's returning item in original list even if prioritized!!!!!!!!!!
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + objects[result].getName());
+			return objects[result];
+		}
+		else return null;
+	}
+	public static Listable queryList(MesquiteWindow parent, String title, String message, String helpString, Listable[] objects, int current) {
+		if (objects==null) 
+			return null;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, objects, io, null,true, false);
+		id.setVisible(true);
+		id.dispose();
+		int result = io.getValue();
+		if (io.isUnassigned())
+			return null;
+		if (result>=0 && result<objects.length){
+				MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + objects[result].getName());
+			return objects[result];
+		}
+		else return null;
+	}
+	public static int queryList(MesquiteWindow parent, String title, String message, String helpString, Context[] contexts, int current, boolean doShow) {
+		if (contexts==null)
+			return MesquiteInteger.unassigned;
+		MesquiteInteger io = new MesquiteInteger(current);
+		String[] names = new String[contexts.length];
+		for (int i = 0; i<names.length; i++)
+			names[i]=contexts[i].getContextName();
+
+		String thirdButton = null;
+		if (doShow)
+			thirdButton = "Show"; //NOTE about a kludge: the name of this button needs to remain "show".  See buttonHit in ListDialog
+		while (true) {
+			ListDialog id = new ListDialog(parent, title, message, true,helpString, names, io, thirdButton,true, false);
+
+			id.setVisible(true);
+			id.dispose();
+			if (io.isUnassigned())
+				return MesquiteInteger.unassigned;
+			int result = io.getValue();
+			if (result <0) { //negative value; must be asking to show
+				result = - result - 1;  
+				if (result>=0 && result<contexts.length) {
+					Context li =  contexts[result];
+					if (li instanceof Showable) {
+						((Showable)li).showMe();
+					}
+					io.setValue(result);
+				}
+			}
+			else if (result>=0 && result<contexts.length)
+				return result;
+
+			else return MesquiteInteger.unassigned;
+		}
+	}
+	public static int queryList(MesquiteWindow parent, String title, String message, String helpString, String[] names, int current, String okButton, String cancelButton) {
+		if (names==null)
+			return MesquiteInteger.unassigned;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, names, io, null,true, false, okButton, cancelButton);
+		id.setVisible(true);
+		id.dispose();
+		if (io.isCombinable() && io.getValue()>=0 && io.getValue()<names.length)
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + names[io.getValue()]);
+		return io.getValue();
+	}
+	public static int queryList(MesquiteWindow parent, String title, String message, String helpString, String[] names, int current) {
+		if (names==null)
+			return MesquiteInteger.unassigned;
+		MesquiteInteger io = new MesquiteInteger(current);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, names, io, null,true, false);
+		id.setVisible(true);
+		id.dispose();
+		if (io.isCombinable() && io.getValue()>=0 && io.getValue()<names.length)
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + names[io.getValue()]);
+		return io.getValue();
+	}
+	public static String queryList(MesquiteWindow parent, String title, String message, String helpString, Class dutyClass, Object condition, MesquiteModule prospectiveEmployer) {
+		Listable[] names = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(dutyClass, condition, prospectiveEmployer);
+		if (names==null)
+			return null;
+		MesquiteInteger io = new MesquiteInteger(0);
+		ListDialog id = new ListDialog(parent, title, message, true,helpString, names, io, null,true, false);
+		id.setVisible(true);
+		id.dispose();
+		if (io.isUnassigned())
+			return null;
+		if (io.getValue()>=0){
+			MesquiteTrunk.mesquiteTrunk.logln("Chosen: " + names[io.getValue()].getName());
+			return names[io.getValue()].getName();
+		}
+		else
+			return null;
+	}
+	protected DoubleClickList getList(){
+		return list;
+	}
+	private int[] translateIndicesUsedToOriginal(int[] indices){
+		if (indices !=null && listablesUsed !=null && listablesUsed != originalListables){
+			int count = 0;
+			for (int i=0; i< indices.length; i++){
+				if (translateIndexUsedToOriginal(indices[i]) >=0)
+					count++;
+			}
+			if (count == 0)
+				return indices;
+			int[] usedIndices = new int[count];
+			count =0;
+			for (int i=0; i< indices.length; i++){
+				int used = translateIndexUsedToOriginal(indices[i]);
+				if (used >=0)
+					usedIndices[count++] = used;
+			}
+			return usedIndices;
+		}
+		return indices;
+	}
+	private int findListable(Listable[] lArray, Listable target){
+		if (lArray==null)
+			return -1;
+		for (int i=0; i< lArray.length; i++)
+			if (target == lArray[i])
+				return i;
+		return -1;
+	}
+	private int translateIndexUsedToOriginal(int index){
+		if (listablesUsed !=null && listablesUsed != originalListables && index>0 && index < originalListables.length && index < listablesUsed.length){
+			Listable listable = listablesUsed[index];
+			int which = findListable(originalListables, listable);
+			return which;
+		}
+		return index;
+	}
+	/*.................................................................................................................*/
+	public void doubleClicked(Component c){
+		if (c==list) {
+			try {
+				try {   
+					Thread.sleep(100);   // for reasons that are entirely unclear, putting this in here prevents the Java 1.6/MacOS X 10.6.2 crash
+					// that happens if one doubleclicks in a list to set up a Maj Rule consensus tree and the like
+				} 
+				catch (Exception e) {
+				}
+				if (selected!=null) {
+					selected.setValue(translateIndexUsedToOriginal(list.getSelectedIndex()));
+				}
+				indicesSelected.setValues(translateIndicesUsedToOriginal(list.getSelectedIndexes()));
+			}
+			catch (NumberFormatException eq){}
+			dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	public void buttonHit(String buttonLabel, Button button) {
+		if (buttonLabel!=null)
+			if (buttonLabel.equalsIgnoreCase(getMainButton().getLabel())){
+				try {
+					if (selected!=null) {
+						selected.setValue(translateIndexUsedToOriginal(list.getSelectedIndex()));
+					}
+					indicesSelected.setValues(translateIndicesUsedToOriginal(list.getSelectedIndexes()));
+				}
+				catch (NumberFormatException eq){}
+
+				dispose();
+			}
+			else if (buttonLabel.equalsIgnoreCase("Show")){
+				int i = translateIndexUsedToOriginal(list.getSelectedIndex());
+				if (i>=0 && selected!=null) 
+					selected.setValue(-i-1); //if nothing selected do not respond!
+				dispose();
+			}
+			else if (buttonLabel.equalsIgnoreCase(thirdButton)){
+				selected.setValue(-1); 
+			}
+			else {
+				if (selected!=null)
+					selected.setToUnassigned();
+				indicesSelected.setValues(null);
+				//if (autoDispose || buttonLabel.equalsIgnoreCase("Cancel"))
+				dispose();
+			}
+	}
+}
+
+class WorkaroundThread extends Thread { //workaround for bug in Java 1.5 on OS X
+	ListDialog dlog;
+	boolean done = false;
+	public WorkaroundThread(ListDialog dlog){
+		this.dlog = dlog;
+	}
+	public void run(){
+		int count = 0;
+		while (!done && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting){
+			try {
+				Thread.sleep(20);
+				count++;
+				if (dlog.redoResetWorkaround){
+					dlog.resetWorkaround();
+					count = 0;
+				}
+				else if (count % 25 == 0 && dlog.firstTouchWorkaround){
+					dlog.redoResetWorkaround = true;
+				}
+			}
+			catch (InterruptedException e){
+				done = true;
+			}
+
+		}
+	}
+}
diff --git a/Source/mesquite/lib/Listable.java b/Source/mesquite/lib/Listable.java
new file mode 100644
index 0000000..4db38d0
--- /dev/null
+++ b/Source/mesquite/lib/Listable.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is listable, e.g. in List windows*/
+public interface Listable {
+ 	public String getName();
+}
+
diff --git a/Source/mesquite/lib/ListableVector.java b/Source/mesquite/lib/ListableVector.java
new file mode 100644
index 0000000..1ae0875
--- /dev/null
+++ b/Source/mesquite/lib/ListableVector.java
@@ -0,0 +1,851 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.text.*;
+import java.util.*;
+
+import mesquite.lib.characters.CharacterStates;
+import mesquite.lib.characters.CodonPositionsSet;
+
+/* ======================================================================== */
+/*Vector of listable objects along with a simple, currently stupid system to display the list*/
+public class ListableVector extends FileElement implements StringLister, Commandable, MesquiteListener {
+	Vector vec;
+	protected boolean notifyOfChanges = true;
+	public static int totalCreated = 0;
+	public static int totalDisposed = 0;
+	public static int totalFinalized = 0;
+	public static long totalElementsAdded = 0;
+	MesquiteListWindow listWindow;
+	public ListableVector() {
+		super(0);
+		totalCreated++;
+		vec = new Vector();
+	}
+	public ListableVector(int initCapacity) {
+		super(0);
+		totalCreated++;
+		vec = new Vector(initCapacity);
+	}
+	public String toHTMLStringDescription(){
+		if (size() == 0)
+			return "";
+		String sH = "";
+		
+		for (int i=0; i<size(); i++){
+			Listable e = elementAt(i);
+			
+
+			if (e instanceof HTMLDescribable){
+				String sT =  ((HTMLDescribable)e).toHTMLStringDescription();
+				if (!StringUtil.blank(sT))
+					sH += sT;
+				else
+					sH += "<li>" + e.getName() + "</li>";
+			}
+			else 
+				sH += "<li>" + e.getName() + "</li>";
+
+				
+		}
+	//	if (StringUtil.blank(s))
+	//		return "";
+		return "<li>" + getTypeName() + " (" + size() + " units)<ul>" + sH + "</ul>" + super.toHTMLStringDescription() + "</li>";
+	}
+	public void dispose(){
+		removeAllElements(false);
+		totalDisposed++;
+		super.dispose();
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	
+	public String getTypeName(){
+		return "Listable Vector";
+	}
+	public Listable getElement(String name){
+		if (name==null)
+			return null;
+		for (int i=0; i<size(); i++) {
+			Listable obj = elementAt(i);
+			if (name.equals(obj.getName()))
+				return obj;
+		}
+		return null;
+	}
+	
+	public Vector getElements(String name){
+		if (name==null)
+			return null;
+		Vector list = new Vector();
+		for (int i=0; i<size(); i++) {
+			Listable obj = elementAt(i);
+			if (name.equals(obj.getName()))
+				list.addElement(obj);
+		}
+		return list;
+	}
+	public Listable getElementIgnoreCase(String name){
+		if (name==null)
+			return null;
+		for (int i=0; i<size(); i++) {
+			Listable obj = elementAt(i);
+			if (name.equalsIgnoreCase(obj.getName()))
+				return obj;
+		}
+		return null;
+	}
+	public String[] getStringArrayList(){
+		String[] temp = new String[size()];
+		for (int i=0; i<size(); i++) {
+			Object obj = elementAt(i);
+			if (obj instanceof SpecialListName)
+				temp[i]= ((SpecialListName)obj).getListName();
+			else
+				temp[i]= ((Listable)obj).getName();
+		}
+		return temp;
+	}
+	public String getList(){
+		String temp = "";
+		for (int i=0; i<size(); i++) {
+			Object obj = elementAt(i);
+			if (obj instanceof SpecialListName)
+				temp += ((SpecialListName)obj).getListName() + StringUtil.lineEnding();
+			else
+				temp += ((Listable)obj).getName() + StringUtil.lineEnding();
+		}
+		return temp;
+	}
+	public String nameOfElementAt(int i){
+		Object obj = elementAt(i);
+		if (obj == null)
+			return null;
+		if (obj instanceof SpecialListName)
+			return ((SpecialListName)obj).getListName();
+		else
+			return ((Listable)obj).getName();
+	}
+	public Listable[] getElementArray(){
+		Listable[] temp =  new Listable[size()];
+		for (int i=0; i<size(); i++)
+			temp[i] = (Listable)elementAt(i);
+		return temp;
+	}
+	public String getUniqueName(String base){
+		if (size()==0)
+			return base;
+		else {
+			int count =1;
+			while (true){
+				
+				String candidate;
+				if (count==1)
+					candidate = base;
+				else
+					candidate = base + count;
+				if (getElementIgnoreCase(candidate)==null)
+					return candidate;
+				count++;
+			}
+		}
+	}
+	public boolean uniqueName(String name){
+		if (size()==0 || name==null)
+			return false;
+		else {
+			int count=0;
+			for (int i=0; i<size(); i++)
+				if (name.equals(((Listable)elementAt(i)).getName())){
+					count++;
+					if (count>1)
+						return false;
+				}
+			return count==1;
+		}
+	}
+	public boolean nameAlreadyInList(String name, int dontCountItem){
+		if (size()==0 || name==null)
+			return false;
+		else {
+			for (int i=0; i<size(); i++)
+				if (i!=dontCountItem && name.equals(((Listable)elementAt(i)).getName())){
+					return true;
+				}
+			return false;
+		}
+	}
+	public boolean nameAlreadyInList(String name){
+		return nameAlreadyInList (name, -1);
+	}
+	public boolean allNamesUnique(){
+		if (size()==0)
+			return true;
+		else {
+			String s;
+			Listable listable;
+			for (int i=0; i<size(); i++) {
+				s = ((Listable)elementAt(i)).getName();
+				if (s!=null)
+					for (int j=i+1; j<size(); j++) {
+						listable = (Listable)elementAt(j);
+						if (listable!=null)
+							if (s.equals(listable.getName()))
+								return false;
+					}
+			}
+			return true;
+		}
+	}
+	public static String[] getStrings(Listable[] objects){
+		if (objects==null)
+			return null;
+		else {
+			String[] s = new String[objects.length];
+			for (int i=0; i<objects.length; i++) {
+				if ( objects[i]!=null)
+					s[i] = objects[i].getName();
+			}
+			return s;
+		}
+	}
+	public Listable[] getListables(){
+		Listable[] temp = new Listable[size()];
+		for (int i=0; i<size(); i++)
+			temp[i]= (Listable)elementAt(i);
+		return temp;
+	}
+	public String[] getStrings(){
+		String[] temp = new String[size()];
+		for (int i=0; i<size(); i++)
+			temp[i]= ((Listable)elementAt(i)).getName();
+		return temp;
+	}
+	public static String toString(Listable[] names){
+		if (names==null)
+			return null;
+		String s = "[ ";
+		for (int i=0; i<names.length; i++)
+			if (names[i] !=null)
+				s += " \"" + names[i].getName() + "\" ";
+		return s + " ]";
+	}
+	/*-------------ListableVector----------------*/
+	public void addElements(ListableVector objects, boolean notify) {
+		if (objects == null)
+			return;
+		for (int i = 0; i< objects.size(); i++)
+			addElement(objects.elementAt(i), false);
+		numElements = vec.size();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+	}
+	/*-------------ListableVector----------------*/
+	private void addElement(Listable obj) {
+		int code = 0;
+		try {
+			if (vec.indexOf(obj)>=0){
+				if (MesquiteTrunk.debugMode)
+					MesquiteMessage.println("adding object to ListableVector that is already present " + obj.getName() + " " + obj.getClass());
+				return;
+			}
+			code = 0;
+			totalElementsAdded++;
+			addParts(size(), 1);
+			code = 1;
+			vec.addElement(obj);
+			numElements = vec.size();
+			code = 2;
+		}
+		catch(OutOfMemoryError e){
+			MesquiteMessage.println("OutOfMemoryError in ListableVector addElement (code " + code + ").  See file memory.txt in the Mesquite_Folder.");
+		}
+	}
+	/*-------------ListableVector----------------*/
+	public void addElement(Listable obj, boolean notify) {
+		if (obj==null) {
+			MesquiteMessage.warnProgrammer("null object added to ListableVector " + this.getClass().toString());
+			MesquiteMessage.printStackTrace();
+			return;
+		}
+		addElement(obj);
+		if (listWindow!=null)
+			listWindow.table.setNumRows(listWindow.table.numRowsTotal+1);
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+	}
+	
+	/*-------------ListableVector----------------*/
+	public void insertElementAt(Listable obj, int index, boolean notify) {
+		if (obj==null) {
+			MesquiteMessage.warnProgrammer("null object inserted to ListableVector " + this.getClass().toString());
+			MesquiteMessage.printStackTrace();
+			return;
+		}
+		addParts(index-1, 1);
+		vec.insertElementAt(obj, index);
+		numElements = vec.size();
+		if (listWindow!=null)
+			listWindow.table.setNumRows(listWindow.table.numRowsTotal-1);
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+	}
+	/*-------------ListableVector----------------*/
+	public void replaceElements(ListableVector newV, boolean notify) {
+		if (newV!=null) {
+			removeAllElements(false);
+			//vec.setCapacity(newV.size());
+			for (int i=0; i<newV.size(); i++)
+				addElement((Listable)newV.elementAt(i));
+			numElements = vec.size();
+			if (listWindow!=null)
+				listWindow.table.setNumRows(newV.size());
+			if (notify)
+				notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+		}
+	}
+	/*-------------ListableVector----------------*/
+	public void replaceElement(Listable old, Listable replacement, boolean notify) {
+		if (replacement!=null && old !=null && indexOf(old)>=0) {
+			int index = indexOf(old);
+			removeElement(old, false);
+			vec.insertElementAt(replacement, index);
+			if (notify)
+				notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+		}
+	}
+	/*-------------ListableVector----------------*/
+	public void removeElement(Listable obj, boolean notify) {
+		if (obj==null)
+			return;
+		if (vec.indexOf(obj)>=0)
+			deleteParts(vec.indexOf(obj), 1);
+		vec.removeElement(obj);
+		numElements = vec.size();
+		if (vec.indexOf(obj)>=0)
+			MesquiteMessage.warnProgrammer("object removed from listableVector but other copy remains " + this.getClass().toString() + "  " + obj);
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+	}
+	/*-------------ListableVector----------------*/
+	public void removeElementAt(int i, boolean notify) {
+		removeElement(elementAt(i), notify);
+	}
+	
+	/*-------------ListableVector----------------*/
+	public void removeAllElements(boolean notify){
+		vec.removeAllElements();
+		numElements = vec.size();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+	}
+	/*...........................................................*/
+	public boolean swapParts(int first, int second) {
+		if (first<0 || first>=size() || second<0 || second>=size()) 
+			return false;
+		mesquite.lib.duties.ElementManager m = null;
+		if (elementAt(first) instanceof FileElement)
+			m = ((FileElement)elementAt(first)).getManager();
+		
+		Object objFirst = vec.elementAt(first);
+		Object objSecond = vec.elementAt(second);
+		vec.setElementAt(objSecond, first);
+		vec.setElementAt(objFirst, second);
+		if (m != null)
+			m.elementsReordered(this);
+		return super.swapParts(first, second);
+		
+	}
+	/*...........................................................*/
+	public boolean moveParts(int starting, int num, int justAfter) {
+		if (num<=0 || starting>=size() || (justAfter>=starting && justAfter<=starting+num-1)) 
+			return false;
+		if (justAfter>=size())
+			justAfter = size()-1;
+		if (justAfter<0)
+			justAfter = -1;
+		mesquite.lib.duties.ElementManager m = null;
+		if (elementAt(0) instanceof FileElement)
+			m = ((FileElement)elementAt(0)).getManager();
+		
+		Vector newValues = new Vector(size());
+		if (starting>justAfter){
+			for (int i=0; i<=justAfter; i++)
+				newValues.addElement(elementAt(i));
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues.addElement(elementAt(i));
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues.addElement(elementAt(i));
+			for (int i=starting+num; i<size(); i++)
+				newValues.addElement(elementAt(i));
+		}
+		else {
+			for (int i=0; i<=starting-1; i++)
+				newValues.addElement(elementAt(i));
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues.addElement(elementAt(i));
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues.addElement(elementAt(i));
+			for (int i=justAfter+1; i<size(); i++)
+				newValues.addElement(elementAt(i));
+		}
+		vec.removeAllElements();
+		for (int i=0; i<newValues.size(); i++)
+			vec.addElement(newValues.elementAt(i));
+		numElements = vec.size();
+		if (m != null)
+			m.elementsReordered(this);
+		boolean moved = super.moveParts(starting, num, justAfter);
+		if (false)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+		return moved;
+	}
+ 	/*.................................................................................................................*/
+	/** notifies listeners that element has been disposed*/
+	public void notifyListenersOfDisposed(Object disp){ //{ ��� need in file element removeal to have all in one (dispose & remove) thjat calls this
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+	 			listener.disposing(disp);
+			}
+		}
+	}
+	int numElements = 0;
+	public int size() {
+		if (vec != null)
+			numElements =  vec.size();
+		return numElements;
+	}
+	/** returns number of elements whose classes are subclasses of c */
+	public int size(Class c) {
+		if (c==null)
+			return 0;
+		int count =0;
+		Enumeration e = vec.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (c.isAssignableFrom(obj.getClass()))
+				count ++;
+		}
+		return count;
+	}
+	public Listable elementAt(int i) {
+		if (i<0 || i>=size())
+			return null;
+		return (Listable)vec.elementAt(i);
+	}
+	public Listable elementWithName(String name){
+		if (name==null)
+			return null;
+		for (int i=0; i<size(); i++) {
+			Listable obj = elementAt(i);
+			if (name.equals(obj.getName()))
+				return obj;
+		}
+		return null;
+	}
+	public Enumeration elements() {
+		return vec.elements();
+	}
+	public int indexOfClass(Class c){
+		if (c==null)
+			return -1;
+		for (int i=0; i<size(); i++) {
+			Object obj = vec.elementAt(i);
+			if (obj != null && obj.getClass() == c)
+				return i;
+		}
+		return -1;
+	}
+	public Listable[] elementsOfClass(Class c){
+		if (c==null)
+			return null;
+		int count = 0;
+		for (int i=0; i<size(); i++) {
+			Object obj = vec.elementAt(i);
+			if (obj != null && obj.getClass() == c)
+				count++;
+		}
+		if (count == 0)
+			return null;
+		Listable[] list = new Listable[count];
+		count = 0;
+		for (int i=0; i<size(); i++) {
+			Object obj = vec.elementAt(i);
+			if (obj != null && obj.getClass() == c) {
+				list[count]= (Listable)obj;
+				count++;
+			}
+		}
+		return list;
+	}
+	/*Returns any elements of interface OwnedByModule which claim to have module as owner */
+	public Listable[] myElements(MesquiteModule module){
+		if (module==null)
+			return null;
+		int count = 0;
+		for (int i=0; i<size(); i++) {
+			Object obj = vec.elementAt(i);
+			if (obj != null && obj instanceof OwnedByModule && ((OwnedByModule)obj).getOwnerModule() == module)
+				count++;
+		}
+		if (count == 0)
+			return null;
+		Listable[] list = new Listable[count];
+		count = 0;
+		for (int i=0; i<size(); i++) {
+			Object obj = vec.elementAt(i);
+			if (obj != null && obj instanceof OwnedByModule && ((OwnedByModule)obj).getOwnerModule() == module) {
+				list[count]= (Listable)obj;
+				count++;
+			}
+		}
+		return list;
+	}
+	public int indexOf(Object obj){
+		if (obj==null)
+			return -1;
+		return vec.indexOf(obj);
+	}
+	public static int indexOf(Listable[] list, Object obj){
+		if (obj==null || list == null)
+			return -1;
+		for (int i=0; i<list.length; i++)
+			if (obj == list[i])
+				return i;
+		return -1;
+	}
+	public static int indexOf(Listable[] list, String name){
+		if (list == null)
+			return -1;
+		for (int i=0; i<list.length; i++) {
+			String iName = list[i].getName();
+			if (list[i]!=null && (iName==name || (iName != null && iName.equals(name))))
+				return i;
+		}
+		return -1;
+	}
+	public static int indexOfByName(Vector v, Object target){
+		if (target == null || v == null)
+			return -1;
+		String name = null;
+		if (target instanceof String)
+			name = (String)target;
+		else if (target instanceof Listable)
+			name = ((Listable)target).getName();
+			else 
+			return -1;
+		if (name == null)
+			return -1;
+		for (int i=0; i<v.size(); i++) {
+			Object obj = v.elementAt(i);
+			if (obj instanceof Listable)
+				
+				if (name.equals(((Listable)obj).getName()))
+					return i;
+		}
+		return -1;
+	}
+	public  int indexOfByName(String name){
+		if (name==null)
+			return -1;
+		for (int i=0; i<size(); i++) {
+			Object obj = elementAt(i);
+			if (name.equals(((Listable)obj).getName()))
+				return i;
+		}
+		return -1;
+	}
+	public int indexOfByNameIgnoreCase(String name){
+		if (name==null)
+			return -1;
+		for (int i=0; i<size(); i++) {
+			Object obj = elementAt(i);
+			if (name.equalsIgnoreCase(((Listable)obj).getName()))
+				return i;
+		}
+		return -1;
+	}
+	public void showList(String title){
+		listWindow = new MesquiteListWindow(title, MesquiteTrunk.mesquiteTrunk, this, false);
+	}
+	public void showList(String title, MesquiteModule ownerModule){
+		listWindow = new MesquiteListWindow(title, ownerModule, this, false);
+	}
+	static int endSequenceByThree(Listable[] listArray1, Object obj1,NumberArray numberArray2, int number2, int ic){
+		int previousThird = ic;
+		for (int ik = ic+1; ik< listArray1.length&& ik< numberArray2.getNumParts(); ik++){
+			Object thisObj1 = listArray1[ik];
+			int num2= numberArray2.getInt(ik);
+			if (thisObj1 == obj1 && number2==num2) {
+				//is a match; if not modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 !=0)
+					return previousThird;
+				else
+					previousThird = ik;
+			}
+			else {
+				//is not a match; if modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 ==0)
+					return previousThird;
+			}
+		
+		}
+		return previousThird;
+	}
+	static int endSequenceByThree(Listable[] listArray, Object obj, int ic){
+		int previousThird = ic;
+		for (int ik = ic+1; ik< listArray.length; ik++){
+			Object thisObj = listArray[ik];
+			if (thisObj == obj) {
+				//is a match; if not modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 !=0)
+					return previousThird;
+				else
+					previousThird = ik;
+			}
+			else {
+				//is not a match; if modulus 3 on from ic then return previousThird 
+				if ((ik-ic) % 3 ==0)
+					return previousThird;
+			}
+		
+		}
+		return previousThird;
+	}
+	/** returns a string listing the elements of the array that are the passed object.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static  String getListOfMatches(Listable[] listArray, Object obj, int offset) {
+		return getListOfMatches(listArray, obj, offset, true);
+	}
+	/** returns a string listing the elements of the array that are the passed object.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static  String getListOfMatches(Listable[] listArray, Object obj, int offset, boolean doByThirds) {
+		return  getListOfMatches(listArray,  obj,  offset,  doByThirds, "");
+	}
+	/** returns a string listing the elements of the array that are the passed object.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static  String getListOfMatches(Listable[] listArray, Object obj, int offset, boolean doByThirds, String separator) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		boolean writeSeparator=false;
+		int lastWritten = -1;
+		for (int i=0; i<listArray.length; i++) {
+			if (listArray[i]==obj) {
+				found=true;
+				if (continuing == 0) {//first instance
+					//first, check to see if there is a series of thirds....
+					int lastThird = 0;
+					if (doByThirds)
+						lastThird = endSequenceByThree(listArray, obj, i);
+					//if so, then go the series of thirds 
+					if (doByThirds && lastThird != i){
+						if (writeSeparator) {
+							s+=separator;
+							writeSeparator=false;
+						}
+						s += " " + CharacterStates.toExternal(i) + " - " +  CharacterStates.toExternal(lastThird) + "\\3";
+						writeSeparator=true;
+						i = lastThird;
+					}
+					else { //otherwise write as normal*/
+						if (writeSeparator) {
+							s+=separator;
+							writeSeparator=false;
+						}
+						s += " " + (i + offset);
+						lastWritten = i;
+						continuing = 1;
+					}
+				}
+				else if (continuing == 1) {  //second instance
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {  // we've already seen at least one
+				if (lastWritten != i-1) {
+					if (writeSeparator) {
+						s+=separator;
+						writeSeparator=false;
+					}
+					s += " " + (i-1 + offset);
+					writeSeparator=true;
+					lastWritten = i-1;
+				}
+				else {
+					writeSeparator=true;
+					lastWritten = -1;
+				}
+				continuing = 0;
+			}
+		}
+		if (continuing>1){
+			if (writeSeparator) {
+				s+=separator;
+				writeSeparator=false;
+			}
+			s += " " + (listArray.length-1 + offset);
+		}
+		if (found)
+			return s;
+		else
+			return null;
+	}
+	/*...........................................................*/
+	/** returns a string listing the elements of the array that are the passed object.  In the format
+	of NEXUS character, taxa lists (e.g., "1- 3 6 201-455".  The offset is what the first element is to be numbered
+	(e.g., 0 or 1)  */
+	public static  String getListOfMatches(Listable[] listArray1, Object obj1, NumberArray numberArray2, int number2, int offset, boolean doByThirds) {
+		int continuing = 0;
+		String s="";
+		boolean found=false;
+		int lastWritten = -1;
+		for (int i=0; i<listArray1.length && i<numberArray2.getNumParts(); i++) {
+			if (listArray1[i]==obj1 && numberArray2.getInt(i)==number2) {
+				found=true;
+				if (continuing == 0) {//first instance
+				//first, check to see if there is a series of thirds....
+				 int lastThird = 0;
+				 if (doByThirds)
+					 lastThird = endSequenceByThree(listArray1, obj1,numberArray2, number2, i);
+				//if so, then go the series of thirds 
+				if (doByThirds && lastThird != i){
+					s += " " + CharacterStates.toExternal(i) + " - " +  CharacterStates.toExternal(lastThird) + "\\3";
+					i = lastThird;
+				}
+				else { //otherwise write as normal*/
+					s += " " + (i + offset);
+					lastWritten = i;
+					continuing = 1;
+				}
+				}
+				else if (continuing == 1) {
+					s += " - ";
+					continuing = 2;
+				}
+			}
+			else if (continuing >0) {
+				if (lastWritten != i-1) {
+					s += " " + (i-1 + offset);
+					lastWritten = i-1;
+				}
+				else
+					lastWritten = -1;
+				continuing = 0;
+			}
+		}
+		if (continuing>1)
+			s += " " + (listArray1.length-1 + offset);   //TODO:  what about listArray2???
+		if (found)
+			return s;
+		else
+			return null;
+	}
+
+	/*...........................................................*/
+ 	static Collator collator;
+	static {
+		collator = Collator.getInstance();
+	}
+
+	/*...........................................................*/
+	public static void sort(int[] array){
+		if (array==null || array.length<=1)
+			return;
+		
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				int temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		
+	}
+	public static void sort(Listable[] array){
+ 		if (array==null)
+ 			return;
+ 		boolean done = false;
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]!=null && array[j+1] !=null && collator.compare(array[j].getName(), array[j+1].getName())>0; j--) {
+						Listable temp = array[j];
+						array[j] = array[j+1];
+						array[j+1]=temp;
+					
+				
+				
+			}
+		}
+ 	}
+ 	boolean distributeCommands = false;
+	/*.................................................................................................................*/
+	/** Note that command "distributeCommands" causes subsequent commands to be sent
+	 on to any Commandables among the elements, until the next "endDistributeCommands" command */
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Deletes elements", "[start][end]", commandName, "deleteElements")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int first = MesquiteInteger.fromString(arguments, pos);
+    	 		int last = MesquiteInteger.fromString(arguments, pos);
+    	 		if (MesquiteInteger.isCombinable(first) && MesquiteInteger.isCombinable(last)) {
+    	 			for (int i = last; i>=first ; i--)
+    	 				removeElementAt(i, false);
+				notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			}
+    	 			
+ 		}
+ 		else 	if (checker.compare(this.getClass(), "Turns off the distibution of commands to elements", null, commandName, "endDistributeCommands")) {
+			distributeCommands = false;
+		}
+		else if (distributeCommands){
+			for (int i=0; i<size(); i++) {
+				Object obj = elementAt(i);
+				if (obj instanceof Commandable) {
+					((Commandable)obj).doCommand(commandName, arguments, checker);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Turns on the distibution of commands to elements", null, commandName, "distributeCommands")) {
+			distributeCommands = true;
+		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (indexOf(obj)>=0 && code != MesquiteListener.SELECTION_CHANGED && code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_ADDED && code != MesquiteListener.ANNOTATION_DELETED)
+			notifyListeners(this, new Notification(MesquiteListener.ELEMENT_CHANGED));
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/lib/Listenable.java b/Source/mesquite/lib/Listenable.java
new file mode 100644
index 0000000..6035d5e
--- /dev/null
+++ b/Source/mesquite/lib/Listenable.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+
+public interface Listenable {
+ 	/*.................................................................................................................*/
+	/** notifies listeners that element has changed*/
+	public void notifyListeners(Object caller, Notification notification);
+	/** adds a listener to notify if the element changes*/
+	public void addListener(MesquiteListener listener);
+	/** adds a listener to notify if the element changes; add to start of listener vector so it will be notified early*/
+	public void addListenerHighPriority(MesquiteListener listener);
+	/** removes a listener*/
+	public void removeListener(MesquiteListener listener);
+	/** Increments the suppression of listener notification*/
+	public void incrementNotifySuppress();
+	/** Decrements the suppression of listener notification*/
+	public void decrementNotifySuppress();
+	/** Dump to log a list of listeners*/
+	public void listListeners();
+	/** Returns whether the listener is in the list of listeners*/
+	public boolean amIListening(MesquiteListener me);
+}
+
diff --git a/Source/mesquite/lib/Listened.java b/Source/mesquite/lib/Listened.java
new file mode 100644
index 0000000..7fcb92e
--- /dev/null
+++ b/Source/mesquite/lib/Listened.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/*.................................................................................................................*/
+/** A class that notifies listeners if it changes.  Superclass for Associable and MesquiteString*/
+public class Listened implements Listenable {
+	protected Vector listeners;
+	public static int listenersRemaining=0;
+	private int notifySuppress = 0;
+	private Notification lastNotification = null;
+	private boolean notifyPending = false;
+	private boolean dumpNotified = false;
+	private static boolean checkMemory = MesquiteTrunk.checkMemory;
+	public static long notifications = 0;
+	public static ClassVector classes, classesNotified; //for detecting efficiency problems
+	public static Vector allListeners; //for detecting memory leaks
+	static {
+		allListeners = new Vector();//for detecting memory leaks
+	}
+	public Listened (){
+	}
+
+	public boolean isUserVisible(){ //here as a courtesy so that as many classes as possible can support this
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** lists listeners of element*/
+	public void listListeners() {
+		if (listeners!=null) {
+			MesquiteTrunk.mesquiteTrunk.logln("Listeners of  " +this);
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+				if (listener instanceof Listable && listener instanceof Identifiable)
+					MesquiteTrunk.mesquiteTrunk.logln("      listener: " + ((Listable)listener).getName()+ " id " + ((Identifiable)listener).getID() + " class " + listener.getClass());
+			}
+			MesquiteTrunk.mesquiteTrunk.logln("- - - - - - -  " +this);
+		}
+	}
+	public String listenersToString() {
+		if (listeners == null)
+			return "";
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i< listeners.size(); i++){
+			Object obj = listeners.elementAt(i);
+			sb.append(MesquiteModule.getShortClassName(obj.getClass()) + " ");
+			if (obj instanceof Listable)
+				sb.append(((Listable)obj).getName());
+			sb.append("\n");
+		}
+		return sb.toString();
+	}
+	public int getNumListeners() {
+		if (listeners == null)
+			return 0;
+		return listeners.size();
+	}
+	/*.................................................................................................................*/
+	/** adds a listener to notify if the element changes*/
+	public void addListener(MesquiteListener listener) {
+		if (listener==this)
+			MesquiteMessage.warnProgrammer("********* Listener is listening to itself!");
+		if (listeners==null) 
+			listeners = new Vector();
+		if (listener!=null && listeners.indexOf(listener)<0) {
+			listeners.addElement(listener);
+			listenersRemaining++;
+			if (checkMemory)
+				allListeners.addElement(new ObjectR(listener, this));
+		}
+	}
+	/*.................................................................................................................*/
+	/** adds a listener to notify if the element changes*/
+	public void addListenerHighPriority(MesquiteListener listener) {
+		if (listeners==null) 
+			listeners = new Vector();
+		if (listener!=null && listeners.indexOf(listener)<0) {
+			listeners.insertElementAt(listener, 0);
+			listenersRemaining++;
+			if (checkMemory)
+				allListeners.addElement(new ObjectR(listener, this));
+		}
+	}
+	/*.................................................................................................................*/
+	/** removes all listeners*/
+	public void removeAllListeners() {
+		if (listeners!=null) {
+			while( listeners.size()>0)
+				removeListener((MesquiteListener)listeners.elementAt(0));
+		}
+	}
+	/*.................................................................................................................*/
+	/** removes a listener*/
+	public void removeListener(MesquiteListener listener) {
+		if (listeners!=null && listener !=null) {
+			listeners.removeElement(listener);
+			listenersRemaining--;
+			if (checkMemory)
+				ObjectR.removeMe(allListeners, listener, this);
+		}
+	}
+	public static String reportListeners() {
+		if (!checkMemory)
+			return "checkMemory is false; listeners cannot be reported";
+		ClassVector classesListened = new ClassVector();
+		ClassVector classesListener = new ClassVector();
+		for (int i=0; i<allListeners.size(); i++){
+			ObjectR rec = (ObjectR)allListeners.elementAt(i);
+			classesListened.record(rec.listened.getClass());
+			classesListener.record(rec.listener.getClass());
+		}
+		String s = "classes listened=====\n" + classesListened.recordsToString();
+		s += "\nclasses listener=====\n" + classesListener.recordsToString();
+		return s;
+	}
+	public void incrementNotifySuppress(){
+		notifySuppress ++;
+	}
+	public void decrementNotifySuppress(){
+		notifySuppress --;
+		if (notifySuppress<=0){
+			notifySuppress = 0;
+			if (notifyPending){
+				notifyListeners(this, lastNotification);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns whether the listener is in the list of listeners*/
+	public boolean amIListening(MesquiteListener me) {
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+				if (me==listener)
+					return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** When true, causes list of notifications made to be echoed to the console*/
+	public void setDumpNotified(boolean dn){
+		dumpNotified = dn;
+	}
+	MesquiteTimer[] timers = {new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),new MesquiteTimer(),
+			new MesquiteTimer(),new MesquiteTimer()};
+
+	/*.................................................................................................................*/
+	/** notifies listeners that the element, and in particular part i, has changed.  The ith part may
+ 	be the ith character (if element is a CharacterData), or the ith tree (if a TreeVector), etc..
+ 	Notifies only those elements of class clss if boolean is true; notifies only those elements not of class
+ 	clss if boolean is false*/
+	public  void notifyListeners(Object caller, Notification notification, Class clss, boolean classOnly) { 
+		if (MesquiteThread.getListenerSuppressionLevel()>1)
+			return;
+		if (listeners!=null) {
+			if (notifySuppress==0){
+				MesquiteThread.incrementDuringNotification();
+				boolean timeListeners = true;
+				MesquiteTimer timer = new MesquiteTimer();
+				timer.start();
+
+				notifications++;
+				if (classes !=null)
+					classes.record(getClass());
+				notifyPending = false;
+				lastNotification = null;
+				/*Listeners notified by first building array, so as to avoid notifying 
+				listeners newly added to this list during this notification process */
+				MesquiteListener[] ls = new MesquiteListener[listeners.size()];
+				for (int m=0; m<ls.length; m++)
+					ls[m]= (MesquiteListener)listeners.elementAt(m);
+				for (int m=0; m<ls.length; m++) {
+					if (clss == null || (classOnly && clss.isAssignableFrom(ls[m].getClass())) || (!classOnly && !clss.isAssignableFrom(ls[m].getClass())))
+						if (!(ls[m] instanceof Doomable) || !((Doomable)ls[m]).isDoomed()) {
+							if (dumpNotified)
+								MesquiteTrunk.mesquiteTrunk.logln("(" + m + ") notifying " + ls[m] + " of change in " + this + ": " + notification.getCode() + " (caller: " + caller + ")");
+							if (classesNotified !=null)
+								classesNotified.record(ls[m].getClass());
+							if (dumpNotified && m<timers.length)
+								timers[m].start();
+							if (MesquiteTrunk.debugMode) {
+								timer.timeSinceLast();
+								ls[m].changed(caller, this, notification);
+								long time = timer.timeSinceLast();
+								if (time>20)
+									MesquiteMessage.println("@Time: " +  time + " ms. " + "Object: " + this + ".   Listener: " + ls[m]);
+							} else {
+								try {
+									ls[m].changed(caller, this, notification);
+								}
+								catch (Throwable e){  //added 2. 72 to avoid crash in changed from stopping all other listeners from hearing
+									try {
+										String warning = "Crash when notifying " + ls[m] + " of change in " + this + " {Notification code " + Notification.getCode(notification) + " params " + IntegerArray.toString(Notification.getParameters(notification)) + "} ";
+										MesquiteMessage.println("Crash when notifying " + ls[m] + " of change in " + this);
+										MesquiteFile.throwableToLog(this, e);
+										MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, warning);
+									}
+									catch (Throwable f){
+									}
+								}
+							}
+							if (dumpNotified && m<timers.length){
+								timers[m].end();
+							}
+						}
+				}
+				if (dumpNotified){
+					System.out.print("timers " );
+					for (int m = 0; m<timers.length; m++)
+						System.out.print(" (" + m + ") " + timers[m].getAccumulatedTime());
+					System.out.println();
+				}
+				MesquiteThread.decrementDuringNotification();
+			}
+			else {
+				notifyPending = true;
+				lastNotification =notification;
+			}
+		}
+		doAfterNotify(notification);
+	}
+	/*.................................................................................................................*/
+	//can be overrided as needed (see CharacterData for example)
+	public void doAfterNotify(Notification notification){
+
+	}
+
+	/*.................................................................................................................*/
+	/** notifies listeners that the element, and in particular part i, has changed.  The ith part may
+ 	be the ith character (if element is a CharacterData), or the ith tree (if a TreeVector), etc. */
+	public void notifyListeners(Object caller, Notification notification) { 
+		notifyListeners(caller, notification, null, true);
+	}
+	/*.................................................................................................................*/
+	/** Returns the number of listeners remaining that are still registered with this element.
+ 	Useful to see that listeners are removing themselves as needed. */
+	public static int getRemainingListeners(){
+		return listenersRemaining;
+	}
+
+	/*-------------------------------------------------------*/
+	/** Deletes the object. Should typically be called via close()  to make sure that the file element is not in use etc. */
+	public void dispose() {
+	
+		/*  tell all listeners that this is being dleeted*/
+		if (listeners!=null) {
+			if (notifySuppress==0){
+				boolean sizeChanged = false;
+				Vector notified = new Vector();
+				
+				boolean stillGoing = true;
+				while (stillGoing) {
+					stillGoing = false;
+					sizeChanged = false;
+					for (int i=0; i<listeners.size(); i++) {
+						Object obj = listeners.elementAt(i);
+						MesquiteListener listener = (MesquiteListener)obj;
+						if ((notified.indexOf(listener)<0) && (!(listener instanceof Doomable) || !((Doomable)listener).isDoomed())){
+							if (dumpNotified)
+								MesquiteTrunk.mesquiteTrunk.logln("notifying " + listener + " of disposal of " + this);
+							int oldSize = listeners.size();
+							notified.addElement(listener);
+							listener.disposing(this); //in this the listeners could be changed, thus
+							if (!sizeChanged)
+								sizeChanged = listeners.size() != oldSize;
+						}
+						listenersRemaining--;
+						if (checkMemory)
+							ObjectR.removeMe(allListeners, listener, this);
+					}
+					if (sizeChanged)
+						stillGoing = true;
+				}
+			}
+			listeners.removeAllElements();
+		}
+	}
+
+	/*-------------------------------------------------------*/
+	/** Notifies all the listeners that the passed object is being disposed.  Added June 02*/
+	public void notifyDisposing(Object doomedObject) {
+		/*  tell all listeners that this object is being dleeted*/
+		if (listeners!=null) {
+			if (notifySuppress==0){
+				for (int i=0; i<listeners.size(); i++) {
+					Object obj = listeners.elementAt(i);
+					MesquiteListener listener = (MesquiteListener)obj;
+					if (!(listener instanceof Doomable) || !((Doomable)listener).isDoomed())
+						listener.disposing(doomedObject); 
+				}
+
+			}
+		}
+	}
+}
+
+class ObjectR extends ObjectContainer {
+	Object listener;
+	Listened listened;
+	public ObjectR(Object listener, Listened listened){
+		this.listener = listener;
+		this.listened = listened;
+		setObject(listener);
+	}
+	static void removeMe(Vector allListeners, Object listener, Listened listened){
+		for (int i = 0; i<allListeners.size(); i++){
+			ObjectR r = (ObjectR)allListeners.elementAt(i);
+			if (r.listener == listener && r.listened == listened) {
+				allListeners.removeElement(r);
+				return;
+			}
+		}
+	}
+	public String toString() {
+		String s = "Listener " + listener.getClass();
+		if (listener instanceof Listable)
+			s+= " (name " + ((Listable)listener).getName() + ")";
+		s += ", listening to " + listened.getClass();
+		if (listener instanceof FileElement)
+			s+= " (disposed " + ((FileElement)listener).isDisposed() + ")";
+		if (listened instanceof Listable)
+			s+= " (name " + ((Listable)listened).getName() + ")";
+		if (listened instanceof FileElement)
+			s+= " (disposed " + ((FileElement)listened).isDisposed() + ")";
+		return s;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/LogValueToPixel.java b/Source/mesquite/lib/LogValueToPixel.java
new file mode 100644
index 0000000..ee5d03a
--- /dev/null
+++ b/Source/mesquite/lib/LogValueToPixel.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.*;
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/*=================*/
+public class LogValueToPixel extends ValueToPixel {
+	public LogValueToPixel  (double minValue, double maxValue, double minSweetSpotValue, double maxSweetSpotValue, int totalPixels) {
+		super(minValue, maxValue, minSweetSpotValue,maxSweetSpotValue,totalPixels);
+	}
+	public double getValue(int pixel){
+			//0 = 0;  maxValue = 0.5; infinity = 1;   
+			
+			if (pixel*1.0/totalPixels >0.7) //in right half of slider
+				return maxSweetSpotValue - 5* Math.log((1.0 - pixel*1.0/totalPixels)/0.3);
+			else
+				return Math.log(pixel*1.0/totalPixels/0.7) + maxSweetSpotValue;
+	}
+	public double getPixelPercent(double value){
+		/* if above maxSweetSpotValue then   1- 0.3*exp(maxSweetSpotValue-x)
+			if below maxSweetSpotValue then 0.7*exp(x-maxSweetSpotValue) */
+		if (value>maxSweetSpotValue)
+			return 1.0 - 0.3*Math.exp((maxSweetSpotValue-value)/5);
+		else  
+			return 0.7*Math.exp(value-maxSweetSpotValue);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/LogWindow.java b/Source/mesquite/lib/LogWindow.java
new file mode 100644
index 0000000..4bdc78d
--- /dev/null
+++ b/Source/mesquite/lib/LogWindow.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.trunk.ProjectTreeWindow;
+
+
+/* ======================================================================== */
+/** The window that displays the log. */
+public class LogWindow extends ConsoleWindow implements SystemWindow {
+	boolean keyHasBeenDown = false;
+	int bannerHeight = 46;
+	BannerPanel bannerPanel;
+	HelpSearchStrip searchStrip;
+	int searchHeight = 20;
+	int searchLeft = 4;
+	public LogWindow(String t) {
+		super(MesquiteModule.mesquiteTrunk, "Log", false); //infobar
+		setText(t);
+		System.out.println(t);
+		MesquiteFile.writeToLog(t);  
+		bannerPanel = new BannerPanel(this);
+		addToWindow(bannerPanel);
+		bannerPanel.setSize(getWidth(), bannerHeight);
+		bannerPanel.setLocation(0,0);
+		bannerPanel.setVisible(true);
+		searchStrip = new HelpSearchStrip(this, false);
+
+		addToWindow(searchStrip);
+		searchStrip.setBounds(searchLeft, getHeight()-searchHeight, getWidth() - searchLeft, searchHeight);
+		searchStrip.setVisible(true);
+		
+		tA.setLocation(0, bannerHeight);
+		
+		//setBackground(ColorDistribution.paleGoldenRod);
+		setBackground(ColorDistribution.mesquiteBrown);
+		//setBackground(ColorTheme.getInterfaceBackground());
+
+	}
+	public boolean isCompactible(){
+		return true;
+	}
+	public boolean permitViewMode(){
+		return false;
+	}
+
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 1;
+	}
+	public void requestFocus(){
+		tA.requestFocus();
+		tA.requestFocusInWindow();
+	}
+	public boolean keyDown(){
+		return keyHasBeenDown;
+	}
+	public void repaintSearchStrip(){
+		searchStrip.repaint();
+	}
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		if (tA!=null)
+			tA.setSize(getWidth(), getHeight() - bannerHeight - searchHeight); //getFullWidth
+		if (bannerPanel!=null)
+			bannerPanel.setSize(getWidth(), bannerHeight);
+		if (searchStrip!= null)
+			searchStrip.setBounds(searchLeft, getHeight()-searchHeight, getWidth() - searchLeft, searchHeight);
+
+	}
+	/** Sets the window size.  To be used instead of setSize. 
+	public void containerSizeSet(int width, int height) {
+	}
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize.  */
+	public void setWindowSize(int width, int height) {
+		super.setWindowSize(width, height);
+		if (tA!=null)
+			tA.setSize(getWidth(), getHeight() - bannerHeight - searchHeight);
+		if (bannerPanel!=null)
+			bannerPanel.setSize(getWidth(), bannerHeight);
+		if (searchStrip!= null)
+			searchStrip.setBounds(searchLeft, getHeight()-searchHeight, getWidth() - searchLeft, searchHeight);
+	}
+	public void keyTyped(KeyEvent e){
+		keyHasBeenDown = true;
+		super.keyTyped(e);
+	}
+	
+	public void keyPressed(KeyEvent e){ 
+		keyHasBeenDown = true;
+		super.keyPressed(e);
+	}
+	
+	public void keyReleased(KeyEvent e){
+		super.keyReleased(e);
+	}
+}
+class BannerPanel extends Panel {
+	Image banner;
+	int bannerHeight;
+	public BannerPanel(LogWindow w){
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease())
+			banner=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/bannerBeta.gif");  
+		else
+			banner=  MesquiteImage.getImage(MesquiteModule.getRootPath() +"images/banner.gif");  
+		bannerHeight = w.bannerHeight;
+		setBackground(ColorDistribution.mesquiteBrown);
+
+	}
+	
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		g.drawImage(banner, 0, 0, this);
+		g.setColor(ColorDistribution.lightYellow);
+		if (StringUtil.notEmpty(MesquiteModule.getSpecialVersion()))
+			g.drawString( MesquiteModule.getSpecialVersion() , 224,bannerHeight-18);
+		g.drawString( "Version " + MesquiteModule.getMesquiteVersion() + " " + MesquiteModule.getBuildVersion() , 224,bannerHeight-4);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/Logger.java b/Source/mesquite/lib/Logger.java
new file mode 100644
index 0000000..3dde630
--- /dev/null
+++ b/Source/mesquite/lib/Logger.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it maintains a log*/
+public interface Logger {
+ 	public void logln(String s);
+ 	public void log(String s);
+}
+
+
diff --git a/Source/mesquite/lib/Long2DArray.java b/Source/mesquite/lib/Long2DArray.java
new file mode 100644
index 0000000..65db8eb
--- /dev/null
+++ b/Source/mesquite/lib/Long2DArray.java
@@ -0,0 +1,339 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+public class Long2DArray {
+	long[][] values;
+	int numC;
+	 int numT;
+	NameReference name=null;
+	public Long2DArray(int numC, int numT){
+		this.numC = numC;
+		this.numT = numT;	
+		values = new long[numC][numT];
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  MesquiteLong.unassigned;
+	}
+	public Long2DArray(long[][] input){
+		this(numFullColumns(input), numFullRows(input));
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  input[i][j];
+	}
+	/*...........................................................*/
+	public static int getMaxColumnLength(long[][] matrix){
+		int maxLength = 0;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]!=null)
+				maxLength = MesquiteInteger.maximum(matrix[i].length, maxLength);  //maxLength stores the maximum row length
+		}
+		return maxLength;
+	}
+	/*...........................................................*/
+	public static long[][] transpose(long[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return null;
+		int maxLength = getMaxColumnLength(matrix);
+		long[][] transposed = new long[maxLength][matrix.length];
+		for (int ic=0; ic<transposed.length; ic++)
+			for (int it=0; it<transposed[ic].length; it++)
+				transposed[ic][it] =  0;
+		for (int ic=0; ic<matrix.length; ic++)
+			for (int it=0; it<matrix[ic].length; it++)
+				transposed[it][ic] =  matrix[ic][it];
+		return transposed;
+	}
+	/*...........................................................*/
+	public static int numFullRows(long[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(long[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public long getValue(int ic, int it){
+		if (values==null || (ic <0 || ic >= values.length) || (it <0 || it >= values[ic].length))
+			return MesquiteLong.unassigned;
+		else
+			return values[ic][it];
+	}
+	/*...........................................................*/
+	public long[] getValues(int ic) {
+		if (values == null || ic <0 || ic >= values.length)
+			return null;
+		else
+			return values[ic];
+	}
+	/*...........................................................*/
+	public long[][] getMatrix() {
+		return values;
+	}
+	/*...........................................................*/
+	public void setValue(int ic, int it, long value) {
+		if (values!=null && ic >=0 && ic < values.length)
+		 	if (it >=0 && it < values[ic].length)
+				values[ic][it] = value;
+	}
+	/*...........................................................*/
+	public void setValues(Long2DArray incoming) {
+		if (incoming !=null) {
+			resetSize(incoming.getSizeC(), incoming.getSizeT());
+			for (int it=0; it<incoming.getSizeT() && it < getSizeT(); it++) {
+				for (int ic=0; ic<incoming.getSizeC() && ic < getSizeC(); ic++) {
+					setValue(ic, it, incoming.getValue(ic, it));
+				}
+			}
+		}
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public static void zeroArray(long [][] array){
+		for (int ic=0; ic<array.length; ic++)
+			for (int it=0; it<array[ic].length; it++)
+			array[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  MesquiteLong.unassigned;
+	}
+	/*...........................................................*/
+	/** Changes the array size to the new dimensions*/
+	public void resetSize(int newNumC, int newNumT) {
+		if (newNumC == numC && newNumT == numT)
+			return;
+		long[][] newLongValues = new long[newNumC][newNumT];
+		for (int i=0; i<newNumC; i++)
+			for (int j=0; j<newNumT; j++) {
+				if (i<numC && j<numT)
+					newLongValues[i][j]=values[i][j];
+				else
+					newLongValues[i][j]=0;
+			}
+		values=newLongValues;
+		numC=newNumC;
+		numT=newNumT;
+	}
+	/*...........................................................*/
+	public int getSizeC() {
+		return numC;
+	}
+	/*...........................................................*/
+	public int getSizeT() {
+		return numT;
+	}
+	/*...........................................................*/
+	public static long maximumInColumn(long[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteLong.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteLong.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmLessThan(values[column][i]);
+		return d.getLongValue();
+	}
+	/*...........................................................*/
+	public static long minimumInColumn(long[][] values, int column){
+		if (values==null || values.length<=column || values[column]==null)
+			return MesquiteLong.unassigned;
+		MesquiteNumber d = new MesquiteNumber(MesquiteLong.unassigned);
+		for (int i=0; i<values[column].length; i++)
+			d.setMeIfIAmMoreThan(values[column][i]);
+		return d.getLongValue();
+	}
+	/*...........................................................*/
+	public static void swapColumns(long[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		long[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveColumns(long[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		long[][] newValues = new long[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	
+	/*...........................................................*/
+	public static long[][] addColumns(long[][] d, int numRows, long defaultValue, int starting, int num){
+		if (num <= 0 || d == null)
+			return d;
+		int numChars = d.length;
+		if (d.length <= 0) {
+			long[][] newMatrix=new long[numChars+num][numRows];
+			for (int ic=0; ic<numChars+num; ic++){
+				for (int it=0; it<numRows; it++) 
+					newMatrix[ic][it] = defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+		int numTaxa = d[0].length;
+		if (numTaxa == 0 && numRows >=0)
+			numTaxa = numRows;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+		
+		long[][] newMatrix=new long[newNumChars][numTaxa];
+		for (int ic=0; ic<newNumChars; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic][it] = defaultValue; //filling with missing data
+		}
+		for (int ic=0; ic<=starting && ic < d.length; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic][it] = d[ic][it]; //transferring old first part
+		}
+		for (int ic=0; ic<numChars - starting -1 ; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic + starting + num + 1][it] = d[starting + ic+1][it]; //transferring old second part
+		}
+		return newMatrix;
+		
+	}
+	/*.................................................................................................................*/
+	public static long[] extractRow(long[][] array, int row) {
+		long[] newArray = new long[array.length];
+		for (int i = 0; i<array.length; i++) {
+			newArray[i] = array[i][row];
+		}
+		return newArray;
+	}
+	/*...........................................................*/
+	public static long[][] addColumns(long[][] d, long defaultValue, int starting, int num){
+		return addColumns(d, -1, defaultValue, starting, num);
+	}
+	/*...........................................................*/
+	public static long[][] deleteColumns(long[][] d, int starting, int num){
+		if (num <= 0 || d == null)
+			return d;
+		int numChars = d.length;
+		if (starting<0)
+			return d;
+		else if (starting>numChars)
+			return d;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars =numChars-num;
+
+
+		if (d.length <= 0)
+			return new long[numChars-num][];
+		int numTaxa = d[0].length;
+		
+		long[][] newMatrix=new long[newNumChars][numTaxa];
+		for (int ic=0; ic<starting; ic++){
+			for (int it=0; it<numTaxa && it< d[ic].length; it++) 
+				newMatrix[ic][it] = d[ic][it]; //transferring old first part
+		}
+		for (int ic=starting + num; ic<numChars  && ic-num<newNumChars; ic++){
+			for (int it=0; it<numTaxa && it< d[ic].length; it++) 
+				newMatrix[ic-num][it] = d[ic][it]; //transferring old second part
+		}
+		return newMatrix;
+	}
+	
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	public static String toString(long[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		for (int j=0; j<numRows; j++) {
+			result.append('[');
+			for (int i=0; i<numColumns; i++) {
+				
+				result.append(MesquiteLong.toString(matrix[i][j]));
+				result.append(' ');
+			}
+			result.append(']');
+			result.append('\n');
+		}
+		return result.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/LongArray.java b/Source/mesquite/lib/LongArray.java
new file mode 100644
index 0000000..8998b6c
--- /dev/null
+++ b/Source/mesquite/lib/LongArray.java
@@ -0,0 +1,382 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+
+
+/* ======================================================================== */
+
+public class LongArray implements Listable {
+	long[] values;
+	NameReference name=null;
+	int autoExpandAmount = 0;
+	
+	public LongArray(int num){	
+		this(num, 0);
+	}
+
+	public LongArray(int num, int autoExpandAmount){
+		values = new long[num];
+		for (int i=0; i<num; i++)
+			values[i] =  MesquiteLong.unassigned;
+		this.autoExpandAmount = autoExpandAmount;
+	}
+		
+	//used for Associables that might need to record whether reference is to part or in between part
+	//intially for MesquiteTree to know if info applies to node or branch ancestral to node
+	boolean between = false;
+	public void setBetweenness(boolean b){
+		between = true;  
+	}
+	public boolean isBetween(){
+		return between;
+	}
+	/*...........................................................*/
+	public boolean legalIndex(int i){
+		return (values!=null && i>=0 && i<values.length);
+	}
+	/*...........................................................*/
+	public long[] getMatrix(){
+		return values;
+	}
+	/*...........................................................*/
+	public long getValue(int index){
+		if (!legalIndex(index))
+			return MesquiteLong.unassigned;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public void setValue(int index, long value) {
+		if (legalIndex(index))
+			values[index] = value;
+		else if (autoExpandAmount>0){
+			if (index >= values.length){
+				int newSize = 0;
+				if (index-values.length+1 < autoExpandAmount)
+					newSize = values.length + autoExpandAmount;
+				else
+					newSize = index + autoExpandAmount;
+				resetSize(newSize);
+				if (legalIndex(index))
+					values[index] = value;
+			}
+		}
+	}
+	/*...........................................................*/
+	public void setValues(long[] values) {
+		if (values==null)
+			this.values = new long[0];
+		else
+			this.values= values;
+	}
+	/*...........................................................*/
+	public void copyTo(LongArray d){
+		if (d==null || d.values.length!=values.length)
+			return;
+		for (int i=0; i<values.length; i++)
+			d.values[i] =  values[i];
+	}
+	/*...........................................................*/
+	public void copyTo(DoubleArray d){
+		if (d==null || d.values.length!=values.length)
+			return;
+		for (int i=0; i<values.length; i++){
+			d.values[i] =  MesquiteDouble.toDouble(values[i]);
+		}
+	}
+	/*...........................................................*/
+	/** turns value to absolute value. */
+	public void abs() {
+		for (int i=0; i<values.length; i++){
+			if (MesquiteLong.isCombinable(values[i]))
+				values[i] = Math.abs(values[i]);
+		}
+	}
+	public void zeroArray(){
+
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	public static void zeroArray(long[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteLong.unassigned;
+	}
+	/*...........................................................*/
+	public static void deassignArray(long[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  MesquiteLong.unassigned;
+	}
+	/*...........................................................*/
+	public static long[] reverse(long[] d){
+		if (d==null)
+			return null;
+		long[] values = new long[d.length];
+		for (int i=0; i<values.length; i++)
+			values[values.length-1-i] =  d[i];
+		return values;
+	}
+	/*...........................................................*/
+	public int indexOf(long match){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(long[] values, long match){
+		if (values==null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int countSame(long[] a, long match){
+		if (a==null)
+			return 0;
+		int count= 0;
+		for (int i=0; i<a.length; i++)
+			if (a[i]== match)
+				count++;
+		return count;
+	}
+	/*...........................................................*/
+	public boolean fillNextUnassigned(long v){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== MesquiteLong.unassigned) {
+				values[i] = v;
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	public static void sort(long[] array){
+		if (array==null || array.length<=1)
+			return;
+
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				long temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+
+	}
+	/*...........................................................*/
+	public int getSize() {
+		if (values==null)
+			return 0;
+		return values.length;
+	}
+	/*...........................................................*/
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		long[] newLongValues = new long[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newLongValues[i]=values[i];
+		if (newNum>getSize())
+			for (int i=getSize(); i<newNum; i++)
+				newLongValues[i]=MesquiteLong.unassigned;
+		values=newLongValues;
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num, long defaultValue) {
+		values=addParts(values, starting, num, defaultValue);
+	}
+	/*...........................................................*/
+	public static long[] addParts(long[] d, int starting, int num, long defaultValue) {
+		if (num<=0 || d==null)
+			return d;
+
+		if (d.length <= 0) {
+			long[] newMatrix=new long[num];
+			for (int ic=0; ic<num; ic++){
+				newMatrix[ic] = defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+
+		if (starting<0) 
+			starting = -1;
+		if (starting>d.length) 
+			starting = d.length-1;
+		int newNum = d.length + num;
+		long[] newValues = new long[newNum];
+		for (int i=0; i<=starting; i++)
+			newValues[i]=d[i];
+		for (int i=0; i<num ; i++)
+			newValues[starting + i + 1]=defaultValue;
+		for (int i=0; i<d.length-starting-1; i++)
+			newValues[i +starting+num+1]=d[starting + i + 1];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0 || starting<0 || starting>=getSize())
+			return;
+		values = deleteParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static long[] deleteParts(long[] d, int starting, int num) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		if (num+starting>d.length)
+			num = d.length-starting;
+		int newNum =d.length - num;
+		long[] newValues = new long[newNum];
+		for (int i=0; i<starting; i++)
+			newValues[i]=d[i];
+		for (int i=starting+num; i<d.length; i++)
+			newValues[i-num]=d[i];
+		return newValues;
+	}
+	/*...........................................................*/
+	public static long[] getMoveParts(long[] d, int starting, int num, int justAfter) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		long[] newValues = new long[d.length];
+
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+
+		return newValues;
+	}
+	/*...........................................................*/
+	public void moveParts(int starting, int num, int justAfter) {
+		moveParts(values, starting, num, justAfter);
+	}
+	/*...........................................................*/
+	public boolean swapParts(int first, int second) {
+		if (first<0 || first>=values.length || second<0 || second>=values.length) 
+			return false;
+		long temp = values[first];
+		values[first] = values[second];
+		values[second] = temp;
+		return true;
+	}
+	/*...........................................................*/
+	public static void swapParts(long[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		long temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveParts(long[] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		long[] newValues = new long[d.length];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public static String toString(long[] vector){
+		if (vector==null ||  vector.length==0)
+			return null;  
+		StringBuffer result = new StringBuffer(vector.length*2);
+		result.append('[');
+		for (int i=0; i<vector.length; i++) {
+			if (vector[i] == MesquiteLong.unassigned)
+				result.append('?');
+			else
+				result.append(Long.toString(vector[i]));
+			result.append(' ');
+		}
+		result.append(']');
+		return result.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/LongField.java b/Source/mesquite/lib/LongField.java
new file mode 100644
index 0000000..d3417dc
--- /dev/null
+++ b/Source/mesquite/lib/LongField.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+
+/*===============================================*/
+/** a field for longs */
+public class LongField  {
+	ExtensibleDialog dialog;
+	SingleLineTextField textField;
+	long initialValue=0;
+	/*.................................................................................................................*/
+	public LongField (ExtensibleDialog dialog, String message, long initialValue, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = initialValue;
+		textField = dialog.addTextField (message, MesquiteLong.toString(initialValue), fieldLength);
+	}
+	/*.................................................................................................................*/
+	public LongField (ExtensibleDialog dialog, String message, int fieldLength) {
+		super();
+		this.dialog = dialog;
+		this.initialValue = 0;
+		textField = dialog.addTextField (message, "", fieldLength);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField getTextField () {
+		return textField;
+	}
+	/*.................................................................................................................*/
+	public long getValue () {
+		String s = textField.getText();
+		if (s != null && s.equals("?"))
+			return MesquiteLong.unassigned;
+		long value = MesquiteLong.fromString(s);
+		if (!MesquiteLong.isCombinable(value)) {
+			value=initialValue;
+		}
+	        return value;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/LowLevelListener.java b/Source/mesquite/lib/LowLevelListener.java
new file mode 100644
index 0000000..d820e56
--- /dev/null
+++ b/Source/mesquite/lib/LowLevelListener.java
@@ -0,0 +1,27 @@
+package mesquite.lib;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+
+/* ======================================================================== */
+public interface LowLevelListener {
+	//change cell of matrix, code VALUE_CHANGED, i1 = ic, i2 = it, i3 not used
+	//add characters to CharacterData or taxa to Taxa, code PARTS_ADDED, i1 = justAfter, i2 = num
+	//delete characters in CharacterData or taxa in Taxa, code PARTS_DELETED, i1 = starting, i2 = num
+	//move characters in CharacterData or taxa in Taxa, code PARTS_MOVED, i1=starting, i2= num, i3 = justAfter
+	//swap characters in CharacterData or taxa in Taxa, code PARTS_SWAPPED, i1= first, i2 = second
+	public void llChange(Object obj, int code, int i1, int i2, int i3);
+}
+
diff --git a/Source/mesquite/lib/MRPopup.java b/Source/mesquite/lib/MRPopup.java
new file mode 100644
index 0000000..7614b0c
--- /dev/null
+++ b/Source/mesquite/lib/MRPopup.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+public class MRPopup extends MesquitePopup implements ActionListener {
+	public MRPopup(Container c){
+		super(c);
+		addActionListener(this);
+	}
+	public void actionPerformed(ActionEvent e) {
+		//Event queue
+		/*return super.postEvent(evt);*/
+		if (e.getSource() instanceof MenuItem) {   
+			MenuContainer gp = getParent();
+			if (gp !=null)
+				gp.remove(this);
+		}
+		/**/
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MainThread.java b/Source/mesquite/lib/MainThread.java
new file mode 100644
index 0000000..4baf626
--- /dev/null
+++ b/Source/mesquite/lib/MainThread.java
@@ -0,0 +1,162 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.duties.*;
+
+/** The main thread for executing commands */
+public class MainThread extends MesquiteThread {
+	public static ListableVector pendingCommands;
+	public static MainThread mainThread;
+	public static boolean emergencyCancelled = false;
+	static PendingCommand currentlyExecuting;
+	long c = 0;
+	static {
+		pendingCommands = new ListableVector(10);
+	}
+	public MainThread () {
+		super();
+	}
+	boolean dead = false;
+
+	public static void deleteCommand(MesquiteCommand command){
+		try{
+			while (!commandAlreadyOnQueue(command)) {
+				for (int i= 0; i< pendingCommands.size(); i++) {
+					PendingCommand pc =  (PendingCommand)pendingCommands.elementAt(i); 
+					MesquiteCommand mc = pc.getCommand();
+					if (command == mc){
+						pendingCommands.removeElement(pc, false);
+						break;
+					}
+				}
+			}
+		}
+		catch (Exception e){
+			//MesquiteFile.throwableToLog(null, e);
+		}
+	}
+	public static boolean commandAlreadyOnQueue(MesquiteCommand command){
+		try{
+			for (int i= 0; i< pendingCommands.size(); i++) {
+				PendingCommand pc =  (PendingCommand)pendingCommands.elementAt(i); 
+				MesquiteCommand mc = pc.getCommand();
+				if (command == mc)
+					return true;
+			}
+		}
+		catch (Exception e){
+			//MesquiteFile.throwableToLog(null, e);
+		}
+		return false;
+	}
+	public static ListableVector listPendingCommands(){
+		ListableVector list = new ListableVector(10);
+		for (int i= 0; i< pendingCommands.size(); i++) {
+			PendingCommand pc =  (PendingCommand)pendingCommands.elementAt(i); 
+			MesquiteCommand mc = pc.getCommand();
+			if (!mc.hideInList)
+				list.addElement(pc, false);
+		}
+		return list;
+	}
+
+	public static PendingCommand getCurrentlyExecuting(){
+		return currentlyExecuting;
+	}
+	public CommandRecord getCommandRecord(){
+		if (currentlyExecuting !=null)
+			return currentlyExecuting.getCommandRecord();
+		return null;
+	}
+	public void setCommandRecord(CommandRecord c){
+		if (currentlyExecuting !=null)
+			currentlyExecuting.setCommandRecord(c);
+	}
+	public String getCurrentCommandName(){
+		if (currentlyExecuting !=null)
+			return currentlyExecuting.getListName();
+		return null;
+	}
+	public String getCurrentCommandExplanation(){
+		if (currentlyExecuting !=null)
+			return currentlyExecuting.getExplanation();
+		return null;
+	}
+	/** DOCUMENT */
+	public void run() {
+		try {
+			while (!MesquiteTrunk.mesquiteTrunk.isDoomed() && !isInterrupted()) { 
+				while  (pendingCommands.size()==0) {
+					Thread.sleep(100);
+				}
+				try {
+					if (pendingCommands.size()>0) {
+
+						PendingCommand pc = (PendingCommand)pendingCommands.elementAt(0);  // get it so that we can set it to busy
+						MesquiteCommand c = pc.getCommand();
+						pc = (PendingCommand)pendingCommands.elementAt(0);  // pluck it off again
+						if (pc != null){
+							pendingCommands.removeElement(pc, false);
+							pc.setThread(this);
+							currentlyExecuting = pc;
+							setCurrent(pc.id);
+							patience = 5;
+							boolean loggerSet = false;
+							if (c.getSupplementalLogger() != null && logger == null){
+								MesquiteThread.setLoggerCurrentThread(c.getSupplementalLogger());
+								loggerSet = true;
+							}
+								
+							pc.go();
+							if (loggerSet){
+								MesquiteThread.setLoggerCurrentThread(null);
+							}
+							setCurrent(-1);
+							currentlyExecuting = null;
+						}
+					}
+				}
+				catch (Exception e){
+					setCurrent(-1);
+					currentlyExecuting = null;
+					MesquiteDialog.closeWizard();
+					MesquiteFile.throwableToLog(this, e);
+				}
+				catch (Error e){
+					if (e instanceof OutOfMemoryError)
+						MesquiteMessage.println("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+					currentlyExecuting = null;
+					setCurrent(-1);
+					MesquiteFile.throwableToLog(this, e);
+					throw e;
+				}
+			}
+		}
+		catch (InterruptedException e){
+			Thread.currentThread().interrupt();
+		}
+		dead = true;
+		threadGoodbye();
+	}
+	public void interrupt(){
+			MesquiteDialog.closeWizard();
+		super.interrupt();
+	}
+
+}
+
diff --git a/Source/mesquite/lib/MarchingAnts.java b/Source/mesquite/lib/MarchingAnts.java
new file mode 100644
index 0000000..6c4565b
--- /dev/null
+++ b/Source/mesquite/lib/MarchingAnts.java
@@ -0,0 +1,115 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+public class MarchingAnts {
+	AntMarcher ants;
+	protected int x;
+	protected int y;
+	protected int width;
+	protected int height;
+	Timer tmr;
+	protected Graphics g;
+	public MarchingAnts() {
+	}
+	public MarchingAnts(Graphics g, int x, int y, int width, int height) {
+		this.x=x; 
+		this.y=y;
+		this.width=width;
+		this.height = height;
+		this.g = g;
+		startAnts();
+	}
+	public void startAnts() {
+		ants = new AntMarcher(g, this);
+		tmr = new Timer();
+		tmr.schedule(ants, 0,20);
+	}
+	public void resize (int x, int y, int width, int height){
+		if (ants!=null)
+			ants.drawAnts();  //draws old size just to get rid of it
+		this.x=x; 
+		this.y=y;
+		this.width=width;
+		this.height = height;
+	}
+	public int getX() {
+		return x;
+	}
+	public int getY() {
+		return y;
+	}
+	public int getWidth() {
+		return width;
+	}
+	public int getHeight() {
+		return height;
+	}
+	public void cancel() {
+		if (ants!=null) 
+			ants.cancel();
+	}
+	public void setLineWidth(float lineWidth){
+		if (ants!=null)
+			ants.setLineWidth(lineWidth);
+	}
+
+}
+
+class AntMarcher extends TimerTask {
+	float dashPhase = 0;
+	Graphics2D g2;
+	MarchingAnts c = null;
+	float lineWidth = 1.5f;
+	
+	public AntMarcher (Graphics g, MarchingAnts c) {
+		this.c=c;
+		if (g instanceof Graphics2D) {
+			g2 = (Graphics2D)g;
+			drawAnts();
+		}
+		else
+			cancel();
+	}
+	public void setLineWidth(float lineWidth){
+		this.lineWidth = lineWidth;
+	}
+	public boolean cancel() {
+		drawAnts();
+		return super.cancel();
+	}
+	public void drawAnts() {
+		if (c==null)
+			return;
+		g2.setPaint(Color.black);
+		g2.setXORMode(Color.white);
+		//	Stroke stroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[]{4, 2, 6, 2},dashPhase);
+		Stroke stroke = new BasicStroke(lineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[]{4, 4},dashPhase);
+		g2.setStroke(stroke);
+		g2.drawRect(c.getX(),c.getY(),c.getWidth(),c.getHeight());
+	}
+	public  void run() {
+		if (c==null)
+			return;
+		//g2.fillRect(c.getX(),c.getY(),c.getWidth(),c.getHeight());
+
+		drawAnts();
+		dashPhase++;
+		drawAnts();
+
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/lib/MenuItemsSpecsVector.java b/Source/mesquite/lib/MenuItemsSpecsVector.java
new file mode 100644
index 0000000..b3a2b98
--- /dev/null
+++ b/Source/mesquite/lib/MenuItemsSpecsVector.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/*====================================================*/
+/**The vector of menuItems used by a mesquite module.*/
+public class MenuItemsSpecsVector extends ListableVector {
+	public MenuItemsSpecsVector  () {
+		super();
+		notifyOfChanges = false;
+	}
+	public void dispose(){
+		removeAllElements(false);
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+	 				listener.disposing(this);
+				}
+		}
+		disposed = true;
+		super.dispose();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MenuOwner.java b/Source/mesquite/lib/MenuOwner.java
new file mode 100644
index 0000000..ba7ac84
--- /dev/null
+++ b/Source/mesquite/lib/MenuOwner.java
@@ -0,0 +1,2761 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.applet.Applet;
+import java.io.UnsupportedEncodingException;
+import java.net.*;
+import java.util.*;
+import java.awt.event.*;
+
+import mesquite.distance.lib.TaxaDistFromMatrix;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+/* ��������������������������� Menus ������������������������������� */
+
+/* ======================================================================== */
+/**Menus in Mesquite are composed by the code in the MenuOwner class, which is designed to be a superclass only for
+the MesquiteModule class.  The methods of the MenuOwner class were separated from MesquiteModule because the latter
+was becoming unwieldy.  We expect MenuOwner will never be used apart from its status as superclass to MesquiteModule.<p>
+
+MesquiteModules request menus and menu items by creating MesquiteMenuSpec's (for menus, using
+makeMenu or addAuxiliaryMenu) or MesquiteMenuItemSpec's (for items, using addMenuItem).  These
+Specs store the necessary information to allow actual Java Menu and MenuItems to be created when
+menu bars are composed using resetMenus (of MesquiteWindow) and composeMenuBar (of MesquiteModule).
+Menu bars in general are re-composed when employees are hired, because the new employees may have menu items that need adding.<p>
+
+All menu items operate via a Command; thus, to define a MesquiteMenuItem you need to pass it
+the command that is to be invoked when the menu item is selected.  Similarly the MiniScrolls are passed
+a command to be called on changes of their index, and MesquiteButtons are passed a command to be called
+when they are touched.  Branch moves will soon also be done via tool objects that store commands.
+ */
+public abstract class MenuOwner implements Doomable { //EMBEDDED: extends Applet
+	public static final int MAXPRIORITY=25;  //needs to be 25 to accommodate genetic codes
+	public static boolean considerPriorities = false;  //this allow ones to turn off the priority system
+	//protected MesquiteMenuSpec defaultsMenuSpec; 
+	//protected MesquiteSubmenu defaultSubMenu;
+
+	/** The module corresponding to this object (maybe always will be the same as this object */
+	protected MesquiteModule module;
+
+	/** The window, if any, belonging to the MesquiteModule*/
+	MesquiteWindow window=null; 
+
+	/** Vector of specifications for module's menu items*/
+	MenuItemsSpecsVector menuItemsSpecs=null; 
+	/** The specification for the module's own menu.  Each module gets one menu it can request as its basic.  All otherwise unplaced menu items of the module and its
+	employees are placed there.  The module can also specify auxiliary menus.*/
+	MesquiteMenuSpec moduleMenuSpec;  
+	/** The specification for the menu to which items are assigned (if no moduleMenu)*/
+	MesquiteMenuSpec assignedMenuSpec;  
+	/** The vector of the module's auxiliary menus.*/
+	Vector auxiliaryMenus;
+
+	/*if flag off, this modules menus are not put in menubar; instead can be accessed in popupmenu*/
+	private boolean useMenuBar=true;
+	private MRPopup popUp;
+
+	public static boolean menuTracing = false;
+
+	MesquiteMenuItem undoMenuItem = null;
+	boolean undoEnabled = true;
+
+	MesquiteMenuItem previousToolMenuItem = null;
+
+
+	protected Parser parser = new Parser();
+
+	/** true if name of MesquiteModule is to be shown in alerts*/
+	private static final boolean showModuleInAlert = true;
+	/** true if name of MesquiteModule is to be shown in log entries*/
+	private static final boolean showModuleInLog = false;
+	/** true if alerts should show a dialog, or merely write to log.*/
+	private static final boolean alertUseDialog = true;
+
+	protected boolean doomed = false;
+	private static int menuSuppression = 0;
+	private static boolean resetAllMenuPending = false;
+	private static boolean resetWindowsMenuPending = false;
+
+	private static int composeCount = 0;
+
+	private static MenuShortcut newShortcut, openShortcut, saveShortcut, printShortcut, getInfoShortcut, quitShortcut, ccShortcut, previousToolShortcut;
+	private static MenuShortcut undoShortcut, copyShortcut, cutShortcut, clearShortcut, selectAllShortcut, pasteShortcut;
+
+	public static String leftBracket, rightBracket;
+
+	static {
+
+		// A list of keyboard equivalents is at the bottom of this file
+
+		newShortcut = new MenuShortcut(KeyEvent.VK_N);
+		openShortcut = new MenuShortcut(KeyEvent.VK_O);
+		saveShortcut = new MenuShortcut(KeyEvent.VK_S);
+		printShortcut = new MenuShortcut(KeyEvent.VK_P);
+		getInfoShortcut = new MenuShortcut(KeyEvent.VK_I);
+		quitShortcut = new MenuShortcut(KeyEvent.VK_Q);
+		ccShortcut = new MenuShortcut(KeyEvent.VK_PERIOD);
+
+		undoShortcut = new MenuShortcut(KeyEvent.VK_Z);
+		previousToolShortcut = new MenuShortcut(KeyEvent.VK_T);
+		copyShortcut = new MenuShortcut(KeyEvent.VK_C);
+		cutShortcut = new MenuShortcut(KeyEvent.VK_X);
+		clearShortcut = new MenuShortcut(KeyEvent.VK_CLEAR);
+		selectAllShortcut = new MenuShortcut(KeyEvent.VK_A);
+		pasteShortcut = new MenuShortcut(KeyEvent.VK_V);
+		/*if (MesquiteTrunk.isMacOSX()){
+			leftBracket = "◀";//byte[] b = {(byte) 226, (byte)150, (byte)160};  new String(b, "UTF-8");
+			rightBracket = "▶"; //byte[] bb = {(byte) 226, (byte)150, (byte)161};  new String(bb, "UTF-8");
+		}
+		else {*/
+		leftBracket = "«";//byte[] b = {(byte) 226, (byte)150, (byte)160};  new String(b, "UTF-8");
+		rightBracket = "»"; //byte[] bb = {(byte) 226, (byte)150, (byte)161};  new String(bb, "UTF-8");
+		//}
+
+	}
+	/** The constructor in general is to be avoided, because modules are instantiated momentarily on startup to gather
+	information.  The usual functions of a constructor are performed by startJob*/
+	public MenuOwner () {
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	protected void setModule(MesquiteModule mb){
+		module = mb;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void setModuleWindow(MesquiteWindow w){
+		window = w;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public MesquiteWindow getModuleWindow(){
+		return window;
+	}
+
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public boolean isDoomed(){
+		return doomed;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void doom(){
+		doomed = true;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	protected void disposeMenuSpecifications() {
+		if (menuItemsSpecs!=null) {
+			Enumeration e = menuItemsSpecs.elements();
+			while(e.hasMoreElements()){
+				MesquiteMenuItemSpec mmis = (MesquiteMenuItemSpec)e.nextElement();
+				mmis.disconnect();
+			}
+			menuItemsSpecs.dispose();
+		}
+		if (auxiliaryMenus!=null) {
+			auxiliaryMenus.removeAllElements();
+		}
+		moduleMenuSpec=null;
+		menuItemsSpecs = null;
+		auxiliaryMenus = null;
+		assignedMenuSpec = null;
+	}
+	public MenuItemsSpecsVector getMenuItemSpecs(){
+		return menuItemsSpecs;
+	}
+	public boolean needsMenu() {
+		if (menuItemsSpecs != null && menuItemsSpecs.size()>0)
+			return true;
+		if (module == null)
+			return false;
+		EmployeeVector employees = module.getEmployeeVector();
+		if (employees == null)
+			return false;
+		Enumeration e = employees.elements();
+		while(e.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)e.nextElement();
+			if (mb.needsMenu())
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** This resets the menu bar in which the MesquiteModule menu items reside*/
+	public void resetContainingMenuBar() {
+
+		if (resetAllMenuPending)
+			return;
+		else if (menuSuppression==0) { //currently menu rebuilding is not suppressed; therefore do immediately
+			if (window!=null) { 
+				window.resetMenuPending = false;
+				if (!doomed)
+					window.resetMenus();
+			}
+			else if (module.getEmployer()!=null)
+				module.getEmployer().resetContainingMenuBar();
+		}
+		else { //find containerOfModule() and sets its menu bar as needing reset
+			MesquiteWindow w = window;
+			MesquiteModule mb = module;
+			while (mb!=null) {
+				if (mb.window!=null) {
+					mb.window.resetMenuPending = true;
+					return;
+				}
+				mb = mb.getEmployer();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** This requests that the Windows menu of ALL menu bars be recomposed.*/
+	public static final void resetAllWindowsMenus(){
+		if (menuSuppression==0) {
+			resetWindowsMenuPending = false;
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				if (mw!=null) {
+					if (!mw.resetMenuPending){
+						MesquiteModule owner = mw.getOwnerModule();
+						if (owner!=null && !owner.isDoomed())
+							owner.recomposeWindowsMenu(mw.getMesquiteMenuBar(), mw);
+					}
+				}
+			}
+		}
+		else 
+			resetWindowsMenuPending = true; //set this so will later know that full reset is needed
+	}
+	/*.................................................................................................................*/
+	/** This requests that ALL menu bars be recomposed.*/
+	public static final void resetAllMenuBars() {
+		resetWindowsMenuPending = false;
+
+		if (menuSuppression==0) {
+			MesquiteTrunk.suppressResetCheckMenuItems();
+			resetAllMenuPending = false;
+			if (MesquiteTrunk.checkMemory)
+				MesquiteModule.mesquiteTrunk.logln(">- Resetting all menus -<");  //temporary; to check efficiency
+
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				if (mw!=null) {
+					mw.resetMenuPending = false;
+					MesquiteModule owner = mw.getOwnerModule();
+					if (owner==null || !owner.isDoomed())
+						mw.resetMenus();
+				}
+			}
+			MesquiteTrunk.resumeResetCheckMenuItems();
+		}
+		else 
+			resetAllMenuPending = true; //set this so will later know that full reset is needed
+	}
+
+	/*for debugging */
+	public static boolean reportMenuReset = false;
+	/*.................................................................................................................*/
+	/** Increments suppression level of menus; if 0 then menus can be reset. */
+	public static final void incrementMenuResetSuppression(){
+
+		menuSuppression++;
+		if (menuSuppression ==0)
+			menuSuppression = 1;
+		if (reportMenuReset){
+			MesquiteMessage.printStackTrace("increment menuSuppression " + menuSuppression);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Decrements suppression level of menus to zero; then menus can be reset. */
+	public static final void zeroMenuResetSuppression(){
+		menuSuppression =1;
+		decrementMenuResetSuppression();
+		warnAlreadyZero = false;
+	}
+	static boolean warnAlreadyZero = true;
+	/*.................................................................................................................*/
+	/** Decrements suppression level of menus; if 0 then menus can be reset. */
+	public static final void decrementMenuResetSuppression(){
+		if (menuSuppression ==0) {
+			if (warnAlreadyZero)
+				MesquiteMessage.warnProgrammer("decrementMenuResetSuppression when already zero");
+			return;
+		}
+		menuSuppression--;
+		if (menuSuppression<0)
+			menuSuppression =0;
+		if (reportMenuReset){
+			MesquiteMessage.printStackTrace("decrement menuSuppression " + menuSuppression);
+		}
+		if (menuSuppression ==0){  //menu suppression just removed and requests pending; reset menus
+			if (resetAllMenuPending)
+				resetAllMenuBars();
+			else {
+				if (resetWindowsMenuPending)
+					resetAllWindowsMenus();
+				Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					MesquiteModule owner = mw.getOwnerModule();
+					if (mw!=null && mw.resetMenuPending && (owner==null || !owner.isDoomed())){
+						mw.resetMenuPending = false;
+						mw.resetMenus();
+					}
+				}
+			}
+		}
+	}
+	/** Gets whether menu resets are to be suppressed. */
+	public static final int getMenuResetSuppression(){
+		return menuSuppression;
+	}
+	/** Sets suppression level of menu resets. */
+	public static final void setMenuResetSuppression(int r){
+		menuSuppression = r;
+	}
+	/*.................................................................................................................*/
+	/** This indicates what menu is to be used (e.g., employer sets it).  All of its otherwise unplaced menu items, and those of its
+	employees, will be placed there.*/
+	public final void setMenuToUse(MesquiteMenuSpec menu){
+		if (!useMenuBar)
+			return;
+		assignedMenuSpec = menu;
+		if (menu!=null)
+			menu.addGuestModule(module);
+	}
+	/*.................................................................................................................*/
+	boolean usingGuestMenu = false;
+	/** A module requests of this module to have its menu items as guests.*/
+	public final void setUsingGuestMenu(boolean usingGuestMenu){
+		this.usingGuestMenu = usingGuestMenu;
+	}
+	/*.................................................................................................................*/
+	/** A module requests of this module to have its menu items as guests.*/
+	public final void requestGuestMenuPlacement(MesquiteModule mb){
+		if (moduleMenuSpec!=null){
+			moduleMenuSpec.addGuestModule(mb);
+			mb.setUsingGuestMenu(true);
+		}
+	}
+	/*.................................................................................................................*/
+	/** This requests a main menu for the MesquiteModule.  All of its otherwise unplaced menu items, and those of its
+	employees, will be placed there.*/
+	public final MesquiteMenuSpec makeMenu(String menuName){
+		if (moduleMenuSpec!=null)
+			MesquiteMessage.warnProgrammer("Error: module requesting second menu: " + menuName + " (module " + getClass().getName());
+		return moduleMenuSpec = new MesquiteMenuSpec(null, menuName, module);
+	}
+
+	/*.................................................................................................................*/
+	/** This returns the main menu for the MesquiteModule.*/
+	public MesquiteMenuSpec getMenu(){
+		return moduleMenuSpec;
+	}
+	/*.................................................................................................................*/
+	/** This requests the main menu for the MesquiteModule be destroyed.*/
+	public final void destroyMenu(){
+		if (moduleMenuSpec!=null)
+			moduleMenuSpec = null;
+	}
+	/*.................................................................................................................*/
+	/** This requests an auxiliary menu for the MesquiteModule*/
+	public final MesquiteMenuSpec addAuxiliaryMenu(String menuName){
+		if (auxiliaryMenus==null)
+			auxiliaryMenus= new Vector();
+		MesquiteMenuSpec newMenu=new MesquiteMenuSpec(null, menuName, module);
+		auxiliaryMenus.addElement(newMenu);
+		return newMenu;
+	}
+	/*.................................................................................................................*/
+	/** Finds a menu of given name from employers*/
+	public final MesquiteMenuSpec findMenuAmongEmployers(String menuName){
+		if (menuName==null)
+			return null;
+		if (moduleMenuSpec!=null)
+			if (menuName.equals(moduleMenuSpec.getLabel()))
+				return moduleMenuSpec;
+		if (auxiliaryMenus!=null) {
+			for (int i=0; i<auxiliaryMenus.size(); i++)
+				if (menuName.equals(((MesquiteMenuSpec)auxiliaryMenus.elementAt(i)).getLabel()))
+					return ((MesquiteMenuSpec)auxiliaryMenus.elementAt(i));
+		}
+		if (module.getEmployer()!=null)
+			return module.getEmployer().findMenuAmongEmployers(menuName);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void checkMISVector() {
+		if (menuItemsSpecs==null)
+			menuItemsSpecs = new MenuItemsSpecsVector();
+	}
+	/*.................................................................................................................*/
+	/** Sets whether module's menu items are to appear in menubar or not. */
+	public final void setUseMenubar(boolean useMenuBar){
+		this.useMenuBar=useMenuBar;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether module's menu items are to appear in menubar or not. Does not apply to menu items in special menus (file, edit, windows, help).
+	Menu items don't appear in menu bar if the useMenuBar flag is set to false either for this module or for one of its employers */
+	public final boolean getUseMenubar(){
+		if (!useMenuBar)
+			return false;
+		if (window==null && moduleMenuSpec==null && assignedMenuSpec == null && module.getEmployer()!=null) {
+			return module.getEmployer().getUseMenubar(); 
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Shows module's menus in popup. */
+	public final void showPopUp(Container cont, int x, int y){
+		if (cont == null || !cont.isVisible())
+			return;
+		if (popUp==null)
+			popUp = new MRPopup(cont);
+		else
+			popUp.removeAll();
+		composeMenuDescendants(popUp);
+		try {
+			cont.add(popUp);
+			popUp.show(cont, x,y);
+		}
+		catch (Exception e){
+		}
+		//cont.remove(popUp); //todo: this is zapping the menu on linux immediately
+	}
+	/*.................................................................................................................*/
+	/** Called during Mesquite startup when the list of available modules is being constructed; is mined for information about menu commands.
+	When "accumulating" is set, the method is being called not to build menus but to accumulate information about them.
+	Best to be overridden for any defined menus.  The reason for this separate method is so that it can serve both to define menus when modules are hired,
+	but also can serve to accumulate documentation about available menu items at Mesquite startup.  In the latter, strange things are done to subvert addMenuItem
+	addSubmenu and other such methods below so that they divert information to the information accumulator instead of actually making menu item specifications. The system would
+	have been designed a bit differently had information accumulation been a function from the start.*/
+	public void defineMenus(boolean accumulating){
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a dividing line to the module's containing menu. */
+	public final MesquiteMenuItemSpec addMenuLine(){
+		return addMenuItem("-",null);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the module's containing menu.  When selected, the given command will be executed. */
+	public final MesquiteMenuItemSpec addMenuItem(String itemName, MesquiteCommand command){
+		MesquiteMenuItemSpec mmis = MesquiteMenuItemSpec.getMMISpec(null, itemName, module, command);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the given menu.  When selected, the given command will be executed. */
+	public final MesquiteMenuItemSpec addMenuItem(MesquiteMenuSpec whichMenu, String itemName, MesquiteCommand command){
+		MesquiteMenuItemSpec mmis =MesquiteMenuItemSpec.getMMISpec(whichMenu, itemName, module, command);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the given menu.. */
+	public final MesquiteMenuItemSpec addMenuItem(MesquiteMenuSpec whichMenu, MesquiteMenuItemSpec item){
+		item.setInMenu(whichMenu);
+		menuItemsSpecs.addElement(item, false);
+		return (item);
+	}
+	/*.................................................................................................................*/
+	/** Adds a series of menu items, one for each of the modules belonging to the given dutyClass, to a menu.  This differs from
+	the similar addSubMenu in that menu items are not placed in a submenu.  Each menu item has its own command associated. */
+	public final MesquiteMenuItemSpec addModuleMenuItems(MesquiteMenuSpec whichMenu, MesquiteCommand command, Class dutyClass){
+		if (dutyClass ==null)
+			return null;
+		MesquiteMenuItemSpec mmis =MesquiteMenuItemSpec.getMMISpec(whichMenu, null, module, command);
+		if (mmis==null) return null;
+		mmis.setList(dutyClass);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a submenu of the given name.  This submenu will not have a command associated with it.  Instead, menu items with their
+	own independent commands can be added to it using addItemToSubmenu. */
+	public final MesquiteSubmenuSpec addSubmenu(MesquiteMenuSpec whichMenu, String submenuName){
+		MesquiteSubmenuSpec mmis =MesquiteSubmenuSpec.getMSSSpec(whichMenu, submenuName, module);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a submenu of the given name.  What to fill the submenu with SHOULD BE INDICATED BY A SUBSEQUENT CALL TO MesquiteSubmenuSpec.setList. 
+	Then, submenu created will be automatically
+	formulated, and additional items should *not* be added using addItemToSubmenu.  The submenu itself has a command
+	stored with it, and upon receiving a selection even it will append the <strong>item name</strong> selected as argument.*/
+	public final MesquiteSubmenuSpec addSubmenu(MesquiteMenuSpec whichMenu, String submenuName, MesquiteCommand command){
+		MesquiteSubmenuSpec mmis =addSubmenu(whichMenu, submenuName);
+		if (mmis==null) return null;
+		mmis.setCommand(command);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a submenu of the given name with all the modules belonging to the given dutyClass. The submenu created will be automatically
+	formulated, and additional items should *not* be added using addItemToSubmenu.  The submenu itself has a command
+	stored with it, and upon receiving a selection even it will append the <strong>item name</strong> selected as argument.*/
+	public final MesquiteSubmenuSpec addSubmenu(MesquiteMenuSpec whichMenu, String submenuName, MesquiteCommand command, Class dutyClass){
+		MesquiteSubmenuSpec mmis =addSubmenu(whichMenu, submenuName);
+		if (mmis==null) return null;
+		mmis.setCommand(command);
+		mmis.setList(dutyClass);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/** Adds a submenu of the given name with all the items in the ListableVector listed as items. The submenu created will be automatically
+	formulated, and additional items should *not* be added using addItemToSubmenu.  The submenu itself has a command
+	stored with it, and upon receiving a selection even it will append the <strong>number of the item</strong> selected as argument.*/
+	public final MesquiteSubmenuSpec addSubmenu(MesquiteMenuSpec whichMenu, String submenuName, MesquiteCommand command, ListableVector lVector){
+		MesquiteSubmenuSpec mmis =addSubmenu(whichMenu, submenuName);
+		if (mmis==null) return null;
+		mmis.setCommand(command);
+		mmis.setList(lVector);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/** Adds a submenu of the given name with all the items in the String array listed as items. The submenu created will be automatically
+	formulated, and additional items should *not* be added using addItemToSubmenu.  The submenu itself has a command
+	stored with it, and upon receiving a selection even it will append the <strong>number of the item</strong> selected as argument.*/
+	public final MesquiteSubmenuSpec addSubmenu(MesquiteMenuSpec whichMenu, String submenuName, MesquiteCommand command, StringLister names){
+		MesquiteSubmenuSpec mmis =addSubmenu(whichMenu, submenuName);
+		if (mmis==null) return null;
+		mmis.setCommand(command);
+		mmis.setList(names);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a dividing line to the given submenu of the given menu. */
+	public final MesquiteMenuItemSpec addLineToSubmenu(MesquiteMenuSpec whichMenu, MesquiteSubmenuSpec submenu){
+		return addItemToSubmenu(whichMenu, submenu, "-", null);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the given submenu of the given menu.  When selected, the given command will be executed. */
+	public final MesquiteMenuItemSpec addItemToSubmenu(MesquiteMenuSpec whichMenu, MesquiteSubmenuSpec submenu, String itemName, MesquiteCommand command){
+		MesquiteMenuItemSpec mmis =MesquiteMenuItemSpec.getMMISpec(whichMenu, itemName, module, command);
+		if (mmis!=null)
+			mmis.setInSubmenu(submenu);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the given submenu of the given menu.  When selected, the given command will be executed. */
+	public final MesquiteCMenuItemSpec addCheckMenuItemToSubmenu(MesquiteMenuSpec whichMenu, MesquiteSubmenuSpec submenu, String itemName, MesquiteCommand command, MesquiteBoolean b){
+		MesquiteCMenuItemSpec mmis =MesquiteCMenuItemSpec.getMCMISpec(whichMenu, itemName, module, command, b);
+		if (mmis!=null)
+			mmis.setInSubmenu(submenu);
+		return (mmis);
+	}
+
+	/*.................................................................................................................*/
+	/* ����� */
+	/** Adds a menu item to the given submenu of the given menu.  When selected, the given command will be executed. */
+	public final MesquiteMenuItemSpec addItemToSubmenu(MesquiteMenuSpec whichMenu, MesquiteSubmenuSpec submenu, MesquiteMenuItemSpec item){
+		checkMISVector();
+		item.setInMenu(whichMenu);
+		item.setInSubmenu(submenu);
+		menuItemsSpecs.addElement(item, false);
+		return (item);
+	}
+	/*.................................................................................................................*/
+	/** Add check menu item.  Checked according to state of passed MesquiteBoolean */
+	public final MesquiteCMenuItemSpec addCheckMenuItem(MesquiteMenuSpec whichMenu, String itemName, MesquiteCommand command, MesquiteBoolean checkBoolean){
+		MesquiteCMenuItemSpec mmis =MesquiteCMenuItemSpec.getMCMISpec(whichMenu, itemName, module, command, checkBoolean);
+		return (mmis);
+	}
+	/*.................................................................................................................*/
+	/** Delete indicated menu item. */
+	public final void deleteAllMenuItems(){
+		if (menuItemsSpecs!=null) {
+			for (int i = 0; i< menuItemsSpecs.size(); i++)
+				deleteMenuItem((MesquiteMenuItemSpec)menuItemsSpecs.elementAt(i));
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** Delete indicated menu item. */
+	public final void deleteMenuItem(MesquiteMenuItemSpec whichMenuItem){
+		if (whichMenuItem!=null) {
+			if (menuItemsSpecs!=null) {
+				menuItemsSpecs.removeElement(whichMenuItem, false);
+				if (whichMenuItem instanceof MesquiteCMenuItemSpec)
+					((MesquiteCMenuItemSpec)whichMenuItem).releaseBoolean();
+				whichMenuItem.disconnect();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Return the specific menu that had been assigned to contain its items (as opposed to the default menu to contain them). */
+	public final MesquiteMenuSpec getContainingMenuSpec() {
+		if (assignedMenuSpec!=null)
+			return assignedMenuSpec;
+		else if (moduleMenuSpec!=null) {
+			return moduleMenuSpec;
+		}
+		else if (module.getEmployer()!=null)
+			return module.getEmployer().getContainingMenuSpec();
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/**
+	This composes the menu bar for a MesquiteModule.  It is only called for modules that own windows (i.e., a frame that
+	can own a menu bar).  It adds menus in the following sequence:
+	<ol>
+	<li> the File menu belonging to the Mesquite trunk module,
+	<li> the menus belonging to this module's ancestors (employers).  Only the directly ancestral menu items are
+	shown; not the menu items that may fall within an employer's menu but which are contributed by aunts and sisters
+	of the current module
+	<li> the menu items of the current module on its menu or if none on an employer's menu
+	<li> the menu items of the module's employees (on the module's menu or if none on an employer's menu)
+	<li> the Menus of descendant employees
+	<li> the auxiliary menus of the current module
+	<li> the Windows menu belonging to the Mesquite trunk module
+	</ol>
+	 */
+
+	public final synchronized void composeMenuBar(MesquiteMenuBar menuBar, MesquiteWindow whichWindow) {
+		if (module.isDoomed())
+			return;
+		if (System.getProperty("os.name").indexOf("Mac OS")<0 && whichWindow.minimalMenus)
+			return; //minimalMenu windows don't have menu bars in Windows etc.
+		try {
+			composeCount++;
+			if (whichWindow!=null)
+				whichWindow.deassignMenus();
+
+			/* the following needed only if menubar not new (see "couldDelete" in resetMenus of MesquiteWindows 
+		 	if (menuBar!=null) {
+		 		for (int i=menuBar.getMenuCount()-1; i>=0; i--)  
+		 			menuBar.remove(i);
+		 	}
+			/**/
+			if (MesquiteTrunk.fileMenu==null)
+				MesquiteMessage.warnProgrammer("WARNING: file menu null in composeMenuBar for " + module.getName());
+			/*else if (window==null) {
+				MesquiteMessage.warnProgrammer("WARNING: window null in composeMenuBar for " + module.getName());
+				MesquiteMessage.printStackTrace();
+				return;
+			}
+			 */
+			else if (menuBar==null)
+				MesquiteMessage.warnProgrammer("WARNING: menuBar null in composeMenuBar for " + module.getName());
+
+			if (module.isDoomed())
+				return;
+			composeFileMenu(menuBar, MesquiteTrunk.fileMenu, whichWindow);
+			if (module.isDoomed())
+				return;
+			composeEditMenu(menuBar, MesquiteTrunk.editMenu, whichWindow);
+			if (module.isDoomed())
+				return;
+			composeSpecificMenu(menuBar, null, MesquiteTrunk.charactersMenu, true);
+			if (module.isDoomed())
+				return;
+			composeSpecificMenu(menuBar, null, MesquiteTrunk.treesMenu, true);
+
+			//MENUS FORMERLY TO RIGHT OF WINDOW=SPECIFIC
+			if (module.isDoomed())
+				return;
+			MesquiteMenu cMenu = composeSpecificMenuByZones(menuBar, null, MesquiteTrunk.analysisMenu, true);
+			//MesquiteMenu.add(cMenu, new MesquiteMenuItem("Save Window as Macro...", module, MesquiteModule.makeCommand("saveMacroForAnalysis", whichWindow)));  //commandArgument
+			//	MesquiteSubmenu macrosSubmenu = makeMacrosSubmenu(cMenu, module.getFileCoordinator(), MesquiteMacro.ANALYSIS, "Macros Making Windows");
+			//	cMenu.add(macrosSubmenu);
+			//addBottom(cMenu, null, "!");
+			if (module.isDoomed())
+				return;
+			MesquiteMenu wMenu = fillWindowsMenu(menuBar, null, whichWindow);
+			menuBar.add(wMenu);
+			if (module.isDoomed())
+				return;
+			//=============MENUS FORMERLY TO RIGHT OF WINDOW=SPECIFIC
+
+			//@@@@@@@@========  menus that are specific to this module/window
+			resetEmbeddedMenus(whichWindow);
+
+			//else {
+			//	if (MesquiteTrunk.isMacOSX()){
+			Menu spot = new Menu(leftBracket);
+			//	spot.setFont(new Font ("SanSerif", Font.PLAIN, 12));
+			spot.add(new MenuItem("Menus between " + leftBracket + " " + rightBracket));
+			spot.add(new MenuItem("  refer to current window"));
+			menuBar.add(spot);
+			int numBeforeSpecificMenus = menuBar.getMenuCount();
+			MesquiteMenu menu;  
+			if (moduleMenuSpec!=null) {
+				menu = MesquiteMenu.getMenu(moduleMenuSpec);
+			}
+			else menu = null;
+			MesquiteMenu ancestralMenu=null;
+			if (module.isDoomed())
+				return;
+			if (module.getEmployer()!=null)
+				ancestralMenu= module.getEmployer().composeMenuAncestors(menuBar);
+
+			MesquiteMenu menuToUse=null;
+			menuToUse=menu;
+
+			if (menuToUse !=null  && !module.isDoomed())
+				addMyMenuItems(menuToUse);
+
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb !=null && !mb.isDoomed() && mb.getUseMenubar() && !mb.usingGuestMenu && mb.window==null && mb.moduleMenuSpec==null && mb.assignedMenuSpec == null) 
+						mb.composeMenuDescendants(menuToUse);
+				}
+			}
+
+
+			addBottom(menu, null, "%");
+			if (menu!=null && menu.getItemCount()>0) {  //why is this menu and not menuToUse????
+				menuBar.add(menu);
+			}
+
+			if (module.isDoomed())
+				return;
+			composeMenusOfDescendants(menuBar);
+
+			if (module.isDoomed())
+				return;
+			if (auxiliaryMenus!=null) {
+				int num = auxiliaryMenus.size();
+				for (int i=0; i<num; i++){
+					Object obj = auxiliaryMenus.elementAt(i);
+					MesquiteMenuSpec m = (MesquiteMenuSpec)obj;
+					if (m!=null) {
+						composeSpecificMenu(menuBar, null, m, true);
+					}
+				}
+			}
+			//}
+			if (!MesquiteTrunk.isMacOSX() && whichWindow.isLoneWindow()){
+				MesquiteMenu wwMenu = fillWindowMenu(menuBar, whichWindow);
+				menuBar.add(wwMenu);
+			}
+			if (numBeforeSpecificMenus == menuBar.getMenuCount()){
+				menuBar.remove(spot);
+			}
+			else {
+				Menu spot2 = new Menu(rightBracket);
+				spot2.add(new MenuItem("Menus between " + leftBracket + " " + rightBracket));
+				spot2.add(new MenuItem("  refer to current window"));
+				menuBar.add(spot2);
+			}
+			//		}
+			MesquiteMenu hMenu = composeSpecificMenu(menuBar, null, MesquiteTrunk.helpMenu, false);
+
+			menuBar.setHelpMenu(hMenu);
+			//@@@@@@@@========  menus that are specific to this module/window
+
+
+
+			//RIGHT MENUS USED TO GO HERE
+
+
+			if (module.isDoomed())
+				return;
+			if (menuBar!=null) {
+				for (int i=menuBar.getMenuCount()-1; i>=1; i--){  //leave first (file menu) in place
+					try{
+						if (menuEmpty(menuBar.getMenu(i))) 
+							menuBar.remove(i);
+						else
+							removeEmptySubmenus(menuBar.getMenu(i));
+					}
+					catch (Exception e){
+					}
+				}
+			}
+			if (menuBar!=null) {
+				for (int i=0; i<menuBar.getMenuCount(); i++)  
+					sortSubmenusBySpecsOrder(menuBar.getMenu(i));  //this is a kludge to repair an issue of ordering: submenus of submenus floating to top
+			}
+
+		}
+		catch (NullPointerException e){
+			e.printStackTrace();
+		}
+	}
+
+	public void removeEmptySubmenus(Menu parent){
+		for (int i=parent.getItemCount()-1; i>=0; i--){  
+			try{
+				MenuItem item = parent.getItem(i);
+				if (item instanceof Menu){
+					if (menuEmpty((Menu)item))
+						parent.remove(i);
+					else 
+						removeEmptySubmenus((Menu)item);
+				}
+			}
+			catch (Exception e){
+			}
+		}
+	}
+	/*-------------------------------------------------------------*/
+	public Vector getEmbeddedMenusVector(){
+		return embeddedMenusVector;
+	}
+
+	public void resetEmbeddedMenus(MesquiteWindow whichWindow){
+		if ((window != null && window.getShowInfoBar()) && (MesquiteTrunk.isMacOSX() || (whichWindow == null || !whichWindow.isLoneWindow()))) // && MesquiteTrunk.isMacOSX())   //these menus belong in the window, as long as an info bar is shown
+			embeddedMenusVector = composeEmbeddedMenuBar(whichWindow);
+		else
+			embeddedMenusVector = null;
+	}
+	Vector embeddedMenusVector = null;
+	public Vector composeEmbeddedMenuBar(MesquiteWindow whichWindow){
+		MesquitePopup menu;
+		Vector menuVector = new Vector();
+
+		if (moduleMenuSpec!=null) {
+			menu = MesquitePopup.getPopupMenu(moduleMenuSpec, whichWindow.infoBar);
+		}
+		else menu = null;
+		MesquitePopup ancestralMenu=null;
+		if (module.isDoomed())
+			return null;
+		if (module.getEmployer()!=null)
+			ancestralMenu= module.getEmployer().composeMenuAncestors(menuVector);
+
+		MesquitePopup menuToUse=menu;
+
+		if (menuToUse !=null  && !module.isDoomed())
+			addMyMenuItems(menuToUse);
+
+		ListableVector L =module.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++){
+				Object obj = L.elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb !=null && !mb.isDoomed() && mb.getUseMenubar() && !mb.usingGuestMenu && mb.window==null && mb.moduleMenuSpec==null && mb.assignedMenuSpec == null) 
+					mb.composeMenuDescendants(menuToUse);
+			}
+		}
+
+
+		addBottom(menu, null, "%");
+		if (menu!=null && menu.getItemCount()>0) {  //why is this menu and not menuToUse????
+			menuVector.add(menu);
+		}
+
+		if (module.isDoomed())
+			return null;
+		composeMenusOfDescendants(menuVector);
+
+		if (module.isDoomed())
+			return null;
+		if (auxiliaryMenus!=null) {
+			int num = auxiliaryMenus.size();
+			for (int i=0; i<num; i++){
+				Object obj = auxiliaryMenus.elementAt(i);
+				MesquiteMenuSpec m = (MesquiteMenuSpec)obj;
+				if (m!=null) {
+					composeSpecificMenu(menuVector, null, m, true);
+				}
+			}
+		}
+
+		if (module != MesquiteTrunk.mesquiteTrunk){  //Window menu
+			MesquitePopup windowMenu = fillWindowMenu(menuVector, whichWindow);
+			menuVector.add(windowMenu);
+		}
+		return menuVector;
+		/*
+		 * MesquiteMenu ancestralMenu=null;
+		if (module.isDoomed())
+			return;
+		if (module.getEmployer()!=null)
+			ancestralMenu= module.getEmployer().composeMenuAncestors(menuBar);
+
+		MesquiteMenu menuToUse=null;
+		menuToUse=menu;
+
+		if (menuToUse !=null  && !module.isDoomed())
+			addMyMenuItems(menuToUse);
+
+		ListableVector L =module.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++){
+				Object obj = L.elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb !=null && !mb.isDoomed() && mb.getUseMenubar() && mb.window==null && mb.moduleMenuSpec==null && mb.assignedMenuSpec == null) 
+					mb.composeMenuDescendants(menuToUse);
+			}
+		}
+
+
+		addBottom(menu, null, "%");
+		if (menu!=null && menu.getItemCount()>0) {  //why is this menu and not menuToUse????
+			menuBar.add(menu);
+		}
+
+		if (module.isDoomed())
+			return;
+		composeMenusOfDescendants(menuBar);
+
+		if (module.isDoomed())
+			return;
+		if (auxiliaryMenus!=null) {
+			int num = auxiliaryMenus.size();
+			for (int i=0; i<num; i++){
+				Object obj = auxiliaryMenus.elementAt(i);
+				MesquiteMenuSpec m = (MesquiteMenuSpec)obj;
+				if (m!=null) {
+					composeSpecificMenu(menuBar, null, m, true);
+				}
+			}
+		}
+		if (module != MesquiteTrunk.mesquiteTrunk){
+			MesquiteMenu windowMenu = fillWindowMenu(menuBar, whichWindow);
+			menuBar.add(windowMenu);
+		}
+		 */
+	}
+	void addBottom(Menu menu, MesquiteModule mb, String e){
+		if (menu == null)
+			return;
+		long menuOwnerID = -1;
+		MesquiteModule useModule = module;
+		if (mb !=null) 
+			useModule = mb;
+		long moduleID = useModule.getID();
+		boolean myMenu = false;
+		Vector guests=null;
+
+		MesquiteMenuSpec mms = null;
+		if (menu instanceof MesquitePopup)
+			mms = ((MesquitePopup)menu).getSpecification();
+		else if (menu instanceof MesquiteMenu)
+			mms = ((MesquiteMenu)menu).getSpecification();
+		if (mms!=null) {
+			menuOwnerID = mms.getOwnerModuleID();
+			myMenu = (mms == useModule.moduleMenuSpec || mms == useModule.assignedMenuSpec);
+			guests = mms.getGuests();
+		}
+		if (guests!=null)
+			for (int i=0; i<guests.size(); i++) { 
+				MesquiteModule guest = (MesquiteModule)guests.elementAt(i);
+				guest.addMyMenuItems(menu);
+			}
+
+
+		/*
+	# % @
+		 */
+		if (menuOwnerID == moduleID && myMenu)
+			addMacrosMenus(menu, useModule);
+		if (guests!=null)
+			for (int i=0; i<guests.size(); i++) { 
+				MesquiteModule guest = (MesquiteModule)guests.elementAt(i);
+				addMacrosMenus(menu, guest);
+			}
+
+	}
+	private void addMacrosMenus(Menu menu, MesquiteModule useModule){
+		if (useModule.getAutoSaveMacros()) {
+			MesquiteMenu.add(menu, new MenuItem("-"));
+			MesquiteMenu.add(menu, new MesquiteMenuItem("Save Macro for " +  useModule.getNameForMenuItem() + "...", useModule, useModule.makeCommand("saveMacro", useModule)));  //commandArgument
+		}
+		if (!(useModule instanceof FileCoordinator)) {
+			MesquiteSubmenu ms = makeMacrosSubmenu(menu, useModule, 0, "Macros for " + useModule.getNameForMenuItem());
+			if (ms!=null) 
+				menu.add(ms);
+		}
+	}
+	/*.................................................................................................................*/
+	/**
+	This recomposes the Windows menu for a MesquiteModule.  It is only called for modules that own windows (i.e., a frame that
+	can own a menu bar). 
+	 */
+	public final synchronized void recomposeWindowsMenu(MesquiteMenuBar menuBar, MesquiteWindow whichWindow) {
+		MesquiteMenu currentWindowsMenu = null;
+		int currentWindowsNumber = menuBar.getMenuCount()-2;
+		if (menuBar==null)
+			return;
+		else {
+			for (int i=menuBar.getMenuCount()-1; i>=0 && currentWindowsMenu==null; i--){  //leave first (file menu) in place
+				Menu m = menuBar.getMenu(i);
+				if (m instanceof MesquiteMenu && ((MesquiteMenu)m).getSpecification() == MesquiteTrunk.windowsMenu){
+					currentWindowsMenu = (MesquiteMenu)m;
+					currentWindowsMenu.removeAll();
+					currentWindowsNumber = i;
+				}
+			}
+		}
+		fillWindowsMenu(menuBar, currentWindowsMenu, whichWindow);
+	}
+	private MesquitePopup fillWindowMenu(Vector menuBar, MesquiteWindow whichWindow){
+		MesquitePopup wMenu = MesquitePopup.getPopupMenu(new MesquiteMenuSpec(null, "Window", module), whichWindow.infoBar);  
+		if (whichWindow!=null) {
+			if (whichWindow.permitViewMode()){   
+				MesquiteSubmenu setViewModeMenu = MesquiteSubmenu.getSubmenu("View Mode", wMenu, module);
+				setViewModeMenu.add(new MesquiteMenuItem("Graphics (Standard)", module, MesquiteModule.makeCommand("showPage", whichWindow), Integer.toString(0)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Text", module, module.makeCommand("showPage", whichWindow), Integer.toString(1)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Parameters", module, module.makeCommand("showPage", whichWindow), Integer.toString(2)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Modules", module, module.makeCommand("showPage", whichWindow), Integer.toString(3)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Citations", module, module.makeCommand("showPage", whichWindow), Integer.toString(4)));  //commandArgument
+				wMenu.add(setViewModeMenu);
+			}
+			//wMenu.add(whichWindow.infoBarMenuItem);
+			if (module.getEmployer()!=null && module.getEmployer().getClonableEmployeeCommand(module)!=null) {
+				wMenu.add(whichWindow.cloneWindowMenuItem);
+			}
+			//experimental
+			wMenu.add("-");
+			wMenu.add(whichWindow.saveRecipeMenuItem);
+
+
+			MesquiteSubmenu macrosSubmenu = makeMacrosSubmenu(wMenu, module.getFileCoordinator(), 0, "Macros");
+			if (macrosSubmenu !=null) {
+				wMenu.add(macrosSubmenu);
+			}
+			MesquiteSubmenu scriptingSubmenu=MesquiteSubmenu.getSubmenu("Scripting", wMenu, module);  //make submenu
+			scriptingSubmenu.add(whichWindow.snapshotMenuItem); //��� scripting
+			scriptingSubmenu.add(whichWindow.sendScriptMenuItem);  //��� scripting
+			wMenu.add(scriptingSubmenu);
+			wMenu.add("-");
+			whichWindow.setPopTileMenuItemNames();
+			if (!whichWindow.isPoppedOut()) {
+				wMenu.add(whichWindow.popOutWindowMenuItem);
+				wMenu.add(whichWindow.tileOutWindowMenuItem);
+			} else {
+				if (whichWindow.getPopAsTile())
+					wMenu.add(whichWindow.tileOutWindowMenuItem);
+				else 
+					wMenu.add(whichWindow.popOutWindowMenuItem);
+			}
+
+			//wMenu.add("-", insertPoint);
+		}
+		return wMenu;
+	}
+	private MesquiteMenu fillWindowMenu(MesquiteMenuBar menuBar, MesquiteWindow whichWindow){
+		MesquiteMenu wMenu = MesquiteMenu.getMenu(new MesquiteMenuSpec(null, "Window", module));  
+		if (whichWindow!=null) {
+			if (whichWindow.permitViewMode()){  
+				MesquiteSubmenu setViewModeMenu = MesquiteSubmenu.getSubmenu("View Mode", wMenu, module);
+				setViewModeMenu.add(new MesquiteMenuItem("Graphics (Standard)", module, MesquiteModule.makeCommand("showPage", whichWindow), Integer.toString(0)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Text", module, module.makeCommand("showPage", whichWindow), Integer.toString(1)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Parameters", module, module.makeCommand("showPage", whichWindow), Integer.toString(2)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Modules", module, module.makeCommand("showPage", whichWindow), Integer.toString(3)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Citations", module, module.makeCommand("showPage", whichWindow), Integer.toString(4)));  //commandArgument
+				wMenu.add(setViewModeMenu);
+			}
+			//wMenu.add(whichWindow.infoBarMenuItem);
+			if (module.getEmployer()!=null && module.getEmployer().getClonableEmployeeCommand(module)!=null) {
+				wMenu.add(whichWindow.cloneWindowMenuItem);
+			}
+			//experimental
+			wMenu.add("-");
+			wMenu.add(whichWindow.saveRecipeMenuItem);
+
+
+			MesquiteSubmenu macrosSubmenu = makeMacrosSubmenu(wMenu, module.getFileCoordinator(), 0, "Macros");
+			if (macrosSubmenu !=null) {
+				wMenu.add(macrosSubmenu);
+			}
+			MesquiteSubmenu scriptingSubmenu=MesquiteSubmenu.getSubmenu("Scripting", wMenu, module);  //make submenu
+			scriptingSubmenu.add(whichWindow.snapshotMenuItem); //��� scripting
+			scriptingSubmenu.add(whichWindow.sendScriptMenuItem);  //��� scripting
+			wMenu.add(scriptingSubmenu);
+			wMenu.add("-");
+			whichWindow.setPopTileMenuItemNames();
+			if (!whichWindow.isPoppedOut()) {
+				wMenu.add(whichWindow.popOutWindowMenuItem);
+				wMenu.add(whichWindow.tileOutWindowMenuItem);
+			} else {
+				if (whichWindow.getPopAsTile())
+					wMenu.add(whichWindow.tileOutWindowMenuItem);
+				else 
+					wMenu.add(whichWindow.popOutWindowMenuItem);
+			}
+
+			//wMenu.add("-", insertPoint);
+		}
+		return wMenu;
+	}	
+
+	private MesquiteMenu fillWindowsMenu(MesquiteMenuBar menuBar, MesquiteMenu currentWindowsMenu, MesquiteWindow whichWindow){
+		MesquiteMenu wMenu = currentWindowsMenu; //composeSpecificMenu(menuBar, currentWindowsMenu, MesquiteTrunk.windowsMenu, false);
+		if (wMenu ==null)
+			wMenu= MesquiteMenu.getMenu(MesquiteTrunk.windowsMenu);
+		if (whichWindow!=null) {
+			/*
+			 * if (whichWindow.permitViewMode()){   
+				MesquiteSubmenu setViewModeMenu = MesquiteSubmenu.getSubmenu("View Mode", wMenu, module);
+				setViewModeMenu.add(new MesquiteMenuItem("Graphics (Standard)", module, module.makeCommand("showPage", whichWindow), Integer.toString(0)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Text", module, module.makeCommand("showPage", whichWindow), Integer.toString(1)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Parameters", module, module.makeCommand("showPage", whichWindow), Integer.toString(2)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Modules", module, module.makeCommand("showPage", whichWindow), Integer.toString(3)));  //commandArgument
+				setViewModeMenu.add(new MesquiteMenuItem("Citations", module, module.makeCommand("showPage", whichWindow), Integer.toString(4)));  //commandArgument
+				wMenu.add(setViewModeMenu);
+			}
+			//wMenu.add(whichWindow.infoBarMenuItem);
+			 */
+			wMenu.add(whichWindow.explanationsMenuItem);
+			/*if (module.getEmployer()!=null && module.getEmployer().getClonableEmployeeCommand(module)!=null) {
+				wMenu.add(whichWindow.cloneWindowMenuItem);
+			}
+			 */
+			//experimental
+			wMenu.add("-");
+			/*
+			wMenu.add(whichWindow.saveRecipeMenuItem);
+
+
+			MesquiteSubmenu macrosSubmenu = makeMacrosSubmenu(wMenu, module.getFileCoordinator(), 0, "Macros");
+			if (macrosSubmenu !=null) {
+				wMenu.add(macrosSubmenu);
+			}
+			MesquiteSubmenu scriptingSubmenu=MesquiteSubmenu.getSubmenu("Scripting", wMenu, module);  //make submenu
+			scriptingSubmenu.add(whichWindow.snapshotMenuItem); //��� scripting
+			scriptingSubmenu.add(whichWindow.sendScriptMenuItem);  //��� scripting
+			wMenu.add(scriptingSubmenu);
+			 */
+			//wMenu.add("-", insertPoint);
+		}
+		wMenu.add("-");
+		wMenu.add(new MesquiteMenuItem("Bring All Windows To Front", module, MesquiteTrunk.mesquiteTrunk.showAllCommand));
+		MesquiteSubmenu msm = new MesquiteSubmenu("Projects", wMenu, MesquiteModule.mesquiteTrunk);
+		wMenu.add(msm);
+		for (int i=0; i< MesquiteTrunk.projects.getNumProjects(); i++){
+			MesquiteProject proj = MesquiteTrunk.projects.getProject(i);
+			msm.add(new MesquiteMenuItem(proj.getName(), proj.getCoordinatorModule(), MesquiteModule.makeCommand("allToFront", proj.getCoordinatorModule())));
+		}
+		addCurrentWindows(wMenu);
+		composeSpecificMenu(menuBar, wMenu, MesquiteTrunk.windowsMenu, false);
+		return wMenu;
+	}
+	/*.................................................................................................................*/
+	boolean menuEmpty(Menu menu) {
+		if (menu.getItemCount() ==0)
+			return true;
+		else {
+			for (int i=0; i<menu.getItemCount(); i++) {
+				MenuItem item = menu.getItem(i);
+				if (item instanceof Menu) {  //item is submenu; return nonempty if item in it
+					if (!menuEmpty((Menu)item))
+						return false;
+				}
+				else
+					return false; //item is not submenu; return nonempty
+			}
+			return true;
+		}
+	}
+	/*.................................................................................................................*/
+	final MesquiteMenu composeMenuAncestors(MesquiteMenuBar menuBar) {
+		MesquiteMenu putHere;
+		if (moduleMenuSpec!=null) {
+			putHere = MesquiteMenu.getMenu(moduleMenuSpec);
+			addMyMenuItems(putHere);
+			//addBottom(putHere, null, "^");
+			menuBar.add(putHere);
+			if (module.getEmployer()!=null) 
+				module.getEmployer().composeMenuAncestors(menuBar);
+			return putHere;
+		}
+		else if (module.getEmployer()!=null) {
+			putHere = module.getEmployer().composeMenuAncestors(menuBar);
+			if (putHere!=null) {
+				addMyMenuItems(putHere);
+			}
+			return putHere;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	final MesquitePopup composeMenuAncestors(Vector menuBar) {
+		MesquitePopup putHere;
+		if (moduleMenuSpec!=null) {
+			putHere = MesquitePopup.getPopupMenu(moduleMenuSpec, null);
+			addMyMenuItems(putHere);
+			//addBottom(putHere, null, "^");
+			menuBar.addElement(putHere);
+			if (module.getEmployer()!=null) 
+				module.getEmployer().composeMenuAncestors(menuBar);
+			return putHere;
+		}
+		else if (module.getEmployer()!=null) {
+			putHere = module.getEmployer().composeMenuAncestors(menuBar);
+			if (putHere!=null) {
+				addMyMenuItems(putHere);
+			}
+			return putHere;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	final boolean inMenuBar(Menu menu) {  
+		if (menu==null)
+			return false;
+		if (menu instanceof MesquitePopup)
+			return false;
+		MenuContainer p = menu.getParent();
+		while (p!=null) {
+			if (p instanceof MesquitePopup)
+				return false;
+			else if (p instanceof MenuBar) 
+				return true;
+			else if (p instanceof MenuComponent)
+				p = ((MenuComponent)p).getParent();
+			else
+				return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	final void composeMenuDescendants(Menu menu) {  
+		if (doomed) 
+			;//MesquiteMessage.println("Error: composing menu of module that has been turned off: " + getName());
+		else {
+			if (menuTracing) MesquiteMessage.notifyProgrammer("Composing menu of " + module.getName());
+			addMyMenuItems(menu);
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if ((mb.getUseMenubar() || !inMenuBar(menu)) && !mb.usingGuestMenu &&  mb.window==null && mb.moduleMenuSpec==null && mb.assignedMenuSpec == null) {
+						mb.composeMenuDescendants(menu);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	final void composeMenusOfDescendants(Vector menuBar) {  
+		if (doomed) 
+			;//MesquiteMessage.println("Error: composing menu of module that has been turned off: " + getName());
+		else {
+			if (menuTracing) MesquiteMessage.notifyProgrammer("Composing menu of " + module.getName());
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb.getUseMenubar() && !mb.usingGuestMenu && mb.window==null ) {
+						if (mb.moduleMenuSpec!=null) {
+							MesquitePopup menu = MesquitePopup.getPopupMenu(mb.moduleMenuSpec, null);
+							mb.composeMenuDescendants(menu);
+							addBottom(menu, mb, "@");
+							if (menu.getItemCount()>0) {
+								menuBar.add(menu);
+							}
+						}
+						if (mb.auxiliaryMenus!=null) {
+							num = mb.auxiliaryMenus.size();
+							for (int j=0; j<num; j++){
+								obj = mb.auxiliaryMenus.elementAt(j);
+								MesquiteMenuSpec m = (MesquiteMenuSpec)obj;
+								if (m!=null) {
+									mb.composeSpecificMenu(menuBar, null, m, true);
+								}
+							}
+						}
+						mb.composeMenusOfDescendants(menuBar);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	final void composeMenusOfDescendants(MesquiteMenuBar menuBar) {    ///TO BE DELETED
+		if (doomed) 
+			;//MesquiteMessage.println("Error: composing menu of module that has been turned off: " + getName());
+		else {
+			if (menuTracing) MesquiteMessage.notifyProgrammer("Composing menu of " + module.getName());
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb.getUseMenubar() && !mb.usingGuestMenu && mb.window==null ) {
+						if (mb.moduleMenuSpec!=null) {
+							MesquiteMenu menu = MesquiteMenu.getMenu(mb.moduleMenuSpec);
+							mb.composeMenuDescendants(menu);
+							addBottom(menu, mb, "@");
+							if (menu.getItemCount()>0) {
+								menuBar.add(menu);
+							}
+						}
+						if (mb.auxiliaryMenus!=null) {
+							num = mb.auxiliaryMenus.size();
+							for (int j=0; j<num; j++){
+								obj = mb.auxiliaryMenus.elementAt(j);
+								MesquiteMenuSpec m = (MesquiteMenuSpec)obj;
+								if (m!=null) {
+									mb.composeSpecificMenu(menuBar, null, m, true);
+								}
+							}
+						}
+						mb.composeMenusOfDescendants(menuBar);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	int addListableToMenu (int currentCount, Menu menu, MesquiteMenuItemSpec mmi, Object o, MesquiteInteger j, int priorityLevel) {
+		Enumeration e = mmi.getListableVector().elements();
+		int count = currentCount;
+		while (count++<128 && e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof Listened && !((Listened)obj).isUserVisible()){
+			}
+			else if (!considerPriorities || ((obj instanceof Priority && ((Priority)obj).getPriority()==priorityLevel) || (!(obj instanceof Priority) && priorityLevel==0))) {
+				Listable mw = (Listable)obj;
+				String name = null;
+				if (mw instanceof MesquiteModule)
+					name = ((MesquiteModule)mw).getNameForMenuItem();
+				else
+					name = mw.getName();
+				if (mmi.getListableFilter()==null || mmi.getListableFilter().isInstance(mw)) {
+					int hiddenStatus = 0;
+					Class moduleClass = null;
+					if (mw instanceof MesquiteModule)
+						moduleClass = mw.getClass();
+					else if (mw instanceof MesquiteModuleInfo)
+						moduleClass = ((MesquiteModuleInfo)mw).getModuleClass();
+					if (InterfaceManager.isFilterable(menu) && ((hiddenStatus = InterfaceManager.isHiddenMenuItem(mmi, name,  j.toString(), mmi.command, moduleClass)) == InterfaceManager.HIDDEN))
+						;
+					else if (mw instanceof CompatibilityChecker && o !=null){
+						if (((CompatibilityChecker)mw).isCompatible(o, null, null)) {
+							MesquiteMenuItem m =new MesquiteMenuItem(name, null /*mmi.ownerModule*/, mmi.command, j.toString());
+							m.setHiddenStatus(hiddenStatus);
+							j.add(1);
+							m.setDocument(mmi.getDocumentItems());
+							m.setReferent(mw);
+							MesquiteMenu.add(menu, m);
+						}
+					}
+					else  {
+						MesquiteMenuItem m =new MesquiteMenuItem(name, null /*mmi.ownerModule*/, mmi.command, j.toString());
+						j.add(1);
+						m.setHiddenStatus(hiddenStatus);
+						m.setDocument(mmi.getDocumentItems());
+						m.setReferent(mw);
+						MesquiteMenu.add(menu, m);
+					}
+				}
+			}			
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	final boolean addListsToMenu(MesquiteMenuItemSpec mmi, Menu menu) {
+		if (mmi.getDutyClass()!=null) {  //module dutyClass specified; need to create list of modules to choose
+			MesquiteModuleInfo mbi=null;
+			int count = 0;
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(mmi.getDutyClass(), mbi))!=null) {
+				int hiddenStatus = 0;
+				if (moduleIsCompatible(mmi, mbi) && mbi.getUserChooseable() && (!InterfaceManager.isFilterable(menu) || (hiddenStatus = InterfaceManager.isHiddenMenuItem(mmi, mbi.getNameForMenuItem(),  StringUtil.tokenize(mbi.getName()), mmi.command, mbi.getModuleClass(), mmi.getDutyClass())) != InterfaceManager.HIDDEN)) {
+					if (mbi.getHireSubchoice()==null) {
+						MesquiteMenuItem m = new MesquiteMenuItem(mbi.getNameForMenuItem(), null /*mmi.ownerModule*/, mmi.command, StringUtil.tokenize(mbi.getName()));
+						m.setHiddenStatus(hiddenStatus, mmi.getDutyClass());
+						m.setDocument(mmi.getDocumentItems());
+						m.setReferent(mbi);
+						MesquiteMenu.add(menu, m);
+
+					}
+					else {
+						MesquiteSubmenu submenu=MesquiteSubmenu.getSubmenu(mbi.getNameForMenuItem(), menu, module);  //make submenu
+						submenu.setHiddenStatus(hiddenStatus, mmi.getDutyClass());
+						submenu.setReferent(mbi);
+						MesquiteMenu.add(menu, submenu);
+
+						//populate it with subchoices
+						MesquiteModuleInfo smbi=null;
+						int count2 = 0;
+						int countPrimary2 = 0;
+						int countOthers2 = 0;
+						if (EmployerEmployee.useOtherChoices)
+							while (count2++<128 && (smbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModuleFilteredByNot( mbi.getHireSubchoice(), mbi.getDontHireSubchoice(), smbi))!=null) {
+								if (!smbi.getUserChooseable())
+									;
+								else if (smbi.isPrimary(mbi.getHireSubchoice())) 
+									countPrimary2++;
+								else
+									countOthers2++;
+							}
+						boolean useOthers2 = EmployerEmployee.useOtherChoices &&  countOthers2>0 && countPrimary2>0;
+						Listable[] others2 = null;
+						if (useOthers2)
+							others2 = new Listable[countOthers2];
+						smbi = null;
+						countOthers2 =0;
+						count2 = 0;
+						while (count2++<128 && (smbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModuleFilteredByNot( mbi.getHireSubchoice(), mbi.getDontHireSubchoice(),smbi))!=null) {
+							int hiddenStatus2 = 0;
+							if (!smbi.getUserChooseable())
+								;
+							else if (InterfaceManager.isFilterable(submenu) && (hiddenStatus2 = InterfaceManager.isHiddenMenuItem(mmi, smbi.getNameForMenuItem(),  "$ " + StringUtil.tokenize(mbi.getName()) + "  " + StringUtil.tokenize(smbi.getName()), mmi.command, smbi.getModuleClass(), mbi.getHireSubchoice())) == InterfaceManager.HIDDEN)
+								;
+							else if (useOthers2 && !smbi.isPrimary(mbi.getHireSubchoice()))
+								others2[countOthers2++] = smbi;
+							else {
+								MesquiteMenuItem m = new MesquiteMenuItem(smbi.getNameForMenuItem(), null /*mmi.ownerModule*/, mmi.command, "$ " + StringUtil.tokenize(mbi.getName()) + "  " + StringUtil.tokenize(smbi.getName()));
+								m.setDocument(mmi.getDocumentItems());
+								m.setHiddenStatus(hiddenStatus2, mbi.getHireSubchoice());
+								m.setReferent(smbi);
+								submenu.add(m);
+							}
+						}
+						if (useOthers2) {
+							//make new mesquite menu item "others"
+							submenu.add(new MenuItem("-"));
+							MesquiteMenuItem othersItem =new MesquiteMenuItem("Other Choices...", null, mmi.command, "$ " + StringUtil.tokenize(mbi.getName()) + "  ");  
+							othersItem.setOthers(others2);
+							submenu.add(othersItem);
+						}
+					}
+				}
+			}
+			return true;
+		}
+		else if (mmi.getListableVector()!=null) { //
+			MesquiteInteger j=new MesquiteInteger(0);
+			Object o = mmi.getCompatibilityCheck();
+			//int count = 0;
+			int count = 0;
+			if (considerPriorities)
+				for (int i=1; i<MAXPRIORITY; i++)
+					count = addListableToMenu(count, menu, mmi, o, j, i);
+			count = addListableToMenu(count, menu, mmi, o, j, 0);
+			return true;
+		}
+		else if (mmi.getStrings()!=null) {  //
+			String[] names = mmi.getStrings();
+			for (int j=0; j<names.length; j++) {
+				if (names[j]!=null) {
+					int hiddenStatus = 0;
+					if (!InterfaceManager.isFilterable(menu) || (hiddenStatus =InterfaceManager.isHiddenMenuItem(mmi, names[j],  StringUtil.tokenize(names[j]), mmi.command , null)) != InterfaceManager.HIDDEN){
+						MesquiteMenuItem m =new MesquiteMenuItem(names[j], null /*mmi.ownerModule*/, mmi.command, StringUtil.tokenize(names[j]) + "  " + j);
+						m.setHiddenStatus(hiddenStatus);
+						m.setDocument(mmi.getDocumentItems());
+						MesquiteMenu.add(menu, m);
+					}
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+	/*................................................................................................................. */
+	final MesquiteSubmenu addSubmenuIfAbsent(Menu containingMenu, MesquiteSubmenuSpec msms) {
+		if (doomed) {
+			;//MesquiteMessage.println("Error: composing menu of module that has been turned off: " + getName());
+		}
+		else {
+			MesquiteSubmenu submenu = findSubmenu(containingMenu, msms);
+			if (submenu ==null) {  //submenu not yet created; create it
+				submenu=MesquiteSubmenu.getSubmenu(msms, containingMenu, module);
+				if (msms.getSelected()!=null) //if selected string is available for check marks
+					submenu.setSelected(msms.getSelected());
+				MesquiteMenu.add(containingMenu, submenu);
+				addMySpecificMenuItems(msms, submenu);   //NEW Nov 07
+			}
+			return submenu;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	final MesquiteSubmenu addSubmenuWithListsIfAbsent(Menu containingMenu, MesquiteSubmenuSpec msms) {
+		//find or make submenu
+		boolean needToAddSubmenu = false;
+		MesquiteSubmenu submenu = findSubmenu(containingMenu, msms);
+		if (submenu ==null) {  //submenu not yet created; create it
+			submenu=MesquiteSubmenu.getSubmenu(msms, containingMenu, module);
+			if (msms.getSelected()!=null) //if selected string is available for check marks
+				submenu.setSelected(msms.getSelected());
+			needToAddSubmenu = true;
+		}
+		fillSubmenu(containingMenu, submenu, msms, needToAddSubmenu);
+		if (needToAddSubmenu)
+			addMySpecificMenuItems(msms, submenu);   //NEW Nov 07
+		return submenu;
+	}
+	boolean moduleIsCompatible(MesquiteMenuItemSpec mmi, MesquiteModuleInfo mbi){
+		return (mmi.getCompatibilityCheck()==null || mbi.isCompatible(mmi.getCompatibilityCheck(), module.getProject(), null)) && (mmi.getListableFilter()==null || mmi.getListableFilter().isAssignableFrom(mbi.getModuleClass()) || ((CompatibilityChecker)mbi).isCompatible(mmi.getListableFilter(), null, null));
+	}
+	/*.................................................................................................................*/
+	int fillSubmenuWithListable (int currentCount, Menu menu, MesquiteSubmenu submenu, MesquiteSubmenuSpec msms, Object o, MesquiteInteger j, int priorityLevel) {
+		Enumeration e = msms.getListableVector().elements();
+		int count=currentCount;
+		while (count++<128 && e.hasMoreElements()) {
+			Object obj = e.nextElement();
+
+			if (obj instanceof Listened && !((Listened)obj).isUserVisible()){
+			}
+			else if (!considerPriorities || ((obj instanceof Priority && ((Priority)obj).getPriority()==priorityLevel) || (!(obj instanceof Priority) && priorityLevel==0))) {
+				Listable mw = (Listable)obj;
+
+				String name = null;
+				String referentID = null;
+				if (mw instanceof MesquiteModule) {
+					name = ((MesquiteModule)mw).getNameForMenuItem();
+					referentID = Long.toString(((MesquiteModule)mw).getID());
+				}
+				else {
+					name = mw.getName();
+					if (mw instanceof Identifiable) {
+						referentID = Long.toString(((Identifiable)mw).getID());
+					}
+				}
+
+				if (msms.getListableFilter()==null || msms.getListableFilter().isInstance(mw) || mw instanceof CompatibilityChecker) {
+
+					boolean OK = !(mw instanceof CompatibilityChecker) || o ==null;
+					if (!OK){  //second chance, might be compatible
+						boolean OK2 = ((CompatibilityChecker)mw).isCompatible(o, null, null);
+						boolean OK3 =  ((CompatibilityChecker)mw).isCompatible(msms.getListableFilter(), null, null);
+						OK = OK2 && OK3;
+					}
+					if (OK){
+						int hiddenStatus = 0;
+						Class moduleClass = null;
+						if (mw instanceof MesquiteModule)
+							moduleClass = mw.getClass();
+						else if (mw instanceof MesquiteModuleInfo)
+							moduleClass = ((MesquiteModuleInfo)mw).getModuleClass();
+						if (msms.isFilterable() && (hiddenStatus = InterfaceManager.isHiddenMenuItem(msms, name,   j.toString(), msms.command , moduleClass)) == InterfaceManager.HIDDEN)
+							;
+						else if (submenu.getSelected()!=null){ //selected string available for checkmark 
+							MesquiteCheckMenuItem m =new MesquiteCheckMenuItem(name, null /*msms.ownerModule*/, msms.command, j.toString() + " " + ParseUtil.tokenize(name), submenu.getSelected());
+							m.setReferentID(referentID);
+							j.add(1);
+							//m.setDocument(msms.getDocumentItems());
+							m.setHiddenStatus(hiddenStatus);
+							m.setReferent(mw);
+							submenu.add(m);
+						}
+						else {
+							MesquiteMenuItem m =new MesquiteMenuItem(name, null /*msms.ownerModule*/, msms.command, j.toString());
+							j.add(1);
+							m.setHiddenStatus(hiddenStatus);
+							m.setDocument(msms.getDocumentItems());
+							m.setReferent(mw);
+							submenu.add(m);
+						}
+					}
+				}
+
+			}
+		}
+		return count;
+	}
+	MenuItem[] primaryItems = new MenuItem[500];
+	MenuItem[] secondaryItems = new MenuItem[500];
+	MenuItem[] primaryItems2 = new MenuItem[500];
+	MenuItem[] secondaryItems2 = new MenuItem[500];
+	private void zeroArray(MenuItem[] m){
+		for (int i= 0; i<m.length; i++)
+			m[i] = null;
+	}
+
+	/*.................................................................................................................*/
+	final boolean fillSubmenu(Menu menu, MesquiteSubmenu submenu, MesquiteSubmenuSpec msms, boolean needToAddSubmenu) {
+		if (msms.getDutyClass()!=null) {        //module dutyClass specified; need to create list of modules to choose
+			MesquiteModuleInfo mbi=null;
+			int countPrimary = 0;
+			int countOthers = 0;
+			int count = 0;
+			zeroArray(primaryItems);
+			zeroArray(secondaryItems);
+			int countItems = 0;
+			//First, find if there are both primary and secondary choices.  If so, use "Other Choice..." system.
+			//	if (EmployerEmployee.useOtherChoices)
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule( msms.getDutyClass(), mbi))!=null) {
+				if (moduleIsCompatible(msms, mbi)) {
+					if (!mbi.getUserChooseable())
+						;
+					else if (mbi.isPrimary(msms.getDutyClass())) 
+						countPrimary++;
+					else
+						countOthers++;
+				}
+			}
+			boolean useOthers = EmployerEmployee.useOtherChoices && countOthers>0 && countPrimary>0;
+			Listable[] others = null;
+			if (useOthers)
+				others = new Listable[countOthers];
+			mbi = null;
+			countOthers = 0;
+			count = 0;
+			while (count++<128 && (mbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule( msms.getDutyClass(), mbi))!=null) {
+				boolean primary = mbi.isPrimary(msms.getDutyClass());
+				if (moduleIsCompatible(msms, mbi)) {
+					int hiddenStatus = 0;
+					if (!mbi.getUserChooseable())
+						;
+					else if (useOthers && !primary)
+						others[countOthers++] = mbi;
+					else 	if (msms.isFilterable() && (hiddenStatus =InterfaceManager.isHiddenMenuItem(msms, mbi.getNameForMenuItem(),  StringUtil.tokenize(mbi.getName()), msms.command, mbi.getModuleClass(), msms.getDutyClass() )) == InterfaceManager.HIDDEN){
+					}
+					else if (mbi.getHireSubchoice()==null) { // potential employee hasn't indicated it would like subemployee submenu
+						if (submenu.getSelected()!=null){ //selected string available for checkmark 
+							MesquiteCheckMenuItem m =new MesquiteCheckMenuItem(mbi.getNameForMenuItem(), null, msms.command, StringUtil.tokenize(mbi.getName()), submenu.getSelected());  
+							//m.setDocument(msms.getDocumentItems());
+							m.setReferent(mbi);
+							m.setHiddenStatus(hiddenStatus, msms.getDutyClass());
+							if (primary)
+								primaryItems[countItems++] = m;
+							else
+								secondaryItems[countOthers++] = m;
+							//	submenu.add(m);
+						}
+						else {
+							MesquiteMenuItem m =new MesquiteMenuItem(mbi.getNameForMenuItem(), null, msms.command, StringUtil.tokenize(mbi.getName()));  
+							m.setDocument(msms.getDocumentItems());
+							m.setReferent(mbi);
+							m.setHiddenStatus(hiddenStatus, msms.getDutyClass());
+							if (primary)
+								primaryItems[countItems++] = m;
+							else
+								secondaryItems[countOthers++] = m;
+
+							//submenu.add(m);
+						}
+					}
+					else { // potential employee has indicated it would like subemployee submenu
+						MesquiteSubmenu submenu2=MesquiteSubmenu.getSubmenu(mbi.getNameForMenuItem(), submenu, module);  //make submenu
+						submenu2.setHiddenStatus(hiddenStatus, msms.getDutyClass());
+						if (primary)
+							primaryItems[countItems++] = submenu2;
+						else
+							secondaryItems[countOthers++] = submenu2;
+						//submenu.add(submenu2);
+						submenu2.setReferent(mbi);
+						//populate it with subchoices
+						MesquiteModuleInfo smbi=null;
+						int count2 = 0;
+						int countPrimary2 = 0;
+						int countOthers2 = 0;
+						zeroArray(primaryItems2);
+						zeroArray(secondaryItems2);
+						int countItems2 = 0;
+						//		if (EmployerEmployee.useOtherChoices)
+						while (count2++<128 && (smbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModuleFilteredByNot( mbi.getHireSubchoice(), mbi.getDontHireSubchoice(), smbi))!=null) {
+							if (!smbi.getUserChooseable())
+								;
+							else if (smbi.isPrimary(mbi.getHireSubchoice())) 
+								countPrimary2++;
+							else
+								countOthers2++;
+						}
+						boolean useOthers2 = EmployerEmployee.useOtherChoices && countOthers2>0 && countPrimary2>0;
+						Listable[] others2 = null;
+						if (useOthers2)
+							others2 = new Listable[countOthers2];
+						smbi = null;
+						countOthers2 =0;
+						count2 = 0;
+						while (count2++<128 && (smbi = MesquiteTrunk.mesquiteModulesInfoVector.findNextModuleFilteredByNot( mbi.getHireSubchoice(), mbi.getDontHireSubchoice(), smbi))!=null) {
+							boolean primary2 = smbi.isPrimary(mbi.getHireSubchoice());
+							int hiddenStatus2 = 0;
+							//TODO: this tokenization of the names for argument will not work if name of module includes '  -- must use full tokenization/detokenization
+							if (!smbi.getUserChooseable() || (msms.isFilterable() && (hiddenStatus2 = InterfaceManager.isHiddenMenuItem(msms, smbi.getNameForMenuItem(),  "$ " + StringUtil.tokenize(mbi.getName()) + "  " + StringUtil.tokenize(smbi.getName()), msms.command, smbi.getModuleClass(), mbi.getHireSubchoice() )) == InterfaceManager.HIDDEN)) 
+								;
+							else if (useOthers2 && !primary2)
+								others2[countOthers2++] = smbi;
+							else if (submenu.getSelected()!=null){ //selected string available for checkmark 
+								MesquiteCheckMenuItem m =new MesquiteCheckMenuItem(smbi.getNameForMenuItem(), null, msms.command, "$ " + StringUtil.tokenize(mbi.getName()) + "  " + StringUtil.tokenize(smbi.getName()), submenu.getSelected());  
+								//m.setDocument(msms.getDocumentItems());
+								m.setReferent(smbi);
+								m.setHiddenStatus(hiddenStatus2, mbi.getHireSubchoice());
+								//submenu2.add(m);
+								if (primary2)
+									primaryItems2[countItems2++] = m;
+								else
+									secondaryItems2[countOthers2++] = m;
+							}
+							else {
+								MesquiteMenuItem m =new MesquiteMenuItem(smbi.getNameForMenuItem(), null, msms.command, "$ " + StringUtil.tokenize(mbi.getName()) + "  " + StringUtil.tokenize(smbi.getName()));
+								m.setDocument(msms.getDocumentItems());
+								m.setHiddenStatus(hiddenStatus2, mbi.getHireSubchoice());
+								m.setReferent(smbi);
+								//submenu2.add(m);
+								if (primary2)
+									primaryItems2[countItems2++] = m;
+								else
+									secondaryItems2[countOthers2++] = m;
+							}
+						}
+						for (int i=0; i<primaryItems2.length && primaryItems2[i] != null; i++)
+							submenu2.add(primaryItems2[i]);
+						if (!useOthers2 && countOthers2>0 && countItems2>0){
+							submenu2.add(new MenuItem("-"));
+							submenu2.add(new MenuItem("-"));
+						}
+						for (int i=0; i<secondaryItems2.length && secondaryItems2[i] != null; i++)
+							submenu2.add(secondaryItems2[i]);
+						if (useOthers2) {
+							//make new mesquite menu item "others"
+							submenu2.add(new MenuItem("-"));
+							MesquiteMenuItem othersItem2 =new MesquiteMenuItem("Other Choices...", null, msms.command, "$ " + StringUtil.tokenize(mbi.getName()) + "  ");  
+							othersItem2.setOthers(others2);
+							submenu2.add(othersItem2);
+						}
+					}
+				}
+
+			}
+			for (int i=0; i<primaryItems.length && primaryItems[i] != null; i++)
+				submenu.add(primaryItems[i]);
+			if (!useOthers && countOthers>0 && countItems>0){
+				submenu.add(new MenuItem("-"));
+				submenu.add(new MenuItem("-"));
+			}
+			for (int i=0; i<secondaryItems.length && secondaryItems[i] != null; i++)
+				submenu.add(secondaryItems[i]);
+			if (useOthers) {
+				//make new mesquite menu item "others"
+				submenu.add(new MenuItem("-"));
+				MesquiteMenuItem othersItem =new MesquiteMenuItem("Other Choices...", null /*msms.ownerModule*/, msms.command, null);  
+				othersItem.setOthers(others);
+				submenu.add(othersItem);
+			}
+			if (submenu.getItemCount()<=1 && msms.getBehaviorIfNoChoice() != MesquiteSubmenuSpec.SHOW_SUBMENU){
+				int b = msms.getBehaviorIfNoChoice();
+				int hiddenStatus = 0;
+				if (msms.isFilterable() && (hiddenStatus = InterfaceManager.isHiddenMenuItem(msms, msms.getSubmenuName(),  null, msms.command, null)) == InterfaceManager.HIDDEN) 
+					;
+				else if (b == MesquiteSubmenuSpec.ONEDISABLE_ZERODISABLE || (submenu.getItemCount()==0 && (b == MesquiteSubmenuSpec.ONESUBMENU_ZERODISABLE || b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE))){
+					//add a menu item here instead of submenu & disable it
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					m.setHiddenStatus(hiddenStatus);
+					MesquiteMenu.add(menu, m);
+					m.setEnabled(false);
+					needToAddSubmenu = false;
+				}
+				else  if (submenu.getItemCount()==1 && b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE){
+					//add a menu item here instead of submenu
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					m.setHiddenStatus(hiddenStatus);
+					MesquiteMenu.add(menu, m);
+					needToAddSubmenu = false;
+				}
+			}
+			if (needToAddSubmenu)
+				MesquiteMenu.add(menu, submenu);
+			return true;
+		}
+		else if (msms.getListableVector()!=null) {  
+			MesquiteInteger j = new MesquiteInteger(0); 
+
+			Object o = msms.getCompatibilityCheck();
+			int count = 0;
+			if (considerPriorities)
+				for (int i=1; i<MAXPRIORITY; i++)
+					count = fillSubmenuWithListable(count, menu, submenu, msms, o, j, i);
+			count = fillSubmenuWithListable(count, menu, submenu, msms, o, j, 0);
+
+			if (submenu.getItemCount()<=1 && msms.getBehaviorIfNoChoice() != MesquiteSubmenuSpec.SHOW_SUBMENU){
+				int b = msms.getBehaviorIfNoChoice();
+				int hiddenStatus = 0;
+				if (msms.isFilterable() && (hiddenStatus = InterfaceManager.isHiddenMenuItem(msms, msms.getSubmenuName(),  null, msms.command, null)) == InterfaceManager.HIDDEN) 
+					;
+				else if (b == MesquiteSubmenuSpec.ONEDISABLE_ZERODISABLE || (submenu.getItemCount()==0 && (b == MesquiteSubmenuSpec.ONESUBMENU_ZERODISABLE || b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE))){
+					//add a menu item here instead of submenu & disable it
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					MesquiteMenu.add(menu, m);
+					m.setHiddenStatus(hiddenStatus);
+					m.setEnabled(false);
+					needToAddSubmenu = false;
+				}
+				else  if (submenu.getItemCount()==1 && b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE){
+					//add a menu item here instead of submenu
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					m.setHiddenStatus(hiddenStatus);
+					MesquiteMenu.add(menu, m);
+					needToAddSubmenu = false;
+				}
+			}
+			if (needToAddSubmenu)
+				MesquiteMenu.add(menu, submenu);
+			return true;
+		}
+		else if (msms.getStrings()!=null) {  //
+			String[] names = msms.getStrings();
+			for (int j=0; j<names.length; j++) {
+				if (names[j]!=null) {
+					int hiddenStatus = 0;
+					if (msms.isFilterable() && (hiddenStatus = InterfaceManager.isHiddenMenuItem(msms, names[j],  StringUtil.tokenize(names[j]), msms.command, null)) == InterfaceManager.HIDDEN) 
+						;
+					else if (submenu.getSelected()!=null){
+						MesquiteCheckMenuItem m =new MesquiteCheckMenuItem(names[j], null /*msms.ownerModule*/, msms.command, StringUtil.tokenize(names[j]), submenu.getSelected());
+						//m.setDocument(msms.getDocumentItems());
+						m.setHiddenStatus(hiddenStatus);
+
+						submenu.add(m); 
+					}
+					else {
+						MesquiteMenuItem m =new MesquiteMenuItem(names[j], null /*msms.ownerModule*/, msms.command, StringUtil.tokenize(names[j]) + " " + j);
+						m.setDocument(msms.getDocumentItems());
+						m.setHiddenStatus(hiddenStatus);
+						submenu.add(m); 
+					}
+				}
+			}
+			if (submenu.getItemCount()<=1 && msms.getBehaviorIfNoChoice() != MesquiteSubmenuSpec.SHOW_SUBMENU){
+				int b = msms.getBehaviorIfNoChoice();
+				int hiddenStatus = 0;
+				if (msms.isFilterable() && (hiddenStatus = InterfaceManager.isHiddenMenuItem(msms, msms.getSubmenuName(),  null, msms.command, null)) == InterfaceManager.HIDDEN) 
+					;
+				else if (b == MesquiteSubmenuSpec.ONEDISABLE_ZERODISABLE || (submenu.getItemCount()==0 && (b == MesquiteSubmenuSpec.ONESUBMENU_ZERODISABLE || b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE))){
+					//add a menu item here instead of submenu & disable it
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					m.setHiddenStatus(hiddenStatus);
+					MesquiteMenu.add(menu, m);
+					m.setEnabled(false);
+					needToAddSubmenu = false;
+				}
+				else  if (submenu.getItemCount()==1 && b == MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE){
+					//add a menu item here instead of submenu
+					MesquiteMenuItem m = new MesquiteMenuItem(msms);
+					m.setHiddenStatus(hiddenStatus);
+					MesquiteMenu.add(menu, m);
+					needToAddSubmenu = false;
+				}
+			}
+			if (needToAddSubmenu)
+				MesquiteMenu.add(menu, submenu);
+			return true;
+		}
+		//---------------------------------------
+		return false;
+	}
+	boolean descendantsWithMenus(MesquiteModule mb){
+		boolean withMenus = false;
+		ListableVector L =mb.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++){
+				Object obj = L.elementAt(i);
+				MesquiteModule mbe = (MesquiteModule)obj;
+				if (mbe.menuItemsSpecs!=null && mbe.menuItemsSpecs.size()>0)
+					return true;
+				if (descendantsWithMenus(mbe))
+					return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................
+	This adds the module's menu items to a menu.  The menu is generally either the module's own menu or, if
+	the module has none, in the nearest menu in its employer chain.*/
+	final void addMyMenuItems(Menu menu){
+		try {
+			if (menuTracing) MesquiteMessage.notifyProgrammer("         adding menus of " + toString());
+			if (menuItemsSpecs!=null) {
+				for (int i=0; i<menuItemsSpecs.size(); i++) {
+					MesquiteMenuItemSpec mmi = (MesquiteMenuItemSpec)menuItemsSpecs.elementAt(i);
+
+					if (mmi != null && mmi.whichMenu==null && assignedMenuSpec==null) {
+						int hiddenStatus = 0;
+						String arg = null;
+						if (mmi.getArgument() != null)
+							arg = mmi.getArgument();
+						else if (mmi.command != null)
+							arg = mmi.command.getDefaultArguments();
+						if (InterfaceManager.isFilterable(menu) && (hiddenStatus = InterfaceManager.isHiddenMenuItem(mmi, mmi.getName(),  arg, mmi.command, null)) == InterfaceManager.HIDDEN) 
+							;
+						else if (mmi instanceof MesquiteSubmenuSpec) {  //add submenu
+
+							MesquiteSubmenu ms = addSubmenuWithListsIfAbsent(menu,  ((MesquiteSubmenuSpec)mmi));
+							ms.setHiddenStatus(hiddenStatus);
+
+							/*if (submenu!=null) {
+							addListsToMenu(mmi, submenu);
+							//MesquiteMenu.add(menu, submenu);
+						}
+							 */
+						}
+						else if (mmi.submenuIn() != null) {
+							MesquiteSubmenu submenu= addSubmenuIfAbsent(menu,  mmi.submenuIn());
+							if (submenu !=null) {  //CHECK
+								if (mmi instanceof MesquiteCMenuItemSpec) {
+									MesquiteCheckMenuItem cmi = null;
+									submenu.add(cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+									cmi.setHiddenStatus(hiddenStatus);
+								}
+								else if (submenu.getSelected()!=null)  {//selected string available for checkmark
+									MesquiteCheckMenuItem cmi = null;
+									submenu.add(cmi = new MesquiteCheckMenuItem(mmi.getName(), null /*mmi.ownerModule*/, mmi.command, StringUtil.tokenize(mmi.getName()), submenu.getSelected()));  //todo: name should be tokenized???
+									cmi.setHiddenStatus(hiddenStatus);
+								}
+								else {
+									MesquiteMenuItem mi = null;
+									submenu.add(mi = new MesquiteMenuItem(mmi));
+									mi.setHiddenStatus(hiddenStatus);
+									//MesquiteMenu.add(menu, submenu);
+								}
+							}
+						}
+						else if (!addListsToMenu(mmi, menu)){ //CHECK
+							if (mmi instanceof MesquiteCMenuItemSpec){
+								MesquiteCheckMenuItem cmi = null;
+								MesquiteMenu.add(menu, cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+								cmi.setHiddenStatus(hiddenStatus);
+							}
+							else {
+								MesquiteMenuItem mi = null;
+								MesquiteMenu.add(menu, mi = new MesquiteMenuItem(mmi));
+								mi.setHiddenStatus(hiddenStatus);
+							}
+						}
+						if (menuTracing && mmi!=null) MesquiteMessage.notifyProgrammer("MENU Item " + mmi.itemName + " added");
+					}
+				}
+			}
+			/*boolean macroMenuMade = false;
+		if (module.getAutoSaveMacros()) {
+			MesquiteMenu.add(menu, new MenuItem("-"));
+			MesquiteMenu.add(menu, new MesquiteMenuItem("Save Macro for " +  module.getNameForMenuItem() + "...", module, module.makeCommand("saveMacro", module)));  //commandArgument
+			macroMenuMade = true;
+		}
+		if (!(module instanceof FileCoordinator)) {
+			MesquiteSubmenu ms = makeMacrosSubmenu(menu, module, 0, "Macros for " + module.getNameForMenuItem());
+			if (ms!=null) {
+				if (!macroMenuMade)
+					MesquiteMenu.add(menu, new MenuItem("-"));
+				menu.add(ms);
+				macroMenuMade = true;
+			}
+		}
+		if (descendantsWithMenus(module) && macroMenuMade)
+			MesquiteMenu.add(menu, new MenuItem("-"));
+			 */
+		}
+		catch (Exception e){
+		}
+	}
+	private final MesquiteSubmenu makeMacrosSubmenu(Menu menu, MesquiteModule mb, int menuNum, String label){
+		if (mb == null)
+			return null;
+		MesquiteModuleInfo mmi = mb.getModuleInfo();
+		if (mmi!=null){
+			Vector macros = mb.getModuleInfo().getMacros();
+			if (macros!=null && macros.size()>0){
+				MesquiteSubmenu submenu=MesquiteSubmenu.getSubmenu(label, menu, mb);
+				for (int i=0; i<macros.size(); i++) {
+					MesquiteMacro macro = (MesquiteMacro)macros.elementAt(i);
+					if (macro!=null && macro.getPreferredMenu() == menuNum) 
+						submenu.add(new MesquiteMenuItem(macro.getName(), mb, mb.makeCommand("applyMacro", mb), Integer.toString(i)));  //commandArgument
+				}
+				return submenu;
+			}
+		}
+		return null;
+	}
+	/*................................................................................................................. */
+	final void addFilesToSubmenu(MesquiteSubmenu submenu, MesquiteProject proj, boolean onlyIfLocal, MesquiteCommand command){
+		Enumeration enumeration=proj.getFiles().elements();
+		MesquiteFile fi;
+		int count = 0;
+		while (count++<128 && enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof MesquiteFile) {
+				fi = (MesquiteFile)obj;
+				if (!onlyIfLocal || fi.isLocal())
+					submenu.add(new MesquiteMenuItem(fi.getName(), MesquiteModule.mesquiteTrunk, command, Long.toString(fi.getID())));
+			}
+		}
+	}
+	/*................................................................................................................. */
+	private final MesquiteMenu composeFileMenu(MesquiteMenuBar menuBar, MesquiteMenuSpec menuSpec, MesquiteWindow whichWindow) {
+		if (menuSpec!=null) {
+			MesquiteMenu newMenu= MesquiteMenu.getMenu(menuSpec);
+			String projName;
+			MesquiteProject proj = module.getProject();
+
+			//if module has no project, i.e. is trunkward of a file coordinator module, then if there is just one project, treat the file menu as if it were for that project
+			if (proj == null) {
+				if (MesquiteTrunk.getProjectList().getNumProjects()==1)
+					proj = MesquiteTrunk.getProjectList().getProject(0);
+			}
+			if (proj==null)
+				projName = "";
+			else if (StringUtil.titled(proj.getName()))
+				projName = proj.getName();
+			else
+				projName = "current project...";
+
+			MesquiteMenuItem newItem =new MesquiteMenuItem("New", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.newFileCommand);
+			//TODO: should allow New Linked!!!!
+			newItem.setShortcut(newShortcut);
+			newMenu.add(newItem);
+			if (proj!=null){
+				MesquiteMenuItem newLinkedItem =new MesquiteMenuItem("New Linked File", MesquiteModule.mesquiteTrunk, proj.getNewLinkFileCommand());
+				newMenu.add(newLinkedItem);
+			}
+			int numLinkedFiles = 0;
+			if (proj!=null)
+				numLinkedFiles = proj.getNumberLinkedFiles();
+			/*-------------- open file menu or submenu 
+			MesquiteSubmenu openFileSubmenu=MesquiteSubmenu.getSubmenu("Open", newMenu, module);  //make submenu
+			newMenu.add(openFileSubmenu);
+			if (proj!=null && numLinkedFiles!=0) {
+				openFileSubmenu.add(new MesquiteMenuItem("(as separate project)", null, null));
+				openFileSubmenu.add(new MenuItem("-"));
+			}
+			 */
+			if (!MesquiteTrunk.isApplet()) {
+				MesquiteMenuItem openItem = new MesquiteMenuItem("Open File...", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.openFileCommand);
+				openItem.setShortcut(openShortcut);
+				newMenu.add(openItem);
+			}
+			/*-------------- open URL menu or submenu */
+			//newMenu.add(new MesquiteMenuItem("Open URL...", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.openURLCommand));
+
+
+			addSubmenuWithListsIfAbsent(newMenu,  MesquiteTrunk.mesquiteTrunk.openExternalSMS);
+
+
+			if (proj!=null && numLinkedFiles>0) {
+				if (!MesquiteTrunk.isApplet()) {
+					newMenu.add(new MesquiteMenuItem("Link File...", MesquiteModule.mesquiteTrunk, proj.getLinkFileCommand()));
+					newMenu.add(new MesquiteMenuItem("Include File...", MesquiteModule.mesquiteTrunk, proj.getIncludeFileCommand()));
+				}
+
+
+			}
+
+			/*-------------- Close submenu TODO: should make this a submenu Close with Project, then list files one by one as in save*/
+			if (proj!=null && !MesquiteTrunk.isApplet()) {
+				if (numLinkedFiles>1) {
+					//newMenu.add(new MesquiteMenuItem("Close Linked Files", MesquiteModule.mesquiteTrunk, proj.getCloseCommand()));
+					MesquiteSubmenu closeSubmenu=MesquiteSubmenu.getSubmenu("Close", newMenu, module);  //make submenu
+					newMenu.add(closeSubmenu);
+					closeSubmenu.add(new MesquiteMenuItem(projName, MesquiteModule.mesquiteTrunk, proj.getCloseFilesCommand()));
+					closeSubmenu.add("-");
+					addFilesToSubmenu(closeSubmenu, proj, false,  proj.getCloseCommand());
+				}
+				else {
+					newMenu.add(new MesquiteMenuItem("Close File", MesquiteModule.mesquiteTrunk, proj.getCloseFilesCommand()));
+				}
+			}
+			if (MesquiteTrunk.getProjectList() !=null && MesquiteTrunk.getProjectList().getNumProjects()>=1)
+				newMenu.add(new MesquiteMenuItem("Close All", MesquiteModule.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.closeAllCommand));
+			if (proj!=null && !MesquiteTrunk.isApplet() && (MesquiteTrunk.isMacOSX() || MesquiteTrunk.isWindows())) {
+				if (numLinkedFiles>1) {
+					//newMenu.add(new MesquiteMenuItem("Close Linked Files", MesquiteModule.mesquiteTrunk, proj.getCloseCommand()));
+					MesquiteSubmenu showFileSubmenu=MesquiteSubmenu.getSubmenu("Show File Location", newMenu, module);  //make submenu
+					newMenu.add(showFileSubmenu);
+					addFilesToSubmenu(showFileSubmenu, proj, false,  proj.getShowFileOnDiskCommand());
+				}
+				else {
+					newMenu.add(new MesquiteMenuItem("Show File Location", MesquiteModule.mesquiteTrunk, proj.getShowFileOnDiskCommand()));
+				}
+			}
+			newMenu.add(whichWindow.closeWindowMenuItem);
+			if (whichWindow.closeAllMenuItem != null)
+				newMenu.add(whichWindow.closeAllMenuItem);
+			/*-------------- Save & Save As menu or submenu */
+			newMenu.add("-");		
+			if (proj!=null && !MesquiteTrunk.isApplet()) {
+				if (numLinkedFiles>1) {
+					MesquiteSubmenu saveSubmenu=MesquiteSubmenu.getSubmenu("Save", newMenu, module);  //make submenu
+					newMenu.add(saveSubmenu);
+					MesquiteMenuItem saveAllItem = new MesquiteMenuItem("All Files in " + projName, MesquiteModule.mesquiteTrunk, proj.getSaveFilesCommand());
+					saveSubmenu.add(saveAllItem);
+					saveAllItem.setShortcut(saveShortcut);	
+					saveSubmenu.add("-");
+					addFilesToSubmenu(saveSubmenu, proj, true,  proj.getSaveCommand());
+					MesquiteSubmenu saveAsSubmenu=MesquiteSubmenu.getSubmenu("Save As", newMenu, module);  //make submenu
+					newMenu.add(saveAsSubmenu);
+					addFilesToSubmenu(saveAsSubmenu, proj, true,  proj.getSaveAsCommand());
+				}
+				else	{
+					MesquiteMenuItem saveItem = new MesquiteMenuItem("Save File", MesquiteModule.mesquiteTrunk, proj.getSaveCommand());	
+					saveItem.setShortcut(saveShortcut);	
+					newMenu.add(saveItem);		
+					//newMenu.add(new MesquiteSubMenuItem("Save File", MesquiteModule.mesquiteTrunk, proj.getSaveCommand()));		
+					newMenu.add(new MesquiteMenuItem("Save File As...", MesquiteModule.mesquiteTrunk, proj.getSaveAsCommand()));
+				}
+				if (MesquiteTrunk.getProjectList().getNumProjects()>1){
+					MesquiteMenuItem saveAllItem = new MesquiteMenuItem("Save All Files All Projects", MesquiteModule.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.saveAllCommand);	
+					newMenu.add(saveAllItem);
+				}	
+				newMenu.add(new MesquiteMenuItem("Export...", MesquiteModule.mesquiteTrunk, proj.exportCommand));
+				newMenu.add(new MesquiteMenuItem("Revert to Saved", MesquiteModule.mesquiteTrunk, proj.getRevertCommand()));
+				MesquiteMenuItem gi;
+				newMenu.add(gi = new MesquiteMenuItem("Get Info...", MesquiteModule.mesquiteTrunk, proj.getInfoCommand));
+				gi.setShortcut(getInfoShortcut);
+			}
+			else if (MesquiteTrunk.isApplet() || MesquiteTrunk.getProjectList().getNumProjects()==0) {
+				//can't save either because this is menu for window trunkward of projects, and there is no project open, or is applet.  Give user warning
+				MesquiteMenuItem saveItem = new MesquiteMenuItem("Save File...", MesquiteModule.mesquiteTrunk, MesquiteModule.makeCommand("explainNoSave", MesquiteModule.mesquiteTrunk));	
+				saveItem.setShortcut(saveShortcut);	
+				newMenu.add(saveItem);		
+			}
+			else {
+				MesquiteMenuItem saveAllItem = new MesquiteMenuItem("Save All Files All Projects", MesquiteModule.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.saveAllCommand);	
+				saveAllItem.setShortcut(saveShortcut);	
+				newMenu.add(saveAllItem);		
+			}
+
+			if (whichWindow!=null)
+				newMenu.add(new MesquiteMenuItem("Save Window as Text...", module, whichWindow.saveAsTextCommand));
+			newMenu.add("-");
+			/*-------------- Print item */
+
+			MesquiteMenuItem printItem = new MesquiteMenuItem(menuBar.getOwnerWindow().getPrintMenuItem(), MesquiteModule.mesquiteTrunk, menuBar.getOwnerWindow().printCommand);
+			newMenu.add(printItem);		
+			if (menuBar.getOwnerWindow() instanceof Fittable) {
+				MesquiteMenuItem printToFitItem = new MesquiteMenuItem(menuBar.getOwnerWindow().getPrintToFitMenuItem());
+				newMenu.add(printToFitItem);		
+				printToFitItem.setShortcut(printShortcut);
+			}
+			else
+				printItem.setShortcut(printShortcut);
+			MesquiteMenuItem printPDFItem = new MesquiteMenuItem(menuBar.getOwnerWindow().getPrintToPDFMenuItemName(), MesquiteModule.mesquiteTrunk, menuBar.getOwnerWindow().printToPDFCommand);
+			newMenu.add(printPDFItem);		
+			newMenu.add("-");		
+			/*-------------- Macros items *
+			MesquiteSubmenu mac = composeMacrosSubmenu(MesquiteTrunk.class, FileCoordinator.class, newMenu, whichWindow);
+			if (mac!=null && mac.getItemCount()>0) {
+				newMenu.add(mac);
+				newMenu.add("-");
+			}
+			/*-------------- items from employers & employees */
+			composeSpecificMenuAncestors(menuSpec, newMenu);
+			addMySpecificMenuItems(menuSpec, newMenu);
+			ListableVector L =module.getEmployeeVector();
+			if (L != null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if ( mb.window==null) 
+						mb.composeSpecificMenuDescendants(menuSpec, newMenu);
+				}
+			}
+
+
+
+			//defaultSubMenu=MesquiteSubmenu.getSubmenu("Defaults", newMenu, module);  //make submenu
+			//newMenu.add(defaultSubMenu);
+			//defaultsMenuSpec = defaultSubMenu.getSpec();
+
+
+			addBottom(newMenu, null, "*");
+
+			//newMenu.add(new MesquiteMenuItem("Edit Menu Visibility", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.editMenuVisibilityCommand));
+
+
+			newMenu.add(new MesquiteMenuItem("Reset Menus", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.resetMenusCommand));
+			//MesquiteMenuItem ccItem =new MesquiteMenuItem("Current Command...", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.currentCommandCommand);
+			//ccItem.setShortcut(ccShortcut);
+			//newMenu.add(ccItem);		
+			//newMenu.add(new MesquiteMenuItem("Pending Commands...", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.pendingCommandsCommand));
+			newMenu.add(new MesquiteMenuItem("Force Quit", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.forceQuitCommand));
+			MesquiteMenuItem quitItem = new MesquiteMenuItem("Quit Mesquite", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.quitCommand);
+			//if (!MesquiteTrunk.isMacOSX()) bug causes quit to ignore "cancel"
+			quitItem.setShortcut(quitShortcut);
+			newMenu.add(quitItem);
+			//	composeSpecificMenuDescendants(menu, newMenu);
+			if (newMenu.getItemCount()>0)
+				menuBar.add(newMenu);
+			//dumpMenu(newMenu, " ");
+			return newMenu;
+		}
+		return null;
+	}
+
+	/*................................................................................................................. */
+	public void setUndoMenuItemEnabled(boolean b) {
+		if (undoMenuItem!=null) {
+			undoEnabled=b;
+			undoMenuItem.setEnabled(b);
+			if (b)
+				undoMenuItem.setLabel("Undo");
+			else {
+				undoMenuItem.setLabel("Can't Undo");
+			}
+		}
+
+	}
+	/*................................................................................................................. */
+	private final MesquiteMenu composeEditMenu(MesquiteMenuBar menuBar, MesquiteMenuSpec menuSpec, MesquiteWindow whichWindow) {
+		if (menuSpec!=null) {
+			MesquiteMenu newMenu= MesquiteMenu.getMenu(menuSpec);
+
+
+			MesquiteMenuItem cut, copy, paste, clear, selectAll;
+			undoMenuItem =new MesquiteMenuItem("Undo", MesquiteModule.mesquiteTrunk, whichWindow.getUndoCommand());
+			newMenu.add(undoMenuItem);		
+			if (whichWindow.getUndoCommand()!=null)
+				undoMenuItem.setShortcut(undoShortcut);
+			previousToolMenuItem =new MesquiteMenuItem("Previous Tool", MesquiteModule.mesquiteTrunk, whichWindow.getPreviousToolCommand());
+			newMenu.add(previousToolMenuItem);		
+			if (whichWindow.getPreviousToolCommand()!=null)
+				previousToolMenuItem.setShortcut(previousToolShortcut);
+			setUndoMenuItemEnabled(undoEnabled);
+			newMenu.add("-");		
+			cut =new MesquiteMenuItem("Cut", MesquiteModule.mesquiteTrunk,MesquiteModule.makeCommand("cut", whichWindow));// whichWindow.getCutCommand());
+			newMenu.add(cut);
+			if(whichWindow.getCutCommand()!=null)
+				cut.setShortcut(cutShortcut);	
+			cut.setEnabled(whichWindow.getCutCommand()!=null); //window must return a copy command if command-based copying is to be enabled; otherwise allows automatic system
+
+			MesquiteCommand copyCommand = MesquiteModule.makeCommand("copy", whichWindow);
+			copyCommand.setSuppressLogging(true); //set true so that writing "copy" doesn't prevent copying from selection in log itself
+			copy =new MesquiteMenuItem("Copy", MesquiteModule.mesquiteTrunk, copyCommand);
+			newMenu.add(copy);		
+			copy.setShortcut(copyShortcut);
+
+			if (whichWindow.getCopySpecialCommand()!=null){
+				newMenu.add(new MesquiteMenuItem(whichWindow.getCopySpecialName(), MesquiteModule.mesquiteTrunk, whichWindow.getCopySpecialCommand()));		
+			}
+
+			paste = new MesquiteMenuItem("Paste", MesquiteModule.mesquiteTrunk, MesquiteModule.makeCommand("paste", whichWindow)); //whichWindow.getPasteCommand());
+			newMenu.add(paste);	
+			if (whichWindow.getPasteCommand()!=null)
+				paste.setShortcut(pasteShortcut);	
+			paste.setEnabled(whichWindow.getPasteCommand()!=null); //window must return a copy command if command-based copying is to be enabled; otherwise allows automatic system
+			if (whichWindow.getPasteSpecialCommand()!=null){
+				newMenu.add(new MesquiteMenuItem(whichWindow.getPasteSpecialName(), MesquiteModule.mesquiteTrunk, whichWindow.getPasteSpecialCommand()));		
+			}
+
+			clear =new MesquiteMenuItem("Clear", MesquiteModule.mesquiteTrunk, MesquiteModule.makeCommand("clear", whichWindow));//whichWindow.getClearCommand());
+			newMenu.add(clear);		
+			if (whichWindow.getClearCommand()!=null)
+				clear.setShortcut(clearShortcut);	
+			clear.setEnabled(whichWindow.getClearCommand()!=null); //window must return a copy command if command-based copying is to be enabled; otherwise allows automatic system
+
+			selectAll = new MesquiteMenuItem("Select All", MesquiteModule.mesquiteTrunk, MesquiteModule.makeCommand("selectAll", whichWindow));//whichWindow.getSelectAllCommand());
+			newMenu.add(selectAll);		
+			selectAll.setShortcut(selectAllShortcut);	
+			newMenu.add("-");		
+
+			whichWindow.fontSubmenu=MesquiteSubmenu.getFontSubmenu("Font", newMenu, module, menuBar.getOwnerWindow().setFontCommand);
+			newMenu.add(whichWindow.fontSubmenu);
+			MesquiteCommand setFontSizeCommand = menuBar.getOwnerWindow().setFontSizeCommand;
+			whichWindow.fontSizeSubmenu=MesquiteSubmenu.getFontSizeSubmenu("Font Size", newMenu, module, setFontSizeCommand);
+			newMenu.add(whichWindow.fontSizeSubmenu);
+			Font font = menuBar.getOwnerWindow().currentFont;
+			if (font != null) {
+				whichWindow.fontSubmenu.checkName(font.getName());
+				whichWindow.fontSizeSubmenu.checkName(Integer.toString(font.getSize()));
+			}
+			newMenu.add(new MenuItem("-"));
+
+			composeSpecificMenuAncestors(menuSpec, newMenu);
+			addMySpecificMenuItems(menuSpec, newMenu);
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++){
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb.window==null) 
+						mb.composeSpecificMenuDescendants(menuSpec, newMenu);
+				}
+			}
+			if (newMenu.getItemCount()>0)
+				menuBar.add(newMenu);
+			return newMenu;
+		}
+		return null;
+	}
+	/*.................................................................................................................
+	This and the methods it calls below compose a single menu with specification menuSpec.
+	This is used for the special File and Windows menus, and the auxiliary menus that MesquiteModules
+	can have  */
+	final MesquiteMenu composeSpecificMenu(MesquiteMenuBar menuBar, MesquiteMenu newMenu, MesquiteMenuSpec menuSpec, boolean addToMenuBar) {
+		if (menuSpec!=null) {
+			if (newMenu ==null)
+				newMenu= MesquiteMenu.getMenu(menuSpec);
+
+			//for (int i=menu.getItemCount()-1; i>=0; i--)   // 1.1 use menu.removeAll();
+			//	menu.remove(i);
+
+			composeSpecificMenuAncestors(menuSpec, newMenu);
+			addMySpecificMenuItems(menuSpec, newMenu);
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++) {
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb.window==null)
+						mb.composeSpecificMenuDescendants(menuSpec, newMenu);
+				}
+			}
+			//	composeSpecificMenuDescendants(menu, newMenu);
+			addBottom(newMenu, null, "#");
+			if (newMenu.getItemCount()>0 && addToMenuBar)
+				menuBar.add(newMenu);
+			return newMenu;
+		}
+		return null;
+	}
+	/*.................................................................................................................
+	This and the methods it calls below compose a single menu with specification menuSpec.
+	This is used for the special File and Windows menus, and the auxiliary menus that MesquiteModules
+	can have  */
+	final Menu composeSpecificMenu(Vector menuBar, MesquitePopup newMenu, MesquiteMenuSpec menuSpec, boolean addToMenuBar) {
+		if (menuSpec!=null) {
+			if (newMenu ==null)
+				newMenu= MesquitePopup.getPopupMenu(menuSpec, null);
+
+			//for (int i=menu.getItemCount()-1; i>=0; i--)   // 1.1 use menu.removeAll();
+			//	menu.remove(i);
+
+			composeSpecificMenuAncestors(menuSpec, newMenu);
+			addMySpecificMenuItems(menuSpec, newMenu);
+			ListableVector L =module.getEmployeeVector();
+			if (L!=null) {
+				int num = L.size();
+				for (int i=0; i<num; i++) {
+					Object obj = L.elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					if (mb.window==null)
+						mb.composeSpecificMenuDescendants(menuSpec, newMenu);
+				}
+			}
+			//	composeSpecificMenuDescendants(menu, newMenu);
+			addBottom(newMenu, null, "#");
+			if (newMenu.getItemCount()>0 && addToMenuBar)
+				menuBar.add(newMenu);
+			return newMenu;
+		}
+		return null;
+	}
+	/*.................................................................................................................
+	This and the methods it calls below compose a single menu with specification menuSpec.
+	This is used for the special File and Windows menus, and the auxiliary menus that MesquiteModules
+	can have  */
+	final MesquiteMenu composeSpecificMenuByZones(MesquiteMenuBar menuBar, MesquiteMenu newMenu, MesquiteMenuSpec menuSpec, boolean addToMenuBar) {
+		if (menuSpec!=null) {
+			if (newMenu ==null)
+				newMenu= MesquiteMenu.getMenu(menuSpec);
+			for (int zone=0; zone<MesquiteMenuItemSpec.MAXZONE; zone++) {
+				composeSpecificMenuAncestorsByZone(menuSpec, newMenu, zone);
+				addMySpecificMenuItemsByZone(menuSpec, newMenu, zone);
+				ListableVector L =module.getEmployeeVector();
+				if (L!=null) {
+					int num = L.size();
+					for (int i=0; i<num; i++) {
+						Object obj = L.elementAt(i);
+						MesquiteModule mb = (MesquiteModule)obj;
+						if (mb.window==null)
+							mb.composeSpecificMenuDescendantsByZone(menuSpec, newMenu, zone);
+					}
+				}
+			}
+			addBottom(newMenu, null, "#");
+			if (newMenu.getItemCount()>0 && addToMenuBar)
+				menuBar.add(newMenu);
+			return newMenu;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	final void composeSpecificMenuAncestors(MesquiteMenuSpec menuSpec, Menu menu) {
+		if (module.getEmployer()!=null) {
+			module.getEmployer().composeSpecificMenuAncestors(menuSpec, menu);
+			if (module.getEmployer()!=null)
+				module.getEmployer().addMySpecificMenuItems(menuSpec, menu);
+		}
+	}
+	/*.................................................................................................................*/
+	final void composeSpecificMenuAncestorsByZone(MesquiteMenuSpec menuSpec, MesquiteMenu menu, int zone) {
+		if (module.getEmployer()!=null) {
+			module.getEmployer().composeSpecificMenuAncestorsByZone(menuSpec, menu, zone);
+			if (module.getEmployer()!=null)
+				module.getEmployer().addMySpecificMenuItemsByZone(menuSpec, menu, zone);
+		}
+	}
+	/*.................................................................................................................*/
+	final void composeSpecificMenuDescendantsByZone(MesquiteMenuSpec menuSpec, MesquiteMenu menu, int zone) {
+		addMySpecificMenuItemsByZone(menuSpec, menu, zone);
+		ListableVector L =module.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++) {
+				Object obj = L.elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb.window==null)
+					mb.composeSpecificMenuDescendants(menuSpec, menu);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	final void composeSpecificMenuDescendants(MesquiteMenuSpec menuSpec, Menu menu) {
+		addMySpecificMenuItems(menuSpec, menu);
+		ListableVector L =module.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++) {
+				Object obj = L.elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb.window==null)
+					mb.composeSpecificMenuDescendants(menuSpec, menu);
+			}
+		}
+	}
+	/*.................................................................................................................
+	 */
+	final void addCurrentWindows(MesquiteMenu menu) {
+		//other windows
+		Menu currentWindows = new MesquiteMenu("Current Windows");
+		MesquiteMenu.add(menu, currentWindows);
+		Enumeration e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.getShowMenuLocation()==2){
+				MesquiteMenuItem mmi = new MesquiteMenuItem(mw.getTitle(), MesquiteModule.mesquiteTrunk, mw.showCommand);
+				MesquiteMenu.add(currentWindows, mmi);
+				mmi.setEnabled(true);
+			}
+		}
+		MesquiteMenu.add(currentWindows, new MenuItem("-"));
+		e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.getShowMenuLocation()==0){
+				MesquiteMenuItem mmi = new MesquiteMenuItem(mw.getTitle(), MesquiteModule.mesquiteTrunk, mw.showCommand);
+				MesquiteMenu.add(currentWindows, mmi);
+				mmi.setEnabled(true);
+			}
+		}
+		//System windows
+		e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.getShowMenuLocation()==1){
+				MesquiteMenuItem mmi = new MesquiteMenuItem(mw.getTitle(), MesquiteModule.mesquiteTrunk, mw.showCommand);
+				MesquiteMenu.add(menu, mmi);
+				mmi.setEnabled(true);
+			}
+		}
+		menu.add(new MesquiteMenuItem("Display License", MesquiteModule.mesquiteTrunk, MesquiteModule.mesquiteTrunk.showLicenseCommand));
+		MesquiteMenu.add(menu, new MenuItem("-"));
+
+	}
+	/*.................................................................................................................*/
+	final void addMySpecificMenuItemsByZone(MesquiteMenuSpec menuSpec, MesquiteMenu menu, int zone){
+		if (menuItemsSpecs!=null) {
+			for (int i=0; menuItemsSpecs!=null && i<menuItemsSpecs.size(); i++) {
+				if (menuItemsSpecs==null)
+					return;
+				MesquiteMenuItemSpec mmi = (MesquiteMenuItemSpec)menuItemsSpecs.elementAt(i);
+				int hiddenStatus = 0;
+				String arg = null;
+				if (mmi.getArgument() != null)
+					arg = mmi.getArgument();
+				else if (mmi.command != null)
+					arg = mmi.command.getDefaultArguments();
+				if (mmi.getZone() == zone && (mmi.whichMenu==menuSpec || getContainingMenuSpec() == menuSpec)) {
+					if (InterfaceManager.isFilterable(menu) && (hiddenStatus = InterfaceManager.isHiddenMenuItem(mmi, mmi.getName(),  arg, mmi.command, null)) == InterfaceManager.HIDDEN) 
+						;
+					else if (mmi instanceof MesquiteSubmenuSpec) {  //add submenu
+						MesquiteSubmenu submenu = addSubmenuWithListsIfAbsent(menu,  ((MesquiteSubmenuSpec)mmi));
+						submenu.setHiddenStatus(hiddenStatus);
+					}
+					else if (mmi.submenuIn() != null) {
+						MesquiteSubmenu submenu= addSubmenuIfAbsent(menu,  mmi.submenuIn()); //&&&
+						if (submenu !=null) {  //CHECK
+							if (mmi instanceof MesquiteCMenuItemSpec){
+								MesquiteCheckMenuItem cmi = null;
+								submenu.add(cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+								cmi.setHiddenStatus(hiddenStatus);
+							}
+							else {
+								MesquiteMenuItem mi = null;
+								submenu.add(mi = new MesquiteMenuItem(mmi));
+								mi.setHiddenStatus(hiddenStatus);
+							}
+						}
+					}
+					else if (!addListsToMenu(mmi, menu)){
+						if (mmi instanceof MesquiteCMenuItemSpec){
+							MesquiteCheckMenuItem cmi = null;
+							MesquiteMenu.add(menu, cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+							cmi.setHiddenStatus(hiddenStatus);
+						}
+						else {
+							MesquiteMenuItem mi = null;
+							MesquiteMenu.add(menu, mi = new MesquiteMenuItem(mmi));
+							mi.setHiddenStatus(hiddenStatus);
+						}
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	final void addMySpecificMenuItems(MesquiteMenuSpec menuSpec, Menu menu){
+		if (menuItemsSpecs!=null) {
+			for (int i=0; menuItemsSpecs!=null && i<menuItemsSpecs.size(); i++) {
+				if (menuItemsSpecs==null)
+					return;
+				MesquiteMenuItemSpec mmi = (MesquiteMenuItemSpec)menuItemsSpecs.elementAt(i);
+				int hiddenStatus = 0;
+				String arg = null;
+				if (mmi.getArgument() != null)
+					arg = mmi.getArgument();
+				else if (mmi.command != null)
+					arg = mmi.command.getDefaultArguments();
+
+				if (mmi.whichMenu==menuSpec || getContainingMenuSpec() == menuSpec) {
+					if (InterfaceManager.isFilterable(menu) && (hiddenStatus = InterfaceManager.isHiddenMenuItem(mmi, mmi.getName(),  arg, mmi.command, null)) == InterfaceManager.HIDDEN) 
+						;
+					else if (mmi instanceof MesquiteSubmenuSpec) {  //add submenu
+						MesquiteSubmenu submenu = addSubmenuWithListsIfAbsent(menu,  ((MesquiteSubmenuSpec)mmi));
+						submenu.setHiddenStatus(hiddenStatus);
+					}
+					else if (mmi.submenuIn() != null) {
+						MesquiteSubmenu submenu= addSubmenuIfAbsent(menu,  mmi.submenuIn()); //&&&
+						if (submenu !=null) {  //CHECK
+							if (mmi instanceof MesquiteCMenuItemSpec){
+								MesquiteCheckMenuItem cmi = null;
+								submenu.add(cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+								cmi.setHiddenStatus(hiddenStatus);
+							}
+							else {
+								MesquiteMenuItem mi = null;
+								submenu.add(mi = new MesquiteMenuItem(mmi));
+								mi.setHiddenStatus(hiddenStatus);
+							}
+						}
+					}
+					else if (!addListsToMenu(mmi, menu)){
+						if (mmi instanceof MesquiteCMenuItemSpec){
+							MesquiteCheckMenuItem cmi = null;
+							MesquiteMenu.add(menu, cmi = new MesquiteCheckMenuItem((MesquiteCMenuItemSpec)mmi));
+							cmi.setHiddenStatus(hiddenStatus);
+						}
+						else {
+							MesquiteMenuItem mi = null;
+							MesquiteMenu.add(menu, mi = new MesquiteMenuItem(mmi));
+							mi.setHiddenStatus(hiddenStatus);
+						}
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	final MesquiteMenu findMenu(MesquiteMenuBar menuBar, String name){
+		if (menuItemsSpecs!=null) {
+			for (int i=0; i<menuBar.getMenuCount(); i++) {
+				if (menuTracing) MesquiteMessage.notifyProgrammer("MENU " + menuBar.getMenu(i).getLabel());
+				if (name.equalsIgnoreCase(menuBar.getMenu(i).getLabel()))
+					return (MesquiteMenu)menuBar.getMenu(i);
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	final MesquiteSubmenu findSubmenu(Menu menu, MesquiteSubmenuSpec smSpec){
+		if (menu!=null) {
+			for (int i=0; i<menu.getItemCount(); i++) {
+				if (smSpec.getSubmenuName().equalsIgnoreCase(menu.getItem(i).getLabel()) && menu.getItem(i) instanceof MesquiteSubmenu && ((MesquiteSubmenu)menu.getItem(i)).getOwnerModuleID() == smSpec.getOwnerModuleID()) {
+					return (MesquiteSubmenu)menu.getItem(i);
+				}
+			}
+		}
+		return null;
+	}
+	private MenuItem inMenu(Menu menu, MesquiteMenuItemSpec spec){
+		for (int i = 0; i< menu.getItemCount(); i++){
+			MenuItem mmi = menu.getItem(i);
+			MesquiteMenuItemSpec mmis = null;
+			if (mmi instanceof MesquiteMenuItem)
+				mmis = ((MesquiteMenuItem)mmi).getSpecification();
+			else if (mmi instanceof MesquiteCheckMenuItem)
+				mmis = ((MesquiteCheckMenuItem)mmi).getSpecification();
+			else if (mmi instanceof MesquiteMenu)
+				mmis = ((MesquiteMenu)mmi).getSpecification();
+			if (mmis != null && mmis == spec)
+				return mmi;
+		}
+		return null;
+	}
+
+	private void surveySpecs(Menu menu, MenuItem[] specsOrder, MesquiteInteger count, MenuItemsSpecsVector miSpecsVector){
+		try {
+			if (miSpecsVector!=null) {
+				for (int i=0; miSpecsVector!=null && i<miSpecsVector.size(); i++) {
+					if (miSpecsVector==null)
+						return;
+					MesquiteMenuItemSpec mmi = (MesquiteMenuItemSpec)miSpecsVector.elementAt(i);
+					MenuItem mi = inMenu(menu, mmi);
+					if (mi != null){
+						specsOrder[count.getValue()] = mi;
+						count.increment();
+					}
+				}
+			}
+
+		}
+		catch (Exception e){
+			MesquiteMessage.warnProgrammer("Exception in ListableVector");
+		}
+
+	}
+	/*.................................................................................................................*/
+	void surveyDescendents(Menu menu, MenuItem[] specsOrder, MesquiteInteger count) {
+		surveySpecs(menu, specsOrder, count, menuItemsSpecs);
+		ListableVector L =module.getEmployeeVector();
+		if (L!=null) {
+			int num = L.size();
+			for (int i=0; i<num; i++) {
+				Object obj = L.elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb.window==null)
+					mb.surveyDescendents(menu, specsOrder, count);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	void surveyAncestors(Menu menu, MenuItem[] specsOrder, MesquiteInteger count) {
+		if (moduleMenuSpec!=null  && menu instanceof MesquiteMenu && ((MesquiteMenu)menu).getSpecification() == moduleMenuSpec) {
+			surveySpecs(menu, specsOrder, count, menuItemsSpecs);
+			if (module.getEmployer()!=null) 
+				module.getEmployer().surveyAncestors(menu, specsOrder, count);
+		}
+		else {
+			if (module.getEmployer()!=null) 
+				module.getEmployer().surveyAncestors(menu, specsOrder, count);
+			surveySpecs(menu, specsOrder, count, menuItemsSpecs);
+		}
+
+	}
+	private void sortSubmenusBySpecsOrder(Menu menu){
+		if (menu == null)
+			return;
+		if (menu instanceof MesquiteSubmenu){
+			MenuItem[] specsOrder= new MenuItem[menu.getItemCount()];
+			MesquiteInteger count = new MesquiteInteger(0);
+
+			if (module.getEmployer()!=null) 
+				module.getEmployer().surveyAncestors(menu, specsOrder, count);
+			surveyDescendents(menu, specsOrder, count);
+
+			for (int i = 0; i< specsOrder.length; i++)
+				if (specsOrder[i] != null)
+					menu.remove(specsOrder[i]);
+			int ecount = 0;
+			for (int i = 0; i< specsOrder.length; i++){
+				if (specsOrder[i] != null){
+					menu.insert(specsOrder[i], ecount);
+					ecount++;
+				}
+			}
+		}
+		for (int i = 0; i< menu.getItemCount(); i++){
+			MenuItem mmi = menu.getItem(i);
+			if (mmi instanceof Menu)
+				sortSubmenusBySpecsOrder((Menu)mmi);
+		}
+	}
+
+	private void dumpMenu(Menu menu, String spacer){
+		if (menu == null)
+			return;
+		String addM = "";
+		if (menu instanceof MesquiteMenu && ((MesquiteMenu)menu).getSpecification() != null)
+			addM = "  ====> " + ((MesquiteMenu)menu).getSpecification().getName();
+		MesquiteMessage.println(spacer + "Menu: " + menu.getLabel() + addM);
+		for (int i = 0; i< menu.getItemCount(); i++){
+			MenuItem mmi = menu.getItem(i);
+			if (mmi instanceof Menu)
+				dumpMenu((Menu)mmi, spacer + "  ");
+			else {
+				String addMI = "";
+				if (mmi instanceof MesquiteMenuItem && ((MesquiteMenuItem)mmi).getSpecification() != null)
+					addMI = "  ====- " + ((MesquiteMenuItem)mmi).getSpecification().getName();
+				else if (mmi instanceof MesquiteCheckMenuItem && ((MesquiteCheckMenuItem)mmi).getSpecification() != null)
+					addMI = "  ====- " + ((MesquiteCheckMenuItem)mmi).getSpecification().getName();
+				MesquiteMessage.println(spacer + mmi.getLabel() + addMI);
+			}
+		}
+	}
+
+	/*  Menu Keyboard Equivalents / Menu Shortcuts
+
+	 A: Select All
+	 B:
+	 C:  Copy
+	 D: Toggle Fades (Chromaseq)
+	 E:
+	 F:  Find
+	 G:  Find Again
+	 H:  Find Footnote String
+	 I:  Get Info
+	 J:
+	 K:  
+	 L: Make Item Label (AnnotPanel)
+	 M: Move Selected (List Window)
+	 N:  New File
+	 O:  Open File
+	 P:  Print
+	 Q:  Quit
+	 R:  Revert Selected to Called (Chromaseq)
+	 S:  Save File
+	 T:  Previous Tool
+	 U:  
+	 V:  Paste
+	 W: Close Window
+	 X:  Cut
+	 Y:  
+	 Z:  Undo
+
+	 Clear: Clear
+	 .:  ccShortcut
+	 -: Convert Selected To Gaps (Chromaseq)
+
+	 Right, Left:  Next, Previous in Trace Character History
+	 Up, Down:  March Selection Forward / Reverse (Scattergram)
+	 				next / previous Tree in TraceCharacterHistory
+
+	 3: Find String   
+	 6: Find Sequence Again (FindSequence)
+	 8: Find Again  
+
+
+
+	 */
+
+
+}
+
diff --git a/Source/mesquite/lib/MenuVisibility.java b/Source/mesquite/lib/MenuVisibility.java
new file mode 100644
index 0000000..fa0f4a6
--- /dev/null
+++ b/Source/mesquite/lib/MenuVisibility.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+public class MenuVisibility implements Listable {
+	public String label;
+	public String command;
+	public String arguments;
+	public String commandableClassName;
+	public String dutyClass;
+	
+	public MenuVisibility(String label, String arguments, String command, String commandableClassName, String dutyClass){
+		this.label = label;
+		this.arguments = arguments;
+		this.commandableClassName = commandableClassName;
+		this.dutyClass = dutyClass;
+		this.command = command;
+	}
+	public String getName(){
+		return label;
+	}
+
+	public boolean matchesMenuItem(String label, String arguments, String command, String commandableClassName, String dutyClass){
+		if (this.command == null)
+			return false;
+		if (!stringsEqual(dutyClass,this.dutyClass))
+			return false;
+		if (dutyClass == null){ //no dutyclass
+			if (!stringsEqual(commandableClassName,this.commandableClassName))
+				return false;
+			if (!this.command.equals(command))
+				return false;
+			if (this.label.equals(label)) //this is sufficient
+					return true;
+			return false;
+			// ((arguments == null && this.arguments != null) || (arguments == null && this.arguments != null));
+		}
+		else {  //with dutyclass; 
+			return (this.label.equals(label)); //this is sufficient
+		/*			return true;
+			if ((arguments == null && this.arguments != null) || (arguments == null && this.arguments != null))
+				return false;
+			return (this.command.equals(command));*/
+		}
+	}
+	/*.................................................................................................................*/
+	public static boolean stringsEqual(String a, String b) {
+		if (a ==b)
+			return true;
+		if (a == null && b == null)
+			return true;
+		if ((a == null && b != null) || (a != null && b == null))
+			return false;
+		
+		return (a.equals(b));
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/MesqJEditorPane.java b/Source/mesquite/lib/MesqJEditorPane.java
new file mode 100644
index 0000000..a8e3e66
--- /dev/null
+++ b/Source/mesquite/lib/MesqJEditorPane.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import javax.swing.JEditorPane;
+import java.awt.*;
+
+//workaround for crashes on OS X
+public class MesqJEditorPane extends JEditorPane{
+	public MesqJEditorPane(String a, String b){
+		super(a, b);
+	}
+	public Dimension getPreferredSize(){
+		try {
+			return super.getPreferredSize();
+		}
+		catch(Exception e){
+		}
+		return new Dimension(300, 600);
+	}
+	public boolean getScrollableTracksViewportWidth() {
+		try {
+			return super.getScrollableTracksViewportWidth();
+		}
+		catch(Exception e){
+		}
+		return true;
+	}
+	public boolean getScrollableTracksViewportHeight() {
+		try {
+			return super.getScrollableTracksViewportHeight();
+		}
+		catch(Exception e){
+		}
+
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/Mesquite3DIntPoint.java b/Source/mesquite/lib/Mesquite3DIntPoint.java
new file mode 100644
index 0000000..69a576f
--- /dev/null
+++ b/Source/mesquite/lib/Mesquite3DIntPoint.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+
+public class Mesquite3DIntPoint  {
+	public int x, y, z;
+	public Mesquite3DIntPoint () {
+		x = 0; y = 0; z = 0;
+	}
+	public Mesquite3DIntPoint (int x, int y, int z) {
+		this.x = x;
+		this.y = y;
+		this.z = z;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteBoolean.java b/Source/mesquite/lib/MesquiteBoolean.java
new file mode 100644
index 0000000..e17dd7c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteBoolean.java
@@ -0,0 +1,229 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+/* ���������������������������bits������������������������������� */
+
+/* ======================================================================== */
+/** This boolean wrapper class is used to be able to pass integers by reference and have the
+	original change as needed.*/
+public class MesquiteBoolean implements Listable {
+	private boolean value;
+	private MesquiteCMenuItemSpec cmis = null;
+	public static MesquiteBoolean TRUE, FALSE;
+	private String name = null;
+	private boolean unassigned = true;
+	static {
+		TRUE = new MesquiteBoolean(true);
+		FALSE = new MesquiteBoolean(false);
+	}
+	public MesquiteBoolean(String name, boolean value) {
+		this.value=value;
+		unassigned = false;
+		this.name = name;
+	}
+	public MesquiteBoolean(boolean value) {
+		this.value=value;
+		unassigned = false;
+	}
+	public MesquiteBoolean() {
+		value = false;
+		unassigned = true;
+	}
+	
+	public void setName(String s){
+		name = s;
+	}
+	public String getName(){
+		return name;
+	}
+	public boolean getValue() {
+		return value;
+	}
+	public boolean isUnassigned() {
+		return unassigned;
+	}
+
+	public void setToUnassigned() {
+		unassigned=true;
+		value = false;
+	}
+
+	public void setValue(boolean value) {
+		unassigned = false;
+		if (value != this.value) {
+			this.value=value;
+			if (cmis!=null) {
+				MesquiteTrunk.resetCheckMenuItems();
+			}
+		}
+	}
+	public void setValue(String b) {
+		unassigned = true;
+		if (b == null){
+			value = false;
+			if (cmis!=null) 
+				MesquiteTrunk.resetCheckMenuItems();
+			return;
+		}
+		boolean v;
+		if (b.equalsIgnoreCase("true"))
+			v= true;
+		else if (b.equalsIgnoreCase("false"))
+			v = false;
+		else {
+			value = false;
+			if (cmis!=null) 
+				MesquiteTrunk.resetCheckMenuItems();
+			return;
+		}
+		unassigned = false;
+		if (v != this.value) {
+			this.value=v;
+			if (cmis!=null) 
+				MesquiteTrunk.resetCheckMenuItems();
+		}
+	}
+	
+  	MesquiteInteger pos = new MesquiteInteger();
+  	
+	public void toggleValue(String arguments) {
+	 	if (StringUtil.blank(arguments))
+			toggleValue();
+		else {
+			 if ("on".equalsIgnoreCase(arguments))
+				setValue(true);
+			else if  ("off".equalsIgnoreCase(arguments))
+				setValue(false);
+			else {
+				 String s = ParseUtil.getFirstToken(arguments, pos);
+				 if ("on".equalsIgnoreCase(s))
+					setValue(true);
+				else if  ("off".equalsIgnoreCase(s))
+					setValue(false);
+				else
+					toggleValue();
+			}
+		}
+	}
+	public void toggleValue() {
+		unassigned = false;
+		value=!value;
+		if (cmis!=null) {
+			MesquiteTrunk.resetCheckMenuItems();
+		}
+	}
+	public void bindMenuItem(MesquiteCMenuItemSpec cmis) {
+		this.cmis = cmis;
+	}
+	public void releaseMenuItem() {
+		this.cmis = null;
+	}
+	public static String toOffOnString(boolean b) {
+		if (b)
+			return "on";
+		else
+			return "off";
+	}
+	
+	public String toOffOnString() {
+		if (unassigned)
+			return "?";
+		else if (value)
+			return "on";
+		else
+			return "off";
+	}
+	public static boolean fromOffOnString(String b) {
+		if (b == null || b.equalsIgnoreCase("off"))
+			return false;
+		else
+			return true;
+	}
+	public static boolean fromTrueFalseString(String b) {
+		if (b != null && b.equalsIgnoreCase("true"))
+			return true;
+		else
+			return false;
+	}
+	public void setFromTrueFalseString(String b) {
+		if (b != null && b.equalsIgnoreCase("true"))
+			setValue(true);
+		else
+			setValue(false);
+	}
+	public static String toTrueFalseString(boolean b) {
+		if (b)
+			return "true";
+		else
+			return "false";
+	}
+	public String toString(){
+		if (unassigned)
+			return "?";
+		else if (value)
+			return "TRUE";
+		else
+			return "FALSE";
+	}
+	/*--------------------------------QUERY DIALOGS--------------------------*/
+	/*.................................................................................................................*/
+	/** queries user yes/no.*/
+	public static boolean yesNoQuery(MesquiteWindow parent, String s) {
+		return AlertDialog.query(parent,  "Query", s);
+	}
+	
+	/*.................................................................................................................*/
+	/** Presents a dialog with check box; returns true if OK hit.  New Dec 2001*/
+	public static MesquiteBoolean queryCheckBox(MesquiteWindow parent, String title, String message, String label, String help, boolean current) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog checkBoxDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (!StringUtil.blank(help))
+			checkBoxDialog.appendToHelpString(help);
+		checkBoxDialog.addLargeOrSmallTextLabel (message);
+		Checkbox cb = checkBoxDialog.addCheckBox(label, current);
+		
+		checkBoxDialog.completeAndShowDialog(true);
+		MesquiteBoolean value = new MesquiteBoolean();
+		if (buttonPressed.getValue()==0) 
+			value.setValue(cb.getState());
+		checkBoxDialog.dispose();
+		return value;
+	}
+	/*.................................................................................................................*/
+	/** Presents a dialog with check box; returns true if OK hit.  New Dec 2001*/
+	public static MesquiteBoolean queryCheckBox(MesquiteWindow parent, String title, String message, String label, boolean current) {
+		return queryCheckBox(parent,title,message,label,null, current);
+	}
+	/*.................................................................................................................*/
+	/** Presents a dialog with check box; returns true if OK hit.  THIS VERSION IS TO BE PHASED OUT*/
+	public static boolean queryCheckBox(MesquiteWindow parent, String title, String message, String label, MesquiteBoolean value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog checkBoxDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		checkBoxDialog.addLargeOrSmallTextLabel (message);
+		Checkbox cb = checkBoxDialog.addCheckBox(label, value.getValue());
+		
+		checkBoxDialog.completeAndShowDialog(true);
+		
+		if (buttonPressed.getValue()==0) 
+			value.setValue(cb.getState());
+		checkBoxDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteButton.java b/Source/mesquite/lib/MesquiteButton.java
new file mode 100644
index 0000000..9c676d5
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteButton.java
@@ -0,0 +1,411 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+/** A button that responds to a touch by calling its associated command.  Has "off" and "on" images associated with it.
+Used, for instance, for palette of tool-choosing buttons in the standard tree window.*/
+public class MesquiteButton extends MousePanel implements Explainable, ImageOwner { //, ComponentListener {
+	Image image;
+	Image optionImage;
+	public static Image[] offImage, onImage;  
+	MesquiteModule ownerModule;
+	public int totalWidth;
+	public int totalHeight;
+	MesquiteCommand command;
+	public String arguments;
+	boolean on = false;
+	private MediaTracker mt;
+	MesquiteTool tool;
+	int scheme;
+	Polygon dropDownTriangle;
+	boolean useWaitThread = true;
+	static {
+		offImage=  new Image[ColorDistribution.numColorSchemes];  
+		onImage=  new Image[ColorDistribution.numColorSchemes];  
+	}
+	public MesquiteButton (MesquiteModule ownerModule, MesquiteCommand command, String arguments, boolean initialState, String imagePath, int height, int width) {
+		this.image = MesquiteImage.getImage(imagePath);
+		this.ownerModule = ownerModule;
+		mt= new MediaTracker(ownerModule.containerOfModule().getOuterContentsArea());
+		mt.addImage(this.image, 0);
+		scheme = ColorDistribution.getColorScheme(ownerModule);
+		//mt.addImage(this.offImage, 1);
+		//mt.addImage(this.onImage, 2);
+		this.on = initialState;
+		this.totalWidth = width;
+		this.totalHeight = height;
+		this.command=command;
+		this.arguments = arguments;
+		dropDownTriangle=MesquitePopup.getDropDownTriangle();
+		setSize(totalWidth, totalHeight);
+		setBackground(ColorTheme.getInterfaceBackground()); //ggray
+		//addComponentListener(this);
+	}
+	public void setCommand(MesquiteCommand command){
+		this.command = command;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+	public void dispose(){ 
+		if (mt!=null)
+			mt.removeImage(image);
+		command = null;
+		mt = null;
+		if (waitThread !=null){
+			waitThread.interrupt();
+		}
+	}
+	public void setUseWaitThread(boolean useThread){
+		useWaitThread = useThread;
+	}
+	public String getToolExplanation(){
+		if (tool !=null) {
+			if (tool.getDescription()!= null){
+				String s = "Tool: " +tool.getDescription();
+				if (!tool.getEnabled())
+					s += " (disabled)";
+				if (!(tool.getExplanation()==null || tool.getDescription().equals(tool.getExplanation())))
+					s += "\n(" +tool.getExplanation() + ")";
+				return s;
+			}
+		}
+		return "";
+	}
+	public String getExplanation(){
+		if (tool!=null) {
+			String s= tool.getExplanation();
+			if (ownerModule!=null)
+				s+=" <font color=\"#808080\">(for module: " + ownerModule.getName() + ")</font>";
+			return s;
+		}
+		return "";
+	}
+	String buttonExplanation = null;
+	public void setButtonExplanation(String e){
+		buttonExplanation = e;
+	}
+	public String getButtonExplanation(){
+		if (buttonExplanation != null)
+			return buttonExplanation;
+		return getToolExplanation();
+	}
+	public void setOptionImagePath(String path){
+		if (path == null)
+			optionImage = null;
+		else
+			optionImage = MesquiteImage.getImage(path);
+	}
+	public String getImagePath(){
+		if (tool!=null)
+			return tool.getImagePath();
+		return "";
+	}
+	public void resetImage(String path){
+		if (mt!=null)
+			mt.removeImage(image);
+
+		this.image = MesquiteImage.getImage(path);
+		if (mt!=null)
+			mt.addImage(image, 4);
+		waitUntilImagesLoaded();
+		repaint();
+	}
+	public boolean imagesLoaded(){
+		return mt.checkAll();
+	}
+	public void waitUntilImagesLoaded(){
+		try {
+			mt.waitForAll();
+		} catch (Exception e) {
+		}
+	}
+	public void setTool(MesquiteTool tool){
+		this.tool = tool;
+		if (tool !=null)
+			tool.setButton(this);
+	}
+	public MesquiteTool getTool(){
+		return tool;
+	}
+	public void setOffOn(boolean on) {
+		this.on = on;
+}
+	public void update (Graphics g) {
+		paint(g);
+	}
+	boolean showBackground = true;
+	public void setShowBackground(boolean sh){
+		showBackground = sh;
+	}
+	private void drawImage(Graphics g, Image im, int x, int y, int w, int h, Component c){
+		if (im !=null)
+			g.drawImage(im, x, y, w, h, c);
+	}
+	private void drawImage(Graphics g, Image im, int x, int y, Component c){
+		if (im !=null)
+			g.drawImage(im, x, y, c);
+	}
+	public int getHiddenStatus(){
+		if (tool == null)
+			return InterfaceManager.NORMAL;
+		return InterfaceManager.isHiddenTool(tool);
+	}
+	public boolean getEnabled(){
+		if (tool == null)
+			return true;
+		return tool.getEnabled();
+	}
+	
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		//Rectangle rect = getBounds();
+		g.clearRect(0,0, totalWidth, totalHeight);
+		int hiddenStatus = getHiddenStatus();
+		if (hiddenStatus != InterfaceManager.NORMAL && InterfaceManager.isSimpleMode() && !InterfaceManager.isEditingMode()){
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+
+		Composite composite = null;
+		if (tool!=null && !tool.getEnabled()){
+			composite = ColorDistribution.getComposite(g);
+			ColorDistribution.setTransparentGraphics(g,0.2f);
+		}
+		int offset = 0;
+		if (showBackground){
+			offset = 5;
+			if (on){
+				g.setColor(ColorTheme.getActiveLight());
+				g.fillRoundRect(0, 0, totalWidth-1, totalHeight-1, 3, 3);
+				g.setColor(ColorTheme.getActiveDark());
+				g.drawRoundRect(0, 0, totalWidth-1, totalHeight-1, 3, 3);
+				//	drawImage(g, onImage[scheme],0,0, totalWidth, totalHeight, this);
+			}
+			else {
+				g.setColor(ColorTheme.getInterfaceElement());
+				g.fillRoundRect(1, 1, totalWidth-3, totalHeight-3, 3, 3);
+				g.setColor(ColorTheme.getInterfaceEdgeNegative());
+				g.drawRoundRect(1, 1, totalWidth-3, totalHeight-3, 3, 3);
+				//drawImage(g, offImage[scheme], 0, 0, totalWidth, totalHeight, this);
+			}
+		}
+		if (optionDown && optionImage!=null) 
+			drawImage(g, optionImage, offset,offset, this);
+		else
+			drawImage(g, image,offset,offset, this);  //16x16 pixels is standard tool cursor size
+		if (tool !=null){
+			if (tool.getPopUpOwner()!=null || tool.getOptionsCommand() !=null) {
+				dropDownTriangle.translate(totalWidth-7,2);
+				g.setColor(Color.white);
+				g.drawPolygon(dropDownTriangle);
+				g.setColor(Color.black);
+				g.fillPolygon(dropDownTriangle);
+				dropDownTriangle.translate(-(totalWidth-7),-(2));
+			}
+		}
+		if (tool!=null && !tool.getEnabled()) 
+			ColorDistribution.setComposite(g,composite);
+		if (hiddenStatus != InterfaceManager.NORMAL && InterfaceManager.isEditingMode()){
+			if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+				g.setColor(Color.red);
+			else {
+				g.setColor(Color.blue);
+			}
+			g.drawRoundRect(0, 0, totalWidth-1, totalHeight-1, 3, 3);
+			g.drawRoundRect(1, 1, totalWidth-3, totalHeight-3, 3, 3);
+			g.drawRoundRect(2, 2, totalWidth-5, totalHeight-5, 3, 3);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void setOptionDown(boolean d){
+		optionDown = d;
+	}
+	/* pass modifiers */
+	public void modifierKeysPressed (int modifiers) {
+		String modString = MesquiteEvent.modifiersToString(modifiers);
+		if (modString.indexOf("option")>=0) {
+			if (tool!=null && !optionDown){
+				if (optionImage!=null)
+					tool.setCursorImage(null);
+				tool.setOptionDown(true);
+
+				if (tool.getInUse() && (optionImage!=null || tool.hasTemporaryOptionCursor())) {
+					MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+					if (w!=null)
+						w.resetCursor();
+				}
+			}
+			optionDown = true;
+			repaint();
+		} else if (modString.indexOf("shift")>=0) {
+			if (tool!=null){
+				if (tool.getInUse() && ( tool.hasTemporaryShiftCursor())) {
+					MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+					if (w!=null)
+						w.resetCursor();
+				}
+			}
+		}
+
+	}
+	boolean optionDown;
+	/* pass modifiers */
+	public void modifierKeysReleased (int modifiers) {
+		String modString = MesquiteEvent.modifiersToString(modifiers);
+		if (modString.indexOf("option")<0) {
+			if (tool!=null && optionDown){
+				if (optionImage!=null)
+					tool.setCursorImage(null);
+				tool.setOptionDown(false);
+				if (tool.getInUse() && (optionImage!=null || tool.hasTemporaryOptionCursor())) {
+					MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+					if (w!=null)
+						w.resetCursor();
+				}
+			}
+			optionDown = false;
+			repaint();
+		} else if (modString.indexOf("shift")>=0) {
+			if (tool!=null){
+				if (tool.getInUse() && ( tool.hasTemporaryShiftCursor())) {
+					MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+					if (w!=null)
+						w.resetCursor();
+				}
+			}
+		}
+
+	}
+	ButtonWaitThread waitThread;
+	/* pass modifiers */
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool toolTouching) {
+		if (tool!=null && !tool.getEnabled()) 
+			return;
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Button", command, this);
+		}
+		else if (tool != null && InterfaceManager.isHiddenTool(tool) != InterfaceManager.NORMAL)
+			;
+		else if (useWaitThread){
+			String modString = MesquiteEvent.modifiersToString(modifiers);
+			//command.doItMainThread(arguments + "  " + Integer.toString(x) + "  " + Integer.toString(y) + "  " + modString, CommandChecker.getQueryModeString("Button", command, this));
+			if (modString == null || modString.indexOf("command")<0){
+				waitThread = new ButtonWaitThread(this, when, x, y);
+				waitThread.start();
+			}
+
+		}
+	}
+	boolean suppressUp = false;
+	boolean hideable = true;
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool toolTouching) {
+		if (tool!=null && !tool.getEnabled()) 
+			return;
+		if (waitThread!=null){
+			waitThread.goOff = true;
+			waitThread.interrupt();
+			waitThread = null;
+
+		}
+		if (command == null)
+			return;
+		String modString = MesquiteEvent.modifiersToString(modifiers);
+		int hiddenStatus = 0;
+		if (InterfaceManager.isEditingMode()){
+			if (tool != null && hideable){
+				hiddenStatus = InterfaceManager.isHiddenTool(tool);
+				if (hiddenStatus == InterfaceManager.NORMAL){
+					InterfaceManager.addToolToHidden(tool, true);
+					MesquiteTrunk.resetAllToolPalettes();
+				}
+				else if (hiddenStatus != InterfaceManager.HIDDENCLASS) {
+					InterfaceManager.removeToolFromHidden(tool.getName(), tool.getDescription(), true);
+					MesquiteTrunk.resetAllToolPalettes();
+				}
+
+			}
+		}
+		else 		if (!suppressUp)
+			command.doItMainThread(arguments + "  " + Integer.toString(x) + "  " + Integer.toString(y) + "  " + modString, CommandChecker.getQueryModeString("Button", command, this), this);
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool toolTouching) {
+		if (MesquiteWindow.windowOfItem(this)!=null) {
+			MesquiteWindow.windowOfItem(this).setExplanation(getButtonExplanation());
+		}
+		if (this.tool !=null && !this.tool.getEnabled()) {
+			setCursor(getDisabledCursor());
+		}
+		super.mouseEntered(modifiers,x,y, toolTouching);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool toolTouching) {
+		if (MesquiteWindow.windowOfItem(this)!=null) 
+			MesquiteWindow.windowOfItem(this).setExplanation("");
+		super.mouseExited(modifiers,x,y, toolTouching);
+	}
+	public void setOn () {
+		if (!on) {
+			on=true;
+			repaint();
+		}
+	}
+	public void setOff () {
+		if (on) {
+			on=false;
+			repaint();
+		}
+	}
+}
+
+class ButtonWaitThread extends Thread {
+	static final int waitTime = 500;
+	MesquiteButton button;
+	long when;
+	int x, y;
+	boolean goOff = false;
+	public ButtonWaitThread (MesquiteButton button, long when, int x, int y) {
+		this.button = button;
+		this.when = when;
+		this.x = x;
+		this.y=y;
+	}
+	/** DOCUMENT */
+	public void run() {
+		try {
+			while (!goOff && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting){
+				sleep(50);
+				if (!goOff && System.currentTimeMillis()-when>waitTime){
+					button.suppressUp = true;
+					button.command.doIt(button.arguments + "  " + Integer.toString(x) + "  " + Integer.toString(y) + "  command"); //double click and command interpreted as same
+					button.suppressUp = false;
+					goOff = true;
+				}
+			}
+
+		}
+		catch (InterruptedException e) {
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteCMenuItemSpec.java b/Source/mesquite/lib/MesquiteCMenuItemSpec.java
new file mode 100644
index 0000000..e6cec87
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteCMenuItemSpec.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Specifications to later make check menu items.*/
+
+public class MesquiteCMenuItemSpec extends MesquiteMenuItemSpec{
+	MesquiteBoolean checkBoolean;
+	public static CommandChecker checkerMCMI = null;
+	public MesquiteCMenuItemSpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule, MesquiteCommand command, MesquiteBoolean checkBoolean) {
+		super(whichMenu, itemName, ownerModule, command);
+		this.checkBoolean = checkBoolean;
+		if (checkBoolean!=null)
+			checkBoolean.bindMenuItem(this);
+	}
+
+	//This is constructor used, e.g. when submenu of candidate employees not requested
+	public MesquiteCMenuItemSpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule, MesquiteCommand command, String argument, MesquiteBoolean checkBoolean) {
+		super(whichMenu,  itemName,  ownerModule,  command);
+		setArgument(argument);
+		this.checkBoolean = checkBoolean;
+		if (checkBoolean!=null)
+			checkBoolean.bindMenuItem(this);
+	}
+	public static MesquiteCMenuItemSpec getMCMISpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule, MesquiteCommand command, MesquiteBoolean checkBoolean){
+		if (checkerMCMI!=null) {
+			checkerMCMI.registerMenuItem(ownerModule, itemName, command);
+			return null;
+		}
+		else {
+			ownerModule.checkMISVector();
+			MesquiteCMenuItemSpec mmis = new MesquiteCMenuItemSpec(whichMenu, itemName, ownerModule, command, checkBoolean);
+			ownerModule.getMenuItemSpecs().addElement(mmis, false);
+			return mmis;
+		}
+	}
+	
+	public void releaseBoolean() {
+		if (checkBoolean!=null)
+			checkBoolean.releaseMenuItem();
+	}
+	public MesquiteBoolean getBoolean() {
+		return checkBoolean;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteChart.java b/Source/mesquite/lib/MesquiteChart.java
new file mode 100644
index 0000000..a5ee160
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteChart.java
@@ -0,0 +1,1255 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.datatransfer.*;
+
+
+/* ======================================================================== */
+/** Charts for general use.  Currently only a few chart types.  At the moment this is specialized for 
+charts of points (2D), but in future basic class should be
+more abstract, and point-chart should be a subclass */
+public class MesquiteChart extends MesquitePanel  implements OwnedByModule {
+
+	//orientation stored in chart as 0 = items by values; 1 = values by items   (y by x)
+	public static final int VALUESONX = 0;
+	public static final int ITEMSONX = 1;
+
+	/**The core area of the chart that contains the graphical plot, just inside the axes*/
+	private ChartField field;
+	/**  ChartDisplayExtras attached to this chart*/
+	private ListableVector extras;
+	/** Dimensions of chart itself (pixels), including axis area and field*/
+	private int chartWidth = 48;
+	private int chartHeight = 48;
+	/** Margin within chart field (pixels), from axis to first point etc*/
+	private int margin = 0;
+	/**Margin between left edge of chart and Y axis (i.e., between edge of chart and chart field*/
+	private int xAxisEdge = 0; 
+	/**Margin between bottom edge of chart and X axis (i.e., between edge of chart and chart field*/
+	private int yAxisEdge = 0;
+	/**Are max and min's for axes constrained to something other than max and min's among data points? 
+	(used to make a series of charts have same ranges on axes*/
+	private boolean maxXConstrained=false;
+	private boolean maxYConstrained=false;
+	private boolean maxZConstrained=false;
+	private boolean minXConstrained=false;
+	private boolean minYConstrained=false;
+	private boolean minZConstrained=false;
+	private boolean showOrigin = false;
+	private String[] namesArray = null;
+	private Color[] colorsArray = null;
+	private Charter charter=null;
+	private int numPoints;
+	private MesquiteModule ownerModule;
+	public TextRotator textRotator;
+	public StringInABox yAxisWriter;
+	private int idNumber=0;
+	private NumberArray xArray;
+	private NumberArray yArray;
+	private NumberArray zArray;
+	private Bits selected;
+	private LongArray catArray;
+	private MesquiteNumber minX, minY, maxX, maxY, minZ, maxZ, utilA, utilB;
+	public MesquiteNumber axisMinX, axisMinY, axisMaxX, axisMaxY;
+	/*the number of pixels the left margin of the field is offset (for scrolling -- home is 0, but if scrolled first pixel of field
+	would be the effectively the nth pixel of the axis as it needs to be drawn*/
+	private int xPixelBase = 0; 
+	private int yPixelBase = 0; 
+	private boolean sizeToFit = true;
+	private int totalFieldWidth; 
+	private int totalFieldHeight; 
+	private int visWidth;
+	private int visHeight;
+	public String xAxisName="";
+	public String yAxisName="";
+	public String zAxisName="";
+	public MesquiteNumber temp = new MesquiteNumber();
+	//ChartScroll horizScroll, vertScroll;
+	public static final int scrollWidth = 16;
+	int initPosX = 0;
+	int initPosY = 0;
+	MesquiteCommand copyCommand;
+	ChartTool arrowTool, infoTool;
+	int orientation = 0; //specific to type of chart, used for charter etc. to record orientation
+	int numPointsMunched = 0;
+	public MesquiteChart(MesquiteModule ownerModule, int numToAllocate, int idNumber, Charter charter){
+		this.ownerModule = ownerModule;
+		this.idNumber=idNumber;
+		setLayout(null);
+		copyCommand = MesquiteModule.makeCommand("copy", this);
+		extras = new ListableVector();
+		xArray=new NumberArray(numToAllocate);
+		yArray=new NumberArray(numToAllocate);
+		selected = new Bits(numToAllocate);
+		numPoints=0;
+		minX = new MesquiteNumber();
+		maxX = new MesquiteNumber();
+		minY = new MesquiteNumber();
+		maxY = new MesquiteNumber();
+		minZ = new MesquiteNumber();
+		maxZ = new MesquiteNumber();
+		axisMinX = new MesquiteNumber();
+		axisMaxX = new MesquiteNumber();
+		axisMinY = new MesquiteNumber();
+		axisMaxY = new MesquiteNumber();
+		utilA = new MesquiteNumber();
+		utilB = new MesquiteNumber();
+		totalFieldWidth = MesquiteInteger.unassigned;
+		totalFieldHeight = MesquiteInteger.unassigned;
+		/*-----------
+
+		add(t = new TextField());
+		t.setBounds(0,0,64,64);
+		t.setVisible(true);
+		t.setBackground(Color.white);
+		t.setText("88888");
+		/*-----------*/
+		field = new ChartField(this);
+		togglePane(true);
+		field.setVisible(true);
+		setChartSize(chartWidth,chartHeight);
+		setCharter(charter);
+
+		//setBackground(Color.white);
+	}
+	public void dispose(){
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				ex.dispose();
+			}
+		}
+	}
+	public ListableVector getExtras() {
+		return extras;
+	}
+	public void addExtra(ChartExtra extra) {
+		if (extras != null)
+			extras.addElement(extra, false);
+	}
+	public void removeExtra(ChartExtra extra) {
+		if (extras != null)
+			extras.removeElement(extra, false);
+	}
+	public void removeAllExtrasOwned(MesquiteModule mb) {
+		if (extras != null) {
+			ChartExtra[] owned = new ChartExtra[extras.size()];
+			int count =0;
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				if (ex.getOwnerModule()== mb){
+					owned[count++] = ex;
+				}
+			}
+			for (int i=0; i<owned.length; i++)
+				if (owned[i]!=null)
+					removeExtra(owned[i]);
+		}
+	}
+	public boolean findExtra(ChartExtra extra) {
+		if (extras == null)
+			return false;
+		return (extras.indexOf(extra) >= 0);
+	}
+	public void destroyExtras(){
+		if (extras!=null)
+			extras.removeAllElements(true);
+	}
+	public boolean calculateAllExtras() {
+		boolean remunch = false;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				remunch |= ex.doCalculations();
+			}
+		}
+		return remunch;
+	}
+	public void drawAllBackgroundExtras(Graphics g) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				if (ex instanceof ChartBkgdExtra) {
+					if (ownerModule==null || ownerModule.isDoomed()) 
+						return;
+					ex.drawOnChart(g);
+				}
+			}
+		}
+	}
+	public void drawAllExtras(Graphics g) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				if (!(ex instanceof ChartBkgdExtra)) {
+					if (ownerModule==null || ownerModule.isDoomed()) 
+						return;
+					ex.drawOnChart( g);
+				}
+			}
+		}
+	}
+	public void drawAllExtrasAxes(Graphics g) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				ex.drawOnAxes(g, this);
+			}
+		}
+	}
+	public void printAllExtras(Graphics g) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ChartExtra ex = (ChartExtra)obj;
+				if (ownerModule==null || ownerModule.isDoomed()) 
+					return;
+				ex.printOnChart(g);
+			}
+		}
+	}
+	public void addPanelPlease(Panel P){
+		add(P);
+	}
+	public void removePanelPlease(Panel P){
+		remove(P);
+	}
+	public void addComponentPlease(Component P){
+		add(P);
+	}
+	public void removeComponentPlease(Component P){
+		remove(P);
+	}
+	public void setArrowTool(ChartTool tool){
+		arrowTool = tool;
+	}
+	public ChartTool getArrowTool(){
+		return arrowTool;
+	}
+	public void setInfoTool(ChartTool tool){
+		infoTool = tool;
+	}
+	public ChartTool getInfoTool(){
+		return infoTool;
+	}
+	/*.................................................................................................................*/
+	public long getID() {   
+		return idNumber;
+	}
+	ChartScrollPane fieldPane;
+	public void togglePane(boolean initiating) {
+		if (!sizeToFit) {
+			if (fieldPane==null || initiating) {
+				if (!initiating)
+					remove(field);
+				fieldPane = new ChartScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
+				//fieldPane.setBackground(Color.pink);
+				sizeDisplay();
+				add(fieldPane);
+				fieldPane.addField(field);
+				fieldPane.setScrollPosition(-initPosX, -initPosY);
+				sizeDisplay();
+				if (!initiating) {
+					fieldPane.setVisible(true);
+					field.repaint();
+				}
+			}
+		}
+		else {
+			if (fieldPane!=null || initiating)  {
+				if (!initiating)
+					remove(fieldPane);
+				fieldPane = null;
+				sizeDisplay();
+				add(field);
+				sizeDisplay();
+				if (!initiating) {
+					field.setVisible(true);
+					field.repaint();
+				}
+			}
+		}
+	}
+	void sizeDisplay(){
+		visWidth =chartWidth-getXAxisEdge();
+		visHeight =chartHeight-getYAxisEdge();
+
+		if (sizeToFit){
+			field.setSize(visWidth, visHeight);
+			field.setLocation(getXAxisEdge(), 0);
+		}
+		else {
+			fieldPane.setSize(visWidth, visHeight);
+			fieldPane.setLocation(getXAxisEdge(), 0);
+			field.setLocation(0, 0);
+			field.setSize(getFieldWidth(), getFieldHeight());
+			fieldPane.doLayout();
+		}
+	}
+	boolean setSizeDebugg = true;
+	public void setChartSize(int w, int h) { 
+		chartWidth=w;
+		chartHeight=h;
+		setSizeDebugg = false;
+		setSize(w,h);
+		setSizeDebugg = true;
+		sizeDisplay();
+	}
+	public void setSize(int w, int h) {   
+		if (setSizeDebugg)
+			MesquiteMessage.warnProgrammer("Programmer: use setChartwSize instead of setSize for Charts: " + getName());
+		super.setSize(w,h);
+	}
+	public void setTotalField(int w, int h) {   
+		totalFieldWidth = w;
+		totalFieldHeight = h;
+		sizeDisplay();
+	}
+	public void setTotalFieldWidth(int w) {   
+		totalFieldWidth = w;
+		sizeDisplay();
+	}
+	public void setTotalFieldHeight( int h) {   
+		totalFieldHeight = h;
+		sizeDisplay();
+	}
+	public int getFieldWidth() {   
+		if (sizeToFit)
+			return visWidth;
+		else if (!MesquiteInteger.isCombinable(totalFieldWidth))
+			return visWidth-scrollWidth;
+		else
+			return totalFieldWidth;
+	}
+	public int getFieldHeight() {   
+		if (sizeToFit)
+			return visHeight;
+		else if (!MesquiteInteger.isCombinable(totalFieldHeight))
+			return visHeight-scrollWidth;
+		else
+			return totalFieldHeight;
+	}
+	public int getVisWidth() {   
+		return visWidth;
+	}
+	public int getVisHeight() {   
+		return visHeight;
+	}
+	public void setXPixelBase(int b) {   
+		xPixelBase = b;
+	}
+	public void setYPixelBase(int b) {   
+		yPixelBase = b;
+	}
+	public int getXPixelBase() {   
+		return xPixelBase;
+	}
+	public int getYPixelBase() {   
+		return yPixelBase;
+	}
+	public void setSizeToFit(boolean b) {   
+		sizeToFit = b;
+		togglePane(false);
+		repaint();
+		if (fieldPane!=null)
+			fieldPane.repaint();
+		field.repaint();
+	}
+	public boolean getSizeToFit() {   
+		return sizeToFit;
+	}
+	public void setXAxisEdge(int edge) {   
+		xAxisEdge=edge;
+		sizeDisplay();
+	}
+	public void setYAxisEdge(int edge) {   
+		yAxisEdge=edge;
+		sizeDisplay();
+	}
+	public int getXAxisEdge() {   
+		return xAxisEdge;
+	}
+	public int getYAxisEdge() {   
+		return yAxisEdge;
+	}
+	public int getMargin() {   
+		return margin;
+	}
+	public int getChartWidth() {   
+		return chartWidth;
+	}
+	public int getChartHeight() {   
+		return chartHeight;
+	}
+	public int getNumPoints() {   
+		return numPoints;
+	}
+	public int getNumPointsMunched() {   
+		return numPointsMunched;
+	}
+	public Charter getCharter() {   
+		return charter;
+	}
+	public void setCharter(Charter c) {   
+		if (c != charter && c!= null) {
+			if (charter!=null)
+				charter.close();
+			this.charter=c;
+			charter.open(this);
+			charter.calculateChart(this);
+			repaint();
+			if (field!= null)
+				field.repaint();
+		}
+	}
+	public ChartField getField() {
+		return field;
+	}
+	public MesquiteModule getOwnerModule() {
+		return ownerModule;
+	}
+
+	/**
+	public void setMinimumX(MesquiteNumber num) {   
+		minX.setValue(num);
+	}
+	public void setMinimumY(MesquiteNumber num) {   
+		minY.setValue(num);
+	}
+	public void setMinimumZ(MesquiteNumber num) {   
+		minZ.setValue(num);
+	}
+/**/
+
+	public MesquiteNumber getMinimumX() {   
+		return minX;
+	}
+	public MesquiteNumber getMinimumY() {   
+		return minY;
+	}
+	public MesquiteNumber getMinimumZ() {   
+		return minZ;
+	}
+	public MesquiteNumber getMaximumX() {   
+		return maxX;
+	}
+	public MesquiteNumber getMaximumY() {   
+		return maxY;
+	}
+	public MesquiteNumber getMaximumZ() {   
+		return maxZ;
+	}
+	public MesquiteNumber getAxisMinimumX() {   
+		if (getShowOrigin() && axisMinX.isMoreThan(0)) axisMinX.setValue(0);
+		return axisMinX;
+	}
+	public MesquiteNumber getAxisMinimumY() {   
+		if (getShowOrigin() && axisMinY.isMoreThan(0)) axisMinY.setValue(0);
+		return axisMinY;
+	}
+	public void putVisMinimumX(MesquiteNumber num) {   
+		if (num==null)
+			return;
+		if (sizeToFit || fieldPane==null || fieldPane.getHAdjustable() == null)
+			num.setValue(getAxisMinimumX());
+		else {
+			Adjustable p = fieldPane.getHAdjustable();
+			double d = ((double)p.getValue())/(p.getMaximum() - p.getMinimum()) * (axisMaxX.getDoubleValue()-axisMinX.getDoubleValue());
+			num.setValue(d);
+		}
+		//calculate scroll position on x
+	}
+	public void putVisMinimumY(MesquiteNumber num) {   
+		if (num==null)
+			return;
+		if (sizeToFit || fieldPane==null || fieldPane.getVAdjustable() == null)
+			num.setValue(getAxisMinimumY());
+		else {
+			Adjustable p = fieldPane.getVAdjustable();
+			double d = ((double)p.getValue())/(p.getMaximum() - p.getMinimum()) * (axisMaxY.getDoubleValue()-axisMinY.getDoubleValue());
+			num.setValue(d);
+		}
+	}
+	public int scrollXOffset() {   
+		if (sizeToFit || fieldPane==null || fieldPane.getHAdjustable() == null)
+			return 0;
+		else {
+			Adjustable p = fieldPane.getHAdjustable();
+			if (p==null)
+				return 0;
+			return p.getValue();
+		}
+	}
+	public int scrollYOffset() {   
+		if (sizeToFit || fieldPane==null || fieldPane.getVAdjustable() == null)
+			return 0;
+		else {
+			Adjustable p = fieldPane.getVAdjustable();
+			if (p==null)
+				return 0;
+			return p.getValue();
+		}
+	}
+	public MesquiteNumber getAxisMaximumX() {   
+		return axisMaxX;
+	}
+	public MesquiteNumber getAxisMaximumY() {   
+		return axisMaxY;
+	}
+	public NumberArray getXArray() {
+		return xArray;
+	}
+	public NumberArray getYArray() {
+		return yArray;
+	}
+	public NumberArray getZArray() {
+		return zArray;
+	}
+	public MesquiteNumber getXTotal() {
+		return xArray.getTotal();
+	}
+	public MesquiteNumber getYTotal() {
+		return yArray.getTotal();
+	}
+	public MesquiteNumber getZTotal() {
+		return zArray.getTotal();
+	}
+	public Bits getSelected() {
+		return selected;
+	}
+
+	/*.................................................................................................................*/
+	public MesquiteCommand getCopyCommand() {
+		return copyCommand;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Copies information from the chart (or its selected points)", null, commandName, "copy")) {
+			String c = "";
+			MesquiteWindow f = MesquiteWindow.windowOfItem(this);
+			if (f instanceof MesquiteWindow){
+				MesquiteWindow w = (MesquiteWindow)f;
+				if (w.getMode()!=InfoBar.GRAPHICS)
+					c = w.getTextContents();
+				else
+					c = getTextVersion("\t", true, true);
+			}
+			else
+				c = getTextVersion("\t", true, true);
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(c);
+			clip.setContents(ss, ss);
+			return c;
+		}
+		else if (checker.compare(this.getClass(), "Selects all points", null, commandName, "selectAll")) {
+			selectAllPoints();
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	public String getTextVersion(){
+		return getTextVersion("\n", false, false);
+	}
+	public String getTextVersion(String spacer, boolean forClipboard, boolean selectedOnly){
+		return getTextVersion(spacer, StringUtil.lineEnding(), forClipboard, selectedOnly);
+	}
+	public void putRawTextVersion(int[] ord, String spacer, String betweenPoints, boolean selectedOnly, boolean forClipboard, StringBuffer s){
+		if (!forClipboard) {
+			s.append( StringUtil.lineEnding() + "Individual Points" + StringUtil.lineEnding());
+		}
+		boolean first = true;
+		for (int j= 0;j<getNumPoints(); j++) {
+			int i=j;
+			if (ord !=null && j<ord.length)
+				i = ord[j];
+			if ((!selectedOnly || selected.isBitOn(i)) && (!xArray.isUnassigned(i) || !yArray.isUnassigned(i))) {
+				if (!first)
+					s.append(betweenPoints);
+				first = false;
+				s.append(xArray.toString(i) + spacer + yArray.toString(i)) ;
+				if (zArray !=null)
+					s.append(spacer + zArray.toString(i));
+				if (!forClipboard && namesExist()){
+					String ss = getName(i);
+					if (ss!=null)
+						s.append(" (" + ss + ")");
+				}
+			}
+		}
+	}
+
+	public String getTextVersion(String spacer, String betweenPoints, boolean forClipboard, boolean selectedOnly){
+		if (getNumPoints() == 0)
+			return "The chart does not yet have any points.  It may be in the process of being recalculated or needing recalculation.";
+		int[] ord =  getOrderByX();
+		StringBuffer s = new StringBuffer();  
+		if (selectedOnly && !selected.anyBitsOn())
+			selectedOnly = false;
+		if (forClipboard){
+			putRawTextVersion(ord, spacer, betweenPoints, selectedOnly, forClipboard, s);
+		}
+		else {
+			s.append("X Axis - " + xAxisName + spacer + "Y Axis - " + yAxisName);
+			if (zArray !=null)
+				s.append(spacer + "Z Axis - " + zAxisName);
+			s.append(StringUtil.lineEnding());
+			if (charter !=null){
+				String fromCharter = charter.getTextVersion(this);
+				if (fromCharter !=null) {
+					if (zArray !=null)
+						s.append(StringUtil.lineEnding() + "Values (X: Y: Z)");
+					else
+						s.append(StringUtil.lineEnding() + "Values (X: Y)");
+
+					s.append(StringUtil.lineEnding() + fromCharter + StringUtil.lineEnding());
+				}
+			}
+
+			if (extras != null) {
+				int loc = s.length();
+				boolean appended = false;
+				Enumeration e = extras.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					ChartExtra ex = (ChartExtra)obj;
+					String sEx =ex.writeOnChart();
+					if (!StringUtil.blank(sEx)) {
+						appended = true;
+						s.append(StringUtil.lineEnding() + StringUtil.lineEnding() + sEx);
+					}
+				}
+				if (appended)
+					s.insert(loc,StringUtil.lineEnding() + "========================" + StringUtil.lineEnding());
+			}
+		}
+		return s.toString();
+	}
+	public LongArray getCatArray() {
+		return catArray;
+	}
+	public void setXAxisName(String name) {   
+		xAxisName=name;
+		//repaint();
+	}
+	public String getYAxisNameSuffix() {   
+		if (getCharter()==null)
+			return "";
+		else {
+			String s = getCharter().getYAxisNameSuffix();
+			if (StringUtil.blank(s)) 
+				return "";
+			else return " " + s;
+		}
+	}
+	public void setYAxisName(String name) {   
+		yAxisName=name;
+		if (textRotator==null)
+			textRotator = new TextRotator(100);
+		if (yAxisWriter==null)
+			yAxisWriter = new StringInABox(name, getFont(), getVisHeight());
+		else
+			yAxisWriter.setString(name);
+		//repaint();
+	}
+	public void setZAxisName(String name) {   
+		zAxisName=name;
+		if (textRotator==null)
+			textRotator = new TextRotator(100);
+		//repaint();
+	}
+	public String getXAxisName() {   
+		return xAxisName;
+	}
+	public String getYAxisName() {   
+		return yAxisName;
+	}
+	public String getZAxisName() {   
+		return zAxisName;
+	}
+	public void zeroChart() {   
+		xArray.zeroArray();
+		yArray.zeroArray();
+		if (zArray!=null)
+			zArray.zeroArray();
+		selected.clearAllBits();
+		numPoints=0;
+	}
+	public void deassignChart() {   
+		xArray.deassignArrayToInteger();
+		yArray.deassignArrayToInteger();
+		if (zArray!=null)
+			zArray.deassignArrayToInteger();
+		zArray = null;
+		if (catArray!=null)
+			catArray.deassignArray();
+		selected.clearAllBits();
+		catArray = null;
+		namesArray = null;
+		colorsArray = null;
+		numPoints=0;
+	}
+	public boolean colorsExist() {
+		return (colorsArray!=null);
+	}
+	boolean legalPoint(int index){
+		return (index>=0 && index<numPoints);
+	}
+	public Color getColor(int index) {
+		if (!legalPoint(index))
+			return null;
+		if (colorsArray!=null && index>=0 && index < colorsArray.length)
+			return (colorsArray[index]);
+		else 
+			return null;
+	}
+	public void setColor(int point, Color color) {  
+		if (!legalPoint(point))
+			return;
+		if (colorsArray==null) {
+			colorsArray = new Color[numPoints+100];
+		}
+		else if (numPoints>=colorsArray.length) {
+			Color[] temp = new Color[numPoints+100];
+			for (int i = 0; i<colorsArray.length; i++)
+				temp[i]=colorsArray[i];
+			colorsArray = temp;
+		}
+		colorsArray[point] = color;
+	}
+	public boolean namesExist() {
+		return (namesArray!=null);
+	}
+	public String getName(int index) {
+		if (namesArray!=null && index>=0 && index < namesArray.length)
+			return (namesArray[index]);
+		else 
+			return null;
+	}
+	public void setName(int point, String name) {   
+		if (!legalPoint(point))
+			return;
+		if (namesArray==null) {
+			namesArray = new String[numPoints+100];
+		}
+		else if (numPoints>=namesArray.length) {
+			String[] temp = new String[numPoints+100];
+			for (int i = 0; i<namesArray.length; i++)
+				temp[i]=namesArray[i];
+			namesArray = temp;
+		}
+		namesArray[point] = name;
+	}
+	//currently not used; points can be assigned to categories
+	public void setCategory(int point, long category) {   
+		if (!legalPoint(point))
+			return;
+		if (catArray == null && category !=MesquiteLong.unassigned) {
+			catArray = new LongArray(numPoints + 100);
+			catArray.deassignArray();
+		}
+		else if (catArray!=null && numPoints>= catArray.getSize())
+			catArray.resetSize(numPoints + 100);
+		if (catArray!=null)
+			catArray.setValue(point, category);
+	}
+	public void selectPoint(int point){
+		if (!legalPoint(point))
+			return;
+		selected.setBit(point);
+	}
+	public void deselectPoint(int point){
+		if (!legalPoint(point))
+			return;
+		selected.clearBit(point);
+	}
+	public void selectAllPoints(){
+		selected.setAllBits();
+	}
+	public void deselectAllPoints(){
+		selected.clearAllBits();
+	}
+	public void synchronizePointSelection(Selectionable a){
+		if (a==null)
+			return;
+		selected.clearAllBits();
+		for (int i=0; i<numPoints && i<a.getNumberOfSelectableParts(); i++)
+			if (a.getSelected(i)) {
+				selectPoint(i);
+			}
+	}
+	public int addPoint(MesquiteNumber x, MesquiteNumber y) { 
+		if (numPoints+1>=xArray.getSize())
+			xArray.resetSize(xArray.getSize()+100);
+		xArray.setValue(numPoints, x);
+		if (numPoints+1>=yArray.getSize())
+			yArray.resetSize(yArray.getSize()+100);
+		yArray.setValue(numPoints, y);
+		if (numPoints+1>=selected.getSize())
+			selected.resetSize(selected.getSize()+100);
+		selected.clearBit(numPoints);
+		numPoints++;
+		return numPoints-1;
+	}
+
+	public int addSumPoint(MesquiteNumber x, MesquiteNumber y) {   
+		temp.setValue(y);
+		int already = xArray.findValue(x);
+		if (already!=-1) {
+			yArray.addValue(already, temp); //use temp because temp's value will be changed
+			return already;
+		}
+		else {
+			return addPoint(x,y);
+		}
+	}
+
+	public int addPoint(MesquiteNumber x, MesquiteNumber y, MesquiteNumber z) {   
+
+		if (z!=null) {
+			if (zArray==null)
+				zArray = new NumberArray(numPoints+1);
+			if (numPoints+1>=zArray.getSize())
+				zArray.resetSize(zArray.getSize()+100);
+			zArray.setValue(numPoints, z);
+		}
+		return addPoint(x,y);
+	}
+
+	public void constrainMaximumX(MesquiteNumber c){
+		maxXConstrained=true;
+		maxX.setValue(c);
+		axisMaxX.setValue(c);
+	}
+	public void constrainMaximumY(MesquiteNumber c){
+		maxYConstrained=true;
+		maxY.setValue(c);
+		axisMaxY.setValue(c);
+	}
+	public void constrainMaximumZ(MesquiteNumber c){
+		maxZConstrained=true;
+		maxZ.setValue(c);
+		//axisMaxZ.setValue(c);
+	}
+	public void constrainMinimumX(MesquiteNumber c){
+		minXConstrained=true;
+		minX.setValue(c);
+		axisMinX.setValue(c);
+	}
+	public void constrainMinimumY(MesquiteNumber c){
+		minYConstrained=true;
+		minY.setValue(c);
+		axisMinY.setValue(c);
+	}
+	public void constrainMinimumZ(MesquiteNumber c){
+		minZConstrained=true;
+		minZ.setValue(c);
+		//axisMinZ.setValue(c);
+	}
+
+	public boolean isMaximumXConstrained(){
+		return maxXConstrained;
+	}
+	public boolean isMaximumYConstrained(){
+		return maxYConstrained;
+	}
+	public boolean isMaximumZConstrained(){
+		return maxZConstrained;
+	}
+	public boolean isMinimumXConstrained(){
+		return minXConstrained;
+	}
+	public boolean isMinimumYConstrained(){
+		return minYConstrained;
+	}
+	public boolean isMinimumZConstrained(){
+		return minZConstrained;
+	}
+
+	public void deConstrainMaximumX(){
+		maxXConstrained=false;
+	}
+	public void deConstrainMaximumY(){
+		maxYConstrained=false;
+	}
+	public void deConstrainMaximumZ(){
+		maxZConstrained=false;
+	}
+	public void deConstrainMinimumX(){
+		minXConstrained=false;
+	}
+	public void deConstrainMinimumY(){
+		minYConstrained=false;
+	}
+	public void deConstrainMinimumZ(){
+		minZConstrained=false;
+	}
+	public int[] getOrderByX () {
+		int numPts = numPoints; //prevents problems if numPoints modified meanwhile
+		int[] ord = new int[numPts];
+		NumberArray copy = xArray.cloneArray();
+		for (int i = 1; i < numPts; i++)
+			ord[i]=i;
+		for (int i = 1; i < numPts; i++) {
+			for (int j= i-1; j>=0 && copy.firstIsGreater(j,j+1); j--) {
+				copy.swapValues(j,j+1);
+				int temp = ord[j];
+				ord[j]=ord[j+1];
+				ord[j+1]=temp;
+			}
+		}
+		return ord;
+	}
+	public int[] getOrderByY () {
+		int numPts = numPoints; //prevents problems if numPoints modified meanwhile
+		int[] ord = new int[numPts];
+		NumberArray copy = yArray.cloneArray();
+		for (int i = 1; i < numPts; i++)
+			ord[i]=i;
+		for (int i = 1; i < numPts; i++) {
+			for (int j= i-1; j>=0 && copy.firstIsGreater(j,j+1); j--) {
+				copy.swapValues(j,j+1);
+				int temp = ord[j];
+				ord[j]=ord[j+1];
+				ord[j+1]=temp;
+			}
+		}
+		return ord;
+	}
+	public int[] getOrderByZ () {
+		int numPts = numPoints; //prevents problems if numPoints modified meanwhile
+		int[] ord = new int[numPts];
+		for (int i = 1; i < numPts; i++)
+			ord[i]=i;
+		if (zArray==null)
+			return ord;
+		NumberArray copy = zArray.cloneArray();
+		for (int i = 1; i < numPts; i++) {
+			for (int j= i-1; j>=0 && copy.firstIsGreater(j,j+1); j--) {
+				copy.swapValues(j,j+1);
+				int temp = ord[j];
+				ord[j]=ord[j+1];
+				ord[j+1]=temp;
+			}
+		}
+		return ord;
+	}
+	public void sortByX () {
+		for (int i = 1; i < numPoints; i++) {
+			for (int j= i-1; j>=0 && xArray.firstIsGreater(j,j+1); j--) {
+				xArray.swapValues(j,j+1);
+				yArray.swapValues(j,j+1);
+				if (zArray !=null)
+					zArray.swapValues(j,j+1);
+				selected.swapValues(j, j+1);
+			}
+		}
+	}
+	public void sortByY () {
+		for (int i = 1; i < numPoints; i++) {
+			for (int j= i-1; j>=0 && yArray.firstIsGreater(j,j+1); j--) {
+				xArray.swapValues(j,j+1);
+				yArray.swapValues(j,j+1);
+				if (zArray !=null)
+					zArray.swapValues(j,j+1);
+				selected.swapValues(j, j+1);
+			}
+		}
+	}
+	public void sortByZ () {
+		if (zArray!=null) {
+			for (int i = 1; i < numPoints; i++) {
+				for (int j= i-1; j>=0 && zArray.firstIsGreater(j,j+1); j--) {
+					xArray.swapValues(j,j+1);
+					yArray.swapValues(j,j+1);
+					zArray.swapValues(j,j+1);
+					selected.swapValues(j, j+1);
+				}
+			}
+		}
+	}
+	public void munch(){
+		while (inMunch())
+			;
+		field.repaint();  //the field will call the chart to be repainted, so that axes are drawn afterward
+	}
+	private boolean inMunch(){
+		int expandX=0;
+		if (!minXConstrained) {
+			xArray.placeMinimumValue(minX, numPoints);
+		}
+		if (!maxXConstrained) {
+			xArray.placeMaximumValue(maxX, numPoints);
+		}
+		if (!minYConstrained) {
+			yArray.placeMinimumValue(minY, numPoints);
+
+		}
+		if (!maxYConstrained) {
+			yArray.placeMaximumValue(maxY, numPoints);
+		}
+		if (zArray!=null) {
+			if (!minZConstrained)
+				zArray.placeMinimumValue(minZ, numPoints);
+			if (!maxZConstrained) 
+				zArray.placeMaximumValue(maxZ, numPoints);
+		}
+		utilA.setValue(maxX);
+		utilA.subtract(minX);
+		utilA.divideBy(20);
+		if (utilA.isZero())
+			utilA.add(1);
+		if (!minXConstrained) {
+			utilB.setValue(minX);
+			utilB.subtract(utilA);
+			axisMinX.setValue(utilB);
+		}
+		else {
+			axisMinX.setValue(minX);
+		}
+		if (!maxXConstrained) {
+			utilB.setValue(maxX);
+			utilB.add(utilA);
+			axisMaxX.setValue(utilB);
+		}
+		else {
+			axisMaxX.setValue(maxX);
+		}
+		if (yArray.getValueClass() == NumberArray.DOUBLE){
+			utilA.setValue(maxY);
+			utilA.subtract(minY);
+			utilA.divideBy(20);
+			if (utilA.isZero())
+				utilA.add(1);
+			if (!minYConstrained) {
+				utilB.setValue(minY);
+				utilB.subtract(utilA);
+				axisMinY.setValue(utilB);
+			}
+			else {
+				axisMinY.setValue(minY);
+			}
+			if (!maxYConstrained) {
+				utilB.setValue(maxY);
+				utilB.add(utilA);
+				axisMaxY.setValue(utilB);
+			}
+			else {
+				axisMaxY.setValue(maxY);
+			}
+		}
+		else {
+			axisMinY.setValue(minY);
+			axisMaxY.setValue(maxY);
+			if (maxY.getLongValue()-minY.getLongValue()<20){
+				axisMinY.subtract(1);
+				axisMaxY.add(1);
+			} 
+			else {
+				long inc = (maxY.getLongValue()-minY.getLongValue())/10;
+				if (inc <1)
+					inc = 1;
+				axisMinY.subtract(inc); //'FIX
+				axisMaxY.add(inc);
+			}
+		}
+		numPointsMunched = numPoints;
+
+		if (charter!=null)
+			charter.calculateChart(this);
+		else
+			MesquiteMessage.printStackTrace("charter null in MesquiteChart");
+		return calculateAllExtras();
+	}
+	public Color getFieldBackground() {   
+		return field.getBackground();
+	}
+	public void showQuickMessage(int whichPoint, int x, int y, String message){
+		if (charter!=null)
+			charter.showQuickMessage(this, whichPoint, x, y, message);
+	}
+	public void hideQuickMessage(){
+		charter.hideQuickMessage(this);
+	}
+	/**/
+	public void drawAxes(boolean printing) {
+		Graphics g = getGraphics();
+		if (charter!=null && g!=null) {
+			charter.drawAxes(g, printing, chartWidth, chartHeight, this);
+			drawAllExtrasAxes(g);
+			g.dispose();
+		}
+	}
+
+	/*...............................................................................................................*/
+	public void print(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Color bgc = getBackground();
+		setBackground(Color.white);
+		if (charter!=null)
+			charter.drawAxes(g, true, chartWidth, chartHeight, this);
+		setBackground(bgc);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (charter!=null)
+			charter.drawAxes(g, false, chartWidth, chartHeight, this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+
+	/*.................................................................................................................*/
+	public void printChart(MesquitePrintJob pjob, MesquiteWindow window) {
+		if (pjob != null) {
+			pjob.printComponent(this, new Dimension(getFieldWidth() + getXAxisEdge(), getFieldHeight() + getYAxisEdge() + 50), null);
+			/*
+	 		field.suppressBlank = true;
+			Dimension dim = pjob.getPageDimension();
+			int w;
+			int h;
+ 			int currentWidth = getChartWidth();
+ 			int currentHeight = getChartHeight();
+ 			if (currentHeight == 0 || currentWidth == 0) {
+ 				w = dim.width;
+ 				h = dim.height;
+ 			}
+ 			else if (((double)dim.width)/currentWidth > ((double)dim.height)/currentHeight) {
+ 				w = (int)(((double)dim.height)/currentHeight * currentWidth);
+ 				h = dim.height;
+ 			}
+ 			else {
+ 				w = dim.width;
+ 				h = (int)(((double)dim.width)/currentWidth * currentHeight);
+ 			}
+			setChartSize(w, h); // why doesn't this work???
+			if (sizeToFit){
+	 			Graphics pg = pjob.getGraphics();
+	 			if (pg!=null) {
+	 				pg.setFont(getFont());
+	 				printAll(pg); 
+	 				pg.dispose();
+	 			}
+ 			}
+ 			else {
+				int x = getXPixelBase();
+				int y = getYPixelBase();
+ 	 			int pixelHeight = 0;
+				while (pixelHeight<=totalFieldHeight) {
+			 		setYPixelBase(pixelHeight);
+	 	 			int pixelWidth = 0;
+					while (pixelWidth<=totalFieldWidth) {
+		    	 			Graphics pg = pjob.getGraphics();
+			 			setXPixelBase(pixelWidth);
+		    	 			if (pg!=null) {
+		    	 				pg.setFont(getFont());
+		    	 				printAll(pg); 
+		    	 				pg.dispose();
+		    	 			}
+		    	 			pixelWidth += visWidth;
+		 			}
+		    	 		pixelHeight += visHeight;
+	 			}
+	 			setXPixelBase(x);
+	 			setYPixelBase(y);
+ 			}
+			setChartSize(currentWidth, currentHeight);
+	 		field.suppressBlank = false;
+			 */
+		}
+	}
+	/*.................................................................................................................*/
+	/**
+	 * @author Peter Midford
+	 */
+	public void chartToPDF(MesquitePDFFile pdff, MesquiteWindow window, int fitToPage) {
+		if (pdff != null) {
+			Graphics g2 = pdff.getPDFGraphicsForComponent(this, new Dimension(getFieldWidth()+getXAxisEdge(), getFieldHeight()+getYAxisEdge()+50));
+			this.print(g2);
+			g2.translate(getXAxisEdge(),0);
+			field.print(g2);
+			this.printAllExtras(g2);
+			pdff.end();
+		}
+	}
+	/*.................................................................................................................*/
+	public void drawBlank() {   
+		field.drawBlank();
+	}
+
+	public void setOrientation(int orient){
+		orientation = orient;
+	}
+	public int getOrientation(){
+		return orientation;
+	}
+	boolean useAverage=false;
+	public void setUseAverage(boolean ua){
+		useAverage = ua;
+	}
+	public boolean getUseAverage(){
+		return useAverage;
+	}
+	public boolean getShowOrigin() {
+		return showOrigin;
+	}
+	public void setShowOrigin(boolean showOrigin) {
+		this.showOrigin = showOrigin;
+	}
+}
+/* ======================================================================== */
+class ChartScrollPane extends ScrollPane {
+	public ChartScrollPane (int scrollPolicy) {
+		super(scrollPolicy);
+	}
+	public void addField(Component c){
+		addImpl(c, null, 0);
+	}
+}
+
+
+/* ======================================================================== */
+/* scrollbar for chart */
+class ChartScroll extends MesquiteScrollbar {
+	MesquiteChart chart;
+	public ChartScroll (MesquiteChart chart, int orientation, int value, int visible, int min, int max){
+		super(orientation, value, visible, min, max);
+		this.chart=chart;
+	}
+
+	public void scrollTouched(){
+		int currentValue = getValue();
+		//chart.setPosition(this, currentValue);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteCheckMenuItem.java b/Source/mesquite/lib/MesquiteCheckMenuItem.java
new file mode 100644
index 0000000..b75a9eb
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteCheckMenuItem.java
@@ -0,0 +1,287 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+
+/* ======================================================================== */
+/** A class for checkboxmenuitems.*/
+
+public class MesquiteCheckMenuItem extends CheckboxMenuItem implements Commandable, ActionListener, ItemListener{
+	public MesquiteCommand command, resetCommand;
+	private MesquiteModule ownerModule;
+	public String itemName, itemID;
+	public String argument;
+	public Class dutyClass = null;
+	MesquiteBoolean checkBoolean;
+	MesquiteString selected;
+	boolean previousState;
+	private boolean disposed = false;
+	public boolean disconnectable = true;
+	//private boolean alternator = false; //THIS SHOULD BE EXPUNGED.  PRESENT BECAUSE MRJ CALLS TWICE. 
+	MesquiteCMenuItemSpec specification;
+	int hiddenStatus = InterfaceManager.NORMAL;
+	boolean hiddenStatusSet = false;
+	boolean hideable = true;
+
+	//This is constructor used to make menu from specs
+	public MesquiteCheckMenuItem(MesquiteCMenuItemSpec specification) {
+		super();
+		resetCommand = new MesquiteCommand("reset", this);
+		addActionListener(this);
+		addItemListener(this);
+		if (specification.itemName == null) {
+			MesquiteMessage.println("Menu item with null name: specification " + specification);
+			MesquiteCommand c = specification.getCommand();
+			if (c!=null) {
+				MesquiteMessage.println("      -- command " + c.getName() + " to " + c.getOwner());
+			}
+			this.setLabel("untitled");
+		}
+		else
+			this.setLabel(specification.itemName);
+		this.specification = specification;
+		if (specification.shortcut!=null)
+			setShortcut(new MenuShortcut(specification.shortcut.getValue(), specification.shortcutNeedsShift));
+		this.itemName = specification.itemName;
+		this.itemID = specification.referentID;
+		this.argument = specification.argument;
+		//As a test of whether it's necessary to remember ownerModule, commented out:  this.ownerModule = specification.ownerModule;
+		this.command = specification.command;
+		this.dutyClass = specification.dutyClass;
+		this.checkBoolean = specification.getBoolean();
+		if (checkBoolean!=null)
+			setState(checkBoolean.getValue());
+		previousState = getState();
+		if (command==null || !specification.isEnabled()) {
+			setEnabled(false);
+		}
+	}
+	public MesquiteCheckMenuItem(String itemName, MesquiteModule ownerModule, MesquiteCommand command, String argument, MesquiteString selected) {
+		super();
+		resetCommand = new MesquiteCommand("reset", this);
+		addActionListener(this);
+		addItemListener(this);
+		this.itemName = itemName;
+		if (itemName == null) {
+			MesquiteMessage.printStackTrace("Check Menu item with null name: ownerModule " + ownerModule);
+			this.setLabel("untitled");
+		}
+		else
+			this.setLabel(itemName);
+		this.argument = argument;
+		//As a test of whether it's necessary to remember ownerModule, commented out:  this.ownerModule = ownerModule;
+		this.command = command;
+		this.checkBoolean = null;
+		this.selected = selected;
+
+		if (selected!=null) {
+			if (selected.getValue() == null)
+				setState(false);
+			else
+				setState(selected.getValue().equals(itemName)); 
+			//setState(StringUtil.tokenize(selected.getValue()).equals(argument));  //why is this using the argument (and hence needs to tokenize) instead of the itemName?
+			selected.bindMenuItem();
+		}
+		previousState = getState();
+		if (command==null)
+			setEnabled(false);
+	}
+
+	public void setHiddenStatus(int hiddenStatus){
+		setHiddenStatus(hiddenStatus, null);
+	}
+	public void setHideable(boolean h ){
+		hideable = h;
+	}
+	public void resetLabel(){
+		if (InterfaceManager.isEditingMode()){
+			if (!hideable)
+				setLabel("(*) " + itemName);
+			else if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+				setLabel("(OFF) " + itemName);
+			else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+				setLabel("(PACKAGE OFF) " + itemName);
+			else
+				setLabel("" + itemName);
+		}
+		else
+			setLabel(itemName);
+	}
+	public void setHiddenStatus(int hiddenStatus, Class dutyClass){
+		if (!hideable){
+			if (InterfaceManager.isEditingMode())
+				setLabel("(*) " + itemName);
+			else
+				setLabel(itemName);
+			return;
+		}
+		hiddenStatusSet = true;
+		this.hiddenStatus = hiddenStatus;
+		if (dutyClass != null)
+			this.dutyClass = dutyClass;
+		if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+			setLabel("(OFF) " + itemName);
+		else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+			setLabel("(PACKAGE OFF) " + itemName);
+		else
+			setLabel("" + itemName);
+	}
+	public MesquiteMenuItemSpec getSpecification(){
+		return specification;
+	}
+	public void resetEnable() {
+		if (specification != null)
+			setEnabled(specification.isEnabled());
+	}
+	public void disconnect(){
+		//if (command!=null && command.getOwner()==ownerModule) //MEMORY shouldn't adways set null
+		//	command.setOwner(null);
+		if (disconnectable){
+			disposed = true;
+			ownerModule = null;
+			command = null;
+			checkBoolean = null;
+		}
+	}
+	public void set(boolean s){
+		super.setState(s);
+		previousState =getState();
+	}
+	Object referent = null;
+	public void setReferent(Object referent){
+		this.referent = referent;
+	}
+	public Object getReferent(){
+		return referent;
+	}
+	
+	public void setReferentID(String id){
+		itemID = id;
+	}
+	public String getReferentID(){
+		return itemID;
+	}
+	public void resetCheck() {
+		if (checkBoolean != null)
+			setState(checkBoolean.getValue());
+		else if (selected!=null) {
+			if (selected.getValue()== null)
+				setState(false);
+			else {
+				if (selected.getReferentID() != null && itemID != null){
+					setState(selected.getValue().equals(itemName) && selected.getReferentID().equals(itemID));
+				}
+				else
+					setState(selected.getValue().equals(itemName));
+			}
+		}
+		previousState = getState();
+	}
+	Journal j =null;
+	public void actionPerformed(ActionEvent e) {
+		//Event queue
+		if (previousState != getState()) {   
+			if (disposed)
+				MesquiteMessage.notifyUser("Warning: attempt to use disposed checked menu item");
+			if (command==null)
+				MesquiteMessage.warnProgrammer("command null in check menu item");
+			if (hideable && hiddenStatusSet && InterfaceManager.isEditingMode()){
+				if (hiddenStatus == InterfaceManager.NORMAL){
+					InterfaceManager.addMenuItemToHidden(itemName, argument, command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.TOBEHIDDEN);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+				else if (hiddenStatus != InterfaceManager.HIDDENCLASS) {
+					InterfaceManager.removeMenuItemFromHidden(itemName, argument, command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.NORMAL);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+			}
+			else	{
+				previousState = getState();
+				if ((e.getModifiers() & ActionEvent.ALT_MASK)!=0)
+					MesquiteWindow.respondToQueryMode("Menu item \"" + getLabel() + "\"", command, this);
+				else {
+					chooseItem(argument);
+					return;
+				}
+			}
+		}
+		resetCheck();
+	}
+
+	public void itemStateChanged(ItemEvent e) {
+		//Event queue
+		if (previousState != getState()) {   
+			
+			if (disposed)
+				MesquiteMessage.notifyUser("Warning: attempt to use disposed checked menu item");
+			if (command==null)
+				MesquiteMessage.warnProgrammer("command null in check menu item");
+			if (hideable && hiddenStatusSet && InterfaceManager.isEditingMode()){
+				if (hiddenStatus == InterfaceManager.NORMAL){
+					InterfaceManager.addMenuItemToHidden(itemName, argument, command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.TOBEHIDDEN);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+				else if (hiddenStatus != InterfaceManager.HIDDENCLASS) {
+					InterfaceManager.removeMenuItemFromHidden(itemName, argument, command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.NORMAL);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+				resetCheck();
+			}
+			else {
+				previousState = getState();
+				/*if ((e.modifiers & ActionEvent.ALT_MASK)!=0)
+				MesquiteWindow.respondToQueryMode("Menu item \"" + getLabel() + "\"", command, this);
+			else*/
+				chooseItem(argument);
+			}
+
+		}
+
+	}
+	public void chooseItem(String arg) {
+		if (command == null || MesquiteTrunk.suppressMenuResponse)
+			return;
+		if (!command.bypassQueue && MesquiteDialog.currentWizard != null){
+			MesquiteTrunk.mesquiteTrunk.alert("Please complete the questions of the Wizard dialog before selecting menu items");
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (argument != null)
+			command.doItMainThread(arg, CommandChecker.getQueryModeString("Menu item", command, this), this, MesquiteDialog.useWizards);  // command invoked
+		else
+			command.doItMainThread("", CommandChecker.getQueryModeString("Menu item", command, this), this, MesquiteDialog.useWizards);  // command invoked
+		resetCommand.doItMainThread("", null, false, false, this);
+	}
+
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "resetsChecks", null, commandName, "resetCheckMenus")) {
+
+			MesquiteTrunk.resetCheckMenuItems();
+			MesquiteTrunk.checkForResetCheckMenuItems();   
+			
+		}
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteCollator.java b/Source/mesquite/lib/MesquiteCollator.java
new file mode 100644
index 0000000..3dd7d19
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteCollator.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.text.Collator;
+
+//an alternative to Collator that considers numerical values
+public class MesquiteCollator {
+	Collator collator;
+	Parser pA, pB;
+	public MesquiteCollator (){
+		collator = Collator.getInstance();
+		pA = new Parser();
+		pB = new Parser();
+	}
+	boolean couldBeNumber(String a){
+		if (a == null || a.length() == 0)
+			return false;
+		char c = a.charAt(0);
+		if (c == '0')
+			return true;
+		else if (c == '1')
+			return true;
+		else if (c == '2')
+			return true;
+		else if (c == '3')
+			return true;
+		else if (c == '4')
+			return true;
+		else if (c == '5')
+			return true;
+		else if (c == '6')
+			return true;
+		else if (c == '7')
+			return true;
+		else if (c == '8')
+			return true;
+		else if (c == '9')
+			return true;
+		else if (c == '.')
+			return true;
+		else if (c == '-')
+			return true;
+		return false;
+	}
+	public int compare(String a, String b){
+		pA.setString(a);
+		pB.setString(b);
+
+		if (couldBeNumber(a) && couldBeNumber(b)){
+			double dA = MesquiteDouble.fromString(pA);
+			double dB = MesquiteDouble.fromString(pB);
+			if (MesquiteDouble.isCombinable(dA) && MesquiteDouble.isCombinable(dB)){
+				if (dA < dB)
+					return -1;
+				else if (dA == dB)
+					return 0;
+				else
+					return 1;
+			}
+		}
+		return collator.compare(a,b);
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteColorTable.java b/Source/mesquite/lib/MesquiteColorTable.java
new file mode 100644
index 0000000..a11769e
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteColorTable.java
@@ -0,0 +1,493 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** This establishes and curates color tables for character states for use in shading etc.
+Eventually facilitities should be provided for changing the colors, and distinct tables for categorical and continuous
+states, and perhaps even distinct tables could be allowed at each character*/
+public  class MesquiteColorTable  {
+	public static final int maxNumStates = 64;
+	public static final int DEFAULT = -1;
+	public static final int GRAYSCALE = 0;
+	public static final int COLORS = 1;
+	public static final int COLORS_NO_BW = 2;
+	public static final int BIGCOLORS = 3;
+	public static final int GREENSCALE = 4;
+	public static final int BLUESCALE = 5;
+	public static final int REDSCALE = 6;
+	public static final int ORANGESCALE = 7;
+	public static final int PURPLESCALE = 8;
+	public static MesquiteColorTable DEFAULTGRAYTABLE = null;
+	public static MesquiteColorTable DEFAULTCOLORTABLE = null;
+	public static MesquiteColorTable DEFAULTREDTABLE = null;
+	public static MesquiteColorTable DEFAULTGREENTABLE = null;
+	public static MesquiteColorTable DEFAULTBLUETABLE = null;
+	public static MesquiteColorTable DEFAULTORANGETABLE = null;
+	public static MesquiteColorTable DEFAULTPURPLETABLE = null;
+	private static Color[][] defaultColorTable = null;
+	private static Color[] defaultBIGColorTable = null;
+	private static Color[][] defaultGrayTable = null;
+	private static Color[][] defaultGreenTable = null;
+	private static Color[][] defaultOrangeTable = null;
+	private static Color[][] defaultPurpleTable = null;
+	private static Color[][] defaultBlueTable = null;
+	private static Color[][] defaultRedTable = null;
+	private Color[][] colorTable;
+	private int mode = COLORS;
+	private boolean setColorDisabled = false;
+	static {
+		defaultColorTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultColorTable[i][j] = Color.white;
+			}
+		}
+		
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultColorTable[maxState][0] = Color.white;
+			defaultColorTable[maxState][maxState] = Color.black;
+			for (int theState=1; theState<maxState; theState++) {
+				int adjust = 0;
+				if (maxState>4) adjust=1;
+				defaultColorTable[maxState][theState] = new Color(Color.HSBtoRGB((float)((maxState-theState-adjust) * 0.8 /maxState),(float)1.0,(float)1.0));
+				//defaultColorTable[maxState][theState] = new Color(Color.HSBtoRGB((float)(theState * 0.8 /maxState),(float)1.0,(float)1.0));
+			}
+			if (maxState==9 || maxState == 8) {
+				defaultColorTable[maxState][4] = new Color(Color.HSBtoRGB((float)((3) * 0.8 /maxState),(float)0.7,(float)0.7));
+			} else if (maxState==7) {
+				defaultColorTable[maxState][4] = new Color(Color.HSBtoRGB((float)(0.17),(float)1.0,(float)1.0));
+			}  else if (maxState==6) {
+				defaultColorTable[maxState][3] = new Color(Color.HSBtoRGB((float)(0.17),(float)1.0,(float)1.0));
+			}  else if (maxState==4) {
+				defaultColorTable[maxState][3] = new Color(Color.HSBtoRGB((float)(0.17),(float)1.0,(float)1.0));
+			}
+
+		}
+		DEFAULTCOLORTABLE = new MesquiteColorTable();
+		DEFAULTCOLORTABLE.colorTable = defaultColorTable;
+		defaultBIGColorTable = new Color[1000];
+		//defaultBIGColorTable[0] = Color.white;
+		//defaultBIGColorTable[999] = Color.black;
+		for (int theState=0; theState<1000; theState++) {
+			defaultBIGColorTable[theState] = new Color(Color.HSBtoRGB((float)((1000-theState) * 0.8 /1000),(float)1.0,(float)1.0));
+		}
+
+		defaultGrayTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultGrayTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultGrayTable[maxState][0] = Color.white;
+			defaultGrayTable[maxState][maxState] = Color.black;
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)((maxState-theState) * 1.0 /maxState);
+				defaultGrayTable[maxState][theState] = new Color(c,c,c);
+			}
+		}
+		DEFAULTGRAYTABLE = new MesquiteColorTable();
+		DEFAULTGRAYTABLE.colorTable = defaultGrayTable;
+		
+		defaultGreenTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultGreenTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultGreenTable[maxState][0] = Color.white;
+			defaultGreenTable[maxState][maxState] = new Color(0, 200, 0);
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)((maxState-theState) * 1.0 /maxState);
+				defaultGreenTable[maxState][theState] = new Color(c, 1, c);
+			}
+		}
+		DEFAULTGREENTABLE = new MesquiteColorTable();
+		DEFAULTGREENTABLE.colorTable = defaultGreenTable;
+
+		defaultOrangeTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultOrangeTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultOrangeTable[maxState][0] = Color.white;
+			defaultOrangeTable[maxState][maxState] = Color.black;
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)(((maxState-theState) * 0.5 /maxState)+0.5);
+				defaultOrangeTable[maxState][theState] = new Color(1, c, 0);
+			}
+		}
+		DEFAULTORANGETABLE = new MesquiteColorTable();
+		DEFAULTORANGETABLE.colorTable = defaultOrangeTable;
+
+		defaultPurpleTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultPurpleTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultPurpleTable[maxState][0] = Color.white;
+			defaultPurpleTable[maxState][maxState] = Color.black;
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)(((maxState-theState) * 0.3 /maxState)+0.7);
+				float c2 = (float)(((maxState-theState) * 0.5 /maxState)+0.5);
+				defaultPurpleTable[maxState][theState] = new Color(c, c2, c);
+			}
+		}
+		DEFAULTPURPLETABLE = new MesquiteColorTable();
+		DEFAULTPURPLETABLE.colorTable = defaultPurpleTable;
+
+		defaultBlueTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultBlueTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultBlueTable[maxState][0] = Color.white;     
+			defaultBlueTable[maxState][maxState] = new Color(0, 0, 200);
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)((maxState-theState) * 1.0 /maxState);
+				defaultBlueTable[maxState][theState] = new Color(c, c, 1);
+			}
+		}
+		DEFAULTBLUETABLE = new MesquiteColorTable();
+		DEFAULTBLUETABLE.colorTable = defaultBlueTable;
+
+		defaultRedTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				defaultRedTable[i][j] = Color.white;
+			}
+		}
+		for (int maxState=1; maxState<maxNumStates; maxState++) {
+			defaultRedTable[maxState][0] = Color.white;
+			defaultRedTable[maxState][maxState] = new Color(200, 0, 0);
+			for (int theState=1; theState<maxState; theState++) {
+				float c = (float)((maxState-theState) * 1.0 /maxState);
+				defaultRedTable[maxState][theState] = new Color(1, c, c);
+			}
+		}
+		DEFAULTREDTABLE = new MesquiteColorTable();
+		DEFAULTREDTABLE.colorTable = defaultRedTable;
+
+	}
+	public MesquiteColorTable() {
+		colorTable = new Color[maxNumStates][maxNumStates];
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				colorTable[i][j] = defaultColorTable[i][j];
+			}
+		}
+	}
+	
+	public MesquiteColorTable cloneColorTable(){
+		MesquiteColorTable table = new MesquiteColorTable();
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				table.colorTable[i][j] = colorTable[i][j];
+			}
+		}
+		table.mode = mode;
+		return table;
+	}
+	public void setToClone(MesquiteColorTable table){
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				colorTable[i][j] = table.colorTable[i][j];
+			}
+		}
+		mode = table.mode;
+	}
+	/**sets whether to use grayscale or color*/
+	public void setMode(int mode){
+		this.mode = mode;
+	}
+	/**gets whether to use grayscale or color*/
+	public int getMode(){
+		return mode;
+	}
+	/**resets to default mode*/
+	public void resetDefaultMode(){
+		mode = COLORS;
+	}
+	/**resets to default mode*/
+	public void resetToDefaults(){
+		resetDefaultMode();
+		for (int i=0; i<maxNumStates; i++) {
+			for (int j=0; j<maxNumStates; j++) {
+				colorTable[i][j] = defaultColorTable[i][j];
+			}
+		}
+	}
+	
+	double[] bins;
+	public double[] getPreferredBinBoundaries(){  //appropriate only for ContColorTable!
+		return bins;
+	}
+	public void setPreferredBinBoundaries(double[] b){  //appropriate only for ContColorTable!
+		bins = b;
+	}
+	
+	/** gets color for state i with given maximum state possible, from default color table*/
+	public static Color getDefaultColor(int maxState, int i, int mode) {
+		if (maxState<0 || i<0)
+			return Color.white;
+		else if (mode == GRAYSCALE){
+			if ((maxState)<defaultGrayTable.length && (i)<defaultGrayTable[0].length)
+				return defaultGrayTable[maxState][i];
+			else
+				return defaultGrayTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == GREENSCALE){
+			if ((maxState)<defaultGreenTable.length && (i)<defaultGreenTable[0].length)
+				return defaultGreenTable[maxState][i];
+			else
+				return defaultGreenTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == ORANGESCALE){
+			if ((maxState)<defaultOrangeTable.length && (i)<defaultOrangeTable[0].length)
+				return defaultOrangeTable[maxState][i];
+			else
+				return defaultOrangeTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == PURPLESCALE){
+			if ((maxState)<defaultPurpleTable.length && (i)<defaultPurpleTable[0].length)
+				return defaultPurpleTable[maxState][i];
+			else
+				return defaultPurpleTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == BLUESCALE){
+			if ((maxState)<defaultBlueTable.length && (i)<defaultBlueTable[0].length)
+				return defaultBlueTable[maxState][i];
+			else
+				return defaultBlueTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == REDSCALE){
+			if ((maxState)<defaultRedTable.length && (i)<defaultRedTable[0].length)
+				return defaultRedTable[maxState][i];
+			else
+				return defaultRedTable[maxNumStates-1][maxNumStates-1];
+			
+		}
+		else if (mode == COLORS_NO_BW && (maxState+2)<defaultColorTable.length && (i+1)<defaultColorTable[0].length)
+			return defaultColorTable[maxState+2][i+1]; //TODO: guard that in bounds!
+		else if ((maxState)<defaultColorTable.length && (i)<defaultColorTable[0].length)
+			return defaultColorTable[maxState][i];
+		else 
+			return defaultColorTable[maxNumStates-1][maxNumStates-1];
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** sets color in color table */
+	public void disableSetColor(boolean setColorDisabled) {
+		this.setColorDisabled = setColorDisabled;
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** sets color in color table */
+	public boolean setColorEnabled() {
+		return !setColorDisabled;
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** sets color in color table */
+	public void setColor(int maxState, int i, Color color) {
+		if (colorTable!=null){
+			 if (mode == COLORS_NO_BW) {
+				 if ((maxState+2)<colorTable.length && (i+1)<colorTable[0].length)
+					 colorTable[maxState+2][i+1] = color;
+			 }
+			 else
+				 colorTable[maxState][i] = color;
+	}
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** gets color for state i with given maximum state possible, from color table*/
+	public Color getColorDirect(int maxState, int i) {
+		if (maxState<0 || i<0)
+			return Color.white;
+		if (colorTable == null)
+			return null;
+		 if (mode == COLORS_NO_BW && (maxState+2)<colorTable.length && (i+1)<colorTable[0].length){
+			return colorTable[maxState+2][i+1]; 
+	}
+
+		return colorTable[maxState][i];
+
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** gets color for state i with given maximum state possible, from color table*/
+	public Color getColor(int maxState, int i) {
+		if (maxState<0 || i<0)
+			return Color.white;
+		Color[][] usedColorTable = colorTable;
+		if (colorTable == null)
+			usedColorTable = defaultColorTable;
+
+		if (mode == GRAYSCALE){
+			return getGrayScale(i, 0, maxState);
+		}
+		else if (mode == COLORS_NO_BW && (maxState+2)<usedColorTable.length && (i+1)<usedColorTable[0].length){
+				return usedColorTable[maxState+2][i+1]; 
+		}
+		else if ((maxState)<usedColorTable.length && (i)<usedColorTable[0].length){
+				return usedColorTable[maxState][i];
+		}
+		else 
+				return usedColorTable[maxNumStates-1][maxNumStates-1];
+		
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** gets color for double d given range*/
+	public Color getColor(double state, double min, double max) {
+		if (state>= min && state <= max && min !=max) {
+			if (mode == GRAYSCALE){
+				return getGrayScale(state, min, max);
+			}
+			int i =(int)(1000*(state-min)/(max-min));
+			if (i==1000)
+				i=999;
+			return defaultBIGColorTable[i];
+		}
+		else
+			return Color.white;
+	}
+	/*--------------------------------------------------------------------------------------------------------------*/
+	/** gets green value for double "state" given range*/
+	public static Color getGreenScale(double state, double min, double max, boolean log, int power) {
+		if (state>= min && state <= max && min !=max) {
+			double fraction = (state-min)/(max-min);   // the fraction, with 1 being black, 0 white
+			if (power>1) {
+				double origFraction=fraction;
+				for (int i = 1; i<=3; i++) {
+					fraction= fraction*origFraction;
+				}
+			}
+			if (log) {
+				fraction = (Math.exp(fraction)-1)/(Math.exp(1)-1);   
+			}
+			fraction = 1.0-fraction;   // the fraction, with 0 being black, 1 white
+			return new Color((float)fraction, (float)1, (float)fraction);
+		}
+		else
+			return Color.white;
+	}
+	public static Color getGreenScale(double state, double min, double max, boolean log) {
+		return getGreenScale(state,min,max,log,1);
+	}
+	/** gets green value for double "state" given range*/
+	public static Color getYellowScale(double state, double min, double max, boolean log, int power) {
+		if (state>= min && state <= max && min !=max) {
+			double fraction = (state-min)/(max-min);   // the fraction, with 1 being black, 0 white
+			if (power>1) {
+				double origFraction=fraction;
+				for (int i = 1; i<=3; i++) {
+					fraction= fraction*origFraction;
+				}
+			}
+			if (log) {
+				fraction = (Math.exp(fraction)-1)/(Math.exp(1)-1);   
+			}
+			fraction = 1.0-fraction;   // the fraction, with 0 being black, 1 white
+			return new Color((float)1, (float)1, (float)fraction);
+		}
+		else
+			return Color.white;
+	}
+	public static Color getYellowScale(double state, double min, double max, boolean log) {
+		return getYellowScale(state,min,max,log,1);
+	}
+	/** gets red value for double "state" given range*/
+	public static Color getRedScale(double state, double min, double max, boolean log, int power) {
+		if (state>= min && state <= max && min !=max) {
+			double fraction = (state-min)/(max-min);   // the fraction, with 1 being black, 0 white
+			if (power>1) {
+				double origFraction=fraction;
+				for (int i = 1; i<=3; i++) {
+					fraction= fraction*origFraction;
+				}
+			}
+			if (log) {
+				fraction = (Math.exp(fraction)-1)/(Math.exp(1)-1);   
+			}
+			fraction = 1.0-fraction;   // the fraction, with 0 being black, 1 white
+			return new Color((float)1, (float)fraction, (float)fraction);
+		}
+		else
+			return Color.white;
+	}
+	public static Color getRedScale(double state, double min, double max, boolean log) {
+		return getRedScale(state,min,max,log,1);
+	}
+	/** gets blue value for double "state" given range*/
+	public static Color getBlueScale(double state, double min, double max, boolean log, int power) {
+		if (state>= min && state <= max && min !=max) {
+			double fraction = (state-min)/(max-min);   // the fraction, with 1 being black, 0 white
+			if (power>1) {
+				double origFraction=fraction;
+				for (int i = 1; i<=3; i++) {
+					fraction= fraction*origFraction;
+				}
+			}
+			if (log) {
+				fraction = (Math.exp(fraction)-1)/(Math.exp(1)-1);   
+			}
+			fraction = 1.0-fraction;   // the fraction, with 0 being black, 1 white
+			return new Color((float)fraction, (float)fraction, (float)1);
+		}
+		else
+			return Color.white;
+	}
+	public static Color getBlueScale(double state, double min, double max, boolean log) {
+		return getBlueScale(state,min,max,log,1);
+	}
+	/** gets gray value for double "state" given range*/
+	public static Color getGrayScale(double state, double min, double max, boolean log, int power) {
+		if (state>= min && state <= max && min !=max) {
+			double fraction = (state-min)/(max-min);   // the fraction, with 1 being black, 0 white
+			if (power>1) {
+				double origFraction=fraction;
+				for (int i = 1; i<=3; i++) {
+					fraction= fraction*origFraction;
+				}
+			}
+			if (log) {
+				fraction = (Math.exp(fraction)-1)/(Math.exp(1)-1);   
+			}
+			fraction = 1.0-fraction;   // the fraction, with 0 being black, 1 white
+			return new Color((float)fraction, (float)fraction, (float)fraction);
+		}
+		else
+			return Color.white;
+	}
+	public static Color getGrayScale(double state, double min, double max, boolean log) {
+		return getGrayScale(state,min,max,log,1);
+	}
+	public static Color getGrayScale(double state, double min, double max) {
+		return getGrayScale(state,min,max,false,1);
+	}
+
+}
+
diff --git a/Source/mesquite/lib/MesquiteCommand.java b/Source/mesquite/lib/MesquiteCommand.java
new file mode 100644
index 0000000..5b7e2bf
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteCommand.java
@@ -0,0 +1,356 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/*====================== Mesquite command.  ======================*/
+/** Each MesquiteCommand object stores a single sort of command that can be made, including its name
+(e.g. "setEdgeWidth") and the Commandable object to which the command is to be sent (e.g., an instantiation
+of a module).  To be commandable, objects must claim to implement the Commandable
+interface. These MesquiteCommands are currently
+used mostly with Menus and Buttons, and with scripting.  For instance, to each menu item is attached a command, and when the menu item is selected, the
+command is executed.  By "executing" the command, we mean that the command's doIt method is called, which in turn calls
+the doCommand method of the Commandable object to which the command applies.
+*/
+public class MesquiteCommand  implements Listable, MesquiteListener {
+	private String commandName;
+	private Commandable ownerObject;  
+	String defaultArguments = null;
+	boolean disposed = false;
+	boolean letMe = true;
+	public static ListableVector currentThreads;
+	boolean bypassQueue = false;
+	boolean hideInList = false; 
+	boolean suppressLogging = false;
+	public static boolean logEverything = false;
+	boolean dontDuplicate = false; //if true then the same command on to the same object will not be put on the queue more than once
+	//to find memory leaks
+	public static int totalCreated =0;
+	public int ID = 0;
+	public static int totalFinalized =0;
+	public static int totalDisposed =0;
+	public static Vector classesLinked, classesUnlinked, countsOfClasses; //to detect memory leaks
+	private Logger logger = null;
+	private Logger supplementalLogger = null;
+	
+	static {
+		currentThreads = new ListableVector(10);
+		if (MesquiteTrunk.checkMemory) {
+			classesLinked = new Vector();
+			classesUnlinked = new Vector();
+			countsOfClasses = new Vector();
+		}
+	}
+	public MesquiteCommand(String commandName,  Commandable ownerObject) {
+		this(commandName, null, ownerObject);
+	}
+	public MesquiteCommand(String commandName,  String defaultArguments, Commandable ownerObject) {
+		this.commandName = commandName;
+		this.ownerObject = ownerObject;
+		this.defaultArguments = defaultArguments;
+		if (ownerObject!=null && MesquiteTrunk.checkMemory){
+			if (classesLinked.indexOf(ownerObject.getClass())<0) {
+				classesLinked.addElement(ownerObject.getClass());
+				countsOfClasses.addElement(new MesquiteInteger(1));
+			}
+			else {
+				MesquiteInteger c = (MesquiteInteger)countsOfClasses.elementAt(classesLinked.indexOf(ownerObject.getClass()));
+				if (c!=null)
+					c.increment();
+			}
+		}
+		totalCreated++;
+		ID = totalCreated;
+	}
+	
+	public int getID() {
+		return ID;
+	}
+	public void setSupplementalLogger(Logger logger){
+		this.supplementalLogger = logger;
+	}
+	public Logger getSupplementalLogger(){
+		return supplementalLogger;
+	}
+
+	public void setLogger(Logger logger){
+		this.logger = logger;
+	}
+	
+	public void notifyDoing(String s){
+		if (logger !=null)
+			logger.logln("Doing command " + commandName + " (" + s + ")");
+	}
+	public void notifyDone(String s){
+		if (logger !=null)
+			logger.logln("Done command " + commandName + " (" + s + ")");
+	}
+	public static void stampLog(Object ownerObject, String commandName, String arguments, boolean separateThread){
+		String logString = " > " + commandName;
+		if (arguments!=null && !arguments.equals(""))
+			logString +=  " \"" + arguments + "\"";
+		if (ownerObject instanceof Listable)
+			logString = ((Listable)ownerObject).getName() + logString;
+		else
+			logString = "[" + ownerObject.getClass().getName() + "]"  + logString;
+		if (separateThread)
+			logString += " -- on separate thread ";
+			
+		/*
+		if (ownerObject instanceof Logger)
+			((Logger)ownerObject).logln(logString);
+		else*/
+			MesquiteModule.mesquiteTrunk.logln(logString);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  *
+	public Object doIt(String arguments) {
+		return doIt(arguments, null);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public Object doIt(String arguments) {
+		if (disposed)
+			return null;
+		if (ownerObject == null) {
+			MesquiteMessage.warnProgrammer("Warning: Command given to null object (" + commandName + "  " + arguments + ") MesquiteCommand");
+			return null;
+		}
+		if (StringUtil.blank(arguments))
+			arguments = defaultArguments;
+		if (!suppressLogging || logEverything)
+			stampLog(ownerObject, commandName, arguments, false);
+		CommandRecord previous = MesquiteThread.getCurrentCommandRecord();
+		CommandRecord record =  new CommandRecord(false);
+		MesquiteThread.setCurrentCommandRecord(record);
+		if (!suppressLogging)
+			MesquiteWindow.tickClock("Command: " + getName());
+		Object returned = ownerObject.doCommand(commandName, arguments,CommandChecker.defaultChecker);  //if a command is executed in this way, assumed that not scripting
+		if (!suppressLogging)
+			MesquiteWindow.hideClock();
+		if (ownerObject instanceof FileDirtier)
+			((FileDirtier)ownerObject).fileDirtiedByCommand(this);
+		ProgressIndicator pi = record.getProgressIndicator();
+		if (pi !=null)
+			pi.goAway();
+		MesquiteThread.setCurrentCommandRecord(previous);
+		return returned;
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public void doItNewThread(String arguments, String uiCallInformation) {
+		doItNewThread(arguments, uiCallInformation, true, true);
+	}
+	
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public void doItNewThread(String arguments, String uiCallInformation, boolean showWaitCursors, boolean logCommand) {
+		if (bypassQueue) {
+			doIt(arguments);
+			return;
+		}
+		if (StringUtil.blank(arguments))
+			arguments = defaultArguments;
+		if (false && CommandThread.waitCursorDepth==0 && showWaitCursors){
+			MesquiteWindow.setAllWaitCursors();
+		}
+		if ((logCommand && !suppressLogging) && logEverything)
+			stampLog(ownerObject, commandName, arguments, true);
+		CommandThread thread = new CommandThread(this, arguments, uiCallInformation, false && showWaitCursors, logCommand && !suppressLogging);
+		currentThreads.addElement(thread, false);
+		thread.start();
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public void doItMainThread(String arguments, String uiCallInformation, Object c) {
+		doItMainThread(arguments, uiCallInformation, c, false);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public void doItMainThread(String arguments, String uiCallInformation, Object c, boolean useWizard) {
+		doItMainThread(arguments, uiCallInformation, true, true, c, useWizard);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  */
+	public void doItMainThread(String arguments, String uiCallInformation, boolean showWaitCursors, boolean logCommand) {
+		doItMainThread(arguments, uiCallInformation, showWaitCursors, logCommand, null);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  Object passed is UI object (if any), such as menu item or button in window, from which command was issued*/
+	public void doItMainThread(String arguments, String uiCallInformation, boolean showWaitCursors, boolean logCommand, Object c) {
+		doItMainThread(arguments, uiCallInformation, showWaitCursors, logCommand, c, false);
+	}
+	/** Do the command, passing the given arguments.  This will call the commanded object's doCommand method.  Object passed is UI object (if any), such as menu item or button in window, from which command was issued*/
+	public void doItMainThread(String arguments, String uiCallInformation, boolean showWaitCursors, boolean logCommand, Object c, boolean useWizard) {
+		if (dontDuplicate && MainThread.commandAlreadyOnQueue(this))
+			return;
+		if (bypassQueue) {
+			doIt(arguments);
+			return;
+		}
+		if (ownerObject == null)
+			MesquiteMessage.printStackTrace("doItMainThread with null target Object " + commandName);
+		if (disposed)
+			MesquiteMessage.printStackTrace("doItMainThread in disposed MesquiteCommand " + commandName + " " + ownerObject);
+		if (StringUtil.blank(arguments))
+			arguments = defaultArguments;
+		PendingCommand thread = new PendingCommand(this, arguments, uiCallInformation, false && showWaitCursors, logCommand && !suppressLogging);
+		thread.setUseWizard(useWizard);
+		MainThread.pendingCommands.addElement(thread, false);
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		CommandRecord.tick("");
+		if (obj instanceof CommandRecord && caller instanceof CommandThread && Notification.getCode(notification) == MesquiteListener.COMMAND_CANCELLED){
+			String s = ((CommandThread)caller).getListName();
+			((Listened)caller).removeListener(this);
+			MesquiteTrunk.mesquiteTrunk.alert("A command was cancelled or failed to complete its execution (command: \"" + s + "\").  It is possible that some calculations will remain incomplete, and that other error messages will be shown.");
+			((Thread)caller).interrupt();
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){return true;}
+	/** returns the command name */
+	public String getName() {
+		return commandName;
+	}
+	boolean watchD = false;
+	public void watchDisposal(boolean wd) {
+		//for debugging;
+		watchD = wd;
+	}
+	/** disposes of this command by setting the commanded object to null */
+	public void dispose() {
+		if (watchD)
+			MesquiteMessage.printStackTrace("DISPOSED " + ID);
+		if (disposed)
+			return;
+		disposed = true;
+		if (ownerObject!=null && MesquiteTrunk.checkMemory)
+			if (classesUnlinked.indexOf(ownerObject.getClass())<0)
+				classesUnlinked.addElement(ownerObject.getClass());
+		ownerObject=null;
+		totalDisposed++;
+	}
+	/** to track memory leaks */
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	/** returns the object to be commanded */
+	public Commandable getOwner() {
+		return ownerObject;
+	}
+	/** sets the object to be commanded */
+	public void setOwner(Commandable obj) {
+		ownerObject = obj;
+	}
+	/** sets the name of the command */
+	public void setCommandName(String name) {
+		commandName = name;
+	}
+	/** sets the default arguments to be passed if argument is null */
+	public MesquiteCommand setDefaultArguments(String defaultArgs) {
+		defaultArguments = defaultArgs;
+		return this;
+	}
+	/** returns the default arguments to be passed if argument is null */
+	public String getDefaultArguments() {
+		return defaultArguments ;
+	}
+	/** sets whether the command is to be let finish (i.e. a warning is give on quit if pending) */
+	public void setLetMeFinish(boolean letMe) {
+		this.letMe = letMe;
+	}
+	/** gets whether the command is to be let finish (i.e. a warning is give on quit if pending) */
+	public boolean getLetMeFinish() {
+		return letMe;
+	}
+	/** sets whether the command is to bypass the command queue (e.g., for force quit) */
+	public void setQueueBypass(boolean bypass) {
+		bypassQueue = bypass;
+	}
+	/** sets whether the command is to be suppressed from the command queue if there is already the same command to the same object there*/
+	public void setDontDuplicate(boolean dd) {
+		dontDuplicate = dd;
+	}
+	/** sets whether the command is to be shown in the log when given by user interface command*/
+	public void setSuppressLogging(boolean dd) {
+		suppressLogging = dd;
+	}
+	/** gets whether the command is to be shown in the log when given by user interface command*/
+	public boolean getSuppressLogging() {
+		return suppressLogging;
+	}
+	/** Deletes pending references to this command on main queue*/
+	public void deleteOnQueue() {
+		MainThread.deleteCommand(this);
+	}
+	/** returns whether there are any commands in the command queue */
+	public static boolean anyQueuedCommands(boolean countCommandsWithoutLetMeFinish) {
+		if (countCommandsWithoutLetMeFinish)
+			return MainThread.pendingCommands.size()>0;
+		else {
+			for (int i=0;i<MainThread.pendingCommands.size(); i++){
+				PendingCommand ct = (PendingCommand)MainThread.pendingCommands.elementAt(i);
+				MesquiteCommand c = ct.getCommand();
+				if (c.letMe)
+					return true;
+			}
+			return false;
+		}
+	}
+	/** returns whether there are any commands in the command queue that have crashed*/
+	public static boolean anyCrashedCommands() {
+			for (int i=0;i<currentThreads.size(); i++){
+				CommandThread ct = (CommandThread)currentThreads.elementAt(i);
+				MesquiteCommand c = ct.getCommand();
+				if (ct.hasCrashed())
+					return true;
+			}
+			return false;
+	}
+	/** returns list of commands */
+	public static String commandList() {
+		return MainThread.pendingCommands.getList();
+	}
+	
+	/** deletes other commands as specified */
+	public static void deleteSpecifiedCommands(int numToLeave, long idLimit, Commandable owner, String commandName) {
+		if (numToLeave<0)
+			return;
+		int count =0;
+		for (int i=0;i<MainThread.pendingCommands.size(); i++){  // first count them
+			PendingCommand ct = (PendingCommand)MainThread.pendingCommands.elementAt(i);
+			MesquiteCommand c = ct.getCommand();
+			if (MainThread.currentlyExecuting!=ct && c.getName().equals(commandName) && c.getOwner()==owner && ct.getID()<=idLimit){
+				count++;		
+			}		
+		}
+		
+		for (int i=MainThread.pendingCommands.size()-1;i>=0; i--){  // now delete them
+			PendingCommand ct = (PendingCommand)MainThread.pendingCommands.elementAt(i);
+			MesquiteCommand c = ct.getCommand();
+			if (MainThread.currentlyExecuting!=ct && c.getName().equals(commandName) && c.getOwner()==owner && ct.getID()<=idLimit){
+				if (count>numToLeave) {
+					MainThread.pendingCommands.removeElement(ct, false);
+				}
+				count--;		
+			}		
+		}
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/MesquiteCursor.java b/Source/mesquite/lib/MesquiteCursor.java
new file mode 100644
index 0000000..f2263a4
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteCursor.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls*/
+/* ======================================================================== */
+/** A tool (i.e. cursor) that can be active and used on items on the screen.*/
+public class MesquiteCursor {
+	protected String  name; 
+	protected String imageDirectoryPath;
+	protected String imageFileName;
+	protected Cursor cursor;
+	Point hotSpot;
+	Image cursorImage = null;
+	
+	public MesquiteCursor (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY) {
+		if (initiator !=null)
+			this.name = initiator.getClass().getName() + "." + name;
+		else
+			this.name = name;
+		this.imageDirectoryPath = imageDirectoryPath;
+		this.imageFileName = imageFileName;
+		hotSpot = new Point(hotX, hotY);
+	}
+	
+	public void setCursorImage(Image i){
+		cursorImage = i;
+	}
+	public Image getCursorImage(){
+		return cursorImage;
+	}
+	public String getName(){
+		return name;
+	}
+	public void setHotSpot(int x, int y){
+		hotSpot.x = x;
+		hotSpot.y = y;
+	}
+	public Point getHotSpot(){
+		return hotSpot;
+	}
+	/*.................................................................................................................*/
+	public Cursor getCursor(){  
+		if (MesquiteFile.fileExists(getImagePath())){
+			Image im = getCursorImage();
+			if (im == null){
+				Dimension best = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
+				if ((best.width>16 || best.height>16) && MesquiteFile.fileExists(getSizedImagePath(best.width))){
+					im = MesquiteImage.getImage(getSizedImagePath(best.width));
+					if (im == null)
+						im = MesquiteImage.getImage(getImagePath());
+				}
+				else 
+					im = MesquiteImage.getImage(getImagePath());
+				setCursorImage(im);
+			}
+			if (!MesquiteImage.waitForImageToLoad(im)) {
+				MesquiteMessage.println("Note: image of cursor of tool not obtained: " + getName() + "  " + getImagePath());
+				return Cursor.getDefaultCursor();
+			}
+			
+			Cursor c = Toolkit.getDefaultToolkit().createCustomCursor(im, getHotSpot(), getName());
+			return c;
+		}
+		return Cursor.getDefaultCursor();
+	}
+	public String getImagePath(){
+		return imageDirectoryPath + imageFileName;
+	}
+	public void setImageFileName(String name){
+		imageFileName = name;
+		cursorImage = null; // to force reloading
+	}
+	/*.................................................................................................................*/
+	public String getSizedImagePath(int s){
+		return imageDirectoryPath + s + imageFileName;
+	}
+	
+}
diff --git a/Source/mesquite/lib/MesquiteDialog.java b/Source/mesquite/lib/MesquiteDialog.java
new file mode 100644
index 0000000..b6980b6
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDialog.java
@@ -0,0 +1,934 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Vector;
+
+/* =============================================== */
+/** A dialog box */
+public abstract class MesquiteDialog implements Commandable, Listable, ComponentListener, KeyListener, MouseListener {
+	static Vector dialogListeners = new Vector();
+	static int numCreated = 0;
+
+	int id = 0;
+
+	boolean alreadyDisposed = false;
+
+	protected String defaultButtonString = null;
+
+	int savedX = 0;
+
+	int savedY = 0;
+
+	public int tickled = 0;
+
+	boolean autoDispose = true;
+	String title;
+
+	Thread thread;
+
+	boolean holdsConsoleFocus = false;
+	protected MesquiteDialogParent parentDialog;
+	MDPanel outerContents;
+
+	public static boolean responsePending = false;  //is there currently a dialog with response pending?
+
+	public static boolean useWizards = false;  //enable wizards in general
+	boolean usingWizard = false;
+	boolean waitingOnButtonPush = false;
+	public static final int wizardWidth = 700;
+	public static final int wizardHeight = 500;
+	public static MesquiteDialogParent currentWizard;
+
+	public MesquiteDialog(Object parent, String title) {
+		this(parent, title, false);
+	}
+	public MesquiteDialog(Object parent, String title, boolean suppressWizardIfFirst) {
+		//super(MesquiteWindow.dialogAnchor, title, true);
+		numCreated++;
+		id = numCreated;
+		this.title = title;
+		CommandRecord rec = CommandRecord.getRecDIfNull();
+		parentDialog = rec.getWizard();
+		if (parentDialog ==null) {
+			if (currentWizard== null && !suppressWizardIfFirst && rec.establishWizard()){
+				usingWizard = true;
+			}
+			Frame f = MesquiteWindow.dialogAnchor;
+			if (parent != null){
+				if (parent instanceof Frame)
+					f = (Frame)parent;
+				else if (parent instanceof MesquiteWindow){
+					MesquiteWindow mw = ((MesquiteWindow)parent);
+					if (!mw.isVisible() && mw.getOwnerModule() != null)
+						mw = mw.getOwnerModule().visibleContainerOfModule();
+					if (mw == null)
+						f = MesquiteWindow.dialogAnchor;
+					else
+						f = mw.getParentFrame();
+				}
+			}
+
+			parentDialog = new MesquiteDialogParent(f, title, !usingWizard);
+			//parentDialog = new MesquiteDialogParent(MesquiteWindow.dialogAnchor, title, !usingWizard);
+			MesquiteWindow.numDialogs++;
+			if (!usingWizard)
+				MesquiteWindow.numNonWizardDialogs++;
+			if (MesquiteModule.mesquiteTrunk.dialogVector != null)
+				MesquiteModule.mesquiteTrunk.dialogVector.addElement(this, false);
+			if (usingWizard){
+				rec.setWizard(parentDialog);
+				rec.requestEstablishWizard(false);
+				parentDialog.setSize(wizardWidth, wizardHeight);
+				parentDialog.setAsWizard();
+
+			}
+		}
+		else {
+			usingWizard = true;
+
+		}
+
+		setTitle(title);
+		outerContents = new MDPanel(usingWizard);
+		outerContents.setForeground(Color.black);
+		outerContents.addComponentListener(this);
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+		//	setBackground(ColorTheme.getInterfaceBackground());
+		outerContents.setCursor(Cursor.getDefaultCursor());
+		parentDialog.add(this);
+
+
+
+		if (!usingWizard)
+			MainThread.incrementSuppressWaitWindow();
+		alreadyDisposed = false;
+		// MesquiteWindow.dialogAnchor.toFront();
+
+	}
+	public static void closeWizard(){
+		if (MesquiteDialog.currentWizard != null)
+			MesquiteDialog.currentWizard.dispose();
+	}
+	public static void hideWizardForCalculation(){
+		if (currentWizard != null && !MesquiteTrunk.isMacOSX()){
+			currentWizard.hideForCalculation();
+		}
+	}
+	public static void cleanUpWizard(){
+		CommandRecord rec = CommandRecord.getRecDIfNull();
+		rec.requestEstablishWizard(false);
+		MesquiteDialogParent dlog = rec.getWizard();
+		if (dlog != null) {
+			if (dlog.hiddenForCalculation)
+				dlog.setVisible(true);
+			MesquiteDialog currentDialog =dlog.getCurrentDialog();
+			if (currentDialog != null){
+				currentDialog.usingWizard = false;
+				currentDialog.dispose();
+			}
+			else 
+				dlog.pleaseDispose();
+		}
+		rec.setWizard(null);
+
+		MesquiteDialog.currentWizard = null;
+
+	}
+	public boolean isInWizard(){
+		return usingWizard;
+	}
+	public void setInWizard(boolean w){
+		usingWizard = w;
+	}
+
+	public static void addDialogListener(DialogListener dlogL){
+		dialogListeners.addElement(dlogL);
+	}
+	public static void removeDialogListener(DialogListener dlogL){
+		dialogListeners.addElement(dlogL);
+	}
+
+	public void repaintAll(){
+		if (outerContents != null)
+			MesquiteWindow.rpAll(outerContents);
+	}
+	/*=====@@@@@@@@@@@@@@@============*/
+	public Font getFont(){
+		return outerContents.getFont();
+	}
+	public void setFont(Font f){
+		outerContents.setFont(f);
+	}
+	public void setBackground(Color c){
+		outerContents.setBackground(c);
+	}
+	public Color getBackground (){
+		return outerContents.getBackground();
+	}
+	public void add(Component c){
+		outerContents.add(c);
+	}
+	public void add(Component c, String s){
+		outerContents.add(c, s);
+	}
+	public void add(String s, Component c){
+		outerContents.add(s, c);
+	}
+
+	public void setLayout(LayoutManager f){
+		outerContents.setLayout(f);
+	}
+	public void repaint(){
+		outerContents.repaint();
+	}
+	public void doLayout(){
+		outerContents.doLayout();
+	}
+
+	public Graphics getGraphics(){
+		return outerContents.getGraphics();
+	}
+	public Component getOuterContents(){
+		return outerContents;
+	}
+	public Component[] getComponents(){
+		return outerContents.getComponents();
+	}
+	public void setCursor(Cursor c){
+		outerContents.setCursor(c);
+	}
+
+	/*=====@@@@@@@@@@@@@@@============*/
+	public Point getLocation(){
+		return parentDialog.getLocation();
+	}
+	public Rectangle getBounds(){
+		Rectangle bounds = parentDialog.getBounds();
+		return bounds;
+	}
+	public void setDialogLocation(int x, int y) {
+		savedX = x;
+		savedY = y;
+		//		parentDialog.setLocationSet(true);
+		parentDialog.setLocation(x, y);
+	}
+	public void addWindowListener(WindowListener w){
+		parentDialog.addWindowListener(w);
+	}
+	public void setResizable(boolean f){
+		parentDialog.setResizable(f);
+	}
+	public void invalidate(){
+		parentDialog.invalidate();
+	}
+	public void validate(){
+		parentDialog.validate();
+	}
+	public void requestFocus(){
+		parentDialog.pleaseRequestFocus();
+	}
+
+	public void pack(){
+		//	if (!usingWizard)
+		parentDialog.pack();
+	}
+	public Dimension getPreferredSize(boolean contentsOnly){
+		return parentDialog.getPreferredSize(contentsOnly);
+	}
+	public Dimension getPreferredSize(){
+		return parentDialog.getPreferredSize();
+	}
+	public void setDialogSize(Dimension h){
+		parentDialog.setSize(h);
+	}
+	public void setDialogSize(int w, int h){
+		parentDialog.setSize(w,h);
+	}
+	public void setDialogBounds(int x, int y, int w, int h){
+		/*if (usingWizard && parentDialog.isLocationSet()){
+			parentDialog.setSize(w,h);
+			return;
+		}*/
+		parentDialog.setBounds(x, y, w,h);
+	}
+	public void setSize(Dimension h){
+		if (!usingWizard)
+			parentDialog.setSize(h);
+	}
+	public void setSize(int w, int h){
+		if (!usingWizard)
+			parentDialog.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		/*if (usingWizard && parentDialog.isLocationSet()){
+			parentDialog.setSize(w,h);
+			return;
+		}*/
+		if (!usingWizard)
+			parentDialog.setBounds(x, y, w,h);
+	}
+	public void toFront(){
+		parentDialog.pleaseBringToFront();
+	}
+	public MesquiteDialogParent getParentDialog(){
+		return parentDialog;
+	}
+	public Dimension getSize(){
+		return parentDialog.getSize();
+	}
+	public void setTitle(String s){
+		parentDialog.setTitle(s);
+	}
+	public String getTitle(){
+		return parentDialog.getTitle();
+	}
+	/*=====@@@@@@@@@@@@@@@============*/
+	public void showDialog(){
+		setResponsePending(true);
+
+		if (usingWizard){
+			if (!(Thread.currentThread() instanceof MesquiteThread))
+				MesquiteMessage.printStackTrace("Wizard show on non-MT");
+			if (isVisible())
+				toFront();
+
+			else 
+				parentDialog.pleaseShow();  //called so as not to hang this thread (in case a wizard is being used and it needs to return on button hit
+			try {
+
+				if (waitingOnButtonPush)
+
+					MesquiteMessage.printStackTrace("Wizard open waitingOnButtonPush already true");				
+				waitingOnButtonPush = true;
+				while (waitingOnButtonPush){
+					Thread.sleep(20);
+				}
+
+			}
+			catch(InterruptedException e){
+			}
+		}
+		else {
+			parentDialog.setVisible(true);
+
+		}
+
+	}
+	public void hide(){
+		setResponsePending(false);
+
+		if (!usingWizard){
+			parentDialog.hide();
+		}
+		else {
+			//outerContents.setVisible(false);
+			parentDialog.removeDialog(this);
+			waitingOnButtonPush = false;
+		}
+	}
+	public boolean isVisible(){
+		return parentDialog.isVisible();
+	}
+	public void setVisible(boolean vis) {
+		setResponsePending(vis);
+		if (!vis) {
+			waiting = false;
+			if (!usingWizard){
+				parentDialog.setVisible(false);
+			}
+			else {
+				//outerContents.setVisible(false);
+				parentDialog.removeDialog(this);
+				if (!(Thread.currentThread() instanceof MesquiteThread))
+					MesquiteMessage.printStackTrace("Wizard close on non-MT");
+				if (!waitingOnButtonPush)
+
+					MesquiteMessage.printStackTrace("Wizard close waitingOnButtonPush already false");
+				waitingOnButtonPush = false;
+			}
+		}
+		else {
+			if (Thread.currentThread() instanceof ConsoleThread){  //can't set visible on console thread, since then dlog will be hanging on consoleThread and consoleThread can't feed it input
+
+				MDConsoleShowThread t = new MDConsoleShowThread(this);
+				t.start();
+				return;
+			}
+			System.out.println("Dialog box shown.  Title: " + getName());
+			System.out.println("");
+			System.out.println("For console choice use component numbers");
+			showDialogComponents(outerContents, new MesquiteInteger(0), " ", true);
+			ConsoleThread.setConsoleObjectCommanded(this, false, true);
+			holdsConsoleFocus = true;
+			if (!MesquiteWindow.GUIavailable || MesquiteWindow.suppressAllWindows) {
+				if (MesquiteThread.isScripting())
+					return;
+				waitingOnButtonPush = true;
+				try {
+					waiting = true;
+					while (waiting && waitingOnButtonPush)
+						Thread.sleep(20);
+				} catch (InterruptedException e) {
+				}
+				return;
+			}
+
+			// if defaultButtonString flag is non null, then recurse through components setting key listeners
+			if (defaultButtonString != null)
+				setKeyListeners(outerContents);
+			setMouseListeners(outerContents);
+			// pack();
+			thread = Thread.currentThread();
+			for (int i=0; i< dialogListeners.size(); i++){
+				DialogListener dL = (DialogListener)dialogListeners.elementAt(i);
+				dL.dialogShown(this);
+			}
+			showDialog();
+			invalidate();// attempt to workaround bug in Jaguar
+			validate(); // attempt to workaround bug in Jaguar
+			/*
+			 * if (mt instanceof MesquiteThread) { thread = (MesquiteThread)mt; }
+			 */
+			// waitForOtherDialogThreads();
+		}
+
+
+	}
+	private void setResponsePending(boolean p){
+		responsePending = p;
+		if (Thread.currentThread() instanceof MesquiteThread){
+			MesquiteThread thread = (MesquiteThread)Thread.currentThread();
+			if (thread.getProgressIndicator() != null && thread.getProgressIndicator().isVisible()){
+				thread.getProgressIndicator().getProgressWindow().setVisible(false);
+			}
+		}
+	}
+	public void dispose() {
+		setResponsePending(false);
+		waiting = false;
+		if (holdsConsoleFocus) {
+			ConsoleThread.releaseConsoleObjectCommanded(this, true);
+			System.out.println("Dialog closed");
+		}
+		holdsConsoleFocus = false;
+		if (!usingWizard){
+			outerContents.setVisible(false);
+			if (alreadyDisposed) {
+				return;
+			}
+			alreadyDisposed = true;
+			MesquiteWindow.numDialogs--;
+			MesquiteWindow.numNonWizardDialogs--;
+			if (MesquiteModule.mesquiteTrunk.dialogVector != null)
+				MesquiteModule.mesquiteTrunk.dialogVector.removeElement(this, false);
+			if (MesquiteWindow.numDialogs <= 0)
+				MesquiteWindow.dialogAnchor.toBack();
+			MainThread.decrementSuppressWaitWindow();
+			parentDialog.pleaseDispose();
+		}
+		else {
+			//	outerContents.setVisible(false);
+
+			parentDialog.removeDialog(this); 
+			MesquiteWindow.numDialogs--;
+			if (MesquiteModule.mesquiteTrunk.dialogVector != null)
+				MesquiteModule.mesquiteTrunk.dialogVector.removeElement(this, false);
+			waitingOnButtonPush = false;
+		}
+	}
+	/*=====@@@@@@@@@@@@@@@============*/
+	public long getID() {
+		return id;
+	}
+
+	public String getName() {
+		return parentDialog.getTitle();
+	}
+
+	/* ................................................................................................................. */
+	/** A request for the object to perform a command. It is passed two strings, the name of the command and the arguments. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), null, null, commandName, "show")) {
+			System.out.println("Components of dialog");
+			showDialogComponents(this, new MesquiteInteger(0), " ", true);
+		}
+		else {
+			MesquiteInteger pos = new MesquiteInteger();
+			int whichComponent = MesquiteInteger.fromFirstToken(commandName, pos);
+			if (MesquiteInteger.isCombinable(whichComponent)) {
+				Component c = findDialogComponents(this, new MesquiteInteger(0), whichComponent);
+				if (c instanceof TextComponent && ((TextComponent) c).isEditable()) {
+					String text = ParseUtil.getFirstToken(arguments, pos);
+					if (text != null)
+						((TextComponent) c).setText(text);
+					showDialogComponents(this, new MesquiteInteger(0), " ", true);
+				}
+				else if (c instanceof Choice) {
+					System.out.println("Choice selected");
+					Choice choice = (Choice) c;
+					int whichItem = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+					if (MesquiteInteger.isCombinable(whichItem)) {
+						choice.select(whichItem - 1);
+						showDialogComponents(this, new MesquiteInteger(0), " ", true);
+					}
+
+					else {
+						Parser parser = new Parser();
+						String iss = parser.getFirstToken(arguments);
+						boolean selected = false;
+						if (iss != null)
+							for (int i = choice.getItemCount() - 1; i >= 0; i--) {
+								String s = choice.getItem(i);
+								if (s.equalsIgnoreCase(iss)) {
+									choice.select(i);
+									selected = true;
+								}
+							}
+						if (selected)
+							showDialogComponents(this, new MesquiteInteger(0), " ", true);
+
+					}
+				}
+				else if (c instanceof Label) {
+
+				}
+				else if (c instanceof Button) {
+
+					selectButton(((Button) c).getLabel());
+				}
+				else if (c instanceof Checkbox) {
+					System.out.println("Checkbox selected");
+					Checkbox cb = (Checkbox) c;
+					cb.setState(!cb.getState()); // needs to use event
+					ItemListener[] listeners = cb.getItemListeners();
+					int is;
+					if (cb.getState())
+						is = ItemEvent.SELECTED;
+					else
+						is = ItemEvent.DESELECTED;
+					if (listeners != null)
+						for (int i = 0; i < listeners.length; i++)
+							listeners[i].itemStateChanged(new ItemEvent(cb, ItemEvent.ITEM_STATE_CHANGED, cb.getLabel(), is));
+					showDialogComponents(this, new MesquiteInteger(0), " ", true);
+				}
+				else if (c instanceof List) {
+					List cList = (List) c;
+					int whichItem = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+					if (MesquiteInteger.isCombinable(whichItem)) {
+						cList.select(whichItem - 1);
+						showDialogComponents(this, new MesquiteInteger(0), " ", true);
+					}
+
+					else {
+						System.out.println("Item in list selected");
+						Parser parser = new Parser();
+						String iss = parser.getFirstToken(arguments);
+						boolean selected = false;
+						if (iss != null)
+							for (int i = cList.getItemCount() - 1; i >= 0; i--) {
+								String s = cList.getItem(i);
+								if (s.equalsIgnoreCase(iss)) {
+									cList.select(i);
+									selected = true;
+								}
+							}
+						if (selected)
+							showDialogComponents(this, new MesquiteInteger(0), " ", true);
+
+					}
+				}
+			}
+			else if (checker.compare(getClass(), null, null, commandName, "show")) {
+			}
+
+		}
+		/*
+		 * else return  super.doCommand(commandName, arguments, checker);
+		 */
+		return null;
+	}
+
+	public static Component findDialogComponents(MesquiteDialog c, MesquiteInteger count, int target) {
+		return findDialogComponents(c.outerContents, count, target);
+	}
+	public static Component findDialogComponents(Component c, MesquiteInteger count, int target) {
+
+		if ((c instanceof TextComponent && ((TextComponent) c).isEditable()) || c instanceof Choice || c instanceof Button || c instanceof Checkbox || c instanceof List) {
+			count.increment();
+			if (count.getValue() == target)
+				return c;
+		}
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++) {
+					Component q = findDialogComponents(cc[i], count, target);
+					if (q != null)
+						return q;
+				}
+		}
+		return null;
+	}
+
+	public static void showDialogComponents(MesquiteDialog c, MesquiteInteger count, String spacer, boolean outer) {
+		showDialogComponents(c.outerContents, count, spacer, true);
+	}
+	static boolean hasText, hasListOrChoice;
+
+	public static void showDialogComponents(Component c, MesquiteInteger count, String spacer, boolean outer) {
+		if (outer){
+			hasText = false;
+			hasListOrChoice = false;
+
+		}
+		if (c instanceof TextComponent) {
+			String s = ((TextComponent) c).getText();
+			if (StringUtil.blank(s))
+				s = "<blank>";
+			if (((TextComponent) c).isEditable()) {
+				hasText = true;
+				count.increment();
+				System.out.println(spacer + count.getValue() + " " + s);
+			}
+			else
+				System.out.println(spacer + " " + s);
+		}
+		else if (c instanceof Label) {
+			System.out.println(spacer + " " + ((Label) c).getText());
+		}
+		else if (c instanceof Choice) {
+			hasListOrChoice = true;
+
+			count.increment();
+			Choice choice = (Choice) c;
+			System.out.println(spacer + "--------------");
+			System.out.println(spacer + count.getValue() + " Choice ");
+			for (int k = 0; k < choice.getItemCount(); k++) {
+				if (choice.getSelectedIndex() == k)
+					System.out.println(spacer + "  " + (k+1) + " *" + choice.getItem(k));
+				else
+					System.out.println(spacer + "  " + (k+1) + "  " + choice.getItem(k));
+			}
+			System.out.println(spacer + "--------------");
+		}
+		else if (c instanceof Button) {
+			count.increment();
+			System.out.println(spacer + count.getValue() + " (" + ((Button) c).getLabel() + ")");
+		}
+		else if (c instanceof Checkbox) {
+			count.increment();
+			if (((Checkbox) c).getState())
+				System.out.print(spacer + count.getValue() + " " + "[on] ");
+			else
+				System.out.print(spacer + count.getValue() + " " + "[off] ");
+
+			System.out.println(((Checkbox) c).getLabel());
+		}
+		else if (c instanceof List) {
+			hasListOrChoice = true;
+			System.out.println(spacer + "--------------");
+			count.increment();
+			System.out.println(spacer + count.getValue() + " List ");
+			List list = (List) c;
+			for (int k = 0; k < list.getItemCount(); k++) {
+				if (list.isIndexSelected(k))
+					System.out.println(spacer + "  " + (k+1) + " *" + list.getItem(k));
+				else
+					System.out.println(spacer + "  " + (k+1) + "  " + list.getItem(k));
+			}
+			System.out.println(spacer + "--------------");
+		}
+		else {
+			// System.out.println(spacer + count.getValue() + " COMPONENT " + c.getClass().getName());
+		}
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					showDialogComponents(cc[i], count, spacer + "  ", false);
+		}
+		if (outer){
+			System.out.println("Enter number of component to select.");
+			if (hasListOrChoice){
+				System.out.println(" If component is a list or choice menu, enter");
+				System.out.println(" both number of component and number of item within it to choose");
+				System.out.println(" (e.g. if a list is component 1, and you want to select its item 2, enter \"1 2\"");
+				System.out.println("");
+			}
+			if (hasText){
+				System.out.println(" If component is a editable text, enter");
+				System.out.println(" both number of component and the text within it");
+				System.out.println(" (e.g. if you want to specify the text for component 1 to be \"100.0\",");
+				System.out.println(" enter \"1 100.0\"");
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	/*
+	 * public Component add(Component c){ if (c!=null) c.addKeyListener(this); return super.add(c); } public void add(Component c, Object obj){ if (c!=null) c.addKeyListener(this); super.add(c, obj); } public void add(Component c, Object obj, int i){ if (c!=null) c.addKeyListener(this); super.add(c, obj, i); } public Component add(Component c, int i){ if (c!=null) c.addKeyListener(this); return super.add(c, i); } public Component add(String s, Component c){ if (c!=null) c.addKeyListener(thi [...]
+	 * return super.add(c); } public void addWithoutKeyListener(Component c, Object obj){ super.add(c, obj); } public void addWithoutKeyListener(Component c, Object obj, int i){ super.add(c, obj, i); } public Component addWithoutKeyListener(Component c, int i){ return super.add(c, i); } public Component addWithoutKeyListener(String s, Component c){ return super.add(s, c); }
+	 */
+	/* ................................................................................................................. */
+	public void setAutoDispose(boolean autoDispose) {
+		this.autoDispose = autoDispose;
+	}
+
+	/* ................................................................................................................. */
+	public boolean getAutoDispose() {
+		return autoDispose;
+	}
+
+	/* ................................................................................................................. */
+	public void componentResized(ComponentEvent e) {
+	}
+
+	/* ................................................................................................................. */
+	public void componentMoved(ComponentEvent e) {
+	}
+
+	/* ................................................................................................................. */
+	public void componentHidden(ComponentEvent e) {
+	}
+
+	/* ................................................................................................................. */
+	public void componentShown(ComponentEvent e) {
+		if (MesquiteTrunk.isMacOSXJaguar()) { // attempts to get around Jaguar bugs
+			valAll(this);
+
+			setDialogLocation(savedX, savedY);
+		}
+		Toolkit.getDefaultToolkit().sync();
+	}
+
+	public void getButtons(MesquiteDialog c, Vector v) {
+		getButtons(c.outerContents, v);
+	}
+	public void getButtons(Component c, Vector v) {
+		if (c == null || v == null)
+			return;
+		if (c instanceof Button)
+			v.addElement(((Button) c).getLabel());
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					getButtons(cc[i], v);
+		}
+
+	}
+
+	private void valAll(MesquiteDialog c) {
+		valAll(c.outerContents);
+	}
+	private void valAll(Component c) {
+		if (c == null)
+			return;
+		if (c instanceof Container) {
+			c.invalidate();
+			c.validate();
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					valAll(cc[i]);
+		}
+
+	}
+
+	private void rpAll(Component c) {
+		if (c == null)
+			return;
+		c.repaint();
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					rpAll(cc[i]);
+		}
+
+	}
+
+	/* ................................................................................................................. */
+	public static void addComponent(MesquiteDialog container, Component component, int gridx, int gridy, int gridwidth, int gridheight, int weightx, int weighty, int fill, int anchor) {
+		addComponent(container.outerContents, component, gridx, gridy, gridwidth, gridheight, weightx, weighty,fill, anchor);
+	}
+	/* ................................................................................................................. */
+	public static void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth, int gridheight, int weightx, int weighty, int fill, int anchor) {
+		LayoutManager lm = container.getLayout();
+		if (lm instanceof GridBagLayout) {
+			GridBagConstraints gbc = new GridBagConstraints();
+			gbc.gridx = gridx;
+			gbc.gridy = gridy;
+			gbc.gridwidth = gridwidth;
+			gbc.gridheight = gridheight;
+			gbc.weightx = weightx;
+			gbc.weighty = weighty;
+			gbc.fill = fill;
+			gbc.anchor = anchor;
+			((GridBagLayout) lm).setConstraints(component, gbc);
+		}
+		container.add(component);
+	}
+
+	public abstract void buttonHit(String buttonLabel, Button button);
+
+
+	private void setMouseListeners(Component c) {
+		if (c == null)
+			return;
+		if (c instanceof Button)
+			c.addMouseListener(this);
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					setMouseListeners(cc[i]);
+		}
+
+	}
+
+	// TODO: have way to remove default button or set default button in all dialog boxes
+	private void setKeyListeners(Component c) {
+		if (c == null)
+			return;
+		c.addKeyListener(this);
+		if (c instanceof Button && defaultButtonString != null && defaultButtonString.equals(((Button) c).getLabel())) {
+			Font f = c.getFont();
+			Font fontToSet = new Font(f.getName(), Font.ITALIC, f.getSize());
+			c.setFont(fontToSet);
+		}
+		if (c instanceof Container) {
+			Component[] cc = ((Container) c).getComponents();
+			if (cc != null && cc.length > 0)
+				for (int i = 0; i < cc.length; i++)
+					setKeyListeners(cc[i]);
+		}
+
+	}
+
+
+	boolean waiting = false;
+
+
+	// don't show dialog if there are already showing dialogs on other threads!!!!!
+	private void waitForOtherDialogThreads() {
+		try {
+			while (othersExist()) {
+				Thread.sleep(20);
+			}
+		} catch (Exception e) {
+		} catch (Error e) {
+			if (e instanceof OutOfMemoryError)
+				MesquiteMessage.println("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+		}
+	}
+	private boolean othersExist() {
+		ListableVector ds = MesquiteModule.mesquiteTrunk.dialogVector;
+		if (ds == null || ds.size() < 1)
+			return false;
+		for (int i = 0; i < ds.size(); i++) {
+			MesquiteDialog dlog = (MesquiteDialog) ds.elementAt(i);
+			if (dlog != this && dlog.isVisible() && dlog.thread != null && thread != null && dlog.thread != thread)
+				return true;
+		}
+		return false;
+	}
+
+	public void setDefaultButton(String s) {
+		defaultButtonString = s;
+	}
+
+	public void keyTyped(KeyEvent e) {
+		if ((e.getKeyCode() == 10 || e.getKeyCode() == 13) && defaultButtonString != null) {
+			buttonHit(defaultButtonString, null);
+			if (autoDispose)
+				dispose();
+		}
+	}
+
+	public void keyPressed(KeyEvent e) {
+	}
+
+	public void keyReleased(KeyEvent e) {
+		if ((e.getKeyCode() == 10 || e.getKeyCode() == 13) && defaultButtonString != null) {
+			buttonHit(defaultButtonString, null);
+			if (autoDispose)
+				dispose();
+		}
+	}
+
+	public void mouseClicked(MouseEvent e) {
+	}
+
+	public void mouseEntered(MouseEvent e) {
+	}
+
+	public void mouseExited(MouseEvent e) {
+	}
+
+	public void mousePressed(MouseEvent e) {
+		if (MesquiteTrunk.isMacOSXYosemite() && MesquiteTrunk.isJavaVersionLessThan(1.7) && e.getComponent() instanceof Button) {
+			buttonHit(((Button) e.getComponent()).getLabel(), (Button) e.getComponent());
+			dispose();
+		}
+	}
+
+	public void mouseReleased(MouseEvent e) {
+		if (e.getComponent() instanceof Button) {
+			buttonHit(((Button) e.getComponent()).getLabel(), (Button) e.getComponent());
+			dispose();
+		}
+	}
+
+	public void selectButton(String label) { // for use by scripting & console
+
+		buttonHit(label, null);
+		dispose();
+	}
+}
+class MDPanel extends Panel {
+	boolean usingWizard = false;
+	public MDPanel (boolean usingWizard){
+		this.usingWizard = usingWizard;
+		//setBackground(Color.green);
+	}
+	public Dimension getPreferredSize(boolean contentsOnly){
+		if (usingWizard && !contentsOnly)
+			return new Dimension(MesquiteDialog.wizardWidth - MesquiteDialogParent.infoWidth, MesquiteDialog.wizardHeight);
+		return super.getPreferredSize();
+	}
+	public Dimension getPreferredSize(){
+		if (usingWizard)
+			return new Dimension(MesquiteDialog.wizardWidth - MesquiteDialogParent.infoWidth, MesquiteDialog.wizardHeight);
+		return super.getPreferredSize();
+	}
+
+
+
+}
+
+class MDConsoleShowThread extends Thread {
+	MesquiteDialog dlog;
+	public MDConsoleShowThread(MesquiteDialog dlog){
+		this.dlog = dlog;
+	}
+	public void run(){
+		dlog.setVisible(true);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteDialogParent.java b/Source/mesquite/lib/MesquiteDialogParent.java
new file mode 100644
index 0000000..6f7087a
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDialogParent.java
@@ -0,0 +1,506 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import javax.swing.*;
+
+/* =============================================== */
+/** A dialog box */
+public class MesquiteDialogParent extends JDialog implements Identifiable {
+	LayoutManager layout;
+	Component current;
+	boolean enlargeOnly = false;
+	MDPShowThread showThread;
+	MDPHelperThread helperThread;
+	boolean isWizard = false;
+	WizardInfoPanel infoPanel;
+	public static int infoWidth = 200;
+	MesquiteDialog currentDialog;
+	public static long totalCreated = 0;
+	long id;
+	public static long totalDisposed = 0;
+	public static long totalFinalized  = 0;
+	public WaitPanel waitPanel;
+	Vector dialogsToAdd = new Vector();
+	Vector dialogsToRemove = new Vector();
+	boolean hiddenForCalculation = false;
+	public MesquiteDialogParent(Frame f, String title, boolean b) {
+		super(f, title, b);
+		//setLocation(0, 0);
+		id = totalCreated++;
+		
+		getContentPane().setLayout(layout = new CardLayout());
+		setResizable(false);
+		setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+		setForeground(Color.black);
+		showThread = new MDPShowThread(this);
+		showThread.start();
+		helperThread = new MDPHelperThread(this);
+		helperThread.start();
+		waitPanel = new WaitPanel(this);
+		waitPanel.setBackground(ColorTheme.getInterfaceBackground());
+
+		MesquiteWindow.centerWindow(this);
+	}
+	public Container getContentPane(){
+		if (MesquiteWindow.headless)
+			return new Panel();
+		return super.getContentPane();
+	}
+	public long getID(){
+		return id;
+	}
+	MesquiteModule initiatingModule;
+	public MesquiteModule setInitiatingModuleIfNeeded(MesquiteModule w){
+		if (initiatingModule == null)
+			initiatingModule = w;
+		return initiatingModule ;
+	}
+	public MesquiteModule getInitiatingModule(){
+		return initiatingModule ;
+	}
+	/*-------------------------------------------------------*/
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	public void pleaseDispose(){
+		if (helperThread != null)
+		helperThread.pleaseDispose = true;
+
+	}
+	public void pleaseShow(){
+		if (showThread != null)
+		showThread.pleaseShow = true;
+	}
+	public void pleaseBringToFront(){
+		if (helperThread != null)
+		helperThread.pleaseBringToFront = true;
+	}
+	public void toFront(){
+		if (!hiddenForCalculation)
+			super.toFront();
+	}
+	public void pleaseRequestFocus(){
+		if (helperThread != null)
+		helperThread.pleaseRequestFocus = true;
+	}
+	boolean alreadyDisposed = false;
+	
+	boolean inArray(Component[] components, Component c){
+		for (int i=0; i< components.length; i++)
+			if (c == components[i])
+				return true;
+		return false;
+	}
+	void hideAll(Component c){
+		c.setVisible(false);
+		if (c instanceof Container){
+			Component[] components = ((Container)c).getComponents();
+			for (int i=0; i<components.length; i++)
+				hideAll(components[i]);
+		}
+	}
+	public void removeDialog(MesquiteDialog d){
+		dialogsToRemove.addElement(d);
+		removeOldest();
+		//dialogsToRemove.addElement(d);
+		//helperThread.pleaseRemoveDialog = true;
+		pleaseRequestFocus();
+	}
+	public void removeOldest(){
+		if (dialogsToRemove.size()==0)
+			return;
+		MesquiteDialog dlog = (MesquiteDialog)dialogsToRemove.elementAt(0);
+		dialogsToRemove.removeElement(dlog);
+		Component c = dlog.outerContents;
+		remove(c);
+		Component[] components = getComponents();
+		hideAll(c);
+		if (c instanceof Container)
+			((Container)c).removeAll();
+
+//		components = getComponents();
+		if (!inArray(components, waitPanel)){
+			if (layout instanceof BorderLayout)
+				super.getContentPane().add(waitPanel,BorderLayout.CENTER);  //LINE_END
+			else
+				super.getContentPane().add(waitPanel);
+		}
+		waitPanel.setVisible(true);
+		current = waitPanel;
+		currentDialog = null;
+		resetInfo();
+		resetSizes();
+		doLayout();
+		waitPanel.repaint();
+	}
+	public void dispose(){
+		if (alreadyDisposed) {
+			return;
+		}
+		alreadyDisposed = true;
+		
+		if (isWizard) 
+			remove(infoPanel);
+		if (this == MesquiteDialog.currentWizard)
+			MesquiteDialog.currentWizard = null;
+		removeAll();
+		showThread.go = false;
+		helperThread.go = false;
+		super.setVisible(false);
+		totalDisposed++;
+		
+		super.dispose();
+	}
+	public void setVisible(boolean b){
+		if (alreadyDisposed)
+			return;
+		if (b)
+			hiddenForCalculation = false;
+		if (!b && this == MesquiteDialog.currentWizard)
+			MesquiteDialog.currentWizard = null;
+		if (b && isWizard)
+			MesquiteDialog.currentWizard = this;
+		super.setVisible(b);
+	}
+
+	public void hideForCalculation(){
+		if (alreadyDisposed)
+			return;
+		hiddenForCalculation = true;
+		super.setVisible(false);
+	}
+	public Dimension getPreferredSize(boolean contentsOnly){
+		if (isWizard){
+			if (contentsOnly && currentDialog!= null && currentDialog.outerContents != null) {
+				Dimension ps =  currentDialog.outerContents.getPreferredSize(true);
+				return ps;
+			}
+			else
+				return new Dimension(MesquiteDialog.wizardWidth, MesquiteDialog.wizardHeight);
+		}
+		return super.getPreferredSize();
+	}
+	public Dimension getPreferredSize(){
+		if (isWizard)
+			return new Dimension(MesquiteDialog.wizardWidth, MesquiteDialog.wizardHeight);
+		return super.getPreferredSize();
+	}
+	void addNext(){
+		if (dialogsToAdd.size()==0)
+			return;
+		MesquiteDialog dlog = (MesquiteDialog)dialogsToAdd.elementAt(0);
+		dialogsToAdd.removeElement(dlog);
+		Component c = dlog.outerContents;
+		String s = Integer.toString(dlog.id);
+		if (alreadyDisposed)
+			return;
+		if (layout instanceof BorderLayout) {
+			super.remove(waitPanel);
+			getContentPane().add(c,BorderLayout.CENTER); //LINE_END
+		}
+		else{
+			getContentPane().add(c, s);
+			//((CardLayout)layout).show(this, s);
+		}
+		if (current != null)
+			remove(current);
+		current = c;
+		
+		currentDialog = dlog;
+		//	pleaseRequestFocus();
+
+		//&*	c.requestFocusInWindow();
+		resetSizes();
+
+	}
+	public void add(MesquiteDialog dlog){
+		dialogsToAdd.addElement(dlog);
+		addNext();
+		//helperThread.pleaseAddDialog = true;
+
+	}
+	public MesquiteDialog getCurrentDialog(){
+		return currentDialog;
+	}
+	public void setAsWizard(){
+
+		getContentPane().setLayout(layout = new BorderLayout());
+
+		if (infoPanel == null){
+			infoPanel = new WizardInfoPanel(this);
+			infoPanel.setSize(infoWidth, getBounds().height);
+			infoPanel.setVisible(true);
+			getContentPane().add(infoPanel, BorderLayout.WEST); //LINE_START
+		}
+		resetSizes();
+		enlargeOnly = true;
+		isWizard = true;
+		if (isVisible())
+			MesquiteDialog.currentWizard = this;
+	}
+	public boolean isWizard(){
+		return isWizard;
+	}
+	void resetSizes(){
+		if (alreadyDisposed)
+			return;
+		if (layout instanceof CardLayout){
+			if (helperThread != null)
+				helperThread.pleaseResetInfo = true;
+			return;
+		}
+		Insets insets = getInsets();
+		int netHeight = getBounds().height - insets.top - insets.bottom;
+		int netWidth = getBounds().width - insets.left - insets.right;
+		 if (infoPanel != null)
+				infoPanel.setSize(infoWidth, netHeight);
+			if (current != null) {
+				current.setSize(netWidth - infoWidth, netHeight);
+			}
+			
+		
+		if (helperThread != null)
+			helperThread.pleaseResetInfo = true;
+	}
+	void resetInfo(){
+		if (alreadyDisposed)
+			return;
+		try {
+			if (currentDialog != null && currentDialog instanceof ExtensibleDialog){
+				String st = ((ExtensibleDialog)currentDialog).getHelpString();
+				if (st != null && infoPanel != null)
+					infoPanel.setText(st);
+			}
+			else 
+				infoPanel.setText("<html><body bgcolor=\"#DEB887\"></body></html>");
+		}
+		catch (Throwable e){
+
+		}
+		try {
+		if (current != null){
+			current.doLayout();
+			current.invalidate();
+			current.validate();
+		}
+		}
+		catch (Throwable e){
+
+		}
+
+	}
+	public void pack(){
+		if (alreadyDisposed)
+			return;
+		if (isWizard){
+			resetSizes();
+			super.pack();
+			invalidate();
+			validate();
+			doLayout();
+			MesquiteWindow.rpAll(current);
+			resetSizes();
+		}
+		else
+			super.pack();
+	}
+
+	public void setSize(Dimension d){
+		if (alreadyDisposed)
+			return;
+		if (enlargeOnly){
+			if (d.width < getWidth())
+				d.width = getWidth();
+			if (d.height < getHeight())
+				d.height = getHeight();
+		}
+		super.setSize(d);
+		resetSizes();
+
+	}
+	public void setSize(int w, int h){
+		if (alreadyDisposed)
+			return;
+		if (enlargeOnly){
+			if (w < getWidth())
+				w = getWidth();
+			if (h < getHeight())
+				h = getHeight();
+		}
+		super.setSize(w, h);
+		resetSizes();
+
+	}
+	public void setBounds(int x, int y, int w, int h){
+		if (alreadyDisposed)
+			return;
+		if (enlargeOnly){
+			if (w < getWidth())
+				w = getWidth();
+			if (h < getHeight())
+				h = getHeight();
+		}
+//		if (isWizard && locOnceSet)
+		super.setBounds(x, y, w, h);
+		resetSizes();
+	}
+	public void setLocation(int x, int y){
+		if (alreadyDisposed)
+			return;
+		super.setLocation(x, y);
+	}
+}
+
+class MDPShowThread extends Thread {
+	MesquiteDialogParent parent;
+	boolean pleaseShow = false;
+	int count = 0;
+	boolean go;
+	public MDPShowThread(MesquiteDialogParent parent){
+		this.parent = parent;
+	}
+	public void run(){
+		go = true;
+		try{
+			while (go  && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting){
+				Thread.sleep(50);
+				if (pleaseShow){
+
+					pleaseShow = false;
+					//go = false;
+					parent.setVisible(true);
+				}
+			}
+		}
+		catch (InterruptedException e){
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+}
+
+class MDPHelperThread extends Thread {
+	MesquiteDialogParent parent;
+	boolean pleaseDispose = false;
+	boolean pleaseResetInfo = false;
+	boolean pleaseBringToFront = false;
+	boolean pleaseRequestFocus = false;
+	boolean pleaseRemoveDialog = false;
+	boolean pleaseAddDialog = false;
+	boolean disposed = false;
+	boolean go;
+	int count = 0;
+	public MDPHelperThread(MesquiteDialogParent parent){
+		this.parent = parent;
+	}
+	public void run(){
+		go = true;
+		try{
+			while (go && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting){
+				Thread.sleep(50);
+				if (pleaseResetInfo){
+					parent.resetInfo();
+					pleaseResetInfo = false;
+				}
+				if (pleaseBringToFront){
+					parent.toFront();
+					pleaseBringToFront = false;
+				}
+				if (pleaseRequestFocus){
+					parent.requestFocus();
+					pleaseRequestFocus = false;
+				}
+				if (pleaseRemoveDialog){
+					parent.removeOldest();
+					pleaseRemoveDialog = false;
+				}
+				if (pleaseAddDialog){
+					parent.addNext();
+					pleaseAddDialog = false;
+				}
+				if (pleaseDispose){
+					parent.dispose();
+					disposed = true;
+					pleaseDispose = false;
+					go = false;
+				}
+			}
+		}
+		catch (InterruptedException e){
+		}
+		if (!disposed)
+			parent.dispose();
+	}
+}
+
+class WizardInfoPanel extends MesquitePanel {
+	MesquiteDialogParent parent;
+	JEditorPane text;
+	public WizardInfoPanel (MesquiteDialogParent parent){
+		this.parent = parent;
+		setLayout(null);
+		text = new MesqJEditorPane("text/html","<html><body bgcolor=\"#DEB887\"></body></html>");
+		add(text);
+		text.setVisible(true);
+		setBackground(ColorDistribution.mesquiteBrown);
+		//text.setBounds(0, 0, 50, 50);
+	}
+	public void setText(String s){
+		try{
+			text.setText("<html><body bgcolor=\"#DEB887\">" + s + "</body></html>");	
+	 	}
+		catch(Exception e){
+			try{
+				text.setText("<html><body bgcolor=\"#DEB887\"></body></html>");	
+		 	}
+			catch(Exception e2){
+			}
+		}
+		
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		text.setBounds(4, 4, w-8, h-8);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		text.setBounds(4, 4, w-8, h-8);
+	}
+	public Dimension getPreferredSize(){
+		return new Dimension(parent.infoWidth, MesquiteDialog.wizardHeight);
+	}
+
+}
+class WaitPanel extends MesquitePanel {
+	MesquiteDialogParent parent;
+//	public ProgressPanel progressPanel;
+	public boolean showWait = true;
+	public WaitPanel (MesquiteDialogParent parent){
+		this.parent = parent;
+		setLayout(null);
+		//	progressPanel = new ProgressPanel(null, null, null, 0, null);
+		//	add(progressPanel);
+		//	progressPanel.setBounds(0,0,0,0);
+	}
+	public void paint(Graphics g){
+		//	Component[] c = getComponents();
+		if (showWait)
+			g.drawString("Please Wait...", getBounds().width/2-40, getBounds().height/3);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteDouble.java b/Source/mesquite/lib/MesquiteDouble.java
new file mode 100644
index 0000000..a7128ba
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDouble.java
@@ -0,0 +1,1299 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+import corejava.Format;
+
+/*Last documented:  August 1999 */
+
+/* ======================================================================== */
+/** This double wrapper class is used to be able to pass doubles by reference and have the
+	original change as needed*/
+public class MesquiteDouble implements Listable {
+	public static final double unassigned = Double.MAX_VALUE * 0.9999;
+	public static final double inapplicable = Double.MAX_VALUE * 0.99999;
+	public static final double infinite = Double.POSITIVE_INFINITY;
+	public static final double negInfinite = Double.NEGATIVE_INFINITY;
+	public static final double impossible = Double.MAX_VALUE * 0.999999;
+	public static final double veryLargeNumber = 1.0e100;
+	private double value;
+	private String name = null;
+	static double log10 = Math.log(10.0);
+	public static long totalCreated = 0;
+	public static int defaultDigits = 8; //changed from 6, 17 Dec 01
+	
+	public MesquiteDouble(double value) {
+		this.value=value;
+		totalCreated++;
+	}
+	public MesquiteDouble(String name, double value) {
+		this.value=value;
+		this.name = name;
+		totalCreated++;
+	}
+	public MesquiteDouble() {
+		this.value=unassigned;
+		totalCreated++;
+	}
+	
+	public void setName(String s){
+		name = s;
+	}
+	public String getName(){
+		return name;
+	}
+	/*--------------------------------GET/SET--------------------------*/
+	/** Returns value as double */
+	public double getValue() {
+		return value;
+	}
+
+	/** Sets value */
+	public void setValue(double value) {
+		this.value=value;
+	}
+	/** Sets value */
+	public void setValue(String s) {
+		this.value=fromString(s);
+	}
+	/** Adds one to value */
+	public void increment() {
+		value+=1;
+	}
+	/** Subtracts one from value */
+	public void decrement() {
+		value-=1;
+	}
+	/** Sets value to unassigned */
+	public void setToUnassigned() {
+		value=unassigned;
+	}
+	/*--------------------------------CONVERSION--------------------------*/
+	/** Returns the double conversion of the passed integer, considering
+	unassigned, infinite etc. values */
+	public static double toDouble(int v) {
+		if (v==MesquiteInteger.unassigned)
+			return MesquiteDouble.unassigned;
+		else if (v==MesquiteInteger.infinite)
+			return MesquiteDouble.infinite;
+		else if (v==MesquiteInteger.negInfinite)
+			return MesquiteDouble.negInfinite;
+		else if (v==MesquiteInteger.inapplicable)
+			return MesquiteDouble.inapplicable;
+		else if (v==MesquiteInteger.impossible)
+			return MesquiteDouble.impossible;
+		else
+			return v;
+	}
+	/** Returns the double conversion of the passed long, considering
+	unassigned, infinite etc. values */
+	public static double toDouble(long v) {
+		if (v==MesquiteLong.unassigned)
+			return MesquiteDouble.unassigned;
+		else if (v==MesquiteLong.infinite)
+			return MesquiteDouble.infinite;
+		else if (v==MesquiteLong.negInfinite)
+			return MesquiteDouble.negInfinite;
+		else if (v==MesquiteLong.inapplicable)
+			return MesquiteDouble.inapplicable;
+		else if (v==MesquiteLong.impossible)
+			return MesquiteDouble.impossible;
+		else
+			return v;
+	}
+
+	/*--------------------------------QUERY--------------------------*/
+	/** Returns whether value is unassigned */
+	public boolean isUnassigned() {
+		return (value==unassigned);
+	}
+	/** Returns whether value is unassigned */
+	public static boolean isUnassigned(double d) {
+		return (d==unassigned);
+	}
+	/** Returns whether value is infinite */
+	public boolean isInfinite() {
+		return (value==infinite || value == negInfinite);
+	}
+	/** Returns whether value is infinite */
+	public static boolean isInfinite(double d) {
+		return (d==infinite || d == negInfinite);
+	}
+	/** Returns whether value is impossible */
+	public boolean isImpossible() {
+		return (value==impossible);
+	}
+	/** Returns whether value is impossible */
+	public static boolean isImpossible(double d) {
+		return (d==impossible);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public boolean isInapplicable() {
+		return (value==inapplicable);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public static boolean isInapplicable(double d) {
+		return (d==inapplicable);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable() {
+		return (value!=unassigned && value!=infinite && value!=impossible && value != negInfinite && value!=inapplicable && (value!=Double.NaN));
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public static boolean isCombinable(double d) {
+		return (d!=unassigned && d!=infinite && d!=impossible && d!=inapplicable && d!=negInfinite  && (!Double.isNaN(d))); //NaN test added Apr 02
+	}
+
+	/*--------------------------------ARITHMETICS--------------------------*/
+	/** Adds to current value.  Considers infinite, unassigned etc. */
+	public void add(double toAdd) {
+		value = add(toAdd, value);
+	}
+	/** Subtracts from current value.  Considers infinite, unassigned etc. */
+	public void subtract(double toSubtract) {
+		value = subtract(value, toSubtract);
+	}
+	/** Adds two doubles.  Considers infinite, unassigned etc. */
+	public static double add(double value1, double value2) {
+		if (value1 == infinite){
+			if (value2== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (value2 == negInfinite)
+			return negInfinite;
+		else if (isCombinable(value1)) {
+			if (isCombinable(value2))
+				return value1 + value2;
+			else
+				return value1;
+		}
+		else
+			return value2;
+	}
+	/** Subtracts value2 from value 1.  Considers infinite, unassigned etc. */
+	public static double subtract(double value1, double value2) {
+		if (value2 == negInfinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== infinite)
+				return 0;
+			else
+				return negInfinite;
+		}
+		else if (value1 == infinite)
+			return infinite;
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (isCombinable(value2)) {
+			if (isCombinable(value1))
+				return value1 - value2;
+			else
+				return -value2;
+		}
+		else
+			return value1;
+	}
+	/** Multiplies two doubles.  Considers infinite, unassigned etc. */
+	public static double multiply(double value1, double value2) {
+		if (value1 == 0 || value2==0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return value1*value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite){
+					if (value1<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value2== negInfinite) {
+					if (value1<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				if (value1 == infinite){
+					if (value2<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value1== negInfinite) {
+					if (value2<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+			else { //neither combinable
+				if (value1 == infinite && value2 == infinite)
+					return infinite;
+				else if (value1 == infinite && value2 == negInfinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == infinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == negInfinite)
+					return infinite;
+				else 
+					return unassigned;
+			}
+		}
+		
+	}
+	/** Returns whether the two values differ by less than p OR their ratio differs from 1 by less than p. */
+	public static boolean closeEnough(double value1, double value2, double p) {
+		if (value1== value2)
+			return true;
+		if (!isCombinable(value1) || !isCombinable(value2))
+			return false;
+		if ( Math.abs(value1-value2)<p)
+			return true;
+		return (Math.abs(1.0 - value1/value2) < p);
+			
+	}
+	/** Squared difference betwen two doubles.  Considers infinite, unassigned etc. */
+	public static double squaredDifference(double value1, double value2) {
+		if (value1 == 0 || value2==0 || value1 == value2)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2)) {
+				double diff = value1-value2;
+				return diff*diff;
+			}
+		}
+		return unassigned;
+	/*
+			else {  //value 2 not combinable
+				if (value2 == infinite){
+					if (value1<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value2== negInfinite) {
+					if (value1<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				if (value1 == infinite){
+					if (value2<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value1== negInfinite) {
+					if (value2<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+			else { //neither combinable
+				if (value1 == infinite && value2 == infinite)
+					return infinite;
+				else if (value1 == infinite && value2 == negInfinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == infinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == negInfinite)
+					return infinite;
+				else 
+					return unassigned;
+			}
+		}
+		*/
+		
+	}
+	/** Divides first double by second double.  Considers infinite, unassigned etc. */
+	public static double divide(double value1, double value2) {
+		if (value2==0)
+			return MesquiteDouble.infinite;
+		else if (value1 == 0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return ((double)value1)/value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				return unassigned;
+			}
+			else { //neither combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return unassigned;
+			}
+		}
+	}
+	/** returns the negative log of the value. */
+	public static double negLog(double value) {
+		if (!isCombinable(value))
+			return value;
+		else
+			return -Math.log(value);
+	
+	}
+	/*--------------------------------MIN-MAX--------------------------*/
+
+	/** Returns maximum of two doubles.  Accounts for infinite, unassigned, etc. */
+	public static double maximum(double a, double b) {
+		if (a == unassigned || a == inapplicable || a == negInfinite || a == impossible) {
+			if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible)
+				return unassigned;
+			else
+				return b;
+		}
+		else if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible)
+			return a;
+		else if (a==infinite)
+			return a;
+		else if (b==infinite)
+			return b;
+		else if (a>b)
+			return a;
+		else
+			return b;
+	}
+	/** Returns minimum of two doubles.  Accounts for infinite, unassigned, etc. */
+	public static double minimum(double a, double b) {
+		if (a == unassigned || a == inapplicable || a == infinite || a == impossible){
+			if (b==unassigned || b == inapplicable || b== infinite || b == impossible)
+				return unassigned;
+			else
+				return b;
+		}
+		else if (b==unassigned || b == inapplicable || b== infinite || b == impossible)
+			return a;
+		else if (a==negInfinite)
+			return a;
+		else if (b==negInfinite)
+			return b;
+		else if (a<b)
+			return a;
+		else
+			return b;
+	}
+	/*--------------------------------INEQUALITIES--------------------------*/
+
+	/** Returns true if value 1 is less than value 2.  Its response is conservative 
+	by a proportional tolerance as given (i.e., if tolerance is 0.01, then this returns false even if
+	value1 is greater than or equal to value 2, as long as the difference between
+	value1 and value2 is less than 1% of the larger of the absolute values of value1 and value2*/
+	public static boolean lessThan(double value1, double value2, double toleranceProportion) {
+		if (value1 == infinite) 
+			return false;
+		else if (value2 == infinite) 
+			return true;
+		else if (value1 == negInfinite) 
+			return true;
+		else if (value2 == negInfinite) 
+			return false;
+		else if (!isCombinable(value2))
+			return isCombinable(value1);
+		else if (!isCombinable(value1))
+			return false;
+		else if (toleranceProportion >0.0) { //if tolerance negative, ignore
+			double a1 = Math.abs(value1);
+			double a2 = Math.abs(value2);
+			double den;
+			if (a1> a2)
+				den = a1;
+			else
+				den = a2;
+			if (den == 0.0)
+				return false;  //equal and 0, thus not less than
+			else if ( Math.abs((value1-value2)/den) < toleranceProportion) //proportional difference less than tolerance
+				return false;
+			else
+				return (value1<value2);
+		}
+		else 
+			return (value1<value2);
+	}
+	/** Returns true if value 1 is greater than value 2.  Its response is conservative 
+	by a proportional tolerance as given (i.e., if tolerance is 0.01, then this returns false even if
+	value1 is less than or equal to value 2, as long as the difference between
+	value1 and value2 is less than 1% of the larger of the absolute values of value1 and value2*/
+	public static boolean greaterThan(double value1, double value2, double toleranceProportion) {
+		if (value1 == infinite) 
+			return true;
+		else if (value2 == infinite) 
+			return false;
+		else if (value1 == negInfinite) 
+			return false;
+		else if (value2 == negInfinite) 
+			return true;
+		else if (!isCombinable(value2)) //TODO: think about these rules
+			return isCombinable(value1);
+		else if (!isCombinable(value1))
+			return false;
+		else if (toleranceProportion >0.0) { //if tolerance negative, ignore
+			double a1 = Math.abs(value1);
+			double a2 = Math.abs(value2);
+			double den;
+			if (a1> a2)
+				den = a1;
+			else
+				den = a2;
+			if (den == 0.0)
+				return false;  //equal and 0, thus not less than
+			else if ( Math.abs((value1-value2)/den) < toleranceProportion) //proportional difference less than tolerance
+				return false;
+			else
+				return (value1>value2);
+		}
+		else 
+			return (value1>value2);
+	}
+	/** Returns true if value 1 is equal to value 2,
+	within the proportional tolerance as given (i.e., if tolerance is 0.01, then this returns false even if
+	value1 is less than or equal to value 2, as long as the difference between
+	value1 and value2 is less than 1% of the larger of the absolute values of value1 and value2*/
+	public static boolean equals(double value1, double value2, double toleranceProportion) {
+		if (value1 == value2) 
+			return true;
+		else if (value1 == infinite || value2 == infinite || value1 == negInfinite || value2 == negInfinite) 
+			return false;
+		else if (toleranceProportion>0.0){
+			double a1 = Math.abs(value1);
+			double a2 = Math.abs(value2);
+			double den;
+			if (a1> a2)
+				den = a1;
+			else
+				den = a2;
+			if (den == 0.0)
+				return true; 
+			if (Math.abs((value1-value2)/den) < toleranceProportion) //less than 0.000001 proportion difference
+				return true;
+			else
+				return false;
+		}
+		else
+			return false;
+	}
+	
+		/** Returns true if value 1 is greater than value 2 by at least the factor given.  Its response is conservative 
+	by a proportional tolerance as given (i.e., if tolerance is 0.01, then this returns false even if
+	value1 is less than or equal to value 2, as long as the difference between
+	value1 and value2 is less than 1% of the larger of the absolute values of value1 and value2*/
+	public static boolean greaterThanByFactor(double value1, double value2, double factor) {
+		if (value1 == value2) 
+			return false;
+		else if (factor<=0)
+			return true;
+		else if (value2 == infinite) 
+			return false;
+		else if (value1 == negInfinite) 
+			return false;
+		else if (value2 == negInfinite) 
+			return true;
+		else if (!isCombinable(value2)) 
+			return isCombinable(value1);
+		else if (!isCombinable(value1))
+			return false;
+		else if (value2== 0 && value1 > 0) 
+			return true;
+		else if (value1== 0 || value2 == 0) 
+			return false;
+		else if (value1 > 0  && value2 < 0) //not same sign
+			return true;
+		else if (value1<0 &&  value2 > 0) //not same sign
+			return false;
+		else if (value1/value2 >= factor){
+			return true;
+		}
+		else
+			return false;
+	}
+	/** Returns true if otherValue is equal to current value or is within closeness of it*/
+	public boolean isCloseEnough(double otherValue, double closeness) {
+		if (otherValue == value) 
+			return true;
+		else if (!isCombinable(otherValue) || !isCombinable(value)) 
+			return false;
+		else if (otherValue* value < 0) //not same sign
+			return false;
+		else {
+			if (Math.abs(otherValue-value) <= closeness){
+				return true;
+			}
+			else
+				return false;
+		}
+	}
+	/** Returns true if value 1 is equal to value 2,
+	within the factor as given (i.e., if factor is 2, then this returns true if
+	value1/ value 2 is between 0.5 and 2.0)*/
+	public static boolean equalsWithinFactor(double value1, double value2, double factor) {
+		if (value1 == value2) 
+			return true;
+		else if (!isCombinable(value1) || !isCombinable(value2)) 
+			return false;
+		else if (value1== 0 || value2 == 0) 
+			return false;
+		else if (factor<=0)
+			return false;
+		else if (value1* value2 < 0) //not same sign
+			return false;
+		else {
+			if (factor< 1)
+				factor = 1/factor;
+			if (value1>value2 && Math.abs(value1/value2) < factor){
+				return true;
+			}
+			else if (value2>value1 &&  Math.abs(value2/value1) < factor){
+				return true;
+			}
+			else
+				return false;
+		}
+	}
+/** DOCUMENT */
+	public static double magnitude(double d) {
+		if (!isCombinable(d))
+			return impossible;
+		double ad = Math.abs(d);
+		double result = Math.exp(log10* (powerOfTen(ad)));
+		return result;
+	}
+	/** DOCUMENT */
+	public static int powerOfTen(double d) {
+		if (!isCombinable(d))
+			return MesquiteInteger.impossible;
+		double ad = Math.abs(d);
+		if (d<1) {
+			double t =Math.log(ad)/log10 ;
+			if (t== (int)(t))
+				return (int) (t);
+			else
+				return (int) (t-1.0);
+		}
+		else
+			return (int) (Math.log(ad)/log10);
+	}
+	/** DOCUMENT */
+	public static double nextOfMagnitude(double mag, double x) {
+		if (!isCombinable(x))
+			return impossible;
+		if (x==0)
+			return 0;
+		else if (x<0) {
+			 double y = -x;
+			 if ((int)(y/mag)<=1)
+				return 0;
+			else
+				return -mag*((int)(y/mag));			
+		}
+		else if ((int)(x/mag)<=1)
+			return mag;
+		else
+			return mag*((int)(x/mag) + 1);
+	}
+	/** DOCUMENT */
+	public static int orderOfMagnitude(double x) {
+		if (!isCombinable(x))
+			return MesquiteInteger.impossible;
+		double log10 = Math.log(10.0);
+		if (x<1)
+			return - ((int) (Math.log(1/x)/log10)+1);
+		else
+			return ((int) (Math.log(x)/log10));
+	}
+	
+	/*--------------------------------RULERS--------------------------*/
+	/** For a ruler or marked scale that is "span" long, 
+	with start point at min and at least minTicks marks, what is first scale mark? */
+	public static double firstScaleMark(double span, double min, int minTicks) {
+		if (!isCombinable(min) || !isCombinable(span))
+			return impossible;
+		double mag = magnitude(span);
+		if (span/mag < minTicks) //ensure at least this many tick marks
+			mag /= 10.0;
+		return nextOfMagnitude(mag, min);
+	}
+	/** For a ruler span long, with start point at min and at least minTicks marks, 
+	what is increment between ticks? */
+	public static double scaleIncrement(double span, double min, int minTicks) {
+		if (!isCombinable(min) || !isCombinable(span))
+			return impossible;
+		double mag = magnitude(span);
+		if (span/mag < minTicks) //ensure at least this many tick marks
+			mag /= 10.0;
+		return mag;
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string version of this value.  Returns "unassigned" etc. if needed*/
+	public String toString() {
+		return toStringDigitsSpecified(value, defaultDigits);
+	}
+	/** Appends string version of value to StringBuffer.  Uses "unassigned" etc. if needed*/
+	public static void toString(double d, StringBuffer buffer) {  
+		toStringDigitsSpecified(d, defaultDigits, buffer);
+	}
+	/** Returns string version of value.  Returns "unassigned" etc. if needed*/
+	public static String toString(double d) {  
+		return toStringDigitsSpecified(d, defaultDigits);
+	}
+	/** Returns string version of value.  Returns "unassigned" etc. if needed*/
+	public static String toStringInRange(double d, double range) {  
+		double threshold = Math.abs(range)*0.0001; //if close enough to zero compared to range, call it that
+		double absD = Math.abs(d);
+		if (absD<threshold)
+			return "0.0";
+		return toStringDigitsSpecified(d, defaultDigits);
+	}
+	/** Returns string version of value, showing the given number of digits.
+	 Returns "unassigned" etc. if needed*/
+	public String toString(int digits) {
+		return toStringDigitsSpecified(value, digits);
+	}
+	public static void toStringDecimal(double d, int digits, StringBuffer s) { 
+		if (s==null)
+			return;
+		if (d>1) {
+			MesquiteMessage.println("toStringDecimal passed number bigger than 1");
+			return;
+		}
+		double rounder = 0.5;
+		for (int i=0; i<digits; i++) {
+			rounder *= 0.1;
+		}
+		d+= rounder;
+		for (int i=0; i<digits-1; i++) {
+			s.append(Integer.toString((int)(d*10.0)));
+			d = (d*10) - (int)(d*10.0);
+		}
+		s.append( Long.toString((long)(d*10.0)));
+	}
+	/** Returns string version of value, showing the given number of digits*/
+	public static String toStringDigitsSpecified(double d, int digits) {  
+		if (d == MesquiteDouble.unassigned)
+			return "?";
+		int stringSize = digits; 
+		if (digits<0) //added 17 Dec 01 
+			stringSize = 1;
+		StringBuffer s = new StringBuffer(stringSize);
+		toStringDigitsSpecified(d, digits, s);
+		return s.toString();
+	}
+	/*.................................................................................................................*/
+	/** Returns string version of value, showing the given number of digits*/
+   	 public static String toPrecisionSpecifiedString(double value, int precision){
+  	 	DecimalFormat df = (DecimalFormat)NumberFormat.getInstance();
+  	 	df.setDecimalFormatSymbols(new EnglishDecimalFormatSymbols());
+  	 	df.setMaximumFractionDigits(precision);
+  	 	return df.format(value);
+   	 }
+	public static String toStringNoNegExponential(double d){ //added 14 apr 02 -- needs to use string buffers etc!
+		boolean neg = false;
+		if (d<0) {
+			d = -d;
+			neg = true;
+		}
+		String s = Double.toString(d);
+		if (s.indexOf("E-")>=0){ //neg exponential; move decim place to left
+			String e = s.substring(s.indexOf("E-")+2, s.length());
+			int numMoves = Integer.parseInt(e);
+			int decPlace = s.indexOf(".");
+			int extraZeros = numMoves - decPlace;
+			String qs = "0.";
+			for (int i=0; i<extraZeros; i++)
+				qs += '0';
+			char c = '\0';
+			for (int i=0; i<s.length() && c != 'E'; i++) {
+				c = s.charAt(i);
+				if (c != '.' && c != 'E')
+					qs += c;
+			}
+			s = qs;
+				
+		}
+		
+		if (neg)
+			return "-" + s;
+		else
+			return s;
+		
+	}
+	
+	/** Appends string version of value, showing the given number of digits, to StringBuffer*/
+	public static void toStringDigitsSpecified(double d, int digits, StringBuffer s) {  
+		toStringDigitsSpecified(d,digits,s, true);
+	}
+	
+	
+	/** Appends string version of value, showing the given number of digits, to StringBuffer*/
+	public static String toStringDigitsSpecified(double d, int digits, boolean allowExponentialNotation) {  
+		StringBuffer sb = new StringBuffer();
+		if (d==unassigned|| d==infinite||d==negInfinite ||d==impossible ||d==inapplicable){
+			if (d==unassigned) 
+				sb.append("?"); //changed from "unassigned" June 02
+			else if (d==infinite) 
+				sb.append("infinite");
+			else if (d==negInfinite)
+				sb.append("neg.infinite");  
+			else if (d==impossible)
+				sb.append("impossible");  
+			else if (d==inapplicable)
+				sb.append("inapplicable"); 
+			return sb.toString();
+		}
+		else if (d == 0.0){
+			sb.append("0.0");
+			return sb.toString();
+		}
+		if (d<0){
+			d = -d;
+			sb.append('-');
+		}
+		String sFromDouble;
+		
+		
+		if (digits<0){ //added 17 Dec 01.  digits < 0 signals full accuracy
+			digits=20;
+		}
+		String dec = "";
+		double lowerLimit=1.0;
+		for(int i=1; i<=digits; i++){
+			dec+="#";
+			lowerLimit*=0.1;
+		}
+		DecimalFormat myFormatter=null;
+		EnglishDecimalFormatSymbols formatSymbols = new EnglishDecimalFormatSymbols();
+		
+		if (allowExponentialNotation){
+			if (d>10000 || d<lowerLimit)
+				myFormatter = new DecimalFormat("0."+dec+"E0",formatSymbols);
+			else 
+				myFormatter = new DecimalFormat("#."+dec,formatSymbols);
+		}
+		else {
+			myFormatter = new DecimalFormat("#."+dec,formatSymbols);
+		}
+
+		sFromDouble = myFormatter.format(d);
+		if (digits==0) 
+			sFromDouble = StringUtil.removeLastCharacterIfMatch(sFromDouble, '.');
+		sb.append(sFromDouble);
+		return sb.toString();
+
+	}
+	/** Appends string version of value, showing the given number of digits, to StringBuffer*/
+	public static void toStringDigitsSpecified(double d, int digits, StringBuffer s, boolean allowExponentialNotation) {  
+		if (s==null)
+			return;
+		s.append(toStringDigitsSpecified(d,digits,allowExponentialNotation));
+	}
+	/** Appends string version of value, showing the given number of digits, to StringBuffer*/
+	public static void toStringDigitsSpecifiedOld(double d, int digits, StringBuffer s, boolean allowExponentialNotation) {  
+		if (s==null)
+			return;
+		if (d==unassigned|| d==infinite||d==negInfinite ||d==impossible ||d==inapplicable){
+			if (d==unassigned) 
+				s.append("?"); //changed from "unassigned" June 02
+			else if (d==infinite) 
+				s.append("infinite");
+			else if (d==negInfinite)
+				s.append("neg.infinite");  
+			else if (d==impossible)
+				s.append("impossible");  
+			else if (d==inapplicable)
+				s.append("inapplicable"); 
+			return;
+		}
+		if (d<0){
+			d = -d;
+			s.append('-');
+		}
+		String sFromDouble;
+		
+		
+		if (allowExponentialNotation)
+			sFromDouble = Double.toString(d);
+		else {
+			DecimalFormat myFormatter = new DecimalFormat("0.000000000000000000");
+			sFromDouble = myFormatter.format(d);
+		}
+
+		if (digits<0){ //added 17 Dec 01
+			s.append(sFromDouble);
+			return;
+		}
+		int decimalPos = sFromDouble.indexOf(".");
+		int zerosPos = -1;
+		if (digits<3)
+			zerosPos = sFromDouble.indexOf("000");
+		else if (digits<4)
+			zerosPos = sFromDouble.indexOf("0000");
+		else if (digits<5)
+			zerosPos = sFromDouble.indexOf("00000");
+		else if (digits<6)
+			zerosPos = sFromDouble.indexOf("000000");
+		else if (digits<7)
+			zerosPos = sFromDouble.indexOf("0000000");
+		else if (digits<8)
+			zerosPos = sFromDouble.indexOf("00000000");
+		else if (digits<9)
+			zerosPos = sFromDouble.indexOf("000000000");
+		int ninesPos = -1;
+		if (digits<3)
+			ninesPos = sFromDouble.indexOf("999");
+		else if (digits<4)
+			ninesPos = sFromDouble.indexOf("9999");
+		else if (digits<5)
+			ninesPos = sFromDouble.indexOf("99999");
+		else if (digits<6)
+			ninesPos = sFromDouble.indexOf("999999");
+		else if (digits<7)
+			ninesPos = sFromDouble.indexOf("9999999");
+		else if (digits<8)
+			ninesPos = sFromDouble.indexOf("99999999");
+		else if (digits<9)
+			ninesPos = sFromDouble.indexOf("999999999");
+		
+			if (decimalPos>=0 && ninesPos>decimalPos){
+				String expo = getExpo(sFromDouble);
+				if (decimalPos+1 == ninesPos) {
+					long dLong = MesquiteLong.fromString(sFromDouble.substring(0, decimalPos)) + 1;
+					sFromDouble = Long.toString(dLong) + ".0";
+				}
+				else {
+					char c = sFromDouble.charAt(ninesPos-1);
+					sFromDouble = sFromDouble.substring(0, ninesPos-1);
+					sFromDouble += (++c);
+				}
+				sFromDouble += expo;
+			}
+			else if (decimalPos>=0 && zerosPos>decimalPos){
+				String expo = getExpo(sFromDouble);
+				sFromDouble = sFromDouble.substring(0, zerosPos+1);
+				sFromDouble += expo;
+			}
+		
+		boolean countOn = false;
+		int digitCount = 0;
+
+		for (int i=0; i<sFromDouble.length(); i++){
+			char c = sFromDouble.charAt(i);
+			if (c=='.'){ //start counting digits
+				countOn = true;
+				if (digits>0)
+					s.append(c);
+			}
+			else if (c=='e' || c=='E'){ //stop counting digits
+				countOn = false;
+				s.append(c);
+			}
+			else if (countOn) { //in decimal places after "."
+				digitCount++;
+				if (digitCount == digits && i+1<sFromDouble.length()) {
+					char cNext = sFromDouble.charAt(i+1);
+                    if (cNext>='5') { //round up
+
+                        if (c=='0')
+                            s.append('1');
+                        else if (c=='1')
+                            s.append('2');
+                        else if (c=='2')
+                            s.append('3');
+                        else if (c=='3')
+                            s.append('4');
+                        else if (c=='4')
+                            s.append('5');
+                        else if (c=='5')
+                            s.append('6');
+                        else if (c=='6')
+                            s.append('7');
+                        else if (c=='7')
+                            s.append('8');
+                        else if (c=='8')
+                            s.append('9');
+                        else {
+                            s.append(c);
+                            s.append(cNext);
+                        }
+                    }
+                    else
+                        s.append(c);
+					
+				}
+				else if (digitCount<=digits){ //still within first digits
+					s.append(c);
+				}
+			}
+			else {
+				s.append(c);
+			}
+		}
+/*
+		double backTranslate = fromString(s.toString());
+		if (Math.abs(backTranslate-d)/d > 0.1)
+			MesquiteMessage.warnProgrammer("Error in double string representation: original " + d + "; string " + s 
+					+ " zerosPos " + zerosPos	+ " ninesPos " + ninesPos);
+*/
+	}
+	static String getExpo(String s){
+		if (s==null)
+			return "";
+		int e = s.indexOf("E");
+		if (e<0)
+			e = s.indexOf("e");
+		if (e<0)
+			return "";
+		return s.substring(e, s.length());
+	}
+	
+	
+	public static String toFixedWidthString(double d, int width) {
+		return toFixedWidthString(d,width,false);
+	}
+	
+	public static String toFixedWidthString(double d, int width, boolean noExponent) {
+		if (Math.abs(d) < 1)
+			return toFixedWidthString(d,width,noExponent,"0");
+		if (d>= 100000)
+			return toFixedWidthString(d,width,noExponent,"+INF");
+		// either it's small or there's no problem
+		return toFixedWidthString(d,width,noExponent,"-INF");
+	}
+
+
+	public static String toFixedWidthString(double d, int width, boolean noExponent, String failString) {
+		String myFmt;
+		String filler = "                             ";
+
+		if ((Math.abs(Math.log(Math.abs(d))/log10) >= width) && noExponent)  // is 10 the right value here???
+			return filler.substring(0,width-failString.length()) + failString;
+		else if (noExponent) {
+		 	myFmt = "%" + Integer.toString(width) + "." + Integer.toString(width-2) + "F";
+		 	String formatResult = new corejava.Format(myFmt).form(d); // force the correct width!
+		 	return formatResult;
+			}
+		else {
+	 		myFmt = "%" + Integer.toString(width) + "." + Integer.toString(width-5) + "E";
+			String formatResult =  new corejava.Format(myFmt).form(d);
+			if (formatResult.indexOf("E") >0)        
+				return  formatResult.substring(0,formatResult.length()-3) + formatResult.substring(formatResult.length()-2,formatResult.length());
+			else 
+				return formatResult;
+		}
+	}
+
+	/** Returns string version of value, showing the given number of digits*/
+	public static String OLDtoString(double d, int digits) {  
+		StringBuffer s = new StringBuffer(digits);
+		OLDtoString(d, digits, s);
+		return s.toString();
+	}
+	/** Appends string version of value, showing the given number of digits, to StringBuffer*/
+	public static void OLDtoString(double d, int digits, StringBuffer s) {  
+		if (s==null)
+			return;
+		if (d==unassigned|| d==infinite||d==negInfinite ||d==impossible ||d==inapplicable){
+			if (d==unassigned) 
+				s.append("?"); //changed from "unassigned" June 02
+			else if (d==infinite) 
+				s.append("infinite");
+			else if (d==negInfinite)
+				s.append("neg.infinite");  
+			else if (d==impossible)
+				s.append("impossible");  
+			else if (d==inapplicable)
+				s.append("inapplicable"); 
+			return;
+		}
+		int initialPosition = s.length();
+		boolean addNegative = (d<0);
+		double ad = Math.abs(d);
+		if (ad == 0.0) {
+			s.append('0');
+			s.append('.');
+			toStringDecimal(ad, digits, s);
+		}
+		else if (ad == 1.0 || (ad<1.0 && ad>0.999999999)) {
+			s.append('1');
+			s.append('.');
+			for (int i=0; i<digits-1; i++) {
+				s.append('0');
+			}
+		}
+		else if (ad>1.0) {
+			if (ad>1000000) {
+				long pow = powerOfTen(ad);
+				long first = (long)(ad/magnitude(ad)); //todo: this doesn't work for 100,000
+				if (first==0)
+					first = 1L;
+				s.append(Long.toString(first));
+				s.append('.');
+				digits--;
+				while (ad > 1 && digits>0) {
+					ad = ad - first*magnitude(ad);
+					first = (long)(ad/magnitude(ad));
+					digits--;
+					s.append( Long.toString(first));
+				}
+				s.append('e');
+				s.append(Long.toString(pow));
+			}
+			else {
+				long whole = (long) ad;
+				if (ad-whole>0.999999999)
+					whole+=1;
+				 s.append(Long.toString(whole));
+				int digitsLeft = digits - s.length() ;
+				if (digitsLeft<1) digitsLeft =1;
+				s.append('.');
+				toStringDecimal(ad - whole, digitsLeft, s);
+			}
+				
+		}
+		else {
+			if (ad < 0.001) {
+				long pow = powerOfTen(ad);
+				long first = (long)(ad/magnitude(ad));
+				s.append(Long.toString(first));
+				s.append('.');
+				ad = ad/magnitude(ad) - first;
+				toStringDecimal(ad, digits, s);
+				s.append('e');
+				s.append(Long.toString(pow));
+			}
+			else {
+				s.append('0');
+				s.append('.');
+				toStringDecimal(ad, digits, s);
+			}
+		}
+		
+		if (addNegative)
+			s.insert(initialPosition, "-");
+	}
+	
+	/** Returns double parsed from given string.  Assumes entire string is what should be parsed. */
+	public static double fromString(String s) {
+		return fromString(s, false);
+	}
+	/** Returns double parsed from given string; warns about NumberFormatException if boolean is true.
+	  Assumes entire string is what should be parsed. */
+	public static double fromString(String s, boolean warn) {
+		if (StringUtil.blank(s))
+			return impossible;
+		try {
+			double d = Double.valueOf(s).doubleValue();
+			return d;
+		}
+		catch (NumberFormatException e) {
+			if (s !=null) {
+				if (s.equals("-")) //TODO: use gap symbol
+					return inapplicable;
+				else if (s.equals("?")) //TODO: use missing symbol
+					return unassigned;
+				else if (s.equalsIgnoreCase("unassigned"))
+					return unassigned;
+				else if (s.equalsIgnoreCase("estimate"))
+					return unassigned;
+				else if (s.equalsIgnoreCase("infinite")|| s.equalsIgnoreCase("i"))
+					return infinite;
+				else if (s.equalsIgnoreCase("inapplicable"))
+					return inapplicable;
+				else if (s.equalsIgnoreCase("neg.Infinite"))
+					return negInfinite;
+				else if (s.equalsIgnoreCase("impossible"))
+					return impossible;
+			}
+			if (warn)
+				MesquiteMessage.println("NumberFormatException in parsing string \"" + s + "\"");
+			return impossible;
+		}
+	}
+	/** returns first number found in string; allows exponentials and negative numbers*/
+	public static double fromString (String sT, MesquiteInteger stringLoc) {
+  		String c = ParseUtil.getToken(sT, stringLoc);
+  		if (c!=null && c.length()>0) {
+			if (c.equals("?")) //TODO: use missing symbol
+				return unassigned;
+			else if (c.equalsIgnoreCase("unassigned"))
+				return unassigned;
+			else if (c.equalsIgnoreCase("estimate"))
+				return unassigned;
+			else if (c.equalsIgnoreCase("infinite")|| c.equalsIgnoreCase("i"))
+				return infinite;
+			else if (c.equalsIgnoreCase("inapplicable"))
+				return inapplicable;
+			else if (c.equalsIgnoreCase("neg.Infinite"))
+				return negInfinite;
+			else if (c.equalsIgnoreCase("impossible"))
+				return impossible;
+  			char clast = c.charAt(c.length()-1);
+  			if (clast == 'e' || clast == 'E') { //must be number with exponential to negative
+  				String f =ParseUtil.getToken(sT, stringLoc);
+  				c +=f;
+  				if ("-".equals(f) || "+".equals(f))
+  					c +=ParseUtil.getToken(sT, stringLoc);
+  			}
+  			else if (clast == '-') { //negative
+  				return -fromString(sT, stringLoc);
+  			}
+  		}
+  		try {
+  			double d = Double.valueOf(c).doubleValue();
+  			return d;
+  		}
+  		catch (NumberFormatException e){}
+  		catch (NullPointerException e){}
+  		return impossible;
+	}
+	/** returns first number found in string; allows exponentials and negative numbers*/
+	public static double fromString (Parser parser) {
+  		String c = parser.getNextToken();
+ 		if (c!=null && c.length()>0) {
+			if (c.equals("?")) //TODO: use missing symbol
+				return unassigned;
+			else if (c.equalsIgnoreCase("unassigned"))
+				return unassigned;
+			else if (c.equalsIgnoreCase("estimate"))
+				return unassigned;
+			else if (c.equalsIgnoreCase("infinite")|| c.equalsIgnoreCase("i"))
+				return infinite;
+			else if (c.equalsIgnoreCase("inapplicable"))
+				return inapplicable;
+			else if (c.equalsIgnoreCase("neg.Infinite"))
+				return negInfinite;
+			else if (c.equalsIgnoreCase("impossible"))
+				return impossible;
+  			char clast = c.charAt(c.length()-1);
+  			if (clast == 'e' || clast == 'E') { //must be number with exponential to negative
+  				String f =parser.getNextToken();
+  				c +=f;
+  				if ("-".equals(f) || "+".equals(f))
+  					c +=parser.getNextToken();
+  			}
+  			else if (clast == '-') { //negative
+  				return -fromString(parser);
+  			}
+  		}
+  		try {
+  			double d = Double.valueOf(c).doubleValue();
+  			return d;
+  		}
+  		catch (NumberFormatException e){}
+  		catch (NullPointerException e){}
+  		return impossible;
+	}
+	/** Returns whether a string can be interpreted as a double. */
+	public static boolean interpretableAsDouble(String s,  MesquiteInteger pos) {
+		int oldPos = pos.getValue();
+		boolean interpretable = fromString(s, pos)!= impossible;
+		pos.setValue(oldPos);
+		return interpretable;
+	}	
+	/** Returns whether a string can be interpreted as a double. */
+	public static boolean interpretableAsDouble(String s,  MesquiteInteger pos, int posToSet) {
+		int oldPos = pos.getValue();
+		if (posToSet >=0)
+			pos.setValue(posToSet);
+		boolean interpretable = fromString(s, pos)!= impossible;
+		pos.setValue(oldPos);
+		return interpretable;
+	}	
+	/*--------------------------------QUERY DIALOGS--------------------------*/
+	/** Presents dialog querying user for a double, with no check for minimum and maximum */
+	public static double queryDouble(MesquiteWindow parent, String title, String message, double current) {
+		MesquiteDouble io = new MesquiteDouble(current);
+		QueryDialogs.queryDouble(parent, title, message, io);
+		return io.getValue();
+	}
+	/** Presents dialog querying user for a double, with a check for minimum and maximum */
+	public static double queryDouble(MesquiteWindow parent, String title, String message, double current, double minimum, double maximum) {
+		return queryDouble(parent, title, message, "", current, minimum, maximum);
+	}
+	/** Presents dialog querying user for a double, with a check for minimum and maximum */
+	public static double queryDouble(MesquiteWindow parent, String title, String message, String help, double current, double minimum, double maximum) {
+		if ((current>maximum && MesquiteDouble.isCombinable(maximum) )|| (current<minimum && MesquiteDouble.isCombinable(minimum)))
+			current=minimum;
+		MesquiteDouble io = new MesquiteDouble(current);
+		if (StringUtil.blank(help))
+			help = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a number.  <p>The initial value is " + MesquiteDouble.toString(current) 
+			+ "; the minimum value permitted is " + MesquiteDouble.toString(minimum)+ " and the maximum value permitted is " + MesquiteDouble.toString(maximum);
+		boolean done=false;
+		while (!done) {
+			//DoubleDialog id = new DoubleDialog(parent, title, message, io);
+			//id.dispose();
+			QueryDialogs.queryDouble(parent,title,message,help,io);
+			if (!io.isCombinable() || (io.getValue()<=maximum && io.getValue()>=minimum))
+				done=true;
+			else {
+				MesquiteModule.mesquiteTrunk.alert("Value must be between " + MesquiteDouble.toString(minimum) + " and " + MesquiteDouble.toString(maximum));
+				io.setValue(current);
+			}
+		}
+		return io.getValue();
+	}
+	public static boolean queryTwoDoubles(MesquiteWindow parent, String title, String message1, MesquiteDouble value1, String message2, MesquiteDouble value2) {
+		return QueryDialogs.	queryTwoDoubles( parent,  title,  message1,  value1,  message2,  value2);
+
+	}
+	/** Presents dialog querying user for two doubles */
+	public static void queryTwoDoubles(MesquiteWindow parent, String title, String label1, String label2, MesquiteBoolean answer, MesquiteDouble num1, MesquiteDouble num2) {
+		 MesquiteString str1 = new MesquiteString(num1.toString());
+		 MesquiteString str2 = new MesquiteString(num2.toString());
+		 TwoStringsDialog tsd = new TwoStringsDialog(parent, title, label1, label2, answer, str1, str2,false);
+		 tsd.dispose();
+		 num1.setValue(str1.getValue());
+		 num2.setValue(str2.getValue());
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteDropListener.java b/Source/mesquite/lib/MesquiteDropListener.java
new file mode 100644
index 0000000..ed33009
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDropListener.java
@@ -0,0 +1,25 @@
+package mesquite.lib;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.io.*;
+
+public interface MesquiteDropListener {
+
+	public boolean processDroppedObject(Object obj);
+}
+
diff --git a/Source/mesquite/lib/MesquiteDropManager.java b/Source/mesquite/lib/MesquiteDropManager.java
new file mode 100644
index 0000000..b81a993
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDropManager.java
@@ -0,0 +1,133 @@
+package mesquite.lib;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/*.................................................................................................................*/
+/** A class that looks after the droplisteners for a particular target*/
+public class MesquiteDropManager {
+	protected Vector listeners;
+	public static int listenersRemaining=0;
+	int listenerRemoved = -1;
+	private static boolean checkMemory = MesquiteTrunk.checkMemory;
+	public static Vector allListeners; //for detecting memory leaks
+	static {
+		allListeners = new Vector();//for detecting memory leaks
+	}
+	public MesquiteDropManager (){
+	}
+ 	/*.................................................................................................................*/
+	/** adds a listener to notify if the element changes*/
+	public void addListener(MesquiteDropListener listener) {
+		if (listeners==null) 
+			listeners = new Vector();
+		if (listener!=null && listeners.indexOf(listener)<0) {
+			listeners.addElement(listener);
+			listenersRemaining++;
+			if (checkMemory)
+				allListeners.addElement(new DropObjectR(listener, this));
+		}
+	}
+ 	/*.................................................................................................................*/
+	/** adds a listener to notify if the element changes*/
+	public void addListenerHighPriority(MesquiteDropListener listener) {
+		if (listeners==null) 
+			listeners = new Vector();
+		if (listener!=null && listeners.indexOf(listener)<0) {
+			listeners.insertElementAt(listener, 0);
+			listenersRemaining++;
+			if (checkMemory)
+				allListeners.addElement(new DropObjectR(listener, this));
+		}
+	}
+ 	/*.................................................................................................................*/
+	/** removes a listener*/
+	public void removeListener(MesquiteDropListener listener) {
+		if (listeners!=null && listener !=null) {
+			listenerRemoved = listeners.indexOf(listener);
+			listeners.removeElement(listener);
+			listenersRemaining--;
+			if (checkMemory)
+				DropObjectR.removeMe(allListeners, listener, this);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns whether the listener is in the list of listeners*/
+	public boolean amIListening(MesquiteDropListener me) {
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteDropListener listener = (MesquiteDropListener)obj;
+	 			if (me==listener)
+	 				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	/** notifies listeners that the element, and in particular part i, has changed.  The ith part may
+ 	be the ith character (if element is a CharacterData), or the ith tree (if a TreeVector), etc..
+ 	Notifies only those elements of class clss if boolean is true; notifies only those elements not of class
+ 	clss if boolean is false*/
+	public  boolean askListenersToProcess(Object obj, boolean onlyOneProcessor) { 
+		boolean success=false;
+		if (listeners!=null) {
+				MesquiteDropListener[] ls = new MesquiteDropListener[listeners.size()];
+				for (int m=0; m<ls.length; m++)
+					ls[m]= (MesquiteDropListener)listeners.elementAt(m);
+				for (int m=0; m<ls.length; m++) {
+		 			if ( ls[m].processDroppedObject(obj))
+		 				success=true;
+		 			if (success && onlyOneProcessor)
+		 				return true;
+		 		
+	 		}
+		}
+		return success;
+	}
+	/*.................................................................................................................*/
+ 	/** Returns the number of listeners remaining that are still registered with this element.
+ 	Useful to see that listeners are removing themselves as needed. */
+	public static int getRemainingListeners(){
+		return listenersRemaining;
+	}
+	
+	
+}
+
+class DropObjectR extends ObjectContainer {
+	Object listener;
+	MesquiteDropManager listened;
+	public DropObjectR(Object listener, MesquiteDropManager listened){
+		this.listener = listener;
+		this.listened = listened;
+		setObject(listener);
+	}
+	static void removeMe(Vector allListeners, Object listener, MesquiteDropManager listened){
+		for (int i = 0; i<allListeners.size(); i++){
+			DropObjectR r = (DropObjectR)allListeners.elementAt(i);
+			if (r.listener == listener && r.listened == listened) {
+				allListeners.removeElement(r);
+				return;
+			}
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteDroppedFileHandler.java b/Source/mesquite/lib/MesquiteDroppedFileHandler.java
new file mode 100644
index 0000000..980e958
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteDroppedFileHandler.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import mesquite.lib.duties.FileInterpreter;
+
+public interface MesquiteDroppedFileHandler {
+	
+	public FileInterpreter findFileInterpreter(String droppedContents, String fileName);
+	
+	public void actUponDroppedFileContents(FileInterpreter fileInterpreter, String droppedContents);
+
+
+}
diff --git a/Source/mesquite/lib/MesquiteEvent.java b/Source/mesquite/lib/MesquiteEvent.java
new file mode 100644
index 0000000..51f9492
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteEvent.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**This class is used to look after events*/
+public class MesquiteEvent {  //DRM
+
+	public static int getModifiers(InputEvent e){
+		int mod = e.getModifiers();
+		if (e.isShiftDown())
+			mod |= InputEvent.SHIFT_MASK;
+		if (e.isAltDown())
+			mod |= InputEvent.ALT_DOWN_MASK;
+		if (e.isControlDown())
+			mod |= InputEvent.CTRL_MASK;
+		if (e.isMetaDown())
+			mod |= InputEvent.META_MASK;
+		return mod;
+	}
+	public static boolean shiftKeyDown(int modifiers) {
+		return ((modifiers & InputEvent.SHIFT_MASK)!=0);
+	}
+	public static boolean optionKeyDown(int modifiers) {
+		return ((modifiers & InputEvent.ALT_DOWN_MASK)!=0);
+	}
+	public static boolean controlKeyDown(int modifiers) {
+		return ((modifiers & InputEvent.CTRL_MASK)!=0);
+	}
+	public static boolean rightClick(int modifiers) {
+		return ((modifiers & InputEvent.CTRL_MASK)!=0) || ((modifiers & InputEvent.BUTTON2_DOWN_MASK)!=0) || ((modifiers & Event.META_MASK)!=0);
+	}
+	public static boolean commandKeyDown(int modifiers) {
+		return ((modifiers & InputEvent.META_MASK)!=0);
+	}
+	public static boolean commandOrControlKeyDown(int modifiers) {
+		return ((modifiers & InputEvent.META_MASK)!=0 || (modifiers & InputEvent.CTRL_MASK)!=0);
+	}
+	public static String modifiersToString(int modifiers){
+			String s = "";
+			if (shiftKeyDown(modifiers))
+				s+= " shift";
+			if (controlKeyDown(modifiers))
+				s+= " control";
+			else if (optionKeyDown(modifiers)) //else is here because of discord between Sun and Apple styles & Sun's overloading BUTTON2 and ALT.  Rule in Mesquite is that control option always behaves like control.  Right click therefore varies
+				s+= " option";
+			if (commandKeyDown(modifiers))
+				s+= " command";
+			 return s;
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteException.java b/Source/mesquite/lib/MesquiteException.java
new file mode 100644
index 0000000..bddee7c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteException.java
@@ -0,0 +1,32 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+public class MesquiteException extends RuntimeException{
+	public static int lastLocation = 0;
+	public static String lastCommand = "";
+	public static String lastLocMessage(){
+		if (lastLocation == 0 || StringUtil.blank(lastCommand))
+		return "";
+		return "(loc: " + lastLocation +") " + lastCommand;
+	}
+	/*
+	 * 1 - tree drawing
+	 * 100 - MousePanel
+	 */
+}
+
diff --git a/Source/mesquite/lib/MesquiteExternalProcess.java b/Source/mesquite/lib/MesquiteExternalProcess.java
new file mode 100644
index 0000000..3b9dc92
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteExternalProcess.java
@@ -0,0 +1,100 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.io.*;
+
+
+
+public class MesquiteExternalProcess  {
+	OutputStream inputToProcess;
+	OutputStreamWriter inputStreamsWriter;
+	BufferedWriter inputBufferedWriter;
+	StreamGobbler errorGobbler;
+	StreamGobbler outputGobbler;
+	Process proc;
+
+	public MesquiteExternalProcess(Process proc) {
+		this.proc = proc;
+		errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
+		outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
+		errorGobbler.start();
+		outputGobbler.start();
+
+	}
+	public MesquiteExternalProcess() {
+	}
+	/*.................................................................................................................*/
+	public Process getProcess() {
+		return proc;
+	}
+	/*.................................................................................................................*/
+
+	public void setProcess(Process proc) {
+		this.proc = proc;
+	}
+	/*.................................................................................................................*/
+	public void kill () {
+		proc.destroy();
+	}
+
+	/*.................................................................................................................*/
+
+	public void dispose() {
+		try {
+			if (inputBufferedWriter!=null)
+				inputBufferedWriter.close();
+		}
+		catch (Exception e) {
+		}
+	}
+	/*.................................................................................................................*/
+
+	public boolean processRunning() {
+		if (proc==null)
+			return false;
+		try {
+			proc.exitValue();
+		} catch (IllegalThreadStateException e) {
+			return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void sendStringToProcess(String s) {
+		if (proc==null)
+			return;
+		if (inputToProcess==null)
+			inputToProcess = proc.getOutputStream();
+		if (inputToProcess!=null && inputStreamsWriter==null)
+			inputStreamsWriter = new OutputStreamWriter(inputToProcess);
+		if (inputToProcess==null || inputStreamsWriter==null)
+			return;
+		if (inputBufferedWriter==null)
+			inputBufferedWriter = new BufferedWriter(inputStreamsWriter);
+		if (inputBufferedWriter==null)
+			return;
+		try {
+			try {
+				inputBufferedWriter.write(s);
+			} finally {
+				inputBufferedWriter.flush();
+				//	inputBufferedWriter.close();
+			} 
+		} catch (Exception e) {
+		}
+
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteFile.java b/Source/mesquite/lib/MesquiteFile.java
new file mode 100644
index 0000000..bf54097
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteFile.java
@@ -0,0 +1,3279 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import com.apple.mrj.*;
+import javax.swing.*;
+
+/* ======================================================================== */
+/**This MesquiteFile is the file on disk, not the project.*/
+public class MesquiteFile extends Listened implements HNode, Commandable, Listable, Explainable { 
+	public static final int QUERY_NONE = 0;
+	public static final int QUERY_CLOSE = 1;
+	public static final int QUERY_DELETE = 2;
+	public static final int QUERY_QUIT = 3;
+	private InputStream inStream; //DataInputStream //BufferedInputStream
+	private FileOutputStream outStream;
+	private boolean writing = false;
+	private int readCategory = -1; //0, linked; 1, include; -1 home file
+	public static final int LINKED = 0;
+	public static final int INCLUDED = 1;
+	public static final int HOME = -1;
+
+	private boolean local = true;
+	private URL url;
+	//private InputStream streamFromHeaven;
+	private String fileName,  directoryName;
+	private MesquiteInteger startChar;
+	//private String bufferString;
+	boolean bufferRead = false;
+	private MesquiteInteger pendingBrackets;
+	private MesquiteProject project=null;
+	private ListableVector fileElements;
+	private long id=0;
+	private static PrintWriter logStream = null;
+	public static int totalCreated = 0;
+	public static int totalDisposed = 0;
+	public static int totalFinalized = 0;
+	private boolean beingSaved = false;
+	private boolean closed = false;
+	private StringBuffer sB = new StringBuffer(100);
+	private boolean writeProtected = false;
+	private String comment = null;
+	boolean dirtiedByCommand = false;
+	private boolean openAsUntitled = false;
+	private boolean closeAfterReading = false;
+	private String untitledReasons ="";
+	public Vector foreignElements; //keeps list of foreign elements to report to user after file read; may be disposed immediately after report
+	public boolean useDataBlocks = false;  //todo: this is temporary until general format options system built
+	public boolean useSimplifiedNexus = false;  //todo: this is temporary until general format options system built
+	public boolean useConservativeNexus = false;  //todo: this is temporary until general format options system built
+	public boolean readMesquiteBlock = true;  //todo: this is temporary until general format options system built
+	public boolean useStandardizedTaxonNames = false;  //todo: this is temporary until general format options system built
+	public boolean interleaveAllowed = true; //todo: this is temporary until general format options system built
+	public boolean simplifyNames = false;  //todo: this is temporary until general format options system built
+	public boolean ambiguityToMissing = false;  //todo: this is temporary until general format options system built
+	public boolean writeCharLabels = false;  //todo: this is temporary until general format options system built
+	public boolean writeExcludedCharacters=true;
+	public boolean writeTaxaWithAllMissing = true;
+	public boolean writeOnlySelectedTaxa = false;
+	public String fileReadingArguments = null;
+	public int exporting = 0;  //todo: temporary.  0 = not exporting;  1 = first export; 2 = subsequent exports
+	public boolean notesBugWarn = false;
+	public Vector notesBugVector;
+	StringBuffer remnantString;
+	long filePos = 0;
+	ProgressIndicator progIndicator;
+	StringBuffer betweenCommandComments;
+	private boolean isNexus = false;
+	boolean projectClosing = false;
+	MesquiteTimer nextBlockTimer, readLineTimer, getNextCommandStatusTimer;
+	MesquiteCommand saveCommand = null;
+	//private boolean dirty = false;
+	public static String fileSeparator;
+	public static boolean appendToLog = false;
+	private byte[] lineEndingBytes;
+
+	public ListableVector taxaNameTranslationTable = new ListableVector();
+	public ListableVector characterDataNameTranslationTable = new ListableVector();
+
+	private Author previousSaver;
+
+	/*NEXUS files by PAUP convention have "current" taxa and characters blocks, namely last ones read.  
+	The following are to enable this to be supported in Mesquite.  The reference should be nulled when reading is finished to prevent memory leaks! */
+	private mesquite.lib.characters.CharacterData currentData;
+	private Taxa currentTaxa;
+
+	Parser parser;
+	static {
+		fileSeparator = System.getProperty("file.separator");
+	}
+	public MesquiteFile() {
+		id = totalCreated;
+		totalCreated++;
+		parser = new Parser();
+		remnantString = new StringBuffer(10);
+		betweenCommandComments = new StringBuffer(10);
+		pendingBrackets = new MesquiteInteger(0);
+		startChar = new MesquiteInteger(0);
+		nextBlockTimer = new MesquiteTimer();
+		readLineTimer = new MesquiteTimer();
+		try {
+			lineEndingBytes = StringUtil.lineEnding().getBytes("ISO-8859-1");
+		}
+		catch (UnsupportedEncodingException e){
+			lineEndingBytes = StringUtil.lineEnding().getBytes();
+		}
+		getNextCommandStatusTimer = new MesquiteTimer();
+	}
+	/*-------------------------------------------------------*/
+	public long getID(){
+		return id;
+	}
+	public void finalize() throws Throwable{
+		totalFinalized++;
+		super.finalize();
+	}
+
+	public void setReadCategory(int r){
+		readCategory = r;
+	}
+	//0 = linked; 1 = include; -1 = home file
+	public int getReadCategory(){
+		return readCategory;
+	}
+
+	public void setPreviousSaver(Author a){
+		previousSaver = a;
+	}
+	public Author getPreviousSaver(){
+		return previousSaver;
+	}
+	/*-------------------------------------------------------*/
+	public void setCurrentData(mesquite.lib.characters.CharacterData d){
+		currentData = d;
+	}
+	public mesquite.lib.characters.CharacterData getCurrentData(){
+		return currentData;
+	}
+	public void setCurrentTaxa(Taxa d){
+		currentTaxa = d;
+	}
+	public Taxa getCurrentTaxa(){
+		return currentTaxa;
+	}
+	/*-------------------------------------------------------*/
+	public static int getNumberOfFiles(){
+		return totalCreated;
+	}
+
+	public String getOpenAsUntitled(){
+		if (openAsUntitled)
+			return untitledReasons;
+		return null;
+	}
+	public void setOpenAsUntitled(String reason){
+		openAsUntitled = true;
+		untitledReasons += "\n" + reason;
+	}
+	/*-------------------------------------------------------*/
+	public boolean getCloseAfterReading(){
+		return closeAfterReading;
+	}
+	public void setCloseAfterReading(boolean c){
+		closeAfterReading = c;
+	}
+	/*-------------------------------------------------------*/
+	public void setBeingSaved(boolean s){
+		beingSaved = s;
+	}
+	/*-------------------------------------------------------*/
+	public boolean getBeingSaved(){
+		return beingSaved;
+	}
+	/*-------------------------------------------------------*/
+	public void setIsNexus(boolean s){
+		isNexus = s;
+	}
+	/*-------------------------------------------------------*/
+	public boolean isClosed(){
+		return closed;
+	}
+	/*-------------------------------------------------------*/
+	/** for development purposes; to time file reading //TODO: get rid of this in final*/
+	public void reportTimes() {
+		MesquiteMessage.println("Time in getNextBlock: " + nextBlockTimer.getAccumulatedTime());
+		MesquiteMessage.println("Time for readLine: " + readLineTimer.getAccumulatedTime());
+		MesquiteMessage.println("Time for getNextCommand(status): " + getNextCommandStatusTimer.getAccumulatedTime());
+	}
+
+	/*.................................................................................................................*/
+	/** The method by which commands are sent to the file using text-based scripting.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(this.getClass(), "Returns identification number of this file", null, commandName, "getID")) {
+			return new MesquiteInteger((int)getID());
+		}
+		else if (checker.compare(this.getClass(), "Returns coordinator module of project", null, commandName, "getCoordinatorModule")) {
+			if (project!=null)
+				return project.getCoordinatorModule();
+		}
+		else  if (checker.compare(this.getClass(), "Closes this file", null, commandName, "close")) {
+			if (project!=null && project.getCoordinatorModule()!=null)
+				project.getCoordinatorModule().closeFile(this);
+		}
+		else  if (checker.compare(this.getClass(), "Saves this file", null, commandName, "save")) {
+			if (project!=null && project.getCoordinatorModule()!=null)
+				project.getCoordinatorModule().saveFile(this);
+		}
+		else  if (checker.compare(this.getClass(), "Saves this file as", null, commandName, "saveAs")) {
+			if (project!=null && project.getCoordinatorModule()!=null)
+				project.getCoordinatorModule().saveFileAs(this);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns size of existing file on disk corresponding to this MesquiteFile*/
+	public long existingLength() {
+		if (local) {
+			String path =directoryName+fileName;
+			File testing = new File(path);
+			return testing.length();
+		}
+		return 0;
+	}	
+
+	public String toString() {
+		return "File \"" + fileName + "\" in directory \"" + directoryName + "\", id " + getID();
+	}
+
+	/*-------------------------------------------------------*/
+	/** if not applet, opens new file on disk with given name */
+	public static MesquiteFile newFile(String directoryName, String fileName) {
+		if (!MesquiteTrunk.isApplet()) {
+			//test to see if directory exists
+			MesquiteFile mF = new MesquiteFile();
+			mF.local = true;
+			mF.fileName = fileName;
+			mF.directoryName = directoryName;
+			return mF;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static boolean createDirectory(String path){
+		if (!MesquiteFile.fileOrDirectoryExists(path)) {
+			String containing = StringUtil.getAllButLastItem(path, "/");
+			String containing2 = StringUtil.getAllButLastItem(path, fileSeparator);
+			// use longest string that is not the same size as the original path
+			if (containing.length()>=  path.length()){  //can't use containing
+				if (containing2.length()< path.length()) //only containing2 is shorter; use it
+					containing = containing2;
+				else return false;  //can't use either 
+			}
+			else if (containing2.length()>= path.length())//both are too long
+				return false;
+			else if (containing2.length()>containing.length()) //neither too long; therefore take longest
+				containing = containing2;
+
+			createDirectory(containing);
+			File f = new File(path);
+			boolean b = f.mkdir();
+			return b;
+		} 
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** A basic method for copying one File to another; if the destination file does not exist, it will be created */
+	public static void copy(File src, File dst) throws IOException {
+		InputStream in = new FileInputStream(src);
+		OutputStream out = new FileOutputStream(dst);
+
+		// Transfer bytes from in to out
+		byte[] buf = new byte[1024];
+		int len;
+		while ((len = in.read(buf)) > 0) {
+			out.write(buf, 0, len);
+		}
+		in.close();
+		out.close();
+	}
+
+
+	/*.................................................................................................................*/
+	/** A basic method for copying one File to another; if the destination file does not exist, it will be created */
+	public static void copyFileFromPaths(String originalPath, String newPath, boolean warn) {
+		if (StringUtil.blank(originalPath) || StringUtil.blank(newPath))
+			return;
+		try { 
+			File originalFile = new File(originalPath); //
+			File newFile = new File(newPath); //
+			MesquiteFile.copy(originalFile, newFile);
+		}
+		catch (IOException e) {
+			if (warn)
+				MesquiteMessage.println("Can't copy file \n    " + originalPath + "\nto\n    " + newPath);
+		}
+	}
+
+
+	/*-------------------------------------------------------*/
+	/** if not applet, allows user to choose, then opens existing file on disk */
+	public static MesquiteFile open(boolean local, FilenameFilter fileFilter, String message, String suggestedDirectory) {
+		if (local) {
+
+			if (!MesquiteTrunk.isApplet()) {
+				MainThread.incrementSuppressWaitWindow();
+				MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.LOAD);
+				fdlg.setResizable(true);
+				if (suggestedDirectory !=null)
+					fdlg.setDirectory(suggestedDirectory);
+				fdlg.setBackground(ColorTheme.getInterfaceBackground());
+				if (fileFilter!=null)
+					fdlg.setFilenameFilter(fileFilter);
+
+				fdlg.setVisible(true);
+
+				String fName=fdlg.getFile();
+				String dName =fdlg.getDirectory();
+				String pathName=dName + fName;
+				//fdlg.dispose();
+				MainThread.decrementSuppressWaitWindow();
+				if (!StringUtil.blank(fName) && !StringUtil.blank(dName)) {
+					MesquiteFile mF = new MesquiteFile();
+					mF.local = true;
+					mF.fileName = fName;
+					mF.directoryName = dName;
+					return mF;
+				}
+				if (StringUtil.blank(dName) &&  StringUtil.blank(fName))
+					MesquiteTrunk.mesquiteTrunk.logln("Open File cancelled by user");
+				else if ( StringUtil.blank(fName))
+					MesquiteTrunk.mesquiteTrunk.logln("Open File not completed because file name not supplied.");
+				else if ( StringUtil.blank(dName))
+					MesquiteTrunk.mesquiteTrunk.logln("Open File not completed because directory name not supplied.");
+
+			}
+		}
+		else {
+			String s= MesquiteString.queryString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Open URL", "URL to open:", "");
+			URL url=null;
+			if (!StringUtil.blank(s)) {
+				try {
+					url = new URL(s);
+					MesquiteFile mF = new MesquiteFile();
+					mF.local = false;
+					mF.url= url;
+					String urlString = url.toString();
+					mF.fileName = StringUtil.getLastItem(urlString, fileSeparator, "/"); 
+					mF.directoryName = StringUtil.getAllButLastItem(urlString, fileSeparator, "/") + fileSeparator; 
+
+					return mF;
+				}
+				catch (MalformedURLException e) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"Bad URL specified for data file: \"" + s + "\"");}
+			}
+		}
+		return null;
+	}
+	/*-------------------------------------------------------*/
+	/** opens existing file on disk or URL*/
+	public static MesquiteFile open(boolean local, String location) {
+		if (StringUtil.blank(location))
+			return open(local, (FilenameFilter)null, "Open file:", null);
+		else if (local) {
+			if (!MesquiteTrunk.isApplet()) {
+				String fName = StringUtil.getLastItem(location, fileSeparator, "/"); 
+				String dName = StringUtil.getAllButLastItem(location, fileSeparator, "/") + fileSeparator; 
+				return open(dName, fName);
+			}
+		}
+		else {
+			URL url=null;
+			if (!StringUtil.blank(location)) {
+				try {
+					url = new URL(location);
+					return open(url);
+				}
+				catch (MalformedURLException e) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"Bad URL specified for data file: \"" + location + "\"");}
+			}
+		}
+		return null;
+	}
+	/*-------------------------------------------------------*/
+	/** opens existing file on disk or URL*/
+	public static MesquiteFile open(boolean local, String location, String suggestedDirectory) {
+		return open(local, location, "Open file:", suggestedDirectory);
+	}
+
+	/*-------------------------------------------------------*/
+	/** opens existing file on disk or URL*/
+	public static MesquiteFile open(boolean local, String location, String message, String suggestedDirectory) {
+		if (StringUtil.blank(location))
+			return open(local, (FilenameFilter)null, message, suggestedDirectory);
+		else if (local) {
+			if (!MesquiteTrunk.isApplet()) {
+				String fName = ""; 
+				String dName = ""; 
+				if (location.indexOf(fileSeparator) <0 && location.indexOf("/")<0)
+					fName = location;
+				else {
+					fName = StringUtil.getLastItem(location, fileSeparator, "/"); 
+					dName = StringUtil.getAllButLastItem(location, fileSeparator, "/") + fileSeparator; 
+				}
+				return open(dName, fName);
+			}
+		}
+		else {
+			URL url=null;
+			if (!StringUtil.blank(location)) {
+				try {
+					url = new URL(location);
+					return open(url);
+				}
+				catch (MalformedURLException e) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"Bad URL specified for data file: \"" + location + "\"");}
+			}
+		}
+		return null;
+	}
+	/*-------------------------------------------------------*/
+	/** if not applet, opens existing file on disk with given name */
+	public static MesquiteFile open(String directoryName, String fileName) {
+		if (!fileExists(directoryName+ fileName))  {
+			if (StringUtil.blank(directoryName))
+				directoryName = MesquiteTrunk.suggestedDirectory;
+			else if (directoryName.endsWith(fileSeparator) || directoryName.endsWith("/"))
+				directoryName = MesquiteTrunk.suggestedDirectory + directoryName;
+			else
+				directoryName = MesquiteTrunk.suggestedDirectory + directoryName + fileSeparator;  //Dec 2013 this was backwards!
+				
+
+
+		}
+		if ((directoryName.indexOf("//")<0) && fileExists(directoryName+ fileName)) { //Dec 2013 added check on double //
+			MesquiteFile mF = new MesquiteFile();
+			mF.local = true;
+			mF.fileName = fileName;
+			mF.directoryName = directoryName;
+			return mF;
+		}
+		MesquiteModule.mesquiteTrunk.discreetAlert(MesquiteThread.isScripting(), "File Busy or Not Found  (0): \ndirectory <" + directoryName + "> \nfile <" + fileName + ">");
+		return null;
+	}
+	/*-------------------------------------------------------*/
+	/** opens existing file at given URL */
+	public static MesquiteFile open(URL url) {
+		MesquiteFile mF = new MesquiteFile();
+		mF.local = false;
+		mF.url= url;
+		String urlString = url.toString();
+		mF.fileName = StringUtil.getLastItem(urlString, fileSeparator, "/"); 
+		mF.directoryName = StringUtil.getAllButLastItem(urlString, fileSeparator, "/") + fileSeparator; 
+		return mF;
+	}
+	/*-------------------------------------------------------*/
+	/** opens an input stream, e.g. if Mesquite is acting as a servlet *
+	public static MesquiteFile open(InputStream streamFromHeaven) {
+		MesquiteFile mF = new MesquiteFile();
+		mF.local = false;
+		mF.url= null;
+		mF.streamFromHeaven = streamFromHeaven;
+		mF.fileName = null;
+		mF.directoryName = null;
+		return mF;
+	}
+	/*-------------------------------------------------------*/
+	public boolean isDirty(){
+		if (dirtiedByCommand) {
+			return true;
+		}
+		if (fileElements!=null){
+			Enumeration e = fileElements.elements();
+			while (e.hasMoreElements()) {
+				FileElement elem = (FileElement)e.nextElement();
+				if (elem.getDirty()) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	/*-------------------------------------------------------*/
+	/** Closes the file and removes from the project all file elements belonging to it.*/
+	public boolean close() {
+		if (MesquiteTrunk.checkMemory)
+			MesquiteTrunk.mesquiteTrunk.logln(">= Closing file " + getName() + " =<");
+		try {
+			while (beingSaved) {
+				Thread.sleep(50);
+			}
+		}
+		catch(InterruptedException e){}
+		boolean dirty = false;
+		try {
+			if (fileElements!=null){
+				project.incrementProjectWindowSuppression();
+				int numElements = fileElements.size();
+				Enumeration eD = fileElements.elements();
+				int numDisposed=0;
+				int numToDispose = calcNumToDispose();
+				boolean didOne;
+				while (numToDispose>0 /*&& lastNumToDispose != numToDispose*/) {
+					didOne=false;
+					numToDispose = calcNumToDispose();
+					if (numToDispose>0){
+						Enumeration eDd = fileElements.elements();
+						while (eDd.hasMoreElements()) {
+							FileElement elem = (FileElement)eDd.nextElement();
+							elem.projectClosing = projectClosing;
+							if (projectClosing)
+								elem.incrementNotifySuppress();
+							elem.dispose();
+							if (!elem.isDoomed())
+								MesquiteMessage.warnProgrammer("oops, deleted element not marked as doomed");
+							numDisposed++;
+							project.removeFileElement(elem);
+							numToDispose--;
+							didOne = true;
+						}
+						if (!didOne)
+							MesquiteMessage.warnProgrammer("oops, cycle none disposed");
+					}
+				}
+				if (numElements!= numDisposed && fileElements.size()>0) {
+					MesquiteMessage.warnProgrammer("Number elements disposed (" + numDisposed + ") not same as number reference (" + numElements + ") in file " + getName());
+					Enumeration eDe = fileElements.elements();
+					while (eDe.hasMoreElements()) {
+						FileElement elem = (FileElement)eDe.nextElement();
+						if (!elem.isDisposed())
+							MesquiteMessage.warnProgrammer("    Not disposed: " + elem.getName() + " of class " + elem.getClass().getName());
+					}
+				}
+				fileElements.removeAllElements(false);
+				fileElements.dispose();
+				fileElements = null;
+				project.decrementProjectWindowSuppression();
+			}
+		}
+		catch (NullPointerException e){
+		}
+		project.removeFile(this);
+		closed = true;
+		project = null;
+		MesquiteTrunk.mesquiteTrunk.resetAllMenuBars();
+		totalDisposed++;
+		dispose();
+		return true;
+	}
+
+	int calcNumToDispose(){
+		int numToDispose = 0;
+		for (int i=0; i<fileElements.size(); i++){
+			FileElement elem = (FileElement)fileElements.elementAt(i);
+			if (elem != null && !elem.isDoomed())
+				numToDispose++;
+		}
+		return numToDispose;
+	}
+	boolean justCleaned = false;
+	/*-------------------------------------------------------*/
+	public void setDirtiedByCommand(boolean dirtied){
+		dirtiedByCommand = dirtied;
+	}
+	/*-------------------------------------------------------*/
+	/** Closes the file, removes from the project all file elements belonging to it, and deletes it.*/
+	public boolean closeAndDelete(){
+		close();
+		return deleteFile(directoryName + fileName);
+	}
+	/*.................................................................................................................*/
+	/** Downloads the file present at the ftp URL urlString, saves the file into the local directory at localSaveDirectoryPath,
+	in the file localSaveName.  If localSaveName is blank, then it saves the file name given in the URL.*/
+	public static boolean downloadFTPorHTTPFile(String urlString, String localSaveDirectoryPath, String localSaveName){
+		//    first, acquire the name of the remote file 
+		if (StringUtil.blank(urlString))
+			return false;
+		if (!(urlString.toLowerCase().startsWith("ftp://") || urlString.toLowerCase().startsWith("http://") || urlString.toLowerCase().startsWith("https://"))) {
+			return false;
+		}
+		String fileName = "downloadedFile";
+		if (!StringUtil.blank(localSaveName)) {
+			fileName = localSaveName;
+		} else {
+			fileName = urlString;
+			while (fileName.indexOf("/")>=0)
+				fileName = fileName.substring(fileName.indexOf("/")+1, fileName.length());
+			if (StringUtil.blank(fileName))
+				fileName = "downloadedFile";
+		}
+
+
+		try { 
+			//    now, down load the remote file 
+			URL ftp = new URL(urlString); 
+			URLConnection conn = ftp.openConnection (); 
+			final int BUF_SIZE = 4096; 
+			byte[] buf = new byte[BUF_SIZE]; 
+			DataInputStream inStream = new DataInputStream(conn.getInputStream()); //, BUF_SIZE); 
+
+			//    write the file locally 
+			FileOutputStream outStream = new FileOutputStream(localSaveDirectoryPath + MesquiteFile.fileSeparator + fileName); 
+			int bytesRead = -1; 
+			int count=0;
+			while ((bytesRead = inStream.read(buf, 0, BUF_SIZE)) > -1) { 
+
+				outStream.write(buf, 0, bytesRead); 
+			} 
+			outStream.close(); 
+			inStream.close(); 
+			MesquiteModule.mesquiteTrunk.logln(" ");
+			MesquiteModule.mesquiteTrunk.logln("File " + fileName + " downloaded");
+		} 
+		catch(Exception e) { 
+			MesquiteModule.mesquiteTrunk.logln("File " + fileName + " could not be downloaded");
+			MesquiteModule.mesquiteTrunk.logln("Exception: " + e.toString());
+			e.printStackTrace(); 
+			return false;
+		} 
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Downloads the file present at the ftp URL urlString, saves the file into the local directory at localSaveDirectoryPath,
+	using the file name given in the URL.*/
+	public static boolean downloadFTPorHTTPFile(String urlString, String localSaveDirectoryPath){
+		return downloadFTPorHTTPFile(urlString,localSaveDirectoryPath,null);
+	}
+	/*-------------------------------------------------------*/
+	/** A low-level call to change various location parameters.  Shouldn't be used too liberally; changeLocation does more housekeeping.*/
+	public void setLocs(boolean local, URL url, String f, String d){
+		this.local = local;
+		this.url = url;
+		this.fileName = f;
+		this.directoryName = d;
+	}
+	/*-------------------------------------------------------*/
+	/** A low-level call to change fileName.  Shouldn't be used too liberally; changeLocation does more housekeeping.*/
+	public void setPath(String path) {
+		if (path==null)
+			return;
+		if (path.indexOf(MesquiteFile.fileSeparator)<0) {
+			fileName =path;
+		}
+		else {
+			directoryName = StringUtil.getAllButLastItem(path, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			fileName = StringUtil.getLastItem(path, MesquiteFile.fileSeparator, "/");
+		}
+	}
+	/*-------------------------------------------------------*/
+	/** Returns path to file on disk  19 Jan 02*/
+	public String getPath() {
+		if (local) {
+			return directoryName+fileName;
+		}
+		return null;
+	}	
+	public void setFileName(String fileName){
+		this.fileName = fileName;
+	}
+	/*-------------------------------------------------------*/
+	/** redirects place at which file will be rewritten; for use by save as */
+	public void changeLocation(String directoryName, String fileName) {
+		this.fileName =fileName;
+		this.directoryName=directoryName;
+		MesquiteWindow.resetAllTitles();
+		MesquiteModule.resetAllMenuBars();
+		if (getHShow()) {
+			MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteFile.class);
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		}
+	}
+	/*-------------------------------------------------------*/
+	/** for use by save as; user puts file.  Returns true if new location successfuly found */
+	public boolean changeLocation(String message) {
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.SAVE);
+		fdlg.setResizable(true);
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setFile(fileName);
+		fdlg.setVisible(true);
+		String tempFileName=fdlg.getFile();
+		String tempDirectoryName=fdlg.getDirectory();
+		// fdlg.dispose();
+		MainThread.decrementSuppressWaitWindow();
+		if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+			fileName=tempFileName;
+			directoryName=tempDirectoryName;
+			MesquiteWindow.resetAllTitles(); //TODO: should also send out message to all modules thatfilename changed
+			MesquiteModule.resetAllMenuBars();
+			if (getHShow()) {
+				MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteFile.class);
+				if (getProject() != null)
+					getProject().refreshProjectWindow();
+			}
+			return true;
+		}
+		else {
+			if (StringUtil.blank(tempDirectoryName) &&  StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As cancelled by user");
+			else if ( StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As not completed because file name not supplied.");
+			else if ( StringUtil.blank(tempDirectoryName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As not completed because directory name not supplied.");
+			return false;
+		}
+	}
+	/*-------------------------------------------------------*/
+	/** for use by save as; user puts file.  Returns new location */
+	public static String saveFileAsDialog(String message) {
+		return saveFileAsDialog(message, null);
+	}
+
+	/*-------------------------------------------------------*/
+	/** for use by save as; user puts file.  Returns new location */
+	public static String saveFileAsDialog(String message, StringBuffer fileNameBuffer) {
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.SAVE);
+		fdlg.setResizable(true);
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setVisible(true);
+		String tempFileName=fdlg.getFile();
+		if (fileNameBuffer != null)
+			fileNameBuffer.append(tempFileName);
+		String tempDirectoryName=fdlg.getDirectory();
+		// fdlg.dispose();
+		MainThread.decrementSuppressWaitWindow();
+		if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+			return tempDirectoryName + tempFileName;
+		}
+		else {
+			if (StringUtil.blank(tempDirectoryName) &&  StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As cancelled by user");
+			else if ( StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As not completed because file name not supplied.");
+			else if ( StringUtil.blank(tempDirectoryName))
+				MesquiteTrunk.mesquiteTrunk.logln("Save As not completed because directory name not supplied.");
+			return null;
+		}
+	}
+	/*-------------------------------------------------------*/
+	/** To choose a directory; returns path */
+	public static String chooseDirectory(String message) {
+		return chooseDirectory(message, null);
+	}
+	/*-------------------------------------------------------*/
+	/** To choose a directory; returns path */
+	public static String chooseDirectory(String message, String suggestedDir) {
+		MainThread.incrementSuppressWaitWindow();
+		String tempFileName=null;
+		String tempDirectoryName=null;
+		if (!MesquiteWindow.GUIavailable ||  MesquiteWindow.suppressAllWindows || (MesquiteTrunk.isMacOS() && MesquiteTrunk.isJavaVersionLessThan(1.4))) {
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, 3);
+			fdlg.setResizable(true);
+			if (suggestedDir != null)
+				fdlg.setDirectory(suggestedDir);
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setVisible(true);
+			tempFileName=fdlg.getFile();
+			tempDirectoryName=fdlg.getDirectory();
+			// fdlg.dispose();
+		}
+		else	if (MesquiteTrunk.isMacOS() || MesquiteTrunk.isMacOSX()) {  
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.LOAD);
+			System.setProperty("apple.awt.fileDialogForDirectories", "true");
+			fdlg.setResizable(true);
+			if (suggestedDir != null)
+				fdlg.setDirectory(suggestedDir);
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setVisible(true);
+			tempFileName=fdlg.getFile();
+			if (tempFileName==null)
+				tempDirectoryName=null;
+			else
+				tempDirectoryName=fdlg.getDirectory();
+
+			// fdlg.dispose();
+			System.setProperty("apple.awt.fileDialogForDirectories", "false");
+		}
+		else {
+			JFileChooser fdlg;
+
+			if (suggestedDir != null) {
+				fdlg= new JFileChooser(new File(suggestedDir));
+			}
+			else
+				fdlg= new JFileChooser();
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setDialogTitle(message);
+			fdlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+			int returnValue = fdlg.showOpenDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule().getParentFrame());
+			if (returnValue == JFileChooser.APPROVE_OPTION){
+				tempDirectoryName = fdlg.getSelectedFile().getAbsolutePath();
+				tempFileName = null;
+			}
+		}
+		MainThread.decrementSuppressWaitWindow();
+		if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName))
+			return tempDirectoryName + tempFileName;
+		if (!StringUtil.blank(tempDirectoryName))  
+			return tempDirectoryName;
+		return null;
+	}
+	/*-------------------------------------------------------*/
+	/** for use by open; chooses file.  Returns full path and also separate directory and file names in MesquiteStrings */
+	public static String openFileDialog(String message, MesquiteString directoryName, MesquiteString fileName) {
+
+
+		if (message == null)
+			message = "Select file";
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.LOAD);
+		fdlg.setResizable(true);
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setVisible(true);
+		String tempFileName=fdlg.getFile();
+		String tempDirectoryName=fdlg.getDirectory();
+		// fdlg.dispose();
+		MainThread.decrementSuppressWaitWindow();
+		if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+			if (directoryName!=null)
+				directoryName.setValue(tempDirectoryName);
+			if (fileName!=null)
+				fileName.setValue(tempFileName);
+			return tempDirectoryName + tempFileName;
+		}
+		else {
+			if (StringUtil.blank(tempDirectoryName) &&  StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Open File cancelled by user");
+			else if ( StringUtil.blank(tempFileName))
+				MesquiteTrunk.mesquiteTrunk.logln("Open File not completed because file name not supplied.");
+			else if ( StringUtil.blank(tempDirectoryName))
+				MesquiteTrunk.mesquiteTrunk.logln("Open File not completed because directory name not supplied.");
+			return null;
+		}
+
+	}
+	/*-------------------------------------------------------*/
+	/** returns true if file is local (on disk), false if remote (via URL).*/
+	public boolean isLocal(){
+		return local;
+	}
+	/*-------------------------------------------------------*/
+	/** sets the project to which the MesquiteFile belongs.*/
+	public void setProject(MesquiteProject proj) {
+		project = proj;
+	}
+	/*-------------------------------------------------------*/
+	/** gets the project to which the MesquiteFile belongs.*/
+	public MesquiteProject getProject(){
+		return project;
+	}
+	/*-------------------------------------------------------*/
+	/** Opens the file for reading.*/
+	public boolean openReading(boolean warn) {
+		remnantString.setLength(0);
+		if (local) {
+			try {
+				inStream = new DataInputStream(new FileInputStream(directoryName + fileName)); //this had been BufferedInputStream with buffer 1024 but this caused OutOfMemoryErrors on large files, at least on OS X
+				filePos = 0;
+				currentByte = 0;
+				bytesAvailable = 0;
+				return true;
+			}
+			catch( FileNotFoundException e ) {
+				if (warn) {
+					MesquiteMessage.printStackTrace();
+					MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File Busy or Not Found (1): \ndirectory <" + directoryName + "> \nfile <" + fileName + ">");
+				}
+				} 
+			catch( IOException e ) {
+				if (warn){
+					MesquiteMessage.printStackTrace();
+					MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"IO exception in openReading (local) for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage());
+				}
+				}
+		}
+		else {
+			if (url!=null) {
+				try {
+					inStream = new DataInputStream(url.openStream()); //, 1024);
+					filePos = 0;
+					currentByte = 0;
+					bytesAvailable = 0;
+					return true;
+				}
+				catch( IOException e ) {
+					if (warn){
+						MesquiteMessage.printStackTrace();
+						MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"IO exception in openReading (url) for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage() );
+					}
+					}
+			}
+			/*else if (streamFromHeaven !=null) {
+
+					inStream = new DataInputStream(streamFromHeaven); //, 1024);
+					filePos = 0;
+					currentByte = 0;
+					bytesAvailable = 0;
+					return true;
+
+			}*/
+
+		}
+		return false;
+	}
+	/*-------------------------------------------------------*/
+	/** Opens the file for reading.*/
+	public boolean openReading() {
+		return openReading(true);
+	}
+	/*-------------------------------------------------------*/
+	/** Closes the file for reading.*/
+	public void closeReading() {
+		try {
+			currentData = null;
+			currentTaxa = null;
+			if (progIndicator!=null)
+				progIndicator.goAway();
+			progIndicator = null;
+			if (inStream!=null){
+				inStream.close();
+			}
+			inStream = null;
+			filePos = 0;
+			currentByte = 0;
+			bytesAvailable = 0;
+		}
+		catch( IOException e ) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "IO exception in closeReading for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage() );}
+	}
+
+	/*-------------------------------------------------------*/
+	/*if autoCopySuffix is non null, then subsequent writing saves as special temporary copy with that sring embedded in its name, 
+	 * which closeWriting does not erase or rename into old name, and the saved name is available immediately after within autoCopyName
+	 * */
+	String autoCopySuffix = null; 
+	String autoCopyName = null;
+	public void setWriteAsAutoCopy(String autoCopySuffix){
+		autoCopyName = null;
+		this.autoCopySuffix = autoCopySuffix;
+	}
+	public String getAutoCopySuffix(){
+		return autoCopySuffix;
+	}
+	public String getTempAutoCopyName(){
+		return autoCopyName;
+	}
+
+	/*-------------------------------------------------------*/
+	String tempFileName;
+	String writingFileName, backupDirPath, backupFileName;
+
+	/** Open file for writing. */
+	public boolean openWriting(boolean ascii) {
+		if (writeProtected) {
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "File is write protected <" + directoryName + "> \nfile <" + fileName + ">"  );
+			return false;
+		}
+		writing = true;
+		MesquiteModule.mesquiteTrunk.logln( "Saving File: " + fileName);
+		if (directoryName !=null) {
+			writingFileName = directoryName + fileName;
+			backupDirPath = directoryName + "backups" + fileSeparator;
+			backupFileName = backupDirPath + fileName;
+			MesquiteModule.mesquiteTrunk.logln( "In Directory: " + directoryName);
+		}
+		else {
+			writingFileName = fileName;
+			backupDirPath = "backups" + fileSeparator;
+			backupFileName = "backups" + fileSeparator + fileName;
+		}
+		if (fileExists(writingFileName) && !canWrite(writingFileName)){
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File cannot be written.  It may be locked or open in another application. (1; Path: " + writingFileName + ")"); 
+
+			return false;
+		}
+		int tempNumber = 1;
+		String ac = "T";
+		if (autoCopySuffix != null)
+			ac = autoCopySuffix;
+		autoCopyName = null;
+		while (new File(tempFileName= (writingFileName + ac + (tempNumber++))).exists())
+			;
+
+		try {
+			/*
+			if (ascii && System.getProperty("os.name").startsWith("Mac"))
+				outStream = new OutputStreamWriter(new FileOutputStream(tempFileName), "ASCII");
+			else
+			 */
+			outStream = new FileOutputStream(new File(tempFileName));  //PrintWriter
+			return true;
+		}
+		catch( FileNotFoundException e ) {
+			MesquiteMessage.printStackTrace();
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File Busy or Not Found  (2): \ndirectory <" + directoryName + "> \nfile <" + fileName + "> "  + tempFileName);
+		} 
+		catch( IOException e ) {
+			MesquiteMessage.printStackTrace();
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"IO exception in openWriting for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage());
+		}
+		return false;
+	}
+
+	/*-------------------------------------------------------*/
+	/** Write string to file and add newline character. */
+	public void writeLine(String s)
+	{	
+		if (outStream!=null){
+			try {
+
+				byte[] sBytes = s.getBytes("ISO-8859-1");
+
+				outStream.write(sBytes); 
+				outStream.write(lineEndingBytes); //was '\n'
+				outStream.flush();
+			}
+			catch (IOException ioe){}
+		}
+		else
+			MesquiteMessage.printStackTrace("ERROR: attempt to write to null stream");
+	}
+	/*-------------------------------------------------------*/
+	/** Write string to file */
+	public void write(String s)
+	{	
+		if (outStream!=null){
+			try {
+				byte[] sBytes = s.getBytes("ISO-8859-1");
+
+				outStream.write(sBytes); 
+				outStream.flush();
+
+			}
+			catch (IOException ioe){}
+		}
+		else
+			MesquiteMessage.printStackTrace("ERROR: attempt to write to null stream");
+	}
+	/*-------------------------------------------------------*/
+	/** Close file for writing */
+	public void closeWriting() {
+		closeWriting(0);
+	}
+	/*-------------------------------------------------------*/
+	/** Close file for writing */
+	public void closeWriting(int numBackups) {
+		if (outStream!=null){
+			try {
+				outStream.close();
+				if (writingFileName == null)
+					return;
+				File writingFile = new File(writingFileName);
+				String setFileType = "MESQ";
+				if (isNexus && writingFile.exists()){
+					try {
+						MRJOSType type = MRJFileUtils.getFileCreator(writingFile);
+						String ts = null;
+						if (type !=null)
+							ts = type.toString();
+
+						if  (type != null && !StringUtil.blank(ts)) {
+							setFileType = ts;
+						}
+					}
+					catch (Throwable t){
+					}
+				}
+				if (autoCopySuffix == null && numBackups>0){
+					File bkpDir = new File(backupDirPath);
+					bkpDir.mkdirs();
+					for (int i = numBackups-1; i>0; i--) {
+						MesquiteFile.rename(backupFileName + "BKP"  + (i), backupFileName + "BKP"  + (i+1));
+					}
+					MesquiteFile.rename(writingFileName, backupFileName + "BKP1");
+
+
+				}
+				else if (autoCopySuffix == null)
+					writingFile.delete();
+				if (autoCopySuffix != null){
+					autoCopyName = tempFileName;
+				}
+				else {
+					writingFile = new File(writingFileName); //not sure if needed
+					if (!MesquiteFile.rename(tempFileName, writingFileName)){
+
+						MesquiteMessage.warnProgrammer("The temporary file " + tempFileName + " could not be renamed to " + writingFileName + ". The operating system claims you do not have permission to modify one or the other file.");
+						if (MesquiteTrunk.isWindows())
+							MesquiteMessage.warnProgrammer("If you are working on a Windows machine, you may have modified the original file with another program, which may mysteriously prevent you from modifying it in Mesquite.  This appears to be a bug in Windows.   Try duplicating the file, or using Save As in Mesquite to make a new copy of the file which should be free of the problem, or using another operating system.");
+					}
+					try {MRJFileUtils.setFileTypeAndCreator(writingFile, new MRJOSType("TEXT"), new MRJOSType(setFileType));}
+					catch (Throwable t){}
+				}
+			}
+			catch (IOException ioe){}
+		}
+		else
+			MesquiteMessage.printStackTrace("ERROR: attempt to close null stream");
+		writing = false;
+	}
+
+	public boolean isWriting(){
+		return writing;
+	}
+
+	/*-------------------------------------------------------*/
+	/** Get directory in which file resides (actually, entire path) */
+	public String getDirectoryName() {
+		return directoryName;
+	}
+
+	/*-------------------------------------------------------*/
+	/** Get name of file. */
+	public String getFileName() {
+		return fileName;
+	}
+
+	/*-------------------------------------------------------*/
+	/** Get URL of file (null if a local file). */
+	public URL getURL() {
+		return url;
+	}
+	/*-------------------------------------------------------*/
+	/** Return string for directory path from full file path*/
+	public static String getDirectoryPathFromFilePath(String path) { 
+		return StringUtil.getAllButLastItem(path, fileSeparator, "/") + fileSeparator; 
+	}
+	/*-------------------------------------------------------*/
+	/** Return string for directory path from full file path*/
+	public static String getFileNameFromFilePath(String path) { 
+		return StringUtil.getLastItem(path, fileSeparator, "/"); 
+	}
+	/*-------------------------------------------------------*/
+	/** Return string for path, accommodating ../ at start of filename. If second string passed begins with "/", this 
+	assumes that the string is an entire path to a local volume (e.g. "/HardDrive/MyDirectory/picture.gif") and ignores
+	the first string.  In some cases, d is directory; f is file*/
+	public static String composePath(String d, String f) { //TODO: this isn't all correct.  May work reasonably well for local, but for web URL's won't work
+		if (d==null) 
+			return f;
+		else if (f==null)
+			return d;
+		int count=0;
+		if (f.startsWith("http://")) //NOTE: Assumes if first is / then is /hardDrive/directory...etc.
+			return f;
+		if (f.startsWith("https://")) //NOTE: Assumes if first is / then is /hardDrive/directory...etc.
+			return f;
+		if (f.startsWith("file://")) //NOTE: Assumes if first is / then is /hardDrive/directory...etc.
+			return f;
+		if (f.startsWith("/")) //NOTE: Assumes if first is / then is /hardDrive/directory...etc.
+			return f;
+		if (f.indexOf(":\\") == 1) //NOTE: Assumes if second is : and third is \ that it's a windows full path
+			return f;
+		while (d.endsWith("../")){
+			count++;
+			d = d.substring(0, d.length()-3);
+		}
+		while (f.startsWith("../")){
+			count++;
+			f = f.substring(3, f.length());
+		}
+		if (d.endsWith(fileSeparator)) {//count>0 && 
+			d = d.substring(0, d.length()-1);
+		}
+		while (count>0 && d.length()>0) {
+			count--;
+			d = StringUtil.getAllButLastItem(d, fileSeparator);  
+		}
+		return d+fileSeparator + f;
+	}
+	/*-------------------------------------------------------*/
+	/** Converts absolute to relative string for path*/
+	public static String decomposePath(String relativeTo, String path) {
+		if (relativeTo==null) 
+			return path;
+		else if (path==null)
+			return relativeTo;
+		int count;
+		int lastSlashCount=0;
+
+		for (count = 0; count< relativeTo.length() && count<path.length() && relativeTo.charAt(count)==path.charAt(count); count++){
+			if (relativeTo.charAt(count)=='/' ||containedAt(relativeTo, fileSeparator, count))
+				lastSlashCount = count+1;  // we will want to take the part from just past the slash onward
+		}
+		if (lastSlashCount==0)
+			return path;  
+		//count is now at first character at which they don't match.  Eat up first part of both and set relative.
+		path = path.substring(lastSlashCount, path.length());
+		relativeTo = relativeTo.substring(lastSlashCount, relativeTo.length());
+		//count number of "/" in relativeTo
+		count = 0;
+		for (int i = 0; i<relativeTo.length(); i++)
+			if (relativeTo.charAt(i)== '/' ||containedAt(relativeTo, fileSeparator, i))
+				count++;
+		for (int i=0; i<count; i++)
+			path = "../" + path;
+
+		return StringUtil.replace(path, fileSeparator, "/");
+	}
+	/*-------------------------------------------------------*/
+	static boolean containedAt(String container, String contained, int where){
+		if (container == null || contained == null || where>= container.length())
+			return false;
+		int i;  //counter in container
+		int j;  //counter in contained
+		for (i = where, j=0; j<contained.length() && i<container.length(); i++, j++)
+			if (contained.charAt(j) != container.charAt(i))
+				return false;
+		return j == contained.length();  //reached the end of contained
+	}
+	/*-------------------------------------------------------*/
+	/** converts an existing local file path to a URL string.  See also StringUtil.encodeForURL*/
+	public static String massageStringToFilePathSafe(String path) {
+		if (StringUtil.blank(path))
+			return path;
+		path = StringUtil.replace(path, ':', '|');
+		path = StringUtil.replace(path, '/', '|');
+		path = StringUtil.replace(path, '\\', '|');
+		path = StringUtil.replace(path, '\'', '|');
+		path = StringUtil.replace(path, '"', '|');
+		return path;
+
+	}
+	/*-------------------------------------------------------*/
+	/** converts an existing local file path to a URL string.  See also StringUtil.encodeForURL*/
+	public static String massageFilePathToURL(String path) {
+		if (StringUtil.blank(path))
+			return path;
+		try {
+			File f = new File(path);
+			if (f.exists()) {
+				String s = f.toURL().toString();  //errors caught in case this isn't a 1.4 VM
+				return s;
+			}
+		}
+		catch (Throwable t){
+		}
+		path = StringUtil.replaceFirst(path, "://", "|/"); //a kludge for problems under Windows
+		path = StringUtil.replaceFirst(path, ":\\\\", "|\\"); //a kludge for problems under Windows
+		path = StringUtil.replace(path, ':', '|');//a kludge for problems under Windows
+		if (path.charAt(0)!='/')
+			return "file:///" + path;
+		else
+			return "file://" + path;
+		/*	try {
+			URL url = new URL("file", "", path);
+			q = url.toString();
+		}
+		catch (MalformedURLException e){
+		}
+		return q;
+		 */
+	}
+	/*.................................................................................................................*/
+	/** Links progress indicator*/
+	public void linkProgressIndicator(ProgressIndicator pi){
+		if (progIndicator!=null)
+			progIndicator.goAway();
+		progIndicator = pi;
+		if (progIndicator!=null)
+			progIndicator.setTotalValue(existingLength());
+	}
+	/*.................................................................................................................*/
+	/** Returns true if user has requested file reading or writing stop.*/
+	public boolean getFileAborted(){
+		if (progIndicator !=null) {
+			return progIndicator.isAborted();
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Update the progress window to current filePos.*/
+	private void updateProgress(){
+		if (progIndicator !=null) {
+			progIndicator.setCurrentValue(filePos);
+		}
+
+	}
+	/*.................................................................................................................*/
+	byte[] bytes = new byte[4096];
+	int currentByte = 0;
+	int bytesAvailable = 0;
+	byte[] oneByte = new byte[1];
+	String bytesString = null;
+	private int readNextChar() throws IOException {
+		int b = 0;
+		byte by = 0;
+
+		if (bytesAvailable == -1) {
+			currentByte = 0;
+			return -1;
+		}
+		else if (currentByte>=bytesAvailable){
+			currentByte = 0;
+			bytesAvailable = inStream.read(bytes);
+
+			if (bytesAvailable <=0)
+				return -1;
+			filePos++;
+			by = bytes[currentByte++];
+			b = (int) by;
+
+		}
+		else  {
+			filePos++;
+			by = bytes[currentByte++];
+			b = (int) by;
+		}
+		if (b<0){  
+			// high ASCII; must fiddle to get it into default encoding.
+			// needs to be manipulated because bytes are unsigned in java
+			// this masks the right most 8 bits
+			b = (b & 0xff);
+		}
+		return b;
+
+	}
+	private int ALTreadNextChar() throws IOException {
+		int c = inStream.read();
+		filePos++;
+		return c;
+	}
+	/*.................................................................................................................*/
+	/** read next line from file, return as String. */
+	public String readLine(String endLine) {
+		if (endLine == null || endLine.length() ==0)  {
+			if ( readLine(sB))
+				return sB.toString();
+			else
+				return null;
+		}
+		sB.setLength(0);
+		if (inStream==null)
+		{return null;
+		}
+		else	{
+			try {
+				if (remnantString.length() >0) {
+					sB.append(remnantString.toString());
+				}
+				remnantString.setLength(0);
+				boolean done = false;
+				readLineTimer.start();
+				int c=0;
+				while (c!= -1) {
+					c= readNextChar();
+
+					if (c == endLine.charAt(0)){// || oldPos == pos)
+						remnantString.append((char)c);
+						//appendToStringBuffer(remnantString, c);
+						c = -1;
+						int k;
+						int index = 0;
+						do{ 
+							index++;
+							k= readNextChar();
+							if (k== -1){
+								done = true;
+							}
+							else 
+								remnantString.append((char)k);
+							//appendToStringBuffer(remnantString, k);
+						}
+						while  (index<endLine.length() && k == endLine.charAt(index) && !done);
+						if (index>= endLine.length() && !done) {
+							remnantString.setLength(0);
+							//	appendToStringBuffer(remnantString, k);
+							remnantString.append((char)k);
+						}
+					}
+					else if (c!= -1)
+						//	appendToStringBuffer(sB, c);
+						sB.append((char)c);
+					else { // end of stream had been reached
+						done = true;
+						remnantString.setLength(0);
+					}
+
+				}
+				readLineTimer.end();
+				String s = sB.toString();
+				if (done && StringUtil.blank(s)) {
+					updateProgress();
+					return null;
+				}
+				updateProgress();
+				return s;
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "File Busy or Not Found  (3): \ndirectory <" + directoryName + "> \nfile <" + fileName + ">" );
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "IO exception in readLine for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage() );
+				//MesquiteMessage.printStackTrace();
+			}
+			updateProgress();
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	int totalWaitingAppend = 100;
+	char[] toAppend = new char[totalWaitingAppend];
+	int readyToAppend = 0;
+
+	/** read next line from file, return as String. */
+	public boolean readLine(StringBuffer buffer) {	
+		buffer.setLength(0);
+		if (inStream==null) {
+			return false;
+		}
+		else	{
+			try {
+				readyToAppend = 0;
+
+				int c=0;
+				if (remnantString.length() >0) {
+					int k= remnantString.charAt(0);
+					if (k == '\n' || k == '\r') {//last remnant was a new line; thus done
+						c = -1;
+					}
+					else {
+						StringUtil.append(buffer, remnantString);
+					}
+				}
+				remnantString.setLength(0);
+				boolean done = false;
+				readLineTimer.start();
+				while (c!= -1) {
+					c= readNextChar();
+					if (c == '\n' || c == '\r'){  //end of line character
+						int k= readNextChar(); //get to next character to see if a different end of line character (e.g. DOS file)
+						if (k== -1){ //end of file
+							done = true;
+							remnantString.setLength(0);
+						}
+						else if (k == '\n' || k == '\r') { //next is same end of line character
+							if (k==c) {
+								remnantString.setLength(0);
+								//	appendToStringBuffer(remnantString, k);
+								remnantString.append((char)k);
+								c = -1; //done line
+							}
+							//c=k;
+						}
+						else { //next is not end of line character
+							remnantString.setLength(0);
+							//appendToStringBuffer(remnantString, k);
+							remnantString.append((char)k);
+							//c=k;
+						}
+						c = -1;
+					}
+					else if (c!= -1) {
+						toAppend[readyToAppend++] = (char)c;
+						if (readyToAppend>= totalWaitingAppend) {
+							buffer.append(toAppend, 0, (readyToAppend));
+							readyToAppend = 0;
+						}
+					}
+					else { // end of stream had been reached
+						done = true;
+						remnantString.setLength(0);
+					}
+				}
+				readLineTimer.end();
+				if (readyToAppend>0){
+					buffer.append(toAppend, 0, (readyToAppend));
+					readyToAppend = 0;
+				}
+				if (done && StringUtil.blank(buffer)) {
+					updateProgress();
+					return false;
+				}
+				updateProgress();
+				return true;
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "File Busy or Not Found  (3): \ndirectory <" + directoryName + "> \nfile <" + fileName + ">" );
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "IO exception in readLine for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage() );
+				//MesquiteMessage.printStackTrace();
+			}
+			catch( OutOfMemoryError e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "OutOfMemoryError in readLine (sB.length()  " + sB.length() + " remnantString.length() " + remnantString.length()+ ") .  See file memory.txt in the Mesquite_Folder." );
+				//MesquiteMessage.printStackTrace();
+			}
+			updateProgress();
+		}
+		return false;
+	}
+	/** read next line from file, return as String. */
+	public String readLine() {	
+		sB.setLength(0);
+		if (inStream==null) {
+			return null;
+		}
+		else	{
+			try {
+				readyToAppend = 0;
+
+				int c=0;
+				if (remnantString.length() >0) {
+					int k= remnantString.charAt(0);
+					if (k == '\n' || k == '\r') {//last remnant was a new line; thus done
+						c = -1;
+					}
+					else {
+						StringUtil.append(sB, remnantString);
+					}
+				}
+				remnantString.setLength(0);
+				boolean done = false;
+				readLineTimer.start();
+				while (c!= -1) {
+					c= readNextChar();
+					if (c == '\n' || c == '\r'){  //end of line character
+						int k= readNextChar(); //get to next character to see if a different end of line character (e.g. DOS file)
+						if (k== -1){ //end of file
+							done = true;
+							remnantString.setLength(0);
+						}
+						else if (k == '\n' || k == '\r') { //next is same end of line character
+							if (k==c) {
+								remnantString.setLength(0);
+								//appendToStringBuffer(remnantString, k);
+								remnantString.append((char)k);
+								c = -1; //done line
+							}
+							//c=k;
+						}
+						else { //next is not end of line character
+							remnantString.setLength(0);
+							//appendToStringBuffer(remnantString, k);
+							remnantString.append((char)k);
+							//c=k;
+						}
+						c = -1;
+					}
+					else if (c!= -1) {
+						toAppend[readyToAppend++] = (char)c;
+						if (readyToAppend>= totalWaitingAppend) {
+							sB.append(toAppend, 0, (readyToAppend));
+							readyToAppend = 0;
+						}
+					}
+					else { // end of stream had been reached
+						done = true;
+						remnantString.setLength(0);
+					}
+				}
+				readLineTimer.end();
+				if (readyToAppend>0){
+					sB.append(toAppend, 0, (readyToAppend));
+					readyToAppend = 0;
+				}
+				if (done && StringUtil.blank(sB)) {
+					updateProgress();
+					return null;
+				}
+				updateProgress();
+				return sB.toString();
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "File Busy or Not Found  (3): \ndirectory <" + directoryName + "> \nfile <" + fileName + ">" );
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "IO exception in readLine for <" + directoryName + "> \nfile <" + fileName + "> " + e.getMessage() );
+				//MesquiteMessage.printStackTrace();
+			}
+			catch( OutOfMemoryError e ) {
+				MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(), "OutOfMemoryError in readLine (sB.length()  " + sB.length() + " remnantString.length() " + remnantString.length()+ ") " );
+				//MesquiteMessage.printStackTrace();
+			}
+			updateProgress();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** read next line from file, return as String. */
+	public static String readLine(InputStream inStream, StringBuffer sBuff, MesquiteInteger remnantChar) {	
+		return readLine(inStream, sBuff, remnantChar, null);
+	}
+	/*.................................................................................................................*/
+	/** read next line from file, return as String. */
+	public static String readLine(InputStream inStream, StringBuffer sBuff, MesquiteInteger remnantChar, MesquiteLong fPOS) {	
+		sBuff.setLength(0);
+		if (inStream==null)
+		{return null;
+		}
+		else	{
+			try {
+				if (remnantChar.getValue()>=0)
+					sBuff.append((char)remnantChar.getValue());
+				remnantChar.setValue(-1);
+				boolean done = false;
+				int c=0;
+				while (c!= -1) {
+					c= inStream.read();
+					if (fPOS != null)
+						fPOS.increment();
+					if (c == '\n' || c == '\r'){// || oldPos == pos)
+						int k= inStream.read();
+						if (fPOS != null)
+							fPOS.increment();
+						if (!((k == '\n' || k == '\r') && k!=c)) {
+							remnantChar.setValue(k);
+							//c=k;
+						}
+						c = -1;
+					}
+					else if (c!= -1)
+						sBuff.append((char)c);
+					else // end of stream had been reached
+						done = true;
+
+				}
+				String s = sBuff.toString();
+				if (done && StringUtil.blank(s)) { 
+					//updateProgress();
+					return null;
+				}
+				//updateProgress();
+				return s;
+			}
+			catch( IOException e ) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"IO exception in readLine(2) " + e.getMessage() );}
+			//updateProgress();
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	/** read next dark line from file, return as String. */
+	public String readNextDarkLine() {	
+		boolean line = readLine(sB);
+		while (StringUtil.blank(sB)) {
+			if (!line)
+				break;
+			line = readLine(sB); 
+		}
+		return sB.toString();
+	}
+	MesquiteBoolean suppressComments = new MesquiteBoolean(false);
+	/*.................................................................................................................*/
+
+	/** Returns next token from file.  Note that firstToken is used for the first token in a command *
+	public String nextToken(StringBuffer commentBuffer){	
+			pendingBrackets.setValue(0);  //level of nesting of incompleteness of comment square brackets
+			suppressComments.setValue(false);
+			String token="";
+			if (!bufferRead) {
+				bufferRead =readLine(parser.getBuffer());
+				parser.setPosition(0);
+				if (!StringUtil.blank(parser.getBuffer())) 
+					token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments);
+			}
+			else
+				token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+			boolean bracketEnd = false;
+				//if [ found, and not closed, or if no tokens in remaining part of bufferstring, then need to continue reading lines
+			while (bufferRead && (StringUtil.blank(token) || pendingBrackets.getValue()>0)) {
+				boolean wasPending = (pendingBrackets.getValue()>0);
+				if (StringUtil.blank(token)) {// no tokens in remaining part of bufferString
+					bufferRead=readLine(parser.getBuffer());
+					parser.setPosition(0);
+					token = StringUtil.lineEnding();
+				}
+				else {
+					parser.setPosition(0);
+					if (!StringUtil.blank(parser.getBuffer())) 
+						token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+				}
+				bracketEnd = (wasPending && pendingBrackets.getValue()==0);
+			}
+			if (token==null)
+				token = "";
+			if (parser.getBuffer().length()==0)
+				bufferRead = false;
+			return token;
+	}
+	 */
+
+
+	/*.................................................................................................................*/
+	/** Returns next token from file. Used for first token of command, to preserves leading whitespace (used to preserve
+	leading tabs/spaces for blocks such as the MesquiteBlock).*/
+	public String firstToken(StringBuffer commentBuffer){	
+		//TODO: getUnalteredToken stops at the end of a line.  Should have pendingQuote to indicate it must keep going until quote used up
+		pendingBrackets.setValue(0);  //level of nesting of incompleteness of comment square brackets
+		suppressComments.setValue(false);
+		String token="";
+
+		if (!bufferRead) {
+			bufferRead=readLine(parser.getBuffer());
+			parser.setPosition(0);
+			if (!StringUtil.blank(parser.getBuffer())) 
+				token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments);
+		}
+		else
+			token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments);
+
+
+
+		//if [ found, and not closed, or if no tokens in remaining part of bufferstring, then need to continue reading lines
+		while (bufferRead && (StringUtil.blank(token) || pendingBrackets.getValue()>0)) {
+			//TODO: why did automatically start reading new bufferString instead of continuing to use old one?
+			if (StringUtil.blank(token)) {// no tokens in remaining part of bufferString
+				bufferRead=readLine(parser.getBuffer());
+				parser.setPosition(0);
+			}
+			if (!StringUtil.blank(parser.getBuffer())) 
+				token = parser.getUnalteredToken( true, pendingBrackets, commentBuffer, suppressComments);
+		}
+		if (token==null)
+			token = "";
+		return token;
+	}
+	/*.................................................................................................................*/
+	private boolean emptyToken(String token) {
+		return token == null || token.length() ==0;
+		//return StringUtil.blank(token);   
+	}
+	/*.................................................................................................................*/
+
+	/** Returns next token from file.  Note that firstToken is used for the first token in a command */
+	public String nextToken(StringBuffer commentBuffer){	
+		pendingBrackets.setValue(0);  //level of nesting of incompleteness of comment square brackets
+		String token=null;
+		suppressComments.setValue(false);
+		if (!bufferRead) {
+			bufferRead =readLine(parser.getBuffer());
+			parser.setPosition(0);
+			if (bufferRead) 
+				token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+			else
+				token = "";
+		}
+		else
+			token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+
+		boolean bracketEnd = false;
+		//if [ found, and not closed, or if no tokens in remaining part of bufferstring, then need to continue reading lines
+		while (bufferRead && (emptyToken(token) || pendingBrackets.getValue()>0)) {
+			boolean wasPending = (pendingBrackets.getValue()>0);
+			if (emptyToken(token)) {// no tokens in remaining part of bufferString
+				bufferRead=readLine(parser.getBuffer());
+
+				parser.setPosition(0);
+				if (pendingBrackets.getValue()>0) //in this case, would reenter loop and wipe out the current line because token will be blank
+					token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+				else			
+					token = StringUtil.lineEnding();
+				//token ="";
+			}
+			else if (StringUtil.blank(token)) {   // added this section 22 Oct 07 to deal with bracketed comments split over multiple lines
+				bufferRead =readLine(parser.getBuffer());
+				parser.setPosition(0);
+				if (bufferRead) 
+					token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+				else
+					token = "";
+			}
+			else { 
+				parser.setPosition(0);
+				if (!StringUtil.blank(parser.getBuffer())) 
+					token = parser.getUnalteredToken(true, pendingBrackets, commentBuffer, suppressComments); //was false
+			}
+			bracketEnd = (wasPending && pendingBrackets.getValue()==0);
+		}
+		if (token==null)
+			token = "";
+		return token;
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns the next command in the file.  Extra information about the command is
+	returned in the MesquiteInteger status.  If the command is the "begin", 1 is returned; if "end;", 2 is returned.
+	Otherwise 0 is returned.   
+	If includeEntireCommand is true, then the entire command is returned; if false, the only the first token (command name) is returned.
+	(Returning only part of the command can save time if the commands are long (e.g., a TREE) and not needed. */
+	public String getNextCommand(MesquiteInteger status, StringBuffer commandComments, boolean includeEntireCommand) {
+		getNextCommandStatusTimer.start();
+		StringBuffer command= new StringBuffer(300);
+		betweenCommandComments.setLength(0);
+		if (commandComments !=null)
+			commandComments.setLength(0);
+		String token = firstToken(betweenCommandComments);
+
+
+		if (StringUtil.blank(token)) {
+			return token;
+		}
+		if (ParseUtil.darkBeginsWithIgnoreCase(token, "Begin"))
+			status.setValue(1);
+		else
+			status.setValue(0);
+
+		if (!emptyToken(token)) {
+			command.append(token);  // this is the command name
+			while (!emptyToken(token) && !token.equals(";")) {
+				token = nextToken(commandComments);
+				if (includeEntireCommand && !emptyToken(token)) {
+					if (token.charAt(0)!=';' && !parser.whitespace(token.charAt(0))) 
+						command.append(' ');
+					command.append(token);
+				}
+			}
+		}
+		String result = command.toString();
+		if (ParseUtil.darkBeginsWithIgnoreCase(result, "end;") || ParseUtil.darkBeginsWithIgnoreCase(result, "endblock;"))
+			status.setValue(2);
+		getNextCommandStatusTimer.end();
+		return result;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the next command in the file.  Extra information about the command is
+	returned in the MesquiteInteger status.  If the command is the "begin", 1 is returned; if "end;", 2 is returned.
+	Otherwise 0 is returned. */
+	public String getNextCommand(MesquiteInteger status, StringBuffer commandComments) {
+		return getNextCommand(status,commandComments, true);
+	}
+
+	/*.................................................................................................................*/
+	/** skips the next command in the file.  Extra information is
+	returned in the MesquiteInteger status.  If the command is the "begin", 1 is returned; if "end;", 2 is returned.
+	Otherwise 0 is returned. */
+	public void skipNextCommand(MesquiteInteger status) {
+		String token =firstToken(null);
+		if (StringUtil.blank(token)) 
+			return;
+
+		if (ParseUtil.darkBeginsWithIgnoreCase(token, "Begin"))
+			status.setValue(1);
+		else
+			status.setValue(0);
+		String lastT = null;
+		if (!emptyToken(token)) {
+			while (token!=null && !token.equals(";")) {
+				lastT = token;
+				token = nextToken(null);
+			}
+		}
+		if (ParseUtil.darkBeginsWithIgnoreCase(lastT, "end;") || ParseUtil.darkBeginsWithIgnoreCase(lastT, "endblock;"))
+			status.setValue(2);
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/** returns the next block; blockName is passed back via the MesquiteString object */
+	public FileBlock getNextBlockOLD(MesquiteString blockName, StringBuffer fileComments, StringBuffer blockComments) {
+		nextBlockTimer.start();
+		FileBlock block = new FileBlock();
+		if (blockComments!=null)
+			blockComments.setLength(0);
+		MesquiteInteger status = new MesquiteInteger(0);
+		StringBuffer withinCommandComments = new StringBuffer(10);
+		StringBuffer command = new StringBuffer(getNextCommand(status, withinCommandComments));
+		if (betweenCommandComments.length()>0 && fileComments!=null) {
+			String bcc = betweenCommandComments.toString();
+			if (ParseUtil.darkBeginsWithIgnoreCase(bcc, "!"))
+				fileComments.append(bcc.substring(bcc.indexOf('!')+1, bcc.length())+ StringUtil.lineEnding());
+		}
+		if (!StringUtil.blank(command)) {
+			if (status.getValue()==0) {
+				MesquiteMessage.println("last command " + Integer.toString(command.length()) + ": " + command);
+			}
+			else {
+				Parser nameParser = new Parser();
+				String bName =nameParser.getTokenNumber(command.toString(), 2); //resets string!
+				blockName.setValue(bName);
+				block.addCommand(command.toString(), withinCommandComments.toString());
+				//block.append(StringUtil.lineEnding());
+				command.setLength(0);
+				String temp = getNextCommand(status, withinCommandComments);
+				if (betweenCommandComments.length()>0 && blockComments!=null) {
+					String bcc = betweenCommandComments.toString();
+					if (ParseUtil.darkBeginsWithIgnoreCase(bcc, "!"))
+						blockComments.append(bcc.substring(bcc.indexOf('!')+1, bcc.length())+ StringUtil.lineEnding());
+				}
+				//here withinCommandComments would contain the command comments, but there's no place to put them
+				command.append(temp);
+				if (!StringUtil.blank(command)) {
+					block.addCommand(command.toString(), withinCommandComments.toString());
+					long numCommands = 0; //added 21 Sept 01
+					while (!StringUtil.blank(command) && status.getValue()!=2) {
+						numCommands ++;
+						if (numCommands % 1000 == 0) {
+							Runtime.getRuntime().gc(); //added 21 Sept 01
+						}
+						command.setLength(0);
+						String c = getNextCommand(status, withinCommandComments);
+						if (betweenCommandComments.length()>0 && blockComments!=null) {
+							String bcc = betweenCommandComments.toString();
+							if (ParseUtil.darkBeginsWithIgnoreCase(bcc, "!"))
+								blockComments.append(bcc.substring(bcc.indexOf('!')+1, bcc.length())+ StringUtil.lineEnding());
+						}
+						//here withinCommandComments would contain the command comments, but there's no place to put them
+						if (!StringUtil.blank(c)) {
+							command.append(c);
+							block.addCommand(command.toString(), withinCommandComments.toString());
+						}
+
+					}
+				}
+			}
+		}
+		nextBlockTimer.end();
+		return block;
+	}
+	/*.................................................................................................................*/
+	/** returns the next block; blockName is passed back via the MesquiteString object */
+	public FileBlock getNextBlock(MesquiteString blockName, StringBuffer fileComments, StringBuffer blockComments) {
+		nextBlockTimer.start();
+		return new FileBlock(this,  blockName,  fileComments, blockComments);
+	}
+
+	/*.................................................................................................................*/
+	public long getFilePosition(){
+
+		return filePos;
+	}
+
+	/*.................................................................................................................*/
+	public boolean atEOF(){
+		return filePos >= existingLength();
+	}
+	/*.................................................................................................................*/
+	public void goToFilePosition(long pos){
+		if (!MesquiteLong.isCombinable(pos)) {
+			MesquiteMessage.println("Uncombinable goToFilePosition (" + pos + ")");
+			return;
+		}
+		bufferRead = false;
+		currentByte = 0;
+		bytesAvailable = 0;
+		if (remnantString != null)
+			remnantString.setLength(0);
+		if (parser != null)
+			parser.setString("");
+		try {
+			if (inStream == null)
+				return;
+			if (pos!=filePos) {
+				closeReading();
+				openReading();
+				inStream.skip(pos);
+			}
+			else if (pos == filePos){
+			}
+			filePos = pos;
+		}
+		catch (IOException e){
+			MesquiteMessage.println("ioe goToFilePosition (" + pos + ")");
+			filePos = -1;
+			MesquiteFile.throwableToLog(this, e);
+		}
+		catch (Throwable e){
+			filePos = -1;
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** returns the file position of the start of the next block; returns blockName */
+	public String goToNextBlockStart(MesquiteLong startPos) {
+		MesquiteInteger status = new MesquiteInteger(0);
+		StringBuffer command = new StringBuffer(getNextCommand(status, null)); //������������
+
+		if (!StringUtil.blank(command)) {
+			if (status.getValue()==0) {  //in middle of block; need to continue reading until get to end of block
+				while (!StringUtil.blank(command) && status.getValue()!=2) {
+					command.setLength(0);
+					String c = getNextCommand(status, null);
+					if (!StringUtil.blank(c)) 
+						command.append(c);
+				}
+				//reached end of this block, hence mark position for resetting
+				if (startPos !=null)
+					startPos.setValue(getFilePosition()+1);
+
+				//at end of block; now get next to find first part of next block
+				command.setLength(0);
+				String c = getNextCommand(status, null);
+				if (!StringUtil.blank(c)) 
+					command.append(c);
+			} else {
+				if (!startPos.isCombinable())
+					startPos.setValue(getFilePosition()+1);
+			}
+
+			Parser nameParser = new Parser();
+			return nameParser.getTokenNumber(command.toString(), 2); 
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Adds the passed FileElement to the file. */
+	public void addFileElement(FileElement element) {
+		if (fileElements == null)
+			fileElements = new ListableVector( 1);
+		fileElements.addElement(element, true);
+	}
+	/*.................................................................................................................*/
+	/** Removes the passed FileElement from the file. */
+	public void removeFileElement(FileElement element) {
+		if (fileElements != null) {
+			if (element !=null)
+				fileElements.removeElement(element, true);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Gets list of file elements. */
+	public ListableVector getFileElements() {
+		return fileElements;
+	}
+	/*.................................................................................................................*/
+	/** appends a number to the end of the path until it finds that no file or directory does not exist at that path */
+	public static String getUniqueNumberedPath(String path) {
+		if (!fileOrDirectoryExists(path+"1"))
+			return path+"1";
+
+		int count = 1;
+		while (fileOrDirectoryExists(path+count)) {
+			count++;
+
+		}
+		return path + count;
+	}	
+	/*.................................................................................................................*/
+	/** appends a number to the end of the path until it finds that no file or directory does not exist at that path */
+	public static String getUniqueModifiedPath(String path) {
+		if (!fileOrDirectoryExists(path))
+			return path;
+		int count = 0;
+		while (fileOrDirectoryExists(path)) {
+			path+=""+(count++);
+		}
+		return path;
+	}	
+	/*.................................................................................................................*/
+	/** appends a number to the end of the path until it finds that no file or directory does not exist at that path */
+	public static String getUniqueModifiedFileName(String path, String extension) {
+		if (!fileOrDirectoryExists(path + "." + extension))
+			return path + "." + extension;
+		int count = 0;
+		while (fileOrDirectoryExists(path + count + "." + extension)) {
+			count++;
+		}
+		return path + count + "." + extension;
+	}	
+	/*.................................................................................................................*/
+	/** deletes file at path */
+	public static boolean deleteFile(String path) {
+		if (fileExists(path) && canWrite(path)) {
+			File testing = new File(path);
+			testing.delete();
+			return true;
+		}
+		return false;
+	}	
+
+	/*.................................................................................................................*/
+	public static boolean deleteDirectory(String directoryPath){
+		try {
+			File directory = new File(directoryPath);
+			if (directory!=null && directory.isDirectory()) {
+				String[] files = directory.list();
+				for (int i=0; i<files.length; i++) {
+					String path = directoryPath + MesquiteFile.fileSeparator + files[i];
+					File f = new File(path);
+					if (f.isDirectory()) {
+						boolean success = deleteDirectory(path);
+						if (!success)
+							return false;
+					}
+					else
+						if (MesquiteFile.fileExists(path)) {
+							f.delete();
+						}
+				}
+				directory.delete();
+			}
+		} catch (SecurityException e){
+			MesquiteMessage.println("Directory could not be deleted: " + directoryPath);
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a directory OR file*/
+	public static long fileOrDirectoryLastModified(String path) {
+		if (path != null) {
+			if (path.indexOf("//")>=0)
+				MesquiteMessage.printStackTrace("double // in path " + path); 
+			File testing = new File(path);
+			return testing.lastModified();
+		}
+		return 0;
+	}	
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a directory OR file*/
+	public static boolean fileOrDirectoryExists(String path) {
+		if (path != null) {
+			if (path.indexOf("//")>=0)
+				MesquiteMessage.printStackTrace("double // in path " + path);
+			File testing = new File(path);
+			if (testing.exists())
+				return true;
+		}
+		return false;
+	}	
+
+	public static boolean fileExists(String directoryName, String fileName){ //Dec 2013.  Why was this appending existing directory to suggested?  Was generating double // errors
+		if (fileExists(directoryName+ fileName))  
+			return true;
+		else if (StringUtil.blank(directoryName))
+			return fileExists(MesquiteTrunk.suggestedDirectory +fileName);
+		else if (!(directoryName.endsWith(fileSeparator) || directoryName.endsWith("/"))) 
+			return fileExists(directoryName + fileSeparator +fileName);
+
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a file that is not a directory*/
+	public static boolean fileExists(String path) {
+		if (path != null) {
+			if (path.indexOf("//")>=0)
+				MesquiteMessage.printStackTrace("double // in path " + path);  
+			File testing = new File(path);
+			if (testing.exists() && !testing.isDirectory())
+				return true;
+		}
+		return false;
+	}	
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a file that is not a directory*/
+	public static String getAvailableFileName(String directoryName, String fileNameBase) {
+		if (!fileExists(directoryName,fileNameBase))
+			return fileNameBase;
+		int counter=1;
+		while (fileExists(directoryName,fileNameBase+counter))
+			counter++;
+		return fileNameBase+counter;
+	}	
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a file that is not a directory*/
+	public static String getAvailableFileName(String directoryName, String fileNameBase, String fileNameExtension) {
+		if (!fileExists(directoryName,fileNameBase+fileNameExtension))
+			return fileNameBase+fileNameExtension;
+		int counter=1;
+		while (fileExists(directoryName,fileNameBase+counter+fileNameExtension))
+			counter++;
+		return fileNameBase+counter+fileNameExtension;
+	}	
+	/*.................................................................................................................*/
+	/** Checks to see if can write to a file*/
+	public static boolean canWrite(String path) {
+		if (path != null && !MesquiteTrunk.isApplet()) {
+			File testing = new File(path);
+			if (testing.canWrite())
+				return true;
+		}
+		return false;
+	}	
+	/*.................................................................................................................*/
+	/** renames file.  Used instead of File.renameTo because of bug in Windows*/
+	public static boolean rename(String path, String newPath) {
+		if (path != null && newPath != null) {
+			File oldFile = new File(path);
+			if (!oldFile.exists())
+				return false;
+			File newFile = new File(newPath);
+			if (newFile.exists()){
+				newFile.delete();
+				int count = 0;
+				while ((new File(newPath)).exists() && count++<10){ //wait for file system to clean up
+					try{
+						Thread.sleep(20);
+					}
+					catch (InterruptedException e){
+						return false;
+					}
+				}
+				if (count>= 10)
+					return false;
+			}
+			int count = 0;
+			File file = new File(path);
+			while (!file.renameTo(new File(newPath)) && count++<10){ //wait for file system to clean up
+				try{
+					Thread.sleep(20);
+				}
+				catch (InterruptedException e){
+					return false;
+				}
+			}
+			if (count>= 10)
+				return false;
+			return true;
+		}
+		return false;
+	}	
+	/*.................................................................................................................*/
+	/** Checks to see if path leads to a file; if so, path returned; if not, user is asked to choose new file.*/
+	public static String checkFilePath(String path, String selectMessage) {
+		String resultPath = path;
+		boolean request=false;
+		if (path == null)
+			request = true;
+		else {
+			File testing = new File(path);
+			if (!testing.exists())
+				request = true;
+		}
+
+		if (request && !MesquiteThread.suppressInteractionAsLibrary) {
+			MesquiteTrunk.mesquiteTrunk.alert(selectMessage);
+			MainThread.incrementSuppressWaitWindow();
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), selectMessage, FileDialog.LOAD);
+			fdlg.setResizable(true);
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setVisible(true);
+			if (StringUtil.blank(fdlg.getDirectory()) || StringUtil.blank(fdlg.getFile())) {
+				// fdlg.dispose();
+				MainThread.decrementSuppressWaitWindow();
+				return null;
+			}
+			resultPath=fdlg.getDirectory() + fdlg.getFile();
+			// fdlg.dispose();
+			MainThread.decrementSuppressWaitWindow();
+		}
+		return resultPath;
+	}
+	/*.................................................................................................................*/
+	/** Returns the first line of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String getFileFirstContents(String relativePath) {
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(100);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+				while (newS != null) {
+					newS =readLine(stream, sBb, remnant);
+					if (!StringUtil.blank(newS))
+						return newS;
+				}
+			}
+			catch( FileNotFoundException e ) {
+			} 
+			catch( IOException e ) {
+			}
+		}
+		else {/*
+			if (url!=null) {
+				try {
+					stream = new DataInputStream(url.openStream());
+					return stream.readEverything();
+					}
+				catch( IOException e ) {MesquiteModule.mesquiteTrunk.discreetAlert(MesquiteThread.isScripting(),"IO exception" );}
+			}
+		 */
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	private static String[] addStringToEnd(String[] strings, String s) {
+		boolean stringAdded = false;
+		for (int i = 0; i<strings.length; i++) {  //go through strings until you get to the first null one
+			if (strings[i]==null) {
+				strings[i]=s;
+				stringAdded = true;
+				return strings;
+			}
+		}
+		if (!stringAdded) {  //need to move them down and add it at the end
+			for (int i = 0; i<strings.length-1;i++) {
+				strings[i]=strings[i+1];
+			}
+			strings[strings.length-1]=s;
+		}
+		return strings;
+	}
+	/*.................................................................................................................*/
+	private static boolean someStrings(String[] strings) {
+		for (int i = 0; i<strings.length-1;i++) {  //go through strings until you get to the first null one
+			if (strings[i]!=null) {
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	private static String concatStrings(String[] strings) {
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i<strings.length;i++) {  //go through strings until you get to the first null one
+			if (strings[i]!=null) {
+				sb.append(strings[i]+StringUtil.lineEnding());
+			}
+		}
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	/** Returns the last line of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String getFileLastContents(String relativePath, int numLines) {
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(100);
+		String lastS = null;
+		String[] lastLines = new String[numLines];
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+				while (newS != null) {
+					lastLines = addStringToEnd(lastLines, newS);
+					newS =readLine(stream, sBb, remnant);
+				}
+
+				if (someStrings(lastLines)) {
+					return concatStrings(lastLines);
+				}
+			}
+			catch( FileNotFoundException e ) {
+			} 
+			catch( IOException e ) {
+			}
+		}
+		else {
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the last line of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String getFileLastContents(String relativePath) {
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(100);
+		String lastS = null;
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+				while (newS != null) {
+					lastS = newS;
+					newS =readLine(stream, sBb, remnant);
+				}
+				if (!StringUtil.blank(lastS))
+					return lastS;
+			}
+			catch( FileNotFoundException e ) {
+			} 
+			catch( IOException e ) {
+			}
+		}
+		else {
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the last dark line of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String getFileLastDarkLine(String relativePath) {
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(100);
+		String lastS = null;
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String lastDarkLine = null;
+				String newS = " ";
+				while (newS != null) {
+					lastS = newS;
+					newS =readLine(stream, sBb, remnant);
+					if (!StringUtil.blank(newS)) 
+						lastDarkLine=newS;
+				}
+				if (!StringUtil.blank(lastDarkLine))
+					return lastDarkLine;
+			}
+			catch( FileNotFoundException e ) {
+			} 
+			catch( IOException e ) {
+			}
+		}
+		else {
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[] getFileContentsAsStrings(String relativePath) {
+
+		return getFileContentsAsStrings(relativePath, true);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[] getFileContentsAsStrings(String relativePath, boolean notifyIfNotFound) {
+		DataInputStream stream;
+		Vector v = new Vector();
+		String[] s = null;
+		StringBuffer sBb= new StringBuffer(100);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+
+				while (newS != null) {
+					newS =readLine(stream, sBb, remnant);
+					if (newS != null)
+						v.addElement(newS);
+				}
+				if (v.size()!=0) {
+					s = new String[v.size()];
+					int count = 0;
+					Enumeration e = v.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						s[count]= (String)obj;
+						count++;
+					}
+				}
+			}
+			catch( FileNotFoundException e ) {
+				if (notifyIfNotFound){
+					MesquiteMessage.warnProgrammer("File Busy or Not Found (5) : " + relativePath);
+					MesquiteFile.throwableToLog(null, e);
+				}
+				return null;
+			} 
+			catch( IOException e ) {
+				if (notifyIfNotFound){
+					MesquiteMessage.warnProgrammer("IO Exception found (5): " + relativePath + "   " + e.getMessage());
+					MesquiteFile.throwableToLog(null, e);
+				}
+				return null;
+			}
+			return s;
+		}
+		else {/*
+			if (url!=null) {
+				try {
+					stream = new DataInputStream(url.openStream());
+					return stream.readEverything();
+					}
+				catch( IOException e ) {MesquiteModule.mesquiteTrunk.discreetAlert(MesquiteThread.isScripting(), "IO exception" );}
+			}
+		 */
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[][] getTabDelimitedTextFile(String relativePath, boolean warn) {
+		DataInputStream stream;
+		Vector v = new Vector();
+		String[][] s = null;
+		StringBuffer sBb= new StringBuffer(100);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+
+				while (newS != null) {
+					newS =readLine(stream, sBb, remnant);
+					if (newS != null)
+						v.addElement(newS);
+				}
+				if (v.size()!=0) {
+					s = new String[v.size()][];
+					int count = 0;
+					Enumeration e = v.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						s[count]= StringUtil.tabDelimitedTokensToStrings((String)obj);
+						count++;
+					}
+				}
+				stream.close();
+			}
+			catch( FileNotFoundException e ) {
+				if (warn) MesquiteMessage.warnProgrammer("File Busy or Not Found (z5) : " + relativePath);
+				return null;
+			} 
+			catch( IOException e ) {
+				if (warn) MesquiteMessage.warnProgrammer("IO Exception found (z5): " + relativePath + "   " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+				return null;
+			}
+			return s;
+		}
+		else {		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[][] getTabDelimitedTextFile(String relativePath) {
+		return getTabDelimitedTextFile(relativePath, true);
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName".*/
+	public static String getFileContentsAsString(String relativePath) {
+		return getFileContentsAsString(relativePath, -1,100);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file, local or remote.  The parameter "maxCharacters"
+	sets an upper limit on how many characters are read (if <0, then all characters read in)*/
+	public String getFileContentsAsString(int maxCharacters) {
+		StringBuffer sb = new StringBuffer(100);
+		StringBuffer line = new StringBuffer(100);
+		openReading();
+		while (readLine(line) && (maxCharacters<0 ||  sb.length() <maxCharacters)){
+			sb.append(line.toString());
+			sb.append(StringUtil.lineSeparator);			
+		}
+		closeReading();
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName".  The parameter "maxCharacters"
+	sets an upper limit on how many characters are read (if <0, then all characters read in)*/
+	public static String getFileContentsAsString(String relativePath, int maxCharacters) {
+		return getFileContentsAsString(relativePath,maxCharacters,100);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName".  The parameter "maxCharacters"
+	sets an upper limit on how many characters are read (if <0, then all characters read in)*/
+	public static String getFileContentsAsString(String relativePath, int maxCharacters, int startBufferSize) {
+		return getFileContentsAsString(relativePath, maxCharacters, startBufferSize, true);
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName".  The parameter "maxCharacters"
+	sets an upper limit on how many characters are read (if <0, then all characters read in)*/
+	public static String getFileContentsAsString(String relativePath, int maxCharacters, int startBufferSize, boolean warnIfProblem) {
+		if (StringUtil.blank(relativePath))
+			return "";
+		try {
+			File fin = new File(relativePath);
+			FileInputStream fis = new FileInputStream(fin);
+			BufferedReader in = new BufferedReader(new InputStreamReader(fis, "UTF-8"));  // why not ISO-8859-1? or something newer???
+			int length = (int)fin.length();  //2. 71 restricting to maxCharacters
+			if (maxCharacters>=0 && length>maxCharacters)
+				length = maxCharacters;
+			char[] chrArr = new char[length];
+			int count=0;
+			MesquiteTimer timer = new MesquiteTimer();
+			timer.start();
+			while(in.ready()==false) {
+				if (timer.timeSinceVeryStart()>2000) {
+					if (warnIfProblem)
+						MesquiteMessage.warnProgrammer("File could not be read (6) : " + relativePath);
+					return null;
+				}
+			}
+			in.read(chrArr);
+			in.close();
+			return new String(chrArr);
+		}
+		catch( FileNotFoundException e ) {
+			if (warnIfProblem)
+				MesquiteMessage.warnProgrammer("File Busy or Not Found (6) : " + relativePath);
+			//MesquiteMessage.printStackTrace();
+			return null;
+		} 
+		catch( IOException e ) {
+			if (warnIfProblem)
+				MesquiteMessage.warnProgrammer("IO Exception found (6) : " + relativePath + "   " + e.getMessage());
+			//MesquiteMessage.printStackTrace();
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName".  The parameter "maxCharacters"
+	sets an upper limit on how many characters are read (if <0, then all characters read in)*/
+	public static String getFileContentsAsStringOld(String relativePath, int maxCharacters, int startBufferSize) {
+		if (StringUtil.blank(relativePath))
+			return "";
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(startBufferSize);
+		StringBuffer s= new StringBuffer(startBufferSize);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				stream = new DataInputStream(new FileInputStream(relativePath));
+				String newS = " ";
+				int count = 0;
+
+				while (newS != null && (maxCharacters<0 || count<maxCharacters)) {
+					newS =readLine(stream, sBb, remnant);  //TODO: this won't stop if very long lines
+					if (newS!=null) {
+						count += newS.length();
+						s.append(newS + StringUtil.lineEnding());
+					}
+				}
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteMessage.warnProgrammer("File Busy or Not Found (6) : " + relativePath);
+				//MesquiteMessage.printStackTrace();
+				return null;
+			} 
+			catch( IOException e ) {
+				MesquiteMessage.warnProgrammer("IO Exception found (6) : " + relativePath + "   " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+				return null;
+			}
+			return s.toString();
+		}
+		else {/*
+			if (url!=null) {
+				try {
+					stream = new DataInputStream(url.openStream());
+					return stream.readEverything();
+					}
+				catch( IOException e ) {MesquiteModule.mesquiteTrunk.discreetAlert(MesquiteThread.isScripting(), "IO exception" );}
+			}
+		 */
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file at the url*/
+	public static String getURLContentsAsString(String path, int maxCharacters) {
+		return getURLContentsAsString(path, maxCharacters, true);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file at the url*/
+	public static String getURLContentsAsString(String path, int maxCharacters, boolean warnIfProblem) {
+		DataInputStream stream;
+		StringBuffer sBb= new StringBuffer(100);
+		StringBuffer s= new StringBuffer(100);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		String firstFour = path.substring(0,4);
+		boolean isHTTP = firstFour.equalsIgnoreCase("HTTP");
+		URL url = null;
+		try {
+			url = new URL(path);
+		}
+		catch (MalformedURLException e){
+			return null;
+		}
+
+		try {
+			URLConnection urlConnection = url.openConnection();
+			//		if (MesquiteTrunk.getJavaVersionAsDouble()>=1.5)
+			//			url.setConnectTimeout(2000);
+			InputStream inputStream = urlConnection.getInputStream();
+			stream = new DataInputStream(inputStream);
+			String newS = " ";
+			int count = 0;
+
+			while (newS != null && (maxCharacters<0 || count<maxCharacters)) {
+				newS =readLine(stream, sBb, remnant);  //TODO: this won't stop if very long lines
+				if (newS!=null) {
+					count += newS.length();
+					s.append(newS + StringUtil.lineEnding());
+				}
+			}
+		}
+		catch( IOException e ) {
+			if (warnIfProblem)
+				MesquiteMessage.warnProgrammer("IO Exception found (6a) : " + path + "\n   " + e.getMessage());
+			//MesquiteMessage.printStackTrace();  
+			return null;
+		}
+		return s.toString();
+
+	}
+	/*.................................................................................................................*/
+	public static void download(String address, String localFileName) {
+		OutputStream out = null;
+		URLConnection conn = null;
+		InputStream  in = null;
+		try {
+			URL url = new URL(address);
+			out = new BufferedOutputStream(
+					new FileOutputStream(localFileName));
+			conn = url.openConnection();
+			in = conn.getInputStream();
+			byte[] buffer = new byte[1024];
+			int numRead;
+			long numWritten = 0;
+			while ((numRead = in.read(buffer)) != -1) {
+				out.write(buffer, 0, numRead);
+				numWritten += numRead;
+			}
+			System.out.println(localFileName + "\t" + numWritten);
+		} catch (Exception exception) {
+			exception.printStackTrace();
+		} finally {
+			try {
+				if (in != null) {
+					in.close();
+				}
+				if (out != null) {
+					out.close();
+				}
+			} catch (IOException ioe) {
+			}
+		}
+	}
+
+	/** Downloads the contents of the file at the url to a local file*/
+	// 0 if unknown problem in downloading/writing
+	// -1 if problem reading from server
+	// -2 if problem writing download
+	public static int downloadURLContents(String urlPath, String writePath, boolean warnIfProblem, boolean showProgressIndicator) {
+		URLConnection uC;
+		OutputStream outFile = null;
+		InputStream  input = null;
+		ProgressIndicator progIndicator=null;
+		int doing = 0;
+		try {
+			byte[] buf = new byte[1024];
+			doing = 1; //
+			URL url = new URL(urlPath);
+			//outFile = new BufferedOutputStream(new FileOutputStream(writePath));
+			uC = url.openConnection();
+			int length = uC.getContentLength();
+			if (showProgressIndicator) {
+				progIndicator = new ProgressIndicator(null,"File Download", length, false);
+				if (progIndicator!=null){
+					progIndicator.start();
+					progIndicator.toFront();
+				}
+			}
+			input = uC.getInputStream();
+			int numRead;
+			long numWritten = 0;
+			while ((numRead = input.read(buf)) != -1) {
+				doing = 2;
+				if (outFile == null)
+					outFile = new BufferedOutputStream(new FileOutputStream(writePath));
+					
+				outFile.write(buf, 0, numRead);
+				doing = 1;
+				numWritten += numRead;
+				CommandRecord.tick("" + numWritten + " bytes downloaded");
+				if (progIndicator!=null){
+					progIndicator.setText("" + numWritten + " bytes downloaded");
+					progIndicator.setCurrentValue(numWritten);
+				}
+			}
+			doing = 1;
+			input.close();
+			doing = 2;
+			outFile.close();
+			doing = 0;
+			if (progIndicator!=null)
+				progIndicator.goAway();
+		} 
+		catch (Exception e) {
+			if (warnIfProblem){
+				MesquiteMessage.warnProgrammer("IO Exception found (6q) : " + writePath + "   " + e.getMessage() );
+				e.printStackTrace();
+			}
+			if (progIndicator!=null)
+				progIndicator.goAway();
+			return -doing;
+		}
+		return 1;
+
+	}
+	/** Returns the contents of the file at the url*/
+	public static int downloadURLContents(String urlPath, String writePath, boolean warnIfProblem) {
+		return downloadURLContents(urlPath, writePath, warnIfProblem, false);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[] getURLContentsAsStrings(String path) {
+		return getURLContentsAsStrings(path, true);
+	}
+	/*.................................................................................................................*/
+	/** Returns the contents of the file.  path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public static String[] getURLContentsAsStrings(String path, boolean notifyIfNotFound) {
+		DataInputStream stream;
+		Vector v = new Vector();
+		String[] s = null;
+		StringBuffer sBb= new StringBuffer(100);
+		MesquiteInteger remnant = new MesquiteInteger(-1);
+		URL url = null;
+
+		try {
+			url = new URL(path);
+		}
+		catch (MalformedURLException e){
+			return null;
+		}
+
+		try {
+
+			stream = new DataInputStream(url.openStream());
+			String newS = " ";
+
+			while (newS != null) {
+				newS =readLine(stream, sBb, remnant);  //TODO: this won't stop if very long lines
+				if (newS!=null) {
+					v.addElement(newS);
+				}
+			}
+			if (v.size()!=0) {
+				s = new String[v.size()];
+				int count = 0;
+				Enumeration e = v.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					s[count]= (String)obj;
+					count++;
+				}
+				return s;
+			}
+		}
+		catch( IOException e ) {
+			if (notifyIfNotFound)
+				MesquiteMessage.warnProgrammer("IO Exception found (6a1) : " + path + "   " + e.getMessage());
+			//MesquiteMessage.printStackTrace(e);
+			return null;
+		}
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static void putFileContentsQuery(String message, String output, boolean ascii){
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), message, FileDialog.SAVE);   // Save File dialog box
+		fdlg.setVisible(true);
+		String tempFileName=fdlg.getFile();
+		String tempDirectoryName=fdlg.getDirectory();
+		// fdlg.dispose();
+		if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+			MesquiteFile.putFileContents(tempDirectoryName+tempFileName, output, true);
+		}
+		MainThread.decrementSuppressWaitWindow();
+	}
+	/*.................................................................................................................*/
+	static boolean w = false;
+	/** Places to a file the contents.  Path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public synchronized static void putFileContents(String relativePath, String[] contents, boolean ascii) {
+		if (contents==null)
+			return;
+		if (w)
+			MesquiteMessage.warnProgrammer("writing simultaneously ");
+
+		w = true;
+		if (fileExists(relativePath) && !canWrite(relativePath)) {
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File cannot be written.  It may be locked or open in another application. (2; Path: " + relativePath + ")"); 
+			//MesquiteMessage.warnProgrammer("can't write file " + relativePath);
+			//MesquiteMessage.printStackTrace();
+			return;
+		}
+		Writer stream;
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				if (ascii && System.getProperty("os.name").startsWith("Mac"))
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath), "ASCII");
+				else
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath));
+				for (int i=0; i< contents.length; i++) {
+					if (contents[i]!=null) {
+						stream.write(contents[i] + StringUtil.lineEnding());
+						stream.flush();
+					}
+				}
+				stream.close();
+				try {MRJFileUtils.setFileTypeAndCreator(new File(relativePath), new MRJOSType("TEXT"), new MRJOSType("R*ch"));}
+				catch (Throwable t){}
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteMessage.warnProgrammer( "File Busy or Not Found:  put file contents (0)");
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteMessage.warnProgrammer( "IO exception put file contents  (0) " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+			}
+		}
+		else {
+			//files cannot be written with applets
+		}
+		w = false;
+	}
+	/*.................................................................................................................*/
+	/** Places to a file the contents.  Path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public synchronized static void putFileContents(String relativePath, Vector contents, boolean ascii) {
+		if (contents==null)
+			return;
+		if (w)
+			MesquiteMessage.warnProgrammer("writing simultaneously ");
+
+		w = true;
+		if (fileExists(relativePath) && !canWrite(relativePath)) {
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File cannot be written.  It may be locked or open in another application. (3; Path: " + relativePath + ")"); 
+			return;
+		}
+		Writer stream;
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				if (ascii && System.getProperty("os.name").startsWith("Mac"))
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath), "ASCII");
+				else
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath));
+				for (int i=0; i< contents.size(); i++) {
+					if (contents.elementAt(i)!=null) {
+						stream.write(contents.elementAt(i).toString() + StringUtil.lineEnding());
+						stream.flush();
+					}
+				}
+				stream.close();
+				try {MRJFileUtils.setFileTypeAndCreator(new File(relativePath), new MRJOSType("TEXT"), new MRJOSType("R*ch"));}
+				catch (Throwable t){}
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteMessage.warnProgrammer( "File Busy or Not Found: put file contents  (1) [" + relativePath + "]");
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteMessage.warnProgrammer( "IO exception put file contents  (1)  [" + relativePath + "] " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+			}
+		}
+		else {
+			//files cannot be written with applets
+		}
+		w = false;
+	}
+	/*.................................................................................................................*/
+	/** Places to a file the contents.  Path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public synchronized static void putFileContents(String relativePath, String contents, boolean ascii) {
+		putFileContents(relativePath, contents, ascii, true);
+	}
+	/*.................................................................................................................*/
+	/** Places to a file the contents.  Path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public synchronized static void putFileContents(String relativePath, String contents, boolean ascii, boolean warn) {
+		if (contents==null || relativePath==null)
+			return;
+		if (w)
+			MesquiteMessage.warnProgrammer("writing simultaneously ");
+
+		w = true;
+		if (fileExists(relativePath) && !canWrite(relativePath)) {
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File cannot be written.  It may be locked or open in another application. (4; Path: " + relativePath + ")"); 
+			return;
+		}
+		Writer stream;
+		if (!MesquiteTrunk.isApplet()) {
+
+			try {
+				if (ascii && System.getProperty("os.name").startsWith("Mac"))
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath), "ASCII");
+				else
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath));
+				if (contents!=null) {
+					stream.write(contents);
+					stream.flush();
+					stream.close();
+					try {MRJFileUtils.setFileTypeAndCreator(new File(relativePath), new MRJOSType("TEXT"), new MRJOSType("R*ch"));}
+					catch (Throwable t){}
+				}
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteMessage.warnProgrammer( "File Busy or Not Found:  put file contents  (2) [" + relativePath + "]");
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteMessage.warnProgrammer( "IO exception put file contents  (2)  [" + relativePath + "] " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+			}
+		}
+		else {
+			//files cannot be written with applets
+		}
+		w = false;
+	}
+	/*.................................................................................................................*/
+	/** Appends to a file the contents.  Path is relative to the root of the package heirarchy; i.e. for file in
+	a module's folder, indicate "mesquite/modules/moduleFolderName/fileName" */
+	public synchronized static void appendFileContents(String relativePath, String contents, boolean ascii) {
+		if (w)
+			MesquiteMessage.warnProgrammer("writing simultaneously ");
+
+		w = true;
+		if (fileExists(relativePath) && !canWrite(relativePath)) {
+			MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"File cannot be written.  It may be locked or open in another application. (5; Path: " + relativePath + ")"); 
+			return;
+		}
+		Writer stream;
+		if (!MesquiteTrunk.isApplet()) {
+			try {
+				if (ascii && System.getProperty("os.name").startsWith("Mac"))
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath, true), "ASCII");
+				else
+					stream = new OutputStreamWriter(new FileOutputStream(relativePath, true));
+				if (contents!=null) {
+					stream.write(contents);
+					stream.flush();
+					stream.close();
+				}
+			}
+			catch( FileNotFoundException e ) {
+				MesquiteMessage.warnProgrammer( "File Busy or Not Found:  append file contents  (3) [" + relativePath + "]");
+				//MesquiteMessage.printStackTrace();
+			} 
+			catch( IOException e ) {
+				MesquiteMessage.warnProgrammer( "IO exception append file contents  (3)  [" + relativePath + "] " + e.getMessage());
+				//MesquiteMessage.printStackTrace();
+			}
+		}
+		else {
+			//files cannot be written with applets
+		}
+		w = false;
+	}
+
+	/*.................................................................................................................*/
+	/** Shows the File in the finder or Windows Explorer" */
+	public static void showDirectory(String path) {
+		if (path == null)
+			return;
+		File file = new File(path);
+		if (!file.exists()|| !file.isDirectory())
+			return;
+		if (MesquiteTrunk.isMacOSX()) {
+
+			try {
+				Runtime.getRuntime().exec(
+						new String[] { "open", file.getAbsolutePath() });
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else if (MesquiteTrunk.isWindows()){
+			try {
+				Runtime.getRuntime().exec(
+						new String[] { "explorer", file.getAbsolutePath() });
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else {
+			System.err.println("Sorry, can't show folder under this operating system");
+		}
+	}
+
+	/*.................................................................................................................*/
+	public static int numFilesEndingWith(String directoryPath, String[] files, String ending){
+		int count=0;
+		for (int i=0; i<files.length; i++) { // going through the folders and finding the ace files
+			if (files[i]!=null ) {
+				String filePath = directoryPath + MesquiteFile.fileSeparator + files[i];
+				File cFile = new File(filePath);
+				if (cFile.exists()) {
+					if (!cFile.isDirectory()) {
+						if (files[i].endsWith(ending)) {
+							count++;
+						}
+					}
+				}
+			}
+		}
+		return count;
+	}
+
+
+	static boolean warnedLogNoWrite = false;
+	/*.................................................................................................................*/
+	/** Writes to the log file*/
+	public static void writeToLog(String s) {
+		if (MesquiteModule.userDirectory == null)
+			return;
+		String logPath = null;
+		if (!MesquiteTrunk.isApplet() && s!=null) {
+			try {
+				if (logStream==null) {
+					logPath = MesquiteModule.userDirectory + fileSeparator + "Mesquite_Support_Files" + fileSeparator + MesquiteTrunk.logFileName; //TODO: should have user settable in future
+					logStream = new PrintWriter(new FileOutputStream(logPath, appendToLog));
+					appendToLog = true;  //subsequent calls append
+				}
+				logStream.write(s);
+				logStream.flush();
+			}
+			catch( FileNotFoundException e ) {
+				System.out.println("Error writing log file: FileNotFoundException. (User dir should be at " + MesquiteModule.userDirectory + "; log path " + logPath + ")"); 
+			}
+			catch( IOException e ) {
+				System.out.println("Error writing log file: IOException. (User dir should be at " + MesquiteModule.userDirectory + "; log path \"" + logPath + "\")"); 
+			}
+			catch (Throwable e){
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static PrintWriter getLogWriter(){
+		return logStream;
+	}
+	/*.................................................................................................................*/
+	public static void throwableToLog(Object obj, Throwable e){
+		try {
+			if (e == null)
+				return;
+			ByteArrayOutputStream throwableStream= new ByteArrayOutputStream();
+			PrintWriter throwableWriter= new PrintWriter(throwableStream);
+			e.printStackTrace(throwableWriter);
+			throwableWriter.flush();
+			if (MesquiteTrunk.mesquiteTrunk == null)
+				return;
+			if (obj != null)
+				MesquiteTrunk.mesquiteTrunk.logln("(Following stack trace from object of class: " + obj.getClass().toString() + ")");
+			MesquiteTrunk.mesquiteTrunk.logln(throwableStream.toString());
+		}
+		catch (Throwable t){
+		}
+	}
+	/*.................................................................................................................*/
+	/** Closes to the log file*/
+	public static void closeLog() {
+		if (logStream!=null) {
+			logStream.close();
+			logStream = null;
+			try {MRJFileUtils.setFileTypeAndCreator(new File(MesquiteModule.userDirectory + fileSeparator + "Mesquite_Support_Files" + fileSeparator + MesquiteTrunk.logFileName), new MRJOSType("TEXT"), new MRJOSType("R*ch"));}
+			catch (Throwable t){}
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean getWriteProtected(){
+		return writeProtected;
+	}
+	public void setWriteProtected(boolean prot){
+		writeProtected = prot;
+	}
+	/** Sets the annotation (e.g., footnote) of this element */
+	public void setAnnotation(String e, boolean notify){
+		comment = e;
+	}
+	/** Returns the annotation (e.g., footnote) of this element */
+	public String getAnnotation(){
+		return comment;
+	}
+	/** Returns the explanation (e.g., footnote plus additional information) of this file */
+	public String getExplanation(){
+		if (project == null)
+			return "No project";
+		String extra = "";
+		extra += "This file has " + project.getNumberTaxas(this)+ " block(s) of taxa and  " + project.getNumberCharMatrices(this)+ " character matrices.\n";
+		if (project.getNumberLinkedFiles()>1)
+			extra += "It is part of the project with home file \"" + project.getHomeFileName()+ "\"\n";
+		return extra;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public HNode[] getHDaughters(){
+		return null;
+		/* post 2. 01, the projects & files window no longer shows file elements
+		if (fileElements == null || fileElements.size()== 0)
+			return null;
+		HNode[] daughters = new HNode[fileElements.size()];
+		for (int i = 0; i < fileElements.size(); i++)
+			daughters[i] = (HNode)fileElements.elementAt(i);
+		return daughters;
+		 */
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public HNode getHMother(){
+		return project;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public String getName(){
+		return getFileName();
+	}
+	public String getTypeName(){
+		return "File";
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public int getNumSupplements(){
+		return 0;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public String getSupplementName(int index){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public void hNodeAction(Container c, int x, int y, int action){
+		if (c==null || project == null)
+			return;
+		if (action == HNode.MOUSEDOWN){
+			MesquitePopup popup = new MesquitePopup(c);
+			popup.addItem(getName(), project.getCoordinatorModule(), null);
+			popup.addItem("Close File", project.getCoordinatorModule(), project.getCloseCommand(), Long.toString(getID())); //22 Dec 01 changed from project.getFileNumber(this)
+			popup.showPopup(x,y);
+		}
+		else if (action == HNode.MOUSEMOVE){
+			String e = getExplanation();
+			if (!StringUtil.blank(e)){
+				MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+				if (f!=null && f instanceof MesquiteWindow){
+					((MesquiteWindow)f).setExplanation(e);
+				}
+			}
+			e = getAnnotation();
+			if (!StringUtil.blank(e)){
+				MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+				if (f!=null && f instanceof MesquiteWindow){
+					((MesquiteWindow)f).setAnnotation(e, "Footnote above refers to file " + getName());
+				}
+			}
+		}
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public void hSupplementTouched(int index){}
+	/* ---------------- for HNode interface ----------------------*/
+	public Image getHImage(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Color getHColor(){
+		return ColorTheme.getInterfaceBackgroundPale();  //project color
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public boolean getHShow(){
+		return true; 
+	}
+}
+
+class DirFilenameFilter implements FilenameFilter {
+	public boolean accept(File dir, String name){
+		File f = new File(dir + MesquiteFile.fileSeparator + name);
+		if (f.exists() && f.isDirectory())
+			return true;
+		return false;		
+	}
+}
+class MqFilterInputStream extends FilterInputStream {
+	public MqFilterInputStream (InputStream s){
+		super(s);
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteFileDialog.java b/Source/mesquite/lib/MesquiteFileDialog.java
new file mode 100644
index 0000000..2e09fad
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteFileDialog.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+
+/*===============================================*/
+/** A dialog box*/
+public class MesquiteFileDialog extends FileDialog implements Commandable, Listable {
+	String path = MesquiteTrunk.getRootPath(); //TODO: use default directory
+	String message = null;
+	String fileName = null;
+	boolean holdsConsoleFocus = false;
+	boolean doneByConsole = false;
+	int type;
+	//MFDThread mfdThread = null;
+	public static MesquiteFileDialog currentFileDialog = null;
+	public MesquiteFileDialog (MesquiteWindow f, String message, int type) {
+		super(getFrame(f), message, type);
+		this.message = message;
+		this.type = type;
+		currentFileDialog = this;
+		//mfdThread = new MFDThread(this);
+		//mfdThread.start();
+		MainThread.incrementSuppressWaitWindow();
+	}
+	static Frame getFrame(MesquiteWindow f){
+		if (f == null)
+			return null;
+		return f.getParentFrame();
+	}
+	public void setDirectory(String path){
+		super.setDirectory(path);
+		this.path = path;
+		if (path != null && !path.endsWith(MesquiteFile.fileSeparator))
+			path += MesquiteFile.fileSeparator;
+	}
+	public String getFile(){
+		if (doneByConsole)
+			return fileName;
+		return super.getFile();
+	}
+	public String getDirectory(){
+		if (doneByConsole) {
+			if (path != null && !path.endsWith(MesquiteFile.fileSeparator))
+				path += MesquiteFile.fileSeparator;
+			return path;
+		}
+		return super.getDirectory();
+	}
+	public String getName(){
+		String s = "";
+		if (getTitle() == null)
+			s = "FileDialog";
+		else
+			s =  "File Dialog: " + getTitle();
+		if (getDirectory() != null)
+			s += " (" + getDirectory() + ")";
+		return s;
+	}
+	boolean waiting = false;
+	public void setVisible(boolean vis){
+
+
+		if (type == 3){  //choosing a directory
+			if (vis) {
+				System.out.println("Choose Directory Dialog box shown.  Message: " + message);
+				System.out.println("");
+
+				showFiles();
+				System.out.println("Enter \"chooseThis\" to choose current directory; number to open directory");
+				ConsoleThread.setConsoleObjectCommanded(this, false, true);
+				holdsConsoleFocus = true;
+				if (!MesquiteWindow.GUIavailable ||  MesquiteWindow.suppressAllWindows) {
+					try {
+						waiting = true;
+						while (waiting)
+							Thread.sleep(20);
+					}
+					catch (InterruptedException e){
+					}
+					return;
+				}
+			}
+			else {
+				if (holdsConsoleFocus)
+					ConsoleThread.releaseConsoleObjectCommanded(this, true);
+				holdsConsoleFocus = false;
+
+			}
+		}
+		else if (type == FileDialog.LOAD){
+			if (vis) {
+				System.out.println("Open File Dialog box shown.  Message: " + message);
+				System.out.println("");
+
+				showFiles();
+
+				ConsoleThread.setConsoleObjectCommanded(this, false, true);
+				holdsConsoleFocus = true;
+				if (!MesquiteWindow.GUIavailable ||  MesquiteWindow.suppressAllWindows) {
+					try {
+						waiting = true;
+						while (waiting)
+							Thread.sleep(20);
+					}
+					catch (InterruptedException e){
+					}
+					return;
+				}
+			}
+			else {
+				if (holdsConsoleFocus)
+					ConsoleThread.releaseConsoleObjectCommanded(this, true);
+				holdsConsoleFocus = false;
+
+			}
+		}
+		else {
+				if (vis) {
+					System.out.println("Save File Dialog box shown.  Message: " + message);
+					System.out.println("");
+
+					showFiles();
+					System.out.println("Enter name of file to be saved as \"name '<filename>'\"");
+					ConsoleThread.setConsoleObjectCommanded(this, false, true);
+					holdsConsoleFocus = true;
+					if (!MesquiteWindow.GUIavailable ||  MesquiteWindow.suppressAllWindows) {
+						try {
+							waiting = true;
+							while (waiting)
+								Thread.sleep(20);
+						}
+						catch (InterruptedException e){
+						}
+						return;
+					}
+				}
+				else {
+					if (holdsConsoleFocus)
+						ConsoleThread.releaseConsoleObjectCommanded(this, true);
+					holdsConsoleFocus = false;
+
+				}
+			}
+		if (!vis){
+			if (currentFileDialog == this)
+				currentFileDialog = null;
+			super.setVisible(false);
+		}
+		else {
+			super.setVisible(true);
+			/*
+			mfdThread.pleaseShow = true;
+			mfdThread.start();
+			try {
+				while (mfdThread.go)
+					Thread.sleep(20);
+			}
+			catch (InterruptedException e){
+			}*/
+		}
+		
+
+	}
+	void sv(){
+		super.setVisible(true);
+	}
+	public void dispose(){
+
+		if (currentFileDialog == this)
+			currentFileDialog = null;
+		if (alreadyDisposed)
+			return;
+		alreadyDisposed = true;
+		super.dispose();
+		if (holdsConsoleFocus)
+			ConsoleThread.releaseConsoleObjectCommanded(this, true);
+		holdsConsoleFocus = false;
+		MainThread.decrementSuppressWaitWindow();
+
+	}
+	boolean alreadyDisposed = false;
+	/*.................................................................................................................*/
+	/** A request for the object to perform a command.  It is passed two strings, the name of the command and the arguments.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(getClass(), null, null, commandName, "show")) {
+			showFiles();
+		}
+		else if (checker.compare(getClass(), null, null, commandName, "up")) {
+			if (path == null)
+				return null;
+			if (path.endsWith(MesquiteFile.fileSeparator))
+				path = path.substring(0, path.length()-1);
+			path = StringUtil.getAllButLastItem(path, MesquiteFile.fileSeparator) + MesquiteFile.fileSeparator;  
+
+			showFiles();
+			if (type == FileDialog.SAVE)
+				System.out.println("Enter name of file to be saved as \"name '<filename>'\"");
+		}
+		else if (checker.compare(getClass(), null, null, commandName, "name")) {
+			if (path == null)
+				return null;
+			MesquiteInteger pos = new MesquiteInteger();
+			String name = ParseUtil.getFirstToken(arguments, pos);
+			if (!StringUtil.blank(name)){
+				File ff = new File(path + name);
+				if (ff.isDirectory()) {
+					path = path + name + MesquiteFile.fileSeparator;
+					showFiles();
+					return null;
+				}
+				if (type != 3){
+					fileName = name;
+				doneByConsole = true;
+				waiting = false;
+				setVisible(false);
+				dispose();
+				}
+			}
+		}
+		else if (checker.compare(getClass(), null, null, commandName, "chooseThis")) {
+			if (path == null)
+				return null;
+			
+					fileName = null;
+				doneByConsole = true;
+				waiting = false;
+				setVisible(false);
+				dispose();
+			
+		}
+		else if (checker.compare(getClass(), null, null, commandName, "cancel")) {
+
+				fileName = null;
+				path = null;
+				doneByConsole = true;
+				waiting = false;
+				setVisible(false);
+				dispose();
+
+		}
+		else {
+			if (path == null)
+				return null;
+			MesquiteInteger pos = new MesquiteInteger();
+			int im = MesquiteInteger.fromFirstToken(commandName, pos);
+			if (MesquiteInteger.isCombinable(im)){
+				im--;
+				if (im >=0 && im<getNumFiles()){
+					String file = getFileName(im);
+					File ff = new File(path + file);
+					if (ff.isDirectory()) {
+						path = path + file + MesquiteFile.fileSeparator;
+						showFiles();
+					}
+					else if (type == FileDialog.LOAD) {
+						doneByConsole = true;
+						fileName = file;
+						waiting = false;
+						setVisible(false);
+						dispose();
+					}
+				}
+			}
+			
+		}
+		/*
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+		 */
+		return null;
+	}
+	public int getNumFiles(){
+		if (path == null)
+			return 0;
+		File f = new File(path);
+		if (f.isDirectory()){
+			String[] list = f.list();
+			return list.length;
+		}
+		return 1;
+	}
+	public String getFileName(int i){
+		if (path == null)
+			return null;
+		File f = new File(path);
+		if (f.isDirectory()){
+			String[] list = f.list();
+			if (i>=0 && i<list.length)
+				return list[i];
+		}
+		return null;
+	}
+	public void showFiles(){
+		if (path == null)
+			return;
+		File f = new File(path);
+		if (f.isDirectory()){
+			System.out.println("Directory : " + path);
+			String[] list = f.list();
+			if (list==null)
+				return;
+			for (int i = 0; i<list.length; i++){
+				File ff = new File(path + list[i]);
+				if (ff.isDirectory())
+					System.out.println("  " + (i+1) + " - " + list[i] + "/");
+				else
+					System.out.println("  " + (i+1) + " - " + list[i]);
+			}
+		}
+		System.out.println("Enter number to select file");
+	}
+
+}
+
+class MFDThread extends Thread {
+	MesquiteFileDialog parent;
+	boolean pleaseShow = false;
+	int count = 0;
+	boolean go= true;
+	public MFDThread(MesquiteFileDialog parent){
+		this.parent = parent;
+	}
+	public void run(){
+		go = true;
+		try{
+			while (go && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting){
+				Thread.sleep(50);
+				if (pleaseShow){
+					parent.sv();
+					go = false;
+				}
+			}
+		}
+		catch (InterruptedException e){
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteFileUtil.java b/Source/mesquite/lib/MesquiteFileUtil.java
new file mode 100644
index 0000000..dedcc46
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteFileUtil.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.io.File;
+
+public class MesquiteFileUtil {
+
+	/*.................................................................................................................*/
+	public static String createDirectoryForFiles(MesquiteModule module, boolean askForLocation, String name) {
+		MesquiteBoolean directoryCreated = new MesquiteBoolean(false);
+		String rootDir = null;
+		if (!askForLocation)
+			rootDir = module.createEmptySupportDirectory(directoryCreated) + MesquiteFile.fileSeparator;  //replace this with current directory of file
+		if (!directoryCreated.getValue()) {
+			rootDir = MesquiteFile.chooseDirectory("Choose folder for storing "+name+" files");
+			if (rootDir==null) {
+				MesquiteMessage.discreetNotifyUser("Sorry, directory for storing "+name+" files could not be created.");
+				return null;
+			} else
+				rootDir += MesquiteFile.fileSeparator;
+		}
+		return rootDir;
+	}
+	
+	public static final int IN_SUPPORT_DIR = 0;
+	public static final int BESIDE_HOME_FILE = 1;
+	public static final int ASK_FOR_LOCATION = 2;
+	/*.................................................................................................................*/
+	public static String createDirectoryForFiles(MesquiteModule module, int location, String name, String suffix, boolean createUniqueDatedName) {
+		MesquiteBoolean directoryCreated = new MesquiteBoolean(false);
+		String rootDir = null;
+		if (location == IN_SUPPORT_DIR)
+			rootDir = module.createEmptySupportDirectory(directoryCreated) + MesquiteFile.fileSeparator;  //replace this with current directory of file
+		else if (location == BESIDE_HOME_FILE) {
+			String dir = module.getProject().getHomeFile().getDirectoryName();
+			String path = dir + name;
+			if (createUniqueDatedName) {
+				path+= "-" + StringUtil.getDateDayOnly() + suffix;
+				path = MesquiteFile.getUniqueNumberedPath(path);
+			}
+			File f = new File(path);
+			boolean b = f.mkdir();
+			directoryCreated.setValue(b);
+			if (b)
+				rootDir = path + MesquiteFile.fileSeparator;
+		}
+		if (!directoryCreated.getValue()) {
+			rootDir = MesquiteFile.chooseDirectory("Choose folder for storing "+name+" files");
+			if (rootDir==null) {
+				MesquiteMessage.discreetNotifyUser("Sorry, directory for storing "+name+" files could not be created.");
+				return null;
+			} else
+				rootDir += MesquiteFile.fileSeparator;
+		}
+		return rootDir;
+	}
+	/*.................................................................................................................*/
+	public static String createDirectoryForFiles(MesquiteModule module, int location, String name, String suffix) {
+		return createDirectoryForFiles( module,  location,  name,  suffix, true);
+	}
+
+
+}
diff --git a/Source/mesquite/lib/MesquiteFrame.java b/Source/mesquite/lib/MesquiteFrame.java
new file mode 100644
index 0000000..3151bc7
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteFrame.java
@@ -0,0 +1,2197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.*;
+import java.util.*;
+import javax.swing.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+/* ======================================================================== */
+/** an intermediary class that can be changed to extend Panel versus Frame, to allow embedding versus not 
+UNEMBEDDED VERSION */
+public class MesquiteFrame extends Frame implements Commandable {
+
+	Vector windows;
+	Vector orderedWindows;
+	MesquiteWindow frontWindow;
+	private CardLayout mainLayout, resourcesLayout, poptileLayout;
+	MesquiteProject project;
+	MesquiteWindow projectWindow;
+	MesquiteModule ownerModule;
+	static int numTotal = 0;
+	boolean isSystemFrame = false;
+	public static int cornerBuffer = 8;
+
+
+	int num = 0;
+	int id = 0;
+	int leftPoptile = -1;
+	Panel main;
+	private Panel resources;
+	Panel  poptile;
+	private BetweenPanel rBetweenPanel;   // this is the vertical bar between the project panel and the main window region
+	private BetweenPanel pBetweenPanel;
+	private static int BETWEENWIDTH = 6;
+	public static final int RESOURCES = 0;  // for project
+	public static final int MAIN = 1;
+	public static final int POPTILE = 2;
+	boolean resourcesFullWindow = false; //0 for closed; 1 for open partly; 2 for full window;
+	boolean resourcesClosedWhenMinimized = false; //0 for closed; 1 for open partly; 2 for full window;
+	int resourcesWidth = 0;
+	int poptileWidth = 300;
+	public static int defaultResourcesWidth = 100; 
+	public static boolean respectFileSpecificResourceWidth = true; 
+	public static int resourcesFontSize = 10;
+	FrameTabsPanel tabs;
+	int tabHeight = 36;
+	boolean isPrimarylMesquiteFrame = false;  //true if it's the main window with projects/log/search
+	boolean compacted = false;
+	public static long totalCreated = 0;
+	public static long totalDisposed = 0;
+	public static long totalFinalized  = 0;
+	Color backgroundColor;
+	public MesquiteFrame(boolean compactible, Color backgroundColor) {
+		super();
+		this.backgroundColor = backgroundColor;
+		totalCreated++;
+		id = numTotal++;
+		if (MesquiteTrunk.isMacOSXPanther33())
+			compacted = false;
+		else
+			compacted = compactible;
+		windows = new Vector();
+		orderedWindows = new Vector();
+		oldInsetTop=oldInsetBottom=oldInsetRight= oldInsetLeft= -1; 
+		/**/
+		setResizable(true);
+		setBackground(backgroundColor);
+		setLayout(null);
+		rBetweenPanel = new BetweenPanel(this);
+		add(rBetweenPanel);
+		pBetweenPanel = new BetweenPanel(this);
+		add(pBetweenPanel);
+		poptile = new Panel();
+		poptile.setBackground(backgroundColor);
+		add(poptile);
+		resources = new Panel();
+		resources.setBackground(backgroundColor);
+		add(resources);
+		main = new Panel();
+		main.setBackground(backgroundColor);
+		if (compactible){
+			tabs = new FrameTabsPanel(this);
+			add(tabs);
+		}
+		else tabHeight = 0;
+		add(main);
+
+
+		resetSizes(true);
+		main.setLayout(mainLayout = new CardLayout());
+		resources.setLayout(resourcesLayout = new CardLayout());
+		poptile.setLayout(poptileLayout = new CardLayout());
+		addComponentListener(new MWCE(this));
+
+		/* EMBEDDED if embedded remove this */
+		addWindowListener(new MWWE(this));
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	public void setAsPrimaryMesquiteFrame(boolean p){
+		isPrimarylMesquiteFrame = p;
+	}
+	public void setResizable(boolean r){
+		if (project != null && !r)
+			return;
+		super.setResizable(r);
+	}
+	public int getID(){
+		return id;
+	}
+	public MesquiteModule getOwnerModule(){ //mesquite or basic file coordinator
+		return ownerModule;
+	}
+	public void setOwnerModule(MesquiteModule mb){ //mesquite or basic file coordinator
+		ownerModule = mb;
+		if (ownerModule != null)
+			project = ownerModule.getProject();
+		isSystemFrame = mb == MesquiteTrunk.mesquiteTrunk;
+		if (tabs != null)
+			tabs.setBackground(ColorTheme.getExtInterfaceBackground(isSystemFrame));
+	}
+
+	/*.................................................................................................................*/
+	boolean alreadyDisposed = false;
+	public void dispose() {
+		if (alreadyDisposed)
+			return;
+		try{
+			removeAll();
+		}
+		catch (Exception e){
+			//strange things can happen with threading...
+		}
+		alreadyDisposed = true;
+		if (activeWindow == this)
+			activeWindow = null;
+		totalDisposed++;
+
+		super.dispose();
+		ownerModule = null;
+		if (project != null && project.getFrame() == this) {
+			project.setFrame(null);
+		}
+		project = null;
+		windows = null;
+	}
+	public void setMenuBar(MesquiteWindow which, MenuBar mbar) {
+		if (which == frontWindow) {
+			try {
+				super.setMenuBar(mbar);
+				which.repaintInfoBar();
+			}
+			catch(Exception e){
+			}
+		}
+		checkInsets(true);
+	}
+	public int getNumWindows(){
+		return windows.size();
+	}
+	public int getNumWindows(int location){
+		int count =0;
+		for (int i=orderedWindows.size()-1; i>=0; i--){
+			MesquiteWindow w = (MesquiteWindow)orderedWindows.elementAt(i);
+			if (w.getTileLocation() == location)
+				count++;
+		}
+		return count;
+	}
+	public void windowTitleChanged(MesquiteWindow w) {
+		if (windows.size() == 1)
+			setTitle(w.getTitle());
+		else if (w instanceof SystemWindow)
+			setTitle("Mesquite");
+		else if (project == null)
+			setTitle("Mesquite Window");
+		else if (project.hasName())
+			setTitle(project.getName());
+		else
+			setTitle(project.getHomeFileName());
+		if (tabs !=null)
+			tabs.repaint();
+	}
+	public void setResourcesState(boolean resourcesFullWindow, boolean resourcesClosedWhenMinimized, int resourcesWidth){
+		this.resourcesFullWindow = resourcesFullWindow; 
+		this.resourcesClosedWhenMinimized = resourcesClosedWhenMinimized; 
+		this.resourcesWidth = resourcesWidth;
+		MesquiteWindow w = frontMostInLocation(RESOURCES);
+		if (w != null)
+			w.setMinimized(resourcesClosedWhenMinimized);
+		if (tabs != null)
+			tabs.repaint();
+		resetSizes(true);
+	}
+	public boolean getResourcesFullWindow(){
+		return resourcesFullWindow; 
+	}
+	public boolean getResourcesClosedWhenMinimized(){
+		return resourcesClosedWhenMinimized; 
+	}
+	public int getResourcesWidth(){
+		return resourcesWidth; 
+	}
+	public void setPopoutWidth(int poptileWidth){
+		this.poptileWidth = poptileWidth;
+		if (tabs != null)
+			tabs.repaint();
+		resetSizes(true);
+	}
+	public int getPopoutWidth(){
+		return poptileWidth; 
+	}
+	public boolean anythingPopped(){
+		MesquiteWindow w = frontMostInLocation(MesquiteFrame.POPTILE);
+		return w != null;
+	}
+	public boolean anythingPoppedOtherThanMe(MesquiteWindow me){
+		for (int i=orderedWindows.size()-1; i>=0; i--){
+			MesquiteWindow w = (MesquiteWindow)orderedWindows.elementAt(i);
+			if (w.getTileLocation() == POPTILE && w != me)
+				return true;
+		}
+		return false;
+	}
+	public void removePage(MesquiteWindow w){
+		if (w.getTileLocation()==MAIN)
+			main.remove(w.outerContents);
+		else if (w.getTileLocation()==RESOURCES)
+			resources.remove(w.outerContents);
+		else if (w.getTileLocation()==POPTILE)
+			poptile.remove(w.outerContents);
+		setAsFrontWindow(null);
+		if (windows != null){
+			windows.removeElement(w);
+			orderedWindows.removeElement(w);
+			showFrontWindow();
+		}
+	}
+	/*.................................................................................................................*/
+	public void addPage(MesquiteWindow w){
+		addPage(w, w.getTileLocation());
+	}
+	/*.................................................................................................................*/
+	public void addPage(MesquiteWindow w, int where){
+
+		w.inParent();
+
+		w.outerContents.setBackground(ColorTheme.getInterfaceElement());
+		setBackground(ColorTheme.getInterfaceElement());
+		//	if (tabs !=null)
+		//		tabs.setBackground(light);
+		String id = Integer.toString(w.getID());
+		if (where == MAIN){
+			main.add(w.outerContents, id);
+			mainLayout.addLayoutComponent(w.getOuterContentsArea(), id);
+			w.setTileLocation(MAIN);
+		}
+		else if (where == POPTILE){
+			poptile.add(w.outerContents, id);
+			poptileLayout.addLayoutComponent(w.getOuterContentsArea(), id);
+			w.setTileLocation(POPTILE);
+		}
+		else if (where == RESOURCES){
+			resourcesWidth = defaultResourcesWidth;
+			resources.add(w.outerContents, id);
+			projectWindow = w;
+			resourcesLayout.addLayoutComponent(w.getOuterContentsArea(), id);
+			w.setTileLocation(RESOURCES);
+			w.setMinimized(resourcesClosedWhenMinimized);
+		}
+		windows.addElement(w);
+
+		orderedWindows.addElement(w);
+		setAsFrontWindow(w);
+		resetSizes(true);
+		if (tabs !=null)
+			tabs.repaint();
+		if (windows.size() == 1)
+			setTitle(w.getTitle());
+		else if (w instanceof SystemWindow)
+			setTitle("Mesquite");
+		else if (project == null)
+			setTitle("Mesquite Window");
+		else if (project.hasName())
+			setTitle(project.getName());
+		else
+			setTitle(project.getHomeFileName());
+
+
+	}
+	public void fixFrontness(){
+		MesquiteWindow w = frontMostInLocation(MesquiteFrame.POPTILE);
+		if (w!= null && poptile.getComponentZOrder(w.outerContents) != 0){
+			showInLayout(w.getTileLocation(), Integer.toString(w.getID()));	
+			reconnect(w);
+		}
+		w = frontMostInLocation(MesquiteFrame.MAIN);
+		if (w != null && main.getComponentZOrder(w.outerContents) != 0){
+			showInLayout(w.getTileLocation(), Integer.toString(w.getID()));	
+			reconnect(w);
+		}
+	}
+	public void incrementPanelWidth(BetweenPanel p, int w){
+		if (p == rBetweenPanel){
+			if (w+ resourcesWidth<3)
+				return;
+			resourcesWidth = w + resourcesWidth;
+
+			resetSizes(true);
+			defaultResourcesWidth = resourcesWidth;
+			MesquiteTrunk.mesquiteTrunk.storePreferences();
+		}
+		else if (p == pBetweenPanel){
+			if (poptileWidth-w<50)
+				return;
+			poptileWidth = poptileWidth-w;
+			resetSizes(true);
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean windowPresent(MesquiteWindow window){
+		for (int i = 0; i<windows.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+			if (w == window)
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	private MesquiteWindow findWindow(String s){
+		for (int i = 0; i<windows.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+			if (Integer.toString(w.getID()).equals(s))
+				return w;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void showPage(MesquiteWindow w){
+		//	if (w == frontWindow)
+		//		return;
+		showPage(Integer.toString(w.getID()));
+		setAsFrontWindow(w);
+
+	}
+	public void showFirstPage(){
+		mainLayout.first(main);
+	}
+	public void showNextPage(){
+		mainLayout.next(main);
+
+	}
+	/*.................................................................................................................*/
+	public void showPage(int i){
+		if (i <0 || i>=windows.size())
+			return;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		//	if (w == frontWindow)
+		//		return;
+		showPage(Integer.toString(w.getID()));
+	}
+
+	/*.................................................................................................................*/
+	public void showPage(String s){
+		MesquiteWindow w = findWindow(s);
+		if (w == null){
+			MesquiteMessage.printStackTrace("Attempting to show page; page not found " + s);
+			return;
+		}
+		showInLayout(w.getTileLocation(), s);
+		setAsFrontWindow(w);
+		resetSizes(true);
+		validate();
+		if (tabs !=null)
+			tabs.repaint();
+		setMenuBar(w, w.getMenuBar());
+
+	}
+	void showInLayout(int location, String s){
+		try {
+			if (location == MAIN) {
+				if (resourcesFullWindow){
+					resourcesFullWindow = false;
+					resetSizes(true);
+				}
+				mainLayout.show(main, s);
+			}
+			else if (location == POPTILE) {
+				if (resourcesFullWindow){
+					resourcesFullWindow = false;
+					resetSizes(true);
+				}
+				poptileLayout.show(poptile, s);
+			}
+			else if (location == RESOURCES) {
+				if (!resourcesFullWindow){
+					resourcesFullWindow = true;
+					resetSizes(true);
+				}
+				resourcesLayout.show(resources, s);
+			}
+		}
+		catch (Throwable t){
+			MesquiteMessage.warnProgrammer("Exception or Error in showInLayout (MesquiteFrame); details in Mesquite log file.");
+			MesquiteFile.throwableToLog(this, t);
+		}
+	}
+	/*.................................................................................................................*/
+	public void dispose(MesquiteWindow w){
+		if (windows == null || windows.size()==0)
+			dispose();
+	}
+	void closeWindowRequested(){
+		if (isPrimarylMesquiteFrame){
+			if (MesquiteTrunk.mesquiteTrunk.projects.getNumProjects() == 0)
+				MesquiteTrunk.mesquiteTrunk.doCommand("quit", null, CommandChecker.defaultChecker);
+			else {
+				toBack();
+				MesquiteTrunk.mesquiteTrunk.doCommand("showAllWindows", null, CommandChecker.defaultChecker);
+
+			}
+		}
+		else if (ownerModule != null && ownerModule.getProject() != null && compacted){
+
+			MesquiteProject proj = ownerModule.getProject();
+			FileCoordinator coord = ownerModule.getFileCoordinator();
+			coord.closeFile(proj.getHomeFile());
+
+		}
+
+		else if (frontWindow != null && frontWindow.closeWindowCommand != null)
+			frontWindow.closeWindowCommand.doIt(null); //this might be best done on separate thread, but because of menu disappearance bug after closing a window in Mac OS, is done immediately
+	}
+
+	/*.................................................................................................................*/
+	boolean permitGoAway(int i){
+		if (windows == null)
+			return false;
+		if (i <0 || i>=windows.size())
+			return false;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		if(w.getTileLocation() == RESOURCES  && !resourcesFullWindow)
+			return false;  //don't show goaway if resources and not frontmost
+
+		return !(w instanceof SystemWindow);
+	}
+	/*.................................................................................................................*/
+	boolean goAwayOrShow(int i){
+		if (!permitGoAway(i))
+			return false;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+
+		if(w.getTileLocation() != RESOURCES || resourcesFullWindow)
+			return true;  //show goaway if not resources or if now full window
+
+		if (resourcesClosedWhenMinimized)  //not full window; therefore closed
+			return false;
+		return true;
+
+	}
+	/*.................................................................................................................*/
+	boolean showMinimizeMaximize(int i){
+		if (windows == null || i <0 || i>=windows.size())
+			return false;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		if (w.getTileLocation() == RESOURCES){  //resources; different rules
+			return !resourcesFullWindow;
+		}
+		return false; //!(w instanceof SystemWindow);
+	}
+	/*.................................................................................................................*/
+	public boolean showPopOut(int i){
+		if (i <0 || i>=windows.size())
+			return false;
+		if (i ==0)
+			return false;
+
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		if (w.getTileLocation() == MAIN && getNumWindows(MAIN)<=1)
+			return false;
+		return !(w instanceof SystemWindow);
+	}
+	public void popOut(MesquiteWindow w, boolean makeVisible){
+		if (windows.indexOf(w)<0)
+			return;
+		popOut(windows.indexOf(w), makeVisible);
+	}
+
+	public void popOut(int i, boolean makeVisible){
+		if (windows.size() == 1)
+			return;
+		MesquiteWindow w = null;
+		try {
+			w = (MesquiteWindow)windows.elementAt(i);
+		}
+		catch (Exception e){
+			return;
+		}
+		if (w.popAsTile){
+			removePage(w); //setVisible(w, false);  //remove from resources
+			w.poppedOut = true;
+			addPage(w, POPTILE); 
+			if (makeVisible){
+				setVisible(w, makeVisible);
+				setAsFrontWindow(w);
+				showFrontWindow();
+				tabs.repaint();
+			}
+		}
+		else {
+			w.poppedOut = true;
+			MesquiteFrame parentFrame = new MesquiteFrame(false, backgroundColor);
+			parentFrame.setOwnerModule(ownerModule);
+			Menu fM = new MesquiteMenu("File");
+			MenuBar mBar = new MenuBar();
+			mBar.add(fM);
+			parentFrame.setMenuBar(mBar);
+			parentFrame.setLocation(getLocation().x + 50, getLocation().y + 50);
+			/*			Dimension s = getSize();
+			s.height -= tabHeight;
+			parentFrame.storeInsets(parentFrame.getInsets());
+			parentFrame.setSize(s);
+			 */			Rectangle s = getBounds(w);
+			 //s.height -= tabHeight;
+			 parentFrame.storeInsets(parentFrame.getInsets());
+			 parentFrame.setBounds(s);
+			 /**/
+			 parentFrame.saveFullDimensions();
+			 setVisible(w, false);
+			 w.setParentFrame(parentFrame);
+			 w.poppedOut = true;
+
+			 parentFrame.addPage(w); 
+			 parentFrame.setVisible(makeVisible);
+			 MesquiteModule mb = w.getOwnerModule();
+			 if (mb != null){
+				 mb.resetContainingMenuBar();
+			 }
+		}
+
+		MesquiteWindow fw = frontMostInLocation(MAIN);
+		reconnect(fw);
+	}
+	public void popIn(MesquiteWindow w){
+		if (windows == null || (!w.popAsTile && windows.indexOf(w)>=0))  //POPOUTBUGS: If window is popped out in separate window, then this doesn't work, in part as windows.indexOf(w)=0 but there is only one window.  
+			return;
+		if (w.popAsTile){
+			setVisible(w, false);  //remove from resources
+			w.poppedOut = false;
+			addPage(w, MAIN); 
+			setVisible(w, true);
+		}
+		else {
+			MesquiteFrame parentFrame = w.getParentFrame();
+			if (parentFrame == this)
+				return;
+			parentFrame.setVisible(w, false);
+			parentFrame.hide();
+			parentFrame.dispose();
+			addPage(w);
+			setVisible(w, true);
+			w.setParentFrame(this);
+			MesquiteModule mb = w.getOwnerModule();
+			if (mb != null){
+				mb.resetContainingMenuBar();
+			}
+			w.poppedOut = false;
+		}
+		resetSizes(true);
+
+	}
+	/*.................................................................................................................*/
+	public MesquiteWindow getMesquiteWindow(){
+		return (MesquiteWindow)windows.elementAt(0); //should return frontmost
+	}
+	/*.................................................................................................................*/
+	public void hide(MesquiteWindow w){
+		setVisible(w, false);
+	}
+	public MesquiteWindow frontMostInLocation(int location){
+		for (int i=orderedWindows.size()-1; i>=0; i--){
+			MesquiteWindow w = (MesquiteWindow)orderedWindows.elementAt(i);
+			if (w.getTileLocation() == location)
+				return w;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(int i){
+		if (i <0 || i>=windows.size())
+			return;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		if (w.getTileLocation()==RESOURCES){
+			//hide(w);
+			resourcesFullWindow = false;
+			MesquiteWindow ww = frontMostInLocation(MAIN);
+			setAsFrontWindow(ww);
+			resetSizes(true);
+
+		}
+		else if (w.ownerModule != null)
+			w.ownerModule.windowGoAway(w);
+		else if (w.closeWindowCommand != null)
+			w.closeWindowCommand.doIt(null); 
+	}
+	/*.................................................................................................................*/
+	public void toggleMinimize(int i){
+		if (i <0 || i>=windows.size())
+			return;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		if (w.getTileLocation() == RESOURCES){
+			w.setMinimized(!w.isMinimized());
+			resourcesClosedWhenMinimized = w.isMinimized();
+			resetSizes(true);
+			if (tabs !=null)
+				tabs.repaint();
+		}
+	}
+	public void hide(int i){
+		if (i <0 || i>=windows.size())
+			return;
+		MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+		hide(w);
+	}
+	/*.................................................................................................................*/
+	public void setVisible(MesquiteWindow w, boolean vis){
+		if (windows == null)
+			return;
+		if (vis){
+			if (w != null && project != null && project.isDoomed)
+				return;
+			if (windows.indexOf(w)<0){
+				//	if (!CommandRecord.getRecNSIfNull().scripting())
+				addPage(w);
+			}
+			if (!MesquiteThread.isScripting()){
+				w.readyToPaint = true;
+				showInLayout(w.getTileLocation(), Integer.toString(w.getID()));
+
+			}
+			setAsFrontWindow(w);
+			if (tabs !=null)
+				tabs.repaint();
+			try {
+				validate();
+			}
+			catch(Exception e){
+			}
+			if (!isVisible())
+				setVisible(true);
+			reconnect(w);
+		}
+		else {
+			if (w == frontWindow){
+				setAsFrontWindow(null);
+			}
+			if (w == frontWindow && windows.size() ==1){ //if only one left, then treat it as a whole frame hide
+				setVisible(false);
+				return;
+			}
+			try {
+				if (w.getTileLocation() == MAIN){
+					mainLayout.removeLayoutComponent(w.getOuterContentsArea());	
+					main.remove(w.getOuterContentsArea());
+				}
+				else if (w.getTileLocation() == RESOURCES){
+					resourcesLayout.removeLayoutComponent(w.getOuterContentsArea());	
+					resources.remove(w.getOuterContentsArea());
+				}
+				else if (w.getTileLocation() == POPTILE){
+					poptileLayout.removeLayoutComponent(w.getOuterContentsArea());	
+					poptile.remove(w.getOuterContentsArea());
+				}
+				int loc = w.getTileLocation();
+				windows.removeElement(w);
+				w.removedFromParent();
+				orderedWindows.removeElement(w);
+				if (orderedWindows.size() > 0 && !MesquiteThread.isScripting())
+					showPage((MesquiteWindow)orderedWindows.elementAt(orderedWindows.size()-1));
+				if (tabs !=null)
+					tabs.repaint();
+				resetSizes(true);
+				if (windows.size()==0){
+					setVisible(false);
+				}
+				else if (windows.size() == 1)
+					resetSizes(true);
+				MesquiteWindow fw = frontMostInLocation(loc);
+				if (fw != null)
+					reconnect(fw);
+			}
+			catch (Exception e){  //this might occur if disposing as this call is coming in
+			}
+		}
+
+	}
+	/*
+	void listWindows(String heading){
+		System.out.println("))))))))" + heading);
+		for (int i = 0; i< orderedWindows.size(); i++){
+			System.out.println("      " + i + " -- " + ((MesquiteWindow)orderedWindows.elementAt(i)).getTitle());
+		}
+		if (frontWindow != null)
+			System.out.println("      front -- " + frontWindow.getTitle());
+	}
+	 */
+
+	private void reconnect(MesquiteWindow w){
+		if (w == null)
+			return;
+		if (w.getTileLocation() == RESOURCES || isPrimarylMesquiteFrame)
+			return;
+		for (int i = 0; i<windows.size(); i++){  //This is a workaround for bug in OS X Java 1.7 and higher by which panels behind would leak to panels in front
+			MesquiteWindow ww = (MesquiteWindow)windows.elementAt(i);
+			if (ww != w && ww.getTileLocation() == w.getTileLocation()){ 
+				ww.disconnectGraphics();
+			}
+		}
+		w.reconnectGraphics();
+		invalidate();
+		validate();
+
+	}
+
+	private void refreshGraphics(){
+		for (int i = 0; i<windows.size(); i++){  //This is a workaround for bug in OS X Java 1.7 and higher by which panels behind would leak to panels in front
+			MesquiteWindow ww = (MesquiteWindow)windows.elementAt(i);
+			//	ww.validate();
+		}
+	}
+
+	public void setAsFrontWindow(MesquiteWindow w){
+		//	frontWindow = null;
+		if (w != null && windows.indexOf(w)>=0) {
+			if (w.getOwnerModule() != null && w.getOwnerModule().isDoomed())
+				return;
+			w.readyToPaint = true;
+			frontWindow = w;
+			if (project != null && windows.indexOf(project.getCoordinatorModule().getModuleWindow())>=0)
+				project.activeWindowOfProject = w;
+			if (orderedWindows != null && orderedWindows.indexOf(w) != orderedWindows.size()-1){
+				orderedWindows.remove(w);
+				orderedWindows.addElement(w);
+			}
+
+			reconnect(w);
+
+
+		}	
+		if (w != null)
+			setMenuBar(w, w.getMenuBar());
+		if (tabs !=null)
+			tabs.repaint();
+	}
+	public void OLDsetAsFrontWindow(MesquiteWindow w){
+		//	frontWindow = null;
+		if (w != null && windows.indexOf(w)>=0) {
+			if (w.getOwnerModule() != null && w.getOwnerModule().isDoomed())
+				return;
+
+			w.readyToPaint = true;
+			frontWindow = w;
+			if (project != null && windows.indexOf(project.getCoordinatorModule().getModuleWindow())>=0)
+				project.activeWindowOfProject = w;
+			if (orderedWindows != null && orderedWindows.indexOf(w) != orderedWindows.size()-1){
+				orderedWindows.remove(w);
+				orderedWindows.addElement(w);
+			}
+		}	
+		if (w != null)
+			setMenuBar(w, w.getMenuBar());
+		if (tabs !=null)
+			tabs.repaint();
+	}
+
+	public void showFrontWindow(){
+		fixFrontness();
+		if (frontWindow != null){
+			showInLayout(frontWindow.getTileLocation(), Integer.toString(frontWindow.getID()));	
+			resetSizes(true);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Shows the window */
+	public void setVisible(boolean vis) {
+		if (doingShow)
+			return;
+		doingShow = true;
+		if (vis){
+			if (!checkInsets(false))
+				resetSizes(true);
+			if (!MesquiteWindow.GUIavailable || MesquiteWindow.suppressAllWindows){
+				doingShow = false;
+				return;
+			}
+		}
+		super.setVisible(vis);
+		doingShow = false;
+		ProgressWindow.allIndicatorsToFront();
+	}
+	int countMenus(){
+		MenuBar b = getMenuBar();
+		if (b == null)
+			return 0;
+		return b.getMenuCount();
+	}
+	/*.................................................................................................................*/
+	public void diagnose(){
+		System.out.println("  FRAME ~~~~~~~~~ visible = " + isVisible() + " size " + getBounds().width + " " + getBounds().height + " this =" + id);
+		System.out.println("  layout  = " + mainLayout);
+		for (int i = 0; i<windows.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+			System.out.println("      " + w.getClass() + " visible = " + w.isVisible() + " loc " + w.getBounds().x + " " + w.getBounds().y + " size " + w.getBounds().width + " " + w.getBounds().height);
+		}
+	}
+	/*.................................................................................................................*/
+	boolean doingShow = false;
+	private int oldInsetTop, oldInsetBottom, oldInsetRight, oldInsetLeft;
+
+	int savedX = 0;
+	int savedY = 0;
+	int savedW = 0;
+	int savedHWithoutTabs = 0;
+	int savedHWithTabs = 0;
+	int savedFullW = 0;
+	int savedFullH = 0;
+	/*.................................................................................................................*
+	public void show(){
+		if (doingShow)
+			return;
+		setVisible(true);
+	}
+
+		/*.................................................................................................................*/
+	protected void saveFullDimensions(){
+		savedFullW = getBounds().width;
+		savedFullH = getBounds().height;
+	}
+
+	/*.................................................................................................................*/
+	public void setSavedDimensions(int w, int h){
+		savedW = w;
+		if (windows != null && (windows.size()>1)){
+			savedHWithoutTabs = h - tabHeight;
+			savedHWithTabs = h;
+		}
+		else {
+			savedHWithoutTabs = h;
+			savedHWithTabs = h + tabHeight;
+		}
+	}
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize. 
+	 * Passed are the requested size of the contents. This frame must accommodate extra for insets in setting its own size*/
+	public void setWindowSize(MesquiteWindow w, int width, int height) {
+		setWindowSize(w, width, height, true);
+	}
+	/*.................................................................................................................*/
+	public void setWindowSize(MesquiteWindow ww,int width, int height, boolean expandOnly) {
+
+		Insets insets = getInsets();
+		storeInsets(insets);
+		boolean adjustWidthOnly = !MesquiteInteger.isCombinable(height);
+		boolean adjustHeightOnly =  !MesquiteInteger.isCombinable(width);
+
+		int totalNeededWidth = getWidth();
+		if (!adjustHeightOnly){
+			totalNeededWidth = width + insets.left + insets.right;
+			if (ww.getTileLocation()== MAIN){
+				if (poptileWidth>0 && frontMostInLocation(POPTILE) != null && frontMostInLocation(POPTILE).popAsTile)
+					totalNeededWidth += poptileWidth; // + BETWEENWIDTH ;
+			}
+			else	if (ww.getTileLocation()== POPTILE){
+				if (ww.popAsTile && frontMostInLocation(MAIN) != null)
+					totalNeededWidth += frontMostInLocation(MAIN).getWidth(); // + BETWEENWIDTH ;
+			}
+
+			/*	if (ww.getTileLocation()== MAIN){
+			MesquiteWindow w = frontMostInLocation(POPTILE);
+			if (w != null)
+				totalNeededWidth += w.getWidth() + BETWEENWIDTH;
+		}
+		else if (ww.getTileLocation()== POPTILE){
+			MesquiteWindow w = frontMostInLocation(MAIN);
+			if (w != null)
+				totalNeededWidth += w.getWidth() + BETWEENWIDTH;
+		}*/
+			if (ww.getTileLocation()!= RESOURCES && resourcesWidth>0 && !resourcesFullWindow && !resourcesClosedWhenMinimized)
+				totalNeededWidth += resourcesWidth; // + BETWEENWIDTH ;
+
+			//	int savedWidth = neededWidth - (insets.left + insets.right);
+			if (expandOnly && totalNeededWidth < getBounds().width){
+				totalNeededWidth = getBounds().width;
+			}
+		}
+
+
+		int totalNeededHeight = getHeight();
+		if (!adjustWidthOnly){
+			totalNeededHeight = height + insets.top +insets.bottom;
+
+			//	int savedHeight = neededHeight - (insets.top +insets.bottom);
+			if ((windows.size()>1))
+				totalNeededHeight += tabHeight;
+			if (expandOnly && totalNeededHeight < getBounds().height){
+				totalNeededHeight = getBounds().height;
+			}
+		}
+		setSavedDimensions(totalNeededWidth, totalNeededHeight);
+		setSize(totalNeededWidth, totalNeededHeight);
+		resetSizes(true);
+		for (int i = 0; i<windows.size(); i++){
+			MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+			w.resetContentsSize();
+		}
+		//storeInsets(getInsets());
+		saveFullDimensions();
+	}
+
+	public Rectangle getBounds(MesquiteWindow w){
+		if (w.getTileLocation() == RESOURCES)
+			return resources.getBounds();
+		else if (w.getTileLocation() == POPTILE)
+			return poptile.getBounds();
+		return main.getBounds();
+	}
+	/*.................................................................................................................*/
+	public void resetSizes(boolean resizeContainedWindows){
+		resetSizes(resizeContainedWindows, false);
+	}
+	/*.................................................................................................................*/
+	public void resetSizes(boolean resizeContainedWindows, boolean force){
+		Insets insets = getInsets();
+		if (!force && (getBounds().width != savedFullW || getBounds().height != savedFullH)){
+		}
+		else if (oldInsetTop!=insets.top || oldInsetBottom !=insets.bottom || oldInsetRight!= insets.right || oldInsetLeft != insets.left) {
+
+			int totalNeededWidth = savedFullW+(insets.right-oldInsetRight)+(insets.left-oldInsetLeft);
+			int totalNeededHeight = savedFullH+(insets.top-oldInsetTop)+(insets.bottom-oldInsetBottom);
+			setSavedDimensions(totalNeededWidth, totalNeededHeight);
+			setSize(totalNeededWidth, totalNeededHeight);
+
+		}
+		saveFullDimensions();
+		storeInsets(insets);
+		int effectiveResourcesWidth = resourcesWidth;
+		boolean effectiveResourcesFullWindow = resourcesFullWindow;
+		if (windows == null)
+			return;
+		if (windows.size()==1 && frontMostInLocation(RESOURCES)!= null)
+			effectiveResourcesFullWindow= true;
+		if (resourcesClosedWhenMinimized)
+			effectiveResourcesWidth = 0;
+		int effectivePoptileWidth = poptileWidth -BETWEENWIDTH;
+		int effectivePBETWEENWIDTH = BETWEENWIDTH;
+
+		if (windows.size()==1 || frontMostInLocation(POPTILE)==null)
+			effectivePoptileWidth= 0;
+		if (effectivePoptileWidth == 0)
+			effectivePBETWEENWIDTH = 0;
+		if (windows.size()>1 || frontMostInLocation(RESOURCES)!= null){
+			if (tabs !=null){
+				tabs.setVisible(true);
+				tabs.setBounds(insets.left, insets.top, getBounds().width - insets.left - insets.right, tabHeight);
+				tabs.repaint();
+			}
+			if (effectiveResourcesFullWindow){
+				resources.setBounds(insets.left, insets.top + tabHeight, getBounds().width - insets.left - insets.right, getBounds().height - insets.top - insets.bottom - tabHeight);
+				if (projectWindow != null)
+					projectWindow.windowResized();
+				main.setVisible(false);
+				main.setBounds(0,0,0,0);
+				rBetweenPanel.setVisible(false);
+				rBetweenPanel.setBounds(0,0,0,0);
+				pBetweenPanel.setVisible(false);
+				pBetweenPanel.setBounds(0,0,0,0);
+				poptile.setVisible(false);
+				poptile.setBounds(0,0,0,0);
+				resources.doLayout();
+			}
+			else {
+				resources.setBounds(insets.left, insets.top + tabHeight, effectiveResourcesWidth- BETWEENWIDTH, getBounds().height - insets.top - insets.bottom - tabHeight);
+				if (projectWindow != null)
+					projectWindow.windowResized();
+
+				main.setBounds(effectiveResourcesWidth + insets.left, insets.top + tabHeight, getBounds().width - insets.left - insets.right - effectiveResourcesWidth - effectivePoptileWidth-effectivePBETWEENWIDTH, getBounds().height - insets.top - insets.bottom - tabHeight);
+				main.setVisible(true);
+				if (effectivePoptileWidth>0){
+					poptile.setVisible(true);
+					leftPoptile = main.getWidth() + main.getX();
+					poptile.setBounds(main.getWidth() + main.getX()+effectivePBETWEENWIDTH, insets.top + tabHeight, effectivePoptileWidth, getBounds().height - insets.top - insets.bottom - tabHeight );
+					pBetweenPanel.setBounds(main.getWidth() + main.getX(), insets.top + tabHeight, effectivePBETWEENWIDTH, getBounds().height - insets.top - insets.bottom - tabHeight);
+					pBetweenPanel.setVisible(true);
+					poptile.doLayout();
+				}
+				else {
+					leftPoptile = -1;
+					poptile.setVisible(false);
+					poptile.setBounds(0,0,0,0);
+					pBetweenPanel.setVisible(false);
+					pBetweenPanel.setBounds(0,0,0,0);
+
+				}
+				rBetweenPanel.setBounds(effectiveResourcesWidth + insets.left- BETWEENWIDTH, insets.top + tabHeight, BETWEENWIDTH, getBounds().height - insets.top - insets.bottom - tabHeight);
+				rBetweenPanel.setVisible(true);
+				resources.doLayout();
+				main.doLayout();
+			}
+			if (resizeContainedWindows){
+
+				for (int i = 0; i<windows.size(); i++){
+					MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+					try{
+						w.resetContentsSize();
+					}
+					catch(Throwable t){
+					}
+				}
+			}
+		}
+		else {
+			if (tabs !=null){
+				tabs.setVisible(false);
+				tabs.setBounds(0,0,0,0);
+			}
+			if (effectiveResourcesFullWindow){
+				resources.setBounds(insets.left, insets.top, getBounds().width - insets.left - insets.right, getBounds().height - insets.top - insets.bottom);
+				main.setVisible(false);
+				main.setBounds(0,0,0,0);
+				rBetweenPanel.setVisible(false);
+				rBetweenPanel.setBounds(0,0,0,0);
+				pBetweenPanel.setVisible(false);
+				pBetweenPanel.setBounds(0,0,0,0);
+				poptile.setVisible(false);
+				poptile.setBounds(0,0,0,0);
+				resources.doLayout();
+			}
+			else {
+				resources.setBounds(insets.left, insets.top + tabHeight, effectiveResourcesWidth, getBounds().height - insets.top - insets.bottom - tabHeight);
+				main.setVisible(true);
+				main.setBounds(effectiveResourcesWidth + insets.left, insets.top, getBounds().width - insets.left - insets.right - effectiveResourcesWidth -effectivePoptileWidth-effectivePBETWEENWIDTH, getBounds().height - insets.top - insets.bottom );
+				if (effectivePoptileWidth>0){
+					poptile.setVisible(true);
+					leftPoptile = main.getWidth() + main.getX();
+					poptile.setBounds(main.getWidth() + main.getX()+effectivePBETWEENWIDTH, insets.top, effectivePoptileWidth, getBounds().height - insets.top - insets.bottom );
+					pBetweenPanel.setBounds(main.getWidth() + main.getX(), insets.top, effectivePBETWEENWIDTH, getBounds().height - insets.top - insets.bottom);
+					pBetweenPanel.setVisible(true);
+					poptile.doLayout();
+				}
+				else {
+					leftPoptile = -1;
+					poptile.setVisible(false);
+					poptile.setBounds(0,0,0,0);
+					pBetweenPanel.setVisible(false);
+					pBetweenPanel.setBounds(0,0,0,0);
+
+				}
+				rBetweenPanel.setBounds(effectiveResourcesWidth + insets.left- BETWEENWIDTH, insets.top, BETWEENWIDTH, getBounds().height - insets.top - insets.bottom);
+				rBetweenPanel.setVisible(true);
+				resources.doLayout();
+				main.doLayout();
+			}
+			if (resizeContainedWindows & windows != null){
+				for (int i = 0; i<windows.size(); i++){
+					MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+					try {
+						w.resetContentsSize();
+					}
+					catch (Throwable t){
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	boolean locationPreviouslySet = false;
+	boolean locationPreviouslySetScripting = false;
+	public void setWindowLocation(int x, int y, boolean overridePrevious, boolean scripting){
+		if (!overridePrevious && windows.size()>1 && ((!scripting && locationPreviouslySet)|| (scripting && locationPreviouslySetScripting)))
+			return;
+		if (scripting)
+			locationPreviouslySetScripting = true;
+		else
+			locationPreviouslySet = true;
+		savedX = x;
+		savedY = y;
+		setLocation(x, y);
+	}
+	public void paint(Graphics g){
+		if (checkInsets(true))
+			super.paint(g);
+	}
+	/*.................................................................................................................*/
+	boolean checkInsets(boolean resetSizesIfNeeded){
+		Insets insets = getInsets();
+		if (oldInsetTop!=insets.top || oldInsetBottom !=insets.bottom || oldInsetRight!= insets.right || oldInsetLeft != insets.left) {
+			//storeInsets(insets);
+			if (resetSizesIfNeeded)
+				resetSizes(true);
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void storeInsets(Insets insets){
+		oldInsetTop=insets.top;
+		oldInsetBottom=insets.bottom;
+		oldInsetRight= insets.right;
+		oldInsetLeft= insets.left; 
+	}
+	/*.................................................................................................................*/
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Requests close", null, commandName, "closeWindowRequested")) {
+			closeWindowRequested();
+		}
+		return null;
+	}
+
+
+	private boolean checkAndResetInsets(int width, int height){
+		Insets insets = getInsets();
+		if (oldInsetTop!=insets.top || oldInsetBottom !=insets.bottom || oldInsetRight!= insets.right || oldInsetLeft != insets.left) {
+			int totalNeededWidth = width+(insets.right-oldInsetRight)+(insets.left-oldInsetLeft);
+			int totalNeededHeight = height+(insets.top-oldInsetTop)+(insets.bottom-oldInsetBottom);
+			setSavedDimensions(totalNeededWidth, totalNeededHeight);
+			setSize(totalNeededWidth, totalNeededHeight);
+			storeInsets(insets);
+			saveFullDimensions();
+			resetSizes(true);
+			for (int i = 0; i<windows.size(); i++){
+				MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+				w.resetContentsSize();
+			}
+			return true;
+		}
+		storeInsets(insets);
+		return false;
+	}
+	/*.................................................................................................................*/
+	class MWCE extends ComponentAdapter{
+		MesquiteFrame f;
+		public MWCE (MesquiteFrame f){
+			super();
+			this.f = f;
+		}
+		public void componentResized(ComponentEvent e){
+			if (e==null || e.getComponent()!= f || (getOwnerModule()!=null && (getOwnerModule().isDoomed()))) // || disposing)))
+				return;
+
+			if (savedFullH== getBounds().height&& savedFullW == getBounds().width) {
+				checkAndResetInsets(savedFullW, savedFullH);
+			}
+			else if (doingShow || !isResizable()){
+				if (windows.size() >1 || frontMostInLocation(RESOURCES) != null)
+					setSize(savedW, savedHWithTabs);
+				else
+					setSize(savedW, savedHWithoutTabs);
+				resetSizes(true);
+			}
+			else {
+				resetSizes(true);
+			}
+
+		}
+		public void componentMoved(ComponentEvent e){
+			if (e==null || e.getComponent()!= f || (getOwnerModule()!=null && (getOwnerModule().isDoomed())))// || disposing)))
+				return;
+			//	if (doingShow)
+			//		setLocation(savedX,savedY);
+		}
+		public void componentShown(ComponentEvent e){
+			Insets insets = getInsets();
+			if (!checkAndResetInsets(savedFullW, savedFullH)) //if (!checkInsets(false))
+				//resetSizes(true);
+				//else
+			{
+				if (MesquiteTrunk.isMacOSXJaguar()) {
+					for (int i = 0; i<windows.size(); i++){
+						MesquiteWindow w = (MesquiteWindow)windows.elementAt(i);
+						w.repaintAll();
+					}
+				}
+			}
+			Toolkit.getDefaultToolkit().sync();
+			if (e.getComponent() instanceof Frame && !(e.getComponent() instanceof ProgressWindow))
+				ProgressWindow.allIndicatorsToFront();
+
+		}
+
+	}
+
+	public static MesquiteFrame activeWindow;
+	/*.................................................................................................................*/
+	class MWWE extends WindowAdapter{
+		MesquiteFrame f;
+		MesquiteCommand closeCommand;
+		public MWWE (MesquiteFrame f){
+			this.f = f;
+			closeCommand = new MesquiteCommand("closeWindowRequested", f);
+		}
+		public void windowClosing(WindowEvent e){
+
+			MesquiteModule.incrementMenuResetSuppression();
+			try {
+				if (MesquiteTrunk.isMacOS() && f!=activeWindow && activeWindow!=null) //workaround the Mac OS menu disappearance bug after closing a window
+					toFront();
+				closeCommand.doItMainThread(null, null, null);
+
+
+			}
+			catch (Exception ee){
+			}
+			MesquiteModule.decrementMenuResetSuppression();
+
+		}
+		public void windowActivated(WindowEvent e){
+			try {
+				if (f !=null) {
+					activeWindow = f;//for workaround the Mac OS menu disappearance bug after closing a window
+					if (f.ownerModule !=null && f.ownerModule.getProject() !=null && windows.indexOf(f.ownerModule.getProject().getCoordinatorModule().getModuleWindow())>=0){ //so that file save will remember foremost window
+						f.ownerModule.getProject().activeWindowOfProject = f.frontWindow;
+					}
+					/*	if (e.getComponent() instanceof Frame && !(e.getComponent() instanceof ProgressWindow))
+					ProgressWindow.allIndicatorsToFront();
+					 */
+				}
+			}
+			catch (Exception ex){
+			}
+
+		}
+	}
+}
+
+
+class FrameTabsPanel extends MousePanel {
+	MesquiteFrame frame;
+	int[] lefts, rights;
+	Font[] fonts = new Font[6];
+	int intertabSpace = 4;
+	int defaultBackEdge = 10;
+	public static int lowerBarHeight = 4;
+
+	static Image goaway, popOut, popIn, minimize, mediumize, show, goawayMouseOver;
+	static {
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goawayTransparent.gif");
+		goawayMouseOver = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "windowIcons" + MesquiteFile.fileSeparator + "goaway.gif");
+		minimize = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "minimizeTransparent.gif");
+		mediumize = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "mediumizeTransparent.gif");
+		popOut = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "decompactTransparent.gif");
+		popIn = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "compactTransparent.gif");
+		show = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "showTransparent.gif");
+	}
+	MesquitePopup popupForPopoutWindow=null;
+	MesquiteCommand popCommand, tileCommand, closeCommand;
+	public FrameTabsPanel(MesquiteFrame f){
+		this.frame = f;
+		//fonts[0] = new Font("SanSerif", Font.PLAIN, 13);
+		fonts[0] = new Font("SanSerif", Font.PLAIN, 11);
+		fonts[1] = new Font("SanSerif", Font.PLAIN, 11);
+		fonts[2] = new Font("SanSerif", Font.PLAIN, 10);
+		fonts[3] = new Font("SanSerif", Font.PLAIN, 9);
+		fonts[4] = new Font("SanSerif", Font.PLAIN, 8);
+		fonts[5] = new Font("SanSerif", Font.PLAIN, 7);
+		//	f.diagnose();
+		if (goaway == null){
+			goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goawayTransparent.gif");
+			goawayMouseOver = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "windowIcons" + MesquiteFile.fileSeparator + "goaway.gif");
+			minimize = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "minimizeTransparent.gif");
+			mediumize = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "mediumizeTransparent.gif");
+			popOut = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "decompactTransparent.gif");
+			popIn = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "compactTransparent.gif");
+			show = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "showTransparent.gif");
+		}
+		closeCommand = new MesquiteCommand("closeWindow", this);
+		popCommand = new MesquiteCommand("popOut", this);
+		tileCommand = new MesquiteCommand("tileOut", this);
+		setBackground(ColorTheme.getExtInterfaceBackground());
+
+	}
+	/*.................................................................................................................*/
+	int findTab(int x){
+		if (lefts == null || lefts.length == 0)
+			return MesquiteInteger.unassigned;
+		if (x < lefts[0])
+			return -1;
+		for (int i = 0; i<lefts.length; i++){
+			if (x > lefts[i] && x < rights[i])
+				return i;
+		}
+		for (int i = 0; i<lefts.length-1; i++){
+			if (x > rights[i] && x < lefts[i+1])
+				return -1;
+		}
+		return lefts.length;
+	}
+	int tabTouched = MesquiteInteger.unassigned;
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		tabTouched = findTab(x);
+		if (tabTouched>= 0 && MesquiteEvent.commandOrControlKeyDown(modifiers)){
+			redoPopoutWindowMenu(tabTouched);
+			popupForPopoutWindow.show(this, x,y);
+		}
+	}
+
+	static int goAwayTop = 6;
+	static int goAwayBottom = 18;
+
+	int getGoAwayControlTop(){
+		if (scaling < 1.0)
+			return 6;
+		return panelHeight-22;
+	}
+	int getGoAwayControlBottom(){
+		return getGoAwayControlTop()+12;
+	}
+	int getGoAwayControlLeft(){
+		return intertabSpace -1;
+	}
+	int getGoAwayControlRight(){
+		return getGoAwayControlLeft() + 12;
+	}
+	public void explainTab(int whichTab) {
+		frame.frontWindow.setExplanation(getTabTitle(whichTab));
+
+	}
+	private MesquiteWindow getWindow(int i){
+		try {
+			MesquiteWindow w = (MesquiteWindow)frame.windows.elementAt(i);
+			return w;
+		}
+		catch(Exception e){
+		}
+		catch(Error e){
+		}
+		return null;
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		try {
+			int i = findTab(x);
+			if (i == MesquiteInteger.unassigned)
+				return;
+			if (tabTouched>=10000 || tabTouched <0)
+				return;
+			if (i== tabTouched){  //down and up on same
+				if (frame.permitGoAway(i) && x> lefts[i] + getGoAwayControlLeft() && x<lefts[i] +getGoAwayControlRight() && y >= getGoAwayControlTop() && y<=getGoAwayControlBottom()){
+					if (frame.goAwayOrShow(i))  //showing goaway
+						frame.windowGoAway(i);
+					else
+						;
+				}
+				//				else if (frame.showMinimizeMaximize(i) && x> rights[i] - 20 && y >4 && y<20){
+				else if (frame.showMinimizeMaximize(i) && x< lefts[i] + 20 && y >12 && y<28){
+					frame.toggleMinimize(i);
+				}
+				else {
+					MesquiteWindow w = getWindow(tabTouched);
+					if (isProjectWindow(w))
+						return;
+					frame.showPage(i);
+				}
+			}
+			else if (tabTouched != MesquiteInteger.unassigned){
+				if (tabTouched<0 || tabTouched>= frame.windows.size())
+					return;
+				MesquiteWindow w = getWindow(tabTouched);
+				if (w == null)
+					return;
+				if (w.isPoppedOut())
+					return;
+				if (MesquiteWindow.checkDoomed(w)){
+					MesquiteWindow.uncheckDoomed(w);
+					return;
+				}
+
+				if (i>=10000)
+					i = i - 10000;
+				if (i<tabTouched && tabTouched > 1){  //can't be first window other than project panel
+					if (i<=0)
+						i = 1;
+					if (frame.windows.indexOf(w) != i){
+						frame.windows.removeElement(w);
+						if (i >= frame.windows.size())
+							frame.windows.addElement(w);
+						else
+							frame.windows.insertElementAt(w, i);
+					}
+					frame.showPage(w);
+					repaint();
+
+				}
+				else if (i> tabTouched && tabTouched >0 && tabTouched < lefts.length-1){
+					if (frame.windows.indexOf(w) != i){
+						frame.windows.removeElement(w);
+						if (i >= frame.windows.size())
+							frame.windows.addElement(w);
+						else
+							frame.windows.insertElementAt(w, i);
+					}
+					frame.showPage(w);
+					repaint();
+				}
+			}
+		}
+		catch (Exception e){
+		}
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	int lastTabOver = -1;
+	int tabOver = -1;
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (frame==null || frame.windows==null){
+			return;
+		}
+		tabOver = findTab(x);
+		if (tabOver != lastTabOver && tabOver > 0 && (lefts==null || tabOver<lefts.length) ){
+			Graphics g = getGraphics();
+			if (g != null){
+				MesquiteWindow w = getWindow(tabOver);
+				if (w == null)
+					return;
+				drawAndFillTab (g, w,  lefts[tabOver],  rights[tabOver],  tabOver, scaling);
+			}
+			explainTab(tabOver);
+		}
+		if (tabOver != lastTabOver && lastTabOver>=0 && (lefts==null || lastTabOver<lefts.length)  && lastTabOver < frame.windows.size()){
+			Graphics g = getGraphics();
+			if (g != null){
+				MesquiteWindow w = getWindow(lastTabOver);
+				if (w == null)
+					return;
+				drawAndFillTab (g, w,  lefts[lastTabOver],  rights[lastTabOver],  lastTabOver, scaling);
+			}
+		}
+		lastTabOver = tabOver;
+	}
+	long entryTime = -1;
+
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (frame==null || frame.windows==null){
+			return;
+		}
+		tabOver = findTab(x);
+		if (entryTime<0)
+			entryTime = System.currentTimeMillis();
+		if (tabOver != lastTabOver && tabOver > 0 && (lefts==null || tabOver<lefts.length) ){
+			Graphics g = getGraphics();
+			if (g != null){
+				MesquiteWindow w = getWindow(tabOver);
+				if (w == null)
+					return;
+				drawAndFillTab (g, w,  lefts[tabOver],  rights[tabOver],  tabOver, scaling);
+				entryTime=-1;
+			}
+		}
+		if (tabOver != lastTabOver && lastTabOver>=0 && (lefts==null || lastTabOver<lefts.length)  && lastTabOver < frame.windows.size()){
+			Graphics g = getGraphics();
+			if (g != null){
+				MesquiteWindow w = getWindow(lastTabOver);
+				if (w == null)
+					return;
+				drawAndFillTab (g, w,  lefts[lastTabOver],  rights[lastTabOver],  lastTabOver, scaling);
+			}
+		}
+		explainTab(tabOver);
+		lastTabOver = tabOver;
+	}
+
+
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		tabOver  = -1;
+		if (frame==null || frame.windows==null){
+			return;
+		}
+		entryTime=-1;
+		if (lastTabOver>=0 && (lefts==null || lastTabOver<lefts.length) && (lastTabOver < frame.windows.size())){
+			Graphics g = getGraphics();
+			if (g != null){
+				MesquiteWindow w = getWindow(lastTabOver);
+				if (w == null)
+					return;
+				drawAndFillTab (g, w,  lefts[lastTabOver],  rights[lastTabOver],  lastTabOver, scaling);
+			}
+			lastTabOver = -1;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Pops out the window", null, commandName, "popOut")) {
+			int i = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(i)){
+				MesquiteWindow w = getWindow(i);
+				if (w != null)
+					w.setPopAsTile(false);
+				frame.popOut(i, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Tiles out the window", null, commandName, "tileOut")) {
+			int i = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(i)){
+				MesquiteWindow w = getWindow(i);
+				if (w != null)
+					w.setPopAsTile(true);
+				frame.popOut(i, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes window", null, commandName, "closeWindow")) {
+			int i = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(i)){
+				MesquiteWindow w = getWindow(i);
+				if (w != null){
+					if (frame.goAwayOrShow(i))  //showing goaway
+						frame.windowGoAway(i);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	void redoPopoutWindowMenu(int i) {
+		if (popupForPopoutWindow==null)
+			popupForPopoutWindow = new MesquitePopup(this);
+		popupForPopoutWindow.removeAll();
+		closeCommand.setDefaultArguments(Integer.toString(i));
+		popCommand.setDefaultArguments(Integer.toString(i));
+		tileCommand.setDefaultArguments(Integer.toString(i));
+		if (i < frame.windows.size()){
+			MesquiteWindow w = (MesquiteWindow)frame.windows.elementAt(i);
+			MesquiteMenuItem mtitle = new MesquiteMenuItem(w.getTitle(), null, null);
+
+			popupForPopoutWindow.add(mtitle);
+		}
+		MesquiteMenuItem mItemClose = new MesquiteMenuItem("Close Window", null, closeCommand);
+		MesquiteMenuItem mItem = new MesquiteMenuItem("Pop Out as Separate Window", null, popCommand);
+		MesquiteMenuItem mItem2 = new MesquiteMenuItem("Put in Separate Tile", null, tileCommand);
+		popupForPopoutWindow.add(mItemClose);
+		popupForPopoutWindow.add(mItem);
+		popupForPopoutWindow.add(mItem2);
+		add(popupForPopoutWindow);
+	}
+	int getFrontness(MesquiteWindow w){
+		boolean popped = w.getTileLocation() == MesquiteFrame.POPTILE;
+		boolean isFrontOfType = !frame.resourcesFullWindow && ((popped && (frame.frontMostInLocation(MesquiteFrame.POPTILE)==w)) || (!popped && (frame.frontMostInLocation(MesquiteFrame.MAIN)==w)));
+		isFrontOfType = isFrontOfType || (frame.resourcesFullWindow && w.getTileLocation() == MesquiteFrame.RESOURCES);
+		int frontness = 0;
+		if (isFrontOfType){
+			if (frame.frontWindow == w)
+				frontness = 2;
+			else
+				frontness = 1;
+		}
+		return frontness;
+	}
+	static final int tabBottomLineHeight = 4;
+	void drawAndFillTab (Graphics g, MesquiteWindow w, int tabLeft, int tabRight, int whichTab, double scaling){
+		int frontness = getFrontness(w);
+
+		g.setFont(fonts[fontChosen]);
+		Shape oldClip = g.getClip();
+		if (w == frame.projectWindow)
+			g.setClip(tabLeft-1, 0, tabRight -tabLeft+4, panelHeight-tabBottomLineHeight-1);
+		else g.setClip(tabLeft-1, 0, tabRight -tabLeft+4, panelHeight);
+		String title = w.getTitle();
+		if (w == frame.projectWindow && projectPanelWidth <=0)
+			title = "Project";
+		Image icon = w.getIcon();
+		int iconWidth = 0;
+		if (icon != null || w == frame.projectWindow)
+			iconWidth = 20;
+
+
+
+
+		drawTab(g, whichTab, w, frontness, tabLeft, tabRight, panelHeight, projectPanelWidth, w == frame.projectWindow, w instanceof SystemWindow);
+		if (w == frame.projectWindow)
+			g.setClip(tabLeft-1, 0, tabRight -tabLeft+1, panelHeight-tabBottomLineHeight-1);
+		else
+			g.setClip(tabLeft-1, 0, tabRight -tabLeft+1, panelHeight-tabBottomLineHeight);
+		if (frontness == 2) 
+			g.setColor(ColorTheme.getExtInterfaceTextContrast(w instanceof SystemWindow)); //Color.black);
+		else if (frontness == 1) 
+			g.setColor(ColorTheme.getExtInterfaceTextMuted(w instanceof SystemWindow)); //Color.black);
+		else 
+			g.setColor(ColorTheme.getExtInterfaceTextMuted(w instanceof SystemWindow)); //Color.black);
+		if (scaling < 1.0){
+			int wish = StringUtil.getStringDrawLength(g, title);
+			int offer = (int)(scaling * wish);
+			StringInABox box = new StringInABox(title, g.getFont(), offer);
+			box.drawTight(g, tabLeft + intertabSpace + iconWidth, 1);
+			if (tabOver == whichTab && frame.permitGoAway(whichTab)){
+				if (frontness>0){ // a tab for a selected window
+					if (frontness>1)   //the selected window on the selected tile (i.e. the one owning the menu bar)
+						g.setColor(ColorTheme.getExtInterfaceElementContrast(w instanceof SystemWindow)); 
+					else //a selected window, but in the unselected tile (i.e. the other tile not owning the menu bar)
+						g.setColor(ColorTheme.getExtInterfaceElementContrast2(w instanceof SystemWindow));
+				}
+				else  //a tab for a window hidden in the background
+					g.setColor(ColorTheme.getExtInterfaceElement(w instanceof SystemWindow));
+				g.fillRect(tabLeft  +getGoAwayControlLeft(), getGoAwayControlTop(), 16, 12);
+				g.drawImage(goawayMouseOver, tabLeft +getGoAwayControlLeft(), getGoAwayControlTop(), this);
+			}
+			else if (icon != null)
+				g.drawImage(icon, tabLeft + intertabSpace, 6, this);
+
+		}
+		else {
+			g.drawString(title, tabLeft + intertabSpace + iconWidth, panelHeight -12);
+			if (tabOver == whichTab && frame.permitGoAway(whichTab)){
+				if (frontness>0){ // a tab for a selected window
+					if (frontness>1)   //the selected window on the selected tile (i.e. the one owning the menu bar)
+						g.setColor(ColorTheme.getExtInterfaceElementContrast(w instanceof SystemWindow)); 
+					else //a selected window, but in the unselected tile (i.e. the other tile not owning the menu bar)
+						g.setColor(ColorTheme.getExtInterfaceElementContrast2(w instanceof SystemWindow));
+				}
+				else  //a tab for a window hidden in the background
+					g.setColor(ColorTheme.getExtInterfaceElement(w instanceof SystemWindow));
+				g.fillRect(tabLeft  +getGoAwayControlLeft(), getGoAwayControlTop(), 16, 12);
+				g.drawImage(goawayMouseOver, tabLeft +getGoAwayControlLeft(), getGoAwayControlTop(), this);
+			}
+			else if (icon != null)
+				g.drawImage(icon, tabLeft + intertabSpace, panelHeight -22, this);
+		}
+		if (w == frame.projectWindow){
+			if (minimize != null && !w.isMinimized())
+				g.drawImage(minimize, tabLeft+intertabSpace, 12, this); //tabRight-17
+			else if (mediumize != null && w.isMinimized())
+				g.drawImage(mediumize, tabLeft+intertabSpace, 12, this);//tabRight-17
+		}
+		g.setClip(oldClip );
+	}
+
+	/*.................................................................................................................*/
+
+	private boolean isProjectWindow(MesquiteWindow w) {
+		return w==frame.projectWindow;
+	}
+
+	int paintCount =0;
+	int panelWidth;
+	int panelHeight;
+	int projectPanelWidth;
+	double scaling = 1.0;
+	int fontChosen = 0;
+
+	/*.................................................................................................................*/
+	public String getTabTitle(int i) {
+		if (i<0 || i>=frame.windows.size())
+			return "";
+		MesquiteWindow w = (MesquiteWindow)frame.windows.elementAt(i);
+		String s = w.getTitle();
+		if (w == frame.projectWindow && projectPanelWidth<=0)
+			s = "Project";
+		return s;
+	}
+
+	/*.................................................................................................................*/
+	public void paint(Graphics g){
+
+		//frame.ontabDark = new Color(160, 82, 45);
+		if (!(g instanceof Graphics2D))
+			return;
+		paintCount++;
+		Graphics2D g2 = (Graphics2D)g;
+
+		if (!frame.checkInsets(true)){
+			repaint();
+			return;
+		}
+		projectPanelWidth = 0;
+		if (frame.projectWindow != null)
+			projectPanelWidth = frame.projectWindow.getBounds().width;
+		if (InterfaceManager.isEditingMode()){
+			Color co = g2.getColor();
+			g2.setColor(Color.cyan);
+			g2.fillRect(0, 0, getWidth(), getHeight());
+			g2.setColor(co);
+		}
+		panelWidth = getBounds().width;
+		panelHeight = getBounds().height;
+		Vector frameWindows = (Vector)frame.windows.clone();
+
+		g2.setColor(ColorTheme.getContentFrame());
+		//	BasicStroke stroke = new BasicStroke(4);
+		g2.drawLine(projectPanelWidth+MesquiteFrame.cornerBuffer, panelHeight-1, panelWidth, panelHeight-1);
+		g2.fillRect(projectPanelWidth+MesquiteFrame.cornerBuffer, panelHeight-4, panelWidth-4, 4);
+
+
+		//g.fillRect(projectPanelWidth, height-4, width, 4);
+		//g.setColor(Color.red);
+		//	g.fillRect(projectPanelWidth-3, panelHeight-3, panelWidth, 3);
+		//g.setColor(Color.green);
+		//g.fillRect(projectPanelWidth-2, panelHeight-2, panelWidth, 2);
+		//	g.setColor(ColorDistribution.veryDarkMesquiteBrown);
+
+		int numWindows = frameWindows.size();
+		int numTabs = numWindows;
+		if (numTabs<2 && frame.frontMostInLocation(MesquiteFrame.RESOURCES) == null) //if has resources window, then show tabs
+			return;
+		if (lefts == null || lefts.length != numTabs){
+			lefts = new int[numTabs];
+			rights = new int[numTabs];
+		}
+		String totalString = "";
+		int iconNumber = 0;
+		String[] titles = new String[numWindows];
+		for (int i = 0; i<numWindows; i++){
+			MesquiteWindow w = (MesquiteWindow)frame.windows.elementAt(i);
+			String s = w.getTitle();
+			if (w == frame.projectWindow && projectPanelWidth<=0)
+				s = "Project";
+			titles[i] = s;
+			if (s != null)
+				totalString += s;
+			if (w.getIcon() !=null)
+				iconNumber ++;
+		}
+		int iconsWidth = iconNumber * 20;
+
+		int edges = (intertabSpace + defaultBackEdge) * numTabs; //NOTE: this is not calculated quite properly, causing David's compaction when many windows
+		if (frame.frontMostInLocation(MesquiteFrame.POPTILE)!=null)
+			edges += 30;
+		//~~~~~~Setting up sizing/scaling~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		fontChosen = 0;
+		scaling = 1.0;
+		boolean ready = false;
+		int narrowest = 5000;
+		int widest = 0;
+		int numLoops = 0;
+
+		while (!ready && numLoops<100){  //checking scaling/sizing
+			numLoops++;
+			fontChosen = 0;
+			g2.setFont(fonts[0]);
+
+			int needed = 0;
+			while ((needed = StringUtil.getStringDrawLength(g2, totalString) + iconsWidth +edges) > panelWidth && fontChosen<4){  //was i<fonts.length-1
+				fontChosen++;
+				g2.setFont(fonts[fontChosen]);
+			}
+			needed = StringUtil.getStringDrawLength(g2, totalString) + iconsWidth +edges;
+			scaling = 1.0;
+			if (needed> panelWidth-edges){
+				scaling = (panelWidth-edges-projectPanelWidth-MesquiteFrame.cornerBuffer)*1.0/(StringUtil.getStringDrawLength(g2, totalString) + iconsWidth);
+			}
+
+			//trial run the tab widths
+			narrowest = 500000;
+			widest = 0;
+			int totalWidth = 0;
+			//			int leftMargin = 0;
+			//			int rightMargin = panelWidth - defaultBackEdge;
+			//	int i = 0;
+			for (int i = 0; i<numWindows; i++){
+				MesquiteWindow w = (MesquiteWindow)frameWindows.elementAt(i);
+				if (!isProjectWindow(w) && w.isVisible()) {   // not the project window
+					/*				int backSpace;
+				if (w == frame.projectWindow){
+					backSpace = defaultBackEdge + 20;
+				}
+				else {
+					backSpace = defaultBackEdge;
+				}
+					 */
+					boolean popped = w.getTileLocation() == MesquiteFrame.POPTILE;
+					Image icon = w.getIcon();
+					int iconWidth = 0;
+					if (icon != null)
+						iconWidth = 20;
+					/*				if (!popped)
+					leftMargin += intertabSpace;
+				else 
+					rightMargin -= intertabSpace;
+					 */
+					String title=null;
+					if (i>=0 && i<titles.length)
+						title = titles[i];
+					int sw = 0;
+					if (StringUtil.notEmpty(title)) {
+						sw = StringUtil.getStringDrawLength(g2, title);
+						int offer = sw + iconWidth;
+						if (scaling < 1.0)
+							offer = (int)(scaling * offer);
+						/*					if (!popped)
+						leftMargin += offer;
+					else
+						rightMargin -= offer;		
+						 */
+						totalWidth += offer;
+						if (offer + iconWidth > widest)
+							widest = offer + iconWidth;
+						else if (offer + iconWidth < narrowest){
+							narrowest = offer + iconWidth;
+						}
+					} else {
+					}
+
+				}
+			}		
+
+
+
+			//if some tabs are very narrow AND there is a big variance in tab size, then delete characters from long tabs and try again 			
+			if (1.0*widest/narrowest > 2.0 && narrowest < 30 && widest>30 && totalWidth + 100 > panelWidth){
+				//Delete last character of longest string & recalculate totalString
+				int max = 0;
+				int whichMax = -1;
+				for (int k = 0; k<titles.length; k++){
+					int thisL = StringUtil.getStringDrawLength(g2, titles[k]);
+					if (thisL>max){
+						whichMax = k;
+						max = thisL;
+					}
+				}
+				if (whichMax>=0 && whichMax<titles.length)
+					titles[whichMax] = titles[whichMax].substring(0, titles[whichMax].length()-1);
+				totalString = "";
+				for (int k = 0; k<titles.length; k++){
+					totalString += titles[k];
+				}
+			}
+			else 
+				ready = true;
+		}
+		if (fontChosen >3 && narrowest > 20){
+			fontChosen = 3;
+			g2.setFont(fonts[fontChosen]);
+			int needed = StringUtil.getStringDrawLength(g2, totalString) + iconsWidth +edges;
+			scaling = 1.0;
+			if (needed> panelWidth-edges-projectPanelWidth-MesquiteFrame.cornerBuffer){  // remove "projectPanelWidth" here and in next line if other tabs can go over project panel
+				scaling = (panelWidth-edges-projectPanelWidth-MesquiteFrame.cornerBuffer)*1.0/(StringUtil.getStringDrawLength(g2, totalString) + iconsWidth);
+			}
+		}
+		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		int leftMargin = 0;  //this is the current left margin, moving rightward as left-side tabs are added
+		int rightMargin = panelWidth - intertabSpace;//this is the current right margin, moving leftward as right-side tabs are added
+
+		//~~~~~~~~~~~~~~~Drawing tab by tab ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		for (int i = 0; i<numWindows; i++){
+			int backSpace;
+			MesquiteWindow w = (MesquiteWindow)frameWindows.elementAt(i);
+			if (isProjectWindow(w)){ //project window has minimize button
+				backSpace = defaultBackEdge + 20;
+			}
+			else {
+				backSpace = defaultBackEdge;
+			}
+			int tabLeft, tabRight;     //these are the left and right edges of the current tab
+
+			boolean popped = w.getTileLocation() == MesquiteFrame.POPTILE;
+			Image icon = w.getIcon();
+			int iconWidth = 0;
+			if (icon != null)
+				iconWidth = 20;
+			if (!popped){
+				leftMargin += intertabSpace;
+				tabLeft = leftMargin;
+				tabRight = leftMargin + backSpace-2;
+			}
+			else {
+				rightMargin -= intertabSpace;
+				tabRight = rightMargin -2;
+				tabLeft = rightMargin - intertabSpace;
+			}
+
+			String title = null;
+			if (i>=0 && i<titles.length)
+				title = titles[i];
+			if (title != null){
+				if (isProjectWindow(w)){
+					tabLeft = 0;
+					tabRight = projectPanelWidth+MesquiteFrame.cornerBuffer;
+					if (projectPanelWidth <0){
+						title = "Project";
+						titles[i] = title;
+						tabRight = 64; //StringUtil.getStringDrawLength(g2, title) + iconWidth + intertabSpace;
+					}
+					leftMargin = tabRight;
+				} 
+				else if (scaling < 1.0){
+					int wish = StringUtil.getStringDrawLength(g2, title) + iconWidth;
+					int offer = (int)(scaling * wish);
+					if (!popped){
+						tabRight = leftMargin + offer + backSpace-2;
+						leftMargin = tabRight;
+					}
+					else {
+						tabLeft = rightMargin - offer - intertabSpace - backSpace +2;
+						rightMargin = tabLeft;
+					}					
+				}
+				else {
+					int offer = StringUtil.getStringDrawLength(g2, title) + iconWidth;
+					if (!popped) {
+						tabRight = leftMargin + offer + backSpace-2;
+						leftMargin = tabRight;
+					}
+					else {
+						tabLeft = rightMargin - offer - intertabSpace - backSpace +2;
+						rightMargin = tabLeft;
+					}
+				}
+				drawAndFillTab (g2, w,  tabLeft, tabRight,  i, scaling);
+
+			}
+			else 
+				MesquiteMessage.println("window without title " + w.getClass());
+
+			/*if (w == frame.projectWindow){
+				if (minimize != null && !w.isMinimized())
+					g2.drawImage(minimize, tabRight-17, 4, this);
+				else if (mediumize != null && w.isMinimized())
+					g2.drawImage(mediumize, tabRight-17, 4, this);
+			}*/
+
+
+
+			g2.setColor(ColorTheme.getExtInterfaceEdgeContrast(w instanceof SystemWindow)); //Color.black);
+			try{
+				lefts[i] = tabLeft;
+				rights[i] = tabRight;
+			}
+			catch (ArrayIndexOutOfBoundsException e){
+				repaint();
+			}
+		}
+
+
+		// this little section draws the rounded corner on the upper (and outer) left side of the main part of the window
+		g2.setColor(ColorTheme.getContentFrame());
+		Stroke st = g2.getStroke();
+		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+		MesquitePath2DFloat path = new MesquitePath2DFloat();
+		if (path.OK()) {
+			int adjust = 0;
+			int pathLeft = projectPanelWidth;
+			int pathRight = pathLeft+12;  //+14
+			int pathTop = getBounds().height-FrameTabsPanel.lowerBarHeight-1;
+			if (projectPanelWidth <=0)  //project panel closed, so lower the curve a bit to make it not leave negative corner
+				pathTop +=1;
+			int pathBottom = pathTop+MesquiteFrame.cornerBuffer+8;  //+10
+			path.moveTo(adjust+pathRight, adjust+pathTop);
+			path.lineTo(adjust+pathRight, adjust+pathBottom);
+			path.lineTo(adjust+pathLeft,adjust+pathBottom);
+			path.curveTo(adjust+pathLeft, adjust+pathTop+(pathBottom-pathTop)/3, adjust+pathLeft+(pathRight-pathLeft)/3, adjust+pathTop, adjust+pathRight, adjust+pathTop);
+			path.closePath();
+			path.fill(g2);
+
+		}
+		else {
+			int pathLeft = projectPanelWidth;
+			int pathRight = projectPanelWidth+4;  //+14
+			int pathTop = panelHeight;
+			g2.fillRect(pathLeft+4, pathTop-4, pathRight-pathLeft, 4);
+			g2.fillRect(pathLeft+3, pathTop-3, pathRight-pathLeft, 3);
+			g2.fillRect(pathLeft+2, pathTop-2, pathRight-pathLeft, 2);
+			g2.fillRect(pathLeft+1, pathTop-1, pathRight-pathLeft, 1);
+			g2.drawLine(pathLeft+3, pathTop-1, pathRight, pathTop-1);
+		}
+
+		g2.setStroke(st);
+
+	}
+	/*.................................................................................................................*/
+
+	void drawTab(Graphics g, int whichTab, MesquiteWindow w, int frontness, int tabLeft, int tabRight, int height, int projectPanelWidth, boolean isProjectTab, boolean isMesquiteWindow){
+		// to figure out whether strong lower edge of tab is needed, find out left edge of poptile, if showing
+		boolean forceThickLine = false;
+		if (frame.leftPoptile>0){
+			boolean popped = w.getTileLocation() == MesquiteFrame.POPTILE;
+			if (popped && tabRight<frame.leftPoptile)
+				forceThickLine = true;
+			else if (!popped && !isMesquiteWindow && !isProjectTab && tabLeft>frame.leftPoptile)
+				forceThickLine = true;
+		}
+		int roundness = 10;  
+		int top = 4;  
+		if (!(g instanceof Graphics2D))
+			return;
+		Graphics2D g2 = (Graphics2D)g;
+		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+		if (frontness>0){ // a tab for a selected window
+			if (frontness>1){   //the selected window on the selected tile (i.e. the one owning the menu bar)
+
+				g2.setColor(ColorTheme.getExtInterfaceElementContrast(isMesquiteWindow)); 
+				g2.fillRoundRect(tabLeft, top, tabRight - tabLeft - 2, height+60, roundness, roundness);  //background of tab
+				g2.setColor(ColorTheme.getExtInterfaceEdgeContrast(isMesquiteWindow));
+				g2.drawRoundRect(tabLeft, top, tabRight - tabLeft - 2, height+60, roundness, roundness);  //highlight edge of tab
+				g2.setColor(Color.black);  //black
+				g2.drawRoundRect(tabLeft-1, top-1, tabRight - tabLeft, height+62, roundness+1, roundness+1); //primary edge of tab
+				if (forceThickLine){
+					g2.setColor(ColorTheme.getContentFrame());
+					g2.fillRect(tabLeft-1, height-4, tabRight-tabLeft+1, 4);
+					g2.drawLine(tabLeft-1, height-1, tabRight, height-1);
+				}
+				else if (!isMesquiteWindow){
+					g2.setColor(Color.lightGray);
+					g2.drawLine(tabLeft-1, top+height-5, tabRight, top+height-5);  //line under the tab
+				}
+			}
+			else { //a selected window, but in the unselected tile (i.e. the other tile not owning the menu bar)
+				g2.setColor(ColorTheme.getExtInterfaceElementContrast2(isMesquiteWindow));
+				g2.fillRoundRect(tabLeft, top, tabRight - tabLeft - 2, height+60, roundness, roundness); //background of tab
+
+				//g.setColor(ColorTheme.getExtInterfaceEdgeContrast());
+				//	g.drawRoundRect(tabLeft, top, tabRight - tabLeft - 2, height+60, roundness, roundness);
+				g2.setColor(Color.darkGray);
+				g2.drawRoundRect(tabLeft-1, top-1, tabRight - tabLeft, height+62, roundness+1, roundness+1);  //primary edge of tab
+
+				if (forceThickLine){
+					g2.setColor(ColorTheme.getContentFrame());
+					g2.fillRect(tabLeft-1, height-4, tabRight-tabLeft+1, 4);
+					g2.drawLine(tabLeft-1, height-1, tabRight, height-1);
+				}
+				else {
+					g2.setColor(Color.lightGray);
+					g2.drawLine(tabLeft-1, top+height-5, tabRight, top+height-5);//line under the tab
+				}
+			}
+		}
+		else { //a tab for a window hidden in the background
+			g2.setColor(ColorTheme.getExtInterfaceElement(isMesquiteWindow));
+			g2.fillRoundRect(tabLeft, top, tabRight - tabLeft - 2, height+60, roundness, roundness);
+			if (!isProjectTab){
+				g2.setColor(ColorTheme.getExtInterfaceEdgeMuted(isMesquiteWindow));
+				g2.drawRoundRect(tabLeft-1, top-1, tabRight - tabLeft, height+62, roundness+1, roundness+1);
+			}
+			//now about to draw the lines/border beneath the tab
+
+
+			if (tabLeft> projectPanelWidth+MesquiteFrame.cornerBuffer ){ //entirely over main windows
+				g2.setColor(ColorTheme.getContentFrame());
+				//g2.setColor(Color.red);
+				g2.fillRect(tabLeft-1, height-4, tabRight-tabLeft+1, 4);
+				g2.drawLine(tabLeft-1, height-1, tabRight, height-1);
+			}
+			else { //extending over project panel, but not project tab
+				g2.setColor(getBackground());
+				g2.fillRect(tabLeft-1, height-4, tabRight-tabLeft+1, tabBottomLineHeight);
+				g2.setColor(ColorTheme.getContentFrame());
+				if (!isProjectTab) {
+					if (whichTab==1) {
+
+						//g2.fillRect(tabLeft-4, height-tabBottomLineHeight, 5, tabBottomLineHeight);
+						MesquitePath2DFloat path = new MesquitePath2DFloat();
+						if (path.OK()) {
+							int rightPath = 7;
+							int topPath = 6;
+							g2.fillRect(tabLeft+rightPath-1, height-tabBottomLineHeight, projectPanelWidth+MesquiteFrame.cornerBuffer-tabLeft+4, tabBottomLineHeight);
+							path.moveTo(tabLeft-1, height-topPath);
+							path.lineTo(tabLeft, height-topPath);
+							path.curveTo(tabLeft+2, height-4,tabLeft+4, height-4, tabLeft+rightPath, height-tabBottomLineHeight);
+							path.lineTo(tabLeft+rightPath, height);
+							path.curveTo(tabLeft-1, height-2,tabLeft+2, height-4, tabLeft-1, height-topPath);
+							path.closePath();
+							path.fill(g2);
+						}
+						else {
+							g2.fillRect(tabLeft+1, height-tabBottomLineHeight, projectPanelWidth+MesquiteFrame.cornerBuffer-tabLeft-1+5, tabBottomLineHeight);
+							g2.fillRect(tabLeft, height-5, 3, 3);
+							g2.fillRect(tabLeft, height-7, 1, 4);
+						}
+
+					} else {
+						g2.fillRect(tabLeft-4, height-tabBottomLineHeight, projectPanelWidth+MesquiteFrame.cornerBuffer-tabLeft+4, tabBottomLineHeight);
+					}
+
+				}
+				if (tabRight> projectPanelWidth){
+					MesquitePath2DFloat path = new MesquitePath2DFloat();
+					if (path.OK()) {
+						int adjust = 0;
+						int pathLeft = 0;
+						int pathRight = 0+4;  //+14
+						int pathTop = height;
+						int pathBottom = height+4;  //+10
+						path.moveTo(adjust+pathRight, adjust+pathTop);
+						path.lineTo(adjust+pathLeft, adjust+pathTop);
+						path.lineTo(adjust+pathLeft,adjust+pathBottom);
+						path.curveTo(adjust+pathLeft, adjust+pathTop+(pathBottom-pathTop)/3, adjust+pathLeft+(pathRight-pathLeft)/3, adjust+pathTop, adjust+pathRight, adjust+pathTop);
+						path.closePath();
+						path.fill(g2);
+					}
+					else {
+						g2.fillRect(projectPanelWidth+4, height-4, tabRight-projectPanelWidth, 4);
+						g2.fillRect(projectPanelWidth+3, height-3, tabRight-projectPanelWidth, 3);
+						g2.fillRect(projectPanelWidth+2, height-2, tabRight-projectPanelWidth, 2);
+						g2.fillRect(projectPanelWidth+1, height-1, tabRight-projectPanelWidth, 1);
+						g2.drawLine(projectPanelWidth+3, height-1, tabRight, height-1);
+					}
+
+				}
+
+			}
+
+
+		}
+
+	}
+	/*.................................................................................................................*/
+
+}
+class BetweenPanel extends MousePanel{
+	MesquiteFrame f;
+
+	public BetweenPanel(MesquiteFrame f){ 
+		super();
+		setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
+		this.f=f;
+		//setBackground(ColorDistribution.darkMesquiteBrown);
+		//setBackground(Color.yellow);
+		//setBackground(Color.darkGray);
+	}
+	int touchX = -1;
+	public void paint (Graphics g) {
+		if (!(g instanceof Graphics2D))
+			return;
+		Graphics2D g2 = (Graphics2D)g;
+		g2.setColor(ColorTheme.getContentFrame());
+		g2.fillRect(0,MesquiteFrame.cornerBuffer-1,getBounds().width, getBounds().height);
+		Stroke st = g2.getStroke();
+		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+		MesquitePath2DFloat path = new MesquitePath2DFloat();
+		if (path.OK()) {
+			g2.setColor(ColorTheme.getContentFrame());
+			int adjust = 0;
+			int pathLeft = 0;
+			int pathRight = 12;  //+14
+			int pathTop = 0-FrameTabsPanel.lowerBarHeight;
+			int pathBottom = 8;  //+10
+			path.moveTo(adjust+pathRight, adjust+pathTop);
+			path.lineTo(adjust+pathRight, adjust+pathBottom);
+			path.lineTo(adjust+pathLeft,adjust+pathBottom);
+			path.curveTo(adjust+pathLeft, adjust+pathTop+(pathBottom-pathTop)/3, adjust+pathLeft+(pathRight-pathLeft)/3, adjust+pathTop, adjust+pathRight, adjust+pathTop);
+			path.closePath();
+			path.fill(g2);
+		}
+		else {
+			g2.setColor(ColorTheme.getContentFrame());
+			int pathLeft = 0;
+			int pathRight = 12;  //+14
+			int pathTop = 0;
+			int pathBottom = 8;  //+10
+			g2.fillRect(pathLeft+4, pathTop-4, pathRight-pathLeft, 4);
+			g2.fillRect(pathLeft+3, pathTop-3, pathRight-pathLeft, 3);
+			g2.fillRect(pathLeft+2, pathTop-2, pathRight-pathLeft, 2);
+			g2.fillRect(pathLeft+1, pathTop-1, pathRight-pathLeft, 1);
+			g2.drawLine(pathLeft+3, pathTop-1, pathRight, pathTop-1);
+		}
+
+		g2.setStroke(st);
+
+
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		touchX= x;
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (touchX>=0){
+			f.incrementPanelWidth(this, x-touchX);
+		}
+		touchX = -1;
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteHTMLWindow.java b/Source/mesquite/lib/MesquiteHTMLWindow.java
new file mode 100644
index 0000000..09567c5
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteHTMLWindow.java
@@ -0,0 +1,233 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.html.*;
+import java.util.*;
+/* ======================================================================== */
+/** A window that displays text.  Yet to do: make it editable or not, have getText, etc.. */
+public class MesquiteHTMLWindow extends MesquiteWindow implements HyperlinkListener {
+	JEditorPane tA;
+	String assignedTitle;
+	MesquiteCommand linkTouchedCommand;
+	Vector pastTexts = new Vector();
+	MHTMLControl controls;
+	JScrollPane scrollPane;
+	MesquiteWindow dataWindow;
+	boolean showBack = true;
+	int controlHeight = 0;
+	boolean backEnabled = true;
+	public MesquiteHTMLWindow(MesquiteModule module, MesquiteCommand linkTouchedCommand, String assignedTitle, boolean showInfoBar) {
+		this(module, linkTouchedCommand, assignedTitle, true, showInfoBar);
+	}
+	public MesquiteHTMLWindow(MesquiteModule module, MesquiteCommand linkTouchedCommand, String assignedTitle, boolean showPanel, boolean showInfoBar) {
+		super(module, showInfoBar);// ���
+		this.assignedTitle = assignedTitle;
+		setTitle(assignedTitle);
+		//setBackground(Color.white);
+		//setWindowSize(600, 400);
+		this.linkTouchedCommand = linkTouchedCommand;
+		tA= new MesqJEditorPane("text/html","<html></html>");
+		tA.setEditable(false);
+		tA.setBackground(Color.white);
+		tA.setForeground(Color.black);
+		tA.setVisible(true);
+		tA.addHyperlinkListener(this);
+		showBack = (linkTouchedCommand != null);
+		scrollPane = new  JScrollPane(); 
+		scrollPane.getViewport().add( tA,  BorderLayout.CENTER ); 
+		if (showPanel)
+			showPanel();
+		resetTitle();
+	}
+	public void showPanel(){
+		addToWindow(scrollPane);
+		if (showBack){
+			controlHeight = 18;
+			controls = new MHTMLControl(this);
+			addToWindow(controls);
+			controls.setBounds(0, 0, getWidth(), controlHeight);
+			controls.setBackground(Color.white);
+		}
+		scrollPane.setBounds(0, controlHeight, getWidth(), getHeight() - controlHeight);
+	}
+	public void setLinkTouchedCommand(MesquiteCommand c){
+		linkTouchedCommand = c;
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(assignedTitle);
+	}
+	/*.................................................................................................................*/
+	public void setDataWindow(MesquiteWindow w){
+		this.dataWindow = w;
+	}
+	public MesquiteWindow getDataWindow(){
+		if (dataWindow != null){
+			if (dataWindow.disposed())
+				return null;
+		}
+		return dataWindow;
+	}
+	/*.................................................................................................................*/
+	/** Gets the minimum height of the content area of the window */
+	public int getMinimumContentHeight(){
+		return 100;
+	}
+	public void setText(String s) {
+		try {
+			if (backEnabled)
+				pastTexts.addElement(tA.getText());
+			tA.setText(s);
+		}
+		catch (Exception e){
+			MesquiteMessage.println("HTMLWindow: setText caused exception");
+		}
+		//tA.repaint();
+		if (showBack)
+			controls.repaint();
+	}
+	void goBack(){
+		if (backEnabled && pastTexts.size() <= 1)
+			return;
+		String t = (String)pastTexts.lastElement();
+		pastTexts.removeElementAt(pastTexts.size()-1);
+		tA.setText(t);
+		//tA.repaint();
+		if (showBack)
+			controls.repaint();
+	}
+	public void setBackEnabled(boolean en){
+		backEnabled = en;
+		if (showBack)
+		controls.repaint();
+	}
+	public String getText() {
+		return tA.getText();
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Goes back to previous page",null, commandName, "goBack")) {
+			goBack();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+		return getText();
+	}
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		if (scrollPane!=null){
+			scrollPane.setBounds(0, controlHeight, getWidth(), getHeight() - controlHeight);
+			scrollPane.invalidate();
+			scrollPane.validate();
+			
+			if (showBack)
+				controls.setBounds(0, 0, getWidth(), controlHeight);
+		}
+	}
+
+	/** Sets the window size.  To be used instead of setSize. 
+	public void containerSizeSet(int width, int height) {
+	}
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize. */
+	public void setWindowSize(int width, int height) {
+		super.setWindowSize(width, height);
+		if (scrollPane!=null){
+			scrollPane.setBounds(0, controlHeight, getWidth(), getHeight() - controlHeight);
+			if (showBack)
+				controls.setBounds(0, 0, getWidth(), controlHeight);
+		}
+	}
+	/*.................................................................................................................*/
+	public void copyGraphicsPanel(){
+		if (tA == null)
+			return;
+		String s = tA.getSelectedText();
+		if (!StringUtil.blank(s)) {
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(s);
+			clip.setContents(ss, ss);
+		}
+		else {
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(tA.getText());
+			clip.setContents(ss, ss);
+		}
+	}
+	/*.................................................................................................................*/
+
+
+	public void hyperlinkUpdate(HyperlinkEvent e) {
+		if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+			JEditorPane pane = (JEditorPane) e.getSource();
+
+			if (e instanceof HTMLFrameHyperlinkEvent) {
+				HTMLFrameHyperlinkEvent  evt = (HTMLFrameHyperlinkEvent)e;
+				HTMLDocument doc = (HTMLDocument)pane.getDocument();
+				doc.processHTMLFrameHyperlinkEvent(evt);
+			} else {
+				try {
+					pane.setPage(e.getURL());
+				} catch (Throwable t) {
+					if (linkTouchedCommand != null)
+						linkTouchedCommand.doItMainThread(ParseUtil.tokenize(e.getDescription()), null, false, false);
+				}
+			}
+		}
+	}
+
+}
+class MHTMLControl extends MesquitePanel {
+	MesquiteHTMLWindow window;
+	static Image backImage, backDimImage;
+
+	MesquiteCommand goBackCommand = null;
+	public MHTMLControl (MesquiteHTMLWindow window){
+		if (	backImage==null){
+			backImage=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "back.gif");  
+			backDimImage=  MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "backDim.gif");  
+		}
+		this.window = window;
+		goBackCommand = new MesquiteCommand("goBack", window);
+	}
+	/*.................................................................................................................*/
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (x>16 && x<46 && y>0 && y<window.controlHeight)
+			goBackCommand.doItMainThread(null, null, null);
+	}
+	public void paint(Graphics g){
+		if (window.backEnabled && window.pastTexts.size() > 1)
+			g.drawImage(backImage, 16, 0, this);
+		else
+			g.drawImage(backDimImage, 16, 0, this);
+
+		g.fillRect(0,getBounds().height -2,getBounds().width, 4);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteImage.java b/Source/mesquite/lib/MesquiteImage.java
new file mode 100644
index 0000000..4c795ab
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteImage.java
@@ -0,0 +1,244 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.net.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/*===============================================*/
+/** This class provides utilities to recover images from local file or URL, automatically choosing
+depending whether Mesquite is being run as applet or application.*/
+public abstract class MesquiteImage extends Image {
+	static int noFileErrorCount = 0;
+	/** Returns an image at a given path relative to the code base of Mesquite*/
+	public static Image getImageNullIfDoesntExist(String path) {
+		if (!MesquiteFile.fileExists(path)) {
+			if (noFileErrorCount == 10)
+				MesquiteMessage.printStackTrace("Image file doesn't exist: " + path + "; THIS MESSAGE WILL NOT BE REPEATED DURING THIS RUN OF MESQUITE");
+			else if (noFileErrorCount<10)
+				MesquiteMessage.println("Image file doesn't exist: " + path);
+			noFileErrorCount++; 
+			return null;
+		}
+		return Toolkit.getDefaultToolkit().getImage(path);
+	}
+	/** Returns an image at a given path relative to the code base of Mesquite*/
+	public static Image getImage(String path) {
+		return getImage(path, true);
+	}
+	/** Returns an image at a given path relative to the code base of Mesquite*/
+	public static Image getImage(String path, boolean warn) {
+		if (path == null)
+			return null;
+		if (path.indexOf("://")>=0){
+			try {
+				URL imageURL = new URL(path);
+				return Toolkit.getDefaultToolkit().getImage(imageURL);
+			}
+			catch (MalformedURLException e) {
+				MesquiteMessage.println("malformed URL in get image(1) " + path);
+				return null;
+			}
+		}
+		if (!MesquiteFile.fileExists(path)) {
+			if (warn){
+				if (noFileErrorCount == 10)
+					MesquiteMessage.printStackTrace("Image file doesn't exist: " + path + "; THIS MESSAGE WILL NOT BE REPEATED DURING THIS RUN OF MESQUITE");
+				else if (noFileErrorCount<10)
+					MesquiteMessage.println("Image file doesn't exist: " + path);
+				noFileErrorCount++; 
+			}
+		return null;
+		}
+		return Toolkit.getDefaultToolkit().getImage(path);
+	}
+
+	/** Returns an image at a given path relative to the location of a file (URL or local)*/
+	public static Image getImage(String path, MesquiteProject project) {
+		if (project.getHomeURL()==null) {
+			return Toolkit.getDefaultToolkit().getImage(MesquiteFile.composePath(project.getHomeDirectoryName(), path));
+		}
+		else {
+			URL url = project.getHomeURL();
+			try {
+				String directoryName = url.getFile().substring(0, url.getFile().lastIndexOf(MesquiteFile.fileSeparator)+1); 
+				URL imageURL = new URL(url.getProtocol() + "://" + directoryName + path);
+				return Toolkit.getDefaultToolkit().getImage(imageURL);
+			}
+			catch (MalformedURLException e) {
+				MesquiteMessage.println("malformed URL in get image (2) " + path);
+				return null;
+			}
+
+		}
+	}
+	/*...........................................................*/
+	public static void swapParts(Image[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		Image temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveParts(Image[] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		Image[] newValues = new Image[d.length];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*.................................................................................................................*/
+	public static boolean waitForImageToLoad(Image image){
+		return waitForImageToLoad(image, MesquiteModule.logWindow.getParentFrame());
+	}
+	/*.................................................................................................................*/
+	public static boolean waitForImageToLoad(Image image, Component component){
+		MediaTracker mt = new MediaTracker(component);
+		mt.addImage(image, 0);
+		try {
+			mt.waitForID(0);
+			} catch (Exception e) {
+			MesquiteFile.throwableToLog(component, e);
+		}
+		while (mt.statusID(0, true) == MediaTracker.LOADING) {
+			try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+				MesquiteFile.throwableToLog(component, e);
+			break;
+			}
+		}
+
+		boolean complete =  (mt.statusID(0, true) == MediaTracker.COMPLETE);
+		mt.removeImage(image, 0);
+		return complete;
+}
+	/*.................................................................................................................*/
+	public static Image loadImage(String message, String path, Component component,  MesquiteString imagePath) {
+		String imagePathLocal = path;
+		if (StringUtil.blank(path)) {
+			if (MesquiteThread.isScripting())
+				return null;
+			MesquiteString directoryName= new MesquiteString();
+			MesquiteString fileName= new MesquiteString();
+			imagePathLocal = MesquiteFile.openFileDialog(message, directoryName, fileName);
+		}
+		if (StringUtil.blank(imagePathLocal))
+			return null;
+
+		Image image = getImageNullIfDoesntExist(imagePathLocal);
+
+		if (imagePath!=null)
+			imagePath.setValue(imagePathLocal);
+
+		if (image!=null && (component == null || waitForImageToLoad(image,component)))
+			return image;
+		return null;
+	}
+	/*.................................................................................................................*/
+	/* Returns reduction needed to reduce into constraints; if width and height already smaller, then returns 1.0*/
+	public static double getScaleToReduce(int width, int height, int constrainedWidth, int constrainedHeight){
+		if (constrainedWidth == 0 || constrainedHeight == 0)
+			return 1.0;
+		if (width > constrainedWidth || height > constrainedHeight){
+			double scale = 1.0;
+			if (width*1.0/constrainedWidth > height*1.0/constrainedHeight) //width proportionately way too big
+				scale = constrainedWidth*1.0/width;
+			else  //height proportionately way too big
+				scale =constrainedHeight*1.0/height;
+			width *= scale;
+			height *= scale;
+			return scale;
+		}
+		else if (width < constrainedWidth || height < constrainedHeight){
+			double scale = 1.0;
+			if (width*1.0/constrainedWidth > height*1.0/constrainedHeight) //width proportionately way too big
+				scale = constrainedWidth*1.0/width;
+			else  //height proportionately way too big
+				scale =constrainedHeight*1.0/height;
+			width *= scale;
+			height *= scale;
+			return scale;
+		}
+		return 1.0;
+	}
+
+	public static Rectangle drawImageWithinRect(Graphics g, Image pic, int w, int h, ImageObserver io){
+		return drawImageWithinRect(g, pic, 0, 0, w, h, io);
+	}
+	public static Rectangle drawImageWithinRect(Graphics g, Image pic, int x, int y,  int w, int h, ImageObserver io){
+		return drawImageWithinRect(g, pic, x, y, w, h, true, io);
+	}
+	public static Rectangle drawImageWithinRect(Graphics g, Image pic, int x, int y,  int w, int h, boolean center, ImageObserver io){
+		if (pic == null)
+			return null;
+		int picWidth = pic.getWidth(io);
+		int picHeight = pic.getHeight(io);
+		double scale = getScaleToReduce(picWidth, picHeight, w, h);
+	//	if (scale<1.0){
+			picWidth *= scale;
+			picHeight *= scale;
+	//	}
+	//	else
+	//		scale = 1.0;
+		if (center){
+			int picX = x + (w-picWidth)/2;
+			int picY = y + (h-picHeight)/2;
+			if (g != null)
+				g.drawImage(pic,picX, picY, picWidth, picHeight, io);
+			return new Rectangle(picX, picY, picWidth, picHeight);
+		}
+		else {
+			if (g != null)
+				g.drawImage(pic,x, y, picWidth, picHeight, io);
+			return new Rectangle(x, y, picWidth, picHeight);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteInteger.java b/Source/mesquite/lib/MesquiteInteger.java
new file mode 100644
index 0000000..913dbfa
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteInteger.java
@@ -0,0 +1,717 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.consensus.lib.Bipartition;
+
+/*Last documented:  August 1999 */
+
+/* ======================================================================== */
+/**This int wrapper class is used to be able to pass integers by reference and have the
+	original change as needed*/
+public class MesquiteInteger implements Listable{
+	public static final int unassigned = Integer.MIN_VALUE+1;
+	public static final int impossible = Integer.MAX_VALUE - 1;
+	public static final int finite = Integer.MAX_VALUE-3;
+	public static final int infinite = Integer.MAX_VALUE;
+	public static final int negInfinite = Integer.MIN_VALUE;
+	public static final int inapplicable = Integer.MAX_VALUE -2;
+	private int value;
+	public static long totalCreated = 0;
+	
+	public MesquiteInteger (String name, int value) {
+		this.name = name;
+		this.value=value;
+		totalCreated++;
+	}
+	public MesquiteInteger(int value) {
+		this.value=value;
+		totalCreated++;
+	}
+	public MesquiteInteger() {
+		this.value=unassigned;
+		totalCreated++;
+	}
+	/*--------------------------------GET/SET--------------------------*/
+	/** Returns value as an integer */
+	public int getValue() {
+		return value;
+	}
+	/** Sets value */
+	public void setValue(int value) {
+		this.value=value;
+	}
+	/** Sets value */
+	public void setValue(String s) {
+		this.value=fromString(s);
+	}
+	/** Adds one to value */
+	public void increment() {
+		value++;
+	}
+	/** Adds one to value */
+	public void increment(int incrementValue) {
+		value+=incrementValue;
+	}
+	/** Subtracts one from value */
+	public void decrement() {
+		value--;
+	}
+	/** Subtracts one from value */
+	public void decrement(int decrementValue) {
+		value-= decrementValue;
+	}
+	/** Sets value to unassigned */
+	public void setToUnassigned() {
+		value=unassigned;
+	}
+	/*--------------------------------QUERY--------------------------*/
+	/** Returns whether value is unassigned */
+	public boolean isUnassigned() {
+		return (value==unassigned);
+	}
+	/** Returns whether value is unassigned */
+	public static boolean isUnassigned(int i) {
+		return (i==unassigned);
+	}
+	/** Returns whether value is infinite */
+	public boolean isInfinite() {
+		return (value==infinite || value == negInfinite);
+	}
+	/** Returns whether value is infinite */
+	public static boolean isInfinite(int i) {
+		return (i==infinite || i == negInfinite);
+	}
+	/** Returns whether value is finite */
+	public boolean isFinite() {
+		return (value==finite || isCombinable());
+	}
+	/** Returns whether value is finite */
+	public static boolean isFinite(int i) {
+		return (i==finite || isCombinable(i));
+	}
+	/** Returns whether value is impossible */
+	public boolean isImpossible() {
+		return (value==impossible);
+	}
+	/** Returns whether value is impossible */
+	public static boolean isImpossible(int i) {
+		return (i==impossible);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public boolean isInapplicable() {
+		return (value==inapplicable);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public static boolean isInapplicable(int i) {
+		return (i==inapplicable);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable() {
+		return (value!=unassigned && value!=infinite && value!=impossible&& value!=inapplicable && value != finite);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public static boolean isCombinable(int i) {
+		return (i!=unassigned && i!=infinite && i!=impossible&& i!=inapplicable && i != finite);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) and greater than zero */
+	public static boolean isPositive(int i) {
+		return isCombinable(i) && i>0;
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) and non-negative */
+	public static boolean isNonNegative(int i) {
+		return isCombinable(i) && i>=0;
+	}
+	/*--------------------------------INEQUALITIES--------------------------*/
+
+	/** Returns true if value 1 is less than value 2. */
+	public static boolean lessThan(int value1, int value2) {
+		if (value1 == infinite) 
+			return false;
+		else if (value2 == infinite) 
+			return true;
+		else if (value1 == negInfinite) 
+			return true;
+		else if (value2 == negInfinite) 
+			return false;
+		else if (!isCombinable(value2))
+			return isCombinable(value1);
+		else if (!isCombinable(value1))
+			return false;
+		else 
+			return (value1<value2);
+	}
+	/** Returns true if value 1 is greater than value 2. */
+	public static boolean greaterThan(int value1, int value2) {
+		if (value1 == infinite) 
+			return true;
+		else if (value2 == infinite) 
+			return false;
+		else if (value1 == negInfinite) 
+			return false;
+		else if (value2 == negInfinite) 
+			return true;
+		else if (!isCombinable(value2)) //TODO: think about these rules
+			return isCombinable(value1);
+		else if (!isCombinable(value1))
+			return false;
+		else 
+			return (value1>value2);
+	}
+	/*-------------------------------- firstIsGreaterThan --------------------------*/
+	/** Returns 1 if the first integer is greater than the second, -1 if the second is greater than the first, 0 otherwise.  Accounts for infinite, unassigned, etc. */
+	public static int whichIsGreater(int a, int b) {
+		if (a == unassigned || a == inapplicable || a == negInfinite || a == impossible || a == finite) {
+			if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible || b == finite)
+				return 0;
+			else
+				return -1;    //a is bad, b is combinable
+		}
+		
+		else if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible || b == finite)
+			return 1;  
+		else if (a==infinite)
+			return 1;
+		else if (b==infinite)
+			return -1;
+		else if (a>b)
+			return 1;
+		else if (b>a)
+			return -1;
+		else return 0;
+	}
+	/*--------------------------------CONTAINS--------------------------*/
+	/** Returns true iff the integer a is contained within the bounds of b1 through b2, inclusive. */
+	public static boolean contains(int a, int b1, int b2) {
+		if (!isCombinable(a) || !isCombinable(b1)||!isCombinable(b2))
+			return false;
+		if (b1<=b2)
+			if (a>=b1 && a<=b2)
+				return true;
+		if (b1>=b2)
+			if (a<=b1 && a>=b2)
+				return true;
+		return false;
+	}
+
+		/*--------------------------------MIN-MAX--------------------------*/
+	/** Returns maximum of two integers.  Accounts for infinite, unassigned, etc. */
+	public static int maximum(int a, int b) {
+		if (a == unassigned || a == inapplicable || a == negInfinite || a == impossible || a == finite) {
+			if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible || b == finite)
+				return unassigned;
+			else
+				return b;
+		}
+		
+		else if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible || b == finite)
+			return a;
+		else if (a==infinite)
+			return a;
+		else if (b==infinite)
+			return b;
+		else if (a>b)
+			return a;
+		else
+			return b;
+	}
+	/** Returns minimum of two integers.  Accounts for infinite, unassigned, etc. */
+	public static int minimum(int a, int b) {
+		if (a == unassigned || a == inapplicable || a == infinite || a == impossible || a == finite){
+			if (b==unassigned || b == inapplicable || b== infinite || b == impossible || b == finite)
+				return unassigned;
+			else
+				return b;
+		}
+		else if (b==unassigned || b == inapplicable || b== infinite || b == impossible || b == finite)
+			return a;
+		else if (a==negInfinite)
+			return a;
+		else if (b==negInfinite)
+			return b;
+		else if (a<b)
+			return a;
+		else
+			return b;
+	}
+	/** Returns maximum of three integers.  Accounts for infinite, unassigned, etc. */
+	public static int maximum(int a, int b, int c) {
+		return maximum(a,maximum(b,c));
+	}
+	/** Returns maximum of four integers.  Accounts for infinite, unassigned, etc. */
+	public static int maximum(int a, int b, int c, int d) {
+		return maximum(a,maximum(b,maximum(c,d)));
+	}
+	/** Returns minimum of three integers.  Accounts for infinite, unassigned, etc. */
+	public static int minimum(int a, int b, int c) {
+		return minimum(a,minimum(b,c));
+	}
+	/** Returns minimum of four integers.  Accounts for infinite, unassigned, etc. */
+	public static int minimum(int a, int b, int c, int d) {
+		return minimum(a,minimum(b,minimum(c,d)));
+	}
+	
+	/*--------------------------------Arithmetics--------------------------*/
+	/** Adds to current value.  Considers infinite, unassigned etc. */
+	public void add(int toAdd) {
+		value = add(toAdd, value);
+	}
+	/** Subtracts from current value.  Considers infinite, unassigned etc. */
+	public void subtract(int toSubtract) {
+		value = subtract(value, toSubtract);
+	}
+	/** Adds two ints.  Considers infinite, unassigned etc. */
+	public static int add(int value1, int value2) {
+		if (value1 == infinite){
+			if (value2== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (value2 == negInfinite)
+			return negInfinite;
+		else if (value1 == finite || value2 == finite)
+			return finite;
+		else if (isCombinable(value1)) {
+			if (isCombinable(value2))
+				return value1 + value2;
+			else
+				return value1;
+		}
+		else
+			return value2;
+	}
+	/** Subtracts value2 from value 1.  Considers infinite, unassigned etc. */
+	public static int subtract(int value1, int value2) {
+		if (value2 == negInfinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== infinite)
+				return 0;
+			else
+				return negInfinite;
+		}
+		else if (value1 == infinite)
+			return infinite;
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (isCombinable(value2)) {
+			if (isCombinable(value1))
+				return value1 - value2;
+			else if (value2 == finite)
+				return value2;
+			else
+				return -value2;
+		}
+		else
+			return value1;
+	}
+	/** Multiplies two ints.  Considers infinite, unassigned etc. */
+	public static int multiply(int value1, int value2) {
+		if (value1 == 0 || value2==0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return value1*value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite){
+					if (value1<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value2== negInfinite) {
+					if (value1<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				if (value1 == infinite){
+					if (value2<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value1== negInfinite) {
+					if (value2<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+			else { //neither combinable
+				if (value1 == infinite && value2 == infinite)
+					return infinite;
+				else if (value1 == infinite && value2 == negInfinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == infinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == negInfinite)
+					return infinite;
+				else 
+					return unassigned;
+			}
+		}
+		
+	}
+	/** Divides first int by second int.  Considers infinite, unassigned etc. */
+	public static double divide(int value1, int value2) {
+		if (value2==0)
+			return MesquiteDouble.infinite;
+		else if (value1 == 0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return ((double)value1)/value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return MesquiteDouble.unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				return MesquiteDouble.unassigned;
+			}
+			else { //neither combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return MesquiteDouble.unassigned;
+			}
+		}
+	}
+	/*----------------------------------------------------------*/
+	public static boolean isDivisibleBy(int value, int diviser) {
+		if (diviser == 0) 
+			return false;
+		int fraction = (int)java.lang.Math.round(value/diviser);
+		return (fraction*diviser==value);
+	}
+	/*----------------------------------------------------------*/
+	public static int roundUp(double value) {
+		return (int)java.lang.Math.round(value+0.4999999999999);
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	String name = null;
+	/** Returns string version of this value.  Returns "unassigned" etc. if needed. (for Listable interface)*/
+	public String getName(){
+		if (name == null)
+		return toString();
+		else return name;
+	}
+	/** Returns string version of this value.  Returns "unassigned" etc. if needed*/
+	public String toString() {
+		return toString(value);
+	}
+	/** Returns string version of value.  Returns "unassigned" etc. if needed*/
+	public static String toString(int v) {
+		if (v==unassigned)
+			return "?"; //changed from "unassigned" June 02
+		else if (v==infinite)
+			return "infinite";
+		else if (v==negInfinite)
+			return "neg.infinite";  
+		else if (v==impossible)
+			return "impossible";  
+		else if (v==inapplicable)
+			return "inapplicable"; 
+		else if (v==finite)
+			return "finite"; 
+		else {
+			try {
+				return Integer.toString(v);
+			}
+			catch (NumberFormatException ne){
+				return "impossible";
+			}
+		}
+	}
+
+	/** Returns string version of this value, with leading zeros as needed.  Returns "unassigned" etc. if needed*/
+	public static String toStringDigitsSpecified(int v, int digits) {
+		if (v==unassigned)
+			return "?"; 
+		else if (v==infinite)
+			return "infinite";
+		else if (v==negInfinite)
+			return "neg.infinite";  
+		else if (v==impossible)
+			return "impossible";  
+		else if (v==inapplicable)
+			return "inapplicable"; 
+		else if (v==finite)
+			return "finite"; 
+		else {
+			try {
+				String s = "";
+				boolean negative = (v<0);
+				if (negative)
+					s = Integer.toString(-v);
+				else
+					s = Integer.toString(v);
+				if (s.length()<digits)
+					for (int i=0; i<digits-s.length(); i++)
+						s="0"+s;
+				if (negative) 
+					s="-"+s;
+				return s;
+			}
+			catch (NumberFormatException ne){
+				return "impossible";
+			}
+		}
+	}
+
+	public static boolean isNumber(String s) {
+		if (StringUtil.blank(s))
+			return false;
+		try {
+			int value = Integer.parseInt(s);
+			return true;
+		}
+		catch (NumberFormatException e) {
+			return false;
+		}
+	}
+	
+	/** DOCUMENT */
+	public static int orderOfMagnitude(int x) {
+		if (!isCombinable(x))
+			return MesquiteInteger.impossible;
+		int current = 1;
+		for (int i = 0; ; i++) {
+			if (x<current)
+				return i;
+			try {
+				current *=10;
+			}
+			catch (Exception e) {
+				return i;
+			}
+		}
+	}
+
+	/** DOCUMENT */
+	public static int getDigit(int x, int digit) {
+		if (!isCombinable(x))
+			return MesquiteInteger.impossible;
+		int baseNumber = 1;
+		for (int i=1; i<=digit; i++)
+			baseNumber*=10;
+		int leftOver = x % baseNumber;  // now need to strip off everything to the right
+		if (digit == 1) return leftOver;
+		baseNumber /= 10;
+		leftOver /= baseNumber;
+		return leftOver;
+	}
+
+	/** DOCUMENT */
+	public static int power(int x, int power) {
+		if (!isCombinable(x))
+			return MesquiteInteger.impossible;
+		if (power==0)
+			return 1;
+		int value = x;
+		if (power>0) {
+			for (int i=2; i<=power; i++)
+				value=value*x;
+		} else
+			for (int i=2; i<=-power; i++)
+				value= value/x;
+		return value;
+	}
+
+	public static void logHorizIntegerList(int max){
+		int orderOfMag = MesquiteInteger.orderOfMagnitude(max);
+		StringBuffer sb = new StringBuffer();
+		
+		for (int OOM = orderOfMag-1; OOM>=0; OOM--) {
+			int count = 1;
+			int baseNumber = power(10,OOM);
+			for (int i=0; i<max; i++){
+				if (baseNumber>0 && (i+1) % baseNumber==0) {
+					if ((i+1)/baseNumber>0) {
+						sb.append("" + getDigit(i+1,OOM+1));
+					}
+					else
+						sb.append(" ");
+				}
+				else if (baseNumber==0)
+					sb.append(getDigit(i+1,1));
+				else sb.append(" ");
+				count++;
+			}
+			sb.append("\n");
+		}
+		MesquiteMessage.println(sb.toString());
+	}
+
+	/** Returns integer parsed from given string.  Assumes entire string is what should be parsed. */
+	public static int fromString(String s) { 
+		return fromString(s, false);
+	}
+	
+	/** Returns integer parsed from given string; warns about NumberFormatException if boolean is true,
+	   using warningMessage.
+	  Assumes entire string is what should be parsed. */
+	public static int fromString(String s, String warningMessage, boolean warnQuiet, boolean warnProminent) {
+		if (StringUtil.blank(s))
+			return impossible;
+		try {
+			return Integer.parseInt(s);
+		}
+		catch (NumberFormatException e) {
+			if (s !=null) {
+				if (s.equalsIgnoreCase("unassigned") || s.equalsIgnoreCase("estimate") ||s.equalsIgnoreCase("?"))
+					return unassigned;
+				else if (s.equalsIgnoreCase("infinite") || s.equalsIgnoreCase("i"))
+					return infinite;
+				else if (s.equalsIgnoreCase("inapplicable"))
+					return inapplicable;
+				else if (s.equalsIgnoreCase("neg.Infinite"))
+					return negInfinite;
+				else if (s.equalsIgnoreCase("impossible"))
+					return impossible;
+				else if (s.equalsIgnoreCase("finite"))
+					return finite;
+			}
+			if (warnQuiet)
+				MesquiteMessage.println(warningMessage);
+			else if (warnProminent)
+				MesquiteTrunk.mesquiteTrunk.alert(warningMessage);
+			return impossible;
+		}
+	}
+	/** Returns integer parsed from given string; warns about NumberFormatException if boolean is true using the
+	message "NumberFormatException in parsing string "<s>". Assumes entire string is what should be parsed. */
+	public static int fromString(String s, boolean warn) {
+		
+		return fromString(s,"NumberFormatException in parsing string \"" + s + "\"",warn, false);
+	}
+	/** Returns integer parsed from given string, starting at string position given.
+	Assumes only first token from pos is to be parsed. */
+	public static int fromString(Parser parser) {
+		String f =parser.getNextToken(); 
+		if ("-".equals(f))
+			return -fromString(parser.getNextToken(), false); 
+		else
+			return fromString(f, false); 
+	}
+	/** Returns integer parsed from given string, starting at string position given.
+	Assumes only first token from pos is to be parsed. */
+	public static int fromString(String s, MesquiteInteger pos) {
+		String f =ParseUtil.getToken(s,pos); 
+		if ("-".equals(f))
+			return -fromString(ParseUtil.getToken(s,pos), false); 
+		else
+			return fromString(f, false); 
+	}
+	/** Returns integer parsed from first token of given string, and sets value of pos
+	to character at end of this token. */
+	public static int fromFirstToken(String s, MesquiteInteger pos) {
+		pos.setValue(0);
+		return fromString(s,pos);
+	}
+	/*--------------------------------QUERY DIALOGS--------------------------*/
+	/** Presents dialog querying user for two integers */
+	public static void queryTwoIntegers(MesquiteWindow parent, String title, String label1, String label2, MesquiteBoolean answer, MesquiteInteger num1, MesquiteInteger num2,int min1,int max1,int min2, int max2, String helpString) {
+		 TwoIntegersDialog tid = new TwoIntegersDialog(parent, title, label1, label2, answer, num1, num2,min1,max1,min2,max2, helpString);
+		 tid.dispose();
+		 
+	}
+	/** Presents dialog querying user for an integers, with no check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, int current) {
+		MesquiteInteger io = new MesquiteInteger(current);
+		//IntegerDialog id = new IntegerDialog(parent, title, message, io);
+		//	id.dispose();
+		QueryDialogs.queryInteger(parent, title, message, true, io);
+		return io.getValue();
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, int current, int minimum, int maximum, boolean allowCancel) {
+		return queryInteger( parent,  title,  message, "",  current,  minimum,  maximum,  allowCancel);
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, String secondaryMessage, String help, int current, int minimum, int maximum, boolean allowCancel) {
+		if (MesquiteInteger.isCombinable(maximum) && current>maximum)
+			current=maximum;
+		else if (MesquiteInteger.isCombinable(minimum) && current<minimum)
+			current=minimum;
+		MesquiteInteger io = new MesquiteInteger(current);
+		boolean done=false;
+		if (StringUtil.blank(help)) {
+			help = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a whole number (integer).  <p>The initial value is " + MesquiteInteger.toString(current) + ". ";
+			if (MesquiteInteger.isCombinable(minimum))
+				help += "The minimum value permitted is " + MesquiteInteger.toString(minimum)+ ". ";
+			if (MesquiteInteger.isCombinable(maximum))
+				help += "The maximum value permitted is " + MesquiteInteger.toString(maximum)+ ". ";
+		}
+		while (!done) {
+			//IntegerDialog id = new IntegerDialog(parent, title, message, io);
+			//id.dispose();
+			QueryDialogs.queryInteger(parent, title, message, secondaryMessage, help, allowCancel, io);
+			if (!io.isCombinable() || ((!MesquiteInteger.isCombinable(maximum) || io.getValue()<=maximum) && (!MesquiteInteger.isCombinable(minimum) ||  io.getValue()>=minimum)))
+				done=true;
+			else {
+				if (maximum==infinite)
+					MesquiteModule.mesquiteTrunk.alert("Value must be " + Integer.toString(minimum) + " or more");
+				else
+					MesquiteModule.mesquiteTrunk.alert("Value must be between " + Integer.toString(minimum) + " and " + Integer.toString(maximum));
+				io.setValue(current);
+			}
+		}
+		return io.getValue();
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, String help, int current, int minimum, int maximum, boolean allowCancel) {
+		return queryInteger(parent, title, message, null, help, current, minimum, maximum, allowCancel);
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, int current, int minimum, int maximum) {
+		return queryInteger(parent, title, message, current, minimum, maximum, true);
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, String secondaryMessage, String help, int current, int minimum, int maximum) {
+		return queryInteger(parent, title, message, secondaryMessage, help, current, minimum, maximum, true);
+	}
+	/** Presents dialog querying user for an integers, with a check for minimum and maximum */
+	public static int queryInteger(MesquiteWindow parent, String title, String message, String help, int current, int minimum, int maximum) {
+		return queryInteger(parent, title, message, help, current, minimum, maximum, true);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteLabel.java b/Source/mesquite/lib/MesquiteLabel.java
new file mode 100644
index 0000000..9535d9c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteLabel.java
@@ -0,0 +1,251 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/** A small label that automatically resizes itself.  Still needs work, since should check if font has changed.
+Handles up to MAXLINES lines.*/
+public class MesquiteLabel extends MousePanel {
+	String[] s;
+	private int myWidth = 5;
+	//private MesquiteModule ownerModule;
+	int idNumber=0;
+	boolean recheckSize = false;
+	int numLines = 0;
+	Font curFont;
+	int oldLineHeight = 16;
+	Color color, dark, darkdark;
+	MesquiteCommand command = null;
+	static final int MAXLINES = 32;
+	String arguments = null;
+	boolean checkedDoomed = true; //used because DrawHierarchy was having trouble on quit
+	public MesquiteLabel(MesquiteModule ownerModule, int idNumber){ //TODO: get rid of ownerModule
+		super();
+		//this.ownerModule = ownerModule;
+		this.idNumber=idNumber;
+		//setBackground(Color.green);
+		setSize(1, 1);
+		setVisible(false);
+		this.color = Color.lightGray;
+		s = new String[MAXLINES];
+		for (int i=0; i<MAXLINES; i++)
+			s[i]=null;
+	}
+	public MesquiteLabel(MesquiteModule ownerModule){
+		this(ownerModule, 0);
+	}
+	public void setCheckDoomed(boolean checkedDoomed){
+		this.checkedDoomed = checkedDoomed;
+	}
+	/*public MesquiteModule getOwnerModule() {
+		return ownerModule;
+	}*/
+	public void dispose(){
+		if (command !=null)
+			command.dispose();
+		command = null;
+		super.dispose();
+	}
+	public void setText(String st) {  
+		if ((st==null) || (st.equals(""))) {
+			numLines = 0;
+			setSize(1, 1);
+			setVisible(false);
+		}
+		else  {
+			if (st.indexOf('\n')<0) {
+				this.s[0]=st;
+				numLines = 1;
+			}
+			else {
+				numLines = 0;
+				while(st.indexOf('\n')>=0){
+					String firstLine = st.substring(0, st.indexOf('\n'));
+					s[numLines]=firstLine;
+					if (numLines<MAXLINES)
+						numLines++;
+					st = st.substring(st.indexOf('\n')+1, st.length());
+				}
+				if (!StringUtil.blank(st)){
+					addLine(st);
+					setVisible(true);
+					recheckSize = true;
+					repaint();
+					return;
+				}
+			}
+			setVisible(true);
+			recheckSize = true;
+			repaint();
+		}
+	}
+	public void setCommand(MesquiteCommand command) {  
+		this.command = command;
+	}
+	public void setArguments(String arguments) {  
+		this.arguments = arguments;
+	}
+	public String getText(int line) {  
+		if (line<numLines)
+			return s[line];
+		else
+			return "";
+	}
+	public void addLine(String st) {  
+		if ((st==null) || (st.equals(""))) {
+		}
+		else {
+			setVisible(true);
+			s[numLines]=st;
+			if (numLines<MAXLINES)
+				numLines++;
+			recheckSize = true;
+			repaint();
+		}
+	}
+	
+	public void setFontName (String name) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (name, curFont.getStyle(), curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+	public void setFontStyle (int style) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), style, curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+    	 public void setFontSize (int size) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), size);
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setFont(curFont);
+ 		}
+    	 }
+    	 public void setColor (Color color) {
+		this.color = color;
+		if (color != null) {
+			dark = color.darker();
+			darkdark = dark.darker();
+		}
+    	 }
+    	public int getWidth(Graphics g){
+    		if (g==null)
+    			return 0;
+			FontMetrics fm=g.getFontMetrics(g.getFont());
+			int maxWidth = 0;
+			for (int i=0; i<numLines; i++){
+				int thisWidth =fm.stringWidth(s[i]);
+				if (thisWidth>maxWidth)
+					maxWidth = thisWidth;
+			}
+			if (myWidth!=maxWidth+10) 
+				return maxWidth+10;
+			else
+				return myWidth;
+    	}
+    	public void update(Graphics g){
+    		paint(g);
+    	}
+    	
+	public void paint(Graphics g) {
+	   	if (checkedDoomed){
+		   	if (MesquiteWindow.checkDoomed(this))
+		   		return;
+		}
+		int w =getBounds().width;
+		int h = getBounds().height;
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int lineHeight = fm.getAscent() + fm.getDescent() + 4;
+		
+		if (recheckSize || lineHeight!=oldLineHeight) {
+			recheckSize = false;
+			int maxWidth = 0;
+			for (int i=0; i<numLines; i++){
+				int thisWidth =fm.stringWidth(s[i]);
+				if (thisWidth>maxWidth)
+					maxWidth = thisWidth;
+			}
+			if (myWidth!=maxWidth+10 || lineHeight!=oldLineHeight) {
+				oldLineHeight = lineHeight;
+				myWidth = maxWidth+10;
+				setSize(myWidth, lineHeight*numLines);
+				repaint();
+			   	if (checkedDoomed)
+				   	MesquiteWindow.uncheckDoomed(this);
+				return;
+			}
+			oldLineHeight = lineHeight;
+		} 
+		g.setColor(getBackground());
+		g.fillRect(0,0,w,h);
+			
+		if (color != null) {
+			g.setColor(color);
+			g.fillRoundRect(0,0,w,h, 5, 5);
+			g.setColor(Color.darkGray);
+			g.drawRoundRect(0,0,w-1,h-1, 5, 5);
+			g.setColor(Color.white);
+			g.drawRoundRect(1,1,w-3,h-3, 5, 5);
+			//g.setColor(dark);
+			//g.drawRoundRect(1,1,w-1,h-1, 5, 5);
+		}
+		g.setColor(Color.black);
+		for (int i=0; i<numLines && i < s.length; i++){
+			if (s[i] == null || s[i].length() == 0){
+			}
+			else if (s[i].charAt(0) == '\2') {
+				GraphicsUtil.setFontStyle(Font.BOLD, g);
+				g.drawString(s[i].substring(1), 4,(i+1)*lineHeight-fm.getDescent()-2);
+				GraphicsUtil.setFontStyle(Font.PLAIN, g);
+			}
+			else if (s[i].charAt(0) == '\1') {
+				GraphicsUtil.setFontStyle(Font.ITALIC, g);
+				g.drawString(s[i].substring(1), 4,(i+1)*lineHeight-fm.getDescent()-2);
+				GraphicsUtil.setFontStyle(Font.PLAIN, g);
+			}
+			else
+				g.drawString(s[i], 4,(i+1)*lineHeight-fm.getDescent()-2);
+		}
+		if (checkedDoomed)
+			MesquiteWindow.uncheckDoomed(this);
+	}
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Label", command, this);
+			return;
+		}
+		else if (command == null)
+ 			MesquiteModule.mesquiteTrunk.logln("Label touched with ID number " + Integer.toString(idNumber));
+ 		else
+ 			command.doItMainThread(arguments +  " "  + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Label", command, this), this);
+ 		return;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteListTable.java b/Source/mesquite/lib/MesquiteListTable.java
new file mode 100644
index 0000000..e7d785c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteListTable.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+/* ======================================================================== */
+/** A table for List windows*/
+public class MesquiteListTable extends MesquiteTable {
+	MesquiteModule ownerModule;
+	Listable[] array;
+	ListableVector vector; 
+	boolean useArray=true;
+	
+	public MesquiteListTable (Listable[] array, MesquiteModule ownerModule, int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int columnNamesWidth) {
+		super(numRowsTotal, numColumnsTotal, totalWidth, totalHeight, columnNamesWidth, ColorDistribution.getColorScheme(ownerModule),true,false);
+		this.ownerModule=ownerModule;
+		this.array = array;
+		useArray=true;
+	}
+	
+	public MesquiteListTable (ListableVector vector, MesquiteModule ownerModule, int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int columnNamesWidth) {
+		super(numRowsTotal, numColumnsTotal, totalWidth, totalHeight, columnNamesWidth, ColorDistribution.getColorScheme(ownerModule),true,false);
+		this.ownerModule=ownerModule;
+		this.vector = vector;
+		useArray=false;
+	}
+	
+	public void drawMatrixCell(Graphics g, int x, int y,  int w, int h, int column, int row, boolean selected){  
+	}
+	
+	public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column){
+	}
+	/*.................................................................................................................*/
+//	public String getRowComment(int row) {
+//		return getExplanation(row);
+/*		String rN = "";
+		if (useArray) {
+//			if (!(array == null || row>=array.length || array[row] == null))
+//				rN = ((Listable)array[row]).getExplanation();
+		}
+		else {
+			if (!(vector == null || row>=vector.size() || vector.elementAt(row) == null)) 
+				rN = ((Listable)vector.elementAt(row)).getExplanation();
+		}
+		return rN;
+*/
+//	}
+
+	/*.................................................................................................................*/
+
+	public void drawRowNameCell(Graphics g, int x, int y,  int w, int h, int row){
+		String rN = null;
+		if (useArray) {
+			if (array == null) {
+				MesquiteMessage.warnProgrammer("Error: List table is using array but array is null");
+				rN = "<array null>";
+			}
+			else if (row>=array.length) {
+				MesquiteMessage.warnProgrammer("Error: List table has too many rows (array) " + row);
+				rN = "<no array element>";
+			}
+			else if (array[row] == null) {
+				MesquiteMessage.warnProgrammer("Error: List table has null element (array)" + row);
+				rN = "<null array element>";
+			}
+			else
+				rN = ((Listable)array[row]).getName();
+		}
+		else {
+			if (vector == null) {
+				MesquiteMessage.warnProgrammer("Error: List table is using vector but vector is null");
+				rN = "<vector null>";
+			}
+			else if (row>=vector.size()) {
+				MesquiteMessage.warnProgrammer("Error: List table has too many rows (vector)" + row);
+				rN = "<no vector element>";
+			}
+			else if (vector.elementAt(row) == null) {
+				MesquiteMessage.warnProgrammer("Error: List table has null element (vector)" + row);
+				rN = "<null vector element>";
+			}
+			else
+				rN = ((Listable)vector.elementAt(row)).getName();
+		}
+		if (rN==null)
+			rN="<no name>";
+		g.drawString(rN, x+getNameStartOffset(), StringUtil.getStringVertPosition(g,y,h, null));
+	}
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV,int modifiers, int clickCount) {
+		System.out.println(" Item " + Integer.toString(row) + " and feature " + Integer.toString(column) + " touched");
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteListWindow.java b/Source/mesquite/lib/MesquiteListWindow.java
new file mode 100644
index 0000000..0ea6b08
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteListWindow.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+/* ======================================================================== */
+/** This is used to list elements of a ListableVector; it is designed for quick and dirty use.  It is expected to be replaced.  */
+public class MesquiteListWindow extends MesquiteWindow {
+	public ListableVector vector; 
+	public MesquiteListTable table;
+	int windowWidth=200;
+	int windowHeight=400;
+	String assignedTitle;
+	public MesquiteListWindow (String assignedTitle, MesquiteModule ownerModule, ListableVector vector, boolean showInfoBar) {
+		super(ownerModule, showInfoBar);
+		this.assignedTitle = assignedTitle;
+		setWindowSize(windowWidth, windowHeight);
+		//setLayout(new BorderLayout());
+		int numItems = vector.size();
+
+		table = new MesquiteListTable (vector, ownerModule, numItems, 0, windowWidth, windowHeight, 160);
+		table.setUserAdjust(MesquiteTable.NOADJUST, MesquiteTable.RESIZE);
+ 		addToWindow(table);
+ 		table.setVisible(true);
+		table.setLocation(0,0);
+		resetTitle();
+ 		setVisible(true);
+ 
+	}
+	
+	public MesquiteListWindow (String assignedTitle, MesquiteModule ownerModule, Listable[] array, boolean showInfoBar) {
+		super( ownerModule, showInfoBar);
+		this.assignedTitle = assignedTitle;
+		setWindowSize(windowWidth, windowHeight);
+		//setLayout(null);
+		int numItems=array.length;
+		
+		table = new MesquiteListTable (array, ownerModule, numItems, 0, windowWidth, windowHeight, 90);
+ 		addToWindow(table);
+ 		table.setVisible(true);
+		table.setLocation(0,0);
+ 		setVisible(true);
+
+	}
+	
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(assignedTitle);
+	}
+	public void windowResized() {
+		super.windowResized();
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+   	 	if (table!=null && (getHeight()!=windowHeight) || (getWidth()!=windowWidth)) {
+   	 		windowHeight =getHeight();
+   	 		windowWidth = getWidth();
+   			table.setSize(windowWidth, windowHeight);
+   	 	}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteListener.java b/Source/mesquite/lib/MesquiteListener.java
new file mode 100644
index 0000000..db48421
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteListener.java
@@ -0,0 +1,102 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+
+/* ======================================================================== */
+/** An interface so that objects know some other object has changed (see Taxa)*/
+public interface MesquiteListener {
+	/** Constant for listener notify system.  Unknown change occured to object. */
+	public final static int UNKNOWN = MesquiteInteger.unassigned;
+	/** Names of parts have changed*/
+	public final static int NAMES_CHANGED = -1;
+	/** Selection of parts has changed*/
+	public final static int SELECTION_CHANGED= 128;
+	/** Parts have been added*/
+	public final static int PARTS_ADDED=-2;   
+	/** Parts have been deleted*/
+	public final static int PARTS_DELETED=-3;
+	/** Parts have been moved*/
+	public final static int PARTS_MOVED=-4;
+	/** Parts have been added, deleted, moved, or changed in some other serious way*/
+	public final static int PARTS_CHANGED=-5; 
+	/** Parts have been added, deleted, moved, or changed in some other serious way*/
+	public final static int PARTS_SWAPPED=-17; 
+	/** An element of a vector has changed */
+	public final static int ELEMENT_CHANGED=-6;
+	/** Branch lengths of tree have been changed*/
+	public final static int BRANCHLENGTHS_CHANGED = 111; 
+	/** Branches of tree have been rearranged*/
+	public final static int BRANCHES_REARRANGED = 112; 
+	/** One or more items in a source have been added terminally*/
+	public final static int ITEMS_ADDED = 113; 
+	/** One or more items in a source have been added terminally*/
+	public final static int NUM_ITEMS_CHANGED = 114; 
+	/** The value of the object has been changed*/
+	public final static int VALUE_CHANGED = -7; 
+	/** The taxa block on which this object is based was substituted for another*/
+	public final static int TAXA_SUBSTITUTED = -8; 
+	/** The annotations of the object has been changed*/
+	public final static int ANNOTATION_CHANGED = -10; 
+	/** The associated values of the Associable has been changed*/
+	public final static int ASSOCIATED_CHANGED = -11; 
+	/** The object has been destroyed (not used within Mesquite as of March 05)*/
+	public final static int OBJECT_DESTROYED = -12; 
+	/** An annotation of the object has been added*/
+	public final static int ANNOTATION_ADDED = -13; 
+	/** An annotation of the object has been added*/
+	public final static int ANNOTATION_DELETED = -14; 
+	/** An editable text field has been edited*/
+	public final static int TEXTFIELD_EDITED = -15; 
+	/** New results available*/
+	public final static int NEW_RESULTS = -16; 
+	/** Entries in a data matrix have been changed*/
+	public final static int DATA_CHANGED = -18; 
+	/** The main object (e.g. tree block) has been deleted*/
+	public final static int BLOCK_DELETED=-19;
+
+	/** Param of the tree drawing have been changed in such a way that its size may have changed.*/
+	public final static int TREE_DRAWING_SIZING_CHANGED = 800; 
+
+	
+	
+	/** Subcode values specifying how much of the data has changed*/
+	public final static int SINGLE_CELL = 900; 
+	public final static int SINGLE_CHARACTER = 901; 
+	public final static int SINGLE_TAXON = 902; 
+	public final static int CELL_BLOCK = 903; 
+	/** Subcode value specifying that the change is only a substitution of state in a cell, not a change from inapplicable or unassigned to or from a valid state*/
+	public final static int CELL_SUBSTITUTION = 904; 
+	/** Subcode value specifying that the change is only a shifting of all cells in each taxon, from first to last applicable, with no addition or deletion of characters*/
+	public final static int ALL_CELLS_ONLY_SHIFTED = 905; 
+	public final static int TAXA_CHANGED = 906;
+
+	
+	
+
+	/** A command was cancelled (used by CommandRecord)*/
+	public final static int COMMAND_CANCELLED = -9;
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification); 
+	/** passes which object was disposed*/
+	public void disposing(Object obj);
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser);
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteLong.java b/Source/mesquite/lib/MesquiteLong.java
new file mode 100644
index 0000000..7bc1f81
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteLong.java
@@ -0,0 +1,423 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+
+/* ======================================================================== */
+/**This long wrapper class is used to be able to pass integers by reference and have the
+	original change as needed.*/
+public class MesquiteLong implements Listable {
+	public static final long unassigned = Long.MIN_VALUE+1;
+	public static final long inapplicable = Long.MAX_VALUE - 1;
+	public static final long infinite = Long.MAX_VALUE;
+	public static final long negInfinite = Long.MIN_VALUE;
+	public static final long impossible = Long.MAX_VALUE - 2;
+	private long value;
+	public static long totalCreated = 0;
+	private String name = null;
+	
+	public MesquiteLong(long value) {
+		this.value=value;
+		totalCreated++;
+	}
+	
+	public MesquiteLong(String name, long value) {
+		this.value=value;
+		this.name = name;
+		totalCreated++;
+	}
+	public MesquiteLong() {
+		this.value=unassigned;
+		totalCreated++;
+	}
+	public void setName(String s){
+		name = s;
+	}
+	public String getName(){
+		return name;
+	}
+	/*--------------------------------GET/SET--------------------------*/
+	/** Returns value as a long */
+	public long getValue() {
+		return value;
+	}
+
+	/** Sets value */
+	public void setValue(String s) {
+		this.value=fromString(s);
+	}
+	/** Sets value */
+	public void setValue(long value) {
+		this.value=value;
+	}
+	/** Adds one to value */
+	public void increment() {
+		value++;
+	}
+	/** Subtracts one from value */
+	public void decrement() {
+		value--;
+	}
+	/** Sets value to unassigned */
+	public void setToUnassigned() {
+		value=unassigned;
+	}
+	/*--------------------------------CONVERSION--------------------------*/
+	public static long toLong(int v) {
+		if (v==MesquiteInteger.unassigned)
+			return MesquiteLong.unassigned;
+		else if (v==MesquiteInteger.infinite)
+			return MesquiteLong.infinite;
+		else if (v==MesquiteInteger.negInfinite)
+			return MesquiteLong.negInfinite;
+		else if (v==MesquiteInteger.impossible)
+			return MesquiteLong.impossible;
+		else if (v==MesquiteInteger.inapplicable)
+			return MesquiteLong.inapplicable;
+		else
+			return v;
+	}
+	/*--------------------------------QUERY--------------------------*/
+	/** Returns whether value is unassigned */
+	public boolean isUnassigned() {
+		return (value==unassigned);
+	}
+	/** Returns whether value is unassigned */
+	public static boolean isUnassigned(long i) {
+		return (i==unassigned);
+	}
+	/** Returns whether value is infinite */
+	public boolean isInfinite() {
+		return (value==infinite || value == negInfinite);
+	}
+	/** Returns whether value is infinite */
+	public static boolean isInfinite(long i) {
+		return (i==infinite || i == negInfinite);
+	}
+	/** Returns whether value is impossible */
+	public boolean isImpossible() {
+		return (value==impossible);
+	}
+	/** Returns whether value is impossible */
+	public static boolean isImpossible(long i) {
+		return (i==impossible);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public boolean isInapplicable() {
+		return (value==inapplicable);
+	}
+	/** Returns whether characteristic is inapplicable */
+	public static boolean isInapplicable(long i) {
+		return (i==inapplicable);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable() {
+		return (value!=unassigned && value!=infinite && value!=impossible&& value!=inapplicable);
+	}
+	/** Returns whether value is a regular number (NOT unassigned, infinite, inapplicable, impossible) */
+	public static boolean isCombinable(long i) {
+		return (i!=unassigned && i!=infinite && i!=impossible&& i!=inapplicable);
+	}
+	/*--------------------------------MIN-MAX--------------------------*/
+	/** Returns maximum of two long integers.  Accounts for infinite, unassigned, etc. */
+	public static long maximum(long a, long b) {
+		if (a == unassigned || a == inapplicable || a == negInfinite || a == impossible) {
+			if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible)
+				return unassigned;
+			else
+				return b;
+		}
+		else if (b==unassigned || b == inapplicable || b== negInfinite || b == impossible)
+			return a;
+		else if (a==infinite)
+			return a;
+		else if (b==infinite)
+			return b;
+		else if (a>b)
+			return a;
+		else
+			return b;
+	}
+	/** Returns minimum of two long integers.  Accounts for infinite, unassigned, etc. */
+	public static long minimum(long a, long b) {
+		if (a == unassigned || a == inapplicable || a == infinite || a == impossible){
+			if (b==unassigned || b == inapplicable || b== infinite || b == impossible)
+				return unassigned;
+			else
+				return b;
+		}
+		else if (b==unassigned || b == inapplicable || b== infinite || b == impossible)
+			return a;
+		else if (a==negInfinite)
+			return a;
+		else if (b==negInfinite)
+			return b;
+		else if (a<b)
+			return a;
+		else
+			return b;
+	}
+	/*--------------------------------Arithmetics--------------------------*/
+	/** turns value to absolute value. */
+	public void abs() {
+		if (isCombinable(value))
+			value = Math.abs(value);
+	}
+	/** Adds to current value.  Considers infinite, unassigned etc. */
+	public void add(long toAdd) {
+		value = add(toAdd, value);
+	}
+	/** Subtracts from current value.  Considers infinite, unassigned etc. */
+	public void subtract(long toSubtract) {
+		value = subtract(value, toSubtract);
+	}
+	/** Adds two doubles.  Considers infinite, unassigned etc. */
+	public static long add(long value1, long value2) {
+		if (value1 == infinite){
+			if (value2== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (value2 == negInfinite)
+			return negInfinite;
+		else if (isCombinable(value1)) {
+			if (isCombinable(value2))
+				return value1 + value2;
+			else
+				return value1;
+		}
+		else
+			return value2;
+	}
+	/** Subtracts value2 from value 1.  Considers infinite, unassigned etc. */
+	public static long subtract(long value1, long value2) {
+		if (value2 == negInfinite){
+			if (value1== negInfinite)
+				return 0;
+			else
+				return infinite;
+		}
+		else if (value2 == infinite){
+			if (value1== infinite)
+				return 0;
+			else
+				return negInfinite;
+		}
+		else if (value1 == infinite)
+			return infinite;
+		else if (value1 == negInfinite)
+			return negInfinite;
+		else if (isCombinable(value2)) {
+			if (isCombinable(value1))
+				return value1 - value2;
+			else
+				return -value2;
+		}
+		else
+			return value1;
+	}
+	/** Multiplies two longs.  Considers infinite, unassigned etc. */
+	public static long multiply(long value1, long value2) {
+		if (value1 == 0 || value2==0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return value1*value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite){
+					if (value1<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value2== negInfinite) {
+					if (value1<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				if (value1 == infinite){
+					if (value2<0)
+						return negInfinite;
+					else 
+						return infinite;
+				}
+				else if (value1== negInfinite) {
+					if (value2<0)
+						return infinite;
+					else 
+						return negInfinite;
+				}
+				else
+					return unassigned;
+			}
+			else { //neither combinable
+				if (value1 == infinite && value2 == infinite)
+					return infinite;
+				else if (value1 == infinite && value2 == negInfinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == infinite)
+					return negInfinite;
+				else if (value1 == negInfinite && value2 == negInfinite)
+					return infinite;
+				else 
+					return unassigned;
+			}
+		}
+		
+	}
+	/** Divides first long by second long.  Considers infinite, unassigned etc. */
+	public static double divide(long value1, long value2) {
+		if (value2==0)
+			return MesquiteDouble.infinite;
+		else if (value1 == 0)
+			return 0;
+		else if (isCombinable(value1)){
+			if (isCombinable(value2))
+				return ((double)value1)/value2;
+			else {  //value 2 not combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return MesquiteDouble.unassigned;
+			}
+		}
+		else {//value 1 not combinable
+			if (isCombinable(value2)){
+				return MesquiteDouble.unassigned;
+			}
+			else { //neither combinable
+				if (value2 == infinite || value2== negInfinite)
+					return 0;
+				else
+					return MesquiteDouble.unassigned;
+			}
+		}
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string version of this value.  Returns "unassigned" etc. if needed*/
+	public String toString() {
+		return toString(value);
+	}
+	
+	/** Returns string version of value.  Returns "unassigned" etc. if needed*/
+	public static String toString(long v) {
+		if (v==unassigned)
+			return "?";  //changed from "unassigned" June 02
+		else if (v==infinite)
+			return "infinite";
+		else if (v==negInfinite)
+			return "neg.infinite";  
+		else if (v==impossible)
+			return "impossible";  
+		else if (v==inapplicable)
+			return "inapplicable"; 
+		else {
+			try {
+				return Long.toString(v);
+			}
+			catch (NumberFormatException ne){
+				return "impossible";
+			}
+		}
+	}
+	/** Returns long parsed from given string.  Assumes entire string is what should be parsed. */
+	public static long fromString(String s) { 
+		return fromString(s, false);
+	}
+	/** Returns long parsed from given string; warns about NumberFormatException if boolean is true.
+	  Assumes entire string is what should be parsed. */
+	public static long fromString(String s, boolean warn) {
+		if (StringUtil.blank(s))
+			return impossible;
+		try {
+			return Long.parseLong(s);
+		}
+		catch (NumberFormatException e) {
+			if (s !=null) {
+				if (s.equalsIgnoreCase("unassigned") || s.equalsIgnoreCase("estimate") || s.equalsIgnoreCase("?"))
+					return unassigned;
+				else if (s.equalsIgnoreCase("infinite")|| s.equalsIgnoreCase("i"))
+					return infinite;
+				else if (s.equalsIgnoreCase("impossible"))
+					return impossible;
+				else if (s.equalsIgnoreCase("neg.Infinite"))
+					return negInfinite;
+				else if (s.equalsIgnoreCase("inapplicable"))
+					return inapplicable;
+			}
+			if (warn)
+				MesquiteMessage.println("NumberFormatException in parsing string \"" + s + "\"");
+			return impossible;
+		}
+	}
+	/** Returns long parsed from given string, starting at string position given.
+	Assumes only first token from pos is to be parsed. */
+	public static long fromString(String s, MesquiteInteger pos) {
+		String f =ParseUtil.getToken(s,pos); 
+		if ("-".equals(f))
+			return -fromString(ParseUtil.getToken(s,pos), false); 
+		else
+			return fromString(f, false); 
+	}
+	/** Returns long parsed from first token of given string, and sets value of pos
+	to character at end of this token. */
+	public static long fromFirstToken(String s, MesquiteInteger pos) {
+		pos.setValue(0);
+		return fromString(s,pos);
+	}
+	/** Returns whether a string can be interpreted as a long. */
+	public static boolean interpretableAsLong(String s,  MesquiteInteger pos) {
+		int oldPos = pos.getValue();
+		boolean interpretable = fromString(s, pos)!= impossible;
+		pos.setValue(oldPos);
+		return interpretable;
+	}	
+	/** Returns whether a string can be interpreted as a long. */
+	public static boolean interpretableAsLong(String s,  MesquiteInteger pos, int posToSet) {
+		int oldPos = pos.getValue();
+		if (posToSet >=0)
+			pos.setValue(posToSet);
+		boolean interpretable = fromString(s, pos)!= impossible;
+		pos.setValue(oldPos);
+		return interpretable;
+	}	
+	/** Presents dialog querying user for an longs, with no check for minimum and maximum */
+	public static long queryLong(MesquiteWindow parent, String title, String message, long current) {
+		MesquiteLong io = new MesquiteLong(current);
+		//IntegerDialog id = new IntegerDialog(parent, title, message, io);
+		//	id.dispose();
+		QueryDialogs.queryLong(parent, title, message, io);
+		return io.getValue();
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteMacro.java b/Source/mesquite/lib/MesquiteMacro.java
new file mode 100644
index 0000000..e3f11e7
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMacro.java
@@ -0,0 +1,193 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+
+/* ======================================================================== */
+/** Holds the name.*/
+
+public class MesquiteMacro implements Listable, Explainable {
+	String name;
+	String explanation;
+	String path; 
+	int preferredMenu =0;
+	
+	public final static int UNSPECIFIED = 0;
+	public final static int ANALYSIS = 1;
+
+	MesquiteModuleInfo moduleInfo;
+	boolean auto = false;
+	
+	public MesquiteMacro (String name, String explanation, String path, MesquiteModuleInfo mmi) {  
+		this.name = name; 
+ 		this.explanation =explanation;
+ 		this.path = path;
+		moduleInfo = mmi;
+	}
+	/** returns info for the owner module */
+	public MesquiteModuleInfo getModuleInfo() {
+		return moduleInfo;
+	}
+	/** sets preferred menu in which macro is to appear */
+	public void setPreferredMenu(int a) {
+		if (MesquiteInteger.isCombinable(a))
+			preferredMenu = a;
+	}
+	/** returns preferred menu in which macro is to appear */
+	public int getPreferredMenu() {
+		return preferredMenu;
+	}
+	/** sets whether macro was made by autosave */
+	public void setAutoSave(boolean a) {
+		auto = a;
+	}
+	/** returns whether macro was made by autosave */
+	public boolean isAutoSave() {
+		return auto;
+	}
+	/** returns name of macro */
+	public String getName() {
+		return name;
+	}
+	/** sets name of macro */
+	public void setName(String n) {
+		name = n;
+	}
+	/** sets explanation of macro */
+	public void setExplanation(String n) {
+		explanation = n;
+	}
+ 	/** returns an explanation of what the macro does*/
+ 	public String getExplanation() { 
+ 		if (moduleInfo==null)
+ 			return explanation;
+ 		else if (auto)
+ 			return explanation + "\n\nIt was built automatically at user request, to instruct the module \"" + moduleInfo.getNameForMenuItem() + "\"";
+ 		else 
+ 			return explanation + "\n\nInstructs module \"" + moduleInfo.getNameForMenuItem() + "\"";
+   	}
+ 	public String getRawExplanation() { 
+ 			return explanation;
+   	}
+ 	/** returns path*/
+ 	public String getPath() { 
+ 		return path;
+   	}
+ 	/** returns object that lists autosaved macros*/
+ 	public static StringLister getAutoSavedLister() { 
+ 		return new AutoSavedLister();
+   	}
+   	
+   	public static MesquiteMacro findMacro(String name){
+   		if (StringUtil.blank(name)) {
+   			return (MesquiteMacro)ListDialog.queryList(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Macro", "Select Macro", MesquiteString.helpString, new AutoSavedLister().getListables(), 0);
+   		}
+		for (int i = 0; i<MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.elementAt(i);
+			if (mmi.getMacros()!=null && mmi.getMacros().size()>0){
+				Vector mForM = mmi.getMacros();
+				for (int j = 0; j<mForM.size(); j++){
+					MesquiteMacro mmr = (MesquiteMacro)mForM.elementAt(j);
+					if (name.equals(mmr.getName()))
+						return mmr;
+				}
+			}
+		}
+		return null;
+   	}
+   	public static void saveMacro (MesquiteModule target, String defaultMacroName, int preferredMenu, String macroCommands){
+			MesquiteBoolean answer = new MesquiteBoolean(false);
+			MesquiteString name = new MesquiteString(defaultMacroName);
+			MesquiteString explanation = new MesquiteString("");
+			MesquiteString.queryTwoStrings(target.containerOfModule(), "Save Macro", "Name of macro (to appear as menu item)", "Explanation of macro",  answer, name, explanation,true);
+			if (!answer.getValue())
+				return;
+			if (StringUtil.blank(name.getValue()))
+				name.setValue(defaultMacroName);
+			if (StringUtil.blank(explanation.getValue()))
+				explanation.setValue("(no explanation supplied)");
+			String firstLine = "telling " +   target.getClass().getName()  + "  " + ParseUtil.tokenize(name.getValue()) + "   " +  ParseUtil.tokenize(explanation.getValue()) + "   " +  preferredMenu  + ";" + StringUtil.lineEnding();
+
+			String base = MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator +"macros";
+			if (!MesquiteFile.fileExists(base)) {
+				File f = new File(base);
+				f.mkdir();
+			}
+			String candidate = base + "/macro1";
+			int count = 2;
+			while (MesquiteFile.fileExists(candidate)){
+				candidate = base + "/macro" + (count++);
+			}
+			MesquiteModuleInfo mmi = target.getModuleInfo();
+			MesquiteMacro macro = new MesquiteMacro(name.getValue(), explanation.getValue(), candidate, mmi);
+			macro.setAutoSave(true);
+			macro.setPreferredMenu(preferredMenu);
+			MesquiteFile.putFileContents(candidate, firstLine + macroCommands, true); 
+			mmi.addMacro(macro);
+			if (target !=null) {
+				if (target.nameMatches("BasicTreeWindowMaker"))
+					target.alert("The macro saved may appear in Macros For Tree Window submenu of the Tree menu of the Tree Window or elsewhere, such as the Macros submenus of the Window or Analysis menu");
+				else
+					target.alert("The macro saved may appear in the Macros submenus of the Window or Analysis menus.");
+			}
+			MesquiteTrunk.mesquiteTrunk.resetAllMenuBars();
+   	 }
+
+}
+
+class AutoSavedLister implements StringLister{
+	/*.................................................................................................................*/
+	public String[] getStrings(){
+	
+		ListableVector macros = new ListableVector();
+		for (int i = 0; i<MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.elementAt(i);
+			if (mmi.getMacros()!=null && mmi.getMacros().size()>0){
+				Vector mForM = mmi.getMacros();
+				for (int j = 0; j<mForM.size(); j++){
+					MesquiteMacro mmr = (MesquiteMacro)mForM.elementAt(j);
+					if (mmr.isAutoSave())
+						macros.addElement(mmr, false);
+				}
+			}
+		}
+		if (macros.size() == 0)
+			return null;
+		return macros.getStrings();
+	}
+	/*.................................................................................................................*/
+	public ListableVector getListables(){
+	
+		ListableVector macros = new ListableVector();
+		for (int i = 0; i<MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteTrunk.mesquiteModulesInfoVector.elementAt(i);
+			if (mmi.getMacros()!=null && mmi.getMacros().size()>0){
+				Vector mForM = mmi.getMacros();
+				for (int j = 0; j<mForM.size(); j++){
+					MesquiteMacro mmr = (MesquiteMacro)mForM.elementAt(j);
+					if (mmr.isAutoSave())
+						macros.addElement(mmr, false);
+				}
+			}
+		}
+		if (macros.size() == 0)
+			return null;
+		return macros;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteMenu.java b/Source/mesquite/lib/MesquiteMenu.java
new file mode 100644
index 0000000..1fd6a9c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMenu.java
@@ -0,0 +1,216 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+
+/* ======================================================================== */
+/** A menu.*/
+public class MesquiteMenu extends Menu implements Commandable, Listable{
+	public static int totalSubmenus = 0;
+	public boolean recycle = false;
+	MesquiteMenuSpec spec;
+	//static MesquiteSubmenu[] menus = new MesquiteSubmenu[255];
+	long id = 0;
+	static long numInstances = 0;
+	String menuName;
+	int hiddenStatus = InterfaceManager.NORMAL;
+	Class dutyClass = null;
+	boolean hideable = false;
+	protected boolean filterable = true;
+	public MesquiteMenu(MesquiteMenuSpec spec) {
+		super(spec.getLabel(), true);  // true to designate as tearoff; doesn't seem to work on macos
+		id = numInstances++;
+		filterable = spec.isFilterable();
+		if (spec.getLabel() == null) {
+			MesquiteMessage.println("menu with no name: ");
+			setEnabled(false);
+		}
+		menuName = spec.getLabel();
+		if (!spec.isEnabled())
+			setEnabled(false);
+		this.spec = spec;
+	}
+	public MesquiteMenu(String label) {
+		super(label, true);  // true to designate as tearoff; doesn't seem to work on macos
+		id = numInstances++;
+		if (label == null) {
+			MesquiteMessage.println("menu with no name: ");
+			setEnabled(false);
+		}
+		menuName = label;
+		this.spec = null;
+	}
+	public boolean isFilterable(){
+		return filterable;
+		//return filterable;
+	}
+	public void setHideable(boolean h){
+		hideable = h;
+	}
+	public void resetLabel(){
+		if (true)
+			return;
+		if (InterfaceManager.isEditingMode()){
+			if (!hideable || !filterable)
+				setLabel("(*) " + menuName);
+			else if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+				setLabel("(OFF) " + menuName);
+			else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+				setLabel("(PACKAGE OFF) " + menuName);
+			else
+				setLabel("" + menuName);
+		}
+		else
+			setLabel(menuName);
+	}
+	public void setHiddenStatus(int hiddenStatus){
+		setHiddenStatus(hiddenStatus, null);
+	}
+	public void setHiddenStatus(int hiddenStatus, Class dutyClass){
+		if (!hideable || !filterable){
+			if (InterfaceManager.isEditingMode())
+				setLabel("(*) " + menuName);
+			else
+				setLabel(menuName);
+			return;
+		}
+		hideable = true;
+		this.hiddenStatus = hiddenStatus;
+		if (dutyClass != null)
+			this.dutyClass = dutyClass;
+		if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+			setLabel("(OFF) " + menuName);
+		else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+			setLabel("(PACKAGE OFF) " + menuName);
+		else
+			setLabel("" + menuName);
+	}
+	public MesquiteMenuSpec getSpecification(){
+		return spec;
+	}
+	public static MesquiteMenu getMenu(MesquiteMenuSpec spec) {
+
+		return new MesquiteMenu(spec);
+	}
+	public long getID(){
+		return id;
+	}
+	public String getName(){
+		if (this instanceof MesquiteSubmenu)
+			return "Submenu: " + getLabel();
+		else
+			return "Menu: " + getLabel();
+	}
+	public void listItems(){
+		String output = "";
+		if (this instanceof MesquiteSubmenu)
+			output += ("  Submenu: " + this.getLabel() +"\n");
+		else
+			output += ("  Menu: " + this.getLabel() +"\n");
+		for (int j = 0; j<this.getItemCount(); j++) {
+			if (!("-".equals(this.getItem(j).getLabel()))){
+				output += ("      " + (j+1) + "  --  " + this.getItem(j).getLabel());
+				if(this.getItem(j) instanceof Menu)
+					output += " >";
+				output += "\n";
+			}
+		}
+		System.out.println(output);
+		System.out.println("Enter number to select item");
+	}
+	/*.................................................................................................................*/
+	/** A request for the object to perform a command.  It is passed two strings, the name of the command and the arguments.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(getClass(), null, null, commandName, "show")) {
+			listItems();
+		}
+		else {
+			MesquiteInteger pos = new MesquiteInteger();
+			int im = MesquiteInteger.fromFirstToken(commandName, pos);
+			if (MesquiteInteger.isCombinable(im)){
+				im--;
+				if (im >=0 && im<getItemCount()){
+					MenuItem item = getItem(im);
+					if (item instanceof MesquiteMenu){
+						System.out.println(((MesquiteMenu)item).getName() + " selected");
+						((MesquiteMenu)item).listItems();
+						ConsoleThread.setConsoleObjectCommanded(item, true, false);
+					}
+					else if (item instanceof MesquiteMenuItem){
+						if (this instanceof MesquiteSubmenu && ((MesquiteSubmenu)this).getCommand()!= null){
+							System.out.println("Item " + (im+1) + " selected");
+							((MesquiteSubmenu)this).chooseItem(im);
+						}
+						else  {
+							System.out.println(((MesquiteMenuItem)item).getLabel() + " selected");
+							((MesquiteMenuItem)item).chooseItem(arguments);  
+						}
+					}
+				}
+			}
+		}
+		return null;
+
+	}
+	boolean itemWithSameLabelExists(String label){
+		for (int i=0; i<getItemCount(); i++)
+			if (getItem(i).getLabel().equals(label))
+				return true;
+		return false;
+	}
+	static boolean itemWithSameLabelExists(Menu menu, String label){
+		if (menu == null)
+			return false;
+		for (int i=0; i<menu.getItemCount(); i++)
+			if (menu.getItem(i).getLabel().equals(label))
+				return true;
+		return false;
+	}
+
+	public MenuItem add(MenuItem mmi) {
+		if (mmi==null)
+			return null;
+		if (mmi instanceof Menu)
+			totalSubmenus++;
+		if (!isFilterable()) {
+			if (mmi instanceof MesquiteMenuItem){
+				((MesquiteMenuItem)mmi).setHideable(false);
+				((MesquiteMenuItem)mmi).resetLabel();
+			}
+			else if (mmi instanceof MesquiteCheckMenuItem){
+				((MesquiteCheckMenuItem)mmi).setHideable(false);
+				((MesquiteCheckMenuItem)mmi).resetLabel();
+			}
+			else if (mmi instanceof MesquiteSubmenu){
+				((MesquiteSubmenu)mmi).setHideable(false);
+				((MesquiteSubmenu)mmi).resetLabel();
+			}
+
+		}
+		return super.add(mmi);
+	}
+	public static void add(Menu menu, MenuItem mmi) {
+		if (mmi==null  || menu == null)
+			return;
+
+		menu.add(mmi);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteMenuBar.java b/Source/mesquite/lib/MesquiteMenuBar.java
new file mode 100644
index 0000000..a030f1e
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMenuBar.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+/** A menu bar attached to a window.*/
+public class MesquiteMenuBar extends MenuBar {
+	MesquiteWindow ownerWindow;
+	public static long totalCreated = 0;
+	public MesquiteMenuBar(MesquiteWindow ownerWindow){
+		super();
+		this.ownerWindow=ownerWindow;
+		totalCreated++;
+	}
+	
+	public MesquiteWindow getOwnerWindow(){
+		return ownerWindow;
+	}
+	boolean menuWithSameLabelExists(String label){
+		for (int i=0; i<getMenuCount(); i++)
+			if (getMenu(i).getLabel().equals(label))
+				return true;
+		return false;
+	}
+	public Menu add(Menu menu) {
+		if (menu==null)
+			return null;
+		while (menuWithSameLabelExists(menu.getLabel()))
+			menu.setLabel(menu.getLabel()+".");
+		return super.add(menu);
+	}
+	public void disconnect() {
+		ownerWindow = null;
+	/*
+		for (int i=0; i<getMenuCount(); i++){
+			Menu menu = getMenu(i);
+			if (menu instanceof MesquiteMenu)
+				((MesquiteMenu)menu).recycle = true; //setting recycle flag so can be recycled
+			for (int j=0; j<menu.getItemCount(); j++) {
+				MenuItem item = menu.getItem(i);
+				if (item instanceof MesquiteMenu)
+					((MesquiteMenu)item).recycle = true; //setting recycle flag so can be recycled
+			}
+		}
+		for (int i=getMenuCount()-1; i>=0; i--){
+			Menu menu = getMenu(i);
+			menu.removeAll();
+			remove(menu);
+		}
+	//	removeAll();
+	*/
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteMenuItem.java b/Source/mesquite/lib/MesquiteMenuItem.java
new file mode 100644
index 0000000..a190e86
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMenuItem.java
@@ -0,0 +1,265 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+
+/* ======================================================================== */
+/**A menu item.  Note that a command must be associated with each menu item.
+Each menu item belongs to a MesquiteModule.*/
+
+public class MesquiteMenuItem extends MenuItem implements ActionListener{
+	public static long totalCreated = 0;//to catch memory leaks
+	public static long totalDisposed =0;//to catch memory leaks
+	public static long totalFinalized =0;//to catch memory leaks
+	MesquiteCommand command; 
+	private String itemName;
+	private String argument;
+	boolean disconnectable = true;
+	boolean document = true;
+	private long ownerModuleID =0;
+	private Listable[] others;
+	private MesquiteMenuItemSpec specification;
+	int hiddenStatus = InterfaceManager.NORMAL;
+	boolean hiddenStatusSet = false;
+	boolean hideable = true;
+	Class dutyClass = null;
+	
+
+	public MesquiteMenuItem(String itemName, MesquiteModule ownerModule, MesquiteCommand command) {
+		super();
+		addActionListener(this);
+		if (itemName == null) {
+			MesquiteMessage.printStackTrace("Menu item with null name: ownerModule " + ownerModule);
+			this.setLabel("untitled");
+		}
+		else
+			this.setLabel(itemName);
+		this.itemName = itemName;
+		this.command = command;
+		if (ownerModule!=null)
+			this.ownerModuleID = ownerModule.getID();
+		if (itemName == null) {
+			MesquiteMessage.println("menu item with no name: ");
+			setEnabled(false);
+		}
+		if (command==null) {
+			setDocument(false);
+			setEnabled(false);
+		}
+		totalCreated++;
+	}
+
+
+	public MesquiteMenuItem(String itemName, MesquiteModule ownerModule, MesquiteCommand command, String argument) {
+		this( itemName,  ownerModule,  command);
+		this.argument = argument;
+		//totalCreated++;
+	}
+
+	//This is constructor used to make menu from specs
+	public MesquiteMenuItem(MesquiteMenuItemSpec specification) {
+		super();
+		addActionListener(this);
+		this.specification = specification;
+		if (specification.itemName == null) {
+			MesquiteMessage.println("Menu item with null name: specification " + specification);
+			MesquiteCommand c = specification.getCommand();
+			if (c!=null) {
+				MesquiteMessage.println("      -- command " + c.getName() + " to " + c.getOwner());
+			}
+
+			this.setLabel("untitled");
+		}
+		else
+			this.setLabel(specification.itemName);
+		if (specification.shortcut!=null)
+			setShortcut(new MenuShortcut(specification.shortcut.getValue(), specification.shortcutNeedsShift));
+		if (!specification.isEnabled())
+			setEnabled(false);
+		this.itemName = specification.itemName;
+		this.ownerModuleID = specification.getOwnerModuleID();
+		this.argument = specification.argument;
+		this.command = specification.command;
+		if (command==null) {
+			setDocument(false);
+			setEnabled(false);
+		}
+		//	addActionListener(this);
+		totalCreated++;
+	}
+	public MesquiteMenuItemSpec getSpecification(){
+		return specification;
+	}
+	public void setHiddenStatus(int hiddenStatus){
+		setHiddenStatus(hiddenStatus, null);
+	}
+	public void setHideable(boolean h ){
+		hideable = h;
+	}
+	public void resetLabel(){
+		if (InterfaceManager.isEditingMode()){
+			if (!hideable)
+				setLabel("(*) " + itemName);
+			else if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+				setLabel("(OFF) " + itemName);
+			else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+				setLabel("(PACKAGE OFF) " + itemName);
+			else
+				setLabel("" + itemName);
+		}
+		else
+			setLabel(itemName);
+	}
+	public void setHiddenStatus(int hiddenStatus, Class dutyClass){
+		if (!hideable){
+			if (InterfaceManager.isEditingMode())
+				setLabel("(*) " + itemName);
+			else
+				setLabel(itemName);
+			return;
+		}
+		hiddenStatusSet = true;
+		this.hiddenStatus = hiddenStatus;
+		if (dutyClass != null)
+			this.dutyClass = dutyClass;
+		if (hiddenStatus == InterfaceManager.TOBEHIDDEN)
+			setLabel("(OFF) " + itemName);
+		else if (hiddenStatus == InterfaceManager.HIDDENCLASS)
+			setLabel("(PACKAGE OFF) " + itemName);
+		else
+			setLabel("" + itemName);
+	}
+	public void resetEnable() {
+		if (specification != null)
+			setEnabled(specification.isEnabled());
+	}
+	public Listable[] getOthers(){
+		return others;
+	}
+	public void setOthers(Listable[] o){
+		others = o;
+	}
+	public long getOwnerModuleID(){
+		return ownerModuleID;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+	public boolean getDocument(){
+		return document;
+	}
+	/** this returns MesquiteMenuItem instead of void for reasons of historical intertia*/
+	public MesquiteMenuItem setDocument(boolean document){
+		this.document = document;
+		return this;
+	}
+
+	Object referent = null;
+	public void setReferent(Object referent){
+		this.referent = referent;
+	}
+	public Object getReferent(){
+		return referent;
+	}
+	public void disconnect(){
+		if (disconnectable){
+			command = null;
+			totalDisposed++;
+		}
+	}
+	Journal j =null;
+
+	public void actionPerformed(ActionEvent e) {
+		//Event queue
+		if (command==null)
+			return ;//true;
+		if (hideable && hiddenStatusSet && InterfaceManager.isEditingMode()){
+			if (hiddenStatus == InterfaceManager.NORMAL){
+				InterfaceManager.addMenuItemToHidden(itemName, argument, command, dutyClass, true);
+				setHiddenStatus(InterfaceManager.TOBEHIDDEN);
+				MesquiteTrunk.resetAllMenuBars();
+			}
+			else if (hiddenStatus != InterfaceManager.HIDDENCLASS) {
+				InterfaceManager.removeMenuItemFromHidden(itemName, argument, command, dutyClass, true);
+				setHiddenStatus(InterfaceManager.NORMAL);
+				MesquiteTrunk.resetAllMenuBars();
+			}
+		}
+		else	if ((e.getModifiers() & ActionEvent.ALT_MASK)!=0) {
+			String s = "Menu item \"" + getLabel() + "\"";
+			if (getParent() instanceof MesquiteSubmenu && ((MesquiteSubmenu)getParent()).getDutyClass() != null)
+				s += " (duty class: " + ((MesquiteSubmenu)getParent()).getDutyClass().getName() + ")";
+			if (getParent() instanceof MesquiteSubmenu && ((MesquiteSubmenu)getParent()).getFilter() != null)
+				s += " (filter: " + ((MesquiteSubmenu)getParent()).getFilter().getName() + ")";
+
+			MesquiteWindow.respondToQueryMode(s, command, this);
+		}
+		else {
+			int mod = e.getModifiers();
+			if (mod != 0)
+				chooseItem(argument  + " " + MesquiteEvent.modifiersToString(mod));
+			else
+				chooseItem(argument); 
+		}
+	}
+
+	public void chooseItem() {
+		chooseItem(argument);
+	}
+	public void chooseItem(String arg) {
+		if (command == null || MesquiteTrunk.suppressMenuResponse)
+			return;
+		if (!command.bypassQueue && MesquiteDialog.currentWizard != null){
+			MesquiteTrunk.mesquiteTrunk.alert("Please complete the questions of the Wizard dialog before selecting menu items");
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (others!=null) {
+			//MesquiteTrunk.mesquiteTrunk.alert(StringArray.toString(others));
+			MesquiteInteger io = new MesquiteInteger(0);
+			MenuContainer cont = getParent();
+			String intro = "C";
+
+			if (cont instanceof MenuItem) {
+				String n = ((MenuItem)cont).getLabel();
+				if (n != null)
+					intro ="For " + n + ", c";
+			}
+			ListDialog id = new ListDialog(MesquiteWindow.windowOfItem(this), "Select", intro + "hoose one of the following", true, MesquiteString.helpString,others, io, null,true, false);
+			id.setVisible(true);
+			id.dispose();
+			if (io.isCombinable()) {
+				if (argument == null)
+					argument = "";
+				command.doItMainThread(argument + ParseUtil.tokenize(others[io.getValue()].getName()), CommandChecker.getQueryModeString("Menu item", command, this), this, MesquiteDialog.useWizards);  // command invoked
+			}
+		}
+		else if (argument != null)
+			command.doItMainThread(arg, CommandChecker.getQueryModeString("Menu item", command, this), this, MesquiteDialog.useWizards);  // command invoked
+		else
+			command.doItMainThread("", CommandChecker.getQueryModeString("Menu item", command, this), this, MesquiteDialog.useWizards);  // command invoked
+	}
+	public void finalize() throws Throwable{
+		totalFinalized++;
+		super.finalize();
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteMenuItemSpec.java b/Source/mesquite/lib/MesquiteMenuItemSpec.java
new file mode 100644
index 0000000..4be639d
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMenuItemSpec.java
@@ -0,0 +1,214 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** Specifications to later make menu items.*/
+
+public class MesquiteMenuItemSpec implements Listable {
+	public MesquiteCommand command;
+	private MesquiteModule ownerModule;
+	protected String itemName;
+	protected String referentID;
+	protected MesquiteMenuSpec whichMenu;
+	protected String argument = null;
+	protected MesquiteSubmenuSpec submenu;
+	protected Class dutyClass = null;
+	protected Object compatibilityRestriction = null;
+	protected ListableVector lVector = null;
+	protected Class subclassFilter = null;
+	Class ownerClass = null;
+	protected StringLister stringLister;
+	protected MesquiteInteger shortcut = null;
+	protected boolean shortcutNeedsShift = false;
+	private int zone = 3; //to indicate what zone in menu to place; rarely used except Analysis menu
+	private boolean enabled = true;
+	long ownerID = 0;
+	boolean document = true;
+	public static final int MAXZONE = 7;
+	public static CommandChecker checkerMMI = null;
+	public static int totalCreated = 0; //to catch memory leaks
+	public static int totalDisposed = 0;//to catch memory leaks
+	public static int totalFinalized = 0;//to catch memory leaks
+	//This is constructor used, e.g. when submenu of candidate employees not requested
+	public MesquiteMenuItemSpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule, MesquiteCommand command) {
+		this.whichMenu = whichMenu;
+		this.itemName = itemName;
+		if (ownerModule!=null){
+			ownerID  = ownerModule.getID();
+			ownerClass = 	ownerModule.getClass();
+	}
+		this.command = command;
+		totalCreated++;
+	}
+	public MesquiteSubmenuSpec submenuIn() {
+		return submenu;
+	}
+	public static MesquiteMenuItemSpec getMMISpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule, MesquiteCommand command){
+		if (checkerMMI!=null) {
+			checkerMMI.registerMenuItem(ownerModule, itemName, command);
+			return null;
+		}
+		else {
+			ownerModule.checkMISVector();
+			MesquiteMenuItemSpec mmis = new MesquiteMenuItemSpec(whichMenu, itemName, ownerModule, command);
+			ownerModule.getMenuItemSpecs().addElement(mmis, false);
+			return mmis;
+		}
+	}
+	public void setZone(int zone){
+		if (zone > MAXZONE)
+			zone = MAXZONE;
+		this.zone = zone;
+	}
+	public int getZone(){
+		return zone;
+	}
+	public void setEnabled(boolean enabled){
+		this.enabled = enabled;
+	}
+	public boolean isEnabled(){
+		return enabled;
+	}
+	public Class getOwnerClass(){
+		return ownerClass;
+	}
+	public long getOwnerModuleID(){
+		return ownerID;
+	}
+	public void setOwnerModuleID(long id){
+		ownerID = id;
+	}
+	public String getName(){
+		return getCurrentItemName();
+	}
+	NameHolder nameHolder;
+	public void setNameHolder(NameHolder nH){
+		nameHolder = nH;
+	}
+	public String getCurrentItemName(){  //used if external holder wants control of menu item's name
+		if (nameHolder != null){
+			String s = nameHolder.getMyName(this);
+			if (s != null)
+				return s;
+		}
+		return itemName;
+	}
+	public void setName(String name){
+		 itemName = name;
+	}
+	public void setReferentID(String name){
+		 referentID = name;
+	}
+	public String getReferentID(){
+		 return referentID;
+	}
+	public void disconnect(){
+		//if (command!=null && command.getOwner()==ownerModule) //MEMORY shouldn't adways set null
+		//	command.setOwner(null);
+		if (command!=null)
+			command.dispose();
+		command = null;
+		ownerModule =null;
+		whichMenu =null;
+		lVector = null;
+		stringLister = null;
+		submenu = null;
+		totalDisposed++;
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	public void setInSubmenu(MesquiteSubmenuSpec submenu){
+		this.submenu = submenu;
+	}
+	public void setInMenu(MesquiteMenuSpec menu){
+		this.whichMenu = menu;
+	}
+	public void setArgument(String argument){
+		this.argument = argument;
+	}
+	public String getArgument(){
+		return argument;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+	public void setCommand(MesquiteCommand command){
+		this.command = command;
+	}
+	
+	public void setList(Class dutyClass){
+		this.dutyClass = dutyClass;
+	}
+	public void setList(ListableVector lVector){
+		this.lVector = lVector;
+	}
+	public void setList(StringLister s){
+		this.stringLister = s;
+	}
+	
+	public ListableVector getListableVector(){
+		return lVector;
+	}
+	public Class getDutyClass(){
+		return dutyClass;
+	}
+	public void setShortcut(int shortcut){
+		this.shortcut = new MesquiteInteger(shortcut);
+	}
+	public MesquiteInteger getShortcut(){
+		return shortcut;
+	}
+	public void setShortcutNeedsShift(boolean needs){
+		shortcutNeedsShift = needs;
+	}
+	public boolean getShortcutNeedsShift(){
+		return shortcutNeedsShift;
+	}
+	public String[] getStrings(){
+		if (stringLister==null) {
+			return null;
+		}
+		else
+			return stringLister.getStrings();
+	}
+	public Object getCompatibilityCheck(){
+		return compatibilityRestriction;
+	}
+	public void setCompatibilityCheck(Object obj){
+		this.compatibilityRestriction = obj;
+	}
+	public Class getListableFilter(){
+		return subclassFilter;
+	}
+	public void setListableFilter(Class subclassFilter){ //THIS should 
+		this.subclassFilter = subclassFilter;
+	}
+	public void setDocumentItems(boolean document){
+		this.document = document;
+	}
+	public boolean getDocumentItems(){
+		return document;
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/MesquiteMenuSpec.java b/Source/mesquite/lib/MesquiteMenuSpec.java
new file mode 100644
index 0000000..484ce7c
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMenuSpec.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/** Specifications to later make a menu.*/
+public class MesquiteMenuSpec extends MesquiteMenuItemSpec { 
+	String label;
+	Vector guests;
+	boolean universalMenu;
+	public MesquiteMenuSpec(MesquiteMenuSpec whichMenu, String menuName,  MesquiteModule ownerModule, boolean universalMenu) {
+		super(whichMenu, menuName, ownerModule, null);
+		this.label = menuName; 
+		this.universalMenu = universalMenu;
+	}
+	public MesquiteMenuSpec(MesquiteMenuSpec whichMenu, String menuName,  MesquiteModule ownerModule) {
+		super(whichMenu, menuName, ownerModule, null);
+		this.label = menuName; 
+	}
+	boolean filterable = true;
+	public boolean isFilterable() {
+		return filterable;
+	}
+	public void setFilterable(boolean f) {
+		filterable = f;
+	}
+
+	public String getLabel() {
+		return label;
+	}
+	public boolean isUniversalMenu() {
+		return universalMenu;
+	}
+	public void addGuestModule(MesquiteModule mb) {
+		if (mb == null)
+			return;
+		if (guests == null)
+			guests = new Vector();
+		guests.addElement(mb);
+	}
+	public void removeGuestModule(MesquiteModule mb) {
+		if (mb == null || guests == null)
+			return;
+		guests.removeElement(mb);
+	}
+	public boolean isGuestModule(MesquiteModule mb) {
+		if (mb == null || guests == null)
+			return false;
+		return guests.indexOf(mb) >=0;
+	}
+	public Vector getGuests() {
+		return guests;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteMessage.java b/Source/mesquite/lib/MesquiteMessage.java
new file mode 100644
index 0000000..02f5f2f
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteMessage.java
@@ -0,0 +1,90 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+ import java.util.*;
+ 
+/*=======================*/
+/** A utility class with method to duplicate System.out.println, or to generate user alerts.
+These methods currently all call System.out.println, but will be differentiable in the future (e.g., some warnings will
+go only to the console, while others will bring up dialog boxes).*/
+public class MesquiteMessage extends Debugg {
+	
+	public static void warnProgrammer(String s) {
+		MesquiteThread.suspendThreadLogging();
+		MesquiteModule.showLogWindow(true);
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			MesquiteTrunk.mesquiteTrunk.logln(s);
+		else
+			System.out.println(s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void notifyProgrammer(String s) {
+		MesquiteThread.suspendThreadLogging();
+		MesquiteModule.showLogWindow(true);
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			MesquiteTrunk.mesquiteTrunk.logln(s);
+		else
+			System.out.println(s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void warnUser(String s) {
+		MesquiteThread.suspendThreadLogging();
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			MesquiteTrunk.mesquiteTrunk.logln(s);
+		else
+			System.out.println(s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void discreetNotifyUser( String s) {
+		MesquiteThread.suspendThreadLogging();
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			MesquiteTrunk.mesquiteTrunk.discreetAlert( s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void notifyUser(String s) {
+		MesquiteThread.suspendThreadLogging();
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			AlertDialog.notice(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Notice", s);
+		MesquiteThread.resumeThreadLogging();
+	}
+	public static void beep() {
+           try {
+        	   if (MesquiteWindow.GUIavailable)
+        	   java.awt.Toolkit.getDefaultToolkit().beep();
+           }
+        	   catch(Throwable e){
+        	   }
+	}
+	
+	
+	public static void logCurrentTime(String message) {
+		MesquiteThread.suspendThreadLogging();
+		String s = getCurrentTime();
+		if (MesquiteTrunk.mesquiteTrunk !=null)
+			MesquiteTrunk.mesquiteTrunk.logln(message + " " + s);
+		else
+			System.out.println(message + " " + s);
+		MesquiteThread.resumeThreadLogging();
+		
+	}
+	public static String getCurrentTime() {
+		Date dnow = new Date(System.currentTimeMillis());
+		return dnow.toString();
+	}
+	
+	
+	
+}
+
diff --git a/Source/mesquite/lib/MesquiteModule.java b/Source/mesquite/lib/MesquiteModule.java
new file mode 100644
index 0000000..8abd5d1
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteModule.java
@@ -0,0 +1,2696 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.lang.StringEscapeUtils;
+
+import mesquite.lib.duties.*;
+import mesquite.tol.lib.BaseHttpRequestMaker;
+import edu.stanford.ejalbert.*;  //for Browserlauncher
+
+
+
+/* ============================Class MesquiteModule============================================ */
+/** The Mesquite system operates around a tree of modules (subclasses of MesquiteModule), with the class containing the "main" method being
+the <strong>trunk</strong> module, and the other modules like branches that are attached to the trunk.<p>
+
+When Mesquite starts up, the trunk starts up and surveys the mesquite folder to acquire information about all of the available modules
+(i.e., all of the available subclasses of MesquiteModule). To be found, a module must be in a folder (directory) of the same name as itself; that is,
+a module whose class file is "MyModule.class" must be in a directory named "MyModule".  Mesquite remembers the modules in a vector of MesquiteModuleInfo objects.  
+Later, when modules need to be "hired" to perform certain tasks, this vector of information can be used to help choose which module to hire.  To be hired, a module is instantiated
+and linked to its employer module.  Thus, a new branch sprouts in the Mesquite bureaucratic hierarchy. 
+<p>
+
+Modules are chosen for hire by other modules according to their talents.  What talents a module has is implicit in its superclass.  For instance, a module
+that subclasses the NumberForTree class (itself a subclass of MesquiteModule) calculates a number for a tree.  Any module that
+wants numbers calculated for trees can therefore hire a module that is an instance of the NumberForTree class. 
+The basic talent-defining classes are part of the Mesquite Class LIbrary, in the subpackage duties.  There is in addition a system to determine whether a
+module is compatible with a particular condition (e.g. operating on continuous-valued data.)<p>
+
+The only types of module that the trunk knows of directly are the FileCoordinator and FileInterpreter classes.  Each instance
+of the File Coordinator is associated with one file, and it is responsible for using employee modules to
+read and write the file, and to hire tree windows and data windows.  The trunk is a specific subclass of MesquiteModule,
+a MesquiteTrunk<p>  
+
+Because menus are composed hierarchically along the employee tree,  menu composition is most easily done where there is easy access to
+employee-employer relations.  For this reason, it is most convenient to have the menu composition embedded within the module code.  In order not to
+burden the MesquiteModule class with numerous methods to handle employee-employer relations, the MesquiteModule class was split into three: its superclass,
+EmployeeEmployer (which handles employee-employer relations), MenuOwner (which handles all menu issues) and MesquiteModule itself, which handles its basic functions.
+EmployeeEmployer and MenuOwner are intended to be used ONLY as superclasses to MesquiteModule<p>
+
+The MesquiteModule class is more or less equivalent to the MacClade proto4 ModuleRecord, while its instantiated objects
+are more or less equivalent to the MacClade proto4 Tasks.  Hence, "task" is sometimes used in names for
+MesquiteModule objects.<p>
+ */
+
+
+public abstract class MesquiteModule extends EmployerEmployee implements Commandable, Showable, Logger, FunctionExplainable,  Identifiable, FileDirtier, MesquiteListener, XMLPreferencesProcessor {
+	/*.................................................................................................................*/
+	/** returns build date of the Mesquite system (e.g., "22 September 2003") */
+	public final static String getBuildDate() {
+		return "16 August 2015";
+	}
+	/*.................................................................................................................*/
+	/** returns version of the Mesquite system */
+	public final static String getMesquiteVersion() {
+		return "3.04";
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	//As of 3.0 this becomes fixed, not changing with version)
+	public static String errorReportURL =  "http://mesquiteproject.org/pyMesquiteFeedback";
+	/*.................................................................................................................*/
+	/** returns letter in the build number of the Mesquite system (e.g., "e" of "e58") */
+	public final static String getBuildLetter() {
+		//see comment under getBuildNumber
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** returns number in the build number of the Mesquite system (e.g., 58 of "e58") */
+	public final static int getBuildNumber() {
+		//as of 26 Dec 08, build naming changed from letter + number to just number.  Accordingly j105 became 473, based on
+		// highest build numbers of d51+e81+g97+h66+i69+j105 + 3 for a, b, c
+		return 	725;  
+	}
+	//0.95.80    14 Mar 01 - first beta release 
+	//0.96  2 April 01 beta  - second beta release
+	//0.97 30 May 01 - not a release version
+	//0.98  24 July 01 0.98
+	//0.99   released 21 Aug 02   hits at posting: 12860 home page; 3251 download; 466 source
+	//0.991 = d21   released 14 Sep 02    hits at posting: 13599 home page; 3460 download; 502 source
+	//0.992 = d24   released 27 Sep 02    approximate hits at posting: 14171 home page; 3590 download; 525 source
+	//0.993 = d42   released 10 Jan 03    approximate hits at posting: 16122 home page; 4458 download; 671 source
+	//0.994 = d51   released 7 Feb 03    approximate hits at posting: 16790 home page; 4831 download; 720 source
+	//0.995 = e23   released 21 May 03    approximate hits at posting: 19389 home page; 6088 download; 898 source
+	//0.996 = e30   released 21 June 03     approximate hits at posting: 20028 home page; 6349 download; 958 source
+	//1.0 = e58   released 22 September 03    approximate hits at posting: 21315 home page; 6880 download; 1087 source
+	//1.01 = e80   released 14 January 04    approximate hits at posting: 25636 home page; 8753 download; 1359 source
+	//        = e81   released 17 January 04    minor change to MesquiteTable to prevent problem with autoSizeColumns under Windows
+	//1.02 = g6  released 6 May 04      approximate hits at posting: 28719 home page; 10170 download; 1574 source
+	//        = g7 released 12 May 04  minor change to fix cosmetic bug
+	//1.03 = g19 released 1 July 04      approximate hits at posting: 30058 home page; 10803 download; 1685 source
+	//1.04 = g21 released 1 September 04      approximate hits at posting: 31636 home page; 11462 download; 1806 source
+	//1.05 = g24 released 29 September 04      approximate hits at posting: 32502 home page; 11827 download; 1864 source
+	//1.06 = g97 released 30 August 05      approximate hits at posting: 44106 home page; 16865 download; 2478 source
+	//1.1 = h60 released 18 May 06      approximate hits at posting: 56303 home page; 22012 download; 3168 source
+	//24may just before evoldir announcement 56781/22266/3209
+	//1.11 = h64 released  21 June 06    approximate hits 58671/ 23167/3319
+	//1.12 = h66 released 23 September 06
+	//2.0 = i68 released 21 September 07  80089 / 31816 / 4666; i69 released 24 Sept to fix java 1.4 ExtensibleDialog setCaretPosition crash
+	//2.01 = j27 released 7 December 07 85399/ 34315 / 4910; j28 released 7 December 07 to fix coalescence counting bug
+	//2.5 = j77 released 9 June 08  95129/ 38754 / 5526
+	//2.6 = 486 released 24 January 09  107577/ 45169 / 6123
+	//2.7 = 510 released 26 August 09  121070/ 52820 / 6830
+	//2.71 = 514 released 7 Sept 09  121886/ 53466 / 6867
+	//2.72 = 527 released 11 Dec 09  129448/ 58128 / 7207;  528 released 20 Dec 09 to fix non-substantive bugs
+	//2.73 = 544 released 25 July 10  144981 / 67206 / 7817
+	//2.74 = 550 released 3 October 10  150117 / 71997 / 7980
+	//2.75 = 564 released 30 September 2011  179839 / 91129 / 8939
+	//       = 565 included 4 October 2011  in Chromaseq release; slight changes to UndoInstructions for Chromaseq
+	//       = 566 update 10 October 2011, small fix in this module to re-enable error reporting of NullPointerExceptions and ArrayIndexOutOfBoundsExceptions
+	//3.00  = 644 released 29 Aug 2014; 645 released 4 Sept 2014
+	//3.01  = 658 released 19 Sep 2014
+	//3.02  = 681 released 6 January 2015
+	//3.03  = 702 released 31 March 2015
+	//3.04  = 725 released 16 August 2015
+	/*.................................................................................................................*/
+	/** returns a string if this is a special version of Mesquite */
+	public final static String getSpecialVersion() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public final static String getBuildVersion() {
+		return " (build " + getBuildLetter() + getBuildNumber() + ")";
+	}
+	/*.................................................................................................................*/
+
+
+	LeakFinder leakFinder = MesquiteTrunk.leakFinderObject;
+	/** Static storage so that everyone can find the trunk MesquiteModule object*/
+	public static MesquiteTrunk mesquiteTrunk; 
+	/** The root of the mesquite classpath.*/
+	public static File mesquiteDirectory=null;  
+	/** The root of the mesquite classpath.*/
+	public static String mesquiteDirectoryPath=null;  
+	/** The directory that includes all the preference files.*/
+	public static File prefsDirectory=null;  
+
+	/** The user's directory.*/
+	public static File userDirectory=null;  
+	/** The window, created by mesquiteTrunk, that displays the log.*/
+	public static LogWindow logWindow;
+	/** true if name of MesquiteModule is to be shown in alerts*/
+	private static final boolean showModuleInAlert = true;
+	/** true if name of MesquiteModule is to be shown in log entries*/
+	private static final boolean showModuleInLog = false;
+	/** true if alerts should show a dialog, or merely write to log.*/
+	private static final boolean alertUseDialog = true;
+	/** the file path to the web browser for showing web pages*/
+	protected static String browserString = null;	
+	/** true if does extra check for module compatibility at startup.*/
+	public static boolean checkMethodsAtStartup = false;
+
+	public static final int NEXTRELEASE = Integer.MAX_VALUE;
+
+	/** this is for modules to store their last MesquiteNumber result for later use; intended for NumberForItem subclasses */
+	protected  Object lastResult;
+	/** this is for modules to store their last result string for later use; intended for NumberForItem subclasses */
+	protected  String lastResultString; 
+
+
+	/** The default author for this machine and user account */
+	public static Author author = new Author();
+
+	/** This module was hired as a default choice in scripting*/
+	public boolean hiredAsDefaultInScripting = false;
+	//
+	/** Has module requested enabling of macro auto-save?*/
+	private boolean autoSaveMacros = false;
+
+	private boolean lastEmployee = false;
+	public static int totalFinalized = 0;
+	/** the MesquiteModuleInfo that refers to the module*/
+	protected MesquiteModuleInfo moduleInfo = null;
+	/** The project that the module was hired under.  Almost all modules are descendant from a file coordinating module that belongs to
+	a specific project*/
+	protected MesquiteProject proj=null;  
+	/** for the paging system (may be defunct)*/
+	Vector pagingsEphemeral = new Vector();
+	/** for the paging system (may be defunct)*/
+	Vector pagingsPersistent = new Vector();
+
+	Vector subfunctions = new Vector();
+	public ListableVector attachments = new ListableVector();
+
+	public static boolean textEdgeRemembered = false;
+	public static int textEdgeCompensationHeight = 5; //6 on mac; 7 on pc
+	public static int textEdgeCompensationWidth = 10; //12 on mac; 28 on pc
+	private static int instantiations = 0;
+	private int idNumber;
+	private String permanentIDString = null;
+	private String assignedIDString = null;
+	private static Random randomNumberGenerator;
+	static {
+		randomNumberGenerator = new Random(System.currentTimeMillis());
+	}
+
+	/** The constructor in general is to be avoided, because modules are instantiated momentarily on startup to gather
+	information.  The usual functions of a constructor are performed by startJob*/
+	public MesquiteModule () {
+		super();
+		setModule(this);
+		instantiations++;
+		idNumber = instantiations;
+		permanentIDString = Integer.toString(idNumber) + "." + System.currentTimeMillis() + "." + Math.abs(randomNumberGenerator.nextLong());
+		assignedIDString = null;//new String(permanentIDString);
+	}
+	/*.................................................................................................................*/
+	/** instantiations of modules are numbered sequentially so they can be referred to by number*/
+	public long getID(){
+		return idNumber;
+	}
+	/*.................................................................................................................*/
+	/** A string that uniquely refers to this module (unique even across runs of Mesquite)*/
+	public String getPermanentIDString(){
+		if (assignedIDString == null)
+			return permanentIDString;
+		else
+			return assignedIDString;
+	}
+	/*.................................................................................................................*/
+	/** A string that should uniquely refer to this module during this run time
+	public String getAssignedIDString(){
+		return assignedIDString;
+	}
+	/*.................................................................................................................*/
+	/** Broadcasts that an id has been assigned to a module.  This is used for scripting, in which a module assigns itself
+	an id string in a snapshot (e.g., a TreeContext) that an interested module can clue in to (e.g., TreeOfContext).  This
+	allows the interested module to hook up to the assigning module even if the former was script-created before the latter
+	(see interaction between BasicTreeWindow and TreeOfContext)*/
+	public void broadCastAssignedID(MesquiteModule module, String assignedID){
+		if (assignedID == null)
+			return;
+		if (employees ==null)
+			return;
+		Enumeration enumeration=employees.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			mb.broadCastAssignedID(module, assignedID);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void incrementNumStarts(){
+		getModuleInfo().incrementNumStarts();
+	}
+	/*.................................................................................................................*/
+	/** superStartJob is called automatically when an employee is hired.  This is intended for use by superclasses of modules that need
+	their own constructor-like call, without relying on the subclass to be polite enough to call super.startJob().*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** startJob is called automatically when an employee is hired.  The parameter scripting indicates if the hiring occurs in the context
+	of automated scripting (e.g., on reading a Mesquite block of a NEXUS file).  The module can limit user interface calls (e.g. dialog boxes)
+	when scripting occurs.<p>
+	The MesquiteModule should override this method, to add code to 
+	initialize things it needs, and to hire relevant necessary employees.  startJob must return
+	true if the module was successfully started; false otherwise.  Thus, if the module needs a data matrix
+	but the file has none, it returns false and the hiring process is undone.<p>
+	Most modules will ignore the arguments and condition.*/
+	public abstract boolean startJob(String arguments, Object condition, boolean hiredByName);
+
+
+	/*.................................................................................................................*/
+	/** Resets the hiring condition, e.g. that matrices returned must be continuous.  This may not always work as it was added in '09 in Stored Characters.*/
+	public void setHiringCondition(Object condition){
+	}
+	/*.................................................................................................................*/
+	/** endJob is called as a module is quitting; modules should put their clean up code here.*/
+	public void endJob() {
+	}
+	/*.................................................................................................................*/
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	/*.................................................................................................................*/
+	/** dispose is called automatically when an employee is fired. It fires all employees and their subemployees etc.  
+	The MesquiteModule should call endJob to 
+	finalize things it needs..  NOTE: if a module wants to quit on its own accord, it should call "iQuit" so that
+	the replacement hiring system can take effect.*/
+	protected void dispose() {
+		if (assignedMenuSpec !=null)
+			assignedMenuSpec.removeGuestModule(this);
+		if (moduleMenuSpec !=null)
+			moduleMenuSpec.removeGuestModule(this);
+		doomed = true;
+		MesquiteWindow w = getModuleWindow();
+		if (w !=null) {
+			if (!(w instanceof SystemWindow)){ //not needed, since quitting
+				w.removeAll();
+			}				
+			w.setVisible(false);
+
+		}
+		boolean employerDoomed =  (employer!=null && employer.doomed);
+
+		if (!employerDoomed)
+			incrementMenuResetSuppression();
+		//storePreferences();
+		if (pagingsEphemeral!=null)
+			pagingsEphemeral.removeAllElements();
+		if (pagingsPersistent!=null)
+			pagingsPersistent.removeAllElements();
+		disposeMenuSpecifications();
+		if (w !=null) {
+			if (!w.disposed()) {
+				w.dispose();
+			}
+			resetAllMenuBars();
+		}
+
+		//	if (employer!=null && quit) //TODO: only call this if the employer quit on its own
+		//		employer.employeeQuit(this);
+		if (MesquiteTrunk.trackActivity) MesquiteMessage.notifyProgrammer ("MesquiteModule " + getName() + "  closing down ");
+		closeDownAllEmployees (this);
+		if (employer!=null && !employer.doomed && employer.employees!=null) {
+			employer.employees.removeElement(this, false);
+		}
+		if (!employerDoomed)
+			resetContainingMenuBar();
+		employer = null; //MEMORY: cut this out to promote memory leaks (tying modules together WHILE debugging NEW aug 99
+		if (employees!=null)
+			employees.dispose();
+		employees = null;
+		if (!employerDoomed)
+			decrementMenuResetSuppression();
+		proj = null;
+		totalDisposed++;
+	}
+	/*.................................................................................................................*/
+	/** Notifies all employees that a file is about to be closed.*/
+	public void fileCloseRequested () {
+		if (employees==null || doomed)
+			return;
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule)obj;
+			if (mbe!=null) {
+				mbe.fileCloseRequested(); 
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** To be called by a module to close down on its own (as opposed to being fired).  This might happen, for
+	example, if conditions change so that the module can no longer function (e.g. all stored matrices are deleted 
+	from a file, and so StoredMatrices can no longer supply matrices). A module could
+	also call its own endJob() method, but iQuit is to be preferred because it evokes the automatic replacement
+	hiring system if available.  (See setHiringCommand of EmployerEmployee) */
+	public final void iQuit(){
+		iQuit(true);
+	}
+	public final void iQuit(boolean giveMessage){
+		incrementMenuResetSuppression();
+		MesquiteCommand command = getHiringCommand();
+		doomAll();
+		MesquiteModule employerMod = employer;
+		MesquiteModule localRefEmployer = employer;
+		boolean employerDoomed =  (employer==null || employer.doomed || employerMod.quittingConditions());
+		if (!employerDoomed) {
+			localRefEmployer.incrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+			localRefEmployer.refreshBrowser(MesquiteModule.class);
+		}
+		endJob();
+		dispose();
+		resetAllWindowsMenus();
+		/* if hiringCommand isn't null, then look among the module info's for possible replacements
+		and use the hiringCommand to attempt to hire them.
+		In looking for possible replacements:
+			-- use the hiringCondition to find compatible modules
+			-- don't choose again the current module
+		With each candidate replacement, call the command's doIt method, passing the name of 
+		the candidate as an argument.  If the Object returned by doIt is non-null and is an instance of the
+		candidate module, then it is assume the replacement was successful and the search for replacements is ended.
+		(It may make sense to notify the user of the replacement.)
+		 */
+		if (employerDoomed || employerMod.quittingConditions()) {
+		}
+		else if (command!=null){
+			resetContainingMenuBar();
+			if (giveMessage)
+				alert("Module \"" + getName() + "\" has quit; a replacement module will be sought."); //TODO: ask user
+
+			MesquiteModuleInfo c=null;
+			//			boolean found = false;
+			if (getHiringCondition()==null){
+				String name =ListDialog.queryList(module.containerOfModule(), "Select replacement", "Select module to replace " + getName(), MesquiteString.helpString, getHiredAs(), null, employerMod);
+				if (StringUtil.blank(name)) {
+
+					//alert("Module \"" + getName() + "\" quit but none chosen to replace it.  This may");
+					hiredAs = null;
+					hiringCondition = null;
+					employerMod.employeeQuit(this);
+					decrementMenuResetSuppression();
+					if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+					return;
+				}
+				CommandRecord cr = new CommandRecord(false);
+				cr.setEmergencyRehire(true);
+				Object mb = command.doIt(StringUtil.tokenize(name));
+				if (mb!=null && mb instanceof MesquiteModule && ((MesquiteModule)mb).getModuleInfo()!= getModuleInfo() && getHiredAs()!=null && getHiredAs().isAssignableFrom(mb.getClass())) {
+					if (giveMessage)
+						alert("Module \"" + ((Listable)mb).getName() + "\" hired to replace \"" + getName() + "\", which has quit");
+					decrementMenuResetSuppression();
+					if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+					return;
+				}
+
+
+				MesquiteModuleInfo prevC = null;
+				while ((c = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(getHiredAs(), c)) != null) {  // if wasn't successful, find first that works.
+					if (c!=prevC){
+						cr = new CommandRecord(false);
+						cr.setEmergencyRehire(true);
+						CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+						MesquiteThread.setCurrentCommandRecord(cr);
+						mb = command.doIt(StringUtil.tokenize(c.getName()));
+						MesquiteThread.setCurrentCommandRecord(prevR);
+						if (mb!=null && mb instanceof MesquiteModule && ((MesquiteModule)mb).getModuleInfo()!= getModuleInfo() && getHiredAs()!=null && getHiredAs().isAssignableFrom(mb.getClass())) {
+							alert("Module \"" + ((Listable)mb).getName() + "\" hired to replace \"" + getName() + "\", which has quit");
+							decrementMenuResetSuppression();
+							if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+							return;
+						}
+						prevC = c;
+					}
+				}
+			}
+			else {
+				String name =ListDialog.queryList(module.containerOfModule(), "Select replacement", "Select module to replace " + getName(), MesquiteString.helpString, getHiredAs(), getHiringCondition(), employerMod);
+				if (StringUtil.blank(name)) {
+					hiredAs = null;
+					hiringCondition = null;
+					employerMod.employeeQuit(this);
+					decrementMenuResetSuppression();
+					if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+					return;
+				}
+				Object mb = command.doIt(StringUtil.tokenize(name));
+				if (mb!=null && mb instanceof MesquiteModule && ((MesquiteModule)mb).getModuleInfo()!= getModuleInfo() && getHiredAs()!=null && getHiredAs().isAssignableFrom(mb.getClass())) {
+					if (giveMessage)
+						alert("Module \"" + ((Listable)mb).getName() + "\" hired to replace \"" + getName() + "\", which has quit");
+					decrementMenuResetSuppression();
+					if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+					return;
+				}
+
+				MesquiteModuleInfo prevC = null;
+				while ((c = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule(getHiredAs(), c, getHiringCondition(), getProject(), employerMod)) != null) {  // if wasn't successful, find first that works.
+					if (c!=prevC){
+						mb = command.doIt(StringUtil.tokenize(c.getName()));
+						if (mb!=null && mb instanceof MesquiteModule && ((MesquiteModule)mb).getModuleInfo()!= getModuleInfo() && getHiredAs()!=null && getHiredAs().isAssignableFrom(mb.getClass())) {
+							if (giveMessage)
+								alert("Module \"" + ((Listable)mb).getName() + "\" hired to replace \"" + getName() + "\", which has quit");
+							decrementMenuResetSuppression();
+							if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+							return;
+						}
+					}
+					prevC = c;
+				}
+			}
+			alert("Employee quit but no replacement hire was found");
+			employerMod.employeeQuit(this);
+
+		}
+		else {
+			//alert("Module \"" + getName() + "\" has quit."); 
+			employerMod.employeeQuit(this);
+		}
+
+		decrementMenuResetSuppression();
+		if (!employerDoomed) localRefEmployer.decrementEmployeeBrowserRefreshSuppression(MesquiteModule.class);
+
+	}
+	/*.................................................................................................................*/
+	/** Query module as to whether conditions are such that it will have to quit soon -- e.g. if its taxa block has been doomed.  The tree window, data window, 
+	etc. override this to return true if their object is doomed. This is useful in case MesquiteListener disposing method is not called for an employer before one of its
+	employees discovers that it needs to quit.  If the employer is going to quit anyway,there is no use to use auto rehire for the quit employee.*/
+	public boolean quittingConditions(){
+		if (employer!=null) {
+			return employer.quittingConditions();
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been established but not yet read in.*/
+	public void projectEstablished() {
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately before a Mesquite block is to be read */
+	public void aboutToReadMesquiteBlock(MesquiteFile f) {
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately before a file is to be saved.*/
+	public void fileAboutToBeWritten(MesquiteFile f) {
+	}
+	/*.................................................................................................................*/
+	/** A method called when a FileElement added to the project; module can respond as needed (e.g., 
+ 	InitializeParsimony can add default model set to a CharacterData.  (currently only called for Taxa and CharacterData additions).*/
+	public void fileElementAdded(FileElement element) {
+	}
+	/*.................................................................................................................*/
+	/** Returns duty Class the module belongs to; should be defined not by module itself but by abstract class representing duty */
+	public abstract Class getDutyClass();
+	/*.................................................................................................................*/
+	/** Returns module info for module*/
+	public MesquiteModuleInfo getModuleInfo(){
+		return moduleInfo;
+	}
+	/** Notifies all employees that a class field has changed.*/
+	public void classFieldChanged (Class c, String fieldName) {
+		if (employees==null || doomed)
+			return;
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule)obj;
+			if (mbe!=null) {
+				mbe.classFieldChanged(c, fieldName);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	Listened optionalListened = null;
+	public Listened getParametersChangedNotifier(){
+		if (optionalListened == null)
+			optionalListened = new Listened();
+		return optionalListened;
+	}
+	/*.................................................................................................................*/
+	/** A generic call to tell employer that the module's parameters have changed
+	sufficiently that its basic calculations are no longer valid, and a recalculation should
+	be requested.  The employer receives the message as a call to its employeeParametersChanged.
+	(Typically, this might follow an outputInvalid call, which */
+	public final void parametersChanged(Notification notification) {
+		//CommandRecord.tick("Parameters of module changed");
+		if (employer!=null && !doomed) {
+			if (!hasOldStyleEPC(employer))
+				employer.employeeParametersChanged(this, this, notification);
+		}
+		if (optionalListened != null)
+			optionalListened.notifyListeners(this, notification);
+	}
+	public final void parametersChanged() {
+		parametersChanged(null);
+	}
+	
+		/*.................................................................................................................*/
+	/** A generic call to ask employer whether to handle something myself as employee */
+	public final boolean dearEmployerShouldIHandleThis(Notification notification) {
+		//CommandRecord.tick("Parameters of module changed");
+		if (employer!=null && !doomed) {
+				return employer.employeeRequestingIndependenceOfAction(this, this, notification);
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	private boolean hasOldStyleEPC(MesquiteModule mb){
+		try {
+			mb.getClass().getMethod("employeeParametersChanged", new Class[] {MesquiteModule.class, MesquiteModule.class, CommandRecord.class});
+		}
+		catch(NoSuchMethodException e){
+			return false;
+		}
+		catch(SecurityException e){
+			return false; //hope for best
+		}
+		alert("The module " + employer.getName() +" appears to be old and incompatible with the current version of Mesquite.");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee calling its parametersChanged method.  The MesquiteModule should act accordingly, for instance, asking
+	the employee to do a recalculation. */
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		//CommandRecord.tick("Parameters of employee module changed");
+		if (employer!=null && !doomed) {
+			if (!hasOldStyleEPC(employer))
+				employer.employeeParametersChanged(this, source, notification);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee calling its dearEmployerShouldIHandleThis method.  The MesquiteModule should respond false if the employer wants to handle it itself. */
+	public boolean employeeRequestingIndependenceOfAction(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employer!=null && !doomed) {
+				return employer.employeeRequestingIndependenceOfAction(this, source, notification);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** This passes an employeeOutputInvalid call to the employer, and so on, until some employer overrides it to do something about it.  
+	The purpose of this is not to call for recalculations, but primarily to allow the output to be turned blank while
+	long recalculations are done. To force recalculation, parametersChanged should be called after outputInvalid is called*/
+	public final void outputInvalid() {
+		if (employer!=null && !doomed)
+			employer.employeeOutputInvalid(this, this);
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee calling its outputInvalide method.  The MesquiteModule should blank any output. */
+	public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+		if (employer!=null && !doomed)
+			employer.employeeOutputInvalid(this, source);
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+	}
+	/*.................................................................................................................*/
+	/** Sets this module to remain one of the last employees of its employers. */
+	public void setToLastEmployee(boolean last){
+		lastEmployee = last;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether this module is to remain one of the last employees of its employers. */
+	public boolean getIfLastEmployee(){
+		return lastEmployee;
+	}
+	/*.................................................................................................................*/
+	/** Sets whether module has requested to enable auto-save of macros. */
+	public void setAutoSaveMacros(boolean aut){
+		autoSaveMacros = aut;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether module has requested to enable auto-save of macros. */
+	public boolean getAutoSaveMacros(){
+		return autoSaveMacros;
+	}
+	/*.................................................................................................................*/
+	/** Called typically by employer to indicate that will be called soon, therefore don't update graphics. */
+	public void onHold() {
+	}
+	/*.................................................................................................................*/
+	/** Called typically by employer to turn off hold, therefore don't update graphics. */
+	public void offHold() {
+	}
+	/*.................................................................................................................*/
+	public String supportDirectoryPath (){
+		return getTempDirectoryPath()  + MesquiteFile.fileSeparator +  getShortClassName(this.getClass());
+	}
+	/*.................................................................................................................*/
+	public static String getTempDirectoryPath (){
+		return MesquiteTrunk.tempDirectory; //+ Math.abs(rng.nextInt()));
+	}
+	/*.................................................................................................................*/
+	private String prefsPath (){
+		return prefsDirectory  + MesquiteFile.fileSeparator +  getShortClassName(this.getClass()) +".pref";
+	}
+	/*.................................................................................................................*/
+	private String prefsPathXML (){
+		return prefsDirectory  + MesquiteFile.fileSeparator +  getShortClassName(this.getClass()) +".xml";
+	}
+	/*.................................................................................................................*/
+	public String createTempDirectory(MesquiteBoolean success){
+		boolean baseDirectoryExists = false;
+		String base = prefsDirectory  + MesquiteFile.fileSeparator +  "temp";
+		if (!MesquiteFile.fileOrDirectoryExists(base)) {
+			File f = new File(base);
+			baseDirectoryExists = f.mkdir();
+		}  else 
+			baseDirectoryExists = true;
+		if (success!=null && !baseDirectoryExists)
+			success.setValue(false);
+		base = prefsDirectory  + MesquiteFile.fileSeparator +  "temp" + MesquiteFile.fileSeparator +  "temp" + MesquiteFile.massageStringToFilePathSafe(MesquiteTrunk.getUniqueIDBase()) ;
+		if (baseDirectoryExists) {
+			if (!MesquiteFile.fileOrDirectoryExists(base)) {
+				File f = new File(base);
+				boolean b = f.mkdir();
+				if (success!=null)
+					success.setValue(b);
+			} else if (success!=null)
+				success.setValue(true);
+		}
+		MesquiteTrunk.tempDirectory = base;
+		return base;
+	}
+	/*.................................................................................................................*/
+	public String createTempDirectory(){
+		return createTempDirectory(null);
+	}
+	/*.................................................................................................................*/
+	public void deleteTempDirectory(){
+		String directoryPath = getTempDirectoryPath();
+		MesquiteFile.deleteDirectory(directoryPath);
+	}
+
+	/*.................................................................................................................*/
+	public String createEmptySupportDirectory(MesquiteBoolean success){
+		String base = supportDirectoryPath();
+		if (MesquiteFile.fileOrDirectoryExists(base)) 
+			MesquiteFile.deleteDirectory(base);
+		if (!MesquiteFile.fileOrDirectoryExists(base)) {
+			File f = new File(base);
+			boolean b = f.mkdir();
+			if (success!=null)
+				success.setValue(b);
+		} else if (success!=null)
+			success.setValue(true);
+
+		return base;
+	}
+	/*.................................................................................................................*/
+	public String createSupportDirectory(MesquiteBoolean success){
+		String base = supportDirectoryPath();
+		if (!MesquiteFile.fileOrDirectoryExists(base)) {
+			File f = new File(base);
+			boolean b = f.mkdir();
+			if (success!=null)
+				success.setValue(b);
+		} else if (success!=null)
+			success.setValue(true);
+
+		return base;
+	}
+	/*.................................................................................................................*/
+	public String createSupportDirectory(){
+		return createSupportDirectory(null);
+	}
+
+	/*.................................................................................................................*/
+	public void deleteSupportDirectory(){
+		String directoryPath = supportDirectoryPath();
+		MesquiteFile.deleteDirectory(directoryPath);
+	}
+
+
+	/* XMLPreferencesDocumentation
+	 * Herewith a description of how a module can use the simple, one-level deep XML preferences system:
+ 		1. in startjob, call loadPreferences();
+ 		2. call storePreferences(); where appropriate in the module (e.g., after you press ok on an options dialog box)
+ 		3. override preparePreferencesForXML() to prepare the XML to write
+  		4. override processSingleXMLPreference(String, String) to read XML tag as it comes in.
+
+  		Here are examples of preparePreferencesForXML and processSingleXMLPreference to use as models.  
+  		These presume we have three variables whose values we want to store:
+
+  		boolean booleanValue;
+  		String stringValue;
+  		int intValue;
+
+  		and that we want to name the tags the same as the variable names:
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "mesquiteBoolean", mesquiteBoolean);   
+		StringUtil.appendXMLTag(buffer, 2, "booleanValue", booleanValue);   
+		StringUtil.appendXMLTag(buffer, 2, "integerValue", integerValue);  
+		StringUtil.appendXMLTag(buffer, 2, "stringValue", stringValue);  
+		return buffer.toString();
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("mesquiteBoolean".equalsIgnoreCase(tag))
+			mesquiteBoolean.setValue(content);
+		else if ("booleanValue".equalsIgnoreCase(tag))
+			booleanValue = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("integerValue".equalsIgnoreCase(tag))
+			integerValue = MesquiteInteger.fromString(content);
+		else if ("stringValue".equalsIgnoreCase(tag))
+			stringValue = StringUtil.cleanXMLEscapeCharacters(content);
+	}
+
+
+
+	/*.................................................................................................................*/
+	public String getXMLModuleName (){
+		String moduleName = getShortClassName(this.getClass());
+		if (this == mesquiteTrunk)
+			moduleName = "MesquiteTrunk";
+		return moduleName;
+	}
+	/*.................................................................................................................*/
+	public String getStartOfXMLPrefs (int version){
+		StringBuffer buffer = new StringBuffer(60);
+		StringUtil.appendStartOfXMLFile(buffer);
+		buffer.append("<mesquite>\n");
+		buffer.append("\t<" + getXMLModuleName() + ">\n");
+		buffer.append("\t\t<version>" +version + "</version>\n");
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public String getEndOfXMLPrefs (){
+		StringBuffer buffer = new StringBuffer(60);
+		buffer.append("\t</" + getXMLModuleName() + ">\n");
+		buffer.append("</mesquite>\n");
+		return buffer.toString();
+	}
+
+
+	/*.................................................................................................................*/
+	/** This causes the file "prefs" in the module's directory to be read, and the contents
+	are then sent to "processPreferencesFromFile".*/
+	public final void loadPreferences (MesquiteString xml) {
+
+		if (MesquiteFile.fileExists(prefsPathXML())){	
+			String prefsStringXML = MesquiteFile.getFileContentsAsString(prefsPathXML());
+			if (prefsStringXML!=null) {
+				if (xml!=null)
+					xml.setValue(prefsStringXML);
+				if (!parseFullXMLDocument(prefsStringXML)) {
+
+					XMLUtil.readXMLPreferencesFromFile(this,this, prefsPathXML());
+
+					//					XMLUtil.readXMLPreferences(this,this, prefsStringXML);
+
+				}
+			}
+			// the xml pref exists; check to see if the old one exists; if so, delete it
+			if (MesquiteFile.fileExists(prefsPath())){  //old one exists; delete it
+				MesquiteFile.deleteFile(prefsPath());
+			}
+
+		}
+		else if (MesquiteFile.fileExists(prefsPath())){  //note that the XML version thus supercedes the .prefs version
+			String[] prefsString = MesquiteFile.getFileContentsAsStrings(prefsPath());
+			if (prefsString!=null)
+				processPreferencesFromFile(prefsString);
+		}
+
+		//the following was added build 487 v 2. 6, to permit prefs that followed Mesquite_Folder to override (e.g., for classroom copies)
+		String overridePrefsPath = getInstallationSettingsPath() + "prefs.xml";
+		if (MesquiteFile.fileExists(overridePrefsPath)){	
+			String prefsStringXML = MesquiteFile.getFileContentsAsString(overridePrefsPath);
+			if (prefsStringXML!=null) {
+				if (xml!=null)
+					xml.setValue(prefsStringXML);
+				if (!parseFullXMLDocument(prefsStringXML)) {
+					System.out.println("Prefs overridden via file in settings directory for module " + getName());
+					XMLUtil.readXMLPreferences(this,this, prefsStringXML);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** This causes the file "prefs" in the module's directory to be read, and the contents
+	are then sent to "processPreferencesFromFile".*/
+	public final void loadPreferences () {
+		loadPreferences(null);
+	}
+	protected static boolean isCorrectRootTag(String tagName, Class classObj) {
+		return getShortClassName(classObj).equalsIgnoreCase(tagName);
+	}
+	/**
+	 * Hook for subclasses to provide their own xml preferences parsing implementations
+	 * @return
+	 */
+	protected boolean parseFullXMLDocument(String xmlString) {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** This is called following a "processPreferencesFromXML" call by a module.  A module can override it
+	to process an individual XML preferences string*/
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+	}
+	/*.................................................................................................................*/
+	/** This is called following a "loadPreferences" call by a module.  A module can override it
+	to process the preferences string*/
+	public void processPreferencesFromFile (String[] prefs) {
+	}
+	/*.................................................................................................................*/
+	/** This causes the file "prefs" in the module's directory to be written, using contents
+	returned by the module via "preparePreferencesForFile"*/
+	public final void storePreferences () {
+		String prefsStringXML = preparePreferencesForXML();
+		if (prefsStringXML!=null) {
+			boolean isAlreadyFullDocument = prefsStringXML.startsWith("<?xml");
+			// if subclasses return a full document, just write that out.  
+			// otherwise add the beginning and end of the document
+			String xmlToWrite = isAlreadyFullDocument ? prefsStringXML : getStartOfXMLPrefs(getXMLPrefsVersion()) + prefsStringXML+ getEndOfXMLPrefs(); 
+			MesquiteFile.putFileContents(prefsPathXML(), xmlToWrite, false);			
+		} else {
+			String[] prefsString = preparePreferencesForFile();
+			if (prefsString!=null)
+				MesquiteFile.putFileContents(prefsPath(), prefsString, false);
+		}
+	}
+	/*.................................................................................................................*/
+	/** This is called following a "storePreferences" call by a module. A module should override it
+	to indicate the strings to save to its preferences file. */
+	public String[] preparePreferencesForFile () {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public int getXMLPrefsVersion () {
+		return 1;
+	}
+	public boolean xmlPrefsVersionMustMatch() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** This is called following a "storePreferences" call by a module. A module should override it
+	to indicate the strings to save to its preferences file. */
+	public String preparePreferencesForXML () {
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns path to this module's directory for installation settings (i.e., belonging to Mesquite_Folder, not to the user)*/
+	public String getInstallationSettingsPath() {  
+		if (this == MesquiteTrunk.mesquiteTrunk)
+			return getRootPath() + "settings" + MesquiteFile.fileSeparator;
+		String base = getRootPath() + "settings" + MesquiteFile.fileSeparator;
+		String modulePath = moduleInfo.getClassName();
+		modulePath = modulePath.substring(modulePath.indexOf(".")+1, modulePath.length());
+		modulePath = StringUtil.getAllButLastItem(modulePath, ".");
+		modulePath = StringUtil.replace(modulePath, ".", MesquiteFile.fileSeparator) +MesquiteFile.fileSeparator ;
+		//modulePath = modulePath.substring(9, modulePath.length());
+		return  base + modulePath;
+	}
+	/*.................................................................................................................*/
+	/** returns path to this module's directory*/
+	public String getPath() {  
+		if (this == MesquiteTrunk.mesquiteTrunk)
+			return getRootPath() + "mesquite" + MesquiteFile.fileSeparator;
+		if (moduleInfo == null)
+			return null;
+		return  moduleInfo.getDirectoryPath();
+	}
+	/*.................................................................................................................*/
+	/** returns path to this module's package directory*/
+	public String getPackagePath() {  
+		if (this == MesquiteTrunk.mesquiteTrunk)
+			return getRootPath() + "mesquite" + MesquiteFile.fileSeparator;
+		return  moduleInfo.getPackagePath();
+	}
+	/*.................................................................................................................*/
+	/** returns path to the image directory for this module's images*/
+	public String getPackageImagesPath() {  
+		if (this == MesquiteTrunk.mesquiteTrunk)
+			return getRootPath() + "mesquite" + MesquiteFile.fileSeparator;
+		return  moduleInfo.getPackagePath() + "images"+ MesquiteFile.fileSeparator;
+	}
+	/*.................................................................................................................*/
+	/** returns path to the root directory of Mesquite (i.e., above mesquite, images, etc.)*/
+	public static String getRootPath() {
+		String s= StringUtil.getAllButLastItem(mesquiteDirectoryPath, MesquiteFile.fileSeparator);
+		if (s==null)
+			return null;
+		else
+			return s + MesquiteFile.fileSeparator;
+	}
+	/*.................................................................................................................*/
+	/** returns path to the root directory of Mesquite images*/
+	public static String getRootImageDirectoryPath() {
+		String s = getRootPath();
+		if (s==null)
+			return null;
+		else
+			return s + "images/";
+	}
+	/*.................................................................................................................*/
+	public static String getSizedRootImageFilePath(int s, String imageFileName){
+		return getRootImageDirectoryPath() + s + imageFileName;
+	}
+	/*.................................................................................................................*/
+	/** returns path to the root directory of the documentation of Mesquite*
+	public static String getDocsPath() {
+		String s= StringUtil.getAllButLastItem(mesquiteDirectoryPath, MesquiteFile.fileSeparator);
+		if (s==null)
+			return null;
+		else
+			return s + MesquiteFile.fileSeparator + "docs/mesquite/"; xxx
+	}
+	/*.................................................................................................................*/
+	/** returns a local file path expected by the module.  This allows the module to say "I am going to need this".  Mesquite
+ 	check on startup and issues warning if not found . */
+	public String  getExpectedPath(){ 
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** An employee can call this to know if it's ok to query for options or do any other UI interaction involving a user response.
+	 * An employer can override this to say "no".*/
+	public boolean okToInteractWithUser(int howImportant, String messageToUser){
+		if (whomToAskIfOKToInteractWithUser!=null)
+			return whomToAskIfOKToInteractWithUser.okToInteractWithUser(howImportant, messageToUser);
+		if (employer!= null)
+			return employer.okToInteractWithUser(howImportant, messageToUser);
+		return true;
+	}
+	public static final int CAN_PROCEED_ANYWAY = 0;
+	public static final int WILL_FAIL_OTHERWISE = 1;
+
+	MesquiteModule whomToAskIfOKToInteractWithUser = null;
+	public void setWhomToAskIfOKToInteractWithUser(MesquiteModule m){
+		whomToAskIfOKToInteractWithUser = m;
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in log; also in dialog if flag is set.*/
+	public void alert(String s, String windowTitle, String logTitle) {
+		if (s == null)
+			return;
+		if (startupBailOut)
+			return;
+		if (showModuleInAlert)
+			logln(logTitle+": (" + getName() + "): " + s);
+		else
+			logln(logTitle+": " + s);
+
+		if (alertUseDialog) {
+			AlertDialog.notice(containerOfModule(),windowTitle, s);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in log; also in dialog if flag is set.*/
+	public void alertHTML(String s, String windowTitle, String logTitle) {
+		alertHTML(s, windowTitle, logTitle, 400, 400);
+
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in log; also in dialog if flag is set.*/
+	public void alertHTML(String s, String windowTitle, String logTitle, int width, int height) {
+		if (s == null)
+			return;
+		if (startupBailOut)
+			return;
+		if (showModuleInAlert)
+			logln(logTitle+": (" + getName() + "): " + s);
+		else
+			logln(logTitle+": " + s);
+
+		if (alertUseDialog) {
+			AlertDialog.noticeHTML(containerOfModule(),windowTitle, s, width, height, null);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in log.*/
+	public void alert(String s) {
+		alert(s,"Alert", "ALERT");
+	}
+
+	/*.................................................................................................................*/
+	private boolean isNonReportable(Throwable e){  //here keep a list of exceptions that are not Mesquite's problem...
+		if (e == null)
+			return true;
+		if (e instanceof IllegalStateException)
+			return true;
+		if (e.getClass() == RuntimeException.class)
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in connection to a detected error and offers to send to server*/
+	public void reportableProblemAlert(String s) {
+		MesquiteTrunk.errorReportedDuringRun = true;
+		MesquiteDialog.cleanUpWizard();
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread)
+			((MesquiteThread)t).doCleanUp();
+		logln(s);
+		Exception e = new Exception();
+
+
+		if (!PhoneHomeUtil.phoneHomeSuccessful || !MesquiteTrunk.reportErrors || MesquiteTrunk.suppressErrorReporting || MesquiteThread.isScripting()){
+			return;
+		}
+		String addendum = "";
+
+		if (MainThread.emergencyCancelled || MesquiteTrunk.errorReportedToHome){// if emergency cancelled, reporting suppressed because silly user didn't restart!  Also, only one report per run.
+			discreetAlert(s);
+
+		}
+		else if (AlertDialog.query(containerOfModule(), "Problem", s + "\n\nPlease send a report of this problem to the Mesquite server, to help us debug it and improve Mesquite.  None of your data will be sent, but your log file up to this point will be sent." + addendum, "OK, Send Report and Continue", "Close without sending"))
+			reportCrashToHome(e, s);
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in connection to an exception*/
+	public void exceptionAlert(Throwable e, String s) {
+		MesquiteTrunk.errorReportedDuringRun = true;
+		StackTraceElement[] stt = e.getStackTrace();
+		String rep = MesquiteException.lastLocMessage() + "\n";
+		rep += getRootPath() + "\n";
+		rep += e + "\n";
+		rep += s + "\n";
+		for (int i= 0; i< stt.length; i++)
+			rep += stt[i] + "\n";
+		s = rep;
+		MesquiteDialog.cleanUpWizard();
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread)
+			((MesquiteThread)t).doCleanUp();
+		logln(s);
+		if (!PhoneHomeUtil.phoneHomeSuccessful || !MesquiteTrunk.reportErrors || MesquiteTrunk.suppressErrorReporting){
+			if (!MesquiteThread.isScripting() && !AlertDialog.query(containerOfModule(), "Crash", s, "OK", "Force Quit"))
+				MesquiteTrunk.mesquiteTrunk.exit(true, 0);
+			return;
+		}
+		if (MesquiteThread.isScripting()){
+			return;
+		}
+		String addendum = "";
+		if (isNonReportable(e)){
+			StackTraceElement[] stack = e.getStackTrace();
+			String report = MesquiteException.lastLocMessage() + "\n";
+			report += e + "\n";
+			report += s + "\n";
+			for (int i= 0; i< stack.length; i++)
+				report += stack[i] + "\n";
+			logln(report);
+		}
+		else if (MainThread.emergencyCancelled || MesquiteTrunk.errorReportedToHome){// if emergency cancelled, reporting suppressed because silly user didn't restart!  Also, only one report per run.
+			if (!MesquiteThread.isScripting() && !AlertDialog.query(containerOfModule(), "Crash", s, "OK", "Force Quit"))
+				MesquiteTrunk.mesquiteTrunk.exit(true, 0);
+
+		}
+		else {
+			int resp = AlertDialog.query(containerOfModule(), "Crash", s + "\n\nPlease send a report of this crash to the Mesquite server, to help us debug it and improve Mesquite.  None of your data will be sent, but your log file up to this point will be sent." + addendum, "OK, Send Report and Continue", "OK, Send and Force Quit", "Close without sending");
+			if (resp < 2)
+				reportCrashToHome(e, s);
+			if (resp == 1)
+				MesquiteTrunk.mesquiteTrunk.exit(true, 0);
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Reports crash or error to Mesquite server*/
+	public void reportCrashToHome(Throwable e, String s) {
+		StackTraceElement[] stack = e.getStackTrace();
+		String report = MesquiteException.lastLocMessage() + "\n";
+		report += e + "\n";
+		report += s + "\n";
+		for (int i= 0; i< stack.length; i++)
+			report += stack[i] + "\n";
+		if (MainThread.emergencyCancelled)
+			report += "\n\nEMERGENCY CANCELLED";
+
+		report += "\n\n\n";
+		report += logWindow.getText();
+		report += "\n\n\n";
+		reportProblemToHome(report);
+		MesquiteTrunk.errorReportedToHome = true;
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in connection to an exception*/
+	public void reportableAlert(String s, String details) {
+		if (!PhoneHomeUtil.phoneHomeSuccessful || !MesquiteTrunk.reportErrors || MesquiteTrunk.suppressErrorReporting){
+			alert(s);
+			return;
+		}
+		String addendum = "";
+		if (MainThread.emergencyCancelled || MesquiteTrunk.errorReportedToHome){// if emergency cancelled, reporting suppressed because silly user didn't restart!  Also, only one report per run.
+			discreetAlert(s);
+		}
+		else {
+			boolean q = AlertDialog.query(containerOfModule(), "Error", s + "\n\nPlease send a report of this error to the Mesquite server, to help us understand how often this happens.  None of your data will be sent." + addendum, "OK, Send Report",  "Close without sending");
+			if (q){
+				reportProblemToHome(s + "\n\n" + details + "\n\n@@@@@@@@@@@@@@@\n\n" + logWindow.getText());
+				MesquiteTrunk.errorReportedToHome = true;
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public String getClassName() {
+		return moduleInfo.getClassName();
+	}
+	/*.................................................................................................................*/
+
+	/** posts a Bean to the bean log on the MesquiteServer*/
+	public void postBean(String notes, boolean notifyUser) {
+		if (!MesquiteTrunk.reportUse){
+			return;
+		}
+		if (MesquiteTrunk.noBeans) {
+			if (notifyUser) 
+				logln("No beans were sent as the -nb flag was set.");
+			return;
+		}
+		int numPairs=3;
+		if (StringUtil.notEmpty(notes))
+			numPairs=4;
+		NameValuePair[] pairs = new NameValuePair[numPairs];
+		pairs[0] = new NameValuePair("module", StringUtil.tokenize(moduleInfo.getClassName()));
+		pairs[1] = new NameValuePair("version", StringUtil.tokenize(getVersion()));
+		pairs[2] = new NameValuePair("build", ""+getBuildNumberOfPackage());
+		if (numPairs>=4)
+			pairs[3] = new NameValuePair("notes", StringUtil.tokenize(notes));
+
+		if (BaseHttpRequestMaker.sendInfoToServer(pairs, "http://mesquiteproject.org/pyMesquiteBeans", null, 0)){  // changed to not retry
+			if (notifyUser) 
+				MesquiteMessage.println("Bean sent to Mesquite server.");
+		}
+		else
+			if (notifyUser) 
+				logln("Sorry, Mesquite was unable to connect to the server to send the bean.");
+	}
+	/*.................................................................................................................*/
+	/** posts a Bean to the bean log on the MesquiteServer*/
+	public void postBean() {
+		postBean("", false);
+	}
+	/*.................................................................................................................*/
+	/** Displays an alert in connection to an exception*/
+	public void reportProblemToHome(String s) {
+		String email = MesquiteString.queryString(containerOfModule(), "E-mail for follow up?", "[Optional] Thank you for reporting this problem.  " + 
+				"In order to fix this bug, we may need to contact you for more details.  " + 
+				"If you don't mind our contacting you, please indicate your email address here.  Thanks. " + 
+				"(If you want a response urgently, please send an email directly to info at mesquiteproject.org.)", "");
+		String report = "build " + MesquiteTrunk.mesquiteTrunk.getBuildNumber() + "\n";
+		report += "java:" + System.getProperty("java.version") +"; vm:" + System.getProperty("java.vendor") + "; os:" + System.getProperty("os.name") + "; osversion:" + System.getProperty("os.version") + "; arch:" + System.getProperty("os.arch") + "\n";
+		if (!StringUtil.blank(email))
+			report += "EMAIL\t" + email +  "\n\n";
+		else
+			report += "EMAIL NOT GIVEN\n\n";
+
+		report += s + "\n";
+		StringBuffer response = new StringBuffer();
+		if (BaseHttpRequestMaker.postToServer(report, errorReportURL, response)){
+			String r = response.toString();
+			if (r == null || r.indexOf("mq3rs")<0)
+				discreetAlert("Sorry, Mesquite was unable to communicate properly with the server to send the report.");
+			else
+				AlertDialog.noticeHTML(containerOfModule(),"Note", r, 600, 400, null);
+		}
+		else
+			discreetAlert("Sorry, Mesquite was unable to connect to the server to send the report.");
+
+
+	}
+	/*.................................................................................................................*/
+	/** If scripting, puts alert in log; otherwise puts up alert dialog.*/
+	public void discreetAlert( String s) {
+		discreetAlert(MesquiteThread.isScripting(), s);
+	}
+	/*.................................................................................................................*/
+	/** If scripting, puts alert in log; otherwise puts up alert dialog.*/
+	public void discreetAlert(boolean beDiscreet, String s) {
+		if (beDiscreet)
+			logln("Note: " + s);
+		else
+			alert(s,"Note", "Note");
+	}
+	/*.................................................................................................................*/
+	/** If scripting, puts alert in log; otherwise puts up alert dialog.*/
+	public void discreetAlertHTML(String s) {
+		if (MesquiteThread.isScripting())
+			logln("Note: " + s);
+		else
+			AlertDialog.noticeHTML(containerOfModule(),"Note", s, 600, 400, null);
+	}
+	/*.................................................................................................................*/
+	/** Displays a message and returns false.  For use when a method fails and is returning false to indicate this, and needs to present a notice to the user.
+	(This method was made so as to change easily statements of "return false" so that they also gave a message, without having to split into two lines.) */
+	public boolean sorry(String s) {
+		CommandRecord.tick("Sorry, module couldn't be started");
+		if (!startupBailOut){
+			if (!MesquiteThread.isScripting()) 
+				alert(s);
+			else
+				logln("Message from " + getNameForMenuItem() + ": " + s);
+		}
+		return false;
+	}
+
+	boolean useSysOut(){
+		return (!MesquiteTrunk.suppressSystemOutPrintln && ((!MesquiteTrunk.isMacOS() || (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>1.39))));
+
+	}
+	/*.................................................................................................................*/
+	/** Places string in log AND in System.out.println.*/
+	public void log(String s, boolean echoToDetails) {
+		logNoEcho(s);
+		if (useSysOut())
+			System.out.print(s);
+		if (echoToDetails)
+			CommandRecord.tick(s);
+	}
+	/*.................................................................................................................*/
+	/** Places string in log AND in System.out.println.*/
+	public void log(String s) {
+		logNoEcho(s);
+		if (useSysOut())
+			System.out.print(s);
+	}
+	/*.................................................................................................................*/
+	/** Places string and newline character in log AND in System.out.println.*/
+	public void logln(String s, boolean echoToDetails) {
+		loglnNoEcho(s);
+		if (useSysOut())
+			System.out.println(s);
+		if (echoToDetails)
+			CommandRecord.tick(s);
+	}
+	/*.................................................................................................................*/
+	public void loglnEchoToStringBuffer(String s, StringBuffer sb){
+		logln(s);
+		if (sb!=null) {
+			sb.append(s);
+			sb.append(StringUtil.lineEnding());   
+		}
+	}
+	/*.................................................................................................................*/
+	/** Places string and newline character in log AND in System.out.println.*/
+	public void logln(String s) {
+		loglnNoEcho(s);
+		MesquiteThread.loglnToThreadLogger(s);
+		if (useSysOut())
+			System.out.println(s);
+	}
+	/*.................................................................................................................*/
+	/** Places string in log.*/
+	public void logNoEcho(String s) {
+		if (logWindow!=null) {
+			if (showModuleInLog)
+				logWindow.append(getName() + "-- " + s);
+			else
+				logWindow.append(s);
+		}
+		MesquiteFile.writeToLog(s);  //TODO: have a flag that turns this on
+		if (this != mesquiteTrunk){
+			Object cOM = containerOfModule();
+			if (cOM instanceof MesquiteWindow)
+				((MesquiteWindow)cOM).log(s); //Wayne: this seems to be causing loss of focus in lo9g window
+		}
+		CommandRecord cRec = MesquiteThread.getCurrentCommandRecord();
+		if (cRec != null && cRec.getEchoCommunicator()!=null)
+			cRec.getEchoCommunicator().log(s);
+	}
+	/*.................................................................................................................*/
+	/** Places string and newline character in log.*/
+	public void loglnNoEcho(String s) {
+		if (logWindow!=null) {
+			if (showModuleInLog)
+				logWindow.append(getName() + "-- " + s + "\n");
+			else
+				logWindow.append(s + "\n");
+		}
+		MesquiteFile.writeToLog(s+ StringUtil.lineEnding());
+		if (this != mesquiteTrunk){
+			Object cOM = containerOfModule();
+			if (cOM != null && cOM instanceof MesquiteWindow)
+				((MesquiteWindow)cOM).logln(s);
+		}
+		CommandRecord cRec = MesquiteThread.getCurrentCommandRecord();
+		if (cRec != null && cRec.getEchoCommunicator()!=null)
+			cRec.getEchoCommunicator().log(s);
+	}
+	/*.................................................................................................................*/
+	/** Shows the log window.*/
+	public static void showLogWindow() {
+		showLogWindow(true);
+	}
+	/*.................................................................................................................*/
+	/** Shows the log window.*/
+	public static void showLogWindow(boolean bringToFront) {
+		if (logWindow!=null) {
+			if (bringToFront || !logWindow.isVisible())
+				logWindow.setVisible(true);
+		}
+	}
+	/*.................................................................................................................*/
+	/** This requests that ALL tool palettes be recomposed.*/
+	public static final void resetAllToolPalettes() {
+		Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw!=null) {
+				ToolPalette palette = mw.getPalette();
+				if (palette != null) {
+					palette.recheckSize();
+					palette.repaint();
+					palette.repaintAll();
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+	}
+	/*.................................................................................................................*/
+	/** Requests modules to start profiling.*/
+	public void startProfiling(){
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule)obj;
+			mbe.startProfiling();
+		}
+	}
+	/*.................................................................................................................*/
+	/** Requests modules to report profiling.*/
+	public void reportProfiling(){
+		Enumeration e = employees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule)obj;
+			mbe.reportProfiling();
+		}
+	}
+	public boolean permanentIDExists(String id) {
+		if (id == null || employees ==null)
+			return false;
+		if (id.equalsIgnoreCase(getPermanentIDString())) //had been getAssignedIDString
+			return true;
+		Enumeration enumeration=employees.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			if (mb.permanentIDExists(id))
+				return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** Sets  last results variables to unassigned or null */
+	public void clearResultAndLastResult(Object result){
+		if (result instanceof MesquiteNumber) {
+			((MesquiteNumber)result).setToUnassigned();
+			((MesquiteNumber)result).copyAuxiliaries((MesquiteNumber[])null);
+
+		}
+		else if (result instanceof NumberArray) {
+			((NumberArray)result).deassignArray();
+
+		}
+		lastResult = null;
+		lastResultString=null;
+	}
+	/*.................................................................................................................*/
+	/** Sets all last result variables to unassigned or null */
+	public void clearLastResult(){
+		lastResult = null;
+		lastResultString=null;
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResult.*/
+	public void saveLastResult(Object result){
+		if (result==null)
+			this.lastResult=null;
+		else if (result instanceof MesquiteNumber) {
+			this.lastResult = new MesquiteNumber((MesquiteNumber)result, true);
+		}
+		else if (result instanceof NumberArray) {
+			this.lastResult = ((NumberArray)result).cloneArray();
+		}
+		else
+			this.lastResult = result;
+
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResult.*/
+	public void saveLastResult(double lastResult){
+		this.lastResult = new MesquiteNumber(lastResult);
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResult.*/
+	public void saveLastResult(int lastResult){
+		this.lastResult = new MesquiteNumber(lastResult);
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResult.*/
+	public void saveLastResult(long lastResult){
+		this.lastResult = new MesquiteNumber(lastResult);
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResultString.*/
+	public void saveLastResultString(String lastResultString){
+		this.lastResultString = lastResultString;
+	}
+	/*.................................................................................................................*/
+	/** Store a value in lastResultString.*/
+	public void saveLastResultString(MesquiteString lastResultString){
+		if (lastResultString==null)
+			this.lastResultString = null;
+		else
+			this.lastResultString = lastResultString.getValue();
+	}
+	/*.................................................................................................................*/
+	/** return whether or not this module should have snapshot saved when saving a macro given the current snapshot mode.*/
+	public boolean satisfiesSnapshotMode(){
+		return (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL);
+	}
+	/*.................................................................................................................*/
+	/** return the value of items to be snapshotted when saving a macro.*/
+	public int getMacroSnapshotMode(){
+		return Snapshot.SNAPALL;
+	}
+	/*.................................................................................................................*/
+	/** return the module responsible for snapshotting when saving a macro.*/
+	public MesquiteModule getMacroSnapshotModule(){
+		return this;
+	}
+	/*.................................................................................................................*/
+	/** return the command string to get the module responsible for snapshotting when saving a macro.*/
+	public String getMacroSnapshotModuleCommand(){
+		return null;
+	}
+
+	public Object doCommand(String commandName, String arguments) {
+		return doCommand(commandName, arguments, CommandChecker.defaultChecker);
+	}
+
+	/*.................................................................................................................*/
+	/** A request for the MesquiteModule to perform a command.  It is passed two strings, the name of the command and the arguments.
+	This should be overridden by any module that wants to respond to a command.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(MesquiteModule.class, null, null, commandName, "showEmployeeTree")) {
+			EmployeeTree etM = (EmployeeTree)findImmediateEmployeeWithDuty(EmployeeTree.class);
+			if (etM == null)
+				etM = (EmployeeTree)hireEmployee(EmployeeTree.class, null);
+			if (etM!=null)
+				etM.showEmployeeTreeWindow(this);
+			return etM;
+		}
+		else if (checker.compare(MesquiteModule.class, "Show employers of this module", null, commandName, "employers")) {
+			logln(getEmployerPath());
+		}
+		else  if (checker.compare(MesquiteModule.class, "Executes a shell script", "[path to script file]", commandName, "executeShellScript")) {
+			String scriptPath = parser.getFirstToken(arguments);
+			if (StringUtil.blank(scriptPath)) 
+				return null;
+			else {
+				ShellScriptUtil.executeAndWaitForShell(scriptPath, getName());
+			}
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "dumpParameterTree")) {
+			System.out.println("=============\nParameters of modules of window of " + getName() + "\n" + listEmployeeParameters("") + "\n=============");
+		}
+		else  if (checker.compare(MesquiteModule.class, "Shows manual in browser", null, commandName, "showManual")) {
+			showManual();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "showCommandPage")) {
+			showWebPage(getCommandPagePath(), true);
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "showMiniInfoWindow")) {
+			return new ModuleInfoWindow(module);
+		} 
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "openSourceInEclipse")) {
+			openSourceInEclipse();
+		}
+		else if (checker.compare(getClass(), "Logs last result string", null, commandName, "logLastResultString")) {
+			logln("Last result:\n" +  lastResultString);
+		}
+		else if (checker.compare(getClass(), "Returns last result string", null, commandName, "getLastResultString")) {
+			return lastResultString;
+		}
+		else if (checker.compare(getClass(), "Returns last MesquiteNumber result", null, commandName, "getLastResult")) {
+			return lastResult;
+		}
+
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "setAssignedID")) {
+			if (getFileCoordinator()!=null && getFileCoordinator().permanentIDExists(arguments))
+				assignedIDString = getPermanentIDString(); // make new one if old exists
+			else
+				assignedIDString = arguments;
+			if (getFileCoordinator()!=null)
+				getFileCoordinator().broadCastAssignedID(this, arguments);
+			else
+				mesquiteTrunk.broadCastAssignedID(this, arguments);
+			return assignedIDString;
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "getWindow")) {
+			return getModuleWindow();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "getContainingWindow")) {
+			return containerOfModule();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "saveMacro")) {
+			MesquiteTrunk.snapshotMode = getMacroSnapshotMode();
+			MesquiteModule mb = getMacroSnapshotModule();
+			if (mb ==null){
+				discreetAlert("The Macro snapshot module can't be found.");
+				return null;
+			}
+			boolean otherModule = !mb.equals(this);
+			String prefix = "";
+			if (otherModule) {
+				prefix = "\t" + getMacroSnapshotModuleCommand()+";" + StringUtil.lineEnding();
+				prefix+="\t\ttell It;" + StringUtil.lineEnding();
+			}
+			String recipe = Snapshot.getSnapshotCommands(getMacroSnapshotModule(), null, "");
+			if (otherModule) {
+				recipe = prefix + recipe + "\t\tendTell;" + StringUtil.lineEnding();
+
+			}
+			MesquiteMacro.saveMacro(this, "Untitled Macro for " + getNameForMenuItem(), 0, recipe);
+			MesquiteTrunk.snapshotMode = Snapshot.SNAPALL;
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "applyMacro")) {
+			MesquiteModuleInfo mmi = getModuleInfo();
+			if (mmi==null)
+				return null;
+			Vector macros = mmi.getMacros();
+			if (macros ==null || macros.size()<=0)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int macroNumber = MesquiteInteger.fromString(arguments, io); 
+			if (macroNumber>=0 && macroNumber<macros.size()) {
+				MesquiteMacro macro = (MesquiteMacro)macros.elementAt(macroNumber);
+				if (macro!=null) {
+					Puppeteer p = new Puppeteer(this);
+					p.applyMacroFile(macro.getPath(), this);
+				}
+			}
+
+			return null;
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "showWindow")) {
+			if (getModuleWindow()!=null) {
+				getModuleWindow().setVisible(true, MesquiteThread.isScripting());
+				//getModuleWindow().repaintAll();
+			}
+			return getModuleWindow();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "showWindowForce")) {
+
+			if (getModuleWindow()!=null) {
+				getModuleWindow().setVisible(true);
+				getModuleWindow().getParentFrame().showFrontWindow();
+				//getModuleWindow().repaint();
+			}
+			return getModuleWindow();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "repaintWindow")) {
+			if (getModuleWindow()!=null) {
+				getModuleWindow().repaintAll();
+			}
+			return null;
+		}
+		else if (checker.compare(MesquiteModule.class, null, null, commandName, "showFile")) {
+			if (arguments==null)
+				return null;
+			FileCoordinator fc = getFileCoordinator();
+			if (fc!=null)
+				return fc.displayFile(MesquiteFile.composePath(getProject().getHomeDirectoryName(), parser.getFirstToken(arguments)), -1);  //
+
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "getFileCoordinator")) {
+			return getFileCoordinator();
+		}
+		else  if (checker.compare(MesquiteModule.class, null, null, commandName, "getProject")) {
+			return getProject();
+		}
+		else if (checker.compare(MesquiteModule.class, null, null, commandName, "getProjectID")) {
+			MesquiteProject proj = getProject();
+			if (proj!=null)
+				return new MesquiteInteger((int)proj.getID());
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "getEmployee")) {
+			MesquiteModule mb =  findEmployeeWithName(parser.getFirstToken(arguments));
+			return mb;
+			//TODO: add getEmployeeWithDuty and pass duty class name
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "getImmediateEmployee")) {
+			MesquiteModule mb =  findEmployeeWithName(parser.getFirstToken(arguments),true);
+			return mb;
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "hireEmployee")) {
+			MesquiteModule mb = hireNamedEmployee(MesquiteModule.class, arguments);
+			return mb;
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "notifyParametersChanged")) {
+			parametersChanged();
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "fireEmployee")) {
+			MesquiteModule mb = findEmployeeWithName(parser.getFirstToken(arguments));
+			if (mb!=null)
+				fireEmployee(mb);
+		}
+		else if  (checker.compare(MesquiteModule.class, null, null, commandName, "resign")) {
+			iQuit();
+		}
+		else if (checker.getAccumulateMode()) {
+			if (this instanceof CommandableOwner){
+				Commandable[] commandables = ((CommandableOwner)this).getCommandablesForAccumulation();
+
+				for (int i=0; commandables!=null && i<commandables.length; i++){
+					checker.addString("<ul><li><strong>Commands for " + getShortClassName(commandables[i].getClass())+ "</strong>");
+					checker.accumulateOnlyFrom(commandables[i].getClass());
+					commandables[i].doCommand(null, null, checker);//���
+					checker.addString("</ul>");
+				}
+			}
+		}
+		else {
+			//AFTERDEMO:
+			if (commandName!=null && !checker.getAccumulateMode() && checker.warnIfNoResponse) {
+				MesquiteMessage.warnProgrammer("Module " + getName() + " (" + (getClass().getName()) + ") did not respond to command " + commandName + " with arguments (" + arguments + ")");
+			}
+		}
+		/* // the following should be place so that superclasses can respond to command, at least where latter is commandable
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+		 */
+		return null;
+	}
+	/*___________________________ Windows __________________________*/
+	/*.................................................................................................................*/
+	/** Returns the window of the MesquiteModule, or if none, the window of the nearest employer with a window.
+	EMBEDDED VERSION  *
+ 	public Frame containerOfModule() {
+		Object f = getParent ();
+		while (! (f instanceof Frame) && !(f==null))
+			f = ((Component) f).getParent ();
+		return  (Frame) f;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the window of the MesquiteModule, or if none, the window of the nearest employer with a window.
+	NONEMBEDDED VERSION*/
+	public MesquiteWindow containerOfModule() {
+		if (getModuleWindow()!=null ) 
+			return getModuleWindow();
+		else if (employer!=null)
+			return employer.containerOfModule();
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the window of the MesquiteModule, or if none, the window of the nearest employer with a window.
+	NONEMBEDDED VERSION*/
+	public MesquiteWindow visibleContainerOfModule() {
+		if (getModuleWindow()!=null && getModuleWindow().isVisible()) 
+			return getModuleWindow();
+		else if (employer!=null)
+			return employer.visibleContainerOfModule();
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the employer with a window*/
+	public MesquiteModule employerWithWindow() {
+		if (getModuleWindow()!=null) 
+			return this;
+		else if (employer!=null)
+			return employer.employerWithWindow();
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the project of the MesquiteModule*/
+	public MesquiteProject getProject() {
+		if (proj!=null) 
+			return proj;
+		else if (employer!=null)
+			return employer.getProject();
+		else {
+			//System.out.println("Error: request by \"" + getName() + "\" for current project, but project is null");
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	/** sets the file of the MesquiteModule*/
+	public void setProject(MesquiteProject proj) {
+		this.proj = proj;
+	}
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow != null)
+			whichWindow.hide();
+		//whichWindow.dispose();
+	}
+	/*.................................................................................................................*/
+	/** Requests a panel to close.*/
+	public void panelGoAway(Panel p) {
+	}
+
+	/*__________________________________________________________*/
+	/*___________________________ Commands __________________________*/
+	/*.................................................................................................................*/
+	/**  Commands are created here.  This method is used in case Mesquite wants to catalogue available Commands
+	(so far, this has not proved useful).  The commands used to be stored within a single static vector, but this caused many otherwise
+	defunct objects (the Commandables that are the object of the commands) to be referenced and thus not GC'd.
+	In the future, commands might be more sophisticated,
+	and passed here will be not only the commandName, but also the parameter types expected and how they are to be called.
+	See the sublibrary for more information about Commands. */
+	public final static MesquiteCommand makeCommand(String commandName, Commandable ownerObject){
+		MesquiteCommand c = new MesquiteCommand(commandName, ownerObject);
+		return c;
+	}
+	/*__________________________________________________________*/
+
+
+
+	/*__________________________________________________________*/
+	/*___________________________ NEXUS file reading/writing __________________________*/
+	/*.................................................................................................................*/
+	/** Adds NEXUS block to the file. */
+	public void addNEXUSBlock(NexusBlock nb){
+		FileCoordinator fCoord = getFileCoordinator();
+		NexusFileInterpreter fi = (NexusFileInterpreter)fCoord.findEmployeeWithDuty(NexusFileInterpreter.class);
+		if (fi!=null) {
+			fi.addBlock(nb);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Remove NEXUS block from the file. */
+	public void removeNEXUSBlock(NexusBlock nb){
+		FileCoordinator fCoord = getFileCoordinator();
+		NexusFileInterpreter fi = (NexusFileInterpreter)fCoord.findEmployeeWithDuty(NexusFileInterpreter.class);
+		if (fi!=null) {
+			fi.removeBlock(nb);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Finds the NEXUS block containing the given FileElement. */
+	public NexusBlock findNEXUSBlock(FileElement e){
+		try{
+			FileCoordinator fCoord = getFileCoordinator();
+
+			NexusFileInterpreter fi = (NexusFileInterpreter)fCoord.findEmployeeWithDuty(NexusFileInterpreter.class);
+			if (fi!=null)
+				return fi.findBlock(e);
+			else return null;
+		}
+		catch(Exception ex){
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Read the nexus block passed (passed only to modules claiming they can read it). */
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments) {return null;} 
+	/** Read the nexus command in the given block (passed only to modules claiming they can read it).  Returns true if successful*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){
+		return false;
+	}
+	/*.................................................................................................................*/
+	private boolean findReaderForCommand (MesquiteFile mf, NexusBlock nBlock, String blockName, String commandName, String command, MesquiteString comment, MesquiteModule mb) {
+		if (mb ==null || mb.getEmployeeVector()== null)
+			return false;
+		Enumeration enumeration=mb.getEmployeeVector().elements(); 
+
+		//look among employees for one that can read
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			MesquiteModule employeeModule = (MesquiteModule)obj;
+			MesquiteModuleInfo mbi = employeeModule.getModuleInfo();
+			if (mbi==null)
+				System.out.println("no employees of ownerModule!!!");
+			else if (mbi.nexusCommandTest!=null) {
+				if (mbi.nexusCommandTest.readsWritesCommand(blockName, commandName, command)) {
+					if (employeeModule.readNexusCommand(mf, nBlock, blockName, command, comment))
+						return true;
+				}
+			}
+		}
+		enumeration=mb.getEmployeeVector().elements(); // WHY ARE ONLY EMPLOYEES OF FILE COORDINATOR USED????
+		//look among employees for one that can read
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			MesquiteModule employeeModule = (MesquiteModule)obj;
+			if (findReaderForCommand(mf, nBlock, blockName, commandName, command, comment, employeeModule)) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Read the unrecognized command, first by looking for a module reading it, second by storing it as unrecognized within the nexus block. */
+	public void readUnrecognizedCommand(MesquiteFile file, NexusBlock nBlock, String blockName, FileBlock block, String commandName, String command, StringBuffer blockComments, MesquiteString comment){
+		if (!findReaderForCommand(file, nBlock, blockName, commandName, command, comment, getFileCoordinator())) {
+			if (")".equals(commandName) || "null".equals(commandName)) //to catch an only file reading/writing problem
+				file.setOpenAsUntitled("There appears to be a problem in the file format.  Illegal NEXUS command (\"" + commandName + "\", in " + blockName + " block). ");
+			else if (";".equals(commandName)) //to catch an only file reading/writing problem
+				;
+			else if (nBlock!=null) 
+				nBlock.storeUnrecognizedCommand(command);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Writes any nexus commands to file. */
+	public boolean writeNexusCommands(MesquiteFile file, String blockName, MesquiteString pending){ 
+		String s = getNexusCommands(file, blockName);
+		if (!StringUtil.blank(s)) {
+			if (pending != null && !pending.isBlank()){
+
+				file.writeLine(pending.toString());
+				pending.setValue("");
+			}
+			file.writeLine(s);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Return any nexus commands belonging to block in file. */
+	public String getNexusCommands(MesquiteFile file, String blockName){ return "";}
+
+	/*.................................................................................................................*/
+	/** check if any adjustments are needed before writing, .e.g. resolve name conflicts.  Format is file type, e.g. NEXUS, NEXML. */
+	public void preWritingCheck(MesquiteFile file, String format){		
+	}
+
+
+	/** Return Mesquite commands that will put the module (approximately) back into its current state. Used
+	so that on file save, a Mesquite block can be saved that will return the user more or less to previous state. */
+	public Snapshot getSnapshot(MesquiteFile file) {  //this allows employees to be dealt with
+		Snapshot temp = new Snapshot();
+
+		/* examples
+ 		temp.addLine("toggleMesquiteBoolean " + mesquiteBoolean.toOffOnString());
+		temp.addLine("setPrimerInfoSource " +  StringUtil.tokenize(primerInfoTask.getClassName()));  
+
+		 */
+
+		return temp;
+	}
+
+	/*__________________________________________________________*/
+	/** for the paging system (may be defunct)*/
+	public void pageModule(MesquiteModule fromModule, boolean persistent){
+		if (!persistent)
+			pagingsEphemeral.addElement(fromModule);
+		else
+			pagingsPersistent.addElement(fromModule);
+	}
+	/*.................................................................................................................*/
+	/** for the paging system (may be defunct)*/
+	public void removePaging(MesquiteModule fromModule){
+		pagingsEphemeral.removeElement(fromModule);
+		pagingsPersistent.removeElement(fromModule);
+	}
+	/*.................................................................................................................*/
+	/** for the paging system (may be defunct)*/
+	protected void returningPage(MesquiteModule pagedModule){
+	}
+	/*.................................................................................................................*/
+	/** for the paging system (may be defunct)*/
+	protected void respondToPaging(){
+		Enumeration enumeration = pagingsEphemeral.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule fromModule = (MesquiteModule)enumeration.nextElement();
+			fromModule.returningPage(this);
+		}
+		enumeration = pagingsPersistent.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule fromModule = (MesquiteModule)enumeration.nextElement();
+			fromModule.returningPage(this);
+		}
+		pagingsEphemeral.removeAllElements();
+	}
+	/*___________________________ Utilities __________________________*/
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	private boolean parametersInPath(MesquiteModule module) {
+		if  (StringUtil.blank(module.getParameters())) {
+			if (module.getEmployeeVector()==null)
+				return false;
+			int num = module.getEmployeeVector().size();
+			for (int i=0; i<num; i++) {
+				Object obj = module.getEmployeeVector().elementAt(i);
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (parametersInPath(mb))
+					return true;
+			}
+		}
+		else
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String accumulateParameters(String spacer) {
+		if (parametersInPath(this)) {
+			String thisBranch;
+			if  (StringUtil.blank(getParameters()))
+				thisBranch = spacer + getName()  + StringUtil.lineEnding();
+			else
+				thisBranch=spacer + getName() + ":  " + getParameters() + StringUtil.lineEnding();
+			if (getEmployeeVector()!=null){
+				int num = getEmployeeVector().size();
+				spacer +="    ";
+				for (int i=0; i<num; i++) {
+					Object obj = getEmployeeVector().elementAt(i);
+					MesquiteModule mb = (MesquiteModule)obj;
+					thisBranch += mb.accumulateParameters(spacer);
+				}
+			}
+			return thisBranch;
+		}
+		else
+			return "";
+	}
+	/** returns current parameters, for logging etc.. */
+	public String getParameters() {
+		return "";
+	}
+	/** returns name plus current parameters, for logging etc.. */
+	public String getNameAndParameters() {
+		String p = getParameters();
+		if (StringUtil.blank(p))
+			return getName();
+		else
+			return getName() + " (" + p + ")";
+	}
+	/*.................................................................................................................*/
+	/** Lists  the parameters of  all employees of this MesquiteModule.*/
+	//TODO: use stringbuffer here (pass it)
+	public String listEmployeeParameters (String spacer) {
+		String thisBranch="";
+
+		thisBranch += spacer +getName() + ": " + getParameters() + StringUtil.lineEnding();
+		int num = employees.size();
+		spacer +="  ";
+		for (int i=0; i<num; i++) {
+			Object obj = employees.elementAt(i);
+			MesquiteModule mb = (MesquiteModule)obj;
+			//thisBranch += spacer + mb.getName() + ": " + mb.getParameters() + StringUtil.lineEnding();
+			thisBranch += mb.listEmployeeParameters(spacer);
+		}
+		return thisBranch;
+	}
+
+	public String listEmployees (String spacer, MesquiteInteger count) {
+		String thisBranch="";
+
+		int num = employees.size();
+		spacer = "    " + spacer;
+		for (int i=0; i<num; i++) {
+			count.increment();
+			Object obj = employees.elementAt(i);
+			MesquiteModule mb = (MesquiteModule)obj;
+			thisBranch += spacer + count.getValue() + "  -- " + mb.getName() + StringUtil.lineEnding();
+			thisBranch += mb.listEmployees(spacer, count);
+		}
+		return thisBranch;
+	}
+	MesquiteModule getDeepEmployee (int target, MesquiteInteger count) {
+		for (int i=0; i<employees.size(); i++) {
+			count.increment();
+			MesquiteModule mb = (MesquiteModule)employees.elementAt(i);
+			if (count.getValue() == target)
+				return mb;
+			MesquiteModule found = mb.getDeepEmployee(target, count);
+			if (found !=null)
+				return found;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns short (not full package) name of class*/
+	public static String getShortClassName(Class classToShow) {
+		if (classToShow == null) {
+			return "";
+		}
+		else {
+			return StringUtil.getLastItem(classToShow.getName(), ".");
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns short (not full package) name of class*/
+	public String getShortClassName() {
+		return StringUtil.getLastItem(getClass().getName(), ".");
+	}
+	/*.................................................................................................................*/
+	/** returns whether name of Module matches passed String.  First checks to see if name matches directly (e.g., "Tree Window"); then checks to see if matches at whole package path
+	(e.g. mesquite.minimal.BasicTreeWindowMaker.BasicTreeWindowMaker); then checks to see if matches at immediate classname (e.g., BasicTreeWindowMaker)*/
+	public boolean nameMatches(String s) {
+		if (s==null)
+			return false;
+		if (s.equalsIgnoreCase(getName()))
+			return true;
+		if (s.equals(getClass().getName()))
+			return true;
+		if (s.equals(getShortClassName()))
+			return true;
+		s = StringUtil.getLastItem(s, ".");
+		if (s!=null && s.equals(getShortClassName()))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether the passed class, or a superclass or interface of it, has the passed name*/
+	public static boolean nameIsInstanceOf(String n, Class c){
+		if (c==null || StringUtil.blank(n))
+			return false;
+		Class sup= c;
+		while (sup!=null) {
+			if (n.equalsIgnoreCase(getShortClassName(sup)))
+				return true;
+			if (n.equalsIgnoreCase(sup.getName()))
+				return true;
+			sup = sup.getSuperclass();
+		}
+		//also check using  Class[] getInterfaces() to see if the class has an interface of the given name
+		Class[] interfaces = c.getInterfaces();
+		for (int i=0; i<interfaces.length; i++) {
+			if (interfaces[i].getName().equalsIgnoreCase(n))
+				return true;
+		}
+		return false;
+
+	}
+	/*.................................................................................................................*/
+	/** returns path to manual.  Null if manual doesn't exist*/
+	public String getManualPath() {
+		if (MesquiteTrunk.isApplet()) 
+			return null;
+		String manualPath;
+		String manP;
+		if (this instanceof MesquiteTrunk)
+			return mesquiteWebSite;
+		else
+			manP= "manual.html";
+		manualPath = getPath() + manP; 
+		File testing = new File(manualPath);
+		if (testing.exists())
+			return manualPath;
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** returns path to page showing the commands.  Null if page doesn't exist*/
+	public String getCommandPagePath() {
+		if (MesquiteTrunk.isApplet()) 
+			return null;
+		if (!CommandChecker.documentationComposed) {
+			CommandChecker checker = new CommandChecker();
+			checker.composeDocumentation();
+		}	
+		String manualPath;
+		manualPath = MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "commands" + MesquiteFile.fileSeparator  + MesquiteModule.getShortClassName(getClass()) + ".html"; 
+
+		File testing = new File(manualPath);
+		if (testing.exists()) {
+			return manualPath;
+		}
+		else {
+			return null;
+		}
+	}
+
+	public static final String mesquiteWebSite = "http://mesquiteproject.wikispaces.com";
+	/*.................................................................................................................*/
+	/** returns path to manual.  Null if manual doesn't exist*/
+	public String getBrowserManualPath() { 
+		if (MesquiteTrunk.isApplet()) 
+			return null;
+		String manualPath;
+		//String manP;
+		if (this instanceof MesquiteTrunk)
+			return mesquiteWebSite;
+		else
+			manualPath= getPath() + "manual.html";
+		File testing = new File(manualPath);
+		if (testing.exists()) {
+			return manualPath;
+		}
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** shows manual for module*/
+	public void showManual() {
+		showWebPage(getBrowserManualPath(), false); 
+	}
+	/*.................................................................................................................*/
+	//TODO: have showWebPage(MesquiteFile file, String path) and showWebPage(MesquiteProject project, String path) to say relative to what (otherwise relative to Mesquite home folder)
+	/** requests browser to show page.  boolean indicates whether the standard auto-generated documentation pages for all the modules should be composed if they haven't been. *
+ 	public static void TEMPshowWebPage(String path, boolean autoCompose) {
+		if (path !=null) {
+			if (MesquiteTrunk.isApplet()) {
+	 			//TODO: FILL THIS IN
+			}
+			else {
+				if (System.getProperty("os.name").startsWith("Mac OS X") && path.indexOf(":/")<0) {
+					osXshowLocalWebPage(path, autoCompose);
+					return;
+				}
+				if (path.indexOf(":/")<0) {//local file
+					File testing = new File(path);
+					if (!testing.exists()) {
+						MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the file could not be found." );
+						return;
+					}
+					path = MesquiteFile.massageFilePathToURL(path);
+				}
+				try {
+					BrowserLauncher.openURL(path);
+				}
+				catch (IOException e) {
+					browserString = null;
+					MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the web browser could not be used properly.  There may be a problem with insufficient memory or the location of the web page or browser." );
+				}
+			}
+		}
+ 	}
+
+ 	/**
+	 * Write the classname to a text file in Mesquite_Folder so that the eclipse plugin
+	 * can read that and open the file.
+	 *
+	 */
+	private void openSourceInEclipse() {
+		String path = getRootPath() + MesquiteFile.fileSeparator + "mesquiteclassname.txt";
+		File mesquiteClassnameFile = new File(path);
+		FileOutputStream fos = null;
+		try {
+			if (!mesquiteClassnameFile.exists()) {
+				mesquiteClassnameFile.createNewFile();
+			}
+			fos = new FileOutputStream(mesquiteClassnameFile);
+			String fullClassName = getClass().getName();
+			fos.write(fullClassName.getBytes());
+		} catch (Exception e) {
+			MesquiteTrunk.mesquiteTrunk.alert("Unable to open the source in Eclipse.");
+		} finally {
+			try {
+				fos.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+	public void showHTMLSnippet(String s){
+		mesquiteTrunk.showHTMLSnippet(s);
+	}
+	/*.................................................................................................................*/ 	
+	public static void showWebPage(String path, boolean autoCompose) {
+		showWebPage(path,autoCompose,true);
+	}
+	/*.................................................................................................................*/
+	public static void showWebPage(String path, boolean autoCompose, boolean removePastNumberSign) {
+		if (path !=null) {
+			if (MesquiteTrunk.isApplet()) {
+				//TODO: FILL THIS IN
+			}
+			else {
+				String pathToCheck = path;
+				if (path.indexOf("#")>0 && removePastNumberSign)
+					pathToCheck = StringUtil.getAllButLastItem(path, "#");
+				path = pathToCheck;  //Todo: this is temporary, as the launching methods don't seem to handle within-page anchors
+				String[] browserCommand = null;
+				boolean remote = path.indexOf(":/")>=0;
+
+				boolean useDesktop = false;
+				if (MesquiteTrunk.getJavaVersionAsDouble()>= 1.6){  // let's check to see if this will work first
+					try {
+						if (Desktop.isDesktopSupported()) {
+							Desktop desktop = Desktop.getDesktop();
+							if (desktop.isSupported(Desktop.Action.BROWSE)) {
+								useDesktop = true;
+							}
+						}
+					} catch (Exception e) {
+					}
+				}
+
+				if (useDesktop){  
+					Desktop d = Desktop.getDesktop();
+					try {
+						URI uri = null;
+						if (path.indexOf("http:/")<0 && path.indexOf("https:/")<0){ // it's a local reference
+							File file = new File(path);
+							uri=file.toURI();
+						} else
+							uri = new URI(path);
+						if (!remote && !CommandChecker.documentationComposed && autoCompose) {
+							CommandChecker checker = new CommandChecker();
+							checker.composeDocumentation();
+						}	
+						d.browse(uri);
+					}
+					catch (IOException e) {
+						browserString = null;
+						MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the web browser could not be used properly.  There may be a problem with insufficient memory or the location of the web page or browser." );
+					} catch (URISyntaxException e) {
+						MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the address was not interpretable." );
+					}
+				}
+				else if (MesquiteTrunk.isMacOSX()){ //Mac OS X
+					if (remote) { //remote OSX file, use browser laucher
+						try {
+							BrowserLauncher.openURL(path);
+						}
+						catch (IOException e) {
+							browserString = null;
+							MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the web browser could not be used properly.  There may be a problem with insufficient memory or the location of the web page or browser." );
+						}
+						return;
+					}
+					else { 
+						if (!remote && !CommandChecker.documentationComposed && autoCompose) {
+							CommandChecker checker = new CommandChecker();
+							checker.composeDocumentation();
+						}	
+						File testing = new File(pathToCheck);
+						if (!testing.exists()) {
+							MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the file could not be found. (" + pathToCheck + ")" );
+							return;
+						}
+						if (!CommandChecker.documentationComposed && autoCompose) {
+							CommandChecker checker = new CommandChecker();
+							checker.composeDocumentation();
+						}	
+						browserString = "open";
+						String brs = "Safari.app";
+						File br = new File("/Applications/Safari.app");
+						if (!br.exists())
+							brs = "Firefox.app";
+						if (!br.exists())
+							brs = "Internet Explorer.app";
+
+						String[] b = {browserString, "-a", brs, path}; 
+
+						browserCommand = b;
+						try {
+							//String[] browserCommand = {browserString, arg1, arg2, arg3};
+							//if (MesquiteTrunk.isMacOSXLeopard())  //bug in 10.5 occasionally prevented Safari from starting
+							//	Runtime.getRuntime().exec(new String[]{browserString, "-a", brs});
+							Runtime.getRuntime().exec(browserCommand); 
+						}
+						catch (IOException e) {
+							browserString = null;
+							MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the web browser could not be used properly.  There may be a problem with insufficient memory or the location of the web page or browser." );
+						}
+					}
+				}
+				else {
+
+					try {
+						BrowserLauncher.openURL(path);
+						return;
+					}
+					catch (IOException e) {
+					}
+					if (!remote) {//local file
+						File testing = new File(pathToCheck);
+						if (!testing.exists()) {
+							MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the file could not be found." );
+							return;
+						}
+						path = MesquiteFile.massageFilePathToURL(path);
+					}
+					browserString = MesquiteFile.checkFilePath(browserString, "Please select a web browser.");
+					if (StringUtil.blank(browserString)){
+						browserString = MesquiteString.queryString(mesquiteTrunk.containerOfModule(), "Enter browser path", "If you wish, enter the path to the browser (E.g., /hard_disk/programs/myBrowser.exe)", "");
+						if (StringUtil.blank(browserString))
+							return;
+					}
+					String[] b = {browserString, path};
+					browserCommand = b;
+					try {
+						//String[] browserCommand = {browserString, arg1, arg2, arg3};
+
+						Runtime.getRuntime().exec(browserCommand); 
+					}
+					catch (IOException e) {
+						browserString = null;
+						MesquiteTrunk.mesquiteTrunk.alert("The requested page could not be shown, because the web browser could not be used properly.  There may be a problem with insufficient memory or the location of the web page or browser." );
+					}
+				}
+			}
+		}
+	}	
+	/*.................................................................................................................*/
+	/** Asks for hierarchy browser panel (File coordinator or trunk should override to return.*/
+	public HPanel getBrowserPanel(){
+		if (employer!=null)
+			return getEmployer().getBrowserPanel();
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** In some way shows the module, either by showing its window or its place in hierarchy*/
+	public void showMe(){
+		if (getModuleWindow()!=null) {
+			getModuleWindow().toFront();
+		}
+		else {
+			HPanel hp;
+			EmployeeTree etM = (EmployeeTree)findImmediateEmployeeWithDuty(EmployeeTree.class);
+			if (etM == null)
+				etM = (EmployeeTree)hireEmployee( EmployeeTree.class, null);
+			if (etM!=null) {
+				hp = etM.showEmployeeTreeWindow(MesquiteTrunk.mesquiteTrunk);
+				if (hp !=null)
+					hp.highlightNode(this);
+			}
+		}
+	}
+	/*__________________________________________________________*/
+	/*_____________________ NEEDED ON MESQUITE STARTUP____________________________*/
+	/*.................................................................................................................*/
+	/** Returns the name of the module in very short form.  For use for column headings and other constrained places.  Unless overridden returns getName()*/
+	public String getVeryShortName(){
+		return getName();
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module for menu items.  Unless overridden returns getName()*/
+	public String getNameForMenuItem(){
+		return getName();
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module*/
+	public abstract String getName();
+	/*.................................................................................................................*/
+	/** Returns the authors of the module.  */
+	public String getAuthors()  {
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && mmi.getPackageAuthors()!=null)
+			return mmi.getPackageAuthors();
+		//if part of standard
+		if (inStandardPackages()) {
+			return MesquiteTrunk.mesquiteTrunk.getAuthors();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number string of the module. */
+	public String  getVersion(){ 
+		if (this instanceof PackageIntro){
+			if (!StringUtil.blank(((PackageIntro)this).getPackageVersion()))
+				return ((PackageIntro)this).getPackageVersion();
+		}
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && !StringUtil.blank(mmi.getPackageVersion()))
+			return mmi.getPackageVersion();
+
+		//if part of standard
+		if (inStandardPackages()) {
+			return MesquiteTrunk.mesquiteTrunk.getVersion();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number string of the module. */
+	public int  getBuildNumberOfPackage(){ 
+		if (this instanceof PackageIntro){
+			if (!StringUtil.blank(((PackageIntro)this).getPackageVersion()))
+				return ((PackageIntro)this).getPackageBuildNumber();
+		}
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && (mmi.getPackageBuildNumber()!=0))
+			return mmi.getPackageBuildNumber();
+
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number string of the module as an integer. */
+	public int  getVersionInt(){ 
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && mmi.getPackageVersionInt()!=0)
+			return mmi.getPackageVersionInt();
+		//if part of standard
+		if (inStandardPackages()) {
+			return MesquiteTrunk.mesquiteTrunk.getVersionInt();
+		}
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/** returns the year released, as a string.  //TODO: SHOULD BE ABSTRACT TO FORCE INCLUSION*/
+	public String  getDateReleased(){ 
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && mmi.getPackageDateReleased()!=null)
+			return mmi.getPackageDateReleased();
+		//if part of standard
+		if (inStandardPackages()) {
+			return MesquiteTrunk.mesquiteTrunk.getDateReleased();
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the URL of the notices file for this module so that it can phone home and check for messages */
+	public String  getHomePhoneNumber(){ 
+		return null;
+	}
+
+	// store info about other packages
+	/*.................................................................................................................*/
+	/** Returns whether or not the module does substantive calculations and thus should be cited.  If true, its citation will
+ 	appear in the citations panel of the windows */
+	public boolean showCitation()  {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns the citation of the module. By default this returns the citation of the package in which the module resides, and returns if
+ 	only if "showCitation" returns true.  The method may be overridden for module-specific citations.*/
+	public String getCitation()  {
+		if (!showCitation())
+			return null;
+		MesquiteModuleInfo mmi = getPackageIntroModule();
+		if (mmi!=null && mmi.getPackageCitation()!=null)
+			return mmi.getPackageCitation();
+		//if part of standard
+		if (inStandardPackages()) {
+			return MesquiteTrunk.mesquiteTrunk.getCitation();
+		}
+		return null;
+	}
+	private boolean inStandardPackages(){
+		//String packageName = StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(getClass().getName(), "."), ".");  //getting package string
+		for (int i=0; i<MesquiteTrunk.standardPackages.length; i++)
+			if (getClass().getName().startsWith("mesquite." + MesquiteTrunk.standardPackages[i]))
+				return true;
+		for (int i=0; i<MesquiteTrunk.standardExtras.length; i++)
+			if (getClass().getName().startsWith("mesquite." + MesquiteTrunk.standardExtras[i]))
+				return true;
+		return false;
+
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module introducing package of modules (e.g., "#aParsimonyIntro")*/
+	public MesquiteModuleInfo getPackageIntroModule(){
+		String packageName = StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(getClass().getName(), "."), ".");  //getting package string
+		return MesquiteTrunk.mesquiteModulesInfoVector.findModule(packageName, PackageIntroInterface.class);
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is a prerelease version.  This returns "TRUE" here, forcing modules to override to claim they are not prerelease */
+	public boolean isPrerelease(){
+		return true;  //LEAVE AS TRUE HERE, forcing overriding
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package. 
+	 * Use NEXTRELEASE if bound for the next release version of Mesquite.*/
+	public int getVersionOfFirstRelease(){
+		return 0;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean getHideable() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module does substantive calculations affecting analysis results, 
+		or only a graphical/UI/input-output module */
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this or employee modules are substantive and prerelease */
+	public boolean anySubstantivePrereleases(){
+		if (isSubstantive() && isPrerelease())
+			return true;
+		if (employees ==null)
+			return false;
+		Enumeration enumeration=employees.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			if (mb.anySubstantivePrereleases())
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether the module is compatible with the current OS, Mesquite system, Java VM, and so on.  If false then the module will not be loaded as a possibility at startup*/
+	public boolean  compatibleWithSystem(){ 
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether the module should be loaded on startup.  This can be overridden to exclude modules from consideration. */  
+	public boolean  loadModule(){ 
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getAppletInfo() {
+		return getName() + ", version " + getVersion();
+	}
+
+	/*.................................................................................................................*/
+	public String toString() {
+		return getName() + " (id# " + getID() +")";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.  //TODO: SHOULD BE ABSTRACT TO FORCE INCLUSION*/
+	public  String getHTMLExplanation()  {
+		if (!StringUtil.blank(getExplanation()))
+			return getExplanation();
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.  //TODO: SHOULD BE ABSTRACT TO FORCE INCLUSION*/
+	public  String getExplanation()  {
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** returns an icon to accompany the explanation of what the module does.  */
+	public  String getFunctionIconPath()  {
+		return "";
+	}
+	public void getSubfunctions(){
+	}
+	public Vector getSubfunctionsVector(){
+		return subfunctions;
+	}
+	public FunctionExplanation registerSubfunction(FunctionExplanation e){
+		subfunctions.addElement(e);
+		return e;
+	}
+	/*.................................................................................................................*/
+	/** returns keywords related to what the module does, for help-related searches. */ 
+	public  String getKeywords()  {
+		return "";
+	}
+
+	/*.................................................................................................................*/
+	/** for FileDirtier interface */
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (getProject()!=null && getProject().getHomeFile()!=null)
+			getProject().getHomeFile().setDirtiedByCommand(true);
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the name of the duty; set by the duty-defining library classes.*/
+	public String getDateAndTime() {
+		long time = System.currentTimeMillis();
+		Date dnow = new Date(time);
+		return dnow.toString();
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the name of the duty; set by the duty-defining library classes.*/
+	public String getDutyName() {
+		return "";
+	}
+	/** Returns a String containing the URL for this module */
+	public String getURLString(){
+		return "";
+	}
+	/** Returns whether or not the URL for this module is a relative reference from the PackageIntro directory */
+	public boolean URLinPackageIntro(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns name of default module for superclass.*/
+	public String[] getDefaultModule (){return null;}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){return null;}
+	/*.................................................................................................................*/
+	/** Returns NexusBlockTest so interpreter knows if this module can interpret a block. */
+	public  NexusBlockTest getNexusBlockTest(){return null;}
+	/*.................................................................................................................*/
+	/** Returns NexusCommandTest so interpreter knows if this module can interpret a command. */
+	public  NexusCommandTest getNexusCommandTest(){return null;}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true;
+	}
+
+	public void processSingleXMLPreference (String tag, String flavor, String content){
+	}
+
+	/*.................................................................................................................*/
+	/** Returns duty Class that module would like to hire immediately upon hiring. If a module wants to present a user with a choice of 
+	employees to hire, it can request a submenu listing these possible employees.  However, if one of these employees would like to immediately
+	(on startup) hire a user-specified subemployee (without having to go through a dialog box, etc.), this employee can indicate this by
+	passing back through getHireSubchoice the duty class of the subemployee it would like to hire.  Mesquite then lists a subsubmenu
+	indicating possible subemployees.  That way, the user not only chooses the employee, but specifies the subemployee.  When
+	the employee is started via startJob, the tokenized string of the name of the
+	module that the user requested as subemployee is passed as an argument.*/
+	public  Class getHireSubchoice(){return null;}
+	/*.................................................................................................................*/
+	/** Returns duty Classes that module should NOT hire immediately upon hiring. */
+	public  Class[] getDontHireSubchoice(){return null;}
+	/*.................................................................................................................*/
+	/** Called during Mesquite startup when the list of available modules is being constructed.*/
+	public void mesquiteStartup(){
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteModuleInfo.java b/Source/mesquite/lib/MesquiteModuleInfo.java
new file mode 100644
index 0000000..afa6f7a
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteModuleInfo.java
@@ -0,0 +1,492 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.duties.*;
+
+import java.util.*;
+import java.net.*;
+
+/* ======================================================================== */
+/** Holds information re a Mesquite module. Since modules are not instantiated until
+hired as employees, they cannot be queried directly for basic information.  Thus, each is instantiated
+temporarily on Mesquite startup, queried for some basic information, which is stored in a MesquiteModulesInfo
+object.  These objects are stored in the mesquiteTrunk's ModuleInfoVector object.<p>
+This approach is somewhat of a remnant of
+MacClade proto4; a more Java-natural approach might be to have getName, getAuthors, etc. be static methods, that way
+there is no need to instantiate the module.*/
+
+public class MesquiteModuleInfo implements Listable, CompatibilityChecker, FunctionExplainable, Prioritizable {
+	String name;
+	String moduleURL;
+	boolean URLinPackageIntroDirectory;
+	String htmlExplanation;
+	String nameForMenuItem;
+	String authors;
+	String version;
+	int versionInt;
+	String explanation;
+	String functionIconPath;
+	String keywords;
+	String dutyName;
+	String[] defaultForSuper;
+	String manualPath;
+	Class mbClass;
+	Class dutyClass;
+	Class hireSubchoice;
+	Class[] dontHireSubchoice;
+	String directoryPath;
+	String splashURL;
+	String packageName;
+	String packageCitation;
+	String packageAuthors;
+	String packageVersion;
+	String packageDateReleased;
+	int packageMesquiteVersionOfFirstRelease;
+	int packageVersionInt;
+	int packageBuildNumber;
+	boolean builtInPackage;
+	String packageURL;
+	String homePhoneNumber;
+	Vector commands;
+	Vector menus;
+	Vector explanations;
+	Vector subfunctions;
+	boolean userChooseable = true;
+	boolean searchableAsModule;
+	boolean splashExists;
+	boolean isPrimaryChoice = false;
+	boolean substantive = true;
+	boolean sCitation = false;
+	boolean prerelease = true;
+	boolean isPackageIntro = false;
+	boolean hideable = true;
+	int versionOfFirstRelease = 0;
+	boolean def = false;
+	int numStarts = 0;
+	NexusBlockTest nexusBlockTest;
+	NexusCommandTest nexusCommandTest;
+	CompatibilityTest compatibilityTest;
+	/** Associated macro records.*/
+	Vector macros; 
+	Vector employeeNeedsVector;  //a vector of registered employee needs, used for documentation/searches of how to do analyses, but perhaps eventually also used in hiring
+	
+	public MesquiteModuleInfo (Class c, MesquiteModule mb, CommandChecker checker, String directoryPath) {  
+		checker =CommandChecker.accumulate(mb, checker);
+		mb.moduleInfo = this;
+ 		this.manualPath = mb.getManualPath();
+  		if (directoryPath!=null)
+  			this.directoryPath = new String(directoryPath); //must come first so subsequent can call module's path method
+		this.splashExists = (mb instanceof PackageIntroInterface && (( PackageIntroInterface)mb).hasSplash());
+		if (mb instanceof PackageIntroInterface)
+			this.splashURL = (( PackageIntroInterface)mb).getSplashURL();
+ 		this.commands = checker.getAccumulatedCommands();
+ 		this.explanations = checker.getAccumulatedExplanations();
+ 		this.menus =checker.getAccumulatedMenus();
+		this.mbClass = c;
+		isPrimaryChoice = mb.requestPrimaryChoice();
+		this.hireSubchoice = mb.getHireSubchoice();
+		this.dontHireSubchoice = mb.getDontHireSubchoice();
+		this.name = mb.getName(); //�
+		this.nameForMenuItem = mb.getNameForMenuItem(); //�
+ 		this.authors =mb.getAuthors();//�
+ 		this.version =mb.getVersion();//�
+ 		
+ 		this.versionOfFirstRelease = mb.getVersionOfFirstRelease();
+ 		this.explanation =mb.getExplanation();//�
+ 		this.sCitation = mb.showCitation();
+ 		this.userChooseable =mb.getUserChooseable();//�
+ 		this.substantive = mb.isSubstantive();
+ 		this.prerelease = mb.isPrerelease();
+ 		this.dutyClass =mb.getDutyClass();//�
+ 		this.dutyName =mb.getDutyName();//�
+ 		this.defaultForSuper = mb.getDefaultModule();
+ 		this.keywords = mb.getKeywords();
+ 		this.versionInt = mb.getVersionInt();
+		if (mb instanceof PackageIntroInterface){
+			this.packageCitation = (( PackageIntroInterface)mb).getPackageCitation();
+			this.packageName =  (( PackageIntroInterface)mb).getPackageName();
+			this.packageAuthors = (( PackageIntroInterface)mb).getPackageAuthors();
+			this.packageVersion = (( PackageIntroInterface)mb).getPackageVersion();
+			this.packageDateReleased = (( PackageIntroInterface)mb).getPackageDateReleased();
+			this.builtInPackage = (( PackageIntroInterface)mb).isBuiltInPackage();
+			this.packageMesquiteVersionOfFirstRelease = (( PackageIntroInterface)mb).getVersionOfFirstRelease();
+			this.packageVersionInt = (( PackageIntroInterface)mb).getPackageVersionInt();
+			this.packageBuildNumber = (( PackageIntroInterface)mb).getPackageBuildNumber();
+			this.packageURL = (( PackageIntroInterface)mb).getPackageURL();
+			isPackageIntro = true;
+			hideable = (( PackageIntroInterface)mb).getHideable();
+ 		}
+  		mb.mesquiteStartup();
+		this.nexusBlockTest = mb.getNexusBlockTest();//�
+ 		this.nexusCommandTest = mb.getNexusCommandTest();//�
+		this.compatibilityTest = mb.getCompatibilityTest();
+		this.searchableAsModule = mb.getSearchableAsModule();
+		try{
+			mb.getEmployeeNeeds();
+		}
+		catch (java.lang.NoClassDefFoundError e){
+		}
+		this.functionIconPath = mb.getFunctionIconPath();
+		this.moduleURL = mb.getURLString();
+		this.URLinPackageIntroDirectory = mb.URLinPackageIntro();
+		this.htmlExplanation = mb.getHTMLExplanation();
+		this.employeeNeedsVector = mb.getEmployeeNeedsVector();
+		this.homePhoneNumber = mb.getHomePhoneNumber();
+		String localPhoneBookPath = directoryPath + "phoneBook.txt";
+		if (MesquiteFile.fileExists(localPhoneBookPath)) {
+			String phoneNumber = MesquiteFile.getFileContentsAsString(localPhoneBookPath);
+			if (StringUtil.notEmpty(phoneNumber)) {
+				this.homePhoneNumber = phoneNumber;
+			}
+		}
+		if (employeeNeedsVector != null)
+			for (int i = 0; i< employeeNeedsVector.size(); i++){
+				EmployeeNeed need = (EmployeeNeed)employeeNeedsVector.elementAt(i);
+				need.setRequestor(this);
+			}
+		mb.getSubfunctions();
+		this.subfunctions = mb.getSubfunctionsVector();
+	//timer3.end();
+	}
+	/** returns name of Module */
+	public String getName() {
+		return name;
+	}
+	/** returns HTML Explanation of Module */
+	public String getHTMLExplanation() {
+		return htmlExplanation;
+	}
+	/** returns URL of Module */
+	public String getURLString() {
+		return moduleURL;
+	}
+	/** Returns whether or not the URL for this module is a relative reference from the PackageIntro directory */
+	public boolean URLinPackageIntro(){
+		return URLinPackageIntroDirectory;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the URL of the notices file for this module so that it can phone home and check for messages */
+	public String  getHomePhoneNumber(){ 
+		return homePhoneNumber;
+	}
+
+
+	/** returns whether name of Module matches passed String.  First checks to see if name matches directly (e.g., "Tree Window"); then checks to see if matches at whole package path
+	(e.g. mesquite.minimal.BasicTreeWindowMaker.BasicTreeWindowMaker); then checks to see if matches at immediate classname (e.g., BasicTreeWindowMaker)*/
+	public boolean nameMatches(String s) {
+		if (s==null)
+			return false;
+		if (s.equalsIgnoreCase(name))
+			return true;
+		if (s.equals(getModuleClass().getName()))
+			return true;
+		if (s.length()>0 && s.charAt(0)=='#')
+			s = s.substring(1, s.length());
+		if (s.equals(getShortClassName()))
+			return true;
+		s = StringUtil.getLastItem(s, ".");
+		if (s!=null && s.equals(getShortClassName()))
+			return true;
+		return false;
+	}
+	public Vector getEmployeeNeedsVector(){
+		return employeeNeedsVector;
+	}
+	public boolean hasNeeds(){
+		return employeeNeedsVector != null && employeeNeedsVector.size()>0;
+	}
+	public boolean getSearchableAsModule(){
+		return searchableAsModule;
+	}
+	public Vector getSubfunctionsVector(){
+		return subfunctions;
+	}
+	public String getKeywords(){
+		return keywords;
+	}
+	public boolean isDefault(){
+		return def;
+	}
+	public void setAsDefault(boolean d){
+		def = d;
+	}
+	/** Returns information about a package of modules*/
+ 	public boolean getHideable(){
+ 		return hideable;
+ 	}
+	/** Returns information about a package of modules*/
+ 	public boolean getIsPackageIntro(){
+ 		return isPackageIntro;
+ 	}
+	/** Returns information about a package of modules*/
+ 	public String getPackageCitation(){
+ 		return packageCitation;
+ 	}
+ 	public String getPackageAuthors(){
+ 		return packageAuthors;
+ 	}
+ 	public String getPackageVersion(){
+ 		return packageVersion;
+ 	}
+	public int getVersionOfFirstRelease(){
+ 		return versionOfFirstRelease;
+ 	}
+	public String getPackageDateReleased(){
+ 		return packageDateReleased;
+ 	}
+	public boolean isBuiltInPackage(){
+ 		return builtInPackage;
+ 	}
+	public int getMesquiteVersionOfFirstPackageRelease(){
+ 		return packageMesquiteVersionOfFirstRelease;
+ 	}
+ 	
+ 	public int getPackageVersionInt(){
+ 		return packageVersionInt;
+ 	}
+ 	public int getPackageBuildNumber(){
+ 		return packageBuildNumber;
+ 	}
+ 	public String getPackageURL(){
+ 		return packageURL;
+ 	}
+ 	public boolean showCitation(){
+ 		return sCitation;
+ 	}
+	public void addMacro(MesquiteMacro macro){
+		if (macros == null)
+			macros = new Vector();
+		macros.addElement(macro);
+	}
+	public void removeMacro(MesquiteMacro macro){
+		if (macros != null)
+			macros.removeElement(macro);
+	}
+	public Vector getMacros(){
+		return macros;
+	}
+	public int getNumStarts() {
+		return numStarts;
+	}
+	public void setNumStarts(int numStarts) {
+		this.numStarts = numStarts;
+	}
+	public void incrementNumStarts() {
+		 numStarts++;
+	}
+
+	
+	/** returns name to be used in menu item to hire the module.  By default this is the same as the name of the module, but can be different if the
+	module overrides its own getNameForMenuItem method.*/
+	public String getNameForMenuItem() {
+		return nameForMenuItem;
+	}
+	/** returns the vector of command descriptions accumulated during startup */
+	public Vector getMenus () {
+		return menus;
+	}
+	/** returns the vector of command descriptions accumulated during startup */
+	public Vector getCommands () {
+		return commands;
+	}
+	/** returns the vector of command descriptions accumulated during startup */
+	public Vector getExplanations () {
+		return explanations;
+	}
+	/** returns whether it is a module that appears in lists for the user to choose as an option (otherwise, it can be chosen only directly by other modules, or by CommandRecord.nr */
+	public boolean getUserChooseable(){
+		return userChooseable;
+	}
+ 	/** Returns the default module for the superclass (duty class)*/
+	public String[] getDefaultModule () {
+		return defaultForSuper;
+	}
+ 	/** Returns the authors string of the module*/
+ 	public String getAuthors() { 
+ 		return authors;
+   	}
+
+ 	/** returns the version number string of the module*/
+ 	public String getVersion() { 
+ 		return version;
+   	}
+ 	/** returns the version number of the module as an integer*/
+ 	public int getVersionInt() { 
+ 		return versionInt;
+   	}
+ 	/** returns whether the module is marked as substantive*/
+ 	public boolean isSubstantive(){
+ 		return substantive;
+ 	}
+ 	/** returns whether the module is marked as release*/
+ 	public boolean isPrerelease(){
+ 		return prerelease;
+ 	}
+
+ 	/** returns an explanation of what the module does*/
+ 	public String getExplanation() { 
+ 		return explanation;
+   	}
+ 	public String getFunctionIconPath(){
+ 		return functionIconPath;
+ 	}
+ 	/** returns path to manual*/
+ 	public String getManualPath() { 
+ 		return manualPath;
+   	}
+ 	/** returns path to directory of module*/
+ 	public String getDirectoryPath() { 
+ 		return directoryPath;
+   	}
+ 	/** returns path to package of module*/
+ 	public String getPackagePath() { 
+ 		String s= StringUtil.getAllButLastItem(directoryPath, MesquiteFile.fileSeparator);
+ 		s= StringUtil.getAllButLastItem(s, MesquiteFile.fileSeparator);
+		if (s==null)
+			return null;
+		else
+			return s + MesquiteFile.fileSeparator;
+   	}
+
+ 	/** returns the class of the module*/
+ 	public Class getModuleClass() { 
+ 		return mbClass;
+   	}
+ 	/** returns the complete String name of the class of the module (e.g., mesquite.minimal.BasicTreeWindowMaker.BasicTreeWindowMaker)*/
+ 	public String getClassName() { 
+ 		return mbClass.getName();
+   	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module introducing package of modules (e.g., "#aParsimonyIntro")*/
+ 	public MesquiteModuleInfo getPackageIntroModule(){
+ 		String packageName = StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(getClassName(), "."), ".");  //getting package string
+ 		return MesquiteTrunk.mesquiteModulesInfoVector.findModule(packageName, PackageIntroInterface.class);
+ 	}
+
+ 	/** returns the immediate classnameof the module (e.g., BasicTreeWindowMaker)*/
+ 	public String getShortClassName() { 
+ 		return MesquiteModule.getShortClassName(mbClass);
+   	}
+ 	/** Returns the name of the duty performed (usually defined in duty defining superclass)*/
+ 	public String getDutyName() {
+ 		return dutyName;
+   	}
+ 	/** returns the duty class*/
+ 	public Class getDutyClass() { 
+ 		return dutyClass;
+   	}
+   	public NexusBlockTest getNexusBlockTest(){
+   		return nexusBlockTest;
+   	}
+   	
+ 	/** returns the class of the employee desired*/
+ 	public Class getHireSubchoice() { 
+ 		return hireSubchoice;
+   	}
+ 	/** returns the classes that the employee shouldn't represent*/
+ 	public Class[] getDontHireSubchoice() { 
+ 		return dontHireSubchoice;
+   	}
+	/** Returns whether module is compatible with given object*/
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+ 		return isCompatible(obj, project, prospectiveEmployer, null);
+ 	}
+ 	/** Returns whether module is compatible with given object*/
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report) {
+ 		if (compatibilityTest==null) {
+ 			return true;
+ 		}
+ 		else {
+ 			boolean c = compatibilityTest.isCompatible(obj, project, prospectiveEmployer, report);
+ 			return c;
+ 		}
+   	}
+	/** returns whether this module is one of the primary that appears in first-level choices */
+   	public boolean isPrimary(Class dutyClass){
+		if (isPrimaryChoice)
+			return true;
+		String[] defaults = MesquiteTrunk.mesquiteModulesInfoVector.getDutyDefaults(dutyClass);
+		if (defaults == null)
+			return false;
+		for (int i = 0; i<defaults.length; i++)
+			if (nameMatches(defaults[i]))
+				return true;
+   		return false;  
+   	}
+   	
+	/** returns whether this module is one of the primary that appears in first-level choices; for Prioritizable interface */
+	public boolean isFirstPriority(Class c){
+		return isPrimary(c);
+	}
+
+ 	/** Returns whether module is instance of particular duty-defining class*/
+	public boolean doesDuty (Class dutyClass) {
+		if (dutyClass == null)
+			return false;
+		if (dutyClass == MesquiteModule.class)
+			return true;
+		if (mbClass!=null) {
+			if (dutyClass.isInterface()){
+				if (dutyClass.isAssignableFrom(mbClass))
+					return true;
+			}
+			
+			for (Class superC = mbClass; superC != MesquiteModule.class; superC = superC.getSuperclass())
+				if (superC == dutyClass)
+					return true;
+			return false;
+		}
+		else
+			return false;
+	}
+ 	/** Returns whether module is instance of particular duty-defining class*/
+	public boolean doesADuty (Class[] dutyClasses) {
+		if (dutyClasses == null)
+			return false;
+		for (int i=0; i<dutyClasses.length; i++){
+			if (doesDuty(dutyClasses[i]))
+					return true;
+		}
+			return false;
+	}
+	public String getPackageName(){
+		return packageName;
+	}
+ 	/** Returns whether module has splash screen*/
+	public boolean hasSplash () {
+		return splashExists;
+	}
+	public String getSplashURL(){
+		return splashURL;
+	}
+	public void explainSplash(){
+		if (!StringUtil.blank(splashURL)) {
+			String s;
+			if (packageName!=null)
+				s= "This banner indicates that the package \"" + packageName +"\" is currently installed.  Would you like to see the package's introductory web page?";
+			else
+				s= "This banner refers to a package that is currently installed.  Would you like to see the package's introductory web page?";
+			if (AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Installed Package", s, "Web Page", "No"))
+				MesquiteTrunk.mesquiteTrunk.showWebPage(splashURL, false);
+		} 
+		else if (packageName!=null)
+			MesquiteTrunk.mesquiteTrunk.alert("This banner indicates that the package \"" + packageName +"\" is currently installed");
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteNumber.java b/Source/mesquite/lib/MesquiteNumber.java
new file mode 100644
index 0000000..fd64928
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteNumber.java
@@ -0,0 +1,1294 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+/* ======================================================================== */
+/**This class is used to store numbers flexibly, so that system doesn't need to know whether int, long or double.
+Automatically upgrades calculations to use long or double as needed.  Because they have the overhead of objects,
+it is best to avoid their wanton proliferation.  If an array is needed, better to use the NumberArray,
+which behaves similarly but stores the data as a primitive type arrays.  
+Most of the methods in MesquiteNumber use the incoming parameter 
+	as a guide to how the data should be stored.  Thus there are int, long, and
+	double versions of many methods.  Calculations involving mixed types automatically
+	upgrade the storage to the bigger type. */
+public class MesquiteNumber implements Listable, WithStringDetails{
+	private int intValue=0;
+	private long longValue=0;
+	private double doubleValue=0;
+	private int valueClass = 0;
+	public static final int INT = 0;
+	public static final int LONG = 1;
+	public static final int DOUBLE = 2;
+	private boolean unassignedFlag = true; // have inappplicable?
+	private boolean infiniteFlag = false;
+	private MesquiteNumber temp = null;
+	private MesquiteNumber temp2 = null;
+	private MesquiteNumber[] auxiliaries = null;
+	private String name = null;
+	public static long totalCreated = 0;
+	boolean watchpoint = false;
+	public MesquiteNumber() {
+		setToUnassigned();
+		totalCreated++;
+	}
+	public MesquiteNumber(int value) {
+		this.intValue=value;
+		unassignedFlag = value==MesquiteInteger.unassigned;
+		valueClass =INT;
+		totalCreated++;
+	}
+
+	public MesquiteNumber(long value) {
+		this.longValue=value;
+		unassignedFlag = value==MesquiteLong.unassigned;
+		valueClass = LONG;
+		totalCreated++;
+	}
+	public MesquiteNumber(double value) {
+		this.doubleValue=value;
+		unassignedFlag = value==MesquiteDouble.unassigned;
+		valueClass = DOUBLE;
+		totalCreated++;
+	}
+	public MesquiteNumber(MesquiteNumber toCopy) {
+		this(toCopy, false);
+	}
+	public MesquiteNumber(MesquiteNumber toCopy, boolean copyAuxiliaries) {
+		setValue(toCopy);
+		setName(toCopy.getName());
+		copyAuxiliaries(toCopy.getAuxiliaries());
+		totalCreated++;
+	}
+	public void setWatchpoint(boolean w){
+		watchpoint = w;
+	}
+	public int getValueClass(){
+		return valueClass;
+	}
+	public void copyFrom(MesquiteNumber n){
+		intValue = n.intValue;
+		longValue = n.longValue;
+		doubleValue = n.doubleValue;
+		valueClass = n.valueClass;
+		unassignedFlag = n.unassignedFlag;
+		infiniteFlag = n.infiniteFlag;
+		name = n.name;
+		watchpoint = n.watchpoint;
+	}
+	public void copyFrom(MesquiteParameter n){
+		intValue = 0;
+		longValue = 0;
+		doubleValue = n.getValue();
+		unassignedFlag = doubleValue==MesquiteDouble.unassigned;
+		valueClass = DOUBLE;
+		name = n.getName();
+	}
+	public MesquiteNumber[] getAuxiliaries(){  // in case a complex result with multiple numbers is needed
+		return auxiliaries;
+	}
+	public void copyAuxiliaries(MesquiteNumber[] aux){  // in case a complex result with multiple numbers is needed
+		if (aux == null){
+			auxiliaries = null;
+			return;
+		}
+		if (auxiliaries == null || auxiliaries.length != aux.length)
+			auxiliaries = new MesquiteNumber[aux.length];
+		for (int i = 0; i< auxiliaries.length; i++) {
+			if (auxiliaries[i] == null){
+				auxiliaries[i] = new MesquiteNumber(aux[i]);
+			}
+			else
+				auxiliaries[i].copyFrom(aux[i]);
+		}
+	}
+	public void copyAuxiliaries(MesquiteParameter[] aux){  // in case a complex result with multiple numbers is needed
+		if (aux == null){
+			auxiliaries = null;
+			return;
+		}
+		if (auxiliaries == null || auxiliaries.length != aux.length)
+			auxiliaries = new MesquiteNumber[aux.length];
+		for (int i = 0; i< auxiliaries.length; i++) {
+			if (auxiliaries[i] == null)
+				auxiliaries[i] = new MesquiteNumber();
+			auxiliaries[i].copyFrom(aux[i]);
+			if (aux[i].getConstrainedTo() != null && auxiliaries[i].getName()!= null)
+				auxiliaries[i].setName(auxiliaries[i].getName() + " (= " + aux[i].getConstrainedTo().getName() + ")");
+		}
+	}
+	public void setName(String n){
+		name = n;
+	}
+	public String getName(){
+		return name;
+	}
+	/*--------------------------------GET/SET--------------------------*/
+	/** Returns the stored value as an int */
+	public int getIntValue() {
+		if (isInfinite())
+			return MesquiteInteger.infinite;
+		if (isUnassigned())
+			return MesquiteInteger.unassigned;
+
+		if (valueClass==INT)
+			return intValue;
+		else if (valueClass == LONG)
+			return (int)(longValue);
+		else if (valueClass == DOUBLE)
+			return (int)doubleValue;
+//		return java.lang.Math.round(doubleValue);
+		else return 0;
+	}
+	/*...........................................................*/
+	/** Returns the stored value as a long */
+	public long getLongValue() {
+		if (isInfinite())
+			return MesquiteLong.infinite;
+		if (isUnassigned())
+			return MesquiteLong.unassigned;
+		if (valueClass==INT)
+			return intValue;
+		else if (valueClass == LONG)
+			return longValue;
+		else if (valueClass == DOUBLE)
+			return (long)doubleValue;
+		else return 0;
+	}
+	/*...........................................................*/
+	/** Returns the stored value as a double */
+	public double getDoubleValue() {
+		if (isInfinite())
+			return MesquiteDouble.infinite;
+		if (isUnassigned())
+			return MesquiteDouble.unassigned;
+		if (valueClass==INT)
+			return intValue;
+		else if (valueClass == LONG)
+			return (longValue);
+		else if (valueClass == DOUBLE)
+			return doubleValue;
+		else return 0;
+	}
+	/** Sets the stored value to the passed integer */
+	public void setValue(int v) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to " + v);
+		intValue = v;
+		valueClass = INT;
+		unassignedFlag = (v==MesquiteInteger.unassigned);
+		infiniteFlag = (v==MesquiteInteger.infinite);
+	}
+
+	/** Sets the stored value to the passed long */
+	public void setValue(long v) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to " + v);
+		longValue = v;
+		valueClass =LONG;
+
+		unassignedFlag = (v==MesquiteLong.unassigned);
+		infiniteFlag = (v==MesquiteLong.infinite);
+	}
+
+	/** Sets the stored value to the passed double */
+	public void setValue(double v) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to " + v);
+		doubleValue = v;
+		valueClass=DOUBLE;
+		unassignedFlag = (v==MesquiteDouble.unassigned);
+		infiniteFlag = (v==MesquiteDouble.infinite);
+	}
+
+	/** Sets the values to be the same as the passed MesquiteNumber */
+	public void setValue(MesquiteNumber v) {
+		if (v==null)
+			return;
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to " + v);
+		valueClass=v.valueClass;
+		intValue=v.intValue;
+		longValue=v.longValue;
+		doubleValue=v.doubleValue;
+		unassignedFlag = v.unassignedFlag;
+		infiniteFlag = v.infiniteFlag;
+	}
+	/*...........................................................*/
+	/** Sets the value to be that represented by the string*/
+	public void setValue(String toBeParsed) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to " + toBeParsed);
+		if (toBeParsed==null || toBeParsed.equalsIgnoreCase("unassigned") || toBeParsed.equalsIgnoreCase("?") || toBeParsed.equalsIgnoreCase("estimate")) //"?" included Apr 02
+			setToUnassigned();
+		else if (toBeParsed.equalsIgnoreCase("infinite")|| toBeParsed.equalsIgnoreCase("i"))
+			setToInfinite();
+		else if (toBeParsed.indexOf(".")>=0) {
+			setValue(MesquiteDouble.fromString(toBeParsed));
+		}
+		else {
+			try {
+				int d = Integer.parseInt(toBeParsed);
+				setValue(d);
+			}
+			catch (NumberFormatException e) {
+				try {
+					long d = Long.valueOf(toBeParsed).longValue();
+					setValue(d);
+				}
+				catch (NumberFormatException e2) {
+					setToUnassigned();
+				}
+			}
+		}
+	}
+	/*...........................................................*/
+	/** Sets the value to unassigned of this and auxiliaries */
+	public void deassignAllValues() {
+		setToUnassigned();
+		if (auxiliaries != null){
+			for (int i = 0; i< auxiliaries.length; i++)
+				auxiliaries[i].setToUnassigned();
+		}
+	}
+	/*...........................................................*/
+	/** Sets the value to unassigned */
+	public void setToUnassigned() {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to unassigned");
+		unassignedFlag = true;
+		infiniteFlag = false;
+		intValue=MesquiteInteger.unassigned;
+		longValue=MesquiteLong.unassigned;
+		doubleValue=MesquiteDouble.unassigned;
+		valueClass =INT;
+	}
+	/*...........................................................*/
+	/** Sets the value to Infinity */
+	public void setToInfinite() {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value to infinity");
+		infiniteFlag = true;
+		unassignedFlag = false;
+		intValue=MesquiteInteger.infinite;
+		longValue=MesquiteLong.infinite;
+		doubleValue=MesquiteDouble.infinite;
+		valueClass =INT;
+	}
+	/*--------------------------------QUERY--------------------------*/
+	/** Returns true if value is unassigned */
+	public boolean isUnassigned() {
+		if (unassignedFlag)
+			return true;
+		else if (valueClass==INT) {
+			return intValue==MesquiteInteger.unassigned;
+		}
+		else if (valueClass == LONG) {
+			return longValue==MesquiteLong.unassigned;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue==MesquiteDouble.unassigned;
+		}
+		return false;
+	}
+	/** Returns true if value is infinite */
+	public boolean isInfinite() {
+		if (infiniteFlag)
+			return true;
+		else if (valueClass==INT) {
+			return intValue==MesquiteInteger.infinite;
+		}
+		else if (valueClass == LONG) {
+			return longValue==MesquiteLong.infinite;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue==MesquiteDouble.infinite;
+		}
+		return false;
+	}
+	/** Returns true if value is combinable (not unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable() {
+		if (isUnassigned() || isInfinite())
+			return false;
+		else if (valueClass==INT) {
+			return (MesquiteInteger.isCombinable(intValue));
+		}
+		else if (valueClass == LONG) {
+			return (MesquiteLong.isCombinable(longValue));
+		}
+		else if (valueClass == DOUBLE) {
+			return (MesquiteDouble.isCombinable(doubleValue));
+		}
+		return false;
+	}
+	/** Returns true if value is combinable (not unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable(int v) {
+		return (MesquiteInteger.isCombinable(v));
+	}
+	/** Returns true if value is combinable (not unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable(long v) {
+		return (MesquiteLong.isCombinable(v));
+	}
+	/** Returns true if value is combinable (not unassigned, infinite, inapplicable, impossible) */
+	public boolean isCombinable(double v) {
+		return (MesquiteDouble.isCombinable(v));
+	}
+	/*...........................................................*/
+	/** Returns true if value is 0 */
+	public boolean isZero() {
+		if (isUnassigned() || isInfinite())
+			return false;
+		else if (valueClass==INT) {
+			return intValue==0;
+		}
+		else if (valueClass == LONG) {
+			return longValue==0;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue==0;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** Returns true if value is negative */
+	public boolean isNegative() {
+		if (isUnassigned() || isInfinite())
+			return false;
+		else if (valueClass==INT) {
+			return intValue<0;
+		}
+		else if (valueClass == LONG) {
+			return longValue<0;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue<0;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** Changes sign of value */
+	public void changeSign() {
+		if (isUnassigned() || isInfinite())
+			return;
+		else if (valueClass==INT) {
+			intValue = -intValue;
+		}
+		else if (valueClass == LONG) {
+			longValue = -longValue;
+		}
+		else if (valueClass == DOUBLE) {
+			doubleValue = -doubleValue;
+		}
+	}
+	/*--------------------------------ARITHMETICS--------------------------*/
+	/**  Sets to absolute value */
+	public void abs() {
+		if (valueClass==INT) {
+			intValue = Math.abs(intValue);
+		}
+		else if (valueClass == LONG)
+			longValue = Math.abs(longValue);
+		else if (valueClass == DOUBLE)
+			doubleValue = Math.abs(doubleValue);
+
+	}
+	/** Adds value to current value */
+	public void add(int toAdd) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (add)  " + toAdd);
+		if (valueClass==INT)
+			setValue(MesquiteInteger.add(intValue, toAdd));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.add(longValue, MesquiteLong.toLong(toAdd)));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.add(doubleValue, MesquiteDouble.toDouble(toAdd)));
+	}
+
+	/**  Adds value to current value */
+	public void add(long toAdd) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (add)  " + toAdd);
+		if (valueClass==INT)
+			setValue(MesquiteLong.add(MesquiteLong.toLong(intValue), toAdd));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.add(longValue, toAdd));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.add(doubleValue, MesquiteDouble.toDouble(toAdd)));
+	}
+
+	/**  Adds value to current value */
+	public void add(double toAdd) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (add)  " + toAdd);
+		if (valueClass==INT)
+			setValue(MesquiteDouble.add(MesquiteDouble.toDouble(intValue), toAdd));
+		else if (valueClass == LONG)
+			setValue(MesquiteDouble.add(MesquiteDouble.toDouble(longValue), toAdd));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.add(doubleValue, toAdd));
+	}
+	/**  Adds value to current value */
+	public void add(MesquiteNumber toAdd) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (add)  " + toAdd);
+		if (toAdd!=null) {
+			if (toAdd.valueClass==INT)
+				add(toAdd.intValue);
+			else if (toAdd.valueClass == LONG)
+				add(toAdd.longValue);
+			else if (toAdd.valueClass == DOUBLE)
+				add(toAdd.doubleValue);
+		}
+	}
+	/*...........................................................*/
+	/**  Subtracts value from current value */
+	public void subtract(int toSubtract) {  
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (subtract)  " + toSubtract);
+		if (valueClass==INT)
+			setValue(MesquiteInteger.subtract(intValue, toSubtract));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.subtract(longValue, MesquiteLong.toLong(toSubtract)));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.subtract(doubleValue, MesquiteDouble.toDouble(toSubtract)));
+	}
+
+	/**  Subtracts value from current value */
+	public void subtract(long toSubtract) { 
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (subtract)  " + toSubtract);
+		if (valueClass==INT)
+			setValue(MesquiteLong.subtract(MesquiteLong.toLong(intValue), toSubtract));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.subtract(longValue, toSubtract));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.subtract(doubleValue, MesquiteDouble.toDouble(toSubtract)));
+	}
+
+	/**  Subtracts value from current value */
+	public void subtract(double toSubtract) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (subtract)  " + toSubtract);
+		if (valueClass==INT)
+			setValue(MesquiteDouble.subtract(MesquiteDouble.toDouble(intValue), toSubtract));
+		else if (valueClass == LONG)
+			setValue(MesquiteDouble.subtract(MesquiteDouble.toDouble(longValue), toSubtract));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.subtract(doubleValue, toSubtract));
+	}
+	/**  Subtracts value from current value */
+	public void subtract(MesquiteNumber toSubtract) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (subtract)  " + toSubtract);
+		if (toSubtract!=null) {
+			if (toSubtract.valueClass==INT)
+				subtract(toSubtract.intValue);
+			else if (toSubtract.valueClass == LONG)
+				subtract(toSubtract.longValue);
+			else if (toSubtract.valueClass == DOUBLE)
+				subtract(toSubtract.doubleValue);
+		}
+	}
+	/*...........................................................*/
+	/** Multiplies current value by passed value */
+	public void multiplyBy(int toMultiply) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (multiplyBy)  " + toMultiply);
+		if (valueClass==INT)
+			setValue(MesquiteInteger.multiply(intValue, toMultiply));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.multiply(longValue, MesquiteLong.toLong(toMultiply)));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.multiply(doubleValue, MesquiteDouble.toDouble(toMultiply)));
+	}
+
+	/** Multiplies current value by passed value */
+	public void multiplyBy(long toMultiply) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (multiplyBy)  " + toMultiply);
+		if (valueClass==INT)
+			setValue(MesquiteLong.multiply(MesquiteLong.toLong(intValue), toMultiply));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.multiply(longValue, toMultiply));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.multiply(doubleValue, MesquiteDouble.toDouble(toMultiply)));
+	}
+
+	/** Multiplies current value by passed value */
+	public void multiplyBy(double toMultiply) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (multiplyBy)  " + toMultiply);
+		if (valueClass==INT)
+			setValue(MesquiteDouble.multiply(MesquiteDouble.toDouble(intValue), toMultiply));
+		else if (valueClass == LONG)
+			setValue(MesquiteDouble.multiply(MesquiteDouble.toDouble(longValue), toMultiply));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.multiply(doubleValue, toMultiply));
+	}
+	/** Multiplies current value by passed value */
+	public void multiplyBy(MesquiteNumber toMultiply) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (multiplyBy)  " + toMultiply);
+		if (toMultiply==null)
+			return;
+		if (toMultiply.valueClass==INT)
+			multiplyBy(toMultiply.intValue);
+		else if (toMultiply.valueClass == LONG)
+			multiplyBy(toMultiply.longValue);
+		else if (toMultiply.valueClass == DOUBLE)
+			multiplyBy(toMultiply.doubleValue);
+	}
+	/*...........................................................*/
+	/** Divides current value by passed value */
+	public void divideBy(int toDivide) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (divideBy)  " + toDivide);
+		if (valueClass==INT)
+			setValue(MesquiteInteger.divide(intValue, toDivide));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.divide(longValue, MesquiteLong.toLong(toDivide)));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.divide(doubleValue, MesquiteDouble.toDouble(toDivide)));
+	}
+
+	/** Divides current value by passed value */
+	public void divideBy(long toDivide) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (divideBy)  " + toDivide);
+		if (valueClass==INT)
+			setValue(MesquiteLong.divide(MesquiteLong.toLong(intValue), toDivide));
+		else if (valueClass == LONG)
+			setValue(MesquiteLong.divide(longValue, toDivide));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.divide(doubleValue, MesquiteDouble.toDouble(toDivide)));
+	}
+
+	/** Divides current value by passed value */
+	public void divideBy(double toDivide) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (divideBy)  " + toDivide);
+		if (valueClass==INT)
+			setValue(MesquiteDouble.divide(MesquiteDouble.toDouble(intValue), toDivide));
+		else if (valueClass == LONG)
+			setValue(MesquiteDouble.divide(MesquiteDouble.toDouble(longValue), toDivide));
+		else if (valueClass == DOUBLE)
+			setValue(MesquiteDouble.divide(doubleValue, toDivide));
+	}
+	/** Divides current value by passed value */
+	public void divideBy(MesquiteNumber toDivide) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (divideBy)  " + toDivide);
+		if (toDivide!=null) {
+			
+			if (toDivide.valueClass==INT)
+				divideBy(toDivide.intValue);
+			else if (toDivide.valueClass == LONG)
+				divideBy(toDivide.longValue);
+			else if (toDivide.valueClass == DOUBLE)
+				divideBy(toDivide.doubleValue);
+		}
+	}
+	/*--------------------------------INEQUALITIES--------------------------*/
+	/** Determines if current value equals passed value.  If "mustBeCombinable" is true, then
+	returns false if either current value or passed value are not combinable. Otherwise, returns
+	true if the stored values are identical*/
+	public boolean equals(int value, boolean mustBeCombinable) {
+		if (mustBeCombinable && (!isCombinable() || !isCombinable(value)))
+			return false;
+		else if (valueClass==INT) 
+			return (intValue==value);
+		else if (valueClass == LONG)
+			return (longValue==MesquiteLong.toLong(value));
+		else if (valueClass == DOUBLE)
+			return (doubleValue==MesquiteDouble.toDouble(value));
+		return false;
+	}
+	/** Determines if current value equals passed value.  If "mustBeCombinable" is true, then
+	returns false if either current value or passed value are not combinable. Otherwise, returns
+	true if the stored values are identical*/
+	public boolean equals(long value, boolean mustBeCombinable) {
+		if (mustBeCombinable && (!isCombinable() || !isCombinable(value)))
+			return false;
+		else if (valueClass==INT) 
+			return (MesquiteLong.toLong(intValue)==value);
+		else if (valueClass == LONG)
+			return (longValue==value);
+		else if (valueClass == DOUBLE)
+			return (doubleValue==MesquiteDouble.toDouble(value));
+		return false;
+	}
+	/** Determines if current value equals passed value.  If "mustBeCombinable" is true, then
+	returns false if either current value or passed value are not combinable. Otherwise, returns
+	true if the stored values are identical*/
+	public boolean equals(double value, boolean mustBeCombinable) {
+		if (mustBeCombinable && (!isCombinable() || !isCombinable(value)))
+			return false;
+		else if (valueClass==INT) 
+			return (MesquiteDouble.toDouble(intValue)==value);
+		else if (valueClass == LONG)
+			return (MesquiteDouble.toDouble(longValue)==value);
+		else if (valueClass == DOUBLE)
+			return (doubleValue==value);
+		return false;
+	}
+	/** Determines if current value equals passed value.*/
+	public boolean equals(MesquiteNumber n) {
+		if (unassignedFlag!=n.unassignedFlag)  
+			return false;
+		if (infiniteFlag!=n.infiniteFlag)  
+			return false;
+		if (valueClass==INT)
+			return n.equals(intValue, false);
+		else if (valueClass == LONG) 
+			return  n.equals(longValue, false);
+		else if (valueClass == DOUBLE)
+			return n.equals(doubleValue, false);
+		return false;
+	}
+	/*...........................................................*/
+	/** Sets this number to incoming if current is greater (used to find minima). */
+	public void setMeIfIAmMoreThan(MesquiteNumber n) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmMoreThan)  " + n);
+		if (isUnassigned() || isInfinite())
+			setValue(n);
+		else if (n.valueClass==INT) {
+			setMeIfIAmMoreThan(n.intValue);
+		}
+		else if (n.valueClass == LONG) {
+			setMeIfIAmMoreThan(n.longValue);
+		}
+		else if (n.valueClass == DOUBLE) {
+			setMeIfIAmMoreThan(n.doubleValue);
+		}
+	}
+	/*...........................................................*/
+	/** Sets this number to incoming if current is greater (used to find minima). */
+	public void setMeIfIAmMoreThan(int value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmMoreThan)  " + value);
+		if (isUnassigned() || isInfinite())
+			setValue(value);
+		else if (!MesquiteInteger.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if (intValue>value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if (longValue>value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue>value)
+				setValue(value);
+		}
+	}
+	/** Sets this number to incoming if current is greater (used to find minima). */
+	public void setMeIfIAmMoreThan(long value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmMoreThan)  " + value);
+		if (isUnassigned() || isInfinite())
+			setValue(value);
+		else if (!MesquiteLong.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if (intValue>value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if (longValue>value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue>value)
+				setValue(value);
+		}
+	}
+	/** Sets this number to incoming if current is greater (used to find minima). */
+	public void setMeIfIAmMoreThan(double value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmMoreThan)  " + value);
+		if (isUnassigned() || isInfinite())
+			setValue(value);
+		else if (!MesquiteDouble.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if (intValue>value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if (longValue>value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue>value)
+				setValue(value);
+		}
+	}
+	/*...........................................................*/
+	/** Sets this number to incoming if current is less (used to find maxima). */
+	public void setMeIfIAmLessThan(MesquiteNumber n) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmLessThan)  " + n);
+		if (isUnassigned())
+			setValue(n);
+		else if (isInfinite())
+			return;
+		else if (n.valueClass==INT) 
+			setMeIfIAmLessThan(n.intValue);
+		else if (n.valueClass == LONG) 
+			setMeIfIAmLessThan(n.longValue);
+		else if (n.valueClass == DOUBLE) 
+			setMeIfIAmLessThan(n.doubleValue);
+	}
+	/*...........................................................*/
+	/** Sets this number to incoming if current is less (used to find maxima). */
+	public void setMeIfIAmLessThan(int value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmLessThan)  " + value);
+		if (isUnassigned())
+			setValue(value);
+		else if (isInfinite())
+			return;
+		else if (!MesquiteInteger.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if (intValue<value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if (longValue<(long)value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue<(double)value)
+				setValue(value);
+		}
+	}
+	/** Sets this number to incoming if current is less (used to find maxima). */
+	public void setMeIfIAmLessThan(long value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmLessThan)  " + value);
+		if (isUnassigned())
+			setValue(value);
+		else if (isInfinite())
+			return;
+		else if (!MesquiteLong.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if ((long)intValue<value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if (longValue<value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue<(double)value)
+				setValue(value);
+		}
+	}
+	/** Sets this number to incoming if current is less (used to find maxima). */
+	public void setMeIfIAmLessThan(double value) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setMeIfIAmLessThan)  " + value);
+		if (isUnassigned())
+			setValue(value);
+		else if (isInfinite())
+			return;
+		else if (!MesquiteDouble.isCombinable(value))
+			return;
+		else if (valueClass==INT) {
+			if ((double)intValue<value)
+				setValue(value);
+		}
+		else if (valueClass == LONG) {
+			if ((double)longValue<value)
+				setValue(value);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValue<value)
+				setValue(value);
+		}
+	}	/*...........................................................*/
+	/** Returns true if current value is less than value of n . */
+	public boolean isBetterThan(MesquiteNumber n, boolean biggerIsBetter) {
+		if (biggerIsBetter)
+			return isMoreThan(n);
+		return isLessThan(n);
+	}
+
+	/*...........................................................*/
+	/** Returns true if current value is less than value of n . */
+	public boolean isLessThan(MesquiteNumber n) {
+		if (n==null) return false;
+		if (isUnassigned() || isInfinite()) return false;
+		if (n.isUnassigned() || n.isInfinite()) return true;
+		if (valueClass==INT) {
+			if (n.valueClass==INT)
+				return intValue<n.intValue;
+			else if (n.valueClass == LONG)
+				return intValue<n.longValue;
+			else if (n.valueClass == DOUBLE)
+				return intValue<n.doubleValue;
+		}
+		else if (valueClass == LONG) {
+			if (n.valueClass==INT)
+				return longValue<n.intValue;
+			else if (n.valueClass == LONG)
+				return longValue<n.longValue;
+			else if (n.valueClass == DOUBLE)
+				return longValue<n.doubleValue;
+		}
+		else if (valueClass == DOUBLE) {
+			if (n.valueClass==INT)
+				return doubleValue<n.intValue;
+			else if (n.valueClass == LONG)
+				return doubleValue<n.longValue;
+			else if (n.valueClass == DOUBLE)
+				return doubleValue<n.doubleValue;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** Returns true if current value is more than value of n . */
+	public boolean isMoreThan(MesquiteNumber n) {
+		if (n==null) return false;
+		if (isUnassigned() || n.isInfinite()) return false;
+		if (n.isUnassigned() || isInfinite()) return true;
+		if (valueClass==INT) {
+			if (n.valueClass==INT)
+				return intValue>n.intValue;
+				else if (n.valueClass == LONG)
+					return intValue>n.longValue;
+					else if (n.valueClass == DOUBLE)
+						return intValue>n.doubleValue;
+		}
+		else if (valueClass == LONG) {
+			if (n.valueClass==INT)
+				return longValue>n.intValue;
+				else if (n.valueClass == LONG)
+					return longValue>n.longValue;
+					else if (n.valueClass == DOUBLE)
+						return longValue>n.doubleValue;
+		}
+		else if (valueClass == DOUBLE) {
+			if (n.valueClass==INT)
+				return doubleValue>n.intValue;
+				else if (n.valueClass == LONG)
+					return doubleValue>n.longValue;
+					else if (n.valueClass == DOUBLE)
+						return doubleValue>n.doubleValue;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** Returns true if current value is less than d . */
+	public boolean isLessThan(double d) {
+		if (isUnassigned() || isInfinite()) return false;
+		if (MesquiteDouble.isUnassigned(d) || MesquiteDouble.isInfinite(d)) return true;
+		if (!MesquiteDouble.isCombinable(d) || !isCombinable())
+			return false;
+		if (valueClass==INT) {
+			return intValue<d;
+		}
+		else if (valueClass == LONG) {
+			return longValue<d;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue<d;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** Returns true if current value is more than d . */
+	public boolean isMoreThan(double d) {
+		if (isUnassigned() || MesquiteDouble.isInfinite(d)) return false;
+		if (MesquiteDouble.isUnassigned(d) || isInfinite()) return true;
+		if (!MesquiteDouble.isCombinable(d) || !isCombinable())
+			return false;
+		if (valueClass==INT) {
+			return intValue>d;
+		}
+		else if (valueClass == LONG) {
+			return longValue>d;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValue>d;
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	/** Checks to see if the number value is less than min (in which case min is reset) or greater than max
+	(in which case max is reset).  If it is the first time this function is called for this particular use, 
+	the values of min and max are set to the value . */
+	public static void checkMinMax (MesquiteBoolean first, MesquiteNumber min, MesquiteNumber max, MesquiteNumber value){
+		if (first.getValue()) {
+			min.setValue(value);
+			max.setValue(value);
+			first.setValue(false);
+		}
+		else {
+			max.setMeIfIAmLessThan(value);
+			min.setMeIfIAmMoreThan(value);
+		}
+	}
+	/*...........................................................*/
+	/** Returns true if current value is more than value of n . */
+	public static void exchangeValues(MesquiteNumber n1, MesquiteNumber n2) {
+		MesquiteNumber ntemp = new MesquiteNumber(n1);
+		n1.setValue(n2);
+		n2.setValue(ntemp);
+	}
+	/*_________________________________________________*/
+	private int mag(long d){
+		if (d<10)
+			return 1;
+		else if (d<100)
+			return 10;
+		else if (d<1000)
+			return 100;
+		else if (d<10000)
+			return 1000;
+		else
+			return 10000;
+	}
+	/*--------------------------------BYTE CONVERSION--------------------------*/
+	public static byte[] longToBytes(long dt, byte[] bytes){
+		if (bytes == null || bytes.length!=8)
+			bytes = new byte[8];
+		for (int i = 0; i<8; i++) 
+			bytes[i] =getByte(dt, i); //storing block of bits
+		return bytes;
+	}
+	public static byte[] shortToBytes(short dt, byte[] bytes){
+		if (bytes == null || bytes.length!=2)
+			bytes = new byte[2];
+		for (int i = 0; i<2; i++) 
+			bytes[i] =getByte(dt, i); //storing block of bits
+		return bytes;
+	}
+	public static byte[] doubleToBytes(double d, byte[] bytes){
+		long dt =Double.doubleToLongBits(d);
+		if (bytes == null || bytes.length!=8)
+			bytes = new byte[8];
+		for (int i = 0; i<8; i++) 
+			bytes[i] =getByte(dt, i); //storing block of bits
+		return bytes;
+	}
+	public static double bytesToDouble(byte[] bytes ){
+		if (bytes == null || bytes.length!=8)
+			return 0;
+		long temp = 0L; //ready to be filled
+		for (int i = 0; i<8; i++) {
+			temp |= putByteInLong(bytes[i], i);
+		}
+		return Double.longBitsToDouble(temp);
+	}
+	public static long bytesToLong(byte[] bytes ){
+		if (bytes == null || bytes.length!=8)
+			return 0;
+		long temp = 0L; //ready to be filled
+		for (int i = 0; i<8; i++) {
+			temp |= putByteInLong(bytes[i], i);
+		}
+		return temp
+		;
+	}
+	public static long putByteInLong(byte b, int whichByte){
+		long L = ((long) b) & 0x00000000000000FFL;
+		L <<= whichByte*8;
+		return L;
+	}
+	public static long getByteLong(long original, int whichByte){
+		original >>>= whichByte*8;
+		return original & 0x00000000000000FFL;
+	}
+	public static byte getByte(long original, int whichByte){
+		original >>>= whichByte*8;
+		return (byte)(original & 0x00000000000000FFL);
+	}
+	/*--------------------------------RULERS--------------------------*/
+	/** For a ruler or marked scale that is with start point at min, end at max, and at least minTicks marks, what is first scale mark? */
+	public void setToFirstScaleMark(MesquiteNumber min, MesquiteNumber max, int minTicks) {
+		if (min == null|| max == null)
+			return;
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setToFirstScaleMark)  ");
+		if (!min.isCombinable() || !max.isCombinable()) {
+			setToUnassigned();
+			return;
+		}
+		if ((min.valueClass == INT || min.valueClass == LONG) && (max.valueClass == INT || max.valueClass == LONG)) {
+			//all integer
+			long inc = 1;
+			long spanL = max.getLongValue()-min.getLongValue(); //finding tick increment first
+
+			if (spanL> minTicks) {
+				int magn = mag(spanL);
+				if (magn == 1 || spanL/magn>minTicks) {
+					inc = magn;
+				}
+				else {
+					inc = magn/5;
+				}
+			}
+			if (inc == 1) {
+				valueClass = LONG;
+				setValue(min.getLongValue()-1);
+				return;
+			}
+			else {
+				long maxL = max.getLongValue();
+				// find something divisible by 10
+				valueClass = LONG;
+				int magn = mag(maxL);
+				setValue(min.getLongValue()/inc*inc/magn*magn - magn);
+				return;
+			}
+
+		}
+		double span = max.getDoubleValue()-min.getDoubleValue();
+		double mag = MesquiteDouble.magnitude(span);
+		if (span/mag < minTicks) //ensure at least this many tick marks
+			mag /= 10.0;
+		setValue(MesquiteDouble.nextOfMagnitude(mag, min.getDoubleValue()));
+	}
+	/** For a ruler or marked scale that is with start point at min, end at max, and at least minTicks marks, what is increment between ticks? */
+	public void setToScaleIncrement(MesquiteNumber min, MesquiteNumber max, int minTicks) {
+		if (watchpoint) MesquiteMessage.printStackTrace("MesquiteNumber changed value (setToScaleIncrement)  ");
+		if (min == null|| max == null)
+			return;
+		if (!min.isCombinable() || !max.isCombinable()) {
+			setToUnassigned();
+			return;
+		}
+		if ((min.valueClass == INT || min.valueClass == LONG) && (max.valueClass == INT || max.valueClass == LONG)) {
+			//all integer
+			long spanL = max.getLongValue()-min.getLongValue();
+			if (spanL<= minTicks) {
+				valueClass = INT;
+				setValue(1);
+				return;
+			}
+			else {
+				int inc =1;
+				int magn = mag(spanL);
+				if (magn == 1 || spanL/magn>minTicks) {
+					inc = magn;
+				}
+				else {
+					inc = magn/5;
+				}
+				setValue(inc);
+				return;
+			}
+		}
+		double span = max.getDoubleValue()-min.getDoubleValue();
+		double mag = MesquiteDouble.magnitude(span);
+		if (span/mag < minTicks) //ensure at least this many tick marks
+			mag /= 10.0;
+		setValue(mag);
+	}
+	/*...........................................................*/
+	/** this method is used to return the object's value as an integer between
+	0 and numUnits, scaling it according to its position between min and max's values.
+	This is useful for graphing and so on, since the graphing program doesn't have to 
+	know the data types of this object, min or max in order to calculate the appropriate pixel placement 
+	in a graph, for instance */
+	public int setWithinBounds(MesquiteNumber min, MesquiteNumber max, int numUnits) {
+		if (min==null || max == null)
+			return 0;
+		MesquiteNumber div = new MesquiteNumber(max);
+		div.subtract(min);
+		if (div.isZero())
+			return 0;
+		MesquiteNumber num = new MesquiteNumber(this);
+		num.subtract(min);
+		num.divideBy(div);
+		num.multiplyBy(numUnits);
+		return num.getIntValue();
+		//	MesquiteModule.mesquiteTrunk.alert("out of getBounds within setWithinBounds" + " /min " + min.toString() + " /this " + this.toString() + " /max " + max.toString());
+	}
+	/*...........................................................*/
+	/** this method does the inverse of setWithinBounds.  
+	 */
+	public double getUnboundedValue(MesquiteNumber min, MesquiteNumber max, int numUnits) {
+		if (min==null || max == null)
+			return 0;
+		if (numUnits==0)
+			return 0;
+		MesquiteNumber num = new MesquiteNumber(this);
+		num.divideBy(numUnits);  // fraction of bound that this is
+		MesquiteNumber mult = new MesquiteNumber(max);
+		mult.subtract(min);
+		num.multiplyBy(mult);
+		num.add(min);
+		return num.getDoubleValue();
+	}
+	/*...........................................................*/
+	/** this method is used to set the object's value according to value, a number between 0 and bound,
+	so that the difference between min and max is scaled to bound */
+	public void findWithinBounds(MesquiteNumber min, MesquiteNumber max, int value, int bound) {
+		if (min==null || max == null)
+			setToUnassigned();
+		else if (value>=0 && value<= bound && min.isLessThan(max) && bound>0) {
+			setValue(max);
+			subtract(min);
+			divideBy(bound);
+			multiplyBy(value);
+			add(min);
+		}
+	}
+	/*...........................................................*/
+	/** this method is returns which interval the value occurs in, if the given range 
+	is cut into the given number of intervals.
+	This is useful for graphing histograms that group into intervals. */
+	public int findInterval(MesquiteNumber min, MesquiteNumber max, int numIntervals) {
+		if ((!isLessThan(min)) && !isMoreThan(max)) {
+			if (temp2 == null)
+				temp2 = new MesquiteNumber(max);
+			else
+				temp2.setValue(max);
+			temp2.subtract(min);
+			if (temp2.isZero())
+				return 0;
+			temp2.divideBy(numIntervals);
+			if (temp == null)
+				temp = new MesquiteNumber(this);
+			else
+				temp.setValue(this);
+			temp.subtract(min);
+			temp.divideBy(temp2);
+			return temp.getIntValue();
+		}
+		//	MesquiteModule.mesquiteTrunk.alert("out of getBounds within setWithinBounds" + " /min " + min.toString() + " /this " + this.toString() + " /max " + max.toString());
+		return -1;
+	}
+	/*...........................................................*/
+	/** this method is returns which interval the value occurs in, if the given range 
+	is cut into intervals of width "unit".
+	This is useful for graphing histograms that group into intervals. */
+	public int findInterval(MesquiteNumber min, MesquiteNumber unit) {
+		if (!isLessThan(min)) {
+			if (temp == null)
+				temp = new MesquiteNumber(this);
+			else
+				temp.setValue(this);
+			temp.subtract(min);
+			temp.divideBy(unit);
+			return temp.getIntValue();
+		}
+		//	MesquiteModule.mesquiteTrunk.alert("out of getBounds within setWithinBounds" + " /min " + min.toString() + " /this " + this.toString() + " /max " + max.toString());
+		return -1;
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string representation of this number*/
+	public String toString() {
+		if (isUnassigned())
+			return "?"; //changed from "unassigned" June 02
+		else if (isInfinite())
+			return "infinite";
+		else if (valueClass==INT)
+			return MesquiteInteger.toString(intValue);// + " (int)";
+		else if (valueClass == LONG)
+			return MesquiteLong.toString(longValue);// + " (long)";
+		else if (valueClass == DOUBLE)
+			return MesquiteDouble.toString(doubleValue);// + " (double)";
+		else return "";
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string representation of an array of MesquiteNumbers*/
+	public static String toString(MesquiteNumber[] numbers) {
+		if (numbers==null)
+			return null;
+		if (numbers.length==0)
+			return "";
+		StringBuffer sb = new StringBuffer("[");
+		for (int i=0; i<numbers.length; i++){
+			sb.append(numbers[i].toString());
+			if (i<numbers.length-1)
+				sb.append(" ");
+		}
+		sb.append("]");
+		return sb.toString();
+		
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string representation of the names*/
+	public String toStringNames() {
+		String s = "";
+
+		if (name != null)
+			s += name;
+		s += "\t";
+		if (auxiliaries != null){
+			for (int i = 0; i< auxiliaries.length; i++){
+				if (auxiliaries[i] != null && auxiliaries[i].getName() != null)
+					s += auxiliaries[i].getName();
+				s += "\t";
+			}
+		}
+		return s;
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string representation of this number*/
+	public String toStringWithDetails() {
+		String s = "";
+
+		if (name != null)
+			s += name;
+		s += "\t";
+		s += toString();
+		s += "\t";
+		if (auxiliaries != null){
+			for (int i = 0; i< auxiliaries.length; i++){
+				if (auxiliaries[i] != null && auxiliaries[i].getName() != null)
+					s += auxiliaries[i].getName();
+				s += "\t";
+				if (auxiliaries[i] != null)
+					s += auxiliaries[i].toString();
+				s += "\t";
+			}
+		}
+		return s;
+	}
+	/*--------------------------------STRINGS--------------------------*/
+	/** Returns string representation of this number.  Number is indicated as 0 if number is double && abs(number)< range*0.0001*/
+	public String toString(double range) {
+		if (isUnassigned())
+			return "?"; //changed from "unassigned" June 02
+		else if (isInfinite())
+			return "infinite";
+		else if (valueClass==INT)
+			return MesquiteInteger.toString(intValue);// + " (int)";
+		else if (valueClass == LONG)
+			return MesquiteLong.toString(longValue);// + " (long)";
+		else if (valueClass == DOUBLE)
+			return MesquiteDouble.toStringInRange(doubleValue, range);// + " (double)";
+		else return "";
+	}
+	public String toString(int digits, boolean allowExponentialNotation) {
+		
+		if (isUnassigned())
+			return "?"; //changed from "unassigned" June 02
+		else if (isInfinite())
+			return "infinite";
+		else if (valueClass==INT)
+			return MesquiteInteger.toString(intValue);// + " (int)";
+		else if (valueClass == LONG)
+			return MesquiteLong.toString(longValue);// + " (long)";
+		else if (valueClass == DOUBLE)
+			return MesquiteDouble.toStringDigitsSpecified(doubleValue, digits, allowExponentialNotation);// + " (double)";
+		else return "";
+
+	}
+
+	/*...........................................................*/
+	/** Returns type of number stored here*/
+	public String valueTypeToString() {
+		if (isUnassigned())
+			return "?"; //changed from "unassigned" June 02
+		else if (isInfinite())
+			return "infinite";
+		else if (valueClass==INT)
+			return "int";
+		else if (valueClass == LONG)
+			return "long";
+		else if (valueClass == DOUBLE)
+			return "double";
+		else return "";
+	}
+	/** Presents dialog querying user for a number, with no check for minimum and maximum */
+	public static MesquiteNumber queryNumber(MesquiteWindow parent, String title, String message, MesquiteNumber current) {
+		MesquiteNumber io = new MesquiteNumber(current);
+		//NumberDialog id = new NumberDialog(parent, title, message, io);
+		//	id.dispose();
+		QueryDialogs.queryMesquiteNumber(parent,title,message,io);
+		return io;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquitePDFFile.java b/Source/mesquite/lib/MesquitePDFFile.java
new file mode 100644
index 0000000..ccc1789
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePDFFile.java
@@ -0,0 +1,476 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+This class originally by P. Midford March 2005, based on iText example files and MesquitePrintJob.
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified May 02 especially for annotations*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.util.*;
+import java.awt.print.*;
+import java.io.*;
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+
+
+/* ======================================================================== */
+
+/**
+ at author Peter Midford
+ */
+public class MesquitePDFFile {
+
+	int fitToPage;
+	PrintJob job1;
+	PrinterJob job2;
+	Document document = null;
+	String name;
+	MesquiteWindow frame;
+	Dimension dimension;
+	PageFormat pf;
+	String pdfPathString = "";
+	com.lowagie.text.Rectangle pageRectangle;
+	PdfWriter writer;
+	PdfContentByte cb;
+	PdfTemplate tp;
+
+	/*.......................................................................*/
+	protected MesquitePDFFile(MesquiteWindow w, String name) {
+		this.frame = w;
+		if (name == null)
+			this.name = "Print to PDF";
+		else
+			this.name = name;
+	}	
+
+	/**
+	@param frame the MesquiteWindow to copy to a PDF file
+	@param name string holding the title of the *file choice menu*
+	@param fitToPage integer controlling whether the image is fit to the page
+	 */
+	public static MesquitePDFFile getPDFFile(MesquiteWindow w, String name) {
+		MesquitePDFFile f = new MesquitePDFFile(w,name);
+		if (f.prepareDocument())
+			return f;
+		else
+			return null;
+	}
+
+	/**
+	@return boolean
+	 */
+	public boolean prepareDocument() {
+
+		// This is different because a file is being created
+		String suggestedFileName;
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(this.frame, this.name, FileDialog.SAVE);   // Save File dialog box
+		suggestedFileName = "untitled.pdf";
+		fdlg.setFile(suggestedFileName);
+
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setVisible(true);
+		if (fdlg.getFile() == null) {
+			// fdlg.dispose();
+			MainThread.decrementSuppressWaitWindow();
+			return false;
+		}
+		pdfPathString = fdlg.getDirectory()+fdlg.getFile();
+		// fdlg.dispose();
+		// Back to getting page settings.
+
+		job2 = PrinterJob.getPrinterJob();
+		if (job2 == null) {
+			MesquiteTrunk.mesquiteTrunk.alert("Error: no printer job returned in prepareDocument");
+			MainThread.decrementSuppressWaitWindow();
+			return false;
+		}
+		pf = job2.defaultPage();
+		if (pf == null) {
+			MesquiteTrunk.mesquiteTrunk.alert("Error: no default page returned in prepareDocument");
+			MainThread.decrementSuppressWaitWindow();
+			return false;
+
+		}
+		MainThread.decrementSuppressWaitWindow();
+		return true;		
+	}
+
+
+	/**
+	@param fitToPage
+	 */
+	public void setSizeOrientation(int fitToPage) {
+		this.fitToPage = fitToPage;
+		if (job2 == null) 
+			return;
+		else {
+			switch (fitToPage) {
+			case MesquitePrintJob.AUTOFIT: {   //fits landscape or portrait depending on what requires least shrinkage
+				break;
+			}
+			case MesquitePrintJob.FIT_LANDSCAPE: { //fits into landscape
+				pf.setOrientation(PageFormat.LANDSCAPE);
+				break;
+			}
+			case MesquitePrintJob.FIT_PORTRAIT: {  //fits into portrait
+				pf.setOrientation(PageFormat.PORTRAIT);
+				break;
+			}
+			default: {    //prints at current size using page setup (thus, possibly over multiple pages)
+				PageFormat tmp = job2.pageDialog(pf);
+				if (tmp == null) 
+					MesquiteTrunk.mesquiteTrunk.alert("Warning: no page dialog returned in prepareDocument - will use default");
+				else
+					pf = tmp;	
+			}
+			}
+			return;
+		}
+	}			
+
+	/** Utility
+	 *@return Array
+	 */
+	private float[] zeroPageMatrix() {
+		float zero[] = new float[6];
+		for (int i=0; i<6; i++)
+			zero[i] = 0.0f;
+		return zero;
+	}
+
+	/**
+	 *@arg document Document object representing the output file
+	 * Add metadata to the PDF fle
+	 */
+	private void addMetaData(Document document) {
+		document.addCreator("Mesquite " + MesquiteModule.getMesquiteVersion() + " using portions of " + document.getVersion());
+		try {
+			String uname = System.getProperty("user.name");
+			document.addAuthor(uname);
+		}
+		catch (SecurityException e) {
+			document.addAuthor("Unknown");
+		}
+		document.addKeywords("Mesquite");   // more later
+		//document.addTitle(this.component.getParent().getName());  // ToDo: get the window's actual title 
+	}
+
+	/**
+	@arg s String holds the text that the pdf file will contain
+	@arg font java.awt.Font the font is specified this way for compatibility with the similar method in MesquitePrintJob
+	 */
+	public void printText(String s, java.awt.Font font) {
+		final String exceptionMessage = "Error, an exception occurred while creating the pdf text document: ";
+		if (s == null || font == null)
+			return;
+
+		//do the translation from logical to physical font here		
+		//currently, the only font this method ever gets called with is "Monospaced",PLAIN,10.  So the
+		//translation effort here will be minimal		
+		int desiredFontFamily;   // "Monospaced" isn't defined in com.lowagie.text.Font
+		if (font.getFamily().equals("Monospaced")) 
+			desiredFontFamily = com.lowagie.text.Font.COURIER;
+		else desiredFontFamily = com.lowagie.text.Font.TIMES_ROMAN;
+		com.lowagie.text.Font textFont;
+		switch (font.getStyle()) {
+		case java.awt.Font.BOLD: {
+			textFont = new com.lowagie.text.Font(desiredFontFamily,font.getSize(),com.lowagie.text.Font.BOLD);
+			break;
+		}
+		case java.awt.Font.ITALIC: {
+			textFont = new com.lowagie.text.Font(desiredFontFamily,font.getSize(),com.lowagie.text.Font.ITALIC);
+			break;
+		}
+		case java.awt.Font.PLAIN: {
+			textFont = new com.lowagie.text.Font(desiredFontFamily,font.getSize(),com.lowagie.text.Font.NORMAL);
+			break;
+		}
+		default: {
+			textFont = new com.lowagie.text.Font(desiredFontFamily,font.getSize(),com.lowagie.text.Font.BOLDITALIC);
+		}
+		}  
+		document = new Document();
+		try{
+			PdfWriter.getInstance(document,new FileOutputStream(pdfPathString));
+			addMetaData(document);
+			document.open();
+			document.add(new Paragraph(s,textFont));
+		}
+		catch (DocumentException de) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + de.getMessage());
+		}
+		catch (IOException ioe) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage  + ioe.getMessage());
+		}
+		this.end();
+	}
+
+
+
+
+	/**
+	@arg component Component to display
+	@arg dim
+	@return Graphics for pdf output
+	 */
+	public Graphics getPDFGraphicsForComponent(Component component, Dimension dim) {
+		final String exceptionMessage = "Error, an exception occurred while creating the PDF document: ";
+		float pageMatrix[] = zeroPageMatrix();
+		int pageOrientation = PageFormat.LANDSCAPE;
+		float imageableHeight;
+		float imageableWidth;
+		float pageHeight;   //dimensions of the virtual page, not the imageable area
+		float pageWidth;    // actually these are only different for Java2D pages
+		Graphics g = null;
+
+		if ((component == null)) { 
+			return null;
+		}
+		if (dim == null)
+			dimension = component.getSize();
+		else
+			dimension = dim;
+
+		if (fitToPage >= 0) {
+			if (dimension == null || dimension.width <= 0 || dimension.height <= 0) {
+				return null;
+			}
+			double shrinkWidth;
+			double shrinkHeight;
+			double shrinkRatioLANDSCAPE = 0.0;
+			double shrinkRatioPORTRAIT = 0.0;
+			double shrink;
+			//Java2Davailable == true
+			if ((job2 == null) || pf == null)
+				return null;
+			//pf = job2.defaultPage();
+
+			pf.setOrientation(PageFormat.LANDSCAPE);
+			shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+			shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+			if (shrinkWidth < shrinkHeight)
+				shrinkRatioLANDSCAPE = shrinkWidth;
+			else
+				shrinkRatioLANDSCAPE = shrinkHeight;	
+			pf.setOrientation(PageFormat.PORTRAIT);
+			shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+			shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+			if (shrinkWidth < shrinkHeight)
+				shrinkRatioPORTRAIT = shrinkWidth;
+			else
+				shrinkRatioPORTRAIT = shrinkHeight;
+			if (shrinkRatioPORTRAIT < shrinkRatioLANDSCAPE){
+				pf.setOrientation(PageFormat.LANDSCAPE);
+				shrink = shrinkRatioLANDSCAPE;
+			}
+			else {
+				pf.setOrientation(PageFormat.PORTRAIT);
+				shrink = shrinkRatioPORTRAIT;
+			}	
+			pageOrientation = pf.getOrientation();
+
+			imageableWidth = (float)pf.getImageableWidth();
+			imageableHeight = (float)pf.getImageableHeight();
+			pageWidth = (float)pf.getWidth();
+			pageHeight = (float)pf.getHeight();
+			//pageMatrix = zeroPageMatrix();
+			pageMatrix[0] = (float)shrink;
+			pageMatrix[3] = (float)shrink;  
+
+		}
+		else {    // not fit to page
+			// Java2Davailable == true
+			if (job2 == null) 
+				return null;
+			imageableWidth = (float)pf.getImageableWidth();
+			imageableHeight = (float)pf.getImageableHeight();
+			pageHeight = (float)pf.getHeight();
+			pageWidth = (float)pf.getWidth(); 
+			//pageMatrix = pf.getMatrix();
+			//pageMatrix = zeroPageMatrix();
+			pageOrientation = pf.getOrientation();
+			pageMatrix[0] = pageMatrix[3] = 1f;
+
+		}
+		pageRectangle = new com.lowagie.text.Rectangle(0.0f,imageableHeight,imageableWidth,0.0f);
+		try {
+			document = new Document(pageRectangle);
+			writer = PdfWriter.getInstance(document,new FileOutputStream(pdfPathString)); 
+			addMetaData(document);
+			document.open();
+			cb = writer.getDirectContent();
+			tp = cb.createTemplate((int)pageWidth, (int)pageHeight);  //dump this??
+
+			cb.concatCTM(pageMatrix[0],pageMatrix[1],pageMatrix[2],pageMatrix[3],pageMatrix[4],pageMatrix[5]);
+			g = cb.createGraphics((float)dimension.getWidth(),(float)dimension.getHeight()); //HEADLESS :  comment this line out for headless mode
+
+		}
+		catch (java.io.IOException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		catch (com.lowagie.text.BadElementException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		catch (com.lowagie.text.DocumentException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		return g;
+	}
+
+	/**
+	@arg component Component to display
+	@arg dim
+	@arg font
+	 */
+	public void printComponent(Component component, Dimension dim, java.awt.Font font) {
+		final String exceptionMessage = "Error, an exception occurred while creating the PDF document: ";
+		float pageMatrix[] = zeroPageMatrix();
+		int pageOrientation = PageFormat.LANDSCAPE;
+		float imageableHeight;
+		float imageableWidth;
+		float pageHeight;   //dimensions of the virtual page, not the imageable area
+		float pageWidth;    // actually these are only different for Java2D pages
+
+
+		if ((component == null)) { 
+			return;
+		}
+		if (dim == null)
+			dimension = component.getSize();
+		else
+			dimension = dim;
+
+		if (fitToPage >= 0) {
+			if (dimension == null || dimension.width <= 0 || dimension.height <= 0) {
+				return;
+			}
+			double shrinkWidth;
+			double shrinkHeight;
+			double shrinkRatioLANDSCAPE = 0.0;
+			double shrinkRatioPORTRAIT = 0.0;
+			double shrink;
+			   //Java2Davailable == true
+				if ((job2 == null) || pf == null)
+					return;
+				//pf = job2.defaultPage();
+
+				pf.setOrientation(PageFormat.LANDSCAPE);
+				shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+				shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+				if (shrinkWidth < shrinkHeight)
+					shrinkRatioLANDSCAPE = shrinkWidth;
+				else
+					shrinkRatioLANDSCAPE = shrinkHeight;	
+				pf.setOrientation(PageFormat.PORTRAIT);
+				shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+				shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+				if (shrinkWidth < shrinkHeight)
+					shrinkRatioPORTRAIT = shrinkWidth;
+				else
+					shrinkRatioPORTRAIT = shrinkHeight;
+				if (shrinkRatioPORTRAIT < shrinkRatioLANDSCAPE){
+					pf.setOrientation(PageFormat.LANDSCAPE);
+					shrink = shrinkRatioLANDSCAPE;
+				}
+				else {
+					pf.setOrientation(PageFormat.PORTRAIT);
+					shrink = shrinkRatioPORTRAIT;
+				}	
+				pageOrientation = pf.getOrientation();
+
+				imageableWidth = (float)pf.getImageableWidth();
+				imageableHeight = (float)pf.getImageableHeight();
+				pageWidth = (float)pf.getWidth();
+				pageHeight = (float)pf.getHeight();
+				//pageMatrix = zeroPageMatrix();
+				pageMatrix[0] = (float)shrink;
+				pageMatrix[3] = (float)shrink;  
+			}
+		
+		else {    // not fit to page
+			    // Java2Davailable == true
+				if (job2 == null) 
+					return;
+				imageableWidth = (float)pf.getImageableWidth();
+				imageableHeight = (float)pf.getImageableHeight();
+				pageHeight = (float)pf.getHeight();
+				pageWidth = (float)pf.getWidth(); 
+				//pageMatrix = zeroPageMatrix();
+				pageOrientation = pf.getOrientation();
+				pageMatrix[0] = pageMatrix[3] = 1f;
+			
+		}
+		pageRectangle = new com.lowagie.text.Rectangle(0.0f,imageableHeight,imageableWidth,0.0f);
+		try {
+			document = new Document(pageRectangle);
+			writer = PdfWriter.getInstance(document,new FileOutputStream(pdfPathString)); 
+			addMetaData(document);
+			document.open();
+			cb = writer.getDirectContent();
+			tp = cb.createTemplate((int)pageWidth, (int)pageHeight);  //dump this??
+
+			java.awt.Image jImage= component.createImage((int)dimension.getWidth(),(int)dimension.getHeight());
+
+			Graphics j2 = jImage.getGraphics();
+			component.printAll(j2);
+			//com.lowagie.text.Image outImage = null; //HEADLESS  Use this line for headless mode
+			com.lowagie.text.Image outImage = com.lowagie.text.Image.getInstance(jImage,null);  //HEADLESS  Comment this line out for headless mode
+			float verticalIncrement = imageableHeight/pageMatrix[0];
+			float horizontalIncrement = imageableWidth/pageMatrix[3];
+			float heightLimit = (imageableHeight/pageMatrix[0]);
+			float widthLimit = -1*outImage.width();
+			float verticalStart = (imageableHeight/pageMatrix[0])-outImage.height();
+			for (float vertical = verticalStart; vertical < heightLimit ; vertical += verticalIncrement) {
+				for (float horizontal = 0; horizontal > widthLimit; horizontal -= horizontalIncrement) {
+					document.newPage();
+					cb.concatCTM(pageMatrix[0],pageMatrix[1],pageMatrix[2],pageMatrix[3],pageMatrix[4],pageMatrix[5]);
+					switch (pageOrientation) {
+					case PageFormat.LANDSCAPE: {
+						cb.addImage(outImage,outImage.width(),0f,0f,outImage.height(),horizontal,vertical);
+						break;
+					}
+					case PageFormat.PORTRAIT: 
+					default: {
+						cb.addImage(outImage,outImage.width(),0.0f,0.0f,outImage.height(),horizontal,vertical);
+						break;
+					}
+					}
+				}	
+			}
+		}
+		catch (java.io.IOException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		catch (com.lowagie.text.BadElementException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		catch (com.lowagie.text.DocumentException e) {
+			MesquiteTrunk.mesquiteTrunk.alert(exceptionMessage + e);
+		}
+		end();
+	}
+
+
+	/**
+	 */
+	public void end() {
+		// step 5: we close the document
+		if (document != null)
+			document.close();
+	}
+
+}
diff --git a/Source/mesquite/lib/MesquitePackageRecord.java b/Source/mesquite/lib/MesquitePackageRecord.java
new file mode 100644
index 0000000..70807ba
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePackageRecord.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public class MesquitePackageRecord implements Listable, Explainable {
+	String[] pStored;
+	boolean loaded = false;
+	public MesquitePackageRecord(){
+		pStored = new String[3];
+	}
+	public void setStored(int which, String s){
+		if (which>=0 && which < pStored.length){
+			pStored[which] = s;
+		}
+	}
+	public String getName(){
+		String s = null;
+		if (pStored[1] == null)
+			s= pStored[0];
+		else
+			s= pStored[1];
+		return s;
+	}
+	public boolean getLoaded(){
+		return loaded;
+	}
+	public void setLoaded(boolean l){
+		loaded = l;
+	}
+	public String getExplanation(){
+		if (StringUtil.blank(pStored[2]))
+			return "Sorry, no explanation is available for the package \"" + getName() + "\"";
+		return pStored[2];
+	}
+	public String getPackageName(){
+		if (pStored[0]==null)
+			return null;
+		return "mesquite." + pStored[0];
+	}
+	public static MesquitePackageRecord findPackage(String s){
+		if (s==null)
+			return null;
+		ListableVector packages = MesquiteTrunk.mesquiteTrunk.packages;
+		for (int i=0; i<packages.size(); i++){
+			Object obj = packages.elementAt(i);
+			if (obj instanceof MesquitePackageRecord) {
+				MesquitePackageRecord mpr = (MesquitePackageRecord)obj;
+				if (s.equals(mpr.getPackageName()))
+					return mpr;
+			}
+		}
+		return null;
+	}
+	public static boolean allPackagesActivated(){
+		ListableVector packages = MesquiteTrunk.mesquiteTrunk.packages;
+		for (int i=0; i<packages.size(); i++){
+			Object obj = packages.elementAt(i);
+			if (obj instanceof MesquitePackageRecord) {
+				MesquitePackageRecord mpr = (MesquitePackageRecord)obj;
+				if (!mpr.getLoaded())
+					return false;
+			}
+		}
+		return true;
+	}
+}
diff --git a/Source/mesquite/lib/MesquitePanel.java b/Source/mesquite/lib/MesquitePanel.java
new file mode 100644
index 0000000..58cb009
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePanel.java
@@ -0,0 +1,209 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+
+/* ======================================================================== */
+/** This class adds drop down menu capabilities to panels.  A default component of the drop down
+menu is the Font selection */
+
+public class MesquitePanel extends MousePanel  {
+	LeakFinder leakFinder = MesquiteTrunk.leakFinderObject;
+	MesquitePopup popup=null;
+	MesquiteCommand setFontCommand, setFontSizeCommand;
+	Font curFont = null;
+
+
+	 
+	public MesquitePanel () {
+		super();
+		setLayout(null);
+		setFontCommand =MesquiteModule.makeCommand("setFont",  this);
+		setFontSizeCommand =MesquiteModule.makeCommand("setFontSize",  this);
+
+	}
+	public Frame getFrame() {
+		Container c = getParent();
+		while (c!=null && !(c instanceof Frame))
+			 c = c.getParent();
+		return (Frame)c;
+	}
+	public void dispose(){
+		setFontCommand =null;
+		setFontSizeCommand =null;
+		if (popup!=null)
+			remove(popup);
+		super.dispose();
+	}
+	public Component add(Component c){
+		if (c==null)
+			return null;
+			else
+				return super.add(c, 0);
+	}
+	public void remove(Component c){
+		requestFocusInWindow();
+		if (c!=null)
+			super.remove(c);
+	}
+	/*.................................................................................................................*/
+	public void setBounds(int x, int y, int width, int height ){
+		super.setBounds(x, y, width, height);
+		int locX, locY;
+		if (width>32)
+			locX = (width-32)/2;
+		else
+			locX = 0;
+		if (height>32)
+			locY = (height-32)/2;
+		else
+			locY = 0;
+	}
+	/*.................................................................................................................*/
+	public void setSize(int width, int height ){
+		super.setSize(width, height);
+		int locX, locY;
+		if (width>32)
+			locX = (width-32)/2;
+		else
+			locX = 0;
+		if (height>32)
+			locY = (height-32)/2;
+		else
+			locY = 0;
+	}
+	/*.................................................................................................................*/
+	void redoMenu() {
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		MesquiteSubmenu submenuFont=MesquiteSubmenu.getFontSubmenu("Font", popup, null, setFontCommand);
+		/*Toolkit tk = this.getToolkit();
+		String[] fonts = tk.getFontList();
+		for (int i=0; i<fonts.length; i++)
+			submenuFont.add(new MesquiteMenuItem(fonts[i],  null, setFontCommand, fonts[i]));
+		*/
+		popup.add(submenuFont);
+		MesquiteSubmenu submenuSize=MesquiteSubmenu.getFontSizeSubmenu("Size", popup, null, setFontSizeCommand);
+		popup.add(submenuSize);
+		add(popup);
+	}
+	/*.................................................................................................................*/
+	public void setFontName (String name) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (name, curFont.getStyle(), curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setPanelFont(curFont);
+ 		}
+    	 }
+	/*.................................................................................................................*/
+	public void setFontStyle (int style) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), style, curFont.getSize());
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setPanelFont(curFont);
+ 		}
+    	 }
+	/*.................................................................................................................*/
+    	 public void setFontSize (int size) {
+		if (curFont==null)
+			curFont = getParent().getFont();
+ 		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), size);
+ 		if (fontToSet!= null) {
+ 			curFont = fontToSet;
+ 			setPanelFont(curFont);
+ 		}
+    	 }
+    	 
+	/*...............................................................................................................*/
+	public void setWindowAnnotation(String s, String annotationExplanation) {
+		MesquiteWindow f = MesquiteWindow.windowOfItem(this);
+		if (f != null && f instanceof MesquiteWindow){
+			((MesquiteWindow)f).setAnnotation(s, annotationExplanation);
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+     	 	Snapshot temp = new Snapshot();
+     	 	Rectangle b = getBounds();
+ 		temp.addLine("setBounds " +  b.x + " " + b.y + " " + b.width+ " " + b.height);
+  	 	if (curFont!=null) {
+	 		temp.addLine("setFont " +  ParseUtil.tokenize(curFont.getName()));  //fixed to tokenize 12 Oct 01
+  	 		temp.addLine("setFontSize " +  curFont.getSize());
+	 	}
+	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the font of the panel", "[font name]", commandName, "setFont")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+			if (curFont==null)
+				curFont = getParent().getFont();
+    	 		Font fontToSet = new Font (ParseUtil.getFirstToken(arguments, pos), curFont.getStyle(), curFont.getSize()); //fixed to get first token 12 Oct 01
+    	 		if (fontToSet!= null) {
+    	 			curFont = fontToSet;
+    	 			setPanelFont(curFont);
+	    	 		repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the font size of the panel", "[font size]", commandName, "setFontSize")) {
+			if (curFont==null)
+				curFont = getParent().getFont();
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int siz = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+    	 		if (!MesquiteInteger.isCombinable(siz)) {
+				siz = MesquiteInteger.queryInteger(MesquiteWindow.windowOfItem(this), "Set Font Size", "Font size", curFont.getSize(), 2, 256);
+			}
+    	 		if (MesquiteInteger.isCombinable(siz)) {
+	    	 		Font fontToSet = new Font (curFont.getName(), curFont.getStyle(), siz);
+	    	 		if (fontToSet!= null) {
+	    	 			curFont = fontToSet;
+	    	 			setPanelFont(curFont);
+	    	 			repaint();
+	    	 		}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the bounds of the panel, in pixels", "[x (left bound)] [y (upper bound)] [width] [height]", commandName, "setBounds")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int xA = MesquiteInteger.fromString(arguments, pos);
+    	 		int yA = MesquiteInteger.fromString(arguments, pos);
+    	 		int wA =  MesquiteInteger.fromString(arguments, pos);
+    	 		int hA  = MesquiteInteger.fromString(arguments, pos);
+    	 		setBounds(xA, yA, wA, hA);
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+    		public boolean autoFontSubmenu () {
+  			return true;
+    		}
+	/* to be used by subclasses to tell that panel touched */
+    	 protected void panelTouched (int modifiers,int x, int y, boolean controlNeeded) {
+if (autoFontSubmenu() && MesquiteEvent.rightClick(modifiers) || !controlNeeded) {
+			if (popup==null)
+				redoMenu();
+			popup.show(this, x,y);
+		}
+	}
+	
+
+
+}
diff --git a/Source/mesquite/lib/MesquiteParameter.java b/Source/mesquite/lib/MesquiteParameter.java
new file mode 100644
index 0000000..0cd1bb8
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteParameter.java
@@ -0,0 +1,237 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+/* ======================================================================== */
+/**An object to wrap a parameter used.  New after 1. 12.  Limited use; in future could replace many uses of MesquiteDouble for module parameters.*/
+public class MesquiteParameter extends MesquiteDouble implements Explainable {
+	double minimumAllowed = MesquiteDouble.unassigned;
+	double maximumAllowed = MesquiteDouble.unassigned;
+	double minimumSuggested = MesquiteDouble.unassigned;
+	double maximumSuggested = MesquiteDouble.unassigned;
+	String explanation = "";
+	boolean valueLocked = false;
+	double provisional = MesquiteDouble.unassigned;
+	MesquiteParameter constrainedToBe;
+	public MesquiteParameter(){
+	}
+	public MesquiteParameter(String name, String explanation,	double value, double minimumAllowed, double maximumAllowed, double minimumSuggested, double maximumSuggested){
+		setName(name);
+		this.explanation = explanation;
+		setValue(value);
+		this.minimumAllowed = minimumAllowed;
+		this.maximumAllowed = maximumAllowed;
+		this.minimumSuggested = minimumSuggested;
+		this.maximumSuggested = maximumSuggested;
+	}
+	public MesquiteParameter(MesquiteParameter param){
+		setName(param.getName());
+		this.explanation = param.explanation;
+		setValue(param.getValue());
+		this.minimumAllowed = param.minimumAllowed;
+		this.maximumAllowed = param.maximumAllowed;
+		this.minimumSuggested = param.minimumSuggested;
+		this.maximumSuggested = param.maximumSuggested;
+	}
+	public MesquiteParameter getConstrainedTo(){
+		return constrainedToBe;
+	}
+	public void setConstrainedTo(MesquiteParameter other, boolean resetValue){
+		constrainedToBe = other;
+		if (other != null && resetValue){
+			setValue(other.getValue());
+		}
+	}
+	public void setValues(MesquiteParameter param){
+		setName(param.getName());
+		this.explanation = param.explanation;
+		setValue(param.getValue());
+		this.minimumAllowed = param.minimumAllowed;
+		this.maximumAllowed = param.maximumAllowed;
+		this.minimumSuggested = param.minimumSuggested;
+		this.maximumSuggested = param.maximumSuggested;
+		this.provisional = provisional;
+	}
+	public int whichParameter(MesquiteParameter[] p){
+		if (p == null)
+			return -1;
+		for (int i=0; i<p.length; i++){
+			if (this == p[i])
+				return i;
+		}
+		return -1;
+	}
+	public void setValue(double d){
+		super.setValue(d);
+		if (constrainedToBe != null){
+			//constrainedToBe.setValueButNotConstrainee(d);
+		}
+	}
+	public void setValueButNotConstrainee(double d){
+		super.setValue(d);
+	}
+ 	public double getMinimumAllowed(){
+ 		return minimumAllowed;
+ 	}
+ 	public void setMinimumAllowed(double m){
+ 		minimumAllowed = m;
+ 	}
+	public double getMaximumAllowed(){
+ 		return maximumAllowed;
+ 	}
+ 	public void setMaximumAllowed(double m){
+ 		maximumAllowed = m;
+ 	}
+ 	public double getMinimumSuggested(){
+ 		return minimumSuggested;
+ 	}
+ 	public void setMinimumSuggested(double m){
+ 		minimumSuggested = m;
+ 	}
+	public double getMaximumSuggested(){
+ 		return maximumSuggested;
+ 	}
+ 	public void setMaximumSuggested(double m){
+ 		maximumSuggested = m;
+ 	}
+	public String getExplanation(){
+ 		return explanation;
+ 	}
+ 	public void setExplanation(String e){
+ 		explanation = e;
+ 	}
+ 	public boolean isValueLocked(){
+ 		return valueLocked;
+ 	}
+ 	public void setValueLocked(boolean vl){
+ 		valueLocked = vl;
+ 	}
+ 	
+ 	public void setProvisionalValue(double p){ //for dialog boxes etc. to set value without it being fixed until acceptProvisionalValue() is called
+ 		provisional = p;
+ 	}
+	public double getProvisionalValue(){ //for dialog boxes etc. to set value without it being fixed until acceptProvisionalValue() is called
+		return provisional;
+ 	}
+	public void acceptProvisionalValue(){ //for dialog boxes etc. to set value without it being fixed until acceptProvisionalValue() is called
+		setValue(provisional);
+ 	}
+	
+		public static int getWhichConstrained(MesquiteParameter[] params, int i){
+		if (params == null)
+			return -1;
+		MesquiteParameter p = params[i].getConstrainedTo();
+		if (p == null)
+			return -1;
+		for (int k=0; k<params.length; k++){
+			if (params[k] == p)
+				return k;
+		}
+		return -1;
+	}
+		public static String paramsToScriptString(MesquiteParameter[] p){
+			if (p == null)
+				return null;
+			String pString = "";
+			for (int i = 0; i<p.length; i++)
+				pString += " " + p[i].toString()+ " " + MesquiteParameter.constraintsToString(p, i);
+			return pString;
+		}
+		public static String constraintsToString(MesquiteParameter[] params, int i){
+			if (params == null)
+				return "";
+			MesquiteParameter p = params[i].getConstrainedTo();
+			if (p == null)
+				return "";
+			for (int k=0; k<params.length; k++){
+				if (params[k] == p)
+					return " =" + k;
+			}
+			return "";
+		}
+	public static MesquiteParameter[] cloneArray(MesquiteParameter[] original, MesquiteParameter[] destination){
+		if (original == null)
+			return null;
+		if (destination == null || destination.length != original.length)
+			destination = new MesquiteParameter[original.length];
+		for (int i=0; i<destination.length; i++){
+			if (destination[i] == null)
+				destination[i] = new MesquiteParameter();
+			destination[i].setValues(original[i]);
+		}
+		for (int i=0; i<destination.length; i++){
+			MesquiteParameter con = original[i].getConstrainedTo();
+			if (con != null)
+				destination[i].setConstrainedTo(destination[MesquiteParameter.getWhichConstrained(original, i)], true);
+			else
+				destination[i].setConstrainedTo(null, false);
+		}
+		return destination;
+	}
+	public static int numberSpecified(MesquiteParameter[] params){
+		if (params == null)
+			return 0;
+		int count = 0;
+		for (int i=0; i<params.length; i++){
+			if (params[i].isCombinable())
+				count++;
+		}
+		return count;
+	}
+	public static String toString(MesquiteParameter[] params){
+		if (params == null)
+			return "";
+		String s = "";
+		for (int i=0; i<params.length; i++)
+			s += params[i].getName() + "=" + MesquiteDouble.toStringDigitsSpecified(params[i].getValue(), 5) + " ";
+		return s;
+	}
+	public static String toStringForAnalysis(MesquiteParameter[] params){
+		if (params == null)
+			return "";
+		String s = "";
+		for (int i=0; i<params.length; i++){
+			if (i>0)
+				s += "\t";
+			s += MesquiteDouble.toString(params[i].getValue());
+		}
+		return s;
+	}
+	public static String toString(double[] params){
+		if (params == null)
+			return "";
+		String s = "";
+		for (int i=0; i<params.length; i++)
+			s += MesquiteDouble.toStringDigitsSpecified(params[i], 5) + " ";
+		return s;
+	}
+	public static String toStringWithConstraints(MesquiteParameter[] params){
+		if (params == null)
+			return "";
+		String s = toString(params);
+		boolean cfound = false;
+		for (int i=0; i<params.length; i++){
+			MesquiteParameter con = params[i].getConstrainedTo();
+			if (con != null) {
+				s += i + "=" + MesquiteParameter.getWhichConstrained(params, i) + " ";
+				cfound = true;
+			}
+		}
+		if (!cfound)
+			s += " [no constraints]";
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquitePasswordField.java b/Source/mesquite/lib/MesquitePasswordField.java
new file mode 100644
index 0000000..8cbce69
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePasswordField.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import javax.swing.*;
+
+/*===============================================*/
+/** a field for text that cannot have line feeds/carriage returns in it.  */
+public class MesquitePasswordField extends JPasswordField  {
+	Label fieldLabel; 
+	/*.................................................................................................................*/
+	public MesquitePasswordField (String initialString, int fieldLength) {
+		super(initialString,fieldLength);
+	}
+	/*.................................................................................................................*/
+	public Label getLabel() {
+		return fieldLabel;
+	}
+	/*.................................................................................................................*/
+	public void setLabel(Label fieldLabel) {
+		this.fieldLabel = fieldLabel;
+	}
+	/*.................................................................................................................*/
+	public void setLabelText(String s) {
+		if (fieldLabel!=null)
+			fieldLabel.setText(s);
+	}
+	/*.................................................................................................................*/
+	public Dimension getPreferredSize() {
+		Dimension d = super.getPreferredSize();
+		d.height +=4;
+		return d;
+	}
+	/*.................................................................................................................*/
+	public MesquitePasswordField (String initialString) {
+		super(initialString);
+	}
+	/*.................................................................................................................*
+	public String getText () {
+		int count = 0;
+		while (count++<10){
+			try {
+				char[] s = super.getPassword();
+				if (s==null)
+					return "";
+				s = StringUtil.removeNewLines(s);
+			        if (StringUtil.blank(s)) {
+			        	if (preserveBlanks)
+			        		return s;
+			        	else
+			        	 	return "";
+			        }
+			        else
+			        	return s;
+		        }
+		        catch (Exception e){
+		        	//MesquiteMessage.warnProgrammer("Exception in getText of SingleLineTextField");
+		        }
+	        }
+        	return "";
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/lib/MesquitePath2DFloat.java b/Source/mesquite/lib/MesquitePath2DFloat.java
new file mode 100644
index 0000000..0795e80
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePath2DFloat.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.geom.Area;
+import java.awt.geom.Path2D;
+import java.text.*;
+
+
+/* ======================================================================== */
+public class MesquitePath2DFloat {
+	Object pFloat;
+	public MesquitePath2DFloat(){
+		try {
+			Class.forName("java.awt.geom.Path2D");
+		pFloat = new java.awt.geom.Path2D.Float();
+		}
+		catch (Error e){
+		}
+		catch (Exception e){
+		}
+	}
+	
+	
+	public void closePath(){
+		((java.awt.geom.Path2D.Float)pFloat).closePath();
+	}
+	             
+
+	public void moveTo(int x, int y){
+		((java.awt.geom.Path2D.Float)pFloat).moveTo(x, y);
+	}
+	public void lineTo(int x, int y){
+		((java.awt.geom.Path2D.Float)pFloat).lineTo(x, y);
+	}
+
+	public void curveTo(double d1, double d2, double d3, double d4, double d5, double d6){
+		((java.awt.geom.Path2D.Float)pFloat).curveTo(d1, d2, d3, d4,d5,d6);
+	}
+	public void fill(Graphics2D g){
+		g.fill(((java.awt.geom.Path2D.Float)pFloat));
+	}
+	public Area getArea(){
+		return new Area(((java.awt.geom.Path2D.Float)pFloat));
+	}
+	public boolean OK(){
+		return pFloat != null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquitePopup.java b/Source/mesquite/lib/MesquitePopup.java
new file mode 100644
index 0000000..7bb9920
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePopup.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+public class MesquitePopup extends PopupMenu {
+	Container c;
+	int id = 0;
+	MesquiteMenuSpec spec;
+	protected boolean filterable = true;
+	public MesquitePopup(Container c){
+		super();
+		this.c = c;
+	}
+	public MesquitePopup(MesquiteMenuSpec spec, Container c){
+		super(spec.getLabel());  // true to designate as tearoff; doesn't seem to work on macos
+		filterable = spec.isFilterable();
+		if (spec.getLabel() == null) {
+			MesquiteMessage.println("menu with no name: ");
+			setEnabled(false);
+		}
+		if (!spec.isEnabled())
+			setEnabled(false);
+		this.spec = spec;
+	}
+	public static MesquitePopup getPopupMenu(MesquiteMenuSpec spec, Container c) {
+
+		return new MesquitePopup(spec, c);
+	}
+	Container getComponent(){
+		return c;
+	}
+	public void setComponent(Container c){
+		this.c = c;
+	}
+	public MesquiteMenuSpec getSpecification(){
+		return spec;
+	}
+	
+	public static Polygon getDropDownTriangle(){
+		Polygon dropDownTriangle=new Polygon();
+		dropDownTriangle.xpoints = new int[4];
+		dropDownTriangle.ypoints = new int[4];
+		dropDownTriangle.npoints=0;
+		dropDownTriangle.addPoint(0, 0);
+		dropDownTriangle.addPoint(6, 0);
+		dropDownTriangle.addPoint(3,3);
+		dropDownTriangle.addPoint(0, 0);
+		dropDownTriangle.npoints=4;
+		return dropDownTriangle;
+	}
+	public void addItem(String label, MesquiteModule module, MesquiteCommand respondCommand, String argument){
+		MesquiteMenuItem m = new MesquiteMenuItem(label, module, respondCommand, argument);
+		add(m);
+	}
+	public void addItem(String label, MesquiteCommand respondCommand, String argument){
+		addItem(label, null, respondCommand, argument);
+	}
+	public void addItem(String label, MesquiteModule module, MesquiteCommand respondCommand){
+		addItem(label, module, respondCommand, null);
+	}
+
+
+	public void addItems(String[] labels, MesquiteModule[] modules, MesquiteCommand[] respondCommands){
+		if (labels!=null){
+			for (int i=0; i<labels.length; i++) 
+				addItem(labels[i], modules[i], respondCommands[i], null);
+		}
+	}
+
+
+	public void showPopup(int x, int y){
+		
+		c.add(this);
+		if (c instanceof MousePanel)
+			((MousePanel)c).suppressEvents = true;
+		show(c, x,y);
+		if (c instanceof MousePanel)
+			((MousePanel)c).suppressEvents = false;
+		//c.remove(this);
+	}
+	
+
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquitePrintJob.java b/Source/mesquite/lib/MesquitePrintJob.java
new file mode 100644
index 0000000..2c6c090
--- /dev/null
+++ b/Source/mesquite/lib/MesquitePrintJob.java
@@ -0,0 +1,306 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified May 02 especially for annotations*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import java.awt.print.*;
+import java.awt.geom.*;
+import java.io.*;
+/* ======================================================================== */
+
+
+public class MesquitePrintJob {
+	public static final int AUTOFIT = 3;
+	public static final int FIT_LANDSCAPE = 1;
+	public static final int FIT_PORTRAIT = 0;
+	public static final int NATURAL = -1;
+
+	int fitToPage = AUTOFIT; ;
+	Component component;
+	Font font;
+	PrintJob job1;
+	PrinterJob job2;
+	String name;
+	MesquiteFrame frame;
+	Dimension dimension;
+	P2 p2;
+	PageFormat pf = null;
+
+	protected MesquitePrintJob(MesquiteFrame frame, String name){
+		this.frame = frame;
+		if (name == null)
+			name = "Print";
+		this.name = name;
+		try {
+			p2 = new P2();
+		}
+		catch (Throwable e){
+			MesquiteFile.throwableToLog(this, e);
+			MesquiteTrunk.mesquiteTrunk.alert("Exception or Error in making P2; details in Mesquite log file");
+		}
+
+	}
+	public static MesquitePrintJob getPrintJob(MesquiteFrame frame, String name, int fitToPage){
+		MesquiteTrunk.mesquiteTrunk.logln("Getting print job");
+		MesquitePrintJob job = new MesquitePrintJob(frame, name);
+		MesquiteTrunk.mesquiteTrunk.logln("Preparing to print");
+		if (job == null)
+			return null;
+		if (job.preparePrint(fitToPage))
+			return job;
+		else {
+			return null;
+		}
+	}
+	public boolean preparePrint(int fitToPage) {
+		this.fitToPage = fitToPage;
+
+
+		job2 = PrinterJob.getPrinterJob();
+		if (job2 ==null) {
+			MesquiteTrunk.mesquiteTrunk.alert("Error: no printer job returned in preparePrint");
+			return false;
+		}
+		job2.setPrintable(p2);
+
+		if (fitToPage == AUTOFIT){  //fits landscape or portrait depending on what requires least shrinkage
+			pf = job2.defaultPage();
+			if (pf ==null) {
+				MesquiteTrunk.mesquiteTrunk.alert("Error: no defaultPage returned in preparePrint (autofit)");
+				return false;
+			}
+		}
+		else if (fitToPage == FIT_LANDSCAPE){ //fits into landscape
+			pf = job2.defaultPage();
+			if (pf ==null) {
+				MesquiteTrunk.mesquiteTrunk.alert("Error: no defaultPage returned in preparePrint (landscape)");
+				return false;
+			}
+			pf.setOrientation(PageFormat.LANDSCAPE);
+		}
+		else if (fitToPage == FIT_PORTRAIT){ //fits into portrait
+			pf = job2.defaultPage();
+			if (pf ==null) {
+				MesquiteTrunk.mesquiteTrunk.alert("Error: no defaultPage returned in preparePrint (portrait)");
+				return false;
+			}
+			pf.setOrientation(PageFormat.PORTRAIT);
+		}
+		else { //prints at current size using page setup (thus, possibly over multiple pages)
+			pf = job2.pageDialog(job2.defaultPage());
+			if (pf == null) {
+				MesquiteTrunk.mesquiteTrunk.alert("Error: no page dialog returned in preparePrint");
+				return false;
+			}
+		}
+		job2.validatePage(pf);
+		job2.setPrintable(p2, pf);  
+		if (MesquiteThread.isScripting())
+			return true;
+		else
+			return job2.printDialog();
+	}
+
+	public void printComponent(Component component, Dimension dim, Font font) {
+		this.font = font;
+		this.component = component;
+		if (dim == null){
+			if (component instanceof TreeDisplay){
+				
+				dimension = new Dimension(((TreeDisplay)component).getFieldWidth(), ((TreeDisplay)component).getFieldHeight());
+			}
+			else
+				dimension = component.getSize();
+		}
+		else
+			dimension = dim;
+
+
+		if (job2==null)
+			return;
+		Dimension oldTreeDisplaySize = null;
+		Rectangle oldTreeVisRect = null;
+		if (component instanceof TreeDisplay){
+			oldTreeDisplaySize = component.getSize();
+			oldTreeVisRect = ((TreeDisplay)component).getVisRect();
+			((TreeDisplay)component).setVisRect(null);
+			((TreeDisplay)component).setPrintingInProcess(true);
+			component.setSize(((TreeDisplay)component).getFieldWidth(), ((TreeDisplay)component).getFieldHeight());
+		}
+		if (fitToPage == AUTOFIT){  //fits landscape or portrait depending on what requires least shrinkage
+			if (dimension.width<=0 || dimension.height <=0)
+				return;
+			PageFormat pf = job2.defaultPage();
+			pf.setOrientation(PageFormat.LANDSCAPE);
+			double shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+			double shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+			double shrinkRatioLANDSCAPE;
+			if (shrinkWidth< shrinkHeight)
+				shrinkRatioLANDSCAPE = shrinkHeight/shrinkWidth;
+			else
+				shrinkRatioLANDSCAPE = shrinkWidth/shrinkHeight;
+			pf.setOrientation(PageFormat.PORTRAIT);
+			shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+			shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+			double shrinkRatioPORTRAIT;
+			if (shrinkWidth< shrinkHeight)
+				shrinkRatioPORTRAIT = shrinkHeight/shrinkWidth;
+			else
+				shrinkRatioPORTRAIT = shrinkWidth/shrinkHeight;
+
+			if (shrinkRatioPORTRAIT>shrinkRatioLANDSCAPE)
+				pf.setOrientation(PageFormat.LANDSCAPE);
+			job2.validatePage(pf);
+			job2.setPrintable(p2, pf);  
+		}
+
+		try {
+			job2.print();  
+		} 
+		catch (Exception ex) {
+			  //ex.printStackTrace();
+		}
+		if (component instanceof TreeDisplay){
+			component.setSize(oldTreeDisplaySize.width, oldTreeDisplaySize.height);
+			((TreeDisplay)component).setVisRect(oldTreeVisRect);
+			((TreeDisplay)component).setPrintingInProcess(false);
+			((TreeDisplay)component).repaintAll();
+		}
+
+	}
+
+	public void printText(String s, Font font) {
+		if (s == null || font==null)
+			return;
+
+
+		if (job2==null)
+			return;
+
+		if (pf == null){
+			pf = job2.defaultPage(); //currently disallow page setup because at least on OS X cropping prevents the 
+			//pf = job2.pageDialog(job2.defaultPage());
+		}
+		job2.validatePage(pf);
+		job2.setPrintable(new P2Text(s, font), pf);  
+
+		try {
+			job2.print();  
+		} 
+		catch (Exception ex) {
+			//  ex.printStackTrace();
+		}
+
+	}
+
+	public void end(){
+
+	}
+	public class P2Text implements Printable {
+		StringBuffer sB;
+		Font font;
+		StringInABox sBox;
+		public P2Text(String s, Font font){
+			sB = new StringBuffer(s);
+			this.font = font;
+			sBox = new StringInABox(sB, font, 1000);  
+		}
+		public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+			if (font !=null)
+				g.setFont(font);
+			Graphics2D g2 = (Graphics2D)g;
+			AffineTransform at = g2.getTransform();
+			double scale = at.getScaleX();
+			int effectivePageWidth = (int)(pf.getImageableWidth()/scale);
+			sBox.setWidth(effectivePageWidth);
+
+			double dPagesHigh =  (sBox.getHeight() * scale)/pf.getImageableHeight(); //need to add pixels for number of pages in case lines cut
+			int pagesHigh = (int)dPagesHigh;
+			if ((double)pagesHigh != dPagesHigh)
+				pagesHigh++;
+
+			if (pi >= pagesHigh) {
+				return Printable.NO_SUCH_PAGE;
+			}
+
+			double dEffectivePageHeight = pf.getImageableHeight()/scale;
+
+			g2.scale(1/scale, 1/at.getScaleY());  //why this is & following line are needed isn't clear, but without it OS X 10.2 crops instead of scales
+			g2.scale(scale, at.getScaleY());//why this is & preceding line are needed isn't clear, but without it OS X 10.2 crops instead of scales
+			g2.translate((int)(pf.getImageableX() + 0.5),(int)(-dEffectivePageHeight*pi + pf.getImageableY() + 0.5));
+			sBox.draw(g2, 0, 0, 0, 99999999); 
+			return Printable.PAGE_EXISTS;
+
+		}
+	}
+	public class P2 implements Printable {
+		public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+			if (font !=null)
+				g.setFont(font);
+			Graphics2D g2 = (Graphics2D)g;
+			AffineTransform at = g2.getTransform();
+			double scale = at.getScaleX();
+			if (fitToPage >= 0){ // not using natural size; fit into page
+				if (pi >= 1 || dimension == null || dimension.width <= 0 || dimension.height <= 0) {
+					return Printable.NO_SUCH_PAGE;
+				}
+				double shrinkWidth = pf.getImageableWidth()*1.0/dimension.width;
+				double shrinkHeight = pf.getImageableHeight()*1.0/dimension.height;
+				double shrink;
+				if (shrinkWidth< shrinkHeight)
+					shrink = shrinkWidth;
+				else
+					shrink = shrinkHeight;
+				g2.translate((int)(pf.getImageableX() + 0.5),(int)(pf.getImageableY() + 0.5));
+				g2.scale(shrink, shrink);
+			}
+			else {  //print at current size using page setup information
+				if (dimension == null) {
+					dimension = component.getSize();
+				}
+				double dPagesWide =  (dimension.width * scale)/pf.getImageableWidth();
+				double dPagesHigh =  (dimension.height * scale)/pf.getImageableHeight();
+				int pagesWide = (int)dPagesWide;
+				int pagesHigh = (int)dPagesHigh;
+
+				if ((double)pagesWide != dPagesWide)
+					pagesWide++;
+				if ((double)pagesHigh != dPagesHigh)
+					pagesHigh++;
+
+				if (pi >= pagesWide*pagesHigh) {
+					return Printable.NO_SUCH_PAGE;
+				}
+
+				double dEffectivePageWidth = pf.getImageableWidth()/scale;
+				double dEffectivePageHeight = pf.getImageableHeight()/scale;
+				int piW = pi % pagesWide;
+				int piH = pi / pagesWide;
+
+				g2.scale(1/scale, 1/at.getScaleY());  //why this is & following line are needed isn't clear, but without it OS X 10.2 crops instead of scales
+				g2.scale(scale, at.getScaleY());//why this is & preceding line are needed isn't clear, but without it OS X 10.2 crops instead of scales
+				g2.translate((int)(-dEffectivePageWidth*piW + pf.getImageableX() + 0.5),(int)(-dEffectivePageHeight*piH + pf.getImageableY() + 0.5));
+			}
+
+
+			component.printAll((Graphics2D) g);
+			return Printable.PAGE_EXISTS;
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteProject.java b/Source/mesquite/lib/MesquiteProject.java
new file mode 100644
index 0000000..599aef4
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteProject.java
@@ -0,0 +1,2282 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modifications:
+28 July 01 (WPM) getCompatibleFileElements added
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.net.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** An object of this class represents a collection of information (data matrices, tree blocks, etc.) that may reside in more than one
+file (MesquiteFile, which represents files on disk or at a URL).  More than one project can be open at once.  Information from different projects
+generally doesn't interact (e.g., a data matrix from one project can't belong to a set of taxa from another project), but within a single project
+information can interact regardless of what file the information belongs to.<p>
+Although more than one file can belong to the project, the first file opened is treated as the "home file".  In the future the idea of a "project" may be made stronger,
+and a separate sort of file (the project file) may be created.  tHis would eliminate the need for a "home file".
+ */
+public class MesquiteProject extends Attachable implements Listable, MesquiteListener, Commandable, HNode, HTMLDescribable {
+	LeakFinder leakFinder = MesquiteTrunk.leakFinderObject;
+	/** A vector of the sets of taxa within the project.*/
+	public ListableVector taxas;  
+	/** Vector of data sets (including matrix) within the project. */
+	public ListableVector datas;  
+	/** Character models belonging to the project.*/
+	protected ModelVector charModels; 
+	/** Other file elements belonging to the project.*/
+	protected ListableVector otherElements; 
+
+	/** frame for this project */
+	private MesquiteFrame frame = null;
+
+	/** Nexus blocks belonging to the files in the project.*/
+	protected ListableVector nexusBlocks; 
+	/** */
+	CentralModelListener modelListener;
+	public boolean virginProject = true;
+	public long startupTime = 0;
+	public MesquiteWindow windowToActivate, activeWindowOfProject;
+	/** The files belonging to the project. */
+	ListableVector files;
+	/** The home file of the project. */
+	MesquiteFile homeFile;
+
+	/** Commands used with standard Close, Save and Save As...and other menu items*/
+	private MesquiteCommand closeCommand, closeFilesCommand, showFileOnDiskCommand, saveCommand, saveFilesCommand, saveAsCommand, saveLinkagesCommand, revertCommand, linkFileCommand, linkURLCommand, includeFileCommand, includeURLCommand;
+	public MesquiteCommand exportCommand, newLinkFileCommand, getInfoCommand;
+	/** The file coordinator module that owns this object*/
+	public FileCoordinator ownerModule=null; 
+
+	/** Background color scheme for project's windows*/ 
+	public int projectColor;  
+
+	public static int totalCreated = 0;  // a static counter of the number of projects that have been opened
+	public static int totalDisposed = 0;  // to catch memory leaks
+	public static int totalFinalized = 0;  // to catch memory leaks
+	private int idNumber;
+	public boolean developing = true;
+	public boolean autosave = false;
+	public boolean isDoomed = false;
+	public long timePreviouslySavedAsRecorded = 0;
+	public long timePreviouslySavedByFile = 0;
+
+	public MesquiteProject(FileCoordinator ownerModule) {
+		this.ownerModule = ownerModule;
+		startupTime = System.currentTimeMillis();
+		datas = new ListableVector();  
+		taxas = new ListableVector();  
+		charModels = new ModelVector();
+		datas.addListener(this);
+		taxas.addListener(this);
+		charModels.addListener(this);
+		modelListener = new CentralModelListener();
+		otherElements = new ListableVector();
+		otherElements.setName("other file elements in project");
+		files = new ListableVector();
+		nexusBlocks = new ListableVector( 1);
+		idNumber = totalCreated;
+		totalCreated++;
+
+
+		projectColor = MesquiteTrunk.mesquiteTrunk.projects.requestNextColor();
+
+		closeCommand= MesquiteModule.makeCommand("closeFile", ownerModule);
+		closeFilesCommand= MesquiteModule.makeCommand("closeProject", ownerModule);
+		showFileOnDiskCommand = MesquiteModule.makeCommand("showFileOnDisk", ownerModule);
+
+		saveCommand= MesquiteModule.makeCommand("saveFile", ownerModule);
+		saveFilesCommand= MesquiteModule.makeCommand("saveFiles", ownerModule);
+		saveAsCommand= MesquiteModule.makeCommand("saveFileAs", ownerModule);
+		revertCommand= MesquiteModule.makeCommand("revert", ownerModule);
+		exportCommand= MesquiteModule.makeCommand("export", ownerModule);
+		getInfoCommand= MesquiteModule.makeCommand("getInfo", ownerModule);
+		saveLinkagesCommand= MesquiteModule.makeCommand("saveLinkagesAs", ownerModule);
+		linkFileCommand = MesquiteModule.makeCommand("linkFile", ownerModule);
+		newLinkFileCommand = MesquiteModule.makeCommand("newLinkedFile", ownerModule);
+		linkURLCommand = MesquiteModule.makeCommand("linkURL", ownerModule);
+		includeFileCommand = MesquiteModule.makeCommand("includeFile", ownerModule);
+		includeURLCommand = MesquiteModule.makeCommand("includeURL", ownerModule);
+	}
+
+	public void refreshProjectWindow(){
+		if (refreshSuppression == 0){
+			refreshPending = false;
+			if (ownerModule != null)
+				ownerModule.refreshProjectWindow();
+		}
+		else {
+			refreshPending = true;
+		}
+	}
+	public void repaintProjectWindow(){
+		if (ownerModule != null && ownerModule.getModuleWindow() != null)
+			ownerModule.getModuleWindow().repaintAll();
+	}
+	public void showProjectWindow(){
+		if (ownerModule != null)
+			ownerModule.showProjectWindow();
+	}
+
+	public int refreshSuppression = 0;
+	public boolean refreshPending = false;
+	/*.................................................................................................................*/
+	/** Increments suppression level of menus; if 0 then menus can be reset. */
+	public void incrementProjectWindowSuppression(){
+		refreshSuppression++;
+
+		if (refreshSuppression ==0)
+			refreshSuppression = 1;
+	}
+	/*.................................................................................................................*/
+	/** Decrements suppression level of menus to zero; then menus can be reset. */
+	public void zeroProjectWindowSuppression(){
+		refreshSuppression =1;
+		decrementProjectWindowSuppression();
+	}
+	/*.................................................................................................................*/
+	/** Decrements suppression level of menus; if 0 then menus can be reset. */
+	public void decrementProjectWindowSuppression(){
+		if (refreshSuppression ==0) {
+			MesquiteMessage.warnProgrammer("decrementProjectWindowSuppression when already zero");
+			return;
+		}
+		refreshSuppression--;
+		if (refreshSuppression<0)
+			refreshSuppression =0;
+		if (refreshSuppression ==0){  //menu suppression just removed and requests pending; reset menus
+			if (refreshPending) {
+				if (ownerModule != null)
+					ownerModule.refreshProjectWindow();
+			}
+		}
+	}
+
+	public String toHTMLStringDescription(){
+
+		String s = "";
+		if (getHomeFileName() == null)
+			s += "<h2>Project (without home file)</h2>";
+		else
+			s +="<h2>Project with home file " + getHomeFileName() + "</h2>";
+		if (getHomeDirectoryName() != null)
+			s += "Location: in directory <a href = \"showDirectory:\">" + getHomeDirectoryName() + "</a><p>";
+		if (files.size()>1){
+
+			s += "<hr><h3>Linked files</h3>";
+			for (int i = 0; i<files.size(); i++){
+				MesquiteFile file = (MesquiteFile)files.elementAt(i);
+				if (file != homeFile)
+					s += "<strong>" + file.getName() + "</strong> at " + file.getDirectoryName();
+			}
+			s += "<hr>";
+		}
+		if (taxas.size()>0){
+			s += "<ul>";
+			for (int i = 0; i< taxas.size(); i++){
+				Taxa t = (Taxa)taxas.elementAt(i);
+				s += t.toHTMLStringDescription(); 
+				if (getNumberCharMatrices(t)>0){
+					s += "<ul>";
+					for (int k = 0; k<getNumberCharMatrices(t); k++){
+						CharacterData data = getCharacterMatrix(t, k);
+						s += data.toHTMLStringDescription();
+					}
+					s += "</ul>";
+				}
+				if (getNumberOfFileElements(TreeVector.class)>0){
+					String tr = "";
+					for (int k = 0; k<getNumberOfFileElements(TreeVector.class); k++){
+						TreeVector trees = (TreeVector)getFileElement(TreeVector.class, k);
+						if (trees.getTaxa() == t)
+							tr += trees.toHTMLStringDescription();
+					}
+					if (!StringUtil.blank(tr)){
+						s += "<ul>" + tr + "</ul>";
+					}
+				}
+
+			}
+			s += "</ul>";
+		}
+		return s;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the Trees with given id number */
+	public TreeVector getTreesByID(long id) {
+		//second look for match with .# file number
+		for (int i=0; i<getNumberOfFileElements(TreeVector.class); i++) {
+			TreeVector trees = (TreeVector)getFileElement(TreeVector.class, i);
+			if (id == trees.getID())
+				return trees;
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the Tree Vectors */
+	public ListableVector getTreeVectors() {
+		ListableVector v = new ListableVector();		
+		for (int i=0; i<getNumberOfFileElements(TreeVector.class); i++) {
+			TreeVector trees = (TreeVector)getFileElement(TreeVector.class, i);
+			if (!trees.isDoomed())
+				v.addElement(trees, false);
+		}
+		return v;
+	}
+
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s))
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		String list = "";
+		String cR;
+		if (taxas.size()>0){
+			for (int i = 0; i< taxas.size(); i++){
+				Taxa t = (Taxa)taxas.elementAt(i);
+				cR = t.searchData(s, null);
+				if (!StringUtil.blank(cR))
+					list += cR;
+				if (getNumberCharMatrices(t)>0){
+
+					for (int k = 0; k<getNumberCharMatrices(t); k++){
+						CharacterData data = getCharacterMatrix(t, k);
+						cR = data.searchData(s, null);
+						if (!StringUtil.blank(cR))
+							list += cR;
+					}
+				}
+				if (getNumberOfFileElements(TreeVector.class)>0){
+					String tr = "";
+					for (int k = 0; k<getNumberOfFileElements(TreeVector.class); k++){
+						TreeVector trees = (TreeVector)getFileElement(TreeVector.class, k);
+						if (trees.getTaxa() == t){
+							cR = trees.searchData(s, null);
+							if (!StringUtil.blank(cR))
+								list += cR;
+						}
+					}
+				}
+			}
+		}
+		if (charModels.size()>0){
+			for (int k = 0; k<charModels.size(); k++){
+				FileElement fe = (FileElement)charModels.elementAt(k);
+				cR = fe.searchData(s, null);
+				if (!StringUtil.blank(cR))
+					list += cR;
+			}
+		}
+		if (otherElements.size()>0){
+			for (int k = 0; k<otherElements.size(); k++){
+				FileElement fe = (FileElement)otherElements.elementAt(k);
+				cR = fe.searchData(s, null);
+				if (!StringUtil.blank(cR))
+					list += cR;
+			}
+		}
+		if (StringUtil.blank(list))
+			return "<h2>No matches found (searched: \"" + s + "\")</h2>";
+
+		return "<h2>Matches to search string in " + getName() + ": \"" + s + "\"</h2>" + list;
+	}
+	public void setFrame(MesquiteFrame f){
+		frame = f;
+	}
+	public MesquiteFrame getFrame(){
+		return frame;
+	}
+	/*.................................................................................................................*/
+	/** instantiations of projects are numbered sequentially so they can be referred to by number*/
+	public long getID(){
+		return idNumber;
+	}
+
+	/*.................................................................................................................*/
+	/** Disposes of the components of the project. */
+	public void dispose(){  //TODO: should all the dispose methods be renamed to something  else???
+		isDoomed = true;
+
+
+		for (int i=0; i< files.size(); i++) {
+			((MesquiteFile)files.elementAt(i)).projectClosing = true;
+			((MesquiteFile)files.elementAt(i)).close();
+		}
+		windowToActivate = null;
+		activeWindowOfProject = null;
+		files.dispose();
+		taxas.dispose();
+		datas.dispose();
+		charModels.dispose();
+		otherElements.dispose();
+		nexusBlocks.dispose();
+		files = null;
+		taxas = null;
+		datas = null;
+		charModels = null;
+		otherElements = null;
+		nexusBlocks = null;
+
+		ownerModule = null; // to minimize chance of memory leaks
+		closeCommand= null;
+		closeFilesCommand= null;
+		saveCommand= null;
+		saveFilesCommand= null;
+		saveAsCommand= null;
+		exportCommand= null;
+		getInfoCommand= null;
+		saveLinkagesCommand= null;
+		linkFileCommand =null;
+		newLinkFileCommand = null;
+		linkURLCommand = null;
+		includeFileCommand = null;
+		includeURLCommand = null;
+		totalDisposed++;
+
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	/*.................................................................................................................*/
+	/** returns whether any files are dirty */
+	public boolean isDirty(){  
+		Enumeration enumeration=files.elements();
+		MesquiteFile fi;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof MesquiteFile) {
+				fi = (MesquiteFile)obj;
+				if (fi.isDirty())
+					return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (file == null || file != getHomeFile())
+			return null;
+		boolean saveSnapAttach = anyAttachments();
+		if (name != null || saveSnapAttach) {
+			Snapshot temp = new Snapshot();
+			if (name != null)
+				temp.addLine("setName " + ParseUtil.tokenize(name));
+			if (saveSnapAttach)
+				temp.addLine("attachments "+ writeAttachments(false));
+			return temp;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Here as a placeholder; doesn't do anything at the moment. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns coordinator module of project", null, commandName, "getCoordinatorModule")) {
+			return ownerModule;
+		}
+		else if (checker.compare(this.getClass(), "Stores attachments", null, commandName, "attachments")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			ParseUtil.getToken(arguments, pos);
+			readAttachments(arguments, pos);
+		}
+		else if (checker.compare(this.getClass(), "Sets name", null, commandName, "setName")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			String n = ParseUtil.getToken(arguments, pos);
+			if (n == null && !MesquiteThread.isScripting())
+				n = MesquiteString.queryString(ownerModule.containerOfModule(), "Name of Project", "Name of Project", getName());
+			if (n != null)
+				name = n;
+			if (!MesquiteThread.isScripting()){
+				MesquiteWindow.resetAllTitles();
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the background color scheme for the project's windows.  This is 0, unless multiple projects are open
+	simultaneously, in which case other colors are used as well (to distinguish windows belonging to different projects). */
+	public int getProjectColor(){
+		return projectColor;
+	}
+	/* ---------------------------- DIRECTORIES/NAMES ------------------------------*/
+
+	/** Returns name of directory of home file. */
+	public String getHomeDirectoryName() {
+		if (getHomeFile()==null)
+			return null;
+		return getHomeFile().getDirectoryName();
+	}
+	/*.................................................................................................................*/
+	/** Returns name of home file. */
+	public String getHomeFileName() {
+		if (getHomeFile()==null)
+			return null;
+		return getHomeFile().getFileName();
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the project.  Currently (temporarily?), the name is based upon the name of the home file. */
+	public String getName() {  
+		if (name != null)
+			return name;
+		if (StringUtil.blank(getHomeFileName()))
+			return "Project";
+		return "Project of \"" + getHomeFileName() + "\"";
+	}
+	/*.................................................................................................................*/
+	String name = null;
+	/** Sets the name of the project.   */
+	public void setName(String n) { 
+		name = n;
+	}
+	public boolean hasName(){
+		return name != null;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public URL getHomeURL() {
+		if (getHomeFile()==null)
+			return null;
+		return getHomeFile().getURL();
+	}
+	/* ---------------------------- FILES/DIRECTORES ------------------------------*/
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void setHomeFile(MesquiteFile file){
+		homeFile = file;
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public MesquiteFile getHomeFile(){
+		return homeFile;
+	}
+	/*.................................................................................................................*/
+	/*  writes backup to same directory as home file but with suffix appended to filename.  Returns path to backup*/
+	public String writeBackupOfHomeFile(String suffix){
+		String ac = homeFile.getAutoCopySuffix();
+		homeFile.setWriteAsAutoCopy(suffix);
+		ownerModule.writeFile(homeFile);
+		String name = homeFile.getTempAutoCopyName();
+		homeFile.setWriteAsAutoCopy(ac);
+		return name;
+	}
+	/* Loads backup at path as project with same name and location as current.*/
+	public void revertToBackupOfHomeFile(String path){
+		ownerModule.closeWindows();
+		String oldHomeFileName = getHomeFileName();
+		String dir = getHomeDirectoryName();
+		MesquiteProject newProj = MesquiteTrunk.mesquiteTrunk.newProject(path, 1, true);
+		if (newProj == null)
+			return;
+
+		newProj.getHomeFile().changeLocation(dir, oldHomeFileName);
+		MesquiteFile.deleteFile(dir+ oldHomeFileName);
+		MesquiteFile.rename(path, dir+ oldHomeFileName);
+		ownerModule.iQuit();
+	}
+	/*.................................................................................................................*/
+	/** add a file to list of currently linked files */
+	public void addFile(MesquiteFile file){
+		files.addElement(file, true);
+		refreshProjectWindow();
+	}
+	/*.................................................................................................................*/
+	/** remove a file from list of currently linked files */
+	public void removeFile(MesquiteFile file){
+		removeNexusBlocks(file);
+		files.removeElement(file, true);
+		refreshProjectWindow();
+	}
+	/*.................................................................................................................*/
+	/** Puts all file elements belonging to passed file into home file, and gets rid of record of file. */
+	public void mergeFile(MesquiteFile file){
+		if (file==homeFile)
+			return;
+		if (files.indexOf(file)<0)
+			return;
+		//first, all file elements move to other home file
+		Enumeration enumeration = datas.elements();
+		while (enumeration.hasMoreElements()){
+			FileElement obj = (FileElement)enumeration.nextElement();
+			if (obj.getFile() == file) {
+				obj.setFile(homeFile, false);
+				homeFile.addFileElement(obj);
+			}
+		}
+		enumeration = taxas.elements();
+		while (enumeration.hasMoreElements()){
+			FileElement obj = (FileElement)enumeration.nextElement();
+			if (obj.getFile() == file) {
+				obj.setFile(homeFile, false);
+				homeFile.addFileElement(obj);
+			}
+		}
+		enumeration = charModels.elements();
+		while (enumeration.hasMoreElements()){
+			FileElement obj = (FileElement)enumeration.nextElement();
+			if (obj.getFile() == file) {
+				obj.setFile(homeFile, false);
+				homeFile.addFileElement(obj);
+			}
+		}
+		enumeration = otherElements.elements();
+		while (enumeration.hasMoreElements()){
+			FileElement obj = (FileElement)enumeration.nextElement();
+			if (obj.getFile() == file) {
+				obj.setFile(homeFile, false);
+				homeFile.addFileElement(obj);
+			}
+		}
+		removeFile(file);
+	}
+	/*.................................................................................................................*/
+	/** returns number of currently linked files */
+	public int getNumberLinkedFiles(){
+		if (files == null)
+			return 0;
+		return files.size();
+	}
+	/*.................................................................................................................*/
+	/** returns the index of a currently linked file */
+	public int getFileNumber(MesquiteFile f){
+		if (f == null || files == null)
+			return -1;
+		return files.indexOf(f);
+	}
+	/*.................................................................................................................*/
+	/** returns a currently linked file */
+	public MesquiteFile getFile(String name){
+		return (MesquiteFile)files.getElement(name);
+	}
+	/*.................................................................................................................*/
+	/** returns a currently linked file */
+	public MesquiteFile getFile(int num){
+		if (num<0 || files == null || num>= files.size())
+			return null;
+		return (MesquiteFile)files.elementAt(num);
+	}
+	/*.................................................................................................................*/
+	/** returns a currently linked file */
+	public MesquiteFile getFileByID(int id){  //TODO: FIND BY id number!!!
+		Enumeration enumeration=files.elements();
+		MesquiteFile fi;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof MesquiteFile) {
+				fi = (MesquiteFile)obj;
+				if (fi.getID()==id) {
+					return fi;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns currently linked files */
+	public ListableVector getFiles(){
+		return files;
+	}
+
+	/*.................................................................................................................*/
+	/** Select one of the currently linked files; selects first if only one or if scripting. 12 Jan 02 */
+	public MesquiteFile chooseFile( String message){
+		if (getNumberLinkedFiles()==1 || MesquiteThread.isScripting())
+			return getHomeFile();
+		else 
+			return (MesquiteFile)ListDialog.queryList(ownerModule.containerOfModule(), "Select file", message, MesquiteString.helpString, files, 0);
+	}
+	/* ---------------------------- COMMANDS ------------------------------*/
+	/*.................................................................................................................*/
+	/** returns command to close a file*/
+	public MesquiteCommand getCloseCommand(){
+		return closeCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to close project (linked files)*/
+	public MesquiteCommand getCloseFilesCommand(){
+		return closeFilesCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to close a file*/
+	public MesquiteCommand getShowFileOnDiskCommand(){
+		return showFileOnDiskCommand;
+	}
+
+	/*.................................................................................................................*/
+	/** returns command to save a file*/
+	public MesquiteCommand getSaveCommand(){
+		return saveCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to save project (linked files)*/
+	public MesquiteCommand getSaveFilesCommand(){
+		return saveFilesCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to revert home file to that saved*/
+	public MesquiteCommand getRevertCommand(){
+		return revertCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to link file*/
+	public MesquiteCommand getLinkFileCommand(){
+		return linkFileCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to make new linked file*/
+	public MesquiteCommand getNewLinkFileCommand(){
+		return newLinkFileCommand;
+	}
+
+	/*.................................................................................................................*/
+	/** returns command to link file*/
+	public MesquiteCommand getLinkURLCommand(){
+		return linkURLCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to incorporate file*/
+	public MesquiteCommand getIncludeFileCommand(){
+		return includeFileCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to incorporate file*/
+	public MesquiteCommand getIncludeURLCommand(){
+		return includeURLCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to save as*/
+	public MesquiteCommand getSaveAsCommand(){
+		return saveAsCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns command to save as project (linked files)*/
+	public MesquiteCommand getSaveLinkagesCommand(){
+		return saveLinkagesCommand;
+	}
+	/*.................................................................................................................*/
+	/** returns the file coordinator module in charge of the project*/
+	public FileCoordinator getCoordinatorModule(){
+		return ownerModule;
+	}
+	/* ---------------------------- FILE ELEMENTS ------------------------------*/
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if ((obj == datas || obj == taxas || obj == charModels) && (code == MesquiteListener.PARTS_ADDED || code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_MOVED || code == MesquiteListener.ITEMS_ADDED)){
+			ownerModule.resetAllMenuBars();
+			return;
+		}
+
+		if (code != MesquiteListener.SELECTION_CHANGED)
+			notifyListeners(this, new Notification(MesquiteListener.ELEMENT_CHANGED));
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Adds the passed element to the project.  */
+	public void addFileElement(FileElement element) {
+		if (element==null)
+			return;
+
+		if (element instanceof Taxa) {
+			if (taxas.indexOf(element)<0){
+				taxas.addElement(element, true);
+				element.addListener(taxas);
+			}
+		}
+		else if (element instanceof mesquite.lib.characters.CharacterData){
+			if (datas.indexOf(element)<0){
+				datas.addElement(element, true);
+				element.addListener(datas);
+			}
+		}
+		else if (element instanceof CharacterModel) {
+			if (charModels.indexOf(element)<0){
+				charModels.addElement(element, true);
+				modelListener.addModel((CharacterModel)element);
+			}
+		}
+		else {
+			if (otherElements.indexOf(element)<0)
+				otherElements.addElement(element, true);
+		}
+		element.addListener(this);
+		broadcastAddFileElement(ownerModule, element);
+		notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void removeFileElement(FileElement element) {
+		if (element==null)
+			return;
+		element.removeListener(this);
+		if (element instanceof Taxa) {
+			if (taxas != null) {
+				taxas.removeElement(element, true);
+				element.removeListener(taxas);
+			}
+			//taxas.notifyListenersOfDisposed(element);
+		}
+		else if (element instanceof mesquite.lib.characters.CharacterData) {
+			if (datas != null) {
+				datas.removeElement(element, true);
+				element.removeListener(datas);
+			}
+			//datas.notifyListenersOfDisposed(element);
+		}
+		else if (element instanceof CharacterModel) {
+			if (charModels != null)
+				charModels.removeElement(element, true);
+			//charModels.notifyListenersOfDisposed(element);
+			if (modelListener != null)
+				modelListener.removeModel((CharacterModel)element);
+		}
+		else {
+			if (otherElements != null)
+				otherElements.removeElement(element, true);
+			//otherElements.notifyListenersOfDisposed(element);
+		}
+		notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+		//TODO: shouldn't broadcase of deletion be here?
+	}
+	/*.................................................................................................................*/
+	/** DOCUMENT */
+	public void removeAllFileElements(Class c, boolean notify) {
+		if (Taxa.class.isAssignableFrom(c)) {
+			if (taxas != null){
+				for (int i = 0; i< taxas.size(); i++){
+					FileElement element = (FileElement)taxas.elementAt(i);
+					element.deleteMe(false);
+				}
+				taxas.removeAllElements(notify);
+			}
+		}
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c)){
+
+			if (datas != null){
+				for (int i = 0; i< datas.size(); i++){
+					FileElement element = (FileElement)datas.elementAt(i);
+					element.deleteMe(false);
+				}
+				datas.removeAllElements(notify);
+			}
+		}
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			if (charModels != null){
+				for (int i = 0; i< charModels.size(); i++){
+					FileElement element = (FileElement)charModels.elementAt(i);
+					element.deleteMe(false);
+				}
+				charModels.removeAllElements(notify);
+			}
+		}
+		else {
+			if (otherElements != null){
+				for (int i = 0; i< otherElements.size(); i++){
+					FileElement element = (FileElement)otherElements.elementAt(i);
+					if (element.getClass().isAssignableFrom(c))
+						element.deleteMe(false);
+				}
+			}
+		}
+	}	
+	/*.................................................................................................................*/
+	public void removeAllFileElements(boolean notify) {
+		if (taxas != null){
+			for (int i = 0; i< taxas.size(); i++){
+				FileElement element = (FileElement)taxas.elementAt(i);
+				element.deleteMe(false);
+			}
+			taxas.removeAllElements(notify);
+		}
+
+		if (datas != null){
+			for (int i = 0; i< datas.size(); i++){
+				FileElement element = (FileElement)datas.elementAt(i);
+				element.deleteMe(false);
+			}
+			datas.removeAllElements(notify);
+		}
+
+		if (charModels != null){
+			for (int i = 0; i< charModels.size(); i++){
+				FileElement element = (FileElement)charModels.elementAt(i);
+				element.deleteMe(false);
+			}
+			charModels.removeAllElements(notify);
+		}
+
+		if (otherElements != null){
+			for (int i = 0; i< otherElements.size(); i++){
+				FileElement element = (FileElement)otherElements.elementAt(i);
+				element.deleteMe(false);
+			}
+		}
+	}	
+
+	/*.................................................................................................................*/
+	/** Returns the number of FileElements that are subclasses of the given class.  */
+	public int getNumberOfFileElements(Class c) {
+		if (c ==null)
+			return 0;
+
+		if (Taxa.class.isAssignableFrom(c)) {
+			return taxas.size();
+		}
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c))
+			return datas.size();
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			return charModels.size();
+		}
+		else {
+			return otherElements.size(c);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Sets elements of file as not dirty (i.e. saved).  */
+	public void fileSaved(MesquiteFile f) {
+		try {
+			if (f == null)
+				return;
+			f.setDirtiedByCommand(false);
+			for (int i=0; i<taxas.size(); i++) {
+				FileElement fe = (FileElement)taxas.elementAt(i);
+				if (fe.getFile() == f)
+					fe.setDirty(false);
+			}
+			for (int i=0; i<datas.size(); i++) {
+				FileElement fe = (FileElement)datas.elementAt(i);
+				if (fe.getFile() == f)
+					fe.setDirty(false);
+			}
+			for (int i=0; i<charModels.size(); i++) {
+				FileElement fe = (FileElement)charModels.elementAt(i);
+				if (fe.getFile() == f)
+					fe.setDirty(false);
+			}
+			for (int i=0; i<otherElements.size(); i++) {
+				FileElement fe = (FileElement)otherElements.elementAt(i);
+				if (fe.getFile() == f)
+					fe.setDirty(false);
+			}
+		}
+		catch (NullPointerException e){
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** Returns a vector of FileElements that are of the given class or are of its subclasses.  */
+	public Listable[] getFileElements(Class c) {
+		if (c ==null)
+			return null;
+
+		if (Taxa.class.isAssignableFrom(c)) {
+			return taxas.getElementArray();
+		}
+		else if (mesquite.lib.characters.CharacterData.class == c)
+			return datas.getElementArray();
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c)) {
+			int count =0;
+			for (int i=0; i<datas.size(); i++)
+				if (c.isAssignableFrom(datas.elementAt(i).getClass()))
+					count++;
+			Listable[] v = new Listable[count];
+			count =0;
+			for (int i=0; i<datas.size(); i++)
+				if (c.isAssignableFrom(datas.elementAt(i).getClass())) {
+					v[count] = (Listable)datas.elementAt(i);
+					count++;
+				}
+			return v;
+		}
+		else if (CharacterModel.class == c)
+			return charModels.getElementArray();
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			int count =0;
+			for (int i=0; i<charModels.size(); i++)
+				if (c.isAssignableFrom(charModels.elementAt(i).getClass()))
+					count++;
+			Listable[] v = new Listable[count];
+			count =0;
+			for (int i=0; i<charModels.size(); i++)
+				if (c.isAssignableFrom(charModels.elementAt(i).getClass())) {
+					v[count] = (Listable)charModels.elementAt(i);
+					count++;
+				}
+			return v;
+		}
+		else {
+			int count =0;
+			for (int i=0; i<otherElements.size(); i++)
+				if (c.isAssignableFrom(otherElements.elementAt(i).getClass())) {
+					count++;
+				}
+			Listable[] v = new Listable[count];
+			count =0;
+			for (int i=0; i<otherElements.size(); i++)
+				if (c.isAssignableFrom(otherElements.elementAt(i).getClass())) {
+					v[count] = (Listable)otherElements.elementAt(i);
+					count++;
+				}
+			return v;
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** Returns a vector of FileElements that are of the given class or are of its subclasses, and which are compatible with the passed object.  */
+	public Listable[] getCompatibleFileElements(Class c, Object condition) {
+		if (c ==null)
+			return null;
+		Listable[] elementArray = getFileElements(c); //first get all elements, then filter for compatibility
+		if (elementArray == null)
+			return null;
+		if (condition == null)
+			return elementArray;
+		int count =0;
+		for (int i=0; i<elementArray.length; i++) {
+			Object element = elementArray[i];
+			if (element instanceof CompatibilityChecker){
+				if (((CompatibilityChecker)element).isCompatible(condition, this, null)){
+					count++;
+				}
+			}
+			else
+				count++;
+		}
+		Listable[] v = new Listable[count];
+		count =0;
+		for (int i=0; i<elementArray.length; i++) {
+			Object element = elementArray[i];
+			if (element instanceof CompatibilityChecker){
+				if (((CompatibilityChecker)element).isCompatible(condition, this, null)){
+					v[count] = (Listable)element;
+					count++;
+				}
+			}
+			else {
+				v[count] = (Listable)element;
+				count++;
+			}
+		}
+		return v;
+	}
+	/*.................................................................................................................*/
+	/** Returns the ith FileElement that is a subclass of the given class.  */
+	public FileElement getFileElement(Class c, int i) {
+		if (c ==null || i<0)
+			return null;
+
+		if (Taxa.class.isAssignableFrom(c)) {
+			if (i< taxas.size())
+				return (FileElement)taxas.elementAt(i);
+		}
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c)) {
+			if (i< datas.size())
+				return (FileElement)datas.elementAt(i);
+		}
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			if (i< charModels.size())
+				return (FileElement)charModels.elementAt(i);
+		}
+		else {
+			int count =0;
+			Enumeration e = otherElements.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (c.isAssignableFrom(obj.getClass())) {
+					if (count == i)
+						return (FileElement)obj;
+					count ++;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the index position of the  FileElement among others of its the subclass c.  */
+	public int getFileElementNumber(FileElement f, Class c) {
+		if (f ==null || c==null)
+			return -1;
+
+		if (Taxa.class.isAssignableFrom(c)) {
+			return getTaxaNumber((Taxa)f);
+		}
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c)) {
+			return getMatrixNumber((mesquite.lib.characters.CharacterData)f);
+		}
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			int count =0;
+			Enumeration e = charModels.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (c.isAssignableFrom(obj.getClass())) {
+					if (obj == f)
+						return count;
+					count ++;
+				}
+			}
+		}
+		else {
+			int count =0;
+			Enumeration e = otherElements.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (c.isAssignableFrom(obj.getClass())) {
+					if (obj == f)
+						return count;
+					count ++;
+				}
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/* A method called to broadcast to all descendent modules that file element has been added.*/
+	private void broadcastAddFileElement(MesquiteModule module, FileElement element) {
+		module.fileElementAdded(element);
+		EmployeeVector e = module.getEmployeeVector();
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+			broadcastAddFileElement(employee, element);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Adds the passed NEXUS block to the project. */
+	public void addNexusBlock(NexusBlock block) {
+		nexusBlocks.addElement(block, true);
+	}
+	/*.................................................................................................................*/
+	/** Removes the passed NEXUS block  from the project. */
+	public void removeNexusBlock(NexusBlock block) {
+		if (nexusBlocks != null) {
+			if (block !=null) {
+				if (files.indexOf(block.getFile())<0)
+					MesquiteMessage.warnProgrammer("Error: NEXUS block found referring to file that no longer exists " + block.getClass());
+				nexusBlocks.removeElement(block, true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns those NEXUS blocks belonging to the given file. */
+	public void removeNexusBlocks(MesquiteFile f) {
+		if (nexusBlocks==null)
+			return;
+		int count = 0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (nb.getFile()==f)
+				count++;
+		}
+		if (count==0)
+			return;
+		NexusBlock[] nbs = new NexusBlock[count];
+		count=0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (nb.getFile()==f) {
+				nbs[count]= nb;
+				count++;
+			}
+		}
+
+		for (int i = 0; i<count; i++) {
+			removeNexusBlock(nbs[i]);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns an array of NEXUS blocks of the given type and belonging to the given file. */
+	public NexusBlock[] getNexusBlocks(Class c, MesquiteFile f) {
+		int count = 0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (c.isAssignableFrom(nb.getClass()) && (nb.getFile()==f || f == null))
+				count++;
+		}
+		if (count==0)
+			return null;
+		NexusBlock[] nbs = new NexusBlock[count];
+		count=0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (c.isAssignableFrom(nb.getClass()) &&  (nb.getFile()==f || f == null)) {
+				nbs[count]= nb;
+				count++;
+			}
+		}
+		return nbs;
+	}
+	/*.................................................................................................................*/
+	/** Returns an array of NEXUS blocks of the given type name. 12 Jan 02*/
+	public NexusBlock[] getNexusBlocks(String typeName) {
+		if (StringUtil.blank(typeName))
+			return null;
+		int count = 0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (typeName.equalsIgnoreCase(nb.getBlockName()))
+				count++;
+		}
+		if (count==0)
+			return null;
+		NexusBlock[] nbs = new NexusBlock[count];
+		count=0;
+		for (int i = 0; i<nexusBlocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)nexusBlocks.elementAt(i);
+			if (typeName.equalsIgnoreCase(nb.getBlockName())) {
+				nbs[count]= nb;
+				count++;
+			}
+		}
+		return nbs;
+	}
+	/*.................................................................................................................*/
+	/** Returns the ListableVector of NEXUS blocks in the project. */
+	public ListableVector getNexusBlocks() {
+		return nexusBlocks;
+	}
+
+	/* ---------------------------- AUTHORS ------------------------------*/
+	ListableVector authors;
+	public ListableVector getAuthors(){
+		if (authors == null)
+			authors = new ListableVector();
+		return authors;
+	}
+
+	public int numAuthors(){
+		if (authors == null)
+			return 0;
+		return authors.size();
+	}
+	public Author findAuthor(String s, boolean tryName){
+		if (s == null)
+			return null;
+		//first, interpret as code
+		if (MesquiteModule.author != null && s.equals(MesquiteModule.author.getCode()))
+			return MesquiteModule.author;
+		if (numAuthors()>0){
+			ListableVector v = getAuthors();
+			for (int i = 0; i< v.size(); i++){
+				Author a = (Author)v.elementAt(i);
+				if (a.getCode()!= null && s.equals(a.getCode()))
+					return a;
+			}
+		}
+		if (tryName){
+			//second, try as author name
+			if (MesquiteModule.author != null && s.equals(MesquiteModule.author.getName()))
+				return MesquiteModule.author;
+			if (numAuthors()>0){
+				ListableVector v = getAuthors();
+				for (int i = 0; i< v.size(); i++){
+					Author a = (Author)v.elementAt(i);
+					if (a.getName()!= null && s.equals(a.getName()))
+						return a;
+				}
+			}
+		}
+		return null;
+	}
+	//hackathon
+	public ListableVector getOtherElements(){
+		return otherElements;
+	}
+	/* ---------------------------- TAXA ------------------------------*/
+	public Taxa createTaxaBlock(int numTaxa){
+		TaxaManager mTaxa = (TaxaManager)ownerModule.findEmployeeWithDuty(TaxaManager.class);
+		Object t = null;
+		if (mTaxa!=null)
+			t = mTaxa.doCommand("newTaxa",Integer.toString(numTaxa) + " " + ParseUtil.tokenize("taxa"), CommandChecker.defaultChecker); //treat as scripting so as not to complain if something not found 19Jan02
+		return (Taxa)t;
+	}
+	/*.................................................................................................................*/
+	/** returns the list of Taxa  */
+	public ListableVector getTaxas() {
+		return taxas;
+	}
+	/*.................................................................................................................*/
+	/** Returns the number of FileElements that are subclasses of the given class.  */
+	public FileElement getElementByID(Class c, int id) {
+		if (c ==null)
+			return null;
+
+		if (Taxa.class.isAssignableFrom(c)) {
+			for (int i = 0; i<taxas.size(); i++){
+				FileElement element = (FileElement)taxas.elementAt(i);
+				if (element.getID() == id)
+					return element;
+			}
+		}
+		else if (mesquite.lib.characters.CharacterData.class.isAssignableFrom(c)) {
+			for (int i = 0; i<datas.size(); i++){
+				FileElement element = (FileElement)datas.elementAt(i);
+				if (element.getID() == id)
+					return element;
+			}
+		}
+		else if (CharacterModel.class.isAssignableFrom(c)) {
+			for (int i = 0; i<charModels.size(); i++){
+				FileElement element = (FileElement)charModels.elementAt(i);
+				if (element.getID() == id)
+					return element;
+			}
+		}
+		else {
+			for (int i = 0; i<otherElements.size(); i++){
+				FileElement element = (FileElement)otherElements.elementAt(i);
+				if (element.getID() == id)
+					return element;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa of given number */
+	public Taxa getTaxa(int taxaNumber) {
+		if (taxaNumber>=0 && taxaNumber < taxas.size())
+			return (Taxa)taxas.elementAt(taxaNumber);
+		MesquiteMessage.warnProgrammer("Error: attempt to get taxa set " + taxaNumber + "; maximum  " + taxas.size());
+		MesquiteMessage.printStackTrace();
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa with given id number */
+	public Taxa getTaxaByID(long id) {
+		//second look for match with .# file number
+		for (int i=0; i<taxas.size(); i++) {
+			Taxa taxa = (Taxa)taxas.elementAt(i);
+			if (id == taxa.getID())
+				return taxa;
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the Taxa of given name */
+	public Taxa getTaxaLastFirst(String name) {
+		return getTaxaLastFirst(null, name);
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa of given reference, name or number (as indicated by string passed) */
+	public Taxa getTaxaLastFirst(MesquiteFile f, String ref) {
+		if (ref==null)
+			return null;
+		if (ref.length()>1 && ref.charAt(0)=='#'){ //using id number reference
+			String id = ref.substring(1, ref.length());
+			//first look for direct match in same file
+			for (int i=taxas.size()-1; i>=0; i--) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if ((f==null || f == taxa.getFile()) && id.equals(taxa.getAssignedID()))
+					return taxa;
+
+			}
+			//second look for match with .# file number
+			for (int i=taxas.size()-1; i>=0; i--) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if (f != null && (id.indexOf('.') < 0)){
+					String supID = id + "." + f.getID();
+					if (supID.equals(taxa.getAssignedID())) {
+						return taxa;
+					}
+				}
+			}
+			//third strip file number and see if match
+			for (int i=taxas.size()-1; i>=0; i--) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if ((taxa.getAssignedID().indexOf('.') >= 0)){
+					String supID2 = taxa.getAssignedID().substring(0, taxa.getAssignedID().indexOf('.'));
+					if (id.equals(supID2)) {
+						return taxa;
+					}
+				}
+
+			}
+		}
+		else { 
+			for (int i=taxas.size()-1; i>=0; i--) {
+				//check to see if name of taxa is being passed
+				Taxa t = (Taxa)taxas.elementAt(i);
+				if (t.getName()!=null && t.getName().equalsIgnoreCase(ref) && (f==null || t.getFile() == f))
+					return (Taxa)taxas.elementAt(i);
+			}
+
+			return getTaxa(f, MesquiteInteger.fromString(ref)); //try to see if number
+
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa of given name */
+	public Taxa getTaxa(String name) {
+		return getTaxa(null, name);
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa of given reference, name or number (as indicated by string passed) */
+	public Taxa getTaxa(MesquiteFile f, String ref) {
+		if (ref==null)
+			return null;
+		if (ref.length()>1 && ref.charAt(0)=='#'){ //using id number reference
+			String id = ref.substring(1, ref.length());
+			//first look for direct match in same file
+			for (int i=0; i<taxas.size(); i++) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if ((f==null || f == taxa.getFile()) && id.equals(taxa.getAssignedID()))
+					return taxa;
+
+			}
+			//second look for match with .# file number
+			for (int i=0; i<taxas.size(); i++) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if (f != null && (id.indexOf('.') < 0)){
+					String supID = id + "." + f.getID();
+					if (supID.equals(taxa.getAssignedID())) {
+						return taxa;
+					}
+				}
+			}
+			//third strip file number and see if match
+			for (int i=0; i<taxas.size(); i++) {
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				if ((taxa.getAssignedID().indexOf('.') >= 0)){
+					String supID2 = taxa.getAssignedID().substring(0, taxa.getAssignedID().indexOf('.'));
+					if (id.equals(supID2)) {
+						return taxa;
+					}
+				}
+
+			}
+		}
+		else { 
+			for (int i=0; i<taxas.size(); i++) { //check to see if name of taxa is being passed
+				Taxa t = (Taxa)taxas.elementAt(i);
+				if (t.getName()!=null && t.getName().equalsIgnoreCase(ref) && (f==null || t.getFile() == f))
+					return (Taxa)taxas.elementAt(i);
+			}
+
+			return getTaxa(f, MesquiteInteger.fromString(ref)); //try to see if number
+
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the jth of taxa blocks with given unique ID*/
+	public Taxa getTaxa(String uniqueID, int j) {
+		int count=0;
+		for (int i=0; i<taxas.size(); i++) { 
+			Taxa taxa = (Taxa)taxas.elementAt(i);
+
+			if (!taxa.isDoomed()  && uniqueID != null && taxa.getUniqueID() != null && taxa.getUniqueID().equals(uniqueID)) {
+				if (count==j) {
+					return taxa;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the Taxa of given number belonging to given file */
+	public Taxa getTaxa(MesquiteFile f, int taxaNumber) {
+		int count=0;
+		for (int i=0; i<taxas.size(); i++) {
+			Taxa taxa = ((Taxa)taxas.elementAt(i));
+			if (f== null || taxa.getFile()==f) {
+				if (count==taxaNumber)
+					return taxa;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the number (index position) of the Taxa of given name */
+	public int getTaxaNumber(String name) {
+		for (int i=0; i<taxas.size(); i++) {
+			if (((Taxa)taxas.elementAt(i)).getName().equalsIgnoreCase(name))
+				return i;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** returns the number (index position) of the Taxa */
+	public int getTaxaNumber(MesquiteFile file, Taxa taxa) {
+		if (file == null)
+			return getTaxaNumber(taxa);
+		if (taxa==null)
+			return -1;
+		int count =0;
+		for (int i=0; i<taxas.size(); i++) {
+			Taxa t = ((Taxa)taxas.elementAt(i));
+			if (t== taxa) 
+				return count;
+			if (t.getFile()==file)
+				count++;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** returns the number (index position) of the Taxa */
+	public int getTaxaNumber(Taxa taxa) {
+		if (taxa==null)
+			return -1;
+		if (taxa.isDuplicate()){ //This subverts the taxa if it's a duplicate, instead giving number of original copy
+			for (int i=0; i<taxas.size(); i++) {
+				Taxa t =(Taxa)taxas.elementAt(i);
+				if (taxa.equals(t, false, true) && !t.isDuplicate()) {
+					return i;
+				}
+			}
+		}
+		for (int i=0; i<taxas.size(); i++) {
+			if (((Taxa)taxas.elementAt(i)) == taxa) {
+				return i;
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** returns a string that can be used to refer to  taxa block */
+	public String getTaxaReferenceInternal(Taxa taxa) {
+		if (taxa == null)
+			return null;
+		return "#" + taxa.getAssignedID();
+	}
+	/*.................................................................................................................*/
+	/** returns a string that can be used to refer to  taxa block */
+	public String getTaxaReferenceExternal(Taxa taxa) {
+		if (taxa == null)
+			return null;
+		return "#" + taxa.getAssignedIDNumber();
+	}
+	/*.................................................................................................................*/
+	/** This is deprecated and should be avoided */
+	public String getTaxaReference(Taxa taxa) {
+		return getTaxaReferenceExternal(taxa);
+	}
+	/*.................................................................................................................*/
+	public Taxa chooseTaxa(MesquiteWindow frame, String message){
+		return chooseTaxa(frame, message, false,null,null);
+	}
+	/*.................................................................................................................*/
+	public Taxa chooseTaxa(MesquiteWindow frame, String message, boolean askEvenIfOne){
+		return chooseTaxa(frame,message,askEvenIfOne,null,null);
+	}
+	/*.................................................................................................................*/
+	public Taxa chooseTaxa(MesquiteWindow frame, String message, boolean askEvenIfOne, String okButton, String cancelButton){
+		int num = getNumberTaxas();
+		if (num==0)
+			return null;
+		else if ((num==1 && !askEvenIfOne) || (MesquiteThread.isScripting() && num>=1))
+			return getTaxa(0);
+		String[] taxaNames = new String[num];
+		for (int i=0; i<num;i++) 
+			taxaNames[i] = getTaxa(i).getName();
+		int whichTaxa = ListDialog.queryList(frame, "Select taxa", message, MesquiteString.helpString, taxaNames, 0, okButton, cancelButton);
+		if (!MesquiteInteger.isCombinable(whichTaxa)) 
+			return null;
+		else if (whichTaxa>=0) 
+			return getTaxa(whichTaxa);
+		else
+			return getTaxa(0);
+	}
+	/*.................................................................................................................*/
+	public Taxa findTaxa(MesquiteFile file, String token){
+		Taxa t = getTaxaLastFirst(file, token);
+		if (t == null && file != null){
+			Listable ms = file.taxaNameTranslationTable.elementWithName(token);
+			if (ms != null)
+				token = ((MesquiteString)ms).getValue();  //substitute translated name
+		}
+		if (t==null)
+			t = getTaxaLastFirst(token);
+		if (t==null){
+			int wt = MesquiteInteger.fromString(token);
+			if (MesquiteInteger.isCombinable(wt))
+				t = getTaxa(wt-1);
+		}
+		if (t == null && getNumberTaxas(file)==1)
+			t = getTaxa(file, 0);
+		if (t == null && getNumberTaxas(file)>1)
+			t = getTaxa(file, getNumberTaxas(file)-1);
+		if (t == null && getNumberTaxas()==1)
+			t = getTaxa(0);
+		if (t == null && getNumberTaxas()>1)
+			t = getTaxa(getNumberTaxas()-1);
+		return t;
+	}
+	/*.................................................................................................................*/
+	public CharacterData findCharacterMatrix(MesquiteFile file, Taxa defaultTaxa, String token){
+		CharacterData d = getCharacterMatrixReverseOrder(file, token);
+		if (d == null && file != null){
+			Listable ms = file.characterDataNameTranslationTable.elementWithName(token);
+			if (ms != null)
+				token = ((MesquiteString)ms).getValue();  //substitute translated name
+		}
+		if (d==null)
+			d = getCharacterMatrixReverseOrder(token);
+		if (d==null){
+			int wt = MesquiteInteger.fromString(token);
+			if (MesquiteInteger.isCombinable(wt))
+				d = getCharacterMatrix(defaultTaxa, wt-1);
+		}
+		if (d == null && getNumberCharMatrices(file)==1){
+			d = getCharacterMatrix(file, 0);
+		}
+		if (d == null && getNumberCharMatrices()==1){
+			d = getCharacterMatrix(0);
+		}
+		return d;
+	}
+	/*.................................................................................................................*/
+	//TODO: ��� have general get number of elements, passing project, or file; counts
+	/** returns the number of Taxa objects stored in project belonging to a file*/
+	public int  getNumberTaxas(MesquiteFile f) {
+		int count = 0;
+		for (int i=0; i<taxas.size(); i++) {
+			if (f==null || ((Taxa)taxas.elementAt(i)).getFile()==f)
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int  getNumberTaxas(String uniqueID) {
+		int count = 0;
+		for (int i=0; i<taxas.size(); i++) {
+			Taxa taxa = (Taxa)taxas.elementAt(i);
+			if (uniqueID != null && taxa.getUniqueID() != null && taxa.getUniqueID().equals(uniqueID))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	/** returns the number of Taxa objects stored in project */
+	public int  getNumberTaxas() {
+		if (taxas == null)
+			return 0;
+		return taxas.size();
+	}
+
+	public TreeVector storeTree(MesquiteWindow parent, TreeVector trees, Tree tree, boolean askIfSingleBlock){
+		if (ownerModule == null || tree == null)
+			return null;
+		if (trees == null){
+			TreesManager manager = (TreesManager)ownerModule.findElementManager(TreeVector.class);
+			if (manager !=null){
+				int numLists = manager.getNumberTreeBlocks(tree.getTaxa());
+				if (numLists==0) {
+					String treesListName = MesquiteString.queryString(parent, "New Tree Block" , "Name of new Tree Block: ", "Trees");
+					MesquiteFile f = ownerModule.getProject().chooseFile("In which file should new tree block be placed?");  
+					trees = manager.makeNewTreeBlock(tree.getTaxa(), treesListName, f);
+				}
+				else if (numLists == 1 && !askIfSingleBlock){
+					trees = manager.getTreeBlock(tree.getTaxa(), 0);
+				}
+				else {
+					Listable[] lists = new Listable[numLists+1];
+					for (int i=0; i<numLists; i++)
+						lists[i] = manager.getTreeBlock(tree.getTaxa(), i);
+					lists[numLists] = new MesquiteString("New Trees Block...", "New Trees Block...");
+					Object obj = ListDialog.queryList(parent, "Where to store tree?", "Choose tree block in which to store tree:",MesquiteString.helpString, lists, 0);
+					if (obj instanceof MesquiteString){
+						ListableVector v = manager.getTreeBlockVector();
+						String suggestedName = v.getUniqueName("Trees");
+						String treesListName = MesquiteString.queryString(parent, "New Tree Block" , "Name of new Tree Block: ", suggestedName);
+						MesquiteFile f = ownerModule.getProject().chooseFile("In which file should new tree block be placed?");  
+						trees = manager.makeNewTreeBlock(tree.getTaxa(), treesListName, f);
+					}
+					else
+						trees = (TreeVector)obj;
+				}
+			}
+		}
+		if (trees!=null) {
+			trees.addElement(tree, true);
+			return trees;
+		}
+		return null;
+	}
+	/* ---------------------------- CHARACTERDATA ------------------------------*/
+	/*.................................................................................................................*/
+	/** returns jth data set in file*/
+	public ListableVector getCharacterMatrices() {
+		return datas;
+	}
+	/*.................................................................................................................*/
+	//NOTE: dataClass to be used is subclass of CharacterState, not of CharacterData
+	public boolean compatibleMatrix(Object dataClass, mesquite.lib.characters.CharacterData data){
+		if (dataClass ==null)
+			return true;
+		if (dataClass instanceof Class){
+			return ((Class)dataClass).isAssignableFrom(data.getStateClass());
+		}
+		else if (dataClass instanceof Class[]){
+			Class[] dataClasses = ((Class[])dataClass);
+			for (int i=0; i<dataClasses.length; i++){
+				if (dataClasses[i].isAssignableFrom(data.getStateClass()))
+					return true;
+			}
+			return false;
+		}
+		return false;
+	}
+	/*===============================================================*/
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets in file*/
+	public int  getNumberCharMatrices() { //CORE, collab, chromaseq, STRAT TOOLS
+		return getNumberCharMatrices(null, null, null, false);
+	}
+	/*......................*/
+	/** returns jth data set in file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(int j) {  //core, chromaseq, collab; can use RAW
+		return getCharacterMatrix(j, false);
+	}
+	public mesquite.lib.characters.CharacterData getCharacterMatrixDoomedOrNot(int j) {  
+		int count=0;
+		mesquite.lib.characters.CharacterData data;
+		for (int i=0; i<datas.size(); i++) {
+			data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if (count==j)
+				return data;
+			count++;
+
+		}
+		MesquiteTrunk.mesquiteTrunk.logln("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		MesquiteMessage.printStackTrace("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		return null;
+	}
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(int j, boolean onlyVisible) {  //core, chromaseq, collab; can use RAW
+		int count=0;
+		mesquite.lib.characters.CharacterData data;
+		for (int i=0; i<datas.size(); i++) {
+			data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if (!data.isDoomed() && (!onlyVisible || data.isUserVisible())) {
+				if (count==j)
+					return data;
+				count++;
+			}
+		}
+		MesquiteTrunk.mesquiteTrunk.logln("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		MesquiteMessage.printStackTrace("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		return null;
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets in file*/
+	public int  getNumberCharMatricesVisible() { //���
+		return getNumberCharMatrices(null, null, null, true);
+	}
+	/*......................*/
+	/** returns jth data set in file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixVisible(int j) {  //core, chromaseq, collab; can use RAW
+		int count=0;
+		mesquite.lib.characters.CharacterData data;
+		for (int i=0; i<datas.size(); i++) {
+			data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if (data.isUserVisible() && !data.isDoomed()) {
+				if (count==j)
+					return data;
+				count++;
+			}
+		}
+		MesquiteTrunk.mesquiteTrunk.logln("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		MesquiteMessage.printStackTrace("Error: attempt to get data set beyond number (0) [" + j + "] {" + datas.size() + " }"  + getName());
+		return null;
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets belonging to given taxa*/
+	public int  getNumberCharMatrices(Taxa taxa) { //�����
+		return getNumberCharMatrices(null, taxa, null, false);
+	}
+	/*......................*/
+	/** returns the jth data set belonging to given taxa.*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(Taxa taxa, int j) { //core, collab, ppod, rLink
+		return getCharacterMatrix(null, taxa, null, j, false);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets belonging to given taxa*/
+	public int  getNumberCharMatricesVisible(Taxa taxa) { //�����
+		return getNumberCharMatrices(null, taxa, null, true);
+	}
+	/*......................*/
+	/** returns the jth data set belonging to given taxa.*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixVisible(Taxa taxa, int j) { //core, collab, ppod, rLink
+		return getCharacterMatrix(null, taxa, null, j, true);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed)*/
+	public int  getNumberCharMatricesVisible(Object dataClass) {  //�����
+		return getNumberCharMatrices(null, null, dataClass, true);
+	}
+	/*......................*/
+	/** returns the jth data set for given CharacterState subclass.*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixVisible(int j, Object dataClass) {  //stepmatrix model ONLY
+		return getCharacterMatrix(null, null, dataClass, j, true);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed)*/
+	public int  getNumberCharMatrices(Object dataClass) {  //�����
+		return getNumberCharMatrices(null, null, dataClass, false);
+	}
+	/*......................*/
+	/** returns the jth data set for given CharacterState subclass.*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(int j, Object dataClass) {  //stepmatrix model ONLY
+		return getCharacterMatrix(null, null, dataClass, j, false);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed) belonging to given taxa*/
+	public int  getNumberCharMatricesVisible(Taxa taxa, Object dataClass) {  //�����
+		return getNumberCharMatrices(null, taxa, dataClass, true);
+	}
+	/*......................*/
+	/** returns the jth data set belonging to given taxa for given CharacterState subclass.*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixVisible(Taxa taxa, int j, Object dataClass) { //����
+		return getCharacterMatrix(null, taxa, dataClass, j, true);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets belonging to a given file*/
+	public int  getNumberCharMatrices(MesquiteFile f) { //�����
+		return getNumberCharMatrices(f, null, null, false);
+	}
+	/*......................*/
+	/** returns the jth of data sets belonging to a given file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(MesquiteFile f, int j) {  //�����
+		return getCharacterMatrix(f, null, null, j, false);
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed) belonging to given taxa.  If permitTaxaMatching is true, 
+	 * considers taxa equal if names coincide*/
+	public int  getNumberCharMatricesDoomedOrNot(MesquiteFile file, Taxa taxa, Object dataClass) {  //MesquiteProject
+		int count=0;
+		if (datas == null)
+			return 0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if ((file == null || data.getFile()==file) && (taxa == null || taxa == data.getTaxa()) && (dataClass==null || compatibleMatrix(dataClass, data)))
+				count++;
+		}
+		return count;
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed) belonging to given taxa.  If permitTaxaMatching is true, 
+	 * considers taxa equal if names coincide*/
+	public int  getNumberCharMatrices(MesquiteFile file, Taxa taxa, Object dataClass, boolean visibleOnly) {  //MesquiteProject
+		int count=0;
+		if (datas == null)
+			return 0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if ((!visibleOnly || data.isUserVisible()) && !data.isDoomed() && (file == null || data.getFile()==file) && (taxa == null || taxa == data.getTaxa()) && (dataClass==null || compatibleMatrix(dataClass, data)))
+				count++;
+		}
+		return count;
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns number of data sets of a given data class (CharacterState subclass is passed) belonging to given taxa.  If permitTaxaMatching is true, 
+	 * considers taxa equal if names coincide*/
+	public int  getNumberCharMatricesExactClass(MesquiteFile file, Taxa taxa, Object dataClass, boolean visibleOnly) {  //MesquiteProject
+		int count=0;
+		if (datas == null)
+			return 0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+			if ((!visibleOnly || data.isUserVisible()) && !data.isDoomed() && (file == null || data.getFile()==file) && (taxa == null || taxa == data.getTaxa()) && (dataClass==null || dataClass == data.getStateClass()))
+				count++;
+		}
+		return count;
+	}
+	/*......................*/
+	/** returns the jth of data sets belonging to a given file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixVisible(MesquiteFile f, Taxa taxa, Object dataClass, int j) {  //���� not used yet
+		return getCharacterMatrix(f, taxa, dataClass, j, true);
+	}
+	/*......................*/
+	/** returns the jth of data sets belonging to a given file*/
+	private mesquite.lib.characters.CharacterData getCharacterMatrix(MesquiteFile f, Taxa taxa, Object dataClass, int j) {  //����
+		return getCharacterMatrix(f, taxa, dataClass, j, false);
+	}
+	/*......................*/
+	/** returns the jth of data sets belonging to a given file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrix(MesquiteFile f, Taxa taxa, Object dataClass, int j, boolean visibleOnly) {  //MesquiteProject only
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if ((!visibleOnly || data.isUserVisible()) && !data.isDoomed() && (f== null || data.getFile()==f) && (taxa == null || taxa == data.getTaxa()) && (dataClass == null || compatibleMatrix(dataClass, data))) {
+				if (count==j) {
+					return data;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*......................*/
+	/** returns the jth of data sets belonging to a given file*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixExactClass(MesquiteFile f, Taxa taxa, Object dataClass, int j, boolean visibleOnly) {  //MesquiteProject only
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if ((!visibleOnly || data.isUserVisible()) && !data.isDoomed() && (f== null || data.getFile()==f) && (taxa == null || taxa == data.getTaxa()) && (dataClass == null || dataClass == data.getStateClass())) {
+				if (count==j) {
+					return data;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*---------===---------===---------===---------===---------===---------===-------------------*/
+	/** returns the jth of data sets with given unique ID*/
+	public mesquite.lib.characters.CharacterData getCharacterMatrixByUniqueID(String uniqueID, int j) {  //ManageCharacters only
+		int count=0;
+		for (int i=0; i<datas.size(); i++) { 
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if (!data.isDoomed()  && uniqueID != null && data.getUniqueID() != null && data.getUniqueID().equals(uniqueID)) {
+				if (count==j) {
+					return data;
+				}
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixByReference(MesquiteFile f, String ref) {  //CORE, pPod
+		return getCharacterMatrixByReference(f, null, null, ref);
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixByReference(MesquiteFile f, String ref, boolean onlyUserVisible) {  //CORE, pPod
+		return getCharacterMatrixByReference(f, null, null, ref, onlyUserVisible);
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixByReference(MesquiteFile f, Taxa taxa, Object dataClass, String ref, boolean onlyUserVisible) {  //StoredCharacters, StoredMatrices, MesquiteProject
+		if (ref !=null && ref.length()>1 && ref.charAt(0)=='#'){ //using id number reference
+			String id = ref.substring(1, ref.length());
+			//restricted case first
+			if (f != null && (id.indexOf('.') < 0)){
+				for (int i=0; i<datas.size(); i++) {
+					mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+					String supID = id + "." + f.getID();
+					if (!data.isDoomed() && (supID.equals(data.getAssignedID())) && (taxa==null || data.getTaxa() == taxa) && (dataClass == null || compatibleMatrix(dataClass, data)) && (!onlyUserVisible || data.isUserVisible())) {
+						return data;
+					}
+				}
+			}
+			for (int i=0; i<datas.size(); i++) {
+				mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+				if (!data.isDoomed() && ((id.indexOf('.') < 0 && id.equals(Long.toString(data.getAssignedIDNumber()))) ||(id.indexOf('.') >= 0 && id.equals(data.getAssignedID()))) && (taxa==null || data.getTaxa() == taxa) && (dataClass == null || compatibleMatrix(dataClass, data))&& (!onlyUserVisible || data.isUserVisible())) {
+					return data;
+				}
+			}
+		}
+		else { //using name or number
+			for (int i=0; i<datas.size(); i++) {
+				mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+				if (!data.isDoomed() && data.getName().equalsIgnoreCase(ref) && (f==null || data.getFile() == f) && (taxa==null || data.getTaxa() == taxa)&& (dataClass == null || compatibleMatrix(dataClass, data))&& (!onlyUserVisible || data.isUserVisible()))
+					return data;
+			}
+			return getCharacterMatrix(f, taxa, dataClass, MesquiteInteger.fromString(ref), onlyUserVisible); //try to see if number
+		}
+		return null;  //CHECK FOR COMPATIBLE
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixByReference(MesquiteFile f, Taxa taxa, Object dataClass, String ref) {  //StoredCharacters, StoredMatrices, MesquiteProject
+		return getCharacterMatrixByReference(f,taxa,dataClass,ref,false);
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixReverseOrder(String name) {  //CORE (check)
+		return getCharacterMatrixReverseOrder((MesquiteFile)null, (Taxa)null, null, name);
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixReverseOrder(MesquiteFile file, String name) {  //Collab
+		return getCharacterMatrixReverseOrder(file, (Taxa)null, null, name);
+	}
+	/*.................................................................................................................*/
+	/** gets the data set of given reference string (ref. number, name, number) from the project */
+	public mesquite.lib.characters.CharacterData getCharacterMatrixReverseOrder(MesquiteFile f, Taxa taxa, Object dataClass, String ref) {  //Collab, MesquiteProject
+		if (ref !=null && ref.length()>1 && ref.charAt(0)=='#'){ //using id number reference
+			String id = ref.substring(1, ref.length());
+			//restricted case first
+			if (f != null && (id.indexOf('.') < 0)){
+				for (int i=datas.size()-1; i>=0; i--) {
+					mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+					String supID = id + "." + f.getID();
+					if (!data.isDoomed() && (supID.equals(data.getAssignedID())) && (taxa==null || data.getTaxa() == taxa) && (dataClass == null || compatibleMatrix(dataClass, data))) {
+						return data;
+					}
+				}
+			}
+			for (int i=datas.size()-1; i>=0; i--) {
+				mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+				if (!data.isDoomed() && ((id.indexOf('.') < 0 && id.equals(Long.toString(data.getAssignedIDNumber()))) ||(id.indexOf('.') >= 0 && id.equals(data.getAssignedID()))) && (taxa==null || data.getTaxa() == taxa) && (dataClass == null || compatibleMatrix(dataClass, data))) {
+					return data;
+				}
+			}
+		}
+		else { //using name or number
+			for (int i=datas.size()-1; i>=0; i--) {
+				mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+				if (!data.isDoomed() && data.getName().equalsIgnoreCase(ref) && (f==null || data.getFile() == f) && (taxa==null || data.getTaxa() == taxa)&& (dataClass == null || compatibleMatrix(dataClass, data)))
+					return data;
+			}
+			return getCharacterMatrix(f, taxa, dataClass, MesquiteInteger.fromString(ref)); //try to see if number
+		}
+		return null;  //CHECK FOR COMPATIBLE
+	}
+	/*.................................................................................................................*/
+	/** returns how many character matrices have this name */
+	public int getNumberCharacterMatricesWithName(MesquiteFile f, Taxa taxa, Object dataClass, String name) {  
+		int count = 0;
+		for (int i=datas.size()-1; i>=0; i--) {
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datas.elementAt(i);
+
+			if (!data.isDoomed() && data.getName().equalsIgnoreCase(name) && (f==null || data.getFile() == f) && (taxa==null || data.getTaxa() == taxa)&& (dataClass == null || compatibleMatrix(dataClass, data)))
+				count++;
+		}
+
+		return count;
+	}
+
+	/*.................................................................................................................*/
+	/** gets the number (index position) of the data set. */
+	public int getMatrixNumber(mesquite.lib.characters.CharacterData data) {   //core
+		for (int i=0; i<datas.size(); i++) {
+			if ((mesquite.lib.characters.CharacterData)datas.elementAt(i) == data)
+				return i;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** returns a string that can be used to refer to  taxa block */
+	public String getCharMatrixReferenceInternal(mesquite.lib.characters.CharacterData data) {   //Core, strat tools
+		if (data == null)
+			return null;
+		return "#" + data.getAssignedID();
+	}
+	/*.................................................................................................................*/
+	/** returns a string that can be used to refer to  taxa block */
+	public String getCharMatrixReferenceExternal(mesquite.lib.characters.CharacterData data) {
+		if (data == null)
+			return null;
+		return "#" + data.getAssignedIDNumber();
+	}
+	/*.................................................................................................................*/
+	public mesquite.lib.characters.CharacterData chooseData(MesquiteWindow frame, Taxa taxa, Object dataClass, String message){ 
+		return chooseData(frame, null, taxa, dataClass, message);
+	}
+	/*.................................................................................................................*/
+	public mesquite.lib.characters.CharacterData chooseData(MesquiteWindow frame, MesquiteFile file, Taxa taxa, Object dataClass, String message){
+		return chooseData(frame, file, taxa, dataClass, message, false);
+	}
+	/*.................................................................................................................*/
+	public mesquite.lib.characters.CharacterData chooseData(MesquiteWindow frame, MesquiteFile file, Taxa taxa, Object dataClass, String message, boolean askEvenIfOne){
+		return chooseData(frame, file, taxa, dataClass, message, askEvenIfOne,null,null);
+
+	}
+	/*.................................................................................................................*/
+	public mesquite.lib.characters.CharacterData chooseData(MesquiteWindow frame, MesquiteFile file, Taxa taxa, Object dataClass, String message, boolean askEvenIfOne, String okButton, String cancelButton){
+		int num = getNumberCharMatrices(file, taxa, dataClass, true);
+		if (num==0)
+			return null;
+		else if ((num==1 && !askEvenIfOne) || (MesquiteThread.isScripting() && num>=1))
+			return getCharacterMatrix(file, taxa, dataClass, 0, true);
+		String[] dataNames = new String[num];
+		for (int i=0; i<num;i++) 
+			dataNames[i] = getCharacterMatrix(file, taxa, dataClass, i, true).getName();
+		int whichData = ListDialog.queryList(frame, "Select data matrix", message, MesquiteString.helpString, dataNames, 0, okButton, cancelButton);
+		if (!MesquiteInteger.isCombinable(whichData)) 
+			return null;
+		else if (whichData>=0) 
+			return getCharacterMatrix(file, taxa, dataClass, whichData, true);
+		else
+			return getCharacterMatrix(file, taxa, dataClass, 0, true);
+	}
+	/*.................................................................................................................*/
+	public mesquite.lib.characters.CharacterData chooseDataExactClass(MesquiteWindow frame, MesquiteFile file, Taxa taxa, Object dataClass, String message, boolean askEvenIfOne, String okButton, String cancelButton){
+		int num = getNumberCharMatricesExactClass(file, taxa, dataClass, true);
+		if (num==0)
+			return null;
+		else if ((num==1 && !askEvenIfOne) || (MesquiteThread.isScripting() && num>=1))
+			return getCharacterMatrixExactClass(file, taxa, dataClass, 0, true);
+		String[] dataNames = new String[num];
+		for (int i=0; i<num;i++) 
+			dataNames[i] = getCharacterMatrixExactClass(file, taxa, dataClass, i, true).getName();
+		int whichData = ListDialog.queryList(frame, "Select data matrix", message, MesquiteString.helpString, dataNames, 0, okButton, cancelButton);
+		if (!MesquiteInteger.isCombinable(whichData)) 
+			return null;
+		else if (whichData>=0) 
+			return getCharacterMatrixExactClass(file, taxa, dataClass, whichData, true);
+		else
+			return getCharacterMatrixExactClass(file, taxa, dataClass, 0, true);
+	}
+	/* ---------------------------- CHARACTER MODELS ------------------------------*/
+	/*.................................................................................................................*/
+	/** adds the character model to those stored in the project 
+ 	public void addCharacterModel(CharacterModel model) {
+ 		charModels.addElement(model);
+ 	}
+ 	/*.................................................................................................................*/
+	/** returns the vector of stored character models */
+	public ModelVector getCharacterModels() {
+		return charModels;
+	}
+	/*.................................................................................................................*/
+	/** returns the number of character models stored */
+	public int getNumModels() {
+		if (charModels == null)
+			return 0;
+		return charModels.size();
+	}
+	/*.................................................................................................................*/
+	/** returns a vector of stored character models that are subclasses of the given class*/
+	public Listable[] getCharacterModels(Class c, Class stateClass) {
+		if (charModels == null || c==null)
+			return null;
+		int numModels = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (c.isAssignableFrom(mod.getClass()) && (stateClass==null || mod.getStateClass() == stateClass))
+				numModels++;
+		}
+		Listable[] mV = new Listable[numModels];
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (c.isAssignableFrom(mod.getClass()) && (stateClass==null || mod.getStateClass() == stateClass))
+				mV[count++] = mod;
+		}
+		return mV;
+	}
+	/*.................................................................................................................*/
+	/** returns a vector of stored character models that are compatible with the passed information*/
+	public Listable[] getCharacterModels(ModelCompatibilityInfo mci, Class stateClass) {
+		if (charModels == null || mci==null)
+			return null;
+		int numModels = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (mod.isCompatible(mci, null, null))
+				numModels++;
+		}
+		Listable[] mV = new Listable[numModels];
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (mod.isCompatible(mci, null, null))
+				mV[count++] = mod;
+		}
+		return mV;
+	}
+	/*.................................................................................................................*/
+	public CentralModelListener getCentralModelListener(){
+		return modelListener;
+	}
+	/*.................................................................................................................*/
+	/** returns the index'th character model. */
+	public CharacterModel getCharacterModel(int index) {
+		return (CharacterModel)charModels.elementAt(index);
+	}
+	/*.................................................................................................................*/
+	/** returns the index'th character model that is a subclass of c. */
+	public CharacterModel getCharacterModel(ModelCompatibilityInfo mci, int index) {
+		if (charModels == null || mci==null)
+			return null;
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (mod.isCompatible(mci, null, null)) {
+				if (index== count)
+					return mod;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the character model of name "name' that is a subclass of c. */
+	public CharacterModel getCharacterModel(ModelCompatibilityInfo mci, String name) {
+		if (charModels == null || mci==null || StringUtil.blank(name))
+			return null;
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (mod.isCompatible(mci, null, null)) {
+				if (!StringUtil.blank(mod.getName()) && name.equalsIgnoreCase(mod.getName()))
+					return mod;
+				if (!StringUtil.blank(mod.getNEXUSName()) &&  name.equalsIgnoreCase(mod.getNEXUSName()) )
+					return mod;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the index of the passed character model among compatible models. Added Apr 02*/
+	public int getWhichCharacterModel(ModelCompatibilityInfo mci, CharacterModel model) {
+		if (charModels == null || model == null)
+			return -1;
+		if (mci == null){
+			int count = 0;
+			for (int i=0; i<getNumModels(); i++) {
+				CharacterModel mod = getCharacterModel(i);
+				if (model == mod || model.getMother()== mod)  
+					return count;
+				count++;
+			}
+			return -1;
+		}
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (mod.isCompatible(mci, null, null)) {
+				if (model == mod || model.getMother()== mod)  
+					return count;
+				count++;
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** returns the index'th character model that is a subclass of c. */
+	public CharacterModel getCharacterModel(Class c, boolean allowBuiltIn, int index) {
+		if (charModels == null || c==null)
+			return null;
+		int count = 0;
+		for (int i=0; i<getNumModels(); i++) {
+			CharacterModel mod = getCharacterModel(i);
+			if (c.isAssignableFrom(mod.getClass()) && (allowBuiltIn || !mod.isBuiltIn())) {
+				if (index== count)
+					return mod;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the index'th character model that is a subclass of c. */
+	public CharacterModel getCharacterModel(Class c, int index) {
+		return getCharacterModel(c, true, index);
+	}
+	/*.................................................................................................................*/
+	/** returns the character model with the given name */
+	public CharacterModel getCharacterModel(String name) {
+		return charModels.getCharacterModel(name);
+	}
+	/* ---------------------------- HNODE ------------------------------*/
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public HNode[] getHDaughters(){
+		ListableVector files = getFiles();
+		if (files == null || files.size()== 0)
+			return null;
+		HNode[] daughters = new HNode[files.size()];
+		for (int i = 0; i < files.size(); i++)
+			daughters[i] = (HNode)files.elementAt(i);
+		return daughters;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public HNode getHMother(){
+		return null; //TODO: should return a class that contains links to all open projects
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public int getNumSupplements(){
+		return 0;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public String getSupplementName(int index){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public void hNodeAction(Container c, int x, int y, int action){
+		if (c==null)
+			return;
+		if (action == HNode.MOUSEDOWN){
+			MesquitePopup popup = new MesquitePopup(c);
+			popup.addItem(getName(), ownerModule, null);
+			popup.addItem("Bring All Windows To Front", ownerModule, ownerModule.makeCommand("allToFront", ownerModule));
+			popup.addItem("Close Project", ownerModule, ownerModule.makeCommand("closeProject", ownerModule));
+			popup.showPopup( x,y);
+		}
+		else if (action == HNode.MOUSEMOVE){
+			MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+			if (f != null && f instanceof MesquiteWindow){
+				String st = "This represents a project, which currently represents information from ";
+				if (getNumberLinkedFiles() == 1) {
+					st += " a single file.";
+					if (!StringUtil.blank(getHomeDirectoryName()))
+						st += " The file is located at " + getHomeDirectoryName() + ".";
+				}
+				else {
+					st += getNumberLinkedFiles() + ". The home file of the project is " + getHomeFileName();
+					if (!StringUtil.blank(getHomeDirectoryName()))
+						st +=  " and is located at " + getHomeDirectoryName() + ".";
+				}
+				((MesquiteWindow)f).setExplanation(st);
+			}
+		}
+		else if (action == HNode.MOUSEEXIT){
+			/*
+			Frame f = ownerModule.containerOfModule();
+			if (f != null && f instanceof MesquiteWindow){
+				((MesquiteWindow)f).setExplanation("");
+			}
+			 */
+		}
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public String getTypeName(){
+		return null; //"Project"; not needed since name of project includes "Project"
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	/** for HNode interface */
+	public void hSupplementTouched(int index){
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Image getHImage(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Color getHColor(){
+		return ColorTheme.getInterfaceBackgroundPale();  //project color
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public boolean getHShow(){
+		return true; 
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteScrollbar.java b/Source/mesquite/lib/MesquiteScrollbar.java
new file mode 100644
index 0000000..a7654c1
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteScrollbar.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.system.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+/* scrollbar for tree */
+public abstract class MesquiteScrollbar extends Scrollbar implements AdjustmentListener {
+	public MesquiteScrollbar ( int orientation, int value, int visible, int min, int max){
+		super(orientation, value, visible, min, max);
+		addAdjustmentListener(this);
+		SystemUtil.setFocusable(this, false);
+		setCursor(Cursor.getDefaultCursor());
+	}
+	public void adjustmentValueChanged(AdjustmentEvent e) {
+		//Event queue
+		if (processDuringAdjustment() || !e.getValueIsAdjusting())
+			scrollTouched();
+	}
+	public abstract void scrollTouched();
+	
+	public boolean processDuringAdjustment() {
+		return true;
+	}
+	
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteSet.java b/Source/mesquite/lib/MesquiteSet.java
new file mode 100644
index 0000000..8e111f1
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteSet.java
@@ -0,0 +1,210 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+/* ���������������������������bits������������������������������� */
+
+
+/* ======================================================================== */
+/**This class provides some basic utilities for small sets, as in the CategoricalState (which maintains many of the
+same methods independently; this is done so CategoricalState can subclass CharacterState).*/
+public class MesquiteSet {
+	/** The state (1L<<63) that corresponds to missing data.*/
+	public static final long unassigned = 1L<<63;
+	/** The state (0) that corresponds to a gap (inapplicable)*/
+	public static final long inapplicable = 0L;
+	/** The maximum allowed categorical state (60) */
+	public static  final int maxElement = 60;
+	/** The state (1L<<62) that corresponds to an invalid MesquiteSet.*/
+	public static final long impossible = 1L<<62;
+	
+	private static final int MAXBIT = 63; //MAXBIT for bitwise manipulations
+	
+	/*..........................................MesquiteSet.....................................*/
+	/**returns empty state set */
+	public static long emptySet() {
+		return 0L;  
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**returns state set consisting of all elements */
+	public static long fullSet() {
+		return 0xFFFFFFFFFFFFFFFFL;  
+	}
+	/*.................................................................................................................*/
+	/**Returns the set that is {0,...,(numInSet-1)}  That is, the first "numInSet" bits are set.
+	This is designed for use with next set, to generate for instance all possible sets containing
+	numInSet elements */
+	public static long firstSet(int numInSet) { 
+		if (numInSet==0)
+			return 0;
+		else
+			return fullSet()>>>(64-numInSet);
+	}
+	/*.................................................................................................................*/
+	/**When passed a set, returns the next set in sequence with the same
+	number of elements and with maximum element maxS.  This can be called
+	repeatedly (after starting with firstSet) to generate all sets with a
+	certain number of elements.  When the current set is the last one,
+	returns an empty set.    */
+	//
+	public static long nextSet(long current, int maxS) { //todo: have mask instead of just maxS
+		if (current==0)
+			return 0;
+		long result = current;
+		int max = maximum(current);
+		if (max < maxS) { //still room to move over left; do it
+			result = clearFromSet(result, max);
+			return addToSet(result, max +1);
+		}
+		else { //no; get next from all but last
+			result = clearFromSet(result, max);
+			result = nextSet(result, max-1);
+			if (result==0){ //hadn't been any more
+				return 0;
+			}
+			else  {
+				int newMax = maximum(result);
+				return addToSet(result, newMax+1);
+			}
+		}
+	}
+	
+	/*..........................................MesquiteSet.....................................*/
+	/**returns true iff e is element in state set s */
+	public static boolean isElement(long s, int e) {
+		if ((e>maxElement) || (e<0))
+			return false;
+		else
+			return (((1L<<e)&s)!=0);
+	}
+	
+	/*..........................................MesquiteSet.....................................*/
+	/**returns minimum element in state set s */
+	public static int minimum(long s) {
+		for (int e=0; e<=maxElement; e++) {
+			if (((1L<<e)&s)!=0)
+				return e;
+		}
+		return maxElement;  
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**returns number of states in state set s */
+	public static int cardinality(long s) {
+		if (s==0L) {
+		 	return 0;  
+		}
+		else {
+			int count =0;
+			for (int e=0; e<= maxElement; e++) {
+				if (((1L<<e)&s)!=0) {  //test bit
+					count++;
+				}
+			}
+			return count;
+		}
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**return maximum value of states in state set s */
+	public static int maximum(long s) {
+		if (s==0L) {
+		 	return -1;  
+		}
+		else {
+			int max = -1;
+			for (int e=0; e<= maxElement; e++) {
+				if (((1L<<e)&s)!=0) {  //test bit
+					max=e;
+				}
+			}
+			return max;
+		}
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**returns true if e is only state in state set s */
+	public static boolean isOnlyElement(long s, int e) {
+		if ((e>maxElement) || (e<0))
+			return false;
+		else
+			return ((1L<<e)==s);
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**returns a state set including only the state e */
+	public static long makeSet(int e) {
+		if ((e<=maxElement) || (e>=0))
+			return (1L<<e);
+		else 
+			return impossible;
+	}
+
+	/*..........................................MesquiteSet.....................................*/
+	/**return a state set with all states a through b inclusive. */
+	public static long span(int a, int b) {
+		if (((a>maxElement) || (a<0)) || ((b>maxElement) || (b<0)))
+			return impossible;
+		else if (a>b) {
+			int c=a;
+			a = b;
+			b = c;
+		}
+		return ((~(0L)) << a) & ((~(0L)) >>> (MAXBIT-b));
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**return the result of adding state e to state set s */
+	public static long addToSet(long s, int e) {
+		if ((e<=maxElement) || (e>=0))
+			return (1L<<e) | s;
+		else 
+			return s;
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/**return the result of subtracting state e to state set s */
+	public static long clearFromSet(long s, int e) {
+		if ((e<=maxElement) || (e>=0))
+			return (~(1L<<e))&s;
+		else 
+			return s;
+	}
+
+	/*..........................................MesquiteSet.....................................*/
+	/** converts passed long (treated as MesquiteSet) to string.  Uses braces, and does not use character state names*/
+	public static String toString(long s) {
+		return toString(s, true);
+	}
+	/*..........................................MesquiteSet.....................................*/
+	/** converts passed long (treated as MesquiteSet) to string.  Uses character state names if available.*/
+	public static String toString(long s, boolean useBraces) {
+		boolean first=true;
+		String temp;
+		if (useBraces) 
+			temp="{";
+		else
+			temp="";
+		for (int e=0; e<=maxElement; e++) {
+			if (isElement(s, e)) {
+				if (!first)
+					temp+=",";
+				temp+=Integer.toString(e);
+				first=false;
+			}
+		}
+		if (useBraces)
+			temp+="}";
+		return temp;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteString.java b/Source/mesquite/lib/MesquiteString.java
new file mode 100644
index 0000000..344d112
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteString.java
@@ -0,0 +1,196 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+/**This String wrapper class is used to be able to pass Strings by reference and have the
+	original change as needed*/
+public class MesquiteString extends Listened implements Listable, Identifiable, Explainable {
+	public static final int riseOffset = 5;
+	private boolean bound = false;
+	public static long totalCreated = 0;
+	public static String helpString=null;
+	private StringBuffer sb;
+	private boolean isNull = true;
+	private String name = null;
+	long id;
+	public MesquiteString() {
+		super();
+		id = totalCreated;
+		totalCreated++;
+		sb = new StringBuffer();
+	}
+	public MesquiteString(String value) {
+		super();
+		if (value == null)
+			sb = new StringBuffer();
+		else
+			sb = new StringBuffer(value);
+		isNull = value==null;
+		id = totalCreated;
+		totalCreated++;
+	}
+	public MesquiteString(String name, String value) {
+		this(value);
+		this.name = name;
+	}	
+
+	public long getID(){
+		return id;
+	}
+
+	String referentID = null; //so that object whose name is recorded in MesquiteString can also be identified by an ID
+	public String getReferentID(){
+		return referentID;
+	}
+	public void setReferentID(String rID){
+		referentID = rID;
+	}
+	public String getValue() {
+		if (isNull)
+			return null;
+		return sb.toString();
+	}
+	public String toString() {
+		if (isNull)
+			return "null";
+		return sb.toString();
+	}
+	public boolean isBlank() {
+		if (isNull)
+			return true;
+		return StringUtil.blank(sb.toString());
+	}
+	public void setName(String s){
+		name = s;
+	}
+	public String getName() {
+		if (name == null)
+			return getValue();
+		else
+			return name;
+	}
+	public String getExplanation(){
+		return getValue();
+	}
+	public static boolean explicitlyUnassigned(String s){
+		if (s==null)
+			return false;
+		return ("?".equals(s) || "unassigned".equalsIgnoreCase(s) || "estimate".equalsIgnoreCase(s));
+
+	}
+
+	public void setValue(String value) {
+		setValue(value, true);
+	}
+	public void setValue(MesquiteString value) {
+		if (value==null){
+			sb.setLength(0);
+			return;
+		}
+		setValue(value.toString(), true);
+	}
+
+	public void setValue(String value, boolean notify) {
+		if (value==null){
+			sb.setLength(0);
+			if (!isNull){
+				isNull = true;
+				if (bound)
+					MesquiteTrunk.resetCheckMenuItems(); //TODO: shouldn't this method be in MenuOwner???
+				if (notify)
+					notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+			}
+		}
+		else {
+			isNull = false;
+			if (!value.equals(sb.toString())) {
+				sb.setLength(0);
+				sb.append(value);
+				if (bound)
+					MesquiteTrunk.resetCheckMenuItems(); //TODO: shouldn't this method be in MenuOwner???
+				if (notify)
+					notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+			}
+			else if (bound)
+				MesquiteTrunk.resetCheckMenuItems(); //TODO: shouldn't this method be in MenuOwner???
+		}
+	}
+
+	public void append(String value) {
+		if (value!=null) {
+			if (isNull)
+				sb.setLength(0);
+			isNull = false;
+			sb.append(value);
+			if (bound)
+				MesquiteTrunk.resetCheckMenuItems(); //TODO: shouldn't this method be in MenuOwner???
+			notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+		}
+	}
+	public void prepend(String value) {
+		if (value!=null) {
+			if (isNull){
+				sb.setLength(0);
+				isNull = false;
+				sb.append(value);
+			}
+			else
+				sb.insert(0,value);
+			if (bound)
+				MesquiteTrunk.resetCheckMenuItems(); //TODO: shouldn't this method be in MenuOwner???
+			notifyListeners(this, new Notification(MesquiteListener.VALUE_CHANGED));
+		}
+	}
+	public void bindMenuItem() {
+		bound = true;
+	}
+	public void releaseMenuItem() {
+		bound = false;
+	}
+	public static String queryMultiLineString(MesquiteWindow parent, String title, String message, String current, int rows, boolean hasDefault, boolean useSmallText) { //TODO: use Frame passed
+		MesquiteString io = new MesquiteString(current);
+		QueryDialogs.queryMultiLineString(parent, title, message, io, rows, hasDefault, useSmallText);
+		return io.getValue();
+	}
+	public static String queryString(MesquiteWindow parent, String title, String message, String current, int rows) { //TODO: use Frame passed
+		MesquiteString io = new MesquiteString(current);
+		QueryDialogs.queryString(parent, title, message, io, rows);
+		return io.getValue();
+	}
+	public static String queryString(MesquiteWindow parent, String title, String message, String current) { //TODO: use Frame passed
+		MesquiteString io = new MesquiteString(current);
+		QueryDialogs.queryString(parent, title, message, io);
+		return io.getValue();
+	}
+	public static String queryShortString(MesquiteWindow parent, String title, String message, String current, boolean hasDefault) { //TODO: use Frame passed
+		MesquiteString io = new MesquiteString(current);
+		QueryDialogs.queryShortString(parent, title, message, io, hasDefault);
+		return io.getValue();
+	}
+	public static String queryShortString(MesquiteWindow parent, String title, String message, String current) { //TODO: use Frame passed
+		MesquiteString io = new MesquiteString(current);
+		QueryDialogs.queryShortString(parent, title, message, io);
+		return io.getValue();
+	}
+	public static void queryTwoStrings(MesquiteWindow parent, String title, String label1, String label2, MesquiteBoolean answer, MesquiteString resp1, MesquiteString resp2, boolean secondLong) {
+		new TwoStringsDialog(parent, title, label1, label2, answer, resp1, resp2,false, secondLong);
+	}
+	/*.................................................................................................................*/
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteSubmenu.java b/Source/mesquite/lib/MesquiteSubmenu.java
new file mode 100644
index 0000000..5478414
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteSubmenu.java
@@ -0,0 +1,295 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+
+/* ======================================================================== */
+/**A submenu.*/
+public class MesquiteSubmenu extends MesquiteMenu implements ActionListener {
+	public MesquiteCommand command;
+	private MesquiteModule ownerModule;
+	public Menu ownerMenu;
+	MesquiteSubmenuSpec msms;
+	MesquiteString checkString = null;
+	public boolean disconnectable = true;
+	long ownerID;
+//	static MesquiteSubmenu[] submenus = new MesquiteSubmenu[255];
+	public MesquiteSubmenu(MesquiteSubmenuSpec msms, Menu ownerMenu, MesquiteModule ownerModule) {
+		super(msms.getSubmenuName());  
+		filterable = msms.isFilterable();
+		addActionListener(this);
+		this.msms = msms;
+		if (msms.getSubmenuName() == null) {
+			System.out.println("submenu with no name");
+		}
+		if (!msms.isEnabled())
+			setEnabled(false);
+		this.ownerMenu = ownerMenu;
+		this.ownerID = msms.getOwnerModuleID();
+		this.command = msms.getCommand();
+	}
+
+	public MesquiteSubmenu(String submenuName, Menu ownerMenu, MesquiteModule ownerModule) {
+		super(submenuName);  
+		addActionListener(this);
+		if (submenuName == null) {
+			System.out.println("submenu with no name");
+		}
+		this.ownerMenu = ownerMenu;
+		if (ownerModule!=null)
+			this.ownerID = ownerModule.getID();
+		this.command = command;
+	}
+
+	public MesquiteMenuSpec getSpecification(){
+		return msms;
+	}
+
+	public long getOwnerModuleID(){
+		return ownerID;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+	public static MesquiteSubmenu getSubmenu(MesquiteSubmenuSpec msms, Menu ownerMenu, MesquiteModule ownerModule) {
+		return new MesquiteSubmenu(msms, ownerMenu, ownerModule);
+	}
+	public static MesquiteSubmenu getSubmenu(String submenuName, Menu ownerMenu, MesquiteModule ownerModule) {
+		return new MesquiteSubmenu(submenuName, ownerMenu, ownerModule);
+	}
+
+	public static StringLister getFontList() {
+		Toolkit tk = Toolkit.getDefaultToolkit();
+		String[] fonts = tk.getFontList();
+		StringArray f = new StringArray(fonts.length);
+		for (int i=0; i<fonts.length; i++)
+			f.setValue(i,fonts[i]);
+		return f;
+	}
+	public static StringLister getFontSizeList() {
+		StringArray f = new StringArray(9);
+		f.setValue(0,"9");
+		f.setValue(1,"10");
+		f.setValue(2,"12");
+		f.setValue(3,"14");
+		f.setValue(4,"18");
+		f.setValue(5,"24");
+		f.setValue(6,"30");
+		f.setValue(7,"36");
+		f.setValue(8,"Other...");
+		return f;
+	}
+	public static MesquiteSubmenu getFontSubmenu(String title, Menu ownerMenu, MesquiteModule ownerModule, MesquiteCommand setFontCommand) {
+		MesquiteSubmenu submenuFont=getSubmenu(title, ownerMenu, ownerModule);
+		submenuFont.setSelected(new MesquiteString(""));
+		Toolkit tk = Toolkit.getDefaultToolkit();
+		String[] fonts = tk.getFontList();
+		for (int i=0; i<fonts.length; i++)
+			submenuFont.add(new MesquiteCheckMenuItem(fonts[i],  null, setFontCommand, StringUtil.tokenize(fonts[i]), submenuFont.checkString));
+		return submenuFont;
+	}
+	public static MesquiteSubmenu getFontSizeSubmenu(String title, Menu ownerMenu, MesquiteModule ownerModule, MesquiteCommand setFontSizeCommand) {
+		MesquiteSubmenu submenuSize=MesquiteSubmenu.getSubmenu(title, ownerMenu, ownerModule);
+		submenuSize.setSelected(new MesquiteString(""));
+		submenuSize.add(new MesquiteCheckMenuItem("9",  ownerModule, setFontSizeCommand, "9", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("10",  ownerModule, setFontSizeCommand, "10", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("12",  ownerModule, setFontSizeCommand, "12", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("14",  ownerModule, setFontSizeCommand, "14", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("18",  ownerModule, setFontSizeCommand, "18", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("24",  ownerModule, setFontSizeCommand, "24", submenuSize.checkString));
+		submenuSize.add(new MesquiteCheckMenuItem("36",  ownerModule, setFontSizeCommand, "36", submenuSize.checkString));
+		//	submenuSize.add((new MesquiteMenuItem("36",  ownerModule, setFontSizeCommand, "36")).setDocument(false));
+		//submenuSize.add(new MesquiteMenuItem("-",  null, null, null));
+		submenuSize.add((new MesquiteMenuItem("Other...",  ownerModule, setFontSizeCommand, null)).setDocument(false));
+		return submenuSize;
+	}
+	public void checkName(String s){
+		checkString.setValue(s);
+		resetCheck();
+	}
+	/** A method to resent which CheckBoxMenuItem is checked.  Currently not used because of bug in
+	 MRJ check menu system*/
+	public void resetCheck() {
+		try{
+		if (checkString != null) {
+			int numItems = getItemCount();
+			for (int i = 0; i<numItems; i++) {
+				MenuItem mi = getItem(i);
+				if (mi instanceof CheckboxMenuItem && mi!=null) {
+					if (mi.getLabel() != null && mi.getLabel().equals(checkString.getValue())) {
+						if (mi instanceof MesquiteCheckMenuItem)
+							((MesquiteCheckMenuItem)mi).resetCheck();
+						else ((CheckboxMenuItem)mi).setState(true);
+					}
+					else {
+						if (mi instanceof MesquiteCheckMenuItem)
+							((MesquiteCheckMenuItem)mi).resetCheck();
+						else ((CheckboxMenuItem)mi).setState(false);
+					}
+
+				}
+			}
+		}
+		}
+		catch (Exception e){
+		}
+	}
+	public void resetEnable() {
+		if (msms != null)
+			setEnabled(msms.isEnabled());
+	}
+	Object referent = null;
+	public void setReferent(Object referent){
+		this.referent = referent;
+	}
+	public Object getReferent(){
+		return referent;
+	}
+	public void disconnect(){
+		if (disconnectable){
+			command = null;
+			ownerModule = null;
+			ownerMenu = null;
+			msms = null;
+			if (checkString!=null)
+				checkString.releaseMenuItem();
+			checkString = null;
+		}
+	}
+	public void setSelected(MesquiteString selected) {
+		checkString = selected;
+		if (checkString!=null)
+			checkString.bindMenuItem();
+	}
+	public MesquiteString getSelected() {
+		return checkString;
+	}
+	public void chooseItem(int itemNumber){
+		if (itemNumber<0 || itemNumber>= getItemCount() || MesquiteTrunk.suppressMenuResponse)
+			return;
+		String s = getItem(itemNumber).getLabel();
+		if (msms.getListableVector() == null && msms.getStrings() == null) {
+			if (itemNumber>=0)
+				chooseItem(StringUtil.tokenize(s) + " " + itemNumber); 
+			else
+				chooseItem(StringUtil.tokenize(s));
+		}
+		else if (msms.getListableVector() != null) {
+			if (itemNumber>=0) {
+				chooseItem(Integer.toString(itemNumber) + " " + StringUtil.tokenize(s));
+			}
+		}
+		else {
+			if (itemNumber>=0)
+				chooseItem(StringUtil.tokenize(s) + " " + itemNumber); 
+			else
+				chooseItem(StringUtil.tokenize(s));
+		}	 
+		resetCheck();
+
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		//Event queue
+		Object target = e.getSource();
+		if (command != null)  { // there is a submenu-wide command; use it and pass name as argument
+			MenuItem mi = ((MenuItem)target);
+			if (hideable && InterfaceManager.isEditingMode()){
+				if (hiddenStatus == InterfaceManager.NORMAL){
+					InterfaceManager.addMenuItemToHidden(mi.getLabel(), StringUtil.tokenize(mi.getLabel()), command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.TOBEHIDDEN);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+				else if (hiddenStatus != InterfaceManager.HIDDENCLASS) {
+					InterfaceManager.removeMenuItemFromHidden(mi.getLabel(), StringUtil.tokenize(mi.getLabel()), command, dutyClass, true);
+					setHiddenStatus(InterfaceManager.NORMAL);
+					MesquiteTrunk.resetAllMenuBars();
+				}
+				return;
+			}
+			if (mi == this){ //this submenu selected directly, not one of its items
+				return;
+			}
+			int itemNumber = 0;
+			while (itemNumber < getItemCount() && mi != getItem(itemNumber) )
+				itemNumber++;
+			if (itemNumber<0 || itemNumber<= getItemCount() || mi != getItem(itemNumber)) 
+				itemNumber = -1;
+			if ((e.getModifiers() & ActionEvent.ALT_MASK)!=0) {
+				if (!(target instanceof MesquiteMenuItem) && !(target instanceof MesquiteCheckMenuItem)) {
+					MesquiteWindow.respondToQueryMode("Menu item \"" + getLabel() + "\"", command, target);
+				}
+			}
+			else if (msms.getListableVector() == null && msms.getStrings() == null) {
+				if (itemNumber>=0)
+					chooseItem(StringUtil.tokenize(e.getActionCommand()) + " " + itemNumber); 
+				else
+					chooseItem(StringUtil.tokenize(e.getActionCommand()));
+			}
+			else if (msms.getListableVector() != null) {
+				if (itemNumber>=0) {
+					chooseItem(Integer.toString(itemNumber) + " " + StringUtil.tokenize(getItem(itemNumber).getLabel()));
+				}
+			}
+			else {
+				if (itemNumber>=0)
+					chooseItem(StringUtil.tokenize(e.getActionCommand()) + " " + itemNumber); 
+				else
+					chooseItem(StringUtil.tokenize(e.getActionCommand()));
+			}
+		}
+		else if (target instanceof MesquiteMenuItem) {
+			MesquiteCommand com = ((MesquiteMenuItem)target).getCommand();
+			if (com==null)
+				return;
+			if ((e.getModifiers() & ActionEvent.ALT_MASK)!=0) {
+				MesquiteWindow.respondToQueryMode("Menu item \"" + ((MesquiteMenuItem)target).getLabel() + "\"", command, target);
+			}
+			else
+				((MesquiteMenuItem)target).chooseItem("");
+		}
+		else {
+	}
+		resetCheck();
+	}
+	public Class getFilter(){
+		if (msms != null && msms.getListableFilter() != null)
+			return msms.getListableFilter();
+		return null;
+	}
+	public Class getDutyClass(){
+		if (msms != null && msms.getDutyClass() != null)
+			return msms.getDutyClass();
+		return null;
+	}
+	public void chooseItem(String arg){
+		if (command == null || MesquiteTrunk.suppressMenuResponse)
+			return;
+		if (!command.bypassQueue && MesquiteDialog.currentWizard != null){
+			MesquiteTrunk.mesquiteTrunk.alert("Please complete the questions of the Wizard dialog before selecting menu items");
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		command.doItMainThread(arg, CommandChecker.getQueryModeString("Submenu", command, this), this, MesquiteDialog.useWizards);
+		resetCheck();
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteSubmenuSpec.java b/Source/mesquite/lib/MesquiteSubmenuSpec.java
new file mode 100644
index 0000000..f8b9f12
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteSubmenuSpec.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** Specifications to later make a submenu.*/
+public class MesquiteSubmenuSpec extends MesquiteMenuSpec{ 
+	//public String submenuName;
+	MesquiteString selected;
+	public static final int SHOW_SUBMENU =0;
+	public static final int ONEMENUITEM_ZERODISABLE = 1;
+	public static final int ONEDISABLE_ZERODISABLE = 2;
+	public static final int ONESUBMENU_ZERODISABLE = 3;
+	int beh = ONESUBMENU_ZERODISABLE;
+	public static CommandChecker checkerMS = null;
+	
+	public MesquiteSubmenuSpec(MesquiteMenuSpec whichMenu, String submenuName,  MesquiteModule ownerModule) {
+		super(whichMenu,  submenuName,  ownerModule);
+	//	this.submenuName = submenuName;
+	}
+	
+	public static MesquiteSubmenuSpec getMSSSpec(MesquiteMenuSpec whichMenu, String itemName, MesquiteModule ownerModule){
+		if (checkerMS!=null) {
+			checkerMS.registerMenuItem(ownerModule, itemName, null);
+			return null;
+		}
+		else {
+			ownerModule.checkMISVector();
+			MesquiteSubmenuSpec mmis = new MesquiteSubmenuSpec(whichMenu, itemName, ownerModule);
+			ownerModule.getMenuItemSpecs().addElement(mmis, false);
+			return mmis;
+		}
+	}
+	public String getSubmenuName(){
+		return getCurrentItemName();
+	}
+	
+	public void setBehaviorIfNoChoice(int beh) {
+		this.beh = beh;
+	}
+	public int getBehaviorIfNoChoice() {
+		return beh;
+	}
+	
+	public void setSelected(MesquiteString selected) {
+		this.selected = selected;
+	}
+	public MesquiteString getSelected() {
+		return selected;
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteSymbol.java b/Source/mesquite/lib/MesquiteSymbol.java
new file mode 100644
index 0000000..0f2c590
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteSymbol.java
@@ -0,0 +1,116 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class MesquiteSymbol extends Listened implements Listable  {
+	protected String name;
+	protected int size=8;
+	Color color = Color.black;
+	IntegerField sizeField = null;
+	public MesquiteSymbol() {
+	}
+	/**sets the size of the symbol*/
+	public void setSize(int size){
+		this.size = size;
+	}
+	/**gets the size of the symbol*/
+	public int getSize(){
+		return size;
+	}
+	/**gets the name of the symbol*/
+	public String getName(){
+		return "";
+	}
+	/**gets the NEXUS commands to specify the options specific to this tool*/
+	public String getBasicNexusOptions(){
+		return " ";
+	}
+	/**gets the NEXUS commands to specify the options specific to this tool*/
+	public String getExtraNexusOptions(){
+		return " ";
+	}
+	/*.................................................................................................................*/
+	public void  setToCloned(MesquiteSymbol cloned){
+		setSize(cloned.getSize());
+	}
+	/*.................................................................................................................*/
+	public  abstract MesquiteSymbol  cloneMethod();
+	/*.................................................................................................................*/
+	public void addDialogElements(ExtensibleDialog dialog, boolean includeSize){
+		if (includeSize)
+			sizeField = dialog.addIntegerField("Size: ", size,4);
+	}
+	/*.................................................................................................................*/
+	public void getDialogOptions(){
+		if (sizeField!=null)
+			size = sizeField.getValue();
+	}
+	/*.................................................................................................................*/
+	public void interpretNexus(Parser subcommands){
+		if (subcommands !=null){ //this should be passed into group to handle?
+			String token = null;
+			while ((token = subcommands.getNextToken())!=null){
+				processSubcommand(token, subcommands);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void processSubcommand(String token, Parser subcommands){
+		if (token.equalsIgnoreCase("SIZE")){
+			token = subcommands.getNextToken(); //=
+			int symSize = MesquiteInteger.fromString(subcommands.getNextToken()); 
+			if (MesquiteInteger.isCombinable(symSize))
+				size=symSize;
+		}
+	}
+	/**sets fill color*/
+	public void setColor(Color color){
+		this.color = color;
+	}
+	/**draws the Symbol*/
+	public void drawSymbol(Graphics g, int x, int y){
+		drawSymbol(g,x,y,0,0,false);
+	}
+	/**draws the Symbol*/
+	public void drawSymbol(Graphics g, int x, int y, int maxWidth, int maxHeight, boolean fillBlack){
+	}
+	/**fills the Symbol with current color*/
+	public void fillSymbol(Graphics g, int x, int y){
+		fillSymbol(g,x,y,0,0);
+	}
+	/**fills the Symbol with current color*/
+	public void fillSymbol(Graphics g, int x, int y, int maxWidth, int maxHeight){
+	}
+	/**returns if the point x, y is contained within the Symbol*/
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y, int maxWidth, int maxHeight){
+		return false;
+	}
+	/**returns if the point x, y is contained within the Symbol*/
+	public boolean inSymbol(int symbolX, int symbolY, int x, int y){
+		return inSymbol(symbolX, symbolY, x,y,0,0);
+	}
+	/**returns if the point x, y is contained within the Symbol*/
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2, int maxWidth, int maxHeight){
+		return false;
+	}
+	/**returns if the point x, y is contained within the Symbol*/
+	public boolean inRect(int symbolX, int symbolY, int x1, int y1, int x2, int y2){
+		return inRect(symbolX, symbolY, x1,y1,x2,y2,0,0);
+	}
+}
+
diff --git a/Source/mesquite/lib/MesquiteTabbedPane.java b/Source/mesquite/lib/MesquiteTabbedPane.java
new file mode 100644
index 0000000..219d086
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTabbedPane.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import java.awt.*;
+
+
+public class MesquiteTabbedPane extends JTabbedPane {
+	MesquiteTabbedPanel panel;
+	public MesquiteTabbedPane(MesquiteTabbedPanel panel){
+		super();
+		this.panel = panel;
+	}
+	
+	int count = 0;
+	
+	public void setSelectedIndex2(int i){
+	
+		 int current = getSelectedIndex();
+		if (current>=0) {
+			JPanel p2 = panel.getTabPanel(current);
+			if (p2 != null)
+				p2.setVisible(false);
+		}
+
+		super.setSelectedIndex(i);
+
+
+		JPanel p = panel.getTabPanel(i);
+		//	setVisible(true);
+		if (p != null) {
+			p.setVisible(true);
+			Graphics g = p.getGraphics();
+			if (g!=null)
+				g.setClip(null);
+			p.invalidate();
+		}
+		invalidate();
+		//	try {Thread.sleep(20);} catch (Exception e) {}
+	//	super.setSelectedIndex(i);
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteTabbedPanel.java b/Source/mesquite/lib/MesquiteTabbedPanel.java
new file mode 100644
index 0000000..4e0c58e
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTabbedPanel.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+
+public class MesquiteTabbedPanel extends JPanel  {
+	MesquiteTabbedPane tabbedPane;
+	int numPanels=0;
+	ExtensibleDialog dialog;
+	
+	public MesquiteTabbedPanel (ExtensibleDialog dialog) {
+		super(new GridLayout(1,1));
+		this.dialog = dialog;
+		tabbedPane = new MesquiteTabbedPane(this);
+		add(tabbedPane);
+        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+	}
+	public JPanel addPanel(String title, boolean setAsAddPanel){
+		JPanel panel = new JPanel();
+		tabbedPane.addTab(title, panel);
+		//panel.add(new Checkbox("testing panel " + numPanels));
+		panel.setVisible(false);
+		if (setAsAddPanel && dialog!=null)
+			dialog.setAddJPanel(panel);
+		numPanels++;
+		return panel;
+	}
+	public JPanel getTabPanel(int i) {
+		Component c = tabbedPane.getComponentAt(i);
+		if (c instanceof JPanel) 
+			return (JPanel)c;
+		return null;
+		
+	}
+	public void cleanup(){
+		setVisible(true);
+		tabbedPane.setSelectedIndex(0);
+		tabbedPane.doLayout();
+		tabbedPane.validate();
+		if (dialog!=null)
+			dialog.pack();
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteTextCanvas.java b/Source/mesquite/lib/MesquiteTextCanvas.java
new file mode 100644
index 0000000..386c108
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTextCanvas.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/*===============================================*/
+/** A field for displaying uneditable text. */
+public class MesquiteTextCanvas extends TextArea  {
+	String message;
+	int width = 0;
+	int totalLength;
+	int totalHeight;
+	int lineHeight;
+	int numReturns=0;
+	Font font;
+	/*.................................................................................................................*/
+	public MesquiteTextCanvas (int width, Font font, String message, int scrollbars) {
+		super(message, 6, 40, TextArea.SCROLLBARS_NONE);
+		this.message = message;
+		numReturns = StringUtil.getNumMatchingChars(message, '\n');
+		this.width = width;
+		if (font == null)
+			font = ExtensibleDialog.defaultBigFont;
+		this.font = font;
+		setFont(font);
+		reCalcRows(width);
+		setEditable(false);
+		disableEvents(AWTEvent.MOUSE_EVENT_MASK+AWTEvent.MOUSE_MOTION_EVENT_MASK);
+	}
+	/*.................................................................................................................*/
+	public void reCalcRows (int width) {
+		totalLength = StringUtil.getStringDrawLength(this,message);
+		lineHeight = StringUtil.getTextLineHeight(this);
+		int estimatedRows;
+		if (width == 12)
+			estimatedRows = 2+numReturns; //added 13 Dec 01
+		else
+			estimatedRows = totalLength / (width-12) +2+numReturns;
+		if (estimatedRows <= 0)
+			estimatedRows = 3;
+		else if (estimatedRows >20)
+			estimatedRows = 20;
+		estimatedRows++;  //and one for the pot
+		setRows(estimatedRows);
+	}
+	/*.................................................................................................................*/
+	public void setCanvasRows (int width) {
+		Font font = getFont();
+		if (font==null)
+			setFont(new Font("Dialog", Font.PLAIN, 12));
+		reCalcRows(width);
+		if (getBackground() != getParent().getBackground())
+			setBackground(getParent().getBackground());
+	}
+
+	public static MesquiteTextCanvas getTextCanvas(int width, Font font, String message){
+		MesquiteTextCanvas tc = new MesquiteTextCanvas(width, font, message, TextArea.SCROLLBARS_NONE);
+		if (tc.getRows()>50){
+			return new MesquiteTextCanvas(width, font, message, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		}
+		else
+			return tc;
+	}
+	public void paint(Graphics g){
+		if (getBackground() != getParent().getBackground())
+			setBackground(getParent().getBackground());
+		super.paint(g);
+	}
+
+
+}
diff --git a/Source/mesquite/lib/MesquiteTextWindow.java b/Source/mesquite/lib/MesquiteTextWindow.java
new file mode 100644
index 0000000..04b78d8
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTextWindow.java
@@ -0,0 +1,234 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.duties.*;
+import java.awt.datatransfer.*;
+
+/* ======================================================================== */
+/** A window that displays text.  Yet to do: make it editable or not, have getText, etc.. */
+public class MesquiteTextWindow extends MesquiteWindow implements FocusListener {
+	protected TextArea tA;
+	String assignedTitle;
+	MesquiteCommand copyCommand;
+	MesquiteCommand pasteCommand = null;
+	public MesquiteTextWindow(MesquiteModule module, String assignedTitle, boolean showInfoBar) {
+		this(module, assignedTitle, showInfoBar, true, false);
+	}
+	public MesquiteTextWindow(MesquiteModule module, String assignedTitle, boolean showInfoBar, boolean wrap, boolean allowPaste) {
+		super(module, showInfoBar);// ���
+		this.assignedTitle = assignedTitle;
+		//setBackground(Color.white);
+		setWindowSize(400, 450);
+		if (wrap)
+			tA= new TextArea("", 90, 90,  TextArea.SCROLLBARS_VERTICAL_ONLY);
+		else
+			tA= new TextArea("", 90, 90,  TextArea.SCROLLBARS_BOTH);
+		tA.setEditable(false);
+		tA.setBackground(Color.white);
+		tA.setForeground(Color.black);
+		tA.setVisible(true);
+		tA.addFocusListener(this);
+		addToWindow(tA);
+		tA.setSize(getWidth(), getHeight());
+		try {
+			tA.setFocusTraversalKeysEnabled(false);
+		}
+		catch (Error e){
+			MesquiteMessage.printStackTrace("error with setFocusTraversalKeysEnabled");
+		}
+		//	pack();
+		resetTitle();
+		if (allowPaste)
+			pasteCommand = MesquiteModule.makeCommand("paste", this);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(assignedTitle);
+	}
+	public void setTitle(String s){ //in case set after instantiation, so that change stays
+		super.setTitle(s);
+		assignedTitle = s;
+	}
+	public MesquiteCommand getPasteCommand() {
+		return pasteCommand; 
+	}
+
+	/*.................................................................................................................*/
+	/** Gets the minimum height of the content area of the window */
+	public int getMinimumContentHeight(){
+		return 100;
+	}
+	public void setEditable(boolean ed) {
+		tA.setEditable(ed);
+	}
+	public void append(String s) {
+		tA.append(s);
+	}
+	public void consume(int i) {
+		int L = tA.getText().length();
+		tA.replaceRange("", L-i, L);
+	}
+	public void setText(String s) {
+		tA.setText(s);
+		try {
+			tA.setCaretPosition(0);
+		}
+		catch (Exception e){
+		}
+		tA.repaint();
+	}
+	public String getText() {
+		return tA.getText();
+	}
+	public void focusGained(FocusEvent e){
+
+	}
+	public void focusLost(FocusEvent e){
+
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+		return getText();
+	}
+	/*.................................................................................................................*/
+	public void printWindow(MesquitePrintJob pjob) {
+		if (pjob != null) {
+			if (infoBar.getMode()>0) 
+				super.printWindow(pjob);
+			else 
+				pjob.printText(getText(), new Font("Monospaced", Font.PLAIN, 12));
+		}
+	}
+	/*.................................................................................................................*/
+	/**
+	@author Peter Midford
+	 */
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			if (infoBar.getMode()>0)
+				super.windowToPDF(pdfFile, fitToPage);
+			else
+				//Changed font size to 10, since courier is the only adobe supplied monospace font and
+				//it is a little larger than the system supplied monospace font.
+				pdfFile.printText(getText(), new Font("Monospaced", Font.PLAIN, 10));
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		if (tA!=null)
+			tA.setSize(getWidth(), getHeight()); //getFullWidth
+	}
+	/** Sets the window size.  To be used instead of setSize. 
+	public void containerSizeSet(int width, int height) {
+	}
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize. */
+	public void setWindowSize(int width, int height) {
+		super.setWindowSize(width, height);
+		if (tA!=null)
+			tA.setSize(getWidth(), getHeight());
+	}
+	/*.................................................................................................................*/
+	/** Sets the window font size.  */
+	public boolean setWindowFontSize(int fontSize) {
+		if (!MesquiteInteger.isCombinable(fontSize))
+			fontSize = MesquiteInteger.queryInteger(MesquiteWindow.windowOfItem(this), "Font size", "Font size for window", currentFont.getSize(), 4, 256);
+		if (!MesquiteInteger.isCombinable(fontSize))
+			return false;
+		Font fontToSet = new Font (currentFont.getName(), currentFont.getStyle(), fontSize);
+		if (fontToSet!= null) {
+			currentFont = fontToSet;
+			if (tA!=null)
+				tA.setFont(fontToSet); //added here 12 Oct 01 because text area font was not being set in OS X 10.1
+		}
+		return super.setWindowFontSize(fontSize);
+	}
+	/*.................................................................................................................*/
+	/** Sets the window font.  */
+	public void setWindowFont(String fontName) {
+		Font fontToSet = new Font (fontName, currentFont.getStyle(), currentFont.getSize());
+		if (fontToSet!= null) {
+			currentFont = fontToSet;
+			if (tA!=null)
+				tA.setFont(fontToSet); //added here 12 Oct 01 because text area font was not being set in OS X 10.1
+		}
+		super.setWindowFont(fontName);
+	}
+	/*.................................................................................................................*/
+	public void copyGraphicsPanel(){
+		if (tA == null)
+			return;
+		String s = tA.getSelectedText();
+		if (!StringUtil.blank(s)) {
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(s);
+			clip.setContents(ss, ss);
+		}
+		else {
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(tA.getText());
+			clip.setContents(ss, ss);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets the font of the window", "[name of font]", commandName, "setFont")) { 
+			String fontName = ParseUtil.getFirstToken(arguments, pos);
+			setWindowFont(fontName);
+		}
+		else if (checker.compare(getClass(), "Sets the font size of the window", "[font size]", commandName, "setFontSize")) {
+			int fontSize = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (!setWindowFontSize(fontSize))
+				return null;
+		}
+		else if (checker.compare(getClass(), "Prints the contents of the window", null, commandName, "printWindow")) {
+			prWindow(MesquitePrintJob.AUTOFIT);
+		}
+		else if (checker.compare(getClass(), "Pastes selection from clipboard", null, commandName, "paste")) {
+			if (tA == null)
+				return null;
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			Transferable t = clip.getContents(this);
+			try {
+				String s = (String)t.getTransferData(DataFlavor.stringFlavor);
+				if (s!=null && tA!=null) {
+					String text = tA.getText();
+					String newText = text.substring(0, tA.getSelectionStart()) + s + text.substring(tA.getSelectionEnd(), text.length());
+					tA.setText(newText);
+					return s;
+				}
+			}
+			catch(Exception e){
+				MesquiteMessage.printStackTrace(e);
+			}
+			return null;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker); //note that this will repeat the setFont for the window
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteThread.java b/Source/mesquite/lib/MesquiteThread.java
new file mode 100644
index 0000000..0736de5
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteThread.java
@@ -0,0 +1,635 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import java.io.*;
+
+/** A thread for executing commands */
+public class MesquiteThread extends Thread implements CommandRecordHolder {
+	public static Vector threads;
+	static ListableVector doomedIndicators = null; //for progress indicators hidden but not yet disposed; to counter an OS X bug
+	static int suppressWaitWindow = 0;
+	private long currentlyExecutingID = 0; 
+	private long previouslyExecutingID = -1; 
+	protected boolean spontaneousIndicator = true;
+	public long count = 0;
+	public boolean checkOften = false;
+	protected int patience = 5;
+	private boolean suppressAllProgressIndicators = false;
+	private ProgressIndicator progressIndicator;
+	int id=0;
+	boolean dead = false;
+	protected CommandRecord comRec;
+	protected boolean sayGoodbye = true;
+	public static boolean suppressInteractionAsLibrary = false;
+	public static boolean unknownThreadIsScripting = true;
+	private Vector hints;  // a vector of MesquiteStrings supplying hints to MesquiteModules during execution, e.g. temporary defaults for module startup
+	private Vector cleanUpJobs;
+	private int listenerSuppressionLevel = 0; //0 no suppression; 1 lower level only; 2 all suppressed
+	public static int numFilesBeingRead =0;
+	
+	static int numInst = 1;
+	static {
+		threads = new Vector(10);
+		doomedIndicators = new ListableVector(10);
+	}
+	public MesquiteThread () {
+		super();
+		threads.addElement(this);
+		id = numInst++;
+		if (MesquiteTrunk.checkMemory)
+			MesquiteTrunk.mesquiteTrunk.logln("Thread started (id " + id + ")");
+	}
+	public MesquiteThread (Runnable r) {
+		super(r);
+		threads.addElement(this);
+		id = numInst++;
+		if (MesquiteTrunk.checkMemory)
+			MesquiteTrunk.mesquiteTrunk.logln("Thread started (id " + id + ")");
+	}
+	public static boolean isThreadBelongingToMesquite(){
+		Thread t = Thread.currentThread();
+		return (t instanceof MesquiteThread) ||(t instanceof ConsoleThread);
+	}
+	public String toString(){
+		return getClass().getName() + " = " + super.toString();
+	}
+
+	//=====================
+	/*logger for current thread */
+	Logger logger = null;
+	public void setLogger(Logger logger){
+		this.logger = logger;
+	}
+	public Logger getLogger(){
+		return logger;
+	}
+	public static void setLoggerCurrentThread(Logger logger){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.setLogger(logger);
+		}
+	}
+	public static void loglnToThreadLogger(String s){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.loglnToLogger(s);
+		}
+	}
+	public void loglnToLogger(String s){
+		if (logger != null && !loggingSuspended)
+			logger.logln(s);
+	}
+	public static void logToThreadLogger(String s){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.logToLogger(s);
+		}
+	}
+	public void logToLogger(String s){
+		if (logger != null && !loggingSuspended)
+			logger.log(s);
+	}
+	boolean loggingSuspended;
+	public static void suspendThreadLogging(){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.loggingSuspended = true;
+		}
+	}
+	public static void resumeThreadLogging(){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.loggingSuspended = false;
+		}
+	}
+	
+	boolean indicatorSuppressed = false;
+	public static boolean pleaseSuppressProgressIndicatorsCurrentThread(){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			return mt.indicatorSuppressed;
+		}
+		return false;
+	}
+	//request that explictly made progress indicators be suppressed
+	public static void setHintToSuppressProgressIndicatorCurrentThread(boolean s){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = ((MesquiteThread)t);
+			mt.indicatorSuppressed = s;
+		}
+	}
+	//=====================
+	//suppression level 0: no suppression; 1: lower level notifications suppressed; 2: 
+	public static boolean setListenerSuppressionLevel(int s){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			((MesquiteThread)t).setListenerSuppressionLevelOnThread(s);
+			return true;
+		}
+		return false;
+	}
+	public static int getListenerSuppressionLevel(){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			return ((MesquiteThread)t).getListenerSuppressionLevelOnThread();
+		}
+		return 0;
+	}
+	public int getListenerSuppressionLevelOnThread(){
+		return listenerSuppressionLevel;
+	}
+	public void setListenerSuppressionLevelOnThread(int s){
+		listenerSuppressionLevel = s;
+	}
+	public static void addCleanUpJob(CleanUpJob job){ //the name of the string is the module class name to which it applies; the value is the hint
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)t;
+			if (mt.cleanUpJobs == null)
+				mt.cleanUpJobs = new Vector();
+			mt.cleanUpJobs.addElement(job);
+		}
+
+	}
+	public static void removeCleanUpJob(CleanUpJob job){ //the name of the string is the module class name to which it applies; the value is the hint
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)t;
+			if (mt.cleanUpJobs != null)
+			mt.cleanUpJobs.removeElement(job);
+		}
+
+	}
+	public void doCleanUp(){
+			if (cleanUpJobs != null){
+				for (int i = 0; i< cleanUpJobs.size(); i++){
+					CleanUpJob job = (CleanUpJob)cleanUpJobs.elementAt(i);
+					job.cleanUp();
+				}
+				cleanUpJobs.removeAllElements();
+		}
+		
+	}
+	public static void addHint(MesquiteString hint){ //the name of the string is the module class name to which it applies; the value is the hint
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)t;
+			if (mt.hints == null)
+				mt.hints = new Vector();
+			mt.hints.addElement(hint);
+		}
+
+	}
+	public static String retrieveAndDeleteHint(MesquiteModule mb){
+		Thread t = Thread.currentThread();
+		if (t instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)t;
+			if (mt.hints == null)
+				return null;
+			for (int i=0; i<mt.hints.size(); i++){
+				MesquiteString s = (MesquiteString)mt.hints.elementAt(i);
+				if (mb.nameMatches(s.getName())) {
+					String q =  s.getValue();
+					mt.hints.removeElement(s);
+					return q;
+				}
+			}
+		}
+		return null;
+	}
+	public static void triggerWizard(){
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		if (cr != null)
+			cr.requestEstablishWizard(true);
+	}
+	public static void detriggerWizard(){
+		CommandRecord comRec = getCurrentCommandRecord();
+		if (comRec == null)
+			return;
+		comRec.requestEstablishWizard(false);
+		MesquiteDialogParent dlog = comRec.getWizard();
+		if (dlog != null) {
+			if (dlog.hiddenForCalculation)
+				dlog.setVisible(true);
+			MesquiteDialog currentDialog =dlog.getCurrentDialog();
+			if (currentDialog != null){
+				currentDialog.usingWizard = false;
+				currentDialog.dispose();
+				MesquiteDialog.currentWizard = null;
+			}
+			else 
+				dlog.pleaseDispose();
+		}
+	}
+
+	public void run(){
+		try {
+			super.run();
+			if (sayGoodbye)
+				threadGoodbye();
+		}
+		catch (MesquiteException e){
+			MesquiteMessage.warnProgrammer("MesquiteException thrown");
+		}
+	}
+	/*
+	public static boolean inScriptingCommand(){
+		Thread thisThread = Thread.currentThread();
+
+		if (!(thisThread instanceof CommandRecordHolder))
+			return false;
+		else {
+			CommandRecord attachedToThread = ((CommandRecordHolder) thisThread).getCommandRecord();
+			if (attachedToThread != null)
+				return attachedToThread.inScriptingCommand();			
+		}
+		return false;
+	}
+	 */
+	/*----------------*/
+	int duringNotification = 0;
+	public static boolean isDuringNotification(){
+		Thread t = Thread.currentThread();
+		if (!(t instanceof MesquiteThread))
+			return false;
+		MesquiteThread mt = (MesquiteThread)t;
+		return mt.duringNotification >0;
+	}
+	public static void incrementDuringNotification(){
+		Thread t = Thread.currentThread();
+		if (!(t instanceof MesquiteThread))
+			return;
+		MesquiteThread mt = (MesquiteThread)t;
+		mt.duringNotification++;
+	}
+	public static void decrementDuringNotification(){
+		Thread t = Thread.currentThread();
+		if (!(t instanceof MesquiteThread))
+			return;
+		MesquiteThread mt = (MesquiteThread)t;
+		mt.duringNotification--;
+		if (mt.duringNotification < 0)
+			mt.duringNotification = 0;
+	}
+	/*----------------*/
+	public static boolean isScripting(){
+		return isScripting(false);
+	}
+	public static boolean isScripting(boolean diagnose){
+		if (suppressInteractionAsLibrary){
+			if (diagnose) MesquiteMessage.println("isScripting:actingAsLibrary");
+			return true;
+		}
+		Thread thisThread = Thread.currentThread();
+
+		/*	default behaviour in thread-based system will be:
+		 * If not MesquiteThread, treat as scripting (i.e. suppress user interaction)
+		 * 		except if Mesquite is starting up (MesquiteTrunk.mesquiteTrunk.isStartupThread(mt)) then treat as nonscripting
+		 * If MesquiteThread but no CommandRecord is associatd with thread, treat as nonscripting (i.e. be safe and verbose)
+		 * */
+		//===  The following is temporary, to check how consistenly a CommandRecord is associated with the current thread
+		boolean stackTrace = false;
+		int situation = 0;
+		boolean shouldBeScripting = unknownThreadIsScripting;
+
+		//First check to see if this is MesquiteThread.  If not, then use default rules
+		if (thisThread instanceof mesquite.trunk.PhoneHomeThread){
+			if (diagnose) MesquiteMessage.println("isScripting:instanceof mesquite.trunk.PhoneHomeThread");
+			return false;
+		}
+		else if (thisThread instanceof mesquite.lib.ConsoleThread){
+			if (diagnose) MesquiteMessage.println("isScripting:instanceof mesquite.lib.ConsoleThread");
+			return MesquiteTrunk.consoleListenSuppressed;  //treat as scripting if backgrounded
+		}
+		else if (!(thisThread instanceof CommandRecordHolder)){ //not a MesquiteThread
+			if (MesquiteTrunk.mesquiteTrunk.isStartupShutdownThread(thisThread) || (MesquiteTrunk.isMacOSX() && mesquite.trunk.EAWTHandler.openFileThreads.indexOf(thisThread)>=0)) {
+				shouldBeScripting = false;  //startup, shutdown; should be treated as nonscripting, but if scripting then OK
+				situation = 1;
+				if (diagnose) MesquiteMessage.println("isScripting:!CommandRecordHolder, 1");
+				return false;
+			}
+			else {  //otherwise an unknown thread; treat as scripting
+				shouldBeScripting = unknownThreadIsScripting;
+				situation = 2;
+				if (diagnose) MesquiteMessage.println("isScripting:!CommandRecordHolder, 2");
+		}
+
+		}
+		//Second see if there is a CommandRecord attached to the current thread
+		else {
+			CommandRecord attachedToThread = ((CommandRecordHolder) thisThread).getCommandRecord();
+			//No CommandRecord attached to current thread, and yet this is a MesquiteThread.  Should be treated as nonscripting
+			if (attachedToThread == null){
+				shouldBeScripting = false;  
+				situation = 3;
+				if (diagnose) MesquiteMessage.println("isScripting:CommandRecordHolder, 3");
+			}
+			//That's OK as long as they agree about scripting
+			else {
+				shouldBeScripting = attachedToThread.recordIsScripting();  //Note: problem if attached is different command rec and disgrees on scripting!
+				if (attachedToThread.recordIsScripting())
+					situation = 4;
+				else
+					situation = 5;
+				if (diagnose) MesquiteMessage.println("isScripting:CommandRecordHolder, " + situation);
+			}
+		}
+		/*
+		if (shouldBeScripting != isScripting || stackTrace){
+			MesquiteMessage.println("@@@@@@@@@@@@@@@@@@@@");
+			MesquiteMessage.printStackTrace("UNEXPECTED SCRIPTING STATUS:  " + situation + " (" + isScripting + "; thread: " + thisThread + ")");
+		}*/
+		return shouldBeScripting;
+	}
+	public static void setShowWaitWindow(boolean show){
+		if (show)
+			suppressWaitWindow--;
+		else
+			suppressWaitWindow++;
+	}
+	public static void incrementSuppressWaitWindow(){
+		suppressWaitWindow++;
+	}
+	public static void decrementSuppressWaitWindow(){
+		suppressWaitWindow--;
+		if (suppressWaitWindow < 0){
+			MesquiteMessage.printStackTrace("Oops - negative suppressWaitWindow ");
+			suppressWaitWindow = 0;
+		}
+	}
+
+	public static boolean getShowWaitWindow(){
+		return suppressWaitWindow<1;
+	}
+
+	//not yet used
+	public static void setSuppressProgressIndicatorCurrentThread(boolean suppress){
+		Thread c = Thread.currentThread();
+		if (c instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)c;
+			mt.setSpontaneousIndicator(!suppress);
+		}
+	}
+	//not yet used
+	public static boolean getSuppressProgressIndicatorCurrentThread(){
+		Thread c = Thread.currentThread();
+		if (c instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)c;
+			return !mt.getSpontaneousIndicator();
+		}
+		return false;
+	}
+
+	//not yet used
+	public static void setSuppressAllProgressIndicatorsCurrentThread(boolean suppress){
+		Thread c = Thread.currentThread();
+		if (c instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)c;
+			mt.suppressAllProgressIndicators = suppress;
+		}
+	}
+	public static boolean getSuppressAllProgressIndicators(Thread c){
+		if (c !=null && c instanceof MesquiteThread){
+			MesquiteThread mt = (MesquiteThread)c;
+			return mt.suppressAllProgressIndicators;
+		}
+		return false;
+	}
+	public static void doomIndicator(Component indicator){
+		if (indicator == null)
+			return;
+		Frame f = MesquiteWindow.frameOfComponent(indicator);
+		if (f != null && f instanceof ProgressWindow){
+			f.hide();
+			if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()<1.4)
+				doomedIndicators.addElement((ProgressWindow)f, false);
+			else
+				f.dispose();
+		}
+		else {
+			indicator.setVisible(false);
+		}
+	}
+	public static void doomIndicator(ProgressWindow indicator){
+		if (indicator == null)
+			return;
+		indicator.hide();
+		if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()<1.4)
+			doomedIndicators.addElement(indicator, false);
+		else
+			indicator.dispose();
+	}
+	public static void surveyDoomedIndicators(){
+		if (doomedIndicators==null)
+			return;
+		try {
+
+			Listable[] dIndicators = doomedIndicators.getElementArray();
+			for (int i=0; i<dIndicators.length; i++) {
+				ProgressWindow doomed = (ProgressWindow) dIndicators[i];
+				doomed.doomTicks++;
+				if (doomed.doomTicks >5){
+					doomedIndicators.removeElement(doomed, false);
+					doomed.dispose();
+				}
+			}
+		}
+		catch (Exception e){
+			MesquiteMessage.warnProgrammer("***Exception surveying doomed indicators" + e);
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+
+	/* Called only for OS X jaguar, whose paint bugs with new window are worked around if resize forced*/
+	public static void surveyNewWindows(){
+		try {
+			if (MesquiteModule.mesquiteTrunk.windowVector.size() == 0)
+				return;
+			else {
+				Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+				while (e.hasMoreElements()) {
+					MesquiteWindow win = (MesquiteWindow)e.nextElement();
+					if (win.isVisible()){
+						win.tickled++;
+						if (win.tickled==2) {
+							Toolkit.getDefaultToolkit().sync();
+							win.setWindowSize(win.getWindowWidth(), win.getWindowHeight());
+						}
+					}
+				}
+			}
+			if (MesquiteModule.mesquiteTrunk.dialogVector.size() == 0)
+				return;
+			else {
+				Enumeration e = MesquiteModule.mesquiteTrunk.dialogVector.elements();
+				while (e.hasMoreElements()) {
+					MesquiteDialog dlog = (MesquiteDialog)e.nextElement();
+					if (dlog.isVisible()){
+						dlog.tickled++;
+						if (dlog.tickled==2) {
+							Toolkit.getDefaultToolkit().sync();
+							if (!dlog.alreadyDisposed && dlog instanceof ExtensibleDialog)
+								dlog.setSize(dlog.getSize().width+1, dlog.getSize().height+1);
+							//else
+							//	dlog.pack();
+						}
+					}
+				}
+			}
+		}
+		catch (Exception e){
+			MesquiteMessage.warnProgrammer("***Exception surveying new windows " + e);
+			MesquiteFile.throwableToLog(null, e);
+		}
+	}
+	/**/
+	public long getID(){
+		return id;
+	}
+	public int getPatience(){
+		return patience;
+	}
+	protected void setCurrent(long c){
+		currentlyExecutingID = c;
+	}
+
+	public long getCurrent(){
+		return currentlyExecutingID;
+	}
+	public void setPrevious(long c){
+		previouslyExecutingID = c;
+	}
+
+	public long getPrevious(){
+		return previouslyExecutingID;
+	}
+	public CommandRecord getCommandRecord(){
+		return comRec;
+	}
+	public void setCommandRecord(CommandRecord c){
+		comRec = c;
+	}
+	public String getCurrentCommandName(){
+		return null;
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public static void pauseForSeconds(double seconds){   
+		try {
+			Thread.sleep((int)(1000*seconds)); 
+		}
+		catch (InterruptedException e) {
+			return;
+		}
+	}
+	public static CommandRecord getCurrentCommandRecord(){
+		Thread mt = Thread.currentThread();
+		if (mt instanceof CommandRecordHolder)
+			return ((MesquiteThread)mt).getCommandRecord();
+		else
+			return null;
+	}
+	public static void setCurrentCommandRecord(CommandRecord c){
+		Thread mt = Thread.currentThread();
+		if (mt instanceof CommandRecordHolder)
+			((MesquiteThread)mt).setCommandRecord(c);
+	}
+	public static CommandRecord getCurrentCommandRecordDefIfNull(CommandRecord defaultIfNull){
+		Thread mt = Thread.currentThread();
+		CommandRecord cr = null;
+		if (mt instanceof CommandRecordHolder)
+			cr = ((CommandRecordHolder)mt).getCommandRecord(); // 
+		if (cr == null) {
+			if (MesquiteTrunk.debugMode && mt != MesquiteTrunk.startupShutdownThread && (MesquiteTrunk.isMacOSX() &&mesquite.trunk.EAWTHandler.openFileThreads.indexOf(mt)<0) && defaultIfNull == CommandRecord.nonscriptingRecord)
+				MesquiteMessage.printStackTrace("@@@@@@@@@@@@@@@@\nNS CommandRecord used because none is attached to thread");
+			return defaultIfNull;
+		}
+		return cr;
+
+	}
+	public boolean getSpontaneousIndicator(){
+		return spontaneousIndicator;
+	}
+	public void setSpontaneousIndicator(boolean sp){
+		spontaneousIndicator = sp;
+	}
+	public static boolean setProgressIndicatorCurrentThread(ProgressIndicator progressIndicator){
+		Thread thread = Thread.currentThread();
+		if (!(thread instanceof MesquiteThread))
+			return false;
+		MesquiteThread mt = (MesquiteThread)thread;
+		if (mt.progressIndicator!=null && progressIndicator != mt.progressIndicator) {
+			mt.progressIndicator.goAway();
+		}
+		CommandRecord cr = mt.getCommandRecord();
+		if (cr !=null)
+			cr.setProgressIndicator(progressIndicator);
+		mt.progressIndicator = progressIndicator;
+		if (progressIndicator !=null)
+			progressIndicator.setOwnerThread(mt);
+		return true;
+	}
+	public void setProgressIndicator(ProgressIndicator progressIndicator){
+
+		if (this.progressIndicator!=null && progressIndicator != this.progressIndicator) {
+			this.progressIndicator.goAway();
+		}
+		CommandRecord cr = getCommandRecord();
+		if (cr !=null)
+			cr.setProgressIndicator(progressIndicator);
+		this.progressIndicator = progressIndicator;
+		if (progressIndicator !=null)
+			progressIndicator.setOwnerThread(this);
+	}
+
+	public ProgressIndicator getProgressIndicator(){
+		return progressIndicator;
+	}
+	public void threadGoodbye(){
+		if (progressIndicator!=null)
+			progressIndicator.goAway();
+		threads.removeElement(this);
+		if (MesquiteTrunk.checkMemory)
+			MesquiteTrunk.mesquiteTrunk.logln("Thread disposed (id " + id + ")");
+		CommandRecord rc = getCurrentCommandRecord();
+		if (rc != null && rc.getScriptingFile()!=null)
+			rc.getScriptingFile().closeReading();
+		dead = true;
+	}
+	public boolean dead(){
+		return dead;
+	}
+	public void interrupt(){
+		threadGoodbye();
+		setPriority(MIN_PRIORITY);
+		super.interrupt();
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/MesquiteTimer.java b/Source/mesquite/lib/MesquiteTimer.java
new file mode 100644
index 0000000..25f923b
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTimer.java
@@ -0,0 +1,157 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+ 
+/*=======================*/
+/** A timer for profiling.*/
+public class MesquiteTimer {
+	long accumulatedTime = 0;
+	long currentBout = 0;
+	long lastCheckedTime = 0;
+	long veryStart = 0;
+	int timesStarted = 0;
+	public MesquiteTimer(){
+		veryStart = System.currentTimeMillis();
+	}
+	public MesquiteTimer(boolean startNow){
+		veryStart = System.currentTimeMillis();
+	}
+	public void start() {
+		if (timesStarted==0) // set veryStart to first call to start.
+			veryStart = System.currentTimeMillis();
+		timesStarted++;
+		currentBout = System.currentTimeMillis();
+		lastCheckedTime = currentBout;
+	}
+	public void reset() {
+		currentBout = 0;
+		accumulatedTime = 0;
+	}
+	public void resetLastTime() {
+		lastCheckedTime = System.currentTimeMillis();
+	}
+	public void fullReset() {
+		veryStart = System.currentTimeMillis();
+		reset();
+		resetLastTime();
+	}
+	public void end() {
+		lastCheckedTime = System.currentTimeMillis();
+		accumulatedTime += System.currentTimeMillis() - currentBout;
+	}
+	public long timeSinceLast() {
+		long t =System.currentTimeMillis() -lastCheckedTime;
+		lastCheckedTime = System.currentTimeMillis();
+		return  t;
+	}
+	public double timeSinceLastInSeconds() {
+		long t =System.currentTimeMillis() -lastCheckedTime;
+		lastCheckedTime = System.currentTimeMillis();
+		return  (1.0*t)/1000.0;
+	}
+	public long timeSinceVeryStart() {
+		long t =System.currentTimeMillis() -veryStart;
+		return  t;
+	}
+	public double timeSinceVeryStartInSeconds() {
+		long t =System.currentTimeMillis() -veryStart;
+		lastCheckedTime = System.currentTimeMillis();
+		return  (1.0*t)/1000.0;
+	}
+	public static String getDayHoursMinutesSecondsFromMilliseconds(long t) {
+		double seconds =  (1.0*t)/1000.0;
+		long minutes = 0;
+		long hours = 0;
+		long days = 0;
+		if (seconds>60.0){
+			minutes = (long)seconds/60;
+			seconds = seconds-minutes*60.0;
+		}
+		if (minutes>60){
+			hours = minutes/60;
+			minutes = minutes-hours*60;
+		}
+		if (hours>24){
+			days = hours/24;
+			hours = hours-days*24;
+		}
+		String s = "";
+		if (days>0){
+			if (days==1)
+				s+= "1 day ";
+			else
+				s+= "" + days + " days ";
+		}
+		if (hours>0) {
+			if (hours==1)
+				s+= "1 hour ";
+			else
+				s+= "" + hours + " hours ";
+		}
+		if (minutes>0) {
+			if (minutes==1)
+				s+= "1 minute ";
+			else
+				s+= "" + minutes + " minutes ";
+		}
+		if (seconds>0.0)
+			s+= "" + MesquiteDouble.toStringDigitsSpecified(seconds, 1) + " seconds ";
+		return s;
+	}
+	public static String getHoursMinutesSecondsFromMilliseconds(long t) {
+		double seconds =  (1.0*t)/1000.0;
+		long minutes = 0;
+		long hours = 0;
+		if (seconds>60.0){
+			minutes = (long)seconds/60;
+			seconds = seconds-minutes*60.0;
+		}
+		if (minutes>60){
+			hours = minutes/60;
+			minutes = minutes-hours*60;
+		}
+		String s = "";
+		if (hours>0) {
+			if (hours==1)
+				s+= "1 hour ";
+			else
+				s+= "" + hours + " hours ";
+		}
+		if (minutes>0) {
+			if (minutes==1)
+				s+= "1 minute ";
+			else
+				s+= "" + minutes + " minutes ";
+		}
+		if (seconds>0.0)
+			s+= "" + MesquiteDouble.toStringDigitsSpecified(seconds, 1) + " seconds ";
+		return s;
+	}
+
+	public String timeSinceVeryStartInHoursMinutesSeconds() {
+		long t =System.currentTimeMillis() -veryStart;
+		lastCheckedTime = System.currentTimeMillis();
+		return getHoursMinutesSecondsFromMilliseconds(t);
+	}
+
+	public long getAccumulatedTime() {
+		return accumulatedTime;
+	}
+	public long getTimesStarted() {
+		return timesStarted;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MesquiteTool.java b/Source/mesquite/lib/MesquiteTool.java
new file mode 100644
index 0000000..4da60e6
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTool.java
@@ -0,0 +1,346 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls*/
+/* ======================================================================== */
+/** A tool (i.e. cursor) that can be active and used on items on the screen.*/
+public class MesquiteTool implements Listable, Explainable, ImageOwner, KeyListener {
+	protected String name; 
+	protected String imageDirectoryPath;
+	protected String imageFileName;
+	protected String fullDescription;
+	protected String explanation;
+	protected String optionImageFileName;
+	protected ToolPalette palette;
+	private boolean inUse = false;
+	boolean amIArrowTool = false;
+	private ToolKeyListener toolKeyListener;
+	MesquiteCommand optionsCommand;
+	MesquiteModule popupOwner;
+	MesquiteButton button;
+	Point hotSpot, optionHotSpot;
+	boolean optionDown = false;
+	Image cursorImage = null;
+	boolean[] currentKeyCodesDown, currentKeyCharsDown;
+	private boolean allowAnnotate = false;
+	MesquiteCursor standardCursor;
+	protected MesquiteCursor optionCursor;
+	MesquiteCursor currentStandardCursor;
+	MesquiteCursor currentOptionCursor;
+	protected Object initiator;
+	protected boolean enabled=true;
+	protected boolean onlyWorksWhereSpecified = false;
+	protected boolean hasTemporaryOptionCursor = false;
+	protected boolean hasTemporaryShiftCursor = true;
+	
+	public MesquiteTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String fullDescription, String explanation) {
+		if (initiator !=null)
+			this.name = initiator.getClass().getName() + "." + name;
+		else
+			this.name = name;
+		this.initiator = initiator;
+		this.imageDirectoryPath = imageDirectoryPath;
+		this.imageFileName = imageFileName;
+		this.fullDescription = fullDescription;
+		this.explanation = explanation;
+		hotSpot = new Point(hotX, hotY);
+		optionHotSpot = new Point(hotX, hotY);
+		currentKeyCodesDown = new boolean[512];
+		currentKeyCharsDown = new boolean[512];
+		standardCursor = new MesquiteCursor(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY);
+		currentStandardCursor = standardCursor;
+		
+	}
+	public Object getInitiator(){
+		return initiator;
+	}
+	public void setAllowAnnotate(boolean allow){
+		allowAnnotate = allow;
+	}
+	public boolean getAllowAnnotate(){
+		return allowAnnotate;
+	}
+	public void setCursorImage(Image i){
+		cursorImage = i;
+	}
+	public Image getCursorImage(){
+		return cursorImage;
+	}
+	public void setOptionDown(boolean od){
+		optionDown = od;
+	}
+	public String getName(){
+		return name;
+	}
+	public void setButton(MesquiteButton button){
+		this.button = button;
+	}
+	public MesquiteButton getButton(){
+		return button;
+	}
+	public void setPalette(ToolPalette palette){
+		this.palette = palette;
+	}
+	public ToolPalette getPalette(){
+		return palette;
+	}
+	public void setEnabled(boolean enabled){
+		boolean oldEnabled = this.enabled;
+		this.enabled = enabled;
+		if (oldEnabled!=enabled) {
+			if (getButton()!=null)
+				getButton().repaint();
+			if (!enabled && getPalette()!=null && getButton()!= null && getPalette().getCurrentTool()==this)  //turning off
+				getPalette().setToDefaultTool();
+		}
+	}
+	public boolean getEnabled(){
+		return enabled;
+	}
+	
+	
+	//can be overridden to, for instance, change the cursor
+	public void cursorInPanel(int modifiers, int x, int y, MousePanel panel, boolean in){
+	}
+	
+	public void setIsArrowTool(boolean a){
+		amIArrowTool = a;
+	}
+	public boolean isArrowTool(){
+		return amIArrowTool;
+	}
+	public void setHotSpot(int x, int y){
+		hotSpot.x = x;
+		hotSpot.y = y;
+	}
+	public Point getHotSpot(){
+		if (optionDown && optionImageFileName!=null)
+			return optionHotSpot;
+		return hotSpot;
+	}
+	public MesquiteCommand getOptionsCommand(){
+		return optionsCommand;
+	}
+	public void setOptionsCommand(MesquiteCommand oc){
+		optionsCommand = oc;
+	}
+	public void setPopUpOwner(MesquiteModule own){
+		popupOwner = own;
+	}
+	public MesquiteModule getPopUpOwner(){
+		return popupOwner;
+	}
+	public void chooseOptions(Container c, int x, int y){
+		if (optionsCommand!=null)
+			optionsCommand.doItMainThread(Integer.toString(x) + " " + y + " " + ParseUtil.tokenize(getName()), CommandChecker.getQueryModeString("Tool", optionsCommand, this), this);
+		else if (popupOwner!=null)
+			popupOwner.showPopUp(c, x+5, y+5);  
+	}
+	public void setDescription(String text){
+		this.fullDescription = text;
+	}
+	public String getDescription(){
+		return fullDescription;
+	}
+	/*.................................................................................................................*/
+	public Cursor getCursor(){  
+		if (optionDown && currentOptionCursor!=null) 
+			return currentOptionCursor.getCursor();
+		else
+			return currentStandardCursor.getCursor();
+	}
+	/*.................................................................................................................*
+	public Cursor getCursor(Image im, String imageFileName, Point hotSpot){  
+		try { //just in case Java2 not available
+			if (im == null){
+				Dimension best = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
+				if ((best.width>16 || best.height>16) && MesquiteFile.fileExists(getSizedImagePath(best.width, imageFileName))){
+					im = MesquiteImage.getImage(getSizedImagePath(best.width, imageFileName));
+					if (im == null)
+						im = MesquiteImage.getImage(getImagePath(imageFileName));
+				}
+				else 
+					im = MesquiteImage.getImage(getImagePath(imageFileName));
+				setCursorImage(im);
+			}
+			if (!MesquiteImage.waitForImageToLoad(im)) {
+				MesquiteMessage.println("Note: image of cursor of tool not obtained: " + getName() + "  " + getImagePath(imageFileName));
+				return Cursor.getDefaultCursor();
+			}
+			
+			Cursor c = Toolkit.getDefaultToolkit().createCustomCursor(im, hotSpot, getName());
+			return c;
+		}
+		catch (Throwable t){
+			return Cursor.getDefaultCursor();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getExplanation(){
+		if (explanation==null)
+			return getDescription();
+		else
+			return explanation; 
+	}
+	/* override this to do cleanup with the tool is turned off */
+	public void turningOff(){
+	}
+	public void setInUse(boolean inUse){
+		if (this.inUse && !inUse)
+			turningOff();
+		this.inUse = inUse;
+	}
+	public boolean getInUse(){
+		return inUse;
+	}
+	public void setOptionImageFileName(String path, int x, int y){
+		optionImageFileName = path;
+		optionHotSpot.x = x;
+		optionHotSpot.y = y;
+		optionCursor = new MesquiteCursor(null, name, imageDirectoryPath, path, x, y);
+		currentOptionCursor = optionCursor;
+	}
+	public void setCurrentOptionCursor(MesquiteCursor mc){
+		if (mc==null)
+			currentOptionCursor = optionCursor;
+		else
+			currentOptionCursor = mc;
+	}
+	public void setCurrentStandardCursor(MesquiteCursor mc){
+		if (mc==null)
+			currentStandardCursor = standardCursor;
+		else
+			currentStandardCursor = mc;
+	}
+	public void setStandardCursor(MesquiteCursor mc, String name){
+		if (mc!=null) {
+			standardCursor = mc;
+			setCurrentStandardCursor(mc);
+			if (name!=null)
+				setImageFileName(name);
+		}
+	}
+	public String getOptionImagePath(){
+		if (optionImageFileName ==null)
+			return null;
+		return imageDirectoryPath + optionImageFileName;
+	}
+	public String getSizedOptionImagePath(int s){
+		if (optionImageFileName ==null)
+			return null;
+		return imageDirectoryPath + s + optionImageFileName;
+	}
+	public String getImagePath(){
+		if (optionDown && getOptionImagePath()!=null) {
+			return getOptionImagePath();
+		}
+		return imageDirectoryPath + imageFileName;
+	}
+	/*.................................................................................................................*/
+	public String getImagePath(String imageFileName){
+		return imageDirectoryPath + imageFileName;
+	}
+	public void setImageFileName(String name){
+		imageFileName = name;
+		cursorImage = null; // to force reloading
+		if (button !=null) {
+			button.resetImage(getImagePath());
+		}
+	}
+	/*.................................................................................................................*/
+	public String getSizedImagePath(int s, String imageFileName){
+		return imageDirectoryPath + s + imageFileName;
+	}
+	public String getSizedImagePath(int s){
+		if (optionDown && getSizedOptionImagePath(s)!=null) {
+			return getSizedOptionImagePath(s);
+		}
+		return imageDirectoryPath + s + imageFileName;
+	}
+	
+	public void setToolKeyListener(ToolKeyListener  t){ 
+		toolKeyListener = t;
+	}
+	
+	/**Returns whether or not Tool considers that a particular key is down and not yet released; by keyCode.  Note this does not distinguish upper case from lower case letter*/
+	public boolean keyCodeDown(int kc){ 
+		if (kc>=0 && kc<currentKeyCodesDown.length)
+			return currentKeyCodesDown[kc];
+		return false;
+	}
+	/**Returns whether or not Tool considers that a particular key is down and not yet released; by keyChar. Note this does not report modifiers*/
+	public boolean keyCharDown(int kc){ 
+		if (kc>=0 && kc<currentKeyCharsDown.length)
+			return currentKeyCharsDown[kc];
+		return false;
+	}
+	/*-------*/
+	public void keyTyped(KeyEvent e){
+		if (toolKeyListener!=null)
+			toolKeyListener.keyTyped(e, this);
+	}
+	
+	public void keyPressed(KeyEvent e){
+		int kc = e.getKeyCode();
+		if (kc>=0 && kc<currentKeyCodesDown.length)
+			currentKeyCodesDown[kc] = true;
+		int kch = e.getKeyChar();
+		if (kch>=0 && kch<currentKeyCharsDown.length)
+			currentKeyCharsDown[kch] = true;
+		if (toolKeyListener!=null)
+			toolKeyListener.keyPressed(e, this);
+	}
+	public void keyReleased(KeyEvent e){
+		int kc = e.getKeyCode();
+		if (kc>=0 && kc<currentKeyCodesDown.length)
+			currentKeyCodesDown[kc] = false;
+		int kch = e.getKeyChar();
+		if (kch>=0 && kch<currentKeyCharsDown.length)
+			currentKeyCharsDown[kch] = false;
+		if (toolKeyListener!=null)
+			toolKeyListener.keyReleased(e, this);
+	}
+	public void dispose(){ 
+	}
+
+	public boolean getOnlyWorksWhereSpecified() {
+		return onlyWorksWhereSpecified;
+	}
+
+	public void setOnlyWorksWhereSpecified(boolean onlyWorksWhereSpecified) {
+		this.onlyWorksWhereSpecified = onlyWorksWhereSpecified;
+	}
+
+	public boolean hasTemporaryOptionCursor() {
+		return hasTemporaryOptionCursor;
+	}
+
+	public void setHasTemporaryOptionCursor(boolean hasTemporaryOptionCursor) {
+		this.hasTemporaryOptionCursor = hasTemporaryOptionCursor;
+	}
+
+	public boolean hasTemporaryShiftCursor() {
+		return hasTemporaryShiftCursor;
+	}
+
+	public void setHasTemporaryShiftCursor(boolean hasTemporaryShiftCursor) {
+		this.hasTemporaryShiftCursor = hasTemporaryShiftCursor;
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteTree.java b/Source/mesquite/lib/MesquiteTree.java
new file mode 100644
index 0000000..f9eba18
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTree.java
@@ -0,0 +1,6101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified:
+25 Aug 01 (WPM): added getTerminalNode
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+import java.util.*;
+
+import mesquite.lib.duties.NumberForTree;
+
+/* ======================================================================== */
+/** The basic Tree class of Mesquite.  Nodes are represented by integers (Object representation of nodes is too
+memory-costly). Node relationships use the first daughter/next sister system to accommodate polytomies easily.
+Thus a recursive method can take the following form and be called initially by recurse(tree, tree.getRoot()); :
+<pre><dl><dd>void recurse (Tree tree, int N) {
+<dl><dd>for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+<dl><dd>recurse(tree, d);</dl></dl><dd>}</dl></pre>
+Daughters, sisters and parents of a node can be found using public methods.<p>
+Information can be stored at the nodes of the tree in the following ways.  The first two storage sites are directly embedded within the Tree.  Modules
+cannot store their own private information directly in the Tree, but they can use the other storage methods.
+<ul>
+<li>Arrays embedded within the Tree object storing which nodes are mother, sister, daughter, etc.  
+These arrays are always instantiated and are private; they are accessed via methods such as motherOfNode(node).
+<li>Arrays storing branch lengths and any String label attached to the node.  
+These arrays are instantiated as needed and are private, but their information can be set and gotten using methods provided.
+<li>Because Tree extends Associable, arrays (LongArray, DoubleArray, ObjectArray or Bits) can be requested that will be attached to the tree and maintained (i.e. the array sizes 
+will be automatically adjusted if the tree's size changes).   This is useful place to store information that is to follow the tree around, to be stuck\
+to the tree like lichen. When the tree is written, this information will be written within the tree description String in special comments
+associated with each node.  When such a tree description is read, the information will be read without assistance from modules.  Thus, the information
+is of restricted forms, but is public and persistent.  Some things that currently use this associable storage are: whether the branch is selected, 
+the color of the branch, the width of the lineage.  Branch selection is given special status because it is used in various calculations, and thus has 
+streamlined methods to access the information.  The information is stored just as is the other Associable information.
+<li>There is a special vector that allows objects to be associated with the tree, called the "sensitiveAttachments".  It is private, but objects can be attached, removed
+or retrieved from it using the methods provided.  Such information is "sensitive" in the sense that it it to be detached as soon as the tree is 
+altered.  This system is still immature; it was invented for information that was to be attached to the tree and used by other modules, but
+the information would become untrustworthy as soon as the tree changed.  Since the module attaching it to the tree would find it difficult to follow the tree 
+as it is subsequently used, it attaches the information with the understanding that the information is to be destroyed as soon as the tree changes 
+(this is done in incrementVersion()).
+<li>All of the above information is referenced directly or indirectly from the Tree object, and thus follows the tree object around.  Most modules will
+find it useful to have private information that is associated with the tree.  They can do this by maintaining arrays that have as many elements
+as numNodeSpaces in the tree, with the ith element of the array being associated with the ith node.  The size of the array can be checked, and readjusted 
+if needed, each time a tree is passed.
+</ul>
+Support for special sorts of trees:
+<ul>
+<li>Reticulate trees:  Support  is incomplete. For each node, only one mother node is designated, but if additional parents are specified, they are added to the set
+of parents of the node.  Thus, calculations needing non-reticulate trees can simply use the mother node and pretend
+like the additional parents don't exist.  Calculations needing reticulate trees can ask for the parents.  (The set of parents
+should be built to include the mother node.)  Tree reading of reticulate nodes is incomplete. 
+<li>Observed taxa fixed as ancestors: not yet supported.
+<li>Truly unrooted trees, with node-rings storage and recursion used by PHYLIP:  not yet supported.  There are some special methods whose names end in
+UR that allow access to the tree as if unrooted.
+</ul>*/
+public class MesquiteTree extends Associable implements AdjustableTree, Listable, Renamable, Commandable, MesquiteListener, CompatibilityChecker, Identifiable {
+	/** The set of taxa to which terminal nodes refer. */
+	private Taxa taxa;
+	/** The tree vector to which this Tree belongs.  The tree does not need to belong to a TreeVector, but if it is, then it is stored here
+	so that the TreeVector's translation table can be used when the Tree is written */
+	private TreeVector treeVector = null;
+	/** The name of the tree.*/
+	private String name;
+	/** the nodes that are the root and subRoot*/
+	private int root, subRoot;
+	/** The number of taxa in the Taxa at last check. */
+	private int oldNumTaxa;
+	/** The size of various arrays within the tree object; that is, the number of spaces there are for individual nodes in the tree.  This is automatically increased as needed.*/
+	private int numNodeSpaces;
+	/** true if nodes other than root and subRoot are assigned*/
+	private boolean exists;
+	/** The array of first daughter nodes.  The ith element indicates what is the number of the first daughter of the ith node.*/
+	private int[] firstDaughter;  
+	/** The array of next sister nodes.  The ith element indicates what is the number of the next sister of the ith node.*/
+	private int[] nextSister;  
+	/** The array of mother nodes.  The ith element indicates what is the number of the mother of the ith node.*/
+	private int[] mother;  
+	/** The array of taxon numbers.  If the node is internal, this number should be negative.  Otherwise, the taxon number is the the number of the taxon within the Taxa*/
+	private int[] taxonNumber;  
+	/** The array of node numbers of taxa; the inverse of taxonNumber.  New to 2. 7, for efficiency with large trees.  If the taxon is not in the tree this number should be negative.*/
+	private int[] nodeOfTaxon;  
+	/** A temporary array of booleans, for use currently to reset taxonNumbers (see resetNodeOfTaxonNumbers).*/
+	private boolean[] flags;  
+	/** The branch lengths of the branches.  This array is instantiated only if needed.*/
+	private double[] branchLength;
+	/** The clade name labels at the nodes.   This array is instantiated only if needed.*/
+	private String[] label;  
+	/** The array of parents arrays (used for reticulate trees).  This array is always instantiated, but at each node the array of parents is instantiated only if needed.*/
+	private int[][] parents;
+	/** An array of id's of taxa; this is obtained from the Taxa initially and is updated when taxa are deleted, added or moved; it serves as a reference for what this Tree thinks
+	are the current taxa id's.  If taxa are added, deleted or moved, it is used to compare to the current id array returned by the Taxa to decide how taxon numbers (which
+	are not the same as taxa id's, and instead are linear 1... within the Taxa) in the tree should be updated.  At any other time, if there is a mismatch between the stored
+	taxa id's and those returned by the Taxa, then a warning can be given.  In future it may be best to have the Taxa store an oldID's array that is reset after every notifyListeners so as
+	not to burden every MesquiteTree (and CharacterData, and...) to store an array, but that would remove the error checking ability.*/
+	private long[] taxaIDs;
+	/** A vector to store objects that are to be cut off if the tree changes, though to be kept if it's cloned*/
+	private Vector sensitiveAttachments; 
+	/** A number recording the topology version number.  With changes of topology of the tree, the version number is incremented.  This way you know if you're dealing with the exact same tree or not.*/
+	private long topologyVersion = 0;
+	/** A number recording the branch lengths version number.  With changes of branch lengths or topology of the tree, the version number is incremented.  This way you know if you're dealing with the exact same tree or not.*/
+	private long branchLengthsVersion = 0;
+	/** A number recording the last taxa version with which synchronized.*/
+	private long taxaVersion = 0;
+	/** Locks name to provoke error messages if name change attempted.*/
+	private boolean nameLock = false;
+	/** Currently not used internally, though a query to isLocked currently does indicate true if the tree is at that moment undergoing modification and thus shouldn't be touched.*/
+	private boolean locked = false;
+	/** A vector to store the MesquiteListeners currently listening for changes in this tree.
+	Vector listeners;
+	/** A count of the listeners remaining, used to try to catch memory leaks.
+	private static int listenersRemaining=0;
+	 */
+	/** True if internal node names are treated as cosmetic */
+	public static boolean cosmeticInternalNames = true;
+	/** True if internal node names should be converted to annotations */
+	public static boolean convertInternalNames = false;
+	/** True if should warn if reticulations found */
+	//public static boolean warnReticulations = true;
+	/** True if polytomies in tree treated as hard by default */
+	public static boolean polytomyDefaultHard = true;
+	/** True if tree reading permits truncated taxon names */
+	public static boolean permitTruncTaxNames = true;
+	/** True if tree reading permits taxon names to be expressed as t0, t1, etc.*/
+	public static boolean permitT0Names = true;
+	/** If true, then taxa block is enlarged when unfamiliar taxon name encountered */
+	private boolean permitTaxaBlockEnlargement = false;
+	/** 0 if polytomies in tree treated as hard, 1 if soft, 2 if not yet assigned */
+	private int polytomiesHard = 2;
+	/** A boolean that stores whether the tree is rooted or not */
+	private boolean rooted = true;
+	/** A counter of the total number of Trees created (for debugging/memory leaks)*/
+	public static long totalCreated = 0;
+	/** A counter of the total number of Trees disposed (for debugging/memory leaks)*/
+	public static long totalDisposed = 0;
+	/** A counter of the total number of Trees finalized (for debugging/memory leaks)*/
+	public static long totalFinalized = 0;
+	/** The id number of this Tree (each tree during a run receives its own number */
+	private long id=0;
+
+	/** If this tree is read in from a file, this is the number of this tree within the file */
+	private int fileIndex = MesquiteInteger.unassigned;
+
+	/** If modified since named, "*" is returned with name. */
+	private boolean modifiedSinceNamed = false;
+	/** The assigned number of the tree (used by Stored Trees to record the index of the original tree in a TreeVector from which this was cloned) */ 
+	private int sequenceNumber = -1;
+
+	/** If true then after branch moves, etc., tree integrity is checked.*/
+	public static boolean checkIntegrity = false; //Todo: have settable preference
+
+	private static MesquiteTimer[] timers;
+
+	static {
+		timers = new MesquiteTimer[10];
+		for (int i= 0; i<10; i++)
+			timers[i] = new MesquiteTimer();
+	}
+	/** The constructor, passed the Taxa on which the tree is based */
+	public MesquiteTree (Taxa taxa) {
+		super(standardNumNodeSpaces(taxa));
+		totalCreated++;
+		id = totalCreated;
+		this.taxa = taxa;
+		numNodeSpaces = standardNumNodeSpaces(taxa); //extra in case bad taxa OR INTERNAL UNBRANCHED NODES
+		firstDaughter= new int[numNodeSpaces];  
+		nextSister= new int[numNodeSpaces];  
+		mother= new int[numNodeSpaces];  
+		taxonNumber= new int[numNodeSpaces];  
+		flags = new boolean[numNodeSpaces];
+		parents = new int[numNodeSpaces][];
+		if (taxa==null)
+			MesquiteMessage.warnProgrammer(" Taxa in constructor for Tree is null ");
+		else {
+			nodeOfTaxon = new int[taxa.getNumTaxa()];
+			oldNumTaxa = taxa.getNumTaxa();
+			taxaVersion = taxa.getVersionNumber();
+			taxaIDs = taxa.getTaxaIDs();
+			//	taxa.addListener(this);//modified 19 Nov 01; trees no longer responsible for listening, to prevent memory leaks if not disposed; TreeVector in charge of notifying
+		}
+		intializeTree();
+	}
+	/** The constructor, passed the Taxa on which the tree is based.  This initializer is used only for cloning,
+	as it prepares for an exact copy of the tree even if it's currently out of date*/
+	public MesquiteTree (Taxa taxa, int numTaxa, int numNodeSpaces, long taxaVersion) {
+		super(numNodeSpaces);
+		totalCreated++;
+		id = totalCreated;
+		this.taxa = taxa;
+		this.numNodeSpaces = numNodeSpaces; //extra in case bad taxa OR INTERNAL UNBRANCHED NODES
+		firstDaughter= new int[numNodeSpaces];  
+		nextSister= new int[numNodeSpaces];  
+		mother= new int[numNodeSpaces];  
+		taxonNumber= new int[numNodeSpaces];  
+		nodeOfTaxon = new int[taxa.getNumTaxa()];
+		flags = new boolean[numNodeSpaces];
+		parents = new int[numNodeSpaces][];
+		this.taxaVersion = taxaVersion;
+		if (taxa==null)
+			MesquiteMessage.warnProgrammer(" Taxa in constructor for Tree is null ");
+		else {
+			oldNumTaxa = numTaxa;
+			taxaIDs = taxa.getTaxaIDs();
+			//	taxa.addListener(this);//modified 19 Nov 01; trees no longer responsible for listening, to prevent memory leaks if not disposed; TreeVector in charge of notifying
+		}
+		intializeTree();
+	}
+	/** The constructor, passed the Taxa on which the tree is based, and a string description of the tree */
+	public MesquiteTree (Taxa taxa, String description) {
+		this(taxa);
+		readTree(description);
+	}
+	public String toHTMLStringDescription(){
+		String sT = super.toHTMLStringDescription();
+		if (!StringUtil.blank(sT))
+			return "<li>Tree: " + getName() + "<ul>" + sT + "</ul></li>";
+		return "<li>Tree: " + getName() + "</li>";
+	}
+	/*-----------------------------------------*/
+	/** This sets arrays to default values, including zapping the labels and parents array elements.  Sensitive attachments also removed.
+	It does not change Associateds nor does it reset numNodeSpaces */
+	private void intializeTree() {
+		exists = false;
+		for (int i=0; i<numNodeSpaces; i++){	//not extras, not just 2t+3
+			firstDaughter[i]=0;
+			nextSister[i]=0;
+			mother[i]=0;
+			setTaxonNumber(i, -1);
+			flags[i] = false;
+		}
+		firstDaughter[0]=-1;
+		nextSister[0]=-1;
+		mother[0]=-1;
+		setTaxonNumber(0, -1);
+		for (int i=0; i< nodeOfTaxon.length; i++)
+			nodeOfTaxon[i] = -1;
+		subRoot = 1;
+		mother[subRoot] = -1;
+		root = 2;
+		mother[root] = subRoot;
+		firstDaughter[subRoot]=root;
+		if (branchLength!=null) 
+			for (int i=0; i<numNodeSpaces; i++)
+				branchLength[i] = MesquiteDouble.unassigned;
+		if (label!=null) 
+			for (int i=0; i<numNodeSpaces; i++)
+				label[i] = null;
+		for (int i=0; i<numNodeSpaces; i++)
+			parents[i] = null;
+		if (sensitiveAttachments!=null)
+			sensitiveAttachments.removeAllElements();
+
+		rooted = true;
+		locked = false;
+	}
+	/*-----------------------------------------*/
+	int lastOpenFound = -1;
+	/** Returns an open (unused) node space in the arrays.  If none available, automatically expands storage. */
+	private int openNode() {
+		if (lastOpenFound>=-1 && lastOpenFound+1<numNodeSpaces){
+			if (mother[lastOpenFound +1] == 0){
+				lastOpenFound++;
+				return lastOpenFound;
+			}
+		}
+		for (int i=1; i<numNodeSpaces; i++)
+			if (mother[i]==0){
+				lastOpenFound = i;
+				return i;
+			}
+		setNumNodeSpaces(numNodeSpaces+20); //one chance to expand
+		for (int i=1; i<numNodeSpaces; i++)
+			if (mother[i]==0){
+				lastOpenFound = i;
+				return i;
+			}
+		MesquiteMessage.warnProgrammer("no open nodes in Tree");//for some reason didn't work
+		lastOpenFound = -1;
+		return 0;
+	}
+	/*-----------------------------------------*/
+	long cloneID = 0;
+	/** Returns a clone of the tree.  Care is required:  as MesquiteTree on its own does not establish a listener
+	to the Taxa to respond to changes in the Taxa.  It is not needed if the clone is to be placed in a TreeVector, nor if the tree will be
+	remade by a Tree Source in response to taxa changes.  Otherwise, a listener should be established.*/
+	public MesquiteTree cloneTree() {
+		MesquiteTree T = null;
+		boolean success = false;
+		cloneID++;
+		int gcCount = 0;
+		while (!success){
+			try {
+				T = new MesquiteTree(taxa, oldNumTaxa, numNodeSpaces, taxaVersion);
+				T.setToClone(this);
+				success = true;
+			}
+			catch (OutOfMemoryError e){
+				System.out.println("Out of memory error while cloning tree " + getID() + " clone ID " + cloneID + " gc " + gcCount + "; Mesquite will attempt to continue..  See file memory.txt in the Mesquite_Folder.");
+				MesquiteTrunk.mesquiteTrunk.logln("Out of memory error while cloning tree " + getID() + " clone ID " + cloneID + " gc " + gcCount + "; Mesquite will attempt to continue..  See file memory.txt in the Mesquite_Folder.");
+				try {
+					Thread.sleep(50);
+					Runtime rtm = Runtime.getRuntime();
+					rtm.gc();
+					gcCount++;
+				}
+				catch (InterruptedException ie){
+					Thread.currentThread().interrupt();
+				}
+				catch (OutOfMemoryError ee){
+				}
+			}
+		}
+		return T;
+	}
+	/*-----------------------------------------*/
+	/** Sets this tree to be a clone of that passed.*/
+	public void setToClone(MesquiteTree tree) {
+		if(!taxa.equals(tree.getTaxa(), false, true))
+			this.taxa = tree.getTaxa();
+		if (!tree.hasNodeLabels())
+			label = null;
+		if (!tree.hasBranchLengths())
+			branchLength = null;
+		//tree.checkTaxaIDs(null);
+		oldNumTaxa = tree.oldNumTaxa;
+		taxaVersion = tree.taxaVersion;
+		sequenceNumber = tree.sequenceNumber;
+		nodeOfTaxon = new int[taxa.getNumTaxa()];
+		if (tree.getNumNodeSpaces()!=numNodeSpaces){
+			numNodeSpaces = tree.getNumNodeSpaces(); //extra in case bad taxa OR INTERNAL UNBRANCHED NODES
+			setNumberOfParts(numNodeSpaces);
+			flags = new boolean[numNodeSpaces];
+			firstDaughter= new int[numNodeSpaces];  
+			nextSister= new int[numNodeSpaces];  
+			mother= new int[numNodeSpaces];  
+			taxonNumber= new int[numNodeSpaces];  
+			parents = new int[numNodeSpaces][];
+			if (tree.hasNodeLabels())
+				label = new String[numNodeSpaces];
+			if (tree.hasBranchLengths())
+				branchLength = new double[numNodeSpaces];
+		}
+		else {
+			if (tree.hasNodeLabels() && label == null)
+				label = new String[numNodeSpaces];
+			if (tree.hasBranchLengths() && branchLength == null)
+				branchLength = new double[numNodeSpaces];
+			flags = new boolean[numNodeSpaces];
+
+		}
+
+		intializeTree();
+
+		for (int i=0; i<numNodeSpaces; i++){	
+			if (branchLength!=null && tree.branchLength!=null)
+				branchLength[i]=tree.branchLength[i];
+			firstDaughter[i]=tree.firstDaughter[i];
+			nextSister[i]=tree.nextSister[i];
+			mother[i]=tree.mother[i];
+			flags[i] = false;
+			setTaxonNumber(i, tree.taxonNumber[i]);
+			if (tree.parents[i]!=null) { //TODO: leave parents null until needed?
+				parents[i] = new int[tree.parents[i].length];
+				for (int j=0; j<tree.parents[i].length; j++)
+					parents[i][j]=tree.parents[i][j];
+			}
+			if (label!=null && tree.label!=null)
+				if (tree.label[i]!=null) 
+					label[i] = new String(tree.label[i]);
+		}
+		for (int i=0; i<nodeOfTaxon.length; i++)
+			nodeOfTaxon[i] = -1;
+		for (int i=0; i<taxa.getNumTaxa() && i < tree.nodeOfTaxon.length; i++)
+			nodeOfTaxon[i] = tree.nodeOfTaxon[i];
+		setAssociateds(tree);
+		setAttachments(tree);
+		if (tree.sensitiveAttachments!=null) {
+			if (sensitiveAttachments==null)
+				sensitiveAttachments = new Vector();
+			else
+				sensitiveAttachments.removeAllElements();
+			int s = tree.sensitiveAttachments.size();
+			for (int i=0; i<s; i++)
+				sensitiveAttachments.addElement(tree.sensitiveAttachments.elementAt(i));
+		}
+		else if (sensitiveAttachments!=null)
+			sensitiveAttachments.removeAllElements();
+
+		if (tree.anySelectedInClade(tree.getRoot())){
+			NameReference sN = makeAssociatedBits("selected"); //this won't make new Bits if not needed, just return reference
+			selected = getWhichAssociatedBits(sN);
+		}
+		else
+			selected = null;
+		checkAssociated();
+		setAnnotation(tree.getAnnotation(), false); 
+		root=tree.root;
+		subRoot=tree.subRoot;
+		//treeVector = tree.treeVector;
+		numNodeSpaces = tree.numNodeSpaces;
+		name = tree.name;
+		modifiedSinceNamed = tree.modifiedSinceNamed;
+		if (nameLock)
+			MesquiteMessage.printStackTrace("name changed in locked tree");
+		rooted = tree.rooted;
+		polytomiesHard = tree.polytomiesHard;
+		exists = true;
+	}
+	/*-----------------------------------------*/
+	/** Sets this tree to be a clone of that passed.*/
+	public void setToCloneFormOnly(Tree tree) {
+		if(!taxa.equals(tree.getTaxa(), false, true))
+			this.taxa = tree.getTaxa();
+		if (!tree.hasNodeLabels())
+			label = null;
+		if (!tree.hasBranchLengths())
+			branchLength = null;
+		nodeOfTaxon = new int[taxa.getNumTaxa()];
+		if (tree.getNumNodeSpaces()!=numNodeSpaces){
+			numNodeSpaces = tree.getNumNodeSpaces(); //extra in case bad taxa OR INTERNAL UNBRANCHED NODES
+			setNumberOfParts(numNodeSpaces);
+			firstDaughter= new int[numNodeSpaces];  
+			nextSister= new int[numNodeSpaces];  
+			mother= new int[numNodeSpaces];  
+			taxonNumber= new int[numNodeSpaces];  
+			flags = new boolean[numNodeSpaces];
+			parents = new int[numNodeSpaces][];
+			if (tree.hasBranchLengths())
+				branchLength = new double[numNodeSpaces];
+			if (tree.hasNodeLabels())
+				label = new String[numNodeSpaces];
+		}
+		else {
+			if (tree.hasBranchLengths() && branchLength == null)
+				branchLength = new double[numNodeSpaces];
+		}
+
+
+		intializeTree();
+
+		for (int i=0; i<numNodeSpaces; i++){	
+			if (branchLength!=null && tree.hasBranchLengths())
+				branchLength[i]=tree.getBranchLength(i);
+			flags[i] = false;
+			firstDaughter[i]=tree.firstDaughterOfNode(i);
+			nextSister[i]=tree.nextSisterOfNode(i);
+			mother[i]=tree.motherOfNode(i);
+			setTaxonNumber(i, tree.taxonNumberOfNode(i));
+		}
+		root=tree.getRoot();
+		subRoot=tree.getSubRoot();
+		//treeVector = tree.treeVector;
+		numNodeSpaces = tree.getNumNodeSpaces();
+		name = tree.getName();
+		rooted = tree.getRooted();
+		polytomiesHard = tree.getPolytomiesAssumption();
+		exists = true;
+	}
+	public boolean upToDateWithTaxa(){
+		if (getTaxa() == null)
+			return false;
+		if (getTaxa().getVersionNumber()==taxaVersion)
+			return true;
+		if (taxaIDs.length != taxa.getNumTaxa())
+			return false;
+		for (int i = 0; i<taxaIDs.length; i++)
+			if (taxa.getTaxon(i).getID() != taxaIDs[i])
+				return false;
+		taxaVersion = getTaxa().getVersionNumber();
+		return true;
+
+	}
+	public long getTaxaVersion(){
+		return taxaVersion;
+	}
+	/*----------------------------------------*/
+	private int recordMinTerms(Tree tree, int node, int[] minTerms){
+		if (tree.nodeIsTerminal(node)) {
+			minTerms[node]= tree.taxonNumberOfNode(node);
+		}
+		else{
+			int min = 999999999;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				int m = recordMinTerms(tree, d, minTerms);
+				if (m<min)
+					min = m;
+			}
+			minTerms[node] = min;
+		}
+		return minTerms[node] ;
+	}
+	private boolean coTraverse(Tree tree, int node, int[] minTerms, Tree tree2, int node2, int[] minTerms2, boolean checkBranchLengths){
+		if (checkBranchLengths && (tree.getBranchLength(node) != tree2.getBranchLength(node2)))
+			return false;
+		if (tree.nodeIsTerminal(node)){
+			if (!tree2.nodeIsTerminal(node2))
+				return false;
+			if (tree.taxonNumberOfNode(node) != tree2.taxonNumberOfNode(node2))
+				return false;
+			return true;
+		}
+		int numD = tree.numberOfDaughtersOfNode(node);
+		int numD2 = tree2.numberOfDaughtersOfNode(node2);
+		if (numD != numD2)
+			return false;
+
+		int currentMin = -1;
+		for (int i=0; i<numD; i++){  //going through daughters by order of min terminal
+			int dMin =0;
+			int dMin2 = 0;
+			int min = 9999999;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				int m = minTerms[d];
+				if (m<min && m > currentMin){
+					min = m;
+					dMin = d;
+				}
+			}
+			int min2 = 9999999;
+			for (int d = tree2.firstDaughterOfNode(node2); tree2.nodeExists(d); d = tree2.nextSisterOfNode(d)) {
+				int m = minTerms2[d];
+				if (m<min2 && m > currentMin){
+					min2 = m;
+					dMin2 = d;
+				}
+			}
+			if (min != min2)
+				return false;
+			if (!coTraverse(tree, dMin, minTerms, tree2, dMin2, minTerms2, checkBranchLengths))
+				return false;
+			currentMin = min;
+		}
+		return true;
+	}
+
+	/** Returns true if trees have same topology. */
+	public boolean equalsTopology(Tree tree, boolean checkBranchLengths){
+		if (tree==null)
+			return false;
+		int[] minTermsThis = new int[getNumNodeSpaces()];
+		int[] minTermsOther = new int[tree.getNumNodeSpaces()];
+		recordMinTerms(this, getRoot(), minTermsThis);
+		recordMinTerms(tree, tree.getRoot(), minTermsOther);
+		return coTraverse(this, getRoot(), minTermsThis, tree, tree.getRoot(), minTermsOther, checkBranchLengths);
+	}
+	/*----------------------------------------*/
+	/** Returns true if passed tree has same core array storage (same root, mothers, firstDaughter, nextSister, taxonNumber). */
+	public boolean equalsCoreArrays(MesquiteTree tree){
+		if (tree ==null || taxa != tree.taxa || numNodeSpaces!=tree.numNodeSpaces || root != tree.root)
+			return false;
+		if ((parents==null) != (tree.parents == null))
+			return false;
+		if (parents != null ){
+			if (parents.length != tree.parents.length)
+				return false;
+			if (parents.length !=0 && parents[0]!=null && tree.parents[0] !=null) {
+				if (parents[0].length!= tree.parents[0].length)
+					return false;
+			}
+		}
+		for (int i=0; i< numNodeSpaces; i++){
+			if (firstDaughter[i] != tree.firstDaughter[i])
+				return false;  
+			if (nextSister[i] != tree.nextSister[i])
+				return false;  
+			if (mother[i] != tree.mother[i])
+				return false;  
+			if (taxonNumber[i] != tree.taxonNumber[i])
+				return false;  
+			if (parents != null && parents.length !=0  && parents[i] !=null && tree.parents[i] !=null) {
+				for (int j=0; j<parents[i].length; j++)
+					if (parents[i][j] != tree.parents[i][j])
+						return false;
+			}
+		}
+		return true;
+	}
+	/** Returns true if passed tree has same core array storage (same root, mothers, firstDaughter, nextSister, taxonNumber). */
+	public boolean equalsCoreArraysPlusBranchLengths(MesquiteTree tree){
+		if (!equalsCoreArrays(tree))
+			return false;
+		if (tree ==null || taxa != tree.taxa || numNodeSpaces!=tree.numNodeSpaces || root != tree.root)
+			return false;
+		if ((branchLength==null) != (tree.branchLength == null))
+			return false;
+		if (branchLength == null)
+			return true;
+		for (int i=0; i< numNodeSpaces; i++){
+			if (branchLength[i] != tree.branchLength[i])
+				return false;  
+		}
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Returns the base numNodeSpaces used for a tree of numTaxa taxa; a convenient starting point for modules that need to allocate space
+	for storage for nodes but which don't yet have a tree in hand. */
+	public static int standardNumNodeSpaces(int numTaxa){
+		return numTaxa*3+5;
+	}
+	/*-----------------------------------------*/
+	/** Returns the base numNodeSpaces used for a tree for the passed taxa; a convenient starting point for modules that need to allocate space
+	for storage for nodes but which don't yet have a tree in hand. */
+	public static int standardNumNodeSpaces(Taxa taxa){
+		if (taxa==null)
+			return 0;
+		else
+			return taxa.getNumTaxa()*3+5;
+	}
+	/*-----------------------------------------*/
+	/** Resets the number of node spaces to that passed.  arrays are expanded or shrunk as needed. */
+	private void setNumNodeSpaces(int newNumNodeSpaces){
+		if (newNumNodeSpaces==numNodeSpaces)
+			return;
+		int[] newFirstDaughter= new int[newNumNodeSpaces];  
+		int[] newNextSister= new int[newNumNodeSpaces];  
+		int[] newMother= new int[newNumNodeSpaces];  
+		int[] newTaxonNumber= new int[newNumNodeSpaces];  
+		int[][] newParents = new int[newNumNodeSpaces][];
+		boolean[] newFlags = new boolean[newNumNodeSpaces];
+		for (int i=0; i<numNodeSpaces && i<newNumNodeSpaces; i++) {
+			newFlags[i] = flags[i];
+			newFirstDaughter[i]=firstDaughter[i];
+			newNextSister[i]=nextSister[i];
+			newMother[i]=mother[i];
+			newTaxonNumber[i] = taxonNumber[i]; //nodeOfTaxon should remain unchanged
+			newParents[i] = parents[i]; 
+		}
+		for (int i=numNodeSpaces; i<newNumNodeSpaces; i++) {
+			newFlags[i] = false;
+			newFirstDaughter[i]=0;
+			newNextSister[i]=0;
+			newMother[i]=0;
+			newTaxonNumber[i] = -1; //nodeOfTaxon should remain unchanged
+			newParents[i] = null; 
+		}
+		firstDaughter = newFirstDaughter;
+		nextSister = newNextSister;
+		mother = newMother ;
+		taxonNumber = newTaxonNumber;
+		parents=newParents;
+		flags = newFlags;
+		if (branchLength!=null) {
+			double[] newBranchLength = new double[newNumNodeSpaces];
+			for (int i=0; i<numNodeSpaces && i<newNumNodeSpaces; i++)
+				newBranchLength[i] = branchLength[i];
+			for (int i=numNodeSpaces; i<newNumNodeSpaces; i++) 
+				newBranchLength[i] = MesquiteDouble.unassigned;
+			branchLength = newBranchLength;
+		}
+		if (label!=null) {
+			String[] newLabel = new String[newNumNodeSpaces];
+			for (int i=0; i<numNodeSpaces && i<newNumNodeSpaces; i++)
+				newLabel[i] = label[i];
+			label = newLabel;
+		}
+
+
+		numNodeSpaces = newNumNodeSpaces;
+		resetNodeOfTaxonNumbers();
+		setNumberOfParts(numNodeSpaces);
+	}
+	/*-----------------------------------------*/
+	/**Returns the unique id number of this tree*/
+	public long getID(){
+		return id;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether the tree has a name.*/
+	public boolean hasName() {
+		return (name!=null);
+	}
+	/*-----------------------------------------*/
+	/** Returns the name of the tree, or "Untitled" if no name has been set.*/
+	public String getName() {
+		if (name==null)
+			return "Untitled Tree";
+		if (modifiedSinceNamed)
+			return name + '+';
+		return name;
+	}
+	/*-----------------------------------------*/
+	/** Sets the name of the tree.*/
+	public void setName(String name) {
+		if (nameLock)
+			MesquiteMessage.printStackTrace("Error: locked name in tree changed");
+		else {
+			this.name = name;
+			modifiedSinceNamed = false;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Sets whether name is locked*/
+	public void setNameLock(boolean lock) {
+		nameLock = lock;
+	}
+	/*-----------------------------------------*/
+	/** Returns topology version number of tree.  Version number should be incremented with each change in topology.*/
+	public long getTopologyVersion(){
+		return topologyVersion;
+	}
+	/*-----------------------------------------*/
+	/** Returns branch lengths version number of tree.  Version number should be incremented with each change in branch lengths.*/
+	public long getBranchLengthsVersion(){
+		return branchLengthsVersion;
+	}
+	/*-----------------------------------------*/
+	/** Used to keep track of version numbers of tree.  Each time tree is changed, call this.  Also removes sensitive attachments. */
+	private void incrementVersion(int code, boolean notify){
+		versionNumber++;
+		if (code == BRANCHES_REARRANGED) {
+			topologyVersion++;
+			branchLengthsVersion++;
+		}
+		if (code == BRANCHLENGTHS_CHANGED)
+			branchLengthsVersion++;
+		if (sensitiveAttachments!=null)
+			sensitiveAttachments.removeAllElements();
+		modifiedSinceNamed = true; 
+		setDirty(true);
+		if (nameLock)
+			MesquiteMessage.printStackTrace("Error: locked name in tree changed 2");
+		if (notify)
+			notifyListeners(this, new Notification (code));
+
+	}
+	/*-----------------------------------------*/
+	/* Returns whether tree is the same id, topology, branch lengths and or full version */
+	public boolean sameTreeVersions(TreeReference tr, boolean checkBranchLengths, boolean exact){
+		if (tr==null)
+			return false;
+		if (tr.getID() != getID())
+			return false;
+		if (tr.getTopologyVersion() != getTopologyVersion())
+			return false;
+		if (checkBranchLengths && (tr.getBranchLengthsVersion() != getBranchLengthsVersion()))
+			return false;
+		if (exact && (tr.getVersionNumber() != getVersionNumber()))
+			return false;
+		return true;
+	}
+	/*-----------------------------------------*/
+	/* Returns whether tree is the same id, topology, branch lengths and or full version */
+	public boolean sameTreeVersions(MesquiteTree tr, boolean checkBranchLengths, boolean exact){
+		if (tr==null)
+			return false;
+		if (tr.getID() != getID())
+			return false;
+		if (tr.getTopologyVersion() != getTopologyVersion())
+			return false;
+		if (checkBranchLengths && (tr.getBranchLengthsVersion() != getBranchLengthsVersion()))
+			return false;
+		if (exact && (tr.getVersionNumber() != getVersionNumber()))
+			return false;
+		return true;
+	}
+	/*-----------------------------------------*/
+	/* Returns whether tree is the same id, topology, branch lengths and or full version */
+	public TreeReference getTreeReference(TreeReference tr){
+		if (tr==null)
+			tr = new TreeReference();
+		tr.setID(getID());
+		tr.setTopologyVersion(getTopologyVersion());
+		tr.setBranchLengthsVersion(getBranchLengthsVersion());
+		tr.setVersionNumber(getVersionNumber());
+		return tr;
+	}
+	/*-----------------------------------------*
+ 	public boolean equals(Object obj){
+ 		if (!(obj instanceof MesquiteTree))
+ 			return false;
+ 		MesquiteTree tree = (MesquiteTree)obj;
+ 		return equalsCoreArraysPlusBranchLengths(tree);
+ 	}
+	/*-----------------------------------------*/
+	/** Returns the Taxa to which the tree refers.*/
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	/*-----------------------------------------*/
+	/** returns true if object is set of taxa on which tree is based.  For CompatibilityChecker interface*/
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj instanceof Taxa) {
+			if (obj != taxa && report != null)
+				report.setValue("tree applies to a different block of taxa.");
+			return (obj == taxa);
+		}
+		return true;
+	}
+	/** Returns whether module is compatible with given object*/
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+	/*-----------------------------------------*/
+	boolean inProgressAddingTaxa = false;
+	public boolean isEmpty(){
+		if (inProgressAddingTaxa)
+			return false;
+		if (!isDefined())
+			return true;
+		if (!inBounds(getRoot()))
+			return true;
+		if (nodeIsTerminal(getRoot()))
+			return true;
+		if (numberOfTerminalsInClade(getRoot())<1)
+			return true;
+		if (numberOfDaughtersOfNode(getRoot())<1)
+			return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns number of terminal taxa in clade.*/
+	public  int numberOfNegativeTerminalsInClade(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node) && taxonNumberOfNode(node)<0)
+			return 1; //count node itself
+		else{
+			int count = 0;
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				count += numberOfNegativeTerminalsInClade(d);
+			return count;
+		}
+	}
+	/*-----------------------------------------*/
+	public boolean isValid(){
+		return !isEmpty() && (numberOfNegativeTerminalsInClade(getRoot())<=0);
+	}
+	/*-----------------------------------------*/
+	public boolean isDefined(){
+		return exists;
+	}
+	/*-----------------------------------------*/
+	public void setAsDefined(boolean defined){
+		exists = defined;
+	}
+	/*-----------------------------------------*/
+	/** Returns false if tree is null, has no nodes, or is locked.*/
+	public static boolean OK(Tree tree) {
+		if (tree==null)
+			return false;
+		else if ((tree.isDefined()) && (!tree.isLocked())) {
+			return true;
+		}
+		else 
+			return false;
+	}
+	/*-----------------------------------------*/
+	/** Sets the  tree vector to which the tree belongs.*/
+	public void setTreeVector(TreeVector treeVector) {
+		this.treeVector = treeVector;
+	}
+	/*-----------------------------------------*/
+	/** Gets the  tree vector to which the tree belongs.*/
+	public TreeVector getTreeVector() {
+		return treeVector;
+	}
+	/*-----------------------------------------*/
+	/** Disconnects listeners */
+	public void dispose(){
+		/*if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+	 				listener.disposing(this);
+
+				}
+			listeners.removeAllElements();
+			listenersRemaining=0;
+			listeners = null;
+		}
+		 */
+		if (taxa!=null)
+			taxa.removeListener(this);
+		removeAllListeners();
+		totalDisposed++;
+
+	}
+
+	public void finalize() throws Throwable {
+		//	if (taxa!=null)
+		//		taxa.removeListener(this);
+		totalFinalized++;
+		super.finalize();
+	}
+	/*-----------------------------------------*/
+	/** For Commandable interface; currently responds to set branch length messages and tree description writing */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Sets all branch lengths of the tree", "[length]", commandName, "setAllBranchLengths")) {
+			double bL = MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(bL)|| MesquiteDouble.isUnassigned(bL)){
+				setAllBranchLengths(bL, true);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets branch lengths of all branches with unassigned lengths of the tree", "[length]", commandName, "setAllUnassignedBranchLengths")) {
+			double bL = MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(bL)|| MesquiteDouble.isUnassigned(bL)) {
+				for (int i=0; i<numNodeSpaces; i++)
+					if (nodeExists(i)) {
+						double d = getBranchLength(i);
+						if (MesquiteDouble.isUnassigned(d))
+							setBranchLength(i, bL, false);
+					}
+				incrementVersion(BRANCHLENGTHS_CHANGED, true);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Multiplies all branch lengths of the tree by a factor", "[factor]", commandName, "scaleAllBranchLengths")) {
+			double bL = MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(bL)|| MesquiteDouble.isUnassigned(bL)) {
+				for (int i=0; i<numNodeSpaces; i++)
+					if (nodeExists(i)) {
+						double d = getBranchLength(i);
+						if (MesquiteDouble.isCombinable(d))
+							setBranchLength(i, d*bL, false);
+						//else if (MesquiteDouble.isUnassigned(d))
+						//	setBranchLength(i, bL, false);   // as it was unassigned, presume 1 before scale
+					}
+				incrementVersion(BRANCHLENGTHS_CHANGED, true);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Multiplies lengths of all selected branches by a factor", "[factor]", commandName, "scaleLengthSelectedBranches")) {
+			double bL = MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(bL)|| MesquiteDouble.isUnassigned(bL)) {
+				for (int i=0; i<numNodeSpaces; i++)
+					if (nodeExists(i) && getSelected(i)) {
+						double d = getBranchLength(i);
+						if (MesquiteDouble.isCombinable(d))
+							setBranchLength(i, d*bL, false);
+					}
+				incrementVersion(BRANCHLENGTHS_CHANGED, true);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets lengths of all selected branches", "[length]", commandName, "setLengthSelectedBranches")) {
+			double bL = MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(bL) || MesquiteDouble.isUnassigned(bL)) {
+				for (int i=0; i<numNodeSpaces; i++)
+					if (nodeExists(i) && getSelected(i))
+						setBranchLength(i, bL, false);
+				incrementVersion(BRANCHLENGTHS_CHANGED, true);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Set length of indicated branch", "[length][node number]", commandName, "setBranchLength")) {
+			pos.setValue(0);
+			double L = MesquiteDouble.fromString(arguments, pos);
+			int node = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteDouble.isCombinable(L) && MesquiteInteger.isCombinable(node) && nodeExists(node)) {
+				setBranchLength(node, L, false);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Set label of indicated branch", "[label][node number]", commandName, "setBranchLabel")) {
+			String name = ParseUtil.getFirstToken(arguments, pos);
+			int node = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(node) && nodeExists(node)) {
+				setNodeLabel(name, node);
+				return MesquiteBoolean.TRUE;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Gets node number that corresponds to a taxon", "[taxon]", commandName, "getNodeOfTaxonNumber")) {
+			pos.setValue(0);
+			int tax1 = MesquiteInteger.fromString(arguments, pos);
+
+			if (MesquiteInteger.isCombinable(tax1)) {
+				int node1 = nodeOfTaxonNumber(tax1);
+				return new MesquiteInteger(node1);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Gets node number that is MRCA of two taxa", "[taxon1][taxon2]", commandName, "getMRCAofTaxa")) {
+			pos.setValue(0);
+			int tax1 = MesquiteInteger.fromString(arguments, pos);
+			int tax2 = MesquiteInteger.fromString(arguments, pos);
+
+			if (MesquiteInteger.isCombinable(tax1) && MesquiteInteger.isCombinable(tax2)) {
+				int node1 = nodeOfTaxonNumber(tax1);
+				int node2 = nodeOfTaxonNumber(tax2);
+
+				return new MesquiteInteger(mrca(node1, node2));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets all branch lengths of the tree to unassigned", null, commandName, "deassignAllBranchLengths")) {
+			for (int i=0; i<numNodeSpaces; i++)
+				if (nodeExists(i))
+					setBranchLength(i, MesquiteDouble.unassigned, false);
+			incrementVersion(BRANCHLENGTHS_CHANGED, true);
+		}
+		else if (checker.compare(this.getClass(), "Sets lengths of selected branches to unassigned", null, commandName, "deassignLengthSelectedBranches")) {
+			for (int i=0; i<numNodeSpaces; i++)
+				if (nodeExists(i) && getSelected(i))
+					setBranchLength(i, MesquiteDouble.unassigned, false);
+			incrementVersion(BRANCHLENGTHS_CHANGED, true);
+		}
+		else if (checker.compare(this.getClass(), "Writes the tree as a string to the log window", null, commandName, "writeTree")) {
+			MesquiteTrunk.mesquiteTrunk.logln("Tree \"" + getName() + "\"    " + writeTree(BY_NAMES));
+		}
+		else if (checker.compare(this.getClass(), "Returns a string description of the tree (with taxa indicated by their numbers)", null, commandName, "getDescriptionByNumbers")) {
+			return writeTree(BY_NUMBERS);
+		}
+		else if (checker.compare(this.getClass(), "Returns a string description of the tree (with taxa indicated by their names)", null, commandName, "getDescriptionByNames")) {
+			return writeTree(BY_NAMES);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*-----------------------------------------*/
+	/*.......................................basic node utilities.............................................*/
+	/*-----------------------------------------*/
+	/** Returns the root of the tree (i.e., the most recent common ancestor of the terminal taxa in the tree.*/
+	public int getRoot() {
+		return root;
+	}
+	/*-----------------------------------------*/
+	/** Returns the subRoot of the tree (the mother of the most recent common ancestral node of the tree).  
+	The subroot exists so that some traversals (including for drawing the root branch)
+	don't choke when they come to the root and look for an ancestor.*/
+	public int getSubRoot() {
+		return subRoot;
+	}
+	/*-----------------------------------------*/
+	/** Sets whether tree is rooted.*/
+	public void setRooted(boolean rooted, boolean notify) {
+		if (rooted != this.rooted) {
+			this.rooted = rooted;
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED, notify);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns whether tree is rooted.*/
+	public boolean getRooted() {
+		return rooted;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether root is real.  It isn't real if the tree is unrooted.*/
+	public boolean rootIsReal() {
+		return rooted;
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of terminal taxa in the Taxa to which the tree refers.  This is not necessarily the 
+	number of terminal taxa in the tree itself (for that, call numberOfTerminalsInClade(root)).*/
+	public int getNumTaxa() {
+		return taxa.getNumTaxa();
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of node spaces available in storage arrays within tree object.*/
+	public int getNumNodeSpaces() {
+		return numNodeSpaces;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if N is a valid node designation in tree.*/
+	public  boolean nodeExists(int node) {
+		return inBounds(node); 
+	}
+	//TODO: nodeExists should be renamed nodeInRange and most occurences in program should use it; should be separate nodeInTree (see below)
+	/** Overriding method of Associable.*/
+	protected boolean inBounds(int node) {
+		return ((node>0)&&(node<numNodeSpaces)); 
+	}
+	/*-----------------------------------------*/
+	/** Returns true if node is an internal node.*/
+	public  boolean nodeIsInternal(int node) {
+		if (!inBounds(node))
+			return false;
+		return (firstDaughter[node]!=0); }
+	/*-----------------------------------------*/
+	/** Returns true if node is a terminal node.*/
+	public  boolean nodeIsTerminal(int node) {
+		if (!inBounds(node))
+			return false;
+		return (firstDaughter[node]==0); }
+	/*-----------------------------------------*/
+	/** Returns the taxon number of the node.  This is -1 if the node is internal,
+	the taxon number if terminal.*/
+	public  int taxonNumberOfNode(int node) {  //todo: should only return if actually in tree!!!!!!
+		if (!inBounds(node))
+			return -1;
+		return taxonNumber[node]; }
+	/*-----------------------------------------*/
+	private void flagNodesInTree(int node){
+		flags[node] = true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d) && !nodeWasFound; d = nextSisterOfNode(d))
+			flagNodesInTree(d);
+	}
+	/*-----------------------------------------*/
+	private void zeroUnflaggedNodes(int node){
+		if (!flags[node]){
+			firstDaughter[node]=0;
+			nextSister[node]=0;
+			mother[node]=0;
+			taxonNumber[node] = -1; 
+			parents[node] = null; 
+		}
+		for (int d = firstDaughterOfNode(node); nodeExists(d) && !nodeWasFound; d = nextSisterOfNode(d))
+			zeroUnflaggedNodes(d);
+	}
+	/*-----------------------------------------*/
+	/** Refills the nodeOfTaxon array. Also cleans up node spaces that used to have nodes in them.*/
+	private void resetNodeOfTaxonNumbers() {
+		if (nodeOfTaxon == null || taxa.getNumTaxa() != nodeOfTaxon.length){
+			nodeOfTaxon = new int[taxa.getNumTaxa()];
+		}
+		for (int i=1; i<nodeOfTaxon.length; i++)// Nov 2013 initialize
+			nodeOfTaxon[i] = -1;
+
+		for (int i=1; i<flags.length; i++)// Sept 2014
+			flags[i] = false;
+		flagNodesInTree(getRoot());
+		zeroUnflaggedNodes(getRoot());
+		for (int i=1; i<flags.length; i++)// Sept 2014
+			flags[i] = false;
+
+		for (int i=1; i<numNodeSpaces; i++)
+			if (taxonNumber[i]>=0 && taxonNumber[i]<taxa.getNumTaxa() ){  // Nov 2013 check if in tree
+				nodeOfTaxon[taxonNumber[i]] = i;
+			}
+	}
+	/*-----------------------------------------*/
+	/** Returns the terminal node corresponding to the given taxon number; 0 if the taxon  is not part of the tree.*/
+	public int nodeOfTaxonNumber(int taxonNum) {
+		if (taxonNum<0)
+			return 0;
+		if (taxonNum < nodeOfTaxon.length){
+			int n = nodeOfTaxon[taxonNum];
+			if (n >=0 && n< taxonNumber.length && taxonNumber[n] == taxonNum)
+				return n;
+		}
+
+		for (int i=1; i<numNodeSpaces; i++)
+			if (taxonNumber[i]==taxonNum && nodeInTree(i)){  //todo: should only return if actually in tree!!!!!!
+				/*if (taxonNum> nodeOfTaxon.length)
+					---("    Temporary debugging code in MesquiteTree (nodeOfTaxonNumber) " + taxonNum + " i  " + i + " taxonNum too large for nodeOfTaxon array; length: " + nodeOfTaxon.length); 
+
+				else
+					---("    Temporary debugging code in MesquiteTree (nodeOfTaxonNumber) " + taxonNum + " i  " + i + " nodeOfTaxon[taxonNum] " + nodeOfTaxon[taxonNum]); 
+				 */
+				return i;
+			}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Sets the taxon number for the node.  If the node is internal, the number should
+	be set to -1.  Otherwise it should be set to the taxon corresponding to the node.
+	NOTE: this should be used with caution, since it doesn't check for tree integrity.  Intended primarily
+	for internal use (with MesquiteTree).*/
+	public void setTaxonNumber(int node, int num, boolean notify) { 
+		if (!inBounds(node))
+			return;
+		setTaxonNumber(node, num); 
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Returns the immediate ancestor of node (mother) if node is non-reticulate.
+	If node is reticulate, returns the first (primary) parent.*/
+	public  int motherOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		return mother[node]; }
+	/*-----------------------------------------*/
+	/** Returns the node's mother's mother.*/
+	public  int grandmotherOfNode(int node) {
+		return motherOfNode(motherOfNode(node)); 
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of parents of node.*/
+	public int numberOfParentsOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (parents[node] == null)
+			return 1;
+		else
+			return parents[node].length;
+	}
+	/*-----------------------------------------*/
+	/** Returns the indexTH parent of node.*/
+	public int parentOfNode(int node, int index) {
+		if (!inBounds(node))
+			return 0;
+		if (parents[node] == null && index ==1) {
+			return motherOfNode(node);
+		}
+		else if (index <= parents[node].length) {
+			return parents[node][index - 1];
+		}	
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the array of parents of node.  If node is not reticulate, the array returned contains
+	only the mother node.*/
+	public int[] parentsOfNode(int node) {
+		if (!inBounds(node))
+			return null;
+		if (parents[node] == null) {
+			int[] anc = new int[1];
+			anc[0] = motherOfNode(node);
+			return anc;
+		}
+		else {
+			int[] anc = new int[parents[node].length];
+			for (int i=0; i<parents[node].length; i++)
+				anc[i] = parents[node][i];
+			return anc;
+		}	
+	}
+	/*-----------------------------------------*/
+	/** An indelicate quick way to delete all reticulations from a node. Added 4 Feb 02*/
+	public void snipReticulations(int node){
+		if (!inBounds(node))
+			return;
+		parents[node] = null;
+	}
+	/*-----------------------------------------*/
+	/** Sets par to be an additional parent of node.  Used to make reticulations.  Currently there
+	is no way to subtract parents individually, nor to rearrange trees that contain reticulations.*/
+	public void setParentOfNode(int node, int par, boolean notify) {
+		if (!inBounds(node))
+			return;
+		int numParents;
+		if (parents[node] == null)
+			numParents=1;
+		else
+			numParents = parents[node].length+1;
+		int[] newParents = new int[numParents];
+		for (int i=0; i<numParents; i++) {
+			if (parents[node] == null || i>= parents[node].length)
+				newParents[i] = 0;
+			else
+				newParents[i]=parents[node][i];
+		}
+		newParents[numParents-1] = par;
+		parents[node] = newParents;
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Returns true iff first branch is a descendant of second branch.*/
+	public boolean descendantOf(int branchD, int branchA) { 
+		if (branchD == branchA)
+			return false;
+		else if (!nodeExists(branchD)|!nodeExists(branchA))
+			return false;
+		else {
+			int b = branchD;
+			while (b!=subRoot && nodeExists(b)) {
+				b = motherOfNode(b);
+				if (b==branchA)
+					return true;
+			}
+			return false;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns depth of second branch below first; -1 if not ancestral.*/
+	public int depthToAncestor(int branchD, int branchA) { 
+		if (branchD == branchA)
+			return 0;
+		else if (!nodeExists(branchD)|!nodeExists(branchA))
+			return -1;
+		else {
+			int b = branchD;
+			int depth = 0;
+			while (b!=subRoot && nodeExists(b)) {
+				depth++;
+				b = motherOfNode(b);
+				if (b==branchA)
+					return depth;
+			}
+			return -1;
+		}
+	}
+
+	/*-----------------------------------------*/
+	/** Returns the deepest path in a clade, in terms of numbers of nodes*/
+	public int deepestPath( int node) { 
+		int deepest = 0;
+		for (int it = 0; it< getTaxa().getNumTaxa(); it++){
+			if (taxonInTree(it)){  // taxon in tree (ideally do taxon in clade)
+				int current = depthToAncestor(nodeOfTaxonNumber(it),node); 
+				if (current>deepest)
+					deepest = current;
+			}
+		}
+		return deepest;
+	}
+
+	/*-----------------------------------------*/
+	/** Traversal in which nodes are ignored as illegal.
+	 * Codes for nodes:
+	 * ILLEGAL if illegal and nothing in subclade is legal; 
+	 * SEMILEGAL: node itself is illegal but subclade includes legal one;
+     * LEGAL if legal (i.e. either more than one descendant is legal, or this is a legal terminal
+	 * The permits tree traversal where illegal lineages are ignored as if they aren't there
+	 * */
+	public static final int ILLEGAL = 2;
+	public static final int SEMILEGAL = 1;
+	public static final int LEGAL = 0;
+	/*-----------------------------------------*/
+	/** Returns the first (left-most) legal daughter of node, where legality is implied by integer array with values 
+	 * */
+	public  int firstLegalDaughterOfNode(int node, int[] legality) {
+		if (legality == null || node>=legality.length)
+			return firstDaughterOfNode(node);
+		if (!inBounds(node))
+			return 0;
+		for (int candidate = firstDaughterOfNode(node); nodeExists(candidate); candidate= nextSisterOfNode(candidate)){
+			if (candidate>=legality.length)
+				return candidate;
+			if (legality[candidate] == LEGAL) //candidate itself is legal; return it
+				return candidate;
+			if (legality[candidate] == SEMILEGAL) //candidate itself is illegal, but its subclade contains something legal
+				return firstLegalDaughterOfNode(candidate, legality);
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the next legal sister of node, where legality is implied by integer array with values 
+	 * */
+	public  int nextLegalSisterOfNode(int node, int[] legality) {
+		if (legality == null || node>=legality.length)
+			return nextSisterOfNode(node);
+		if (!inBounds(node))
+			return 0;
+
+		//check through sisters until find one legal
+		for (int candidate = nextSisterOfNode(node); nodeExists(candidate); candidate= nextSisterOfNode(candidate)){
+			if (candidate>=legality.length)
+				return candidate;
+			if (legality[candidate] == LEGAL) //candidate itself is legal; return it
+				return candidate;
+			if (legality[candidate] == SEMILEGAL) //candidate itself is illegal, but its subclade contains something legal
+				return firstLegalDaughterOfNode(candidate, legality);
+		}
+		int mom = motherOfNode(node);  //if this is legal, then you've gone as far as you need to go; next sister not found
+		if (!nodeExists(mom) || mom>=legality.length || legality[mom] == LEGAL)
+			return 0;
+		
+		//all sisters next are entirely illegal; go down to mother and the next aunt
+		for (int ancestor = motherOfNode(node); nodeExists(ancestor); ancestor= motherOfNode(ancestor)){
+			
+			//look to all this ancestor's sisters
+			for (int candidate = nextSisterOfNode(ancestor); nodeExists(candidate); candidate= nextSisterOfNode(candidate)){
+				if (candidate>=legality.length)
+					return candidate;
+				if (legality[candidate] == LEGAL) //candidate itself is legal; return it
+					return candidate;
+				if (legality[candidate] == SEMILEGAL) //candidate itself is illegal, but its subclade contains something legal
+					return firstLegalDaughterOfNode(candidate, legality);
+			}
+			// have looked to ancestor's sisters, and not found.  The next ancestor deeper is legal, then you're done.
+			int ancAnc = motherOfNode(ancestor);  
+			
+			if (!nodeExists(ancAnc) || ancAnc>=legality.length || legality[ancAnc] == LEGAL)//if this is ancestor legal, then you've gone as far as you need to go; next sister not found
+				return 0;
+			
+		}
+		
+		//nothing found!!!	
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the right-most daughter of node.*/
+	public int lastLegalDaughterOfNode(int node, int[] legality) {
+		if (!inBounds(node))
+			return 0;
+
+		int thisSister = firstLegalDaughterOfNode(node, legality);
+		while (nodeExists(nextLegalSisterOfNode(thisSister, legality)))
+			thisSister = nextLegalSisterOfNode(thisSister, legality);
+		return thisSister;
+	}
+	/*-----------------------------------------*/
+	/** Returns the first (left-most) daughter of node.*/
+	public  int firstDaughterOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		return firstDaughter[node]; }
+	/*-----------------------------------------*/
+	/** Returns the right-most daughter of node.*/
+	public int lastDaughterOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+
+		int thisSister = firstDaughterOfNode(node);
+		while (nodeExists(nextSisterOfNode(thisSister)))
+			thisSister = nextSisterOfNode(thisSister);
+		return thisSister;
+	}
+	/*-----------------------------------------*/
+	/** Returns the array of daughters of a node.  Normally it will be best to cycle through the
+	daughters as shown in the recursion example in the documentation for the Tree class.*/
+	public int[] daughtersOfNode(int node) {
+		if (!inBounds(node))
+			return null;
+		int thisSister = firstDaughterOfNode(node);
+		int count = 0;
+		while (nodeExists(thisSister)) {
+			count ++;
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		int[] desc = new int[count];
+		count=0;
+		thisSister = firstDaughterOfNode(node);
+		while (nodeExists(thisSister)) {
+			desc[count] = thisSister;
+			count ++;
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		return desc;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if branchD is an immediate daughter of branchA */
+	public boolean daughterOf(int branchD, int branchA) { 
+		if (branchD == branchA)
+			return false;
+		else if (!nodeExists(branchD)|!nodeExists(branchA))
+			return false;
+		else if (nodeIsInternal(branchA)) {
+			int thisSister = firstDaughterOfNode(branchA);
+			while (nodeExists(thisSister)) {
+				if (thisSister==branchD)
+					return true;
+				thisSister = nextSisterOfNode(thisSister);
+			}
+			return false;
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if node is the first (leftmost) daughter of its mother.*/
+	public boolean nodeIsFirstDaughter(int node) {
+		if (!inBounds(node))
+			return false;
+		if (firstDaughterOfNode(motherOfNode(node))==node) 
+			return true;
+		else
+			return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns the index of the node among its sisters (i.e., if it is daughter number 0 of
+	its mother, 1, 2, etc. (zero based).*/
+	public int whichDaughter(int node) {
+		if (!nodeExists(node) || !nodeExists(motherOfNode(node)))
+			return -1;
+		int m = motherOfNode(node);
+
+
+		int thisSister = firstDaughterOfNode(m);
+		if (thisSister==node)
+			return 0;
+		int count =0;
+		while (thisSister!=node && nodeExists(thisSister)) {
+			thisSister = nextSisterOfNode(thisSister);
+			count++;
+		}
+		if (count==0)
+			return -1;
+		return count;
+	}
+	/*-----------------------------------------*/
+	/** Returns the indexTH daughter of node (zero based).*/
+	public int indexedDaughterOfNode(int node, int index) {
+		if (!inBounds(node))
+			return 0;
+		int thisSister = firstDaughterOfNode(node);
+		int count = 0;
+		while (nodeExists(thisSister)) {
+			if (count == index)
+				return thisSister;
+			count ++;
+
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of daughters of the node.*/
+	public int numberOfDaughtersOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		int thisSister = firstDaughterOfNode(node);
+		int count = 0;
+		while (nodeExists(thisSister)) {
+			count ++;
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		return count;
+	}
+	/*-----------------------------------------*/
+	/** Returns if branchD is descendant of branchA, then which daughter of branchA does it descend from?
+		Returns 0 if not descendant.*/
+	public int whichDaughterDescendantOf(int branchD, int branchA) { 
+		if (branchD == branchA)
+			return 0;
+		else if (!nodeExists(branchD)|!nodeExists(branchA))
+			return 0;
+		else {
+			int lastB;
+			int b = branchD;
+			while (b!=subRoot) {
+				lastB = b;
+				b = motherOfNode(b);
+				if (b==branchA)
+					return lastB;
+			}
+			return 0;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns the node's sister immediately to the right.  If the node has no
+	sister to the right, returns 0 (which is not a valid node designation).*/
+	public  int nextSisterOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		return nextSister[node]; }
+	/*-----------------------------------------*/
+	/** Returns the node's sister immediately to the left.  If the node has no 
+	sister to the right, returns 0 (which is not a valid node designation).*/
+	public int previousSisterOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		int thisSister = firstDaughterOfNode(motherOfNode(node));
+		if (node==thisSister)
+			return 0;
+		int lastSister;
+		while (nodeExists(thisSister)) {
+			lastSister=thisSister;
+			thisSister = nextSisterOfNode(thisSister);
+			if (thisSister==node)
+				return lastSister;
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if branch1 and branch2 are sisters by their mother (i.e., primary parent).
+	There is currently no method to return whether two nodes share at least one parent.*/
+	public  boolean nodesAreSisters(int branch1, int branch2) { 
+		if (branch1 == branch2)
+			return false;
+		else if (branch1== root || branch2 == root)
+			return false;
+		else if (!nodeExists(branch1)|!nodeExists(branch2))
+			return false;
+		else 
+			return (motherOfNode(branch1)==motherOfNode(branch2));
+	}
+	/*-----------------------------------------*/
+	/** Returns whether clade has nodes with more than one parent.*/
+	private  boolean hasReticulations(int node) {
+		if (!inBounds(node))
+			return false;
+		if (numberOfParentsOfNode(node)>1) 
+			return true;
+		if (nodeIsTerminal(node))
+			return false;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			if (hasReticulations(d))
+				return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether tree has nodes with more than one parent.*/
+	public  boolean hasReticulations() {
+		return hasReticulations(getRoot());
+	}
+
+	/*-----------------------------------------*/
+	/** Deletes any unbranched internal nodes.*/
+	public  void deleteUnbranchedInternals(int node, boolean notify) {
+		if (!inBounds(node))
+			return;
+		if (nodeIsTerminal(node))
+			return;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)){
+			deleteUnbranchedInternals(d, notify);
+		}
+		int d =  firstDaughterOfNode(node);
+		while (nodeExists(d)){
+			if (nodeIsUnbranchedInternal(d)) {
+				int nextd = nextSisterOfNode(d);
+				collapseBranch(d, false);
+				d = nextd;
+			}
+			else 
+				d =  nextSisterOfNode(d);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns whether clade has unbranched internal nodes.*/
+	public  boolean hasUnbranchedInternals(int node) {
+		if (!inBounds(node))
+			return false;
+		if (nodeIsTerminal(node))
+			return false;
+		if (nodeIsUnbranchedInternal(node))
+			return true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			if ( hasUnbranchedInternals(d))
+				return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the node is an internal node with only a single daughter.*/
+	public boolean nodeIsUnbranchedInternal(int node) {
+		if (!inBounds(node))
+			return false;
+		if (nodeIsTerminal(node))
+			return false;
+		int thisSister = firstDaughterOfNode(node);
+		int count = 0;
+		while (nodeExists(thisSister)) {
+			count ++;
+			if (count>1)
+				return false;
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether clade has polytomies.*/
+	public  boolean hasPolytomies(int node) {
+		if (!inBounds(node))
+			return false;
+		if (nodeIsTerminal(node))
+			return false;
+		if (nodeIsPolytomous(node))
+			return true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			if ( hasPolytomies(d))
+				return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the node is polytomous (has more than two daughters).*/
+	public boolean nodeIsPolytomous(int node) {
+		if (!inBounds(node))
+			return false;
+		if (nodeIsTerminal(node))
+			return false;
+		int thisSister = firstDaughterOfNode(node);
+		int count = 0;
+		while (nodeExists(thisSister)) {
+			count ++;
+			if (count>2)
+				return true;
+			thisSister = nextSisterOfNode(thisSister);
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the node has one descendant, two, or is a hard polytomy.*/
+	public boolean nodeIsHard(int node) { //TODO: in future allow individual trees or nodes to store whether polytomy is hard or soft
+		if (!inBounds(node))
+			return false;
+		if (!nodeIsPolytomous(node))
+			return true;
+		if (polytomiesHard==2)
+			return polytomyDefaultHard;
+		return polytomiesHard == 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the node is a soft polytomy.*/
+	public boolean nodeIsSoft(int node) {
+		if (!inBounds(node))
+			return false;
+		if (!nodeIsPolytomous(node))
+			return false;
+		if (polytomiesHard==2)
+			return !polytomyDefaultHard;
+		return polytomiesHard == 1;
+	}
+	/*-----------------------------------------*/
+	/** Sets the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+	public void setPolytomiesAssumption(int assumption, boolean notify){
+		if (polytomiesHard != assumption){
+			polytomiesHard = assumption;
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED, notify);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+	public int getPolytomiesAssumption(){
+		return polytomiesHard;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether clade has soft polytomies (uncertain resolution).*/
+	public  boolean hasSoftPolytomies(int node) {
+		if (nodeIsSoft(node))
+			return true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			if (hasSoftPolytomies(d))
+				return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns number of total nodes (internal and external) in clade.*/
+	public  int numberOfNodesInClade(int node) {
+		if (!inBounds(node))
+			return 0;
+		int count = 0;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			count += numberOfNodesInClade(d);
+		count++; //count node itself
+		return count;
+	}
+	/*-----------------------------------------*/
+	/** Returns number of terminal taxa in clade.*/
+	public  int numberOfTerminalsInClade(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 1; //count node itself
+		else{
+			int count = 0;
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				count += numberOfTerminalsInClade(d);
+			return count;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns number of internal nodes in clade.*/
+	public  int numberOfInternalsInClade(int node) {
+		if (!inBounds(node))
+			return 0;
+		int count = 0;
+		if (nodeIsInternal(node)) {
+			count++; //count node itself
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				count += numberOfInternalsInClade(d);
+		}
+		return count;
+	}
+	/*-----------------------------------------*/
+	/** Returns the left-most terminal that is descendant from node.*/
+	public  int leftmostTerminalOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return node;
+		else {
+			int d = firstDaughter[node];
+			while (nodeIsInternal(d))
+				d = firstDaughter[d];
+			return d; 
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns the right-most terminal that is descendant from node.*/
+	public  int rightmostTerminalOfNode(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return node;
+		else
+			return rightmostTerminalOfNode(lastDaughterOfNode(node)); 
+	}
+	/*-----------------------------------------*/
+	private void fillBits(int node, Bits b) {
+		if (nodeIsInternal(node)) {
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				fillBits(d, b);
+		}
+		else {
+			int n = taxonNumberOfNode(node);
+			b.setBit(n);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa of clade of node.*/
+	public Bits getTerminalTaxaAsBits(int node){
+		if (!inBounds(node))
+			return null;
+		Bits b = new Bits(numNodeSpaces);
+		fillBits(node, b);
+		return b;
+	}
+	/*-----------------------------------------*/
+	private void offBits(int node, Bits b) {
+		if (nodeIsInternal(node)) {
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				offBits(d, b);
+		}
+		else {
+			int n = taxonNumberOfNode(node);
+			b.setBit(n, false);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa in a tree that are NOT of clade of node.*/
+	public Bits getTerminalTaxaComplementAsBits(int node){
+		if (!inBounds(node))
+			return null;
+		Bits b = new Bits(numNodeSpaces);
+		fillBits(getRoot(), b);  // turn on all bits
+		offBits(node, b);  // turn off all bits that are in clade
+		return b;
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa of clade of node.*/
+	public int[] getTerminalTaxa(int node){
+		if (!inBounds(node))
+			return null;
+		int numTerms = numberOfTerminalsInClade(node);
+		int[] result = new int[numTerms];
+		MesquiteInteger count = new MesquiteInteger(0);
+		if (numTerms>0)
+			fillTermAr(node, result, count);
+		return result;
+	}
+	/*-----------------------------------------*/
+	private void gNAtHeight(int node, double target, int[] nodes, double heightToAncestor, double lengthIfUnassigned, MesquiteInteger count){
+		if (target>heightToAncestor){
+			double bL = getBranchLength(node, lengthIfUnassigned);
+			if (node != getRoot() && heightToAncestor + bL >= target) { //this is a branch that crosses the target height
+				nodes[count.getValue()] = node;
+				count.increment();
+			}
+			else if (nodeIsInternal(node)) {
+				if (node != getRoot())
+					heightToAncestor += bL;
+				for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+					gNAtHeight(d, target, nodes, heightToAncestor, lengthIfUnassigned, count);
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns list of nodes at a particular height above the root.  Array may have some elements filled with -1 meaning no node*/
+	public int[] getNodesAtHeight(double height, double lengthIfUnassigned, int[] nodes){
+		if (nodes == null || nodes.length < taxa.getNumTaxa())
+			nodes = new int[taxa.getNumTaxa()];
+		for (int i = 0; i< nodes.length; i++)
+			nodes[i] = -1;
+		MesquiteInteger count = new MesquiteInteger(0);
+		gNAtHeight(getRoot(), height, nodes, 0.0, lengthIfUnassigned, count);
+
+		return nodes;
+	}
+	/*-----------------------------------------*/
+	private void fillTermAr(int node, int[] ar, MesquiteInteger count){
+		if (nodeIsTerminal(node)) {
+			ar[count.getValue()] = taxonNumberOfNode(node);
+			count.increment();
+		}
+		else
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+				fillTermAr(d, ar, count);
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa NOT in clade of node.*/
+	public int[] getTerminalTaxaComplement(int node){
+		return getTerminalTaxaComplement(getTerminalTaxa(getRoot()),getTerminalTaxa(node));
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa NOT in clade of node.  Into this version you pass the int[] of the terminal taxa in the tree, for speed's sake. */
+	public int[] getTerminalTaxaComplement(int[] allTerminals, int node){
+		return getTerminalTaxaComplement(allTerminals,getTerminalTaxa(node));
+	}
+	/*-----------------------------------------*/
+	/** Returns list of terminal taxa NOT in clade of node.  Into this version you pass the int[] of the terminal taxa in the tree, for speed's sake. */
+	public int[] getTerminalTaxaComplement(int[] allTerminals, int[] nodeTerminals){
+		return IntegerArray.subtractArrays(allTerminals,nodeTerminals);
+	}
+	/*-----------------------------------------*/
+	private synchronized void downMarkPathsFromTerminals(Bits terminals, Bits nodes, int node){
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			downMarkPathsFromTerminals(terminals, nodes, d);
+			if (nodeIsTerminal(d) && terminals.isBitOn(taxonNumberOfNode(d))){   // this is a terminal
+				nodes.setBit(d);
+			}
+			if (nodes.isBitOn(d)){   // there is terminal above this point
+				nodes.setBit(node);
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	private synchronized void upMarkPathsFromTerminals(Bits nodes, int node){
+		int numLines = 0;
+		int line =-1;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			if (nodes.isBitOn(d)){   // there is terminal above this point
+				numLines++;
+				line = d;
+			}
+		}
+		if (numLines<=1)
+			nodes.setBit(node,false);
+		if (numLines==1)
+			upMarkPathsFromTerminals(nodes, line);
+	}
+	/*-----------------------------------------*/
+	private synchronized void markPathsFromTerminals(Bits terminals, Bits nodes, int node) { 
+		if (terminals==null || nodes==null)
+			return;
+		downMarkPathsFromTerminals(terminals, nodes, node);
+		upMarkPathsFromTerminals(nodes,  node);
+	}
+	/*-----------------------------------------*/
+	private synchronized boolean scanForUnmarkedDescendants(Bits terminals, Bits nodes, int node){
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			if (scanForUnmarkedDescendants(terminals, nodes, d))
+				return true;
+			if (!nodes.isBitOn(d) && nodes.isBitOn(node)){   // an ancestor is marked but not a descendant
+				return true;
+			}
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the terminals form a clade.*/
+	public boolean isClade(Bits terminals) { 
+		Bits nodes = new Bits(numNodeSpaces);
+		markPathsFromTerminals(terminals, nodes, getRoot());
+		return !scanForUnmarkedDescendants(terminals, nodes, getRoot());
+	}
+	/*-----------------------------------------*/
+	/** Returns true if the terminals form a clade.*/
+	public int makeClade(Bits terminals) { 
+		int mrca = mrca(terminals);
+		Bits nodes = new Bits(numNodeSpaces);
+		markPathsFromTerminals(terminals, nodes,mrca);
+		int count = 0;
+		int firstDaughter = 0;
+		for (int d = firstDaughterOfNode(mrca); nodeExists(d); ) {
+			int nextDaughter = nextSisterOfNode(d);
+			if (nodes.isBitOn(d)){
+				if (count==0)
+					firstDaughter=d;
+				moveBranch(d,firstDaughter,false);
+				if (count>1)
+					collapseBranch(motherOfNode(firstDaughter),false);
+				count++;
+			}
+			d= nextDaughter;
+		}
+		return motherOfNode(firstDaughter);
+	}
+	/*-----------------------------------------*/
+	private synchronized void scanForMultipleTransitions(Bits terminals, Bits nodes, int node, MesquiteInteger numTransitions, MesquiteInteger descendantBoundary){
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			scanForMultipleTransitions(terminals, nodes, d, numTransitions, descendantBoundary);
+			if (numTransitions.getValue()>1)
+				return;
+			if (nodes.isBitOn(d) != nodes.isBitOn(node)){   // an ancestor is marked but not a descendant
+				numTransitions.add(1);
+				descendantBoundary.setValue(d);
+			}
+		}
+		if (numTransitions.getValue()>1)
+			return;
+	}
+	/*-----------------------------------------*/
+	/** Returns true iff the terminal taxa listed in "terminals" form a convex part of the tree.  Also returns the node that forms the boundary*/
+	public boolean isConvex(Bits terminals, MesquiteInteger descendantBoundary) {
+		if (terminals==null) {
+			return false;
+		}
+		MesquiteInteger single = new MesquiteInteger();
+		if (terminals.oneBitOn(single)) {
+			descendantBoundary.setValue(nodeOfTaxonNumber(single.getValue()));
+			return true;
+		}
+		else {
+			Bits nodes = new Bits(numNodeSpaces);
+			markPathsFromTerminals(terminals, nodes, getRoot());
+			MesquiteInteger numTransitions = new MesquiteInteger(0);
+			scanForMultipleTransitions(terminals, nodes, getRoot(), numTransitions, descendantBoundary);
+			return numTransitions.getValue()<=1;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns true iff the terminal taxa listed in "terminals" form a convex part of the tree. */
+	public boolean isConvex(Bits terminals) {
+		MesquiteInteger boundary = new MesquiteInteger(0);
+		return isConvex(terminals, boundary);
+	}
+
+	public  void convertBranchLengthToNodeValue(int node, NameReference nameRef){
+		if (nodeIsInternal(node)) {
+			double bl = getBranchLength(node); 
+			if (MesquiteDouble.isCombinable(bl)){
+				setAssociatedDouble(nameRef, node, 0.01*bl, true);  // value will be a percentage
+			}
+			for (int d = firstDaughterOfNode(node); nodeExists(d) && !nodeWasFound; d = nextSisterOfNode(d))
+				convertBranchLengthToNodeValue(d, nameRef);
+		}
+	}
+
+	public  void convertBranchLengthsToNodeValue(String nameRefString){
+		NameReference nameRef = NameReference.getNameReference("consensusFrequency");
+		convertBranchLengthToNodeValue(getRoot(), nameRef);
+	}
+
+
+	/*-----------------------------------------*/
+	/** Returns the nth terminal node in the clade (0 based), from left to right.  If is too low or high,
+	 returns 0.*/
+	public int getTerminalNode(int node, int n){
+		if (!inBounds(node))
+			return 0;
+		int numTerms = numberOfTerminalsInClade(node);
+		if (numTerms==0 || n>=numTerms || n<0)
+			return 0;
+		MesquiteInteger count = new MesquiteInteger(0);
+		MesquiteInteger result = new MesquiteInteger(0);
+		findTerm(node, n, result, count);
+		return result.getValue();
+	}
+	private void findTerm(int node, int n, MesquiteInteger ar, MesquiteInteger count){
+		if (nodeIsTerminal(node)) {
+			if (count.getValue()== n)
+				ar.setValue(node);
+			count.increment();
+		}
+		else
+			for (int d = firstDaughterOfNode(node); nodeExists(d) && ar.getValue()==0; d = nextSisterOfNode(d))
+				findTerm(d, n, ar, count);
+	}
+	/*-----------------------------------------*/
+	public void cleanTree(){
+		for (int i=0; i<firstDaughter.length; i++){	
+			if (!nodeInTree(i)){
+				firstDaughter[i]=0;
+				nextSister[i]=0;
+				mother[i]=0;
+				setTaxonNumber(i, -1);
+			}
+		}
+		firstDaughter[0]=-1;
+		nextSister[0]=-1;
+		mother[0]=-1;
+		setTaxonNumber(0, -1);
+		mother[subRoot] = -1;
+		mother[root] = subRoot;
+		firstDaughter[subRoot]=root;
+	}
+	/*-----------------------------------------*/
+	private boolean nodeWasFound;
+	private void findNodeInTree(int node, int sought){
+		if (node==sought)
+			nodeWasFound=true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d) && !nodeWasFound; d = nextSisterOfNode(d))
+			findNodeInTree(d, sought);
+	}
+	/** Returns whether node is part of tree. Differs from nodeExists by doing full recursion (more reliable, slower).*/
+	public boolean nodeInTree(int sought){
+		if (!inBounds(sought))
+			return false;
+		nodeWasFound=false;
+		if ((sought>1) && (sought<=numNodeSpaces))
+			findNodeInTree(root, sought);
+		return nodeWasFound;
+	}
+	/** Returns whether taxon is part of tree. Does a full recursion (more reliable, slower).*/
+	private boolean taxonWasFound = false;
+	public void findTaxonInTree(int node, int sought){
+		if (nodeIsTerminal(node) && taxonNumber[node]==sought)
+			taxonWasFound=true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d) && !taxonWasFound; d = nextSisterOfNode(d))
+			findTaxonInTree(d, sought);
+	}
+	/** Returns whether taxon is part of tree. */
+	public boolean taxonInTree(int taxonNum){
+		taxonWasFound=false;
+		if ((taxonNum>=0) && (taxonNum<taxa.getNumTaxa()))
+			findTaxonInTree(root, taxonNum);
+		return taxonWasFound;
+	}
+	/*-----------------------------------------*/
+	public int nextInPreorder(int node){
+		if (nodeIsInternal(node))
+			return firstDaughterOfNode(node);
+		if (nodeExists(nextSisterOfNode(node)))
+			return nextSisterOfNode(node);
+		int mother = motherOfNode(node);
+		while (mother != root && !nodeExists(nextSisterOfNode(mother))) {
+			mother = motherOfNode(mother);
+		}
+		if (mother == root)
+			return 0;
+		return nextSisterOfNode(mother);
+	}
+	/*-----------------------------------------*/
+	public int nextInPostorder(int node){
+		if (node == root)
+			return 0;
+		if (nodeExists(nextSisterOfNode(node)))
+			return leftmostTerminalOfNode(nextSisterOfNode(node));
+		return motherOfNode(node);
+
+
+	}
+	public int firstInPostorder(){
+		return leftmostTerminalOfNode(root);
+	}
+	/*-----------------------------------------*/
+	private int countNodes;
+	private int nodeFound;
+	/** goes through the tree returning which node is the nodeNumberTH found in the traversal */
+	private synchronized void findNodeInTraversal(int node, int nodeNumber){
+		countNodes++;
+		if ((countNodes==nodeNumber) && (nodeFound==0))
+			nodeFound=node;
+		for (int d = firstDaughterOfNode(node); nodeExists(d) && nodeFound==0; d = nextSisterOfNode(d))
+			findNodeInTraversal(d, nodeNumber);
+	}
+	/*-----------------------------------------*/
+	/**Returns indexTH node in tree traversal*/
+	public int nodeInTraversal(int index){
+		countNodes=-1;
+		nodeFound=0;
+		findNodeInTraversal(root, index);
+		return nodeFound;
+	}
+	/*-----------------------------------------*/
+	/**Returns indexTH node in traversal through clade*/
+	public int nodeInTraversal(int index, int cladeRoot){
+		countNodes=-1;
+		nodeFound=0;
+		findNodeInTraversal(cladeRoot, index);
+		return nodeFound;
+	}
+	/*-----------------------------------------*/
+	/** Returns most recent common ancestor of two branches.*/
+	public int mrca(int branchA, int branchB) { 
+		if (branchB == branchA)
+			return branchB;
+		else if (!nodeExists(branchB)|!nodeExists(branchA))
+			return 0;
+		else if (descendantOf(branchA, branchB) )
+			return branchB;
+		else if (descendantOf(branchB, branchA) )
+			return branchA;
+		else {
+			int a = branchA;
+			while (a!=subRoot) {
+				a = motherOfNode(a);
+				if (descendantOf(branchB, a)) {
+					return a;
+				}
+			}
+			return 0;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns most recent common ancestor for an array of nodes.*/
+	public int mrca(int[] nodes){
+		for (int nodeCheck = 0; nodeCheck < nodes.length; nodeCheck++){
+			if(!nodeExists(nodes[nodeCheck])){
+				return 0;
+			}
+		}
+		return mrca(nodes, false);
+	}
+	/*-----------------------------------------*/
+	/** Returns most recent common ancestor for an array of nodes; if boolean ignoreMissing = false, it 
+	 * will only return a non-zero (existing) node if all the nodes in the array are present in the 
+	 * tree.  If ignoreMissing = true, it will return the mrca of those nodes passed in the node array
+	 * that are actually present in the tree; nodes in the node array that are not present in the tree 
+	 * are ignored.*/
+	public int mrca(int[] nodes, boolean ignoreMissing){
+		boolean allIncluded = false;
+		int a = nodes[0];
+		if(!ignoreMissing){
+			while (a!=subRoot){
+				a = motherOfNode(a);
+				descendantCheckLoop: for (int descendantCheck = 0; descendantCheck < nodes.length; descendantCheck++){
+					if(!descendantOf(nodes[descendantCheck], a)){
+						allIncluded = false;
+						break descendantCheckLoop;
+					} else {
+						allIncluded = true;
+					}
+				}
+				if(allIncluded){
+					return a;
+				}
+			}
+			return 0;
+		}
+		else{
+			int nodeCheck = 1;
+			while(!nodeExists(a) && nodeCheck < (nodes.length - 1)){
+				a = nodes[nodeCheck];
+				nodeCheck++;
+			}
+			if(!nodeExists(a) && nodeCheck==(nodes.length-1)) //at least two nodes of passed array MUST exist in the tree for a mrca to be defined.
+				return 0;
+			while (a!=subRoot){
+				a = motherOfNode(a);
+				descendantCheckLoop: for (int descendantCheck = 0; descendantCheck < nodes.length; descendantCheck++){
+					/*The following conditional makes sure that only those nodes that exist in the tree are used
+					 * to determine mrca.  If node does not exist in the tree, it is ignored.*/
+					if(nodeExists(nodes[descendantCheck])){
+						if(!descendantOf(nodes[descendantCheck], a)){
+							allIncluded = false;
+							break descendantCheckLoop;
+						}
+						else {
+							allIncluded = true;
+						}
+					}
+				}
+				if(allIncluded){
+					return a;
+				}
+			}
+			return 0;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns most recent common ancestor for an array of taxon numbers; if boolean ignoreMissing = false, it 
+	 * will only return a non-zero (existing) node if all the taxons in the array are present in the 
+	 * tree.  If ignoreMissing = true, it will return the mrca of those taxons passed in the taxon array
+	 * that are actually present in the tree; taxons in the taxon array that are not present in the tree 
+	 * are ignored.*/
+	public int mrcaTaxons(int[] taxons, boolean ignoreMissing){
+		int[] nodes = new int[taxons.length];
+		for(int it = 0; it < nodes.length; it++){
+			nodes[it] = nodeOfTaxonNumber(taxons[it]);
+		}
+		return mrca(nodes, ignoreMissing);
+	}
+	/*-----------------------------------------*/
+	private synchronized int getDeepest(int aTerminal, Bits nodes){
+		int d = aTerminal;
+		for (int p = aTerminal; nodeExists(p); p = motherOfNode(p)) {
+			if (!nodes.isBitOn(p))
+				return d;
+			d = p;
+		}
+		return getRoot();
+	}
+	/*-----------------------------------------*/
+	/** Returns most recent common ancestor of the terminals designated in terminals.*/
+	public int mrca(Bits terminals) { 
+		Bits nodes = new Bits(numNodeSpaces);
+		markPathsFromTerminals(terminals, nodes, getRoot());
+		int firstTerminal = terminals.firstBitOn();
+		return getDeepest(nodeOfTaxonNumber(firstTerminal), nodes);
+	}
+	/*-----------------------------------------*/
+	/** Returns the closest ancestor that has more than one daughter.*/
+	public  int branchingAncestor(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (node==root)
+			return node;
+		int anc = motherOfNode(node);
+		while(numberOfDaughtersOfNode(anc)==1 && anc!=subRoot) //or root?
+			anc = motherOfNode(anc);
+		return anc;
+	}
+	/*-----------------------------------------*/
+	/** Returns the closest descendant that has more than one daughter, or is terminal.*/
+	public  int branchingDescendant(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return node;
+		int desc = node;
+		while(numberOfDaughtersOfNode(desc)==1 && nodeIsInternal(desc))
+			desc = firstDaughterOfNode(desc);
+		return desc;
+	}
+	/*-----------------------------------------*/
+	/** Returns the next (clockwise) to node connected to anc.  This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public int nextAroundUR(int anc, int node){
+		if (!nodeExists(node) && !nodeExists(anc))
+			return 0;
+		if (node== mother[anc])
+			return firstDaughter[anc];
+		int candidate = nextSister[node];
+		if (!nodeExists(candidate)) {
+			if (anc==root)
+				candidate = firstDaughter[root];
+			else
+				candidate = mother[anc];
+		}
+		return candidate;
+	}
+	/*-----------------------------------------*/
+	/** Returns the first (left-most) daughter of node in an UNROOTED sense where the node
+	is treated as descendant from anc. This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int firstDaughterOfNodeUR(int anc, int node) {
+		if (!nodeExists(node) && !nodeExists(anc))
+			return 0;
+		if (anc==mother[node] || anc == node) //heading up tree or starting here
+			return firstDaughter[node]; 
+		else
+			return nextAroundUR(node, anc);
+	}
+	/*-----------------------------------------*/
+	/** Returns the node's sister immediately to the right in an UNROOTED sense where the node
+	is treated as descendant from anc, which is descendant from ancAnc.  If the node has no
+	sister to the right, returns 0 (which is not a valid node designation). This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int nextSisterOfNodeUR(int ancAnc, int anc, int node) {
+		if (!nodeExists(node) && !nodeExists(anc))
+			return 0;
+		int candidate = nextAroundUR(anc, node);
+		if (candidate == ancAnc)
+			return 0;
+		else if (ancAnc==anc && candidate == firstDaughter[anc])
+			return 0;
+		else
+			return candidate;
+	}
+	/*-----------------------------------------*/
+	/** Returns the first (left-most) daughter of node in an UNROOTED sense where the node
+	is treated as descendant from anc. This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int lastDaughterOfNodeUR(int anc, int node) {
+		if (!nodeExists(node) && !nodeExists(anc))
+			return 0;
+		int first = firstDaughterOfNodeUR(anc, node);
+		int prev = first;
+		while (nodeExists(first)) {
+			prev = first;
+			first = nextSisterOfNodeUR(anc, node, first);
+		}
+		return prev;
+	}
+	/*-----------------------------------------*/
+	/** Returns what node number in Mesquite's standard rooted sense corresponds to the anc-node branch.*/
+	public  int nodeOfBranchUR(int anc, int node) {
+		if (anc==mother[node])
+			return node; 
+		else if (node == mother[anc])
+			return anc;
+		else
+			return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether any branchLengths are assigned.*/
+	private boolean lengthsAssigned(int node) { 
+		if (branchLength ==null)
+			return false;
+		if (!MesquiteDouble.isUnassigned(branchLength[node]))
+			return true;
+		for (int daughter = firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter))
+			if (lengthsAssigned(daughter))
+				return true;
+
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if tree has branch lengths.*/
+	public boolean hasBranchLengths() { 
+		if (branchLength ==null)
+			return false;
+		return lengthsAssigned(root);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether all branchLengths are assigned.*/
+	private boolean allLengthsAssigned(int node, boolean includeRoot) { 
+		if (branchLength ==null)
+			return false;
+		if ((node != root || includeRoot) && MesquiteDouble.isUnassigned(branchLength[node]))
+			return false;
+		for (int daughter = firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter))
+			if (!allLengthsAssigned(daughter, includeRoot))
+				return false;
+
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Returns true if tree has all nodes with branch lengths assigned.*/
+	public boolean allLengthsAssigned(boolean includeRoot) { 
+		return allLengthsAssigned(root, includeRoot);
+	}
+	/*-----------------------------------------*/
+	/** Returns true if tree has all nodes with branch lengths assigned.*/
+	public boolean allLengthsAssigned() { 
+		return allLengthsAssigned(true);
+	}
+	/*-----------------------------------------*/
+	/** Returns the branch length of the node.*/
+	public  double getBranchLength(int node) { 
+		if (!inBounds(node))
+			return MesquiteDouble.unassigned;
+		if (branchLength==null)
+			return MesquiteDouble.unassigned;
+		else 
+			return branchLength[node];
+	}
+	/*-----------------------------------------*/
+	/** Returns the branch length of the node.  If the branch length is unassigned, pass back the double passed in*/
+	public  double getBranchLength(int node, double ifUnassigned) { 
+		if (!inBounds(node))
+			return ifUnassigned;
+		if (branchLength==null)
+			return ifUnassigned;
+		else if (MesquiteDouble.isUnassigned(branchLength[node]))
+			return ifUnassigned;
+		else
+			return branchLength[node];
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of nodes (stored as a double internally).*/
+	private void setLengths(int node, double length) { 
+		for (int daughter = firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter))
+			setLengths(daughter, length);
+
+		branchLength[node]= length; 
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of all nodes whose length is currently unassigned.*/
+	private  void setAllUnassignedBranchLengthsRec(int node, double length) { 
+		for (int daughter = firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter))
+			setAllUnassignedBranchLengthsRec(daughter, length);
+		if (getBranchLength(node) == MesquiteDouble.unassigned)
+			setBranchLength(node, length, false); 
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of all nodes whose length is currently unassigned.*/
+	public  void setAllUnassignedBranchLengths(double length, boolean notify) { 
+		if (branchLength==null) {
+			branchLength = new double[numNodeSpaces];
+			for (int i=0; i<numNodeSpaces; i++) {
+				branchLength[i]= MesquiteDouble.unassigned;
+			}
+		}
+		setAllUnassignedBranchLengthsRec(getRoot(), length);
+		incrementVersion(BRANCHLENGTHS_CHANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of node.*/
+	public  void setAllBranchLengths(double length, boolean notify) { 
+
+		if (branchLength==null) {
+			branchLength = new double[numNodeSpaces];
+			for (int i=0; i<numNodeSpaces; i++) {
+				branchLength[i]= MesquiteDouble.unassigned;
+			}
+		}
+		setLengths(root, length); 
+		incrementVersion(BRANCHLENGTHS_CHANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of node.*/
+	public  void scaleAllBranchLengths(double factor, boolean notify) { 
+
+		if (branchLength==null) {
+			return;
+		}
+		for (int i=0; i<numNodeSpaces; i++)
+			if (nodeExists(i) && !branchLengthUnassigned(i))
+				setBranchLength(i, getBranchLength(i)*factor, false);
+		incrementVersion(BRANCHLENGTHS_CHANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of node (stored as a double internally).*/
+	public  void setBranchLength(int node, int length, boolean notify) { 
+		if (!inBounds(node))
+			return;
+		if (branchLength==null) {
+			branchLength = new double[numNodeSpaces];
+			for (int i=0; i<numNodeSpaces; i++) {
+				branchLength[i]= MesquiteDouble.unassigned;
+			}
+		}
+		if (MesquiteInteger.unassigned ==length)
+			branchLength[node]= MesquiteDouble.unassigned; 
+		else 
+			branchLength[node]= length; 
+		if (MesquiteInteger.isCombinable(length) && length<0)
+			;//MesquiteMessage.notifyProgrammer("Warning: branch length being set to negative number (" + length + ")");
+		incrementVersion(BRANCHLENGTHS_CHANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Sets the branch length of node.*/
+	public  void setBranchLength(int node, double length, boolean notify) { 
+		if (!inBounds(node))
+			return;
+		if (branchLength==null) {
+			branchLength = new double[numNodeSpaces];
+			for (int i=0; i<numNodeSpaces; i++) {
+				branchLength[i]= MesquiteDouble.unassigned;
+			}
+		}
+		branchLength[node] = length; 
+		if (MesquiteDouble.isCombinable(length) && length<0)
+			;//MesquiteMessage.notifyProgrammer("Warning: branch length being set to negative number (" + length + ")");
+		incrementVersion(BRANCHLENGTHS_CHANGED, notify);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether branch length of node is unassigned.*/
+	public  boolean branchLengthUnassigned(int node) { 
+		if (!inBounds(node))
+			return true;
+		return (branchLength==null || MesquiteDouble.isUnassigned(branchLength[node]));
+	}
+	/*-----------------------------------------*/
+	/** returns tallest path in number of nodes, not branch length, above a node.  Added 3 Nov 01 WPM */
+	public int mostStepsAboveNode (int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		int maximum = 0;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			int thisWay = mostStepsAboveNode(daughter) + 1;
+			if (thisWay>maximum)
+				maximum = thisWay;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** returns the node whose distance from the root in branch length is the tallest.  Added 3 Nov 01 WPM*/
+	public int tallestNode (int node) {
+		if (!inBounds(node))
+			return node;
+		if (nodeIsTerminal(node))
+			return node;
+		double maximum = 0;
+		int tallest = 0;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			double thisWay = tallestPathAboveNode(daughter);
+			if (!branchLengthUnassigned(daughter))
+				thisWay += getBranchLength(daughter);
+			if (thisWay>maximum) {
+				maximum = thisWay;
+				tallest = tallestNode(daughter);
+			}
+		}
+		return tallest;
+	}
+	/*-----------------------------------------*/
+	/** returns the node whose distance from the root in branch length is the tallest.  Added 3 Nov 01 WPM*/
+	public int tallestNode (int node, double perUnassignedLength) {
+		if (!inBounds(node))
+			return node;
+		if (nodeIsTerminal(node))
+			return node;
+		double maximum = 0;
+		int tallest = 0;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			double thisWay = tallestPathAboveNode(daughter);
+			thisWay += getBranchLength(daughter, perUnassignedLength);
+			if (thisWay>maximum) {
+				maximum = thisWay;
+				tallest = tallestNode(daughter);
+			}
+		}
+		return tallest;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to tallest terminal */
+	public double tallestPathAboveNode (int node) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		double maximum = 0;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			double thisWay = tallestPathAboveNode(daughter);
+			if (!branchLengthUnassigned(daughter))
+				thisWay += getBranchLength(daughter);
+			if (thisWay>maximum)
+				maximum = thisWay;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to tallest terminal */
+	public double tallestPathAboveNodeUR (int anc, int node) {
+		if (!inBounds(node) || !inBounds(anc))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		double maximum = 0;
+		for (int daughter=firstDaughterOfNodeUR(anc, node); nodeExists(daughter); daughter = nextSisterOfNodeUR(anc, node, daughter) ) {
+			double thisWay = tallestPathAboveNodeUR(node, daughter);
+			if (!branchLengthUnassigned(nodeOfBranchUR(node,daughter)))
+				thisWay += getBranchLength(nodeOfBranchUR(node,daughter));
+			if (thisWay>maximum)
+				maximum = thisWay;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to tallest terminal */
+	public double tallestPathAboveNodeUR (int anc, int node, double perUnassignedLength) {
+		if (!inBounds(node) || !inBounds(anc))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		double maximum = 0;
+		for (int daughter=firstDaughterOfNodeUR(anc, node); nodeExists(daughter); daughter = nextSisterOfNodeUR(anc, node, daughter) ) {
+			double bL =getBranchLength(nodeOfBranchUR(node,daughter));
+			if (MesquiteDouble.isUnassigned(bL))
+				bL = perUnassignedLength;
+			double thisWay = tallestPathAboveNodeUR(node, daughter, perUnassignedLength) +bL;
+			if (thisWay>maximum)
+				maximum = thisWay;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to tallest terminal, with unassigned lengths given value "perUnassignedLength" */
+	public double tallestPathAboveNode (int node, double perUnassignedLength) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		double maximum = 0;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			double bL =getBranchLength(daughter);
+			if (MesquiteDouble.isUnassigned(bL))
+				bL = perUnassignedLength;
+			double thisWay = tallestPathAboveNode(daughter, perUnassignedLength) +bL;
+			if (thisWay>maximum)
+				maximum = thisWay;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node up to shortest terminal, with unassigned lengths given value "perUnassignedLength" */
+	public double shortestPathAboveNode (int node, double perUnassignedLength) {
+		if (!inBounds(node))
+			return 0;
+		if (nodeIsTerminal(node))
+			return 0;
+		double minimum = MesquiteDouble.unassigned;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			double bL =getBranchLength(daughter);
+			if (MesquiteDouble.isUnassigned(bL))
+				bL = perUnassignedLength;
+			double thisWay = shortestPathAboveNode(daughter, perUnassignedLength) +bL;
+			if (minimum == MesquiteDouble.unassigned || thisWay<minimum)
+				minimum = thisWay;
+		}
+		return minimum;
+	}
+	/*-----------------------------------------*/
+	/** returns total of branchlengths from node down to root, with unassigned lengths given value "perUnassignedLength" */
+	public double distanceToRoot (int node, boolean countUnassigned, double perUnassignedLength) {
+		if (!inBounds(node))
+			return 0;
+		if (node == root || node == subRoot)
+			return 0;
+		int current = node;
+		double total = 0.0;
+		boolean found = false;
+		int count = 0;
+		while (current != root && (count++ < getNumNodeSpaces())){
+			double bL = getBranchLength(current);
+			if (!MesquiteDouble.isCombinable(bL)){
+				if (countUnassigned && bL == MesquiteDouble.unassigned){
+					total += perUnassignedLength;
+					found = true;
+				}
+			}
+			else {
+				total += bL;
+				found = true;
+			}
+			current = motherOfNode(current);
+		}
+		if (!found)
+			return MesquiteDouble.unassigned;
+		return total;
+	}
+	/*-----------------------------------------*/
+	NameReference branchNotesRef = NameReference.getNameReference("note");
+	/** Reads a token refering to a named internal node. */
+	private String readNamedInternal(String TreeDescription, String c, int sN, MesquiteInteger stringLoc){
+
+		if (convertInternalNames){
+			setAssociatedObject(branchNotesRef, sN, c);
+			return ParseUtil.getToken(TreeDescription, stringLoc);  //skip parens or next comma
+		}
+		else {
+			int taxon = taxa.whichTaxonNumber(c, false, permitTruncTaxNames && !permitTaxaBlockEnlargement);
+			if (taxon>=0){
+				System.out.println("Observed taxon " + c + " in ancestral position; not yet allowed by Mesquite.  Tree will not be read in properly");
+			}
+			if (cosmeticInternalNames){
+				setNodeLabel(c, sN); 
+				if (taxa!=null && taxa.getClades()!=null && taxa.getClades().findClade(c) == null)
+					taxa.getClades().addClade(c);
+				return ParseUtil.getToken(TreeDescription, stringLoc);  //skip parens or next comma
+			}
+			else {
+				int labNode = nodeOfLabel(c);
+				if (labNode==-1) {
+					setNodeLabel(c, sN); 
+					if (taxa!=null && taxa.getClades()!=null && taxa.getClades().findClade(c) == null)
+						taxa.getClades().addClade(c);
+					return ParseUtil.getToken(TreeDescription, stringLoc);  //skip parens or next comma
+				}
+				else {//IF LABEL already exists, then attach new ancestor
+					String s = "";
+					if (permitTruncTaxNames)
+						s =" (This may have occured because of a corrupted file, or because tree reading is set to permit truncated taxon names (see Defaults menu to turn this off), leading to ambiguities.)"; 
+					if (numReticWarnings++ < 5)
+						MesquiteMessage.warnProgrammer("Apparent reticulation found (two taxon names or clade names interpreted as the same)." + s  + " " + TreeDescription);
+					else if (numReticWarnings == 5)
+						MesquiteTrunk.mesquiteTrunk.discreetAlert("Five warnings about apparent reticulations have been given. " + s + "  If there are further problems in this run of Mesquite, only short warnings will be given");
+					else if (numReticWarnings <100)
+						MesquiteMessage.println("Another tree with apparent reticulations found.");
+					else if (numReticWarnings == 100)
+						MesquiteMessage.println("NO MORE WARNINGS ABOUT RETICULATIONS WILL BE GIVEN IN THIS RUN OF MESQUITE.");
+
+
+					setParentOfNode(labNode, motherOfNode(labNode), false);
+					setParentOfNode(labNode, motherOfNode(sN), false);
+					return ParseUtil.getToken(TreeDescription, stringLoc);  //skip parens or next comma
+				}
+			}
+		}
+	}
+	static int numReticWarnings = 0;
+	static boolean dWarn = true;
+	private boolean expectedPunctuation(String c){
+		return (")".equals(c) || ",".equals(c) || ";".equals(c) || "<".equals(c));
+	}
+	public void setPermitTaxaBlockEnlargement(boolean permit){
+		this.permitTaxaBlockEnlargement = permit;
+	}
+	public boolean getPermitTaxaBlockEnlargement(){
+		return permitTaxaBlockEnlargement;
+	}
+	/*...............................................  read tree ....................................................*/
+	/** Continues reading a tree description, starting at node "node" and the given location on the string*/
+	static final int CONTINUE = 0;
+	static final int DONT_SPROUT = 1;
+	static final int FAILED = 2;
+	private int readClade(String TreeDescription, int node, MesquiteInteger stringLoc, TaxonNamer namer,  String whitespaceString, String punctuationString) {
+		if (StringUtil.blank(TreeDescription))
+			return FAILED;
+
+		String c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);
+		if ("<".equals(c)) {
+			while (!">".equals(c)  && c != null) 
+				c=ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);
+			c=ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);
+		}
+		if ("(".equals(c)){  //internal node
+			int sprouted = sproutDaughter(node, false);
+			int result = readClade(TreeDescription, sprouted,stringLoc, namer, whitespaceString, punctuationString);
+			if (result == FAILED)//������������������������
+				return FAILED;
+			c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma
+			if (!((",".equals(c))||(")".equals(c)) || (":".equals(c)) || "<".equals(c) || "%".equals(c) || "#".equals(c))){ // name of internal node!!!!
+				c = readNamedInternal(TreeDescription, c, sprouted, stringLoc);
+			}
+			while (":".equals(c) || "<".equals(c)|| "%".equals(c) || "#".equals(c)) {
+				if (":".equals(c)) {
+					readLength(TreeDescription, sprouted, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+					if (!expectedPunctuation(c)) {
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 1");
+						return FAILED;
+					}
+				}
+				else if ("%".equals(c) || "#".equals(c)) {
+					skipValue(TreeDescription, sprouted, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+					if (!expectedPunctuation(c)) {
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 2");
+						return FAILED;
+					}
+				}
+				else if ("<".equals(c)) {
+					readAssociated(TreeDescription, sprouted, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+					if (!(c!=null && ":".equals(c)) && !expectedPunctuation(c)) {
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 3");
+						return FAILED;
+					}
+				}
+			}
+			while (",".equals(c)) {
+				if (result == CONTINUE)
+					sprouted = sproutDaughter(node, false);
+				result = readClade(TreeDescription, sprouted,stringLoc, namer, whitespaceString, punctuationString);
+				if (result == FAILED) //������������������������
+					return FAILED;
+				c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString); //skip parens or next comma
+				if (!((",".equals(c))||(")".equals(c)) || (":".equals(c)) || "<".equals(c)|| "%".equals(c) || "#".equals(c))){ // name of internal node!!!!
+					c = readNamedInternal(TreeDescription, c, sprouted, stringLoc);
+				}
+				while (":".equals(c) || "<".equals(c)|| "%".equals(c) || "#".equals(c)) {
+					if (":".equals(c)) {
+						readLength(TreeDescription, sprouted, stringLoc);
+						c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+						if (!expectedPunctuation(c)) {
+							MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 4");
+							return FAILED;
+						}
+					}
+					else if ("%".equals(c) || "#".equals(c)) {
+						skipValue(TreeDescription, sprouted, stringLoc);
+						c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+						if (!expectedPunctuation(c)) {
+							MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 5");
+							return FAILED;
+						}
+					}
+					else if ("<".equals(c)) {
+						readAssociated(TreeDescription, sprouted, stringLoc);
+						c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //get next token
+						if (!(c!=null && ":".equals(c)) && !expectedPunctuation(c)) {
+							MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 6");
+							return FAILED;
+						}
+					}
+				}
+			}
+			return CONTINUE;
+		}
+		else {
+			int path = 0;
+			int taxonNumber = -1;
+			int fromWhichNamer = -1;
+			if (namer != null){
+				taxonNumber = namer.whichTaxonNumber(taxa, c);
+				fromWhichNamer = 1;
+			}
+			if (taxonNumber < 0){
+				if (treeVector !=null) {
+					taxonNumber = treeVector.whichTaxonNumber(c, permitTruncTaxNames && !permitTaxaBlockEnlargement); //use treeVector's translation table if one is available
+					fromWhichNamer = 2;
+					if (taxonNumber <0) {
+						taxonNumber = taxa.whichTaxonNumber(c, false, permitTruncTaxNames && !permitTaxaBlockEnlargement);
+						fromWhichNamer = 3;
+					}
+					path += 1;
+				}
+				else {  //if (taxonNumber == -1) {
+					taxonNumber = taxa.whichTaxonNumber(c, false, permitTruncTaxNames && !permitTaxaBlockEnlargement);
+					fromWhichNamer = 4;
+				}
+				if (taxonNumber<0){
+					if (MesquiteTree.permitT0Names && c != null && c.startsWith("t")){  //not found in taxon names, but as permits t0, t1 style names, look for it there 
+						String number = c.substring(1, c.length());
+						int num = MesquiteInteger.fromString(number);
+						if (MesquiteInteger.isCombinable(num) && num>=0 && num<taxa.getNumTaxa())
+							taxonNumber = num;
+					}
+				}
+			}
+			if (taxonNumber >=0){ //taxon successfully found
+				if (taxonNumber>= nodeOfTaxon.length)
+					resetNodeOfTaxonNumbers();
+				if (taxonNumber>= nodeOfTaxon.length){
+					MesquiteMessage.warnProgrammer("taxon number too high found (" + c + ")");
+					return FAILED;
+				}
+
+				if (nodeOfTaxon[taxonNumber]<=0){  // first time taxon encountered
+					//if (nodeOfTaxonNumber(taxonNumber)<=0){  // first time taxon encountered
+					setTaxonNumber(node, taxonNumber, false);
+					return CONTINUE;
+				}
+				else {
+					int termN = nodeOfTaxonNumber(taxonNumber);
+					if (motherOfNode(termN) != motherOfNode(node)) { //protect against redundant references; NOTE: may not protect if more than two parents
+						//apparent reticulation found!
+						String s = "";
+						if (permitTruncTaxNames)
+							s =" (This may have occured because of a corrupted file, or because tree reading is set to permit truncated taxon names (see Defaults menu to turn this off), leading to ambiguities.)"; 
+						if (numReticWarnings++ < 5)
+							MesquiteMessage.warnProgrammer("Apparent reticulation found (two taxon names or clade names interpreted as the same). [" + c + "] " + s  + " " + TreeDescription);
+						else if (numReticWarnings == 5)
+							MesquiteTrunk.mesquiteTrunk.discreetAlert("Five warnings about apparent reticulations have been given. " + s + "  If there are further problems in this run of Mesquite, only short warnings will be given");
+						else if (numReticWarnings <100)
+							MesquiteMessage.println("Another tree with apparent reticulations found.");
+						else if (numReticWarnings == 100)
+							MesquiteMessage.println("NO MORE WARNINGS ABOUT RETICULATIONS WILL BE GIVEN IN THIS RUN OF MESQUITE.");
+						setParentOfNode(termN, motherOfNode(termN), false);
+						setParentOfNode(termN, motherOfNode(node), false);
+						return DONT_SPROUT; //don't continue up tree
+					}
+					else {//redundant
+						MesquiteMessage.warnUser("Redundant taxon or node name in tree  (" + c + ", taxon number " + taxonNumber + "; number from " + fromWhichNamer + " permitTruncTaxNames " + permitTruncTaxNames + "); attempt will be made to read tree, but some clades or taxa may be missing. " + TreeDescription);
+						//snip last daughter added, as redundant
+						int prev = previousSisterOfNode(node);
+						if (prev>=0 && prev<nextSister.length)
+							nextSister[prev] = 0;
+						return DONT_SPROUT;
+					}
+				}
+			}
+			else { //see if apparent taxon is actually name of previously labelled internal node
+				int labNode = nodeOfLabel(c);
+				if (labNode!=-1) {//IF LABEL already exists, then attach new ancestor
+					if (motherOfNode(labNode) != motherOfNode(node)) { //protect against redundant references; NOTE: may not protect if more than two parents
+						String s = "";
+						if (permitTruncTaxNames)
+							s =" (This may have occured because of a corrupted file, or because tree reading is set to permit truncated taxon names (see Defaults menu to turn this off), leading to ambiguities.)"; 
+						if (numReticWarnings++ < 5)
+							MesquiteMessage.warnProgrammer("Apparent reticulation found (two taxon names or clade names interpreted as the same). [" + c + "] " + s  + " " + TreeDescription);
+						else if (numReticWarnings == 5)
+							MesquiteTrunk.mesquiteTrunk.discreetAlert("Five warnings about apparent reticulations have been given. " + s + "  If there are further problems in this run of Mesquite, only short warnings will be given");
+						else if (numReticWarnings <100)
+							MesquiteMessage.println("Another tree with apparent reticulations found.");
+						else if (numReticWarnings == 100)
+							MesquiteMessage.println("NO MORE WARNINGS ABOUT RETICULATIONS WILL BE GIVEN IN THIS RUN OF MESQUITE.");
+						setParentOfNode(labNode, motherOfNode(labNode), false);
+						setParentOfNode(labNode, motherOfNode(node), false);
+						//c = ParseUtil.getToken(TreeDescription, stringLoc);  //skip internal node name
+						return DONT_SPROUT; //don't continue up tree
+					}
+					else {  //redundant
+						MesquiteMessage.warnUser("Redundant taxon or node name in tree description  (" + c + ", internal node); attempt will be made to read tree, but some clades or taxa may be missing. " + TreeDescription);
+						//snip last daughter added, as redundant
+						int prev = previousSisterOfNode(node);
+						if (prev>=0 && prev<nextSister.length)
+							nextSister[prev] = 0;
+						return DONT_SPROUT;
+					}
+				}
+				else {
+					if (permitTaxaBlockEnlargement){
+						inProgressAddingTaxa = true;
+						boolean success = taxa.addTaxa(taxa.getNumTaxa(), 1, true);
+						if (success){
+							taxa.setTaxonName(taxa.getNumTaxa()-1, c);
+							oldNumTaxa = taxa.getNumTaxa();
+							taxaIDs = taxa.getTaxaIDs();
+							setTaxonNumber(node, taxa.getNumTaxa()-1, false);
+							inProgressAddingTaxa = false;
+							return CONTINUE;
+
+						}
+						inProgressAddingTaxa = false;
+					}
+
+					if (dWarn) { //modified 13 Nov 01
+						if (AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Unrecognized taxon name", "Unrecognized name (\"" + c + "\") of terminal taxon in tree", "Continue", "Don't warn again", 0)) {
+							dWarn = false;
+						}
+						MesquiteMessage.warnUser("Unrecognized name (\"" + c + "\") of terminal taxon in tree " + getName() + " for taxa " + getTaxa().getName() + " (search for \"ERROR>\" in output in log file) " + path);
+						StringBuffer sb = new StringBuffer(TreeDescription);
+						sb.insert(stringLoc.getValue()-1, "ERROR>");
+						MesquiteTrunk.mesquiteTrunk.logln(sb.toString());
+					}
+					else {
+						MesquiteMessage.warnUser("Unrecognized name (\"" + c + "\") of terminal taxon in tree " + getName() + " for taxa " + getTaxa().getName() + " (search for \"ERROR>\" in output in log file) " + path);
+						lastUnrecognizedName = c;
+					}
+					return FAILED;
+				}
+			}
+		}
+	}
+	public boolean graftCladeFromDescription(String TreeDescription, int node, MesquiteInteger stringLoc, TaxonNamer namer) {
+		setTaxonNumber(node, -1);
+		try {
+			if (readClade(TreeDescription, node, stringLoc, namer, null, null) == FAILED){
+				if (lastUnrecognizedName != null)
+					MesquiteMessage.warnProgrammer("graft clade failed; taxon name unrecognized: " + lastUnrecognizedName);
+				else
+					MesquiteMessage.printStackTrace("graft clade failed");
+
+
+				return false;
+			}
+			if (!checkTreeIntegrity(root)) {
+				MesquiteMessage.printStackTrace("graft clade failed (integrity check)");
+				return false;
+			}
+		}
+		catch (Throwable e){
+			MesquiteTrunk.mesquiteTrunk.logln("Problem grafting clade " + TreeDescription);
+
+			MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "Problem reading tree");
+			return false;
+		}
+		return true;
+	}
+	/*-----------------------------------------*/
+	/* reads the branch length; allows exponentials and negative numbers*/
+	private void skipValue (String TreeDescription, int node, MesquiteInteger stringLoc) {
+		double d = MesquiteDouble.fromString(TreeDescription, stringLoc);
+	}
+	/*-----------------------------------------*/
+	/* reads the branch length; allows exponentials and negative numbers*/
+	private void readLength (String TreeDescription, int node, MesquiteInteger stringLoc) {
+		double d = MesquiteDouble.fromString(TreeDescription, stringLoc);
+		if (d!=MesquiteDouble.impossible)
+			setBranchLength(node, d, false);
+	}
+	/*-----------------------------------------*/
+	String lastUnrecognizedName = null;
+	/** Reads the tree description string and sets the tree object to store the tree described.*/
+	public boolean readTree(String TreeDescription) {
+		return readTree(TreeDescription, null);
+	}
+
+	/** Reads the tree description string and sets the tree object to store the tree described.*/
+	public boolean readTree(String TreeDescription, TaxonNamer namer) {
+		return readTree(TreeDescription, null, null, null);
+	}
+
+	/** Reads the tree description string and sets the tree object to store the tree described.*/
+	public boolean readTree(String TreeDescription, TaxonNamer namer, String whitespaceString, String punctuationString) {
+		deassignAssociated();
+
+		MesquiteInteger stringLoc = new MesquiteInteger(0);
+
+		intializeTree();
+		lastUnrecognizedName = null;
+		try {
+			if (readClade(TreeDescription, root, stringLoc, namer, whitespaceString, punctuationString) == FAILED){
+				if (lastUnrecognizedName != null)
+					MesquiteMessage.warnProgrammer("read clade failed; taxon name unrecognized: " + lastUnrecognizedName);
+				else
+					MesquiteMessage.printStackTrace("read clade failed");
+				if (MesquiteTrunk.debugMode)
+					MesquiteMessage.discreetNotifyUser("\nTree description: \n"+TreeDescription +"\n");
+
+				intializeTree();
+
+				return false;
+			}
+		}
+		catch (Throwable e){
+			MesquiteTrunk.mesquiteTrunk.logln("Problem reading tree " + TreeDescription);
+
+			MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "Problem reading tree");
+			return false;
+		}
+		String c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+		if (!StringUtil.blank(c) && !(";".equals(c))){  //TODO: all these "equals" should be replaced by StringUtil static methods
+			if (!((",".equals(c))||(")".equals(c)) || (":".equals(c)) || "<".equals(c) || "%".equals(c) || "#".equals(c)))// name of internal node!!!!
+				c = readNamedInternal(TreeDescription, c, root, stringLoc);
+			while (":".equals(c) || "<".equals(c)|| "%".equals(c) || "#".equals(c)) {
+				if (":".equals(c)) {
+					readLength(TreeDescription, root, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+					if (!expectedPunctuation(c)) {
+						intializeTree();
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 7");
+						return false;
+					}
+				}
+				else if ("%".equals(c)||"#".equals(c)) {
+					skipValue(TreeDescription, root, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+					if (!expectedPunctuation(c)) {
+						intializeTree();
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 8");
+						return false;
+					}
+				}
+				else if ("<".equals(c)) {
+					readAssociated(TreeDescription, root, stringLoc);
+					c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+					if (!(c!=null && ":".equals(c)) && !expectedPunctuation(c)) {
+						intializeTree();
+						MesquiteMessage.warnProgrammer("bad token in tree where ,  ) ; expected (" + c + ") 9");
+						return false;
+					}
+					if ("<".equals(c)){
+						readAttachedProperties(TreeDescription, stringLoc);
+						c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+					}
+					if ("<".equals(c)){
+						readExtras(TreeDescription, stringLoc);
+						c = ParseUtil.getToken(TreeDescription, stringLoc, whitespaceString, punctuationString);  //skip comma or parens
+					}
+				}
+			}
+		}
+		selected = getWhichAssociatedBits(NameReference.getNameReference("selected"));
+		checkAssociated();
+		exists=true;
+		if (!checkTreeIntegrity(root)) {
+			intializeTree();
+			MesquiteMessage.warnProgrammer("tree failed integrity check");
+			return false;
+		}
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,true);
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Sets the tree to be a default bush.*/
+	public void setToDefaultBush(Bits whichTaxa, boolean notify) {
+		int numTaxa = whichTaxa.numBitsOn();
+		if (numTaxa == 0)
+			return;
+		String temp = "(";
+		boolean first=true;
+		for (int it=0; it<whichTaxa.getSize(); it++) {
+			if (whichTaxa.isBitOn(it)){
+				if (first)
+					first=false;
+				else
+					temp+=",";
+				temp+=Integer.toString(Taxon.toExternal(it));
+			}
+		}
+		temp+=");";
+		readTree(temp);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		setName("Default Bush");
+	}
+	/*-----------------------------------------*/
+	/** Sets the tree to be a default bush.*/
+	public void setToDefaultBush(int numTaxa, boolean notify) {
+		if (numTaxa == 0)
+			return;
+		String temp = "(";
+		boolean first=true;
+		for (int it=0; it<numTaxa; it++) {
+			if (first)
+				first=false;
+			else
+				temp+=",";
+			temp+=Integer.toString(Taxon.toExternal(it));
+		}
+		temp+=");";
+		readTree(temp);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		setName("Default Bush");
+	}
+	/*-----------------------------------------*/
+	/** Sets the tree to be a default ladder.*/
+	public void setToDefaultLadder(int numTaxa, boolean notify) {
+		String temp = "";
+		for (int it=0; it<numTaxa-1; it++) 
+			temp+="("+ Taxon.toExternal(it) +",";
+		temp+=Taxon.toExternal(numTaxa-1);
+		for (int it=0; it<numTaxa-1; it++)
+			temp+=")";
+		temp+=";";
+		readTree(temp);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		setName("Default Ladder");
+	}
+	/*.................................................................................................................*/
+	void formSymmetricalClade( int minTaxon, int maxTaxon){
+		int range = maxTaxon-minTaxon + 1;
+		if (range > 1) {
+			int newRight = minTaxon + range/2;
+			splitTerminal(minTaxon, newRight, false);
+			formSymmetricalClade(minTaxon, newRight -1);
+			formSymmetricalClade(newRight, maxTaxon);
+		}
+	}
+	public void setToDefaultSymmetricalTree(int numTaxa, boolean notify) {
+		if (numTaxa == 1){
+			setToDefaultBush(1, false);
+			return;
+		}
+		setToDefaultBush(2, false);
+		int secondHalf = numTaxa/2;
+		int rightNode = nextSisterOfNode(firstDaughterOfNode(getRoot()));
+		setTaxonNumber(rightNode, secondHalf, false);
+		formSymmetricalClade(0, secondHalf-1);
+		formSymmetricalClade(secondHalf, numTaxa-1);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		setName("Default Symmetrical Tree");
+	}
+	/*-----------------------------------------*/
+	/*.........................................Write tree.................................................*/
+	/** Writes a tree description into the StringBuffer using taxon numbers instead of labels or taxon names */
+	private void writeTreeByNumbersGeneral(int node, StringBuffer treeDescription, boolean includeAssociated, boolean includeBranchLengths, boolean includeNodeLabels, boolean zeroBased, String delimiter) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByNumbersGeneral(thisSister, treeDescription, includeAssociated, includeBranchLengths, includeNodeLabels,  zeroBased, delimiter);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				if (delimiter!=null)
+					treeDescription.append(delimiter);
+				else
+					treeDescription.append(' ');
+				writeTreeByNumbersGeneral(thisSister, treeDescription, includeAssociated, includeBranchLengths, includeNodeLabels,  zeroBased,  delimiter);
+			}
+			treeDescription.append(')');
+			if (includeNodeLabels && nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else if (zeroBased)
+			treeDescription.append(Integer.toString(taxonNumberOfNode(node)));
+		else
+			treeDescription.append(Integer.toString(Taxon.toExternal(taxonNumberOfNode(node))));
+		if (includeBranchLengths && !branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (includeAssociated){
+			String a = writeAssociated(node, true);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon names */
+	private void writeTreeByNamesGeneral(int node, StringBuffer treeDescription, boolean includeAssociated, boolean includeBranchLengths,  boolean includeNodeLabels, String delimiter) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByNamesGeneral(thisSister, treeDescription, includeAssociated, includeBranchLengths, includeNodeLabels,  delimiter);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				if (delimiter!=null)
+					treeDescription.append(delimiter);
+				else
+					treeDescription.append(' ');
+				writeTreeByNamesGeneral(thisSister, treeDescription, includeAssociated, includeBranchLengths, includeNodeLabels,  delimiter);
+			}
+			treeDescription.append(')');
+			if (includeNodeLabels && nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else {
+			treeDescription.append(StringUtil.tokenize(taxa.getTaxonName(taxonNumberOfNode(node))));
+		}
+		if (includeBranchLengths && !branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (includeAssociated){
+			String a = writeAssociated(node, true);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the tree in standard parenthesis notation (Newick standard), using taxon
+	names or numbers to refer to the taxa, depending on the boolean parameter byNames.*/
+	public String writeTreeSimple(int byWhat, boolean includeAssociated, boolean includeBranchLengths, boolean includeNodeLabels, boolean zeroBased, String delimiter) {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		if (byWhat == BY_NAMES)
+			writeTreeByNamesGeneral(root, s, includeAssociated, includeBranchLengths,  includeNodeLabels, delimiter);
+		else if (byWhat == BY_NUMBERS)
+			writeTreeByNumbersGeneral(root, s, includeAssociated, includeBranchLengths,  includeNodeLabels, zeroBased, delimiter);
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree into the string buffer, placing node numbers in comments after the nodes */
+	private void writeTreeByNumbersWithNodeNumbers(int node, StringBuffer treeDescription, boolean suppressAssociated) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByNumbersWithNodeNumbers(thisSister, treeDescription, suppressAssociated);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeByNumbersWithNodeNumbers(thisSister, treeDescription, suppressAssociated);
+			}
+			treeDescription.append(')');
+			if (nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+			treeDescription.append("[" + node + "]");
+		}
+		else {
+			treeDescription.append(Integer.toString(Taxon.toExternal(taxonNumberOfNode(node))));
+			treeDescription.append("[" + node + "]");
+		}
+		if (!branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (!suppressAssociated){
+			String a = writeAssociated(node, false);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon numbers instead of labels or taxon names */
+	private void writeTreeByNumbers(int node, StringBuffer treeDescription, boolean includeAssociated, boolean associatedUseComments) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByNumbers(thisSister, treeDescription, includeAssociated, associatedUseComments);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeByNumbers(thisSister, treeDescription,includeAssociated, associatedUseComments);
+			}
+			treeDescription.append(')');
+			if (nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else {
+			treeDescription.append(Integer.toString(Taxon.toExternal(taxonNumberOfNode(node))));
+		}
+		if (!branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (includeAssociated){
+			String a = writeAssociated(node, associatedUseComments);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon names in simple style: t0, t1, t2, etc. */
+	private void writeTreeByT0Names(int node, StringBuffer treeDescription, boolean includeBranchLengths) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByT0Names(thisSister, treeDescription, includeBranchLengths);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeByT0Names(thisSister, treeDescription,includeBranchLengths);
+			}
+			treeDescription.append(')');
+		}
+		else {
+			treeDescription.append("t" + taxonNumberOfNode(node));
+		}
+		if ( includeBranchLengths && !branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon names in simple style: t0, t1, t2, etc. */
+	public String writeTreeByT0Names(boolean includeBranchLengths) {
+		StringBuffer tD = new StringBuffer(10);
+		writeTreeByT0Names(getRoot(), tD, includeBranchLengths);
+		return tD.toString();
+			
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon names */
+	private void writeTreeByNames(int node, StringBuffer treeDescription, boolean includeBranchLengths, boolean includeAssociated, boolean associatedUseComments) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByNames(thisSister, treeDescription, includeBranchLengths, includeAssociated, associatedUseComments);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeByNames(thisSister, treeDescription,includeBranchLengths, includeAssociated, associatedUseComments);
+			}
+			treeDescription.append(')');
+			if (nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else {
+			treeDescription.append(StringUtil.tokenize(taxa.getTaxonName(taxonNumberOfNode(node))));
+		}
+		if ( includeBranchLengths && !branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (includeAssociated){
+			String a = writeAssociated(node, associatedUseComments);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using translation table labels if available */
+	private void writeTreeByLabels(int node, StringBuffer treeDescription, boolean associatedUseComments) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeByLabels(thisSister, treeDescription, associatedUseComments);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeByLabels(thisSister, treeDescription, associatedUseComments);
+			}
+			treeDescription.append(')');
+			if (nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else {
+			if (treeVector !=null){//use treeVector's translation table if one is available
+				treeDescription.append(treeVector.getTranslationLabel(taxonNumberOfNode(node))); 
+			}
+			else
+				treeDescription.append(Integer.toString(Taxon.toExternal(taxonNumberOfNode(node))));
+		}
+		if (!branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			String bL = MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1);
+			treeDescription.append(bL); //add -1 to signal full accuracy 17 Dec 01
+		}
+		String a = writeAssociated(node, associatedUseComments);
+		treeDescription.append(a);
+	}
+	/*-----------------------------------------*/
+	/** Outputs as string; currently returns name if the tree exists, otherwise calls super.toString() */
+	public String toString(){
+		if (!exists)
+			return super.toString();
+		return getName() + " (id " + getID() + ", version " + getVersionNumber() + ")"; //writeTree(BY_NAMES);
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the tree in standard parenthesis notation (Newick standard), using taxon
+	numbers to refer to the taxa.*/
+	public String writeTreeWithNodeNumbers() {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*20);
+		writeTreeByNumbersWithNodeNumbers(root, s, true);
+		writeTreeProperties(s, true);
+
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the tree in standard parenthesis notation (Newick standard), using taxon
+	numbers to refer to the taxa.*/
+	public String writeTree() {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		writeTreeByNumbers(root, s, true, true);
+		writeTreeProperties(s, true);
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Returns a simple string describing the tree in standard parenthesis notation (Newick standard), excluding associated information except branch lengths.
+	To be used for output to user, not internally (as it may lose information).*/
+	public String writeTreeSimpleByNames() {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		writeTreeByNames(root, s, true, false, false);
+		//writeTreeProperties(s, true);
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Returns a simple string describing the tree in standard parenthesis notation (Newick standard), excluding associated information except branch lengths.
+	To be used for output to user, not internally (as it may lose information).*/
+	public String writeTreeSimpleByNumbers() {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		writeTreeByNumbers(root, s, false, false);
+		//writeTreeProperties(s, true);
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer using taxon names */
+	private void writeTreeWithNamer(int node, StringBuffer treeDescription, TaxonNamer namer, boolean includeBranchLengths, boolean includeAssociated, boolean associatedUseComments) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTreeWithNamer(thisSister, treeDescription, namer, includeBranchLengths, includeAssociated, associatedUseComments);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTreeWithNamer(thisSister, treeDescription,  namer, includeBranchLengths, includeAssociated, associatedUseComments);
+			}
+			treeDescription.append(')');
+			if (nodeHasLabel(node))
+				treeDescription.append(StringUtil.tokenize(getNodeLabel(node)));
+		}
+		else {
+			treeDescription.append(StringUtil.tokenize(namer.getNameToUse(taxa, taxonNumberOfNode(node))));
+		}
+		if ( includeBranchLengths && !branchLengthUnassigned(node)) {
+			treeDescription.append(':');
+			treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node), -1)); //add -1 to signal full accuracy 17 Dec 01
+		}
+		if (includeAssociated){
+			String a = writeAssociated(node, associatedUseComments);
+			treeDescription.append(a);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns a Newick tree with taxon names supplied by TaxonNamer, e.g. so that modules may use their own codes for taxa.*/
+	public String writeTreeWithNamer(TaxonNamer namer, boolean includeBranchLengths, boolean includeAssocAndProperties) {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		writeTreeWithNamer(root, s, namer, includeBranchLengths, includeAssocAndProperties, true);
+		if (includeAssocAndProperties)
+			writeTreeProperties(s, true);
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the tree in standard parenthesis notation (Newick standard), using taxon
+	names or numbers to refer to the taxa, depending on the boolean parameter byNames.*/
+	public String writeTree(int byWhat) {
+		return writeTree(byWhat, true);
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the clade in standard parenthesis notation (Newick standard), using taxon
+	names or numbers to refer to the taxa, depending on the boolean parameter byNames.*/
+	public String writeClade(int node, int byWhat, boolean associatedUseComments) {
+		StringBuffer s = new StringBuffer(numberOfNodesInClade(root)*40);
+		if (byWhat == BY_NAMES)
+			writeTreeByNames(node, s, true, true, associatedUseComments);
+		else if (byWhat == BY_NUMBERS)
+			writeTreeByNumbers(node, s, true, associatedUseComments);
+		else if (byWhat == BY_TABLE)
+			writeTreeByLabels(node, s, associatedUseComments);
+		writeTreeProperties(s, associatedUseComments);
+		s.append(';');
+		return s.toString();
+	}
+	/*-----------------------------------------*/
+	/** Returns a string describing the tree in standard parenthesis notation (Newick standard), using taxon
+	names or numbers to refer to the taxa, depending on the boolean parameter byNames.*/
+	public String writeTree(int byWhat, boolean associatedUseComments) {
+		return writeClade(root, byWhat, associatedUseComments);
+	}
+	/*-----------------------------------------*/
+	private void writeTreeProperties(StringBuffer sb, boolean useComments){
+		String spref = "";
+		if (StringUtil.blank(writeAssociated(root, useComments))){ //if nothing at root put dummy so second will be tree properties
+			if (useComments)
+				spref = "[% ]"; 
+			else
+				spref = "<>";
+		}
+		MesquiteBoolean mb = null;
+		MesquiteBoolean mr = null;
+		if (!getRooted()) {
+			mr = new MesquiteBoolean(!getRooted());
+			mr.setName("unrooted");
+			attachIfUniqueName(mr);
+		}
+		if (polytomiesHard == 0 || polytomiesHard == 1) {
+			mb = new MesquiteBoolean(polytomiesHard==0);
+			mb.setName("polytomiesHard");
+			attachIfUniqueName(mb);
+		}
+		String s = writeAttachments(useComments);
+		String sprefpref = "";
+		if (StringUtil.blank(s)){
+			if (useComments)
+				sprefpref = "[% ]"; 
+			else
+				sprefpref = "<>";
+		}
+		else 
+			sprefpref = s;
+		if (mb !=null) {
+			detach(mb);
+		}
+		if (mr !=null) {
+			detach(mr);
+		}
+		if (s ==null || s.length()>0) {
+			sb.append(spref + " " + s);
+			spref = "";
+		}
+		String b = writeAssociatedBetweenness();
+		if (!StringUtil.blank(b)){
+			sb.append(spref + " " + sprefpref + " ");
+			if (useComments)
+				sb.append("[% " + b + " ]"); 
+			else
+				sb.append("< " + b + " >"); 
+		}
+
+	}
+	/*-----------------------------------------*/
+	private void readAttachedProperties(String TreeDescription, MesquiteInteger stringLoc){
+		readAttachments(TreeDescription, stringLoc);
+		Object or = getAttachment("unrooted");
+		Object ob = getAttachment("polytomiesHard");
+
+		MesquiteBoolean mr = null;
+		MesquiteBoolean mb = null;
+		if (or instanceof MesquiteBoolean)
+			mr = (MesquiteBoolean)or;
+		if (ob instanceof MesquiteBoolean)
+			mb = (MesquiteBoolean)ob;
+		if (mr !=null){
+			setRooted(!mr.getValue(), false);
+			detach(mr);
+		}
+		if (mb !=null){
+			if (mb.getValue())
+				setPolytomiesAssumption(0, false);
+			else
+				setPolytomiesAssumption(1, false);
+			detach(mb);
+		}
+	}
+	public void readExtras(String assocString, MesquiteInteger pos){
+		//assumes already past "<";
+		String key=ParseUtil.getToken(assocString, pos);
+		while (!">".equals(key)) {
+			if (StringUtil.blank(key))
+				return;
+			String tok = ParseUtil.getToken(assocString, pos); //eating up equals
+			int oldPos = pos.getValue();
+			String value = ParseUtil.getToken(assocString, pos); //finding value
+			if (StringUtil.blank(value))
+				return;
+			if (key.equalsIgnoreCase("setBetweenBits")) {
+				NameReference nRef = NameReference.getNameReference(value);
+				Bits b = getWhichAssociatedBits(nRef);
+				if (b != null)
+					b.setBetweenness(true);
+			}
+			else if (key.equalsIgnoreCase("setBetweenLong")) {
+				NameReference nRef = NameReference.getNameReference(value);
+				LongArray b = getWhichAssociatedLong(nRef);
+				if (b != null)
+					b.setBetweenness(true);
+			}
+			else if (key.equalsIgnoreCase("setBetweenDouble")) {
+				NameReference nRef = NameReference.getNameReference(value);
+				DoubleArray b = getWhichAssociatedDouble(nRef);
+				if (b != null)
+					b.setBetweenness(true);
+			}
+			else if (key.equalsIgnoreCase("setBetweenObject")) {
+				NameReference nRef = NameReference.getNameReference(value);
+				ObjectArray b = getWhichAssociatedObject(nRef);
+				if (b != null)
+					b.setBetweenness(true);
+			}
+			key=ParseUtil.getToken(assocString, pos);
+			if (",".equals(key)) //eating up "," separating subcommands
+				key=ParseUtil.getToken(assocString, pos);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Branches a terminal node off taxon number taxonNum, and assigns it taxon newNumber.  If newNumber < 0, then assign next available taxon not in tree  */
+	public synchronized void splitTerminal(int taxonNum, int newNumber, boolean notify) {
+		int node = nodeOfTaxonNumber(taxonNum);
+		if (nodeExists(node)) {
+			int N1= sproutDaughter(node, notify);
+			setTaxonNumber(N1, taxonNum, false);
+			int N2= sproutDaughter(node, notify);
+			if (newNumber<0){
+				for (int it = 0; it< taxa.getNumTaxa(); it++){
+					if (!taxonInTree(it)){  // found taxon not in tree
+						newNumber = it;
+						break;
+					}
+				}
+			}
+			setTaxonNumber(N2, newNumber, false);
+			setTaxonNumber(node, -1, false);
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		}
+
+	}
+	/*-----------------------------------------*/
+	/** Sprouts a new daughter from node and returns it. */
+	public synchronized int sproutDaughter(int node, boolean notify) {
+		if (!nodeExists(node))
+			return 0;
+		int op = openNode();
+		if (op == 0)
+			return 0;
+		mother[op] = node;
+
+		if (!nodeExists(firstDaughterOfNode(node)))
+			firstDaughter[node] = op;
+		else
+			nextSister[lastDaughterOfNode(node)] = op;
+		if (branchLength!=null)
+			branchLength[op] = MesquiteDouble.unassigned; //add 1. 1 just in case
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return op;
+	}
+
+	/*-----------------------------------------*/
+	//VIRTUAL DELETION. See also LEGAL system as an alternative
+	/** Marks taxon (and any nodes required by it) as deleted virtually in the boolean array.  Used in conjunction with subsequent
+	 * traversals that ignore the deleted area, e.g. for ignoring taxa with missing data.*/
+	public void virtualDeleteTaxon(int it, boolean[] deleted){
+		if (deleted == null)
+			return;
+		int node = nodeOfTaxonNumber(it);
+		int mother = motherOfNode(node);
+		if (!nodeExists(node) || node >= deleted.length || mother >= deleted.length)
+			return;
+		deleted[node] = true;
+		virtualDeleteReviewClades(getRoot(), deleted);
+		virtualDeleteReviewAttachPoints(getRoot(), deleted);
+
+	}
+	/*-----------------------------------------*/
+	/* Ensures that virtual deletion doesn't leave orphaned internal nodes*/
+	private void virtualDeleteReviewClades(int node, boolean[] deleted){
+		boolean allDescDeleted = true;
+		if (nodeIsTerminal(node))
+			return;
+		if (node < deleted.length)
+			deleted[node] = false;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)){
+			virtualDeleteReviewClades(d, deleted);
+			if (d < deleted.length && !deleted[d])
+				allDescDeleted = false;
+		}
+		if (allDescDeleted && node < deleted.length)
+			deleted[node] = true;
+
+	}
+	/*-----------------------------------------*/
+	/* Ensures that virtual deletion doesn't leave orphaned internal nodes*/
+	private void virtualDeleteReviewAttachPoints(int node, boolean[] deleted){
+		if (nodeIsTerminal(node))
+			return;
+		int numNotDeleted = 0;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)){
+			if (d < deleted.length && !deleted[d])
+				numNotDeleted++;
+			virtualDeleteReviewAttachPoints(d, deleted);
+		}
+		if (numNotDeleted<2)
+			deleted[node] = true;
+
+	}
+	/*-----------------------------------------*/
+	/** Writes a tree description into the StringBuffer, filtering virtually deleted nodes */
+	public void writeTree(int node, StringBuffer treeDescription, boolean[] deleted) {
+		if (nodeIsInternal(node)) {
+			treeDescription.append('(');
+			int thisSister = firstDaughterOfNode(node);
+			writeTree(thisSister, treeDescription, deleted);
+			while (nodeExists(thisSister = nextSisterOfNode(thisSister))) {
+				treeDescription.append(',');
+				writeTree(thisSister, treeDescription, deleted);
+			}
+			treeDescription.append(')');
+		}
+		else {
+			treeDescription.append(Integer.toString(Taxon.toExternal(taxonNumberOfNode(node))));
+		}
+		if (deleted != null && node < deleted.length && deleted[node])
+			treeDescription.append("*");
+		//if (!branchLengthUnassigned(node, deleted)) {
+		treeDescription.append(':');
+		treeDescription.append(MesquiteDouble.toStringDigitsSpecified(getBranchLength(node, 1.0, deleted), -1)); //add -1 to signal full accuracy 17 Dec 01
+		//}
+	}
+	/*-----------------------------------------*/
+	/** Returns the root of the tree (i.e., the most recent common ancestor of the terminal taxa in the tree.*/
+	public int getRoot(boolean[] deleted) {
+		if (deleted == null)
+			return root;
+		return findFirstNonDeleted(root, -1, deleted);
+	}
+	/*-----------------------------------------*/
+	/** Returns whether root is a real node, considering virtually deleted nodes.*/
+	public boolean rootIsReal(boolean[] deleted) {
+		if (deleted == null)
+			return rootIsReal();
+		if (root < deleted.length && deleted[root])
+			return true;
+		return rootIsReal();
+	}
+	/*-----------------------------------------*/
+	/** Returns the first (left-most) daughter of node filtering virtuallyDeleted nodes.*/
+	public  int firstDaughterOfNode(int node, boolean[] deleted) {
+		if (deleted == null)
+			return firstDaughterOfNode(node);
+		if (!inBounds(node) || node >= deleted.length || deleted[node])
+			return 0;
+		return findFirstNonDeleted(node, node, deleted);
+		/*int d = node;
+		while ((d = firstDaughter[d])!= 0){
+			 if (d < deleted.length && !deleted[d])
+				return d;
+		}
+		return 0;*/
+	}
+	/*-----------------------------------------*/
+	/** Returns the right-most daughter of node, filtering virtually deleted nodes.*/
+	public int lastDaughterOfNode(int node, boolean[] deleted) {
+		if (deleted == null)
+			return lastDaughterOfNode(node);
+		if (!inBounds(node))
+			return 0;
+		int thisSister = firstDaughterOfNode(node, deleted);
+		while (nodeExists(nextSisterOfNode(thisSister, deleted)))
+			thisSister = nextSisterOfNode(thisSister, deleted);
+		return thisSister;
+	}
+	/*-----------------------------------------*/
+	/* finding first non deleted in traversal*/
+	private int findFirstNonDeleted(int node, int exceptThisNode, boolean[] deleted){
+		if (node != exceptThisNode && node < deleted.length && !deleted[node])
+			return node;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)){
+			int n = findFirstNonDeleted(d, exceptThisNode, deleted);
+			if (n != 0)
+				return n;
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the node's sister immediately to the right, filtering virtually deleted nodes.*/
+	public  int nextSisterOfNode(int node, boolean[] deleted) {
+		if (deleted == null)
+			return nextSisterOfNode(node);
+		if (!inBounds(node) || node >= deleted.length || deleted[node])
+			return 0;
+		int mn = node;
+		while (mn!=0){ 
+			int d = mn;
+
+			while ((d = nextSisterOfNode(d))!= 0){
+				int n = findFirstNonDeleted(d, -1, deleted);
+				if (n != 0)
+					return n; 
+			}
+			//unsuccessful; go to next level of cousin
+			mn = motherOfNode(mn);
+			if (mn< deleted.length && !deleted[mn])//mn exists, thus ran out of chances
+				return 0;
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the node's sister immediately to the left, filtering virtually deleted nodes.*/
+	public int previousSisterOfNode(int node, boolean[] deleted) {
+		if (deleted == null)
+			return previousSisterOfNode(node);
+		if (!inBounds(node))
+			return 0;
+		int thisSister = firstDaughterOfNode(motherOfNode(node, deleted),  deleted);
+		if (node==thisSister)
+			return 0;
+		int lastSister;
+		while (nodeExists(thisSister)) {
+			lastSister=thisSister;
+			thisSister = nextSisterOfNode(thisSister,  deleted);
+			if (thisSister==node)
+				return lastSister;
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the immediate ancestor of node (mother) if node is non-reticulate, filtering virtually deleted nodes*/
+	public  int motherOfNode(int node, boolean[] deleted) {
+		if (deleted == null)
+			return motherOfNode(node);
+		if (!inBounds(node) || node >= deleted.length || deleted[node])
+			return 0;
+		int d = node;
+		while ((d = mother[d])!= 0){
+			if (d == getRoot(deleted))
+				return d;
+			if (d < deleted.length && !deleted[d])
+				return d;
+		}
+		return 0;
+	}
+	/*-----------------------------------------*/
+	/** Returns the branch length of the node, filtered by virtual deletion of nodes.*/
+	public  double getBranchLength(int node, boolean[] deleted) {
+		return getBranchLength(node, MesquiteDouble.unassigned, deleted);
+	}
+	/*-----------------------------------------*/
+	/** Returns the branch length of the node.  If the branch length is unassigned, pass back the double passed in, filtered by virtual deletion of nodes*/
+	public  double getBranchLength(int node, double ifUnassigned, boolean[] deleted) {
+		if (deleted == null)
+			return getBranchLength(node, ifUnassigned);
+		if (!inBounds(node) || node >= deleted.length || deleted[node])
+			return ifUnassigned;
+		if (branchLength==null)
+			return ifUnassigned;
+		int d = node;
+		double sum = MesquiteDouble.unassigned;
+		int mom = motherOfNode(node, deleted);
+		if (mom == 0)
+			return ifUnassigned;
+		while ( d != mom ) {  //bug fixed June 08 by R. FitzJohn
+			sum = MesquiteDouble.add(sum, branchLength[d]);
+			d = mother[d];
+		}
+		if (MesquiteDouble.isUnassigned(sum))
+			return ifUnassigned;
+		else
+			return sum;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether branch length of node is unassigned, filtering virtually deleted nodes.*/
+	public  boolean branchLengthUnassigned(int node, boolean[] deleted) { 
+		if (deleted == null)
+			return branchLengthUnassigned(node);
+		if (!inBounds(node))
+			return true;
+		double b = getBranchLength(node, deleted);
+		return MesquiteDouble.isUnassigned(b);
+	}
+	/*-----------------------------------------*/
+	private int lowestValuedTerminal(int node){
+		if (nodeIsTerminal(node))
+			return taxonNumberOfNode(node);
+		int min = lowestValuedTerminal(firstDaughterOfNode(node));
+		for (int d = nextSisterOfNode(firstDaughterOfNode(node)); nodeExists(d); d = nextSisterOfNode(d)) {
+			int dT = lowestValuedTerminal(d);
+			if (dT<min)
+				min = dT;
+		}
+		return min;
+	}
+	private boolean firstSortsAfter(int firstNode, int secondNode, boolean leftToRight){
+		int fN = numberOfTerminalsInClade(firstNode);
+		int sN = numberOfTerminalsInClade(secondNode);
+		if (leftToRight){
+			if (fN>sN)
+				return true;
+			else if (sN>fN)
+				return false;
+			else 
+				return lowestValuedTerminal(firstNode) > lowestValuedTerminal(secondNode);
+		}
+		else {
+			if (fN<sN)
+				return true;
+			else if (sN<fN)
+				return false;
+			else 
+				return lowestValuedTerminal(firstNode) < lowestValuedTerminal(secondNode);
+		}
+	}
+
+	private synchronized void sortDescendants(int node, boolean leftToRight){
+		if (nodeIsTerminal(node))
+			return;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			sortDescendants(d, leftToRight);
+		int numDaughters = numberOfDaughtersOfNode(node);
+		for (int i=1; i<numDaughters; i++) {
+			for (int j= i-1; j>=0 && firstSortsAfter(indexedDaughterOfNode(node, j), indexedDaughterOfNode(node, j+1), leftToRight); j--) {
+				interchangeBranches(indexedDaughterOfNode(node, j), indexedDaughterOfNode(node, j+1), false);
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of a randomly chosen node.*/
+	public int randomNode(RandomBetween rng, boolean allowRoot){
+		int candidate = -1;
+		while (!(nodeExists(candidate) && getSubRoot()!=candidate && (getRoot()!=candidate || allowRoot))) {
+			candidate = rng.randomIntBetween(0, getNumNodeSpaces());
+		}
+		return candidate;
+	}
+
+	/*-----------------------------------------*/
+	private synchronized void randomizeDescendants(int node, Random rng){
+		if (nodeIsTerminal(node))
+			return;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			randomizeDescendants(d, rng);
+
+		int numDaughters = numberOfDaughtersOfNode(node);
+		int[] order = new int[numDaughters];
+		IntegerArray.fillWithRandomOrderValues(order, rng);
+		for (int i=0; i<numDaughters; i++) {
+			int positionOfDaughter = -1;
+			for (int j=i; j<numDaughters && positionOfDaughter<0; j++) {
+				if (order[j]==i) // we've found the next one, and it is at j
+					positionOfDaughter=j;
+			}
+			if (i!=positionOfDaughter)
+				interchangeBranches(indexedDaughterOfNode(node, i), indexedDaughterOfNode(node, positionOfDaughter), false);
+		}
+	}
+
+	/*-----------------------------------------*/
+	/** Puts clade in random arrangement.*/
+	public synchronized boolean randomlyRotateDescendants(int node, Random rng, boolean notify){
+		randomizeDescendants(node, rng);
+		checkTreeIntegrity(getRoot());
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Puts clade in standard arrangement, such that smaller clades to left, 
+	and if sister clades have same number of terminals, then with one with lowest numbered terminal to left.*/
+	public synchronized boolean standardize(int node, boolean notify){
+		return standardize(node, true, notify);
+	}
+	/*-----------------------------------------*/
+	/** Puts clade in standard arrangement, such that smaller clades to left (or right, depending on boolean passed), 
+	and if sister clades have same number of terminals, then with one with lowest numbered terminal to left (or right).*/
+	public synchronized boolean standardize(int node, boolean leftToRight, boolean notify){
+		sortDescendants(node, leftToRight);
+		checkTreeIntegrity(root);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Puts clade in standard arrangement, such that smaller clades to left (or right, depending on boolean passed), 
+	and if sister clades have same number of terminals, then with one with lowest numbered terminal to left (or right).*/
+	public synchronized boolean standardize(TaxaSelectionSet taxonSet, boolean notify){
+		MesquiteInteger descendantBoundary = new MesquiteInteger();
+		if (taxonSet==null) {
+			for (int i=0; i<getNumTaxa(); i++) { // find lowest number taxon that is in the tree
+				if (taxonInTree(i)) {
+					int atBranch = nodeOfTaxonNumber(i);   
+					reroot(atBranch, getRoot(), false);
+					break;
+				}
+			}
+		}
+		else if (isConvex(taxonSet.getBits(), descendantBoundary)) {
+			if (descendantBoundary.isCombinable())
+				reroot(descendantBoundary.getValue(), getRoot(), false);
+			else 
+				for (int i=0; i<getNumTaxa(); i++) { // find lowest number taxon that is in the tree
+					if (taxonInTree(i)) {
+						int atBranch = nodeOfTaxonNumber(i);
+						reroot(atBranch, getRoot(), false);
+						break;
+					}
+				}
+		}
+		else
+
+			for (int i=0; i<getNumTaxa(); i++) { // find lowest number taxon that is in the set
+				if (taxonInTree(i) && taxonSet.isBitOn(i)) {
+					int atBranch = nodeOfTaxonNumber(i);
+					reroot(atBranch, getRoot(), false);
+					break;
+				}
+			}
+		return standardize(getRoot(), true, notify);
+	}
+
+	private synchronized void focalSortDescendants(int node, int focalNode, boolean leftToRight, boolean extremeAlreadySorted){
+		if (nodeIsTerminal(node))
+			return;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d))
+			focalSortDescendants(d, focalNode, leftToRight, extremeAlreadySorted);
+		int numDaughters = numberOfDaughtersOfNode(node);
+		int startDaughter = 1;
+		int endDaughter = numDaughters;
+		if (extremeAlreadySorted && descendantOf(focalNode,node)) {
+			if (leftToRight)
+				endDaughter--;
+			else if (!leftToRight )
+				startDaughter++;
+		}
+		for (int i=startDaughter; i<endDaughter; i++) {
+			for (int j= i-1; j>=startDaughter-1&& firstSortsAfter(indexedDaughterOfNode(node, j), indexedDaughterOfNode(node, j+1), leftToRight); j--) {
+				interchangeBranches(indexedDaughterOfNode(node, j), indexedDaughterOfNode(node, j+1), false);
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	/** Puts clade in standard arrangement, such that focalTaxon is to left (or right, depending on boolean passed). */
+	public synchronized boolean focalStandardize(int focalTaxon, boolean leftToRight, boolean notify){
+		int focalNode = nodeOfTaxonNumber(focalTaxon);
+		int node = focalNode;
+		while (node!=getSubRoot() && nodeExists(node)) {
+			int motherNode = motherOfNode(node);
+			if (motherNode>0)
+				if (!leftToRight &&  node!= firstDaughterOfNode(motherNode))
+					interchangeBranches(firstDaughterOfNode(motherNode), node, false);
+				else if (leftToRight &&  node!= lastDaughterOfNode(motherNode))
+					interchangeBranches(lastDaughterOfNode(motherNode), node, false);
+			node = motherOfNode(node);
+		}
+
+
+		focalSortDescendants(root, focalNode, leftToRight, true);
+		checkTreeIntegrity(root);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Interchanges two branches of tree.*/
+	public synchronized boolean interchangeBranches(int node, int otherNode, boolean notify) {   
+		return interchangeBranches(node, otherNode, false, notify);
+	}
+	/*-----------------------------------------*/
+	/** Interchanges two branches of tree.*/
+	public synchronized boolean interchangeBranches(int node, int otherNode, boolean preserveHeights, boolean notify) {   
+		if (!nodeExists(node) || !nodeExists(otherNode))
+			return false;
+		if (node==otherNode)
+			return false;
+		else if  (descendantOf(node,otherNode) || descendantOf(otherNode,node))
+			return false;
+		double oldNodeHeight = 0;
+		double oldOtherNodeHeight = 0;
+		double oldNodeMotherHeight = 0;
+		double oldOtherNodeMotherHeight = 0;
+		if (preserveHeights){
+			oldNodeHeight = distanceToRoot(node, false, 0);
+			oldOtherNodeHeight = distanceToRoot(otherNode, false, 0);
+			oldNodeMotherHeight = distanceToRoot(motherOfNode(node), false, 0);
+			oldOtherNodeMotherHeight = distanceToRoot(motherOfNode(otherNode), false, 0);
+		}
+		if (nodeIsInternal(node) || nodeIsInternal(otherNode)) {
+			int nFD = firstDaughterOfNode(node);
+			int mFD = firstDaughterOfNode(otherNode);
+
+			for (int d = firstDaughterOfNode(node); nodeExists(d); d=nextSisterOfNode(d))
+				mother[d]=otherNode;  // trade first all the daughters
+			for (int d = firstDaughterOfNode(otherNode); nodeExists(d); d=nextSisterOfNode(d))
+				mother[d]=node;  // trade first all the daughters
+
+			firstDaughter[node]=mFD; 
+			firstDaughter[otherNode]=nFD;
+		}
+
+		if (branchLength!=null) {
+			double nL = branchLength[node];  // trade lengths
+			branchLength[node]=branchLength[otherNode];
+			branchLength[otherNode]=nL;
+		}
+		if (label!=null) {
+			String nL = label[node];  // trade lengths
+			label[node]=label[otherNode];
+			label[otherNode]=nL;
+		}
+		exchangeAssociated(node,otherNode);
+		boolean mIs = getSelected(otherNode);
+		setSelected(otherNode, getSelected(node));
+		setSelected(node, mIs);
+		int nN = taxonNumber[node];  // trade NUMBERS
+		taxonNumber[node]=taxonNumber[otherNode]; 
+		taxonNumber[otherNode]=nN; 
+		if (taxonNumber[otherNode]>=0)
+			nodeOfTaxon[taxonNumber[otherNode]] = otherNode;
+		if (taxonNumber[node]>=0)
+			nodeOfTaxon[taxonNumber[node]] = node;
+		if (preserveHeights){ 
+			if (MesquiteDouble.isCombinable(oldNodeHeight) && MesquiteDouble.isCombinable(oldOtherNodeHeight) && MesquiteDouble.isCombinable(oldNodeMotherHeight) && MesquiteDouble.isCombinable(oldOtherNodeMotherHeight)){
+
+				setBranchLength(otherNode, oldNodeHeight-oldOtherNodeMotherHeight, false);
+				setBranchLength(node, oldOtherNodeHeight-oldNodeMotherHeight, false);
+
+			}
+		}
+		checkTreeIntegrity(root);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Collapses branch to yield polytomy.*/
+	public synchronized boolean collapseBranch(int node, boolean notify) {   
+		if (!nodeExists(node))
+			return false;
+		if (nodeIsInternal(node) && (node!=root)) {
+			int pS = previousSisterOfNode(node);
+			if (MesquiteTrunk.trackActivity) System.out.println("collapse branch");
+			int sis = nextSisterOfNode(node);
+			int d = firstDaughterOfNode(node);
+
+			while (nodeExists(d)) {	// connecting all Daughters to their grandmother
+				if (!branchLengthUnassigned(node)){ //added post 1. 12 to preserve ultrametricity
+					if (branchLengthUnassigned(d))
+						branchLength[d] = branchLength[node];
+					else
+						branchLength[d] += branchLength[node];
+				}
+				mother[d] = motherOfNode(node);
+				d = nextSisterOfNode(d);
+
+			}
+			nextSister[lastDaughterOfNode(node)] = sis;
+			if (nodeIsFirstDaughter(node))
+				firstDaughter[motherOfNode(node)] = firstDaughterOfNode(node);
+			else 
+				nextSister[pS] = firstDaughterOfNode(node);
+			firstDaughter[node]=0;
+			nextSister[node]=0;
+			mother[node]=0;
+			setTaxonNumber(node, -1);
+			if (branchLength!=null)
+				branchLength[node] = MesquiteDouble.unassigned;
+			if (label !=null)
+				label[node] = null;
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+			return true;
+
+		}
+		else {
+			if (MesquiteTrunk.trackActivity) System.out.println("collapse branch failed");
+			return false;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Collapses all internal branches within clade above node, to yield bush.*/
+	private synchronized void inCollapseAllBranches(int node) {   
+		int d=firstDaughterOfNode(node);
+		while (nodeExists(d)) {
+			int nNS = nextSisterOfNode(d);
+			inCollapseAllBranches(d);
+			if (nodeIsInternal(d))
+				collapseBranch(d, false);
+			d = nNS;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Collapses all internal branches within tree BELOW node, to yield bush.*/
+	private synchronized void inCollapseAllBranchesUntilNode(int node, int endNode) {   
+		int d=firstDaughterOfNode(node);
+		while (nodeExists(d)) {
+			int nNS = nextSisterOfNode(d);
+			if (d!=endNode)
+				inCollapseAllBranchesUntilNode(d, endNode);
+			if (nodeIsInternal(d) && d!=endNode)
+				collapseBranch(d, false);
+			d = nNS;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Collapses all internal branches within clade above node, to yield bush.*/
+	public synchronized boolean collapseAllBranches(int node, boolean below, boolean notify) {   
+		if (!nodeExists(node))
+			return false;
+		if (below)
+			inCollapseAllBranchesUntilNode(root, node);
+		else
+			inCollapseAllBranches(node);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void reshuffleTerminals(RandomBetween rng){ 
+
+		int[] terminals = getTerminalTaxa(getRoot());
+		int numTerminals =numberOfTerminalsInClade(getRoot());
+		for (int fT = 0; fT < numTerminals-1; fT++) {
+			int firstTerminal = terminals[fT];
+			int secondTerminal = terminals[rng.randomIntBetween(fT,numTerminals-1)];
+
+			int firstTaxonNode = nodeOfTaxonNumber(firstTerminal);
+			int secondTaxonNode = nodeOfTaxonNumber(secondTerminal);
+			setTaxonNumber(secondTaxonNode,firstTerminal,false);
+			setTaxonNumber(firstTaxonNode,secondTerminal,false);
+
+		}
+		terminals = getTerminalTaxa(getRoot());
+	}
+	/*-----------------------------------------*/
+	private void zeroClade(int node){
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d=nextSisterOfNode(d)) {
+			zeroClade(d);
+		}
+		firstDaughter[node]=0;
+		nextSister[node] = 0;
+		mother[node]=0;
+		setTaxonNumber(node, -1);
+		if (label !=null)
+			label[node] = null;
+		deassignAssociated(node);
+	}
+	/** Excise node and clade above it from tree, zeroing information at each node in clade.*/
+	public synchronized boolean deleteClade(int node, boolean notify) {   
+		if (snipClade(node, notify)){
+			zeroClade(node);
+			return true;
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Excise node and clade above it from tree but leave the clade intact, in case it is to be attached elsewhere.*/
+	public synchronized boolean snipClade(int node, boolean notify) {   
+		if (node==root)
+			return false;
+		else {  // also prohibit if will be left fewer than three??
+			if (!nodeExists(node))
+				return false;
+			locked = true;
+			//int numSnipped = numberOfTerminalsInClade(node);
+			int mom = motherOfNode(node);
+			if (!nodeExists(mom))
+				return false;
+			if (numberOfDaughtersOfNode(mom)>2) {     //easy case; just pluck out
+				int sisterRight=nextSisterOfNode(node);
+				if (nodeIsFirstDaughter(node)) {
+					firstDaughter[mom] = sisterRight;
+				}
+				else {
+					int sisterLeft=previousSisterOfNode(node);
+					if (!nodeExists(sisterLeft))
+						return false;
+					nextSister[sisterLeft] = sisterRight;
+				}
+
+			}
+			else {// moving sister into mother's place
+				if (numberOfDaughtersOfNode(mom)==1) {     //cut down to 
+					while (mom != root && numberOfDaughtersOfNode(mom) == 1 && mom != 0){
+						node = mom;  //cut one deeper
+						mom = motherOfNode(mom);
+					}
+					if (!nodeExists(mom))
+						return false;
+					if (mom == root && numberOfDaughtersOfNode(mom)==1){
+						locked = false;
+						exists = false;
+						root = 0;
+						incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+						return true;
+					}
+				}
+				int sister;
+				if (nodeIsFirstDaughter(node)) 
+					sister = nextSisterOfNode(node);
+				else  
+					sister = previousSisterOfNode(node);
+				if (!nodeExists(sister))
+					return false;
+				if (hasBranchLengths()) { //remember length of branches to adjust afterward
+					MesquiteDouble lengthOfRemoved = new MesquiteDouble();
+					if (!nodeIsPolytomous(mom)){ // && mom != root) {  post-1.12: adds also for root
+						lengthOfRemoved.setValue(branchLength[mom]); //add length of mom;
+						lengthOfRemoved.add(branchLength[sister]); // add length of sister of branchFrom
+						setBranchLength(sister, lengthOfRemoved.getValue(), false);
+					}
+				}
+				int neice = firstDaughterOfNode(sister);
+				firstDaughter[mom] = firstDaughter[sister];
+				while (nodeExists(neice)) {
+					mother[neice] = mom;
+					neice = nextSisterOfNode(neice);
+				}
+
+				if (branchLength!=null)
+					branchLength[mom] = branchLength[sister];
+				taxonNumber[mom] = taxonNumber[sister]; 
+				if (taxonNumber[mom]>=0 && taxonNumber[mom]<nodeOfTaxon.length)
+					nodeOfTaxon[taxonNumber[mom]] = mom;
+				if (label!=null)
+					label[mom] = label[sister];
+				transferAssociated(sister, mom);
+
+				deassignAssociated(sister);
+				setSelected(mom, getSelected(sister));
+				setSelected(sister, false);
+				firstDaughter[sister]=0;
+				nextSister[sister]=0;
+				mother[sister]=0;
+				setTaxonNumber(sister, -1);
+				if (label!=null)
+					label[sister] = null;
+				if (branchLength!=null)
+					branchLength[sister] = MesquiteDouble.unassigned;
+			}
+			locked = false;
+
+			resetNodeOfTaxonNumbers();  //added Nov 2013
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+
+			return true;
+		}
+	}
+	/*................................................................................................................*/
+	/** Attach terminal taxon to tree along given branch.*/
+	public synchronized boolean graftTaxon(int taxon, int toN, boolean notify) {   
+		if (!nodeInTree(toN)) {
+			MesquiteMessage.warnProgrammer("ATTEMPT TO GRAFT ONTO NODE NOT IN TREE");
+			return false;
+		}
+		int fromN = openNode();
+		if (fromN==0)
+			return false;
+		mother[fromN] = -1;  //done some next openNode thinks it's not open
+		setTaxonNumber(fromN, taxon);
+		if (label!=null)
+			label[fromN] = null;
+		firstDaughter[fromN] = 0;
+		nextSister[fromN] = 0;
+		deassignAssociated(fromN);
+
+
+		boolean success = (nodeExists(graftClade(fromN, toN, notify)));
+
+
+		return success;
+	}
+	/*-----------------------------------------*/
+	/** Attach node fromN (and any clade to attached to it) along node toN.  Returns the new node created to attach fromN*/
+	public synchronized int graftClade(int fromN, int toN, boolean notify) {   
+		if (!nodeExists(fromN) || !nodeExists(toN))
+			return 0;
+		locked = true;
+		int newMother = openNode();
+		if (newMother==0)
+			return 0;
+		setTaxonNumber(newMother, -1);
+		if (label!=null)
+			label[newMother] = null;
+		deassignAssociated(newMother);
+
+		int toMother = motherOfNode(toN);
+
+		if (nodeIsFirstDaughter(toN)) {
+			int nextSis = nextSisterOfNode(toN);
+			firstDaughter[toMother]=newMother;
+			firstDaughter[newMother]=toN;
+			nextSister[toN]=fromN;
+			mother[newMother]=toMother;
+			mother[toN]=newMother;
+			mother[fromN]=newMother;
+			nextSister[fromN]=0;
+			nextSister[newMother]=nextSis;
+		}
+		else {
+			int prevSister = previousSisterOfNode(toN);
+			mother[newMother]=toMother;
+			mother[toN]=newMother;
+			mother[fromN]=newMother;
+			nextSister[prevSister]=newMother;
+			firstDaughter[newMother]=fromN;
+			nextSister[fromN]=toN;
+			nextSister[newMother]=nextSister[toN];
+			nextSister[toN]=0;
+		}
+		if (toN==root)
+			root = newMother;
+		locked = false;
+
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return newMother;
+	}
+	/*-----------------------------------------*/
+	/** Move branch so as to excise branchFrom from its current position, and attach it to branch beneath
+	node branchTo.  If successful, rename as given (to ensure renamed before notified).*/
+	public synchronized boolean moveBranch(int branchFrom, int branchTo, boolean notify) {
+		return moveBranch(branchFrom, branchTo, notify, false, 0.0);
+	}
+	/*-----------------------------------------*/
+	/** Move branch so as to excise branchFrom from its current position, and attach it to branch beneath
+	node branchTo.  If successful, rename as given (to ensure renamed before notified).
+	Preserve heights indicates that height of descendants from ancestor is preserved.
+	Preserve proportion indicates how the branch lengths are distributed; if 0 then new branches are 0 length; 0.5 means the new branch is 
+	half the length of the shortest of the two branches from/to.  preserveProportion is <strong>only</strong> considered when {@code preserveHeights=true};
+	if {@code preserveHeights=false} the branch receiving the new branch is effectively split in half by the newly grafted branch.*/
+	public synchronized boolean moveBranch(int branchFrom, int branchTo, boolean notify, boolean preserveHeights, double preserveProportion) {
+		if (branchFrom==branchTo)
+			return false;
+		else if (!nodeExists(branchFrom) || !nodeExists(branchTo))
+			return false;
+		else if  (descendantOf(branchTo,branchFrom))
+			return false;
+		else if  (branchTo == motherOfNode(branchFrom) && !nodeIsPolytomous(branchTo))
+			return false;
+		else if (nodesAreSisters(branchTo, branchFrom) && (numberOfDaughtersOfNode(motherOfNode(branchFrom))==2))
+			return false;
+		else if (numberOfDaughtersOfNode(motherOfNode(branchFrom))==1) //TODO: NOTE that you can't move a branch with 
+			return false;
+
+		checkTreeIntegrity(root);
+
+		double  toLength = getBranchLength(branchTo);
+		double  fromLength = getBranchLength(branchFrom);
+
+		//first, pluck out "branchFrom"
+		//next, attach branchFrom clade onto branchTo
+		if (snipClade(branchFrom, false)) {
+			int newMother = graftClade(branchFrom, branchTo, false);
+			if (hasBranchLengths() && MesquiteDouble.isCombinable(toLength)) { //remember length of branches to adjust afterward
+				if (preserveHeights){
+					if (preserveProportion< 0 || !MesquiteDouble.isCombinable(fromLength))
+						preserveProportion = 0;
+					if (preserveProportion>1)
+						preserveProportion = 1;
+					if (preserveProportion == 0)
+						setBranchLength(newMother, 0, false);
+					else {
+						double min = 0;
+						if (toLength > fromLength)
+							min = fromLength*preserveProportion;
+						else
+							min = toLength*preserveProportion;
+
+						setBranchLength(newMother, min, false);
+						setBranchLength(branchTo, toLength-min, false);
+						setBranchLength(branchFrom, fromLength-min, false);
+					}
+				}
+				else {
+					setBranchLength(newMother, toLength/2.0, false);
+					setBranchLength(branchTo, toLength/2.0, false);
+				}
+			}
+		}
+		if (!checkTreeIntegrity(root)) {
+			locked = true;
+			//what to do here?  notify?
+		}
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+
+	}
+	/*-----------------------------------------*/
+	/** Inserts a new node on the branch represented by "node", and returns the number of the inserted node */
+	public synchronized int insertNode(int node, boolean notify){
+		if (!nodeExists(node))
+			return -1;
+		int mom = motherOfNode(node);
+		int wD = whichDaughter(node);
+		int newN= openNode();
+		if (newN>0 && wD>=0) {
+			int youngerSister = nextSister[node];
+			if (wD==0){ //first daughter
+				firstDaughter[mom] = newN;
+			}
+			else {
+				int olderSister = indexedDaughterOfNode(mom, wD-1);
+				nextSister[olderSister] = newN;
+			}
+			nextSister[node] = 0;
+			nextSister[newN] = youngerSister;
+			firstDaughter[newN]= node;
+			taxonNumber[newN] = -1;  //Nov 2013
+			mother[node]=newN;
+			mother[newN]=mom;
+			if (node==root)
+				root = newN;
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+			return newN;
+		}
+		return -1;
+
+	}
+	/*-----------------------------------------*/
+	/** Adds d to be a new daughter of node. */
+	private synchronized void insertDaughter(int node, int d) {
+		if (node!= 0){
+			if (!nodeExists(firstDaughterOfNode(node)))
+				firstDaughter[node] = d;
+			else
+				nextSister[lastDaughterOfNode(node)] =d;
+			nextSister[d]=0;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Adds d to be a new daughter of node. */
+	private synchronized void flipFirstTwoDaughters(int node) {
+		if (node!= 0){
+			int first = firstDaughter[node];
+			int second = nextSister[first];
+			firstDaughter[node]=second;
+			nextSister[second] =first;
+			nextSister[first]=0;
+		}
+	}
+	/*------------------- SUBTLE REROOTING OF AUXILIARY INFORMATION ----------------------*/
+	/* This messy section up until floatNode is new as of 2. 72.  It permits information associated with the parts of the tree to be associated
+	 * either with the nodes or branches.  This is relevant in rerooting, because branch associated information then needs to flip to another node once
+	 * the branch is moved to the other side of the root.  Any associated arrays that have betweenness == true will behave as branch associated; others are node associated.
+	 * Modules setting these associated can indicate they are branch associated by adding the setAsBetween boolean = true to the setAssociatedXXXXX methods or
+	 * by the direct methods setAssociatedXXXXXBetweenness.  These write to the file as a special comment (see readExtras) at the end of the tree.
+	 *   For old files the standard branch associated info are forced
+	 * as such by checkAssociated() that looks to see if the name reference is recognized as branch associated */
+
+	public boolean rerootAssocBetweenOnlyFloatPoly(int first, int second){
+		if (first>numParts || first<0) 
+			return false;
+		if (second>numParts || second<0) 
+			return false;
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b.isBetween())
+					b.swapParts(first, second);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b.isBetween())
+					b.swapParts(first, second);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b.isBetween())
+					b.swapParts(first, second);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b.isBetween())
+					b.swapParts(first, second); //comments handled here
+			}
+
+		setDirty(true);
+		return true;
+	}
+	/*-----------------------------------------*/
+	public boolean rerootAssocBetweenOnlyFloatDichot(int previousFromAtNode, int sis, int targetNode){
+		if (previousFromAtNode>numParts || previousFromAtNode<0) 
+			return false;
+		if (sis>numParts || sis<0) 
+			return false;
+		if (targetNode>numParts || targetNode<0) 
+			return false;
+
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b.isBetween()) {
+					boolean newValue;
+					if (b.isBitOn(previousFromAtNode) || b.isBitOn(sis))
+						newValue = true;
+					else 
+						newValue = false;
+					boolean bT = b.isBitOn(targetNode);
+
+					b.setBit(sis, newValue);
+					b.setBit(previousFromAtNode, bT);
+					b.setBit(targetNode, false);
+				}
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b.isBetween()) {
+					long newValue = MesquiteLong.unassigned;
+					if (MesquiteLong.isUnassigned(b.getValue(previousFromAtNode)))
+						newValue = b.getValue(sis);
+					else if (MesquiteLong.isUnassigned(b.getValue(sis)))
+						newValue = b.getValue(previousFromAtNode);
+					else if (b.getValue(sis) == b.getValue(previousFromAtNode))
+						newValue = b.getValue(sis);
+					else
+						newValue = MesquiteLong.unassigned;
+					long bT = b.getValue(targetNode);
+					b.setValue(sis, newValue);
+					b.setValue(previousFromAtNode, bT);
+					b.setValue(targetNode, MesquiteLong.unassigned);
+				}
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b.isBetween()) {
+					double newValue = MesquiteLong.unassigned;
+					if (MesquiteDouble.isUnassigned(b.getValue(previousFromAtNode)))
+						newValue = b.getValue(sis);
+					else if (MesquiteDouble.isUnassigned(b.getValue(sis)))
+						newValue = b.getValue(previousFromAtNode);
+					else if (b.getValue(sis) == b.getValue(previousFromAtNode))
+						newValue = b.getValue(sis);
+					else
+						newValue = MesquiteDouble.unassigned;
+					double bT = b.getValue(targetNode);
+
+					b.setValue(sis, newValue);
+					b.setValue(previousFromAtNode, bT);
+					b.setValue(targetNode, MesquiteDouble.unassigned);
+				}
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b.isBetween()) {
+					Object newValue = null;
+					if (b.getValue(previousFromAtNode) == null)
+						newValue = b.getValue(sis);
+					else if (b.getValue(sis) == null)
+						newValue = b.getValue(previousFromAtNode);
+					else if (b.getValue(sis).equals(b.getValue(previousFromAtNode)))
+						newValue = b.getValue(sis);
+					else
+						newValue = null;
+					Object bT = b.getValue(targetNode);
+
+					b.setValue(sis, newValue);
+					b.setValue(previousFromAtNode, bT);
+					b.setValue(targetNode, null);
+				}
+			}
+
+		setDirty(true);
+		return true;
+	}
+
+	/*-----------------------------------------*/
+	public boolean rerootAssocBetweenOnlyCladeRoot(int oldMother, int atNode, int cladeRoot){
+		if (oldMother>numParts || oldMother<0) 
+			return false;
+		if (atNode>numParts || atNode<0) 
+			return false;
+		if (cladeRoot>numParts || cladeRoot<0) 
+			return false;
+
+
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b.isBetween()) {
+					boolean bT = b.isBitOn(atNode);
+					boolean bSpan = b.isBitOn(oldMother);
+
+					b.setBit(oldMother, false);
+					b.setBit(atNode, bSpan);
+
+					b.setBit(cladeRoot, bT);
+				}
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b.isBetween()) {
+					long bT = b.getValue(atNode);
+					long bSpan = b.getValue(oldMother);
+
+					b.setValue(atNode, bSpan);
+					b.setValue(oldMother, MesquiteLong.unassigned);
+
+					b.setValue(cladeRoot, bT);
+				}
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b.isBetween()) {
+					double bT = b.getValue(atNode);
+					double bSpan = b.getValue(oldMother);
+
+					b.setValue(atNode, bSpan);
+					b.setValue(oldMother, MesquiteDouble.unassigned);
+
+					b.setValue(cladeRoot, bT);
+				}
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b.isBetween()) {
+					Object bT = b.getValue(atNode);
+					Object bSpan = b.getValue(oldMother);
+
+					//b.setValue(oldMother, MesquiteDouble.unassigned);
+					b.setValue(atNode, bSpan);
+					b.setValue(oldMother, null);
+					b.setValue(cladeRoot, bT);
+				}
+			}
+
+		setDirty(true);
+		return true;
+	}
+	static final String[] betweenLongs = new String[]{"color"};
+	static final String[] betweenDoubles = new String[]{"width", "consensusFrequency", "posteriorProbability"};
+	static final String[] betweenObjects = new String[]{};
+	static final String[] betweenBits = new String[]{};
+	/*
+	public void setAssociatedBit(NameReference nRef, int index, boolean value){
+		setAssociatedBit(nRef, index, value, StringArray.indexOfIgnoreCase(betweenBits, nRef.getValue())>=0);
+	}
+	public void setAssociatedLong(NameReference nRef, int index, long value){
+		setAssociatedLong(nRef, index, value, StringArray.indexOfIgnoreCase(betweenLongs, nRef.getValue())>=0);
+	}
+	public void setAssociatedDouble(NameReference nRef, int index, double value){
+		setAssociatedDouble(nRef, index, value, StringArray.indexOfIgnoreCase(betweenDoubles, nRef.getValue())>=0);
+	}
+	public void setAssociatedObject(NameReference nRef, int index, Object value){
+		setAssociatedObject(nRef, index, value, StringArray.indexOfIgnoreCase(betweenObjects, nRef.getValue())>=0);
+	}
+	 */
+	private void checkAssociated(){   //for old data files that don't have betweenness recorded
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				NameReference nRef = b.getNameReference();
+				if (StringArray.indexOfIgnoreCase(betweenBits, nRef.getValue())>=0)
+					b.setBetweenness(true);
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				NameReference nRef = b.getNameReference();
+				if (StringArray.indexOfIgnoreCase(betweenLongs, nRef.getValue())>=0)
+					b.setBetweenness(true);
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				NameReference nRef = b.getNameReference();
+				if (StringArray.indexOfIgnoreCase(betweenDoubles, nRef.getValue())>=0)
+					b.setBetweenness(true);
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				NameReference nRef = b.getNameReference();
+				if (StringArray.indexOfIgnoreCase(betweenObjects, nRef.getValue())>=0)
+					b.setBetweenness(true);
+			}
+
+
+	}
+
+	private String writeAssociatedBetweenness(){
+		String s = "";
+		if (bits!=null) {
+			for (int i=0; i< bits.size(); i++) {
+				Bits b = (Bits)bits.elementAt(i);
+				if (b.isBetween())
+					s += " setBetweenBits = " + StringUtil.tokenize(b.getNameReference().getValue());
+			}
+		}
+		if (longs!=null) {
+			for (int i=0; i< longs.size(); i++) {
+				LongArray b = (LongArray)longs.elementAt(i);
+				if (b.isBetween())
+					s += " setBetweenLong = " + StringUtil.tokenize(b.getNameReference().getValue());
+			}
+		}
+		if (doubles!=null)
+			for (int i=0; i< doubles.size(); i++) {
+				DoubleArray b = (DoubleArray)doubles.elementAt(i);
+				if (b.isBetween())
+					s += " setBetweenDouble = " + StringUtil.tokenize(b.getNameReference().getValue());
+			}
+		if (objects!=null)
+			for (int i=0; i< objects.size(); i++) {
+				ObjectArray b = (ObjectArray)objects.elementAt(i);
+				if (b.isBetween())
+					s += " setBetweenObject = " + StringUtil.tokenize(b.getNameReference().getValue());
+			}
+		return s;
+	}
+	/*-----------------------------------------*/
+	//floatNode and reroot corrected to handle branch lengths 29 Sept 2001
+
+	/** For rerooting.  This starts from the node chosen for the new root, and proceeds down to the clade root.
+	It then unhooks the clade root and lets it float upward, temporarily making the new clade root to be the previous
+	node on the path from the chosen node.  It then back up to that node, and lets it float upward, making the new clade
+	root to be the previous node on the path.  And so on, letting the clade float upward piece by piece from its root
+	back toward the chosen node. */
+	private synchronized void floatNode(int targetNode, int previousFromAtNode, int cladeRoot){
+		if (targetNode!=cladeRoot) {
+			floatNode(motherOfNode(targetNode), targetNode, cladeRoot);  //go down until at the clade root
+		}
+		/*Either at the original clade root, or coming back up from it.  If coming back up, then previous floating will have left
+		the targetNode to be the current (possibly temporary) root of the clade.  The goal here will be to snip this target
+		from its mother and let it float upward relative to the previous node up the path from the chosen node*/
+		//About to snip the current targe
+		if (nodeIsPolytomous(targetNode)) { // target polytomous
+			//branch length that had belonged to previousFromAtNode needs to be assigned to targetNode
+			double bP = 0;
+			double bT = 0;
+			if (branchLength!=null) {
+				bP = branchLength[previousFromAtNode];
+				bT = branchLength[targetNode];
+			}
+			if (firstDaughter[targetNode]==previousFromAtNode) {
+				firstDaughter[targetNode]= nextSister[previousFromAtNode];
+			}
+			else {
+				int pSis = previousSisterOfNode(previousFromAtNode);
+				nextSister[pSis]= nextSister[previousFromAtNode];
+			}
+			mother[targetNode]=previousFromAtNode;
+			nextSister[previousFromAtNode] = 0;
+			insertDaughter(previousFromAtNode, targetNode);
+			if (branchLength!=null) {
+				branchLength[targetNode] = bP;
+				branchLength[previousFromAtNode] = bT;
+			}
+			rerootAssocBetweenOnlyFloatPoly(targetNode, previousFromAtNode);
+		}
+		else { //target dichotomous 
+			int sis = nextSisterOfNode(previousFromAtNode);
+			if (!nodeExists(sis))
+				sis = previousSisterOfNode(previousFromAtNode);
+			//branch lengths that had belonged to previousFromAtNode and sis need to be summed to be assigned to sis
+			double bSum = 0;
+			double bT = 0;
+			if (branchLength!=null) {
+				if (MesquiteDouble.isUnassigned(branchLength[previousFromAtNode]))
+					bSum = branchLength[sis];
+				else if (MesquiteDouble.isUnassigned(branchLength[sis]))
+					bSum = branchLength[previousFromAtNode];
+				else
+					bSum = branchLength[previousFromAtNode] + branchLength[sis];
+				bT = branchLength[targetNode];
+			}
+			mother[sis]=previousFromAtNode;
+			nextSister[previousFromAtNode] = 0;
+			insertDaughter(previousFromAtNode, sis);
+			mother[cladeRoot]=0; // zeroing root so it will be open
+			setTaxonNumber(cladeRoot,-1);
+			if (label!=null)
+				label[cladeRoot] = null;
+			if (branchLength!=null) {
+				branchLength[sis] = bSum;
+				branchLength[previousFromAtNode] = bT;
+				branchLength[targetNode] = MesquiteDouble.unassigned;
+			}
+			rerootAssocBetweenOnlyFloatDichot(previousFromAtNode, sis, targetNode);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns sum of all branchLengths.*/
+	private double totalBranchLength(int node) { 
+		if (branchLength ==null)
+			return MesquiteDouble.unassigned;
+		double total = branchLength[node];
+		if (nodeIsInternal(node))
+			for (int daughter = firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter))
+				total = MesquiteDouble.add(total, totalBranchLength(daughter));
+		return total;
+	}
+	/*-----------------------------------------*/
+	boolean nodeIsUnbranchedDescendantOfRoot(int node){
+		if (node == root)
+			return true;
+		int anc = motherOfNode(node);
+		while (anc != root && nodeExists(anc)){
+			if (!nodeIsUnbranchedInternal(anc))
+				return false;
+			anc = motherOfNode(anc);
+		}
+		if (anc == root)
+			return true;
+		return false;
+
+	}
+
+	/*-----------------------------------------*/
+	void collapseRootwardUnbranched(int node){
+
+		if (nodeIsUnbranchedInternal(node)){
+			collapseRootwardUnbranched(firstDaughterOfNode(node));
+		}
+		if (node != root)
+			collapseBranch(node, false);
+	}
+	/*-----------------------------------------*/
+	static boolean warnedUnbranchedReroot = false;
+	/** reroot the clade below node atNode.*/
+	public synchronized boolean reroot(int atNode, int cladeRoot, boolean notify) {
+		if (!nodeExists(atNode) || !nodeExists(cladeRoot) ||cladeRoot==atNode || (!nodeIsPolytomous(cladeRoot) && cladeRoot == motherOfNode(atNode)))
+			return false;
+		checkTreeIntegrity(root);
+		if (hasUnbranchedInternals(root)){
+			//deleteUnbranchedInternals(root, false);
+			if (nodeIsUnbranchedInternal(atNode)){
+				taxa.discreetAlert("Sorry, you can't reroot at an unbranched internal node.");
+				return false;
+			}
+			if (nodeIsUnbranchedDescendantOfRoot(atNode)){
+				taxa.discreetAlert("Sorry, you can't reroot at an unbranched descendant of root.");
+				return false;
+			}
+			//delete all unbranched descendants of root
+			collapseRootwardUnbranched(root);
+			if (!nodeExists(atNode) || !nodeExists(cladeRoot) ||cladeRoot==atNode || (!nodeIsPolytomous(cladeRoot) && cladeRoot == motherOfNode(atNode)))
+				return true;
+
+
+			if (descendantOf(atNode, cladeRoot)) { 
+				int anc = atNode;
+				while (anc != cladeRoot && nodeExists(anc) && anc != root){
+					int ta = motherOfNode(anc);
+					if (nodeIsUnbranchedInternal(anc)) {
+						collapseBranch(anc, false);
+						if (!warnedUnbranchedReroot){
+							taxa.discreetAlert("Note: Unbranched internal nodes involved in rerooting were deleted.");
+							warnedUnbranchedReroot = true;
+						}
+					}
+					anc = ta;
+				}
+			}
+		}
+		double branchLengthBefore = totalBranchLength(root);
+		int oldMother = motherOfNode(atNode);
+		int oldMotherOfClade = motherOfNode(cladeRoot);
+		int oldPrevSisterOfRoot = previousSisterOfNode(cladeRoot);
+		int oldNextSisterOfRoot = nextSisterOfNode(cladeRoot);
+		boolean rootWasFirstDaughter = firstDaughter[oldMotherOfClade]==cladeRoot;
+		boolean atNodeWasFirstDaughter = firstDaughter[oldMother]==atNode;
+
+		//Do the major part of the work for the rerooting
+		floatNode(motherOfNode(atNode), atNode, cladeRoot);
+
+		//Clean up: floating will have rerooted it directly at atNode; must shift to be just below atNode
+		//At new root of clade:  create new node for new root of clade
+		if (cladeRoot==root) {
+			//establish tree's root at new location if needed
+			cladeRoot = openNode();
+			root = cladeRoot;
+		}
+		else
+			cladeRoot = openNode();
+		if (cladeRoot==0)
+			return false;
+
+		double bSpan = 0;
+		double bT = 0;
+		if (branchLength!=null) {
+			bT = branchLength[atNode];
+			bSpan = branchLength[oldMother];
+		}
+
+		setTaxonNumber(cladeRoot,-1);  //set clade root to be not terminal
+		if (label!=null)
+			label[cladeRoot] = null;
+
+		//had clade root previously been the first daughter of its mother?
+		if (rootWasFirstDaughter)		//if so, connect this mother to its new first daughter
+			firstDaughter[oldMotherOfClade]=cladeRoot; 
+		else { //otherwise, connect the sister that had been the link to the clade root to its new next sister
+			nextSister[oldPrevSisterOfRoot]=cladeRoot;
+			nextSister[cladeRoot]=oldNextSisterOfRoot;
+		}
+
+		//shift connections so that new root of clade is just below atNode
+		if (oldMother== firstDaughter[atNode]) { //if so, it must be connected as first daughter of cladeRoot
+			firstDaughter[atNode]= nextSister[oldMother];
+			firstDaughter[cladeRoot]=oldMother;
+			insertDaughter(cladeRoot, atNode);
+		}
+		else {
+			int pSis = previousSisterOfNode(oldMother);
+			nextSister[pSis]= nextSister[oldMother];
+			nextSister[oldMother] = 0;
+			firstDaughter[cladeRoot]=atNode;
+			insertDaughter(cladeRoot, oldMother);
+			if (!atNodeWasFirstDaughter) {   //added 2. 01 to prevent odd flipping
+				flipFirstTwoDaughters(cladeRoot);
+			}
+		}
+		if (branchLength!=null) {
+			branchLength[cladeRoot] = bT;
+			if (MesquiteDouble.isCombinable(bSpan)){
+				branchLength[oldMother] = bSpan/2.0;
+				branchLength[atNode] = bSpan/2.0;
+			}
+		}
+		rerootAssocBetweenOnlyCladeRoot(oldMother, atNode, cladeRoot);
+		mother[atNode]= cladeRoot;
+		mother[oldMother] = cladeRoot;
+		mother[cladeRoot]=oldMotherOfClade;
+		double branchLengthAfter = totalBranchLength(root);
+		if (!MesquiteDouble.closeEnough(branchLengthAfter, branchLengthBefore, 0.000001))
+			MesquiteMessage.warnProgrammer("Error: sum of branch lengths not preserved on reroot (before " + branchLengthBefore + " after " + branchLengthAfter + ")");
+		checkTreeIntegrity(root);
+		incrementVersion(MesquiteListener.BRANCHES_REARRANGED,notify);
+		return true;
+
+	}
+	/*-----------------------------------------*/
+	/** makes trees for all rootings of clade above node given, and places them into TreeVector*/
+	public void makeAllRootings(int cladeRoot, TreeVector trees) {
+		if (trees!= null && nodeExists(cladeRoot)) {
+			MesquiteTree baseTree = cloneTree();
+			baseTree.setName("original");
+			trees.addElement(baseTree, false); //save first unrooted version
+			int numReroots = baseTree.numberOfNodesInClade(cladeRoot)-1;
+			int count = 1;
+			for (int i = 1; i<=numReroots; i++) {
+				int atNode = baseTree.nodeInTraversal(i, cladeRoot);
+				if (baseTree.nodeIsPolytomous(cladeRoot) || baseTree.motherOfNode(atNode)!= cladeRoot) {
+					count++;
+					MesquiteTree newTree = baseTree.cloneTree();
+					newTree.setName("Rooting " + count);
+					newTree.reroot(newTree.nodeInTraversal(i, cladeRoot), cladeRoot, false);
+					trees.addElement(newTree, false);
+				}
+			}
+		}
+	}
+	/*-----------------------------------------*/
+	/** Outputs to console the mother, firstDaughter and nextSister storage */
+	public void dump (){
+		System.out.println("------------------------------------->");
+		System.out.println("tree: " +writeTree());
+		System.out.println("root: " + root);
+		System.out.println("numNodeSpaces: " + numNodeSpaces);
+		System.out.println("nodes not indicated have label[i] == null && mother[i] == 0 && firstDaughter[i] != 0 && nextSister[i] == 0 && taxonNumber[i] == -1");
+		for (int i=0; i<numNodeSpaces; i++) {
+			if (label != null){
+				if (label[i] != null && mother[i] != 0 || firstDaughter[i] != 0 || nextSister[i] != 0 || taxonNumber[i] != -1)
+					System.out.println("node " + i + " (label "+ label[i] + " ) (mother "+ mother[i] + ") (firstDaughter "+ firstDaughter[i] + ") (nextSister " + nextSister[i] + ") (taxon " + taxonNumber[i] + ")");
+			}
+			else
+				if (mother[i] != 0 || firstDaughter[i] != 0 || nextSister[i] != 0 || taxonNumber[i] != -1)
+					System.out.println("node " + i + " (mother "+ mother[i] + ") (firstDaughter "+ firstDaughter[i] + ") (nextSister " + nextSister[i] + ") (taxon " + taxonNumber[i] + ")");
+
+		}
+		System.out.println("<-------------------------------------");
+	}
+	/*-----------------------------------------*/
+	/** Returns a string with error message concerning the tree's integrity.  Does it recursively and hence may suffer when integrity damaged. (see dump as alternative) */
+	private String outputcheckTreeIntegrity(int node) {
+		String s = "[Error in tree "  + getName() + " (id " + getID() + ", version " + getVersionNumber() + ")";
+		if (nodeIsTerminal(node) && (taxonNumberOfNode(node)<0)) 
+			s += ":  terminal node with number 0;  node = " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]";
+		if (!nodeIsTerminal(node) && (taxonNumberOfNode(node)>=0)) 
+			s += ":  internal node with number non zero;  node = " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]";
+		if (!daughterOf(node, motherOfNode(node))) 
+			s += ":  node is not mother's daughter;  node = " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]";
+		if (node!=root)
+			if (!daughterOf(motherOfNode(node), motherOfNode(motherOfNode(node))))
+				s += ":  mother is not grandmother's daughter;  node = " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]";
+		int thisSister = firstDaughterOfNode(node);
+
+		if (nodeIsTerminal(node)) 
+			return Integer.toString(taxonNumberOfNode(node));
+		else {
+			s += "(";
+			boolean first = true;
+			while (nodeExists(thisSister)) {
+				if (!first)
+					s += ",";
+				first = false;
+				s += outputcheckTreeIntegrity(thisSister);
+				thisSister = nextSisterOfNode(thisSister);
+			}
+			s += ")";
+			return s;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Checks the tree integrity and outputs errors to system console if there are problems */
+	private void recursecheckTreeIntegrity(int node) {
+		if (nodeIsTerminal(node) && (taxonNumberOfNode(node)<0)) {
+			System.out.println("*Error in tree " + getName() + ":  terminal node with number 0; node= " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]");
+			dump();
+			System.out.println(outputcheckTreeIntegrity(root));
+		}
+		if (!nodeIsTerminal(node) && (taxonNumberOfNode(node)>=0)) {
+			System.out.println("*Error in tree " + getName() + ":  internal node with number non zero; node= " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]");
+			dump();
+			System.out.println(outputcheckTreeIntegrity(root));
+		}
+		if (!daughterOf(node, motherOfNode(node))) {
+			System.out.println("*Error in tree " + getName() + ":  node is not mother's daughter; node= " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]");
+			dump();
+			System.out.println(outputcheckTreeIntegrity(root));
+		}
+		if (node!=root)
+			if (!daughterOf(motherOfNode(node), motherOfNode(motherOfNode(node)))) {
+				System.out.println("*Error in tree " + getName() + ":  mother is not grandmother's daughter; node= " + Integer.toString(node) + " (taxa: " + taxa.getName()+ ")]");
+				dump();
+				System.out.println(outputcheckTreeIntegrity(root));
+			}
+
+		int thisSister = firstDaughterOfNode(node);
+
+		while (nodeExists(thisSister)) {
+			recursecheckTreeIntegrity(thisSister);
+			thisSister = nextSisterOfNode(thisSister);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Outputs warning */
+	private boolean doWarn(String t) {
+		MesquiteTrunk.mesquiteTrunk.logln(t);
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Checks integrity of tree and outputs messages for any errors found. */
+	private boolean checkTreeIntegrity(int node) {
+		if (!checkIntegrity)
+			return true;
+		checkTaxaIDs();
+		boolean toReturn=true;
+
+		for (int i=1; i<numNodeSpaces; i++) {
+			if (motherOfNode(i)!=0) {
+				if (motherOfNode(i)==firstDaughterOfNode(i))
+					toReturn = doWarn("node " + Integer.toString(i) + " mother=first ");
+				if (motherOfNode(i)==nextSisterOfNode(i))
+					toReturn = doWarn("node " + Integer.toString(i) + " mother=next ");
+				if (motherOfNode(i)==i)
+					toReturn = doWarn("node " + Integer.toString(i) + " mother=node ");
+				if (firstDaughterOfNode(i)==i)
+					toReturn = doWarn("node " + Integer.toString(i) + " first=node ");
+				if (nextSisterOfNode(i)==i)
+					toReturn = doWarn("node " + Integer.toString(i) + " next=node ");
+			}
+		}
+
+		/**/
+		recursecheckTreeIntegrity(root);
+		if (false){ //This checking has never or rarely generated an error, and is expensive in time
+			int[] countsReferencesAsMother = new int[numNodeSpaces];
+			int[] countsReferencesAsDaughter = new int[numNodeSpaces];
+			for (int i=1; i<numNodeSpaces; i++) {
+				countsReferencesAsMother[i]=0;
+				countsReferencesAsDaughter[i]=0;
+			}
+			for (int i=1; i<numNodeSpaces; i++) {
+				if (nodeInTree(i)) {
+					if (inBounds(mother[i]))
+						countsReferencesAsMother[mother[i]]++;
+					if (inBounds(firstDaughter[i]))
+						countsReferencesAsDaughter[firstDaughter[i]]++;
+					if (inBounds(nextSister[i]))
+						countsReferencesAsDaughter[nextSister[i]]++;
+				}
+			}
+			for (int i=2; i<numNodeSpaces; i++) {
+				if (nodeInTree(i) && countsReferencesAsDaughter[i]>1)
+					toReturn = doWarn("node " + Integer.toString(i) + " claimed as daughter more than once ");
+			}
+			for (int i=1; i<numNodeSpaces; i++) {
+				if (nodeInTree(i) && countsReferencesAsMother[i]!=numberOfDaughtersOfNode(i))
+					toReturn = doWarn("node " + Integer.toString(i) + " claimed as mother not same as Daughter count ");
+			}
+		}
+		return toReturn;
+	}
+	/*
+	static boolean noMoreWarnRet = false;
+	public void warnRetIfNeeded(){
+		if (noMoreWarnRet || !warnReticulations)
+			return;
+		if (hasReticulations()){
+			String w = "Tree has reticulations.  This may be unintentional, resulting from internal nodes with duplicate names; to avoid this request Convert Internal Names in the Defaults menu.  This warning can be turned off in the Defaults menu.";
+			if (MesquiteThread.isScripting()) {
+				MesquiteTrunk.mesquiteTrunk.logln(w);
+			}
+			else if (!AlertDialog.query(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Reticulations!", w, "OK", "Don't warn again"))
+				noMoreWarnRet = true;
+
+		}
+	}
+	/*-----------------------------------------*/
+	/** Finds the highest taxon number in the given clade */
+	private int findHighestTaxonNumber (int node) {
+		if (!inBounds(node))
+			return -1;
+		if (nodeIsTerminal(node))
+			return taxonNumberOfNode(node);
+		int maximum = -1;
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			int highestInDaughter = findHighestTaxonNumber(daughter);
+			if (highestInDaughter>maximum)
+				maximum = highestInDaughter;
+		}
+		return maximum;
+	}
+	/*-----------------------------------------*/
+	/** Finds the node of the highest taxon number in the given clade */
+	private int findTerminalOfHighestTaxonNumber (int node) {
+		return nodeOfTaxonNumber(findHighestTaxonNumber(node));
+	}
+	/*-----------------------------------------*/
+	/** Finds the lowest taxon number in the given clade */
+	private int findLowestTaxonNumber (int node) {
+		if (!inBounds(node))
+			return -1;
+		if (nodeIsTerminal(node))
+			return taxonNumberOfNode(node);
+		int minimum = getNumTaxa();
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+			int lowestInDaughter = findLowestTaxonNumber(daughter);
+			if (lowestInDaughter<minimum)
+				minimum = lowestInDaughter;
+		}
+		return minimum;
+	}
+	/*-----------------------------------------*/
+	/** Finds the node of the lowest taxon number in the given clade */
+	private int findTerminalOfLowestTaxonNumber (int node) {
+		return nodeOfTaxonNumber(findLowestTaxonNumber(node));
+	}
+	/*-----------------------------------------*/
+	/** Places into the passed array (which must have been sized correctly in advance) the taxon numbers in the clade */
+	public void accumulateTerminals (int node, int[] terminals, MesquiteInteger next) {
+		if (!inBounds(node))
+			return;
+		if (terminals==null || next==null || next.getValue()>= terminals.length)
+			return;
+		if (nodeIsTerminal(node))  {
+			terminals[next.getValue()] = taxonNumberOfNode(node);
+			next.increment();
+		}
+		else
+			for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) )
+				accumulateTerminals(daughter, terminals, next);
+	}
+	/*-----------------------------------------*/
+	/** For enumerating all trees: returns whether the clade is set to the last form in the sequence *
+   	private boolean cladeIsLastInSequence(int node){
+   		if (nodeIsTerminal(node))
+   			return true;
+   		else {
+	   		int leftDaughter = firstDaughterOfNode(node);
+	   		int rightDaughter =nextSisterOfNode( firstDaughterOfNode(node));
+	   		if (nodeIsTerminal(leftDaughter)) {
+	   			return (findTerminalOfHighestTaxonNumber(node) == leftDaughter)&&cladeIsLastInSequence(rightDaughter);
+	   		}
+   			return (nodeIsTerminal(leftDaughter) && (findTerminalOfHighestTaxonNumber(node) == leftDaughter) &&cladeIsLastInSequence(rightDaughter));  //todo: leftDaughter also needs to have some value
+   		}
+   	}
+	/*-----------------------------------------*/
+	/* First in sequence is left ladder with terminal taxa in order from lowest numbered to highest numbered*
+   	private void setCladeToFirstInSequence(int node){
+		if (!inBounds(node))
+			return;
+   		if (nodeIsTerminal(node))
+   			return;
+   		if (nodeIsPolytomous(node))
+   			MesquiteMessage.warnProgrammer("Oops -- setCladeToFirstInSequence doesn't yet handle polytomies");//TODO: needs to change polytomies to 
+   		int leftDaughter = firstDaughterOfNode(node);
+   		int rightDaughter =nextSisterOfNode(leftDaughter);
+   		if (nodeIsTerminal(rightDaughter) && nodeIsTerminal(leftDaughter)) {
+   			if (taxonNumberOfNode(leftDaughter)>taxonNumberOfNode(rightDaughter))
+   				interchangeBranches(rightDaughter, leftDaughter, false);
+   		}
+   		else {
+    			//find lowest valued terminal and move it to be sister to rest
+   			int nodeOfLowestTaxon = findTerminalOfLowestTaxonNumber(node);
+   			int base = node;
+   			if (nodeOfLowestTaxon == rightDaughter)
+   				interchangeBranches(rightDaughter, leftDaughter, false);
+   			else {
+	   			moveBranch(nodeOfLowestTaxon, node, false);
+	   			base = motherOfNode(node);
+	   			int lef = firstDaughterOfNode(base);
+	   			if (nodeOfLowestTaxon == nextSisterOfNode(lef))
+   					interchangeBranches(nodeOfLowestTaxon, lef, false);
+	   		}
+   			int ontoNode = firstDaughterOfNode(base);
+   			//now go through terminals on right side, moving the lowest onto left side one by one
+   			while (nodeIsInternal(rightDaughter =nextSisterOfNode(firstDaughterOfNode(base)))) {
+   				nodeOfLowestTaxon = findTerminalOfLowestTaxonNumber(rightDaughter);
+	   			moveBranch(nodeOfLowestTaxon, ontoNode, false);
+	   			ontoNode = firstDaughterOfNode(base);
+   			}
+
+   		}	
+   	}
+	/*-----------------------------------------*/
+	/** Represent s as bitfield (actually a simple long) with bit cleared where element is in s but not in subS, bit set where in subS *
+   	private long representSubset(int[] s, int[] subS){
+   		if (s== null || subS==null)
+   			return 0L;
+   		long result=0L;
+   		for(int i=0; i<subS.length; i++){
+   			int loc = IntegerArray.indexOf(s, subS[i]);
+   			if (loc>=0)
+   				result = MesquiteSet.addToSet(result, loc);
+   		}
+   		return result;
+   	}
+	/*-----------------------------------------*/
+	/** Sets this the clade to have the next form in the sequence of all possible topologies (e.g., for exhaustive searches). *
+   	private boolean setCladeToNextInSequence(int node, int whoseCalling){ 
+   		if (nodeIsTerminal(node)) {
+   			return false;
+   		}
+   		else if (nodeIsPolytomous(node))
+   			setCladeToFirstInSequence(node);
+   		int leftDaughter = firstDaughterOfNode(node);
+   		int rightDaughter =nextSisterOfNode( firstDaughterOfNode(node));
+   		if (!setCladeToNextInSequence(rightDaughter, ++whoseCalling)) {
+   			if (setCladeToNextInSequence(leftDaughter, ++whoseCalling)) {
+   				setCladeToFirstInSequence(rightDaughter);
+   				return true;
+   			}
+   			else {
+   				/*left and right are individually last and so go to next partition into left and right
+   				First, check to see if this is last partition with this left-right balance.  If not, then
+   				interchange taxa to make it the next partition with this left-right balance. If last, then
+   				go to the next left-right balance as long as the current balance is not even or n-(n-1)*
+   				int numOnLeft = numberOfTerminalsInClade(leftDaughter);
+   				int numOnRight = numberOfTerminalsInClade(rightDaughter);
+   				if (numOnLeft==numOnRight){ //even balance
+	    				/*This is last partition with this left-right balance for even balances (e.g. 2-2 or 3-3)
+	   				if all of the highest number taxa are on the left (they started on the right)*
+	   				if (numOnLeft==1) {
+	   					return false;
+	   				}	
+	   				else {
+						int[] allTaxa = new int[numOnLeft+numOnRight];
+						int[] leftTaxa = new int[numOnLeft];
+						int[] rightTaxa = new int[numOnRight];
+						MesquiteInteger next = new MesquiteInteger(0);
+						accumulateTerminals(leftDaughter, leftTaxa, next);
+						next.setValue(0);
+						accumulateTerminals(rightDaughter, rightTaxa, next);
+						next.setValue(0);
+						accumulateTerminals(node, allTaxa, next);
+						IntegerArray.sort(leftTaxa);
+						IntegerArray.sort(rightTaxa);
+						IntegerArray.sort(allTaxa);
+	   					long thisSet = representSubset(allTaxa, leftTaxa); // represent allTaxa as bitfield with 0's where taxon is in right, 1 where in left
+	   					boolean done=false;
+	   					int times = 0;
+						while (!done){
+	   						long nextSet = MesquiteSet.nextSet(thisSet, allTaxa.length-1);
+	   						times++;
+	   						if (nextSet==0L) {
+	   							return times<=1;
+	   						}
+	   						else {
+	   							long changedTo0 = (thisSet ^ nextSet) & (~nextSet);
+	   							long changedTo1 = (thisSet ^ nextSet) & (~thisSet);
+	   							while (changedTo0!=0L && changedTo1!=0L){
+			   						int elementChangedTo0 = MesquiteSet.minimum(changedTo0);
+			   						int elementChangedTo1 = MesquiteSet.minimum(changedTo1);
+			   						int whichTaxonMovedLeftToRight = nodeOfTaxonNumber(allTaxa[elementChangedTo0]);
+			   						int whichTaxonMovedRightToLeft = nodeOfTaxonNumber(allTaxa[elementChangedTo1]);
+			   						interchangeBranches(whichTaxonMovedLeftToRight,whichTaxonMovedRightToLeft,false);
+			   						changedTo0 = MesquiteSet.clearFromSet(changedTo0, elementChangedTo0);
+			   						changedTo1 = MesquiteSet.clearFromSet(changedTo1, elementChangedTo1);
+	   							}
+
+		   						if (MesquiteSet.isElement(nextSet, 0))
+		   							done=true;
+		   						thisSet = nextSet;
+	   						}
+						}
+						setCladeToFirstInSequence(rightDaughter);
+						setCladeToFirstInSequence(leftDaughter);
+						return true;
+					}
+  				}
+   				else { //unbalanced
+	   				/*This is last partition with this left-right balance
+	   				if all of the highest number taxa are on the left (they started on the right)*
+	   				int highestTaxonRight = taxonNumberOfNode(findTerminalOfHighestTaxonNumber(rightDaughter));
+	   				int lowestTaxonLeft = taxonNumberOfNode(findTerminalOfLowestTaxonNumber(leftDaughter));
+   					if (highestTaxonRight<lowestTaxonLeft){ //is last partition with this balance; go to next balance
+   						if (numOnLeft-numOnRight>1){ //not yet last balance
+   							//move any terminal from left to right to change balance
+   							int nodeOfHighestTaxonLeft = findTerminalOfHighestTaxonNumber(leftDaughter);
+   							moveBranch(nodeOfHighestTaxonLeft, rightDaughter, false);
+							rightDaughter = motherOfNode(rightDaughter);
+     							//then cycle, interchanging lowest and highest until all highest on left
+     							int nodeOfLowestTaxonRight;
+	   						while ((taxonNumberOfNode(nodeOfLowestTaxonRight = findTerminalOfLowestTaxonNumber(rightDaughter)))<(taxonNumberOfNode(nodeOfHighestTaxonLeft=findTerminalOfHighestTaxonNumber(leftDaughter))))
+	   							interchangeBranches(nodeOfLowestTaxonRight, nodeOfHighestTaxonLeft, false);
+
+   							setCladeToFirstInSequence(rightDaughter);
+   							setCladeToFirstInSequence(leftDaughter);
+   							return true;
+   						}
+   						else 
+   							return false;
+   					}
+   					else { //is not yet last partition with this balance; go to next partition
+   						int[] allTaxa = new int[numOnLeft+numOnRight];
+   						int[] leftTaxa = new int[numOnLeft];
+   						int[] rightTaxa = new int[numOnRight];
+   						MesquiteInteger next = new MesquiteInteger(0);
+   						accumulateTerminals(leftDaughter, leftTaxa, next);
+   						next.setValue(0);
+   						accumulateTerminals(rightDaughter, rightTaxa, next);
+   						next.setValue(0);
+   						accumulateTerminals(node, allTaxa, next);
+   						IntegerArray.sort(leftTaxa);
+   						IntegerArray.sort(rightTaxa);
+   						IntegerArray.sort(allTaxa);
+   						long thisSet = representSubset(allTaxa, leftTaxa); // represent allTaxa as bitfield with 0's where taxon is in right, 1 where in left
+   						long nextSet = MesquiteSet.nextSet(thisSet, allTaxa.length-1);
+   						if (nextSet==0L)
+   							return false;
+    						else {
+   							long changedTo0 = (thisSet ^ nextSet) & (~nextSet);
+   							long changedTo1 = (thisSet ^ nextSet) & (~thisSet);
+   							while (changedTo0!=0L && changedTo1!=0L){
+		   						int elementChangedTo0 = MesquiteSet.minimum(changedTo0);
+		   						int elementChangedTo1 = MesquiteSet.minimum(changedTo1);
+		   						int whichTaxonMovedLeftToRight = nodeOfTaxonNumber(allTaxa[elementChangedTo0]);
+		   						int whichTaxonMovedRightToLeft = nodeOfTaxonNumber(allTaxa[elementChangedTo1]);
+		   						interchangeBranches(whichTaxonMovedLeftToRight,whichTaxonMovedRightToLeft,false);
+		   						changedTo0 = MesquiteSet.clearFromSet(changedTo0, elementChangedTo0);
+		   						changedTo1 = MesquiteSet.clearFromSet(changedTo1, elementChangedTo1);
+   							}
+   							setCladeToFirstInSequence(rightDaughter);
+   							setCladeToFirstInSequence(leftDaughter);
+	   						return true;
+   						}
+   					}
+   				}
+   			}
+   		}
+   		else  //rightClade has reached end
+   			return true;
+   	}
+
+	/*-----------------------------------------*/
+	/** Returns the first tree in the sequence of all possible trees (polytomies are set to first resolution)*
+	public void setToFirstInSequence(){
+		setCladeToFirstInSequence(getRoot());
+	}
+	/*-----------------------------------------*/
+	/** Returns the next tree in the sequence of all possible trees (polytomies are set to first resolution)*
+	public boolean setToNextInSequence(){
+		if (numberOfTerminalsInClade(root)>60) {
+			MesquiteMessage.warnProgrammer("Cannot find next tree in sequence if tree has more than 60 terminal taxa");
+			return false;
+		}
+		else
+			return setCladeToNextInSequence(getRoot(), 0);
+	}
+
+	/*-----------------------------------------*/
+	/** Returns whether the tree has node labels */
+	public boolean hasNodeLabels(){
+		return (label!=null);
+	}
+	/*-----------------------------------------*/
+	/** Sets the node label to the passed string (doesn't copy string; just uses reference) */
+	public void setNodeLabel(String s, int node){
+		if (!nodeExists(node))
+			return;
+		if (label==null) {
+			label = new String[numNodeSpaces];
+			for (int i=0; i<numNodeSpaces; i++) {
+				label[i] = null;
+			}
+		}
+		label[node] = s;
+	}
+	/*-----------------------------------------*/
+	/** Gets the node label of the node */
+	public String getNodeLabel(int node){
+		if (!inBounds(node))
+			return  null;
+		if (nodeIsTerminal(node)) {
+			int it = taxonNumberOfNode(node);
+			if (it>=0)
+				return taxa.getTaxonName(it);
+		}
+		if (label==null) {
+			return null;
+		}
+		return label[node];
+	}
+	/*-----------------------------------------*/
+	/** Returns whether the node has a label */
+	public boolean nodeHasLabel(int node){
+		return (label!=null && nodeExists(node) && label[node]!=null) || (nodeIsTerminal(node));
+	}
+	/*-----------------------------------------*/
+	/** Finds the node with the given label */
+	public int nodeOfLabel(String s){
+		return nodeOfLabel(s, false);
+	}
+	/*-----------------------------------------*/
+	/** Finds the node with the given label */
+	public int nodeOfLabel(String s, boolean caseSensitive){
+		if (label==null || StringUtil.blank(s))
+			return -1;
+		else if (caseSensitive) {
+			for (int i=0; i<numNodeSpaces; i++) {
+				if (s.equals(label[i]))
+					return i;
+			}
+			int it = taxa.whichTaxonNumber(s, true, permitTruncTaxNames && !permitTaxaBlockEnlargement);
+			if (it>=0)
+				return nodeOfTaxonNumber(it);
+			return -1;
+		}
+		else  {
+			for (int i=0; i<numNodeSpaces; i++) {
+				if (s.equalsIgnoreCase(label[i]))
+					return i;
+			}
+			int it = taxa.whichTaxonNumber(s, false, permitTruncTaxNames && !permitTaxaBlockEnlargement);
+			if (it>=0)
+				return nodeOfTaxonNumber(it);
+			return -1;
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns whether tree is locked.*/
+	public boolean isLocked() {
+		return locked;
+	}
+	/*-----------------------------------------*/
+	/** Locks the tree (Currently, not used properly!!!!).*/
+	public void setLocked(boolean locked) {
+		this.locked= locked;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any selected nodes in the clade */
+	private boolean selectedInClade( int node) {
+		if (!inBounds(node))
+			return false;
+		if (selected==null)
+			return false;
+		if (getSelected(node))
+			return true;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			if (selectedInClade(d))
+				return true;
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any selected nodes in the clade */
+	public boolean anySelectedInClade(int node) {
+		if (!inBounds(node))
+			return false;
+		if (selected==null)
+			return false;
+		return selectedInClade(node);
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of nodes selected in the clade */
+	public int numberSelectedInClade( int node) {
+		if (!inBounds(node))
+			return 0;
+		if (selected==null)
+			return 0;
+		int numInClade=0;
+		if (getSelected(node))
+			numInClade++;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			numInClade+= numberSelectedInClade(d);
+		}
+		return numInClade;
+	}
+	/*-----------------------------------------*/
+	/** Gets the first node selected in clade of node node */
+	public int getFirstSelected(int node) {
+		if (!inBounds(node))
+			return 0;
+		if (getSelected(node))
+			return node;
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			int s = getFirstSelected(d);
+			if (s!=-1)
+				return s;
+		}
+		return -1;
+	}
+	/*-----------------------------------------*/
+	/** SelectsAllNodes in the clade */
+	public void selectAllInClade( int node) {
+		if (!inBounds(node))
+			return;
+		if (selected==null)
+			return;
+		setSelected(node, true);
+		for (int d = firstDaughterOfNode(node); nodeExists(d); d = nextSisterOfNode(d)) {
+			selectAllInClade(d);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Attach the object to the sensitive attachments */
+	public void attachToSensitives(Object obj){
+		if (obj ==null)
+			return;
+		if (sensitiveAttachments ==null)
+			sensitiveAttachments = new Vector();
+		sensitiveAttachments.addElement(obj);
+	}
+	/*-----------------------------------------*/
+	/** Remove the object from the sensitive attachments */
+	public void removeFromSensitives(Object obj){
+		if (obj ==null || sensitiveAttachments ==null)
+			return;
+		sensitiveAttachments.removeElement(obj);
+	}
+	/*-----------------------------------------*/
+	/** Remove all objects from the sensitive attachments */
+	public void removeAllSensitives(){
+		if (sensitiveAttachments ==null)
+			return;
+		sensitiveAttachments.removeAllElements();
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any sensitive attachments of the given class or a subclass */
+	public boolean anyAttachedSensitive(Class c){
+		if (c ==null ||sensitiveAttachments == null ||sensitiveAttachments.size() == 0)
+			return false;
+		int s = sensitiveAttachments.size();
+		for (int i= 0; i< s; i++)
+			if (c.isAssignableFrom(sensitiveAttachments.elementAt(i).getClass()))
+				return true;
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** Returns the number of sensitive attachments of the given class or a subclass */
+	public int numberAttachedSensitive(Class c){
+		if (c ==null ||sensitiveAttachments == null ||sensitiveAttachments.size() == 0)
+			return 0;
+		int s = sensitiveAttachments.size();
+		int count =0;
+		for (int i= 0; i< s; i++)
+			if (c.isAssignableFrom(sensitiveAttachments.elementAt(i).getClass()))
+				count++;
+		return count;
+	}
+	/*-----------------------------------------*/
+	/** Returns the indexTH sensitive attachment of the given class or a subclass */
+	public Object getAttachedSensitive(Class c, int index){
+		if (c ==null ||sensitiveAttachments == null ||sensitiveAttachments.size() == 0)
+			return null;
+		int s = sensitiveAttachments.size();
+		int count =0;
+		for (int i= 0; i< s; i++)
+			if (c.isAssignableFrom(sensitiveAttachments.elementAt(i).getClass())) {
+				if (count==index)
+					return sensitiveAttachments.elementAt(i);
+				count++;
+			}
+		return null;
+	}
+	/*-----------------------------------------*/
+	/** Lists attached sensitives */
+	public String getListAttachedSensitives(){
+		if (sensitiveAttachments == null ||sensitiveAttachments.size() == 0)
+			return null;
+		String s = "";
+		for (int i= 0; i< sensitiveAttachments.size(); i++)
+			s += sensitiveAttachments.elementAt(i) + "\n";
+		return s;
+	}
+	private boolean doChecks = false; //turned off because of problems with mismatch of notifications causing frequent messages
+	private boolean checkTaxaIDs(){
+		if (!doChecks)
+			return true;
+		String warning = null;
+		if (oldNumTaxa != taxa.getNumTaxa()) 
+			warning = "Error in tree "  + getName() + " (id " + getID() + ", version " + getVersionNumber() + ", treeVector: " + treeVector + "): oldNumTaxa != taxa.getNumTaxa()";
+		if (taxaIDs.length !=oldNumTaxa) 
+			warning = "Error in tree "  + getName() + " (id " + getID() + ", version " + getVersionNumber() + ", treeVector: " + treeVector +"): oldNumTaxa != taxaIDs.length";
+		for (int i = 0; i<taxa.getNumTaxa() && warning == null; i++)
+			if (i>= taxaIDs.length || taxa.getTaxon(i).getID() != taxaIDs[i])
+				warning = "Error in tree "  + getName() + " (id " + getID() + ", version " + getVersionNumber() + ", treeVector: " + treeVector +"): id of taxon " + i +" in Taxa doesn't match id recorded in MesquiteTree";
+		if (warning == null)
+			return true;
+		MesquiteMessage.warnProgrammer(warning);
+		return false;
+	}
+	public void reconcileTaxa(int code, Notification notification){
+		reconcileTaxa(code, notification, true);
+	}
+	public void reconcileTaxa(int code, Notification notification, boolean notify){
+		//check id list of taxa to see that it matches; otherwise add or subtract taxa;  ASSUMES TAXA DELETED OR ADDED BUT NOT MOVED!!!!!!
+		int newNumTaxa = taxa.getNumTaxa();
+		if (newNumTaxa == oldNumTaxa) {
+			if (code== MesquiteListener.PARTS_MOVED || code== MesquiteListener.PARTS_CHANGED) {
+				/*go through list of taxa.  If any taxon is not in sequence expected from Taxa then find where it is in the list of taxaID's
+				and move it into place*/
+				for (int i = 0; i<taxa.getNumTaxa(); i++){ //go through list of taxa
+					if (taxa.getTaxon(i).getID() != taxaIDs[i]){ //taxon i is not in sequence expected from Taxa
+						int loc = LongArray.indexOf(taxaIDs, taxa.getTaxon(i).getID());
+						if (loc <0) {
+							MesquiteTrunk.mesquiteTrunk.discreetAlert( "Error in MesquiteTree: taxaID's cannot be reconciled with current Taxa");
+							return;
+						}
+						else {
+							//taxon in place loc in the taxaID's has been renumbered to i.  Must adjust taxonNumber array accordingly
+							//if loc>i, then any taxonNumber>loc or <i stay the same; taxonNumbers <loc and >=i get bumped up by one; taxonNumber loc becomes i
+							//if loc<i, then any taxonNumber<loc or >i stay the same; taxonNumbers >loc and <=i go down by one; taxonNumber loc becomes i
+							if (loc>i){
+								for (int j=0; j<numNodeSpaces; j++) {
+									int t = taxonNumber[j];
+									if (t < loc && t>=i)
+										incrementTaxonNumber(j, 1);
+									else if (t == loc)
+										setTaxonNumber(j, i);
+								}
+							}
+							else {
+								for (int j=0; j<numNodeSpaces; j++) {
+									int t = taxonNumber[j];
+									if (t > loc && t<=i)
+										decrementTaxonNumber(j, 1);
+									else if (t == loc)
+										setTaxonNumber(j, i);
+								}
+							}
+							LongArray.moveParts(taxaIDs, loc, 1, i-1);
+
+						}
+					}
+				}
+				//MesquiteTrunk.mesquiteTrunk.discreetAlert( "ERROR in MesquiteTree: MesquiteListener.PARTS_MOVED not yet handled");
+				if (notify)
+					notifyListeners(this, notification);
+			}
+			else
+				checkTaxaIDs();
+			resetNodeOfTaxonNumbers();
+		}
+		else {
+			long[] oldTaxaIDs = taxaIDs;
+			boolean chgd = false;
+			if (code== MesquiteListener.PARTS_ADDED) {
+				//cycle through finding which taxa in Taxa are not in tree, and adding them
+				for (int i=0; i<newNumTaxa; i++) {
+					Taxon t = taxa.getTaxon(i);
+					long tid = t.getID();
+					if (LongArray.indexOf(oldTaxaIDs, tid)<0){
+						int tN = taxa.whichTaxonNumber(t);
+						addTaxa(tN-1, 1, false, false);
+						//should instead find contiguous block and add all at once!
+					}
+				}
+
+			}
+			else if (code== MesquiteListener.PARTS_DELETED) {
+				//cycle through finding which taxa in tree have been deleted && deleting them from tree
+				for (int i=oldNumTaxa-1; i>=0; i--) {
+					Taxon t = taxa.getTaxonByID(oldTaxaIDs[i]);
+					if (t==null) {
+						deleteTaxa(i, 1, false, false);
+						chgd = true;
+						//should instead find contiguous block and delete all at once!
+					}
+				}
+			}
+			else {
+				//cycle through finding which taxa deleted && deleting them from tree
+				for (int i=oldNumTaxa-1; i>=0 && i<oldTaxaIDs.length; i--) {
+					Taxon t = taxa.getTaxonByID(oldTaxaIDs[i]);
+					if (t==null) {
+						deleteTaxa(i, 1, false, false);
+						chgd = true;
+						//should instead find contiguous block and delete all at once!
+					}
+				}
+				//cycle through finding which taxa in Taxa are not in tree, and adding them
+				for (int i=0; i<newNumTaxa; i++) {
+					Taxon t = taxa.getTaxon(i);
+					long tid = t.getID();
+					if (LongArray.indexOf(oldTaxaIDs, tid)<0){
+						int tN = taxa.whichTaxonNumber(t);
+						addTaxa(tN-1, 1, false, false);
+						chgd = true;
+						//should instead find contiguous block and add all at once!
+					}
+				}
+			}
+
+			oldNumTaxa = taxa.getNumTaxa();
+
+			taxaIDs = taxa.getTaxaIDs();
+			checkTaxaIDs();
+			if (chgd)
+				incrementVersion(MesquiteListener.BRANCHES_REARRANGED,true);
+			resetNodeOfTaxonNumbers();
+		}
+	}
+	private void addTaxa(int starting, int num, boolean resetOldNumTaxa, boolean notify){
+		//TODO: make more efficient. This leaves the arrays big
+		int newNumTaxa = oldNumTaxa+num;
+		setNumNodeSpaces(numNodeSpaces + standardNumNodeSpaces(num));
+		boolean added = false;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=oldNumTaxa)
+			starting = oldNumTaxa-1;
+		for (int i=0; i<numNodeSpaces; i++) {
+			if (taxonNumber[i] > starting) {
+				incrementTaxonNumber(i,  num);
+				added = true;
+			}
+		}
+		nodeOfTaxon =  IntegerArray.addParts(nodeOfTaxon, starting, num);
+		taxaIDs = taxa.getTaxaIDs();
+		if (resetOldNumTaxa)
+			oldNumTaxa = taxa.getNumTaxa();
+		taxaVersion = taxa.getVersionNumber();
+		if (added && notify)
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,true);
+	}
+	private void setTaxonNumber(int node, int taxNumber){
+		if (node<0 || node>=taxonNumber.length || taxNumber>= taxa.getNumTaxa())
+			return;
+		taxonNumber[node] = taxNumber;
+		if (taxNumber>=0 && taxNumber<nodeOfTaxon.length){
+			nodeOfTaxon[taxNumber]=node;
+		}
+	}
+	private void decrementTaxonNumber(int node, int  num){
+		if (node<0 || node>=taxonNumber.length)
+			return;
+		taxonNumber[node] -= num;
+		if (taxonNumber[node]>=0 && taxonNumber[node]<nodeOfTaxon.length)
+			nodeOfTaxon[taxonNumber[node]]=node;
+	}
+	private void incrementTaxonNumber(int node, int  num){
+		if (node<0 || node>=taxonNumber.length)
+			return;
+		taxonNumber[node] += num;
+		if (taxonNumber[node]>=0 && taxonNumber[node]<nodeOfTaxon.length)
+			nodeOfTaxon[taxonNumber[node]]=node;
+	}
+	private void deleteTaxa(int starting, int num, boolean resetOldNumTaxa, boolean notify){
+		//TODO: make more efficient. This leaves the arrays big
+		int deleted = 0; //added 14 Feb 02
+		for (int i=0; i<num; i++) {
+			if (starting+i>=0 && starting+i<oldNumTaxa)
+				snipClade(nodeOfTaxonNumber(starting+i), false);
+		}
+		for (int i=0; i<numNodeSpaces; i++) {
+			if (taxonNumber[i] >= starting) {
+				if (taxonNumber[i]-starting < num){ //among deleted
+					setTaxonNumber(i, -1);
+					deleted++; //added 14 Feb 02
+				}
+				else {
+					decrementTaxonNumber(i, num);
+				}
+			}
+		}
+		nodeOfTaxon =  IntegerArray.deleteParts(nodeOfTaxon, starting, num);
+		taxaIDs = taxa.getTaxaIDs();
+		if (resetOldNumTaxa)
+			oldNumTaxa = taxa.getNumTaxa();
+		taxaVersion = taxa.getVersionNumber();
+		if (deleted>0 && notify)
+			incrementVersion(MesquiteListener.BRANCHES_REARRANGED,true);
+	}
+	/*-----------------------------------------*/
+	private long[] lastNotifications = new long[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; //a partial protection against responding to the same notification twice, e.g. coming via two different pathways.
+	private boolean notificationFound(Notification notification){
+		if (notification ==null)
+			return false;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return false;
+		if (LongArray.indexOf(lastNotifications, id)>=0)
+			return true;
+		return false;
+	}
+	private void rememberNotification(Notification notification){
+		if (notification ==null)
+			return;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return;
+		for (int i = 0; i< lastNotifications.length-1; i++)
+			lastNotifications[i+1] = lastNotifications[i];
+		lastNotifications[0] = id;
+	}
+	/** For MesquiteListener interface.  Passes which object changed, along with optional integer (e.g. for character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (notificationFound(notification))
+			return;
+		rememberNotification(notification);
+		if (obj == taxa){
+			if (Notification.appearsCosmetic(notification))
+				return;
+			int code = Notification.getCode(notification);
+			if  (code==MesquiteListener.SELECTION_CHANGED)  
+				return;
+			int[] parameters = Notification.getParameters(notification);
+			if ((parameters == null) || (code != MesquiteListener.PARTS_ADDED && code != MesquiteListener.PARTS_DELETED && code != MesquiteListener.PARTS_MOVED)) {
+				reconcileTaxa(code, notification);
+				return;
+			}
+			int starting = 0;
+			int num =  0;
+			try{
+				starting = parameters[0];
+				num = parameters[1];
+			}
+			catch (ArrayIndexOutOfBoundsException e){
+				MesquiteMessage.warnProgrammer("Error: insufficient parameters in changed in MesquiteTree ");
+				return;
+			}
+			if (code==MesquiteListener.PARTS_ADDED) {
+				addTaxa(starting, num, true, true);
+				taxaIDs = taxa.getTaxaIDs();
+				checkTaxaIDs();
+			}
+			else if (code==MesquiteListener.PARTS_DELETED){
+				deleteTaxa(starting, num, true, true);
+				taxaIDs = taxa.getTaxaIDs();
+				checkTaxaIDs();
+			}
+			else if (code==MesquiteListener.PARTS_MOVED){
+				reconcileTaxa(code, notification);
+				taxaIDs = taxa.getTaxaIDs();
+				incrementVersion(MesquiteListener.BRANCHES_REARRANGED,true);
+			}
+			taxaVersion = taxa.getVersionNumber();
+		}
+	}
+	
+	public void resetTaxaInfo(){
+		taxaIDs = taxa.getTaxaIDs();
+		oldNumTaxa = taxa.getNumTaxa();
+	}
+	/*-----------------------------------------*/
+	/** For MesquiteListener interface.  Passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/*-----------------------------------------*/
+	/** For MesquiteListener interface.  Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+
+	/*-----------------------------------------*/
+	/** Returns the number assigned to this tree (used by Stored Trees, see comment at field declaration)*/
+	public int getAssignedNumber(){
+		return sequenceNumber;
+	}
+	/*-----------------------------------------*/
+	/** Sets the number assigned to this tree (used by Stored Trees, see comment at field declaration)*/
+	public void setAssignedNumber(int num){
+		sequenceNumber = num;
+	}
+	/*-----------------------------------------*/
+	/**Translates internal numbering system to external (currently, 0 based to 1 based)*/
+	public static int toExternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i+1;
+	}
+	/*-----------------------------------------*/
+	/**Translates external numbering system to internal (currently, 1 based to 0 based)*/
+	public static int toInternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i-1;
+	}
+	/*-----------------------------------------*/
+	/** returns the number of dichotomous trees with the passed number of terminal taxa.  At 12 this is greater than the maximum int. */
+	public static BigInteger numberOfDichotomousTrees(int numTaxa){
+		if (numTaxa<=0)
+			return null;
+		BigInteger product = new BigInteger("1");
+		if (numTaxa<3)
+			return product;
+
+		for (int i=3; i<=numTaxa; i++)
+			product = product.multiply(new BigInteger(Integer.toString(2*i - 3)));
+		return product;
+	}
+
+	public static String getProfileReport(){
+		String s = "MesquiteTree profiling: ";
+		for (int i=0; i<timers.length; i++){
+			if (timers[i] != null)
+				s += " (" + i + ") " + timers[i].getAccumulatedTime();
+		}
+		return s;
+	}
+
+
+
+	/** Ultrametricizes the tree, in simple fashion.*/
+	/*.................................................................................................................*/
+	public  void arbitrarilyUltrametricize(){
+		setUnassignedToOnes(getRoot());
+		ut(getRoot(), tallestPathAboveNode(getRoot(), 0));
+	}
+	/*.................................................................................................................*/
+	private void setUnassignedToOnes(int node){
+		if (!MesquiteDouble.isCombinable(getBranchLength(node))) {
+			setBranchLength(node, 1, false);
+		}
+		for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter =  nextSisterOfNode(daughter) ) {
+			setUnassignedToOnes(daughter);
+		}
+	}
+	/*.................................................................................................................*/
+	private void ut( int node, double targetHeight){
+		if (nodeIsTerminal(node)) {
+			setBranchLength(node, targetHeight, false);
+		}
+		else {
+			double heightAbove = tallestPathAboveNode(node, 0);
+			double nodeLength;
+			if (heightAbove==0) 
+				nodeLength = targetHeight/2;
+			else
+				nodeLength = targetHeight-heightAbove;
+			if (getRoot()!=node)
+				setBranchLength(node, nodeLength, false);
+			for (int daughter=firstDaughterOfNode(node); nodeExists(daughter); daughter = nextSisterOfNode(daughter) ) {
+				ut(daughter, targetHeight - nodeLength);
+			}
+		}
+
+	}
+
+	public int getFileIndex(){
+		return fileIndex;
+	}
+	public void setFileIndex(int index){
+		fileIndex =index;
+	}
+	/*_________________________________________________*/
+	public boolean ancestorHasNameReference(NameReference nameRef, int node) {
+		if (!nodeExists(node))
+			return false;
+		if (getAssociatedBit(nameRef, motherOfNode(node)))
+			return true;
+		if (getRoot() == node || getSubRoot() == node)
+			return false;
+		return ancestorHasNameReference(nameRef, motherOfNode(node));
+	}
+	/*_________________________________________________*/
+	public int ancestorWithNameReference(NameReference nameRef, int node) {
+		if (!nodeExists(node))
+			return 0;
+		if (getAssociatedBit(nameRef, motherOfNode(node)))
+			return motherOfNode(node);
+		if (getRoot() == node || getSubRoot() == node)
+			return 0;
+		return ancestorWithNameReference(nameRef, motherOfNode(node));
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteTrunk.java b/Source/mesquite/lib/MesquiteTrunk.java
new file mode 100644
index 0000000..85cacf7
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteTrunk.java
@@ -0,0 +1,560 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+import mesquite.trunk.ProjectTreeWindow;
+
+import java.util.*;
+
+
+
+/* ����������������������������������������������������������������� */
+/* ======================================================================== */
+/**  The superclass of the Mesquite class, which resides within the trunk MesquiteModule, has the "main" for the program
+Mesquite, and instantiates itself as mesquiteTrunk.  MesquiteTrunk is placed in the class library so that all MesquiteModules (modules) can communicate 
+with the trunk. */
+
+public abstract class MesquiteTrunk extends MesquiteModule  
+{
+	public static boolean startedAsLibrary = false;
+	//turns on checking of classes in FileElement, NexusBlock and MesquiteCommand (possibly others), to detect memory leaks
+	public static final boolean checkMemory = false;
+	public static boolean attemptingToQuit = false;
+	public static LeakFinder leakFinderObject;
+	public static String tempDirectory ="";
+	public static String[] startupArguments = null;  //ask if flag "-myFlag" is in startupArguments by StringArray.indexOf(MesquiteTrunk.startupArguments, "-myFlag")>=0
+	public static boolean errorReportedDuringRun = false;
+	public static boolean errorReportedToHome = false;
+	public static boolean suppressMenuResponse = false;
+	static {
+		leakFinderObject = new LeakFinder();
+	}
+	/** Vector of information about all the modules (MesquiteModules).*/
+	public static ModulesInfoVector mesquiteModulesInfoVector;  // the vector of information on all available modules
+	/** Vector of all windows.*/
+	public static ListableVector windowVector;
+	/** Vector of all dialogs.*/
+	public static ListableVector dialogVector;
+
+	/** Vector of information records of installed (not necessarily loaded) packages.*/
+	public ListableVector packages;
+
+	/** List of standard packages.*/
+	public static String[] standardPackages = new String[]{
+		"minimal",
+		"charMatrices",
+		"basic", 
+		"trees",
+		"categ", 
+		"cont", 
+		"ancstates",
+		"charts",
+		"lists",
+		"io", 
+		"parsimony", 
+		"stochchar", 
+		"genesis"
+	};
+	/** List of standard packages.*/
+	public static String[] standardExtras = new String[]{
+		"batchArch",
+		"assoc", 
+		"correl",
+		"coalesce", 
+		"diverse",
+		"rhetenor", 
+		"align",
+		"consensus",
+		"treefarm",
+		"molec",
+		"search", 
+		"distance",
+		"ornamental",
+		"pairwise",
+		"dmanager",
+		"mb",
+		"meristic",
+		"tol"
+	};
+	public HelpSearchManager helpSearchManager;
+	public InterfaceManager interfaceManager;
+	//hackathon
+	public static boolean suppressSystemOutPrintln = false;
+	/** Default directory used in Open file dialogs and for consoles' current directory.  Adjusted by minimal.BasicFileCoordinator */
+	public static String suggestedDirectory = null;
+	/** Time of startup.*/
+	public static long startupTime;
+
+	/** Name of user logged in */
+	public static String currentAuthor = null;
+
+	/** Menu specifications of special menus owned by the trunk of Mesquite.*/
+	public static MesquiteMenuSpec fileMenu, editMenu, charactersMenu, treesMenu, analysisMenu, windowsMenu, helpMenu, utilitiesMenu;  
+	public static MesquiteSubmenuSpec defaultsSubmenu, setupSubmenu;
+	/** Commands belonging to special menu items owned by the trunk of Mesquite.  */
+	public MesquiteCommand newFileCommand, openFileCommand, openURLCommand, showLicenseCommand, resetMenusCommand,currentCommandCommand, pendingCommandsCommand,  forceQuitCommand, quitCommand, showAllCommand, closeAllCommand, saveAllCommand;
+	public MesquiteSubmenuSpec openExternalSMS;
+	/** True if MesquiteModule hiring and firing should be logged.*/
+	public static boolean trackActivity = false;
+	/** The name of the current module set loaded */
+	protected String configuration = null;
+	protected static Projects projects=null;  
+	private BrowseHierarchy drawTask=null;
+	protected static boolean defaultHideMesquiteWindow = false;
+	public static boolean substantivePrereleasesExist = false;
+	public static int numPrevLogs = 5;
+
+	public static int  maxNumMatrixUndoTaxa = 1000;
+	public static int  maxNumMatrixUndoChars = 15000;
+
+	public static String logFileName = "Mesquite_Log";
+	public static String recentFilesFileName = "RecentFiles.xml";
+	protected ProjectTreeWindow projectsWindow;
+	public int lastNotice = 0;  //here for phone home system
+	public int lastNoticeForMyVersion = 0;//here for phone home system
+	public int lastVersionNoticed = 0;//here for phone home system
+
+	public StringBuffer jarFilesLoaded = new StringBuffer();
+
+
+	public static ConsoleThread consoleThread = null;
+
+
+	public static boolean consoleListenSuppressed = false;
+	public static boolean suppressVersionReporting = false;
+	public static boolean suppressErrorReporting = false;
+	public static boolean noBeans = false;
+	public static boolean startedFromExecutable = false;
+	public static boolean debugMode = false;
+	public static boolean mesquiteExiting = false;
+	public static int snapshotMode = Snapshot.SNAPALL;
+
+
+
+
+	//true if Mesquite should check website for notices
+	public static boolean phoneHome = true;
+	public static boolean reportErrors = true;
+	public static boolean reportUse = true;
+
+	/** The panel in which all Mesquite "windows" fit if run as applet embedded in page.*/
+	public Panel embeddedPanel;
+
+	protected static boolean isApplication = false;
+
+	protected static Image logo;
+	public void init(){
+	}
+	public abstract void exit(boolean emergency, int status);
+	public void dispose(){
+		mesquiteModulesInfoVector.dispose();
+		windowVector.dispose();
+		dialogVector.dispose();
+		packages.dispose();
+		super.dispose();
+	}
+	public abstract double getMesquiteVersionNumber();
+	/*.................................................................................................................*/
+	public abstract void reportMemory();
+	public abstract void searchKeyword(String s, boolean useBrowser);
+	public abstract void searchData(String s, MesquiteWindow window);
+	/*.................................................................................................................*/
+	/** Placed here so that MesquiteModules are able to request that the trunk module of Mesquite
+	open a new file */
+	public abstract MesquiteProject openFile(String pathname);
+	/*.................................................................................................................*/
+	/** Placed here so that MesquiteModules are able to request that the trunk module of Mesquite
+	open a new file */
+	public abstract MesquiteProject newProject(String pathname, int code, boolean actAsScriptingRegardless);
+	/*.................................................................................................................*/
+	/** make a blank projects */
+	public static MesquiteProject makeBlankProject(){
+		FileCoordinator coord = (FileCoordinator)MesquiteTrunk.mesquiteTrunk.hireEmployee(FileCoordinator.class, null);
+		MesquiteFile file = coord.createBlankProject();
+		return file.getProject();
+	}
+	/*.................................................................................................................*/
+	/** add a project to Mesquite's list of currently active projects */
+	public void addProject(MesquiteProject proj){
+		if (projects == null)
+			projects = new Projects();
+		projects.addProject(proj);
+	}
+	/*.................................................................................................................*/
+	/** remove a project to Mesquite's list of currently active projects */
+	public void removeProject(MesquiteProject proj){
+		if (projects != null)
+			projects.removeProject(proj);
+	}
+	/*.................................................................................................................*/
+	/** get list of currently active projects */
+	public static Projects getProjectList(){
+		return projects;
+	}
+	/*.................................................................................................................*/
+	public static Thread startupShutdownThread = null;
+	public boolean isStartupShutdownThread(Thread t) {
+		return t == startupShutdownThread;
+	}
+	/*.................................................................................................................*/
+	public Class getDutyClass() {
+		return MesquiteTrunk.class;
+	}
+	/*.................................................................................................................*/
+	public String getDutyName() {
+		return "Central Mesquite module";
+	}
+	public void repaintSearchStrip(){
+		if (projectsWindow != null)
+			projectsWindow.repaintSearchStrip();
+		if (logWindow != null)
+			logWindow.repaintSearchStrip();
+	}
+	/*.................................................................................................................*/
+	public static boolean isMacOS(){
+		return !StringUtil.blank(System.getProperty("mrj.version"));
+	}
+	public static boolean isMacOSX(){
+		return System.getProperty("os.name").startsWith("Mac OS X");
+	}
+	/*.................................................................................................................*/
+	/** Returns the first three characters of "java.version" as a string; e.g., "1.4.1" is returned as the string 1.4 */
+	public static String getJavaVersionAsString(){
+		return System.getProperty("java.version").substring(0,3);
+	}
+	/*.................................................................................................................*/
+	/** Returns the full  "java.version" as a string; e.g., "1.4.1" is returned as the string 1.4.1 */
+	public static String getJavaVersionAsStringFull(){
+		return System.getProperty("java.version");
+	}
+	/*.................................................................................................................*/
+	/** Returns the first three characters of "java.version" as a double; e.g., "1.4.1" is returned as the double 1.4 */
+	public static double getJavaVersionAsDouble(){
+		try {
+			Double versionDouble = Double.valueOf(System.getProperty("java.version").substring(0,3));
+			return versionDouble.doubleValue();
+		}
+		catch (NumberFormatException e) {
+			return 0.0;
+		}
+	}
+	/*.................................................................................................................*/
+	public static boolean isJavaVersionLessThan(double queryVersion){
+		return getJavaVersionAsDouble() < queryVersion;
+	}
+	/*.................................................................................................................*/
+	public static boolean isMacOSXPanther(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.3")>=0);
+	}
+	/*.................................................................................................................*/
+	public static boolean isMacOSXPanther33(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.3")>=0) && mrj.startsWith("3.3");
+	}
+	/*.................................................................................................................*/
+	public static boolean isMacOSXAfterJaguarRunning33(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.0")<0 && System.getProperty("os.version").indexOf("10.1")<0 && System.getProperty("os.version").indexOf("10.2")<0) && mrj.startsWith("3.3");
+	} 	
+	/*.................................................................................................................*/
+	public static boolean isMacOSXBeforePanther(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.0")>=0 || System.getProperty("os.version").indexOf("10.1")>=0 || System.getProperty("os.version").indexOf("10.2")>=0);
+	} 	
+	/*.................................................................................................................*/
+	public static boolean isMacOSXBeforeSnowLeopard(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.0")>=0 || System.getProperty("os.version").indexOf("10.1")>=0 || System.getProperty("os.version").indexOf("10.2")>=0|| System.getProperty("os.version").indexOf("10.3")>=0 || System.getProperty("os.version").indexOf("10.4")>=0 || System.getProperty("os.version").indexOf("10.5")>=0);
+	} 	
+	/*.................................................................................................................*/
+	public static boolean isMacOSXLeopard(){
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.5")>=0);
+	} 	
+	/*.................................................................................................................*/
+	public static boolean isMacOSXYosemite(){
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.10")>=0);
+	} 	
+	/*.................................................................................................................*/
+	public static boolean isMacOSXJaguar(){
+		String mrj = System.getProperty("mrj.version");
+		if (mrj == null)
+			return false;
+		return System.getProperty("os.name").startsWith("Mac OS X") && (System.getProperty("os.version").indexOf("10.2")>=0) && mrj.startsWith("3.3");
+	}
+	public static boolean isLinux(){
+		return System.getProperty("os.name").indexOf("Linux")>=0 || System.getProperty("os.name").indexOf("linux")>=0 || System.getProperty("os.name").indexOf("LINUX")>=0;
+	}
+	public static boolean isWindows(){
+		return System.getProperty("os.name").indexOf("Windows")>=0 || System.getProperty("os.name").indexOf("windows")>=0 || System.getProperty("os.name").indexOf("WINDOWS")>=0;
+	}
+	/*.................................................................................................................*/
+	public static String getUniqueIDBase(){
+		return MesquiteTrunk.author.getCode() +  Long.toHexString(System.currentTimeMillis());
+	}
+	/*.................................................................................................................*/
+	public String getConfiguration(){
+		if (configuration == null)
+			return "All installed modules";
+		else
+			return configuration;
+	}
+	/*.................................................................................................................*/
+	public void setConfiguration(String s){
+		configuration = s;
+	}
+	/*.................................................................................................................*/
+	public abstract void substantivePrereleasesFound();
+	/*.................................................................................................................*/
+	/** Returns  whether Mesquite is running as applet or application*/
+	public static boolean isApplet(){
+		return !isApplication;
+	}
+	public static void requestLogFocus(){
+		if (logWindow != null)
+			logWindow.requestFocus();
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(this.getClass(), null, null, commandName, "showAbout")) {
+			if (getModuleWindow()!=null)
+				getModuleWindow().setVisible(true);
+		}
+		else if (checker.compare(this.getClass(), null, null, commandName, "hideAbout")) {
+			if (getModuleWindow()!=null)
+				getModuleWindow().hide();
+		}
+		else if (checker.compare(this.getClass(), null, null, commandName, "projects")) {
+			if (projects != null) {
+				int n = projects.getNumProjects();
+				if (n == 0)
+					logln("There are no projects open");
+				else for (int i = 0; i<n; i++)
+					logln(projects.getProject(i).getName());
+			}
+		}
+		else if (checker.compare(this.getClass(), null, null, commandName, "explainNoSave")) {
+			if (MesquiteTrunk.isApplet())
+				alert("You cannot save files because Mesquite is being run as a web applet.");
+			else if (getProjectList().getNumProjects()==0)
+				alert("You cannot save a file because none is open.");
+			else if (getProjectList().getNumProjects()>1)
+				alert("This menu item belongs to a window not associated with any particular open file or project.  To save a file, go to a window associated with it and select Save from its File menu.");
+		}
+		else if (checker.compare(this.getClass(), null, null, commandName, "gp")) {
+			if (projects != null) {
+				int i = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+				if (MesquiteInteger.isCombinable(i))
+					return projects.getProject(i);
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public HPanel getBrowserPanel(){
+		if (drawTask==null)
+			drawTask= (BrowseHierarchy)hireEmployee(BrowseHierarchy.class, null);
+		if (drawTask==null)
+			return null;
+		return drawTask.makeHierarchyPanel();
+	}
+	/*.................................................................................................................*/
+	/** Updates the  menu items to ensure that they are enabled or disabled as appropriate.  */
+	public final static void resetMenuItemEnabling(){
+		try {
+			Enumeration e = mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				MenuBar mbar = mw.getMenuBar();
+				if (mbar!=null) {
+					int numMenus = mbar.getMenuCount();
+					for (int imenu = 0; imenu<numMenus; imenu++) {
+						Menu menu = mbar.getMenu(imenu);
+						resetEnabling(menu);
+					}
+				}
+				Vector v = mw.getOwnerModule().embeddedMenusVector;
+				if (v != null){
+					for (int i = 0; i< v.size(); i++){
+						Menu menu = (Menu)v.elementAt(i);
+
+						resetEnabling(menu);
+					}
+				}
+			}
+		}
+		catch (Exception e){
+		}
+	}
+
+	/*.................................................................................................................*/
+	private static void resetEnabling(Menu menu) {
+		int numItems = menu.getItemCount();
+		for (int i = 0; i<numItems; i++) {
+			MenuItem mi = menu.getItem(i);
+			if (mi instanceof MesquiteSubmenu) {
+				((MesquiteSubmenu)mi).resetEnable();
+				resetEnabling((Menu)mi);
+			}
+			else if (mi instanceof Menu)
+				resetEnabling((Menu)mi);
+			else if (mi instanceof MesquiteMenuItem) {
+				((MesquiteMenuItem)mi).resetEnable();
+			}
+			else if (mi instanceof MesquiteCheckMenuItem) {
+				((MesquiteCheckMenuItem)mi).resetEnable();
+			}
+		}
+	}
+	static boolean resetCheckSuppressed = false;
+	public final static void suppressResetCheckMenuItems(){
+		resetCheckSuppressed =true;
+	}
+	public final static void resumeResetCheckMenuItems(){
+		resetCheckSuppressed = false;
+		resetCheckMenuItems();
+	}
+	static boolean resetNeededForCheckMenuItems = false;
+	/*.................................................................................................................*/
+	/** Updates the checked menu items to ensure that they are checked or not as appropriate.  */
+	public final static void checkForResetCheckMenuItems(){
+		if (!resetNeededForCheckMenuItems)
+			return;
+		if (resetCheckSuppressed)
+			return;
+		try {
+			Enumeration e = mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				MenuBar mbar = mw.getMenuBar();
+				if (mbar!=null) {
+					int numMenus = mbar.getMenuCount();
+					for (int imenu = 0; imenu<numMenus; imenu++) {
+						Menu menu = mbar.getMenu(imenu);
+						resetChecks(menu);
+					}
+				}
+				if (mw.getOwnerModule() != null){
+					Vector v = mw.getOwnerModule().embeddedMenusVector;
+					if (v != null){
+						for (int i = 0; i< v.size(); i++){
+							Menu menu = (Menu)v.elementAt(i);
+							resetChecks(menu);
+						}
+					}
+				}
+
+
+			}
+			resetNeededForCheckMenuItems = false;
+		}
+		catch (Exception e){
+		}
+	}
+	/*.................................................................................................................*/
+	/** Updates the checked menu items to ensure that they are checked or not as appropriate.  */
+	public final static void resetCheckMenuItems(){//now simply sets a flag that is dealt with on the ClockWatcherThread
+		resetNeededForCheckMenuItems = true;
+	}
+
+	/*.................................................................................................................*/
+	public static void resetChecks(Menu menu) {
+		int numItems = menu.getItemCount();
+		for (int i = 0; i<numItems; i++) {
+			MenuItem mi = menu.getItem(i);
+			if (mi instanceof MesquiteSubmenu) {
+				((MesquiteSubmenu)mi).resetCheck();
+				resetChecks((Menu)mi);
+			}
+			else if (mi instanceof Menu)
+				resetChecks((Menu)mi);
+			else if (mi instanceof MesquiteCheckMenuItem) {
+				((MesquiteCheckMenuItem)mi).resetCheck();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private static void resetChecks(Menu menu, MesquiteMenuSpec menuSpec) {
+		int numItems = menu.getItemCount();
+		for (int i = 0; i<numItems; i++) {
+			MenuItem mi = menu.getItem(i);
+			if (mi instanceof MesquiteSubmenu && menuSpec == ((MesquiteSubmenu)mi).getSpecification()) {
+				((MesquiteSubmenu)mi).resetCheck();
+				resetChecks((Menu)mi);
+			}
+			else if (mi instanceof Menu)
+				resetChecks((Menu)mi, menuSpec);
+			else if (mi instanceof MesquiteCheckMenuItem && menu instanceof MesquiteSubmenu && menuSpec == ((MesquiteSubmenu)menu).getSpecification()) {
+				((MesquiteCheckMenuItem)mi).resetCheck();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static void resetChecks(MesquiteMenuSpec menuSpec) {
+		Enumeration e = mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			MenuBar mbar = mw.getMenuBar();
+			if (mbar!=null) {
+				int numMenus = mbar.getMenuCount();
+				for (int imenu = 0; imenu<numMenus; imenu++) {
+					Menu menu = mbar.getMenu(imenu);
+					resetChecks(menu, menuSpec);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static long getMaxAvailableMemory () {
+		Runtime rt = Runtime.getRuntime();
+		rt.gc();
+		long maxMem =  rt.maxMemory();
+		long totalMem =  rt.totalMemory();
+		long freeMem = rt.freeMemory(); 			
+		long maxAvailMem = maxMem - totalMem + freeMem;
+		//("Free memory : " + maxMem + " - " + totalMem + " + " + freeMem + " = " + maxAvailMem);
+		return maxAvailMem; 
+
+		/* What's being done here? 
+		 * 
+		 *    maxMem =  the most the VM will possibly take              |--------------------------------------------------------|
+		 *    totalMem = the amount of mem currently used by VM   |-------------------------------|
+		 *    freeMem = the amount (of total) that is currently free                        |--------------|
+		 *    maxAvailMem = the most memory available                                      |--------------.-------------------------|
+		 *                                                                                                         {freeMem} + {maxMem-totalMem}
+		 */
+
+	}
+	/** add a package splash banner to Mesquite's list of currently active packages */
+	public abstract void addSplash(MesquiteModuleInfo mmi);
+}
+
diff --git a/Source/mesquite/lib/MesquiteWindow.java b/Source/mesquite/lib/MesquiteWindow.java
new file mode 100644
index 0000000..94338a4
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteWindow.java
@@ -0,0 +1,3229 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified May 02 especially for annotations*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+import mesquite.lib.simplicity.SimplicityStrip;
+/* ======================================================================== */
+/** A stand alone window ("Frame").  The modules do not add their components directly to this window, but rather
+to special Containers within the window.  This is done to deal with the difficulties of sizing, because of insets in non-MacOS systems,
+given Mesquite's tendency to use null Layouts.  The first Component within the MesquiteWindow is the OuterContentsArea. It
+contains the InfoBar and the InterContentArea.  The InterContentArea contains a series of ContentAreas.  One of these, graphics[0]
+below, is the one to which a module should add any Components it needs to display (this is done by calling addToWindow()).  The
+other ContentAreas are for textual information or Mesquite-controlled graphical information.*/
+public abstract class MesquiteWindow implements Listable, Commandable, OwnedByModule, FileDirtier, Logger {
+	LeakFinder leakFinder = MesquiteTrunk.leakFinderObject;
+	//	static Vector cd;
+	public MesquiteModule ownerModule;
+	public MesquiteMenuBar menuBar;
+
+	public boolean resetMenuPending = false;
+	public int painting = 0;
+	public boolean disposing = false;
+	public static boolean autoShow = true;
+	static int highestRank =0;
+	static int lowestRank =0;
+	int rank = -1;
+	private Object currentObject = null;
+	boolean minimalMenus = false;
+	public static boolean headless = false;  //HEADLESS : set this to true for headless mode
+	public static boolean suppressAllWindows = headless; //for command line use; pass argument -w
+	public static boolean GUIavailable = !headless;
+	public static boolean Java2Davailable = true;
+	protected MesquiteCommand showCommand, showInfoBarCommand, saveAsTextCommand, printCommand, printToFitCommand;
+	protected MesquiteCommand setFontCommand, setFontSizeCommand, listEmployeesCommand, doMacroCommand, showExplanationsCommand;
+	protected MesquiteCommand showSnapshotCommand, sendScriptCommand, showFileCommand, closeWindowCommand, tileOutWindowCommand, popOutWindowCommand;
+	protected MesquiteCommand printToPDFCommand;
+	public static boolean pdfOutputAvailable = true; 
+	boolean readyToPaint = true;
+	protected Font currentFont;
+	public static Font defaultFont;
+
+	private MesquiteTool currentTool;
+	private MesquiteTool previousTool = null;
+	private ToolPalette palette;
+	private ExplanationArea explanationArea, annotationArea;
+
+	private Annotatable defaultAnnotatable;
+	public int tickled = 0;  //repaint control to deal with Jaguar bug; see surveyNewWindows in MesquiteThread
+
+	//	protected UndoInstructions undoInstructions = null;
+	protected Undoer[] undoer = null;
+	protected MesquiteCommand undoCommand = null; 
+	protected MesquiteCommand previousToolCommand = null; 
+
+	private int setSizeDebugg = 0;
+	private boolean wasDisposed = false;
+	private int menuResets = 0;
+	private static boolean reportMenuResets = false;
+	OuterContentArea outerContents;
+	private InterContentArea interContents;
+	private ContentArea[] graphics;
+	protected boolean windowFinishedBuilding = false;
+	protected TextContentArea[]  text;
+	protected InfoBar infoBar;
+	protected Cursor waitCursor, restoreCursor;
+	public static final int infoBarHeightAllowance = 22;
+	protected int infoBarHeight = infoBarHeightAllowance;
+	boolean queryMode = false;
+	protected MesquiteMenuItem cloneWindowMenuItem, saveRecipeMenuItem,explanationsMenuItem, snapshotMenuItem, sendScriptMenuItem, closeWindowMenuItem, closeAllMenuItem, popOutWindowMenuItem, tileOutWindowMenuItem;
+
+	private MesquiteMenuItemSpec ptfMMIS;
+	private MesquiteMenuItemSpec pPDFMMIS;
+	private MesquiteMenuItemSpec popOutWindowMSpec;
+	private boolean showInfoBar = false;
+	private StringBuffer logText;
+	public static Frame dialogAnchor;
+	public static MesquiteTimer startingTime, resetMenuTime, windowShowTime, windowTimer;
+	public static int numDialogs=0;
+	public static int numNonWizardDialogs=0;
+	static int numWindowsTotal = 0;
+	int id = 0;
+	static MenuShortcut closeWindowShortcut;
+	public static ClassVector componentsPainted; //for detecting efficiency problems
+	MesquiteFrame parentFrame;
+	public static boolean compactWindows = true;
+	boolean closeable = false;
+	public static long totalCreated = 0;
+	public static long totalDisposed = 0;
+	public static long totalFinalized  = 0;
+	public static long numDisposing = 0;
+	int tileLocation;
+	static {
+
+		startingTime = new MesquiteTimer();
+		windowShowTime = new MesquiteTimer();
+		resetMenuTime = new MesquiteTimer();
+		windowTimer = new MesquiteTimer();
+
+		dialogAnchor = new Frame();
+		dialogAnchor.setBounds(-64, -64, 32,32);
+		closeWindowShortcut = new MenuShortcut(KeyEvent.VK_W);
+		defaultFont = new Font ("SanSerif", Font.PLAIN, 10); //added 5 Nov 01
+
+	}
+	/** a constructor not to be used except internally!!!  This is used for accumulating commands*/
+	public MesquiteWindow () {
+		id = numWindowsTotal++;
+	}
+	/**the standard constructor for MesquiteWindows*/
+	public MesquiteWindow (MesquiteModule ownerModule, boolean showInfoBar) {
+		super();
+		tileLocation = getDefaultTileLocation();
+		readyToPaint = false;
+		totalCreated++;
+		id = numWindowsTotal++;
+		this.showInfoBar = showInfoBar;
+		if ((compactWindows || this instanceof SystemWindow) && ownerModule != null){
+			MesquiteProject proj = ownerModule.getProject();
+			MesquiteFrame frame = null;
+			if (proj == null){
+				if (MesquiteTrunk.mesquiteTrunk.containerOfModule()!= null)
+					frame = MesquiteTrunk.mesquiteTrunk.containerOfModule().getParentFrame();
+			}
+			else
+				frame = proj.getFrame();
+			if (frame!= null){
+				parentFrame = frame;
+			}
+		}
+		if (parentFrame == null){
+			parentFrame = new MesquiteFrame(isCompactible(), ColorTheme.getInterfaceBackground());
+			parentFrame.setOwnerModule(ownerModule);
+			/*following done for OS 9 because of crashing bug in MRJ 2.2.5 if application menu touched; also may help other OS's to establish insets early?? */
+			Menu fM = new MesquiteMenu("File");
+			MenuBar mBar = new MenuBar();
+			mBar.add(fM);
+			parentFrame.setMenuBar(mBar);
+		}
+
+
+		this.ownerModule = ownerModule;
+		undoCommand = MesquiteModule.makeCommand("undo", this);
+		previousToolCommand = MesquiteModule.makeCommand("setToPreviousTool", this);
+
+		startingTime.start();
+
+		if (!showInfoBar)
+			infoBarHeight = 0;
+		//setLayout(new CardLayout());
+		outerContents = new OuterContentArea(this);
+
+		parentFrame.addPage(this); 
+		outerContents.setForeground(Color.black);
+		outerContents.requestFocusInWindow(); //this may address a MRJ 2.2.3 bug
+
+		waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
+		restoreCursor = Cursor.getDefaultCursor();
+
+		infoBar = new InfoBar(this);
+		outerContents.add(infoBar, "InfoBar"); //"InfoBar"
+		outerContents.setInfoArea(infoBar);
+
+		explanationArea = new ExplanationArea(this, false); 
+		explanationArea.setName("EXPL");  //for debugging purposes, so explanation area knows what sort it is
+
+		outerContents.setExplanationArea(explanationArea);
+		outerContents.add(explanationArea, "ExplanationArea"); 
+		explanationArea.setBackground(ColorTheme.getInterfaceBackground());
+		annotationArea = new ExplanationArea(this, true);
+		annotationArea.setName("ANOT");  //for debugging purposes, so explanation area knows what sort it is
+		annotationArea.setBackground(Color.white);
+		outerContents.setAnnotationArea(annotationArea);
+		setAnnotation(null);
+		//windowAnnotation.addListener(this);
+		//defaultAnnotation = windowAnnotation;
+		outerContents.add(annotationArea, "AnnotationArea"); 
+
+		interContents = new InterContentArea();
+		outerContents.add(interContents, "InterContents"); 
+		graphics = new ContentArea[2];
+		graphics[0] = new ContentArea(this, true);   //this is the main graphics page
+		graphics[1] = new ETContentArea(ownerModule);   // this is the employee tree graphics page
+		interContents.addPage(graphics[0], Integer.toString(InfoBar.GRAPHICS)); // primary graphics page
+		interContents.addPage(graphics[1], Integer.toString(InfoBar.EMPLOYEE_TREE));
+		text = new TextContentArea[InfoBar.numModes];  //text pages
+		text[InfoBar.TEXT_CONTENTS] = new TextContentArea();
+		interContents.addPage(text[InfoBar.TEXT_CONTENTS], Integer.toString(InfoBar.TEXT_CONTENTS)); //strings correspond to modes
+		text[InfoBar.TEXT_PARAMETERS] = new TextContentArea();
+		interContents.addPage(text[InfoBar.TEXT_PARAMETERS], Integer.toString(InfoBar.TEXT_PARAMETERS)); //strings correspond to modes
+		text[InfoBar.TEXT_CITATIONS] = new TextContentArea();
+		interContents.addPage(text[InfoBar.TEXT_CITATIONS], Integer.toString(InfoBar.TEXT_CITATIONS)); //strings correspond to modes
+
+		outerContents.setContentsArea(graphics, text, interContents);
+		if (infoBar != null)
+			infoBar.setContentsArea(graphics, text, interContents);
+		outerContents.setSize(0,0);
+		interContents.showPage(InfoBar.GRAPHICS);
+		//if (isMainWindowOfBranch && ownerModule!=null)
+		//	ownerModule.window=this;
+		currentFont = defaultFont;
+		setWindowFont(currentFont);
+
+		graphics[0].setBackground(ColorTheme.getInterfaceElement());
+		interContents.setBackground(ColorTheme.getInterfaceElement());
+		outerContents.setBackground(ColorTheme.getInterfaceElement());
+		MesquiteTrunk.windowVector.addElement(this, true);
+		saveAsTextCommand = MesquiteModule.makeCommand("saveTextToFile",  this);
+		showCommand = MesquiteModule.makeCommand("showWindow",  this);
+		printCommand = MesquiteModule.makeCommand("printWindow",  this);
+		printToFitCommand = MesquiteModule.makeCommand("printToFit",  this);
+		if (this instanceof Fittable)
+			ptfMMIS = new MesquiteMenuItemSpec(null, "Print Window To Fit Page...", MesquiteModule.mesquiteTrunk, printToFitCommand);
+		printToPDFCommand = MesquiteModule.makeCommand("printToPDF", this);
+		if (pdfOutputAvailable)
+			pPDFMMIS = new MesquiteMenuItemSpec(null,"Save Window As PDF...", MesquiteModule.mesquiteTrunk, printToPDFCommand);
+
+		setFontCommand =MesquiteModule.makeCommand("setFont",  this);
+		setFontSizeCommand =MesquiteModule.makeCommand("setFontSize",  this);
+		listEmployeesCommand = MesquiteModule.makeCommand("listEmployees",  this);
+		showInfoBarCommand = MesquiteModule.makeCommand("toggleInfoBar", this);
+		doMacroCommand =MesquiteModule.makeCommand("doMacro", this);
+		showFileCommand = MesquiteModule.makeCommand("showFile", ownerModule);
+		closeWindowCommand = MesquiteModule.makeCommand("closeWindow", this);
+		popOutWindowCommand = MesquiteModule.makeCommand("togglePopOutWindow", this);
+		tileOutWindowCommand = MesquiteModule.makeCommand("toggleTileOutWindow", this);
+		showExplanationsCommand =MesquiteModule.makeCommand("showExplanations", this);
+		showSnapshotCommand = MesquiteModule.makeCommand("showSnapshot", this);
+		sendScriptCommand = MesquiteModule.makeCommand("sendScript", this);
+		/*	infoBarMenuItem = new MesquiteCheckMenuItem(new MesquiteCMenuItemSpec(null,"Show Information Bar", getOwnerModule(), showInfoBarCommand, null));
+		infoBarMenuItem.set(showInfoBar);
+		infoBarMenuItem.disconnectable = false;*/
+		explanationsMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null,"Menu & Control Explanations", getOwnerModule(), showExplanationsCommand));
+		explanationsMenuItem.disconnectable = false;
+		cloneWindowMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Clone Window", getOwnerModule(), MesquiteModule.makeCommand("cloneWindow", this)));
+		cloneWindowMenuItem.disconnectable = false;
+		popOutWindowMSpec = new MesquiteMenuItemSpec(null, "Pop Out as Separate Window", getOwnerModule(), popOutWindowCommand);
+		popOutWindowMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Pop Out as Separate Window", getOwnerModule(), popOutWindowCommand));
+		popOutWindowMenuItem.disconnectable = false;
+		tileOutWindowMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Put in Separate Tile", getOwnerModule(), tileOutWindowCommand));
+		tileOutWindowMenuItem.disconnectable = false;
+		saveRecipeMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Save Window as Macro...", getOwnerModule(), MesquiteModule.makeCommand("saveMacroForWindow", this)));
+		saveRecipeMenuItem.disconnectable = false;
+		snapshotMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null,"Show Snapshot", getOwnerModule(), showSnapshotCommand));
+		snapshotMenuItem.disconnectable = false;
+		sendScriptMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null,"Send Script", getOwnerModule(), sendScriptCommand));
+		sendScriptMenuItem.disconnectable = false;
+		if (getOwnerModule() instanceof FileCoordinator)
+			closeWindowMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Close Window", getOwnerModule(), closeWindowCommand));
+		else
+			closeWindowMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Close Tab", getOwnerModule(), closeWindowCommand));
+		closeWindowMenuItem.disconnectable = false;
+		closeWindowMenuItem.setShortcut(closeWindowShortcut);	
+		MesquiteProject proj = ownerModule.getProject();
+		if (proj != null)
+			closeAllMenuItem = new MesquiteMenuItem(new MesquiteMenuItemSpec(null, "Close All Tabs Of Project", getOwnerModule(), new MesquiteCommand("closeAllWindows", getOwnerModule().getFileCoordinator())));
+
+		
+		
+		menuBar = new MesquiteMenuBar(this);
+		//setMenuBar(menuBar);  //���
+		parentFrame.setWindowLocation(60, 10, false, false); //default window position
+		addKeyListenerToAll(graphics[0], palette, true);
+		outerContents.requestFocusInWindow(); //this may address a MRJ 2.2.3 bug
+		startingTime.end();
+		closeable = true;
+		windowFinishedBuilding = true;
+	}
+	
+	public void setPopTileMenuItemNames(){
+		popOutWindowMenuItem.setLabel("Pop Out as Separate Window");
+		tileOutWindowMenuItem.setLabel("Put in Separate Tile");
+		if (isPoppedOut()) {
+			if (getPopAsTile()) {
+				tileOutWindowMenuItem.setLabel("Return Tile to Main Window");
+				closeWindowMenuItem.setLabel("Close Tab");
+			}
+			else {
+				popOutWindowMenuItem.setLabel("Reset within Main Window");
+				closeWindowMenuItem.setLabel("Close Window");
+			}
+		} 
+		else
+			closeWindowMenuItem.setLabel("Close Tab");
+
+
+	}
+	
+	public void startWindowTimer(){
+		if (windowTimer!=null)
+			windowTimer.start();
+	}
+	public MesquiteTimer getWindowTimer(){
+		return windowTimer;
+	}
+	public void resetTime(){
+		if (windowTimer!=null)
+			windowTimer.resetLastTime();
+	}
+	public void logTime(String message){
+		if (windowTimer!=null)
+			if (!StringUtil.blank(message))
+				MesquiteMessage.println(message + "  " + windowTimer.timeSinceLast());
+			else
+				MesquiteMessage.println("  " + windowTimer.timeSinceLast());
+	}
+
+	public boolean isCompactible(){
+		return compactWindows;
+	}
+	
+	public boolean permitViewMode(){
+		return true;
+	}
+	public int getTileLocation(){
+		return tileLocation;
+	}
+	public void setTileLocation(int loc){
+		this.tileLocation = loc;
+	}
+	boolean minimized = false;
+	public boolean isMinimized(){  //for Resources window only as of 08
+		return minimized;
+	}
+	public void setMinimized(boolean min){
+		this.minimized = min;
+	}
+	public int getDefaultTileLocation(){
+		return MesquiteFrame.MAIN;
+	}
+	boolean poppedOut = false;
+	public boolean isPoppedOut(){
+		return poppedOut;
+	}
+	boolean popAsTile = false;
+	public boolean getPopAsTile(){
+		return popAsTile;
+	}
+	public void setPopAsTile(boolean popAsTile){
+		this.popAsTile = popAsTile;
+		ownerModule.resetEmbeddedMenus(this);
+	}
+
+	public void popOut(boolean setVisible){
+		if (!isLoneWindow() && parentFrame!=null){
+			if (!parentFrame.anythingPoppedOtherThanMe(this) && MesquiteInteger.isCombinable(preferredPopoutWidth) && preferredPopoutWidth>0)
+				parentFrame.setPopoutWidth(preferredPopoutWidth);
+			parentFrame.popOut(this, setVisible);
+			ownerModule.resetEmbeddedMenus(this);
+		}
+	}
+	
+	int preferredPopoutWidth = MesquiteInteger.unassigned;
+	public void setPreferredPopoutWidth(int preferredWidth){
+		preferredPopoutWidth = preferredWidth;
+	}
+	
+	public void popIn(){
+		if (isLoneWindow()){
+			try {
+				getOwnerModule().getFileCoordinator().getModuleWindow().getParentFrame().popIn(this);
+			}
+			catch(Exception e){
+			}
+		}
+		else if ((getPopAsTile()) && parentFrame!=null){
+			parentFrame.popIn(this);
+		}
+		ownerModule.resetEmbeddedMenus(this);
+	}
+
+	public boolean isLoneWindow(){
+		return (isPoppedOut() && !popAsTile) || (parentFrame == null && parentFrame.getNumWindows()<=1);
+	}
+	public boolean isCompacted(){
+		return (compactWindows || this instanceof SystemWindow) && !poppedOut;
+	}
+	public int getID(){
+		return id;
+	}
+	protected void addWindowListener(WindowListener listener){
+		parentFrame.addWindowListener(listener);
+	}
+	public MesquiteFrame getParentFrame(){
+		return parentFrame;
+	}
+	public void setParentFrame(MesquiteFrame f){
+		parentFrame = f;
+		if (parentFrame != null)
+			parentFrame.setMenuBar(mbar);
+	}
+	public boolean isFrontMostInLocation(){
+		return parentFrame.frontMostInLocation(getTileLocation()) == this;
+	}
+	public void setAsPrimaryMesquiteWindow(boolean p){
+		if (parentFrame != null)
+			parentFrame.setAsPrimaryMesquiteFrame(p);
+	}
+	boolean orphan = false;
+	public void removedFromParent(){
+		orphan = true;
+	}
+	public void inParent(){
+		orphan = false;
+	}
+	public OuterContentArea getOuterContentsArea(){
+		return outerContents;
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule getOwnerModule() {
+		return ownerModule;
+	}
+	/*.................................................................................................................*/
+	/** For FileDirtier interface */
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (ownerModule!=null && ownerModule.getProject()!=null && ownerModule.getProject().getHomeFile()!=null)
+			ownerModule.getProject().getHomeFile().setDirtiedByCommand(true);
+	}
+	public boolean setAsFrontOnClickAnyContent(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getColorScheme(){
+		return ColorDistribution.getColorScheme(ownerModule);
+	}
+	/*.................................................................................................................*/
+	public MesquiteCommand getPreviousToolCommand() {
+		return previousToolCommand; 
+	}
+	/*.................................................................................................................*/
+	public MesquiteCommand getUndoCommand() {
+		return undoCommand; 
+	}
+	public void setUndoMenuItemEnabled(boolean b) {
+		if (ownerModule!=null)
+			ownerModule.setUndoMenuItemEnabled(b);
+	}
+	public Undoer[] getUndoer () {
+		return undoer;
+	}
+	public void setNewUndoState (Object newState) {
+		if (undoer!=null && undoer[0]!=null)
+			undoer[0].setNewState(newState);
+	}
+	public void setUndoer (Undoer[] undoer) {
+		if (this.undoer!=null) {
+			for (int i=0; i<this.undoer.length; i++)
+				if (this.undoer[i]!=null)
+					this.undoer[i].dispose();
+		}
+		this.undoer = undoer;
+		checkUndoMenuStatus();
+	}
+	public void setUndoer (Undoer undoer) {
+		if (this.undoer!=null) {
+			for (int i=0; i<this.undoer.length; i++)
+				if (this.undoer[i]!=null)
+					this.undoer[i].dispose();
+		}
+		this.undoer = new Undoer[] {undoer};
+		checkUndoMenuStatus();
+	}
+	public void setUndoer (UndoReference undoReference) {
+		if (undoReference!=null)
+			setUndoer(undoReference.getUndoer());
+		else
+			setUndoer();
+	}
+	public void setUndoer () {
+		setUndoer((Undoer[]) null);
+		checkUndoMenuStatus();
+	}
+	public void checkUndoMenuStatus () {
+		//resetMenus();
+		setUndoMenuItemEnabled(undoer!=null);
+	}
+	/*.................................................................................................................*/
+	/** Shows information in response to query mode*/
+	public static void respondToQueryMode(String item, MesquiteCommand command, Object widget){
+		if (command!=null && widget !=null) {
+			MesquiteWindow w = null;
+			if (widget instanceof Component)
+				w = windowOfItem((Component)widget);
+			else if (widget instanceof MenuComponent)
+				w = windowOfItem((MenuComponent)widget);
+			if (w==null)
+				return;
+			MesquiteTrunk.mesquiteTrunk.showLogWindow(false);
+			String s = CommandChecker.getQueryModeString(item, command, widget);
+			w.setExplanation(s);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns where the MesquiteWindow containing the component is in queryMode.  Returns false if not contained in a MesquiteWindow.
+	NOTE: this system was built in 2000 when the info bar had a ? button to turn on query mode.  Now (Jan 2001) that that's gone, and now that there is
+	an explanation area at the bottom of windows, an alternative systems were developed for explaining items on the fly (including control-select for menu items).
+	These query mode methods are left here in case it makes sense to resurrect them*/
+	public static boolean getQueryMode(Component c){
+		if (c==null)
+			return false;
+		if (c instanceof OuterContentArea)
+			return ((OuterContentArea)c).ownerWindow.queryMode;
+
+		Container cont = c.getParent();
+		while (cont!= null && !(cont instanceof OuterContentArea))
+			cont = cont.getParent();
+		if (cont instanceof OuterContentArea)
+			return ((OuterContentArea)cont).ownerWindow.queryMode;
+		else 
+			return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns where the MesquiteWindow containing the menu item is in queryMode.  Returns false if not contained in a MesquiteWindow.
+	NOTE: this system was built in 2000 when the info bar had a ? button to turn on query mode.  Now (Jan 2001) that that's gone, and now that there is
+	an explanation area at the bottom of windows, an alternative systems were developed for explaining items on the fly (including control-select for menu items).
+	These query mode methods are left here in case it makes sense to resurrect them*/
+	public static boolean getQueryMode(MenuComponent c){
+		MesquiteWindow win = windowOfItem(c);
+		if (win!=null)
+			return win.queryMode;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the menu item*/
+	public static MesquiteWindow windowOfItem(MesquiteWindow c){
+		return c;
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the menu item*/
+	public static MesquiteWindow windowOfItem(MenuComponent c){
+		if (c==null)
+			return null;
+		if (c instanceof MenuBar)
+			return getWindow((MenuBar)c);
+		if (!(c instanceof MenuComponent))
+			return null;
+		MenuContainer cont = ((MenuComponent)c).getParent();
+		while (cont!= null && !(cont instanceof MenuBar) && !(cont instanceof MesquitePopup)&& cont instanceof MenuComponent)
+			cont =  ((MenuComponent)cont).getParent();
+		if (cont instanceof MenuBar) {
+			return getWindow((MenuBar)cont);
+		}
+		else if (cont instanceof MesquitePopup){
+			return windowOfItem(((MesquitePopup)cont).getComponent());
+		}
+		return null;
+	}
+	private static MesquiteWindow getWindow(MenuBar mb){
+		if(mb==null)
+			return null;
+
+		Enumeration e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.getMenuBar()==mb)
+				return mw;
+		}
+		return null;
+
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the component.  Returns null if not contained in a MesquiteWindow*/
+	public static MesquiteWindow windowOfItem(Component c){
+		if (c==null)
+			return null;
+		if (c instanceof OuterContentArea)
+			return ((OuterContentArea)c).ownerWindow;
+
+		Container cont = c.getParent();
+		while (cont!= null && !(cont instanceof OuterContentArea))
+			cont = cont.getParent();
+		if (cont instanceof OuterContentArea)
+			return ((OuterContentArea)cont).ownerWindow;
+		else 
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the component.  Returns null if not contained in a MesquiteWindow*/
+	public static String getContext(Component c){
+		if (c==null)
+			return null;
+		String s = "";
+
+		Container cont = c.getParent();
+		while (cont!= null){
+			s += cont.getClass().getName() + " " + cont.getLayout() + "\n";			
+			cont = cont.getParent();
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the menu item*/
+	public static boolean isReadyToPaint(MesquiteWindow c){
+		return c.readyToPaint;
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the component.  Returns null if not contained in a MesquiteWindow*/
+	public static boolean isReadyToPaint(Component c){
+		MesquiteWindow w = windowOfItem(c);
+		if (w != null)
+			return w.readyToPaint;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns the Frame containing the component.  Returns null if not contained in a Frame*/
+	public static Frame frameOfComponent(Frame c){
+		return c;
+	}
+	/*.................................................................................................................*/
+	/** Returns the Frame containing the component.  Returns null if not contained in a Frame*/
+	public static Frame frameOfComponent(Component c){
+		if (c==null)
+			return null;
+		if (c instanceof Frame)
+			return (Frame)c;
+
+		Container cont = c.getParent();
+		while (cont!= null && !(cont instanceof Frame))
+			cont = cont.getParent();
+		if (cont instanceof Frame)
+			return (Frame)cont;
+		else 
+			return null;
+	}
+	static boolean checkcheck = false;
+	static long checkedCount = 0;
+	static Component lastComponent = null;
+	static boolean writeUnchecked = false;
+	public static long totalCheckDoomedCount = 0;
+	public static boolean checkDoomed(MesquiteWindow c){ 
+		return checkDoomed(c.outerContents);
+	}
+	/*.................................................................................................................*/
+	/** Returns whether the window belongs to a doomed module (one about to be closed).  To be called at the start of all
+	paint methods to abort the paint.  At the same time, this method sets a flag in the window to say that painting is in progress.
+	While this flag is set, the window will not be disposed.  The method uncheckDoomed(Component c) must be called at the end of the paint*/
+	public static boolean checkDoomed(Component c){ 
+		if (windowOfItem(c) == null)
+			return false;
+		totalCheckDoomedCount++;
+		
+		if (c!=null && componentsPainted!=null)
+			componentsPainted.recordWithTime(c.getClass());
+		if (checkcheck){
+			if (c == lastComponent){
+				checkedCount++;
+				if (checkedCount % 100 == 0) {
+					MesquiteFile.writeToLog("checkDoomed " + checkedCount + "  " + c + StringUtil.lineEnding());
+					writeUnchecked = true;
+				}
+			}
+			else {
+				checkedCount =1;
+				writeUnchecked = true;
+			}
+			lastComponent = c;
+		}
+		MesquiteWindow w = null;
+		if (c instanceof OuterContentArea){//EMBEDDED : needs to be changed
+
+			w = ((OuterContentArea)c).ownerWindow;
+		}
+		else {
+			Container cont = c.getParent();
+			while (cont!= null && !(cont instanceof OuterContentArea))
+				cont = cont.getParent();
+			if (cont instanceof OuterContentArea)
+				w = ((OuterContentArea)cont).ownerWindow;
+			else if (!(cont instanceof Frame))
+				return true;
+			else  {
+				return false;
+			}
+		}
+		if (w==null) {
+			return false;
+		}
+		//		MesquiteFile.writeToLog("         checkDoomed window " + w + StringUtil.lineEnding());
+		if (w.getOwnerModule()!=null && (w.getOwnerModule().isDoomed() || w.disposing)) {
+			return true;
+		}
+		//		cd.addElement(c);
+		w.painting++;
+		return false;
+	}
+	public static void uncheckDoomed(MesquiteWindow c){ 
+		uncheckDoomed(c.outerContents);
+	}
+	/*.................................................................................................................*/
+	public static void uncheckDoomed(Component c){
+		MesquiteWindow w = windowOfItem(c);
+		if (c!=null && componentsPainted!=null)
+			componentsPainted.stopTime(c.getClass());
+		if (checkcheck && writeUnchecked && c == lastComponent) {
+			MesquiteFile.writeToLog("         uncheckDoomed " + c + StringUtil.lineEnding());
+		}
+		if (MesquiteTrunk.isMacOSXJaguar())
+			Toolkit.getDefaultToolkit().sync();
+		if (w==null) 
+			return;
+		w.painting--;
+	}
+
+	/*--------------------------------PAINT/PRINT/SAVETEXT contents ----------------------------------*/
+	public static void invalidateAll(Component c){
+		if (c==null)
+			return;
+		c.invalidate();
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					invalidateAll(cc[i]);
+		}
+
+	}
+	public void contentsChanged() {
+		repaintAll();
+		if (disposing)
+			return;
+		if (graphics==null || graphics[0]==null || graphics[1]==null)
+			return;
+		if (infoBar!=null&& infoBar.getMode()>0) 
+			updateTextPage();
+	}
+	public void repaint() {
+		//super.repaint();
+		if (disposing)
+			return;
+		if (graphics==null || graphics[0]==null || graphics[1]==null)
+			return;
+		if (infoBar==null)
+			graphics[0].repaint();
+		else if (infoBar.getMode()==InfoBar.GRAPHICS)
+			graphics[0].repaint();
+		else if (infoBar.getMode()==InfoBar.EMPLOYEE_TREE)
+			graphics[1].repaint();
+		//	if (showInfoBar)
+		infoBar.repaint();
+	}
+	/*.................................................................................................................*/
+	public void repaintInfoBar() {
+		if (infoBar != null){
+			rpAll(infoBar);
+		}
+	}
+	/*.................................................................................................................*/
+	/** calls repaint of all components*/
+	public void repaintAll() {
+		if (infoBar != null){
+			if (infoBar.getMode()==InfoBar.GRAPHICS) {
+				rpAll(graphics[0]);
+				rpAll(palette);
+				rpAll(explanationArea);
+				rpAll(annotationArea);
+			}
+			rpAll(infoBar);
+			if (parentFrame != null && parentFrame.tabs != null)
+				parentFrame.tabs.repaint();
+		}
+	}
+	public static void rpAll(Component c){
+		if (c==null)
+			return;
+		c.repaint();
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					rpAll(cc[i]);
+		}
+
+	}
+	public void reportComponents(){
+		reportComponents(outerContents, "");
+
+	}
+	public static void reportComponents(Component c, String spacer){
+		if (c==null)
+			return;
+		spacer += "  ";
+		MesquiteMessage.println(spacer + c);
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					reportComponents(cc[i], spacer);
+		}
+
+	}
+	private Component focusWithin(Component c){
+		if (c==null)
+			return null;
+		if (c.hasFocus())
+			return c;
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++){
+					Component q = focusWithin(cc[i]);
+					if (q != null)
+						return q;
+				}
+		}
+		return null;
+
+	}
+	public Component componentWithFocus(){
+		if (infoBar.getMode()==InfoBar.GRAPHICS) {
+			Component cg = (focusWithin(graphics[0]));
+			if (cg != null)
+				return cg;
+		}
+		Component c = focusWithin(palette);
+		if (c != null)
+			return c;
+		c = focusWithin(explanationArea);
+		if (c != null)
+			return c;
+		c = focusWithin(annotationArea);
+		if (c != null)
+			return c;
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static boolean belongsTo(Component possibleContent, Component possibleContainer){
+		if (possibleContainer==possibleContent)
+			return true;
+		if (possibleContainer instanceof Container){
+			Component[] cc = ((Container)possibleContainer).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++){
+					if (belongsTo(possibleContent, cc[i]))
+						return true;
+				}
+		}
+		return false;
+
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows instead of paint to draw their contents*/
+	public void paintContents(Graphics g) {
+	}
+	/*.................................................................................................................*/
+	/** set the cursor to be the wait cursor.*/
+	public void setGraphicsWaitCursor() {
+		if (parentFrame == null)
+			return;
+		restoreCursor = parentFrame.getCursor();
+		setGraphicsCursor(waitCursor);
+	}
+	/*...............................................................................................................*/
+	/** set the cursor to be the default cursor.*/
+	public void setGraphicsDefaultCursor() {
+		if (parentFrame == null)
+			return;
+		restoreCursor = parentFrame.getCursor();
+		setGraphicsCursor(Cursor.getDefaultCursor());
+	}
+	/*...............................................................................................................*/
+	protected void setContentsCursor(Cursor c){
+		if (graphics != null && graphics.length>0 && graphics[0] != null)
+			graphics[0].setCursor(c);
+	}
+	/*...............................................................................................................*/
+	/** set the cursor to be that passed.*/
+	public void setGraphicsCursor(Cursor c) {
+		if (parentFrame == null)
+			return;
+		restoreCursor = parentFrame.getCursor();
+		if (c!=null)
+			setContentsCursor(c);
+	}
+	/*...............................................................................................................*/
+	/** restores the cursor to previous.*/
+	public void restoreGraphicsCursor() {
+		if (restoreCursor!=null)
+			setContentsCursor(restoreCursor);
+		restoreCursor = null;
+	}
+	/*...............................................................................................................*/
+	/** restores the cursor of all windows to previous.*/
+	public static void restoreAllCursors() {
+		Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			MesquiteWindow win = (MesquiteWindow)e.nextElement();
+			win.restoreGraphicsCursor();
+		}
+	}
+	/*...............................................................................................................*/
+	/** restores the cursor of all windows to wait cursor.*/
+	public static void setAllWaitCursors() {
+		Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			MesquiteWindow win = (MesquiteWindow)e.nextElement();
+			win.setGraphicsWaitCursor();
+		}
+	}
+	/*...............................................................................................................*/
+	/** restores the cursor of all windows to previous.*/
+	public static void repaintAllWindows() {
+		Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			MesquiteWindow win = (MesquiteWindow)e.nextElement();
+			win.repaintAll();
+		}
+	}
+	/*.................................................................................................................*/
+	/** to be called to update the current text page's contents*/
+	public final void updateTextPage() {
+		if (infoBar!=null)
+			for (int i=1; i<InfoBar.numModes; i++)
+				infoBar.refreshText(i);
+	}
+	/*.................................................................................................................*/
+	/** Update the page showing the employee tree (to be called after employees added or
+	subtracted)  */
+	public void updateEmployeeTree(){
+		if (graphics[1] instanceof ETContentArea) {
+			HPanel b = ((ETContentArea)graphics[1]).getBrowser();
+			if (b!=null)
+				b.renew();
+		}
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s))
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		if (getOwnerModule() != null && getOwnerModule().getProject() != null){
+			MesquiteProject proj = getOwnerModule().getProject();
+			return proj.searchData(s, null);
+		}
+		Projects projects = MesquiteTrunk.getProjectList();
+		if (projects == null || projects.getNumProjects() ==0)
+			return "<h2>No projects open; therefore, no data to search (searched: \"" + s + "\")</h2>";
+		String list = "";
+		for (int i = 0; i<projects.getNumProjects(); i++){
+			MesquiteProject proj = projects.getProject(i);
+			list += proj.searchData(s, null);
+		}
+		return list;
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+		return "Sorry, there is not a text version of this window's contents";
+	}
+	boolean w = false;
+	/*.................................................................................................................*/
+	/** saves text file with contents of window*/
+	public String saveTextToFile(String path, boolean append) {
+		while (w)
+			;
+		w = true;
+		String result = getTextContents();
+		if (append)
+			MesquiteFile.appendFileContents(path, result, false);
+		else
+			MesquiteFile.putFileContents(path, result, false);
+		w = false;
+		return result;
+	}
+
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 2;
+	}
+	/*.................................................................................................................*/
+	/** To be overridden to provide more appropriate print menu item (e.g., "Print Tree...", "Print Chart..."*/
+	public String getPrintMenuItem() {
+		return "Print Window...";
+	}
+	/*.................................................................................................................*/
+	/** To be overridden to provide more appropriate print menu item (e.g., "Print Tree To Fit Page...", "Print Chart To Fit Page..."*/
+	public String getPrintToFitMenuItemName() {
+		return "Print Window To Fit Page...";
+	}
+	/*.................................................................................................................*/
+	MesquiteMenuItemSpec getPrintToFitMenuItem() {
+		if (ptfMMIS!=null)
+			ptfMMIS.setName(getPrintToFitMenuItemName());
+		return ptfMMIS;
+	}
+	/*.................................................................................................................*/
+	/** To be overridden to provide more appropriate print menu item (e.g., "Print Tree to PDF...", "Print Chart..."*/
+	public String getPrintToPDFMenuItemName() {
+		return "Save Window as PDF...";
+	}
+
+	/*.................................................................................................................*/
+	MesquitePrintJob pjob;
+	/** Prints the current display in the window.  To be overridden to print in any special way.*/
+	public void printWindow(MesquitePrintJob pjob) {
+		if (pjob != null) {
+			int mode;
+			if (infoBar==null)
+				mode =InfoBar.GRAPHICS;
+			else mode = infoBar.getMode();
+			if (mode==InfoBar.GRAPHICS || mode == InfoBar.EMPLOYEE_TREE) {//graphical mode
+				if (mode==InfoBar.GRAPHICS)
+					pjob.printComponent(graphics[0], null, currentFont);
+				else
+					pjob.printComponent(graphics[1], null, currentFont);
+			}
+			else if (infoBar!=null){  //text mode
+
+				String s = infoBar.getText(mode);
+				pjob.printText(s, new Font("Monospaced", Font.PLAIN, 12));
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Print the parameters of the current module output. */
+	public final void printParameters(MesquitePrintJob pjob) {
+		if (pjob != null && infoBar!=null) {
+			String s = infoBar.getText(InfoBar.TEXT_PARAMETERS);
+			pjob.printText(s, outerContents.getFont());
+		}
+	}
+
+	/*.................................................................................................................*/
+	private void openPrWindow(int fitToPage) {
+		Frame f = this.getParentFrame();
+		if (!(f instanceof MesquiteFrame))
+			return;
+		int fitRule;
+		if (infoBar.getMode()!= InfoBar.GRAPHICS)
+			fitRule = MesquitePrintJob.AUTOFIT;
+		else
+			fitRule = fitToPage;
+		pjob = MesquitePrintJob.getPrintJob((MesquiteFrame)f, "Print Window", fitRule);
+	}
+	/*.................................................................................................................*/
+	private void doPrWindow() {
+		if (pjob != null) {
+			printWindow(pjob);
+		}
+	}
+	/*.................................................................................................................*/
+	private void closePrWindow() {
+		if (pjob != null) {
+			pjob.end();
+		}
+	}
+
+	//for java 1.1 printing
+	public Object getFitPrintObject(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	protected void prWindow(int fitToPage) {
+		Frame f = this.getParentFrame();
+		if (!(f instanceof MesquiteFrame))
+			return;
+		MainThread.incrementSuppressWaitWindow();
+		int fitRule;
+		if (infoBar.getMode()!= InfoBar.GRAPHICS)
+			fitRule = MesquitePrintJob.AUTOFIT;
+		else
+			fitRule = fitToPage;
+		pjob = MesquitePrintJob.getPrintJob((MesquiteFrame)f, "Print Window", fitRule);
+		if (pjob != null) {
+			MesquiteTrunk.mesquiteTrunk.logln("Printing window");
+			printWindow(pjob);
+			/*
+			if (infoBar !=null && infoBar.getMode()!=InfoBar.TEXT_PARAMETERS)
+				printParameters(pjob);
+			 */
+			pjob.end();
+		}
+		MainThread.decrementSuppressWaitWindow();
+	}
+	/*.................................................................................................................*/
+	MesquitePDFFile pdfFile;
+	/**
+	Writes the current display in the window to a PDF file.  To be overridden to display in any special way.
+	@author Peter Midford
+	 */
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			int mode;
+			int fitRule = fitToPage;     //move fitRule here so it can be overridden
+			pdfFile.setSizeOrientation(fitRule);        //will prompt for a size
+			//if (infoBar.getMode()!= InfoBar.GRAPHICS)
+			//	fitRule = MesquitePrintJob.AUTOFIT;
+			//else
+			//	fitRule = MesquitePrintJob.AUTOFIT; //fitToPage;
+			if (infoBar==null)
+				mode = InfoBar.GRAPHICS;
+			else mode = infoBar.getMode();
+			if (mode==InfoBar.GRAPHICS || mode == InfoBar.EMPLOYEE_TREE) {//graphical mode
+				Component printingComponent;
+				if (mode==InfoBar.GRAPHICS) 
+					printingComponent = graphics[0];
+				else
+					printingComponent = graphics[1];
+				pdfFile.printComponent(printingComponent,null,currentFont);
+				//TODO: figure out why calling print(g) generates empty pages.
+				//Graphics g = pdfFile.getPDFGraphicsForComponent(printingComponent, null);
+				//printingComponent.print(g);
+				//pdfFile.end();
+			}
+			else if (infoBar!=null){  //text mode	
+				String s = infoBar.getText(mode);
+				//Changed font size to 10, since courier is the only adobe supplied monospace font and
+				//it is a little larger than the system supplied monospace font.
+				pdfFile.printText(s, new Font("Monospaced", Font.PLAIN, 10));
+			}
+		}		
+	}
+
+	/*.................................................................................................................*/
+	/**
+	@author Peter Midford
+	@param fitToPage int no longer used; PDF will always fit to one page; user can edit the file if necessary 
+	 */
+	protected void pdfWindow(int fitToPage) {
+		MainThread.incrementSuppressWaitWindow();
+		pdfFile = MesquitePDFFile.getPDFFile(this, "Save Window to PDF");
+		if (pdfFile != null) {
+			windowToPDF(pdfFile, fitToPage);
+		}
+		MainThread.decrementSuppressWaitWindow();
+	}
+
+
+	/*--------------------------------MODE (GRAPHICS, TEXT, INFO.) ----------------------------------*/
+	/*.................................................................................................................*/
+	/** The method to be called to add a component for display (adds it to the graphics[0] content area) */
+	public Component addToWindow(Component c) {
+		if (c == null || graphics == null || graphics[0] == null)
+			return null;
+		if (currentTool!=null) {
+			removeKeyListener(graphics[0], currentTool);
+		}
+		removeKeyListener(graphics[0], palette);
+		Component cc =  graphics[0].add(c);
+		if (currentTool!=null) {
+			addKeyListenerToAll(graphics[0], currentTool, true);
+		}
+		addKeyListenerToAll(graphics[0], palette, true);
+
+		return cc;
+	}
+	/*.................................................................................................................*/
+	/** The method to be called to remove a component from display (removes if from the graphics[0] content area) */
+	public void removeFromWindow(Component c) {
+		if (c == null || graphics == null || graphics[0] == null)
+			return;
+		if (currentTool!=null) {
+			removeKeyListener(graphics[0], currentTool);
+		}
+		removeKeyListener(graphics[0], palette);
+		if (graphics[0] !=null)
+			graphics[0].remove(c);
+		if (currentTool!=null) {
+			addKeyListenerToAll(graphics[0], currentTool, true);
+		}
+		addKeyListenerToAll(graphics[0], palette, true);
+	}
+	/*.................................................................................................................*/
+	/** Called in some circumstances (not all) when a component is added to a container in the window.  Currently used so that
+	the Tree window knows that a component has been added to the TreeDisplay.*/
+	public void componentAdded(Container cont, Component comp){
+	}
+	/*.................................................................................................................*/
+	/** Causes the main graphics area to request focus*/
+	public void graphicsRequestFocus() {
+		if (graphics[0] !=null)
+			graphics[0].requestFocus();
+	}
+	/*.................................................................................................................*/
+	/** Gets the main graphics content area in which modules can add their components */
+	public Component getGraphicsZero() {
+		if (graphics == null)
+			return null;
+		return graphics[0];
+	}
+	/*.................................................................................................................*/
+	/** Hides or disconnects the main graphics panel of the window */
+	public void disconnectGraphics() {
+		if (interContents == null )
+			return;
+		try {
+		outerContents.remove(interContents);
+		}
+		catch (Exception e){
+		}
+		}
+	/** Hides or disconnects the main graphics panel of the window */
+	public void reconnectGraphics() {
+		if (interContents == null )
+			return;
+		try {
+			outerContents.add(interContents, "InterContents"); 
+		}
+		catch (Exception e){
+		}
+	}
+	/*.................................................................................................................*/
+	/** Gets the main graphics content area in which modules can add their components */
+	public Panel getGraphicsArea() {
+		if (graphics[0] != null)
+			return graphics[0].getMainPanel();
+		return null;
+	}
+	/** returns whether that panel is a side panel */
+	public boolean hasSidePanel(MousePanel sp) {
+		if (graphics[0] != null)
+			return graphics[0].hasSidePanel(sp);
+		return false;
+	}
+	/** requests that a side panel be added to main graphics panel */
+	public void addSidePanel(MousePanel sp, int width) {
+		if (graphics[0] != null)
+			graphics[0].addSidePanel(sp, width);
+	}
+	/** requests that a side panel be added to main graphics panel */
+	public void removeSidePanel(MousePanel sp) {
+		if (graphics[0] != null)
+			graphics[0].removeSidePanel(sp);
+	}
+	/** requests that a ledge panel be added to main graphics panel */
+	public void addLedgePanel(MousePanel sp, int width) {
+		if (graphics[0] != null)
+			graphics[0].addLedgePanel(sp, width);
+	}
+	/** requests that a side panel be added to main graphics panel */
+	public void removeLedgePanel(MousePanel sp) {
+		if (graphics[0] != null)
+			graphics[0].removeLedgePanel(sp);
+	}
+	public void checkPanelPositionsLegal(){  //available to be overridden
+	}
+	/*.................................................................................................................*/
+	/** Sets the palette of the main graphics content area */
+	void setPalette(ToolPalette palette) {
+		this.palette = palette;
+		if (graphics[0] == null)
+			return;
+		graphics[0].setPalette(palette); //setting palette into main graphics page
+		removeKeyListener(graphics[0], palette);
+		addKeyListenerToAll(graphics[0], palette, true);
+	}
+	/*.................................................................................................................*/
+	/** Gets the tool palette of the main graphics content area */
+	public ToolPalette getPalette() {
+		return palette;
+	}
+	/*.................................................................................................................*/
+	public static void addKeyListener(MesquiteWindow c, KeyListener k){
+		addKeyListenerToAll(c.outerContents, k, true);
+	}
+	/*.................................................................................................................*/
+	public static void addKeyListener(MesquiteWindow c, KeyListener k, boolean nonTextOnly){
+		addKeyListenerToAll(c.outerContents, k, nonTextOnly);
+	}
+	/*.................................................................................................................*/
+	public static void removeKeyListener(MesquiteWindow c, KeyListener k){
+		removeKeyListener(c.outerContents, k);
+	}
+	/*.................................................................................................................*/
+	public static void addKeyListenerToAll(Component c, KeyListener k, boolean nonTextOnly){
+		if (c==null || k == null)
+			return;
+		if (!nonTextOnly || ( !(c instanceof TextComponent) || c == k))
+			c.addKeyListener(k);
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					addKeyListenerToAll(cc[i], k, nonTextOnly);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static void removeKeyListener(Component c, KeyListener k){
+		if (c==null || k == null)
+			return;
+		c.removeKeyListener(k);
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					removeKeyListener(cc[i], k);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public void resetCursor(){  //May 02
+		if (currentTool == null || currentTool.getOnlyWorksWhereSpecified()){
+			setGraphicsDefaultCursor();
+			return;
+		}
+		Cursor c = currentTool.getCursor();
+		if (c!=null){
+			setGraphicsCursor(c);
+			if (palette!=null)
+				palette.repaintAll();  //a workaround for Windows Java VM bug?
+		}
+		else
+			setGraphicsDefaultCursor();
+	}
+	/*.................................................................................................................
+	public void resetCursor(){  //May 02
+		if (currentTool == null){
+			setGraphicsDefaultCursor();
+			return;
+		}
+		try { //just in case Java2 not available
+			Image im = currentTool.getCursorImage();
+			if (im == null){
+				Dimension best = getToolkit().getBestCursorSize(16, 16);
+				if ((best.width>16 || best.height>16) && MesquiteFile.fileExists(currentTool.getSizedImagePath(best.width))){
+					im = MesquiteImage.getImage(currentTool.getSizedImagePath(best.width));
+					if (im == null)
+						im = MesquiteImage.getImage(currentTool.getImagePath());
+				}
+				else 
+					im = MesquiteImage.getImage(currentTool.getImagePath());
+				currentTool.setCursorImage(im);
+			}
+			Cursor c = getToolkit().createCustomCursor(im, currentTool.getHotSpot(), currentTool.getName());
+			if (c!=null){
+				setGraphicsCursor(c);
+				if (palette!=null)
+					palette.repaintAll();  //a workaround for Windows Java VM bug?
+			}
+		}
+		catch (Throwable t){
+			setGraphicsDefaultCursor();
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void setCurrentTool(MesquiteTool tool){
+		if (tool!=null && !tool.getEnabled())
+			return;
+		MesquiteTool prevTool = null;
+		if (currentTool !=null) {
+			currentTool.setInUse(false);
+			previousTool = currentTool;
+			removeKeyListener(graphics[0], currentTool); 
+		}
+		currentTool = tool;
+		addKeyListenerToAll(graphics[0], currentTool, true); 
+		setExplanation("");
+		if (currentTool !=null) {
+			currentTool.setInUse(true);
+			if (currentTool.getDescription()!= null){
+				if (currentTool.getExplanation()==null || currentTool.getDescription().equals(currentTool.getExplanation()))
+					setExplanation("Tool: " + currentTool.getDescription());
+				else
+					setExplanation("Tool: " + currentTool.getDescription() + "\n(" +currentTool.getExplanation() + ")");
+			}
+			resetCursor();
+		}
+	}
+	/*.................................................................................................................*/
+	public MesquiteTool getCurrentTool(){
+		return currentTool;
+	}
+
+	protected ToolPalette makeToolPalette(){
+		return new ToolPalette(ownerModule, this, 1);
+	}
+	/*.................................................................................................................*/
+	public MesquiteButton addTool(MesquiteTool tool){
+		if (palette==null) {
+			setPalette(makeToolPalette()); //note default of 1
+		}
+		palette.setEnabled(true);
+		palette.setVisible(true);
+		
+		return palette.addTool(tool);
+	}
+	/*.................................................................................................................*/
+	public void removeTool(MesquiteTool tool){
+		if (palette !=null)
+			palette.removeTool(tool);
+	}
+	/*.................................................................................................................*/
+	public void toolTextChanged(){
+		if (palette !=null)
+			palette.toolTextChanged(); //fixed Apr 02
+	}
+	/*.................................................................................................................*/
+	/** Gets the visibility of the InfoBar */
+	public boolean getShowInfoBar() {
+		return showInfoBar;
+	}
+	/*.................................................................................................................*/
+	/** Sets the visibility of the InfoBar *
+	public void setShowInfoBar(boolean vis) {
+		int h = getHeight();
+		showInfoBar = vis;
+		if (infoBar==null && vis){
+			infoBar = new InfoBar(this);
+			outerContents.add(infoBar, "InfoBar"); //"InfoBar"
+			outerContents.setInfoArea(infoBar);
+			infoBar.setContentsArea(graphics, text, interContents);
+		}
+		if (showInfoBar) 
+			infoBarHeight = 17;
+		else
+			infoBarHeight = 0;
+		setWindowSize(getFullWidth(),h);
+		showPage(InfoBar.GRAPHICS);
+		if (infoBarMenuItem !=null)
+			infoBarMenuItem.set(showInfoBar);
+	}
+	/*.................................................................................................................*/
+	/** Gets the visibility of the explanation area */
+	public boolean getShowExplanation() {
+		return explanationHeight != 0;
+	}
+	/*.................................................................................................................*/
+	/** Sets the visibility of the explanation area */
+	public void setShowExplanation(boolean vis) {
+		setShowExplanation(vis, ExplanationArea.minimumHeightExplanation);
+	}
+	/*.................................................................................................................*/
+	/** Gets the height of the explanation area */
+	public int getExplanationHeight() {
+		return explanationHeight;
+	}
+	/*.................................................................................................................*/
+	/** Sets the visibility of the explanation area */
+	public void setShowExplanation(boolean vis, int height) {
+		int h = getContentsHeight();
+		int oldEH = explanationHeight;
+		if (vis) 
+			explanationHeight = height;
+		else
+			explanationHeight = 0;
+
+		setWindowSize(MesquiteInteger.unassigned,h - (explanationHeight - oldEH));  //unassigned
+	}
+	/*.................................................................................................................*/
+	/** Increments the height of the explanation area */
+	public void incrementExplanationArea() {
+		explanationArea.plus();
+	}
+	/*.................................................................................................................*/
+	/** Increments the height of the annotation area */
+	public void incrementAnnotationArea() {
+		annotationArea.plus();
+	}
+	/*.................................................................................................................*/
+	/** Gets the text in the explanation area.  This text is not editable */
+	public String getExplanation(){
+		if (explanationArea!=null) {
+			return explanationArea.getExplanation();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Gets the visibility of the Annotation area */
+	public boolean getShowAnnotation() {
+		return annotationHeight != 0;
+	}
+	/*.................................................................................................................*/
+	/** Sets the visibility of the Annotation area */
+	public void setShowAnnotation(boolean vis) {
+		setShowAnnotation(vis, ExplanationArea.minimumHeightAnnotation);
+	}
+	/*.................................................................................................................*/
+	/** Gets the height of the Annotation area */
+	public int getAnnotationHeight() {
+		return annotationHeight;
+	}
+	/*.................................................................................................................*/
+	/** Sets the visibility of the Annotation area */
+	public void setShowAnnotation(boolean vis, int height) {
+		int h = getContentsHeight();
+		int oldAH = annotationHeight;
+		if (vis) 
+			annotationHeight = height;
+		else
+			annotationHeight = 0;
+		setWindowSize(MesquiteInteger.unassigned, h - (annotationHeight - oldAH));  //unassigned pass to say adjust height only
+	}
+
+	/*.................................................................................................................*/
+	/** Returns whether annotation area has input focus */
+	public boolean annotationHasFocus(){
+		if (annotationArea!=null) {
+			return annotationArea.hasFocus;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/** Set the text in the explanation area.  This text is not editable */
+	public String getAnnotation(){
+		if (annotationArea!=null) {
+			try {
+			return annotationArea.getExplanation();
+			}
+			catch(Exception e){
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Sets the text in the explanation area.  This text is not editable */
+	public void setExplanation(String text){
+		if (explanationArea!=null) {
+			try {
+			explanationArea.setExplanation(text);
+			}
+			catch(Exception e){
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Sets the Annotatable whose annotation will be used for the default text in the annotation area.  */
+	public void setDefaultAnnotatable(Annotatable annot) {
+		defaultAnnotatable = annot;
+	}		
+	/*.................................................................................................................*/
+	/** Sets whether the explanation and annotation areas can receive focus.*/
+	public void setAEFocusSuppression(boolean suppress){
+		if (annotationArea!=null)
+			annotationArea.setFocusSuppression(suppress);
+		if (explanationArea!=null)
+			explanationArea.setFocusSuppression(suppress);
+	}
+	/*.................................................................................................................*/
+	/** Sets the text in the annotation area.  This text is editable; changes will be made in the MesquiteString object itself */
+	public void setAnnotation(Annotatable annot){
+		if (annotationArea!=null) {
+			if (annot != null) {
+
+				annotationArea.setExplanation(annot); 
+				if (StringUtil.blank(annot.getName()))
+					setExplanation("");
+				else
+					setExplanation("Footnote above refers to " + annot.getName());
+
+			}
+			else if (defaultAnnotatable !=null) {
+				annotationArea.setExplanation(defaultAnnotatable);
+				if (StringUtil.blank(defaultAnnotatable.getName()))
+					setExplanation("");
+				else
+					setExplanation("Footnote above refers to " + defaultAnnotatable.getName());
+			}
+			else {
+				annotationArea.setExplanation("");
+				setExplanation("");
+			}
+		}
+		resetCursor();
+	}
+	/*.................................................................................................................*/
+	/** Sets the text in the annotation area.  This text is not editable */
+	public void setAnnotation(String text, String annotationExplanation){
+		if (annotationArea!=null) {
+			if (StringUtil.blank(text)) {
+				annotationArea.setExplanation("");
+				setExplanation(annotationExplanation);
+			}
+			else {
+				annotationArea.setExplanation(text);
+				setExplanation(annotationExplanation);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static void tickClock(String tickString){
+		if (MesquiteTrunk.isMacOSXPanther() || MesquiteTrunk.isMacOSXBeforePanther())
+			return;
+		if (MesquiteModule.mesquiteTrunk.windowVector.size() == 0)
+			return;
+		else {
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				MesquiteWindow win = (MesquiteWindow)e.nextElement();
+				win.explanationArea.tickClock(tickString);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public static void hideClock(){
+		if (MesquiteModule.mesquiteTrunk.windowVector.size() == 0)
+			return;
+		else {
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				MesquiteWindow win = (MesquiteWindow)e.nextElement();
+				win.explanationArea.hideClock();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Return main object displayed.  Usage is specific to subclasses (see especially ListWindows)*/
+	public Object getCurrentObject(){
+		return currentObject;
+	}
+
+	/*.................................................................................................................*/
+	/** Sets the main object displayed.  Usage is specific to subclasses (see especially ListWindows)*/
+	public void setCurrentObject(Object object){
+		currentObject = object;
+	}
+	/*.................................................................................................................*/
+	boolean temp;
+	/*.................................................................................................................*/
+	/** Requests the page to be displayed (see InfoBar) */
+	public void showPage(int mode) {
+		if (mode>=0 && mode<InfoBar.numModes) {
+			interContents.showPage(mode);
+		}
+		if (ptfMMIS!=null) {
+			ptfMMIS.setEnabled(mode == InfoBar.GRAPHICS);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+	}
+	/*.................................................................................................................*/
+	/** Gets the mode (page) displayed */
+	public int getMode() {
+		if (infoBar!=null)
+			return infoBar.getMode();
+		else
+			return 0;
+	}
+
+	/*--------------------------------WINDOW SIZE, POSITION ----------------------------------*/
+	/*.................................................................................................................*/
+	/** OuterContainer is telling window its size was reset MAY BE DEFUNCT*
+	public void containerSizeReset(){
+		if (setSizeDebugg>=0) {  //something else is setting container bounds; react by storing new content areas
+			Insets insets = parentFrame.getInsets();
+			if ((oldInsetTop<0 || oldInsetBottom <0 || oldInsetRight<0 || oldInsetLeft<0) && (0==insets.top || 0==insets.bottom || 0==insets.right || 0==insets.left) ) {
+			}
+			else if (oldInsetTop!=insets.top || oldInsetBottom !=insets.bottom || oldInsetRight!=insets.right || oldInsetLeft!=insets.left) {
+				setWindowSize(contentWidth, contentHeight);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Widens the window. */
+	public void widenWindow(int widthIncrement) {
+		setWindowSize(getContentsWidth()+widthIncrement, MesquiteInteger.unassigned);  //unassigned to say widen only
+	}
+	/*.................................................................................................................*/
+	/** Heightens the window. */
+	public void heightenWindow(int heightIncrement) {
+		setWindowSize(MesquiteInteger.unassigned, getContentsHeight() + heightIncrement); //unassigned to say heighten only
+	}
+	int contentHeight = 0;
+	int contentWidth = 0;
+	protected int explanationHeight = 0;
+	protected int annotationHeight = 0;
+	/*.................................................................................................................*/
+	public int getWindowWidth() {
+		return parentFrame.getBounds().width;
+	}
+	/*.................................................................................................................*/
+	public int getWindowHeight() {
+		return parentFrame.getBounds().height;
+	}
+	/*.................................................................................................................*/
+	public void setWindowSizeDirect(int width, int height) {
+		//before telling parent, indicate all the things I need
+		int outerWidth = width;
+		int outerHeight = height; //+infoBarHeight + explanationHeight + annotationHeight + graphics[0].getLedgePanelHeight();		
+		parentFrame.setWindowSize(this, outerWidth, outerHeight);
+	}
+	protected boolean fromScriptCommand = false;
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize. */
+	public void setWindowSize(int width, int height) {  //pass MesquiteInteger.unassigned to either width or height to keep as is
+		if (MesquiteThread.isScripting() && !fromScriptCommand && !isLoneWindow()){
+			if(MesquiteInteger.isCombinable(width) && width > 100)
+				width = 100;
+			if (MesquiteInteger.isCombinable(height) && height > 100)
+				height = 100;
+		}
+		//before telling parent, indicate all the things I need
+		int outerWidth = width;
+		int outerHeight = height;
+		int g0LPH = 0;
+		if (graphics != null && graphics.length > 0 && graphics[0] != null)
+			g0LPH = graphics[0].getLedgePanelHeight();
+		if (MesquiteInteger.isCombinable(height))
+			outerHeight += infoBarHeight + explanationHeight + annotationHeight + g0LPH;		
+		parentFrame.setWindowSize(this, outerWidth, outerHeight, !isLoneWindow());
+	}
+	/*.................................................................................................................*/
+	/** Forces a reset of the window size. */
+	public void resetWindowSizeForce() {
+		setWindowSizeForce(getContentsWidth(), getContentsHeight());
+	}
+	/*.................................................................................................................*/
+	/** Sets the window size.  To be used instead of setSize. */
+	public void setWindowSizeForce(int width, int height) {
+		//before telling parent, indicate all the things I need
+		int outerWidth = width;
+		int g0LPH = 0;
+		if (graphics != null && graphics.length > 0 && graphics[0] != null)
+			g0LPH = graphics[0].getLedgePanelHeight();
+		int outerHeight = height+infoBarHeight + explanationHeight + annotationHeight + g0LPH;		
+		parentFrame.setWindowSize(this, outerWidth, outerHeight, !isLoneWindow());
+	}
+
+	public Insets getInsets(){
+		if (parentFrame!=null)
+			return parentFrame.getInsets();
+		return null;
+	}
+	public void resetContentsSize(){  //the size returned may not be that requested!  Thus, recalcualte contentHeight here
+		/*	Insets insets = parentFrame.getInsets();
+	//	outerContents.setBounds(insets.left,insets.top ,width, height-30);//
+
+		setSizeDebugg--;
+		//setSize(parentFrame.contentWidth+insets.left+insets.right, outerHeight);
+		setSizeDebugg++;
+		outerContents.validate();
+		 */
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (windowFinishedBuilding)
+			outerContents.validate();
+		windowResized();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void pack(){
+		setSizeDebugg--;
+		parentFrame.pack();
+		setSizeDebugg++;
+	}
+	/*.................................................................................................................*/
+	/** Sets the size of the window (not to be used directly) *
+	public void setSize(int w, int h) {
+		if (setSizeDebugg>=0) {
+			MesquiteMessage.warnProgrammer("Programmer: use setWindowSize instead of setSize for MesquiteWindows: " + getTitle());
+		}
+		super.setSize(w,h);
+	}
+	/*.................................................................................................................*/
+	/** Sets the size of the window (not to be used directly) *
+	public void setBounds(int x, int y, int w, int h) {
+			super.setBounds(x, y, w,h); 
+
+	}
+	/*.................................................................................................................*/
+	/** Gets the minimum height of the content area of the window */
+	public int getMinimumContentHeight(){
+		return 200;
+	}
+	/*.................................................................................................................*/
+	/** Gets the minimum size of the window */
+	public Dimension getMinimumSize(){
+		//return new Dimension(100,100);
+		Insets insets = getInsets();
+		int width  = insets.right+infoBar.getInfoBarWidth()+4;
+
+		return new Dimension(width, infoBarHeight + explanationHeight + annotationHeight+ insets.top +insets.bottom+getMinimumContentHeight());
+	}
+	/*.................................................................................................................*/
+	public Dimension getMaximumSize() {
+		return parentFrame.getMaximumSize();
+	}
+
+	public void setBackground(Color c){
+		outerContents.setBackground(c);
+	}
+	public Color getBackground(){
+		return outerContents.getBackground();
+	}
+	public Font getFont(){
+		return outerContents.getFont();
+	}
+	public void setFont(Font f){
+		outerContents.setFont(f);
+	}
+	public void setWindowLocation(int x, int y, boolean overridePrevious){
+		setWindowLocation(x, y, overridePrevious, false);
+	}
+	public void setWindowLocation(int x, int y, boolean overridePrevious, boolean scripting){
+		parentFrame.setWindowLocation(x, y, overridePrevious, scripting);
+	}
+	public void setLocation(int x, int y){
+		parentFrame.setWindowLocation(x, y, false, false);
+	}
+
+	public Point getLocation(){
+		return parentFrame.getLocation();
+	}
+
+	public Rectangle getBounds(){
+		if (parentFrame == null)
+			return new Rectangle(0,0,0,0);
+		Rectangle bounds = parentFrame.getBounds(this);
+		return bounds;
+	}
+	public boolean isShowing(){
+		return parentFrame.isShowing();
+	}
+	public void requestFocus(){
+		outerContents.requestFocus();
+	}
+	/*.................................................................................................................*/
+	/** Gets the content width of the window (excluding the insets) */
+	public int getContentsWidth(){
+		///return	 (outerContents.getBounds().width);
+		Insets insets = getInsets();
+		return (getBounds().width);
+	}
+	/*.................................................................................................................*/
+	/** Gets the content width of the window (excluding the insets) */
+	public int getFullWidth(){
+		///return	 (outerContents.getBounds().width);
+		Insets insets = getInsets();
+		return (getBounds().width);
+	}
+	/*.................................................................................................................*/
+	/** Gets the content height of the window (excluding the insets) */
+	public int getContentsHeight(){
+		Insets insets = getInsets();
+		if (insets==null)
+			return (getBounds().height - infoBarHeight - explanationHeight -annotationHeight);
+		return (getBounds().height - infoBarHeight -explanationHeight -annotationHeight);
+	}
+	/*.................................................................................................................*/
+	/** Gets the content width of the graphics content area of the window (excluding the insets).  Also included tool palette if asked */
+	
+	public int getWidth(boolean includePalette){
+		if (graphics==null)
+			return 0;
+		if (graphics[0] == null || getBounds() == null)
+			return 0;
+		int baseWidth = getBounds().width;
+		if (!includePalette) {
+			ToolPalette palette =graphics[0].getPalette();
+			if (palette != null && palette.isVisible())
+				baseWidth -= palette.getWidth();
+		}
+		baseWidth -= graphics[0].getSidePanelWidth();
+
+		return baseWidth;
+	}
+	/*.................................................................................................................*/
+	/** Gets the content width of the graphics content area of the window (excluding the insets AND any palette) */
+	public int getWidth(){
+		return getWidth(false);
+	}
+	/*.................................................................................................................*/
+	/** Gets the content height of the window (excluding the insets) */
+	public int getHeight(){
+		if (graphics == null)
+			return 0;
+		if (graphics[0] == null)
+			return 0;
+		if (getBounds()==null)
+			return 0;
+		try {
+			return (getBounds().height - infoBarHeight - explanationHeight -annotationHeight) - graphics[0].getLedgePanelHeight();
+		}
+		catch (Exception e){
+		}
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindow(MesquiteDialog w){
+		centerWindow(w.getParentDialog());
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindow(MesquiteDialogParent w){
+		if (w.isWizard()){
+			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+			int v, h;
+			h = (screenSize.width-MesquiteDialog.wizardWidth)/2;
+			int menuBarHeight = 0;
+			if (!StringUtil.blank(System.getProperty("mrj.version")))
+				menuBarHeight = 32;
+			v = (screenSize.height-MesquiteDialog.wizardHeight - menuBarHeight)/2 + menuBarHeight;
+			if (v < menuBarHeight)
+				v = menuBarHeight;
+
+			w.setLocation(h, v);
+		}
+		else 
+			centerWindow((Window)w);
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindow(MesquiteWindow w){
+		MesquiteFrame f = w.getParentFrame();
+		if (f.getNumWindows()>1)
+			return; //don't center if other windows already tabbed in frame
+		centerWindow(w.getParentFrame(), true, true);
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindow(Window w){
+		centerWindow(w, true, true);
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindow(Window f, boolean horizontally, boolean vertically){
+
+		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+		int v, h;
+		if (horizontally)
+			h = (screenSize.width-f.getBounds().width)/2;
+		else
+			h = f.getBounds().x;
+		int menuBarHeight = 0;
+		if (!StringUtil.blank(System.getProperty("mrj.version")))
+			menuBarHeight = 32;
+		if (vertically) {
+			v = (screenSize.height-f.getBounds().height - menuBarHeight)/2 + menuBarHeight;
+			if (v < menuBarHeight)
+				v = menuBarHeight;
+		}
+		else
+			v = f.getBounds().y;
+
+		f.setLocation(h, v);
+	}
+	/*.................................................................................................................*/
+	/** Center the passed window in the screen */
+	public static void centerWindowTile(Window f, int tile){
+		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+		int fWidth = f.getBounds().width;
+		int fHeight = f.getBounds().height;
+		int screenWidth = screenSize.width;
+		int screenHeight = screenSize.height;
+		int screenTop = 0;
+		if (f instanceof ProgressWindow && ((ProgressWindow)f).isSpontaneous()){
+			if (MesquiteDialog.currentWizard != null && MesquiteDialog.currentWizard.isVisible())
+				screenTop = screenHeight - (screenHeight-MesquiteDialog.wizardHeight)/2;
+			else
+				screenTop = screenHeight - (screenHeight)/2;
+			screenHeight = screenHeight - screenTop;
+		}
+		if (tile==0) 
+			f.setLocation((screenWidth-fWidth)/2, screenTop + (screenHeight-fHeight)/2-48);
+		else if (tile==1) 
+			f.setLocation((screenWidth-fWidth)/2, screenTop + (screenHeight-fHeight)/2-48+fHeight+18);
+		else {
+			int tileVerAmount = (tile % 5)*(fHeight/2);
+			int tileHorAmount = (tile / 5)*(fWidth/2);
+			f.setLocation((screenWidth-fWidth)/2+tileHorAmount, screenTop + (screenHeight-fHeight)/2-48+tileVerAmount+fHeight+10);
+		}
+	}
+
+	/*--------------------------------WINDOW order ----------------------------------*/
+	/*.................................................................................................................*/
+	/** INCOMPLETE. 
+	public void toBack(){
+		super.toBack();
+		MesquiteMessage.warnProgrammer("Progammer: window.toBack() should be avoided until window ranks system works properly");
+	}
+/**/
+
+	/*.................................................................................................................*/
+	/** INCOMPLETE. */
+	public void toFront(){
+		if (doingShow)
+			return;
+		if (parentFrame == null)
+			return;
+		setVisible(true);
+		parentFrame.setAsFrontWindow(this);
+		if (isVisible() && rank!=highestRank) { //window of intermediate rank brought to front; must readjust ranks of all
+			rank = ++highestRank;
+		}
+	}
+	/*.................................................................................................................*/
+	/** INCOMPLETE. */
+	public int getRank(){
+		return rank;
+	}
+	/*.................................................................................................................*/
+
+	public boolean isVisible(){
+		return parentFrame != null && parentFrame.isVisible() && parentFrame.windowPresent(this);  
+	}
+	/*.................................................................................................................*/
+	boolean doingShow = false;
+
+
+	public void show(){
+		if (doingShow)
+			return;
+		setVisible(true);
+		parentFrame.setVisible(true);
+	}
+	/** Shows the window */
+	public void setVisible(boolean vis, boolean scripting) {
+		if (scripting && vis && isCompacted()){
+			setVisible(vis);
+			parentFrame.setVisible(true);
+		}
+		else
+			setVisible(vis);
+	}
+	public void removeAll(){
+		try {
+		outerContents.removeAll();
+		}
+		catch (Exception e){
+			// sometimes exceptions are thrown, possible because of mistimed threads
+		}
+	}
+	/** Shows the window */
+	public void setVisible(boolean vis) {
+		if (!vis && !closeable){
+			if (MesquiteTrunk.debugMode)
+				MesquiteMessage.printStackTrace("Using setVisible (false) before window is even instantiated!");
+			return;
+		}
+		if (doingShow)
+			return;
+		boolean wasVis = isVisible();
+		doingShow = true;
+		if (vis){
+			if (!GUIavailable || suppressAllWindows){
+				doingShow = false;
+				return;
+			}
+		}
+		if (parentFrame == null)
+			return;
+		if (orphan){
+			parentFrame.popIn(this);
+			orphan = false;
+		}
+		parentFrame.setVisible(this, vis);
+		if (vis)
+			parentFrame.setVisible(true);
+		doingShow = false;
+		if (!wasVis && vis && graphics != null && graphics[0]!=null && (!MesquiteTrunk.mesquiteTrunk.isStartupShutdownThread(Thread.currentThread()) || (!(this instanceof SystemWindow) && !(this instanceof mesquite.trunk.AboutWindow))))
+			graphics[0].requestFocusInWindow();
+	}
+	/*--------------------------------MENU BARS ----------------------------------*/
+	private final void deassign(MenuItem mi){
+		if (mi ==null)
+			return;
+		if (mi instanceof MesquiteMenuItem)
+			((MesquiteMenuItem)mi).disconnect();
+		else if (mi instanceof MesquiteCheckMenuItem)
+			((MesquiteCheckMenuItem)mi).disconnect();
+		else if (mi instanceof MesquiteSubmenu) {
+			((MesquiteSubmenu)mi).disconnect();
+			for (int k=0; k<((MesquiteSubmenu)mi).getItemCount(); k++) {
+				deassign( ((MesquiteSubmenu)mi).getItem(k));
+			}
+		}
+	}
+	public final void deassignMenus(){
+		if (menuBar!=null) {
+			try {
+				for (int i=0; i<menuBar.getMenuCount(); i++){  
+					Menu m = menuBar.getMenu(i);
+					for (int j = 0; j< m.getItemCount(); j++) {
+						deassign(m.getItem(j));
+					}
+				}
+				menuBar.disconnect();
+			}
+			catch (Exception e){
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** DEBUGGING */
+	public static void setReportMenuResets(boolean r){
+		reportMenuResets = r;
+	}
+	/*.................................................................................................................*/
+	/** Resets the menu bar of the window */
+	public void resetMenus(){
+
+		resetMenuTime.start();
+		deassignMenus();
+		MesquiteMenuBar tempMenuBar = new MesquiteMenuBar(this); //could delete??
+		resetMenuTime.end();
+		if (ownerModule==null) {
+			MesquiteMessage.printStackTrace("@@@@@@@@@@@@@@@@@@null ownerModule in window");
+			return;
+		}
+		else {
+			ownerModule.composeMenuBar(tempMenuBar, this); //could set to menuBar
+		}
+		resetMenuTime.start();
+		setMenuBar(tempMenuBar);  //IF THIS IS THE FIRST TIME, and size is not set afterward, should reset size
+		menuBar = tempMenuBar;//need to remember this in case anyone wants access to menu bar
+
+		menuResets++;
+		if (reportMenuResets)
+			System.out.println(Integer.toString(menuResets) + " menu resets for " + getTitle());
+		resetMenuTime.end();
+	}
+	public MesquiteMenuBar getMesquiteMenuBar(){
+		return menuBar;
+	}
+	public void setMinimalMenus(boolean minimal){
+		minimalMenus = minimal;
+	}
+	public boolean getMinimalMenus(){
+		return minimalMenus;
+	}
+
+	public MesquiteCommand getCopySpecialCommand() {
+		return null; 
+	}
+	public String getCopySpecialName() {
+		return "Copy Special"; 
+	}
+	public MesquiteCommand getPasteSpecialCommand() {
+		return null; 
+	}
+	public String getPasteSpecialName() {
+		return "Paste Special"; 
+	}
+	public MesquiteCommand getCutCommand() {
+		return null;
+	}
+	public MesquiteCommand getPasteCommand() {
+		return null; 
+	}
+	public MesquiteCommand getClearCommand() {
+		return null; 
+	}
+	public void selectAll() {
+		if (annotationHasFocus()){
+			annotationArea.getTextArea().selectAll();
+		}
+		else if (infoBar.getMode()==InfoBar.GRAPHICS) {
+			selectAllGraphicsPanel();
+		}
+		else {
+			TextArea textArea = infoBar.getTextArea(infoBar.getMode());
+			if (textArea!=null){
+				textArea.selectAll();
+			}
+		}
+	}
+
+	public void selectAllGraphicsPanel(){
+	}
+
+	public void copy(){
+		if (annotationHasFocus()){
+			String s = annotationArea.getTextArea().getSelectedText();
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(s);
+			clip.setContents(ss, ss);
+		}
+		else if (infoBar.getMode()==InfoBar.GRAPHICS) {
+			copyGraphicsPanel();
+		}
+		else {
+			infoBar.refreshText(infoBar.getMode());
+			TextArea textArea = infoBar.getTextArea(infoBar.getMode());
+			if (textArea!=null){
+				String s = textArea.getSelectedText();
+				if (StringUtil.blank(s))
+					s = textArea.getText();
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(s);
+				clip.setContents(ss, ss);
+			}
+		}
+
+	}
+	public void copyGraphicsPanel(){
+
+		Component focused = componentWithFocus();
+		if (focused != null && focused instanceof TextComponent){
+			String sel = ((TextComponent)focused).getSelectedText();
+			if (sel != null){
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(sel);
+				clip.setContents(ss, ss);
+				return;
+			}
+		}
+		infoBar.refreshText(InfoBar.TEXT_CONTENTS);
+		TextArea textArea = infoBar.getTextArea(InfoBar.TEXT_CONTENTS);
+		if (textArea!=null){
+			String s = textArea.getSelectedText();
+			if (StringUtil.blank(s))
+				s = textArea.getText();
+			if (StringUtil.blank(s))
+				return;
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			StringSelection ss = new StringSelection(s);
+			clip.setContents(ss, ss);
+		}
+	}
+
+	/*-------------------------------- COMMANDS  ----------------------------------*/
+	/*.................................................................................................................*/
+	/** Incorporate into the passed snapshot the complete snapshot commands for the window (including getWindow, tell It, and endTell)*/
+	public void incorporateSnapshot(Snapshot snap, MesquiteFile file){
+		Snapshot fromWindow =getSnapshot(file);
+		snap.addLine("getWindow");
+		snap.addLine("tell It");
+		snap.incorporate(fromWindow, true);
+		snap.addLine("endTell");
+	}
+	/*.................................................................................................................*/
+	/** Gets basic snapshot for window, including size, location. */
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (isPoppedOut() && compactWindows){
+			if (popAsTile)
+				temp.addLine("popAsTile true");
+			else
+				temp.addLine("popAsTile false");
+			temp.addLine("popOut");
+		}
+		//	if (getParentFrame().getWithTabWhenSaved())
+		//		temp.addLine("tabbedWhenSaved");
+		/*
+		 * if (showInfoBar)
+			temp.addLine("onInfoBar");
+		else
+			temp.addLine("offInfoBar");
+		 */
+		temp.addLine("setExplanationSize " + explanationHeight);
+		temp.addLine("setAnnotationSize " + annotationHeight);
+		temp.addLine("setFontIncAnnot " + StringUtil.tokenize(Integer.toString(annotationArea.fontIncrement)));
+		temp.addLine("setFontIncExp " + StringUtil.tokenize(Integer.toString(explanationArea.fontIncrement)));
+		temp.addLine("setSize " + getContentsWidth() + " " + getContentsHeight());
+		temp.addLine("setLocation " + getLocation().x + " " + getLocation().y);
+		temp.addLine("setFont " + ParseUtil.tokenize(currentFont.getName())); //fixed to tokenize 12 Oct 01
+		temp.addLine("setFontSize " + currentFont.getSize());
+		/*if (!StringUtil.blank(windowAnnotation.toString())) {
+    	 		temp.addLine("setAnnotation " + ParseUtil.tokenize(windowAnnotation.toString()));
+  	 	}
+		 */
+		if (graphics[0] != null && graphics[0].getPalette()!=null) {
+			temp.addLine("getToolPalette");
+			temp.addLine("tell It");
+			temp.incorporate(graphics[0].getPalette().getSnapshot(file), true);
+			temp.addLine("endTell");
+		}
+		if (getMode()>0)
+			temp.addLine("showPage " + getMode());
+		if (ownerModule != null && ownerModule.getProject()!=null && ownerModule.getProject().activeWindowOfProject == this)
+			temp.addLine("setActive"); //so that file save will remember foremost window
+
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public boolean setWindowFontSize(int fontSize) {
+		if (!MesquiteInteger.isCombinable(fontSize))
+			fontSize = MesquiteInteger.queryInteger(MesquiteWindow.windowOfItem(this), "Font size", "Font size for window", currentFont.getSize(), 4, 256);
+		if (!MesquiteInteger.isCombinable(fontSize))
+			return false;
+		Font fontToSet = new Font (currentFont.getName(), currentFont.getStyle(), fontSize);
+		setWindowFont(fontToSet);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void setWindowFont(String fontName) {
+		Font fontToSet = new Font (fontName, currentFont.getStyle(), currentFont.getSize());
+		setWindowFont(fontToSet);
+	}
+	MesquiteSubmenu fontSubmenu, fontSizeSubmenu;
+
+	Font getCurrentFont(){
+		return currentFont;
+	}
+	/*.................................................................................................................*/
+	public void setWindowFont(Font fontToSet) {
+		if (fontToSet!= null) {
+			currentFont = fontToSet;
+			//setFont(fontToSet);
+			setComponentFont(graphics[0], currentFont);
+			if (annotationArea!=null)
+				annotationArea.setFont(currentFont);
+			if (explanationArea!=null)
+				explanationArea.setFont(currentFont);
+			repaintAll();
+			if (fontSubmenu != null)
+				fontSubmenu.checkName(fontToSet.getName());
+			if (fontSizeSubmenu != null)
+				fontSizeSubmenu.checkName(Integer.toString(fontToSet.getSize()));
+		}
+		MesquiteTrunk.resetCheckMenuItems();
+	}
+	/*.................................................................................................................*/
+	/** Returns the MesquiteWindow containing the menu item*/
+	public void setComponentFont(Component c, Font f){
+		if (c==null)
+			return;
+
+		if (!(c instanceof MousePanel))  //only inherited as far as Mesquite specific
+			return;
+		if (c instanceof MousePanel && ((MousePanel)c).fontExplicitlySet())
+			return;
+		c.setFont(f);
+		if (MesquiteTrunk.isMacOSX())  //not needed on Mac; components inherite fonts from containers
+			return;
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					setComponentFont(cc[i], f);
+		}
+
+	}
+	
+	/*.................................................................................................................*/
+	public void setToPreviousTool() {
+		if (previousTool !=null) {
+			ToolPalette toolPalette = graphics[0].getPalette();
+			if (toolPalette!=null)
+				toolPalette.setCurrentTool(previousTool);
+			setCurrentTool(previousTool);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(MesquiteWindow.class, "Makes the window visible", null, commandName, "showWindow")) {
+			setVisible(true, MesquiteThread.isScripting());
+		}
+		else if (checker.compare(MesquiteWindow.class, "brings window to front", null, commandName, "setAsFront")) {
+			getParentFrame().showPage(this);
+		//	getParentFrame().showFrontWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Makes the window visible", null, commandName, "showWindowForce")) {
+			setVisible(true);
+			getParentFrame().showFrontWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Forces repaint of window", null, commandName, "forceRepaint")) {
+			repaintAll();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Pops Window out of project window (if compacted)", null, commandName, "popOut")) {
+			if (compactWindows && !isPoppedOut() && parentFrame != null)
+				parentFrame.popOut(this, false);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Indicates whether to pop as tile or separate window", "[true or false]", commandName, "popAsTile")) {
+			if (arguments != null && arguments.equalsIgnoreCase("true"))
+				setPopAsTile(true);
+			else
+				setPopAsTile(false);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Lists windows of frame", null, commandName, "frame")) {
+			parentFrame.diagnose();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Flips to window of frame", null, commandName, "first")) {
+			parentFrame.showFirstPage();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Flips to window of frame", null, commandName, "next")) {
+			parentFrame.showNextPage();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets this window to be foremost; to be used in scripting", null, commandName, "setActive")) {
+			if (ownerModule != null && ownerModule.getProject()!=null)
+				ownerModule.getProject().windowToActivate = this; //so that file read will restore foremost window
+		}
+		else if (checker.compare(MesquiteWindow.class, "Closes the window (calls owner module's windowGoAway)", null, commandName, "closeWindow")) {
+			closeWindow();
+		}
+		else if (checker.compare(this.getClass(), "Undoes the previous change in the window", null, commandName, "undo")) {
+			if (getUndoer()!=null){
+				Undoer[] undoers = getUndoer();
+				if (undoers!=null) {
+					Undoer[] newUndoers = new Undoer[undoers.length];
+					for (int i=0;i<undoers.length; i++)
+						if (undoers[i] != null)
+							newUndoers[i]=undoers[i].undo();
+					setUndoer(newUndoers);
+				}
+			}
+			else
+				MesquiteMessage.discreetNotifyUser( "Can't Undo");
+		}
+		else if (checker.compare(this.getClass(), "Sets the tool to the previous tool.", null, commandName, "setToPreviousTool")) {
+			setToPreviousTool();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Composes and shows the menu and control explanations web page", null, commandName, "showExplanations")) {
+			CommandChecker.showExplanations(graphics[0], getMenuBar(), getName()); 
+		}
+		else if (checker.compare(this.getClass(), "Shows the commands needed to put window and its modules into their current states", null, commandName, "showSnapshot")) {
+			if (getOwnerModule() == null)
+				return null;
+			FileCoordinator mb = getOwnerModule().getFileCoordinator();
+			if (mb!=null) {
+				String s = "Snapshot: commands needed to put window and its modules into their current states\n" + Snapshot.getSnapshotCommands(getOwnerModule(), null, "");
+				return mb.displayText(s, "Snapshot of commands");
+			}
+			else {
+				MesquiteModule.mesquiteTrunk.alert("Snapshot not available (no module associated with window)");
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Put text version of window into log", null, commandName, "text")) {
+			if (ownerModule !=null)
+				ownerModule.logln("Window " + getName() + "\n" + getTextContents());
+
+		}
+		else if (checker.compare(MesquiteWindow.class, "Copies current selection to clipboard", null, commandName, "copy")) {
+			copy();
+		}
+		else if  (checker.compare(MesquiteWindow.class, "Copies current selection to clipboard and clears from selection", null, commandName, "cut")) {
+			if (!annotationHasFocus()){
+				MesquiteCommand com = getCutCommand();
+				if (com!=null)
+					com.doItMainThread("", null, this);  // command invoked
+				else {
+					Component focused = componentWithFocus();
+					if (focused != null && focused instanceof TextComponent){
+						TextComponent tf = (TextComponent)focused;
+						String sel = tf.getSelectedText();
+						String all = tf.getSelectedText();
+						if (sel != null){
+							Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+							StringSelection ss = new StringSelection(sel);
+							clip.setContents(ss, ss);
+							if (tf.isEditable())
+								tf.setText(all.substring(tf.getSelectionStart(), tf.getSelectionEnd()));
+						}
+					}
+				}
+			}
+			else {
+				TextArea ta = annotationArea.getTextArea();
+				String s = ta.getSelectedText();
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(s);
+				clip.setContents(ss, ss);
+				ta.replaceRange("", ta.getSelectionStart(), ta.getSelectionEnd());
+				setAnnotation(ta.getText(), null);
+			}
+		}
+		else if  (checker.compare(MesquiteWindow.class, "Clears current selection", null, commandName, "clear")) {
+			if (!annotationHasFocus()){
+				MesquiteCommand com = getClearCommand();
+				if (com!=null)
+					com.doItMainThread("", null, this);  // command invoked
+			}
+			else {
+				TextArea ta = annotationArea.getTextArea();
+				ta.replaceRange("", ta.getSelectionStart(), ta.getSelectionEnd());
+				setAnnotation(ta.getText(), null);
+			}
+		}
+
+		else if  (checker.compare(MesquiteWindow.class, "Pastes from clipboard into current selection", null, commandName, "paste")) {
+			if (!annotationHasFocus()){
+				MesquiteCommand com = getPasteCommand();
+				if (com!=null)
+					com.doItMainThread("", null, this);  // command invoked
+			}
+			else {
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				try {
+				Transferable t = clip.getContents(this);
+					String s = (String)t.getTransferData(DataFlavor.stringFlavor);
+					if (s!=null) {
+						TextArea ta = annotationArea.getTextArea();
+						int st = ta.getSelectionStart();
+						ta.replaceRange(s, ta.getSelectionStart(), ta.getSelectionEnd());
+						Annotatable a = annotationArea.getAnnotatable();
+						if (a == null)
+							setAnnotation(ta.getText(), null);
+						else
+							a.setAnnotation(ta.getText(), true);
+						ta.setSelectionStart(st + s.length());
+						ta.setSelectionEnd(st + s.length());
+					}
+				}
+				catch(Exception e){
+					MesquiteMessage.printStackTrace(e);
+				}
+			}
+		}
+		else if  (checker.compare(MesquiteWindow.class, "Selects all", null, commandName, "selectAll")) {
+			selectAll();
+		}
+
+		else if (checker.compare(MesquiteWindow.class, "Presents dialog through which user can send commands to the module in charge of the window", null, commandName, "sendScript")) {
+			MesquiteModule module = getOwnerModule();
+			if (module!=null) {
+				Puppeteer p = new Puppeteer(module);
+				p.dialogScript(module, module.containerOfModule(), "owner module (" + module.getName() + ") of this window");
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Toggles whether this window is tiled out or not", null, commandName, "toggleTileOutWindow")) {  
+			if (isPoppedOut()){
+				popIn();
+				popOutWindowMSpec.setEnabled(true);
+			}
+			else {
+				setPopAsTile(true);
+				popOut(true);
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Toggles whether this window is popped out or not", null, commandName, "togglePopOutWindow")) { 
+			if (isPoppedOut())
+				popIn();  
+			else if (compactWindows){
+				setPopAsTile(false);
+				popOut(true);
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets which page of the window (graphics, text, explanations, parameters, employee tree, etc.) is showing", "[page number]", commandName, "showPage")) {
+			if (infoBar==null)
+				return null;
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int mode = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(mode)){
+				infoBar.setMode(mode);
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Prints the contents of the window", null, commandName, "printWindow")) {
+			prWindow(MesquitePrintJob.NATURAL);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Prints the contents of the window to fit a page", null, commandName, "printToFit")) {
+			prWindow(MesquitePrintJob.AUTOFIT);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sends the contents of the window to a PDF file",null,commandName,"printToPDF")) {
+			pdfWindow(MesquitePrintJob.AUTOFIT);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Opens the print window (for cases where the printing calls are separated)", null, commandName, "openPrintWindowToFit")) {
+			MainThread.incrementSuppressWaitWindow();
+			openPrWindow(MesquitePrintJob.AUTOFIT);
+			MainThread.decrementSuppressWaitWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Opens the print window (for cases where the printing calls are separated)", null, commandName, "openPrintWindow")) {
+			MainThread.incrementSuppressWaitWindow();
+			openPrWindow(MesquitePrintJob.NATURAL);
+			MainThread.decrementSuppressWaitWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class,  "Prints the window (for cases where the printing calls are separated)", null, commandName, "doPrintWindow")) {
+			MainThread.incrementSuppressWaitWindow();
+			doPrWindow();
+			MainThread.decrementSuppressWaitWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class,  "Closes the print window (for cases where the printing calls are separated)", null, commandName, "closePrintWindow")) {
+			MainThread.incrementSuppressWaitWindow();
+			closePrWindow();
+			MainThread.decrementSuppressWaitWindow();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Returns the tool palette of the window", null, commandName, "getToolPalette")) {
+			return graphics[0].getPalette();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Clones the window if possible", null, commandName, "cloneWindow")) {
+			MesquiteModule cloned = (MesquiteModule)ownerModule.getEmployer().cloneEmployee(ownerModule);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Saves a macro that serves as a macro to reproduce an analysis or window", null, commandName, "saveMacroForWindow")) {
+			saveWindowMacro(0);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Saves a macro that serves as a macro to reproduce an analysis or window", null, commandName, "saveMacroForAnalysis")) {
+			saveWindowMacro(MesquiteMacro.ANALYSIS);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Saves the text version of the window to a file", "[file name]", commandName, "saveTextToFile")) {
+			if (StringUtil.blank(arguments)) {
+				arguments = MesquiteFile.saveFileAsDialog("Save window text");
+				if (StringUtil.blank(arguments))
+					return null;
+				return saveTextToFile(arguments, false);
+			}
+			else
+				return saveTextToFile(MesquiteFile.composePath(ownerModule.getProject().getHomeDirectoryName(),ParseUtil.getFirstToken(arguments, pos)), false);
+
+		}
+		else if (checker.compare(MesquiteWindow.class, "Appends the text version of the window to an existing file", "[file name]", commandName, "appendTextToFile")) {
+			if (StringUtil.blank(arguments)) {
+				arguments = MesquiteFile.saveFileAsDialog("Append window text");
+				if (StringUtil.blank(arguments))
+					return null;
+				return saveTextToFile(arguments, true);
+			}
+			else
+				return saveTextToFile(MesquiteFile.composePath(ownerModule.getProject().getHomeDirectoryName(),ParseUtil.getFirstToken(arguments, pos)), true);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Toggles whether the information bar at the top of the window is shown or not", null, commandName, "toggleInfoBar")) { 
+			//setShowInfoBar(!showInfoBar); //todo why are this and the following two not replaced by a single setInfoBar [on or off]???
+		}
+		else if (checker.compare(MesquiteWindow.class, "Shows the information bar at the top of the window", null, commandName, "onInfoBar")) { 
+			//	if (!showInfoBar)
+			//		setShowInfoBar(true);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Hides the information bar at the top of the window", null, commandName, "offInfoBar")) { 
+			//	if (showInfoBar)
+			//		setShowInfoBar(false);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Executes the macro file", "[file name]", commandName, "doMacro")) { 
+			if (ownerModule!=null) {
+				Puppeteer p = new Puppeteer(ownerModule);
+				p.applyMacroFile(ParseUtil.getFirstToken(arguments, pos), ownerModule);
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Returns the module owning the window", null, commandName, "getOwnerModule")) { 
+			return ownerModule;
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the size of the window", "[width in pixels][height in pixels]", commandName, "setSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int width= MesquiteInteger.fromString(arguments, io);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(width) && MesquiteInteger.isCombinable(height)) {
+				fromScriptCommand = true;//this is needed to counteract difficulties with popping in/out and size setting in window constructors
+				setWindowSize(width, height);
+				fromScriptCommand = false;
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the height of the explanation area", "[height in pixels]", commandName, "setExplanationSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(height) && height>=0) {
+				fromScriptCommand = true;//this is needed to counteract difficulties with popping in/out and size setting in window constructors
+				setShowExplanation(height !=0,  height);
+				fromScriptCommand = false;
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the height of the annotation area", "[height in pixels]", commandName, "setAnnotationSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(height) && height>=0) {
+				fromScriptCommand = true;//this is needed to counteract difficulties with popping in/out and size setting in window constructors
+				setShowAnnotation(height !=0,  height);
+				fromScriptCommand = false;
+			}
+		}
+		/*
+    	 	else if (checker.compare(MesquiteWindow.class, "Sets the annotation for the window.", "[annotation]", commandName, "setAnnotation")) {
+   	 		if (useAnnotatableForAnnotation)
+   	 			return null;
+   	 		MesquiteInteger io = new MesquiteInteger(0);
+   	 		String note = ParseUtil.getToken(arguments, io);
+   	 		if (!StringUtil.blank(note)) {
+   	 			windowAnnotation.setValue(note);
+   	 			if (windowAnnotation == defaultAnnotation)
+   	 				setAnnotation(windowAnnotation, false, null);
+
+   	 		}
+    	 	}
+		 */
+		else if (checker.compare(MesquiteWindow.class, "Sets the location of the window", "[x coordinate of upper left][y coordinate of upper left]", commandName, "setLocation")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(x) && MesquiteInteger.isCombinable(y)) {
+				Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+				if (x> screenSize.width-16)
+					x=screenSize.width-64;
+				else if (x+getBounds().width<16)
+					x= 16 - getBounds().width;
+				if (y> screenSize.height-16)
+					y=screenSize.height-64;
+				else if (y+getBounds().height<16)
+					y= 16 - getBounds().height;
+				if (y<0)
+					y=0;
+				if (MesquiteTrunk.isMacOSX() && y<22 && x<0)  //workaround for bug in OS X; June 2004
+					x=0;
+				setWindowLocation(x, y, false, true);
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the font of the window", "[name of font]", commandName, "setFont")) {
+			String fontName = ParseUtil.getFirstToken(arguments, pos);
+			setWindowFont(fontName);
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the font size of the window", "[font size]", commandName, "setFontSize")) {
+			int fontSize = MesquiteInteger.fromString(arguments);
+			if (!setWindowFontSize(fontSize))
+				return null;
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the font size difference of the explanation area", "[font increment]", commandName, "setFontIncExp")) {
+			int fontInc = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(fontInc) && fontInc< 100 && fontInc > -100) {
+				explanationArea.fontIncrement= fontInc;
+				explanationArea.resetFont();
+			}
+			return null;
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the font size difference of the annotations area", "[font increment]", commandName, "setFontIncAnnot")) {
+			int fontInc = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(fontInc) && fontInc< 100 && fontInc > -100) {
+				annotationArea.fontIncrement= fontInc;
+				annotationArea.resetFont();
+			}
+			return null;
+		}
+		else if (checker.compare(MesquiteWindow.class, "Dumps to the log a list of the employees of the owner module", null, commandName, "listEmployees")) {
+			if (ownerModule!=null)
+				ownerModule.logln(ownerModule.listEmployees(""));
+		}
+		else if (checker.compare(this.getClass(), "Selects tree", "[number of tree][id of tree block]", commandName, "selectTree")) {
+			int whichPart = MesquiteInteger.fromFirstToken(arguments, pos);
+			int whichBlock = MesquiteInteger.fromString(arguments, pos);
+			selectPart(TreeVector.class, whichPart, whichBlock);		
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Touches taxon (selects it and shows it if possible)", "[number of taxon][id of taxa block]", commandName, "touchTaxon")) {
+			int whichPart = MesquiteInteger.fromFirstToken(arguments, pos);
+			int whichBlock = MesquiteInteger.fromString(arguments, pos);
+			selectPart(Taxa.class, whichPart, whichBlock);
+			Projects projects = MesquiteTrunk.getProjectList();
+			for (int i = 0; i<projects.getNumProjects(); i++){
+				MesquiteProject project = projects.getProject(i);
+				FileElement elem = project.getElementByID(Taxa.class, whichBlock);
+				if (elem != null && elem instanceof Taxa){
+					//taxa block found.  Tell all windows in project to select that 
+					Enumeration e = MesquiteTrunk.mesquiteTrunk.windowVector.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						MesquiteWindow mw = (MesquiteWindow)obj;
+						if (mw.isVisible() && mw.getOwnerModule()!=null && mw.getOwnerModule().getProject()== project)
+							mw.doCommand("showTaxon", "" + whichBlock + " " + whichPart, CommandChecker.quietDefaultChecker);
+					}
+				}
+			}
+			
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Selects character", "[number of character][id of character matrix]", commandName, "selectCharacter")) {
+			int whichPart = MesquiteInteger.fromFirstToken(arguments, pos);
+			int whichBlock = MesquiteInteger.fromString(arguments, pos);
+			selectPart(mesquite.lib.characters.CharacterData.class, whichPart, whichBlock);		
+			return null;
+		}
+		else {
+			//AFTERDEMO:
+			if (commandName!=null && !checker.getAccumulateMode() && checker.warnIfNoResponse) {
+				MesquiteMessage.warnProgrammer("Window " + getName() + " did not respond to command " + commandName + " with arguments (" + arguments + ")");
+			}
+		}
+		return null;
+	}
+
+	
+	private void selectPart(Class c, int whichPart, int whichBlock){
+		Projects projects = MesquiteTrunk.getProjectList();
+		for (int i = 0; i<projects.getNumProjects(); i++){
+			MesquiteProject project = projects.getProject(i);
+			FileElement elem = project.getElementByID(c, whichBlock);
+			if (elem != null){
+				elem.setSelected(whichPart, !elem.getSelected(whichPart));
+				elem.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+	}
+
+	private void saveWindowMacro(int preferredMenu){
+		MesquiteModule mb = ownerModule.getEmployer();
+		if (mb == null)
+			return;
+		String cloneCommand = mb.getClonableEmployeeCommand(ownerModule);
+
+		String beforeTell = "";
+		String afterTell = "endTell;\n";
+
+		while (mb !=null && mb.getModuleWindow()==null) {
+			beforeTell = "getEmployee " + "#" + mb.getClass().getName()  + ";\ntell It;\n" + beforeTell;
+			afterTell += "endTell;\n";
+
+			mb = mb.getEmployer();
+		}
+		MesquiteModuleInfo mmi = mb.getModuleInfo();
+		if (mmi == null)
+			return;
+		if (StringUtil.blank(cloneCommand))
+			beforeTell += "getEmployee " + "#" + ownerModule.getClass().getName() + ";\ntell It;\n";
+		else
+			beforeTell += cloneCommand + "\ntell It;\n";
+		String recipe =  beforeTell;
+		recipe += Snapshot.getSnapshotCommands(ownerModule, null, "");
+		recipe +=  afterTell;
+		MesquiteMacro.saveMacro(mb, "Untitled Macro for Window", preferredMenu, recipe);
+	}
+	/*.................................................................................................................*/
+
+	public String getName(){
+		return getTitle();
+	}
+
+	/*.................................................................................................................*/
+	Image icon;
+	public Image getIcon(){
+		return icon;
+	}
+	public void setIcon(String s){
+		icon = MesquiteImage.getImage(s);
+	}
+
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public abstract void resetTitle();
+	/*.................................................................................................................*/
+	public static void resetAllTitles(){
+		Enumeration e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			mw.resetTitle();
+			mw.infoBar.repaint();
+		}
+	}
+	/*.................................................................................................................*/
+	public static void repaintAllSearchStrips(){
+		/*
+		 * Enumeration e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.infoBar!= null && mw.infoBar.isVisible())
+				mw.infoBar.repaintSearchStrip();
+		}
+		*/
+		MesquiteTrunk.mesquiteTrunk.repaintSearchStrip();
+	}
+
+	/** to be called to add to log*/
+	public final void logln(String s) {
+		if (logText == null)
+			logText = new StringBuffer("Log for window" + getTitle() +  "\n");
+		logText.append(s + "\n");
+	}
+	/*.................................................................................................................*/
+	/** to be called to add to log*/
+	public final void log(String s) {
+		if (logText == null)
+			logText = new StringBuffer("Log for window" + getTitle() +  "\n");
+		logText.append(s);
+	}
+	/*.................................................................................................................*/
+	/** to be called to add to log*/
+	public final String getLogText() {
+		if (logText == null)
+			logText = new StringBuffer("Log for window" + getTitle() +  "\n");
+		return logText.toString();
+	}
+	/*.................................................................................................................*/
+	public void hide(){
+		if (parentFrame != null)
+			parentFrame.hide(this);
+		if (!suppressAllWindows && autoShow && noWindowsShowing() &&  !MesquiteTrunk.mesquiteTrunk.isDoomed()) {
+			MesquiteModule.mesquiteTrunk.doCommand("showAbout","", CommandChecker.defaultChecker);
+			if (!AlertDialog.query(MesquiteModule.mesquiteTrunk.containerOfModule(), "How to Quit", "If you hadn't intended to quit Mesquite, select \"Go back to Mesquite\"..  Because Mesquite needs at least one window open, the Mesquite window will be shown.  If you want to Force Quit right now, select \"Force Quit\" now (the standard and safer way to quit Mesquite is to select Quit Mesquite from the File menu).", "Go back to Mesquite", "Force Quit"))
+				MesquiteModule.mesquiteTrunk.doCommand("goAwayForceQuit",null, CommandChecker.defaultChecker);
+		}
+	}
+
+	/**/
+	public boolean disposed() {
+		return wasDisposed;
+	}
+	public void waitUntilDisposable() {
+		/*int pp = 0;
+		while (painting>0) {
+			try {
+				Thread.sleep(50);
+			}
+			catch (InterruptedException e) {
+				return;
+			}
+			if (++pp % 5 == 0){ //TODO: should be 1000 ??
+				MesquiteMessage.warnProgrammer("Waiting (" + pp + ") to dispose window " + getName() + " " +painting);
+			}
+			if (pp > 15)
+				return;
+		}
+		 */
+		if (painting>0) {
+			try {
+				Thread.sleep(50); //pause to allow some time to clean up
+			}
+			catch (InterruptedException e) {
+				return;
+			}
+		}
+	}
+	private void disposeAll(Component c){
+		if (c==null)
+			return;
+		if (c instanceof MousePanel)
+			((MousePanel)c).dispose();
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					disposeAll(cc[i]);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public void dispose() {
+		removeAll();
+		disposing = true;
+		numDisposing++;
+		if (ownerModule != null && ownerModule.getProject()!=null && ownerModule.getProject().activeWindowOfProject == this)
+			ownerModule.getProject().activeWindowOfProject = null;
+		hide();
+		waitUntilDisposable();
+		if (graphics != null)
+			disposeAll(graphics[0]);
+		disposeAll(palette);
+		disposeAll(explanationArea);
+		disposeAll(annotationArea);
+		if (windowTimer!=null)
+			windowTimer.end();
+		if (graphics != null)
+		removeKeyListener(graphics[0], currentTool); 
+		if (annotationArea!=null)
+			annotationArea.dispose();
+		if (explanationArea!=null)
+			explanationArea.dispose();
+		annotationArea.setExplanation((Annotatable)null); 
+		if (infoBar!=null)
+			infoBar.dispose();
+		if (ownerModule!=null)
+			ownerModule.setModuleWindow(null);
+		MesquiteModule.mesquiteTrunk.windowVector.removeElement(this, false);
+
+
+		deassignMenus();
+		if (parentFrame != null)
+			parentFrame.removePage(this);
+		ETContentArea etc = (ETContentArea)graphics[1];
+		outerContents.dispose();
+		if (infoBar!=null)
+			infoBar.dispose();
+		if (etc!=null)
+			etc.dispose();
+		menuBar=null;
+		wasDisposed = true;
+		ownerModule = null;
+
+
+		/*if (infoBarMenuItem !=null) {
+			infoBarMenuItem.disconnectable = true;
+			infoBarMenuItem.disconnect();
+		}*/
+		if (showCommand!=null){
+			showCommand.dispose();
+			showInfoBarCommand.dispose();
+			saveAsTextCommand.dispose();
+			printCommand.dispose();
+			printToFitCommand.dispose();
+			printToPDFCommand.dispose();
+			setFontCommand.dispose();
+			setFontSizeCommand.dispose();
+			listEmployeesCommand.dispose();
+			doMacroCommand.dispose();
+			showExplanationsCommand.dispose();
+			showSnapshotCommand.dispose();
+			sendScriptCommand.dispose();
+			showFileCommand.dispose();
+			closeWindowCommand.dispose();
+		}
+		showCommand=null;
+		showInfoBarCommand=null;
+		saveAsTextCommand.dispose();
+		printCommand=null;
+		printToFitCommand = null;
+		printToPDFCommand = null;
+		setFontCommand=null;
+		setFontSizeCommand =null;
+		listEmployeesCommand =null;
+		doMacroCommand = null;
+		showExplanationsCommand = null;
+		showSnapshotCommand = null;
+		sendScriptCommand = null;
+		showFileCommand = null;
+		closeWindowCommand = null;
+		MesquiteWindow.totalDisposed++;
+
+		//infoBarMenuItem =null;
+
+		if (parentFrame != null)
+			parentFrame.dispose(this);
+		parentFrame = null;
+		boolean done = false;
+		numDisposing--;
+		/*	while (!done){  //dangerous? but addressed bugs in OS X!
+			try {
+				parentFrame.dispose();
+				done = true;
+			}
+			catch (Exception e){
+				MesquiteMessage.warnProgrammer("Exception in disposing window " + e);
+				MesquiteFile.throwableToLog(this, e);
+				done = true;
+			}
+		}
+		 */
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	/*.................................................................................................................*/
+	/** windows with manually resized components (i.e. null layoutmanagers) can override to respond to window resizing here */
+	public void windowResized(){
+	}
+	/*.................................................................................................................*/
+	public void buttonHit(String label, Button button){
+		//buttons can use this to say to the window they've been hit
+	}
+	/*.................................................................................................................*/
+	protected void closeWindow(){
+		if (!(this instanceof SystemWindow)){
+			if (ownerModule!=null) {
+				if (getOwnerModule().isDoomed() || disposing)
+					return;
+				if (autoShow && noWindowsShowing(this, ownerModule.getProject())) {
+					FileCoordinator p = ownerModule.getFileCoordinator();
+					if (p!=null)  {
+						int response=2;
+						response = AlertDialog.query(MesquiteModule.mesquiteTrunk.containerOfModule(), "Close Project?", "You have just requested to close the last open window of a project.  If you want to close the project, select \"Close Project\".  Otherwise, select \"Continue\", which will bring up a small window to represent the project.", "Continue", "Close Project", "Cancel", 3);
+						if (response==1){  //hit close project;
+							p.closeFile(p.getProject().getHomeFile());
+							return;
+						} else if (response==2) //cancel
+							return;
+					}
+					ownerModule.windowGoAway(this);
+					if (p!=null) {
+						p.doCommand("showWindow","", CommandChecker.defaultChecker);
+					}
+					else
+						MesquiteMessage.warnProgrammer("file coord null");
+				}
+				else 
+					ownerModule.windowGoAway(this);
+			}
+			else {
+				hide();
+				dispose();
+			}
+		}
+		else
+			MesquiteMessage.println("This window cannot be closed without quitting Mesquite");
+		if (!suppressAllWindows && autoShow && noWindowsShowing()) {
+			MesquiteModule.mesquiteTrunk.doCommand("showAbout","", CommandChecker.defaultChecker);
+			if (!AlertDialog.query(MesquiteModule.mesquiteTrunk.containerOfModule(), "How to Quit", "If you hadn't intended to quit Mesquite, select \"Go back to Mesquite\"..  Because Mesquite needs at least one window open, the Mesquite window will be shown.  If you want to Force Quit right now, select \"Force Quit\" now (the standard and safer way to quit Mesquite is to select Quit Mesquite from the File menu).", "Go back to Mesquite", "Force Quit"))
+				MesquiteModule.mesquiteTrunk.doCommand("goAwayForceQuit",null, CommandChecker.defaultChecker);
+		}
+	}
+	boolean noWindowsShowing(MesquiteWindow w, MesquiteProject proj){
+		if (proj==null)
+			return noWindowsShowing();
+		if (MesquiteModule.mesquiteTrunk.windowVector.size() == 0)
+			return true;
+		else {
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				MesquiteWindow win = (MesquiteWindow)e.nextElement();
+				if (win != w && !win.minimalMenus && win.isVisible() && win.ownerModule!=null && win.ownerModule.getProject()==proj)
+					return false;
+			}
+			return true;
+		}
+	}
+	boolean noWindowsShowing(){
+		if (MesquiteModule.mesquiteTrunk.windowVector.size() == 0)
+			return true;
+		else {
+			Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				MesquiteWindow win = (MesquiteWindow)e.nextElement();
+				if (!win.minimalMenus && win.isVisible())
+					return false;
+			}
+			return true;
+		}
+	}
+	/*.................................................................................................................*/
+	/** This requests that simplicity strips be repainted.*/
+	public static final void resetAllSimplicity() {
+		Enumeration e = MesquiteModule.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw!=null) {
+				InfoBar ib = mw.infoBar;
+				if (ib != null) {
+					SimplicityStrip ss = ib.simplicityStrip;	
+					if (ss != null){
+						/*if (InterfaceManager.locked)
+							ss.setVisible(false);
+						else {*/
+						if (!ss.isVisible())
+							ss.setVisible(true);
+						ss.repaint();
+						//}
+					}
+				}
+			}
+		}
+		repaintAllWindows();
+		InterfaceManager.resetSimplicity();
+	}
+	String title = "Mesquite Window";
+	public void setTitle(String name) {
+		if (title != null && name != null && title.equals(name))
+			return;
+		title = name;
+		if (parentFrame != null)
+			parentFrame.windowTitleChanged(this);
+	}
+	public String getTitle() {
+		return title;
+	}
+	MenuBar mbar;
+	public void setMenuBar(MenuBar mbar) {
+		this.mbar = mbar;
+		if (parentFrame!=null)
+			parentFrame.setMenuBar(this, mbar);
+	}
+	public MenuBar getMenuBar() {
+		return mbar;
+	}
+	public void setResizable(boolean yes) {
+		if (parentFrame!=null)
+			parentFrame.setResizable(yes);
+	}
+
+
+	PopUpPanel quickPanel;
+	public void showQuickMessage( int xPixel, int yPixel,  String message){
+		showQuickMessage(getGraphicsArea(), null,xPixel, yPixel, message);
+	}
+	public void showQuickMessage(Panel panel, int xPixel, int yPixel,  String message){
+		showQuickMessage(panel, null,xPixel, yPixel, message);
+	}
+	public void showQuickMessage(Panel panel, Rectangle rect,int xPixel, int yPixel,  String message){
+		Rectangle boundingBox = rect;
+		if (boundingBox==null)
+			boundingBox = panel.getBounds();
+		int boxWidth = 96;
+		if (StringUtil.blank(message))
+			return;
+		if (quickPanel==null) {
+			panel.add(quickPanel = new PopUpPanel());
+			quickPanel.setBackground(ColorDistribution.sienna);
+		}
+		quickPanel.setText(message, panel.getFont(), boxWidth);
+		int offsetRight = 12;
+		StringInABox sb = quickPanel.getBox();
+		int xOffset = boundingBox.x;
+		int yOffset = boundingBox.y;
+		int xPos=0;
+		if (xPixel+boxWidth+8 + offsetRight>boundingBox.width) 
+			xPos = xPixel-boxWidth + xOffset;
+		else
+			xPos = xPixel+4 + xOffset + offsetRight;
+		int yPos=0;
+
+		if (yPixel+sb.getHeight()>boundingBox.height + yOffset && yPixel-sb.getHeight() + yOffset>=0)
+			yPos = yPixel-sb.getHeight() + yOffset;
+		else
+			yPos = yPixel + yOffset;
+		quickPanel.setSize(boxWidth +2, sb.getHeight() +2);
+		quickPanel.setLocation(xPos, yPos);
+		quickPanel.setVisible(true);
+		quickPanel.repaint();
+
+	}
+	/* ----------------------------------*/
+	public void hideQuickMessage(MesquiteChart chart){
+		if (quickPanel!=null)
+			quickPanel.setVisible(false);
+	}
+}
+
+
+
+class PopUpPanel extends Panel {
+	String t;
+	StringInABox sb;
+	void setText(String s, Font f, int w){
+		t = s;
+		sb = new StringInABox(t, f, w);
+	}
+	StringInABox getBox(){
+		return sb;
+	}
+	public void paint(Graphics g){
+		if (sb == null)
+			return;
+
+		sb.drawInBox(g, getBackground(), 3, 1);
+		g.setColor(Color.black);
+		g.drawRect(0,0,getBounds().width-1, getBounds().height-1);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/MesquiteXMLPreferencesModule.java b/Source/mesquite/lib/MesquiteXMLPreferencesModule.java
new file mode 100644
index 0000000..8eaf63a
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteXMLPreferencesModule.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hivemind.util.PropertyUtils;
+import org.dom4j.*;
+
+
+/**
+ * MesquiteModule subclass that automatically handles writing preferences to
+ * xml.  Simply override getPreferencePropertyNames to return the names of
+ * the properties one is interested in and they will automatically get
+ * serialized and de-serialized
+ * @author dmandel
+ *
+ */
+public abstract class MesquiteXMLPreferencesModule extends MesquiteModule implements PropertyNamesProvider {
+	private static final String VERSION = "version";
+	private static final String PREFERENCE = "preference";
+	private static final String KEY = "key";
+	
+	/**
+	 * Ideally this should not be static but since we don't always have control over the superclass,
+	 * make it available for classes that might otherwise not be able to use it due to inheritance
+	 * constraints
+	 * @param provider
+	 * @param versionInt
+	 * @return
+	 */
+	public static String preparePreferencesForXML (PropertyNamesProvider provider, int versionInt) {
+		String[] propertyNames = provider.getPreferencePropertyNames();
+		Element rootElement = DocumentHelper.createElement("mesquite");
+		Document preferencesDoc = DocumentHelper.createDocument(rootElement);
+		preferencesDoc.setRootElement(rootElement);
+		Element classElement = DocumentHelper.createElement(getShortClassName(provider.getClass()));
+		rootElement.add(classElement);
+		Element versionElement = DocumentHelper.createElement(VERSION);
+		versionElement.setText("" + versionInt);
+		classElement.add(versionElement);
+		for (int i = 0; i < propertyNames.length; i++) {
+			String currentPropertyName = propertyNames[i];
+			try {
+				Object prefsContent = PropertyUtils.read(provider, currentPropertyName);
+				if (prefsContent != null) {
+					Element nextPrefsElement = DocumentHelper.createElement(PREFERENCE);
+					nextPrefsElement.addAttribute(KEY, currentPropertyName);
+					nextPrefsElement.add(DocumentHelper.createCDATA(prefsContent.toString()));
+					classElement.add(nextPrefsElement);
+				}
+			} catch (Exception e) {
+				MesquiteMessage.warnProgrammer("Could not read property value " + currentPropertyName + " for writing xml preferences on module: " + provider);
+			}
+			//nextPrefsElement.addContent(new CDATA())
+		}
+		return XMLUtil.getDocumentAsXMLString(preferencesDoc);
+	}
+	/**
+	 * delegate to the static method
+	 */
+	protected boolean parseFullXMLDocument(String prefsXML) {
+		return parseFullXMLDocument(prefsXML, this, getVersionInt(), xmlPrefsVersionMustMatch());
+	}
+	/**
+	 * Ideally this should not be static but since we don't always have control over the superclass,
+	 * make it available for classes that might otherwise not be able to use it due to inheritance
+	 * constraints
+	 * @param prefsXML
+	 * @param provider
+	 * @param version
+	 * @param versionsMustMatch
+	 * @return
+	 */
+	public static boolean parseFullXMLDocument(String prefsXML, PropertyNamesProvider provider, 
+			int version, boolean versionsMustMatch) {
+		Document doc = XMLUtil.getDocumentFromString(prefsXML);
+		if (doc == null) {
+			// not xml -- can't parse it
+			return false;
+		}
+		Element rootElement = doc.getRootElement();
+		String shortClassName = getShortClassName(provider.getClass());
+		Element classElement = rootElement.element(shortClassName);
+		if (classElement != null) {
+			String versionString = classElement.elementText(VERSION);
+			int versionInXml = MesquiteInteger.fromString(versionString);
+			boolean acceptableVersion = (versionInXml == version || !versionsMustMatch);
+			if (isCorrectRootTag(classElement.getName(), provider.getClass()) && acceptableVersion) {
+				List prefsChildren = classElement.elements(PREFERENCE);
+				for (Iterator iter = prefsChildren.iterator(); iter.hasNext();) {
+					Element nextPreferenceElement = (Element) iter.next();
+					String key = nextPreferenceElement.attributeValue(KEY);
+					String value = nextPreferenceElement.getText();
+					try {
+						PropertyUtils.smartWrite(provider, key, value);
+					} catch (Exception e) {
+						MesquiteMessage.warnProgrammer("Could not write property value " + key + " for loading xml preferences on module: " + provider);
+					}
+				}
+				return true;			
+			}
+		}
+		return false;
+	}
+	/**
+	 * delegate to the static method
+	 * @param versionInt
+	 * @return
+	 */
+	public String preparePreferencesForXML() {
+		return MesquiteXMLPreferencesModule.preparePreferencesForXML(this, getVersionInt());
+	}
+}
diff --git a/Source/mesquite/lib/MesquiteXMLUtilities.java b/Source/mesquite/lib/MesquiteXMLUtilities.java
new file mode 100644
index 0000000..5a5e42e
--- /dev/null
+++ b/Source/mesquite/lib/MesquiteXMLUtilities.java
@@ -0,0 +1,121 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.util.Map;
+
+
+import org.dom4j.*;
+import mesquite.tol.lib.*;
+
+import mesquite.tol.lib.XMLConstants;
+
+/**
+ * Class used for xml communication over http
+ * 
+ * Note that this class is currently NOT thread safe --
+ * only one thread may use it at a time
+ * @author dmandel
+ * 
+ * 25 Feb 08:  made it thread safe by removing dependency on static Strings - DRM
+ *
+ */
+public class MesquiteXMLUtilities {
+	private static String checkConnectionURL = "http://google.com";
+	//public static String baseDatabaseURL = "http://btol.tolweb.org/onlinecontributors/app"; 	
+	//public static String baseDatabaseURL = "http://zissou.cals.arizona.edu/onlinecontributors/app";	
+	//private static String databaseURL = baseDatabaseURL + "?page=";
+	/**
+	 * tapestry application name
+	 */
+	protected static final String HTTP = "http://";
+	
+	public static Document getDocumentFromTapestryPageName(String url, String pageName, Map args) {
+		return getDocumentFromTapestryPageName(url, pageName, args, false);
+	}
+	public static Document getDocumentFromTapestryPageNameMultipart(String databaseURL,String pageName, Map stringArgs, 
+			Map fileArgs) {
+		String url = databaseURL;
+		// need this here so tapestry will call the external service
+		stringArgs.put("page", pageName);
+		try {
+			Document returnDoc = BaseHttpRequestMaker.getTap4ExternalUrlDocumentMultipart(url, pageName, 
+		    		stringArgs, fileArgs);
+			return returnDoc;
+		} catch (Exception e) {
+			e.printStackTrace();
+			// error in communication, likely a dead connection on one end or the other
+			return null;
+		}
+	}
+	public static Document getDocumentFromTapestryPageName(String url, String pageName, Map args, boolean isPost) {
+		Document returnDoc = null;
+		args.put("service", "external");
+		if (checkConnection()) {
+			//String url = getDatabaseURL();
+			try {
+				returnDoc = BaseHttpRequestMaker.getTap4ExternalUrlDocument(url, 
+						pageName, args, isPost);
+			} catch (Exception e) {
+				// communication error, allow doc to remain null
+			}
+			if (returnDoc == null || returnDoc.getRootElement() == null) {
+				returnDoc = null;
+			}
+		} else {
+			String error = "You don't appear to have an internet connection.  This operation cannot complete without a connection";
+			MesquiteMessage.println(error);
+		}
+		return returnDoc;
+	}
+	
+	public static Document getDocumentFromString(String docString) {
+		return XMLUtil.getDocumentFromString(docString);		
+	}
+	
+	public static Document getDocumentFromFilePath(String path) {
+		String docString = MesquiteFile.getFileContentsAsString(path);
+		return getDocumentFromString(docString);
+	}
+	
+	public static void outputRequestXMLError() {
+		String errorMessage = "A network error has occurred, this usually means one of three things:\n(1) You don't have an internet connection" + 
+		"\n(2) The server you are attempting to contact is having problems"+
+		"\n(3) The information sent from the server is not formatted in a way Mesquite can understand."+
+			"\nPlease make sure you have an internet connection and try again.";
+		MesquiteMessage.warnUser(errorMessage);
+	}
+	
+	private static boolean checkConnection() {
+		/*byte[] bytes = BaseHttpRequestMaker.makeHttpRequest(checkConnectionURL);
+		return bytes != null;*/
+		return true;
+	}
+	/*
+	public static String getDatabaseURL() {
+		return databaseURL;
+	}
+	/**
+	 * This needs to be called before any database communication can occur
+	 * @param URL
+	 */
+	
+
+	
+	
+	public static boolean getIsError(Document doc) {
+		return doc == null || doc.getRootElement() == null ||
+			doc.getRootElement().getName().equals(XMLConstants.ERROR);		
+	}
+}
diff --git a/Source/mesquite/lib/MessagePanel.java b/Source/mesquite/lib/MessagePanel.java
new file mode 100644
index 0000000..b1e0cb7
--- /dev/null
+++ b/Source/mesquite/lib/MessagePanel.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A panel at the bottom of a table or window that can be used for temporary messages.*/
+public class MessagePanel extends Panel {
+	String message;
+	Color textColor;
+	boolean outline = true;
+	public MessagePanel(int colorScheme) {  
+		super();
+		message="";
+		setBackground(ColorTheme.getInterfaceBackground());
+		
+	}
+	public MessagePanel(Color background, boolean outline) {  
+		super();
+		message="";
+		setBackground(background);
+		this.outline = outline;
+	}
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (outline)
+			g.drawRect(0,0, getBounds().width, getBounds().height-1);
+		if (textColor !=null)
+			g.setColor(textColor);
+		if (message != null)
+			g.drawString(message,  4, 12);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void setTextColor(Color c){
+		textColor = c;
+	}
+	public void setMessage(String s) {
+		if (s==null)
+			message = "";
+		else
+			message = s;
+		repaint();
+	}
+	public String getMessage(){
+		return message;
+	}
+}
+
diff --git a/Source/mesquite/lib/MiniControl.java b/Source/mesquite/lib/MiniControl.java
new file mode 100644
index 0000000..0567587
--- /dev/null
+++ b/Source/mesquite/lib/MiniControl.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+public interface MiniControl  {
+	public void acceptText();
+}
+
+
diff --git a/Source/mesquite/lib/MiniNumberEditor.java b/Source/mesquite/lib/MiniNumberEditor.java
new file mode 100644
index 0000000..000eb0f
--- /dev/null
+++ b/Source/mesquite/lib/MiniNumberEditor.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/*=================*/
+public class MiniNumberEditor extends MiniStringEditor{
+	double origDouble = MesquiteDouble.impossible;
+	public MiniNumberEditor (MesquiteModule ownerModule,  MesquiteCommand command) {
+		super(ownerModule, command);
+	}
+ 	public void acceptText(){
+			String resultString= null;
+			String newText =text.getText();
+			if (!origText.equals(newText)) {
+				double newS =MesquiteDouble.fromString(newText);
+				if (newS!=origDouble)
+					resultString = MesquiteDouble.toStringDigitsSpecified(newS, -1); //changed 17 Dec for full accuracy
+ 			}
+ 			command.doItMainThread(resultString, CommandChecker.getQueryModeString("Mini number editor", command, this), this);  
+ 	}
+
+	public void setNumber(double s){
+		origText = MesquiteDouble.toStringDigitsSpecified(s, -1);//changed 17 Dec for full accuracy
+		origDouble =s;
+		text.setText(origText);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MiniScroll.java b/Source/mesquite/lib/MiniScroll.java
new file mode 100644
index 0000000..b657844
--- /dev/null
+++ b/Source/mesquite/lib/MiniScroll.java
@@ -0,0 +1,467 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/** A miniature scroller used in the tree window and trace character legends.  It provides
+an incrementing and decrementing arrow, and a text field to show current value. */
+public class MiniScroll extends MousePanel implements MiniControl, Explainable, ImageOwner, ActionListener, TextListener {
+	public long currentValue, minValue, maxValue;
+	ScrollTextField tf;
+	TextField dummy;
+	MiniScrollButton decrementButton, incrementButton;
+	String itemName="";
+	EnterButton enterButton;
+	private int textBoxWidth = 34;
+	private int textBoxHeight = 18;
+	private int arrowHeight = 26;
+	public int totalWidth = 0;  
+	public int totalHeight=0; 
+	private int oldTextBoxWidth = 1;
+	private int oldTextBoxHeight = 1;
+	Color bg = Color.white;
+
+	public boolean stacked = false;
+	public boolean horizontal = false;
+	MesquiteCommand command;
+	//int enterWidth = 8;
+	// be passed max and min values  
+	
+	public MiniScroll (MesquiteCommand command, boolean stacked, int currentValue, int minValue, int maxValue, String itemName) {
+		this(command, stacked, true, (long)currentValue,  (long)minValue,  (long)maxValue, itemName);
+	}
+	public MiniScroll (MesquiteCommand command, boolean stacked, boolean horizontal, int currentValue, int minValue, int maxValue, String itemName) {
+		this(command, stacked, horizontal,  (long)currentValue,  (long)minValue,  (long)maxValue, itemName);
+	}
+	public MiniScroll (MesquiteCommand command, boolean stacked, long currentValue, long minValue, long maxValue, String itemName) {
+		this(command, stacked, true, currentValue, minValue, maxValue, itemName);
+	}
+	
+	public MiniScroll (MesquiteCommand command, boolean stacked, boolean horizontal,long currentValue, long minValue, long maxValue, String itemName) {
+		this.currentValue = currentValue;
+		this.itemName = itemName;
+		this.minValue = minValue;
+		this.maxValue = maxValue;
+		this.stacked = stacked; 
+		this.horizontal = horizontal; 
+		this.command=command;
+		if (!horizontal && !stacked){
+			totalWidth = textBoxWidth + 10;
+			totalHeight = textBoxHeight + 40 + EnterButton.MIN_DIMENSION+2;
+		}
+		else if (stacked) {
+			totalWidth = textBoxWidth  + EnterButton.MIN_DIMENSION+2;
+			totalHeight = textBoxHeight + 28;
+		}
+		else  {
+			totalWidth = textBoxWidth + 40 + EnterButton.MIN_DIMENSION+2;
+			totalHeight = textBoxHeight + 2;
+		}
+		setSize(totalWidth, totalHeight);
+		setLayout(null);
+		if (this.horizontal){
+			add(decrementButton= new MiniScrollButton(this, MiniScrollButton.LEFT, itemName));
+			add(incrementButton= new MiniScrollButton(this, MiniScrollButton.RIGHT, itemName));
+		}
+		else {
+			add(decrementButton= new MiniScrollButton(this, MiniScrollButton.DOWN, itemName));
+			add(incrementButton= new MiniScrollButton(this, MiniScrollButton.UP, itemName));
+		}
+		add(enterButton = new EnterButton(this, horizontal || stacked));
+		add(tf = new ScrollTextField(this, Long.toString(currentValue), 2));
+		tf.setVisible(false);
+		tf.addActionListener(this);
+		tf.addTextListener(this);
+		tf.setSize(5, 5);
+		tf.setLocation(5,5);
+
+		add(dummy = new TextField(""));
+		dummy.setEditable(false);
+		dummy.setSize(0,0);
+		dummy.setBackground(bg);
+		dummy.setLocation(0,0);
+
+		decrementButton.setVisible(false);
+		incrementButton.setVisible(false);
+		enterButton.setVisible(false);
+		if (horizontal){
+			if (stacked) {
+				tf.setSize(1, 1);
+				decrementButton.setLocation(2,arrowHeight);
+				incrementButton.setLocation(totalWidth-20,arrowHeight);
+			}
+			else {
+				tf.setSize( 1, 1);
+				decrementButton.setLocation(0,2);
+				tf.setLocation(decrementButton.getBounds().x + decrementButton.getBounds().width, 2);
+				incrementButton.setLocation(tf.getBounds().x + tf.getBounds().width + EnterButton.MIN_DIMENSION+1,2);
+			}
+		}
+		else {
+			if (stacked) {
+				tf.setSize(1, 1);
+				decrementButton.setLocation(2,arrowHeight);
+				incrementButton.setLocation(totalWidth-26,arrowHeight);
+			}
+			else {
+				tf.setSize( 1, 1);
+				incrementButton.setLocation(0,0);
+				tf.setLocation(0, decrementButton.getBounds().height+6);
+				decrementButton.setLocation(0, tf.getBounds().y + tf.getBounds().height + EnterButton.MIN_DIMENSION+1);
+			}
+		}
+
+		tf.setBackground(bg);
+		setBackground(bg);
+		enterButton.setEnabled(false);
+		decrementButton.setEnabled(currentValue>minValue);
+		incrementButton.setEnabled(currentValue<maxValue);
+	}
+	public int getTotalHeight(){
+		return totalHeight;
+	}
+	public int getTotalWidth(){
+		return totalWidth;
+	}
+	Font oldFont = null;
+	String text=null;
+	String oldText=null;
+	int sw = 0;
+	int sh = 0;
+	
+	private boolean recalcPositions(Graphics g){
+		Font f =  g.getFont();
+		if (f != oldFont || !(StringUtil.stringsEqual(oldText, text))){
+			FontMetrics fm = g.getFontMetrics(f);
+			sw = MesquiteInteger.maximum(fm.stringWidth("888"), fm.stringWidth(tf.getText()));
+			sh = fm.getMaxAscent()+fm.getMaxDescent();
+			
+		}
+		oldText = text;
+		oldFont = f;
+		if (oldTextBoxWidth < sw + MesquiteModule.textEdgeCompensationWidth -1 || oldTextBoxHeight < sh + MesquiteModule.textEdgeCompensationHeight -1){
+			textBoxWidth = sw + MesquiteModule.textEdgeCompensationWidth; //34
+			textBoxHeight =  sh + MesquiteModule.textEdgeCompensationHeight; //18
+			oldTextBoxWidth = textBoxWidth;
+			oldTextBoxHeight = textBoxHeight;
+			if (horizontal){
+				if (stacked) {
+					totalWidth = textBoxWidth +  EnterButton.MIN_DIMENSION+2;
+					totalHeight = textBoxHeight + 20;
+					setSize(totalWidth, totalHeight);
+					tf.setSize(textBoxWidth, textBoxHeight);
+					tf.setLocation(0, 0);
+					decrementButton.setLocation(2,textBoxHeight+4);
+					incrementButton.setLocation(totalWidth-20,textBoxHeight+4);
+				}
+				else  {
+					totalWidth = textBoxWidth +36  +  EnterButton.MIN_DIMENSION+2;
+					totalHeight = textBoxHeight+4;
+					setSize(totalWidth, totalHeight);
+					tf.setSize( textBoxWidth, textBoxHeight);
+					decrementButton.setLocation(0,2);
+					tf.setLocation(decrementButton.getBounds().x + decrementButton.getBounds().width + 1, 0);  // 1 added to x
+					incrementButton.setLocation(tf.getBounds().x + tf.getBounds().width + EnterButton.MIN_DIMENSION+2,2);  //1 added to x
+				}
+				enterButton.setLocation(tf.getBounds().x + tf.getBounds().width+1, 2);
+			}
+			else {
+				if (stacked) {
+					totalWidth = textBoxWidth +  EnterButton.MIN_DIMENSION+2;
+					totalHeight = textBoxHeight + 20;
+					setSize(totalWidth, totalHeight);
+					tf.setSize(textBoxWidth, textBoxHeight);
+					tf.setLocation(0, 0);
+					decrementButton.setLocation(2,textBoxHeight + 4);
+					incrementButton.setLocation(totalWidth-22,textBoxHeight+4);	
+					enterButton.setLocation(tf.getBounds().x + tf.getBounds().width+1, 2);
+				}
+				else  {
+					totalWidth = textBoxWidth; //should be 0
+					totalHeight = textBoxHeight + 36 +  EnterButton.MIN_DIMENSION+2;
+
+					setSize(totalWidth, totalHeight);
+					tf.setSize( textBoxWidth, textBoxHeight);
+					incrementButton.setLocation(1,2);
+					tf.setLocation(0, incrementButton.getBounds().height+3);
+					decrementButton.setLocation(1, tf.getBounds().y + tf.getBounds().height + EnterButton.MIN_DIMENSION+2);
+					enterButton.setLocation(1, tf.getBounds().y + tf.getBounds().height+1);
+				}
+			}
+			incrementButton.repaint();
+			decrementButton.repaint();
+			enterButton.repaint();
+			repaint();
+			getParent().repaint();
+			return true;
+		}
+		if (checkBackground()){
+			repaint();
+			return true;
+		}
+	/*	if (!getBackground().equals(getParent().getBackground())) {
+			bg =getParent().getBackground();
+			setBackground(bg);
+			//setBackground(Color.green);
+			tf.setBackground(bg);
+			decrementButton.setBackground(bg);
+			incrementButton.setBackground(bg);
+			enterButton.setBackground(bg);
+			repaint();
+			return true;
+		}*/
+		return false;
+	}
+	
+	
+	public void repaint(){
+		text = tf.getText();
+		Graphics g = getGraphics();
+		if (g!= null){
+			recalcPositions(g);
+			g.dispose();
+		}
+		super.repaint();
+	}
+	boolean neverCalculated = true;
+	public void paint(Graphics g) { //^^^
+		if (g instanceof PrintGraphics)
+			return;
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		/**/
+		if (getParent()==null ) {
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+		if (neverCalculated){
+			if (recalcPositions(g)){
+				MesquiteWindow.uncheckDoomed(this);
+				neverCalculated = false;
+				return;
+			}
+		}
+		/**/	
+		/* This stuff below seems unnecessary, but for some reason on MacOS 8.1/MRJ 2.0 it was leaving garbage around; likewise for components*/
+		g.setColor(getBackground());
+		g.fillRect(getBounds().x,getBounds().y,getBounds().width,getBounds().height);
+		g.setColor(Color.black);
+		//tf.repaint();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void printAll(Graphics g) { 
+	}
+	public void paintComponents(Graphics g) { 
+		if (g instanceof PrintGraphics)
+			return;
+		else
+			super.paintComponents(g);
+	}
+	public void printComponents(Graphics g) { 
+	}
+	public void print(Graphics g) { 
+	}
+	private boolean checkBackground(){
+		if (getParent() !=null && getBackground()!=null && !getBackground().equals(getParent().getBackground())) {
+			bg =getParent().getBackground();
+			setBackground(bg);
+			//setBackground(Color.green);
+			if (tf!=null)
+				tf.setBackground(bg);
+			if (decrementButton!=null)
+				decrementButton.setBackground(bg);
+			if (incrementButton!=null)
+				incrementButton.setBackground(bg);
+			if (enterButton!=null)
+				enterButton.setBackground(bg);
+			return true;
+		}
+		else return false;
+	}
+	public void setVisible(boolean b) {
+		if (b)
+			checkBackground();
+		super.setVisible(b);
+		tf.setVisible(b);
+		decrementButton.setVisible(b);
+		incrementButton.setVisible(b);
+		enterButton.setVisible(b);
+		repaint();
+	}
+	public void setColor(Color c) {
+		tf.setForeground(c);
+	}
+	boolean enterLock = false;
+	public void setEnterLock(boolean lock){
+		enterLock = lock;
+		if (!lock){
+			boolean b = (currentValue<=maxValue && currentValue>=minValue);
+			enterButton.setEnabled(b);
+		}
+		else
+			enterButton.setEnabled(false);
+	}
+	public void setEnableEnter(boolean en){
+		if (enterLock)
+			return;
+		enterButton.setEnabled(en);
+	}
+	public void setMaximumValue (int i) { 
+		if (i!=maxValue) {
+			maxValue=i;
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public void setMinimumValue (int i) { 
+		if (i!=minValue) {
+			minValue=i;
+			decrementButton.setEnabled(currentValue>minValue);
+		}
+	}
+	public void setMaximumValueLong (long i) { 
+		if (i!=maxValue) {
+			maxValue=i;
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public void setMinimumValueLong (long i) { 
+		if (i!=minValue) {
+			minValue=i;
+			decrementButton.setEnabled(currentValue>minValue);
+		}
+	}
+
+	public void setCurrentValue (int i) {  
+		if (i<=maxValue && (i>=minValue)) {
+			currentValue=i;
+			tf.setText(Integer.toString((int)currentValue));
+			decrementButton.setEnabled(currentValue>minValue);
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public int getCurrentValue () {  
+		return (int)currentValue;
+	}
+	public void setCurrentValueLong (long i) {  
+		if (i<=maxValue && (i>=minValue)) {
+			currentValue=i;
+			tf.setText(Long.toString(currentValue));
+			decrementButton.setEnabled(currentValue>minValue);
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public long getCurrentValueLong () {  
+		return currentValue;
+	}
+
+	public void acceptText(){
+		String s = tf.getText();
+		oldText = null;
+		text = s;
+		try {
+			int value = MesquiteInteger.fromString(s);
+			crement(value);
+		}
+		catch (NumberFormatException e){}
+	}
+	public void actionPerformed(ActionEvent e){
+		//Event queue
+			acceptText();
+	}
+	
+	 public boolean isTextValid() {
+	 	boolean b = false;
+		String s = tf.getText();
+		try {
+			int value = MesquiteInteger.fromString(s);
+			b = (value<=maxValue && value>=minValue);
+		}
+		catch (NumberFormatException e){}
+		return b;
+	}
+	 public void textValueChanged(TextEvent e) {
+		boolean b = false;
+		String s = tf.getText();
+		try {
+			int value = MesquiteInteger.fromString(s);
+			b = (value<=maxValue && value>=minValue && value!=currentValue);
+		}
+		catch (NumberFormatException ex){}
+	 	enterButton.setEnabled(b && !enterLock);
+	}
+
+
+	public void crement (int i) {  
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Mini scroll", command, this);
+			return;
+		}
+		if (i<=maxValue && (i>=minValue) && command!=null) {
+			currentValue=i;
+			command.doItMainThread(Long.toString(currentValue), CommandChecker.getQueryModeString("Mini scroll", command, this), this);
+			tf.setText(Long.toString(currentValue));
+			decrementButton.setEnabled(i>minValue);
+			incrementButton.setEnabled(i<maxValue);
+		}
+	}
+	public void increment () {  // have interface incrementable and pass object to this miniscroll so it can notify object
+ 		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Mini scroll", command, this);
+			return;
+		}
+		if (currentValue<maxValue && command!=null) {
+			currentValue++;
+			command.doItMainThread(Long.toString(currentValue), CommandChecker.getQueryModeString("Mini scroll", command, this), this);
+			tf.setText(Long.toString(currentValue));
+			enterButton.setEnabled(false);
+			decrementButton.setEnabled(currentValue>minValue);
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public void decrement () {
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Mini scroll", command, this);
+			return;
+		}
+		if (currentValue>minValue && command!=null) {
+			currentValue--;
+			tf.setText(Long.toString(currentValue));
+			command.doItMainThread(Long.toString(currentValue), CommandChecker.getQueryModeString("Mini scroll", command, this), this);
+			enterButton.setEnabled(false);
+			decrementButton.setEnabled(currentValue>minValue);
+			incrementButton.setEnabled(currentValue<maxValue);
+		}
+	}
+	public String getExplanation(){ //TODO: this should use string passed in constructor
+		return "This is a mini-scroll";
+	}
+	public String getImagePath(){ //TODO: this should use path to standard image
+		if (stacked)
+			return MesquiteModule.getRootPath() + "images/miniscrollVert.gif"; 
+		else
+			return MesquiteModule.getRootPath() + "images/miniscrollHoriz.gif"; 
+	}
+	
+}
+
+
+
+
diff --git a/Source/mesquite/lib/MiniScrollButton.java b/Source/mesquite/lib/MiniScrollButton.java
new file mode 100644
index 0000000..81654b6
--- /dev/null
+++ b/Source/mesquite/lib/MiniScrollButton.java
@@ -0,0 +1,265 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/** arrow for MiniScroll*/
+public class MiniScrollButton extends MousePanel {
+	public MiniScroll miniScroll;
+	Polygon arrowPoly;
+	int orientation;
+	public static final int UP = 0;
+	public static final int RIGHT = 1;
+	public static final int DOWN =2;
+	public static final int LEFT = 3;
+	boolean disabled = false, pressed = false;
+	public static Image leftArrow,leftArrowPressed, leftArrowDisabled;
+	public static Image rightArrow,rightArrowPressed, rightArrowDisabled;
+	public static Image upArrow,upArrowPressed, upArrowDisabled;
+	public static Image downArrow,downArrowPressed, downArrowDisabled;
+	private boolean firsttime=true;
+	String itemName="";
+	
+	static {
+		leftArrow = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "leftarrow.gif");
+		leftArrowPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "leftarrowPressed.gif");
+		leftArrowDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "leftarrowDisabled.gif");
+		rightArrow = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "rightarrow.gif");
+		rightArrowPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "rightarrowPressed.gif");
+		rightArrowDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "rightarrowDisabled.gif");
+		upArrow = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "uparrow.gif");
+		upArrowPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "uparrowPressed.gif");
+		upArrowDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "uparrowDisabled.gif");
+		downArrow = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "downarrow.gif");
+		downArrowPressed = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "downarrowPressed.gif");
+		downArrowDisabled = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "downarrowDisabled.gif");
+	}
+	public MiniScrollButton (MiniScroll miniScroll, int orientation, String itemName) {
+		this.orientation = orientation;
+		this.miniScroll = miniScroll;
+		this.itemName = itemName;
+		arrowPoly= new Polygon();
+		arrowPoly.xpoints = new int[4];
+		arrowPoly.ypoints = new int[4];
+		if (orientation==LEFT) {
+			arrowPoly.npoints=0;
+			arrowPoly.addPoint(1, 7);
+			arrowPoly.addPoint(15, 15);
+			arrowPoly.addPoint(15, 0);
+			arrowPoly.addPoint(1, 7);
+			arrowPoly.npoints=4;
+		}
+		else if (orientation == RIGHT){
+			arrowPoly.npoints=0;
+			arrowPoly.addPoint(15, 7);
+			arrowPoly.addPoint(1, 15);
+			arrowPoly.addPoint(1, 0);
+			arrowPoly.addPoint(15, 7);
+			arrowPoly.npoints=4;
+		}
+		else if (orientation==UP) {
+			arrowPoly.npoints=0;
+			arrowPoly.addPoint(7, 1);
+			arrowPoly.addPoint(15, 15);
+			arrowPoly.addPoint(0, 15);
+			arrowPoly.addPoint(7,1);
+			arrowPoly.npoints=4;
+		}
+		else if (orientation == DOWN){
+			arrowPoly.npoints=0;
+			arrowPoly.addPoint(7, 15);
+			arrowPoly.addPoint(15, 1);
+			arrowPoly.addPoint(0, 1);
+			arrowPoly.addPoint(7, 15);
+			arrowPoly.npoints=4;
+		}
+		setBackground(ColorTheme.getInterfaceBackground());
+		setBounds(0,0,16,16);
+	}
+	
+	public void setEnabled(boolean b) {
+		disabled = !b;
+		repaint();
+	}
+	public void print (Graphics g) {
+	}
+	public void paint (Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (!getBackground().equals(getParent().getBackground()))
+			setBackground(getParent().getBackground());
+		/*
+		g.setColor(getBackground());
+		g.fillRect(0,0,16,16);
+		g.setColor(Color.black);
+		*/
+		if (orientation==LEFT) {
+			if (firsttime) {  //done to cache so doesn't flash on user touch
+				g.drawImage(leftArrowPressed,0,0,this);
+				g.drawImage(leftArrowDisabled,0,0,this);
+				g.drawImage(leftArrow,0,0,this);
+			}
+			firsttime=false;
+			if (pressed)
+				g.drawImage(leftArrowPressed,0,0,this);
+			else if (disabled)
+				g.drawImage(leftArrowDisabled,0,0,this);
+			else
+				g.drawImage(leftArrow,0,0,this);
+		}
+		else if (orientation==RIGHT){
+			if (firsttime) {  //done to cache so doesn't flash on user touch
+				g.drawImage(rightArrowPressed,0,0,this);
+				g.drawImage(rightArrowDisabled,0,0,this);
+				g.drawImage(rightArrow,0,0,this);
+			}
+			firsttime=false;
+			if (pressed)
+				g.drawImage(rightArrowPressed,0,0,this);
+			else if (disabled)
+				g.drawImage(rightArrowDisabled,0,0,this);
+			else
+				g.drawImage(rightArrow,0,0,this);
+		}
+		else if (orientation==UP){
+			if (firsttime) {  //done to cache so doesn't flash on user touch
+				g.drawImage(upArrowPressed,0,0,this);
+				g.drawImage(upArrowDisabled,0,0,this);
+				g.drawImage(upArrow,0,0,this);
+			}
+			firsttime=false;
+			if (pressed)
+				g.drawImage(upArrowPressed,0,0,this);
+			else if (disabled)
+				g.drawImage(upArrowDisabled,0,0,this);
+			else
+				g.drawImage(upArrow,0,0,this);
+		}
+		else if (orientation==DOWN){
+			if (firsttime) {  //done to cache so doesn't flash on user touch
+				g.drawImage(downArrowPressed,0,0,this);
+				g.drawImage(downArrowDisabled,0,0,this);
+				g.drawImage(downArrow,0,0,this);
+			}
+			firsttime=false;
+			if (pressed)
+				g.drawImage(downArrowPressed,0,0,this);
+			else if (disabled)
+				g.drawImage(downArrowDisabled,0,0,this);
+			else
+				g.drawImage(downArrow,0,0,this);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		
+		Graphics g=getGraphics();
+		if (g == null)
+			return;
+ 		if (arrowPoly.contains(x,y)) {
+	 		if (orientation==LEFT || orientation == DOWN) {
+	 			pressed = true;
+	 			if (miniScroll.currentValue <= miniScroll.minValue) {
+	 				disabled = true;
+					if (orientation==LEFT)
+						g.drawImage(leftArrowDisabled,0,0,this);
+					else
+						g.drawImage(downArrowDisabled,0,0,this);
+				}
+	 			else {
+		 			disabled=false;
+					if (orientation==LEFT)
+						g.drawImage(leftArrowPressed,0,0,this);
+					else
+						g.drawImage(downArrowPressed,0,0,this);
+				}
+	 		}
+			else if (orientation==RIGHT || orientation == UP){
+				pressed = true;
+	 			if (miniScroll.currentValue >= miniScroll.maxValue) {
+	 				disabled=true;
+	 				if (orientation==RIGHT)
+						g.drawImage(rightArrowDisabled,0,0,this);
+					else
+						g.drawImage(upArrowDisabled,0,0,this);
+				}
+	 			else {
+		 			disabled = false;
+		 			if (orientation==RIGHT)
+						g.drawImage(rightArrowPressed,0,0,this);
+					else
+						g.drawImage(upArrowPressed,0,0,this);
+				}
+	 		}
+ 			//repaint();
+ 		}
+  		g.dispose();
+	}
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+ 		pressed = false;
+ 		pressed = false;
+ 		if (arrowPoly.contains(x,y)) {
+	 		if (orientation==LEFT || orientation == DOWN) {
+	 			if (miniScroll.currentValue <= miniScroll.minValue) {
+				}
+	 			else {
+					miniScroll.decrement();
+				}
+	 		}
+			else if (orientation==RIGHT || orientation == UP){
+	 			if (miniScroll.currentValue >= miniScroll.maxValue) {
+
+				}
+	 			else {
+		 			miniScroll.increment();
+				}
+	 		}
+ 			//repaint();
+ 		}
+ 		repaint();
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.windowOfItem(this)!=null) {
+			String name = "item";
+			if (!StringUtil.blank(itemName))
+				name = itemName;
+			String s="";
+	 		if (orientation==LEFT || orientation == DOWN) {
+	 			s+="This button will take you to the previous "+name+". ";
+	 			if (miniScroll.currentValue <= miniScroll.minValue) 
+	 				s += "It is disabled as it is already at the first "+name+".";
+	 		}
+			else if (orientation==RIGHT || orientation == UP){
+	 			s+="This button will take you to the next "+name+". ";
+	 			if (miniScroll.currentValue >= miniScroll.maxValue) 
+	 				s += "It is disabled as it is already at the last "+name+".";
+	 		}
+			MesquiteWindow.windowOfItem(this).setExplanation(s);
+		}
+		super.mouseEntered(modifiers,x,y, tool);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.windowOfItem(this)!=null) 
+			MesquiteWindow.windowOfItem(this).setExplanation("");
+		super.mouseExited(modifiers,x,y, tool);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MiniSlider.java b/Source/mesquite/lib/MiniSlider.java
new file mode 100644
index 0000000..5860c60
--- /dev/null
+++ b/Source/mesquite/lib/MiniSlider.java
@@ -0,0 +1,364 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/** A miniature slider used to set the value of a MesquiteNumber.  It provides
+an incrementing and decrementing arrow, and a text field to show current value. */
+public class MiniSlider extends MousePanel implements Explainable, ImageOwner {
+	double currentValue, minValue, maxValue;
+	double minSweetValue, maxSweetValue;
+	ValueToPixel valueToPixel=null;
+	//SliderButton slideButton;
+	int widthSet = 0;
+	public int totalWidth = 0;  
+	public int totalHeight=0; 
+	boolean sliderIsMoving = false;
+	Color bg = Color.white;
+	boolean horizontal = true;
+	int insetEdge = 4;
+	MesquiteCommand command;
+	Color color = null;
+	MiniSliderWithText textToNotify = null;
+	static Image enterVertical, enterHorizontal;
+	private Image enter;
+	int touchOffset = 0;
+	MesquiteTimer timer=null;
+	//boolean enforceMin, enforceMax;
+	static {
+		enterVertical = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "sliderVert.gif");
+		enterHorizontal = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "sliderHoriz.gif");
+	}
+	public MiniSlider (MesquiteCommand command, boolean horizontal, double currentValue, double minValue, double maxValue, double minSweetValue, double maxSweetValue) {
+		setCursor(Cursor.getDefaultCursor());
+		this.currentValue = currentValue;
+		this.minValue = minValue;
+		this.maxValue = maxValue;
+		this.minSweetValue = minSweetValue;
+		this.maxSweetValue = maxSweetValue;
+		this.command=command;
+		this.horizontal = horizontal;
+		
+		setLayout(null);
+		//add(slideButton = new SliderButton(this, horizontal));
+		//adjustSlider();
+		//setBackground(Color.green);
+		if (horizontal) 
+			enter = enterVertical;
+		else 
+			enter = enterHorizontal;
+//		this.enforceMin = enforceMin;
+//		this.enforceMax = enforceMax;
+		valueToPixel = new LinearValueToPixel(minValue,maxValue, minSweetValue, maxSweetValue, sliderRangeInPixels());
+	}
+
+	/*.................................................................................................................*/
+	 public boolean getSliderIsMoving() {
+	 	return sliderIsMoving;
+  	 }
+	/*.................................................................................................................*/
+	 public void useExponentialScale(boolean exp) {         // not yet functioning
+  	 //	valueToPixel.dispose();   
+/*
+  	 	if (exp)
+  	 		valueToPixel = new LogValueToPixel(minValue,maxValue, minSweetValue, maxSweetValue, sliderRangeInPixels());
+  	 	else
+  	 		valueToPixel = new LinearValueToPixel(minValue,maxValue, minSweetValue, maxSweetValue, sliderRangeInPixels());
+  	 	repaint();
+*/
+  	 }
+	public void  setColor(Color c){
+		color = c;
+	}
+	public void setRangeInPixels(int w){
+		if (horizontal)
+			setSize(w, 16);
+		else
+			setSize(16, w);
+		if (valueToPixel!= null)
+			valueToPixel.setTotalPixels(sliderRangeInPixels());
+		//adjustSlider();
+	}
+	int sliderRangeInPixels(){
+		if (horizontal)
+			return getBounds().width -8; //-8 for width of image
+		else
+			return getBounds().height -8;
+	}
+	double percentPosition(){
+		if (MesquiteDouble.isCombinable(currentValue) && (maxValue-minValue)!=0) {
+			valueToPixel.setTotalPixels(sliderRangeInPixels());
+			return valueToPixel.getPixelPercent(currentValue);
+		}
+		else
+			return 0;
+	}
+	int sliderPositionInPixels(){
+		double pp = percentPosition();
+		return (int)( percentPosition()*sliderRangeInPixels());
+	}
+	public void setTextToNotify(MiniSliderWithText t){
+		textToNotify = t;
+	}
+	public void paint(Graphics g) { //^^^
+		if (g instanceof PrintGraphics)
+			return;
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		//g.setColor(getBackground());
+		//g.fillRect(0,0,getBounds().width,getBounds().height);
+		if (color!=null) {
+			g.setColor(color);
+    			g.fillRect(insetEdge, insetEdge, getBounds().width-insetEdge-insetEdge,getBounds().height-insetEdge-insetEdge);
+		}
+		if (valueToPixel.hasStartingNonSweet()) {
+			g.setColor(Color.lightGray);
+    			g.fillRect(insetEdge, insetEdge,valueToPixel.getStartSweetPixels(),getBounds().height-insetEdge-insetEdge);
+		}
+		if (valueToPixel.hasEndingNonSweet()) {
+			g.setColor(Color.lightGray);
+    			g.fillRect(insetEdge+valueToPixel.getEndSweetPixels()+1, insetEdge,valueToPixel.getPostSweetPixels(),getBounds().height-insetEdge-insetEdge);
+		}
+		g.setColor(Color.black);
+    		g.drawRect(insetEdge, insetEdge, getBounds().width-insetEdge-insetEdge,getBounds().height-insetEdge-insetEdge);
+		if (horizontal)
+			g.drawImage(enter,sliderPositionInPixels(), 0, this);
+		else
+			g.drawImage(enter,0, sliderPositionInPixels(), this);
+		/*if (sliderIsMoving){
+			if (horizontal)
+				g.drawString(MesquiteDouble.toString(currentValue), 4, getBounds().height-insetEdge-insetEdge);
+			else
+				g.drawString(MesquiteDouble.toString(currentValue), 24, 4);
+		}*/
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void printAll(Graphics g) { 
+	}
+	public void paintComponents(Graphics g) { 
+		if (g instanceof PrintGraphics)
+			return;
+		else
+			super.paintComponents(g);
+	}
+	public void printComponents(Graphics g) { 
+	}
+	public void print(Graphics g) { 
+	}
+	private boolean checkBackground(){
+		if (getParent() !=null && getBackground()!=null && !getBackground().equals(getParent().getBackground())) {
+			bg =getParent().getBackground();
+			setBackground(bg);
+			return true;
+		}
+		else return false;
+	}
+	public void setVisible(boolean b) {
+		if (b)
+			checkBackground();
+		super.setVisible(b);
+		repaint();
+	}
+	public void setMaximumValue (double i) { 
+		if (i!=maxValue) {
+			maxValue=i;
+			valueToPixel.setMaxValue(maxValue);
+			if (MesquiteDouble.isCombinable(currentValue) && (currentValue>maxValue))
+				setCurrentValue(maxValue);
+			else
+				setCurrentValue(currentValue); //this ensures draw correctly
+			repaint();
+		}
+	}
+	public void setMinimumValue (double i) { 
+		if (i!=minValue) {
+			minValue=i;
+			valueToPixel.setMinValue(minValue);
+			if (MesquiteDouble.isCombinable(currentValue) && (currentValue<minValue))
+				setCurrentValue(minValue);
+			else
+				setCurrentValue(currentValue); //this ensures draw correctly
+			repaint();
+		}
+	}
+	public void setMaximumSweetValue (double i) { 
+		if (i!=maxSweetValue) {
+			maxSweetValue=i;
+			valueToPixel.setMaxSweetValue(i);
+			repaint();
+		}
+	}
+	public void setMinimumSweetValue (double i) { 
+		if (i!=minSweetValue) {
+			minSweetValue=i;
+			valueToPixel.setMinSweetValue(i);
+			repaint();
+		}
+	}
+	public void setCurrentValue (double i) {  
+		if (MesquiteDouble.isUnassigned(i)) {
+			currentValue = i;
+			return;
+		}
+		if (!MesquiteDouble.isCombinable(i))
+			return;
+		if (i<=maxValue && (i>=minValue) && i!=currentValue) {
+			currentValue=i;
+		}
+		repaint();
+		//adjustSlider();
+	}
+
+	public MesquiteNumber getMaximumValue () { 
+			return  new MesquiteNumber(maxValue);
+	}
+	public MesquiteNumber getMinimumValue () { 
+			return  new MesquiteNumber(minValue);
+	}
+	public MesquiteNumber getCurrentValue () {  
+			return  new MesquiteNumber(currentValue);
+	}
+	public void sliderAt(int x) { 
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Mini slider", command, this);
+			return;
+		}
+		double i;
+		valueToPixel.setTotalPixels(sliderRangeInPixels());
+		i = valueToPixel.getValue(x);
+				
+		if (command!=null) {
+			if (i>maxValue)
+				i=maxValue;
+			if (i<minValue)
+				i=minValue;
+			currentValue=i;
+			if (textToNotify!=null)
+				textToNotify.setCurrentNoSliderUpdate(i);
+			command.doItMainThread(MesquiteDouble.toString(currentValue), CommandChecker.getQueryModeString("Mini slider", command, this), false, false); //false, false added 17 Nov 01
+		}
+	}
+	public String getExplanation(){ //TODO: this should use string passed in constructor
+		return "This is a slider control";
+	}
+	public String getImagePath(){ //TODO: this should use path to standard image
+		return MesquiteModule.getRootImageDirectoryPath() + "sliderVert.gif";
+	}
+	
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+  		sliderIsMoving = true;
+		if (!horizontal) {
+			touchOffset = y - sliderPositionInPixels(); //get position of touch relative to  slider
+		}
+		else {
+			touchOffset = x - sliderPositionInPixels();
+		}
+		repaint();
+	}
+   	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+   		if (timer==null) {
+   			timer = new MesquiteTimer();
+   			timer.start();
+   		}
+   		if (timer==null || timer.timeSinceLast()>20)  // only check this if it has been 20 milliseconds
+   			if (!horizontal){
+   				int newLoc = (y-touchOffset); //this is only for vertical
+   				if (newLoc>=0 && newLoc< sliderRangeInPixels()) {
+   					sliderAt(newLoc);
+   					repaint();
+   				}
+   			}
+   			else {
+   				int newLoc =  (x-touchOffset); //this is only for horizontal
+   				if (newLoc>=0 && newLoc< sliderRangeInPixels()) {
+   					sliderAt(newLoc);
+   					repaint();
+   				}
+   			}
+	}
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		//miniSlider.acceptText();
+		sliderIsMoving = false;
+	}
+}
+/*
+class SliderButton extends MousePanel {
+	public MiniSlider miniSlider;
+	public static Image enterVertical, enterHorizontal;
+	private Image enter;
+	private boolean firsttime=true;
+	int touched = 0;
+	private boolean horizontal = true;
+	static {
+		enterVertical = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "sliderVert.gif");
+		enterHorizontal = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "sliderHoriz.gif");
+	}
+	public SliderButton (MiniSlider miniSlider, boolean horizontal) {
+		this.miniSlider = miniSlider;
+		this.horizontal = horizontal;
+		if (horizontal) {
+			enter = enterVertical;
+			setBounds(0,0,8,16);
+		}
+		else {
+			enter = enterHorizontal;
+			setBounds(0,0,16,8);
+		}
+	}
+	public SliderButton (MiniSlider miniSlider) {
+		this(miniSlider, true);
+	}
+	
+	public void paint (Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		g.drawImage(enter,0,0,this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (!horizontal)
+			touched = y;
+		else
+			touched = x;
+		repaint();
+	}
+   	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!horizontal){
+			int newLoc = getLocation().y + (y-touched); //this is only for vertical
+			if (newLoc>=0 && newLoc< miniSlider.sliderRangeInPixels()) {
+				miniSlider.sliderAt(newLoc);
+				setLocation(getLocation().x, newLoc);
+			}
+		}
+		else {
+			int newLoc = getLocation().x + (x-touched); //this is only for horizontal
+			if (newLoc>=0 && newLoc< miniSlider.sliderRangeInPixels()) {
+				miniSlider.sliderAt(newLoc);
+				setLocation(newLoc, getLocation().y);
+			}
+		}
+	}
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		//miniSlider.acceptText();
+	}
+}
+*/
+
diff --git a/Source/mesquite/lib/MiniSliderWithText.java b/Source/mesquite/lib/MiniSliderWithText.java
new file mode 100644
index 0000000..0f33672
--- /dev/null
+++ b/Source/mesquite/lib/MiniSliderWithText.java
@@ -0,0 +1,346 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/** A miniature slider used to set the value of a MesquiteNumber.  It provides
+an incrementing and decrementing arrow, and a text field to show current value. */
+public class MiniSliderWithText extends Panel implements MiniControl, Explainable, ImageOwner, ActionListener, TextListener {
+	double currentValue, minValue, maxValue;
+	boolean adjustingSizes = true;
+	boolean allowEstimation=false;
+	String currentText="";
+	TextField tf;
+	TextField dummy;
+	EnterButton enterButton;
+	MiniSlider slider;
+	private int textBoxWidth = 34;
+	private int textBoxHeight = 18;
+	int widthSet = 0;
+	public int totalWidth = 0;  
+	public int totalHeight=0; 
+	private int oldTextBoxWidth = 1;
+	private int oldTextBoxHeight = 1;
+	Color bg = Color.white;
+	int edge = 4;
+	int edgeRight = 8;
+//	boolean enforceMin, enforceMax;
+	double minSweetValue, maxSweetValue;
+
+	MesquiteCommand command;
+	int enterWidth = 8;
+	// be passed max and min values  
+	
+	public MiniSliderWithText (MesquiteCommand command, double currentValue, double minValue, double maxValue, double minSweetValue, double maxSweetValue) {
+		this.currentValue = currentValue;
+		this.minSweetValue = minSweetValue;
+		this.maxSweetValue = maxSweetValue;
+		this.command=command;
+		this.minValue = minValue;
+		this.maxValue = maxValue;
+		initValues();
+	}
+	/*.................................................................................................................*/
+  	 public void useExponentialScale(boolean exp) {
+  	 	slider.useExponentialScale(exp);
+  	 }
+	/*.................................................................................................................*/
+  	 public void setText(String t) {
+  	 	tf.setText(t);
+  	 	currentText = t;
+  	 }
+	public void setWidth(int w){
+		Point loc = getLocation();
+		widthSet = w;
+		calcTextBoxSize(getGraphics());
+		setTotalSize();
+		//slider.setLocation(10, textBoxHeight);
+		slider.setRangeInPixels(widthSet);
+		//valueToPixel.setTotalPixels(slider.sliderRangeInPixels());
+	//setLocation(loc);
+	}
+	/*.................................................................................................................*/
+  	 public void setAllowEstimation(boolean allow) {
+  	 	allowEstimation = allow;
+  	 }
+	/*.................................................................................................................*/
+  	 public Dimension getPreferredSize() {
+  	 	return new Dimension(totalWidth, totalHeight);
+  	 }
+	/*.................................................................................................................*/
+  	 public EnterButton getEnterButton() {
+  	 	return enterButton;
+  	 }
+	/*.................................................................................................................*/
+  	 public void setTotalSize() {
+		if (textBoxWidth  + EnterButton.MIN_DIMENSION+2 >widthSet)
+			totalWidth = textBoxWidth + EnterButton.MIN_DIMENSION+2;
+		else
+			totalWidth = widthSet  + EnterButton.MIN_DIMENSION+2;
+		totalHeight = textBoxHeight + 24;
+		setSize(totalWidth, totalHeight);
+  	 }
+	/*.................................................................................................................*/
+	private void initValues(){
+		adjustingSizes = true;
+		calcTextBoxSize(getGraphics());
+		setTotalSize();
+		setLayout(null);
+		add(slider = new MiniSlider(command, true, currentValue, minValue, maxValue, minSweetValue, maxSweetValue));
+		slider.setLocation(10, textBoxHeight);
+		slider.setTextToNotify(this);
+		slider.setRangeInPixels(widthSet);
+		slider.setColor(Color.white);
+		slider.setVisible(true);
+		add(enterButton = new EnterButton(this, true));
+		enterButton.setEnabled(false);
+		currentText = MesquiteDouble.toString(currentValue);
+		add(tf = new TextField("888888", 2));
+			tf.setText(currentText);
+		
+		tf.addActionListener(this);
+		tf.addTextListener(this);
+		tf.setVisible(false);
+		enterButton.setVisible(false);
+		tf.setSize(1, 1);
+		tf.setBackground(Color.white);
+	/*	add(dummy = new TextField(""));
+		dummy.setEditable(false);
+		dummy.setSize(0,0);
+		dummy.setBackground(bg);
+		dummy.setLocation(0,0);
+	*/
+
+		recalcPositions(true);
+		setBackground(bg);
+		adjustingSizes = false;
+		//paint();
+	}
+	private void calcTextBoxSize(Graphics g){
+		if (g!=null) {
+			Font f = g.getFont();
+			FontMetrics fm = g.getFontMetrics(f);
+			int sw1 = MesquiteInteger.maximum(fm.stringWidth("888888888888888888"), fm.stringWidth(tf.getText()));  // width of text in text field
+			int sw = MesquiteInteger.maximum(sw1, widthSet);   // check if user-specified width is bigger
+			int sh = fm.getMaxAscent()+fm.getMaxDescent();
+			
+			textBoxWidth = sw1 + MesquiteModule.textEdgeCompensationWidth; //34
+			textBoxHeight =  sh + MesquiteModule.textEdgeCompensationHeight; //18
+			if (tf!= null) {
+				if (Math.abs(tf.getBounds().width -  textBoxWidth)>2 || Math.abs(tf.getBounds().height - textBoxHeight)>0){
+					tf.setBounds(0, 0, textBoxWidth, textBoxHeight);
+				}
+				if (enterButton != null) {
+					if (Math.abs(enterButton.getLocation().x - ( tf.getBounds().x + tf.getBounds().width + 4))>2 || enterButton.getLocation().y != 2)
+						enterButton.setLocation(tf.getBounds().x + tf.getBounds().width + 4, 2);
+					enterButton.repaint();
+				}
+				if (slider != null && (slider.getLocation().x != 10 || Math.abs(slider.getLocation().y - ( tf.getBounds().y+tf.getBounds().height+4))>2))
+					slider.setLocation(10, tf.getBounds().y+tf.getBounds().height+4);
+			}
+		}
+	}
+	private boolean recalcPositions(boolean doRepaint){
+		Graphics g = getGraphics();
+		if (g != null){
+			adjustingSizes = true;
+			calcTextBoxSize(g);
+			setTotalSize();
+			if (doRepaint)
+				repaint();
+			if (getParent()!= null)
+				getParent().repaint();
+			adjustingSizes = false;
+			g.dispose();
+		}
+		return true;
+	}
+	public void paint(Graphics g) { 
+		//recalcPositions(g, false);
+	}
+	public void repaint() { 
+		recalcPositions( false);
+	}
+	public void printAll(Graphics g) { 
+	}
+	public void paintComponents(Graphics g) { 
+		if (g instanceof PrintGraphics)
+			return;
+		else
+			super.paintComponents(g);
+	}
+	public void printComponents(Graphics g) { 
+	}
+	public void print(Graphics g) { 
+	}
+	private boolean checkBackground(){
+		if (getParent() !=null && getBackground()!=null && !getBackground().equals(getParent().getBackground())) {
+			bg =getParent().getBackground();
+			setBackground(bg);
+			//setBackground(Color.green);
+			if (tf!=null)
+				tf.setBackground(Color.white);
+			if (enterButton!=null)
+				enterButton.setBackground(bg);
+			return true;
+		}
+		else return false;
+	}
+	public void setVisible(boolean b) {
+		if (b)
+			checkBackground();
+		super.setVisible(b);
+		tf.setVisible(b);
+		enterButton.setVisible(b);
+		repaint();
+	}
+	public void setColor(Color c) {
+		tf.setForeground(c);
+	}
+	public MiniSlider getSlider() {  
+		return slider;
+	}
+	public void setMaximumValue (double i) { 
+		if (i!=maxValue) {
+			maxValue=i;
+			slider.setMaximumValue(i);
+			if (MesquiteDouble.isCombinable(currentValue) && (currentValue>maxValue))
+				setCurrentValue(maxValue);
+			else
+				setCurrentValue(currentValue); //this ensures draw correctly
+		}
+	}
+	public void setMinimumValue (double i) { 
+		if (i!=minValue) {
+			minValue=i;
+			slider.setMinimumValue(i);
+			if (MesquiteDouble.isCombinable(currentValue) && (currentValue<minValue))
+				setCurrentValue(minValue);
+			else
+				setCurrentValue(currentValue); //this ensures draw correctly
+		}
+	}
+	public void setMaximumSweetValue (double i) { 
+		if (i!=maxSweetValue) {
+			maxSweetValue=i;
+			slider.setMaximumSweetValue(i);
+		}
+	}
+	public void setMinimumSweetValue (double i) { 
+		if (i!=minSweetValue) {
+			minSweetValue=i;
+			slider.setMinimumSweetValue(i);
+		}
+	}
+	public void setCurrentNoSliderUpdate (double i) {  
+		if (!MesquiteDouble.isCombinable(i))
+			return;
+		if ((i<=maxValue) && (i>=minValue) && i!=currentValue) {
+			currentValue=i;
+		}
+		tf.setText(MesquiteDouble.toString(currentValue));
+	}
+	public void setCurrentValue (double i) {  
+		if (!MesquiteDouble.isCombinable(i))
+			return;
+		if ((i<=maxValue) && (i>=minValue) && i!=currentValue) {
+			currentValue=i;
+		}
+		slider.setCurrentValue(i);
+		tf.setText(MesquiteDouble.toString(currentValue));
+		enterButton.setEnabled(false);
+	}
+	public MesquiteNumber getMaximumValue () { 
+			return  new MesquiteNumber(maxValue);
+	}
+	public MesquiteNumber getMinimumValue () { 
+			return  new MesquiteNumber(minValue);
+	}
+	public MesquiteNumber getMaximumSweetValue () { 
+			return  new MesquiteNumber(maxSweetValue);
+	}
+	public MesquiteNumber getMinimumSweetValue () { 
+			return  new MesquiteNumber(minSweetValue);
+	}
+	public MesquiteNumber getCurrentValue () {  
+			return  new MesquiteNumber(currentValue);
+	}
+	public boolean textValid(String s){
+		double d = MesquiteDouble.fromString(s);
+		if (MesquiteString.explicitlyUnassigned(s) && allowEstimation)
+			return true;
+		if (!MesquiteDouble.isCombinable(d))
+			return false;
+		if (d>maxValue) {
+			MesquiteTrunk.mesquiteTrunk.alert("That value (" + d + ") is above the maximum currently allowed (" + maxValue + ")");
+			return false;
+		}
+		else if (d<minValue) {
+			MesquiteTrunk.mesquiteTrunk.alert("That value (" + d + ") is below the minimum currently allowed (" + minValue + ")");
+			return false;
+		}
+		return true;
+	}
+	 public void textValueChanged(TextEvent e) {
+	 	String s = tf.getText();
+	 	double d = MesquiteDouble.fromString(s);
+	 	if (!slider.getSliderIsMoving() && (d!=currentValue)) {
+	 		enterButton.setEnabled(textValid(s));
+	 	}
+	 	else
+	 		enterButton.setEnabled(false);
+	}
+	public void acceptText(){
+		if (MesquiteWindow.getQueryMode(this)) {
+			MesquiteWindow.respondToQueryMode("Mini slider", command, this);
+			return;
+		}
+		String s = tf.getText();
+		if (MesquiteString.explicitlyUnassigned(s) && allowEstimation){
+			currentValue=MesquiteDouble.unassigned;
+			slider.setCurrentValue(currentValue);
+			command.doItMainThread(s, CommandChecker.getQueryModeString("Mini slider", command, this), this);
+			return;
+		}
+		if (!textValid(s))
+			return;
+		currentText=s;
+		double d = MesquiteDouble.fromString(s);
+		setCurrentValue(d);
+		//enterButton.repaint();
+		command.doItMainThread(MesquiteDouble.toString(d), CommandChecker.getQueryModeString("Mini slider", command, this), this);
+		enterButton.setEnabled(false);
+	}
+	public void actionPerformed(ActionEvent e){
+		//Event queue
+			acceptText();
+	}
+	public String getExplanation(){ //TODO: this should use string passed in constructor
+		return "This is a number control with text entry and slider";
+	}
+	public String getImagePath(){ //TODO: this should use path to standard image
+		return null;
+	}
+	
+}
+
+
+
diff --git a/Source/mesquite/lib/MiniStringEditor.java b/Source/mesquite/lib/MiniStringEditor.java
new file mode 100644
index 0000000..7f244e3
--- /dev/null
+++ b/Source/mesquite/lib/MiniStringEditor.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.*;
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/*=================*/
+public class MiniStringEditor extends Panel implements ActionListener, MiniControl{
+	MesquiteModule ownerModule;
+	EnterButton enterButton;
+	protected TextField text;
+	protected MesquiteCommand command;
+	protected String origText ="";
+	public MiniStringEditor (MesquiteModule ownerModule,  MesquiteCommand command) {
+		setCursor(Cursor.getDefaultCursor());
+		this.ownerModule=ownerModule;
+		this.command = command;
+		setSize(EnterButton.MIN_DIMENSION + 92,12 + MesquiteModule.textEdgeCompensationHeight);
+		text = new TextField("");
+		text.addActionListener(this);
+		setLayout(null);
+		add(text);
+		text.setLocation(EnterButton.MIN_DIMENSION+1, 0);
+		text.setSize(EnterButton.MIN_DIMENSION + 90, 12 + MesquiteModule.textEdgeCompensationHeight);
+		add(enterButton = new EnterButton(this));
+		enterButton.setVisible(false);
+		enterButton.setLocation(0, (12 + MesquiteModule.textEdgeCompensationHeight)/2 - 8);
+	}
+ 	public void acceptText(){
+			String resultString = text.getText();
+ 			command.doItMainThread(resultString, CommandChecker.getQueryModeString("Mini text editor", command, this), this);  
+	}
+	public void prepare(){
+		text.requestFocusInWindow();
+		text.selectAll();
+	}
+
+	public void setVisible(boolean vis){
+		if (!text.isVisible() && vis)
+			prepare();
+		text.setVisible(vis);
+		enterButton.setVisible(vis);
+		super.setVisible(vis);
+	}
+	public void setText(String s){
+		if (s == null) //added 14 Feb 02
+			s = "";
+		origText = s;
+		text.setText(origText);
+	}
+	public void actionPerformed(ActionEvent e){
+		//Event queue
+			acceptText();
+	}
+	
+
+}
+
+class EnterTextField extends TextField{
+	
+}
+
+
diff --git a/Source/mesquite/lib/ModuleInfoWindow.java b/Source/mesquite/lib/ModuleInfoWindow.java
new file mode 100644
index 0000000..c6fd0bd
--- /dev/null
+++ b/Source/mesquite/lib/ModuleInfoWindow.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.io.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** A Dialog giving information about an instantiated module or a class of modules*/
+public class ModuleInfoWindow extends ExtensibleDialog {
+	TextArea t;
+	public ModuleInfoWindow (MesquiteModule module) {
+		super(null, "Active Module: " + module.getName());
+		String versionString = module.getVersion();
+		if (versionString == null)
+			versionString = "?";
+		t = addTextArea("Information concerning active module \n\nModule: "  + module.getName() + "\n" 
+		+ "Version: " + versionString + "\n" 
+		+ "Author(s): " + module.getAuthors()+ "\n\n" 
+		+ "Class: " + module.getClass().getName()  + "\n"
+		+ "[id: " + module.getID() + "]\n\n"
+		+ "Duty Performed: " + module.getDutyName()+  " (" + module.getDutyClass().getName() + ")\n\n" 
+		+ "Explanation: " + module.getExplanation()+ "\n\n" 
+		+ "Current Parameters: " + module.getParameters(), 20);
+		addAuxiliaryDefaultPanels();
+		addPrimaryButtonRow("OK");
+		prepareAndDisplayDialog();
+	}
+	public ModuleInfoWindow (MesquiteWindow parent, Class dutyClass, String name) {
+		super(parent, "");
+		MesquiteModuleInfo mbi =MesquiteTrunk.mesquiteModulesInfoVector.findModule(dutyClass, name);
+		if (mbi!=null) { 
+			try {
+				MesquiteModule mb = (MesquiteModule)mbi.mbClass.newInstance();
+				if (mb!=null) {
+					setTitle("Information concerning module \n\nModule: " + mb.getName());
+					String versionString = mb.getVersion();
+					if (versionString == null)
+						versionString = "?";
+					t = addTextArea("Module: " + mb.getName() + "\n\n" 
+					+ "Version: " + versionString + "\n\n" 
+					+ "Author(s): " + mb.getAuthors()+ "\n\n" 
+					+ "Duty Performed: " + mb.getDutyName()+ "\n\n" 
+					+ "Explanation: " + mb.getExplanation(),20);
+					setVisible(true);
+				}
+			}
+			catch (Exception e){
+				MesquiteTrunk.mesquiteTrunk.alert("Sorry, there was a problem");
+				MesquiteFile.throwableToLog(this, e);
+				dispose(); }
+		}
+		addAuxiliaryDefaultPanels();
+		addPrimaryButtonRow("OK");
+		prepareAndDisplayDialog();
+	}
+}
+
diff --git a/Source/mesquite/lib/ModulesInfoVector.java b/Source/mesquite/lib/ModulesInfoVector.java
new file mode 100644
index 0000000..7a8a99f
--- /dev/null
+++ b/Source/mesquite/lib/ModulesInfoVector.java
@@ -0,0 +1,588 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.duties.*;
+
+import java.util.*;
+
+/* ======================================================================== */
+/** The vector of information (MesquiteModuleInfo objects) about available modules.*/
+public class ModulesInfoVector extends ListableVector {
+	Vector dutyClasses;
+	Vector dutyDefaultsSourceClass; //duty class of module that supplied dutyDefault;  
+	Vector dutyDefaults;
+	public ModulesInfoVector  () {
+		super(50);
+		notifyOfChanges = false;
+		dutyClasses = new Vector(100);
+		dutyDefaults = new Vector(100);
+		dutyDefaultsSourceClass = new Vector(100);
+	}
+
+	public void dispose(){
+		removeAllElements(false);
+		dutyClasses.removeAllElements(); 
+		dutyDefaults.removeAllElements(); 
+		dutyDefaultsSourceClass.removeAllElements(); 
+	}
+	public Vector getDutyList(){//hackathon
+		Vector list = new Vector();
+		for (int d = 0; d < dutyClasses.size(); d++) {
+			Class duty = (Class) dutyClasses.elementAt(d);
+
+			int num = size();
+			MesquiteModuleInfo mbi;
+			boolean first = true;
+			for (int i = 0; i < num; i++) {
+				mbi = (MesquiteModuleInfo) elementAt(i);
+				if (mbi.getDutyClass() == duty) {
+					if (first) {
+						list.addElement(mbi.getDutyName() + " (Class name " + mbi.getDutyClass().getName() + ")");
+						first = false;
+					}
+				}
+
+			}
+		}
+		return list;
+	}
+	public Vector whoUsesMe(MesquiteModuleInfo module){
+		
+		Vector v = new Vector();
+		if (MesquiteTrunk.class.isAssignableFrom(module.getClass())) //no other modules use the trunk!
+			return v;
+		Class target = module.getModuleClass();
+		/*
+		 * for (int i = 0; i< dutyDefaults.size(); i++){
+			MesquiteModuleInfo mm = (MesquiteModuleInfo)dutyDefaults.elementAt(i);
+			if (mm != null){
+				Vector needs = mm.getEmployeeNeedsVector();
+				if (needs != null){
+					for (int k = 0; k< needs.size(); k++){
+						EmployeeNeed need = (EmployeeNeed)needs.elementAt(k);
+						if (need.getDutyClass().isAssignableFrom(target))
+							v.addElement(mm, false);  //should also store which use this is!  (i.e. store the particular need)
+
+					}
+				}
+			}
+		}
+		 */
+		int numHighPriority = 0;
+		int numMediumPriority = 0;
+		MesquiteModuleInfo mm = null;
+		MesquiteInteger lastIndex =  new MesquiteInteger(-1);
+		MesquiteInteger category = new MesquiteInteger(0);
+		while ((mm = (MesquiteModuleInfo)MesquiteTrunk.mesquiteModulesInfoVector.getNextModule(lastIndex, category))!=null){
+			if (mm != null && mm != module){
+				Vector needs = mm.getEmployeeNeedsVector();
+				if (needs != null){
+					for (int k = 0; k< needs.size(); k++){
+						EmployeeNeed need = (EmployeeNeed)needs.elementAt(k);
+						if (need.getDutyClass().isAssignableFrom(target) && v.indexOf(need) < 0) {
+							if (need.getPriority() >= 2){
+								v.insertElementAt(need, numHighPriority);
+								numHighPriority++;
+							}
+							else if (need.getPriority() ==1 ){
+								v.insertElementAt(need, numHighPriority + numMediumPriority);
+								numMediumPriority++;
+							}
+							else
+								v.addElement(need);  //should also store which use this is!  (i.e. store the particular need)
+						}
+
+					}
+				}
+			}
+		}
+		if (v.size() == 0)
+			return null;
+		return v;
+	}
+
+	public boolean isDefault(MesquiteModule mb){
+		String[] defaults = mb.getDefaultModule();
+		return (whichDefault(defaults, mb.getModuleInfo())>=0);
+	}
+	//returns all modules in sequence, starting first with defaults, then with ones with primary choice, then remaining
+	public MesquiteModuleInfo getNextModule(MesquiteInteger lastIndex, MesquiteInteger category){
+		if (lastIndex == null || category == null)
+			return null;
+		if (category.getValue() == 0){ // defaults
+			int i = lastIndex.getValue()+1;
+			while (i < size()){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)elementAt(i);
+				if (mmi.isDefault()){
+					lastIndex.setValue(i);
+					return mmi;
+				}
+				i++;
+			}
+			category.setValue(1); //failed; go to next category
+			lastIndex.setValue(-1);
+		}
+		if (category.getValue() == 1){ // primary choice
+			int i = lastIndex.getValue()+1;
+			while (i < size()){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)elementAt(i);
+				if (!mmi.isDefault() && mmi.isPrimaryChoice){
+					lastIndex.setValue(i);
+					return mmi;
+				}
+				i++;
+			}
+			category.setValue(2); //failed; go to next category
+			lastIndex.setValue(-1);
+		}
+		if (category.getValue() == 2){ // remaining
+			int i = lastIndex.getValue()+1;
+			while (i < size()){
+				MesquiteModuleInfo mmi = (MesquiteModuleInfo)elementAt(i);
+				if (!mmi.isDefault() && !mmi.isPrimaryChoice){
+					lastIndex.setValue(i);
+					return mmi;
+				}
+				i++;
+			}
+			category.setValue(3); //failed; go to next category
+			lastIndex.setValue(-1);
+		}
+		return null;
+	}
+	private String[] filterDefaults(String[] candidates, Class dutyClass){ //making sure the listed defaults are all valid
+		if (candidates == null)
+			return null;
+		if (dutyClass == null)
+			return null;
+		int count = 0;
+		for (int i=0; i<candidates.length; i++){
+			MesquiteModuleInfo mbi = findModule(dutyClass, candidates[i]);
+			if (mbi != null)
+				count++;
+		}
+		if (count == candidates.length)
+			return candidates;
+		String[] result = new String[count];
+		count = 0;
+		for (int i=0; i<candidates.length; i++){
+			MesquiteModuleInfo mbi = findModule(dutyClass, candidates[i]);
+			if (mbi != null) {
+				result[count++] = candidates[i];
+			}
+		}
+		return result;
+	}
+	public void filterAllDutyDefaults(){//making sure the listed defaults are all valid
+		for (int i=0; i<dutyDefaults.size(); i++){
+			dutyDefaults.setElementAt(filterDefaults((String[])dutyDefaults.elementAt(i), (Class)dutyDefaultsSourceClass.elementAt(i)), i); 
+		}
+	}
+	private boolean inStandardPackages(MesquiteModuleInfo mmi){
+		//String packageName = StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(getClass().getName(), "."), ".");  //getting package string
+		for (int i=0; i<MesquiteTrunk.standardPackages.length; i++)
+			if (mmi.getModuleClass().getName().startsWith("mesquite." + MesquiteTrunk.standardPackages[i]))
+				return true;
+		for (int i=0; i<MesquiteTrunk.standardExtras.length; i++)
+			if (mmi.getModuleClass().getName().startsWith("mesquite." + MesquiteTrunk.standardExtras[i]))
+				return true;
+		return false;
+
+	}
+	public void accumulateAllVersions(){//making sure the listed defaults are all valid
+		for (int i=0; i<size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)elementAt(i);
+			if (mmi.doesDuty(PackageIntroInterface.class)){
+				if (!StringUtil.blank(mmi.getPackageVersion())){
+					mmi.version = mmi.getPackageVersion();
+				}
+			}
+			MesquiteModuleInfo pim = mmi.getPackageIntroModule();
+			if (pim!=null && !StringUtil.blank(pim.getPackageVersion())) {
+				mmi.version =  pim.getPackageVersion();
+				mmi.packageName = pim.packageName;
+			}
+			
+			//if part of standard
+			if (inStandardPackages(mmi)) {
+				mmi.version =  MesquiteTrunk.mesquiteTrunk.getVersion();
+				mmi.packageName = "Mesquite standard packages";
+			}
+		}
+	}
+	public void recordDuty(MesquiteModule mb){
+		if (mb==null) return;
+		/*Class dutyClass = mb.getDutyClass();
+		if (dutyClasses.indexOf(dutyClass)<0){
+			dutyClasses.addElement(dutyClass);
+			dutyDefaults.addElement(mb.getDefaultModule());
+		}*/
+		boolean isDefault = false;
+		Class c = mb.getDutyClass();
+		String[] defaults = mb.getDefaultModule();
+		while (c!=MesquiteModule.class){
+			int loc = dutyClasses.indexOf(c);
+			if (loc<0){ //not found; simply added
+				dutyClasses.addElement(c);
+				dutyDefaults.addElement(defaults); 
+				dutyDefaultsSourceClass.addElement(mb.getDutyClass()); 
+			}
+			else {
+				Class prevSource = (Class)dutyDefaultsSourceClass.elementAt(loc);
+				if (mb.getDutyClass().isAssignableFrom(prevSource) && mb.getDutyClass() != prevSource ) { 
+					// this module is of duty class that is superclass to duty class of module that had supplied these entries; use this instead
+					dutyDefaults.setElementAt(defaults, loc); 
+					dutyDefaultsSourceClass.setElementAt(mb.getDutyClass(), loc); 
+				}
+			}
+			c = c.getSuperclass();
+		}
+	}
+	public String getDutyName(Class dutyClass){
+		int num = size();
+		for (int i=0; i<num; i++){
+			MesquiteModuleInfo mbi = (MesquiteModuleInfo)elementAt(i);
+			if (mbi.getDutyClass() == dutyClass)
+				return mbi.getDutyName();
+		}
+		for (int i=0; i<num; i++){
+			MesquiteModuleInfo mbi = (MesquiteModuleInfo)elementAt(i);
+			if (dutyClass.isAssignableFrom(mbi.getDutyClass()))
+				return mbi.getDutyName();
+		}
+		return null;
+	}
+	public String[] getDutyDefaults(Class dutyClass){
+		Class c = dutyClass;
+		while (c!=MesquiteModule.class && c!=null){
+			for (int i=0; i<dutyClasses.size(); i++){
+				if (dutyClasses.elementAt(i) == c)
+					return (String[])dutyDefaults.elementAt(i);
+			}
+			c = c.getSuperclass();
+		}
+		return null;
+	}
+
+	/** Dumps list of available modules to System.out.*/
+	public void dumpModuleList () {
+		int num = size();
+		System.out.println("=====Modules List=====");
+		MesquiteModuleInfo mbi;
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)elementAt(i);
+			System.out.println(mbi.getName() + "  duty class " + mbi.getDutyClass());
+		}
+		System.out.println("=================");
+	}
+	/** Return a String array listing all modules that subclass the passed duty class.  *
+	public Listable[] getModuleNamesOfDuty(Class dutyClass, Object condition, MesquiteModule prospectiveEmployer) {
+		int num = size();
+		MesquiteModuleInfo mbi=null;
+		int count=0;
+		while ((mbi = findNextModule(dutyClass, mbi))!=null) {
+		//todo: could check for compatibility here as in menus
+			if (mbi.doesDuty(dutyClass) && mbi.getUserChooseable()){
+				count++;
+			}
+		}
+		if (count==0)
+			return null;
+		else {
+			Listable[] names = new Listable[count];
+			int imod=0;
+			mbi=null;
+			while ((mbi = findNextModule(dutyClass, mbi))!=null) {
+			//todo: could check for compatibility here as in menus
+				if (mbi.doesDuty(dutyClass) && mbi.getUserChooseable()){
+					names[imod]=mbi;
+					imod++;
+				}
+			}
+			return names;
+		}
+	}
+	/** Return a String array listing all modules that subclass the passed duty class.  */
+	public Listable[] getModulesOfDuty(Class dutyClass, Object condition, MesquiteModule prospectiveEmployer) {
+		return getModulesOfDuty(dutyClass, condition, prospectiveEmployer, null);
+	}
+	
+	/** Return a String array listing all modules that subclass the passed duty class.  */
+	public Listable[] getModulesOfDuty(Class dutyClass, Object condition, MesquiteModule prospectiveEmployer, StringBuffer compatibilityReport) {
+		int num = size();
+		MesquiteModuleInfo mbi=null;
+		MesquiteProject proj = null;
+		if (prospectiveEmployer !=null)
+			proj = prospectiveEmployer.getProject();
+		int count=0;
+		while ((mbi = findNextModule(dutyClass, mbi))!=null) {
+			//todo: could check for compatibility here as in menus
+			if (mbi.doesDuty(dutyClass) && mbi.getUserChooseable() && (/*condition==null || */mbi.isCompatible(condition, proj, prospectiveEmployer))){
+				count++;
+			}
+		}
+		if (count==0)
+			return null;
+		else {
+			Listable[] infos = new Listable[count];
+			int imod=0;
+			mbi=null;
+			MesquiteString report = new MesquiteString();
+			while ((mbi = findNextModule(dutyClass, mbi))!=null) {
+				//todo: could check for compatibility here as in menus
+				report.setValue("");
+				if (mbi.doesDuty(dutyClass) && mbi.getUserChooseable()&&  (/*condition==null || */mbi.isCompatible(condition, proj, prospectiveEmployer, report))){
+					infos[imod]=mbi;
+					imod++;
+				}
+				if (!report.isBlank() && compatibilityReport != null)
+					compatibilityReport.append("  " + mbi.getName() + " is not an available choice because " + report);
+			}
+			return infos;
+		}
+	}
+	/*........................................................................*/
+	/** Returns module information for first module found that is instance of dutyClass and has given name.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findModule (Class dutyClass, String name) {
+		if (StringUtil.blank(name))
+			return null;
+		int num = size();
+		MesquiteModuleInfo mbi;
+
+		boolean className = (name.charAt(0) == '#');
+		String useName;
+		if (className) {
+			useName = name.substring(1, name.length());
+		}
+		else
+			useName = name;
+
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)elementAt(i);
+			if ((dutyClass == null || mbi.doesDuty(dutyClass)) && mbi.nameMatches(useName)) {
+				return mbi;
+			}
+		}
+		return null;
+	}
+	/*........................................................................*/
+	/** Returns module information for first module found that is instance of dutyClass within the given package (e.g. "mesquite.parsimony").
+	Returns null if none found.*/
+	public MesquiteModuleInfo findModule (String packageName, Class dutyClass) {
+		if (StringUtil.blank(packageName))
+			return null;
+		int num = size();
+		MesquiteModuleInfo mbi;
+
+
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)elementAt(i);
+			String packageMBI = StringUtil.getAllButLastItem(StringUtil.getAllButLastItem(mbi.getModuleClass().getName(), "."), ".");
+			boolean correctPackage = packageName.equals(packageMBI);
+			if (mbi.doesDuty(dutyClass) && correctPackage) {
+				return mbi;
+			}
+		}
+		return null;
+	}
+	/*........................................................................*/
+	/** returns mbi's index among the default modules named in the string array; if not present, returns -1 */ 
+	private int whichDefault(String[] defaults, MesquiteModuleInfo mbi){ //finds out if mbi is in defaults list
+		if (defaults==null || defaults.length==0)
+			return -1;
+		for (int i=0; i<defaults.length; i++) {
+			if (defaults[i]==null)
+				;
+			else if (mbi.getName().equalsIgnoreCase(defaults[i]))
+				return i;
+			else if (defaults[i].equalsIgnoreCase("#"+ mbi.getShortClassName()))
+				return i;
+			else if (defaults[i].equalsIgnoreCase(mbi.getShortClassName()))
+				return i;
+		}
+		return -1;
+	}
+	/*........................................................................*/
+	/** Returns module information for first module found that is instance of dutyClass.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findModule (Class dutyClass) {
+		return findModule(dutyClass, null, null, null);
+	}
+	/*........................................................................*/
+	/** Returns module information for first module found that is instance of dutyClass and satisfies given condition.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findModule(Class dutyClass, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		int num = size();
+		// first, see if there is an available compatible default module
+		MesquiteModuleInfo mbi = findNextDefaultModule(dutyClass, -1, condition, project, prospectiveEmployer);
+		if (mbi!=null)
+			return mbi;
+
+		// Next, look among all of the modules to choose the first compatible one
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)elementAt(i);
+			if (mbi.doesDuty(dutyClass)   && mbi.isCompatible(condition, project, prospectiveEmployer)){ //&& mbi.getUserChooseable()
+				return mbi;
+			}
+		}
+		return null;
+	} 
+	/*........................................................................*/
+	/** Returns module information for first module found that is instance of dutyClass and satisfies given condition.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findModuleFilteredByNot(Class dutyClass, Class[] notDutyClasses, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		int num = size();
+		// first, see if there is an available compatible default module
+		MesquiteModuleInfo mbi = findNextDefaultModuleFilteredByNot(dutyClass, notDutyClasses, -1, condition, project, prospectiveEmployer);
+		if (mbi!=null)
+			return mbi;
+
+		// Next, look among all of the modules to choose the first compatible one
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)elementAt(i);
+			if (mbi.doesDuty(dutyClass)   && mbi.isCompatible(condition, project, prospectiveEmployer)){ //&& mbi.getUserChooseable()
+				return mbi;
+			}
+		}
+		return null;
+	} 
+	/*........................................................................*/
+	/** Returns module information for next default module found, after the previousTH default, that is instance of dutyClass and satisfies given condition.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findNextDefaultModuleFilteredByNot (Class dutyClass, Class[] notDutyClasses, int previous, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		int num = size();
+		MesquiteModuleInfo mbi;
+		String[] defaultModules = null;
+		boolean dutyClassFound = false;
+		// first, finding defaults
+		defaultModules =getDutyDefaults(dutyClass);
+		if (defaultModules==null || defaultModules.length == 0 || previous >= defaultModules.length-1)
+			return null;
+		if (previous<0)
+			previous = -1;
+		for (int i=previous+1; i<defaultModules.length; i++){
+
+			mbi = findModule(dutyClass, defaultModules[i]);
+			if (mbi !=null && mbi.doesDuty(dutyClass)  && !mbi.doesADuty(notDutyClasses) && mbi.isCompatible(condition, project, prospectiveEmployer)){ //&& mbi.getUserChooseable()
+				return mbi;
+			}
+		}
+		return null;
+	}
+	/*........................................................................*/
+	/** Returns module information for next default module found, after the previousTH default, that is instance of dutyClass and satisfies given condition.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findNextDefaultModule (Class dutyClass, int previous, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		int num = size();
+		MesquiteModuleInfo mbi;
+		String[] defaultModules = null;
+		boolean dutyClassFound = false;
+		// first, finding defaults
+		defaultModules =getDutyDefaults(dutyClass);
+		if (defaultModules==null || defaultModules.length == 0 || previous >= defaultModules.length-1)
+			return null;
+		if (previous<0)
+			previous = -1;
+		for (int i=previous+1; i<defaultModules.length; i++){
+
+			mbi = findModule(dutyClass, defaultModules[i]);
+			if (mbi !=null && mbi.doesDuty(dutyClass)  && mbi.isCompatible(condition, project, prospectiveEmployer)){ //&& mbi.getUserChooseable()
+				return mbi;
+			}
+		}
+		return null;
+	}
+	/*........................................................................*/
+	/** Returns module information for next module found, after previousModule, that is instance of dutyClass. However, also makes sure that the module found is NOT one of the notDutyClasses. 
+	Returns null if none found.  */
+	public MesquiteModuleInfo findNextModuleFilteredByNot (Class dutyClass, Class[] notDutyClasses, MesquiteModuleInfo previousModule) {
+		return findNextModule(dutyClass, notDutyClasses, previousModule, null, null, null);
+	}
+	/*........................................................................*/
+	/** Returns module information for next module found, after previousModule, that is instance of dutyClass.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findNextModule (Class dutyClass, MesquiteModuleInfo previousModule) {
+		return findNextModule(dutyClass, previousModule, null, null, null);
+	}
+	/*........................................................................*/
+	/** Returns module information for next module found, after previousModule, that is instance of dutyClass and satisfies given condition.
+	Returns null if none found.*/
+	public MesquiteModuleInfo findNextModule (Class dutyClass, MesquiteModuleInfo previousModule, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		return findNextModule(dutyClass, null, previousModule, condition, project, prospectiveEmployer);
+	}
+	/*........................................................................*/
+	/** Returns module information for next module found, after previousModule, that is instance of dutyClass and satisfies given condition. However, also makes sure that the module found is NOT one of the notDutyClasses 
+	Returns null if none found.  */
+	public MesquiteModuleInfo findNextModule (Class dutyClass, Class[] notDutyClasses, MesquiteModuleInfo previousModule, Object condition, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		if (previousModule==null) {// no previous; find first module
+			return findModuleFilteredByNot(dutyClass, notDutyClasses, condition, project, prospectiveEmployer);
+		}
+
+		boolean chooseNext = false;
+		boolean defaultsExist = false;
+		int num = size();
+		MesquiteModuleInfo mbi;
+		//first, check to see if there are any more defaults that could be chosen
+		String[] defaultModules =getDutyDefaults(dutyClass); 
+		if (defaultModules!=null &&  defaultModules.length>=1) { //check if there is a subsequent default
+			defaultsExist = true;
+			if (previousModule == null){
+				MesquiteModuleInfo fmbi =findNextDefaultModuleFilteredByNot(dutyClass, notDutyClasses, -1, condition, project, prospectiveEmployer);
+				if (fmbi!=null)
+					return fmbi;
+			}
+			else {
+				int where = whichDefault(defaultModules, previousModule);
+
+
+				if (where >= 0 ) { // is a default, thus go to next
+					if (where == defaultModules.length-1){ //previous is exactly last default; thus go to non-defaults
+						chooseNext = true;
+					}
+					else if (where<defaultModules.length-1){ 
+						MesquiteModuleInfo fmbi =findNextDefaultModuleFilteredByNot(dutyClass, notDutyClasses, where, condition, project, prospectiveEmployer);
+						if (fmbi!=null)
+							return fmbi;
+					}
+				}
+			}
+		}
+		else
+			defaultsExist = false;
+
+		for (int i=0; i<num; i++){ //next, go through non-defaults
+			mbi = (MesquiteModuleInfo)elementAt(i); //If there are defaults, don't choose if is default (otherwise defaults will be chosen more than once
+			if (chooseNext) {
+				if (mbi.doesDuty(dutyClass) && !mbi.doesADuty(notDutyClasses)){
+					if ((!defaultsExist || whichDefault(defaultModules, mbi)<0)  && mbi.isCompatible(condition, project, prospectiveEmployer)) { //&& mbi.getUserChooseable()
+						return mbi;
+					}
+				}
+			}
+			else {
+				if (mbi.mbClass == previousModule.getModuleClass()) {
+					chooseNext = true;
+				}
+			}
+		}
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/MousePanel.java b/Source/mesquite/lib/MousePanel.java
new file mode 100644
index 0000000..e70e78a
--- /dev/null
+++ b/Source/mesquite/lib/MousePanel.java
@@ -0,0 +1,733 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+ */
+package mesquite.lib;
+
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import java.util.List;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.table.AutoScrollThread;
+
+
+/* ======================================================================== */
+/** This class adds drop down menu capabilities to panels.  A default component of the drop down
+menu is the Font selection */
+
+public class MousePanel extends Panel implements Commandable, FileDirtier, MouseMotionListener, MouseListener, DropTargetListener {
+	MesquiteCommand downCommand, upCommand, dragCommand, movedCommand, clickedCommand, enteredCommand, exitedCommand;
+	MesquiteCommand filesDroppedCommand, fileStringDroppedCommand;
+	MesquiteCommand showWindowCommand;
+	MesquiteDropManager dropManager;
+	long moveFrequency, moveCount;
+	boolean suppressEvents = false; //WWW
+	private int currentX = -1;
+	private int currentY = -1;
+	int ps = 0;  //reserved for use in preferred with as window sidepanel
+	private Cursor disabledCursor = null;
+	protected DropTarget dropTarget;
+	Vector dndObjectVector = new Vector();
+	AutoScrollThread autoScrollThread=null;
+	public static final int AUTOSCROLLOFF= 0;
+	public static final int AUTOSCROLLBOTH = 1;
+	public static final int AUTOSCROLLHORIZONTAL = 2;
+	public static final int AUTOSCROLLVERTICAL = 3;
+
+	int autoscrollDirection = AUTOSCROLLBOTH;
+
+	static long exited, clicked, entered,pressed, released, dragged, moved;
+	static{
+		exited = clicked= entered=pressed=released=dragged= moved=0;
+	}
+	public MousePanel() {
+		super();
+
+		try {
+			setFocusTraversalKeysEnabled(false);
+		}
+		catch (Error e){
+		}
+		dropManager = new MesquiteDropManager();
+		moveCount =0;
+		moveFrequency = 0;
+		setForeground(Color.black);
+		addMouseMotionListener(this);
+		addMouseListener(this);
+		downCommand= MesquiteModule.makeCommand("mouseDown", this);
+		upCommand= MesquiteModule.makeCommand("mouseUp", this);
+		dragCommand= MesquiteModule.makeCommand("mouseDrag", this);
+		movedCommand= MesquiteModule.makeCommand("mouseMoved", this);
+		movedCommand.setLetMeFinish(false);
+		clickedCommand= MesquiteModule.makeCommand("mouseClicked", this);
+		enteredCommand= MesquiteModule.makeCommand("mouseEntered", this);
+		enteredCommand.setLetMeFinish(false);
+		exitedCommand= MesquiteModule.makeCommand("mouseExited", this);
+		filesDroppedCommand= MesquiteModule.makeCommand("filesDropped", this);
+		fileStringDroppedCommand= MesquiteModule.makeCommand("fileStringDropped", this);
+		exitedCommand.setLetMeFinish(false);
+		downCommand.setSuppressLogging(true);
+		upCommand.setSuppressLogging(true);
+		dragCommand.setSuppressLogging(true);
+		movedCommand.setSuppressLogging(true);
+		clickedCommand.setSuppressLogging(true);
+		enteredCommand.setSuppressLogging(true);
+		exitedCommand.setSuppressLogging(true);
+		downCommand.hideInList = true;
+		upCommand.hideInList = true;
+		movedCommand.hideInList = true;
+		clickedCommand.hideInList = true;
+		enteredCommand.hideInList = true;
+		exitedCommand.hideInList = true;
+		setDontDuplicateCommands(false);
+		disabledCursor = setupDisabledCursor("disabled.gif", "disabled", 4,2);
+		if (disabledCursor ==null)
+			disabledCursor = Cursor.getDefaultCursor();
+	}
+	public void dispose(){
+		if (downCommand!=null)
+			downCommand.dispose();
+		if (upCommand!=null)
+			upCommand.dispose();
+		if (movedCommand!=null)
+			movedCommand.dispose();
+		if (clickedCommand!=null)
+			clickedCommand.dispose();
+		if (enteredCommand!=null)
+			enteredCommand.dispose();
+		if (exitedCommand!=null)
+			exitedCommand.dispose();
+		downCommand = null;
+		upCommand = null;
+		movedCommand = null;
+		clickedCommand = null;
+		enteredCommand = null;
+		exitedCommand = null;
+		removeMouseListener(this);
+		if (autoScrollThread!=null)
+			removeMouseListener(autoScrollThread);
+	}
+
+	public void setMoveFrequency(long mf){
+		moveFrequency = mf;
+	}
+	public MesquiteWindow getMesquiteWindow() {
+		Container c = getParent();
+		while (c!=null && !(c instanceof OuterContentArea))
+			c = c.getParent();
+		if (c==null)
+			return null;
+		return ((OuterContentArea)c).ownerWindow;
+	}
+	boolean fontSet = false;
+	public void setFont(Font f){
+		super.setFont(f);
+	}
+	public void setPanelFont(Font f){
+		fontSet = true;
+		super.setFont(f);
+	}
+	public boolean fontExplicitlySet(){
+		return fontSet;
+	}
+	public void update(Graphics paramGraphics){
+		if (paramGraphics instanceof Graphics2D){
+			Graphics2D g = (Graphics2D) paramGraphics;
+			g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,  // to recover antialiasing in OS X java 1.7 and in Windows.  1.7 broke text rotation when not antialiased on OSX.
+					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+		}
+		super.update(paramGraphics);
+	}
+	public Graphics getGraphics(){
+		Graphics gg = super.getGraphics();
+		if (gg instanceof Graphics2D){
+
+			Graphics2D g = (Graphics2D)gg;
+			if (g ==null)
+				return null;
+			g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+		}
+		return gg;
+	}
+	/*.................................................................................................................*/
+	public boolean canAutoscrollHorizontally() {
+		return autoscrollDirection == AUTOSCROLLBOTH || autoscrollDirection == AUTOSCROLLHORIZONTAL;
+	}
+	/*.................................................................................................................*/
+	public boolean canAutoscrollVertically() {
+		return autoscrollDirection == AUTOSCROLLBOTH || autoscrollDirection == AUTOSCROLLVERTICAL;
+	}
+	/*.................................................................................................................*/
+	public boolean askListenersToProcess(Object obj, boolean onlyOneProcessor) {
+		if (dropManager!=null)
+			return dropManager.askListenersToProcess(obj, onlyOneProcessor);
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void addDropListener(MesquiteDropListener dropListener) {
+		if (dropManager!=null)
+			dropManager.addListener(dropListener);
+	}
+
+	/*.................................................................................................................*/
+	public void removeDropListener(MesquiteDropListener dropListener) {
+		if (dropManager!=null)
+			dropManager.removeListener(dropListener);
+	}
+
+
+	/*.................................................................................................................*/
+
+	public void addMouseListener(MouseListener l){
+		if (l instanceof AutoScrollThread) {
+			autoScrollThread = (AutoScrollThread)l;
+		}
+		super.addMouseListener(l);
+	}
+
+
+	public void deletePendingMoveDrag(){
+		dragCommand.deleteOnQueue();
+		movedCommand.deleteOnQueue();
+	}
+	public void setDontDuplicateCommands(boolean dd){
+		downCommand.setDontDuplicate(dd);
+		dragCommand.setDontDuplicate(dd);
+		upCommand.setDontDuplicate(dd);
+		movedCommand.setDontDuplicate(dd);
+		clickedCommand.setDontDuplicate(dd);
+		enteredCommand.setDontDuplicate(dd);
+		exitedCommand.setDontDuplicate(dd);
+	}
+	public MesquiteWindow getWindow(){
+		return MesquiteWindow.windowOfItem(this);
+	}
+
+	MesquiteTool getT(){
+		try{
+			Container c = this;
+			while ((c= c.getParent())!=null){
+				if (c instanceof OuterContentArea) {
+					MesquiteTool tool = ((OuterContentArea)c).ownerWindow.getCurrentTool();
+					return tool;
+				}
+			}
+		}
+		catch (Exception e){
+		}
+		return null;
+	}
+	Image disabledCursorImage = null;
+	/*.................................................................................................................*/
+	private Cursor setupDisabledCursor(String imageFileName, String name, int x, int y){  
+		try { //just in case Java2 not available
+			Image im =  disabledCursorImage;  
+			if (im == null){
+				String s=MesquiteModule.getRootImageDirectoryPath();
+				Dimension best = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
+				if ((best.width>16 || best.height>16) && MesquiteFile.fileExists(MesquiteModule.getSizedRootImageFilePath(best.width, imageFileName))){
+					im = MesquiteImage.getImage((MesquiteModule.getSizedRootImageFilePath(best.width, imageFileName)));
+					if (im == null && s!=null)
+						im = MesquiteImage.getImage(s + imageFileName);
+				}
+				else if (s!=null)
+					im = MesquiteImage.getImage(s + imageFileName);
+				//setCursorImage(im);
+			}
+			Point p = new Point(x, y);
+			if (im== null)
+				return null;
+			disabledCursorImage = im;
+			Cursor c = Toolkit.getDefaultToolkit().createCustomCursor(im, p, name);
+			return c;
+		}
+		catch (Throwable t){
+			return null;
+		}
+	}
+	/*...............................................................................................................*/
+	public Cursor getDisabledCursor() {
+		return disabledCursor;
+	}
+
+	public void setCursor(Cursor c){
+		super.setCursor(c);
+	}
+	public int getMouseX(){
+		return currentX;
+	}
+	public int getMouseY(){
+		return currentY;
+	}
+	public void setVisible(boolean vis){
+		super.setVisible(vis);
+		invalidate(); //to workaround bug in Jaguar
+		validate(); //to workaround bug in Jaguar
+	}
+
+	ObjectContainer  findObjectContainer(int objectID) {
+		if (dndObjectVector==null)
+			return null;
+		for (int i = 0; i<dndObjectVector.size(); i++) {
+			ObjectContainer oc = (ObjectContainer)dndObjectVector.get(i);
+			if (objectID==oc.getID())
+				return oc;
+		}
+		return null;
+	}
+
+	void  deleteObjectContainer(int objectID) {
+		if (dndObjectVector==null)
+			return;
+		for (int i = 0; i<dndObjectVector.size(); i++) {
+			ObjectContainer oc = (ObjectContainer)dndObjectVector.get(i);
+			if (objectID==oc.getID())
+				dndObjectVector.remove(i);
+		}
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (MesquiteWindow.checkDoomed(this))
+			return null;
+		if (checker.compare(this.getClass(), "Mouse down", "[modifiers as integer][click count][when][x][y]", commandName, "mouseDown")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int clickCount = MesquiteInteger.fromString(arguments, pos);
+			long when = MesquiteLong.fromString(ParseUtil.getToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 101;
+			requestFocus();
+			try{
+				mouseDown(modifiers, clickCount, when, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse up", "[modifiers as integer][x][y]", commandName, "mouseUp")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 102;
+			try{
+				mouseUp(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse drag", "[modifiers as integer][x][y]", commandName, "mouseDrag")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 103;
+			try{
+				mouseDrag(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse moved", "[modifiers as integer][x][y]", commandName, "mouseMoved")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteTool t = getT();
+			MesquiteException.lastLocation = 104;
+			if (t!=null)
+				t.cursorInPanel(modifiers, x, y, this, true);
+			try{
+				mouseMoved(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse entered", "[modifiers as integer][x][y]", commandName, "mouseEntered")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 107;
+			MesquiteTool t = getT();
+			if (t!=null)
+				t.cursorInPanel(modifiers, x, y, this, true);
+			try{
+				mouseEntered(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse exited", "[modifiers as integer][x][y]", commandName, "mouseExited")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 105;
+			MesquiteTool t = getT();
+			if (t!=null)
+				t.cursorInPanel(modifiers, x, y, this, false);
+			try{
+				mouseExited(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "Mouse clicked", "[modifiers as integer][x][y]", commandName, "mouseClicked")) {
+			int modifiers = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			MesquiteException.lastLocation = 106;
+			try{
+				mouseClicked(modifiers, x, y, getT());
+			}
+			catch (Exception e){
+			}
+			MesquiteException.lastLocation = 0;
+		}
+		else if (checker.compare(this.getClass(), "File String Dropped into Panel", "[ObjectContainer ID]", commandName, "fileStringDropped")) {
+			int objectID = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			ObjectContainer objectContainer = findObjectContainer(objectID);
+			if (objectContainer!=null) {
+				String path = (String)objectContainer.getObject();
+
+				processFileStringDroppedOnPanel(path);
+
+				deleteObjectContainer(objectID);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Files Dropped into Panel", "[ObjectContainer ID]", commandName, "filesDropped")) {
+			int objectID = MesquiteInteger.fromString(ParseUtil.getFirstToken(arguments, pos));
+			ObjectContainer objectContainer = findObjectContainer(objectID);
+			if (objectContainer!=null) {
+				List files = (List)objectContainer.getObject();
+
+				processFilesDroppedOnPanel(files);
+
+				deleteObjectContainer(objectID);
+			}
+			//data.notifyListeners(this, new Notification(CharacterData.DATA_CHANGED, null, null));
+		}
+		MesquiteWindow.uncheckDoomed(this);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseClicked(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+	}
+
+	/*...............................................................................................................*/
+	public void mouseClicked(MouseEvent e)   {
+		if (MesquiteDialog.currentWizard != null){
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (suppressEvents || clickedCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 108;
+		clickedCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " " +  e.getX() + " " + e.getY(), null, false, false);
+		MesquiteException.lastLocation = 0;
+	}
+	/*...............................................................................................................*/
+	public void mouseEntered(MouseEvent e)   {
+		if (MesquiteDialog.currentWizard != null){
+			return;
+		}
+
+		if (suppressEvents || enteredCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 109;
+		enteredCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " " +  e.getX() + " " + e.getY(), null, false, false);
+		MesquiteException.lastLocation = 0;
+	}
+	/*...............................................................................................................*/
+	public void mouseExited(MouseEvent e)   {
+		if (MesquiteDialog.currentWizard != null){
+			return;
+		}
+		if (suppressEvents || exitedCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 110;
+		exitedCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " " +  e.getX() + " " + e.getY(), null, false, false);
+		MesquiteException.lastLocation = 0;
+		currentX = MesquiteInteger.unassigned;
+		currentY = MesquiteInteger.unassigned;
+	}
+	/*...............................................................................................................*/
+	/* these events are handled via the MesquiteCommand system so that they can be put on the thread cue to prevent interference with already running threads */
+	public void  mousePressed(MouseEvent e)   {
+		if (MesquiteDialog.currentWizard != null){
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (suppressEvents || downCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 111;
+		downCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " " + e.getClickCount() + " " + e.getWhen() + " " +  e.getX() + " " + e.getY(), null, false, false);
+		MesquiteException.lastLocation = 0;
+	}
+
+	/*...............................................................................................................*/
+	public void mouseReleased(MouseEvent e)  {
+		if (MesquiteDialog.currentWizard != null){
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (suppressEvents || upCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null && w.setAsFrontOnClickAnyContent() && w.getParentFrame().frontWindow != w){
+			if (showWindowCommand == null)
+				showWindowCommand = new MesquiteCommand("setAsFront", w);
+			showWindowCommand.doItMainThread("", null, false, false);
+		}
+		upCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " "  +  e.getX() + " " + e.getY(), null, false, false);
+		currentX = MesquiteInteger.unassigned;
+		currentY = MesquiteInteger.unassigned;
+	}
+	/*...............................................................................................................*/
+	public void mouseDragged(MouseEvent e)  {
+		if (MesquiteDialog.currentWizard != null){
+			MesquiteDialog.currentWizard.toFront();
+			return;
+		}
+		if (suppressEvents || dragCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 112;
+		if (moveFrequency == 0 || moveCount++ % moveFrequency ==0) {
+			dragCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " "  +  e.getX() + " " + e.getY(), null, false, false);
+		}
+		MesquiteException.lastLocation = 0;
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(MouseEvent e) {
+		if (MesquiteDialog.currentWizard != null){
+			return;
+		}
+		if (suppressEvents || movedCommand == null)
+			return;
+		currentX = e.getX();
+		currentY = e.getY();
+		MesquiteException.lastLocation = 113;
+		if (moveFrequency == 0 || moveCount++ % moveFrequency ==0) {
+			movedCommand.doItMainThread(Integer.toString(MesquiteEvent.getModifiers(e)) + " " +  e.getX() + " " + e.getY(), null, false, false);
+		}
+		MesquiteException.lastLocation = 0;
+	}
+
+
+	/*.................................................................................................................*/
+	/** For FileDirtier interface */
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (command != null && command.getOwner() == this && ("mouseMoved".equalsIgnoreCase(command.getName()) || "mouseExited".equalsIgnoreCase(command.getName()) || "mouseEntered".equalsIgnoreCase(command.getName())))
+			return;
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w!=null)
+			w.fileDirtiedByCommand(command);
+	}
+	public void printAll(Graphics g){
+		print(g);
+		printComponents(g);
+	}
+	// ----------------------- DND Support -------------------------------
+	public void dragEnter(DropTargetDragEvent dtde) {
+		dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
+	}
+	public void dragOver(DropTargetDragEvent dtde) {
+	}
+	public void dropActionChanged(DropTargetDragEvent dtde) {
+	}
+	public void dragExit(DropTargetEvent dte) {
+	}
+	/*..................................................................*/
+	public void drop(DropTargetDropEvent e) {
+		Transferable t = e.getTransferable();	
+		DataFlavor flavors[] = e.getTransferable().getTransferDataFlavors();
+		for (int i = 0; i < flavors.length; i++) {
+			DataFlavor flavor = flavors[i];
+			//system.out.println("flavor's name is: " + flavor.getHumanPresentableName());
+		}		
+		if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
+			//system.out.println("drop action is: " + e.getDropAction());
+			//system.out.println("file list supported");
+			e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+			//system.out.println("drop accepted");
+			List files = null;
+			try {
+				//system.out.println("going to get transfer data");
+				files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);				
+			} catch (Exception e1) {
+				//system.out.println("exception!");
+				e1.printStackTrace();
+			}
+			//system.out.println("have files");
+			if (files != null) {
+				handleDroppedFileList(files);
+			} else {
+				//system.out.println("files null");
+			}
+		} else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+			e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);			
+			StringReader fileContents = null;
+			try {
+				fileContents = (StringReader) t.getTransferData(DataFlavor.stringFlavor);
+			} catch (Exception e1) {
+				e1.printStackTrace();
+			}
+			handleDroppedFileStringContents(fileContents);
+		}
+		e.dropComplete(true);
+	}
+	/*..................................................................*/
+	private void handleDroppedFileStringContents(StringReader fileContents) {
+		int nextByte;
+		List bytes = new ArrayList();
+		try {
+			while ((nextByte = fileContents.read()) != -1) {
+				// need to mask it if it's below 0
+				if (nextByte < 0) {
+					nextByte = nextByte & 0xff;
+				}
+				bytes.add(new Integer(nextByte));
+			}
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		byte[] byteArray = new byte[bytes.size()];
+		int i = 0;
+		for (Iterator iter = bytes.iterator(); iter.hasNext();) {
+			Integer nextInteger = (Integer) iter.next();
+			byteArray[i++] = nextInteger.byteValue();
+		}
+		try {
+			String path = new String(byteArray, "ISO-8859-1");
+			handleDroppedFileString(path);
+		} catch (UnsupportedEncodingException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}			
+	}
+
+
+	/**
+	 * Action method that acts upon a string that
+	 * was dropped onto the panel.  For Linux, the string
+	 * is a local url to the filename i.e. 
+	 * file:///home/dmandel/Desktop/test.txt
+	 * @param string
+	 */
+	/*..................................................................*/
+	protected void handleDroppedFileString(String path) {
+		try {
+			ObjectContainer droppedObject = new ObjectContainer(path);
+			dndObjectVector.add(droppedObject);
+			fileStringDroppedCommand.doItMainThread(""+ droppedObject.getID(), null, false, false);
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}		
+	}
+	/**
+	 * For OS X, when file(s) are dropped on the panel,
+	 * they are passed as a List of file objects that can then
+	 * be acted upon
+	 * @param files
+	 */
+	/*..................................................................*/
+	protected void handleDroppedFileList(List files) {
+		if (!(this instanceof MesquiteDroppedFileHandler)) {
+			MesquiteMessage.warnProgrammer("DropTargetListener for files must implement MesquiteDroppedFileHandler");
+			return;
+		}
+		ObjectContainer droppedObject = new ObjectContainer(files);
+		dndObjectVector.add(droppedObject);
+		filesDroppedCommand.doItMainThread(""+ droppedObject.getID(), null, false, false);
+	}
+
+
+	/*..................................................................*/
+	/**
+	 * Method for panels to override in order to do determine 
+	 * the fileInterpreter needed for dropped file contents
+	 * @param droppedContents
+	 */
+	public FileInterpreter findFileInterpreter(String droppedContents, String fileName) {
+		return null;
+	}
+	/**
+	 * Method for panels to override in order to do something
+	 * with dropped file contents
+	 * @param droppedContents
+	 */
+	public void actUponDroppedFileContents(FileInterpreter fileInterpreter, String path) {
+		MesquiteMessage.warnProgrammer("Uncaught Dropped File in Mesquite Panel");
+	}
+	/*.................................................................................................................*/
+	public void processFilesDroppedOnPanel(List files) {
+		MesquiteMessage.warnProgrammer("Unprocessed Dropped File in Mesquite Panel");
+
+	}
+	/*.................................................................................................................*/
+	public void processFileStringDroppedOnPanel(String path) {
+		MesquiteMessage.warnProgrammer("Unprocessed Dropped File String in Mesquite Panel");
+
+	}
+	public int getAutoscrollDirection() {
+		return autoscrollDirection;
+	}
+	public void setAutoscrollDirection(int autoscrollDirection) {
+		this.autoscrollDirection = autoscrollDirection;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/NameHolder.java b/Source/mesquite/lib/NameHolder.java
new file mode 100644
index 0000000..c30b298
--- /dev/null
+++ b/Source/mesquite/lib/NameHolder.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+
+/* ======================================================================== */
+public interface NameHolder {
+	public String getMyName(Object obj);
+}
+
+
+
+
diff --git a/Source/mesquite/lib/NameReference.java b/Source/mesquite/lib/NameReference.java
new file mode 100644
index 0000000..1de130d
--- /dev/null
+++ b/Source/mesquite/lib/NameReference.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.net.URI;
+
+
+/* ======================================================================== */
+/**A class to hold a string.  It is used to speed up string checking.  That is, in some circumstances (see ContinuousData)
+one can obtain a NameReference containing a string giving the name of some object.  Then, if one later is checking objects
+one can ask if its NameReference is the one obtained previously.  Before checking that the contained strings are identical,
+it can check if the NameReferences are identical, thus saving lots of time.  Used where some name/string needs to be checked often.*/
+public class NameReference implements Listable {
+	static ListableVector names = new ListableVector();
+	private String value=null;
+	private URI mNamespace=null;
+	public static long totalCreated = 0;
+	public NameReference() {
+		totalCreated++;
+	}
+	public NameReference(String value) {
+		if (value == null)
+			this.value=value;
+		else
+			this.value = new String(value);
+		totalCreated++;
+	}
+	/*...........................................................*/
+	public static NameReference getNameReference(String name){
+		Object obj = names.getElement(name);
+		if (obj==null) {
+			NameReference nr = new NameReference(name);
+			names.addElement(nr, false);
+			return nr;
+		}
+		else
+			return (NameReference)obj;
+	}
+	public boolean equals (NameReference nr){
+		if (nr==this)
+			return true;
+		else if (nr == null )
+			return false;
+		else if (nr.getValue()==null && value == null)
+			return true;
+		else if (nr.getValue()==null && value != null)
+			return false;
+		else if (nr.getValue()!=null && value == null)
+			return false;
+		else if (nr.getValue().equalsIgnoreCase(value))
+			return true;
+		return false;
+	}
+	public static boolean equal (NameReference nr, NameReference nr2){
+		if (nr!= null)
+			return nr.equals(nr2);
+		if (nr2 == null)
+			return true;
+		return false;
+	}
+	public String getValue() {
+		return value;
+	}
+	public void setValue(String value) {
+		this.value=new String(value);
+	}
+	public String getName() {
+		return value;
+	}
+	public void setName(String value) {
+		this.value=new String(value);
+	}
+	public URI getNamespace() {
+		return mNamespace;
+	}
+	public void setNamespace(URI namespace) {
+		mNamespace = namespace;
+	}
+	
+	
+	public String toString(){
+		if (value == null)
+			return "NameReference, value is null";
+		return "NameReference to String (" + value + ")";
+	}
+	
+}
+
+
diff --git a/Source/mesquite/lib/NexusBlock.java b/Source/mesquite/lib/NexusBlock.java
new file mode 100644
index 0000000..8a70d7a
--- /dev/null
+++ b/Source/mesquite/lib/NexusBlock.java
@@ -0,0 +1,375 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+
+
+
+/* ======================================================================== */
+/**Represents a block in a NEXUS file.  Often contains a reference to the object to be written (e.g., a CharacterData
+or TreeVector.
+ */
+public abstract class NexusBlock implements Listable, Identifiable {
+	public static int  numBackups =0; //number of backups of NEXUS files
+	MesquiteModule manager;
+	MesquiteFile file;
+	String name;
+	Vector unrec; //to store unrecognized commands
+	public static Vector classesCreated, classesFinalized, countsOfClasses, countsOfClassesFinalized; //to detect memory leaks
+	public static long totalCreated =0;
+	public static long totalDisposed =0;
+	public static long totalFinalized =0;
+
+	private String defaultTaxa = null;
+	private String defaultCharacters = null;
+
+	long id;
+	public static boolean suppressTITLE = false;
+	public static boolean suppressLINK = false;
+	static {
+		if (MesquiteTrunk.checkMemory) {
+			classesCreated = new Vector();
+			classesFinalized = new Vector();
+			countsOfClassesFinalized = new Vector();
+			countsOfClasses = new Vector();
+		}
+	}
+
+	public NexusBlock(MesquiteFile f, MesquiteModule manager){
+		totalCreated++;
+		if (MesquiteTrunk.checkMemory)
+			countCreated();
+		id = totalCreated;
+		file = f;
+		this.manager = manager;
+		/*
+		if (f==null)
+			MesquiteMessage.warnProgrammer("Warning: file null in NexusBlock " + this.getClass());
+		if (manager==null)
+			MesquiteMessage.warnProgrammer("Warning: manager null in NexusBlock" + this.getClass());
+		 */
+	}
+	public boolean getWritable(){
+		return true;
+	}
+	public static int findCorrespondingBlock(ListableVector nexusBlocks, FileElement fileElement){
+		for (int i = 0; i<nexusBlocks.size(); i++){
+			NexusBlock e = (NexusBlock)nexusBlocks.elementAt(i);
+			if (e.contains(fileElement))
+				return i;
+
+		}
+		return -1;
+	}
+	public static void equalizeOrdering(ListableVector v, ListableVector nexusBlocks){ 
+		// start at back of v
+		// put each one in place in nexus blocks just after last nexusBlock it must be after
+		for (int i = v.size()-1; i>=0; i--){
+			Object e = v.elementAt(i);
+			int blockNum = findCorrespondingBlock(nexusBlocks, (FileElement)e);
+			if (blockNum >=0){
+				nexusBlocks.moveParts(blockNum, 1, 0);
+				bubbleBlockDown(nexusBlocks, (NexusBlock)nexusBlocks.elementAt(0));
+			}
+		}
+	}
+	public static boolean bubbleBlockDown(ListableVector blocks, NexusBlock nb){
+		if (nb==null)
+			return false;
+		
+		int index = blocks.indexOf(nb); //find current height
+		if (index >=0){
+			int height = index;
+			//make sure block is in OK place
+			for (int i = index+1; i<blocks.size(); i++) { //now look to all higher to see if nb should jump above them
+				NexusBlock nR = (NexusBlock)blocks.elementAt(i);
+				if (nb.mustBeAfter(nR) && (nb.getFile()==nR.getFile())) { //nb needs to fall below nR
+					height = i;  //remember height of nR
+				}
+			}
+			if (height > index){ //nb needs to fall to height; move it
+				blocks.removeElement(nb, false);
+				blocks.insertElementAt(nb, height, false);
+				return true;
+			}
+		}
+		return false;
+
+	}
+	public void setDefaultTaxa(Taxa t){
+		if (t==null)
+			return;
+		if (file == null || file.getProject() == null)
+			return;
+		defaultTaxa = file.getProject().getTaxaReferenceInternal(t); //remembered as id's to prevent memory leaks
+	}
+	public Taxa getDefaultTaxa(){
+		if (file == null || file.getProject() == null)
+			return null;
+		if (defaultTaxa == null){
+			Taxa dc = file.getCurrentTaxa();
+			if (dc!=null) {
+				setDefaultTaxa(dc);
+				return dc;
+			}
+		}
+		if (defaultTaxa == null){
+			Taxa t = file.getProject().getTaxa(0);
+			setDefaultTaxa(t);
+			return t;
+		}
+		return file.getProject().getTaxa(null, defaultTaxa);
+	}
+
+	public void setDefaultCharacters(mesquite.lib.characters.CharacterData t){
+		if (t==null)
+			return;
+		if (file == null || file.getProject() == null)
+			return;
+		defaultCharacters = file.getProject().getCharMatrixReferenceInternal(t); //remembered as id's to prevent memory leaks
+	}
+	public mesquite.lib.characters.CharacterData getDefaultCharacters(){
+		if (file == null || file.getProject() == null)
+			return null;
+		if (defaultCharacters == null){
+			mesquite.lib.characters.CharacterData dc = file.getCurrentData();
+			if (dc!=null) {
+				setDefaultCharacters(dc);
+				return dc;
+			}
+		}
+
+		if (defaultCharacters == null){
+			mesquite.lib.characters.CharacterData t = file.getProject().getCharacterMatrix(getDefaultTaxa(), 0);
+			setDefaultCharacters(t);
+			return t;
+		}
+		return file.getProject().getCharacterMatrixByReference(null, defaultCharacters);
+	}
+
+	public void processLinkCTCommand(String s, MesquiteProject project, Parser parser){
+		MesquiteInteger stringPos = new MesquiteInteger();
+		stringPos.setValue(parser.getPosition());
+		String[][] subcommands  = ParseUtil.getSubcommands(s, stringPos);
+		if (!(subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)){
+			String ttoken = null;
+			String ctoken = null;
+			for (int i=0; i<subcommands[0].length; i++){
+				String subC = subcommands[0][i];
+				if  (subC.equalsIgnoreCase("CHARACTERS")) {
+					ctoken  = subcommands[1][i];
+				}
+				else if  (subC.equalsIgnoreCase("TAXA")) {
+					ttoken  = subcommands[1][i];
+				}
+
+			}
+			if (!StringUtil.blank(ttoken)){
+				Taxa t = project.getTaxaLastFirst(ttoken);
+
+				if (t==null){
+					int wt = MesquiteInteger.fromString(ttoken);
+					if (MesquiteInteger.isCombinable(wt))
+						t = project.getTaxa(wt-1);
+				}
+				if (t == null && project.getNumberTaxas(file)==1){
+					t = project.getTaxa(file, 0);
+				}
+				if (t!=null) {
+					setDefaultTaxa(t);
+				}
+			}
+			CharacterData d = project.getCharacterMatrixReverseOrder(ctoken);
+			if (d==null){
+				int wt = MesquiteInteger.fromString(ctoken);
+				if (MesquiteInteger.isCombinable(wt))
+					d = project.getCharacterMatrix(getDefaultTaxa(), wt-1);
+			}
+			if (d == null && project.getNumberCharMatrices(file)==1){
+				d = project.getCharacterMatrix(file, 0);
+			}
+			if (d!=null) {
+				setDefaultCharacters(d);
+			}
+
+		}
+	}
+	void countCreated(){
+		if (classesCreated.indexOf(getClass())<0) {
+			classesCreated.addElement(getClass());
+			countsOfClasses.addElement(new MesquiteInteger(1));
+			countsOfClassesFinalized.addElement(new MesquiteInteger(0));
+		}
+		else {
+			MesquiteInteger c = (MesquiteInteger)countsOfClasses.elementAt(classesCreated.indexOf(getClass()));
+			if (c!=null)
+				c.increment();
+		}
+	}
+	public void dispose() {
+		manager = null;
+		file = null;
+		totalDisposed++;
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		if (MesquiteTrunk.checkMemory) {
+			if (classesFinalized.indexOf(getClass())<0) {
+				classesFinalized.addElement(getClass());
+			}
+			MesquiteInteger c = (MesquiteInteger)countsOfClassesFinalized.elementAt(classesCreated.indexOf(getClass()));
+			if (c!=null)
+				c.increment();
+		}
+		super.finalize();
+	}
+	public long getID(){
+		return id;
+	}
+
+	/** Returns the offical NEXUS block name (e.g. "TAXA")*/
+	public abstract String getBlockName();
+
+	/** DOCUMENT */
+	public MesquiteFile getFile() { 
+		return file;
+	}
+	/** DOCUMENT */
+	public void setFile(MesquiteFile f) { 
+		file = f;
+	}
+	/** DOCUMENT */
+	public String getName() { 
+		if (name == null)
+			return "Untitled";
+		else
+			return name;
+	}
+	/** DOCUMENT */
+	public void setName(String n) { 
+		name = n;
+	}
+	/** DOCUMENT */
+	public MesquiteModule getManager(){
+		return manager;
+	}
+	/** DOCUMENT */
+	public void setManager(MesquiteModule manager){
+		this.manager = manager;
+	}
+	/** DOCUMENT */
+	public abstract boolean contains(FileElement e);
+
+	/** Returns true if this block must occur after the given block*/
+	public abstract boolean mustBeAfter(NexusBlock block);
+
+	/** DOCUMENT */
+	public String getUnrecognizedCommands(){
+		if (unrec==null)
+			return "";
+		String result = "";
+		Enumeration enumeration=unrec.elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			result += (String)obj + StringUtil.lineEnding();
+		}
+		return result;
+	}
+	/** DOCUMENT */
+	void storeUnrecognizedCommand(String s){
+		if (StringUtil.blank(s))
+			return;
+
+		if (unrec ==null)
+			unrec = new Vector();
+		unrec.addElement(s);
+		if (file !=null && file.foreignElements!=null)
+			file.foreignElements.addElement("Command: " + s + " in " + getBlockName() + " block ");
+	}
+	/** Returns the NEXUS block as a string for writing into the file.  Block must override either this or writeNEXUSBlock to write to file*/
+	protected String getNEXUSBlock(){
+		return null;
+	}
+	/** Writes the NEXUS block into the file  Block must override either this or getNEXUSBlock to write to file*/
+	public void writeNEXUSBlock(MesquiteFile file, ProgressIndicator progIndicator){
+		String s = getNEXUSBlock();
+		if (!StringUtil.blank(s)){
+			MesquiteTrunk.mesquiteTrunk.logln("      Writing " + getName());
+			file.writeLine(s);
+		}
+	}
+	/*   */
+
+	public static String getNEXUSTime(long millis){
+		GregorianCalendar calendar = new GregorianCalendar();
+		calendar.setTimeZone(TimeZone.getDefault());
+		calendar.setTime(new Date(millis));
+		return Integer.toString(calendar.get(Calendar.YEAR)) + "." + (calendar.get(Calendar.MONTH) +1) + "." + calendar.get(Calendar.DATE) + "." + calendar.get(Calendar.HOUR_OF_DAY) + "." + calendar.get(Calendar.MINUTE) + "." + calendar.get(Calendar.SECOND);
+	}
+	public static long getTimeFromNEXUS(String s){
+		if (StringUtil.blank(s))
+			return 0;
+		try {
+			DateFormat df = new SimpleDateFormat();
+			Date ds = df.parse(s); 
+			return ds.getTime();
+		}
+		catch (ParseException e){
+		}
+		GregorianCalendar calendar = new GregorianCalendar();
+		calendar.setTimeZone(TimeZone.getDefault());
+		calendar.clear();
+		StringTokenizer st = new StringTokenizer(s, ".");
+		int year = MesquiteInteger.unassigned;
+		int month = MesquiteInteger.unassigned;
+		int date = MesquiteInteger.unassigned;
+		int hour = MesquiteInteger.unassigned;
+		int minute = MesquiteInteger.unassigned;
+		int seconds = MesquiteInteger.unassigned;
+
+		try{
+			year = MesquiteInteger.fromString(st.nextToken());
+			month = MesquiteInteger.fromString(st.nextToken())-1;
+			date = MesquiteInteger.fromString(st.nextToken());
+			hour = MesquiteInteger.fromString(st.nextToken());
+			minute = MesquiteInteger.fromString(st.nextToken());
+			seconds = MesquiteInteger.fromString(st.nextToken());
+		}
+		catch (Exception e){
+		}
+		if (MesquiteInteger.isCombinable(year) && MesquiteInteger.isCombinable(month) && MesquiteInteger.isCombinable(date)) {
+			if (MesquiteInteger.isCombinable(minute) && MesquiteInteger.isCombinable(hour)) {
+				if (MesquiteInteger.isCombinable(seconds)){
+					calendar.set(year, month, date, hour, minute, seconds);
+				}
+				else 
+					calendar.set(year, month, date);
+			}
+			else
+				calendar.set(year, month, date, hour, minute);
+		}
+		else
+			return 0;
+		Date d = calendar.getTime();
+		return d.getTime();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/NexusBlockEditableRaw.java b/Source/mesquite/lib/NexusBlockEditableRaw.java
new file mode 100644
index 0000000..2af61dd
--- /dev/null
+++ b/Source/mesquite/lib/NexusBlockEditableRaw.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Represents a block in a NEXUS file that is editable raw (e.g., a foreign block, or a Mesquite block.
+ */
+public abstract class NexusBlockEditableRaw extends NexusBlock {
+	EditRawNexusBlock editor;
+	public NexusBlockEditableRaw(MesquiteFile f, MesquiteModule manager){
+		super(f, manager);
+	}
+	/** DOCUMENT */
+	public abstract String getText();
+
+	/** DOCUMENT */
+	public abstract void setText(String n);
+	
+	/** DOCUMENT THIS should only be called if it is an editable-raw nexus block*/
+	public void setEditor(EditRawNexusBlock editor) {
+		this.editor = editor;
+	}
+	/** DOCUMENT THIS should only be called if it is an editable-raw nexus block*/
+	public EditRawNexusBlock getEditor() {
+		return editor;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/NexusBlockTest.java b/Source/mesquite/lib/NexusBlockTest.java
new file mode 100644
index 0000000..896654a
--- /dev/null
+++ b/Source/mesquite/lib/NexusBlockTest.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/** Objects of the NexusBlockTest class can be returned by modules on Mesquite's startup.  They are stored in modulesinfo and used to test, 
+without having to employ the module, whether the module would be able to read a nexus block.  Thus, if a module
+wants to read a particular sort of block, it overrides that MesquiteModule method getNexusBlockTest() so as to instantiate and return
+a NexusBlockTest object.  When the NEXUS file is being read and a block is found,
+ the nexus file reading module (InterpretNEXUS) looks into the modulesinfo of all the modules and when it finds a NexusBlockTest object, it
+ passes it the name of the block and the block itself, and the object returns whether it is readable by the module.  If so, the module is 
+ hired and used to process the block.*/
+public abstract class NexusBlockTest  {
+	/**returns whether or not the module can deal with given block with the given blockName*/
+	public abstract boolean readsWritesBlock(String blockName, FileBlock block);  
+}
+
diff --git a/Source/mesquite/lib/NexusCommandTest.java b/Source/mesquite/lib/NexusCommandTest.java
new file mode 100644
index 0000000..4d9db5f
--- /dev/null
+++ b/Source/mesquite/lib/NexusCommandTest.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/** An object of this kind can be returned by getNexusCommandTest that will be stored in the modulesinfo vector and used
+to search for modules that can read a particular command in a particular block.  (Much as the NexusBlockObject.)*/
+public abstract class NexusCommandTest  {
+	/**returns whether or not the module can deal with command*/
+	public abstract boolean readsWritesCommand(String blockName, String commandName, String command);  
+}
+
+
diff --git a/Source/mesquite/lib/NexusWritable.java b/Source/mesquite/lib/NexusWritable.java
new file mode 100644
index 0000000..7431d7a
--- /dev/null
+++ b/Source/mesquite/lib/NexusWritable.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+/**An object that can be written as a command or subcommand in a NEXUS file
+ */
+public interface NexusWritable {
+	public abstract String getNexusString();
+}
+
+
diff --git a/Source/mesquite/lib/Notification.java b/Source/mesquite/lib/Notification.java
new file mode 100644
index 0000000..7e3f5c5
--- /dev/null
+++ b/Source/mesquite/lib/Notification.java
@@ -0,0 +1,155 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+
+/* ======================================================================== */
+/** An object that contains information about a notification event (e.g., call to notifyListeners or parametersChanged)*/
+public class Notification implements Identifiable {
+	int code = MesquiteListener.UNKNOWN;
+	int[] parameters = null;
+	int[] subcodes = null;
+	long id;
+	long nn = -1;
+	static long numCreated = 0;
+	UndoReference undoReference = null;
+	Class objectClass = null;
+	
+	public Notification(int code, int[] parameters){
+		this();
+		this.code = code;
+		this.parameters = parameters;
+	}
+	public Notification(int code){
+		this();
+		this.code = code;
+	}
+	public Notification(int code,  UndoReference undoReference){
+		this();
+		this.code = code;
+		this.undoReference = undoReference;
+	}
+	public Notification(int code,  int[] parameters, UndoReference undoReference){
+		this();
+		this.code = code;
+		this.undoReference = undoReference;
+		this.parameters = parameters;
+	}
+	
+	public String toString(){
+		return "Notification: " + getID() + " code = " + code + " parameters " + IntegerArray.toString(parameters);
+	}
+	public Notification(){
+		id = numCreated++;
+	}
+	public long getID(){
+		return id;
+	}
+	public Notification setNotificationNumber(long nn){
+		this.nn = nn;
+		return this;
+	}
+	public long getNotificationNumber(){
+		if (nn<0)
+			return id;
+		else
+			return nn;
+	}
+	public void dispose() {
+		if (undoReference!=null)
+			undoReference.dispose();
+	}
+	public int getCode(){
+		return code;
+	}
+	public int[] getParameters(){
+		return parameters;
+	}
+	public Class getObjectClass(){
+		return objectClass;
+	}
+	public void setObjectClass(Class c){
+		this.objectClass=c;
+	}
+	public int[] getSubcodes(){
+		return subcodes;
+	}
+	public void setSubcodes(int[] subcodes){
+		this.subcodes=subcodes;
+	}
+	public boolean subcodesContains(int subcode){
+		if (subcodes!=null) {
+			for (int i=0; i<subcodes.length; i++)
+				if (subcodes[i]==subcode)
+					return true;
+		}
+		return false;
+	}
+	
+	public static long getNotificationNumber(Notification n){
+		if (n==null)
+			return -1;
+		else
+			return n.getNotificationNumber();
+	}
+	public static int getCode(Notification n){
+		if (n==null)
+			return MesquiteListener.UNKNOWN;
+		else
+			return n.getCode();
+	}
+	public static int[] getParameters(Notification n){
+		if (n==null)
+			return null;
+		else
+			return n.getParameters();
+	}
+	public static int[] getSubcodes(Notification n){
+		if (n==null)
+			return null;
+		else
+			return n.getSubcodes();
+	}
+	public static boolean appearsCosmetic(Notification n){
+		if (n==null)
+			return false;
+		else
+			return n.getCode() == MesquiteListener.ANNOTATION_CHANGED  ||  n.getCode() == MesquiteListener.ANNOTATION_ADDED  || n.getCode() == MesquiteListener.ANNOTATION_DELETED  ||n.getCode() == MesquiteListener.NAMES_CHANGED  ;
+	}
+	public static boolean appearsCosmeticOrSelection(Notification n){
+		if (n==null)
+			return false;
+		else
+			return n.getCode() == MesquiteListener.SELECTION_CHANGED  || n.getCode() == MesquiteListener.ANNOTATION_CHANGED  ||  n.getCode() == MesquiteListener.ANNOTATION_ADDED  || n.getCode() == MesquiteListener.ANNOTATION_DELETED  ||n.getCode() == MesquiteListener.NAMES_CHANGED  ;
+	}
+	public UndoReference getUndoReference() {
+		return undoReference;
+	}
+	public void setUndoReference(UndoReference undoReference) {
+		this.undoReference = undoReference;
+	}
+	public static UndoReference getUndoReference(Notification n){
+		if (n==null)
+			return null;
+		else
+			return n.getUndoReference();
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/NumSpecsSet.java b/Source/mesquite/lib/NumSpecsSet.java
new file mode 100644
index 0000000..37e8064
--- /dev/null
+++ b/Source/mesquite/lib/NumSpecsSet.java
@@ -0,0 +1,177 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+
+/* ======================================================================== */
+/** A specset with numerical information.*/
+public abstract class NumSpecsSet extends SpecsSet  {
+	NumberArray nums;
+	public NumSpecsSet(String name, int numParts, MesquiteNumber defaultValue){
+		super(name, numParts);
+		nums = new NumberArray(numParts);
+		if (defaultValue!=null)
+			for (int i=0; i<numParts; i++)
+				nums.setValue(i, defaultValue);
+	}
+	public String getTypeName(){
+		return "Number specificaton set";
+	}
+	public NumberArray getNumberArray(){
+		return nums;
+	}
+	public boolean equals(int index, MesquiteNumber n) {
+		return nums.equals(index, n);
+	}
+ 	/*.................................................................................................................*/
+ 	/** Sets the value for part "part" to be the same as that at part "otherPart" in the incoming specsSet*/
+	public void equalizeSpecs(SpecsSet other, int otherPart, int part){
+		if (other instanceof NumSpecsSet){
+			NumSpecsSet nss = (NumSpecsSet)other;
+			if (nss.isInt()){
+				int n = nss.getInt(otherPart);
+				setValue(part, n);
+			}
+			else if (nss.isLong()){
+				long n = nss.getLong(otherPart);
+				setValue(part, n);
+			}
+			else if (nss.isDouble()){
+				double n = nss.getDouble(otherPart);
+				setValue(part, n);
+			}
+		}
+	}
+ 	/*.................................................................................................................*/
+	/** Returns whether or not number type is "int". */
+	public boolean isInt(){
+		return nums.getValueClass() == NumberArray.INT;
+	}
+ 	/*.................................................................................................................*/
+	/** Returns whether or not number type is "long". */
+	public boolean isLong(){
+		return nums.getValueClass() == NumberArray.LONG;
+	}
+ 	/*.................................................................................................................*/
+	/** Returns whether or not number type is "double". */
+	public boolean isDouble(){
+		return nums.getValueClass() == NumberArray.DOUBLE;
+	}
+ 	/*.................................................................................................................*/
+	/** Returns whether part ic is unassigned. */
+	public boolean isUnassigned(int ic){
+		return nums.isUnassigned(ic);
+	}
+ 	/*.................................................................................................................*/
+	/** Returns int value of part ic. */
+	public int getInt(int ic){
+		return nums.getInt(ic);
+	}
+ 	/*.................................................................................................................*/
+	/** Returns long value of part ic. */
+	public long getLong(int ic){
+		return nums.getLong(ic);
+	}
+ 	/*.................................................................................................................*/
+	/** Returns double value of part ic. */
+	public double getDouble(int ic){
+		return nums.getDouble(ic);
+	}
+	/** Places the value of part ic into the passed MesquiteNumber*/
+	public void placeValue(int ic, MesquiteNumber n){
+		if (n==null)
+			return;
+		nums.placeValue(ic, n);
+	}
+	/** Set value of part ic */
+	public void setValue(int ic, MesquiteNumber n){
+		setDirty(true);
+		nums.setValue(ic, n);
+	}
+	/** Set value of part ic */
+	public void setValue(int ic, int n){
+		setDirty(true);
+		nums.setValue(ic, n);
+	}
+	/** Set value of part ic */
+	public void setValue(int ic, long n){
+		setDirty(true);
+		nums.setValue(ic, n);
+	}
+	/** Set value of part ic */
+	public void setValue(int ic, double n){
+		setDirty(true);
+		nums.setValue(ic, n);
+	}
+	/** Deassigns all values */
+	public void deassignAll(){
+		setDirty(true);
+		nums.deassignArray();
+	}
+	/** Zeros all values */
+	public void zeroAll(){
+		setDirty(true);
+		nums.zeroArray();
+	}
+ 	/*.................................................................................................................*/
+	/** Returns a string representing the number assigned to part ic. */
+	public String toString(int ic){
+		return nums.toString(ic);
+	}
+ 	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		setDirty(true);
+ 		nums.addParts(starting, num); //TODO: set default (for inclusion, set to on!!!)
+ 		if (defaultValue != null)
+ 			for (int i = starting+1; i<=starting+num; i++)
+ 				nums.setValue(i, defaultValue);
+		numParts = nums.getSize();
+		return true;
+	}
+  	
+	/*.................................................................................................................*/
+	/** Sets default value, e.g. "1" for weights  */
+	MesquiteNumber defaultValue;
+  	public void setDefaultValue(MesquiteNumber def){
+  		defaultValue = def;
+  	}
+	/*.................................................................................................................*/
+	/** Delete num parts from and including "starting"  */
+	public boolean deleteParts(int starting, int num){ 
+		setDirty(true);
+ 		nums.deleteParts(starting, num);
+		numParts = nums.getSize();
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** */
+	public boolean moveParts(int starting, int num, int justAfter){  
+		setDirty(true);
+ 		nums.moveParts(starting, num, justAfter);
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	/** */
+	public boolean swapParts(int first, int second){  
+		setDirty(true);
+ 		nums.swapParts(first, second);
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/lib/Number2DArray.java b/Source/mesquite/lib/Number2DArray.java
new file mode 100644
index 0000000..e6e36d5
--- /dev/null
+++ b/Source/mesquite/lib/Number2DArray.java
@@ -0,0 +1,501 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+
+
+/* ======================================================================== */
+/**This class is used to store numbers flexibly, so that system doesn't need to know whether int, long or double.
+Automatically upgrades to use long or double as needed.
+This stores a whole 2Darray of similarly typed numbers.  For single numbers, use NumberObjects instead.*/
+public class Number2DArray {
+	public int[][] intValues;
+	public long[][] longValues;
+	public double[][] doubleValues;
+	public static final int INT = 0;
+	public static final int LONG = 1;
+	public static final int DOUBLE = 2;
+	public int valueClass = INT;
+	private int lengthC = 0;  // the size of the array
+	private int lengthT = 0;  // the size of the array
+	private NameReference name;
+
+	public Number2DArray(int lengthC, int lengthT) {
+		intValues = new int[lengthC][lengthT];
+		this.lengthC=lengthC;
+		this.lengthT=lengthT;
+		for (int i=0; i<lengthC; i++)
+			for (int j=0; j<lengthT; j++)
+				intValues[i][j]=0;
+		this.valueClass = INT;
+	}
+	public Number2DArray(int lengthC, int lengthT, int valueClass) {
+		this.lengthC=lengthC;
+		this.lengthT=lengthT;
+		if (valueClass==INT) {
+			intValues = new int[lengthC][lengthT];
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					intValues[i][j]=0;
+		}
+		else if (valueClass == LONG) {
+			longValues = new long[lengthC][lengthT];
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					longValues[i][j]=0;
+		}
+		else if (valueClass == DOUBLE) {
+			doubleValues = new double[lengthC][lengthT];
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					doubleValues[i][j]=0;
+		}
+		this.valueClass = valueClass;
+	}
+	
+	/*...........................................................*/
+	/** DOCUMENT */
+	public boolean legalIndices(int i, int j) {
+		if (valueClass==INT)
+			return intValues!=null && i>=0 && i<intValues.length && intValues.length>0 && j>=0 && j< intValues[0].length;
+		else if (valueClass == LONG)
+			return longValues!=null && i>=0 && i<longValues.length && longValues.length>0 && j>=0 && j< longValues[0].length;
+		else //if (valueClass == DOUBLE)
+			return doubleValues!=null && i>=0 && i<doubleValues.length && doubleValues.length>0 && j>=0 && j< doubleValues[0].length;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public double getDoubleValue(int i, int j) {
+		if (!legalIndices(i, j))
+			return MesquiteDouble.unassigned;
+		if (valueClass==INT)
+			return MesquiteDouble.toDouble(intValues[i][j]);
+		else if (valueClass == LONG)
+			return MesquiteDouble.toDouble(longValues[i][j]);
+		else //if (valueClass == DOUBLE)
+			return doubleValues[i][j];
+	}
+	/*-------------------------------------GET/SET ------------------------------------*/
+	/** Places the value at array element i,j into
+	the MesquiteNumber n.  Used instead of getValue to avoid creating a MesquiteNumber object. */
+	public void placeValue(int i, int j, MesquiteNumber n) {
+		if (!legalIndices(i, j))
+			return;
+		if (n!=null) {
+			if (valueClass==INT)
+				n.setValue(intValues[i][j]);
+			else if (valueClass == LONG)
+				n.setValue(longValues[i][j]);
+			else if (valueClass == DOUBLE)
+				n.setValue(doubleValues[i][j]);
+		}
+	}
+	/*...........................................................*/
+	/** Sets value at i,j to value passed */
+	public void setValue(int i, int j, int v) {
+		if (!legalIndices(i, j))
+			return;
+		if (valueClass==INT)
+			intValues[i][j] = v;
+		else if (valueClass == LONG)
+			longValues[i][j] = MesquiteLong.toLong(v);
+		else if (valueClass == DOUBLE)
+			doubleValues[i][j]=MesquiteDouble.toDouble(v);
+	}
+
+	/** Sets value at i,j to value passed */
+	public void setValue(int i, int j, long v) {
+		if (!legalIndices(i, j))
+			return;
+		if (valueClass==INT) {
+			longValues = new long[lengthC][lengthT];
+			for (int ni=0; ni<lengthC; ni++)
+				for (int nj=0; nj<lengthT; nj++)
+					longValues[ni][nj]=MesquiteLong.toLong(intValues[ni][nj]); 
+			longValues[i][j] = v;
+			intValues=null;
+			valueClass=LONG;
+		}
+		else if (valueClass == LONG)
+			longValues[i][j] = v;
+		else if (valueClass == DOUBLE)
+			doubleValues[i][j]=MesquiteDouble.toDouble(v);
+	}
+	
+	/** Sets value at i,j to value passed */
+	public void setValue(int i, int j, double v) {
+		if (!legalIndices(i, j))
+			return;
+		if (valueClass==INT) {
+			doubleValues = new double[lengthC][lengthT];
+			for (int ni=0; ni<lengthC; ni++)
+				for (int nj=0; nj<lengthT; nj++)
+					doubleValues[ni][nj]=MesquiteDouble.toDouble(intValues[ni][nj]);
+			doubleValues[i][j] = v;
+			intValues=null;
+			valueClass=DOUBLE;
+		}
+		else if (valueClass == LONG) {
+			doubleValues = new double[lengthC][lengthT];
+			for (int ni=0; ni<lengthC; ni++)
+				for (int nj=0; nj<lengthT; nj++)
+					doubleValues[ni][nj]=MesquiteDouble.toDouble(longValues[ni][nj]);
+			doubleValues[i][j] = v;
+			longValues=null;
+			valueClass=DOUBLE;
+		}
+		else if (valueClass == DOUBLE)
+			doubleValues[i][j]=v;
+	}
+
+	/** Sets value at i,j to value passed */
+	public void setValue(int i, int j, MesquiteNumber v) {
+		if (v==null)
+			return;
+		if (!legalIndices(i, j))
+			return;
+		if (v.getValueClass()==INT)
+			setValue(i,j, v.getIntValue());
+		else if (v.getValueClass() == LONG)
+			setValue(i,j, v.getLongValue());
+		else if (v.getValueClass() == DOUBLE)
+			setValue(i, j, v.getDoubleValue());
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void setToInfinite(int i, int j) {
+		if (!legalIndices(i, j))
+			return;
+		if (valueClass==INT)
+			intValues[i][j] = MesquiteInteger.infinite;
+		else if (valueClass == LONG)
+			longValues[i][j] = MesquiteLong.infinite;
+		else if (valueClass == DOUBLE)
+			doubleValues[i][j]=MesquiteDouble.infinite;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void setToZero(int i, int j) {
+		if (!legalIndices(i, j))
+			return;
+		if (valueClass==INT)
+			intValues[i][j] = 0;
+		else if (valueClass == LONG)
+			longValues[i][j] = 0;
+		else if (valueClass == DOUBLE)
+			doubleValues[i][j]=0;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void zeroArray() {
+		if (valueClass==INT) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					intValues[i][j]=0;
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					longValues[i][j]=0;
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					doubleValues[i][j]=0;
+		}
+	}
+	/** DOCUMENT */
+	public void deassignArray() {
+		if (valueClass==INT) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					intValues[i][j]=MesquiteInteger.unassigned;
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					longValues[i][j]=MesquiteLong.unassigned;
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<lengthC; i++)
+				for (int j=0; j<lengthT; j++)
+					doubleValues[i][j]=MesquiteDouble.unassigned;
+		}
+	}
+	/*-------------------------------------ARITHMETIC ------------------------------------*/
+	/**Add the value in the passed MesquiteNumber to that of element i,j.  NOTE: the sum will be returned in the MesquiteNumber passed!*/
+	public void addValue(int i, int j, MesquiteNumber n) {
+		if (!legalIndices(i, j))
+			return;
+		if (n!=null) {
+			if (valueClass==INT)
+				n.add(intValues[i][j]);
+			else if (valueClass == LONG)
+				n.add(longValues[i][j]);
+			else if (valueClass == DOUBLE)
+				n.add(doubleValues[i][j]);
+			setValue( i,j, n);
+		}
+	}
+	/*-------------------------------------QUERY, COMPARISON ------------------------------------*/
+	/** DOCUMENT */
+	public boolean isZero(int i, int j) {
+		if (!legalIndices(i, j))
+			return false;
+		if (valueClass==INT) {
+			return intValues[i][j]==0;
+		}
+		else if (valueClass == LONG) {
+			return longValues[i][j]==0;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValues[i][j]==0;
+		}
+		return false;
+	}
+	/** DOCUMENT */
+	public boolean isUnassigned(int i, int j) {
+		if (!legalIndices(i, j))
+			return true;
+		if (valueClass==INT) {
+			return intValues[i][j]==MesquiteInteger.unassigned;
+		}
+		else if (valueClass == LONG) {
+			return longValues[i][j]==MesquiteLong.unassigned;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValues[i][j]==MesquiteDouble.unassigned;
+		}
+		return false;
+	}
+	/** DOCUMENT */
+	public boolean isInfinite(int i, int j) {
+		if (!legalIndices(i, j))
+			return false;
+		if (valueClass==INT) {
+			return intValues[i][j]==MesquiteInteger.infinite;
+		}
+		else if (valueClass == LONG) {
+			return longValues[i][j]==MesquiteLong.infinite;
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValues[i][j]==MesquiteDouble.infinite;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public boolean equals(int i, int j, MesquiteNumber n){
+		if (!legalIndices(i, j))
+			return false;
+		if (n==null)
+			return false;
+		else {
+			if (valueClass==INT)
+				return n.equals(intValues[i][j], true);
+			else if (valueClass == LONG)
+				return n.equals(longValues[i][j], true);
+			else if (valueClass == DOUBLE)
+				return n.equals(doubleValues[i][j], true);
+			return false;
+		}
+	}
+	/*...........................................................*/
+	/** this places the minimum value along second dimension at first dim = "index" into
+	the MesquiteNumber n */
+	public void placeMinimum2nd(int i, MesquiteNumber n) {
+		if (!legalIndices(i, 0))
+			return;
+		if (n!=null && lengthC>0 && lengthT>0) {
+			if (valueClass==INT) {
+				int min = intValues[i][0];
+				for (int j=0; j<lengthT; j++) {
+					min = MesquiteInteger.minimum(min, intValues[i][j]);
+				}
+				n.setValue(min);
+			}
+			else if (valueClass == LONG) {
+				long min = longValues[i][0];
+				for (int j=0; j<lengthT; j++) {
+					min = MesquiteLong.minimum(min, longValues[i][j]);
+				}
+				n.setValue(min);
+			}
+			else if (valueClass == DOUBLE) {
+				double min = doubleValues[i][0];
+				for (int j=0; j<lengthT; j++) {
+					min = MesquiteDouble.minimum(min, doubleValues[i][j]);
+				}
+				n.setValue(min);
+			}
+		}
+	}
+	/*-------------------------------------SIZE ------------------------------------*/
+	/** DOCUMENT */
+	public int getSizeC() {
+		return lengthC;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public int getSizeT() {
+		return lengthT;
+	}
+	/*...........................................................*/
+	/** Changes the array size to the new dimensions*/
+	public void resetSize(int newNumC, int newNumT) {
+		if (newNumC == lengthC && newNumT == lengthT)
+			return;
+		if (valueClass==INT) {
+			//System.out.println("grow nao 1");
+			int[][] newIntValues = new int[newNumC][newNumT];
+			for (int i=0; i<newNumC; i++)
+				for (int j=0; j<newNumT; j++) {
+					if (i<lengthC && j<lengthT)
+						newIntValues[i][j]=intValues[i][j];
+					else
+						newIntValues[i][j]=0;
+				}
+			intValues=newIntValues;
+		}
+		else if (valueClass == LONG) {
+			//System.out.println("grow nao 2");
+			long[][] newLongValues = new long[newNumC][newNumT];
+			for (int i=0; i<newNumC; i++)
+				for (int j=0; j<newNumT; j++) {
+					if (i<lengthC && j<lengthT)
+						newLongValues[i][j]=longValues[i][j];
+					else
+						newLongValues[i][j]=0;
+				}
+			longValues=newLongValues;
+		}
+		else if (valueClass == DOUBLE) {
+			//System.out.println("grow nao 3");
+			double[][] newDoubleValues = new double[newNumC][newNumT];
+			for (int i=0; i<newNumC; i++)
+				for (int j=0; j<newNumT; j++) {
+					if (i<lengthC && j<lengthT)
+						newDoubleValues[i][j]=doubleValues[i][j];
+					else
+						newDoubleValues[i][j]=0;
+				}
+			doubleValues=newDoubleValues;
+		}
+		lengthC=newNumC;
+		lengthT=newNumT;
+	}
+	/*-------------------------------------STRINGS, NAMES ------------------------------------*/
+	/** Returns the i,jth element as a string */
+	public String toString(int i, int j) {
+		if (valueClass==INT)
+			return MesquiteInteger.toString(intValues[i][j]);// + " (int)";
+		else if (valueClass == LONG)
+			return MesquiteLong.toString(longValues[i][j]);// + " (long)";
+		else if (valueClass == DOUBLE)
+			return MesquiteDouble.toString(doubleValues[i][j]);// + " (double)";
+		else return "";
+	}
+	/*...........................................................*/
+	/** Returns the entire array as a string, with tabs between elements */
+	public String toString() {
+		String s = "";
+		if (valueClass==INT) {
+			for (int i=0; i<lengthC; i++) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteInteger.toString(intValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<lengthC; i++) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteLong.toString(longValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<lengthC; i++) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteDouble.toString(doubleValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		return s;
+	}
+	/*...........................................................*/
+	/** Returns the upper left corner (up to numC, numT) of the matrix as a string. */
+	public String partToString(int numC, int numT) {
+		String s = "";
+		if (numC>lengthC)
+			numC = lengthC;
+		if (numT>lengthT)
+			numT = lengthT;
+		if (valueClass==INT) {
+			for (int i=0; i<numC; i++) {
+				for (int j=0; j<numT; j++)
+					s+= MesquiteInteger.toString(intValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<numC; i++) {
+				for (int j=0; j<numT; j++)
+					s+= MesquiteLong.toString(longValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<numC; i++) {
+				for (int j=0; j<numT; j++)
+					s+= MesquiteDouble.toString(doubleValues[i][j]) + "\t";
+				s += "\n";
+			}
+		}
+		return s;
+	}
+	/*...........................................................*/
+	/** Returns a string indicating values along a single column */
+	public String toString2nd(int i) {
+		if (!legalIndices(i, 0))
+			return "";
+		String s = "";
+		if (valueClass==INT) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteInteger.toString(intValues[i][j]) + "\t";
+		}
+		else if (valueClass == LONG) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteLong.toString(longValues[i][j]) + "\t";
+		}
+		else if (valueClass == DOUBLE) {
+				for (int j=0; j<lengthT; j++)
+					s+= MesquiteDouble.toString(doubleValues[i][j]) + "\t";
+		}
+		return s;
+	}
+	/*...........................................................*/
+	/** Sets the name reference for the array */
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	/** Gets the name reference for the array */
+	public NameReference getNameReference(){
+		return name;
+	}
+}
+
diff --git a/Source/mesquite/lib/NumberArray.java b/Source/mesquite/lib/NumberArray.java
new file mode 100644
index 0000000..f7169b2
--- /dev/null
+++ b/Source/mesquite/lib/NumberArray.java
@@ -0,0 +1,1137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+/*Last documented:  August 1999 */
+
+/* ======================================================================== */
+/**This class is used to store numbers flexibly, so that system doesn't need to know whether int, long or double.
+Automatically upgrades to use long or double as needed.
+This stores a whole array of similarly typed numbers.  For single numbers, use NumberObjects instead.*/
+public class NumberArray {
+	public int[] intValues;
+	public long[] longValues;
+	public double[] doubleValues;
+	public static final int INT = 0;
+	public static final int LONG = 1;
+	public static final int DOUBLE = 2;
+	public int valueClass = INT;
+	private int length = 0;  // the size of the array
+	private NameReference name;
+
+	public NumberArray() {
+	}
+	public NumberArray(int length) {
+		intValues = new int[length];
+		this.length=length;
+		for (int i=0; i<length; i++)
+			intValues[i]=0;
+		this.valueClass = 0;
+	}
+	/*...........................................................*/
+	public NumberArray(int length, int valueClass) {
+		this.length=length;
+		if (valueClass==INT) {
+			intValues = new int[length];
+			for (int i=0; i<length; i++)
+				intValues[i]=0;
+		}
+		else if (valueClass == LONG) {
+			longValues = new long[length];
+			for (int i=0; i<length; i++)
+				longValues[i]=0;
+		}
+		else if (valueClass == DOUBLE) {
+			doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=0;
+		}
+		this.valueClass = valueClass;
+	}
+	/*...........................................................*/
+	public NumberArray(double[] values) {
+		if (values==null)
+			length=0;
+		else 
+			length=values.length;
+		valueClass = DOUBLE;
+		doubleValues = new double[length];
+		for (int i=0; i<length; i++)
+			doubleValues[i]=values[i];
+
+	}
+	public int getValueClass(){
+		return valueClass;
+	}
+	/*...........................................................*/
+	public void switchToDoubles(){
+		if (valueClass==INT) {
+			doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=intValues[i]*1.0;
+		}
+		else if (valueClass == LONG) {
+			doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=longValues[i]*1.0;
+		}
+		valueClass= DOUBLE;
+	}
+	/*...........................................................*/
+	public NumberArray cloneArray(){
+		NumberArray c = new NumberArray();
+		c.length = length;
+		if (valueClass==INT) {
+			c.intValues = new int[length];
+			for (int i=0; i<length; i++)
+				c.intValues[i]=intValues[i];
+		}
+		else if (valueClass == LONG) {
+			c.longValues = new long[length];
+			for (int i=0; i<length; i++)
+				c.longValues[i]=longValues[i];
+		}
+		else if (valueClass == DOUBLE) {
+			c.doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				c.doubleValues[i]=doubleValues[i];
+		}
+		c.valueClass = valueClass;
+		c.name = name;
+		return c;
+	}
+	/*...........................................................*/
+	/** Sets this array to be a clone of the passed array*/
+	public void setToClone(NumberArray a){
+		if (a == null)
+			return;
+		if (a.length != length || a.valueClass != valueClass){
+			if (a.valueClass==INT) {
+				intValues = new int[a.length];
+			}
+			else if (a.valueClass == LONG) {
+				longValues = new long[a.length];
+			}
+			else if (a.valueClass == DOUBLE) {
+				doubleValues = new double[a.length];
+			}
+			length = a.length;
+			valueClass = a.valueClass;
+		}
+		if (valueClass==INT) {
+			for (int i=0; i<length; i++)
+				intValues[i]=a.intValues[i];
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<length; i++)
+				longValues[i]=a.longValues[i];
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<length; i++)
+				doubleValues[i]=a.doubleValues[i];
+		}
+		name = a.name;
+	}
+	/*...........................................................*/
+	public boolean legalIndex(int i){
+		return (i>=0 && i<length);
+	}
+	/*--------------------------------GET/SET-----------------------------*/
+	/*...........................................................*/
+	/** Returns int value at index. */
+	public int getInt(int index) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.printStackTrace("NumberArray index out of bounds (a1) " + index + "  max: " + length);
+			//MesquiteMessage.warnProgrammer("NumberArray index out of bounds (a1) " + index + "  max: " + length);
+		}
+		else  {
+			if (valueClass==INT)
+				return getI(index);
+			else if (valueClass == LONG)
+				return (int)getL(index);
+			else if (valueClass == DOUBLE)
+				return (int)getD(index);
+		}
+		return MesquiteInteger.unassigned;
+	}
+	/*...........................................................*/
+	/** Returns long value at index. */
+	public long getLong(int index) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (a2) " + index + "  max: " + length);
+		}
+		else  {
+			if (valueClass==INT)
+				return getI(index);
+			else if (valueClass == LONG)
+				return getL(index);
+			else if (valueClass == DOUBLE)
+				return (long)getD(index);
+		}
+		return MesquiteLong.unassigned;
+	}
+	/*...........................................................*/
+	/** Returns double value at index. */
+	public double getDouble(int index) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (a3) " + index + "  max: " + length);
+		}
+		else  {
+			if (valueClass==INT)
+				return getI(index);
+			else if (valueClass == LONG)
+				return getL(index);
+			else if (valueClass == DOUBLE)
+				return getD(index);
+		}
+		return MesquiteDouble.unassigned;
+	}
+	//these protect against NPE's but give warning; special use; only in connection to above methods
+	private double getD(int index){
+		if (doubleValues == null){
+			MesquiteMessage.printStackTrace("mistaken value class in Number Array " + valueClass);
+			return MesquiteDouble.unassigned;
+		}
+		return doubleValues[index];
+		}
+	private long getL(int index){
+		if (longValues == null){
+			MesquiteMessage.printStackTrace("mistaken value class in Number Array " + valueClass);
+			return MesquiteLong.unassigned;
+		}
+		return longValues[index];
+	}
+	private int getI(int index){
+		if (intValues == null){
+			MesquiteMessage.printStackTrace("mistaken value class in Number Array " + valueClass);
+			return MesquiteInteger.unassigned;
+		}
+		return intValues[index];
+	}
+	/*...........................................................*/
+	/** Returns average value of doubles. */
+	public double getDoubleAverage() {
+		double value;
+		double count = 0;
+		double total = 0.0;
+		for (int i=0; i<length; i++) {
+			value = getDouble(i);
+			if (MesquiteDouble.isCombinable(value)){
+				count++;
+				total += value;
+			}		
+		}
+		if (count==0)
+			return MesquiteDouble.unassigned;
+		return total/count;
+	}
+	/*...........................................................*/
+	/** Places the value at array element "index" into
+	the MesquiteNumber n.  Used instead of a simple getValue to avoid having to create
+	a MesquiteNumber object. */
+	public void placeValue(int index, MesquiteNumber n) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.printStackTrace("NumberArray index out of bounds (a4) " + index + "  max: " + length);
+			return;
+		}
+		if (n!=null) {
+			if (valueClass==INT)
+				n.setValue(intValues[index]);
+			else if (valueClass == LONG)
+				n.setValue(longValues[index]);
+			else if (valueClass == DOUBLE)
+				n.setValue(doubleValues[index]);
+		}
+	}
+	/*...........................................................*/
+	/** Sets value of element "index" to the passed value */
+	public void setValue(int index, int v) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (b) " + index + "  max: " + length);
+			return;
+		}
+
+		if (valueClass==INT)
+			intValues[index] = v;
+		else if (valueClass == LONG)
+			longValues[index] = MesquiteLong.toLong(v);
+		else if (valueClass == DOUBLE)
+			doubleValues[index]=MesquiteDouble.toDouble(v);
+	}
+
+	/** Sets value of element "index" to the passed value */
+	public void setValue(int index, long v) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (c) " + index + "  max: " + length);
+			return;
+		}
+		if (valueClass==INT) {
+			longValues = new long[length];
+			for (int i=0; i<length; i++) {
+				longValues[i]=MesquiteLong.toLong(intValues[i]);
+			}
+			longValues[index] = v;
+			intValues=null;
+			valueClass=LONG;
+		}
+		else if (valueClass == LONG)
+			longValues[index] = v;
+		else if (valueClass == DOUBLE)
+			doubleValues[index]=MesquiteDouble.toDouble(v);
+	}
+
+	/** Sets value of element "index" to the passed value */
+	public void setValue(int index, double v) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (d) " + index + "  max: " + length);
+			return;
+		}
+		if (valueClass==INT) {
+			doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=MesquiteDouble.toDouble(intValues[i]);
+			doubleValues[index] = v;
+			intValues=null;
+			valueClass=DOUBLE;
+		}
+		else if (valueClass == LONG) {
+			doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=MesquiteDouble.toDouble(longValues[i]);
+			doubleValues[index] = v;
+			longValues=null;
+			valueClass=DOUBLE;
+		}
+		else if (valueClass == DOUBLE)
+			doubleValues[index]=v;
+	}
+
+	/** Sets value of element "index" to the passed value */
+	public void setValue(int index, MesquiteNumber v) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.printStackTrace("NumberArray index out of bounds (e) " + index + "  max: " + length);
+			return;
+		}
+		if (v==null)
+			return;
+		if (v.isUnassigned())
+			setToUnassigned(index);
+		else if (v.isInfinite())
+			setToInfinite(index);
+		else if (v.getValueClass()==INT)
+			setValue(index, v.getIntValue());
+		else if (v.getValueClass() == LONG)
+			setValue(index, v.getLongValue());
+		else if (v.getValueClass() == DOUBLE)
+			setValue(index, v.getDoubleValue());
+	}
+	/** Sets value of the next open (unassigned) element to the passed value */
+	private int findOpenValue() {
+		if (valueClass==INT) {
+			for (int i=0; i<length; i++)
+				if (MesquiteInteger.isUnassigned(intValues[i]))
+					return i;
+		}
+		else if (valueClass == LONG){
+			for (int i=0; i<length; i++)
+				if (MesquiteLong.isUnassigned(longValues[i]))
+					return i;
+		}
+		else if (valueClass == DOUBLE){
+			for (int i=0; i<length; i++)
+				if (MesquiteDouble.isUnassigned(doubleValues[i]))
+					return i;
+		}
+		return -1;
+	}
+	/** Sets value of the next open (unassigned) element to the passed value */
+	public void setOpenValue(MesquiteNumber v) {
+		if (v == null || v.isUnassigned())
+			return;
+		int index = findOpenValue();
+		if (index<0)
+			return;
+		if (v.isInfinite())
+			setToInfinite(index);
+		else if (v.getValueClass()==INT)
+			setValue(index, v.getIntValue());
+		else if (v.getValueClass() == LONG)
+			setValue(index, v.getLongValue());
+		else if (v.getValueClass() == DOUBLE)
+			setValue(index, v.getDoubleValue());
+	}
+	/*...........................................................*/
+	/** Sets value of element "index" to the passed value */
+	public void setValues(double[] values) {
+		if (values==null)
+			deassignArray();
+		else {
+			valueClass = DOUBLE;
+			length=values.length;
+			if (doubleValues==null || doubleValues.length !=length)
+				doubleValues = new double[length];
+			for (int i=0; i<length; i++)
+				doubleValues[i]=values[i];
+		}
+	}
+	/*...........................................................*/
+	/** Sets value of element "index" to unassigned */
+	public void setToUnassigned(int index) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (f) " + index + "  max: " + length);
+			return;
+		}
+		if (valueClass==INT)
+			intValues[index]= MesquiteInteger.unassigned;
+		else if (valueClass == LONG)
+			longValues[index]= MesquiteLong.unassigned;
+		else if (valueClass == DOUBLE)
+			doubleValues[index]= MesquiteDouble.unassigned;
+	}
+	/*...........................................................*/
+	/** Sets value of element "index" to the infinite */
+	public void setToInfinite(int index) {
+		if (!legalIndex(index)) {
+			MesquiteMessage.warnProgrammer("NumberArray index out of bounds (g) " + index + "  max: " + length);
+			return;
+		}
+		if (valueClass==INT)
+			intValues[index]= MesquiteInteger.infinite;
+		else if (valueClass == LONG)
+			longValues[index]= MesquiteLong.infinite;
+		else if (valueClass == DOUBLE)
+			doubleValues[index]= MesquiteDouble.infinite;
+	}
+	/*...........................................................*/
+	/** Swaps the values at i and j*/
+	public void swapValues(int i, int j) {
+		if (!legalIndex(i) && !legalIndex(j)) 
+			return;
+		if (valueClass==INT) {
+			int q = intValues[i];
+			intValues[i] = intValues[j];
+			intValues[j] = q;
+		}
+		else if (valueClass == LONG) {
+			long q = longValues[i];
+			longValues[i] = longValues[j];
+			longValues[j] = q;
+		}
+		else if (valueClass == DOUBLE) {
+			double q = doubleValues[i];
+			doubleValues[i] = doubleValues[j];
+			doubleValues[j] = q;
+		}
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void deassignArrayToInteger() {
+		valueClass = INT;
+		if (intValues== null || intValues.length!=length)
+			intValues = new int[length];
+		for (int i=0; i<intValues.length; i++)
+			intValues[i]=MesquiteInteger.unassigned;
+		longValues = null; //TODO: would be better to leave arrays around so as not to have them comjing and going
+		doubleValues = null;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void zeroArray() {
+		if (valueClass==INT) {
+			for (int i=0; i<length; i++)
+				intValues[i]=0;
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<length; i++)
+				longValues[i]=0L;
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<length; i++)
+				doubleValues[i]=0.0;
+		}
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void deassignArray() {
+		if (valueClass==INT) {
+			for (int i=0; i<length; i++)
+				intValues[i]=MesquiteInteger.unassigned;
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<length; i++)
+				longValues[i]=MesquiteLong.unassigned;
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<length; i++)
+				doubleValues[i]=MesquiteDouble.unassigned;
+		}
+	}
+	/*...........................................................*/
+	/** this method calculates the minimum value in the objects array from 
+	elements 0 through numToCheck-1, and places the minimum in the MesquiteNumber r */
+	public void placeMinimumValue(MesquiteNumber r, int numToCheck) {
+		if (r!=null) {
+			if (valueClass==INT) {
+				if (intValues.length==0)
+					return;
+				int min = intValues[0];
+				for (int i=0; i<numToCheck; i++)
+					min=MesquiteInteger.minimum(min, intValues[i]);
+				r.setValue(min);
+			}
+			else if (valueClass == LONG) {
+				if (longValues.length==0)
+					return;
+				long min = longValues[0];
+				for (int i=0; i<numToCheck; i++)
+					min = MesquiteLong.minimum(min, longValues[i]);
+				r.setValue(min);
+			}
+			else if (valueClass == DOUBLE) {
+				if (doubleValues.length==0)
+					return;
+				double min = doubleValues[0];
+				for (int i=0; i<numToCheck; i++)
+					min = MesquiteDouble.minimum(min,doubleValues[i]);
+				r.setValue(min);
+			}
+		}
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void placeMinimumValue(MesquiteNumber r) {
+		placeMinimumValue(r, length);
+	}
+	/*...........................................................*/
+	/** this method calculates the maximum value in the objects array from 
+	elements 0 through numToCheck-1, and places the maximum in the MesquiteNumber r */
+	public void placeMaximumValue(MesquiteNumber r, int numToCheck) {
+		if (r!=null) {
+			if (valueClass==INT) {
+				if (intValues.length==0)
+					return;
+				int max = intValues[0];
+				for (int i=0; i<numToCheck; i++)
+					max = MesquiteInteger.maximum(max, intValues[i]);
+				r.setValue(max);
+			}
+			else if (valueClass == LONG) {
+				if (longValues.length==0)
+					return;
+				long max = longValues[0];
+				for (int i=0; i<numToCheck; i++)
+					max = MesquiteLong.maximum(max, longValues[i]);
+				r.setValue(max);
+			}
+			else if (valueClass == DOUBLE) {
+				if (doubleValues.length==0)
+					return;
+				double max = doubleValues[0];
+				for (int i=0; i<numToCheck; i++)
+					max = MesquiteDouble.maximum(max, doubleValues[i]);
+				r.setValue(max);
+			}
+		}
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void placeMaximumValue(MesquiteNumber r) {
+		placeMaximumValue(r, length);
+	}
+	/*--------------------------------------QUERY-----------------------------------*/
+	/** DOCUMENT */
+	public boolean isZero(int i) {
+		if (!legalIndex(i))
+			return false;
+		if (valueClass==INT) {
+			if (intValues !=null)
+				return intValues[i]==0;
+		}
+		else if (valueClass == LONG) {
+			if (longValues !=null)
+				return longValues[i]==0;
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValues !=null)
+				return doubleValues[i]==0;
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public boolean isCombinable(int i) {
+		if (!legalIndex(i))
+			return false;
+		if (valueClass==INT) {
+			if (intValues !=null)
+				return MesquiteInteger.isCombinable(intValues[i]);
+		}
+		else if (valueClass == LONG) {
+			if (longValues !=null)
+				return MesquiteLong.isCombinable(longValues[i]);
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValues !=null)
+				return MesquiteDouble.isCombinable(doubleValues[i]);
+		}
+		return true;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public boolean isUnassigned(int i) {
+		if (!legalIndex(i))
+			return false;
+		if (valueClass==INT) {
+			if (intValues !=null)
+				return intValues[i]==MesquiteInteger.unassigned;
+		}
+		else if (valueClass == LONG) {
+			if (longValues !=null)
+				return longValues[i]==MesquiteLong.unassigned;
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValues !=null)
+				return doubleValues[i]== MesquiteDouble.unassigned;
+		}
+		return true;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public boolean isInfinite(int i) {
+		if (!legalIndex(i))
+			return false;
+		if (valueClass==INT) {
+			if (intValues !=null)
+				return intValues[i]==MesquiteInteger.infinite;
+		}
+		else if (valueClass == LONG) {
+			if (longValues !=null)
+				return longValues[i]==MesquiteLong.infinite;
+		}
+		else if (valueClass == DOUBLE) {
+			if (doubleValues !=null)
+				return doubleValues[i]== MesquiteDouble.infinite;
+		}
+		return false;
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Multiplies the element "index" by the value in the passed MesquiteNumber*/
+	public void multiplyBy(int index, MesquiteNumber n) {
+		if (!legalIndex(index))
+			return;
+		if (n!=null) {
+			if (valueClass==INT)
+				intValues[index] = intValues[index]*n.getIntValue();
+			else if (valueClass == LONG)
+				longValues[index] = longValues[index]*n.getLongValue();
+			else if (valueClass == DOUBLE)
+				doubleValues[index] = doubleValues[index]*n.getDoubleValue();
+		}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Divides all by the value in the passed MesquiteNumber*/
+	public void multiplyAllBy(MesquiteNumber n) {
+		for (int i = 1; i < length; i++) {
+				multiplyBy(i,n);
+		}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Divide the element "index" by the value in the passed MesquiteNumber*/
+	public void divideBy(int index, MesquiteNumber n) {
+		if (!legalIndex(index))
+			return;
+		if (n!=null) {
+			if (valueClass==INT)
+				intValues[index] = intValues[index]/n.getIntValue();
+			else if (valueClass == LONG)
+				longValues[index] = longValues[index]/n.getLongValue();
+			else if (valueClass == DOUBLE)
+				doubleValues[index] = doubleValues[index]/n.getDoubleValue();
+		}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Divides all by the value in the passed MesquiteNumber*/
+	public void divideAllBy(MesquiteNumber n) {
+		for (int i = 1; i < length; i++) {
+				divideBy(i,n);
+		}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Add the value in the passed MesquiteNumber to that of element "index".  
+	NOTE: the sum will be returned in the MesquiteNumber passed!*/
+	public void addValue(int index, MesquiteNumber n) {
+		if (!legalIndex(index))
+			return;
+		if (n!=null) {
+			if (valueClass==INT)
+				n.add(intValues[index]);
+			else if (valueClass == LONG)
+				n.add(longValues[index]);
+			else if (valueClass == DOUBLE)
+				n.add(doubleValues[index]);
+			setValue(index, n);
+		}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Add the values in the passed numberArray to the equivalent elements of this array */
+	public void addArray(NumberArray otherArray) {
+		if (length!=otherArray.length)
+			return;
+		for (int index = 1; index < length; index++) {
+				if (valueClass==INT)
+					intValues[index] += otherArray.getInt(index);
+				else if (valueClass == LONG)
+					longValues[index] += otherArray.getLong(index);
+				else if (valueClass == DOUBLE)
+					doubleValues[index] += otherArray.getDouble(index);
+			}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Add the values in the passed numberArray to the equivalent elements of this array */
+	public void subtractArray(NumberArray otherArray) {
+		if (length!=otherArray.length)
+			return;
+		for (int index = 1; index < length; index++) {
+				if (valueClass==INT)
+					intValues[index] -= otherArray.getInt(index);
+				else if (valueClass == LONG)
+					longValues[index] -= otherArray.getLong(index);
+				else if (valueClass == DOUBLE)
+					doubleValues[index] -= otherArray.getDouble(index);
+			}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Squares the values */
+	public void squareValues() {
+		for (int index = 1; index < length; index++) {
+				if (valueClass==INT)
+					intValues[index] *= intValues[index];
+				else if (valueClass == LONG)
+					longValues[index] *= longValues[index];
+				else if (valueClass == DOUBLE)
+					doubleValues[index] *= doubleValues[index];
+			}
+	}
+	/*--------------------------------ARITHMETRIC, COMPARISON-----------------------------*/
+	/**Takes the square root of the values */
+	public void squareRootValues() {
+		if (valueClass!=DOUBLE)
+			switchToDoubles();
+		for (int index = 1; index < length; index++) {
+				doubleValues[index] = Math.sqrt(doubleValues[index]);
+			}
+	}
+	/*...........................................................*/
+	/** Sorts values from highest to lowest; uncombinable put at end*/
+	public void sortDown () {
+		for (int i = 1; i < length; i++) {
+			for (int j= i-1; j>=0 && firstIsGreaterUC(j+1,j); j--) {
+				swapValues(j,j+1);
+			}
+		}
+	}
+	/*...........................................................*/
+	/** Sorts values from lowest to highest; uncombinable put at end*/
+	public void sortUp () {
+		for (int i = 1; i < length; i++) {
+			for (int j= i-1; j>=0 && firstIsGreater(j,j+1); j--) {
+				swapValues(j,j+1);
+			}
+		}
+	}
+	/*...........................................................*/
+	/** Sorts values from lowest to highest AND places medians in passed numbers*/
+	public void sortAndPlaceMedian(MesquiteNumber med1, MesquiteNumber med2){
+		if (med1 == null || med2 == null)
+			return;
+		sortUp();
+		int numValid = 0;
+		med1.setToUnassigned();
+		med2.setToUnassigned();
+		if (valueClass==INT) {
+			for (int i = 0; i< intValues.length && MesquiteInteger.isCombinable(intValues[i]); i++)
+				numValid++;
+			int count = 0;
+			int target = numValid/2; 
+			if (target * 2 ==numValid) //even; subtract one
+				target--;
+			int first = 0;
+			int second  = 0;
+			for (int i = 0; i< intValues.length && count<= target+1; i++) {
+				if (MesquiteInteger.isCombinable(intValues[i])){
+					if (count == target)
+						first = intValues[i];
+					else	if (count == target + 1)
+						second = intValues[i];
+					count++;
+				}
+			}
+			med1.setValue(first);
+			if (first !=second)
+				med2.setValue(second);
+		}
+		else if (valueClass == LONG) {
+			for (int i = 0; i< longValues.length && MesquiteLong.isCombinable(longValues[i]); i++)
+				numValid++;
+			int count = 0;
+			int target = numValid/2;
+			if (target * 2 ==numValid) //even; subtract one
+				target--;
+			long first = 0;
+			long second  = 0;
+			for (int i = 0; i< longValues.length && count<= target+1; i++) {
+				if (MesquiteLong.isCombinable(longValues[i])){
+					if (count == target)
+						first = longValues[i];
+					else	if (count == target + 1)
+						second = longValues[i];
+					count++;
+				}
+			}
+			med1.setValue(first);
+			if (first !=second)
+				med2.setValue(second);
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i = 0; i< doubleValues.length && MesquiteDouble.isCombinable(doubleValues[i]); i++)
+				numValid++;
+			int count = 0;
+			int target = numValid/2;
+			if (target * 2 ==numValid) //even; subtract one
+				target--;
+			double first = 0;
+			double second  = 0;
+			for (int i = 0; i< doubleValues.length && count<= target+1; i++) {
+				if (MesquiteDouble.isCombinable(doubleValues[i])){
+					if (count == target)
+						first = doubleValues[i];
+					else	if (count == target + 1)
+						second = doubleValues[i];
+					count++;
+				}
+			}
+			med1.setValue(first);
+			if (first !=second)
+				med2.setValue(second);
+		}
+		if (numValid / 2 * 2 != numValid)
+			med2.setToUnassigned();
+	}
+	/*...........................................................*/
+	/** returns true if the value at i is greater than that at j; all uncombinable treated as larger*/
+	public boolean firstIsGreater(int i, int j) {
+		if (!legalIndex(i) && !legalIndex(j)) 
+			return false;
+		if (valueClass==INT) {
+			return  (intValues[i] > intValues[j] || !MesquiteInteger.isCombinable(intValues[i])) && (MesquiteInteger.isCombinable(intValues[j]));
+		}
+		else if (valueClass == LONG) {
+			return (longValues[i] > longValues[j] || !MesquiteLong.isCombinable(longValues[i])) && (MesquiteLong.isCombinable(longValues[j]));
+		}
+		else if (valueClass == DOUBLE) {
+			return (doubleValues[i] > doubleValues[j] || !MesquiteDouble.isCombinable(doubleValues[i]))  && (MesquiteDouble.isCombinable(doubleValues[j]));
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** returns true if the value at i is greater than that at j; all uncombinable treated as smaller*/
+	public boolean firstIsGreaterUC(int i, int j) {
+		if (!legalIndex(i) && !legalIndex(j)) 
+			return false;
+		if (valueClass==INT) {
+			return  intValues[i] > intValues[j] || !MesquiteInteger.isCombinable(intValues[j]);
+		}
+		else if (valueClass == LONG) {
+			return longValues[i] > longValues[j]  || !MesquiteLong.isCombinable(longValues[j]);
+		}
+		else if (valueClass == DOUBLE) {
+			return doubleValues[i] > doubleValues[j] || !MesquiteDouble.isCombinable(doubleValues[j]);
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** returns true if the value at i is equal to that at j*/
+	public boolean equal(int i, int j) {
+		if (!legalIndex(i) && !legalIndex(j)) 
+			return false;
+		try {
+			if (valueClass==INT) {
+
+				return intValues[i] == intValues[j];
+			}
+			else if (valueClass == LONG) {
+				return longValues[i] == longValues[j];
+			}
+			else if (valueClass == DOUBLE) {
+				return doubleValues[i] == doubleValues[j];
+			}
+		}
+		catch (Exception e){
+		}
+		return false;
+	}
+	/*...........................................................*/
+	/** finds a number with value; returns -1 if not found */
+	public int findValue(MesquiteNumber n) {
+		if (n!=null) {
+			if (valueClass==INT) {
+				int v = n.getIntValue();
+				for (int index=0; index<length; index++)
+					if (v == intValues[index])
+						return index;
+			}
+			else if (valueClass == LONG) {
+				long v = n.getLongValue();
+				for (int index=0; index<length; index++)
+					if (v == longValues[index])
+						return index;
+			}
+			else if (valueClass == DOUBLE) {
+				double v = n.getDoubleValue();
+				for (int index=0; index<length; index++)
+					if (v == doubleValues[index])
+						return index;
+			}
+		}
+		return -1;
+	}
+	/*...........................................................*/
+	/** finds a number with value; returns -1 if not found */
+	public MesquiteNumber getTotal() {
+		MesquiteNumber mn = new MesquiteNumber(0);
+		if (valueClass==INT) {
+			int v = 0;
+			for (int index=0; index<length; index++) 
+				if (isCombinable(index))
+					v += intValues[index];
+			mn.setValue(v);
+		}
+		else if (valueClass == LONG) {
+			long v = 0;
+			for (int index=0; index<length; index++)
+				if (isCombinable(index))
+					v += longValues[index];
+			mn.setValue(v);
+		}
+		else if (valueClass == DOUBLE) {
+			double v = 0.0;
+			for (int index=0; index<length; index++) 
+				if (isCombinable(index))
+					v +=  doubleValues[index];
+			mn.setValue(v);
+		}
+		return mn;				
+	}
+	/*...........................................................*/
+	/** returns the MesquiteNumber at a particular index */
+	public MesquiteNumber getMesquiteNumber(int index) {
+		MesquiteNumber mn = new MesquiteNumber(0);
+		if (valueClass==INT) {
+			mn.setValue(intValues[index]);
+		}
+		else if (valueClass == LONG) {
+			mn.setValue(longValues[index]);
+		}
+		else if (valueClass == DOUBLE) {
+			mn.setValue(doubleValues[index]);
+		}
+		return mn;				
+	}
+	/*...........................................................*/
+	/** returns whether or not the value at index is equal to that in the passed MesquiteNumber */
+	public boolean equals(int index, MesquiteNumber n) {
+		if (!legalIndex(index)) 
+			return false;
+		if (n!=null) {
+			if (valueClass==INT) {
+				if (n.equals(intValues[index], true))
+					return true;
+			}
+			else if (valueClass == LONG) {
+				if (n.equals(longValues[index], true))
+					return true;
+			}
+			else if (valueClass == DOUBLE) {
+				if (n.equals(doubleValues[index], true))
+					return true;
+			}
+		}
+		return false;
+	}
+	/*--------------------------------------SIZE-----------------------------------*/
+	/** DOCUMENT */
+	public int getSize() {
+		return length;
+	}
+	/*...........................................................*/
+	/** this changes the array size */
+	public void resetSize(int newNum) {
+		if (newNum>length) {
+			if (valueClass==INT) {
+				//System.out.println("grow nao 1");
+				int[] newIntValues = new int[newNum];
+				for (int i=0; i<length; i++)
+					newIntValues[i]=intValues[i];
+				for (int i=length; i<newNum; i++)
+					newIntValues[i]=0;
+				intValues=newIntValues;
+			}
+			else if (valueClass == LONG) {
+				//System.out.println("grow nao 2");
+				long[] newLongValues = new long[newNum];
+				for (int i=0; i<length; i++)
+					newLongValues[i]=longValues[i];
+				for (int i=length; i<newNum; i++)
+					newLongValues[i]=0;
+				longValues=newLongValues;
+			}
+			else if (valueClass == DOUBLE) {
+				//System.out.println("grow nao 3");
+				double[] newDoubleValues = new double[newNum];
+				for (int i=0; i<length; i++)
+					newDoubleValues[i]=doubleValues[i];
+				for (int i=length; i<newNum; i++)
+					newDoubleValues[i]=0;
+				doubleValues=newDoubleValues;
+			}
+			length=newNum;
+		}
+		else if (newNum<length) {
+			if (valueClass==INT) {
+				//System.out.println("shrink nao 1");
+				int[] newIntValues = new int[newNum];
+				for (int i=0; i<newNum; i++)
+					newIntValues[i]=intValues[i];
+				intValues=newIntValues;
+			}
+			else if (valueClass == LONG) {
+				//System.out.println("shrink nao 2");
+				long[] newLongValues = new long[newNum];
+				for (int i=0; i<newNum; i++)
+					newLongValues[i]=longValues[i];
+				longValues=newLongValues;
+			}
+			else if (valueClass == DOUBLE) {
+				//System.out.println("shrink nao 3");
+				double[] newDoubleValues = new double[newNum];
+				for (int i=0; i<newNum; i++)
+					newDoubleValues[i]=doubleValues[i];
+				doubleValues=newDoubleValues;
+			}
+			length=newNum;
+		}
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num) {
+		if (num<=0)
+			return;
+		intValues = IntegerArray.addParts(intValues, starting, num);
+		doubleValues = DoubleArray.addParts(doubleValues, starting, num);
+		longValues = LongArray.addParts(longValues, starting, num, MesquiteLong.unassigned);
+		length += num;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0)
+			return;
+		intValues = IntegerArray.deleteParts(intValues, starting, num);
+		doubleValues = DoubleArray.deleteParts(doubleValues, starting, num);
+		longValues = LongArray.deleteParts(longValues, starting, num);
+		length -= num;
+	}
+	/*...........................................................*/
+	public void moveParts (int starting, int num, int justAfter){
+		if (num<=0)
+			return;
+		intValues = IntegerArray.moveParts(intValues, starting, num, justAfter);
+		doubleValues = DoubleArray.getMoveParts(doubleValues, starting, num, justAfter);
+		longValues = LongArray.getMoveParts(longValues, starting, num, justAfter);
+	}
+	/*...........................................................*/
+	public void swapParts (int first, int second){
+		if (first<0 || first>=length || second<0 || second>=length) 
+			return;
+		IntegerArray.swapParts(intValues, first, second);
+		DoubleArray.swapParts(doubleValues, first, second);
+		LongArray.swapParts(longValues, first, second);
+	}
+	/*...........................................................*/
+	public int getNumParts() {
+		return length;
+	}
+	/*--------------------------------------STRINGS, NAME----------------------------------*/
+	/** DOCUMENT */
+	public String toString(int index, int digits, boolean allowExponentialNotation) {
+		if (!legalIndex(index)) 
+			return MesquiteInteger.toString(MesquiteInteger.unassigned);
+		if (valueClass==INT) {
+			return MesquiteInteger.toString(intValues[index]);// + " (int)";
+		}
+		else if (valueClass == LONG) {
+			return MesquiteLong.toString(longValues[index]);// + " (long)";
+		}
+		else if (valueClass == DOUBLE) {
+			return MesquiteDouble.toStringDigitsSpecified(doubleValues[index], digits, allowExponentialNotation);// + " (double)";
+		}
+		else return "";
+	}
+	/** DOCUMENT */
+	public String toString(int index) {
+		if (!legalIndex(index)) 
+			return MesquiteInteger.toString(MesquiteInteger.unassigned);
+		if (valueClass==INT) {
+			return MesquiteInteger.toString(intValues[index]);// + " (int)";
+		}
+		else if (valueClass == LONG) {
+			return MesquiteLong.toString(longValues[index]);// + " (long)";
+		}
+		else if (valueClass == DOUBLE) {
+			return MesquiteDouble.toString(doubleValues[index]);// + " (double)";
+		}
+		else return "";
+	}
+	/** DOCUMENT */
+	public String toString() {
+		String s = "[ ";
+		if (valueClass==INT) {
+			for (int i=0; i<length; i++)
+				s += MesquiteInteger.toString(intValues[i]) + " ";
+		}
+		else if (valueClass == LONG) {
+			for (int i=0; i<length; i++)
+				s +=  MesquiteLong.toString(longValues[i]) + " ";
+		}
+		else if (valueClass == DOUBLE) {
+			for (int i=0; i<length; i++)
+				s +=  MesquiteDouble.toString(doubleValues[i]) + " ";
+		}
+		else return "";
+		s += "]";
+		return s;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	/** DOCUMENT */
+	public NameReference getNameReference(){
+		return name;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/OTUIDCodeInfoCoord.java b/Source/mesquite/lib/OTUIDCodeInfoCoord.java
new file mode 100644
index 0000000..bc6d118
--- /dev/null
+++ b/Source/mesquite/lib/OTUIDCodeInfoCoord.java
@@ -0,0 +1 @@
+/* Mesquite source code.  Copyright 2005 and onward David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */


package mesquite.lib; 




/* ======================================================================== */

public abstract class  OTUIDCodeInfoCoord extends MesquiteModule {
   	 public Class getDutyClass() {
   	 	return OTUIDCodeInfoCoord.class;
   	 }
 	public String getDutyName() {
 		return "Coordinator of Sources of OTU ID Code information";
   	 }

   	public abstract VoucherInfoFromOTUIDDB getVoucherInfo(String sourceID, String id);
	   	 
}


\ No newline at end of file
diff --git a/Source/mesquite/lib/OTUIDCodeInfoSource.java b/Source/mesquite/lib/OTUIDCodeInfoSource.java
new file mode 100644
index 0000000..71b6e31
--- /dev/null
+++ b/Source/mesquite/lib/OTUIDCodeInfoSource.java
@@ -0,0 +1 @@
+/* Mesquite source code.  Copyright 2005 and onward David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */

package mesquite.lib; 




/* ======================================================================== */

public abstract class  OTUIDCodeInfoSource extends MesquiteModule {
   	 public Class getDutyClass() {
   	 	return OTUIDCodeInfoSource.class;
   	 }
 	public String getDutyName() {
 		return "Source of OTU ID Code information";
   	 }

   	public abstract VoucherInfoFromOTUIDDB getVoucherInfo(String databaseID, String id);
   	public abstract boolean handlesDatabase(String databaseID);
	   	 
}


\ No newline at end of file
diff --git a/Source/mesquite/lib/Object2DArray.java b/Source/mesquite/lib/Object2DArray.java
new file mode 100644
index 0000000..a6db769
--- /dev/null
+++ b/Source/mesquite/lib/Object2DArray.java
@@ -0,0 +1,181 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+public class Object2DArray implements Listable {
+	Object[][] values;
+	NameReference name=null;
+	public Object2DArray(int numC, int numT){
+		values = new Object[numC][numT];
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	public void zeroArray(){
+		for (int i=0; i<values.length; i++)
+			if (values[i]!=null)
+				for (int j=0; j<values[i].length;j++)
+					values[i][j] =  null;
+	}
+	/*...........................................................*/
+	public void setValue(int column, int row, Object value) {
+		if (column >=0 && column < values.length && values[column]!=null && row>=0 && row<values[column].length)
+			values[column][row]= value;
+	}
+	public Object getValue(int column, int row){
+		if (column >=0 && column < values.length && values[column]!=null && row>=0 && row<values[column].length)
+			return values[column][row];
+		else
+			return null;
+	}
+	/*...........................................................*/
+	public Object[][] getMatrix() {
+		return values;
+	}
+	/*...........................................................*/
+	public void setMatrix(Object[][] m) {
+		values = m;
+	}
+	/*...........................................................*/
+	public static void moveColumns(Object[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		Object[][] newValues = new Object[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {   // (starting<=justAfter)
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public static void swapColumns(Object[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		Object[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void swapCell(Object[][] d, int first, int second, int k) {
+		if (k<0)
+			return;
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		if (d[first] == null || k>= d[first].length || d[second] == null || k>= d[second].length)
+			return;
+		Object temp = d[first][k];
+		d[first][k]=d[second][k];
+		d[second][k] = temp;
+	}
+	/*...........................................................*/
+	public static void moveRows(Object[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || d.length == 0)
+			return;
+		int numRows = d[0].length;
+		if (starting>=numRows || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=numRows)
+			justAfter = numRows-1;
+		if (justAfter<0)
+			justAfter = -1;
+		Object[] newValues = new Object[numRows];
+		for (int column = 0; column<d.length; column++){
+			if (starting>justAfter){
+				int count =0;
+				for (int i=0; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting+num; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			else {
+				int count =0;
+				for (int i=0; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting+num; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			for (int i=0; i<numRows; i++)
+				d[column][i]=newValues[i];
+		}
+	}
+	public static Object[][] addRows(Object[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		
+		for (int column = 0; column<d.length; column++){
+			d[column]=ObjectArray.addParts(d[column], starting, num);
+		}
+		return d;
+	}
+	public static Object[][] deleteRows(Object[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		for (int column = 0; column<d.length; column++){
+			d[column]=ObjectArray.deleteParts(d[column], starting, num);
+		}
+		return d;
+	}
+	/*...........................................................*/
+}
+
diff --git a/Source/mesquite/lib/ObjectArray.java b/Source/mesquite/lib/ObjectArray.java
new file mode 100644
index 0000000..9853288
--- /dev/null
+++ b/Source/mesquite/lib/ObjectArray.java
@@ -0,0 +1,222 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+public class ObjectArray implements Listable {
+	Object[] values;
+	NameReference name=null;
+	public ObjectArray(int num){
+		values = new Object[num];
+		for (int i=0; i<num; i++)
+			values[i] =  null;
+	}
+	//used for Associables that might need to record whether reference is to part or in between part
+	//intially for MesquiteTree to know if info applies to node or branch ancestral to node
+	boolean between = false;
+	public void setBetweenness(boolean b){
+		between = true;  
+	}
+	public boolean isBetween(){
+		return between;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	public void zeroArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  null;
+	}
+	/*...........................................................*/
+	public void copyTo(ObjectArray d){
+		if (d==null || d.values.length!=values.length)
+			return;
+		for (int i=0; i<values.length; i++) {
+			d.values[i] =  values[i];
+		}
+	}
+	public void setValue(int index, Object value) {
+		if (index >=0 && index < values.length)
+			values[index] = value;
+	}
+	public Object getValue(int index){
+		if (index <0 || index >= values.length)
+			return null;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public static int indexOf(Object[] values, Object match){
+		if (values==null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public int indexOf(Object match){
+		if (values==null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public int getSize() {
+		return values.length;
+	}
+	/*...........................................................*/
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		Object[] newValues = new Object[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newValues[i]=values[i];
+		if (newNum>getSize())
+			for (int i=getSize(); i<newNum; i++)
+				newValues[i]=null;
+		values=newValues;
+	}
+	/*...........................................................*/
+	public boolean addParts(int starting, int num){
+		if (num<=0)
+			return false;
+		values = addParts(values, starting, num);
+		return true;
+	}
+	/*...........................................................*/
+	public boolean deleteParts(int starting, int num){
+
+		if (num==0)
+			return false;
+		if (starting>values.length || starting<0) 
+			return false;
+		values = deleteParts(values, starting, num);
+		return true;
+	}
+	/*...........................................................*/
+	public static Object[] addParts(Object[] values, int starting, int num){
+		if (num<=0 || values == null)
+			return values;
+		if (starting<0) 
+			starting = -1;
+		if (starting>values.length) 
+			starting = values.length-1;
+		int newNumParts = values.length+num;
+		Object[] newValues = new Object[newNumParts];
+		for (int i=0; i<= starting; i++) {
+			newValues[i] = values[i];
+		}
+		for (int i=0; i<num ; i++) {
+			newValues[starting + i + 1] = null;
+		}
+		for (int i=0; i<values.length-starting-1; i++) {
+			newValues[i +starting+num+1] = values[starting + i+1];
+		}
+		return newValues;
+	}
+	/*...........................................................*/
+	public static Object[] deleteParts(Object[] values, int starting, int num){
+		if (num<=0 || values == null)
+			return values;
+		if (num+starting>values.length)
+			num = values.length-starting;
+		int newNumParts = values.length-num;
+		Object[] newValues = new Object[newNumParts];
+		
+		for (int i=0; i<starting; i++) {
+			newValues[i] = values[i];
+		}
+		for (int i=starting+num; i<values.length; i++) {
+			newValues[i-num ] = values[i];
+		}
+		return newValues;
+	}
+	/*...........................................................*/
+	public static void swapParts(Object[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		Object temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public boolean swapParts(int first, int second) {
+		if (first<0 || first>=values.length || second<0 || second>=values.length) 
+			return false;
+		Object temp = values[first];
+		values[first] = values[second];
+		values[second] = temp;
+		return true;
+	}
+	/*...........................................................*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>values.length)
+			return false;
+
+		Object[] newValues = new Object [values.length];
+		
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=values[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=values[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=values[i];
+			for (int i=starting+num; i<values.length; i++)
+				newValues[count++]=values[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=values[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=values[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=values[i];
+			for (int i=justAfter+1; i<values.length; i++)
+				newValues[count++]=values[i];
+		}
+		for (int i=0; i<values.length; i++)
+			values[i]=newValues[i];
+		return true;
+	}
+	/*...........................................................*/
+}
+
diff --git a/Source/mesquite/lib/ObjectContainer.java b/Source/mesquite/lib/ObjectContainer.java
new file mode 100644
index 0000000..35174ca
--- /dev/null
+++ b/Source/mesquite/lib/ObjectContainer.java
@@ -0,0 +1,56 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+/**An object that holds a reference to another object; to pass as argument into method and have filled in response*/
+public class ObjectContainer implements Listable {
+	Object object;
+	static int totalCreated = 0;
+	String name = null;
+	public ObjectContainer() {
+ 		totalCreated++;
+	}
+	public ObjectContainer(Object o) {
+ 		totalCreated++;
+ 		object = o;
+	}
+	public ObjectContainer(String name, Object o) {
+ 		totalCreated++;
+ 		object = o;
+ 		this.name = name;
+	}
+	public int getID() {
+		return totalCreated;
+	}
+ 	public Object getObject(){
+ 		return object;
+ 	}
+ 	public void setObject(Object o){
+ 		object = o;
+ 	}
+ 	public void setName(String name){
+ 		this.name = name;
+ 	}
+ 	public String getName(){
+ 		if (name == null && object != null && object instanceof Listable)
+ 			return ((Listable)object).getName();
+ 		return name;
+ 	}
+}
+
diff --git a/Source/mesquite/lib/ObjectSpecsSet.java b/Source/mesquite/lib/ObjectSpecsSet.java
new file mode 100644
index 0000000..e818787
--- /dev/null
+++ b/Source/mesquite/lib/ObjectSpecsSet.java
@@ -0,0 +1,208 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.characters.CharacterModel;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+/* ======================================================================== */
+/** DOCUMENT.*/
+public abstract class ObjectSpecsSet  extends SpecsSet {
+	Object[] properties;
+	Object defaultProperty;
+	public ObjectSpecsSet (String name, int numParts, Object defaultProperty) {
+		super(name, numParts);
+		this.defaultProperty = defaultProperty;
+		properties = getNewPropertyStorage(numParts);
+		for (int i=0; i<numParts; i++) {
+			properties[i] = defaultProperty;
+		}
+	}
+
+	public String toString(int ic){
+		return "" + getProperty(ic);
+	}
+	/*.................................................................................................................*/
+	/** Sets model of character*/
+	public void setProperty(Object property, int index) {
+		setDirty(true);
+		if (index<0)
+			System.out.println("Error: attempt to set object of part-- " + index + " " + this);
+		else if (index>=properties.length)
+			System.out.println("Error: attempt to set object of part- " + index + " " + this);
+		else
+			properties[index]=property;
+	}
+	/*.................................................................................................................*/
+	/** Sets the value for part "part" to be the same as that at part "otherPart" in the incoming specsSet*/
+	public void equalizeSpecs(SpecsSet other, int otherPart, int part){
+		if (other instanceof ObjectSpecsSet){
+			setProperty(((ObjectSpecsSet)other).getProperty(otherPart), part);
+		}
+	}
+	/*.................................................................................................................*/
+	/** return array of character properties (can also get indivitually using getProperty)*/
+	public Object[] getProperties() {
+		return properties;
+	}
+	/*.................................................................................................................*/
+	/** returns property for specified character*/
+	public Object getProperty(int index) {
+		if (index>= 0 && index< properties.length)
+			return properties[index];
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Gets default property specified for PropertySet*/
+	public Object getDefaultProperty() {
+		return defaultProperty;
+	}
+	/*.................................................................................................................*/
+	/** sets default property*/
+	public void setDefaultProperty(Object defaultProperty) {
+		setDirty(true);
+		this.defaultProperty = defaultProperty;
+	}
+	/*.................................................................................................................*/
+	/** Gets default model specified for ModelSet*/
+	public Object getDefaultProperty(int ic) {
+		return getDefaultProperty();
+	}
+	/*.................................................................................................................*/
+	/** gets storage for set of properties*/
+	public abstract Object[] getNewPropertyStorage(int numParts);
+	/*.................................................................................................................*/
+	/** Add num characters just after "starting" (filling with default values)  */
+	public boolean addParts(int starting, int num){  
+		if (num <=0)
+			return false;
+		if (getProject() != null && getProject().isDoomed)
+			return false;
+		setDirty(true);
+		if (properties == null || properties.length==0){
+			properties = getNewPropertyStorage(num);
+			for (int i=0; i<num; i++) 
+				properties[i] = getDefaultProperty(0);
+			numParts = num;
+		}
+		else {
+			if (starting<0)
+				starting = -1;
+			else if (starting>=getNumberOfParts())
+				starting = getNumberOfParts()-1;
+			int newNumParts = getNumberOfParts() + num;
+			Object[] newProperties = getNewPropertyStorage(newNumParts);
+			for (int i=0; i<=starting; i++) {
+				newProperties[i] = properties[i];
+			}
+			for (int i=0; i<num; i++) {
+				newProperties[starting + i + 1] = getDefaultProperty(starting);
+			}
+			for (int i=0; i<properties.length-starting-1; i++) {
+				newProperties[i +starting+num+1] = properties[starting + i+1];
+			}
+
+			properties = newProperties;
+			numParts = newNumParts;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Delete num characters from and including "starting"  */
+	public boolean deleteParts(int starting, int num){  
+		if (num<=0 || starting<0 || starting>=getNumberOfParts())
+			return false;
+		setDirty(true);
+		if (num+starting>getNumberOfParts())
+			num = getNumberOfParts()-starting;
+		int newNumParts = getNumberOfParts() - num;
+		Object[] newProperties = getNewPropertyStorage(newNumParts);
+		for (int i=0; i<starting; i++) {
+			newProperties[i] = properties[i];
+		}
+		for (int i=starting+num; i<properties.length; i++) {
+			newProperties[i-num ] = properties[i];
+		}
+		properties = newProperties;
+		numParts = newNumParts;
+		return true;
+	}
+	/*...........................................................*/
+	public boolean swapParts( int first, int second) {
+		if (first<0 || first>=properties.length || second<0 || second>=properties.length) 
+			return false;
+		setDirty(true);
+		Object temp = properties[first];
+		properties[first] = properties[second];
+		properties[second] = temp;
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** */
+	public boolean moveParts(int starting, int num, int justAfter){  
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>getNumberOfParts())
+			return false;
+		setDirty(true);
+		Object[] newValues = getNewPropertyStorage(getNumberOfParts());
+
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=properties[i];
+
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=properties[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=properties[i];
+			for (int i=starting+num; i<properties.length; i++)
+				newValues[count++]=properties[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=properties[i];
+
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=properties[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=properties[i];
+			for (int i=justAfter+1; i<properties.length; i++)
+				newValues[count++]=properties[i];
+		}
+		for (int i=0; i<properties.length; i++)
+			properties[i]=newValues[i];
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+
+		for (int i=0; i<properties.length; i++) {
+			if (properties[i] == obj)
+				properties[i] = getDefaultProperty();
+		}
+
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/Optimizer.java b/Source/mesquite/lib/Optimizer.java
new file mode 100644
index 0000000..b21fe5a
--- /dev/null
+++ b/Source/mesquite/lib/Optimizer.java
@@ -0,0 +1,1491 @@
+/* Mesquite source code.  Copyright 2002-2003 D. Swofford & W. Maddison and D. Maddison. All Rights reserved.
+Version 1.0, September 2003. */
+package mesquite.lib;
+import java.util.*;
+/* ======================================================================== */
+/* translated april 2002 from C translation by D. Swofford of Algol version by Brent */
+public class Optimizer {
+	static final int MAX_ITER = 50;
+	static final double CGOLD = 0.3819660113;		/* = (3 - sqrt(5))/2 */
+	//static long			praxisSeed;
+	public  int			nl;				/* counter for number of line minimizations performed */
+	 double		dmin; //most of these changed to instance variables from statics  WPM Nov '09
+	 double		ldt;
+	 double		qf1;
+	 double		qd0, qd1;
+	 double		m2, m4;
+	 double		esmall;			/* DLS 03feb2001: renamed 'small' to 'esmall' to avoid conflict with Win32
+										   "#define small char" */
+	 double		toler, htol;	/* global versions of Praxis arguments */
+	 int			n;
+	 double		gfx;
+//	static double[]		xnew;
+	 double		machEps;
+	 double		DBL_EPSILON = 2.2204460492503131e-16;
+	 boolean FOREVER = true;
+	 double[][]	v;
+	Random rng;
+	double[] d, q0, q1, xnew, y, z;
+	Evaluator evaluator;
+	double t = 1e-10; //for LocalMin
+	double eps = DBL_EPSILON; //for LocalMin 16-13
+	double tol = 1e-4; //original e-4
+	static final double h = 1.0;
+	int dimension;
+	Abortable abortable;
+	double acceptableValue = MesquiteDouble.unassigned;
+	
+	double[] lowerBoundsSearched, upperBoundsSearched;//added WPM April 2002
+	
+	public Optimizer(Evaluator evaluator){
+		rng = new Random(1);
+		this.evaluator = evaluator;
+		/*if (dimension!=1){
+			v = new double[dimension][dimension];
+			d = new double[dimension];
+			q0 = new double[dimension];
+			q1 = new double[dimension];
+			xnew = new double[dimension];
+			y = new double[dimension];
+			z = new double[dimension];
+		}*/
+		this.dimension = 0;
+	}
+	public void setDimension(int n){//added WPM April 2002
+		if (dimension!=n){
+			dimension = n;
+			v = new double[dimension][dimension];
+			d = new double[dimension];
+			q0 = new double[dimension];
+			q1 = new double[dimension];
+			xnew = new double[dimension];
+			y = new double[dimension];
+			z = new double[dimension];
+			lowerBoundsSearched = new double[dimension];
+			upperBoundsSearched = new double[dimension];
+		}
+		dimension = n;
+	}
+	public int getDimension(){//added WPM April 2002
+		return dimension;
+	}
+	void checkBoundsDimension(double[] x){//added WPM April 2002
+		if (x==null)
+			return;
+		if (lowerBoundsSearched == null) {
+			lowerBoundsSearched = new double[x.length];
+			upperBoundsSearched = new double[x.length];
+			for (int i=0; i<x.length; i++){
+				lowerBoundsSearched[i]=x[i];
+				upperBoundsSearched[i]=x[i];
+			}
+		}
+		else if (x.length>lowerBoundsSearched.length) {
+			double[] lbs = new double[x.length];
+			double[] ubs = new double[x.length];
+			for (int i=0; i<x.length; i++){
+				if (i>=lowerBoundsSearched.length) {
+					lbs[i]=x[i];
+					ubs[i]=x[i];
+				}
+				else {
+					lbs[i]=lowerBoundsSearched[i];
+					ubs[i]=upperBoundsSearched[i];
+				}
+			}
+		}
+	}
+	void checkBoundsSearched(double[] x){//added WPM April 2002
+		if (x==null)
+			return;
+		checkBoundsDimension(x);
+		for (int i=0; i<x.length; i++){
+			double xi = x[i];
+			if (xi<lowerBoundsSearched[i]) 
+				lowerBoundsSearched[i] = xi;
+			if (xi>upperBoundsSearched[i]) 
+				upperBoundsSearched[i] = xi;
+		}
+	}
+
+	public double[] getLowerBoundsSearched(){//added WPM April 2002
+		return lowerBoundsSearched;
+	}
+	public double[] getUpperBoundsSearched(){ //added WPM April 2002
+		return upperBoundsSearched;
+	}
+	
+	public double[][] grid(double min1, double max1, double min2, double max2, int divisions, Object extraInfo){
+		double[][] g = new double[divisions][divisions];
+		double[] x = new double[2];
+		for (int i = 0; i<divisions; i++){
+			x[0] =i* (max1-min1)/divisions + min1;
+			for (int j = 0; j<divisions; j++){
+				x[1] =j* (max2-min2)/divisions + min2;
+				double fcn = evaluator.evaluate(x, extraInfo);
+				g[i][j] = fcn;
+				//System.out.println(x[0] + "\t" + x[1] + "\t" + fcn);
+			}
+		}
+		return g;
+	}
+	
+	
+	public boolean valueAcceptable(double fx){  //DRM
+		if (MesquiteDouble.isCombinable(acceptableValue) && fx<=acceptableValue) {
+			return true;
+		}
+		return false;
+	}
+	public boolean getAbort(){  //DRM
+		if (abortable!=null && abortable.isAborted()) {
+			return true;
+		}
+		return false;
+	}
+
+	public double optimize(double[] point, Object extraInfo){ //multi-dimensional; p should contain initial guess
+		return optimize(point,MesquiteDouble.unassigned, extraInfo,null);
+	}
+
+	public double optimize(double[] point, double acceptableValue, Object extraInfo, Abortable abortable){ //multi-dimensional; p should contain initial guess
+		this.acceptableValue = acceptableValue;
+		this.abortable = abortable;
+		if (point.length != dimension)
+			setDimension(point.length);
+		return Praxis(tol, h, point.length,point, evaluator, extraInfo);
+	}
+	
+	public double optimize(MesquiteDouble p, double lower, double upper, Object extraInfo){ //one dimensional; p should contain initial guess
+		if (!p.isCombinable())
+			p.setValue(0.1);
+		return LocalMin(lower, upper,  eps,	t, evaluator, extraInfo, p)	; //t and eps need to be defined
+	}
+	
+	private double Praxis_FLin(int j, double lambda, double[] x, double[] q0, double[] q1, double[][] v,
+                      Evaluator f, Object dataPtr)
+	{
+	int		i;
+	double	qa, qb, qc;
+
+	if (j >= 0)
+		{
+		/* Try point in linear search */
+		for (i = 0; i < n; i++)
+			xnew[i] = x[i] + lambda*v[i][j];
+		}
+	else
+		{
+		/* Search along a parabolic space curve */
+		qa = lambda*(lambda - qd1)/(qd0*(qd0 + qd1));
+		qb = (lambda + qd0)*(qd1 - lambda)/(qd0*qd1);
+		qc = lambda*(lambda + qd0)/(qd1*(qd0 + qd1));
+		
+		/* Previous three points were stored as follows: x' in q0, x'' in x, and x''' in q1 */
+		for (i = 0; i < n; i++)
+			xnew[i] = qa*q0[i] + qb*x[i] + qc*q1[i];
+		}
+
+	checkBoundsSearched(xnew); //added WPM April 2002
+	return f.evaluate(xnew, dataPtr);
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	LocalMin
+|
+|	Finds a private minimum of a function of one variable using Brent's (1973) method.
+|
+|	This function is reentrant.
+*/
+
+
+public double LocalMin(
+  double		a,			/* on input, (a,b) must bracket a private minimum */
+  double		b,
+  double		eps,		/* t and eps define tol = eps|x| + t, f is never evaluated at two points */
+  double		t,			/*   closer together than tol;  eps should be > sqrt(DBL_EPSILON)        */
+  Evaluator	f,			/* function to minimize */
+  Object 	dataPtr,	/* pointer to data to be passed to 'f' */
+  MesquiteDouble		px)		/* value of x when f(x) is minimal */
+	{
+	double		e, m, p, q, r, x, tol, t2, u, v, w, fu, fv, fw, fx,
+				d = 0.0;	/* shuts up bogus lint warning */
+	int			iter;
+	MesquiteDouble xA = new MesquiteDouble();
+	MesquiteDouble uA = new MesquiteDouble();
+
+	v = w = x = a + CGOLD*(b - a);
+	e = 0.0;
+	xA.setValue(x);
+	fv = fw = fx =f.evaluate(xA, dataPtr);
+	x = xA.getValue();
+	if (getAbort() || valueAcceptable(fx))   //DRM April 2005
+		return fx;
+	//RETURN_IF_ABORTED 
+	
+
+	/* Main loop */
+
+	for (iter = 0; iter < MAX_ITER; iter++)
+		{
+		m = 0.5*(a + b);
+		tol = eps*Math.abs(x) + t;
+		t2 = 2.0*tol;
+
+		/* Check stopping criterion */
+		if (Math.abs(x - m) <= t2 - 0.5*(b - a))
+			break;
+
+		p = q = r = 0.0;
+		if (Math.abs(e) > tol)
+			{
+			/* Fit parabola (trial) */
+			r = (x - w)*(fx - fv);
+			q = (x - v)*(fx - fw);
+			p = (x - v)*q - (x - w)*r;
+			q = 2.0*(q - r);
+			if (q > 0.0)
+				p = -p;
+			else
+				q = -q;
+			r = e;
+			e = d;	/* lint complains about possible use of 'd' before being set, but it's not a problem because e=0
+			           first time through, so "Math.abs(e) > tol" test fails */
+			}
+			
+		/* Take parabolic-interpolation or golden-section step (note that Brent's Algol procedure had an error,
+		   p > q*(a-x) is correct) */
+		if ((Math.abs(p) < Math.abs(0.5*q*r)) && (p > q*(a - x)) && (p < q*(b - x)))
+			{
+			/* Parabolic interpolation step */
+			d = p/q;
+			u = x + d;
+			/* Don't evaluate f too close to a or b */
+			if ((u - a < t2) || (b - u < t2))
+				d = (x < m) ? tol : -tol;
+			}
+		else
+			{
+			/* "Golden section" step */
+			e = ((x < m) ? b : a) - x;
+			d = CGOLD*e;
+			}
+
+		/* Don't evaluate f too close to x */
+		if (Math.abs(d) >= tol)
+			u = x + d;
+		else if (d > 0.0)
+			u = x + tol;
+		else 
+			u = x - tol;
+
+		uA.setValue(u);
+		fu = f.evaluate(uA, dataPtr);
+		u = uA.getValue();
+		if (getAbort() || valueAcceptable(fx))   //DRM April 2005
+			return fx;
+		//RETURN_IF_ABORTED 
+		
+		/* Update a, b, v, w, and x */
+		if (fu <= fx)
+			{
+			if (fu <= fx)
+				{
+				if (u < x)
+					b = x;
+				else
+					a = x;
+				v = w;
+				fv = fw;
+				w = x;
+				fw = fx;
+				x = u;
+				fx = fu;
+				}
+			}
+		else
+			{
+			if (u < x)
+				a = u;
+			else
+				b = u;
+			if ((fu <= fw) || (w == x))
+				{
+				v = w;
+				fv = fw;
+				w = u;
+				fw = fu;
+				}
+			else if ((fu <= fv) || (v == x) || (v == w))
+				{
+				v = u;
+				fv = fu;
+				}
+			}
+		}
+	px.setValue(x);
+	return fx;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	TransformUnboundedToLU
+|
+|	Maps y in R to x in [g,h] using the transformation x = g + (h - g)sin^2 y, where g and h are lower and upper
+|	bounds, respectively, on x.
+|
+|	This transformation is used to allow unconstrained minimization of a function with simple linear bounds on the
+|	variables; see: Box, M. J.  1966.  A comparison of several current optimization methods, and the use of
+|	transformations in constrained problems.  Computer Journal 9:67-77.
+*/
+	
+public double TransformUnboundedToLU(MesquiteDouble py, double g, double h, boolean oldSystem)
+	{
+	if (oldSystem)
+		{
+		/* Brute force adjustment of out-of-bounds parameter values */
+		if (py.getValue() < g)
+			py.setValue(g);
+		else if (py.getValue() > h)
+			py.setValue(h);
+		return py.getValue();
+		}
+	else
+		{
+		double sin_y = Math.sin(py.getValue());
+		return g + (h - g)*sin_y*sin_y;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	TransformLUtoUnbounded
+|
+|	Maps x in [g,h] to y in R using the inverse of the transformation x = g + (h - g)sin^2 y, where g and h are lower
+|	and upper bounds, respectively, on x.
+*/
+
+public double TransformLUtoUnbounded(double x, double g, double h, boolean oldSystem)
+	{
+	if (oldSystem)
+		{
+		return x;				/* No transformation was actually done */
+		}
+	else
+		{
+		double		y, z;
+
+		y = (g - x)/(g - h);	/* (Caller guarantees that h > g) */
+
+		if (y < 0.0)			/* Protect against roundoff error */				
+			y = 0.0;
+
+		z = Math.sqrt(y);	
+		if (z > 1.0)			/* Should never happen, but prevent death in asin just in case */
+			z = 1.0;
+
+		return Math.asin(z);
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	TransformUnboundedToLower
+|
+|	Maps y in R to x in [g,infinity] using the transformation x = exp(y) + g, where g is a lower bound on x.
+|
+|	This transformation is used to allow unconstrained minimization of a function with simple linear bounds on the
+|	variables; see: Box, M. J.  1966.  A comparison of several current optimization methods, and the use of
+|	transformations in constrained problems.  Computer Journal 9:67-77.
+|
+|	TO DO: If/when we abandon the 'oldSystem' option for brute-force adjustment of out-of-bounds parameter values, we
+|	       can pass y directly (rather than py).
+*/
+	
+public double TransformUnboundedToLower(MesquiteDouble py, double g, boolean oldSystem)
+	{
+	if (oldSystem)
+		{
+		if (py.getValue() < g)
+			py.setValue(g);
+		return py.getValue();
+		}
+	else
+		{
+		double y = py.getValue();
+		if (y < -300.0)				/* avoid underflow potential */
+			y = -300.0;
+
+		return Math.exp(y) + g;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	TransformLowerToUnbounded
+|
+|	Maps x in [g,infinity] to y in R using the inverse of the transformation x = exp(y) + g where g is a lower bound
+|	on x.
+*/
+
+public double TransformLowerToUnbounded(double x, double g, boolean oldSystem)
+	{
+	if (oldSystem)
+		{
+		return x;					/* No transformation was actually done */
+		}
+	else
+		{
+		double	z = x - g;
+
+		if (z < DBL_EPSILON)		/* Avoid possible numerical problems */
+			z = DBL_EPSILON;
+		
+		return Math.log(z);
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	Praxis_Min
+|
+|	Minimizes the objective function from point x in the direction v(*,j) (if j >= 0), or performs a quadratic search
+|	in the plane defined by q0, q1, and x (if j < 0).
+*/
+
+private void Praxis_Min(
+  int			j,			/* column of direction matrix (or <0 flag for quadratic search) */
+  int			nits,		/* number of times an attempt is made to halve the interval */
+  double[]		x,			/* current point */
+  double[]		q0,		/* previous point */
+  double[]		q1,		/* second previous point */
+  double[][]	v,		/* direction-set matrix */
+  MesquiteDouble	pd2,		/* approximation to half f'' (or zero) */
+  MesquiteDouble	px1,		/* x1 = estimate of distance to minimum, returned as actual distance found */
+  double		f1,			/* if fk=true, FLin(x1), otherwise ignored */
+  boolean			fk,			/* flag (see above) */
+  Evaluator	f,			/* function to minimize */
+  Object	dataPtr)	/* pointer to data to be passed to 'f' */
+	{
+	boolean	dz, success;
+	int			i, k;
+	double		x1, x2, xm, f0, f2, fm, d1, d2, t2, s, sf1, sx1;
+	
+	/* Copy args passed by reference to locals (will pass back at end) */
+	d2 = pd2.getValue();
+	x1 = px1.getValue();
+	
+	sf1 = f1;
+	sx1 = x1;
+	k = 0;
+	xm = 0.0;
+	f0 = fm = gfx;
+	dz = (d2 < machEps);	/* if true, we need f''(0) */
+	
+	/* Find step size */
+	s = 0.0;
+	for (i = 0; i < n; i++)
+		{
+//#		if 0
+		/* DLS 22jun00: Use of the temporary variable here seems to be important for numerical accuracy (not sure why,
+		   but different code is generated in both PPC Metrowerks and Dec Alpha compilers). */
+//		s += x[i]*x[i];
+//#		else	/* use this for release version */
+		double xi = x[i];
+		s += xi*xi;
+//#		endif
+		}
+	s = Math.sqrt(s);
+
+	t2 = m4*Math.sqrt(Math.abs(gfx)/(dz ? dmin : d2) + s*ldt) + m2*ldt;
+	s = m4*s + toler;
+	if (dz && (t2 > s))
+		t2 = s;
+	if (t2 < esmall)
+		t2 = esmall;
+	if (t2 > 0.01*htol)
+		t2 = 0.01*htol;
+
+	if (fk && (f1 <= fm))
+		{
+		xm = x1;
+		fm = f1;
+		}
+
+	if (!fk || (Math.abs(x1) < t2))
+		{
+		x1 = (x1 >= 0.0) ? t2 : -t2;
+
+		f1 = Praxis_FLin(j, x1, x, q0, q1, v, f, dataPtr);
+		if (getAbort())  //DRM Apr 2005
+			return; //VOID_RETURN_IF_ABORTED 
+		}
+	if (f1 <= fm)
+		{
+		xm = x1;
+		fm = f1;
+		}
+	
+	/* Find a distance x2 ("lambda*") that approximately minimizes f in the chosen direction */
+	do	{
+		if (dz)
+			{
+			/* Evaluate FLin at another point and estimate the second derivative */
+			x2 = (f0 < f1) ? -x1 : 2.0*x1;
+			f2 = Praxis_FLin(j, x2, x, q0, q1, v, f, dataPtr);
+			if (getAbort())  //DRM Apr 2005
+				return; //VOID_RETURN_IF_ABORTED 
+			if (f2 <= fm)
+				{
+				xm = x2;
+				fm = f2;
+				}
+			d2 = (x2*(f1 - f0) - x1*(f2 - f0))/(x1*x2*(x1 - x2));
+			dz = false;		/* DLS 11jun00: see explanation below */
+			}
+	
+		/* Estimate first derivative at 0 */	
+		d1 = (f1 - f0)/x1 - x1*d2;
+
+		/* DLS 11jun00: I think the statement below on Brent's page 160 is erroneous.  If dz remains true, and this
+		                loop executes again, then x2 will be reset to -x1 at the top of the loop, but x1 is never
+		                changed within the loop. Since neither x1 nor x2 changes, additional iterations of the loop
+		                are just wasted calculation requiring pointless function evaluations.  I think what Brent
+		                *meant* to do was to set dz to false, since we now have an estimate of the second derivative
+		                and don't need to redo this again if the loop continues to iterate.
+		dz = true;
+		*/
+			//dls 10 apr: but why would dz = true below then be necessary?????????
+
+//#		if defined(PAUP)
+			/* This is necessary to reproduce B4a results with aml.usingOldBoundSys=true */
+//			if (aml.usingOldBoundSys)
+//				dz = true;
+//#		endif
+
+		/* Predict minimum */
+		if (d2 <= esmall)
+			x2  = (d1 < 0.0) ? htol : -htol;
+		else
+			{
+			x2 = -0.5*d1/d2;
+			if (Math.abs(x2) > htol)
+				x2 = (x2 > 0.0) ? htol : -htol;
+			}
+
+		/* Evaluate f at predicted minimum */
+		do	{
+			f2 = Praxis_FLin(j, x2, x, q0, q1, v, f, dataPtr);
+			if (getAbort())  //DRM Apr 2005
+				return; //VOID_RETURN_IF_ABORTED 
+			success = true;
+			if ((k < nits) && (f2 > f0))
+				{
+				/* No success so halve interval and try again */
+				success = false;
+				k++;
+				if ((f0 < f1) && (x1*x2 > 0.0))
+					break;
+				x2 *= 0.5;
+				}
+			}
+			while (!success);
+		}		
+		while (!success);
+
+	nl++;	/* increment counter for number of line searches */
+
+	if (f2 > fm)
+		x2 = xm;
+	else
+		fm = f2;
+		
+	/* Get new estimate of second derivative */
+	if (Math.abs(x2*(x2 - x1)) > esmall)
+		d2 = (x2*(f1 - f0) - x1*(fm - f0))/(x1*x2*(x1 - x2));
+	else if (k > 0)
+		d2 = 0.0;
+	if (d2 < esmall)
+		d2 = esmall;
+
+	x1 = x2;
+	gfx = fm;
+	if (sf1 < gfx)
+		{
+		gfx = sf1;
+		x1 = sx1;
+		}
+		
+	/* Update x for linear search but not for parabolic search */
+	if (j >= 0)
+		{
+		for (i = 0; i < n; i++)
+			x[i] += x1*v[i][j];
+		}
+
+	px1.setValue(x1);
+	pd2.setValue(d2);
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	Praxis_Quad
+|
+|	Looks for the function minimum along a curve defined by q0, q1, and x.
+|
+|	DLS 15jun00: I modified Brent's code so that q0 and q1 are passed as arguments to Praxis_MIN rather than being
+|	             global within Praxis.  This made it possible to avoid some unnecessary vector swapping.
+*/
+MesquiteDouble sA = new MesquiteDouble(); //WPM: this might cause reentrancy problems; pass into PraxisQuad?
+MesquiteDouble lambdaA = new MesquiteDouble();
+
+private void Praxis_Quad(double[] x, double[] q0, double[] q1, double[][] v, Evaluator f, Object dataPtr)
+	{
+	int		i;
+	double	lambda, s;
+	double	qa, qb, qc;
+
+	/* q0 and q1 contain previous two points */
+
+	s = gfx;
+	gfx = qf1;
+	qf1 = s;
+	
+	qd1 = 0.0;
+	for (i = 0; i < n; i++)
+		{
+		/* DLS: Brent had this (see above) ...
+		s = x[i];
+		x[i] = q1[i];
+		q1[i] = s;
+		qd1 += (q1[i] - x[i])*(q1[i] - x[i]);
+		
+		... but we avoid having to swap q1 and x vectors ... */
+		s = q1[i] - x[i];
+		qd1 += s*s;
+		}
+	qd1 = Math.sqrt(qd1);
+	if ((qd0 > 0.0) && (qd1 > 0.0) && (nl >= 3*n*n))
+		{
+		s = 0.0;
+		lambda = qd1;
+
+		/* DLS: note position of q1 and x args (see comments above) */
+		sA.setValue(s);
+		lambdaA.setValue(lambda);
+		Praxis_Min(-1, 2, q1, q0, x, v, sA, lambdaA, qf1, true, f, dataPtr);
+		s = sA.getValue();
+		lambda = lambdaA.getValue();
+		if (getAbort())  //DRM Apr 2005
+			return; //VOID_RETURN_IF_ABORTED 
+		qa = lambda*(lambda - qd1)/(qd0*(qd0 + qd1));
+		qb = (lambda + qd0)*(qd1 - lambda)/(qd0*qd1);
+		qc = lambda*(lambda + qd0)/(qd1*(qd0 + qd1));
+		}
+	else
+		{
+		gfx = qf1;
+		qa = qb = 0.0;
+		qc = 1.0;
+		}
+	qd0 = qd1;
+	for (i = 0; i < n; i++)
+		{
+		s = q0[i];
+
+		/* DLS: Brent had this ...
+		q0[i] = x[i];
+		x[i] = qa*s + qb*x[i] + qc*q1[i];
+
+		... but must be modified as below since we didn't swap x and q1 above ... */
+		q0[i] = q1[i];
+		q1[i] = x[i];
+		x[i] = qa*s + qb*q0[i] + qc*x[i];
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	Praxis_MinFit
+|
+|	Gets singular value decomposition using a modified version of Golub and Reinsch's (1969) routine, restricted to
+|	m=n.  The singular values of the array 'ab' are returned in 'q', and 'ab' is overwritten with the orthogonal
+|	matrix V such that U.diag(Q) = AB.V, where U is another orthogonal matrix.
+*/
+
+private void Praxis_MinFit(double eps, double tol, double[][] ab, double[] q,
+                         double[] e)	/* work vector of size n */
+	{
+	int			i, j, k, l, l2, kt;
+	double		c, f, g, h, s, x, y, z;
+	l = 0; //here merely so java compiler doesn't complain that l might not have been initialized
+	
+	/* Householder's reduction to bidiagonal form */
+	g = x = 0.0;
+	for (i = 0; i < n; i++)
+		{
+		e[i] = g;
+		s = 0.0;
+		l = i + 1;
+		for (j = i; j < n; j++)
+			s += ab[j][i]*ab[j][i];
+		if (s < tol)
+			g = 0.0;
+		else
+			{
+			f = ab[i][i];
+			g = (f < 0.0) ? Math.sqrt(s) : -Math.sqrt(s);
+			h = f*g - s;
+			ab[i][i] = f - g;
+			for (j = l; j < n; j++)
+				{
+				f = 0.0;
+				for (k = i; k < n; k++)
+					f += ab[k][i]*ab[k][j];
+				f /= h;
+				for (k = i; k < n; k++)
+					ab[k][j] += f*ab[k][i];
+				}
+			}
+		q[i] = g;
+		s = 0.0;
+		for (j = l; j < n; j++)
+			s += ab[i][j]*ab[i][j];
+		
+		if (s < tol)
+			g = 0.0;
+		else
+			{
+			f = ab[i][i + 1];		/* (DLS note: when i=n-1, s is always 0) */
+			g = (f < 0.0) ? Math.sqrt(s) : -Math.sqrt(s);
+			h = f*g - s;
+			ab[i][i + 1] = f - g;
+			for (j = l; j < n; j++)
+				e[j] = ab[i][j]/h;
+			for (j = l; j < n; j++)
+				{
+				s = 0.0;
+				for (k = l; k < n; k++)
+					s += ab[j][k]*ab[i][k];
+				for (k = l; k < n; k++)
+					ab[j][k] += s*e[k];
+				}
+			}
+		y = Math.abs(q[i]) + Math.abs(e[i]);
+		if (y > x)
+			x = y;
+		}
+	
+	/* Accumulation of right-hand transformations */
+	for (i = n - 1; i >= 0; i--)
+		{
+		if (g != 0.0)
+			{
+			h = ab[i][i + 1]*g;
+			for (j = l; j < n; j++)
+				ab[j][i] = ab[i][j]/h;
+			for (j = l; j < n; j++)
+				{
+				s = 0.0;
+				for (k = l; k < n; k++)
+					s += ab[i][k]*ab[k][j];
+				for (k = l; k < n; k++)
+					ab[k][j] += s*ab[k][i];
+				}
+			}
+		for (j = l; j < n; j++)
+			ab[i][j] = ab[j][i] = 0.0;
+		ab[i][i] = 1.0;
+		g = e[i];
+		l = i;
+		}
+	boolean testSplitting = false;
+	/* Diagonalization of the bidiagonal form */
+	eps *= x;
+	kt = 0;
+
+	for (k = n - 1; k >= 0 || testSplitting; k--)
+		{
+
+		if (testSplitting)
+			k++;
+		else
+			kt = 0;
+		testSplitting = false;
+		boolean gotoConvergence = false;
+		if (++kt > 30)
+			{
+			e[k] = 0.0;
+			}
+		for (l2 = k; l2 >= 0; l2--)
+			{
+			l = l2;
+			if (Math.abs(e[l]) <= eps)
+				{
+				gotoConvergence = true;
+				break;
+				}
+			if (Math.abs(q[l - 1]) <= eps)
+				break;
+			}
+		if (!gotoConvergence)
+			{
+			/* Cancellation of e[l] if l > 1 */
+			c = 0.0;
+			s = 1.0;
+			for (i = l; i <= k; i++)
+				{
+				f = s*e[i];
+				e[i] *= c;
+				if (Math.abs(f) <= eps)
+					break;
+				g = q[i];
+				if (Math.abs(f) < Math.abs(g))						/* (implies g > eps) */
+					h = Math.abs(g)*Math.sqrt(1.0 + (f/g)*(f/g));
+				else if (f != 0.0)
+					h = Math.abs(f)*Math.sqrt(1.0 + (g/f)*(g/f));
+				else
+					h = 0.0;
+				q[i] = h;
+				if (h == 0.0)
+					g = h = 1.0;	/* Note: this replaces q[i]=h=sqrt(g*g+f*f) which may give incorrect results if the
+									         squares underflow or if f=g=0 */
+				c = g/h;
+				s = -f/h;
+				}
+			}
+			
+		z = q[k];
+		
+		testSplitting = false;
+		if (l != k)
+			{			
+			/* Shift from bottom 2x2 minor */
+			x = q[l];
+			y = q[k - 1];
+			g = e[k - 1];
+			h = e[k];
+			f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y);
+			g = Math.sqrt(f*f + 1.0);
+			s = (f < 0.0) ? f - g : f + g;
+			f = ((x - z)*(x + z) + h*(y/s - h))/x;
+				
+			/* Next QR transformation */
+			c = s = 1.0;
+			for (i = l + 1; i <= k; i++)
+				{
+				g = e[i];
+				y = q[i];
+				h = s*g;
+				g *= c;
+				/* DLS note: Golob and Reinsch had "z = sqrt(f*f + h*h))" below */
+				if (Math.abs(f) < Math.abs(h))
+					z = Math.abs(h)*Math.sqrt(1.0 + (f/h)*(f/h));
+				else if (f != 0.0)
+					z = Math.abs(f)*Math.sqrt(1.0 + (h/f)*(h/f));
+				else
+					z = 0.0;
+				e[i - 1] = z;
+				if (z == 0.0)
+					z = f = 1.0;
+				c = f/z;
+				s = h/z;
+				f = x*c + g*s;
+				g = -x*s + g*c;
+				h = y*s;
+				y *= c;
+				for (j = 0; j < n; j++)
+					{
+					x = ab[j][i - 1];
+					z = ab[j][i];
+					ab[j][i - 1] = x*c + z*s;
+					ab[j][i] = -x*s + z*c;
+					}
+				/* DLS note: Golob and Reinsch had "z = sqrt(f*f + h*h))" below */
+				if (Math.abs(f) < Math.abs(h))
+					z = Math.abs(h)*Math.sqrt(1.0 + (f/h)*(f/h));
+				else if (f != 0.0)
+					z = Math.abs(f)*Math.sqrt(1.0 + (h/f)*(h/f));
+				else
+					z = 0.0;
+				q[i - 1] = z;
+				if (z == 0.0)
+					z = f = 1.0;
+				c = f/z;
+				s = h/z;
+				f = c*g + s*y;
+				x = -s*g + c*y;
+				}
+			e[l] = 0.0;
+			e[k] = f;
+			q[k] = x;
+			testSplitting = true;
+			}
+		
+		if (!testSplitting && z < 0.0)
+			{
+			/* q[k] is made non-negative */
+			q[k] = -z;
+			for (j = 0; j < n; j++)
+				ab[j][k] = -ab[j][k];
+			}
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	Praxis_SortDV
+|
+|	Sorts the elements of 'd' and corresponding elements of 'v' into descending order.
+*/
+
+private void Praxis_SortDV(double[] d, double[][] v)
+	{
+	int		i, j, k;
+	double	s;
+
+	for (i = 0; i < n - 1; i++)
+		{
+		k = i;
+		s = d[i];
+		for (j = i + 1; j < n; j++)
+			{
+			if (d[j] > s)
+				{
+				k = j;
+				s = d[j];
+				}
+			}
+		if (k > i)
+			{
+			d[k] = d[i];
+			d[i] = s;
+			for (j = 0; j < n; j++)
+				{
+				s = v[j][i];
+				v[j][i] = v[j][k];
+				v[j][k] = s;
+				}
+			}
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	Praxis
+|
+|	Minimizes a function f of n variables using Brent's (1973) principal axis method,which is a modification of
+|	Powell's (1964) method.  Translated by David Swofford from the Algol program in Brent's book.
+|
+|	Note: this function is NOT reentrant, due to the need for the globals below.
+*/
+
+public double Praxis(
+  double		tol,		/* tolerance used for convergence criterion */
+  double		h,			/* maximum step size */
+  int			nn,			/* number of variables */
+  double[]		x,			/* on input, must contain initial guess for optimal point */
+  Evaluator	f,			/* the function to be minimized */
+  Object		dataPtr	/* pointer to data to be passed to 'f' */
+)		
+	{
+	int			i, j, k, k2, kl, kt, ktm;
+	boolean illc;
+	double		vsmall, large, vlarge, scbd, ldfac, sf, df, f1, lds, t2, sl, dn, s, sz;
+
+	machEps = DBL_EPSILON;
+
+	/* Copy args to global equivalents */
+	toler = tol;
+	htol = h;
+	n = nn;
+	/* Partition work space provided by caller into arrays used here --WPM: in translation to Java, done on instantiation 
+	d = work;
+	q0 = d + nn;
+	q1 = q0 + nn;
+	xnew = q1 + nn;
+	y = xnew + nn;
+	z = y + nn;
+	*/
+	
+	/* Machine-dependent initializations */
+	esmall = machEps*machEps;
+	vsmall = esmall*esmall;
+	large = 1.0/esmall;
+	vlarge = 1.0/vsmall;
+	m2 = Math.sqrt(machEps);
+	m4 = Math.sqrt(m2);
+	
+	//praxisSeed = 1;		/* starting seed for random number generator */
+	
+	/* Heuristic numbers:
+	   - if axes may be badly scaled (which should be avoided if possible), set scbd=10, otherwise 1
+	   - if the problem is known to be ill-conditioned, set illc=true, otherwise false
+	   - ktm+1 is the number of iterations without improvement before the algorithm terminates (see section 7.6 of
+	     Brent's book).  ktm=4 is very cautious; usually ktm=1 is satisfactory.
+	*/
+	scbd = 1.0;
+	illc = false;
+	ktm = 1;
+
+	ldfac = illc ? 0.1 : 0.01;
+	kt = nl = 0;
+	checkBoundsSearched(x); //added WPM April 2002
+	qf1 = gfx = f.evaluate(x, dataPtr);
+	if (getAbort() || valueAcceptable(gfx))  //DRM Apr 2005
+		return gfx; 
+	//RETURN_IF_ABORTED 
+	toler = t2 = esmall + Math.abs(toler);
+	dmin = esmall;
+	if (htol < 100.0*toler)
+		htol = 100.0*toler;
+	ldt = htol;
+	Double2DArray.setToIdentityMatrix(v);
+
+	d[0] = qd0 = 0.0;
+	for (i = 0; i < n; i++)
+		{
+		q0[i] = 0.0;	/* DLS: this wasn't included in Brent's code, but it's important */
+		q1[i] = x[i];
+		}
+
+	checkBoundsSearched(x); //added WPM April 2002
+	
+	/* ------ main loop ------ */
+	MesquiteDouble dEA = new MesquiteDouble();
+	MesquiteDouble sA = new MesquiteDouble();
+
+	while (FOREVER)
+		{
+		checkBoundsSearched(x); //added WPM April 2002
+		sf = d[0];
+		d[0] = s = 0.0;
+		
+		/* Minimize along first direction */
+		dEA.setValue(d[0]);
+		sA.setValue(s);
+		Praxis_Min(0, 2, x, q0, q1, v,dEA, sA, gfx, false, f, dataPtr);
+		d[0] = dEA.getValue();
+		s = sA.getValue();
+		if (getAbort() || valueAcceptable(gfx))  //DRM Apr 2005
+			return gfx; 
+		//RETURN_IF_ABORTED 
+		if (s < 0.0)
+			{
+			for (i = 0; i < n; i++)
+				v[i][0] = -v[i][0];
+			}
+		if ((sf <= 0.9*d[0]) || (0.9*sf >= d[0]))
+			{
+			for (i = 1; i < n; i++)
+				d[i] = 0.0;
+			}
+		kl = 0; //so compiler doesn't complain not initialized
+		for (k = 1; k < n; k++)
+			{
+			for (i = 0; i < n; i++)
+				y[i] = x[i];
+			sf = gfx;
+			illc = illc || (kt > 0);
+	
+			while (FOREVER)
+				{
+				kl = k;
+				df = 0.0;
+				if (illc)
+					{
+					/* Random step to get off resolution valley */
+					for (i = 0; i < n; i++)
+						{
+						s = z[i] = (0.1*ldt + t2*Math.pow(10.0, (double)kt))*(rng.nextDouble() - 0.5); //rnd 0 to 1
+						for (j = 0; j < n; j++)
+							x[j] += s*v[j][i];
+						}
+					checkBoundsSearched(x); ////added WPM April 2002
+					gfx = f.evaluate(x, dataPtr);
+					if (getAbort() || valueAcceptable(gfx)) //DRM Apr 2005
+						return gfx; 
+					//RETURN_IF_ABORTED 
+					}
+				for (k2 = k; k2 < n; k2++)
+					{
+					sl = gfx;
+					s = 0.0;
+					/* Minimize along "non-conjugate" directions */
+					dEA.setValue(d[k2]);
+					sA.setValue(s);
+					Praxis_Min(k2, 2, x, q0, q1, v, dEA, sA, gfx, false, f, dataPtr);
+					d[k2] = dEA.getValue();
+					s = sA.getValue();
+					if (getAbort() || valueAcceptable(gfx)) //DRM Apr 2005
+						return gfx; 
+					//RETURN_IF_ABORTED 
+					if (illc)
+						{
+						sz = s + z[k2];
+						s = d[k2]*sz*sz;
+						}
+					else
+						s = sl - gfx;
+					if (df < s)
+						{
+						df = s;
+						kl = k2;
+						}
+					}
+				if (!illc && (df < Math.abs(100.0*machEps*gfx)))
+					illc = true;	/* no success with illc=false so try once with illc=true */
+				else
+					break;
+				}
+			
+			for (k2 = 0; k2 < k; k2++)
+				{
+				/* Minimize along "conjugate" directions */
+				s = 0.0;
+				dEA.setValue(d[k2]);
+				sA.setValue(s);
+				Praxis_Min(k2, 2, x, q0, q1, v, dEA, sA, gfx, false, f, dataPtr);
+				d[k2] = dEA.getValue();
+				s = sA.getValue();
+				if (getAbort() || valueAcceptable(gfx)) //DRM Apr 2005
+					return gfx; 
+				//RETURN_IF_ABORTED 
+				}
+	
+			f1 = gfx;
+			gfx = sf;
+			lds = 0.0;
+			for (i = 0; i < n; i++)
+				{
+				sl = x[i];
+				x[i] = y[i];
+				y[i] = (sl -= y[i]);
+				lds += sl*sl;
+				}
+			lds = Math.sqrt(lds);
+			if (lds > esmall)
+				{
+				/* Throw away direction kl */
+				for (i = kl - 1; i >= k; i--)
+					{
+					for (j = 0; j < n; j++)
+						v[j][i + 1] = v[j][i];
+					d[i + 1] = d[i];
+					}
+
+				/* Set new "conjugate" direction ... */
+				d[k] = 0.0;
+				for (i = 0; i < n; i++)
+					v[i][k] = y[i]/lds;
+								
+				/* ... and minimize along it */
+				dEA.setValue(d[k]);
+				sA.setValue(lds);
+				Praxis_Min(k, 4, x, q0, q1, v, dEA, sA, f1, true, f, dataPtr);
+				d[k] = dEA.getValue();
+				lds = sA.getValue();
+				if (getAbort() || valueAcceptable(gfx))  //DRM Apr 2005
+					return gfx; 
+				//RETURN_IF_ABORTED 
+				if (lds <= 0.0)
+					{
+					lds = -lds;
+					for (i = 0; i < n; i++)
+						v[i][k] = -v[i][k];
+					}
+				}
+			ldt *= ldfac;
+			if (ldt < lds)
+				ldt = lds;
+			t2 = 0.0;
+			for (i = 0; i < n; i++)
+				t2 += x[i]*x[i];
+			t2 = m2*Math.sqrt(t2) + toler;
+			
+			/* See if step length exceeds half the tolerance (stopping criterion) */
+			kt = (ldt > 0.5*t2) ? 0 : kt + 1;
+			if (kt > ktm)
+				{
+				return gfx;
+				}
+			}
+		
+		/* Try quadratic extrapolation in case we are stuck in a curved valley */
+		Praxis_Quad(x, q0, q1, v, f, dataPtr);
+		if (getAbort() || valueAcceptable(gfx))  //DRM Apr 2005
+			return gfx; 
+		//RETURN_IF_ABORTED 
+	
+		/* Calculate V = U.(D^(-1/2))  (note: 'v' currently contains U) */
+		dn = 0.0;
+		for (i = 0; i < n; i++)
+			{
+			d[i] = 1.0/Math.sqrt(d[i]);
+			if (d[i] > dn)
+				dn = d[i];
+			}
+		for (j = 0; j < n; j++)
+			{
+			s = d[j]/dn;
+			for (i = 0; i < n; i++)
+				v[i][j] *= s;
+			}
+
+		if (scbd > 1.0)
+			{
+			/* Scale axes in attempt to reduce condition number */
+			s = vlarge;
+			for (i = 0; i < n; i++)
+				{
+				sl = 0.0;
+				for (j = 0; j < n; j++)
+					sl += v[i][j]*v[i][j];
+				z[i] = Math.sqrt(sl);
+				if (z[i] < m4)
+					z[i] = m4;
+				if (s > z[i])
+					s = z[i];
+				}
+			for (i = 0; i < n; i++)
+				{
+				sl = s/z[i];
+				z[i] = 1.0/sl;
+				if (z[i] > scbd)
+					{
+//#					if 0	/* DLS 6jan97: Borland C says this is a do-nothing statement,
+ //                                          and they're right */
+//					sl = 1.0/scbd;
+//#					endif
+					z[i] = scbd;
+					}
+				}
+			}
+
+		/* Transpose v for MinFit */
+		for (i = 1; i < n; i++)
+			{
+			for (j = 0; j < i; j++)
+				{
+				s = v[i][j];
+				v[i][j] = v[j][i];
+				v[j][i] = s;
+				}
+			}
+
+		/* Find the singular value decomposition of v.  This gives the eigenvalues and principal axes of the
+		   approximating quadratic form without squaring the condition number. */
+		Praxis_MinFit(machEps, vsmall, v, d, y);	/* ('y' is just a scratch vector) */
+
+		if (scbd > 1.0)
+			{
+			/* Unscaling */
+			for (i = 0; i < n; i++)
+				{
+				s = z[i];
+				for (j = 0; j < n; j++)
+					v[i][j] *= s;
+				}
+			for (i = 0; i < n; i++)
+				{
+				s = 0.0;
+				for (j = 0; j < n; j++)
+					s += v[j][i]*v[j][i];
+				s = Math.sqrt(s);
+				d[i] *= s;
+				s = 1.0/s;
+				for (j = 0; j < n; j++)
+					v[j][i] *= s;
+				}
+			}
+
+		for (i = 0; i < n; i++)
+			{
+			s = dn*d[i];
+			if (s > large)
+				d[i] = vsmall;
+			else if (s < esmall)
+				d[i] = vlarge;
+			else
+				d[i] = 1.0/(s*s);
+			}
+			
+		/* Sort new eigenvalues and eigenvectors */
+		Praxis_SortDV(d, v);
+
+		dmin = d[n - 1];
+		if (dmin < esmall)
+			dmin = esmall;
+		
+		illc = (m2*d[0] > dmin);
+		}
+		return 0;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|
+|	BracketMinimum
+|
+|	Brackets a function minimum using method of Press et al.
+|
+|	This function is reentrant.
+*/
+private double sign(double a,double b){
+	return ((b) > 0.0 ? Math.abs(a) : -Math.abs(a));
+}
+static final double GOLD = 1.618034;
+static final double TINY = 1e-20;
+//#if 0
+//#	define GLIMIT	100.0	/* DLS 07mar98: this was the original setting (see below) */
+//#else
+	/* DLS 07mar98: the original GLIMIT setting of 100.0 was sometimes allowing too great an extrapolation, causing
+	   problems with gamma shape parameter estimation in PAUP*.  Setting to a smaller value shouldn't hurt anything;
+	   in the worst case it will just take a little longer to find the bracket */
+//#	define GLIMIT	10.0
+//#endif
+static final double GLIMIT = 10.0;
+
+public void BracketMinimum(MesquiteDouble pA, MesquiteDouble pB, Evaluator f, Object dataPtr)
+	{
+	double		a, b, c, x, fa, fb, fc, fx, xlim, r, q, temp;
+	MesquiteDouble cA = new MesquiteDouble();
+	MesquiteDouble xA = new MesquiteDouble();
+	
+	fa = f.evaluate(pA, dataPtr);
+	if (getAbort())  //DRM Apr 2005
+		return; 
+	//VOID_RETURN_IF_ABORTED 
+	a = pA.getValue();
+	fb = f.evaluate(pB, dataPtr);
+	if (getAbort())  //DRM Apr 2005
+		return; 
+	//VOID_RETURN_IF_ABORTED 
+	b = pB.getValue();
+	if (fb > fa)
+		{
+		/* Swap a and b so we can go downhill in direction of a to b */
+		temp = a;
+		a = b;
+		b = temp;
+		temp = fa;
+		fa = fb;
+		fb = temp;
+		}
+	c = b + GOLD*(b - a);		/* first guess for c */
+	cA.setValue(c);
+	fc = f.evaluate(cA, dataPtr);
+	c = cA.getValue();
+	if (getAbort())  //DRM Apr 2005
+		return; 
+	//VOID_RETURN_IF_ABORTED 
+
+
+	while (fb > fc)
+		{
+		/* Use inverse parabolic interpolation to compute a new trial point x (= the abcissa which is the minimum of
+		   a parabola through f(a), f(b), and f(c))  */
+		r = (b - a)*(fb - fc);
+		q = (b - c)*(fb - fa);
+		x = b - ((b - c)*q - (b - a)*r) / (2.0*sign(Math.max(Math.abs(q - r), TINY), q - r));
+		xlim = b + GLIMIT*(c - b);
+		if ((b - x)*(x - c) > 0.0)
+			{
+			/* x is between b and c */
+			xA.setValue(x);
+			fx = f.evaluate(xA, dataPtr);
+			x = xA.getValue();
+			if (getAbort())  //DRM Apr 2005
+				return; 
+			//VOID_RETURN_IF_ABORTED 
+			if (fx < fc)
+				{
+				/* There's a minimum between b and c */
+				a = b;
+//#				if 0	/* lines below are apparently do-nothing statements */
+//				fa = fb;
+//				b = x;
+//				fb = fx;
+//#				endif
+				break;
+				}
+			else if (fx > fb)
+				{
+				/* There's a minimum between a and x */
+				c = x;
+//#				if 0	/* line below is apparently a do-nothing statement */
+//				fc = fx;
+//#				endif
+				break;
+				}
+			/* Parabolic fit failed; "magnify" using default magnification */
+			x = c + GOLD*(c - b);
+			xA.setValue(x);
+			fx = f.evaluate(xA, dataPtr);
+			x = xA.getValue();
+			if (getAbort())  //DRM Apr 2005
+				return; 
+			//VOID_RETURN_IF_ABORTED 
+			}
+		else if ((c - x)*(x - xlim) > 0.0)
+			{
+			/* x from parabolic fit is between c and its allowed limit */
+			xA.setValue(x);
+			fx = f.evaluate(xA, dataPtr);
+			x = xA.getValue();
+			//VOID_RETURN_IF_ABORTED 
+			if (getAbort())  //DRM Apr 2005
+				return; 
+			if (fx < fc)
+				{
+				b = c; fb = fc;
+				c = x; fc = fx;
+				x = c + GOLD*(c - b);
+				xA.setValue(x);
+				fx = f.evaluate(xA, dataPtr);
+				x = xA.getValue();
+				if (getAbort())  //DRM Apr 2005
+					return; 
+				//VOID_RETURN_IF_ABORTED 
+				}
+			}
+		else if ((x - xlim)*(xlim - c) > 0.0)
+			{
+			/* Limit parabolic fit to its maximum allowed value */
+			x = xlim;
+			xA.setValue(x);
+			fx = f.evaluate(xA, dataPtr);
+			x = xA.getValue();
+			if (getAbort())  //DRM Apr 2005
+				return; 
+			//VOID_RETURN_IF_ABORTED 
+			}
+		else
+			{
+			/* Reject parabolic x; use default magnification */
+			x = c + GOLD*(c - b);
+			xA.setValue(x);
+			fx = f.evaluate(xA, dataPtr);
+			x = xA.getValue();
+			if (getAbort())  //DRM Apr 2005
+				return; 
+			//VOID_RETURN_IF_ABORTED 
+			}
+		
+		/* New bracket is (b,c,x) */
+		a = b; fa = fb;
+		b = c; fb = fc;
+		c = x; fc = fx;		
+		}
+	if (a < c)
+		{
+		pA.setValue(a);
+		pB.setValue(c);
+		}
+	else
+		{
+		pA.setValue(c);
+		pB.setValue(a);
+		}
+	}
+}
diff --git a/Source/mesquite/lib/OtherAnalysis.java b/Source/mesquite/lib/OtherAnalysis.java
new file mode 100644
index 0000000..ef389ff
--- /dev/null
+++ b/Source/mesquite/lib/OtherAnalysis.java
@@ -0,0 +1,5 @@
+package mesquite.lib;
+
+public interface OtherAnalysis {
+
+}
diff --git a/Source/mesquite/lib/OuterContentArea.java b/Source/mesquite/lib/OuterContentArea.java
new file mode 100644
index 0000000..5748362
--- /dev/null
+++ b/Source/mesquite/lib/OuterContentArea.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A container placed in a window to help ensure that insets don't cause problems on non-MacOS systems.
+In turn it contains the infoBar and the InterContentArea.  When the window is resized, this container is in
+charge of resizing the infoBar and InterContentArea, along with the principle components within the InterContentArea.*/
+class OuterContentArea extends Panel {
+	ContentArea[] graphics;
+	ContentArea[] text;
+	InterContentArea iC;
+	MesquiteWindow ownerWindow;
+	InfoBar infoBar;
+	ExplanationArea explanationArea, annotationArea;
+	public OuterContentArea (MesquiteWindow ownerWindow) {
+		this.ownerWindow = ownerWindow;
+		//addComponentListener(new OCACE(this));
+		setLayout(null);
+	}
+	public void dispose(){
+		ownerWindow=null;
+		for (int i=0; i < graphics.length; i++) 
+			graphics[i]=null;
+		for (int i=0; i < text.length; i++) 
+			text[i]=null;
+		iC = null;
+		infoBar=null;  
+	}
+
+	/*.................................................................................................................*/
+	/** Registers the content areas so that they can be resized as needed */
+	public void setContentsArea(ContentArea[] graphics, ContentArea[] text, InterContentArea iC){
+		this.graphics=graphics;
+		this.iC = iC;
+		this.text = text;
+	}
+	/*.................................................................................................................*/
+	/** Registers the InfoBar so it can be resized as needed */
+	public void setInfoArea(InfoBar iB){
+		this.infoBar=iB;
+	}
+	/*.................................................................................................................*/
+	/** Registers the ExplanationArea so it can be resized as needed */
+	public void setExplanationArea(ExplanationArea eA){
+		this.explanationArea=eA;
+	}
+	/*.................................................................................................................*/
+	/** Registers the AnnotationArea so it can be resized as needed */
+	public void setAnnotationArea(ExplanationArea eA){
+		this.annotationArea=eA;
+	}
+	/*.................................................................................................................*/
+	/** Sets the bounds of this and the content areas within it */
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+//TODO: undone mar 2000		ownerWindow.containerSizeSet(w,h);  //compensate by difference in insets (if inset has gotten bigger, adjust to compensate
+		try{
+		if (ownerWindow==null)
+			return;
+		int contentHeight = h - ownerWindow.infoBarHeight - ownerWindow.explanationHeight - ownerWindow.annotationHeight;
+		if (iC!=null)
+			iC.setBounds(0, ownerWindow.infoBarHeight, w,  contentHeight);
+		if (graphics!=null)
+			for (int i=0; i<graphics.length; i++){
+				if (graphics[i]!=null) {
+					graphics[i].setBounds(0, 0, w, contentHeight);
+					graphics[i].doLayout();
+				}
+			}
+		if (text!=null)
+			for (int i=0; i<text.length; i++){
+				if (text[i]!=null)
+					text[i].setBounds(0, 0, w, contentHeight);
+			}
+		if (infoBar!=null)
+			infoBar.setBounds(0, 0, w,ownerWindow.infoBarHeight);
+		if (explanationArea!=null)
+			explanationArea.setBounds(0, ownerWindow.infoBarHeight + contentHeight + ownerWindow.annotationHeight, w, ownerWindow.explanationHeight);
+		if (annotationArea!=null)
+			annotationArea.setBounds(0, ownerWindow.infoBarHeight + contentHeight, w, ownerWindow.annotationHeight);
+		doLayout(); //added 18Mar02
+		}
+		catch (NullPointerException e){ //may happen if in process of disposing window
+		}
+	}
+	/*.................................................................................................................*/
+	/** Sets the size of this and the content areas within it */
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		try{
+		if (ownerWindow==null)
+			return;
+		int contentHeight = h - ownerWindow.infoBarHeight - ownerWindow.explanationHeight -ownerWindow.annotationHeight;
+		if (iC!=null)
+			iC.setSize(w,contentHeight);
+		if (graphics!=null)
+			for (int i=0; i<graphics.length; i++){
+				if (graphics[i]!=null) {
+					graphics[i].setSize(w,contentHeight);
+					graphics[i].doLayout();
+				}
+			}
+		if (text!=null)
+			for (int i=0; i<text.length; i++){
+				if (text[i]!=null) {
+					text[i].setSize(w,contentHeight);
+					text[i].doLayout();
+				}
+			}
+		if (infoBar!=null) {
+			infoBar.setSize(w,ownerWindow.infoBarHeight);
+			infoBar.doLayout();
+		}
+			if (explanationArea!=null)
+				explanationArea.setSize(w, ownerWindow.explanationHeight);
+			if (annotationArea!=null)
+				annotationArea.setSize(w, ownerWindow.annotationHeight);
+			doLayout(); //added 18Mar02
+		}
+		catch (NullPointerException e){
+		}
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/OutputFilePathModifier.java b/Source/mesquite/lib/OutputFilePathModifier.java
new file mode 100644
index 0000000..27253ac
--- /dev/null
+++ b/Source/mesquite/lib/OutputFilePathModifier.java
@@ -0,0 +1,7 @@
+package mesquite.lib;
+
+public interface OutputFilePathModifier {
+
+	public String[] modifyOutputPaths(String[] outputFilePaths); 
+
+}
diff --git a/Source/mesquite/lib/OutputFileProcessor.java b/Source/mesquite/lib/OutputFileProcessor.java
new file mode 100644
index 0000000..99d0836
--- /dev/null
+++ b/Source/mesquite/lib/OutputFileProcessor.java
@@ -0,0 +1,23 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public interface OutputFileProcessor extends OutputFilePathModifier {
+	
+	public void processOutputFile(String[] outputFilePaths, int fileNum);
+	
+	public void processCompletedOutputFiles(String[] outputFilePaths);
+	
+
+}
diff --git a/Source/mesquite/lib/OwnedByModule.java b/Source/mesquite/lib/OwnedByModule.java
new file mode 100644
index 0000000..5c37aae
--- /dev/null
+++ b/Source/mesquite/lib/OwnedByModule.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is owned by a module*/
+public interface OwnedByModule {
+ 	public MesquiteModule getOwnerModule();
+}
+
diff --git a/Source/mesquite/lib/PanelOfCards.java b/Source/mesquite/lib/PanelOfCards.java
new file mode 100644
index 0000000..b4f8452
--- /dev/null
+++ b/Source/mesquite/lib/PanelOfCards.java
@@ -0,0 +1,159 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+
+
+/*===============================================*/
+/** a field for longs */
+public abstract class PanelOfCards extends Panel  {
+	ExtensibleDialog dialog;
+	Panel addPanel = null;
+	Panel oldAddPanel = null;
+	Panel choicePanel;
+	Panel cardPanel = null;
+	CardPanel card = null;
+	CardLayout cardLayout = new CardLayout();
+	int currentCard = 0;
+	int numCards = 0;
+	protected String name;
+	GridBagLayout cardPanelLayout;
+	GridBagConstraints cardPanelConstraints;
+
+	PanelOfCards (ExtensibleDialog dialog, String name){
+		super();
+		this.dialog = dialog;
+		this.name = name;
+//		oldAddPanel = dialog.getAddPanel();
+
+		cardPanelLayout = new GridBagLayout();
+		cardPanelConstraints = new GridBagConstraints();
+		cardPanelConstraints.gridx=0;
+		cardPanelConstraints.gridy = GridBagConstraints.RELATIVE;
+		cardPanelConstraints.gridwidth=1;
+		cardPanelConstraints.gridheight=1;
+		cardPanelConstraints.ipadx=4;
+		cardPanelConstraints.ipadx=1;
+		cardPanelConstraints.weightx=1;
+		cardPanelConstraints.weighty=1;
+		cardPanelConstraints.fill=GridBagConstraints.BOTH;
+		cardPanelConstraints.anchor=GridBagConstraints.CENTER;
+		cardPanelLayout.setConstraints(this,cardPanelConstraints);
+		this.setLayout(cardPanelLayout);
+
+		choicePanel = new Panel();
+		add(choicePanel,cardPanelConstraints);
+
+		cardPanel = new Panel();
+		add(cardPanel,cardPanelConstraints);
+
+		cardLayout = new CardLayout();
+		cardPanel.setLayout(cardLayout);
+
+		installChoicePanel(choicePanel);
+		dialog.nullifyAddPanel();
+	}
+	/*.................................................................................................................*/
+	public LayoutManager getCardLayout () {
+		return cardLayout;
+	}
+	/*.................................................................................................................*/
+	public LayoutManager getCardPanelLayout () {
+		return cardPanelLayout;
+	}
+	/*.................................................................................................................*/
+	public Panel getCardPanel () {
+		return cardPanel;
+	}
+	/*.................................................................................................................*/
+	public void showCard (int item) {
+		cardLayout.first(cardPanel);
+		if (item>0)
+			for (int i=0; i<item; i++)
+				cardLayout.next(cardPanel);
+		//cardLayout.show(cardPanel, Integer.toString(item));
+		MesquiteWindow.invalidateAll(cardPanel);
+		cardPanel.validate();
+		cardPanel.doLayout();
+		//cardLayout.layoutContainer(cardPanel);
+		cardLayout.invalidateLayout(cardPanel);
+	}
+	/*.................................................................................................................*/
+	public abstract void installChoicePanel (Panel choicePanel) ;
+	/*.................................................................................................................*/
+	public abstract void addChoice (String s) ;
+	/*.................................................................................................................*
+	public abstract void prepareChoicePanel (Panel choicePanel) ;
+	/*.................................................................................................................*
+	public abstract void cleanEmptyChoice (Panel choicePanel) ;
+	/*.................................................................................................................*
+	public abstract void createChoicePanel (Panel choicePanel) ;
+	/*.................................................................................................................*/
+	public Panel addNewCard (String title) {
+		String cardTitle =Integer.toString(numCards);
+		PoCPanel newPanel = new PoCPanel();  //the new panel
+		cardPanel.add(newPanel, cardTitle);
+		cardLayout.addLayoutComponent(newPanel, cardTitle);
+		addChoice(title);
+
+	//	if (numCards==0)
+	//		showCard(0);
+		numCards++;
+		return newPanel;
+	}
+
+
+	/*.................................................................................................................*
+	public void finalizeCards () {
+		if (getComponentCount()<=1) { //there is only one card; don't need tabs
+			cleanEmptyChoice(choicePanel);
+			remove(choicePanel);
+		}
+		else
+			createChoicePanel(choicePanel);
+		dialog.setAddPanel(oldAddPanel);
+	}
+	/*.................................................................................................................*
+	public void newCard (String title, String cardTitle) {
+		prepareNewCard();
+    		card =new CardPanel();
+    		finalizeNewCard(title, cardTitle);
+	}
+	/*.................................................................................................................*
+	public void prepareNewCard () {
+		if (card!=null && (card.getComponentCount()==0))  //then it is an empty card, get rid of it
+			remove(card);
+		dialog.setAddPanel(this);
+	}
+	/*.................................................................................................................*
+	public void finalizeNewCard (String title, String cardTitle) {
+    		add(cardTitle, card);
+    		card.setName(cardTitle);
+     		card.setLayout(dialog.getGridBagLayout());
+		dialog.setAddPanel(card);
+		//dialog.addLabel(title);
+	}
+	 */
+}
+
+
+class PoCPanel extends Panel {
+	public Dimension getPreferredSize(){
+		return new Dimension(500, 500);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/PanelsAtNodes.java b/Source/mesquite/lib/PanelsAtNodes.java
new file mode 100644
index 0000000..609815a
--- /dev/null
+++ b/Source/mesquite/lib/PanelsAtNodes.java
@@ -0,0 +1,235 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class PanelsAtNodes  {
+	protected MesquiteModule ownerModule;
+	protected int numNodes;
+	protected Panel[] panels;
+	protected TreeDisplay treeDisplay;
+	private boolean[] inTree;
+	private boolean[] shown;
+	
+	public PanelsAtNodes(MesquiteModule ownerModule, int numNodes, TreeDisplay treeDisplay){
+		this.ownerModule = ownerModule;
+		this.numNodes = numNodes;
+		this.treeDisplay = treeDisplay;
+		panels=new Panel[numNodes];
+		shown=new boolean[numNodes];
+		inTree=new boolean[numNodes];
+
+		for (int i=0; i<numNodes; i++) {
+			panels[i]=makePanel(i);
+			shown[i]=true;
+			inTree[i]=false;
+			
+			if (treeDisplay!= null)
+				treeDisplay.addPanelPlease(panels[i]);
+			if (panels[i]!=null)
+				panels[i].setVisible(false);
+			
+	
+		}
+	}
+	
+	public abstract Panel makePanel(int i);
+	
+	public TreeDisplay getTreeDisplay(){
+		return treeDisplay;
+	}
+	public void setTreeDisplay(TreeDisplay treeDisplay){
+		if (treeDisplay == this.treeDisplay)
+			return;
+		for (int i=0; i<numNodes; i++) {
+			if (this.treeDisplay!=null)
+				this.treeDisplay.removePanelPlease(getPanel(i));
+			treeDisplay.addPanelPlease(getPanel(i));
+		}
+		this.treeDisplay = treeDisplay;
+	}
+	
+	public void resetNumNodes(int numNodes){
+		for (int i=0; i<this.numNodes; i++) {
+ 			Panel p =getPanel(i);
+			if (p!= null) {
+				p.setVisible(false);
+				if (treeDisplay!=null)
+					treeDisplay.removePanelPlease(p);
+			}
+		}
+		this.numNodes = numNodes;
+		panels=new Panel[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			panels[i]=makePanel(i);
+			if (treeDisplay != null)
+				treeDisplay.addPanelPlease(panels[i]);
+			panels[i].setVisible(true);
+		}
+	}
+ 	public void hideAllPanels(){
+ 		for (int i=0; i<numNodes; i++) {
+ 			Panel p =getPanel(i);
+ 			if (p != null) {
+				shown[i]=false;
+				if (p.isVisible())
+					p.setVisible(false);
+			}
+		}
+ 	}
+ 	public void showAllPanels(){
+ 		for (int i=0; i<numNodes; i++) {
+ 			Panel p =getPanel(i);
+ 			if (p !=null) {
+				shown[i]=true;
+				if (!p.isVisible())
+					p.setVisible(true);
+			}
+		}
+ 	}
+ 	public void toggleShowPanel(int i){
+ 		//check if legal!!!
+ 		Panel p =getPanel(i);
+		if (p!=null) {
+			shown[i]=!shown[i];
+			p.setVisible(shown[i]);
+		}
+ 	}
+ 	public void showPanel(int i){
+ 		//check if legal!!!
+ 		Panel p =getPanel(i);
+		if (p!=null) {
+			if (!p.isVisible())
+				p.setVisible(true);
+			shown[i]=true;
+		}
+ 	}
+ 	public void hidePanel(int i){
+ 		Panel p =getPanel(i);
+		if (p!=null) {
+			shown[i]=false;
+			if (p.isVisible())
+				p.setVisible(false);
+		}
+ 	}
+ 	public void toggleShowPanel(Panel panel){
+ 		for (int i=0; i<numNodes; i++) {
+ 			Panel p =getPanel(i);
+ 			if (p == panel) {
+				shown[i]=!shown[i];
+				p.setVisible(shown[i]);
+				return;
+			}
+			
+		}
+ 	}
+ 	public void hidePanel(Panel panel){
+ 		for (int i=0; i<numNodes; i++) {
+ 			Panel p =getPanel(i);
+ 			if (p == panel) {
+				shown[i]=false;
+				if (p.isVisible())
+					p.setVisible(false);
+				return;
+			}
+			
+		}
+ 	}
+ 	public void showPanel(Panel panel){
+ 		for (int i=0; i<numNodes; i++) {
+ 			Panel p =getPanel(i);
+ 			if (p == panel) {
+				shown[i]=true;
+				if (!p.isVisible())
+					p.setVisible(true);
+				return;
+			}
+			
+		}
+ 	}
+	/*.................................................................................................................*/
+	public   void repaintPanels(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				repaintPanels(tree, d);
+				
+		int nodeX = treeDisplay.getTreeDrawing().x[node];
+		int nodeY = treeDisplay.getTreeDrawing().y[node];
+		Panel p = getPanel(node);
+		if (p!=null) {
+			p.repaint(); 
+		}
+		
+	}
+	/*.................................................................................................................*/
+	private void recShowPanels(Tree tree, int N) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				recShowPanels(tree, d);
+		inTree[N]=true;
+	}
+	/*.................................................................................................................*/
+	public void showPanels(Tree tree, int drawnRoot) {
+		for (int i=0; i<inTree.length; i++)
+			inTree[i]=false;
+		recShowPanels(tree, drawnRoot);
+		int count =0;
+		for (int i=0; i<inTree.length; i++) {
+			if (!inTree[i] || !shown[i]) {
+		 		Panel p =getPanel(i);
+				if (p!=null && p.isVisible()) 
+					p.setVisible(false);
+			}
+			else {
+		 		Panel p =getPanel(i);
+				if (p!=null && !p.isVisible()) 
+					p.setVisible(true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void locatePanels(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				locatePanels(tree, d);
+				
+		int nodeX = treeDisplay.getTreeDrawing().x[node];
+		int nodeY = treeDisplay.getTreeDrawing().y[node];
+		Panel p = getPanel(node);
+		if (p!=null){
+			if  ((p.getLocation()==null) || ((p.getLocation().x!=nodeX) || (p.getLocation().y!=nodeY)))
+				p.setLocation(nodeX, nodeY);  //only do if moved
+		}
+		
+	}
+	public void dispose() {
+		for (int i=0; i<numNodes; i++) {
+			Panel C = getPanel(i);
+			
+			if (C!=null) {
+				treeDisplay.removePanelPlease(C);
+			}
+			panels[i] = null;
+		}
+	}
+	public Panel getPanel(int N) {
+		if (N<0 || N>= panels.length)
+			return null;
+		return panels[N];
+	}
+	public int getNumNodes() {
+		return numNodes;
+	}
+}
+
diff --git a/Source/mesquite/lib/ParametersDialog.java b/Source/mesquite/lib/ParametersDialog.java
new file mode 100644
index 0000000..7d93fff
--- /dev/null
+++ b/Source/mesquite/lib/ParametersDialog.java
@@ -0,0 +1,215 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+/*===============================================*/
+/** An extensible dialog box containing a list with standard buttons.  */
+public class ParametersDialog extends ExtensibleDialog implements ItemListener {
+	MesquiteParameter[] parameters;
+	Checkbox[] boxes;
+	DoubleField[] min, max, value;
+	Choice[] constraintMenu;
+//	int[] constraints;
+	boolean usingSelection = false;
+	int minSelect, maxSelect;
+	int[] selectionAge;
+	boolean[] selected;
+	int age = 0;
+	boolean showRange; 
+	/*.................................................................................................................*/
+	public ParametersDialog (MesquiteWindow parent, String title, String label, MesquiteParameter[] parameters, boolean[] selected, int minSelect, int maxSelect, boolean showRange) {
+		super(parent, title, new MesquiteInteger());
+		this.parameters  = parameters;
+		this.selected = selected;
+		this.showRange = showRange;
+		if (selected !=null){
+			boxes = new Checkbox[parameters.length];
+			selectionAge = new int[parameters.length];
+			usingSelection = true;
+		}
+		min = new DoubleField[parameters.length];
+		max = new DoubleField[parameters.length];
+		value = new DoubleField[parameters.length];
+		constraintMenu = new Choice[parameters.length];
+		/*
+		 * 		constraints = new int[parameters.length];
+			for (int i= 0; i<parameters.length; i++) {
+				if (parameters[i].getConstrainedTo() == null) 
+					constraints[i] = i;
+		}
+		 */
+		if (label != null)
+			addLabel(label);
+		this.minSelect = minSelect;
+		this.maxSelect = maxSelect;
+		for (int i=0; i<parameters.length; i++){
+			if (selected !=null && i < selected.length && selected.length>1 && minSelect<parameters.length){
+				boxes[i] = addCheckBox(parameters[i].getName(), selected[i]);
+				if (selected[i])
+					selectionAge[i] = age++;
+				boxes[i].addItemListener(this);
+			}
+			else {
+				addLabel(parameters[i].getName());
+			}
+			suppressNewPanel();
+			value[i] = addDoubleField("Current Value: ", parameters[i].getValue(), 10, parameters[i].getMinimumAllowed(), parameters[i].getMaximumAllowed());
+			value[i].setDigits(6);
+			value[i].setPermitUnassigned(true);
+			if (showRange){
+				suppressNewPanel();
+				min[i] = addDoubleField("Min: ", parameters[i].getMinimumSuggested(), 6, parameters[i].getMinimumAllowed(), parameters[i].getMaximumAllowed());
+				suppressNewPanel();
+				max[i] = addDoubleField("Max: ", parameters[i].getMaximumSuggested(), 6, parameters[i].getMinimumAllowed(), parameters[i].getMaximumAllowed());
+			}
+			//	if (parameters[i].getConstrainedTo()!= null){
+			suppressNewPanel();
+			String[] constraintNames = new String[parameters.length];
+			for (int k = 0; k<parameters.length; k++)
+				if (k == i)
+					constraintNames [k]= "-";
+				else
+					constraintNames[k] = parameters[k].getName();
+			int constraint = i;
+			if (parameters[i].getConstrainedTo()!= null)
+				constraint = whichParameter(parameters[i].getConstrainedTo());
+			constraintMenu[i] = addPopUpMenu ("Constrain = ", constraintNames, constraint); 
+			constraintMenu[i].addItemListener(this);
+
+			//		}
+			if (!StringUtil.blank(parameters[i].getExplanation())){
+				addLabel (parameters[i].getExplanation(), Label.LEFT);
+			}
+			addHorizontalLine(1);
+		}
+
+	}
+	int whichParameter(MesquiteParameter p){
+		for (int i=0; i<parameters.length; i++){
+			if (p == parameters[i])
+				return i;
+		}
+		return -1;
+	}
+	void constraintChosen(int i, int chosen){
+		if (i == chosen)
+			parameters[i].setConstrainedTo(null, false);
+		else {
+			parameters[i].setConstrainedTo(parameters[chosen], true);
+		}
+	}
+	public void acceptParameters(){
+		for (int i=0; i<parameters.length; i++){
+
+			parameters[i].setValue(value[i].getValue());
+				if (showRange){
+				parameters[i].setMinimumSuggested(min[i].getValue());
+				if (max[i].getValue()<min[i].getValue())
+					max[i].setValue(min[i].getValue());
+				parameters[i].setMaximumSuggested(max[i].getValue());
+			}
+			constraintChosen(i, constraintMenu[i].getSelectedIndex());
+		}
+
+	}
+
+	int getNumSelected(){
+		if (!usingSelection || selected == null)
+			return 0;
+		int count = 0;
+		for (int i=0; i<selected.length; i++){
+			if (selected[i])
+				count++;
+		}
+		return count;
+	}
+	int getOldest(boolean selectedYes){
+		if (!usingSelection)
+			return -1;
+		int min = age+1;
+		int oldest = 0;
+		for (int i=0; i<selectionAge.length; i++){
+			if (selected[i]==selectedYes && selectionAge[i] < min){
+				min = selectionAge[i];
+				oldest = i;
+			}
+		}
+		return oldest;
+	}
+
+	void expandSelectToMin(int changed){
+
+		while (getNumSelected()<minSelect && getNumSelected() < selected.length){
+			int oldest = getOldest(false);
+			dontListen = true;
+			boxes[oldest].setState(true);
+			selected[oldest] = true;
+			selectionAge[oldest] = age++;
+			dontListen = false;
+		}
+	}
+	void contractSelectToMax(int changed){		
+		while (getNumSelected()>maxSelect && (getNumSelected()> 0)){
+			int oldest = getOldest(true);
+			dontListen = true;
+			boxes[oldest].setState(false);
+			selected[oldest] = false;
+			//selectionAge[oldest] = 0;
+			dontListen = false;
+		}
+
+	}
+	boolean dontListen = false;
+	/*.................................................................................................................*/
+	public void itemStateChanged(ItemEvent e){
+		if (e.getItemSelectable() instanceof Choice){
+			for (int i=0; i< constraintMenu.length; i++){
+				if (e.getItemSelectable() == constraintMenu[i]){
+					constraintChosen(i, constraintMenu[i].getSelectedIndex());
+				}
+			}
+		}
+
+		if (!usingSelection || dontListen){
+
+			return;
+		}
+
+		for (int i=0; i<boxes.length; i++){
+			if (e.getItem().equals(boxes[i].getLabel())){
+
+				if (boxes[i].getState())
+					selectionAge[i] = age++;
+				selected[i] = boxes[i].getState();
+				int num = getNumSelected();
+
+				if (num< minSelect)
+					expandSelectToMin(i);
+				else if(num > maxSelect)
+					contractSelectToMax(i);
+
+				return;
+			}
+		}
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/lib/ParametersExplorable.java b/Source/mesquite/lib/ParametersExplorable.java
new file mode 100644
index 0000000..88a40db
--- /dev/null
+++ b/Source/mesquite/lib/ParametersExplorable.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+/* ======================================================================== */
+/**Interface for object to claim it has parameters that can be explored for the value they produce; e.g., a likelihood calculator.*/
+public interface ParametersExplorable {
+	/** Returns a list of the currently settable parameters and their current values. */
+ 	public MesquiteParameter[] getExplorableParameters();
+ 	
+ 	public double calculate(MesquiteString resultString);
+ 	
+ 	public void restoreAfterExploration();
+ 	
+ 
+ 	
+}
+
diff --git a/Source/mesquite/lib/ParseUtil.java b/Source/mesquite/lib/ParseUtil.java
new file mode 100644
index 0000000..8e4bd98
--- /dev/null
+++ b/Source/mesquite/lib/ParseUtil.java
@@ -0,0 +1,662 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ��������������������������� parse util ������������������������������� */
+/* this probably should move to a NEXUS library
+/* ======================================================================== */
+/** A set of string parsing methods.  Should be renamed StringParser or NEXUSParser.*/
+public class ParseUtil extends StringUtil {
+//TODO: these should be protected against string overruns
+
+	private static String getQuoted(String line, MesquiteInteger startChar) {
+		if (line==null)
+			return null;
+		StringBuffer temp = new StringBuffer(line.length());
+		char c;
+		boolean done = false;
+		while (!done) {
+			int where = startChar.getValue();
+			if (where<line.length()) {
+				c= line.charAt(where);
+				if (c==defaultQuote){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt==defaultQuote) {
+							temp.append(defaultQuote);
+							startChar.increment();  //skip to \'
+							startChar.increment(); //skip to next
+						}
+						else 
+							done = true;
+					}
+					else done = true;
+				}
+				else if (c=='^'){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt=='n') {
+							temp.append('\n');
+							startChar.increment();  //skip to \n
+							startChar.increment(); //skip to next
+						}
+						else if (nxt=='r') {
+							temp.append('\r');
+							startChar.increment();  //skip to \n
+							startChar.increment(); //skip to next
+						}
+						else
+							startChar.increment();  //skip to next
+					}
+					else done = true;
+				}
+				else {
+					temp.append(c);
+					startChar.increment();
+				}
+			}
+			else
+				done = true;
+			
+		}
+		startChar.increment();
+		return temp.toString();
+	}
+	/*.........................................................................................................*/
+	/*  doesn't replace '' by ' */
+	static String getQuotedUnaltered(String line, MesquiteInteger startChar) {
+		if (line==null)
+			return null;
+		StringBuffer temp = new StringBuffer(line.length());
+		char c;
+		boolean done = false;
+		while (!done) {
+			int where = startChar.getValue();
+			if (where<line.length()) {
+				c= line.charAt(where);
+				if (c==defaultQuote){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt==defaultQuote) {
+							temp.append('\'');
+							temp.append('\'');
+							startChar.increment();  //skip to \'
+							startChar.increment(); //skip to next
+						}
+						else 
+							done = true;
+					}
+					else done = true;
+				}
+				else {
+					temp.append(c);
+					startChar.increment();
+				}
+			}
+			else
+				done = true;
+			
+		}
+		startChar.increment();
+		return temp.toString();
+	}
+	/*.........................................................................................................*/
+	/** returns remainder of line starting at startChar; including square bracket comments*/
+	public static String getRemaining(String line, MesquiteInteger startChar) {
+		if (line == null)
+			return null;
+		else
+			return line.substring(startChar.getValue(), line.length());
+	}
+
+	/*............................................  ....................................................*/
+	/** returns first token from string; sets pos to end of token; excluding square bracket comments*/
+	public static String getFirstToken(String line, MesquiteInteger pos) {
+		if (pos == null)
+			pos = new MesquiteInteger(0);
+		else
+			pos.setValue(0);
+		return getToken(line, pos);
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at startChar; excluding square bracket comments*/
+	public static String getToken(String line, MesquiteInteger startChar) {
+		return getToken(line, startChar, (String)null, (String)null);
+	}
+	/*.................................................................................................................*/
+	public static char charOnDeck(String line, MesquiteInteger pos, int ahead) {
+		int posTemp = pos.getValue() +ahead;
+		if (posTemp>=line.length()) {
+			return 0;
+		}
+		return line.charAt(posTemp);
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at startChar; excluding square bracket comments*/
+	public static String getToken(String line, MesquiteInteger startChar, String whitespaceString, String punctuationString) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		 if (startChar.getValue() >= line.length())
+			return null;
+		StringBuffer temp = new StringBuffer(100); //better to pass from outside
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(line, startChar), whitespaceString))
+				;
+			if (punctuation(c, punctuationString)) {
+				continu = false;
+				if (c == defaultQuote) {
+					temp.setLength(0);
+					temp.append(getQuoted(line, startChar));
+				}
+				else if (c == '-') {
+					char cod = charOnDeck(line, startChar, 1);
+					char cod2 = charOnDeck(line, startChar, 2);
+					if (("0123456789".indexOf(cod)>=0)||(cod=='.' && ("0123456789".indexOf(cod2)>=0))) {
+						temp.append(c);
+						c=getNextChar(line, startChar);
+						continu = true;
+					}
+					else {
+						temp.append(c);
+					}
+				}
+				else
+					temp.append(c);
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuation(c, punctuationString)) && c!=0) {
+					if (c=='_')
+						c = ' ';
+					temp.append(c);
+					c=getNextChar(line, startChar);
+				}
+				if (punctuation(c, punctuationString)) {
+					startChar.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			startChar.setValue(line.length());
+			}
+		return temp.toString();
+	}
+	/*.........................................................................................................*/
+	/** returns token from line starting at startChar; excluding square bracket comments*
+	public static String getUnalteredToken(String line, MesquiteInteger startChar, boolean includeWhitespace) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		 if (startChar.getValue() >= line.length())
+			return null;
+		StringBuffer temp = new StringBuffer(100); //better to pass from outside
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(line, startChar), null))
+				if (includeWhitespace)
+					temp.append(c);
+			if (punctuation(c, null)) {
+				continu = false;
+				if (c == defaultQuote) {
+					temp.setLength(0);
+					temp.append(defaultQuote);
+					temp.append(getQuotedUnaltered(line, startChar));
+					temp.append(defaultQuote);
+				}
+				else if (c == '-') {
+					char cod = charOnDeck(line, startChar, 1);
+					char cod2 = charOnDeck(line, startChar, 2);
+					if (("0123456789".indexOf(cod)>=0)||(cod=='.' && ("0123456789".indexOf(cod2)>=0))) {
+						temp.append(c);
+						c=getNextChar(line, startChar);
+						continu = true;
+					}
+					else {
+						temp.setLength(0);
+						temp.append(c);
+					}
+				}
+				else {
+					temp.setLength(0);
+					temp.append(c);
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, null) && !punctuation(c, null)) && c!=0) {
+					temp.append(c);
+					c=getNextChar(line, startChar);
+				}
+				if (punctuation(c, null)) {
+					startChar.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			startChar.setValue(line.length());
+			}
+		if (blank(temp)) 
+			return null;
+		return temp.toString();
+	}
+	/*.........................................................................................................*/
+	/** returns token from line starting at startChar; keeps track of pending square bracket closure, etc.*
+	public static String getUnalteredToken(String line, MesquiteInteger startChar, boolean includeWhitespace, MesquiteInteger pendingBrackets, StringBuffer comment) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		 if (startChar.getValue() >= line.length())
+			return null;
+		StringBuffer temp = new StringBuffer(100); //better to pass from outside
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(line, startChar, pendingBrackets, comment), null))  //skipping whitespace in front
+				if (includeWhitespace)
+					temp.append(c);
+			if (punctuation(c, null)) {
+				continu = false;
+				if (c == defaultQuote) {
+					temp.setLength(0);
+					temp.append(defaultQuote);
+					temp.append(getQuotedUnaltered(line, startChar));
+					temp.append(defaultQuote);
+				}
+				else if (c == '-') {
+					char cod = charOnDeck(line, startChar, 1);
+					char cod2 = charOnDeck(line, startChar, 2);
+					if (("0123456789".indexOf(cod)>=0)||(cod=='.' && ("0123456789".indexOf(cod2)>=0))) {
+						temp.append(c);
+						c=getNextChar(line, startChar, pendingBrackets, comment);
+						continu = true;
+					}
+					else {
+						temp.setLength(0);
+						temp.append(c);
+					}
+				}
+				else {
+					temp.setLength(0);
+					temp.append(c);
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, null) && !punctuation(c, null)) && c !=0) {
+					temp.append(c);
+					c=getNextChar(line, startChar, pendingBrackets, comment);
+				}
+				if (punctuation(c, null)) {
+					startChar.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 1");
+			startChar.setValue(line.length());
+			}
+		if (blank(temp)) 
+			return null;
+		return temp.toString();
+	}
+	/*.................................................................................................................*/
+	/** returns token from line starting at startChar; keeps track of pending square bracket closure, etc.*
+	public static String getToken(String line, MesquiteInteger startChar, MesquiteInteger pendingBrackets, StringBuffer comment) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		 if (startChar.getValue() >= line.length())
+			return null;
+		StringBuffer temp = new StringBuffer(100); //better to pass from outside
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(line, startChar, pendingBrackets, comment), null))  //skipping whitespace in front
+				;
+			if (punctuation(c, null)) {
+				continu = false;
+				if (c == defaultQuote) {
+					temp.setLength(0);
+					temp.append(getQuoted(line, startChar));
+				}
+				else if (c == '-') {
+					char cod = charOnDeck(line, startChar, 1);
+					char cod2 = charOnDeck(line, startChar, 2);
+					if (("0123456789".indexOf(cod)>=0)||(cod=='.' && ("0123456789".indexOf(cod2)>=0))) {
+						temp.append(c);
+						c=getNextChar(line, startChar, pendingBrackets, comment);
+						continu = true;
+					}
+					else {
+						temp.append(c);
+					}
+				}
+				else
+					temp.append(c);
+			}
+			if (continu) {
+				while ((!whitespace(c, null) && !punctuation(c, null)) && c !=0) {
+					if (c=='_')
+						c = ' ';
+					temp.append(c);
+					c=getNextChar(line, startChar, pendingBrackets, comment);
+				}
+				if (punctuation(c, null)) {
+					startChar.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 1");
+			startChar.setValue(line.length());
+			}
+		return temp.toString();
+	}
+	/*.................................................................................................................*/
+	public static boolean darkBeginsWithIgnoreCase(String s, String find){
+		//cycle through s until darkspace hit; 
+		//then go in parallel through s and find to see if the characters are equivalent 
+		
+		if (s==null || find == null)
+			return false;
+		int sIndex = 0;
+		while (sIndex < s.length() && whitespace(s.charAt(sIndex), null))
+			sIndex++;
+		if (sIndex == s.length())
+			return false;
+		int fIndex = 0;
+		while (sIndex < s.length() && fIndex<find.length()) {
+			if (Character.toUpperCase(s.charAt(sIndex))!=Character.toUpperCase(find.charAt(fIndex)))
+				return false;
+			sIndex++;
+			fIndex++;
+		}
+		if (fIndex== find.length()) //got to end with not problem
+			return true;
+		return false;
+		
+	}
+	/*.................................................................................................................*/
+	public static boolean darkBeginsWithIgnoreCase(StringBuffer s, String find){
+		//cycle through s until darkspace hit; 
+		//then go in parallel through s and find to see if the characters are equivalent 
+		
+		if (s==null || find == null)
+			return false;
+		int sIndex = 0;
+		while (sIndex < s.length() && whitespace(s.charAt(sIndex), null))
+			sIndex++;
+		if (sIndex == s.length())
+			return false;
+		int fIndex = 0;
+		while (sIndex < s.length() && fIndex<find.length()) {
+			if (Character.toUpperCase(s.charAt(sIndex))!=Character.toUpperCase(find.charAt(fIndex)))
+				return false;
+			sIndex++;
+			fIndex++;
+		}
+		if (fIndex== find.length()) //got to end with not problem
+			return true;
+		return false;
+		
+	}
+	/*.................................................................................................................*
+	static char getNextChar(String s, MesquiteInteger current, MesquiteInteger pendingBrackets, StringBuffer comment) {
+		int pos = current.getValue();
+		if (pos>=s.length()) {
+			return 0;
+		}
+		char c = s.charAt(pos);
+		pos++;
+		int debt = pendingBrackets.getValue();
+		
+		boolean hadBrack = false;
+		if (openingSquareBracket(c)) {
+			if (debt>0)
+				if (comment!=null) comment.append(c);
+			debt++;
+		}
+		else if (closingSquareBracket(c)) {
+			if (debt>0){
+				debt--;
+				if (debt>0)
+					if (comment!=null) comment.append(c);
+			}
+			c=0;
+		}
+		else if (debt>0)
+			if (comment!=null) comment.append(c);
+		while  (debt>0 && pos< s.length()) {
+			c=s.charAt(pos);
+			hadBrack=true;
+			if (openingSquareBracket(c)) {
+				if (debt>0)
+					if (comment!=null) comment.append(c);
+				debt++;
+			}
+			else if (closingSquareBracket(c)) {
+				if (debt>0){
+					debt--;
+					if (debt>0)
+						if (comment!=null) comment.append(c);
+				}
+				c=0;
+			}
+			else if (debt>0)
+				if (comment!=null) comment.append(c);
+			pos++;
+		}
+		pendingBrackets.setValue(debt);
+		current.setValue(pos);
+		if (pos>s.length())
+			c=0;
+		else if (hadBrack) {
+			return getNextChar(s, current,pendingBrackets, comment);
+		}
+		return c;
+	}
+	
+	/*.................................................................................................................*/
+	static char getNextChar(String s, MesquiteInteger current) {
+		int pos = current.getValue();
+		if (pos>=s.length()) {
+			return 0;
+		}
+		char c = s.charAt(pos);
+		pos++;
+		int debt = 0;
+		boolean hadBrack = false;
+		if (openingSquareBracket(c))
+			debt++;
+		while  (debt>0 && pos< s.length()) {
+			c=s.charAt(pos);
+			hadBrack = true;
+			if (openingSquareBracket(c)) {
+				debt++;
+			}
+			else if (closingSquareBracket(c)) {
+				if (debt>0)
+					debt--;
+				c=0;
+			}
+			pos++;
+		}
+		current.setValue(pos);
+		if (pos>s.length())
+			c=0;
+		else if (hadBrack) {
+			return getNextChar(s, current);
+		}
+		return c;
+	}
+	/*.................................................................................................................*/
+	public static String getTokenNumber(String s, MesquiteInteger startChar, int tokenNumber) {
+			if (startChar==null)
+				startChar= new MesquiteInteger(0);
+			else
+				startChar.setValue(0);
+			String token=null;
+			for (int i=1; i<= tokenNumber; i++)
+				token = getToken(s, startChar);
+			return token;
+	}
+	/*.................................................................................................................*/
+	public static String getTokens(String s, MesquiteInteger startChar, int first, int last) {
+			if (startChar==null)
+				startChar= new MesquiteInteger(0);
+			else
+				startChar.setValue(0);
+			String token=null;
+			for (int i=1; i<= first; i++)
+				token = getToken(s, startChar);
+			String tokens = null;
+			if (token !=null) {
+				tokens = tokenize(token);
+				for (int i=first+1; i<= last; i++)
+					tokens += tokenize(getToken(s, startChar));
+			}
+			return tokens;
+	}
+	/*.................................................................................................................*/
+	public static String[][] getSubcommands(String s, MesquiteInteger startChar) {
+			if (startChar==null)
+				startChar= new MesquiteInteger(0);
+			int startValue = startChar.getValue();
+			String token= getToken(s, startChar); //subcommandName
+			int count =0;
+			boolean scan = false;
+			while (token !=null && !token.equals(";")) {
+				token = getToken(s, startChar); //=
+					
+				if (token !=null && !token.equals(";")) {
+					token = getToken(s, startChar); //subcommandParameters
+					if (token != null && token.equals("-")){
+						scan = true;
+						int current = startChar.getValue();
+						String nextToken = getToken(s, startChar); //rest of negative number?
+						try {
+							double d = Double.valueOf(nextToken).doubleValue();
+							token = token +  nextToken; //rest of negative number
+						}
+						catch (NumberFormatException e) {
+							startChar.setValue(current);  // was just lone -, so back up for next token
+						}
+					}
+					count++;
+				}
+				
+				token = getToken(s, startChar); //subcommandName
+			}
+			if (count==0)
+				return null;
+			String[][] strings = new String[2][count];
+			startChar.setValue(startValue);
+			for (int i=0; i< count; i++) {
+				strings[0][i] = getToken(s, startChar); //subcommandName
+				token = getToken(s, startChar); //=
+				token = getToken(s, startChar); //subcommandParameters
+				if (token != null && token.equals("-")){
+					int current = startChar.getValue();
+					String nextToken = getToken(s, startChar); //rest of negative number?
+					try {
+						double d = Double.valueOf(nextToken).doubleValue();
+						token = token +  nextToken; //rest of negative number
+					}
+					catch (NumberFormatException e) {
+						startChar.setValue(current);  // was just lone -, so back up for next token
+					}
+					//token = token + getToken(s, startChar); //rest of negative number
+				}
+				strings[1][i] = token; 
+			}
+			
+			return strings;
+	}
+	/*.................................................................................................................*/
+	public static void skipComment(String line, MesquiteInteger startChar) {
+		try {
+			int index = startChar.getValue();
+			char c;
+			while ((c = line.charAt(index)) != ']') {
+				if (c=='[') {
+					startChar.setValue(index);
+					skipComment(line, startChar);
+					index=startChar.getValue()-1;
+				} 
+				index++;
+			}
+			index++;
+			startChar.setValue(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {}
+	}
+	/*.................................................................................................................*/
+	public static void skipToDarkspace(String line, MesquiteInteger startChar) {
+		try {
+			int index = startChar.getValue();
+			while (whitespace(line.charAt(index), null))
+				index++;
+			startChar.setValue(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			startChar.setValue(line.length());
+		}
+	}
+	/*.................................................................................................................*/
+	public static char nextDarkChar(String line, MesquiteInteger startChar) {
+		try {
+			int index = startChar.getValue();
+			while (whitespace(line.charAt(index), null))
+				index++;
+			char dark =line.charAt(index);
+			startChar.setValue(++index);
+			if (whitespace(dark, null))
+				return '\0';
+			else
+				return dark;
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			startChar.setValue(line.length());
+		}
+		return '\0';
+	}
+	/*.................................................................................................................*/
+	public static char firstDarkChar(String line) {
+		try {
+			int index = 0;
+			while (whitespace(line.charAt(index), null))
+				index++;
+			return line.charAt(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {}
+		return '\0';
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/lib/Parser.java b/Source/mesquite/lib/Parser.java
new file mode 100644
index 0000000..ea6ce91
--- /dev/null
+++ b/Source/mesquite/lib/Parser.java
@@ -0,0 +1,1533 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ======================================================================== */
+/** A class for parsing strings for NEXUS files and commands.*/
+public class Parser extends StringUtil {
+	StringBuffer buffer, buffer2;
+	StringBuffer commandBuffer;
+	String whitespaceString = null;
+	String whitespaceStringSet = null;
+	String punctuationString = null;
+	String punctuationStringSet = null;
+	String lineEndString = null;
+	String lineEndStringSet = null;
+	static char openCommentBracket = '[';
+	static char closeCommentBracket = ']';
+	public static boolean allowComments = true;
+	char quoteChar = defaultQuote;
+	boolean lineEndingsDark = false;
+	MesquiteInteger pos;
+	boolean hyphensArePartOfNumbers = true;
+	StringBuffer line = new StringBuffer(1000);
+	public Parser(){
+		pos = new MesquiteInteger(0);
+		buffer = new StringBuffer(100); 
+		buffer2 = new StringBuffer(100); 
+		openCommentBracket = '[';
+		closeCommentBracket = ']';
+		allowComments = true;
+
+	}
+	public Parser(String line){
+		this();
+		setString(line);
+	}
+	public void setString(String s){
+		if (s == null)
+			s = "";
+		line.setLength(0);
+		line.append(s);
+		pos.setValue(0);
+	}
+	/*this causes the passed buffer to be used.  Danger is that the Parser is later subject to this buffer's external chagnes.
+	thus, call resetBufferToLocal afterward to make Parser behave normally */
+	public void setBuffer(StringBuffer s){
+		if (s == null)
+			return;
+		line = s;
+		pos.setValue(0);
+	}
+	public void resetBufferToLocal(){
+		line = new StringBuffer(1000);
+	}
+	public StringBuffer getBuffer(){
+		return line;
+	}
+	public String getString(){
+		if (line == null)
+			return null;
+		return line.toString();
+	}
+	public boolean blank(){
+		if (line == null)
+			return true;
+		if (line.length() == 0)
+			return true;
+		for (int i=0; i< line.length(); i++)
+			if (!whitespace(line.charAt(i)))
+				return false;
+		return true;
+	}
+	public boolean atEnd(){
+		return pos.getValue()>=line.length();
+	}
+	public int getPosition(){
+		return pos.getValue();
+	}
+	public void setPosition(int p){
+		pos.setValue(p);
+	}
+	public String getlineEndString(){
+		return lineEndString;
+	}
+	public void setLineEndString(String s){
+		if (s==null){
+			lineEndString = defaultLineEnd;
+			lineEndStringSet = null;
+		}
+		else {
+			lineEndString = s;
+			lineEndStringSet = s;
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean lineEndCharacter(char c) {
+		if (c<0)
+			return true;
+		if (c==0)
+			return false;  
+		if (lineEndString!=null)
+			return lineEndString.indexOf(c)>=0;
+			return defaultLineEnd.indexOf(c)>=0;
+	}
+
+	public String getWhitespaceString(){
+		return whitespaceString;
+	}
+	public void setWhitespaceString(String s){
+		if (s==null){
+			whitespaceString = defaultWhitespace;
+			whitespaceStringSet = null;
+		}
+		else {
+			whitespaceString = s;
+			whitespaceStringSet = s;
+		}
+		if (lineEndingsDark){
+			if (whitespaceString ==null)
+				whitespaceString = StringUtil.defaultWhitespace;
+			whitespaceString = StringUtil.delete(whitespaceString, '\n');
+			whitespaceString = StringUtil.delete(whitespaceString, '\r');
+		}
+	}
+	public boolean getLineEndingsDark(){
+		return lineEndingsDark;
+	}
+	public void setLineEndingsDark(boolean b){
+		lineEndingsDark = b;
+		if (lineEndingsDark){
+			if (whitespaceString ==null)
+				whitespaceString = StringUtil.defaultWhitespace;
+			whitespaceString = StringUtil.delete(whitespaceString, '\n');
+			whitespaceString = StringUtil.delete(whitespaceString, '\r');
+			if (punctuationString == null)
+				punctuationString = defaultPunctuationPlusLB;
+			else {
+				if (punctuationString.indexOf('\n')<0)
+					punctuationString = punctuationString + '\n';
+				if (punctuationString.indexOf('\r')<0)
+					punctuationString = punctuationString + '\r';
+			}
+		}
+		else {
+			whitespaceString =  whitespaceStringSet;
+			punctuationString = punctuationStringSet;
+		}
+	}
+	public void addToDefaultPunctuationString(String s){
+		if (s==null)
+			return;
+		punctuationString = defaultPunctuation+s;
+		punctuationStringSet = defaultPunctuation+s;
+		if (lineEndingsDark){
+			if (punctuationString.indexOf('\n')<0)
+				punctuationString = punctuationString + '\n';
+			if (punctuationString.indexOf('\r')<0)
+				punctuationString = punctuationString + '\r';
+		}
+	}
+
+	public void setPunctuationString(String s){
+		if (s==null){
+			punctuationStringSet = null;
+			if (lineEndingsDark)
+				punctuationString = defaultPunctuationPlusLB;
+			else
+				punctuationString = defaultPunctuation;
+
+		}
+		else {
+			punctuationString = s;
+			punctuationStringSet = s;
+			if (lineEndingsDark){
+				if (punctuationString == null)
+					punctuationString = defaultPunctuationPlusLB;
+				else {
+					if (punctuationString.indexOf('\n')<0)
+						punctuationString = punctuationString + '\n';
+					if (punctuationString.indexOf('\r')<0)
+						punctuationString = punctuationString + '\r';
+				}
+			}
+		}
+	}
+	public void setPunctuationStringRaw(String s){
+		if (s==null){
+			punctuationStringSet = null;
+			punctuationString = null;
+		}
+		else {
+			setPunctuationString(s);
+		}
+	}
+	public String getPunctuationString (){
+		return punctuationString;
+	}
+	private String getQuoted() {
+		if (line==null)
+			return null;
+		buffer2.setLength(0);
+		char c;
+		boolean done = false;
+		while (!done) {
+			int where = pos.getValue();
+			if (where<line.length()) {
+				c= line.charAt(where);
+				if (c==quoteChar){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt==quoteChar) {
+							buffer2.append(quoteChar);
+							pos.increment();  //skip to \'
+							pos.increment(); //skip to next
+						}
+						else 
+							done = true;
+					}
+					else done = true;
+				}
+				else if (c=='^'){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt=='n') {
+							buffer2.append('\n');
+							pos.increment();  //skip to \n
+							pos.increment(); //skip to next
+						}
+						else if (nxt=='r') { 
+							buffer2.append('\n');  //translated for windows
+							pos.increment();  //skip to \r
+							pos.increment(); //skip to next
+						}
+						else {
+							pos.increment(); //skip to next
+						}
+					}
+					else done = true;
+				}
+				else {
+					buffer2.append(c);
+					pos.increment();
+				}
+			}
+			else
+				done = true;
+
+		}
+		pos.increment();
+		return buffer2.toString();
+	}
+	/*.........................................................................................................*/
+	/*  doesn't replace '' by ' */
+	private StringBuffer getQuotedUnaltered(StringBuffer buf) {
+		if (line==null)
+			return null;
+		buf.setLength(0);
+		char c;
+		boolean done = false;
+		while (!done) {
+			int where = pos.getValue();
+			if (where<line.length()) {
+				c= line.charAt(where);
+				if (c==quoteChar){
+					int np = where + 1;
+					if (np<line.length()) {
+						char nxt= line.charAt(np);
+						if (nxt==quoteChar) {
+							buf.append('\'');
+							buf.append('\'');
+							pos.increment();  //skip to \'
+							pos.increment(); //skip to next
+						}
+						else 
+							done = true;
+					}
+					else done = true;
+				}
+				else {
+					buf.append(c);
+					pos.increment();
+				}
+			}
+			else
+				done = true;
+
+		}
+		pos.increment();
+		return buf;
+	}
+	/*.........................................................................................................*/
+	/** returns remainder of line starting at pos; including square bracket comments*/
+	public String getRemaining() {
+		if (line == null)
+			return null;
+		else if (pos.getValue()<0 || line.length() == 0)
+			return null;
+		else
+			return line.toString().substring(pos.getValue(), line.length());
+	}
+
+	public void setQuoteCharacter(char c){
+		quoteChar = c;
+	}
+	public void setNoQuoteCharacter(){
+		quoteChar = (char)0;
+	}
+	/*............................................  ....................................................*/
+	/** if first character of string is a quote ('), takes to contents of the quote and returns them (calling getFirstToken).
+	Otherwise returns the string*/
+	public String getUnquotedToken() {
+		if (line == null || line.length()==0 || line.charAt(0)!= quoteChar)
+			return line.toString();
+		else
+			return getFirstToken(line.toString());
+	}
+	/*............................................  ....................................................*/
+	/** returns first token from string; sets pos to end of token; excluding square bracket comments*/
+	public String getFirstToken(StringBuffer s) {
+		setBuffer(s);
+		pos.setValue(0);
+		return getNextToken();
+	}
+	/*............................................  ....................................................*/
+	/** returns first token from string; sets pos to end of token; excluding square bracket comments*/
+	public String getFirstToken(String line) {
+		setString(line);
+		pos.setValue(0);
+		return getNextToken();
+	}
+	/*............................................  ....................................................*/
+	/** returns first token from string; afterward sets pos to end of token; excluding square bracket comments*/
+	public String getFirstToken() {
+		pos.setValue(0);
+		return getNextToken();
+	}
+	/*............................................  ....................................................*/
+	/** returns first index of occurence of target token; useful to find if token is in string*/
+	public int tokenIndexOfIgnoreCase(String line, String target) {
+		if (target == null || line == null)
+			return -1;
+		setString(line);
+		pos.setValue(0);
+		String token = null;
+		int count = 0;
+		while ((token = getNextToken()) != null){
+			if (target.equalsIgnoreCase(token))
+				return count;
+			count++;
+		}
+		return -1;
+	}
+	/*............................................  ....................................................*/
+	/** returns first index of occurence of target token; useful to find if token is in string*/
+	public int tokenIndex(String line, String target) {
+		if (target == null || line == null)
+			return -1;
+		setString(line);
+		pos.setValue(0);
+		String token = null;
+		int count = 0;
+		while ((token = getNextToken()) != null){
+			if (target.equals(token))
+				return count;
+			count++;
+		}
+		return -1;
+	}
+	/*............................................  ....................................................*/
+	/** returns characters from pos to first instance of c*/
+	public String getRemainingUntilChar(char stopChar) {
+		return getRemainingUntilChar(stopChar,false);
+	}
+	/*............................................  ....................................................*/
+	/** returns characters from pos to first instance of c*/
+	public String getRemainingUntilChar(char stopChar, boolean skipPast) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c=getNextChar();
+		buffer.setLength(0);
+		while (c!=stopChar && pos.getValue()<line.length()) {  // or should this be <= line.length?
+			buffer.append(c);
+			c=getNextChar();
+		}
+		if (c!=stopChar)
+			buffer.append(c);
+		if (c==stopChar && !skipPast)
+			setPosition(getPosition()-1);
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	/** returns characters from pos to first instance of any character in stopChars */
+	public String getRemainingUntilChars(String stopChars, boolean skipPast) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c=getNextChar();
+		buffer.setLength(0);
+		while (stopChars.indexOf(c)<0 && pos.getValue()<line.length()) {  // or should this be <= line.length?
+			buffer.append(c);
+			c=getNextChar();
+		}
+		if (stopChars.indexOf(c)<0)
+			buffer.append(c);
+		if (stopChars.indexOf(c)>=0 && !skipPast)
+			setPosition(getPosition()-1);
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	public boolean lineEndsAreDefaults() {
+		return (lineEndString==null || defaultLineEnd.equals(lineEndString));
+	}
+	/*............................................  ....................................................*/
+	/** returns characters from pos to first instance of \r or \n*/
+	public String getRawNextLine() {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c=getNextChar();
+		buffer.setLength(0);
+
+		while (!lineEndCharacter(c) && pos.getValue()<=line.length() && c!=(char)0) {  
+			buffer.append(c);
+			c=getNextChar();
+		}
+		if (c=='\r' && lineEndsAreDefaults()) {
+			int pos = getPosition();
+			c=getNextChar();
+			if (c!='\n')   // if the next char is a newline, we want to go past it; otherwise, step back
+				setPosition(pos);
+		}
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	/** returns n characters from pos */
+	public String getPiece(int n) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c=getNextChar();
+		buffer.setLength(0);
+		
+		int count = 0;
+		while (count++< n && pos.getValue()<=line.length() && c!=(char)0) {  
+			buffer.append(c);
+			c=getNextChar();
+		}
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	/** returns n characters from pos */
+	public String getPieceOfLine(int n) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c=getNextChar();
+		buffer.setLength(0);
+		
+		int count = 0;
+		while (count++< n && !lineEndCharacter(c) &&  pos.getValue()<=line.length() && c!=(char)0) {  
+			buffer.append(c);
+			c=getNextChar();
+		}
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	/** returns characters from pos to first instance of \r or \n*/
+	public String getRawNextDarkLine() {
+		String s = "";
+		while (StringUtil.blank(s) && pos.getValue() <  line.length())
+			s = getRawNextLine();
+		return s;
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getLastToken() {
+		String s = getFirstToken();
+		String sLast = s;
+		while (!StringUtil.blank(s)) {
+			sLast = s;
+			s = getNextToken();
+		}
+		return sLast;
+	}
+	/*............................................  ....................................................*/
+	/** returns the position just before the last token */
+	public int getPosBeforeLastToken() {
+		String s = getFirstToken();
+		int lastPos = 0;
+		int prevPos=0;
+		while (!StringUtil.blank(s)) {
+			prevPos=lastPos;
+			lastPos=pos.getValue();
+			s = getNextToken();
+		}
+		return prevPos;
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getNextTrimmedToken() {
+		String s = getNextToken();
+		if (s!=null)
+			return s.trim();
+		return null;
+	}
+	/*............................................  ....................................................*/
+	int startOfToken;
+	public int getStartOfPreviousToken(){
+		return startOfToken;
+	}
+	private void recordStartOfToken(){
+		if (!MesquiteInteger.isCombinable(startOfToken))
+			startOfToken = pos.getValue()-1;
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getNextToken() {
+		startOfToken = MesquiteInteger.unassigned;
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		char c;
+		buffer.setLength(0);
+		startOfToken = MesquiteInteger.unassigned;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(), whitespaceString))
+				;
+			if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+				continu = false;
+				if (c == quoteChar) {
+					buffer.setLength(0);
+					recordStartOfToken();
+					buffer.append(getQuoted());
+				}
+				else if (c == '-' && hyphensArePartOfNumbers) {
+					char cod = charOnDeck(1);
+					char cod2 = charOnDeck(2);
+					if ((digits.indexOf(cod)>=0)||(cod=='.' && (digits.indexOf(cod2)>=0))) {
+						recordStartOfToken();
+						buffer.append(c);
+						c=getNextChar();
+						continu = true;
+					}
+					else {
+						recordStartOfToken();
+						buffer.append(c);
+					}
+				}
+				else{
+					recordStartOfToken();
+					buffer.append(c);
+				}
+				if (lineEndCharacter(c)) {
+					char r = charOnDeck(1);
+					//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+					if (r!=c && lineEndCharacter(r))
+						pos.increment();
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuationOrQuote(c, punctuationString, quoteChar)) && c!=0) {
+					if (c=='_')
+						c = ' ';
+					else if (c=='^'){
+						char nxt = getNextChar();
+						if (nxt=='n') 
+							c='\n';
+						else if (nxt=='r') 
+							c='\n'; //translated for windows
+					}
+					recordStartOfToken();
+					buffer.append(c);
+					c=getNextChar();
+				}
+				if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+					pos.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			startOfToken = MesquiteInteger.unassigned;
+			pos.setValue(line.length());
+		}
+		return buffer.toString();
+	}
+	/*.........................................................................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getUnalteredToken(boolean includeWhitespace) {
+		startOfToken = MesquiteInteger.unassigned;
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		buffer.setLength(0);
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(), whitespaceString))
+				if (includeWhitespace){
+					recordStartOfToken();
+					buffer.append(c);
+				}
+			if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+				continu = false;
+				if (c == quoteChar) {
+					buffer.setLength(0);
+					recordStartOfToken();
+					buffer.append(quoteChar);
+					buffer.append(getQuotedUnaltered(buffer2).toString());
+					buffer.append(quoteChar);
+				}
+				else if (c == '-'  && hyphensArePartOfNumbers) {
+					char cod = charOnDeck(1);
+					char cod2 = charOnDeck(2);
+					if ((digits.indexOf(cod)>=0)||(cod=='.' && (digits.indexOf(cod2)>=0))) {
+						recordStartOfToken();
+						buffer.append(c);
+						c=getNextChar();
+						continu = true;
+					}
+					else {
+						buffer.setLength(0);
+						recordStartOfToken();
+						buffer.append(c);
+					}
+				}
+				else {
+					buffer.setLength(0);
+					recordStartOfToken();
+					buffer.append(c);
+				}
+				if (lineEndCharacter(c)) {
+					char r = charOnDeck(1);
+					//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+					if (r!=c && lineEndCharacter(r))
+						pos.increment();
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuationOrQuote(c, punctuationString, quoteChar)) && c!=0) {
+					recordStartOfToken();
+					buffer.append(c);
+					c=getNextChar();
+				}
+				if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+					pos.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			pos.setValue(line.length());
+			startOfToken = MesquiteInteger.unassigned;
+		}
+		if (blankByCurrentWhitespace(buffer)) 
+			return null;
+		return buffer.toString();
+	}
+	/*.........................................................................................................*/
+	/** returns token from line starting at pos; keeps track of pending square bracket closure, etc.*/
+	public String getUnalteredToken(boolean includeWhitespace, MesquiteInteger pendingBrackets, StringBuffer comment, MesquiteBoolean suppressComment) {
+		startOfToken = MesquiteInteger.unassigned;
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		buffer.setLength(0);
+
+		char c = 0;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(pendingBrackets, comment, suppressComment), whitespaceString))  //skipping whitespace in front
+				if (includeWhitespace){
+					recordStartOfToken();
+					buffer.append(c);
+				}
+			if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+				continu = false;
+				if (c == quoteChar) {
+					buffer.setLength(0);
+					recordStartOfToken();
+					buffer.append(quoteChar);
+					buffer.append(getQuotedUnaltered(buffer2).toString());
+					buffer.append(quoteChar);
+				}
+				else if (c == '-' && hyphensArePartOfNumbers) {
+					char cod = charOnDeck(1);
+					char cod2 = charOnDeck(2);
+					if ((digits.indexOf(cod)>=0)||(cod=='.' && (digits.indexOf(cod2)>=0))) {
+						recordStartOfToken();
+						buffer.append(c);
+						c=getNextChar(pendingBrackets, comment, suppressComment);
+						continu = true;
+					}
+					else {
+						buffer.setLength(0);
+						recordStartOfToken();
+						buffer.append(c);
+					}
+				}
+				else {
+					buffer.setLength(0);
+					recordStartOfToken();
+					buffer.append(c);
+				}
+				if (lineEndCharacter(c)) {
+					char r = charOnDeck(1);
+					//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+					if (r!=c && lineEndCharacter(r)) {
+						pos.increment();
+					}
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuationOrQuote(c, punctuationString, quoteChar)) && c !=0) {
+					recordStartOfToken();
+					buffer.append(c);
+					c=getNextChar(pendingBrackets, comment, suppressComment);
+				}
+				if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+					pos.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 1");
+			startOfToken = MesquiteInteger.unassigned;
+			pos.setValue(line.length());
+		}
+		if (blankByCurrentWhitespace(buffer)) 
+			return null;
+		return buffer.toString();
+	}
+	/*.........................................................................................................*/
+	/** Fills StringBuffer with token from line starting at pos; keeps track of pending square bracket closure, etc.  Returns false if null string to be returned*/
+	public boolean getUnalteredToken(StringBuffer token, boolean includeWhitespace, MesquiteInteger pendingBrackets, StringBuffer comment, MesquiteBoolean suppressComment) {
+		startOfToken = MesquiteInteger.unassigned;
+		if (token == null)
+			return false;
+		token.setLength(0);
+		if (line==null)
+			return false;
+		if (pos.getValue() >= line.length())
+			return false;
+		if (line.equals(""))
+			return true;
+
+		char c = 0;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(pendingBrackets, comment, suppressComment), whitespaceString))  //skipping whitespace in front
+				if (includeWhitespace){
+					recordStartOfToken();
+					token.append(c);
+				}
+			if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+				continu = false;
+				if (c == quoteChar) {
+					token.setLength(0);
+					recordStartOfToken();
+					token.append(quoteChar);
+					/*�*/StringUtil.append(token, getQuotedUnaltered(buffer2));
+					token.append(quoteChar);
+				}
+				else if (c == '-' && hyphensArePartOfNumbers) {
+					char cod = charOnDeck(1);
+					char cod2 = charOnDeck(2);
+					if ((digits.indexOf(cod)>=0)||(cod=='.' && (digits.indexOf(cod2)>=0))) {
+						recordStartOfToken();
+						token.append(c);
+						c=getNextChar(pendingBrackets, comment, suppressComment);
+						continu = true;
+					}
+					else {
+						token.setLength(0);
+						recordStartOfToken();
+						token.append(c);
+					}
+				}
+				else {
+					token.setLength(0);
+					recordStartOfToken();
+					token.append(c);
+				}
+				if (lineEndCharacter(c)) {
+					char r = charOnDeck(1);
+					//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+					if (r!=c && lineEndCharacter(r)) {
+						pos.increment();
+					}
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuationOrQuote(c, punctuationString, quoteChar)) && c !=0) {
+					recordStartOfToken();
+					token.append(c);
+					c=getNextChar(pendingBrackets, comment, suppressComment);
+				}
+				if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+					pos.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 1");
+			startOfToken = MesquiteInteger.unassigned;
+			pos.setValue(line.length());
+		}
+		if (blankByCurrentWhitespace(token)) 
+			return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns token from line starting at pos; keeps track of pending square bracket closure, etc.*/
+	public String getToken(MesquiteInteger pendingBrackets, StringBuffer comment, MesquiteBoolean suppressComment) {
+		startOfToken = MesquiteInteger.unassigned;
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		if (pos.getValue() >= line.length())
+			return null;
+		buffer.setLength(0);
+		char c;
+		try {
+			boolean continu = true;
+			while (whitespace(c=getNextChar(pendingBrackets, comment, suppressComment), whitespaceString))  //skipping whitespace in front
+				;
+			if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+				continu = false;
+				if (c == quoteChar) {
+					recordStartOfToken();
+					buffer.append(getQuoted());
+				}
+				else if (c == '-' && hyphensArePartOfNumbers) {
+					char cod = charOnDeck(1);
+					char cod2 = charOnDeck(2);
+					if ((digits.indexOf(cod)>=0)||(cod=='.' && (digits.indexOf(cod2)>=0))) {
+						recordStartOfToken();
+						buffer.append(c);
+						c=getNextChar(pendingBrackets, comment, suppressComment);
+						continu = true;
+					}
+					else {
+						recordStartOfToken();
+						buffer.append(c);
+					}
+				}
+				else {
+					recordStartOfToken();
+					buffer.append(c);
+				}
+				if (lineEndCharacter(c)) {
+					char r = charOnDeck(1);
+					//if next character is also lineEndCharacter but of opposite sort (i.e. \n instead of \r) then eat it up
+					if (r!=c && lineEndCharacter(r)) {
+						pos.increment();
+					}
+				}
+			}
+			if (continu) {
+				while ((!whitespace(c, whitespaceString) && !punctuationOrQuote(c, punctuationString, quoteChar)) && c !=0) {
+					if (c=='_')
+						c = ' ';
+					recordStartOfToken();
+					buffer.append(c);
+					c=getNextChar(pendingBrackets, comment, suppressComment);
+				}
+				if (punctuationOrQuote(c, punctuationString, quoteChar)) {
+					pos.decrement();
+				}
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 1");
+			startOfToken = MesquiteInteger.unassigned;
+			pos.setValue(line.length());
+		}
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	public boolean hasFileReadingArgument(String arguments, String target){
+		String fRA = getFirstToken(arguments);
+		while (!StringUtil.blank(fRA)) {
+			if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + target))
+				return true;
+			fRA = getNextToken();
+		}
+		return false;
+	}
+	/*............................................  ....................................................*/
+	/** returns next XML starttag element name.  Returns attributes in MesquiteString attributes.  If it is an empty element (ending in /) or a processing instruction (bounded by ?) that too is returned in the arguments.*/
+	//TODO: does this deal with escaped characters?
+	public String getNextXMLTag(MesquiteInteger startPos, MesquiteString attributes, MesquiteBoolean isEmptyElement, MesquiteBoolean isProcessingInstruction, MesquiteBoolean isEndTag) {
+		if (line==null)
+			return null;
+		else if (line.equals(""))
+			return "";
+		String s2 = line.toString();
+		if (pos.getValue() >= line.length())
+			return null;
+		char c;
+		boolean processedFirst = false;
+		if (isEmptyElement!=null) 
+			isEmptyElement.setValue(false);
+		if (isProcessingInstruction!=null) 
+			isProcessingInstruction.setValue(false);
+		if (isEndTag!=null) 
+			isEndTag.setValue(false);
+		boolean isProcessing = false;
+		boolean isEnd=false;
+		buffer.setLength(0);
+		StringBuffer attributesBuffer = new StringBuffer();
+		boolean withinAttributes = false;
+		try {
+			while ((c=getNextChar())!='<')  //exit once we have found '<'
+				if (pos.getValue()>=line.length()) {
+					return "";
+				}
+			if (startPos!=null)
+				startPos.setValue(pos.getValue()-1);
+			while ((c=getNextChar())!='>' && pos.getValue()<line.length()){ //now we are in the tag
+				if (!processedFirst){  //examine the first character in the tag
+					processedFirst=true;
+					if (isProcessingInstruction!=null) 
+						isProcessingInstruction.setValue(c=='?');
+					if (isEndTag!=null) 
+						isEndTag.setValue(c=='/');
+					isProcessing=c=='?';
+					isEnd =c=='/';
+					if (!isProcessing && !isEnd)
+						buffer.append(c);
+				}
+				else if (c=='/' && isEmptyElement!=null) {
+					isEmptyElement.setValue(true);
+				}
+				else if (!withinAttributes) {
+					if (whitespace(c))
+						withinAttributes = true;
+					else 
+						buffer.append(c);
+				}
+				attributesBuffer.append(c);
+			}
+
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			pos.setValue(line.length());
+		}
+		if (attributes!=null)
+			attributes.setValue(attributesBuffer.toString());
+		return buffer.toString();
+	}
+	/*............................................  ....................................................*/
+	/** checks to see if the contained String from the attributes string of an XML tag has an attribute called attribute with a value called value */
+	public static boolean attributesContains(String attributes, String attribute, String value) {
+		Parser parser = new Parser(attributes);
+		parser.setPunctuationString("=\"");
+		String token = parser.getNextToken();
+		while (!StringUtil.blank(token)) {
+			if (attribute.equalsIgnoreCase(token)) {
+				token = parser.getNextToken();  //=
+				token = parser.getNextToken(); //"
+				token = parser.getNextToken();
+				if (value.equalsIgnoreCase(token))
+					return true;
+				token = parser.getNextToken(); //"
+			}
+			token = parser.getNextToken();
+		} 
+		return false;
+	}
+	/*............................................  ....................................................*/
+	/** returns next tag in <>*/
+	public String getNextXMLTag(MesquiteInteger startPos) {
+		return getNextXMLTag(startPos,null,null,null,null);
+	}
+	/*............................................  ....................................................*/
+	/** returns next tag in <>*/
+	public String getNextXMLTag() {
+		return getNextXMLTag(null,null,null,null,null);
+	}
+	/*............................................  ....................................................*/
+	/** checks to see if the contained String is an XML document */
+	public boolean isXMLDocument(boolean rememberPosition) {
+		int oldPos = getPosition();
+		setPosition(0);
+		MesquiteBoolean isProcessingElement = new MesquiteBoolean(false);
+		String tag = getNextXMLTag(null,null,null, isProcessingElement,null);   
+		if (rememberPosition)
+			setPosition(oldPos);
+		return (isProcessingElement.getValue() && tag.startsWith("xml"));  
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getNextXMLTaggedContent(MesquiteString tag, MesquiteString attributes) {
+		MesquiteBoolean isEmptyElement = new MesquiteBoolean(false);
+		MesquiteBoolean isProcessingElement = new MesquiteBoolean(false);
+		MesquiteBoolean isEndTag = new MesquiteBoolean(false);   //utilize this!!!
+		String s = getNextXMLTag(null,attributes,isEmptyElement, isProcessingElement,isEndTag);  // get start tag
+		tag.setValue(s);
+		if (isEndTag.getValue() || isProcessingElement.getValue() || isEmptyElement.getValue())
+			return null;
+		String endTag = s;
+		String nextTag;
+		int startPos = pos.getValue();
+		if (startPos>=line.length()) {
+			return null;
+		}
+
+		MesquiteInteger endPos = new MesquiteInteger(startPos);
+		try {
+			while (!endTag.equalsIgnoreCase(nextTag=getNextXMLTag(endPos,null,null,null,isEndTag)) && !StringUtil.blank(nextTag)) {//get end tag
+				if (!isEndTag.getValue())
+					;  //complain
+			}
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			System.out.println("string bounds exceeded 0");
+			pos.setValue(line.length());
+			endPos.setValue(line.length());
+		}
+		if (endPos.getValue()<=startPos)
+			return null;
+		else
+			return line.substring(startPos,endPos.getValue());
+	}
+	/*............................................  ....................................................*/
+	/** returns token from line starting at pos; excluding square bracket comments*/
+	public String getNextXMLTaggedContent(MesquiteString tag) {
+		return getNextXMLTaggedContent(tag,null);
+	}
+	/*............................................  ....................................................*/
+	/** checks for tag, and resets parser to be for the contained text*/
+	public boolean resetToXMLTagContents(String searchTag) {
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent = getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(nextTag.getValue())) {
+			if (searchTag.equalsIgnoreCase(nextTag.getValue())) {
+				setString(tagContent);  // reset this parser so that it is for the mesquite root tag contents
+				return true;
+			}
+			tagContent = getNextXMLTaggedContent(nextTag);
+		}
+		return false;
+	}
+	/*............................................  ....................................................*/
+	/** checks for root Mesquite tag, and resets parser to be for the contained text*/
+	public boolean resetToMesquiteTagContents() {
+		return resetToXMLTagContents("mesquite");
+	}
+	/*.................................................................................................................*/
+	private boolean storeCharToComment(String c, int debt, StringBuffer comment, MesquiteBoolean suppressComment){
+		if (debt >0 && comment!=null && !suppressComment.getValue()) {
+			comment.append(c);
+			return true;
+		}
+		else
+			return false;
+	}
+	/*.................................................................................................................*/
+	private boolean storeCharToComment(char c, int debt, StringBuffer comment, MesquiteBoolean suppressComment){
+		if (debt >0 && comment!=null && !suppressComment.getValue()) {
+			comment.append(c);
+			return true;
+		}
+		else
+			return false;
+	} 
+	/*.................................................................................................................*/
+	public void setCharAt(char c, int position) {
+		if (( position>0) && (position<line.length()))
+			line.setCharAt(position-1, c); 
+	}
+	/*.................................................................................................................*/
+
+	int pendingPComment = 0;
+	/*.................................................................................................................*/
+	char getNextChar(MesquiteInteger pendingBrackets, StringBuffer comment, MesquiteBoolean suppressComment) {
+		int posTemp = pos.getValue();
+		if (posTemp>=line.length()) {
+			return 0;
+		}
+		char c = line.charAt(posTemp);
+		posTemp++;
+		int debt = pendingBrackets.getValue();
+		boolean hadBrack = false;
+		boolean checkExclamation = false;
+		if (openingCommentBracket(c)) {
+			if (posTemp>= line.length()) //c was last character of line, therefore add space as workaround for line-ending "["
+				line.append(' ');
+
+			char next = 0;
+			if (posTemp<line.length())
+				next = line.charAt(posTemp);
+			if (debt==0 && (next == '%')) { 
+				c = '<';
+				posTemp++; //done to go past %
+				line.setCharAt(posTemp-1, c); //done in case punctuation passed back will cause pos to decrement
+				pendingPComment = 1;
+			}
+			else {
+				if (!storeCharToComment(c, debt, comment, suppressComment))
+					checkExclamation = true;
+				if (comment !=null && comment.length()>0)
+					comment.append(' ');
+				debt++;
+			}
+
+		}
+		else if (closingCommentBracket(c)) {
+			if (comment!=null)
+				comment.append("$1");
+			if (debt==0 && pendingPComment >0) {
+				c = '>';
+				line.setCharAt(posTemp-1, c); //done in case punctuation passed back will cause pos to decrement
+				pendingPComment = 0;
+			}
+			else {
+				if (debt>0){
+					debt--;
+					storeCharToComment(c, debt, comment, suppressComment);
+					if (debt ==0)
+						suppressComment.setValue(false);
+				}
+				c=0;
+			}
+		}
+		else 
+			storeCharToComment(c, debt, comment, suppressComment);
+		int count = 0;
+		while  (debt>0 && posTemp< line.length()) {
+			count++;
+			c=line.charAt(posTemp);
+			if (!whitespace(c) && count == 1 && checkExclamation){
+				if (checkExclamation && debt ==1)
+					if (c != '!' && c!= '&')
+						suppressComment.setValue(true);
+				checkExclamation = false;
+			}
+			hadBrack=true;
+			if (openingCommentBracket(c)) {
+				if (posTemp+1== line.length()) //c was last character of line, therefore add space as workaround for line-ending "["
+					line.append(' ');
+				storeCharToComment(c, debt, comment, suppressComment);
+				debt++;
+			}
+			else if (closingCommentBracket(c)) {
+				if (comment!=null)
+					comment.append("$2");
+				if (debt>0){
+					debt--;
+					storeCharToComment(c, debt, comment, suppressComment);
+					if (debt ==0)
+						suppressComment.setValue(false);
+				}
+				c=0;
+			}
+			else storeCharToComment(c, debt, comment, suppressComment);
+			posTemp++;
+		}
+		if (posTemp>=line.length()) {
+			storeCharToComment(StringUtil.lineEnding(), debt, comment, suppressComment);
+		}
+		pendingBrackets.setValue(debt);
+		pos.setValue(posTemp);
+		if (posTemp>line.length())
+			c=0;
+		else if (hadBrack) {
+			return getNextChar(pendingBrackets, comment, suppressComment);
+		}
+		return c;
+	}
+
+	/*.................................................................................................................*/
+	public char charOnDeck(int ahead) {
+		int posTemp = pos.getValue() +ahead;
+		if (posTemp>=line.length()) {
+			return 0;
+		}
+		return line.charAt(posTemp);
+	}
+	/*.................................................................................................................*/
+	public char getNextChar() {
+		int posTemp = pos.getValue();
+		if (posTemp>=line.length()) {
+			return 0;
+		}
+		char c = line.charAt(posTemp);
+		posTemp++;
+		int debt = 0;
+		boolean hadBrack = false;
+		if (openingCommentBracket(c)){
+			if (posTemp>= line.length()) //%% c was last character of line, therefore add space as workaround for line-ending "["
+				line.append(' ');
+			debt++;
+		}
+		while  (debt>0 && posTemp< line.length()) {
+			c=line.charAt(posTemp);
+			hadBrack = true;
+			if (openingCommentBracket(c)) {
+				if (posTemp+1>= line.length()) //%% c was last character of line, therefore add space as workaround for line-ending "["
+					line.append(' ');
+				debt++;
+			}
+			else if (closingCommentBracket(c)) {
+
+				if (debt>0)
+					debt--;
+				c=0;
+			}
+			posTemp++;
+		}
+		pos.setValue(posTemp);
+		if (posTemp>line.length())
+			c=0;
+		else if (hadBrack) {
+			return getNextChar();
+		}
+		return c;
+	}
+	/*.................................................................................................................*/
+	public String getTokenNumber(String s, int tokenNumber) {
+		setString(s);
+		return getTokenNumber(tokenNumber);
+	}
+	/*.................................................................................................................*/
+	public String getTokenNumber(int tokenNumber) {
+		pos.setValue(0);
+		String token=null;
+		for (int i=1; i<= tokenNumber; i++)
+			token = getNextToken();
+		return token;
+	}
+	/*.................................................................................................................*/
+	public String getTokens(String s, int first, int last) {
+		setString(s);
+		return getTokens(first, last);
+	}
+	/*.................................................................................................................*/
+	public String getTokens(int first, int last) {
+		pos.setValue(0);
+		String token=null;
+		for (int i=1; i<= first; i++)
+			token = getNextToken();
+		String tokens = null;
+		if (token !=null) {
+			tokens = StringUtil.tokenize(token);
+			for (int i=first+1; i<= last; i++)
+				tokens += StringUtil.tokenize(getNextToken());
+		}
+		return tokens;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTokens(String s) {
+		setString(s);
+		return getNumberOfTokens();
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTokens() {
+		pos.setValue(0);
+		return getNumberOfTokensRemaining();
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTokensRemaining() {
+		int oldPos = pos.getValue();
+		String token=null;
+		int count=0;
+		do {
+			token = getNextToken();
+			if (token!=null)
+				count++;
+		} while (token!=null);
+		pos.setValue(oldPos);
+		return count;
+	}
+	/*.................................................................................................................*/
+	/** returns in String the next "number" dark characters */
+	public String getNextDarkChars(int number) {
+		char c;
+		StringBuffer b = new StringBuffer(number);
+		for (int i = 1; i<=number && getPosition()<line.length(); i++) {
+			c=nextDarkChar();
+			b.append(c);
+		}
+		return b.toString();
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfSpecifiedCharRemaining(char theChar) {
+		char c=' ';
+		int count=0;
+		do {
+			c = nextDarkChar();
+			if (theChar == c)
+				count++;
+		} while (getPosition()<line.length());
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfSpecifiedChar(char theChar) {
+		setPosition(0);
+		return getNumberOfSpecifiedCharRemaining(theChar);
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfDarkChars() {
+		char c=' ';
+		int count=0;
+		do {
+			c = nextDarkChar();
+			count++;
+		} while (getPosition()<line.length());
+		return count;
+	}
+	/*.................................................................................................................*/
+	void skipComment() {
+		try {
+			int index = pos.getValue();
+			char c;
+			while ((c = line.charAt(index)) != closeCommentBracket) {
+				if (c==openCommentBracket && allowComments) {
+					pos.setValue(index);
+					skipComment();
+					index=pos.getValue()-1;
+				} 
+				index++;
+			}
+			index++;
+			pos.setValue(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {}
+	}
+	/*.................................................................................................................*/
+	void skipToDarkspace() {
+		try {
+			int index = pos.getValue();
+			while (whitespace(line.charAt(index), whitespaceString))
+				index++;
+			pos.setValue(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			pos.setValue(line.length());
+		}
+	}
+	/*.................................................................................................................*/
+	public char nextDarkChar() {
+		try {
+			int index = pos.getValue();
+			while (whitespace(line.charAt(index), whitespaceString))
+				index++;
+			char dark =line.charAt(index);
+			pos.setValue(++index);
+			if (whitespace(dark, whitespaceString))
+				return '\0';
+			else
+				return dark;
+		}
+		catch (StringIndexOutOfBoundsException e) {
+			pos.setValue(line.length());
+		}
+		return '\0';
+	}
+	/*.................................................................................................................*/
+	public char firstDarkChar() {
+		try {
+			int index = 0;
+			while (whitespace(line.charAt(index), whitespaceString))
+				index++;
+			return line.charAt(index);
+		}
+		catch (StringIndexOutOfBoundsException e) {}
+		return '\0';
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public char getCharAt(int index) {
+		if (line != null && index >=0 && index<line.length())
+			return line.charAt(index);
+		return '\0';
+	}
+	/*.................................................................................................................*/
+	public boolean whitespace(char c) {
+		return whitespace(c, whitespaceString);
+	}
+	/*.................................................................................................................*/
+	public boolean punctuation(char c) {
+		return punctuation(c, punctuationString);
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the next command in the string passed starting at the given character.  Resets pos afterward to start of command name. */
+	public String getNextCommandName(MesquiteInteger p) {
+		if (p!=null)
+			pos.setValue(p.getValue());
+		String token = getUnalteredToken(false);
+		if (p!=null)
+			pos.setValue(p.getValue());
+		return token;
+	}
+	/*.................................................................................................................*/
+	/** Returns the next command in the string passed starting at the given character */
+	public String getNextCommand(MesquiteInteger p) {
+		if (p!=null)
+			pos.setValue(p.getValue());
+		String token = getNextCommand();
+		if (p!=null)
+			p.setValue(pos.getValue());
+		return token;
+	}
+	/*.................................................................................................................*/
+	/** Returns the next command in the string passed starting at the given character */
+	public String getNextCommand() {
+		if (commandBuffer==null)
+			commandBuffer = new StringBuffer(300);
+		commandBuffer.setLength(0);
+		if (line == null || pos.getValue()>=line.length())
+			return null;
+		String token = getUnalteredToken(false);
+		if (!blankByCurrentWhitespace(token)) {
+			commandBuffer.append(token);
+			while (!blankByCurrentWhitespace(token) && !token.equals(";")) {
+				token = getUnalteredToken( false);
+				if (token != null && token.length() >0) {
+					if (token.charAt(0)!=';') 
+						commandBuffer.append(' ');
+					commandBuffer.append(token);
+				}
+			}
+		}
+		return commandBuffer.toString();
+	}
+	/*.................................................................................................................*/
+	public boolean blankByCurrentWhitespace(String line) {
+		if (line==null)
+			return true;
+		else if (line.length()==0)
+			return true;
+		else {
+			for (int i=0; i<line.length(); i++)
+				if (!whitespace(line.charAt(i)))
+					return false;
+			return true;
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean blankByCurrentWhitespace(StringBuffer line) {
+		if (line==null)
+			return true;
+		else if (line.length()==0)
+			return true;
+		else {
+			try{
+				for (int i=0; i<line.length(); i++)
+					if (!whitespace(line.charAt(i)))
+						return false;
+			}
+			catch(StringIndexOutOfBoundsException e){ //here in case multithreading zaps line in progress
+				return true;
+			}return true;
+		}
+	}
+	/*.................................................................................................................*/
+	public  void setAllowComments(boolean b) {
+		allowComments = b;
+	}
+	/*.................................................................................................................*/
+	public static boolean allowComments() {
+		return allowComments;
+	}
+	/*.................................................................................................................*/
+	public  void setOpeningCommentBracket(char c) {
+		openCommentBracket = c;
+	}
+	/*.................................................................................................................*/
+	public  void setClosingCommentBracket(char c) {
+		closeCommentBracket = c;
+	}
+	/*.................................................................................................................*/
+	protected static boolean openingCommentBracket(char c) {
+		return (c==openCommentBracket && allowComments);
+	}
+	/*.................................................................................................................*/
+	protected static boolean closingCommentBracket(char c) {
+		return (c==closeCommentBracket && allowComments);
+	}
+	public boolean getHyphensArePartOfNumbers() {
+		return hyphensArePartOfNumbers;
+	}
+	public void setHyphensArePartOfNumbers(boolean hyphensArePartOfNumbers) {
+		this.hyphensArePartOfNumbers = hyphensArePartOfNumbers;
+	}
+}
+
diff --git a/Source/mesquite/lib/ParsimonyAnalysis.java b/Source/mesquite/lib/ParsimonyAnalysis.java
new file mode 100644
index 0000000..59535d5
--- /dev/null
+++ b/Source/mesquite/lib/ParsimonyAnalysis.java
@@ -0,0 +1,5 @@
+package mesquite.lib;
+
+public interface ParsimonyAnalysis {
+
+}
diff --git a/Source/mesquite/lib/PathHolder.java b/Source/mesquite/lib/PathHolder.java
new file mode 100644
index 0000000..1b25d65
--- /dev/null
+++ b/Source/mesquite/lib/PathHolder.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public interface PathHolder {
+	public String getFilePath();
+}
+
+
diff --git a/Source/mesquite/lib/PendingCommand.java b/Source/mesquite/lib/PendingCommand.java
new file mode 100644
index 0000000..874f05e
--- /dev/null
+++ b/Source/mesquite/lib/PendingCommand.java
@@ -0,0 +1,337 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.io.*;
+
+public class PendingCommand implements SpecialListName, Explainable {
+	MesquiteCommand command;
+	String arguments;
+	public static long numInstances =0; 
+	long id = 0; 
+	String uiCallInformation;
+	//String explanation; 
+	boolean logCommand;
+	public boolean logRequestFocus = false;
+	static int waitCursorDepth =0;
+	boolean showWaitCursor;
+	boolean running = false;
+	boolean crashed = false;
+	boolean fromCommandLine = false;
+	Thread thread;
+	public boolean interrupted = false;
+	boolean usingCommand = false;
+	CommandRecord comRec = null;
+	CommandCommunicator communicator;
+	Puppeteer puppeteer;
+	Object commandedObject;
+	String commands;
+	boolean echo;
+	boolean useWizard;
+	//For a single command
+	public PendingCommand (MesquiteCommand command, String arguments, String uiCallInformation, boolean showWaitCursor, boolean logCommand) {
+		id = numInstances++; 
+		usingCommand = true;
+		this.command = command;
+
+		this.arguments = arguments;
+		this.uiCallInformation = uiCallInformation;
+		this.logCommand = logCommand;
+		this.showWaitCursor = showWaitCursor;
+		if (showWaitCursor)
+			waitCursorDepth++;
+	}
+
+	//Will route through a puppeteer; may be a whole script (new as of 0.994)
+	public PendingCommand (CommandCommunicator communicator, Puppeteer puppeteer, Object commandedObject, String commands, boolean showWaitCursor) {
+		id = numInstances++; 
+		usingCommand = false;
+		this.puppeteer = puppeteer;
+		this.commandedObject = commandedObject;
+		this.commands = commands;
+		this.communicator = communicator;
+		this.showWaitCursor = showWaitCursor;
+		if (showWaitCursor)
+			waitCursorDepth++;
+	}
+	public long getID(){
+		return id;
+	}
+	public MesquiteCommand getCommand(){
+		return command;
+	}
+
+	public void setFromCommandLine(boolean b){
+		fromCommandLine = b;
+	}
+	public void setUseWizard(boolean uw){
+		useWizard = uw;
+	}
+	public boolean getUseWizard(){
+		return useWizard;
+	}
+	public void setEchoToCommunicator(boolean echo){
+		this.echo = echo;
+	}
+
+	public boolean permitQuitUnqueried(){
+		if (command == null)
+			return false;
+		return !command.getLetMeFinish();
+	}
+	public void setThread(Thread t){
+		thread = t;
+	}
+	public Thread getThread(){
+		return thread;
+	}
+
+	public CommandRecord getCommandRecord(){
+		return comRec;
+	}
+	public void setCommandRecord(CommandRecord c){
+		comRec = c;
+	}
+	public boolean hasCrashed(){
+		return crashed;
+	}
+	public String getName(){
+		return getListName();
+	}
+	public String getListName(){
+		String s;
+		if (usingCommand){
+			if (command == null)
+				s = "No command";
+			else if (command.getOwner() instanceof Listable)
+				s= "Command: " + command.getName() + " to " + ((Listable)command.getOwner()).getName() + " ID: " + getID();
+			else
+				s= "Command: " + command.getName() + " to unknown object";
+			/*
+			if (running)
+				return "(IN PROGRESS) " + s;
+			 */
+		}
+		else {
+			if (commandedObject == null)
+				s = "No commanded object";
+			else if (commandedObject instanceof Listable)
+				s= "Commanded object: " + ((Listable)commandedObject).getName();
+			else
+				s= "Command object of class: " + commandedObject.getClass().getName();
+			/*
+			if (running)
+				return "(IN PROGRESS) " + s;
+			 */
+		}
+		return s;
+	}
+	/**/
+	public String getExplanation(){
+		/*String e;
+		if (explanation == null)
+			e = "";
+		else
+			e = "\n" + explanation;
+
+		if (running)
+			return "(IN PROGRESS) Called by: " + uiCallInformation;*/
+		return "Called by: " + uiCallInformation;
+	}
+	/** DOCUMENT Returns false only if thread died*/
+	public void go() {
+		int menuResetLevel = MesquiteModule.getMenuResetSuppression();
+		String logString = "";
+		try {
+			if (usingCommand){
+				int count = 0;
+				//execute command here
+				if (command.disposed){
+					finishUp();
+					return;
+				}
+				else if (command.getOwner() == null) {
+					MesquiteMessage.warnProgrammer("Warning: Command given to null object (" + command.getName() + "  " + arguments + ") + PendingCommand");
+					finishUp();
+					return;
+				}
+				else if (command.getOwner() instanceof Component){  //don't send command to graphical component about to be disposed
+					MesquiteWindow w = MesquiteWindow.windowOfItem((Component)command.getOwner());
+					if (w != null && w.getOwnerModule()!=null && (w.getOwnerModule().isDoomed() || w.disposing)) {
+						finishUp();
+						return;
+					}
+				}
+				logString = " > " + command.getName();
+				if (arguments!=null && !arguments.equals(""))
+					logString +=  " \"" + arguments + "\"";
+				if (command.getOwner() instanceof Listable)
+					logString = ((Listable)command.getOwner()).getName() + logString;
+				else
+					logString = "[" + command.getOwner().getClass().getName() + "]"  + logString;
+				MesquiteException.lastCommand = logString;
+				if (logCommand){
+					MesquiteModule.mesquiteTrunk.logln(logString);
+				}
+				running = true;
+				CommandRecord previous = MesquiteThread.getCurrentCommandRecord();
+				comRec = new CommandRecord(Thread.currentThread(), false);
+				if (useWizard)
+					comRec.requestEstablishWizard(true);
+				if (echo)
+					comRec.setEchoCommunicator(communicator);
+				comRec.setFromCommandLine(fromCommandLine);
+
+
+				MesquiteThread.setCurrentCommandRecord(comRec);
+				comRec.addListener(command);
+				command.notifyDoing(arguments);
+				if (!command.getSuppressLogging()) MesquiteWindow.tickClock("Command: " + command.getName());
+				MesquiteModule.incrementMenuResetSuppression();
+				if (MesquiteCommand.logEverything)
+					MesquiteCommand.stampLog(command.getOwner(), command.getName(), arguments, false);
+				menuResetLevel = MesquiteModule.getMenuResetSuppression();
+				Object returned = command.getOwner().doCommand(command.getName(), arguments, CommandChecker.defaultChecker);  //if a command is executed in this way, assumed that not scripting
+				MesquiteModule.decrementMenuResetSuppression();
+				
+				if (comRec != null) {
+					useWizard = useWizard || comRec.tempWizardWasEstablished(); //just in case the wizard was requested along the way
+					comRec.requestEstablishWizardTemp(false);
+				}
+				if (useWizard && comRec != null){
+					comRec.requestEstablishWizard(false);
+					MesquiteDialogParent dlog = comRec.getWizard();
+					if (dlog != null) {
+						if (dlog.hiddenForCalculation)
+							dlog.setVisible(true);
+						MesquiteDialog currentDialog =dlog.getCurrentDialog();
+						if (currentDialog != null){
+							currentDialog.usingWizard = false;
+							currentDialog.dispose();
+							MesquiteDialog.currentWizard = null;
+						}
+						else 
+							dlog.pleaseDispose();
+					}
+				}
+				if (!command.getSuppressLogging()) MesquiteWindow.hideClock();
+				MesquiteException.lastCommand = "";
+				command.notifyDone(arguments);
+				if (comRec !=null){
+					comRec.removeListener(command);
+					ProgressIndicator pi=null;
+					if (comRec!=null)
+						 pi = comRec.getProgressIndicator();
+					if (pi !=null)
+						pi.goAway();
+				}
+				if (logRequestFocus)
+					MesquiteTrunk.requestLogFocus();
+				MesquiteThread.setCurrentCommandRecord(previous);
+
+			}
+			else {
+				running = true;
+				CommandRecord previous = MesquiteThread.getCurrentCommandRecord();
+				comRec = new CommandRecord(Thread.currentThread(), false);
+				comRec.setFromCommandLine(fromCommandLine);
+				if (echo)
+					comRec.setEchoCommunicator(communicator);
+				if (comRec !=null){
+					MesquiteThread.setCurrentCommandRecord(comRec);
+
+					if (command != null && !command.getSuppressLogging()) MesquiteWindow.tickClock("Command: " + command.getName());
+					MesquiteModule.incrementMenuResetSuppression();	
+					menuResetLevel = MesquiteModule.getMenuResetSuppression();
+					Object returned = puppeteer.sendCommands(commandedObject, commands, new MesquiteInteger(0), null, false, null, CommandChecker.defaultChecker);
+					MesquiteModule.decrementMenuResetSuppression();	
+					if (command != null &&!command.getSuppressLogging()) MesquiteWindow.hideClock();
+
+					ProgressIndicator pi = comRec.getProgressIndicator();
+					if (pi !=null)
+						pi.goAway();
+					MesquiteThread.setCurrentCommandRecord(previous);
+					communicator.commandDone(returned);
+					if (logRequestFocus)
+						MesquiteTrunk.requestLogFocus();
+				}
+			}
+			finishUp();
+			return;
+		}
+		/*
+		catch (InterruptedException e){
+			Thread.currentThread().interrupt();
+		}
+		 */
+		catch (Exception e){
+			crashed = true;
+			MesquiteDialog.closeWizard();
+			//corruption warning
+			if (Thread.currentThread() instanceof MesquiteThread && ((MesquiteThread)Thread.currentThread()).dead()) {
+
+			}
+			else {
+				MesquiteFile.throwableToLog(this, e);
+				MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "A command could not be completed because an exception occurred (i.e. a crash; " + e.getClass() + " " + MesquiteException.lastLocMessage() + "). WARNING: there is a chance this crash could have corrupted your data.  Please check your data carefully.  If you save any files, you might best use Save As... in case file saving doesn't work properly.\n\n" + logString);
+			}
+
+			//TODO: should have flag in modules and windows that successfully completed startup; if not, then zap them
+			finishUp();
+			MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+			MesquiteTrunk.resetAllMenuBars();
+		
+
+		}
+		catch (Error e){
+			if (!(e instanceof ThreadDeath)){
+				crashed = true;
+				//corruption warning
+				MesquiteFile.throwableToLog(this, e);
+				if (e instanceof OutOfMemoryError)
+					MesquiteTrunk.mesquiteTrunk.discreetAlert("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite. ("+ MesquiteException.lastLocMessage()+ "). WARNING: there is a chance this crash could have corrupted your data.  Please check your data carefully.  If you save any files, you might best use Save As... in case file saving doesn't work properly.\n\n" + logString);
+				else
+					MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "A command could not be completed because an error occurred (i.e. a crash; " + e.getClass()  + " " + MesquiteException.lastLocMessage()+ "). WARNING: there is a chance this crash could have corrupted your data.  Please check your data carefully.  If you save any files, you might best use Save As... in case file saving doesn't work properly.\n\n" + logString);
+				MesquiteDialog.closeWizard();
+				//TODO: should have flag in modules and windows that successfully completed startup; if not, then zap them
+				finishUp();
+				MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+				MesquiteTrunk.resetAllMenuBars();
+			
+			}
+			throw e;
+
+		}
+	}
+
+	private void finishUp(){
+		running = false;
+		if (usingCommand){
+			if (command.getOwner() instanceof FileDirtier)
+				((FileDirtier)command.getOwner()).fileDirtiedByCommand(command);
+		}
+		else {
+			if (commandedObject instanceof FileDirtier)
+				((FileDirtier)commandedObject).fileDirtiedByCommand(null);
+		}
+		if (showWaitCursor) {
+			--waitCursorDepth;
+			if (waitCursorDepth<1) //MesquiteCommand.currentThreads.size()==1 && 
+				MesquiteWindow.restoreAllCursors();
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/PhoneHomeRecord.java b/Source/mesquite/lib/PhoneHomeRecord.java
new file mode 100644
index 0000000..08cb9dc
--- /dev/null
+++ b/Source/mesquite/lib/PhoneHomeRecord.java
@@ -0,0 +1,124 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import mesquite.lib.*;
+
+public class PhoneHomeRecord implements Listable {
+	
+	private int lastVersionUsed = 0;
+	private int lastNotice = 0;
+	private int lastNoticeForMyVersion = 0;
+	private int lastVersionNoticed = 0;
+	private int lastNewerVersionReported = 0;
+	String message = null;
+	String moduleName;
+
+	
+	public PhoneHomeRecord(String moduleName,int lastVersionUsed, int lastNotice, int lastNoticeForMyVersion, int lastVersionNoticed, int lastNewerVersionReported) {
+		this.lastVersionUsed = lastVersionUsed;
+		this.lastNotice = lastNotice;
+		this.lastNoticeForMyVersion = lastNoticeForMyVersion;
+		this.lastVersionNoticed = lastVersionNoticed;
+		this.lastNewerVersionReported = lastNewerVersionReported;
+		this.moduleName = moduleName;
+	}
+
+	public PhoneHomeRecord(String moduleShortName) {
+		this.moduleName = moduleShortName;
+	}
+
+	public void setCurrentValues(MesquiteModuleInfo mmi) {
+		if (mmi!=null) {
+			if (mmi.getIsPackageIntro()) {
+				lastVersionUsed = mmi.getPackageVersionInt();
+			}
+			else 
+				lastVersionUsed = mmi.getVersionInt();
+		}
+	}
+
+	public int getLastNotice() {
+		return lastNotice;
+	}
+
+
+	public void setLastNotice(int lastNotice) {
+		this.lastNotice = lastNotice;
+	}
+
+
+	public int getLastNoticeForMyVersion() {
+		return lastNoticeForMyVersion;
+	}
+
+
+	public void setLastNoticeForMyVersion(int lastNoticeForMyVersion) {
+		this.lastNoticeForMyVersion = lastNoticeForMyVersion;
+	}
+
+
+	public int getLastVersionNoticed() {
+		return lastVersionNoticed;
+	}
+
+
+	public void setLastVersionNoticed(int lastVersionNoticed) {
+		if (MesquiteInteger.isCombinable(lastVersionNoticed))
+			this.lastVersionNoticed = lastVersionNoticed;
+	}
+
+
+	public String getMessage() {
+		return message;
+	}
+
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+
+	public String getModuleName() {
+		return moduleName;
+	}
+
+
+	public void setModuleName(String moduleShortName) {
+		this.moduleName = moduleShortName;
+	}
+
+	public String getName(){
+		return getModuleName();
+	}
+
+	public int getLastVersionUsed() {
+		return lastVersionUsed;
+	}
+
+	public void setLastVersionUsed(int lastVersionUsed) {
+		this.lastVersionUsed = lastVersionUsed;
+	}
+
+	public int getLastNewerVersionReported() {
+		return lastNewerVersionReported;
+	}
+
+	public void setLastNewerVersionReported(int lastNewerVersionReported) {
+		this.lastNewerVersionReported = lastNewerVersionReported;
+	}
+
+
+
+}
diff --git a/Source/mesquite/lib/PhoneHomeUtil.java b/Source/mesquite/lib/PhoneHomeUtil.java
new file mode 100644
index 0000000..024e57e
--- /dev/null
+++ b/Source/mesquite/lib/PhoneHomeUtil.java
@@ -0,0 +1,680 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.util.*;
+
+import org.dom4j.*;
+
+public class PhoneHomeUtil {	
+
+	static int OS = 0;
+	static int OSVERSION=1;
+	static int JAVAVERSION=2;
+	public static boolean phoneHomeSuccessful = false;
+	public static boolean suppressErrorReporting = false;
+
+	//vvvvvvvvvvvvvvvvvvvv====INSTALL/UPDATE SYSTEM ====vvvvvvvvvvvvvvvvvvvv
+	/*updating/install system.  See also INSTALL/UPDATE SYSTEM: below 
+	 * Explanation of system is in mesquite.minimal.Installer.Installer.java and in NoticesAndInstallationExplanation.xml.
+	 * Also see example XML files in mesquite.minimal.Installer*/
+	public static Vector updateRecords = new Vector();
+	public static Vector installedReceipts = new Vector();
+	public static Vector installMenuItems = new Vector();
+	public static ListableVector adHocRecord = null;
+	static MesquiteSubmenuSpec installSubmenu;
+
+	public static void refreshUpdateMenuItems(){  //will call resetAllMenuBars at end of phoning all homes
+		for (int i = 0; i< installMenuItems.size(); i++){
+			MesquiteMenuItemSpec mmis = (MesquiteMenuItemSpec)installMenuItems.elementAt(i);
+			MesquiteTrunk.mesquiteTrunk.deleteMenuItem(mmis);
+		}
+		if (installSubmenu == null)
+			installSubmenu = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.fileMenu, "Available to Install or Update");
+		installMenuItems.removeAllElements();
+		for (int i = 0; i< updateRecords.size(); i++){
+			ListableVector rec = (ListableVector)updateRecords.elementAt(i);
+			String identity = ((MesquiteString)rec.getElement("identity")).getValue();
+			String version = ((MesquiteString)rec.getElement("updateVersion")).getValue();
+			if (!alreadyInReceipts(identity, version)){
+				String name = ((MesquiteString)rec.getElement("packageName")).getValue();
+				String uniqueID = ((MesquiteString)rec.getElement("uniqueID")).getValue();
+				MesquiteCommand phlt = new MesquiteCommand("phoneHomeLinkTouched", ParseUtil.tokenize("install:" + uniqueID), PhoneHomeUtil.getLinkHandler());
+				installMenuItems.addElement(MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, installSubmenu, name, phlt));
+			}
+		}
+
+	}
+	public static boolean alreadyInReceipts(ListableVector v){
+		String identity = ((MesquiteString)v.getElement("identity")).getValue();
+		String version = ((MesquiteString)v.getElement("updateVersion")).getValue();
+		return alreadyInReceipts(identity, version);
+	}
+	public static boolean alreadyInReceipts(String identity, String version){
+		for (int i = 0; i< installedReceipts.size(); i++){
+			ListableVector rec = (ListableVector)installedReceipts.elementAt(i);
+			String idInstalled =  ((MesquiteString)rec.getElement("identity")).getValue();
+			String versInstalled =  ((MesquiteString)rec.getElement("updateVersion")).getValue();
+			if (idInstalled != null && idInstalled.equalsIgnoreCase(identity)){
+				int iv = MesquiteInteger.fromString(version);
+				int ivInstalled = MesquiteInteger.fromString(versInstalled);
+				if (MesquiteInteger.isCombinable(ivInstalled) && MesquiteInteger.isCombinable(iv) && ivInstalled>= iv){
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+	public static ListableVector getUpdateRecord(String uniqueID){
+		for (int i = 0; i<updateRecords.size(); i++){
+			ListableVector vec = (ListableVector)updateRecords.elementAt(i);
+			MesquiteString id = (MesquiteString)vec.getElement("uniqueID");
+			if (uniqueID.equals(id.getValue()))
+				return vec;
+
+		}
+		return null;
+	}
+	public static MesquiteCommand getPhoneHomeDialogLinkCommand(){
+		return new MesquiteCommand("phoneHomeLinkTouched", getLinkHandler());
+	}
+	static MesquiteModule getLinkHandler(){
+		MesquiteModule installer = MesquiteModule.mesquiteTrunk.findEmployeeWithName("#mesquite.minimal.Installer.Installer");
+		return installer;
+	}
+	//^^^^^^^^^^^^^^^^====install/update system ====^^^^^^^^^^^^^^^^
+
+
+
+	/*.................................................................................................................*/
+	public static void readOldPhoneRecords(String path, ListableVector phoneRecords) {
+		if (StringUtil.blank(path))
+			return ;
+		String oldPhoneRecords = null;
+		try{
+			oldPhoneRecords = MesquiteFile.getFileContentsAsString(path, -1, 100, false);
+		} catch (Exception e) {
+			return ;
+		}
+		if (StringUtil.blank(oldPhoneRecords))
+			return;
+
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite", oldPhoneRecords);
+		if (root==null)
+			return;
+
+		Element messagesFromHome = root.element("phoneRecords");
+		if (messagesFromHome != null) {
+			Element versionElement = messagesFromHome.element("version");
+			if (versionElement == null || !versionElement.getText().equals("1")) {
+				return ;
+			}
+
+			//let's get the phone records
+			List noticesFromHomeList = messagesFromHome.elements("record");
+			for (Iterator iter = noticesFromHomeList.iterator(); iter.hasNext();) {   // this is going through all of the notices
+				Element messageElement = (Element) iter.next();
+				String moduleName = messageElement.elementText("module");
+				MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(MesquiteModule.class, moduleName);
+				int lastVersionUsedInt = MesquiteInteger.fromString(messageElement.elementText("lastVersionUsed"));
+				int lastNotice = MesquiteInteger.fromString(messageElement.elementText("lastNotice"));
+				int lastNoticeForMyVersion = MesquiteInteger.fromString(messageElement.elementText("lastNoticeForMyVersion"));
+				if (mmi!=null && lastVersionUsedInt != getVersion(mmi))
+					lastNoticeForMyVersion = 0;
+				int lastVersionNoticed = MesquiteInteger.fromString(messageElement.elementText("lastVersionNoticed"));
+				int lastNewerVersionReported = MesquiteInteger.fromString(messageElement.elementText("lastNewerVersionReported"));
+
+				PhoneHomeRecord phoneRecord = new PhoneHomeRecord(moduleName, lastVersionUsedInt, lastNotice,  lastNoticeForMyVersion,  lastVersionNoticed, lastNewerVersionReported);
+				phoneRecords.addElement(phoneRecord, false);
+			}
+
+		} 
+	}
+	/*.................................................................................................................*/
+	public static void writePhoneRecords(String path, ListableVector phoneRecords) {
+		if (StringUtil.blank(path))
+			return ;
+		Element mesquiteElement = DocumentHelper.createElement("mesquite");
+		Document doc = DocumentHelper.createDocument(mesquiteElement);
+		Element phoneRecordElement = DocumentHelper.createElement("phoneRecords");
+		mesquiteElement.add(phoneRecordElement);
+		Element versionElement = DocumentHelper.createElement("version");
+		versionElement.addText("1");
+		phoneRecordElement.add(versionElement);
+
+		for (int i= 0; i<phoneRecords.size(); i++){
+			Element recordElement = DocumentHelper.createElement("record");
+			phoneRecordElement.add(recordElement);
+			PhoneHomeRecord phoneRecord = (PhoneHomeRecord)phoneRecords.elementAt(i);
+			Element element = DocumentHelper.createElement("module");
+			element.add(DocumentHelper.createCDATA(phoneRecord.getModuleName()));
+			recordElement.add(element);
+			MesquiteModuleInfo mmi = MesquiteTrunk.mesquiteModulesInfoVector.findModule(MesquiteModule.class, phoneRecord.getModuleName());
+			XMLUtil.addFilledElement(recordElement, "lastVersionUsed",MesquiteInteger.toString(phoneRecord.getLastVersionUsed()));
+			XMLUtil.addFilledElement(recordElement, "lastNotice",MesquiteInteger.toString(phoneRecord.getLastNotice()));
+			XMLUtil.addFilledElement(recordElement, "lastNoticeForMyVersion",MesquiteInteger.toString(phoneRecord.getLastNoticeForMyVersion()));
+			XMLUtil.addFilledElement(recordElement, "lastVersionNoticed",MesquiteInteger.toString(phoneRecord.getLastVersionNoticed()));
+			XMLUtil.addFilledElement(recordElement, "lastNewerVersionReported",MesquiteInteger.toString(phoneRecord.getLastNewerVersionReported()));
+		}
+		String xml = XMLUtil.getDocumentAsXMLString(doc);
+		if (!StringUtil.blank(xml))
+			MesquiteFile.putFileContents(path, xml, true);
+
+	}
+
+
+
+
+
+	/*.................................................................................................................*/
+	public static int getVersion(MesquiteModuleInfo mmi) {
+		if (mmi == null)
+			return 0;
+		if (mmi.getIsPackageIntro())
+			return mmi.getPackageVersionInt();
+		else
+			return mmi.getVersionInt();
+	}
+	/*.................................................................................................................*/
+	public static void processSingleNotice(MesquiteModuleInfo mmi, StringBuffer notices, boolean hideFromDialog, MesquiteInteger countNotices, int forMesquiteVersionLessOrEqual, 
+			int noticeNumber, String noticeType, String message, int lastVersionNoticed, int lastNoticeForMyVersion, int lastNotice, 
+			PhoneHomeRecord phoneHomeRecord, Vector osVector, 
+			int forBuildNumberEqualOrGreater, int forBuildNumberEqualOrLess, int forBuildNumberExactly, 
+			int forPackageVersionEqualOrGreater, int forPackageVersionEqualOrLess, int forPackageVersionExactly, ListableVector v, boolean adHoc) {
+		boolean pleaseDeleteFromUpdates = false;
+		if (!MesquiteInteger.isCombinable(forMesquiteVersionLessOrEqual))
+			forMesquiteVersionLessOrEqual = MesquiteInteger.infinite;
+		if (MesquiteInteger.isCombinable(noticeNumber)){
+
+			boolean appliesToOSVersion = true;
+			if (osVector!=null) {
+				appliesToOSVersion=false;
+				for (int i=0; i<osVector.size() && !appliesToOSVersion; i++) {
+					String [] osStrings = (String[])osVector.get(i);
+					boolean osMatches =(StringUtil.blank(osStrings[OS])|| System.getProperty("os.name").startsWith(osStrings[OS]));
+					boolean osVersionMatches =(StringUtil.blank(osStrings[OSVERSION])|| System.getProperty("os.version").startsWith(osStrings[OSVERSION]));
+					boolean javaMatches =(StringUtil.blank(osStrings[JAVAVERSION])|| MesquiteTrunk.getJavaVersionAsString().startsWith(osStrings[JAVAVERSION]));
+					if (osMatches && osVersionMatches && javaMatches) {
+						appliesToOSVersion=true;
+					}
+				}
+			}
+
+			boolean appliesToBuild = true;
+			if (mmi == null || mmi.getName().equals("Mesquite") || mmi.getName().equals("Installer") || mmi.getName().equals("Defaults")){
+				if (MesquiteInteger.isCombinable(forBuildNumberExactly)) 
+					appliesToBuild =  appliesToBuild && (forBuildNumberExactly == MesquiteModule.getBuildNumber());
+				if (MesquiteInteger.isCombinable(forBuildNumberEqualOrGreater)) 
+					appliesToBuild =  appliesToBuild && (forBuildNumberEqualOrGreater <= MesquiteModule.getBuildNumber());
+				if (MesquiteInteger.isCombinable(forBuildNumberEqualOrLess))  
+					appliesToBuild =  appliesToBuild && (forBuildNumberEqualOrLess >= MesquiteModule.getBuildNumber());
+			}
+			else {
+				if (MesquiteInteger.isCombinable(forBuildNumberExactly)) 
+					appliesToBuild =  appliesToBuild && (forBuildNumberExactly == MesquiteModule.getBuildNumber());
+				if (MesquiteInteger.isCombinable(forBuildNumberEqualOrGreater)) 
+					appliesToBuild =  appliesToBuild && (forBuildNumberEqualOrGreater <= MesquiteModule.getBuildNumber());
+				if (MesquiteInteger.isCombinable(forBuildNumberEqualOrLess))  
+					appliesToBuild =  appliesToBuild && (forBuildNumberEqualOrLess >= MesquiteModule.getBuildNumber());
+
+				if (MesquiteInteger.isCombinable(forPackageVersionExactly)) 
+					appliesToBuild =  appliesToBuild && (forPackageVersionExactly == mmi.getVersionInt());
+				if (MesquiteInteger.isCombinable(forPackageVersionEqualOrGreater)) 
+					appliesToBuild =  appliesToBuild && (forPackageVersionEqualOrGreater <= mmi.getVersionInt());
+				if (MesquiteInteger.isCombinable(forPackageVersionEqualOrLess))  
+					appliesToBuild =  appliesToBuild && (forPackageVersionEqualOrLess >= mmi.getVersionInt());
+
+			}
+
+			//suppose Mesquite is version 2. 01
+			int currentMesquiteVersion = getVersion(mmi);
+
+			//vvvvvvvvvvvvvvvvvvvv====INSTALL/UPDATE SYSTEM ====vvvvvvvvvvvvvvvvvvvv
+			boolean critical = false;
+			boolean appearsToNeedInstallation = false;
+			if (noticeType != null && noticeType.equalsIgnoreCase("update")){
+				MesquiteString uniqueLocation = (MesquiteString)v.getElement("uniqueLocation");
+				MesquiteString identity = (MesquiteString)v.getElement("identity");
+				MesquiteString updateVersion = (MesquiteString)v.getElement("updateVersion");
+				if (uniqueLocation != null)
+					appearsToNeedInstallation = !MesquiteFile.fileOrDirectoryExists(MesquiteTrunk.getRootPath() + uniqueLocation.getValue());
+
+				MesquiteString updateOnly = (MesquiteString)v.getElement("updateOnly");
+				if (updateOnly != null && !appearsToNeedInstallation && "critical".equalsIgnoreCase(updateOnly.getValue()) && identity != null && alreadyInReceipts(identity.getValue(), "0") && !alreadyInReceipts(identity.getValue(), updateVersion.getValue()))  
+					critical = true;
+				else if (updateOnly != null && !"false".equalsIgnoreCase(updateOnly.getValue()) && appearsToNeedInstallation)
+					pleaseDeleteFromUpdates = true;
+			}
+			//^^^^^^^^^^^^^^^^====install/update system ====^^^^^^^^^^^^^^^^
+
+			//notice assumed to have been seen before if its version number is less than current
+			boolean seenBefore = false;
+
+			if (mmi == null || mmi.getName().equals("Mesquite") || mmi.getName().equals("Installer") || mmi.getName().equals("Defaults")){  //a Mesquite update
+				seenBefore = seenBefore || !adHoc && (forMesquiteVersionLessOrEqual < currentMesquiteVersion);  //e.g., notice is version 2.0
+
+				//or if Mesquite's version is same as notice's, but notice number is already seen for this version than last one noticed.
+				seenBefore = seenBefore || (forMesquiteVersionLessOrEqual ==  currentMesquiteVersion && noticeNumber <= lastNoticeForMyVersion);  //e.g., notice is 2. 01; notice number has already been seen
+
+				//or if Mesquite's version is less than notice's, and notice's is same as lastVersion noticed, but notice is already seen.
+				seenBefore = seenBefore || (currentMesquiteVersion<forMesquiteVersionLessOrEqual && lastVersionNoticed == forMesquiteVersionLessOrEqual && noticeNumber <= lastNotice);  //e.g., notice is 2.02; 2.02 notices previously read; notice already seen
+
+				//or if Mesquite's version is less than notice's, and notice's is less than as lastVersion noticed, but notice is already seen.
+				seenBefore = seenBefore || (currentMesquiteVersion<forMesquiteVersionLessOrEqual && lastVersionNoticed> forMesquiteVersionLessOrEqual);  //e.g., notice is 2.02; 2.03 notices previously read
+			}
+			else {  //third party update
+				seenBefore = seenBefore || (noticeNumber <= lastNoticeForMyVersion);  //e.g., notice is 2. 01; notice number has already been seen
+
+				seenBefore = seenBefore || (noticeNumber <= lastNotice);  //e.g., notice is 2.02; 2.02 notices previously read; notice already seen
+			}
+			boolean javaInsufficient = false;
+			boolean requirementsNotMet = false;
+			if (v != null){
+				MesquiteString java = (MesquiteString)v.getElement("java");
+				MesquiteString requiredPath = (MesquiteString)v.getElement("requiredPath");
+				if (java != null){
+					double jV = MesquiteDouble.fromString(java.getValue(), new MesquiteInteger(0));
+					if (MesquiteTrunk.isJavaVersionLessThan(jV))
+						javaInsufficient = true;
+				}
+				if (requiredPath != null && !StringUtil.blank(requiredPath.getValue())){
+					String requiredP = requiredPath.getValue();
+					if (!MesquiteFile.fileOrDirectoryExists(MesquiteTrunk.getRootPath() + requiredP)){
+						requirementsNotMet = true;
+					}
+				}
+			}
+
+			// otherwise assumed to have been seen before if version is same as current and notice is at or before recalled one
+			if ((!seenBefore || critical) && appliesToOSVersion && appliesToBuild){  //relevant
+				boolean skip = false;
+				if (noticeType != null && noticeType.equalsIgnoreCase("alert")){
+					//notices.append( countNotices.toString() + ". " + message + "<hr>\n");
+					if (!hideFromDialog){
+						notices.append(message + "<hr>\n");
+						countNotices.increment();
+				}
+				}
+				//vvvvvvvvvvvvvvvvvvvv====INSTALL/UPDATE SYSTEM ====vvvvvvvvvvvvvvvvvvvv
+				else if (noticeType != null && noticeType.equalsIgnoreCase("update")){
+					if (v != null && !hideFromDialog){
+						MesquiteString java = (MesquiteString)v.getElement("java");
+						MesquiteString requiredName = (MesquiteString)v.getElement("requires");
+						MesquiteString requiredPath = (MesquiteString)v.getElement("requiredPath");
+						MesquiteString updateOnly = (MesquiteString)v.getElement("updateOnly");
+						MesquiteString updateVersion = (MesquiteString)v.getElement("updateVersion");
+						MesquiteString identity = (MesquiteString)v.getElement("identity");
+						if (java != null){
+							double jV = MesquiteDouble.fromString(java.getValue(), new MesquiteInteger(0));
+							if (MesquiteTrunk.isJavaVersionLessThan(jV)){
+								javaInsufficient = true;
+								if (appearsToNeedInstallation || (identity != null && !alreadyInReceipts(identity.getValue(), "0")))  //this package is not already installed in some form									
+									skip = true;
+							}
+						}
+						if (requiredPath != null && !StringUtil.blank(requiredPath.getValue())){
+							String requiredP = requiredPath.getValue();
+							if (!MesquiteFile.fileOrDirectoryExists(MesquiteTrunk.getRootPath() + requiredP)){
+								requirementsNotMet = true;
+							}
+						}
+						if (!javaInsufficient && updateOnly != null && !"false".equalsIgnoreCase(updateOnly.getValue())){  //update only tag is active
+							if (appearsToNeedInstallation || (identity != null && !alreadyInReceipts(identity.getValue(), "0")))  //this package is not already installed in some form									
+								skip = true;
+						}
+						if (!skip){
+							MesquiteString packageName = (MesquiteString)v.getElement("packageName");
+							MesquiteString explanation = (MesquiteString)v.getElement("explanation");
+							MesquiteString uniqueID = (MesquiteString)v.getElement("uniqueID");
+							if (requirementsNotMet && requiredName != null){
+								notices.append("<h2>Available for installation: " + packageName + "</h2>");
+								notices.append("HOWEVER, this package requires " + requiredName.getValue() + ", which apparently is not installed.  If you install this other package, you may install " + packageName + " later by selecting the item in the \"Available to Install or Update\" submenu of the File menu.<hr>\n");
+								pleaseDeleteFromUpdates = true;
+								countNotices.increment();
+							}
+							else if (javaInsufficient){
+								notices.append("<h2>Available for installation: " + packageName + "</h2>");
+								notices.append("HOWEVER, your version of Java is too old for this package.  You need Java version " + java.getValue() + ".  If you install a sufficiently recent version of java, you may install this package later by selecting the item in the \"Available to Install or Update\" submenu of the File menu.<hr>\n");
+								pleaseDeleteFromUpdates = true;
+								countNotices.increment();
+							}
+							else {
+								if (critical)
+									notices.append("<h2>CRITICAL UPDATE Available for installation: " + packageName + "</h2>");
+								else
+									notices.append("<h2>Available for installation: " + packageName + "</h2>");
+								notices.append(explanation);
+								String installHTML = null;
+								if (!MesquiteFile.canWrite(MesquiteTrunk.getRootPath() + "mesquite")){
+									installHTML = ("<p>HOWEVER, you cannot install this update because you do not have privileges to write into the Mesquite_Folder." +
+									"  Once this is resolved, you may install later by selecting the item in the \"Available to Install or Update\" submenu of the File menu.");
+								}
+								else {
+									installHTML = "<p><a href = \"install:" + uniqueID + "\"><img border = 0 src =\"" + MesquiteFile.massageFilePathToURL(MesquiteTrunk.mesquiteTrunk.getRootPath()+"images" + MesquiteFile.fileSeparator + "download.gif") + "\"> Install</a>";
+									if (!adHoc)
+										installHTML += "  If you do not install now, you may install later by selecting the item in the \"Available to Install or Update\" submenu of the File menu.";
+								}
+
+								notices.append(installHTML);
+								if (!appearsToNeedInstallation) notices.append("<p><b>Note:</b> A version of this package may already be installed.\n");
+								notices.append("<hr>\n");
+								countNotices.increment();
+							}
+						}
+					}
+				}
+				//^^^^^^^^^^^^^^^^====install/update system ====^^^^^^^^^^^^^^^^
+				else {
+					String fromWhom = null;
+					if (mmi != null){
+						if (mmi.getModuleClass() == mesquite.Mesquite.class)
+							fromWhom = "Mesquite";
+						else if (!StringUtil.blank(mmi.getPackageName()))
+							fromWhom = mmi.getPackageName();
+						else
+							fromWhom = mmi.getName();
+					}
+					MesquiteMessage.println("\n\nNOTICE from " + fromWhom + ": " + message + "\n");
+				}
+				if (mmi == null || mmi.getName().equals("Mesquite") || mmi.getName().equals("Installer") || mmi.getName().equals("Defaults")){  //Mesquite update
+					if (!skip && MesquiteInteger.isCombinable(forMesquiteVersionLessOrEqual)){
+						if (forMesquiteVersionLessOrEqual ==  currentMesquiteVersion){  //version of note is this version of Mesquite
+							if (phoneHomeRecord.getLastNoticeForMyVersion() < noticeNumber)  // this is a later notice than we had seen before; record it
+								phoneHomeRecord.setLastNoticeForMyVersion(noticeNumber);
+							if (forMesquiteVersionLessOrEqual ==  phoneHomeRecord.getLastVersionNoticed() && noticeNumber >phoneHomeRecord.getLastNotice())
+								phoneHomeRecord.setLastNotice(noticeNumber);
+						}
+						if (forMesquiteVersionLessOrEqual >=  phoneHomeRecord.getLastVersionNoticed()){
+							phoneHomeRecord.setLastVersionNoticed(forMesquiteVersionLessOrEqual);
+							if (noticeNumber >phoneHomeRecord. getLastNotice())
+								phoneHomeRecord.setLastNotice(noticeNumber);
+						}
+					}
+				}
+				else {  //third party update
+					if (!skip){
+						if (phoneHomeRecord.getLastNoticeForMyVersion() < noticeNumber)  // this is a later notice than we had seen before; record it
+							phoneHomeRecord.setLastNoticeForMyVersion(noticeNumber);
+						if (noticeNumber >phoneHomeRecord.getLastNotice())
+							phoneHomeRecord.setLastNotice(noticeNumber);
+
+					}
+				}
+
+			}
+			if (javaInsufficient ||  requirementsNotMet || !appliesToOSVersion  || !appliesToBuild)
+				pleaseDeleteFromUpdates = true;
+		}
+
+
+		if (pleaseDeleteFromUpdates)
+			updateRecords.removeElement(v);
+
+	}
+	/*.................................................................................................................*/
+
+	public static void checkForNotices(String URLString) {
+		if (StringUtil.blank(URLString))
+			return;
+		String noticesFromHome = null;
+		try{
+			noticesFromHome = MesquiteFile.getURLContentsAsString(URLString, -1, false);
+
+		} catch (Exception e) {
+			MesquiteTrunk.mesquiteTrunk.discreetAlert("Sorry, no relevant information found at that URL");
+			return;
+		}
+		if (StringUtil.blank(noticesFromHome)){
+			MesquiteTrunk.mesquiteTrunk.discreetAlert("Sorry, no relevant information found at that URL");
+			return;
+		}
+		PhoneHomeRecord phr = new PhoneHomeRecord("");
+		String notices = handleMessages(true, noticesFromHome, null, phr, null);
+		if (!StringUtil.blank(notices)){
+			String note = ("<h2>Notices from " + StringUtil.protectForXML(URLString) + "</h2><hr><b>NOTE:</b> these notices may include some that have already been seen and dealt with.  When you ask specifically to check for notices, you are shown all whether seen previously or not.<hr>" + notices.toString() + "<br>");
+			if (!MesquiteThread.isScripting()){
+				AlertDialog.noticeHTML(MesquiteTrunk.mesquiteTrunk.containerOfModule(),"Note", note, 600, 400, new MesquiteCommand("phoneHomeLinkTouchedAdHoc", getLinkHandler()), true);
+			}
+			else
+				System.out.println(note);
+		}
+		else
+			MesquiteTrunk.mesquiteTrunk.discreetAlert("Sorry, relevant no information found at that URL");
+	}
+	/*.................................................................................................................*/
+
+	public static String retrieveMessagesFromHome(MesquiteModuleInfo mmi, PhoneHomeRecord phoneHomeRecord, StringBuffer logBuffer) {
+		String url = mmi.getHomePhoneNumber();
+		if (StringUtil.blank(url))
+			return null;
+		String noticesFromHome = null;
+		try{
+			noticesFromHome = MesquiteFile.getURLContentsAsString(url, -1, false);
+
+		} catch (Exception e) {
+			return null;
+		}
+		if (StringUtil.blank(noticesFromHome))
+			return null;
+		if (mmi.getModuleClass() == mesquite.Mesquite.class)
+			phoneHomeSuccessful = true;
+		return handleMessages(false, noticesFromHome, mmi, phoneHomeRecord, logBuffer);
+	}
+	/*.................................................................................................................*/
+
+	private static String handleMessages(boolean adHoc, String noticesFromHome, MesquiteModuleInfo mmi, PhoneHomeRecord phoneHomeRecord, StringBuffer logBuffer) {
+		/*	String url = mmi.getHomePhoneNumber();
+		if (StringUtil.blank(url))
+			return null;
+		String noticesFromHome = null;
+		try{
+			noticesFromHome = MesquiteFile.getURLContentsAsString(url, -1, false);
+
+		} catch (Exception e) {
+			return null;
+		}
+		if (StringUtil.blank(noticesFromHome))
+			return null;
+		if (mmi.getModuleClass() == mesquite.Mesquite.class)
+			phoneHomeSuccessful = true;
+		 */
+
+		int lastNoticeForMyVersion = phoneHomeRecord.getLastNoticeForMyVersion();
+		int lastNotice = phoneHomeRecord.getLastNotice();
+		int lastVersionNoticed = phoneHomeRecord.getLastVersionNoticed();
+
+
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite",noticesFromHome);
+		if (root==null)
+			return null;
+		Element messagesFromHome = root.element("MessagesFromHome");
+		if (messagesFromHome != null) {
+			Element versionElement = messagesFromHome.element("version");
+			if (versionElement == null || !versionElement.getText().equals("1")) { 
+				return null;
+			}
+
+			StringBuffer notices = new StringBuffer();
+
+
+			MesquiteInteger countNotices = new MesquiteInteger(1);
+
+			//let's get the notices
+			List noticesFromHomeList = messagesFromHome.elements("notice");
+			for (Iterator iter = noticesFromHomeList.iterator(); iter.hasNext();) {   // this is going through all of the notices
+				Element messageElement = (Element) iter.next();
+				int forMesquiteVersionLessOrEqual = MesquiteInteger.fromString(messageElement.elementText("forMesquiteVersionLessOrEqual"));    // notice is for this version and any previous version			
+				if (!MesquiteInteger.isCombinable(forMesquiteVersionLessOrEqual))
+					forMesquiteVersionLessOrEqual = MesquiteInteger.fromString(messageElement.elementText("forVersion"));    // old name
+				//NOTE: for adhoc requests forMesquiteVersionLessOrEqual is not used
+
+				int forPackageVersionExactly = MesquiteInteger.fromString(messageElement.elementText("forPackageVersionExactly"));    // notice is for this version and any previous version
+				int forPackageVersionEqualOrGreater = MesquiteInteger.fromString(messageElement.elementText("forPackageVersionEqualOrGreater"));    // notice is for this version and any previous version
+				int forPackageVersionEqualOrLess = MesquiteInteger.fromString(messageElement.elementText("forPackageVersionEqualOrLess"));    // notice is for this version and any previous version
+				int forBuildNumberExactly = MesquiteInteger.fromString(messageElement.elementText("forBuildNumberExactly"));
+				int forBuildNumberEqualOrGreater = MesquiteInteger.fromString(messageElement.elementText("forBuildNumberEqualOrGreater"));
+				int forBuildNumberEqualOrLess = MesquiteInteger.fromString(messageElement.elementText("forBuildNumberEqualOrLess"));
+				int noticeNumber = MesquiteInteger.fromString(messageElement.elementText("noticeNumber"));
+				String hideFromDialogString = messageElement.elementText("hideFromDialog");
+				boolean hideFromDialog = false;
+				if (hideFromDialogString != null && hideFromDialogString.equalsIgnoreCase("true"))
+					hideFromDialog = true;
+				String messageType = messageElement.elementText("messageType");
+				String message = messageElement.elementText("message");
+				Vector osVector = null;
+				List osList = messageElement.elements("forOS");
+				for (Iterator i = osList.iterator(); i.hasNext();) {   // this is going through all of the notices
+					if (osVector==null)
+						osVector = new Vector();
+					Element osElement = (Element) i.next();
+					String[] osStrings= new String[3];
+					osStrings[OS] = osElement.elementText("OS");
+					osStrings[OSVERSION] = osElement.elementText("OSVersion");
+					osStrings[JAVAVERSION]  = osElement.elementText("JavaVersion");
+					osVector.addElement(osStrings);
+				}
+				//INSTALLER: recording update record for later use in dialog and in menu items.
+				//vvvvvvvvvvvvvvvvvvvv====INSTALL/UPDATE SYSTEM ====vvvvvvvvvvvvvvvvvvvv
+				ListableVector v = null;
+				if (messageType.equalsIgnoreCase("update")){
+					v = new ListableVector();
+					String packageName = messageElement.elementText("packageName");
+					String versionNum = messageElement.elementText("updateVersion");
+					String uniqueLocation = messageElement.elementText("uniqueLocation");
+					String explanation = messageElement.elementText("explanation");
+					String updateOnly = messageElement.elementText("updateOnly");
+					String java = messageElement.elementText("java");
+					String requires = messageElement.elementText("requires");
+					String requiredPath = messageElement.elementText("requiredPath");
+					String beforeMessage = messageElement.elementText("beforeMessage");
+					String afterMessage = messageElement.elementText("afterMessage");
+					String uniqueID = MesquiteTrunk.getUniqueIDBase() + updateRecords.size();
+					v.addElement(new MesquiteString("uniqueID", uniqueID), false);
+					v.addElement(new MesquiteString("identity", messageElement.elementText("identity")), false);
+					v.addElement(new MesquiteString("packageName", packageName), false);
+					v.addElement(new MesquiteString("explanation", explanation), false);
+					if (updateOnly != null)
+						v.addElement(new MesquiteString("updateOnly", updateOnly), false);
+					if (requiredPath != null)
+						v.addElement(new MesquiteString("requiredPath", requiredPath), false);
+					if (requires != null)
+						v.addElement(new MesquiteString("requires", requires), false);
+					if (beforeMessage != null)
+						v.addElement(new MesquiteString("beforeMessage", beforeMessage), false);
+					if (afterMessage != null)
+						v.addElement(new MesquiteString("afterMessage", afterMessage), false);
+					v.addElement(new MesquiteString("updateVersion", versionNum), false);
+					v.addElement(new MesquiteString("uniqueLocation", uniqueLocation), false);
+					v.addElement(new ObjectContainer("install", messageElement.elements("install")), false);
+					v.addElement(new MesquiteBoolean("isInstalled", false), false);
+					if (java != null)
+						v.addElement(new MesquiteString("java", java), false);
+					String ux = XMLUtil.getElementAsXMLString(messageElement, "UTF-8", true) ;
+
+					if (ux != null){
+						ux = "<updateXML>" + ux + "</updateXML>";  //strip for more compact file when viewed
+						ux = StringUtil.replace(ux, "\n", null);
+						ux = StringUtil.replace(ux, "\r", null);
+						ux = StringUtil.replace(ux, "\t", null);
+						ux = StringUtil.stripStuttered(ux, "  ");
+						v.addElement(new MesquiteString("updateXML", ux), false);
+					}
+					if (!adHoc)
+						updateRecords.addElement(v);  
+					else  
+						adHocRecord = v;
+				}
+				//^^^^^^^^^^^^^^^^====install/update system ====^^^^^^^^^^^^^^^^
+
+				// process other notice tags here if they are present
+				processSingleNotice(mmi, notices, hideFromDialog, countNotices, forMesquiteVersionLessOrEqual, noticeNumber, messageType, message,  lastVersionNoticed, lastNoticeForMyVersion,  lastNotice,phoneHomeRecord, osVector, forBuildNumberEqualOrGreater, forBuildNumberEqualOrLess, forBuildNumberExactly, forPackageVersionEqualOrGreater, forPackageVersionEqualOrLess, forPackageVersionExactly, v, adHoc);
+
+			}
+			//INSTALLER: here go through updateRecords to figure out which are already installed, which not; which have newer versions already installed, etc.
+			refreshUpdateMenuItems();
+
+			// now see if there is a tag for the current release version
+			Element currentReleaseVersion = messagesFromHome.element("currentReleaseVersion");
+			if (mmi != null && currentReleaseVersion !=null) {
+				String releaseString = "";
+				String releaseStringHTML ="";
+				String versionString = currentReleaseVersion.elementText("versionString");
+				String versionStringInstalled = null;
+				if (mmi.getIsPackageIntro() && !StringUtil.blank(mmi.getPackageVersion()))
+					versionStringInstalled =  mmi.getPackageVersion();
+
+				else if (!StringUtil.blank(mmi.getVersion()))
+					versionStringInstalled = mmi.getVersion();
+				String buildString = currentReleaseVersion.elementText("build");
+				boolean skip = false;
+
+				if (versionStringInstalled != null && versionString != null && versionStringInstalled.equals(versionString)){  //same version
+					if (mmi.getModuleClass() != mesquite.Mesquite.class || buildString == null ||  buildString.equals(Integer.toString(MesquiteModule.getBuildNumber())))
+						skip = true; //skip unless Mesquite and different build
+				}
+				if (!skip){
+					String URL = currentReleaseVersion.elementText("URL");
+					String downloadURL = currentReleaseVersion.elementText("downloadURL");
+					int releaseVersionInt = MesquiteInteger.fromString(currentReleaseVersion.elementText("version"));
+					int userVersionInt = getVersion(mmi);
+					String fromWhom = null;
+					if (mmi.getModuleClass() == mesquite.Mesquite.class)
+						fromWhom = "Mesquite";
+					else if (!StringUtil.blank(mmi.getPackageName()))
+						fromWhom = mmi.getPackageName();
+					else
+						fromWhom = mmi.getName();
+					if (!StringUtil.blank(versionString))
+						releaseString+="The current release version of " + fromWhom + " is " + versionString;
+					if (!StringUtil.blank(buildString))
+						releaseString+= " build " + buildString;
+					if (!StringUtil.blank(releaseString)) {
+						if (mmi.getIsPackageIntro()) {
+							if (!StringUtil.blank(mmi.getPackageVersion()))
+								releaseString+= " (the version you have installed is "+ mmi.getPackageVersion() + ").";
+						}
+						else if (!StringUtil.blank(mmi.getVersion()))
+							releaseString+= " (the version you have installed is "+ mmi.getVersion() + ").";
+						releaseStringHTML = releaseString;
+						if (!StringUtil.blank(URL)) {
+							releaseStringHTML +=" <a href=\"" + URL + "\">Home page</a><BR>";
+							releaseString+=" The home page is: " + URL+ ". ";
+						}
+						if (!StringUtil.blank(downloadURL)) {
+							releaseStringHTML +=" <a href=\"" + downloadURL + "\">Download page</a>.   You may also find an option to install this using Mesquite's automatic installation system (look in File menu under Available to Install or Update).";
+							releaseString+=" The latest version is downloadable at: " + downloadURL+ ".   You may also be able to install this using Mesquite's automatic installation system (look in File menu under Available to Install or Update).";
+						}
+					}
+
+					if (MesquiteInteger.isCombinable(releaseVersionInt) && userVersionInt<releaseVersionInt) {
+						if (phoneHomeRecord.getLastNewerVersionReported()<releaseVersionInt) { // we've not reported on this new version yet
+							notices.append("\n" +releaseStringHTML);  // there is a newer version that has been released
+							phoneHomeRecord.setLastNewerVersionReported(releaseVersionInt);
+						}
+						if (logBuffer!=null)
+							logBuffer.append("\n" +releaseString);
+					}
+				}
+
+			}
+
+			// process other tags if they are there
+			return notices.toString();
+
+		} 
+		return null;
+	}
+
+}
diff --git a/Source/mesquite/lib/PopUpPanelOfCards.java b/Source/mesquite/lib/PopUpPanelOfCards.java
new file mode 100644
index 0000000..b85c341
--- /dev/null
+++ b/Source/mesquite/lib/PopUpPanelOfCards.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+
+/*===============================================*/
+/** This is a PanelOfCards that uses a pop-up menu to switch between cards.  */
+public class PopUpPanelOfCards extends PanelOfCards implements ItemListener, Commandable {
+	Choice cardChoice;
+	MesquiteCommand showCardCommand = new MesquiteCommand("showCard", this);
+	PopUpPanelOfCards (ExtensibleDialog dialog, String name){
+		super(dialog,name);
+	}
+	
+	/*.................................................................................................................*/
+	public void prepareChoicePanel (Panel choicePanel) {
+	//	popUpMenu = new PanelOfPopUp(dialog);
+	//	choicePanel.add(popUpMenu);
+	}
+	/*.................................................................................................................*/
+	public void installChoicePanel (Panel choicePanel) {
+		dialog.setAddPanel(choicePanel);
+		cardChoice = dialog.addPopUpMenu(name);
+		cardChoice.addItemListener(this);
+	}
+	/*.................................................................................................................*/
+	public void cleanEmptyChoice (Panel choicePanel) {
+//		choicePanel.remove(popUpMenu);
+	}
+	/*.................................................................................................................*/
+	public void createChoicePanel (Panel choicePanel) {
+//		popUpMenu.createChoice();
+	}
+	/*.................................................................................................................*/
+	public void addChoice (String s) {
+		cardChoice.add(s);
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+  	 	if (checker.compare(this.getClass(), null, null, commandName, "showCard")) {
+  	 		int which = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+  		  	 		showCard(which);
+  	 	}
+  	 	return null;
+	}
+	public void showCard(int i){
+		cardChoice.requestFocus();
+		super.showCard(i);
+	}
+ /*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == cardChoice){
+	  		showCard(cardChoice.getSelectedIndex());
+  			showCardCommand.doItNewThread(Integer.toString(cardChoice.getSelectedIndex()), null, false, false);
+  		}
+  	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/Prioritizable.java b/Source/mesquite/lib/Prioritizable.java
new file mode 100644
index 0000000..fc12f42
--- /dev/null
+++ b/Source/mesquite/lib/Prioritizable.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim whether or not it is of first or second priority (in future may allow other priorities as well)*/
+public interface Prioritizable {
+ 	public boolean isFirstPriority(Class c);
+}
+
diff --git a/Source/mesquite/lib/Priority.java b/Source/mesquite/lib/Priority.java
new file mode 100644
index 0000000..4485570
--- /dev/null
+++ b/Source/mesquite/lib/Priority.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is reports on its priority*/
+public interface Priority {
+ 	public int getPriority();
+}
+
diff --git a/Source/mesquite/lib/ProgressIndicator.java b/Source/mesquite/lib/ProgressIndicator.java
new file mode 100644
index 0000000..b27183a
--- /dev/null
+++ b/Source/mesquite/lib/ProgressIndicator.java
@@ -0,0 +1,398 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*
+ things to do:  
+- immediate update?
+- dealing with double progress windows?
+
+
+File reading:
+- have verbose mode of file-reading whereby it sends titles of all nexus commands to log file?
+- reports previous block
+- 
+ */
+
+
+
+/*===============================================*/
+/** presents a progress window*/
+public class ProgressIndicator implements Abortable {
+	ProgressWindowThread t;
+	MesquiteThread ownerThread;
+	Color barColor;
+	Color barBackColor;
+	static int defaultHeight = 130;
+	static int defaultWidth = 300;
+	int height = 130;
+	int width = 300;
+	static long totalCreated = 0;
+	long id =0;
+	int buttonMode = FLAG_AND_HIDE;
+	String title;
+	private boolean fromClockWatcher = false;
+	public static final int NOSTOP = -1;
+	public static final int FLAG = 0;
+	public static final int FLAG_AND_HIDE = 1;
+	public static final int OFFER_CONTINUE = 2;
+	public static final int OFFER_KILL_THREAD = 3;
+	public static final int OFFER_FLAG_OR_KILL_THREAD =4;
+	public static final int OFFER_CONTINUE_FORCEQUIT = 5;
+
+	public boolean dontStart = false;
+	MesquiteTimer timer = null;
+
+//	0 = posts flag that button hit; 1 = posts flag that button hit AND gets rid of dialog; 2 = aborts owner thread
+	//boolean goneAway = false;
+	public ProgressIndicator (MesquiteProject mp, String title, String initialMessage, long total, String buttonName) {
+		if (mp!=null) {
+			barColor= ColorTheme.getActiveDark();
+			barBackColor= ColorTheme.getActiveLight();
+		}
+		else {
+			barColor= ColorDistribution.spinDark;
+			barBackColor = ColorDistribution.spinLight;
+		}
+		this.title = title;
+		id = totalCreated++;
+		t = new ProgressWindowThread(this,title, initialMessage, total, buttonName);
+	}
+
+	public ProgressIndicator (MesquiteProject mp, String title, String initialMessage, long total, boolean showStop) {
+		this(mp, title, initialMessage, total, showStop ? "Stop" : null);
+		setButtonMode(FLAG_AND_HIDE);
+	}
+	public ProgressIndicator (MesquiteProject mp, String title, long total, boolean showStop) {
+		this(mp,title, "", total, showStop);
+	}
+	public ProgressIndicator (MesquiteProject mp, String title, long total) {
+		this(mp,title, total, true);
+	}
+	/** If this constructor is used, then the progress indicator doesn't have a final value, and thus is just a "spinning" indicator */
+	public ProgressIndicator (MesquiteProject mp, String title) {
+		this(mp,title, 0, true);
+	}
+	public void toFront(){
+		if (t != null && t.dlog != null)
+			t.dlog.toFront();
+	}
+
+	public boolean getIsFromWatcher(){
+		return fromClockWatcher;
+	}
+	public void setIsFromWatcher(boolean v){
+		fromClockWatcher = v;
+	}
+	public long getID(){
+		return id;
+	}
+	public void setOwnerThread(MesquiteThread th){
+		ownerThread = th;
+		if (t.dlog !=null)
+			t.dlog.setButtonsVisible(!(buttonMode >= OFFER_KILL_THREAD && ownerThread != MainThread.mainThread));
+	}
+	public MesquiteThread getOwnerThread(){
+		return ownerThread;
+	}
+	public void setSize(int w, int h){
+		height = h;
+		width = w;
+	}
+	public void setButtonMode(int a){ //0 = posts flag that button hit; 1 = posts flag that button hit AND gets rid of dialog; 2 = aborts owner thread
+		buttonMode = a;
+		if (t.dlog !=null)
+			t.dlog.setButtonsVisible(buttonMode!= NOSTOP && !(buttonMode == OFFER_KILL_THREAD && ownerThread != MainThread.mainThread));
+
+	}
+	public int getButtonMode(){ //0 = posts flag that button hit; 1 = posts flag that button hit AND gets rid of dialog; 2 = aborts owner thread
+		return buttonMode;			
+	}
+	public String getStopButtonName(){
+		if (t.dlog !=null)
+			return t.dlog.getStopButtonName();
+		return "Stop";
+	}
+	public void setStopButtonName(String buttonName){
+		if (t.dlog !=null)
+			t.dlog.setStopButtonName(buttonName);
+
+	}
+	public void startTimer() {
+		timer = new MesquiteTimer();
+	}
+
+	//assign
+	public void start(){
+		try {
+			if (getOwnerThread() == null && Thread.currentThread() instanceof MesquiteThread)
+				setOwnerThread((MesquiteThread)Thread.currentThread()); //by default the owner thread is the one that requests the window to start
+			t.start();
+		}
+		catch(IllegalThreadStateException e){
+		}
+	}
+	public void goAway(){
+		if (timer!=null)
+			if (title!= null)
+				MesquiteMessage.println("Total time (for " + title + "): " + timer.timeSinceVeryStart());
+			else 
+				MesquiteMessage.println("Total time operation: " + timer.timeSinceVeryStart());
+		t.stopDLOG();
+		t.interrupt();
+	}
+	public ProgressWindow getProgressWindow(){
+		if (t == null)
+			return null;
+		return t.dlog;
+	}
+	public boolean isVisible(){
+		if (t == null)
+			return false;
+		if (t.dlog == null)
+			return false;
+		return t.dlog.isVisible();
+	}
+	/*.................................................................................................................*/
+	public boolean isAborted () {
+		if (t.dlog!=null)
+			return t.dlog.wasButtonHit() && buttonMode > 0;
+			else
+				return false;
+	}
+	/*.................................................................................................................*/
+	public void spin(){
+		if (t.dlog!=null)
+			t.dlog.spin();
+	}
+	/*.................................................................................................................*/
+	public Color getBarColor(){
+		return barColor;
+	}
+	/*.................................................................................................................*/
+	public Color getBarBackColor(){
+		return barBackColor;
+	}
+	/*.................................................................................................................*/
+	public void setAbort(){
+		if (t.dlog!=null)
+			t.dlog.setAbort();
+	}
+	String offerContinueString = "Are you sure you want to stop?";
+	/*.................................................................................................................*/
+	public void setOfferContinueMessageString(String ocs){
+		offerContinueString = ocs;
+	}
+
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront, boolean immediately) {
+		if (t.dlog!=null)
+			t.dlog.setText(s, bringToFront, immediately);
+		else
+			t.setText (s);
+	}
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront) {
+		if (t.dlog!=null)
+			t.dlog.setText(s, bringToFront);
+		else
+			t.setText (s);
+	}
+	/*.................................................................................................................*/
+	public void setText (String s) {
+		t.setText (s);
+	}
+	/*.................................................................................................................*/
+	public void setSecondaryMessage (String s) {
+		t.setSecondaryMessage(s);
+	}
+	/*.................................................................................................................*/
+	public void setTertiaryMessage (String s) {
+		t.setTertiaryMessage(s);
+	}
+	/*.................................................................................................................*/
+	public long getTextRefreshInterval(){
+		return t.getTextRefreshInterval();
+	}
+	/*.................................................................................................................*/
+	public void setTextRefreshInterval(long interval){
+		t.setTextRefreshInterval(interval);
+	}
+	/*.................................................................................................................*/
+	MesquiteFile scriptingFile;
+	public void setScriptingFile(MesquiteFile file){
+		scriptingFile = file;
+	}
+	public MesquiteFile getScriptingFile(){
+		return scriptingFile;
+	}
+	/*.................................................................................................................*/
+	public void setCurrentValue (long current) {
+		if (t.dlog!=null)
+			t.dlog.setCurrentValue(current);
+	}
+	/*.................................................................................................................*/
+	public void increment () {
+		if (t.dlog!=null){
+			t.dlog.setCurrentValue(t.dlog.getCurrentValue() + 1);
+		}
+	}
+	/*.................................................................................................................*/
+	public long getCurrentValue () {
+		if (t.dlog!=null)
+			return t.dlog.getCurrentValue();
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public void setTitle (String s) {
+		if (t.dlog!=null)
+			t.dlog.setTitle(s);
+	}
+	/*.................................................................................................................*/
+	public void setCurrentAndText (long current, String s) {
+		if (t.dlog!=null)
+			t.dlog.setCurrentAndText(current, s);
+	}
+	/*.................................................................................................................*/
+	public void setTotalValue (long total) {
+		if (t.dlog!=null)
+			t.dlog.setTotalValue(total);
+	}
+	/*.................................................................................................................*/
+	public long getTotalValue () {
+		if (t.dlog!=null)
+			return t.dlog.getTotalValue();
+		else 
+			return 0;
+	}
+
+	public String toString(){
+		String name = "";
+		if (t.dlog!=null)
+			name = t.dlog.getName();
+		return "Progress indicator (" + name + "  id: " + getID()  + "; button mode: "+ getButtonMode()  + ")";
+	}
+}
+
+/* ======================================================================== */
+class ProgressWindowThread extends Thread {
+	ProgressWindow dlog;
+	String title,initialMessage;
+	StringBuffer secondaryMessage = new StringBuffer();
+	StringBuffer tertiaryMessage = new StringBuffer();
+	long textRefreshInterval = 500;
+	long total;
+	String buttonName;
+	boolean dontStart = false;
+	ProgressIndicator progressIndicator=null;
+
+	public ProgressWindowThread (ProgressIndicator progressIndicator, String title, String initialMessage, long total, String buttonName) {
+		this.title = title;
+		this.initialMessage = initialMessage;
+		this.total = total;
+		this.buttonName = buttonName;
+		this.progressIndicator = progressIndicator;
+		if (progressIndicator != null)
+			progressIndicator.dontStart = dontStart;
+	}
+	void setText(String message){
+		this.initialMessage = message;
+		if (dlog !=null)
+			dlog.setText(message);
+	}
+	void setText(String message, boolean immediately){
+		this.initialMessage = message;
+		if (dlog !=null)
+			dlog.setText(message, false, immediately);
+	}
+	/*.................................................................................................................*/
+	public long getTextRefreshInterval(){
+		if (dlog==null)
+			return textRefreshInterval;
+		else
+			return dlog.getTextRefreshInterval();
+	}
+	/*.................................................................................................................*/
+	/** Allows one to set the interval, in milliseconds, between refreshes of the text in the progress indicator.  Default is 500. */
+	public void setTextRefreshInterval(long interval){
+		if (dlog!=null)
+			dlog.setTextRefreshInterval(interval);
+	}
+	void setSecondaryMessage(String message){
+		secondaryMessage.setLength(0);
+		if (message!=null)
+			secondaryMessage.append(message);
+		if (dlog !=null)
+			dlog.setSecondaryMessage(message);
+	}
+	void setTertiaryMessage(String message){
+		tertiaryMessage.setLength(0);
+		if (message!=null)
+			tertiaryMessage.append(message);
+		if (dlog !=null)
+			dlog.setTertiaryMessage(message);
+	}
+	/** DOCUMENT */
+	public void run() {
+		if (!dontStart) {
+			dlog = new ProgressWindow(progressIndicator, title, initialMessage, total, buttonName);
+			if (!dontStart)
+				dlog.setVisible(true); //TODO: if thread doesn't show until after file reading started, and alert appears, could be hidden under this, with STOP being only option
+			if (dontStart) 
+				dlog.hide();
+			/*if (dlog.isVisible()){
+				while (showDialog){
+
+				}
+			}*/
+		}
+	}
+	public void stopDLOG() {
+		dontStart = true;
+		if (progressIndicator != null)
+			progressIndicator.dontStart = dontStart;
+		if (dlog!=null) {
+			dlog.setVisible(false);
+
+
+			if (MesquiteTrunk.isMacOSX() && !MesquiteTrunk.isMacOSXJaguar()){
+				try {
+					Thread.sleep(10); //attempt to workaround bug in 1.3.1 update 1 on OS X
+				}
+				catch(InterruptedException e) {
+					Thread.currentThread().interrupt();
+				}
+			}
+			MesquiteThread.doomIndicator(dlog);
+		}
+	}
+
+	public void interrupt(){
+		dontStart = true;
+		if (progressIndicator != null)
+			progressIndicator.dontStart = dontStart;
+		if (dlog!=null) {
+			dlog.hide();
+			MesquiteThread.doomIndicator(dlog);
+		}
+		super.interrupt();
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/ProgressPanel.java b/Source/mesquite/lib/ProgressPanel.java
new file mode 100644
index 0000000..4608fdb
--- /dev/null
+++ b/Source/mesquite/lib/ProgressPanel.java
@@ -0,0 +1,507 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/** a thermometer panel (see class ProgressIndicator)*/
+public class ProgressPanel extends MesquitePanel implements MouseListener {
+	public ThermoPanel progressBar;
+	public ProgressPanel progressPanel;
+	ProgressWindow pWindow;
+	long currentValue = 0;
+	long totalValue = 0;
+	long textRefreshInterval = 500;
+	public static int visibleProgWindows=0;
+	int defaultDialogHeight = 130;
+	int defaultDialogWidth = 380;
+	int dialogHeight = defaultDialogHeight;
+	int dialogWidth = defaultDialogWidth;
+	int detailsExtraHeight = 220;
+	int barHeight = 20;
+	int barFromSide = 20;
+	int textFromBottom = 8;
+	boolean showDetails = false;
+	int barTop = (dialogHeight-barHeight)/2-5;
+	ProgressIndicator progressIndicator;
+	String buttonName = "Stop";
+	String progressString = "";
+	public boolean buttonWasHit = false;
+	private boolean hidden = false;
+	private boolean disposed = false;
+	Button stop;
+	Panel buttons;
+	Font textFont;
+	public long doomTicks = 0;
+	StringInABox stringInABox2, stringInABox3;
+	boolean inWizard = false;
+
+	int buttonTop=dialogHeight - barHeight - 22; //barHeight +barTop+8;
+	public ProgressPanel (ProgressIndicator progressIndicator, ProgressWindow pWindow, String title, String initialMessage, long total, String buttonName) {
+		setLayout(null);
+		this.progressIndicator=progressIndicator;
+		this.pWindow = pWindow;
+		progressBar = new ThermoPanel();
+		progressBar.setProgressIndicator(progressIndicator);
+		progressBar.setLocation(barFromSide,barTop);
+		progressBar.setSize(dialogWidth-20*2,barHeight);
+		add(progressBar);
+		if (progressIndicator != null){
+			dialogWidth = progressIndicator.width;
+			dialogHeight = progressIndicator.height;
+		}
+		if (showDetails)
+			dialogHeight += detailsExtraHeight;
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+		this.buttonName =buttonName;
+		progressString = initialMessage ;
+
+
+		if (total==0)
+			progressBar.setBackground(ColorDistribution.straw);
+		//	progressBar.setBackground(Color.magenta);
+		progressBar.setVisible(true);
+		setTotalValue(total);
+		progressBar.repaint();
+
+		//addMouseListener(this);
+
+		setSize(dialogWidth, dialogHeight);
+		StringBuffer seco = new StringBuffer("");
+		StringBuffer tert = new StringBuffer("");
+		if (progressIndicator != null){
+			seco = progressIndicator.t.secondaryMessage;
+			tert = progressIndicator.t.tertiaryMessage;
+		}
+		stringInABox2 = new StringInABox(seco, getFont(), dialogWidth-20);
+		stringInABox3 = new StringInABox(tert, getFont(), dialogWidth-20);
+		textFont = new Font ("SanSerif", Font.PLAIN, 10);
+		if (buttonName !=null){
+			buttons = new Panel();
+			Font f2 = new Font ("Dialog", Font.PLAIN, 12);
+			buttons.add("East", stop = new Button(buttonName));
+			//stop.setBackground(Color.white);
+			stop.setFont(f2);
+			stop.setVisible(true);//����
+			stop.requestFocusInWindow();
+			add(buttons);
+			buttons.setLocation(0,buttonTop);
+			buttons.setSize(dialogWidth, barHeight + 16); //dialogHeight - buttonTop);
+			//buttons.setBackground(Color.yellow);
+			//container.add("South", buttons);
+			if (progressIndicator != null)
+				buttons.setVisible(!(progressIndicator.buttonMode == ProgressIndicator.OFFER_KILL_THREAD && progressIndicator.ownerThread != MainThread.mainThread));
+			stop.addMouseListener(this);
+		}
+		resetSizes();
+	}
+	void resetSizes(){
+		progressBar.setLocation(barFromSide,barTop);
+		progressBar.setSize(dialogWidth-20*2,barHeight);
+		progressBar.setVisible(true);
+		progressBar.repaint();
+		if (buttons != null){
+			buttons.setLocation(0,buttonTop);
+			buttons.setSize(dialogWidth, barHeight + 16); //dialogHeight - buttonTop);
+		}
+	}
+	/*
+	public void setVisible(boolean vis){
+		super.setVisible(vis);
+		if (vis){
+			progressBar.requestFocusInWindow();
+		}
+	}*/
+	public void windowClosing(){
+		if (buttonName!=null)
+			buttonHit(buttonName, stop);
+	}
+	public void setStopButtonName(String buttonName){
+		if (stop ==null)
+			return;
+		stop.setLabel(buttonName);
+		if (buttons != null){
+			buttons.invalidate();
+			buttons.validate();
+			buttons.doLayout();
+		}
+	}
+	public String getStopButtonName(){
+		if (stop ==null)
+			return "Stop";
+		return stop.getLabel();
+	}
+	/*.................................................................................................................*/
+	public void buttonHit( String buttonLabel, Button button){
+		if (progressIndicator != null && progressIndicator.buttonMode <ProgressIndicator.OFFER_KILL_THREAD) {
+			setText("");
+			buttonWasHit = true;
+		}
+	}
+	public boolean checkForMouseInDetailTriangle (int mouseX, int mouseY){
+		int y = progressBar.getBounds().y + progressBar.getBounds().height;
+		int x = 10;
+		if (mouseX >= x && mouseX< x + 16 && mouseY >= y && mouseY< y + 16){
+			showDetails = !showDetails;
+			resetShowDetails();
+			return true;
+		}
+		return false;
+	}	
+	public void mouseClicked(MouseEvent e){
+		//	if (e.getComponent() == this){
+		//		checkForMouseInDetailTriangle(e.getX(), e.getY());
+		//	}
+	}
+	private void resetShowDetails(){
+		if (showDetails)
+			dialogHeight = defaultDialogHeight + detailsExtraHeight;
+		else
+			dialogHeight = defaultDialogHeight;
+		pWindow.dialogWidth = dialogWidth;
+		pWindow.dialogHeight = dialogHeight;
+		setSize(dialogWidth, dialogHeight);
+		pWindow.setSize(dialogWidth, dialogHeight);
+		int buttonTop=dialogHeight - barHeight - 22; //barHeight +barTop+8;
+		if (buttons != null)
+			buttons.setLocation(0,buttonTop);
+	}
+
+	public void mouseEntered(MouseEvent e){
+	}
+	public void mouseExited(MouseEvent e){
+	}
+	public void mousePressed(MouseEvent e){
+		if (e.getComponent() == this){
+			if (checkForMouseInDetailTriangle(e.getX(), e.getY()))
+				e.consume();
+		}
+	}
+
+	public void mouseReleased(MouseEvent e){
+		if (e.getComponent() instanceof Button) {
+			if (progressIndicator == null)
+				return;
+			if (progressIndicator.buttonMode== ProgressIndicator.OFFER_CONTINUE){
+				if (!AlertDialog.query(this, "Stop?", progressIndicator.offerContinueString, "Continue", "Stop", 1)){
+					buttonHit(((Button)e.getComponent()).getLabel(), (Button)e.getComponent());
+					hide();
+					MesquiteThread.doomIndicator(this);
+				}
+			}
+			else if (progressIndicator.buttonMode<ProgressIndicator.OFFER_KILL_THREAD) {
+				buttonHit(((Button)e.getComponent()).getLabel(), (Button)e.getComponent());
+				if (progressIndicator.buttonMode== ProgressIndicator.FLAG_AND_HIDE){
+					hide();
+					MesquiteThread.doomIndicator(this);
+				}
+			}
+			else if (progressIndicator.buttonMode == ProgressIndicator.OFFER_KILL_THREAD) {
+				if (progressIndicator.getOwnerThread()!=null) {
+					if (progressIndicator.getOwnerThread() == MainThread.mainThread && MainThread.mainThread != Thread.currentThread()){
+						if (AlertDialog.query(this, "Cancel?", "Are you sure you want to cancel the command?  Cancelling in this way will stop the command immediately regardless of the consequences.  Various errors may occur, you may lose unsaved data, and your calculations may be incomplete or incorrect.  It is recommended that you cancel only when you absolutely need to.", "Continue", "Cancel Command", 1))
+							return;
+
+
+						hide();
+						MesquiteDialog.cleanUpWizard();
+						MainThread.mainThread.doCleanUp();
+						MesquiteThread.doomIndicator(this);
+						if (MainThread.getCurrentlyExecuting()!=null)
+							MainThread.getCurrentlyExecuting().interrupted = true;
+						
+						try {
+							MainThread.mainThread.interrupt();
+						}
+						catch (Exception ex){
+							MesquiteMessage.println("Exception cancelling command");
+							MesquiteMessage.printStackTrace(ex);
+						}
+						if (MainThread.getCurrentlyExecuting()!=null)
+							MesquiteTrunk.mesquiteTrunk.alert("Command stopped: " + MainThread.getCurrentlyExecuting().getListName() + ".  Because this command was stopped by an emergency cancel, it is possible that some calculations or operations were partially completed, and MESQUITE MAY NOW BE UNSTABLE.  IT IS HIGHLY RECOMMENDED THAT YOU RESTART MESQUITE.  If you need to save your file, is best to use \"Save As\"."); 
+						else 
+							MesquiteTrunk.mesquiteTrunk.alert("Command stopped.  Because this command was stopped by an emergency cancel, it is possible that some calculations or operations were partially completed, and MESQUITE MAY NOW BE UNSTABLE.  IT IS HIGHLY RECOMMENDED THAT YOU RESTART MESQUITE.  If you need to save your file, is best to use \"Save As\"."); 
+						MainThread.emergencyCancelled = true;
+						MainThread.mainThread = new MainThread();
+						MainThread.mainThread.start();
+					}
+				}
+			}
+			else if (progressIndicator.buttonMode == ProgressIndicator.OFFER_FLAG_OR_KILL_THREAD) {
+				int response = AlertDialog.query(this, "Stop?", "Do you want to stop the file reading gracefully, after the next commands are processed, or do you want to cancel command processing immediately?  The latter is not recommended except in cases of emergency, as it will leave the file still open but with portions missing or analyses incomplete.", "Continue", "Stop Gracefully", "Emergency Cancel", 2);
+
+				if (response == 0)
+					return;
+
+				if (response == 1){
+					buttonHit(((Button)e.getComponent()).getLabel(), (Button)e.getComponent());
+					hide();
+					MesquiteThread.doomIndicator(this);
+				}
+				else if (progressIndicator.getOwnerThread()  != Thread.currentThread()){
+					if (progressIndicator.getScriptingFile() !=null){
+						progressIndicator.getScriptingFile().closeReading(); //needed so that thread can later be interrupted
+					}
+
+					if (progressIndicator.getOwnerThread() == MainThread.mainThread ){
+						hide();
+						MesquiteThread.doomIndicator(this);
+						if (MainThread.getCurrentlyExecuting()!=null)
+							MainThread.getCurrentlyExecuting().interrupted = true;
+						try {
+							MainThread.mainThread.interrupt();
+						}
+						catch (Exception ex){
+							MesquiteMessage.println("Exception cancelling command");
+							MesquiteMessage.printStackTrace(ex);
+						}
+						if (MainThread.getCurrentlyExecuting()!=null)
+							MesquiteTrunk.mesquiteTrunk.alert("Command stopped: " + MainThread.getCurrentlyExecuting().getListName() + ".  Because this command was stopped by an emergency cancel, it is possible that some calculations or operations were partially completed, and MESQUITE MAY NOW BE UNSTABLE.  IT IS HIGHLY RECOMMENDED THAT YOU RESTART MESQUITE.  If you need to save your file, is best to use \"Save As\"."); 
+						else
+							MesquiteTrunk.mesquiteTrunk.alert("Command stopped.  Because this command was stopped by an emergency cancel, it is possible that some calculations or operations were partially completed, and MESQUITE MAY NOW BE UNSTABLE.  IT IS HIGHLY RECOMMENDED THAT YOU RESTART MESQUITE.  If you need to save your file, is best to use \"Save As\"."); 
+						MainThread.emergencyCancelled = true;
+						MainThread.mainThread = new MainThread();
+						MainThread.mainThread.start();
+					}
+					else {
+						hide();
+						MesquiteThread.doomIndicator(this);
+						progressIndicator.getOwnerThread().interrupt();  //currently this doesn't work on file read, perhaps because of open stream
+					}
+				}
+			}
+			else if (progressIndicator.buttonMode == ProgressIndicator.OFFER_CONTINUE_FORCEQUIT) {
+				if (!AlertDialog.query(this, "Force Quit?", "Do you want to continue or force quit Mesquite? If you Force Quit, changes may be lost", "Continue", "Force Quit"))
+					MesquiteTrunk.mesquiteTrunk.exit(true, 0);
+
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	int secondaryOffset = 20;
+	int tertiaryOffset = secondaryOffset+40;
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+
+		int y = progressBar.getBounds().y + progressBar.getBounds().height;
+		int h = progressBar.getBounds().x;
+
+		g.setFont(textFont);
+		/*	if (inWizard){
+
+				g.setColor(getBackground());
+
+			g.fillRect(h-15,barTop-textFromBottom-30,dialogWidth, tertiaryOffset+secondaryOffset);
+		}
+		 */
+		g.setColor(Color.black);
+
+
+		g.drawString(progressString, h-10,  barTop-textFromBottom);
+		if (progressIndicator != null && (progressIndicator.t.secondaryMessage.length()>0 || progressIndicator.t.tertiaryMessage.length()>0)){
+			g.drawString("Details", h+8,  y + secondaryOffset -8);
+			g.drawLine(h,  y + secondaryOffset, dialogWidth - 20, y + secondaryOffset);
+			if (showDetails){
+				g.drawImage(InfoBar.triangleImageDown, h-10, y, this);
+				if (progressIndicator.t.secondaryMessage.length()>0){
+					stringInABox2.setStringAndFont(progressIndicator.t.secondaryMessage, g.getFont());
+					stringInABox2.draw(g, h-10,  y + secondaryOffset);
+				}
+				if (progressIndicator.t.tertiaryMessage.length()>0){
+					stringInABox3.setStringAndFont(progressIndicator.t.tertiaryMessage, g.getFont());
+					stringInABox3.draw(g, h-10,  y + tertiaryOffset);
+				}
+			}
+			else {
+				g.drawImage(InfoBar.triangleImage, h-10, y, this);
+			}
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	private void drawProgressText () {
+		try {
+
+			Graphics g=getGraphics();
+			if (g != null) {
+				update(g);
+				g.dispose();
+			}
+		}
+		catch (NullPointerException e){
+			return;
+		}
+	}
+	/*.................................................................................................................*/
+	private void drawSecondaryMessage () {
+		if (!showDetails || MesquiteWindow.checkDoomed(this))
+			return;
+
+		Graphics g=getGraphics();
+		if (g != null) {
+			g.setFont(textFont);
+			g.setColor(getBackground());
+			int y = progressBar.getBounds().y + progressBar.getBounds().height;
+			g.fillRect(5,y + secondaryOffset -1,dialogWidth, tertiaryOffset-secondaryOffset);
+			g.setColor(Color.black);
+			if (progressIndicator  != null && progressIndicator.t.secondaryMessage.length()>0){
+				//g.drawString("Details", 28,  y + secondaryOffset -8);
+				g.drawLine(20,  y + secondaryOffset, dialogWidth - 20, y + secondaryOffset);
+				g.drawImage(InfoBar.triangleImageDown, 10, y, this);
+				stringInABox2.setStringAndFont(progressIndicator.t.secondaryMessage, g.getFont());
+				stringInABox2.draw(g, 10,  y + secondaryOffset);
+			}
+			g.dispose();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	private void drawTertiaryMessage () {
+		if (!showDetails || MesquiteWindow.checkDoomed(this))
+			return;
+		Graphics g=getGraphics();
+		if (g != null) {
+			g.setFont(textFont);
+			g.setColor(getBackground());
+			int y = progressBar.getBounds().y + progressBar.getBounds().height;
+			g.fillRect(5,y + tertiaryOffset-1,dialogWidth, dialogHeight);
+			g.setColor(Color.black);
+			//g.drawString(progressString, 10,  barTop-textFromBottom);
+			if (progressIndicator  != null && progressIndicator.t.tertiaryMessage.length()>0){
+				//g.drawString("Details", 28,  y + secondaryOffset -8);
+				g.drawLine(20,  y + secondaryOffset, dialogWidth - 20, y + secondaryOffset);
+				g.drawImage(InfoBar.triangleImageDown, 10, y, this);
+				stringInABox3.setStringAndFont(progressIndicator.t.tertiaryMessage, g.getFont());
+				stringInABox3.draw(g, 10,  y + tertiaryOffset);
+			}
+			g.dispose();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public void setAbort(){
+		buttonWasHit = true;
+	}
+
+	/*.................................................................................................................*/
+	public long getTextRefreshInterval(){
+		return textRefreshInterval;
+	}
+	/*.................................................................................................................*/
+	public void setTextRefreshInterval(long interval){
+		textRefreshInterval = interval;
+	}
+	long lastText = 0;
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront) {
+		setText(s, bringToFront, false);
+	}
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront, boolean immediately) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		progressString = s;
+		long c = System.currentTimeMillis();
+		if (immediately || c-lastText > textRefreshInterval) {
+			lastText = c;
+			drawProgressText();
+		}
+		if (bringToFront && MesquiteWindow.numNonWizardDialogs<=1)
+			setVisible(true);
+	}
+	long lastSecondary = 0;
+	/*.................................................................................................................*/
+	public void setSecondaryMessage (String s) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		long c = System.currentTimeMillis();
+		if (c-lastSecondary > textRefreshInterval) {
+			lastSecondary = c;
+			drawSecondaryMessage();
+		}
+	}
+	/*.................................................................................................................*/
+	public void setTertiaryMessage (String s) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		drawTertiaryMessage();
+	}
+	/*.................................................................................................................*/
+	public void spin () {
+		currentValue = 0;
+		totalValue = 0;
+		progressBar.setTime(totalValue, currentValue);
+		Graphics g = progressBar.getGraphics();
+		if (g !=null) {
+			progressBar.spin(g);
+			g.dispose();
+		}
+		else
+			progressBar.repaint();
+	}
+	/*.................................................................................................................*/
+	public void setText (String s) {
+		setText(s, false);  //default changed here so that doesn't bring to front by default
+	}
+	/*.................................................................................................................*/
+	public void setCurrentValue (long current) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		currentValue = current;
+		progressBar.setTime(totalValue, currentValue);
+		if (inWizard)
+			resetSizes();
+		progressBar.repaint();
+		//	if (inWizard)
+		//		repaint();
+		//setVisible(true);
+	}
+	/*.................................................................................................................*/
+	public long getCurrentValue () {
+		return currentValue;
+	}
+	/*.................................................................................................................*/
+	public void setCurrentAndText (long current, String s) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		progressString = s;
+		currentValue = current;
+		drawProgressText();
+		progressBar.setTime(totalValue, currentValue);
+		if (inWizard)
+			resetSizes();
+		progressBar.repaint();
+		//	if (inWizard)
+		//		repaint();
+		//setVisible(true);
+	}
+	/*.................................................................................................................*/
+	public void setTotalValue (long total) {
+		if (buttonWasHit && progressIndicator  != null && progressIndicator.buttonMode == 1)
+			return;
+		totalValue = total;
+		progressBar.setTime(totalValue, currentValue);
+	}
+	/*.................................................................................................................*/
+	public long getTotalValue () {
+		return totalValue;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ProgressWindow.java b/Source/mesquite/lib/ProgressWindow.java
new file mode 100644
index 0000000..db202fc
--- /dev/null
+++ b/Source/mesquite/lib/ProgressWindow.java
@@ -0,0 +1,296 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+/** a thermometer window (see class ProgressIndicator)*/
+public class ProgressWindow extends Frame implements Listable, WindowListener, ComponentListener {
+	public ProgressPanel progressPanel;
+	long textRefreshInterval = 500;
+	public static int visibleProgWindows=0;
+	int defaultDialogHeight = 130;
+	int defaultDialogWidth = 380;
+	int dialogHeight = defaultDialogHeight;
+	int dialogWidth = defaultDialogWidth;
+	int detailsExtraHeight = 220;
+	boolean showDetails = false;
+	ProgressIndicator progressIndicator;
+	private boolean hidden = false;
+	private boolean disposed = false;
+	Font textFont;
+	public long doomTicks = 0;
+	boolean inWizard = false;
+	boolean useWizard = false;
+	public static Vector allIndicators;
+	static {
+		allIndicators = new Vector();
+	}
+	public ProgressWindow (ProgressIndicator progressIndicator, String title, String initialMessage, long total, String buttonName) {
+		super(title);
+		setLayout(null);
+		this.progressIndicator=progressIndicator;
+		progressPanel = new ProgressPanel(progressIndicator, this, title,  initialMessage,  total,  buttonName);
+		if (useWizard && MesquiteDialog.currentWizard != null){  //not used
+			inWizard = true;
+			MesquiteDialog.currentWizard.waitPanel.showWait = false;
+			MesquiteDialog.currentWizard.waitPanel.repaint();
+			MesquiteDialog.currentWizard.waitPanel.add(progressPanel);
+			MesquiteDialog.currentWizard.pleaseRequestFocus();
+		}
+		else 
+			add(progressPanel);
+
+		dialogWidth = progressIndicator.width;
+		dialogHeight = progressIndicator.height;
+		if (showDetails)
+			dialogHeight += detailsExtraHeight;
+	//	setBackground(ColorDistribution.paleGoldenRod); //.light[0]); //ggray
+		setBackground(ColorTheme.getInterfaceBackgroundPale()); //.light[0]); //ggray
+
+
+		setTotalValue(total);
+
+
+		setSize(dialogWidth, dialogHeight);
+		progressPanel.setSize(dialogWidth, dialogHeight);
+		if (inWizard){
+			progressPanel.setLocation(100, 100);
+			//progressPanel.setBackground(Color.green);
+			progressPanel.setVisible(true);
+			MesquiteDialog.currentWizard.pleaseRequestFocus();
+		}
+		addWindowListener(this);
+
+		this.setResizable(false);
+		MesquiteWindow.centerWindowTile(this,visibleProgWindows);
+	}
+	public static void allIndicatorsToFront(){
+		for (int i = 0; i< allIndicators.size(); i++){
+			ProgressWindow w = (ProgressWindow)allIndicators.elementAt(i);
+			w.toFront();
+		}
+	}
+	public boolean isSpontaneous(){
+		return progressIndicator.getIsFromWatcher();
+	}
+	public void show(){
+		if (MesquiteWindow.suppressAllWindows)
+			return;
+		if (progressIndicator.dontStart)
+			return;
+		hidden = false;
+		if (!inWizard)
+			super.show();
+		else {
+			progressPanel.setVisible(true);
+			MesquiteDialog.currentWizard.pleaseRequestFocus();
+		}
+		registerProgressWindow(true);
+
+	}
+	boolean countedInTotal = false;
+	private void registerProgressWindow(boolean r){
+		if (r){
+			if (allIndicators.indexOf(this)<0){
+			if (!inWizard)
+				ProgressWindow.visibleProgWindows++;
+				allIndicators.addElement(this);
+			countedInTotal = true;
+			}
+		}
+		else {
+			if (allIndicators.indexOf(this)>=0){
+				if (!inWizard)
+			ProgressWindow.visibleProgWindows--;
+			allIndicators.removeElement(this);
+			countedInTotal = false;
+			}
+		}
+	}
+	public void setVisible(boolean vis){
+		if (!MesquiteWindow.GUIavailable || MesquiteWindow.suppressAllWindows)
+			return;
+		if (vis && (MesquiteThread.getSuppressAllProgressIndicators(Thread.currentThread())) || MesquiteThread.getSuppressAllProgressIndicators(progressIndicator.ownerThread))
+			return;
+
+
+		if (vis)
+			hidden = false;
+		//if (vis && !isVisible())
+		//	pack();
+		registerProgressWindow(vis);
+		if (!inWizard){
+			super.setVisible(vis);
+		}
+		else if (!vis){
+			progressPanel.setVisible(vis);
+			MesquiteDialog.currentWizard.waitPanel.showWait = true;
+		}
+		else {
+			progressPanel.setVisible(vis);
+			MesquiteDialog.currentWizard.pleaseRequestFocus();
+		}
+	}
+	public String getName(){
+		return getTitle();// + " id " + getID();
+	}
+	public void hide(){
+		if (!hidden){
+			super.hide();
+			if (inWizard){
+				MesquiteDialog.currentWizard.waitPanel.showWait = true;
+			}
+			registerProgressWindow(false);
+
+			hidden = true;
+		}
+	}
+
+	public void dispose(){
+
+		if (!disposed){
+			removeAll();
+			if (inWizard){
+				progressPanel.removeAll();
+				//progressPanel.setVisible(false);
+			}
+			disposed = true;
+			super.dispose();
+			registerProgressWindow(false);
+
+		}
+
+
+	}
+
+	public void setStopButtonName(String buttonName){
+		progressPanel.setStopButtonName(buttonName);
+	}
+	public String getStopButtonName(){
+		return 		progressPanel.getStopButtonName();
+
+	}
+	
+	/*.................................................................................................................*/
+	public void componentResized(ComponentEvent e){
+		if (getBounds().height !=dialogHeight || getBounds().width != dialogWidth){
+			setSize(dialogWidth, dialogHeight);
+			progressPanel.setSize(dialogWidth, dialogHeight);
+		}
+	}
+	public void componentMoved(ComponentEvent e){
+	}
+	public void componentHidden(ComponentEvent e){
+	}
+	public void componentShown(ComponentEvent e){
+
+		Toolkit.getDefaultToolkit().sync();
+	}
+
+	/*.................................................................................................................*/
+	public void windowActivated(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowClosed(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowClosing(WindowEvent e) {
+		progressPanel.windowClosing();
+	}
+	/*.................................................................................................................*/
+	public void windowDeactivated(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowDeiconified(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowIconified(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowOpened(WindowEvent e) {
+	}
+
+	public void setButtonsVisible(boolean vis){
+		if (progressPanel == null || progressPanel.buttons == null)
+			return;
+		progressPanel.buttons.setVisible(vis);
+	}
+	public boolean wasButtonHit(){
+		return progressPanel.buttonWasHit;
+	}
+	/*.................................................................................................................*/
+	public void setAbort(){
+		progressPanel.setAbort();
+	}
+
+	/*.................................................................................................................*/
+	public long getTextRefreshInterval(){
+		return progressPanel.getTextRefreshInterval();
+	}
+	/*.................................................................................................................*/
+	public void setTextRefreshInterval(long interval){
+		progressPanel.setTextRefreshInterval(interval);
+	}
+	long lastText = 0;
+	/*.................................................................................................................*/
+	public void setText (String s) {
+		setText(s, false);  //default changed here so that doesn't bring to front by default
+	}
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront) {
+		progressPanel.setText(s, bringToFront);
+	}
+	/*.................................................................................................................*/
+	public void setText (String s, boolean bringToFront, boolean immediately) {
+		progressPanel.setText(s, bringToFront, immediately);
+	}
+	long lastSecondary = 0;
+	/*.................................................................................................................*/
+	public void setSecondaryMessage (String s) {
+		progressPanel.setSecondaryMessage(s);
+	}
+	/*.................................................................................................................*/
+	public void setTertiaryMessage (String s) {
+		progressPanel.setTertiaryMessage(s);
+	}
+	/*.................................................................................................................*/
+	public void spin () {
+		progressPanel.spin();
+	}
+	/*.................................................................................................................*/
+	public void setCurrentValue (long current) {
+		progressPanel.setCurrentValue(current);
+	}
+	/*.................................................................................................................*/
+	public long getCurrentValue () {
+		return progressPanel.getCurrentValue();
+	}
+	/*.................................................................................................................*/
+	public void setCurrentAndText (long current, String s) {
+		progressPanel.setCurrentAndText(current, s);
+	}
+	/*.................................................................................................................*/
+	public void setTotalValue (long total) {
+		progressPanel.setTotalValue(total);
+	}
+	/*.................................................................................................................*/
+	public long getTotalValue () {
+		return progressPanel.getTotalValue();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ProjPanelCommand.java b/Source/mesquite/lib/ProjPanelCommand.java
new file mode 100644
index 0000000..04366d4
--- /dev/null
+++ b/Source/mesquite/lib/ProjPanelCommand.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+import java.util.*;
+
+public class ProjPanelCommand {
+	public boolean menuOnly;
+	public String iconFileName;
+	public String label;
+	public String shortLabel;
+	public MesquiteCommand command;
+	public Image icon=null;
+	public int left = -1;
+	public int right = -1;
+	public ProjPanelCommand(boolean menuOnly, String iconFileName, String label, String shortLabel, MesquiteCommand command){
+		this.menuOnly =menuOnly;
+		this.iconFileName =iconFileName;
+		this.label =label;
+		this.shortLabel =shortLabel;
+		this.command =command;
+	}
+}
diff --git a/Source/mesquite/lib/ProjPanelPanel.java b/Source/mesquite/lib/ProjPanelPanel.java
new file mode 100644
index 0000000..fe18183
--- /dev/null
+++ b/Source/mesquite/lib/ProjPanelPanel.java
@@ -0,0 +1,436 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTarget;
+import java.util.*;
+import java.util.List;
+
+import mesquite.lib.duties.*;
+import mesquite.minimal.BasicFileCoordinator.ProjectWindow;
+
+/* ======================================================================== */
+/**An interface for a set of trees or a tree source.*/
+public class ProjPanelPanel extends ClosablePanel implements MesquiteListener, ClosablePanelContainer, MesquiteDroppedFileHandler {
+	protected Vector commands = new Vector();
+	protected MesquitePopup popup=null;
+	protected FileCoordinator bfc;
+	protected StringInABox notes, commandBox;
+	protected int notesWidth = 560;
+	protected int notesLeft = 10;
+	protected int commandBoxWidth = 64;
+	protected int COMMANDHEIGHT = 64 - MINHEIGHT;
+	protected Image im;
+	protected Vector subPanels = new Vector();
+	protected MesquiteWindow w = null;
+	MesquiteModule owner;
+	ProjectWindow projectWindow;
+
+	public ProjPanelPanel(FileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, String name, MesquiteModule owner){
+		super(container, name);
+		this.owner = owner;
+		
+		this.w = w;
+		projectWindow = (ProjectWindow)w;
+		setOpen(false);
+		setColors(ColorTheme.getExtInterfaceBackground(), ColorTheme.getExtInterfaceBackground(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		
+		this.bfc = bfc;
+		if (getIconFilePath() != null)
+			im = 	MesquiteImage.getImage(getIconFilePath());
+		currentHeight = COMMANDHEIGHT + MINHEIGHT;
+
+		setTightness(2);
+		notes =  new StringInABox(getNotes(), new Font("SansSerif", Font.PLAIN, MesquiteFrame.resourcesFontSize), notesWidth);
+		commandBox =  new StringInABox(getNotes(), new Font("SansSerif", Font.PLAIN, MesquiteFrame.resourcesFontSize), commandBoxWidth);
+		dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);  
+
+		refresh();
+	}
+	public void setOpen(boolean b){
+		super.setOpen(false);  //sorry, closed only
+	}
+	public boolean isOpen(){
+		return false;
+	}
+public void resetTitle(){
+	}
+	public MesquiteModule getOwnerModule(){
+		return owner;
+	}
+	protected int getFontSize(){
+		return MesquiteFrame.resourcesFontSize;
+	}
+	public void refreshGraphics(){
+		if (getBold())
+			setFont(new Font("SansSerif", Font.BOLD, getFontSize()));
+		else
+			setFont(new Font("SansSerif", Font.PLAIN, getFontSize()));
+		notes.setFont(new Font("SansSerif", Font.PLAIN, MesquiteFrame.resourcesFontSize));
+		commandBox.setFont(new Font("SansSerif", Font.PLAIN, MesquiteFrame.resourcesFontSize));
+		setColors(ColorTheme.getExtInterfaceBackground(), ColorTheme.getExtInterfaceBackground(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		repaint();
+		if (subPanels != null)
+			for (int i = 0; i<subPanels.size(); i++){
+				ProjPanelPanel p = (ProjPanelPanel)subPanels.elementAt(i);
+				p.refreshGraphics();
+			}
+	}
+	public void actUponDroppedFileContents(FileInterpreter fileInterpreter, String droppedContents) {
+	}
+	public FileInterpreter findFileInterpreter(String droppedContents, String fileName) {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void processFilesDroppedOnPanel(List files) {
+	}
+	/*.................................................................................................................*/
+	public void processFileStringDroppedOnPanel(String path) {
+	}
+
+	public void refreshIcon(){
+		if (getIconFilePath() != null)
+			im = 	MesquiteImage.getImage(getIconFilePath());
+		else
+			im = null;
+	}
+	/*.................................................................................................................*/
+	public String getIconFilePath(){ //for small 16 pixel icon at left of main bar
+		if (getIconFileName() != null) {
+			String p = bfc.getPath()+ "projectHTML" + MesquiteFile.fileSeparator + getIconFileName();
+			return p;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getIconFileName(){ //for small 16 pixel icon at left of main bar
+		return null;
+	}
+	public Image getIcon(){ //for small 16 pixel icon at left of main bar
+		return im;
+	}
+	public int requestSpacer(){
+		return 0;
+	}
+	public String getNotes(){
+		return null;
+	}
+	public String getFootnote(){
+		return null;
+	}
+	public String getFootnoteHeading(){
+		return null;
+	}
+		
+	public void cursorEnter(){
+		String text = getFootnote();
+		String heading = getFootnoteHeading();
+		
+		hover = true;
+		repaint();
+		projectWindow.setFootnote(heading, text);
+	}
+
+	public void cursorExit(){
+		hover = false;
+		repaint();
+		projectWindow.setFootnote(null,null);
+	}
+	public boolean upToDate(){
+		return true;
+	}
+	public void setColors(Color bgTopColor, Color bgBottomColor, Color barColor, Color textColor){
+		super.setColors(bgTopColor, bgBottomColor, barColor, textColor);
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			panel.setColors(bgBottomColor, bgBottomColor, bgBottomColor, textColor);
+		}
+	}
+	public void refresh(){
+		if (upToDate()) {
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			return;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		subPanels.removeAllElements();
+	}
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel){
+		return null;
+	}
+	void chart(){  //to be overridden to respond to command to chart the element
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+			refresh();
+	}
+	/*.................................................................................................................*/
+
+	public void paint(Graphics g){
+		if (!sizesMatch(getWidth(), getHeight())){
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			repaint();
+			return;
+		}
+		g.setColor(ColorTheme.getExtInterfaceTextMedium());
+		int nH = 0;
+		if (!StringUtil.blank(getNotes())){
+			String s = notes.getString();
+			if (s != null && !s.equals(getNotes()))
+				notes.setString(getNotes());
+			notes.draw(g,notesLeft, MINHEIGHT-4);
+			nH = 16;
+		}
+		g.setColor(barColor);
+		g.fillRect(0, getHeight()-2, getWidth(), 2);
+		g.setColor(ColorTheme.getExtInterfaceTextMedium());
+		if (commands.size()>0){
+			int left = notesLeft;
+			for (int i=0; i<commands.size(); i++){
+				ProjPanelCommand ec = (ProjPanelCommand)commands.elementAt(i);
+				if (!ec.menuOnly){
+					ec.left=left;
+					if (ec.icon !=null){
+						Composite comp = ((Graphics2D)g).getComposite();
+						ColorDistribution.setTransparentGraphics(g,0.8f);		
+						g.drawImage(ec.icon, left, MINHEIGHT+nH + 4, this);
+						((Graphics2D)g).setComposite(comp);
+						left += ec.icon.getWidth(this) + 2;
+					}
+					if (ec.label != null){
+						commandBox.setString(ec.label);
+						g.setColor(ColorTheme.getExtInterfaceTextLink());
+						commandBox.draw(g,left, MINHEIGHT+nH);
+
+						g.setColor(ColorTheme.getExtInterfaceTextMedium());
+						left += commandBox.getMaxWidthDrawn() + 2;
+					}
+					ec.right=left;
+					left += 12;
+
+				}
+			}
+
+		}
+		super.paint(g);
+	}	
+	protected void addExtraPanel(ProjPanelPanel p, boolean doReset){
+		subPanels.addElement(p);
+		add(p);
+		if (doReset) {
+			resetSizes(getWidth(), getHeight());
+			p.setVisible(true);
+		}
+	}
+	public void repaintAllPanels(){
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			panel.repaint();
+		}
+	}
+	public void requestHeightChange(ClosablePanel panel){
+		resetSizes(getWidth(), getHeight());
+		container.requestHeightChange(this);
+	}
+	static final int indent = 20;
+	protected void resetSizes(int w, int h){
+		if (bfc.isDoomed() || bfc.getProject().refreshSuppression>0)
+			return;
+		if (!isOpen()){
+			for (int i = 0; i<subPanels.size(); i++){
+				ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+				panel.setBounds(0, 0, 0, 0);
+				panel.setVisible(false);
+			}
+			return;
+		}
+
+		int vertical = MINHEIGHT+2;
+		if (anyGraphicalCommands())
+			vertical += COMMANDHEIGHT;
+		if (getNotes() != null)
+			vertical += 24;
+
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			int requestedlHeight = panel.getRequestedHeight(w);
+			panel.setVisible(false);
+			panel.setBounds(indent, vertical, w-indent, requestedlHeight);
+			panel.setVisible(true);
+
+			vertical += requestedlHeight;
+		}
+	}
+	boolean sizesMatch(int w, int h){
+		if (!isOpen()){
+			for (int i = 0; i<subPanels.size(); i++){
+				ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+				if (panel.getWidth() != 0 || panel.getHeight() != 0)
+					return false;
+
+			}
+			return true;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			int requestedlHeight = panel.getRequestedHeight(w);
+			if (panel.getWidth() != w-indent || panel.getHeight() != requestedlHeight)
+				return false;
+		}
+		return true;
+	}
+	boolean anyGraphicalCommands(){
+		if (commands.size() == 0)
+			return false;
+		for (int i=0; i<commands.size(); i++){
+			ProjPanelCommand ec = (ProjPanelCommand)commands.elementAt(i);
+			if (!ec.menuOnly)
+				return true;
+
+		}
+		return false;
+	}
+	public int getRequestedHeight(int width){
+		if (!isOpen())
+			return MINHEIGHT;
+		int total = MINHEIGHT+5;
+		if (anyGraphicalCommands())
+			total += COMMANDHEIGHT;
+		if (getNotes() != null)
+			total += 24;
+		for (int i=0; i<subPanels.size(); i++){
+			ClosablePanel mp = (ClosablePanel)subPanels.elementAt(i);
+			total += mp.getRequestedHeight(width-20);
+		}
+		return total;
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		resetSizes(w, h);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		resetSizes(w, h);
+	}	
+	public void deleteAllCommands(){
+		commands.removeAllElements();
+	}
+	public void addCommand(boolean menuOnly, String iconFileName, String label, String shortLabel, MesquiteCommand command){
+		ProjPanelCommand ec = new ProjPanelCommand(menuOnly, iconFileName, label, shortLabel, command);
+		if (iconFileName != null)
+			ec.icon = MesquiteImage.getImage(bfc.getPath() + "projectHTML" + MesquiteFile.fileSeparator + iconFileName);
+
+		commands.addElement(ec);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Charts the file element", null, commandName, "chart")) {
+			chart();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void disposing(Object obj){
+
+	}
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		//if modifiers include right click/control, then do dropdown menu
+		if (MesquiteEvent.rightClick(modifiers) || y<= MINHEIGHT && x> triangleOffset + 8) {
+			redoMenu();
+			popup.show(this, x,y);
+			return;
+		}
+
+		else if (y<= MINHEIGHT) {
+			super.mouseDown(modifiers,  clickCount,  when,  x,  y,  tool);
+			return;
+		}
+		else {
+			for (int i=0; i<commands.size(); i++){
+				ProjPanelCommand ec = (ProjPanelCommand)commands.elementAt(i);
+				if (!ec.menuOnly){
+					if (x>=ec.left && x<ec.right){
+						ec.command.doItMainThread(null, null, this);
+						repaint();
+						return;
+					}
+
+				}
+			}
+		}
+	}
+
+	protected String getMenuHeading(){
+		String heading = getTitle();
+		return heading;
+	}
+	protected void resetCommands(){ //use this only if last minute command changes might exist
+	}
+	/*.................................................................................................................*/
+	void redoMenu() {
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		resetCommands();
+		popup.removeAll();
+		String heading = getMenuHeading();
+		popup.add(new MesquiteMenuItem(heading, bfc, null));
+		for (int i=0; i<commands.size(); i++) {
+			ProjPanelCommand m = (ProjPanelCommand)commands.elementAt(i);
+			MesquiteMenuItem mItem = new MesquiteMenuItem(m.shortLabel, bfc, m.command);
+			popup.add(mItem);
+		}
+		add(popup);
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseEntered(modifiers, x, y, tool);
+		cursorEnter();
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseMoved(modifiers, x, y, tool);
+		cursorEnter();
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		super.mouseExited(modifiers, x, y, tool);
+		cursorExit();
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!MesquiteEvent.rightClick(modifiers) && y<= MINHEIGHT) {
+			super.mouseUp(modifiers,  x,  y,  tool);
+			return;
+		}
+	}
+	public void dispose(){
+		if (popup!=null)
+			remove(popup);
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			panel.dispose();
+		}
+		super.dispose();
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/ProjectRead.java b/Source/mesquite/lib/ProjectRead.java
new file mode 100644
index 0000000..99c78cb
--- /dev/null
+++ b/Source/mesquite/lib/ProjectRead.java
@@ -0,0 +1,265 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ProjectRead implements Runnable {
+	String arguments;
+	int  category;
+	MesquiteModule mesquite;
+	ObjectContainer projCont = null;
+	public static int totalCreated = 0; //to find memory leaks
+	public static int totalFinalized = 0;
+	boolean wasScripting;
+	public InputStream stream;
+	public ProjectRead (String arguments,  int  category, MesquiteModule mesquite, ObjectContainer p) {
+		projCont = p;
+		this.arguments = arguments;
+		wasScripting = MesquiteThread.isScripting();
+		this.category = category;
+		this.mesquite = mesquite;
+		totalCreated++;
+		//spontaneousIndicator = false;
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	public String getCurrentCommandName(){
+		return "Reading file";
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject openGeneral(String arguments){
+		mesquite.incrementMenuResetSuppression();
+		FileCoordinator mb = (FileCoordinator)mesquite.hireEmployee(FileCoordinator.class, null); //if this could be scripted, pass into method
+		if (mb==null)
+			mesquite.alert("Mesquite cannot function: no file coordinator available");
+		else {
+			mesquite.logln("Opening external");
+			Date d = new Date(System.currentTimeMillis());
+			mesquite.logln("     at " + d.toString());
+			/*===getting project===*/
+			CommandRecord comRec = new CommandRecord(wasScripting);
+			CommandRecord prevRec = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(comRec);
+			mb.readProjectGeneral(arguments);
+			MesquiteThread.setCurrentCommandRecord(prevRec);
+			/*================*/
+			mesquite.resetAllMenuBars();
+			mesquite.decrementMenuResetSuppression();
+			MesquiteProject project =mb.getProject();
+			if (projCont != null)
+				projCont.setObject(project);
+			if (project==null)
+				mb.iQuit();
+			return project;
+		}
+		mesquite.decrementMenuResetSuppression();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject openURLString(String urlString){
+		mesquite.incrementMenuResetSuppression();
+		FileCoordinator mb = (FileCoordinator)mesquite.hireEmployee(FileCoordinator.class, null); //if this could be scripted, pass into method
+		if (mb==null)
+			mesquite.alert("Mesquite cannot function: no file coordinator available");
+		else {
+			if (urlString==null)
+				mesquite.logln("Opening URL");
+			else
+				mesquite.logln("Opening URL " + urlString);
+			Date d = new Date(System.currentTimeMillis());
+			mesquite.logln("     at " + d.toString());
+			//patience = 30;
+			/*===READING FILE===*/
+			CommandRecord comRec = new CommandRecord(wasScripting);
+			CommandRecord prevRec = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(comRec);
+			mb.readProject(false, urlString, arguments);
+			/*================*/
+			mesquite.resetAllMenuBars();
+			mesquite.decrementMenuResetSuppression();
+			MesquiteProject project =mb.getProject();
+			if (projCont != null)
+				projCont.setObject(project);
+			if (project==null)
+				mb.iQuit();
+			return project;
+		}
+		mesquite.decrementMenuResetSuppression();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject openStream(){
+		mesquite.incrementMenuResetSuppression();
+		FileCoordinator mb = (FileCoordinator)mesquite.hireEmployee(FileCoordinator.class, null); //if this could be scripted, pass into method
+		if (mb==null)
+			mesquite.alert("Mesquite cannot function: no file coordinator available");
+		else {
+			mesquite.logln("Opening Stream " + stream);
+			Date d = new Date(System.currentTimeMillis());
+			mesquite.logln("     at " + d.toString());
+			//patience = 30;
+			/*===READING FILE===*/
+			CommandRecord comRec = new CommandRecord(wasScripting);
+			CommandRecord prevRec = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(comRec);
+			//mb.readProject(false, urlString, arguments);
+			/*================*/
+			mesquite.resetAllMenuBars();
+			mesquite.decrementMenuResetSuppression();
+			MesquiteProject project =mb.getProject();
+			if (projCont != null)
+				projCont.setObject(project);
+			if (project==null)
+				mb.iQuit();
+			return project;
+		}
+		mesquite.decrementMenuResetSuppression();
+		return null;
+	}
+	String originalArguments = null; //hackathon
+	public void setOriginalArguments(String orig){
+		originalArguments = orig;
+	}
+	/*.................................................................................................................*/
+	/* give alternative method which takes full file and passes it to FileCoordinator,
+	which then uses alternative methods in MesquiteProject reader that parses this string
+	instead of input stream*/
+	public MesquiteProject openFile(String pathname){
+		mesquite.incrementMenuResetSuppression();
+
+		FileCoordinator mb = (FileCoordinator)mesquite.hireEmployee(FileCoordinator.class, null);
+		if (mb==null)
+			mesquite.alert("Mesquite cannot function: no file coordinator available");
+		else {
+
+			if (pathname==null)
+				mesquite.logln("Opening file"); 
+			else
+				mesquite.logln("Opening file " + pathname);
+			Date d = new Date(System.currentTimeMillis());
+			mesquite.logln("     at " + d.toString());
+			//patience = 30;
+			/*===READING FILE===*/
+			CommandRecord comRec = new CommandRecord(wasScripting);
+			CommandRecord prevRec = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(comRec);
+			if (originalArguments == null) //hackathon
+				originalArguments = arguments;
+			mb.readProject(true, pathname, originalArguments); 
+			/*================*/
+			mesquite.resetAllMenuBars();
+			mesquite.decrementMenuResetSuppression();
+			MesquiteProject project =mb.getProject();
+			if (projCont != null)
+				projCont.setObject(project);
+			if (project==null) {
+				mb.iQuit();
+			}
+			return project;
+		}
+		mesquite.decrementMenuResetSuppression();
+		return null;
+	}
+	/*.................................................................................................................*/
+	/* makes and returns a new project.*/
+	public MesquiteProject newFile(String arguments, boolean makeTaxa){
+		FileCoordinator mb = (FileCoordinator)mesquite.hireEmployee(FileCoordinator.class, null);
+		if (mb==null) {
+			mesquite.alert("Mesquite cannot function: no file coordinator available");
+			return null;
+		}
+		else {
+			mb.createProject(arguments, makeTaxa); 
+			MesquiteProject project = mb.getProject();
+			if (projCont != null)
+				projCont.setObject(project);
+			if (project==null){
+				mb.iQuit();
+				return null;
+			}
+			if (!MesquiteThread.isScripting())
+				mb.doCommand("saveFile", null, CommandChecker.defaultChecker);
+			return mb.getProject();
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteThread thread;
+	public void setThread(MesquiteThread thread) {
+		this.thread = thread;
+	}
+	/**/
+	/** DOCUMENT */
+	public void run() {
+		try {
+			CommandRecord comRec = new CommandRecord(wasScripting);
+			CommandRecord prevRec = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(comRec);
+			//spontaneousIndicator = false;
+			Thread t = Thread.currentThread();
+			if (t instanceof MesquiteThread){
+				((MesquiteThread)t).setCurrent(1);
+			}
+
+			if (category <= 0)
+				newFile(arguments, category==0);
+			else if (category == 1)
+				openFile(arguments);
+			else if (category == 2)
+				openURLString(arguments);
+			else if (category == 3)
+				openGeneral(arguments);
+			//	else if (category == 4)
+			//		openStream(arguments);
+			if (thread !=null) {
+				thread.setProgressIndicator(null);
+				if (comRec != null && comRec.getProgressIndicator()!=null)
+					MesquiteThread.doomIndicator(comRec.getProgressIndicator().getProgressWindow());
+			}
+			if (t instanceof MesquiteThread){
+				((MesquiteThread)t).setCommandRecord(null);
+			}
+			thread = null;
+			MesquiteTrunk.mesquiteTrunk.logWindow.showPrompt();
+		}
+		catch (Exception e){
+			MesquiteFile.throwableToLog(this, e);
+			MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "File reading could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + "). If you save any files, you might best use Save As... in case data were lost or file saving doesn't work properly.");
+
+		}
+		catch (Error e){
+			if (e instanceof OutOfMemoryError)
+				MesquiteTrunk.mesquiteTrunk.discreetAlert("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+			else if (!(e instanceof ThreadDeath)){
+				MesquiteFile.throwableToLog(this, e);
+				MesquiteDialog.closeWizard();
+				MesquiteTrunk.mesquiteTrunk.exceptionAlert(e, "File reading could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + "). If you save any files, you might best use Save As... in case data were lost or file saving doesn't work properly.");
+			}
+			throw e;
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/lib/ProjectReadThread.java b/Source/mesquite/lib/ProjectReadThread.java
new file mode 100644
index 0000000..2a60538
--- /dev/null
+++ b/Source/mesquite/lib/ProjectReadThread.java
@@ -0,0 +1,70 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import java.io.*;
+
+/** A thread for executing commands */
+public class ProjectReadThread extends MesquiteThread {
+	public static ProjectReadThread ongoingThread = null;
+	ProjectReadThread subsequent;
+	String tempID;
+	public void settempID(String id){
+		tempID = id;
+	}
+	public ProjectReadThread () {
+		super();
+		sayGoodbye = false;
+	}
+	public ProjectReadThread (Runnable r) {
+		super(r);
+		sayGoodbye = false;
+	}
+	public synchronized void addSubsequentThread(ProjectReadThread thread){ //chaining threads
+		if (subsequent != null){
+			subsequent.addSubsequentThread(thread);
+		}
+		else
+			subsequent = thread;
+	}
+	public void start(){
+		try {
+			ongoingThread.addSubsequentThread(this);
+		}
+		catch (Exception e)
+		{
+			ongoingThread = this;
+			super.start();
+		}
+	}
+	public void run(){
+		try {
+			super.run();
+			ongoingThread = null;
+			if (subsequent != null) 
+				
+				subsequent.start();
+
+			threadGoodbye();
+		}
+		catch (MesquiteException e){
+			MesquiteMessage.warnProgrammer("MesquiteException thrown");
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/lib/Projects.java b/Source/mesquite/lib/Projects.java
new file mode 100644
index 0000000..50f4c58
--- /dev/null
+++ b/Source/mesquite/lib/Projects.java
@@ -0,0 +1,169 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+
+
+/* ��������������������������� projects & files ������������������������������� */
+/* ======================================================================== */
+/** A class with a vector storing the projects currently active (one instantiation of this belongs to MesquiteTrunk)*/
+public class Projects implements HNode {
+	
+	Vector projects;
+	boolean[] colorsUsed;
+	public static int projectsAdded = 0;//to catch memory leaks
+	public static int projectsRemoved = 0; //to catch memory leaks
+	public Projects() {
+		if (ColorDistribution.numColorSchemes>0)
+			colorsUsed = new boolean[ColorDistribution.numColorSchemes];
+		else
+			colorsUsed = new boolean[32];
+		for (int i=0; i<colorsUsed.length; i++)
+			colorsUsed[i]=false;
+		projects = new Vector(1);
+	}
+	
+	public int getNumProjects(){
+		return projects.size();
+	}
+	
+	/** Get p'th project. */
+	public MesquiteProject getProject(int p) {
+		if (p>=0 && p<projects.size())
+			return (MesquiteProject)projects.elementAt(p);
+		return null;
+	}
+	/** Get project with given id number. */
+	public MesquiteProject getProjectByID(int id) {
+		for (int i=0; i<projects.size(); i++){
+			MesquiteProject project =(MesquiteProject)projects.elementAt(i);
+			if (project.getID() == id)
+				return project;
+		}
+		return null;
+	}
+	/** Add project to the list of projects. */
+	public void addProject(MesquiteProject project) {
+		projects.addElement(project);
+		projectsAdded++;
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+	}
+	private void resetColorsAvailable(){
+		for (int i=0; i<colorsUsed.length; i++)
+			colorsUsed[i]=false;
+		for (int i=0; i<projects.size(); i++){
+			MesquiteProject mp = (MesquiteProject)projects.elementAt(i);
+			if (mp.getProjectColor()< colorsUsed.length)
+				colorsUsed[mp.getProjectColor()] = true;
+		}
+	}
+	private boolean colorAvailable(int which){
+		if (which< colorsUsed.length)
+			return !colorsUsed[which];
+		return false;
+	}
+	/** Returns the next base color for the project's windows (used when project starts up) */
+	public int requestNextColor(){
+		for (int i=0; i<ColorDistribution.numColorSchemes; i++)
+			if (colorAvailable(i)) {
+				colorsUsed[i] = true;
+				return i;
+			}
+		return 0;
+		
+	}
+	/** Remove project from list of projects.  The File Coordinator is responsible for disposing of the files within the project. */
+	public void removeProject(MesquiteProject project) {
+		projects.removeElement(project);
+		projectsRemoved++;
+		resetColorsAvailable();
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+	}
+	/** For HNode interface; returns projects themselves */
+	public HNode[] getHDaughters(){
+		if (projects.size()== 0)
+			return null;
+		HNode[] daughters = new HNode[projects.size()];
+		for (int i = 0; i < projects.size(); i++)
+			daughters[i] = (HNode)projects.elementAt(i);
+		return daughters;
+	}
+	/** For HNode interface */
+	public HNode getHMother(){
+		return null;
+	}
+	/** For HNode interface */
+	public String getName(){
+		String name = null;
+		if (getNumProjects() == 0)
+			name = "No Projects Open";
+		else	if (getNumProjects() == 1)
+			name = Integer.toString(getNumProjects()) + " Project Open";
+		else
+			name = Integer.toString(getNumProjects()) + " Projects Open";
+		if (MesquiteTrunk.author.hasDefaultSettings())
+			return name;
+		else
+			return name + ".  Current Author: " + MesquiteTrunk.author.getName();
+	}
+	/** For HNode interface */
+	public String getTypeName(){
+		return null;
+	}
+	/** For HNode interface */
+	public int getNumSupplements(){
+		return 0;
+	}
+	/** For HNode interface */
+	public String getSupplementName(int index){
+		return null;
+	}
+	/** For HNode interface */
+	public void hNodeAction(Container c, int x, int y, int action){
+		if (action == HNode.MOUSEMOVE){
+			MesquiteWindow f = MesquiteWindow.windowOfItem(c);
+			if (f != null && f instanceof MesquiteWindow){
+				((MesquiteWindow)f).setExplanation("This is a list of all active projects, the files that they comprise, and all of the major contained elements of information");
+			}
+		}
+		else if (action == HNode.MOUSEEXIT){
+			/*
+			Frame f = MesquiteTrunk.mesquiteTrunk.containerOfModule();
+			if (f != null && f instanceof MesquiteWindow){
+				((MesquiteWindow)f).setExplanation("");
+			}
+			*/
+		}
+	}
+	/** For HNode interface */
+	public void hSupplementTouched(int index){
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Image getHImage(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Color getHColor(){
+		return Color.white;
+		//return ColorTheme.getInterfaceBackground(); 
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public boolean getHShow(){
+		return true; 
+	}
+}
+
diff --git a/Source/mesquite/lib/PropertyNamesProvider.java b/Source/mesquite/lib/PropertyNamesProvider.java
new file mode 100644
index 0000000..ebe288e
--- /dev/null
+++ b/Source/mesquite/lib/PropertyNamesProvider.java
@@ -0,0 +1,18 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public interface PropertyNamesProvider {
+	public abstract String[] getPreferencePropertyNames();
+}
diff --git a/Source/mesquite/lib/PuppetThread.java b/Source/mesquite/lib/PuppetThread.java
new file mode 100644
index 0000000..4bebd23
--- /dev/null
+++ b/Source/mesquite/lib/PuppetThread.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+
+/* ======================================================================== */
+/** A class that serves as a separate Thread on which commands can be sent. */
+public class PuppetThread extends MesquiteThread {
+	Object baseObject;
+	String commands;
+	NexusBlock nblock;
+	Puppeteer puppeteer;
+	String endString;
+	boolean skip;
+	MesquiteInteger pos;
+	public PuppetThread (Puppeteer puppeteer, Object object, String commands, MesquiteInteger pos, String endString, boolean skip, NexusBlock nblock, boolean scripting) {
+		super();
+		this.baseObject = object;
+		this.commands = commands;
+		this.nblock = nblock;
+		this.puppeteer = puppeteer;
+		this.endString = endString;
+		this.skip = skip;
+		this.pos = pos;
+		setCommandRecord(new CommandRecord(scripting));
+		spontaneousIndicator = false;
+		setCurrent(1);
+	}
+	public String getCurrentCommandName(){
+		return null;
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	/** run the commands that were stored in the PuppetThread in its constructor. */
+	public void run() {
+			MesquiteModule.incrementMenuResetSuppression();
+			puppeteer.execute(baseObject, commands, pos, endString, skip, nblock, null);
+			baseObject = null;
+			commands = null;
+			MesquiteModule.decrementMenuResetSuppression();
+			threadGoodbye();
+	}
+
+}
+
diff --git a/Source/mesquite/lib/Puppeteer.java b/Source/mesquite/lib/Puppeteer.java
new file mode 100644
index 0000000..0121cd9
--- /dev/null
+++ b/Source/mesquite/lib/Puppeteer.java
@@ -0,0 +1,1408 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: getID output as well in response to message for objects
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+import java.io.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+
+/* ======================================================================== */
+/**An object that handles scripting.  Puppeteers are the main contollers of scripts (saved in Mesquite blocks of NEXUS files, or used to clone windows, or 
+in macros).  It creates its own thread to pass commands.*/
+public class Puppeteer  {
+	MesquiteProject project;
+	MesquiteModule ownerModule;
+	Random rng = new Random();
+	int levelCounter = 0;
+	Parser parser = new Parser();
+	private Parser parser2 = new Parser();
+	public Puppeteer (MesquiteModule ownerModule) {
+		this.ownerModule = ownerModule;
+		project = ownerModule.getProject();
+		parser2.setPunctuationString("(){}:,;-+<>=\\/\''\"");
+		parser.setPunctuationString("(){}:,;-+<>=\\/\''\"");
+	}
+	/* -------------------------------------*/
+	/** Calls up a dialog box in which the user can enter a script to be sent to the passed object. */
+	public void dialogScript(Object baseObject, MesquiteWindow f, String objectToCommand){
+		if (f==null)
+			f = MesquiteTrunk.mesquiteTrunk.containerOfModule();
+		String commands = MesquiteString.queryMultiLineString(f, "Script", "Script by which to command " + objectToCommand, "", 8, false, true);
+		if (!StringUtil.blank(commands))  {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			MesquiteWindow.tickClock("Executing script");
+			MesquiteModule.incrementMenuResetSuppression();	
+			CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(new CommandRecord(true));
+			sendCommands(baseObject, commands, pos, "", false, null,  CommandChecker.defaultChecker);
+			MesquiteThread.setCurrentCommandRecord(prevR);
+			MesquiteModule.decrementMenuResetSuppression();	
+			MesquiteWindow.hideClock();
+		}
+	}
+	/* -------------------------------------*/
+	/** Execute the passed string of commands (currently at string location 'pos') until the String "endString' is reached, skipping commands if 
+	the skip flag is set.  The NexusBlock is passed currently only so that the commands may assign it a title */
+	public void execute(Object baseObject, String commands, MesquiteInteger pos, String endString, boolean skip, NexusBlock nblock, MesquiteFile file){ 
+		MesquiteModule.incrementMenuResetSuppression();	
+		if (file == null){
+			MesquiteWindow.tickClock("Executing script");
+			sendCommands(baseObject, commands, pos, endString, skip,nblock, CommandChecker.defaultChecker);
+			MesquiteWindow.hideClock();
+		}
+		else {
+			CommandChecker checker = new CommandChecker();
+			checker.setFile(file);
+			MesquiteWindow.tickClock("Executing script");
+			sendCommands(baseObject, commands, pos, endString, skip,nblock, checker);
+			MesquiteWindow.hideClock();
+		} 
+		MesquiteModule.decrementMenuResetSuppression();	
+	}
+
+	/* -------------------------------------*/
+	/** Execute the passed string of commands (currently at string location 'pos') until the String "endString' is reached, skipping commands if 
+	the skip flag is set.  The NexusBlock is passed currently only so that the commands may assign it a title */
+	public Object executeWithResult(Object baseObject, String commands, MesquiteInteger pos, String endString, boolean skip, NexusBlock nblock, MesquiteFile file){ 
+		Object result = null;
+		MesquiteModule.incrementMenuResetSuppression();	
+		if (file == null){
+			MesquiteWindow.tickClock("Executing script");
+			result = sendCommands(baseObject, commands, pos, endString, skip,nblock, CommandChecker.defaultChecker);
+			MesquiteWindow.hideClock();
+		}
+		else {
+			CommandChecker checker = new CommandChecker();
+			checker.setFile(file);
+			MesquiteWindow.tickClock("Executing script");
+			result = sendCommands(baseObject, commands, pos, endString, skip,nblock, checker);
+			MesquiteWindow.hideClock();
+		} 
+		MesquiteModule.decrementMenuResetSuppression();	
+		return result;
+	}
+	/* -------------------------------------*/
+	/** Execute the passed string of commands (currently at string location 'pos') until the String "endString' is reached, skipping commands if 
+	the skip flag is set. */
+	public void execute(Object baseObject, String commands, MesquiteInteger pos, String endString, boolean skip){
+		execute(baseObject, commands, pos, endString, skip,null, null); 
+	}
+	/* -------------------------------------*/
+	/** Apply macro file to given commandable*/
+	public void applyMacroFile(String fileName, Commandable obj){
+		if (obj == null)
+			return;
+		String tellingCommand = MesquiteFile.getFileFirstContents(fileName);
+		MesquiteInteger macroPos = new MesquiteInteger(0);
+		String com = ParseUtil.getFirstToken(tellingCommand, macroPos);
+		Commandable toCommand = obj;
+		if ("telling".equalsIgnoreCase(com)){
+			String cName = ParseUtil.getToken(tellingCommand, macroPos);
+			if (cName.equalsIgnoreCase("FileCoordinator"))
+				toCommand = ownerModule.getFileCoordinator();
+			else if (cName.equalsIgnoreCase("Mesquite"))
+				toCommand = MesquiteTrunk.mesquiteTrunk;
+		}
+
+		String macroFile = MesquiteFile.getFileContentsAsString(fileName);
+		if (StringUtil.blank(macroFile))
+			return;
+		macroPos.setValue(0);
+		MesquiteModule.incrementMenuResetSuppression(); // seems to hang for some macros involving drawing trees (may be thread deadlock issue
+		CommandRecord mr = MesquiteThread.getCurrentCommandRecord();
+		MesquiteThread.setCurrentCommandRecord(CommandRecord.macroRecord);
+		execute(toCommand, macroFile, macroPos, "", false, null, null); 
+		MesquiteThread.setCurrentCommandRecord(mr);
+		MesquiteModule.decrementMenuResetSuppression(); //seems to hang for some macros involving drawing trees (may be thread deadlock issue
+	}
+	/*--------------------------------------*/
+	/** Gets the second part of the string, the token after the '.' */
+	private String getSecondWord(String s) {
+		MesquiteInteger period = new MesquiteInteger(s.indexOf(".") + 1);
+		return ParseUtil.getToken(s, period);
+	}
+	/*--------------------------------------*/
+	/* The following sections deal with the variable types for strings, objects, integers and numbers.
+	There are local variables for each of these to hold the variables the script creates.*/
+	/*-----------------STRINGS ---------------------*/
+	private int arrayLengths = 128;
+	private String[] strings = new String[arrayLengths];
+	private String[] stringNames = new String[arrayLengths];
+	private int numStrings = 0;
+
+	/*--------------------------------------*/
+	/** returns the String stored in the variable with the given name */
+	private String findString(String name) {
+		int item = StringArray.indexOfIgnoreCase(stringNames, name);
+		if (item>=0 && item < strings.length)
+			return strings[item];
+		else
+			return null;
+	}
+	/*-------------------OBJECTS-------------------*/
+	private Object[] objects = new Object[arrayLengths];
+	private String[] objectNames = new String[arrayLengths];
+	private int numObjects = 0;
+	/*--------------------------------------*/
+	/** returns the Object stored in the variable with the given name */
+	private Object findObject(String name) {
+		int item = StringArray.indexOfIgnoreCase(objectNames, name);
+		if (item>=0 && item < objects.length)
+			return objects[item];
+		else
+			return null;
+	}
+	/*--------------------INTEGERS ------------------*/
+	private MesquiteInteger[] integers = new MesquiteInteger[arrayLengths];
+	private String[] integerNames = new String[arrayLengths];
+	private int numIntegers = 0;
+	/*--------------------------------------*/
+	/** returns the MesquiteInteger stored in the variable with the given name */
+	private MesquiteInteger findInteger(String name) {
+		int item = StringArray.indexOfIgnoreCase(integerNames, name);
+		if (item>=0 && item < integers.length)
+			return integers[item];
+		else
+			return null;
+	}
+	/*------------------NUMBERS--------------------*/
+	private MesquiteNumber[] numbers = new MesquiteNumber[arrayLengths];
+	private String[] numberNames = new String[arrayLengths];
+	private int numNumbers = 0;
+	/*--------------------------------------*/
+	/** returns the MesquiteNumber stored in the variable with the given name */
+	private MesquiteNumber findNumber(String name) {
+		int item = StringArray.indexOfIgnoreCase(numberNames, name);
+		if (item>=0 && item < numbers.length)
+			return numbers[item];
+		else
+			return null;
+	}
+	/*====================================*/
+	/** Translates an argument that is intended to be a string but which may be some indirect reference into a string */
+	private String argumentToString(String rawArguments, Object result) {
+		if (ParseUtil.firstDarkChar(rawArguments)=='\'')
+			return rawArguments; //ParseUtil.getToken(rawArguments, pos);
+		String processed = "";
+		String name;
+		boolean first = true;
+		parser2.setString(rawArguments);
+		while (!StringUtil.blank(name = parser2.getNextToken())) {
+			if (!first)
+				processed += " ";
+			first = false;
+			if (name.length() == 1 && name.charAt(0)=='*') //this is needed because system was written to have * attached to next word, but in nexus file could be unattached
+				name+=parser2.getNextToken();
+
+			if (name.startsWith("*")) { //key character to indicate non-literal; i.e., look for substituting object
+				String st = name.substring(name.lastIndexOf("*")+1, name.length());
+				if (st.equalsIgnoreCase("it")) {
+					if (result !=null) {
+						if (result instanceof String)
+							processed += (String)result;
+						else if (result instanceof MesquiteInteger)
+							processed += result.toString();
+						else if ( result instanceof Listable)
+							processed +=((Listable)result).getName();
+						if (result instanceof Identifiable)
+							processed += " (id " +  ((Identifiable)result).getID() + ")";
+					}
+				}
+				else {
+					if (StringUtil.startsWithIgnoreCase(st,"Integer")) {
+						MesquiteInteger mi = findInteger(getSecondWord(st));
+						if (mi!=null)
+							processed += mi.toString();
+					}
+					else if (StringUtil.startsWithIgnoreCase(st,"Number")) {
+						MesquiteNumber mi = findNumber(getSecondWord(st));
+						if (mi!=null)
+							processed += mi.toString();
+					}
+					else if (StringUtil.startsWithIgnoreCase(st,"Object")) {
+						Object obj = findObject(getSecondWord(st));
+						if (obj != null && obj instanceof Listable)
+							processed +=((Listable)obj).getName();
+						if (obj != null && obj  instanceof Identifiable)
+							processed += " (id " +  ((Identifiable)obj).getID() + ")";
+					}
+					else if (StringUtil.startsWithIgnoreCase(st,"String")) {
+						String s0 = findString(getSecondWord(st));
+						if (s0!=null)
+							processed += s0;
+					}
+
+				}
+			}
+			else {
+				processed += StringUtil.tokenize(name); //StringUtil.deTokenize(name);
+			}
+		}
+		return processed;
+
+	}
+	/*--------------------------------------*/
+	/** Translates an argument that is intended to be a number but which may be some indirect reference into a number */
+	private void argumentToNumber(String name, Object result, MesquiteNumber theNum) {
+		if (name.startsWith("*")) { //key character to indicate non-literal; i.e., look for substituting object
+			String st = name.substring(name.lastIndexOf("*")+1, name.length());
+			if (st.equalsIgnoreCase("it")) {
+				if (result !=null) {
+					if (result instanceof String)
+						theNum.setValue((String)result);
+					else if (result instanceof MesquiteNumber)
+						theNum.setValue((MesquiteNumber)result);
+					else
+						theNum.setToUnassigned();
+				}
+			}
+			else {
+				if (StringUtil.startsWithIgnoreCase(st,"Integer")) {
+					MesquiteInteger mi = findInteger(getSecondWord(st));
+					if (mi!=null)
+						theNum.setValue(mi.getValue());
+				}
+				else if (StringUtil.startsWithIgnoreCase(st,"Number")) {
+					MesquiteNumber mi = findNumber(getSecondWord(st));
+					if (mi!=null)
+						theNum.setValue(mi);
+				}
+				else if (StringUtil.startsWithIgnoreCase(st,"Object")) {
+					Object obj = findObject(getSecondWord(st));
+					if (obj != null && obj instanceof MesquiteInteger)
+						theNum.setValue(((MesquiteInteger)obj).getValue());
+					else if (obj != null && obj instanceof MesquiteNumber)
+						theNum.setValue(((MesquiteNumber)obj));
+				}
+				else if (StringUtil.startsWithIgnoreCase(st,"String")) {
+					String s0 = findString(getSecondWord(st));
+					if (s0!=null)
+						theNum.setValue(s0);
+				}
+
+			}
+		}
+		else
+			theNum.setValue(name);
+	}
+	/*--------------------------------------*/
+	/** Translates an argument that is intended to be an integer but which may be some indirect reference into an integer */
+	private int argumentToInteger(String name, Object result) {
+		if (name.startsWith("*")) { //key character to indicate non-literal; i.e., look for substituting object
+			String st = name.substring(name.lastIndexOf("*")+1, name.length());
+			if (st.equalsIgnoreCase("it")) {
+				if (result !=null) {
+					if (result instanceof String)
+						return MesquiteInteger.fromString((String)result);
+					else if (result instanceof MesquiteInteger)
+						return ((MesquiteInteger)result).getValue();
+					else
+						return 0;
+				}
+			}
+			else {
+				if (StringUtil.startsWithIgnoreCase(st,"Integer")) {
+					MesquiteInteger mi = findInteger(getSecondWord(st));
+					if (mi!=null)
+						return mi.getValue();
+				}
+				else if (StringUtil.startsWithIgnoreCase(st,"Object")) {
+					Object obj = findObject(getSecondWord(st));
+					if (obj != null && obj instanceof MesquiteInteger)
+						return ((MesquiteInteger)obj).getValue();
+				}
+				else if (StringUtil.startsWithIgnoreCase(st,"String")) {
+					String s0 = findString(getSecondWord(st));
+					if (s0!=null)
+						return MesquiteInteger.fromString(s0);
+				}
+
+			}
+			return 0;
+		}
+		else return MesquiteInteger.fromString(name);
+	}
+	/*--------------------------------------*/
+	private boolean debugging = false; 
+	private boolean logOnly = false;
+	private MesquiteTimer timer;
+	private boolean showTime = false;
+	/*................................................................................................................*/
+	private MesquiteInteger pagingPos = new MesquiteInteger(0);
+	private String pagingBlock;
+	private boolean pagingSkip;
+	private NexusBlock pagingNB;
+	private MesquiteModule pagedModule;
+	/** This is for the paging system, which may be defunct. */
+	protected void returningPage(MesquiteModule pagedModule){
+		if (this.pagedModule == pagedModule){
+			MesquiteInteger stringPos = new MesquiteInteger(pagingPos.getValue());
+			sendCommands(pagedModule, pagingBlock, stringPos, "endPaging;", pagingSkip, pagingNB, CommandChecker.defaultChecker);
+		}
+	}
+	/*--------------------------------------*/
+	private boolean stampToLog = true;
+	/** Stamp the string to the System console and perhaps also the log */
+	private void stamp(String s){
+		if (logOnly)
+			MesquiteFile.writeToLog(s+ StringUtil.lineEnding());
+		else {
+			System.out.println(s);
+			if (stampToLog)
+				ownerModule.logln(s);
+		}
+	}
+	/*--------------------------------------*/
+	/** Stamp the time since the last call for a time stamp */
+	private void stampTimeSinceLast() {
+		stamp("        TIME " + timer.timeSinceLast() + "  of  " + timer.timeSinceVeryStart());
+	}
+	//this is needed because system was written to have * attached to next word, but in nexus file could be unattached
+	private String nextTokenCompressAsterisk(Parser parser){
+		String s = parser.getNextToken();
+		if (s !=null && s.startsWith("*")) {
+			String n = parser.getNextToken();
+			if (n!=null)
+				return s+=n;
+			else
+				return s;
+		}
+		else
+			return s;
+	}
+	/* -------------------------------------*/
+	/** Sends commands to the object, but on a new thread. */
+	public void sendCommandsOnNewThread(Object baseObject, String commands, MesquiteInteger pos, String endString, boolean skip, NexusBlock nblock, boolean scripting){
+		PuppetThread puppetThread = new PuppetThread(this, baseObject, commands, pos, endString, skip, nblock, scripting);
+		puppetThread.start();
+	}
+	String[] defunctModules = new String[]{"#mesquite.ornamental.CellPictures.CellPictures", "#mesquite.collab.aaManageImageIndices.aaManageImageIndices", "#mesquite.collab.DataImages.DataImages"};
+	boolean defunctModule(String moduleName){
+		if (StringArray.indexOf(defunctModules, moduleName) >= 0)
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	private String getEmployeeNotFoundWarning(String moduleName){
+		if (moduleName == null)
+			return "A script has failed to execute properly, possibly because it expected certain modules not available in the current configuration of Mesquite.  Details: A command (\" getEmployee\") did not result in the return of an object as expected.  The script's results may not be as expected.\nMore details are written into Mesquite's log file."; 
+		if (defunctModule(moduleName))
+			return null;
+		String message = "A script has failed to execute properly, as it refers to a module \"" + StringUtil.getLastItem(moduleName, ".") + "\", that either did not start or was unavailable because the module is not installed or activated.";
+		boolean compoundClassName = (moduleName.charAt(0) == '#' && moduleName.indexOf(".")>=0);
+		if (moduleName.charAt(0) == '#' && moduleName.indexOf(".")>=0) { //compound class name
+			String useName = moduleName.substring(1, moduleName.length());
+			String s = StringUtil.getAllButLastItem(useName, ".");
+			while (s!=null && StringUtil.characterCount(s, '.')>1) {
+				s = StringUtil.getAllButLastItem(s, ".");
+			}
+			if (s!=null && StringUtil.characterCount(s, '.')==1){
+				//s is now package name; find package and diagnose
+				MesquitePackageRecord mpr = MesquitePackageRecord.findPackage(s);
+				if (mpr == null)
+					message += "\nThe package in which this module resides (" + s + ") appears not to be installed.";
+				else if (mpr.loaded)
+					message += "\nThe package in which this module resides (" + mpr.getName() + ") is installed and activated (loaded).  Perhaps the script has an error, or the module failed to start, or the package has changed.";
+				else 
+					message += "\nThe package in which this module resides (" + mpr.getName() + ") is installed but is not activated (loaded).  To use this module, change the activation/deactivation status of the package using the menu items in the File menu, and restart Mesquite.";
+			}
+
+		}
+		else { 
+			String useName = moduleName;
+			if (moduleName.charAt(0) == '#')
+				useName = moduleName.substring(1, moduleName.length());
+			if (!MesquitePackageRecord.allPackagesActivated())
+				message += "\nSome packages of modules appear to be installed but not activated (loaded). Check and perhaps change the activation/deactivation status of packages using the menu items in the File menu.";
+		}
+		return message;
+	}
+	private Object cancel(MesquiteInteger stringPos, String block){
+		stringPos.setValue(block.length()); 
+		MesquiteTrunk.mesquiteTrunk.alert("Script cancelled.");
+		return null;
+	}
+	private void showCommands(Object mb, String arguments, boolean showExpl){
+
+		if (mb != null || mb instanceof Commandable){
+			String objectName;
+			if (mb instanceof Listable) {
+				if (mb instanceof MesquiteWindow)
+					objectName = "Window: " + ((Listable)mb).getName();
+				else
+					objectName = ((Listable)mb).getName();
+			}
+			else
+				objectName = mb.getClass().getName();
+			if (";".equals(arguments))
+				arguments = null;
+			boolean single = !StringUtil.blank(arguments);
+			CommandChecker cc = new CommandChecker();
+			cc.setSparseMode();
+			CommandChecker.accumulate((Commandable)mb, cc);
+			Vector v = cc.getAccumulatedCommands();
+			Vector ve = cc.getAccumulatedExplanations();
+			if (v !=null || v.size() == 0) {
+				if (!single)
+					MesquiteTrunk.mesquiteTrunk.logln("Commands of " + objectName);
+				for (int i = 0; i< v.size(); i++) {
+					Object obj = v.elementAt(i);
+
+					if (obj instanceof String) {
+						String sCM = (String)obj;
+						if (StringUtil.blank(arguments) || arguments.equalsIgnoreCase(sCM)) {
+							Object objE = null;
+							if ((showExpl || single) && i < ve.size())
+								objE = ve.elementAt(i);
+							if (objE !=null)
+								sCM += "  - " + objE;
+							if (single || showExpl)
+								MesquiteTrunk.mesquiteTrunk.logln(sCM);
+							else
+								MesquiteTrunk.mesquiteTrunk.log("  " + sCM);
+						}
+
+					}
+				}
+				MesquiteTrunk.mesquiteTrunk.logln("");
+			}
+			else
+				MesquiteTrunk.mesquiteTrunk.logln(" No Commands are available for " + objectName);
+		}
+	}
+	private MesquiteProject getProject(Object mb, NexusBlock nb, Object result){
+		if (nb !=null) {
+			MesquiteFile f = nb.getFile();
+			if (f !=null) {
+				return f.getProject();
+			}
+		}
+		if (CommandRecord.getScriptingFileS() !=null){
+			return CommandRecord.getScriptingFileS().getProject();
+		}
+		if (mb != null && mb instanceof MesquiteModule  && ((MesquiteModule)mb).getProject() != null){
+			return ((MesquiteModule)mb).getProject();
+		}
+		if (result != null && result instanceof MesquiteModule  && ((MesquiteModule)result).getProject() != null){
+			return ((MesquiteModule)result).getProject();
+		}
+		if (mb != null && mb instanceof MesquiteProject){
+			return  (MesquiteProject)mb;
+		}
+		if (mb != null && mb instanceof MesquiteFile){
+			return  ((MesquiteFile)mb).getProject();
+		}
+		return null;
+	}
+	private String writingDirectory(){
+		if (project == null){
+			if (MesquiteTrunk.getProjectList().getNumProjects()==1)
+				return MesquiteTrunk.getProjectList().getProject(0).getHomeDirectoryName();
+			return "";
+		}
+		String s = project.getHomeDirectoryName();
+		return s;
+	}
+	/*--------------------------------------------------------------------------------------------------------*/
+	/* This assumes string position is just afer a control block start; it will go until corresponding endString */
+	public Object sendCommands(Object mb, String block, MesquiteInteger stringPos, String endString, boolean skip, NexusBlock nb, CommandChecker checker) {
+		int level = levelCounter++;
+		Parser parser = new Parser();
+		Parser commandParser = new Parser();
+		commandParser.setString(block);
+		String s;
+		Object cm = null;
+		Object result = null;
+		boolean fineDebugging = false;
+		String previousCommand = "";
+		String previousArguments = "";
+		String previousCommandName = "";
+		String rememberedArguments = null;
+		while (!StringUtil.blank(s=commandParser.getNextCommand(stringPos)) && !s.equalsIgnoreCase(endString)) {
+
+			if (debugging) {
+				if (mb == null)
+					stamp("<NULL OBJECT>" + s);
+				else
+					stamp("<" +  mb.getClass().getName() + ">" + s);
+			}
+			if (fineDebugging) stamp("-sc- (" + level + ")1");
+			String commandName = parser.getFirstToken(s);
+			//MesquiteWindow.tickClock("Executing: " + commandName);
+			CommandRecord.tick("Executing " + commandName);
+			if (fineDebugging) stamp("-sc- (" + level + ")2");
+			if (checker.compare(null, "Send the commands to follow (until endTell) to the indicated object", "[Object to which commands are to be sent]", commandName, "tell")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")7");
+				String argument = nextTokenCompressAsterisk(parser);
+				Object who = null;
+				if (fineDebugging) stamp("-sc- (" + level + ")8");
+				if (argument.equalsIgnoreCase("It"))
+					who = result;
+				else if (argument.equalsIgnoreCase("Mesquite"))
+					who = MesquiteTrunk.mesquiteTrunk;
+				else if (argument.equalsIgnoreCase("ProjectCoordinator")) {
+					if (mb instanceof FileCoordinator)
+						who = mb;
+					else if (result instanceof FileCoordinator)
+						who = result;
+					else if (mb instanceof MesquiteModule &&  ((MesquiteModule)mb).getFileCoordinator()!=null){
+						who = ((MesquiteModule)mb).getFileCoordinator();
+					}
+					else {
+						who = getProject(mb, nb, result);
+					}
+				}
+				else
+					who = findObject(getSecondWord(argument));
+
+				if (fineDebugging) stamp("-sc- (" + level + ")9");
+				if (who==null && !skip) {
+					String message ="Object of tell command is null (previous command: \"" + previousCommand + "\" to object " + mb + ")";
+					if (debugging)
+						stamp(message);
+					else 
+						ownerModule.logln("A script has failed to execute properly, possibly because it expected certain modules not available in the current configuration of Mesquite.  Details: " + message);
+					CommandRecord comRec = MesquiteThread.getCurrentCommandRecord();
+					if (comRec != null){
+						if (!comRec.getErrorFound()) {
+							if ("getEmployee".equalsIgnoreCase(previousCommandName)){ //the common case in which a better error can be given informing user about unloaded packages
+								MesquiteTrunk.mesquiteTrunk.logln(getEmployeeNotFoundWarning(previousArguments));
+							}
+							else
+								MesquiteTrunk.mesquiteTrunk.alert("A script has failed to execute properly, possibly because it expected certain modules not available in the current configuration of Mesquite.  Details: A command (\"" + previousCommand + "\") did not result in the return of an object as expected.  The script's results may not be as expected.\nMore details are written into Mesquite's log file."); 
+						}
+						comRec.setObjectToldNullWarning();
+						comRec.setErrorFound();
+					}
+				}
+				if (debugging) {
+					if (skip) 
+						stamp("  [skipping]");
+					else if (who==null)
+						stamp("  [will pass over commands]");
+					else if (who instanceof Listable)
+						stamp("   ----- about to send commands to " + "  ---[" + ((Listable)who).getName() + "]");
+					else
+						stamp("   ----- about to send commands to " + "  ---[" + who + "]");
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")10");
+				sendCommands(who, block, stringPos, "endTell;", skip, nb, checker);
+				if (fineDebugging) stamp("-sc- (" + level + ")11");
+			} 
+			//else if (checker.compare(null, "End this level of the script", null, commandName, "endTell")) {
+			else if (checker.compare(null, "End this level of the script", null, commandName, "endTell")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3a1");
+				stringPos.setValue(stringPos.getValue()-8); //reset to before the endTell, since this should only get here because of an exitTell, and need to save the endTell for appropriate level
+				return null;
+			}
+			else if (checker.compare(null, "Exit out of this current level of the script, jumping to 'endTell'", null, commandName, "exitTell")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3");
+				sendCommands(mb, block, stringPos, null, true, nb, checker);
+			}
+			else if (checker.compare(null, "Toggles suppression of all progress indicators on this thread", null, commandName, "toggleSuppressAllProgressIndicatorsCurrentThread")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3#toggleSuppressAllProgressIndicatorsCurrentThread");
+				MesquiteThread.setSuppressAllProgressIndicatorsCurrentThread(!MesquiteThread.getSuppressAllProgressIndicators(Thread.currentThread()));
+			}
+			else if (checker.compare(null, "Shows the log window", null, commandName, "showLogWindow")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3#showLogWindow");
+				MesquiteTrunk.showLogWindow();
+			}
+			else if (checker.compare(null, "Writes to log & console a list of the commands available for the currently commanded object", null, commandName, "sc")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3#");
+				showCommands(mb, nextTokenCompressAsterisk(parser), false);
+			}
+			else if (checker.compare(null, "Writes to log & console a list of the commands available for the currently commanded object", null, commandName, "?")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3#?");
+				showCommands(mb, nextTokenCompressAsterisk(parser), false);
+			}
+			else if (checker.compare(null, "Writes to log & console a list of the commands available for the currently commanded object", null, commandName, "??")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3#?");
+				showCommands(mb, nextTokenCompressAsterisk(parser), true);
+			}
+			else if (checker.compare(null, "Stop this script", null, commandName, "stop")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")3a");
+				stringPos.setValue(block.length()); 
+				skip = true;
+				return null;
+			}
+			else if (skip && !checker.getAccumulateMode()) {
+				if (debugging) stamp("  [skipping]");
+			}	
+			/*=== Commands above this are processed even if the "skip" flag is on; commands below this are skipped if the flag is on ====*/
+
+			/* ----------------------- CONTROL FLOW -----------------------*/
+			else if (checker.compare(null, "The start of a FOR loop (end is 'endFor')", "[An integer or reference to an integer, indicating the number of times the loop is to be cycled]", commandName, "for")) {
+				int startRepeatPos = stringPos.getValue();
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				int repetitions = 0;
+				if (theInt==null)
+					repetitions = MesquiteInteger.fromString(argument);
+				else 
+					repetitions = theInt.getValue();
+
+				if (debugging)
+					stamp("    @FOR loop with " + repetitions + " repetitions (skip " + skip + ")");
+				while (repetitions>0) {
+					stringPos.setValue(startRepeatPos);
+					sendCommands(mb, block, stringPos, "endFor;", skip, nb, checker);
+					if (skip)
+						repetitions = 0; //end immediately
+					else
+						repetitions --;
+				}
+
+			}
+			else if (checker.compare(null, "The start of a WHILE loop (end is 'endWhile')", "[An integer or reference to an integer; loop is cycled until that integer equals zero]", commandName, "while")) {
+				int startRepeatPos = stringPos.getValue();
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				if (debugging) 
+					stamp("           @WHILE with argument: " + argument + " value: " + theInt);
+				if (theInt == null || skip)
+					sendCommands(mb, block, stringPos, "endWhile;", true, nb, checker);
+				else {
+					while (theInt.getValue()!=0) {
+						stringPos.setValue(startRepeatPos);
+						sendCommands(mb, block, stringPos, "endWhile;", skip, nb, checker);
+					}
+				}
+			}
+			else if (checker.compare(null, "The start of an IF block (end is 'endIf')", "[An integer or reference to an integer; block is entered if integer is non-zero]", commandName, "if")) {
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				if (debugging) 
+					stamp("           @IF with argument: " + argument + " value: " + theInt);
+				sendCommands(mb, block, stringPos, "endIf;", skip || (theInt==null) || theInt.getValue() == 0, nb, checker);
+			}
+			else if (checker.compare(null, "The start of an IFNOT block (end is 'endIf')", "[An integer or reference to an integer; block is entered if integer is zero]", commandName, "ifNot")) {
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				if (debugging) 
+					stamp("           @IFNOT with argument: " + argument + " value: " + theInt);
+				sendCommands(mb, block, stringPos, "endIf;", skip || (theInt==null) || theInt.getValue() != 0, nb, checker);
+			}
+			else if (checker.compare(null, "The start of an IFEXISTS block (end is 'endIf')", "[A reference to an object; block is entered if object is non-null]", commandName, "ifExists")) {
+				Object who = null;
+				String argument = nextTokenCompressAsterisk(parser);
+				if (argument!=null){
+					if (argument.equalsIgnoreCase("It"))
+						who = result;
+					else if (argument.equalsIgnoreCase("Mesquite"))
+						who = MesquiteTrunk.mesquiteTrunk;
+					else
+						who = findObject(getSecondWord(argument));
+				}
+				if (debugging) 
+					stamp("           @IFEXISTS with argument: " + argument + " who: " + who);
+				sendCommands(mb, block, stringPos, "endIf;", skip || (who==null), nb, checker);
+
+			}
+			else if (checker.compare(null, "The start of an IFCOMBINABLE block (end is 'endIf')", "[A reference to a number object; block is entered if object is combinable]", commandName, "ifCombinable")) {
+				Object who = null;
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				if (debugging) 
+					stamp("           @IFCOMBINABLE with argument: " + argument + " value: " + theInt);
+				sendCommands(mb, block, stringPos, "endIf;", skip || (theInt==null) || !theInt.isCombinable(), nb, checker);
+			}
+			else if (checker.compare(null, "The start of an IFNOTCOMBINABLE block (end is 'endIf')", "[A reference to a number object; block is entered if object is not combinable]", commandName, "ifNotCombinable")) {
+				Object who = null;
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteInteger theInt = findInteger(getSecondWord(argument));
+				if (debugging) 
+					stamp("           @IFNOTCOMBINABLE with argument: " + argument + " value: " + theInt);
+				sendCommands(mb, block, stringPos, "endIf;", skip || ((theInt!=null) && theInt.isCombinable()), nb, checker);
+			}
+			else if (checker.compare(null, "The start of an IFNOTEXISTS block (end is 'endIf')", "[A reference to an object; block is entered if object is null]", commandName, "ifNotExists")) {
+				Object who = null;
+				String argument = nextTokenCompressAsterisk(parser);
+				if (argument!=null){
+					if (argument.equalsIgnoreCase("It"))
+						who = result;
+					else if (argument.equalsIgnoreCase("Mesquite"))
+						who = MesquiteTrunk.mesquiteTrunk;
+					else
+						who = findObject(getSecondWord(argument));
+				}
+				if (debugging) 
+					stamp("           @IFNOTEXISTS with argument: " + argument + " who: " + who);
+				sendCommands(mb, block, stringPos, "endIf;", skip || (who!=null), nb, checker);
+			}
+
+			/* ----------------------- VARIABLES -----------------------*/
+			else if (checker.compareStart(null, "Defines or recalls an integer variable", "To be immediately followed by name of integer, as part of the same token  [integer, or reference to integer variable, or 'random']", commandName, "Integer.")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")14");
+				MesquiteInteger theInt = findInteger(getSecondWord(commandName));
+				String argument = nextTokenCompressAsterisk(parser);
+				boolean doAdd = false;
+				boolean doSubtract = false;
+				if (argument.equals("-")){
+					doSubtract = true;
+					argument = nextTokenCompressAsterisk(parser);
+				}
+				else if (argument.startsWith("-")) {
+					doSubtract = true;
+					argument = argument.substring(argument.indexOf("+")+1, argument.length());
+				}
+				else if (argument.equals("+")){
+					doAdd = true;
+					argument = nextTokenCompressAsterisk(parser);
+				}
+				else if (argument.startsWith("+")) {
+					doAdd = true;
+					argument = argument.substring(argument.indexOf("+")+1, argument.length());
+				}
+				int value;
+				if (argument !=null && argument.equalsIgnoreCase("random")){
+					value = Math.abs(rng.nextInt());
+				}
+				else
+					value =argumentToInteger(argument, result);
+
+				if (fineDebugging) stamp("-sc- (" + level + ")15");
+				if (debugging) 
+					stamp("           argument: " + argument + " value of integer: " + value);
+				if (theInt ==null) {
+					integers[numIntegers] = new MesquiteInteger(value);
+					integerNames[numIntegers] = getSecondWord(commandName);
+					numIntegers++;
+				}
+				else {
+					if (doAdd)
+						theInt.add(value);
+					else if (doSubtract)
+						theInt.subtract(value);
+					else
+						theInt.setValue(value);
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")16");
+			}
+			else if (checker.compareStart(null, "Defines or recalls a numerical variable (integer or not)", "To be immediately followed by name of number, as part of the same token [integer, or reference to integer variable, or 'random' (double between 0 and 1); if token is preceded by '+', value will be added to existing]", commandName, "Number.")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")17");
+				MesquiteNumber theNum = findNumber(getSecondWord(commandName));
+				String argument = nextTokenCompressAsterisk(parser);
+				boolean doAdd = false;
+				boolean doSubtract = false;
+				if (argument.equals("-")){
+					doSubtract = true;
+					argument = nextTokenCompressAsterisk(parser);
+				}
+				else if (argument.startsWith("-")) {
+					doSubtract = true;
+					argument = argument.substring(argument.indexOf("+")+1, argument.length());
+				}
+				else if (argument.equals("+")){
+					doAdd = true;
+					argument = nextTokenCompressAsterisk(parser);
+				}
+				else if (argument.startsWith("+")) {
+					doAdd = true;
+					argument = argument.substring(argument.indexOf("+")+1, argument.length());
+				}
+				if (theNum ==null) {
+					theNum =  new MesquiteNumber();
+					numbers[numNumbers] = theNum;
+					numberNames[numNumbers] = getSecondWord(commandName);
+					numNumbers++;
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")18");
+				if (argument !=null && argument.equalsIgnoreCase("random")) {
+					if (doAdd)
+						theNum.add(Math.abs(rng.nextDouble()));
+					else if (doSubtract)
+						theNum.subtract(Math.abs(rng.nextDouble()));
+					else
+						theNum.setValue(Math.abs(rng.nextDouble()));
+				}
+				else {
+					if (doAdd) {
+						MesquiteNumber toAdd = new MesquiteNumber(0);
+						argumentToNumber(argument, result, toAdd);
+						theNum.add(toAdd);
+					}
+					else if (doSubtract) {
+						MesquiteNumber toSub = new MesquiteNumber(0);
+						argumentToNumber(argument, result, toSub);
+						theNum.subtract(toSub);
+					}
+					else
+						argumentToNumber(argument, result, theNum);
+				}
+				if (debugging) 
+					stamp("           value of number: " + theNum.toString());
+				if (fineDebugging) stamp("-sc- (" + level + ")19");
+			}
+			else if (checker.compareStart(null, "Decrements by one the named integer variable, or by a value other than one if that number follows the first token.", "To be immediately followed by the name of the variable, as part of the same token", commandName, "decrement.")) {
+				MesquiteInteger theInt = findInteger(getSecondWord(commandName));
+				String amountString = nextTokenCompressAsterisk(parser);
+				MesquiteInteger amount = new MesquiteInteger();
+				amount.setValue(amountString);
+				if (theInt !=null) 
+					if (amount.isCombinable()) {
+						theInt.decrement(amount.getValue());
+					}
+					else
+						theInt.decrement();
+				if (debugging) 
+					stamp("           decremented to: " + theInt);
+			}
+			else if (checker.compareStart(null, "Increments by one the named integer variable, or by a value other than one if that number follows the first token", "To be immediately followed by the name of the variable, as part of the same token", commandName, "increment.")) {
+				MesquiteInteger theInt = findInteger(getSecondWord(commandName));
+
+				String amountString = nextTokenCompressAsterisk(parser);
+				MesquiteInteger amount = new MesquiteInteger();
+				amount.setValue(amountString);
+				if (theInt !=null) 
+					if (amount.isCombinable()) {
+						theInt.increment(amount.getValue());
+					}
+					else
+						theInt.increment();
+				if (debugging) 
+					stamp("           incremented to: " + theInt);
+			}
+			else if (checker.compareStart(null, "Defines or recalls a variable containing an Object", "To be immediately followed by the name of the variable, as part of the same token  [A reference to an object]", commandName, "Object.")) {
+				//Object theObj = findObject(getSecondWord(commandName));
+				int whichObject = StringArray.indexOfIgnoreCase(objectNames, getSecondWord(commandName));
+				if (whichObject<0) {
+					objects[numObjects] = result;
+					objectNames[numObjects] = getSecondWord(commandName);
+					numObjects++;
+				}
+				else
+					objects[whichObject] = result;
+			}
+			else if (checker.compareStart(null, "Defines or recalls a String variable", "To be immediately followed by the name of the variable, as part of the same token  [A string or a reference to a string]", commandName, "String.")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")25");
+				int itemNum  = StringArray.indexOfIgnoreCase(stringNames, getSecondWord(commandName));
+				String argument = nextTokenCompressAsterisk(parser);
+				String value =null;
+				boolean concat = false;
+				if (argument.equalsIgnoreCase("*It")) {
+					if (result != null) {
+						if (result instanceof WithStringDetails)
+							value = ((WithStringDetails)result).toStringWithDetails();
+						else
+							value = result.toString();
+					}
+				}
+				else {
+					if (argument.equals("+")){
+						concat = true;
+						argument = nextTokenCompressAsterisk(parser);
+					}
+					else if (argument.startsWith("+")) {
+						concat = true;
+						argument = argument.substring(argument.indexOf("+")+1, argument.length());
+					}
+					if (argument.startsWith("*")) {
+						String parg = argument.substring(argument.indexOf("+")+1, argument.length());
+						argument = argumentToString(parg, result);
+
+					}
+
+					if (fineDebugging) stamp("-sc- (" + level + ")26");
+					if ((argument.equals(";") || StringUtil.blank(argument)) && result !=null && result instanceof String)
+						value = (String)result;
+					else {
+						value = argument.substring(0, argument.length());
+					}
+				}
+
+				if (itemNum<0) {
+					itemNum = numStrings;
+					strings[numStrings] = value;
+					stringNames[numStrings] = getSecondWord(commandName);
+					numStrings++;
+				}
+				else {
+					if (concat && strings[itemNum]!=null)
+						strings[itemNum] += value;
+					else
+						strings[itemNum] = value;
+				}
+				if (debugging)
+					stamp("       String number " + itemNum + "defined or modified to \"" + strings[itemNum] + "\"");
+				if (fineDebugging) stamp("-sc- (" + level + ")27");
+			}
+			else if (checker.compareStart(null, "Tokenizes a String variable", "To be immediately followed by the name of the variable, as part of the same token  [A string or a reference to a string]", commandName, "tokenize.")) {
+				int itemNum  = StringArray.indexOfIgnoreCase(stringNames, getSecondWord(commandName));
+
+				if (itemNum>=0 && itemNum< strings.length)  {
+					if (strings[itemNum]!=null)
+						strings[itemNum] = ParseUtil.tokenize(strings[itemNum] );
+					if (debugging)
+						stamp("       String number " + itemNum + "tokenized to \"" + strings[itemNum] + "\"");
+					if (fineDebugging) stamp("-sc- (" + level + ")27at");
+				}
+			}
+			else if (checker.compare(null, "Queries the user for a String", "[Message to be shown to user (as a quoted token)]", commandName, "queryString")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")30");
+				String argument = nextTokenCompressAsterisk(parser);
+				String r = MesquiteString.queryString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), argument, argument, "");
+				result = r;
+				if (r==null || r.equals("")) {
+					return cancel(stringPos, block);
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")31");
+			}
+			else if (checker.compare(null, "Queries the user for an integer value", "[Message to be shown to user (as a quoted token)]", commandName, "queryInteger")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")32");
+				String argument = nextTokenCompressAsterisk(parser);
+				int i = MesquiteInteger.queryInteger(ownerModule.containerOfModule(), argument, argument, 0);
+				if (MesquiteInteger.isCombinable(i))
+					result = new MesquiteInteger(i);
+				else {
+					return cancel(stringPos, block);
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")33");
+			}
+			else if (checker.compare(null, "Queries the user for a numerical value", "[Message to be shown to user (as a quoted token)]", commandName, "queryNumber")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")34");
+				String argument = nextTokenCompressAsterisk(parser);
+				MesquiteNumber m = new MesquiteNumber(0);
+				MesquiteNumber r = MesquiteNumber.queryNumber(ownerModule.containerOfModule(), argument, argument, m);
+				if (r.isCombinable())
+					result = r;
+				else {
+					return cancel(stringPos, block);
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")35");
+			}
+			else if (checker.compare(null, "Queries the user with a list from which an item is to be chosen; returned is the integer position in the list", "[reference to ListableVector object] [Message to be shown to user (as a quoted token)]", commandName, "queryListNumber")) {
+				String argument = nextTokenCompressAsterisk(parser);
+				Object who = null;
+				if (argument.equalsIgnoreCase("It"))
+					who = result;
+				else if (argument.equalsIgnoreCase("Mesquite"))
+					who = MesquiteTrunk.mesquiteTrunk;
+				else
+					who = findObject(getSecondWord(argument));
+				if (who!=null && who instanceof ListableVector){
+					String queryMessage = nextTokenCompressAsterisk(parser);
+					Listable r = ListDialog.queryList(ownerModule.containerOfModule(), "Select", queryMessage, MesquiteString.helpString, (ListableVector)who, 0);
+					if (r!=null) {
+						int i = ((ListableVector)who).indexOf(r);
+						result = new MesquiteInteger(i);
+					}
+					else {
+						return cancel(stringPos, block);
+					}
+				}
+			}
+			else if (checker.compare(null, "Queries the user with a list from which an item is to be chosen; returned is the object in the list", "[reference to ListableVector object] [Message to be shown to user (as a quoted token)]", commandName, "queryList")) {
+				String argument = nextTokenCompressAsterisk(parser);
+				Object who = null;
+				if (argument.equalsIgnoreCase("It"))
+					who = result;
+				else if (argument.equalsIgnoreCase("Mesquite"))
+					who = MesquiteTrunk.mesquiteTrunk;
+				else
+					who = findObject(getSecondWord(argument));
+				if (who!=null && who instanceof ListableVector){
+					String queryMessage = nextTokenCompressAsterisk(parser);
+					result = ListDialog.queryList(ownerModule.containerOfModule(), "Select", queryMessage,MesquiteString.helpString,  (ListableVector)who, 0);
+					if (result==null) {
+						return cancel(stringPos, block);
+					}
+				}
+			}
+			else if (checker.compare(null, "Queries the user to choose a file; returned is the tokenized path to the file", "[Message to be shown to user (as a quoted token)]", commandName, "queryFile")) {
+				String queryMessage = nextTokenCompressAsterisk(parser);
+				MainThread.incrementSuppressWaitWindow();
+				MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), queryMessage, FileDialog.LOAD);
+				fdlg.setBackground(ColorTheme.getInterfaceBackground());
+				fdlg.setVisible(true);
+				String tempFileName=fdlg.getFile();
+				String tempDirectoryName=fdlg.getDirectory();
+				// fdlg.dispose();
+				MainThread.decrementSuppressWaitWindow();
+				if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+					String r= tempDirectoryName + tempFileName;
+					result = ParseUtil.tokenize(r);
+					if (r==null || r.equals("")) {
+						return cancel(stringPos, block);
+					}
+
+				}
+			}
+			else if (checker.compare(null, "Queries the user to choose a file name by which to save a file; returned is the tokenized path to the file", "[Message to be shown to user (as a quoted token)]", commandName, "queryFileSave")) {
+				String queryMessage = nextTokenCompressAsterisk(parser);
+				MainThread.incrementSuppressWaitWindow();
+				MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), queryMessage, FileDialog.SAVE);
+				fdlg.setBackground(ColorTheme.getInterfaceBackground());
+				fdlg.setVisible(true);
+				String tempFileName=fdlg.getFile();
+				String tempDirectoryName=fdlg.getDirectory();
+				// fdlg.dispose();
+				MainThread.decrementSuppressWaitWindow();
+				if (!StringUtil.blank(tempFileName) && !StringUtil.blank(tempDirectoryName)) {
+					String r= tempDirectoryName + tempFileName;
+					result = ParseUtil.tokenize(r);
+					if (r==null || r.equals("")) {
+						return cancel(stringPos, block);
+					}
+
+				}
+			}
+			else if (checker.compare(null, "Queries the user about a yes/no choice; returned is 0 (no) or 1 (yes)", "[Message to be shown to user (as a quoted token)] [String for No] [String for Yes]", commandName, "queryYesNo")) {
+				String queryMessage = nextTokenCompressAsterisk(parser);
+				String no = nextTokenCompressAsterisk(parser);
+				String yes = nextTokenCompressAsterisk(parser);
+
+				boolean yesChosen = AlertDialog.query(ownerModule.containerOfModule(), "Query", queryMessage,yes, no);
+				MesquiteInteger mi = new MesquiteInteger();
+				if (yesChosen)
+					mi.setValue(1);
+				else
+					mi.setValue(0);
+				result = mi;
+
+			}
+			/* other ideas: 
+	queryGetFile;  // querys user and puts result into It
+	queryPutFile;  // querys user and puts result into It
+	queryDirectory;  // querys user and puts result into It
+	queryObject <ListableVector>;  // querys user and puts result into It
+			 */
+			else if (checker.compare(null, "Appends string to a file", "[filename] [an object or variable that can be converted to a string]", commandName, "appendMessageToFile")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String fileName = null;
+				if (argument!=null && argument.startsWith("*"))
+					fileName = findString(getSecondWord(argument));
+				else
+					fileName = argument;
+				String whatToWrite = argumentToString(nextTokenCompressAsterisk(parser), result); //whatToWrite
+				
+				MesquiteFile.appendFileContents(MesquiteFile.composePath(writingDirectory(), fileName), whatToWrite, false);
+			}
+			else if (checker.compare(null, "Appends literal string to a file", "[filename] [a string or a reference to a string]", commandName, "appendLiteralToFile")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String fileName = null;
+				if (argument!=null && argument.startsWith("*"))
+					fileName = findString(getSecondWord(argument));
+				else
+					fileName = argument;
+				String whatToWrite =nextTokenCompressAsterisk(parser); //whatToWrite
+				MesquiteFile.appendFileContents(MesquiteFile.composePath(writingDirectory(),fileName), whatToWrite, false);
+			}
+			else if (checker.compare(null, "Saves string to a file", "[filename] [an object or variable that can be converted to a string]", commandName, "saveMessageToFile")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String fileName = null;
+				if (argument!=null && argument.startsWith("*"))
+					fileName = findString(getSecondWord(argument));
+				else
+					fileName = argument;
+				String whatToWrite = argumentToString(nextTokenCompressAsterisk(parser), result); //whatToWrite
+				MesquiteFile.putFileContents(MesquiteFile.composePath(writingDirectory(),fileName), whatToWrite, false);
+			}
+			else if (checker.compare(null, "Appends an end line character/characters to a file", "[filename]", commandName, "appendReturnToFile")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String fileName = null;
+				if (argument!=null && argument.startsWith("*"))
+					fileName = findString(getSecondWord(argument));
+				else
+					fileName = argument;
+				MesquiteFile.appendFileContents(MesquiteFile.composePath(writingDirectory(), fileName), ""+ StringUtil.lineEnding(), false);
+			}
+			else if (checker.compare(null, "Appends an tab to a file", "[filename]", commandName, "appendTabToFile")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String fileName = null;
+				if (argument!=null && argument.startsWith("*"))
+					fileName = findString(getSecondWord(argument));
+				else
+					fileName = argument;
+				MesquiteFile.appendFileContents(MesquiteFile.composePath(writingDirectory(), fileName), "\t", false);
+			}
+			else if (checker.compare(null, "Requests that file (if any) containing script being executed be closed after reading", null, commandName, "closeFileAfterRead")) {  
+				if (nb !=null && nb.getFile() != null)
+					nb.getFile().setCloseAfterReading(true);
+			}
+			else if (checker.compare(null, "Sets the arguments for the following command", "[args]", commandName, "rememberArguments")) {  
+				String argument = nextTokenCompressAsterisk(parser); 
+				rememberedArguments = null;
+				if (argument!=null && argument.startsWith("*"))
+					rememberedArguments = findString(getSecondWord(argument));
+				else
+					rememberedArguments = argument;
+			}
+			else if (checker.compare(null, "Makes a new directory", "[path]", commandName, "mkdir")) {  
+				String argument = nextTokenCompressAsterisk(parser); //fileName
+				String path = null;
+				if (argument!=null && argument.startsWith("*"))
+					path = findString(getSecondWord(argument));
+				else
+					path = argument;
+				File f = new File(MesquiteFile.composePath(writingDirectory(), path));
+				f.mkdir();
+			}
+			else if (checker.compare(null, "For subsequent commands at this level in the script, execute on a new Thread", null, commandName, "newThread")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")4");
+				if (debugging) {
+					stamp("   STARTING NEW THREAD  ");
+
+				}
+				boolean scripting = MesquiteThread.isScripting();
+				if (fineDebugging) stamp("-sc- (" + level + ")5");
+				
+				sendCommandsOnNewThread(mb, block, stringPos, endString, skip, nb, scripting);
+				if (fineDebugging) stamp("-sc- (" + level + ")6");
+				return null;
+			}
+			else if (commandName.equalsIgnoreCase("TITLE") && mb instanceof FileCoordinator) {
+				if (fineDebugging) stamp("-sc- (" + level + ")12");
+				if (nb !=null)
+					nb.setName(nextTokenCompressAsterisk(parser));
+				if (fineDebugging) stamp("-sc- (" + level + ")13");
+			}
+
+			else if (checker.compare(null, "Writes the current 'It' to the System console", null, commandName, "writeIt")) {  //writes current "It" to console
+				if (result!=null)
+					stamp(" [ It: " + result.toString() + "]");
+				else
+					stamp("[ It is null ]");
+			}
+			else if (checker.compare(null, "Displays a message in the system console", "The message to be displayed (a single token; use quotes ' if needed)", commandName, "message")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")20");
+				String argument = nextTokenCompressAsterisk(parser);
+				stamp(argumentToString(argument, result));
+			}
+			else if (checker.compare(null, "Displays a message in the system console", "The message to be displayed (a single token; use quotes ' if needed)", commandName, "messageLiteral")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")20");
+				String argument = nextTokenCompressAsterisk(parser);
+				stamp(argument);
+			}
+			else if (checker.compare(null, "Displays a message in an alert dialog for the user", "The message to be displayed (a single token; use quotes ' if needed)", commandName, "alert")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")21");
+				String argument = nextTokenCompressAsterisk(parser);
+				ownerModule.alert(argumentToString(argument, result));
+			}
+			else if (checker.compare(null, "Displays a message in the system console indicating the current object being commanded", null, commandName, "showObjectCommanded")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")22");
+				stamp("     object commanded: " + mb);
+				result = mb;
+			}
+			else if (checker.compare(null, "Used at the start of macros, to indicate the Class to which the macro is designed to direct its commands", "[short (packageless) name of Class]", commandName, "telling")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")23");
+				String argument = nextTokenCompressAsterisk(parser);
+				if (mb == null) {
+					System.out.println("commands for object of class " + argument + " given to null object");
+					skip = true;
+				}
+				else {
+
+					if (!MesquiteModule.nameIsInstanceOf(argument, mb.getClass())) { //TODO: should allow subclasses also
+						System.out.println("commands for object of class " + argument + " given to object of inappropriate class " + MesquiteModule.getShortClassName(mb.getClass()));
+						skip = true;
+					}
+				}
+				if (fineDebugging) stamp("-sc- (" + level + ")24");
+			}
+			else if (checker.compare(null, "Toggles debug mode -- in debug mode, a record of commands and results returned is written to the System console", null, commandName, "debug")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")28");
+				debugging = !debugging;
+			}
+			else if (checker.compare(null, "Toggles logonlydebug mode -- in logonlydebug mode, a record of commands and results returned is written to the log file", null, commandName, "logonlydebug")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")28");
+				debugging = !debugging;
+				logOnly = !logOnly;
+			}
+			else if (checker.compare(null, "Returns System.currentTimeMillis as a string", null, commandName, "millis")) {
+				result = Long.toString(System.currentTimeMillis());
+			}
+			else if (checker.compare(null, "Toggles timing mode -- in timing mode, the time required to complete each command is written to the System console", null, commandName, "time")) {
+				showTime = !showTime;
+				if (showTime) {
+					timer = new MesquiteTimer();
+					timer.start();
+				}
+			}
+			else if (checker.compare(null, "Stamps the time to the log", null, commandName, "stampVersion")) {
+				MesquiteTrunk.mesquiteTrunk.logln("Mesquite version " + MesquiteModule.getMesquiteVersion() + MesquiteModule.getBuildVersion());
+			}
+			else if (checker.compare(null, "Stamps the time to the log", null, commandName, "stampTime")) {
+				long t = System.currentTimeMillis();
+				Date dnow = new Date(t);
+				MesquiteTrunk.mesquiteTrunk.logln( dnow.toString());
+			}
+			else if (checker.compare(null, "Toggles whether the messages (for instance, if the debug toggle is on) are echoed into log" , null, commandName, "messagesToLog")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")28");
+				stampToLog = !stampToLog;
+			}
+			/*else if (checker.compare(null, "Toggles whether the hiring path of modules is written to the System console (for debugging)", null, commandName, "toggleShowHiringPath")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")28a");
+				MesquiteModule.showHiringPath = !MesquiteModule.showHiringPath;
+			}*/
+			else if (checker.compare(null, "Sleeps", "[integer of how long this thread is to sleep]", commandName, "sleep")) {
+				String argument = nextTokenCompressAsterisk(parser);
+				int howLong = MesquiteInteger.fromString(argument);
+				try {Thread.sleep(howLong);}
+				catch(InterruptedException e){}
+			}
+			else if (checker.compare(null, "call the Runtime garbage collector", null, commandName, "gc")) {
+				if (fineDebugging) stamp("-sc- (" + level + ")29");
+				Runtime rtm = Runtime.getRuntime();
+				rtm.gc();
+			}
+			else if (checker.compare(null, "may be defunct", null, commandName, "paging")) {
+				if (mb instanceof MesquiteModule){
+					String argument = nextTokenCompressAsterisk(parser);
+					pagingPos.setValue(stringPos.getValue());
+					pagingBlock = block;
+					pagingSkip = skip;
+					pagingNB = nb;
+					pagedModule = (MesquiteModule)mb;
+					//	((MesquiteModule)mb).removePaging(this);
+					sendCommands(null, block, stringPos, "endPaging;", true, nb, checker);
+					((MesquiteModule)mb).pageModule(ownerModule, "persistent".equalsIgnoreCase(argument)); //persistent if says so
+				}
+				else
+					sendCommands(null, block, stringPos, "endPaging;", true, nb, checker);
+			} 
+			else if (checker.compare(null, "may be defunct", null, commandName, "removePaging")) {
+				if (mb instanceof MesquiteModule)
+					((MesquiteModule)mb).removePaging(ownerModule);
+			} 
+			else if (!skip && !checker.getAccumulateMode()) {
+				if (fineDebugging) stamp("-sc- (" + level + ")100");
+				String commandArguments;
+
+				if (rememberedArguments !=null)
+					commandArguments = rememberedArguments;
+				else if (StringUtil.blank(s) || parser.getPosition()>= s.length()) 
+					commandArguments = null;
+				else {
+					commandArguments = s.substring(parser.getPosition(), s.length()-1);
+					commandArguments = argumentToString(commandArguments, result);
+				}
+				previousArguments = commandArguments;
+				if (fineDebugging) stamp("-sc- (" + level + ")101");
+				if (mb !=null && mb instanceof Commandable) {
+					if (fineDebugging) stamp("-sc- (" + level + ")102");
+					if (mb instanceof Logger) {
+						String logString;
+						if (mb instanceof Listable)
+							logString = ((Listable)mb).getName() + ">" + s;
+						else
+							logString = "[" + mb.getClass().getName() + "]"  + ">" + s;
+						//((Logger)mb).logln(logString);
+					}
+					//else
+					//	MesquiteModule.mesquiteTrunk.logln(">" + s);
+					if (fineDebugging) stamp("-sc- (" + level + ")103");
+
+					try{
+						result = ((Commandable)mb).doCommand(commandName, commandArguments,checker);  //cm = mb.doCommand(commandName, commandArguments);
+						//CommandRecord.tick("Command complete");
+						CommandRecord.tick(commandName + " complete");
+					}
+					catch (Exception e){ 
+						result = null;
+						CommandRecord comRec = MesquiteThread.getCurrentCommandRecord();
+						if (comRec != null)
+							comRec.setErrorFound();
+						MesquiteFile.throwableToLog(this, e);
+						String message = "Command being executed when Exception was thrown: " + commandName + "[arguments: " + commandArguments + "], commanding ";
+						if (mb instanceof Listable)
+							message += " the object \"" + ((Listable)mb).getName() + "\" of class " + mb.getClass();
+						else
+							message += " an object of class " + mb.getClass();
+						MesquiteProject proj = getProject(mb, nb, result);
+
+						if (proj !=null && proj.isDoomed){
+							MesquiteTrunk.mesquiteTrunk.logln("Execution thrown in script " + message);
+						}
+						else {
+							MesquiteTrunk.mesquiteTrunk.exceptionAlert(e,  "There has been a problem executing a script; a Java Exception was thrown.  " + message + ". This may be the result of an old, incompatible module or script being used.  (ERROR: " + e.getMessage() + ")");
+							MesquiteMessage.printStackTrace(e);
+						}
+						MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+						MesquiteTrunk.resetAllMenuBars();
+
+					}
+					catch (Error e){
+						if (e instanceof OutOfMemoryError)
+							MesquiteMessage.println("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+						result = null;
+						MesquiteFile.throwableToLog(this, e);
+						CommandRecord comRec = MesquiteThread.getCurrentCommandRecord();
+						if (comRec != null)
+							comRec.setErrorFound();
+						MesquiteDialog.closeWizard();
+						String message = "Command being executed when Error was thrown: " + commandName + "[arguments: " + commandArguments + "], commanding ";
+						if (mb instanceof Listable)
+							message += " the object \"" + ((Listable)mb).getName() + "\" of class " + mb.getClass();
+						else
+							message += " an object of class " + mb.getClass();
+						MesquiteProject proj = getProject(mb, nb, result);
+						if (proj !=null && proj.isDoomed){
+							MesquiteTrunk.mesquiteTrunk.logln("Execution thrown in script " + message);
+						}
+						else {
+							if (!(e instanceof OutOfMemoryError))
+								MesquiteTrunk.mesquiteTrunk.exceptionAlert(e,  "There has been a problem executing a script; a Java Error was thrown.  " + message + ". This may be the result of an old, incompatible module or script being used.  (ERROR: " + e.getMessage() + ")");
+							MesquiteMessage.printStackTrace(e);
+						}
+						MesquiteTrunk.zeroMenuResetSuppression(); //EXCEPTION HANDLER
+						MesquiteTrunk.resetAllMenuBars();
+
+					}
+					rememberedArguments= null;
+
+					if (fineDebugging) stamp("-sc- (" + level + ")104");
+					if (debugging) {
+						if (result == null)
+							stamp(s + "  ---{null was returned}");
+						else if (result instanceof MesquiteInteger)
+							stamp(s + "  ---{returned: " + ((MesquiteInteger)result).toString() + "}");
+						else if (result instanceof Listable)
+							stamp(s + "  ---{returned: " + ((Listable)result).getName() + "}");
+						else
+							stamp(s + "  ---{returned  " + result + "}");
+					}
+					if (fineDebugging) stamp("-sc- (" + level + ")105");
+				}
+			}
+			if (fineDebugging) stamp("-sc- (" + level + ")106");
+			if (showTime)
+				stampTimeSinceLast();
+			if (fineDebugging) stamp("-sc- (" + level + ")107");
+			previousCommand = s;
+			previousCommandName = commandName;
+		}
+		return result;
+	}
+	public void finalize () throws Throwable{
+		for (int i=0; i<numbers.length; i++)
+			numbers[i]=null;
+		for (int i=0; i<integers.length; i++)
+			integers[i]=null;
+		for (int i=0; i<objects.length; i++)
+			objects[i]=null;
+		for (int i=0; i<strings.length; i++)
+			strings[i]=null;
+		//	pagingNB = null;
+		//	pagedModule = null;
+		super.finalize();
+	}
+}
+
diff --git a/Source/mesquite/lib/QueryDialogs.java b/Source/mesquite/lib/QueryDialogs.java
new file mode 100644
index 0000000..ac1fb3d
--- /dev/null
+++ b/Source/mesquite/lib/QueryDialogs.java
@@ -0,0 +1,277 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/** A utility class with static methods that present the user with a dialog box in which they can type a number.*/
+public class QueryDialogs  {
+	
+	/*.................................................................................................................*/
+	public static boolean queryInteger(MesquiteWindow parent, String title, String message,  boolean allowCancel, MesquiteInteger value) {
+		return queryInteger(parent, title, message, "", allowCancel, value);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryInteger(MesquiteWindow parent, String title, String message, String help, boolean allowCancel, MesquiteInteger value) {
+		return queryInteger(parent, title, message, null, help, allowCancel, value);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryInteger(MesquiteWindow parent, String title, String message, String secondaryMessage, String help, boolean allowCancel, MesquiteInteger value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		queryDialog.addLargeOrSmallTextLabel(message);
+		if (StringUtil.blank(help) && queryDialog.isInWizard())
+			help = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a whole number (integer).  <p>The initial value is " + value;
+		queryDialog.appendToHelpString(help);
+		IntegerField integerField = queryDialog.addIntegerField("", value.getValue(), 20);
+		
+		queryDialog.setDefaultTextComponent(integerField.getTextField());
+		queryDialog.setDefaultComponent(integerField.getTextField());
+		if (StringUtil.notEmpty(secondaryMessage))
+			queryDialog.addLabelSmallText(secondaryMessage);
+		
+		if (allowCancel)
+			queryDialog.completeAndShowDialog(true);
+		else
+			queryDialog.completeAndShowDialog("OK", null, null, "OK");
+		
+		value.setValue(integerField.getValue());
+		if (buttonPressed.getValue()!=0) 
+			value.setValue(MesquiteInteger.unassigned);
+		queryDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryLong(MesquiteWindow parent, String title, String message, MesquiteLong value) {
+		return queryLong(parent, title, message, "", value);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryLong(MesquiteWindow parent, String title, String message, String help, MesquiteLong value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		queryDialog.addLargeOrSmallTextLabel(message);
+		if (StringUtil.blank(help) && queryDialog.isInWizard())
+			help = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a whole number (integer).  <p>The initial value is " + value;
+		queryDialog.appendToHelpString(help);
+		LongField longField = queryDialog.addLongField("", value.getValue(), 20);
+		queryDialog.setDefaultTextComponent(longField.getTextField());
+		queryDialog.completeAndShowDialog(true);
+		value.setValue(longField.getValue());
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue(MesquiteLong.unassigned);
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryDouble(MesquiteWindow parent, String title, String message, MesquiteDouble value) {
+		return queryDouble(parent, title, message, "", value);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryDouble(MesquiteWindow parent, String title, String message, String help, MesquiteDouble value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		queryDialog.addLargeOrSmallTextLabel(message);
+		if (StringUtil.blank(help) && queryDialog.isInWizard())
+			help = "<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a number.  It does not need to be a whole number.  To indicate exponentials, use E.  Thus, 2x10^6 is written 2e6.  <p>The initial value is " + value;
+		queryDialog.appendToHelpString(help);
+		SingleLineTextField textField = queryDialog.addTextField("", value.toString(), 30);
+		queryDialog.setDefaultTextComponent(textField);
+		queryDialog.completeAndShowDialog(true);
+		value.setValue(MesquiteDouble.fromString(textField.getText()));
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue(MesquiteDouble.unassigned);
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryTwoDoubles(MesquiteWindow parent, String title, String message1, MesquiteDouble value1, String message2, MesquiteDouble value2) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter two numbers.  To indicate exponentials, use E.  Thus, 2x10^6 is written 2e6.  <p>The initial values are " + value1 + " and " + value2);
+		
+		queryDialog.addLargeOrSmallTextLabel(message1);
+		SingleLineTextField textField1 = queryDialog.addTextField("", value1.toString(), 30);
+		queryDialog.addLargeOrSmallTextLabel(message2);
+		SingleLineTextField textField2 = queryDialog.addTextField("", value2.toString(), 30);
+		queryDialog.completeAndShowDialog(true);
+		value1.setValue(MesquiteDouble.fromString(textField1.getText()));
+		value2.setValue(MesquiteDouble.fromString(textField2.getText()));
+		
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) {
+			value1.setValue(MesquiteDouble.unassigned);
+			value2.setValue(MesquiteDouble.unassigned);
+		}
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryMesquiteNumber(MesquiteWindow parent, String title, String message, MesquiteNumber value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a number.  <p>The initial value is " + value);
+		queryDialog.addLargeOrSmallTextLabel(message);
+		SingleLineTextField textField = queryDialog.addTextField("", value.toString(), 30);
+		queryDialog.setDefaultTextComponent(textField);
+		queryDialog.completeAndShowDialog(true);
+		String s = textField.getText();
+		if (s!=null && s.length()>0 && s.charAt(s.length()-1) == (char)10){
+			s = s.substring(0,s.length()-1); 
+		}
+		value.setValue(s);
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setToUnassigned();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryShortString(MesquiteWindow parent, String title, String message, MesquiteString value, boolean hasDefault) {
+		if (value==null)
+			return false;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a short string of text.");
+		if (!hasDefault)
+			queryDialog.setDefaultButton(null);
+		queryDialog.addLargeOrSmallTextLabel(message);
+		String start = "";
+		if (StringUtil.notEmpty(value.toString()))
+				start = value.toString();
+		SingleLineTextField textField = queryDialog.addTextField("", value.toString(), 30);
+		queryDialog.setDefaultTextComponent(textField);
+		if (hasDefault)
+			queryDialog.completeAndShowDialog(true);
+		else
+			queryDialog.completeAndShowDialog();
+		String s = textField.getText();
+		if (s!=null && s.length()>0 && s.charAt(s.length()-1) == (char)10){
+			s = s.substring(0,s.length()-1); 
+		}
+		value.setValue(s);
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue((String)null);
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryShortString(MesquiteWindow parent, String title, String message, MesquiteString value) {
+		return queryShortString(parent, title, message, value, true);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryMultiLineString(MesquiteWindow parent, String title, String message, MesquiteString value, int numRows, boolean hasDefault, boolean useSmallText) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (!hasDefault)
+			queryDialog.setDefaultButton(null);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter text.");
+		queryDialog.addLargeOrSmallTextLabel(message);
+		TextArea textArea = queryDialog.addTextArea(value.getValue(),numRows);
+		queryDialog.setDefaultTextComponent((TextComponent)textArea);
+		if (useSmallText){
+			textArea.setFont(new Font ("SanSerif", Font.PLAIN, 10));
+		}
+		if (hasDefault)
+			queryDialog.completeAndShowDialog(true);
+		else
+			queryDialog.completeAndShowDialog();
+		String resultText = null;
+		int count = 0;
+		while (count++<10){
+			try {
+				resultText = textArea.getText();
+				count = 10;
+		        }
+		        catch (Exception e){
+		        }
+	        }
+		value.setValue(resultText);
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue((String)null);
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryString(MesquiteWindow parent, String title, String message, String help, MesquiteString value, int numRows, boolean hasDefault, boolean useSmallText) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+		if (!hasDefault)
+			queryDialog.setDefaultButton(null);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a string of text. ");
+		if (StringUtil.notEmpty(help))
+			queryDialog.appendToHelpString(help);
+
+		queryDialog.addLargeOrSmallTextLabel(message);
+		SingleLineTextArea textArea = queryDialog.addSingleLineTextArea(value.getValue(),numRows);
+		textArea.addKeyListener(queryDialog);
+		queryDialog.setDefaultTextComponent((TextComponent)textArea);
+		if (useSmallText){
+			textArea.setFont(new Font ("SanSerif", Font.PLAIN, 10));
+		}
+		if (hasDefault)
+			queryDialog.completeAndShowDialog(true);
+		else
+			queryDialog.completeAndShowDialog();
+		value.setValue(textArea.getText());
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue((String)null);
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryString(MesquiteWindow parent, String title, String message, MesquiteString value, int numRows, boolean hasDefault, boolean useSmallText) {
+		return queryString( parent,  title,  message,  "", value, numRows,  hasDefault,  useSmallText);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryString(MesquiteWindow parent, String title, String message, MesquiteString value, int numRows) {
+		return queryString(parent, title, message, value,numRows, true, false);
+	}
+	/*.................................................................................................................*/
+	public static boolean queryString(MesquiteWindow parent, String title, String message, MesquiteString value) {
+		return queryString(parent, title, message, value,3, true, false);
+	}
+	
+	/*.................................................................................................................*/
+	public static boolean queryChar(MesquiteWindow parent, String title, String message, MesquiteString value) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(parent, title,buttonPressed);
+			queryDialog.setDefaultButton(null);
+		if (StringUtil.blank(queryDialog.getHelpString()) && queryDialog.isInWizard())
+			queryDialog.appendToHelpString("<h3>" + StringUtil.protectForXML(title) + "</h3>Please enter a single character.");
+		queryDialog.addLargeOrSmallTextLabel(message);
+		SingleLineTextField symbolField = queryDialog.addTextField(value.getValue(),5);
+		symbolField.addKeyListener(queryDialog);
+		queryDialog.setDefaultTextComponent((TextComponent)symbolField);
+			queryDialog.completeAndShowDialog(true);
+		String s = symbolField.getText();
+		boolean success = true;
+		if (s.length()>1)
+			s = s.substring(1,1);
+		else if (s.length()<=0)
+			success = false;
+		value.setValue(s);
+
+		queryDialog.dispose();
+		if (buttonPressed.getValue()!=0) 
+			value.setValue((String)null);
+		return (buttonPressed.getValue()==0 && success);
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/RadioButtons.java b/Source/mesquite/lib/RadioButtons.java
new file mode 100644
index 0000000..fb1434d
--- /dev/null
+++ b/Source/mesquite/lib/RadioButtons.java
@@ -0,0 +1,132 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+
+/*===============================================*/
+/** This class holds radio buttons (CheckboxGroup) for an ExtensibleDialog. */
+public class RadioButtons implements ItemListener {
+	ExtensibleDialog dialog;
+	CheckboxGroup cbg;
+	Checkbox[] checkboxArray;
+	int numCheckBoxes;
+	Panel newPanel;
+	GridBagConstraints constraints;
+	/*.................................................................................................................*/
+	public RadioButtons (ExtensibleDialog dialog, String[] labels, Panel[] subPanels, int defaultBox) {
+
+		initialize(dialog,labels,subPanels, defaultBox);
+
+	}
+	/*.................................................................................................................*/
+	public RadioButtons (ExtensibleDialog dialog, String[] labels, int defaultBox) {
+		initialize(dialog,labels,null, defaultBox);
+		
+	}
+	
+	/*.................................................................................................................*/
+	void initialize (ExtensibleDialog dialog, String[] labels, Panel[] subPanels, int defaultBox) {
+
+		this.dialog = dialog;
+		cbg = new CheckboxGroup();
+		numCheckBoxes = labels.length;
+		checkboxArray = new Checkbox[numCheckBoxes];
+		dialog.forceNewPanel();
+		newPanel = dialog.addNewDialogPanel();  
+
+		GridBagLayout gridBag = new GridBagLayout();
+		constraints = new GridBagConstraints();
+		constraints.gridx=0;
+		constraints.gridy = GridBagConstraints.RELATIVE;
+		constraints.gridwidth=1;
+		constraints.gridheight=1;
+		constraints.fill=GridBagConstraints.BOTH;
+		constraints.anchor=GridBagConstraints.WEST;
+		constraints.insets = new Insets(0,25,0,20);
+		constraints.weighty=1.0;
+		newPanel.setLayout(gridBag);
+
+
+		for (int i=0; i< numCheckBoxes; i++) {
+			checkboxArray[i] = new Checkbox(labels[i], cbg, true);
+			checkboxArray[i].addItemListener(this);
+			newPanel.add(checkboxArray[i]);
+			if (subPanels!=null && i<subPanels.length)
+				newPanel.add(subPanels[i]);
+			gridBag.setConstraints(checkboxArray[i],constraints);
+		}
+		if (defaultBox>=0 && defaultBox<numCheckBoxes) {
+			cbg.setSelectedCheckbox(checkboxArray[defaultBox]);
+			checkboxArray[defaultBox].requestFocusInWindow();
+		}
+		else if (labels.length>0) {
+			cbg.setSelectedCheckbox(checkboxArray[0]);
+			checkboxArray[0].requestFocusInWindow();
+		}
+
+	}
+
+	public void itemStateChanged(ItemEvent e){
+		dialog.requestFocus();
+	}
+	public void setEnabled(int button, boolean b){
+		if (button>=0 && button<numCheckBoxes)
+			checkboxArray[button].setEnabled(b);
+	}
+	
+	/*.................................................................................................................*/
+	public boolean isAButton(ItemSelectable itemSelectable) {
+		for (int i=0; i< numCheckBoxes; i++) {
+			if (checkboxArray[i]==itemSelectable)
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    public void addItemListener(ItemListener itemListener) {
+		for (int i=0; i< numCheckBoxes; i++) {
+			checkboxArray[i].addItemListener(itemListener);
+		}
+    }
+	/*.................................................................................................................*/
+	public Checkbox getSelectedCheckbox () {
+		return cbg.getSelectedCheckbox();
+	}
+	/*.................................................................................................................*/
+	public CheckboxGroup getCheckBoxGroup () {
+		return cbg;
+	}
+	/*.................................................................................................................*/
+	public Checkbox getCheckbox(int i) {
+		if (i>=0 && i<numCheckBoxes)
+			return checkboxArray[i];
+		return null;
+	}
+	/*.................................................................................................................*/
+	public int getValue () {
+		Checkbox checkbox  = cbg.getSelectedCheckbox();
+		for (int i=0; i< numCheckBoxes; i++) {
+			if (checkbox == checkboxArray[i]) 
+				return i;
+		}
+		return 0;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/RandomBetween.java b/Source/mesquite/lib/RandomBetween.java
new file mode 100644
index 0000000..bec3f8e
--- /dev/null
+++ b/Source/mesquite/lib/RandomBetween.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/*Last documented:  August 1999 */
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+
+
+
+
+/* ======================================================================== */
+/** subclass of Random to return random integer between min and max inclusive.*/
+public class RandomBetween extends Random {
+	public long requests = 0;
+	public static boolean askSeed;
+	public RandomBetween() {
+		super();
+	}
+	public RandomBetween(long seed) {
+		super(seed);
+	}
+	/*.................................................................................................................*/
+	/** Returns a random integer between min and max inclusive.*/
+   	public int randomIntBetween(int min, int max) {
+   		requests++;
+   		int minUse=min, maxUse=max;   		
+   		if (!MesquiteInteger.isCombinable(min))
+   			minUse = 0;
+   		if (!MesquiteInteger.isCombinable(min))
+   			maxUse = minUse+1;
+   		return ((int)(nextDouble()*(maxUse-minUse + 1))) + minUse;
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random double between min and max inclusive.*/
+   	public double randomDoubleBetween(double min, double max) {
+   		requests++;
+   		double minUse=min, maxUse=max;   		
+   		if (!MesquiteDouble.isCombinable(min))
+   			minUse = 0.0;
+   		if (!MesquiteDouble.isCombinable(min))
+   			maxUse = minUse+1.0;
+   		return ((nextDouble()*(max-minUse))) + minUse;
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random long between min and max inclusive.*/
+   	public long randomLongBetween (long min, long max) {
+   		requests++;
+  		long minUse=min, maxUse=max;   		
+   		if (!MesquiteLong.isCombinable(min))
+   			minUse = 0;
+   		if (!MesquiteLong.isCombinable(min))
+   			maxUse = minUse+1;
+   		return ((long)(nextDouble()*(max-minUse + 1))) + minUse;
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random double between min and max inclusive.*/
+   	public double getDouble(double min, double max) {
+   		requests++;
+   		return randomDoubleBetween(min,max);
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random double between min and max inclusive.*/
+   	public static double getDoubleStatic(double min, double max) {
+   		RandomBetween rnb = new RandomBetween();
+   		return rnb.randomDoubleBetween(min,max);
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random double between min and max inclusive.*/
+   	public static long getLongStatic(long min, long max) {
+   		RandomBetween rnb = new RandomBetween();
+   		return rnb.randomLongBetween(min,max);
+   	}
+	/*.................................................................................................................*/
+	/** Returns a random double between min and max inclusive.*/
+   	public static int getIntStatic(int min, int max) {
+   		RandomBetween rnb = new RandomBetween();
+   		return rnb.randomIntBetween(min,max);
+   	}
+   	
+	/*.................................................................................................................*/
+	public void setSeedToValueAtIndex(int index, long originalSeed, MesquiteLong seed) {
+		setSeed(originalSeed);
+		long rnd = originalSeed;  
+		for (int it = 0; it<= index; it++) 
+			rnd =  nextInt();
+		setSeed(rnd+1);
+		if (seed!=null)
+			seed.setValue(rnd + 1); 
+	}
+	
+	/*.................................................................................................................*/
+	public void addRequests(int index) {
+		for (int it = 0; it< index; it++)  {
+			nextDouble();
+			requests++;
+		}
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/Reconnectable.java b/Source/mesquite/lib/Reconnectable.java
new file mode 100644
index 0000000..cc70867
--- /dev/null
+++ b/Source/mesquite/lib/Reconnectable.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 2013 W. Maddison and D. Maddison.
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+
+/* ======================================================================== */
+/**Interface for object to claim it is reconnectable, for processes that need to be re-established*/
+public interface Reconnectable {
+   	/** Called when Mesquite re-reads a file that had had unfinished tree filling, e.g. by an external process, to pass along the command that should be executed on the main thread when trees are ready.*/
+   	public void reconnectToRequester(MesquiteCommand command);
+}
+
diff --git a/Source/mesquite/lib/Renamable.java b/Source/mesquite/lib/Renamable.java
new file mode 100644
index 0000000..d15dadd
--- /dev/null
+++ b/Source/mesquite/lib/Renamable.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is renameable*/
+public interface Renamable {
+ 	public void setName(String name);
+}
+
diff --git a/Source/mesquite/lib/ResizableLegend.java b/Source/mesquite/lib/ResizableLegend.java
new file mode 100644
index 0000000..1923661
--- /dev/null
+++ b/Source/mesquite/lib/ResizableLegend.java
@@ -0,0 +1,148 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+
+/* ======================================================================== */
+public abstract class ResizableLegend extends Legend {
+	boolean sizing = false;
+	protected int sizeOffsetX = 0;
+	protected int sizeOffsetY=0;
+	protected	int legendWidth;
+	protected	int legendHeight;
+	
+	public ResizableLegend (int defaultWidth, int defaultHeight) {
+		super(defaultWidth, defaultHeight);
+		legendWidth = defaultWidth;
+		legendHeight = defaultHeight;
+	}
+	/*.................................................................................................................*/
+	public void legendResized(int widthChange, int heightChange){
+	}
+	
+	public void setSize(int w, int h){
+		legendWidth = w;
+		legendHeight = h;
+		super.setSize(w, h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		legendWidth = w;
+		legendHeight = h;
+		super.setBounds(x, y, w, h);
+	}
+	public int getLegendWidth(){
+		return legendWidth;
+	}
+	public int getLegendHeight(){
+		return legendHeight;
+	}
+	public void mouseDrag (int modifiers, int x, int y, MesquiteTool tool) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (sizing && GraphicsUtil.useXORMode(null, false)) {
+			Graphics g=getParent().getGraphics();
+	    	if (g!=null){
+
+		    		g.setXORMode(Color.white);
+		    		g.setClip(null);
+		   		g.setColor(Color.black);
+				g.drawRect(getBounds().x, getBounds().y, getBounds().width-1 + sizeOffsetX, getBounds().height-1 + sizeOffsetY);
+				sizeOffsetX=x-origTouchX;
+				sizeOffsetY=y-origTouchY;
+				g.drawRect(getBounds().x, getBounds().y, getBounds().width-1 + sizeOffsetX, getBounds().height-1 + sizeOffsetY);
+				g.dispose();
+			}
+		}
+		else
+			super.mouseDrag(modifiers, x, y, tool);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (MesquiteEvent.controlKeyDown(modifiers)){
+			super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+		else if (y> getBounds().height-8 && x > getBounds().width - 8) {
+			sizing = true;
+			origTouchX=x;
+			origTouchY=y;
+			sizeOffsetX=0;
+			sizeOffsetY=0;
+			if (GraphicsUtil.useXORMode(null, false)){
+				Graphics g=getParent().getGraphics();
+	    	if (g!=null){
+	    		g.setClip(null);
+	    		g.setXORMode(Color.white);
+		   		g.setColor(Color.black);
+				g.drawRect(getBounds().x, getBounds().y, getBounds().width-1, getBounds().height-1);
+				g.dispose();
+			}
+			}
+		}
+		else {
+			super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseUp (int modifiers, int x, int y, MesquiteTool tool) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (sizing && GraphicsUtil.useXORMode(null, false)) {
+			Graphics g=getParent().getGraphics();
+	    	if (g!=null){
+		    	g.setXORMode(Color.white);
+		   		g.setColor(Color.black);
+				g.drawRect(getBounds().x, getBounds().y, getBounds().width-1 + sizeOffsetX, getBounds().height-1 + sizeOffsetY);
+				g.dispose();
+				legendWidth = getBounds().width + sizeOffsetX;
+				legendHeight = getBounds().height + sizeOffsetY;
+				if (legendWidth<16)
+					legendWidth = 16;
+				if (legendHeight<16)
+					legendHeight = 16;
+					
+				legendResized(sizeOffsetX, sizeOffsetY);
+				setSize(legendWidth, legendHeight);
+				sizing = false;
+			}
+		}
+		else
+			super.mouseUp(modifiers, x, y, tool);
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the bounds of the panel, in pixels", "[x (left bound)] [y (upper bound)] [width] [height]", commandName, "setBounds")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int xA = MesquiteInteger.fromString(arguments, pos);
+    	 		int yA = MesquiteInteger.fromString(arguments, pos);
+    	 		int wA =  MesquiteInteger.fromString(arguments, pos);
+    	 		int hA  = MesquiteInteger.fromString(arguments, pos);
+    	 		int currentW = getBounds().width;
+    	 		int currentH = getBounds().height;
+    	 		setBounds(xA, yA, wA, hA);
+    	 		legendResized(wA - currentW, hA - currentH);
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+}
+
diff --git a/Source/mesquite/lib/RotatedRectangle.java b/Source/mesquite/lib/RotatedRectangle.java
new file mode 100644
index 0000000..3524085
--- /dev/null
+++ b/Source/mesquite/lib/RotatedRectangle.java
@@ -0,0 +1,162 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/** This class draws and fills a rotated rectangle, using an internal polygon.  The rectangle is defined by two points
+(x1, y1 and x2, y2), the line between which serve as one edge of the rectangle (its "spine"), and a width.
+The width is either above or below the line (higher or lower y's) depending on the boolean "extendAbove".  The shape
+parameter determines if it is a full rectangle or some truncated part thereof.*/
+public class RotatedRectangle {
+	public static final int RECTANGLE =0;
+	public static final int FLATHORIZONTAL =1;
+	public static final int FLATVERTICAL =2;
+	/*
+	public static final int HOUSEUP =3;
+	public static final int HOUSEDOWN =4;
+	public static final int HOUSERIGHT =5;
+	public static final int HOUSELEFT =6;
+	*/
+	private int primaryX1, primaryY1,primaryX2, primaryY2;
+	boolean extendAbove = true;
+	Polygon poly;
+	public RotatedRectangle(){
+		poly = new Polygon();
+		poly.xpoints = new int[8];
+		poly.ypoints = new int[8];
+	}
+	public void setShape(int x1, int y1, int x2, int y2, int width, boolean extendAbove, int shape){
+		primaryX1 = x1;
+		primaryY1 = y1;
+		primaryX2 = x2;
+		primaryY2 = y2;
+		this.extendAbove = extendAbove;
+		if (x1==x2) {
+			poly.npoints=0;
+			poly.addPoint(x1, y1);
+			if (extendAbove) {
+				poly.addPoint(x1-width, y1);
+				poly.addPoint(x2-width, y2);
+			}
+			else {
+				poly.addPoint(x1+width, y1);
+				poly.addPoint(x2+width, y2);
+			}
+			poly.addPoint(x2, y2);
+			poly.addPoint(x1, y1);
+			poly.npoints=5;
+		}
+		else if (y1==y2){
+			poly.npoints=0;
+			poly.addPoint(x1, y1);
+			if (extendAbove) {
+				poly.addPoint(x1, y1-width);
+				poly.addPoint(x2, y2-width);
+			}
+			else {
+				poly.addPoint(x1, y1+width);
+				poly.addPoint(x2, y2+width);
+			}
+			poly.addPoint(x2, y2);
+			poly.addPoint(x1, y1);
+			
+			poly.npoints=5;
+		}
+		else {
+			poly.npoints=0;
+			double oldSlope = (y1-y2)*1.0/(x1-x2);
+			double newSlope = 1.0/oldSlope;
+			double ns2 = (1+newSlope*newSlope);
+			double os2 = (1+oldSlope*oldSlope);
+			int offsetX = (int) Math.sqrt((width*width)*1.0/ns2);
+			int offsetY = (int) Math.sqrt((width*width)*1.0/os2);
+
+			if (shape == FLATHORIZONTAL) {
+				offsetX += (int)Math.abs((Math.sqrt((width*width)*1.0/os2))/oldSlope);
+				offsetY = 0;
+			}
+			else if (shape == FLATVERTICAL){
+				offsetY += (int)Math.abs(Math.sqrt((width*width)*1.0/ns2)*oldSlope);
+				offsetX = 0;
+			}
+			else {
+				offsetX = (int) Math.sqrt((width*width)*1.0/ns2);
+				offsetY = (int) Math.sqrt((width*width)*1.0/os2);
+			}
+			poly.addPoint(x1, y1);
+			if (extendAbove) {
+				if ((x1>x2 && y1>y2)|| (x1<x2 && y1<y2)) {
+					poly.addPoint(x1+ offsetX, y1-offsetY);
+					poly.addPoint(x2+ offsetX, y2-offsetY);
+				}
+				else {
+					poly.addPoint(x1- offsetX, y1-offsetY);
+					poly.addPoint(x2- offsetX, y2-offsetY);
+				}
+			}
+			else {
+				if ((x1>x2 && y1<y2) || (x1<x2 && y1>y2)){
+					poly.addPoint(x1+ offsetX, y1+offsetY);
+					poly.addPoint(x2+ offsetX, y2+offsetY);
+				}
+				else {
+					poly.addPoint(x1- offsetX, y1+offsetY);
+					poly.addPoint(x2- offsetX, y2+offsetY);
+				}
+			}
+			poly.addPoint(x2, y2);
+			poly.addPoint(x1, y1);
+			poly.npoints=5;
+		}
+	}
+	public boolean contains(int x, int y){ 
+		return poly.contains(x,y);		
+	}
+	public void draw(Graphics g){ 
+		g.drawPolygon(poly);		
+	}
+	private void offsetLine(Graphics g, int  x1, int  y1, int  x2, int  y2, int offset){
+		if (extendAbove) 
+			g.drawLine(x1, y1-offset, x2, y2-offset); 
+		else
+			g.drawLine(x1, y1+offset, x2, y2+offset); 
+	}
+	
+	public void fill(Graphics g, boolean threeD){ 
+		if (threeD){
+			Color c = g.getColor();
+			Color light = ColorDistribution.brighter(c, 0.66);
+			g.setColor(light);
+			g.fillPolygon(poly);
+			light = ColorDistribution.brighter(light, 0.66);
+			g.setColor(light);
+			offsetLine(g, primaryX1,primaryY1, primaryX2, primaryY2, 1); 
+			offsetLine(g, primaryX1, primaryY1, primaryX2, primaryY2, 3); 
+			offsetLine(g, primaryX1, primaryY1, primaryX2, primaryY2, 4); 
+			g.setColor(Color.white);
+			offsetLine(g, primaryX1, primaryY1, primaryX2, primaryY2, 2); 
+			if (c!=null) g.setColor(c);
+			g.drawPolygon(poly);
+		}
+		else
+			g.fillPolygon(poly);		
+	}
+}
+
+
diff --git a/Source/mesquite/lib/ScrollTextField.java b/Source/mesquite/lib/ScrollTextField.java
new file mode 100644
index 0000000..0ff567b
--- /dev/null
+++ b/Source/mesquite/lib/ScrollTextField.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/*===============================================*/
+/** little text field for MiniScroll*/
+public class ScrollTextField extends TextField {
+	MiniScroll miniScroll;
+	Color color=null;
+	boolean forgetFocusGained=false;
+	boolean suppressFocusLost = false;
+	public ScrollTextField (MiniScroll miniScroll, String text, int i) {
+		super(text, i);
+		this.miniScroll = miniScroll;
+		//addFocusListener(new FListener());
+	}
+	
+	public void print(Graphics g){
+	}
+	
+/*	public boolean lostFocus (Evenxxxt e, Object o) {
+	
+		try {
+			int value = MesquiteInteger.fromString(getText());
+			miniScroll.crement(value);
+		} catch (NumberFormatException ex) {}
+	
+		return super.lostFocus(e, o);
+	}
+*/	
+}
+
diff --git a/Source/mesquite/lib/SelectionRectangle.java b/Source/mesquite/lib/SelectionRectangle.java
new file mode 100644
index 0000000..023f86e
--- /dev/null
+++ b/Source/mesquite/lib/SelectionRectangle.java
@@ -0,0 +1,71 @@
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+// not yet used; only partially built
+/* ======================================================================== */
+public class SelectionRectangle  {
+	Rectangle selectionRect;
+	
+	public SelectionRectangle(Graphics2D g2, int x, int y, int w, int h){
+		this.selectionRect = new Rectangle(x,y,w,h);
+		GraphicsUtil.fillTransparentSelectionRectangle(g2, x,y,w,h);
+	}
+	public Rectangle setRectangle() {
+		return selectionRect;
+	}
+	public void setRectangle(Rectangle selectionRect) {
+		this.selectionRect = selectionRect;
+	}
+	public void zeroRectangle(Rectangle selectionRect) {
+		this.selectionRect = null;
+	}
+	public void setRectangle(int x, int y, int w, int h) {
+		this.selectionRect = new Rectangle(x,y,w,h);
+		GraphicsUtil.fixRectangle(selectionRect);
+	}
+
+	public static Area createAreaFromRectangle(Rectangle rect) {
+		try{
+			MesquitePath2DFloat path = new MesquitePath2DFloat();
+		path.moveTo(rect.x, rect.y);
+		path.lineTo(rect.x+rect.width, rect.y);
+		path.lineTo(rect.x+rect.width, rect.y+rect.height);
+		path.lineTo(rect.x, rect.y+rect.height);
+		path.lineTo(rect.x, rect.y);
+		path.closePath();
+		return path.getArea();
+		}
+		catch (Error e){
+			return null;
+		}
+		catch (Exception e){
+			return null;
+		}
+	}
+	public void drawSelectionDifference(Graphics2D g2, Component comp, int x, int y, int w, int h) {
+		Rectangle newRect = new Rectangle(x,y,w,h);
+		GraphicsUtil.fixRectangle(newRect);
+		Area newArea = createAreaFromRectangle(newRect);
+		Area differenceArea = createAreaFromRectangle(selectionRect);
+		
+		if (differenceArea!=null) {
+			differenceArea.exclusiveOr(newArea);
+			Shape oldClip = g2.getClip();
+			g2.setClip(differenceArea);
+			if (selectionRect.contains(newRect)) { // original rect is bigger
+				comp.repaint(selectionRect.x, selectionRect.y, selectionRect.width, selectionRect.height);
+				GraphicsUtil.fillTransparentSelectionRectangle(g2, x,y,w,h);
+			} else if (newRect.contains(selectionRect)) { // new rect is bigger
+				GraphicsUtil.fillTransparentSelectionArea(g2, differenceArea);
+			}
+			g2.setClip(oldClip);
+		}
+
+		
+		selectionRect.setRect(newRect);
+	
+		
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/lib/Selectionable.java b/Source/mesquite/lib/Selectionable.java
new file mode 100644
index 0000000..156c6c9
--- /dev/null
+++ b/Source/mesquite/lib/Selectionable.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*.................................................................................................................*/
+/**    */
+public interface Selectionable extends Listenable {
+	/** Sets whether or not the part is selected */
+	public void setSelected(int part, boolean select);
+
+	/** Returns whether the part is selected */
+	public boolean getSelected(int part);
+
+	/** Deselects all parts */
+	public void deselectAll();
+
+	/** Selects all parts */
+	public void selectAll();
+
+	/** Returns whether there are any selected parts */
+	public boolean anySelected();
+
+	/** Returns number of selected parts */
+	public int numberSelected();
+	
+	/** Returns number of parts that can be selected*/
+	public int getNumberOfSelectableParts();
+}
+
+
+
+
diff --git a/Source/mesquite/lib/ShellScriptRunner.java b/Source/mesquite/lib/ShellScriptRunner.java
new file mode 100644
index 0000000..8971054
--- /dev/null
+++ b/Source/mesquite/lib/ShellScriptRunner.java
@@ -0,0 +1,172 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+
+import mesquite.lib.duties.*;
+
+/* TODO: 
+ * make a MesquiteExternalProcess that extends Process and stores things like 
+ * 		OutputStream inputToProcess = proc.getOutputStream();
+		OutputStreamWriter inputStreamsWriter = new OutputStreamWriter(inputToProcess);
+
+ * */
+
+/* ======================================================================== */
+public class ShellScriptRunner implements Commandable  {
+	static int sleepTime = 50;
+	Process proc;
+	String scriptPath;
+	String runningFileMessage;
+	boolean appendRemoveCommand;
+	String name;
+	String runningFilePath; //reconnect
+	String[] outputFilePaths; //reconnect
+	OutputFileProcessor outputFileProcessor; //reconnect
+	ShellScriptWatcher watcher; //reconnect
+	boolean visibleTerminal;
+	long[] lastModified;
+	
+	public ShellScriptRunner(String scriptPath, String runningFilePath, String runningFileMessage, boolean appendRemoveCommand, String name, String[] outputFilePaths, OutputFileProcessor outputFileProcessor, ShellScriptWatcher watcher, boolean visibleTerminal){
+		this.scriptPath=scriptPath;
+		this.runningFilePath=runningFilePath;
+		if (runningFilePath == null && !StringUtil.blank(scriptPath))
+			this.runningFilePath=ShellScriptUtil.getDefaultRunningFilePath();
+
+		this.runningFileMessage=runningFileMessage;
+		this.appendRemoveCommand =appendRemoveCommand;
+		this.name = name;
+		this.outputFilePaths = outputFilePaths;
+		this.outputFileProcessor = outputFileProcessor;
+		this.watcher = watcher;
+		this.visibleTerminal = visibleTerminal;
+	}
+	public ShellScriptRunner(){  //to be used for reconnecting
+	}
+
+	public void setOutputProcessor(OutputFileProcessor outputFileProcessor){
+		this.outputFileProcessor = outputFileProcessor;
+	}
+	public void setWatcher(ShellScriptWatcher watcher){
+		this.watcher = watcher;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setRunningFilePath " + ParseUtil.tokenize(runningFilePath));
+		if (outputFilePaths != null){
+			String files = " ";
+			for (int i = 0; i< outputFilePaths.length; i++){
+				files += " " + ParseUtil.tokenize(outputFilePaths[i]);
+			}
+			temp.addLine("setOutputFilePaths " + files);
+		}
+		return temp;
+	}
+	Parser parser = new Parser();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the running file path", "[file path]", commandName, "setRunningFilePath")) {
+			runningFilePath = parser.getFirstToken(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Sets the output file paths", "[file paths]", commandName, "setOutputFilePaths")) {
+			int num = parser.getNumberOfTokens(arguments);
+			outputFilePaths = new String[num];
+			if (num >0)
+				outputFilePaths[0] = parser.getFirstToken();
+			for (int i=1; i<num; i++)
+				outputFilePaths[i] = parser.getNextToken();
+		}
+		return null;
+	}	
+	
+	/*.................................................................................................................*/
+	public void resetLastModified(int i){
+		if (i>=0 && i<lastModified.length)
+			lastModified[i]=0;
+	}
+	/*.................................................................................................................*/
+	public void processOutputFiles(){
+		if (outputFileProcessor!=null && outputFilePaths!=null && lastModified !=null) {
+			String[] paths = outputFileProcessor.modifyOutputPaths(outputFilePaths);
+			for (int i=0; i<paths.length && i<lastModified.length; i++) {
+				File file = new File(paths[i]);
+				long lastMod = file.lastModified();
+				if (!MesquiteLong.isCombinable(lastModified[i])|| lastMod>lastModified[i]){
+					outputFileProcessor.processOutputFile(paths, i);
+					lastModified[i] = lastMod;
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** executes a shell script at "scriptPath".  If runningFilePath is not blank and not null, then Mesquite will create a file there that will
+	 * serve as a flag to Mesquite that the script is running.   */
+	public boolean executeInShell(){
+		proc = null;
+		try{
+			ShellScriptUtil.setScriptFileToBeExecutable(scriptPath);
+			if (!StringUtil.blank(runningFilePath)) {
+				if (StringUtil.blank(runningFileMessage))
+					MesquiteFile.putFileContents(runningFilePath, "Script running...", true);
+				else
+					MesquiteFile.putFileContents(runningFilePath, runningFileMessage, true);
+				if (appendRemoveCommand && MesquiteFile.fileExists(runningFilePath))
+					MesquiteFile.appendFileContents(scriptPath, StringUtil.lineEnding() + ShellScriptUtil.getRemoveCommand(runningFilePath), true);  //append remove command to guarantee that the runningFile is deleted
+				//+StringUtil.lineEnding()+ShellScriptUtil.getExitCommand()
+			}
+			proc = ShellScriptUtil.executeScript(scriptPath, visibleTerminal);
+
+		}
+		catch (IOException e){
+			MesquiteMessage.warnProgrammer("IOException in shell script executed by " + name);
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** monitors the run.   */
+	public boolean monitorAndCleanUpShell(){
+		lastModified=null;
+		boolean stillGoing = true;
+		if (outputFilePaths!=null) {
+			lastModified = new long[outputFilePaths.length];
+			LongArray.deassignArray(lastModified);
+		}
+
+		if (!StringUtil.blank(runningFilePath))   // is file at runningFilePath; watch for its disappearance
+			while (MesquiteFile.fileExists(runningFilePath) && stillGoing){
+				processOutputFiles();
+				try {
+					Thread.sleep(sleepTime);
+				}
+				catch (InterruptedException e){
+					MesquiteMessage.notifyProgrammer("InterruptedException in shell script executed by " + name);
+					return false;
+				}
+				stillGoing = watcher == null || watcher.continueShellProcess(proc);
+			}
+
+		if (outputFileProcessor!=null)
+			outputFileProcessor.processCompletedOutputFiles(outputFilePaths);
+		return true;
+	}
+
+
+
+}
diff --git a/Source/mesquite/lib/ShellScriptUtil.java b/Source/mesquite/lib/ShellScriptUtil.java
new file mode 100644
index 0000000..2cc0387
--- /dev/null
+++ b/Source/mesquite/lib/ShellScriptUtil.java
@@ -0,0 +1,325 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.util.*;
+import java.io.*;
+
+
+/* TODO: 
+ * make a MesquiteExternalProcess that extends Process and stores things like 
+ * 		OutputStream inputToProcess = proc.getOutputStream();
+		OutputStreamWriter inputStreamsWriter = new OutputStreamWriter(inputToProcess);
+	- all of the isWindows, StringUtil.lineEnding() needs to use line endings etc. from the computer running the process, not the local computer.
+
+ * */
+
+/* ======================================================================== */
+public class ShellScriptUtil  {
+	static int sleepTime = 50;
+
+	/*.................................................................................................................*/
+	public static String protectForShellScript(String s) {  //Is this only used for paths???!!!!!  See StringUtil.protectForWindows.
+		if (MesquiteTrunk.isWindows())
+			return StringUtil.protectForWindows(s);
+		else
+			return StringUtil.protectForUnix(s);
+	}
+	/*.................................................................................................................*/
+	public static String getWriteStringAsFile(String path, String contents) {
+		if (MesquiteTrunk.isWindows())
+			return "echo \"" + contents + "\" > " + StringUtil.protectForWindows(path) + StringUtil.lineEnding();
+		else
+			return "echo \"" + contents + "\" > " + StringUtil.protectForUnix(path) + StringUtil.lineEnding();
+	}
+
+	/*.................................................................................................................*
+    	String getAliasCommand(String alias, String expansion){
+    		return "alias " +StringUtil.protectForUnix(alias) + " " + StringUtil.protectForUnix(expansion) +StringUtil.lineEnding();
+    	}
+    	/*.................................................................................................................*/
+	public static String getLinkCommand(String path, String aliasPath){
+		if (MesquiteTrunk.isWindows())
+			return "shortcut -f -t " +StringUtil.protectForWindows(path) + " -n " + StringUtil.protectForUnix(aliasPath) +StringUtil.lineEnding();
+		else
+			return "ln  " +StringUtil.protectForUnix(path) + " " + StringUtil.protectForUnix(aliasPath) +StringUtil.lineEnding();
+	}
+	/*.................................................................................................................*/
+	public static String getChangeDirectoryCommand(String directory){
+		String directoryString;
+		if (MesquiteTrunk.isWindows()) {
+			directoryString = StringUtil.protectForWindows(directory);
+		} else {
+			directoryString = StringUtil.protectForUnix(directory);
+		}
+		return "cd " + directoryString +StringUtil.lineEnding();
+	}
+	/*.................................................................................................................*/
+	public static String getRemoveCommand(String filePath){
+		if (MesquiteTrunk.isWindows())
+			return "del " + StringUtil.protectForWindows(filePath) +StringUtil.lineEnding();
+		else
+			return "rm -f " + StringUtil.protectForUnix(filePath) +StringUtil.lineEnding();
+	}
+	/*.................................................................................................................*/
+	public static String getExitCommand(){
+		if (MesquiteTrunk.isWindows()){
+			return "";
+		}
+		else
+			return "exit " +StringUtil.lineEnding();
+	}
+	/*.................................................................................................................*/
+	public static String getSetFileTypeCommand(String filePath){
+		if (MesquiteTrunk.isMacOSX())
+			return "/Developer/Tools/setFile -t TEXT " + StringUtil.protectForUnix(filePath) +StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public static String getOpenDirectoryCommand(String directoryPath){
+		if (MesquiteTrunk.isMacOSX())
+			return "open " + StringUtil.protectForUnix(directoryPath) +StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public static void sendToProcessInput (Process proc, String input) {
+		
+		OutputStream inputToProcess = proc.getOutputStream();
+		OutputStreamWriter inputStreamsWriter = new OutputStreamWriter(inputToProcess);
+		BufferedWriter inputBufferedWriter = new BufferedWriter(inputStreamsWriter);
+		try {
+			try {
+				inputBufferedWriter.write(input);
+			} finally {
+				inputBufferedWriter.flush();
+			//	inputBufferedWriter.close();
+			} 
+		} catch (Exception e) {
+		}
+	}
+	/*.................................................................................................................*
+	public static MesquiteExternalProcess startExternalProcess(String executablePath){ 	
+		Process proc=null;
+		try {
+			if (MesquiteTrunk.isMacOSX()|| MesquiteTrunk.isLinux()) {
+				// remove double slashes or things won't execute properly
+				executablePath = executablePath.replaceAll("//", "/");
+				proc = Runtime.getRuntime().exec(executablePath);
+			} else {
+			}
+		}  catch (IOException e) {
+			MesquiteMessage.println("Script execution failed.");
+			return null;
+		}
+		if (proc != null) {
+			return new MesquiteExternalProcess(proc);
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public static Process executeScript(String scriptPath){ 
+		return executeScript(scriptPath, true);
+	}
+	/*.................................................................................................................*/
+	public static Process executeScript(String scriptPath, boolean visibleTerminal){ 
+		Process proc;
+		try {
+			String[] pathArray = null;
+			if (MesquiteTrunk.isMacOSX()){
+				if (visibleTerminal) {
+                    pathArray = new String[] {"open",  "-a","/Applications/Utilities/Terminal.app",  scriptPath};
+				}
+				else {
+					scriptPath = scriptPath.replaceAll("//", "/");
+                   	pathArray = new String[] {scriptPath};
+				}
+			}
+			else if (MesquiteTrunk.isLinux()) {
+				// remove double slashes or things won't execute properly
+				scriptPath = scriptPath.replaceAll("//", "/");
+               	pathArray = new String[] {scriptPath};
+				proc = Runtime.getRuntime().exec(pathArray);
+			} else {
+				scriptPath = "\"" + scriptPath + "\"";
+				pathArray = new String[] {"cmd", "/c", scriptPath};
+			}
+			proc = Runtime.getRuntime().exec(pathArray);
+		}  catch (IOException e) {
+			MesquiteMessage.println("Script execution failed. " + e.getMessage());
+			return null;
+		}
+		if (proc != null) {
+			StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
+			StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
+			errorGobbler.start();
+			outputGobbler.start();
+		}
+		return proc;
+	}
+	/*.................................................................................................................*/
+	public static boolean setScriptFileToBeExecutable(String scriptPath) throws IOException {
+		Process proc;
+		try {
+			//Original implementation (permission change was not complete before script execution attempted)
+			//if (!MesquiteTrunk.isWindows())
+			//	Runtime.getRuntime().exec(new String[] {"chmod", "+x", scriptPath } );
+			if(!MesquiteTrunk.isWindows()){
+				proc = Runtime.getRuntime().exec(new String[] {"chmod", "+x", scriptPath } );
+				try{// waitFor() so thread waits for permission change to complete before trying to run the script
+					proc.waitFor();
+				} catch (InterruptedException e){
+					MesquiteMessage.println("Thread interrupted while waiting for change in ownership.");
+					return false;
+				}
+			}
+		}
+		catch (IOException e) {
+			MesquiteMessage.println("Script cannot be set to be executable.");
+			return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public static String getDefaultRunningFilePath(){
+		Random rng = new Random(System.currentTimeMillis());
+		String runningFilePath = MesquiteModule.getTempDirectoryPath()  + MesquiteFile.fileSeparator + "running" + MesquiteFile.massageStringToFilePathSafe(MesquiteTrunk.getUniqueIDBase() + Math.abs(rng.nextInt()));
+		return runningFilePath;
+	}
+	/*.................................................................................................................*/
+	public static String getOutputFileCopyPath(String path) {
+		if (path==null)
+			return null;
+		else
+			return path + "2";
+	}
+	/*.................................................................................................................*/
+	public static void processOutputFiles(OutputFileProcessor outputFileProcessor, String[]outputFilePaths, long[] lastModified){
+		if (outputFileProcessor!=null && outputFilePaths!=null && lastModified !=null) {
+			String[] paths = outputFileProcessor.modifyOutputPaths(outputFilePaths);
+			for (int i=0; i<paths.length && i<lastModified.length; i++) {
+				File file = new File(paths[i]);
+				long lastMod = file.lastModified();
+				if (!MesquiteLong.isCombinable(lastModified[i])|| lastMod>lastModified[i]){
+					outputFileProcessor.processOutputFile(paths, i);
+					lastModified[i] = lastMod;
+				}
+			}
+		}
+	}
+
+
+	/*.................................................................................................................*/
+	/** executes a shell script at "scriptPath".  If runningFilePath is not blank and not null, then Mesquite will create a file there that will
+	 * serve as a flag to Mesquite that the script is running.   */
+	public static boolean executeAndWaitForShell(String scriptPath, String runningFilePath, String runningFileMessage, boolean appendRemoveCommand, String name, String[] outputFilePaths, OutputFileProcessor outputFileProcessor, ShellScriptWatcher watcher, boolean visibleTerminal){
+		Process proc = null;
+		long[] lastModified=null;
+		boolean stillGoing = true;
+		if (outputFilePaths!=null) {
+			lastModified = new long[outputFilePaths.length];
+			LongArray.deassignArray(lastModified);
+		}
+		try{
+			ShellScriptUtil.setScriptFileToBeExecutable(scriptPath);
+			if (!StringUtil.blank(runningFilePath)) {
+				if (StringUtil.blank(runningFileMessage))
+					MesquiteFile.putFileContents(runningFilePath, "Script running...", true);
+				else
+					MesquiteFile.putFileContents(runningFilePath, runningFileMessage, true);
+				if (appendRemoveCommand && MesquiteFile.fileExists(runningFilePath))
+					MesquiteFile.appendFileContents(scriptPath, StringUtil.lineEnding() + ShellScriptUtil.getRemoveCommand(runningFilePath), true);  //append remove command to guarantee that the runningFile is deleted
+				//+StringUtil.lineEnding()+ShellScriptUtil.getExitCommand()
+			}
+			proc = ShellScriptUtil.executeScript(scriptPath, visibleTerminal);
+
+			if (proc==null) {
+				MesquiteMessage.notifyProgrammer("Process is null in shell script executed by " + name);
+				return false;
+			}
+			else if (!StringUtil.blank(runningFilePath))   // is file at runningFilePath; watch for its disappearance
+				while (MesquiteFile.fileExists(runningFilePath) && stillGoing){
+					processOutputFiles (outputFileProcessor, outputFilePaths, lastModified);
+					try {
+						Thread.sleep(sleepTime);
+					}
+					catch (InterruptedException e){
+						MesquiteMessage.notifyProgrammer("InterruptedException in shell script executed by " + name);
+						return false;
+					}
+					stillGoing = watcher == null || watcher.continueShellProcess(proc);
+				}
+		}
+		catch (IOException e){
+			MesquiteMessage.warnProgrammer("IOException in shell script executed by " + name);
+			return false;
+		}
+		if (outputFileProcessor!=null)
+			outputFileProcessor.processCompletedOutputFiles(outputFilePaths);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** executes a shell script at "scriptPath".  If runningFilePath is not blank and not null, then Mesquite will create a file there that will
+	 * serve as a flag to Mesquite that the script is running.   */
+	public static boolean executeAndWaitForShell(String scriptPath, String runningFilePath, String runningFileMessage, boolean appendRemoveCommand, String name){
+		return executeAndWaitForShell( scriptPath,  runningFilePath,  runningFileMessage,  appendRemoveCommand,  name, null, null, null, true);
+	}
+	/*.................................................................................................................*/
+	public static boolean executeAndWaitForShell(String scriptPath, String name){
+		String runningFilePath = null;
+		if (!StringUtil.blank(scriptPath))
+			runningFilePath=getDefaultRunningFilePath();
+		return executeAndWaitForShell(scriptPath, runningFilePath, null, true, name);
+	}
+
+	/*.................................................................................................................*/
+	public static boolean executeLogAndWaitForShell(String scriptPath, String name, String[] outputFilePaths, OutputFileProcessor outputFileProcessor, ShellScriptWatcher watcher){
+		String runningFilePath = null;
+		if (!StringUtil.blank(scriptPath))
+			runningFilePath=getDefaultRunningFilePath();
+		return executeAndWaitForShell(scriptPath, runningFilePath, null, true, name, outputFilePaths, outputFileProcessor, watcher, true);
+	}
+
+
+
+}
+
+class StreamGobbler extends Thread {
+	InputStream is;
+
+	String type;
+
+	StreamGobbler(InputStream is, String type) {
+		this.is = is;
+		this.type = type;
+	}
+
+	public void run() {
+		try {
+			InputStreamReader isr = new InputStreamReader(is);
+			BufferedReader br = new BufferedReader(isr);
+			String line = null;
+			while ((line = br.readLine()) != null) {
+				System.out.println(type + ": " + line);
+
+			}
+		} catch (IOException ioe) {
+			ioe.printStackTrace();
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/ShellScriptWatcher.java b/Source/mesquite/lib/ShellScriptWatcher.java
new file mode 100644
index 0000000..43f419f
--- /dev/null
+++ b/Source/mesquite/lib/ShellScriptWatcher.java
@@ -0,0 +1,20 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public interface ShellScriptWatcher {
+
+	public boolean continueShellProcess(Process proc);
+
+}
diff --git a/Source/mesquite/lib/Short2DArray.java b/Source/mesquite/lib/Short2DArray.java
new file mode 100644
index 0000000..abe94b1
--- /dev/null
+++ b/Source/mesquite/lib/Short2DArray.java
@@ -0,0 +1,293 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/* ======================================================================== */
+public class Short2DArray {
+	short[][] values;
+	int numC;
+	 int numT;
+	NameReference name=null;
+	public Short2DArray(int numC, int numT){
+		this.numC = numC;
+		this.numT = numT;	
+		values = new short[numC][numT];
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  ShortArray.unassigned;
+	}
+	public Short2DArray(short[][] input){
+		this(numFullColumns(input), numFullRows(input));
+		for (int i=0; i<numC; i++)
+			for (int j=0; j<numT; j++)
+				values[i][j] =  input[i][j];
+	}
+	/*...........................................................*/
+	public static int numFullRows(short[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(short[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public short getValue(int ic, int it){
+		if (values==null || (ic <0 || ic >= values.length) || (it <0 || it >= values[ic].length))
+			return ShortArray.unassigned;
+		else
+			return values[ic][it];
+	}
+	/*...........................................................*/
+	public short[] getValues(int ic) {
+		if (values == null || ic <0 || ic >= values.length)
+			return null;
+		else
+			return values[ic];
+	}
+	/*...........................................................*/
+	public short[][] getMatrix() {
+		return values;
+	}
+	/*...........................................................*/
+	public void setValue(int ic, int it, short value) {
+		if (values!=null && ic >=0 && ic < values.length)
+		 	if (it >=0 && it < values[ic].length)
+				values[ic][it] = value;
+	}
+	/*...........................................................*/
+	public void setValues(Short2DArray incoming) {
+		if (incoming !=null) {
+			resetSize(incoming.getSizeC(), incoming.getSizeT());
+			for (int it=0; it<incoming.getSizeT() && it < getSizeT(); it++) {
+				for (int ic=0; ic<incoming.getSizeC() && ic < getSizeC(); ic++) {
+					setValue(ic, it, incoming.getValue(ic, it));
+				}
+			}
+		}
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int ic=0; ic<values.length; ic++)
+			for (int it=0; it<values[ic].length; it++)
+			values[ic][it] =  ShortArray.unassigned;
+	}
+	/*...........................................................*/
+	/** Changes the array size to the new dimensions*/
+	public void resetSize(int newNumC, int newNumT) {
+		if (newNumC == numC && newNumT == numT)
+			return;
+		short[][] newLongValues = new short[newNumC][newNumT];
+		for (int i=0; i<newNumC; i++)
+			for (int j=0; j<newNumT; j++) {
+				if (i<numC && j<numT)
+					newLongValues[i][j]=values[i][j];
+				else
+					newLongValues[i][j]=0;
+			}
+		values=newLongValues;
+		numC=newNumC;
+		numT=newNumT;
+	}
+	/*...........................................................*/
+	public int getSizeC() {
+		return numC;
+	}
+	/*...........................................................*/
+	public int getSizeT() {
+		return numT;
+	}
+	public static void swapColumns(short[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		short[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveColumns(short[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		short[][] newValues = new short[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	
+	/*...........................................................*/
+	public static short[][] addColumns(short[][] d, int numRows, short defaultValue, int starting, int num){
+		if (num <= 0 || d == null)
+			return d;
+		int numChars = d.length;
+		if (d.length <= 0) {
+			short[][] newMatrix=new short[numChars+num][numRows];
+			for (int ic=0; ic<numChars+num; ic++){
+				for (int it=0; it<numRows; it++) 
+					newMatrix[ic][it] = defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+		int numTaxa = d[0].length;
+		if (numTaxa <= 0 && numRows>=0)
+			numTaxa = numRows;
+		else if (numTaxa<0)
+			numTaxa=0;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+		if (newNumChars<0) {
+			MesquiteMessage.printStackTrace("Short2DArray.addColumns with newNumChars = " + newNumChars);
+			MesquiteMessage.println("numChars: " + numChars + ", num: " + num+ ", d.length: " + num);
+			return d;
+		}
+		if (numTaxa<0) {
+			MesquiteMessage.printStackTrace("Short2DArray.addColumns with numTaxa = " + numTaxa);
+			return d;
+		}
+		short[][] newMatrix=new short[newNumChars][numTaxa];
+		for (int ic=0; ic<newNumChars; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic][it] = defaultValue; //filling with missing data
+		}
+		for (int ic=0; ic<=starting; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic][it] = d[ic][it]; //transferring old first part
+		}
+		for (int ic=0; ic<numChars - starting -1 ; ic++){
+			for (int it=0; it<numTaxa; it++) 
+				newMatrix[ic + starting + num + 1][it] = d[starting + ic+1][it]; //transferring old second part
+		}
+		return newMatrix;
+		
+	}
+	/*...........................................................*/
+	public static short[][] addColumns(short[][] d, short defaultValue, int starting, int num){
+		return addColumns(d, -1, defaultValue, starting, num);
+	}
+	/*...........................................................*/
+	public static short[][] deleteColumns(short[][] d, int starting, int num){
+		if (num <= 0 || d == null)
+			return d;
+		int numChars = d.length;
+		if (starting<0)
+			return d;
+		else if (starting>numChars)
+			return d;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars =numChars-num;
+
+
+		if (d.length <= 0)
+			return new short[numChars-num][];
+		int numTaxa = d[0].length;
+		
+		short[][] newMatrix=new short[newNumChars][numTaxa];
+		for (int ic=0; ic<starting; ic++){
+			for (int it=0; it<numTaxa && it< d[ic].length; it++) 
+				newMatrix[ic][it] = d[ic][it]; //transferring old first part
+		}
+		for (int ic=starting + num; ic<numChars && ic-num<newNumChars; ic++){
+			for (int it=0; it<numTaxa && it< d[ic].length; it++) {
+				newMatrix[ic-num][it] = d[ic][it]; //transferring old second part
+			}
+		}
+		return newMatrix;
+	}
+	
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	public static String toString(short[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		for (int j=0; j<numRows; j++) {
+			result.append('[');
+			for (int i=0; i<numColumns; i++) {
+				
+				result.append(Short.toString(matrix[i][j]));
+				result.append(' ');
+			}
+			result.append(']');
+			result.append('\n');
+		}
+		return result.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/ShortArray.java b/Source/mesquite/lib/ShortArray.java
new file mode 100644
index 0000000..a185ab1
--- /dev/null
+++ b/Source/mesquite/lib/ShortArray.java
@@ -0,0 +1,357 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+public class ShortArray implements Listable {
+	short[] values;
+	NameReference name=null;
+	
+	public static final short unassigned = Short.MIN_VALUE+1;
+	public ShortArray(int num){
+		values = new short[num];
+		for (int i=0; i<num; i++)
+			values[i] =  unassigned;
+	}
+	/*...........................................................*/
+	public boolean legalIndex(int i){
+		return (values!=null && i>=0 && i<values.length);
+	}
+	/*...........................................................*/
+	public short[] getMatrix(){
+		return values;
+	}
+	/*...........................................................*/
+	public short getValue(int index){
+		if (!legalIndex(index))
+			return unassigned;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public void setValue(int index, short value) {
+		if (legalIndex(index))
+			values[index] = value;
+	}
+	/*...........................................................*/
+	public void setValues(short[] values) {
+		if (values==null)
+			this.values = new short[0];
+		else
+			this.values= values;
+	}
+	/*...........................................................*/
+	public void copyTo(ShortArray d){
+		if (d==null || d.values.length!=values.length)
+			return;
+		for (int i=0; i<values.length; i++)
+			d.values[i] =  values[i];
+	}
+	/*...........................................................*/
+	public void zeroArray(){
+		
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	public static void zeroArray(short[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  0;
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  unassigned;
+	}
+	/*...........................................................*/
+	public static void deassignArray(short[] values){
+		if (values==null)
+			return;
+		for (int i=0; i<values.length; i++)
+			values[i] =  unassigned;
+	}
+	/*...........................................................*/
+	public int indexOf(short match){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(short[] values, short match){
+		if (values==null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (values[i]== match)
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int countSame(short[] a, short match){
+		if (a==null)
+			return 0;
+		int count= 0;
+		for (int i=0; i<a.length; i++)
+			if (a[i]== match)
+				count++;
+		return count;
+	}
+	/*...........................................................*/
+	public boolean fillNextUnassigned(short v){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== unassigned) {
+				values[i] = v;
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	public static void sort(short[] array){
+		if (array==null || array.length<=1)
+			return;
+		
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && array[j]>array[j+1]; j--) {
+				short temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		
+	}
+	/*...........................................................*/
+	public int getSize() {
+		if (values==null)
+			return 0;
+		return values.length;
+	}
+	/*...........................................................*/
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		short[] newLongValues = new short[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newLongValues[i]=values[i];
+		if (newNum>getSize())
+			for (int i=getSize(); i<newNum; i++)
+				newLongValues[i]=unassigned;
+		values=newLongValues;
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num, short defaultValue) {
+		values=addParts(values, starting, num, defaultValue);
+	}
+	/*...........................................................*/
+	public static short[] addParts(short[] d, int starting, int num, short defaultValue) {
+		if (num<=0 || d==null)
+			return d;
+		
+		if (d.length <= 0) {
+			short[] newMatrix=new short[num];
+			for (int ic=0; ic<num; ic++){
+					newMatrix[ic]= defaultValue; //filling with missing data
+			}
+			return newMatrix;
+		}
+		
+		if (starting<0) 
+			starting = -1;
+		if (starting>d.length) 
+			starting = d.length-1;
+		int newNum = d.length + num;
+		short[] newValues = new short[newNum];
+		for (int i=0; i<=starting; i++)
+			newValues[i]=d[i];
+		for (int i=0; i<num ; i++)
+			newValues[starting + i + 1]=defaultValue;
+		for (int i=0; i<d.length-starting-1; i++)
+			newValues[i +starting+num+1]=d[starting + i + 1];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0 || starting<0 || starting>=getSize())
+			return;
+		values = deleteParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static short[] deleteParts(short[] d, int starting, int num) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		if (num+starting>d.length)
+			num = d.length-starting;
+		int newNum =d.length - num;
+		short[] newValues = new short[newNum];
+		for (int i=0; i<starting; i++)
+			newValues[i]=d[i];
+		for (int i=starting+num; i<d.length; i++)
+			newValues[i-num]=d[i];
+		return newValues;
+	}
+	/*...........................................................*/
+	public static short[] getMoveParts(short[] d, int starting, int num, int justAfter) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		short[] newValues = new short[d.length];
+
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+
+		return newValues;
+	}
+	/*...........................................................*/
+	public void moveParts(int starting, int num, int justAfter) {
+		moveParts(values, starting, num, justAfter);
+	}
+	/*...........................................................*/
+	public boolean swapParts(int first, int second) {
+		if (first<0 || first>=values.length || second<0 || second>=values.length) 
+			return false;
+		short temp = values[first];
+		values[first] = values[second];
+		values[second] = temp;
+		return true;
+	}
+	/*...........................................................*/
+	public static void swapParts(short[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		short temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveParts(short[] d, int starting, int num, int justAfter) {   //DRM new 7 March 08
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		short[] newValues = new short[d.length];
+		if (starting>justAfter){
+			int count =justAfter+1;
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+
+			for (int i=justAfter+1; i<=starting+num-1; i++)
+				d[i]=newValues[i];
+
+		}
+		else {  // moving down			
+			int count =starting;
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=justAfter; i++)
+				d[i]=newValues[i];
+		}
+	}
+	/*...........................................................*/
+	public static void movePartsOriginal(short[] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		short[] newValues = new short[d.length];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public static String toString(short[] vector){
+		if (vector==null ||  vector.length==0)
+			return null;  
+		StringBuffer result = new StringBuffer(vector.length*2);
+		result.append('[');
+		for (int i=0; i<vector.length; i++) {
+			if (vector[i] == unassigned)
+				result.append('?');
+			else
+				result.append(Short.toString(vector[i]));
+			result.append(' ');
+		}
+		result.append(']');
+		return result.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/Showable.java b/Source/mesquite/lib/Showable.java
new file mode 100644
index 0000000..ef78616
--- /dev/null
+++ b/Source/mesquite/lib/Showable.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+
+/* ======================================================================== */
+/**Interface for object to claim it can be shown, i.e. when "showMe" is called, the object in some way will present itself
+to the user*/
+public interface Showable {
+ 	public void showMe();
+}
+
diff --git a/Source/mesquite/lib/SimpleIntegerField.java b/Source/mesquite/lib/SimpleIntegerField.java
new file mode 100644
index 0000000..99d4099
--- /dev/null
+++ b/Source/mesquite/lib/SimpleIntegerField.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*===============================================*/
+/** a field for text that cannot have line feeds/carriage returns in it.  */
+public class SimpleIntegerField extends TextField  {
+	boolean isInteger=true;
+	int initialValue=0;
+	int min=MesquiteInteger.unassigned;
+	int max=MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public SimpleIntegerField (int initialValue, int fieldLength, int min, int max) {
+		super(""+initialValue,fieldLength);
+		this.initialValue = initialValue;
+		this.min = min;
+		this.max = max;
+	}
+	/*.................................................................................................................*/
+	public Dimension getPreferredSize() {
+		Dimension d = super.getPreferredSize();
+		d.height +=4;
+		return d;
+	}
+	/*.................................................................................................................*/
+	public SimpleIntegerField (String initialString) {
+		super(initialString);
+	}
+	/*.................................................................................................................*/
+	public int getValue () {
+		String s = getText();
+		int value = MesquiteInteger.fromString(s);
+		isInteger=true;
+		if (!MesquiteInteger.isCombinable(value)) {
+			value=initialValue;
+			isInteger=false;
+		} else if (value< min && MesquiteInteger.isCombinable(min))
+			value = min;
+		else if (value>max && MesquiteInteger.isCombinable(max)) 
+			value = max;
+		return value;
+	}
+
+}
diff --git a/Source/mesquite/lib/SimpleTaxonNamer.java b/Source/mesquite/lib/SimpleTaxonNamer.java
new file mode 100644
index 0000000..7c4f06c
--- /dev/null
+++ b/Source/mesquite/lib/SimpleTaxonNamer.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public class SimpleTaxonNamer extends TaxonNamer {
+	String[] translationTable= null;
+	
+	public SimpleTaxonNamer() {
+	}
+	public boolean initialize(Taxa taxa){
+		getTranslationTable(taxa);
+		return true;
+	}
+	public String getNameToUse(Taxon taxon){
+		return "t" + taxon.getNumber();  
+	}
+	public String getNameToUse(Taxa taxa, int it){
+		return "t"+it;
+	}
+	/** Given a taxon name "name", this method returns the taxon number this name represents. 
+	This one is based upon the contents of the translation file only. */
+	public boolean loadTranslationTable(Taxa taxa, String translationFile){
+		if (taxa==null || StringUtil.blank(translationFile))
+			return false;
+		if (translationTable==null || translationTable.length!=taxa.getNumTaxa())
+			translationTable = new String[taxa.getNumTaxa()];
+		Parser parser = new Parser(translationFile);
+		Parser subParser = new Parser();
+		String line = parser.getRawNextDarkLine();
+
+		boolean abort = false;
+		subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+		subParser.setWhitespaceString("\t");
+		subParser.setPunctuationString("");
+
+
+		while (!StringUtil.blank(line) && !abort) {
+			String taxonNameInUse = subParser.getFirstToken();  //taxon Name
+			String originalTaxonName = subParser.getNextToken();
+			int taxonNumber = taxa.whichTaxonNumber(originalTaxonName);
+			if (taxonNumber>=0 && taxonNumber<translationTable.length && MesquiteInteger.isCombinable(taxonNumber))
+				translationTable[taxonNumber] = taxonNameInUse;
+
+			line = parser.getRawNextDarkLine();
+			subParser.setString(line); //sets the string to be used by the parser to "line" and sets the pos to 0
+		}	
+		return true;
+	}
+	
+	/** Given a taxon name "name", this method returns the taxon number this name represents. 
+	This one is based upon the contents of the translation table created from the translation file only. */
+	public int whichTaxonNumberFromTranslationTable(Taxa taxa, String name){
+		if (StringUtil.blank(name) || translationTable==null || translationTable.length!=taxa.getNumTaxa())
+			return -1;
+		for (int it=0; it<translationTable.length; it++){
+			if (name.equalsIgnoreCase(translationTable[it])) {  //we've found the one we want
+				return it;
+			}
+		}
+		return -1;
+	}
+
+	public String getTranslationTable(Taxa taxa){
+		StringBuffer sb = new StringBuffer();
+		if (translationTable==null || translationTable.length!=taxa.getNumTaxa())
+			translationTable = new String[taxa.getNumTaxa()];
+		for (int it=0; it<taxa.getNumTaxa(); it++) {
+			sb.append(getNameToUse(taxa,it)+"\t" + taxa.getTaxonName(it) + StringUtil.lineEnding());
+			translationTable[it]=getNameToUse(taxa,it);
+		}
+		return sb.toString();
+	}
+	public int whichTaxonNumberDefault(Taxa taxa, String name){
+		if (StringUtil.notEmpty(name) && name.length()>=2) {
+			if (name.charAt(0)=='t' || name.charAt(0)=='T') {
+				String s = name.substring(1);
+				return MesquiteInteger.fromString(s);
+			}
+		}
+		return -1;
+	}
+	public int whichTaxonNumber(Taxa taxa, String name){
+		if (StringUtil.blank(name))
+			return -1;
+		if (translationTable==null || translationTable.length!=taxa.getNumTaxa())
+			return whichTaxonNumberDefault(taxa, name);
+		
+		return whichTaxonNumberFromTranslationTable(taxa, name);
+	}
+
+}
diff --git a/Source/mesquite/lib/SingleLineTextArea.java b/Source/mesquite/lib/SingleLineTextArea.java
new file mode 100644
index 0000000..a21afc6
--- /dev/null
+++ b/Source/mesquite/lib/SingleLineTextArea.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.table.EditorTextField;
+
+/*===============================================*/
+/** a field for text that cannot have line feeds/carriage returns in it.  */
+public class SingleLineTextArea extends TextArea  {
+	KeyAdapterToConsumeKeys kListener;
+	boolean allowReturn;
+	/*.................................................................................................................*/
+	public SingleLineTextArea (String initialString, int numRows, int fieldLength, int scrollVis, boolean allowReturn) {
+		super(initialString,numRows,fieldLength, scrollVis);
+		kListener = new KeyAdapterToConsumeKeys(allowReturn);
+		addKeyListener(kListener);
+		this.allowReturn = allowReturn;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextArea (String initialString, boolean allowReturn) {
+		super(initialString);
+		this.allowReturn = allowReturn;
+	}
+	/*.................................................................................................................*/
+	public String getText () {
+		int count = 0;
+		while (count++<10){
+			try {
+				String s = super.getText();
+				if (s==null)
+					return "";
+				s = StringUtil.removeNewLines(s);
+			        if (StringUtil.blank(s))
+			        	return "";
+			        else
+			        	return s;
+		        }
+		        catch (Exception e){
+		        	//MesquiteMessage.warnProgrammer("Exception in getText of SingleLineTextArea");
+		        }
+	        }
+        	return "";
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/SingleLineTextField.java b/Source/mesquite/lib/SingleLineTextField.java
new file mode 100644
index 0000000..4efa37e
--- /dev/null
+++ b/Source/mesquite/lib/SingleLineTextField.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*===============================================*/
+/** a field for text that cannot have line feeds/carriage returns in it.  */
+public class SingleLineTextField extends TextField  {
+	Label fieldLabel; 
+	boolean preserveBlanks = false;
+	/*.................................................................................................................*/
+	public SingleLineTextField (String initialString, int fieldLength, boolean preserveBlanks) {
+		super(initialString,fieldLength);
+		this.preserveBlanks = preserveBlanks;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField (String initialString, int fieldLength) {
+		super(initialString,fieldLength);
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField (String initialString, boolean preserveBlanks) {
+		super(initialString);
+		this.preserveBlanks = preserveBlanks;
+	}
+	/*.................................................................................................................*/
+	public Label getLabel() {
+		return fieldLabel;
+	}
+	/*.................................................................................................................*/
+	public void setLabel(Label fieldLabel) {
+		this.fieldLabel = fieldLabel;
+	}
+	/*.................................................................................................................*/
+	public void setLabelText(String s) {
+		if (fieldLabel!=null)
+			fieldLabel.setText(s);
+	}
+	/*.................................................................................................................*/
+	public Dimension getPreferredSize() {
+		Dimension d = super.getPreferredSize();
+		d.height +=4;
+		return d;
+	}
+	/*.................................................................................................................*/
+	public SingleLineTextField (String initialString) {
+		super(initialString);
+	}
+	/*.................................................................................................................*/
+	public String getText () {
+		int count = 0;
+		while (count++<10){
+			try {
+				String s = super.getText();
+				if (s==null)
+					return "";
+				s = StringUtil.removeNewLines(s);
+			        if (StringUtil.blank(s)) {
+			        	if (preserveBlanks)
+			        		return s;
+			        	else
+			        	 	return "";
+			        }
+			        else
+			        	return s;
+		        }
+		        catch (Exception e){
+		        	//MesquiteMessage.warnProgrammer("Exception in getText of SingleLineTextField");
+		        }
+	        }
+        	return "";
+	}
+
+}
+
diff --git a/Source/mesquite/lib/SliderWindow.java b/Source/mesquite/lib/SliderWindow.java
new file mode 100644
index 0000000..112e28c
--- /dev/null
+++ b/Source/mesquite/lib/SliderWindow.java
@@ -0,0 +1,197 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+public class SliderWindow extends MesquiteWindow {
+	//TextField tF;
+	Label label;
+	GridBagLayout gridBag;
+	GridBagConstraints constraints;
+	MiniSliderWithText sliderWithText;
+	MesquiteMenuItemSpec minItem, maxItem;
+	boolean allowEstimation=false;
+	static int insetFromWindow = 40;
+	static int minWindowWidth = 200;
+	String title ="Slider";
+	double minValue, maxValue;
+	double minSweetValue, maxSweetValue;
+	Panel contents;
+	public SliderWindow(MesquiteModule module, String title, String name, MesquiteCommand command, double initialValue, double min, double max, double minSweet, double maxSweet) {
+		super(module, true);
+		setPreferredPopoutWidth(300);
+		setWindowSize(minWindowWidth, 100);
+		minItem = module.addMenuItem("Slider Core Minimum...", module.makeCommand("setSweetMin", this));
+		maxItem = module.addMenuItem("Slider Core Maximum...", module.makeCommand("setSweetMax", this));
+		this.title = title;
+		contents = getGraphicsArea();
+		//contents.setLayout(new BorderLayout());
+		gridBag = new GridBagLayout();
+		constraints = new GridBagConstraints();
+		constraints.gridx=1;
+		constraints.gridy = 1;
+		constraints.weightx=1;
+		constraints.weighty=1;
+		constraints.ipadx=1;
+		constraints.ipady=1;
+		constraints.insets=new Insets(0,8,0,8);
+		constraints.fill=GridBagConstraints.BOTH;
+		constraints.anchor=GridBagConstraints.CENTER;
+
+		contents.setLayout(gridBag);
+
+		label = new Label();
+		if (!StringUtil.blank(name))
+			label.setText(name);
+		//label.setBackground(Color.blue);
+		contents.add(label,constraints);
+
+		constraints.weighty=2;
+		constraints.gridy = 2;
+		sliderWithText = new MiniSliderWithText(command, initialValue, min, max, minSweet, maxSweet);
+		minValue = min;
+		maxValue = max;
+		minSweetValue = minSweet;
+		maxSweetValue = maxSweet;
+		//sliderWithText.setLayout(new BorderLayout());
+		contents.add(sliderWithText,constraints);
+		//	contents.setBackground(Color.red);
+		//	contents.add("Center", sliderWithText);
+		int toFitWidth = getBounds().width-insetFromWindow;
+		if (toFitWidth > 400)
+			toFitWidth = 400;
+		sliderWithText.setWidth(toFitWidth);
+		sliderWithText.setVisible(true);
+		//setVisible(true);  Windows should not set themselves visible!
+		resetTitle();
+		sliderWithText.getEnterButton().setEnabled(false);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree lists, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(title);
+	}
+
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		if (sliderWithText!= null) {
+			int toFitWidth = getBounds().width-insetFromWindow;
+			if (toFitWidth > 400)
+				toFitWidth = 400;
+			sliderWithText.setWidth(toFitWidth);
+
+		}
+		if (contents != null){
+			contents.invalidate();
+			contents.validate();
+		}
+	}
+	/*.................................................................................................................*/
+	public void useExponentialScale(boolean exp) {
+		sliderWithText.useExponentialScale(exp);
+	}
+	/*.................................................................................................................*/
+	public Dimension getMinimumSize() {
+		return new Dimension(minWindowWidth,getWindowHeight());
+	}
+	/*.................................................................................................................*/
+	public Dimension getMaximumSize() {
+		return new Dimension(super.getMaximumSize().width, getWindowHeight());  // forces height to not change
+	}
+	/*.................................................................................................................*/
+	public void setAllowEstimation(boolean allow) {
+		allowEstimation = allow;
+		if (sliderWithText!=null)
+			sliderWithText.setAllowEstimation(allow);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setSweetMin " + sliderWithText.getMinimumSweetValue());
+		temp.addLine("setSweetMax " + sliderWithText.getMaximumSweetValue());
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the lower boundary for the core area of the slider, over which values change slowly", "[minimum value]", commandName, "setSweetMin")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			double x= MesquiteDouble.fromString(arguments, io);
+			if (!MesquiteDouble.isCombinable(x)){
+				x = MesquiteDouble.queryDouble(MesquiteWindow.windowOfItem(this), "Slider Core Minimum...", "Set lower boundary for slider's core:", sliderWithText.getMinimumSweetValue().getDoubleValue());
+			}
+			if (MesquiteDouble.isCombinable(x)) 
+				if (x>=maxSweetValue)
+					MesquiteMessage.notifyUser("Lower boundary cannot be more than the upper boundary.");
+				else if (x>minValue || minValue==MesquiteDouble.negInfinite){
+					sliderWithText.setMinimumSweetValue(x);
+					sliderWithText.repaint();
+				}
+		}
+		else if (checker.compare(this.getClass(), "Sets the upper boundary for the core area of the slider, over which values change slowly", "[maximum value]", commandName, "setSweetMax")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			double x= MesquiteDouble.fromString(arguments, io);
+			if (!MesquiteDouble.isCombinable(x)){
+				x = MesquiteDouble.queryDouble(MesquiteWindow.windowOfItem(this), "Slider Core Maximum...", "Set upper boundary for slider's core:", sliderWithText.getMaximumSweetValue().getDoubleValue());
+			}
+			if (MesquiteDouble.isCombinable(x)) 
+				if (x<=minSweetValue)
+					MesquiteMessage.notifyUser("Upper boundary cannot be less than the lower boundary.");
+				else if (x<=maxValue || maxValue==MesquiteDouble.infinite){
+					sliderWithText.setMaximumSweetValue(x);
+					sliderWithText.repaint();
+				}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setColor(Color c){
+		setBackground(c);
+		label.setBackground(c);
+		Panel contents = getGraphicsArea();
+		contents.setBackground(c);
+		repaintAll();
+	}
+	public MiniSliderWithText getSlider() {
+		return sliderWithText;
+	}
+	public void setText(String s) {
+		label.setText(s);
+		label.repaint();
+		repaint();
+	}
+	public String getText() {
+		return label.getText();
+	}
+
+	public void dispose(){
+		getOwnerModule().deleteMenuItem(minItem);
+		getOwnerModule().deleteMenuItem(maxItem);
+		super.dispose();
+	}
+	/*=============*/
+	public void buttonHit(String label, Button button) {
+		if (label.equalsIgnoreCase("Close")) {
+			getOwnerModule().windowGoAway(this);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/Snapshot.java b/Source/mesquite/lib/Snapshot.java
new file mode 100644
index 0000000..cbb0da1
--- /dev/null
+++ b/Source/mesquite/lib/Snapshot.java
@@ -0,0 +1,302 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+
+/* ======================================================================== */
+/**Used by modules (and sometimes other Commandables) to return commands that would restore the
+module to its current state on file read-in or in other contexts (e.g., cloning a window).  On saving a file, a module (currently Manage Mesquite Blocks)
+recurses through the employee tree, collecting their Snapshots, and using them to compose a Mesquite block
+for a NEXUS file that will return the active modules and windows to their current state.*/
+public class Snapshot {
+	public static final int SNAPALL = 0;
+	public static final int SNAPDISPLAYONLY = 1;
+	String[] lines;
+	MesquiteModule[] modules;
+	boolean[] conditional;
+	int numLines = 0;
+	public Snapshot () {
+		lines = new String[10];
+		modules = new MesquiteModule[10];
+		conditional = new boolean[10];
+		for (int i=0; i<10; i++) {
+			lines[i] = null;
+			modules[i] = null;
+			conditional[i]=false;
+		}
+	}
+	
+	/** Add the given command to the list of commands.  This command should be one that hires an employee, and the current
+	module that would represent that hiring should be passed.  The command passed is only the first token (command name),
+	not the entire command.  Thus addHiringLine("setTreeDrawer", drawTreeTask) would compose a command of the sort
+	"setTreeDrawer 'Arc Tree';".
+	<p>This allows the module saving the Nexus block to
+	insert immediately afterward the tell It... endTell block of commands that refer to that employee.  (this is
+	important to avoid ambiguity of a getEmployee command that can result if more than one employee has the
+	same name.  By placing the tell block immediately afterward, that hired employee will get the commands
+	appropriate to just it. */
+	public void addLine(String command, MesquiteModule module) {
+		if (numLines>=lines.length)
+			upgrade();
+		lines[numLines] = command;
+		modules[numLines] = module;
+		numLines++;
+	}
+	/** Add command if there is any snapshot from module*/
+	public void addLineIfAnythingToTell(String command, MesquiteModule module) {
+		if (numLines>=lines.length)
+			upgrade();
+		lines[numLines] = command;
+		modules[numLines] = module;
+		conditional[numLines] = true;
+		numLines++;
+	}
+	/** suppress commands to module; used by module that doesn't want to rehire employee*/
+	public void suppressCommandsToEmployee(MesquiteModule module) {
+		if (numLines>=lines.length)
+			upgrade();
+		lines[numLines] = null;
+		modules[numLines] = module;
+		numLines++;
+	}
+	/** Add the given command to the list of commands.  The command should be the entire command line EXCEPT the
+	semicolon.*/
+	public void addLine(String commandLine) {
+		if (numLines>=lines.length)
+			upgrade();
+		lines[numLines] = commandLine;
+		modules[numLines] = null;
+		numLines++;
+	}
+	/** Incorporates given Snapshot into current ones, pulling in lines and modules*/
+	public void incorporate(Snapshot snap, boolean addTab){
+		if (snap !=null) {
+			for (int i= 0; i<snap.getNumLines(); i++)
+				if (addTab)
+					addLine("\t" + snap.getCommand(i), snap.getModule(i));
+				else
+					addLine(snap.getCommand(i), snap.getModule(i));
+		}
+	}
+	
+	static final boolean useClassName= true;
+	/** Returns the given command from the list of commands. The line returned is the fully formatted command*/
+	public String getLine(int index) {
+		if (index < lines.length) {
+			if (lines[index]== null)
+				return null;
+			if (modules[index]!=null) {
+				if (useClassName)
+					return  lines[index] + " #" + modules[index].getClass().getName() + ";";
+				else
+					return  lines[index] + " " + StringUtil.tokenize(modules[index].getName()) + ";";//quote
+			}
+			else
+				return lines[index] + ";";
+		}
+		else
+			return "";
+	}
+	/** Returns the given command from the list of commands.*/
+	public String getCommand(int index) {
+		if (index < lines.length) {
+			return lines[index];
+		}
+		else
+			return "";
+	}
+	/** Returns the associated module from the list of commands.*/
+	public MesquiteModule getModule(int index) {
+		if (index < modules.length)
+			return modules[index];
+		else
+			return null;
+	}
+	/** Returns whether the module is associated with some command.*/
+	public boolean modulePresent(MesquiteModule module) {
+		for (int i=0; i<modules.length; i++)
+			if (modules[i] == module)
+				return true;
+		return false;
+	}
+	/** Returns whether the line is conditional on anything to tell*/
+	public boolean getConditional(int index) {
+		if (index < conditional.length)
+			return conditional[index];
+		else
+			return false;
+	}
+	/** Returns the number of lines in the snapshot.*/
+	public int getNumLines() {
+		return numLines;
+	}
+	/** Dumps the snapshot to the system console*/
+	public void dump(){
+			for (int i= 0; i<getNumLines(); i++) {
+				System.out.println(" command: (" + getCommand(i) + ") module : (" + getModule(i) + ")");
+			}
+	}
+	/** allocates more space in arrays for snapshot  */
+	private void upgrade() {
+		int oldNum = lines.length;
+		String[] newLines = new String[oldNum+10];
+		boolean [] newConditional = new boolean[oldNum+10];
+		MesquiteModule[] newModules = new MesquiteModule[oldNum+10];
+		for (int i=0; i<oldNum; i++) {
+			newLines[i] = lines[i];
+			newModules[i] = modules[i];
+			newConditional[i]= conditional[i];
+		}
+		for (int i=oldNum; i<oldNum+10; i++) {
+			newLines[i] = null;
+			newModules[i] = null;
+			newConditional[i]=false;
+		}
+		lines = newLines;
+		modules = newModules;
+		conditional = newConditional;
+	}
+	
+	public String toString(MesquiteFile file, String spacer){
+ 		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i<getNumLines(); i++) {
+				//if conditional then wait to se if anything added
+			if (getLine(i)==null)
+				;
+			else if (getConditional(i) && getModule(i)!=null) {
+				String emp = getSnapshotCommands(getModule(i), file, spacer);
+				if (!StringUtil.blank(emp)) {
+					sb.append(spacer + getLine(i) + StringUtil.lineEnding());
+					sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+					sb.append(emp);
+					sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+				}
+			}
+			else {
+				sb.append(spacer + getLine(i) + StringUtil.lineEnding());
+  				MesquiteModule mb = getModule(i);
+  				if (mb != null) {
+			 		String emp = getSnapshotCommands(mb, file, spacer);
+					if (!StringUtil.blank(emp)) {
+						sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+						sb.append(emp);
+						sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+			 		}
+  				}
+			}
+		}
+		return sb.toString();
+	}
+	public static String getIDSnapshotCommands(FileElementManager module, MesquiteFile file, String spacer) {
+ 		StringBuffer sb = new StringBuffer();
+  		spacer += "\t"; 
+		Snapshot snapshot = module.getIDSnapshot(file);
+		if (snapshot != null) {
+			for (int i = 0; i<snapshot.getNumLines(); i++) {
+					//if conditional then wait to se if anything added
+				if (snapshot.getLine(i)==null)
+					;
+				else if (snapshot.getConditional(i) && snapshot.getModule(i)!=null) {
+				 	String emp = getSnapshotCommands(snapshot.getModule(i), file, spacer);
+					if (!StringUtil.blank(emp)) {
+							sb.append(spacer + snapshot.getLine(i) + StringUtil.lineEnding());
+							sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+							sb.append(emp);
+							sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+				 		}
+				}
+ 				else {
+ 					sb.append(spacer + snapshot.getLine(i) + StringUtil.lineEnding());
+	  				MesquiteModule mb = snapshot.getModule(i);
+	  				if (mb != null) {
+				 		String emp = getSnapshotCommands(mb, file, spacer);
+						if (!StringUtil.blank(emp)) {
+							sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+							sb.append(emp);
+							sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+				 		}
+	  				}
+  				}
+			}
+		}
+ 		return sb.toString();
+	}
+
+
+	/** accumulate snapshot (e.g., as for MESQUITE block of NEXUS file) beginning at the passed module, as if
+		writing for the file indicated.  The spacer string is passed to prefix lines with tabs to give an indented organization.
+
+		A problem to be solved are dependencies among modules (especially TreeContexts).  If a snapshot creating a module A needed by module B is written
+		after the snapshot creating module B, then module B on starting up will not find the needed module A.   */
+	public static String getSnapshotCommands(MesquiteModule module, MesquiteFile file, String spacer) {
+
+
+		StringBuffer sb = new StringBuffer();
+		spacer += "\t"; 
+		String previousSpacer = spacer;
+		Snapshot snapshot = module.getSnapshot(file);
+		if (snapshot != null) {
+			for (int i = 0; i<snapshot.getNumLines(); i++) {
+				//if conditional then wait to se if anything added
+				if (snapshot.getLine(i)==null)
+					;
+				else if (snapshot.getConditional(i) && snapshot.getModule(i)!=null) {
+					String emp = getSnapshotCommands(snapshot.getModule(i), file, spacer);
+					if (!StringUtil.blank(emp)) {
+						sb.append(spacer + snapshot.getLine(i) + StringUtil.lineEnding());
+						sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+						sb.append(emp);
+						sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+					}
+				}
+				else {
+					sb.append(spacer + snapshot.getLine(i) + StringUtil.lineEnding());
+					MesquiteModule mb = snapshot.getModule(i);
+					if (mb != null) {
+						String emp = getSnapshotCommands(mb, file, spacer);
+						if (!StringUtil.blank(emp)) {
+							sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+							sb.append(emp);
+							sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+						}
+					}
+				}
+			}
+			//deal with all employees not dealt with in snapshot
+			spacer = previousSpacer;
+
+			for (int i = 0; i< module.getNumberOfEmployees(); i++) {
+				MesquiteModule mb = (MesquiteModule)module.getEmployeeVector().elementAt(i);
+				if (!snapshot.modulePresent(mb) && (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL || mb.satisfiesSnapshotMode())) {  //employee not covered in snapshot
+					String emp = getSnapshotCommands(mb, file, spacer);
+					if (!StringUtil.blank(emp)) {
+						sb.append(spacer + "getEmployee " + StringUtil.tokenize(module.getEmployeeReference(mb)) + ";" + StringUtil.lineEnding());//quote
+						sb.append(spacer + "tell It;" + StringUtil.lineEnding());
+						sb.append(emp);
+						sb.append(spacer + "endTell;" + StringUtil.lineEnding());
+					}
+				}
+			}
+		}
+		return sb.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/SpecialListName.java b/Source/mesquite/lib/SpecialListName.java
new file mode 100644
index 0000000..fa48a39
--- /dev/null
+++ b/Source/mesquite/lib/SpecialListName.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is has a special list name method, to prefered over getName 
+in List dialogs.  This was put in place primarily for those classes whose getName method has some special use
+or is dictated by Java (e.g., Thread has final getName() method which therefore prevent our use of names
+for threads)*/
+public interface SpecialListName extends Listable {
+ 	public String getListName();
+}
+
diff --git a/Source/mesquite/lib/SpecsSet.java b/Source/mesquite/lib/SpecsSet.java
new file mode 100644
index 0000000..6bc16a3
--- /dev/null
+++ b/Source/mesquite/lib/SpecsSet.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+/* ======================================================================== */
+/** DOCUMENT.*/
+public abstract class SpecsSet extends FileElement {	
+	//protected int numParts;
+	public static long totalCreated = 0;
+	private String nexusBlockStored = null;
+	AssociableWithSpecs parent = null;
+	
+	public SpecsSet (String name, int numParts) {
+		this.name = name;
+		this.numParts = numParts;
+		totalCreated++;
+	}
+	public SpecsSet (int numParts) {
+		this.numParts = numParts;
+		totalCreated++;
+	}
+	public abstract String getTypeName();
+	public abstract SpecsSet cloneSpecsSet();
+	public abstract SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts);
+	public void setNexusBlockStored(String s){
+		if (s==null)
+			nexusBlockStored = null;
+		else
+			nexusBlockStored = new String(s);
+	}
+	public String toHTMLStringDescription(){
+		return "<li>" + getName() + "<ul>" + super.toHTMLStringDescription() + "</ul></li>";
+	}
+	public String getNexusBlockStored(){
+		return nexusBlockStored;
+	}
+	public void setParent(AssociableWithSpecs aws){
+ 		this.parent = aws;
+	}
+	public AssociableWithSpecs getParent(){
+ 		return parent;
+	}
+	public void setChangedFromCloned(boolean ch){
+ 		setDirty(true);
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfParts(){
+		return numParts;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Sets the value for part "part" to be the same as that at part "otherPart" in the incoming specsSet*/
+	public abstract void equalizeSpecs(SpecsSet other, int otherPart, int part);
+ 	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public abstract boolean addParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Delete parts specified  */
+	public abstract boolean deleteParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Move num parts starting at first, to just after parts justAfter  */
+	public abstract boolean moveParts(int starting, int num, int justAfter);
+	/*----*/
+	
+	public abstract String toString(int part);
+}
+
diff --git a/Source/mesquite/lib/SpecsSetVector.java b/Source/mesquite/lib/SpecsSetVector.java
new file mode 100644
index 0000000..49cd22a
--- /dev/null
+++ b/Source/mesquite/lib/SpecsSetVector.java
@@ -0,0 +1,108 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.Vector;
+
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules
+/* ======================================================================== */
+/** Set of sets, e.g. all of the model sets or weight sets associated with a data matrix.  Thus, all of the model sets are housed in
+one SpecsSetVector.  All of the weight sets are housed in another, and so on.  Each of these SpecsSetVectors is housed
+in the Vector specsVectors of CharacterData.  The different vectors are distinguished by a name associated with them.*/
+public class SpecsSetVector extends ListableVector  {
+	SpecsSet current;
+	Class type;
+	String typeName;
+	public SpecsSetVector  (String typeName) {
+		super();
+		this.typeName = typeName;
+	}
+	public String getTypeName(){
+		return typeName;
+	}
+	public int getNumSpecsSets() {  
+		return size();
+	}
+	public SpecsSet getSpecsSet(int i){
+		if (i>=0 && i<size())
+			return (SpecsSet)elementAt(i);
+		return null;
+	}
+	public void doom(){
+		doomed = true;
+	  		for (int i=0; i<size(); i++) {
+	  			SpecsSet s = (SpecsSet)elementAt(i);
+	  			if (s!=null)
+	  				s.doom();
+	  		}
+  		
+  		super.doom();
+	}
+	
+	public SpecsSet getCurrentSpecsSet(){
+		return current;
+	}
+	public void loadSpecsSetToCurrent(int index){
+		if (index>=0 && index<size())
+			setCurrentSpecsSet((SpecsSet)elementAt(index));
+	}
+	public void setCurrentSpecsSet(SpecsSet specsSet){
+		current = specsSet;
+	}
+	public SpecsSet storeCurrentSpecsSet(){
+		if (current == null)
+			return null;
+		SpecsSet c = current.cloneSpecsSet();
+		c.setParent(current.getParent());
+		c.setProject(current.getProject());
+		addSpecSet(c);
+		return c;
+	}
+	public void replaceStoredSpecsSet(SpecsSet oldOne, SpecsSet replacement){
+		if (replacement ==null)
+			return;
+		SpecsSet clone = replacement.cloneSpecsSet();
+		String name = replacement.getName();
+		clone.setName(oldOne.getName());
+		replaceElement(oldOne, clone, true);
+	}
+	/**returns name of item stored; e.g. "Parsimony Model" ,  "Weight", "Inclusion", "Selection"
+	public String getName() {  
+		return name;
+	}
+	public void setName(String name){
+		this.name = name;
+	}
+	*/
+	/**returns type of item stored; e.g. ParsimonyModelSet.class, WeightSet.class*/
+	public Class getType() {  
+		return type;
+	}
+	public void setType(Class type){
+		this.type = type;
+	}
+	
+	/** Add specs set to vector */
+	public void addSpecSet(Listable specsSet){
+		addElement(specsSet, true);
+	}
+	/** remove specs set from vector */
+	public void removeSpecSet(Listable specsSet){ //if current, change current
+		removeElement(specsSet, true);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/StringArray.java b/Source/mesquite/lib/StringArray.java
new file mode 100644
index 0000000..256f071
--- /dev/null
+++ b/Source/mesquite/lib/StringArray.java
@@ -0,0 +1,494 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+/* ======================================================================== */
+public class StringArray implements StringLister, Listable {
+	String[] values;
+	int maxFilled = -1;
+	NameReference name=null;
+	public StringArray(int num){	
+		values = new String[num];
+		for (int i=0; i<num; i++)
+			values[i] =  null;
+	}
+	/*...........................................................*/
+	public String[] getStrings(){
+		return values;
+	}
+	/*...........................................................*/
+	public String[] getFilledStrings(){
+		int count=0;
+		for (int i=0; i<getFilledSize(); i++)
+			if (values[i]!=null)
+				count++;
+		String[] strings = new String[count];
+		count=0;
+		for (int i=0; i<getFilledSize(); i++)
+			if (values[i]!=null) {
+				strings[count] = values[i];
+				count++;
+			}
+		return strings;
+	}
+	/*...........................................................*/
+	public static void sort(String[] array){
+		if (array==null || array.length<=1)
+			return;
+		MesquiteCollator coll = new MesquiteCollator();
+		for (int i=1; i<array.length; i++) {
+			for (int j= i-1; j>=0 && coll.compare(array[j],array[j+1])>0; j--) {
+				String temp = array[j];
+				array[j] = array[j+1];
+				array[j+1]=temp;
+			}
+		}
+		
+	}
+	/*...........................................................*/
+	public String getValue(int index){
+		if (index <0 || index >= values.length)
+			return null;
+		else
+			return values[index];
+	}
+	/*...........................................................*/
+	public void setValue(int index, String value) {
+		if (index >=0 && index < values.length) {
+			values[index] = value;
+			if (index>maxFilled)
+				maxFilled = index;
+		}
+	}
+	/*...........................................................*/
+	public void deassignArray(){
+		for (int i=0; i<values.length; i++)
+			values[i] =  null;
+		maxFilled = -1;
+	}
+
+	/*...........................................................*/
+	public static int lastIndexOfIgnoreCase(String[]s, String match){
+		if (match == null || s==null)
+			return -1;
+		for (int i=s.length-1; i>=0; i--)
+			if (match.equalsIgnoreCase(s[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int lastIndexOf(String[]s, String match){
+		if (match == null || s==null)
+			return -1;
+		for (int i=s.length-1; i>=0; i--)
+			if (match.equals(s[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOfIgnoreCase(String[]s, String match){
+		if (match == null || s==null)
+			return -1;
+		for (int i=0; i<s.length; i++)
+			if (match.equalsIgnoreCase(s[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public int indexOfIgnoreCase(String match){
+		if (match == null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (match.equalsIgnoreCase(values[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(String[]s, String match){
+		if (match == null || s==null)
+			return -1;
+		for (int i=0; i<s.length; i++)
+			if (match.equals(s[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOfIgnoreCase(java.util.Vector v, String match){
+		if (match == null)
+			return -1;
+		for (int i=0; i<v.size(); i++){
+			String string = (String)v.elementAt(i);
+			if (match.equalsIgnoreCase(string))
+				return i;
+		}
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOf(java.util.Vector v, String match){
+		if (match == null)
+			return -1;
+		for (int i=0; i<v.size(); i++){
+			String string = (String)v.elementAt(i);
+			if (match.equals(string))
+				return i;
+		}
+		return -1;
+	}
+	/*...........................................................*/
+	public static int indexOfIgnoreCase(String[][] s, int firstIndex, String match){
+		if (match == null || s==null || s.length == 0 || firstIndex>=s.length || firstIndex<0)
+			return -1;
+		for (int i=0; i<s[firstIndex].length; i++)
+			if (match.equalsIgnoreCase(s[firstIndex][i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public int indexOf(String match){
+		if (match == null)
+			return -1;
+		for (int i=0; i<values.length; i++)
+			if (match.equals(values[i]))
+				return i;
+		return -1;
+	}
+	/*...........................................................*/
+	public boolean exists(String s){
+		return indexOf(s)>=0;
+	}
+
+	/*...........................................................*/
+	public boolean fillNextUnassigned(String v){
+		for (int i=0; i<values.length; i++)
+			if (values[i]== null) {
+				values[i] = v;
+				if (i>maxFilled)
+					maxFilled = i;
+				return true;
+			}
+		return false;
+	}
+	/*...........................................................*/
+	public boolean addAndFillNextUnassigned(String v){
+		if (!fillNextUnassigned(v)) {
+			resetSize(getSize()+10);
+			return fillNextUnassigned(v);
+		}
+		return true;
+	}
+	/*...........................................................*/
+	public int getSize() {
+		return values.length;
+	}
+	/*...........................................................*/
+	public void addParts(int starting, int num) {
+		values=addParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static String[] addParts(String[] d, int starting, int num) {
+		if (num<=0 || d == null)
+			return d;
+		if (starting<0) 
+			starting = -1;
+		if (starting>d.length) 
+			starting = d.length-1;
+		
+		int newNumParts = d.length+num;
+		String[] newValues = new String[newNumParts];
+		
+		for (int i=0; i<= starting; i++) {
+			newValues[i] = d[i];
+		}
+		for (int i=0; i<num ; i++) {
+			newValues[starting + i + 1] = null;
+		}
+		for (int i=0; i<d.length-starting-1; i++) {
+			newValues[i +starting+num+1] = d[starting + i+1];
+		}
+		return newValues;
+	}
+	/*...........................................................*/
+	public static String[] addToStart(String[] d, String s) {
+		String[] sa = addParts(d,-1,1);
+		sa[0]=s;
+		return sa;
+	}
+	/*...........................................................*/
+	public void deleteParts(int starting, int num) {
+		if (num<=0 || starting<0 || starting>=getSize())
+			return;
+		values = deleteParts(values, starting, num);
+	}
+	/*...........................................................*/
+	public static String[] deleteParts(String[] d, int starting, int num) {
+		if (d==null || num<=0 || starting<0 || starting>=d.length)
+			return d;
+		if (num+starting>d.length)
+			num = d.length-starting;
+
+		int newNum =d.length - num;
+		String[] newValues = new String[newNum];
+		for (int i=0; i<starting; i++)
+			newValues[i]=d[i];
+		for (int i=starting+num; i<d.length; i++)
+			newValues[i-num]=d[i];
+		return newValues;
+	}
+	/*...........................................................*/
+	public void moveParts(int starting, int num, int justAfter) {
+		moveParts(values, starting, num, justAfter);
+	}
+	/*...........................................................*/
+	public static void swapParts(String[] d, int first, int second) {
+		if (d == null || first<0 || first>=d.length || second<0 || second>=d.length) 
+			return;
+		String temp = d[first];
+		d[first] = d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void swapCell(String[][] d, int first, int second, int k) {
+		if (k<0)
+			return;
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		if (d[first] == null || k>= d[first].length || d[second] == null || k>= d[second].length)
+			return;
+		String temp = d[first][k];
+		d[first][k]=d[second][k];
+		d[second][k] = temp;
+	}
+	/*...........................................................*/
+	public static void swapColumns(String[][] d, int first, int second) {
+		if (first<0 || d==null || first>=d.length || second<0 || second>=d.length) 
+			return;
+		String[] temp = d[first];
+		d[first]=d[second];
+		d[second] = temp;
+	}
+	/*...........................................................*/
+	public static void moveParts(String[] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		String[] newValues = new String[d.length];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	/** assumes String[columns][rows] */
+	public static void moveRows(String[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || d.length == 0)
+			return;
+		int numRows = d[0].length;
+		if (starting>=numRows || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=numRows)
+			justAfter = numRows-1;
+		if (justAfter<0)
+			justAfter = -1;
+		String[] newValues = new String[numRows];
+		for (int column = 0; column<d.length; column++){
+			if (starting>justAfter){
+				int count =0;
+				for (int i=0; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting+num; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			else {
+				int count =0;
+				for (int i=0; i<=starting-1; i++)
+					newValues[count++]=d[column][i];
+				
+				for (int i=starting+num; i<=justAfter; i++)
+					newValues[count++]=d[column][i];
+				for (int i=starting; i<=starting+num-1; i++)
+					newValues[count++]=d[column][i];
+				for (int i=justAfter+1; i<numRows; i++)
+					newValues[count++]=d[column][i];
+			}
+			for (int i=0; i<numRows; i++)
+				d[column][i]=newValues[i];
+		}
+	}
+	public static String[][] addRows(String[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		for (int column = 0; column<d.length; column++){
+			d[column]=addParts(d[column], starting, num);
+		}
+		return d;
+	}
+	public static String[][] deleteRows(String[][] d, int starting, int num) {
+		if (num==0 || d == null || d.length == 0)
+			return d;
+		for (int column = 0; column<d.length; column++){
+			d[column]=deleteParts(d[column], starting, num);
+		}
+		return d;
+	}
+	/*...........................................................*/
+	public static void moveColumns(String[][] d, int starting, int num, int justAfter) {
+		if (num<=0 || d==null || starting>=d.length || (justAfter>=starting && justAfter<=starting+num-1)) //starting???
+			return;
+		if (justAfter>=d.length)
+			justAfter = d.length-1;
+		if (justAfter<0)
+			justAfter = -1;
+		String[][] newValues = new String[d.length][];
+		if (starting>justAfter){
+			int count =0;
+			for (int i=0; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		else {   // (starting<=justAfter)
+			int count =0;
+			for (int i=0; i<=starting-1; i++)
+				newValues[count++]=d[i];
+			for (int i=starting+num; i<=justAfter; i++)
+				newValues[count++]=d[i];
+			for (int i=starting; i<=starting+num-1; i++)
+				newValues[count++]=d[i];
+			for (int i=justAfter+1; i<d.length; i++)
+				newValues[count++]=d[i];
+		}
+		for (int i=0; i<d.length; i++)
+			d[i]=newValues[i];
+	}
+	/*...........................................................*/
+	public void resetSize(int newNum) {
+		if (newNum == getSize())
+			return;
+		String[] newValues = new String[newNum];
+		for (int i=0; i<getSize() && i<newNum; i++)
+			newValues[i]=values[i];
+		values=newValues;
+	}
+	/*...........................................................*/
+	public int getFilledSize() {
+		return maxFilled+1;
+	}
+	/*...........................................................*/
+	public String getName(){
+		if (name!=null)
+			return name.getValue();
+		else
+			return "";
+	}
+	/*...........................................................*/
+	public void setName(String nr){
+		name = NameReference.getNameReference(nr);
+	}
+		/*...........................................................*/
+	public void setNameReference(NameReference nr){
+		name = nr;
+	}
+	/*...........................................................*/
+	public NameReference getNameReference(){
+		return name;
+	}
+	/*...........................................................*/
+	public static boolean equals(String[] s, String[] t){
+		if (s==null && t == null)
+			return true;
+		if (s==null || t == null)
+			return false;
+		if (s.length != t.length)
+			return false;
+		for (int i=0; i<s.length; i++) {
+			if (s[i] != null && t[i]!=null) {
+				if (!s[i].equals(t[i]))
+					return false;
+			}
+			else if (s[i]!=t[i])
+				return false;
+		}
+		return true;
+	}
+	/*...........................................................*/
+	public String toString(){
+		if (values==null)
+			return "null";
+		String r = "";
+		for (int i=0; i<values.length; i++)
+			r += "[" +values[i] + "] ";
+		return r;
+	}
+	/*...........................................................*/
+	public static String toString(String[]s){
+		if (s==null)
+			return "null";
+		String r = "";
+		for (int i=0; i<s.length; i++)
+			r += "[" +s[i] + "] ";
+		return r;
+	}
+	/*...........................................................*/
+	public static String toString(String[][] s){
+		if (s==null)
+			return "null";
+		String r = "";
+		for (int i=0; i<s.length; i++) {
+			r += "[";
+			for (int j=0;j<s[i].length; j++)
+				r += "(" +s[i][j] + ") ";
+			r += "]\n";
+		}
+		return r;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/StringInABox.java b/Source/mesquite/lib/StringInABox.java
new file mode 100644
index 0000000..7aaca20
--- /dev/null
+++ b/Source/mesquite/lib/StringInABox.java
@@ -0,0 +1,561 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+
+
+/* ======================================================================== */
+/** A utility class to draw a string in a box, useful for printing and screen display.  A bit like TextArea, but
+without rectangle around it and with multipage printing facility.  The string, font, and width are given to it, 
+and it calculates a breakdown of the string into an array of strings each of which will fit in the allotted
+width, and also calcualted is how high of a rectangle is needed to accommodate all of the text.  */
+public class StringInABox {
+	Font font = null;
+	StringBuffer sb = null;
+	int width = 0;
+	int maxWidth = -1;
+	int maxWidthMunched = -1;
+	int height = 0;
+	static final char linebreak = '\n';
+	static int spacesPerTab = 4;
+	static final char space = ' ';
+	int buffer = 2;
+	static final int leftMargin = 0;
+	String[] strings;
+	Color textColor, edgeColor;
+	int linkEnd = -1;
+	int linkStart = -1;
+	Rectangle linkBox = null;
+	/* ----------------------------------------------- */
+	public StringInABox(StringBuffer s, Font f, int w){
+		font = f;
+		width = w;
+		sb = s;
+		munch();
+	}
+	/* ----------------------------------------------- */
+	public StringInABox(String s, Font f, int w){
+		font = f;
+		width = w;
+		if (s==null)
+			s = "";
+		sb = new StringBuffer(s);
+		munch();
+	}
+	/* ----------------------------------------------- */
+	public void setLink(int start, int end){
+		//permits characters start to end to be treated as a link; in blue
+		linkStart = start;
+		linkEnd = end;
+	}
+	public Rectangle getLinkBounds(){  //the box must have been drawn before the bounds are known
+		if (linkEnd < 0 && linkStart<0)
+			return null;
+		return linkBox;
+	}
+	public boolean inLink(int x, int y){  //the box must have been drawn before the bounds are known
+		if (linkEnd < 0 && linkStart<0)
+			return false;
+		if (linkBox == null)
+			return false;
+		return x >= linkBox.x && x <= linkBox.x + linkBox.width && y >= linkBox.y && y <= linkBox.y + linkBox.height;
+	}
+	/* ----------------------------------------------- */
+	public void setBuffer(int b){
+		buffer = b;
+	}
+	public void setStringAndFont(StringBuffer s, Font f){
+		sb = s;
+		font = f;
+		munch();
+	}
+	public void setFont(Font f){
+		if (font==f)
+			return;
+		font = f;
+		munch();
+	}
+	public Font getFont(){
+		return font;
+	}
+	Font storedFont;
+	public void storeFont(){
+		storedFont = font;
+	}
+	public void recallFont(){
+		if (storedFont != null)
+		setFont(storedFont);
+	}
+	public void scaleFont(double scale){
+		if (font == null)
+			return;
+		int size = (int)(font.getSize()*scale);
+		if (size == 0)
+			size = 2;
+		setFont(new Font(font.getName(), font.getStyle(), size));
+	}
+	public void setWidth(int w){
+		if (width==w)
+			return;
+		width = w;
+		munch();
+	}
+	public int getWidth(){
+		return width;
+	}
+	public int getMaxWidthMunched(){
+		if (maxWidthMunched >=0)
+			return maxWidthMunched;
+		return width;
+	}
+	public int getMaxWidthDrawn(){
+		if (maxWidth >=0)
+			return maxWidth;
+		return width;
+	}
+	public void setString(StringBuffer s){
+		sb = s;
+		munch();
+	}
+	public void setString(String s, Graphics g){
+		if (s==null)
+			s = "";
+		sb = new StringBuffer(s);
+		munch(g);
+	}
+	public void setStringAndFontAndWidth(String s, Font f, int w, Graphics g){
+		if (s==null)
+			s = "";
+		font = f;
+		width = w;
+		sb = new StringBuffer(s);
+		munch(g);
+	}
+	public void setString(String s){
+		if (s==null)
+			s = "";
+		sb = new StringBuffer(s);
+		munch();
+	}
+	public String getString(){
+		if (sb!=null)
+			return sb.toString();
+		else
+			return null;
+	}
+	/* ----------------------------------------------- */
+	/**Prints the passed string (automatically prints with full page width and on
+	multiple pages as needed.  \n are used as linebreads.  Text is wrapped as necessary to
+	fit onto page*/
+	public static void printText(Frame f, String s, Font font) {
+		if (s == null || f==null || font==null)
+			return;
+		MainThread.incrementSuppressWaitWindow();
+		PrintJob pjob = f.getToolkit().getPrintJob(f, "Print?", null);
+		if (pjob != null) {
+			Dimension dim = pjob.getPageDimension();
+			StringBuffer sB = new StringBuffer(s);
+			StringInABox sBox = new StringInABox(sB,font, dim.width);  //TODO: should set font here!!!
+			int tot =  sBox.getHeight();
+			int lastY = 0;
+			boolean done = false; 
+			while (lastY<tot && !done){
+				int r = sBox.getRemainingHeight(lastY);
+				if (r> dim.height)
+					r=dim.height;
+				Graphics pg = pjob.getGraphics();
+				if (pg!=null) {
+					lastY = sBox.draw(pg, 0, 0, lastY, r);  
+					pg.dispose();
+				}
+				else done = true;
+			}
+		}
+		pjob.end();
+		MainThread.decrementSuppressWaitWindow();
+	}
+	/* ----------------------------------------------- */
+	/**Prints the passed string using given PrintJob (automatically prints with full page width and on
+	multiple pages as needed.  \n are used as linebreads.  Text is wrapped as necessary to
+	fit onto page*/
+	public static void printText(PrintJob pjob, String s, Font font) {
+		if (s == null || font==null || pjob==null)
+			return;
+		Dimension dim = pjob.getPageDimension();
+		StringBuffer sB = new StringBuffer(s);
+		StringInABox sBox = new StringInABox(sB, font, dim.width);  
+		int tot =  sBox.getHeight();
+		int lastY = 0;
+		boolean done = false; 
+		while (lastY<tot && !done){
+			int r = sBox.getRemainingHeight(lastY);
+			if (r> dim.height)
+				r=dim.height;
+			Graphics pg = pjob.getGraphics();
+			if (pg!=null) {
+				lastY = sBox.draw(pg, 0, 0, lastY, r);  
+				pg.dispose();
+			}
+			else done = true;
+		}
+	}
+	/* ----------------------------------------------- */
+	private boolean lineEnd(char c){
+		return (c=='\n' || c=='\r');
+	}
+	/* ----------------------------------------------- */
+	private boolean isPunc(char c){
+		return (c=='\n' || c=='\r' || c==',' || c==';' || c==':' || c==')' || c==']'|| c=='}'|| c=='!'|| c=='?'|| c=='-');
+	}
+	/* ----------------------------------------------- */
+	/* takes stringBuffer and inserts line breaks as needed to satisfy available width, does some other processing
+	(e.g., tabs to spaces, \r to \n), then converts to an array of strings*/
+	private void munch(){
+		try {
+		munch(null);
+		}
+		catch (Exception e){
+			e.printStackTrace();
+		}
+	}
+	private char getCharAt(StringBuffer sb, int i){
+		try {
+			if (i < sb.length())
+			return sb.charAt(i);
+		}
+		catch (StringIndexOutOfBoundsException e){
+		}
+		return 0;
+	}
+	/* ----------------------------------------------- */
+	/* takes stringBuffer and inserts line breaks as needed to satisfy available width, does some other processing
+	(e.g., tabs to spaces, \r to \n), then converts to an array of strings*/
+	private synchronized void munch(Graphics g){
+		if (sb!=null && font!=null && width>0 && sb.length()>0){
+			StringBuffer sMunched = new StringBuffer(sb.length());
+
+			FontMetrics fm = null;
+			if (g != null){
+				Font prevFont = g.getFont();
+				g.setFont(font);
+				fm  = g.getFontMetrics();
+				g.setFont(prevFont);
+
+			}
+			else fm =Toolkit.getDefaultToolkit().getFontMetrics(font);
+			int pos = 0;
+			maxWidthMunched = 0;
+			int i=0;
+			long count = 0;
+			do {
+				count++;
+				if (count>100000) {
+					//MesquiteMessage.warnProgrammer("munch in StringInABox exceeded 100000 iterations (i " + i + " sb.length() " + sb.length() + ") ");
+					return;
+				}
+				char nextChar = 0;
+					nextChar = getCharAt(sb, i);
+				if (lineEnd(nextChar)) {
+					sMunched.append(linebreak);
+					pos = 0;
+					i++;
+				}
+				else if (nextChar == '\t'){  //tab
+					for (int j = 1; j<spacesPerTab && pos<width; j++) {
+						sMunched.append(space);
+						pos += fm.charWidth(space);
+					}
+					if (pos > maxWidthMunched)  //this may be off by one character's worth of width if over
+						maxWidthMunched = pos;
+					if (pos>width) {
+						sMunched.append(linebreak);
+						pos = 0;
+					}
+					i++;
+				}
+				else if (nextChar == space) {
+					sMunched.append(space);
+					pos += fm.charWidth(space);
+					if (pos > maxWidthMunched)  //this may be off by one character's worth of width if over
+						maxWidthMunched = pos;
+					if (pos>width) {
+						sMunched.append(linebreak);
+						pos = 0;
+					}
+					i++;
+				}
+				else if (StringUtil.punctuation(nextChar, null)) {
+					sMunched.append(nextChar);
+					pos += fm.charWidth(nextChar);
+					if (pos > maxWidthMunched)  //this may be off by one character's worth of width if over
+						maxWidthMunched = pos;
+					if (pos>width) {
+						sMunched.append(linebreak);
+						pos = 0;
+					}
+					i++;
+				}
+				else {
+					int wordLength = 0;
+					int j = i;
+					char c =(char)0;;
+						c = getCharAt(sb, j);
+					while (j<sb.length() && !StringUtil.punctuation(c, null) && !StringUtil.whitespace(c, null)) { //measuring next word
+						wordLength +=fm.charWidth(c);
+						j++;
+							c = getCharAt(sb, j);
+					}
+					if ((wordLength>=width && pos==0) || pos+wordLength<width){ 
+						//single word wider than width; break into pieces;  or, will fit and og as far as can
+							c = getCharAt(sb, i);
+						while (i<sb.length() && !StringUtil.punctuation(c, null) && !StringUtil.whitespace(c, null) && pos<width) {
+							sMunched.append(c);
+							pos += fm.charWidth(c);
+							i++;
+								c = getCharAt(sb, i);
+						}
+						if (pos > maxWidthMunched)  //this may be off by one character's worth of width if over
+							maxWidthMunched = pos;
+					}
+					else {
+						sMunched.append(linebreak);
+						pos = 0;
+					}
+				}
+			} while(i<sb.length());
+
+
+			StringTokenizer tokenizer = new StringTokenizer(sMunched.toString(), ""+ linebreak);  
+			storeInStrings(tokenizer);
+		}
+	}
+	/* ----------------------------------------------- */
+	private void storeInStrings(StringTokenizer tokenizer){
+		strings = new String[tokenizer.countTokens()];
+		int i=0;
+		while (tokenizer.hasMoreTokens() && i<strings.length) {
+			strings[i] = tokenizer.nextToken();
+			i++;
+		}	
+	}
+	/* To use StringUtil.highlightString (only works for horizontal text)*/
+	public void setColors(Color textColor, Color edgeColor){
+		this.textColor = textColor;
+		this.edgeColor = edgeColor;
+	}
+	/* ----------------------------------------------- */
+	/** draw text based at x, y, starting at local position y in box for height h*/
+	public int getNextPageTop(int yPos, int h){
+
+		if (sb!=null && strings!=null && font!=null && width>0){
+			int lastDrawnYPos = yPos;
+			FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+			int increment = fm.getMaxAscent() + fm.getMaxDescent() + buffer;
+			int accumulatedHeight = increment;
+			int i = 0;
+			while (i<strings.length && accumulatedHeight<yPos) {
+				accumulatedHeight += increment;
+				i++;
+			}
+			int heightOnThisPage = increment;
+			while (i<strings.length && heightOnThisPage<h) {
+				lastDrawnYPos = heightOnThisPage + accumulatedHeight;
+				heightOnThisPage += increment;
+				i++;
+			}	
+			return lastDrawnYPos;
+		}
+		return 0;
+	}
+	/* ----------------------------------------------- */
+	TextRotator textRotator;
+	/** draw text based at x, y, starting at local position y in box for height h*/
+	public int draw(Graphics g, int x, int y, int yPos, int h, Component component, boolean drawHorizontal){
+		return draw(g, x, y, yPos, h, component, drawHorizontal, false);
+	}
+	public int draw(Graphics g, int x, int y, int yPos, int h, Component component, boolean drawHorizontal, boolean tightVertical){
+		try {
+			if (sb!=null && sb.length()>0 && strings!=null && font!=null && width>0){
+				int lastDrawnYPos = yPos;
+				Font prevFont = g.getFont();
+				Color prevColor = g.getColor();
+				g.setFont(font); //use g's font if font is null
+				FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+				int increment = fm.getMaxAscent() + fm.getMaxDescent() + buffer;
+				int accumulatedHeight = increment;
+				int i = 0;
+				while (i<strings.length && accumulatedHeight<yPos) {
+					accumulatedHeight += increment;
+					i++;
+				}
+				if (!drawHorizontal && textRotator==null)
+					textRotator = new TextRotator(MesquiteInteger.maximum(10, strings.length));
+				int heightOnThisPage = increment;
+				if (tightVertical)
+					increment -= 4;
+				maxWidth = -1;
+				int charCount = 0;
+				linkBox = null;
+				while (i<strings.length && heightOnThisPage<h) {
+					if (strings[i] != null){
+						if (drawHorizontal) {
+							if (textColor !=null && edgeColor!=null) {
+								StringUtil.highlightString(g, strings[i], x, y + heightOnThisPage, textColor, edgeColor);
+							}
+							else {
+								boolean drawn = false;
+								
+								//LINKS=====
+								if (linkStart >= 0 && linkEnd>=0){
+									int localLength = strings[i].length();
+									int localLinkStart = linkStart - charCount;
+									int localLinkEnd = linkEnd - charCount;
+									if (localLinkStart<localLength && localLinkEnd >= 0){
+
+										if (localLinkStart<0)
+											localLinkStart = 0;
+										if (localLinkEnd>localLength)
+											localLinkEnd = localLength;
+										int prelinkWidth = 0;
+										int linkWidth = 0;
+										String prelink = strings[i].substring(0, localLinkStart);
+										if (prelink == null)
+											prelink = "";
+										else
+											prelinkWidth =  fm.stringWidth(prelink);
+										String link = strings[i].substring(localLinkStart, localLinkEnd);
+										if (link == null)
+											link = "";
+										else
+											linkWidth =  fm.stringWidth(link);
+										String remnant = strings[i].substring(localLinkEnd, strings[i].length());
+										if (remnant == null)
+											remnant = "";
+										g.drawString(prelink, x, y + heightOnThisPage);  
+										Color c = g.getColor();
+										g.setColor(Color.blue);
+										g.drawString(link,  x + prelinkWidth, y + heightOnThisPage);  
+										g.drawLine(x + prelinkWidth, y + heightOnThisPage+1, x + prelinkWidth + linkWidth, y + heightOnThisPage+1);  
+										if (linkBox == null) {
+											linkBox = new Rectangle(x + prelinkWidth, y + heightOnThisPage+1- increment, linkWidth, increment);
+										}
+										else {
+											if (linkBox.x + linkBox.width < x + prelinkWidth + linkWidth)
+												linkBox.width = x + prelinkWidth + linkWidth - linkBox.x;
+											if (linkBox.x> x + prelinkWidth)
+												linkBox.x = x + prelinkWidth;
+											if (linkBox.y + linkBox.height < y + heightOnThisPage+1)
+												linkBox.height = y + heightOnThisPage+1 - linkBox.y;
+											if (linkBox.y> y + heightOnThisPage+1- increment)
+												linkBox.y = y + heightOnThisPage+1- increment;
+										}
+										//g.drawRect(linkBox.x, linkBox.y, linkBox.width, linkBox.height);
+										g.setColor(c);
+										g.drawString(remnant, x + fm.stringWidth(prelink + link), y + heightOnThisPage);  
+										drawn = true;
+									}
+								}
+								//LINKS=====
+								
+								
+								if (!drawn) {
+									g.drawString(strings[i], x, y + heightOnThisPage); 
+								}
+							}
+						}
+						else {
+							g.setColor(textColor);
+							textRotator.assignBackground(edgeColor);
+							textRotator.drawRotatedText(strings[i], i, g, component, x + heightOnThisPage, y);
+						}
+
+						lastDrawnYPos = y + heightOnThisPage + accumulatedHeight;
+						heightOnThisPage += increment;
+						int w = 0;
+						if (i>=0 && i< strings.length && strings[i] != null)
+							w = fm.stringWidth(strings[i]);
+						if (w>maxWidth)
+							maxWidth = w;
+						charCount += strings[i].length();
+					}
+					i++;
+				}	
+				g.setFont(prevFont);
+				g.setColor(prevColor);
+
+				return lastDrawnYPos;
+			}
+		}
+		catch (Exception e){
+			return 0;
+		}
+		return 0;
+	}
+	/* ----------------------------------------------- */
+	/** draw text based at x, y, starting at local position y in box for height h*/
+	public int draw(Graphics g, int x, int y, int yPos, int h){
+		return draw(g,x,y,yPos,h, null, true);
+	}
+	/* ----------------------------------------------- */
+	/** draw text based at x, y*/
+	public int draw(Graphics g, int x, int y){
+		return draw(g, x, y, 0, getHeight());
+	}
+	/* ----------------------------------------------- */
+	/** draw text based at x, y*/
+	public int drawTight(Graphics g, int x, int y){
+		return draw(g,x,y,0,getHeight(), null, true, true);
+	}
+	/* ----------------------------------------------- */
+	/** draw text based at x, y*/
+	public int drawInBox(Graphics g, Color backgroundColor, int x, int y){
+		int h = getHeight();
+		Color c = g.getColor();
+		g.setColor(backgroundColor);
+		g.fillRect(x-8, y, width+12, h+8);
+		if (c!=null) g.setColor(c);
+		g.drawRect(x-8, y, width+11, h+7);
+		return draw(g, x, y, 0, h);
+	}
+	/* ----------------------------------------------- */
+	public int getHeight(){
+		if (strings==null)
+			return 0;
+		FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+		int increment = fm.getMaxAscent() + fm.getMaxDescent() + buffer;
+		return (strings.length) * increment + buffer;	
+	}
+	/* ----------------------------------------------- */
+	public int getRemainingHeight(int usedSoFar){
+		FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+		int increment = fm.getMaxAscent() + fm.getMaxDescent() + buffer;
+		return getHeight() - usedSoFar/increment*increment + increment+ buffer;	
+	}
+	/*.................................................................................................................*/
+	public static void drawStringIfNotBlank(Graphics g, String s, int x, int y){
+		if (g == null || StringUtil.blank(s))
+			return;
+		try {
+			g.drawString(s, x, y);
+		}
+		catch (Exception e){
+		}
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/StringIntegerDialog.java b/Source/mesquite/lib/StringIntegerDialog.java
new file mode 100644
index 0000000..f807936
--- /dev/null
+++ b/Source/mesquite/lib/StringIntegerDialog.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+/** A dialog box to return a string and an integer*/
+public class StringIntegerDialog extends ExtensibleDialog  {
+	SingleLineTextField stringField;
+	IntegerField numberField;
+	MesquiteString string;
+	MesquiteInteger number;
+	int min, max;
+	String report = "";
+	String numberTitle;
+	boolean valuesChecked = false;
+	
+	public StringIntegerDialog (MesquiteWindow parent, String title, String stringTitle, String numberTitle, MesquiteString string, MesquiteInteger number, int min, int max, MesquiteInteger buttonPressed,String helpString, boolean showDialogInConstructor) {
+		super(parent,title,buttonPressed);
+		this.number = number;
+		this.string = string;
+		this.min = min;
+		this.max = max;
+		this.numberTitle = numberTitle;
+		addLabel(stringTitle + ": ", Label.LEFT);
+		stringField = addTextField(this.string.getValue());
+		numberField = addIntegerField(numberTitle + ": ",this.number.getValue(),12);
+		
+		if (helpString!=null)
+			appendToHelpString(helpString);
+			
+		setAutoDispose(false);
+
+		if (showDialogInConstructor) {
+			completeAndShowDialog(true,this);
+				
+			if (!valuesChecked && buttonPressed.getValue()==0)
+				processOK();
+		}
+			
+	}	
+	public StringIntegerDialog (MesquiteWindow parent, String title, String stringTitle, String numberTitle, MesquiteString string, MesquiteInteger number, int min, int max, MesquiteInteger buttonPressed,String helpString) {
+		this(parent,title,stringTitle,numberTitle,string,number,min, max,buttonPressed,helpString,true);
+	}
+	public StringIntegerDialog (MesquiteWindow parent, String title, String stringTitle, String numberTitle, MesquiteString string, MesquiteInteger number,MesquiteInteger buttonPressed,String helpString) {
+		this(parent,title,stringTitle,numberTitle,string,number,MesquiteInteger.unassigned, MesquiteInteger.unassigned,buttonPressed,helpString,true);
+	}
+	/*.................................................................................................................*/
+	 public  boolean checkNumber() {
+	 	int num = getNumber();
+	 	if (!numberField.isValidInteger()) {
+	 		report = "Entry for "+numberTitle+ " is not a valid number";
+	 		return false;
+	 	}
+	 	if (!MesquiteInteger.isCombinable(num))
+	 		return false;
+	 	if (MesquiteInteger.isCombinable(min))
+	 		if (num<min) {
+	 			report = "Entry for "+numberTitle+ " is below the minimum allowed";
+	 			return false;
+	 		}
+	 	if (MesquiteInteger.isCombinable(max))
+	 		if (num>max){
+	 			report = "Entry for "+numberTitle+ " is above the maximum allowed";
+	 			return false;
+	 		}
+	 	return true;
+	 }
+	/*.................................................................................................................*/
+	 public  void setValues() {
+ 		number.setValue(getNumber());
+ 		string.setValue(getString());
+	 }
+	/*.................................................................................................................*/
+	 public  void processOK() {
+		if (checkNumber()) {
+			valuesChecked = true;
+	 		buttonPressed.setValue(0);
+	 		setValues();
+	 		dispose();
+	 	}
+	 	else
+	 		MesquiteMessage.notifyUser(report);
+	 }
+	/*.................................................................................................................*/
+	 public  String getString() {
+	 	return stringField.getText();
+	 }
+	/*.................................................................................................................*/
+	 public  int getNumber() {
+	 	return numberField.getValue();
+	 }
+	/*.................................................................................................................*/
+	public void keyReleased(KeyEvent e){
+		if (e.getKeyCode() == 10) {
+			processOK();
+		}
+	}
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	if   (defaultOKLabel.equals(e.getActionCommand())) {
+			processOK();
+		}
+		else if  (defaultCancelLabel.equals(e.getActionCommand())) {
+			buttonPressed.setValue(1);
+			dispose();
+		}
+		else
+			super.actionPerformed(e);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/StringIntegerListDlog.java b/Source/mesquite/lib/StringIntegerListDlog.java
new file mode 100644
index 0000000..fe0d000
--- /dev/null
+++ b/Source/mesquite/lib/StringIntegerListDlog.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+/** A dialog box to return a string and an integer and an item selected from a list.*/
+public class StringIntegerListDlog extends StringIntegerDialog   {
+	DoubleClickList list;
+	MesquiteString listString;
+	String listTitle;
+	boolean chooseFromList=true;
+	String[] names;
+	MesquiteInteger selected;
+	boolean exactlyOneSelected = true;
+	boolean acceptsDoubleClicks = false;
+	
+	public StringIntegerListDlog (MesquiteWindow parent, String title, String stringTitle, String numberTitle,String listTitle,String[] names, boolean exactlyOneSelected, MesquiteString string, MesquiteInteger number, MesquiteString listString, int min, int max, MesquiteInteger buttonPressed,String helpString) {
+		super(parent,title,stringTitle,numberTitle,string, number,min,max,buttonPressed,helpString,false);
+		this.names=names;
+		if (names==null)
+			chooseFromList = false;
+		else if (names.length==0)
+			chooseFromList = false;
+		selected = new MesquiteInteger(0);
+		this.listString = listString;
+		this.listTitle = listTitle;
+		this.exactlyOneSelected = exactlyOneSelected;
+		completeAndShowDialog(true,this);
+	}	
+	/*.................................................................................................................*/
+	public int getSelectedIndexFromString(String s) {
+		for (int i=0; i<names.length; i++)
+			if (names[i].equalsIgnoreCase(s))
+				return i;
+		return -1;
+	}
+	/*.................................................................................................................*/
+	public void addAuxiliaryDefaultPanels(){
+		if (chooseFromList) {
+			addBlankLine();
+			addLabel(listTitle + ": ",Label.LEFT);
+			Panel mainPanel = addNewDialogPanel();
+			int defaultItem =getSelectedIndexFromString(listString.getValue());
+			if (exactlyOneSelected && defaultItem>=0 && defaultItem<=names.length)
+				selected.setValue(defaultItem);
+			list = createListenedList (names,selected, 6, this,null, false);
+			list.setEnableDoubleClicks(acceptsDoubleClicks);  
+			list.setForceSize(true);
+			mainPanel.add(list);
+		}
+			
+	}
+	/*.................................................................................................................*/
+	 public  String getListString() {
+	 	if (chooseFromList) {
+			int i = list.getSelectedIndex();
+			if (i>=0 && i<names.length)
+				return names[i];
+	 	}
+	 	return null;
+	 }
+	/*.................................................................................................................*/
+	 public  void setValues() {
+ 		number.setValue(getNumber());
+ 		string.setValue(getString());
+ 		listString.setValue(getListString());
+	 }
+}
+
+
+
diff --git a/Source/mesquite/lib/StringLister.java b/Source/mesquite/lib/StringLister.java
new file mode 100644
index 0000000..d08eb09
--- /dev/null
+++ b/Source/mesquite/lib/StringLister.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+
+
+/* ======================================================================== */
+public interface StringLister {
+	public String[] getStrings();
+	/*---*/
+}
+
+
+
+
diff --git a/Source/mesquite/lib/StringUtil.java b/Source/mesquite/lib/StringUtil.java
new file mode 100644
index 0000000..502f248
Binary files /dev/null and b/Source/mesquite/lib/StringUtil.java differ
diff --git a/Source/mesquite/lib/SymbolGraphicsPanel.java b/Source/mesquite/lib/SymbolGraphicsPanel.java
new file mode 100644
index 0000000..1a1ae78
--- /dev/null
+++ b/Source/mesquite/lib/SymbolGraphicsPanel.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+
+public class SymbolGraphicsPanel extends DialogGraphicsPanel {
+	MesquiteSymbol symbol;
+	
+	public SymbolGraphicsPanel(ExtensibleDialog dialog, MesquiteSymbol symbol){
+		super(dialog);
+		this.symbol = symbol;
+	}
+	/*.................................................................................................................*/
+	public void setSymbol (MesquiteSymbol symbol) {
+		this.symbol = symbol;
+		repaint();
+	}
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		if (symbol!=null) {
+			symbol.drawSymbol(g,getBounds().width/2,getBounds().height/2);
+		}
+	}
+   	
+}
+
+
diff --git a/Source/mesquite/lib/SymbolsVector.java b/Source/mesquite/lib/SymbolsVector.java
new file mode 100644
index 0000000..96386cf
--- /dev/null
+++ b/Source/mesquite/lib/SymbolsVector.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+/** DOCUMENT.*/
+public class SymbolsVector extends ListableVector {
+
+}
+
diff --git a/Source/mesquite/lib/SystemWindow.java b/Source/mesquite/lib/SystemWindow.java
new file mode 100644
index 0000000..ce24aa0
--- /dev/null
+++ b/Source/mesquite/lib/SystemWindow.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+public interface SystemWindow {
+
+}
+
+
diff --git a/Source/mesquite/lib/TDLegendWithColors.java b/Source/mesquite/lib/TDLegendWithColors.java
new file mode 100644
index 0000000..65a1522
--- /dev/null
+++ b/Source/mesquite/lib/TDLegendWithColors.java
@@ -0,0 +1,237 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+/* ======================================================================== */
+public class TDLegendWithColors extends TreeDisplayLegend {
+	private LegendHolder traceModule;
+	private MesquiteString resultString;
+	private static final int defaultLegendWidth=142;
+	private static final int defaultLegendHeight=120;
+	private TCMPanel messageBox;
+	private TextArea specsBox;
+	private boolean holding = false;
+	final int scrollAreaHeight = 25;
+	private int messageHeight = 22;
+	final int defaultSpecsHeight = (34 + MesquiteModule.textEdgeCompensationHeight) * 1;
+	private int specsHeight = defaultSpecsHeight;
+	private int e = 4;
+	private String title;
+	private Color titleColor;
+	ColorRecord[] colorRecords;
+	
+	public TDLegendWithColors(LegendHolder traceModule, TreeDisplay treeDisplay, MesquiteString resultString, String title, Color titleColor) {
+		super(treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		setVisible(false);
+		this.title = title;
+		this.titleColor = titleColor;
+		this.resultString = resultString;
+		legendWidth=defaultLegendWidth;
+		legendHeight=defaultLegendHeight;
+		setOffsetX(traceModule.getInitialOffsetX());
+		setOffsetY(traceModule.getInitialOffsetY());
+		this.traceModule = traceModule;
+		//setBackground(ColorDistribution.light);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+
+		specsBox = new TextArea(" ", 2, 2, TextArea.SCROLLBARS_NONE);
+		specsBox.setEditable(false);
+		if (traceModule.showLegend())// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(false);
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		add(specsBox);
+		messageBox = new TCMPanel();
+		messageBox.setBounds(2,legendHeight-messageHeight-4,legendWidth-6, messageHeight);
+		messageBox.setText("\n");
+		//messageBox.setColor(Color.pink);
+		//messageBox.setBackground(Color.pink);
+		add(messageBox);
+	}
+	
+	public void setTitle(String title) {
+		this.title = title;
+	}
+	
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (messageBox!=null)
+			messageBox.setVisible(b);
+		if (specsBox!=null)// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(b);
+	}
+	
+	public void setColorRecords(ColorRecord[] colors){
+		int old = getNumBoxes();
+		colorRecords = colors;
+		if (old != getNumBoxes())
+			reviseBounds();
+	}
+	
+	public void refreshSpecsBox(){
+		if (resultString!=null)
+			specsBox.setText(resultString.getValue()); 
+	}
+	public void paint(Graphics g) {
+		   	if (MesquiteWindow.checkDoomed(this))
+		   		return;
+			if (!holding) {
+				g.setColor(Color.black);
+				if (colorRecords!=null) {
+					for (int ibox=0; ibox<colorRecords.length; ibox++) {
+						if (colorRecords[ibox]!=null) {
+							g.setColor(colorRecords[ibox].getColor());
+							g.fillRect(4, ibox*16+scrollAreaHeight + specsHeight+ e, 20, 12);
+							g.setColor(Color.black);
+							g.drawRect(4, ibox*16+scrollAreaHeight + specsHeight + e, 20, 12);
+							if (colorRecords[ibox].getString()!=null)
+								g.drawString(colorRecords[ibox].getString(), 28, ibox*16 + specsHeight+scrollAreaHeight + 12 + e);
+						}
+					}
+				}
+				g.setColor(Color.cyan);
+				g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+				g.fillRect(legendWidth-6, legendHeight-6, 6, 6);
+				g.drawLine(0, scrollAreaHeight, legendWidth-1, scrollAreaHeight);
+				
+				g.setColor(titleColor);
+				g.drawString(title, 4, 14);
+				g.setColor(Color.black);
+				if (resultString!=null  && resultString.getValue()!=null && !resultString.getValue().equals(specsBox.getText())){
+					specsBox.setText(resultString.getValue()); 
+				}
+				if (specsBox.getBackground() != getBackground())
+					specsBox.setBackground(getBackground());
+			}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	public void printAll(Graphics g) {
+		g.setColor(Color.black);
+		g.drawString(title, 4, 14);
+		int QspecsHeight = 0;
+		if (resultString!=null) {
+			String info = resultString.getValue();
+			StringInABox sib = new StringInABox(info, g.getFont(), legendWidth);
+			sib.draw(g, 4, 16);
+			QspecsHeight = sib.getHeight();
+		}
+		int lastBox = QspecsHeight + 20;
+		//int QspecsHeight = 0;
+		//int lastBox = scrollAreaHeight + QspecsHeight + 20 + 12;
+		if (colorRecords!=null) {
+			for (int ibox=0; ibox<colorRecords.length; ibox++) {
+				if (colorRecords[ibox]!=null) {
+					g.setColor(colorRecords[ibox].getColor());
+					g.fillRect(4, ibox*16+ QspecsHeight + 20, 20, 12);
+					g.setColor(Color.black);
+					g.drawRect(4, ibox*16+ QspecsHeight + 20, 20, 12);
+					if (colorRecords[ibox].getString()!=null)
+						g.drawString(colorRecords[ibox].getString(),  28, ibox*16 + QspecsHeight + 32);
+					lastBox =ibox*16 + QspecsHeight + 20 + 12;
+				}
+			}
+		}
+	}
+	
+	private int getNumBoxes(){
+		if (colorRecords == null)
+			return 0;
+		return colorRecords.length;
+	}
+	
+	public void legendResized(int widthChange, int heightChange){
+		if ((specsHeight + heightChange)>= defaultSpecsHeight)
+			specsHeight += heightChange;
+		else
+			specsHeight  = defaultSpecsHeight;
+		checkComponentSizes();
+	}
+//int reviseBoundsCounter=0;
+	public void reviseBounds(){
+		checkComponentSizes();
+		Point where = getLocation();
+		Rectangle bounds = getBounds();
+		if (bounds.width!=legendWidth || bounds.height!=legendHeight) //make sure a change is really needed
+			setBounds(where.x,where.y,legendWidth, legendHeight);
+	}
+	public void checkComponentSizes(){
+		specsBox.setBounds(1,scrollAreaHeight+2,legendWidth-2, specsHeight);
+		specsBox.setVisible(true);
+		messageHeight = messageBox.getHeightNeeded();
+		if (messageHeight<20)
+			messageHeight = 20;
+		legendHeight=getNumBoxes()*16+scrollAreaHeight + specsHeight + e + messageHeight + 4;
+		messageBox.setBounds(2,legendHeight-messageHeight-4,legendWidth-6, messageHeight);
+	}
+	
+	public void setMessage(String s) {
+		if (s==null || s.equals("")) {
+			//messageBox.setBackground(ColorDistribution.light);
+			messageBox.setText("\n");
+			reviseBounds();
+		}
+		else {
+			//messageBox.setBackground(Color.white);
+			messageBox.setText(s);
+			reviseBounds();
+		}
+	}
+	public void onHold() {
+		holding = true;
+	}
+	
+	public void offHold() {
+		holding = false;
+	}
+}
+
+class TCMPanel extends Panel {
+	String message = "";
+	StringInABox box;
+	public TCMPanel(){
+		super();
+		box =  new StringInABox("", null, getBounds().width);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		box.setWidth(w);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		box.setWidth(w);
+	}
+	public int getHeightNeeded(){
+		return box.getHeight();
+	}
+	public void paint (Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		box.setFont(g.getFont());
+		box.draw(g,0, 0);
+		//g.drawString(message, 2, 10);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	public void setText(String s) {
+		if (!message.equals(s)) {
+			message = s;
+			box.setString(s);
+			repaint();
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/lib/Taxa.java b/Source/mesquite/lib/Taxa.java
new file mode 100644
index 0000000..6d4f77c
--- /dev/null
+++ b/Source/mesquite/lib/Taxa.java
@@ -0,0 +1,1355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+import java.util.Vector;
+
+import mesquite.categ.lib.CategoricalData;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.duties.StringMatcher;
+
+/* ======================================================================== */
+/**
+ * An object of this class represents a single set of taxa (a TAXA block in a
+ * NEXUS file).
+ */
+public class Taxa extends FileElement {
+	private int numTaxa;
+	private Taxon[] taxon;
+	private MesquiteTree defaultTree;
+	private Clades clades;
+	String equalTaxaMessage = null;
+	boolean writeToEqualTaxaMessage = false;
+
+	public static boolean inventUniqueIDs = false;
+	private String uniqueID; // id's of the taxa block
+
+
+	public static final int MAXNUMTAXA = 100000;
+	public static int totalCreated = 0;
+	int id = 0;
+
+	private boolean inFlux = false;
+	private boolean duplicate = false;
+	
+
+	public Taxa(int numTaxa) {
+		super(numTaxa); // For associable
+		clades = new Clades();
+		this.numTaxa = numTaxa;
+		totalCreated++;
+		name = "Taxa";
+		taxon = new Taxon[numTaxa];
+		for (int it = 0; it < numTaxa; it++) {
+			taxon[it] = new Taxon(this);
+			taxon[it].setIndex(it);
+			taxon[it].setName("taxon " + Integer.toString(it + 1));
+			taxon[it].setNameIsDefault(true);
+		}
+		recordDefaultOrder();
+		if (Taxa.inventUniqueIDs)
+			setUniqueID(MesquiteTrunk.getUniqueIDBase() + totalCreated);
+	}
+	/*.................................................................................................................*/
+	Vector llListeners = new Vector();
+	public void addLowLevelListener(LowLevelListener listener){
+		llListeners.addElement(listener);
+	}
+	public void removeLowLevelListener(LowLevelListener listener){
+		llListeners.removeElement(listener);
+	}
+	void notifyOfChangeLowLevel(int code, int i1, int i2, int i3){
+			for (int i = 0; i< llListeners.size(); i++){
+				LowLevelListener lll = (LowLevelListener)llListeners.elementAt(i);
+				try {
+					lll.llChange(this, code, i1, i2, i3);
+				}
+				catch (Throwable e){ //don't want problem in one of these to stop notifications
+				}
+			}
+	}
+	/* ................................................................................................................. */
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String) null);
+		if (StringUtil.blank(s))
+			return null;
+		String list = "";
+		String fc = ""; // to receive the direct command
+		int numFound = 0;
+		for (int it = 0; it < getNumTaxa(); it++) {
+			String name = getTaxonName(it);
+			if (name != null && StringUtil.foundIgnoreCase(name, s)) {
+				list += "<li>Taxon " + (it + 1) + ": <strong>"
+				+ StringUtil.protectForXML(name)
+				+ "</strong>. <a href=\"touchTaxon:" + it + " "
+				+ getID() + "\">Touch taxon</a></li>";
+				numFound++;
+				fc = "touchTaxon:" + it + " " + getID();
+			}
+		}
+		if (commandResult != null && numFound == 1)
+			commandResult.setValue(fc);
+		if (StringUtil.blank(list))
+			return list;
+		return "<h2>Taxa \"" + StringUtil.protectForXML(getName())
+		+ "\"</h2><ul>" + list + "</ul>";
+	}
+
+	private int inhibitEdit = 0;
+	/*.................................................................................................................*/
+	public void incrementEditInhibition(){
+		inhibitEdit++;
+	}
+	/*.................................................................................................................*/
+	public void decrementEditInhibition(){
+		inhibitEdit--;
+		if (inhibitEdit == 0)
+			inhibitEdit = 0;
+	}
+	public boolean isEditInhibited(){
+		return inhibitEdit>0;
+	}
+	/* ................................................................................................................. */
+	/** gets the explanation (footnote) of this block of taxa */
+	public String getExplanation() {
+		String extra = "This block of taxa has " + getNumTaxa() + " taxa.\n";
+		return extra;
+	}
+
+	/* ................................................................................................................. */
+	public void dispose() {
+		for (int it = 0; it < numTaxa; it++) {
+			taxon[it] = null;
+		}
+		numTaxa = 0;
+		taxon = null;
+		clades = null;
+		super.dispose();
+	}
+
+	/* ................................................................................................................. */
+	public String getTypeName() {
+		return "Taxa";
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Call this before you might call the equals method if you wish the equals
+	 * method to store a list of reasons for differences between taxa.
+	 */
+	public void prepareEqualTaxaMessage() {
+		equalTaxaMessage = "";
+		writeToEqualTaxaMessage = true;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Call this before you might call the equals method if you wish the equals
+	 * method to store a list of reasons for differences between taxa.
+	 */
+	public void turnOffEqualTaxaMessage() {
+		equalTaxaMessage = "";
+		writeToEqualTaxaMessage = false;
+	}
+
+	/* ................................................................................................................. */
+	public String getEqualTaxaMessage() {
+		return equalTaxaMessage;
+	}
+
+	/* ................................................................................................................. */
+	public void appendToEqualTaxaMessage(String s) {
+		if (writeToEqualTaxaMessage)
+			if (StringUtil.blank(equalTaxaMessage))
+				equalTaxaMessage += s;
+			else
+				equalTaxaMessage += "; " + s;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns true if passed Taxa is the exact same, or if all of its taxon
+	 * names are the same
+	 */
+	public boolean equals(Taxa taxa, boolean ignoreName) {
+		return equals(taxa, ignoreName, true);
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns true if passed Taxa is the exact same, or if all of its taxon
+	 * names are the same
+	 */
+	public boolean equals(Taxa taxa, boolean ignoreName, boolean ignoreOrder) {
+		if (isDoomed()) {
+			return false;
+		}
+		// check name of Taxa???
+		if (taxa == this) {
+			// appendToEqualTaxaMessage("Taxon block compared with itself");
+			// writeToEqualTaxaMessage = false;
+			return true;
+		} else if (taxa == null) {
+			appendToEqualTaxaMessage("Taxon block null");
+			return false;
+		} else if (taxa.getNumTaxa() != numTaxa) {
+			appendToEqualTaxaMessage("Different numbers of taxa");
+			return false;
+		}
+		if (!ignoreName && name != null && taxa.name != null
+				&& !name.equalsIgnoreCase(taxa.name)) {
+			appendToEqualTaxaMessage("Taxa blocks have different names");
+			return false;
+		}
+		for (int it = 0; it < numTaxa; it++)
+			if (taxa.getTaxon(taxon[it].getName()) == null) {
+				appendToEqualTaxaMessage("Taxon " + taxon[it].getName()
+						+ " not found in second matrix");
+				return false;
+			}
+		for (int it = 0; it < numTaxa; it++)
+			if (getTaxon(taxa.getTaxonName(it)) == null) {
+				appendToEqualTaxaMessage("Taxon " + taxa.getTaxonName(it)
+						+ " not found in original matrix");
+				return false;
+			}
+		if (!ignoreOrder) {
+			for (int it = 0; it < numTaxa; it++)
+				if (taxa.whichTaxonNumber(taxon[it].getName()) != it) {
+					appendToEqualTaxaMessage("Taxon " + taxon[it].getName()
+							+ " not found in same place in second matrix");
+					return false;
+				}
+			for (int it = 0; it < numTaxa; it++)
+				if (whichTaxonNumber(taxa.getTaxonName(it)) != it) {
+					appendToEqualTaxaMessage("Taxon " + taxa.getTaxonName(it)
+							+ " not found in same order in original matrix");
+					return false;
+				}
+		}
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Returns true if passed Taxa is the exact same, or if all of its taxon
+	 * names are the same, or if the passed Taxa is a subset of this one
+	 */
+	public boolean contains(Taxa taxa, boolean ignoreName, boolean ignoreOrder) {
+		if (isDoomed()) {
+			return false;
+		}
+		// check name of Taxa???
+		if (taxa == this) {
+			// appendToEqualTaxaMessage("Taxon block compared with itself");
+			// writeToEqualTaxaMessage = false;
+			return true;
+		} else if (taxa == null) {
+			appendToEqualTaxaMessage("Taxon block null");
+			return false;
+		} else if (taxa.getNumTaxa() > numTaxa) {
+			appendToEqualTaxaMessage("Taxon block has more taxa");
+			return false;
+		}
+		if (!ignoreName && name != null && taxa.name != null
+				&& !name.equalsIgnoreCase(taxa.name)) {
+			appendToEqualTaxaMessage("Taxa blocks have different names");
+			return false;
+		}
+		int inputNumTaxa = taxa.getNumTaxa();
+		for (int it = 0; it < inputNumTaxa; it++)
+			if (getTaxon(taxa.getTaxonName(it)) == null) {
+				appendToEqualTaxaMessage("Taxon " + taxa.getTaxonName(it)
+						+ " not found in original matrix");
+				return false;
+			}
+		if (!ignoreOrder) {
+			for (int it = 0; it < inputNumTaxa; it++)
+				if (whichTaxonNumber(taxa.getTaxonName(it)) != it) {
+					appendToEqualTaxaMessage("Taxon " + taxa.getTaxonName(it)
+							+ " not found in same order in original matrix");
+					return false;
+				}
+		}
+		return true;
+	}
+
+	public int findEquivalentTaxon(Taxa oTaxa, int oit) {
+		if (oTaxa == null)
+			return -1;
+		if (oTaxa == this)
+			return oit;
+		int idt = findByUniqueID(oTaxa.getUniqueID());
+		if (idt >= 0)
+			return idt;
+		idt = whichTaxonNumber(oTaxa.getTaxonName(oit));
+		if (idt >= 0)
+			return idt;
+		return -1;
+	}
+
+	private NameReference notesNameRef = NameReference
+	.getNameReference("notes");
+
+	/*-----------------------------------------------------------*/
+	public void equalizeTaxon(Taxa oTaxa, int oit, int it) {
+		if (oTaxa == null || oit < 0 || it < 0)
+			return;
+		Taxon taxon = getTaxon(it);
+		Taxon oTaxon = oTaxa.getTaxon(oit);
+		taxon.setName(oTaxon.getName());
+		setAnnotation(it, oTaxa.getAnnotation(oit));
+		taxon.setUniqueID(oTaxon.getUniqueID());
+		AttachedNotesVector notes = (AttachedNotesVector) oTaxa
+		.getAssociatedObject(notesNameRef, oit);
+		if (notes != null)
+			setAssociatedObject(notesNameRef, it, notes.cloneVector(this));
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Note this does not yield a full clone of the taxa, as Associable and
+	 * Illustration info is not cloned
+	 */
+	public Taxa cloneTaxa(boolean[] taxaToClone) {
+		int numTax = numTaxa;
+		if (taxaToClone != null) {
+			int count = 0;
+			for (int i = 0; i < taxaToClone.length; i++)
+				if (taxaToClone[i])
+					count++;
+			numTax = count;
+		}
+		if (isDoomed())
+			return null;
+		Taxa temp = new Taxa(numTax);
+		temp.name = name;
+		if (taxaToClone != null) {
+			int count = 0;
+			for (int i = 0; i < taxaToClone.length; i++)
+				if (taxaToClone[i]) {
+					if (count<numTax)
+						temp.taxon[count].setName(taxon[i].getName());
+					count++;
+				}
+		} else
+			for (int it = 0; it < numTaxa; it++) {
+				temp.taxon[it].setName(taxon[it].getName());
+			}
+		return temp;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * Note this does not yield a full clone of the taxa, as Associable and
+	 * Illustration info is not cloned
+	 */
+	public Taxa cloneTaxa() {
+		if (isDoomed())
+			return null;
+		Taxa temp = new Taxa(numTaxa);
+		temp.name = name;
+		for (int it = 0; it < numTaxa; it++) {
+			temp.taxon[it].setName(taxon[it].getName());
+		}
+		return temp;
+	}
+
+	/***************************************************************************
+	 * .................................................................................................................
+	 * public Snapshot getSnapshot(MesquiteFile file) { return
+	 * super.getSnapshot(file); //here to remind to call super's version if
+	 * anything added here }
+	 * /*.................................................................................................................
+	 */
+	public Object doCommand(String commandName, String arguments,
+			CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the name of the taxon",
+				"[number of taxon, 0 based]", commandName, "setTaxonName")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int c = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(c) && c >= 0 && c < numTaxa) {
+				String n = ParseUtil.getToken(arguments, pos);
+				setTaxonName(c, n);
+			}
+		} else {
+			return super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumber(String taxonName) {
+		return whichTaxonNumber(taxonName, false);
+	}
+
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumber(String taxonName, boolean caseSensitive) {
+		return whichTaxonNumber(taxonName, caseSensitive, false);
+	}
+
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumberUsingMatcher(StringMatcher nameMatcher, String taxonName) {
+		if (StringUtil.blank(taxonName))
+			return -1;
+		for (int i = 0; i < numTaxa; i++){  //check UniqueID's
+			String uniqueID = taxon[i].getUniqueID();
+			if (uniqueID != null && taxonName.equals(uniqueID))
+				return i;
+		}
+		int tN0 = MesquiteInteger.fromString(taxonName, false);
+		if (MesquiteInteger.isCombinable(tN0) && tN0 >= 1 && tN0 <= numTaxa) {
+			return Taxon.toInternal(tN0);
+		}
+
+		int match = -1;
+		int numMatches = 0;
+		for (int i = 0; i < numTaxa; i++) {
+			String ti = taxon[i].getName();
+			if (ti != null  && nameMatcher.stringsMatch(ti, taxonName)) {
+				match = i;
+				numMatches++;
+			}
+		}
+		if (numMatches < 2 && match >= 0)
+			return match;
+
+		// System.out.println("ERROR: bad taxon name: "+ taxonName);
+		return -1;
+	}
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumber(StringMatcher nameMatcher, String taxonName, boolean caseSensitive, boolean forgivingOfTruncation) {
+		if (nameMatcher==null || nameMatcher.useDefaultMatching())
+			return whichTaxonNumber(taxonName, caseSensitive, forgivingOfTruncation);
+		return whichTaxonNumberUsingMatcher(nameMatcher, taxonName);
+	}
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumber(String taxonName, boolean caseSensitive, boolean forgivingOfTruncation) {
+		if (StringUtil.blank(taxonName))
+			return -1;
+		// second, see if there is an exact match
+		if (caseSensitive) {
+			for (int i = 0; i < numTaxa; i++)
+				if (taxonName.equals(taxon[i].getName()))
+					return i;
+		} else {
+			for (int i = 0; i < numTaxa; i++) { // first try exact match
+				if (taxonName.equals(taxon[i].getName()))
+					return i;
+			}
+			for (int i = 0; i < numTaxa; i++) {
+				if (taxonName.equalsIgnoreCase(taxon[i].getName()))
+					return i;
+			}
+		}
+		for (int i = 0; i < numTaxa; i++){  //check UniqueID's
+			String uniqueID = taxon[i].getUniqueID();
+			if (uniqueID != null && taxonName.equals(uniqueID))
+				return i;
+		}
+		// first see if integer. If integer, interpret first as
+		// taxon number in case forgivingOfTrunctation permits taxon name
+		// beginning with integer
+		int tN0 = MesquiteInteger.fromString(taxonName, false);
+		if (MesquiteInteger.isCombinable(tN0) && tN0 >= 1 && tN0 <= numTaxa) {
+			return Taxon.toInternal(tN0);
+		}
+		if (forgivingOfTruncation) {
+			// third, see if there is an unambiguous match of truncation
+			// NOTE: currently we permit only truncation in the incoming name to
+			// be considered a match against the Taxa block
+			if (caseSensitive) {
+				int matchTrunc = -1;
+				int numMatches = 0;
+				for (int i = 0; i < numTaxa; i++) {
+					String ti = taxon[i].getName();
+					if (ti != null && ti.startsWith(taxonName)) {
+						matchTrunc = i;
+						numMatches++;
+					}
+				}
+				if (numMatches < 2 && matchTrunc >= 0)
+					return matchTrunc;
+
+				/*
+				 * this code would permit match if name is extended beyond that
+				 * in Taxa block if (numMatches <2){ int matchExtend = -1;
+				 * numMatches = 0; for (int i=0; i<numTaxa; i++){ String ti =
+				 * taxon[i].getName(); if (taxonName.startsWith(ti)) {
+				 * matchExtend = i; numMatches++; } } if (numMatches <2){ if
+				 * (matchTrunc >=0){ if (matchExtend <0 || matchTrunc ==
+				 * matchExtend) return matchTrunc; } else if (matchExtend >=0)
+				 * return matchExtend; } }
+				 */
+			} else {
+				int matchTrunc = -1;
+				int matchExtend = -1;
+				int numMatches = 0;
+				for (int i = 0; i < numTaxa; i++) {
+					String ti = taxon[i].getName();
+					if (ti != null
+							&& StringUtil.startsWithIgnoreCase(ti, taxonName)) {
+						matchTrunc = i;
+						numMatches++;
+					}
+				}
+				if (numMatches < 2 && matchTrunc >= 0)
+					return matchTrunc;
+				/*
+				 * this code would permit match if name is extended beyond that
+				 * in Taxa block if (numMatches <2){ numMatches = 0; for (int
+				 * i=0; i<numTaxa; i++){ String ti = taxon[i].getName(); if
+				 * (StringUtil.startsWithIgnoreCase(taxonName, ti)) {
+				 * matchExtend = i; numMatches++; } } if (numMatches <2){ if
+				 * (matchTrunc >=0){ if (matchExtend <0 || matchTrunc ==
+				 * matchExtend) return matchTrunc; } else if (matchExtend >=0)
+				 * return matchExtend; } }
+				 */
+			}
+		}
+
+		// System.out.println("ERROR: bad taxon name: "+ taxonName);
+		return -1;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * returns which taxon (i.e., its number) has the given name, doing reverse
+	 * search from last to first
+	 */
+	public int whichTaxonNumberRev(String taxonName, boolean caseSensitive) {
+		if (StringUtil.blank(taxonName))
+			return -1;
+		if (caseSensitive) {
+			for (int i = numTaxa - 1; i >= 0; i--)
+				if (taxonName.equals(taxon[i].getName()))
+					return i;
+		} else {
+			for (int i = numTaxa - 1; i >= 0; i--)
+				// first try exact match
+				if (taxonName.equals(taxon[i].getName()))
+					return i;
+			for (int i = numTaxa - 1; i >= 0; i--)
+				if (taxonName.equalsIgnoreCase(taxon[i].getName()))
+					return i;
+		}
+		try {
+			int tNum = Taxon.toInternal(MesquiteInteger.fromString(taxonName,
+					false));
+			if ((tNum < numTaxa) && (tNum >= 0))
+				return tNum;
+		} catch (NumberFormatException e) {
+			System.out.println("ERROR: bad taxon number/taxon name: "
+					+ taxonName);
+			return -1;
+		}
+		// System.out.println("ERROR: bad taxon name: "+ taxonName);
+		return -1;
+	}
+	/* ................................................................................................................. */
+	/**
+	 * returns which taxon (i.e., its number) has the given name, doing reverse
+	 * search from last to first
+	 */
+	public int whichTaxonNumberUsingMatcherRev(StringMatcher nameMatcher, String taxonName) {
+		if (StringUtil.blank(taxonName))
+			return -1;
+
+		for (int i = numTaxa - 1; i >= 0; i--)
+			if (nameMatcher.stringsMatch(taxonName, taxon[i].getName()))
+				return i;
+		try {
+			int tNum = Taxon.toInternal(MesquiteInteger.fromString(taxonName, false));
+			if ((tNum < numTaxa) && (tNum >= 0))
+				return tNum;
+		} catch (NumberFormatException e) {
+			System.out.println("ERROR: bad taxon number/taxon name: "
+					+ taxonName);
+			return -1;
+		}
+		// System.out.println("ERROR: bad taxon name: "+ taxonName);
+		return -1;
+	}
+	
+	/* ................................................................................................................. */
+	/**
+	 * returns which taxon (i.e., its number) has the given name, doing reverse
+	 * search from last to first
+	 */
+	public int whichTaxonNumberRev(StringMatcher nameMatcher, String taxonName, boolean caseSensitive) {
+		if (nameMatcher==null)
+			return whichTaxonNumberRev(taxonName, caseSensitive);
+		return whichTaxonNumberUsingMatcherRev(nameMatcher, taxonName);
+	}
+
+
+	/* ................................................................................................................. */
+	/** returns which number has the given taxon. */
+	public int whichTaxonNumber(Taxon t) {
+		if (t == null || t.getTaxa() != this)
+			return -1;
+		int ind =  t.getIndex();
+		if (ind < 0 || !MesquiteInteger.isCombinable(ind))
+			return whichTaxonNumberCheck(t);
+		else
+			return ind;
+	}
+	/* ................................................................................................................. */
+	/** returns which number has the given taxon. */
+	public int whichTaxonNumberCheck(Taxon t) {
+		for (int i = 0; i < numTaxa; i++)
+			if (t == taxon[i])
+				return i;
+		return -1;
+	}
+
+	/* ................................................................................................................. */
+	public String getUniqueName(String base) {
+		int count = 1;
+		while (true) {
+
+			String candidate;
+			if (count == 1)
+				candidate = base;
+			else
+				candidate = base + "." + count;  
+			if (whichTaxonNumber(candidate) < 0)
+				return candidate;
+			count++;
+		}
+
+	}
+
+	/* ................................................................................................................. */
+	public void setName(String name) {
+		setDirty(true);
+		this.name = name;
+		notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+		if (getHShow()) {
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		}
+	}
+
+	/* ................................................................................................................. */
+	public String getName() {
+		if (name == null)
+			return "Taxa";
+		return name;
+	}
+	/** returns true if this has name equivalent to default name*/
+	public boolean hasDefaultName() {
+		return  (name==null) || name.equals("Taxa");
+	}
+
+	/* ................................................................................................................. */
+	/** Gets the default tree for these taxa (default default is bush) */
+	public MesquiteTree getDefaultTree() {
+		if (isDoomed())
+			return null;
+		if (defaultTree == null) {
+			MesquiteTree tree = new MesquiteTree(this);
+			tree.setToDefaultBush(getNumTaxa(), false);
+			return tree;
+		}
+		return defaultTree;
+	}
+
+	/* ................................................................................................................. */
+	/** Gets the default tree for these taxa (default default is bush) */
+	public MesquiteTree getDefaultDichotomousTree(MesquiteTree tree) {
+		if (isDoomed())
+			return null;
+		if (tree == null || tree.getTaxa() != this) {
+			tree = new MesquiteTree(this);
+		}
+		tree.setToDefaultSymmetricalTree(getNumTaxa(), false);
+		return tree;
+	}
+
+	/* ................................................................................................................. */
+	/** sets the default tree for these taxa */
+	public void setDefaultTree(MesquiteTree tree) {
+		defaultTree = tree;
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+
+	/* ................................................................................................................. */
+	public int getNumTaxa() {
+		if (isDoomed())
+			return 0;
+		return numTaxa;
+	}
+
+	String findName(int num, Taxon[] t) {
+		while (true) {
+			String s = "taxon " + Integer.toString(num);
+			if (getTaxon(s) == null && !nameInTaxonArray(s, t))
+				return s;
+			num++;
+		}
+	}
+
+	boolean nameInTaxonArray(String name, Taxon[] t) {
+		if (t == null || name == null)
+			return false;
+		for (int i = 0; i < t.length; i++)
+			if (t[i] != null && name.equals(t[i].getName()))
+				return true;
+		return false;
+	}
+	public Taxon addTaxon(boolean notify){
+		if (addTaxa(getNumTaxa(), 1, notify))
+			return getTaxon(getNumTaxa()-1);
+		return null;
+	}
+	public void deleteTaxon(Taxon taxon, boolean notify){
+		if (inhibitEdit>0)
+			return;
+		int it = whichTaxonNumber(taxon);
+		if (it>=0)
+			deleteTaxa(it, 1, notify);
+	}
+	/*.................................................................................................................*/
+	public void deleteTaxaWithDuplicateNames (){
+		if (inhibitEdit>0)
+			return;
+		IntegerArray originalIndices = (IntegerArray) getAttachment("originalIndicesDupRead", IntegerArray.class);
+		if (originalIndices != null)
+			for (int i=0; i<getNumTaxa(); i++)
+				originalIndices.setValue(i, i);
+		boolean[] toDelete = new boolean[getNumTaxa()];
+		for (int i=0; i<getNumTaxa(); i++){
+			if (!toDelete[i]){
+				String name = getTaxonName(i);
+				boolean dup = false;
+				toDelete[i] = true;
+				for (int j=i+1; j<getNumTaxa(); j++){
+					String name2 = getTaxonName(j);
+					if (name!=null && name.equalsIgnoreCase(name2)) {
+						toDelete[j] = true;
+						if (originalIndices != null){
+							originalIndices.setValue(j, i);  //indicate to what this deleted is equivalent
+							// mark all subsequent nondeleted to one less
+							for (int k = j+1;  k<getNumTaxa(); k++){
+								if (!toDelete[k])
+									originalIndices.setValue(k, originalIndices.getValue(k)-1);
+							}
+						}
+					}
+				}
+				toDelete[i] = false;
+			}
+		}
+		for (int i=getNumTaxa()-1; i>=0; i--){
+			if (toDelete[i]){
+				deleteTaxon(getTaxon(i), false);
+			}
+		}
+		notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+	}
+	/*.................................................................................................................*/
+	public String hasDuplicateNames (){
+		return hasDuplicateNames(false);
+	}
+	/*.................................................................................................................*/
+	public String hasDuplicateNames (boolean report){
+		StringBuffer list = new StringBuffer();
+		int numTaxa = getNumTaxa();
+		if (report && numTaxa>1000)  MesquiteMessage.println("");
+		for (int i=0; i<numTaxa; i++){
+			String name = getTaxonName(i);
+			long iChecksum = taxon[i].getNameChecksum();
+			if (report && numTaxa>1000 && i % 500 == 0) 
+				MesquiteMessage.print(".");
+			for (int j=i+1; j<numTaxa; j++){
+				long jChecksum = taxon[j].getNameChecksum();
+				if (iChecksum == jChecksum){
+					String name2 = getTaxonName(j);
+					if (name!=null && name.equalsIgnoreCase(name2)) {
+						list.append(" [" + i + "-" + j + "] " + name);
+						MesquiteMessage.println(name);
+					}
+				}
+			}
+		}
+		if (list.length() == 0)
+			return null;
+		return list.toString();
+	}
+	/* ................................................................................................................. */
+	/**
+	 * An equivalent to addParts but with notification added. Final because
+	 * overriding should be done of the Parts method instead
+	 */
+	public final boolean addTaxa(int first, int num, boolean notify) {
+		if (inhibitEdit>0)
+			return false;
+	UndoReference undoReference = null;
+		if (notify) {
+			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED, this);
+			resetJustAdded();
+			undoReference = new UndoReference(undoInstructions, null);
+		}
+
+		boolean added = addParts(first, num);
+		if (added && notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] { first, num },undoReference));
+		return added;
+
+	}
+
+	/* ................................................................................................................. */
+	/** Adds new taxa starting just after taxon "starting" */
+	public boolean addParts(int starting, int num) {
+		if (isDoomed())
+			return false;
+		if (num <= 0)
+			return false;
+		if (!checkThread(false))
+			return false;
+		if (inhibitEdit>0)
+			return false;
+		inFlux = true;
+		if (starting < 0)
+			starting = -1;
+		else if (starting >= numTaxa)
+			starting = numTaxa - 1;
+		int newNumTaxa = numTaxa + num;
+		Taxon[] newTaxonArray = new Taxon[newNumTaxa];
+
+		for (int it = 0; it <= starting; it++)
+			newTaxonArray[it] = taxon[it];
+		for (int it = 0; it < num; it++) {
+			newTaxonArray[starting + it + 1] = new Taxon(this);
+			newTaxonArray[starting + it + 1].setName(findName(
+					starting + it + 2, newTaxonArray));
+		}
+		for (int it = 0; it < numTaxa - starting - 1; it++){
+			newTaxonArray[it + starting + num + 1] = taxon[starting + it + 1];
+		}
+		taxon = newTaxonArray;
+		numTaxa = newNumTaxa;
+		for (int it = 0; it < numTaxa; it++)
+			taxon[it].setIndex(it);
+		super.addParts(starting, num);
+		inFlux = false;
+		uncheckThread();
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_ADDED, starting, num, 0);  
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * An equivalent to deleteParts but with notification added. Final because
+	 * overriding should be done of the Parts method instead
+	 */
+	public final boolean deleteTaxa(int first, int num, boolean notify) {
+		if (inhibitEdit>0)
+			return false;
+		boolean deleted = deleteParts(first, num);
+		if (deleted && notify)
+			notifyListeners(this, new Notification(
+					MesquiteListener.PARTS_DELETED, new int[] { first, num }));
+		return deleted;
+
+	}
+
+	/* ................................................................................................................. */
+	/** Deletes num taxa beginning at and including "starting" */
+	public boolean deleteParts(int starting, int num) {
+		if (inhibitEdit>0)
+			return false;
+		
+		if (num <= 0 || starting < 0 || starting >= numTaxa)
+			return false;
+		
+		if (!checkThread(false))
+			return false;
+		inFlux = true;
+		if (num + starting > numTaxa)
+			num = numTaxa - starting;
+
+		int newNumTaxa = numTaxa - num;
+		Taxon[] newTaxonArray = new Taxon[newNumTaxa];
+
+		for (int it = 0; it < starting; it++)
+			newTaxonArray[it] = taxon[it];
+		for (int it = starting + num; it < numTaxa; it++)
+			newTaxonArray[it - num] = taxon[it];
+
+		taxon = newTaxonArray;
+		numTaxa = newNumTaxa;
+		for (int it = 0; it < numTaxa; it++)
+			taxon[it].setIndex(it);
+		super.deleteParts(starting, num);
+		inFlux = false;
+		uncheckThread();
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_DELETED, starting, num, 0);  
+		return true;
+	}
+
+	/* ................................................................................................................. */
+	/** Swaps taxa first and second */
+	public boolean swapTaxa(int first, int second, boolean notify) {
+		if (isDoomed())
+			return false;
+		if (first >= taxon.length || second >= taxon.length || first < 0
+				|| second < 0 || first == second)
+			return false;
+		if (inhibitEdit>0)
+			return false;
+		swapParts(first, second);
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_SWAPPED, first, second, 0);  
+		inFlux = true;
+		/*
+		 * Taxon temp = taxon[first]; taxon[first] = taxon[second];
+		 * taxon[second] = temp; if (first<second) { moveParts(first, 1,
+		 * second); moveParts(second-1, 1, first-1); } else { moveParts(second,
+		 * 1, first); moveParts(first-1, 1, second-1); }
+		 */
+		if (notify)
+			notifyListeners(this,
+					new Notification(MesquiteListener.PARTS_MOVED));
+		inFlux = false;
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	/**
+	 * An equivalent to moveParts but with notification added. Final because
+	 * overriding should be done of the Parts method instead
+	 */
+	public final boolean moveTaxa(int first, int num, int justAfter, boolean notify) {
+		if (inhibitEdit>0)
+			return false;
+		boolean moved = moveParts(first, num, justAfter);
+		if (moved && notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, new int[] { first, num, justAfter }));
+		return moved;
+
+	}
+
+	/* ........................................................... */
+	public boolean swapParts(int first, int second) {
+		if (first < 0 || first >= taxon.length || second < 0
+				|| second >= taxon.length)
+			return false;
+		if (!checkThread(false))
+			return false;
+		if (inhibitEdit>0)
+			return false;
+		inFlux = true;
+		Taxon temp = taxon[first];
+		taxon[first] = taxon[second];
+		taxon[second] = temp;
+		boolean success = super.swapParts(first, second);
+		taxon[first].setIndex(first);
+		taxon[second].setIndex(second);
+		inFlux = false;
+		uncheckThread();
+		return success;
+	}
+
+	/* ................................................................................................................. */
+	/** Moves num taxa starting at first to be just after justAfter */
+	public boolean moveParts(int first, int num, int justAfter) {
+		if (isDoomed())
+			return false;
+		if (!checkThread(false))
+			return false;
+		if (inhibitEdit>0)
+			return false;
+		inFlux = true;
+
+		if (justAfter >= taxon.length)
+			justAfter = taxon.length - 1;
+		if (justAfter < 0)
+			justAfter = -1;
+		Taxon[] newTaxa = new Taxon[taxon.length];
+		if (first > justAfter) {
+			int count = 0;
+			for (int i = 0; i <= justAfter; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = first; i <= first + num - 1; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = justAfter + 1; i <= first - 1; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = first + num; i < taxon.length; i++)
+				newTaxa[count++] = taxon[i];
+		} else { // (first<=justAfter)
+			int count = 0;
+			for (int i = 0; i <= first - 1; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = first + num; i <= justAfter; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = first; i <= first + num - 1; i++)
+				newTaxa[count++] = taxon[i];
+			for (int i = justAfter + 1; i < taxon.length; i++)
+				newTaxa[count++] = taxon[i];
+		}
+		taxon = newTaxa;
+		super.moveParts(first, num, justAfter);
+		for (int it = 0; it < numTaxa; it++)
+			taxon[it].setIndex(it);
+		inFlux = false;
+		uncheckThread();
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_MOVED, first, num, justAfter);  
+		return true;
+	}
+
+	public boolean isInFlux() {
+		return inFlux;
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxon(String name) {
+		return getTaxon(name, false);
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxon(String name, boolean caseSensitive) {
+		return getTaxon(name, caseSensitive, false);
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxon(String name, boolean caseSensitive,
+			boolean forgivingOfTruncation) {
+		if (isDoomed())
+			return null;
+		if (name != null) {
+			int it = whichTaxonNumber(name, caseSensitive,
+					forgivingOfTruncation);
+			if (it >= 0)
+				return taxon[it];
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxonAllowingSynonyms(String name, boolean caseSensitive) {
+		if (isDoomed())
+			return null;
+		if (name != null) {
+			int it = whichTaxonNumber(name, caseSensitive);
+			if (it >= 0)
+				return taxon[it];
+			it = whichTaxonNumberAllowingSynonyms(name, caseSensitive);
+			if (it >= 0)
+				return taxon[it];
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	/** returns which taxon (i.e., its number) has the given name */
+	public int whichTaxonNumberAllowingSynonyms(String taxonName,
+			boolean caseSensitive) {
+		if (StringUtil.blank(taxonName))
+			return -1;
+		if (caseSensitive) {
+			for (int i = 0; i < numTaxa; i++)
+				if (taxon[i].getSynonym() != null
+						&& taxonName.equals(taxon[i].getSynonym()))
+					return i;
+		} else {
+			for (int i = 0; i < numTaxa; i++)
+				// first try exact match
+				if (taxon[i].getSynonym() != null
+						&& taxonName.equals(taxon[i].getSynonym()))
+					return i;
+			for (int i = 0; i < numTaxa; i++)
+				if (taxon[i].getSynonym() != null
+						&& taxonName.equalsIgnoreCase(taxon[i].getSynonym()))
+					return i;
+		}
+		return -1;
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxonByID(long id) {
+		if (isDoomed())
+			return null;
+		for (int i = 0; i < numTaxa; i++)
+			if (taxon[i].getID() == id)
+				return taxon[i];
+		return null;
+	}
+
+	public long[] getTaxaIDs() {
+		long[] taxaIDs = new long[numTaxa];
+		for (int i = 0; i < numTaxa; i++) {
+			Taxon t = getTaxon(i);
+			if (t != null)
+				taxaIDs[i] = t.getID();
+		}
+		return taxaIDs;
+	}
+
+	// setting uniqueID for block
+	public void setUniqueID(String id) {
+		uniqueID = id;
+	}
+
+	// getting uniqueID for block
+	public String getUniqueID() {
+		return uniqueID;
+	}
+
+	public void deleteUniqueIDs() {
+		for (int i = 0; i < numTaxa; i++) {
+			taxon[i].setUniqueID(null);
+		}
+	}
+
+	public int findByUniqueID(String target) {
+		if (target == null)
+			return -1;
+		String base = MesquiteTrunk.getUniqueIDBase();
+		for (int i = 0; i < numTaxa; i++) {
+			String id = getUniqueID(i);
+			if (id != null && id.equals(target))
+				return i;
+		}
+		return -1;
+	}
+
+	public void stampUniqueIDs(boolean replaceExisting) {
+		String base = MesquiteTrunk.getUniqueIDBase();
+		for (int i = 0; i < numTaxa; i++) {
+			if (replaceExisting || StringUtil.blank(taxon[i].getUniqueID()))
+				taxon[i].setUniqueID(base + Taxon.totalCreated++);
+		}
+	}
+
+	public void stampUniqueID(int i, boolean replaceExisting) {
+		String base = MesquiteTrunk.getUniqueIDBase();
+		if (replaceExisting || StringUtil.blank(taxon[i].getUniqueID()))
+			taxon[i].setUniqueID(base + Taxon.totalCreated++);
+	}
+
+	public void setUniqueID(int it, String id) {
+		Taxon t = getTaxon(it);
+		if (t != null)
+			t.setUniqueID(id);
+	}
+
+	public String getUniqueID(int it) {
+		Taxon t = getTaxon(it);
+		if (t != null)
+			return t.getUniqueID();
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public Taxon getTaxon(int it) {
+		if (isDoomed())
+			return null;
+		if (it >= 0 && it < numTaxa)
+			return taxon[it];
+		else
+			return null;
+	}
+
+	/* ................................................................................................................. */
+	public void setTaxon(int it, Taxon t) {
+		setDirty(true);
+		taxon[it] = t;
+		notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+	}
+
+	/* ................................................................................................................. */
+	public static String getStandardizedTaxonName(int it) {
+		return "t"+it;
+	}
+
+	/* ................................................................................................................. */
+	public String getTaxonName(int it) {
+		if (it >= 0 && it < numTaxa)
+			return taxon[it].getName();
+		else
+			return "";
+	}
+
+	/* ................................................................................................................. */
+	public void setTaxonName(int it, String s) {
+		setTaxonName(it, s, true);
+	}
+
+	/* ................................................................................................................. */
+	public void setTaxonNameNoWarnNoNotify(int it, String s) {
+		if (it >= 0 && it < numTaxa) {
+			setDirty(true);
+			taxon[it].setName(s);
+		}
+	}
+	/* ................................................................................................................. */
+	public void setTaxonName(int it, String s, boolean notify) {
+		if (it >= 0 && it < numTaxa) {
+			setDirty(true);
+			taxon[it].setName(s);
+			warnIfNameIllegal(it, s);
+			notifyOfChangeLowLevel(MesquiteListener.NAMES_CHANGED, it, 0, 0);  
+			if (notify)
+				notifyListeners(this, new Notification(
+						MesquiteListener.NAMES_CHANGED, new int[] { it }));
+		}
+	}
+
+	/* ................................................................................................................. */
+	private void warnIfNameIllegal(int it, String s) {
+		String st = checkNameLegality(it, s);
+		if (st != null)
+			MesquiteMessage.warnProgrammer(st);
+	}
+
+	java.util.zip.CRC32 crc = new java.util.zip.CRC32();
+	
+
+	/* ................................................................................................................. */
+	public String checkNameLegality(int it, String s) {
+		return checkNameLegality(it, numTaxa, s);
+	}
+	/* ................................................................................................................. */
+	public String checkNameLegality(int it, int checkUntil, String s) {
+		if (StringUtil.blank(s)) {
+			return "Illegal taxon name (null or blank)";
+		}
+		try {
+			int i = Integer.parseInt(s);
+			return "The taxon name \""	+ s + "\" is illegal because it consists only of numbers.  This may cause various problems and should be fixed.";
+		} catch (NumberFormatException e) {
+		}
+		crc.reset();
+		for (int i = 0; i< s.length(); i++)
+			crc.update(s.charAt(i));
+		long sChecksum = crc.getValue();
+		for (int i = 0; i < checkUntil; i++) {
+			Taxon otherTaxon = taxon[i];
+			if (i != it 
+					&&  sChecksum == otherTaxon.getNameChecksum() 
+					&&  !otherTaxon.isNameNull() //(i < it || !otherTaxon.isNameDefault()) &&
+					&&  s.equals(otherTaxon.getName())
+				) { 
+				return "The taxon name \"" + s + "\" for taxon " + (it + 1) + " is illegal because another taxon (#" + (i + 1) + ") already has it.  This may cause various problems and should be fixed.";
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public String getName(int it) {
+		if (it >= 0 && it < numTaxa) {
+			String s = taxon[it].getName();
+			if (s == null)
+				return "";
+			return s;
+		} else
+			return "";
+	}
+
+	/* ................................................................................................................. */
+	public int getLongestTaxonNameLength() {
+		int maxLength = 0;
+		int itLength;
+		for (int it = 0; it < numTaxa; it++) {
+			itLength = getName(it).length();
+			if (itLength > maxLength)
+				maxLength = itLength;
+		}
+		return maxLength;
+	}
+
+	/* ................................................................................................................. */
+	public Taxon userChooseTaxon(MesquiteWindow parent, String message) {
+		Listable[] names = new Listable[numTaxa];
+		for (int i = 0; i < numTaxa; i++)
+			names[i] = taxon[i];
+		Listable chosen = ListDialog.queryList(parent, "Choose taxon", message,
+				MesquiteString.helpString, names, -1);
+		return (Taxon) chosen;
+	}
+
+	/* ................................................................................................................. */
+	public String toString() {
+		return "Taxa block (name: " + getName() + " number of taxa: " + numTaxa
+		+ " id: " + getID() + ")";
+	}
+
+	public String toHTMLStringDescription() {
+		//	String s = "<li>Taxa block: <strong>" + getName() + "</strong>.  Number of taxa: " + numTaxa + ".  (<a href =\"showTaxa:" + getID() + "\">List & Manage</a>)  (<a href =\"chartTaxa:" + getID() + "\">Chart</a>)(<a href =\"renameTaxa:" + getID() + "\">Rename</a>)  (<a href =\"editCommentTaxa:" + getID() + "\">Edit Comment</a>)  (<a href =\"deleteTaxa:" + getID() + "\">Delete</a>)";
+		String s = "<li>Taxa block: <strong>" + getName() + "</strong>.  Number of taxa: " + numTaxa + ". ";
+		String comment = getAnnotation();
+		if (!StringUtil.blank(comment))
+			s+= "<br><font color=\"#777777\">" + comment + "</font>";
+		if (HTMLDescribable.verbose)
+			s += "<ul>" + super.toHTMLStringDescription() + "</ul>";
+		s += "</li>";
+		return s;
+	}
+
+	public Clades getClades() {
+		if (isDoomed())
+			return null;
+		return clades;
+	}
+
+	/**
+	 * returns whether this taxa is marked as a duplicate of another. This is
+	 * used for merging taxa and subsequently saving the file. The system is
+	 * kludgey and may change
+	 */
+	public boolean isDuplicate() {
+		return duplicate;
+	}
+
+	
+	/**
+	 * Returns whether this there is any data matrix containing data for taxa itStart through itEnd inclusive.
+	 */
+	public boolean taxaHaveAnyData( int itStart, int itEnd){
+		int numMatrices = getProject().getNumberCharMatrices(null, this, CharacterData.class, true);
+		for (int iM = 0; iM < numMatrices; iM++){
+			CharacterData data = getProject().getCharacterMatrixVisible( this, iM, CharacterData.class);
+			if (data.hasDataForTaxa(itStart, itEnd))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * sets whether this taxa is marked as a duplicate of another. This is used
+	 * for merging taxa and subsequently saving the file. The system is kludgey
+	 * and may change
+	 */
+	public void setDuplicate(boolean dup) {
+		this.duplicate = dup;
+	}
+
+	/* ---------------- for HNode interface ---------------------- */
+	public boolean getHShow() {
+		return true;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/TaxaBitsSet.java b/Source/mesquite/lib/TaxaBitsSet.java
new file mode 100644
index 0000000..b606115
--- /dev/null
+++ b/Source/mesquite/lib/TaxaBitsSet.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ======================================================================== */
+/** A specset with bit information about taxa.   Called "taxa bits set" because it amounts to a selection (bit on = yes, bit off  = no)
+for a whole list of taxa.  It is abstract because it doesn't define cloneSpecsSet  */
+public abstract class TaxaBitsSet extends BitsSpecsSet implements TaxaSpecsSet { //should extend a generic BitsSpecsSet
+	Taxa taxa;
+	public TaxaBitsSet(String name, int numTaxa, Taxa taxa){
+		super(name, numTaxa);
+		this.taxa = taxa;
+	}
+	public String getTypeName(){
+		return "Taxa bits set";
+	}
+ 	/*.................................................................................................................*/
+	public Taxa getTaxa(){
+		return taxa;
+	}
+ 	/*.................................................................................................................*/
+	/** Add num taxa just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		setDirty(true);
+		return super.addParts(starting, num);
+	}
+	/*.................................................................................................................*/
+	/** Delete num Taxa beginning and including character "starting"*/
+	public boolean deleteParts(int starting, int num){  
+		setDirty(true);
+		return super.deleteParts(starting, num);
+	}
+	/*.................................................................................................................*/
+	public boolean moveParts(int first, int num, int justAfter){  
+		setDirty(true);
+		return super.moveParts(first, num, justAfter);
+	}
+	/*.................................................................................................................*/
+	public boolean swapParts(int first, int second){  
+		setDirty(true);
+		return super.swapParts(first, second);
+	}
+	/*.................................................................................................................*/
+	public String getStringList(String delimiter, boolean simplify){  
+		StringBuffer sb= new StringBuffer();
+		boolean first = true;
+		for (int i=0; i<getNumberOfParts(); i++)
+			if (isPresent(i))
+				if (first){
+					sb.append(taxa.getName(i));
+					first = false;
+				}
+				else
+					sb.append(delimiter + taxa.getName(i));
+		return sb.toString();
+
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/TaxaBlock.java b/Source/mesquite/lib/TaxaBlock.java
new file mode 100644
index 0000000..2ed9da4
--- /dev/null
+++ b/Source/mesquite/lib/TaxaBlock.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import mesquite.lib.duties.*;
+
+//Moved into mesquite.lib 13 Dec 01
+/*===============================================*/
+public class TaxaBlock extends NexusBlock {
+	Taxa taxa = null;
+	public TaxaBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public boolean mustBeAfter(NexusBlock block){ //� 13 Dec 01
+		if (block==null)
+			return false;
+		return block.getBlockName().equalsIgnoreCase("AUTHORS");
+		
+	}
+	public void written() {
+		taxa.setDirty(false);
+	}
+	public String getBlockName(){
+		return "TAXA";
+	}
+	public boolean contains(FileElement e) {
+		return e!=null && taxa == e;
+	}
+	public void setTaxa(Taxa taxa) {
+		this.taxa = taxa;
+	}
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	public String getName(){
+		if (taxa==null)
+			return "empty taxa block";
+		else
+			return "Taxa block: " + taxa.getName();
+	}
+	public String getNEXUSBlock(){
+		if (taxa==null)
+			return null;
+		else
+			return ((TaxaManager)getManager()).getTaxaBlock(taxa, this, getFile());
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaDisplay.java b/Source/mesquite/lib/TaxaDisplay.java
new file mode 100644
index 0000000..309d22e
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDisplay.java
@@ -0,0 +1,249 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** The panel in which taxa are drawn.  This is used within a taxon window, and can be used by other
+modules.  A TaxaDisplay is created
+and supervised by a taxon draw coordinator module.  A reference to a TaxaDisplay is needed 
+for shading and decorating the taxa. <P>
+
+Note that this is parallel to TreeDisplay
+*/
+public class TaxaDisplay extends TaxaTreeDisplay  {
+	DrawNamesTaxaDisplay namesTask;
+	/**  The panel in which the taxa are actually drawn.*/
+	private TaxaDrawing taxaDrawing;
+	
+	public TaxaDisplay (MesquiteModule ownerModule, Taxa taxa) { 
+		super(ownerModule,taxa);
+	}
+	
+	public void setTaxaDrawing(TaxaDrawing td) {
+		taxaDrawing = td;
+//		if (taxaDrawing!=null && taxa!=null)
+//			setTaxa(taxa);
+	}
+	public TaxaDrawing getTaxaDrawing() {
+		return taxaDrawing;
+	}
+	   
+	public DrawNamesTaxaDisplay getDrawTaxonNames(){
+		return namesTask;
+	}
+	public void setDrawTaxonNames(DrawNamesTaxaDisplay dtn){
+		namesTask = dtn;
+	}
+	public void setDrawingInProcess(boolean inProgress){
+		this.inProgress= inProgress;
+//		if (!inProgress && holdingTaxa != null) {
+//			setTaxa(holdingTaxa);
+			//repaint();
+//		}
+	}
+	public void redoCalculations(int code){
+		if (taxaDrawing!=null)
+			taxaDrawing.recalculatePositions(taxa); //to force node locs recalc
+		
+	}
+	public void addExtra(TaxaDisplayExtra extra) {
+		if (extras != null)
+			extras.addElement(extra, false);
+	}
+	public void removeExtra(TaxaDisplayExtra extra) {
+		if (extras != null)
+			extras.removeElement(extra, false);
+	}
+	public boolean findExtra(TaxaDisplayExtra extra) {
+		if (extras == null)
+			return false;
+		return (extras.indexOf(extra) >= 0);
+	}
+	public TaxaDisplayExtra[] getMyExtras(MesquiteModule mb) {
+		if (extras != null) {
+			int count = 0;
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+			   	if (ex.getOwnerModule() == mb) 
+			   		 count++;
+		 	}
+		 	if (count == 0)
+		 		return null;
+		 	TaxaDisplayExtra[] ee = new TaxaDisplayExtra[count];
+			e = extras.elements();
+			count = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+			   	if (ex.getOwnerModule() == mb) 
+			   		ee[count++] = ex;
+		 	}
+		 	return ee;
+		}
+		return null;
+	}
+	public void setTaxaAllExtras(Taxa taxa) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+			   	if (ownerModule==null || ownerModule.isDoomed()) 
+			   		return;
+	 			ex.setTaxa(taxa);
+		 	}
+		}
+	}
+	public void drawAllBackgroundExtrasOfPlacement(Taxa taxa, Graphics g, int placement) {
+		if (taxa.isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+	 			if (ex instanceof TaxaDisplayBkgdExtra && ex.getPlacement()==placement) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.drawOnTaxa(taxa, g);
+	 			}
+	 		}
+		}
+	}
+	public void drawAllBackgroundExtras(Taxa taxa, Graphics g) {
+		drawAllBackgroundExtrasOfPlacement(taxa,g,TaxaDisplayExtra.BELOW);
+		drawAllBackgroundExtrasOfPlacement(taxa,g,TaxaDisplayExtra.NORMAL);
+		drawAllBackgroundExtrasOfPlacement(taxa,g,TaxaDisplayExtra.ABOVE);
+	}
+	public void drawAllExtras(Taxa taxa, Graphics g) {
+		if (taxa.isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+	 			if (!(ex instanceof TaxaDisplayBkgdExtra)) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.drawOnTaxa(taxa, g);
+	 			}
+	 		}
+		}
+		if (notice!=null)
+			g.drawString(notice, 6, getBounds().height-6);
+		if (drawFrame)
+			g.drawRoundRect(0, 0, getBounds().width, getBounds().height, 10, 10);
+	}
+	public void printAllBackgroundExtras(Taxa taxa, Graphics g) {
+		if (taxa.isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+	 			if (ex instanceof TaxaDisplayBkgdExtra) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.printOnTaxa(taxa, g);
+	 			}
+	 		}
+		}
+	}
+	public void printAllExtras(Taxa taxa, Graphics g) {
+		if (taxa.isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+	 			if (!(ex instanceof TaxaDisplayBkgdExtra)) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.printOnTaxa(taxa, g);
+	 			}
+	 		}
+		}
+	}
+	public void moveExtraToFront(TaxaDisplayExtra extra){
+		if (extra == null)
+			return;
+		Vector panels = extra.getPanels();
+		for (int i=0; panels !=null && i<panels.size(); i++) {
+			Panel p = (Panel)panels.elementAt(i);
+			remove(p);
+			add(p);
+		}
+		getExtras().removeElement(extra, false);
+		getExtras().addElement(extra, false);
+		pleaseUpdate(false);
+	}
+	
+	public String getTextVersion() {
+		if (taxaDrawing == null)
+			return "";
+		String s="";
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+				if (ex!=null){
+					String sEx =null;
+					sEx = ex.infoAtNodes(taxa);
+		 			if (!StringUtil.blank(sEx)) {
+						String owner = "";
+						if (ex.getOwnerModule()!=null)
+							owner = ex.getOwnerModule().getName();
+						s+= "\n\n--------------- " + owner + " ---------------";
+		 				s+= "\n\n"+ sEx + "\n";
+		 			}
+	 			}
+	 		}
+		}
+		return s;
+	}
+	public void dispose(){
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w!=null)
+			w.waitUntilDisposable();
+		
+		ownerModule =null;
+		if (taxaDrawing !=null)
+			taxaDrawing.dispose();
+		taxaDrawing = null;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TaxaDisplayExtra ex = (TaxaDisplayExtra)obj;
+	 			ex.dispose();
+	 		}
+		}
+		destroyExtras();
+		extras = null;
+		super.dispose();
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/TaxaDisplayActive.java b/Source/mesquite/lib/TaxaDisplayActive.java
new file mode 100644
index 0000000..639cd6a
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDisplayActive.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+public interface TaxaDisplayActive    {
+   	 public boolean mouseDownInTaxaDisplay(int modifiers, int x, int y, TaxaDisplay taxaDisplay, Graphics g);
+   	 public boolean mouseUpInTaxaDisplay(int modifiers, int x, int y, TaxaDisplay taxaDisplay, Graphics g);
+   	 public boolean mouseMoveInTaxaDisplay(int modifiers, int x, int y, TaxaDisplay taxaDisplay, Graphics g);
+   	 public boolean mouseDragInTaxaDisplay(int modifiers, int x, int y, TaxaDisplay taxaDisplay, Graphics g);
+}
+
+
diff --git a/Source/mesquite/lib/TaxaDisplayBkgdExtra.java b/Source/mesquite/lib/TaxaDisplayBkgdExtra.java
new file mode 100644
index 0000000..e878a48
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDisplayBkgdExtra.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of TaxaDisplayExtra.  Used only so that taxon drawing knows to call these before the taxa
+is drawn.. */
+public abstract class TaxaDisplayBkgdExtra extends TaxaDisplayExtra {
+	public TaxaDisplayBkgdExtra (MesquiteModule ownerModule, TaxaDisplay taxaDisplay) {
+		super(ownerModule, taxaDisplay);
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaDisplayDrawnExtra.java b/Source/mesquite/lib/TaxaDisplayDrawnExtra.java
new file mode 100644
index 0000000..fd49009
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDisplayDrawnExtra.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of TaxaDisplayExtra.  Used only so that taxa drawing knows that these are drawn above the
+taxa and can be reordered.. */
+public abstract class TaxaDisplayDrawnExtra extends TaxaDisplayExtra {
+	public TaxaDisplayDrawnExtra (MesquiteModule ownerModule, TaxaDisplay taxaDisplay) {
+		super(ownerModule, taxaDisplay);
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaDisplayExtra.java b/Source/mesquite/lib/TaxaDisplayExtra.java
new file mode 100644
index 0000000..37fe0c9
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDisplayExtra.java
@@ -0,0 +1,164 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/** A class used for additional graphical and calculations elements to be drawn and calculated within 
+TaxaDisplays -- The TaxaDisplayExtra is notified when the cursor 
+is moved over a branch and so on, and when the window is drawn the TaxaDisplayExtra is notified via drawOnTaxa so that
+it can add its items to the taxa.*/
+public abstract class TaxaDisplayExtra implements Listable, OwnedByModule {  
+	public TaxaDisplay taxaDisplay;
+	public MesquiteModule ownerModule;
+	public static long totalCreated = 0;
+	public static int BELOW = 1;
+	public static int NORMAL = 2;
+	public static int ABOVE = 3;
+	int placement=NORMAL;
+	
+	private Vector panels = new Vector();
+	public TaxaDisplayExtra (MesquiteModule ownerModule, TaxaDisplay taxaDisplay) {
+		this.taxaDisplay = taxaDisplay;
+		this.ownerModule=ownerModule;
+		totalCreated++;
+	}
+	
+	public MesquiteModule getOwnerModule(){
+		return ownerModule;
+	}
+	
+	public String getName(){
+		if (ownerModule !=null)
+			return ownerModule.getName();
+		else
+			return getClass().getName();
+	}
+
+	public int getPlacement(){
+		return placement;
+	}
+
+	public void setPlacement(int placement){
+		this.placement = placement;
+	}
+	
+	public TaxaDisplay getTaxaDisplay(){
+		return taxaDisplay;
+	}
+	public void dispose(){
+		ownerModule =null;
+		taxaDisplay=null;
+	}
+	/**notifies the TaxaDisplayExtra that the taxa have changed, so it knows to redo calculations, and so on*/
+	public abstract void setTaxa(Taxa taxa);
+	/**draw on the taxa passed*/
+	public abstract void drawOnTaxa(Taxa taxa, Graphics g);
+	/**print on the taxa passed*/
+	public abstract void printOnTaxa(Taxa taxa, Graphics g);
+
+	/**simply fills the graphics used for the taxon with the current color; used for inverting*/
+	public void fillTaxon(Taxa taxa, Graphics g, int it){}
+	
+	/**returns whether or not the point x, y is in within this extra's graphics for this taxon*/
+	public boolean pointInTaxon(Taxa taxa, int it, int x, int y){
+		return false;
+	}
+
+	/**returns whether or not the taxon is in the bounds specified*/
+	public boolean taxonInRectangle(Taxa taxa, int it, int x1, int y1, int x2, int y2){
+		return false;
+	}
+	
+	/**return a text version of information on taxa*/
+	private String textOnTaxon(Taxa taxa, int it){
+		String s="";
+		s+="[" + textAtNode(it) + "]";
+		return s;
+	}
+	/**return a text version of information on taxa*/
+	private void textOnTaxon(Taxa taxa, int it, String[] nodeStrings){
+		nodeStrings[it]= textAtNode(it);
+	}
+	/**return a text version of information on taxa, displayed as list of nodes with information at each*/
+	public String infoAtNodes(Taxa taxa){
+		String legend = textForLegend();
+		String notes = additionalText(taxa);
+		if (StringUtil.blank(notes))
+			notes = legend;
+		else
+			notes = legend + "\n" + notes;
+		if (!StringUtil.blank(notes))
+			return notes;
+		
+		return "";
+	}
+	/** Returns true if this extra wants the taxon to have its name underlined */
+	public boolean getTaxonUnderlined(Taxon taxon){
+		return false;
+	}
+	/** Returns the color the extra wants the taxon name colored.*/
+	public Color getTaxonColor(Taxon taxon){
+		return null;
+	}
+	/** Returns any strings to be appended to taxon name.*/
+	public String getTaxonStringAddition(Taxon taxon){
+		return null;
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(int it){
+		return "";
+	}
+	/**return text to be placed in legends*/
+	public String textForLegend(){
+		return "";
+	}
+	/**return any additional explanatory text, e.g. if there is extensive information too verbose for a legend but which should be output to text view*/
+	public String additionalText(Taxa taxa){
+		return "";
+	}
+
+	public void cursorEnterTaxon(int M, Graphics g){}
+	/**to inform TaxaDisplayExtra that cursor has just exited name of terminal taxon M*/
+	public void cursorExitTaxon(int M, Graphics g){}
+	/**to inform nDisplayExtra that cursor has just touched name of terminal taxon M*/
+	public void cursorTouchTaxon(int M, Graphics g){}
+	
+	public void addPanelPlease(Panel p){
+		panels.addElement(p);
+		taxaDisplay.addPanelPlease(p);
+	}
+	public void removePanelPlease(Panel p){
+		if (panels !=null)
+			panels.removeElement(p);
+		if (taxaDisplay != null)
+			taxaDisplay.removePanelPlease(p);
+	}
+	protected Vector getPanels(){
+		return panels;
+	}
+
+	public void turnOff() {
+		if (taxaDisplay==null)
+			return;
+		taxaDisplay.removeExtra(this);
+		taxaDisplay.repaint();
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/TaxaDrawing.java b/Source/mesquite/lib/TaxaDrawing.java
new file mode 100644
index 0000000..5adb857
--- /dev/null
+++ b/Source/mesquite/lib/TaxaDrawing.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ��������������������������� taxa ������������������������������� */
+/* ======================================================================== */
+/**This is the base class for the drawing of taxa.  It contains the information about
+the number of nodes, and the x and y positions of the nodes.  It should be subclassed by taxa drawing modules, 
+so that they can add their own needed field.  TaxaDrawings are typically used within TaxaDisplays.*/
+
+public abstract class TaxaDrawing  {
+	public int[] x; //x positions of taxa
+	public int[] y; //y positions of taxa
+	public double[] z; //z positions of taxa (closeness to viewer, smaller numbers closer)
+	public int[] lineBaseX; //base of line on which to draw labels etc.
+	public int[] lineBaseY; 
+	public int[] lineTipX; //tip of line on which to draw labels etc.
+	public int[] lineTipY; 
+	/**labelOrientation indicates where label is to be drawn, in degrees. 0 = normal horizontal 
+	writing to right of node, as would be done for a tree with orientation RIGHT.
+	This does not represent simple rotation, i.e. 180 is on left side, but the writing is not upside down.  Thus
+	0 would be appropriate for tree oriented RIGHT, 90 for tree DOWN, 180 for tree LEFT, 270 for tree UP */
+	public int[] labelOrientation; 
+	
+	/** namesAngle indicates rotation of names from default in radians  (useful only for Java 1.2 or higher)*/
+	public double namesAngle = MesquiteDouble.unassigned;
+
+	public int numTaxa;
+	public TaxaDisplay taxaDisplay;//TODO: many of these should be private fields!!!
+	private int enableTerminalBoxesRequests = 0;
+	public static long totalCreated = 0;
+	public Polygon[] namePolys;
+	
+	public TaxaDrawing (TaxaDisplay taxaDisplay, int numTaxa) {
+		this.taxaDisplay = taxaDisplay;
+		totalCreated++;
+		resetNumTaxa(numTaxa);
+	}
+	public void addOneTaxon(){
+		if (x != null)
+			return;
+		numTaxa++;
+		totalCreated++;
+		x = IntegerArray.copyIntoDifferentSize(x,numTaxa,0);
+		y = IntegerArray.copyIntoDifferentSize(y,numTaxa,0);
+		z = DoubleArray.copyIntoDifferentSize(z,numTaxa,MesquiteDouble.unassigned);
+		labelOrientation = IntegerArray.copyIntoDifferentSize(labelOrientation,numTaxa,MesquiteInteger.unassigned);
+		lineBaseX = IntegerArray.copyIntoDifferentSize(lineBaseX,numTaxa,0);
+		lineBaseY = IntegerArray.copyIntoDifferentSize(lineBaseY,numTaxa,0);
+		lineTipX = IntegerArray.copyIntoDifferentSize(lineTipX,numTaxa,0);
+		lineTipY = IntegerArray.copyIntoDifferentSize(lineTipY,numTaxa,0);
+	}
+	public void resetNumTaxa(int numTaxa){
+		if (this.numTaxa == numTaxa && x != null)
+			return;
+		this.numTaxa=numTaxa;
+		totalCreated++;
+		x = new int[numTaxa];
+		y = new int[numTaxa];
+		z = new double[numTaxa];
+		labelOrientation = new int[numTaxa];
+		lineBaseX = new int[numTaxa];
+		lineBaseY = new int[numTaxa];
+		lineTipX = new int[numTaxa];
+		lineTipY = new int[numTaxa];
+		for (int i=0; i<numTaxa; i++) {
+			x[i]=0;
+			y[i]=0;
+			z[i]=MesquiteInteger.unassigned;
+			lineBaseX[i]=0;
+			lineBaseY[i]=0;
+			lineTipX[i]=0;
+			lineTipY[i]=0;
+			labelOrientation[i] = MesquiteInteger.unassigned;
+		}
+	}
+
+
+	/** Sets the taxa.  This is done outside of a paint() call, and is the place that any complex calculations should be performed! */
+	public abstract void recalculatePositions(Taxa taxa) ;
+
+	/** asks if the point is within "distance" of the location of the taxon */
+	public boolean locationNearTaxon(int it, int distance, int x, int y){
+		if (it<0 || it>=numTaxa)
+			return false;
+		return (Math.abs(this.x[it]-x)<=distance && Math.abs(this.y[it]-y)<=distance );
+	}
+
+	/** Draw taxa in graphics context */
+	public abstract void drawTaxa(Taxa taxa, Graphics g) ;
+	
+	/** Put in a request to enable terminal boxes (this allows taxon names to be drawn to leave room)*/
+	public void incrementEnableTerminalBoxes(){
+		enableTerminalBoxesRequests++;
+	}
+	/** Withdraw request to enable terminal boxes (this allows taxon names to be drawn to leave room)*/
+	public void decrementEnableTerminalBoxes(){
+		enableTerminalBoxesRequests--;
+		if (enableTerminalBoxesRequests<0)
+			enableTerminalBoxesRequests=0;
+	}
+	/** Returns if terminal boxes requested*/
+	public boolean terminalBoxesRequested(){
+		return (enableTerminalBoxesRequests>0);
+	}
+	/** Fill terminal box with current color. */
+	public abstract void fillTerminalBox(Taxa taxa, int node, Graphics g);
+	
+	/** Fill terminal box of node "node" with indicated set of colors */
+	public abstract void fillTerminalBoxWithColors(Taxa taxa, int node, ColorDistribution colors, Graphics g);
+	
+	/** Find which terminal box is at x,y */
+	public abstract int findTerminalBox(Taxa taxa, int x, int y);
+	
+	
+
+	
+	public void setHighlightsOn(boolean on){
+		/*
+		if (on) {
+			if (highlightThread==null) 
+				highlightThread = new HighlightThread(taxaDisplay);
+			if (!highlightThread.isOn())
+				highlightThread.start();
+		}
+		else {
+			if (highlightThread!=null) {
+				highlightThread.stop();
+				highlightThread.dispose();
+			}
+			highlightThread = null;
+		}
+		*/
+		
+	}
+	public boolean getHighlightsOn(){
+		return false;
+		//return (highlightThread!=null);
+	}
+	public void dispose(){
+		taxaDisplay = null;
+		setHighlightsOn(false);
+	}
+	public void finalize() throws Throwable {
+		setHighlightsOn(false);
+		super.finalize();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TaxaGroup.java b/Source/mesquite/lib/TaxaGroup.java
new file mode 100644
index 0000000..1e96621
--- /dev/null
+++ b/Source/mesquite/lib/TaxaGroup.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+import mesquite.lists.lib.GroupDialog;
+
+
+/* ======================================================================== */
+/** DOCUMENT.*/
+public class TaxaGroup extends GroupLabel {
+	Taxa taxa;
+	public TaxaGroup(Taxa taxa) {
+		this.taxa = taxa;
+	}
+	public TaxaGroup() {
+	}
+	public static boolean supportsSymbols() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public static TaxaGroup makeGroup(MesquiteModule mod, String name, Taxa taxa, TaxaGroupVector groups){
+		TaxaGroup group = new TaxaGroup(taxa);
+		group.setName(name);
+		group.addToFile(taxa.getFile(), mod.getProject(), null);
+		if (groups.indexOf(group)<0) 
+			groups.addElement(group, false);
+		return group;
+	}
+	/*.................................................................................................................*/
+	public void editMe(){
+		GroupDialog d = new GroupDialog(getProject(),getProject().getCoordinatorModule().containerOfModule(), "Edit Taxa Group", getName(), getColor(), getSymbol(), supportsSymbols());
+
+		d.completeAndShowDialog();
+		name = d.getName();
+		boolean ok = d.query()==0;
+		Color c = d.getColor();
+		MesquiteSymbol symbol = d.getSymbol();
+		d.dispose();
+		if (!ok)
+			return;
+
+		if (!StringUtil.blank(name)) {
+			setName(name);
+			setColor(c);
+			if (symbol!=null)
+				setSymbol(symbol);
+			if (taxa!=null)
+				taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+			notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		}
+
+	}
+
+}
+
diff --git a/Source/mesquite/lib/TaxaGroupVector.java b/Source/mesquite/lib/TaxaGroupVector.java
new file mode 100644
index 0000000..ae654f3
--- /dev/null
+++ b/Source/mesquite/lib/TaxaGroupVector.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+/** DOCUMENT.*/
+public class TaxaGroupVector extends ListableVector {
+	public TaxaGroupVector(){
+		super();
+		setName("Taxa Groups");
+
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaInclusionSet.java b/Source/mesquite/lib/TaxaInclusionSet.java
new file mode 100644
index 0000000..f0992c4
--- /dev/null
+++ b/Source/mesquite/lib/TaxaInclusionSet.java
@@ -0,0 +1,56 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ======================================================================== */
+/** A taxon inclusion set.   */
+public class TaxaInclusionSet extends TaxaBitsSet { 
+	public TaxaInclusionSet(String name, int numTaxa, Taxa taxa){
+		super(name, numTaxa, taxa);
+	}
+	public String getTypeName(){
+		return "Taxon Inclusion set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		TaxaInclusionSet bss = new TaxaInclusionSet("cloned", getNumberOfParts(), taxa);
+		for (int i=0; i< getNumberOfParts(); i++) {
+			bss.setSelected(i, isBitOn(i));
+		}
+		return bss;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof Taxa))
+			return null;
+		TaxaInclusionSet tis = new TaxaInclusionSet("Inclusion Set", numParts, (Taxa)parent);
+		tis.selectAll();
+		return tis;
+	}
+	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		boolean success = super.addParts(starting, num); 
+		if (success) {
+			for (int i=starting+1; i< starting+num+1; i++) //default is for the bit to be set
+				setSelected(i, true);
+		}
+		return success;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/TaxaPartition.java b/Source/mesquite/lib/TaxaPartition.java
new file mode 100644
index 0000000..d00c246
--- /dev/null
+++ b/Source/mesquite/lib/TaxaPartition.java
@@ -0,0 +1,165 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ======================================================================== */
+/**A TaxaPartition is a specification of which property applies to each taxon (TAXAPARTITION in NEXUS file format).
+  */
+
+public class TaxaPartition  extends ObjectSpecsSet {
+	Taxa taxa;
+	public TaxaPartition (String name, int numTaxa, Object defaultProperty, Taxa taxa) {
+		super(name, numTaxa, defaultProperty);
+		this.taxa = taxa;
+	}
+	public SpecsSet cloneSpecsSet(){
+		if (taxa==null)
+			return null;
+		TaxaPartition ms = new TaxaPartition(new String(name), taxa.getNumTaxa(), getDefaultProperty(), taxa);
+		for (int i=0; i<getNumberOfParts(); i++)
+			ms.setProperty(getProperty(i), i);
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof Taxa))
+			return null;
+		return new TaxaPartition("Inclusion Set", numParts, getDefaultProperty(), (Taxa)parent);
+	}
+	public Taxa getTaxa(){
+		return taxa;
+	}
+	public String getTypeName(){
+		return "Taxa partition";
+	}
+	/*
+	public int getMaxPartitionNumber(){//NOT USED (Jan 01)
+		int max = MesquiteInteger.unassigned;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null)
+				max = MesquiteInteger.maximum(max, mq.getGroupNumber());
+		}
+		return max;
+	}
+	/**Returns an array of all the partition numbers*
+	public int[] getGroupNumbers(){//NOT USED (Jan 01)
+		int[] temp = new int[getNumberOfParts()];
+		int next = 0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null) {
+				int q = mq.getGroupNumber();
+				if (IntegerArray.indexOf(temp, q)<0){
+					temp[next++]=q;
+				}
+			}
+		}
+		if (next==0)
+			return null;
+		int[] result = new int[next];
+		for (int i=0; i<result.length; i++)
+			result[i]=temp[i];
+		
+		return result;
+	}
+	/**Returns an array of all the partition numbers*/
+	public int getNumberOfGroups(){
+		TaxaGroup[] temp = new TaxaGroup[getNumberOfParts()];
+		int next = 0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null) {
+				if (ObjectArray.indexOf(temp, mq)<0){
+					temp[next++]=mq;
+				}
+			}
+		}
+		return next;
+	}
+	/**Returns an array of all the partition numbers*/
+	public TaxaGroup[] getGroups(){
+		TaxaGroup[] temp = new TaxaGroup[getNumberOfParts()];
+		int next = 0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null) {
+				if (ObjectArray.indexOf(temp, mq)<0){
+					temp[next++]=mq;
+				}
+			}
+		}
+		if (next==0)
+			return null;
+		TaxaGroup[] result = new TaxaGroup[next];
+		for (int i=0; i<result.length; i++)
+			result[i]=temp[i];
+		
+		return result;
+	}
+	/*
+	public TaxaGroup getGroup(int groupNumber){
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null && mq.getGroupNumber()==groupNumber)
+				return mq;
+		}
+		return null;
+	}
+	
+	public TaxaGroup getGroup(String name){
+		if (name==null)
+			return null;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq!=null && name.equalsIgnoreCase(mq.getName()))
+				return mq;
+		}
+		return null;
+	}*/
+  	/*.................................................................................................................*/
+	/**/
+	public int getNumberInGroup(TaxaGroup target){
+		int num =0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			TaxaGroup mq = getTaxaGroup(i);
+			if (mq==target)
+				num++;
+		}
+		return num;
+	}
+ 	/*.................................................................................................................*/
+ 	/** gets storage for set of properties*/
+	public Object[] getNewPropertyStorage(int numParts){
+		return new TaxaGroup[numParts];
+	}
+	
+	
+	public TaxaGroup getTaxaGroup(int part){
+		return (TaxaGroup)getProperty(part);
+	}
+	public TaxaGroup getTaxaGroup(Taxon taxon){
+		int it = taxa.whichTaxonNumber(taxon);
+		if (it>=0)
+			 return (TaxaGroup)getProperty(it);
+		else
+			return null;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/TaxaSelectionSet.java b/Source/mesquite/lib/TaxaSelectionSet.java
new file mode 100644
index 0000000..3bc3d0e
--- /dev/null
+++ b/Source/mesquite/lib/TaxaSelectionSet.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ======================================================================== */
+/** A taxon set. */
+public class TaxaSelectionSet extends TaxaBitsSet { 
+	public TaxaSelectionSet(String name, int numTaxa, Taxa taxa){
+		super(name, numTaxa, taxa);
+	}
+	public String getTypeName(){
+		return "Taxon Selection set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		TaxaSelectionSet bss = new TaxaSelectionSet("cloned", getNumberOfParts(), taxa);
+		for (int i=0; i< getNumberOfParts(); i++) {
+			bss.setSelected(i, isBitOn(i));
+		}
+		return bss;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof Taxa))
+			return null;
+		return new TaxaSelectionSet("Selection Set", numParts, (Taxa)parent);
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaSpecsSet.java b/Source/mesquite/lib/TaxaSpecsSet.java
new file mode 100644
index 0000000..d731391
--- /dev/null
+++ b/Source/mesquite/lib/TaxaSpecsSet.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ======================================================================== */
+/** */
+public interface TaxaSpecsSet extends Listable {	
+ 	/*.................................................................................................................*/
+	/** Add num taxa just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Delete taxa specified  */
+	public boolean deleteParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Move num taxa starting at first, to just after taxon justAfter  */
+	public boolean moveParts(int first, int num, int justAfter);
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public boolean swapParts(int first, int second);
+	
+	public Taxa getTaxa();
+}
+
+
diff --git a/Source/mesquite/lib/TaxaStringsSet.java b/Source/mesquite/lib/TaxaStringsSet.java
new file mode 100644
index 0000000..74da0c0
--- /dev/null
+++ b/Source/mesquite/lib/TaxaStringsSet.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+import mesquite.lib.characters.CharactersGroup;
+
+/* ======================================================================== */
+/** A specset with bit information about taxa.   Called "taxa String set" because it stores a string for each of
+for a whole list of taxa.  It is abstract because it doesn't define cloneSpecsSet  */
+public class TaxaStringsSet extends ObjectSpecsSet implements TaxaSpecsSet { //should extend a generic BitsSpecsSet
+	Taxa taxa;
+	String typeName = "Taxa String set";
+	public TaxaStringsSet(String name, int numTaxa, Taxa taxa){
+		super(name, numTaxa, "");
+		this.taxa = taxa;
+	}
+	public String getTypeName(){
+		return typeName;
+	}
+	public void setTypeName(String typeName){
+		this.typeName = typeName;
+	}
+	public SpecsSet cloneSpecsSet(){
+		TaxaStringsSet s = new TaxaStringsSet(name, numParts, taxa);
+		for (int i = 0; i< numParts; i++)
+			s.setProperty(getProperty(i), i);
+		return s;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int i){
+		if (!(parent instanceof Taxa))
+			return null;
+		TaxaStringsSet tis = new TaxaStringsSet("Alternative Naming", numParts, (Taxa)parent);
+		return tis;
+	}
+	/*.................................................................................................................*/
+ 	/** gets storage for set of properties*/
+	public Object[] getNewPropertyStorage(int numParts){
+		return new String[numParts];
+	}
+	/*.................................................................................................................*/
+	public Taxa getTaxa(){
+		return taxa;
+	}
+ 	/*.................................................................................................................*/
+	/** Add num taxa just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		setDirty(true);
+		return super.addParts(starting, num);
+	}
+	/*.................................................................................................................*/
+	/** Delete num Taxa beginning and including character "starting"*/
+	public boolean deleteParts(int starting, int num){  
+		setDirty(true);
+		return super.deleteParts(starting, num);
+	}
+	/*.................................................................................................................*/
+	public boolean moveParts(int first, int num, int justAfter){  
+		setDirty(true);
+		return super.moveParts(first, num, justAfter);
+	}
+	/*.................................................................................................................*/
+	public boolean swapParts(int first, int second){  
+		setDirty(true);
+		return super.swapParts(first, second);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TaxaTool.java b/Source/mesquite/lib/TaxaTool.java
new file mode 100644
index 0000000..7baa4cd
--- /dev/null
+++ b/Source/mesquite/lib/TaxaTool.java
@@ -0,0 +1,210 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+	/** This subclass of MesquiteTool is used in Taxon windows for manipulating the taxa, etc.  Each tool
+	represents a cursor in the tool palette.  Each has MesquiteCommands attached.<p>
+	When a cursor is chosen, its corresponding MesquiteTool is set as
+	the current tool.  The tool When a mousedown etc. event occurs on the taxa, the tool is passed the taxon and the mouse click 
+	parameters -- the branch first touched, the branch dropped upon, etc.  If the tool has a touchedCommand, or droppedCommand,
+	or touchedTaxonCommand, then this command is executed when the tool is informed of the event.  As argument to the command,
+	the branch number(s) are passed in a string.
+	*/
+public class TaxaTool extends MesquiteTool {
+	protected MesquiteCommand touchedCommand;
+	protected MesquiteCommand droppedCommand;
+	protected MesquiteCommand transferredCommand;
+	protected MesquiteCommand draggedCommand;
+	protected MesquiteCommand touchedTaxonCommand;
+	protected MesquiteCommand moveOverTaxonCommand;
+	protected MesquiteCommand draggedTaxonCommand;
+
+	protected MesquiteCommand mouseUpTaxonCommand;
+	protected MesquiteCommand touchedFieldCommand;
+	protected MesquiteCommand mouseUpFieldCommand;
+	protected MesquiteCommand movedCommand;
+	
+	protected boolean ignoreTaxa = false;
+
+
+	public TaxaTool (Object initiator,  String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String fullDescription, String explanation) {
+		super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation);
+	}
+
+	public void dispose(){ 
+		if (touchedCommand!=null) 
+			touchedCommand.dispose();
+		else if (droppedCommand!=null) 
+			droppedCommand.dispose();
+		else if (transferredCommand!=null) 
+			transferredCommand.dispose();
+		else if (draggedCommand!=null) 
+			draggedCommand.dispose();
+		else if (touchedTaxonCommand!=null) 
+			touchedTaxonCommand.dispose();
+		else if (moveOverTaxonCommand!=null) 
+			moveOverTaxonCommand.dispose();
+		else if (draggedTaxonCommand!=null)
+			draggedTaxonCommand.dispose();
+		else if (mouseUpTaxonCommand!=null)
+			mouseUpTaxonCommand.dispose();
+		else if (touchedFieldCommand!=null) 
+			touchedFieldCommand.dispose();
+		else if (mouseUpFieldCommand!=null) 
+			mouseUpFieldCommand.dispose();
+		else if (movedCommand != null)
+			movedCommand.dispose();
+		touchedCommand=null;
+		droppedCommand=null;
+		transferredCommand=null;
+		draggedCommand=null;
+		touchedTaxonCommand=null;
+		moveOverTaxonCommand = null;
+		mouseUpTaxonCommand=null;
+		touchedFieldCommand = null;
+		mouseUpFieldCommand = null;
+		draggedTaxonCommand = null;
+		movedCommand = null;
+		super.dispose();
+	}
+	public boolean getIgnoreTaxa() {
+		return (ignoreTaxa);
+	}
+	public void setIgnoreTaxa(boolean ignoreTaxa) {
+		this.ignoreTaxa = ignoreTaxa;
+	}
+	public boolean informTransfer() {
+		return (transferredCommand!=null);
+	}
+	public boolean informDrop() {
+		return (droppedCommand!=null);
+	}
+	public boolean informTouch() {
+		return (touchedCommand!=null);
+	}
+	public boolean informDrag() {
+		return (draggedCommand!=null);
+	}
+	public boolean informMove() {
+		return (movedCommand!=null);
+	}
+	public boolean informDragTaxon(){
+		return (draggedTaxonCommand!=null);
+	}
+	public boolean informTouchField() {
+		return (touchedFieldCommand!=null);
+	}
+	public boolean informMouseUpTaxon() {
+		return (mouseUpTaxonCommand!=null);
+	}
+	public boolean informMouseUpField() {
+		return (mouseUpFieldCommand!=null);
+	}
+	public void setTransferredCommand(MesquiteCommand transferredCommand){
+		this.transferredCommand = transferredCommand;
+	}
+	public void setTouchedCommand(MesquiteCommand touchedCommand){
+		this.touchedCommand = touchedCommand;
+	}
+	public void setDraggedCommand(MesquiteCommand draggedCommand){
+		this.draggedCommand = draggedCommand;
+		if (draggedCommand != null)
+			draggedCommand.setSuppressLogging(true);
+	}
+	public void setDroppedCommand(MesquiteCommand droppedCommand){
+		this.droppedCommand = droppedCommand;
+	}
+	public void setTouchedTaxonCommand(MesquiteCommand touchedTaxonCommand){
+		this.touchedTaxonCommand = touchedTaxonCommand;
+	}
+	public void setMoveOverTaxonCommand(MesquiteCommand moveOverTaxonCommand){
+		this.moveOverTaxonCommand = moveOverTaxonCommand;
+		if (moveOverTaxonCommand != null)
+			moveOverTaxonCommand.setSuppressLogging(true);
+	}
+	public void setMouseUpTaxonCommand(MesquiteCommand mouseUpTaxonCommand){
+		this.mouseUpTaxonCommand = mouseUpTaxonCommand;
+	}
+	public void setDraggedTaxonCommand(MesquiteCommand draggedTaxonCommand){
+		this.draggedTaxonCommand = draggedTaxonCommand;
+		if (draggedTaxonCommand != null)
+			draggedTaxonCommand.setSuppressLogging(true);
+	}
+	public void setTouchedFieldCommand(MesquiteCommand touchedFieldCommand){
+		this.touchedFieldCommand = touchedFieldCommand;
+	}
+	public void setMouseUpFieldCommand(MesquiteCommand mouseUpFieldCommand){
+		this.mouseUpFieldCommand = mouseUpFieldCommand;
+	}
+	public void setMovedCommand(MesquiteCommand movedCommand){
+		this.movedCommand = movedCommand;
+		if (movedCommand != null)
+			movedCommand.setSuppressLogging(true);
+	}
+
+	public void taxonMoveOver (int M, int modifiers) {
+		if (moveOverTaxonCommand!=null)
+			moveOverTaxonCommand.doItMainThread(Integer.toString(M) + " "  + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", moveOverTaxonCommand, this), false, false);  
+	}
+
+	public void taxonTouched (int M, int modifiers) {
+		if (touchedTaxonCommand!=null)
+			touchedTaxonCommand.doItMainThread(Integer.toString(M) + " "  + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", touchedTaxonCommand, this), false, false);  
+	}
+	
+	
+	
+	public void taxonMouseUp (int M, int x, int y, int modifiers) {
+		if (mouseUpTaxonCommand!=null)
+			mouseUpTaxonCommand.doItMainThread(Integer.toString(M) + " "  + Integer.toString(x)+ " " + Integer.toString(y) + " "  + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", mouseUpTaxonCommand, this), false, false);  
+	}
+
+	public void taxonDragged (int M, int x, int y, int modifiers) {
+		if (draggedTaxonCommand!=null)
+			draggedTaxonCommand.doItMainThread(Integer.toString(M) + " "  + Integer.toString(x)+ " " + Integer.toString(y) + " " +MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", draggedTaxonCommand, this), false, false);  
+	}	
+	
+	
+	public boolean fieldTouched (int x, int y, int modifiers) {
+		if (touchedFieldCommand!=null) { 
+			touchedFieldCommand.doItMainThread(Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", touchedFieldCommand, this), false, false);  
+			return true;
+		}
+		else
+			return false;
+	}
+	public boolean fieldMouseUp (int x, int y, int modifiers) {
+		if (mouseUpFieldCommand!=null) { 
+			mouseUpFieldCommand.doItMainThread(Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", mouseUpFieldCommand, this), false, false);  
+			return true;
+		}
+		else
+			return false;
+	}
+	public boolean moved (int x, int y, int modifiers) {
+		if (movedCommand!=null) {
+			movedCommand.doItMainThread(Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", movedCommand, this), false, false);  
+			return true;
+		}
+		else
+			return false;
+	}
+}
+
diff --git a/Source/mesquite/lib/TaxaTreeDisplay.java b/Source/mesquite/lib/TaxaTreeDisplay.java
new file mode 100644
index 0000000..c1ad73b
--- /dev/null
+++ b/Source/mesquite/lib/TaxaTreeDisplay.java
@@ -0,0 +1,284 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** The panel in which taxa or trees are drawn.  Superclass to TreeDisplay and TaxaDisplay
+*/
+public abstract class TaxaTreeDisplay extends MesquitePanel  {
+	/** The taxa being drawn */
+	protected Taxa taxa;
+	
+	/**  TaxaDisplayExtras attached to this TaxaDisplay*/
+	protected ListableVector extras;
+	/**  This is part of system to record whether the taxa need redrawing, used so as to prevent multiple updates*/
+	protected int repaintsPending =0;
+	/**  Records whether or not the taxon names should be centered, if drawn in one plane, about axis of longest name*/
+	public boolean centerNames = false;
+	/**  Records whether or not the taxon names are to be drawn*/
+	public boolean suppressNames = false;
+	
+	/**  Records whether drawing is to be suppressed*/
+	protected boolean suppress = true;
+	
+	protected boolean paintedOnce = false;
+	/**  A notice that is drawn in the display.*/
+	protected String notice;
+	/**  Is a frame to be drawn in the TaxaDisplay?*/
+	protected boolean drawFrame=false;
+	/**  The area in which the taxa are drawn*/
+	Rectangle field;
+	/**  */
+	protected int taxonNameBuffer = 30;
+	/**  */
+	protected boolean inProgress = false;
+	/**  */
+	protected MesquiteModule ownerModule;
+	/**  */
+	public static long totalCreated;
+	/**  */
+	protected boolean isInvalid = false;
+	/**  */
+	protected boolean crossDrawn = false;
+	
+	public double[] nodeLocsParameters = new double[8]; //parameters for use by node locs module
+	public double[] drawParameters = new double[8];//parameters for use by draw taxon module
+	
+	static {
+		totalCreated = 0;
+	}
+	
+	public TaxaTreeDisplay (MesquiteModule ownerModule, Taxa taxa) { 
+		super();
+		setDontDuplicateCommands(true);
+		if (MesquiteTrunk.isMacOSX())
+			setMoveFrequency(4);
+		else
+			setMoveFrequency(0);
+		totalCreated++;
+		this.ownerModule=ownerModule;
+		field = new Rectangle();
+		extras = new ListableVector();
+		this.taxa = taxa;
+		setLayout(null);
+	}
+	
+	public MesquiteModule getOwnerModule(){
+		return ownerModule;
+	}
+	
+	public int getNumTaxa() {
+		return taxa.getNumTaxa();
+	}
+	public boolean getDrawingInProcess(){
+		return inProgress;
+	}
+	   
+	public void setDrawingInProcess(boolean inProgress){
+		this.inProgress= inProgress;
+	}
+	private boolean printing = false;
+	public boolean getPrintingInProcess(){
+		return printing;
+	}
+	public void setPrintingInProcess(boolean inProgress){
+		this.printing= inProgress;
+	}
+	public void suppressDrawing(boolean toSuppress) {
+		suppress=toSuppress;
+	}
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	public void setTaxa(Taxa taxa) {
+		this.taxa = taxa;
+	}
+	public boolean isCrossDrawn() {
+		return crossDrawn;
+	}
+
+	public void setCrossDrawn(boolean crossDrawn) {
+		this.crossDrawn = crossDrawn;
+	}
+
+	protected boolean redoCalculationsWaiting = false;
+	public void recalculatePositions() {
+		if (!inProgress){
+			try{
+				redoCalculations(12);
+
+				redoCalculationsWaiting = false;
+			}
+			catch (Exception e){
+			
+			}
+		}
+		else
+			redoCalculationsWaiting = true;
+	}
+	public void setTaxonNameBuffer(int b) {
+		taxonNameBuffer = b;
+	}
+	public int getTaxonNameBuffer() {
+		return taxonNameBuffer;
+	}
+	public void setInvalid(boolean iv) {  //this does not cause a redraw; simply posting a note.  Flag gets should be set to false in  drawing
+		this.isInvalid = iv;
+	}
+	public boolean getInvalid() { 
+		return isInvalid;
+	}
+	private void updateComponents(Container c){
+		Component[] cc = c.getComponents();
+		for (int i=0; i<cc.length; i++) {
+			cc[i].repaint();
+			if (cc[i] instanceof Container)
+				updateComponents((Container)cc[i]);
+		}
+	}
+	
+	public void repaintAll() {  //TODO: this whole system needs revamping.  
+		if (isVisible()) {
+			repaint();
+			updateComponents(this);
+		}
+	}
+	public void pleaseUpdate() {  //TODO: this whole system needs revamping.  
+		repaint();
+	}
+	public void pleaseUpdate(boolean resetElements) {  //TODO: this whole system needs revamping.  
+		repaint(resetElements);
+
+		MesquiteWindow mw = MesquiteWindow.windowOfItem(this);
+		if (mw !=null && mw.getMode()>0)
+			mw.updateTextPage();
+	}
+	public void repaint(boolean resetElements){
+		repaint();
+	}
+	public void repaint() {  //TODO: this whole system needs revamping.  
+		if (!isVisible())
+			return;
+		if (redoCalculationsWaiting){
+			try{
+			recalculatePositions();
+			}
+			catch (Exception e){
+			}
+			catch (Throwable e){
+			}
+		}
+		repaintsPending++;
+		if (repaintsPending<=1){
+			super.repaint();
+			crossDrawn=false;
+		}
+	}
+	public void setFrame(boolean doFrame) {
+		drawFrame = doFrame;
+	}
+	public void setSize(){
+		
+	}
+	public abstract void redoCalculations(int code);
+	
+	public void setFieldSize(int x, int y) {
+		boolean ch = (field.width!=x || field.height !=y);
+		field.width=x;
+		field.height=y;
+		if (ch)
+			redoCalculations(4); 
+	}
+	public void setFieldWidth(int x) {
+		boolean ch = (field.width!=x);
+		field.width=x;
+		if (ch)
+			redoCalculations(5); 
+	}
+	public void setFieldHeight(int y) {
+		boolean ch = (field.height !=y);
+		field.height=y;
+		if (ch)
+			redoCalculations(6); 
+	}
+	public int getFieldWidth() {
+		//return getBounds().width;
+		return field.width;
+	}
+	public int getFieldHeight() {
+		//return getBounds().width;
+		return field.height;
+	}
+	public Rectangle getField() { 
+		//return getBounds();
+		return field;
+	}
+
+	public void setNotice(String s) {
+		notice = s;
+	}
+	public ListableVector getExtras() {
+		return extras;
+	}
+	
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+	   	paintedOnce = true;
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void fillTaxon(Graphics g, int m){}
+	public void redrawTaxa(Graphics g, int M) {}
+
+	public boolean pointInTaxon(int m, int x, int y){return false;}
+	public boolean taxonInRectangle(Taxa taxa, int it, int x1, int y1, int x2, int y2){
+		return false;}
+
+	public void addPanelPlease(Panel p){
+		if (p==null)
+			return;
+		add(p);
+		MesquiteWindow window = MesquiteWindow.windowOfItem(this);
+		if (window !=null)
+			window.componentAdded(this, p);
+	}
+	public void removePanelPlease(Panel p){
+		if (p==null)
+			return;
+		remove(p);
+	}
+	public void addComponentPlease(Component p){
+		if (p==null)
+			return;
+		add(p);
+	}
+	public void removeComponentPlease(Component p){
+		if (p==null)
+			return;
+		remove(p);
+	}
+	public void destroyExtras(){
+		if (extras!=null)
+			extras.removeAllElements(true);
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/Taxon.java b/Source/mesquite/lib/Taxon.java
new file mode 100644
index 0000000..ed8ab3d
--- /dev/null
+++ b/Source/mesquite/lib/Taxon.java
@@ -0,0 +1,147 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ��������������������������� taxa ������������������������������� */
+/* ======================================================================== */
+/** A taxon, including the taxon name, its number, an other information (e.g., notes and pictures attached to it).*/
+public class Taxon  implements Listable, Illustratable, Identifiable {
+	private String name;
+	private int index = MesquiteInteger.unassigned;
+	public int number = 0; //not used
+	private Image illustration;
+	private String illustrationPath;
+	public static long totalCreated = 0;
+	public static long totalFinalized = 0;
+	private long id;
+	private String uniqueID;
+	private String link = null;
+	private Taxa taxa = null;
+	private boolean isDefaultName = true;
+	private String synonym = null;
+	//need footnotes etc.
+
+	public Taxon(Taxa taxa){
+		this.taxa = taxa;
+		totalCreated++;
+		id = totalCreated;
+		if (Taxa.inventUniqueIDs)
+			setUniqueID(MesquiteTrunk.getUniqueIDBase() + id);
+	}
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	public void finalize() throws Throwable {
+		totalFinalized++;
+		super.finalize();
+	}
+	public void setIndex(int index){
+		this.index = index;
+	}
+	public int getNumber(){
+		return getIndex();
+	}
+
+	public int getIndex(){
+		if (index != MesquiteInteger.unassigned && taxa.getTaxon(index) == this)
+			return index;
+		return taxa.whichTaxonNumberCheck(this);
+	}
+	public long getID() {
+		return id;
+	}
+	public String getUniqueID() {
+		return uniqueID;
+	}
+	public void setUniqueID(String s) {
+		uniqueID = s;
+	}
+	long nameChecksum = 0;
+	java.util.zip.CRC32 crc = new java.util.zip.CRC32();
+	
+	boolean nameIsNull = true;
+	public void setName(String name) {
+		this.name = name;
+		if (name == null){
+			nameChecksum = 0;
+			nameIsNull = true;
+		}
+		else {
+			nameIsNull = false;
+			crc.reset();
+			for (int i = 0; i< name.length(); i++)
+				crc.update(name.charAt(i));
+			nameChecksum = crc.getValue();
+		}
+		isDefaultName = false;
+	}
+	public long getNameChecksum(){
+		return nameChecksum;
+
+	}
+	public String getName() {
+		return name;
+	}
+	public void setNameIsDefault(boolean def){
+		isDefaultName = def;
+	}
+	public boolean isNameNull(){
+		return nameIsNull;
+	}
+	public boolean isNameDefault(){
+		return isDefaultName;
+	}
+	public void setSynonym(String name) {
+		this.synonym = name;
+	}
+	public String getSynonym() {
+		return synonym;
+	}
+	public void setLink(String link) {
+		this.link = link;
+	}
+	public String getLink() {
+		return link;
+	}
+	/**Translates internal numbering system to external (currently, 0 based to 1 based*/
+	public static int toExternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i+1;
+	}
+	/**Translates external numbering system to internal (currently, 1 based to 0 based*/
+	public static int toInternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i-1;
+	}
+	public void setIllustration(Image illustration, String path) {
+		this.illustration = illustration;
+		this.illustrationPath = path;
+	}
+	public String getIllustrationPath() {
+		return illustrationPath;
+	}
+	public Image getIllustration() {
+		return illustration;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TaxonNamer.java b/Source/mesquite/lib/TaxonNamer.java
new file mode 100644
index 0000000..1d74d3d
--- /dev/null
+++ b/Source/mesquite/lib/TaxonNamer.java
@@ -0,0 +1,32 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.categ.lib.DNAState;
+
+
+/* ======================================================================== */
+public abstract class TaxonNamer  {
+	public abstract boolean initialize(Taxa taxa);
+	public abstract String getNameToUse(Taxon taxon);
+	public abstract String getNameToUse(Taxa taxa, int it);
+
+	/** Given a taxon name "name", this method returns the taxon number this name represents. */
+	public abstract int whichTaxonNumber(Taxa taxa, String name);	
+
+
+}
+
+
diff --git a/Source/mesquite/lib/TaxonPair.java b/Source/mesquite/lib/TaxonPair.java
new file mode 100644
index 0000000..bc712c6
--- /dev/null
+++ b/Source/mesquite/lib/TaxonPair.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ��������������������������� taxon pair ������������������������������� */
+/* ======================================================================== */
+/** A pair of taxa.*/
+public class TaxonPair implements Listable  {
+	private Taxa taxa = null;
+	private Taxon[] pair= new Taxon[2];
+	
+	public TaxonPair(Taxa taxa, int t1, int t2){
+		this.taxa = taxa;
+		if (t1>=0 && t1<taxa.getNumTaxa())
+			pair[0] = taxa.getTaxon(t1);
+		if (t2>=0 && t2<taxa.getNumTaxa())
+			pair[1] = taxa.getTaxon(t2);
+	}
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	public void setTaxon(Taxon taxon1, Taxon taxon2) {
+		pair[0] = taxon1;
+		pair[1] = taxon2;
+	}
+	public Taxon getTaxon(int i) {
+		if (i>=0 && i<=1)
+			return pair[i];
+		else
+			return null;
+	}
+	public String getName() {
+		if (pair[0]!=null && pair[1]!=null)
+			return pair[0].getName() + "/" + pair[1].getName();
+		else
+			return "";
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TextCanvasWithButtons.java b/Source/mesquite/lib/TextCanvasWithButtons.java
new file mode 100644
index 0000000..c519e71
--- /dev/null
+++ b/Source/mesquite/lib/TextCanvasWithButtons.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.Button;
+import mesquite.lib.*;
+
+public class TextCanvasWithButtons {
+	Button button = null;
+	Button button2 = null;
+	MesquiteTextCanvas textCanvas = null;
+
+	public  TextCanvasWithButtons() {
+	}
+
+	public Button getButton() {
+		return button;
+	}
+
+	public void setButton(Button button) {
+		this.button = button;
+	}
+
+	public Button getButton2() {
+		return button2;
+	}
+
+	public void setButton2(Button button2) {
+		this.button2 = button2;
+	}
+
+	public MesquiteTextCanvas getTextCanvas() {
+		return textCanvas;
+	}
+
+	public void setTextCanvas(MesquiteTextCanvas textCanvas) {
+		this.textCanvas = textCanvas;
+	}
+	
+
+}
diff --git a/Source/mesquite/lib/TextContentArea.java b/Source/mesquite/lib/TextContentArea.java
new file mode 100644
index 0000000..59d08bb
--- /dev/null
+++ b/Source/mesquite/lib/TextContentArea.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+/** A ContentArea specifically for text display.  Has methods to control text, like a TextArea.*/
+class TextContentArea extends ContentArea {
+	TextArea tA;
+	
+	public TextContentArea () {
+		super(null);
+		mainPanel.setLayout(new CardLayout());
+    	 	Font fontToSet = new Font ("Monospaced", 0, 12);
+		if (fontToSet!=null)
+			setFont(fontToSet);
+		tA= new TextArea("", 50, 50,  TextArea.SCROLLBARS_BOTH); //or SCROLLBARS_VERTICAL_ONLY???
+		tA.setEditable(false);
+		setBackground(Color.white);
+		tA.setBackground(Color.white);
+		tA.setVisible(true);
+		add(tA, "text");
+	}
+	public void setEditable(boolean ed) {
+		tA.setEditable(ed);
+	}
+	public void print(Graphics g){
+		tA.printAll(g);
+	}
+	public void append(String s) {
+		tA.append(s);
+	}
+	public void setText(String s) {
+		tA.setText(s);
+	}
+	public String getText() {
+		return tA.getText();
+	}
+	public TextArea getTextArea() {
+		return tA;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TextRotator.java b/Source/mesquite/lib/TextRotator.java
new file mode 100644
index 0000000..42f644b
--- /dev/null
+++ b/Source/mesquite/lib/TextRotator.java
@@ -0,0 +1,168 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.awt.geom.*;
+
+
+/* ======================================================================== */
+/** A utility class to draw 90 degree rotated text.  Because this can be slow (bitmap manipulation), it
+can store a series of images for a series of strings.  If on next request nothing seems to have changed,
+it simply uses the old images.*/
+public class TextRotator { 
+	int numStrings;
+	String[] strings;
+	Color[] colors, backgrounds;
+	Font[] fonts;
+	Image[] images;
+	boolean[] validity;
+	Color bg;
+	public TextRotator () {
+	}
+	
+	public TextRotator (int numStrings) {
+		this();
+		this.numStrings = numStrings;
+		strings = new String[numStrings];
+		fonts = new Font[numStrings];
+		colors = new Color[numStrings];
+		backgrounds = new Color[numStrings];
+		images = new Image[numStrings];
+		validity = new boolean[numStrings];
+		for (int i=0; i<numStrings; i++) {
+			strings[i]="";
+			validity[i]=false;
+		}
+	}
+	public void invalidateAll(){
+		if (validity!=null)
+		for (int i=0; i<numStrings; i++) {
+			validity[i]=false;
+		}
+	}
+	public int getNumStrings() {
+		if (strings==null)
+			return 0;
+		else
+			return strings.length;
+	}
+	public void assignBackground(Color bkg) {
+		bg = bkg;
+	}
+	
+	/* -------------------------------------------------*/
+	public void drawRotatedText(String s, Graphics g, Component component, int horizPosition, int vertPosition) {
+		if (s == null || component == null)
+			return;
+		
+		//for Java 1.2
+
+			drawFreeRotatedText(s, g,horizPosition, vertPosition, -Math.PI/2, null, false, null);
+		
+	}
+	
+	public void drawFreeRotatedText(String s, Graphics g, int horizPosition, int vertPosition, double rotation, Point offsets, boolean alignBottom, Polygon poly) {
+			if (s==null)
+				return;
+			Font font = g.getFont();
+			FontMetrics fontMet = g.getFontMetrics(font);
+			int height = fontMet.getHeight();
+			int width = fontMet.stringWidth(s);
+			
+			int textOffsetH, textOffsetV;
+			if (offsets != null) {
+				textOffsetH = offsets.x;
+				textOffsetV = offsets.y;
+			}
+			else {
+				textOffsetH = height*2/3;
+				textOffsetV = 0;
+				if (!alignBottom)
+					textOffsetV = fontMet.stringWidth(s);
+			}
+			Graphics2D g2 = (Graphics2D)g;
+			g2.translate(textOffsetH, textOffsetV);
+			g2.rotate(rotation, horizPosition, vertPosition);
+			if (poly !=null){
+				double x = horizPosition;
+				double y = vertPosition-height*0.667;
+				double w = width;
+				double h = height;
+				AffineTransform transform = g2.getTransform();
+				float[] dest = new float[8];
+				double[] src = new double[8];
+				src[0] = x;
+				src[1] = y;
+				src[2] = x+w;
+				src[3] = y;
+				src[4] = x+w;
+				src[5] = y+h;
+				src[6] = x;
+				src[7] = y+h;
+				transform.transform(src, 0, dest, 0, 4);
+				poly.npoints=0;
+				poly.addPoint((int)dest[0], (int)dest[1]);
+				poly.addPoint((int)dest[2], (int)dest[3]);
+				poly.addPoint((int)dest[4], (int)dest[5]);
+				poly.addPoint((int)dest[6], (int)dest[7]);
+				poly.npoints=4;
+			}
+			if (bg!=null) {
+				Color c = g2.getColor();
+				g2.setColor(bg);
+				g2.fillRect(horizPosition,(int)(vertPosition-height*0.667),width, height);
+				g2.setColor(c);
+			} 
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+			g2.drawString(s, horizPosition, vertPosition);
+			g2.rotate(-rotation, horizPosition, vertPosition);
+			g2.translate(-textOffsetH, -textOffsetV);
+	}
+	/* -------------------------------------------------*/
+	/** This version is to speed up redraws, since it checks if it has already stored the image */
+	public void drawRotatedText(String s, int stringNumber, Graphics g, Component component, int horizPosition, int vertPosition, boolean alignBottom) {
+		if (s == null)
+			return;
+		//for Java 1.2
+
+			drawFreeRotatedText(s, g,horizPosition, vertPosition, -Math.PI/2, null, alignBottom, null);
+
+	}
+	/* -------------------------------------------------*/
+	public void drawRotatedText(String s, int stringNumber, Graphics g, Component component, int horizPosition, int vertPosition) {
+		drawRotatedText(s, stringNumber, g, component,  horizPosition, vertPosition, true);
+	}
+	/* -------------------------------------------------*/
+	private int[] rotateCCW (int pixels[], int width, int height) {
+		int newPixels[] = null;
+		if ((width*height)== pixels.length) {
+			newPixels = new int[width*height];
+			//for (int i=0; i<width*height; i++)
+			//	newPixels[i]= 0;
+				
+			int newIndex=0;
+			for (int oldX= width-1; oldX>=0; oldX--) 
+				for (int oldY= 0; oldY<height; oldY++)
+					newPixels[newIndex++] = pixels[oldY*width+(oldX)];
+			
+		}
+		return newPixels;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TextTree.java b/Source/mesquite/lib/TextTree.java
new file mode 100644
index 0000000..efeeac8
--- /dev/null
+++ b/Source/mesquite/lib/TextTree.java
@@ -0,0 +1,267 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+/**This class fills a StringBuffer with text that displays a tree.  For example:
+
+     ,===== taxon 1
+=====|
+     |  ,== taxon 2
+     `==|
+        `== taxon 3
+
+(Viewable in monospaced font).  The vertical axis is top to bottom (that is, taxon 1 is at vertical position 0).
+The horizontal axis is left to right (so, the root starts at horizontal position 0).
+*/
+
+public class TextTree {
+ 	static final int textTreeTaxonSpace = 1;
+ 	static final int baseTextTreeBranchHeight = 3;
+ 	int textTreeBranchHeight = 3;
+ 	int[] vertical;  //for node locations
+ 	int[] horizontal; //for node locations
+ 	int maxh;
+ 	int rightmostvert, hpos;
+ 	int maxStringLength=0;
+	public TextTree(Tree tree){
+		vertical = new int[tree.getNumNodeSpaces()];
+		horizontal = new int[tree.getNumNodeSpaces()];
+	}
+	/*-------------------------------------*/
+	/** This method finds the longest string at a node.*/
+	int maxStringSize (Tree tree, int N, String[] nodeStrings){ //fixed 21 mar 02
+		if (nodeStrings==null)
+			return 0;
+		int max = 0;
+		for (int i=0; i<nodeStrings.length; i++){
+			if (tree.nodeInTree(i) && nodeStrings[i]!=null) {
+				int t = nodeStrings[i].length();
+				if (t>max)
+					max = t;
+			}
+		}	
+		return max;
+			
+	}
+	/*-------------------------------------*/
+	/** This assigns vertical and horizontal positions to nodes. Vertical = up and down on page (increasing with down); horizontal = left and right
+	Each vertical position corresponds to a line of output.*/
+	void assignLocs (Tree tree, int N, int baseV, int baseCladeSize){
+		int thisCladeSize = tree.numberOfTerminalsInClade(N);
+		if (N != tree.getRoot()){ //{first, calculate node's location in window based on ancestor's}
+			int mother = tree.motherOfNode(N);
+			if (N != tree.lastDaughterOfNode(N))
+				vertical[N] = baseV- textTreeTaxonSpace * (baseCladeSize - thisCladeSize);
+			else
+				vertical[N] = baseV + textTreeTaxonSpace * (baseCladeSize - thisCladeSize);
+
+			horizontal[N] = horizontal[mother]+ textTreeBranchHeight;
+			if (tree.nodeIsPolytomous(mother))
+				horizontal[N] += textTreeBranchHeight;  //{but add one if part of polytomy so not too short}
+			
+			if (horizontal[N] > maxh)
+				maxh = horizontal[N];
+		}
+		if (tree.nodeIsInternal(N)) {
+			int numTerminalsSoFar=0;
+			int newBaseV = vertical[N];
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				assignLocs(tree, d, newBaseV, thisCladeSize-numTerminalsSoFar);//
+				numTerminalsSoFar +=tree.numberOfTerminalsInClade(d);
+				newBaseV = (vertical[N] + textTreeTaxonSpace * (numTerminalsSoFar));
+			}
+		}
+	}
+	/*-------------------------------------*/
+	/** These two methods adjust the vertical positions relative to the leftmost terminal taxon.*/
+	void doadjust (Tree tree, int N, int leftmostvert){
+		vertical[N] = vertical[N] + (1 - leftmostvert);
+		if (tree.nodeIsInternal(N)){
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				doadjust(tree, d, leftmostvert);
+		}
+	}
+	void adjustLocs(Tree tree, int baseN){
+		int leftmostvert =vertical[tree.leftmostTerminalOfNode(baseN)];
+		if (leftmostvert != 1)
+			doadjust(tree, baseN, leftmostvert);
+		rightmostvert = vertical[tree.rightmostTerminalOfNode(baseN)];
+	}
+	
+	/*-------------------------------------*/
+	/** This adjusts vertical positions so mother nodes are centered under their clades.*/
+	void centerTextBranches(Tree tree, int N){
+		if (tree.nodeIsInternal(N)){
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				centerTextBranches(tree, d);
+			vertical[N] = vertical[tree.firstDaughterOfNode(N)]+(vertical[tree.lastDaughterOfNode(N)]-vertical[tree.firstDaughterOfNode(N)]) /  2;
+		}
+	}
+
+	/*-------------------------------------*/
+	int nextInLine;
+	int posnext;
+	/** In a particular vertical position, this finds the next node whose line intersects and needs to be drawn.*/
+	void findNextInLine (Tree tree, int N, int vpos){
+		if (N == tree.getRoot()){
+			if ((vpos == vertical[N]) && (hpos < horizontal[N])){
+				nextInLine = N;
+				posnext = 1;
+			}
+		}
+		else {
+			int mother = tree.motherOfNode(N);
+			if (hpos <= horizontal[mother]){
+				if (horizontal[mother] <= posnext){
+					if (vpos == vertical[N]){
+						nextInLine = N;
+						posnext = horizontal[mother];
+					}
+					else if (((vpos > vertical[N]) && (vpos < vertical[mother])) || ((vpos < vertical[N]) && (vpos > vertical[mother]))){
+						if ((nextInLine <0) || !((vpos == vertical[nextInLine]) && (horizontal[mother] == posnext))){//{can't override a direct line up if equal}
+							nextInLine = N;
+							posnext = horizontal[mother];
+						}
+					}
+				}
+			}
+			else if ((hpos <= horizontal[N]) && (vpos == vertical[N])){ //{just in case one was missed}
+				nextInLine = N;
+				posnext = horizontal[mother];
+			}
+		}
+		if (tree.nodeIsInternal(N)){
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				findNextInLine(tree, d, vpos);
+		}
+	} //{findNextInLine}
+	
+	/*-------------------------------------*/
+	/** Continues writing from left to right along a vertical position, to write whatever is needed for a node N that intersects
+	the line*/
+	void writeNodeInLine (Tree tree, int N, StringBuffer buff, int vpos, String nodeString){
+		int mother = tree.motherOfNode(N);
+		//{=======  root  =======}
+		if (N == tree.getRoot()){ //   {we are writing root of page}
+			if (vpos == vertical[N]) {
+				int fill = 0;
+				if (nodeString==null)
+					fill = maxStringLength;
+				else
+					fill = maxStringLength-nodeString.length();
+				for (int jj = hpos; jj<  horizontal[N] - maxStringLength + fill; jj++)
+					buff.append('=');
+				if (nodeString!=null)
+					buff.append(nodeString);
+				buff.append('|');
+				hpos = horizontal[N] + 1;
+			}
+		}
+		//{=======  not root  =======}
+		else if (vpos == vertical[N]){   //node is directly at this vertical position; thus will need to draw "====" for branch
+			for (int jj = hpos; jj< horizontal[mother]; jj++)
+				buff.append(' ');
+			if (hpos < horizontal[mother])
+				hpos = horizontal[mother];
+			int textBranchRight;
+			if (tree.nodeIsTerminal(N))   //{it is terminal on page, horizontal position of terminal is maxh}
+				textBranchRight = maxh;
+			else
+				textBranchRight = horizontal[N];			//{it is internal, length of branch is horizontal, starting position of branch on left is hpos}
+			int nodeStringLength = 0;
+			if (nodeString==null)
+				nodeStringLength = 0;
+			else
+				nodeStringLength = nodeString.length();
+			int branchPieces = textBranchRight - hpos - nodeStringLength;
+			hpos = textBranchRight + 1;
+
+			//{==== Draw Branch ====}
+			char firstBranchChar = '|';
+			if (N == tree.firstDaughterOfNode(mother))
+				firstBranchChar = ',';
+			else if (N == tree.lastDaughterOfNode(mother))
+				firstBranchChar = '`';
+			else if (vertical[N] <= vertical[mother])
+				firstBranchChar = '=';
+			buff.append(firstBranchChar);
+			branchPieces--;
+			for (int jj = 1; jj<= branchPieces; jj++)
+				buff.append('=');
+			if (nodeString!=null)
+				buff.append(nodeString);
+
+			//{==== Draw Terminal Taxon name ====}
+			if (tree.nodeIsTerminal(N)){
+					buff.append(' ');  //{this puts a blank space in front of every terminal taxon name}
+					buff.append(tree.getTaxa().getTaxonName(tree.taxonNumberOfNode(N)));
+			}
+			else
+				buff.append('|');
+		}
+		else { //{node is not directly at this vertical position, thus its branch base might only cross this vertical position
+			if (((vpos > vertical[N]) && (vpos < vertical[mother])) || ((vpos < vertical[N]) && (vpos > vertical[mother]))){
+				for (int jj = hpos; jj<horizontal[mother]; jj++)
+					buff.append(' ');
+				buff.append('|');
+				hpos = horizontal[mother] + 1;
+			}
+		}
+	}//{writeNodeInLine}
+		
+	/*-------------------------------------*/
+	/* Write a line of output (corresponding to one vertical position)*/
+	void doLine (Tree tree, int vpos, StringBuffer buff, String[] nodeStrings){
+		hpos = 1;
+		do {
+			posnext = 30000;
+			nextInLine = -1;
+			findNextInLine(tree, tree.getRoot(), vpos);
+			if (nextInLine >=0) {
+				if (nodeStrings!=null && nextInLine<nodeStrings.length)
+					writeNodeInLine(tree, nextInLine, buff, vpos, nodeStrings[nextInLine]);
+				else
+					writeNodeInLine(tree, nextInLine, buff, vpos, null);
+			}
+		}
+		while (nextInLine >=0);
+		buff.append('\n');
+	} //{DoLine}
+	/*-------------------------------------*/
+	public void drawTreeAsText(Tree tree, StringBuffer buff){
+		drawTreeAsText(tree, buff, null);
+	}
+	/*-------------------------------------*/
+	public void drawTreeAsText(Tree tree, StringBuffer buff, String[] nodeStrings){
+		int root = tree.getRoot();
+		maxStringLength = maxStringSize(tree, root, nodeStrings) ;  //rearranged 21 mar 02
+		textTreeBranchHeight = baseTextTreeBranchHeight +maxStringLength;
+		horizontal[root] = textTreeBranchHeight + 3;
+		vertical[root] = (tree.numberOfTerminalsInClade(root) * textTreeTaxonSpace) / 2 + textTreeTaxonSpace + 1;
+		maxh = 0;
+		assignLocs(tree, root, vertical[root], tree.numberOfTerminalsInClade(tree.getRoot()));
+		adjustLocs(tree, root);
+		centerTextBranches(tree, root);
+		for (int j = 1; j<= rightmostvert; j++)
+				doLine(tree, j, buff, nodeStrings);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ThermoPanel.java b/Source/mesquite/lib/ThermoPanel.java
new file mode 100644
index 0000000..dbdc364
--- /dev/null
+++ b/Source/mesquite/lib/ThermoPanel.java
@@ -0,0 +1,175 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+
+/* ======================================================================== */
+/** A little panel placed within a container to indicate an ongoing calculations.  Serves like a 
+thermometer window, but embedded in relevant container since there may be several ongoing
+at once.*/
+public class ThermoPanel extends Panel {
+	long current=MesquiteLong.unassigned;
+	long total = MesquiteLong.unassigned;
+	String s = null;
+	Color barColor = ColorDistribution.spinDark;
+	Color barBackColor = ColorDistribution.spinLight;
+	static final int polyBarW = 10;
+	int polyBarSlant = 4;
+	int polyBarOffset = 0;
+	Component drawHereToo;
+	
+	public ThermoPanel (ProgressIndicator progressIndicator) {
+		super();
+		setProgressIndicator(progressIndicator);
+	}
+	public ThermoPanel () {
+		super();
+	}
+	public void setExtraDraw(Component p){
+		drawHereToo = p;
+	}
+	public void setProgressIndicator(ProgressIndicator progressIndicator){
+		if (progressIndicator == null)
+			return;
+		barColor = progressIndicator.getBarColor();
+		barBackColor = progressIndicator.getBarBackColor();
+	}
+	public String getText() {
+		return s;
+	}
+	static final boolean INSTAPAINT = false; //true was causing problems for OS X 1.4.1 beta
+	public void setText(String s) {
+		this.s = s;
+		if (INSTAPAINT) {
+			Graphics g = getGraphics();
+			if (g!=null){
+				dr(g);
+				g.dispose();
+			}
+		}
+		else
+			repaint();
+	}
+	public void setTime(long total, long current) {
+		if (MesquiteLong.isCombinable(current))
+			this.current = current;
+		if (MesquiteLong.isCombinable(total)) {
+			this.total = total;
+			if (total<=0)
+				total = 1;
+		}
+		if (current> total)
+			current = total;
+		if (INSTAPAINT) {
+			Graphics g = getGraphics();
+			if (g!=null){
+				dr(g);
+				g.dispose();
+			}
+		}
+		else
+			repaint();
+	}
+	
+	/*.................................................................................................................*/
+	public void setBarColor(Color barColor) {
+		this.barColor = barColor;
+	}
+	/*.................................................................................................................*/
+	public void setBarBackColor(Color barBackColor) {
+		this.barBackColor = barBackColor;
+	}
+	
+	/*.................................................................................................................*/
+	/** This method is called to draw a simply "spinning" bar */
+	void spin (Graphics g){
+		int w = getBounds().width;
+		int h = getBounds().height;
+		polyBarSlant = h;
+		Polygon spinPoly = new Polygon(new int[]{0, polyBarW, polyBarSlant+polyBarW, polyBarSlant}, new int[]{h, h, 0,0}, 4);
+		int numPolys = (w + polyBarSlant)/(polyBarW*2);
+		spinPoly.translate(-polyBarW+polyBarOffset - polyBarSlant,0);
+		int shift = 0;
+		for (int poly=0; poly<=numPolys; poly++) {
+			g.setColor(barBackColor);
+			//g.setColor(ColorDistribution.spinLight);
+			//g.setColor(ColorDistribution.projectLight[ColorDistribution.getColorScheme(MesquiteWindow.windowOfItem(this).ownerModule)]);
+			g.fillPolygon(spinPoly);
+			spinPoly.translate(polyBarW,0);
+			shift+=polyBarW;
+			g.setColor(barColor);
+			//g.setColor(ColorDistribution.spinDark);
+			//g.setColor(ColorDistribution.medium[ColorDistribution.getColorScheme(MesquiteWindow.windowOfItem(this).ownerModule)]);
+			g.fillPolygon(spinPoly);
+			spinPoly.translate(polyBarW,0);
+			shift+=polyBarW;
+		}
+		polyBarOffset+=2;
+		if (polyBarOffset>polyBarW)
+			polyBarOffset=0;
+	 }
+	/*.................................................................................................................*/
+	
+	void dr(Graphics g){
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		int w = getBounds().width;
+		int h = getBounds().height;
+		if (total==0) {
+			spin(g);
+		}
+		else if ( current == 0 || current == MesquiteLong.unassigned) {
+			g.setColor(getBackground());
+			g.fillRect(1,1, w-3, h-2);
+		}
+		else {
+			g.setColor(barColor);
+			int progressLine;
+			try {
+				progressLine = (int)(w*current/total);
+				g.fillRect(1,1,progressLine, h-2);
+				g.setColor(barBackColor);
+				g.fillRect(progressLine+1,1, w-2 -progressLine, h-2);
+			}
+			catch (Exception e) {
+			}
+		}
+		g.setColor(getForeground());
+		if (!StringUtil.blank(s)) {
+			g.drawString(s, 4, h-8);
+		}
+		g.setColor(Color.black);
+		g.drawRect(0,0, w-1, h-1);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void update(Graphics g){
+		paint(g);
+	}
+	public void paint (Graphics g) {
+	   	dr(g);
+	   	if (drawHereToo != null){
+	   		Graphics gg = drawHereToo.getGraphics();
+	   		if (gg != null){
+	   			dr(gg);
+	   		}
+	   	}
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/ToolKeyListener.java b/Source/mesquite/lib/ToolKeyListener.java
new file mode 100644
index 0000000..3861439
--- /dev/null
+++ b/Source/mesquite/lib/ToolKeyListener.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.*;
+
+/* An interface so that a tool can report a key event */
+
+public interface ToolKeyListener {
+	public void keyTyped(KeyEvent e, MesquiteTool tool);
+	public void keyPressed(KeyEvent e, MesquiteTool tool);
+	public void keyReleased(KeyEvent e, MesquiteTool tool);
+}
+
diff --git a/Source/mesquite/lib/ToolPalette.java b/Source/mesquite/lib/ToolPalette.java
new file mode 100644
index 0000000..8375f67
--- /dev/null
+++ b/Source/mesquite/lib/ToolPalette.java
@@ -0,0 +1,433 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+
+import mesquite.lib.simplicity.InterfaceManager;
+
+public class ToolPalette extends MesquitePanel implements Commandable, KeyListener {
+	protected MesquiteWindow container;
+	public ListableVector tools;
+	protected MesquiteModule ownerModule;
+	MesquiteTool currentTool;
+	private int numTools=0;
+	private static final int buttonSize = 26;
+	int defaultTool = 0;
+	private boolean firsttime=true;
+	MesquiteButton[] toolButtons;
+	int firstHeight = 12;
+	int numColumns = 1;
+	int defaultNumColumns = 1;
+	private int paletteWidth;
+	int spacer =5;
+	int singleColumnSpacer = 20; //13;
+	int colorScheme;
+	static final int triangleLeft= 4;
+	static final int triangleTop = 4;
+	static final int triangleWidth = 11;
+	static final int triangleHeight = 6;
+	Color bgColor;
+	public ToolPalette(MesquiteModule ownerModule, MesquiteWindow container, int numColumns) {  //in future pass general MesquiteWindow
+		super();
+	
+
+		this.numColumns = numColumns;
+		this.defaultNumColumns = numColumns;
+		this.ownerModule=ownerModule;
+		this.container = container;
+		tools = new ListableVector();
+		toolButtons = new MesquiteButton[64];
+		setLayout(null);
+		colorScheme = ColorDistribution.getColorScheme(ownerModule);
+		//bgColor = ColorDistribution.medium[colorScheme];
+		bgColor = ColorTheme.getInterfaceBackground();
+		setBackground(bgColor);
+		//	setBackground(ColorDistribution.medium[colorScheme]);  //used to be light//ggray
+		if (numColumns ==1)
+			paletteWidth =  (buttonSize+singleColumnSpacer);
+		else
+			paletteWidth =  (buttonSize+spacer)*numColumns + spacer;
+		setCursor(Cursor.getDefaultCursor());
+	}
+	public int getWidth(){
+		if (numTools == 0)
+			return 0;
+		return paletteWidth;
+	}
+	public void keyTyped(KeyEvent e){
+	}
+
+	boolean modifiersHadBeenPressed = false;
+
+	public void keyPressed(KeyEvent e){
+		if (MesquiteEvent.getModifiers(e)!=0 && toolButtons!=null) {
+			modifiersHadBeenPressed = true;
+			for (int i = 0; i<toolButtons.length; i++) {
+				if (toolButtons[i] !=null)
+					toolButtons[i].modifierKeysPressed(MesquiteEvent.getModifiers(e));
+			}
+		}
+
+	}
+	public void keyReleased(KeyEvent e){
+		if (modifiersHadBeenPressed && toolButtons!=null) {
+			for (int i = 0; i<toolButtons.length; i++) {
+				if (toolButtons[i] !=null)
+					toolButtons[i].modifierKeysReleased(MesquiteEvent.getModifiers(e));
+			}
+		}
+		if (MesquiteEvent.getModifiers(e)==0)
+			modifiersHadBeenPressed = false;
+	}
+	public void setNumColumns(int i){
+		numColumns = i;
+		if (numColumns ==1)
+			paletteWidth =  (buttonSize+singleColumnSpacer);
+		else
+			paletteWidth =  (buttonSize+spacer)*numColumns + spacer;
+		paletteWidth=paletteWidth;
+		if (paletteWidth <minWidth())
+			paletteWidth = minWidth();
+		recheckSize();
+	}
+	/*.................................................................................................................*
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		String s="";
+		try {
+			if (inShowInfoBarButton(x,y)) {
+				if (!((MesquiteWindow)container).getShowInfoBar())
+					s += "This button will show the information bar at the top of this window, which will allow one to see other graphical and text views, as well as parameter information, active modules, and citations. ";
+			}
+			((MesquiteWindow)container).setExplanation(s);
+			super.mouseMoved(modifiers,x,y,tool);
+		}
+		catch (Exception e){
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean inShowInfoBarButton(int x, int y) {
+		return (x<=triangleLeft+triangleWidth && x>=triangleLeft && y<=triangleTop + triangleHeight && y>=triangleTop);
+	}
+	/*.................................................................................................................*
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+   		if (inShowInfoBarButton(x,y)){
+   			if (container instanceof MesquiteWindow) {
+   				if (!((MesquiteWindow)container).getShowInfoBar()) {
+   					((MesquiteWindow)container).setShowInfoBar(true);
+   					repaint();
+				}
+   			}
+
+   		}
+   	}
+	/*.................................................................................................................*/
+	public MesquiteTool getToolWithName(String name) {
+		if (tools!=null) {
+			Enumeration e = tools.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteTool mt = (MesquiteTool)obj;
+				if (mt.getName().equalsIgnoreCase(name))
+					return mt;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public MesquiteButton getButtonWithName(String name) {
+		if (name !=null && toolButtons!=null) {
+			for (int i = 0; i<toolButtons.length; i++) {
+				if (toolButtons[i] !=null){
+					MesquiteTool tool = toolButtons[i].getTool();
+					if (tool!=null)
+						if (name.equalsIgnoreCase(tool.getName()))
+							return toolButtons[i];
+				}
+			}
+		}
+		return null;
+	}
+	public void repaintAll(){
+		repaint();
+		if (toolButtons!=null){
+			for (int i=0; i<toolButtons.length; i++) {
+				if (toolButtons[i]!=null) {
+					toolButtons[i].repaint();
+				}
+			}
+		}
+	}
+	/**/
+	public void dispose(){
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w!=null)
+			w.waitUntilDisposable();
+		try {
+			if (toolButtons!=null){
+				for (int i=0; i<toolButtons.length; i++) {
+					if (toolButtons[i]!=null) {
+						toolButtons[i].dispose();
+						remove(toolButtons[i]);
+						toolButtons[i]=null;
+					}
+				}
+				toolButtons=null;
+			}
+			if (tools!=null) {
+				tools.removeAllElements(true);
+			}
+		}
+		catch (Exception e){
+		}
+		tools = null;
+		ownerModule=null;
+		currentTool = null;
+		container = null;
+	}
+	public void setFirstToolHeight(int h) {
+		this.firstHeight = h;
+	}
+
+	public int getBottomOfTools() {
+		return firstHeight + ((numTools-1)/numColumns) * (buttonSize+inBetween) + buttonSize;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (currentTool==null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTool " + StringUtil.tokenize(currentTool.getName()));
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the active tool in the tool palette", "[tool name][x coordinate touched][y coordinate touched][modifiers]", commandName, "setTool")) {
+			pos.setValue(0);
+			String toolName = (ParseUtil.getToken(arguments, pos));
+			MesquiteButton button =getButtonWithName(toolName);
+			if (button==null) {
+				//MesquiteMessage.warnProgrammer("button not found!  (" + toolName + ")");
+				return null;
+			}
+			MesquiteTool tool =button.getTool();//getToolWithName(toolName);
+			if (tool!=null){
+				if (tool!=currentTool) {
+					setCurrentTool(tool);
+					container.setCurrentTool(tool);
+				}
+				int x = MesquiteInteger.fromString(arguments, pos);
+				int y = MesquiteInteger.fromString(arguments, pos);
+				String arg = ParseUtil.getToken(arguments, pos);
+				if (MesquiteInteger.isCombinable(x) && MesquiteInteger.isCombinable(y) && arg!=null && arg.indexOf("command")>=0) {
+					tool.chooseOptions(button, x, y);
+				}
+
+			}
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	int inBetween = 2;
+	int findBestNumColumns(int bottom){
+		if (getBounds().height<firstHeight + buttonSize)
+			return 4;
+		int nC = 1;
+		while (nC<5 && bottom <firstHeight + ((numTools-1)/nC) * (buttonSize+inBetween) + buttonSize) {
+			nC++;
+		}
+		if (nC>4)
+			return 4;
+		if (nC<defaultNumColumns)
+			return defaultNumColumns;
+		return nC;
+	}
+	public int minWidth(){
+		return 0;
+	}
+	void recheckSize(){
+		if (toolButtons==null)
+			return;
+		if (numTools==0)
+			return;
+		int totalWidth = getWidth();
+		int neededHeight =   ((numTools)/numColumns) * (buttonSize+inBetween);
+		int neededWidth = numColumns *buttonSize + (numColumns-1) *inBetween;
+
+		int leftEdge = (totalWidth-neededWidth)/2;
+		int ht =getBounds().height;
+		int curBest = findBestNumColumns(ht-48);
+		if (curBest != numColumns) {
+			setNumColumns(curBest);
+		}
+		//else if (numTools-1<toolButtons.length && toolButtons[numTools-1]!=null){
+		//	toolButtons[numTools-1].setLocation(leftEdge+ (buttonSize+inBetween)*((numTools-1)%numColumns), firstHeight + ((numTools-1)/numColumns) * (buttonSize+inBetween));
+		//	toolButtons[numTools-1].setVisible(true);
+		//}
+		if (toolButtons==null)
+			return;
+		deepestButton = 0;
+		int count = 0;
+		for (int i=0; i<= numTools && i<toolButtons.length; i++)
+			if (toolButtons[i]!=null) {
+				if ((!InterfaceManager.isSimpleMode() || InterfaceManager.isEditingMode()) || (toolButtons[i].getHiddenStatus() != InterfaceManager.HIDDEN && toolButtons[i].getHiddenStatus() != InterfaceManager.HIDDENCLASS)){
+					int bDepth = firstHeight + ((count)/numColumns) * (buttonSize+inBetween);
+					toolButtons[i].setLocation(leftEdge+ (buttonSize+inBetween)*((count)%numColumns), bDepth);
+					if (bDepth>deepestButton)
+						deepestButton = bDepth;
+					count++;
+				}
+				else
+					toolButtons[i].setLocation(-100, -100);
+
+			}
+	}
+	int deepestButton = 0;
+	public int getDeepestButton(){
+		return deepestButton + buttonSize;
+	}
+	public MesquiteButton addTool(MesquiteTool tool) {
+		if (tool == null || tools == null)
+			return null;
+		tools.addElement(tool, false);
+		tool.setPalette(this);
+
+		MesquiteButton button = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("setTool", this), StringUtil.tokenize(tool.getName()), false, tool.getImagePath(), buttonSize,buttonSize);
+		toolButtons[numTools] = button;
+		if (tool.getOptionImagePath()!=null)
+			button.setOptionImagePath(tool.getOptionImagePath());
+		toolButtons[numTools].setTool(tool);
+		toolButtons[numTools].waitUntilImagesLoaded();
+		if (numTools==0)
+			toolButtons[0].setOffOn(true);
+		add(toolButtons[numTools]);
+		numTools++;
+		recheckSize();
+		if (toolButtons[numTools-1]!=null)
+			toolButtons[numTools-1].setVisible(true);
+		button.setVisible(true);
+		tool.setButton(button);
+		repaint();
+		return button;
+
+	}
+	public void removeTool(MesquiteTool tool) {
+		if (tool == null || tools == null)
+			return;
+		tools.removeElement(tool, false);
+		for (int i=0; i<toolButtons.length; i++) {
+			if (toolButtons[i]!=null) {
+				if (toolButtons[i].getTool() == tool){
+					MesquiteButton temp = toolButtons[i];
+					for (int j=i+1; j<toolButtons.length; j++){
+						toolButtons[j-1]=toolButtons[j];
+					}
+					numTools--;
+					if (tool == currentTool && toolButtons.length>0)
+						setCurrentTool(0);
+					toolButtons[toolButtons.length-1]=null;
+					temp.dispose();
+					remove(temp);
+					recheckSize();
+					repaint();
+					return;
+				}
+			}
+		}
+	}
+	public MesquiteTool getCurrentTool() {
+		return currentTool;
+	}
+	public int getNumTools() {
+		return numTools;
+	}
+	public void toolTextChanged(){
+		container.setExplanation("");
+		if (currentTool!=null) {
+			container.setExplanation(currentTool.fullDescription);
+			if (currentTool.getDescription()!= null){
+				if (currentTool.getDescription()!=null)
+					container.setExplanation("Current Tool: " + currentTool.getDescription());
+			}
+		}
+	}
+
+	public void setToDefaultTool() {
+		setCurrentTool(defaultTool);
+	}
+	public void setCurrentTool(int button) {
+		MesquiteTool tool =  toolButtons[button].getTool();
+		setCurrentTool(tool);
+	}
+	public void setCurrentTool(MesquiteTool tool) {
+		if (tool==null || !tool.getEnabled())
+			return;
+		Parser parser = new Parser();
+		for (int i=0; i<numTools ; i++) {
+			if (tool.getName().equalsIgnoreCase(parser.getFirstToken(toolButtons[i].arguments))) {  //SHOULDN't RELY ON NAME HERE!!!!!
+				toolButtons[i].setOn();
+			}
+			else
+				toolButtons[i].setOff();
+		}
+		if (currentTool!=null)
+			currentTool.setInUse(false);
+		currentTool = tool;
+		currentTool.setInUse(true);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		//recheckSize();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+	}
+	public void paint(Graphics g) {//^^^
+		bgColor = ColorTheme.getInterfaceBackground();
+		if (	getBackground() != bgColor){
+			setBackground(bgColor);
+			repaint();
+			return;
+		}
+
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		int ht =getBounds().height;
+		int w =getBounds().width;
+
+
+		int locX = 0;
+		int locY = 0;
+		/*if (InterfaceManager.isEditingMode()){
+			Color co = g.getColor();
+			g.setColor(Color.cyan);
+			g.fillRect(0, 0, getWidth(), getHeight());
+			g.setColor(co);
+		}*/
+		g.setColor(ColorTheme.getContentEdgeDark());  //used to be light
+		g.fillRect(w-2, 0, 2, ht);
+		g.setColor(bgColor);  //used to be light
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/TranslationTable.java b/Source/mesquite/lib/TranslationTable.java
new file mode 100644
index 0000000..e9f9421
--- /dev/null
+++ b/Source/mesquite/lib/TranslationTable.java
@@ -0,0 +1,167 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+/* ��������������������������� tree stuff ������������������������������� */
+/* ======================================================================== */
+/** A translation table linking taxa with alternative tokens */
+public class TranslationTable {
+	Taxa taxa;
+	String[] labels;
+
+	public TranslationTable (Taxa taxa){
+		if (taxa!=null) {
+			labels = new String[taxa.getNumTaxa()];
+			this.taxa = taxa;
+		}
+	}
+	public Taxon getTaxon(String label){
+		if (labels==null || taxa == null || label == null)
+			return null;
+		for (int i=0; i<labels.length; i++){
+			if (label.equalsIgnoreCase(labels[i])) {
+				return taxa.getTaxon(i);
+			}
+		}
+		return null;
+	}
+	public String getLabel(Taxon taxon){
+		int i = taxa.whichTaxonNumber(taxon);
+		if (i>=0 && i<taxa.getNumTaxa()) {
+			if (i>=labels.length)
+				resetSizes();
+			return labels[i];
+		}
+		return null;
+
+	}
+	public String getLabel(int i){
+		if (taxa==null || labels == null)
+			return null;
+		if (i>=0 && i<taxa.getNumTaxa()) {
+			if (i>=labels.length)
+				resetSizes();
+			return labels[i];
+		}
+		return null;
+
+	}
+	public void setLabel(Taxon taxon, String label, boolean checkDuplicates){
+		if (taxa==null)
+			return;
+		int i = taxa.whichTaxonNumber(taxon);
+		if (i>=0 && i<taxa.getNumTaxa()) {
+			if (i>=labels.length)
+				resetSizes();
+			labels[i] = label;
+		}
+		if (checkDuplicates)
+			checkDuplicates();
+	}
+
+	public void taxaModified(int category, int starting, int num){
+		int numTaxa = taxa.getNumTaxa();
+		/*
+		String[] newLabels = new String[numTaxa];
+
+		if (category==MesquiteListener.PARTS_ADDED) {
+			for (int i=0; i<=starting; i++)
+				newLabels[i] = labels[i];
+			for (int i=starting+num; i<numTaxa; i++)
+				newLabels[i] = labels[i-num];
+			nullify();
+		}
+		else if (category==MesquiteListener.PARTS_DELETED){
+			for (int i=0; i<starting; i++)
+				newLabels[i] = labels[i];
+			for (int i=starting+num; i<labels.length; i++) {
+				newLabels[i-num] = labels[i];
+			}
+			nullify();
+		}
+		else if (category==MesquiteListener.PARTS_MOVED){
+			MesquiteMessage.warnProgrammer("taxa moved not working for translation table update");
+			MesquiteMessage.printStackTrace();
+		}
+		labels = newLabels;
+		checkDuplicates();
+		 */
+		if (category==MesquiteListener.PARTS_ADDED) {
+			labels = new String[numTaxa];
+		}
+		else if (category==MesquiteListener.PARTS_DELETED){
+			labels = new String[numTaxa];
+		}
+		else if (category==MesquiteListener.PARTS_MOVED){
+			labels = new String[numTaxa];
+		}
+	}
+	public void resetSizes(){
+		int numTaxa = taxa.getNumTaxa();
+		if (labels == null) {
+			labels = new String[numTaxa];
+		}
+		else if (labels.length!=taxa.getNumTaxa()) {
+			labels = new String[numTaxa];
+			/*
+			String[] newLabels = new String[numTaxa];
+			for (int i=0; i<numTaxa && i<labels.length; i++)
+				newLabels[i] = labels[i];
+			labels = newLabels;
+			 */
+		}
+	}
+
+	public void cleanUpTable(){  //adds labels where needed then checks for duplicates
+		if (labels == null) //TODO: construct new labels
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		if (numTaxa>labels.length){
+			String[] newLabels = new String[numTaxa];
+			for (int i=0; i<numTaxa && i<labels.length; i++)
+				newLabels[i] = labels[i];
+			labels = newLabels;
+		}
+		for (int i=0; i<labels.length; i++) {
+			if (labels[i] ==null){
+				labels[i] = "n" + i;
+			}
+		}
+		checkDuplicates();
+
+	}
+	public void checkDuplicates(){
+		if (labels == null) //TODO: construct new labels
+			return;
+		for (int i=0; i<labels.length; i++) {
+			if (labels[i] !=null){
+				while (StringArray.indexOfIgnoreCase(labels, labels[i]) !=StringArray.lastIndexOfIgnoreCase(labels, labels[i]))
+					labels[i] = "t" + labels[i] + "t";
+			}
+		}
+		for (int i=0; i<labels.length; i++) {
+			if (labels[i] ==null){
+				labels[i] = Integer.toString(Taxon.toExternal(i));
+				while (StringArray.indexOfIgnoreCase(labels, labels[i]) !=StringArray.lastIndexOfIgnoreCase(labels, labels[i]))
+					labels[i] = "t" + labels[i] + "t";
+			}
+		}
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/Tree.java b/Source/mesquite/lib/Tree.java
new file mode 100644
index 0000000..303527a
--- /dev/null
+++ b/Source/mesquite/lib/Tree.java
@@ -0,0 +1,322 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+import java.util.*;
+
+/** This interface matches the readable methods of MesquiteTree, and was created so that translator classes could
+be written that could access tree structures from other programs.  Most calculations are passed trees under the
+guise of interface Tree, which allows these calculations to be used on tree structures other than MesquiteTree, and
+which ensures they will not modify the tree.  Some modules that need to modify tree structures check to see whether the passed
+Tree is an instance of AdjustableTree or MesquiteTree.  The change to using interfaces (from the previous system
+which just passed MesquiteTree under the name Tree) was done Aug. 2000, and the change has not fully settled in yet.
+ */
+public interface Tree extends Listable {
+	/** writing mode -- puts full taxon name in tree descriptions */
+	public static final int BY_NAMES = 0;
+	/** writing mode -- puts number of taxon in tree descriptions */
+	public static final int BY_NUMBERS = 1;
+	/** writing mode -- puts label from translation table, if available, in tree descriptions */
+	public static final int BY_TABLE = 2;
+	public MesquiteTree cloneTree();
+	/** Sets this tree to be a clone of that passed.*/
+	public void setToClone(MesquiteTree tree);
+	public boolean isDefined();
+	/** Returns false if tree is null, has no nodes, or is locked.*/
+	public boolean isValid();
+	/** Returns false if tree is null, has no nodes, or is locked, or if some taxonNumbers are negative.*/
+	public boolean isLocked();
+	public long getID();
+	public long getVersionNumber();
+	public Taxa getTaxa();
+	public int getRoot();
+	public int getSubRoot();
+	public boolean getRooted();
+	/** Returns whether root is real.  It isn't real if the tree is unrooted.*/
+	public boolean rootIsReal();
+	/** Returns true if trees have same topology. */
+	public boolean equalsTopology(Tree tree, boolean checkBranchLengths);
+	/** Returns the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = use default.*/
+	public int getPolytomiesAssumption();
+	/** Returns the number of terminal taxa in the Taxa to which the tree refers.  This is not necessarily the 
+	number of terminal taxa in the tree itself (for that, call numberOfTerminalsInClade(root)).*/
+	public int getNumTaxa();
+	/** Returns the number of node spaces available in storage arrays within tree object.*/
+	public int getNumNodeSpaces();
+	/** Returns the number of a randomly chosen node.*/
+	public int randomNode(RandomBetween rng, boolean allowRoot);
+	/** Returns true if N is a valid node designation in tree.*/
+	public  boolean nodeExists(int node);
+	/** Returns whether node is part of tree. Differs from nodeExists by doing full recursion (more reliable, slower).*/
+	public boolean nodeInTree(int sought);
+	/** Returns true if node is an internal node.*/
+	public  boolean nodeIsInternal(int node);
+	/** Returns true if node is a terminal node.*/
+	public  boolean nodeIsTerminal(int node);
+	/** Returns whether taxon is part of tree. */
+	public boolean taxonInTree(int taxonNum);
+	/** Returns the taxon number of the node.  This is -1 if the node is internal,
+	the taxon number if terminal.*/
+	public  int taxonNumberOfNode(int node); 
+	/** Returns the terminal node corresponding to the given taxon number; 0 if the taxon  is not part of the tree.*/
+	public int nodeOfTaxonNumber(int taxonNum);
+	/** Returns the immediate ancestor of node (mother) if node is non-reticulate.
+	If node is reticulate, returns the first (primary) parent.*/
+	public  int motherOfNode(int node);
+	/** Returns the node's mother's mother.*/
+	public  int grandmotherOfNode(int node);
+	public  int firstLegalDaughterOfNode(int node, int[] legality);
+	public  int nextLegalSisterOfNode(int node, int[] legality);
+	public  int lastLegalDaughterOfNode(int node, int[] legality);
+	/** Returns the number of parents of node.*/
+	public int numberOfParentsOfNode(int node);
+	/** Returns the indexTH parent of node.*/
+	public int parentOfNode(int node, int index);
+	/** Returns the array of parents of node.  If node is not reticulate, the array returned contains
+	only the mother node.*/
+	public int[] parentsOfNode(int node);
+	/** Returns true iff first branch is a descendant of second branch.*/
+	public boolean descendantOf(int branchD, int branchA); 
+	/** Returns depth of second branch below first; -1 if not ancestral.*/
+	public int depthToAncestor(int branchD, int branchA); 
+	/** Returns the deepest path in the clade, in terms of numbers of nodes*/
+	public int deepestPath(int node);
+	/** Returns the first (left-most) daughter of node.*/
+	public  int firstDaughterOfNode(int node);
+	/** Returns the right-most daughter of node.*/
+	public int lastDaughterOfNode(int node);
+	/** Returns the array of daughters of a node.  Normally it will be best to cycle through the
+	daughters as shown in the recursion example in the documentation for the Tree class.*/
+	public int[] daughtersOfNode(int node);
+	/** Returns true if branchD is an immediate daughter of branchA */
+	public boolean daughterOf(int branchD, int branchA); 
+	/** Returns true if node is the first (leftmost) daughter of its mother.*/
+	public boolean nodeIsFirstDaughter(int node);
+	/** Returns the index of the node among its sisters (i.e., if it is the first daughter of
+	its mother, the second , third, etc.*/
+	public int whichDaughter(int node);
+	/** Returns the indexTH daughter of node.*/
+	public int indexedDaughterOfNode(int node, int index);
+	/** Returns the number of daughters of the node.*/
+	public int numberOfDaughtersOfNode(int node);
+	/** Returns if branchD is descendant of branchA, then which daughter of branchA does it descend from?
+		Returns 0 if not descendant.*/
+	public int whichDaughterDescendantOf(int branchD, int branchA); 
+	/** Returns the node's sister immediately to the right.  If the node has no
+	sister to the right, returns 0 (which is not a valid node designation).*/
+	public  int nextSisterOfNode(int node);
+	/** Returns the node's sister immediately to the left.  If the node has no 
+	sister to the right, returns 0 (which is not a valid node designation).*/
+	public int previousSisterOfNode(int node);
+	/** Returns true if branch1 and branch2 are sisters by their mother (i.e., primary parent).
+	There is currently no method to return whether two nodes share at least one parent.*/
+	public  boolean nodesAreSisters(int branch1, int branch2); 
+	/** Returns whether tree has nodes with more than one parent.*/
+	public  boolean hasReticulations();
+	/** Returns whether clade has unbranched internal nodes.*/
+	public  boolean hasUnbranchedInternals(int node);
+	/** Returns true if the node is an internal node with only a single daughter.*/
+	public boolean nodeIsUnbranchedInternal(int node);
+	/** Returns whether clade has polytomies.*/
+	public  boolean hasPolytomies(int node);
+	/** Returns whether clade has soft polytomies (uncertainties).*/
+	public  boolean hasSoftPolytomies(int node);
+	/** Returns true if the node is polytomous (has more than two daughters).*/
+	public boolean nodeIsPolytomous(int node);
+	/** Returns true if the node has one descendant, two, or is a hard polytomy.*/
+	public boolean nodeIsHard(int node); //TODO: in future allow individual trees or nodes to store whether polytomy is hard or soft
+	/** Returns true if the node is a soft polytomy.*/
+	public boolean nodeIsSoft(int node);
+	/** Returns number of total nodes (internal and external) in clade.*/
+	public  int numberOfNodesInClade(int node);
+	/** Returns number of terminal taxa in clade.*/
+	public  int numberOfTerminalsInClade(int node);
+	/** Returns number of internal nodes in clade.*/
+	public  int numberOfInternalsInClade(int node);
+	/** Returns the left-most terminal that is descendant from node.*/
+	public  int leftmostTerminalOfNode(int node);
+	/** Returns the right-most terminal that is descendant from node.*/
+	public  int rightmostTerminalOfNode(int node);
+	/** Returns list of terminal taxa of clade of node.*/
+	public Bits getTerminalTaxaAsBits(int node);
+	/** Returns list of terminal taxa of clade of node.*/
+	public int[] getTerminalTaxa(int node);
+	/** Returns list of terminal taxa NOT in clade of node, as bits.*/
+	public Bits getTerminalTaxaComplementAsBits(int node);
+	/** Returns list of terminal taxa NOT in clade of node.  Into this version you pass the int[] of the terminal taxa in the tree, for speed's sake. */
+	public int[] getTerminalTaxaComplement(int node);
+	/** Returns list of terminal taxa NOT in clade of node.  Into this version you pass the int[] of the terminal taxa in the tree, for speed's sake. */
+	public int[] getTerminalTaxaComplement(int[] allTerminals, int node);
+	/** Returns list of terminal taxa NOT in clade of node.  Into this version you pass int[]'s, for speed's sake. */
+	public int[] getTerminalTaxaComplement(int[] allTerminals, int[] nodeTerminals);
+	/** Returns true iff the terminal taxa listed in "terminals" form a clade. */
+	public boolean isClade(Bits terminals);
+	/** Returns true iff the terminal taxa listed in "terminals" form a convex part of the tree.  Also returns the two nodes that form the boundary*/
+	public boolean isConvex(Bits terminals, MesquiteInteger descendantBoundary);
+	/** Returns true iff the terminal taxa listed in "terminals" form a convex part of the tree. */
+	public boolean isConvex(Bits terminals);
+	/**Returns indexTH node in tree traversal*/
+	public int nodeInTraversal(int index);
+	/**Returns indexTH node in traversal through clade*/
+	public int nodeInTraversal(int index, int cladeRoot);
+	/** Returns next node in preorder traversal.*/
+	public int nextInPreorder(int node);
+	/** Returns next node in postorder traversal.*/
+	public int nextInPostorder(int node);
+	/** Returns first node in postorder traversal.*/
+	public int firstInPostorder();
+	/** Returns most recent common ancestor of two branches.*/
+	public int mrca(int branchA, int branchB); 
+	/** Returns most recent common ancestor of the terminals designated in terminals.*/
+	public int mrca(Bits terminals);
+	/*New code added Aug.14.07 oliver*/ //TODO: delete new code comments
+	/** Returns most recent common ancestor for an array of nodes.*/
+	public int mrca(int[] nodes);
+	/** Returns most recent common ancestor for an array of nodes; if boolean ignoreMissing = false, it 
+	 * will only return a non-zero (existing) node if all the nodes in the array are present in the 
+	 * tree.  If ignoreMissing = true, it will return the mrca of those nodes passed in the node array
+	 * that are actually present in the tree; nodes in the node array that are not present in the tree 
+	 * are ignored.*/
+	public int mrca(int[] nodes, boolean ignoreMissing);
+	/** Returns most recent common ancestor for an array of taxon numbers; if boolean ignoreMissing = false, it 
+	 * will only return a non-zero (existing) node if all the taxons in the array are present in the 
+	 * tree.  If ignoreMissing = true, it will return the mrca of those taxons passed in the taxon array
+	 * that are actually present in the tree; taxons in the taxon array that are not present in the tree 
+	 * are ignored.*/
+	public int mrcaTaxons(int[] taxons, boolean ignoreMissing);
+	/*End new code added Aug.14.07 oliver*/
+	/** Returns the closest ancestor that has more than one daughter.*/
+	public  int branchingAncestor(int node);
+	/** Returns the closest descendant that has more than one daughter, or is terminal.*/
+	public  int branchingDescendant(int node);
+	/** Returns the next (clockwise) to node connected to anc.  This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public int nextAroundUR(int anc, int node);
+	/** Returns the first (left-most) daughter of node in an UNROOTED sense where the node
+	is treated as descendant from anc. This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int firstDaughterOfNodeUR(int anc, int node);
+	/** Returns the node's sister immediately to the right in an UNROOTED sense where the node
+	is treated as descendant from anc, which is descendant from ancAnc.  If the node has no
+	sister to the right, returns 0 (which is not a valid node designation). This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int nextSisterOfNodeUR(int ancAnc, int anc, int node);
+	/** Returns the first (left-most) daughter of node in an UNROOTED sense where the node
+	is treated as descendant from anc. This is one of the UR procedures, designed
+	to allow unrooted style traversal through the tree*/
+	public  int lastDaughterOfNodeUR(int anc, int node);
+	/** Returns what node number in Mesquite's standard rooted sense corresponds to the anc-node branch.*/
+	public  int nodeOfBranchUR(int anc, int node);
+	//============virtual taxon deletion ==================
+	/** Marks taxon (and any nodes required by it) as deleted virtually in the boolean array.  Used in conjunction with subsequent
+	 * traversals that ignore the deleted area, e.g. for ignoring taxa with missing data.*/
+	public void virtualDeleteTaxon(int it, boolean[] deleted);
+	/** Writes a tree description into the StringBuffer, filtering virtually deleted nodes */
+	public void writeTree(int node, StringBuffer treeDescription, boolean[] deleted);
+	/** Returns the root, filtering virtually deleted nodes*/
+	public  int getRoot(boolean[] deleted);
+	/** Returns whether root is real.  It isn't real if the tree is unrooted.*/
+	public boolean rootIsReal(boolean[] deleted);
+	/** Returns the first (left-most) daughter of node filtering virtuallyDeleted nodes.*/
+	public  int firstDaughterOfNode(int node, boolean[] deleted);
+	/** Returns the last (right-most) daughter of node filtering virtuallyDeleted nodes.*/
+	public  int lastDaughterOfNode(int node, boolean[] deleted);
+	/** Returns the node's sister immediately to the right, filtering virtually deleted nodes.*/
+	public  int nextSisterOfNode(int node, boolean[] deleted);
+	/** Returns the node's sister immediately to the left, filtering virtually deleted nodes.*/
+	public  int previousSisterOfNode(int node, boolean[] deleted);
+	/** Returns the immediate ancestor of node (mother) if node is non-reticulate, filtering virtually deleted nodes*/
+	public  int motherOfNode(int node, boolean[] deleted);
+	/** Returns the branch length of the node, filtered by virtual deletion of nodes.*/
+	public  double getBranchLength(int node, boolean[] deleted);
+	/** Returns the branch length of the node.  If the branch length is unassigned, pass back the double passed in, filtered by virtual deletion of nodes*/
+	public  double getBranchLength(int node, double ifUnassigned, boolean[] deleted);
+	/** Returns whether branch length of node is unassigned, filtering virtually deleted nodes.*/
+	public  boolean branchLengthUnassigned(int node, boolean[] deleted);
+	//============ ==================
+	/** Puts into TreeVector trees from each rerooting within the clade of the node passed*/ 
+	public void makeAllRootings(int cladeRoot, TreeVector trees);
+	/** Returns true if tree has all branch lengths assigned.*/
+	public boolean allLengthsAssigned(boolean includeRoot); 
+	/** Returns true if tree has branch lengths.*/
+	public boolean hasBranchLengths(); 
+	/** Returns the branch length of the node.*/
+	public  double getBranchLength(int node); 
+	/** Returns the branch length of the node.  If the branch length is unassigned, pass back the double passed in*/
+	public  double getBranchLength(int node, double ifUnassigned); 
+	public  boolean branchLengthUnassigned(int node);
+	public double tallestPathAboveNode (int node);
+	public double tallestPathAboveNodeUR (int anc, int node);
+	public double tallestPathAboveNode (int node, double perUnassignedLength);
+	/** returns the node whose distance from the root in branch length is the tallest*/
+	public int tallestNode (int node);
+	public int tallestNode (int node, double perUnassignedLength);
+	/** returns tallest path in number of nodes, not branch length, above a node */
+	public int mostStepsAboveNode (int node);
+	/** returns total of branchlengths from node up to tallest terminal */
+	public double tallestPathAboveNodeUR (int anc, int node, double perUnassignedLength);
+	public double distanceToRoot (int node, boolean countUnassigned, double perUnassignedLength);
+	public boolean getSelected(int node);
+	public boolean anySelected();
+	/** Returns the number of nodes selected in the clade */
+	public int numberSelectedInClade( int node);
+	/** Returns whether there are any selected nodes in the clade */
+	public boolean anySelectedInClade(int node);
+	/** Gets the first node selected in clade of node node */
+	public int getFirstSelected(int node);
+	public int getNumberAssociatedBits();
+	public Bits getAssociatedBits(int index);
+	public Bits getWhichAssociatedBits(NameReference nRef);
+	public boolean getAssociatedBit(NameReference nRef, int index);
+	public int getNumberAssociatedLongs();
+	public LongArray getAssociatedLongs(int index);
+	public LongArray getWhichAssociatedLong(NameReference nRef);
+	public long getAssociatedLong(NameReference nRef, int index);
+	public int getNumberAssociatedDoubles();
+	public DoubleArray getWhichAssociatedDouble(NameReference nRef);
+	public DoubleArray getAssociatedDoubles(int index);
+	public double getAssociatedDouble(NameReference nRef, int index);
+	public int getNumberAssociatedObjects();
+	public ObjectArray getAssociatedObjects(int index);
+	public ObjectArray getWhichAssociatedObject(NameReference nRef);
+	public Object getAssociatedObject(NameReference nRef, int index);
+	public boolean hasName();
+	public String writeTree();
+
+	public boolean ancestorHasNameReference(NameReference nameRef, int node);
+	public int ancestorWithNameReference(NameReference nameRef, int node);
+
+	/** Returns a simple string describing the tree in standard parenthesis notation (Newick standard), excluding associated information except branch lengths.
+	To be used for output to user, not internally (as it may lose information).*/
+	public String writeTreeSimpleByNames();
+	public String writeTreeSimpleByNumbers();
+	public String writeTreeByT0Names(boolean includeBranchLengths);
+	public String writeTree(int byWhat);
+	public String writeTree(int byWhat, boolean associatedUseComments);
+	public String writeTreeSimple(int byWhat, boolean includeAssociated, boolean includeBranchLengths, boolean includeNodeLabels, boolean zeroBased, String delimiter);
+	public String writeClade(int node, int byWhat, boolean associatedUseComments);
+	/** Returns a tree description using the namer to supply taxon names */
+	public String writeTreeWithNamer(TaxonNamer namer, boolean includeBranchLengths, boolean includeAssocAndProperties);
+	public boolean hasNodeLabels();
+	public String getNodeLabel(int node);
+	public boolean nodeHasLabel(int node);
+	public void dispose();
+
+	public int getFileIndex();
+	public void setFileIndex(int index);
+}
+
+
diff --git a/Source/mesquite/lib/TreeContext.java b/Source/mesquite/lib/TreeContext.java
new file mode 100644
index 0000000..60c68c3
--- /dev/null
+++ b/Source/mesquite/lib/TreeContext.java
@@ -0,0 +1,32 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+/**An interface to be used by modules etc. so that employees can find the current tree in their context.*/
+public interface TreeContext extends Context, Listable {
+	public Tree getTree ();
+	public String getContextName ();
+	public void addTreeContextListener (TreeContextListener listener);
+	public void removeTreeContextListener (TreeContextListener listener);
+	public MesquiteModule getTreeSource ();  //returns source of trees for context so that source can avoid using itself as context for modifications (e.g. SourceModifiedTree)
+}
+
+
+
+
diff --git a/Source/mesquite/lib/TreeContextListener.java b/Source/mesquite/lib/TreeContextListener.java
new file mode 100644
index 0000000..4057459
--- /dev/null
+++ b/Source/mesquite/lib/TreeContextListener.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+/* ======================================================================== */
+public interface TreeContextListener {
+	public void treeChanged(Tree tree); 
+	public void disposing(TreeContext context);
+}
+
+
diff --git a/Source/mesquite/lib/TreeDecorator.java b/Source/mesquite/lib/TreeDecorator.java
new file mode 100644
index 0000000..1eb2385
--- /dev/null
+++ b/Source/mesquite/lib/TreeDecorator.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** Used for decorations of tree - shading, node pictures, node labels, etc.  Modules can have classes to
+subclass this to create objects whose methods are called when the tree drawing needs to be updated.  TreeDecorators
+are more purely for display; TreeDisplayExtras often use them.  TreeDisplayExtras are more of a combination of calculation
+and display.*/
+public abstract class TreeDecorator {
+	public TreeDisplay treeDisplay;
+	public TreeDisplayExtra ownerExtra;
+	public static long totalCreated = 0;
+	public TreeDecorator (TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		this.treeDisplay = treeDisplay;
+		this.ownerExtra = ownerExtra;
+		totalCreated++;
+	}
+	
+	public void calculateOnTree(Tree tree, int drawnRoot, Object obj){
+	}
+	public void drawOnTree(Tree tree, int drawnRoot, Object obj, Object obj2, Object obj3, Graphics g){
+	}
+	public void drawOnTree(Tree tree, int drawnRoot, Graphics g){
+	}
+	public String textAtNode(Tree tree, int node) {
+		return "";
+	}
+	public String additionalText(Tree tree, int node) {
+		return "";
+	}
+	public abstract void turnOff();
+	/*  */
+	public void setThemeColor(Color c){
+	}
+	public void useGrayScale(boolean useGray){  
+	}
+	public void useColorTable(MesquiteColorTable table){  
+	}
+	
+	public ColorRecord[] getLegendColorRecords(){
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TreeDisplay.java b/Source/mesquite/lib/TreeDisplay.java
new file mode 100644
index 0000000..432f535
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplay.java
@@ -0,0 +1,559 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** The panel in which a tree is drawn.  This is used within the main tree window, and can be used by other
+modules.  
+If multiple trees need to be drawn, multiple TreeDisplays should be created.  A TreeDisplay is created
+and supervised by a tree draw coordinator module.  A reference to a TreeDisplay is needed 
+for shading and decorating the tree. <P>
+
+Within the graphics Panel which is the TreeDisplay, a special object of class TreeDrawing is
+actually the one responsible for drawing the tree itself.  The TreeDrawing is created by the
+chosen tree drawing module (e.g. diagonal draw tree).  Modules can contribute to the drawing of the
+TreeDisplay, whether shading or node pictures or a simple tree legend, by creating an object
+of class TreeDisplayExtra and adding it to the vector of extras.  The TreeDisplay calls all of 
+the extras after the tree is drawn, in case those extras need to contribute to the TreeDisplay drawing.
+<p> This needs to be fixed up (e.g., fields made private with set and get methods).
+*/
+public class TreeDisplay extends TaxaTreeDisplay  {
+	DrawNamesTreeDisplay namesTask;
+
+	/** The tree being drawn */
+	protected Tree tree;
+	/** A tree which is to be drawn, but which is being held until drawing of the current tree is finished. */
+	protected Tree holdingTree;
+	/** Orientation of the tree unspecified */
+	public static final int FREEFORM = -1;
+	/** Orientation of the tree with tips up */
+	public static final int UP = 0;
+	/** Orientation of the tree with tips to right */
+	public static final int RIGHT = 1;
+	/** Orientation of the tree with tips to left */
+	public static final int LEFT = 2;
+	/** Orientation of the tree with tips down */
+	public static final int DOWN = 3;
+	/** Tree is drawn in circular arrangement of nodes */
+	public static final int CIRCULAR = 4;
+	/** Tree orientation is not yet set; take from node locs module */
+	public static final int NOTYETSET = -1;
+	
+	public static final int FONTSIZECHANGED = 18275;  //for notification
+
+	/**  The margin from the tips to the edge of the drawing field*/
+	public int tipsMargin = -1;
+	/**  If true, then branches are drawn proportional to their lengths*/
+	public boolean showBranchLengths = false;
+	/**  Scaling of the tree drawing*/
+	public double scaling = 1.0;
+	/**  If tree drawn with fixed depth, this is the depth.*/
+	public double fixedDepthScale = 1.0;
+	/**  Records whether fixed depth scale is in use.*/
+	public boolean fixedScalingOn = false;
+	/**  If true, then in text version draw the extra information directly on the tree; otherwise use node lists*/
+	public boolean textVersionDrawOnTree = false;
+	private int dist=8;
+	private int minDist=8;
+	int minForTerminalBoxes = 0;
+	
+	protected boolean showBranchColors = true;
+	
+	
+	/**  The color of the branches*/
+	public Color branchColor;
+	/**  The color of a dimmed branch*/
+	public Color branchColorDimmed;
+	/**  The panel in which the tree is actually drawn.*/
+	private TreeDrawing treeDrawing;
+	/**  The width of the drawn edges (branches)*/
+	private int edgewidth;
+
+	/**  Spacing in pixels between taxa*/
+	private int taxonSpacing;
+	
+	/**  Spacing in pixels between taxa as set by user*/
+	private int fixedTaxonSpacing;
+	/**  Orientaton of the tree*/
+	private int treeOrientation = NOTYETSET;
+	/**  For vert/horizontal trees, is default to permit stretching by default of the tree.  Set by tree drawer*/
+//	public boolean inhibitStretchByDefault = false;
+	/**  For vert/horizontal trees, is default to permit stretching by default of the tree.  Set by tree window*/
+	public boolean autoStretchIfNeeded = false;
+	/**  Is the orientation fixed, or can reorientation be done?*/
+	private boolean allowReorient = true;
+	private MesquiteInteger highlightedBranch  = new MesquiteInteger(0);
+	
+	/**  whether "triangled" clades are shown as simple triangles or not*/
+	private boolean simpleTriangle=true;
+	
+	
+	public TreeDisplay (MesquiteModule ownerModule, Taxa taxa) { 
+		super(ownerModule,taxa);
+		branchColor = Color.black;
+		branchColorDimmed = Color.gray;
+	}
+	public int getMouseX(){
+		return super.getMouseX();
+	}
+	public int getMouseY(){
+		return super.getMouseY();
+	}
+	
+	public Graphics getGraphics(){
+		Graphics g = super.getGraphics();
+		if (g == null)
+			return null;
+		g.clipRect(100, 100, 200, 200);
+		return g;
+	}
+
+	public Font getTaxonNamesFont(){
+		return namesTask.getFont();
+	}
+
+	public Color getBranchColor(int N){
+		if (!showBranchColors)
+			return branchColor;
+		long c = tree.getAssociatedLong(ColorDistribution.colorNameReference, N);
+		Color col=null;
+		if (!tree.anySelected() || tree.getSelected(N)) {
+			if (MesquiteLong.isCombinable(c) && (col = ColorDistribution.getStandardColor((int)c))!=null)
+				return col;
+			else
+				return branchColor;
+		}
+		else {
+			if (MesquiteLong.isCombinable(c) && (col = ColorDistribution.getStandardColorDimmed((int)c))!=null)
+				return col;
+			else
+				return branchColorDimmed;
+		}
+	}
+
+	public Composite setBranchTransparency(Graphics g, int N){
+		if (!showBranchColors)
+			return null;
+		if (tree.anySelected() && !tree.getSelected(N)) {
+			Composite composite = ColorDistribution.getComposite(g);
+			ColorDistribution.setTransparentGraphics(g, 0.5f);
+			return composite;
+		}
+		return null;
+	}
+public void setTreeDrawing(TreeDrawing td) {
+		treeDrawing = td;
+		if (treeDrawing!=null && tree!=null)
+			setTree(tree);
+	}
+	public TreeDrawing getTreeDrawing() {
+		return treeDrawing;
+	}
+	
+	public void setDrawingInProcess(boolean inProgress){
+		this.inProgress= inProgress;
+		if (!inProgress && holdingTree != null) {
+			setTree(holdingTree);
+			//repaint();
+		}
+	}
+	public boolean repaintPending(){
+		return repaintsPending > 0;
+	}
+	public void forceRepaint(){
+		repaint();
+	}
+	
+	Rectangle visRect;
+
+	public Rectangle getVisRect(){
+		return visRect;
+	}
+	public void setVisRect(Rectangle r){
+		visRect = r;
+	}
+	public Tree getTree() {
+		return tree;
+	}
+	
+	public void setTree(Tree tree) {
+		
+		if (tree!=null && tree.getTaxa() != taxa)
+			setTaxa(tree.getTaxa());
+
+	 	if (inProgress)
+	 		holdingTree = tree;
+	 	else {
+			this.tree = tree;
+			if (treeDrawing !=null) {
+				if (tree !=null)
+					treeDrawing.setDrawnRoot(tree.getRoot());
+				else
+					treeDrawing.setDrawnRoot(0);
+			}
+			redoCalculations(1);
+	 		holdingTree = null;
+	 	}
+	}
+
+	public DrawNamesTreeDisplay getDrawTaxonNames(){
+		return namesTask;
+	}
+	public void setDrawTaxonNames(DrawNamesTreeDisplay dtn){
+		namesTask = dtn;
+	}
+
+
+	boolean tndExplicitlySet = false;
+	public void setMinimumTaxonNameDistance(int minForTerminalBoxes, int min) {
+		this.minForTerminalBoxes = minForTerminalBoxes;
+		this.minDist = min;
+		if (!tndExplicitlySet || dist<minDist)
+			dist = minDist;
+	}
+	public void setTaxonNameDistance(int newDist) { 
+		if (newDist>=minDist) {
+			this.dist = newDist;
+			tndExplicitlySet = true;
+		}
+	}
+	public int getTaxonNameDistance() {
+		if (treeDrawing != null && treeDrawing.terminalBoxesRequested())
+			return dist + minForTerminalBoxes;
+		else
+			return dist;
+	}
+	public void setTipsMargin(int margin) {
+		tipsMargin = margin;
+	}
+	public int getTipsMargin() {
+		return tipsMargin;
+	}
+	public MesquiteInteger getHighlightedBranchMI() {  
+		return highlightedBranch;
+	}
+	public int getHighlightedBranch() {  
+		return highlightedBranch.getValue();
+	}
+	public void setHighlightedBranch(int value) {  
+		highlightedBranch.setValue(value);
+	}
+	public void redoCalculations(int code){
+		if (treeDrawing!=null && tree !=null)
+			treeDrawing.recalculatePositions(tree); //to force node locs recalc
+		
+	}
+	public void setEdgeWidth(int sp) {
+		this.edgewidth = sp;
+	}
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+	public void setTaxonSpacing(int sp) {
+		this.taxonSpacing = sp;
+	}
+	public int getTaxonSpacing() {
+		return taxonSpacing;
+	}
+	public void setFixedTaxonSpacing(int sp) {
+		this.fixedTaxonSpacing = sp;
+	}
+	public int getFixedTaxonSpacing() {
+		return fixedTaxonSpacing;
+	}
+	public void addExtra(TreeDisplayExtra extra) {
+		if (extras != null)
+		extras.addElement(extra, false);
+	}
+	public void removeExtra(TreeDisplayExtra extra) {
+		if (extras != null)
+			extras.removeElement(extra, false);
+	}
+	public boolean findExtra(TreeDisplayExtra extra) {
+		if (extras == null)
+			return false;
+		return (extras.indexOf(extra) >= 0);
+	}
+	public void moveExtraToFront(TreeDisplayExtra extra){
+		if (extra == null)
+			return;
+		Vector panels = extra.getPanels();
+		for (int i=0; panels !=null && i<panels.size(); i++) {
+			Panel p = (Panel)panels.elementAt(i);
+			remove(p);
+			add(p);
+		}
+		getExtras().removeElement(extra, false);
+		getExtras().addElement(extra, false);
+		pleaseUpdate(false);
+	}
+	public TreeDisplayExtra[] getMyExtras(MesquiteModule mb) {
+		if (extras != null) {
+			int count = 0;
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+			   	if (ex.getOwnerModule() == mb) 
+			   		 count++;
+		 	}
+		 	if (count == 0)
+		 		return null;
+		 	TreeDisplayExtra[] ee = new TreeDisplayExtra[count];
+			e = extras.elements();
+			count = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+			   	if (ex.getOwnerModule() == mb) 
+			   		ee[count++] = ex;
+		 	}
+		 	return ee;
+		}
+		return null;
+	}
+	public void setTreeAllExtras(Tree tree) {
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+			   	if (ownerModule==null || ownerModule.isDoomed()) 
+			   		return;
+	 			ex.setTree(tree);
+		 	}
+		}
+	}
+	public void drawAllBackgroundExtrasOfPlacement(Tree tree, int drawnRoot, Graphics g, int placement) {
+		if (tree == null || tree.getTaxa().isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+	 			if (ex instanceof TreeDisplayBkgdExtra && ex.getPlacement()==placement) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+				   	ex.drawOnTree(tree, drawnRoot, g);
+	 			}
+	 		}
+		}
+	}
+	public void drawAllBackgroundExtras(Tree tree, int drawnRoot, Graphics g) {
+		drawAllBackgroundExtrasOfPlacement(tree,drawnRoot,g,TreeDisplayExtra.BELOW);
+		drawAllBackgroundExtrasOfPlacement(tree,drawnRoot,g,TreeDisplayExtra.NORMAL);
+		drawAllBackgroundExtrasOfPlacement(tree,drawnRoot,g,TreeDisplayExtra.ABOVE);
+	}
+	public void drawAllExtras(Tree tree, int drawnRoot, Graphics g) {
+		if (tree == null || tree.getTaxa().isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+	 			if (!(ex instanceof TreeDisplayBkgdExtra)) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.drawOnTree(tree, drawnRoot, g);
+	 			}
+	 		}
+		}
+		if (notice!=null)
+			g.drawString(notice, 6, getBounds().height-6);
+		if (drawFrame)
+			g.drawRoundRect(0, 0, getBounds().width, getBounds().height, 10, 10);
+	}
+	public void printAllBackgroundExtras(Tree tree, int drawnRoot, Graphics g) {
+		if (tree == null || tree.getTaxa().isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+	 			if (ex instanceof TreeDisplayBkgdExtra) {
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+	 				ex.printOnTree(tree, drawnRoot, g);
+	 			}
+	 		}
+		}
+	}
+	public void printAllExtras(Tree tree, int drawnRoot, Graphics g) {
+		if (tree == null || tree.getTaxa().isDoomed())
+			return;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+	 			if (!(ex instanceof TreeDisplayBkgdExtra)) {
+	 
+				   	if (ownerModule==null || ownerModule.isDoomed()) 
+				   		return;
+		 			ex.printOnTree(tree, drawnRoot, g);
+	 			}
+	 		}
+		}
+	}
+	
+	
+	/*.................................................................................................................*/
+	public void setOrientation(int orient) {
+		if (allowReorient)
+			treeOrientation = orient;
+	}
+	/*_________________________________________________*/
+	public void setSimpleTriangle(boolean simpleTriangle) {
+		this.simpleTriangle=simpleTriangle;
+	}
+	/*_________________________________________________*/
+	public boolean getSimpleTriangle() {
+		return simpleTriangle;
+	}
+	/*.................................................................................................................*/
+	public int getOrientation() {
+		return treeOrientation;
+	}
+
+	/*.................................................................................................................*/
+	public void setAllowReorientation(boolean allow) {
+		allowReorient = allow;
+	}
+	/*.................................................................................................................*/
+	public boolean getAllowReorientation() {
+		return allowReorient;
+	}
+	public String getTextVersion() {
+		if (tree==null || treeDrawing == null)
+			return "";
+		String s = "Tree Description:  " +  tree.writeTreeSimpleByNames();
+		TextTree tt = new TextTree(tree);
+		String[] nodeNumbers = new String[tree.getNumNodeSpaces()];
+		for (int i=0; i< nodeNumbers.length; i++)
+			nodeNumbers[i] = Integer.toString(i);
+		StringBuffer buff = new StringBuffer(50);
+		tt.drawTreeAsText(tree, buff, nodeNumbers);
+		if (textVersionDrawOnTree)
+			s+= "\n" + buff.toString();
+		else
+			s+= "\nTree with node numbers:\n" + buff.toString();
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+				if (ex!=null){
+					String sEx =null;
+					if (textVersionDrawOnTree)
+						sEx =ex.writeOnTree(tree, treeDrawing.getDrawnRoot());
+					else
+						sEx = ex.infoAtNodes(tree, treeDrawing.getDrawnRoot());
+		 			if (!StringUtil.blank(sEx)) {
+						String owner = "";
+						if (ex.getOwnerModule()!=null)
+							owner = ex.getOwnerModule().getName();
+						s+= "\n\n--------------- " + owner + " ---------------";
+		 				s+= "\n\n"+ sEx + "\n";
+		 			}
+	 			}
+	 		}
+		}
+		return s;
+	}
+	
+	public String getTableVersion() {
+		if (tree==null || treeDrawing == null)
+			return "";
+		StringBuffer sb = new StringBuffer(100);
+		nodesOnTree(tree, treeDrawing.getDrawnRoot(), sb);
+		String s = "nodes" + sb.toString() + "\n" ;
+		
+		String[] nodeNumbers = new String[tree.getNumNodeSpaces()];
+		for (int i=0; i< nodeNumbers.length; i++)
+			nodeNumbers[i] = Integer.toString(i);
+		StringBuffer buff = new StringBuffer(50);
+
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+				if (ex!=null){
+					String sEx = ex.tableAtNodes(tree, treeDrawing.getDrawnRoot());
+		 			if (!StringUtil.blank(sEx)) {
+						String owner = "";
+						if (ex.getOwnerModule()!=null)
+							owner = ex.getOwnerModule().getName();
+						s+= owner + sEx + "\n";
+		 			}
+	 			}
+	 		}
+		}
+		return s;
+	}
+	/**returns list of node as done by textOnTree of TreeDisplayExtras*/
+	private void nodesOnTree(Tree tree, int node, StringBuffer sb){
+		if (tree.nodeIsInternal(node)){
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) 
+				nodesOnTree(tree, daughter, sb);
+		}
+		sb.append("<tab>" + node);
+	}
+
+	public void dispose(){
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w!=null)
+			w.waitUntilDisposable();
+		
+		ownerModule =null;
+		if (treeDrawing !=null)
+			treeDrawing.dispose();
+		treeDrawing = null;
+		if (extras != null) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+	 			ex.dispose();
+	 		}
+		}
+		destroyExtras();
+		extras = null;
+		/*
+		protected Tree tree, holdingTree;
+		public Vector extras;
+		private TreeDrawing treeDrawing;
+		protected MesquiteModule ownerModule;
+		*/
+		super.dispose();
+	}
+
+	public boolean getShowBranchColors() {
+		return showBranchColors;
+	}
+
+	public void setShowBranchColors(boolean showBranchColors) {
+		this.showBranchColors = showBranchColors;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/TreeDisplayActive.java b/Source/mesquite/lib/TreeDisplayActive.java
new file mode 100644
index 0000000..1c9477a
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplayActive.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+public interface TreeDisplayActive    {
+   	 public boolean mouseDownInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g);
+   	 public boolean mouseUpInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g);
+   	 public boolean mouseMoveInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g);
+   	 public boolean mouseDragInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g);
+}
+
+
diff --git a/Source/mesquite/lib/TreeDisplayBkgdExtra.java b/Source/mesquite/lib/TreeDisplayBkgdExtra.java
new file mode 100644
index 0000000..aa746aa
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplayBkgdExtra.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of TreeDisplayExtra.  Used only so that tree drawing knows to call these before the tree
+is drawn.. */
+public abstract class TreeDisplayBkgdExtra extends TreeDisplayExtra {
+	public TreeDisplayBkgdExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+	}
+}
+
diff --git a/Source/mesquite/lib/TreeDisplayDrawnExtra.java b/Source/mesquite/lib/TreeDisplayDrawnExtra.java
new file mode 100644
index 0000000..8af63a1
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplayDrawnExtra.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/** A subclass of TreeDisplayExtra.  Used only so that tree drawing knows that these are drawn above the
+tree and can be reordered.. */
+public abstract class TreeDisplayDrawnExtra extends TreeDisplayExtra {
+	public TreeDisplayDrawnExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+	}
+}
+
diff --git a/Source/mesquite/lib/TreeDisplayExtra.java b/Source/mesquite/lib/TreeDisplayExtra.java
new file mode 100644
index 0000000..4b0003a
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplayExtra.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/** A class used for additional graphical and calculations elements to be drawn and calculated within 
+TreeDisplayes -- tree legends, trace characters, etc. The TreeDisplayExtra is notified when the cursor 
+is moved over a branch and so on, and when the tree is drawn the TreeDisplayExtra is notified via drawOnTree so that
+it can add its items to the tree.*/
+public abstract class TreeDisplayExtra implements Listable, OwnedByModule {  
+	public TreeDisplay treeDisplay;
+	public MesquiteModule ownerModule;
+	public static long totalCreated = 0;
+	public static int BELOW = 1;
+	public static int NORMAL = 2;
+	public static int ABOVE = 3;
+	int placement=NORMAL;
+	
+	private Vector panels = new Vector();
+	public TreeDisplayExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay) {
+		this.treeDisplay = treeDisplay;
+		this.ownerModule=ownerModule;
+		totalCreated++;
+	}
+	
+	public MesquiteModule getOwnerModule(){
+		return ownerModule;
+	}
+	
+	public String getName(){
+		if (ownerModule !=null)
+			return ownerModule.getName();
+		else
+			return getClass().getName();
+	}
+
+	public int getPlacement(){
+		return placement;
+	}
+
+	public void setPlacement(int placement){
+		this.placement = placement;
+	}
+	
+	public TreeDisplay getTreeDisplay(){
+		return treeDisplay;
+	}
+	public void dispose(){
+		ownerModule =null;
+		treeDisplay=null;
+	}
+	/**notifies the TreeDisplayExtra that the tree has changed, so it knows to redo calculations, and so on*/
+	public abstract void setTree(Tree tree);
+	/**draw on the tree passed*/
+	public abstract void drawOnTree(Tree tree, int drawnRoot, Graphics g);
+	/**print on the tree passed*/
+	public abstract void printOnTree(Tree tree, int drawnRoot, Graphics g);
+	
+	/**return true if any notes at nodes in clade*/
+	private boolean anyText(Tree tree, int node){
+		if (!StringUtil.blank(textAtNode(tree, node)))
+			return true;
+		if (tree.nodeIsInternal(node)){
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+					if (anyText(tree, daughter))
+						return true;
+			}
+		}
+		return false;
+	}
+	/**return a text version of information on tree*/
+	private String textOnTree(Tree tree, int node){
+		String s="";
+		if (tree.nodeIsInternal(node)){
+			s+='(';
+			boolean first = true;
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+					if (!first)
+						s+=",";
+					s+= textOnTree(tree, daughter);
+			}
+			s+=')';
+		}
+		s+="[" + textAtNode(tree, node) + "]";
+		return s;
+	}
+	/**return a text version of information on tree*/
+	private void textOnTree(Tree tree, int node, String[] nodeStrings){
+		if (tree.nodeIsInternal(node)){
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) 
+					textOnTree(tree, daughter, nodeStrings);
+		}
+		nodeStrings[node]= textAtNode(tree, node);
+	}
+	/**return a text version of information on tree, displayed on a text version of the tree*/
+	public String writeOnTree(Tree tree, int node){
+		if (!tree.nodeInTree(node))
+			node = tree.getRoot();
+		String legend = textForLegend();
+		String notes = additionalText(tree, node);
+		if (StringUtil.blank(notes))
+			notes = legend;
+		else
+			notes = legend + "\n" + notes;
+		boolean textAtNodes =anyText(tree, node);
+		if (textAtNodes) {
+			String[] nodeStrings= new String[tree.getNumNodeSpaces()];
+			textOnTree(tree, node, nodeStrings);
+			TextTree tt = new TextTree(tree);
+			StringBuffer buff = new StringBuffer(50);
+			tt.drawTreeAsText(tree, buff, nodeStrings);
+			return notes + "\n\n" + buff.toString();
+		}
+		else if (!StringUtil.blank(notes))
+			return notes;
+		
+		return "";
+	}
+	/**return a text version of information on tree, displayed as list of nodes with information at each*/
+	public String infoAtNodes(Tree tree, int node){
+		if (!tree.nodeInTree(node))
+			node = tree.getRoot();
+		String legend = textForLegend();
+		String notes = additionalText(tree, node);
+		if (StringUtil.blank(notes))
+			notes = legend;
+		else
+			notes = legend + "\n" + notes;
+		boolean textAtNodes =anyText(tree, node);
+		if (textAtNodes) {
+			String[] nodeStrings= new String[tree.getNumNodeSpaces()];
+			textOnTree(tree, node, nodeStrings);
+			StringBuffer buff = new StringBuffer(50);
+			for (int i=0; i<nodeStrings.length; i++)
+				if (!StringUtil.blank(nodeStrings[i]))
+					buff.append("node " + i + ":  " + nodeStrings[i] + "\n");
+					
+			return notes + "\n\n" + buff.toString();
+		}
+		else if (!StringUtil.blank(notes))
+			return notes;
+		
+		return "";
+	}
+	/**return a text version of information on tree, as a table, displayed as list of nodes with information at each*/
+	public String tableAtNodes(Tree tree, int node){
+		if (!tree.nodeInTree(node))
+			node = tree.getRoot();
+		boolean textAtNodes =anyText(tree, node);
+		if (textAtNodes) {
+			String[] nodeStrings= new String[tree.getNumNodeSpaces()];
+			textOnTree(tree, node, nodeStrings);
+			StringBuffer buff = new StringBuffer(50);
+			for (int i=0; i<nodeStrings.length; i++)
+				if (!StringUtil.blank(nodeStrings[i]))
+					buff.append("<tab>" + nodeStrings[i]);
+					
+			return buff.toString();
+		}
+		
+		return "";
+	}
+	/** Returns true if this extra wants the taxon to have its name underlined */
+	public boolean getTaxonUnderlined(Taxon taxon){
+		return false;
+	}
+	/** Returns the color the extra wants the taxon name colored.*/
+	public Color getTaxonColor(Taxon taxon){
+		return null;
+	}
+	/** Returns any strings to be appended to taxon name.*/
+	public String getTaxonStringAddition(Taxon taxon){
+		return null;
+	}
+	/** Returns true if this extra wants the clade to have its label underlined */
+	public boolean getCladeLabelUnderlined(String label, int N){
+		return false;
+	}
+	/** Returns the color the extra wants the clade label colored.*/
+	public Color getCladeLabelColor(String label, int N){
+		return null;
+	}
+	/** Returns any strings to be appended to clade label.*/
+	public String getCladeLabelAddition(String label, int N){
+		return null;
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		return "";
+	}
+	/**return text to be placed in legends*/
+	public String textForLegend(){
+		return "";
+	}
+	/**return any additional explanatory text, e.g. if there is extensive information too verbose for a legend but which should be output to text view*/
+	public String additionalText(Tree tree, int node){
+		return "";
+	}
+
+	public  int findBranch(Tree tree, int drawnRoot, int x, int y){return -1;} // should be renamed; need method to tell assistant to react to mousedown that might be in its node picture etc.
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just exited branch N*/
+	public void cursorExitBranch(Tree tree, int N, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just touched branch N*/
+	public void cursorTouchBranch(Tree tree, int N, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just touched the field (not in a branch or taxon)*/
+	public void cursorTouchField(Tree tree, Graphics g, int x, int y, int modifiers){}
+	/**to inform TreeDisplayExtra that cursor has just entered name of terminal taxon M*/
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just exited name of terminal taxon M*/
+	public void cursorExitTaxon(Tree tree, int M, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just touched name of terminal taxon M*/
+	public void cursorTouchTaxon(Tree tree, int M, Graphics g){}
+	/**to inform TreeDisplayExtra that cursor has just moved OUTSIDE of taxa or branches*/
+	public void cursorMove(Tree tree, int x, int y, Graphics g){}
+	
+	public void addPanelPlease(Panel p){
+		if (panels == null || treeDisplay == null || ownerModule == null)
+			return;
+		panels.addElement(p);
+		treeDisplay.addPanelPlease(p);
+		MesquiteWindow w = ownerModule.containerOfModule();
+		if (w == null)
+			return;
+		w.checkPanelPositionsLegal();
+		
+	}
+	public void removePanelPlease(Panel p){
+		if (panels !=null)
+			panels.removeElement(p);
+		if (treeDisplay != null)
+			treeDisplay.removePanelPlease(p);
+	}
+	protected Vector getPanels(){
+		return panels;
+	}
+
+	public void turnOff() {
+		if (treeDisplay==null)
+			return;
+		treeDisplay.removeExtra(this);
+		treeDisplay.repaint();
+	}
+	
+}
+
diff --git a/Source/mesquite/lib/TreeDisplayLegend.java b/Source/mesquite/lib/TreeDisplayLegend.java
new file mode 100644
index 0000000..e06ba8c
--- /dev/null
+++ b/Source/mesquite/lib/TreeDisplayLegend.java
@@ -0,0 +1,140 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/** Legends for TreeDisplays, e.g. the TraceCharacter Legend. */
+public abstract class TreeDisplayLegend extends ResizableLegend {
+	private TreeDisplay treeDisplay;
+	private int oldOrientation;
+
+	public TreeDisplayLegend (TreeDisplay treeDisplay, int defaultWidth, int defaultHeight) {
+		super(defaultWidth, defaultHeight);
+		this.treeDisplay = treeDisplay;
+		defaultOffsets();
+	}
+	/*.................................................................................................................*/
+	public void defaultOffsets() {
+		if (treeDisplay==null)
+			return;
+		int buffer = 20;
+		if (treeDisplay.getOrientation() == TreeDisplay.DOWN) {
+			setOffsetX(buffer);
+			setOffsetY(buffer);
+		}
+		else if (treeDisplay.getOrientation() == TreeDisplay.RIGHT) {
+			setOffsetX(buffer);
+			setOffsetY(-(defaultHeight+buffer));
+		}
+		else {
+			setOffsetX(-(defaultWidth+buffer));
+			setOffsetY(-(defaultHeight+buffer));
+		}
+		oldOrientation = treeDisplay.getOrientation();
+	}
+	public void adjustLocation() {
+		if (treeDisplay==null)
+			return;
+		if (oldOrientation != treeDisplay.getOrientation())
+			defaultOffsets();
+		int legendX=0;
+		int legendY =0;
+		int conWidth=treeDisplay.getWidth();
+		int conHeight =treeDisplay.getHeight();
+		int conX = 0;
+		int conY = 0;
+		if (constrainingContainer !=null ) {
+			conWidth = constrainingContainer.getBounds().width;
+			//conX = constrainingContainer.getX();
+			conHeight = constrainingContainer.getBounds().height;
+			//conY = constrainingContainer.getY();
+		}
+		else if (constrainingRectangle != null){
+			conWidth = constrainingRectangle.width;
+			//conX = constrainingRectangle.x;
+			
+			conHeight = constrainingRectangle.height;
+			//conY = constrainingRectangle.y;
+		}
+		int baseX;
+		int baseY;
+		if (treeDisplay.getOrientation() == TreeDisplay.UP) {
+			baseX = 0;
+			baseY =  conHeight;
+		}
+		else if (treeDisplay.getOrientation() == TreeDisplay.DOWN) {
+			baseX = 0;
+			baseY = 0;
+		}
+		else if (treeDisplay.getOrientation() == TreeDisplay.RIGHT) {
+			baseX = 0;
+			baseY = 0;
+		}
+		else if (treeDisplay.getOrientation() == TreeDisplay.LEFT) {
+			baseX = conWidth;
+			baseY = 0;
+		}
+		else {
+			baseX = 0;
+			baseY = conHeight;
+		}
+		baseX += conX;
+		baseY += conY;
+		legendX = baseX+getOffsetX();
+		legendY = baseY+getOffsetY();
+		if (constrainingRectangle == null && constrainingContainer == null)	 {
+		}
+		else {
+			if (legendX + legendWidth>conX + conWidth) {
+				setOffsetX(conWidth+conX-baseX-legendWidth);
+				legendX = baseX+getOffsetX();
+			}
+			if (legendX<conX) {
+				setOffsetX(-baseX+conX+4);
+				legendX = baseX+getOffsetX();
+			}
+
+			if (legendY + legendHeight>conY + conHeight) {
+				setOffsetY(conHeight +conY- baseY-legendHeight);
+				legendY = baseY+getOffsetY();
+			}
+			if (legendY<conY) {
+				setOffsetY(-baseY+conY+4);
+				legendY = baseY+getOffsetY();
+			}
+		}
+		if ((legendX!=getBounds().x) || (legendY!=getBounds().y)) {
+			setLocation(legendX, legendY);
+			if (okToRecurse){
+				MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+				okToRecurse = false;
+				if (w != null)
+					w.checkPanelPositionsLegal();
+				okToRecurse = true;
+			}
+			repaint();
+		}
+	}
+	boolean okToRecurse = true;
+	/*public void mouseUp (int modifiers, int x, int y, MesquiteTool tool) {
+	   	super.mouseUp(modifiers, x, y, tool);
+	   	treeDisplay.pleaseUpdate(false);
+		repaint();
+	}*/
+}
+
diff --git a/Source/mesquite/lib/TreeDrawing.java b/Source/mesquite/lib/TreeDrawing.java
new file mode 100644
index 0000000..194f688
--- /dev/null
+++ b/Source/mesquite/lib/TreeDrawing.java
@@ -0,0 +1,411 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.TaxonPolygon;
+/*===  Mesquite Basic Class Library:  Trees    ===*/
+/*===  the basic classes used by the trunk of Mesquite and available to the modules    ===*/
+/* This sublibrary includes taxa and tree classes */
+
+
+
+/* ��������������������������� trees ������������������������������� */
+/* ======================================================================== */
+/**This is the base class for the drawing of the tree.  It contains the information about
+the number of nodes, and the x and y positions of the nodes.  It should be subclassed by tree drawing modules, 
+so that they can add their own needed field (like polygons for the
+tree branches.  TreeDrawings are typically used within TreeDisplays.*/
+
+public abstract class TreeDrawing  {
+	public final static double ATNODE=1.0;
+	public final static double EDGESTART = 0.0;
+	public final static double EDGEEND = 1.0;
+	public final static int MINNODEWIDTH = 6;
+	public final static int ACCEPTABLETOUCHWIDTH = 10;
+	public final static boolean SHOWTOUCHPOLYS = false;
+	public int[] x; //x positions of nodes
+	public int[] y; //y positions of nodes
+	public double[] z; //z positions of nodes (closeness to viewer, smaller numbers closer)
+	public int[] lineBaseX; //base of line on which to draw labels etc.
+	public int[] lineBaseY; 
+	public int[] lineTipX; //tip of line on which to draw labels etc.
+	public int[] lineTipY; 
+	/**labelOrientation indicates where label is to be drawn w.r.t. node, in degrees. 0 = normal horizontal 
+	writing to right of node, as would be done for a tree with orientation RIGHT.
+	This does not represent simple rotation, i.e. 180 is on left side, but the writing is not upside down.  Thus
+	0 would be appropriate for tree oriented RIGHT, 90 for tree DOWN, 180 for tree LEFT, 270 for tree UP */
+	public int[] labelOrientation; 
+	
+	/** namesFollowLines indicates whether orientation of names follows the base to tip line of the branch.
+	Supercedes labelOrientation for terminals and permits Java2D rotation of taxon names in circular tree */
+	public boolean namesFollowLines = false;
+
+	/** namesAngle indicates rotation of names from default in radians  (useful only for Java 1.2 or higher)*/
+	public double namesAngle = MesquiteDouble.unassigned;
+
+	public int numNodes;
+	public TreeDisplay treeDisplay;//TODO: many of these should be private fields!!!
+	private int enableTerminalBoxesRequests = 0;
+	private int drawnRoot=-1;
+	public static long totalCreated = 0;
+	public TaxonPolygon[] namePolys;
+	
+	public TreeDrawing (TreeDisplay treeDisplay, int numNodes) {
+		this.treeDisplay = treeDisplay;
+		totalCreated++;
+		resetNumNodes(numNodes);
+	}
+	public void resetNumNodes(int numNodes){
+		if (this.numNodes == numNodes && x != null)
+			return;
+		this.numNodes=numNodes;
+		totalCreated++;
+		x = new int[numNodes];
+		y = new int[numNodes];
+		z = new double[numNodes];
+		labelOrientation = new int[numNodes];
+		lineBaseX = new int[numNodes];
+		lineBaseY = new int[numNodes];
+		lineTipX = new int[numNodes];
+		lineTipY = new int[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			x[i]=0;
+			y[i]=0;
+			z[i]=MesquiteInteger.unassigned;
+			lineBaseX[i]=0;
+			lineBaseY[i]=0;
+			lineTipX[i]=0;
+			lineTipY[i]=0;
+			labelOrientation[i] = MesquiteInteger.unassigned;
+		}
+	}
+
+	public int getDrawnRoot(){
+		return drawnRoot;
+	}
+	public void setDrawnRoot(int node){
+		drawnRoot = node;
+	}
+	public int getBranchCenterX(int node){
+		return Math.abs(lineBaseX[node] + lineTipX[node])/2;
+}
+	public int getBranchCenterY(int node){
+		return Math.abs(lineBaseY[node] + lineTipY[node])/2;
+}
+	
+	public int getNodeValueTextBaseX(int node, int edgewidth,  int stringwidth, int fontHeight, boolean horizontalText){
+		int baseX = x[node];
+		if (horizontalText){
+			baseX = baseX - stringwidth/2;
+		}
+		else {
+			baseX = baseX - fontHeight*2;
+		}
+		return baseX;
+	}
+	public int getNodeValueTextBaseY(int node, int edgewidth, int stringwidth, int fontHeight, boolean horizontalText){
+		int baseY = y[node];
+		if (horizontalText){
+			baseY = baseY - fontHeight;
+		}
+		else {
+			baseY = baseY + stringwidth/2;
+		}
+		return baseY;
+	}
+
+
+	/** Sets the tree.  This is done outside of a paint() call, and is the place that any complex calculations should be performed! */
+	public abstract void recalculatePositions(Tree tree) ;
+
+	/** Draw tree in graphics context */
+	public abstract void drawTree(Tree tree, int drawnRoot, Graphics g) ;
+	
+	/** Fill branch N with current color of graphics context */
+	public abstract void fillBranch(Tree tree, int N, Graphics g);
+	
+
+	/*_________________________________________________*/
+	/** Does the basic inverting of the color of a branch **/
+	public  void fillBranchInverted (Tree tree, int N, Graphics g) {
+		if (GraphicsUtil.useXORMode(g, true))  {
+			g.setColor(Color.black);
+			g.setXORMode(Color.white);  //for some reason color makes no difference in MacOS, but is inversion color in Win95 
+		//	GraphicsUtil.setToXOR(g);
+			//	g.setColor(Color.yellow);
+			try{
+				fillBranch(tree, N, g);
+			}
+			catch (InternalError e){  //added because of bug in jdk 1.7_45 on windows, crashing with internal error on getRaster
+
+			}
+			g.setPaintMode();
+			g.setColor(Color.black);
+		}
+	}
+	/*_________________________________________________*/
+	/** Does the basic highlighting of a branch **/
+	public  void highlightBranch (Tree tree, int N, Graphics g) {
+			g.setColor(Color.yellow);
+			try{
+				fillBranch(tree, N, g);
+			}
+			catch (InternalError e){  //added because of bug in jdk 1.7_45 on windows, crashing with internal error on getRaster
+
+			}
+			g.setPaintMode();
+			g.setColor(Color.black);
+	}
+	/*_________________________________________________*/
+	/** Does the basic unhighlighting of a branch **/
+	public  void unhighlightBranch (Tree tree, int N, Graphics g) {
+		treeDisplay.repaint();
+	}
+	
+	/** Fill branch N to indicate missing data */
+	public  void fillBranchWithMissingData(Tree tree, int N, Graphics g){  //default; to be overridden for better indication of equivocal
+		Color c = g.getColor();
+		if (g instanceof Graphics2D){
+			Graphics2D g2 = (Graphics2D)g;
+			g2.setPaint(GraphicsUtil.missingDataTexture);
+		}
+		else
+			g.setColor(Color.lightGray);
+		fillBranch(tree, N, g);
+		if (c!=null) g.setColor(c);
+	}
+
+	
+	/** Fill branch N with indicated set of colors */
+	public abstract void fillBranchWithColors(Tree tree, int N, ColorDistribution colors, Graphics g);
+
+	boolean fillBranchColorSequenceWarned = false;
+	/** Fill branch N with indicated set of colors as a sequence, e.g. for stochastic character mapping.  This is not abstract because many tree drawers would have difficulty implementing it */
+	public void fillBranchWithColorSequence(Tree tree, int N, ColorEventVector colors, Graphics g){
+		if (!fillBranchColorSequenceWarned){
+			fillBranchColorSequenceWarned = true;
+			MesquiteModule module = MesquiteTrunk.mesquiteTrunk;
+			if (treeDisplay != null && treeDisplay.getOwnerModule() != null)
+				module = treeDisplay.getOwnerModule();
+			module.alert("The current tree form does not support sequences of changes along branches.  Try selecting another, such as Classic Square Tree.");
+		}
+	}
+	
+	public boolean isAtNode(MesquiteDouble fraction) {
+		return fraction.isCloseEnough(ATNODE,0.00001);
+	}
+	
+	/** If true, then the TreeDrawing should draw the nodes distinctly.  Currently this is only for debugging purposes, so that the node boundaries are evident */
+	public boolean emphasizeNodes() {
+		return false;
+	}
+
+	/*   */
+	 public void redCrosses(Graphics g, Tree tree, int node) {
+		g.setColor(Color.red);
+		MesquiteNumber xC = new MesquiteNumber();
+		MesquiteNumber yC = new MesquiteNumber();
+		MesquiteDouble angle = new MesquiteDouble();
+		getMiddleOfBranch(tree,node,xC, yC, angle);			
+		g.drawLine(xC.getIntValue()-3, yC.getIntValue()-3, xC.getIntValue()+3, yC.getIntValue ()+3);
+		g.drawLine(xC.getIntValue()-3+1, yC.getIntValue()-3, xC.getIntValue()+3+1, yC.getIntValue ()+3);
+		g.drawLine(xC.getIntValue()-3, yC.getIntValue()+3, xC.getIntValue()+3, yC.getIntValue ()-3);
+		g.drawLine(xC.getIntValue()-3+1, yC.getIntValue()+3, xC.getIntValue()+3+1, yC.getIntValue ()-3);
+		GraphicsUtil.drawAngledLine(g, xC.getIntValue(), yC.getIntValue(), angle.getValue(), 100);
+	}
+	/**/
+	
+
+		public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+		xValue.deassignAllValues();
+		yValue.deassignAllValues();
+		angle.setToUnassigned();
+	}
+
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		if ((x-this.x[node])*(x-this.x[node]) + (y-this.y[node])*(y-this.y[node]) < getEdgeWidth()*getEdgeWidth()/4) //use radius
+			return true;
+		else
+			return false;
+	}
+
+	/*_________________________________________________*/
+	public int getNodeWidth() {
+		int w = getEdgeWidth()+4;
+		if (w<MINNODEWIDTH) return MINNODEWIDTH;
+		return w;
+	}
+
+	/** Find which branch is at x,y (-1 if none) */
+	public abstract int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction);
+	
+	/** Put in a request to enable terminal boxes (this allows taxon names to be drawn to leave room)*/
+	public void incrementEnableTerminalBoxes(){
+		enableTerminalBoxesRequests++;
+	}
+	/** Withdraw request to enable terminal boxes (this allows taxon names to be drawn to leave room)*/
+	public void decrementEnableTerminalBoxes(){
+		enableTerminalBoxesRequests--;
+		if (enableTerminalBoxesRequests<0)
+			enableTerminalBoxesRequests=0;
+	}
+	/** Returns if terminal boxes requested*/
+	public boolean terminalBoxesRequested(){
+		return (enableTerminalBoxesRequests>0);
+	}
+	/** Fill terminal box with current color. */
+	public abstract void fillTerminalBox(Tree tree, int node, Graphics g);
+	
+	/** Fill terminal box of node "node" with indicated set of colors */
+	public abstract void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g);
+	
+	/*.................................................................................................................*/
+	/** Find which terminal box is at x,y */
+	public int findTerminalBox(Tree tree,  int N, int x, int y) {
+		int foundTaxon =-1;
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+
+			int taxonNumber = tree.taxonNumberOfNode(N);
+			if (taxonNumber<0) {
+				//MesquiteMessage.warnProgrammer("error: negative taxon number found in findNameOnTree");
+				return -1;
+			}
+			if (taxonNumber>=tree.getTaxa().getNumTaxa()) {
+				MesquiteMessage.warnProgrammer("error:  taxon number too large found in findTerminalBox (" + taxonNumber + ") node: " + N); 
+				return -1;
+			}
+			if (isInTerminalBox(tree, N, x, y))
+					return taxonNumber;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d) && foundTaxon==-1; d = tree.nextSisterOfNode(d)){
+				foundTaxon=findTerminalBox(tree, d, x, y);
+			}
+		}
+		return foundTaxon;
+	}
+	public int findTerminalBox(Tree tree, int x, int y){
+		int drawnRoot = getDrawnRoot(); 
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		return findTerminalBox(tree, drawnRoot, x, y); 
+	}
+	
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/** Draw highlight for branch N with current color of graphics context */
+	public void drawHighlight(Tree tree, int N, Graphics g, boolean flip){}
+
+/** This allows access to edgeWidths */
+	public abstract int getEdgeWidth();
+	
+	/** project point x,y onto the line between N's lineBase to lineTip. */
+	public Point projectionOnLine(int N, int x, int y) {
+		Point thePoint= new Point(x, y);
+		try {
+			if (lineTipX[N] == lineBaseX[N]) {   //slope infinite; projection uses same y and sets x to be lineBaseX
+				thePoint.x =lineBaseX[N];
+			}
+			else if (lineTipY[N] == lineBaseY[N]) {  //slope zero; projection uses same x and sets y to be lineBaseY
+				thePoint.y =lineBaseY[N];
+			}
+			else {
+				double m = (lineTipY[N]-lineBaseY[N])*1.0/(lineTipX[N] - lineBaseX[N]);
+				//MesquiteModule.mesquiteTrunk.logln(" m " + MesquiteDouble.toString(m));
+				double msquare = m*m;
+				double newY = (msquare)/(msquare+1)*((x-lineTipX[N])/m + (lineTipY[N]/msquare) + (y));
+				double newX = m* (y-newY) + x;
+				//MesquiteModule.mesquiteTrunk.logln(" y " + MesquiteDouble.toString(newY));
+				//MesquiteModule.mesquiteTrunk.logln(" x " + MesquiteDouble.toString(newX));
+				thePoint.y = (int)newY;
+				thePoint.x = (int)newX;
+			}
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+		}
+		catch (NullPointerException e) {
+		}
+		return thePoint;
+		
+	}
+	
+	/** Choose point on line from lineBase to lineTip that corresponds to the i'th of "total" units along line. */
+	public Point placeOnLine(int N, int i, int total) {
+		Point thePoint= new Point();
+		try {
+			if (lineTipX[N] == lineBaseX[N]) {   //slope infinite; projection uses same y and sets x to be lineBaseX
+				thePoint.x =lineBaseX[N];
+			}
+			else if (lineTipY[N] == lineBaseY[N]) {  //slope zero; projection uses same x and sets y to be lineBaseY
+				thePoint.y =lineBaseY[N];
+			}
+			else {
+				double m = (lineTipY[N]-lineBaseY[N])*1.0/(lineTipX[N] - lineBaseX[N]);
+				double msquare = m*m;
+				//double newY = (msquare)/(msquare-1)*((x-lineTipX[N])/m + (lineTipY[N]/msquare) + (y));
+				//double newX = m* (y-newY) + x;
+				//thePoint.y =( int)newY;
+				//thePoint.x =(int) newX;
+			}
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+		}
+		catch (NullPointerException e) {
+		}
+		return thePoint;
+	}
+	public void setHighlightsOn(boolean on){
+		/*
+		if (on) {
+			if (highlightThread==null) 
+				highlightThread = new HighlightThread(treeDisplay);
+			if (!highlightThread.isOn())
+				highlightThread.start();
+		}
+		else {
+			if (highlightThread!=null) {
+				highlightThread.stop();
+				highlightThread.dispose();
+			}
+			highlightThread = null;
+		}
+		*/
+		
+	}
+	public boolean getHighlightsOn(){
+		return false;
+		//return (highlightThread!=null);
+	}
+	public void dispose(){
+		treeDisplay = null;
+		setHighlightsOn(false);
+	}
+	public void finalize() throws Throwable {
+		setHighlightsOn(false);
+		super.finalize();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/TreeReference.java b/Source/mesquite/lib/TreeReference.java
new file mode 100644
index 0000000..9abf254
--- /dev/null
+++ b/Source/mesquite/lib/TreeReference.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.math.*;
+
+
+public class TreeReference {
+	long id, versionNumber, topologyVersion, branchLengthsVersion;
+	public TreeReference(){
+	}
+	
+	public long getID(){
+		return id;
+	}
+	public long getVersionNumber(){
+		return versionNumber;
+	}
+	public long getTopologyVersion(){
+		return topologyVersion;
+	}
+	public long getBranchLengthsVersion(){
+		return branchLengthsVersion;
+	}
+	public void setID(long n){
+		id = n;
+	}
+	public void setVersionNumber(long n){
+		versionNumber = n;
+	}
+	public void setTopologyVersion(long n){
+		topologyVersion = n;
+	}
+	public void setBranchLengthsVersion(long n){
+		branchLengthsVersion = n;
+	}
+	
+	public String toString(){
+		return ("Tree id " + id + "  version number: " + versionNumber + "  topology version: " + topologyVersion + "  branch lengths version: " + branchLengthsVersion);
+	}
+	/*-----------------------------------------*/
+	/* Returns whether tree is the same id, topology, branch lengths and or full version */
+ 	public boolean equals(TreeReference tr){
+ 		if (tr==null)
+ 			return false;
+ 		if (tr.getID() != getID())
+ 			return false;
+ 		if (tr.getTopologyVersion() != getTopologyVersion())
+ 			return false;
+ 		if ((tr.getBranchLengthsVersion() != getBranchLengthsVersion()))
+ 			return false;
+ 		if ((tr.getVersionNumber() != getVersionNumber()))
+ 			return false;
+ 		return true;
+ 	}
+}
+
diff --git a/Source/mesquite/lib/TreeTool.java b/Source/mesquite/lib/TreeTool.java
new file mode 100644
index 0000000..a2d274c
--- /dev/null
+++ b/Source/mesquite/lib/TreeTool.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+	/** This subclass of MesquiteTool is used in Tree windows for manipulating the tree, etc.  Each tool
+	represents a cursor in the tool palette.  Each has MesquiteCommands attached.<p>
+	When a cursor is chosen, its corresponding MesquiteTool is set as
+	the current tool.  The tool When a mousedown etc. event occurs on the tree, the tool is passed the tree and the mouse click 
+	parameters -- the branch first touched, the branch dropped upon, etc.  If the tool has a touchedCommand, or droppedCommand,
+	or touchedTaxonCommand, then this command is executed when the tool is informed of the event.  As argument to the command,
+	the branch number(s) are passed in a string.
+	*/
+public class TreeTool extends TaxaTool {
+
+
+	public TreeTool (Object initiator,  String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String fullDescription, String explanation) {
+		super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation);
+	}
+
+
+	public void branchTouched (int N, int x, int y, Tree tree, int modifiers) {
+		if (touchedCommand!=null) {
+			touchedCommand.doItMainThread(Integer.toString(N) + " " + Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", touchedCommand, this), false, false);  
+		}
+	}
+	public void branchTransferred (int fromN, int toN, Tree tree, int modifiers) {
+		if (transferredCommand!=null)
+			transferredCommand.doItMainThread(Integer.toString(fromN) + " " + Integer.toString(toN) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", transferredCommand, this), false, false);  
+	}
+	public void branchDropped (int N, int x, int y, Tree tree, int modifiers) {
+		if (droppedCommand!=null)
+			droppedCommand.doItMainThread(Integer.toString(N) + " " + Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", droppedCommand, this), false, false);  
+	}
+
+
+	public void taxonTouched (int M, Tree tree, int modifiers) {
+		taxonTouched(M,modifiers);
+	}
+	public void taxonMoveOver (int M, Tree tree, int modifiers) {
+		taxonMoveOver(M,modifiers);
+	}
+	public void taxonMouseUp (int M, int x, int y, Tree tree, int modifiers) {
+		taxonMouseUp(M,x, y, modifiers);
+	}
+	public boolean fieldTouched (int x, int y, Tree tree, int modifiers) {
+		return fieldTouched(x,y,modifiers);
+	}
+	public boolean fieldMouseUp (int x, int y, Tree tree, int modifiers) {
+		return fieldMouseUp(x,y,modifiers);
+	}
+	public boolean moved (int x, int y,Tree tree, int modifiers) {
+		return moved(x,y,modifiers);
+	}
+	public void branchDragged (int N, int x, int y, Tree tree, int modifiers) {
+		if (draggedCommand!=null)
+			draggedCommand.doItMainThread(Integer.toString(N) + " " + Integer.toString(x)+ " " + Integer.toString(y) + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", draggedCommand, this), false, false);  
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/TreeUtil.java b/Source/mesquite/lib/TreeUtil.java
new file mode 100644
index 0000000..82adeca
--- /dev/null
+++ b/Source/mesquite/lib/TreeUtil.java
@@ -0,0 +1,120 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.Checkbox;
+import java.awt.Label;
+
+import mesquite.assoc.lib.*;
+
+public class TreeUtil {
+	
+	/** Returns true iff the two trees have the same topologies.  The two trees must use the same block of taxa */
+	public static boolean identicalTopologies (Tree tree1, Tree tree2, boolean checkBranchLengths) {
+		if (tree1==null || tree2==null)
+			return false;
+		if (tree1.getTaxa().equals(tree2.getTaxa())) {
+			return tree1.equalsTopology(tree2, checkBranchLengths);
+		}
+		return false;
+	}
+	/** Returns true iff the contained taxa in all containing taxa are monophyletic . */
+	public static boolean containedAllMonophyletic (Tree containedTree, Tree containingTree, TaxaAssociation association) {
+		if (containedTree==null || containingTree==null || association == null)
+			return false;
+		Taxa containingTaxa = containingTree.getTaxa();
+		
+		for (int outer=0;  outer<containingTaxa.getNumTaxa(); outer++) {  
+			Bits associates = association.getAssociatesAsBits(containingTaxa, outer);
+			if (!containedTree.isClade(associates))
+				return false;
+		}
+		return true;
+	}
+	
+		
+	/*.................................................................................................................*/
+	public  static boolean showAssociatedChoiceDialog(Associable tree, ListableVector names, String message, MesquiteModule module) {
+		if (tree == null)
+			return false;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ListableVector v = new ListableVector();
+		int num = tree.getNumberAssociatedDoubles();
+		boolean[] shown = new boolean[num + names.size()]; //bigger than needed probably
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (da != null){
+				v.addElement(new MesquiteString(da.getName(), ""), false);
+			if (names.indexOfByName(da.getName())>=0)
+				shown[i] = true;
+			}
+		}
+		for (int i = 0; i<names.size(); i++){
+			String name = ((MesquiteString)names.elementAt(i)).getName();
+			if (v.indexOfByName(name)<0){
+				v.addElement(new MesquiteString(name, " (not in current tree)"), false);
+				if (v.size()-1>= shown.length)
+					shown[v.size()-1] = true;
+			}
+		}
+		if (v.size()==0)
+			module.alert("This Tree has no values associated with nodes");
+		else {
+			ExtensibleDialog queryDialog = new ExtensibleDialog(module.containerOfModule(), message,  buttonPressed);
+			queryDialog.addLabel(message, Label.CENTER);
+			Checkbox[] checks = new Checkbox[v.size()];
+			for (int i=0; i<v.size(); i++){
+				MesquiteString ms = (MesquiteString)v.elementAt(i);
+				checks[i] = queryDialog.addCheckBox (ms.getName() + ms.getValue(), shown[i]);
+			}
+
+			queryDialog.completeAndShowDialog(true);
+
+			boolean ok = (queryDialog.query()==0);
+
+			if (ok) {
+				names.removeAllElements(false);
+				for (int i=0; i<checks.length; i++){
+					MesquiteString ms = (MesquiteString)v.elementAt(i);
+					if (checks[i].getState())
+						names.addElement(new MesquiteString(ms.getName(), ms.getName()), false);
+				}
+			}
+
+			queryDialog.dispose();
+			return ok;
+
+		}
+		return false;
+	}
+
+
+	/** Returns true iff the two trees from different taxa blocks have the same topologies; this is used for associated trees in which one is a containing and one a contained tree. *
+	public static boolean containedMatchesContaining (Tree containedTree, Tree containingTree, TaxaAssociation association) {
+		if (containedTree==null || containingTree==null || association == null)
+			return false;
+		if (!containedAllMonophyletic(containedTree, containingTree, association))  // check for monophyly of each contained group
+				return false;
+		Taxa containedTaxa = containedTree.getTaxa();
+		Taxa containingTaxa = containingTree.getTaxa();
+
+// now we know all of the associates are monophyletic within a containing branch.  Let's see if the deeper branches match.
+		
+		
+		
+		return true;
+	}
+	/*......................................*/
+	
+}
diff --git a/Source/mesquite/lib/TreeVector.java b/Source/mesquite/lib/TreeVector.java
new file mode 100644
index 0000000..bea6b12
--- /dev/null
+++ b/Source/mesquite/lib/TreeVector.java
@@ -0,0 +1,628 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+/* ======================================================================== */
+/**A tree block.  Trees are added to it when trees are read from file or stored.  Many methods could be built here, for 
+instance to go through all trees and prune taxa deleted.
+Translation table is stored with each TreeVector.*/
+public class TreeVector extends ListableVector implements Trees, Commandable, Identifiable, CompatibilityChecker, MesquiteListener {
+	Taxa taxa = null;
+	TranslationTable translationTable;
+	public static long totalCreated = 0;
+	public static long totalDisposed = 0;
+	long id;
+	private boolean writeTreeWeights = false;
+	public TreeVector  (Taxa taxa) {
+		super();
+		setTaxa(taxa);
+		totalCreated++;
+		id = totalCreated;
+	}
+	public int getNumberOfTrees(){
+		return size();
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "treesSmall.gif";
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		if (StringUtil.blank(s))
+			return null;
+		String list = "";
+		String fc =""; //to receive the direct command
+		int numFound = 0;
+		for (int it = 0; it< size(); it++){
+			Tree tree = getTree(it);
+			String name = tree.getName();
+			if (name != null && StringUtil.foundIgnoreCase(name, s)){
+				list += "<li>Tree " + (it+1) + ": <strong>" + StringUtil.protectForXML(name) + "</strong>. <a href=\"selectTree:" + it + " " + getID() + "\">Touch tree</a></li>";
+				numFound++;
+				fc = "selectTree:" + it+ " " + getID() ;
+			}
+		}
+		if (commandResult != null && numFound == 1)
+			commandResult.setValue(fc);
+		if (StringUtil.blank(list))
+			return list;
+		return "<h2>Tree block \"" + StringUtil.protectForXML(getName()) + "\"</h2><ul>" + list + "</ul>";
+	}
+
+	/*.................................................................................................................*/
+	public void attachCloneToFile(MesquiteFile f, ElementManager manager){
+		TreeVector trees = new TreeVector(getTaxa());
+		trees.setName(getName());
+		trees.addToFile(f, getProject(), manager); 
+		trees.setWriteWeights(getWriteWeights());
+		for (int i=0; i<size(); i++){
+			trees.addElement(elementAt(i), false);
+			
+		}
+	}
+	public boolean swapParts(int first, int second) {
+		
+		return swapParts(first, second, false);  //NOTE DEFAULT IS FALSE. The reason is to avoid time cost on multiple swaps
+	}
+	public boolean swapParts(int first, int second, boolean resetNumbers) {
+		
+		boolean success = super.swapParts(first, second);
+		if (resetNumbers)
+			resetAssignedNumbers();
+		return success;
+	}
+	/*...........................................................*/
+	public boolean moveParts(int starting, int num, int justAfter) {
+		return moveParts(starting, num, justAfter, false);  //NOTE DEFAULT IS FALSE The reason is to avoid time cost on multiple moves
+	}
+	/*...........................................................*/
+	public boolean moveParts(int starting, int num, int justAfter, boolean resetNumbers) {
+		boolean success =  super.moveParts(starting, num, justAfter);
+		if (resetNumbers)
+			resetAssignedNumbers();
+		return success;
+	}
+	/*.................................................................................................................*/
+	public void addElement(Listable obj, boolean notify) {
+		super.addElement(obj, false);
+		if (obj instanceof MesquiteTree)
+			((MesquiteTree)obj).setTreeVector(this);
+		if (obj instanceof Listened){
+			((Listened)obj).addListener(this);
+		}
+		resetAssignedNumbers();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {size()-2,1}));
+	}
+	public void insertElementAt(Listable obj, int index, boolean notify) {
+		super.insertElementAt(obj, index, false);
+		if (obj instanceof MesquiteTree)
+			((MesquiteTree)obj).setTreeVector(this);
+		if (obj instanceof Listened){
+			((Listened)obj).addListener(this);
+		}
+		resetAssignedNumbers();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {index,1}));
+	}
+	public void removeElement(Listable obj, boolean notify) {
+		if (obj == null)
+			return;
+		super.removeElement(obj, false);
+		if (obj instanceof MesquiteTree)
+			((MesquiteTree)obj).setTreeVector(null);
+		if (obj instanceof Listened){
+			((Listened)obj).removeListener(this);
+		}
+		resetAssignedNumbers();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+	}
+	public void removeElementAt(int index, boolean notify) {
+		Object obj = elementAt(index);
+		if (obj == null)
+			return;
+		super.removeElementAt(index, false);
+		if (obj instanceof MesquiteTree)
+			((MesquiteTree)obj).setTreeVector(null);
+		if (obj instanceof Listened){
+			((Listened)obj).removeListener(this);
+		}
+		resetAssignedNumbers();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+	}
+	public void removeAllElements(boolean notify){
+		for (int i=0; i<size(); i++){
+			Object obj = elementAt(i);
+			if (obj instanceof Listened){
+				((Listened)obj).removeListener(this);
+			}
+
+		}
+		super.removeAllElements(notify);
+	}
+	public void replaceElement(Listable old, Listable replacement, boolean notify) {
+		if (old instanceof Listened){
+			((Listened)old).removeListener(this);
+		}
+		if (old instanceof MesquiteTree)
+			((MesquiteTree)old).setTreeVector(null);
+		super.replaceElement(old, replacement, false);
+		if (replacement instanceof MesquiteTree)
+			((MesquiteTree)replacement).setTreeVector(null);
+		if (replacement instanceof Listened){
+			((Listened)replacement).removeListener(this);
+		}
+		resetAssignedNumbers();
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+	}
+
+	public void resetAssignedNumbers(){
+		for (int i=0; i<size(); i++)
+			if (elementAt(i) instanceof MesquiteTree)
+				((MesquiteTree)elementAt(i)).setAssignedNumber(i);
+	}
+
+	/*.................................................................................................................*/
+	public int indexOfByTopology(Tree tree, boolean checkBranchLengths){
+		if (tree == null)
+			return -1;
+		for (int i=0; i< size(); i++){
+			if (tree.equalsTopology((Tree)elementAt(i), checkBranchLengths)){
+				return i;
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** gets the explanation (footnote) of this tree vector*/
+	public String getExplanation() {
+
+		String extra = null;
+		if (taxa == null){
+			extra = "This block of trees has " + size() + " trees for an unspecified taxa block.\n";
+		}
+		else 
+			extra = "This block of trees has " + size() + " trees for the taxa \"" + taxa.getName() + " \".\n";
+		return extra;
+	}
+	/** returns true if object is set of taxa on which tree vector is based */
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj instanceof Taxa){
+			if (obj != taxa && report != null)
+				report.setValue("tree block applies to a different block of taxa.");
+			return (obj == taxa);
+		}
+		return true;
+	}
+	/** Returns whether module is compatible with given object*/
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer) {
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+	/**Returns the unique id number of this tree block*/
+	public long getID(){
+		return id;
+	}
+	/**Translates internal numbering system to external (currently, 0 based to 1 based*/
+	public static int toExternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i+1;
+	}
+	/**Translates external numbering system to internal (currently, 1 based to 0 based*/
+	public static int toInternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i-1;
+	}
+	public void dispose() {
+		for (int i=0; i<size(); i++)
+			((MesquiteTree)elementAt(i)).dispose();
+		removeAllElements(false);
+		if (taxa != null)
+			taxa.removeListener(this);
+		totalDisposed++;
+		super.dispose();
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Returns identification number of this tree block", null, commandName, "getID")) {
+			return new MesquiteInteger((int)id);
+		}
+		else if (checker.compare(this.getClass(), "Exports the file element", null, commandName, "exportMe")) {
+			ElementManager manager = getManager();
+			if (manager!=null) {
+				((Commandable)manager).doCommand("exportTreesBlock", Integer.toString(getFile().getProject().getFileElementNumber(this, getClass())), CommandChecker.defaultChecker);
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Duplicates the tree block", null, commandName, "duplicateMe")) {
+			if (getProject() != null)
+				getProject().incrementProjectWindowSuppression();
+
+			TreeVector trees = new TreeVector(getTaxa());
+			trees.setName(getName() + " (duplicate)");
+			trees.setWriteWeights(getWriteWeights());
+			for (int i=0; i<size(); i++){
+				Tree t = (Tree)elementAt(i);
+				trees.addElement(t.cloneTree(), false);
+				
+			}
+			trees.addToFile(getFile(), getProject(), getManager()); 
+			getManager().elementAdded(trees);
+			if (getProject() != null)
+				getProject().decrementProjectWindowSuppression();
+			return trees;
+		}
+		else if (checker.compare(this.getClass(), "Prepends to all tree names the given string", "[string to prepend]", commandName, "prefixNames")) {
+			String prefix = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+			if (StringUtil.blank(prefix))
+				return null;
+			for (int i=0; i<size(); i++) {
+				AdjustableTree t = (AdjustableTree)getTree(i);
+				if (t!=null) {
+					String n = t.getName();
+					if (n == null)
+						t.setName(prefix);
+					else
+						t.setName(prefix + n);
+				}
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Shows tree in tree window", null, commandName, "showTreesInWindow")) {
+			ElementManager manager = getManager();
+			if (manager!=null && manager instanceof MesquiteModule) {
+				MesquiteFile file = getFile();
+				if (file!=null && file.getProject()!=null) {
+					CommandRecord oldR = MesquiteThread.getCurrentCommandRecord();
+					CommandRecord scr = new CommandRecord(true);
+					MesquiteThread.setCurrentCommandRecord(scr);
+					((MesquiteModule)manager).doCommand("showTreesInWindow" ,Integer.toString(getFile().getProject().getFileElementNumber(this, getClass())), CommandChecker.defaultChecker);
+					MesquiteThread.setCurrentCommandRecord(oldR);
+				}
+			}
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/** Set the taxa to which the tree block applies */
+	public void setTaxa(Taxa taxa) {
+		if (this.taxa!=taxa && taxa !=null){
+			if (this.taxa!=null)
+				this.taxa.removeListener(this);
+			this.taxa = taxa; //need to redo translation table
+			taxa.addListenerHighPriority(this);
+			translationTable = new TranslationTable(taxa);
+		}
+	}
+	/** Get the taxa to which the tree block applies */
+	public Taxa getTaxa(){
+		return taxa;
+	}
+
+	public Tree getTree(int i) {
+		if (i>=0 && i<size())
+			return (MesquiteTree)elementAt(i);
+		else
+			return null;
+	}
+	/** Set the label of the taxon with given name to be the label passed*/
+	public void setTranslationLabel(String label, String taxonName, boolean checkDuplicates){
+		if (translationTable==null || taxonName == null)
+			return;
+		if (taxa==null)
+			return;
+		Taxon t = taxa.getTaxon(taxonName, false, true);
+		if (t == null) {
+			if (MesquiteTree.permitT0Names && taxonName.startsWith("t")){  //not found in taxon names, but as permits t0, t1 style names, look for it there
+					String number = taxonName.substring(1, taxonName.length());
+					int num = MesquiteInteger.fromString(number);
+					if (MesquiteInteger.isCombinable(num) && num>=0 && num<taxa.getNumTaxa())
+						t = taxa.getTaxon(num);
+			}
+		}
+		if (t==null)
+			MesquiteMessage.warnProgrammer("Taxon name in translation table doesn't correspond to name of known taxon (\"" + taxonName + "\" [a])");
+
+		translationTable.setLabel(t, label, checkDuplicates);
+		setDirty(true);
+	}
+	/** DOCUMENT */
+	public void checkTranslationTable(){
+		if (translationTable==null)
+			return;
+		translationTable.checkDuplicates();
+	}
+
+	/** Get the label of the taxon i.  If no label stored, return external taxon number as string*/
+	public String getTranslationLabel(String iName) {
+		if (StringUtil.blank(iName))
+			return null;
+		Taxon t = taxa.getTaxon(iName, false, true);
+		if (translationTable!=null) {
+			String label = translationTable.getLabel(t);
+			if (!StringUtil.blank(label))
+				return label;
+		}
+		if (t != null)
+			return Integer.toString(Taxon.toExternal(taxa.whichTaxonNumber(t))); 
+		return null;
+	}
+	/** Get the label of the taxon i.  If no label stored, return external taxon number as string*/
+	public String getTranslationLabel(int taxonNumber) {
+		if (taxa == null || translationTable==null || translationTable.getLabel(taxonNumber)==null)
+			return Integer.toString(Taxon.toExternal(taxonNumber)); 
+		return translationTable.getLabel(taxonNumber);
+	}
+
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	/** Get the translation table as a string. */
+	public String getTranslationTable() {
+		if (translationTable==null || taxa == null)
+			return null;
+		String temp = "";
+		for(int i=0; i<taxa.getNumTaxa(); i++) {
+			if (i>0)
+				temp += ","+ StringUtil.lineEnding();
+			temp += "[" + i + "] ";
+			String thisLabel = getTranslationLabel(i);
+			temp += "\t\t" + thisLabel + " " + StringUtil.tokenize(taxa.getTaxonName(i)) ;
+		}
+		return temp;
+	}
+	/** Sets the translation table to match the passed table. */
+	public void setTranslationTable(Vector table) {
+		if (table==null)
+			return;
+		for(int i=0; i<table.size(); i++) {
+			String taxonName = (ParseUtil.getFirstToken((String)table.elementAt(i),pos));
+			String label = (ParseUtil.getToken((String)table.elementAt(i),pos));
+			Taxon t = taxa.getTaxon(taxonName, false, true);
+			translationTable.setLabel(t, label, false); //note label set even if taxon not found; signal later to return null for whichtaxon number
+			if (t==null) {
+				if (MesquiteTree.permitT0Names && taxonName.startsWith("t")){  //not found in taxon names, but as permits t0, t1 style names, look for it there
+						String number = taxonName.substring(1, taxonName.length());
+						int num = MesquiteInteger.fromString(number);
+						if (MesquiteInteger.isCombinable(num) && num>=0 && num<taxa.getNumTaxa())
+							t = taxa.getTaxon(num);
+				}
+			}
+			if (t == null)
+				MesquiteMessage.warnProgrammer(	"Taxon name in translation table doesn't correspond to name of known taxon (\"" + taxonName + "\" [b])");
+
+		}
+		checkTranslationTable();
+	}
+	/** returns true if every taxon in stored translation table is found within the passed taxa. */
+	public boolean tableMatchesTaxa(Taxa taxa, Vector table) {
+		if (table==null)
+			return false;
+		for(int i=0; i<table.size(); i++) {
+			String taxonName = (ParseUtil.getFirstToken((String)table.elementAt(i),pos));
+			if (taxa.whichTaxonNumber(taxonName, false, true) <0)
+				return false;
+		}
+		return true;
+	}
+	/** Returns which taxon number corresponds to the passed taxon label.  Uses the translation table. */
+	public int whichTaxonNumber(String label, boolean forgivingOfTruncation) {
+		if (taxa==null)
+			return -1;
+		if (translationTable==null)
+			return taxa.whichTaxonNumber(label, false, forgivingOfTruncation);
+
+		int i = taxa.whichTaxonNumber(translationTable.getTaxon(label));
+		if (i<0)
+			return taxa.whichTaxonNumber(label, false, forgivingOfTruncation); 
+		else
+			return i;
+	}
+
+	/** Get the name of the tree block. */
+	public String getName(){
+		if (name==null)
+			return "Tree Block";
+		return name;
+	}
+	/** returns true if this has name equivalent to default name*/
+	public boolean hasDefaultName() {
+		return  (name==null) || name.equals("Tree Block");
+	}
+	/** Set the name of the tree block. */
+	public void setName(String name){
+		this.name = name;
+		if (getHShow()) {
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		}
+	}
+
+	/** Get the name & details of the tree block. */
+	public String toString(){
+		return "TreeVector: " + getName() + " [id " + id + " size " + size() + "]";
+	}
+	/**Set whether to write the tree weight into file in the format TREE <tree name> = [&W weight] tree, where weight is the tree weight.*/
+	public void setWriteWeights(boolean useWts){
+		writeTreeWeights = useWts;
+	}
+	/**Get whether to write the tree weight into file in the format TREE <tree name> = [&W weight] tree, where weight is the tree weight.
+	 * Called by the ManageTrees.getTreeBlock method when writing trees to a tree block.*/
+	public boolean getWriteWeights(){
+		return writeTreeWeights;
+	}
+	public String toHTMLStringDescription(){
+		//String s =  "<li>Trees: <strong>" + getName() + ".  </strong> Number of trees: " + size() + ".   (<a href =\"listTrees:" + getID() + "\">List & Manage</a>)  (<a href =\"viewTrees:" + getID() + "\">View, Explore & Edit</a>) (<a href =\"chartTrees:" + getID() + "\">Chart</a>)  (<a href =\"renameTrees:" + getID() + "\">Rename</a>)  (<a href =\"editCommentTrees:" + getID() + "\">Edit Comment</a>)  (<a href =\"deleteTrees:" + getID() + "\">Delete</a>)";
+		String s =  "<li>Trees: <strong>" + getName() + ".  </strong> Number of trees: " + size() + ". ";
+		String comment = getAnnotation();
+		if (!StringUtil.blank(comment))
+			s+= "<br><font color=\"#777777\">" + comment + "</font>";
+		if (HTMLDescribable.verbose)
+			s += "<ul>" + super.toHTMLStringDescription() + "</ul>";
+		s += "</li>";
+		return s;
+	}
+	/** Get the list of tree id's. */
+	public String listIDs(){
+		String s = "Trees: ";
+		for (int i=0; i<size(); i++)
+			s += " " + getTree(i).getID();
+		return s;
+	}
+	/*-----------------------------------------*/
+	boolean suppressNotifyL = false;
+	Thread threadOfTreeChange;
+	
+	private long[] lastNotifications = new long[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; //a partial protection against responding to the same notification twice, e.g. coming via two different pathways.
+	private boolean notificationFound(Notification notification){
+		if (notification ==null)
+			return false;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return false;
+		if (LongArray.indexOf(lastNotifications, id)>=0)
+			return true;
+		return false;
+	}
+	private void rememberNotification(Notification notification){
+		if (notification ==null)
+			return;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return;
+		for (int i = 0; i< lastNotifications.length-1; i++)
+			lastNotifications[i+1] = lastNotifications[i];
+		lastNotifications[0] = id;
+	}
+	/** For MesquiteListener interface.  Passes which object changed, along with optional integer (e.g. for character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (notificationFound(notification))
+			return;
+		rememberNotification(notification);
+		if (obj == taxa){
+			if (Notification.appearsCosmeticOrSelection(notification))
+				return;
+			int[] parameters = Notification.getParameters(notification);
+
+			if (parameters!=null && parameters.length>=2 && translationTable!=null)
+				translationTable.taxaModified(Notification.getCode(notification), parameters[0], parameters[1]);
+			else translationTable.cleanUpTable();
+			for (int i=0; i<size(); i++) {//modified 19 Nov 01
+				Object o = elementAt(i);
+				if (o !=null && o instanceof MesquiteTree) {
+					MesquiteTree tree = (MesquiteTree)o;
+					threadOfTreeChange = Thread.currentThread();
+					suppressNotifyL = true; //this and previous needed to avoid this call to "changed" from notifying listeners here
+					tree.changed(caller, obj, notification);
+					suppressNotifyL = false;
+					threadOfTreeChange =  null;
+				}
+			}
+			if (Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED){
+				boolean deleted = deleteEmptyTrees();
+				if (deleted)
+					notifyListeners(this, (new Notification(MesquiteListener.PARTS_DELETED).setNotificationNumber(notification.getNotificationNumber()))); 
+			}
+		}
+		else {
+			if (!(suppressNotifyL && threadOfTreeChange == Thread.currentThread()) 
+				&& obj instanceof Tree && caller != this 
+				&& Notification.getCode(notification) != MesquiteListener.ANNOTATION_CHANGED 
+				&& Notification.getCode(notification) != MesquiteListener.ANNOTATION_ADDED 
+				&& Notification.getCode(notification) != MesquiteListener.ANNOTATION_DELETED)
+			notifyListeners(this, (new Notification(MesquiteListener.PARTS_CHANGED).setNotificationNumber(notification.getNotificationNumber()))); 
+		}
+	}
+	boolean deleteEmptyTrees(){
+		int count = 0;
+		while (deleteEmptyTree()){
+			count++;
+		}
+		if (count>0){
+			MesquiteTrunk.mesquiteTrunk.logln(Integer.toString(count) + " tree(s) deleted because each contained no taxa.");
+	}
+	return count>0;
+	}
+	boolean deleteEmptyTree(){
+		for (int i=0; i<size(); i++) {
+			Object o = elementAt(i);
+			if (o !=null && o instanceof MesquiteTree) {
+				MesquiteTree tree = (MesquiteTree)o;
+				if (tree.isEmpty()) {
+					removeElement(tree, false);
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	/*-----------------------------------------*/
+	/** For MesquiteListener interface.  Passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa) //modified 19 Nov 01
+			for (int i=0; i<size(); i++) {
+				Object o = elementAt(i);
+				if (o !=null && o instanceof MesquiteTree) {
+					MesquiteTree tree = (MesquiteTree)o;
+					tree.disposing(obj);
+				}
+			}
+	}
+	/*-----------------------------------------*/
+	/** For MesquiteListener interface.  Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+
+	/*-----------------------------------------*/
+	/** For HNode interface.  todo: this should be renamed getHNodeShow*/
+	public boolean getHShow(){
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** For HNode interface.*/
+	public String getTypeName(){
+		return "Tree block";
+	}
+
+	/* ---------------- for use with touched from HNode interface ----------------------*/
+	public void addToBrowserPopup(MesquitePopup popup){
+		super.addToBrowserPopup(popup);
+		ElementManager manager = getManager();
+		if (manager!=null && manager instanceof MesquiteModule) {
+			MesquiteFile file = getFile();
+			if (file!=null && file.getProject()!=null) {
+				popup.add(new MenuItem("-"));
+				popup.add(new MesquiteMenuItem("Show list of trees \"" + getName() + "\"", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("showMe", this)));
+				if (getFile()!=null)
+					popup.add(new MesquiteMenuItem("Show trees \"" + getName() + "\" in tree window", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("showTreesInWindow" , (MesquiteModule)manager),Integer.toString(getFile().getProject().getFileElementNumber(this, TreeVector.class))));
+			}
+		}
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/lib/Trees.java b/Source/mesquite/lib/Trees.java
new file mode 100644
index 0000000..f076c98
--- /dev/null
+++ b/Source/mesquite/lib/Trees.java
@@ -0,0 +1,32 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.util.*;
+
+/* ======================================================================== */
+/**An interface for a set of trees or a tree source.*/
+public interface Trees {
+	/** Get the taxa to which the trees applies */
+	public Taxa getTaxa();
+	
+	public Tree getTree(int i);
+	
+	public int size();
+}
+
+
+
+
diff --git a/Source/mesquite/lib/TwoIntegersDialog.java b/Source/mesquite/lib/TwoIntegersDialog.java
new file mode 100644
index 0000000..f4c6ba9
--- /dev/null
+++ b/Source/mesquite/lib/TwoIntegersDialog.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/*===============================================*/
+/** A dialog box to return two integers*/
+public class TwoIntegersDialog extends ExtensibleDialog {
+	static int numIntegers=2;
+	IntegerField[] numResult = new IntegerField[numIntegers];
+	MesquiteInteger[] num = new MesquiteInteger[numIntegers];
+	int[] min = new int[numIntegers];
+	int[] max = new int[numIntegers];
+	String[] label = new String[numIntegers];
+	MesquiteBoolean answer;
+	String report = "";
+	boolean valuesChecked = false;
+	
+	//also take as input minimum and maximum allowed?
+	public TwoIntegersDialog (MesquiteWindow parent,  String title, String label1, String label2, MesquiteBoolean answer,  MesquiteInteger num1, MesquiteInteger num2,int min1,int max1,int min2, int max2, String helpString) {
+		super(parent,title);
+		for (int i=0; i<numIntegers;i++) {
+			min[i]=MesquiteInteger.unassigned;
+			max[i]=MesquiteInteger.unassigned;
+		}
+		this.min[0] = min1;
+		this.min[1] = min2;
+		this.max[0] = max1;
+		this.max[1] = max2;
+		this.num[0] = num1;
+		this.num[1] = num2;
+		this.label[0]=label1;
+		this.label[1]=label2;
+		
+		this.answer = answer;
+		answer.setValue(false);
+		
+		for (int i=0; i<numIntegers;i++) {
+			numResult[i] = addIntegerField(this.label[i] + ": ",this.num[i].getValue(),12);
+		}
+
+		if (!StringUtil.blank(helpString))
+			appendToHelpString(helpString);
+			
+		setAutoDispose(false);
+
+		completeAndShowDialog(true,this);
+		
+		if (!valuesChecked && answer.getValue())
+			processOK();
+	}
+	public TwoIntegersDialog (MesquiteWindow parent,  String title, String label1, String label2, MesquiteBoolean answer,  MesquiteInteger num1, MesquiteInteger num2,String helpString) {
+		this( parent,  title,  label1,  label2,  answer,   num1,  num2, MesquiteInteger.unassigned,MesquiteInteger.unassigned,MesquiteInteger.unassigned,MesquiteInteger.unassigned,helpString);
+	}
+	/*.................................................................................................................*/
+	 public  boolean checkNumber(int field) {
+	 	int number = getNumber(field);
+	 	if (!numResult[field].isValidInteger()) {
+	 		report = "Entry for "+label[field]+ " is not a valid number";
+	 		return false;
+	 	}
+	 	if (!MesquiteInteger.isCombinable(number))
+	 		return false;
+	 	if (MesquiteInteger.isCombinable(min[field]))
+	 		if (number<min[field]) {
+	 			report = "Entry for "+label[field]+ " is below the minimum allowed";
+	 			return false;
+	 		}
+	 	if (MesquiteInteger.isCombinable(max[field]))
+	 		if (number>max[field]){
+	 			report = "Entry for "+label[field]+ " is above the maximum allowed";
+	 			return false;
+	 		}
+	 	return true;
+	 }
+	/*.................................................................................................................*/
+	 public  void processOK() {
+		if (checkNumber(0) && checkNumber(1)) {
+			valuesChecked = true;
+	 		answer.setValue(true);
+	 		for (int i=0;i<numIntegers;i++)
+	 			num[i].setValue(getNumber(i));
+	 		dispose();
+	 	}
+	 	else
+	 		MesquiteMessage.notifyUser(report);
+	 }
+	/*.................................................................................................................*/
+	 public  int getNumber(int field) {
+	 	return numResult[field].getValue();
+	 }
+	/*.................................................................................................................*/
+	public void keyReleased(KeyEvent e){
+		if (e.getKeyCode() == 10) {
+			processOK();
+		}
+	}
+	/*.................................................................................................................*/
+	 public  void actionPerformed(ActionEvent e) {
+	 	if   (defaultOKLabel.equals(e.getActionCommand())) {
+			processOK();
+		}
+		else if  (defaultCancelLabel.equals(e.getActionCommand())) {
+			answer.setValue(false);
+			dispose();
+		}
+		else
+			super.actionPerformed(e);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/TwoStringsDialog.java b/Source/mesquite/lib/TwoStringsDialog.java
new file mode 100644
index 0000000..a5f0317
--- /dev/null
+++ b/Source/mesquite/lib/TwoStringsDialog.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+
+/*===============================================*/
+/** A dialog box to return two strings*/
+public class TwoStringsDialog extends ExtensibleDialog {
+	SingleLineTextField str1Result;
+	SingleLineTextField str2Result;
+	TextArea str2ResultLong;
+	MesquiteString str1;
+	MesquiteString str2;
+	MesquiteBoolean answer;
+
+	public TwoStringsDialog (MesquiteWindow parent,  String title, String label1, String label2, MesquiteBoolean answer,  MesquiteString str1, MesquiteString str2, boolean secondLong) {
+		this(parent, title, label1, label2, answer, str1, str2, false, secondLong);
+	}
+	
+	public TwoStringsDialog (MesquiteWindow parent,  String title, String label1, String label2, MesquiteBoolean answer,  MesquiteString str1, MesquiteString str2, boolean obscureSecond, boolean secondLong) {
+		super(parent,title);
+		this.str2 = str2;
+		this.str1 = str1;
+		this.answer = answer;
+		answer.setValue(false);
+		
+		addLabel(label1 + ": ", Label.LEFT);
+		str1Result = addTextField(this.str1.getValue());
+		addLabel(label2 + ": ", Label.LEFT);
+		if (secondLong) {
+			str2ResultLong = addTextArea(this.str2.getValue(),3);
+			if (obscureSecond)
+				str2ResultLong.setFont(defaultSmallFont);
+		}
+		else {
+			str2Result = addTextField(this.str2.getValue());
+			if (obscureSecond)
+				str2Result.setFont(defaultSmallFont);
+		}
+
+		str1Result.requestFocus();
+
+		completeAndShowDialog(true,null);
+		boolean ok = (query()==0);
+		if (ok) {
+			str1.setValue(str1Result.getText());
+			if (secondLong)
+				str2.setValue(str2ResultLong.getText());
+			else
+				str2.setValue(str2Result.getText());
+			answer.setValue(true);
+		}
+		dispose();
+
+	}
+	
+}
+
+
+
diff --git a/Source/mesquite/lib/UndoInstructions.java b/Source/mesquite/lib/UndoInstructions.java
new file mode 100644
index 0000000..e5cd6b4
--- /dev/null
+++ b/Source/mesquite/lib/UndoInstructions.java
@@ -0,0 +1,514 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+//import mesquite.charMatrices.lib.*;
+import mesquite.lib.table.*;
+
+/*
+ Undo PARTS_MOVED:
+ 	SortChars and SortTaxa done
+ 	BasicDataWIndow done
+
+ 	- test to see if linked matrices works with parts moved
+
+
+
+ * */
+
+public class UndoInstructions implements Undoer {
+	// Undo mode: what branch of the undo system is being used; what will be remembered
+	public static final int CANTUNDO = -1;
+	public static final int SINGLEDATACELL = 1;
+	public static final int SINGLETAXONNAME = 2;
+	public static final int SINGLECHARACTERNAME = 3;
+	public static final int EDITTEXTFIELD = 4;
+	public static final int ALLDATACELLS = 5;
+	public static final int ALLTAXONNAMES = 6;
+	public static final int ALLCHARACTERNAMES = 7;
+	public static final int PARTS_MOVED = 8;
+	public static final int PARTS_ADDED = 9;
+	public static final int DATABLOCK = 10;
+
+	//	Modes below here are not yet supported
+	public static final int TAXA_DELETED = 30;
+	public static final int CHARACTERS_DELETED = 31;
+
+
+	// Clues for the ALLDATACELLS mode as to what might or might not change
+	public static final int NO_CHAR_TAXA_CHANGES = 100;  //currently allowed
+	public static final int CHAR_ADDED_TO_END = 101;  //currently allowed
+	public static final int CHAR_ADDED_TO_START = 109;  //currently allowed
+	public static final int CHAR_ADDED = 102;  //currently allowed
+	public static final int CHAR_REORDERED = 103;
+	public static final int CHAR_DELETED = 104;
+	public static final int TAX_ADDED_TO_END = 105;  //currently allowed
+	public static final int TAX_ADDED = 106; //currently allowed
+	public static final int TAX_REORDERED = 107;
+	public static final int TAX_DELETED = 108;
+	public static final int TAX_ADDED_TO_START = 110;//currently allowed
+	public static final int CHAR_SPECSETS_CHANGED = 111;
+	public static final int TAX_SPECSETS_CHANGED = 112;
+	public static final int[] allowedChanges = new int[]{NO_CHAR_TAXA_CHANGES, CHAR_ADDED_TO_END, CHAR_ADDED_TO_START, CHAR_ADDED, TAX_ADDED_TO_END, TAX_ADDED, TAX_ADDED_TO_START};
+
+
+
+	int changeClass;
+
+	int itStart;
+	int itEnd;
+	int icStart;
+	int icEnd;
+	int row;
+
+	MesquiteModule ownerModule = null;
+	private Object oldState=null;
+	private Object newState=null;
+	CharacterData data;
+	CharacterData oldData;
+	CharacterData newData;
+	MesquiteTable table;
+	EditorTextField textField;
+	Taxa taxa;
+	Associable assoc;
+	String[] namesList;
+	int[] order = null;
+
+	String[][] oldStateNames;
+	String[][] oldStateNotes;
+
+	MesquiteCommand undoCommand;
+
+
+	/** This is the constructor for single-cell changes. */
+	public UndoInstructions(int changeClass, int ic, int it, Object oldState, Object newState, CharacterData data, MesquiteTable table) {
+
+		this.table = table;
+		this.changeClass = changeClass;
+		this.itStart = it;
+		this.itEnd = it;
+		this.icStart = ic;
+		this.icEnd = ic;
+		this.oldState = oldState;
+		this.newState = newState;
+		this.data = data;
+	}
+
+	/** This is the constructor for single-cell changes to taxon names or character names. */
+	public UndoInstructions(int changeClass, int row, Object oldState, Object newState, Object obj, MesquiteTable table) {
+		this.table = table;
+		this.changeClass = changeClass;
+		this.row = row;
+		this.itStart = row;
+		this.itEnd = row;
+		this.icStart = row;
+		this.icEnd = row;
+		this.oldState = oldState;
+		this.newState = newState;
+		if (obj instanceof CharacterData)
+			data = (CharacterData) obj;
+		if (obj instanceof Taxa)
+			taxa = (Taxa) obj;
+	}
+
+
+	/** This is the constructor for changes to a TextField. */
+	public UndoInstructions(int changeClass, Object oldState, Object newState, EditorTextField textField) {
+		this.changeClass = changeClass;
+		this.oldState = oldState;
+		this.newState = newState;
+		this.textField = textField;
+	}
+
+	/** This is the constructor for changes to lists of taxon names. */
+	public UndoInstructions(int changeClass, Object obj, Taxa taxa) {
+		if (obj == null)
+			return;
+		this.changeClass = changeClass;
+		data = null;
+		this.taxa = taxa;
+		namesList = null;
+		if (obj instanceof Taxa) {
+			taxa = (Taxa) obj;
+			namesList = new String[taxa.getNumTaxa()];
+			for (int i = 0; i < namesList.length; i++)
+				namesList[i] = taxa.getTaxonName(i);
+
+		} else if (obj instanceof String[]) {
+			namesList = new String[((String[]) obj).length];
+			for (int i = 0; i < namesList.length; i++)
+				namesList[i] = ((String[]) obj)[i];
+		}
+	}
+
+	/** This is the constructor for whole-matrix changes or changes to lists of character names. */
+	public UndoInstructions(int changeClass, Object obj, CharacterData data) {
+		if (obj == null)
+			return;
+		this.changeClass = changeClass;
+		this.data = data;
+		if (changeClass == ALLCHARACTERNAMES) {
+
+			namesList = null;
+			if (obj instanceof CharacterData) {
+				data = (CharacterData) obj;
+				namesList = new String[data.getNumChars()];
+				for (int i = 0; i < namesList.length; i++)
+					namesList[i] = data.getCharacterName(i);
+
+			} else if (obj instanceof String[]) {
+				namesList = new String[((String[]) obj).length];
+				for (int i = 0; i < namesList.length; i++)
+					namesList[i] = ((String[]) obj)[i];
+			}
+		}
+	}
+
+	/** This is the constructor for whole-matrix changes or changes to lists of character names. */
+	public UndoInstructions(int changeClass, Object obj, CharacterData data, int[] changesThatMightHappen) {
+		if (obj == null)
+			return;
+		this.changeClass = changeClass;
+		this.data = data;
+
+		if (changeClass==ALLDATACELLS) {
+			if (data != null && obj!=null)
+				if (obj instanceof CharacterData) {
+					if (changesThatMightHappen==null)  // no specification as to what might happen; currently, disallow that
+						return;
+					for (int i=0; i<changesThatMightHappen.length; i++) 
+						if (IntegerArray.indexOf(allowedChanges, changesThatMightHappen[i])<0)// one of the possible changes is not allowed; bail
+							return;
+
+					this.oldData = ((CharacterData)obj).cloneData();
+					if (oldData !=  null){
+						this.oldData.setName("Undo Matrix [old]");
+						this.oldData.disconnectListening();
+						if (obj instanceof CategoricalData) {
+							CategoricalData cd = (CategoricalData)obj;
+							for (int ic=0; ic<cd.getNumChars(); ic++){
+								if (cd.hasStateNames() && cd.hasStateNames(ic))
+									for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+										if (cd.hasStateName(ic,i))
+											((CategoricalData)oldData).setStateName(ic,i,cd.getStateName(ic,i));
+								if (cd.hasStateNotes() && cd.hasStateNotes(ic))
+									for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+										if (cd.hasStateNote(ic,i))
+											((CategoricalData)oldData).setStateNote(ic,i,cd.getStateNote(ic,i));
+							}
+						}
+					}
+				}
+		}
+	}
+
+	/** This is the constructor for a change to a block of the matrix. */
+	public UndoInstructions(int changeClass, Object obj, CharacterData data, int icStartStore, int icEndStore, int itStartStore, int itEndStore, int icStart, int icEnd, int itStart, int itEnd, boolean recordRange) {
+		if (obj == null)
+			return;
+		this.changeClass = changeClass;
+		this.data = data;
+
+		if (changeClass==DATABLOCK) {
+			if (data != null && obj!=null)
+				if (obj instanceof CharacterData) {
+					this.oldData = ((CharacterData)obj).cloneDataBlock(icStart,  icEnd,  itStart, itEnd);
+					this.oldData.setName("Undo Matrix [old]");
+					this.oldData.disconnectListening();
+					if (recordRange) {
+						this.itStart = itStartStore;
+						this.itEnd = itEndStore;
+						this.icStart = icStartStore;
+						this.icEnd = icEndStore;
+					}
+				}
+		} 
+	}
+
+	public UndoInstructions(int changeClass, Object obj) {
+		if (obj == null)
+			return;
+		this.changeClass = changeClass;
+		if (obj instanceof Associable) {
+			assoc = (Associable) obj;
+			if (assoc!=null)
+				if (changeClass==PARTS_MOVED) 
+					recordCurrentOrder(assoc);
+				else if (changeClass==PARTS_ADDED){
+					assoc.resetJustAdded();
+				}
+
+		}
+	}
+
+	/** This is the constructor for changes to taxa. */
+	public UndoInstructions(int changeClass) {
+		this.changeClass = changeClass;
+	}
+
+	public void copyCurrentToPreviousOrder(Associable assoc) {
+		assoc.copyCurrentToPreviousOrder()	;
+		if (assoc instanceof CharacterData) {
+			CharacterData data = (CharacterData)assoc;
+			data.copyCurrentToPreviousOrderInLinked();
+		}
+
+	}
+	public void restoreToPreviousOrder(Associable assoc) {
+		assoc.restoreToPreviousOrder()	;
+		if (assoc instanceof CharacterData) {
+			CharacterData data = (CharacterData)assoc;
+			data.restoreToPreviousOrderInLinked();
+		}
+
+	}
+	public void recordCurrentOrder(Associable assoc) {
+		assoc.recordCurrentOrder()	;
+		if (assoc instanceof CharacterData) {
+			CharacterData data = (CharacterData)assoc;
+			data.recordCurrentOrderInLinked();
+		}
+
+	}
+	public void recordPreviousOrder(Associable assoc) {
+		assoc.recordPreviousOrder()	;
+		if (assoc instanceof CharacterData) {
+			CharacterData data = (CharacterData)assoc;
+			data.recordPreviousOrderInLinked();
+		}
+	}
+
+	public void setNewState(Object newState) {
+		if (newState == null)
+			return;
+		if (this.newState.getClass().equals(newState.getClass()))
+			this.newState = newState;
+	}
+
+	public void setUndoCommand(MesquiteCommand command) {
+		undoCommand = command;
+	}
+	public void doCommand(String arguments) {
+		undoCommand.doItMainThread(arguments, "", this);
+	}
+
+	public Object getNewState() {
+		return newState;
+	}
+	public void setNewData(CharacterData data) {
+		if (data == null){
+			this.newData = null;
+			return;
+		}
+		this.newData = data.cloneData();
+		if (newData == null)
+			return;
+		this.newData.setName("Undo Matrix [new]");
+		newData.disconnectListening();
+	}
+	public void setNewDataBlock(CharacterData data,int icStart, int icEnd, int itStart, int itEnd) {
+		this.newData = data.cloneDataBlock( icStart,  icEnd,  itStart,  itEnd);
+		this.newData.setName("Undo Matrix [new]");
+		newData.disconnectListening();
+	}
+
+	public void deleteJustAdded(Associable assoc) {
+		if (assoc!=null)
+			assoc.deleteJustAdded();
+	}
+
+	public void dispose() {
+		if (oldData!=null)
+			oldData.dispose();
+		if (newData!=null)
+			newData.dispose();
+		oldData=null;
+		newData=null;
+	}
+
+	public void finalize() {
+		dispose();
+	}
+
+	public Undoer undo() {
+		String[] oldNamesList;
+		Notification notification;
+		int[] subcodes=null;
+
+		switch (changeClass) {
+
+		case SINGLEDATACELL:
+			if (table != null) {
+				table.offAllEditingSelection();
+				table.setFocusedCell(icStart, itStart, true);
+			}
+			CharacterState csBefore = data.getCharacterState(null, icStart, itStart);
+			if (oldState instanceof MesquiteString){
+
+				CharacterState cs = data.makeCharacterState();
+				String st = ((MesquiteString) oldState).getValue();
+
+				if (StringUtil.blank(st)){
+					return null;
+				}
+				cs.setValue(st, data);
+				data.setState(icStart, itStart, cs); // receive
+			}
+			else if (data instanceof CategoricalData)  
+				data.setState(icStart, itStart, (CategoricalState) oldState); // receive
+			else
+				data.setState(icStart, itStart, (CharacterState) oldState); // receive
+			// errors?
+			CharacterState csAfter = data.getCharacterState(null, icStart, itStart);
+			notification =new Notification(MesquiteListener.DATA_CHANGED, new int[] { icStart, itStart }) ;
+			subcodes = new int[] {MesquiteListener.SINGLE_CELL};
+			if (csBefore != null && csAfter != null && csBefore.isInapplicable()==csAfter.isInapplicable())
+				subcodes = new int[] {MesquiteListener.SINGLE_CELL, MesquiteListener.CELL_SUBSTITUTION};
+			notification.setSubcodes(subcodes);
+
+			data.notifyListeners(this, notification);
+			UndoInstructions undoInst =  new UndoInstructions(changeClass, icStart, itStart, newState, oldState, data, table);
+
+			return undoInst;
+
+		case SINGLETAXONNAME:
+			if (table != null) {
+				table.offAllEditingSelection();
+				table.setFocusedCell(-1, itStart, true);
+			}
+			if (taxa != null) {
+				taxa.setTaxonName(itStart, ((MesquiteString) oldState).getValue());
+				return new UndoInstructions(changeClass, itStart, newState,
+						oldState, taxa, table);
+			} else if (data != null) {
+				data.getTaxa().setTaxonName(itStart, ((MesquiteString) oldState).getValue());
+				return new UndoInstructions(changeClass, -1, itStart, newState, oldState, data, table);
+			}
+			return null;
+
+		case SINGLECHARACTERNAME:
+			// problems if no name in cell, as with undo will be fixed as
+			// "Character 25", for example, and will display as such
+			if (table != null) {
+				table.offAllEditingSelection();
+				table.setFocusedCell(icStart, -1, true);
+			}
+			if (data != null)
+				data.setCharacterName(icStart, ((MesquiteString) oldState).getValue());
+			return new UndoInstructions(changeClass, icStart, -1, newState, oldState, data, table);
+
+		case EDITTEXTFIELD:
+			if (oldState == null || ((MesquiteString) oldState).getValue() == null)
+				return null;
+			if (textField != null)
+				textField.setText(((MesquiteString) oldState).getValue());
+
+			return new UndoInstructions(changeClass, newState, oldState, textField);
+
+		case ALLDATACELLS:
+			newData = data.cloneData();   // note that this clones the current (live) matrix, which means if it has lost columns, they aren't recovered.  
+			newData.setName("Undo Matrix [new]");
+			newData.disconnectListening();
+			if (data.getNumChars()>oldData.getNumChars())  //I added this to help   //we need a setToClone system in CharacterData, which we don't have yet.
+				data.deleteCharacters(oldData.getNumChars(), data.getNumChars()-oldData.getNumChars(), false);
+			else if (data.getNumChars()<oldData.getNumChars())//I added this to help
+				data.addCharacters(data.getNumChars()-1, oldData.getNumChars()-data.getNumChars(), false);
+			data.copyData(oldData, true);  //THIS DOES NOT expand data to be the same size as oldData
+			if (oldData instanceof CategoricalData) {  ////David: This does NOT recover specssets, so codon positions etc. are all out of whack
+				CategoricalData cd = (CategoricalData)oldData;
+				for (int ic=0; ic<cd.getNumChars(); ic++){
+					if (cd.hasStateNames() && cd.hasStateNames(ic))
+						for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+							if (cd.hasStateName(ic,i) && StringUtil.notEmpty(cd.getStateName(ic,i))) {
+								String s = cd.getStateName(ic,i);
+								((CategoricalData)data).setStateName(ic,i,cd.getStateName(ic,i));
+							}
+					if (cd.hasStateNotes() && cd.hasStateNotes(ic))
+						for (int i = 0; i <= CategoricalState.maxCategoricalState; i++)
+							if (cd.hasStateNote(ic,i))
+								((CategoricalData)data).setStateNote(ic,i,cd.getStateNote(ic,i));
+				}
+			}
+
+			data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+			return new UndoInstructions(changeClass, newData, data);
+
+		case DATABLOCK:
+			newData = data.cloneDataBlock(icStart, icEnd, itStart, itEnd); //this will be just the size of the block
+			newData.setName("Undo Matrix [new]");
+			newData.disconnectListening();
+			data.copyDataBlock(oldData, icStart, icEnd, itStart, itEnd);
+			notification = new Notification(MesquiteListener.DATA_CHANGED);
+			if (itStart==itEnd)
+				subcodes = new int[] {MesquiteListener.SINGLE_TAXON};
+			if (subcodes!=null)
+				notification.setSubcodes(subcodes);
+			data.notifyListeners(this, notification);
+			if (undoCommand!=null)
+				if (itStart==itEnd)
+					doCommand(""+itStart);
+				else
+					doCommand("");
+			return new UndoInstructions(changeClass, newData, data, icStart, icEnd, itStart, itEnd, 0, icEnd-icStart, 0, itEnd-itStart, true);
+
+		case ALLTAXONNAMES:
+			if (taxa == null || namesList==null)
+				return null;
+			oldNamesList = null;
+			oldNamesList = new String[taxa.getNumTaxa()];
+			for (int i = 0; i < oldNamesList.length; i++)
+				oldNamesList[i] = taxa.getTaxonName(i);
+			for (int i = 0; i < namesList.length && i < taxa.getNumTaxa(); i++)
+				taxa.setTaxonName(i, namesList[i], false);
+			taxa.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+			return new UndoInstructions(changeClass, oldNamesList, taxa);
+
+		case ALLCHARACTERNAMES:
+			if (data == null || namesList==null)
+				return null;
+			oldNamesList = null;
+			oldNamesList = new String[data.getNumChars()];
+			for (int i = 0; i < oldNamesList.length; i++)
+				oldNamesList[i] = data.getCharacterName(i);
+			for (int i = 0; i < namesList.length && i < data.getNumChars(); i++)
+				data.setCharacterName(i, namesList[i]);
+			return new UndoInstructions(changeClass, oldNamesList, data);
+
+		case PARTS_MOVED:
+			if (assoc == null)
+				return null;
+			UndoInstructions undoInstructions = new UndoInstructions(changeClass, assoc);
+			recordCurrentOrder(assoc);
+			restoreToPreviousOrder(assoc);
+			assoc.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+			copyCurrentToPreviousOrder(assoc);
+			return undoInstructions;		
+
+		case PARTS_ADDED:
+			if (assoc == null)
+				return null;
+			deleteJustAdded(assoc);
+			assoc.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			return null;		
+		}
+
+		return null;
+	}
+
+}
diff --git a/Source/mesquite/lib/UndoReference.java b/Source/mesquite/lib/UndoReference.java
new file mode 100644
index 0000000..4e923ea
--- /dev/null
+++ b/Source/mesquite/lib/UndoReference.java
@@ -0,0 +1,139 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.*;
+
+public class UndoReference {
+
+	Undoer[] undoer;
+	MesquiteModule responsibleModule;
+
+	public UndoReference() {
+	}
+
+	public UndoReference(CharacterData data, MesquiteModule responsibleModule, int[] changesThatMightHappen) {
+		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(changesThatMightHappen);
+		if (undoInstructions!=null) 
+			undoInstructions.setNewData(data);
+		setUndoer(new Undoer[] {undoInstructions});
+		setResponsibleModule(responsibleModule);
+	}
+
+	public UndoReference(CharacterData data, MesquiteModule responsibleModule, int icStart, int icEnd, int itStart, int itEnd) {
+		UndoInstructions undoInstructions = new UndoInstructions (UndoInstructions.DATABLOCK, data, data, icStart,icEnd, itStart, itEnd, icStart, icEnd, itStart, itEnd,true);
+		//undoInstructions.setNewData(data);
+		setUndoer(new Undoer[] {undoInstructions});
+		setResponsibleModule(responsibleModule);
+	}
+	
+	public static final int ALLCHARACTERNAMES = 7;
+
+	/** a constructor for an Undoreference that preserves both data and the taxon names */
+	public UndoReference(CharacterData data, MesquiteModule responsibleModule, int icStart, int icEnd, int itStart, int itEnd, int[] undoableObjects) {
+		if (undoableObjects==null) return;
+		UndoInstructions[] undoInstructions = new UndoInstructions[undoableObjects.length];
+		for (int i=0; i<undoableObjects.length; i++) {
+			switch(undoableObjects[i]) {
+			case UndoInstructions.ALLDATACELLS:
+				undoInstructions[i] = data.getUndoInstructionsAllMatrixCells(null);  // TODO:  pass into this something more refined!
+				if (undoInstructions!=null)
+					undoInstructions[i].setNewData(data);
+				break;
+			case UndoInstructions.DATABLOCK:
+				undoInstructions[i]= new UndoInstructions (UndoInstructions.DATABLOCK, data, data, icStart,icEnd, itStart, itEnd, icStart, icEnd, itStart, itEnd,true);
+				break;
+
+			case UndoInstructions.ALLTAXONNAMES:
+				if (data!=null)
+					undoInstructions[i]= new UndoInstructions(UndoInstructions.ALLTAXONNAMES,data.getTaxa(), data.getTaxa());
+				break;
+			case UndoInstructions.ALLCHARACTERNAMES:
+				undoInstructions[i] = new UndoInstructions(UndoInstructions.ALLCHARACTERNAMES,data, data);
+				break;
+			}
+		}
+		setUndoer(undoInstructions);
+		setResponsibleModule(responsibleModule);
+	}
+
+	public UndoReference(Undoer[] undoer, MesquiteModule responsibleModule) {
+		this.undoer = undoer;
+		this.responsibleModule = responsibleModule;
+	}
+	
+	public UndoReference(Undoer undoer, MesquiteModule responsibleModule) {
+		this.undoer = new Undoer[] {undoer};
+		this.responsibleModule = responsibleModule;
+	}
+
+	public MesquiteModule getResponsibleModule() {
+		return responsibleModule;
+	}
+
+	public void setResponsibleModule(MesquiteModule responsibleModule) {
+		this.responsibleModule = responsibleModule;
+	}
+
+	public Undoer[] getUndoer() {
+		return undoer;
+	}
+
+	public void setUndoer(Undoer[] undoer) {
+		this.undoer = undoer;
+	}
+
+	public void setUndoer(Undoer undoer) {
+		if (this.undoer!=null) {
+			for (int i=0; i<this.undoer.length; i++)
+				if (this.undoer[i]!=null && undoer != this.undoer[i])
+				this.undoer[i].dispose();
+		}
+		this.undoer = new Undoer[] {undoer};
+	}
+	
+	public void dispose() {
+		if (undoer!=null) {
+			for (int i=0; i<undoer.length; i++)
+				if (this.undoer[i]!=null)
+					undoer[i].dispose();
+		}
+	}
+
+
+	public static UndoReference getUndoReferenceForMatrixSelection(CharacterData data, MesquiteTable table, MesquiteModule responsibleModule, int[] changesThatMightHappen){
+		if (data!=null) 
+			if (table!=null) {
+				MesquiteInteger firstRow= new MesquiteInteger();
+				MesquiteInteger lastRow= new MesquiteInteger();
+				MesquiteInteger firstColumn= new MesquiteInteger();
+				MesquiteInteger lastColumn= new MesquiteInteger();
+				if (table.singleCellBlockSelected( firstRow,  lastRow,  firstColumn,  lastColumn)) {
+					if (table.numRowNamesSelected()>0) 
+						return new UndoReference(data,responsibleModule,firstColumn.getValue(), lastColumn.getValue(), firstRow.getValue(),lastRow.getValue(), new int[] {UndoInstructions.DATABLOCK, UndoInstructions.ALLTAXONNAMES});
+					else
+						return new UndoReference(data,responsibleModule,firstColumn.getValue(), lastColumn.getValue(), firstRow.getValue(),lastRow.getValue(), new int[] {UndoInstructions.DATABLOCK});
+				}
+			}
+			else
+				return new UndoReference(data,responsibleModule,changesThatMightHappen);
+		return null;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/Undoer.java b/Source/mesquite/lib/Undoer.java
new file mode 100644
index 0000000..f78fefe
--- /dev/null
+++ b/Source/mesquite/lib/Undoer.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import mesquite.lib.*;
+
+public interface Undoer  {
+
+	public Undoer undo();
+	
+	public void dispose();
+	
+	public void setNewState (Object newState);
+	public Object getNewState ();
+
+	
+}
diff --git a/Source/mesquite/lib/UserNamePasswordDialog.java b/Source/mesquite/lib/UserNamePasswordDialog.java
new file mode 100644
index 0000000..4f55245
--- /dev/null
+++ b/Source/mesquite/lib/UserNamePasswordDialog.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+/*===============================================*/
+/** A dialog box to allow the user to enter a username and password for authentication. */
+public class UserNamePasswordDialog extends ExtensibleDialog {
+	SingleLineTextField userNameField;
+	MesquitePasswordField passwordField;
+	MesquiteString userName;
+	MesquiteString passWord;
+	MesquiteBoolean answer;
+
+
+
+	public UserNamePasswordDialog (MesquiteWindow parent,  String title, String helpString, String helpURL, String label1, String label2, MesquiteBoolean answer,  MesquiteString str1, MesquiteString str2) {
+		super(parent,title);
+		this.passWord = str2;
+		this.userName = str1;
+		this.answer = answer;
+		answer.setValue(false);
+
+		if (StringUtil.notEmpty(helpString))
+			appendToHelpString(helpString);
+
+		if (StringUtil.notEmpty(helpURL))
+			setHelpURL(helpURL);
+
+		addLabel(title, Label.CENTER, true, true);
+		addBlankLine();
+		userNameField = addTextField(label1, userName.getValue(),26);
+		addBlankLine();
+
+		passwordField = addPasswordField(label2,passWord.getValue(), 20);
+
+		passwordField.requestFocus();
+
+		completeAndShowDialog(true,null);
+		boolean ok = (query()==0);
+		if (ok) {
+			str1.setValue(userNameField.getText());
+			str2.setValue(new String(passwordField.getPassword()));
+
+			answer.setValue(true);
+		}
+		dispose();
+
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/ValueToPixel.java b/Source/mesquite/lib/ValueToPixel.java
new file mode 100644
index 0000000..387bdda
--- /dev/null
+++ b/Source/mesquite/lib/ValueToPixel.java
@@ -0,0 +1,115 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.event.*;
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/*=================*/
+public abstract class ValueToPixel extends Object {
+	double minSweetSpotValue, maxSweetSpotValue;
+	double minValue, maxValue;
+	double effectiveMaxValue, effectiveMinValue;
+	int totalSweetPixels;
+	int startSweetPixels;
+	int endSweetPixels;
+	double startSweetPixelFraction, endSweetPixelFraction, sweetPixelFraction;
+	double nonSweetPixelFraction=0.25;
+	int totalPixels;
+	
+	public ValueToPixel (double minValue, double maxValue, double minSweetSpotValue, double maxSweetSpotValue, int totalPixels) {
+		this.minSweetSpotValue = minSweetSpotValue;
+		this.maxSweetSpotValue = maxSweetSpotValue;
+		this.minValue = minValue;
+		this.maxValue = maxValue;
+		this.totalPixels = totalPixels;
+		calcSweetSpot();
+	}
+	public void calcSweetSpot(){
+		sweetPixelFraction = 1.0;
+		startSweetPixels = 0;
+		endSweetPixels = totalPixels;
+		totalSweetPixels = totalPixels;
+		startSweetPixelFraction = 0.0;
+		endSweetPixelFraction = 0.0;
+		int nonSweetPixels = (int)(totalPixels*nonSweetPixelFraction);
+		effectiveMinValue = minValue;
+		effectiveMaxValue = maxValue;
+		if (minValue!=minSweetSpotValue) {
+			sweetPixelFraction-= nonSweetPixelFraction;
+			startSweetPixels = nonSweetPixels;
+			totalSweetPixels-= nonSweetPixels;
+			startSweetPixelFraction = nonSweetPixelFraction;
+		}
+		if (maxValue!=maxSweetSpotValue) {
+			sweetPixelFraction-= nonSweetPixelFraction;
+			endSweetPixels = totalPixels-nonSweetPixels;
+			totalSweetPixels-= nonSweetPixels;
+			endSweetPixelFraction = nonSweetPixelFraction;
+		}
+		effectiveMinValue = minValue;
+		if (minValue==MesquiteDouble.negInfinite) {
+			effectiveMinValue=-10000.0;
+			if (effectiveMinValue > minSweetSpotValue*10)
+				effectiveMinValue=minSweetSpotValue*10;
+		}
+		effectiveMaxValue = maxValue;
+		if (maxValue==MesquiteDouble.infinite) {
+			effectiveMaxValue=10000.0;
+			if (effectiveMaxValue < maxSweetSpotValue*10)
+				effectiveMaxValue=maxSweetSpotValue*10;
+		}
+	}
+	public boolean hasStartingNonSweet(){
+		return minValue!=minSweetSpotValue;
+	}
+	public boolean hasEndingNonSweet(){
+		return maxValue!=maxSweetSpotValue;
+	}
+	public int getStartSweetPixels(){
+		return startSweetPixels;
+	}
+	public int getEndSweetPixels(){
+		return endSweetPixels;
+	}
+	public int getPostSweetPixels(){
+		return totalPixels-endSweetPixels;
+	}
+	public void setMinSweetValue(double minSweetSpotValue){
+		this.minSweetSpotValue = minSweetSpotValue;
+		calcSweetSpot();
+	}
+	public void setMaxSweetValue(double maxSweetSpotValue){
+		this.maxSweetSpotValue = maxSweetSpotValue;
+		calcSweetSpot();
+	}
+	public void setMinValue(double minValue){
+		this.minValue = minValue;
+		calcSweetSpot();
+	}
+	public void setMaxValue(double maxValue){
+		this.maxValue = maxValue;
+		calcSweetSpot();
+	}
+	public void setTotalPixels(int totalPixels){
+		this.totalPixels = totalPixels-1;  // subtract 1 because of zero-based
+		calcSweetSpot();
+	}
+	public abstract double getValue(int pixel);
+	public abstract double getPixelPercent(double value);
+}
+
+
+
diff --git a/Source/mesquite/lib/VoucherInfoFromOTUIDDB.java b/Source/mesquite/lib/VoucherInfoFromOTUIDDB.java
new file mode 100644
index 0000000..c8a95ed
--- /dev/null
+++ b/Source/mesquite/lib/VoucherInfoFromOTUIDDB.java
@@ -0,0 +1 @@
+/* Mesquite source code.  Copyright 2005 and onward David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */


package mesquite.lib; 




/* ======================================================================== */

public class  VoucherInfoFromOTUIDDB {
	public static final NameReference voucherCodeRef = NameReference.getNameReference("VoucherCode"); //keeping it as "Voucher" even though elsewhere it is now "OTU ID"
					// this is important to maintain compatibility with old NEXUS files.
	public static final NameReference voucherDBRef = NameReference.getNameReference("VoucherDB");

	protected String voucherID;
	protected String species;
	protected String organism = "";
	protected String latLong;
	protected String locality;
	protected String note;
	protected String collectionDate;
	protected String identifiedBy;
	StringArray fieldNames, fieldValues;
	boolean flexible = true;


	public VoucherInfoFromOTUIDDB(){
		fieldNames = new StringArray(20);
		fieldValues = new StringArray(20);
	}
	public VoucherInfoFromOTUIDDB(String voucherID, String species, String latLong, String locality, String note, String collectionDate, String identifiedBy){
		this.voucherID = voucherID;
		this.species = species;
		this.latLong = latLong;
		this.locality = locality;
		this.note = note;
		this.collectionDate = collectionDate;
		this.identifiedBy = identifiedBy;
		flexible=false;
	}

	public void addElement(String fieldName, String fieldValue){
		if (!flexible)
			return;
		if (StringUtil.blank(fieldName))
			return;
		if (fieldNames.getFilledSize()>=fieldNames.getSize()){   //add more elements if needed
			fieldNames.addParts(fieldNames.getSize(), 1);
			fieldValues.addParts(fieldValues.getSize(), 1);
		}
		fieldNames.setValue(fieldNames.getFilledSize(), StringUtil.cleanseStringOfFancyChars(fieldName));
		if (!StringUtil.blank(fieldValue))
			fieldValues.setValue(fieldValues.getFilledSize(), StringUtil.cleanseStringOfFancyChars(fieldValue));
	}

	public void addElement(String fieldName){
		addElement(fieldName,null);
	}

	public void setFieldValue(int i, String fieldValue){
		if (!flexible)
			return;
		if (StringUtil.blank(fieldValue))
			return;
		if (fieldValues==null || i>=fieldValues.getSize())
			return;
		String s = StringUtil.cleanseStringOfFancyChars(fieldValue);
		if (fieldNames!=null && fieldNames.getValue(i)!=null && fieldNames.getValue(i).equalsIgnoreCase("organism"))
			organism = s;
		fieldValues.setValue(i, s);
	}


	public String getVoucherID(){
		return voucherID;
	}
	public String getSpecies(){
		return species;
	}
	public String getLatLong(){
		return latLong;
	}
	public String getLocality(){
		return locality;
	}
	public String getNote(){
		return note;
	}
	public String getCollectionDate(){
		return collectionDate;
	}
	public String getIdentifiedBy() {
		return identifiedBy;
	}

	public String getGenBankFieldValue(String fieldName){
		if (StringUtil.blank(fieldName))
			return null;
		if (flexible) {
			for (int i=0; i<fieldNames.getFilledSize(); i++) 
				if (fieldName.equalsIgnoreCase(fieldNames.getValue(i))) {
					return StringUtil.cleanseStringOfFancyChars(fieldValues.getValue(i));
				}
		}
		return null;
	}


	public String toString(){
		if (flexible) {
			String s = "";
			for (int i=0; i<fieldNames.getFilledSize(); i++) {
				s += fieldNames.getValue(i) + " " ;  			
			}
			return "VoucherInfo: " +s;
		}
		else
			return "VoucherInfo: " + voucherID + " " + species + " " + latLong + " " + locality + " " + note + " " + collectionDate;
	}
	
	//lineage???  lat lon
	public String toGenBankString(){
		if (flexible) {
			String s = "";
			String value = "";
			for (int i=0; i<fieldNames.getFilledSize(); i++) {
				if (fieldNames.getValue(i) != null && !fieldNames.getValue(i).startsWith("*")){  //DON;'t use if starts with *
				value = StringUtil.cleanseStringOfFancyChars(fieldValues.getValue(i));
				if (!StringUtil.blank(value))
					s += "[" + fieldNames.getValue(i) + " = " + value + "] ";  	
				}
			}
			s += "  " + organism + " ";
			return s;
		}
		else {
			String s = "";
			if (!StringUtil.blank(species))
				s += "[organism = " + species + "] ";
			if (!StringUtil.blank(identifiedBy))
				s += "[identified-by = " + identifiedBy + "] ";
			if (!StringUtil.blank(voucherID))
				s += "[specimen-voucher = " + voucherID + "] ";
			if (!StringUtil.blank(locality))
				s += "[country = " + locality + "] ";
			if (!StringUtil.blank(latLong))
				s += "[lat-lon = " + latLong + "] ";
			if (!StringUtil.blank(collectionDate))
				s += "[collection-date = " + collectionDate + "] ";
			if (!StringUtil.blank(note))
				s += "[note = " + note + "] ";

			return s;
		}
	}
}


\ No newline at end of file
diff --git a/Source/mesquite/lib/WindowButton.java b/Source/mesquite/lib/WindowButton.java
new file mode 100644
index 0000000..52bd03f
--- /dev/null
+++ b/Source/mesquite/lib/WindowButton.java
@@ -0,0 +1,54 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+
+
+/* ======================================================================== */
+
+public class WindowButton extends Button implements  MouseListener  {
+	MesquiteWindow window;
+	public WindowButton(String label, MesquiteWindow window) {
+		super(label);
+		this.window = window;
+		addMouseListener(this);
+	}
+
+	/*...............................................................................................................*/
+	public void mouseClicked(MouseEvent e)   {
+  	}
+ 	/*...............................................................................................................*/
+	public void mouseEntered(MouseEvent e)   {
+  	}
+	/*...............................................................................................................*/
+	public void mouseExited(MouseEvent e)   {
+  	}
+	/*...............................................................................................................*/
+	public void  mousePressed(MouseEvent e)   {
+	}
+	/*...............................................................................................................*/
+	public void mouseReleased(MouseEvent e)  {
+   		if (window !=null)
+   			window.buttonHit(getLabel(), this);
+	}
+	/*...............................................................................................................*/
+	public void mouseDragged(MouseEvent e)  {
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(MouseEvent e) {
+	}
+}
+
diff --git a/Source/mesquite/lib/WithStringDetails.java b/Source/mesquite/lib/WithStringDetails.java
new file mode 100644
index 0000000..aeec92e
--- /dev/null
+++ b/Source/mesquite/lib/WithStringDetails.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.awt.*;
+import java.text.*;
+
+/* ======================================================================== */
+/**Interface for object to claim it is listable, e.g. in List windows*/
+public interface WithStringDetails {
+ 	public String toStringWithDetails();
+}
+
diff --git a/Source/mesquite/lib/XMLPreferencesProcessor.java b/Source/mesquite/lib/XMLPreferencesProcessor.java
new file mode 100644
index 0000000..5499e99
--- /dev/null
+++ b/Source/mesquite/lib/XMLPreferencesProcessor.java
@@ -0,0 +1,23 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+public interface XMLPreferencesProcessor {
+	
+	public void processSingleXMLPreference (String tag, String content);
+	
+	public void processSingleXMLPreference (String tag, String flavor, String content);
+
+
+}
diff --git a/Source/mesquite/lib/XMLUtil.java b/Source/mesquite/lib/XMLUtil.java
new file mode 100644
index 0000000..64242d6
--- /dev/null
+++ b/Source/mesquite/lib/XMLUtil.java
@@ -0,0 +1,268 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.util.*;
+import java.io.*;
+
+import org.dom4j.*;
+import org.dom4j.io.*;
+
+public class XMLUtil {
+	
+	public static final String FLAVOR = "flavor";
+	
+	/*.................................................................................................................*/
+	public static Element addFilledElement(Element containingElement, String name, String content) {
+		if (content == null || name == null)
+			return null;
+		Element element = DocumentHelper.createElement(name);
+		element.addText(content);
+		containingElement.add(element);
+		return element;
+	}
+	/*.................................................................................................................*/
+	public static Element addFilledElement(Element containingElement, String name, CDATA cdata) {
+		if (cdata == null || name == null)
+			return null;
+		Element element = DocumentHelper.createElement(name);
+		element.add(cdata);
+		containingElement.add(element);
+		return element;
+	}
+	public static String getTextFromElement(Element containingElement, String name){
+		Element e = containingElement.element(name);
+		if (e == null)
+			return null;
+		else return e.getText();
+	}
+	/*.................................................................................................................*/
+
+	public static String getDocumentAsXMLString(Document doc, boolean escapeText)
+	{
+		try {
+			String encoding = doc.getXMLEncoding();
+
+			if (encoding == null)
+				encoding = "UTF-8";
+
+			Writer osw = new StringWriter();
+			OutputFormat opf = new OutputFormat("  ", true, encoding);
+			XMLWriter writer = new XMLWriter(osw, opf);
+			writer.setEscapeText(escapeText);
+			writer.write(doc);
+			writer.close();
+			return osw.toString();
+		} catch (IOException e) {
+			MesquiteMessage.warnProgrammer("XML Document could not be returned as string.");
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public static String getElementAsXMLString(Element doc, String encoding, boolean escapeText)
+	{
+		try {
+
+			Writer osw = new StringWriter();
+			OutputFormat opf = new OutputFormat("  ", true, encoding);
+			XMLWriter writer = new XMLWriter(osw, opf);
+			writer.setEscapeText(escapeText);
+			writer.write(doc);
+			writer.close();
+			return osw.toString();
+		} catch (IOException e) {
+			MesquiteMessage.warnProgrammer("XML Document could not be returned as string.");
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public static String getDocumentAsXMLString(Document doc) {
+		return getDocumentAsXMLString(doc,true);
+	}
+
+	/*.................................................................................................................*/
+
+	public static String getDocumentAsXMLString2(Document doc)
+	{
+		try {
+			String encoding = doc.getXMLEncoding();
+
+			//if (encoding == null)
+			//	encoding = "UTF-8";
+
+			Writer osw = new StringWriter();
+			OutputFormat opf = new OutputFormat("  ", true);
+			XMLWriter writer = new XMLWriter(osw, opf);
+			writer.write(doc);
+			writer.close();
+			return osw.toString();
+		} catch (IOException e) {
+			MesquiteMessage.warnProgrammer("XML Document could not be returned as string.");
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static String stripSchema(String contents) {
+		if (contents==null)
+			return null;
+		int pos = contents.indexOf("<!DOCTYPE");
+		if (pos>=0) {
+			int pos2 = contents.indexOf(">", pos+1);
+			String newVersion = contents.substring(0, pos) + contents.substring(pos2+1,contents.length());
+			return newVersion;
+		}
+		return contents;
+	}
+	/*.................................................................................................................*/
+	public static Document getDocumentFromString(String rootElementName, String contents,boolean stripSchema) {
+		if (stripSchema)
+			contents = stripSchema(contents);
+		Document doc = null;
+		try { 
+			doc = DocumentHelper.parseText(contents);   //WARNING: this can't handle UTF-8 and other encodings.  Thus, accented characters are disallowed.  Use SAXReader instead
+		} catch (Exception e) {
+			return null;
+		}
+
+		if (doc == null || doc.getRootElement() == null) {
+			return  null;
+		} else if (!StringUtil.blank(rootElementName) && !doc.getRootElement().getName().equals(rootElementName)) {
+			return null;
+		}
+		return doc;
+	}
+	/*.................................................................................................................*/
+	public static Document getDocumentFromString(String rootElementName, String contents) {
+		return getDocumentFromString(rootElementName,contents, true);
+	}
+	/*.................................................................................................................*/
+	public static Document getDocumentFromString(String contents) {
+		return getDocumentFromString("",contents, true);
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromString(String rootElementName, String contents, boolean stripSchema) {
+		Document doc = getDocumentFromString(rootElementName, contents, stripSchema);
+		if (doc==null)
+			return null;
+		return doc.getRootElement();
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromString(String rootElementName, String contents) {
+		return getRootXMLElementFromString(rootElementName,contents, true);
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromString(String contents) {
+		return getRootXMLElementFromString("",contents, true);
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromURL(String rootElementName, String url) {
+		SAXReader saxReader = new SAXReader();
+		Document doc = null;
+		try { 
+			doc = saxReader.read(url); 
+		} catch (Exception e) {
+			return null;
+		}
+
+		if (doc == null || doc.getRootElement() == null) {
+			return  null;
+		} else if (!StringUtil.blank(rootElementName) && !doc.getRootElement().getName().equals(rootElementName)) {
+			return null;
+		}
+		Element root = doc.getRootElement();
+		return root;
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromFile(String rootElementName, String path) {
+		SAXReader saxReader = new SAXReader();
+		Document doc = null;
+		try { 
+			doc = saxReader.read(new File(path)); 
+		} catch (Exception e) {
+			return null;
+		}
+
+		if (doc == null || doc.getRootElement() == null) {
+			return  null;
+		} else if (!StringUtil.blank(rootElementName) && !doc.getRootElement().getName().equals(rootElementName)) {
+			return null;
+		}
+		Element root = doc.getRootElement();
+		return root;
+	}
+	/*.................................................................................................................*/
+	public static Element getRootXMLElementFromURL(String url) {
+		return getRootXMLElementFromURL("",url);
+	}
+
+	/*.................................................................................................................*/
+	public static void readXMLPreferences(MesquiteModule module, XMLPreferencesProcessor xmlPrefProcessor, String contents) {
+		Element root = getRootXMLElementFromString("mesquite",contents);
+		if (root==null)
+			return;
+		Element element = root.element(module.getXMLModuleName());
+		if (element != null) {
+			Element versionElement = element.element("version");
+			if (versionElement == null)
+				return ;
+			else {
+				int version = MesquiteInteger.fromString(element.elementText("version"));
+				boolean acceptableVersion = (module.getXMLPrefsVersion()==version || !module.xmlPrefsVersionMustMatch());
+				if (acceptableVersion) 
+					processPreferencesFromXML(xmlPrefProcessor, element);
+				else
+					return;
+			}
+		} 
+	}
+	/*.................................................................................................................*/
+	public static void readXMLPreferencesFromFile (MesquiteModule module, XMLPreferencesProcessor xmlPrefProcessor, String path) {
+		Element root = getRootXMLElementFromFile("mesquite",path);
+		if (root==null)
+			return;
+		Element element = root.element(module.getXMLModuleName());
+		if (element != null) {
+			Element versionElement = element.element("version");
+			if (versionElement == null)
+				return ;
+			else {
+				int version = MesquiteInteger.fromString(element.elementText("version"));
+				boolean acceptableVersion = (module.getXMLPrefsVersion()==version || !module.xmlPrefsVersionMustMatch());
+				if (acceptableVersion) 
+					processPreferencesFromXML(xmlPrefProcessor, element);
+				else
+					return;
+			}
+		} 
+	}
+	
+	/*.................................................................................................................*/
+	public static void processPreferencesFromXML ( XMLPreferencesProcessor xmlPrefProcessor, Element element) {
+
+		List prefElement = element.elements();
+		for (Iterator iter = prefElement.iterator(); iter.hasNext();) {   // this is going through all of the notices
+			Element messageElement = (Element) iter.next();
+			String flavor = messageElement.attributeValue(FLAVOR);
+			if (StringUtil.notEmpty(flavor))
+				xmlPrefProcessor.processSingleXMLPreference(messageElement.getName(), flavor, messageElement.getText());
+			else
+				xmlPrefProcessor.processSingleXMLPreference(messageElement.getName(), messageElement.getText());
+		}
+		
+	}
+
+
+}
diff --git a/Source/mesquite/lib/ZipUtil.java b/Source/mesquite/lib/ZipUtil.java
new file mode 100644
index 0000000..5f058e7
--- /dev/null
+++ b/Source/mesquite/lib/ZipUtil.java
@@ -0,0 +1,158 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Utility class for dealing with zip files
+ *
+ */
+public class ZipUtil {
+	
+    public static ZipOutputStream createZipFile(List files, OutputStream destStream) throws IOException {
+        byte b[] = new byte[512];
+        ZipOutputStream zout = new ZipOutputStream(destStream);
+        int totalSize = 0;
+        for (Iterator iter = files.iterator(); iter.hasNext();) {
+			File nextFile = (File) iter.next();
+	        InputStream in = new FileInputStream(nextFile);
+	        ZipEntry e = new ZipEntry(nextFile.getName());
+	        zout.putNextEntry(e);
+	        int len=0;
+	        while((len=in.read(b)) != -1) {
+	        	zout.write(b,0,len);
+	        	totalSize += len;
+	        }
+	        zout.closeEntry();
+		}
+        zout.finish();
+        return zout;
+    }	
+
+	/**
+	 * Unzips the zip file at the specified path to the specified directory
+	 * optionally deletes the zip afterwards
+	 * @param fullFilePath The full path to the zip file
+	 * @param directoryPath The path to the directory where things should be unzipped
+	 * @param deleteAfterUnzip Whether to delete the original zip after unzipping
+	 */
+	public static void unzipFileToDirectory(String fullFilePath, String directoryPath, boolean deleteAfterUnzip) {
+		// at this point we should have the zip downloaded and on the local filesystem
+		// now we want to unzip it
+		try {
+			ZipFile zf = new ZipFile(fullFilePath);
+		    Enumeration list = zf.entries();
+		    while (list.hasMoreElements()) {
+		        ZipEntry ze = (ZipEntry)list.nextElement();
+		        if (ze.isDirectory()) {
+		            continue;
+		        }
+		        try {
+		            dumpZipEntry(directoryPath, zf, ze);
+		        } catch (IOException e) {
+		            e.printStackTrace();
+		            MesquiteMessage.warnUser("problem dumping zip entry: " + ze.getName());
+		        }                    
+		    }
+		    // Clean up the zip file once the individual entries have been written out.
+		    File zip = new File(fullFilePath);
+		    if (deleteAfterUnzip && zip.exists()) {
+		        zip.delete();
+		    }
+		    zf.close();		    
+		} catch (ZipException e1) {
+		    e1.printStackTrace();
+		} catch (IOException e2) {
+		    e2.printStackTrace();
+		}
+		
+	}
+	
+	private static void dumpZipEntry(String directory, ZipFile zf, ZipEntry ze) throws IOException {
+		InputStream istr = zf.getInputStream(ze);
+		String filename = ze.getName();
+		filename = cleanStringForFilename(filename);
+		BufferedInputStream bis = null;
+		FileOutputStream fos = null;
+		String additionalPiece = directory.endsWith(MesquiteFile.fileSeparator) ? "" : MesquiteFile.fileSeparator; 
+		directory =  directory + additionalPiece;
+		try {
+			bis = new BufferedInputStream(istr);        	
+		    fos = new FileOutputStream(directory + filename);
+		    int sz = (int)ze.getSize();
+		    final int N = 1024;
+		    byte buf[] = new byte[N];
+		    int ln = 0;
+		    while (sz > 0 &&  // workaround for bug
+		      (ln = bis.read(buf, 0, Math.min(N, sz))) != -1) {
+		        fos.write(buf, 0, ln);
+		        sz -= ln;
+		     }
+		} catch (Exception e) {
+			
+		} finally {
+			if (bis != null) {
+				bis.close();
+			}
+			if (fos != null) {
+				fos.flush();
+				fos.close();
+			}
+			if (istr != null) {
+				istr.close();
+			}
+		}
+	}
+	
+	public static String cleanStringForFilename(String originalString) {
+	    String string = removeSpaces(originalString);
+	    string = removeParens(string);
+	    return string;
+	}
+	
+	public static String removeSpaces(String originalString) {
+	    return removeChar(originalString, ' ');
+	}
+	
+	public static String removeParens(String originalString) {
+	    String string = removeChar(originalString, '(');
+	    string = removeChar(string, ')');
+	    return string;
+	}
+	private static String removeChar(String originalString, char badChar) {
+	    String returnString = "";
+	    char[] array = originalString.toCharArray();
+	    for (int i = 0; i < array.length; i++) {
+            char currentChar = array[i];
+            if (currentChar != ' ') {
+                returnString += currentChar;
+            }
+        }
+	    return returnString;	    
+	}	
+}
diff --git a/Source/mesquite/lib/characters/AdjustableDistribution.java b/Source/mesquite/lib/characters/AdjustableDistribution.java
new file mode 100644
index 0000000..5022d86
--- /dev/null
+++ b/Source/mesquite/lib/characters/AdjustableDistribution.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**An interface to signal that a CharacterDistribution can be changed (i.e. its states set, its parent data set, the number
+of taxa readjusted, and so on.  Classes that implement this should override setParentData and setParentCharacter to
+avoid their use, as AdjustableDistributions should not be dependent on a parent CharacterData.  
+Some CharacterDistributions, such as those that report characters from stored matrices in
+a CharacterData object, are not adjustable.
+  See general discussion of character storage classes under CharacterState*/
+public interface AdjustableDistribution extends CharacterStatesHolder  {
+	/*.........................................AdjustableDistribution.................................................*/
+	/** Adjusts the size of this to store states for each of the terminal taxa.*/
+	public AdjustableDistribution adjustSize(Taxa taxa);
+	/*.........................................AdjustableDistribution.................................................*/
+	/**set all states to missing (unassigned)*/
+	public void deassignStates();
+	/**Trade states of nodes it and it2 */
+	public void tradeStatesBetweenTaxa(int it, int it2);
+	
+	/*.................................................................................................................*/
+	/** sets CharacterState at node/taxon it*/
+	public void setCharacterState (int it, CharacterState cs);
+	
+	/**sets the parent data from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd);
+	/*.................................................................................................................*/
+	/**sets the parent character number from which this CharacterDistribution is derived or related*/
+	public void setParentCharacter (int ic);
+}
+
+
diff --git a/Source/mesquite/lib/characters/AlteredDataParameters.java b/Source/mesquite/lib/characters/AlteredDataParameters.java
new file mode 100644
index 0000000..5067b22
--- /dev/null
+++ b/Source/mesquite/lib/characters/AlteredDataParameters.java
@@ -0,0 +1,26 @@
+package mesquite.lib.characters;
+
+public class AlteredDataParameters {
+	int[] parameters = null;
+	int[] subcodes = null;
+	
+	public AlteredDataParameters() {
+	}
+
+	public int[] getParameters() {
+		return parameters;
+	}
+
+	public void setParameters(int[] parameters) {
+		this.parameters = parameters;
+	}
+
+	public int[] getSubcodes() {
+		return subcodes;
+	}
+
+	public void setSubcodes(int[] subcodes) {
+		this.subcodes = subcodes;
+	}
+
+}
diff --git a/Source/mesquite/lib/characters/CLikelihoodCalculator.java b/Source/mesquite/lib/characters/CLikelihoodCalculator.java
new file mode 100644
index 0000000..f24cc92
--- /dev/null
+++ b/Source/mesquite/lib/characters/CLikelihoodCalculator.java
@@ -0,0 +1,26 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** An object (e.g. a module) that can calculate likelihood. */
+public interface  CLikelihoodCalculator  {
+  	public double logLikelihoodCalc(Tree tree, ProbabilityModel model, CharacterDistribution observedStates);
+}
+
+
diff --git a/Source/mesquite/lib/characters/CModelEstimator.java b/Source/mesquite/lib/characters/CModelEstimator.java
new file mode 100644
index 0000000..d58b516
--- /dev/null
+++ b/Source/mesquite/lib/characters/CModelEstimator.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A character model that can estimate its own parameters. */
+public interface  CModelEstimator  {
+  	public void estimateParameters(Tree tree, CharacterDistribution observedStates, CLikelihoodCalculator lc);
+  	//NOT YET USED public void estimateParameters(Tree tree, MCharactersDistribution observedStates, CLikelihoodCalculator lc);
+}
+
+
diff --git a/Source/mesquite/lib/characters/CellBlock.java b/Source/mesquite/lib/characters/CellBlock.java
new file mode 100644
index 0000000..5f4fbb3
--- /dev/null
+++ b/Source/mesquite/lib/characters/CellBlock.java
@@ -0,0 +1,610 @@
+package mesquite.lib.characters;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CellBlock {
+	CategoricalData data;
+	MesquiteTable table;
+
+	Bits whichTaxa;
+	Bits originalWhichTaxa;
+	MesquiteInteger firstCharInBlock;
+	MesquiteInteger lastCharInBlock;
+	int originalFirstCharInFullBlock;
+	int originalLastCharInFullBlock;
+	int originalFirstCharInBlock;
+	int originalLastCharInBlock;
+	int currentFirstCharInBlock = 0;
+	int currentLastCharInBlock = 0;
+	int previousFirstCharInBlock = 0;
+	int previousLastCharInBlock = 0;
+
+	MesquiteInteger firstTaxonInBlock;
+	MesquiteInteger lastTaxonInBlock;
+//	int originalFirstTaxonInFullBlock;
+//	int originalLastTaxonInFullBlock;
+	int originalFirstTaxonInBlock;
+	int originalLastTaxonInBlock;
+	int currentFirstTaxonInBlock = 0;
+	int currentLastTaxonInBlock = 0;
+//	int previousFirstTaxonInBlock = 0;
+//	int previousLastTaxonInBlock = 0;
+
+	int maxLeftMovement=0;
+	int maxRightMovement=0;
+
+	int currentLeftMovement = 0;
+	int currentRightMovement = 0;
+
+	boolean atEdgeLeft = false;
+	boolean atEdgeRight = false;
+	boolean isRight = false;
+	boolean isLeft = false;
+
+	boolean locked = false;
+	boolean useWhichTaxaBits = false;
+
+	public CellBlock(CategoricalData data, MesquiteTable table) {
+		this.data = data;
+		this.table = table;
+		whichTaxa = new Bits(data.getNumTaxa());
+		whichTaxa.clearAllBits();
+		originalWhichTaxa = new Bits(data.getNumTaxa());
+		originalWhichTaxa.clearAllBits();
+	}
+	/*.................................................................................................................*/
+	public void reset(){    
+		currentLeftMovement = 0;
+		currentRightMovement = 0;
+		whichTaxa = new Bits(data.getNumTaxa());
+		whichTaxa.clearAllBits();
+		originalWhichTaxa = new Bits(data.getNumTaxa());
+		originalWhichTaxa.clearAllBits();
+		setAllBlocks(originalFirstCharInBlock, originalLastCharInBlock,originalFirstTaxonInBlock,originalLastTaxonInBlock);
+		locked = false;
+	}
+	/*.................................................................................................................*/
+	public void restoreCharBlock(MesquiteBoolean dataChanged){    // takes data that is currently at currentBlock location and move to original location
+		if (!(currentLeftMovement==0 && currentRightMovement==0)) {
+			int distanceToMove = originalFirstCharInBlock - previousFirstCharInBlock;
+			int added = data.moveCells(previousFirstCharInBlock,previousLastCharInBlock, distanceToMove, whichTaxa, true, false, true, false,dataChanged,null, null);
+
+			table.redrawBlock(MesquiteInteger.minimum(previousFirstCharInBlock, originalFirstCharInBlock), MesquiteInteger.maximum(previousLastCharInBlock, originalLastCharInBlock), whichTaxa);
+			reset();
+		}
+	}
+	/*.................................................................................................................*/
+
+
+	/*.................................................................................................................*/
+	public void setMaximumMovements (int maxLeftMovement, int maxRightMovement){
+		this.maxLeftMovement = maxLeftMovement;
+		this.maxRightMovement = maxRightMovement;
+	}
+	/*.................................................................................................................*/
+	public void setMaximumMovements (){
+		this.maxLeftMovement = gapColumnsToLeftOfBlock();
+		this.maxRightMovement = gapColumnsToRightOfBlock();
+	}
+	public int getMaxLeftMovement (){
+		return  maxLeftMovement;
+	}
+	public int getMaxRightMovement (){
+		return maxRightMovement;
+	}
+	/*.................................................................................................................*/
+	public int availableLeftMovement (){
+		return maxLeftMovement-currentLeftMovement;
+	}
+	/*.................................................................................................................*/
+	public int availableRightMovement (){
+		return maxRightMovement-currentRightMovement;
+	}
+	/*.................................................................................................................*/
+	public int movementAllowed (int candidateMovement, boolean canExpand){
+		if (candidateMovement<0){  // move to left
+			if (canExpand & isLeft & atEdgeLeft)   // any amount can be accommodated
+				return candidateMovement;
+			if ((-candidateMovement)<=availableLeftMovement())  // it is acceptable
+				return candidateMovement;
+			return -availableLeftMovement();
+		}
+		if (candidateMovement>0){  // move to right
+			if (canExpand & isRight & atEdgeRight)
+				return candidateMovement;
+			if (candidateMovement<=availableRightMovement())  // it is acceptable
+				return candidateMovement;
+			return availableRightMovement();
+		}
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public void switchCharBlock(int icStart, int icEnd){  
+		originalFirstCharInBlock=icStart;
+		originalLastCharInBlock=icEnd;
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+		previousFirstCharInBlock=icStart;
+		previousLastCharInBlock=icEnd;
+	}
+	/*.................................................................................................................*/
+	public Bits getWhichTaxa() {
+		return whichTaxa;
+	}
+	/*.................................................................................................................*/
+	public void resetWhichTaxa() {
+		whichTaxa.clearAllBits();
+		for (int it=currentFirstTaxonInBlock; it<=currentLastTaxonInBlock; it++)
+			whichTaxa.setBit(it);
+	}
+	/*.................................................................................................................*/
+	public void setWhichTaxa(int itStart, int itEnd) {
+		whichTaxa.clearAllBits();
+		for (int it=itStart; it<=itEnd; it++)
+			whichTaxa.setBit(it);
+	}
+	/*.................................................................................................................*/
+	public String listWhichTaxa() {
+		StringBuffer sb = new StringBuffer();
+		for (int it=0; it<=whichTaxa.getSize(); it++)
+			if (whichTaxa.isBitOn(it))
+				sb.append(" " + it);
+		return sb.toString();
+				
+	}
+	/*.................................................................................................................*/
+	public void resetWhichTaxa(boolean reverse) {
+		whichTaxa.setAllBits();
+		for (int it=currentFirstTaxonInBlock; it<=currentLastTaxonInBlock; it++)
+			whichTaxa.clearBit(it);
+	}
+	/*.................................................................................................................*/
+	public void reverseWhichTaxa() {
+		whichTaxa.invertAllBits();
+	}
+
+	/*.................................................................................................................*/
+	public void setCurrentTaxa(int itStart,int itEnd) {
+		currentFirstTaxonInBlock=itStart;
+		currentLastTaxonInBlock=itEnd;
+		resetWhichTaxa();
+	}
+	/*.................................................................................................................*/
+	public void setAllBlocks(int icStart, int icEnd, int itStart, int itEnd){  
+		originalFirstCharInBlock=icStart;
+		originalLastCharInBlock=icEnd;
+		originalFirstTaxonInBlock=itStart;
+		originalLastTaxonInBlock=itEnd;
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+		currentFirstTaxonInBlock=itStart;
+		currentLastTaxonInBlock=itEnd;
+		previousFirstCharInBlock=icStart;
+		previousLastCharInBlock=icEnd;
+	//	previousFirstTaxonInBlock=itStart;
+	//	previousLastTaxonInBlock=itEnd;
+
+	}
+	/*.................................................................................................................*/
+	public void setAllBlocks(int icStart, int icEnd, Bits whichTaxa){  
+		originalFirstCharInBlock=icStart;
+		originalLastCharInBlock=icEnd;
+		originalWhichTaxa = whichTaxa.cloneBits();
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+		this.whichTaxa = whichTaxa.cloneBits();
+		previousFirstCharInBlock=icStart;
+		previousLastCharInBlock=icEnd;
+	//	previousFirstTaxonInBlock=itStart;
+	//	previousLastTaxonInBlock=itEnd;
+
+	}
+	/*.................................................................................................................*/
+	public void setOriginalFullBlockOnTouch(int icStart, int icEnd, int itStart, int itEnd){  
+		originalFirstCharInFullBlock=icStart;
+		originalLastCharInFullBlock=icEnd;
+		//originalFirstTaxonInFullBlock=itStart;
+		//originalLastTaxonInFullBlock=itEnd;
+	}
+	/*.................................................................................................................*/
+	public void setOriginalBlock(int icStart, int icEnd, int itStart, int itEnd){  
+		originalFirstCharInBlock=icStart;
+		originalLastCharInBlock=icEnd;
+		originalFirstTaxonInBlock=itStart;
+		originalLastTaxonInBlock=itEnd;
+	}
+	/*.................................................................................................................*/
+	public void setOriginalFirstCharInBlock(int icStart){  
+		originalFirstCharInBlock=icStart;
+	}
+	/*.................................................................................................................*/
+	public int getOriginalFirstCharInBlock(){  
+		return originalFirstCharInBlock;
+	}
+	/*.................................................................................................................*/
+	public int getOriginalLastCharInBlock(){  
+		return originalLastCharInBlock;
+	}
+	/*.................................................................................................................*
+	public int getOriginalFirstTaxonInBlock(){  
+		return originalFirstTaxonInBlock;
+	}
+	/*.................................................................................................................*
+	public int getOriginalLastTaxonInBlock(){  
+		return originalLastTaxonInBlock;
+	}
+	/*.................................................................................................................*/
+	public int getOriginalFirstCharInFullBlock(){  
+		return originalFirstCharInFullBlock;
+	}
+	/*.................................................................................................................*/
+	public int getOriginalLastCharInFullBlock(){  
+		return originalLastCharInFullBlock;
+	}
+	/*.................................................................................................................*
+	public int getOriginalFirstTaxonInFullBlock(){  
+		return originalFirstTaxonInFullBlock;
+	}
+	/*.................................................................................................................*
+	public int getOriginalLastTaxonInFullBlock(){  
+		return originalLastTaxonInFullBlock;
+	}
+	/*.................................................................................................................*/
+	public void setCurrentCharBlock(int icStart, int icEnd){  
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+	}
+	/*.................................................................................................................*/
+	public void setCurrentBlock(int icStart, int icEnd, int itStart, int itEnd){  
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+		currentFirstTaxonInBlock=itStart;
+		currentLastTaxonInBlock=itEnd;
+	}
+	/*.................................................................................................................*/
+	public void setCurrentBlock(int icStart, int icEnd, Bits whichTaxa){  
+		currentFirstCharInBlock=icStart;
+		currentLastCharInBlock=icEnd;
+		this.whichTaxa = whichTaxa.cloneBits();
+	}
+	/*.................................................................................................................*/
+	public void shiftCurrentBlock(int shift){  
+		currentFirstCharInBlock+=shift;
+		currentLastCharInBlock+=shift;
+		//currentFirstTaxonInBlock+=shift;
+		//currentLastTaxonInBlock+=shift;
+	}
+	/*.................................................................................................................*/
+	public int getCurrentFirstCharInBlock(){  
+		return currentFirstCharInBlock;
+	}
+	/*.................................................................................................................*/
+	public int getCurrentLastCharInBlock(){  
+		return currentLastCharInBlock;
+	}
+	/*.................................................................................................................*
+	public int getCurrentFirstTaxonInBlock(){  
+		return currentFirstTaxonInBlock;
+	}
+	/*.................................................................................................................*
+	public int getCurrentLastTaxonInBlock(){  
+		return currentLastTaxonInBlock;
+	}
+	/*.................................................................................................................*/
+	public void setPreviousCharBlock(int icStart, int icEnd){  
+		previousFirstCharInBlock=icStart;
+		previousLastCharInBlock=icEnd;
+	}
+	/*.................................................................................................................*/
+	public void addToCharBlockValues(int added){  
+		originalFirstCharInBlock+=added;
+		originalLastCharInBlock+=added;
+		currentFirstCharInBlock+=added;
+		currentLastCharInBlock+=added;
+		previousFirstCharInBlock+=added;
+		previousLastCharInBlock+=added;
+	}
+
+	/*.................................................................................................................*/
+	public void transferCurrentToPrevious(){  
+		previousFirstCharInBlock=currentFirstCharInBlock;
+		previousLastCharInBlock=currentLastCharInBlock;
+		//previousFirstTaxonInBlock=currentFirstTaxonInBlock;
+		//previousLastTaxonInBlock=currentLastTaxonInBlock;
+	}
+	/*.................................................................................................................*/
+	public void setPreviousBlock(int icStart, int icEnd, int itStart, int itEnd){  
+		previousFirstCharInBlock=icStart;
+		previousLastCharInBlock=icEnd;
+		//previousFirstTaxonInBlock=itStart;
+		//previousLastTaxonInBlock=itEnd;
+	}
+	/*.................................................................................................................*/
+	public int getPreviousFirstCharInBlock(){  
+		return previousFirstCharInBlock;
+	}
+	/*.................................................................................................................*/
+	public int getPreviousLastCharInBlock(){  
+		return previousLastCharInBlock;
+	}
+	/*.................................................................................................................*
+	public int getPreviousFirstTaxonInBlock(){  
+		return previousFirstTaxonInBlock;
+	}
+	/*.................................................................................................................*
+	public int getPreviousLastTaxonInBlock(){  
+		return previousLastTaxonInBlock;
+	}
+	/*.................................................................................................................*/
+	public void adjustToMove(int movement) {
+		if (movement<0){   //moving left
+			currentLeftMovement-=movement;
+			currentRightMovement+=movement;
+		}
+		else if (movement>0){   //moving right
+			currentLeftMovement-=movement;
+			currentRightMovement+=movement;
+		}
+		shiftCurrentBlock(movement);
+
+	}
+	/*.................................................................................................................*/
+	public void addCharacters(int added, boolean toStart){  
+		if (toStart) {
+			originalFirstCharInBlock+=added;
+			originalLastCharInBlock+=added;
+			currentFirstCharInBlock+=added;
+			currentLastCharInBlock+=added;
+			previousFirstCharInBlock+=added;
+			previousLastCharInBlock+=added;
+		}
+		if (isLeft && toStart)
+			maxLeftMovement+=added;
+		if (isRight && !toStart)
+			maxRightMovement+=added;
+	}
+	/*.................................................................................................................*/
+	public int gapColumnsToLeftOfBlock() {
+		atEdgeLeft = false;
+		if (currentFirstCharInBlock<=0) {
+			atEdgeLeft = true;
+			return 0;
+		}
+		int count = 0;
+		for (int ic = currentFirstCharInBlock-1; ic>=0; ic--) {
+			if (data.inapplicableBlock(ic, ic, whichTaxa)) {
+				count++;
+				if (ic==0)
+					atEdgeLeft=true;
+			}
+			else
+				break;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int gapColumnsToRightOfBlock() {
+		atEdgeRight=false;
+		if (currentLastCharInBlock>=data.getNumChars()-1) {
+			atEdgeRight=true;
+			return 0;
+		}
+		int count = 0;
+		for (int ic = currentLastCharInBlock+1; ic<data.getNumChars(); ic++) {
+			if (data.inapplicableBlock(ic, ic, whichTaxa)){
+				count++;
+				if (ic==data.getNumChars()-1)
+					atEdgeRight=true;
+			}
+			else
+				break;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public void getBlockInSequence(int ic, int it, MesquiteInteger firstInBlock, MesquiteInteger lastInBlock, boolean wholeSelectedBlock, boolean wholeSequenceLeft, boolean wholeSequenceRight, MesquiteBoolean cellHasInapplicable, MesquiteBoolean leftIsInapplicable, MesquiteBoolean rightIsInapplicable){  // determines the block that was touched
+		cellHasInapplicable.setValue(false);
+		leftIsInapplicable.setValue(false);
+		rightIsInapplicable.setValue(false);
+		firstInBlock.setValue(0);
+		lastInBlock.setValue(data.getNumChars()-1);
+		if (ic>0)
+			if (data.isInapplicable(ic-1, it))
+				leftIsInapplicable.setValue(true);
+		if (ic<data.getNumChars())
+			if (data.isInapplicable(ic+1, it))
+				rightIsInapplicable.setValue(true);
+		/*
+		 * 		if (data.isInapplicable(ic, it)) {
+			firstInBlock.setValue(ic);
+			lastInBlock.setValue(-1);
+			cellHasInapplicable.setValue(true);
+			return;
+		}
+		 */
+		if (wholeSequenceLeft) {
+			firstInBlock.setValue(data.firstApplicable(it));
+		} 
+		else if (wholeSelectedBlock) {
+			for (int i=ic; i>=0; i--) {   // find first unselected cell to the left of this point
+				if (!table.isCellSelected(i, it)){  // should be isToolInapplicable
+					firstInBlock.setValue(i+1);
+					break;
+				}
+			}
+		}
+		else {
+			for (int i=ic; i>=0; i--) {   // find first gap to the left of this point
+				if (data.isInapplicable(i, it)){  // should be isToolInapplicable
+					firstInBlock.setValue(i+1);
+					break;
+				}
+			}
+		}
+
+
+		if (wholeSequenceRight) {
+			lastInBlock.setValue(data.lastApplicable(it));
+		}
+		else if (wholeSelectedBlock) {
+			for (int i=ic; i<data.getNumChars(); i++) {  // find first unselected cell to the right of this point
+				if (!table.isCellSelected(i, it)){ 
+					lastInBlock.setValue(i-1);
+					return;
+				}
+			}
+		}
+		else {
+			for (int i=ic; i<data.getNumChars(); i++) {  // find first gap to the right of this point
+				if (data.isInapplicable(i, it)){  // should be isToolInapplicable
+					lastInBlock.setValue(i-1);
+					return;
+				}
+			}
+		}
+	}
+	/** Gets the cell block that contains the cells of character ic from itStart to itEnd */
+	/*.................................................................................................................*/
+	public void getCellBlock(int icStart, int icEnd, int itStart, int itEnd, MesquiteInteger firstInBlock, MesquiteInteger lastInBlock, boolean wholeSelectedBlock, boolean wholeSequenceLeft, boolean wholeSequenceRight, MesquiteBoolean cellHasInapplicable, MesquiteBoolean leftIsInapplicable, MesquiteBoolean rightIsInapplicable){  // determines the block that was touched
+		Bits whichTaxa = new Bits(data.getNumTaxa());
+		for (int it=itStart; it<=itEnd; it++)
+			whichTaxa.setBit(it);
+		getCellBlock( icStart,  icEnd, whichTaxa,  firstInBlock,  lastInBlock,  wholeSelectedBlock,  wholeSequenceLeft,  wholeSequenceRight,  cellHasInapplicable,  leftIsInapplicable,  rightIsInapplicable);  // determines the block that was touched
+
+	}
+	/*.................................................................................................................*/
+	public void getCellBlock(int icStart, int icEnd, Bits whichTaxa, MesquiteInteger firstInBlock, MesquiteInteger lastInBlock, boolean wholeSelectedBlock, boolean wholeSequenceLeft, boolean wholeSequenceRight, MesquiteBoolean cellHasInapplicable, MesquiteBoolean leftIsInapplicable, MesquiteBoolean rightIsInapplicable){  // determines the block that was touched
+		cellHasInapplicable.setValue(false);
+		leftIsInapplicable.setValue(false);
+		rightIsInapplicable.setValue(false);
+		firstInBlock.setValue(0);
+		lastInBlock.setValue(data.getNumChars()-1);
+		if (icStart>0)
+			if (data.inapplicableBlock(icStart-1, icStart-1, whichTaxa))
+				leftIsInapplicable.setValue(true);
+		if (icEnd<data.getNumChars())
+			if (data.inapplicableBlock(icEnd, icEnd, whichTaxa))
+				rightIsInapplicable.setValue(true);
+		if (wholeSequenceLeft) {
+			firstInBlock.setValue(data.firstApplicable(whichTaxa));
+		} 
+		else if (wholeSelectedBlock) {
+			for (int i=icStart; i>=0; i--) {   // find first unselected cell to the left of this point
+				if (!table.isAnyCellSelectedInBlock(i, i, whichTaxa)){ 
+					firstInBlock.setValue(i+1);
+					break;
+				}
+			}
+		}
+		else {
+			for (int i=icStart; i>=0; i--) {   // find first gap to the left of this point
+				if (data.inapplicableBlock(i, i, whichTaxa)){  // should be isToolInapplicable
+					firstInBlock.setValue(i+1);
+					break;
+				} else if (i<icStart&&!data.applicableInBothCharacters(i,i+1,whichTaxa)) {
+					firstInBlock.setValue(i+1);
+					break;
+				}
+			}
+		}
+
+
+		if (wholeSequenceRight) {
+			lastInBlock.setValue(data.lastApplicable(whichTaxa));
+		}
+		else if (wholeSelectedBlock) {
+			for (int i=icEnd; i<data.getNumChars(); i++) {  // find first unselected cell to the right of this point
+				if (!table.isAnyCellSelectedInBlock(i, i, whichTaxa)){ 
+					lastInBlock.setValue(i-1);
+					return;
+				}
+			}
+		}
+		else {
+			for (int i=icEnd; i<data.getNumChars(); i++) {  // find first gap to the right of this point
+				if (data.inapplicableBlock(i,i, whichTaxa)){  // should be isToolInapplicable�
+					lastInBlock.setValue(i-1);
+					return;
+				} else if (i>icEnd &&!data.applicableInBothCharacters(i,i-1,whichTaxa)) {
+					lastInBlock.setValue(i-1);
+					return;
+				}
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Select block of cells. */
+	public void deselectOthersAndSelectBlock() {
+		table.deSelectAndRedrawOutsideBlock(currentFirstCharInBlock, currentLastCharInBlock, whichTaxa);
+		table.selectBlock(currentFirstCharInBlock, currentLastCharInBlock, whichTaxa);
+
+	}
+
+	public int getCurrentLeftMovement() {
+		return currentLeftMovement;
+	}
+	public void setCurrentLeftMovement(int currentLeftMovement) {
+		this.currentLeftMovement = currentLeftMovement;
+	}
+	public int getCurrentRightMovement() {
+		return currentRightMovement;
+	}
+	public void setCurrentRightMovement(int currentRightMovement) {
+		this.currentRightMovement = currentRightMovement;
+	}
+	public boolean isAtEdgeLeft() {
+		return atEdgeLeft;
+	}
+	public void setAtEdgeLeft(boolean atEdgeLeft) {
+		this.atEdgeLeft = atEdgeLeft;
+	}
+	public boolean isAtEdgeRight() {
+		return atEdgeRight;
+	}
+	public void setAtEdgeRight(boolean atEdgeRight) {
+		this.atEdgeRight = atEdgeRight;
+	}
+	public boolean getLeft() {
+		return isLeft;
+	}
+	public boolean getRight() {
+		return isRight;
+	}
+	public void setRight(boolean isRight) {
+		this.isRight = isRight;
+	}
+	public void setLeft(boolean isLeft) {
+		this.isLeft = isLeft;
+	}
+	public boolean isLocked() {
+		return locked;
+	}
+	public void setLocked(boolean locked) {
+		this.locked = locked;
+	}
+	public boolean isUseWhichTaxaBits() {
+		return useWhichTaxaBits;
+	}
+	public void setUseWhichTaxaBits(boolean useWhichTaxaBits) {
+		this.useWhichTaxaBits = useWhichTaxaBits;
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/CentralModelListener.java b/Source/mesquite/lib/characters/CentralModelListener.java
new file mode 100644
index 0000000..c322e47
--- /dev/null
+++ b/Source/mesquite/lib/characters/CentralModelListener.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  17 August 1998; updated May 2000 */
+/* ======================================================================== */
+/** A class for the object belonging to the project that serves as central location for listening to 
+models and reporting to those interested if one changed.  This avoids modules having to sets themselves as listeners for all
+of various models that come and go.  Each character model registers itself with this and the modules set themselves
+as listeners of this CentralModelListener*/
+public class CentralModelListener extends FileElement implements MesquiteListener  {
+
+	public static void staticChanged(Object caller, Class c, Notification notification){
+		Projects ps = MesquiteTrunk.mesquiteTrunk.getProjectList();
+		for (int i=0; i<ps.getNumProjects(); i++){
+			MesquiteProject p = ps.getProject(i);
+			CentralModelListener cml = p.getCentralModelListener();
+			cml.notifyListeners(caller, c, notification);
+			//cml.allModelsOfClassChanged(p, caller, c, code, parameters);
+		}
+	}
+	/*
+	private void allModelsOfClassChanged(MesquiteProject p, Object caller, Class c, int code, int[] parameters){
+		ModelVector mv = p.getCharacterModels();
+		for (int i=0; i<mv.size(); i++){
+			CharacterModel cm = (CharacterModel)mv.elementAt(i);
+			if (c.isAssignableFrom(cm.getClass())) {
+				notifyListeners(caller, cm, code, parameters);
+			}
+		}
+	}
+	*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof CharacterModel){
+			notifyListeners(caller, obj, notification);
+		}
+	}
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	public void disposing(Object obj){
+		if (obj instanceof CharacterModel){
+			notifyDisposing(obj);
+		}
+	}
+	/**/
+	public void addModel(CharacterModel model){
+		model.addListener(this);
+	}
+	public void removeModel(CharacterModel model){
+		model.removeListener(this);
+	}
+ 	/*.................................................................................................................*/
+	/** notifies listeners that model has changed*/
+	public void notifyListeners(Object caller, Object model, Notification notification) {
+		if (MesquiteThread.getListenerSuppressionLevel()>1)
+			return;
+		CommandRecord.tick("Model changed");
+		
+		if (listeners!=null) {
+			Enumeration e = listeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteListener listener = (MesquiteListener)obj;
+	 			listener.changed(caller, model, notification);
+			}
+		}
+	}
+	/**/
+}
+
diff --git a/Source/mesquite/lib/characters/CharBitsSet.java b/Source/mesquite/lib/characters/CharBitsSet.java
new file mode 100644
index 0000000..f234f70
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharBitsSet.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A specset with bit information about characters.   Called "character bits set" because it amounts to a selection (bit on = yes, bit off  = no)
+for a whole list of characters.  It is abstract because it doesn't define cloneSpecsSet  */
+public abstract class CharBitsSet extends BitsSpecsSet implements CharSpecsSet { //should extend a generic BitsSpecsSet
+	CharacterData data;
+	public CharBitsSet(String name, int numChars, CharacterData data){
+		super(name, numChars);
+		this.data = data;
+	}
+	public String getTypeName(){
+		return "Character selection set";
+	}
+ 	/*.................................................................................................................*/
+	public CharacterData getCharacterData(){
+		return data;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharHistoryContainer.java b/Source/mesquite/lib/characters/CharHistoryContainer.java
new file mode 100644
index 0000000..538f88e
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharHistoryContainer.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Stores a CharacterHistory. */
+public interface CharHistoryContainer  {
+	public CharacterHistory getCharacterHistory();
+	public Tree getTree();
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharInclusionSet.java b/Source/mesquite/lib/characters/CharInclusionSet.java
new file mode 100644
index 0000000..ae99141
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharInclusionSet.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A character inclusion set.   */
+public class CharInclusionSet extends CharBitsSet { 
+	public CharInclusionSet(String name, int numChars, CharacterData data){
+		super(name, numChars, data);
+	}
+	public String getTypeName(){
+		return "Character Inclusion set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CharInclusionSet bss = new CharInclusionSet("cloned", getNumberOfParts(), data);
+		for (int i=0; i< getNumberOfParts(); i++) {
+			bss.setSelected(i, isBitOn(i));
+		}
+		return bss;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		CharInclusionSet cis = new CharInclusionSet("Inclusion Set", numParts, (CharacterData)parent);
+		cis.selectAll();
+		return cis;
+	}
+	
+	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		boolean success = super.addParts(starting, num); 
+		if (success) {
+			for (int i=starting+1; i< starting+num+1; i++) //default is for the bit to be set
+				setSelected(i, true);
+		}
+		return success;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharNumSet.java b/Source/mesquite/lib/characters/CharNumSet.java
new file mode 100644
index 0000000..34f46a3
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharNumSet.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A specset with number information about characters.    */
+public abstract class CharNumSet extends NumSpecsSet implements CharSpecsSet { //should extend a generic BitsSpecsSet
+	protected CharacterData data;
+	public CharNumSet(String name, int numChars, MesquiteNumber defaultValue, CharacterData data){
+		super(name, numChars, defaultValue);
+		this.data = data;
+	}
+	public String getTypeName(){
+		return "Character number set";
+	}
+ 	/*.................................................................................................................*/
+	public CharacterData getCharacterData(){
+		return data;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharObjectSpecsSet.java b/Source/mesquite/lib/characters/CharObjectSpecsSet.java
new file mode 100644
index 0000000..d5d6d5c
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharObjectSpecsSet.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+public abstract class CharObjectSpecsSet  extends ObjectSpecsSet implements CharSpecsSet {
+	protected CharacterData data;
+	
+	public CharObjectSpecsSet (String name, int numChars, Object defaultProperty, CharacterData data) {
+		super(name, numChars, defaultProperty);
+		this.data = data;
+	}
+	
+	public int getNumChars(){
+		return getNumberOfParts();
+	}
+ 	/*.................................................................................................................*/
+	public CharacterData getCharacterData(){
+		return data;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharSelectionSet.java b/Source/mesquite/lib/characters/CharSelectionSet.java
new file mode 100644
index 0000000..628b65a
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharSelectionSet.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A character set. */
+public class CharSelectionSet extends CharBitsSet { 
+	public CharSelectionSet(String name, int numChars, CharacterData data){
+		super(name, numChars, data);
+	}
+	public String getTypeName(){
+		return "Character Selection set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CharSelectionSet bss = new CharSelectionSet("cloned", getNumberOfParts(), data);
+		for (int i=0; i< getNumberOfParts(); i++) {
+			bss.setSelected(i, isBitOn(i));
+		}
+		return bss;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharSelectionSet("Selection Set", numParts, (CharacterData)parent);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharSort.java b/Source/mesquite/lib/characters/CharSort.java
new file mode 100644
index 0000000..79d250d
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharSort.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*======================================================================== */
+/** a sorting for characters. */
+public class CharSort  extends CharNumSet {
+	
+	public CharSort (String name, int numChars, CharacterData data) {
+		super(name, numChars, new MesquiteNumber(), data);
+	}
+	public String getTypeName(){
+		return "Character Order";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CharSort ms = new CharSort(new String(name), getNumberOfParts(),  data);
+		MesquiteNumber order = new MesquiteNumber();
+		for (int i=0; i< getNumberOfParts(); i++) {
+			placeValue(i, order);
+			ms.setValue(i, order);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharSort("Character Order", numParts, (CharacterData)parent);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharSpecsSet.java b/Source/mesquite/lib/characters/CharSpecsSet.java
new file mode 100644
index 0000000..b9a7c1b
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharSpecsSet.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  December 1998 */
+/* ======================================================================== */
+/** This abstract class serves to superclass weight sets, model sets, inclusion sets, character sets, and any
+other listing of characters with specification of values for each character.  The different sorts of specsets are stored in different vectors
+within a CharacterData object.*/
+public interface CharSpecsSet extends Listable, Identifiable {	
+ 	/*.................................................................................................................*/
+	/** Add num characters just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Delete characters specified  */
+	public boolean deleteParts(int starting, int num);
+	/*.................................................................................................................*/
+	/** Move num characters starting at first, to just after character justAfter  */
+	public boolean moveParts(int first, int num, int justAfter);
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public boolean swapParts(int first, int second);
+	
+	public CharacterData getCharacterData();
+}
+
diff --git a/Source/mesquite/lib/characters/CharWeightSet.java b/Source/mesquite/lib/characters/CharWeightSet.java
new file mode 100644
index 0000000..2aca227
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharWeightSet.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*======================================================================== */
+/** a weight set for characters. */
+public class CharWeightSet  extends CharNumSet {
+	
+	public CharWeightSet (String name, int numChars, CharacterData data) {
+		super(name, numChars, new MesquiteNumber(1), data);
+		setDefaultValue(new MesquiteNumber(1));
+			for (int i = 0; i<numChars; i++)
+ 				setValue(i, 1);
+	}
+	public String getTypeName(){
+		return "Character Weight set";
+	}
+	
+	public SpecsSet cloneSpecsSet(){
+		CharWeightSet ms = new CharWeightSet(new String(name), getNumberOfParts(),  data);
+		MesquiteNumber weight = new MesquiteNumber();
+		for (int i=0; i< getNumberOfParts(); i++) {
+			placeValue(i, weight);
+			ms.setValue(i, weight);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharWeightSet("Weight Set", numParts, (CharacterData)parent);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharacterData.java b/Source/mesquite/lib/characters/CharacterData.java
new file mode 100644
index 0000000..49882d8
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterData.java
@@ -0,0 +1,3782 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison.
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.util.*;
+import java.util.zip.*;
+
+import javax.swing.text.JTextComponent;
+
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lists.lib.ListModule;
+import mesquite.lib.table.*;
+
+/* last documented: April 2003 */
+/* ======================================================================== */
+/**An object of this class represents a Characters block within a NEXUS file.  It is basically a data matrix
+plus additional information about the characters, symbols, etc. Includes methods to add, delete and move characters. 
+Note: methods to adjust taxa are in Taxa, but they need to appear here also so that matrices may be adjusted
+ as needed (to delete rows).<p>
+This is subclassed separately for categorical and continuous data; it is there that the matrices appear. Also, methods to set and get character
+states occur in generic form using CharacterState objects, but also datatype-specific methods appear in the subclasses to set or return directly 
+the character state in its specific form (e.g. long getState(ic, it). 
+<p>
+CharacterData is a subclass of Associable, which is considered to consist of a series of parts to each of which information may be attached.
+The "parts" of a CharacterData are the characters.  Thus, when addParts, deleteParts, moveParts and so on are called, the response is
+to add, delete and move characters.  To change the rows (taxa) of a matrix, the methods referring explicitly to taxa (addTaxa, etc.) 
+are to be used.
+<p>
+Attached to the CharacterData object are the typesets, weightsets, character sets and so on.  Each type of set is grouped into a SpecsSetVector of SpecsSets.
+These are handled by the superclass AssociableWithSpecs.  These different types of sets are not predefined within
+the CharacterData object, but are established by their managing modules and stored here.<p>
+  See general discussion of character storage classes under CharacterState
+ */
+
+public abstract class CharacterData extends FileElement implements MesquiteListener, StringLister, Identifiable, CompatibilityChecker  {
+	public static String DATATYPENAME="Character Data";
+	protected  int numTaxa; //number of taxa (rows): also determinable by taxa.getNumTaxa()
+	protected  int numChars; //number of characters (columns)
+
+	//	protected UndoInstructions undoInstructions;
+
+	public static boolean defaultInventUniqueIDs = false;
+	protected boolean inventUniqueIDs = defaultInventUniqueIDs;
+
+	protected boolean charNumChanging = false;
+
+
+	private Taxa taxa; //taxa to which this matrix belongs
+	private long[] taxaIDs; //the remembered id's of the taxa; to use to reconcile changed Taxa with last used here
+	private long[] doubleCheckTaxaIDs; //the remembered id's of the taxa; to use to reconcile changed Taxa with last used here
+
+	private long[] charIDs; // id's of the characters; used for error checking, especially 
+	private String[] uniqueIDs; // id's of the characters; intended to be globally unique
+	private String uniqueID; // id's of the matrix; intended to be globally unique
+	private static long totalCharsCreated = 0;
+
+	private String[] characterNames; //names of characters.  State names are needed only for categorical characters, and are to be found in CategoricalData
+	private Image[] characterIllustrations; 
+	private String[] characterIllustrationPath; 
+
+	//information attached to individual cells of the matrix
+	private String[][] footnotes; //strings attached to each cell
+	private Vector cellObjects; //Vector of arrays of objects (Object2DArray) that are attached to cells.  A courtesy to modules, so that they can attach and maintain info at the cells
+	private boolean[][] cellObjectsDisplay; //indicates whether there exist cell objects at a cell that need to be displayed in any way
+	private boolean[][] changedSinceSave; //records whether changed since last save.  
+	private int[] firstApplicable; //records the character number of the first non-applicable character.  
+	private int[] lastApplicable; //records the character number of the first non-applicable character.  
+
+	//the following four fields are for the experimental facility to record history of changes to cells
+	public static boolean defaultSaveChangeHistory = false;
+	public boolean saveChangeHistory = defaultSaveChangeHistory;//todo: make, set
+	public static boolean defaultRequireChangeAuthority = false;
+	public boolean requireChangeAuthority = defaultRequireChangeAuthority;//todo: make, set
+	ChangeAuthority currentChangeAuthority;
+
+	private boolean userVisible = true;
+	private boolean inhibitEditor = false;
+	private boolean locked = false;
+
+	public String problemReading = null;
+	private boolean checksumValid = false;
+	private long rememberedChecksum = 0;
+	private CRC32 crc32 = new CRC32();
+
+	public static final char defaultInapplicableChar = '-';
+	public static final char defaultMissingChar = '?';
+	public static final char defaultMatchChar = '.';
+	private char inapplicableChar = defaultInapplicableChar;
+	private char missingChar = defaultMissingChar;
+	private char matchChar = defaultMatchChar;
+
+
+	private boolean colorCellsByDefault = false;
+	private boolean useDiagonalCharacterNames = false;
+
+	protected CharMatrixManager matrixManager; //module which will supervise this (e.g., writing Characters block to file)
+
+	Tree basisTree; //the tree that was the basis of this matrix (i.e. on which it was simulated), if any
+	protected int nAdd = 0, nDel = 0, nMove = 0; //for debugging
+
+
+	//boolean locked = false; LOCKING SYSTEM not yet in place
+
+	boolean columnWidthAutoSize=true;
+	public boolean interleaved = false; //todo: used as a flag in reading.  Better to be part of general system of info storage for options and format issues
+	public int interleavedLength = 100;
+
+	public boolean suppressChecksum = false;
+	public boolean badImport = false;
+	public final static int OK = 1;
+	public final static int ERROR = 2;
+	public final static int OUTOFBOUNDS = 3;
+	public final static int EOL = 4;
+	public final static int COMMENT = 5;
+
+
+	/** Vector of other CharacterData linked to this one.  Linkage requires a 1-to-1 correspondence of characters, so that for each character in one matrix there's
+	a corresponding charcter in another.  This allows compound data, e.g. a ProteinData (when it exists!) could be linked to a ContinuousData holding landmark
+	positions of amino acid so that both the sequence and 3D conformation of protein are stored. */
+	protected Vector linkedDatas = null;
+
+	private long id;
+
+	public static long totalCreated = 0;
+	public static long totalDisposed = 0;
+
+
+	public CharacterData(CharMatrixManager matrixManager, int numTaxa, int numChars, Taxa taxa){
+		super(numChars); // for Associable
+		NameReference sN = makeAssociatedBits("selected"); //this won't make new Bits if not needed, just return reference
+		selected = getWhichAssociatedBits(sN);
+		this.matrixManager = matrixManager;
+		this.numChars=numChars;
+		this.numTaxa = numTaxa;
+		this.taxa = taxa;
+		linkedDatas = new Vector();
+		taxaIDs = taxa.getTaxaIDs();
+		doubleCheckTaxaIDs = taxa.getTaxaIDs();
+		taxa.addListenerHighPriority(this);  //TODO: this is dangerous for simulation matrices; if not disposed will be source of memory leak
+
+		/* the following should probably be done only on demand (e.g., so that simulation matrices don't need to remake this)*/
+		characterNames = new String[numChars];
+		cellObjects = new Vector();
+		cellObjectsDisplay = new boolean[numChars][numTaxa];
+		changedSinceSave = new boolean[numChars][numTaxa];
+		firstApplicable = new int[numTaxa];
+		lastApplicable = new int[numTaxa];
+		uniqueIDs = new String[numChars];
+		String base = MesquiteTrunk.getUniqueIDBase();
+		charIDs = new long[numChars];
+		for (int i=0; i<numChars; i++){
+			if (inventUniqueIDs)
+				uniqueIDs[i] = base + totalCharsCreated;
+			charIDs[i] = totalCharsCreated++;
+		}
+		if (inventUniqueIDs)
+			setUniqueID(MesquiteTrunk.getUniqueIDBase() + id);
+		totalCreated++;
+		id = totalCreated;
+		recordDefaultOrder();
+	}
+	//used only for cases like UndoInstructions, whose local copies shouldn't listen
+	public void disconnectListening(){
+		if (taxa != null)
+			taxa.removeListener(this);  
+
+	}
+	public void nullifyBooleanArrays () {
+		cellObjectsDisplay = null;
+		changedSinceSave = null;
+	}
+	/*.................................................................................................................*/
+	public boolean getCharNumChanging() {
+		return charNumChanging;
+	}
+	/*.................................................................................................................*/
+	public void setCharNumChanging(boolean charNumChanging) {
+		this.charNumChanging = charNumChanging;
+	}
+	/*.................................................................................................................*/
+	private boolean suppressSpecsetReading = false;  //for fuse taxa & matrices, so that on merge the subsequent specsets don't take over
+	public void setSuppressSpecssetReading(boolean s){
+		suppressSpecsetReading = s;
+	}
+	public boolean getSuppressSpecssetReading(){
+		return suppressSpecsetReading;
+	}
+
+	/*.................................................................................................................*/
+	public UndoInstructions getUndoInstructionsAllMatrixCells(int[] changesThatMightHappen){
+		if (allowFullUndo())
+			return new UndoInstructions (UndoInstructions.ALLDATACELLS, this, this, changesThatMightHappen);
+		else 
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** this is deprecated and will be removed as soon as all modules no longer call this **/  
+	public UndoInstructions getUndoInstructionsAllData(){   //WAYNECHECK:  needs to be removed from gataga and, ideally, pdap, and above method called instead.
+		return getUndoInstructionsAllMatrixCells(null);
+	}
+
+
+	/** true if the matrix is a valid one */
+	public boolean isValid(){
+		return numTaxa>0 && numChars>0;
+	}
+
+
+	protected boolean allowFullUndo() {
+		boolean taxaAcceptable = MesquiteTrunk.mesquiteTrunk.maxNumMatrixUndoTaxa<0 || numTaxa<MesquiteTrunk.mesquiteTrunk.maxNumMatrixUndoTaxa;
+		boolean charsAcceptable = MesquiteTrunk.mesquiteTrunk.maxNumMatrixUndoChars<0 || numChars<MesquiteTrunk.mesquiteTrunk.maxNumMatrixUndoChars;
+
+		return (taxaAcceptable || charsAcceptable);
+	}
+
+	/*.................................................................................................................*/
+	public boolean useDiagonalCharacterNames() {
+		return useDiagonalCharacterNames;
+	}
+	/*.................................................................................................................*/
+	public void setUseDiagonalCharacterNames(boolean useDiagonalNames) {
+		this.useDiagonalCharacterNames = useDiagonalNames;
+	}
+
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		if (StringUtil.blank(s))
+			return null;
+		String list = "";
+		String fc =""; //to receive the direct command
+		int numFound = 0;
+		for (int ic=0; ic< getNumChars(); ic++){
+			String name = getCharacterName(ic);
+			if (name != null && StringUtil.foundIgnoreCase(name, s)){
+				list += "<li>Character " + (ic+1) + ": <strong>" + StringUtil.protectForXML(name) + "</strong>. <a href=\"selectCharacter:" + ic+ " " + getID()  + "\">Touch character</a></li>";
+				numFound++;
+				fc = "selectCharacter:" + ic+ " " + getID() ;
+			}
+		}
+
+		if (commandResult != null && numFound == 1)
+			commandResult.setValue(fc);
+		if (StringUtil.blank(list))
+			return list;
+		return "<h2>Characters of matrix <strong>" + StringUtil.protectForXML(getName()) + "</strong></h2><ul>" + list + "</ul>";
+	}
+	public boolean uniquelyNamed(){
+		MesquiteProject p = null;
+		if (matrixManager != null)
+			p = matrixManager.getProject();
+		else if (getFile() != null)
+			p = getFile().getProject();
+		if (p == null)
+			return true;
+		if (getName() == null)
+			return false;
+		for (int i = 0; i< p.getNumberCharMatrices(); i++){
+			CharacterData d = p.getCharacterMatrix(i);
+			if (d != this && d.getName() != null && d.getName().equals(getName()))
+				return false;
+		}
+		return true;
+	}
+	public void setInventUniqueIDs(boolean invent){
+		inventUniqueIDs = invent;
+	}
+	public boolean getInventUniqueIDs(){
+		return inventUniqueIDs;
+	}
+	public void dispose(){
+		
+		checkThread(true);
+		if (taxa!=null)
+			taxa.removeListener(this);
+		if (getProject()!=null && getProject().getCentralModelListener() !=null)
+			getProject().getCentralModelListener().removeListener(this);
+		else if (getFile() !=null && getFile().getProject() != null && getFile().getProject().getCentralModelListener() != null)
+			getFile().getProject().getCentralModelListener().removeListener(this);
+		if (basisTree !=null) {
+			basisTree.dispose();
+		}
+		resignFromLinkageGroup();
+		linkedDatas=null;
+		taxa = null;
+		characterNames = null; 
+		characterIllustrations = null; 
+		characterIllustrationPath = null; 
+		CharacterData.totalDisposed++;
+		super.dispose();
+	} 
+
+	public long getID(){
+		return id;
+	}
+
+	public void deleteUniqueIDs(){
+		for (int i=0; i<numChars; i++){
+			uniqueIDs[i] = null;
+		}
+	}
+	public void stampUniqueIDs(boolean replaceExisting){
+		String base = MesquiteTrunk.getUniqueIDBase();
+		for (int i=0; i<numChars; i++){
+			if (replaceExisting || StringUtil.blank(uniqueIDs[i]))
+				uniqueIDs[i] = base + totalCharsCreated++;
+		}
+	}
+	public void stampUniqueID(int i, boolean replaceExisting){
+		String base = MesquiteTrunk.getUniqueIDBase();
+		if (replaceExisting || StringUtil.blank(uniqueIDs[i]))
+			uniqueIDs[i] = base + totalCharsCreated++;
+	}
+	//setting uniqueID for matrix
+	public void setUniqueID(String id){
+		uniqueID = id;
+	}
+	//getting uniqueID for matrix
+	public String getUniqueID(){
+		return uniqueID;
+	}
+	//setting unique id for character
+	public void setUniqueID(int ic, String id){
+		if (ic>=0 && ic<numChars)
+			uniqueIDs[ic] = id;
+	}
+
+	public String getUniqueID(int ic){
+		if (ic>=0 && ic<numChars)
+			return uniqueIDs[ic];
+		return null;
+	}
+
+	public void setCurrentGroup(CharactersGroup group, int icStart, int icEnd, MesquiteModule ownerModule) {
+		if (icEnd<icStart || group==null)
+			return;
+		CharacterPartition partition = (CharacterPartition) getCurrentSpecsSet(CharacterPartition.class);
+		if (partition==null){
+			partition= new CharacterPartition("Partition", getNumChars(), null, this);
+			partition.addToFile(getFile(), getProject(), ownerModule.findElementManager(CharacterPartition.class));
+			setCurrentSpecsSet(partition, CharacterPartition.class);
+		}
+		if (group != null) {
+			if (partition != null) {
+				boolean changed = false;
+				for (int ic=icStart; ic<getNumChars() && ic<=icEnd; ic++) {
+					partition.setProperty(group, ic);
+					changed = true;
+
+				}
+				if (changed)
+					notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+			}
+		}
+	}
+	public void setToNewGroup(String name, int icStart, int icEnd, MesquiteModule ownerModule) {
+		if (icEnd<icStart)
+			return;
+		CharacterPartition partition = (CharacterPartition) getCurrentSpecsSet(CharacterPartition.class);
+		if (partition==null){
+			partition= new CharacterPartition("Partition", getNumChars(), null, this);
+			partition.addToFile(getFile(), getProject(), ownerModule.findElementManager(CharacterPartition.class));
+			setCurrentSpecsSet(partition, CharacterPartition.class);
+		}
+		CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		CharactersGroup group = groups.findGroup(name);
+		int count = 0;
+		String groupName = name;
+		while (group!=null) {
+			count++;
+			groupName = name + count;
+			group = groups.findGroup(groupName);
+		}
+		group = new CharactersGroup();
+		group.setName(groupName);
+		group.addToFile(getFile(), getProject(), ownerModule.findElementManager(CharactersGroup.class));
+		if (groups.indexOf(group)<0) 
+			groups.addElement(group, false);
+
+		if (group != null) {
+			if (partition != null) {
+				boolean changed = false;
+				for (int ic=icStart; ic<getNumChars() && ic<=icEnd; ic++) {
+					partition.setProperty(group, ic);
+					changed = true;
+
+				}
+				if (changed)
+					notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+			}
+		}
+	}
+	public CharactersGroup createNewGroup(CharactersGroupVector groups, String groupName, MesquiteModule ownerModule){
+		CharactersGroup group = new CharactersGroup();
+		group.setName(groupName);
+		group.addToFile(getFile(), getProject(), ownerModule.findElementManager(CharactersGroup.class));
+		if (groups.indexOf(group)<0) 
+			groups.addElement(group, false);	
+		return group;
+	}
+
+	public void adjustGroupLabels(String prefix, int icStart, int icEnd, boolean createNewGroups, boolean prefixGroupNamesIfAlreadyAssigned, MesquiteModule ownerModule) {
+		if (icEnd<icStart)
+			return;
+		CharacterPartition partition = (CharacterPartition) getCurrentSpecsSet(CharacterPartition.class);
+		if (partition==null){
+			partition= new CharacterPartition("Partition", getNumChars(), null, this);
+			partition.addToFile(getFile(), getProject(), ownerModule.findElementManager(CharacterPartition.class));
+			setCurrentSpecsSet(partition, CharacterPartition.class);
+		}
+		CharactersGroup group;
+		CharactersGroup newGroup=null;
+		CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		for (int i=0; i<groups.size(); i++){
+			group = (CharactersGroup)groups.elementAt(i);
+			group.setRecentlyModified(false);
+		}
+
+
+
+
+		if (partition != null) {
+			boolean changed = false;
+			for (int ic=icStart; ic<getNumChars() && ic<=icEnd; ic++) {
+				CharactersGroup currentGroup = (CharactersGroup)partition.getProperty(ic);
+				if (currentGroup==null) { // this character doesn't have a group assigned to it; will assign a new group based upon "prefix"
+					if (newGroup==null) { //make a new group
+						group = groups.findGroup(prefix);  //see if one with prefix already exists
+						String groupName = prefix;
+						if (group==null) {
+							newGroup = createNewGroup(groups,groupName,ownerModule);
+							newGroup.setRecentlyModified(true);
+							currentGroup=newGroup;
+						} else {
+							currentGroup=group;
+							currentGroup.setRecentlyModified(true);  // because the character is not assigned to any group, this character will get the group that uses the prefix name, which we don't want to modify, so we set it as already modified.
+						}
+					} else 
+						currentGroup=newGroup;
+				}
+				if (currentGroup!=null && !currentGroup.isRecentlyModified() && prefixGroupNamesIfAlreadyAssigned) {  // rename it with prefix
+					String groupName = prefix+"."+currentGroup.getName();
+					if (createNewGroups) {  // we need to create a new group with the prefix, rather than renaming the one that exists
+						group = groups.findGroup(groupName);  //see if one with prefix already exists
+						if (group==null) {  // there is no group of this name; let's create it
+							currentGroup = createNewGroup(groups,groupName,ownerModule);
+							//							newGroup2.setRecentlyModified(true);
+							//							currentGroup=newGroup2;
+						} else {
+							currentGroup=group;
+							//							currentGroup.setRecentlyModified(true);  // because the character is not assigned to any group, this character will get the group that uses the prefix name, which we don't want to modify, so we set it as already modified.
+						}
+					} else
+						currentGroup.setName(groupName);
+					currentGroup.setRecentlyModified(true);
+				}
+				partition.setProperty(currentGroup, ic);
+				changed = true;
+
+			}
+			if (changed)
+				notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+
+		}
+		for (int i=0; i<groups.size(); i++){
+			group = (CharactersGroup)groups.elementAt(i);
+			group.setRecentlyModified(false);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public  boolean hasCharacterGroups(){
+		CharactersGroup[] parts =null;
+		CharacterPartition characterPartition = (CharacterPartition)getCurrentSpecsSet(CharacterPartition.class);
+		if (characterPartition!=null) {
+			parts = characterPartition.getGroups();
+		}
+		if (parts!=null){
+			return true;
+		}
+		return false;
+	}
+
+	public int findByUniqueID(String target){
+		if (target == null)
+			return -1;
+		String base = MesquiteTrunk.getUniqueIDBase();
+		for (int i=0; i<numChars; i++){
+			String id = getUniqueID(i);
+			if (id != null && id.equals(target))
+				return i;
+		}
+		return -1;
+	}
+	public NexusBlock addToFile(MesquiteFile f, MesquiteProject proj, ElementManager manager){
+		if (proj!=null && proj.getCentralModelListener() !=null) {
+			proj.getCentralModelListener().addListener(this);
+		}
+		else if (f !=null && f.getProject() != null && f.getProject().getCentralModelListener() != null){
+			f.getProject().getCentralModelListener().addListener(this);
+		}
+		return super.addToFile(f, proj, manager);
+	}
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+
+	/** Takes a listable, that in theory should be of length numChars, and returns a copy of it from which all 
+	 * entries corresponding to excluded characters are removed from the list */
+	public Listable[] removeExcludedFromListable(Listable[] listable) {
+		if (listable==null) return null;
+		int numIncluded = getNumCharsIncluded();
+		Listable[] newListable = new Listable[numIncluded];
+		int count = 0;
+		for (int ic=0; count<newListable.length && ic<listable.length; ic++) {
+			if (isCurrentlyIncluded(ic)){
+				newListable[count] = listable[ic];
+				count++;
+			}
+		}
+		return newListable;
+	}
+	/** Takes a listable, that in theory should be of length numChars, and returns a copy of it from which all 
+	 * entries corresponding to excluded characters are removed from the list */
+	public boolean[] getBooleanArrayOfIncluded() {
+		boolean[] newArray = new boolean[numChars]; 
+		for (int ic=0; ic<numChars; ic++) {
+			newArray[ic] = isCurrentlyIncluded(ic);
+		}
+		return newArray;
+	}
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj ==null)
+			return true;
+		else if (obj instanceof Taxa){
+			if (taxa != obj && report != null)
+				report.setValue("matrix applies to a different taxa block");
+			return taxa == obj;
+		}
+		else if (obj instanceof Class){
+			Class c = (Class)obj;
+			boolean compatibleType =  c.isAssignableFrom(getClass()) || c.isAssignableFrom(getStateClass());
+			if (!compatibleType && report != null)
+				report.setValue("matrix is not of the requested data type");
+			return compatibleType;
+		}
+		return true;
+	}
+	/** sets name of data matrix */
+	public void setName(String name) {
+		this.name= name;
+		notifyListeners(this, new Notification(NAMES_CHANGED));
+		if (getHShow()) {
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+		}
+	}
+	/** returns title of data if it has a title, or "Character Matrix" if has no title*/
+	public String getName() {
+		if (name==null)
+			return "Character Matrix";
+		else
+			return name;
+	}
+	/** returns true if this has name equivalent to default name*/
+	public boolean hasDefaultName() {
+		return  (name==null) || name.equals("Character Matrix");
+	}
+	/** returns true if data has a title*/
+	public boolean hasTitle() {
+		return  (name!=null);
+	}
+	public String getTypeName(){
+		return "Character matrix";
+	}
+
+	/**Returns the type of data stored. */
+	public abstract String getDataTypeName();
+
+	/** clones the data set.  Does not clone the associated specs sets etc.*/
+	public abstract CharacterData cloneData(); //SHOULD HERE PASS boolean to say whether to DEAL WITH CHARACTER SPEC SETS, character names, etc.
+
+	public void copyCurrentSpecsSetsTo(CharacterData targetData){
+		Vector specsVectors = getSpecSetsVectorVector();
+		if (specsVectors!=null){ 
+			for (int i=0; i<specsVectors.size(); i++) { 
+				SpecsSetVector origSV = (SpecsSetVector)specsVectors.elementAt(i);
+				SpecsSet origSS = origSV.getCurrentSpecsSet();
+				if (origSS!=null) {
+					Class specsClass = origSV.getType();
+					SpecsSet cloneSS = targetData.getCurrentSpecsSet(specsClass);
+					if (cloneSS == null){
+						cloneSS = origSS.makeSpecsSet(targetData, getNumberOfParts());
+						if (cloneSS != null){
+							if (targetData instanceof FileElement){
+								cloneSS.addToFile(((FileElement)targetData).getFile(), ((FileElement)targetData).getProject(), ((FileElement)targetData).getProject().getCoordinatorModule().findElementManager(specsClass)); 
+							}
+							targetData.setCurrentSpecsSet(cloneSS, specsClass);
+						}
+					}
+					if (cloneSS != null){
+						for (int ic = 0; ic< getNumChars() && ic< targetData.getNumChars(); ic++){
+							cloneSS.equalizeSpecs(origSS, ic, ic);
+						}
+					}
+				}
+
+			}
+		}
+	}
+	//TODO: also need setToClone(data) method to set specsets and names etc. including super.setToClone()
+
+	/**clones a portion of CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneDataBlock(int icStart, int icEnd, int itStart, int itEnd){
+		return cloneData();  //should be overridden to restrict to certain characters and taxa!
+	}
+
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public abstract void copyData(CharacterData sourceData); //TODO: ? SHOULD HERE PASS boolean to say whether to DEAL WITH CHARACTER SPEC SETS, character names, etc.
+
+	/** copy data from the datablock .  Does not copy the associated specs sets etc.*/
+	public void copyDataBlock(CharacterData sourceData, int icStart, int icEnd, int itStart, int itEnd){ //TODO: ? SHOULD HERE PASS boolean to say whether to DEAL WITH CHARACTER SPEC SETS, character names, etc.
+		copyData(sourceData);
+	}
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public void copyData(CharacterData sourceData, boolean allowDifferentSizes){ //TODO: ? SHOULD HERE PASS boolean to say whether to DEAL WITH CHARACTER SPEC SETS, character names, etc.
+		copyData(sourceData);
+	}
+	/** returns the module in charge of managing the data matrix, including reading and writing the corresponding block in a NEXUS file*/
+	public CharMatrixManager getMatrixManager() {
+		return matrixManager;
+	}
+	/** sets the module in charge of managing the data matrix, including reading and writing the corresponding block in a NEXUS file*/
+	public void setMatrixManager(CharMatrixManager matrixManager) {
+		this.matrixManager= matrixManager;
+	}
+	public int getMaxNumChars(){
+		return MesquiteInteger.infinite;
+	}
+	public boolean canMoveChars(){
+		return true;
+	}
+	/** returns number of taxa in data matrix*/
+	public int getNumTaxa(boolean notifyIfError) {
+		return numTaxa;
+	}
+	/** returns number of taxa in data matrix*/
+	public int getNumTaxa() {
+		return getNumTaxa(true);
+	}
+	/** returns number of taxa in data matrix*/
+	public int getNumTaxaWithAnyApplicable() {
+		int count=0;
+		for (int it=0; it<getNumTaxa(); it++) 
+			if (anyApplicableAfter(0,it))
+				count++;
+		return count;
+	}
+	/** returns number of characters in data matrix*/
+	public int getNumChars() {
+		return getNumChars(true);
+	}
+	/** returns number of characters in data matrix*/
+	public int getNumChars(boolean notifyIfError) {
+		return numChars;
+	}
+
+	/** returns the Taxa object to which it applies*/
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	/** returns whether or not one can add characters manually to this matrix; some data classes, e.g., geographic, don't allow it.*/
+	public boolean canAddCharacters() {
+		return true;
+	}
+
+	/*-----------------------------------------------------------*/
+	/** A equivalent of addParts but with notification added */
+	public final boolean addCharacters(int starting, int num, boolean notify){
+		boolean added = addParts(starting, num);
+		if (added && notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {starting, num}));
+		return added;
+	}
+
+	public void calculateFirstLastApplicable(int it){
+		/*   enable once the system of calling this is more refined
+		if (firstApplicable!=null){
+			int first = -1;
+			for (int ic=0; ic<numChars; ic++) {
+				if (!isInapplicable(ic, it)) {
+					first=ic;
+					break;
+				}
+			}
+			if (it<firstApplicable.length)
+				firstApplicable[it] = first;
+
+		}
+		if (lastApplicable!=null){
+			int last = -1;
+			for (int ic=numChars-1; ic>=0; ic--) {
+				if (!isInapplicable(ic, it)) {
+					last=ic;
+					break;
+				}
+			}
+			if (it<lastApplicable.length)
+				lastApplicable[it] = last;
+		}
+		 */
+
+	}
+	public void calculateFirstLastApplicable(){
+		for (int it = 0; it<numTaxa; it++)
+			calculateFirstLastApplicable(it);
+	}
+
+	/*-----------------------------------------------------------*/
+	/**Adds num characters after position "starting".  If "starting" = -1, then inserts at start.  If "starting" >
+	number of characters, adds to end.  Any linked CharacterDatas are
+	to be adjusted separately.  Returns true iff successful.*/
+	public boolean addParts(int starting, int num){
+		if (getMaxNumChars()!=MesquiteInteger.infinite && numChars+num>getMaxNumChars())
+			return false;
+		if (num<=0)
+			return false;
+		if (!checkThread(false))
+			return false;
+		nAdd++;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+
+		//adjusting unique id's 
+		if (uniqueIDs != null) {
+			uniqueIDs = StringArray.addParts(uniqueIDs, starting, num);
+		}
+		String base = MesquiteTrunk.getUniqueIDBase();
+
+		//adjusting character id's 
+		long[] newCharIDs = new long[numChars + num];
+		for (int i=0; i<=starting; i++)
+			newCharIDs[i] = charIDs[i];
+		for (int i=0; i<num; i++) {
+			if (uniqueIDs != null && inventUniqueIDs)
+				uniqueIDs[starting + i + 1] = base + totalCharsCreated; 
+			newCharIDs[starting + i + 1] = totalCharsCreated++;
+		}
+		for (int i=0; i<numChars-starting-1; i++) 
+			newCharIDs[i + starting+num+1] = charIDs[starting + i+1];
+		charIDs = newCharIDs;
+
+
+
+		if (characterNames!=null){
+			characterNames = StringArray.addParts(characterNames, starting, num);
+		}
+
+		if (footnotes!=null){
+			String[][] newFootnotes = new String[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<=starting; i++)
+					newFootnotes[i][j] = footnotes[i][j];
+				for (int i=0; i<num; i++)
+					newFootnotes[starting + i + 1][j] = null;
+				for (int i=0; i<numChars-starting-1; i++) 
+					newFootnotes[i + starting+num+1][j] = footnotes[starting + i+1][j];
+			}
+			footnotes = newFootnotes;
+		}
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] oldObjects = objArray.getMatrix();
+				Object[][] newObjects = new Object[newNumChars][numTaxa];
+				for (int j = 0; j<numTaxa; j++){
+					for (int i=0; i<=starting; i++)
+						newObjects[i][j] = oldObjects[i][j];
+					for (int i=0; i<num; i++)
+						newObjects[starting + i + 1][j] = null;
+					for (int i=0; i<numChars-starting-1; i++) 
+						newObjects[i +starting+num+1][j] = oldObjects[starting + i+1][j];
+				}
+				objArray.setMatrix(newObjects);
+			}
+		}
+		if (cellObjectsDisplay!=null){
+			boolean[][] newCOD = new boolean[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<=starting; i++)
+					newCOD[i][j] = cellObjectsDisplay[i][j];
+				for (int i=0; i<num; i++)
+					newCOD[starting + i + 1][j] = false;
+				for (int i=0; i<numChars-starting-1; i++) 
+					newCOD[i + starting+num+1][j] = cellObjectsDisplay[starting + i+1][j];
+			}
+			cellObjectsDisplay = newCOD;
+		}
+		if (changedSinceSave!=null){
+			boolean[][] newCOD = new boolean[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<=starting; i++)
+					newCOD[i][j] = changedSinceSave[i][j];
+				for (int i=0; i<num; i++)
+					newCOD[starting + i + 1][j] = false;
+				for (int i=0; i<numChars-starting-1; i++) 
+					newCOD[i + starting+num+1][j] = changedSinceSave[starting + i+1][j];
+			}
+			changedSinceSave = newCOD;
+		}
+
+		if (characterIllustrations!=null){
+			Image[] newCharacterIllustrations = new Image[newNumChars];
+			for (int i=0; i<=starting; i++) {
+				newCharacterIllustrations[i] = characterIllustrations[i];
+			}
+			for (int i=0; i<num; i++) {
+				newCharacterIllustrations[starting + i + 1] = null;
+			}
+			for (int i=0; i<numChars-starting-1; i++) {
+				newCharacterIllustrations[i +starting+num+1] = characterIllustrations[starting + i+1];
+			}
+			characterIllustrations = newCharacterIllustrations;
+		}
+		numChars = newNumChars;
+		calculateFirstLastApplicable();
+		super.addParts(starting, num); //for specssets
+		uncheckThread();
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_ADDED, starting, num, 0);  
+		return true;
+	}
+	/*-----------------------------------------------------------*/
+	/** Adds characters in linked data files. */
+	public void addInLinked(int starting, int num, boolean notify){
+		if (linkedDatas != null && linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.addParts(starting, num);
+				if (notify)
+					d.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {starting, num}));
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** An equivalent to deleteParts but with notification added. Final because overriding should be done of the Parts method instead*/
+	public final boolean deleteCharacters(int starting, int num, boolean notify){
+		boolean deleted = deleteParts(starting, num);
+		if (deleted && notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED, new int[] {starting, num}));
+		return deleted;
+	}
+	/*-----------------------------------------------------------*/
+	/** deletes num characters from (and including) position "starting"; returns true iff successful.  Should be overridden by particular subclasses, but this called via super so it can clean up.*/
+	public boolean deleteParts(int starting, int num){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>numChars)
+			return false;
+		if (!checkThread(false))
+			return false;
+		nDel++;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars = numChars - num;
+
+		//adjusting character id's 
+		long[] newCharIDs = new long[newNumChars];
+		for (int i=0; i<starting; i++) {
+			newCharIDs[i] = charIDs[i];
+		}
+		for (int i=starting+num; i<charIDs.length; i++) {
+			newCharIDs[i -num]= charIDs[i];
+		}
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_DELETED, starting, num, 0);  
+
+		charIDs = newCharIDs;
+
+		if (uniqueIDs != null)
+			uniqueIDs = StringArray.deleteParts(uniqueIDs, starting, num);
+
+		if (characterNames!=null){
+			characterNames = StringArray.deleteParts(characterNames, starting, num);
+		}
+		if (footnotes!=null){
+			String[][] newFootnotes = new String[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<starting; i++) {
+					newFootnotes[i][j] = footnotes[i][j];
+				}
+				for (int i=starting+num; i<footnotes.length; i++) {
+					newFootnotes[i -num][j] = footnotes[i][j];
+				}
+			}
+			footnotes = newFootnotes;
+		}
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] oldObjects = objArray.getMatrix();
+				Object[][] newObjects = new Object[newNumChars][numTaxa];
+				for (int j = 0; j<numTaxa; j++){
+					for (int i=0; i<starting; i++) {
+						newObjects[i][j] = oldObjects[i][j];
+					}
+					for (int i=starting+num; i<oldObjects.length; i++) { //bug had been here in 1.03
+						newObjects[i -num][j] = oldObjects[i][j];
+					}
+				}
+				objArray.setMatrix(newObjects);
+			}
+		}
+		if (cellObjectsDisplay!=null){
+			boolean[][] newCOD = new boolean[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<starting; i++) {
+					newCOD[i][j] = cellObjectsDisplay[i][j];
+				}
+				for (int i=starting+num; i<cellObjectsDisplay.length; i++) {
+					newCOD[i -num][j] = cellObjectsDisplay[i][j];
+				}
+			}
+			cellObjectsDisplay = newCOD;
+		}
+		if (changedSinceSave!=null){
+			boolean[][] newCOD = new boolean[newNumChars][numTaxa];
+			for (int j = 0; j<numTaxa; j++){
+				for (int i=0; i<starting; i++) {
+					newCOD[i][j] = changedSinceSave[i][j];
+				}
+				for (int i=starting+num; i<changedSinceSave.length; i++) {
+					newCOD[i -num][j] = changedSinceSave[i][j];
+				}
+			}
+			changedSinceSave = newCOD;
+		}
+
+		if (characterIllustrations!=null){
+			Image[] newCharacterIllustrations = new Image[newNumChars];
+			for (int i=0; i<starting; i++) {
+				newCharacterIllustrations[i] = characterIllustrations[i];
+			}
+			for (int i=starting+num; i<characterIllustrations.length; i++) {
+				newCharacterIllustrations[i-num ] = characterIllustrations[i];
+			}
+			characterIllustrations = newCharacterIllustrations;
+		}
+		numChars = newNumChars;
+		calculateFirstLastApplicable();
+		super.deleteParts(starting, num); //for specs sets
+		uncheckThread();
+		return true;
+	}
+	/*-----------------------------------------------------------*/
+	/** Deletes characters in linked data matrices. */
+	public final void deleteInLinked(int starting, int num, boolean notify){
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.deleteParts(starting, num);
+				if (notify)
+					d.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED, new int[] {starting, num}));
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** An equivalent to moveParts but with notification added.*/
+	public final boolean moveCharacters(int starting, int num, int justAfter, boolean notify){
+		boolean moved = moveParts(starting, num, justAfter);
+		if (moved && notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, new int[] {starting, num, justAfter}));
+		return moved;
+	}
+
+	public String[][] getFootnotes(){	
+		return footnotes;
+	}
+	/*-----------------------------------------------------------*/
+	/**Moves num characters from position "first" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (!canMoveChars()) 
+			return false;
+		if (!checkThread(false))
+			return false;
+		StringArray.moveParts(characterNames, starting, num, justAfter); 
+		StringArray.moveColumns(footnotes, starting, num, justAfter); 
+		StringArray.moveParts(characterIllustrationPath, starting, num, justAfter); 
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] oldObjects = objArray.getMatrix();
+				Object2DArray.moveColumns(oldObjects, starting, num, justAfter);
+			}
+		}
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_MOVED, starting, num, justAfter);  
+
+		Bits.moveColumns(cellObjectsDisplay, starting, num, justAfter);
+		Bits.moveColumns(changedSinceSave, starting, num, justAfter);
+		calculateFirstLastApplicable();
+		MesquiteImage.moveParts( characterIllustrations, starting, num, justAfter); 
+		charIDs = LongArray.getMoveParts(charIDs, starting, num, justAfter);
+		StringArray.moveParts(uniqueIDs, starting, num, justAfter);
+		nMove++;
+		boolean moved =  super.moveParts(starting, num, justAfter);
+		uncheckThread();
+		return moved;
+	}
+	/*-----------------------------------------------------------*/
+	/** Move characters in linked data matrices. */
+	public final void moveInLinked(int starting, int num, int justAfter, boolean notify){
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.moveParts(starting, num, justAfter);
+				if (notify)
+					d.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, new int[] {starting, num, justAfter}));
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/**Swaps metadata for cells of characters first and second.*/
+	public boolean swapCellMetadata(int first, int second){
+		if (!checkThread(false))
+			return false;
+		StringArray.swapColumns(footnotes,  first, second); 
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] oldObjects = objArray.getMatrix();
+				Object2DArray.swapColumns(oldObjects,  first, second);
+			}
+		}
+		Bits.swapColumns(cellObjectsDisplay,  first, second);
+		Bits.swapColumns(changedSinceSave,  first, second);
+
+		uncheckThread();
+		return true;
+	}
+	/*-----------------------------------------------------------*/
+	/**Swaps metadata for cells of characters first and second in taxon it.*/
+	public boolean swapCellMetadata(int first, int second, int it){
+		if (!checkThread(false))
+			return false;
+		StringArray.swapCell(footnotes,  first, second, it); 
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] oldObjects = objArray.getMatrix();
+				Object2DArray.swapCell(oldObjects,  first, second, it);
+			}
+		}
+		Bits.swapCell(cellObjectsDisplay,  first, second, it);
+		Bits.swapCell(changedSinceSave,  first, second, it);
+
+		uncheckThread();
+		return true;
+	}
+	/*-----------------------------------------------------------*/
+	/**Swaps metadata for characters first and second.*/
+	public boolean swapCharacterMetadata(int first, int second){
+		if (!checkThread(false))
+			return false;
+
+		StringArray.swapParts(characterIllustrationPath,  first, second); 
+		StringArray.swapParts(characterNames, first, second); 
+		StringArray.swapParts(uniqueIDs, first, second);
+		//adjusting character id's 
+		if (first<charIDs.length && second<charIDs.length){
+			long oldFirst  = charIDs[first];
+			charIDs[first] = charIDs[second];
+			charIDs[second] = oldFirst;
+		}
+		notifyOfChangeLowLevel(MesquiteListener.PARTS_SWAPPED, first, second, 0);  
+
+		calculateFirstLastApplicable();
+		MesquiteImage.swapParts( characterIllustrations,  first, second); 
+		nMove++;
+		boolean swapped =  super.swapParts( first, second);
+		uncheckThread();
+		return swapped;
+	}
+	/*-----------------------------------------------------------*/
+	/**Swaps characters first and second.*/
+	public boolean swapParts(int first, int second){
+		boolean meta = swapCellMetadata(first, second);
+		if (!meta)
+			return false;
+		boolean swapped =  swapCharacterMetadata( first, second);  // this includes call to super.swapParts!!!!!
+		return swapped;
+	}
+
+	/*-----------------------------------------------------------*/
+	/** Swap characters in linked data matrices. */
+	public final void swapInLinked(int first, int second, boolean notify){
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.swapParts(first, second);
+				if (notify)
+					d.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public int checkCellMoveDistanceAvailable(int distance, int startBlock, int endBlock, Bits whichTaxa, MesquiteBoolean isTerminalBlock, MesquiteInteger boundaryOfAvailableSpace, boolean canExpand){
+		if (!checkThread(false))
+			return 0;
+		boolean terminalBlock=false;
+		int firstTaxon = whichTaxa.firstBitOn();
+		int lastTaxon = whichTaxa.lastBitOn();
+		int gapsAvailable = 0;
+		int g=0;
+		if (distance>0){ //moving right
+			//first check to see whether gaps are to the right 
+			g = endBlock+1;  // start one past end of block  
+			if (!canExpand && g>=numChars) {
+				distance = 0;
+				g=numChars-1;
+				terminalBlock=true;
+			}
+			else {
+
+				while (g<numChars && inapplicableBlock(g,g,whichTaxa, firstTaxon, lastTaxon))  //counting gaps beyond the current one
+					g++;
+				if (g>=numChars) //we reached the end and all gaps
+					terminalBlock = true;
+				g--;  //decrement by one as we must be one over what we should be.  g now stores the number of the last available character
+				gapsAvailable = g-endBlock;
+				if (!(terminalBlock && canExpand) && distance>gapsAvailable) {
+					distance = gapsAvailable;
+				}
+			}
+		}
+		else if (distance<0){ //moving left
+			//first check to see whether gaps can eat at end
+			g = startBlock-1;
+			if (!canExpand && g<0) {
+				distance = 0;
+				g=0;
+				terminalBlock=true;
+			}
+			else {
+				while (g>=0 && inapplicableBlock(g,g,whichTaxa, firstTaxon, lastTaxon))  //counting terminal gaps
+					g--;
+				if (g<0)
+					terminalBlock=true;
+				g++;
+				gapsAvailable = startBlock-g;
+				if (!(terminalBlock && canExpand) && distance<-gapsAvailable) {
+					distance = -gapsAvailable;
+				}
+			}
+		}
+		isTerminalBlock.setValue(terminalBlock);
+		boundaryOfAvailableSpace.setValue(g);
+		uncheckThread();
+		return distance;
+	}
+	/*.................................................................................................................*/
+	public int checkCellMoveDistanceAvailable(int distance, int startBlock, int endBlock, int itStart, int itEnd, MesquiteBoolean isTerminalBlock, MesquiteInteger boundaryOfAvailableSpace, boolean canExpand){
+		Bits whichTaxa = new Bits(numTaxa);
+		for (int it=itStart; it<=itEnd; it++)
+			whichTaxa.setBit(it);
+		return checkCellMoveDistanceAvailable( distance,  startBlock,  endBlock,  whichTaxa,  isTerminalBlock,  boundaryOfAvailableSpace,  canExpand);
+	}
+	/*.................................................................................................................*/
+	protected CharacterState moveOne(int i, int distance, int it, CharacterState cs,  MesquiteBoolean dataChanged){
+		cs = getCharacterState(cs, i, it);
+		if (cs==null)
+			return null;
+		if (!checkThread(false))
+			return null;
+		if (i+distance >= getNumChars())
+			dataIntegrityAlert("moveOne request to move cells beyond limits of matrix!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @ i " + i + " distance " + distance + " getNumChars() " + getNumChars() + " it " + it  + " this " + this);
+		setState(i+distance, it, cs);
+		cs.setToInapplicable();
+		setState(i, it, cs);
+		if (dataChanged!=null)
+			dataChanged.setValue(true);
+
+		if (i+distance>=0 && i+distance< getNumChars()){
+			//footnotes
+			if (footnotes!=null){
+
+				footnotes[i+distance][it] = footnotes[i][it];
+				footnotes[i][it]=null;
+			}
+
+			//cell objects
+			if (cellObjects !=null)
+				for (int k =0; k<cellObjects.size(); k++){
+					Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+					Object[][] objects = objArray.getMatrix();
+					objects[i+distance][it] = objects[i][it];
+					objects[i][it]=null;
+				}
+		}
+		uncheckThread();
+		return cs;
+	}
+	/*.................................................................................................................*/
+	/** moves the cells from character startBlock to character endBlock a distance "distance" for taxon it.  
+	If canExpand is set, then the procedure will add characters to the front or end of the matrix. 
+	If canOverwrite is set, then the procedure can overwrite data (otherwise it can only overwrite inapplicable cells).
+
+	Returns how many characters are added to the front (if value is -ve) or end (if value is +ve) of the matrix.
+	 */
+	public int moveCells(int startBlock, int endBlock, int distance, Bits whichTaxa,  boolean canExpand, boolean canOverwrite, boolean includingLinked, boolean notify, MesquiteBoolean dataChanged,MesquiteInteger charAdded, MesquiteInteger distanceMoved){  //startBlock and endBlock are 0-based
+		if (!checkThread(false))
+			return 0;
+		CharacterState cs = null;
+		MesquiteBoolean isTerminalBlock = new MesquiteBoolean(false);
+		MesquiteInteger boundaryOfAvailableSpace = new MesquiteInteger(0);
+		int gapsAvailable = 0;
+		int openUp = 0;
+		int added = 0;
+		int origStartBlock = startBlock;
+		int origEndBlock = endBlock;
+		if (distance>0){ //moving right
+			int gResultingEndBlock = 0;
+			if (!canOverwrite){ //adjust distance to avoid overwriting
+				distance = checkCellMoveDistanceAvailable(distance, startBlock, endBlock, whichTaxa, isTerminalBlock, boundaryOfAvailableSpace, canExpand);	   	
+				gResultingEndBlock = boundaryOfAvailableSpace.getValue();		
+			}
+			else
+				gResultingEndBlock = endBlock + distance;
+			if (distanceMoved!=null)
+				distanceMoved.setValue(distance);
+			if (isTerminalBlock.getValue() && canExpand) {
+				openUp = distance-(getNumChars()-endBlock)+1;
+				if (openUp>0) {  //makeNewCharacters
+					addCharacters(getNumChars(), openUp, false);
+					if (charAdded!=null)
+						charAdded.setValue(openUp);
+					if (includingLinked)
+						addInLinked(getNumChars(), openUp, false);
+					added = openUp;
+					gResultingEndBlock= endBlock + distance; //NOTE:   this should be end of block, NOT numchars
+					if (dataChanged!=null)
+						dataChanged.setValue(true);
+				}
+			}
+			//now move from end
+			for (int it=0; it<getNumTaxa(); it++) {
+				if (whichTaxa.isBitOn(it))
+					for (int i = gResultingEndBlock-distance; i>=startBlock; i--){
+						cs = moveOne(i, distance, it, cs, dataChanged);
+					}
+			}
+		} 
+		else if (distance<0){ //moving left
+			int g = 0;
+			if (!canOverwrite) { //adjust distance to avoid overwriting
+				distance = checkCellMoveDistanceAvailable(distance, startBlock, endBlock, whichTaxa, isTerminalBlock, boundaryOfAvailableSpace,canExpand);	   	
+				g = boundaryOfAvailableSpace.getValue();		
+			}
+			if (distanceMoved!=null)
+				distanceMoved.setValue(distance);
+
+			if (isTerminalBlock.getValue() && canExpand) {
+				openUp = -distance-startBlock;
+
+				//if not then make new characters
+				if (openUp>0) {
+					addCharacters(-1, openUp, false);
+					if (charAdded!=null)
+						charAdded.setValue(-openUp);
+					if (includingLinked)
+						addInLinked(-1, openUp, false);
+					added = -openUp;
+					if (dataChanged!=null)
+						dataChanged.setValue(true);
+					startBlock += openUp;
+					endBlock += openUp;
+					origStartBlock += openUp;
+					origEndBlock += openUp;
+				}
+			}
+
+			//now move from front end
+			for (int it=0; it<getNumTaxa(); it++)
+				if (whichTaxa.isBitOn(it))
+					for (int i = startBlock; i<=endBlock; i++){
+						cs = moveOne(i, distance, it, cs, dataChanged);
+					}
+
+		}
+		if (includingLinked){
+			if (linkedDatas.size()>0){
+				for (int i=0; i<linkedDatas.size(); i++){
+					CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+					d.moveCells(origStartBlock, origEndBlock, distance, whichTaxa,  false, true, false, notify, null,null, null);
+				}
+			}
+		}
+		uncheckThread();
+		return added;
+	}
+	/*.................................................................................................................*/
+	/** moves the cells from character startBlock to character endBlock a distance "distance" for taxon it.  
+	If canExpand is set, then the procedure will add characters to the front or end of the matrix. 
+	If canOverwrite is set, then the procedure can overwrite data (otherwise it can only overwrite inapplicable cells).
+
+	Returns how many characters are added to the front (if value is -ve) or end (if value is +ve) of the matrix.
+	 */
+	public int moveCells(int startBlock, int endBlock, int distance, int itStart, int itEnd,  boolean canExpand, boolean canOverwrite, boolean includingLinked, boolean notify, MesquiteBoolean dataChanged, MesquiteInteger charAdded, MesquiteInteger distanceMoved){  //startBlock and endBlock are 0-based
+		Bits whichTaxa = new Bits(getNumTaxa());
+		for (int it=itStart; it<=itEnd; it++)
+			whichTaxa.setBit(it);
+		return moveCells( startBlock,  endBlock,  distance, whichTaxa,   canExpand,  canOverwrite,  includingLinked,  notify,  dataChanged, charAdded, distanceMoved);
+	}
+	/*.................................................................................................................*/
+	public int shiftAllCells(int distance, int it,  boolean canExpand,  boolean includingLinked, boolean notify, MesquiteBoolean dataChanged, MesquiteInteger charAdded, MesquiteInteger distanceMoved){  //startBlock and endBlock are 0-based
+		int first = firstApplicable(it);
+		int last = lastApplicable(it);
+		if (first<0)
+			return 0;
+		else {
+			int dist =  moveCells(first,last, distance, it, it, canExpand, false, includingLinked,  notify, dataChanged, charAdded, distanceMoved);
+			return dist;
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** Has linked data matrices send out notifications of change. */
+	public final void notifyInLinked(Notification notification){
+		if (linkedDatas == null)
+			return;
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.notifyListeners(this, notification);
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** Has linked data matrices record current order. */
+	public final void copyCurrentToPreviousOrderInLinked(){
+		if (linkedDatas == null)
+			return;
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.copyCurrentToPreviousOrder();
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** Has linked data matrices record current order. */
+	public final void recordCurrentOrderInLinked(){
+		if (linkedDatas == null)
+			return;
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.recordCurrentOrder();
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** Has linked data matrices record previous order. */
+	public final void recordPreviousOrderInLinked(){
+		if (linkedDatas == null)
+			return;
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.recordPreviousOrder();
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	/** Has linked data matrices record previous order. */
+	public final void restoreToPreviousOrderInLinked(){
+		if (linkedDatas == null)
+			return;
+		if (linkedDatas.size()>0){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d = (CharacterData)linkedDatas.elementAt(i);
+				d.restoreToPreviousOrder();
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	private NameReference notesNameRef = NameReference.getNameReference("notes");
+	private NameReference historyNameRef = NameReference.getNameReference("ChangeHistory");
+	private AttachedNotesVector getVector(CharacterData d, int ic, int it){
+		if (it == -1)
+			return (AttachedNotesVector)d.getAssociatedObject(notesNameRef, ic);
+		else if (ic>= 0 && it>=0)
+			return (AttachedNotesVector)d.getCellObject(notesNameRef, ic, it);
+		return null;
+	}
+	private void copyAnnotations(int ic, int it, CharacterData oData, int oic, int oit){
+		AttachedNotesVector v = getVector(this, ic, it);
+		AttachedNotesVector vO = getVector(oData, oic, oit);
+		if (vO == null) { //no notes; do nothing
+		}
+		else if (ic>=0){
+			v = vO.cloneVector(this);
+			if (it < 0)
+				setAssociatedObject(notesNameRef, ic, v);
+			else {
+				setCellObject(notesNameRef, ic, it, v);
+				setCellObjectDisplay(ic, it);
+			}
+		}
+	}
+	/*-----------------------------------------------------------*/
+	public void equalizeCharacter(CharacterData oData, int oic, int ic){
+		//doesn't yet incorporate colors, etc
+		CharacterState cs2 = null;
+		if (oData.characterNames != null && oic<oData.characterNames.length){
+			characterNames[ic] = oData.characterNames[oic];
+			notifyOfChangeLowLevel(MesquiteListener.NAMES_CHANGED, ic, -1, 0);  
+
+		}
+		for (int it = 0; it<getNumTaxa(); it++){
+			incrementSuppressHistoryStamp();
+			int oit = oData.getTaxa().findEquivalentTaxon(getTaxa(), it);
+			if (oit >= 0){
+				cs2 = oData.getCharacterState(cs2, oic, oit);
+				if (cs2 !=null) 
+					setState(ic, it, cs2);
+				notifyOfChangeLowLevel(MesquiteListener.DATA_CHANGED, ic, it, 0);  
+				copyAnnotations(ic, it, oData, oic, oit);
+				//add: cellObjectsDisplay
+				ChangeHistory h2 = (ChangeHistory)oData.getCellObject(historyNameRef, oic, oit);
+				if (h2 != null)	
+					setCellObject(historyNameRef, ic, it, h2.cloneHistory());
+			}
+		}
+		equalizeParts(oData, oic, ic);
+		decrementSuppressHistoryStamp();
+		setAnnotation(ic, oData.getAnnotation(oic));
+		copyAnnotations( ic, -1, oData, oic, -1);
+	}
+	/*-----------------------------------------------------------*/
+	/**Adds num taxa after position "starting"; returns true iff successful.  Assumes details already handled in subclasses, and numTaxa reset there.*/
+	public boolean addTaxa(int starting, int num){
+		if (!checkThread(false))
+			return false;
+		doubleCheckTaxaIDs = LongArray.addParts(doubleCheckTaxaIDs, starting, num, 0L);
+		for (int i = starting+1; i<= starting+num; i++) {
+			Taxon taxon = taxa.getTaxon(i);
+			if (taxon != null)
+				doubleCheckTaxaIDs[i] = taxon.getID();
+		}
+
+		taxaIDs = taxa.getTaxaIDs();
+		if (footnotes !=null) {
+			footnotes = StringArray.addRows(footnotes, starting, num);
+		}
+		if (cellObjectsDisplay !=null) {
+			cellObjectsDisplay = Bits.addRows(cellObjectsDisplay, starting, num);
+		}
+		if (changedSinceSave !=null) {
+			changedSinceSave = Bits.addRows(changedSinceSave, starting, num);
+		}
+		if (firstApplicable !=null) {
+			firstApplicable = IntegerArray.addParts(firstApplicable, starting, num);
+		}
+		if (lastApplicable !=null) {
+			lastApplicable = IntegerArray.addParts(lastApplicable, starting, num);
+		}
+
+		if (cellObjects != null && cellObjects.size()>0){//Vector of arrays of objects that are attached to cells
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] objects = objArray.getMatrix();
+				objects = Object2DArray.addRows(objects, starting, num);
+				objArray.setMatrix(objects);
+			}
+		}
+		if (taxaInfo != null)
+			taxaInfo.addParts(starting, num);
+		uncheckThread();
+		return true;
+	}
+
+	/*-----------------------------------------------------------*/
+
+	/**Deletes num taxa from position "starting"; returns true iff successful.  Assumes details already handled in subclasses, and numTaxa reset there.*/
+	public boolean deleteTaxa(int starting, int num){
+		if (taxa == null)
+			return false;
+		if (!checkThread(false))
+			return false;
+		doubleCheckTaxaIDs = LongArray.deleteParts(doubleCheckTaxaIDs, starting, num);
+		taxaIDs = taxa.getTaxaIDs();
+		if (footnotes !=null) {
+			footnotes = StringArray.deleteRows(footnotes, starting, num);
+		}
+		if (cellObjectsDisplay !=null) {
+			cellObjectsDisplay = Bits.deleteRows(cellObjectsDisplay, starting, num);
+		}
+		if (changedSinceSave !=null) {
+			changedSinceSave = Bits.deleteRows(changedSinceSave, starting, num);
+		}
+		if (firstApplicable !=null) {
+			firstApplicable = IntegerArray.deleteParts(firstApplicable, starting, num);
+		}
+		if (lastApplicable !=null) {
+			lastApplicable = IntegerArray.deleteParts(lastApplicable, starting, num);
+		}
+
+		if (cellObjects != null && cellObjects.size()>0){//Vector of arrays of objects that are attached to cells
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] objects = objArray.getMatrix();
+				objects = Object2DArray.deleteRows(objects, starting, num);
+				objArray.setMatrix(objects);
+			}
+		}
+		if (taxaInfo != null)
+			taxaInfo.deleteParts(starting, num);
+		uncheckThread();
+		return true;
+	}
+
+	/**moves num taxa from position "starting" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveTaxa(int starting, int num, int justAfter){
+		if (!checkThread(false))
+			return false;
+		if (footnotes !=null) {
+			StringArray.moveRows(footnotes, starting, num, justAfter);
+		}
+		if (cellObjectsDisplay !=null) {
+			Bits.moveRows(cellObjectsDisplay, starting, num, justAfter);
+		}
+		if (changedSinceSave !=null) {
+			Bits.moveRows(changedSinceSave, starting, num, justAfter);
+		}
+		if (firstApplicable !=null) {
+			firstApplicable = IntegerArray.moveParts(firstApplicable, starting, num, justAfter);
+		}
+		if (lastApplicable !=null) {
+			lastApplicable = IntegerArray.moveParts(lastApplicable, starting, num, justAfter);
+		}
+
+
+		if (cellObjects != null && cellObjects.size()>0){//Vector of arrays of objects that are attached to cells
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object[][] objects = objArray.getMatrix();
+				Object2DArray.moveRows(objects, starting, num, justAfter);
+				objArray.setMatrix(objects);
+			}
+		}
+		LongArray.moveParts(taxaIDs, starting, num, justAfter);
+		LongArray.moveParts(doubleCheckTaxaIDs, starting, num, justAfter);
+
+		if (taxaInfo != null)
+			taxaInfo.moveParts(starting, num, justAfter);
+		uncheckThread();
+		return true;
+	}
+	private long[] lastNotifications = new long[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; //a partial protection against responding to the same notification twice, e.g. coming via two different pathways.
+	private boolean notificationFound(Notification notification){
+		if (notification ==null)
+			return false;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return false;
+		if (LongArray.indexOf(lastNotifications, id)>=0)
+			return true;
+		return false;
+	}
+	private void rememberNotification(Notification notification){
+		if (notification ==null)
+			return;
+		long id = notification.getNotificationNumber();
+		if (id <0)
+			return;
+		for (int i = 0; i< lastNotifications.length-1; i++)
+			lastNotifications[i+1] = lastNotifications[i];
+		lastNotifications[0] = id;
+	}
+	/** For MesquiteListener interface; passes which object changed, along with optional integer (e.g. for character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (notificationFound(notification))
+			return;
+		rememberNotification(notification);
+		if (obj == taxa) {
+			if (Notification.appearsCosmetic(notification) || notification == null   || notification.getCode() == MesquiteListener.SELECTION_CHANGED)
+				return;
+			int code = Notification.getCode(notification);
+			int[] parameters = Notification.getParameters(notification);
+			if (parameters==null && obj instanceof Taxa && (Taxa)obj==taxa)
+				reconcileTaxa(code);
+			else {
+				try {
+					if (code== MesquiteListener.PARTS_ADDED)
+						addTaxa(parameters[0],parameters[1]);
+					else if (code== MesquiteListener.PARTS_DELETED)
+						deleteTaxa(parameters[0],parameters[1]);
+					else if (code== MesquiteListener.PARTS_MOVED)
+						moveTaxa(parameters[0],parameters[1], parameters[2]);
+					notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+				}
+				catch (ArrayIndexOutOfBoundsException e){}
+			}
+			if (basisTree!=null && basisTree instanceof MesquiteListener)
+				((MesquiteListener)basisTree).changed(caller, obj, notification);
+		}
+	}
+	/** For MesquiteListener interface*
+	public void disposing(Object obj){
+		super.disposing(obj);
+	}
+	/** For MesquiteListener interface*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+
+
+	public boolean checkTaxaIDs(){  //here for compatibility with older modules
+		String s =  checkIntegrity();
+		if (s == null)
+			return true;
+		dataIntegrityAlert(s);
+		return false;
+	}
+	public void dataIntegrityAlert(String s) {
+		if (badImport){
+			discreetAlert(s);
+			MesquiteMessage.printStackTrace();
+			return;
+		}
+		Thread current = Thread.currentThread();
+		if ((current instanceof MesquiteThread) && !MesquiteThread.isScripting())
+			MesquiteTrunk.mesquiteTrunk.reportableProblemAlert(s);
+		else
+			MesquiteMessage.warnProgrammer(s);
+		MesquiteMessage.printStackTrace();
+	}
+
+
+	public String checkIntegrity(){
+		String warning = null;
+		if (taxa == null)
+			return null;
+		if (numTaxa != taxa.getNumTaxa()) 
+			warning = "Error in CharacterData: numTaxa (" + numTaxa + ") != taxa.getNumTaxa() (" + taxa.getNumTaxa() + ") ";
+		if (taxaIDs.length !=numTaxa) {
+			warning = "Error in CharacterData: numTaxa (" + numTaxa + ") != taxaIDs.length (" + taxaIDs.length + ") (taxa.getNumTaxa() " + taxa.getNumTaxa() + ")";
+		}
+		for (int i = 0; i<taxa.getNumTaxa() && warning == null; i++)
+			if (i>= taxaIDs.length || taxa.getTaxon(i).getID() != taxaIDs[i])
+				warning = "Error in CharacterData: id of taxon " + i +" in Taxa doesn't match id recorded in CharacterData";
+		for (int i = 0; i<taxa.getNumTaxa() && warning == null; i++)
+			if (i>= doubleCheckTaxaIDs.length || taxa.getTaxon(i).getID() != doubleCheckTaxaIDs[i])
+				warning = "Error in CharacterData: id of taxon " + i +" in Taxa doesn't match id* recorded in CharacterData";
+		return warning;
+
+		/*	if (warning == null)
+			return true;
+		MesquiteTrunk.mesquiteTrunk.alert(warning + " (" + this + ")");
+	//	MesquiteMessage.warnProgrammer(warning + " (" + this + ")");
+		return false;*/
+	}
+
+	/*
+	private void dumpIDs(){
+		MesquiteMessage.println("local " + LongArray.toString(taxaIDs));
+		String s = "[ ";
+		for (int i = 0; i<taxa.getNumTaxa(); i++) //go through list of taxa
+			s +=  taxa.getTaxon(i).getID() + "  ";
+		MesquiteMessage.println("in taxa " + s + "]");
+	}
+	 */
+	private void reconcileTaxa(int code){
+		if (taxa == null)
+			return;
+
+		//check id list of taxa to see that it matches; otherwise adjust matrix to match taxa sequence and presence/absence
+		int newNumTaxa = taxa.getNumTaxa();
+		if (newNumTaxa == numTaxa) {
+			if (code== MesquiteListener.PARTS_CHANGED || code== MesquiteListener.PARTS_MOVED) {
+				/*go through list of taxa.  If any taxon is not in sequence expected from Taxa then find where it is in the list of taxaID's
+				and move it into place*/
+				for (int i = 0; i<taxa.getNumTaxa(); i++){ //!!!!! && taxa.getTaxon(i) != null; i++){ //go through list of taxa
+					if (taxa.getTaxon(i).getID() != taxaIDs[i]){ //taxon i is not in sequence expected from Taxa
+						int loc = LongArray.indexOf(taxaIDs, taxa.getTaxon(i).getID());
+						if (loc <0) {
+							MesquiteTrunk.mesquiteTrunk.discreetAlert( "Error in CharacterData: taxaID's cannot be reconciled with current Taxa");
+							return;
+						}
+						else {
+							//move taxon that should be here into this place
+							moveTaxa(loc, 1, i-1);
+						}
+					}
+				}
+				Notification notification = new Notification(MesquiteListener.PARTS_CHANGED);
+				notification.setSubcodes(new int[] {MesquiteListener.TAXA_CHANGED});
+				notifyListeners(this, notification);
+			}
+			else {
+				String s = checkIntegrity();
+				if (s !=null) {
+
+					dataIntegrityAlert(s + " (" + this + ")");
+				}
+
+			}
+		}
+		else {
+			long[] oldTaxaIDs = taxaIDs;
+			if (code== MesquiteListener.PARTS_ADDED) {
+				//cycle through finding which taxa in Taxa are not in matrix, and adding them
+				for (int i=0; i<newNumTaxa; i++) {
+					Taxon t = taxa.getTaxon(i);
+					long tid = t.getID();
+					if (LongArray.indexOf(oldTaxaIDs, tid)<0){
+						int tN = taxa.whichTaxonNumber(t);
+						addTaxa(tN-1, 1);
+						//should instead find contiguous block and add all at once!
+					}
+				}
+
+			}
+			else if (code== MesquiteListener.PARTS_DELETED) {
+				deleteByBlocks(oldTaxaIDs);
+
+			}
+			else {
+				deleteByBlocks(oldTaxaIDs);
+				//cycle through finding which taxa in Taxa are not in matrix, and adding them
+				for (int i=0; i<newNumTaxa; i++) {
+					Taxon t = taxa.getTaxon(i);
+					if (t != null){
+						long tid = t.getID();
+						if (LongArray.indexOf(oldTaxaIDs, tid)<0){
+							int tN = taxa.whichTaxonNumber(t);
+							addTaxa(tN-1, 1);
+							//should instead find contiguous block and add all at once!
+						}
+					}
+				}
+			}
+			taxaIDs = taxa.getTaxaIDs();
+			String s = checkIntegrity();
+			if (s !=null)
+				MesquiteTrunk.mesquiteTrunk.alert(s + " (" + this + ")");
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+		}
+	}
+	private void deleteByBlocks(long[] oldTaxaIDs){
+		int firstOfBlock = -1;
+		int lastOfBlock = -1;
+		//cycle through finding which taxa in matrix have been deleted && deleting them from matrix
+		for (int i=numTaxa-1; i>=0; i--) {
+			Taxon t = taxa.getTaxonByID(oldTaxaIDs[i]);
+			if (t==null) { // taxon was deleted
+				if (lastOfBlock <0){  // no current block growing; establish rightmost of block (going backwards!)
+					firstOfBlock = i;
+					lastOfBlock = i;
+				}
+				else if (firstOfBlock == i+1)  //last deleted was immediately later, so now turn this into last deleted
+					firstOfBlock = i;
+				else {  //there is current block, but last deleted was not immediately after, so delete the current block and establish i as start of new block
+					deleteTaxa(firstOfBlock, lastOfBlock-firstOfBlock +1);
+					firstOfBlock = i;
+					lastOfBlock = i;
+				}						
+			}
+			else if (lastOfBlock>=0){  // this taxon was not deleted, but there is a current block, so delete it
+				deleteTaxa(firstOfBlock, lastOfBlock-firstOfBlock +1);
+				firstOfBlock = -1;
+				lastOfBlock = -1;
+			}
+
+		}
+		if (lastOfBlock>=0){  // this taxon was not deleted, but there is a current block, so delete it
+			deleteTaxa(firstOfBlock, lastOfBlock-firstOfBlock +1);
+			firstOfBlock = -1;
+			lastOfBlock = -1;
+		}
+
+	}
+	long statesVersion = 0;
+	public long getStatesVersion(){
+		return statesVersion;
+	}
+	protected void incrementStatesVersion(){
+		statesVersion++;
+		checksumValid = false;
+	}
+
+	/** extracts data from matrix for character ic, and returns it in a CharacterDistribution object.*/
+	public abstract CharacterDistribution getCharacterDistribution(int ic); //TODO: should pass a CharacterDistribution to save the instantiation
+	/** returns data from matrix wrapped  in a embedded MCharactersDistribution object.*/
+	public abstract MCharactersDistribution getMCharactersDistribution();
+	/** extracts data from matrix, and returns it in an independent MCharactersDistribution object.*/
+	public MCharactersDistribution getIndependentMCharactersDistribution(){
+		CharacterState cs =  null;				
+		MCharactersDistribution md = getMCharactersDistribution(); //this will be embedded; need independent
+		MAdjustableDistribution mda = md.makeBlankAdjustable();
+		for (int ic= 0; ic<getNumChars(); ic++)
+			for (int it = 0; it<getNumTaxa(); it++)
+				mda.setCharacterState(cs = getCharacterState(cs, ic, it), ic, it);
+		return mda;
+	}
+	/** Fills matrix with data from passed MCharactersDistribution object.*/
+	public abstract void setMatrix(MCharactersDistribution states);
+	/** creates an empty CharacterState object of the same data type as CharacterData subclass used.*/
+	public abstract CharacterState makeCharacterState();
+	/** creates an empty CharacterDistribution object of the same data type as CharacterData subclass used.*/
+	public abstract CharacterDistribution makeCharacterDistribution();
+	/** creates an empty CharacterData object of the same data type as CharacterData subclass used.*/
+	public abstract CharacterData makeCharacterData();
+	/** creates an empty CharacterData object of the same data type as CharacterData subclass used, based on CharMatrixManager & Taxa passed.*/
+	public abstract CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa); 
+	/** creates a CharacterData object of the same data type as CharacterData subclass used, with ntaxa and nchars.*/
+	public abstract CharacterData makeCharacterData(int ntaxa, int nchars);
+
+	/** trades the states of character ic and ic2 in taxon it.  Used for reversing sequences (for example).*/
+	public void tradeStatesBetweenCharacters(int ic, int ic2, int it, boolean adjustCellLinked){
+		//trade cell footnotes
+		if (footnotes!= null)  {
+			if (ic<footnotes.length && ic2<footnotes.length && it<footnotes[ic].length) {
+				String ct = footnotes[ic][it];
+				footnotes[ic][it] = footnotes[ic2][it];
+				footnotes[ic2][it] = ct;
+			}
+		}
+		//trade cell objects
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object ob = objArray.getValue(ic, it);
+				objArray.setValue(ic, it, objArray.getValue(ic2, it));
+				objArray.setValue(ic2, it, ob);
+			}
+		}
+		boolean t = cellObjectsDisplay[ic][it];
+		cellObjectsDisplay[ic][it] = cellObjectsDisplay[ic2][it];
+		cellObjectsDisplay[ic2][it] = t;
+		if (adjustCellLinked){
+			for (int i=0; i<linkedDatas.size(); i++){
+				CharacterData d= (CharacterData)linkedDatas.elementAt(i);
+				d.tradeStatesBetweenCharacters(ic,ic2,it,false);
+			}
+		}
+	}
+	/** trades the states of character ic between taxa it and it2.  Used for reshuffling (for example).*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2){
+		//trade cell footnotes
+		if (footnotes!= null)  {
+			if (ic<footnotes.length && it2<footnotes[ic].length && it<footnotes[ic].length) {
+				String ct = footnotes[ic][it];
+				footnotes[ic][it] = footnotes[ic][it2];
+				footnotes[ic][it2] = ct;
+			}
+		}
+		//trade cell objects
+		if (cellObjects.size()>0){
+			for (int k =0; k<cellObjects.size(); k++){
+				Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+				Object ob = objArray.getValue(ic, it);
+				objArray.setValue(ic, it, objArray.getValue(ic, it2));
+				objArray.setValue(ic, it2, ob);
+			}
+		}
+		boolean t = cellObjectsDisplay[ic][it];
+		cellObjectsDisplay[ic][it] = cellObjectsDisplay[ic][it2];
+		cellObjectsDisplay[ic][it2] = t;
+	}
+
+	/** returns whether the matrix would prefer to have columns sized individually in editors.  Default is true.*/
+	public boolean pleaseAutoSizeColumns() {
+		return columnWidthAutoSize;
+	}
+	/** Sets whether to autoSize columns, if this is setable.*/
+	public void setAutoSizeColumns(boolean autoSize) {
+		columnWidthAutoSize = autoSize;
+	}
+	/** returns default column width in editors.  Default is 16.*/
+	public int getDefaultColumnWidth() {
+		return 16;
+	}
+	/** returns default narrow column width in editors.  Default is 16.*/
+	public int getNarrowDefaultColumnWidth() {
+		return 16;
+	}
+
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public abstract void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned);
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public abstract void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay);
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public abstract void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb);
+	/**Set the state at character ic and taxon it from the string in the parser, beginning at current parser position in the string. 
+	Updates current position in string.  If fromEditor is true, should assume whole string is state. Returns a result code (OK, ERROR, EOL, COMMENT).
+	EOL is returned if data are interleaved and end of line found.  If there is an error or a comment, an error message or the comment,
+	respectively, will be returned in the result MesquiteString.*/
+	public abstract int setState(int ic, int it, Parser parser, boolean fromEditor, MesquiteString result);
+
+	/**Override to provide faster and more risky state setting for reading large files.  Assumes it and ic are in bounds, and parser string is not blank*/
+	public int setStateQuickNexusReading(int ic, int it, Parser parser){
+		return setState(ic, it, parser, false, null);
+	}
+	/** sets the state of character ic in taxon it from CharacterState cs*/
+	public abstract void setState(int ic, int it, CharacterState cs);
+
+	/** returns whether the character ic in taxon it has a terminal inapplicable*/
+	public boolean isTerminalInapplicable(int ic, int it){
+		if (!isInapplicable(ic,it)) 
+			return false;
+		if (firstApplicable!=null && it<firstApplicable.length && (firstApplicable[it]<0 || ic<firstApplicable[it]))
+			return true;
+		if (lastApplicable!=null && it<lastApplicable.length && ic>lastApplicable[it] && lastApplicable[it]>=0)
+			return true;
+		/*		boolean terminal = true;
+		for (int i=ic-1; i>=0; i--)
+			if (!isInapplicable(i,it)){
+				terminal=false;
+				break;
+			}
+		if (terminal)
+			return true;
+		terminal=true;
+		for (int i=ic+1; i<numChars; i++)
+			if (!isInapplicable(i,it))
+				return false;
+		 */
+		return false;
+
+	}
+
+	/** returns whether the character ic is inapplicable to taxon it*/
+	public abstract boolean isInapplicable(int ic, int it);
+	/** returns whether the character ic is entirely inapplicable codings*/
+
+	/** sets the state of character ic in taxon it to inapplicable*/
+	public  abstract void setToInapplicable(int ic, int it);
+	/** sets the state of all characters in taxon it to the default state (which in some circumstances may be inapplicable, e.g. gaps for molecular data)*/
+	public void setToInapplicable(int it) {
+		for (int ic=0; ic<numChars; ic++)
+			setToInapplicable(ic,it);
+	}
+	/** sets the state of character ic in taxon it to unassigned*/
+	public  abstract void setToUnassigned(int ic, int it);
+	/** sets the state of all characters in taxon it to unassigned*/
+	public void setToUnassigned(int it) {
+		for (int ic=0; ic<numChars; ic++)
+			setToUnassigned(ic,it);
+	}
+	/** sets the state of character ic in taxon it to the default state (which in some circumstances may be inapplicable, e.g. gaps for molecular data)*/
+	public  abstract void deassign(int ic, int it);
+
+	public boolean hasDataForTaxon(int it){
+		int numChars = getNumChars();
+		for (int ic=0; ic<numChars; ic++) {
+			if (!isInapplicable(ic, it) && !isUnassigned(ic, it))
+				return true;
+		}		
+		return false;
+	}
+	public boolean hasDataForTaxon(int it, boolean considerExcluded){
+		int numChars = getNumChars();
+		for (int ic=0; ic<numChars; ic++) {
+			if (!isInapplicable(ic, it) && !isUnassigned(ic, it) && (considerExcluded || isCurrentlyIncluded(ic)))
+				return true;
+		}		
+		return false;
+	}
+
+	public boolean hasDataForTaxa(int itStart, int itEnd){
+		for (int it=itStart; it<=itEnd; it++)
+			if (hasDataForTaxon(it))
+				return true;
+		return false;
+	}
+
+	public boolean hasDataForCharacter(int ic){
+		int numTaxa = getNumTaxa();
+		for (int it=0; it<numTaxa; it++) {
+			if (!isInapplicable(ic, it) && !isUnassigned(ic, it))
+				return true;
+		}		
+		return false;
+	}
+
+	public boolean hasDataForCharacters(int icStart, int icEnd){
+		for (int ic=icStart; ic<=icEnd; ic++)
+			if (hasDataForCharacter(ic))
+				return true;
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean anyApplicableBefore(int ic, int it){
+		for (int i = 0; i<ic; i++)
+			if (!isInapplicable(i,it))
+				return true;
+
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean anyApplicableAfter(int ic, int it) {
+		int numChars = getNumChars();
+		for (int i = ic+1; i<numChars; i++)
+			if (!isInapplicable(i, it))
+				return true;
+		return false;
+	}
+
+	public boolean removeTaxaThatAreEntirelyGaps(){
+		boolean removedSome = false;
+		int numT = getNumTaxa();
+		for (int it = numT; it>=0; it--){
+			if (entirelyInapplicableTaxon(it)) {
+				int numToDelete = 1;
+				int firstToDelete = it;
+				for (int it2 =it-1; it2>=0; it2--){
+					if (entirelyInapplicableTaxon(it2)) {
+						numToDelete++;
+						firstToDelete= it2;
+					} else break;
+				}
+				deleteTaxa(firstToDelete, numToDelete);
+				it=it-numToDelete+1;
+				removedSome=true;
+			}
+		}
+		return removedSome;
+	}
+
+
+
+
+	public boolean removeCharactersThatAreEntirelyGaps(boolean notify){
+		boolean removedSome = false;
+		for (int ic = getNumChars()-1; ic>=0; ic--){
+			if (entirelyInapplicable(ic)) {
+				int numToDelete = 1;
+				int firstToDelete = ic;
+				for (int ic2 =ic-1; ic2>=0; ic2--){
+					if (entirelyInapplicable(ic2)) {
+						numToDelete++;
+						firstToDelete= ic2;
+					} else break;
+				}
+				deleteCharacters(firstToDelete, numToDelete, notify);
+				deleteInLinked(firstToDelete,numToDelete,notify);
+				ic=ic-numToDelete+1;
+				removedSome=true;
+			}
+		}
+		return removedSome;
+	}
+
+
+
+	public boolean removeCharactersThatAreEntirelyUnassigned(boolean notify){
+		boolean removedSome = false;
+		for (int ic = getNumChars()-1; ic>=0; ic--){
+			if (entirelyUnassigned(ic)) {
+				int numToDelete = 1;
+				int firstToDelete = ic;
+				for (int ic2 =ic-1; ic2>=0; ic2--){
+					if (entirelyUnassigned(ic2)) {
+						numToDelete++;
+						firstToDelete= ic2;
+					} else break;
+				}
+				deleteCharacters(firstToDelete, numToDelete, notify);
+				deleteInLinked(firstToDelete,numToDelete,notify);
+				ic=ic-numToDelete+1;
+				removedSome=true;
+			}
+		}
+		return removedSome;
+	}
+	public boolean removeCharactersThatAreEntirelyUnassignedOrInapplicable(boolean notify){
+		boolean removedSome = false;
+		for (int ic = getNumChars()-1; ic>=0; ic--){
+			if (entirelyUnassignedOrInapplicable(ic)) {
+				int numToDelete = 1;
+				int firstToDelete = ic;
+				for (int ic2 =ic-1; ic2>=0; ic2--){
+					if (entirelyUnassignedOrInapplicable(ic2)) {
+						numToDelete++;
+						firstToDelete= ic2;
+					} else break;
+				}
+				deleteCharacters(firstToDelete, numToDelete, notify);
+				deleteInLinked(firstToDelete,numToDelete,notify);
+				ic=ic-numToDelete+1;
+				removedSome=true;
+			}
+		}
+		return removedSome;
+	}
+
+	public boolean entirelyUnassigned(int ic){
+		for (int it = 0; it< getNumTaxa(); it++)
+			if (!isUnassigned(ic, it))
+				return false;
+		return true;
+	}
+	/** returns true iff all data is at left, with no inapplicable before the data ends */
+	public boolean isUnalignedLeft(int it){
+		boolean inapplicableFound = false;
+		for (int ic = 0; ic< numChars; ic++)
+			if (isInapplicable(ic, it)) {
+				inapplicableFound = true;
+			} else if (inapplicableFound)
+				return false;
+		return true;
+	}
+
+	public int numInapplicable(int it){
+		int count=0;
+		for (int ic = 0; ic< numChars; ic++)
+			if (isInapplicable(ic, it))
+				count++;
+		return count;
+	}
+	public int numUnassigned(int it){
+		int count=0;
+		for (int ic = 0; ic< numChars; ic++)
+			if (isUnassigned(ic, it))
+				count++;
+		return count;
+	}
+	public int numNotInapplicableNotUnassigned(int it){
+		int count=0;
+		for (int ic = 0; ic< numChars; ic++)
+			if (!isUnassigned(ic, it) && !isInapplicable(ic,it))
+				count++;
+		return count;
+	}
+	public boolean entirelyInapplicable(int ic){
+		for (int it = 0; it< numTaxa; it++)
+			if (!isInapplicable(ic, it))
+				return false;
+		return true;
+	}
+	public boolean entirelyInapplicableTaxon(int it){
+		for (int ic = 0; ic< numChars; ic++)
+			if (!isInapplicable(ic, it))
+				return false;
+		return true;
+	}
+	public boolean inapplicableBlock(int icStart, int icEnd, Bits whichTaxa, int firstTaxon, int lastTaxon){
+		for (int it = firstTaxon; it>=0 && it<=lastTaxon && it< numTaxa; it++)
+			if (whichTaxa.isBitOn(it))
+				for (int ic = icStart; ic< getNumChars() && ic<=icEnd; ic++)
+					if (!isInapplicable(ic, it))
+						return false;
+		return true;
+	}
+	public boolean inapplicableBlock(int icStart, int icEnd, Bits whichTaxa){
+		for (int it = 0; it< numTaxa; it++)
+			if (whichTaxa.isBitOn(it))
+				for (int ic = icStart; ic< getNumChars() && ic<=icEnd; ic++)
+					if (!isInapplicable(ic, it))
+						return false;
+		return true;
+	}
+
+	public boolean inapplicableBlock(int icStart, int icEnd, int itStart, int itEnd){
+		for (int it = itStart; it< numTaxa && it<=itEnd; it++)
+			for (int ic = icStart; ic< getNumChars() && ic<=icEnd; ic++)
+				if (!isInapplicable(ic, it))
+					return false;
+		return true;
+	}
+	public boolean applicableInBothCharacters(int ic1, int ic2, int itStart, int itEnd){
+		if (ic1<0 || ic1>=numChars || ic2<0 || ic2>=numChars)
+			return false;
+		for (int it = itStart; it< numTaxa && it<=itEnd; it++)
+			if (!isInapplicable(ic1, it) && !isInapplicable(ic2, it))
+				return true;
+		return false;
+	}
+	public boolean applicableInBothCharacters(int ic1, int ic2, Bits whichTaxa){
+		if (ic1<0 || ic1>=numChars || ic2<0 || ic2>=numChars)
+			return false;
+		for (int it = 0; it< numTaxa; it++)
+			if (whichTaxa.isBitOn(it) && !isInapplicable(ic1, it) && !isInapplicable(ic2, it))
+				return true;
+		return false;
+	}
+	public boolean entirelyUnassignedOrInapplicable(int ic){
+		for (int it = 0; it< numTaxa; it++)
+			if (!isInapplicable(ic, it) && !isUnassigned(ic, it))
+				return false;
+		return true;
+	}
+	/** returns whether the state of character ic is missing in taxon it*/
+	public abstract boolean isUnassigned(int ic, int it);
+
+	/** returns whether the state of character ic is valid in taxon it*/
+	public boolean isValid(int ic, int it){
+		return true;
+	}
+
+	/** returns whether the character ic is included (i.e. not currently excluded)*/
+	public boolean isCurrentlyIncluded(int ic){
+		CharInclusionSet incl = (CharInclusionSet)getCurrentSpecsSet(CharInclusionSet.class);
+		return (incl==null || incl.isBitOn(ic));
+
+	}
+	/** returns number of currently included characters*/
+	public int numCharsCurrentlyIncluded(){
+		CharInclusionSet incl = (CharInclusionSet)getCurrentSpecsSet(CharInclusionSet.class);
+		if (incl!=null)
+			return incl.numBitsOn();
+		return numChars;
+	}
+	/** returns number of currently included characters*/
+	public int numCharsCurrentlyIncluded(boolean countSelectedOnly){
+		CharInclusionSet incl = (CharInclusionSet)getCurrentSpecsSet(CharInclusionSet.class);
+		if (countSelectedOnly) {
+			int count = 0;
+			for (int ic=0; ic<numChars; ic++){
+				if (incl.isBitOn(ic) && selected.isBitOn(ic))
+					count++;
+			}
+			return count;
+		} else {
+			if (incl!=null)
+				return incl.numBitsOn();
+		}
+		return numChars;
+	}
+	public int firstApplicable(Bits whichTaxa){
+		int first = -1;
+		for (int it = 0; it<numTaxa; it++)
+			if (whichTaxa.isBitOn(it)) {
+				int firstInTaxon = firstApplicable(it);
+				if (first==-1)
+					first=firstInTaxon;
+				else if (firstInTaxon>=0)
+					first = MesquiteInteger.minimum(first,firstInTaxon);
+			}
+
+		return first;
+	}
+
+	public int firstApplicable(int itStart, int itEnd){
+		int first = -1;
+		for (int it = itStart; it<=itEnd; it++){
+			int firstInTaxon = firstApplicable(it);
+			if (first==-1)
+				first=firstInTaxon;
+			else if (firstInTaxon>=0)
+				first = MesquiteInteger.minimum(first,firstInTaxon);
+		}
+
+		return first;
+	}
+	public int firstApplicable(int it){
+		for (int ic= 0; ic<numChars; ic++) {
+			if (!isInapplicable(ic,it))
+				return ic;
+		}
+		return -1;
+	}
+	public int lastApplicable(Bits whichTaxa){
+		int last = -1;
+		for (int it = 0; it<numTaxa; it++)
+			if (whichTaxa.isBitOn(it)){
+				int lastInTaxon = lastApplicable(it);
+				last = MesquiteInteger.maximum(last,lastInTaxon);
+			}
+		return last;
+	}
+	public int lastApplicable(int itStart, int itEnd){
+		int last = -1;
+		for (int it = itStart; it<=itEnd; it++){
+			int lastInTaxon = lastApplicable(it);
+			last = MesquiteInteger.maximum(last,lastInTaxon);
+		}
+		return last;
+	}
+	public int lastApplicable(){
+		return lastApplicable(0,numTaxa);
+	}
+	public int lastApplicable(int it){
+		for (int ic= numChars-1; ic>=0; ic--) {
+			if (!isInapplicable(ic,it))
+				return ic;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** if state of character ic, taxon it is applicable, returns ic; otherwise, returns the next character that has applicable data*/
+	public int getNumCharsIncluded() {
+		int count=0;
+		for (int i = 0; i< getNumChars(); i++){
+			if (isCurrentlyIncluded(i))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public String getExcludedCharactersList(CharSpecsSet specsSet){
+		if (specsSet ==null || !(specsSet instanceof CharInclusionSet))
+			return "";
+		CharInclusionSet inclusionSet = (CharInclusionSet)specsSet;
+		String sT = "";
+		if (inclusionSet!=null) {
+			int continuing = 0;
+			int lastWritten = -1;
+			for (int ic=0; ic<getNumChars(); ic++) {
+				if (!inclusionSet.isBitOn(ic)) {
+					if (continuing == 0) {
+						sT += " " + CharacterStates.toExternal(ic);
+						lastWritten = ic;
+						continuing = 1;
+					}
+					else if (continuing == 1) {
+						sT += "-";
+						continuing = 2;
+					}
+				}
+				else if (continuing>0) {
+					if (lastWritten !=ic-1){
+						sT += " " + CharacterStates.toExternal(ic-1);
+						lastWritten = ic-1;
+					}
+					else
+						lastWritten = -1;
+					continuing = 0;
+				}
+
+			}
+			if (continuing>1)
+				sT += " " + CharacterStates.toExternal(getNumChars()-1);
+
+		}
+		return sT;
+	}
+	/*.................................................................................................................*/
+	/** if state of character ic, taxon it is applicable, returns ic; otherwise, returns the previous character that has applicable data*/
+	public int thisOrPreviousApplicableChar(int icC, int it){
+		for (int ic= icC; ic>=0; ic--) {
+			if (!isInapplicable(ic,it))
+				return ic;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	/** if state of character ic, taxon it is applicable, returns ic; otherwise, returns the next character that has applicable data*/
+	public int thisOrNextApplicableChar(int ic, int it) {
+		for (int i = 0; ic+i< getNumChars(); i++){
+			if (!isInapplicable(ic+i,it)) {
+				return ic+i;
+			}
+		}
+		return -1;
+	}
+	/*..........................................   ..................................................*/
+	public boolean dataMatches(int it, int checkChar, int masterTaxon, int masterStart, int masterEnd, MesquiteInteger matchEnd, boolean allowMissing, boolean allowNearExact, double matchFraction, CharacterState cs1, CharacterState cs2) {
+		if (checkChar + (masterEnd-masterStart)>=getNumChars()){ //would extend past end of data
+			return false;
+		}
+		int mismatches = 0;
+		int allowedMismatches = (int)((masterEnd-masterStart+1) * (1.0-matchFraction));
+		for (int ic= 0; ic < masterEnd-masterStart+1; ic++){
+			cs1 = getCharacterState(cs1, checkChar + ic, it);  
+			cs2 = getCharacterState(cs2,masterStart+ic, masterTaxon);  //
+			if (!cs2.equals(cs1,allowMissing, allowNearExact)) {
+				mismatches++;
+				if (matchFraction==1.0 || mismatches>allowedMismatches)
+					return false;
+			} 
+			matchEnd.setValue(ic);
+		}
+
+		return true;
+
+	}
+	/*..........................................   ..................................................*/
+	public boolean dataMatches(int it, int checkChar, int masterTaxon, int masterStart, int masterEnd, MesquiteInteger matchEnd, boolean allowMissing, boolean allowNearExact, CharacterState cs1, CharacterState cs2) {
+		return dataMatches(it, checkChar, masterTaxon, masterStart, masterEnd, matchEnd, allowMissing, allowNearExact, 1.0, cs1, cs2);
+	}
+	/** returns the state of character ic in taxon it*/
+	public abstract CharacterState getCharacterState(CharacterState cs, int ic, int it);
+
+
+	/*..........................................   ..................................................*/
+	/** returns a CharacterState array containing the data in taxon it from icStart to icEnd*/
+	public CharacterState[] getCharacterStateArray(int it, int icStart, int icEnd){
+		CharacterState[] csArray = new CharacterState[icEnd-icStart+1];
+		for (int ic = icStart; ic<=  icEnd && ic < getNumChars(); ic++){
+			csArray[ic-icStart] = makeCharacterState();
+			csArray[ic-icStart] = getCharacterState(csArray[ic-icStart], ic,  it);
+		}
+		return csArray;
+	}
+	/*..........................................   ..................................................*/
+
+
+
+	/** sets the symbol used for inapplicable character (e.g., gap)*/
+	public void setInapplicableSymbol(char inapp) {
+		setDirty(true);
+		inapplicableChar = inapp;
+	}
+	/** returns symbol used for inapplicable character (e.g., gap)*/
+	public char getInapplicableSymbol() {
+		return inapplicableChar;
+	}
+	/** sets the symbol used for missing data (unassigned) character*/
+	public void setUnassignedSymbol(char mc) { 
+		setDirty(true);
+		missingChar = mc;
+	}
+	/** returns symbol used for missing data (unassigned) character*/
+	public char getUnassignedSymbol() { 
+		return missingChar;
+	}
+	/** sets the symbol used for matchChar*/
+	public void setMatchChar(char mc) { 
+		matchChar = mc;
+	}
+	/** returns symbol used for matchChar*/
+	public char getMatchChar() { 
+		return matchChar;
+	}
+	/** sets whether cells are to be colored by default*/
+	public void setColorCellsByDefault(boolean colorCells){
+		colorCellsByDefault = colorCells;
+	}
+
+	/** returns whether cells are to be colored by default*/
+	public boolean colorCellsByDefault(){
+		return colorCellsByDefault;
+	}
+	/** returns the color of character ic; e.g., to indicate codon positions */
+	public Color getDefaultCharacterColor(int ic){
+		return null;
+	}
+	/** returns the dark color of character ic; e.g., to indicate codon positions */
+	public Color getDarkDefaultCharacterColor(int ic){
+		return null;
+	}
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	public  String getStatesSummary(int ic, boolean selectedOnly){
+		return getStatesSummary(ic);
+	}
+
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	public abstract String getStatesSummary(int ic);
+
+
+	/*.................................................................................................................*/
+	/** Indicates whether the data are molecular sequence data or not */ 
+	public boolean isMolecularSequence() {
+		return false;
+	}
+
+	/** Indicates the type of character stored */ 
+	public abstract Class getStateClass();
+	/** Gets the color representing state(s) of character ic in taxon it */ 
+	public abstract Color getColorOfStates(int ic, int it);
+
+	/*.................................................................................................................*/
+	/** returns the default character model for the paradigm (e.g., "parsimony") given in the String */ 
+	public abstract CharacterModel getDefaultModel(String paradigm);
+	/*.................................................................................................................*/
+	/** returns a list of names of the characters (StringLister interface)*/
+	public String[] getStrings(){
+		String[] s = new String[numChars];
+		for (int i=0; i<numChars; i++){
+			if (characterNames == null ||  characterNames[i]==null)
+				s[i]= "Character " + CharacterStates.toExternal(i); 
+			else
+				s[i]= Integer.toString(CharacterStates.toExternal(i)) + ". " + characterNames[i]; 
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	/** returns whether whether any characters have names*/
+	public boolean characterNamesExist() {
+		if (characterNames == null)
+			return false;
+		for (int ic=0; ic<numChars; ic++) {
+			if (characterNames[ic]!=null)
+				return true; 
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether character ic has a name*/
+	public boolean characterHasName(int ic) {
+		if (ic<0 || ic>=numChars) {
+			return false; 
+		}
+		else if (characterNames == null ||  characterNames[ic]==null)
+			return false; 
+		else
+			return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the name of character ic*/
+	public String getCharacterName(int ic) {
+		if (ic<0 || ic>=numChars) {
+			MesquiteMessage.warnProgrammer("Error: character number out of bounds (getCharacterName) " + ic);
+			return ""; 
+		}
+		else if (characterNames == null ||  characterNames[ic]==null)
+			return "Character " + CharacterStates.toExternal(ic); 
+		else
+			return characterNames[ic];
+	}
+	/*.................................................................................................................*/
+	/** sets the name of character ic*/
+	public void setCharacterName(int ic, String name) {
+		if (ic<0 || ic>=numChars) {
+			MesquiteMessage.warnProgrammer("Error: character number out of bounds (setCharacterName) " + ic);
+		}
+		else if (characterNames == null)
+			;
+		else {
+			try {
+				int i = Integer.parseInt(name);
+				name = "#" + name;  //autoadjust to add character
+			}
+			catch (NumberFormatException e){
+			}
+			if (StringUtil.blank(name))
+				name = null;
+			characterNames[ic]= name;
+			notifyOfChangeLowLevel(MesquiteListener.NAMES_CHANGED, ic, -1, 0);  
+			notifyListeners(this, new Notification(NAMES_CHANGED, new int[] {ic}));
+		}
+	}
+	/*.................................................................................................................*/
+	public String checkNameLegality(int it, String s){
+		if (s==null) {
+			return null; //characters can have null names
+		}
+		try {
+			int i = Integer.parseInt(s);
+			return "The character name \"" + s + "\" is illegal because it consists only of numbers";
+		}
+		catch (NumberFormatException e){
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** sets the annotation (footnote) of character ic, taxon it*/
+	public void setAnnotation(int ic, int it, String expl) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			if (ic<-2|| ic>=numChars || it<-2 || it>=numTaxa)
+				MesquiteMessage.println("Error: character or taxon number out of bounds (setAnnotation) " + ic);
+		}
+		else {
+			if (footnotes == null){
+				footnotes = new String[numChars][numTaxa];
+			}
+			if (!(ic<0 || ic>=footnotes.length || it<0 || footnotes[ic]==null || it>=footnotes[ic].length)){
+				if (expl == null)
+					footnotes[ic][it]= null;
+				else
+					footnotes[ic][it]= new String(expl);
+				notifyListeners(this, new Notification(ANNOTATION_CHANGED));
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** gets the annotation (footnote) of character ic, taxon it*/
+	public String getAnnotation(int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return null;
+		}
+		else {
+			if (footnotes == null)
+				return null;
+			if (ic<0 || ic>=footnotes.length || it<0 || footnotes[ic]==null || it>=footnotes[ic].length){
+				return null;
+			}
+			return footnotes[ic][it];
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns whether the matrix cell has been changed since the last file save*/
+	public boolean getChangedSinceSave(int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return false;
+		}
+		else if (changedSinceSave!=null && !(ic<0 || ic>=changedSinceSave.length || it<0 || changedSinceSave[ic]==null || it>=changedSinceSave[ic].length))
+			return changedSinceSave[ic][it];
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** resets to false for all cells whether the matrix cell has been changed since the last file save*/
+	public void resetChangedSinceSave() {
+		boolean c = false;
+		if (changedSinceSave!=null)
+			for (int ic = 0; ic<changedSinceSave.length; ic++)
+				for (int it=0; it<changedSinceSave[ic].length; it++){
+					if (changedSinceSave[ic][it]) {
+						changedSinceSave[ic][it] = false;
+						c = true;
+					}
+				}
+		watchForChange = true;	
+		checksumValid = false;
+		if (c)
+			notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+	}
+	/*.................................................................................................................*/
+	public void resetCellMetadata() {
+		resetChangedSinceSave();
+		calculateFirstLastApplicable();
+	}
+	/*.................................................................................................................*/
+	public Vector getCellObjectsVector(){
+		return cellObjects;
+	}
+	/*.................................................................................................................*/
+	public Object2DArray getWhichCellObjects(NameReference nRef){
+		if (cellObjects!=null && nRef!=null) {
+			for (int i=0; i<cellObjects.size(); i++) {
+				Object2DArray b = (Object2DArray)cellObjects.elementAt(i);
+				if (b !=null && nRef.equals(b.getNameReference())) {
+					return b; 
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** sets whether something drawing the matrix should check for special symbols for cell ic, it*/
+	public void setCellObjectDisplay(int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return;
+		}
+		else if (cellObjectsDisplay!=null && !(ic<0 || ic>=cellObjectsDisplay.length || it<0 || cellObjectsDisplay[ic]==null || it>=cellObjectsDisplay[ic].length)){
+			cellObjectsDisplay[ic][it] = true;
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns whether something drawing the matrix should check for special symbols for cell ic, it*/
+	public boolean getCellObjectDisplay(int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return false;
+		}
+		else if (cellObjectsDisplay!=null && !(ic<0 || ic>=cellObjectsDisplay.length || it<0 || cellObjectsDisplay[ic]==null || it>=cellObjectsDisplay[ic].length))
+			return cellObjectsDisplay[ic][it];
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** gets the object of type "name" attached to character ic, taxon it*/
+	public void setCellObject(NameReference nr, int ic, int it, Object obj) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return;
+		}
+		else {
+			Object2DArray array = getOrMakeCellObjects(nr);
+			if (array !=null) {
+				array.setValue(ic, it, obj);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** gets the object of type "name" attached to character ic, taxon it*/
+	public Object getCellObject(NameReference nr, int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa) {
+			return null;
+		}
+		else {
+			Object2DArray array = getWhichCellObjects(nr);
+			if (array!=null)
+				return array.getValue(ic, it);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** gets the object of type "name" attached to character ic, taxon it*/
+	public Object2DArray getOrMakeCellObjects(NameReference nr) {
+		Object2DArray array = getWhichCellObjects(nr);
+		if (array==null) {
+			array = new Object2DArray(numChars, numTaxa);
+			array.setNameReference(nr);
+			cellObjects.addElement(array);
+		}
+		return array;
+	}
+	/*.................................................................................................................*/
+	//this stores matrix-specific information on the taxa, e.g. regarding the sequences
+	Associable taxaInfo; 
+	public Associable getTaxaInfo(boolean makeIfNotPresent){
+		if (makeIfNotPresent && taxaInfo == null){
+			taxaInfo = new TaxaInfo(numTaxa, this);
+		}
+		return taxaInfo;
+	}
+
+	/*.................................................................................................................*/
+	boolean watchForChange = false;
+	/*.................................................................................................................*/
+	int suppressHistoryStamp = 0;
+	public void incrementSuppressHistoryStamp(){
+		suppressHistoryStamp++;
+	}
+	public void decrementSuppressHistoryStamp(){
+		suppressHistoryStamp--;
+	}
+	/*.................................................................................................................*/
+	Vector llListeners = new Vector();
+
+	public void addLowLevelListener(LowLevelListener listener){
+		llListeners.addElement(listener);
+	}
+	public void removeLowLevelListener(LowLevelListener listener){
+		llListeners.removeElement(listener);
+	}
+	// -1 -2 means that character number/order/etc changed; -2 -1 means that taxa number/order/etc changed
+	void notifyOfChangeLowLevel(int code, int i1, int i2, int i3){
+		if (MesquiteThread.getListenerSuppressionLevel()>0)
+			return;
+
+		for (int i = 0; i< llListeners.size(); i++){
+			LowLevelListener lll = (LowLevelListener)llListeners.elementAt(i);
+			try {
+				lll.llChange(this, code, i1, i2, i3);
+			}
+			catch (Throwable e){  //don't want problem in one of these to stop notifications
+			}
+		}
+	}
+	
+	/* ................................................................................................................. */
+	String nextPasteString(StringBuffer sb) {
+		if (sb.length() == 0)
+			return null;
+		String result = sb.substring(0, 1);
+		sb.delete(0, 1);
+		return result;
+	}
+	/* ............................................................................................................... */
+	public void pasteCell(Parser parser, int column, int row, String s) { 
+		if (StringUtil.blank(s))
+			return;
+		CharacterState csBefore = getCharacterState(null, column, row);
+		parser.setString(s);
+		MesquiteString result = new MesquiteString("");
+		int response = setState(column, row, parser, true, result); // receive errors?
+		if (response == CharacterData.OK) {
+			CharacterState csAfter = getCharacterState(null, column, row);
+			if (csBefore != null && !csBefore.equals(csAfter)) {
+				int[] subcodes = new int[] { MesquiteListener.SINGLE_CELL };
+				if (csBefore.isInapplicable() == csAfter.isInapplicable())
+					subcodes = new int[] { MesquiteListener.SINGLE_CELL, MesquiteListener.CELL_SUBSTITUTION };
+			}
+		}
+	}	
+	/* ................................................................................................................. */
+	boolean pasteData(int it, String s) {
+		String[] lines = StringUtil.getLines(s);
+		StringBuffer sb = new StringBuffer(lines[0]);
+		Parser parser = new Parser();
+		if (sb.indexOf("\t") >= 0) {
+			String result = sb.substring(0, sb.indexOf("\t"));
+			sb.delete(0, sb.indexOf("\t") + 1);
+		}
+		for (int i = 0; i < numChars && sb.length()>0; i++) {
+			pasteCell(parser, i, it, nextPasteString(sb));
+			
+		}
+		return true;
+	}
+
+	/* ................................................................................................................. */
+
+	public void pasteDataFromStringIntoTaxon(int it, String s) {
+			if (StringUtil.notEmpty(s)) {
+				String[] lines = StringUtil.getLines(s);
+				if (lines.length==1) {
+					pasteData(it, s);
+					notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+				}
+			}
+	}
+	/* ................................................................................................................. */
+
+	public void pasteDataIntoTaxon(int it) {
+
+		Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+		Transferable t = clip.getContents(this);
+		try {
+			String s = (String) t.getTransferData(DataFlavor.stringFlavor);
+			pasteDataFromStringIntoTaxon(it, s);
+		} catch (Exception e) {
+			MesquiteMessage.printStackTrace(e);
+		}
+	}
+
+	/*.................................................................................................................*/
+
+	public void copyDataFromRowIntoBuffer(int row, StringBuffer sb) {
+		if (sb ==null)
+			return;
+		String t = null;
+		t = taxa.getTaxonName(row);
+		if (t != null)
+			sb.append(t);
+		sb.append('\t');
+
+		for (int i = 0; i < numChars; i++) {
+			statesIntoStringBuffer(i, row, sb, true);
+		}
+		sb.append(StringUtil.lineEnding());
+	}
+	/*.................................................................................................................*/
+
+	public void copyDataFromRow(int row) {
+		StringBuffer sb = new StringBuffer();
+		copyDataFromRowIntoBuffer(row, sb);
+
+		Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+		StringSelection ss = new StringSelection(sb.toString());
+		clip.setContents(ss, ss);
+	}
+
+	/*.................................................................................................................*/
+	NameReference historyRef = NameReference.getNameReference("ChangeHistory");
+	/** Marks the data for character ic, taxon it as having changed*/
+	public void stampHistoryChange(int ic, int it) {
+		if (ic<0 || ic>=numChars || it<0 || it>=numTaxa || suppressHistoryStamp>0) { //|| MesquiteTrunk.currentAuthor == null
+			return;
+		}
+		else {
+			if (changedSinceSave!=null && !(ic<0 || ic>=changedSinceSave.length || it<0 || changedSinceSave[ic]==null || it>=changedSinceSave[ic].length))
+				changedSinceSave[ic][it] = true;
+			notifyOfChangeLowLevel(MesquiteListener.DATA_CHANGED, ic, it, 0);  
+			checksumValid = false;
+			//if (watchForChange)
+			//MesquiteMessage.warnProgrammer("SHC " + ic + " " + it);
+			watchForChange = false;
+			if (saveChangeHistory){ //|| MesquiteTrunk.currentAuthor == null
+				ChangeHistory history = (ChangeHistory)getCellObject(historyRef, ic, it);
+				ChangeEvent ce = null;
+				StringBuffer sb = new StringBuffer();
+				statesIntoStringBuffer(ic, it, sb, false);
+				long baseTime = MesquiteTrunk.startupTime;
+				if (getProject() != null)
+					baseTime  = getProject().startupTime;
+				if (history != null) {
+					if (!history.timeExists(baseTime)) {
+						ce = history.addEvent(MesquiteModule.author, baseTime, sb.toString()); //MesquiteTrunk.currentAuthor
+					}
+					else {
+						ce = history.updateEvent(MesquiteModule.author, baseTime, sb.toString()); //MesquiteTrunk.currentAuthor
+					}
+				}
+				else {
+					ChangeHistory cH = new ChangeHistory();
+					ce = cH.addEvent(MesquiteModule.author, baseTime, sb.toString());
+					setCellObject(historyRef, ic, it, cH);
+				}
+				stampLastModifiedAuthor();
+				if (ce !=null && requireChangeAuthority){ 
+					if (currentChangeAuthority == null){//no ChangeAuthority on record
+						String s = MesquiteString.queryString(MesquiteFrame.activeWindow.getMesquiteWindow(), "Authority", "On what authority do you change these data?", "I said so");
+						ChangeAuthority ca = new ChangeAuthority();
+						if (s == null)
+							s = "I said so";
+						ca.set(s);
+						currentChangeAuthority = ca; //this is to be reset to null before an independent change is made.
+						//NOTE:  it is assumed this change will be fully done when notifyListeners is called
+						//(Such a convention is a bit delicate, but seems best at moment)
+					}
+					ce.setAuthority(currentChangeAuthority);
+				}
+			}
+		}
+	}
+
+	public void stampHistoryChange() {
+		if (changedSinceSave!=null)
+			for (int ic = 0; ic<getNumChars(); ic++)
+				for (int it = 0; it<numTaxa; it++)
+					changedSinceSave[ic][it] = true;
+	}
+
+	/*.................................................................................................................*/
+	/** checks to see if the Notification that what's changed is a single cell */
+	public boolean singleCellChange(Notification notification) {
+		if (notification==null)
+			return false;
+		int code = notification.getCode();
+		if (code==MesquiteListener.DATA_CHANGED && notification.subcodesContains(MesquiteListener.SINGLE_CELL))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** checks to see if the Notification that what's changed is a simple shifting of the entire block of cells from first applicable to last */
+	public boolean onlyAllCellsShifted(Notification notification) {
+		if (notification==null)
+			return false;
+		int code = notification.getCode();
+		if (code==MesquiteListener.DATA_CHANGED && notification.subcodesContains(MesquiteListener.ALL_CELLS_ONLY_SHIFTED))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** checks to see if the Notification that what's changed is state substitution for a single cell */
+	public boolean singleCellSubstitution(Notification notification) {
+		if (notification==null)
+			return false;
+		int code = notification.getCode();
+		if (code==MesquiteListener.DATA_CHANGED && notification.subcodesContains(MesquiteListener.SINGLE_CELL) && notification.subcodesContains(MesquiteListener.CELL_SUBSTITUTION))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** checks to see if the Notification that what's changed is changes in cell content for a single taxon.  Does not include addition subtraction of characters*/
+	public boolean singleTaxonCellChanges(Notification notification) {
+		if (notification==null)
+			return false;
+		int code = notification.getCode();
+		if (code==MesquiteListener.DATA_CHANGED && (notification.subcodesContains(MesquiteListener.SINGLE_CELL)||notification.subcodesContains(MesquiteListener.SINGLE_TAXON)))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** checks to see if the Notification that what's changed is changes in a single taxon.  Does not include addition subtraction of characters*/
+	public boolean singleTaxonChange(Notification notification) {
+		if (notification==null)
+			return false;
+		int code = notification.getCode();
+		if (code==MesquiteListener.DATA_CHANGED && (notification.subcodesContains(MesquiteListener.SINGLE_TAXON)))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void doAfterNotify(Notification notification){
+		currentChangeAuthority = null;
+	}
+	/*.................................................................................................................*/
+	/** compares checksum arrays, and if requested gives warnings.  Returns whether or not the arrays check as the same **/
+	public boolean compareChecksums(long[] before, long[] after, boolean givewarnings, String operationName){
+		if (before == null || after == null || before.length != after.length){
+			if (givewarnings) {
+				MesquiteMessage.printStackTrace("Stack trace");
+				MesquiteTrunk.mesquiteTrunk.reportableAlert( "WARNING: checksum failed during " + operationName + " because checksum arrays not matching sizes or null.", "");
+			}
+			return false;
+		}
+		String problemFound = "";
+		int mostSeriousProblemFound = NUMCSC;
+		for (int i=0; i<before.length; i++){
+			if (before[i] != after[i]) {
+				if (givewarnings){
+					problemFound = Integer.toString(i) + " ";
+					if (i<mostSeriousProblemFound)
+						mostSeriousProblemFound = i;
+				}
+			}
+		}
+		if (problemFound.length()>0){
+			MesquiteMessage.printStackTrace("Stack trace");
+			MesquiteTrunk.mesquiteTrunk.reportableAlert( "WARNING: " + operationName + " appears to have damaged the integrity of the data matrix or its associated information.  Make sure you have a backup copy of your data file!!!!", "[Problems found: " + problemFound + "]");
+			return false;
+		}
+		return true;
+	}
+
+	static final int CS_Overall = 0;
+	static final int CS_CellStates = 1;
+	static final int CS_CORE = 1;
+	static final int CS_SpecsSets = 2;
+	static final int CS_CAssocLong = 3;
+	static final int CS_CAssocBits = 4;
+	static final int CS_CAssocDoubles = 5;
+	static final int CS_CAssocObjects = 6;
+	static final int CS_CellObjects = 7;
+	static final int CS_UNCLEAR = 7;
+	static final int CS_MName = 8;
+	static final int CS_MAnnot = 9;
+	static final int CS_CNames = 10;
+	static final int CS_CAnnots = 11;
+	static final int CS_CSelected = 12;
+	static final int CS_CellFootnotes = 13;
+	static final int CS_CellObjectsDisp = 14;
+	static final int CS_ChangedSinceSave = 15;
+	static final int CS_CharIllustr = 16;
+	static final int CS_COSMETIC = 16;
+	static final  int NUMCSC = 17;
+	/*.................................................................................................................*/
+	/** calculates a full checksum on all aspects of the matrix, including char names and specsets, done in order of character ids.
+ 	Returned as array so that in future can give checksums on various components independently.  
+ 	Should call compareChecksums to compare arrays and issue warnings */
+	public long[] getIDOrderedFullChecksum(){
+		//finding character ordering according to id's
+		long[] tempIDs = new long [charIDs.length];
+		int[] tempNums = new int[charIDs.length];
+		for (int i=0; i<charIDs.length; i++){
+			tempIDs[i] = charIDs[i];
+			tempNums[i] = i;
+		}
+		for (int i=1; i<tempIDs.length; i++) {  //sorting the id's
+			for (int j= i-1; j>=0 && tempIDs[j]>tempIDs[j+1]; j--) {
+				long temp = tempIDs[j];
+				tempIDs[j] = tempIDs[j+1];
+				tempIDs[j+1]=temp;
+				int tempI = tempNums[j];
+				tempNums[j] = tempNums[j+1];
+				tempNums[j+1]=tempI;
+			}
+		}
+		/**/
+		CRC32[] components = new CRC32[NUMCSC];
+		for (int i = 0; i<NUMCSC; i++){
+			components[i] = new CRC32();
+			components[i].reset();
+		}
+		//CRC32 checksum = components[CS_Overall];
+		StringBuffer sb = new StringBuffer(20);
+		//checksum.reset();
+		//updateChecksum(checksum, getName());   //MName  Cosmetic
+		updateChecksum(components[CS_MName], getName());   //MName  Cosmetic
+		//updateChecksum(checksum, getAnnotation()); //MAnnot  Cosmetic
+		updateChecksum(components[CS_MAnnot], getAnnotation()); //MAnnot  Cosmetic
+		for (int i = 0; i< tempNums.length; i++){
+			int ic = tempNums[i];
+
+			//calculate portion of sum for character ic
+			if (characterHasName(ic)){
+				//updateChecksum(checksum, getCharacterName(ic)); //CNames  Cosmetic
+				updateChecksum(components[CS_CNames], getCharacterName(ic)); //CNames  Cosmetic
+			}
+			//updateChecksum(checksum, getAnnotation(ic)); //CAnnots  Cosmetic
+			updateChecksum(components[CS_CAnnots], getAnnotation(ic)); //CAnnots  Cosmetic
+			//updateChecksum(checksum, getSelected(ic)); //CSelected  Cosmetic
+			updateChecksum(components[CS_CSelected], getSelected(ic)); //CSelected  Cosmetic
+
+			int num = getNumberAssociatedLongs();
+			for (int iA = 0; iA<num; iA++){
+				LongArray array = getAssociatedLongs(iA);
+				//	updateChecksum(checksum, array.getValue(ic)); //CAssocLong
+				updateChecksum(components[CS_CAssocLong], array.getValue(ic)); //CAssocLong
+			}
+			num = getNumberAssociatedBits();
+			for (int iA = 0; iA<num; iA++){
+				Bits array = getAssociatedBits(iA);
+				//	updateChecksum(checksum, array.isBitOn(ic)); //CAssocBits
+				updateChecksum(components[CS_CAssocBits], array.isBitOn(ic)); //CAssocBits
+			}
+			num = getNumberAssociatedDoubles();
+			for (int iA = 0; iA<num; iA++){
+				DoubleArray array = getAssociatedDoubles(iA); //CAssocDoubles
+				//	updateChecksum(checksum, array.getValue(ic));
+				updateChecksum(components[CS_CAssocDoubles], array.getValue(ic));
+			}
+			num = getNumberAssociatedObjects();
+			for (int iA = 0; iA<num; iA++){
+				ObjectArray array = getAssociatedObjects(iA);
+				//	updateChecksum(checksum, array.getValue(ic)); //CAssocObjects
+				updateChecksum(components[CS_CAssocObjects], array.getValue(ic)); //CAssocObjects
+			}
+
+			Vector specsVectors = getSpecSetsVectorVector();
+			if (specsVectors!=null){ //update size of specification sets
+				for (int iv=0; iv<specsVectors.size(); iv++) {
+					SpecsSetVector sv = (SpecsSetVector)specsVectors.elementAt(iv);
+					for (int j=0; j<sv.size(); j++) {
+						SpecsSet css = (SpecsSet)sv.elementAt(j);
+						//	updateChecksum(checksum, css.toString(ic)); //SpecsSets
+						updateChecksum(components[CS_SpecsSets], css.toString(ic)); //SpecsSets
+					}
+					SpecsSet currentSS = sv.getCurrentSpecsSet();
+					if (currentSS!=null) {
+						//	updateChecksum(checksum, currentSS.toString(ic));//SpecsSets
+						updateChecksum(components[CS_SpecsSets], currentSS.toString(ic));//SpecsSets
+					}
+				}
+			}
+
+			if (footnotes!=null){
+				for (int j = 0; j<numTaxa; j++){
+					//	updateChecksum(checksum, footnotes[ic][j]);//CellFootnotes
+					updateChecksum(components[CS_CellFootnotes], footnotes[ic][j]);//CellFootnotes
+				}
+			}
+			if (cellObjects.size()>0){
+				for (int k =0; k<cellObjects.size(); k++){
+					Object2DArray objArray = (Object2DArray)cellObjects.elementAt(k);
+					Object[][] objects = objArray.getMatrix();
+					for (int j = 0; j<numTaxa; j++){
+						//		updateChecksum(checksum, objects[ic][j]);//CellObjects
+						updateChecksum(components[CS_CellObjects], objects[ic][j]);//CellObjects
+					}
+				}
+			}
+			if (cellObjectsDisplay!=null){
+				for (int j = 0; j<numTaxa; j++){
+					//	updateChecksum(checksum, cellObjectsDisplay[ic][j]);//CellObjectsDisp  COSMETIC
+					updateChecksum(components[CS_CellObjectsDisp], cellObjectsDisplay[ic][j]);//CellObjectsDisp  COSMETIC
+				}
+			}
+
+			if (changedSinceSave!=null){
+				for (int j = 0; j<numTaxa; j++){
+					//	updateChecksum(checksum, changedSinceSave[ic][j]);//ChangedSinceSave  COSMETIC
+					updateChecksum(components[CS_ChangedSinceSave], changedSinceSave[ic][j]);//ChangedSinceSave  COSMETIC
+				}
+			}
+			if (characterIllustrations!=null){
+				//	updateChecksum(checksum, characterIllustrations[ic]); //CharIllustr COSMETIC
+				updateChecksum(components[CS_CharIllustr], characterIllustrations[ic]); //CharIllustr COSMETIC
+			}
+
+
+			for (int it=0; it<numTaxa; it++)  {
+				sb.setLength(0);
+				statesIntoStringBuffer(ic, it, sb, true);
+				//	updateChecksum(checksum, sb);  //STATES
+				updateChecksum(components[CS_CellStates], sb);  //STATES
+			}
+
+		}
+		long[] result = new long[NUMCSC];
+		for (int i=0; i<NUMCSC; i++)
+			result[i] = components[i].getValue();
+		return result;
+	}
+
+	static final byte[] nullbytes = "null".getBytes();
+	private void updateChecksum(CRC32  checksum, String i){
+		if (i == null)
+			checksum.update(nullbytes);
+		else
+			checksum.update(i.getBytes());
+	}
+	private void updateChecksum(CRC32  checksum, long i){
+		updateChecksum(checksum, Long.toString(i));
+	}
+	private void updateChecksum(CRC32  checksum, Object i){
+		if (i == null)
+			checksum.update(nullbytes);
+		else
+			updateChecksum(checksum, i.toString());
+	}
+	private void updateChecksum(CRC32  checksum, double i){
+		updateChecksum(checksum, Double.toString(i));
+	}
+	private void updateChecksum(CRC32  checksum, boolean i){
+		if (i)
+			updateChecksum(checksum, "true");
+		else
+			updateChecksum(checksum, "false");
+	}
+	/*.................................................................................................................*/
+	public static int getCurrentChecksumVersion(){
+		return 3;
+	}
+	/*.................................................................................................................*/
+	public long getChecksumForFileRecord(int version){
+		//if (checksumValid)  deleted dec 09 to ensure checksum up to date for file saving
+		//	return rememberedChecksum;
+
+		rememberedChecksum = calculateChecksum(crc32, version);
+		checksumValid = true;
+		return rememberedChecksum;
+	}
+	/*.................................................................................................................*/
+	public String getChecksumSummaryString(){
+		return "numChars = " + getNumChars();
+	}
+	/*.................................................................................................................*/
+	public long getChecksum(){
+		if (checksumValid)
+			return rememberedChecksum;
+
+		rememberedChecksum = calculateChecksum(crc32);
+		checksumValid = true;
+		return rememberedChecksum;
+	}
+	/*.................................................................................................................*/
+	public long calculateChecksum(CRC32 crc32, int version){
+		return calculateChecksum(crc32);
+	}
+	/*.................................................................................................................*/
+	public abstract long calculateChecksum(CRC32 crc32);
+
+	/*.................................................................................................................*/
+	public boolean isUserVisible() {
+		return userVisible;
+	}
+	public void setUserVisible(boolean userVisible) {
+		this.userVisible = userVisible;
+	}
+	/*.................................................................................................................*/
+	public boolean isLocked() {
+		return locked;
+	}
+	public void setLocked(boolean locked) {
+		this.locked = locked;
+	}
+	/*.................................................................................................................*/
+	public boolean getEditorInhibition(){
+		return inhibitEditor || locked;
+	}
+	/*.................................................................................................................*/
+	public void setEditorInhibition(boolean i){
+		inhibitEditor = i;
+	}
+	/*.................................................................................................................*/
+	protected void setDirty(boolean d, int ic, int it){
+		setDirty(d); 
+		stampHistoryChange(ic, it);
+		calculateFirstLastApplicable(it);
+	}
+	/*.................................................................................................................*/
+	public boolean someApplicableInTaxon(int it, boolean countMissing){
+		return  getNumberApplicableInTaxon(it,countMissing)>0;
+	}
+	/*.................................................................................................................*/
+	public int numTaxaWithSomeApplicable(boolean countMissing){
+		int count = 0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (someApplicableInTaxon(it,countMissing))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int numSelectedTaxaWithSomeApplicable(boolean countMissing){
+		int count = 0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (taxa.getSelected(it) && someApplicableInTaxon(it,countMissing))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int numSelectedTaxa(){
+		int count = 0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (taxa.getSelected(it))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int getNumberApplicableInTaxon(int it, boolean countMissing){
+		int count = 0;
+		for (int i = 0; i<numChars; i++) {
+			if (!isInapplicable(i,it))
+				if (!isUnassigned(i, it) || countMissing)
+					count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int nextApplicable(int it, int ic, boolean countMissing){
+		for (int i = ic; i<numChars; i++) {
+			if (!isInapplicable(i,it))
+				if (!isUnassigned(i, it) || countMissing)
+					return i;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	public int prevApplicable(int it, int ic, boolean countMissing){
+		for (int i = ic; i>=0; i--) {
+			if (!isInapplicable(i,it))
+				if (!isUnassigned(i, it) || countMissing)
+					return i;
+		}
+		return -1;
+	}
+
+	/*.................................................................................................................*/
+	/** gets the explanation of this matrix*/
+	public String getExplanation() {
+		if (taxa == null)
+			return null;
+		String lastModAuthor = getLastModifiedAuthor();
+		if (lastModAuthor == null)
+			lastModAuthor = "";
+		else
+			lastModAuthor = " (Last modified by " + lastModAuthor + ")";
+		String extra = "This character matrix" + lastModAuthor + " for the taxa block \"" + taxa.getName() + "\" has " + getNumChars() + " characters for the " + getNumTaxa() + " taxa. Category of data: " + getDataTypeName() + "\n";
+		return extra;
+
+	}
+	/*.................................................................................................................*/
+	/** sets the illustration tied to character ic to the given Image at the given path (URL path or file path)*/
+	public void setIllustration(int ic, Image illustration, String path) {
+		if (ic<0 || ic>=numChars) {
+			MesquiteMessage.println("Error: character number out of bounds (setIllustration) " + ic);
+		}
+		else {
+			if (characterIllustrations==null) {
+				characterIllustrations = new Image[numChars];
+				characterIllustrationPath = new String[numChars];
+			}
+			characterIllustrations[ic] = illustration;
+			characterIllustrationPath[ic] = path;
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns the path of the illustration tied to character ic*/
+	public String getIllustrationPath(int ic) {
+		if (ic<0 || ic>=numChars) {
+			MesquiteMessage.println("Error: character number out of bounds (getIllustrationPath) " + ic);
+			return null;
+		}
+		else if (characterIllustrationPath != null)
+			return characterIllustrationPath[ic] ;
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** returns the illustration tied to character ic*/
+	public Image getIllustration(int ic) {
+		if (ic<0 || ic>=numChars) {
+			MesquiteMessage.println("Error: character number out of bounds (getIllustration) " + ic);
+			return null;
+		}
+		else if (characterIllustrations != null)
+			return characterIllustrations[ic] ;
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns a string describing the contents of the cells (by default, null, but may be overridden to convey
+ 	special information, such as what are the items in a continuous data matrix)*/
+	public String getCellContentsDescription(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** outputs to log file the matrix*/
+	public abstract void logMatrix();
+	/*.................................................................................................................*/
+	/*(LOCKING SYSTEM NOT READY)
+ 	 // locks data
+	public void lockData() {
+		locked = true;
+	}
+ 	//unlocks data
+	public void unlockData() {
+		locked = false;
+	}
+ 	/*.................................................................................................................*/
+	private boolean addDataLinkage(CharacterData other){
+		if (other==null)
+			return false;
+		if (other.getTaxa()!=getTaxa())
+			return false;
+		if (other.getNumChars() != numChars)
+			return false;
+		if (other == this)
+			return false;
+		if (linkedDatas.indexOf(other)>=0)
+			return false;
+		linkedDatas.addElement(other);
+		return true;
+	}
+	private void removeDataLinkage(CharacterData other){
+		if (other==null)
+			return;
+		if (linkedDatas == null)
+			return;
+		linkedDatas.removeElement(other);
+	}
+	/** Adds the passed Character data into this's linkage group */
+	public void addToLinkageGroup(CharacterData other){
+		if (other==null)
+			return;
+		if (linkedDatas == null)
+			return;
+		other.getDataLinkages().removeAllElements();
+		//mutually link other to all of linked ones
+		for (int i=0; i<linkedDatas.size(); i++){
+			CharacterData d= (CharacterData)linkedDatas.elementAt(i);
+			other.addDataLinkage(d);
+			d.addDataLinkage(other);
+		}
+		//mutually link other to this
+		addDataLinkage(other);
+		other.addDataLinkage(this);
+	}
+	/** Removes this Character data from its linkage group */
+	public void resignFromLinkageGroup(){
+		if (linkedDatas == null)
+			return;
+		//cut out of all linked ones
+		for (int i=0; i<linkedDatas.size(); i++){
+			CharacterData d= (CharacterData)linkedDatas.elementAt(i);
+			d.removeDataLinkage(this);
+		}
+		linkedDatas.removeAllElements();
+	}
+	public Vector getDataLinkages(){
+		return linkedDatas;
+	}
+	public boolean isLinked(CharacterData other){
+		if (linkedDatas == null)
+			return false;
+		return (other!=null && linkedDatas.indexOf(other)>=0);
+	}
+	public boolean isLinked(){
+		if (linkedDatas == null)
+			return false;
+		return (linkedDatas.size()>0);
+	}
+	/*------------------*/
+	public boolean concatenate(CharacterData oData, boolean addTaxaIfNew, boolean explainIfProblem, boolean notify){
+		return concatenate(oData, addTaxaIfNew, true, false, false, explainIfProblem,notify);
+	}
+
+	/** Concatenates the CharacterData oData to this object. */
+	public boolean concatenate(CharacterData oData, boolean addTaxaIfNew, boolean concatExcludedCharacters, boolean adjustGroupLabels, boolean prefixGroupNamesIfAlreadyAssigned, boolean explainIfProblem, boolean notify){
+		if (oData==null)
+			return false;
+		if (oData.isLinked(this) || isLinked(oData)) {
+			if (explainIfProblem)
+				discreetAlert( "Sorry, those two matrices cannot be concatenated because they are linked");
+			return false;
+		}
+		if (!((getClass().isAssignableFrom(oData.getClass())) || oData.getClass() == getClass())){
+			if (explainIfProblem)
+				discreetAlert( "Sorry, those two matrices cannot be concatenated because they are of different types");
+			return false;
+		}
+		CommandRecord.tick("Concatenating matrices");
+		MesquiteModule module = MesquiteTrunk.mesquiteTrunk;
+		if (getManager() != null)
+			module = ((MesquiteModule)getManager());
+		if (!oData.getTaxa().equals(getTaxa(), true, true)){
+			Taxa oTaxa = oData.getTaxa();
+			Taxa taxa = getTaxa();
+			boolean extra = false;
+			for (int oit = 0; oit<oTaxa.getNumTaxa() && !extra; oit++)
+				if (taxa.findEquivalentTaxon(oTaxa, oit)<0)
+					extra = true;
+			//different taxa block, with different names.  Offer to add names
+			if (extra && addTaxaIfNew){
+				if (AlertDialog.query(module.containerOfModule(), "Import taxa from other matrix?", "The matrix you are concatenating to this one is based on a different block of taxa, and includes taxa not in this matrix.  Do you want to add these taxa to this matrix before concatenating?")){
+					String names = "";
+
+					for (int oit = 0; oit<oTaxa.getNumTaxa(); oit++){
+						if (taxa.findEquivalentTaxon(oTaxa, oit)<0){
+							taxa.addTaxa(taxa.getNumTaxa(), 1, false);
+							taxa.equalizeTaxon(oTaxa, oit, taxa.getNumTaxa()-1);
+							names += taxa.getTaxonName(taxa.getNumTaxa()-1) + "\n";
+							CommandRecord.tick("Added taxon " + taxa.getTaxonName(taxa.getNumTaxa()-1));
+
+						}
+					}
+					if (!StringUtil.blank(names)){
+						logln("Added to taxa block were:\n" + names);
+						taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null,null));
+					}
+				}
+			}
+
+		}
+		int origNumChars = getNumChars();
+		if (concatExcludedCharacters)
+			addParts(origNumChars+1, oData.getNumChars());
+		else 
+			addParts(origNumChars+1, oData.numCharsCurrentlyIncluded());
+		CharacterPartition partition = (CharacterPartition) getCurrentSpecsSet(CharacterPartition.class);   // partition of this object
+		CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		CharactersGroup group = null;  //see if one with prefix already exists
+		if (partition==null && origNumChars-1>=0){ // let's give the original ones a group, as they didn't have any before
+			group = groups.findGroup(getName());  //let's see if there already exists a group with this matrix name
+			if (group==null)
+				setToNewGroup(getName(), 0, origNumChars-1, module);  //set group
+			else
+				setCurrentGroup(group,0, origNumChars-1, module);  
+		}
+		CharacterPartition oPartition = (CharacterPartition) oData.getCurrentSpecsSet(CharacterPartition.class);   // partition in incoming. This by default will be used.
+		if (oPartition == null){
+			group = groups.findGroup(oData.getName());  //let's see if there already exists a group with this matrix name
+			if (group==null)
+				setToNewGroup(oData.getName(), origNumChars, getNumChars()-1, module);  //set group
+			else
+				setCurrentGroup(group,origNumChars, getNumChars()-1, module);   //set group
+		}
+
+		addInLinked(getNumChars()+1, oData.getNumChars(), true);
+
+		CharacterState cs = null;
+		int count=0;
+		for (int ic = 0; ic<oData.getNumChars(); ic++){
+			if (concatExcludedCharacters || oData.isCurrentlyIncluded(ic)) {
+				CommandRecord.tick("Copying character " + (ic+1) + " in concatenation");
+				equalizeCharacter(oData, ic, count+origNumChars);
+				count++;
+			}
+		}
+
+		if (oPartition != null && adjustGroupLabels)
+			adjustGroupLabels(oData.getName(), origNumChars, getNumChars()-1, true, prefixGroupNamesIfAlreadyAssigned, module);  //there exists a partition in the incoming, so just redo the names for the groups there.
+
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {origNumChars, oData.getNumChars()}));
+		return true;
+	}
+	/*------------------*/
+	public void setBasisTree(Tree tree){
+		if (tree == null) {
+			basisTree = null;
+		}
+		else {
+			basisTree = tree.cloneTree();
+		}
+	}
+	public Tree getBasisTree(){
+		return basisTree;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Image getHImage(){
+		return null;
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public Color getHColor(){
+
+		return ColorTheme.getInterfaceBackground();  //project color
+	}
+	/* ---------------- for HNode interface ----------------------*/
+	public boolean getHShow(){
+		return true; 
+	}
+	/* ---------------- for use with touched from HNode interface ----------------------*/
+	public void addToBrowserPopup(MesquitePopup popup){
+		super.addToBrowserPopup(popup);
+		ElementManager manager = getManager();
+		if (manager!=null && manager instanceof MesquiteModule) {
+			MesquiteFile file = getFile();
+			if (file!=null && file.getProject()!=null) {
+				popup.add(new MenuItem("-"));
+				popup.add(new MesquiteMenuItem("Show List of Characters of \"" + getName() + "\"", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("showCharacters", (MesquiteModule)manager), getFile().getProject().getCharMatrixReferenceInternal(this)));
+				popup.add(new MesquiteMenuItem("Show Matrix Editor for \"" + getName() + "\"", MesquiteTrunk.mesquiteTrunk, MesquiteTrunk.mesquiteTrunk.makeCommand("showDataWindow", (MesquiteModule)manager), getFile().getProject().getCharMatrixReferenceInternal(this)));
+			}
+		}
+	}
+
+	public MesquiteModule showMatrix(){
+		if (getManager() != null && getFile() != null) {
+			return (MesquiteModule)((Commandable)getManager()).doCommand("showDataWindow", getFile().getProject().getCharMatrixReferenceInternal(this), CommandChecker.defaultChecker);
+		}
+		return null;
+	}
+	public void showList(){
+		if (getManager() != null && getFile() != null) 
+			((Commandable)getManager()).doCommand("showCharacters", getFile().getProject().getCharMatrixReferenceInternal(this), CommandChecker.defaultChecker);
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		if (temp == null)
+			temp = new Snapshot();
+		if (getEditorInhibition()){
+			temp.addLine("inhibitEditing");
+		}
+		if (!isUserVisible())
+			temp.addLine("setHidden");
+		if (temp.getNumLines() == 0)
+			return null;
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets editor inhibition", null, commandName, "inhibitEditing")) {
+			setEditorInhibition(true);
+		}
+		else if (checker.compare(this.getClass(), "Sets editor inhibition to false", null, commandName, "uninhibitEditing")) {
+			setEditorInhibition(false);
+		}
+		else if (checker.compare(this.getClass(), "Sets user visibility to false", null, commandName, "setHidden")) {
+			setUserVisible(false);
+		}
+		else if (checker.compare(this.getClass(), "Sets user visibility to true", null, commandName, "setVisible")) {
+			setUserVisible(true);
+		}
+		else if (checker.compare(this.getClass(), "Duplicates the matrix", null, commandName, "duplicateMe")) {
+			if (getProject() != null)
+				getProject().incrementProjectWindowSuppression();
+
+			CharacterData starter = makeCharacterData(getMatrixManager(), getTaxa());  
+			if (getMatrixManager() != null)
+				starter.addToFile(getProject().getHomeFile(), getProject(),  getMatrixManager().findElementManager(CharacterData.class));  
+
+			boolean success = starter.concatenate(this, false, true, false, false, false, false);
+			if (success){
+				String name = getName() + " (duplicate)";
+				if (getProject()!= null)
+					name = getProject().getCharacterMatrices().getUniqueName(name);
+				starter.setName(name);
+			}
+			if (getProject() != null)
+				getProject().decrementProjectWindowSuppression();
+			return starter;
+		}
+		else if (checker.compare(this.getClass(), "Exports the matrix", null, commandName, "exportMe")) {
+			ElementManager manager = getManager();
+			if (manager!=null) {
+				((Commandable)manager).doCommand("exportMatrix", getFile().getProject().getCharMatrixReferenceInternal(this), CommandChecker.defaultChecker);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	public String toString(){
+		return getDataTypeName() + "\"" + getName() + "\" : " + getNumTaxa(false) + " taxa " + getNumChars(false) + " characters (id " + getID() +")";
+	}
+	public String toHTMLStringDescription(){
+		//String s = "<li>Character Matrix: <strong>" + getName() + "</strong> (" + getDataTypeName() + ").  Number of characters: " + getNumChars() + ".  (<a href =\"showMatrix:" + getID() + "\">View & Edit</a>)  (<a href =\"listMatrix:" + getID() + "\">List & Manage</a>) (<a href =\"chartCharacters:" + getID() + "\">Chart Characters</a>) (<a href =\"renameMatrix:" + getID() + "\">Rename</a>)  (<a href =\"editCommentMatrix:" + getID() + "\">Edit Comment</a>)  (<a href =\"deleteMatrix: [...]
+		String s = "<li>Character Matrix: <strong>" + getName() + "</strong> (" + getDataTypeName() + ").  Number of characters: " + getNumChars() + ". ";
+		String comment = getAnnotation();
+		if (!StringUtil.blank(comment))
+			s+= "<br><font color=\"#777777\">" + comment + "</font>";
+		if (HTMLDescribable.verbose){
+			String st = super.toHTMLStringDescription();
+			if (!StringUtil.blank(st))
+				return s + "<ul>" + st + "</ul></li>";
+		}
+		return s + "</li>";
+	}
+
+	public String[] toStringsContig(boolean includeInapplicable){
+		String[] s = new String[getNumTaxa()];
+		StringBuffer sb = new StringBuffer(getNumChars());
+		for (int it= 0; it<getNumTaxa(); it++){
+			for (int ic = 0; ic<getNumChars(); ic++){
+				statesIntoStringBuffer(ic, it,  sb, true, includeInapplicable, true);
+			}
+			s[it] = sb.toString();
+			sb.setLength(0);
+		}
+		return s;
+
+	}
+
+	public boolean setInclusionExclusion(MesquiteModule module, MesquiteTable table, boolean include){
+		boolean changed=false;
+		if (table !=null) {
+
+			CharInclusionSet inclusionSet = (CharInclusionSet) getCurrentSpecsSet(CharInclusionSet.class);
+			if (inclusionSet == null) {
+				inclusionSet= new CharInclusionSet("Inclusion Set", getNumChars(), this);
+				inclusionSet.selectAll();
+				inclusionSet.addToFile(getFile(), getProject(), module.findElementManager(CharInclusionSet.class)); //THIS
+				setCurrentSpecsSet(inclusionSet, CharInclusionSet.class);
+			}
+			if (inclusionSet != null) {
+				for (int i=0; i<getNumChars(); i++) {
+					if (table.wholeColumnSelectedAnyWay(i) || table.isRowNameSelected(i)) {
+						if (include) //include
+							inclusionSet.setSelected(i, true);
+						else if (!include) //exclude
+							inclusionSet.setSelected(i, false);
+						changed = true;
+					}
+				}
+			}
+
+
+			if (changed)
+				notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+		}
+		return changed;
+	}
+
+	public int getTotalNumApplicable(int it, boolean ignoreExcluded) {
+		CharInclusionSet incl = null;
+		if (ignoreExcluded)
+			incl = (CharInclusionSet)getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = getNumChars();
+		int seqLen = 0;
+		if (numChars != 0) {
+			CharacterState cs = null;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){  // adjusted 2. 01 to consider inclusion
+					cs = getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable())
+						seqLen++;
+				}
+			}
+		}	
+		return seqLen;
+
+	}
+
+	public String getNameOfCellEntry(int number){
+		if (number==1)
+			return "entry";
+		else
+			return "entries";
+	}
+
+	/*..........................................CharacterData.....................................*/
+	/**merges the states for taxon it2 into it1  within this Data object */
+	public  boolean mergeSecondTaxonIntoFirst(int it1, int it2) {
+		if ( it1<0 || it1>=getNumTaxa() || it2<0 || it2>=getNumTaxa() )
+			return false;
+
+		boolean mergedAssigned = false;
+		CharacterState cs1= null;
+		CharacterState cs2= null;
+		for (int ic=0; ic<getNumChars(); ic++) {
+			cs1 = getCharacterState(cs1, ic,it1);
+			cs2 = getCharacterState(cs2, ic,it2);
+			if (cs1.isCombinable() && cs2.isCombinable()){ //both have states; just leave first state as is
+				mergedAssigned = true;
+			}
+			else if (cs1.isCombinable()){  // taxon 1 has state but not taxon 2; just use first
+			}
+			else if (cs2.isCombinable()){  // taxon 2 has state but not taxon 1; just use second
+				setState( ic, it1, cs2);
+			}
+			else {
+				setToUnassigned( ic, it1);
+			}
+		}
+		return mergedAssigned;
+	}
+	/*..........................................CharacterData.....................................*/
+	/**merges the states for the taxa recorded in taxaToMerge into taxon it  within this Data object.  
+	 * Returns a boolean array of which taxa had states merged  (i.e. something other than 
+	 * unassigned + assigned or inapplicable + assigned */
+	public boolean[] mergeTaxa(int sinkTaxon, boolean[]taxaToMerge) {
+		if (!(MesquiteInteger.isCombinable(sinkTaxon)) || sinkTaxon<0 || sinkTaxon>=getNumTaxa() || taxaToMerge==null)
+			return null;
+		boolean[] mA = new boolean[taxaToMerge.length];
+		boolean mergedAssigned = false;
+		boolean firstHasData = hasDataForTaxon(sinkTaxon);
+		for (int it=0; it<getNumTaxa() && it<taxaToMerge.length; it++) {
+			if (it!=sinkTaxon && taxaToMerge[it]){
+				boolean mergingHadData = hasDataForTaxon(it);
+				boolean ma = mergeSecondTaxonIntoFirst(sinkTaxon, it);
+				if (mergingHadData && ! firstHasData){
+					//in this case tInfo brought in from merging.  This isn't ideal, as should fuse tInfo if both have data
+					Associable a = getTaxaInfo(false);
+					if (a != null)
+						a.swapParts(sinkTaxon, it);
+				}
+				mA[it] = ma;   
+				mergedAssigned = mergedAssigned | ma;
+
+			}
+		}
+		if (mergedAssigned)
+			return mA;
+		else
+			return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharacterDistribution.java b/Source/mesquite/lib/characters/CharacterDistribution.java
new file mode 100644
index 0000000..818dd6e
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterDistribution.java
@@ -0,0 +1,53 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003*/
+
+
+/* ======================================================================== */
+/** Stores the states in the terminal taxa.  Often passed to calculations routines so that they can count steps, likelihood, reconstruct ancestral states,
+and so on.  See general discussion of character storage classes under CharacterState*/
+public interface CharacterDistribution extends CharacterStatesHolder {
+	
+	/** returns a CharacterDistribution that is adjustable and has the same states*/
+	public AdjustableDistribution getAdjustableClone();
+	
+	/** Adjusts the size of the passed CharacterHistory to be of the same type as this CharacterHistory and to be prepared
+	to store states for each of the nodes of the tree.*/
+	public  CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates);
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data*/
+	public boolean hasMissing ();
+	/**Returns whether or not the character has missing (unassigned) data in the taxa of the tree*/
+	public boolean hasMissing(Tree tree, int node);
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps)*/
+	public boolean hasInapplicable();
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps) in the taxa of the tree*/
+	public boolean hasInapplicable(Tree tree, int node);
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same)*/
+	public boolean isConstant();
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	public boolean isConstant(Tree tree, int node);
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/lib/characters/CharacterHistory.java b/Source/mesquite/lib/characters/CharacterHistory.java
new file mode 100644
index 0000000..b872e4e
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterHistory.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+
+/* ======================================================================== */
+/**Stores the states at all the nodes of a tree.  Has methods to set and get the character states, and to survey the assigned
+states to determine the colors that could be used for character tracing. Often returned by modules reconstructing ancestral states. 
+  See general discussion of character storage classes under CharacterState*/
+public interface CharacterHistory extends AdjustableDistribution, Explainable{
+
+	/** surveys states at nodes to prepare use of getColorsAtNode. */
+	public void prepareColors(Tree tree, int drawnRoot);
+
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable);
+	
+	/** places into the already instantiated ColorDistribution the colors at the node, and returns the number of colors.  Uses default colors. 
+		showWeights for indicates whether weights of states (e.g. frequencies or likelihoods for categorical states) are displayed or indicated
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass).*/
+	//public int getColorsAtNode(int node, ColorDistribution colors, int mode, boolean showWeights);
+	/** places into the already instantiated ColorDistribution the colors at the node, and returns the number of colors.  Uses color table passed.*/
+	public int getColorsAtNode(int node, ColorDistribution colors, MesquiteColorTable stateColors, boolean showWeights);
+	
+	/** returns the vector of ColorEvents in order, e.g. for stochastic character mapping.  Return null if none */
+	public ColorEventVector getColorSequenceAtNode(int node, MesquiteColorTable stateColors);
+	
+	/** places into the already instantiated ColorDistribution the colors corresponding to the CharacterState, and returns the number of colors.  Uses default colors. 
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*/
+	public int getColorsOfState(CharacterState state, ColorDistribution colors, MesquiteColorTable stateColors);
+	/** gets colors and statesnames of states in reconstruction.  For continuous types may break down into ranges of states
+			Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*
+	public int getLegendStates(Color[] cs, String[] stateNames, int mode);
+	/** gets colors and statesnames of states in reconstruction.  For continuous types may break down into ranges of states.*/
+	public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors);
+	
+	/** clones given CharacterHistory.  May be used to generate a similar object without reference to subclass*/
+	public CharacterHistory clone(CharacterHistory s);
+	
+	/** for MPRs, etc., gets the ith resolution of the history */
+	public CharacterHistory getResolution(Tree tree, CharacterHistory resultStates, long i);
+	/** for MPRs, etc., gets the number of resolutions of the history */
+	public long getNumResolutions(Tree tree);
+	
+	/** Returns a new object indicating the states at the tips (used whether or not History is reconstruction)*/
+	public CharacterDistribution getStatesAtTips(Tree tree);
+
+	/** Returns the observed states in the terminal taxa (used if History is reconstruction)*/
+	public CharacterDistribution getObservedStates();
+	/** Sets the states in the terminal taxa (used if History is reconstruction)*/
+	public void setObservedStates(CharacterDistribution observed);
+		
+	/** Adjusts the size of this to store states for each of the terminal taxa.*/
+	public CharacterHistory adjustSize(Tree tree);
+	/*======*/
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharacterModel.java b/Source/mesquite/lib/characters/CharacterModel.java
new file mode 100644
index 0000000..e3f53cc
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterModel.java
@@ -0,0 +1,390 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  May 2000 */
+/* ======================================================================== */
+/** Models of character evolution are represented by objects of subclasses of CharacterModel.  
+Subclasses include parsimony and probability models, which in turn may be subclassed for particular types of data (e.g. CategParsimonyModel)
+which in turn may be further subclassed for specific types of model (e.g., step matrix).
+Usually in calculatins, a given MesquiteModule more or less promises to handle any model belonging to a subclass, e.g. any
+stepmatrix.  By having subclasses of subclasses of CharacterModel, modules can indicate they specialize
+on a particular sort of step matrix, eg. symmetrical ones.
+ */
+public abstract class CharacterModel extends FileElement implements CompatibilityChecker, Explainable, MesquiteListener {
+	static int numModels = 0;
+	Class stateClass;
+	Vector listeners;
+	boolean editCancel = false;
+	String stateClassName = "undetermined";
+	boolean builtIn = false;
+	boolean disposed = false;
+	CharacterModel mother = null;
+	boolean allowSubclass = false;
+	boolean userVisible = true;
+	
+	public CharacterModel (String name, Class stateClass) {
+		this.name = name;
+		this.stateClass = stateClass;
+		
+		if (stateClass != null && stateClass != CharacterState.class && CharacterState.class.isAssignableFrom(stateClass)){
+			try {
+				CharacterState s = (CharacterState)stateClass.newInstance();
+				if (s!=null) {
+					stateClassName = s.getDataTypeName();
+				}
+			}
+			catch (IllegalAccessException e){MesquiteTrunk.mesquiteTrunk.alert("iae csmmm");e.printStackTrace(); }
+			catch (InstantiationException e){MesquiteTrunk.mesquiteTrunk.alert("ie csmmm"); e.printStackTrace();}
+		}
+		numModels++;
+		if (name == null)
+			this.name = "Character Model" + numModels;
+	}
+	/*.................................................................................................................*/
+	/* For cloned models used locally, returns the original model from which they were cloned */
+	public CharacterModel getMother(){
+		return mother;
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "charModelSmall.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean isUserVisible() {
+		return userVisible;
+	}
+	public void setUserVisible(boolean userVisible) {
+		this.userVisible = userVisible;
+	}
+/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	return null;
+  	 }
+  	/*.................................................................................................................*/
+ 	/** Performs command (for Commandable interface) */
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+ 		if (checker.compare(this.getClass(), "Edits the character model", null, commandName, "editMe")){
+				ElementManager manager = getManager();
+				if (manager instanceof mesquite.charMatrices.ManageCharModels.ManageCharModels){
+					mesquite.charMatrices.ManageCharModels.ManageCharModels mn = (mesquite.charMatrices.ManageCharModels.ManageCharModels)manager;
+					CharModelCurator curator = mn.findReader(getClass());
+					if (curator==null)
+						mn.discreetAlert("Sorry, no curator module was found for that sort of character model (category: " + getTypeName() + ")");
+					else 
+						curator.showEditor(this);
+				}
+		
+ 	}
+ 	else if (checker.compare(this.getClass(), "Renames the file element", null, commandName, "renameMe")) {
+ 			String s = MesquiteString.queryString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Rename " + getTypeName(), "Rename " + getTypeName() +" \"" + getName() + "\"", getName());
+ 			if (s!=null) {
+ 				setName(s);
+ 				MesquiteWindow.resetAllTitles();
+ 				ElementManager manager = getManager();
+
+ 				if (manager!=null && manager instanceof MesquiteModule)
+ 					((MesquiteModule)manager).resetAllMenuBars();
+ 				else
+ 					MesquiteTrunk.mesquiteTrunk.resetAllMenuBars();
+ 				MesquiteProject proj = getProject();
+				if (proj != null){
+ 					proj.getCentralModelListener().notifyListeners(this, this, new Notification(MesquiteListener.NAMES_CHANGED));
+ 				}
+
+ 			}
+ 		}
+ 		else
+ 			return  super.doCommand(commandName, arguments, checker);
+
+ 		return null;
+ 	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel pm){
+		if (pm == null)
+			return;
+		pm.name = name;
+		pm.stateClass = stateClass;
+		pm.setProject(getProject());
+	}
+ 	/* establish pm as daughter clone, including add listener to know if original changed */
+	public void completeDaughterClone(CharacterModel formerClone, CharacterModel pm){
+		if (pm == null)
+			return;
+		copyToClone(pm);
+		if (formerClone!=null)
+			formerClone.dispose();
+		pm.mother = this;
+		addListener(pm); //so that pm, the daughter clone, can be informed if changes
+	}
+	/*.................................................................................................................*/
+	/** Mother from which cloned has changed*/
+	public void originalChanged(){
+		if (mother == null)
+			return;
+		mother.copyToClone(this);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+	/*.................................................................................................................*/
+	/** must be called for any cloned daughter models when being discarded!!!!*/
+	public void dispose(){
+		CentralModelListener cml = null;
+		disposed = true;
+		if (getProject() !=null)
+			cml = getProject().getCentralModelListener();
+		super.dispose();
+		if (mother !=null)
+			mother.removeListener(this);
+		if (cml !=null)
+			cml.notifyDisposing(this);
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == mother) {
+			originalChanged();
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	public boolean isDisposed(){
+		return disposed;
+	}
+	/*.................................................................................................................*/
+	public boolean getEditCancel() {
+		return editCancel;
+	}
+	/*.................................................................................................................*/
+	public void setEditCancel(boolean cancel) {
+		editCancel = cancel;
+	}
+	/*.................................................................................................................*/
+	public String getTypeName(){
+		return "Character model";
+	}
+
+	/*.................................................................................................................*/
+	public abstract String getModelTypeName();
+
+	/** returns the paradigm (e.g. "parsimony") of the model.  Mostly used for user's information*/
+	public abstract String getParadigm();
+	
+	/** returns the name of the data type (state class) to which this model applies*/
+	public String getStateClassName(){
+		return stateClassName;
+	}
+	/** sets name of model*/
+	public void setName(String name) {
+		this.name = name;
+		if (name == null)
+			this.name = "Character Model" + numModels;
+		//TODO: notify listeners of name change
+	}
+	/** returns name of model*/
+	public String getName() {
+		return name;
+	}
+	
+	/** returns name of model for writing into NEXUS file*/
+	public String getNEXUSName() {
+		return getName();
+	}
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "";
+	}
+	/** returns nexus command introducing this model (e.g. "USERTYPE" or "CHARMODEL")*/
+	public String getNEXUSCommand() {
+		return "CharModel";
+	}
+	/** returns whether or not model is default (unordered, initial Jukes-Cantor; if so, then doesn't need to be written to file*/
+	public boolean isBuiltIn() {
+		return builtIn;
+	}
+	/** returns whether or not model is default (unordered, initial Jukes-Cantor; if so, then doesn't need to be written to file*/
+	public void setBuiltIn(boolean is) {
+		builtIn=is;
+	}
+	
+	/** read the passed string for specification of the model; string may include extraneous information and
+	hence stringPos is passed to indicate at what string position the description (at the start of the modelSpecification in
+	"USERTYPE modelName (modelClassName) =  modelSpecification;"    Format parameter indicates the format of the description, with
+	0 = XML; 1 = public NEXUS; 2 = private Mesquite NEXUS.*/
+	public static final int XMLFormat = 0;
+	public static final int NEXUSFormat = 1;
+	public static final int MesquiteNEXUSFormat = 2;
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+	}
+	
+	/** return string description of model */
+	public String toString (){
+		return getName() + " (model of class " + getTypeName() + ", id " + getID() + ")";
+	}
+	/** return the NEXUS-format string describing the model.  The string begins at the point of the modelSpecification
+	in "USERTYPE modelName (modelClassName) =  modelSpecification;" */
+	public String getNexusSpecification (){
+		return null;
+	}
+	
+	/** return an explanation of the model. */
+	public abstract String getExplanation ();
+	
+	/** Return an explanation of the settings used in calculations (e.g., optimization settings).  These are not the parameters of the model. */
+	public String getSettingsString(){
+		return null;
+	}
+	
+	/** returns subclass of CharacterState to which model can apply (i.e., categorical versus continuous data)*/
+	public Class getStateClass() {  
+		return stateClass;
+	}
+	
+ 	/*.................................................................................................................*/
+	public void allowUseOnDataSubclasses(boolean allow){
+		this.allowSubclass = allow;
+	}
+	/*.................................................................................................................*/
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+ 		return isCompatible(obj, project, prospectiveEmployer, null);
+ 	}
+ 	/*.................................................................................................................*/
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+ 		if (obj instanceof ModelCompatibilityInfo) {
+ 
+ 			Class targetModelSubclass = ((ModelCompatibilityInfo)obj).targetModelSubclass;
+ 			Class targetStateClass =  ((ModelCompatibilityInfo)obj).targetStateClass;
+			boolean c = (targetModelSubclass.isAssignableFrom(getClass()) && (targetStateClass==null || (allowSubclass && getStateClass().isAssignableFrom(targetStateClass)) || (!allowSubclass && getStateClass() == targetStateClass))); //used to allow "is assignable from"
+ 			return c && ((ModelCompatibilityInfo)obj).isCompatible(this, project, prospectiveEmployer); 
+ 		}
+ 		return true;
+ 	}
+ 	/*.................................................................................................................*/
+ 	/** returns whether changes are equalent in both directions, i.e. a change from 0 to 1 costs as much or
+ 	is as probably as a change from 1 to 0.  Default is true; subclasses must override.  Helps modules know if
+ 	rooting of tree matters, for example*/
+	public boolean isReversible() {
+		return true;
+	}
+		
+ 	/*.................................................................................................................*/
+	public static CharacterModel chooseExistingCharacterModel(MesquiteModule m, Class modelClass, String explanation){
+		Listable[] models = m.getProject().getCharacterModels(modelClass, null);
+		if (models ==null || models.length==0)
+			return null;
+		Listable wh = ListDialog.queryList(m.containerOfModule(), "Choose model", explanation, MesquiteString.helpString, models, 0);
+		return (CharacterModel)wh; 
+	}
+	public static CharacterModel chooseExistingCharacterModel(MesquiteModule m, ModelCompatibilityInfo mci, String explanation){
+		Listable[] models = m.getProject().getCharacterModels(mci, null);
+		if (models ==null || models.length==0)
+			return null;
+		String help = "";
+		boolean wizardInEffect = CommandRecord.wizardInEffect();
+		if (wizardInEffect)
+			help = "<h3>Choose Character Model</h3>";
+		help += "Please choose a model.";
+		
+		Listable wh = ListDialog.queryList(m.containerOfModule(), "Choose model", explanation, help, models, 0);
+		return (CharacterModel)wh; 
+	}
+	public static CharacterModel chooseNewCharacterModel(MesquiteModule m, Class modelClass, String explanation){
+		if (m == null || modelClass == null)
+			return null;
+		String help = "";
+		boolean wizardInEffect = CommandRecord.wizardInEffect();
+		if (wizardInEffect)
+			help = "<h3>Choose Character Model</h3>";
+		help += "Please choose a model.";
+		if (explanation == null)
+			explanation = "Choose model";
+		MesquiteModule cme = (MesquiteModule)m.findElementManager(CharacterModel.class);
+		MesquiteModule[] curators = cme.getImmediateEmployeesWithDuty(CharModelCurator.class);
+		if (curators!=null) {
+			int count=0;
+			for (int i=0; i<curators.length; i++)
+				if (modelClass.isAssignableFrom(((CharModelCurator)curators[i]).getModelClass()))
+					count++;
+			if (count>0){
+				String[] s = new String[count];
+				count=0;
+				for (int i=0; i<curators.length; i++) {
+					if (modelClass.isAssignableFrom(((CharModelCurator)curators[i]).getModelClass())) {
+						s[count]=((CharModelCurator)curators[i]).getNameOfModelClass();
+						count++;
+					}
+				}
+				int choice = ListDialog.queryList(m.containerOfModule(), "Choose model", explanation,help,  s, 0);
+				if (MesquiteInteger.isCombinable(choice)) {
+					count =0;
+					for (int i=0; i<curators.length; i++) {
+						if (modelClass.isAssignableFrom(((CharModelCurator)curators[i]).getModelClass())) {
+							if (count==choice) {
+								String name = "Character Model";
+								if (m.getProject()!=null) {
+									name = m.getProject().getCharacterModels().getUniqueName(name);
+								}
+								return ((CharModelCurator)curators[i]).makeNewModel(name);
+							}
+							count++;
+						}
+					}
+				}
+			}
+		}
+		return null;
+
+	}
+	public static MesquiteModule[] findCurators(MesquiteModule m, Class modelClass){
+		if (m == null || modelClass == null)
+			return null;
+		MesquiteModule cme = (MesquiteModule)m.findElementManager(CharacterModel.class);
+		if (cme == null)
+			return null;
+		MesquiteModule[] curators = cme.getImmediateEmployeesWithDuty(CharModelCurator.class);
+		if (curators!=null) {
+			int count=0;
+			for (int i=0; i<curators.length; i++) {
+				Class mC = ((CharModelCurator)curators[i]).getModelClass();
+				
+				if (mC != null && modelClass.isAssignableFrom(mC))
+					count++;
+			}
+			if (count>0){
+				MesquiteModule[] s = new MesquiteModule[count];
+				count=0;
+				for (int i=0; i<curators.length; i++) {
+					Class mC = ((CharModelCurator)curators[i]).getModelClass();
+					if (mC != null && modelClass.isAssignableFrom(mC)) {
+						s[count]=curators[i];
+						count++;
+					}
+				}
+				return s;
+			}
+		}
+		return null;
+
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharacterPartition.java b/Source/mesquite/lib/characters/CharacterPartition.java
new file mode 100644
index 0000000..0ac33eb
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterPartition.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**A CharacterPartition is a specification of which property applies to each character (CHARPARTITION in NEXUS 1 file format).
+  */
+
+public class CharacterPartition  extends CharObjectSpecsSet {
+	public CharacterPartition (String name, int numChars, Object defaultProperty, CharacterData data) {
+		super(name, numChars, defaultProperty, data);
+	}
+	
+	public SpecsSet cloneSpecsSet(){
+		CharacterPartition ms = new CharacterPartition(new String(name), getNumberOfParts(), (CharactersGroup)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++)
+			ms.setProperty(getProperty(i), i);
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CharacterPartition("Partition", numParts, getDefaultProperty(), (CharacterData)parent);
+	}
+	public String getTypeName(){
+		return "Character partition";
+	}
+
+	public CharactersGroup getCharactersGroup(int part){
+		return (CharactersGroup)getProperty(part);
+	}
+	/**Returns an array of all the partitions for all the charactes*/
+	public CharactersGroup[] getGroups(){
+		CharactersGroup[] temp = new CharactersGroup[getNumberOfParts()];
+		int next = 0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			CharactersGroup mq = getCharactersGroup(i);
+			if (mq!=null) {
+				if (ObjectArray.indexOf(temp, mq)<0){
+					temp[next++]=mq;
+				}
+			}
+		}
+		if (next==0)
+			return null;
+		CharactersGroup[] result = new CharactersGroup[next];
+		for (int i=0; i<result.length; i++)
+			result[i]=temp[i];
+		
+		return result;
+	}
+ 	/*.................................................................................................................*/
+	/**/
+	public int getNumberInGroup(CharactersGroup target){
+		int num =0;
+		for (int i=0; i<getNumberOfParts(); i++) {
+			CharactersGroup mq = getCharactersGroup(i);
+			if (mq==target)
+				num++;
+		}
+		return num;
+	}
+ 	/*.................................................................................................................*/
+	/**/
+	public boolean getAnyCurrentlyUnassigned(){
+		for (int i=0; i<getNumberOfParts(); i++) {
+			CharactersGroup mq = getCharactersGroup(i);
+			if (mq==null)
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+ 	/** gets storage for set of properties*/
+	public Object[] getNewPropertyStorage(int numParts){
+		return new CharactersGroup[numParts];
+	}
+ 	/*.................................................................................................................*/
+ 	/** return array of character properties (can also get indivitually using getProperty)*/
+	public CharactersGroup[] getPartitions() {
+		CharactersGroup[] p = new CharactersGroup[getNumChars()];
+		for (int i=0; i<getNumChars(); i++) {
+			p[i] =(CharactersGroup)getProperty(i);
+		}
+		return p;
+	}
+	
+
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharacterState.java b/Source/mesquite/lib/characters/CharacterState.java
new file mode 100644
index 0000000..9c27d15
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterState.java
@@ -0,0 +1,152 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/*==========================  Mesquite Basic Class Library    ==========================*/
+/*
+Characters and their states are represented by various classes.  One, CharacterState, represents a single state of a character (e.g., the state of 
+a terminal taxon).  <p>
+The class CharacterData and its subclasses represent full datasets with a matrix, character names, and associated sets (model sets,
+exclusion sets, etc.).  <p>
+Subclasses of MCharactersStates represent a matrix of character X taxa (without associated names, sets, etc.), and are used
+for temporary storage of a matrix or for the results of a reconstruction of character evolution in all characters.<p>
+Subclasses of MCharactersStates represent an array of character states in a series of taxa or nodes ("M" for "Multiple", as opposed to the subclasses of
+CharacterStates which refer to a single character).  The subclasses are:
+	<li>MCharactersDistribution - The states in multiple characters in terminal taxa.  Often passed to modules so they can calculate on it.
+		<ul>
+		<li>MCategoricalDistribution - for categorical characters.
+			<ul><li>MCategoricalAdjustable - used for stand-alone characters, such as those coming from a simulation.  Size can be adjusted & states altered.
+			<li>MCategoricalEmbedded - used as a reference to amatrix in an existing CharacterData object.
+			</ul>
+		<li>MContinuousDistribution
+			<ul><li>MContinuousAdjustable - used for stand-alone characters, such as those coming from a simulation.  Size can be adjusted & states altered.
+			<li>MContinuousEmbedded - used as a reference to a matrix in an existing CharacterData object.
+			</ul>
+		</ul>
+	<li>MCharactersHistory - states at the internal and terminal nodes of a tree.  Returned by reconstruction modules.
+			<ul><li>MCategoricalHistory - for categorical characters
+			<li>MContinuousHistory - for continuous characters.
+			</ul>
+<p>
+Subclasses of CharacterStates represent a vector of character states in a single character in a series of taxa or nodes.  The subclasses are:
+	<li>CharacterDistribution - The states in terminal taxa.  Often passed to modules so they can calculate on it.
+		<ul>
+		<li>CategoricalDistribution - for a categorical character.
+			<ul><li>CategoricalAdjustable - used for stand-alone character, such as that coming from a simulation.  Size can be adjusted & states altered.
+			<li>CategoricalEmbedded - used as a reference to a character in an existing CharacterData object.
+			</ul>
+		<li>ContinuousDistribution
+			<ul><li>ContinuousAdjustable - used for stand-alone character, such as that coming from a simulation.  Size can be adjusted & states altered.
+			<li>ContinuousEmbedded - used as a reference to a character in an existing CharacterData object.
+			</ul>
+		</ul>
+	<li>CharacterHistory - states at the internal and terminal nodes of a tree.  Returned by reconstruction modules.
+			<ul><li>CategoricalHistory - for a categorical character
+			<li>ContinuousHistory - for a continuous character.
+			</ul>
+*/
+
+/* ======================================================================== */
+/** An abstraction of a state of a character to allow categorical, continuous and other subclasses. */
+public abstract class CharacterState {
+	/** returns string representation of the character state*/
+	public abstract String toString();
+	/** sets its value to the value in CharacterState passed to it*/
+	public abstract void setValue(CharacterState cs);
+	
+	/** sets its value to the value given by the String passed to it*/
+	public abstract void setValue(String s, CharacterData parentData);
+	
+	/** sets its value to the value given by the String passed to it starting at position pos*
+	public abstract void setValue(String s, MesquiteInteger pos);
+	/**/
+	/** sets its value to unassigned*/
+	public abstract void setToUnassigned();
+	/** sets its value to inapplicable*/
+	public abstract void setToInapplicable();
+	/** returns whether the value is unassigned.  Unassigned is a special value for each character type, equivalent to
+	missing data "?"*/
+	public abstract boolean isUnassigned();
+	/** returns whether value is inapplicable.  Inapplicable is a special value for each character type, equivalent to
+	a gap "-"*/
+	public abstract boolean isInapplicable();
+	/** returns whether value is valid or not.  Impossible is a special value for each character type, and should be used to indicate
+	a state is invalid.*/
+	public abstract boolean isImpossible();
+	/** returns whether value is combinable (i.e. a valid assigned state) or not.*/
+	public abstract boolean isCombinable();
+	/** returns whether the contents of the character states are identical*/
+	public abstract boolean equals(CharacterState s);
+	/** returns whether the contents of the character states are identical, allowing some to be missing if allowMissing is true*/
+	public abstract boolean equals(CharacterState s, boolean allowMissing);
+	/** returns the subclass of CharacterData that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public  abstract boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact);
+	public boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact, boolean allowSubset){
+		return equals(s, allowMissing, allowNearExact);
+	}
+	/** returns the subclass of CharacterData that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public abstract Class getCharacterDataClass();
+	/** returns the subclass of MCharactersDistribution that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public abstract Class getMCharactersDistributionClass();
+	/** returns the subclass of CharacterDistribution that is equivalent to this character type (i.e., in which sort of
+	Distribution would this character state reside?.  Should return an MAdjustableDistribution*/
+	public abstract Class getCharacterDistributionClass();
+	/** returns the subclass of CharacterHistory that is equivalent to this character type (i.e., in which sort of
+	Distribution would this character state reside?*/
+	public abstract Class getCharacterHistoryClass();
+	
+	/** Returns string as would be displayed to user (not necessarily internal shorthand)*/
+	public abstract String toDisplayString();
+	
+	/** returns a AdjustableDistribution that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public abstract AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes);
+	/** returns a CharacterHistory that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public abstract CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes);
+	
+	/** returns a MCharactersDistribution that is equivalent to this character type (i.e., in which sort of
+	matrix would this character state reside?*/
+	public MAdjustableDistribution makeMCharactersDistribution(Taxa taxa, int numChars, int numTaxa) {
+		Class c = getMCharactersDistributionClass();
+		if (c == null) {
+			MesquiteMessage.printStackTrace("no class returned by getMCharactersDistributionClass " + this);
+			return null;
+		}
+		try {
+			MAdjustableDistribution s = (MAdjustableDistribution)c.newInstance();
+			if (s!=null) {
+				s.setTaxa(taxa);
+				s.setSize(numChars, numTaxa);
+				return s;
+			}
+		}
+		catch (IllegalAccessException e){MesquiteTrunk.mesquiteTrunk.alert("iae cs");
+		e.printStackTrace(); }
+		catch (InstantiationException e){MesquiteTrunk.mesquiteTrunk.alert("ie cs");e.printStackTrace(); }
+		return null;
+	}
+	
+	/**Returns the type of data stored.. */
+	public abstract String getDataTypeName();
+}
+
diff --git a/Source/mesquite/lib/characters/CharacterStateTest.java b/Source/mesquite/lib/characters/CharacterStateTest.java
new file mode 100644
index 0000000..64c0fc4
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterStateTest.java
@@ -0,0 +1,31 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+	
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class CharacterStateTest extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return obj == null || ( obj instanceof Class && (CharacterState.class.isAssignableFrom((Class)obj)));
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/CharacterStates.java b/Source/mesquite/lib/characters/CharacterStates.java
new file mode 100644
index 0000000..a8679b0
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterStates.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**Stores the character states at a series of terminal taxa or nodes in a tree.  The class on which particular classes implementing
+CharacterDistribution and CharacterHistory are based.  See general discussion of character storage classes under CharacterState*/
+public abstract class CharacterStates implements CharacterStatesHolder, Listable, Explainable  {  
+	protected CharacterData data=null; //parent CharacterData
+	protected int characterNumber=0; //parent character within the parent CharacterData
+	public static long totalCreated = 0;
+	private String name = null;
+	private Taxa  taxa;
+	private long id;
+	public CharacterStates (Taxa taxa) {
+		id = totalCreated;
+		totalCreated++;
+		this.taxa = taxa;
+	}
+	
+   	public CharacterState makeCharacterState(){
+		Class c = getStateClass();
+		try {
+			CharacterState s = (CharacterState)c.newInstance();
+			return s;
+		}
+		catch (IllegalAccessException e){MesquiteTrunk.mesquiteTrunk.alert("iae csmcs"); }
+		catch (InstantiationException e){MesquiteTrunk.mesquiteTrunk.alert("ie csmcs"); }
+		return null;
+   	}
+   	public long getID(){
+   		return id;
+   	}
+	String explanation;
+	public void setExplanation(String expl){
+		explanation = expl;
+	}
+	public String getExplanation(){
+		return explanation;
+	}
+	/*.................................................................................................................*/
+	/** returns taxa object */
+	public Taxa getTaxa (){
+		return taxa;
+	}
+	/*.................................................................................................................*/
+	/** sets taxa object */
+	public void setTaxa (Taxa taxa){
+		this.taxa = taxa;
+	}
+	/*.................................................................................................................*/
+	/** returns name */
+	public String getName (){
+		return name;
+	}
+	/*.................................................................................................................*/
+	/** sets name */
+	public void setName (String name){
+		this.name = name;
+	}
+	/*.................................................................................................................*/
+	/** returns parent data of this CharacterStates.  There is not a corresponding set procedure because the parent data
+	is set either by the constructor (for Embedded distributions) or by a set procedure (for History or Adjustables) */
+	public CharacterData getParentData (){
+		return data;
+	}
+	/*.................................................................................................................*/
+	/** returns parent character of this CharacterStates*/
+	public int getParentCharacter (){
+		return characterNumber;
+	}
+	/*.................................................................................................................*/
+	protected boolean checkIllegalNode(int node, int where) {
+		if (node<0 || node>=getNumNodes()) {
+			//MesquiteMessage.println("illegal node in CharacterStates (node: " + node + " max: " + getNumNodes() + ") " + where);
+			//MesquiteMessage.printStackTrace();
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**sets the parent CharacterData from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd){
+		data = cd;
+	}
+	/*.................................................................................................................*/
+	/**sets the parent character number from which this CharacterDistribution is derived or related. */
+	public void setParentCharacter (int ic){
+		if (ic<0)
+			ic = 0;
+		if (data!=null) {
+			if (ic<data.getNumChars())
+				this.characterNumber = ic;
+			else
+				this.characterNumber = 0;
+		}
+		else
+			this.characterNumber = ic;
+	}
+	/*.................................................................................................................*/
+	/**Translates internal numbering system of characters to external (currently, 0 based to 1 based*/
+	public static long toExternalLong(long i){
+		if (!MesquiteLong.isCombinable(i))
+			return i;
+		else
+			return i+1;
+	}
+	/*.................................................................................................................*/
+	/**Translates external numbering system of characters to internal (currently, 1 based to 0 based*/
+	public static long toInternalLong(long i){
+		if (!MesquiteLong.isCombinable(i))
+			return i;
+		else
+			return i-1;
+	}
+	/*.................................................................................................................*/
+	/**Translates internal numbering system of characters to external (currently, 0 based to 1 based*/
+	public static int toExternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i+1;
+	}
+	/*.................................................................................................................*/
+	/**Translates external numbering system of characters to internal (currently, 1 based to 0 based*/
+	public static int toInternal(int i){
+		if (!MesquiteInteger.isCombinable(i))
+			return i;
+		else
+			return i-1;
+	}
+	public String toStringWithDetails(){
+		StringBuffer sb = new StringBuffer();
+		CharacterState cs = null;
+		boolean first = true;
+		for (int i = 0; i< getNumNodes(); i++){
+			if (!isUnassigned(i)){
+				if (!first)
+					sb.append('\t');
+				first = false;
+				sb.append(Integer.toString(i));
+				sb.append('\t');
+				cs = getCharacterState(cs, i);
+				sb.append(cs.toString());
+			}
+		}
+		return sb.toString();
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/CharacterStatesHolder.java b/Source/mesquite/lib/characters/CharacterStatesHolder.java
new file mode 100644
index 0000000..e7ba07f
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterStatesHolder.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**Stores the character states at a series of terminal taxa or nodes in a tree.  The class on which both
+CharacterDistribution and CharacterHistory are based.  See general discussion of character storage classes under CharacterState*/
+public interface CharacterStatesHolder extends Listable, Renamable, WithStringDetails {  
+	/*.................................................................................................................*/
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass ();
+	/*.................................................................................................................*/
+	/**returns the corresponding CharacterState subclass*/
+	public Class getStateClass ();
+	/*.................................................................................................................*/
+	/** passed the file, finds the default character model.  This is not done well yet.  Should be passed the paradigm.  Is passed the
+	so the CharacterModel object can be looked up*/
+	public CharacterModel getDefaultModel(MesquiteProject proj, String paradigm);
+	/*.................................................................................................................*/
+	/** Returns the Taxa to which this applies */ 
+	public Taxa getTaxa();
+	/*.................................................................................................................*/
+	/** This is the same as getNumNodes.  This may be unexpected, because it does NOT necessarily give the same results as getTaxa().getNumTaxa().
+	For instance, if this is a CharacterHistory, then this is the same as number of nodes, not the number of terminal taxa.  The reason for this unusual usage is that
+	*/
+	public int getNumTaxa();
+	/*.................................................................................................................*/
+	/** returns number of nodes for which CharacterStates is defined 
+	(either terminal taxa, if CharacterDistribution, or all nodes in tree, if CharacterHistory) */
+	public int getNumNodes();
+	/*.................................................................................................................*/
+	/** returns parent data of this CharacterStates.  There is not a corresponding set procedure because the parent data
+	is set either by the constructor (for Embedded distributions) or by a set procedure (for History or Adjustables) */
+	public CharacterData getParentData ();
+	/*.................................................................................................................*/
+	/** returns parent character of this CharacterStates*/
+	public int getParentCharacter ();
+	/*.................................................................................................................*/
+	/** return whether states at node N is in some way greater than that at node M*/
+	public boolean firstIsGreater (int N, int M);
+	/*.................................................................................................................*/
+	/** get blank CharacterState object*/
+	public CharacterState getCharacterState ();
+	/*.................................................................................................................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int N);
+	/*.................................................................................................................*/
+   	/** returns whether the character is inapplicable at node/taxon N*/
+   	public boolean isInapplicable(int N);
+	/*.................................................................................................................*/
+   	/** returns whether the state of character is missing in node/taxon N*/
+   	public boolean isUnassigned(int N);
+	/*.................................................................................................................*/
+   	/** returns whether the state of character has uncertainty in node/taxon N*/
+   	public boolean isUncertain(int N);
+	/*.................................................................................................................*/
+	/** output to log a list of the states.  for debugging purposes*/
+	public void logStates();
+	/*.................................................................................................................*/
+	/** get string describing character states at terminal taxon or node.*/
+	public String toString (int taxon, String lineEnding);
+	
+	public String toStringWithDetails();
+	/*.................................................................................................................*/
+	/** returns whether states at nodes n and m are equal*/
+	public boolean statesEqual(int n, int m);
+	
+}
+
diff --git a/Source/mesquite/lib/characters/CharacterSubmodel.java b/Source/mesquite/lib/characters/CharacterSubmodel.java
new file mode 100644
index 0000000..a181ef5
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharacterSubmodel.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/** An intermediary superclass that subclasses can extend to help with GUI, so that choices know whether a model
+ is complete (e.g, as in composite DNA mode) or a submodel (e.g., state frequencies model with DNA) */
+public abstract class CharacterSubmodel extends CharacterModel  {
+	
+	public CharacterSubmodel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharactersBlock.java b/Source/mesquite/lib/characters/CharactersBlock.java
new file mode 100644
index 0000000..92b866c
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharactersBlock.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/*===============================================*/
+/** A block in a NEXUS file representing a CharacterData */
+public class CharactersBlock extends NexusBlock {
+	CharacterData data = null;
+	public CharactersBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public boolean getWritable(){
+		if (data == null)
+			return false;
+		return data.getWritable();
+	}
+	public boolean contains(FileElement e) {
+		return e != null && data == e;
+	}
+	public boolean mustBeAfter(NexusBlock block){ 
+		if (block==null)
+			return false;
+		if (data!=null && block instanceof TaxaBlock) {
+			return data.getTaxa() == ((TaxaBlock)block).getTaxa();
+		}
+		return (block.getBlockName().equalsIgnoreCase("TAXA"));
+		
+	}
+	public String getBlockName(){
+		return "CHARACTERS";
+	}
+	public void setData(CharacterData data) {
+		this.data = data;
+	}
+	public CharacterData getData() {
+		return data;
+	}
+	public void written() {
+		data.setDirty(false);
+	}
+	public String getName(){
+		if (data==null)
+			return "empty characters block";
+		else
+			return "Characters block: " + data.getName();
+	}
+	public void writeNEXUSBlock(MesquiteFile file, ProgressIndicator progIndicator){
+		if (data==null)
+			return;
+		if (data.getMatrixManager()!=null) {
+			String s = data.checkIntegrity();
+			if (s !=null) {
+				MesquiteTrunk.errorReportedDuringRun = true;
+				MesquiteTrunk.mesquiteTrunk.alert("WARNING: the data being written appears to be corrupt, possibly because of a crash.  DO NOT RELY ON THIS DATA without checking it over very carefully.  " + s + " (" + data + ")");
+			}
+			MesquiteTrunk.mesquiteTrunk.logln("      Writing " + getName());
+			data.getMatrixManager().writeCharactersBlock(data, this, file, progIndicator);
+			data.resetCellMetadata();
+		}
+	}
+}
+	
+
diff --git a/Source/mesquite/lib/characters/CharactersGroup.java b/Source/mesquite/lib/characters/CharactersGroup.java
new file mode 100644
index 0000000..0d7a233
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharactersGroup.java
@@ -0,0 +1,54 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lists.lib.CharListPartitionUtil;
+import mesquite.lists.lib.GroupDialog;
+
+	
+/* ======================================================================== */
+/** A group to which characters may belong.*/
+public class CharactersGroup extends GroupLabel {
+	public static boolean supportsSymbols() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void editMe(){
+			GroupDialog d = new GroupDialog(getProject(),getProject().getCoordinatorModule().containerOfModule(), "Edit Character Group", getName(), getColor(), getSymbol(), supportsSymbols());
+			d.completeAndShowDialog();
+			String name = d.getName();
+			boolean ok = d.query()==0;
+			Color c = d.getColor();
+			d.dispose();
+			if (!ok)
+				return;
+
+
+			if (!StringUtil.blank(name)) {
+				setName(name);
+				setColor(c);
+	 		//	data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+				notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+			}
+		
+		
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/CharactersGroupVector.java b/Source/mesquite/lib/characters/CharactersGroupVector.java
new file mode 100644
index 0000000..5be7127
--- /dev/null
+++ b/Source/mesquite/lib/characters/CharactersGroupVector.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+	
+/* ======================================================================== */
+/** Stores a list of character groups (partitions).*/
+public class CharactersGroupVector extends ListableVector {
+	public CharactersGroupVector(){
+		super();
+		setName("Character Groups");
+
+	}
+	public CharactersGroup findGroup(String token){ 
+		if (token ==null)
+			return null;
+		for (int i = 0; i< size(); i++){
+			CharactersGroup cg = (CharactersGroup)elementAt(i);
+			if (token.equalsIgnoreCase(cg.getName())){
+				return cg;
+			}
+		}
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/characters/CodonPositionsSet.java b/Source/mesquite/lib/characters/CodonPositionsSet.java
new file mode 100644
index 0000000..b9754e5
--- /dev/null
+++ b/Source/mesquite/lib/characters/CodonPositionsSet.java
@@ -0,0 +1,143 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*======================================================================== */
+/** a designation of codon positions for characters. */
+public class CodonPositionsSet  extends CharNumSet {
+	
+	public CodonPositionsSet (String name, int numChars, CharacterData data) {
+		super(name, numChars, new MesquiteNumber(0), data);
+	}
+	public String getTypeName(){
+		return "Codon Positions set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		CodonPositionsSet ms = new CodonPositionsSet(new String(name), getNumberOfParts(),  data);
+		MesquiteNumber position = new MesquiteNumber();
+		for (int i=0; i< getNumberOfParts(); i++) {
+			placeValue(i, position);
+			ms.setValue(i, position);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new CodonPositionsSet("Codon Positions", numParts, (CharacterData)parent);
+	}
+ 	/*.................................................................................................................*/
+	/** Add num parts just after "starting" (filling with default values)  */
+  	public boolean addParts(int starting, int num){  
+		boolean success = super.addParts(starting, num);
+		MesquiteNumber position = new MesquiteNumber(0);
+		if (starting >=0 && getInt(starting)!=MesquiteInteger.unassigned)
+			
+		for (int i=0; i< num; i++) 
+			setValue(i+starting+1, position);
+		
+		return success;
+	}
+  	
+	int endSequenceByThree(int targetPos, int numChars, int ic, int mainCount, boolean[] include, MesquiteInteger charNumberOfLastThird){
+		int unassignedPosition=4;
+		int previousThird = mainCount; 
+		charNumberOfLastThird.setValue(ic);  //store the char number of the previous end of the triplets
+		int count=mainCount;
+		int ik=0;
+		for (ik = ic+1; ik< numChars; ik++){
+			if (include==null || ik>=include.length || include[ik]){
+				count++;
+				int thisPos = getInt(ik);
+				if (thisPos == targetPos || (thisPos==MesquiteInteger.unassigned && (targetPos==unassignedPosition))) {
+					//is a match; if not modulus 3 on from ic then return previousThird 
+					if ((count-mainCount) % 3 !=0){
+						return previousThird;
+					}
+					else {
+						charNumberOfLastThird.setValue(ik);  //store the char number of the previous end of the triplets
+						previousThird = count;
+					}
+				}
+				else {
+					//is not a match; if modulus 3 on from ic then return previousThird 
+					if ((count-mainCount) % 3 ==0){
+						return previousThird;
+					}
+				}
+			}
+		}
+		return previousThird;
+	}
+  	public String getListOfMatches(int targetPos){
+  		return getListOfMatches(targetPos, 0, null);
+  	}
+  	
+ 	public String getListOfMatches(int targetPos, int offset, boolean[] include){  //offset is number to add to character numbers
+
+ 		int lastWritten = -1;
+		int unassignedPosition=4;
+		String list = "";
+		int continuing = 0;
+		int count = -1;
+		MesquiteInteger charNumberOfLastThird = new MesquiteInteger(-1);
+		for (int ic=0; ic<getNumberOfParts(); ic++) {
+			if (include==null || ic>=include.length || include[ic]){   // it's one to consider
+				count++;
+				int thisPos = getInt(ic);
+				if (thisPos == targetPos || (thisPos==MesquiteInteger.unassigned && (targetPos==unassignedPosition))) {
+					if (continuing == 0) { 
+						//first, check to see if there is a series of thirds....
+						int lastThird = endSequenceByThree(targetPos, getNumberOfParts(), ic, count, include, charNumberOfLastThird);
+						//if so, then go the series of thirds 
+						if (lastThird != count){
+							list += " " + CharacterStates.toExternal(count+offset) + " - " +  CharacterStates.toExternal(lastThird+offset) + "\\3";
+							ic = charNumberOfLastThird.getValue();
+							count = lastThird;
+						}
+						else { //otherwise write as normal*/
+							lastWritten = count;
+							list += " " + CharacterStates.toExternal(count+offset);
+							continuing = 1;
+						}
+					}
+					else if (continuing == 1) {  // we know there are at least two in a row of the same thing
+						list += "-";
+						continuing = 2;   //now set it so that we are waiting for the last one in the series
+					}
+				}
+				else if (continuing>0) {   // we are in a contiguous stretch of the same thing
+					if (lastWritten != count-1){  // last one we wrote wasn't the one just before
+						list += " " + CharacterStates.toExternal(count-1+offset);
+						lastWritten = count-1;
+					}
+					else
+						lastWritten = -1;
+					continuing = 0;
+				}
+			}
+		}
+		if (continuing>1) {  // we are waiting for the last one
+			list += " " + CharacterStates.toExternal(count+offset) + " ";
+			//thisValueString += " " + CharacterStates.toExternal(data.getNumChars()-1+offset) + " ";
+		}
+		return list;
+ 	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/DefaultReference.java b/Source/mesquite/lib/characters/DefaultReference.java
new file mode 100644
index 0000000..8820a78
--- /dev/null
+++ b/Source/mesquite/lib/characters/DefaultReference.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  May 2000 */
+/* ======================================================================== */
+/** A reference to a default model for CharacterData objects. */
+public class DefaultReference {
+	NameReference paradigm;
+	String name;
+	public DefaultReference (NameReference paradigm) {
+		this.paradigm = paradigm;
+	}
+	public void setDefault(String name){
+		this.name = name;
+	}
+	public String getDefault(){
+		return name;
+	}
+	public NameReference getParadigm(){
+		return paradigm;
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/MAdjustableDistribution.java b/Source/mesquite/lib/characters/MAdjustableDistribution.java
new file mode 100644
index 0000000..ffbfc1f
--- /dev/null
+++ b/Source/mesquite/lib/characters/MAdjustableDistribution.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**An interface to signal that a MCharactersDistribution can be changed (i.e. its states set, its parent data set, the number
+of taxa readjusted, and so on.  Some MCharactersDistributions, such as those that report characters from stored matrices in
+a CharacterData object, are not adjustable.  See general discussion of character storage classes under CharacterState*/
+public interface MAdjustableDistribution extends MCharactersDistribution, Annotatable  {
+	/** Set the taxa to which matrix applies */ 
+	public void setTaxa(Taxa taxa);
+	/** Set the size of the matrix */ 
+	public void setSize(int numChars, int numTaxa);
+	/**sets the parent CharacterData from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd);
+	
+	/**sets the character state of character ic and taxon it to that in the passed CharacterState*/
+   	public void setCharacterState(CharacterState s, int ic, int it);
+   	
+   	/** trades the states of character ic between taxa it and it2.  Used for reshuffling.*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2);
+	/** assign missing data (unassigned) to all of the characters*/
+	public void deassignStates();
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public void transferFrom(int ic, CharacterDistribution s);
+	
+}
+
diff --git a/Source/mesquite/lib/characters/MCharactersDistribution.java b/Source/mesquite/lib/characters/MCharactersDistribution.java
new file mode 100644
index 0000000..6622c21
--- /dev/null
+++ b/Source/mesquite/lib/characters/MCharactersDistribution.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**Stores states at each of the terminal taxa, for each of many characters.  See general discussion of character storage classes under CharacterState*/
+public interface MCharactersDistribution extends MCharactersStatesHolder  {
+	/**return CharacterDistribution object for character ic */
+	public CharacterDistribution getCharacterDistribution (int ic);  //TODO: pass existing to save instantiations
+
+	/**return blank adjustable MCharactersDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable();
+
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa);
+	
+	/** Adjusts the size of the passed MCharacterHistory to be of the same type as this MCharactersDistribution and to be prepared
+	to store states for each of the nodes of the tree.*/
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates);
+	/*------------*/
+
+
+	/**get the tree on which this was simulated or otherwise based, if any */
+	public Tree getBasisTree();
+	/**sets the tree on which this was simulated or otherwise based, if any */
+	public void setBasisTree(Tree tree);
+}
+
diff --git a/Source/mesquite/lib/characters/MCharactersHistory.java b/Source/mesquite/lib/characters/MCharactersHistory.java
new file mode 100644
index 0000000..7fd1ebe
--- /dev/null
+++ b/Source/mesquite/lib/characters/MCharactersHistory.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**Stores the reconstructed or simulated states at each of the nodes of a tree, for each of many characters.
+  See general discussion of character storage classes under CharacterState*/
+public interface MCharactersHistory extends MAdjustableDistribution  {
+	/**return CharacterHistory object for character ic */
+	public abstract CharacterHistory getCharacterHistory (int ic);//TODO: pass existing to save instantiations
+	/*------------*/
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public abstract void transferFrom(int ic, CharacterHistory s);
+}
+
diff --git a/Source/mesquite/lib/characters/MCharactersStates.java b/Source/mesquite/lib/characters/MCharactersStates.java
new file mode 100644
index 0000000..4e1d4d6
--- /dev/null
+++ b/Source/mesquite/lib/characters/MCharactersStates.java
@@ -0,0 +1,118 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003*/
+/* ======================================================================== */
+/**An abstract class for an array of  character states for many characters, at each of the taxa  or nodes.
+Although its subclasses (for categorical and continuous data) store matrices of character states, it is not
+a variety of data matrix (CharacterData), because it does not contained associated model sets etc. etc.
+It is is used mainly for calculations to store their results, e.g. downstates,
+or reconstructed states at nodes.
+  See general discussion of character storage classes under CharacterState*/
+public abstract class MCharactersStates implements MCharactersStatesHolder   {
+	protected CharacterData data = null;
+	public static long totalCreated = 0;
+	private String name = null;
+	private Taxa taxa;
+	Tree basisTree; //the tree on which this was based (e.g. if simulated); important in case both tree and matrix are needed
+	
+	public MCharactersStates(Taxa taxa) {
+		totalCreated++;
+		this.taxa = taxa;
+	}
+	
+	public void setBasisTree(Tree tree){ 
+		if (tree == null) {
+			basisTree = null;
+		}
+		else {
+			basisTree = tree.cloneTree();//TODO: establish listener of Taxa, but if so how to remove as there is no dispose method?
+		}
+	}
+	public Tree getBasisTree(){
+		return basisTree;
+	}
+	/*.................................................................................................................*/
+	/** returns taxa object */
+	public Taxa getTaxa (){
+		return taxa;
+	}
+	/*.................................................................................................................*/
+	/** sets taxa object */
+	public void setTaxa (Taxa taxa){
+		if (taxa != this.taxa)
+			basisTree = null;
+		this.taxa = taxa;
+	
+	}
+	/*.................................................................................................................*/
+	/** returns name */
+	public String getName (){
+		return name;
+	}
+	/*.................................................................................................................*/
+	/** sets name */
+	public void setName (String name){
+		this.name = name;
+	}
+	/** Indicates the type of character stored */ 
+	public abstract Class getStateClass();
+
+	/**Returns the type of data stored. */
+	public abstract String getDataTypeName();
+	
+	/** Returns the parent CharacterData */ 
+	public CharacterData getParentData() {
+		return data;
+	}
+	/** get CharacterState of character ic at node or taxon it*/
+	public abstract CharacterState getCharacterState (CharacterState cs, int ic, int it);
+
+	public boolean isCurrentlyIncluded(int ic){
+		if (data!=null)
+			return data.isCurrentlyIncluded(ic);
+		return true;
+	}
+	/*.................................................................................................................*/
+	protected boolean checkIllegalNode(int node, int where) {
+		if (node<0 || node>=getNumNodes()) {
+			return true;
+			//MesquiteMessage.println("illegal node in MCharactersStates (node: " + node + " max: " + getNumNodes() + ") " + where);
+		}
+		return false;
+	}
+	
+	public int getNumNodes(){
+		return getNumTaxa();
+	}
+	
+	public String matrixToString(){
+		String s = "";
+		CharacterState cs  = null;
+		for (int it = 0; it<getNumNodes(); it++){
+			for (int ic = 0; ic<getNumChars(); ic++){
+				cs = getCharacterState(cs, ic, it);
+				s += " " + cs;
+			}
+			s += "\n";
+		}
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/MCharactersStatesHolder.java b/Source/mesquite/lib/characters/MCharactersStatesHolder.java
new file mode 100644
index 0000000..6551832
--- /dev/null
+++ b/Source/mesquite/lib/characters/MCharactersStatesHolder.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+/* ======================================================================== */
+/**Stores the character states for multiple characters at a series of terminal taxa or nodes in a tree.  The class on which both
+MCharactersDistribution and MCharactersHistory are based.
+  See general discussion of character storage classes under CharacterState*/
+public interface MCharactersStatesHolder extends Listable, Renamable   {
+	/*.................................................................................................................*/
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass ();
+	/*.................................................................................................................*/
+	/**returns the corresponding CharacterState subclass*/
+	public Class getStateClass ();
+
+	/**Returns the type of data stored. */
+	public String getDataTypeName();
+	
+	/** Returns the Taxa to which this applies */ 
+	public Taxa getTaxa();
+	/** Returns the parent CharacterData */ 
+	public CharacterData getParentData();
+	/** get CharacterState of character ic at node or taxon it*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it);
+
+	/** Returns whether character ic is currently included */ 
+	public boolean isCurrentlyIncluded(int ic);
+	
+	public int getNumChars();
+	/*.................................................................................................................*/
+	/** returns number of terminal taxa for which MCharactersStates is defined*/
+	public int getNumTaxa();
+	/*.................................................................................................................*/
+	/** returns number of nodes for which MCharactersStates is defined 
+	(either terminal taxa, if MCharactersDistribution, or all nodes in tree, if MCharactersHistory) */
+	public int getNumNodes();
+}
+
diff --git a/Source/mesquite/lib/characters/ModelCompatibilityInfo.java b/Source/mesquite/lib/characters/ModelCompatibilityInfo.java
new file mode 100644
index 0000000..6fdc74b
--- /dev/null
+++ b/Source/mesquite/lib/characters/ModelCompatibilityInfo.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.*;
+
+/*Last documented:  May 2000 */
+/* ======================================================================== */
+public class ModelCompatibilityInfo implements CompatibilityChecker {
+	public Class targetStateClass; //so model can check that it can handle this type of data
+	public Class targetModelSubclass;  //so model can check that it is correct subclass
+	public ModelCompatibilityInfo(Class targetModelSubclass, Class targetStateClass){
+		this.targetModelSubclass=targetModelSubclass;
+		this.targetStateClass = targetStateClass;
+	}
+	 //obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa; added Apr 02
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+ 		return true;
+ 	}
+	 //obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa; added Apr 02
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+ 		return true;
+ 	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/characters/ModelSet.java b/Source/mesquite/lib/characters/ModelSet.java
new file mode 100644
index 0000000..c33332d
--- /dev/null
+++ b/Source/mesquite/lib/characters/ModelSet.java
@@ -0,0 +1,91 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**A ModelSet is a specification of which character model applies to each character (TYPESET in NEXUS 1 file format).
+In Mesquite, character models can be used by parsimony, MLE, etc. calculations.  Different calculations paradigms
+probably will use different models (though not necessarily), and thus parsimony would want to use one current set of models,
+while MLE would want to use another ModelSet, and so on.  Because paradigms are not formally defined in
+Mesquite, the currently active ModelSet that applies to a paradigm is requested by modules according to agreed-upon
+names.  Thus, a parsimony procedure would request a character's
+model in the current ModelSet.  If such a set exists, it would be used by the parsimony
+procedure, otherwise default would be used.  (There would also be a set "Current Parsimony Weights". )
+This will allow multiple defaults, so that for instance, MLE would be using one set of models and parsimony
+another.  */
+
+public abstract class ModelSet  extends CharObjectSpecsSet {
+	
+	public ModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Model Set";
+	}
+
+ 	/*.................................................................................................................*/
+ 	/** gets storage for set of properties*/
+	public Object[] getNewPropertyStorage(int numParts){
+		return new CharacterModel[numParts];
+	}
+ 	/*.................................................................................................................*/
+ 	/** Sets model of character*/
+	public void setModel(CharacterModel model, int index) {
+		setDirty(true);
+		setProperty(model, index);
+	}
+ 	/*.................................................................................................................*/
+ 	/** return array of character models (can also get indivitually using getModel)*/
+	public CharacterModel[] getModels() {
+		Object p = getProperties();
+		if (p==null)
+			return null;
+		else
+			return (CharacterModel[])p;
+	}
+ 	/*.................................................................................................................*/
+ 	/** returns model for specified character*/
+	public CharacterModel getModel(int index) {
+		return (CharacterModel)getProperty(index);
+	}
+ 	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet*/
+	public CharacterModel getDefaultModel() {
+		return (CharacterModel)getDefaultProperty();
+	}
+	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet*/
+	public CharacterModel getDefaultModel(int ic) {
+		return getDefaultModel();
+	}
+	/*.................................................................................................................*/
+ 	/** sets default model*/
+	public void setDefaultModel(CharacterModel defaultModel) {
+		setDirty(true);
+		setDefaultProperty(defaultModel);
+	}
+ 	/*.................................................................................................................*/
+ 	public String toString(){
+		String s = "Model set " + getName() + ": ";
+		for (int i=0; i<getNumberOfParts(); i++) {
+			s +=  getModel(i);
+		}
+		return s;
+ 	}
+}
+
diff --git a/Source/mesquite/lib/characters/ModelVector.java b/Source/mesquite/lib/characters/ModelVector.java
new file mode 100644
index 0000000..3d54084
--- /dev/null
+++ b/Source/mesquite/lib/characters/ModelVector.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  May 2000 */
+/*======================================================================== */
+/** a set of Models, for file to keep track of all of its defined character models. */
+public class ModelVector extends ListableVector {
+	public ModelVector  () {
+		super();
+	}
+	
+	public String getTypeName(){
+		return "Character Models";
+	}
+	/** return CharacterModel of given name*/
+	public CharacterModel getCharacterModel(String name) {
+		if (name==null)
+			return null;
+		Enumeration enumeration =elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			CharacterModel cm = (CharacterModel)obj;
+			if (name.equalsIgnoreCase(cm.getName()) || name.equalsIgnoreCase(cm.getNEXUSName()) )
+				return cm;
+		}
+		return null;
+	}
+
+	/** disposes model*/
+	public void dispose() {
+		Enumeration enumeration =elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			CharacterModel cm = (CharacterModel)obj;
+			cm.dispose();
+		}
+		super.dispose();
+	}
+	public int getNumNotBuiltIn() {
+		Enumeration enumeration =elements();
+		int count = 0;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			CharacterModel cm = (CharacterModel)obj;
+			if (!cm.isBuiltIn())
+				count++;
+		}
+		return count;
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/ProbabilityModel.java b/Source/mesquite/lib/characters/ProbabilityModel.java
new file mode 100644
index 0000000..08283e5
--- /dev/null
+++ b/Source/mesquite/lib/characters/ProbabilityModel.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  May 2000 */
+/* ======================================================================== */
+/** Sublcass of models of character evolution for likelihood and other calculations involving stochastic models of character evolution. It is expected
+that subclasses of this will be specialized for different classes of data (categorical, continuous, etc.)*/
+public abstract class ProbabilityModel extends WholeCharacterModel {
+	int characterNumber = MesquiteInteger.unassigned;
+	private CharacterStatesHolder charDistribution = null;
+	private MCharactersStatesHolder charMatrix = null;
+	int defaultNumChars = 100;
+	
+	
+	public ProbabilityModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+	public abstract CharacterModel cloneModelWithMotherLink(CharacterModel formerClone);
+	
+	public void copyToClone(CharacterModel pm){
+		if (pm==null || !(pm instanceof ProbabilityModel))
+			return;
+		ProbabilityModel model = (ProbabilityModel)pm;
+		model.characterNumber = characterNumber;
+		model.charDistribution = charDistribution;
+		model.charMatrix = charMatrix;
+		super.copyToClone(model);
+	}
+	/** sets the seed for simulated character evolution */
+	public abstract void setSeed(long seed);
+	
+	/** returns the seed for simulated character evolution */
+	public abstract long getSeed();
+	
+  /* NOT YET WORKING
+  	public Object getLikelihoodSurface(Tree tree, CharacterDistribution observedStates, CLikelihoodCalculator lc, int divisions, double[] outputBounds){ //also pass upper & lower bounds
+		return null;
+	}
+*/
+	public String getTypeName(){
+		return "Probability model";
+	}
+	public String getParadigm(){
+		return "Probability";
+	}
+	
+	/** Returns a description of current parameters suitable for viewing by users */
+	public abstract String getParameters();
+	
+	/** Returns whether parameters of model are fully specified.  If so, it can be used for evolving states.*/
+	public abstract boolean isFullySpecified();
+	
+	/** Randomly generates according to model an end state on branch from beginning states*/
+	public abstract void evolveState (CharacterState beginState, CharacterState endState, Tree tree, int node);
+
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public abstract CharacterState getRootState (CharacterState state, Tree tree);
+	
+	/** Tells the model that subsequent calculations/simulations will apply to a different character from
+	previous calculations.  Between calls to this, the model may assume that the same character is being dealt with (note: initForNextCharacter
+	is called automatically by setCharacter */
+	public void initForNextCharacter(){
+	}
+	/** Sets the character number to which this model applies */
+	public void setCharacterNumber(int ic){
+		characterNumber = ic;
+	}
+	/** returns the character number to which this model applies */
+	public int getCharacterNumber(){
+		return characterNumber;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return true if model needs an empirical matrix*/
+	public boolean needsEmpirical(){
+		return false;
+	}
+ 	/*.................................................................................................................*/
+ 	/** Should be overridden to return matrix if model has an empirical matrix*/
+	public MCharactersDistribution getEmpirical(){
+		return null;
+	}
+	/** Sets the character distribution or history to which this model is currently applying */
+	public void setCharacterDistribution (CharacterStatesHolder cd){
+		charDistribution = cd;
+	}
+	public CharacterStatesHolder getCharacterDistribution (){
+		return charDistribution;
+	}
+	/** To be overridden if processing needs to happen after CharMatrix is set */
+	public void recalcAfterSetMCharactersStatesHolder (){
+	}
+	/** Returns default number of characters to simulate. This can be useful if the model wants to specify whether to use an empirical number or some other number*/ 
+   	public int getDefaultNumChars(){
+		return defaultNumChars;
+   	}
+	/** sets default number of characters to simulate. */ 
+   	public void setDefaultNumChars(int numChars){
+		defaultNumChars = numChars;
+   	}
+	/** Sets the character matrix or  history to which this model is currently applying */
+	public void setMCharactersStatesHolder (MCharactersStatesHolder cd){
+		charMatrix = cd;
+		recalcAfterSetMCharactersStatesHolder();
+	}
+	public MCharactersStatesHolder getMCharactersStatesHolder (){
+		return charMatrix;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/characters/ProbabilityModelSet.java b/Source/mesquite/lib/characters/ProbabilityModelSet.java
new file mode 100644
index 0000000..3ebbf81
--- /dev/null
+++ b/Source/mesquite/lib/characters/ProbabilityModelSet.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*======================================================================== */
+/** a ModelSet for probability models. */
+public class ProbabilityModelSet  extends ModelSet {
+	
+	public ProbabilityModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Probability Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		ProbabilityModelSet ms = new ProbabilityModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new ProbabilityModelSet("Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet for character ic or new character added just after ic.  May take from current assignment*/
+	public CharacterModel getDefaultModel(int ic) {
+		return (CharacterModel)getDefaultProperty(ic);
+	}
+	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet*/
+	public Object getDefaultProperty(int ic) {
+		if (getModel(ic) != null)
+			return getModel(ic);
+		int icLeft = ic;
+		while (--icLeft>=0 && getModel(icLeft) != null)  //looking left
+			return getModel(icLeft);
+		int icRight = ic;
+		while (++icRight< getNumChars() && getModel(icRight) != null)
+			return getModel(icRight);
+		return super.getDefaultModel(ic);
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/SlicedCharacterHistory.java b/Source/mesquite/lib/characters/SlicedCharacterHistory.java
new file mode 100644
index 0000000..225d7a7
--- /dev/null
+++ b/Source/mesquite/lib/characters/SlicedCharacterHistory.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**A CharacterHistory that can indicate changes within branches, e.g.for stochastic character mapping*/
+public interface SlicedCharacterHistory extends CharacterHistory {
+
+	/** gets the sequence of character states along the branch below node it, starting with the ancestral node and going up.  
+	The first state is the first change since the ancestral node.   
+	The particular data types (e.g. continuous, categorical) can have additional more efficient methods, e.g. returning a double[] or long[]*/
+	public CharacterState[] getStateSequenceOnBranch(int it);
+	/** gets the timing of the changes of character states along the branch below node it.  
+	Element i is the time of acquisition of the state of element i from the array returned by getStateSequenceOnBranch.
+	This should be in fractions of the branch's length.  Any elements not corresponding to a state (e.g. extra spaces in the array) should be filled with -1*/
+	public double[] getTimeSequenceOnBranch(int it);
+}
+
+
diff --git a/Source/mesquite/lib/characters/StoredCharacterHistory.java b/Source/mesquite/lib/characters/StoredCharacterHistory.java
new file mode 100644
index 0000000..f5c9e94
--- /dev/null
+++ b/Source/mesquite/lib/characters/StoredCharacterHistory.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/*Last documented:  April 2003 */
+
+/* ======================================================================== */
+/**Used to store character History connected with a tree.  Available but not used as of April 2003.*/
+public class StoredCharacterHistory extends FileElement implements Identifiable  {
+	CharacterHistory history;
+	Tree tree;
+	public StoredCharacterHistory(CharacterHistory history, Tree tree){
+		this.history = history;
+		this.tree = tree;
+	}
+	
+	public CharacterHistory getHistory(){
+		return history;
+	}
+	public NexusBlock addToFile(MesquiteFile f, MesquiteProject proj, ElementManager manager){
+
+		return super.addToFile(f, proj, manager);
+		
+	}
+	public Tree getTree(){
+		return tree;
+	}
+}
+
diff --git a/Source/mesquite/lib/characters/TaxaInfo.java b/Source/mesquite/lib/characters/TaxaInfo.java
new file mode 100644
index 0000000..0be8ae7
--- /dev/null
+++ b/Source/mesquite/lib/characters/TaxaInfo.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+
+import mesquite.categ.lib.CategoricalData;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lib.*;
+import mesquite.lists.lib.ListModule;
+
+
+//used in CharacterData
+public class TaxaInfo extends Associable{
+	CharacterData data;
+	public TaxaInfo(int numParts, CharacterData data){
+		super(numParts);
+		this.data = data;
+	}
+	public String getName(){
+		return "Taxa information for matrix " + data.getName();
+	}
+	public CharacterData getData(){
+		return data;
+	}
+}
diff --git a/Source/mesquite/lib/characters/WholeCharacterModel.java b/Source/mesquite/lib/characters/WholeCharacterModel.java
new file mode 100644
index 0000000..a0ed724
--- /dev/null
+++ b/Source/mesquite/lib/characters/WholeCharacterModel.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.characters; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/** An intermediary superclass that subclasses can extend to help with GUI, so that choices know whether a model
+ is complete (e.g, as in composite DNA mode) or a submodel (e.g., state frequencies model with DNA) */
+public abstract class WholeCharacterModel extends CharacterModel  {
+	
+	public WholeCharacterModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/AnalyticalDrawTree.java b/Source/mesquite/lib/duties/AnalyticalDrawTree.java
new file mode 100644
index 0000000..8813c06
--- /dev/null
+++ b/Source/mesquite/lib/duties/AnalyticalDrawTree.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This is superclass of all Mesquite tree drawing modules.  Creates a TreeDrawing, which does
+the drawing of the tree.  Example modules: ArcTree, BallsNSticks, CircularTree, Constellation, DiagonalDrawTree,
+PlotTree, SquareTree.*/
+
+public abstract class AnalyticalDrawTree extends DrawTree  {
+
+   	public Class getDutyClass() {
+   		return AnalyticalDrawTree.class;
+   	}
+   	 
+	public String getDutyName() {
+ 		return "Analytical Draw Tree";
+   	}
+   	public String[] getDefaultModule() {
+   		return new String[] {"#ContainedAssociates", "#PlotTree", "#PlotTree3D"};
+   	}
+   	   	
+
+   	public boolean isSubstantive(){
+   		return true;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/BooleanForCharacter.java b/Source/mesquite/lib/duties/BooleanForCharacter.java
new file mode 100644
index 0000000..854ba2d
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForCharacter.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.lib.duties;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+public abstract class BooleanForCharacter extends MesquiteModule implements BooleanForItem {
+
+	 public Class getDutyClass() {
+	   	 	return BooleanForCharacter.class;
+	   	 }
+	 	public String getDutyName() {
+	 		return "Boolean for Character";
+	   	 }
+
+	   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	   	public void initialize(CharacterData data){}
+
+		public abstract void calculateBoolean(CharacterData data, int ic, MesquiteBoolean result, MesquiteString resultString); 
+		
+		/*===== For BooleanForItem interface ======*/
+	   	public void initialize(Object object1, Object object2){
+			if (object1 instanceof CharacterData) 
+	   			initialize((CharacterData)object1);
+	   	}
+		public  void calculateBoolean(Object object1, Object object2, int i, MesquiteBoolean result, MesquiteString resultString){
+			if (result==null)
+				return;
+			if (object1 instanceof CharacterData && MesquiteInteger.isCombinable(i)){
+				calculateBoolean((CharacterData)object1, i, result, resultString);
+			}
+		}
+	   	public String getNameOfValueCalculated(){ 
+			return getNameAndParameters();
+	   	}
+		/*.................................................................................................................*/
+		public boolean displayTrueAsDark(){
+			return true;
+		}
+		
+		/*.................................................................................................................*/
+		public String getValueString(boolean on){
+			if (on)
+				return getTrueString();
+			else
+				return getFalseString();
+		}
+
+		/** Returns the text to be used to describe the condition of this boolean being true. */
+		/*.................................................................................................................*/
+		public String getTrueString(){
+			return "True";
+		}
+
+		/** Returns the text to be used to describe the condition of this boolean being false. */
+/*.................................................................................................................*/
+		public String getFalseString(){
+			return "False";
+		}
+
+
+	 	/*.................................................................................................................*/
+	 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	 	public int getVersionOfFirstRelease(){
+			return 201;  
+	 	}
+}
diff --git a/Source/mesquite/lib/duties/BooleanForItem.java b/Source/mesquite/lib/duties/BooleanForItem.java
new file mode 100644
index 0000000..c8368d9
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForItem.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies a boolean for an item.*/
+
+public interface BooleanForItem   {
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Object object1, Object object2);
+   	
+   	public String getParameters();
+   	public String getNameAndParameters();
+	public String accumulateParameters(String spacer);
+   	public String getName();
+	public  void calculateBoolean(Object object1, Object object2, int i, MesquiteBoolean result, MesquiteString resultString);
+   	public String getNameOfValueCalculated();
+}
+
+
diff --git a/Source/mesquite/lib/duties/BooleanForTaxon.java b/Source/mesquite/lib/duties/BooleanForTaxon.java
new file mode 100644
index 0000000..6d80b16
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForTaxon.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.lib.duties;
+
+import mesquite.lib.*;
+
+public abstract class BooleanForTaxon extends MesquiteModule implements BooleanForItem {
+
+	 public Class getDutyClass() {
+	   	 	return BooleanForTaxon.class;
+	   	 }
+	 	public String getDutyName() {
+	 		return "Boolean for Taxon";
+	   	 }
+
+	   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	   	public void initialize(Taxa taxa){}
+
+		public abstract void calculateBoolean(Taxa taxa, int i, MesquiteBoolean result, MesquiteString resultString); 
+		
+		/*===== For BooleanForItem interface ======*/
+	   	public void initialize(Object object1, Object object2){
+			if (object1 instanceof Taxa) 
+	   			initialize((Taxa)object1);
+	   	}
+		public  void calculateBoolean(Object object1, Object object2, int i, MesquiteBoolean result, MesquiteString resultString){
+			if (result==null)
+				return;
+			if (object1 instanceof Taxa && MesquiteInteger.isCombinable(i)) {
+				calculateBoolean((Taxa)object1, i, result, resultString);
+			}
+		}
+		/*.................................................................................................................*/
+		public String getValueString(boolean on){
+			if (on)
+				return getTrueString();
+			else
+				return getFalseString();
+		}
+		/** Returns the text to be used to describe the condition of this boolean being true. */
+		/*.................................................................................................................*/
+		public String getTrueString(){
+			return "True";
+		}
+
+		/** Returns the text to be used to describe the condition of this boolean being false. */
+/*.................................................................................................................*/
+		public String getFalseString(){
+			return "False";
+		}
+	   	public String getNameOfValueCalculated(){ 
+			return getNameAndParameters();
+	   	}
+		/*.................................................................................................................*/
+		public boolean isPrerelease(){
+			return false;
+		}
+	}
diff --git a/Source/mesquite/lib/duties/BooleanForTree.java b/Source/mesquite/lib/duties/BooleanForTree.java
new file mode 100644
index 0000000..8651b08
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForTree.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a boolean for a tree.*/
+
+public abstract class BooleanForTree extends MesquiteModule implements BooleanForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return BooleanForTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Boolean for Tree";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CladeInTree"};
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){}
+
+	public abstract void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString); 
+	
+	/*===== For BooleanForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Tree) 
+   			initialize((Tree)object1);
+   	}
+	public  void calculateBoolean(Object object1, Object object2, int i, MesquiteBoolean result, MesquiteString resultString){
+		if (result==null)
+			return;
+		if (object1 instanceof Tree) {
+			calculateBoolean((Tree)object1, result, resultString);
+		}
+	}
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/lib/duties/BooleanForTreeIncr.java b/Source/mesquite/lib/duties/BooleanForTreeIncr.java
new file mode 100644
index 0000000..1724648
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForTreeIncr.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a boolean for a tree.*/
+
+
+public abstract class BooleanForTreeIncr extends BooleanForTree implements Incrementable  {
+
+   	 public Class getDutyClass() {
+   	 	return BooleanForTreeIncr.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Boolean for Tree (Incrementable)";
+   	 }
+}
+
diff --git a/Source/mesquite/lib/duties/BooleanForTreeM.java b/Source/mesquite/lib/duties/BooleanForTreeM.java
new file mode 100644
index 0000000..a8b8252
--- /dev/null
+++ b/Source/mesquite/lib/duties/BooleanForTreeM.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a boolean for a tree.*/
+
+public abstract class BooleanForTreeM extends BooleanForTree  {
+
+   	 public Class getDutyClass() {
+   	 	return BooleanForTreeM.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Boolean for Tree; may return modified tree";
+   	 }
+	public void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString){
+		calculateBoolean(tree, result, resultString, null);
+	}
+	
+	public abstract void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString, MesquiteTree modifiedTree); 
+	
+}
+
diff --git a/Source/mesquite/lib/duties/BranchLengthsAlterer.java b/Source/mesquite/lib/duties/BranchLengthsAlterer.java
new file mode 100644
index 0000000..1d5aa1d
--- /dev/null
+++ b/Source/mesquite/lib/duties/BranchLengthsAlterer.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class BranchLengthsAlterer extends TreeTransformer  {
+
+   	 public Class getDutyClass() {
+   	 	return BranchLengthsAlterer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Branch Lengths Alterer";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#SetBranchLengths", "#SetSelBranchLengths", "#ScaleBranchLengths", "#ScaleSelBranchLengths", "#DeassignBranchLengths"};
+   	 }
+	
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/BranchLengthsAltererMult.java b/Source/mesquite/lib/duties/BranchLengthsAltererMult.java
new file mode 100644
index 0000000..7a92977
--- /dev/null
+++ b/Source/mesquite/lib/duties/BranchLengthsAltererMult.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class BranchLengthsAltererMult extends BranchLengthsAlterer implements TreeTransformerMult  {
+
+   	 public Class getDutyClass() {
+   	 	return BranchLengthsAltererMult.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Branch Lengths Alterer (multiple trees)";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#SetBranchLengths", "#SetSelBranchLengths", "#ScaleBranchLengths", "#ScaleSelBranchLengths", "#DeassignBranchLengths"};
+   	 }
+	
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/BranchNamesAlterer.java b/Source/mesquite/lib/duties/BranchNamesAlterer.java
new file mode 100644
index 0000000..5e31198
--- /dev/null
+++ b/Source/mesquite/lib/duties/BranchNamesAlterer.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class BranchNamesAlterer extends TreeTransformer  {
+
+   	 public Class getDutyClass() {
+   	 	return BranchNamesAlterer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Branch Names Alterer";
+   	 }
+   	 public String[] getDefaultModule() {
+    	 	return new String[] {"#PercentBranchNames", "#ClearBranchNames"};
+   	 }
+	
+}
+
+
diff --git a/Source/mesquite/lib/duties/BranchNamesAltererMult.java b/Source/mesquite/lib/duties/BranchNamesAltererMult.java
new file mode 100644
index 0000000..98bd3bc
--- /dev/null
+++ b/Source/mesquite/lib/duties/BranchNamesAltererMult.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class BranchNamesAltererMult extends BranchNamesAlterer implements TreeTransformerMult  {
+
+   	 public Class getDutyClass() {
+   	 	return BranchNamesAltererMult.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Branch Names Alterer (multiple trees)";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#PercentBranchNames", "#ClearBranchNames"};
+   	 }
+	
+}
+
+
diff --git a/Source/mesquite/lib/duties/BrowseHierarchy.java b/Source/mesquite/lib/duties/BrowseHierarchy.java
new file mode 100644
index 0000000..bf0c8c5
--- /dev/null
+++ b/Source/mesquite/lib/duties/BrowseHierarchy.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class BrowseHierarchy extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return BrowseHierarchy.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Hierarchy Browser";
+   	}
+ 	public abstract HPanel makeHierarchyPanel();
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CellColorer.java b/Source/mesquite/lib/duties/CellColorer.java
new file mode 100644
index 0000000..621cf6d
--- /dev/null
+++ b/Source/mesquite/lib/duties/CellColorer.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This interface says that a module will color the cells of a character matrix.*/
+public interface CellColorer  {
+
+   	public Color getCellColor(int ic, int it);
+   	public ColorRecord[] getLegendColors();
+   	public void colorsLegendGoAway();
+   	public String getColorsExplanation();
+   	public void viewChanged();
+   	public boolean setActiveColors(boolean active);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/CellColorerCharacters.java b/Source/mesquite/lib/duties/CellColorerCharacters.java
new file mode 100644
index 0000000..9a7979a
--- /dev/null
+++ b/Source/mesquite/lib/duties/CellColorerCharacters.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This interface says that a module will color the cells of a character matrix.*/
+public interface CellColorerCharacters  {
+}
+
+
diff --git a/Source/mesquite/lib/duties/CellColorerMatrix.java b/Source/mesquite/lib/duties/CellColorerMatrix.java
new file mode 100644
index 0000000..fc2647e
--- /dev/null
+++ b/Source/mesquite/lib/duties/CellColorerMatrix.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This interface says that a module will color the cells of a character matrix.*/
+public interface CellColorerMatrix  {
+}
+
+
diff --git a/Source/mesquite/lib/duties/CellColorerTaxa.java b/Source/mesquite/lib/duties/CellColorerTaxa.java
new file mode 100644
index 0000000..dca35b7
--- /dev/null
+++ b/Source/mesquite/lib/duties/CellColorerTaxa.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This interface says that a module will color the cells of a character matrix.*/
+public interface CellColorerTaxa  {
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharHistorySource.java b/Source/mesquite/lib/duties/CharHistorySource.java
new file mode 100644
index 0000000..c16f35f
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharHistorySource.java
@@ -0,0 +1,115 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Assigns states to nodes of tree for a character.
+Example modules:  RecAncestralStates.*/
+
+public abstract class CharHistorySource extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return CharHistorySource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Supply history of evolution of a character along a tree";
+   	 }
+   	 public String[] getDefaultModule() {
+ 		return new String[] {"#RecAncestralStates"};
+   	 }
+   	
+	public abstract boolean allowsStateWeightChoice();
+	
+	public abstract void prepareHistory(Tree tree, int ic);
+	public abstract CharacterHistory getMapping(long im, CharacterHistory history, MesquiteString resultString);
+	public abstract String getMappingTypeName();
+	
+	/* in parlance of these modules, 
+	 * History = assignment of possibly-ambiguous states to nodes, e.g. a usual parsimony reconstruction; usually equivalent to Character
+	 * Mappings = a single sampling or resolution, unambiguous, e.g. from equivocal cycling or stochastic character mapping
+	 */
+	public abstract int getNumberOfHistories(Tree tree);
+	public abstract int getNumberOfHistories(Taxa taxa);
+	public abstract long getNumberOfMappings(Tree tree,  int ic);
+	public abstract long getNumberOfMappings(Taxa taxa,  int ic);
+	
+
+	public void prepareForMappings(boolean permissiveOfNoSeparateMappings){
+	}
+	
+	/** sets whether or not module will be requested to do one character at a time; if so, then it might know to put up menu items
+	to change the model of the character, or adjust it in some other way*/
+   	public void setOneCharacterAtATime(boolean chgbl){}
+
+   	/** returns the name of history ic and mapping im*/
+   	public abstract String getMappingName(Taxa taxa, int ic, long im);
+   	/** returns the name of history ic and mapping im*/
+   	public abstract String getMappingName(Tree tree, int ic, long im);
+ 
+   	/** returns the name of history ic*/
+   	public abstract String getHistoryName(Taxa taxa, int ic);
+   	/** returns the name of history ic*/
+   	public abstract String getHistoryName(Tree tree, int ic);
+  
+   	/** returns the name of histories for menu items, e.g. if each history represents a character, return "Character"*/
+   	public abstract String getHistoryTypeName();
+  
+   	/** queryies the user to choose a history and returns an integer of the history chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numChars = getNumberOfHistories(taxa);
+ 		if (MesquiteInteger.isCombinable(numChars)){
+ 			String[] s = new String[numChars];
+ 			for (int i=0; i<numChars; i++){
+ 				s[i]= getHistoryName(taxa, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose character history", "Choose character history " + forMessage,MesquiteString.helpString,  s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose character history", "Number of character history " + forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return CharacterStates.toInternal(r);
+ 			else
+ 				return r;
+ 		}	
+ 				
+    	}
+   	/** queryies the user to choose a history and returns an integer of the history chosen*/
+   	public int queryUserChoose(Tree tree, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numChars = getNumberOfHistories(tree);
+ 		if (MesquiteInteger.isCombinable(numChars)){
+ 			String[] s = new String[numChars];
+ 			for (int i=0; i<numChars; i++){
+ 				s[i]= getHistoryName(tree, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose character history", "Choose character history " + forMessage, MesquiteString.helpString, s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose character history", "Number of character history " + forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return CharacterStates.toInternal(r);
+ 			else
+ 				return r;
+ 		}	
+ 				
+    	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharMapper.java b/Source/mesquite/lib/duties/CharMapper.java
new file mode 100644
index 0000000..0cd5a61
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMapper.java
@@ -0,0 +1,61 @@
+/* Mesquite.  Copyright 1997 and onward, W. Maddison, D. Maddison & Peter Midford. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+import mesquite.stochchar.CurrentProbModels.*;
+
+/* ======================================================================== */
+public abstract class CharMapper extends MesquiteModule {
+	public Class getDutyClass() {
+		return CharStatesForNodes.class;
+	}
+	public String getDutyName() {
+		return "Assign states or state changes of character to branches of tree, fully resolved, as by stochastic characterMapping";
+	}
+	public String[] getDefaultModule() {
+		return new String[] {"#StochCharMapper"};
+	}
+
+	/*.................................................................................................................*/
+	public  abstract void setObservedStates(Tree tree, CharacterDistribution observedStates);
+	/*.................................................................................................................*/
+
+	public  abstract boolean getMapping(long i, CharacterHistory resultStates, MesquiteString resultString); 
+  	public  abstract void prepareForMappings(boolean permissiveOfNoSeparateMappings); 
+  	
+	public abstract long getNumberOfMappings();
+	
+
+	
+	public String getMappingTypeName(){
+		return "Mapping";
+	}
+
+	/** sets whether or not module will be requested to do one character at a time; if so, then it might know to put up menu items
+	to change the model of the character, or adjust it in some other way*/
+	public void setOneCharacterAtATime(boolean chgbl){}
+
+
+	public abstract boolean allowsStateWeightChoice();
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharMatrixFiller.java b/Source/mesquite/lib/duties/CharMatrixFiller.java
new file mode 100644
index 0000000..ebd3844
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMatrixFiller.java
@@ -0,0 +1,108 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+See description of its subclass, CharMatrixSource.
+*/
+
+public abstract class CharMatrixFiller extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharMatrixFiller.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Matrix Filler";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixSource.gif";
+   	 }
+  	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredMatrices", "#SimulatedMatrix"};
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public abstract int getNumberOfMatrices(Taxa taxa);
+   	/** gets the current matrix.*/
+   	public abstract MCharactersDistribution getCurrentMatrix(Taxa taxa);
+   	/** gets the indicated matrix.*/
+   	public abstract MCharactersDistribution getMatrix(Taxa taxa, int im);
+   	/** gets name of the indicated matrix.*/
+   	public abstract String getMatrixName(Taxa taxa, int im);
+   	/** returns the number of the current matrix*/
+   	public abstract int getNumberCurrentMatrix();
+
+   	/** queryies the user to choose a matrix and returns an integer of the matrix chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numMatrices = getNumberOfMatrices(taxa);
+ 		if (MesquiteInteger.isCombinable(numMatrices)){
+ 			String[] s = new String[numMatrices];
+ 			for (int i=0; i<numMatrices; i++){
+ 				s[i]= getMatrixName(taxa, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose matrix", "Choose matrix " + forMessage, MesquiteString.helpString, s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose matrix", "Number of matrix to choose " + forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return r-1; //r-1 for internal zero based
+ 			else
+ 				return r;
+ 		}
+ 				
+    	}
+        /* -- the following are a preliminary attempt to allow matrix sources to know exactly what tree the 
+        matrix will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated matrix attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public int getNumberOfMatrices(Tree tree){
+   		if (tree==null) return 0;
+   		else return getNumberOfMatrices(tree.getTaxa());
+   	}
+   	/** gets the current matrix.*/
+   	public MCharactersDistribution getCurrentMatrix(Tree tree){
+   		if (tree==null) return null;
+   		else return getCurrentMatrix(tree.getTaxa());
+   	}
+   	/** gets the indicated matrix.*/
+   	public MCharactersDistribution getMatrix(Tree tree, int im){
+   		if (tree==null) return null;
+   		else return getMatrix(tree.getTaxa(), im);
+   	}
+   	/** If this matrix source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a matrix if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public boolean usesTree(){
+   		return false;
+   	}
+        /* ----------------*/
+        
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharMatrixManager.java b/Source/mesquite/lib/duties/CharMatrixManager.java
new file mode 100644
index 0000000..2567865
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMatrixManager.java
@@ -0,0 +1,488 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/** Manages character data matrices of particular types.  Also reads and writes parts of CHARACTERS NEXUS block.  Different data
+types have their own managers, so that the coordinating CharactersManager doesn't need to know about the details.
+Example modules: "Manage Categorical char. matrices" (class ManageCategoricalChars); "Manage DNA/RNA matrices" (class ManageDNARNAChars) 
+"Manage Continuous char. matrices" (class ManageContChars)*/
+
+public abstract class CharMatrixManager extends MesquiteModule   {
+	boolean logVerbose = true;
+
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	public Class getDutyClass() {
+		return CharMatrixManager.class;
+	}
+	public String getDutyName() {
+		return "Manager of Character data matrix, including read/write CHARACTERS block";
+	}
+	/** Process format command of NEXUS CHARACTERS block. Return the resulting CharacterData object*/
+	public abstract mesquite.lib.characters.CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments);
+
+	/** Process command in CHARACTERS block other than FORMAT or MATRIX command (e.g., CHARSTATELABELS command).  Should return true if processed
+	successfully, false if not*/
+	public abstract boolean processCommand(mesquite.lib.characters.CharacterData data, String commandName, String commandString);
+	/** return string consisting of CHARACTERS block for NEXUS file.*/
+	public abstract void writeCharactersBlock(mesquite.lib.characters.CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator);
+	/** return true if can read the data type passed (token from NEXUS file is the string passed, e.g. "STANDARD", "CONTINUOUS") */
+	public abstract boolean readsWritesDataType(String dataType);
+	/** return true if can read the data class passed, e.g. CategoricalData.class) */
+	public abstract boolean readsWritesDataType(Class dataClass);
+	/** Return name of data class managed, for listing in menus and so on (e.g. "DNA data" .*/
+	public abstract String getDataClassName();
+	/** Returns data class managed, e.g. ContinuousData.*/
+	public abstract Class getDataClass();
+	/** return a new CharacterData object for the taxa indicated.*/
+	public abstract mesquite.lib.characters.CharacterData getNewData(Taxa taxa, int numChars);
+
+	//	public abstract void processMatrix(Taxa taxa, CharacterData data, String matrixString, boolean nameTaxa);
+
+	/*.................................................................................................................*/
+	public boolean isLogVerbose() {	
+		return logVerbose;
+	}
+	/*.................................................................................................................*/
+	public void setLogVerbose(boolean logVerbose) {	
+		this.logVerbose = logVerbose;
+	}
+	/*.................................................................................................................*/
+	/** Process the matrix, placing data into passed CharacterData object */
+	public void processMatrix(Taxa taxa, mesquite.lib.characters.CharacterData data, Parser parser, int numChars, boolean nameTaxa, int firstTaxon, boolean makeNewTaxaIfNeeded, boolean fuse, MesquiteFile fileBeingRead) {
+		if (data == null)
+			return;
+		if (taxa == null)
+			taxa = data.getTaxa();
+
+		String taxonName;
+		parser.setLineEndingsDark(false);
+		String d = parser.getNextToken(); //eating MATRIX
+		int extraTaxon = -1;
+		if (fuse){
+			int numTaxa = taxa.getNumTaxa();
+			extraTaxon = numTaxa;
+			taxa.addTaxa(numTaxa-1, 1, false);
+			data.addTaxa(numTaxa-1, 1);
+			NameReference colorNameRef = NameReference.getNameReference("color");
+			for (int it = extraTaxon; it<taxa.getNumTaxa(); it++)
+				taxa.setAssociatedLong(colorNameRef, it, 8, true);
+		}
+		if (numChars<0 || !MesquiteInteger.isCombinable(numChars))
+			numChars = data.getNumChars();
+		int overwritingRule = -1;
+		int PREFEREXISTING = 1;
+		int PREFERINCOMING = 0;
+		int SEPARATENOTOVERWRITE = 2;
+		NameReference colorNameRef = NameReference.getNameReference("color");
+		MesquiteTimer readTime = new MesquiteTimer();
+		MesquiteTimer totalTime = new MesquiteTimer();
+
+		totalTime.start();
+		if (data.interleaved) {  //vvvvvvvv  INTERLEAVED #################################################################
+			boolean warned = false;
+			int[] currentCharacter = new int[taxa.getNumTaxa()];
+			for (int i=firstTaxon; i<taxa.getNumTaxa(); i++) currentCharacter[i] =0;
+			boolean done = false;
+			parser.setLineEndingsDark(false);
+			int it=firstTaxon;
+			String deleteID = MesquiteTrunk.getUniqueIDBase() + taxa.getID();
+			boolean toDelete = false;
+			String problem = null;
+			int lastTaxonNumber = -1;
+			int[] overwrites = new int[taxa.getNumTaxa()];
+			int UNTOUCHED = 0;
+			int NOOVERWRITEBLANK = 1;
+			int OVERWRITE = 2;
+			int warnChimera = -1;
+
+			while (!done && !(isEndLine(taxonName=parser.getNextToken()))) {
+				parser.setLineEndingsDark(true);
+
+				if (nameTaxa && it<taxa.getNumTaxa() && taxa.whichTaxonNumber(taxonName,false,false)>=0){ // this name already exists in taxon block
+					if (fuse){
+						if (toDelete || AlertDialog.query(containerOfModule(), "Duplicated taxa", "Some taxon names in the file being read are the same as some already in the project for the taxa block \"" + taxa.getName() + "\". Do you want to merge these taxa? (example of duplicated name: " + taxonName + ").  WARNING: if these taxa have data in matrices that you are fusing to existing matrices, then the taxon will take on the newly fused values. (cmm1)")){
+							taxa.setTaxonNameNoWarnNoNotify(it, deleteID);
+							toDelete = true;
+						}
+						else 
+							taxa.setTaxonName(it,taxonName);
+					} 
+					else {
+						if (!warned)
+							MesquiteMessage.discreetNotifyUser("Duplicate taxon name in interleaved matrix (" + taxonName + "); file will not be properly read.  Data will be incorrect!");
+						else {
+							MesquiteMessage.warnUser("\n****  Duplicate taxon name in interleaved matrix (" + taxonName + "); file will not be properly read.  Data will be incorrect!");
+							MesquiteModule.showLogWindow(true);
+						}
+						warned=true;
+						if (nameTaxa)  
+							taxa.setTaxonName(it,taxonName);
+					}
+				}
+				else if (nameTaxa && it<taxa.getNumTaxa())  
+					taxa.setTaxonName(it,taxonName);
+
+				int whichTaxon = lastTaxonNumber+1;
+				if (!taxonName.equalsIgnoreCase(taxa.getTaxonName(whichTaxon)))
+					whichTaxon = taxa.whichTaxonNumberRev(taxonName, false);  //use reverse order lookup in case newly added taxa with identical names as previous
+				if (whichTaxon == -1) {
+					if (!warned) {
+						MesquiteMessage.warnUser("Unrecognized taxon name: " + taxonName + " in matrix ");
+						if (problem == null)
+							problem = "Unrecognized taxon name: " + taxonName + " in matrix ";
+						MesquiteModule.showLogWindow(true);
+					}
+					whichTaxon = it % taxa.getNumTaxa();
+				}
+				lastTaxonNumber = whichTaxon;
+				int response = mesquite.lib.characters.CharacterData.OK;
+				CommandRecord.tick("Reading character states for " + taxa.getTaxonName(whichTaxon));
+				if (fuse){   //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv    FUSE
+
+					//first write into extra taxon, in case incoming states are all blank
+					int ice = 0;
+					for (int icc =0; icc< numChars; icc++)
+						data.deassign(icc, extraTaxon);
+					CharacterState csTEST = null;
+					while (ice<numChars && response!=mesquite.lib.characters.CharacterData.EOL) {
+						int prevPos = parser.getPosition();
+						readTime.start();
+						response = data.setStateQuickNexusReading(ice, extraTaxon, parser);
+						readTime.end();
+						csTEST = data.getCharacterState(csTEST, ice, extraTaxon);
+						ice++;
+
+						if (response == CharacterData.ERROR){
+							problem = " taxon " + (whichTaxon +1);
+							int curPos = parser.getPosition();
+							parser.setPosition(prevPos);
+							String chunk = parser.getPieceOfLine(10);
+							parser.setPosition(curPos);
+							problem += " (section of matrix as stored: \"" + chunk + "\")";
+							data.problemReading = problem;
+						}
+					}
+
+
+					if (data.hasDataForTaxon(extraTaxon)){  //something read in.  Now transfer to correct taxon
+						int numRead = ice;
+						if (response==mesquite.lib.characters.CharacterData.EOL)
+							numRead--;
+						boolean overwritten = false;
+						int lastOverwritten = -1;
+						ice = 0;
+						CharacterState cs = null;
+						while (currentCharacter[whichTaxon]<numChars && ice < numRead) {
+							int ic = currentCharacter[whichTaxon];
+							if (fuse && (!(data.isUnassigned(ic, whichTaxon) || data.isInapplicable(ic, whichTaxon))))
+								overwritten = true;
+							cs = data.getCharacterState(cs, ice, extraTaxon);
+							data.setState(ic, whichTaxon, cs);
+							if (overwritten)
+								lastOverwritten = ic;
+							currentCharacter[whichTaxon]++;
+							ice++;
+						}
+						if (overwritten){
+							markAsOverwritten(data, whichTaxon, fileBeingRead);
+							for (int ic = lastOverwritten+1; ic<data.getNumChars(); ic++)
+								data.deassign(ic, whichTaxon);
+						}
+						if (overwrites[whichTaxon] == NOOVERWRITEBLANK)
+							warnChimera = whichTaxon;
+						else
+							overwrites[whichTaxon] = OVERWRITE;
+					}
+					else {
+						if (overwrites[whichTaxon] == OVERWRITE)
+							warnChimera = whichTaxon;
+						else
+							overwrites[whichTaxon] = NOOVERWRITEBLANK;
+					}
+
+				}   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  FUSE
+				else {
+					while (whichTaxon<currentCharacter.length && currentCharacter[whichTaxon]<numChars && response!=mesquite.lib.characters.CharacterData.EOL) {
+						int prevPos = parser.getPosition();
+						int ic = currentCharacter[whichTaxon];
+						readTime.start();
+						response = data.setStateQuickNexusReading(ic, whichTaxon, parser);
+						readTime.end();
+						if (response == CharacterData.ERROR){
+							problem = " taxon " + (whichTaxon +1) + ", character " + (ic + 1);
+							int curPos = parser.getPosition();
+							parser.setPosition(prevPos);
+							String chunk = parser.getPieceOfLine(10);
+							parser.setPosition(curPos);
+							problem += " (section of matrix as stored: \"" + chunk + "\")";
+							data.problemReading = problem;
+						}
+						if (response !=mesquite.lib.characters.CharacterData.EOL)
+							currentCharacter[whichTaxon]++;
+					}
+				}
+
+				if (it==0) 
+					data.interleavedLength=currentCharacter[0];
+				done = true;
+				for (int ic=0; ic<currentCharacter.length; ic++) 
+					if (currentCharacter[ic] != numChars)
+						done = false;
+				parser.setLineEndingsDark(false);
+				it++;
+
+
+			}
+			if (fuse){
+				taxa.deleteTaxa(extraTaxon, 1, false);
+				data.deleteTaxa(extraTaxon, 1);
+			}
+			if (problem != null){
+				discreetAlert("There was a problem reading the character matrix " + data.getName() + ".  It appears that the file is corrupt (" + problem + ").");
+				MesquiteTrunk.errorReportedDuringRun = true;
+			}
+			if (warnChimera>=0){
+				discreetAlert("WARNING: The merging process resulted in INCORRECT assignments of states for taxon " + (warnChimera+1) + " (" + taxa.getTaxonName(warnChimera) + ").  The problem may have affected other taxa as well.  It is recommended that you DO NOT SAVE THE FILE and instead merge again so as to prevent this.  To prevent this, ensure that the incoming (merging) data matrix is NOT INTERLEAVED.  Interleaving the matrix presents special problems in merging.");
+				MesquiteTrunk.errorReportedDuringRun = true;
+			}
+			if (toDelete){
+				for (it = taxa.getNumTaxa()-1; it>=0; it--)
+					if (taxa.getTaxonName(it).equalsIgnoreCase(deleteID)){
+						taxa.deleteTaxa(it, 1, false);
+						data.deleteTaxa(it, 1);
+					}
+				taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			}
+			taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			parser.setLineEndingsDark(false);
+		} //^^^^^^^^  INTERLEAVED #################################################################
+		else {  //vvvvvvvv NOT INTERLEAVED #################################################################
+			String deleteID = MesquiteTrunk.getUniqueIDBase() + taxa.getID();
+			boolean toDelete = false;
+			String problem = null;
+			int lastTaxonNumber = -1;
+
+			for (int it=firstTaxon; it<taxa.getNumTaxa() && !isEndLine(taxonName=parser.getNextToken()); it++) {
+
+				boolean preserveNewTaxon = false;
+				int whichTaxon = -1;
+				if (fuse) {
+					whichTaxon = taxa.whichTaxonNumberRev(taxonName, false);  //use reverse order lookup in case newly added taxa with identical names as previous
+					if (whichTaxon<0){ //name only if absent
+						if (nameTaxa)
+							taxa.setTaxonName(it,taxonName);
+					}
+					else {
+						if (nameTaxa){
+							if (toDelete || AlertDialog.query(containerOfModule(), "Duplicated taxa", "Some taxon names in the file being read are the same as some already in the project for the taxa block \"" + taxa.getName() + "\". Do you want to merge these taxa? (example of duplicated name: " + taxonName + ").  WARNING: if these taxa have data in matrices that you are fusing to existing matrices, then the taxon will take on the newly fused values.  (cmm2)")){
+								taxa.setTaxonNameNoWarnNoNotify(it, deleteID);
+								toDelete = true;
+							}
+							else 
+								taxa.setTaxonName(it,taxonName);
+						}
+					}
+				}
+				else if (nameTaxa){
+					taxa.setTaxonName(it,taxonName);
+				}
+				whichTaxon = lastTaxonNumber+1;
+				if (!taxonName.equalsIgnoreCase(taxa.getTaxonName(whichTaxon)))
+					whichTaxon = taxa.whichTaxonNumberRev(taxonName, false);  //use reverse order lookup in case newly added taxa with identical names as previous
+
+				if (whichTaxon == -1) {
+					if (makeNewTaxaIfNeeded){
+						int numTaxa = taxa.getNumTaxa();
+						taxa.addTaxa(numTaxa-1, 1, false);
+						data.addTaxa(numTaxa-1, 1);
+
+						whichTaxon = numTaxa;
+						Taxon taxon = taxa.getTaxon(whichTaxon);
+						taxon.setName(taxonName);
+					}
+					else {
+						MesquiteMessage.warnUser("Unrecognized taxon name: " + taxonName + " in matrix ");
+						MesquiteModule.showLogWindow(true);
+						whichTaxon = it;
+					}
+				}
+				CommandRecord.tick("Reading character states for " + taxa.getTaxonName(whichTaxon));
+				int ic=0;
+				lastTaxonNumber = whichTaxon;
+				if (fuse){ //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv    FUSE
+					//first write into extra taxon, in case incoming states are all blank
+					ic = 0;
+					for (int icc =0; icc< numChars; icc++)
+						data.deassign(icc, extraTaxon);
+
+					while (ic<numChars) {
+						int prevPos = parser.getPosition();
+						readTime.start();
+						int response = data.setStateQuickNexusReading(ic++, extraTaxon, parser);
+						readTime.end();
+						if (response == CharacterData.ERROR){
+							problem = " taxon " + (whichTaxon +1) + ", character " + (ic);
+							int curPos = parser.getPosition();
+							parser.setPosition(prevPos);
+							String chunk = parser.getPieceOfLine(10);
+							parser.setPosition(curPos);
+							problem += " (section of matrix as stored: \"" + chunk + "\")";
+							data.problemReading = problem;
+						}
+					}
+
+
+
+					if (data.hasDataForTaxon(extraTaxon)){  //something read in.  Now transfer to correct taxon
+						if (data.hasDataForTaxon(whichTaxon)){
+							if (fuse && overwritingRule == -1)
+								overwritingRule = AlertDialog.query(containerOfModule(), "Overwrite states?", "States for taxon " + (whichTaxon+1) + " (" + taxa.getTaxonName(whichTaxon) + ") are already in the matrix, as well as in the incoming matrix.  Do you want to overwrite the old states with the incoming, ignore the incoming states, or create a new taxon with the incoming states?\nNOTE: this will apply to all subsequent taxa with potential for overwriting for this matrix.", "Overwrite", "Ignore", "New Taxon");
+							//	(PREFEREXISTING; PREFERINCOMING;  SEPARATENOTOVERWRITE)
+							if (overwritingRule == SEPARATENOTOVERWRITE){  //don't deassign extra taxon, and invent new taxon and change value of extraTaxon
+								preserveNewTaxon = true;
+								taxa.setTaxonName(extraTaxon, taxa.getUniqueName(taxa.getTaxonName(whichTaxon)+" (for " + data.getName() + ", from file " + fileBeingRead.getFileName() + ")"));
+								taxa.setAssociatedLong(colorNameRef, extraTaxon, 13, true);
+								int numTaxa = taxa.getNumTaxa();
+								taxa.addTaxa(numTaxa-1, 1, false);  //this is for future
+								data.addTaxa(numTaxa-1, 1);
+								taxa.setTaxonName(numTaxa, deleteID);
+							}
+
+						}
+						if (!preserveNewTaxon && overwritingRule != PREFEREXISTING){
+							boolean overwritten = false;
+							int lastOverwritten = -1;
+							ic = 0;
+							CharacterState cs = null;
+							while (ic<numChars) {
+								if (!(data.isUnassigned(ic, whichTaxon) || data.isInapplicable(ic, whichTaxon)))
+									overwritten = true;
+								if (overwritten)
+									lastOverwritten = ic;
+								cs = data.getCharacterState(cs, ic, extraTaxon);
+								data.setState(ic++, whichTaxon, cs);
+							}
+							if (overwritten){
+								markAsOverwritten(data, whichTaxon, fileBeingRead);
+								for (int icc = lastOverwritten+1; icc<data.getNumChars(); icc++)
+									data.deassign(icc, whichTaxon);
+							}
+						}
+					}
+				} // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  FUSE
+				else {
+					while (ic<numChars) {
+						int prevPos = parser.getPosition();
+						readTime.start();
+						int response = data.setStateQuickNexusReading(ic++, whichTaxon, parser);
+						readTime.end();
+						if (response == CharacterData.ERROR){
+							problem = " taxon " + (whichTaxon +1) + ", character " + (ic);
+							int curPos = parser.getPosition();
+							parser.setPosition(prevPos);
+							String chunk = parser.getPieceOfLine(10);
+							parser.setPosition(curPos);
+							problem += " (section of matrix as stored: \"" + chunk + "\")";
+							data.problemReading = problem;
+						}
+					}
+				}
+
+				if (fuse && preserveNewTaxon)
+						extraTaxon++;
+						
+			}
+			if (fuse){
+					taxa.deleteTaxa(extraTaxon, 1, false); 
+					data.deleteTaxa(extraTaxon, 1);
+			}
+			if (problem != null){
+				discreetAlert("There was a problem reading the character matrix " + data.getName() + ".  It appears that the file is corrupt (" + problem + ").");
+				MesquiteTrunk.errorReportedDuringRun = true;
+			}
+			if (toDelete){
+				for (int it = taxa.getNumTaxa()-1; it>=0; it--)
+					if (taxa.getTaxonName(it).equalsIgnoreCase(deleteID)){
+						taxa.deleteTaxa(it, 1, false);
+						data.deleteTaxa(it, 1);
+					}
+				taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			}
+
+			taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		}  //^^^^^^^^ NOT INTERLEAVED #################################################################
+
+		totalTime.end();
+	}
+	
+	NameReference orRef = NameReference.getNameReference("Overwritten");
+	private void markAsOverwritten(CharacterData data, int whichTaxon, MesquiteFile fileBeingRead){
+		Associable tInfo = data.getTaxaInfo(true);
+
+		Object obj = tInfo.getAssociatedObject(orRef, whichTaxon);
+		String s = "";
+		if (obj != null && obj instanceof String)
+			s = "; " + (String)obj;
+		s = "Overwritten by states from file " + fileBeingRead.getFileName() + " on " + getDateAndTime() + s;
+		tInfo.setAssociatedObject(orRef, whichTaxon, s);
+
+		MesquiteMessage.warnUser("NOTE: Previous states in matrix \"" + data.getName() + "\" for taxon " + (whichTaxon+1) + " (" + data.getTaxa().getTaxonName(whichTaxon) + ") overwritten using states from file " + fileBeingRead.getFileName());
+
+		MesquiteModule.showLogWindow(true);
+	}
+	private boolean isEndLine(String tN){
+		if (tN == null)
+			return true;
+		return tN.equals(";");
+	}
+
+	protected String getIDsCommand(mesquite.lib.characters.CharacterData data){
+		String s = "";
+		if (anyIDs(data, 0)){
+			s += "IDS ";
+			for (int it=0; it<data.getNumChars() && anyIDs(data, it); it++) {
+				String id = data.getUniqueID(it);
+				if (StringUtil.blank(id))
+					s += " _ ";
+				else
+					s += id + " ";
+			}
+			s += ";" + StringUtil.lineEnding();
+		}
+		if (!StringUtil.blank(data.getUniqueID()))
+			s += "\tBLOCKID " + data.getUniqueID() + ";" + StringUtil.lineEnding();
+		if (StringUtil.blank(s))
+			return null;
+		return s;
+	}
+	boolean anyIDs(mesquite.lib.characters.CharacterData data, int start){
+		for (int ic=start; ic<data.getNumChars(); ic++) {
+			String id = data.getUniqueID(ic);
+			if (!StringUtil.blank(id))
+				return true;
+		}
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharMatrixObedSource.java b/Source/mesquite/lib/duties/CharMatrixObedSource.java
new file mode 100644
index 0000000..4f3abeb
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMatrixObedSource.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+See description of its subclass, CharMatrixSource.
+*/
+
+public abstract class CharMatrixObedSource extends CharMatrixFiller implements ItemsSource  {
+
+   	 public Class getDutyClass() {
+   	 	return CharMatrixObedSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Matrix Source (obed.)";
+   	 }
+        
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+		CommandRecord.tick("Getting matrix " + ic);
+   		return getMatrix(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfMatrices(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Matrix";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Matrices";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+ 	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getMatrixName(taxa, ic);
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharMatrixOneSource.java b/Source/mesquite/lib/duties/CharMatrixOneSource.java
new file mode 100644
index 0000000..49501f7
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMatrixOneSource.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+
+/**
+A class whose declaration is exactly the same as a CharMatrixSource, since both can return character matrices one at a time.
+The only distinction is to know purpose hired, so the CharMatrixOneSource can respond with parameters informing
+about current matrix, while CharMatrixSource can respond in general terms about the matrices it produces.*/
+
+public abstract class CharMatrixOneSource extends CharMatrixObedSource  {
+
+   	 public Class getDutyClass() {
+   	 	return CharMatrixOneSource.class;
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredMatrices", "#SimulatedMatrix"};
+   	 }
+}
+
diff --git a/Source/mesquite/lib/duties/CharMatrixSource.java b/Source/mesquite/lib/duties/CharMatrixSource.java
new file mode 100644
index 0000000..f599a8f
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharMatrixSource.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies character matrices for use in calculation routines.  See its superclass
+CharMatrixObedSource for methods.  
+A Taxa object must be passed to the class's methods because
+the matrices that are relevant may be Taxa specific.  For instance, only some of the available data matrices
+in a file might apply to a given set of taxa, or a matrix may consist of all possible binary character 
+distributions for a given set of taxa.<p>
+This class assumes there is a current matrix that is active, and
+available on request.
+<p>
+This class of modules is a simple subclass of CharMatrixObedSource.  The only reason for the distinction is to allow a module to
+know why it was hired.  A CharMatrixObedSource is not to take control of which matrix is current; it is to allow its
+employers complete control.  Thus a CharMatrixObedSource should not add menu items for which data set is to be used.
+On the other hand, a CharMatrixSource can have such menu items and force a change to the next matrix.
+*/
+
+public abstract class CharMatrixSource extends CharMatrixOneSource  {
+
+   	 public Class getDutyClass() {
+   	 	return CharMatrixSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Matrix Source";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredMatrices", "#SimulatedMatrix"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharModelCurator.java b/Source/mesquite/lib/duties/CharModelCurator.java
new file mode 100644
index 0000000..821b6a2
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharModelCurator.java
@@ -0,0 +1,219 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class CharModelCurator extends MesquiteModule  {
+	Vector modelsToEdit= new Vector();  //provided to keep track of modules being edited (management methods also provided)
+	Vector windowServers= new Vector();//provided in case window holder modules used
+
+	public Class getDutyClass() {
+		return CharModelCurator.class;
+	}
+	public String getDutyName() {
+		return "Model Curator";
+	}
+
+
+	/**Edit model.  Editing must be done in a modal dialog box becuase the results are needed immediately.*
+   	public abstract void editModelModal(CharacterModel model);  //NOT YET IMPLEMENTED
+	 */
+	public abstract String getNameOfModelClass();
+	public abstract String getNEXUSNameOfModelClass();
+	public abstract boolean curatesModelClass(Class modelClass);
+	public abstract Class getModelClass();
+	/**Make new model and return (don't add to file or show to edit)*/
+	public abstract CharacterModel makeNewModel(String name);
+	public abstract CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format);
+	public boolean isSubstantive(){
+		return false;  
+	}
+
+	public void endJob(){
+		for (int i=0; i<modelsToEdit.size(); i++) {
+			CharacterModel model = getModel(i);
+			if (model!=null)
+				model.removeListener(this);
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	protected MesquiteWindow getWindow(int i){
+		if (i>=0 && i< windowServers.size()) {
+			Object obj = windowServers.elementAt(i);
+			if (obj instanceof MesquiteModule)
+				return (MesquiteWindow)((MesquiteModule)windowServers.elementAt(i)).getModuleWindow();
+		}
+		return null;
+	}
+	protected MesquiteModule getWindowHolder(int i){
+		if (i>=0 && i< windowServers.size()) {
+			Object obj = windowServers.elementAt(i);
+			if (obj instanceof MesquiteModule)
+				return (MesquiteModule)windowServers.elementAt(i);
+		}
+		return null;
+	}
+	protected CharacterModel getModel(int i){
+		if (i>=0 && i< modelsToEdit.size()) {
+			Object obj = modelsToEdit.elementAt(i);
+			if (obj instanceof CharacterModel)
+				return (CharacterModel)obj;
+		}
+		return null;
+	}
+	protected int getModelNumber(CharacterModel model){
+		return modelsToEdit.indexOf(model);
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		int i = windowServers.indexOf(m);
+		if (i>=0) {
+			CharacterModel model = getModel(i);
+			if (model!=null) {
+				model.removeListener(this);
+				modelsToEdit.removeElement(model);
+			}
+			windowServers.removeElement(m);
+		}
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj instanceof CharacterModel){
+			int i = modelsToEdit.indexOf(obj);
+			if (i>=0) {
+				fireEmployee(getWindowHolder(i));
+				windowServers.removeElement(obj);
+				CharacterModel m = getModel(i);
+				if (m!=null)
+					m.removeListener(this);
+				modelsToEdit.removeElementAt(i);
+			}
+		}
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void disposeModel(CharacterModel model) {
+		getProject().removeFileElement(model);//must remove first, before disposing
+		model.dispose();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (modelsToEdit.size() ==0)
+			return null;
+		Snapshot temp = new Snapshot();
+		for (int i=0; i<modelsToEdit.size(); i++) {
+			temp.addLine("editModel " + ParseUtil.tokenize(getModel(i).getName()), getWindowHolder(i));
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Edits the character model", "[name of character model]", commandName, "editModel")) {
+			CharacterModel model = getProject().getCharacterModel(parser.getFirstToken(arguments));
+			if (model !=null) {
+				return showEditor(model);
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Makes new character model", "[name of character model]", commandName, "newModel")) {
+			String name = MesquiteString.queryShortString(containerOfModule(), "New "+getName(), "Name of new "+getName()+":", getProject().getCharacterModels().getUniqueName(getName()));
+			if (name==null)
+				return null;
+			CharacterModel model = makeNewModel(name);
+			model.addToFile(null, getProject(), null); //TODO:ok to add to homefile, or query user?
+			//MesquiteModule[] curators = null;
+			//curators = CharacterModel.findCurators(this, model.getClass());
+			showEditor(model);
+			if (model.getEditCancel()) {
+				disposeModel(model);
+				return null;
+			}
+			resetAllMenuBars();
+			return model;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/**Edit model.  Editing to be done in non-modal window, which is to be returned in the ObjectContainer.
+	Returns the module to whom commands are to be sent (in case WindowServer used).  Methods using window holder service should override this*/
+	public MesquiteModule editModelNonModal(CharacterModel model, ObjectContainer window){
+		return this;
+	}
+
+	/*.................................................................................................................*/
+	/**Edit model.  Editing to be done in non-modal window.  Methods not using window holder service could override this.  Returns the module that owns the window produced.*/
+	public MesquiteModule showEditor(CharacterModel model){
+		if (model == null)
+			return null;
+		int i = getModelNumber(model);
+		if (i>=0) {
+			MesquiteModule windowServer = getWindowHolder(i);
+			if (windowServer == null) {
+				alert("error: model found but window holder not found");
+				return null;
+			}
+			MesquiteWindow win = windowServer.getModuleWindow();
+			if (win!=null)
+				win.show();
+			return windowServer;
+		}
+		ObjectContainer w = new ObjectContainer();
+		MesquiteModule mod = editModelNonModal(model, w);
+		MesquiteWindow window = (MesquiteWindow)w.getObject();
+		modelsToEdit.addElement(model);
+		model.addListener(this);
+
+		if (mod !=null) {
+			windowServers.addElement(mod);
+			if (window!=null)
+				mod.setModuleWindow(window);
+		}
+		if (window!=null)
+			window.setDefaultAnnotatable(model);
+
+
+		if (mod != null)
+			mod.resetContainingMenuBar();
+		resetContainingMenuBar();
+
+		if (window !=null){ 
+			if (!MesquiteThread.isScripting())
+				window.setVisible(true);
+			resetAllWindowsMenus();
+		}
+
+		return mod;
+	}
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharSelectCoordinator.java b/Source/mesquite/lib/duties/CharSelectCoordinator.java
new file mode 100644
index 0000000..4e74e05
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharSelectCoordinator.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public abstract class CharSelectCoordinator extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return CharSelectCoordinator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character selection coordinator";
+   	 }
+	public abstract void setTableAndObject(MesquiteTable table, Object object, boolean rows);
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharSourceCoord.java b/Source/mesquite/lib/duties/CharSourceCoord.java
new file mode 100644
index 0000000..e9bafd9
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharSourceCoord.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public abstract class CharSourceCoord extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharSourceCoord.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Independent Character Source Coordinator";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CharSrcCoordIndep"};
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/charSource.gif";
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+   	/** gets the current character.*/
+   	public abstract CharacterDistribution getCurrentCharacter(Taxa taxa);
+
+        /* -- the following are a preliminary attempt to allow matrix sources to know exactly what tree the 
+        matrix will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated matrix attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+
+   	/** If this matrix source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a matrix if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public boolean usesTree(){
+   		return false;
+   	}
+   	
+   	/** gets the current matrix.*/
+   	public CharacterDistribution getCurrentCharacter(Tree tree){
+   		if (tree==null) return null;
+   		else return getCurrentCharacter(tree.getTaxa());
+   	}
+	/*.................................................................................................................*/
+   	public abstract String getCurrentCharacterName(Taxa taxa);
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharSourceCoordObed.java b/Source/mesquite/lib/duties/CharSourceCoordObed.java
new file mode 100644
index 0000000..a5b4fcd
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharSourceCoordObed.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+A class whose declaration is exactly the same as a CharacterSource & CharacterOneSource, since both can return characters one at a time.
+The only distinction is to know purpose hired.  If hired as an obedient source, the module should not control the current character, for instance
+(if hired as not obedient, it is free to do so).  See similar organization in CharMatrixObedSource.*/
+
+public abstract class CharSourceCoordObed extends MesquiteModule implements ItemsSource  {
+
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/charSource.gif";
+   	 }
+  	 public Class getDutyClass() {
+   	 	return CharSourceCoordObed.class;
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CharSrcCoordObed"};
+   	 }
+ 	public String getDutyName() {
+ 		return "Obedient Character Source Coordinator";
+   	 }
+	public abstract void setHiringCondition(Object obj);
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+   	/** returns character numbered ic*/
+   	public abstract CharacterDistribution getCharacter(Taxa taxa, int ic);
+   	/** returns number of characters for given Taxa*/
+   	public abstract int getNumberOfCharacters(Taxa taxa);
+
+   	/** queryies the user to choose a character and returns an integer of the character chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numChars = getNumberOfCharacters(taxa);
+ 		if (MesquiteInteger.isCombinable(numChars)){
+ 			String[] s = new String[numChars];
+ 			for (int i=0; i<numChars; i++){
+ 				s[i]= getCharacterName(taxa, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose character", "Choose character " + forMessage, MesquiteString.helpString,  s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose character", "Number of character " + forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return CharacterStates.toInternal(r);
+ 			else
+ 				return r;
+ 		}	
+ 				
+    	}
+   	/** returns the name of character ic*/
+   	public abstract String getCharacterName(Taxa taxa, int ic);
+
+        /* -- the following are a preliminary attempt to allow character sources to know exactly what tree the 
+        character will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated character attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public int getNumberOfCharacters(Tree tree){
+   		if (tree==null) return 0;
+   		else return getNumberOfCharacters(tree.getTaxa());
+   	}
+   	/** gets the indicated matrix.*/
+   	public CharacterDistribution getCharacter(Tree tree, int ic){
+   		if (tree==null) return null;
+   		else return getCharacter(tree.getTaxa(), ic);
+   	}
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Tree tree, int ic){
+   		if (tree==null) return null;
+   		else return getCharacterName(tree.getTaxa(), ic);
+   	}
+    	/** If this character source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a character if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public boolean usesTree(){
+   		return false;
+   	}
+        /* ----------------*/
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+		CommandRecord.tick("Getting character " + ic);
+   		return getCharacter(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+		CommandRecord.tick("");
+   		return getNumberOfCharacters(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Character";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Characters";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	
+   	CharSelectionSet charHighlightSet;
+   	mesquite.lib.characters.CharacterData highlightData;
+   	String charSetName;
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+ 	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getCharacterName(taxa, ic);
+   	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharSpecsSetManager.java b/Source/mesquite/lib/duties/CharSpecsSetManager.java
new file mode 100644
index 0000000..6079158
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharSpecsSetManager.java
@@ -0,0 +1,321 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/** Manages spec sets.*/
+
+/* ======================================================================== */
+public abstract class CharSpecsSetManager extends SpecsSetManager {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	public NexusBlock elementAdded(FileElement e){
+		if (e!=null && e instanceof mesquite.lib.characters.CharacterData){
+			e.prepareSpecsSetVector(getElementClass(), upperCaseTypeName() + "s");
+		}
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public abstract String upperCaseTypeName();
+	public abstract String lowerCaseTypeName();
+	public abstract String nexusToken();
+	public String alternativeNexusToken(){
+		return null;
+	}
+	public abstract SpecsSet getNewSpecsSet(String name, mesquite.lib.characters.CharacterData data);
+	public abstract boolean appropriateBlockForWriting(String blockName);
+	public abstract boolean appropriateBlockForReading(String blockName);
+	public abstract Object getSpecification(String token);
+	public abstract void setSpecification(SpecsSet specsSet, Object specification, int ic);
+	public boolean hasSpecificationTokens(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	protected boolean writeLinkWithCharacterMatrixName(MesquiteFile file, CharacterData data){
+		return (file.getProject().getNumberCharMatrices()>1 || (!file.useSimplifiedNexus&&  !file.useConservativeNexus && !data.hasDefaultName() && !NexusBlock.suppressTITLE));
+	}
+	
+/*.................................................................................................................*/
+ 	/** A method called immediately after the project has been established.*/
+ 	public void projectEstablished() {
+		 CharactersManager manager = (CharactersManager)findElementManager(mesquite.lib.characters.CharacterData.class);
+		if (manager == null)
+			return;
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.charactersMenu, manager.getListsSubmenu(), upperCaseTypeName() + "s", makeCommand("showList",  this));
+		/**
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.charactersMenu, upperCaseTypeName() + "s", makeCommand("showList",  this),  (ListableVector)getProject().datas);
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		mmis.setOwnerModuleID(getID());
+		/**/
+		super.projectEstablished();
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant) {
+				mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)e.doCommand("getData", null, CommandChecker.defaultChecker);
+  	 			MesquiteWindow w = e.getModuleWindow();
+  	 			if (w != null && w.isVisible())
+  	 				temp.addLine("showList " + getProject().getMatrixNumber(data), e); 
+  	 		}
+		}
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Shows the " + lowerCaseTypeName(), "[optional: number of data matrix for which to show " + lowerCaseTypeName() + "]", commandName, "showList")) {
+    	 		if (StringUtil.blank(arguments)) {
+	    	 		for (int i = 0; i< getProject().getNumberCharMatrices(checker.getFile()); i++) {
+	    	 			showSpecsSets(getProject().getCharacterMatrix(checker.getFile(), i), "List of " + upperCaseTypeName() + "s");
+				}
+    	 		}
+    	 		else {
+       	 			int t = MesquiteInteger.fromFirstToken(arguments, pos);
+ 	 			if (MesquiteInteger.isCombinable(t) && t<getProject().getNumberCharMatrices(checker.getFile())) {
+ 	 				return showSpecsSets(getProject().getCharacterMatrix(checker.getFile(), t), "List of " + upperCaseTypeName() + "s");
+ 	 			}
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSetStandard(CharSpecsSet specsSet, mesquite.lib.characters.CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(getElementClass().isAssignableFrom(specsSet.getClass())))
+			return null;
+		ModelSet modelSet = (ModelSet)specsSet;
+		String s= "";
+		if (modelSet !=null  && (modelSet.getFile()==file || (modelSet.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			boolean firstTime = true;
+			Enumeration enumeration = file.getProject().getCharacterModels().elements();
+			while (enumeration.hasMoreElements()){
+				Object obj = enumeration.nextElement();
+				CharacterModel cm = (CharacterModel)obj;
+				String q = ListableVector.getListOfMatches(modelSet.getModels(), cm, CharacterStates.toExternal(0));
+				if (q != null) {
+					if (!firstTime) {
+						sT += ", ";
+					}
+					sT += StringUtil.tokenize(cm.getNEXUSName()) + ": " + q;
+					firstTime = false;
+				}
+			}
+			if (!StringUtil.blank(sT)) {
+				s+= nexusToken()+ " " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(modelSet.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= "  = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+   	}
+	/*.................................................................................................................*/
+	public abstract String nexusStringForSpecsSet(CharSpecsSet specsSet, mesquite.lib.characters.CharacterData data, MesquiteFile file, boolean isCurrent);
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (appropriateBlockForWriting(blockName)) { 
+			String s= "";
+	 		for (int ids = 0; ids<file.getProject().getNumberCharMatrices(file); ids++) {
+				mesquite.lib.characters.CharacterData data =  file.getProject().getCharacterMatrix(file, ids);
+				if (data.getFile() == file && data.getWritable()){
+					int numSets = data.getNumSpecsSets(getElementClass());
+					SpecsSetVector ssv = data.getSpecSetsVector(getElementClass());
+					if (ssv!=null){
+						SpecsSet ms = (SpecsSet)data.getCurrentSpecsSet(getElementClass());
+						if (ms!=null && (ms.getNexusBlockStored()==null || blockName.equalsIgnoreCase(ms.getNexusBlockStored()))) {
+							ms.setNexusBlockStored(blockName);
+							ms.setName("UNTITLED");
+							s += nexusStringForSpecsSet( (CharSpecsSet)ms, data, file, true);
+						}
+						
+							
+						for (int ims = 0; ims<numSets; ims++) {
+							CharSpecsSet cs = (CharSpecsSet)data.getSpecsSet(ims, getElementClass());
+							s += nexusStringForSpecsSet(cs, data, file, false);
+						}
+					}
+				}
+			}
+			return s;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (appropriateBlockForReading(blockName)) { 
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+
+			String commandName = ParseUtil.getToken(command, startCharT);
+			if (commandName == null)
+				return false;
+			if (commandName.equalsIgnoreCase(nexusToken()) || (alternativeNexusToken()!=null && commandName.equalsIgnoreCase(alternativeNexusToken()))) {
+				String token = ParseUtil.getToken(command, startCharT);
+				boolean isDefault = false;
+				if ("*".equals(token)) {
+					isDefault = true;
+					token = ParseUtil.getToken(command, startCharT);
+				}
+				String nameOfSpecsSet = StringUtil.deTokenize(token); // name of specs set 
+				token = ParseUtil.getToken(command, startCharT);
+				if (token == null)
+					return false;
+				//String paradigmString = null;
+				MesquiteProject project = file.getProject();
+				mesquite.lib.characters.CharacterData data=null;
+				String dataName = null;
+				
+				if (token.equalsIgnoreCase("(")) {
+					token = ParseUtil.getToken(command, startCharT); //CHARACTERS  //TODO: check to see what parameter is being set!
+					token = ParseUtil.getToken(command, startCharT); //=
+					token = (ParseUtil.getToken(command, startCharT)); // name of data
+
+					dataName = token;
+					data = project.getCharacterMatrixByReference(file, dataName);
+					token = (ParseUtil.getToken(command, startCharT)); // )
+					token = ParseUtil.getToken(command, startCharT);  // =
+				}
+				else if (project.getNumberCharMatrices(file)>0) //should use first in this file
+					data= project.getCharacterMatrix(file,0);
+				if (data == null) {
+					if (dataName!=null)
+						data = project.getCharacterMatrixByReference(null, dataName);
+					else
+						data= project.getCharacterMatrix(0);
+				}
+					
+				if (data==null) {
+					MesquiteMessage.discreetNotifyUser("Sorry, a " + lowerCaseTypeName() + " could not be read because its associated data set was not found.  This can occur if you are fusing files, or if you have edited files by hand or with another program.  Another possible cause is that your current Mesquite configuration doesn't include packages to read matrices of that type.  Try restarting Mesquite after selecting \"Use all installed packages\" in the Activate/Deactivate submenu of the File menu [...]
+					return false;
+				}
+				if (data.getSuppressSpecssetReading())
+					return true;  //acting as everything is fine, but in fact specset was ignored
+				if ("=".equals(token))
+					token = ParseUtil.getToken(command, startCharT);  //getting name of first model
+
+				//CharactersGroup defaultProperty =  new CharactersGroup();
+	
+				Object specification = getSpecification(token);
+				
+		 		SpecsSet specsSet= getNewSpecsSet(nameOfSpecsSet, data);
+		 		specsSet.setNexusBlockStored(blockName);
+				
+				int lastChar = -1;
+				boolean join = false;
+				boolean nextIsCharList = !hasSpecificationTokens();
+				while (token !=null && !token.equals(";") && token.length()>0) {
+					if (token.equals("-")) {
+						if (lastChar!=-1)
+							join = true;
+					}
+					else {
+						if (token != null && token.equals("."))
+							token = Integer.toString(data.getNumChars());
+						if (token.startsWith("-")) {
+							if (lastChar!=-1)
+								join = true;
+							token = token.substring(1, token.length());
+						}
+						if (token.equals(":")) {
+							nextIsCharList = true;
+						}
+						else if (token.equals(","))
+							nextIsCharList=false;
+						else if (nextIsCharList) {
+							int whichChar = CharacterStates.toInternal(MesquiteInteger.fromString(token, false));
+							if (MesquiteInteger.isCombinable(whichChar) && whichChar>=0) {
+								if (whichChar>= data.getNumChars())
+									whichChar = data.getNumChars()-1;
+								
+								if (join) {
+									int skip = 1;
+									//check here if next char is "\"; if so then need to skip
+									int temp = startCharT.getValue();
+									token = ParseUtil.getToken(command, startCharT); 
+									if (token.equals("\\")){
+										token = ParseUtil.getToken(command, startCharT); 
+										int tSkip = MesquiteInteger.fromString(token, false);
+										if (MesquiteInteger.isCombinable(tSkip))
+											skip = tSkip;
+									}
+									else
+										startCharT.setValue(temp);
+									for (int j = lastChar; j<=whichChar; j += skip) {
+										setSpecification(specsSet, specification,j);
+									}
+									join = false;
+									lastChar = -1;
+								}
+								else {
+									lastChar = whichChar;
+									setSpecification(specsSet, specification,whichChar);
+								}
+							}
+						}
+						else {
+							specification =  getSpecification(token);
+							nextIsCharList = true;
+						}
+					}
+					token = ParseUtil.getToken(command, startCharT); 
+				}
+				
+				if (isDefault) {
+					if (!"UNTITLED".equals(specsSet.getName())) {
+			 			data.storeSpecsSet(specsSet, getElementClass());
+			 		}
+			 		specsSet.addToFile(file, getProject(), this);
+			 		SpecsSet ss = specsSet.cloneSpecsSet();
+					data.setCurrentSpecsSet(ss, getElementClass());
+				}
+				else {
+		 			data.storeSpecsSet(specsSet, getElementClass());
+			 		specsSet.addToFile(file, getProject(), this);
+			 	}
+			 	return true;
+			}
+		}
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharStatesForNodes.java b/Source/mesquite/lib/duties/CharStatesForNodes.java
new file mode 100644
index 0000000..f8110e3
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharStatesForNodes.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Assigns states to nodes of tree for a character.
+Example modules:  ParsAncestralStates, MaxPosteriorJoint, MLEAncestralStates.
+In 1. 1 this was moved to be subclass of CharMapper.  Employers using as before would call calculateStates and it should behave as before.  Employers using as CharMapper
+have that one's abstract methods filled in to use the calcu*/
+
+public abstract class CharStatesForNodes extends CharMapper  {
+   	 public Class getDutyClass() {
+   	 	return CharStatesForNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assign states of character to nodes";
+   	 }
+   	 public String[] getDefaultModule() {
+ 		return new String[] {"#ParsAncestralStates"};
+   	 }
+   	public  void prepareForMappings( boolean permissiveOfNoSeparateMappings) {
+  	}
+	
+	public abstract boolean calculateStates(Tree tree, CharacterDistribution charStates, CharacterHistory resultStates, MesquiteString resultString); 
+	/*.................................................................................................................*/
+	protected Tree tree;
+	protected CharacterDistribution observedStates;
+	public  void setObservedStates(Tree tree, CharacterDistribution observedStates){
+			this.tree = tree;
+			this.observedStates = observedStates;
+			
+	}
+	/*.................................................................................................................*/
+ 	
+  	public  boolean getMapping(long i, CharacterHistory resultStates, MesquiteString resultString){
+  		if (tree == null || observedStates == null)
+  			return false;
+  		return calculateStates(tree, observedStates, resultStates, resultString);
+  	}
+
+	public  long getNumberOfMappings(){
+		return 1;
+	}
+	public String getMappingTypeName(){
+		return "Mapping";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharSubmodelCurator.java b/Source/mesquite/lib/duties/CharSubmodelCurator.java
new file mode 100644
index 0000000..84d7b8d
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharSubmodelCurator.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class CharSubmodelCurator extends CharModelCurator  {
+
+   	 public Class getDutyClass() {
+   	 	return CharSubmodelCurator.class;
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharTableAssistantI.java b/Source/mesquite/lib/duties/CharTableAssistantI.java
new file mode 100644
index 0000000..7f41be7
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharTableAssistantI.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/**This is superclass of modules to assist tables with characters (e.g., character List, data matrix editor).  
+These are INITs.*/
+
+public abstract class CharTableAssistantI extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharTableAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Character Table";
+   	}
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+  	/** method called by data window to inform assistant that data have changed*/
+	public abstract void setTableAndData(MesquiteTable table, mesquite.lib.characters.CharacterData data, boolean charactersAreRows);
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharacterModelSource.java b/Source/mesquite/lib/duties/CharacterModelSource.java
new file mode 100644
index 0000000..f81741c
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterModelSource.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies character models for use in calculation routines.
+These methods must be passed a Data or a CharacterDistribution object because which models are appropriate will depend on these*/
+
+public abstract class CharacterModelSource extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharacterModelSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Model Source";
+   	 }
+   	/** returns model for character ic in data */
+   	public abstract CharacterModel getCharacterModel(mesquite.lib.characters.CharacterData data, int ic);
+   	/** returns model for character represented by states */
+   	public abstract CharacterModel getCharacterModel(CharacterStatesHolder states);
+   	
+   	/** returns whether requires an input CharacterData or can run off of any CharacterDistribution. Default is false. Should be overridden as appropriate. */
+   	public boolean requiresCharacterData(){
+   		return false;
+   	}
+   	
+   	/**sets whether module may reassign a different model to current character; indicates that employers will have only one character active
+   	at a time, and thus a menu item to change the active character's model is appropriate*/
+   	public void setOneCharacterAtATime(boolean chgbl){}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharacterObedSource.java b/Source/mesquite/lib/duties/CharacterObedSource.java
new file mode 100644
index 0000000..f2213c3
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterObedSource.java
@@ -0,0 +1,150 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+A class whose declaration is exactly the same as a CharacterSource & CharacterOneSource, since both can return characters one at a time.
+The only distinction is to know purpose hired.  If hired as an obedient source, the module should not control the current character, for instance
+(if hired as not obedient, it is free to do so).  See similar organization in CharMatrixObedSource.*/
+
+public abstract class CharacterObedSource extends MesquiteModule implements ItemsSource  {
+
+   	 public Class getDutyClass() {
+   	 	return CharacterObedSource.class;
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredCharacters", "#SimulatedCharacters"};
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Source (obed.)";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/charSource.gif";
+   	 }
+  	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+   	/** returns character numbered ic*/
+   	public abstract CharacterDistribution getCharacter(Taxa taxa, int ic);
+   	/** returns number of characters for given Taxa*/
+   	public abstract int getNumberOfCharacters(Taxa taxa);
+
+   	/** queryies the user to choose a character and returns an integer of the character chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numChars = getNumberOfCharacters(taxa); 
+ 		if (MesquiteInteger.isCombinable(numChars)){
+ 			String[] s = new String[numChars];
+ 			for (int i=0; i<numChars; i++){
+ 				s[i]= getCharacterName(taxa, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose character", "Choose character " + forMessage, MesquiteString.helpString, s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose character", "Number of character " + forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return CharacterStates.toInternal(r);
+ 			else
+ 				return r;
+ 		}	
+ 				
+    	}
+   	/** returns the name of character ic*/
+   	public abstract String getCharacterName(Taxa taxa, int ic);
+
+        /* -- the following are a preliminary attempt to allow character sources to know exactly what tree the 
+        character will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated character attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public int getNumberOfCharacters(Tree tree){
+   		if (tree==null) return 0;
+   		else return getNumberOfCharacters(tree.getTaxa());
+   	}
+   	/** gets the indicated matrix.*/
+   	public CharacterDistribution getCharacter(Tree tree, int ic){
+   		if (tree==null) return null;
+   		else return getCharacter(tree.getTaxa(), ic);
+   	}
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Tree tree, int ic){
+   		if (tree==null) return null;
+   		else return getCharacterName(tree.getTaxa(), ic);
+   	}
+    	/** If this character source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a character if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public boolean usesTree(){
+   		return false;
+   	}
+        /* ----------------*/
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+		CommandRecord.tick("Getting character " + ic);
+   		return getCharacter(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+		CommandRecord.tick("");
+   		return getNumberOfCharacters(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Character";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Characters";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	
+   	CharSelectionSet charHighlightSet;
+   	mesquite.lib.characters.CharacterData highlightData;
+   	String charSetName;
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getCharacterName(taxa, ic);
+   	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharacterOneSource.java b/Source/mesquite/lib/duties/CharacterOneSource.java
new file mode 100644
index 0000000..c633336
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterOneSource.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+A class whose declaration is exactly the same as a CharacterSource, since both can return characters one at a time.
+The only distinction is to know purpose hired, so the CharacterOneSource can respond with parameters informing
+about current character, while CharacterSource can respond in general terms about the characters it produces.*/
+
+public abstract class CharacterOneSource extends CharacterObedSource  {
+
+   	 public Class getDutyClass() {
+   	 	return CharacterOneSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Source";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredCharacters", "#SimulatedCharacters"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharacterSelector.java b/Source/mesquite/lib/duties/CharacterSelector.java
new file mode 100644
index 0000000..3aadf6d
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterSelector.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to select characters in a table.*/
+
+public abstract class CharacterSelector extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharacterSelector.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character selector";
+   	}
+   	
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to select the characters.  It should only add to a selection, not deselect any currently selected.*/
+   	public abstract void selectCharacters(mesquite.lib.characters.CharacterData data);
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/CharacterSimulator.java b/Source/mesquite/lib/duties/CharacterSimulator.java
new file mode 100644
index 0000000..6e4027c
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterSimulator.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Simulates characters.  */
+
+public abstract class CharacterSimulator extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharacterSimulator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Simulator";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/simulate.gif";
+   	 }
+	/** Indicates the type of character created (e.g., "CategoricalState")*/ 
+	public abstract Class getStateClass();
+	
+	/** Does any needed initializations. */ 
+   	public void initialize(Taxa taxa){}
+	//TODO: return also the states at internals!!!!
+	/** Returns a character for the terminal taxa (place in passed CharacterDistribution if it is non-null, and return the same reference, or create
+	new one otherwise). */ 
+   	public abstract CharacterDistribution getSimulatedCharacter(CharacterDistribution statesAtTips, Tree tree, MesquiteLong seed);
+	/** Returns a character for all the nodes in the tree (place in passed CharacterDistribution if it is non-null, and return the same reference, or create
+	new one otherwise). */ 
+   	public abstract CharacterHistory getSimulatedHistory(CharacterHistory statesAtNodes, Tree tree, MesquiteLong seed);
+	/** Returns maximum number of characters to simulate. */ 
+   	public int getMaximumNumChars(Taxa taxa){
+   		return MesquiteInteger.infinite;
+   	}
+	/** Returns default number of characters to simulate. */ 
+   	public int getDefaultNumChars(){
+   		return 100;
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharacterSource.java b/Source/mesquite/lib/duties/CharacterSource.java
new file mode 100644
index 0000000..f87aee6
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharacterSource.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies characters for use in calculation routines.  
+These methods must be passed a Taxa object because which characters are appropriate may depend on the
+taxa*/
+
+public abstract class CharacterSource extends CharacterOneSource  {
+	public static MesquiteBoolean storedAsDefault = new MesquiteBoolean(true);
+	public static MesquiteBoolean closeIfMatrixDeleted = new MesquiteBoolean(false);
+   	 public Class getDutyClass() {
+   	 	return CharacterSource.class;
+   	 }
+   	 public static boolean useStoredAsDefault(){
+   		 return storedAsDefault.getValue() || (mesquite.lib.simplicity.InterfaceManager.isSimpleMode());
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredCharacters", "#SimulatedCharacters"};
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/charSource.gif";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharactersManager.java b/Source/mesquite/lib/duties/CharactersManager.java
new file mode 100644
index 0000000..aeb6724
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharactersManager.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+
+
+/* ======================================================================== */
+/** Coordinates managers of character data matrices. Relies on CharMatrixManagers for the details of
+each data type.  Example module: "Manage CHARACTERS blocks" (class ManageCharacters)*/
+
+public abstract class CharactersManager extends FileElementManager   {
+
+   	 public Class getDutyClass() {
+   	 	return CharactersManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Coordinator of managers of character data matrices";
+   	 }
+ 	 public String[] getDefaultModule() {
+    	 	return new String[] {"#ManageCharacters"};
+    	 }
+	/** create new CharacterData object with data type indicated by passed string.  String is *not* NEXUS keyword
+	for data type, but rather the descriptive phrase returned by the CharMatrixManagers' getDataClassName methods.*/
+	public abstract mesquite.lib.characters.CharacterData newCharacterData(Taxa taxa, int numChars, String dataType);
+	
+	public abstract String[] dataClassesAvailable();
+	
+	public abstract mesquite.lib.characters.CharacterData processFormat(MesquiteFile file, Taxa taxa, String formatCommand, int numChars, String title, String fileReadingArguments);
+	
+	/**Returns the module that reads and writes matrices of a particular subclass*/
+	public abstract CharMatrixManager getMatrixManager(Class dataClass);
+	public abstract MesquiteModule getListOfCharactersModule(CharacterData data, boolean showIfClosed);
+
+	public Class getElementClass(){
+		return mesquite.lib.characters.CharacterData.class;
+	}
+ 	public abstract MesquiteSubmenuSpec getListsSubmenu();
+ 	
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/CharsStatesForNodes.java b/Source/mesquite/lib/duties/CharsStatesForNodes.java
new file mode 100644
index 0000000..588b40e
--- /dev/null
+++ b/Source/mesquite/lib/duties/CharsStatesForNodes.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Assigns states to nodes based on a character source.*/
+
+public abstract class CharsStatesForNodes extends MesquiteModule  {
+	public static final int version = 2; //TODO: what's this???
+	public int oldNumTaxa = 0; //TODO: are these needed????
+	public int oldNumChars = 0;
+
+   	 public Class getDutyClass() {
+   	 	return CharsStatesForNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assign states of characters to nodes";
+   	 }
+	public abstract MCharactersHistory calculateStates(Tree tree, MCharactersDistribution observedStates, MCharactersHistory resultStates, MesquiteString resultString);
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/ChartAssistant.java b/Source/mesquite/lib/duties/ChartAssistant.java
new file mode 100644
index 0000000..751d3ff
--- /dev/null
+++ b/Source/mesquite/lib/duties/ChartAssistant.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*A superclass for the various subclasses of ChartAssistant (I, D and A)*/
+
+public abstract class ChartAssistant extends MesquiteModule  {
+	
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/chart.gif";
+   	 }
+ 	 public Class getDutyClass() {
+   	 	return ChartAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Chart";
+   	 }
+	public  abstract ChartExtra createExtra(MesquiteChart chart);
+	public boolean canHireMoreThanOnce(){
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/lib/duties/Consenser.java b/Source/mesquite/lib/duties/Consenser.java
new file mode 100644
index 0000000..3f8c4eb
--- /dev/null
+++ b/Source/mesquite/lib/duties/Consenser.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Does tree consensus .*/
+
+public abstract class Consenser extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return Consenser.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Consensus tree calculator";
+   	 }
+  	public abstract Tree consense(Trees list);
+   
+ }
+
+
+
diff --git a/Source/mesquite/lib/duties/CuratorWithSettings.java b/Source/mesquite/lib/duties/CuratorWithSettings.java
new file mode 100644
index 0000000..c57ce5c
--- /dev/null
+++ b/Source/mesquite/lib/duties/CuratorWithSettings.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+Model curators that wish to have their names listed under Model Settings need to implement this.*/
+
+public interface CuratorWithSettings  {
+	public void editSettings();
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataAlterer.java b/Source/mesquite/lib/duties/DataAlterer.java
new file mode 100644
index 0000000..2fa69be
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataAlterer.java
@@ -0,0 +1,146 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class DataAlterer extends MesquiteModule  {
+	protected  long numCellsAltered =MesquiteLong.unassigned;
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditorUtil.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return DataAlterer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Alterer";
+   	}
+   	
+   	public long getNumCellsAltered(){
+   		return numCellsAltered;
+   	}
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table.  Returns true if data altered.  For those DataAlterers that supply AlteredDataParameters, this method should be overridden. */
+   	public  boolean alterData(mesquite.lib.characters.CharacterData data, MesquiteTable table, UndoReference undoReference, AlteredDataParameters alteredDataParameters){
+   		return alterData(data,table,undoReference);
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table.  Returns true if data altered*/
+   	public abstract boolean alterData(mesquite.lib.characters.CharacterData data, MesquiteTable table, UndoReference undoReference);
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter the data in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public void alterCell(mesquite.lib.characters.CharacterData data, int ic, int it){
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in cells in table. This is used if the altering procedure can be done on one cell
+   	at a time, independent of all other cells.  If the altering procedure involves dependencies between cells,
+   	then a different method must be built.  */
+   	public boolean alterContentOfCells(mesquite.lib.characters.CharacterData data, MesquiteTable table, UndoReference undoReference){
+   		if (data.getEditorInhibition()){
+			discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+   			return false;
+   		}
+   		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+   		numCellsAltered =MesquiteLong.unassigned;
+		boolean did=false;
+ 		if (table==null && data!=null){    // alter entire matrix
+			for (int i=0; i<data.getNumChars(); i++)
+				for (int j=0; j<data.getNumTaxa(); j++) {
+						alterCell(data,i,j);
+				}
+			return true;
+ 		}
+ 		else if (table!=null && data !=null){
+   	 		boolean[][] done = new boolean[table.getNumColumns()][table.getNumRows()];
+   			if (table.anyCellSelected()) {
+				for (int i=0; i<table.getNumColumns(); i++)
+					for (int j=0; j<table.getNumRows(); j++)
+						if (!done[i][j] && table.isCellSelected(i,j)) {
+							alterCell(data,i,j);
+							did = true;
+							done[i][j]=true;
+						}
+			}
+			if (table.anyRowSelected()) {
+				for (int j=0; j<table.getNumRows(); j++) {
+					if (table.isRowSelected(j))
+						for (int i=0; i<table.getNumColumns(); i++) {
+							if (!done[i][j]) {
+								alterCell(data,i,j);
+								done[i][j]=true;
+							}
+							did = true;
+						}
+				}
+			}
+			if (table.anyColumnSelected()) {
+				for (int i=0; i<table.getNumColumns(); i++){
+					if (table.isColumnSelected(i))
+						for (int j=0; j<table.getNumRows(); j++) {
+							if (!done[i][j]) {
+								alterCell(data,i,j);
+								done[i][j]=true;
+							}
+							did=true;
+						}
+				}
+			}
+			if (!table.anythingSelected()) {
+				for (int i=0; i<data.getNumChars(); i++)
+					for (int j=0; j<data.getNumTaxa(); j++) {
+							if (!done[i][j])
+								alterCell(data,i,j);
+					}
+				return true;
+			}
+		}
+ 		if (undoInstructions!=null) {
+ 			undoInstructions.setNewData(data);
+ 			if (undoReference!=null){
+ 				undoReference.setUndoer(undoInstructions);
+ 				undoReference.setResponsibleModule(this);
+ 			}
+ 		}
+		if (MesquiteLong.isCombinable(numCellsAltered))
+			logln("Number of data cells altered: " + numCellsAltered);
+		return did;
+   	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/DataAltererCon.java b/Source/mesquite/lib/duties/DataAltererCon.java
new file mode 100644
index 0000000..c842a1a
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataAltererCon.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.lib.duties;
+
+
+ import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+ public abstract class DataAltererCon extends DataAlterer {
+
+	 /** An abstract sublcass of DataAlterer intended to only work on contiguous blocks of selected cells in each taxon.
+	  * It requires that AT MOST ONE such block of cells is selected in each taxon; i.e., within each taxon discontinuous selections
+	  * are not allowed. */
+
+	 public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		 return true;
+	 }
+
+	 /** Called to alter data in those cells selected in table*/
+	 public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+		 if (data.getEditorInhibition()){
+				discreetAlert("This matrix is marked as locked against editing. To unlock, uncheck the menu item Matrix>Current Matrix>Editing Not Permitted");
+			 return false;
+		 }
+		 boolean did=false;
+	   		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+		 if ((table==null || !table.anyCellSelectedAnyWay()) && data!=null){
+
+			 alterBlockOfCharacters(data, 0, data.getNumChars()-1);
+			 did = true;
+		 }
+		 else if (table!=null && data !=null){
+				 boolean okToFlip = true;
+				 boolean somethingToFlip = false;
+				 for (int j=0; j<table.getNumRows(); j++) {
+					 if (table.singleContiguousBlockSelected(j, null, null))
+						 somethingToFlip = true;
+					 else if (table.numCellsSelectedInRow(j)>0){ //selected, but not contiguous
+						 alert("Sorry, can't "+ getName() + " when selection of characters is discontinuous within any taxa");
+						 okToFlip = false;
+						 break;
+					 }
+				 }
+
+				 if (data.anySelected() && data.contiguousSelection()){ //any characters selected? If so, assume contiguous block is just there
+					 int first = data.firstSelected();
+					 int last = data.lastSelected();
+					 alterBlockOfCharacters(data, first, last);
+					 did = true;
+
+				 }
+				 else {
+				 if (okToFlip && somethingToFlip){
+					 MesquiteInteger start = new MesquiteInteger();
+					 MesquiteInteger end = new MesquiteInteger();
+					 for (int j=0; j<table.getNumRows(); j++) {
+						 if (table.singleContiguousBlockSelected(j, start, end)){
+							 alterBlockInTaxon(data, start.getValue(), end.getValue(), j);
+							 did = true;
+						 }
+					 }
+				 }
+			 }
+
+		 }
+		 if (undoInstructions!=null) {
+			 undoInstructions.setNewData(data);
+			 if (undoReference!=null){
+				 undoReference.setUndoer(undoInstructions);
+				 undoReference.setResponsibleModule(this);
+			 }
+		 }
+		 if (did)
+			 data.notifyInLinked(new Notification(DATA_CHANGED));
+		 return did;
+	 }
+
+
+	 public abstract boolean alterBlockInTaxon(CharacterData data, int icStart, int icEnd, int it);
+	 public abstract boolean alterBlockOfCharacters(CharacterData data, int icStart, int icEnd);
+
+ }
diff --git a/Source/mesquite/lib/duties/DataColumnNamesAssistant.java b/Source/mesquite/lib/duties/DataColumnNamesAssistant.java
new file mode 100644
index 0000000..5345e79
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataColumnNamesAssistant.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+
+/* ======================================================================== */
+public abstract class DataColumnNamesAssistant extends MesquiteModule  {
+	protected mesquite.lib.characters.CharacterData data=null;
+	protected MesquiteTable table=null;
+	
+   	 public Class getDutyClass() {
+   	 	return DataColumnNamesAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data column names panel assistant";
+   	 }
+	/**  Set the table and data for the module.  This allows the rest of Mesquite to communicate to the module
+	 * the MesquiteTable and CharacterData objects.  The module should store the table and data so that they can 
+	 * use them in the drawInCell method.  */
+   	public abstract void setTableAndData(MesquiteTable table, mesquite.lib.characters.CharacterData data);
+   
+	/** Draw cell for row ic */
+	public abstract void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected);
+	
+
+	/** Returns string to be placed in cell for row */
+	public  String getStringForCharacter(int ic){
+		return "";
+	}
+
+	/** Returns string to be displayed in explanation area on mouseover of cell */
+	public String getStringForExplanation(int ic){
+		return "";
+	}
+
+	/** Returns widest string in column; can return by default a long string for safety */
+	public String getWidestString(){
+		return "";
+	}
+	public boolean canHireMoreThanOnce(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean similarChar(int ic, int ic2) {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the first (if right is true) or last (if right is false) character in the next block with the same 
+	properties as the block that is touched */
+	public boolean getNextBlock(int touched, boolean right, MesquiteInteger startBlock, MesquiteInteger endBlock) {
+		if (data==null || startBlock==null || endBlock==null)
+			return false;
+		boolean currentBlock = true;
+		boolean sim = false;
+		startBlock.setValue(0);
+		endBlock.setValue(data.getNumChars()-1);
+		if (right) {
+			for (int ic=touched+1; ic<data.getNumChars(); ic++) {
+				sim = similarChar(touched,ic);
+				if (!sim)
+					currentBlock = false;
+				else if (sim && !currentBlock) {
+					startBlock.setValue(ic);
+					for (int ic2=ic+1; ic2<data.getNumChars(); ic2++) {
+						if (!similarChar(touched,ic2)) {
+							endBlock.setValue(ic2-1);
+							break;
+						}
+					}
+					return true;
+				}
+			}
+			return false;
+		}
+		else {  // going left
+			for (int ic=touched-1; ic>=0; ic--) {
+				sim = similarChar(touched,ic);
+				if (!sim)
+					currentBlock = false;
+				else if (sim && !currentBlock) { 
+					endBlock.setValue(ic);
+					for (int ic2=ic-1; ic2>=0; ic2--) {
+						if (!similarChar(touched,ic2)) {
+							startBlock.setValue(ic2+1);
+							break;
+						}
+					}
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+	/*.................................................................................................................*/
+	public String toString() {
+		return "";
+ 	}
+	/*.................................................................................................................*/
+	public void setElement(int which) {
+ 	}
+	public int getColumnWidth(){
+		return 0;
+	}
+	/** Returns title of item */
+	public abstract String getTitle();
+}
+
diff --git a/Source/mesquite/lib/duties/DataMatcher.java b/Source/mesquite/lib/duties/DataMatcher.java
new file mode 100644
index 0000000..d1d1e5f
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataMatcher.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+
+public abstract class DataMatcher extends MesquiteModule  {
+	protected MesquiteTable table;
+	protected mesquite.lib.characters.CharacterData data;
+	protected mesquite.lib.characters.CharacterState state;
+
+
+   	 public Class getDutyClass() {
+   	 	return DataMatcher.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Matcher";
+   	}
+	/*.................................................................................................................*/
+	public void setTableAndData( MesquiteTable table, mesquite.lib.characters.CharacterData data) {
+		this.table = table;
+		this.data =data;
+		state = data.makeCharacterState();
+	}
+   	/*.................................................................................................................*/
+   	/** this method holds whatever preparation calls are needed just before use of this method */
+	public void prepare() {
+	}
+   	/*.................................................................................................................*/
+   	/** specifies whether or not the match module can function if the master piece is entirely inapplicable data */
+	public boolean requiresApplicable() {
+		return true;
+	}   	
+ 	/*.................................................................................................................*/
+   	/** Returns the value of the best possible match.  Should be overridden by subclasses if they can calculate the value.*/
+	public abstract double getBestMatchValue(CharacterState[] csOriginalArray) ;
+	/*.................................................................................................................*/
+   	/** Returns the approximate value of the worst possible match.  Should be overridden by subclasses if they can calculate the value.*/
+	public abstract double getApproximateWorstMatchValue(CharacterState[] csOriginalArray) ;
+  	/*.................................................................................................................*/
+   	/** Returns the value of the best possible match.  Should be overridden by subclasses if they can calculate the value.*/
+	public double getBestMatchValue() {
+		return MesquiteDouble.unassigned;
+	}   	
+ 	/*.................................................................................................................*/
+   	/** Returns the value of the worst possible match.  Should be overridden by subclasses if they can calculate the value.*/
+	public double getWorstMatchValue() {
+		return MesquiteDouble.unassigned;
+	}   	
+	/*.................................................................................................................*/
+   	/** Returns whether or not better matches have higher values or not.*/
+	public boolean getHigherIsBetter() {
+		return true;
+	}   	
+
+  	/** Returns whether candidate sequence beginning at candidateStartChar matches a stretch of the matrix (originalTaxon from originalStartChar to originalEndChar) .  
+   	candidateEndChar might be null or not; if it is not null, then this method should return in it the end character of any match. */
+   	public double sequenceMatch(mesquite.lib.characters.CharacterData data, MesquiteTable table, int originalTaxon, int originalStartChar, int originalEndChar, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar){
+   		return sequenceMatch(data,table,data.getCharacterStateArray(originalTaxon,originalStartChar,originalEndChar),candidateTaxon, candidateStartChar, candidateEndChar);
+   	}
+
+   	/** Returns whether candidate stretch of matrix matches the data passed in the CharacterState array csOriginalArray*/
+   	public double sequenceMatch(mesquite.lib.characters.CharacterData data, MesquiteTable table, CharacterState[] csOriginalArray, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar){
+   		setTableAndData(table,data);
+   		return sequenceMatch(csOriginalArray,  candidateTaxon,candidateStartChar,candidateEndChar);
+   	}
+
+   	/** Returns whether candidate stretch of matrix, in taxon candidateTaxon, starting at candidateStartChar, ending at candidateEndChar,
+   	 *  matches the data passed in the CharacterState array csOriginalArray.   Note that while candidateStartChar is fixed, candidateEndChar is not, and 
+   	 *  the length of the potential matching region iis determined by the module, and the chosen end character is to be returned in candidateEndChar.*/
+   	public abstract double sequenceMatch(CharacterState[] csOriginalArray, int candidateTaxon, int candidateStartChar, MesquiteInteger candidateEndChar);
+
+  	/** Returns whether the match for the two given CharacterState arrays.*/
+   	public abstract double sequenceMatch(CharacterState[] csOriginalArray, CharacterState[] csCandidateArray);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataSearcher.java b/Source/mesquite/lib/duties/DataSearcher.java
new file mode 100644
index 0000000..a54b636
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataSearcher.java
@@ -0,0 +1,112 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to search a portion a data matrix.*/
+
+public abstract class DataSearcher extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return DataSearcher.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Searcher";
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to search data in those cells selected in table.  Returns true if search successful*/
+   	public abstract boolean searchData(mesquite.lib.characters.CharacterData data, MesquiteTable table);
+   	
+	/*.................................................................................................................*/
+   	/** True iff one cannot ask for a search involving all or part of multiple taxa*/
+   	public  boolean canSearchMoreThanOnePiece() {
+   		return false;
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Processing to be done after each search.  Returns true iff the number of columns changed in the process).*/
+   	public boolean processAfterEachTaxonSearch(mesquite.lib.characters.CharacterData data, int it){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** message if search failed to find anything.  */
+	public void unsuccessfulSearchMessage(){
+	}
+	/*.................................................................................................................*/
+   	/** Called to search data in a table. This is used if the searching procedure can be done on the selected region in one taxon
+   	at a time, independent of all other taxa.  If the searching procedure involves dependencies between taxa,
+   	then a different method must be built.  */
+   	public boolean searchSelectedTaxa(mesquite.lib.characters.CharacterData data, MesquiteTable table){
+		boolean did=false;
+ 		if (table==null && data!=null){    // alter entire matrix
+ 			if (canSearchMoreThanOnePiece() || data.getNumTaxa()==1)
+ 				return false;
+			for (int j=0; j<data.getNumTaxa(); j++) {
+				if (searchOneTaxon(data,j,0,data.getNumChars()))
+					processAfterEachTaxonSearch(data, j); 
+				else
+					unsuccessfulSearchMessage();
+			}
+			did = true;
+			return true;
+ 		}
+ 		else if (table!=null && data !=null){
+ 		//	table.resetLastInSelectedBlock();
+ 			MesquiteInteger row = new MesquiteInteger();
+ 			MesquiteInteger firstColumn = new MesquiteInteger();
+ 			MesquiteInteger lastColumn = new MesquiteInteger();
+ 	
+ 			while (table.nextSingleRowBlockSelected(row, firstColumn, lastColumn)) { 
+ 				if (searchOneTaxon(data,row.getValue(), firstColumn.getValue(), lastColumn.getValue())){
+ 					boolean resetColumns = processAfterEachTaxonSearch(data, row.getValue());
+ 					if (resetColumns){  //
+ 						lastColumn.setValue(data.getNumChars());
+ 						firstColumn.setValue(0);
+ 					}
+ 				}
+				else {
+					unsuccessfulSearchMessage();
+				}
+				did = true;
+ 			}
+ 			if (!did)
+				discreetAlert( "Sorry, to use the search you need to have one or more stretches of character states (e.g. a section of sequence) selected in one or more taxa.");
+		}
+		return did;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to search the data selected .  If you use the searchSelectedTaxa method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean searchOneTaxon(mesquite.lib.characters.CharacterData data, int it, int icStart, int icEnd){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/DataUtility.java b/Source/mesquite/lib/duties/DataUtility.java
new file mode 100644
index 0000000..80ffbed
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataUtility.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class DataUtility extends MesquiteModule  {
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditorUtil.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return DataUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Utility";
+   	}
+   	
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public abstract boolean operateOnData(mesquite.lib.characters.CharacterData data);
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/DataWSelectionAssistant.java b/Source/mesquite/lib/duties/DataWSelectionAssistant.java
new file mode 100644
index 0000000..6b3e0c6
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWSelectionAssistant.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist data matrix editor.  These are INITs.*/
+
+public abstract class DataWSelectionAssistant extends DataWindowAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return DataWSelectionAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Selection Assistant for Data Window";
+   	}
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#SearchSelect", "#SelectSame", "#SelectSameVert"};
+   	 }
+
+   	/** if returns true, then requests to remain on even after setTableAndData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataWindowAssistant.java b/Source/mesquite/lib/duties/DataWindowAssistant.java
new file mode 100644
index 0000000..ea2bb2d
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWindowAssistant.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist data matrix editor, for analysis (has menu item in menu).*/
+public abstract class DataWindowAssistant extends MesquiteModule  {
+	boolean active = false;
+
+   	 public Class getDutyClass() {
+   	 	return DataWindowAssistant.class;
+   	 }
+   	 
+   	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditor.gif";
+   	 }
+  	/** method called by data window to inform assistant that data have changed*/
+	public abstract void setTableAndData(MesquiteTable table, mesquite.lib.characters.CharacterData data);
+	
+	//called by data editor when selection changed
+	public void tableSelectionChanged(){
+	}
+  	public void colorsLegendGoAway(){
+  	}
+  	 	
+ 	public String getDutyName() {
+ 		return "Data Window Assistant";
+   	}
+   	public boolean hasDisplayModifications(){
+   		return false;
+   	}
+   	public String getDisplayModString(int ic, int it){
+   		return null;
+   	}
+   	public String getCellString(int ic, int it){
+   		return null;
+   	}
+  	public String getCellExplanation(int ic, int it){
+  		return null;
+	}
+  	public void focusInCell(int ic, int it){
+  		
+	}
+ 	public void setActive(boolean a){
+   		active = a;
+   	}
+   	public boolean isActive(){
+   		return active;
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataWindowAssistantA.java b/Source/mesquite/lib/duties/DataWindowAssistantA.java
new file mode 100644
index 0000000..b650c2f
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWindowAssistantA.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist data matrix editor.*/
+
+
+public abstract class DataWindowAssistantA extends DataWindowAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return DataWindowAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Window Assistant (Analysis)";
+   	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataWindowAssistantI.java b/Source/mesquite/lib/duties/DataWindowAssistantI.java
new file mode 100644
index 0000000..e228791
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWindowAssistantI.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist data matrix editor.  These are INITs.*/
+
+public abstract class DataWindowAssistantI extends DataWindowAssistant  {
+   	 public Class getDutyClass() {
+   	 	return DataWindowAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Data Window";
+   	}
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#AddDeleteData", "#AlterData"};
+   	 }
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataWindowAssistantID.java b/Source/mesquite/lib/duties/DataWindowAssistantID.java
new file mode 100644
index 0000000..1bd22fa
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWindowAssistantID.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist data matrix editor.  These are INITs.*/
+
+public abstract class DataWindowAssistantID extends DataWindowAssistantI  {
+   	 public Class getDutyClass() {
+   	 	return DataWindowAssistantID.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Data Window; Display";
+   	}
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#NoColor", "#ColorCells", "#ColorByState", "ColorByFootnote"};
+   	 }
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DataWindowMaker.java b/Source/mesquite/lib/duties/DataWindowMaker.java
new file mode 100644
index 0000000..d7b5170
--- /dev/null
+++ b/Source/mesquite/lib/duties/DataWindowMaker.java
@@ -0,0 +1,51 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to present data matrix editor.*/
+
+public abstract class DataWindowMaker extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return DataWindowMaker.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data Window Maker";
+   	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+   	//not abstract so as not to cause incompatibilities with 1.12 and previous modules
+ 	 public void resignCellColorer(MesquiteModule m){
+ 	 }
+  	 public abstract void requestCellColorer(MesquiteModule m, int ic, int it, String message);
+   	 public abstract void demandCellColorer(MesquiteModule m, int ic, int it, String message);
+
+  	 public abstract mesquite.lib.characters.CharacterData getCharacterData();
+  	 public abstract void linkEditor(DataWindowMaker mb, boolean linkeeIsNew);
+  	 public abstract void unlinkEditor(DataWindowMaker mb);
+	public abstract MesquiteTable getTable();
+	public void setAsExtra(boolean e){
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DefaultsAssistant.java b/Source/mesquite/lib/duties/DefaultsAssistant.java
new file mode 100644
index 0000000..9484014
--- /dev/null
+++ b/Source/mesquite/lib/duties/DefaultsAssistant.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Serves to hold a window for an employer.*/
+
+public abstract class DefaultsAssistant extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return DefaultsAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Defaults Assistant";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+   	public MesquiteCMenuItemSpec addCheckMenuItemToDefaults(MesquiteMenuSpec mms, String label, MesquiteCommand command, MesquiteBoolean b){
+   		return MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, label, command, b);
+   	}
+	public MesquiteMenuItemSpec addMenuItemToDefaults(MesquiteMenuSpec whichMenu, String label, MesquiteCommand command){
+  		return addMenuItem(label, command);
+   	}
+	public MesquiteMenuItemSpec addMenuItemToDefaults(String label, MesquiteCommand command){
+  		return MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, label, command);
+   	}
+	public MesquiteSubmenuSpec addSubmenuToDefaults(String submenuName){
+ 		MesquiteSubmenuSpec mss = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.defaultsSubmenu, submenuName);
+ 		return mss;
+ 	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DisplayCharsStsAtNodes.java b/Source/mesquite/lib/duties/DisplayCharsStsAtNodes.java
new file mode 100644
index 0000000..9035cbe
--- /dev/null
+++ b/Source/mesquite/lib/duties/DisplayCharsStsAtNodes.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Displays the character states of many characters on the tree, for instance using charts at each node.  Example
+module: ChartCharsStOnTree.  Example of use: TraceAllCharacters. 
+*/
+
+public abstract class DisplayCharsStsAtNodes extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return DisplayCharsStsAtNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Display States of characters at nodes";
+   	 }
+   	 
+	/** 	Create TreeDecorator.  The TreeDecorator is used to display the states using a two step process:
+	first, its method calculateOnTree(Tree tree, Object obj) is called to prepare the decorator's memory.
+	Then, when graphical updates are needed, drawOnTree(tree, drawnRoot, g) is called.  */
+	public   TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DisplayNumbersAtNodes.java b/Source/mesquite/lib/duties/DisplayNumbersAtNodes.java
new file mode 100644
index 0000000..86615d5
--- /dev/null
+++ b/Source/mesquite/lib/duties/DisplayNumbersAtNodes.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Displays numbers at nodes on tree.  Example modules: LabelNumbersOnTree.*/
+
+public abstract class DisplayNumbersAtNodes extends MesquiteModule  {
+	protected MesquiteBoolean showLabels= new MesquiteBoolean(false);
+	protected MesquiteBoolean shadeBranches= new MesquiteBoolean(true);   // added DRM 07.iv.14
+	protected MesquiteBoolean shadeInColor= new MesquiteBoolean(true);
+	protected MesquiteBoolean labelTerminals= new MesquiteBoolean(true);  // added DRM 07.iv.14
+	protected MesquiteBoolean usePercentages= new MesquiteBoolean(false);  // added DRM 1 October 2014
+
+	public Class getDutyClass() {
+   	 	return DisplayNumbersAtNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Display Numbers At Nodes";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#LabelNumbersOnTree"};
+   	 }
+   	 
+   	 /** create tree decorator which will do the drawing.  The tree decorator's 
+   	 method drawOnTree(Tree tree, Object obj, Graphics g) will be called to draw the states*/
+	public TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		return null;
+	}
+	public boolean getShowLabels() {
+		return showLabels.getValue();
+	}
+	public void setShowLabels(boolean showLabels) {
+		this.showLabels.setValue(showLabels);
+	}
+	public boolean getShadeBranches() {
+		return shadeBranches.getValue();
+	}
+	public void setShadeBranches(boolean shadeBranches) {
+		this.shadeBranches.setValue(shadeBranches);
+	}
+	public boolean getShadeInColor() {
+		return shadeInColor.getValue();
+	}
+	public void setShadeInColor(boolean shadeInColor) {
+		this.shadeInColor.setValue(shadeInColor);
+	}
+	public boolean getLabelTerminals() {
+		return labelTerminals.getValue();
+	}
+	public void setLabelTerminals(boolean labelTerminals) {
+		this.labelTerminals.setValue(labelTerminals);
+	}
+   	 public boolean getUsePercentages() {
+		return usePercentages.getValue();
+	}
+	public void setUsePercentages(boolean usePercentages) {
+		this.usePercentages.setValue(usePercentages);
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/DisplayStatesAtNodes.java b/Source/mesquite/lib/duties/DisplayStatesAtNodes.java
new file mode 100644
index 0000000..92e3efa
--- /dev/null
+++ b/Source/mesquite/lib/duties/DisplayStatesAtNodes.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Displays character states on tree, for instance for character tracing.  Example modules: LabelStatesOnTree,
+ShadeStatesOnTree, SpotStatesOnTree.*/
+
+public abstract class DisplayStatesAtNodes extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return DisplayStatesAtNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Display States At Nodes";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#ShadeStatesOnTree"};
+   	 }
+   	 
+   	 /** create tree decorator which will do the drawing.  The tree decorator's 
+   	 method drawOnTree(Tree tree, Object obj, Graphics g) will be called to draw the states*/
+	public TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/DistanceBetween2Trees.java b/Source/mesquite/lib/duties/DistanceBetween2Trees.java
new file mode 100644
index 0000000..44bfaef
--- /dev/null
+++ b/Source/mesquite/lib/duties/DistanceBetween2Trees.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a distance between two trees, e.g. how different they are.*/
+
+public abstract class DistanceBetween2Trees extends NumberFor2Trees   {
+
+   	 public Class getDutyClass() {
+   	 	return DistanceBetween2Trees.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Distance between Two Trees";
+   	 }
+
+	public boolean largerIsFurther(){
+		return true;
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawChart.java b/Source/mesquite/lib/duties/DrawChart.java
new file mode 100644
index 0000000..f7bc767
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawChart.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**A class of modules that supplies Charters, to draw charts.  Example modules: Histogram, LineGraph,
+Scattergram, TableChart.*/
+
+public abstract class DrawChart extends MesquiteModule  {
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/chart.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return DrawChart.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Chart";
+   	 }
+ 	/** Supplies a Charter object.*/
+ 	public abstract Charter createCharter(ChartListener listener);
+	
+ 	/** Indicates to the chart module what Associable might be associated with points of the chart. 
+ 	The module need not respond to it.  If called, the module can safely assume each point refers 
+ 	to a part of the associable.*/
+	public abstract void pointsAreSelectable(boolean areParts, Selectionable a, boolean allowSequenceOptions);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawNamesTaxaDisplay.java b/Source/mesquite/lib/duties/DrawNamesTaxaDisplay.java
new file mode 100644
index 0000000..f101104
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawNamesTaxaDisplay.java
@@ -0,0 +1,54 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**This is superclass of Mesquite modules that draw terminal taxon names in a taxa window.  Relies on information in the
+TaxaDisplay and contained TaxaDrawing, such as node locations already calculated.  Example module:
+BasicDrawTaxonNames.  Example of use: see BasicTaxaDrawCoordinator.*/
+
+public abstract class DrawNamesTaxaDisplay extends MesquiteModule  {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+ 
+   	 public Class getDutyClass() {
+   	 	return DrawNamesTaxaDisplay.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Taxon Names For Taxa Display";
+   	 }
+   	 /** Returns font for node locs modules to use for fontMetrics. */
+   	public abstract Font getFont();
+   	 /** Draw names on taxa in given taxa display. */
+	public abstract void drawNames(TaxaDisplay taxaDisplay, Taxa taxa, Graphics g);
+   	 /** Find the taxon name box at x,y (returns 0 if none).  NOTE: this system is not great; it relies on
+   	 taxon name box locations calculated the last time drawNames was called.  This works fine if this module
+   	 has only one TaxaDisplay to work with, but if it has multiple it won't work well (would need to pass the
+   	 TaxaDisplay here) */
+	public abstract  int findTaxon(Taxa taxa, int x, int y);
+   	 /** Fill taxon M's taxon name box with current color. */
+	public abstract  void fillTaxon(Graphics g, int M);
+   	 /** Force a complete redraw of the names next time names are drawn. */
+	public void invalidateNames(TaxaDisplay taxaDisplay) {}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawNamesTreeDisplay.java b/Source/mesquite/lib/duties/DrawNamesTreeDisplay.java
new file mode 100644
index 0000000..3c0fb91
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawNamesTreeDisplay.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**This is superclass of Mesquite modules that draw terminal taxon names on trees.  Relies on information in the
+TreeDisplay and contained TreeDrawing, such as node locations already calculated.  Example module:
+BasicDrawTaxonNames.  Example of use: see BasicTreeDrawCoordinator.*/
+
+public abstract class DrawNamesTreeDisplay extends MesquiteModule  {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return DrawNamesTreeDisplay.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Taxon Names";
+   	 }
+   	 /** Returns font for node locs modules to use for fontMetrics. */
+   	public abstract Font getFont();
+   	 /** Draw names on tree in given tree display. */
+	public abstract void drawNames(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Graphics g);
+   	 /** Find the taxon name box at x,y (returns 0 if none).  NOTE: this system is not great; it relies on
+   	 taxon name box locations calculated the last time drawNames was called.  This works fine if this module
+   	 has only one TreeDisplay to work with, but if it has multiple it won't work well (would need to pass the
+   	 TreeDisplay here) */
+	public void setTree(Tree tree) {
+	}
+	public abstract  int findTaxon(Tree tree, int drawnRoot, int x, int y);
+   	 /** Fill taxon M's taxon name box with current color. */
+	public abstract  void fillTaxon(Graphics g, int M);
+   	 /** Force a complete redraw of the names next time names are drawn. */
+	public void invalidateNames(TreeDisplay treeDisplay) {}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawTaxa.java b/Source/mesquite/lib/duties/DrawTaxa.java
new file mode 100644
index 0000000..4db9d88
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawTaxa.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This is superclass of all Mesquite taxa drawing modules.  Creates a TaxaDrawing, which does
+the drawing of the taxa. */
+
+public abstract class DrawTaxa extends MesquiteModule  {
+
+   	public Class getDutyClass() {
+   		return DrawTaxa.class;
+   	}
+   	 
+ 	public String getDutyName() {
+ 		return "Draw Taxa";
+   	}
+   	public String[] getDefaultModule() {
+   		return new String[] {""};
+   	}
+   	   	
+	/** Returns the preferred size (if any) of the tree drawing */
+	public Dimension getPreferredSize(){
+		return null;
+	}
+   	 /** Returns a TaxaDrawing to be used in the given TaxaDisplay, with the given inital number of terminal taxa*/
+	public abstract TaxaDrawing createTaxaDrawing(TaxaDisplay taxaDisplay, int numTaxa);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawTaxaCoordinator.java b/Source/mesquite/lib/duties/DrawTaxaCoordinator.java
new file mode 100644
index 0000000..5b938dc
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawTaxaCoordinator.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/**A class that supervises the drawing of taxa.  It creates TaxaDisplay objects
+and probably hires DrawTaxa modules. Old and clunky, it either makes a single TaxaDisplay, or multiple
+ones.  Example module: BasicTaxaDrawCoordinator*/
+
+public abstract class DrawTaxaCoordinator extends MesquiteModule  {
+	protected TaxaDisplay taxaDisplay;
+	protected TaxaDisplay[] taxaDisplays;
+	protected Vector assistantTasks;
+	protected int numDisplays = 0;
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+
+   	 public Class getDutyClass() {
+   	 	return DrawTaxaCoordinator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Taxa Coordinator";
+   	 }
+   	 
+	/** Returns the preferred size (if any) of the taxa drawing */
+	public abstract Dimension getPreferredSize();
+
+
+	/** return the module responsible for drawing terminal taxon names. */
+   	 public abstract DrawNamesTaxaDisplay getNamesTask();
+   	 
+	/** Create one taxa display in the given window. */
+ 	public abstract TaxaDisplay createOneTaxaDisplay(Taxa taxa, MesquiteWindow window);
+	/** Create a vector of taxa displays. */
+ 	public abstract TaxaDisplay[] createTaxaDisplays(int numDisplays, Taxa taxa, MesquiteWindow window);
+	/** Create a vector of taxa displays, each with a different Taxa object. */
+ 	public abstract TaxaDisplay[] createTaxaDisplays(int numDisplays, Taxa[] taxa, MesquiteWindow window);
+
+
+	/** Add taxa display assistant */
+	public void addAssistantTask(TaxaDisplayAssistant mb) {
+		if (assistantTasks==null)
+			assistantTasks= new Vector();
+		assistantTasks.addElement(mb);
+	}
+	
+	/** Remove taxa display assistant */
+	public void removeAssistantTask(TaxaDisplayAssistant mb) {
+		if (assistantTasks!=null)
+			assistantTasks.removeElement(mb);
+	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawTree.java b/Source/mesquite/lib/duties/DrawTree.java
new file mode 100644
index 0000000..a12fa76
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawTree.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This is superclass of all Mesquite tree drawing modules.  Creates a TreeDrawing, which does
+the drawing of the tree.  Example modules: ArcTree, BallsNSticks, CircularTree, Constellation, DiagonalDrawTree,
+PlotTree, SquareTree.*/
+
+public abstract class DrawTree extends MesquiteModule  {
+
+   	public Class getDutyClass() {
+   		return DrawTree.class;
+   	}
+   	 
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Draw Tree";
+   	}
+   	public String[] getDefaultModule() {
+   		return new String[] { "#SquareLineTree", "#DiagonalDrawTree"};
+   	}
+   	   	
+	/** Returns the preferred size (if any) of the tree drawing */
+	public Dimension getPreferredSize(){
+		return null;
+	}
+	/** Returns true if it will have a preferred size of the tree drawing */
+	public boolean hasPreferredSize(){
+		return false;
+	}
+	
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return true;
+	}
+   	 /** Returns a TreeDrawing to be used in the given TreeDisplay, with the given inital number of terminal taxa*/
+	public abstract TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa);
+	
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/DrawTreeCoordinator.java b/Source/mesquite/lib/duties/DrawTreeCoordinator.java
new file mode 100644
index 0000000..67c132e
--- /dev/null
+++ b/Source/mesquite/lib/duties/DrawTreeCoordinator.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import java.util.*;
+
+
+/* ======================================================================== */
+/**A class that supervises the drawing of one or more tree.  It creates TreeDisplay objects
+and probably hires DrawTree modules. Old and clunky, it either makes a single TreeDisplay, or multiple
+ones.  Example module: BasicTreeDrawCoordinator*/
+
+public abstract class DrawTreeCoordinator extends MesquiteModule  {
+	protected TreeDisplay treeDisplay;
+	protected TreeDisplay[] treeDisplays;
+	protected Vector assistantTasks;
+	protected int numDisplays = 0;
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return DrawTreeCoordinator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Tree Coordinator";
+   	 }
+   	 
+	/** Returns the preferred size (if any) of the tree drawing */
+	public abstract Dimension getPreferredSize();
+
+	/** Returns true if will have preferred size for the tree drawing */
+	public abstract boolean hasPreferredSize();
+
+	/** return the module responsible for drawing terminal taxon names. */
+   	 public abstract DrawNamesTreeDisplay getNamesTask();
+   	 
+	/** Create one tree display in the given window. */
+ 	public abstract TreeDisplay createOneTreeDisplay(Taxa taxa, MesquiteWindow window);
+	/** Create a vector of tree displays. */
+ 	public abstract TreeDisplay[] createTreeDisplays(int numDisplays, Taxa taxa, MesquiteWindow window);
+	/** Create a vector of tree displays, each with a different Taxa object. */
+ 	public abstract TreeDisplay[] createTreeDisplays(int numDisplays, Taxa[] taxa, MesquiteWindow window);
+
+	/** sets branch color */
+ 	public abstract void setBranchColor(Color c);
+ 	
+ 	
+
+	/** Add tree display assistant */
+	public void addAssistantTask(TreeDisplayAssistant mb) {
+		if (assistantTasks==null)
+			assistantTasks= new Vector();
+		assistantTasks.addElement(mb);
+	}
+	
+	/** Remove tree display assistant */
+	public void removeAssistantTask(TreeDisplayAssistant mb) {
+		if (assistantTasks!=null)
+			assistantTasks.removeElement(mb);
+	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/EditRawNexusBlock.java b/Source/mesquite/lib/duties/EditRawNexusBlock.java
new file mode 100644
index 0000000..2eac500
--- /dev/null
+++ b/Source/mesquite/lib/duties/EditRawNexusBlock.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+//import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class EditRawNexusBlock extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return EditRawNexusBlock.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Edit Raw Nexus Block";
+   	}
+   	public abstract void editNexusBlock(NexusBlockEditableRaw block, boolean recordCurrent);
+   	public abstract void recordBlock(NexusBlockEditableRaw block);
+   	public abstract NexusBlockEditableRaw getCurrentBlock();
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/EditingCurator.java b/Source/mesquite/lib/duties/EditingCurator.java
new file mode 100644
index 0000000..7559075
--- /dev/null
+++ b/Source/mesquite/lib/duties/EditingCurator.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+Model curators that wish to have their names listed under New Character Model and New Submodel need to implement this.*/
+
+public interface EditingCurator  {
+}
+
+
diff --git a/Source/mesquite/lib/duties/ElementManager.java b/Source/mesquite/lib/duties/ElementManager.java
new file mode 100644
index 0000000..5c8a694
--- /dev/null
+++ b/Source/mesquite/lib/duties/ElementManager.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages a type of FileElement and Reads and writes NEXUS block.  Currently subclasses of this are *not*
+hired on the basis of being FileElementManager, but rather because they supplied a
+nexusBlockTest object that allows the NEXUS interpreting module to figure out what blocks
+they can read.  Thus, other modules than FileElementManager's can read and write NEXUS blocks
+and commands.  The class FileElementManager exists mostly to supply a default dutyname.  Example modules:
+class ManageAssumptionsBlock; class ManageMesquiteBlock; class ManageNotesBlock.  Others subclass subclasses
+(e.g. TreesManager).*/
+
+public interface ElementManager{
+	/* put in place so that manager could respond by reordering the corresponding NEXUS blocks*/
+	public void elementsReordered(ListableVector v);  
+	/* put in place so manager could create corresponding NEXUS block*/
+	public NexusBlock elementAdded(FileElement e);
+	public void elementDisposed(FileElement e);
+	public Class getElementClass();
+	public MesquiteModule showElement(FileElement e);
+	public void deleteElement(FileElement e);
+}
+
diff --git a/Source/mesquite/lib/duties/EmployeeTree.java b/Source/mesquite/lib/duties/EmployeeTree.java
new file mode 100644
index 0000000..26c45a4
--- /dev/null
+++ b/Source/mesquite/lib/duties/EmployeeTree.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+//import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class EmployeeTree extends MesquiteModule  {
+
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+  	 public Class getDutyClass() {
+   	 	return EmployeeTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Employee Tree";
+   	}
+   	public abstract HPanel showEmployeeTreeWindow(MesquiteModule module);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/ExternalTreeSearcher.java b/Source/mesquite/lib/duties/ExternalTreeSearcher.java
new file mode 100644
index 0000000..4e003e8
--- /dev/null
+++ b/Source/mesquite/lib/duties/ExternalTreeSearcher.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Searchers to find trees that optimize something.*/
+
+public abstract class ExternalTreeSearcher extends TreeSearcher  {
+   	 public Class getDutyClass() {
+   	 	return ExternalTreeSearcher.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "External Tree Searcher";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {""};
+   	 }
+   	 
+   	 
+  }
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistant.java b/Source/mesquite/lib/duties/FileAssistant.java
new file mode 100644
index 0000000..ae44fa7
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistant.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** A class of modules that promise no specific function, except in some way to be employeable
+to work with a project or file.  By being a FileAssistant, a module can be recognized as hireable by
+another module such as the FileCoordinator, and can put menu items to hire it.  Example modules:
+MultiTreeWindow, Spectrum, TreesChart, TwoValuesOverTrees.*/
+
+public abstract class FileAssistant extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantA.java b/Source/mesquite/lib/duties/FileAssistantA.java
new file mode 100644
index 0000000..392e769
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantA.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that doesn't chart.*/
+
+public abstract class FileAssistantA extends FileAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantC.java b/Source/mesquite/lib/duties/FileAssistantC.java
new file mode 100644
index 0000000..5a34978
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantC.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that produces charts.*/
+
+public abstract class FileAssistantC extends FileAssistant  {
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/chart.gif";
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantC.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Chart Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantCH.java b/Source/mesquite/lib/duties/FileAssistantCH.java
new file mode 100644
index 0000000..43907e7
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantCH.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that produces histogram charts.*/
+
+public abstract class FileAssistantCH extends FileAssistantC  {
+   	 public Class getDutyClass() {
+   	 	return FileAssistantCH.class;
+   	 }
+  	 public String[] getDefaultModule() {
+    	 	return new String[] {"#CharacterValuesChart", "#MatrixValuesChart", "#TreeValuesChart", "#TaxonValuesChart"};
+    	 }
+	public String getDutyName() {
+ 		return "Bar & Lines Chart Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantCP.java b/Source/mesquite/lib/duties/FileAssistantCP.java
new file mode 100644
index 0000000..4610c8d
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantCP.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that produces pairwise charts.*/
+
+public abstract class FileAssistantCP extends FileAssistantC  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantCP.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Pairwise Chart Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantCS.java b/Source/mesquite/lib/duties/FileAssistantCS.java
new file mode 100644
index 0000000..1a855b0
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantCS.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that produces scattergram charts.*/
+
+public abstract class FileAssistantCS extends FileAssistantC  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantCS.class;
+   	 }
+	 public String[] getDefaultModule() {
+ 	 	return new String[] {"#CharsScattergram", "#TreesScattergram", "#TaxaScattergram"};
+ 	 }
+ 	public String getDutyName() {
+ 		return "Scattergram Chart Assistant for File";
+   	 }
+
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+			whichWindow.dispose();
+			iQuit();
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantM.java b/Source/mesquite/lib/duties/FileAssistantM.java
new file mode 100644
index 0000000..601a3d8
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantM.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that deals with character matrices.*/
+
+public abstract class FileAssistantM extends FileAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantM.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Matrix Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantN.java b/Source/mesquite/lib/duties/FileAssistantN.java
new file mode 100644
index 0000000..79aa219
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantN.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that doesn't chart.*/
+
+public abstract class FileAssistantN extends FileAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantN.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Generic Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileAssistantT.java b/Source/mesquite/lib/duties/FileAssistantT.java
new file mode 100644
index 0000000..7fe12ed
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileAssistantT.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Subclass of FileAssistant that deals with trees.*/
+
+public abstract class FileAssistantT extends FileAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return FileAssistantT.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Trees Assistant for File";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileCoordinator.java b/Source/mesquite/lib/duties/FileCoordinator.java
new file mode 100644
index 0000000..a57c3f9
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileCoordinator.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**
+ * The defining superclass for file coordinating modules. A module of this class is the fundamental module second only to the MesquiteTrunk module itself. MesquiteTrunk hires a file coordinating module for each MesquiteProject. Example module: Basic File Coordinator
+ */
+
+public abstract class FileCoordinator extends MesquiteModule {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	public static int totalCreated = 0;
+
+	public static int totalFinalized = 0;
+
+	public FileCoordinator() {
+		super();
+		FileCoordinator.totalCreated++;
+	}
+	
+	public void finalize() throws Throwable {
+		FileCoordinator.totalFinalized++;
+		super.finalize();
+	}
+
+	public Class getDutyClass() {
+		return FileCoordinator.class;
+	}
+
+	public String getDutyName() {
+		return "File Coordinator";
+	}
+	public abstract void elementAdded(FileElement e);
+	public abstract void elementDisposed(FileElement e);
+	/** make a new blank MesquiteProject with user input. */
+	public abstract MesquiteFile createProject(String pathname, boolean createTaxaBlockIfNew);
+
+	/** make a new blank MesquiteProject without user input. */
+	public abstract MesquiteFile createBlankProject();
+	
+	public abstract void refreshGraphicsProjectWindow();
+	public abstract void refreshProjectWindow();
+	public abstract void refreshInProjectWindow(FileElement element);
+	public abstract void showProjectWindow();
+	public abstract void closeWindows();
+	/**
+	 * make a MesquiteProject, reading the information from the given path of a file (if local, interprets as file on disk; if not, as URL specification).
+	 */
+	public abstract MesquiteFile readProject(boolean local, String pathname, String arguments);
+
+	/** make a MesquiteProject, using a module. */
+	public abstract MesquiteFile readProjectGeneral(String arguments);
+
+	public abstract void wrapUpAfterFileRead(MesquiteFile f);  //call after read() methods of file interpreters called outside context of the file Coordinator's project/file reading
+	public abstract MesquiteFile getNEXUSFileForReading(String arguments, String message);
+
+	public abstract FileInterpreter findImporter(MesquiteFile f, int fileType, String arguments);
+
+	public abstract FileInterpreter findImporter(String fileContents, String fileName, int fileType, String arguments,boolean mustReadFromString, Class stateClass);
+
+	public abstract MesquiteProject initiateProject(String pathName, MesquiteFile homeFile);
+
+	/** write the given file; */
+	public abstract void writeFile(MesquiteFile file);
+
+	/** exports the given file; */
+	public abstract boolean export(FileInterpreterI exporter, MesquiteFile file, String arguments);
+
+	/** closes the given file; returns false if cancelled by user. */
+	public abstract boolean closeFile(MesquiteFile file);
+
+	/** Saves file. */
+	public abstract void saveFile(MesquiteFile file);
+
+	/** Saves file. */
+	public abstract void saveFileAs(MesquiteFile file);
+
+	/** Saves all files in the project. */
+	public abstract void saveAllFiles();
+
+	/* ................................................................................................................. */
+	/** Finds the first employee in the m's clade of employees that manages a particular subclass of file element */
+	public abstract ElementManager findManager(MesquiteModule m, Class fileElementClass);
+
+	/** Displays a given local text file; */
+	public abstract TextDisplayer displayFile(String pathName, int maxCharacters);
+
+	/** Displays a given text file, local or not; */
+	public abstract TextDisplayer displayFile(MesquiteFile file, int maxCharacters);
+
+	/** Displays a given text string; */
+	public abstract TextDisplayer displayText(String text, String windowTitle);
+
+	public boolean isSubstantive() {
+		return false;
+	}
+
+	public abstract Snapshot getIDSnapshot(MesquiteFile file);
+}
+
diff --git a/Source/mesquite/lib/duties/FileElementManager.java b/Source/mesquite/lib/duties/FileElementManager.java
new file mode 100644
index 0000000..f58b613
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileElementManager.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages a type of FileElement and Reads and writes NEXUS block.  Currently subclasses of this are *not*
+hired on the basis of being FileElementManager, but rather because they supplied a
+nexusBlockTest object that allows the NEXUS interpreting module to figure out what blocks
+they can read.  Thus, other modules than FileElementManager's can read and write NEXUS blocks
+and commands.  The class FileElementManager exists mostly to supply a default dutyname.  Example modules:
+class ManageAssumptionsBlock; class ManageMesquiteBlock; class ManageNotesBlock.  Others subclass subclasses
+(e.g. TreesManager).*/
+
+public abstract class FileElementManager extends MesquiteModule implements ElementManager   {
+
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+  	 public Class getDutyClass() {
+   	 	return FileElementManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of file elements";
+   	 }
+	/*.................................................................................................................*/
+	public abstract MesquiteModule showElement(FileElement e);
+	/*.................................................................................................................*/
+	public void deleteElement(FileElement e){
+		MesquiteMessage.warnProgrammer("oops, " + getName() + " doesn't delete yet");
+	}
+	/*.................................................................................................................*/
+	/*introduced in 1. 06 to get around issue of sequence of ID assignments; this allows ID assignments to happen early in Mesquite block.
+	This method is called in the Mesquite block manager */
+  	 public Snapshot getIDSnapshot(MesquiteFile file) {
+  	 	return null;
+  	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileInit.java b/Source/mesquite/lib/duties/FileInit.java
new file mode 100644
index 0000000..3d9f335
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileInit.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**A class of modules that promises no particular services, but which is automatically hired by a file coordinator 
+module when a file is read.  Such modules can be used to initialize things for each file.  For instance, InitializeParsimony currently
+initializes default CharacterModels for each file.  Example modules: "Data Window Coordinator", "Tree Window Coordinator"
+"Initialize Parsimony", "Initialize Likelihood", "Manage Character Models", "Manage character selection sets",
+"Manage model sets".*/
+
+public abstract class FileInit extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return FileInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "File Init";
+   	 }
+	public ProjPanelPanel getProjectPanelPanel(){
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileInitEarlyLoad.java b/Source/mesquite/lib/duties/FileInitEarlyLoad.java
new file mode 100644
index 0000000..c7859b7
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileInitEarlyLoad.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**A subclasses of FileInits that loads earlier than rest.*/
+
+public abstract class FileInitEarlyLoad extends FileInit  {
+
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/FileInterpreter.java b/Source/mesquite/lib/duties/FileInterpreter.java
new file mode 100644
index 0000000..9046ef3
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileInterpreter.java
@@ -0,0 +1,379 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+
+
+/* ======================================================================== */
+/**Superclass of file interpreting modules (e.g., NEXUS file reader/writer).  Different subclasses are expected
+to read different data file formats.  Example module: "Interpret NEXUS files" (class InterpretNexus).  Example of use:
+see BasicFileCoordinator.*/
+
+public abstract class FileInterpreter extends MesquiteModule  {
+	public static final int CURRENTDELIMITER=0;
+	public static final int MACOSDELIMITER=1;
+	public static final int WINDOWSDELIMITER=2;
+	public static final int UNIXDELIMITER=3;
+	public int lineDelimiter = CURRENTDELIMITER;
+	public boolean writeOnlySelectedData = false;
+	public boolean writeOnlyIncludedData = true;
+	public boolean writeOnlySelectedTaxa = false;
+	public boolean writeTaxaWithAllMissing = true;  //default changed to true as true  after 2. 75
+	public boolean writeExcludedCharacters = true;
+	
+	protected String filePath=null;
+
+	
+	protected static int STOPIMPORT = -1;
+	protected static int DONTADD = 0;
+	protected static int REPLACEDATA = 1;
+	protected static int REPLACEIFEMPTYOTHERWISEADD = 2;
+	protected static int REPLACEIFEMPTYOTHERWISEIGNORE = 3;
+	protected static int ADDASNEW = 4;
+	
+	protected static int treatmentOfIncomingDuplicates = DONTADD;
+
+//	protected static boolean defaultReplaceDataOfTaxonWithSameName = false;
+	protected static int defaultReplaceDataOfTaxonWithSameNameInt = ADDASNEW;
+	protected static boolean defaultHasQueriedAboutSameNameTaxa = false;
+//	protected boolean replaceDataOfTaxonWithSameName = defaultReplaceDataOfTaxonWithSameName;
+	protected int replaceDataOfTaxonWithSameNameInt = defaultReplaceDataOfTaxonWithSameNameInt;
+	protected boolean hasQueriedAboutSameNameTaxa = defaultHasQueriedAboutSameNameTaxa;
+	protected int totalFilesToImport = 1;
+	protected int importFileNumber = 0;
+	protected boolean multiFileImport = false;
+	protected int lastNewTaxonFilled = -1;
+	protected int maximumTaxonFilled =-1;
+	protected int originalNumTaxa =-1;
+
+	public Class getDutyClass() {
+		return FileInterpreter.class;
+	}
+	public String getFunctionIconPath(){
+		return getRootImageDirectoryPath() + "functionIcons/fileInterpret.gif";
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public void reset(){
+//		replaceDataOfTaxonWithSameName = defaultReplaceDataOfTaxonWithSameName;
+		replaceDataOfTaxonWithSameNameInt = defaultReplaceDataOfTaxonWithSameNameInt;
+		hasQueriedAboutSameNameTaxa = defaultHasQueriedAboutSameNameTaxa;
+		
+	}
+
+	/** This is deprecated and should not be overridden.  The subsequent methods should be used instead.*/
+	public boolean canExport(){
+		return false;
+	}
+	/** returns whether module is able ever to export.*/
+	public boolean canExportEver(){
+		return canExport();
+	}
+	/** returns whether module has something it can export in the project.  Should be overridden*/
+	public boolean canExportProject(MesquiteProject project){
+		return canExport();
+	}
+
+	/** returns whether module can export a character data matrix of the given type.  Should be overridden*/
+	public boolean canExportData(Class dataClass){
+		return canExport();
+	}
+	
+	public int[] getNewTaxaAdded(){
+		return null;
+	}
+	
+	/** Returns whether the module can read (import) files with data of class dataClass*/
+	public boolean canImport(Class dataClass){
+		return canImport();
+	}
+	/** Returns whether the module can read (import) files */
+	public boolean canImport(){
+		return false;
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments, Class dataClass){
+		boolean fuse = parser.hasFileReadingArgument(arguments, "fuseTaxaCharBlocks");
+		if (fuse)
+			return false;
+		return canImport(dataClass);
+	}
+	/** Returns whether the module can read (import) files considering the passed argument string (e.g., fuse) */
+	public boolean canImport(String arguments){
+		return canImport(arguments,null);
+	}
+
+	/** reads a file using the methods of MesquiteFile and places its data into the given MesquiteProject
+	which will already have been instantiated.  Recall that a MesquiteProject is not the external file on disk or server,
+	but is rather the collection of taxa, data, trees, etc. that together typically make up the information in
+	a NEXUS file.  The external file is referred to by the MesquiteFile.*/
+	public abstract void readFile(MesquiteProject mf, MesquiteFile mNF, String arguments);
+
+	//	public abstract void readFile();
+
+	public String getDutyName() {
+		return "File Interpreter";
+	}
+
+	/*.................................................................................................................*/
+	public String getLineEnding() {
+		if (lineDelimiter == CURRENTDELIMITER) 
+			return StringUtil.lineEnding();
+		else if (lineDelimiter == MACOSDELIMITER) 
+			return "\r";
+		else if (lineDelimiter == WINDOWSDELIMITER) 
+			return "\r\n";
+		else if (lineDelimiter == UNIXDELIMITER) 
+			return "\n";
+		return StringUtil.lineEnding();
+	}
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "";
+	}
+
+	NameReference previousTaxaNameRef = new NameReference("previousTaxon");
+	NameReference newlyAddedTaxaNameRef = new NameReference("newlyAddedTaxon");
+	
+	/*.................................................................................................................*/
+	public void startRecordingTaxa(Taxa taxa){
+		taxa.clearAllAssociatedBits(newlyAddedTaxaNameRef);
+		taxa.clearAllAssociatedBits(previousTaxaNameRef);
+		for (int it=0; it<taxa.getNumTaxa(); it++)
+			recordAsPreviousTaxon(taxa,it);
+	}
+	/*.................................................................................................................*/
+	public void recordAsPreviousTaxon(Taxa taxa, int it){
+		taxa.setAssociatedBit(previousTaxaNameRef, it, true);
+	}
+	/*.................................................................................................................*/
+	public void recordAsNewlyAddedTaxon(Taxa taxa, int it){
+		taxa.setAssociatedBit(newlyAddedTaxaNameRef, it, true);
+	}
+	/*.................................................................................................................*/
+	public Bits getNewlyAddedTaxa(Taxa taxa){
+		Bits newTaxa = new Bits(taxa.getNumTaxa());
+		newTaxa.clearAllBits();
+		for (int it=0; it<taxa.getNumTaxa(); it++)
+			if (taxa.getAssociatedBit(newlyAddedTaxaNameRef, it))
+				newTaxa.setBit(it);
+		return newTaxa;
+	}
+	/*.................................................................................................................*/
+	public void endRecordingTaxa(Taxa taxa){
+		taxa.clearAllAssociatedBits(newlyAddedTaxaNameRef);
+		taxa.clearAllAssociatedBits(previousTaxaNameRef);
+	}
+
+
+	/*.................................................................................................................*/
+	protected String stripNex(String name) {
+		if (name == null)
+			return null;
+		int length = name.length();
+		if (length<4)
+			return name;
+		String last4 = name.substring(length-4, length);
+		if (last4.equalsIgnoreCase(".nex")) 
+			return name.substring(0, length-4);
+		else
+			return name;
+	}
+
+	/*.................................................................................................................*/
+	public void setLineDelimiter(int newDelimiter) {
+		lineDelimiter = newDelimiter;
+	}
+
+	public boolean isSubstantive(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void finishImport(ProgressIndicator progIndicator, MesquiteFile file, boolean abort){
+		if (progIndicator!=null)
+			progIndicator.goAway();
+		if (file!=null) 
+			file.closeReading();
+		if (abort){ //���		
+			if (file!=null)
+				file.close();
+			resetAllMenuBars();
+			//decrementMenuResetSuppression();
+			return;
+		}
+		/*
+		 * 	FileCoordinator fc = getFileCoordinator();
+		if (fc!=null && getProject().getNumberCharMatrices()>0) {
+			MesquiteModule dwc = (MesquiteModule)fc.doCommand("getEmployee", "'Data Window Coordinator'",CommandChecker.defaultChecker);
+			if (dwc!=null) {
+				for (int i=0; i< getProject().getNumberCharMatrices(); i++)
+					dwc.doCommand("showDataWindow", ""+i,CommandChecker.defaultChecker);
+			}
+		}
+		 */
+	}
+	/*.................................................................................................................*/
+	public void saveExportedFileWithExtension(StringBuffer outputBuffer, String arguments, String suggestedFileEnding) {
+		if (outputBuffer == null)
+			return;
+		String output = outputBuffer.toString();
+
+		String name = getProject().getHomeFileName();
+		if (name==null)
+			name = "untitled." + suggestedFileEnding;
+		else if (suggestedFileEnding.equalsIgnoreCase("NEX"))
+			name = stripNex(name)+"2." + suggestedFileEnding;
+		else 
+			name = stripNex(name) + "." + suggestedFileEnding;
+		saveExportedFile(output, arguments, name);
+
+	}
+	/*.................................................................................................................*/
+	public String getPathForExport(String arguments, String suggestedFileName, MesquiteString dir, MesquiteString fn) {
+		//check arguments for filename and directory
+		String tempFileName=null;
+		String tempDirectoryName=null;
+		String token = parser.getFirstToken(arguments);
+		while (token !=null){
+			if (token.equalsIgnoreCase("file")){
+				parser.getNextToken(); // =
+				tempFileName = parser.getNextToken();
+			}
+			else if (token.equalsIgnoreCase("directory")){
+				parser.getNextToken(); // =
+				tempDirectoryName = parser.getNextToken();
+				if (tempDirectoryName != null && !tempDirectoryName.endsWith(MesquiteFile.fileSeparator)) //(tempDirectoryName.length()-1) != MesquiteFile.fileSeparator.charAt(0))
+					tempDirectoryName += MesquiteFile.fileSeparator;
+			}
+			token = parser.getNextToken();
+		}
+		if (StringUtil.blank(tempFileName)){
+			String queryMessage = "Export to file";
+			MainThread.incrementSuppressWaitWindow();
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), queryMessage, FileDialog.SAVE);   // Save File dialog box
+			if (suggestedFileName == null)
+				suggestedFileName = "untitled";
+			fdlg.setFile(suggestedFileName);
+
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setVisible(true);
+			tempFileName=fdlg.getFile();
+			tempDirectoryName=fdlg.getDirectory();
+			//	fdlg.dispose();
+			MainThread.decrementSuppressWaitWindow();
+		}
+		if (!StringUtil.blank(tempFileName)) {
+			if (StringUtil.blank(tempDirectoryName))
+				tempDirectoryName = "";
+			if (dir!=null)
+				dir.setValue(tempDirectoryName);
+			if (fn != null){
+				fn.setValue(tempFileName);
+			}
+			return tempDirectoryName+tempFileName;
+		}
+		return null;
+
+	}
+	/*.................................................................................................................*/
+	public String getExportedFileDirectory(){
+		return MesquiteFile.getDirectoryPathFromFilePath(filePath);
+	}
+	/*.................................................................................................................*/
+	public String getExportedFilePath(){
+		return filePath;
+	}
+	/*.................................................................................................................*/
+	public String getExportedFileName(){
+		if (filePath!=null) {
+			return MesquiteFile.getFileNameFromFilePath(filePath);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void saveExportedFile(String output, String arguments, String suggestedFileName) {
+
+		filePath = getPathForExport(arguments, suggestedFileName, null, null);
+		if (filePath!=null) {
+			logln("Exporting file to " + filePath);
+			MesquiteFile.putFileContents(filePath, output, true);
+			logln("Export complete.");
+		}
+	}
+	/** Returns the Character data as a StringBuffer in the Interperter's format.  This method should be overridden for those Interpreters that can provide this service. */
+	/*.................................................................................................................*/
+	public  StringBuffer getDataAsFileText(MesquiteFile file, CharacterData data) {
+		return null;
+	}
+	public int getTotalFilesToImport() {
+		return totalFilesToImport;
+	}
+	public void setTotalFilesToImport(int totalFilesToImport) {
+		this.totalFilesToImport = totalFilesToImport;
+	}
+	public int getImportFileNumber() {
+		return importFileNumber;
+	}
+	public void setImportFileNumber(int importFileNumber) {
+		this.importFileNumber = importFileNumber;
+	}
+	public boolean getMultiFileImport() {
+		return multiFileImport;
+	}
+	public void setMultiFileImport(boolean multiFileImport) {
+		this.multiFileImport = multiFileImport;
+	}
+	public int getLastNewTaxonFilled() {
+		return lastNewTaxonFilled;
+	}
+	public void setLastNewTaxonFilled(int lastNewTaxonFilled) {
+		this.lastNewTaxonFilled = lastNewTaxonFilled;
+		maximumTaxonFilled = lastNewTaxonFilled;
+	}
+	public int getMaximumTaxonFilled() {
+		return maximumTaxonFilled;
+	}
+	public void setMaximumTaxonFilled(int maximumTaxonFilled) {
+		this.maximumTaxonFilled = maximumTaxonFilled;
+	}
+	public void checkMaximumTaxonFilled(int taxonFilled) {
+		if (taxonFilled> this.maximumTaxonFilled)
+			 maximumTaxonFilled = taxonFilled;
+	}
+	public int getOriginalNumTaxa() {
+		return originalNumTaxa;
+	}
+	public void setOriginalNumTaxa(int originalNumTaxa) {
+		this.originalNumTaxa = originalNumTaxa;
+	}
+
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/FileInterpreterI.java b/Source/mesquite/lib/duties/FileInterpreterI.java
new file mode 100644
index 0000000..b64aac0
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileInterpreterI.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Superclass of file interpreting modules (e.g., NEXUS file reader/writer).  Different subclasses are expected
+to read different data file formats.  Example module: "Interpret NEXUS files" (class InterpretNexus).  Example of use:
+see BasicFileCoordinator.*/
+
+/** a subclass for importers (appear in File menu under Import)*/
+public abstract class FileInterpreterI extends FileInterpreter  {
+	
+   	 public Class getDutyClass() {
+   	 	return FileInterpreterI.class;
+   	 }
+	/** exports data to a file.*/
+	public abstract boolean exportFile(MesquiteFile file, String arguments);
+	
+	/** called after hired in case interpreter wants to query user about import*/
+	public void getImportOptions(boolean fuse){
+	}
+  	 public String[] getDefaultModule() {
+    	 	return new String[] {"#InterpretFastaDNA", "#InterpretFastaProtein"};
+    	 }
+	
+}
+
diff --git a/Source/mesquite/lib/duties/FileInterpreterITree.java b/Source/mesquite/lib/duties/FileInterpreterITree.java
new file mode 100644
index 0000000..4c1c51a
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileInterpreterITree.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Superclass of file interpreting modules (e.g., NEXUS file reader/writer).  Different subclasses are expected
+to read different data file formats.  Example module: "Interpret NEXUS files" (class InterpretNexus).  Example of use:
+see BasicFileCoordinator.*/
+
+/** a subclass for importers (appear in File menu under Import)*/
+public abstract class FileInterpreterITree extends FileInterpreterI  {
+	
+   	 public Class getDutyClass() {
+   	 	return FileInterpreterITree.class;
+   	 }
+	public abstract void readTreeFile(MesquiteProject mf, MesquiteFile file, String arguments) ;
+}
+
diff --git a/Source/mesquite/lib/duties/FileProcessor.java b/Source/mesquite/lib/duties/FileProcessor.java
new file mode 100644
index 0000000..607833e
--- /dev/null
+++ b/Source/mesquite/lib/duties/FileProcessor.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a file (e.g. to process matrices within the file).*/
+
+public abstract class FileProcessor extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return FileProcessor.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "File Processor";
+   	}
+   	
+ 	public String getNameForProcessorList() {
+ 		return getName();
+   	}
+   	/** if returns true, then requests to remain on even after alterFile is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	/** Called to process file. Override this or the next*/
+   	public  boolean processFile(MesquiteFile file){
+   		return true;
+   	}
+  	
+	/*.................................................................................................................*/
+	/** Called to process file. */
+	public boolean processFile(MesquiteFile file, MesquiteString notice){
+		return processFile(file);
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/GeneralFileMaker.java b/Source/mesquite/lib/duties/GeneralFileMaker.java
new file mode 100644
index 0000000..98a0f17
--- /dev/null
+++ b/Source/mesquite/lib/duties/GeneralFileMaker.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Modules that can establish a new project*/
+
+public abstract class GeneralFileMaker extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return GeneralFileMaker.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Establisher of new projects";
+   	}
+ 	
+   	/** make a new    MesquiteProject.*/
+ 	public abstract MesquiteProject establishProject(String arguments);
+
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/HistogramAssistantA.java b/Source/mesquite/lib/duties/HistogramAssistantA.java
new file mode 100644
index 0000000..31771d8
--- /dev/null
+++ b/Source/mesquite/lib/duties/HistogramAssistantA.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*An analytical assistant for histograms*/
+
+public abstract class HistogramAssistantA extends ChartAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return HistogramAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Bar and Lines Chart";
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/IncrementalConsenser.java b/Source/mesquite/lib/duties/IncrementalConsenser.java
new file mode 100644
index 0000000..218cabe
--- /dev/null
+++ b/Source/mesquite/lib/duties/IncrementalConsenser.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Does tree consensus .*/
+
+public abstract class IncrementalConsenser extends Consenser   {
+
+   	 public Class getDutyClass() {
+   	 	return IncrementalConsenser.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Incremental Consensus tree calculator";
+   	 }
+  	public abstract void reset(Taxa taxa);
+  	public abstract void addTree(Tree t);
+ 	public abstract Tree getConsensus();
+   
+ }
+
+
+
diff --git a/Source/mesquite/lib/duties/ItemsBiplotter.java b/Source/mesquite/lib/duties/ItemsBiplotter.java
new file mode 100644
index 0000000..0fc3cd9
--- /dev/null
+++ b/Source/mesquite/lib/duties/ItemsBiplotter.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public abstract class ItemsBiplotter extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return ItemsBiplotter.class;
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#ItemsBiplot"};
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/chart.gif";
+   	 }
+	/*...................................................................................................................*/
+	public void doCounts(){
+		doCounts(MesquiteInteger.unassigned, MesquiteInteger.unassigned, true);
+	}
+	/*...................................................................................................................*/
+    	 public abstract void doCounts( int firstItem, int lastItem, boolean fullCount);
+	/*.................................................................................................................*/
+ 	public abstract ChartWindow makeChartWindow(MesquiteModule requester);
+	/*...................................................................................................................*/
+	public abstract void setTaxa(Taxa taxa);
+	/*...................................................................................................................*/
+	public void setAuxiliary(Object object, boolean useAsFirstParameter){
+	}
+	/*...................................................................................................................*/
+	public abstract void setShowNames( boolean showNames);
+	/*...................................................................................................................*/
+	public abstract void setItemsSource( ItemsSource itemsSourceTask);
+	/*...................................................................................................................*/
+	public abstract void setNumberTaskX(NumberForItem numberTask);
+	/*...................................................................................................................*/
+	public abstract void setNumberTaskY(NumberForItem numberTask);
+	/*...................................................................................................................*/
+	public abstract void setNumberTaskZ(NumberForItem numberTask);
+	/*.................................................................................................................*/
+	public abstract void setDefaultNumberOfItems(int def);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/ItemsCharter.java b/Source/mesquite/lib/duties/ItemsCharter.java
new file mode 100644
index 0000000..7ab7a5a
--- /dev/null
+++ b/Source/mesquite/lib/duties/ItemsCharter.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public abstract class ItemsCharter extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return ItemsCharter.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/chart.gif";
+   	 }
+  	 public String[] getDefaultModule() {
+   	 	return new String[] {"#ItemValuesChart"};
+   	 }
+	/*...................................................................................................................*/
+	public abstract void doCounts( int firstItem, int lastItem, boolean fullCount);
+	/*...................................................................................................................*/
+	public void doCounts() {
+		doCounts(MesquiteInteger.unassigned,MesquiteInteger.unassigned, true);
+	}
+	/*.................................................................................................................*/
+	public abstract void incrementSuspension();
+	/*.................................................................................................................*/
+	public abstract void decrementSuspension();
+	/*.................................................................................................................*/
+ 	public abstract ChartWindow makeChartWindow(MesquiteModule requester);
+	/*...................................................................................................................*/
+	public abstract void setTaxa(Taxa taxa);
+	/*...................................................................................................................*/
+	public void setAuxiliary(Object object, boolean useAsFirstParameter){
+	}
+	/*...................................................................................................................*/
+	public abstract void setItemsSource( ItemsSource itemsSourceTask);
+	/*...................................................................................................................*/
+	public abstract void setNumberTask(NumberForItem numberTask);
+	/*.................................................................................................................*/
+	public abstract void setDefaultNumberOfItems(int def);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/ItemsSource.java b/Source/mesquite/lib/duties/ItemsSource.java
new file mode 100644
index 0000000..a574304
--- /dev/null
+++ b/Source/mesquite/lib/duties/ItemsSource.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public interface ItemsSource  {
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa);
+   	
+   	public String accumulateParameters(String spacer);
+   	public String getParameters();
+   	public String getNameAndParameters();
+   	public String getName();
+   	
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic);
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa);
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName();
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural();
+   	/** If the items given by this source are parts of a Selectionable, then this method allows charts and other things to query about it,
+   	which allows coordination of item selection to work.*/
+   	public abstract Selectionable getSelectionable();
+   	
+  	/** zzzzzzzzzzzz*/
+   	public void setEnableWeights(boolean enable);
+   	public boolean itemsHaveWeights(Taxa taxa);
+  	/** zzzzzzzzzzzz*/
+   	public double getItemWeight(Taxa taxa, int ic);
+  	/** zzzzzzzzzzzz*/
+   	public void prepareItemColors(Taxa taxa);
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic);
+ 	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic);
+}
+
diff --git a/Source/mesquite/lib/duties/ManageModelSet.java b/Source/mesquite/lib/duties/ManageModelSet.java
new file mode 100644
index 0000000..48bf540
--- /dev/null
+++ b/Source/mesquite/lib/duties/ManageModelSet.java
@@ -0,0 +1,112 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+public abstract class ManageModelSet extends CharSpecsSetManager {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	public abstract Class getModelClass();
+	public abstract String getParadigm();
+	public abstract ModelSet getNewModelSet(String name, int numChars, CharacterModel defaultModel, mesquite.lib.characters.CharacterData data);
+	/*.................................................................................................................*/
+ 	public void fileElementAdded(FileElement element) {
+		
+ 		if (element instanceof mesquite.lib.characters.CharacterData) {
+	 		if (getProject()==null)
+	 			MesquiteMessage.println("project is null in iMS " + getName());
+			ModelSet currentModelSet;
+	 		CharacterModel defaultModel=null;
+	 		mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)element;
+	 		if (data.getCurrentSpecsSet(getElementClass()) == null) {
+		 		defaultModel =  (CharacterModel)data.getDefaultModel(getParadigm());
+		 		//MesquiteMessage.println("Default model for " + data.getName() + " " + (defaultModel !=null));
+		 		currentModelSet= getNewModelSet("UNTITLED", data.getNumChars(), defaultModel, data);
+		 		currentModelSet.addToFile(element.getFile(), getProject(), null);
+		 		data.setCurrentSpecsSet(currentModelSet, getElementClass());
+		 	}
+	 		if (getProject().getCharacterModels()==null)
+	 			MesquiteMessage.println("charModels null in iMS Init Prob");
+		 }
+ 		 
+	}
+	public Object getSpecification(String token){
+		return getProject().getCharacterModel((token));
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || getElementClass() == null || !(getElementClass().isAssignableFrom(specsSet.getClass())) || getModelClass() == null || specification == null || !(getModelClass().isAssignableFrom(specification.getClass())))
+			return;
+		ObjectSpecsSet sS = (ObjectSpecsSet)specsSet;
+		sS.setProperty(specification,ic);
+	}
+	public SpecsSet getNewSpecsSet(String name, mesquite.lib.characters.CharacterData data){
+		CharacterModel defaultModel =  data.getDefaultModel(getParadigm());
+ 		return getNewModelSet(name, data.getNumChars(), defaultModel, data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("MESQUITECHARMODELS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS") || blockName.equalsIgnoreCase("MESQUITECHARMODELS");
+	}
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, mesquite.lib.characters.CharacterData data, MesquiteFile file, boolean isCurrent){
+		return nexusStringForSpecsSetStandard(specsSet,data,file,isCurrent);
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new ModelsetNexusCommandTest(nexusToken());
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage " + lowerCaseTypeName() + "s";
+   	 }
+   	 
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) " + lowerCaseTypeName() + "s (" + nexusToken() + "\'s)." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class ModelsetNexusCommandTest  extends NexusCommandTest{
+	String token;
+	public ModelsetNexusCommandTest(String token){
+		super();
+		this.token = token;
+	}
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("ASSUMPTIONS") || blockName.equalsIgnoreCase("MESQUITECHARMODELS")) && (commandName.equalsIgnoreCase(token)));
+	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/ManagerAssistant.java b/Source/mesquite/lib/duties/ManagerAssistant.java
new file mode 100644
index 0000000..033a7cd
--- /dev/null
+++ b/Source/mesquite/lib/duties/ManagerAssistant.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages list window of file elements.  Example module: CharacterList.*/
+
+public abstract class ManagerAssistant extends MesquiteModule   {
+
+    	 public Class getDutyClass() {
+   	 	return ManagerAssistant.class;
+   	 }
+	public String getDutyName() {
+ 		return "Manages list window of file element";
+   	 }
+	
+	public abstract void showListWindow(Object obj);
+	public abstract boolean showing(Object obj);
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/MatrixCharter.java b/Source/mesquite/lib/duties/MatrixCharter.java
new file mode 100644
index 0000000..11cac6e
--- /dev/null
+++ b/Source/mesquite/lib/duties/MatrixCharter.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** DOCUMENT.*/
+
+public abstract class MatrixCharter extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return MatrixCharter.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Draw Chart for Matrix";
+   	 }
+
+	public  abstract void setMatrix(double[][] matrix, double min1, double max1, double min2, double max2);
+//	public  abstract void setMatrix(double[][] matrix, double min1, double max1, double min2, double max2, double best1, double best2, String axis1, String axis2);
+	
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/MatrixInfoPanelAssistant.java b/Source/mesquite/lib/duties/MatrixInfoPanelAssistant.java
new file mode 100644
index 0000000..b19bb14
--- /dev/null
+++ b/Source/mesquite/lib/duties/MatrixInfoPanelAssistant.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.charMatrices.lib.*;
+
+
+/* ======================================================================== */
+
+public abstract class MatrixInfoPanelAssistant extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return MatrixInfoPanelAssistant.class;
+   	 }
+ 	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditor.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Assistant for Character Matrix Info Panel";
+   	 }
+	public  abstract MatrixInfoExtraPanel getPanel(ClosablePanelContainer container);
+}
+
+
diff --git a/Source/mesquite/lib/duties/MatrixInfoPanelAssistantI.java b/Source/mesquite/lib/duties/MatrixInfoPanelAssistantI.java
new file mode 100644
index 0000000..9c49cd3
--- /dev/null
+++ b/Source/mesquite/lib/duties/MatrixInfoPanelAssistantI.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.charMatrices.lib.*;
+
+
+/* ======================================================================== */
+
+public abstract class MatrixInfoPanelAssistantI extends MatrixInfoPanelAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return MatrixInfoPanelAssistantI.class;
+   	 }
+ 	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditor.gif";
+   	 }
+	public String getDutyName() {
+ 		return "INIT Assistant for Character Matrix Info Panel";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/MatrixSourceCoord.java b/Source/mesquite/lib/duties/MatrixSourceCoord.java
new file mode 100644
index 0000000..2f8d8cc
--- /dev/null
+++ b/Source/mesquite/lib/duties/MatrixSourceCoord.java
@@ -0,0 +1,70 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public abstract class MatrixSourceCoord extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return MatrixSourceCoord.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Independent Character Matrix Source Coordinator";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CharMatrixCoordObed"}; //, "#CharMatrixCoordIndep"};
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixSource.gif";
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+   	/** gets the current matrix.*/
+   	public abstract MCharactersDistribution getCurrentMatrix(Taxa taxa);
+
+        /* -- the following are a preliminary attempt to allow matrix sources to know exactly what tree the 
+        matrix will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated matrix attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+
+   	/** If this matrix source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a matrix if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public abstract boolean usesTree();
+   	
+   	/** gets the current matrix.*/
+   	public MCharactersDistribution getCurrentMatrix(Tree tree){
+   		if (tree==null) return null;
+   		else return getCurrentMatrix(tree.getTaxa());
+   	}
+	/*.................................................................................................................*/
+   	public abstract String getCurrentMatrixName(Taxa taxa);
+}
+
+
diff --git a/Source/mesquite/lib/duties/MatrixSourceCoordObed.java b/Source/mesquite/lib/duties/MatrixSourceCoordObed.java
new file mode 100644
index 0000000..d3d94f4
--- /dev/null
+++ b/Source/mesquite/lib/duties/MatrixSourceCoordObed.java
@@ -0,0 +1,118 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+*/
+
+public abstract class MatrixSourceCoordObed extends MesquiteModule implements ItemsSource  {
+
+   	 public Class getDutyClass() {
+   	 	return MatrixSourceCoordObed.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Obedient Character Matrix Source Coordinator";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CharMatrixCoordObed"};
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixSource.gif";
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public abstract int getNumberOfMatrices(Taxa taxa);
+   	/** gets the indicated matrix.*/
+   	public abstract MCharactersDistribution getMatrix(Taxa taxa, int im);
+   	/** gets name of the indicated matrix.*/
+   	public abstract String getMatrixName(Taxa taxa, int im);
+
+        /* -- the following are a preliminary attempt to allow matrix sources to know exactly what tree the 
+        matrix will be used with.  These can be overridden by modules to do simulations on the trees, or to see if there
+        is a simulated matrix attached to the tree, or what ---*/
+   	public void initialize(Tree tree){
+   		if (tree==null) return;
+   		else initialize(tree.getTaxa());
+   	}
+   	 /** returns the number of character matrices that can be supplied for the given taxa*/
+    	public int getNumberOfMatrices(Tree tree){
+   		if (tree==null) return 0;
+   		else return getNumberOfMatrices(tree.getTaxa());
+   	}
+   	/** gets the indicated matrix.*/
+   	public MCharactersDistribution getMatrix(Tree tree, int im){
+   		if (tree==null) return null;
+   		else return getMatrix(tree.getTaxa(), im);
+   	}
+   	/** If this matrix source does in fact depend on the tree (i.e. it overrides the methods being passed a tree)
+   	then this method should be overridden to return true.  This allows modules using it to know they should
+   	re-request a matrix if the tree has changed.  (Relying on TreeContext or listening systems could be
+   	too cumbersome since such requests could come in tight loops that are cycling through trees .*/
+   	public boolean usesTree(){
+   		return false;
+   	}
+        /* ----------------*/
+        
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+		CommandRecord.tick("Getting matrix " + ic);
+   		return getMatrix(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfMatrices(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Matrix";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Matrices";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	
+  	/** zzzzzzzzzzzz*/
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	public void prepareItemColors(Taxa taxa){
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+ 	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getMatrixName(taxa, ic);
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/MesquiteInit.java b/Source/mesquite/lib/duties/MesquiteInit.java
new file mode 100644
index 0000000..e9f7809
--- /dev/null
+++ b/Source/mesquite/lib/duties/MesquiteInit.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**A class of modules that promises no particular services, but which is automatically hired by Mesquite at startup.*/
+
+public abstract class MesquiteInit extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return MesquiteInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Mesquite INIT";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NexusFileInterpreter.java b/Source/mesquite/lib/duties/NexusFileInterpreter.java
new file mode 100644
index 0000000..c2c76b5
--- /dev/null
+++ b/Source/mesquite/lib/duties/NexusFileInterpreter.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Superclass of file interpreting modules (e.g., NEXUS file reader/writer).  Different subclasses are expected
+to read different data file formats.  Example module: "Interpret NEXUS files" (class InterpretNexus).  Example of use:
+see BasicFileCoordinator.*/
+
+/** a subclass for reading nexus files*/
+public abstract class NexusFileInterpreter extends FileInterpreter  {
+	/** returns whether module can read given file.*/
+	public abstract boolean canReadFile(MesquiteFile f);
+	/** writes the given MesquiteFile belonging to the MesquiteProject.*/
+	public abstract void writeFile(MesquiteProject mf, MesquiteFile mNF);
+	/** adds nexus block to project (block contains reference to the file it belongs to)*/
+	public abstract void addBlock(NexusBlock nb);
+	public abstract void removeBlock(NexusBlock nb);
+	public abstract NexusBlock findBlock(FileElement e);
+	/** finds the ith block of a given type and returns it raw.*/
+	public abstract FileBlock readOneBlock(MesquiteProject mf, MesquiteFile f, String blockType, int i);
+}
+
+
diff --git a/Source/mesquite/lib/duties/NodeChooser.java b/Source/mesquite/lib/duties/NodeChooser.java
new file mode 100644
index 0000000..182f064
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeChooser.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class NodeChooser extends MesquiteModule  {
+
+	/** */
+	public abstract int chooseNode(Tree tree);
+   	
+ 	public String getDutyName() {
+ 		return "Node Chooser";
+   	 }
+   	 public Class getDutyClass() {
+   	 	return NodeChooser.class;
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/NodeLocs.java b/Source/mesquite/lib/duties/NodeLocs.java
new file mode 100644
index 0000000..23b2fcb
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeLocs.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This class of modules assigns locations to nodes in a drawn tree.  Most modules use subclasses
+of this (e.g., NodeLocsVH, NodeLocsCircle).*/
+
+public abstract class NodeLocs extends MesquiteModule  {
+	/** calculates the locations for a tree drawn within the given rectangle.  Should not be called during paint(); hence Graphics g removed as parameter May 02*/
+	public abstract void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect);
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+  	
+	/** returns whether compatible with given orientation (e.g., UP, RIGHT, CIRCULAR, etc.)*/
+   	public boolean compatibleWithOrientation(int orientation) {
+   		return false;
+   	}
+	/** sets the TreeDisplay's orientation to be the default desired by the module.*/
+   	public void setDefaultOrientation(TreeDisplay treeDisplay) {
+   	}
+	/** gets the module's default tree display orientation.*/
+   	public int getDefaultOrientation(){
+   		return TreeDisplay.FREEFORM;
+   	}
+   	
+   	 public Dimension getPreferredSize(){
+   	 	return null;
+   	 }
+ 	/** Returns true if it will have a preferred size of the tree drawing */
+ 	public boolean hasPreferredSize(){
+ 		return false;
+ 	}
+	public String getDutyName() {
+ 		return "Node Location Calculator";
+   	 }
+   	 public Class getDutyClass() {
+   	 	return NodeLocs.class;
+   	 }
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NodeLocsCircle.java b/Source/mesquite/lib/duties/NodeLocsCircle.java
new file mode 100644
index 0000000..04859ad
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeLocsCircle.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This class of modules assigns node locations for circular trees (orientation CIRCULAR).
+Example subclass: NodeLocsCircular */
+
+public abstract class NodeLocsCircle extends NodeLocs  {
+	/**angle of each branch from 0 degrees (defined as direction of standard positive "x" axis).*/
+	public double [] angle;
+	/**length of each branch measured radially from center.*/
+	public double [] polarLength;
+	/**center of circle about which tree is drawn.*/
+	public Point treeCenter;
+	
+	/** gets the module's default tree display orientation.*/
+   	public int getDefaultOrientation(){
+   		return TreeDisplay.CIRCULAR;
+   	}
+ 	public String getDutyName() {
+ 		return "Node Location (Circular)";
+   	 }
+   	 
+   	 public Class getDutyClass() {
+   	 	return NodeLocsCircle.class;
+   	 }
+}
+
diff --git a/Source/mesquite/lib/duties/NodeLocsFree.java b/Source/mesquite/lib/duties/NodeLocsFree.java
new file mode 100644
index 0000000..3049c74
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeLocsFree.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This class of modules assigns node locations for circular trees (orientation CIRCULAR).
+Example subclass: NodeLocsCircular */
+
+public abstract class NodeLocsFree extends NodeLocs  {
+	
+ 	public String getDutyName() {
+ 		return "Node Location (Freeform)";
+   	 }
+   	 
+   	 public Class getDutyClass() {
+   	 	return NodeLocsFree.class;
+   	 }
+}
+
diff --git a/Source/mesquite/lib/duties/NodeLocsPlot.java b/Source/mesquite/lib/duties/NodeLocsPlot.java
new file mode 100644
index 0000000..9717445
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeLocsPlot.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This class of modules assigns node locations for plotting.
+Example module: NodeLocs2DPlot*/
+
+public abstract class NodeLocsPlot extends NodeLocs  {
+	
+ 	public String getDutyName() {
+ 		return "Node Location (Plot)";
+   	 }
+   	 public Class getDutyClass() {
+   	 	return NodeLocsPlot.class;
+   	 }
+   	 
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/NodeLocsVH.java b/Source/mesquite/lib/duties/NodeLocsVH.java
new file mode 100644
index 0000000..e069a51
--- /dev/null
+++ b/Source/mesquite/lib/duties/NodeLocsVH.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+/* ======================================================================== */
+/**This class of modules assigns node locations for trees with orientations UP, DOWN, LEFT, or RIGHT.
+Example Module: NodeLocsStandard*/
+
+public abstract class NodeLocsVH extends NodeLocs  {
+	public static int defaultOrientation = TreeDisplay.UP;
+ 	public String getDutyName() {
+ 		return "Node Location (Vert/Horiz)";
+   	 }
+   	 public Class getDutyClass() {
+   	 	return NodeLocsVH.class;
+   	 }
+	/** gets the module's default tree display orientation.*/
+   	public int getDefaultOrientation(){
+   		return TreeDisplay.UP;
+   	}
+   	
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumFor2CharHistAndTree.java b/Source/mesquite/lib/duties/NumFor2CharHistAndTree.java
new file mode 100644
index 0000000..f33434a
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumFor2CharHistAndTree.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public abstract class NumFor2CharHistAndTree extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumFor2CharHistAndTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Two Character Histories and Tree";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+
+	public  abstract void calculateNumber(Tree tree, CharacterHistory charHistory1, CharacterHistory charHistory2, MesquiteNumber result, MesquiteString resultString);
+
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumForCharHistAndTree.java b/Source/mesquite/lib/duties/NumForCharHistAndTree.java
new file mode 100644
index 0000000..be928ab
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumForCharHistAndTree.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public abstract class NumForCharHistAndTree extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumForCharHistAndTree.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Character History and Tree";
+   	 }
+
+	public  abstract void calculateNumber(Tree tree, CharacterHistory charHistory, MesquiteNumber result, MesquiteString resultString);
+
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumForCharTreeDep.java b/Source/mesquite/lib/duties/NumForCharTreeDep.java
new file mode 100644
index 0000000..41f2569
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumForCharTreeDep.java
@@ -0,0 +1,21 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+
+/** An interface whose only purpose is to inform that a NumberForCharacter depends on trees/a tree*/
+public interface NumForCharTreeDep {
+
+}
+
diff --git a/Source/mesquite/lib/duties/NumForCharTreeIndep.java b/Source/mesquite/lib/duties/NumForCharTreeIndep.java
new file mode 100644
index 0000000..c6632ff
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumForCharTreeIndep.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+
+
+/** An interface whose only purpose is to inform that something does not depend on trees/a tree*/
+public interface NumForCharTreeIndep {
+
+}
+
diff --git a/Source/mesquite/lib/duties/NumberArrayForMatrix.java b/Source/mesquite/lib/duties/NumberArrayForMatrix.java
new file mode 100644
index 0000000..04369ba
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberArrayForMatrix.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for a data set (a CharacterData object)*/
+
+public abstract class NumberArrayForMatrix extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForMatrix.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Numbers for Matrix";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixNumber.gif";
+   	 }
+  	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(MCharactersDistribution data);
+   	
+	public abstract void calculateNumbers(MCharactersDistribution data, NumberArray result, MesquiteString resultString); //TODO: pass result
+	/*===== For NumberForItem interface ======*/
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	public void initialize(Object object1, Object object2){
+		if (object1 instanceof MCharactersDistribution) 
+   			initialize((MCharactersDistribution)object1);
+   	}
+	public  void calculateNumbers(Object object1, Object object2, NumberArray result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		if (result==null)
+			return;
+		if (object1 instanceof MCharactersDistribution) {
+			calculateNumbers((MCharactersDistribution)object1, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+	public  void calculateNumbersInContext(Object object1, Object object2, ItemsSource source, int whichItem, NumberArray result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		calculateNumbers(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+	public abstract String[] getNumbersNames();
+	public abstract int getNumberOfNumbers();
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberFor2CharAndTree.java b/Source/mesquite/lib/duties/NumberFor2CharAndTree.java
new file mode 100644
index 0000000..13c7bdd
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberFor2CharAndTree.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public abstract class NumberFor2CharAndTree extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberFor2CharAndTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Two Characters and Tree";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree, CharacterDistribution charStates1, CharacterDistribution charStates2);
+
+	public  abstract void calculateNumber(Tree tree, CharacterDistribution charStates1, CharacterDistribution charStates2, MesquiteNumber result, MesquiteString resultString);
+	public boolean returnsMultipleValues(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberFor2Characters.java b/Source/mesquite/lib/duties/NumberFor2Characters.java
new file mode 100644
index 0000000..b15c648
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberFor2Characters.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for two characters.*/
+
+public abstract class NumberFor2Characters extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberFor2Characters.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Two Characters";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(CharacterDistribution c1, CharacterDistribution c2);
+
+	public abstract void calculateNumber(CharacterDistribution c1, CharacterDistribution c2, MesquiteNumber result, MesquiteString resultString);
+	
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberFor2Taxa.java b/Source/mesquite/lib/duties/NumberFor2Taxa.java
new file mode 100644
index 0000000..c2ceded
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberFor2Taxa.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterDistribution;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for two taxa, e.g. the distance between them.*/
+
+public abstract class NumberFor2Taxa extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberFor2Taxa.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Two Taxa";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxon t1, Taxon t2);
+
+	/*===== For NumberForItem interface ======*/
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Taxon && object2 instanceof Taxon)
+   			initialize((Taxon)object1, (Taxon)object2);
+   	}
+   	
+	public abstract void calculateNumber(Taxon t1, Taxon t2, MesquiteNumber result, MesquiteString resultString);
+
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		if (result==null)
+			return;
+		if (object1 instanceof TaxonPair && object1!=null) {
+			calculateNumber(((TaxonPair)object1).getTaxon(0), ((TaxonPair)object1).getTaxon(1), result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+		else
+			MesquiteMessage.warnProgrammer("Error: passing wrong class of objects to ItemSource calculateNumber in " + getName());
+	}
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberFor2TaxaIncr.java b/Source/mesquite/lib/duties/NumberFor2TaxaIncr.java
new file mode 100644
index 0000000..4a4a2e0
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberFor2TaxaIncr.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a taxon.*/
+
+public abstract class NumberFor2TaxaIncr extends NumberFor2Taxa implements Incrementable {
+
+   	 public Class getDutyClass() {
+   	 	return NumberFor2TaxaIncr.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for 2 Taxa (incrementable)";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberFor2Trees.java b/Source/mesquite/lib/duties/NumberFor2Trees.java
new file mode 100644
index 0000000..2f56c17
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberFor2Trees.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for two trees, e.g. how different they are.*/
+
+public abstract class NumberFor2Trees extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberFor2Trees.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Two Trees";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree t1, Tree t2);
+   	
+	public abstract void calculateNumber(Tree t1, Tree t2, MesquiteNumber result, MesquiteString resultString);
+	
+	public boolean largerIsFurther(){
+		return true;
+	}
+	
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#RFtreeDifference", "#WeightedRFtreeDifference"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForCharAndTaxon.java b/Source/mesquite/lib/duties/NumberForCharAndTaxon.java
new file mode 100644
index 0000000..20b4b15
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForCharAndTaxon.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for a character.*/
+
+public abstract class NumberForCharAndTaxon extends MesquiteModule {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForCharAndTaxon.class;
+   	 }
+
+ 	public String getDutyName() {
+ 		return "Number for Character and Taxon";
+   	 }
+
+	/*
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"PercentMissing"};
+   	 }
+	*/
+	
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(mesquite.lib.characters.CharacterData charStates);
+   	
+	public abstract void calculateNumber(mesquite.lib.characters.CharacterData charStates, int ic, int it, MesquiteNumber result, MesquiteString resultString);
+	
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForCharAndTree.java b/Source/mesquite/lib/duties/NumberForCharAndTree.java
new file mode 100644
index 0000000..f977993
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForCharAndTree.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public abstract class NumberForCharAndTree extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForCharAndTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Character and Tree";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+  	 public String[] getDefaultModule() {
+ 		String[] s= {"#ParsCharSteps", "#BiSSELikelihood"};
+ 		return s;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree, CharacterDistribution charStates);
+
+	public  abstract void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString);
+
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Tree && object2 instanceof CharacterDistribution)
+   			initialize((Tree)object1, (CharacterDistribution)object2);
+   	}
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Tree && object2 instanceof CharacterDistribution) {
+			calculateNumber((Tree)object1, (CharacterDistribution)object2, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+		else {
+			MesquiteMessage.warnProgrammer("Error: passing wrong class of objects to ItemSource calculateNumber in " + getName());
+		}
+	}
+
+	
+	
+	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForCharAndTreeM.java b/Source/mesquite/lib/duties/NumberForCharAndTreeM.java
new file mode 100644
index 0000000..e3c98b6
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForCharAndTreeM.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree, and may return a modified tree.*/
+
+public abstract class NumberForCharAndTreeM extends NumberForCharAndTree  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForCharAndTreeM.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Character and Tree; may return modified tree";
+   	 }
+	public void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(tree, charStates, result, resultString, null);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public  abstract void calculateNumber(Tree tree, CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString, MesquiteTree modifiedTree);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForCharacter.java b/Source/mesquite/lib/duties/NumberForCharacter.java
new file mode 100644
index 0000000..6ee1bb0
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForCharacter.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for a character.*/
+
+public abstract class NumberForCharacter extends MesquiteModule implements NumberForItem {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForCharacter.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/characterNumber.gif";
+   	 }
+
+ 	public String getDutyName() {
+ 		return "Number for Character";
+   	 }
+
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#NumForCharCurrentTree", "#PercentMissing", "#NumForCharOnTree"};
+   	 }
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(CharacterDistribution charStates);
+   	
+	public abstract void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString);
+	
+	/*===== For NumberForItem interface ======*/
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	public void initialize(Object object1, Object object2){
+		if (object1 instanceof CharacterDistribution) 
+   			initialize((CharacterDistribution)object1);
+   	}
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		if (result==null)
+			return;
+		if (object1 instanceof CharacterDistribution) {
+				calculateNumber((CharacterDistribution)object1, result, resultString);
+				saveLastResult(result);
+				saveLastResultString(resultString);
+		}
+	}
+	
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+
+
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForCharacterIncr.java b/Source/mesquite/lib/duties/NumberForCharacterIncr.java
new file mode 100644
index 0000000..959e7b4
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForCharacterIncr.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+public interface NumberForCharacterIncr extends Incrementable {
+
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForItem.java b/Source/mesquite/lib/duties/NumberForItem.java
new file mode 100644
index 0000000..957b7eb
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForItem.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for an item.*/
+
+public interface NumberForItem   {
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Object object1, Object object2);
+   	
+   	public String getParameters();
+   	public String getNameAndParameters();
+	public String accumulateParameters(String spacer);
+   	public String getName();
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString);
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString);
+   	public String getNameOfValueCalculated();
+   	public boolean returnsMultipleValues();
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForMatrix.java b/Source/mesquite/lib/duties/NumberForMatrix.java
new file mode 100644
index 0000000..e8a67fd
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForMatrix.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for a data set (a CharacterData object)*/
+
+public abstract class NumberForMatrix extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForMatrix.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Matrix";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixNumber.gif";
+   	 }
+  	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(MCharactersDistribution data);
+   	
+	public abstract void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString); //TODO: pass result
+	/*===== For NumberForItem interface ======*/
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+  	public void initialize(Object object1, Object object2){
+		if (object1 instanceof MCharactersDistribution) 
+   			initialize((MCharactersDistribution)object1);
+   	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		if (result==null)
+			return;
+		if (object1 instanceof MCharactersDistribution) {
+			calculateNumber((MCharactersDistribution)object1, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+		clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+   	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForMatrixAndTree.java b/Source/mesquite/lib/duties/NumberForMatrixAndTree.java
new file mode 100644
index 0000000..e7f4efe
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForMatrixAndTree.java
@@ -0,0 +1,76 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Supplies a number for a character matrix and a tree.*/
+
+public abstract class NumberForMatrixAndTree extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForMatrixAndTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Matrix And Tree";
+   	 }
+  	 public String[] getDefaultModule() {
+    	 	return new String[] {"#TreelengthForMatrix"};
+    	 }
+
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree, MCharactersDistribution matrix);
+
+
+	public abstract  void calculateNumber(Tree tree, MCharactersDistribution matrix, MesquiteNumber result, MesquiteString resultString);
+	/*===== For NumberForItem interface ======*/
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Tree && object2 instanceof MCharactersDistribution)
+   			initialize((Tree)object1, (MCharactersDistribution)object2);
+   	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Tree && object2 instanceof MCharactersDistribution) {
+			calculateNumber((Tree)object1, (MCharactersDistribution)object2, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+		else
+			MesquiteMessage.warnProgrammer("Error: passing wrong class of objects to ItemSource calculateNumber in " + getName());
+	}
+ 	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+  	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForNode.java b/Source/mesquite/lib/duties/NumberForNode.java
new file mode 100644
index 0000000..47d00b8
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForNode.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Suppliies number for a node of a tree.*/
+
+public abstract class NumberForNode extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForNode.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Node of Tree";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree);
+
+	public abstract void calculateNumber(Tree tree, int node, MesquiteNumber result, MesquiteString resultString); 
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForTaxaBlock.java b/Source/mesquite/lib/duties/NumberForTaxaBlock.java
new file mode 100644
index 0000000..3f667d2
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTaxaBlock.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a taxa block.*/
+
+public abstract class NumberForTaxaBlock extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTaxaBlock.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Taxa Block";
+   	 }
+
+	public abstract void calculateNumber(Taxa taxa, MesquiteNumber result, MesquiteString resultString); 
+	
+  	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+   	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Taxa) {
+			calculateNumber((Taxa)object1,result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+  	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForTaxon.java b/Source/mesquite/lib/duties/NumberForTaxon.java
new file mode 100644
index 0000000..7c82116
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTaxon.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a taxon.*/
+
+public abstract class NumberForTaxon extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTaxon.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Taxon";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+	public abstract void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString); 
+	
+  	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Taxa) 
+   			initialize((Taxa)object1);
+   	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Taxon) {
+			calculateNumber((Taxon)object1,result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+  	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForTaxonIncr.java b/Source/mesquite/lib/duties/NumberForTaxonIncr.java
new file mode 100644
index 0000000..2de64a8
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTaxonIncr.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a taxon.*/
+
+public abstract class NumberForTaxonIncr extends NumberForTaxon implements Incrementable {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTaxonIncr.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Taxon (incrementable)";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumberForTree.java b/Source/mesquite/lib/duties/NumberForTree.java
new file mode 100644
index 0000000..810abf2
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTree.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a tree.*/
+
+public abstract class NumberForTree extends NumberForTreeWContext implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTree.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#NumberOfTaxa", "#TreeValueUsingMatrix", "#NumForTreeWithChar", "#NumForTreeWith2Chars"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){}
+
+	
+	public abstract void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString); 
+	
+	public  void calculateNumberInContext(Tree tree, TreeSource source, int whichTree, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(tree, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof Tree) 
+   			initialize((Tree)object1);
+   	}
+	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Tree) {
+			calculateNumberInContext((Tree)object1, (TreeSource)source, whichItem, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof Tree) {
+			calculateNumber((Tree)object1, result, resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+	/** indicates default optimization, e.g. for tree searchers.  If true, tree search will maximize,
+	otherwise minimize.  If number has obvious optimum direction, this should be overridden to indicate
+	optimum*/
+	public boolean biggerIsBetter() {
+		return true;
+	}
+  	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForTreeBlock.java b/Source/mesquite/lib/duties/NumberForTreeBlock.java
new file mode 100644
index 0000000..4e8fdc4
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTreeBlock.java
@@ -0,0 +1,62 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/**Supplies a number for a vector of trees.*/
+
+public abstract class NumberForTreeBlock extends MesquiteModule implements NumberForItem  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTreeBlock.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree Block";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(TreeVector trees);
+
+	public abstract void calculateNumber(TreeVector trees, MesquiteNumber result, MesquiteString resultString);
+	
+ 	public boolean returnsMultipleValues(){
+  		return false;
+  	}
+	/*===== For NumberForItem interface ======*/
+   	public void initialize(Object object1, Object object2){
+		if (object1 instanceof TreeVector) 
+   			initialize((TreeVector)object1);
+   	}
+	public  void calculateNumber(Object object1, Object object2, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (object1 instanceof TreeVector) {
+			calculateNumber((TreeVector)object1, result, resultString);
+		}
+	}
+ 	public  void calculateNumberInContext(Object object1, Object object2, ItemsSource source, int whichItem, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(object1, object2, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+  	public String getNameOfValueCalculated(){ 
+		return getNameAndParameters();
+   	}
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForTreeIncr.java b/Source/mesquite/lib/duties/NumberForTreeIncr.java
new file mode 100644
index 0000000..869186f
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTreeIncr.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a tree.*/
+
+
+public abstract class NumberForTreeIncr extends NumberForTree implements Incrementable  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTreeIncr.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree (Incrementable)";
+   	 }
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForTreeM.java b/Source/mesquite/lib/duties/NumberForTreeM.java
new file mode 100644
index 0000000..f5b1947
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTreeM.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a tree.*/
+
+public abstract class NumberForTreeM extends NumberForTree  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTreeM.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree; may return modified tree";
+   	 }
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		calculateNumber(tree, result, resultString, null);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	
+	public abstract void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString, MesquiteTree modifiedTree); 
+	
+}
+
diff --git a/Source/mesquite/lib/duties/NumberForTreeWContext.java b/Source/mesquite/lib/duties/NumberForTreeWContext.java
new file mode 100644
index 0000000..0299d15
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumberForTreeWContext.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+
+
+/* ======================================================================== */
+/**Supplies a number for a tree.*/
+
+public abstract class NumberForTreeWContext extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumberForTreeWContext.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Number for Tree with Context";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeNumber.gif";
+   	 }
+
+ 	//superclass for numberForTree.  If modules subclasses NumberForTreeWContext but not NumberForTree, it will have this method called
+ 	//otherwise, if it subclasses NumberForTree, the following method may or may not get called.  The rule should be however that
+ 	//if it was hired as a NumberForTreeWContext then this method will get called; if hired as a NumberForTree then calculateNumber will get called instead.
+	public  abstract void calculateNumberInContext(Tree tree, TreeSource source, int whichTree, MesquiteNumber result, MesquiteString resultString);
+}
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodes.java b/Source/mesquite/lib/duties/NumbersForNodes.java
new file mode 100644
index 0000000..7e14917
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodes.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.*/
+
+public abstract class NumbersForNodes extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodes.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeNumber.gif";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree);
+
+	public abstract void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString); //TODO: pass MesquiteString
+	
+	public boolean getDefaultShowLabels() {
+		return false;
+	}
+	public boolean getDefaultShadeBranches() {
+		return true;
+	}
+	public boolean getDefaultShadeInColor() {
+		return true;
+	}
+	public boolean getDefaultLabelTerminals() {
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodesAndChar.java b/Source/mesquite/lib/duties/NumbersForNodesAndChar.java
new file mode 100644
index 0000000..52335f5
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodesAndChar.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.*/
+
+public abstract class NumbersForNodesAndChar extends MesquiteModule {
+
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodesAndChar.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree using a Character Distribution";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree);
+
+	public abstract void calculateNumbers(Tree tree, CharacterDistribution charDistribution, NumberArray result, MesquiteString resultString); 
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodesAndHistory.java b/Source/mesquite/lib/duties/NumbersForNodesAndHistory.java
new file mode 100644
index 0000000..d25b8be
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodesAndHistory.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree given the history of many characters.*/
+
+public abstract class NumbersForNodesAndHistory extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodesAndHistory.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+ 	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree And History";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree, MCharactersHistory charsHistory);
+
+	public abstract void calculateNumbers(Tree tree, MCharactersHistory charsHistory, NumberArray result, MesquiteString resultString); //TODO: pass MesquiteString
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodesAndMatrix.java b/Source/mesquite/lib/duties/NumbersForNodesAndMatrix.java
new file mode 100644
index 0000000..cdf2d18
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodesAndMatrix.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree given a matrix.*/
+
+public abstract class NumbersForNodesAndMatrix extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodesAndMatrix.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeCharNumber.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree and Matrix";
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Tree tree, MCharactersDistribution data);
+
+	public abstract void calculateNumbers(Tree tree, MCharactersDistribution data, NumberArray result, MesquiteString resultString); //TODO: pass MesquiteString
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodesIncr.java b/Source/mesquite/lib/duties/NumbersForNodesIncr.java
new file mode 100644
index 0000000..82ace57
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodesIncr.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.  Is incrementable*/
+
+public abstract class NumbersForNodesIncr extends NumbersForNodes implements Incrementable  {
+
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodesIncr.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree (Incrementable)";
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/NumbersForNodesWith2Char.java b/Source/mesquite/lib/duties/NumbersForNodesWith2Char.java
new file mode 100644
index 0000000..3dcdaa9
--- /dev/null
+++ b/Source/mesquite/lib/duties/NumbersForNodesWith2Char.java
@@ -0,0 +1,223 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.*/
+
+public abstract class NumbersForNodesWith2Char extends NumbersForNodes {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	private CharSourceCoordObed characterSource, characterSourceB;
+	Object dataCondition;
+	int currentCharA = 0;
+	int currentCharB = 1;
+	Taxa taxa;
+	CharacterDistribution observedStatesA, observedStatesB;
+	/*.................................................................................................................*/
+	/** superStartJob is called automatically when an employee is hired.  This is intended for use by superclasses of modules that need
+	their own constructor-like call, without relying on the subclass to be polite enough to call super.startJob().*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+		if (NumbersForNodesWith2Char.class.isAssignableFrom(getHiredAs()))
+			return true;
+		//assume hired as NumbersForNodes; thus responsible for getting characters
+		//hire character source with two characters -- one or two separate sources?
+ 		characterSource = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, getCharacterClass(), "Source of characters (for " + getName() + ")");
+		if (characterSource == null)
+			return sorry(getName() + " couldn't start because no source of characters (for " + getName() + ") was obtained");
+		characterSourceB = characterSource;
+		addMenuItem( "Choose 1st Character (for " + getName() + ")", makeCommand("chooseCharacterA",  this));
+		addMenuItem( "Choose 2nd Character (for " + getName() + ")", makeCommand("chooseCharacterB",  this));
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public Class getCharacterClass() {
+  	 	return null;
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getCharacterSource ", characterSource); 
+  	 	temp.addLine("setCharacterA " + CharacterStates.toExternal(currentCharA)); 
+  	 	if (characterSourceB!= characterSource)
+  	 		temp.addLine("getCharacterSourceB ", characterSourceB); 
+  	 	temp.addLine("setCharacterB " + CharacterStates.toExternal(currentCharB)); 
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+ 			if (characterSource!=null)
+ 				return characterSource.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+ 			return characterSource;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSourceB")) {//temporary, for data files using old system without coordinators
+ 			if (characterSourceB!=null)
+ 				return characterSourceB.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSourceB")) {
+ 			return characterSourceB;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next character for X axis", null, commandName, "nextCharacterA")) {
+    	 		if (characterSource == null)
+    	 			return null;
+    	 		if (currentCharA >= characterSource.getNumberOfCharacters(taxa)-1)
+    	 			currentCharA=0;
+    	 		else
+    	 			currentCharA++;
+   	 		observedStatesA = null;
+	   	 	parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous character for X axis", null, commandName, "previousCharacterA")) {
+    	 		if (characterSource == null)
+    	 			return null;
+    	 		if (currentCharA<=0)
+    	 			currentCharA=characterSource.getNumberOfCharacters(taxa)-1;
+    	 		else
+    	 			currentCharA--;
+   	 		observedStatesA = null;
+ 			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries the user to select a character for X axis", null, commandName, "chooseCharacterA")) {
+    	 		if (characterSource == null)
+    	 			return null;
+    	 		if (taxa==null)
+    	 			return null;
+    	 		int ic=characterSource.queryUserChoose(taxa, " for X axis ");
+    	 		if (MesquiteInteger.isCombinable(ic)) {
+	   			currentCharA = ic;
+	   	 		observedStatesA = null;
+	 			parametersChanged();
+ 			}
+			
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the character to show for X axis", "[number of character]", commandName, "setCharacterA")) {
+    	 		if (characterSource == null)
+    	 			return null;
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 		if ((ic>=0) && (ic<=characterSource.getNumberOfCharacters(taxa)-1)) {
+    	 			currentCharA = ic;
+	   	 		observedStatesA = null;
+	 			parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next character for Y axis", null, commandName, "nextCharacterB")) {
+    	 		if (characterSourceB == null)
+    	 			return null;
+    	 		if (currentCharB >= characterSourceB.getNumberOfCharacters(taxa)-1)
+    	 			currentCharB=0;
+    	 		else
+    	 			currentCharB++;
+ 			observedStatesB = null;
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous character for Y axis", null, commandName, "previousCharacterB")) {
+    	 		if (characterSourceB == null)
+    	 			return null;
+    	 		if (currentCharB<=0)
+    	 			currentCharB=characterSourceB.getNumberOfCharacters(taxa)-1;
+    	 		else
+    	 			currentCharB--;
+ 			observedStatesB = null;
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries the user to select a character for Y axis", null, commandName, "chooseCharacterB")) {
+    	 		if (characterSourceB == null)
+    	 			return null;
+    	 		if (taxa==null)
+    	 			return null;
+    	 		int ic=characterSourceB.queryUserChoose(taxa, " for Y axis ");
+    	 		if (MesquiteInteger.isCombinable(ic)) {
+	   			currentCharB = ic;
+	   	 		observedStatesB = null;
+	 			parametersChanged();
+ 			}
+			
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the second character to use for " + getName(), "[number of character]", commandName, "setCharacterB")) {
+    	 		if (characterSourceB == null)
+    	 			return null;
+    	 		int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+    	 		if ((ic>=0) && (ic<=characterSourceB.getNumberOfCharacters(taxa)-1)) {
+    	 			currentCharB = ic;
+   	 			observedStatesB = null;
+ 				parametersChanged();
+ 			}
+    	 	} 
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof CharacterOneSource) {
+	   	 	observedStatesA = null;
+	   	 	observedStatesB = null;
+	   	 	parametersChanged(notification);
+ 		}
+
+	}
+   	 public Class getDutyClass() {
+   	 	return NumbersForNodesWith2Char.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Numbers for Nodes of Tree using 2 Character Distributions";
+   	 }
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		if (tree!=null)
+			taxa = tree.getTaxa();
+ 		if (observedStatesA ==null)
+ 			observedStatesA = characterSource.getCharacter(tree, currentCharA);
+ 		if (observedStatesB ==null)
+ 			observedStatesB = characterSource.getCharacter(tree, currentCharB);
+		calculateNumbers(tree, observedStatesA, observedStatesB, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == characterSource || employee == characterSourceB)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (tree == null)
+   			return;
+		taxa = tree.getTaxa();
+   		if (characterSource!=null)
+   			characterSource.initialize(tree.getTaxa());
+   		if (characterSourceB!=null && characterSourceB!=characterSource)
+   			characterSourceB.initialize(tree.getTaxa());
+   	}
+
+	public abstract void calculateNumbers(Tree tree, CharacterDistribution charDistribution1, CharacterDistribution charDistribution2, NumberArray result, MesquiteString resultString); 
+}
+
+
diff --git a/Source/mesquite/lib/duties/OneTreeSource.java b/Source/mesquite/lib/duties/OneTreeSource.java
new file mode 100644
index 0000000..b828a5f
--- /dev/null
+++ b/Source/mesquite/lib/duties/OneTreeSource.java
@@ -0,0 +1,51 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies a single tree.  (see TreeSource.  The distinctions between these are not yet fully settled.  See issues
+discussed under CharacterSource and CharMatrixSource*/
+
+public abstract class OneTreeSource extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return OneTreeSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "One Tree Source";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeSource.gif";
+   	 }
+ 	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TreeOfContext"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+   	public abstract Tree getTree(Taxa taxa);
+	/*.................................................................................................................*/
+  	public abstract void setPreferredTaxa(Taxa taxa);
+
+	/* if tree source is getting trees from some other source, e.g. from TreeContext, then pass back here ultimate tree source from which trees are given*/
+  	public abstract MesquiteModule getUltimateSource();
+}
+
+
diff --git a/Source/mesquite/lib/duties/PackageIntro.java b/Source/mesquite/lib/duties/PackageIntro.java
new file mode 100644
index 0000000..3422532
--- /dev/null
+++ b/Source/mesquite/lib/duties/PackageIntro.java
@@ -0,0 +1,173 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.io.*;
+import java.util.Iterator;
+
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Serves to introduce a package*/
+
+public abstract class PackageIntro extends MesquiteModule implements PackageIntroInterface  {
+
+	public Class getDutyClass() {
+		return PackageIntro.class;
+	}
+	public String getDutyName() {
+		return "Introduces a package";
+	}
+
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash screen banner and possibly also URL*/
+	public boolean hasSplash(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns the URL of document shown when splash screen icon touched. By default, returns path to module's manual*/
+	public String getSplashURL(){
+		String splashP =getPath()+"index.html";
+		if (MesquiteFile.fileExists(splashP))
+			return splashP;
+		splashP =getPath()+"splash.html";
+		if (MesquiteFile.fileExists(splashP))
+			return splashP;
+		String s = getManualPath();
+		if (StringUtil.notEmpty(s))
+			return s;
+		s = getPackageURL();
+		if (StringUtil.notEmpty(s))
+			return s;
+		return s;
+	}
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+	
+	
+	/*.................................................................................................................*
+	/** Returns the number of downloads of the latest release*
+	public int getNumReleaseDownloads(){
+		if (StringUtil.notEmpty(getGitHubReleaseURL())) {
+			try {
+				GitHub github = GitHub.connect();
+				if (github!=null) {
+					GHRepository repo = github.getRepository(getGitHubRepository());
+					if (repo!=null) {
+						PagedIterable pagedIterable = repo.listReleases();
+						java.util.List releases = (java.util.List) pagedIterable.asList();
+						for (Iterator iter = releases.iterator(); iter.hasNext();) {
+							GHRelease nextRelease = (GHRelease) iter.next();
+						}
+
+					}
+				}
+				 
+			}
+			catch (IOException ioe) {
+			}
+		}
+		return 0;
+	}
+	
+	/*.................................................................................................................*/
+	
+	public final static int NOREPOSITORY = 0;
+	public final static int GITHUBREPOSITORY = 1;
+	
+	/*.................................................................................................................*/
+	/** Returns the kind of repository*/
+	public int getRepositoryKind(){
+		return NOREPOSITORY;
+	}
+	/** Returns the URL for the release package*/
+	public String getReleaseURL(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** Returns the tag for the release tag*/
+	public String getReleaseTag(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** Returns the repository path on the repository server*/
+	public String getRepositoryPath(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** Returns the repository URL*/
+	public String getRepositoryFullURL(){
+		return "";
+	}
+
+	/*.................................................................................................................*/
+	/** Returns whether hideable*/
+	public boolean getHideable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+	public String getPackageCitation(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns version for a package of modules*/
+	public String getPackageVersion(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns version for a package of modules as an integer*/
+	public int getPackageVersionInt(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/** Returns build number for a package of modules as an integer*/
+	public int getPackageBuildNumber(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	/** Returns authors for a package of modules*/
+	public String getPackageAuthors(){
+		return null;
+	}
+	public String getPackageDateReleased(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Returns the URL for the web page about the package*/
+	public String getPackageURL(){
+		return null;  
+	}
+	/*.................................................................................................................*/
+	/** Returns the integer version of Mesquite for which this package was first released*/
+	public int getVersionOfFirstRelease(){
+		return 0;  
+	}
+
+	public boolean isSubstantive(){
+		return false;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/PackageIntroInterface.java b/Source/mesquite/lib/duties/PackageIntroInterface.java
new file mode 100644
index 0000000..eff0afd
--- /dev/null
+++ b/Source/mesquite/lib/duties/PackageIntroInterface.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Serves to introduce a package*/
+
+public interface PackageIntroInterface  {
+
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage();
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash screen banner and possibly also URL*/
+	public boolean hasSplash();
+	/*.................................................................................................................*/
+	/** Returns the URL of document shown when splash screen icon touched. By default, returns path to module's manual*/
+	public String getSplashURL();
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+	public String getPackageCitation();
+	/*.................................................................................................................*/
+	/** Returns version for a package of modules*/
+	public String getPackageVersion();
+	/*.................................................................................................................*/
+	/** Returns authors for a package of modules*/
+	public String getPackageAuthors();
+	/*.................................................................................................................*/
+	/** Returns date released for a package of modules*/
+	public String getPackageDateReleased();
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules*/
+	public String getPackageName();
+	/*.................................................................................................................*/
+	/** Returns version for a package of modules as an integer*/
+	public int getPackageVersionInt();
+	/*.................................................................................................................*/
+	/** Returns build number for a package of modules as an integer*/
+	public int getPackageBuildNumber();
+	/*.................................................................................................................*/
+	/** Returns the URL for the web page about the package*/
+	public String getPackageURL();
+ 	/*.................................................................................................................*/
+	/** Returns the integer version of Mesquite for which this package was first released*/
+	public int getVersionOfFirstRelease();
+	
+	public boolean getHideable();
+}
+
+
diff --git a/Source/mesquite/lib/duties/ParametersExplorer.java b/Source/mesquite/lib/duties/ParametersExplorer.java
new file mode 100644
index 0000000..c8688ed
--- /dev/null
+++ b/Source/mesquite/lib/duties/ParametersExplorer.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+
+import mesquite.lib.*;
+
+/* ======================================================================== */
+
+public abstract class ParametersExplorer extends MesquiteModule  {
+	public Class getDutyClass() {
+		return ParametersExplorer.class;
+	}
+	public String getDutyName() {
+		return "Parameters Explorer";
+	}
+	/*.................................................................................................................*/
+	public abstract boolean setExplorable(ParametersExplorable explorable);
+	/*.................................................................................................................*/
+	/** notifies this module that explorable's previous values are now invalid */
+	public abstract void explorableChanged(ParametersExplorable explorable);
+	/*.................................................................................................................*/
+	/** notifies this module that explorable's list of parameters is now invalid */
+	public abstract void parameterSpecsChanged(ParametersExplorable explorable);
+	
+
+}
diff --git a/Source/mesquite/lib/duties/ReadFileFromString.java b/Source/mesquite/lib/duties/ReadFileFromString.java
new file mode 100644
index 0000000..806e9ee
--- /dev/null
+++ b/Source/mesquite/lib/duties/ReadFileFromString.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import mesquite.lib.CommandRecord;
+import mesquite.lib.Taxa;
+import mesquite.lib.characters.CharacterData;
+
+public interface ReadFileFromString {
+
+	public void readFileFromString(CharacterData data, Taxa taxa, String contents, String arguments);
+
+		
+}
diff --git a/Source/mesquite/lib/duties/ScattergramAssistantA.java b/Source/mesquite/lib/duties/ScattergramAssistantA.java
new file mode 100644
index 0000000..1896510
--- /dev/null
+++ b/Source/mesquite/lib/duties/ScattergramAssistantA.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*An analytical assistant for scattergrams*/
+
+public abstract class ScattergramAssistantA extends ChartAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return ScattergramAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Scattergram";
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/ScriptingManager.java b/Source/mesquite/lib/duties/ScriptingManager.java
new file mode 100644
index 0000000..4df3de3
--- /dev/null
+++ b/Source/mesquite/lib/duties/ScriptingManager.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages scripting.  Also reads and writes MESQUITE block.  Example module:
+"Manage MESQUITE block" (class ManageTaxa)*/
+
+public abstract class ScriptingManager extends FileElementManager   {
+
+   	 public Class getDutyClass() {
+   	 	return ScriptingManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of scripting, including read/write MESQUITE block";
+   	 }
+	
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/SpecsSetManager.java b/Source/mesquite/lib/duties/SpecsSetManager.java
new file mode 100644
index 0000000..45ef435
--- /dev/null
+++ b/Source/mesquite/lib/duties/SpecsSetManager.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages spec sets.*/
+
+public abstract class SpecsSetManager extends FileInit implements ElementManager   {
+	/*.................................................................................................................*/
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+
+   	 public Class getDutyClass() {
+   	 	return SpecsSetManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of specification sets";
+   	 }
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void deleteElement(FileElement e){
+		if (e instanceof SpecsSet){
+			if (getElementClass()!=null && getElementClass().isAssignableFrom(e.getClass())) {
+				SpecsSet t = (SpecsSet)e;
+				AssociableWithSpecs aws = t.getParent();
+				if (aws !=null)
+					aws.removeSpecsSet(t,getElementClass());
+			}
+		}
+	}
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+  	 public ManagerAssistant showSpecsSets(Object obj, String listerName){
+    	 		//Check to see if already has lister for this
+    	 		boolean found = false;
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if (((ManagerAssistant)e).showing(obj)) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return ((ManagerAssistant)e);
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize(listerName));
+	 			if (lister!=null) {
+	 				lister.showListWindow(obj);
+    	 			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+    	 				lister.getModuleWindow().setVisible(true);
+    	 		}
+	 		return lister;
+    	 		
+  	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/StringMatcher.java b/Source/mesquite/lib/duties/StringMatcher.java
new file mode 100644
index 0000000..0a33aa6
--- /dev/null
+++ b/Source/mesquite/lib/duties/StringMatcher.java
@@ -0,0 +1,33 @@
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Superclass of file interpreting modules (e.g., NEXUS file reader/writer).  Different subclasses are expected
+to read different data file formats.  Example module: "Interpret NEXUS files" (class InterpretNexus).  Example of use:
+see BasicFileCoordinator.*/
+
+/** a subclass for determining whether two strings match*/
+public abstract class StringMatcher extends MesquiteModule  {
+
+	/** returns true if the options are already specified.*/
+	public  boolean optionsSpecified(){
+		return false;
+	}
+	/** returns true if the options are set and accepted.*/
+	public  boolean queryOptions(){
+		return true;
+	}
+	/** returns whether two strings are considered equal.*/
+	public abstract boolean stringsMatch(String s1, String s2);
+	
+	public boolean useDefaultMatching() {
+		return false;
+	}
+	
+	
+}
+
+
diff --git a/Source/mesquite/lib/duties/TWindowMaker.java b/Source/mesquite/lib/duties/TWindowMaker.java
new file mode 100644
index 0000000..f36f599
--- /dev/null
+++ b/Source/mesquite/lib/duties/TWindowMaker.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+
+public abstract class TWindowMaker extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TWindowMaker.class;
+   	 }
+ 	public  abstract void setTree(Tree tree, boolean suppressDrawing);
+	public  abstract void setTree(Tree tree);
+	public  abstract void setWindowVisible(boolean vis);
+	/*.................................................................................................................*/
+	public void  suppressDrawing(boolean suppress){
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistant.java b/Source/mesquite/lib/duties/TaxaDisplayAssistant.java
new file mode 100644
index 0000000..c72d1c8
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistant.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*A superclass for the various subclasses of TaxaDisplayAssistants (I, D and A)*/
+
+public abstract class TaxaDisplayAssistant extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Taxa Display";
+   	 }
+	public  abstract TaxaDisplayExtra createTaxaDisplayExtra(TaxaDisplay taxaDisplay);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantA.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantA.java
new file mode 100644
index 0000000..adbedf5
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantA.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TaxaDisplayAssistants for analysis */
+public abstract class TaxaDisplayAssistantA extends TaxaDisplayAssistantAD  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis Assistant for Taxa Display";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantAD.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantAD.java
new file mode 100644
index 0000000..24cefe0
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantAD.java
@@ -0,0 +1,25 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*A superclass for the various subclasses of TaxaDisplayAssistants (I, D and A)*/
+
+public abstract class TaxaDisplayAssistantAD extends TaxaDisplayAssistant  {
+}
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantD.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantD.java
new file mode 100644
index 0000000..b596619
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantD.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TaxaDisplayAssistants for display.  (Their menu items
+are placed in a display-controlling menu) */
+public abstract class TaxaDisplayAssistantD extends TaxaDisplayAssistantAD  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistantD.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Display Assistant for Taxa Display";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantDI.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantDI.java
new file mode 100644
index 0000000..229e9c4
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantDI.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*Used for drawing-only assistants (for use by any taxa window)*/
+
+public abstract class TaxaDisplayAssistantDI extends TaxaDisplayAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistantDI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Taxa Display";
+   	 }
+	public  abstract TaxaDisplayExtra createTaxaDisplayExtra(TaxaDisplay taxaDisplay);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantI.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantI.java
new file mode 100644
index 0000000..39fab24
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantI.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TaxaDisplayAssistants that are INITS.  Used by Basic Taxa Window for tool modules*/
+public abstract class TaxaDisplayAssistantI extends TaxaDisplayAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Taxa Display";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaDisplayAssistantMA.java b/Source/mesquite/lib/duties/TaxaDisplayAssistantMA.java
new file mode 100644
index 0000000..4fa8679
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaDisplayAssistantMA.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TaxaDisplayAssistants for analysis; these are allowed for use by windows with multiple taxa displays*/
+public abstract class TaxaDisplayAssistantMA extends TaxaDisplayAssistantA  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaDisplayAssistantMA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis Assistant for Taxa Display (Allows multiple)";
+   	 }
+/*   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TaxaLegendMaker", "#TraceCharacterHistory"};
+   	 }
+
+*/
+
+
+}
+
diff --git a/Source/mesquite/lib/duties/TaxaManager.java b/Source/mesquite/lib/duties/TaxaManager.java
new file mode 100644
index 0000000..7f25dc6
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaManager.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages sets of taxa.  Also reads and writes TAXA NEXUS block.  Example module:
+"Manage TAXA blocks" (class ManageTaxa)*/
+
+public abstract class TaxaManager extends FileElementManager   {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+
+   	 public Class getDutyClass() {
+   	 	return TaxaManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of sets of taxa, including read/write TAXA block";
+   	 }
+	
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	/** make new Taxa object with given name and number of taxa*/
+	public abstract Taxa makeNewTaxa(String name, int numTaxa, boolean userQuery);
+	public Class getElementClass(){
+		return Taxa.class;
+	}
+	public abstract String getTaxaBlock(Taxa taxa, TaxaBlock tB, MesquiteFile file);
+	public abstract MesquiteModule getListOfTaxaModule(Taxa taxa, boolean show);
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaPartitionSource.java b/Source/mesquite/lib/duties/TaxaPartitionSource.java
new file mode 100644
index 0000000..45ff7e3
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaPartitionSource.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies TaxaPartitions for use in calculation routines.
+(example, CurrentTaxaPartition and PartitionFromAssociation)*/
+
+public abstract class TaxaPartitionSource extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaPartitionSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Source of Taxa Partitions";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CurrentTaxaPartition"};
+   	 }
+   	/** returns partition for taxa */
+   	public abstract TaxaPartition getPartition(Taxa taxa);
+   	
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaSelectCoordinator.java b/Source/mesquite/lib/duties/TaxaSelectCoordinator.java
new file mode 100644
index 0000000..de5b512
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaSelectCoordinator.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public abstract class TaxaSelectCoordinator extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return TaxaSelectCoordinator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa selection coordinator";
+   	 }
+	public abstract void setTableAndObject(MesquiteTable table, Object object, boolean rows);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaSource.java b/Source/mesquite/lib/duties/TaxaSource.java
new file mode 100644
index 0000000..c758861
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaSource.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies taxa sets.*/
+
+public abstract class TaxaSource extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return TaxaSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Source of taxa blocks";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"Taxa Supplier"};
+   	 }
+   	 /**Returns a set of Taxa.  If the source wants to switch to another set of taxa, it can do so by calling parametersChanged*/
+   	public abstract Taxa getTaxa();
+   	
+    	public boolean isSubstantive(){
+   		return false;  
+   	}
+  }
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaTableAssistantI.java b/Source/mesquite/lib/duties/TaxaTableAssistantI.java
new file mode 100644
index 0000000..bb32cd1
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaTableAssistantI.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist tables with taxa (e.g., taxa List, data matrix editor).  
+These are INITs.*/
+
+public abstract class TaxaTableAssistantI extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaTableAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Taxon Table";
+   	}
+
+  	/** method called by data window to inform assistant that data have changed*/
+	public abstract void setTableAndTaxa(MesquiteTable table, Taxa taxa, boolean taxaAreRows);
+	
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxaWindowAssistant.java b/Source/mesquite/lib/duties/TaxaWindowAssistant.java
new file mode 100644
index 0000000..6bfe395
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaWindowAssistant.java
@@ -0,0 +1,39 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the taxa window.  The taxa window can place these in a menu to allow the user
+to hire them.  Generally these are modules that depend on the taxa in the taxa window.
+*/
+
+public abstract class TaxaWindowAssistant extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaWindowAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Taxa Window";
+   	 }
+	public  abstract void setTaxa(Taxa taxa);
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaWindowAssistantC.java b/Source/mesquite/lib/duties/TaxaWindowAssistantC.java
new file mode 100644
index 0000000..f79bc50
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaWindowAssistantC.java
@@ -0,0 +1,56 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the taxa window specialized for charts.*/
+
+public abstract class TaxaWindowAssistantC extends TaxaWindowAssistant  {
+	
+	/*.................................................................................................................*/
+	/** superStartJob is called automatically when an employee is hired.  This is intended for use by superclasses of modules that need
+	their own constructor-like call, without relying on the subclass to be polite enough to call super.startJob().*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+		addMenuItem("Show Taxa Window", makeCommand("showContext", this));
+		addMenuItem("-", null);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Shows the current context", null, commandName, "showContext")) {
+	  		if (getEmployer() instanceof Showable)
+	  			getEmployer().showMe();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return TaxaWindowAssistantC.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Chart Assistant for Taxa Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaWindowAssistantI.java b/Source/mesquite/lib/duties/TaxaWindowAssistantI.java
new file mode 100644
index 0000000..d084ad9
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaWindowAssistantI.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the taxa window hired automatically (an INIT).  New for 1.02*/
+
+public abstract class TaxaWindowAssistantI extends TaxaWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaWindowAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Taxa Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaWindowAssistantN.java b/Source/mesquite/lib/duties/TaxaWindowAssistantN.java
new file mode 100644
index 0000000..b406943
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaWindowAssistantN.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the taxa window NOT specialized for charts.*/
+
+public abstract class TaxaWindowAssistantN extends TaxaWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TaxaWindowAssistantN.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Generic Assistant for Taxa Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxaWindowMaker.java b/Source/mesquite/lib/duties/TaxaWindowMaker.java
new file mode 100644
index 0000000..74cd76f
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxaWindowMaker.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Presents a single taxa window.*/
+
+public abstract class TaxaWindowMaker extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaWindowMaker.class;
+   	 }
+  	public abstract void makeTaxaWindow(Taxa taxa);
+  	 
+  	public abstract TaxaDisplay getTaxaDisplay();
+  	
+ 	public String getDutyName() {
+ 		return "Taxa Window Maker";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TaxonNameAlterer.java b/Source/mesquite/lib/duties/TaxonNameAlterer.java
new file mode 100644
index 0000000..a7346d0
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxonNameAlterer.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to alter a data matrix.*/
+
+public abstract class TaxonNameAlterer extends MesquiteModule  {
+	protected MesquiteTable table;
+	protected Taxa taxa;
+	
+   	public Class getDutyClass() {
+   	 	return TaxonNameAlterer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon Name Alterer";
+   	}
+   	
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon names in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+   		return false;
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** A stub method for querying the user about options. If alterIndividualTaxonNames is used to 
+   	alter the names, and options need to be specified for the operation, then optionsQuery should be overridden.*/
+ 	public  boolean getOptions(Taxa taxa, int firstSelected){
+   		return true;
+   	}
+
+	/*.................................................................................................................*/
+   	/** A stub method for doing any necessary cleanup after taxon names have been altered.*/
+   	public void cleanupAfterAlterTaxonNames(){
+   	}
+	/*.................................................................................................................*/
+   	/** Called to alter taxon names in table. This is used if the altering procedure can be done on one name
+   	at a time, independent of all other name.  If the altering procedure involves dependencies between names,
+   	then alterTaxonNames should be overridden with a method that uses another procedure.  */
+   	public boolean alterIndividualTaxonNames(Taxa taxa, MesquiteTable table){
+   		if (taxa==null)
+   			return false;
+   		int first = 0;
+   		if (table!=null) {
+   			first = table.firstRowNameSelected();
+   			if (first<0)
+   				first = table.firstRowSelected();   		
+   			if (first<0)
+   				first = 0;
+   		}
+   		this.taxa = taxa;
+   		this.table = table;
+   	
+		if (!getOptions(taxa, first))			return false;
+			
+		boolean anyChanged = false;
+		boolean okDoIt = !taxa.anySelected() && !table.anythingSelected();
+		for (int it=0; it<taxa.getNumTaxa(); it++){
+			
+			if ((okDoIt || taxa.getSelected(it) || table.isRowSelected(it) || table.isRowNameSelected(it)) && alterName(taxa, it))				anyChanged = true;
+		}
+   		return anyChanged;
+   	}
+
+	/*.................................................................................................................*/
+   	/** Called to alter taxon names in those cells selected in table.  Returns true if any taxon names are altered.
+   	This should be overridden if the is doing something that involves dependencies between names.*/
+   	public boolean alterTaxonNames(Taxa taxa, MesquiteTable table){
+    	boolean altered = alterIndividualTaxonNames(taxa, table);
+   		if (altered)
+   			cleanupAfterAlterTaxonNames();
+   		return altered;
+   	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxonPairSource.java b/Source/mesquite/lib/duties/TaxonPairSource.java
new file mode 100644
index 0000000..3351e8c
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxonPairSource.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies taxa.*/
+
+public abstract class TaxonPairSource extends MesquiteModule implements ItemsSource  {
+   	 public Class getDutyClass() {
+   	 	return TaxonPairSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon Pair Source";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredTaxonPairs"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+
+   	 /**Returns TaxonPair number iPair, and sets current Taxon number to iPair*/
+   	public abstract TaxonPair getTaxonPair(Taxa taxa, int iPair);
+   	
+   	 /**Returns number of Taxons available.  If Taxons can be supplied indefinitely, returns MesquiteInteger.infinite*/
+   	public abstract int getNumberOfTaxonPairs(Taxa taxa);
+   	/** returns name of item ic*/
+   	public abstract String getTaxonPairName(Taxa taxa, int ic);
+
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return getTaxonPair(taxa, ic);
+   	}
+   	/** returns number of pairs for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfTaxonPairs(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Taxon Pair";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Taxon Pairs";
+   	}
+   	
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+
+  	ObjectSpecsSet partition;
+  	/** zzzzzzzzzzzz*/
+     	public void setEnableWeights(boolean enable){
+    	}
+  	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	public void prepareItemColors(Taxa taxa){
+		partition=null;
+  	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getTaxonPairName(taxa, ic);
+   	}
+ }
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxonSelector.java b/Source/mesquite/lib/duties/TaxonSelector.java
new file mode 100644
index 0000000..750375d
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxonSelector.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to select taxa in a table.*/
+
+public abstract class TaxonSelector extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxonSelector.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon selector";
+   	}
+   	
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to select the taxa.  It should only add to a selection, not deselect any currently selected.*/
+   	public abstract void selectTaxa(Taxa taxa, mesquite.lib.characters.CharacterData data);
+   	/** Called to select the taxa.  It should only add to a selection, not deselect any currently selected.*/
+   	public abstract void selectTaxa(Taxa taxa);
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxonSource.java b/Source/mesquite/lib/duties/TaxonSource.java
new file mode 100644
index 0000000..721f5da
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxonSource.java
@@ -0,0 +1,113 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies taxa.*/
+
+public abstract class TaxonSource extends MesquiteModule implements ItemsSource  {
+   	 public Class getDutyClass() {
+   	 	return TaxonSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon Source";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredTaxa"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+
+   	 /**Returns first tree, and sets current tree number to 0*/
+   	public abstract Taxon getFirstTaxon(Taxa taxa);
+   	
+   	 /**Returns Taxon number iTaxon, and sets current Taxon number to iTaxon*/
+   	public abstract Taxon getTaxon(Taxa taxa, int iTaxon);
+   	
+   	 /**Increments current Taxon number and returns that Taxon.*/
+   	public abstract Taxon getNextTaxon(Taxa taxa);
+   	
+   	 /**Returns number of Taxons available.  If Taxons can be supplied indefinitely, returns MesquiteInteger.infinite*/
+   	public abstract int getNumberOfTaxa(Taxa taxa);
+   	/** returns name of item ic*/
+   	public abstract String getTaxonName(Taxa taxa, int ic);
+
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return getTaxon(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfTaxa(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Taxon";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Taxa";
+   	}
+   	
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+
+  	ObjectSpecsSet partition;
+  	/** zzzzzzzzzzzz*/
+     	public void setEnableWeights(boolean enable){
+    	}
+  	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	public void prepareItemColors(Taxa taxa){
+		if (taxa==null)
+			partition=null;
+		else
+			partition = (ObjectSpecsSet)taxa.getCurrentSpecsSet(TaxaPartition.class);
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		if (partition==null || taxa == null)
+   			return null;
+		TaxaGroup mi =(TaxaGroup)partition.getProperty(ic);
+		if (mi!=null && mi.getColor()!=null)
+			return (mi.getColor());
+		return null;
+   	}
+ 	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getTaxonName(taxa, ic);
+   	}
+  }
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TaxonUtility.java b/Source/mesquite/lib/duties/TaxonUtility.java
new file mode 100644
index 0000000..ccb140a
--- /dev/null
+++ b/Source/mesquite/lib/duties/TaxonUtility.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class TaxonUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxonUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon list utility";
+   	 }
+
+   	/** if returns true, then requests to remain on even after operateOnTaxa is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the taxa in the block.  Returns true if taxa altered*/
+   	public abstract boolean operateOnTaxa(Taxa taxa);
+}
+
diff --git a/Source/mesquite/lib/duties/TextDisplayer.java b/Source/mesquite/lib/duties/TextDisplayer.java
new file mode 100644
index 0000000..c5859da
--- /dev/null
+++ b/Source/mesquite/lib/duties/TextDisplayer.java
@@ -0,0 +1,53 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Module that displays a file.*/
+
+public abstract class TextDisplayer extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return TextDisplayer.class;
+   	 }
+	
+ 	public String getDutyName() {
+ 		return "Text Displayer";
+   	 } 
+	/** displays contents of given local file.*/
+	public abstract void showFile(String pathName, int maxCharacters, boolean goAwayable);
+	/** displays contents of given local file.*/
+	public abstract void showFile(String pathName, int maxCharacters, boolean goAwayable, int fontSize, boolean monospaced);
+	
+	/** displays contents of given file.*/
+	public abstract void showFile(MesquiteFile file, int maxCharacters, boolean goAwayable);
+	/** displays contents of given file.*/
+	public abstract void showFile(MesquiteFile file, int maxCharacters, boolean goAwayable, int fontSize, boolean monospaced);
+	/** displays a string.*/
+	public abstract void showText(String s, String title, boolean goAwayable);
+	/** sets as separate normal window (w = 0), set as tile (w = 1), or popped out as separate window (w=2).  Default Popped Out.  Must be called before first call to showFile or showText.*/
+	public abstract void setPoppedOut(int w);
+	/** sets whether text is to wrap at right margin.  Must be called before first call to showFile or showText.*/
+	public abstract void setWrap(boolean w);
+	/** sets whether allows pasting into window.  Must be called before first call to showFile or showText.*/
+	public abstract void setAllowPaste(boolean paste);
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TraceCharacterInit.java b/Source/mesquite/lib/duties/TraceCharacterInit.java
new file mode 100644
index 0000000..bdb09f3
--- /dev/null
+++ b/Source/mesquite/lib/duties/TraceCharacterInit.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Is hired on startup by trace character.*/
+
+public abstract class TraceCharacterInit extends MesquiteModule  {
+   	 public Class getDutyClass() {
+   	 	return TraceCharacterInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Trace Character INIT";
+   	 }
+   	 
+   	 public abstract void setCharacterHistoryContainers(Vector historyContainers);
+   }
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeAlterer.java b/Source/mesquite/lib/duties/TreeAlterer.java
new file mode 100644
index 0000000..a63c558
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeAlterer.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class TreeAlterer extends TreeTransformer  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeAlterer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Alterer";
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeAltererMult.java b/Source/mesquite/lib/duties/TreeAltererMult.java
new file mode 100644
index 0000000..85d7701
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeAltererMult.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class TreeAltererMult extends TreeAlterer implements TreeTransformerMult  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeAltererMult.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Alterer (multiple trees)";
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeBlockFiller.java b/Source/mesquite/lib/duties/TreeBlockFiller.java
new file mode 100644
index 0000000..bf0e420
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeBlockFiller.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies trees (compare to OneTreeSource), for instance from a file or simulated.  Most modules
+are subclasses of the subclass TreeSource*/
+
+public abstract class TreeBlockFiller extends MesquiteModule   {
+   	 public Class getDutyClass() {
+   	 	return TreeBlockFiller.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Block Filler";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeSource.gif";
+   	 }
+   	 
+	 public boolean permitSeparateThreadWhenFilling(){
+		 return true;
+	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#SimulateTree", "#RandomModifTree", "#StoredTrees"};
+   	 }
+   	 
+    /** TreeBlockFillers should override this if they want special commands to be sent to a tree window if a tree window is created after they are used. */
+  	 public String getExtraTreeWindowCommands (){
+   		 return "";
+   	 }
+  	 
+     /** TreeBlockFillers should override this if they want special commands to be sent to a tree window if a tree window is created after they are used. */
+  	 public String getExtraIntermediateTreeWindowCommands (){
+   		 return "";
+   	 }
+
+   	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+   	public Reconnectable getReconnectable(){
+   		return null;
+   	}
+   	
+   	 /** Returns whether there is a limited (e.g. stored trees) or unlimited (e.g., simulated trees) number of trees available.
+   	 If this is a TreeSource, this method checks the getNumberOfTrees method.  Otherwise, the module should
+   	 override it.*/
+   	 public boolean hasLimitedTrees(Taxa taxa){
+  		if (taxa == null)
+  			return true;
+  		if (this instanceof TreeSource) {
+  			TreeSource ts = (TreeSource)this;
+  			int numTrees = ts.getNumberOfTrees(taxa);
+  			return (numTrees>=0 && MesquiteInteger.isFinite(numTrees));
+  		}
+  		else 
+  			return false;
+   	 }
+
+
+   	 /** Fills the passed tree block with trees.  The parameter numberIfUnlimited indicates how many trees
+   	 are to be filled if the source offers an unlimited number (e.g., if simulated trees).  This method by default calls
+   	 the methods of TreeSource if this object is of the TreeSource subclass.  If this is not a TreeSource, 
+   	 this method should be overridden*/
+  	public void fillTreeBlock(TreeVector treeList, int numberIfUnlimited, boolean verbose){
+  		if (treeList==null || abort)
+  			return;
+  		if (this instanceof TreeSource && !abort) {
+  			Taxa taxa = treeList.getTaxa();
+  			TreeSource ts = (TreeSource)this;
+  			int numTrees = ts.getNumberOfTrees(taxa);
+  			if (numTrees<=0 || !MesquiteInteger.isFinite(numTrees)) 
+  				numTrees = numberIfUnlimited;
+  			if (numTrees<=0 || !MesquiteInteger.isFinite(numTrees))
+  				return;
+  			Tree tree = ts.getTree(taxa, 0);
+  			if (tree!=null) {
+  				treeList.addElement(tree.cloneTree(), false);
+  			}
+			if (verbose) 
+				logln("Trees about to be made by " + getName());
+  			for(int i=1; i<numTrees && tree != null  && !isDoomed() && !abort; i++) {
+  				tree = ts.getTree(taxa, i);
+  				if (tree!=null)  {
+  					CommandRecord.tick("Adding tree to trees block " + i);
+  					treeList.addElement(tree.cloneTree(), false);
+					if (i%100 == 0)
+						logln("  trees added: " + i);
+  				}
+  			}
+  			treeList.setName(getName());
+			treeList.setAnnotation ("Parameters: "  + getParameters(), false);
+
+  		}
+  		abort = false;
+  	}
+  	
+	 /** Fills the passed tree block with trees.  The parameter numberIfUnlimited indicates how many trees
+	 are to be filled if the source offers an unlimited number (e.g., if simulated trees).  This method by default calls
+	 the methods of TreeSource if this object is of the TreeSource subclass.  If this is not a TreeSource, 
+	 this method should be overridden*/
+	public void fillTreeBlock(TreeVector treeList, int numberIfUnlimited){
+		fillTreeBlock(treeList,numberIfUnlimited, false);
+	}
+
+
+	public void retrieveTreeBlock(TreeVector treeList, int numberIfUnlimited){
+		retrieveTreeBlock(treeList,numberIfUnlimited);
+	}
+
+	protected boolean abort = false;
+	public void abortFilling(){
+		abort = true;
+	}
+	
+
+
+  }
+
+
+	
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeBlockSource.java b/Source/mesquite/lib/duties/TreeBlockSource.java
new file mode 100644
index 0000000..7d6cbd5
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeBlockSource.java
@@ -0,0 +1,131 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies TreeVectors for instance from a file or simulated.*/
+
+public abstract class TreeBlockSource extends MesquiteModule implements ItemsSource  {
+   	 public Class getDutyClass() {
+   	 	return TreeBlockSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Block Source";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeSource.gif";
+   	 }
+ 	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredTreeBlocks"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+   	 /** indicates preferred set of taxa for which trees will be requested */
+  	public abstract void setPreferredTaxa(Taxa taxa);
+  	
+   	 /**Returns first tree block, and sets current tree number to 0*/
+   	public abstract TreeVector getFirstBlock(Taxa taxa);
+   	
+   	 /**Returns indexth tree block*/
+   	public abstract TreeVector getBlock(Taxa taxa, int ic);
+   	
+   	 /**Increments current list number and returns that list.*/
+   	public abstract TreeVector getNextBlock(Taxa taxa);
+   	
+   	 /**Returns current tree block.*/
+   	public abstract TreeVector getCurrentBlock(Taxa taxa);
+
+   	 /**Returns number of trees available.  If trees can be supplied indefinitely, returns MesquiteInteger.infinite*/
+   	public abstract int getNumberOfTreeBlocks(Taxa taxa);
+   	
+   	 /**Returns name of ith tree block.*/
+   	public abstract String getTreeBlockNameString(Taxa taxa, int i);
+
+   	/** queryies the user to choose a tree and returns an integer of the tree chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numBlocks = getNumberOfTreeBlocks(taxa);
+ 		if (MesquiteInteger.isCombinable(numBlocks)){
+ 			String[] s = new String[numBlocks];
+ 			for (int i=0; i<numBlocks; i++){
+ 				s[i]= getTreeBlockNameString(taxa, i);
+ 			}
+ 			if (forMessage == null) {
+ 				forMessage = "Choose tree block";
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose tree block", forMessage, MesquiteString.helpString, s, 0);
+ 		}
+ 		else  {
+ 			if (forMessage == null) {
+ 				forMessage = "Number of tree block to be used";
+ 			}
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose tree block", forMessage, 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return MesquiteTree.toInternal(r);
+ 			else
+ 				return r;
+ 		}
+ 				
+    	}
+
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return getBlock(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfTreeBlocks(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Tree Block";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Tree Blocks";
+   	}
+   	
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+     	public void setEnableWeights(boolean enable){
+    	}
+  	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+  	/** zzzzzzzzzzzz*/
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getTreeBlockNameString(taxa, ic);
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistant.java b/Source/mesquite/lib/duties/TreeDisplayAssistant.java
new file mode 100644
index 0000000..d847cb4
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistant.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*A superclass for the various subclasses of TreeDisplayAssistants (I, D and A)*/
+
+public abstract class TreeDisplayAssistant extends TreeWDIAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistant.class;
+   	 }
+ 	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Assistant for Tree Display";
+   	 }
+	public  abstract TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay);
+	public  Taxa getTaxa(){
+		MesquiteModule mb = findEmployerWithDuty(TreeWindowMaker.class);
+		if (mb != null)
+			return ((TreeWindowMaker)mb).getTaxa();
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantA.java b/Source/mesquite/lib/duties/TreeDisplayAssistantA.java
new file mode 100644
index 0000000..94cced4
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantA.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TreeDisplayAssistants for analysis */
+public abstract class TreeDisplayAssistantA extends TreeDisplayAssistantAD  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis Assistant for Tree Display";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TreeLegendMaker", "#TraceCharacterHistory"};
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantAD.java b/Source/mesquite/lib/duties/TreeDisplayAssistantAD.java
new file mode 100644
index 0000000..a6ee846
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantAD.java
@@ -0,0 +1,22 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+public abstract class TreeDisplayAssistantAD extends TreeDisplayAssistant  {
+}
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantAO.java b/Source/mesquite/lib/duties/TreeDisplayAssistantAO.java
new file mode 100644
index 0000000..36dd0bb
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantAO.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TreeDisplayAssistants for display.  (Their menu items
+are placed in a display-controlling menu) */
+public abstract class TreeDisplayAssistantAO extends TreeDisplayAssistantAD  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantAO.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis (Other) Assistant for Tree Display";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantD.java b/Source/mesquite/lib/duties/TreeDisplayAssistantD.java
new file mode 100644
index 0000000..79b7dd2
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantD.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TreeDisplayAssistants for display.  (Their menu items
+are placed in a display-controlling menu) */
+public abstract class TreeDisplayAssistantD extends TreeDisplayAssistantAD  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantD.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Display Assistant for Tree Display";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantDI.java b/Source/mesquite/lib/duties/TreeDisplayAssistantDI.java
new file mode 100644
index 0000000..b29ccd3
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantDI.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/*Used for drawing-only assistants (for use by any tree window)*/
+
+public abstract class TreeDisplayAssistantDI extends TreeDisplayAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantDI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Tree Display";
+   	 }
+	public  abstract TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay);
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantI.java b/Source/mesquite/lib/duties/TreeDisplayAssistantI.java
new file mode 100644
index 0000000..073bb81
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantI.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TreeDisplayAssistants that are INITS.  Used by Basic Tree Window for tool modules.
+ * Note: this should be renamed since these permit editing of the tree and thus are not for any tree display. TreeDisplayAssistantDEI*/
+public abstract class TreeDisplayAssistantI extends TreeDisplayAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Tree Display";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeDisplayAssistantMA.java b/Source/mesquite/lib/duties/TreeDisplayAssistantMA.java
new file mode 100644
index 0000000..881b4be
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeDisplayAssistantMA.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** This abstract class is for modules that are TreeDisplayAssistants for analysis; these are allowed for use by windows with multiple tree displays*/
+public abstract class TreeDisplayAssistantMA extends TreeDisplayAssistantA  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeDisplayAssistantMA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Analysis Assistant for Tree Display (Allows multiple)";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#TreeLegendMaker", "#TraceCharacterHistory"};
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeInferer.java b/Source/mesquite/lib/duties/TreeInferer.java
new file mode 100644
index 0000000..fc9e621
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeInferer.java
@@ -0,0 +1,191 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.duties;
+
+import java.awt.Button;
+import java.awt.Checkbox;
+
+import mesquite.lib.*;
+import mesquite.trees.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies trees (compare to OneTreeSource), for instance from a file or simulated.  Most modules
+are subclasses of the subclass TreeSource*/
+
+public abstract class TreeInferer extends TreeBlockFiller {
+	Listened listened;
+	TWindowMaker tWindowMaker;
+	 MesquiteBoolean autoSaveFile = new MesquiteBoolean(false);
+
+	 
+	public Class getDutyClass() {
+		return TreeInferer.class;
+	}
+	public String getDutyName() {
+		return "Tree Inferer";
+	}
+	public String[] getDefaultModule() {
+		return null;
+	}
+	
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("autoSaveFile".equalsIgnoreCase(tag))
+			autoSaveFile.setFromTrueFalseString(content);
+		super.processSingleXMLPreference(tag, content);
+	}
+	
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "autoSaveFile", autoSaveFile);  
+	
+		buffer.append(super.preparePreferencesForXML());
+		return buffer.toString();
+	}
+
+	// override to give more information
+	public String getHTMLDescriptionOfStatus(){
+		return getName();
+	}
+	public boolean canGiveIntermediateResults(){
+		return false;
+	}
+	public Tree getLatestTree(Taxa taxa, MesquiteNumber score, MesquiteString titleForWindow){
+		if (score != null)
+			score.setToUnassigned();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setWindowMaker " , tWindowMaker);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module showing the tree", "[name of module]", commandName, "setWindowMaker")) {
+			tWindowMaker = (TWindowMaker)hireNamedEmployee(TWindowMaker.class, "#ObedientTreeWindow");
+			String commands = getExtraTreeWindowCommands();
+			MesquiteWindow w = tWindowMaker.getModuleWindow();
+			
+			if (w != null){
+				if (w instanceof SimpleTreeWindow)
+					((SimpleTreeWindow)w).setWindowTitle("Most Recent Tree");
+				Puppeteer p = new Puppeteer(this);
+				p.execute(w, commands, new MesquiteInteger(0), "end;", false);
+			}
+			return tWindowMaker;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	public void registerListener(MesquiteListener listener){
+		if (listened == null)
+			listened = new Listened();
+		listened.addListener(listener);
+	}
+	public void deregisterListener(MesquiteListener listener){
+		if (listened == null)
+			return;
+		listened.removeListener(listener);
+	}
+	protected void newResultsAvailable(TaxaSelectionSet outgroupSet){
+		MesquiteString title = new MesquiteString();
+		Tree tree = getLatestTree(null, null, title);
+		parametersChanged();
+		
+		if (tree instanceof AdjustableTree) {
+			((AdjustableTree)tree).standardize(outgroupSet, false);
+		}
+		showIntermediatesWindow();
+		if (tree != null && tWindowMaker != null){ 
+			tWindowMaker.setTree(tree);
+			MesquiteWindow w = tWindowMaker.getModuleWindow();
+			if (w != null && w instanceof SimpleTreeWindow){
+				SimpleTreeWindow stw = (SimpleTreeWindow)w;
+				if (title.isBlank())
+					stw.setWindowTitle(title.getValue());
+				
+				int taxonSpacing = 14;
+				int numTaxaInTree = tree.numberOfTerminalsInClade(tree.getRoot());
+				int orientation = stw.getOrientation();
+				if (orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT){
+					stw.setMinimumFieldSize(-1, numTaxaInTree*taxonSpacing);  
+				}
+				else if (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN){
+					stw.setMinimumFieldSize(numTaxaInTree*taxonSpacing, -1);  
+				}
+				else 
+					stw.setMinimumFieldSize(-1, -1); 
+				stw.sizeDisplays();
+				
+			}
+			String commands = getExtraIntermediateTreeWindowCommands();
+			if (!StringUtil.blank(commands)) {
+				if (w != null){
+					Puppeteer p = new Puppeteer(this);
+					p.execute(w, commands, new MesquiteInteger(0), "", false);
+				}
+			}
+
+
+		}
+		if (listened != null)
+			listened.notifyListeners(this, new Notification(MesquiteListener.NEW_RESULTS));
+	}
+	public void showIntermediatesWindow(){
+		if (tWindowMaker == null) {
+			tWindowMaker = (TWindowMaker)hireNamedEmployee(TWindowMaker.class, "#ObedientTreeWindow");
+			String commands = getExtraTreeWindowCommands();
+			MesquiteWindow w = tWindowMaker.getModuleWindow();
+			
+			if (w != null){
+				if (w instanceof SimpleTreeWindow)
+					((SimpleTreeWindow)w).setWindowTitle("Most Recent Tree");
+				Puppeteer p = new Puppeteer(this);
+				p.execute(w, commands, new MesquiteInteger(0), "end;", false);
+			}
+		}
+		if (tWindowMaker != null){
+			tWindowMaker.setWindowVisible(true);
+		}
+		
+	}
+	
+	Checkbox autoSaveFileCheckbox =  null;
+
+	public boolean getAutoSave() {
+		if (autoSaveFile!=null && autoSaveFile.getValue())
+			return true;
+		return false;
+	}
+	
+	// given the opportunity to fill in options for user
+	public  void addItemsToDialogPanel(ExtensibleDialog dialog){
+		autoSaveFileCheckbox = dialog.addCheckBox("auto-save file after inference", autoSaveFile.getValue());
+	}
+	public boolean optionsChosen(){
+		if (autoSaveFileCheckbox!=null)
+			autoSaveFile.setValue(autoSaveFileCheckbox.getState());
+		return true;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeInfoPanelAssistant.java b/Source/mesquite/lib/duties/TreeInfoPanelAssistant.java
new file mode 100644
index 0000000..66b3297
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeInfoPanelAssistant.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.trees.lib.*;
+
+
+/* ======================================================================== */
+/*A superclass for the various subclasses of TreeDisplayAssistants (I, D and A)*/
+
+public abstract class TreeInfoPanelAssistant extends TreeWDIAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeInfoPanelAssistant.class;
+   	 }
+ 	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Assistant for Tree Info Panel";
+   	 }
+	public  abstract TreeInfoExtraPanel getPanel(ClosablePanelContainer container);
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeSearcher.java b/Source/mesquite/lib/duties/TreeSearcher.java
new file mode 100644
index 0000000..c8c4f4a
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeSearcher.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Searchers to find trees that optimize something.*/
+
+public abstract class TreeSearcher extends MesquiteModule  {
+	TreeInferer treeInferer = null;
+
+   	 public Class getDutyClass() {
+   	 	return TreeSearcher.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Searcher";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#AddAndRearrange"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract boolean initialize(Taxa taxa);
+
+	 public TreeInferer getTreeInferer() {
+		 return treeInferer;
+	 }
+	 public void setTreeInferer(TreeInferer treeInferer) {
+		 this.treeInferer = treeInferer;
+	 }
+
+
+	 public String getExtraTreeWindowCommands (){
+   		 return "";
+   	 }
+	 public String getExtraIntermediateTreeWindowCommands (){
+   		 return "";
+   	 }
+
+   	 /** Fills the passed tree block with trees. */
+  	public abstract void fillTreeBlock(TreeVector treeList);
+  	  
+	public void setNumberTask(NumberForTree numTask){
+	}
+  	
+   	public boolean isReconnectable(){
+   		return false;
+   	}
+	
+	 public boolean canGiveIntermediateResults(){
+   		 return false;
+   	 }
+ 	public Tree getLatestTree(Taxa taxa, MesquiteNumber score, MesquiteString titleForWindow){
+   		 if (score != null)
+   			 score.setToUnassigned();
+   		 return null;
+   	 }
+	 protected void newResultsAvailable(TaxaSelectionSet outgroupTaxSet){
+ 		 if (getEmployer() instanceof TreeInferer){
+ 			 ((TreeInferer)getEmployer()).newResultsAvailable(outgroupTaxSet);
+ 		 }
+ 	 }
+	 //Override in subclasses
+		public String getHTMLDescriptionOfStatus(){
+			return getName();
+		}
+
+ 	 }
+
+
diff --git a/Source/mesquite/lib/duties/TreeSimulate.java b/Source/mesquite/lib/duties/TreeSimulate.java
new file mode 100644
index 0000000..5c2d1ff
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeSimulate.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Simulates trees.*/
+
+public abstract class TreeSimulate extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeSimulate.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/simulate.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Tree Simulate";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#EqualRatesMarkovSp"};
+   	 }
+   	 
+   	public abstract int getNumberOfTrees(Taxa taxa);
+   	 
+   	public abstract void initialize(Taxa taxa);
+   	public abstract Tree getSimulatedTree(Taxa taxa, Tree tree, int treeNumber, ObjectContainer extra, MesquiteLong seed);
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeSource.java b/Source/mesquite/lib/duties/TreeSource.java
new file mode 100644
index 0000000..e4d3b65
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeSource.java
@@ -0,0 +1,142 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies trees (compare to OneTreeSource), for instance from a file or simulated.*/
+
+public abstract class TreeSource extends TreeBlockFiller implements ItemsSource  {
+//	public static MesquiteBoolean closeIfTreeBlockDeleted = new MesquiteBoolean(false);
+   	 public Class getDutyClass() {
+   	 	return TreeSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Source";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredTrees", "#DefaultTrees", "#SimulateTree"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+
+   	 /** indicates preferred set of taxa for which trees will be requested */
+  	public abstract void setPreferredTaxa(Taxa taxa);
+  	
+   	 /**Returns tree number itree, and sets current tree number to itree*/
+   	public abstract Tree getTree(Taxa taxa, int itree);
+   	
+    /**Returns number of trees available.  If trees can be supplied indefinitely, returns MesquiteInteger.infinite.  If number of trees is finite but unknown, returns MesquiteInteger.finite*/
+   	public abstract int getNumberOfTrees(Taxa taxa);
+
+    /**Returns number of trees available.  If trees can be supplied indefinitely, returns MesquiteInteger.infinite.*/
+  	public int getNumberOfTrees(Taxa taxa, boolean determineNumberIfFinite) {
+  		return getNumberOfTrees(taxa);
+   	}
+   	 /**Returns name of ith tree.*/
+   	public abstract String getTreeNameString(Taxa taxa, int i);
+   	
+  	 /**Returns name to show in windows etc. for tree block or source of trees.*/
+  	public String getTreesDescriptiveString(Taxa taxa){
+  		return getNameForMenuItem();
+  	}
+ 	 /**Returns notes to show about these trees, e.g. in a footnote or text version.  For stored trees, this will include name and annotation of tree block.*/
+ 	public String getNotesAboutTrees(Taxa taxa){
+ 		return getNameAndParameters();
+ 	}
+
+   	/** queryies the user to choose a tree and returns an integer of the tree chosen*/
+   	public int queryUserChoose(Taxa taxa, String forMessage){
+ 		int ic=MesquiteInteger.unassigned;
+ 		int numTrees = getNumberOfTrees(taxa);
+ 		if (MesquiteInteger.isCombinable(numTrees)){
+ 			String[] s = new String[numTrees];
+ 			for (int i=0; i<numTrees; i++){
+ 				s[i]= getTreeNameString(taxa, i);
+ 			}
+ 			return ListDialog.queryList(containerOfModule(), "Choose tree", "Choose tree", MesquiteString.helpString, s, 0);
+ 		}
+ 		else  {
+ 			int r = MesquiteInteger.queryInteger(containerOfModule(), "Choose tree", "Number of tree to be used", 1);
+ 			if (MesquiteInteger.isCombinable(r))
+ 				return MesquiteTree.toInternal(r);
+ 			else
+ 				return r;
+ 		}
+ 				
+    	}
+
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return getTree(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfTrees(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Tree";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Trees";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	/**--------*/
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	/**--------*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getTreeNameString(taxa, ic);
+   	}
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new TSrcCompatibilityTest();
+  	 }
+}
+
+class TSrcCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return true;
+	}
+}
+
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeSourceDefinite.java b/Source/mesquite/lib/duties/TreeSourceDefinite.java
new file mode 100644
index 0000000..dc7b873
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeSourceDefinite.java
@@ -0,0 +1,106 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Supplies trees; the number is guaranteed to be finite and known.*/
+
+public abstract class TreeSourceDefinite extends MesquiteModule implements ItemsSource  {
+   	 public Class getDutyClass() {
+   	 	return TreeSourceDefinite.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Source (Finite)";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeSource.gif";
+   	 }
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#FiniteTreeSourceCoord"};
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public abstract void initialize(Taxa taxa);
+
+
+   	 /** indicates preferred set of taxa for which trees will be requested */
+  	public abstract void setPreferredTaxa(Taxa taxa);
+  	
+    	
+   	 /**Returns tree number itree, and sets current tree number to itree*/
+   	public abstract Tree getTree(Taxa taxa, int itree);
+   	
+    /**Returns number of trees available.  If trees can be supplied indefinitely, returns MesquiteInteger.infinite.  If number of trees is finite but unknown, returns MesquiteInteger.finite*/
+   	public abstract int getNumberOfTrees(Taxa taxa);
+
+   	 /**Returns name of ith tree.*/
+   	public abstract String getTreeNameString(Taxa taxa, int i);
+   	
+ 
+	/*===== For ItemsSource interface ======*/
+   	/** returns item numbered ic*/
+   	public Object getItem(Taxa taxa, int ic){
+   		return getTree(taxa, ic);
+   	}
+   	/** returns number of characters for given Taxa*/
+   	public int getNumberOfItems(Taxa taxa){
+   		return getNumberOfTrees(taxa);
+   	}
+   	/** returns name of type of item, e.g. "Character", or "Taxon"*/
+   	public String getItemTypeName(){
+   		return "Tree";
+   	}
+   	/** returns name of type of item, e.g. "Characters", or "Taxa"*/
+   	public String getItemTypeNamePlural(){
+   		return "Trees";
+   	}
+   	public Selectionable getSelectionable(){
+   		return null;
+   	}
+   	/**--------*/
+    	public void setEnableWeights(boolean enable){
+    	}
+   	public boolean itemsHaveWeights(Taxa taxa){
+   		return false;
+   	}
+   	public double getItemWeight(Taxa taxa, int ic){
+   		return MesquiteDouble.unassigned;
+   	}
+   	/**--------*/
+   	public void prepareItemColors(Taxa taxa){
+   	}
+   	public Color getItemColor(Taxa taxa, int ic){
+   		return null;
+   	}
+	/** zzzzzzzzzzzz*/
+   	public String getItemName(Taxa taxa, int ic){
+   		return getTreeNameString(taxa, ic);
+   	}
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new TSrcCompatibilityTest();
+  	 }
+}
+
+
+
+
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeSwapper.java b/Source/mesquite/lib/duties/TreeSwapper.java
new file mode 100644
index 0000000..637d5c4
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeSwapper.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Rearranges a given tree.*/
+
+public abstract class TreeSwapper extends MesquiteModule  {
+   	public Class getDutyClass() {
+   	 	return TreeSwapper.class;
+   	}
+ 	public String getDutyName() {
+ 		return "Tree Rearranger";
+	}
+   	 
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#SPRRearranger"};
+   	 }
+	/** Returns the number of rearrangments, not including the unarranged version of the tree.*/
+	public abstract long numberOfRearrangements(AdjustableTree tree);
+
+	/** Returns the number of rearrangments, not including the unarranged version of the tree.*/
+	public abstract long numberOfRearrangements(AdjustableTree tree, int baseNode);
+
+	/** Rearranges the tree to the i'th rearrangment. */
+	public abstract void rearrange(AdjustableTree tree, long i);
+
+
+	/** Rearranges the tree to the i'th rearrangment with the clade marked by the node. */
+	public abstract void rearrange(AdjustableTree tree, int baseNode, long i);
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreeTransformer.java b/Source/mesquite/lib/duties/TreeTransformer.java
new file mode 100644
index 0000000..2dab028
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeTransformer.java
@@ -0,0 +1,53 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**.*/
+
+public abstract class TreeTransformer extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeTransformer.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Transformer";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindowUtil.gif";
+   	 }
+	//Returns true if calling code is responsible for notifying listeners of tree.  This is the old version and is present here for compatibility; it should be considered deprecated.  Old classes will override this
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString){
+		return false;
+	}
+	/**/
+	
+	//Should be overridden; when previous version is deleted in future, this will be abstract.  returns whether successfully transformed.
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		
+		if (transformTree(tree, resultString)){
+			if (notify && tree instanceof Listened)
+				((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+		}
+		return true;
+		
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeTransformerMult.java b/Source/mesquite/lib/duties/TreeTransformerMult.java
new file mode 100644
index 0000000..f203311
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeTransformerMult.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An interface merely to allow tree transformers to claim they can handle multiple trees*/
+
+public interface TreeTransformerMult extends Listable {
+
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify);
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeUtility.java b/Source/mesquite/lib/duties/TreeUtility.java
new file mode 100644
index 0000000..39ee44f
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeUtility.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**This should NOT alter the tree.  New in 1.04*/
+
+public abstract class TreeUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree Utility";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindowUtil.gif";
+   	 }
+  	 
+   	 public abstract void useTree(Tree tree);
+   	 
+   	 /* for now it's assumed that the utility is used once then shut down.
+   	 public boolean pleaseLeaveMeOn() {
+   	 	return false;
+   	 }
+   	 */
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWDIAssistant.java b/Source/mesquite/lib/duties/TreeWDIAssistant.java
new file mode 100644
index 0000000..7f3966f
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWDIAssistant.java
@@ -0,0 +1,52 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Base class for TreeWindowAssistant, TreeDisplayAssistant, TreeInfoPanelAssistant.*/
+
+public abstract class TreeWDIAssistant extends MesquiteModule  {
+	
+	public String nameForWritableResults(){
+		return getName();
+	}
+	public boolean suppliesWritableResults(){
+		return false;
+	}
+	public Object getWritableResults(){
+		return null;
+	}
+	public Object getResultsHeading(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns writable Results", null, commandName, "getWritableResults")) {
+			return getWritableResults();
+		}
+		else if (checker.compare(this.getClass(), "Returns writable Results heading", null, commandName, "getResultsHeading")) {
+			return getResultsHeading();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistant.java b/Source/mesquite/lib/duties/TreeWindowAssistant.java
new file mode 100644
index 0000000..c7dab50
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistant.java
@@ -0,0 +1,44 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window.  The tree window can place these in a menu to allow the user
+to hire them.  Generally these are modules that depend on the tree in the tree window.
+Example modules:  CharactersChartForTree, FelsensteinContrasts, 
+MatricesChartForTree, MirrorTreeWindow.*/
+
+public abstract class TreeWindowAssistant extends TreeWDIAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistant.class;
+   	 }
+ 	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+	public String getDutyName() {
+ 		return "Assistant for Tree Window";
+   	 }
+	public  abstract void setTree(Tree tree);
+	
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistantA.java b/Source/mesquite/lib/duties/TreeWindowAssistantA.java
new file mode 100644
index 0000000..7d4229c
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistantA.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window, to appear in Analysis menu.*/
+
+public abstract class TreeWindowAssistantA extends TreeWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistantA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Tree Window (Analysis)";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistantC.java b/Source/mesquite/lib/duties/TreeWindowAssistantC.java
new file mode 100644
index 0000000..fc596dd
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistantC.java
@@ -0,0 +1,56 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window specialized for charts.*/
+
+public abstract class TreeWindowAssistantC extends TreeWindowAssistant  {
+	
+	/*.................................................................................................................*/
+	/** superStartJob is called automatically when an employee is hired.  This is intended for use by superclasses of modules that need
+	their own constructor-like call, without relying on the subclass to be polite enough to call super.startJob().*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+		addMenuItem("Show Tree Window", makeCommand("showContext", this));
+		addMenuItem("-", null);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Shows the current context", null, commandName, "showContext")) {
+	  		if (getEmployer() instanceof Showable)
+	  			getEmployer().showMe();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistantC.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Chart Assistant for Tree Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistantI.java b/Source/mesquite/lib/duties/TreeWindowAssistantI.java
new file mode 100644
index 0000000..5e5a969
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistantI.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window hired automatically (an INIT).  New for 1.02*/
+
+public abstract class TreeWindowAssistantI extends TreeWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Tree Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistantN.java b/Source/mesquite/lib/duties/TreeWindowAssistantN.java
new file mode 100644
index 0000000..348e7aa
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistantN.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window NOT specialized for charts.*/
+
+public abstract class TreeWindowAssistantN extends TreeWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistantN.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Generic Assistant for Tree Window";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowAssistantOA.java b/Source/mesquite/lib/duties/TreeWindowAssistantOA.java
new file mode 100644
index 0000000..a427778
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowAssistantOA.java
@@ -0,0 +1,36 @@
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**An assistant to the tree window, to appear in Analysis menu.*/
+
+public abstract class TreeWindowAssistantOA extends TreeWindowAssistant  {
+	
+   	 public Class getDutyClass() {
+   	 	return TreeWindowAssistantOA.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Assistant for Tree Window (Other Analysis)";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/lib/duties/TreeWindowMaker.java b/Source/mesquite/lib/duties/TreeWindowMaker.java
new file mode 100644
index 0000000..2bcac2d
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreeWindowMaker.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Presents a single tree window.*/
+
+public abstract class TreeWindowMaker extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return TreeWindowMaker.class;
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindow.gif";
+   	 }
+  	//public abstract void makeTreeWindow(Taxa taxa);
+  	public abstract Taxa getTaxa();
+  	public abstract MesquiteModule getTreeSource();
+  	public abstract TreeDisplay getTreeDisplay();
+	public abstract void transposeField();
+ 	public abstract boolean treeIsEdited();
+ 	public String getDutyName() {
+ 		return "Tree Window Maker";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/TreesManager.java b/Source/mesquite/lib/duties/TreesManager.java
new file mode 100644
index 0000000..0fb3fb4
--- /dev/null
+++ b/Source/mesquite/lib/duties/TreesManager.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** Manages lists of trees.  Also reads and writes TREES NEXUS block.  Example module: "Manage TREE blocks" (class ManageTrees).*/
+
+public abstract class TreesManager extends FileElementManager   {
+	public static final String WEIGHT = "Weight";
+
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+  	 public Class getDutyClass() {
+   	 	return TreesManager.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manager of lists of trees, including read/write TREES block";
+   	 }
+	
+	public abstract void addBlockListener(MesquiteListener ml);
+	public abstract void removeBlockListener(MesquiteListener ml);
+	public abstract int getNumberTreeBlocks(Taxa taxa, MesquiteFile file);
+	public abstract int getNumberTreeBlocks(Taxa taxa);
+	public abstract int getNumberTreeBlocks();
+	public abstract int getTreeBlockNumber(TreeVector trees);
+	public abstract int getTreeBlockNumber(Taxa taxa, TreeVector trees);
+	public abstract TreeVector getTreeBlock(Taxa taxa, int i);
+	public abstract TreeVector getTreeBlock(Taxa taxa, MesquiteFile file, int i);
+	public abstract TreeVector getTreeBlockByID(long id);  //this uses the temporary run-time id of the tree vector
+	public abstract String getTreeBlock(TreeVector trees, NexusBlock tB);
+	public abstract TreeVector makeNewTreeBlock(Taxa taxa, String name, MesquiteFile f);
+	public abstract Taxa findTaxaMatchingTable(TreeVector trees, MesquiteProject proj, MesquiteFile file, Vector table);
+	public abstract ListableVector getTreeBlockVector();
+	public Class getElementClass(){
+		return TreeVector.class;
+	}
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/UtilitiesAssistant.java b/Source/mesquite/lib/duties/UtilitiesAssistant.java
new file mode 100644
index 0000000..1c0be02
--- /dev/null
+++ b/Source/mesquite/lib/duties/UtilitiesAssistant.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Serves to hold a window for an employer.*/
+
+public abstract class UtilitiesAssistant extends MesquiteModule   {
+
+   	 public Class getDutyClass() {
+   	 	return UtilitiesAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Utilities Assistant";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/duties/WholeCharModelCurator.java b/Source/mesquite/lib/duties/WholeCharModelCurator.java
new file mode 100644
index 0000000..092a21e
--- /dev/null
+++ b/Source/mesquite/lib/duties/WholeCharModelCurator.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class WholeCharModelCurator extends CharModelCurator  {
+
+   	 public Class getDutyClass() {
+   	 	return WholeCharModelCurator.class;
+   	 }
+}
+
+
diff --git a/Source/mesquite/lib/duties/WindowHolder.java b/Source/mesquite/lib/duties/WindowHolder.java
new file mode 100644
index 0000000..8fbb617
--- /dev/null
+++ b/Source/mesquite/lib/duties/WindowHolder.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.duties;
+
+import java.awt.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/**Serves to hold a window for an employer.*/
+
+public abstract class WindowHolder extends MesquiteModule   {
+	public boolean getSearchableAsModule(){
+		return false;
+	}
+
+   	 public Class getDutyClass() {
+   	 	return WindowHolder.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Window Holder";
+   	 }
+
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+}
+
+
diff --git a/Source/mesquite/lib/simplicity/InterfaceManager.java b/Source/mesquite/lib/simplicity/InterfaceManager.java
new file mode 100644
index 0000000..426de9c
--- /dev/null
+++ b/Source/mesquite/lib/simplicity/InterfaceManager.java
@@ -0,0 +1,431 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.simplicity;
+
+import mesquite.lib.*;
+import java.awt.*;
+import java.util.*;
+
+public class InterfaceManager {
+
+	/*vvvvvvvvvvvvvvvvvvvvv*/
+	public static final boolean enabled = true;
+	public static boolean locked = false;
+	/*^^^^^^^^^^^^^^^^^^^*/
+
+	Parser parser = new Parser();
+
+	/*.................................................................................................................*/
+	//STATIC
+	//modes
+	/*	private static final int ALL = 0;
+	private static final int SIMPLE = 1;
+	private static final int EDITING = 2;
+	 */
+	private static boolean simpleMode = false;
+	private static boolean editingMode = false;
+	public static boolean isEditingMode(){
+		return editingMode;
+	}
+	public static void setEditingMode(boolean ed){
+		editingMode = ed;
+	}
+	public static boolean isSimpleMode(){
+		return simpleMode;
+	}
+	public static void setSimpleMode(boolean simple){
+		if (simpleMode != simple){
+			if (simple)
+				MesquiteTrunk.mesquiteTrunk.logln("Simplified Interface in use.  Some options will be hidden.");
+			else
+				MesquiteTrunk.mesquiteTrunk.logln("Full Interface in use");
+				
+		}
+		simpleMode = simple;
+	}
+	
+	public static String themeName = null;
+	
+	//status
+	public static final int NORMAL = 0;
+	public static final int HIDDEN = 1;
+	public static final int TOBEHIDDEN = 2;
+	public static final int HIDDENCLASS = 3;
+
+	public static Vector allPackages = new Vector();
+	public static SimplicityManagerModule simplicityModule;
+	public static ListableVector hiddenMenuItems;
+	public static ListableVector hiddenPackages;
+	public static ListableVector hiddenTools;
+	public static ListableVector settingsFiles;
+	static {
+		hiddenMenuItems = new ListableVector();
+		hiddenPackages = new ListableVector();
+		hiddenTools = new ListableVector();
+		settingsFiles = new ListableVector();
+	}
+
+	public static void setLock(boolean lock){
+		boolean wasLocked = locked;
+		locked = lock;
+		if (lock)
+			editingMode = false;
+		if (simplicityModule != null)
+			simplicityModule.lock(lock);
+		reset();
+	}
+	/*.................................................................................................................*/
+	public static void report(){
+		if (!enabled)
+			return;
+		MesquiteMessage.println("-----vvv-----");
+		if (isEditingMode())
+			MesquiteMessage.println("EDITING");
+		MesquiteMessage.println("MENU ITEMS");
+		for (int i = 0; i< hiddenMenuItems.size(); i++){
+			MenuVisibility h = (MenuVisibility)hiddenMenuItems.elementAt(i);
+			MesquiteMessage.println("HIDDEN " + h.getName() + " h commandable " + h.commandableClassName + " arguments " + h.arguments + " command " + h.command);
+		}
+		MesquiteMessage.println("...");
+		MesquiteMessage.println("TOOLS");
+		for (int i = 0; i< hiddenTools.size(); i++){
+			MesquiteString h = (MesquiteString)hiddenTools.elementAt(i);
+			MesquiteMessage.println("HIDDEN " + h.getName() + " =  " + h.getValue());
+		}
+		MesquiteMessage.println("...");
+		MesquiteMessage.println("PACKAGES");
+		for (int i = 0; i< hiddenPackages.size(); i++){
+			MesquiteString h = (MesquiteString)hiddenPackages.elementAt(i);
+			MesquiteMessage.println("HIDDEN " + h.getName() + " =  " + h.getValue());
+		}
+		MesquiteMessage.println("-----^^^-----");
+
+	}
+	public static void addPackageToList(String name, String path, String explanation, boolean isHideable, boolean isPackage){
+		allPackages.addElement(new ObjectContainer(name, new String[]{path, explanation, Boolean.toString(isHideable), Boolean.toString(isPackage)}));
+	}
+
+	static void autoSave(){
+		if (simplicityModule != null)
+			simplicityModule.settingsChanged();
+	}
+	public static void addPackageToHidden(String packagePath, boolean save){
+		hiddenPackages.addElement(new MesquiteString(packagePath, packagePath), false);
+		if (save) 
+			autoSave();
+	}
+	public static void removePackageFromHidden(String packagePath, boolean save){
+		int i = hiddenPackages.indexOfByName(packagePath);
+		if (i>=0){
+			hiddenPackages.removeElementAt(i, false);
+			if (save) 
+				autoSave();
+		}
+	}
+
+	public static void addToolToHidden(MesquiteTool tool, boolean save){ //TODO: should be based on more than just name and description!
+		if (onHiddenToolList(tool))
+			return;
+		hiddenTools.addElement(new MesquiteString(tool.getName(), tool.getDescription()), false);
+		if (save) 
+			autoSave();
+	}
+	public static void removeToolFromHidden(String name, String description, boolean save){ //TODO: should be based on more than just name and description!
+		for (int i = 0; i<hiddenTools.size(); i++){
+			MesquiteString vis = (MesquiteString)hiddenTools.elementAt(i);
+			String hiddenName = vis.getName();
+			String hiddenDescr = vis.getValue();
+			if (hiddenName != null && name.equals(hiddenName) && hiddenDescr != null && description.equals(hiddenDescr)){
+				hiddenTools.removeElementAt(i, false);
+				if (save) 
+					autoSave();
+				return;
+			}
+		}
+
+	}
+
+	public static void addMenuItemToHidden(String label, String arguments, MesquiteCommand command, Class dutyClass, boolean save){
+		if (onHiddenMenuItemList(label, arguments, command, dutyClass))
+			return;
+		if (command == null)
+			return;
+		Class commandable = null;
+		Object owner = command.getOwner();
+		if (owner != null)
+			commandable = owner.getClass();
+		String commandableClassName = null;
+		if (commandable != null)
+			commandableClassName = commandable.getName();
+		String dcName = null;
+		if (dutyClass != null)
+			dcName = dutyClass.getName();
+		hiddenMenuItems.addElement(new MenuVisibility(label, arguments, command.getName(), commandableClassName, dcName), false);
+		if (save) 
+			autoSave();
+	}
+
+	public static void removeMenuItemFromHidden(String label, String arguments, MesquiteCommand command, Class dutyClass, boolean save){
+		if (!onHiddenMenuItemList(label, arguments, command, dutyClass))
+			return;
+		if (command == null)
+			return;
+		Class commandable = null;
+		Object owner = command.getOwner();
+		if (owner != null)
+			commandable = owner.getClass();
+		String commandableClassName = null;
+		if (commandable != null)
+			commandableClassName = commandable.getName();
+		String dcName = null;
+		if (dutyClass != null)
+			dcName = dutyClass.getName();
+		int size = hiddenMenuItems.size();
+		for (int i = 0; i<size; i++){
+			MenuVisibility vis = (MenuVisibility)hiddenMenuItems.elementAt(i);
+			if (vis.matchesMenuItem(label, arguments, command.getName(), commandableClassName, dcName)){
+				hiddenMenuItems.removeElement(vis, false);
+				if (save) 
+					autoSave();
+				return;
+			}
+		}
+	}
+
+	static boolean onHiddenMenuItemList(String label, String arguments, MesquiteCommand command, Class dutyClass){
+		if (command == null)
+			return onHiddenMenuItemList(label, arguments, null, null, dutyClass);
+		Object commandable = command.getOwner();
+		Class c = null;
+		if (commandable != null)
+			c = commandable.getClass();
+
+		if (arguments == null)
+			arguments = command.getDefaultArguments();
+		return onHiddenMenuItemList(label, arguments, command.getName(), c, dutyClass);
+	}
+
+	static boolean onHiddenMenuItemList(String label, String arguments, String command, Class commandable, Class dutyClass){
+		String commandableClassName = null;
+		if (commandable != null)
+			commandableClassName = commandable.getName();
+		String dcName = null;
+		if (dutyClass != null)
+			dcName = dutyClass.getName();
+		for (int i = 0; i<hiddenMenuItems.size(); i++){
+			MenuVisibility vis = (MenuVisibility)hiddenMenuItems.elementAt(i);
+			if (vis.matchesMenuItem(label, arguments, command, commandableClassName, dcName)){
+				return true;
+			}
+		}
+		return false;
+	}
+	static int countC = 0;
+	static int countS = 0;
+	public static boolean onHiddenClassList(Class c){
+		if (c == null)
+			return false;
+		String name = c.getName();
+		int size = hiddenPackages.size();
+		for (int i = 0; i<size; i++){
+			MesquiteString vis = (MesquiteString)hiddenPackages.elementAt(i);
+			String hidden = vis.getName();
+			if (hidden != null && name.startsWith(hidden))
+				return true;
+		}
+
+		return false;
+	}
+	public static boolean onHiddenClassList(String pkg){
+		if (StringUtil.blank(pkg))
+			return false;
+		String name = pkg;
+		int size = hiddenPackages.size();
+		for (int i = 0; i<size; i++){
+			MesquiteString vis = (MesquiteString)hiddenPackages.elementAt(i);
+			String hidden = vis.getName();
+			if (hidden != null && name.startsWith(hidden))
+				return true;
+		}
+
+		return false;
+	}
+	public static boolean onHiddenClassListExactly(String pkg){
+		if (StringUtil.blank(pkg))
+			return false;
+		String name = pkg;
+		int size = hiddenPackages.size();
+		for (int i = 0; i<size; i++){
+			MesquiteString vis = (MesquiteString)hiddenPackages.elementAt(i);
+			String hidden = vis.getName();
+			if (hidden != null && name.equals(hidden))
+				return true;
+		}
+
+		return false;
+	}
+	static boolean onHiddenToolList(MesquiteTool tool){
+		if (tool == null)
+			return false;
+		Object initiator = tool.getInitiator();
+		if (initiator != null && onHiddenClassList(initiator.getClass()))
+			return true;
+		String name = tool.getName();
+		String descr = tool.getDescription();
+		return onHiddenToolList(name, descr);
+	}
+	static boolean onHiddenToolList(String name, String descr){
+		for (int i = 0; i<hiddenTools.size(); i++){
+			MesquiteString vis = (MesquiteString)hiddenTools.elementAt(i);
+			String hiddenName = vis.getName();
+			String hiddenDescr = vis.getValue();
+			if (hiddenName != null && name.equals(hiddenName) && hiddenDescr != null && descr.equals(hiddenDescr))
+				return true;
+		}
+
+		return false;
+	}
+	public static int isHiddenTool(MesquiteTool tool){
+		if (!enabled)
+			return NORMAL;
+		if (!isEditingMode() && !isSimpleMode())
+			return NORMAL;
+		if (tool == null)
+			return NORMAL;
+		Object initiator = tool.getInitiator();
+		if (initiator != null && onHiddenClassList(initiator.getClass()))
+			return HIDDENCLASS;
+		String name = tool.getName();
+		String descr = tool.getDescription();
+		boolean toolHidden =  onHiddenToolList(name, descr);
+		if (toolHidden){
+			if (!isEditingMode() && isSimpleMode())
+				return HIDDEN;
+			if (isEditingMode())
+				return TOBEHIDDEN;
+		}
+		return NORMAL;
+	}
+	public static int isHiddenMenuItem(MesquiteMenuItemSpec mmi, String label, String arguments, MesquiteCommand command, Class moduleClass){
+		if (!enabled)
+			return NORMAL;
+		return isHiddenMenuItem(mmi, label, arguments, command, moduleClass, (Class)null);
+	}
+
+	public static int isHiddenMenuItem(MesquiteMenuItemSpec mmi, String label, String arguments, MesquiteCommand command, Class moduleClass, Class dutyClass){
+		if (!enabled)
+			return NORMAL;
+		if (!isEditingMode() && !isSimpleMode())
+			return NORMAL;
+		boolean classHidden = onHiddenClassList(moduleClass);
+		if (!classHidden && !StringUtil.blank(arguments)){
+			classHidden = onHiddenClassList(arguments);
+		}
+		if (!classHidden && mmi != null && mmi.getOwnerClass() != null)
+			classHidden = onHiddenClassList(mmi.getOwnerClass());
+		if (!classHidden && mmi != null && mmi.getCommand() != null && mmi.getCommand().getOwner() != null)
+			classHidden = onHiddenClassList(mmi.getCommand().getOwner().getClass());
+		if (classHidden){
+			if (!isEditingMode() && isSimpleMode())
+				return HIDDEN;
+			if (isEditingMode())
+				return HIDDENCLASS;
+		}
+		boolean onList = onHiddenMenuItemList(label, arguments, command, dutyClass);
+
+		if (onList){ 
+			if (!isEditingMode() && isSimpleMode())
+				return HIDDEN;
+			if (isEditingMode())
+				return TOBEHIDDEN;
+		}
+		return NORMAL;
+	}
+	/*---------------------------*/
+	public static boolean isFilterable(Menu menu){
+		if (menu instanceof MesquiteMenu){
+			return (((MesquiteMenu)menu).isFilterable());
+
+		}
+		return true;
+	}
+	/*---------------------------
+	public static void getLoadSaveMenu(MesquitePopup popup){
+		if (simplicityModule != null){
+			popup.add(new MesquiteMenuItem("Save Current Simplification", null, new MesquiteCommand("saveCurrent", simplicityModule), null));
+			MesquiteSubmenu ms = new MesquiteSubmenu("Load Simplification", popup, null);
+			for (int i = 0; i< settingsFiles.size(); i++){
+				MesquiteString sf = (MesquiteString)settingsFiles.elementAt(i);
+				ms.add(new MesquiteMenuItem(sf.getName(), null, new MesquiteCommand("load", "" + i, simplicityModule), null));
+			}
+			popup.add(ms);
+		}
+	}
+	public static void getSaveRenameDeleteMenuItems(java.awt.Menu menu){
+		if (simplicityModule != null){
+			menu.add(new MesquiteMenuItem("Save Current...", null, new MesquiteCommand("saveCurrent", simplicityModule), null));
+			MesquiteSubmenu ms = new MesquiteSubmenu("Rename...", menu, null);
+			for (int i = 0; i< settingsFiles.size(); i++){
+				StringArray sf = (StringArray)settingsFiles.elementAt(i);
+				ms.add(new MesquiteMenuItem(sf.getName(), null, new MesquiteCommand("rename", "" + i, simplicityModule), null));
+			}
+			menu.add(ms);
+			MesquiteSubmenu ms2 = new MesquiteSubmenu("Delete...", menu, null);
+			for (int i = 0; i< settingsFiles.size(); i++){
+				StringArray sf = (StringArray)settingsFiles.elementAt(i);
+				ms2.add(new MesquiteMenuItem(sf.getName(), null, new MesquiteCommand("delete", "" + i, simplicityModule), null));
+			}
+			menu.add(ms2);
+		}
+	}
+	public static void getLoadMenuItems(java.awt.Menu menu){
+		if (simplicityModule != null){
+			for (int i = 0; i< settingsFiles.size(); i++){
+				StringArray sf = (StringArray)settingsFiles.elementAt(i);
+				menu.add(new MesquiteMenuItem(sf.getName(), null, new MesquiteCommand("load", "" + i, simplicityModule), null));
+			}
+		}
+	}*/
+	public static void addSettingsMenuItems(java.awt.Menu menu, String command, boolean includeDefaults){
+		if (simplicityModule != null){
+			for (int i = 0; i< settingsFiles.size(); i++){
+				StringArray sf = (StringArray)settingsFiles.elementAt(i);
+				if (includeDefaults || sf.getValue(2) == null || !sf.getValue(2).equalsIgnoreCase("default"))
+					menu.add(new MesquiteMenuItem(sf.getName(), null, new MesquiteCommand(command, "" + i, simplicityModule), null));
+			}
+		}
+	}
+	public static boolean settingsWritable(){
+		if (simplicityModule == null)
+			return false;
+		return MesquiteFile.canWrite(simplicityModule.getInstallationSettingsPath());
+	}
+	/*---------------------------*/
+	public static void resetSimplicity(){
+		if (simplicityModule != null)
+			simplicityModule.resetSimplicity();
+
+	}
+
+
+	/*---------------------------*/
+	public static void reset(){
+		MesquiteTrunk.resetAllMenuBars();
+		MesquiteTrunk.resetAllToolPalettes();
+		MesquiteWindow.resetAllSimplicity();
+		//	report();
+	}
+
+}
+
diff --git a/Source/mesquite/lib/simplicity/SimplicityManagerModule.java b/Source/mesquite/lib/simplicity/SimplicityManagerModule.java
new file mode 100644
index 0000000..f7c1be2
--- /dev/null
+++ b/Source/mesquite/lib/simplicity/SimplicityManagerModule.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.simplicity;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.MesquiteInit;
+
+
+/* ======================================================================== */
+/** Does tree consensus .*/
+
+public abstract class SimplicityManagerModule extends MesquiteInit {
+
+   	 public Class getDutyClass() {
+   	 	return SimplicityManagerModule.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Manages interface simplification";
+   	 }
+  	public abstract void init();
+  	public abstract void resetSimplicity();
+  	public abstract void lock(boolean lock);
+  	public abstract void settingsChanged();
+
+ }
+
+
diff --git a/Source/mesquite/lib/simplicity/SimplicityStrip.java b/Source/mesquite/lib/simplicity/SimplicityStrip.java
new file mode 100644
index 0000000..65b2dce
--- /dev/null
+++ b/Source/mesquite/lib/simplicity/SimplicityStrip.java
@@ -0,0 +1,135 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+modified 26 July 01: protected against NullPointerException if null images in paint
+ */
+package mesquite.lib.simplicity;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+/* ======================================================================== */
+
+import mesquite.lib.*;
+
+public class SimplicityStrip extends MousePanel implements Commandable {
+	Font smallFont = new Font("SanSerif", Font.PLAIN, 10);
+	Font boldFont = new Font("SanSerif", Font.BOLD, 10);
+	MesquiteWindow window;
+	MesquitePopup popup=null;
+	Image editing, power, simple;
+	boolean showText = true;
+	public SimplicityStrip(MesquiteWindow window, boolean showText) {
+		super();
+		this.window = window;
+		this.showText = showText;
+		setLayout(null);
+		setFont(smallFont);
+		setBackground(ColorTheme.getInterfaceBackground());
+		setCursor(Cursor.getDefaultCursor());
+		power = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "simplification/power.gif");  
+		simple = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "simplification/simple.gif");  
+		editing = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "notesTool.gif");  
+	}
+
+	public void dispose(){
+		if (popup!=null)
+			remove(popup);
+		super.dispose();
+	}
+	public void setVisible(boolean vis){
+		if (InterfaceManager.locked && vis)
+			return;
+		super.setVisible(vis);
+	}
+	/*.................................................................................................................*/
+	void redoMenu() {
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		popup.removeAll();
+		if (InterfaceManager.isEditingMode()){
+			MesquiteCheckMenuItem editItem=new MesquiteCheckMenuItem("Turn OFF Interface Editing", null, new MesquiteCommand("offEdit", InterfaceManager.simplicityModule), null, null);
+			editItem.set(InterfaceManager.isEditingMode());
+			editItem.setHideable(false);
+			popup.add(editItem);		
+		}
+		else {
+			MesquiteCheckMenuItem fullItem=new MesquiteCheckMenuItem("Full Interface", null, new MesquiteCommand("full", InterfaceManager.simplicityModule), null, null);
+		fullItem.set(!InterfaceManager.isSimpleMode() && !InterfaceManager.isEditingMode());
+		popup.add(fullItem);
+		MesquiteCheckMenuItem simpleItem=new MesquiteCheckMenuItem("Simple Interface", null, new MesquiteCommand("simple", InterfaceManager.simplicityModule), null, null);
+		simpleItem.set(InterfaceManager.isSimpleMode() && !InterfaceManager.isEditingMode());
+		popup.add(simpleItem);
+		}
+		popup.add(new MenuItem("-"));
+		Menu lsm = new Menu("Load Simplification");
+		popup.add(lsm);
+		InterfaceManager.addSettingsMenuItems(lsm, "load", true);
+		MesquiteMenuItem gs;
+		popup.add(gs = new MesquiteMenuItem("Go to Simplification Control Panel...", null, new MesquiteCommand("showWindow", InterfaceManager.simplicityModule), null));
+		gs.setHideable(false);
+
+		/*
+		 * MesquiteCheckMenuItem editItem=new MesquiteCheckMenuItem("Edit Simple Interface", null, new MesquiteCommand("edit", this), null, null);
+		editItem.setState(InterfaceManager.isEditingMode());
+		popup.add(editItem);
+		popup.add(new MenuItem("-"));
+		popup.add(new MesquiteMenuItem("Instructions...", null, new MesquiteCommand("showInstructions", InterfaceManager.simplicityModule), null));
+		popup.add(new MesquiteMenuItem("Show/Hide Packages...", null, new MesquiteCommand("showWindow", InterfaceManager.simplicityModule), null));
+		popup.add(new MenuItem("-"));
+		*/
+		//InterfaceManager.getLoadSaveMenuItems(popup);
+		add(popup);
+	}
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		int left = 18;
+		//g.drawRect(0, 0, getWidth()-1, getHeight()-1);
+		if (!InterfaceManager.isEditingMode() && !InterfaceManager.isSimpleMode() && showText){
+			g.drawImage(power, 0, 0, this);
+				g.drawString("Full Interface", left, 13);
+		}
+		else if (!InterfaceManager.isEditingMode() && InterfaceManager.isSimpleMode()){
+			g.drawImage(simple, 0, 0, this);
+			if (showText)
+				g.drawString("Simple Interface", left, 13);
+		}
+		else if (InterfaceManager.isEditingMode()){
+			g.setColor(Color.cyan);
+			g.fillRect(0, 0, getWidth(), getHeight());
+			g.setColor(Color.black);
+			g.drawImage(editing, 0, 0, this);
+			g.setFont(boldFont);
+			g.drawString("EDITING INTERFACE", left, 13);
+			g.setFont(smallFont);
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	/*.................................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (InterfaceManager.locked)
+			return;
+		if (!InterfaceManager.isEditingMode() && !InterfaceManager.isSimpleMode())
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+			redoMenu();
+		popup.show(this, 0,20);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/lib/system/SystemUtil.java b/Source/mesquite/lib/system/SystemUtil.java
new file mode 100644
index 0000000..d3c3192
--- /dev/null
+++ b/Source/mesquite/lib/system/SystemUtil.java
@@ -0,0 +1,31 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.system;
+
+import mesquite.lib.*;
+import java.awt.*;
+
+
+public class SystemUtil  {
+	public static void setFocusable(Component c, boolean f) {
+		 try {
+			if (c != null )
+			c.setFocusable(f);
+		}
+		catch (Throwable e){
+		}/**/
+	}
+}
+
+
diff --git a/Source/mesquite/lib/table/AutoScrollThread.java b/Source/mesquite/lib/table/AutoScrollThread.java
new file mode 100644
index 0000000..087ea03
--- /dev/null
+++ b/Source/mesquite/lib/table/AutoScrollThread.java
@@ -0,0 +1,95 @@
+package mesquite.lib.table;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+	
+	Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+	The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+	Perhaps with your help we can be more than a few, and make Mesquite better.
+
+	Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+	Mesquite's web site is http://mesquiteproject.org
+
+	This source code and its compiled class files are free and modifiable under the terms of 
+	GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AutoScrollThread extends Thread implements MouseListener {
+	MousePanel panel;
+	MesquiteTable table;
+	boolean abort = false;
+	boolean suppressed = false;
+	
+	public AutoScrollThread (MesquiteTable table, MousePanel panel) {
+		super();
+		setPriority(Thread.MIN_PRIORITY);
+		this.panel = panel;
+		this.table = table;
+		panel.addMouseListener(this);
+
+	}
+	public void abortThread() {
+		abort = true;
+		interrupt();
+	}
+	
+	/*.................................................................................................................*/
+	public boolean canAutoscrollHorizontally() {
+		return panel.canAutoscrollHorizontally();
+	}
+	/*.................................................................................................................*/
+	public boolean canAutoscrollVertically() {
+		return panel.canAutoscrollVertically();
+	}
+
+	public boolean active() {
+		return !abort && !suppressed;
+	}
+	public void start() {
+		abort = false;
+		super.start();
+	}
+	public void run() {
+		while (!abort && !suppressed && !MesquiteTrunk.mesquiteTrunk.mesquiteExiting) {
+			try {
+				Thread.sleep(200);
+				if (MesquiteInteger.isCombinable(panel.getMouseX()) && MesquiteInteger.isCombinable(panel.getMouseY()) )
+					table.checkForAutoScroll(panel, panel.getMouseX(), panel.getMouseY());
+			}
+			catch (InterruptedException e){
+				Thread.currentThread().interrupt();
+			}
+		}
+	}
+	public void mouseClicked(MouseEvent arg0) {
+	}
+	public void mouseEntered(MouseEvent arg0) {
+	}
+	public void mouseExited(MouseEvent arg0) {
+	}
+	public void mousePressed(MouseEvent arg0) {
+		
+	}
+	public void mouseReleased(MouseEvent arg0) {
+		abortThread();
+	}
+	public boolean isSuppressed() {
+		return suppressed;
+	}
+	public void setSuppressed(boolean suppressed) {
+		this.suppressed = suppressed;
+	}
+
+
+}
diff --git a/Source/mesquite/lib/table/CMTable.java b/Source/mesquite/lib/table/CMTable.java
new file mode 100644
index 0000000..6967c2f
--- /dev/null
+++ b/Source/mesquite/lib/table/CMTable.java
@@ -0,0 +1,33 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.table;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/**  An interface used to expose extra methods of character matrix editor table to assistants. */
+public abstract class CMTable extends MesquiteTable {
+	public CMTable (int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int rowNamesWidth, int colorScheme, boolean showRowNumbers, boolean showColumnNumbers) {
+		super(numRowsTotal,  numColumnsTotal,  totalWidth,  totalHeight,  rowNamesWidth,  colorScheme,  showRowNumbers,  showColumnNumbers);
+	}
+	public abstract DataColumnNamesAssistant getDataColumnNamesAssistant(int subRow);
+	public abstract void setLastColumnVisibleLinked(int column);
+	public abstract void setFirstColumnVisibleLinked(int column);
+	public abstract void setLastRowVisibleLinked(int row);
+	public abstract void setFirstRowVisibleLinked(int row);
+	public abstract CellColorer getCellColorer();
+
+
+}
diff --git a/Source/mesquite/lib/table/ColumnNamesPanel.java b/Source/mesquite/lib/table/ColumnNamesPanel.java
new file mode 100644
index 0000000..31719d4
--- /dev/null
+++ b/Source/mesquite/lib/table/ColumnNamesPanel.java
@@ -0,0 +1,933 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+
+import java.io.*;
+
+/* ======================================================================== */
+/** A panel for column headings for use in MesquiteTable*/
+public class ColumnNamesPanel extends EditorPanel implements FocusListener {
+	MesquiteTable table;
+	public int width,  height;
+	int touchX = -1;
+	int touchY = -1;
+	int touchColumn = -1;
+	int shimmerX = -1;
+	int shimmerY = -1;
+
+	int origShimmer = -1;
+	int numRows = 1;
+	int numInfoStrips = 0;
+	int rowH=20;
+	boolean diagonal = false;
+	TextRotator textRotator;
+	Polygon diagonalMask, diagonalColumnMask;
+	int diagonalSize = 1000;
+	int diagonalHeight = 80;
+	double diagonalAngle = -Math.PI/4;
+
+	public ColumnNamesPanel (MesquiteTable table , int w, int h) {
+		super(table);
+		this.table=table;
+		this.width=w;
+		this.height=h;
+		addFocusListener(this);
+		setAutoscrollDirection(AUTOSCROLLHORIZONTAL);
+		textRotator = new TextRotator(1);
+		textRotator.assignBackground(null);
+		//setBackground(ColorDistribution.medium[table.colorScheme]);
+		setBackground(Color.white);
+		setCursor(table.getHandCursor());
+		setSize(w, h);
+	}
+	public void setTableUnitSize (int w, int h) {
+		this.width=w;
+		this.height=h;
+		setSize(width, h);
+	}
+
+	public void setDiagonal(boolean d){
+		diagonal = d;
+		if (d)
+			table.setColumnNamesRowHeight(diagonalHeight);
+		else
+			table.setColumnNamesRowHeight(20);
+
+		if (d) {
+			textRotator.assignBackground(null);
+			resetDiagonalHeight();
+
+		}
+		table.resetComponentSizes();
+	}
+	public void setDiagonalHeight(int dh){
+		 diagonalHeight = dh;
+		 setDiagonal(diagonal);
+	}
+	public int getDiagonalHeight(){
+		return diagonalHeight;
+	}
+	void resetDiagonalMask(int width){
+		int x= (int)(Math.cos(diagonalAngle)*diagonalHeight);
+		int y = (int)(Math.sin(diagonalAngle)*diagonalHeight);
+		double shrunk = (-diagonalHeight)*1.0/y;
+		y =  (int)(shrunk*y);
+		x = (int)(shrunk*x);
+		diagonalMask.xpoints[2] = x + width; //2
+		diagonalMask.xpoints[3] = width; //3
+	}
+	void resetDiagonalHeight(){
+		int x= (int)(Math.cos(diagonalAngle)*diagonalHeight);
+		int y = (int)(Math.sin(diagonalAngle)*diagonalHeight);
+		double shrunk = (-diagonalHeight)*1.0/y;
+		y =  (int)(shrunk*y);
+		x = (int)(shrunk*x);
+		diagonalMask = new Polygon();
+		diagonalMask.npoints=0;
+		diagonalMask.addPoint(0,0); //0
+		diagonalMask.addPoint(x,y); //1
+		diagonalMask.addPoint(x+diagonalSize,y); //2
+		diagonalMask.addPoint(diagonalSize,0); //3
+		diagonalMask.addPoint(0,0);
+		diagonalMask.npoints=5;
+		int xColumn= (int)(Math.cos(diagonalAngle)*diagonalHeight);
+		int yColumn = (int)(Math.sin(diagonalAngle)*diagonalHeight);
+		shrunk = (-diagonalHeight)*1.0/yColumn;
+		yColumn =  (int)(shrunk*yColumn);
+		xColumn = (int)(shrunk*xColumn);
+		diagonalColumnMask = new Polygon();
+		diagonalColumnMask.npoints=0;
+		diagonalColumnMask.addPoint(0,0); //0
+		diagonalColumnMask.addPoint(xColumn,yColumn); //1
+		diagonalColumnMask.addPoint(xColumn,yColumn); //2 x updated for each column
+		diagonalColumnMask.addPoint(0 , 0); //3 x updated for each column
+		diagonalColumnMask.addPoint(0,0); //4
+		diagonalColumnMask.npoints=5;
+	}
+	public boolean isDiagonal(){
+		return diagonal;
+	}
+	/*...............................................................................................................*/
+	/** Gets the height of the columnNames Panel.*/
+	public int calcColumnNamesHeight() {
+		return rowHeight(-1)*getNumRows() + table.getColumnGrabberWidth();
+	}
+	public void setHeight () {
+		this.height=rowHeight(-1)*numRows + table.getColumnGrabberWidth();
+		setSize(width, height);
+	}
+	public int getNumRows () {
+		return numRows;
+	}
+	public int getNumInfoStrips () {
+		return numInfoStrips;
+	}
+	public void setNumInfoStrips (int num) {
+		numInfoStrips = num;
+		numRows = numInfoStrips+1;
+	}
+	public void appendInfoStrip () {
+		numInfoStrips++;
+		numRows++;
+	}
+	public void decrementInfoStrips () {
+		numInfoStrips--;
+		numRows--;
+	}
+
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellH(int x) {
+		if (x<=0)
+			return 50;
+		int cx = 0;
+		for (int column=table.firstColumnVisible; (column<table.numColumnsTotal) && (cx<x); column++) {
+			cx += table.columnWidths[column];
+			if (column>= table.numColumnsTotal)
+				return 50;
+			else if (cx>=x) {
+				int dXR = cx-x; //distance from right edge to 
+				int dXL = x - (cx-table.columnWidths[column]); //distance from left edge to 
+				return dXL*100/(dXR+dXL);
+			}
+		}
+		return 50;
+
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellV(int y) {
+		if (y<=0)
+			return 50;
+		return (y-startOfRow(-1))*100/(rowHeight(-1));
+	}
+	public int startOfRow(int row){
+		if (table.showColumnGrabbers)
+			return (table.getColumnGrabberWidth());
+		else
+			return 0;
+	}
+	public int firstRowVisible(){
+		return -1;
+	}
+	public int numRowsVisible(){
+		return 1;
+	}
+	public int calcRowHeight(int row) {
+		height=rowHeight(-1)*numRows + table.getColumnGrabberWidth();
+		if (table.showColumnGrabbers)
+			return (height -table.getColumnGrabberWidth())/getNumRows();
+		else
+			return (height)/getNumRows();
+	}
+	public int rowHeight(int num) {
+		return rowH;
+	}
+	public void setRowHeight(int h) {
+		rowH = h;
+	}
+	public int nameRowTop() {
+		return (startOfRow(-1));
+	}
+	public int nameRowBottom() {
+		return (startOfRow(-1) + nameRowHeight());
+	}
+	public int extraRowTop(int extraRow) {
+		return (nameRowBottom() + rowHeight(-1)*(extraRow));
+	}
+	public int nameRowHeight() {
+		return (rowHeight(-1));
+	}
+	public int lastRowBottom() {
+		return (startOfRow(-1) + rowHeight(-1)*getNumRows());
+	}
+	public void textReturned(int column, int row, String text){
+		table.returnedColumnNameText(column, text);
+	}
+	public String getText(int column, int row){
+		return table.getColumnNameText(column);
+	}
+	public void deselectCell(int column,int row){
+		table.deselectColumnName(column);
+	}
+	public void redrawCell(int column, int row){
+		Graphics g = getGraphics();
+		if (g!=null) {
+			redrawName(g, column);
+			g.dispose();
+		}
+	}
+	int leftmostNumber = 0;
+	int rightmostNumber = 0;
+	/*...............................................................................................................*/
+	public void redrawName(Graphics g, int column) {
+		int left = table.getFirstColumnVisible();
+		if (column<left) //TODO: should also fail to draw if to big
+			return;  
+		if (column == returningColumn){
+			return; //don't draw if text about to be returned to cell, and will soon be redrawn anyway
+		}
+		int leftSide = startOfColumn(column);
+		if (leftSide>getBounds().width || leftSide+columnWidth(column)<0)
+			return;
+		int topSide = nameRowTop();
+		int botSide = nameRowBottom();
+		Shape clip = g.getClip();
+		if (diagonal){
+			Color cg = g.getColor();
+			//g.setClip(0,0, getWidth(), getHeight());
+			prepareCell(g, column, startOfColumn(column)+1, topSide,columnWidth(column), botSide, table.focusColumn == column, table.isColumnNameSelected(column) || table.isColumnSelected(column), table.getCellDimmed(column, -1), table.isColumnNameEditable(column));
+
+			String name = table.getColumnNameTextForDisplay(column);
+			if (name == null)
+				name = "";
+			int rRight = endOfColumn(column);
+			int rLeft = startOfColumn(column);
+			int offX= (int)(Math.cos(diagonalAngle)*1000);
+			int offY =(int)(Math.sin(diagonalAngle)*1000);
+			if (offY < -diagonalHeight) {
+				double shrunk = (-diagonalHeight)*1.0/offY;
+				offY =  (int)(shrunk*offY);
+				offX = (int)(shrunk*offX);
+			}
+			if( column == 0)
+				leftmostNumber = offX + rLeft;
+			else if (column == table.firstColumnVisible + table.numColumnsVisible-1)
+				rightmostNumber = rRight + offX;
+			textRotator.drawFreeRotatedText(name, g,(rLeft+rRight)/2, botSide-2, diagonalAngle, null, true, null);
+			if (table.frameColumnNames){
+				g.setColor(Color.gray);
+				g.drawLine(rRight,botSide-1,rRight+offX, botSide-1 + offY);
+				if (column == 0)
+					g.drawLine(rLeft,botSide-1,rLeft+offX, botSide-1 + offY);
+			}
+			leftSide += offX;
+			botSide += offY;
+			g.setColor(cg);
+			Font fnt= null;
+			boolean doFocus = table.focusColumn == column && table.boldFont !=null;
+			if (doFocus){
+				fnt = g.getFont();
+				g.setFont(table.boldFont);
+			}
+			
+			if (table.showColumnGrabbers) {
+				if (table.showColumnNumbers) {
+
+					table.drawRowColumnNumber(g,column,false,leftSide+1,0, columnWidth(column)-2, table.getColumnGrabberWidth());
+				}
+				else
+					table.drawRowColumnNumberBox(g,column, false,leftSide+1,0, columnWidth(column)-2, table.getColumnGrabberWidth());
+			}
+			if (doFocus && fnt !=null){
+				g.setFont(fnt);
+			}
+			g.setClip(0,0, getBounds().width, botSide);
+
+
+			g.setColor(Color.black);
+			if (table.getDropDown(column, -1)) {
+				int offset = 0;
+				if (table.showColumnGrabbers)
+					offset = table.getColumnGrabberWidth();
+
+				dropDownTriangle.translate(leftSide - 8 + columnWidth(column),1 + offset);
+				g.setColor(Color.white);
+				g.drawPolygon(dropDownTriangle);
+				g.setColor(Color.black);
+				g.fillPolygon(dropDownTriangle);
+				dropDownTriangle.translate(-(leftSide - 8 + columnWidth(column)),-(1 + offset));
+			}
+//			g.drawLine(0, botSide-1, width, botSide-1);
+			g.setClip(clip);
+		}
+		else {
+			g.setClip(leftSide,0,columnWidth(column), botSide);
+
+			prepareCell(g,column, -1, leftSide+1, 1,columnWidth(column), botSide, table.focusColumn == column, table.isColumnNameSelected(column) || table.isColumnSelected(column), table.getCellDimmed(column, -1), table.isColumnNameEditable(column));
+
+			g.setClip(0,0, getBounds().width, botSide);
+//			g.setClip(0,0, getBounds().width, getBounds().height);
+
+			if (table.frameColumnNames) {
+				Color cg = g.getColor();
+				g.setColor(Color.gray); 
+				g.drawLine(leftSide+columnWidth(column), 0, leftSide+columnWidth(column), botSide);
+				g.setColor(cg);
+			}
+			Font fnt= null;
+			boolean doFocus = table.focusColumn == column && table.boldFont !=null;
+			if (doFocus){
+				fnt = g.getFont();
+				g.setFont(table.boldFont);
+			}
+			if (table.showColumnGrabbers) {
+				if (table.showColumnNumbers) {
+
+					table.drawRowColumnNumber(g,column,false,leftSide+1,0, columnWidth(column)-2, table.getColumnGrabberWidth());
+				}
+				else
+					table.drawRowColumnNumberBox(g,column, false,leftSide+1,0, columnWidth(column)-2, table.getColumnGrabberWidth());
+				g.setClip( leftSide,nameRowTop(), columnWidth(column), botSide);
+				table.drawColumnNameCell(g, leftSide,nameRowTop(), columnWidth(column), nameRowHeight(), column);
+
+			}
+			else {
+				g.setClip( leftSide,nameRowTop(), columnWidth(column), botSide-1);
+				table.drawColumnNameCell(g, leftSide,nameRowTop(), columnWidth(column), nameRowHeight(), column);
+			}
+			if (doFocus && fnt !=null){
+				g.setFont(fnt);
+			}
+			g.setClip(0,0, getBounds().width, botSide);
+
+
+			g.setColor(Color.black);
+			if (table.getDropDown(column, -1)) {
+				int offset = 0;
+				if (table.showColumnGrabbers)
+					offset = table.getColumnGrabberWidth();
+
+				dropDownTriangle.translate(leftSide - 8 + columnWidth(column),1 + offset);
+				g.setColor(Color.white);
+				g.drawPolygon(dropDownTriangle);
+				g.setColor(Color.black);
+				g.fillPolygon(dropDownTriangle);
+				dropDownTriangle.translate(-(leftSide - 8 + columnWidth(column)),-(1 + offset));
+			}
+			g.setClip(clip);
+		g.drawLine(0, botSide-1, width, botSide-1);
+		}
+		g.setClip(null);
+	}
+	public void offEdit(){  
+		super.offEdit();
+		repaint();
+	}
+	protected void prepareCell(Graphics g, int column, int x, int y, int w, int h, boolean focused, boolean selected, boolean dimmed, boolean editable){
+		Color color = table.getColumnNameFillColor(column, fillColor, focused, selected, dimmed, editable);
+		g.setColor(color);
+		fillCell(g, x, y, w, h, selected);
+
+		Color textColor;
+		float[] hsb = new float[3];
+		hsb[0]=hsb[1]=hsb[2]= 1;
+		Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb);
+		textColor = ColorDistribution.getContrasting(selected, color, hsb, Color.white, Color.black);
+		g.setColor(textColor);
+
+	}
+	/*...............................................................................................................*/
+	public void fillCell(Graphics g, int x, int y, int w, int h, boolean selected){
+		if (diagonal){
+			if (diagonalColumnMask == null)
+				return;
+			diagonalColumnMask.translate(x, h);
+			diagonalColumnMask.xpoints[2] += w;
+			diagonalColumnMask.xpoints[3] += w;
+			g.fillPolygon(diagonalColumnMask);
+			if (selected)
+				GraphicsUtil.fillTransparentSelectionPolygon(g,diagonalColumnMask);
+			diagonalColumnMask.xpoints[2] -= w;
+			diagonalColumnMask.xpoints[3] -= w;
+			diagonalColumnMask.translate(-x, -h);
+		}
+		else {
+			g.fillRect(x+1,y+1,w-1,h-1);
+			if (selected)
+				GraphicsUtil.fillTransparentSelectionRectangle(g,x+1,y+1,w-1,h-1);
+		}
+	}
+	/*...............................................................................................................*/
+	public void repaint(){
+		checkEditFieldLocation();
+		super.repaint();
+	}
+
+	/*...............................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+			int lineX = 0;
+			int oldLineX=lineX;
+			int resetWidth = getBounds().width;
+			int resetHeight = getBounds().height;
+			width = resetWidth;//this is here to test if width/height should be reset here
+			height = resetHeight;
+			Shape clip = g.getClip();
+			g.setClip(null);
+			table.resetNumColumnsVisible();
+			for (int c=table.firstColumnVisible; (c<=table.lastColumnVisible+2 && c<table.numColumnsTotal) && (lineX<width); c++) { // or lineX+table.columnWidths[c]
+				redrawName(g, c);
+			}
+			g.setClip(null);
+			if (diagonal) {
+				if (diagonalMask == null)
+					resetDiagonalHeight();
+				int rLeft = startOfColumn(0);
+				int rRight = endOfColumn(table.numColumnsTotal-1);
+				diagonalMask.translate(-rLeft -diagonalSize, height);
+				g.setColor(ColorTheme.getContentBackgroundPale()); //ggray
+				g.fillPolygon(diagonalMask);
+				diagonalMask.translate(rLeft +diagonalSize, -height);
+				diagonalMask.translate(rRight, height);
+				g.fillPolygon(diagonalMask);
+				diagonalMask.translate(-rRight, -height);
+
+				g.fillRect(0, 0, leftmostNumber-1, height - rowHeight(-1));
+
+				g.fillRect(rightmostNumber+1, 0, width, height - rowHeight(-1));
+				g.setColor(ColorTheme.getContentEdgeDark());
+				g.drawLine(0, height-1, width, height-1);
+				g.setClip(clip);
+				return;
+			}
+			g.setClip(0,0, getBounds().width, getBounds().height);
+
+			if ((endOfLastColumn()>=0) && (endOfLastColumn()<table.matrixWidth)) {
+				g.setColor(ColorTheme.getContentBackgroundPale()); //ggray
+				g.fillRect(endOfLastColumn(), 0, getBounds().width, getBounds().height);
+			}
+
+			table.drawColumnNamesPanelExtras(g, 0,nameRowBottom(),endOfLastColumn(), getBounds().height);
+			if (lastRowBottom()<height) {
+				g.setColor(ColorTheme.getContentBackgroundPale()); //ggray
+				g.fillRect(0, lastRowBottom(), endOfLastColumn(), getBounds().height);
+			}
+	//		g.setColor(Color.black);
+			g.setColor(ColorTheme.getContentEdgeDark());  //used to be light
+			if (table.frameColumnNames)
+				g.drawRect(0, 0, width-1, height);
+			g.drawLine(0, height-1, width, height-1);
+			g.setClip(clip);
+			width = resetWidth;
+		}
+		catch (Throwable e){
+			MesquiteMessage.warnProgrammer("Exception or Error in drawing table (CNP); details in Mesquite log file. d " + diagonalMask + " t " + table);
+			MesquiteFile.throwableToLog(this, e);
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*...............................................................................................................*/
+	public void print(Graphics g) {
+		int lineX = 0;
+		int oldLineX=lineX;
+		Shape clip = g.getClip();
+		for (int c=0; (c<table.numColumnsTotal); c++) { 
+			lineX += table.columnWidths[c];
+			g.setColor(Color.black);
+			//g.setClip( oldLineX,0, table.columnWidths[c], height);
+			table.drawColumnNameCell(g, oldLineX,0, table.columnWidths[c], height, c);
+			g.setColor(Color.black);
+
+			oldLineX = lineX;
+		}
+		g.setColor(Color.black);
+		g.setClip(0,0, table.getTotalColumnWidth(), height);
+		g.drawLine(0, height-1,table.getTotalColumnWidth(), height-1);
+		g.setClip(clip);
+	}
+	/*...............................................................................................................*/
+	public void enterPressed(KeyEvent e){
+		if (!getEditing())
+			return;
+		if (table.getCellsEditable())
+			table.editMatrixCell(editField.getColumn(), 0);
+	}
+	/*...............................................................................................................*/
+	public void downArrowPressed(KeyEvent e){
+		if (getEditing())
+			enterPressed(e);
+		//here should move selection into matrix
+	}
+
+
+
+	/*...............................................................................................................*/
+	/*@@@...............................................................................................................*/
+	/** Returns in which column x lies, -1 if to left, -2 if to right. 
+	Differs from findColumn in that*/
+	public int findHalfColumn(int x, int y) {
+		if (x<=0)
+			return -1;
+		if (diagonal){
+			int cx = 0;
+			int left = 0;
+			int right = table.columnWidths[table.firstColumnVisible]/2;
+			if (betweenDiagonal(x, y, -500, left))
+				return -1;
+			if (betweenDiagonal(x, y, left, right))
+				return table.firstColumnVisible-1;
+			int prevWidth = right*2;
+
+			for (int column=table.firstColumnVisible; (column<table.numColumnsTotal) && (cx<x); column++) {
+				cx += table.columnWidths[column]; //centre point
+				left = cx - prevWidth/2;
+				if (column < table.numColumnsTotal-1)
+					prevWidth = table.columnWidths[column+1];
+				else
+					prevWidth = 0;
+				right = cx + prevWidth/2;
+				if (betweenDiagonal(x, y, left-1, right))
+					return column;
+				if (cx>=x)
+					return -3;  //oops, something wrong
+				//if (column+1 == table.numColumnsTotal)
+				//	return -1;
+			}
+			return -2; //past the last column
+		}
+		int cx = 0;
+		for (int column=table.firstColumnVisible; (column<table.numColumnsTotal) && (cx<x); column++) {
+			cx += table.columnWidths[column];
+			if (column>= table.numColumnsTotal)
+				return -1;
+			if (cx>=x)
+				if (x+(table.columnWidths[column]/2) > cx) // then we are in the right half of the column
+					return column;
+				else
+					return column - 1;
+		}
+		return -2; //past the last column
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findColumn(int x, int y) {
+		if (x<=0)
+			return -1;
+
+		int cx = 0;
+		for (int column=table.firstColumnVisible; (column<table.numColumnsTotal) && (cx<x); column++) {
+			if (diagonal){
+				if (betweenDiagonal(x, y, startOfColumn(column), endOfColumn(column)))
+					return column;
+			}
+			else {
+				cx += table.columnWidths[column];
+				if (column>= table.numColumnsTotal)
+					return -1;
+				else if (cx>=x)
+					return column;
+			}
+		}
+		return -2;//past the last column
+	}
+	boolean betweenDiagonal(int x, int y, int left, int right){
+		diagonalMask.translate(right, height);  //first make sure not to follow
+		int righttop = diagonalMask.xpoints[1];
+		if (!diagonalMask.contains(x, y)){
+			diagonalMask.translate(-right, -height);  
+			diagonalMask.translate(left, height);  //now see if in current
+			int lefttop = diagonalMask.xpoints[1];
+			if (diagonalMask.contains(x, y)) {
+				diagonalMask.translate(-left, -height);
+				return true;
+			}
+			diagonalMask.translate(-left, -height);
+			//not in diagonal portion; check if in column number areas
+			if (y<=table.getColumnGrabberWidth() && x>=lefttop && x< righttop)
+				return true;
+		}
+		else
+			diagonalMask.translate(-right, -height);
+		return false;
+	}
+	/*@@@...............................................................................................................*/
+	/** Returns  the column immediately after the boundary between rows nearest to the y value, -1 if to the left of all columns, -2 if after all columns.*/
+	public int findColumnBeforeBetween(int x, int y) {
+		if (x<=0)
+			return -1;
+		int cx = 0;
+		int columnCenterX = 0;
+		int lastColumnCenterX=-1;
+		for (int column=tb.firstColumnVisible; (column<tb.numColumnsTotal); column++) {
+			cx += tb.columnWidths[column];
+			columnCenterX = cx - tb.columnWidths[column]/2;
+			if (column>= tb.numColumnsTotal)
+				return -1;
+			else if (diagonal){
+				if (betweenDiagonal(x, y, lastColumnCenterX, columnCenterX))
+					return column-1;
+			}
+			else if (x>lastColumnCenterX && x<= columnCenterX) {
+				return column-1;
+			} else if (columnCenterX>x)
+				return column;
+			lastColumnCenterX = columnCenterX;
+		}
+		return -2;//past the last column
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which row y lies, -1 if above, -2 if below.*/
+	public int findRow(int x, int y) {
+		return -1;
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which row y lies, -1 if above, -2 if below.*/
+	public int findSubRow(int x, int y) {
+		if (y<=nameRowBottom())
+			return -1;
+		else {
+			return (int)(y-nameRowBottom())/rowHeight(-1);
+		}
+	}
+	/* ............................................................................................................... */
+	/** returns true if x is near the boundary of a column */
+	public boolean nearColumnBoundary(int x, int y) {
+		int columnBoundary = 0;
+		int nearZoneOnRight;
+		int nearZoneOnLeft;
+		// int lastEdge=0;
+		for (int column = tb.firstColumnVisible; (column < tb.numColumnsTotal) && (columnBoundary < x); column++) {
+			if (column==tb.firstColumnVisible)
+				nearZoneOnLeft = 0;
+			else
+				nearZoneOnLeft = getNearZone(tb.columnWidths[column]);
+			if (column==tb.lastColumnVisible)
+				nearZoneOnRight = 0;
+			else
+				nearZoneOnRight = getNearZone(tb.columnWidths[column]);
+
+			columnBoundary += tb.columnWidths[column];
+			int left = columnBoundary-nearZoneOnLeft;
+			int right = columnBoundary+nearZoneOnRight;
+
+			if (diagonal){
+				if (betweenDiagonal(x, y, left, right))
+					return true;
+			}
+			else if (x>columnBoundary-nearZoneOnLeft  && x<columnBoundary+nearZoneOnRight){
+				return true;
+			}
+		}
+		return false;
+
+	}
+	/* ............................................................................................................... */
+	/** returns true if x is near the boundary of a column */
+	public int nearWhichColumnBoundary(int x, int y) {
+		int columnBoundary = 0;
+		int nearZoneOnRight;
+		int nearZoneOnLeft;
+		// int lastEdge=0;
+		for (int column = tb.firstColumnVisible; (column < tb.numColumnsTotal) && (columnBoundary < x); column++) {
+			if (column==tb.firstColumnVisible)
+				nearZoneOnLeft = 0;
+			else
+				nearZoneOnLeft = getNearZone(tb.columnWidths[column]);
+			if (column==tb.lastColumnVisible)
+				nearZoneOnRight = 0;
+			else
+				nearZoneOnRight = getNearZone(tb.columnWidths[column]);
+
+			columnBoundary += tb.columnWidths[column];
+			int left = columnBoundary-nearZoneOnLeft;
+			int right = columnBoundary+nearZoneOnRight;
+
+			if (diagonal){
+				if (betweenDiagonal(x, y, left, right))
+					return column;
+			}
+			else if (x>columnBoundary-nearZoneOnLeft  && x<columnBoundary+nearZoneOnRight){
+				return column;
+			}
+		}
+		return -1;
+
+	}
+	/*...............................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof TableTool))
+			return;
+		table.stopAutoScrollThread();
+		boolean isArrowEquivalent = ((TableTool)tool).isArrowKeyOnColumn(y,table);
+		table.adjustingColumnWidth = false;
+		touchX=-1;
+		touchColumn=-1;
+		/*@@@*/
+		int possibleTouch = findColumn(x, y);
+		int regionInCellH = findRegionInCellH(x);
+		int regionInCellV = findRegionInCellV(y);
+		int subRow = findSubRow(x, y);
+
+		if (tool != null && isArrowEquivalent && isDiagonal() && y> height-3  && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+			touchY=y;
+			shimmerY = touchY;
+			//	table.shimmerHorizontalOn(shimmerY);
+			table.adjustingColumnNamesHeight = true;
+		}
+		else if (possibleTouch<table.numColumnsTotal && possibleTouch>=0) {
+			table.startAutoScrollThread(this);
+			if (subRow>=0) {  // touch on subrow
+				table.subRowTouched(subRow, possibleTouch,regionInCellH, regionInCellV, x, y, modifiers);
+			}
+			else if (table.touchColumnNameEvenIfSelected() && (table.showColumnGrabbers) && (y>=table.getColumnGrabberWidth())) {
+				if (((TableTool)tool).getIsBetweenRowColumnTool())
+					possibleTouch = findColumnBeforeBetween(x, y);
+				table.columnNameTouched(possibleTouch,regionInCellH, regionInCellV, modifiers, clickCount);
+			}
+			else if (tool != null && isArrowEquivalent && table.getUserAdjustColumn()==MesquiteTable.RESIZE && nearColumnBoundary(x, y)  && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				touchX=x;
+				touchColumn=nearWhichColumnBoundary(x, y);
+				shimmerX = touchX;
+				if (diagonal && touchColumn>=0){
+					shimmerX = (startOfColumn(touchColumn) + endOfColumn(touchColumn))/2;
+				}
+				origShimmer = shimmerX;
+				table.shimmerVerticalOn(shimmerX);
+				table.adjustingColumnWidth = true;
+			}
+			/*@@@*/
+			else if (tool != null && isArrowEquivalent && table.getUserMoveColumn() && table.isColumnSelected(possibleTouch) && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				touchX=x;
+				touchColumn=possibleTouch;
+				shimmerX = touchX;
+				if (diagonal && touchColumn>=0){
+					shimmerX = (startOfColumn(touchColumn) + endOfColumn(touchColumn))/2;
+				}
+				origShimmer = shimmerX;
+				table.shimmerVerticalOn(shimmerX);
+			}
+			else if ((table.showColumnGrabbers) && (y<table.getColumnGrabberWidth())) {
+				if (((TableTool)tool).getIsBetweenRowColumnTool() && !isArrowEquivalent)
+					possibleTouch = findColumnBeforeBetween(x, y);
+				table.columnTouched(isArrowEquivalent, possibleTouch,regionInCellH, regionInCellV, modifiers);
+				if (tool != null && isArrowEquivalent && table.getUserMoveColumn() && table.isColumnSelected(possibleTouch) && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+					touchX=x;
+					shimmerX = MesquiteInteger.unassigned;
+					origShimmer = shimmerX;
+					touchColumn=possibleTouch;
+				}
+			}
+			else {
+				if (((TableTool)tool).getIsBetweenRowColumnTool())
+					possibleTouch = findColumnBeforeBetween(x, y);
+				table.columnNameTouched(possibleTouch,regionInCellH, regionInCellV, modifiers, clickCount);
+			}
+		}
+		else if (possibleTouch==-2 && ((TableTool)tool).getWorksBeyondLastColumn())
+			table.columnTouched(isArrowEquivalent, possibleTouch,regionInCellH, regionInCellV, modifiers);
+		else if (((TableTool)tool).getDeselectIfOutsideOfCells()) {
+			table.offAllEdits();
+			table.outOfBoundsTouched(modifiers, clickCount);
+			if (table.anythingSelected()) {
+				table.deselectAllNotify();
+				table.repaintAll();
+			}
+		}
+		else
+			table.outOfBoundsTouched(modifiers, clickCount);
+
+	}
+	/*...............................................................................................................*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (table.adjustingColumnNamesHeight){
+			//table.shimmerHorizontalOff(shimmerY);
+			//table.shimmerHorizontalOn(y);
+			shimmerY=y;
+		}
+		else if (touchColumn>=0) {
+
+			if (table.getUserAdjustColumn()==MesquiteTable.RESIZE) {
+				table.shimmerVerticalOff(shimmerX);
+				if (diagonal){
+					x = (x-touchX) + origShimmer;
+				}
+				table.shimmerVerticalOn(x);
+				shimmerX=x;
+			}
+			else if (table.getUserMoveColumn() && tool != null && ((TableTool)tool).isArrowKeyOnColumn(y,table)) {
+				table.shimmerVerticalOff(shimmerX);
+				if (diagonal){
+					x = (x-touchX) + origShimmer;
+				}
+				table.shimmerVerticalOn(x);
+				shimmerX=x;
+			}
+			table.checkForAutoScroll(this,x,MesquiteInteger.unassigned);
+		}
+	}
+	/*...............................................................................................................*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (table.adjustingColumnNamesHeight){
+			//table.shimmerHorizontalOff(shimmerY);
+			diagonalHeight = diagonalHeight + (y - touchY);
+			if (diagonalHeight < 30)
+				diagonalHeight = 30;
+			table.setColumnNamesRowHeight(diagonalHeight);
+			resetDiagonalHeight();
+			table.adjustingColumnNamesHeight = false;
+			shimmerY=-1;
+			touchY=-1;
+			table.resetComponentSizes();
+			table.repaintAll();
+		}
+		else 	if (touchColumn>=0 && tool != null ) {
+			if (table.getUserAdjustColumn()==MesquiteTable.RESIZE && table.adjustingColumnWidth) {
+				table.shimmerVerticalOff(shimmerX);
+
+				int newColumnWidth = table.columnWidths[touchColumn] + x-touchX;
+				if ((newColumnWidth >= table.getMinColumnWidth()) && (touchX>=0)) {
+					table.setColumnWidth(touchColumn, newColumnWidth);
+					table.columnWidthsAdjusted.setBit(touchColumn);
+					table.repaintAll();
+					//touchX=-1;
+				}
+
+			}
+			else if (table.getUserMoveColumn() && ((TableTool)tool).isArrowKeyOnColumn(y,table)) {
+				table.shimmerVerticalOff(shimmerX);
+				int dropColumn = findHalfColumn(x, y);   //cursor; regionH; clickCount; colour by selected
+				if (dropColumn == -2)
+					dropColumn = table.getNumColumns();
+				if (dropColumn != touchColumn && (dropColumn!=touchColumn-1) && !table.isColumnSelected(dropColumn)) //don't move dropped on column included in selection
+					table.selectedColumnsDropped(dropColumn);
+			}
+			table.adjustingColumnWidth = false;
+		}
+	}
+	/*...............................................................................................................*/
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (!table.editingAnything() && !table.singleTableCellSelected()) 
+			setWindowAnnotation("", null);
+		setCursor(Cursor.getDefaultCursor());
+		int column = findColumn(x, y);
+		table.mouseExitedCell(modifiers, column, -1, -1, -1, tool);
+	}
+	/*...............................................................................................................*/
+	public void setCurrentCursor(int modifiers, int column, int x, int y, MesquiteTool tool) {
+		if (tool == null || !(tool instanceof TableTool))
+			setCursor(getDisabledCursor());
+		else if (isDiagonal() && y> height-3 && ((TableTool)tool).isArrowKeyOnColumn(y,table)  && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.controlKeyDown(modifiers)) 
+			setCursor(table.getNResizeCursor());
+		else if (column<table.numColumnsTotal && column>=0) {   //within bounds of normal columns
+			if (tool != null && ((TableTool)tool).isArrowKeyOnColumn(y,table)) {
+				if (table.getUserAdjustColumn()==MesquiteTable.RESIZE && nearColumnBoundary(x, y)  && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.controlKeyDown(modifiers)) 
+					setCursor(table.getEResizeCursor());
+				else {
+					setCursor(table.getHandCursor());
+					if (!(table.editingAnything() || table.singleTableCellSelected())) {
+						String s = table.getColumnComment(column);
+						if (s!=null)   
+							setWindowAnnotation(s, "Footnote above refers to " + table.getColumnNameText(column));
+						else
+							setWindowAnnotation("", null);
+					}
+				}
+			}
+			else if (((TableTool)tool).getWorksOnColumnNames())
+				setCursor(tool.getCursor());
+			else {
+				setCursor(getDisabledCursor());
+			}
+		}
+		else if (((TableTool)tool).getWorksBeyondLastColumn() && (column==-2))
+			setCursor(tool.getCursor());
+		else {
+			setCursor(getDisabledCursor());
+		}
+
+	}
+	/*...............................................................................................................*/
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		int column = findColumn(x, y);
+		setCurrentCursor(modifiers, column ,  x, y, tool);
+		table.mouseInCell(modifiers, column,-1, -1, findSubRow(x, y),tool);
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		int column = findColumn(x, y);
+		setCurrentCursor(modifiers, column ,  x, y, tool);
+		table.mouseInCell(modifiers, column, -1,-1,  findSubRow(x, y), tool);
+	}
+	public void focusGained(FocusEvent arg0) {
+	}
+	public void focusLost(FocusEvent arg0) {
+		if (table!=null) table.stopAutoScrollThread();
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/lib/table/CornerPanel.java b/Source/mesquite/lib/table/CornerPanel.java
new file mode 100644
index 0000000..32ae2ef
--- /dev/null
+++ b/Source/mesquite/lib/table/CornerPanel.java
@@ -0,0 +1,208 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A panel in upper left corner of MesquiteTable */
+public class CornerPanel extends MesquitePanel {
+	MesquiteTable table;
+	public int width,  height;
+	Polygon dropDownTriangle;
+	public CornerPanel (MesquiteTable table , int w, int h) {
+		super();
+		dropDownTriangle=MesquitePopup.getDropDownTriangle();
+		this.table=table;
+		this.width=w;
+		this.height=h;
+		setBackground(ColorTheme.getContentBackgroundPale());
+	}
+	public void setTableUnitSize (int w, int h) {
+		this.width=w;
+		this.height=h;
+	}
+	public void deselectCell(int column,int row){
+	}
+	public void redrawCell(int column, int row){
+		Graphics g = getGraphics();
+		if (g!=null) {
+			redrawName(g);
+			g.dispose();
+		}
+	}
+	public void redrawName(Graphics g){
+		if (g ==null)
+			return;
+		int w = getBounds().width;
+		int h = getBounds().height;
+		if (table.cornerIsHeading){
+			if (table.getCellDimmed(-1, -1))
+				g.setColor(Color.lightGray);
+			else
+				g.setColor(ColorTheme.getContentBackgroundPale());
+			g.fillRect(0, 0,w, h);
+			g.setColor(Color.black);
+			//if (table.showColumnGrabbers) 
+			//	g.fillRect(0,0, w, table.getGrabberWidth());
+		}
+	/*
+		g.setColor(Color.lightGray); 
+		Polygon temp = new Polygon(new int[]{w-2, w+1, w+1, w-2}, new int[]{0, 0, h+1, h-2}, 4);
+		g.fillPolygon(temp);
+		g.setColor(Color.gray); 
+		g.drawPolygon(temp);
+	*/
+		//g.fillRect(w-3, 0, 4, h+1);
+		g.setColor(Color.gray);
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		g.drawString(table.getUpperCornerText(), 4, fm.getAscent()+fm.getDescent() + 2);
+		if (table.getCellDimmed(-1, -1))
+			g.setColor(Color.gray);
+		else
+			g.setColor(Color.black);
+		
+		
+		g.drawString(table.getCornerText(), 4, h-MesquiteString.riseOffset);
+		g.setColor(Color.black);
+		if (table.getDropDown(-1, -1) && dropDownTriangle != null) {
+			dropDownTriangle.translate(w-12,4);
+			g.setColor(Color.white);
+			g.drawPolygon(dropDownTriangle);
+			g.setColor(Color.black);
+			g.fillPolygon(dropDownTriangle);
+			dropDownTriangle.translate(12-w,-4);
+		}
+	}
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (!table.useString(-1, -1))
+			table.drawCornerCell(g, 0,0,getBounds().width, getBounds().height);  //added Apr 02
+		else
+			redrawName(g);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void print(Graphics g) {
+		redrawName(g);
+	}
+	/*...............................................................................................................*/
+	int touchX = -1;
+	int lastX = -1;
+	/*...............................................................................................................*/
+   	public void shimmerOff(int x) {
+		if (x<=getBounds().width) {
+			table.shimmerVerticalOff(this,x);
+			table.shimmerVerticalOff(table.rowNames,x);
+		}
+		else {
+			table.shimmerVerticalOff(table.columnNames,x-touchX);
+			table.shimmerVerticalOff(table.matrix,x-touchX);
+		}
+   	 }
+	/*...............................................................................................................*/
+   	public void shimmerOn(int x) {
+		if (x<=getBounds().width) {
+			table.shimmerVerticalOn(this,x);
+			table.shimmerVerticalOn(table.rowNames,x);
+		}
+		else {
+			table.shimmerVerticalOn(table.columnNames,x-touchX);
+			table.shimmerVerticalOn(table.matrix,x-touchX);
+		}
+   	 }
+	/*...............................................................................................................*/
+	public boolean isArrowEquivalent(MesquiteTool tool) {
+		if (tool==null)
+			return false;
+		return (tool.isArrowTool() ||  !((TableTool)tool).getWorksOnCornerPanel());
+	}
+	/*...............................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (tool == null || !isArrowEquivalent(tool))
+			return;
+		touchX=-1;
+		if (x>getBounds().width-8) {
+			touchX=x;
+			lastX = x;
+			shimmerOn(x);
+		}
+		else {
+			table.cornerTouched(x,y, modifiers);
+		}
+	}
+	/*...............................................................................................................*/
+   	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (tool == null || !isArrowEquivalent(tool))
+			return;
+		if (touchX >=0) {
+			shimmerOff(lastX);
+			shimmerOn(x);
+			lastX=x;
+		}
+   	 }
+	/*...............................................................................................................*/
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (tool == null || !isArrowEquivalent(tool))
+			return;
+		if (touchX >=0) {
+			shimmerOff(lastX);
+			int newColumnWidth = getBounds().width + x-touchX-table.rowGrabberWidth;
+			if (newColumnWidth > 16) {
+				table.rowNamesWidthAdjusted = true;
+				table.setRowNamesWidth(newColumnWidth);
+				table.resetTableSize(false);
+				table.repaintAll();
+			}
+		}
+   	 }
+	/*...............................................................................................................*/
+	public void setCurrentCursor(int modifiers, int x, int y, MesquiteTool tool) {
+		if (tool == null || !(tool instanceof TableTool))
+				setCursor(getDisabledCursor());
+		else if (tool.isArrowTool() || !((TableTool)tool).getWorksOnCornerPanel()) {
+			if (x>getBounds().width-8) 
+				setCursor(table.getEResizeCursor());
+			else
+				setCursor(table.getHandCursor());
+		}
+		else 	if (((TableTool)tool).getWorksOnCornerPanel()) 
+			setCursor(tool.getCursor());
+		else
+			setCursor(getDisabledCursor());
+	}
+   	/*...............................................................................................................*/
+   	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		setCursor(Cursor.getDefaultCursor());
+		table.mouseExitedCell(modifiers, -1, -1, -1,-1,  tool);
+  	}
+	/*...............................................................................................................*/
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (tool == null)
+			return;
+		setCurrentCursor(modifiers, x, y, tool);
+		table.mouseInCell(modifiers, -1, -1,-1, -1, tool);
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (tool == null)
+			return;
+		setCurrentCursor(modifiers, x, y, tool);
+		table.mouseInCell(modifiers, -1, -1, -1,-1,  tool);
+	}
+}
+
diff --git a/Source/mesquite/lib/table/EditorPanel.java b/Source/mesquite/lib/table/EditorPanel.java
new file mode 100644
index 0000000..30d8fe1
--- /dev/null
+++ b/Source/mesquite/lib/table/EditorPanel.java
@@ -0,0 +1,553 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** A superclass for the panels that make up a MesquiteTable.  Has an editable text field that can be repositioned over a cell.*/
+public abstract class EditorPanel extends MesquitePanel {
+	MesquiteTable tb;
+	protected EditorTextField editField;
+	protected Color fillColor= null;
+	int editColumn=-1;
+	int editRow = -1;
+	protected int returningColumn = -2;
+	protected int returningRow  = -2;
+	public static final int BEYONDMATRIX = -2;
+	Polygon dropDownTriangle;
+
+	public EditorPanel (MesquiteTable table) {
+		super();
+		dropDownTriangle=MesquitePopup.getDropDownTriangle();
+		tb = table;
+		editField = new EditorTextField(this, 0, 0);
+		add(editField);
+		editField.setVisible(false);
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+	}
+	public abstract void textReturned(int column, int row, String text);
+	public abstract String getText(int column, int row);
+	public void setFillColor(Color toFill){
+		fillColor = toFill;
+	}
+	public int startOfColumn(int column) {
+		return tb.startOfColumn(column);
+	}
+	/*...............................................................................................................*/
+	public void drawBetweenSelection(Graphics g){
+	}
+	public int endOfColumn(int column) {
+		if (column<tb.firstColumnVisible)
+			return -1;
+		else if (column>tb.firstColumnVisible + tb.numColumnsTotal || column>=tb.numColumnsTotal)
+			return -1;
+		else
+			return startOfColumn(column)+tb.columnWidths[column];
+	}
+	public int endOfLastColumn() {
+		int lastColumn = tb.getLastColumn();
+		if (lastColumn<0)
+			return 0;
+		else
+			return startOfColumn(lastColumn)+tb.columnWidths[lastColumn];
+	}
+	public int startOfRow(int row) {
+		if (row<tb.firstRowVisible)
+			return -1;
+		else if (row>tb.firstRowVisible + tb.numRowsTotal)
+			return -1;
+		else {
+			int lineX = 0;
+			//	if (tb.showRowGrabbers)
+			//		lineX = tb.getRowGrabberWidth();
+			for (int c=tb.firstRowVisible; (c<row && c< tb.rowHeights.length); c++) {
+				lineX += tb.rowHeights[c];
+			}
+			return lineX;
+		}
+	}
+	public int leftEdgeOfRow(int row) {
+		return startOfColumn(tb.firstColumnVisible);
+	}
+	public int rightEdgeOfRow(int row) {
+		return endOfColumn(tb.getLastColumnVisible());
+	}
+	public int endOfRow(int row) {
+		if (row<tb.firstRowVisible)
+			return -1;
+		else if (row>tb.firstRowVisible + tb.numRowsTotal)
+			return -1;
+		else
+			return startOfRow(row)+tb.rowHeights[row];
+	}
+	public int endOfLastRow() {
+		int lastRow = tb.getLastRow();
+		if (lastRow<0)
+			return 0;
+		else
+			return startOfRow(lastRow)+tb.rowHeights[lastRow];
+	}
+
+	public abstract int findRegionInCellH(int x);
+	public abstract int findRegionInCellV(int y);
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public abstract int findColumn(int x, int y);
+	/** returns in which row y lies, -1 if above, -2 if below.*/
+	public abstract int findRow(int x, int y);
+
+	/*@@@...............................................................................................................*/
+	/** Returns  the column immediately after the boundary between rows nearest to the y value, -1 if to the left of all columns, -2 if after all columns.*/
+	public int findColumnBeforeBetween(int x, int y) {
+		if (x<=0)
+			return -1;
+		int cx = 0;
+		int columnCenterX = 0;
+		int lastColumnCenterX=-1;
+		for (int column=tb.firstColumnVisible; (column<tb.numColumnsTotal); column++) {
+			cx += tb.columnWidths[column];
+			columnCenterX = cx - tb.columnWidths[column]/2;
+			if (column>= tb.numColumnsTotal)
+				return -1;
+			else if (x>lastColumnCenterX && x<= columnCenterX) {
+				return column-1;
+			} else if (columnCenterX>x)
+				return column;
+			lastColumnCenterX = columnCenterX;
+		}
+		return -2;//past the last column
+	}
+	/*@@@...............................................................................................................*/
+	/** Returns  the row immediately after the boundary between rows nearest to the y value, -1 if above all rows, -2 if below all rows.*/
+	public int findRowBeforeBetween(int x, int y) {
+		if (y<0)
+			return -1;
+		int ry = 0;
+		int rowCenterY = 0;
+		int lastRowCenterY = -1;
+		for (int row=tb.firstRowVisible; (row<tb.numRowsTotal); row++) {
+			ry += tb.rowHeights[row];
+			rowCenterY = ry-tb.rowHeights[row]/2;
+			if (row>= tb.numRowsTotal) {
+				return -2;
+			}
+			else if (y>lastRowCenterY && y<= rowCenterY) {
+				return row-1;
+			} else if (rowCenterY>y)
+				return row;
+			lastRowCenterY = rowCenterY;
+		}
+
+		return -2;//past the last row
+	}
+	/* ............................................................................................................... */
+	protected int getNearZone(int rowColSize) {
+		if (rowColSize<=2)
+			return 0;
+		else if (rowColSize<=4)
+			return 1;
+		else if (rowColSize<=10)
+			return 2;
+		return 3;
+	}
+	/* ............................................................................................................... */
+	/** returns true if x is near the boundary of a column */
+	public boolean nearColumnBoundary(int x, int y) {
+		int columnBoundary = 0;
+		int nearZoneOnRight;
+		int nearZoneOnLeft;
+		// int lastEdge=0;
+		for (int column = tb.firstColumnVisible; (column < tb.numColumnsTotal) && (columnBoundary < x); column++) {
+			if (column==tb.firstColumnVisible)
+				nearZoneOnLeft = 0;
+			else
+				nearZoneOnLeft = getNearZone(tb.columnWidths[column]);
+			if (column==tb.lastColumnVisible)
+				nearZoneOnRight = 0;
+			else
+				nearZoneOnRight = getNearZone(tb.columnWidths[column]);
+
+			columnBoundary += tb.columnWidths[column];
+			if (x>columnBoundary-nearZoneOnLeft  && x<columnBoundary+nearZoneOnRight){
+				return true;
+			}
+		}
+		return false;
+
+	}
+	/* ............................................................................................................... */
+	/** returns true if x is near the boundary of a column */
+	public int nearWhichColumnBoundary(int x, int y) {
+		int columnBoundary = 0;
+		int nearZoneOnRight;
+		int nearZoneOnLeft;
+		// int lastEdge=0;
+		for (int column = tb.firstColumnVisible; (column < tb.numColumnsTotal) && (columnBoundary < x); column++) {
+			if (column==tb.firstColumnVisible)
+				nearZoneOnLeft = 0;
+			else
+				nearZoneOnLeft = getNearZone(tb.columnWidths[column]);
+			if (column==tb.lastColumnVisible)
+				nearZoneOnRight = 0;
+			else
+				nearZoneOnRight = getNearZone(tb.columnWidths[column]);
+
+			columnBoundary += tb.columnWidths[column];
+			if (x>columnBoundary-nearZoneOnLeft  && x<columnBoundary+nearZoneOnRight){
+				return column;
+			}
+		}
+		return -1;
+
+	}
+
+	/* ............................................................................................................... */
+	/** returns true if y is near the boundary of a row */
+	public boolean nearRowBoundary(int x, int y) {
+		int rowBoundary = 0;
+		int nearZoneOnBottom;
+		int nearZoneOnTop;
+		// int lastEdge=0;
+		for (int row = tb.firstRowVisible; (row < tb.numRowsTotal); row++) {
+			if (row==tb.firstRowVisible)
+				nearZoneOnTop = 0;
+			else
+				nearZoneOnTop = getNearZone(tb.rowHeights[row]);
+			if (row==tb.lastRowVisible)
+				nearZoneOnBottom = 0;
+			else
+				nearZoneOnBottom = getNearZone(tb.rowHeights[row]);
+
+			rowBoundary += tb.rowHeights[row];
+			if (y>rowBoundary-nearZoneOnTop  && y<rowBoundary+nearZoneOnBottom)
+				return true;
+		}
+		return false;
+
+	}
+	public MesquiteTable getTable(){
+		return tb;
+	}
+	public int firstColumnVisible(){
+		if (tb == null)
+			return 0;
+		return tb.firstColumnVisible;
+	}
+	public int firstRowVisible(){
+		if (tb == null)
+			return 0;
+		return tb.firstRowVisible;
+	}
+	public int numColumnsVisible(){
+		if (tb == null)
+			return 0;
+		return tb.numColumnsTotal;
+	}
+	public int numRowsVisible(){
+		if (tb == null)
+			return 0;
+		return tb.numRowsTotal;
+	}
+	public int columnWidth(int column) {
+		if (tb == null)
+			return 0;
+		if (!tb.columnLegal(column))
+			return -1;
+		if (column>= tb.columnWidths.length)
+			return -1;
+		return tb.columnWidths[column];
+	}
+	public int rowHeight(int row) {
+		if (tb == null)
+			return 0;
+		if (!tb.rowLegal(row))
+			return -1;
+		if (row>= tb.rowHeights.length)
+			return -1;
+		return tb.rowHeights[row];
+	}
+
+	public boolean getEditing(){
+		return editField.getEditing();
+	}
+	public boolean getEditingAllSelected(){
+		if (!editField.getEditing())
+			return false;
+		return (editField.getSelectionStart()==0 && editField.getSelectionEnd()== editField.getText().length());
+
+	}
+	public EditorTextField getEditField(){
+		return editField;
+	}
+	public boolean checkEditFieldLocation(){
+		if (editField.getEditing()) {
+			int column = editField.getColumn();
+			int row = editField.getRow();
+			if (column>=firstColumnVisible() && column<firstColumnVisible()+numColumnsVisible() && (row == -1 || (row>=firstRowVisible() && row<firstRowVisible()+numRowsVisible())) ) {
+				boolean ok = checkBounds();
+				if (!editField.isVisible())
+					editField.setVisible(true);
+				return ok;
+			}
+			else {
+				editField.setVisible(false);
+			}
+		}
+		else {
+			if (editField.isVisible())
+				editField.setVisible(false);
+		}
+		return true;
+	}
+	public void offEditFocusLost(){  
+		int c = editColumn;
+		int r = editRow;
+		editField.offEdit();
+		editField.setVisible(false);
+		editField.setText(null);
+		editField.setBounds(0, 0, 0, 0);
+		editField.setColumnRow(-2, -2);
+		editColumn=-2;
+		editRow = -2;
+		tb.setFocusedCell(c, r);
+	}
+	public void offEditDontRecord(){  //1. 12
+		editField.offEditDontRecord();
+		editField.setVisible(false);
+		editField.setText(null);
+		editField.setBounds(0, 0, 0, 0);
+		editField.setColumnRow(-2, -2);
+		editColumn=-2;
+		editRow = -2;
+	}
+	public void offEdit(){  
+		editField.offEdit();
+		editField.setVisible(false);
+		editField.setText(null);
+		editField.setBounds(0, 0, 0, 0);
+		editField.setColumnRow(-2, -2);
+		editColumn=-2;
+		editRow = -2;
+	}
+
+	public void recordEdit(){  
+		editField.recordEdit();
+	}
+	public abstract void deselectCell(int column,int row);
+
+	public void aboutToReturnText(int column, int row){
+		returningColumn = column;
+		returningRow  = row;
+		deselectCell(column, row);
+	}
+	public void resetUndoAfterLeavingEditorCell(int column, int row){  
+	}
+
+	public void editCell(int column, int row){  
+		tb.offOtherEdits(this);
+		if (editField.getEditing() && (editField.getColumn()!=column || editField.getRow() != row)) {
+			resetUndoAfterLeavingEditorCell(column, row);
+			recordEdit(); //used to be offEdit
+		}
+		tb.selectCell(column, row);
+		editColumn=column;
+		editRow = row;
+		String t = getText(column, row);
+		if (t==null)
+			t="";
+		editField.setEditing(true);
+		//last
+		editField.setColumnRow(column, row);
+		editField.setText(t);
+		checkBounds();
+		editField.selectAll();
+		editField.setVisible(true);
+		editField.requestFocus();
+		tb.setFocusedCell(column, row);
+	}
+	public abstract void redrawCell(int column, int row);
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Indicates editing is complete and text is being passed back", "[column] [row] [tokenized text]", commandName, "returnText")) {
+			int column = MesquiteInteger.fromFirstToken(arguments, pos);
+			int row = MesquiteInteger.fromString(arguments, pos);
+			String s  = ParseUtil.getToken(arguments, pos);
+			returningColumn = -2;
+			returningRow  = -2;
+			if (s !=null)
+				textReturned(column, row, s);
+			redrawCell(column, row);
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*...............................................................................................................*/
+	protected void prepareCell(Graphics g, int column, int row, int x, int y, int w, int h, boolean focused, boolean selected, boolean dimmed, boolean editable){
+		Color color = tb.getBackgroundColor(column, row, selected);
+		if (color==null) {
+			if (selected) {
+				color = Color.white;
+			}
+			else if (focused)
+				color = Color.lightGray;
+			else if (fillColor!=null)
+				color = fillColor;
+			else if (dimmed)
+				color = Color.lightGray;
+			else if (editable)
+				color = Color.white;
+			else
+				color = ColorDistribution.uneditable;
+		}
+		//		color = Color.lightGray;  //
+		g.setColor(color);
+		g.fillRect(x,y,w,h);
+		if (selected)
+			GraphicsUtil.fillTransparentSelectionRectangle(g,x,y,w,h);
+
+		Color textColor;
+		if (selected)
+			textColor = Color.white;
+		else if (dimmed)
+			textColor = Color.gray;
+		else
+			textColor = Color.black;
+		g.setColor(textColor);
+	}
+	public void enterPressed(KeyEvent e){
+		if (!getEditing()) {
+			return;
+		}
+
+		int r = editField.getRow();
+		if (r+1<tb.numRowsTotal) {
+			e.consume();
+			editCell(editField.getColumn(), r+1);
+		}
+		else if (r+1 == tb.numRowsTotal){
+			e.consume();
+			offEdit();
+			tb.clickOutside();
+		}
+		else
+			e.consume();
+
+	}
+
+	public void tabPressed(KeyEvent e){
+		if (!getEditing())
+			return;
+		int c = editField.getColumn();
+		
+		if (c+1<tb.numColumnsTotal) {
+			e.consume();
+			editCell(c+1, editField.getRow());
+		}
+		else if (c+1==tb.numColumnsTotal) {
+			e.consume();
+			offEdit();
+			tb.clickOutside();
+		}
+		else {
+			e.consume();
+		}
+
+	}
+	public void downArrowPressed(KeyEvent e){
+		if (getEditing())
+			enterPressed(e);
+	}
+
+	public void upArrowPressed(KeyEvent e){ //
+		if (!getEditing())
+			return;
+		int r = editField.getRow();
+		if (r-1>=0) {
+			e.consume();
+			editCell(editField.getColumn(), r-1);
+		}
+		else if (r-1<0) {
+			e.consume();
+			offEdit();
+			tb.clickOutside();
+		}
+		else
+			e.consume();
+	}
+
+	public void rightArrowPressed(KeyEvent e){
+		if (getEditingAllSelected()) {
+			tabPressed(e);
+		}
+	}
+	public void leftArrowPressed(KeyEvent e){
+		if (!getEditing() || !getEditingAllSelected()) {
+			//if cell selected, move selection
+			return;
+		}
+		int c = editField.getColumn();
+		if (c-1>=0) {
+			e.consume();
+			editCell(c-1, editField.getRow());
+		}
+		else if (c-1<0) {
+			e.consume();
+			offEdit();
+			tb.clickOutside();
+		}
+		else {
+			e.consume();
+		}
+	}
+	public boolean checkBounds(){
+		int w;
+		int left=startOfColumn(editColumn);
+		int top = startOfRow(editRow);
+		if (columnWidth(editColumn)+1>editField.getMinimalWidth()) 
+			w = columnWidth(editColumn)+1;
+		else
+			w = editField.getMinimalWidth();
+		if ((editColumn==-1) && tb.showRowGrabbers)
+			left = tb.getRowGrabberWidth();
+		if ((editRow==-1) && tb.showColumnGrabbers)
+			top = tb.getColumnGrabberWidth();
+		Rectangle current = editField.getBounds();
+
+		int buffer = 3;
+		left = left-buffer;
+		w = w+buffer*2;
+		if (current.width != w || (current.height < rowHeight(editRow)+1 || current.height > rowHeight(editRow)+2)){ //1. 06 permit to be one off (strange behaviour in java 1.4)
+			editField.setBounds(left, top, w, rowHeight(editRow)+1);
+			return false;
+		}
+		else if (current.x != left || current.y != top){
+			editField.setLocation(left, top);
+			return false;
+		}
+		return true;
+	}
+	//this is done to limit flickering & because of apparent bugs in Windows java VM (1.3)
+	public void update(Graphics g){
+		paint(g);
+	}
+}
+
+
+
diff --git a/Source/mesquite/lib/table/EditorTextField.java b/Source/mesquite/lib/table/EditorTextField.java
new file mode 100644
index 0000000..6d5cb26
--- /dev/null
+++ b/Source/mesquite/lib/table/EditorTextField.java
@@ -0,0 +1,283 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+
+import java.util.*;
+
+
+/* ======================================================================== */
+/** A text field that is moved from place to place as the text is edited in a panel of a MesquiteTable.*/
+public class EditorTextField extends TextField  {
+	int row, column;
+	EditorPanel panel;
+	boolean editing;
+	boolean forgetFocusGained=false;
+	boolean suppressFocusLost = false;
+	FontMetrics fontMetrics;
+	boolean wasEditingListener=false;
+	String previousText = null;
+	boolean allowReturn = true;
+	MesquiteCommand textReturnedCommand;
+	KListener kListener;
+	String originalText = null;
+	Undoer originalUndoer = null;
+	Listened listened = new Listened();
+	boolean somethingTyped = false;
+	
+	public EditorTextField (EditorPanel panel, int column, int row) {
+		super();
+		try {
+			setFocusTraversalKeysEnabled(false);
+		}
+		catch (Error e){
+		}
+		this.panel = panel;
+		this.column=column;
+		this.row = row;
+		editing = false;
+		textReturnedCommand = MesquiteModule.makeCommand("returnText", panel);
+		textReturnedCommand.setSuppressLogging(true);
+		setBackground(ColorDistribution.veryLightGray);
+	//	setBackground(ColorDistribution.cyan);
+		kListener = new KListener(panel.getMesquiteWindow(), this);
+		addKeyListener(kListener);
+		addFocusListener(new FListener());
+	}
+	
+	public Listened getListened() {
+		return listened;
+	}
+	public void setEditing(boolean editing) {
+		selStart = -1;
+		selEnd = -1;
+		this.editing = editing;
+		wasEditingListener = true;
+		kListener.setWindow(panel.getMesquiteWindow());
+	}
+	public boolean getEditing() {
+		return editing;
+	}
+	public void setFont(Font f){
+		super.setFont(f);
+		Graphics g = getGraphics();
+		if (g==null)
+			return;
+		fontMetrics = g.getFontMetrics(getFont());
+		g.dispose();
+	}
+	
+
+private int ccc = 0;
+	public void setText(String s){
+		if (s == null)
+			super.setText("");
+		else {
+			super.setText(s);
+			originalText = s;
+		}
+		allowReturn = true;
+	}
+	
+	public String getOriginalText(){
+		return originalText;
+	}
+	public int getMinimalWidth(){
+		if (fontMetrics==null) {
+			Graphics g=getGraphics();
+			if (g==null)
+				return 0;
+			fontMetrics = g.getFontMetrics(getFont());
+			g.dispose();
+			if (fontMetrics==null)
+				return 0;
+		}
+		return fontMetrics.stringWidth(getText())+MesquiteModule.textEdgeCompensationWidth;
+	}
+	public void dontRestoreIfFocusGained() {
+		forgetFocusGained = true;
+	}
+	public void setSuppressFocusLost(boolean b) {
+		suppressFocusLost = b;
+	}
+	public void resetLocation(){
+		if (panel == null || panel.getTable() == null || panel.getWindow() == null)
+			return;
+		if (somethingTyped && originalUndoer != null){ 
+			//this is a bit of a kludge, given that it dives into the table to find a CharacterData
+			if (panel.getTable().getColumnAssociable() != null && panel.getTable().getColumnAssociable() instanceof mesquite.lib.characters.CharacterData)
+				panel.getWindow().setUndoer(new UndoInstructions(UndoInstructions.SINGLEDATACELL, column, row, new MesquiteString(getOriginalText()),new MesquiteString(getText()), (mesquite.lib.characters.CharacterData)panel.getTable().getColumnAssociable(), panel.getTable()));
+			else
+				panel.getWindow().setUndoer((Undoer)null);
+				
+		}
+		somethingTyped = false;
+		//setUndoer
+		originalUndoer = null;
+	}
+	public void setColumnRow (int column, int row) {
+		if (this.column!=column || this.row!=row){
+			previousText = null;
+			resetLocation();
+		}
+		this.column=column;
+		this.row = row;
+	}
+	public void paint(Graphics g){ //^^^
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		super.paint(g);
+		if (fontMetrics==null) {
+			fontMetrics = g.getFontMetrics(getFont());
+			panel.checkBounds();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	
+	public int getColumn() {
+		return column;
+	}
+	public int getRow() {
+		return row;
+	}
+	int selStart=0;
+	int selEnd=0;
+	public void offEditDontRecord() {  //1. 12
+		if (editing) {
+			selStart = -1;
+			selEnd = -1;
+			allowReturn = false;
+			setEditing(false);
+		}
+	}
+	public void offEdit() {
+		if (editing) {
+			boolean refreshPanel = false;
+			if (column>=-1 && row >=-1 && allowReturn){
+				panel.aboutToReturnText(column, row);
+				resetLocation();
+				textReturnedCommand.doItMainThread(Integer.toString(column) + " " + row + "  " + ParseUtil.tokenize(getText()), null, this);
+				refreshPanel = true;
+			}
+			else 
+				resetLocation();
+
+			selStart = -1;
+			selEnd = -1;
+			allowReturn = false;
+			setEditing(false);
+			if (refreshPanel)
+				panel.checkEditFieldLocation();
+		}
+	}
+	public void recordEdit() {
+		if (editing) {
+			if (column>=-1 && row >=-1 && allowReturn){
+				panel.aboutToReturnText(column, row);
+				resetLocation();
+				textReturnedCommand.doItMainThread(Integer.toString(column) + " " + row + "  " + ParseUtil.tokenize(getText()), null, this);
+			}
+			else
+				resetLocation();
+			allowReturn = false;
+		}
+	}
+	class FListener extends FocusAdapter {
+		public void focusLost(FocusEvent e){
+			
+			if (editing && !suppressFocusLost) {
+				wasEditingListener = editing;
+				selStart = getSelectionStart();
+				selEnd = getSelectionEnd();
+				previousText = getText();
+				panel.recordEdit();
+			}
+		}
+		public void focusGained(FocusEvent e){
+			if (wasEditingListener && !forgetFocusGained) {
+				if (previousText !=null)
+					setText(previousText);
+				previousText = null;
+				try{
+					if (selStart<0 || selEnd <0) {
+						selectAll();
+						selStart = getSelectionStart();
+						selEnd = getSelectionEnd();
+					}
+					else {
+						setSelectionStart(selStart);
+						setSelectionEnd(selEnd);
+					}
+				}
+				catch (NullPointerException npe){
+				}
+				setEditing(true);
+			}
+		}
+
+	}
+	class KListener extends KeyAdapter {
+		MesquiteWindow window = null;
+		EditorTextField textField;
+		public KListener (MesquiteWindow window, EditorTextField textField){
+			super();
+			this.window=window;
+			this.textField = textField;
+		}
+		public void setWindow(MesquiteWindow window) {
+			this.window = window;
+		}
+		public void keyPressed(KeyEvent e){
+			//Event queue
+		if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+				panel.enterPressed(e);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_TAB) {
+				panel.tabPressed(e);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_RIGHT){
+				if (getSelectionStart()==0 && getSelectionEnd()== getText().length())
+					panel.rightArrowPressed(e);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_LEFT) {
+				if (getSelectionStart()==0 && getSelectionEnd()== getText().length())
+					panel.leftArrowPressed(e);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_UP)
+				panel.upArrowPressed(e);
+			else if (e.getKeyCode()== KeyEvent.VK_DOWN)
+				panel.downArrowPressed(e);
+			else 	if (MesquiteEvent.commandOrControlKeyDown(MesquiteEvent.getModifiers(e))) {
+				if (window!=null & somethingTyped) {
+					window.setNewUndoState(new MesquiteString(textField.getText()));
+				}
+			}
+			else {  //not commandORControl down
+				somethingTyped=true;
+				if (window!=null)
+					if (textField.getOriginalText()!=null) {
+						originalUndoer = new UndoInstructions(UndoInstructions.EDITTEXTFIELD, new MesquiteString(textField.getOriginalText()),new MesquiteString(""), textField);
+						window.setUndoer(originalUndoer);
+					}
+			}
+
+		}
+	}
+}
+
diff --git a/Source/mesquite/lib/table/MatrixPanel.java b/Source/mesquite/lib/table/MatrixPanel.java
new file mode 100644
index 0000000..370214f
--- /dev/null
+++ b/Source/mesquite/lib/table/MatrixPanel.java
@@ -0,0 +1,742 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.FileInterpreter;
+
+import java.io.*;
+
+
+/* ======================================================================== */
+/** A panel for the main body of cells (i.e., excluding the column and row headings) of a MesquiteTable */
+public class MatrixPanel extends EditorPanel implements FocusListener {
+	MesquiteTable table;
+	public int width,  height;
+	int hFloat = -1;
+	int vFloat = -1;
+
+	public MatrixPanel (MesquiteTable table , int w, int h) {
+		super(table);
+		this.table=table;
+		this.width=w;
+		this.height=h;
+		addFocusListener(this);
+		//setBackground(ColorDistribution.medium[table.colorScheme]);
+		setBackground(Color.white);
+	}
+	/*...............................................................................................................*/
+	public void setTableUnitSize (int w, int h) {
+		this.width=w;
+		this.height=h;
+	}
+
+
+	/*...............................................................................................................*/
+	public String getText(int column, int row){
+		return table.getMatrixText(column, row);
+	}
+	public void deselectCell(int column,int row){
+		table.deselectCell(column, row);
+	}
+	/*...............................................................................................................*/
+	static long redrawCells = 0;
+	static long paints = 0;
+	/*...............................................................................................................*/
+	public void redrawCell(int column, int row){
+		Graphics g = getGraphics();
+		if (g!=null) {
+			redrawCell(g, column, row);
+			g.dispose();
+		}
+	}
+	/*...............................................................................................................*/
+	/*MesquiteTimer timer1 = new MesquiteTimer();
+MesquiteTimer timer2 = new MesquiteTimer();
+MesquiteTimer timer3 = new MesquiteTimer();
+MesquiteTimer timer4 = new MesquiteTimer();
+MesquiteTimer timer5 = new MesquiteTimer();
+MesquiteTimer timer6 = new MesquiteTimer();
+
+timer1.start(); //600
+
+timer1.end();
+timer2.start(); //648
+
+timer2.end();
+timer3.start(); //277
+
+timer3.end();
+timer4.start();  //57
+
+timer4.end();
+timer5.start(); //500
+
+timer5.end();
+timer6.start(); //270
+
+timer6.end();
+.println("timers 1 " + timer1.getAccumulatedTime() + " timer2 " + timer2.getAccumulatedTime()  + " timer3 " + timer3.getAccumulatedTime() + " timer4 " + timer4.getAccumulatedTime() + " timer5 " + timer5.getAccumulatedTime() + " timer6 " + timer6.getAccumulatedTime());
+	 */
+	public void redrawCell(Graphics g, int column, int row) {
+		redrawCellOffset(g, column, row, 0, 0);
+	}
+
+	public void redrawCellBlock(Graphics g, int columnStart, int columnEnd, int rowStart, int rowEnd) {
+		for (int i = columnStart; i<=columnEnd; i++)
+			for (int j=rowStart; j<rowEnd; j++)
+				redrawCellOffset(g, i, j, 0, 0);
+	}
+
+	public void redrawRow(Graphics g, int row) {
+		int lineX = 0;
+		int top = table.getTopOfRow(row);
+		for (int i = table.getFirstColumnVisible(); i<=table.getLastColumnVisible(); i++) 
+			if (i>=0 && i<table.getNumColumns()) {
+				lineX += table.columnWidths[i];
+				redrawCellOffset(g, i, row, 0, 0);
+				g.setColor(Color.gray);
+
+				g.drawLine(lineX,top, lineX, top+rowHeight(row));//matrixHeight + columnNamesRowHeight
+				g.drawLine(lineX,top+rowHeight(row), lineX+columnWidth(i), top+rowHeight(row));//matrixHeight + columnNamesRowHeight
+			}
+	}
+
+
+	//draws cell appearing at column, row, but with contents for cell column+offsetColumn, row+offsetRow.  Used with non-zero offsets for quick draw during manual sequence alignment
+	public void redrawCellOffset(Graphics g, int column, int row, int offsetColumn, int offsetRow) {
+		redrawCells++;
+		int left = table.getFirstColumnVisible();
+		int top = table.getFirstRowVisible();
+		if (column<left || row<top)  
+			return;  
+		if (column== returningColumn && row == returningRow){
+			//MesquiteTrunk.mesquiteTrunk.logln("WARNING: error drawing matrix (returning; MatrixPanel) " + column + "  " + row);
+			return; //don't draw if text about to be returned to cell, and will soon be redrawn anyway
+		}
+		if (column>= table.columnWidths.length || row >= table.rowHeights.length)
+			return;
+		int leftSide = startOfColumn(column);
+		int topSide = startOfRow(row);
+		if (leftSide>getBounds().width || leftSide+columnWidth(column)<0) {
+			return;
+		}
+		if (topSide>getBounds().height || topSide+rowHeight(row)<0) {
+			return;
+		}
+		Shape clip = null;
+		if (!table.useQuickMode()) {
+			clip = g.getClip();
+			g.setClip(leftSide,topSide,table.columnWidths[column], table.rowHeights[row]);
+		}
+		if ((offsetColumn!=0 || offsetRow !=0)){
+			if (!table.columnLegal(column+offsetColumn) || !table.rowLegal(row+offsetRow))
+				prepareCell(g, column, row, leftSide+1,topSide+1,table.columnWidths[column]-1, table.rowHeights[row]-1, false, false, true, true);
+			else {
+				boolean selected = table.isCellSelected(column+offsetColumn, row+offsetRow) || table.isRowSelected(row+offsetRow)|| table.isColumnSelected(column+offsetColumn);
+
+				if (!table.useString(column,row)) {
+					table.drawMatrixCell(g, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column+offsetColumn, row+offsetRow, selected);
+				}
+				else  {
+					String supplied = table.getMatrixTextForDisplay(column+offsetColumn,row+offsetRow);
+					prepareCell(g,column, row, leftSide+1,topSide+1,table.columnWidths[column]-1, table.rowHeights[row]-1, false, selected, table.getCellDimmed(column+offsetColumn, row+offsetRow), table.isCellEditable(column+offsetColumn, row+offsetRow));
+					table.drawMatrixCellString(g, null, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column+offsetColumn, row+offsetRow, supplied);
+				}
+//				table.drawMatrixCellExtras(g, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column+offsetColumn, row+offsetRow);
+			}
+		}
+		else {
+			boolean selected = table.isCellSelected(column, row) || table.isRowSelected(row)|| table.isColumnSelected(column);
+
+			if (!table.useString(column,row)) {
+				table.drawMatrixCell(g, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column, row, selected);
+			}
+			else  {
+				String supplied = table.getMatrixTextForDisplay(column,row);
+				prepareCell(g,column, row,  leftSide+1,topSide+1,table.columnWidths[column]-1, table.rowHeights[row]-1, false, selected, table.getCellDimmed(column, row), table.isCellEditable(column, row));
+				table.drawMatrixCellString(g, null, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column, row, supplied);
+			}
+//			table.drawMatrixCellExtras(g, leftSide,topSide,table.columnWidths[column], table.rowHeights[row], column, row);
+
+		}
+
+		if (table.getDropDown(column, row)) {
+			dropDownTriangle.translate(leftSide+1,topSide + 1);
+			g.setColor(Color.white);
+			g.drawPolygon(dropDownTriangle);
+			g.setColor(Color.black);
+			g.fillPolygon(dropDownTriangle);
+			dropDownTriangle.translate(-(leftSide+1),-(topSide + 1));
+		}
+		if (!table.useQuickMode() && clip !=null) {
+			g.setClip(clip);
+		}
+	}
+	/*...............................................................................................................*/
+	public void blankCell(int column, int row) {
+		Graphics g = getGraphics();
+		if (g==null)
+			return;
+		blankCell(column, row, g);
+		g.dispose();
+	}
+	/*...............................................................................................................*/
+	public void blankCell(int column, int row, Graphics g) {
+		int left = table.getFirstColumnVisible();
+		int top = table.getFirstRowVisible();
+
+		if (column<left || row<top)  
+			return;  
+		int leftSide = startOfColumn(column);
+		int topSide = startOfRow(row);
+		if (leftSide>getBounds().width || leftSide+columnWidth(column)<0)
+			return;
+		if (topSide>getBounds().height || topSide+rowHeight(row)<0)
+			return;
+		Shape clip = g.getClip();
+		g.setClip(leftSide,topSide,table.columnWidths[column], table.rowHeights[row]);
+
+		prepareCell(g, column, row, leftSide+1,topSide+1,table.columnWidths[column]-1, table.rowHeights[row]-1, false, table.isCellSelected(column, row) || table.isRowSelected(row)|| table.isColumnSelected(column), false, table.isCellEditable(column, row));
+
+		g.setClip(clip);
+	}
+
+	/*...............................................................................................................*/
+	public void textReturned(int column, int row, String text){
+		table.returnedMatrixText(column, row, text);
+	}
+	/*...............................................................................................................*/
+	public void print(Graphics g) {
+		int lineY;
+		int lineX;
+		if (table.frameMatrixCells) {
+			int columnHeight = table.getTotalRowHeight();
+			g.setColor(Color.gray);
+			lineX = 0;
+			for (int c=0; c<table.numColumnsTotal; c++) {
+				lineX += table.columnWidths[c];
+				g.drawLine(lineX, 0, lineX, columnHeight);//matrixHeight + columnNamesRowHeight
+			}
+			int rowLength = table.getTotalColumnWidth();
+
+			lineY = 0;
+			for (int r=0; (r<table.numRowsTotal); r++) {
+				lineY += table.rowHeights[r];
+				g.drawLine(0, lineY, rowLength, lineY);//rowNamesWidth+matrixWidth
+			}
+		}
+
+		g.setColor(Color.black);
+		lineY = 0;
+		int oldLineY=lineY;
+
+		int numCells = 0;//���
+
+		Shape clip = g.getClip();
+		for (int r=0; (r<table.numRowsTotal); r++) {
+			lineY += table.rowHeights[r];
+
+			lineX = 0;
+			int oldLineX=lineX;
+			for (int c=0; (c<table.numColumnsTotal); c++) {
+				numCells++;
+				lineX += table.columnWidths[c];
+				g.setClip(oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r]);
+				String supplied = table.getMatrixTextForDisplay(c,r);
+				Color bc = table.getBackgroundColor(c, r, false);
+				if (bc != null)
+					g.setColor(bc);
+				else if (fillColor!=null)
+					g.setColor(fillColor);
+				else if (table.isCellEditable(c, r))
+					g.setColor(Color.white);
+				else
+					g.setColor(ColorDistribution.uneditable);
+				g.fillRect(oldLineX+1,oldLineY+1,table.columnWidths[c]-1, table.rowHeights[r]-1);
+				g.setColor(Color.black);
+				if (!table.useString(c,r))
+					table.drawMatrixCell(g, oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r], c, r, false);
+				else 
+					table.drawMatrixCellString(g, null, oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r], c, r, supplied);
+				oldLineX = lineX;
+			}
+			oldLineY=lineY;
+		}
+		g.setClip(clip);
+	}
+
+	/*...............................................................................................................*/
+	public void drawBetweenSelection(Graphics g){
+		if (table.selectedBetweenColumns()) {
+			int x = table.getColumnX(table.getStartBetweenColumnSelection());
+			int top = table.getRowY(table.getStartBetweenRowSelection()-1);
+			int bottom = table.getRowY(table.getEndBetweenRowSelection());
+			g.setColor(Color.blue);
+			g.fillRect(x-MesquiteTable.BETWEENLINEWIDTH/2,top,MesquiteTable.BETWEENLINEWIDTH,bottom-top);
+			g.setColor(Color.yellow);
+			g.drawRect(x-MesquiteTable.BETWEENLINEWIDTH/2,top,MesquiteTable.BETWEENLINEWIDTH,bottom-top);
+		}
+		else if (table.selectedBetweenRows()) {
+			int left = table.getColumnX(table.getStartBetweenColumnSelection()-1);
+			int right = table.getColumnX(table.getEndBetweenColumnSelection());
+			int top = table.getRowY(table.getStartBetweenRowSelection());
+			g.setColor(Color.blue);
+			g.fillRect(left,top-MesquiteTable.BETWEENLINEWIDTH/2, right-left,MesquiteTable.BETWEENLINEWIDTH);
+			g.setColor(Color.yellow);
+			g.drawRect(left,top-MesquiteTable.BETWEENLINEWIDTH/2, right-left,MesquiteTable.BETWEENLINEWIDTH);
+		}
+
+	}
+	/*...............................................................................................................*/
+	public void update(Graphics g){
+		paint(g);
+		hFloat = -1;
+		vFloat = -1;
+	}
+	public void repaint(){
+		checkEditFieldLocation();
+		super.repaint();
+	}
+
+	/*...............................................................................................................*/
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+
+		try {
+			paints++;
+			int lineY;
+			int lineX;
+			width = getBounds().width;//this is here to test if width/height should be reset here
+			height = getBounds().height;
+			if (table.useQuickMode()){
+				g.setColor(Color.white);
+				g.fillRect(0,0,width, height);
+			}
+			
+
+			if (table.frameMatrixCells) {
+				int columnHeight = 0;
+				for (int r=table.firstRowVisible; (r<table.numRowsTotal)  && r< table.rowHeights.length&& (columnHeight<height); r++) {
+					columnHeight += table.rowHeights[r];
+				}
+				if  (columnHeight>height)
+					columnHeight=height;
+				if (table.paleGrid)
+					g.setColor(ColorDistribution.veryLightGray);
+				else
+					g.setColor(Color.gray);
+				lineX = 0;
+				for (int c=table.firstColumnVisible; (c<table.numColumnsTotal) && (lineX<width) && c< table.columnWidths.length; c++) {
+					lineX += table.columnWidths[c];
+					g.drawLine(lineX, 0, lineX, columnHeight);//matrixHeight + columnNamesRowHeight
+				}
+				int rowLength;
+				if  (lineX>width)
+					rowLength=width;
+				else
+					rowLength = lineX;
+
+				lineY = 0;
+				for (int r=table.firstRowVisible; (r<table.numRowsTotal)  && r< table.rowHeights.length && (lineY<height); r++) {
+					lineY += table.rowHeights[r];
+					g.drawLine(0, lineY, rowLength, lineY);//rowNamesWidth+matrixWidth
+				}
+			}
+			g.setColor(Color.black);
+			lineY = 0;
+			int oldLineY=lineY;
+			int resetWidth = getBounds().width;
+			int resetHeight = getBounds().height;
+
+			int numCells = 0;//���
+			
+			Font oldFont = g.getFont();
+			FontMetrics fm = g.getFontMetrics(g.getFont());
+			Font plainFont = new Font(oldFont.getName(), Font.PLAIN, oldFont.getSize());
+			Font boldFont = new Font(oldFont.getName(), Font.BOLD, oldFont.getSize());
+			if (table.boldCellText && boldFont!=null)
+				g.setFont(boldFont);
+			else
+				g.setFont(plainFont);
+				
+			Shape clip = g.getClip();
+			table.resetNumColumnsVisible();
+			table.resetNumRowsVisible();
+			for (int r=table.firstRowVisible; r<=table.lastRowVisible+1 && (r<table.numRowsTotal)   && r< table.rowHeights.length && (lineY<resetHeight); r++) {
+				lineY += table.rowHeights[r];
+
+				lineX = 0;
+				int oldLineX=lineX;
+				for (int c=table.firstColumnVisible; c<=table.lastColumnVisible+1 && (c<table.numColumnsTotal) && c< table.columnWidths.length && (lineX<resetWidth); c++) {
+					numCells++;
+					lineX += table.columnWidths[c];
+					if (c!= returningColumn || r != returningRow){ //don't draw if text about to be returned to cell, and will soon be redrawn anyway
+						if (!table.useQuickMode())
+							g.setClip(oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r]);
+						boolean selected = table.isCellSelected(c, r) || table.isRowSelected(r)|| table.isColumnSelected(c);
+						if (!table.useString(c,r)) {
+							table.drawMatrixCell(g, oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r], c, r, selected);
+						}
+						else {
+							String supplied = table.getMatrixTextForDisplay(c,r);
+							Color color = table.getBackgroundColor(c, r, selected);
+							if (color == null){
+								if (selected) {
+									color = Color.white;
+								}
+								else if (fillColor!=null)
+									color = fillColor;
+								else if (table.isCellEditable(c, r)){
+									if (!table.useQuickMode())
+										color = Color.white;
+								}
+								else
+									color = ColorDistribution.uneditable;
+							}
+							if (color !=null){
+								g.setColor(color);
+								g.fillRect(oldLineX+1,oldLineY+1,table.columnWidths[c]-1, table.rowHeights[r]-1);
+							}
+							if (selected)
+								GraphicsUtil.fillTransparentSelectionRectangle(g,oldLineX+1,oldLineY+1,table.columnWidths[c]-1, table.rowHeights[r]-1);
+							Color textColor = table.getTextColor(c, r, selected);
+							if (textColor==null)
+								if (selected)
+									textColor = Color.white;
+								else if (table.getCellDimmed(c,r))
+									textColor = Color.gray;
+								else
+									textColor = Color.black;
+							g.setColor(textColor);
+							table.drawMatrixCellString(g, fm, oldLineX,oldLineY,table.columnWidths[c], table.rowHeights[r], c, r, supplied);
+						}
+					}
+					oldLineX = lineX;
+				}
+				oldLineY=lineY;
+			}
+			if (table.getBetweenSelected()) {
+				drawBetweenSelection(g);
+			}
+			if ((endOfLastColumn()>=0) && (endOfLastColumn()<table.matrixWidth)) {
+				g.setClip(endOfLastColumn()+1, 0, table.matrixWidth-1, table.matrixHeight-1);
+				g.setColor(ColorTheme.getContentBackgroundPale());   //ggray
+				g.fillRect(endOfLastColumn()+1, 0, table.matrixWidth-1, table.matrixHeight-1);
+			}
+			if ((endOfLastRow()>=0) && (endOfLastRow()<table.matrixHeight)) {
+				g.setClip(0, endOfLastRow()+1, table.matrixWidth-1, table.matrixHeight-1);
+				g.setColor(ColorTheme.getContentBackgroundPale());//ggray
+				g.fillRect(0, endOfLastRow()+1, table.matrixWidth-1, table.matrixHeight-1);
+			}
+			g.setClip(clip);
+//			g.setColor(Color.black);
+			g.setColor(ColorTheme.getContentEdgeDark());  //used to be light
+
+			g.drawRect(0, 0, resetWidth-1, resetHeight-1);
+		}
+		catch (ArrayIndexOutOfBoundsException e){
+		}
+		catch (Throwable e){
+			//MesquiteMessage.warnProgrammer("Exception or Error in drawing table (Matrix Panel); details in Mesquite log file");
+			MesquiteFile.throwableToLog(this, e);
+			repaint();
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void upArrowPressed(KeyEvent e){ //
+		if (getEditing() && (editField.getRow() == 0) && table.isColumnNameEditable(editField.getColumn()))
+			table.editColumnNameCell(editField.getColumn());
+		else
+			super.upArrowPressed(e);
+	}
+
+	public void leftArrowPressed(KeyEvent e){
+		if ((getEditingAllSelected()) && (editField.getColumn() == 0) && table.isRowNameEditable(editField.getRow()))
+			table.editRowNameCell(editField.getRow());
+		else
+			super.leftArrowPressed(e);
+	}
+
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findColumn(int x, int y) {
+		if (x<=0)
+			return -1;
+		int cx = 0;
+		for (int column=table.firstColumnVisible; (column<table.numColumnsTotal) && (cx<x); column++) {
+			cx += table.columnWidths[column];
+			if (column>= table.numColumnsTotal)
+				return -1;
+			else if (cx>=x)
+				return column;
+		}
+		return BEYONDMATRIX;//past the last column
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which row y lies, -1 if above, -2 if below.*/
+	public int findRow(int x, int y) {
+		if (y<=0)
+			return -1;
+		int ry = 0;
+		for (int row=table.firstRowVisible; (row<table.numRowsTotal) && (ry<y); row++) {
+			ry += table.rowHeights[row];
+			if (row>= table.numRowsTotal)
+				return -1;
+			else if (ry>=y)
+				return row;
+		}
+
+		return BEYONDMATRIX;//past the last row
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellH(int x) {
+		int count = 0;
+		if (x<=0)
+			return 50;  //column<=table.lastColumnVisible &&
+		int cx = 0;
+		for (int column=table.firstColumnVisible;  (column<table.numColumnsTotal) && (cx<x); column++) {
+			count++;
+			cx += table.columnWidths[column];
+			if (column>= table.numColumnsTotal) {
+				return 50;
+			}
+			else if (cx>=x) {
+				int dXR = cx-x; //distance from right edge to 
+				int dXL = x - (cx-table.columnWidths[column]); //distance from left edge to 
+				return dXL*100/(dXR+dXL);
+			}
+		}
+		return 50;
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellV(int y) {
+		if (y<=0)
+			return 50;
+
+		int ry = 0;
+		for (int row=table.firstRowVisible;  (row<table.numRowsTotal) && (ry<y); row++) {
+			ry += table.rowHeights[row];
+			if (row>= table.numRowsTotal)
+				return 50;
+			else if (ry>=y) {
+				int dYB = ry-y; //distance from bottom edge to 
+				int dYU = y - (ry-table.rowHeights[row]); //distance from left edge to 
+				return dYU*100/(dYB+dYU);
+			}
+		}
+		return 50;
+	}
+	int previousRowDragged = -1;
+	int firstRowTouched = -1;
+	boolean mouseDownInField = true;
+	boolean mouseDownInPanel = false;
+	/*...............................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (!(tool instanceof TableTool))
+			return;
+		/*MesquiteWindow window = MesquiteWindow.windowOfItem(this);
+		if (window != null)
+			window.toFront();*/
+		int column = findColumn(x,y);
+		int row = findRow(x, y);
+		firstRowTouched = row;
+
+
+		mouseDownInField = false;
+		mouseDownInPanel = true;
+
+		int regionInCellH = findRegionInCellH(x);
+		int regionInCellV = findRegionInCellV(y);
+
+		//((TableTool)tool).getWorksOnColumnNames();
+
+		if (column>-1 && row > -1 && column<table.numColumnsTotal && row<table.numRowsTotal) {
+			table.startAutoScrollThread(this);
+			if (((TableTool)tool).getIsBetweenRowColumnTool()) {
+				column = findColumnBeforeBetween(x, y);
+				row = findRowBeforeBetween(x, y);  //this was findColumnBeforeBetween
+			}
+			table.cellTouched(column, row, regionInCellH, regionInCellV,modifiers, clickCount);
+			if (((TableTool)tool).getEmphasizeRowsOnMouseDown()){
+				table.emphasizeRow(-1,firstRowTouched, -1, false, Color.blue);
+			}
+			mouseDownInField = true;
+//			if (((TableTool)tool).getEmphasizeRowsOnMouseDrag()){
+//			table.emphasizeRow(-1,row, -1, false, Color.red);
+//			}
+		}
+		else if (column==-2 && ((TableTool)tool).getWorksBeyondLastColumn())
+			table.cellTouched(column, row, regionInCellH, regionInCellV,modifiers, clickCount);
+		else if (row==-2 && ((TableTool)tool).getWorksBeyondLastRow())
+			table.cellTouched(column, row, regionInCellH, regionInCellV,modifiers, clickCount);
+		else {
+			table.outOfBoundsTouched(modifiers, clickCount);
+			setWindowAnnotation("", null);
+		}
+
+
+	}
+	int counter = 0;
+	/*_________________________________________________*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!mouseDownInPanel)
+			return;
+		try {
+		int column = findColumn(x, y);
+		int row = findRow(x, y);
+		int regionInCellH = findRegionInCellH(x);
+		int regionInCellV =  findRegionInCellV(y);
+
+		if (column>-1 && row > -1 && column<table.numColumnsTotal && row<table.numRowsTotal) {
+			table.checkForAutoScroll(this,x,y);
+			table.cellDrag(column, row, regionInCellH,  regionInCellV,modifiers);
+			if (((TableTool)tool).getEmphasizeRowsOnMouseDrag()){
+				table.emphasizeRow(previousRowDragged,row, firstRowTouched, false, Color.blue);
+				previousRowDragged = row;
+			}
+
+		} else if (column>=table.numColumnsTotal || row>=table.numRowsTotal)
+			table.checkForAutoScroll(this,x,y);
+		}
+		catch (Exception e){
+		}
+		catch (Throwable e){
+		}
+		}
+	/*_________________________________________________*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (!(tool instanceof TableTool))
+			return;
+		try {
+		table.stopAutoScrollThread();
+		int column = findColumn(x, y);
+		int row = findRow(x, y);
+		int regionInCellH = findRegionInCellH(x);
+		int regionInCellV =  findRegionInCellV(y);
+
+		if (((TableTool)tool).getEmphasizeRowsOnMouseDrag()){
+			table.redrawFullRow(previousRowDragged);
+			table.redrawFullRow(firstRowTouched);
+		}
+
+		if (((TableTool)tool).getEmphasizeRowsOnMouseDown()){
+			table.redrawFullRow(firstRowTouched);
+		}
+
+		if (((TableTool)tool).acceptsOutsideDrops() || (column>-1 && row > -1 && column<table.numColumnsTotal && row<table.numRowsTotal)) {
+			if (((TableTool)tool).getIsBetweenRowColumnTool())
+				column = findColumnBeforeBetween(x, y);
+			table.cellDropped(column, row, regionInCellH, regionInCellV,modifiers);
+		}
+		else if (column==-2 && ((TableTool)tool).getWorksBeyondLastColumn())
+			table.cellDropped(column, row, regionInCellH, regionInCellV,modifiers);
+		else if (row==-2 && ((TableTool)tool).getWorksBeyondLastRow())
+			table.cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+		else if (!mouseDownInField && ((TableTool)tool).getDeselectIfOutsideOfCells()) {
+
+			table.offAllEdits();
+			table.clickOutside();
+			if (table.anythingSelected()) {
+				table.deselectAllNotify();
+				table.repaintAll();
+			}
+		}
+		mouseDownInField = false;
+		mouseDownInPanel = false;
+	}
+	catch (Exception e){
+	}
+	catch (Throwable e){
+	}
+	}
+	/*...............................................................................................................*/
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+		table.stopAutoScrollThread();
+		if (!table.editingAnything() && !table.singleTableCellSelected()) 
+			setWindowAnnotation("", null);
+		setCursor(Cursor.getDefaultCursor());
+		int column = findColumn(x, y);
+		int row = findRow(x, y);
+		table.mouseExitedCell(modifiers, column, -1, row, -1, tool);
+	}
+	catch (Exception e){
+	}
+	catch (Throwable e){
+	}		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*...............................................................................................................*/
+	public void setCurrentCursor(int modifiers, int column, int row, MesquiteTool tool) {
+		if (tool == null || !(tool instanceof TableTool))
+			setCursor(getDisabledCursor());
+		else if (!((TableTool)tool).getWorksOnMatrixPanel()) {
+			setCursor(getDisabledCursor());
+		}
+		else if ((!((TableTool)tool).getWorksBeyondLastRow() && ((row>table.numRowsTotal)||(row<0)))||(!((TableTool)tool).getWorksBeyondLastColumn() && ((column>table.numColumnsTotal)||(column<0)))) 
+			setCursor(getDisabledCursor());
+		else 
+			setCursor(tool.getCursor());
+	}
+	/*...............................................................................................................*/
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+		int column = findColumn(x, y);
+		int row = findRow(x, y);
+		setCurrentCursor(modifiers, column, row, tool);
+		table.mouseInCell(modifiers, column,-1, row, -1,tool);
+		}
+		catch (Exception e){
+		}
+		catch (Throwable e){
+		}		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+		int column = findColumn(x, y);
+		int row = findRow(x, y);
+		setCurrentCursor(modifiers, column,  row, tool);
+		table.mouseInCell(modifiers, column,-1,  row, -1, tool);
+		}
+		catch (Exception e){
+		}
+		catch (Throwable e){
+		}
+		MesquiteWindow.uncheckDoomed(this);
+
+	}
+	public void focusGained(FocusEvent arg0) {
+	}
+	public void focusLost(FocusEvent arg0) {
+		if (table!=null) table.stopAutoScrollThread();
+	}
+
+
+}
+
diff --git a/Source/mesquite/lib/table/MesquiteTable.java b/Source/mesquite/lib/table/MesquiteTable.java
new file mode 100644
index 0000000..b0d515e
--- /dev/null
+++ b/Source/mesquite/lib/table/MesquiteTable.java
@@ -0,0 +1,5826 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import java.awt.datatransfer.*;
+
+import javax.swing.text.JTextComponent;
+
+import pal.math.MathUtils;
+import mesquite.lib.*;
+import mesquite.lib.duties.FileInterpreter;
+
+/* ======================================================================== */
+/**
+ * A base class to be extended for various spreadsheet-like tables. It provides very basic services like shaping the components, drawing the grid, fielding scrolling events and mousedowns, and provides hooks for superclasses to fill the cells. It is expected to be used for the type editor simple text charts, character data editor and list windows. Almost all of the burden of the memory design and management of the cells, rows, columns, etc. is left to the superclasses.
+ * <p>
+ * 
+ * The table is composed of 6 panels: the column for the row names (e.g., "from" state names in type editor or taxon names in data editor), the row for the column names (e.g., "to" state names in type editor or character names in data editor), the little corner between them in the upper left, the main block of cells (the scrollable matrix), and the two scroll bars for the matrix.
+ * <p>
+ * 
+ * Currently there are not too many settable parameters to customize the appearance of the table, but in the future it should be made possible to customize the table's appearance
+ */
+public class MesquiteTable extends MesquitePanel implements KeyListener {
+	protected ColumnNamesPanel columnNames = null;
+	protected RowNamesPanel rowNames = null;
+	protected MatrixPanel matrix;
+	protected CornerPanel cornerCell;
+	protected ControlStrip controlStrip;
+
+	public TableMarchingAnts marchingAnts;
+	static final int AUTOSCROLLBOUNDARY = 4;
+
+
+	public static final int LEFT = 0;
+	public static final int RIGHT = 1;
+	public static final int CENTERED = 2;
+
+	protected boolean columnNamesCopyPaste = true;
+	protected boolean rowNamesCopyPaste = true;
+	int baseRowHeight = 16;
+	//	int thinRowHeight=22;
+	int baseColumnWidth = 16;
+	int nameStartOffset = 5;
+	int focusColumn = -2;
+	int focusRow = -2;
+
+	int justification = CENTERED;
+	private Cursor handCursor;
+	private Cursor eastResizeCursor;
+	private Cursor northResizeCursor;
+
+	TableScroll horizScroll;
+	TableScroll vertScroll;
+
+	Rectangle messageBox; // just to left of horizScroll
+
+	int firstRowVisible = 0; // topmost row with current y scroll position
+	int firstColumnVisible = 0; // leftmost column with current horiz scroll position
+	int numRowsVisible = 0;
+	int numColumnsVisible = 0;
+	int lastRowVisible = 0; // bottom row visible, even if a partial row
+	int lastColumnVisible = 0; // rightmost column visible, even if partial column
+
+	public int numRowsTotal; // TODO: why is this used as if numRowsVisible?????
+	public int numColumnsTotal;
+
+	int columnGrabberWidth = 8;
+	int rowGrabberWidth = 8;
+	int columnNamesRowHeight = 20;
+	int rowNamesWidth = 50;
+	int matrixWidth;
+	int matrixHeight;
+	int[] columnWidths;
+	int[] rowHeights;
+
+	public MesquiteBoolean tight=new MesquiteBoolean(false);
+	public MesquiteBoolean thinRows=new MesquiteBoolean(false);
+
+	Font oldF = null;
+	Font boldFont = null;
+	public boolean frameRowNames = true;
+	public boolean frameColumnNames = true;
+	public boolean frameMatrixCells = true;
+	public boolean paleGrid = false;
+	public boolean boldCellText = false;
+	public boolean paleCellColors = false;
+	public boolean showRowGrabbers = false;
+	public boolean showColumnGrabbers = false;
+	public boolean showRowNumbers = false;
+	public boolean showColumnNumbers = false;
+
+	public boolean cornerIsHeading = false;
+	protected boolean autosizeColumns = false;
+	//	protected boolean autosizeRowNames = false;
+	public MesquiteBoolean autoRowNameWidth = new MesquiteBoolean(false);
+
+	private boolean cellsAutoEditable = false;
+	private boolean rowNamesAutoEditable = false;
+	private boolean columnNamesAutoEditable = false;
+	private boolean cornerAutoEditable = false;
+	private boolean cellsEditable = false;
+	private boolean rowNamesEditable = false;
+	private boolean columnNamesEditable = false;
+	private boolean cornerEditable = false;
+	private boolean cellsSelectable = true;
+	private boolean rowNamesSelectable = true;
+	private boolean columnNamesSelectable = true;
+	private boolean rowsSelectable = true;
+	private boolean columnsSelectable = true;
+	private boolean cornerSelectable = false;
+
+	private boolean quickMode = false;
+
+	public static final int NOADJUST = 0; // these constants refer to column and row user-adjust -- INSERT or RESIZE if interstitial space pulled
+	public static final int RESIZE = 1;
+	public static final int INSERT = 2;
+	private int userAdjustColumn = NOADJUST;
+	private boolean userMoveColumn = false;
+	private int userAdjustRow = NOADJUST;
+	private boolean userMoveRow = false;
+	public boolean adjustingColumnWidth = false;
+	public boolean adjustingColumnNamesHeight = false;
+
+	private Bits[] rowsSelected;
+	private Bits[] columnsSelected;
+	private Bits[] cellsSelected;
+	private Bits[] columnNamesSelected;
+	private Bits[] rowNamesSelected;
+	private boolean[] cornerSelected;
+
+	public static final int BETWEENLINEWIDTH = 4;
+	private int startBetweenRowSelection = MesquiteInteger.unassigned;
+	private int endBetweenRowSelection = MesquiteInteger.unassigned;
+	private int startBetweenColumnSelection = MesquiteInteger.unassigned;
+	private int endBetweenColumnSelection = MesquiteInteger.unassigned;
+
+
+	private int numSelectTypes = 3; // 0 = selection; 1 = dimming; 2 = dropdown menu
+	Bits rowWidthsAdjusted;
+	Bits columnWidthsAdjusted;
+	boolean rowNamesWidthAdjusted = false;
+	private Associable columnAssociable = null;
+	private Associable rowAssociable = null;
+	protected int colorScheme;
+
+	MesquiteCommand pasteCommand = MesquiteModule.makeCommand("paste", this);
+	MesquiteCommand cutCommand = MesquiteModule.makeCommand("cut", this);
+	MesquiteCommand clearCommand = MesquiteModule.makeCommand("clear", this);
+	MesquiteCommand copyCommand = MesquiteModule.makeCommand("copy", this);
+	MesquiteCommand copyLiteralCommand = MesquiteModule.makeCommand("copyLiteral", this);
+	MesquiteCommand selectAllCommand = MesquiteModule.makeCommand("selectAll", this);
+	boolean showRowNames = true;
+
+
+	public static MesquiteTimer tableTime;
+
+	static {
+		tableTime = new MesquiteTimer();
+	}
+
+	public MesquiteTable(int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int rowNamesWidth, int colorScheme, boolean showRowNumbers, boolean showColumnNumbers) {
+		super();
+		tableTime.start();
+		this.colorScheme = colorScheme;
+		this.numRowsTotal = numRowsTotal;
+		this.numColumnsTotal = numColumnsTotal;
+		this.rowNamesWidth = rowNamesWidth;
+		this.showRowNumbers = showRowNumbers;
+		this.showColumnNumbers = showColumnNumbers;
+		if (showRowNumbers)
+			setRowGrabberWidth(24);
+		if (showColumnNumbers)
+			setColumnGrabberWidth(14);
+		matrixWidth = totalWidth - rowNamesWidth - 16 - rowGrabberWidth;
+		matrixHeight = totalHeight - columnNamesRowHeight - 16 - columnGrabberWidth;
+
+		columnWidths = new int[numColumnsTotal];
+		rowWidthsAdjusted = new Bits(numRowsTotal);
+		columnWidthsAdjusted = new Bits(numColumnsTotal);
+		setColumnWidthsUniform(baseColumnWidth);
+		rowHeights = new int[numRowsTotal];
+		setRowHeightsUniform(baseRowHeight);
+		//		setRowHeightsUniform(thinRowHeight);
+
+
+		rowsSelected = new Bits[numSelectTypes];
+		columnsSelected = new Bits[numSelectTypes];
+		cellsSelected = new Bits[numSelectTypes];
+		columnNamesSelected = new Bits[numSelectTypes];
+		rowNamesSelected = new Bits[numSelectTypes];
+		cornerSelected = new boolean[numSelectTypes];
+		for (int i = 0; i < numSelectTypes; i++) {
+			rowsSelected[i] = new Bits(numRowsTotal);
+			columnsSelected[i] = new Bits(numColumnsTotal);
+			cellsSelected[i] = new Bits((numRowsTotal) * (numColumnsTotal));
+			columnNamesSelected[i] = new Bits(numColumnsTotal);
+			rowNamesSelected[i] = new Bits(numRowsTotal);
+			cornerSelected[i] = false;
+		}
+
+		setLayout(null);
+		handCursor = new Cursor(Cursor.HAND_CURSOR);
+		eastResizeCursor = new Cursor(Cursor.E_RESIZE_CURSOR);
+		northResizeCursor = new Cursor(Cursor.N_RESIZE_CURSOR);
+
+		rowNames = new RowNamesPanel(this, rowNamesWidth + rowGrabberWidth, matrixHeight);
+		add(rowNames);
+
+		columnNames = new ColumnNamesPanel(this, matrixWidth, columnNamesRowHeight + columnGrabberWidth);
+		add(columnNames);
+
+		matrix = new MatrixPanel(this, matrixWidth, matrixHeight);
+		add(matrix);
+
+		cornerCell = new CornerPanel(this, rowNamesWidth - 1 + rowGrabberWidth, columnNamesRowHeight - 1 + columnGrabberWidth);
+		add(cornerCell);
+
+		horizScroll = new TableScroll(this, Scrollbar.HORIZONTAL, 0, 0, 0, numColumnsTotal);
+		add(horizScroll);
+
+		controlStrip = new ControlStrip(colorScheme);
+		add(controlStrip);
+		// controlStrip.setBackground(Color.green);
+
+		vertScroll = new TableScroll(this, Scrollbar.VERTICAL, 0, 0, 0, numRowsTotal);
+		add(vertScroll);
+		rowNames.setVisible(true);
+		columnNames.setVisible(true);
+		setSize(totalWidth, totalHeight);
+		matrix.setVisible(true);
+		cornerCell.setVisible(true);
+		horizScroll.setVisible(true);
+		controlStrip.setVisible(true);
+		vertScroll.setVisible(true);
+		tableTime.end();
+		// addKeyListener(this);
+	}
+
+	/** Return Mesquite commands that will put the table back to its current state (approximately). */
+	public Snapshot getSnapshot(MesquiteFile file) { // this allows employees to be dealt with
+		if (columnWidthsAdjusted.anyBitsOn() || rowNamesWidthAdjusted) {
+			Snapshot temp = new Snapshot();
+			if (rowNamesWidthAdjusted)
+				temp.addLine("rowNamesWidth " + rowNamesWidth);
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (columnWidthsAdjusted.isBitOn(i))
+					temp.addLine("columnWidth " + i + " " + getColumnWidth(i));
+			}
+			return temp;
+		}
+		else
+			return null;
+	}
+
+	private String getSelectedText(TextField edit) {
+		int selStart = edit.getSelectionStart();
+		if (edit.getSelectionStart() < 0)
+			return null;
+		int selEnd = edit.getSelectionEnd();
+		String text = edit.getText();
+		if (text == null)
+			return null;
+
+		String copied = text.substring(selStart, selEnd);
+		return copied;
+	}
+
+	/* ................................................................................................................. */
+	public void adjustMarchingAnts(){
+		if (marchingAnts!=null)
+			marchingAnts.moveAnts();
+	}
+
+	/* ................................................................................................................. */
+	public void cancelMarchingAnts(){
+		if (marchingAnts!=null) {
+			marchingAnts.cancel();
+			marchingAnts=null;
+		}
+	}
+
+	/* ................................................................................................................. */
+	public void startMarchingAnts (int column1, int row1, int column2, int row2) {
+		marchingAnts = new TableMarchingAnts(this, getMatrixPanel().getGraphics(),  column1, row1, column2, row2);
+	}
+	/* ................................................................................................................. */
+
+	/* ................................................................................................................. */
+
+	/**
+	 * A request for the MesquiteModule to perform a command. It is passed two strings, the name of the command and the arguments. This should be overridden by any module that wants to respond to a command.
+	 */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(MesquiteTable.class, "Copies current selection to clipboard", null, commandName, "copy")) {
+			if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (rowNames.getEditing())
+					edit = rowNames.getEditField();
+				else if (columnNames.getEditing())
+					edit = columnNames.getEditField();
+				if (edit != null && edit.hasFocus()) {
+					String copied = getSelectedText(edit);
+					if (copied == null)
+						return null;
+					Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+					StringSelection ss = new StringSelection(copied);
+					clip.setContents(ss, ss);
+					return null;
+				}
+			}
+			else {
+				StringBuffer sb = new StringBuffer(100);
+				copyCells(sb, false);
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(sb.toString());
+				clip.setContents(ss, ss);
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "enterPressed")) {
+			enterPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "tabPressed")) {
+			tabPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "rightArrowPressed")) {
+			rightArrowPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "leftArrowPressed")) {
+			leftArrowPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "upArrowPressed")) {
+			upArrowPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Key pressed", null, commandName, "downArrowPressed")) {
+			downArrowPressed(arguments);
+		}
+		else if (checker.compare(MesquiteTable.class, "Copies current selection to clipboard, literally (with full names)", null, commandName, "copyLiteral")) {
+			if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (rowNames.getEditing())
+					edit = rowNames.getEditField();
+				else if (columnNames.getEditing())
+					edit = columnNames.getEditField();
+				if (edit != null && edit.hasFocus()) {
+					String copied = getSelectedText(edit);
+					if (copied == null)
+						return null;
+					Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+					StringSelection ss = new StringSelection(copied);
+					clip.setContents(ss, ss);
+					return null;
+				}
+			}
+			else {
+				StringBuffer sb = new StringBuffer(100);
+				copyCells(sb, true);
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(sb.toString());
+				clip.setContents(ss, ss);
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Copies current selection to clipboard and clears from selection", null, commandName, "cut")) {
+			if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (rowNames.getEditing())
+					edit = rowNames.getEditField();
+				else if (columnNames.getEditing())
+					edit = columnNames.getEditField();
+				if (edit != null && edit.hasFocus()) {
+					String copied = getSelectedText(edit);
+					if (copied == null)
+						return null;
+					String oldText = edit.getText();
+					String newText = oldText.substring(0, edit.getSelectionStart()) + oldText.substring(edit.getSelectionEnd(), oldText.length());
+					edit.setText(newText);
+					Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+					StringSelection ss = new StringSelection(copied);
+					clip.setContents(ss, ss);
+				}
+			}
+			else {
+				StringBuffer sb = new StringBuffer(100);
+				copyCells(sb, false);
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(sb.toString());
+				clip.setContents(ss, ss);
+				clearIt(true);
+				repaintAll();
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Clears current selection", null, commandName, "clear")) {
+			if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (rowNames.getEditing())
+					edit = rowNames.getEditField();
+				else if (columnNames.getEditing())
+					edit = columnNames.getEditField();
+				if (edit != null && edit.hasFocus()) {
+					String text = edit.getText();
+					String newText = text.substring(0, edit.getSelectionStart()) + text.substring(edit.getSelectionEnd(), text.length());
+					edit.setText(newText);
+					return null;
+				}
+			}
+			else {
+				MesquiteWindow ww = MesquiteWindow.windowOfItem(this);
+				if (ww.componentWithFocus() != null){
+					Component c = ww.componentWithFocus();
+					if (c instanceof TextComponent){
+						TextComponent tc = (TextComponent)c;
+						if (tc.isEditable()){
+							tc.setText("");
+						}
+						return null;
+					}
+					else if (c instanceof JTextComponent){
+						JTextComponent tc = (JTextComponent)c;
+						if (tc.isEditable()){
+							tc.setText("");
+						}
+						return null;
+					}
+
+				}
+			}
+
+			clearIt(false);
+			repaintAll();
+
+		}
+		else if (checker.compare(MesquiteTable.class, "Selects all of table, columns, rows, cells, or names, depending on current selection", null, commandName, "selectAll")) {
+			if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+				TextField edit = null;
+				if (matrix.getEditing())
+					edit = matrix.getEditField();
+				else if (rowNames.getEditing())
+					edit = rowNames.getEditField();
+				else if (columnNames.getEditing())
+					edit = columnNames.getEditField();
+				if (edit != null && edit.hasFocus()) {
+					edit.selectAll();
+					return null;
+				}
+			}
+			else {
+				boolean selectA = (!anythingSelected());
+
+				if (cellsSelectable && (selectA || anyCellSelected()))
+					selectBlock(0, 0, numColumnsTotal - 1, numRowsTotal - 1);
+				if (rowsSelectable && (selectA || anyRowSelected())) {
+					selectRows(0, numRowsTotal - 1);
+					if (rowAssociable != null)
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+				if (columnsSelectable && (selectA || anyColumnSelected())) {
+					selectColumns(0, numColumnsTotal - 1);
+					if (columnAssociable != null)
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+				if (rowNamesSelectable && (selectA || anyRowNameSelected()))
+					selectRowNames(0, numRowsTotal - 1);
+				if (columnNamesSelectable && (selectA || anyColumnNameSelected()))
+					selectColumnNames(0, numColumnsTotal - 1);
+				repaintAll();
+				/*
+				 * if (cornerSelectable) selectCorner;
+				 */
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Pastes from clipboard into current selection", null, commandName, "paste")) {
+			MesquiteWindow ww = MesquiteWindow.windowOfItem(this);
+			Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+			Transferable t = clip.getContents(this);
+			try {
+				String s = (String) t.getTransferData(DataFlavor.stringFlavor);
+				if (s != null) {
+					if (matrix.getEditing() || rowNames.getEditing() || columnNames.getEditing()) {
+						TextField edit = null;
+						if (matrix.getEditing())
+							edit = matrix.getEditField();
+						else if (rowNames.getEditing())
+							edit = rowNames.getEditField();
+						else if (columnNames.getEditing())
+							edit = columnNames.getEditField();
+						if (edit != null && edit.hasFocus()) {
+							String text = edit.getText();
+							String newText = text.substring(0, edit.getSelectionStart()) + s + text.substring(edit.getSelectionEnd(), text.length());
+							edit.setText(newText);
+							return newText;
+						}
+					}
+					else if (ww.componentWithFocus() != null){
+						Component c = ww.componentWithFocus();
+						if (c instanceof TextComponent){
+							TextComponent tc = (TextComponent)c;
+							if (tc.isEditable()){
+								String text = tc.getText();
+								String newText = text.substring(0, tc.getSelectionStart()) + s + text.substring(tc.getSelectionEnd(), text.length());
+								tc.setText(newText);
+							}
+							return s;
+						}
+						else if (c instanceof JTextComponent){
+							JTextComponent tc = (JTextComponent)c;
+							if (tc.isEditable()){
+								String text = tc.getText();
+								String newText = text.substring(0, tc.getSelectionStart()) + s + text.substring(tc.getSelectionEnd(), text.length());
+								tc.setText(newText);
+							}
+							return s;
+						}
+
+					}
+					if (clipboardDimensionsFit(s)) {
+						pasteIt(s);
+						repaintAll();
+					}
+
+					else if (anythingSelected()) {
+						MesquiteWindow frame = MesquiteTrunk.mesquiteTrunk.containerOfModule();
+						if (ww != null) {
+							MesquiteModule mm = ww.getOwnerModule();
+							if (mm != null) {
+								frame = mm.containerOfModule();
+							}
+						}
+						if (AlertDialog.query(frame, "Paste shape mismatch", "Sorry, the number of lines and of items pasted don't match the spaces selected to be filled.  Would you like Mesquite to attempt to adjust the selected region so that you can paste?", "OK", "Cancel", 1))
+							setSelectionToShape(getTabbedLines(s));
+
+						return null;
+					}
+				}
+			} catch (Exception e) {
+				MesquiteMessage.printStackTrace(e);
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Sets width of the column containing the row names", "[width]", commandName, "rowNamesWidth")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int width = MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(width)) {
+				setRowNamesWidth(width);
+				resetComponentSizes();
+				rowNamesWidthAdjusted = true;
+			}
+
+		}
+		else if (checker.compare(MesquiteTable.class, "Sets width of a column", "[column][width]", commandName, "columnWidth")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column = MesquiteInteger.fromString(arguments, io);
+			int width = MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(column) && MesquiteInteger.isCombinable(width)) {
+				if (column >= 0 && column < numColumnsTotal) {
+					setColumnWidth(column, width);
+					columnWidthsAdjusted.setBit(column);
+				}
+			}
+
+		}
+		else if (checker.compare(MesquiteTable.class, "Edits cell", "[column][row]", commandName, "editCell")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column = MesquiteInteger.fromString(arguments, io);
+			int row = MesquiteInteger.fromString(arguments, io);
+			boolean doRepaint = (anyRowColumnSelected());
+			deselectAllNotify();
+			if (column < 0)
+				editRowNameCell(row);
+			else if (row < 0)
+				editColumnNameCell(column);
+			else
+				editMatrixCell(column, row);
+			if (doRepaint)
+				repaintAll();
+		}
+		else if (checker.compare(MesquiteTable.class, "Returns column as string", "[column]", commandName, "getColumn")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column = MesquiteInteger.fromString(arguments, io);
+			if (column > 0 && column < getNumColumns()){
+				StringBuffer sb = new StringBuffer(getColumnNameText(column));
+				for (int i=0; i<getNumRows(); i++){
+					sb.append('\t');
+					sb.append(getMatrixText(column, i));
+				}
+				return sb.toString();
+			}
+		}
+		else if (checker.compare(MesquiteTable.class, "Returns row as string", "[row]", commandName, "getRow")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int row = MesquiteInteger.fromString(arguments, io);
+			if (row > 0 && row < getNumRows()){
+				StringBuffer sb = new StringBuffer(getRowNameText(row));
+				for (int i=0; i<getNumColumns(); i++){
+					sb.append('\t');
+					sb.append(getMatrixText(i, row));
+				}
+				return sb.toString();
+			}
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public boolean selectedBetweenRows() {
+		return (getBetweenSelected() && startBetweenRowSelection==endBetweenRowSelection);
+	}
+	/* ................................................................................................................. */
+	public boolean selectedBetweenColumns() {
+		return (getBetweenSelected() && startBetweenColumnSelection==endBetweenColumnSelection);
+	}
+	/* ................................................................................................................. */
+	public int betweenColumn() {
+		return startBetweenColumnSelection;
+	}
+	/* ................................................................................................................. */
+	public int betweenRow() {
+		return startBetweenRowSelection;
+	}
+	/* ................................................................................................................. */
+
+	public boolean inBetweenSelectionRowColumns( int column, int row) {
+		int buff = 2;
+		if (selectedBetweenColumns())
+			return row>=getStartBetweenRowSelection() && row <= getEndBetweenRowSelection() && (column == getStartBetweenColumnSelection()) ;
+			else if (selectedBetweenRows())
+				return column>=getStartBetweenColumnSelection() && column <= getEndBetweenColumnSelection()  && (row == getStartBetweenRowSelection()) ;
+				return false;
+	}
+	/* ................................................................................................................. */
+
+	public boolean inBetweenSelection( int column, int row, int regionInCellH, int regionInCellV) {
+		int buff = 2;
+		if (selectedBetweenColumns())
+			return (row>=getStartBetweenRowSelection() && row <= getEndBetweenRowSelection()) && ((regionInCellH>80 && column == getStartBetweenColumnSelection()) || (regionInCellH<20 && column == getStartBetweenColumnSelection()+1)) ;
+		else if (selectedBetweenRows())
+			return column>=getStartBetweenColumnSelection() && column <= getEndBetweenColumnSelection() && (regionInCellV>80||regionInCellV<20) && (row == getStartBetweenRowSelection()) ;
+			return false;
+	}
+	/* ................................................................................................................. */
+
+	public boolean inBetweenSelection(int x, int y) {
+		int buff = 2;
+		if (selectedBetweenColumns())
+			return (x>= getColumnX(getStartBetweenColumnSelection()-buff - MesquiteTable.BETWEENLINEWIDTH)) && (x<= getColumnX(getEndBetweenColumnSelection()+buff + MesquiteTable.BETWEENLINEWIDTH)) && (y>= getRowY(getStartBetweenRowSelection()-buff)) && (y<= getRowY(getEndBetweenRowSelection()+buff));
+		else if (selectedBetweenRows())
+			return (x>= getColumnX(getStartBetweenColumnSelection()-buff)) && (x<= getColumnX(getEndBetweenColumnSelection()+buff)) && (y>= getRowY(getStartBetweenRowSelection()-buff - MesquiteTable.BETWEENLINEWIDTH)) && (y<= getRowY(getEndBetweenRowSelection()+buff+MesquiteTable.BETWEENLINEWIDTH));
+		return false;
+	}
+	/* ................................................................................................................. */
+	public boolean getBetweenSelected() {
+		boolean assigned = MesquiteInteger.isCombinable(startBetweenRowSelection)&&MesquiteInteger.isCombinable(endBetweenRowSelection)&&MesquiteInteger.isCombinable(startBetweenColumnSelection)&&MesquiteInteger.isCombinable(endBetweenColumnSelection);
+		if (!assigned)
+			return false;
+		boolean inRange =  (startBetweenRowSelection>=0 && startBetweenRowSelection<=getNumRows()) &&  (endBetweenRowSelection>=0 && endBetweenRowSelection<=getNumRows()) &&  (startBetweenColumnSelection>=0 && startBetweenColumnSelection<=getNumColumns()) &&  (endBetweenColumnSelection>=0 && endBetweenColumnSelection<=getNumColumns());
+		if (!inRange)
+			return false;
+		return (Math.abs(startBetweenRowSelection-endBetweenRowSelection)>=0 || Math.abs(startBetweenColumnSelection-endBetweenColumnSelection)>=0);
+	}
+
+	// public static final int GRABBERS = 8;
+	/* ................................................................................................................. */
+	public int getRowGrabberWidth() {
+		return rowGrabberWidth;
+	}
+
+	/* ................................................................................................................. */
+	public void setRowGrabberWidth(int grabberWidth) {
+		this.rowGrabberWidth = grabberWidth;
+	}
+	public void setColumnNamesDiagonal(boolean diagonal){
+		columnNames.setDiagonal(diagonal);
+	}
+	/* ................................................................................................................. */
+	public void setColumnNamesCopyPaste(boolean copyPastable) {
+		this.columnNamesCopyPaste = copyPastable;
+	}
+
+	/* ................................................................................................................. */
+	public void setRowNamesCopyPaste(boolean copyPastable) {
+		this.rowNamesCopyPaste = copyPastable;
+	}
+
+	/* ................................................................................................................. */
+	public int getColumnGrabberWidth() {
+		return columnGrabberWidth;
+	}
+
+	/* ................................................................................................................. */
+	public void setColumnGrabberWidth(int grabberWidth) {
+		this.columnGrabberWidth = grabberWidth;
+	}
+
+	/* ................................................................................................................. */
+	public String getColumnComment(int column) {
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	public String getRowComment(int row) {
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	protected void clearIt(boolean cut) {
+		for (int i = 0; i < numColumnsTotal; i++) {
+			if (isColumnNameSelected(i) || isColumnSelected(i)) {
+				if (columnNamesEditable)
+					returnedColumnNameText(i, null);
+			}
+		}
+		for (int j = 0; j < numRowsTotal; j++) {
+			if (isRowNameSelected(j) || isRowSelected(j)) {
+				if (rowNamesEditable)
+					returnedRowNameText(j, null);
+			}
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+					if (isCellEditable(i, j))
+						returnedMatrixText(i, j, null);
+				}
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	protected void OLDpasteIt(String s) {
+		int count = 0;
+		MesquiteInteger pos = new MesquiteInteger(0);
+		if (columnNamesCopyPaste) {
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isColumnNameSelected(i) || isColumnSelected(i)) {
+					if (columnNamesEditable) {
+						String t = getNextTabbedToken(s, pos);
+						if (t != null)
+							returnedColumnNameText(i, t);
+					}
+					count++;
+				}
+			}
+		}
+		for (int j = 0; j < numRowsTotal; j++) {
+			if (rowNamesCopyPaste && (isRowNameSelected(j) || isRowSelected(j))) {
+				if (rowNamesEditable) {
+					String t = getNextTabbedToken(s, pos);
+					if (t != null)
+						returnedRowNameText(j, t);
+				}
+				count++;
+			}
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+					if (isCellEditable(i, j)) {
+						String t = getNextTabbedToken(s, pos);
+						if (t != null)
+							returnedMatrixText(i, j, t);
+					}
+					count++;
+				}
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	protected void pasteIt(String s) {
+		int count = 0;
+		MesquiteInteger pos = new MesquiteInteger(0);
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isColumnNameSelected(i) || isColumnSelected(i)) {
+						String t = getNextTabbedToken(s, pos);
+						if (t != null && columnNamesEditable && columnNamesCopyPaste)
+							returnedColumnNameText(i, t);
+					count++;
+				}
+			}
+		
+		for (int j = 0; j < numRowsTotal; j++) {
+			if (isRowNameSelected(j) || isRowSelected(j)) {
+					String t = getNextTabbedToken(s, pos);
+					if (t != null && rowNamesEditable && rowNamesCopyPaste)
+						returnedRowNameText(j, t);
+				count++;
+			}
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+						String t = getNextTabbedToken(s, pos);
+						if (t != null && isCellEditable(i, j))
+							returnedMatrixText(i, j, t);
+					count++;
+				}
+			}
+		}
+	}
+
+	/* ................................................................................................................. */
+	public void copyIt(StringBuffer s, boolean literal) {
+		copyIt(s, literal, true, true);
+	}
+
+	/* ................................................................................................................. */
+	public void copyIt(StringBuffer s, boolean literal, boolean copyInsertTabs, boolean copyInsertReturns) {
+		if (s == null)
+			return;
+		int count = 0;
+		boolean firstInLine = true;
+		boolean allSelected = true;
+		boolean nothingSelected = !anythingSelected();
+		if (columnNamesCopyPaste) {
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (nothingSelected || isColumnNameSelected(i) || isColumnSelected(i)) {
+					if (!firstInLine)
+						s.append('\t');
+					firstInLine = false;
+					String t = null;
+					if (literal)
+						t = getColumnNameTextForDisplay(i);
+					else
+						t = getColumnNameText(i);
+					if (t != null)
+						s.append(t);
+				}
+				else
+					allSelected = false;
+			}
+		}
+		else
+			allSelected = false;
+		if (!firstInLine)
+			s.append(StringUtil.lineEnding());
+		boolean previousWasRowName = false;
+		for (int j = 0; j < numRowsTotal; j++) {
+			firstInLine = true;
+			if (rowNamesCopyPaste) {
+				if (nothingSelected || isRowNameSelected(j) || isRowSelected(j)) {
+					String t = null;
+					if (literal)
+						t = getRowNameTextForDisplay(j);
+					else
+						t = getRowNameText(j);
+					if (t != null)
+						s.append(t);
+					firstInLine = false;
+					previousWasRowName = true;
+				}
+				else
+					allSelected = false;
+			}
+			else
+				allSelected = false;
+
+			for (int i = 0; i < numColumnsTotal; i++) {
+				if (nothingSelected || isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i)) {
+					if (previousWasRowName || (!firstInLine && copyInsertTabs)){
+						s.append('\t');
+						previousWasRowName = false;
+					}
+					firstInLine = false;
+					String t = null;
+					if (literal)
+						t = getMatrixTextForDisplay(i, j);
+					else
+						t = getMatrixText(i, j);
+					if (t != null)
+						s.append(t);
+				}
+				else
+					allSelected = false;
+			}
+			if (!firstInLine && copyInsertReturns)
+				s.append(StringUtil.lineEnding());
+		}
+		if (allSelected && copyInsertTabs) // absolutely everyting is selected; prepend tab for corner cell
+			s.insert(0, '\t');
+
+	}
+	/* ................................................................................................................. */
+	public void copyCells(StringBuffer s, boolean literal) {
+		copyIt(s,literal,true, true);
+	}
+
+	/* ................................................................................................................. */
+	protected boolean clipboardDimensionsFit(String s) {
+		int[] fString = getTabbedLines(s);
+		int[] fSelected = getSelectedSpaces();
+		if (fString == null || fSelected == null || fString.length != fSelected.length)
+			return false;
+		for (int i = 0; i < fString.length; i++)
+			if (fString[i] != fSelected[i]) {
+				return false;
+			}
+		return true;
+	}
+	/* ................................................................................................................. */
+	protected Point getTopLeftSelected(){
+		if (anyColumnSelected() || anyRowSelected() || anyCellSelected()) {
+			int firstRow = firstRowSelected();
+			int firstColumn = firstColumnSelected();
+			int top = -1;
+			int left = -1;
+			boolean found = false;
+			for (int row = 0; row < numRowsTotal && !found; row++) { // row dominant choice of upper left
+				for (int column = 0; column < numColumnsTotal && !found; column++) {
+					if (isCellSelected(column, row)) {
+						top = row;
+						left = column;
+						found = true;
+					}
+				}
+			}
+			if (firstRow >= 0 && (firstRow < top || top < 0))
+				top = firstRow;
+			if (firstColumn >= 0 && (firstColumn < left || left < 0))
+				left = firstColumn;
+			if (top < 0 && left >= 0)
+				top = 0;
+			if (left < 0 && top >= 0)
+				left = 0;
+			if (anyColumnSelected())
+				top = -1;
+			if (anyRowSelected())
+				left = -1;
+
+			return new Point(left, top);
+		}
+		else if (anyRowNameSelected()) {
+			int first = rowNamesSelected[0].firstBitOn();
+			return new Point(-1, first);
+		}
+		else if (anyColumnNameSelected()) {
+			int first = columnNamesSelected[0].firstBitOn();
+			return new Point(first, -1);
+		}
+		return new Point(-1, -1);
+	}
+	/* ................................................................................................................. */
+	public void setSelectionToShape(int[] lines) {
+		if (lines == null)
+			return;
+		if (anyColumnSelected() || anyRowSelected() || anyCellSelected()) {
+			int firstRow = firstRowSelected();
+			int firstColumn = firstColumnSelected();
+			int top = -1;
+			int left = -1;
+			boolean found = false;
+			for (int row = 0; row < numRowsTotal && !found; row++) { // row dominant choice of upper left
+				for (int column = 0; column < numColumnsTotal && !found; column++) {
+					if (isCellSelected(column, row)) {
+						top = row;
+						left = column;
+						found = true;
+					}
+				}
+			}
+			if (firstRow >= 0 && (firstRow < top || top < 0))
+				top = firstRow;
+			if (firstColumn >= 0 && (firstColumn < left || left < 0))
+				left = firstColumn;
+			if (top < 0 && left >= 0)
+				top = 0;
+			if (left < 0 && top >= 0)
+				left = 0;
+			if (lines.length == numRowsTotal + 1) { // whole columns had been selected; do likewise
+				for (int column = 0; column < lines[0]; column++)
+					selectColumn(column + left);
+				if (lines[0] == numColumnsTotal + 1) // whole rows had been selected; do likewise
+					for (int row = 0; row < lines.length; row++)
+						selectRow(row + top);
+
+			}
+			else if (lines[0] == numColumnsTotal + 1) { // whole rows had been selected; do likewise
+				for (int row = 0; row < lines.length; row++) {
+					selectRow(row + top);
+				}
+			}
+			else {
+
+				if (top >= 0 && left >= 0) {
+					deselectAll();
+					for (int row = 0; row < lines.length; row++)
+						for (int column = 0; column < lines[row]; column++) {
+							selectCell(column + left, row + top);
+						}
+				}
+				if (columnAssociable != null && firstColumn >= 0)
+					columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				if (rowAssociable != null && firstRow >= 0)
+					rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+		else if (anyRowNameSelected()) {
+			int first = rowNamesSelected[0].firstBitOn();
+			for (int row = first; row < lines.length + first; row++) {
+				selectRowName(row);
+			}
+		}
+		else if (anyColumnNameSelected()) {
+			if (lines.length == 1) {
+				int first = columnNamesSelected[0].firstBitOn();
+				for (int column = first; column < lines[0] + first; column++) {
+					selectColumnName(column);
+
+				}
+			}
+		}
+		repaintAll();
+	}
+
+	/* ................................................................................................................. */
+	protected int[] getSelectedSpaces() {
+
+		// for each row, how many things are selected needs to be calculated
+		// first, figure out how many rows have selections in them.
+		int lines = 0;
+		if ((anyColumnNameSelected() || anyColumnSelected()) && columnNamesCopyPaste)
+			lines++;
+		if (anyColumnSelected())
+			lines += numRowsTotal;
+		else
+			for (int j = 0; j < numRowsTotal; j++) {
+				if ((isRowNameSelected(j) && rowNamesCopyPaste) || isRowSelected(j) || anyCellInRowSelected(j))
+					lines++;
+			}
+
+		// now, figure out how many items in each line
+		int[] result = new int[lines];
+		int line = 0;
+		int numInLine = 0;
+		for (int i = 0; i < numColumnsTotal; i++)
+			if ((isColumnNameSelected(i) || isColumnSelected(i)) && columnNamesCopyPaste)
+				numInLine++;
+		if (numInLine > 0) {
+			result[line] = numInLine;
+			line++;
+		}
+		for (int j = 0; j < numRowsTotal; j++) {
+			numInLine = 0;
+			if (rowNamesCopyPaste && (isRowNameSelected(j) || isRowSelected(j))) // for name of taxon
+				numInLine++;
+			for (int i = 0; i < numColumnsTotal; i++)
+				if (isCellSelected(i, j) || isRowSelected(j) || isColumnSelected(i))
+					numInLine++;
+			if (numInLine > 0) {
+				result[line] = numInLine;
+				line++;
+			}
+		}
+		return result;
+	}
+
+	/* ................................................................................................................. */
+	protected boolean anyCellInRowSelected(int row) {
+		if (!rowLegal(row))
+			return false;
+		for (int i = 0; i < numColumnsTotal; i++) {
+			if (isCellSelected(i, row))
+				return true;
+		}
+		return false;
+	}
+
+	/* ................................................................................................................. */
+	protected String showInvisibles(String s) {
+		if (s == null)
+			return null;
+		String sNew = "";
+		for (int i = 0; i < s.length(); i++)
+			if (s.charAt(i) == '\t')
+				sNew += "<^t>";
+			else if (s.charAt(i) == '\r')
+				sNew += "<^r>";
+			else if (s.charAt(i) == '\n')
+				sNew += "<^n>";
+			else
+				sNew += s.charAt(i);
+		return sNew;
+	}
+
+	public void keyTyped(KeyEvent e) {
+	}
+
+
+	public void keyPressed(KeyEvent e) {  
+		if (!MesquiteWindow.belongsTo(e.getComponent(), this))
+			return;
+		if (e.getComponent() instanceof Scrollbar)
+			return;
+		String arguments = "";
+		if (e.isShiftDown())
+			arguments += " shift ";
+		if (e.isAltDown())
+			arguments += " option ";
+
+		if (e.getKeyCode() == KeyEvent.VK_ENTER){
+			MesquiteCommand key = new MesquiteCommand("enterPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+		else if (e.getKeyCode() == KeyEvent.VK_TAB){
+			MesquiteCommand key = new MesquiteCommand("tabPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+		else if (e.getKeyCode() == KeyEvent.VK_RIGHT){
+			MesquiteCommand key = new MesquiteCommand("rightArrowPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+		else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
+			MesquiteCommand key = new MesquiteCommand("leftArrowPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+		else if (e.getKeyCode() == KeyEvent.VK_UP){
+			MesquiteCommand key = new MesquiteCommand("upArrowPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+		else if (e.getKeyCode() == KeyEvent.VK_DOWN){
+			MesquiteCommand key = new MesquiteCommand("downArrowPressed", arguments, this);
+			key.setSuppressLogging(true);
+			key.doItMainThread(arguments, null, this);
+		}
+
+	}
+
+	public void keyReleased(KeyEvent e) {
+	}
+
+	private EditorTextField getEditField() {
+		if (matrix.getEditing())
+			return matrix.getEditField();
+		if (columnNames.getEditing())
+			return columnNames.getEditField();
+		if (rowNames.getEditing())
+			return rowNames.getEditField();
+		return null;
+	}
+
+	private boolean getEditing() {
+		return matrix.getEditing() || columnNames.getEditing() || rowNames.getEditing();
+	}
+
+	public void enterPressed(String arguments) {
+		if (getEditing()) // let the edit box handle it
+			return;
+		// go to editing
+		if (singleTableCellSelected()) {
+			Dimension sel = getFirstTableCellSelected();
+			if (sel.width >= -1 && sel.height >= -1) {
+				if (sel.width == -1 && sel.height >= 0) { // rowNames
+					if (isRowNameEditable(sel.height))
+						rowNames.editCell(sel.width, sel.height);
+				}
+				else if (sel.width >= 0 && sel.height == -1) { // columnNames
+					if (isColumnNameEditable(sel.width))
+						columnNames.editCell(sel.width, sel.height);
+				}
+				else if (sel.width >= 0 && sel.height >= 0) { // within matrix
+					if (isCellEditable(sel.width, sel.height))
+						matrix.editCell(sel.width, sel.height);
+				}
+			}
+
+		}
+	}
+
+	public void tabPressed(String arguments) {
+		if (getEditing())
+			return;
+		rightArrowPressed(arguments);
+	}
+
+	public void downArrowPressed(String arguments) {
+		if (getEditing())
+			return;
+		if (StringUtil.foundIgnoreCase(arguments, "shift")){
+			if (anyRowSelected()){ //accumulateSelection
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int first = firstRowSelected();
+					selectRows(first, getNumRows()-1);
+					if (rowAssociable != null) 
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+					repaintAll();
+				}
+				else {
+					for (int i = getNumRows()-1; i >=0; i--){
+						if (isRowSelected(i) && !isRowSelected(i+1))
+							selectRow(i+1);
+					}
+					if (rowAssociable != null) 
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+			}
+			if (anyCellSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){
+					for (int column = 0; column< getNumColumns(); column++){
+						boolean doneColumn = false;
+						for (int row = 0; row< getNumRows() && !doneColumn; row++)
+							if (isCellSelected(column, row)){
+								selectBlock(column, row, column, getNumRows()-1);
+								doneColumn = true;
+							}
+					}
+					repaintAll();
+				}
+				else {
+					int firstRow = firstRowWithSelectedCell();
+					int lastRow = lastRowWithSelectedCell();
+					for (int row = lastRow; row>= firstRow; row--){
+						for (int column = 0; column< getNumColumns(); column++)
+							if (isCellSelected(column, row) && !isCellSelected(column, row+1))
+								selectCell(column, row+1);
+					}
+					repaintAll();
+				}
+			}
+			if (anyRowNameSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int first = firstRowNameSelected();
+					selectRowNames(first, getNumRows()-1);
+					repaintAll();
+				}
+				else {
+					for (int i = getNumRows()-1; i >=0; i--){
+						if (isRowNameSelected(i) && !isRowNameSelected(i+1))
+							selectRowName(i+1);
+					}
+					repaintAll();
+				}
+			}
+		}
+		else if (singleTableCellSelected()) {
+			Dimension sel = getFirstTableCellSelected();
+			if (sel.width >= -1 && sel.height >= -1) {
+				if (sel.height + 1 < numRowsTotal) {
+					deselectCell(sel.width, sel.height);
+					selectCell(sel.width, sel.height + 1);
+					redrawCell(sel.width, sel.height);
+					redrawCell(sel.width, sel.height + 1);
+					setFocusedCell(sel.width, sel.height + 1);
+				}
+				else
+					MesquiteMessage.beep();
+			}
+			else
+				MesquiteMessage.beep();
+
+		}
+	}
+
+	public void upArrowPressed(String arguments) { //
+		if (getEditing())
+			return;
+		if (StringUtil.foundIgnoreCase(arguments, "shift")){
+			if (anyRowSelected()){ //accumulateSelection
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int last = lastRowSelected();
+					selectRows(0, last);
+					if (rowAssociable != null) 
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+				else {
+					for (int i = 1; i <getNumRows(); i++){
+						if (isRowSelected(i) && !isRowSelected(i-1))
+							selectRow(i-1);
+					}
+					if (rowAssociable != null) 
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+			}
+			if (anyCellSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){
+					for (int column = 0; column< getNumColumns(); column++){
+						boolean doneColumn = false;
+						for (int row = getNumRows()-1; row>=0 && !doneColumn; row--)
+							if (isCellSelected(column, row)){
+								selectBlock(column, 0, column, row);
+								doneColumn = true;
+							}
+					}
+					repaintAll();
+				}
+				else {
+					int firstRow = firstRowWithSelectedCell();
+					int lastRow = lastRowWithSelectedCell();
+					for (int row = firstRow; row<= lastRow; row++){
+						if (row >0)
+							for (int column = 0; column< getNumColumns(); column++)
+								if (isCellSelected(column, row) && !isCellSelected(column, row-1))
+									selectCell(column, row-1);
+					}
+					repaintAll();
+				}
+			}
+			if (anyRowNameSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int last = lastRowNameSelected();
+					selectRowNames(0, last);
+					repaintAll();
+				}
+				else {
+					for (int i = 1; i <getNumRows(); i++){
+						if (isRowNameSelected(i) && !isRowNameSelected(i-1))
+							selectRowName(i-1);
+					}
+					repaintAll();
+				}
+			}
+		}
+		else if (singleTableCellSelected()) {
+			Dimension sel = getFirstTableCellSelected();
+			if (sel.width >= -1 && sel.height >= 0 && sel.height - 1 < numRowsTotal && (sel.width >= 0 || sel.height > 0)) {
+				deselectCell(sel.width, sel.height);
+				selectCell(sel.width, sel.height - 1);
+				redrawCell(sel.width, sel.height);
+				redrawCell(sel.width, sel.height - 1);
+				setFocusedCell(sel.width, sel.height - 1);
+			}
+			else
+				MesquiteMessage.beep();
+
+		}
+	}
+
+	public void rightArrowPressed(String arguments) {
+		if (getEditing())
+			return;
+		if (StringUtil.foundIgnoreCase(arguments, "shift")){
+			if (anyColumnSelected()){ //accumulateSelection
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int first = firstColumnSelected();
+					selectColumns(first, getNumColumns()-1);
+					if (columnAssociable != null) 
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+				else {
+					for (int i = getNumColumns()-1; i >=0; i--){
+						if (isColumnSelected(i) && !isColumnSelected(i+1))
+							selectColumn(i+1);
+					}
+					if (columnAssociable != null) 
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+			}
+			if (anyCellSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){
+					for (int row = 0; row< getNumRows(); row++){
+						boolean doneRow = false;
+						for (int column = 0; column< getNumColumns() && !doneRow; column++)
+							if (isCellSelected(column, row)){
+								selectBlock(column, row, getNumColumns()-1, row);
+								doneRow = true;
+							}
+					}
+					repaintAll();
+				}
+				else {
+					int firstColumn = firstColumnWithSelectedCell();
+					int lastColumn = lastColumnWithSelectedCell();
+					for (int column = lastColumn; column>= firstColumn; column--){
+						for (int row = 0; row< getNumRows(); row++)
+							if (isCellSelected(column, row) && !isCellSelected(column+1, row))
+								selectCell(column+1, row);
+					}
+					repaintAll();
+				}
+			}
+			if (anyColumnNameSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int first = firstColumnNameSelected();
+					selectColumnNames(first, getNumColumns()-1);
+					repaintAll();
+				}
+				else {
+					for (int i = getNumColumns()-1; i >=0; i--){
+						if (isColumnNameSelected(i) && !isColumnNameSelected(i+1))
+							selectColumnName(i+1);
+					}
+					repaintAll();
+				}
+			}
+		}
+		else if (singleTableCellSelected()) {
+			Dimension sel = getFirstTableCellSelected();
+			if (sel.width >= -1 && sel.height >= -1) {
+				if (sel.width + 1 < numColumnsTotal) {
+					deselectCell(sel.width, sel.height);
+					selectCell(sel.width + 1, sel.height);
+					redrawCell(sel.width, sel.height);
+					redrawCell(sel.width + 1, sel.height);
+					setFocusedCell(sel.width + 1, sel.height);
+
+				}
+				else {
+					MesquiteMessage.beep();
+				}
+			}
+			else
+				MesquiteMessage.beep();
+
+		}
+	}
+
+	public void leftArrowPressed(String arguments) {
+		if (getEditing())
+			return;
+		if (StringUtil.foundIgnoreCase(arguments, "shift")){
+
+			if (anyColumnSelected()){ //accumulateSelection
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int last = lastColumnSelected();
+					selectColumns(0, last);
+					if (columnAssociable != null) 
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+				else {
+					for (int i = 1; i <getNumColumns(); i++){
+						if (isColumnSelected(i) && !isColumnSelected(i-1))
+							selectColumn(i-1);
+					}
+					if (columnAssociable != null) 
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					repaintAll();
+				}
+			}
+			if (anyCellSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){
+					for (int row = 0; row< getNumRows(); row++){
+						boolean doneRow = false;
+						for (int column = getNumColumns()-1; column>=0 && !doneRow; column--)
+							if (isCellSelected(column, row)){
+								selectBlock(0, row, column, row);
+								doneRow = true;
+							}
+					}
+					repaintAll();
+				}
+				else {
+					int firstColumn = firstColumnWithSelectedCell();
+					int lastColumn = lastColumnWithSelectedCell();
+					for (int column = firstColumn; column<= lastColumn; column++){
+						if (column >0)
+							for (int row = 0; row< getNumRows(); row++)
+								if (isCellSelected(column, row) && !isCellSelected(column-1, row))
+									selectCell(column-1, row);
+					}
+					repaintAll();
+				}
+			}
+			if (anyColumnNameSelected()){
+				if (StringUtil.foundIgnoreCase(arguments, "option")){ //select all the way to end
+					int last = lastColumnNameSelected();
+					selectColumnNames(0, last);
+					repaintAll();
+				}
+				else {
+					for (int i = 1; i <getNumColumns(); i++){
+						if (isColumnNameSelected(i) && !isColumnNameSelected(i-1))
+							selectColumnName(i-1);
+					}
+					repaintAll();
+				}
+			}
+		}
+		else if (singleTableCellSelected()) {
+			Dimension sel = getFirstTableCellSelected();
+			if (sel.width >= 0 && sel.height >= -1 && sel.width - 1 < numColumnsTotal && (sel.width > 0 || sel.height >= 0)) {
+				deselectCell(sel.width, sel.height);
+				selectCell(sel.width - 1, sel.height);
+				redrawCell(sel.width, sel.height);
+				redrawCell(sel.width - 1, sel.height);
+				setFocusedCell(sel.width - 1, sel.height);
+			}
+			else
+				MesquiteMessage.beep();
+
+		}
+	}
+
+	public void defocusCell() {
+		int oldFC = focusColumn;
+		int oldFR = focusRow;
+		focusColumn = -2;
+		focusRow = -2;
+		if (oldFR >= -1)
+			rowNames.redrawCell(-1, oldFR);
+		if (oldFC >= -1)
+			columnNames.redrawCell(oldFC, -1);
+		if (oldFR >= 0 && oldFC >= 0) {
+			matrix.redrawCell(oldFC, oldFR);
+		}
+	}
+
+	public void setFocusedCell(int column, int row) {
+		setFocusedCell(column, row, false);
+	}
+
+	public boolean isCellVisible(int column, int row){
+		if (column < -1 || row < -1)
+			return false;
+		if (column > getLastColumnVisible() || column < getFirstColumnVisible())
+			return false;
+		if (row > getLastRowVisible() || row < getFirstRowVisible())
+			return false;
+		return true;
+	}
+	public void setFocusedCell(int column, int row, boolean evenIfMultipleSelected) {
+		// can be overridden to respond to focus as in touch, edit etc. for explanation showing, but should call super.setFocusedCell(column, row);
+		defocusCell();
+		if (column < -1 || row < -1 || (!evenIfMultipleSelected && !singleTableCellSelected()))
+			return;
+		int count = 0;
+		while (count++ < 5 && (column > getLastColumnVisible() || column < getFirstColumnVisible())) { // iterate in case column widths make it tough to figure out
+			if (column > getLastColumnVisible()) {
+				int newFirst = getFirstColumnVisible() + (column - getLastColumnVisible()) + 1;
+				if (newFirst < 0)
+					newFirst = 0;
+				setFirstColumnVisible(newFirst, true);
+			}
+			else if (column < getFirstColumnVisible()) {
+				setFirstColumnVisible(column, true);
+			}
+		}
+		if (column < getFirstColumnVisible())
+			setFirstColumnVisible(column, true);
+
+		count = 0;
+		while (count++ < 5 && (row > getLastRowVisible() || row < getFirstRowVisible())) { // iterate in case row heights make it tough to figure out
+			if (row > getLastRowVisible()) {
+				int newFirst = getFirstRowVisible() + (row - getLastRowVisible()) + 1;
+				if (newFirst < 0)
+					newFirst = 0;
+				setFirstRowVisible(newFirst, true);
+			}
+			else if (row < getFirstRowVisible()) {
+				setFirstRowVisible(row, true);
+			}
+		}
+		if (row < getFirstRowVisible())
+			setFirstRowVisible(row, true);
+
+		focusColumn = column;
+		focusRow = row;
+		rowNames.redrawCell(-1, focusRow);
+		columnNames.redrawCell(focusColumn, -1);
+		if (focusRow >= 0 && focusColumn >= 0)
+			matrix.redrawCell(focusColumn, focusRow);
+	}
+
+	/* attempts to show cells from column through column B along row */
+	public void setFocusedSequence(int column, int columnB, int row) {
+		// can be overridden to respond to focus as in touch, edit etc. for explanation showing, but should call super.setFocusedCell(column, row);
+		defocusCell();
+		if (column < -1 || columnB < -1 || row < -1)
+			return;
+		if (columnB > getLastColumnVisible()) {
+			if (columnB - column == getNumColumnsVisible())
+				setFirstColumnVisible(column);
+			else if (columnB - column < getNumColumnsVisible())
+				setFirstColumnVisible(getFirstColumnVisible() + columnB - getLastColumnVisible());
+			else
+				setFirstColumnVisible(column);
+		}
+		setFocusedCell(column, row, true);
+	}
+
+	public int getTableWidth() {
+		return getBounds().width;
+	}
+
+	boolean constrainMaxAutoColumn = false;
+	public void setConstrainMaxAutoColumn(boolean c) {
+		constrainMaxAutoColumn = c;
+	}
+
+	public boolean getConstrainMaxAutoColumn() {
+		return constrainMaxAutoColumn;
+	}
+
+	public void setConstrainMaxAutoColumnNum(int c) {
+		contrainedMaxColumnNum = c;
+	}
+
+	public int getConstrainMaxAutoColumnNum() {
+		return contrainedMaxColumnNum;
+	}
+	boolean constrainMaxAutoRownames = false;
+	public void setConstrainMaxAutoRownames(boolean c) {
+		constrainMaxAutoRownames = c;
+	}
+
+	public boolean getConstrainMaxAutoRownames() {
+		return constrainMaxAutoRownames;
+	}
+
+	protected int contrainedMaxColumnNum = 3;
+
+	/* ................................................................................................................. */
+	public boolean autoSizeColumns(Graphics g) {
+
+		if (g == null || g.getFont() == null)
+			return false;
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		autoSizeRows(g);
+		String s = getCornerText();
+		boolean changed = false;
+		if (StringUtil.blank(s))
+			s = "GGGGG";
+		int max = fm.stringWidth(s);
+
+		int lengthString = 0;
+		int tableWIDTHpart = (getTableWidth() - getRowNamesWidth()) / (contrainedMaxColumnNum + 1);
+		int newCW = 0;
+		int current = 0;
+
+		// row names
+		if (!rowNamesWidthAdjusted){
+			for (int it = 0; it < getNumRows(); it++) {
+				s = getRowNameTextForDisplay(it);
+				lengthString = fm.stringWidth(s);
+				if (lengthString > max)
+					max = lengthString;
+			}
+			if (constrainMaxAutoRownames && max > tableWIDTHpart) // v. 1.01 e 81
+				max = tableWIDTHpart;
+			newCW = max + 2 + MesquiteModule.textEdgeCompensationHeight;
+			current = getRowNamesWidth();
+			if (newCW != current && (Math.abs(newCW - current) > 1)) {
+				setRowNamesWidth(newCW);
+				changed = true;
+			}
+		}
+		// other columns
+		max = fm.stringWidth("G");
+		for (int ic = 0; ic < getNumColumns(); ic++) {
+			if (!columnAdjusted(ic)) {
+
+				max = 6;
+				s = getColumnNameTextForDisplay(ic);
+				lengthString = fm.stringWidth(s);
+				if (lengthString > max)
+					max = lengthString;
+				for (int it = 0; it < getNumRows(); it++) {
+					s = getMatrixTextForDisplay(ic, it);
+					if (s != null) {
+						lengthString = fm.stringWidth(s);
+						if (lengthString > max)
+							max = lengthString;
+					}
+				}
+
+				if (constrainMaxAutoColumn && max > tableWIDTHpart)
+					max = tableWIDTHpart;
+				newCW = max + 2 + MesquiteModule.textEdgeCompensationHeight;
+				current = getColumnWidth(ic);
+				if (newCW != current && (Math.abs(newCW - current) > 1)) { // don't sweat small changes to avoid infinite loops
+					setColumnWidth(ic, newCW);
+					changed = true;
+				}
+			}
+		}
+		return changed;
+	}
+	public void autoSizeRows (Graphics g) {  
+		FontMetrics fm=g.getFontMetrics(g.getFont());
+		int h = fm.getMaxAscent()+ fm.getMaxDescent();
+		if (!thinRows.getValue()) h+= MesquiteModule.textEdgeCompensationHeight; //2 + MesquiteString.riseOffset;
+		setRowHeightsUniform(h);
+		if (!columnNames.isDiagonal())
+			setColumnNamesRowHeight(h);
+
+	}
+	/* ................................................................................................................. */
+	int maximumRowNamesWidth = 5000;
+	public void setMaximumRowNamesWidth(int m){
+		maximumRowNamesWidth = m;
+	}
+	/* ................................................................................................................. */
+	public boolean autoSizeRowNames(Graphics g) {
+		if (g == null || g.getFont() == null)
+			return false;
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		int h = fm.getMaxAscent() + fm.getMaxDescent() + MesquiteModule.textEdgeCompensationHeight; // 2 + MesquiteString.riseOffset;
+		boolean changed = false;
+		int max = 100;
+		String s = "    ";
+		// row names
+		int lengthString = 0;
+		for (int it = 0; it < getNumRows(); it++) {
+			s = getRowNameTextForDisplay(it);
+			if (!StringUtil.blank(s)) {
+				lengthString = fm.stringWidth(s);
+				if (lengthString > max)
+					max = lengthString;
+			}
+		}
+		if (max > maximumRowNamesWidth)
+			max = maximumRowNamesWidth;
+		int tableWIDTHpart = (getTableWidth() - getRowNamesWidth()) / (contrainedMaxColumnNum + 1);
+		if (constrainMaxAutoRownames && max > tableWIDTHpart) // v. 1.01 e 81
+			max = tableWIDTHpart;
+		int newCW = max + 10 + MesquiteModule.textEdgeCompensationHeight;
+		int current = getRowNamesWidth();
+		if (newCW > current && (Math.abs(newCW - current) > 1)) {
+			setRowNamesWidth(newCW);
+			changed = true;
+		}
+		return changed;
+	}
+	/* ................................................................................................................. */
+	private static final int NOMORE = 0;
+
+	private static final int TAB = 1;
+
+	private static final int LINE = 2;
+
+	private static final int TOKENTabBounded = 3;
+
+	private static final int TOKENReturnBounded = 4;
+
+	private static int goToNext(String s, MesquiteInteger pos) {
+		if (s == null || pos == null || pos.getValue() < -1 || pos.getValue() + 1 > s.length() - 1)
+			return NOMORE;
+		pos.increment();
+		int i = pos.getValue();
+		char c = s.charAt(i);
+		if (c == '\t')
+			return TAB;
+		if (c == '\n' || c == '\r') {
+			if (StringUtil.lineEnding().length() > 1)
+				pos.increment();
+			return LINE;
+		}
+
+		while (i < s.length() && !(c == '\n' || c == '\r' || c == '\t')) {
+			i++;
+			if (i < s.length())
+				c = s.charAt(i);
+			else
+				c = 0;
+		}
+		if (i >= s.length()) {
+			pos.setValue(i);
+			return TOKENReturnBounded;
+		}
+		if (c == '\n' || c == '\r') {
+			i--;
+			pos.setValue(i);
+			return TOKENReturnBounded;
+		}
+		pos.setValue(i);
+		return TOKENTabBounded;
+
+	}
+
+	public int[] getTabbedLines(String s){
+		return getTabbedLinesCount(s);
+	}
+	/* ................................................................................................................. */
+	public static int[] getTabbedLinesCount(String s) {
+		if (s == null)
+			return null;
+		int lines = 0;
+		int token;
+		boolean lastIsLine = true;
+		MesquiteInteger pos = new MesquiteInteger(-1);
+		while ((token = goToNext(s, pos)) != NOMORE) {
+			if (token == LINE) {
+				lines++;
+				lastIsLine = true;
+			}
+			else
+				lastIsLine = false;
+		}
+		if (!lastIsLine)
+			lines++;
+		int[] result = new int[lines];
+		int line = 0;
+		int item = 0;
+		int pending = 0;
+		pos.setValue(-1);
+		while ((token = goToNext(s, pos)) != NOMORE) {
+			if (token == LINE) {
+				item += pending;
+				if (item == 0)
+					item = 1;
+				result[line++] = item;
+				pending = 0;
+				item = 0;
+				lastIsLine = true;
+			}
+			else {
+				if (token == TOKENTabBounded || token == TAB) {
+					pending = 1;
+				}
+				else {
+					pending = 0;
+					if (token == TOKENReturnBounded)
+						lastIsLine = true;
+					else
+						lastIsLine = false;
+				}
+				item++;
+
+			}
+		}
+		if (lastIsLine && line < result.length)
+			result[line] = item;
+
+		return result;
+	}
+
+	/* ................................................................................................................. */
+	String getTabbedToken(String s, int which) {
+		if (s == null)
+			return null;
+		int count = -1;
+		int startOfToken = -1;
+		int endOfToken = -1;
+		for (int i = 0; i < s.length(); i++) {
+			if (isLineBreak(s, i)) {
+				while (i < s.length() && (isLineBreak(s, i)))
+					i++;
+				if (i < s.length()) {
+					count++;
+					if (count == which)
+						startOfToken = i;
+					while (i < s.length() && (s.charAt(i) != '\t') && !isLineBreak(s, i))
+						i++;
+					if (startOfToken >= 0) {
+						endOfToken = i;
+						return s.substring(startOfToken, endOfToken);
+					}
+					// i--;
+				}
+			}
+			else {
+				count++;
+				if (count == which)
+					startOfToken = i;
+				while (i < s.length() && (s.charAt(i) != '\t') && !isLineBreak(s, i))
+					i++;
+				if (startOfToken >= 0) {
+					endOfToken = i;
+					return s.substring(startOfToken, endOfToken);
+				}
+				// i--;
+			}
+		}
+		return null;
+	}
+
+	/* ................................................................................................................. */
+	// this is modified from getTabbedToken which explains its strange style
+	public static String getNextTabbedToken(String s, MesquiteInteger pos) {
+		if (s == null)
+			return null;
+		int which = 0;
+		int count = -1;
+		int startOfToken = -1;
+		int endOfToken = -1;
+		for (int i = pos.getValue(); i < s.length(); i++) {
+			count++;
+			if (count == which)
+				startOfToken = i;
+			while (i < s.length() && (s.charAt(i) != '\t') && !isLineBreak(s, i))
+				i++;
+
+			if (startOfToken >= 0) {
+				endOfToken = i;
+				pos.setValue(i + 1);
+				if (isLineBreak(s,i) && i+1<s.length() && isLineBreak(s, i+1) && s.charAt(i) != s.charAt(i+1) && StringUtil.lineEnding().length() > 1)
+					pos.increment();
+				return s.substring(startOfToken, endOfToken);
+			}
+		}
+		pos.setValue(s.length());
+		return null;
+	}
+
+	static boolean isLineBreak(String s, int index) {
+		if (s == null || index >= s.length() || index < 0)
+			return false;
+		char c = s.charAt(index);
+		return (c == '\n' || c == '\r');
+	}
+
+	/* ................................................................................................................. */
+	public MesquiteCommand getCopyCommand() {
+		return copyCommand;
+	}
+
+	public MesquiteCommand getCopyLiteralCommand() {
+		return copyLiteralCommand;
+	}
+
+	public MesquiteCommand getPasteCommand() {
+		return pasteCommand;
+	}
+
+	public MesquiteCommand getCutCommand() {
+		return cutCommand;
+	}
+
+	public MesquiteCommand getClearCommand() {
+		return clearCommand;
+	}
+
+	public MesquiteCommand getSelectAllCommand() {
+		return selectAllCommand;
+	}
+
+	/* ................................................................................................................. *
+	public void setHorizScrollVisible(boolean vis) {
+		horizScroll.setVisible(vis);
+	}
+
+	public void setVertScrollVisible(boolean vis) {
+		vertScroll.setVisible(vis);
+	}
+
+	/* ................................................................................................................. */
+	public int getLastRow() {
+		return numRowsTotal - 1;
+	}
+
+	/* ................................................................................................................. */
+	public int getLastColumn() {
+		return numColumnsTotal - 1;
+	}
+
+	/* ................................................................................................................. */
+	public int getMatrixWidth() {
+		return matrixWidth;
+	}
+
+	public int getMatrixHeight() {
+		return matrixHeight;
+	}
+
+	private synchronized void  printComponent(Graphics g, Panel c) {
+		int shiftX = c.getBounds().x;
+		int shiftY = c.getBounds().y;
+		g.translate(shiftX, shiftY);
+		c.print(g);
+		g.translate(-shiftX, -shiftY);
+	}
+
+	/* ............................................................................................................... */
+	public synchronized void printAll(Graphics g) {
+		cornerCell.paint(g);
+		printComponent(g, rowNames);
+		printComponent(g, columnNames);
+		printComponent(g, matrix);
+	}
+
+	/* ................................................................................................................. */
+	public void printTable(MesquitePrintJob pjob, MesquiteWindow window) {
+		if (pjob != null) {
+			pjob.printComponent(this, new Dimension(getTotalColumnWidth() + getRowNamesWidth(), getTotalRowHeight() + getColumnNamesRowHeight()), null);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * @author Peter Midford
+	 */
+	public synchronized void tableToPDF(MesquitePDFFile pdfFile, MesquiteWindow window, int fitToPage) {
+		if (pdfFile != null) {
+			printAll(pdfFile.getPDFGraphicsForComponent(this, totalDimension()));
+			pdfFile.end();
+		}
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * @author Peter Midford
+	 */
+	private Dimension totalDimension() {
+		return new Dimension(getTotalColumnWidth() + getRowNamesWidth() + 25, getTotalRowHeight() + getColumnNamesRowHeight() + 20);
+	}
+
+	/* ............................................................................................................... */
+	public boolean checkResetFont(Graphics g) { // ^^^
+		boolean doReset = false;
+		if (g != null) {
+			Font f = g.getFont();
+			if (f != null && f != oldF) {
+				FontMetrics fm = g.getFontMetrics(f);
+				if (fm != null) {
+					int height = fm.getHeight();
+					setGrabberSize(fm);
+					if (!columnNames.isDiagonal())
+						setColumnNamesRowHeight(height + MesquiteModule.textEdgeCompensationHeight);
+					for (int i = firstRowVisible; i < numRowsTotal; i++) {
+						if (rowHeights[i] < height + MesquiteModule.textEdgeCompensationHeight) {
+							setRowHeight(i, height + MesquiteModule.textEdgeCompensationHeight);
+							doReset = true;
+						}
+					}
+					oldF = f;
+				}
+				if (oldF != null)
+					boldFont = new Font(oldF.getName(), Font.BOLD, oldF.getSize());
+			}
+			if (boldFont == null)
+				boldFont = new Font(oldF.getName(), Font.BOLD, oldF.getSize());
+
+		}
+		return doReset;
+
+	}
+
+	/* ............................................................................................................... */
+	public void paint(Graphics g) { // ^^^
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		boolean resized = false;
+		if (autoRowNameWidth.getValue())
+			autoSizeRowNames(g);
+		if (checkResetFont(g)) {
+			if (autosizeColumns)
+				autoSizeColumns(g);
+			else{
+				autoSizeRowNames(g);
+				autoSizeRows(g);
+			}
+			repaintAll();
+		}
+		else if (autosizeColumns) {
+			resized = autoSizeColumns(g);
+		} else
+			autoSizeRows(g);
+		if (resized) {
+			MesquiteWindow.uncheckDoomed(this);
+			repaintAll();
+		}
+		else {
+			super.paint(g);
+			MesquiteWindow.uncheckDoomed(this);
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void update(Graphics g) {
+		paint(g);
+	}
+
+	public boolean flag = false;   //just in case
+	/* ............................................................................................................... */
+	/** repaints all components of the table */
+	public void repaintAll() {
+		// checkResetFont(getGraphics());
+		columnNames.repaint();
+		repaint();
+		rowNames.repaint();
+		cornerCell.repaint();
+		matrix.repaint();
+	}
+	/* ............................................................................................................... */
+	/** repaints all components of the table */
+	public void repaintCells(boolean repaintColumnNames) {
+		if (repaintColumnNames)
+			columnNames.repaint();
+		//repaint();
+		matrix.repaint();
+	}
+
+
+	/* ............................................................................................................... */
+	/** returns a tab delimited text version of the table */
+	public String getTextVersion() {
+		StringBuffer outputBuffer = new StringBuffer(getNumColumns() * getNumRows());
+		for (int column = 0; column < getNumColumns(); column++)
+			outputBuffer.append("\t" + columnNames.getText(column, -1));
+		outputBuffer.append("\n");
+		for (int row = 0; row < getNumRows(); row++) {
+			outputBuffer.append(rowNames.getText(-1, row));
+			for (int column = 0; column < getNumColumns(); column++)
+				outputBuffer.append("\t" + matrix.getText(column, row));
+			outputBuffer.append("\n");
+		}
+		return outputBuffer.toString();
+
+	}
+	public Color getColumnNameFillColor(int column, Color defaultFillColor, boolean focused, boolean selected, boolean dimmed, boolean editable){
+		Color color;
+		if (selected) {
+			color = Color.white;
+		}
+		else if (focused)
+			color = Color.lightGray;
+		else if (defaultFillColor!=null)
+			color = defaultFillColor;
+		else if (dimmed)
+			color = Color.lightGray;
+		else if (editable)
+			color = Color.white;
+		else
+			color = ColorDistribution.uneditable;
+		return color;
+	}
+	/* ............................................................................................................... */
+	/** returns color of row or number box. */
+	public Color getRCNumberBoxColor(boolean isRow, int number) {
+		//return ColorDistribution.medium[colorScheme];
+		return ColorTheme.getContentBackgroundPale();
+
+	}
+
+	/* ............................................................................................................... */
+	/** returns color of row or number box. */
+	public Color getRCNumberBoxDarkColor(boolean isRow, int number) {
+		//return ColorDistribution.dark[colorScheme];
+		return ColorTheme.getContentDarkElement();
+
+	}
+
+	/* ............................................................................................................... */
+	/** Draws any extra content of a columnNamesPanel */
+	public void drawColumnNamesPanelExtras(Graphics g, int left, int top, int width, int height) {
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Draws the shaded box that houses row or column numbers in a table. Can also be used to just draw a shaded box, even if no row or column numbers are to be drawn.
+	 */
+	public void drawRowColumnNumberBox(Graphics g, int number, boolean isRow, int left, int top, int width, int height) {
+		Color oldColor = g.getColor();
+		// g.setColor(Color.lightGray);
+		g.setColor(getRCNumberBoxColor(isRow, number));
+		g.fillRect(left, top, width, height);
+		if ((focusRow == number && isRow) || (focusColumn == number && !isRow))
+			GraphicsUtil.fillTransparentSelectionRectangle(g, left, top, width, height);
+		g.setColor(ColorDistribution.veryVeryLightGray);
+		int newTop;
+		if (isRow)
+			newTop = top;
+		else
+			newTop = top + 1;
+		int newLeft;
+		if (isRow)
+			newLeft = left + 1;
+		else
+			newLeft = left;
+		g.drawLine(newLeft, newTop, left + width - 1, newTop);
+		g.drawLine(newLeft, newTop, newLeft, top + height - 1);
+		// g.setColor(Color.darkGray);
+		g.setColor(getRCNumberBoxDarkColor(isRow, number));
+		g.drawLine(left, top + height, left + width, top + height);
+		g.drawLine(left + width, top + height, left + width, top);
+		g.setColor(oldColor);
+	}
+
+	/* ............................................................................................................... */
+	/** Draws the shaded box containing a row or column number in a table. */
+	public void drawRowColumnNumber(Graphics g, int number, boolean isRow, int left, int top, int width, int height) {
+		drawRowColumnNumberBox(g, number, isRow, left, top, width, height);
+		String s = "" + (number + 1); // +1 is added because internally the rows and columns are 0-based.
+		g.setClip(left, top, width, height);
+		FontMetrics fm = g.getFontMetrics();
+		int length = fm.stringWidth(s);
+		g.drawString(s, left + (width - length) / 2, top + height - (height - fm.getAscent() - fm.getDescent()) / 2 - fm.getDescent());
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the size of the grabberbars */
+	public void setGrabberSize() {
+		MesquiteWindow mw = MesquiteWindow.windowOfItem(this);
+		if (mw != null && mw.getFont() != null) {
+			FontMetrics f = getFontMetrics(mw.getFont());
+			setGrabberSize(f);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the size of the grabberbars */
+	public void setGrabberSize(FontMetrics fm) {
+		if (fm != null) {
+			if (showRowNumbers)
+				setRowGrabberWidth(fm.stringWidth("  " + numRowsTotal) + 4);
+			if (showColumnNumbers)
+				setColumnGrabberWidth(fm.getHeight() + 2);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether or not to show the row or column numbers */
+	public void setShowRCNumbers(boolean srn, boolean scn) {
+		showRowNumbers = srn;
+		showColumnNumbers = scn;
+		if (showRowNumbers)
+			setRowGrabberWidth(24);
+		if (showColumnNumbers)
+			setColumnGrabberWidth(14);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the overall size of the table in pixels, matching the window size. */
+	public void resetTableSize(boolean useFullWindowSize) {
+		if (useFullWindowSize) {
+			MesquiteWindow window = MesquiteWindow.windowOfItem(this);
+			if (window != null)
+				setSize(window.getWidth(), window.getHeight());
+		}
+		else {
+			setSize(getBounds().width, getBounds().height);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the overall size of the table in pixels. */
+	public void setSize(int totalWidth, int totalHeight) {
+		setGrabberSize();
+		matrixWidth = totalWidth - rowNamesWidth - 16 - rowGrabberWidth;
+		matrixHeight = totalHeight - 16 - columnNames.calcColumnNamesHeight();
+		resetComponentSizes();
+		super.setSize(totalWidth, totalHeight);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the overall size of the table in pixels. */
+	public void setBounds(int x, int y, int w, int h) {
+		setGrabberSize();
+		matrixWidth = w - rowNamesWidth - 16 - rowGrabberWidth;
+		matrixHeight = h - 16 - columnNames.calcColumnNamesHeight();
+		resetComponentSizes();
+		super.setBounds(x, y, w, h);
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the height of the columnNames Panel. */
+	// public int recalcColumnNamesHeight() {
+	// return columnNames.rowHeight(-1)*columnNames.getNumRows() + columnGrabberWidth;
+	// }
+	/* ............................................................................................................... */
+	/** Resets sizes of all components. */
+	public void resetComponentSizes() {
+		// columnNamesRowHeight=columnNames.calcColumnNamesHeight()-columnGrabberWidth;
+		rowNames.setSize(rowNamesWidth + rowGrabberWidth, matrixHeight);
+		rowNames.setLocation(0, columnNames.calcColumnNamesHeight());
+		rowNames.setTableUnitSize(rowNamesWidth + rowGrabberWidth, matrixHeight);
+		columnNames.setSize(matrixWidth, columnNames.calcColumnNamesHeight());
+		columnNames.setLocation(rowNamesWidth + rowGrabberWidth, 0);
+		columnNames.setTableUnitSize(matrixWidth, columnNames.calcColumnNamesHeight());
+		matrix.setSize(matrixWidth, matrixHeight);
+		matrix.setLocation(rowNamesWidth + rowGrabberWidth, columnNames.calcColumnNamesHeight());
+		matrix.setTableUnitSize(matrixWidth, matrixHeight);
+		horizScroll.setBounds(rowNamesWidth + rowGrabberWidth, matrixHeight + columnNames.calcColumnNamesHeight(), matrixWidth, 16);
+		vertScroll.setBounds(matrixWidth + rowNamesWidth + rowGrabberWidth, columnNames.calcColumnNamesHeight(), 16, matrixHeight);
+		controlStrip.setBounds(0, matrixHeight + columnNames.calcColumnNamesHeight(), rowNamesWidth + rowGrabberWidth, 16);
+		cornerCell.setLocation(0, 0);
+		cornerCell.setSize(rowNamesWidth - 1 + rowGrabberWidth, columnNames.calcColumnNamesHeight()); // -1, -1
+		cornerCell.setTableUnitSize(rowNamesWidth - 1 + rowGrabberWidth, columnNames.calcColumnNamesHeight());
+		resetNumColumnsVisible();
+		resetNumRowsVisible();
+	}
+
+	/* ............................................................................................................... */
+	/** Deletes the given column (but doesn't call for repaint) */
+	public void deleteColumn(int column) {
+		if (!columnLegal(column))
+			return;
+		if (column < numColumnsTotal && column >= 0) {
+			int[] newColumnWidths = new int[numColumnsTotal - 1];
+			for (int c = 0; c < numColumnsTotal - 1; c++)
+				if (c > column)
+					newColumnWidths[c] = columnWidths[c + 1];
+				else
+					newColumnWidths[c] = columnWidths[c];
+
+			columnWidths = newColumnWidths;
+
+			numColumnsTotal = numColumnsTotal - 1;
+			for (int i = 0; i < numSelectTypes; i++) {
+				columnsSelected[i] = new Bits(numColumnsTotal);
+				cellsSelected[i] = new Bits((numRowsTotal) * (numColumnsTotal));
+				columnNamesSelected[i] = new Bits(numColumnsTotal);
+			}
+			if (firstColumnVisible >= numColumnsTotal || firstColumnVisible < 0)
+				firstColumnVisible = 0; 
+			if (horizScroll != null) {
+				horizScroll.setValue(firstColumnVisible);
+				horizScroll.setMaximum(numColumnsTotal);
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void moveColumns(int starting, int num, int justAfter) {
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the number of rows TOTAL (not just visible) */
+	public void setNumRows(int rows) {
+		if (rows < 0)
+			return;
+		int[] newRowHeights = new int[rows];
+		for (int r = 0; r < numRowsTotal && r < rows; r++)
+			newRowHeights[r] = rowHeights[r];
+		int defHeight = baseRowHeight;
+
+		if (rowHeights != null && rowHeights.length > 0)
+			defHeight = rowHeights[0];
+		if (rows > numRowsTotal)
+			for (int r = numRowsTotal; r < rows; r++)
+				newRowHeights[r] = defHeight;
+		numRowsTotal = rows;
+		rowHeights = newRowHeights;
+		for (int i = 0; i < numSelectTypes; i++) {
+			if (rowsSelected[i] == null)
+				rowsSelected[i] = new Bits(numRowsTotal);
+			else
+				rowsSelected[i].resetSize(numRowsTotal);
+
+			if (cellsSelected[i] == null)
+				cellsSelected[i] = new Bits(numRowsTotal * numColumnsTotal);
+			else {
+				cellsSelected[i].resetSize(numRowsTotal * numColumnsTotal);
+				cellsSelected[i].clearAllBits();
+			}
+
+			if (rowNamesSelected[i] == null)
+				rowNamesSelected[i] = new Bits(numRowsTotal);
+			else
+				rowNamesSelected[i].resetSize(numRowsTotal);
+		}
+		if (rowWidthsAdjusted != null)
+			rowWidthsAdjusted.resetSize(numRowsTotal);
+		if (firstRowVisible >= numRowsTotal || firstRowVisible < 0)
+			firstRowVisible = 0;
+		if (vertScroll != null) {
+			vertScroll.setValue(firstRowVisible);
+			vertScroll.setMaximum(numRowsTotal);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Inserts num columns just after "starting". Calls setNumColumns */
+	public void insertColumns(int starting, int num) {
+		int oldNumColumns = numColumnsTotal;
+		setNumColumns(numColumnsTotal + num);
+		if (starting < oldNumColumns - 2) {
+			for (int c = columnWidths.length - 1; c > starting + num; c--)
+				columnWidths[c] = columnWidths[c - num];
+			for (int c = starting + 1; c < starting + num + 1; c++)
+				columnWidths[c] = baseColumnWidth;
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the number of columns TOTAL (not just visible) */
+	public void setNumColumns(int columns) {
+		if (columns < 0)
+			return;
+		if (numColumnsTotal == 0) {
+			columnWidths = new int[columns];
+			numColumnsTotal = columns;
+			setColumnWidthsUniform(baseColumnWidth);
+			for (int i = 0; i < numSelectTypes; i++) {
+				columnsSelected[i] = new Bits(numColumnsTotal);
+				cellsSelected[i] = new Bits((numRowsTotal) * (numColumnsTotal));
+				columnNamesSelected[i] = new Bits(numColumnsTotal);
+			}
+			horizScroll.setValue(0);
+			horizScroll.setMaximum(numColumnsTotal);
+		}
+		else if (columns != numColumnsTotal) {
+			int[] newColumnWidths = new int[columns];
+			for (int c = 0; c < columnWidths.length && c < newColumnWidths.length; c++)
+				newColumnWidths[c] = columnWidths[c];
+			int defWidth = baseColumnWidth;
+			if (columnWidths != null && columnWidths.length > 0)
+				defWidth = columnWidths[0];
+			if (columns > numColumnsTotal)
+				for (int c = numColumnsTotal; c < columns; c++)
+					newColumnWidths[c] = defWidth;
+			columnWidths = newColumnWidths;
+
+			for (int i = 0; i < numSelectTypes; i++) {
+				if (columnsSelected[i] == null)
+					columnsSelected[i] = new Bits(columns);
+				else
+					columnsSelected[i].resetSize(columns);
+				if (columnNamesSelected[i] == null)
+					columnNamesSelected[i] = new Bits(columns);
+				else
+					columnNamesSelected[i].resetSize(columns);
+				if (cellsSelected[i] == null)
+					cellsSelected[i] = new Bits((numRowsTotal) * (columns));
+				else {
+					cellsSelected[i].resetSize(numRowsTotal * columns);
+					cellsSelected[i].clearAllBits();
+				}
+			}
+			if (columnWidthsAdjusted != null)
+				columnWidthsAdjusted.resetSize(columns);
+			numColumnsTotal = columns;
+			if (firstColumnVisible >= columns || firstColumnVisible < 0)
+				firstColumnVisible = 0;
+			if (horizScroll != null) {
+				horizScroll.setValue(firstColumnVisible);
+				horizScroll.setMaximum(numColumnsTotal);
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of rows TOTAL (not just visible) */
+	public int getNumRows() {
+		return numRowsTotal;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of columns TOTAL (not just visible) */
+	public int getNumColumns() {
+		return numColumnsTotal;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Calculates the number of visible columns, rounded up to the nearest whole number. Also sets the value of the lastColumnVisible, and sets the appropriate page increment for the horizontal scroll bar.
+	 */
+	public void resetNumColumnsVisible() {
+		numColumnsVisible = numColumnsTotal - firstColumnVisible + 1;
+		int sum = 0;
+		for (int c = firstColumnVisible; c < numColumnsTotal && c < columnWidths.length; c++) {
+			sum += columnWidths[c];
+			if (sum >= matrixWidth) {
+				break;
+			}
+			numColumnsVisible = (c - firstColumnVisible + 1); // had been +1 but last column may not be entirely visible
+		}
+		if (numColumnsVisible < 2)
+			horizScroll.setBlockIncrement(1);
+		else
+			horizScroll.setBlockIncrement(numColumnsVisible - 1);
+		lastColumnVisible = firstColumnVisible + numColumnsVisible - 1;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Calculates the number of visible rows, rounded up to the nearest whole number. Also sets the value of the lastRowVisible, and sets the appropriate page increment for the vertical scroll bar.
+	 */
+	public void resetNumRowsVisible() {
+		numRowsVisible = (numRowsTotal - firstRowVisible + 1);
+		int sum = 0;
+		int numRows = 0;
+		for (int r = firstRowVisible; r < numRowsTotal && r <rowHeights.length; r++) {
+			sum += rowHeights[r];
+			numRows++;
+			if (sum >= matrixHeight) {
+				numRowsVisible = (r - firstRowVisible + 1);
+				break;
+			}
+		}
+		int verticalScrollPageIncrement = numRowsVisible - 1;
+		if (sum>0) {
+			double avgRowHeight = (1.0*sum)/numRows;
+			int numRowsPossiblyVisible = (int)(matrixHeight/avgRowHeight)-1;
+			if (numRowsPossiblyVisible>verticalScrollPageIncrement)
+				verticalScrollPageIncrement = numRowsPossiblyVisible;
+		}
+		
+		//vertScroll.setBlockIncrement(getNumRows()-1);
+		if (numRowsTotal < 2)
+			vertScroll.setBlockIncrement(1);
+		else
+			vertScroll.setBlockIncrement(verticalScrollPageIncrement);  //DRM  14 july 14: changed this so that it did full page scrolls
+
+		lastRowVisible = firstRowVisible + numRowsVisible - 1;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of visible columns. Rounded up to the nearest whole number. */
+	public int getNumColumnsVisible() {
+		return numColumnsVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of visible rows. Rounded up to the nearest whole number. */
+	public int getNumRowsVisible() {
+		return numRowsVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of the last visible column. */
+	public int getLastColumnVisible() {
+		return lastColumnVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the number of the last visible row. */
+	public int getLastRowVisible() {
+		return lastRowVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the height of rows TOTAL (not just visible) */
+	public int getTotalRowHeight() {
+		int sum = 0;
+		for (int r = 0; r < numRowsTotal; r++)
+			sum += rowHeights[r];
+		return sum;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets the width of columns TOTAL (not just visible) */
+	public int getTotalColumnWidth() {
+		int sum = 0;
+		for (int c = 0; c < numColumnsTotal; c++)
+			sum += columnWidths[c];
+		return sum;
+	}
+
+	/* ............................................................................................................... */
+	/** Returns the base column width */
+	public int getColumnWidthsUniform() {
+		return baseColumnWidth;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets all column widths to be of uniform width, with given width */
+	public void setColumnWidthsUniform(int width) {
+		baseColumnWidth = width;
+		for (int c = 0; c < numColumnsTotal; c++)
+			columnWidths[c] = width;
+		columnWidthsAdjusted.clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** Sets all row heights to be of uniform height, with given height */
+	public void setRowHeightsUniform(int height) {
+		baseRowHeight = height;
+		for (int r = 0; r < numRowsTotal; r++)
+			rowHeights[r] = height;
+		rowWidthsAdjusted.clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	public int getMinColumnWidth() {
+		return 8;
+	}
+
+	/* ............................................................................................................... */
+	public int getMaxColumnWidth() {
+		return 300;
+	}
+
+	/* ............................................................................................................... */
+	/** set columnwidths according to given array */
+	public void setColumnWidths(int[] widths) {
+		for (int c = 0; c < numColumnsTotal && c < widths.length; c++)
+			columnWidths[c] = widths[c];
+		columnWidthsAdjusted.clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** set rowheights according to given array */
+	public void setRowHeights(int[] heights) {
+		for (int r = 0; r < numRowsTotal && r < heights.length; r++)
+			rowHeights[r] = heights[r];
+		rowWidthsAdjusted.clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** Sets width of given column. */
+	public void setColumnWidth(int column, int width) {
+		if (!columnLegal(column))
+			return;
+		columnWidths[column] = width;
+		columnWidthsAdjusted.clearBit(column);
+	}
+	/* ............................................................................................................... */
+	/** Sets width of given column. */
+	public void setColumnWidth(int column, int width, boolean treatAsAdjusted) {
+		if (!columnLegal(column))
+			return;
+		columnWidths[column] = width;
+		if (treatAsAdjusted)
+			columnWidthsAdjusted.setBit(column);
+		else
+			columnWidthsAdjusted.clearBit(column);
+
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether the column width has been adjusted */
+	public boolean columnAdjusted(int column) {
+		if (!columnLegal(column))
+			return false;
+		return columnWidthsAdjusted.isBitOn(column);
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether the row width has been adjusted */
+	public boolean rowAdjusted(int row) {
+		if (!rowLegal(row))
+			return false;
+		return rowWidthsAdjusted.isBitOn(row);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets height of given row. */
+	public void setRowHeight(int row, int height) {
+		if (!rowLegal(row))
+			return;
+		rowHeights[row] = height;
+		rowWidthsAdjusted.clearBit(row);
+	}
+
+	/* ............................................................................................................... */
+	/** Gets width of given column. */
+	public int getColumnWidth(int column) {
+		if (columnLegal(column))
+			return columnWidths[column];
+		else
+			return 0;
+	}
+
+	/* ............................................................................................................... */
+	/** Gets height of given row. */
+	public int getRowHeight(int row) {
+		if (rowLegal(row))
+			return rowHeights[row];
+		else
+			return 0;
+	}
+
+	public int getColumnX(int column) {
+		int lineX = 0;
+		if (column == firstColumnVisible-1)
+			return 0;
+		for (int c=firstColumnVisible; (c<numColumnsTotal) && c<lastColumnVisible; c++) {
+			lineX += columnWidths[c];
+			if (column==c)
+				return lineX;
+		}
+		return MesquiteInteger.unassigned;
+
+	}
+	public int getRowY(int row) {
+		int lineY = 0;
+		if (row == firstRowVisible-1)
+			return 0;
+		for (int c=firstRowVisible; (c<numRowsTotal) && c<lastRowVisible; c++) {
+			lineY += rowHeights[c];
+			if (row==c)
+				return lineY;
+		}
+		return MesquiteInteger.unassigned;
+
+	}
+	/* ............................................................................................................... */
+	/** Sets height of column names. */
+	public void setColumnNamesRowHeight(int h) {
+		int oldCNRH = columnNamesRowHeight;
+		columnNamesRowHeight = h;
+		columnNames.setRowHeight(h);
+		columnNames.setHeight();
+		int oldMatrixHeight = matrixHeight;
+		matrixHeight = getHeight() - 16 - columnNames.calcColumnNamesHeight();
+		if (oldMatrixHeight!=matrixHeight || oldCNRH != columnNamesRowHeight)
+			resetComponentSizes();
+		// cornerCell.setSize(cornerCell.getBounds().width, height+columnGrabberWidth);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets width of row names. */
+	public void setRowNamesWidth(int width) {
+		rowNamesWidth = width;
+		rowNames.setWidth(width + rowGrabberWidth);
+		cornerCell.setSize(width + rowGrabberWidth - 1, cornerCell.getBounds().height);
+		matrixWidth = getTableWidth() - rowNamesWidth - 16 - rowGrabberWidth;
+		resetComponentSizes();
+	}
+
+	/* ............................................................................................................... */
+	/** Sets the message in the control strip at lower left of table. */
+	public void setMessage(String message) {
+		controlStrip.setMessage(message);
+	}
+
+	/* ............................................................................................................... */
+	/** Adds a button to the control strip at lower left of table. */
+	public void addControlButton(MesquiteButton b) {
+		controlStrip.addButton(b);
+	}
+
+	/* ............................................................................................................... */
+	/** Removes a button from the control strip at lower left of table. */
+	public void removeControlButton(MesquiteButton b) {
+		controlStrip.removeButton(b);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether or not different the message panel is visible. */
+	public void add(boolean vis) {
+		controlStrip.setVisible(vis);
+	}
+
+	/* ............................................................................................................... */
+	/** set color of backgrond of column names */
+	public void setColumnNamesColor(Color c) {
+		columnNames.setFillColor(c);
+	}
+
+	/* ............................................................................................................... */
+	/** set color of backgrond of column names */
+	public void setRowNamesColor(Color c) {
+		rowNames.setFillColor(c);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether or not different parts of table are editable. */
+	public void setAutoEditable(boolean cells, boolean rowNames, boolean columnNames, boolean corner) {
+		cellsAutoEditable = cells;
+		rowNamesAutoEditable = rowNames;
+		columnNamesAutoEditable = columnNames;
+		cornerAutoEditable = corner;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether or not different parts of table are editable. */
+	public void setEditable(boolean cellsE, boolean rowNamesE, boolean columnNamesE, boolean cornerE) {
+		cellsEditable = cellsE;
+		// matrix.setFillColor(editColor(cellsEditable));
+		rowNamesEditable = rowNamesE;
+		// rowNames.setFillColor(editColor(rowNamesEditable));
+		columnNamesEditable = columnNamesE;
+		// columnNames.setFillColor(editColor(columnNamesEditable));
+		cornerEditable = cornerE;
+		if (cornerE)
+			cornerCell.setBackground(Color.white);
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not cells of table are editable. */
+	public boolean getCellsAutoEditable() {
+		return cellsAutoEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not row names of table are editable. */
+	public boolean getRowNamesAutoEditable() {
+		return rowNamesAutoEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not column names of table are auto- editable. */
+	public boolean getColumnNamesAutoEditable() {
+		return columnNamesAutoEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not corner cell of table is editable. */
+	public boolean getCornerAutoEditable() {
+		return cornerAutoEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not cells of table are editable. */
+	public boolean getCellsEditable() {
+		return cellsEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not a cell of table is editable. */
+	public boolean isCellEditable(int column, int row) {
+		if (!columnLegal(column) || !rowLegal(row))
+			return false;
+		return cellsEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not a cell of table is being edited. */
+	public boolean isEditing(int column, int row) {
+		if (column < 0 && row < 0)
+			return false;
+		if (column == -1 && rowNames.getEditing())
+			return rowNames.getEditField().getRow() == row;
+		if (row == -1 && columnNames.getEditing())
+			return columnNames.getEditField().getColumn() == column;
+		return (matrix.getEditing() && matrix.getEditField().getRow() == row && matrix.getEditField().getColumn() == column);
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not a row name of table is editable. */
+	public boolean isRowNameEditable(int row) {
+		if (!rowLegal(row))
+			return false;
+		return rowNamesEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not a column name of table is editable. */
+	public boolean isColumnNameEditable(int column) {
+		if (!columnLegal(column))
+			return false;
+		return columnNamesEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not corner cell of table is editable. */
+	public boolean getCornerEditable() {
+		return cornerEditable;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether or not different parts of table are selectable. */
+	public void setSelectable(boolean cells, boolean rows, boolean columns, boolean rowNames, boolean columnNames, boolean corner) {
+		cellsSelectable = cells;
+		rowsSelectable = rows;
+		columnsSelectable = columns;
+		rowNamesSelectable = rowNames;
+		columnNamesSelectable = columnNames;
+		cornerSelectable = corner;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets user-adjust parameters of rows and columns. */
+	public void setUserAdjust(int rowsAdjust, int columnsAdjust) {
+		userAdjustColumn = columnsAdjust;
+		userAdjustRow = rowsAdjust;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets user-move permission of rows and columns. */
+	public void setUserMove(boolean rowsMove, boolean columnsMove) {
+		userMoveColumn = columnsMove;
+		userMoveRow = rowsMove;
+	}
+
+	/* ............................................................................................................... */
+	public EditorPanel getColumnNamesPanel() {
+		return columnNames;
+	}
+
+	/* ............................................................................................................... */
+	public EditorPanel getRowNamesPanel() {
+		return rowNames;
+	}
+
+	/* ............................................................................................................... */
+	public EditorPanel getMatrixPanel() {
+		return matrix;
+	}
+
+	/* ............................................................................................................... */
+	public MesquitePanel getCornerPanel() {
+		return cornerCell;
+	}
+
+	/* ............................................................................................................... */
+	public TableScroll getVerticalScroll() {
+		return vertScroll;
+	}
+
+	/* ............................................................................................................... */
+	public TableScroll getHorizontalScroll() {
+		return horizScroll;
+	}
+
+	/* ............................................................................................................... */
+	public int getLeftOfColumn(int column) {
+		return startOfColumn(column);
+	}
+
+	/* ............................................................................................................... */
+	public int startOfColumn(int column) {
+
+		if (column<firstColumnVisible)
+			return -1;
+		else if (column>firstColumnVisible + numColumnsTotal || column>=numColumnsTotal)
+			return -1;
+		else {
+			int lineX = 0;
+			//	if (tb.showRowGrabbers)
+			//		lineX = tb.getRowGrabberWidth();
+			for (int c=firstColumnVisible; (c<column); c++) {
+				lineX += columnWidths[c];
+			}
+			return lineX;
+		}
+	}
+
+
+	/* ............................................................................................................... */
+	public int getColumnNamesRowHeight() {
+		return columnNames.rowHeight(-1); // (columnNames.getBounds().height);
+	}
+
+	/* ............................................................................................................... */
+	public int getTopOfRow(int row) {
+		return rowNames.startOfRow(row);
+	}
+
+	public int getRowNamesWidth() {
+		return rowNamesWidth; // (rowNames.getBounds().width);
+	}
+
+	/* ............................................................................................................... */
+	/** returns the current Hand cursor for dragging columns, etc. */
+	public Cursor getHandCursor() {
+		return handCursor;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the current E resize cursor for widening columns, etc. */
+	public Cursor getEResizeCursor() {
+		return eastResizeCursor;
+	}
+	/* ............................................................................................................... */
+	/** returns the current N resize cursor for deepening column names, etc. */
+	public Cursor getNResizeCursor() {
+		return northResizeCursor;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the current mode for user-adjust of columns */
+	public int getUserAdjustColumn() {
+		return userAdjustColumn;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the current mode for user-adjust of rows */
+	public int getUserAdjustRow() {
+		return userAdjustRow;
+	}
+
+	/* @@@............................................................................................................... */
+	/** returns the current permission for user-move of columns */
+	public boolean getUserMoveColumn() {
+		return userMoveColumn;
+	}
+
+	/* @@@............................................................................................................... */
+	/** returns the current permission for user-move of rows */
+	public boolean getUserMoveRow() {
+		return userMoveRow;
+	}
+
+	/* ............................................................................................................... */
+	/** Instantly forces a draw of column to show it as blank */
+	public void blankColumn(int column) {
+		if (!columnLegal(column))
+			return;
+		for (int r = firstRowVisible; r < getNumRows(); r++)
+			// TODO: this and similar places (e.g. redrawMatrix) need to use getNumRowsVisible instead
+			matrix.blankCell(column, r);
+	}
+
+	/* ............................................................................................................... */
+	/** Instantly forces a draw of row to show it as blank */
+	public void blankRow(int row) {
+		if (!rowLegal(row))
+			return;
+		for (int c = firstColumnVisible; c < getNumColumns(); c++)
+			matrix.blankCell(c, row);
+	}
+
+	/* ............................................................................................................... */
+	/** Instantly forces a draw of row to show it as blank */
+	public void blankCell(int column, int row) {
+		if (!columnLegal(column) || !rowLegal(row))
+			return;
+		matrix.blankCell(column, row);
+	}
+
+	/* ............................................................................................................... */
+	/** sets whether filling of rectangles is done in quick way (whole matrix or blocks at once). In this case, subclass of table has to take responsiblity for clip issues in matrixpanel */
+	public void setQuickMode(boolean q) {
+		quickMode = q;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether filling of rectangles is done in quick way (whole matrix or blocks at once). In this case, subclass of table has to take responsiblity for clip issues in matrixpanel */
+	public boolean useQuickMode() {
+		return quickMode;
+	}
+
+	/* ............................................................................................................... */
+	/** redraws visible part of matrix */
+	public void redrawMatrix() {
+		redrawBlock(firstColumnVisible, firstRowVisible, getNumColumns(), getNumRows());
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) all column names */
+	public void redrawColumnNames() {
+		for (int c = firstColumnVisible; c < getNumColumns(); c++)
+			redrawColumnName(c);
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) all row names */
+	public void redrawRowNames() {
+		for (int c = firstRowVisible; c < getNumRows(); c++)
+			redrawRowName(c);
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) the indicated row name */
+	public void redrawRowName(int row) {
+		if (rowLegal(row) && showRowNames) {
+			Graphics g = rowNames.getGraphics();
+			if (g == null)
+				return;
+			rowNames.redrawName(g, row);
+			g.dispose();
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) the indicated column name */
+	public void redrawColumnName(int column) {
+		if (columnLegal(column)) {
+			Graphics g = columnNames.getGraphics();
+			if (g == null)
+				return;
+			columnNames.redrawName(g, column);
+			g.dispose();
+		}
+	}
+
+	// public MesquiteTimer rCellTimer = new MesquiteTimer();
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) the indicated cell */
+	public void redrawCell(int column, int row) {
+		if (column == -1)
+			redrawRowName(row);
+		else if (row == -1)
+			redrawColumnName(column);
+		else {
+			Graphics g = matrix.getGraphics();
+			if (g == null)
+				return;
+			redrawCell(column, row, g);
+			g.dispose();
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) the indicated cell */
+	public void redrawCell(int column, int row, Graphics g) {
+		if (columnLegal(column) && rowLegal(row)) {
+			matrix.redrawCell(g, column, row);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw (directly, without repaint()) the indicated cell, offset from its usual place */
+	public void redrawCellOffset(int column, int row, int offsetColumn, int offsetRow, Graphics g) {
+		if (columnLegal(column) && rowLegal(row)) {
+			matrix.redrawCellOffset(g, column, row, offsetColumn, offsetRow);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw block of cells temporarily offset from. */
+	// draws cell appearing at column, row, but with contents for cell column+offsetColumn, row+offsetRow. Used with non-zero offsets for quick draw during manual sequence alignment
+	public void redrawBlockOffset(int firstColumn, int firstRow, int lastColumn, int lastRow, int offsetColumn, int offsetRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++)
+				if (i < getNumColumns() && j < getNumRows())
+					redrawCellOffset(i, j, offsetColumn, offsetRow, g);
+		g.dispose();
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw block of cells. */
+	public void redrawBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++)
+				if (i < getNumColumns() && j < getNumRows())
+					redrawCell(i, j, g);
+		g.dispose();
+	}
+	/* ............................................................................................................... */
+	/** Redraw block of cells. */
+	public void redrawBlock(int firstColumn, int lastColumn, Bits whichRows) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || whichRows==null)
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int i = c1; i <= c2; i++)
+			for (int j = 0; j <= numRowsTotal; j++)
+				if (whichRows.isBitOn(j) && i < getNumColumns() && j < getNumRows())
+					redrawCell(i, j, g);
+		g.dispose();
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw block of cells blank. */
+	public void redrawBlockBlank(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++)
+				if (i < getNumColumns() && j < getNumRows())
+					matrix.blankCell(i, j, g);
+		g.dispose();
+	}
+
+	/* ............................................................................................................... */
+	/** determines in cell in in the intersection of two blocks. */
+	public boolean cellInIntersectionOfBlocks(int column, int row, int firstColumn, int newFirstColumn, int firstRow, int newFirstRow, int lastColumn, int newLastColumn, int lastRow, int newLastRow) {
+		if (!columnLegal(column) || !rowLegal(row) || !columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow) || !columnLegal(newFirstColumn) || !columnLegal(newLastColumn) || !rowLegal(newFirstRow) || !rowLegal(newLastRow))
+			return false;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		int nc1 = MesquiteInteger.minimum(newFirstColumn, newLastColumn);
+		int nc2 = MesquiteInteger.maximum(newFirstColumn, newLastColumn);
+		int nr1 = MesquiteInteger.minimum(newFirstRow, newLastRow);
+		int nr2 = MesquiteInteger.maximum(newFirstRow, newLastRow);
+
+		return (column >= c1) && (column <= c2) && (column >= nc1) && (column <= nc2) && (row >= r1) && (row <= r2) && (row >= nr1) && (row <= nr2);
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw block of cells that aren't in the intersection of two blocks. */
+	public void redrawDifferenceBlock(int firstColumn, int newFirstColumn, int firstRow, int newFirstRow, int lastColumn, int newLastColumn, int lastRow, int newLastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow) || !columnLegal(newFirstColumn) || !columnLegal(newLastColumn) || !rowLegal(newFirstRow) || !rowLegal(newLastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn, newFirstColumn, newLastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn, newFirstColumn, newLastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow, newFirstRow, newLastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow, newFirstRow, newLastRow);
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++)
+				if ((!cellInIntersectionOfBlocks(i, j, firstColumn, newFirstColumn, firstRow, newFirstRow, lastColumn, newLastColumn, lastRow, newLastRow)) && i < getNumColumns() && j < getNumRows())
+					redrawCell(i, j, g);
+		g.dispose();
+	}
+
+	/* ............................................................................................................... */
+	/** Redraw block of cells that bound selection. */
+	public void redrawSelectedBlock() {
+		if (anyRowSelected()) {
+			repaintAll();
+		}
+		if (anyColumnSelected()) {
+			repaintAll();
+		}
+		if (anyCellSelected())
+			redrawBlock(firstColumnWithSelectedCell(), firstRowWithSelectedCell(), lastColumnWithSelectedCell(), firstColumnWithSelectedCell());
+	}
+
+	/* ............................................................................................................... */
+	/** This doesnt' seem ever to get called! */
+	public void redrawColumn(int column) {
+		MesquiteMessage.warnProgrammer("draw column");
+		if (columnLegal(column)) {
+			MesquiteMessage.warnProgrammer("draw column, column legal");
+			redrawColumnName(column);
+			Graphics g = matrix.getGraphics();
+			if (g == null)
+				return;
+			for (int i = firstRowVisible; i <= lastRowVisible; i++)
+				redrawCell(column, i, g);
+			g.dispose();
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** ���� */
+	public void redrawColumns(int firstColumn, int lastColumn) {
+		for (int column = firstColumn; column <= lastColumn; column++)
+			redrawColumn(column);
+	}
+
+	/* ............................................................................................................... */
+	/** ���� */
+	public void redrawRows(int firstRow, int lastRow) {
+		System.out.println("redraw rows not working yet");
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Draws text into the corner cell. Passed is the graphics context, and the rectangle framing the cell. Must be overridden in subclasses to fill in corner cell appropriately.
+	 */
+	public void drawCornerCell(Graphics g, int x, int y, int w, int h) {
+		cornerCell.redrawName(g);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Draws cell of matrix of given column and row. Must be overridden in subclasses to fill in matrix cell appropriately.  Called only if useString is false for this cell.
+	 */
+	public void drawMatrixCell(Graphics g, int x, int y, int w, int h, int column, int row, boolean selected) {
+		// g.drawString(Integer.toString(row + column), x+2, y+h-2);
+	}
+	/* ............................................................................................................... */
+	//to be overridden to change color; works only for MatrixPanel, and only when useString & overriding permit it
+	public Color getBackgroundColor(int column, int row, boolean selected){
+		return null;
+	}
+	/* ............................................................................................................... */
+	//to be overridden to change color; works only for MatrixPanel, and only when useString & overriding permit it
+	public Color getTextColor(int column, int row, boolean selected){
+		return null;
+	}
+	/* ............................................................................................................... */
+	/**
+	 * ���� HAVE THIS BY COLUMNS; ALSO HAVE COLUMN NAMES AND ROW NAMES JUSTIFYABLE
+	 */
+	public int getJustification() {
+		return justification;
+	}
+
+	/* ............................................................................................................... */
+	/** ���� */
+	public void setJustification(int justification) {
+		this.justification = justification;
+	}
+
+	/* ............................................................................................................... */
+	/** ���� */
+	public void drawMatrixCellString(Graphics g, FontMetrics fm, int x, int y, int w, int h, int column, int row, String supplied) {
+		if (!StringUtil.blank(supplied)){
+			Shape clip = null;
+			boolean useClip=false;
+			if (fm == null && g.getFont() != null)
+				fm = g.getFontMetrics(g.getFont());
+			int svp = StringUtil.getStringVertPosition(fm, y, h, null);
+			if (fm == null) {
+				clip = g.getClip();
+				useClip=true;
+				g.setClip(x, y, w, h);
+				g.drawString(supplied, x + 2, svp);
+			}
+			else {
+				int length = fm.stringWidth(supplied);
+				if (length + 2 > w || svp > y + h) {
+					clip = g.getClip();
+					useClip=true;
+					g.setClip(x, y, w, h);
+				}
+				int useX;
+				if (justification == LEFT)
+					useX = x + 2;
+				else if (justification == RIGHT)
+					useX = w - length - 2;
+				else
+					useX = x + (w - length) / 2;
+				g.drawString(supplied, useX, svp);
+
+			}
+			if (useClip)
+				g.setClip(clip);
+		}
+		if (isAttachedNoteAvailable(column, row)){
+			g.drawLine(x+w-2,y+1, x+w-2,y+2); //left
+			g.drawLine(x+w-2,y+2, x+w,y+2); //bottom
+			g.drawLine(x+w,y+1, x+w,y+2); //right
+			g.drawLine(x+w-2,y, x+w,y); //top
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** ���� */
+	public boolean isAttachedNoteAvailable(int column, int row) {
+		return false;
+	}
+	/* ............................................................................................................... */
+	/** ���� */
+	public boolean useString(int column, int row) {
+		return getMatrixTextForDisplay(column, row) != null;
+	}
+
+	/* ............................................................................................................... */
+	/** Draws column name. */
+	public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column) {
+		String supplied = getColumnNameTextForDisplay(column);
+		if (supplied != null)
+			g.drawString(supplied, x + getNameStartOffset(), StringUtil.getStringVertPosition(g, y, h, null));
+		if (isAttachedNoteAvailable(column, -1)){
+			g.drawLine(x+w-2,y+1, x+w-2,y+2); //left
+			g.drawLine(x+w-2,y+2, x+w,y+2); //bottom
+			g.drawLine(x+w,y+1, x+w,y+2); //right
+			g.drawLine(x+w-2,y, x+w,y); //top
+		}
+	}
+
+
+	/* ............................................................................................................... */
+	public int getNameStartOffset() {
+		return nameStartOffset;
+	}
+
+	/* ............................................................................................................... */
+
+	public void setNameStartOffset(int nameStartOffset) {
+		this.nameStartOffset = nameStartOffset;
+	}
+
+	/* ............................................................................................................... */
+	public void setRowNameColor(Graphics g, int row) {
+	}
+
+	/* ............................................................................................................... */
+	/** Draws row name. */
+	public void drawRowNameCell(Graphics g, int x, int y, int w, int h, int row) {
+		String supplied = getRowNameTextForDisplay(row);
+		if (supplied != null){
+			int svp = StringUtil.getStringVertPosition(g, y, h, null);
+			int xgnso = x + getNameStartOffset();
+			if (showRowNames)
+				g.drawString(supplied, xgnso, svp);
+		}
+		if (isAttachedNoteAvailable(-1, row)){
+			g.drawLine(x+w-3,y+1, x+w-3,y+3); //left
+			g.drawLine(x+w-3,y+3, x+w,y+3); //bottom
+			g.drawLine(x+w,y+1, x+w,y+3); //right
+			g.drawLine(x+w-3,y, x+w,y); //top
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void mouseInCell(int modifiers, int column, int subColumn, int row, int subRow, MesquiteTool tool) {
+	}
+
+	public void mouseExitedCell(int modifiers, int column, int subColumn, int row, int subRow, MesquiteTool tool) {
+	}
+
+	/* ............................................................................................................... */
+	/** Called if corner panel is touched. Can be overridden in subclasses to respond to touch. */
+	public void cornerTouched(int x, int y, int modifiers) {
+		offAllEdits();
+		if (anythingSelected()) {
+			deselectAllNotify();
+			repaintAll();
+		}
+		outOfBoundsTouched(modifiers, 1);
+	}
+
+	/* ............................................................................................................... */
+	/** Called if part of panel out of bounds is touched. */
+	public void outOfBoundsTouched( int modifiers, int clickCount) {
+	}
+	/* ............................................................................................................... */
+	int rowFirstTouched = -2;
+
+	int columnFirstTouched = -2;
+
+	int rowLastTouched = 0;
+
+	int columnLastTouched = 0;
+
+	/* ............................................................................................................... */
+	/** Called if cell is touched. Can be overridden in subclasses to change response to touch. */
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (!columnLegal(column) || !rowLegal(row))
+			return;
+		if (!cellsSelectable && !isCellEditable(column, row))
+			return;
+		/*
+		 * if ((column == columnFirstTouched && row == rowFirstTouched) && (anyCellSelected() || editingMatrixCell())) { offEditMatrixCell(); deselectAllNotify(); selectCell(column,row); redrawCell(column,row); } else
+		 */
+		if (MesquiteEvent.shiftKeyDown(modifiers) && (anyCellSelected() || editingMatrixCell())) {
+			offEditMatrixCell();
+			int firstRow = firstRowWithSelectedCell();
+			int lastRow = lastRowWithSelectedCell();
+			int firstColumn = firstColumnWithSelectedCell();
+			int lastColumn = lastColumnWithSelectedCell();
+
+			deselectAllNotify();
+
+			if (!columnLegal(firstColumn) || !rowLegal(firstRow)) {
+				selectCell(column, row);
+				redrawCell(column, row);
+			}
+			else {
+
+				int newFirstRow, newLastRow, newFirstColumn, newLastColumn;
+
+				if (row <= firstRow) {
+					newLastRow = lastRow;
+					newFirstRow = row;
+					rowFirstTouched = lastRow;
+				}
+				else {
+					newFirstRow = firstRow;
+					newLastRow = row;
+					rowFirstTouched = firstRow;
+				}
+
+				if (column <= firstColumn) {
+					newLastColumn = lastColumn;
+					newFirstColumn = column;
+					columnFirstTouched = lastColumn;
+				}
+				else {
+					newFirstColumn = firstColumn;
+					newLastColumn = column;
+					columnFirstTouched = firstColumn;
+				}
+
+				selectBlock(newFirstColumn, newFirstRow, newLastColumn, newLastRow);
+				// if (newLastColumn>lastColumn)
+				// if (newLastRow>lastRow)
+
+				redrawBlock(MesquiteInteger.minimum(firstColumn, newFirstColumn), MesquiteInteger.minimum(firstRow, newFirstRow), MesquiteInteger.maximum(lastColumn, newLastColumn), MesquiteInteger.maximum(lastRow, newLastRow));
+				// redrawBlock(columnFirstTouched,rowFirstTouched, column, row);
+				// redrawCell(columnFirstTouched,rowFirstTouched);
+			}
+		}
+		else if (MesquiteEvent.commandOrControlKeyDown(modifiers) && (anyCellSelected() || editingMatrixCell())) {
+			if (isCellSelected(column, row))
+				deselectCell(column, row);
+			else
+				selectCell(column, row);
+			offEditMatrixCell();
+			redrawCell(column, row);
+			// redrawCell(columnFirstTouched,rowFirstTouched);
+			columnFirstTouched = column;
+			rowFirstTouched = row;
+		}
+
+		else if (anyRowSelected() || anyColumnSelected()) {
+			deselectAllNotify();
+			columnFirstTouched = column;
+			rowFirstTouched = row;
+			selectCell(column, row);
+			repaintAll();
+		}
+		else {
+			boolean wasSelected = anyCellSelected();
+			boolean wasOneCellSelected = (numCellsSelected() == 1);
+			int firstRow = -1;
+			int lastRow = -1;
+			int firstColumn = -1;
+			int lastColumn = -1;
+
+			if (!wasOneCellSelected && wasSelected) {
+				firstRow = firstRowWithSelectedCell();
+				lastRow = lastRowWithSelectedCell();
+				firstColumn = firstColumnWithSelectedCell();
+				lastColumn = lastColumnWithSelectedCell();
+			}
+
+			// redrawSelectedBlock();
+			deselectAllNotify();
+			offEditMatrixCell();
+			// if (columnFirstTouched>=0)
+			// redrawBlock(columnFirstTouched,rowFirstTouched, columnLastTouched, rowLastTouched);
+			selectCell(column, row);
+			redrawCell(column, row);
+			if (wasSelected)
+				if (wasOneCellSelected) {
+					redrawCell(columnLastTouched, rowLastTouched);
+				}
+				else
+					redrawBlock(firstColumn, firstRow, lastColumn, lastRow);
+			columnFirstTouched = column;
+			rowFirstTouched = row;
+		}
+		columnLastTouched = column;
+		rowLastTouched = row;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Called if mouse dragged over cell. Can be overridden in subclasses to respond.
+	 */
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (!columnLegal(column) || !rowLegal(row))
+			return;
+		if (!cellsSelectable)
+			return;
+		if ((column != columnLastTouched || row != rowLastTouched) && (anyCellSelected() || editingMatrixCell())) {
+			offEditMatrixCell();
+			if (!MesquiteEvent.commandOrControlKeyDown(modifiers))
+				deselectAllNotify();
+			selectBlock(columnFirstTouched, rowFirstTouched, column, row);
+			redrawDifferenceBlock(columnFirstTouched, columnFirstTouched, rowFirstTouched, rowFirstTouched, columnLastTouched, column, rowLastTouched, row);
+			// redrawBlock(columnFirstTouched,rowFirstTouched, columnLastTouched, rowLastTouched);
+			// redrawBlock(columnFirstTouched,rowFirstTouched, column, row);
+		}
+		columnLastTouched = column;
+		rowLastTouched = row;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Called if mouse is dropped on cell. Can be overridden in subclasses to respond.
+	 */
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (!singleTableCellSelected())
+			defocusCell();
+	}
+
+	public boolean touchColumnNameEvenIfSelected(){
+		return false;
+	}
+	/* ............................................................................................................... */
+	/** Called if column name is touched. Can be overridden in subclasses to change response to touch. */
+	public void columnNameTouched(int column, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		// TODO: have extension of selection if shift or command; have boolean if name editable and if selectable
+		if (!columnLegal(column))
+			return;
+		if (!columnNamesEditable && !columnNamesSelectable)
+			return;
+		if ((column == columnFirstTouched && !MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyColumnNameSelected() || editingColumnName())) {
+			deselectAllNotify();
+			offAllEdits();
+			selectColumnName(column);
+			columnNames.repaint();
+		}
+		else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyColumnNameSelected() || editingColumnName())) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				if (isColumnNameSelected(column))
+					deselectColumnName(column);
+				else
+					selectColumnName(column);
+				columnNames.repaint();
+			}
+			else {
+				deselectAllNotify();
+				selectColumnNames(columnFirstTouched, column);
+				offAllEdits();
+				columnNames.repaint();
+			}
+		}
+		else {
+			boolean doRepaint = (anyRowColumnSelected());
+			offAllEdits();
+			deselectAllNotify(true);
+			if (columnNamesAutoEditable)
+				editColumnNameCell(column);
+			else if (columnNamesSelectable)
+				selectColumnName(column);
+			if (doRepaint)
+				repaintAll();
+			else
+				columnNames.repaint();
+			columnFirstTouched = column;
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Called if row name is touched. Can be overridden in subclasses to change response to touch. */
+	public void rowNameTouched(int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		if (!rowNamesEditable && !rowNamesSelectable)
+			return;
+		if (!rowLegal(row))
+			return;
+		if ((row == rowFirstTouched && !MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyRowNameSelected() || editingRowName())) {
+			deselectAllNotify();
+			offAllEdits();
+			selectRowName(row);
+			rowNames.repaint();
+		}
+		else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyRowNameSelected() || editingRowName())) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				if (isRowNameSelected(row))
+					deselectRowName(row);
+				else
+					selectRowName(row);
+				rowNames.repaint();
+			}
+			else {
+				deselectAllNotify();
+				selectRowNames(rowFirstTouched, row);
+				offAllEdits();
+				rowNames.repaint();
+			}
+		}
+		else {
+			boolean doRepaint = (anyRowColumnSelected());
+			offAllEdits();
+			deselectAllNotify(true);
+			if (rowNamesAutoEditable) {
+				editRowNameCell(row);
+			}
+			else if (rowNamesSelectable)
+				selectRowName(row);
+			if (doRepaint)
+				repaintAll(); // repaint section only if something in other panel had been selected (not edited)
+			else {
+				rowNames.repaint();
+			}
+			rowFirstTouched = row;
+		}
+	}
+
+	/* ............................................................................................................... */
+	int firstSelectedColumn = 0;
+
+	int firstSelectedRow = 0;
+
+
+	/* ............................................................................................................... */
+	public void setFirstSelectedRow (int row) {
+		firstSelectedRow = row;
+	}
+	/* ............................................................................................................... */
+	public void setFirstSelectedColumn (int column) {
+		firstSelectedColumn = column;
+	}
+
+	/** Called if column is touched. Can be overridden in subclasses to change response to touch. */
+	/* ............................................................................................................... */
+	public void columnTouched(boolean isArrowEquivalent, int column, int regionInCellH, int regionInCellV, int modifiers) {
+		// int[] columnsToRedraw = new int[2];
+		// columnsToRedraw[0] = column;
+		// columnsToRedraw[1] = column;
+
+		if (!columnsSelectable)
+			return;
+		if (!columnLegal(column))
+			return;
+		if (column == -1) {
+			firstSelectedColumn = column;
+			offAllEdits();
+			deselectAllNotify();
+			selectRowNames(0, numRowsTotal - 1);
+			repaintAll();
+		}
+		else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && anyColumnSelected()) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				if (isColumnSelected(column)) {
+					deselectColumn(column);
+					if (columnAssociable != null) {
+						columnAssociable.setSelected(column, false);
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					}
+				}
+				else {
+					selectColumn(column);
+					if (columnAssociable != null) {
+						columnAssociable.setSelected(column, true);
+						columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					}
+				}
+				// redrawColumnName(column);
+				repaintAll();
+			}
+			else { // shiftkeydown
+				deselectAllNotify();
+				selectColumns(firstSelectedColumn, column);
+				if (columnAssociable != null)
+					columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				repaintAll();
+			}
+		}
+		else {
+			// redrawColumn(firstSelectedColumn);
+			firstSelectedColumn = column;
+			offAllEdits();
+			deselectAll();
+			repaintAll();
+			selectColumn(column);
+			// redrawColumn(column);
+			if (columnAssociable != null) {
+				columnAssociable.setSelected(column, true);
+				columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+			if (rowAssociable != null)
+				rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+	}
+
+	/* ............................................................................................................... */
+	public void subRowTouched(int subRow, int column, int regionInCellH, int regionInCellV, int x, int y, int modifiers) {
+	}
+
+	/* ............................................................................................................... */
+	/** Called if row is touched. Can be overridden in subclasses to change response to touch. */
+	public void rowTouched(boolean asArrow, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (!rowsSelectable) {
+			return;
+		}
+		if (!rowLegal(row)) {
+			return;
+		}
+		if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && anyRowSelected()) {
+			if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				if (isRowSelected(row)) {
+					deselectRow(row);
+					if (rowAssociable != null) {
+						rowAssociable.setSelected(row, false);
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					}
+				}
+				else {
+					selectRow(row);
+					if (rowAssociable != null) {
+						//	rowAssociable.setSelected(row, true);
+						rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					}
+				}
+				// redrawRowName(row);
+				repaintAll();
+			}
+			else { // shiftkeydown
+				deselectAll();
+				selectRows(firstSelectedRow, row);
+				if (columnAssociable != null)
+					columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				if (rowAssociable != null) {
+					//rowAssociable.setSelected(row, true);
+					rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+
+				repaintAll();
+			}
+		}
+		else {
+			firstSelectedRow = row;
+			offAllEdits();
+			deselectAll();
+			selectRow(row);
+			repaintAll();
+
+			if (columnAssociable != null)
+				columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			if (rowAssociable != null) {
+				//	rowAssociable.setSelected(row, true);
+				rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+	}
+
+	/* @@@............................................................................................................... */
+	/**
+	 * Called if column was dragged and dropped. (after = -1 if dropped in front of first column; -2 if after last.) Can be overridden in subclasses to respond. It is the responsibility of subclass to decide if this results in moving column, or other columns were also selected and move along too. ?Should this be called columnDragDropped?
+	 */
+	public void selectedColumnsDropped(int after) {
+		System.out.println("Columns moved   to " + after);
+	}
+
+	/* @@@............................................................................................................... */
+	/**
+	 * Called if row was dragged and dropped. (after = -1 if dropped above first row; -2 if below last.) Can be overridden in subclasses to respond. It is the responsibility of subclass to decide if this results in moving a row, or other row were also selected and move along too. ?Should this be called rowDragDropped?
+	 */
+	public void selectedRowsDropped(int after) {
+		System.out.println("row moved   to " + after);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in cell of matrix. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public String getText(int column, int row) {
+		if (column == -1 && row == -1)
+			return "";
+		else if (column == -1)
+			return getRowNameText(row);
+		else if (row == -1)
+			return getColumnNameText(column);
+		else
+			return getMatrixText(column, row);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in corner of matrix. Should be overridden in subclasses if text returned is appropriate.  This draws low in the corner
+	 */
+	public synchronized String getCornerText() {
+		return "";
+	}
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in corner of matrix. Should be overridden in subclasses if text returned is appropriate. This draws high in the corner
+	 */
+	public synchronized String getUpperCornerText() {
+		return "";
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in cell of matrix, possibly adjusted to include asterisks for footnotes, etc.. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public synchronized String getMatrixTextForDisplay(int column, int row) {
+		return getMatrixText(column, row);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in cell of matrix. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public synchronized String getMatrixText(int column, int row) {
+		return "Column " + Integer.toString(column) + " Row " + Integer.toString(row);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in column name. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public String getColumnNameText(int column) {
+		return "Column " + Integer.toString(column);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in column heading of matrix, possibly adjusted to include asterisks for footnotes, etc.. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public String getColumnNameTextForDisplay(int column) {
+		return getColumnNameText(column);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in row name. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public synchronized String getRowNameText(int row) {
+		return "Row " + Integer.toString(row);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Returns text in row name of matrix, possibly adjusted to include asterisks for footnotes, etc.. Should be overridden in subclasses if text returned is appropriate.
+	 */
+	public synchronized String getRowNameTextForDisplay(int row) {
+		return getRowNameText(row);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Called after editing a cell, passing the String resulting. Can be overridden in subclasses to respond to editing.
+	 */
+	public void returnedMatrixText(int column, int row, String s) {
+		System.out.println("Text [" + s + "] returned for Column " + Integer.toString(column) + " Row " + Integer.toString(row));
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Called after editing a ColumnName, passing the String resulting. Can be overridden in subclasses to respond to editing.
+	 */
+	public void returnedColumnNameText(int column, String s) {
+		System.out.println("Text [" + s + "] returned for Column " + Integer.toString(column));
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Called after editing a row name, passing the String resulting. Can be overridden in subclasses to respond to editing.
+	 */
+	public void returnedRowNameText(int row, String s) {
+		System.out.println("Text [" + s + "] returned for Row " + Integer.toString(row));
+	}
+
+	/* ............................................................................................................... */
+	/** Remove all edit boxes; don't record the states. */
+	public void offAllEditsDontRecord() {//1. 12
+		defocusCell();
+
+		matrix.offEditDontRecord();
+		rowNames.offEditDontRecord();
+		columnNames.offEditDontRecord();
+	}
+	/* ............................................................................................................... */
+	/** Remove all edit boxes. */
+	public void offAllEdits() {
+		defocusCell();
+
+		matrix.offEdit();
+		rowNames.offEdit();
+		columnNames.offEdit();
+	}
+	/* ............................................................................................................... */
+	/** Called to just clean up whatever is now being edited etc. in matrix. */
+	public void offAllEditingSelection() {
+		if (anyCellSelected())
+			deselectAllNotify();
+		offAllEdits();
+	}
+
+	/* ............................................................................................................... */
+	/** Remove all edit boxes but the one of the given panel. */
+	public void offOtherEdits(EditorPanel panel) {
+		if (panel != matrix)
+			matrix.offEdit();
+		if (panel != rowNames)
+			rowNames.offEdit();
+		if (panel != columnNames)
+			columnNames.offEdit();
+	}
+
+	/* ............................................................................................................... */
+	/** Place text edit box in cell with current value, to allow user to edit content. */
+	public void editMatrixCell(int column, int row) {
+		if (!isCellEditable(column, row))
+			return;
+		if (columnLegal(column) && rowLegal(row)) {
+			deselectAllNotify();
+			matrix.editCell(column, row);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Remove text edit box from cell. */
+	public void offEditMatrixCell() {
+		matrix.offEdit();
+	}
+
+	/* ............................................................................................................... */
+	/** Is a matrix cell being edited? */
+	public boolean editingMatrixCell() {
+		return matrix.getEditing();
+	}
+
+	/* ............................................................................................................... */
+	/** Requests that the column name receive a editable text field to be edited by user. NON FUNCTIONAL */
+	public void editColumnNameCell(int column) {
+		if (!columnNamesEditable)
+			return;
+		if (columnLegal(column))
+			;
+		columnNames.editCell(column, -1);
+	}
+
+	/* ............................................................................................................... */
+	/** Is a columnName being edited? */
+	public boolean editingColumnName() {
+		return columnNames.getEditing();
+	}
+
+	/* ............................................................................................................... */
+	/** Requests that the row name receive a editable text field to be edited by user. NON FUNCTIONAL */
+	public void editRowNameCell(int row) {
+		if (!rowNamesEditable)
+			return;
+		if (rowLegal(row))
+			;
+		rowNames.editCell(-1, row);
+	}
+
+	/* ............................................................................................................... */
+	/** Is a row name being edited? */
+	public boolean editingRowName() {
+		return rowNames.getEditing();
+	}
+
+	/* ............................................................................................................... */
+	/** Is anything being edited? */
+	public boolean editingAnything() {
+		return (rowNames.getEditing() || columnNames.getEditing() || matrix.getEditing());
+	}
+
+	/* ............................................................................................................... */
+	/** true if row in range of matrix. */
+	public boolean rowLegal(int row) {
+		return (row >= 0 && row < numRowsTotal);
+	}
+
+	/* ............................................................................................................... */
+	/** true if column in range of matrix. */
+	public boolean columnLegal(int column) {
+		return (column >= 0 && column < numColumnsTotal);
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Sets the Associable whose parts are tied to the columns (e.g., a CharacterData, whose characters are tied to columns) This is used to ensure that the Associable's selected parts are kept synchronous with the selection in this table.
+	 */
+	public void setColumnAssociable(Associable a) {
+		columnAssociable = a;
+	}
+
+	/* ............................................................................................................... */
+	/** Returns the Associable whose parts are tied to the columns (e.g., a CharacterData, whose characters are tied to columns). */
+	public Associable getColumnAssociable() {
+		return columnAssociable;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * Sets the Associable whose parts are tied to the row (e.g., a Taxa, whose taxa are tied to rows) This is used to ensure that the Associable's selected parts are kept synchronous with the selection in this table.
+	 */
+	public void setRowAssociable(Associable a) {
+		rowAssociable = a;
+	}
+
+	/* ............................................................................................................... */
+	/** Returns the Associable whose parts are tied to the row (e.g., a Taxa, whose taxa are tied to rows). */
+	public Associable getRowAssociable() {
+		return rowAssociable;
+	}
+
+	/* ............................................................................................................... */
+	/** Selects cell. */
+	public void selectCell(int column, int row) {
+		if (column < 0 && row < 0)
+			return;
+		else if (column == -1)
+			selectRowName(row);
+		else if (row == -1)
+			selectColumnName(column);
+		else if (columnLegal(column) && rowLegal(row))
+			cellsSelected[0].setBit(row * numColumnsTotal + column);
+	}
+	/* ............................................................................................................... */
+	/** Selects and redraws cell. */
+	public void selectAndRedrawCell(int column, int row) {
+		selectCell(column, row);
+		redrawCell(column,row);
+	}
+
+	/* ............................................................................................................... */
+	/** Selects row; DOES NOT notify listeners of ASSOCIABLE; responsibility of subclasses*/
+	public void selectRow(int row) {
+		if (rowLegal(row)){
+			rowsSelected[0].setBit(row);
+			if (rowAssociable != null)
+				rowAssociable.setSelected(row, true);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects rows */
+	public void selectRows(int first, int last) {
+		if (rowLegal(first) && rowLegal(last)) {
+			int r1 = MesquiteInteger.minimum(first, last);
+			int r2 = MesquiteInteger.maximum(first, last);
+			for (int i = r1; i <= r2; i++) {
+				rowsSelected[0].setBit(i);
+				if (rowAssociable != null) {
+					rowAssociable.setSelected(i, true);
+				}
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Select block of cells. */
+	public void selectBlock(int firstColumn, int lastColumn, Bits whichRows) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || whichRows==null)
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		for (int i = c1; i <= c2; i++)
+			for (int j =0; j <= numRowsTotal ; j++) 
+				if (whichRows.isBitOn(j)){
+					cellsSelected[0].setBit(j * numColumnsTotal + i);
+				}
+	}
+	/* ............................................................................................................... */
+	/** Select block of cells. */
+	public void selectBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++) {
+				cellsSelected[0].setBit(j * numColumnsTotal + i);
+			}
+	}
+	/* ............................................................................................................... */
+	/** Select block of cells. */
+	public void deSelectBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++) {
+				cellsSelected[0].clearBit(j * numColumnsTotal + i);
+			}
+	}
+
+
+	/* ............................................................................................................... */
+	/** Deselects all cells outside the specified rows */
+	public void deSelectAndRedrawOutsideBlock(int firstColumn, int lastColumn, Bits whichRows) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || whichRows==null)
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		for (int row = 0; row <= numRowsTotal; row++)
+			for (int column = 0; column <= numColumnsTotal; column++) {
+				if ((column < c1) || (column > c2) || (!whichRows.isBitOn(row))) { // not in block
+					if (isCellSelected(column, row)) {
+						deselectCell(column, row);
+						redrawCell(column, row);
+					}
+				}
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** Deselects all cells outside the specified block */
+	public void deSelectAndRedrawOutsideBlock(int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		for (int row = 0; row <= numRowsTotal; row++)
+			for (int column = 0; column <= numColumnsTotal; column++) {
+				if ((column < c1) || (column > c2) || (row < r1) || (row > r2)) { // not in block
+					if (isCellSelected(column, row)) {
+						deselectCell(column, row);
+						redrawCell(column, row);
+					}
+				}
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** returns true iff the column and row are within the bounds of the specified block */
+	public boolean cellInBlock(int column, int row, int firstColumn, int firstRow, int lastColumn, int lastRow) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return false;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		return ((column >= c1) && (column <=c2) && (row >= r1) && (row <= r2)) ;
+	}
+	/* ............................................................................................................... */
+	/** returns true iff the column and row are within the bounds of the specified block */
+	public boolean cellInBlock(int column, int row, int firstColumn,int lastColumn, Bits whichRows) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || whichRows==null)
+			return false;
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		return ((column >= c1) && (column <=c2) && whichRows.isBitOn(row)) ;
+	}
+	/* ............................................................................................................... */
+	/** Redraws cells in old and new blocks */
+	public void redrawOldAndNewBlocks(int firstColumnOld, int firstRowOld, int lastColumnOld, int lastRowOld, int firstColumn, int firstRow, int lastColumn, int lastRow, boolean considerAndMoveSelection) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) || !rowLegal(lastRow))
+			return;
+		if (!columnLegal(firstColumnOld) || !columnLegal(lastColumnOld) || !rowLegal(firstRowOld) || !rowLegal(lastRowOld))
+			return;
+		int c1old = MesquiteInteger.minimum(firstColumnOld, lastColumnOld);
+		int c2old = MesquiteInteger.maximum(firstColumnOld, lastColumnOld);
+		int r1old = MesquiteInteger.minimum(firstRowOld, lastRowOld);
+		int r2old = MesquiteInteger.maximum(firstRowOld, lastRowOld);
+		int c1min = firstColumnVisible;
+
+
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		int r1 = MesquiteInteger.minimum(firstRow, lastRow);
+		int r2 = MesquiteInteger.maximum(firstRow, lastRow);
+		Graphics g = matrix.getGraphics();
+
+		for (int row = r1old; row <= r2old; row++)
+			for (int column = c1old; column <= c2old; column++) {
+				if ((column < c1) || (column > c2) || (row < r1) || (row > r2)) { // not in block
+					if ((isCellSelected(column, row)||!considerAndMoveSelection) && !cellInBlock(column, row, c1,r1,c2,r2)) {
+						if (considerAndMoveSelection)
+							deselectCell(column, row);
+						if (column>=firstColumnVisible && column<=lastColumnVisible && row>=firstRowVisible && row<=lastRowVisible)
+							redrawCell(column, row, g);
+					}
+				}
+			}
+		for (int i = c1; i <= c2; i++)
+			for (int j = r1; j <= r2; j++) {
+				if (considerAndMoveSelection)
+					cellsSelected[0].setBit(j * numColumnsTotal + i);
+				if (i>=firstColumnVisible && i<=lastColumnVisible && j>=firstRowVisible && j<=lastRowVisible)
+					redrawCell(i, j,g);
+
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** Redraws cells in old and new blocks */
+	public void redrawOldAndNewBlocks(int firstColumnOld, int lastColumnOld, int firstColumn, int lastColumn, Bits whichRows, boolean considerAndMoveSelection) {
+		if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || whichRows==null)
+			return;
+		if (!columnLegal(firstColumnOld) || !columnLegal(lastColumnOld))
+			return;
+		Graphics g = matrix.getGraphics();
+
+		int c1old = MesquiteInteger.minimum(firstColumnOld, lastColumnOld);
+		int c2old = MesquiteInteger.maximum(firstColumnOld, lastColumnOld);
+		int c1 = MesquiteInteger.minimum(firstColumn, lastColumn);
+		int c2 = MesquiteInteger.maximum(firstColumn, lastColumn);
+		if (!considerAndMoveSelection) {
+			c1old = MesquiteInteger.minimum(c1old, firstColumnVisible);
+			c2old = MesquiteInteger.maximum(c2old, lastColumnVisible);
+
+			c1 = MesquiteInteger.minimum(c1, firstColumnVisible);
+			c2 = MesquiteInteger.maximum(c2, lastColumnVisible);
+			for (int row = firstRowVisible; row < numRowsTotal && row<=lastRowVisible+1; row++)
+				for (int column = c1old; column <= c2old; column++) {
+					if ((column < c1) || (column > c2 || !whichRows.isBitOn(row))) { // not in block
+						if ((isCellSelected(column, row)) && !cellInBlock(column, row, c1,c2,whichRows)) {
+							if (column>=firstColumnVisible && column<=lastColumnVisible+1 && row>=firstRowVisible && row<=lastRowVisible+1)
+								redrawCell(column, row,g);
+						}
+					}
+				}
+			for (int i = c1; i <= c2; i++)
+				for (int j = firstRowVisible; j < numRowsTotal && j<=lastRowVisible+1; j++)
+					if (whichRows.isBitOn(j)){
+						if (i>=firstColumnVisible && i<=lastColumnVisible+1 && j>=firstRowVisible && j<=lastRowVisible+1)
+							redrawCell(i, j,g);
+					}
+		}
+		else	{
+			for (int row = 0; row <= numRowsTotal; row++)
+				for (int column = c1old; column <= c2old; column++) {
+					if ((column < c1) || (column > c2 || !whichRows.isBitOn(row))) { // not in block
+						if ((isCellSelected(column, row)||!considerAndMoveSelection) && !cellInBlock(column, row, c1,c2,whichRows)) {
+							deselectCell(column, row);
+							if (column>=firstColumnVisible && column<=lastColumnVisible+1 && row>=firstRowVisible && row<=lastRowVisible+1)
+								redrawCell(column, row,g);
+						}
+					}
+				}
+			for (int i = c1; i <= c2; i++)
+				for (int j = 0; j <= numRowsTotal; j++) 
+					if (whichRows.isBitOn(j)){
+						cellsSelected[0].setBit(j * numColumnsTotal + i);
+						if (i>=firstColumnVisible && i<=lastColumnVisible+1 && j>=firstRowVisible && j<=lastRowVisible+1)
+							redrawCell(i, j,g);
+					}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects column.; DOES NOT notify listeners of ASSOCIABLE; responsibility of subclasses */
+	public void selectColumn(int column) {
+		if (columnLegal(column)){
+			columnsSelected[0].setBit(column);
+			if (columnAssociable != null)
+				columnAssociable.setSelected(column, true);
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects columns */
+	public void selectColumns(int first, int last) {
+		if (columnLegal(first) && columnLegal(last)) {
+			int r1 = MesquiteInteger.minimum(first, last);
+			int r2 = MesquiteInteger.maximum(first, last);
+			for (int i = r1; i <= r2; i++) {
+				columnsSelected[0].setBit(i);
+				if (columnAssociable != null)
+					columnAssociable.setSelected(i, true);
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects column names. */
+	public void selectColumnNames(int first, int last) {
+		if (columnLegal(first) && columnLegal(last)) {
+			int r1 = MesquiteInteger.minimum(first, last);
+			int r2 = MesquiteInteger.maximum(first, last);
+			for (int i = r1; i <= r2; i++) {
+				columnNamesSelected[0].setBit(i);
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects column name. */
+	public void selectColumnName(int column) {
+		if (columnLegal(column))
+			columnNamesSelected[0].setBit(column);
+	}
+
+	/* ............................................................................................................... */
+	/** Selects row names */
+	public void selectRowNames(int first, int last) {
+		if (rowLegal(first) && rowLegal(last)) {
+			int r1 = MesquiteInteger.minimum(first, last);
+			int r2 = MesquiteInteger.maximum(first, last);
+			for (int i = r1; i <= r2; i++) {
+				rowNamesSelected[0].setBit(i);
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects row name. */
+	public void selectRowName(int row) {
+		if (rowLegal(row))
+			rowNamesSelected[0].setBit(row);
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether anything in matrix is selected. */
+	public boolean anythingSelected() {
+		return (anyRowSelected() || anyColumnSelected() || anyRowNameSelected() || anyColumnNameSelected() || anyCellSelected());
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any cell in matrix is selected in any way. */
+	public boolean anyCellSelectedAnyWay() {
+		return (anyRowSelected() || anyColumnSelected() || anyCellSelected());
+	}
+	/* ............................................................................................................... */
+	/** returns whether any cell in central matrix in column is selected. */
+	public boolean anyCellSelectedInColumnAnyWay(int column) {
+		if (isColumnSelected(column))
+			return true;
+		for (int row = 0; row<getNumRows(); row++)
+			if (isCellSelected(column, row))
+				return true;
+		return false;
+	}
+	/* ............................................................................................................... */
+	/** returns whether any cell in central matrix in column is selected. */
+	public boolean anyCellSelectedInRowAnyWay(int row) {
+		if (isRowSelected(row))
+			return true;
+		for (int column = 0; column<getNumColumns(); column++)
+			if (isCellSelected(column, row))
+				return true;
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any row or column in matrix is selected. */
+	public boolean anyRowColumnSelected() {
+		return (anyRowSelected() || anyColumnSelected());
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any cell in central matrix is selected. */
+	public boolean anyCellSelected() {
+		return cellsSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any row name is selected. */
+	public boolean anyRowNameSelected() {
+		return rowNamesSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any column name is selected. */
+	public boolean anyColumnNameSelected() {
+		return columnNamesSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any row is selected. */
+	public boolean anyRowSelected() {
+		return rowsSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether any column is selected. */
+	public boolean anyColumnSelected() {
+		return columnsSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether anything in the main table (cell, row or column) is selected. */
+	public boolean anyMainTableCellSelected() {
+		return (anyCellSelected() || anyRowSelected() || anyColumnSelected());
+	}
+
+	/* ............................................................................................................... */
+	/** returns first row selected. */
+	public int firstRowNameSelected() {
+		return rowNamesSelected[0].firstBitOn();
+	}
+	/* ............................................................................................................... */
+	/** returns first row selected. */
+	public int firstRowSelected() {
+		return rowsSelected[0].firstBitOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns first column selected. */
+	public int firstColumnNameSelected() {
+		return columnNamesSelected[0].firstBitOn();
+	}
+	/* ............................................................................................................... */
+	/** returns first column selected. */
+	public int firstColumnSelected() {
+		return columnsSelected[0].firstBitOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns the first column in the central matrix in which there is at least one cell selected. */
+	public int firstRowWithSelectedCell() {
+		if (cellsSelected[0].anyBitsOn()) {
+			for (int row = 0; row < numRowsTotal; row++) {
+				for (int column = 0; column < numColumnsTotal; column++)
+					if (cellsSelected[0].isBitOn(row * numColumnsTotal + column))
+						return row;
+			}
+			return -1;
+		}
+		else
+			return -1;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the first column in the central matrix in which there is at least one cell selected. */
+	public int lastRowWithSelectedCell() {
+		if (cellsSelected[0].anyBitsOn()) {
+			for (int row = numRowsTotal - 1; row >= 0; row--) {
+				for (int column = 0; column < numColumnsTotal; column++)
+					if (cellsSelected[0].isBitOn(row * numColumnsTotal + column))
+						return row;
+			}
+			return -1;
+		}
+		else
+			return -1;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the first column in the central matrix in which there is at least one cell selected. */
+	public int firstColumnWithSelectedCell() {
+		if (cellsSelected[0].anyBitsOn()) {
+			for (int column = 0; column < numColumnsTotal; column++) {
+				for (int row = 0; row < numRowsTotal; row++)
+					if (cellsSelected[0].isBitOn(row * numColumnsTotal + column))
+						return column;
+			}
+			return -1;
+		}
+		else
+			return -1;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the first column in the central matrix in which there is at least one cell selected. */
+	public int lastColumnWithSelectedCell() {
+		if (cellsSelected[0].anyBitsOn()) {
+			for (int column = numColumnsTotal - 1; column >= 0; column--) {
+				for (int row = 0; row < numRowsTotal; row++)
+					if (cellsSelected[0].isBitOn(row * numColumnsTotal + column))
+						return column;
+			}
+			return -1;
+		}
+		else
+			return -1;
+	}
+
+	/* ............................................................................................................... */
+	/**
+	 * returns the boundaries of the next single block of cells selected within one row, starting from upper left, and going through each row before going to next row. 
+	 * If rows and columns passed in as MesquiteInteger are unassigned, then this finds the first case. Subsequent calls, if passed the same MesquiteIntegers retaining 
+	 * previously returned values, will find next block.
+	 */
+	public boolean nextSingleRowBlockSelected(MesquiteInteger row, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		if (!anyCellSelectedAnyWay())
+			return false;
+		if (row==null||firstColumn==null||lastColumn==null){
+			MesquiteMessage.warnProgrammer("Wanring: MesquiteIntegers passed to nextSingleRowBlockSelected cannot be null!");
+			return false;
+		}
+		boolean nextRow=false;
+		int incomingRow = row.getValue();
+		if (!row.isCombinable()) {
+			incomingRow = 0;
+		}
+		
+		int incomingLastColumn = lastColumn.getValue();
+		if (!lastColumn.isCombinable()){   // can only happen on first time through
+			incomingLastColumn = -1;
+		}
+		else if (incomingLastColumn >= numColumnsTotal - 1) { // end of previous row, need to go to start of next row
+			nextRow=true;;
+			incomingLastColumn = -1;
+		}
+		else
+			incomingLastColumn++;
+		
+		if (nextRow)
+			incomingRow++;
+		
+		if (incomingRow >= numRowsTotal)  //incomingRow is 0-based but numRowsTotal is 1-based
+			return false;
+		
+		for (int i = incomingRow; i < numRowsTotal; i++) { // go through the rows
+			if (wholeRowSelectedAnyWay(i)) {
+				row.setValue(i);
+				firstColumn.setValue(0);
+				lastColumn.setValue(numColumnsTotal - 1);
+				return true;
+			}
+			else {
+				for (int j = incomingLastColumn + 1; j < numColumnsTotal; j++) {
+					if (isCellSelectedAnyWay(j, i)) {   
+						row.setValue(i);
+						firstColumn.setValue(j);
+						for (int k = j + 1; k < numColumnsTotal; k++) {
+							if (!isCellSelectedAnyWay(k, i)) {
+								lastColumn.setValue(k - 1);
+								return true;
+							}
+							else if (k == numColumnsTotal - 1) {
+								lastColumn.setValue(numColumnsTotal - 1);
+								return true;
+							}
+						}
+
+					}
+
+				}
+			}
+			incomingLastColumn = -1;
+
+		}
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether a single contiguous block in row is selected. Returns first contiguous block selected in row regardless if unique */
+	public boolean singleContiguousBlockSelected(int row, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		if (isRowSelected(row)) {
+			if (firstColumn != null)
+				firstColumn.setValue(0);
+			if (lastColumn != null)
+				lastColumn.setValue(numColumnsTotal - 1);
+			return true;
+		}
+		else {
+			boolean lastWasSelected = false;
+			boolean someSelected = false;
+			int startC = firstColumnSelected();
+			int lastC = lastColumnSelected();
+			for (int j = 0; j < numColumnsTotal; j++) {
+				if ((j>=startC && j<=lastC && isColumnSelected(j)) || isCellSelected(j, row)) {
+					if (!lastWasSelected && someSelected && j>0) {  //we are in a new section of selected
+						return false;
+					}
+					if (!someSelected && !lastWasSelected && firstColumn != null)
+						firstColumn.setValue(j);
+					lastWasSelected = true;
+					someSelected=true;
+				}
+				else if (lastWasSelected) {// hit end of selection
+					if (lastColumn != null)
+						lastColumn.setValue(j - 1);
+					lastWasSelected = false;
+				}
+
+			}
+			if (lastWasSelected && lastColumn != null)
+				lastColumn.setValue(numColumnsTotal - 1);
+			//if (lastWasSelected && someSelected) {
+			//	return false; // second contig block selected at end;
+			//}
+			return someSelected;
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether a single contiguous cell block in matrix is selected. Returns first contiguous block selected in matrix regardless if unique */
+	public boolean boundedBlockSelected(MesquiteInteger firstRow, MesquiteInteger lastRow, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		if (firstRow==null || !firstRow.isCombinable())
+			return false;
+		if (lastRow==null || !lastRow.isCombinable())
+			return false;
+		if (firstColumn==null || !firstColumn.isCombinable())
+			return false;
+		if (lastColumn==null || !lastColumn.isCombinable())
+			return false;
+
+		for (int column =firstColumn.getValue(); column <=lastColumn.getValue(); column++) {
+			if(isColumnSelected(column) && firstRow.getValue()!=0 && lastRow.getValue()!=numRowsTotal-1 )
+				return false;
+		}
+		if(lastColumn.getValue()<numColumnsTotal-1) {
+			if (isColumnSelected(lastColumn.getValue()+1))  // the column just after is selected
+				return false;
+			for (int row =firstRow.getValue(); row <=lastRow.getValue(); row++) 
+				if(isCellSelected(lastColumn.getValue()+1, row) )
+					return false;
+
+		}
+
+		if(firstColumn.getValue()>0) {
+			if (isColumnSelected(firstColumn.getValue()-1))  // the column just after is selected
+				return false;
+			for (int row =firstRow.getValue(); row <=lastRow.getValue(); row++) 
+				if(isCellSelected(firstColumn.getValue()-1, row) )
+					return false;
+		}
+
+		for (int row =firstRow.getValue(); row <=lastRow.getValue(); row++) {
+			if(isRowSelected(row) && firstColumn.getValue()!=0 && lastColumn.getValue()!=numColumnsTotal-1 )
+				return false;
+		}
+
+		if(lastRow.getValue()<numRowsTotal-1) {
+			if (isRowSelected(lastRow.getValue()+1))  // the row just after is selected
+				return false;
+			for (int column =firstColumn.getValue(); column <=lastColumn.getValue(); column++) 
+				if(isCellSelected(column, lastRow.getValue()+1) )
+					return false;
+
+		}
+		if(firstRow.getValue()>0) {
+			if ( isRowSelected(firstRow.getValue()-1))  // the row just after is selected
+				return false;
+			for (int column =firstColumn.getValue(); column <=lastColumn.getValue(); column++) 
+				if(isCellSelected(column, firstRow.getValue()-1) )
+					return false;
+
+
+		}
+
+		for (int column =firstColumn.getValue(); column <=lastColumn.getValue(); column++) {
+			for (int row =firstRow.getValue(); row <=lastRow.getValue(); row++) { 
+				if(!isCellSelected(column, row) )
+					return false;
+			}
+		}
+
+
+
+		return true;
+	}
+
+
+	/* ............................................................................................................... */
+	/** Returns in the MesquiteIntegers the bounds of the selection growing out from the current cell */
+	public boolean findBlockSurroundingCell(int centerColumn, int centerRow, MesquiteInteger firstRow, MesquiteInteger lastRow, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		int firstR = centerRow;
+		int lastR = centerRow;
+		int firstC = centerColumn;
+		int lastC = centerColumn;
+		if (!isCellSelected(centerColumn, centerRow))
+			return false;
+
+		for (int row = centerRow; row < getNumRows(); row++) {
+			if (isCellSelected(centerColumn, row))
+				lastR = row;
+			else
+				break;
+		}
+		for (int row = centerRow; row >=0 ; row--) {
+			if (isCellSelected(centerColumn, row))
+				firstR = row;
+			else
+				break;
+		}
+		for (int column = centerColumn; column < getNumColumns(); column++) {
+			if (isCellSelected(column, centerRow))
+				lastC = column;
+			else
+				break;
+		}
+		for (int column = centerColumn; column >=0 ; column--) {
+			if (isCellSelected(column, centerRow))
+				firstC = column;
+			else
+				break;
+		}
+		firstRow.setValue(firstR);
+		lastRow.setValue(lastR);
+		firstColumn.setValue(firstC);
+		lastColumn.setValue(lastC);
+		return true;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether a single contiguous cell block in matrix is selected. Returns first contiguous block selected in matrix regardless if unique */
+	public boolean singleCellBlockSelected(MesquiteInteger firstRow, MesquiteInteger lastRow, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		int firstR = -1;
+		for (int row = 0; row < getNumRows(); row++) {
+			firstColumn.setToUnassigned();
+			lastColumn.setToUnassigned();
+			if (singleContiguousBlockSelected(row, firstColumn, lastColumn)) { // we've found a row with a singleblock selected.
+				firstR = row;
+				break;
+			}
+		}
+		if (firstR < 0)
+			return false;
+
+		boolean emptyRow = false;
+		int lastR = firstR;
+		for (int row = firstR; row < getNumRows(); row++) {
+			MesquiteInteger firstCol = new MesquiteInteger();
+			MesquiteInteger lastCol = new MesquiteInteger();
+			if (singleContiguousBlockSelected(row, firstCol, lastCol)) { // we've found a row with a singleblock selected.
+				if (emptyRow) // we've encountered an empty row in between two rows with selections
+					return false;
+				if (firstCol.getValue() != firstColumn.getValue() || lastCol.getValue() != lastColumn.getValue())
+					return false;
+				lastR = row;
+			}
+			else
+				emptyRow = true;
+		}
+		firstRow.setValue(firstR);
+		lastRow.setValue(lastR);
+		return true;
+	}
+
+	/* ............................................................................................................... */
+	public boolean onlySingleRowBlockSelected(MesquiteInteger row, MesquiteInteger firstColumn, MesquiteInteger lastColumn) {
+		MesquiteInteger rowInternal = new MesquiteInteger();
+		MesquiteInteger firstColumnInternal = new MesquiteInteger();
+		MesquiteInteger lastColumnInternal = new MesquiteInteger();
+		boolean foundBlock = nextSingleRowBlockSelected(rowInternal, firstColumnInternal, lastColumnInternal);
+		if (!foundBlock)
+			return false;
+		row.setValue(rowInternal.getValue());
+		firstColumn.setValue(firstColumnInternal.getValue());
+		lastColumn.setValue(lastColumnInternal.getValue());
+		foundBlock = nextSingleRowBlockSelected(rowInternal, firstColumnInternal, lastColumnInternal);
+		if (foundBlock)
+			return false;
+		return true;
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of cells in central matrix are selected. */
+	public int numCellsSelected() {
+		return cellsSelected[0].numBitsOn();
+	}
+	/* ............................................................................................................... */
+	/** returns number of cells in central matrix are selected any way. */
+	public int numCellsSelectedAnyWay () {
+		int num = 0;
+		for (int ic= 0; ic< numColumnsTotal; ic++)
+			for (int it= 0; it< numRowsTotal; it++)
+				if (isCellSelectedAnyWay(ic, it))
+					num++;
+		return num;
+	}
+	/* ............................................................................................................... */
+	/** returns number of cells in central matrix are selected within a column. */
+	public int numCellsSelectedInColumn (int column) {
+		if (column == -1)
+			return 0;
+
+		int num = 0;
+		if (columnLegal(column)) {
+			for (int i = 0; i < numRowsTotal; i++)
+				if (isCellSelectedAnyWay(column, i))
+					num++;
+		}
+		return num;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not all cells are selected in a column. */
+	public boolean wholeColumnSelectedAnyWay(int column) {
+		if (isColumnSelected(column))
+			return true;
+		int num = numCellsSelectedInColumn(column);
+		if (num == numRowsTotal)
+			return true;
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not all cells are selected in a column. */
+	public boolean contiguousColumnsSelected() {
+		boolean aWholeColumnSelected = false;
+		for (int i = 0; i < numColumnsTotal; i++) {
+			if (wholeColumnSelectedAnyWay(i)) {  // we've found the first selected one
+				aWholeColumnSelected = true;
+				for (int j = i; j < numColumnsTotal; j++) {
+					if (!wholeColumnSelectedAnyWay(j)) { 
+						// we've found the first unselected one after this
+						if (j==i+1)
+							return false;  // there's only one column selected
+						for (int  emptyColumn=0; emptyColumn < i-1; emptyColumn++) {  // now let's scan through the earlier parts to see if there is anything in there
+							for (int  emptyRow=0; emptyRow < numRowsTotal; emptyRow++) {
+								if (isCellSelectedAnyWay(emptyColumn, emptyRow))
+									return false;
+							}
+						}
+						for (int  emptyColumn=j; emptyColumn <numColumnsTotal; emptyColumn++) {  // now let's scan through the later parts to see if there is anything in there
+							for (int  emptyRow=0; emptyRow < numRowsTotal; emptyRow++) {
+								if (isCellSelectedAnyWay(emptyColumn, emptyRow))
+									return false;
+							}
+						}
+						return true;
+					}
+				}
+
+			}
+
+		}
+		return aWholeColumnSelected;
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of cells in central matrix are selected within a row. */
+	public int numCellsSelectedInRow(int row) {
+		if (row == -1)
+			return 0;
+
+		int num = 0;
+		if (rowLegal(row)) {
+			for (int i = 0; i < numColumnsTotal; i++)
+				if (isCellSelectedAnyWay(i, row))
+					num++;
+		}
+		return num;
+	}
+
+	/* ............................................................................................................... */
+	/** returns true if all cells are selected within a row. */
+	public boolean allCellsSelectedInRow(int row) {
+		if (row == -1)
+			return false;
+
+		if (rowLegal(row)) {
+			for (int i = 0; i < numColumnsTotal; i++)
+				if (!isCellSelectedAnyWay(i, row))
+					return false;
+		}
+		return true;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether or not all cells are selected in a row. */
+	public boolean wholeRowSelectedAnyWay(int row) {
+		if (isRowSelected(row))
+			return true;
+		if (allCellsSelectedInRow(row))
+			return true;
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of row names are selected. */
+	public int numRowNamesSelected() {
+		return rowNamesSelected[0].numBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of column names are selected. */
+	public int numColumnNamesSelected() {
+		return columnNamesSelected[0].numBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of rows are selected. */
+	public int numRowsSelected() {
+		return rowsSelected[0].numBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns true iff only a single column name, row name, or cell selected. */
+	public boolean singleTableCellSelected() {
+		int total = cellsSelected[0].numBitsOnPlural();
+		if (total > 1)
+			return false;
+		total += rowNamesSelected[0].numBitsOnPlural();
+		if (total > 1)
+			return false;
+		total += columnNamesSelected[0].numBitsOnPlural();
+		if (total > 1)
+			return false;
+		return ((total == 1) && !anyRowSelected() && !anyColumnSelected());
+	}
+
+	/* ............................................................................................................... */
+	/** returns column and row of first cell selected (-2, -2 if none). */
+	public Dimension getFirstTableCellSelected() {
+		if (numColumnsTotal == 0)
+			return new Dimension(-2, -2);
+		int firstCell = cellsSelected[0].firstBitOn();
+		if (firstCell >= 0)
+			return new Dimension(firstCell % numColumnsTotal, firstCell / numColumnsTotal);
+		firstCell = rowNamesSelected[0].firstBitOn();
+		if (firstCell >= 0)
+			return new Dimension(-1, firstCell);
+		firstCell = columnNamesSelected[0].firstBitOn();
+		if (firstCell >= 0)
+			return new Dimension(firstCell, -1);
+		return new Dimension(-2, -2);
+	}
+	/* ............................................................................................................... */
+	/** returns column and row of first cell selected (-2, -2 if none). */
+	public Dimension getLastTableCellSelected() {
+		if (numColumnsTotal == 0)
+			return new Dimension(-2, -2);
+		int lastCell = cellsSelected[0].lastBitOn();
+		if (lastCell >= 0)
+			return new Dimension(lastCell % numColumnsTotal, lastCell / numColumnsTotal);
+		lastCell = rowNamesSelected[0].lastBitOn();
+		if (lastCell >= 0)
+			return new Dimension(-1, lastCell);
+		lastCell = columnNamesSelected[0].lastBitOn();
+		if (lastCell >= 0)
+			return new Dimension(lastCell, -1);
+		return new Dimension(-2, -2);
+	}
+
+	/* ............................................................................................................... */
+	/** returns number of columns are selected. */
+	public int numColumnsSelected() {
+		return columnsSelected[0].numBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether cell in central matrix is selected (does not return true if whole row or column is selected). */
+	public boolean isCellSelected(int column, int row) {
+		if (columnLegal(column) && rowLegal(row))
+			return cellsSelected[0].isBitOn(row * numColumnsTotal + column);
+		return false;
+	}
+	/* ............................................................................................................... */
+	/** returns true if any cell in central matrix block is selected (does not return true if whole row or column is selected). */
+	public boolean isAnyCellSelectedInBlock(int columnStart, int columnEnd, int rowStart, int rowEnd) {
+		for (int column=columnStart; column<=columnEnd; column++)
+			for (int row=rowStart; row<=rowEnd; row++)
+				if (isCellSelected(column,row))
+					return true;
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns true if any cell in central matrix block is selected (does not return true if whole row or column is selected). */
+	public boolean isAnyCellSelectedInBlock(int columnStart, int columnEnd, Bits whichRows) {
+		for (int column=columnStart; column<=columnEnd; column++)
+			for (int row=0; row<numRowsTotal; row++)
+				if (whichRows.isBitOn(row) && isCellSelected(column,row))
+					return true;
+		return false;
+	}
+
+
+	/* ............................................................................................................... */
+	/** returns whether cell in central matrix is selected. */
+	public boolean isCellSelectedAnyWay(int column, int row) {
+		if (column == -1)
+			return isRowNameSelectedAnyWay(row);
+		if (row == -1)
+			return isColumnNameSelectedAnyWay(column);
+
+		if (columnLegal(column) && rowLegal(row))
+			return (cellsSelected[0].isBitOn(row * numColumnsTotal + column)) || isRowSelected(row) || isColumnSelected(column);
+		return false;
+	}
+
+	public void synchronizeRowSelection(Associable a) {
+		if (a == null)
+			return;
+		rowsSelected[0].clearAllBits();
+		boolean first = true;
+		for (int i = 0; i < numRowsTotal && i < a.getNumberOfParts(); i++)
+			if (a.getSelected(i)) {
+				selectRow(i);
+				if (first) {
+					setFirstSelectedRow(i);
+					first=false;
+				}
+			}
+	}
+
+	public void synchronizeColumnSelection(Associable a) {
+		if (a == null)
+			return;
+		columnsSelected[0].clearAllBits();
+		boolean first = true;
+		for (int i = 0; i < numColumnsTotal && i < a.getNumberOfParts(); i++)
+			if (a.getSelected(i)) {
+				selectColumn(i);
+				if (first) {
+					setFirstSelectedColumn(i);
+					first=false;
+				}
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** returns the last row selected. */
+	public int lastRowSelected() {
+		for (int i = numRowsTotal - 1; i >= 0; i--)
+			if (rowsSelected[0].isBitOn(i))
+				return i;
+		return -1;
+	}
+	/* ............................................................................................................... */
+	/** returns the last row selected. */
+	public int lastRowNameSelected() {
+		for (int i = numRowsTotal - 1; i >= 0; i--)
+			if (rowNamesSelected[0].isBitOn(i))
+				return i;
+		return -1;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the start of the last contiguous block of rows selected. */
+	public int startOfLastRowBlockSelected() {
+		int lastSelected = lastRowSelected();
+		if (lastSelected < 0)
+			return lastSelected;
+		int i = 0;
+		for (i = lastSelected - 1; i >= 0; i--)
+			if (!rowsSelected[0].isBitOn(i))
+				return i + 1;
+		if (i < 0)
+			return 0;
+		return lastSelected;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the last column selected. */
+	public int lastColumnSelected() {
+		return columnsSelected[0].lastBitOn();
+	}
+	/* ............................................................................................................... */
+	/** returns the last column selected. */
+	public int lastColumnNameSelected() {
+		for (int i = numColumnsTotal - 1; i >= 0; i--)
+			if (columnNamesSelected[0].isBitOn(i))
+				return i;
+		return -1;
+	}
+
+	/* ............................................................................................................... */
+	/** returns the start of the last contiguous block of columns selected. */
+	public int startOfLastColumnBlockSelected() {
+		int lastSelected = lastColumnSelected();
+		if (lastSelected < 0)
+			return lastSelected;
+		int i = 0;
+		for (i = lastSelected - 1; i >= 0; i--)
+			if (!columnsSelected[0].isBitOn(i))
+				return i + 1;
+		if (i < 0)
+			return 0;
+		return lastSelected;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether row is selected. */
+	public boolean isRowSelected(int row) {
+		if (rowLegal(row))
+			return rowsSelected[0].isBitOn(row);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** is any row selected. */
+	public boolean isAnyRowSelected() {
+		return rowsSelected[0].anyBitsOn();
+	}
+
+	/* ............................................................................................................... */
+	/** returns a Bits saying what rows are selected. */
+	public Bits getRowsSelected() {
+		return rowsSelected[0].cloneBits();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether column is selected. */
+	public boolean isColumnSelected(int column) {
+		if (columnLegal(column))
+			return columnsSelected[0].isBitOn(column);
+		return false;
+	}
+
+
+	/* ............................................................................................................... */
+	/** returns a Bits saying what rows are selected. */
+	public Bits getColumnsSelected() {
+		return columnsSelected[0].cloneBits();
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether column name is selected. */
+	public boolean isColumnNameSelected(int column) {
+		if (columnLegal(column))
+			return columnNamesSelected[0].isBitOn(column);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether row name is selected. */
+	public boolean isRowNameSelected(int row) {
+		if (rowLegal(row))
+			return rowNamesSelected[0].isBitOn(row);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether column name is selected in any way. */
+	public boolean isColumnNameSelectedAnyWay(int column) {
+		if (columnLegal(column))
+			return columnNamesSelected[0].isBitOn(column) || columnsSelected[0].isBitOn(column);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns whether row name is selected in any way. */
+	public boolean isRowNameSelectedAnyWay(int row) {
+		if (rowLegal(row))
+			return rowNamesSelected[0].isBitOn(row) || rowsSelected[0].isBitOn(row);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all cells, columns, etc etc. */
+	public void deselectAll() {
+		clearBetweenColumnSelection();
+		deselectAllCells(false);
+		deselectAllRows(false);
+		deselectAllColumns(false);
+		deselectAllColumnNames();
+		deselectAllRowNames();
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all cells, columns, etc etc. and notify any Associables linked to rows or columns */
+	public void deselectAllNotify() {
+		clearBetweenColumnSelection();
+		deselectAllCells(true);
+		deselectAllRows(true);
+		deselectAllColumns(true);
+		deselectAllColumnNames(true);
+		deselectAllRowNames(true);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all cells, columns, etc etc. and notify any Associables linked to rows or columns */
+	public void deselectAllNotify(boolean redrawCells) {
+		clearBetweenColumnSelection();
+		deselectAllCells(redrawCells, true);
+		deselectAllRows(true);
+		deselectAllColumns(true);
+		deselectAllColumnNames(true);
+		deselectAllRowNames(true);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all cells in central matrix. */
+	public void deselectAllCells(boolean notify) {
+		cellsSelected[0].clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all cells in central matrix. */
+
+	public void deselectAllCells(boolean redrawOld, boolean notify) {
+		Graphics g = matrix.getGraphics();
+		if (g == null)
+			return;
+		for (int row = 0; (row < numRowsTotal); row++)
+			for (int column = 0; (column < numColumnsTotal); column++)
+				if (isCellSelected(column, row)) {
+					deselectCell(column, row);
+					if (redrawOld)
+						redrawCell(column, row, g);
+				}
+		g.dispose();
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all rows. */
+	public void deselectAllRows(boolean notify) {
+		rowsSelected[0].clearAllBits();
+		if (rowAssociable != null && rowAssociable.anySelected()) {
+			rowAssociable.deselectAll();
+			if (notify)
+				rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all columns. */
+	public void deselectAllColumns(boolean notify) {
+		columnsSelected[0].clearAllBits();
+		if (columnAssociable != null && columnAssociable.anySelected()) {
+			columnAssociable.deselectAll();
+			if (notify)
+				columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+	}
+	/* ............................................................................................................... */
+	/** deselects all columns. */
+	public void convertColumnSelectionToRows(boolean notify) {
+		for (int row = 0; (row < numRowsTotal); row++)
+			if (wholeRowSelectedAnyWay(row)) {
+				selectRow(row);
+			}
+		deselectAllColumns(true);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all column names. */
+	public void deselectAllColumnNames() {
+		columnNamesSelected[0].clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all column names. */
+	public void deselectAllColumnNames(boolean redrawOld) {
+		for (int column = 0; (column < numColumnsTotal); column++)
+			if (isColumnNameSelected(column)) {
+				deselectColumnName(column);
+				if (redrawOld)
+					redrawColumnName(column);
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all row names. */
+	public void deselectAllRowNames() {
+		rowNamesSelected[0].clearAllBits();
+	}
+
+	/* ............................................................................................................... */
+	/** deselects all row names. */
+	public void deselectAllRowNames(boolean redrawOld) {
+		for (int row = 0; (row < numRowsTotal); row++)
+			if (isRowNameSelected(row)) {
+				deselectRowName(row);
+				if (redrawOld)
+					redrawRowName(row);
+			}
+	}
+
+	/* ............................................................................................................... */
+	/** deselects cell in central matrix. */
+	public void deselectCell(int column, int row) {
+		if (column < 0 && row < 0)
+			return;
+		else if (column == -1)
+			deselectRowName(row);
+		else if (row == -1)
+			deselectColumnName(column);
+		else if (columnLegal(column) && rowLegal(row))
+			cellsSelected[0].clearBit(row * numColumnsTotal + column);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects row; DOES NOT UPDATE ASSOCIABLE*/
+	public void deselectRow(int row) {
+		if (rowLegal(row))
+			rowsSelected[0].clearBit(row);
+
+	}
+
+	/* ............................................................................................................... */
+	/** deselects column; DOES NOT UPDATE ASSOCIABLE */
+	public void deselectColumn(int column) {
+		if (columnLegal(column))
+			columnsSelected[0].clearBit(column);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects column name */
+	public void deselectColumnName(int column) {
+		if (columnLegal(column))
+			columnNamesSelected[0].clearBit(column);
+	}
+
+	/* ............................................................................................................... */
+	/** deselects row name */
+	public void deselectRowName(int row) {
+		if (rowLegal(row))
+			rowNamesSelected[0].clearBit(row);
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether the cell is dimmed (true) or not (false). Column -1 is for row names; row -1 is for column names. */
+	public void setCellDimmed(int column, int row, boolean dimmed) {
+		if (column == -1) {
+			if (row == -1)
+				cornerSelected[1] = dimmed;
+			else if (rowLegal(row))
+				rowNamesSelected[1].setBit(row, dimmed);
+		}
+		else if (row == -1) {
+			if (columnLegal(column))
+				columnNamesSelected[1].setBit(column, dimmed);
+		}
+		else if (columnLegal(column) && rowLegal(row))
+			cellsSelected[1].setBit(row * numColumnsTotal + column, dimmed);
+	}
+
+	/* ............................................................................................................... */
+	/** Gets whether the cell is dimmed (true) or not (false). Column -1 is for row names; row -1 is for column names. */
+	public boolean getCellDimmed(int column, int row) {
+		if (column == -1) {
+			if (row == -1)
+				return cornerSelected[1];
+			else if (rowLegal(row))
+				rowNamesSelected[1].isBitOn(row);
+		}
+		else if (row == -1) {
+			if (columnLegal(column))
+				return columnNamesSelected[1].isBitOn(column);
+		}
+		else if (columnLegal(column) && rowLegal(row))
+			return cellsSelected[1].isBitOn(row * numColumnsTotal + column);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** Sets whether the cell should be drawn with a triangle to indicate a drop down menu (true) or not (false). Column -1 is for row names; row -1 is for column names. */
+	public void setDropDown(int column, int row, boolean enabled) {
+		if (column == -1) {
+			if (row == -1)
+				cornerSelected[2] = enabled;
+			else if (rowLegal(row))
+				rowNamesSelected[2].setBit(row, enabled);
+		}
+		else if (row == -1) {
+			if (columnLegal(column))
+				columnNamesSelected[2].setBit(column, enabled);
+		}
+		else if (columnLegal(column) && rowLegal(row))
+			cellsSelected[2].setBit(row * numColumnsTotal + column, enabled);
+	}
+
+	/* ............................................................................................................... */
+	/** Gets whether the cell should be drawn with a triangle to indicate a drop down menu (true) or not (false). Column -1 is for row names; row -1 is for column names. */
+	public boolean getDropDown(int column, int row) {
+		if (column == -1) {
+			if (row == -1)
+				return cornerSelected[2];
+			else if (rowLegal(row))
+				rowNamesSelected[2].isBitOn(row);
+		}
+		else if (row == -1) {
+			if (columnLegal(column))
+				return columnNamesSelected[2].isBitOn(column);
+		}
+		else if (columnLegal(column) && rowLegal(row))
+			return cellsSelected[2].isBitOn(row * numColumnsTotal + column);
+		return false;
+	}
+
+	/* ............................................................................................................... */
+	/** returns which row is the first visible. */
+	public int getFirstRowVisible() {
+		return firstRowVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** returns which column is the first visible. */
+	public int getFirstColumnVisible() {
+		return firstColumnVisible;
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the first visible. */
+	public void setFirstRowVisible(int value, boolean repaintPlease) {
+		if (value == firstRowVisible)
+			return;
+		if (value < getNumRows() && value >= 0)
+			firstRowVisible = value;
+		if (vertScroll != null)
+			vertScroll.setValue(firstRowVisible);
+		resetNumRowsVisible();
+		if (repaintPlease) {
+			repaint();
+			matrix.repaint();
+			rowNames.repaint();
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the first visible. */
+	public void setFirstRowVisible(int value) {
+		setFirstRowVisible(value, true);
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the first visible. */
+	public void setLastRowVisible(int value, boolean repaintPlease) {
+		int firstRow = value - getNumRowsVisible() + 1;
+		if (firstRow < 0)
+			firstRow = 0;
+		setFirstRowVisible(firstRow, repaintPlease);
+	}
+
+	/* ............................................................................................................... */
+	/** sets which row is the last visible. */
+	public void setLastRowVisible(int value) {
+		setLastRowVisible(value, true);
+	}
+
+	/* ............................................................................................................... */
+	/** sets which column is the first visible. */
+	public void setFirstColumnVisible(int value, boolean repaintPlease) {
+		if (value == firstColumnVisible)
+			return;
+		if (value < getNumColumns() && value >= 0)
+			firstColumnVisible = value;
+		if (horizScroll != null)
+			horizScroll.setValue(firstColumnVisible);
+		resetNumColumnsVisible();
+		if (repaintPlease) {
+			repaint();
+			matrix.repaint();
+			columnNames.repaint();
+		}
+
+	}
+
+	/* ............................................................................................................... */
+	/** sets which column is the first visible. */
+	public void setFirstColumnVisible(int value) {
+		setFirstColumnVisible(value, true);
+	}
+
+	/* ............................................................................................................... */
+	/** sets which column is the last visible. */
+	public void setLastColumnVisible(int value, boolean repaintPlease) {
+		if (value == lastColumnVisible)
+			return;
+		if (value < getNumColumns() && value >= 0)
+			lastColumnVisible = value;
+		int firstColumn = value - getNumColumnsVisible() + 1;
+		if (firstColumn < 0)
+			firstColumn = 0;
+		setFirstColumnVisible(firstColumn, repaintPlease);
+	}
+
+	/* ............................................................................................................... */
+	/** sets which column is the last visible. */
+	public void setLastColumnVisible(int value) {
+		setLastColumnVisible(value, true);
+	}
+
+	AutoScrollThread scrollThread = null;
+	/* ............................................................................................................... */
+	/** Starts the thread for autoscrolling . */
+	public void startAutoScrollThread(MousePanel panel) {
+		stopAutoScrollThread();
+		scrollThread = new AutoScrollThread(this,panel);
+		scrollThread.start();
+	}
+	/* ............................................................................................................... */
+	/** Stops the thread for autoscrolling . */
+	public void  stopAutoScrollThread() {
+		if (scrollThread !=null)
+			scrollThread.abortThread();
+	}
+	/* ............................................................................................................... */
+	public void suppressAutoscroll() {
+		if (scrollThread !=null)
+			scrollThread.setSuppressed(true);
+	}
+	/* ............................................................................................................... */
+	public void allowAutoscroll() {
+		if (scrollThread !=null)
+			scrollThread.setSuppressed(false);
+	}
+	/* ............................................................................................................... */
+
+	/* ............................................................................................................... */
+	public boolean checkForAutoScroll(MousePanel panel, int x, int y) {
+		if (scrollThread ==null ||  !scrollThread.active())
+			return false;
+		if (!MesquiteInteger.isCombinable(x) || !MesquiteInteger.isCombinable(y))
+			return false;
+		boolean scrolled = false;
+		if (MesquiteInteger.isCombinable(y) && scrollThread.canAutoscrollVertically())
+			if (y<=AUTOSCROLLBOUNDARY && getFirstRowVisible()>0) {
+				setFirstRowVisible(getFirstRowVisible()-1);
+				scrolled = true;
+			}
+			else if (y>=(panel.getHeight()-AUTOSCROLLBOUNDARY) && getLastRowVisible()<=getNumRows()) {
+				setFirstRowVisible(getFirstRowVisible()+1);
+				scrolled = true;
+			}
+		if (MesquiteInteger.isCombinable(x) && scrollThread.canAutoscrollHorizontally())
+			if (x<=AUTOSCROLLBOUNDARY && getFirstColumnVisible()>0) {
+				setFirstColumnVisible(getFirstColumnVisible()-1);
+				scrolled = true;
+			}
+			else if (x>=(panel.getWidth()-AUTOSCROLLBOUNDARY) && getLastColumnVisible()<=getNumColumns()) {
+				setFirstColumnVisible(getFirstColumnVisible()+1);
+				scrolled = true;
+			}
+		return scrolled;
+	}
+	/* ............................................................................................................... */
+	/** sets the value of the given scroll. */
+	public void setValue(TableScroll whichScroll, int value) {
+		if (whichScroll == vertScroll) {
+			/*if (matrix.hFloat < 0){
+				matrix.hFloat = matrix.getWidth() - 30;
+				matrix.vFloat = value*(matrix.getHeight()-20)/getNumRows();
+			}
+			Graphics g = matrix.getGraphics();
+			if (g != null){
+				g.setColor(ColorDistribution.paleGoldenRod);
+				g.fillRect(matrix.hFloat, matrix.vFloat, 40, 20);
+				g.setColor(Color.black);
+				g.drawRect(matrix.hFloat, matrix.vFloat, 40, 20);
+				g.drawString(Integer.toString(value), matrix.hFloat+3, matrix.vFloat + 16);
+				g.dispose();
+			}*/
+			/*	if (whichScroll.getValueIsAdjusting()){
+				matrix.hFloat = -1;
+				matrix.vFloat = -1;
+				matrix.repaint();
+			}
+			 */	
+			setFirstRowVisible(value);
+		}
+		else {
+			/*	if (matrix.hFloat < 0){
+				whichScroll.getValue();
+
+			}*/
+			setFirstColumnVisible(value);
+
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Scrolls to the specified cell. */
+	public void scrollToColumn(int column) {
+		if (horizScroll != null  && (column<getFirstColumnVisible() || column>getLastColumnVisible()))
+			setFirstColumnVisible(column-1);
+	}
+	/* ............................................................................................................... */
+	/** Scrolls to the specified cell. */
+	public void scrollToRow(int row) {
+		if (vertScroll != null  && (row<getFirstRowVisible() || row>getLastRowVisible()))
+			setFirstRowVisible(row-1);
+	}
+	/* ............................................................................................................... */
+	/** resets the value of the horizontal scroll to be current value plus value. */
+	public void shiftHorizScroll(int value) {
+		if (horizScroll != null)
+			setFirstColumnVisible(horizScroll.getValue() + value);
+	}
+
+	/* ............................................................................................................... */
+	public void clickOutside(){
+	}
+	/* ............................................................................................................... */
+	public void shimmerVerticalOff(Panel panel, int x) {
+		GraphicsUtil.shimmerVerticalOn(null,panel,0,matrixHeight,x);
+	}
+
+	/* ............................................................................................................... */
+	public void shimmerVerticalOn(Panel panel, int x) {
+		GraphicsUtil.shimmerVerticalOn(null,panel,0,matrixHeight,x);
+	}
+
+	/* ............................................................................................................... */
+	public void shimmerVerticalOff(int x) {
+		/** used for shimmering lines when columns adjusted */
+		shimmerVerticalOff(matrix, x);
+	}
+
+	/* ............................................................................................................... */
+	public void shimmerVerticalOn(int x) {
+		/** used for shimmering lines when columns adjusted */
+		shimmerVerticalOn(matrix, x);
+	}
+
+	/* ............................................................................................................... */
+	public void shimmerHorizontalOff(int y) {
+		GraphicsUtil.shimmerHorizontalOn(null,matrix,0,matrixWidth,y);
+	}
+
+	/* ............................................................................................................... */
+	public void shimmerHorizontalOn(int y) {
+		GraphicsUtil.shimmerHorizontalOn(null,matrix,0,matrixWidth,y);
+	}
+	/* ............................................................................................................... */
+	public void deselectAndRedrawAllSelectedRows() {
+		for (int it=0; it<getNumRows(); it++) {
+			if (isRowSelected(it)) {
+				deselectRow(it);
+				if (it>=firstRowVisible && it<lastRowVisible)
+					redrawFullRow(it);
+			}
+		}
+	}
+	/* ............................................................................................................... */
+	public void redrawFullRow(int row) {
+		if (row<0)
+			return;
+		Graphics mg = matrix.getGraphics();
+		if (mg == null)
+			return;
+		matrix.redrawRow(mg, row);
+		mg.dispose();
+		Graphics rg = rowNames.getGraphics();
+		if (rg == null)
+			return;
+		if (showRowNames)
+			rowNames.redrawName(rg, row);
+		rg.dispose();
+	}
+
+	/* ............................................................................................................... */
+	public void emphasizeRow(int previousRow, int row, int rowNotToEmphasize, boolean emphasizeSelectedRows, Color color) {
+		if (previousRow != row) {
+			Graphics mg = matrix.getGraphics();
+			if (mg == null)
+				return;
+			Graphics rg = rowNames.getGraphics();
+			if (rg == null) {
+				mg.dispose();
+				return;
+			}
+			if (row != rowNotToEmphasize && (emphasizeSelectedRows || !isRowSelected(row))) {
+				int left = matrix.leftEdgeOfRow(row);
+				int top = matrix.startOfRow(row);
+				int right = matrix.rightEdgeOfRow(row);
+				GraphicsUtil.shadeRectangle(mg, left + 1, top + 1, right - left, matrix.endOfRow(row) - top, color);
+				left = 0;
+				top = matrix.startOfRow(row);
+				right = getWidth();
+				GraphicsUtil.shadeRectangle(rg, left + 1, top + 1, right - left, matrix.endOfRow(row) - top, color);
+			}
+
+			if (previousRow > -1) {
+				matrix.redrawRow(mg, previousRow);
+				if (showRowNames)
+					rowNames.redrawName(rg, previousRow);
+			}
+			rg.dispose();
+			mg.dispose();
+		}
+	}
+
+	public void clearBetweenColumnSelection() {
+		setStartBetweenColumnSelection(MesquiteInteger.unassigned);
+		setEndBetweenColumnSelection(MesquiteInteger.unassigned);
+	}
+	public void clearBetweenRowSelection() {
+		setStartBetweenRowSelection(MesquiteInteger.unassigned);
+		setEndBetweenRowSelection(MesquiteInteger.unassigned);
+	}
+
+	public int getEndBetweenColumnSelection() {
+		return endBetweenColumnSelection;
+	}
+
+	public void setEndBetweenColumnSelection(int endBetweenColumnSelection) {
+		this.endBetweenColumnSelection = endBetweenColumnSelection;
+	}
+
+	public int getEndBetweenRowSelection() {
+		return endBetweenRowSelection;
+	}
+
+	public void setEndBetweenRowSelection(int endBetweenRowSelection) {
+		this.endBetweenRowSelection = endBetweenRowSelection;
+	}
+
+	public int getStartBetweenColumnSelection() {
+		return startBetweenColumnSelection;
+	}
+
+	public void setStartBetweenColumnSelection(int startBetweenColumnSelection) {
+		this.startBetweenColumnSelection = startBetweenColumnSelection;
+	}
+
+	public int getStartBetweenRowSelection() {
+		return startBetweenRowSelection;
+	}
+
+	public void setStartBetweenRowSelection(int startBetweenRowSelection) {
+		this.startBetweenRowSelection = startBetweenRowSelection;
+	}
+	public boolean getShowRowNames() {
+		return showRowNames;
+	}
+	public void setShowRowNames(boolean showRowNames) {
+		this.showRowNames = showRowNames;
+	}
+}
+
+/* ======================================================================== */
+/** Scrollbar for central matrix of cells in table */
+class TableScroll extends MesquiteScrollbar {
+	MesquiteTable table;
+
+	public TableScroll(MesquiteTable table, int orientation, int value, int visible, int min, int max) {
+		super(orientation, value, visible, min, max);
+		this.table = table;
+		setFocusTraversalKeysEnabled(false);
+	}
+
+	public void scrollTouched() {
+		int currentValue = getValue();
+		table.setValue(this, currentValue);
+	}
+
+	public void print(Graphics g) {
+	}
+}
+
+/* ======================================================================== */
+/** A panel at the bottom of a table or window that can be used for buttons & messages. */
+class ControlStrip extends MousePanel {
+	String message;
+
+	Color textColor;
+
+	Vector buttons;
+
+	public ControlStrip(int colorScheme) {
+		super();
+		setLayout(null);
+		buttons = new Vector();
+		message = "";
+		setBackground(ColorTheme.getInterfaceBackground());
+
+	}
+
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawRect(0, 0, getBounds().width, getBounds().height - 1);
+		if (textColor != null)
+			g.setColor(textColor);
+		if (message != null)
+			g.drawString(message, buttons.size() * 20 + 6, 12);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setTextColor(Color c) {
+		textColor = c;
+	}
+
+	public void setMessage(String s) {
+		if (s == null)
+			message = "";
+		else
+			message = s;
+		repaint();
+	}
+
+	public void addButton(MesquiteButton s) {
+		if (buttons.indexOf(s) < 0) {
+			buttons.addElement(s);
+			add(s);
+		}
+		s.setVisible(true);
+		resetLocs();
+		repaint();
+	}
+
+	public void removeButton(MesquiteButton s) {
+		buttons.removeElement(s);
+		remove(s);
+		s.setVisible(false);
+		resetLocs();
+		repaint();
+	}
+
+	private void resetLocs() {
+		int x = 4;
+		for (int i = 0; i < buttons.size(); i++) {
+			MesquiteButton b = (MesquiteButton) buttons.elementAt(i);
+			b.setLocation(x, 2);
+			x += 20;
+		}
+
+	}
+
+	public String getMessage() {
+		return message;
+	}
+}
+
diff --git a/Source/mesquite/lib/table/RowNamesPanel.java b/Source/mesquite/lib/table/RowNamesPanel.java
new file mode 100644
index 0000000..c49cd49
--- /dev/null
+++ b/Source/mesquite/lib/table/RowNamesPanel.java
@@ -0,0 +1,547 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+
+import java.io.*;
+
+/* ======================================================================== */
+/** A panel for row headings in a MesquiteTable.*/
+public class RowNamesPanel extends EditorPanel implements FocusListener  {
+	MesquiteTable table;
+	public int width,  height;
+
+	public RowNamesPanel (MesquiteTable table , int w, int h) {
+		super(table);
+		this.table=table;
+		addFocusListener(this);
+		//setBackground(ColorDistribution.medium[table.colorScheme]);
+		setAutoscrollDirection(AUTOSCROLLVERTICAL);
+		setBackground(Color.white);
+		setTableUnitSize(w, h);
+	}
+	public void setTableUnitSize (int w, int h) {
+		this.width=w;
+		this.height=h;
+		setSize(w, height);
+	}
+	public void setWidth (int w) {
+		this.width=w;
+		setSize(w, height);
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findColumn(int x, int y) {
+		return -1; //if left of grabbers?
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which row y lies, -1 if above all rows, -2 if below all rows.*/
+	public int findRow(int x, int y) {
+		if (y<=0)
+			return -1;
+		int ry = 0;
+		for (int row=table.firstRowVisible; (row<table.numRowsTotal) && (ry<y); row++) {
+			ry += table.rowHeights[row];
+			if (row>= table.numRowsTotal)
+				return -1;
+			else if (ry>=y)
+				return row;
+		}
+
+		return -2;//past the last row
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellH(int x) {
+		if (x<=0)
+			return 50;
+		return (x-startOfColumn(-1))*100/(columnWidth(-1)- startOfColumn(-1));
+	}
+	/*@@@...............................................................................................................*/
+	/** returns in which column x lies, -1 if to left, -2 if to right.*/
+	public int findRegionInCellV(int y) {
+		if (y<=0)
+			return 50;
+
+		int ry = 0;
+		for (int row=table.firstRowVisible; (row<table.numRowsTotal) && (ry<y); row++) {
+			ry += table.rowHeights[row];
+			if (row>= table.numRowsTotal)
+				return 50;
+			else if (ry>=y) {
+				int dYB = ry-y; //distance from bottom edge to 
+				int dYU = y - (ry-table.rowHeights[row]); //distance from left edge to 
+				return dYU*100/(dYB+dYU);
+			}
+		}
+		return 50;
+	}
+	public int startOfColumn(int column){
+		return table.getColumnGrabberWidth()-2;
+	}
+	public int firstColumnVisible(){
+		return -1;
+	}
+	public int numColumnsVisible(){
+		return 1;
+	}
+	public int columnWidth(int column) { //todo: why does this not subtract grabbers, but ColumnNames does?
+		return width;
+	}
+	public void textReturned(int column, int row, String text){
+		table.returnedRowNameText(row, text);
+	}
+	public String getText(int column, int row){
+		return table.getRowNameText(row);
+	}
+	public void deselectCell(int column,int row){
+		table.deselectRowName(row);
+	}
+	public void redrawCell(int column, int row){
+		Graphics g = getGraphics();
+		if (g!=null) {
+			redrawName(g, row);
+			g.dispose();
+		}
+	}
+	public void redrawName(Graphics g, int row) {
+		int top = table.getFirstRowVisible();
+
+		if (row<top) //TODO: should also fail to draw if to big
+			return;  
+		if (row == returningRow){
+			return; //don't draw if text about to be returned to cell, and will soon be redrawn anyway
+		}
+		int leftSide = startOfColumn(-1);
+		int topSide = startOfRow(row);
+		if (topSide>getBounds().height || topSide+rowHeight(row)<0)
+			return;
+
+		Shape clip = g.getClip();
+		g.setClip(0,topSide,columnWidth(-1), rowHeight(row));
+
+		prepareCell(g, -1, row, 1,topSide+1,columnWidth(-1), rowHeight(row)-2, table.focusRow == row,  table.isRowNameSelected(row) || table.isRowSelected(row), table.getCellDimmed(-1, row), table.isRowNameEditable(row));
+
+		g.setClip(0,0, getBounds().width, getBounds().height);
+
+
+		if (table.frameRowNames) {
+			Color cg = g.getColor();
+			g.setColor(Color.gray);
+			g.drawLine(0, topSide+rowHeight(row), width, topSide+rowHeight(row));
+			g.setColor(cg);
+		}
+
+		Font fnt = null;
+		boolean doFocus = table.focusRow == row && table.boldFont !=null;
+		if (doFocus){
+			fnt = g.getFont();
+			g.setFont(table.boldFont);
+		}
+		Color oldColor = g.getColor();
+		if (table.showRowGrabbers) {
+			if (table.showRowNumbers) 
+				table.drawRowColumnNumber(g,row,true,0,topSide+1, table.getRowGrabberWidth(),rowHeight(row)-2);
+			else
+				table.drawRowColumnNumberBox(g,row,true,0,topSide+1, table.getRowGrabberWidth(),rowHeight(row)-2);
+			g.setClip(0+table.getRowGrabberWidth(),topSide, width-table.getRowGrabberWidth(),rowHeight(row));
+			table.setRowNameColor(g, row);
+			table.drawRowNameCell(g, 0+table.getRowGrabberWidth(),topSide, width-table.getRowGrabberWidth(),rowHeight(row), row);
+	}
+		else {
+			g.setClip(0,topSide, width,rowHeight(row));
+			table.setRowNameColor(g, row);
+			table.drawRowNameCell(g, 0,topSide, width,rowHeight(row), row);
+		}
+		g.setColor(oldColor);
+		if (doFocus && fnt !=null){
+			g.setFont(fnt);
+		}
+		g.setClip(0,0, getBounds().width, getBounds().height);
+
+		g.setColor(Color.black);
+		if (table.getDropDown(-1, row)) {
+			int offset = 0;
+			if (table.showRowGrabbers)
+				offset = table.getRowGrabberWidth();
+
+			dropDownTriangle.translate(1 + offset,topSide + 1);
+			g.setColor(Color.white);
+			g.drawPolygon(dropDownTriangle);
+			g.setColor(Color.black);
+			g.fillPolygon(dropDownTriangle);
+			dropDownTriangle.translate(-(1 + offset),-(topSide + 1));
+		}
+		g.setClip(clip);
+		g.drawLine(width-1, 0, width-1, height);
+	}
+
+	public void repaint(){
+		checkEditFieldLocation();
+		super.repaint();
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		try {
+			table.checkResetFont(g);
+
+			int lineY = 0;
+			int oldLineY=lineY;
+			int resetWidth = getBounds().width;
+			int resetHeight = getBounds().height;
+			width = resetWidth;//this is here to test if width/height should be reset here
+			height = resetHeight;
+			Shape clip = g.getClip();
+
+			for (int r=table.firstRowVisible; (r<table.numRowsTotal) && (lineY<height); r++) {
+				redrawName(g, r);
+			}
+
+			g.setClip(0,0, getBounds().width, getBounds().height);
+			if (false && getEditing()) {
+				TextField edit = getEditField();
+				if (edit!= null)
+					edit.repaint();
+			}
+			if ((endOfLastRow()>=0) && (endOfLastRow()<table.matrixHeight)) {
+				g.setColor(ColorTheme.getContentBackgroundPale());
+				g.fillRect(0, endOfLastRow()+1, getBounds().width, getBounds().height);
+			}
+			//g.setColor(Color.black);
+			g.setColor(ColorTheme.getContentEdgeDark());  //used to be light
+			if (table.frameRowNames)
+				g.drawRect(0, 0, width, height-1);
+			g.drawLine(width-1, 0, width-1, height);
+			g.setClip(clip);
+		}
+		catch (Throwable e){
+			MesquiteMessage.warnProgrammer("Exception or Error in drawing table (RNP); details in Mesquite log file");
+			MesquiteFile.throwableToLog(this, e);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+
+	}
+	public void print(Graphics g) {
+		int lineY = 0;
+		int oldLineY=lineY;
+		Shape clip = g.getClip();
+		
+		g.setClip(0,0, getBounds().width, getBounds().height);
+		for (int r=0; (r<table.numRowsTotal); r++) {
+			lineY += table.rowHeights[r];
+			g.setClip(0,oldLineY, width, table.rowHeights[r]);
+			g.setColor(Color.black);
+			table.drawRowNameCell(g, 0,startOfRow(r), width,rowHeight(r), r);
+			//table.drawRowNameCell(g, 20,oldLineY, width,table.rowHeights[r], r);
+
+			g.setColor(Color.black);
+			oldLineY=lineY;
+		}
+		g.setClip(0,0, width, table.getTotalRowHeight());
+		g.setColor(Color.black);
+		g.drawLine(width-1, 0, width-1, table.getTotalRowHeight());
+
+		g.setClip(clip);
+	}
+	public void OLDprint(Graphics g) {
+		int lineY = 0;
+		int oldLineY=lineY;
+		int resetWidth = getBounds().width;
+		int resetHeight = getBounds().height;
+		width = resetWidth;//this is here to test if width/height should be reset here
+		height = resetHeight;
+		Shape clip = g.getClip();
+		for (int r=table.firstRowVisible; (r<table.numRowsTotal) && (lineY<height); r++) {
+			lineY += table.rowHeights[r];
+			/*
+			if (table.frameRowNames) {
+				g.setColor(Color.gray);
+				g.drawLine(0, lineY, width, lineY);
+			}
+			 */
+			g.setColor(Color.black);
+			g.setClip(0,oldLineY, width,table.rowHeights[r]);
+			table.drawRowNameCell(g, 0,oldLineY, width,table.rowHeights[r], r);
+			g.setClip(clip);
+
+			g.setColor(Color.black);
+			oldLineY=lineY;
+		}
+		g.setClip(0,0, getBounds().width, getBounds().height);
+		g.setColor(Color.black);
+		g.drawLine(width-1, 0, width-1, height);
+
+		g.setClip(clip);
+	}
+	/*...............................................................................................................*/
+	int touchY = -1;
+	int touchX = -1;
+	int lastX = -1;
+	int lastY=-1;
+	int touchRow;
+	int previousRowDragged = -1;
+	/*...............................................................................................................*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (!(tool instanceof TableTool))
+			return;
+		touchY=-1;
+		touchRow=-1;
+		int possibleTouch = findRow(x, y);
+		int regionInCellH = findRegionInCellH(x);
+		int regionInCellV =findRegionInCellV(y);
+		boolean isArrowEquivalent = ((TableTool)tool).isArrowKeyOnRow(x,table);
+
+		touchX=-1;
+		if (x>getBounds().width-8) {
+			touchX=x;
+			lastX = x;
+			shimmerOn(x);
+		}
+		else
+		if (possibleTouch>=0 && possibleTouch<table.numRowsTotal) {
+			table.startAutoScrollThread(this);
+			if (tool != null && isArrowEquivalent && table.getUserMoveRow() && table.isRowSelected(possibleTouch) && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+				touchY=y;
+				lastY = y;
+				touchRow=possibleTouch;
+				table.shimmerHorizontalOn(touchY);
+			}
+			else if ((table.showRowGrabbers) && (x<table.getRowGrabberWidth())) {
+				if (((TableTool)tool).getIsBetweenRowColumnTool() && !isArrowEquivalent)
+					possibleTouch = findRowBeforeBetween(x, y);
+				table.rowTouched(isArrowEquivalent, possibleTouch,regionInCellH, regionInCellV,modifiers);
+				if (tool != null && isArrowEquivalent && table.getUserMoveRow() && table.isRowSelected(possibleTouch) && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.commandOrControlKeyDown(modifiers)) {
+					touchY=y;
+					lastY = MesquiteInteger.unassigned;;
+					touchRow=possibleTouch;
+					//table.shimmerHorizontalOn(touchY);
+				}
+
+			}
+			else if (isArrowEquivalent) {
+				table.rowNameTouched(possibleTouch,regionInCellH, regionInCellV, modifiers,clickCount);
+			}
+			else if (tool!=null && ((TableTool)tool).getWorksOnRowNames()) {
+				if (((TableTool)tool).getIsBetweenRowColumnTool())
+					possibleTouch = findRowBeforeBetween(x, y);
+				touchY=y;
+				lastY = y;
+				touchRow=possibleTouch;
+				table.rowNameTouched(possibleTouch,regionInCellH, regionInCellV, modifiers,clickCount);
+			}
+		}
+		else if (possibleTouch==-2 && ((TableTool)tool).getWorksBeyondLastRow())
+			table.rowTouched(isArrowEquivalent,possibleTouch,regionInCellH, regionInCellV,modifiers);
+		else if (tool != null && tool.isArrowTool()){
+			table.offAllEdits();
+			table.outOfBoundsTouched(modifiers, clickCount);
+			if (table.anythingSelected()) {
+				table.deselectAllNotify();
+				table.repaintAll();
+			}
+		}
+		else
+			table.outOfBoundsTouched(modifiers, clickCount);
+
+	}
+	/*...............................................................................................................*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (touchX >=0) {
+			shimmerOff(lastX);
+			shimmerOn(x);
+			lastX=x;
+		}
+		else if (touchRow>=0 && tool != null)
+			if (((TableTool)tool).isArrowKeyOnRow(x,table)) {
+				if (table.getUserAdjustColumn()==MesquiteTable.RESIZE) {
+					table.shimmerHorizontalOff(lastY);
+					table.shimmerHorizontalOn(y);
+					lastY=y;
+				}
+				else if (table.getUserMoveColumn()) {
+					table.shimmerHorizontalOff(lastY);
+					table.shimmerHorizontalOn(y);
+					lastY=y;
+				}
+				table.checkForAutoScroll(this, MesquiteInteger.unassigned,y);   // pass unassigned in x so it doesn't do anything in that direction
+			}
+			else if (((TableTool)tool).getWorksOnRowNames()) {
+				table.checkForAutoScroll(this, MesquiteInteger.unassigned,y);   // pass unassigned in x so it doesn't do anything in that direction
+				int dragRow = findRow(x, y);
+				int regionInCellH = findRegionInCellH(x);
+				int regionInCellV =findRegionInCellV(y);
+				((TableTool)tool).cellDrag(-1,dragRow,regionInCellH,regionInCellV,modifiers);
+				if (((TableTool)tool).getEmphasizeRowsOnMouseDrag()){
+					table.emphasizeRow(previousRowDragged,dragRow, touchRow, false, Color.blue);
+					previousRowDragged = dragRow;
+				}
+			}
+	}
+	/*...............................................................................................................*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (touchX >=0) {
+			shimmerOff(lastX);
+			int newColumnWidth = getBounds().width + x-touchX-table.rowGrabberWidth;
+			if (newColumnWidth > 16) {
+				table.rowNamesWidthAdjusted = true;
+				table.setRowNamesWidth(newColumnWidth);
+				table.resetTableSize(false);
+				table.repaintAll();
+			}
+			touchX = -1;
+			lastX = -1;
+		}
+		else if (touchRow>=0 && tool != null)
+			if (((TableTool)tool).isArrowKeyOnRow(x,table)) {
+				if (!table.anyRowSelected()) {
+
+					if (table.getUserAdjustRow()==MesquiteTable.RESIZE) {
+						/*table.shimmerVerticalOff(lastX);
+						int newRH = table.rowHeights[touchRow] + x-touchX;
+						if (newRH > 16) {
+							table.setRowHeight(touchRow, newRH);
+							table.rowHeightsAdjusted.setBit(touchRow);
+							table.repaintAll();
+						}*/
+					}
+					if (table.getUserMoveRow())
+						table.shimmerHorizontalOff(lastY);
+				}
+				/*@@@*/
+				else {
+					if (table.getUserMoveRow()) {
+						table.shimmerHorizontalOff(lastY);
+						int dropRow = findRowBeforeBetween(x, y);
+						if (dropRow == -2)
+							dropRow = table.getNumRows()-1;
+						if (dropRow != touchRow && (dropRow != touchRow-1) && !table.isRowSelected(dropRow)) { //don't move dropped on row included in selection {
+							table.selectedRowsDropped(dropRow);
+						}
+					}
+					else if (table.getUserAdjustRow()==MesquiteTable.RESIZE)
+						;//table.shimmerVerticalOff(lastX);
+				}
+			}
+			else if (((TableTool)tool).getWorksOnRowNames()) {
+				int dropRow = findRow(x, y);
+				int regionInCellH = findRegionInCellH(x);
+				int regionInCellV =findRegionInCellV(y);
+				((TableTool)tool).cellDropped(-1,dropRow,regionInCellH,regionInCellV,modifiers);
+			}
+
+	}
+	/*...............................................................................................................*/
+   	public void shimmerOff(int x) {
+		if (x<=getBounds().width) {
+			table.shimmerVerticalOff(this,x);
+			table.shimmerVerticalOff(table.rowNames,x);
+		}
+		else {
+			table.shimmerVerticalOff(table.columnNames,x-touchX);
+			table.shimmerVerticalOff(table.matrix,x-touchX);
+		}
+   	 }
+	/*...............................................................................................................*/
+   	public void shimmerOn(int x) {
+		if (x<=getBounds().width) {
+			table.shimmerVerticalOn(this,x);
+			table.shimmerVerticalOn(table.rowNames,x);
+		}
+		else {
+			table.shimmerVerticalOn(table.columnNames,x-touchX);
+			table.shimmerVerticalOn(table.matrix,x-touchX);
+		}
+   	 }
+
+	/*...............................................................................................................*/
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		table.stopAutoScrollThread();
+		if (!(table.editingAnything() || table.singleTableCellSelected()) && tool != null && tool.isArrowTool())
+			setWindowAnnotation("", null);
+		setCursor(Cursor.getDefaultCursor());
+		int row = findRow(x, y);
+		table.mouseExitedCell(modifiers, -1, -1, row, -1, tool);
+	}
+	/*...............................................................................................................*/
+	public void setCurrentCursor(int modifiers, int x, int row, MesquiteTool tool) {
+		if (tool == null || !(tool instanceof TableTool))
+			setCursor(getDisabledCursor());
+		else if (row>=0 && row<table.numRowsTotal) {
+			if (((TableTool)tool).isArrowKeyOnRow(x,table)) {
+					if (x>getBounds().width-8) 
+						setCursor(table.getEResizeCursor());
+					else
+						setCursor(table.getHandCursor());
+
+				if (!(table.getUserMoveRow() && table.isRowSelected(row) && !MesquiteEvent.shiftKeyDown(modifiers) && !MesquiteEvent.controlKeyDown(modifiers))) {
+					if (!(table.editingAnything() || table.singleTableCellSelected())) {
+						String s = table.getRowComment(row);
+						if (!StringUtil.blank(s))   
+							setWindowAnnotation(s, "Footnote above refers to " + table.getRowNameText(row));
+						else
+							setWindowAnnotation("", null);
+
+					}
+				}
+			}
+			else if (((TableTool)tool).getWorksOnRowNames()) 
+				setCursor(tool.getCursor());
+			else
+				setCursor(getDisabledCursor());
+		}
+		else if (((TableTool)tool).getWorksBeyondLastRow() && (row==-2))
+			setCursor(tool.getCursor());
+		else
+			setCursor(getDisabledCursor());
+	}
+	/*...............................................................................................................*/
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (table == null)
+			return;
+		int row = findRow(x, y);
+		setCurrentCursor(modifiers, x, row, tool);
+		table.mouseInCell(modifiers, -1, -1, row, -1, tool);
+	}
+	/*...............................................................................................................*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		int row = findRow(x, y);
+		setCurrentCursor(modifiers, x, row, tool);
+		table.mouseInCell(modifiers, -1, -1, row, -1, tool);
+		table.checkForAutoScroll(this, MesquiteInteger.unassigned,y);   // pass unassigned in x so it doesn't do anything in that direction
+	}
+	/*...............................................................................................................*/
+
+
+	public void tabPressed(KeyEvent e){
+		if (!getEditing())
+			return;
+		if (table.getCellsEditable()){
+			e.consume();
+			table.editMatrixCell(0, editField.getRow());
+		}
+	}
+	public void focusGained(FocusEvent arg0) {
+	}
+	public void focusLost(FocusEvent arg0) {
+		if (table!=null) table.stopAutoScrollThread();
+	}
+}
+
diff --git a/Source/mesquite/lib/table/TableMarchingAnts.java b/Source/mesquite/lib/table/TableMarchingAnts.java
new file mode 100644
index 0000000..ec1f6c8
--- /dev/null
+++ b/Source/mesquite/lib/table/TableMarchingAnts.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.lib.table;
+
+import mesquite.lib.*;
+import java.awt.*;
+
+public class TableMarchingAnts extends MarchingAnts {
+	MesquiteTable table;
+	int column1;
+	int column2;
+	int row1;
+	int row2;
+	
+	public  TableMarchingAnts(MesquiteTable table, Graphics g, int column1, int row1, int column2, int row2) {
+		this.column1 = column1;
+		this.column2 = column2;
+		this.row1 = row1;
+		this.row2 = row2;
+		this.table = table;
+		calcMarchingAntsFromRowsColumns(column1, row1,column2, row2);
+		this.g = g;
+		startAnts();
+	}
+	public void calcMarchingAntsFromRowsColumns(int column1, int row1, int column2, int row2) {
+		this.column1 = column1;
+		this.column2 = column2;
+		this.row1 = row1;
+		this.row2 = row2;
+ 		x = table.getColumnX(column1)-2;
+		y = table.getRowY(row1)-2;
+		if (column2 == column1) 
+			width = 4;
+		else
+			width = table.getColumnX(column2) - table.getColumnX(column1)+2;
+		if (row2 == row1) 
+			height = 4;
+		else
+			height = table.getRowY(row2) - table.getColumnX(row1)+2;
+	}
+	public void resetMarchingAntsFromRowsColumns(int column1, int row1, int column2, int row2) {
+		calcMarchingAntsFromRowsColumns(column1, row1,column2, row2);
+		resize (x, y, width, height);
+	}
+	public void moveAnts() {
+		calcMarchingAntsFromRowsColumns(column1, row1,column2, row2);
+		resize (x, y, width, height);
+	}
+
+}
diff --git a/Source/mesquite/lib/table/TableTool.java b/Source/mesquite/lib/table/TableTool.java
new file mode 100644
index 0000000..3460d15
--- /dev/null
+++ b/Source/mesquite/lib/table/TableTool.java
@@ -0,0 +1,211 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.table;
+
+import java.awt.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ��������������������������� commands ������������������������������� */
+/* includes commands,  buttons, miniscrolls
+/* ======================================================================== */
+	/** This subclass of MesquiteTool is used in data windows for manipulating data.
+	*/
+public class TableTool extends MesquiteTool {
+	MesquiteCommand touchedCommand;
+	MesquiteCommand droppedCommand;
+	MesquiteCommand dragCommand;
+	boolean useTableTouch;
+	boolean worksOnRowNames = false;
+	boolean worksOnColumnNames = false;
+	boolean worksBeyondLastRow = false;
+	boolean worksBeyondLastColumn = false;
+	boolean worksOnCornerPanel = false;
+	boolean worksOnMatrixPanel = true;
+	boolean isBetweenRowColumnTool = false;
+	boolean deselectIfOutsideOfCells = true;
+	boolean worksAsArrowOnRowColumnNumbers = true;
+	boolean specialToolForColumnNamesInfoStrips = false;
+	boolean touchOnArrowKey = false;
+	boolean emphasizeRowsOnMouseDrag = false;
+	boolean emphasizeRowsOnMouseDown = false;
+	boolean emphasizeColumnsOnMouseDown = false;
+	boolean acceptsOutsideDrops = false;
+	
+	public TableTool (Object initiator, String name, String imageDirectoryPath, String imageFileName, int hotX, int hotY, String fullDescription, String explanation, MesquiteCommand touchedCommand, MesquiteCommand dragCommand, MesquiteCommand droppedCommand) {
+		super(initiator, name, imageDirectoryPath, imageFileName, hotX, hotY, fullDescription, explanation);
+		this.touchedCommand = touchedCommand;
+		this.dragCommand = dragCommand;
+		this.droppedCommand = droppedCommand;
+		if (dragCommand != null)
+			dragCommand.setSuppressLogging(true);
+		useTableTouch = touchedCommand == null;
+		setOnlyWorksWhereSpecified(true);
+	}
+	
+	
+	public void dispose(){ 
+		if (touchedCommand!=null) 
+			touchedCommand.dispose();
+		else if (droppedCommand!=null) 
+			droppedCommand.dispose();
+		else if (dragCommand!=null) 
+			dragCommand.dispose();
+		touchedCommand=null;
+		droppedCommand=null;
+		dragCommand=null;
+		super.dispose();
+	}
+	//can be overridden to, for instance, change the cursor
+	public void cursorInPanel(int modifiers, int x, int y, MousePanel panel, boolean in){
+		if (in && panel instanceof EditorPanel){
+			EditorPanel ePanel = ((EditorPanel)panel);
+			int column = ePanel.findColumn(x, y);
+			int row = ePanel.findRow(x, y);
+	   		int regionInCellH = ePanel.findRegionInCellH(x);
+	   		int regionInCellV = ePanel.findRegionInCellV(y);
+	   		cursorInCell(modifiers, column, row, regionInCellH, regionInCellV, ePanel);
+		}
+	}
+	
+	//tools can override this to find out when cursor is moved into a cell and a region of the cell
+	public void cursorInCell(int modifiers, int column, int row, int regionInCellH, int regionInCellV, EditorPanel panel){
+		
+		//here can call panel.setCursor(cursor); to set current cursor of panel
+	}
+	
+	public void setWorksOnCornerPanel(boolean u){
+		worksOnCornerPanel = u;
+	}
+	public boolean getWorksOnCornerPanel(){
+		return worksOnCornerPanel;
+	}
+	public void setWorksOnMatrixPanel(boolean u){
+		worksOnMatrixPanel = u;
+	}
+	public boolean getWorksOnMatrixPanel(){
+		return worksOnMatrixPanel;
+	}
+	public void setWorksBeyondLastRow(boolean u){
+		worksBeyondLastRow = u;
+	}
+	public boolean getWorksBeyondLastRow(){
+		return worksBeyondLastRow;
+	}
+	public void setWorksBeyondLastColumn(boolean u){
+		worksBeyondLastColumn = u;
+	}
+	public boolean getWorksBeyondLastColumn(){
+		return worksBeyondLastColumn;
+	}
+	public void setEmphasizeRowsOnMouseDrag(boolean u){
+		emphasizeRowsOnMouseDrag = u;
+	}
+	public boolean getEmphasizeRowsOnMouseDrag(){
+		return emphasizeRowsOnMouseDrag;
+	}
+	public void setEmphasizeRowsOnMouseDown(boolean u){
+		emphasizeRowsOnMouseDown = u;
+	}
+	public boolean getEmphasizeRowsOnMouseDown(){
+		return emphasizeRowsOnMouseDown;
+	}
+
+	public void setWorksAsArrowOnRowColumnNumbers(boolean u){
+		worksAsArrowOnRowColumnNumbers = u;
+	}
+	public boolean getWorksAsArrowOnRowColumnNumbers(){
+		return worksAsArrowOnRowColumnNumbers;
+	}
+	
+	public void setWorksOnColumnNames(boolean u){
+		worksOnColumnNames = u;
+	}
+	public boolean getWorksOnColumnNames(){
+		return worksOnColumnNames;
+	}
+	public void setSpecialToolForColumnNamesInfoStrips(boolean u){
+		specialToolForColumnNamesInfoStrips = u;
+	}
+	public boolean getSpecialToolForColumnNamesInfoStrips(){
+		return specialToolForColumnNamesInfoStrips;
+	}
+	public void setWorksOnRowNames(boolean u){
+		worksOnRowNames = u;
+	}
+	public boolean getWorksOnRowNames(){
+		return worksOnRowNames;
+	}
+	public void setUseTableTouchRules(boolean u){
+		useTableTouch = u;
+	}
+	public boolean useTableTouchRules(){
+		return useTableTouch;
+	}
+	public void setDeselectIfOutsideOfCells(boolean u){
+		deselectIfOutsideOfCells = u;
+	}
+	public boolean getDeselectIfOutsideOfCells(){
+		return deselectIfOutsideOfCells;
+	}
+	
+	public void setIsBetweenRowColumnTool(boolean u){
+		isBetweenRowColumnTool = u;
+	}
+	public boolean getIsBetweenRowColumnTool(){
+		return isBetweenRowColumnTool;
+	}
+	
+
+
+	
+	 
+	/* Sets whether or not tool is requesting to be informed if the up, down, right or left arrow keys are touched.  This is done by responding as if new cell was touched */
+	public void setTouchOnArrowKey(boolean u){
+		touchOnArrowKey = u;
+	}
+	public boolean getTouchOnArrowKey(){
+		return touchOnArrowKey;
+	}
+	public boolean isArrowKeyOnColumn(int y, MesquiteTable table){
+		return super.isArrowTool() || (getWorksAsArrowOnRowColumnNumbers() && table.showColumnGrabbers  && y<=table.getColumnGrabberWidth());
+	}
+	public boolean isArrowKeyOnRow(int x, MesquiteTable table){
+		return super.isArrowTool() || (getWorksAsArrowOnRowColumnNumbers() && table.showRowGrabbers  && x<=table.getRowGrabberWidth());
+	}
+
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (touchedCommand!=null)
+			touchedCommand.doItMainThread(Integer.toString(column) + " " + row + " "  + regionInCellH + " " + regionInCellV + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", touchedCommand, this), false, false);  
+	}
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (dragCommand!=null)
+			dragCommand.doItMainThread(Integer.toString(column) + " " + row + " " + regionInCellH + " " + regionInCellV + " " +  MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", dragCommand, this), false, false);  
+	}
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (droppedCommand!=null)
+			droppedCommand.doItMainThread(Integer.toString(column) + " " + row + " " + regionInCellH + " " + regionInCellV + " " + MesquiteEvent.modifiersToString(modifiers), CommandChecker.getQueryModeString("Tool", droppedCommand, this), false, false);  
+	}
+
+
+	public boolean acceptsOutsideDrops() {
+		return acceptsOutsideDrops;
+	}
+
+
+	public void setAcceptsOutsideDrops(boolean acceptsOutsideDrops) {
+		this.acceptsOutsideDrops = acceptsOutsideDrops;
+	}
+}
+
diff --git a/Source/mesquite/lib/table/TableWindow.java b/Source/mesquite/lib/table/TableWindow.java
new file mode 100644
index 0000000..fd1b63f
--- /dev/null
+++ b/Source/mesquite/lib/table/TableWindow.java
@@ -0,0 +1,312 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lib.table;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** A subclass of window designed to contain a MesquiteTable .*/
+public abstract class TableWindow extends MesquiteWindow {
+	protected static String findString = "";
+	int findNumber = 0;
+
+	/** constructor to be used only for accumulating list of commands*/
+	public TableWindow () {
+	}
+	public TableWindow (MesquiteModule ownerModule, boolean showInfoBar) {
+		super(ownerModule, showInfoBar); //INFOBAR
+		setShowExplanation(true);
+		if (showFindMenuItems()){
+			ownerModule.addMenuItem(MesquiteTrunk.editMenu, "-", null);
+			MesquiteMenuItemSpec mm = ownerModule.addMenuItem(MesquiteTrunk.editMenu, getFindLabel(), MesquiteModule.makeCommand("findString", this));
+			mm.setShortcut(KeyEvent.VK_F);
+			mm = ownerModule.addMenuItem(MesquiteTrunk.editMenu, "Find Again", MesquiteModule.makeCommand("findAgain", this));
+			mm.setShortcut(KeyEvent.VK_G);
+		}
+	}
+
+	public boolean showFindMenuItems(){
+		return true;
+	}
+	public String getFindLabel(){
+		return "Find String...";
+	}
+	public String getFindMessageName(){
+		return "cell of Table";
+	}
+	public abstract MesquiteTable getTable();
+	/*.................................................................................................................*/
+	public void pleaseUpdate() {
+		repaint();
+		if (getTable()==null) return;
+		getTable().repaintAll();
+	}
+	
+	/** Return Mesquite commands that will put the table back to its current state (approximately). */
+  	 public Snapshot getSnapshot(MesquiteFile file) {  //this allows employees to be dealt with
+	   	 	if (getTable()==null)
+	   	 		return null;
+	   	 	Snapshot temp = new Snapshot();
+	   	 	Snapshot ts = getTable().getSnapshot(file);
+	   	 	if (ts!=null) {
+				temp.addLine("getTable");
+				
+				temp.addLine("tell It");
+				temp.incorporate(ts, true);
+				temp.addLine("endTell");
+	   	 	}
+			temp.incorporate(super.getSnapshot(file), false);
+	 	 	return temp;
+  	 }
+	/*...............................................................................................................*/
+	/* these two methods are used for find facility  */
+	protected void selectAndFocus(int ic, int it){
+		MesquiteTable table = getTable();
+		if (table == null)
+			return;
+		table.deselectAll();
+		table.selectCell(ic, it);
+		table.setFocusedCell(ic, it);
+		table.repaintAll();
+	}
+	/* highlights ith cell with string */
+	boolean highlightCellWithString(String s, int i){
+		MesquiteTable table = getTable();
+		if (table == null) 
+			return false;
+		int count = 0;
+		//search row names
+		for (int it = 0; it<table.getNumRows(); it++) {
+			String c = table.getRowNameTextForDisplay(it);
+			if (StringUtil.foundIgnoreCase(c, s)){
+				if (count == i) {
+					selectAndFocus(-1, it);
+					return true;
+				}
+				count++;
+			}
+		}
+		//search column names
+		for (int ic = 0; ic<table.getNumColumns(); ic++) {
+			String c = table.getColumnNameTextForDisplay(ic);
+			if (StringUtil.foundIgnoreCase(c, s)){
+				if (count == i) {
+					selectAndFocus(ic, -1);
+					return true;
+				}
+				count++;
+			}
+		}
+		//search cells
+		for (int ic = 0; ic<table.getNumColumns(); ic++) {
+			for (int it = 0; it<table.getNumRows(); it++) {
+			
+				String c = table.getMatrixTextForDisplay(ic, it);
+				if (StringUtil.foundIgnoreCase(c, s)){
+					if (count == i) {
+						selectAndFocus(ic, it);
+						return true;
+					}
+					count++;
+				}
+			}
+		}
+		MesquiteMessage.println("There are no more occurrences of \"" + s + "\"");
+		MesquiteMessage.beep();
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** A request for the MesquiteModule to perform a command.  It is passed two strings, the name of the command and the arguments.
+	This should be overridden by any module that wants to respond to a command.*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(MesquiteTable.class, "Returns the table object for the list window", null, commandName, "getTable")) {
+			return getTable();
+		}
+    	 	else if (checker.compare(this.getClass(), "Finds cell containing string, selects it and ensures it is shown", null, commandName, "findString")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			findNumber = 0;
+			String temp = MesquiteString.queryString(this, "Find cell", "Find first " + getFindMessageName() + " containing the following string:", findString, 2);
+			if (StringUtil.blank(temp)) {
+				return null;
+			}
+			findString = temp;
+			if (!highlightCellWithString(findString, findNumber))
+				findNumber = 0;
+			else
+				findNumber = 1;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Finds cell containing string, selects it and ensures it is shown", null, commandName, "findAgain")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			if (StringUtil.blank(findString))
+				return null;
+			if (!highlightCellWithString(findString, findNumber))
+				findNumber = 0;
+			else
+				findNumber++;
+    	 	}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+ 	}
+	/*.................................................................................................................*/
+	public boolean shiftDown(String arguments){
+		if (StringUtil.blank(arguments))
+			return false;
+		 return (arguments.indexOf("shift")>=0);
+	}
+	/*.................................................................................................................*/
+	public boolean commandDown(String arguments){
+		if (StringUtil.blank(arguments))
+			return false;
+		 return (arguments.indexOf("command")>=0);
+	}
+	/*.................................................................................................................*/
+	public boolean optionDown(String arguments){
+		if (StringUtil.blank(arguments))
+			return false;
+		 return (arguments.indexOf("option")>=0);
+	}
+	/*.................................................................................................................*/
+	public void paintContents(Graphics g) {
+		if (getTable()==null) return;
+		getTable().repaintAll();
+	}
+	/*.................................................................................................................*/
+	public String getTextContents() {
+		if (getTable()==null) return null;
+		return getTable().getTextVersion();
+	}
+	public void repaintAll() {
+		if (getTable()==null) return;
+		getTable().repaintAll();
+	}
+	/*...............................................................................................................*/
+	/** Adds a button to the control strip at lower left of table.*/
+	public void addControlButton(MesquiteButton b) {
+		getTable().addControlButton(b);
+	}
+	/*...............................................................................................................*/
+	/** Removes a button from the control strip at lower left of table.*/
+	public void removeControlButton(MesquiteButton b) {
+		getTable().removeControlButton(b);
+	}
+	/*.................................................................................................................*/
+	public void printWindow(MesquitePrintJob pjob) {
+		if (getTable()==null) return;
+    	 	getTable().printTable(pjob, this);
+	}
+	/*.................................................................................................................*/
+	public String getPrintToPDFMenuItemName() {
+		return "Save Table As PDF...";
+	}
+
+	/*.................................................................................................................*/
+	/**
+	*@author Peter E. Midford
+	*/
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (getTable()==null) return;
+		getTable().tableToPDF(pdfFile, this, fitToPage);
+	}
+	/*.................................................................................................................*
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			if (infoBar.getMode()>0)
+				super.windowToPDF(pdfFile, fitToPage);
+			else {
+				Graphics g2 = pdfFile.getPDFGraphicsForComponent(getTable(),null);
+				getTable().printAll(g2);
+				pdfFile.end();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetCursor(){  
+		MesquiteTool tool = getCurrentTool();
+		if (!(tool instanceof TableTool))
+			return;
+		if (((TableTool)tool).getWorksOnColumnNames()) {
+			Cursor c = tool.getCursor();
+			if (c != null)
+				getTable().getColumnNamesPanel().setCursor(tool.getCursor());
+		}
+		if (((TableTool)tool).getWorksOnRowNames()) {
+			Cursor c = tool.getCursor();
+			if (c != null)
+				getTable().getRowNamesPanel().setCursor(tool.getCursor());
+		}
+		if (((TableTool)tool).getWorksOnCornerPanel()) {
+			Cursor c = tool.getCursor();
+			if (c != null)
+				getTable().getCornerPanel().setCursor(tool.getCursor());
+		}
+		if (((TableTool)tool).getWorksOnMatrixPanel()) {
+			Cursor c = tool.getCursor();
+			if (c != null)
+				getTable().getMatrixPanel().setCursor(tool.getCursor());
+		}
+		super.resetCursor();
+		//setCursor(Cursor.getDefaultCursor());
+	}
+	/*.................................................................................................................*/
+	public void setCurrentTool(MesquiteTool tool){
+		if (tool!=null && !tool.getEnabled())
+			return;
+		if (!(tool instanceof TableTool)) {
+			MesquiteMessage.warnProgrammer("attempt to set non-table tool as curren tool");
+			return;
+		}
+		super.setCurrentTool(tool);
+		if (getTable()==null) return;
+		resetCursor();
+	}
+	/*.................................................................................................................*/
+    	 public void copyGraphicsPanel() {
+		if (getTable()==null || getTable().getCopyCommand() == null) 
+			return;
+		getTable().getCopyCommand().doItMainThread("", null, this);  // command invoked
+   	 }
+    	 public String getCopySpecialName() {
+		return "Copy Literal"; 
+   	 }
+    	 public MesquiteCommand getCopySpecialCommand() {
+		if (getTable()==null) return null;
+		return getTable().getCopyLiteralCommand(); 
+   	 }
+    	 public MesquiteCommand getPasteCommand() {
+		if (getTable()==null) return null;
+		return getTable().getPasteCommand(); 
+   	 }
+    	 public MesquiteCommand getCutCommand() {
+		if (getTable()==null) return null;
+		return getTable().getCutCommand(); 
+   	 }
+    	 public MesquiteCommand getClearCommand() {
+		if (getTable()==null) return null;
+		return getTable().getClearCommand(); 
+   	 }
+  	public void selectAllGraphicsPanel(){
+		if (getTable()==null && getTable().getSelectAllCommand()!=null) 
+			return;
+		getTable().getSelectAllCommand().doItMainThread(null, "", this); 
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/lists/BooleanForCharList/BooleanForCharList.java b/Source/mesquite/lists/BooleanForCharList/BooleanForCharList.java
new file mode 100644
index 0000000..5d6b409
--- /dev/null
+++ b/Source/mesquite/lists/BooleanForCharList/BooleanForCharList.java
@@ -0,0 +1,221 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.BooleanForCharList;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lists.lib.*;
+
+public class BooleanForCharList extends CharListAssistant implements MesquiteListener {
+	CharacterData data;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Boolean for Character (in List of Characters window)";
+	}
+
+	public String getNameForMenuItem() {
+		return "Boolean for Character";
+	}
+
+	public String getExplanation() {
+		return "Supplies booleans for characters for a character list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BooleanForCharacter.class, getName() + " needs a method to calculate a boolean (yes/no) value for each of the characters.",
+		"You can select a value to show in the Boolean For Character submenu of the Columns menu of the List of Characters Window. ");
+	}
+	/*.................................................................................................................*/
+	BooleanForCharacter booleanTask;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			booleanTask = (BooleanForCharacter)hireNamedEmployee(BooleanForCharacter.class, arguments);
+			if (booleanTask==null) {
+				return sorry("Boolean for character (for list) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			booleanTask = (BooleanForCharacter)hireEmployee(BooleanForCharacter.class, "Value to calculate for character (for character list)");
+			if (booleanTask==null) {
+				return sorry("Boolean for character (for list) can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return BooleanForCharacter.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", booleanTask); 
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a boolean for a character", "[name of module]", commandName, "setValueTask")) {
+			BooleanForCharacter temp= (BooleanForCharacter)replaceEmployee(BooleanForCharacter.class, arguments, "Boolean for a character", booleanTask);
+			if (temp!=null) {
+				booleanTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (data != this.data){
+			if (this.data != null){
+				this.data.removeListener(this);
+				this.data.getTaxa().removeListener(this);
+			}
+			data.addListener(this);
+			data.getTaxa().addListener(this);
+	}
+		this.data = data;
+	
+		if (!suppressed)
+			doCalcs();
+		
+	}
+	public String getTitle() {
+		if (booleanTask==null)
+			return "";
+		return booleanTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	IntegerArray booleanList = new IntegerArray(0);
+	StringArray explArray = new StringArray(0);
+	int totalYes = 0;
+	int totalNo = 0;
+	int totalUndetermined = 0;
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (suppressed || booleanTask==null)
+			return;
+		int numChars = data.getNumChars();
+		booleanList.resetSize(numChars);
+		explArray.resetSize(numChars);
+		MesquiteBoolean mb = new MesquiteBoolean();
+		MesquiteString expl = new MesquiteString();
+		totalYes = 0;
+		totalNo = 0;
+		totalUndetermined = 0;
+		for (int ic=0; ic<numChars; ic++) {
+			CommandRecord.tick("Boolean for character in tree list; examining character " + ic);
+			mb.setToUnassigned();
+			booleanTask.calculateBoolean(data, ic, mb, expl);
+			if (mb.isUnassigned()){
+				booleanList.setValue(ic, -1);
+				totalUndetermined++;
+			}
+			else if (mb.getValue()){
+				booleanList.setValue(ic, 1);
+				totalYes++;
+			}
+			else {
+				totalNo++;
+				booleanList.setValue(ic, 0);
+			}
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		String s = explArray.getValue(ic);
+		if (StringUtil.blank(s))
+			s = getStringForCharacter(ic);
+		return s + " [Totals: Yes: " + totalYes + "; No: " + totalNo + "; Undetermined: " + totalUndetermined + "]";
+	}
+	public String getStringForCharacter(int ic){
+		if (booleanList==null)
+			return "";
+		if (booleanList.getValue(ic)<0)
+			return "-";
+		else if (booleanTask!=null)
+			return booleanTask.getValueString(booleanList.getValue(ic)==1);
+		//return na.toString(ic);
+		return "";
+	}
+	public String getWidestString(){
+		if (booleanTask==null)
+			return "888888";
+		return booleanTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
diff --git a/Source/mesquite/lists/BooleanForTaxaList/BooleanForTaxaList.java b/Source/mesquite/lists/BooleanForTaxaList/BooleanForTaxaList.java
new file mode 100644
index 0000000..b64ace0
--- /dev/null
+++ b/Source/mesquite/lists/BooleanForTaxaList/BooleanForTaxaList.java
@@ -0,0 +1,224 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.BooleanForTaxaList;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.lists.lib.*;
+
+public class BooleanForTaxaList extends TaxonListAssistant implements MesquiteListener {
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Boolean for Taxon (in List of Taxa window)";
+	}
+
+	public String getNameForMenuItem() {
+		return "Boolean for Taxon";
+	}
+
+	public String getExplanation() {
+		return "Supplies booleans for taxa for a taxon list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BooleanForTaxon.class, getName() + " needs a method to calculate a boolean (yes/no) value for each of the characters.",
+		"You can select a value to show in the Boolean For Taxon submenu of the Columns menu of the List of Taxa Window. ");
+	}
+	/*.................................................................................................................*/
+	BooleanForTaxon booleanTask;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			booleanTask = (BooleanForTaxon)hireNamedEmployee(BooleanForTaxon.class, arguments);
+			if (booleanTask==null) {
+				return sorry("Boolean for taxon (for list) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			booleanTask = (BooleanForTaxon)hireEmployee(BooleanForTaxon.class, "Value to calculate for character (for character list)");
+			if (booleanTask==null) {
+				return sorry("Boolean for taxon (for list) can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return BooleanForTaxon.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", booleanTask); 
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a boolean for a character", "[name of module]", commandName, "setValueTask")) {
+			BooleanForTaxon temp= (BooleanForTaxon)replaceEmployee(BooleanForTaxon.class, arguments, "Boolean for a taxon", booleanTask);
+			if (temp!=null) {
+				booleanTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		if (taxa != this.taxa){
+			if (this.taxa != null){
+				this.taxa.removeListener(this);
+			}
+			taxa.addListener(this);
+		}
+		this.taxa = taxa;
+
+		if (!suppressed)
+			doCalcs();
+
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		if (booleanTask==null)
+			return "";
+		return booleanTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		
+		if (!suppressed){
+			if (!Notification.appearsCosmetic(notification) && !(obj instanceof Taxa && notification.getCode()==MesquiteListener.SELECTION_CHANGED)){
+				outputInvalid();
+				doCalcs();
+				parametersChanged(notification);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	IntegerArray booleanList = new IntegerArray(0);
+	StringArray explArray = new StringArray(0);
+	int totalYes = 0;
+	int totalNo = 0;
+	int totalUndetermined = 0;
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (suppressed || booleanTask==null)
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		booleanList.resetSize(numTaxa);
+		explArray.resetSize(numTaxa);
+		MesquiteBoolean mb = new MesquiteBoolean();
+		MesquiteString expl = new MesquiteString();
+		totalYes = 0;
+		totalNo = 0;
+		for (int ic=0; ic<numTaxa; ic++) {
+			CommandRecord.tick("Boolean for taxon in tree list; examining taxon " + ic);
+			mb.setToUnassigned();
+			booleanTask.calculateBoolean(taxa, ic, mb, expl);
+			if (mb.isUnassigned()) {
+				booleanList.setValue(ic, -1);
+				totalUndetermined++;
+			}
+			else if (mb.getValue()){
+				booleanList.setValue(ic, 1);
+				totalYes++;
+			}
+			else {
+				totalNo++;
+				booleanList.setValue(ic, 0);
+			}
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int it){
+		if (explArray == null || explArray.getSize() <= it)
+			return null;
+		String s = explArray.getValue(it);
+		if (StringUtil.blank(s))
+			s = getStringForTaxon(it);
+		return s + " [Totals: Yes: " + totalYes + "; No: " + totalNo + "; Undetermined: " + totalUndetermined + "]";
+	}
+	public String getStringForTaxon(int it){
+		if (booleanList==null)
+			return "";
+		if (booleanList.getValue(it)<0)
+			return "-";
+		else if (booleanTask!=null)
+			return booleanTask.getValueString(booleanList.getValue(it)==1);
+		//return na.toString(ic);
+		return "";
+	}
+	public String getWidestString(){
+		if (booleanTask==null)
+			return "888888";
+		return booleanTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
diff --git a/Source/mesquite/lists/BooleanForTreeList/BooleanForTreeList.java b/Source/mesquite/lists/BooleanForTreeList/BooleanForTreeList.java
new file mode 100644
index 0000000..9798ef5
--- /dev/null
+++ b/Source/mesquite/lists/BooleanForTreeList/BooleanForTreeList.java
@@ -0,0 +1,206 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.BooleanForTreeList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class BooleanForTreeList extends TreeListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Boolean for Tree (in List of Trees window)";
+	}
+
+	public String getNameForMenuItem() {
+		return "Boolean for Tree";
+	}
+
+	public String getExplanation() {
+		return "Supplies booleans for trees for a trees list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BooleanForTree.class, getName() + " needs a method to calculate a boolean (yes/no) value for each of the trees.",
+		"You can select a value to show in the Boolean For Tree submenu of the Columns menu of the List of Trees Window. ");
+		e.setPriority(2);
+	}
+	/*.................................................................................................................*/
+	BooleanForTree booleanTask;
+	TreeVector treesBlock;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			booleanTask = (BooleanForTree)hireNamedEmployee(BooleanForTree.class, arguments);
+			if (booleanTask==null) {
+				return sorry("Boolean for tree (for list) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			booleanTask = (BooleanForTree)hireEmployee(BooleanForTree.class, "Value to calculate for trees (for tree list)");
+			if (booleanTask==null) {
+				return sorry("Boolean for tree (for list) can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return BooleanForTree.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", booleanTask); 
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a boolean for a tree", "[name of module]", commandName, "setValueTask")) {
+			BooleanForTree temp= (BooleanForTree)replaceEmployee(BooleanForTree.class, arguments, "Boolean for a tree", booleanTask);
+			if (temp!=null) {
+				booleanTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+		if (!suppressed)
+			doCalcs();
+	}
+	public String getTitle() {
+		if (booleanTask==null)
+			return "";
+		return booleanTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	IntegerArray booleanList = new IntegerArray(0);
+	StringArray explArray = new StringArray(0);
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (suppressed || booleanTask==null || treesBlock == null)
+			return;
+		int numTrees = treesBlock.size();
+		booleanList.resetSize(numTrees);
+		explArray.resetSize(numTrees);
+		MesquiteBoolean mb = new MesquiteBoolean();
+		MesquiteString expl = new MesquiteString();
+		for (int ic=0; ic<numTrees; ic++) {
+			CommandRecord.tick("Boolean for tree in tree list; examining tree " + ic);
+			Tree tree = treesBlock.getTree(ic);
+			mb.setToUnassigned();
+			booleanTask.calculateBoolean(tree, mb, expl);
+			if (mb.isUnassigned())
+				booleanList.setValue(ic, -1);
+			else if (mb.getValue())
+				booleanList.setValue(ic, 1);
+			else 
+				booleanList.setValue(ic, 0);
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public String getStringForTree(int ic){
+		if (booleanList==null)
+			return "";
+		if (booleanList.getValue(ic)<0)
+			return "-";
+		else if (booleanList.getValue(ic)==1)
+			return "Yes";
+		else
+			return "No";
+		//return na.toString(ic);
+	}
+	public String getWidestString(){
+		if (booleanTask==null)
+			return "888888";
+		return booleanTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/CharGroupList/CharGroupList.java b/Source/mesquite/lists/CharGroupList/CharGroupList.java
new file mode 100644
index 0000000..3545b71
--- /dev/null
+++ b/Source/mesquite/lists/CharGroupList/CharGroupList.java
@@ -0,0 +1,317 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharGroupList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharGroupList extends ListModule {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharGroupListAssistant.class, "The List of Character Groups window can display columns showing information for each character group.",
+				"You can request that columns be shown using the Columns menu of the List of Character Groups Window. ");
+	}
+	CharactersGroupVector groups;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("New Character Group...", MesquiteModule.makeCommand("newGroup",  this));
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null && obj == groups);
+	}
+
+	public void showListWindow(Object obj){
+		setModuleWindow(new CharGroupListWindow(this));
+		groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		((CharGroupListWindow)getModuleWindow()).setObject(groups);
+		//makeMenu("Character_Models");
+		makeMenu("List");
+
+
+		if (!MesquiteThread.isScripting()){
+			CharGroupListAssistant assistant = (CharGroupListAssistant)hireNamedEmployee(CharGroupListAssistant.class, StringUtil.tokenize("#CharGroupListColor"));
+			if (assistant!= null){
+				((CharGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/*		assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("#ModelsListParadigm"));
+			if (assistant!= null){
+				((CharGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("#ModelsListWhole"));
+			if (assistant!= null){
+				((CharGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("Data type for model"));
+			if (assistant!= null){
+				((CharGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			 */
+		}
+
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//getModuleWindow().setVisible(true);
+	}
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Creates a new group", "[]", commandName, "newGroup")) {
+			MesquiteString ms = new MesquiteString("");
+			MesquiteFile file = getProject().chooseFile( "Select file to which to add the new group label"); 
+			CharactersGroup group = CharListPartitionUtil.makeGroup(this,file,containerOfModule(), ms);      
+			if (group!=null) {
+				((CharGroupListWindow)getModuleWindow()).getTable().repaint();  
+				parametersChanged();
+			}
+			return group;
+		}
+		else if (checker.compare(this.getClass(), "Returns data set whose characters are listed", null, commandName, "getData")) {
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return getProject().getFileElement(CharactersGroupVector.class, 0);     
+	}
+	public int getNumberOfRows(){
+		if (getProject().getFileElement(CharactersGroupVector.class, 0)==null)
+			return 0;
+		else
+			return ((ListableVector)getProject().getFileElement(CharactersGroupVector.class, 0)).size();
+	}
+	public Class getAssistantClass(){
+		return CharGroupListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Character Group";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character Groups";
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		CharactersGroup group = ((CharGroupListWindow)getModuleWindow()).getCharGroup(row);
+		if (group!=null){
+			group.deleteMe(false);
+			return true;
+
+		}
+		return false;
+	}
+
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ 
+		if (row<0 || row>= getNumberOfRows())
+			return null;
+		CharactersGroup group = ((CharGroupListWindow)getModuleWindow()).getCharGroup(row);
+		return group.getAnnotation();
+	}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return;
+		CharactersGroup group = ((CharGroupListWindow)getModuleWindow()).getCharGroup(row);
+		group.setAnnotation(s, notify);
+	}
+	/** returns a String of explanation for a row*/
+	public String getExplanation(int row){
+		CharactersGroup group = ((CharGroupListWindow)getModuleWindow()).getCharGroup(row);
+		if (group!=null)
+			return group.getExplanation();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		//if (getModuleWindow()!=null && !getModuleWindow().isVisible())
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Requests a getModuleWindow() to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		//Debug.println("disposing of getModuleWindow()");
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Character Group Labels";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character groups and information about them." ;
+	}
+
+}
+
+/* ======================================================================== */
+class CharGroupListWindow extends ListWindow implements MesquiteListener {
+	CharactersGroupVector groups;
+	public CharGroupListWindow (CharGroupList ownerModule) {
+		super(ownerModule);
+		MesquiteTable t = getTable();
+		if (t!=null)
+			t.setAutoEditable(false, false, false, false);
+	}
+	/*.................................................................................................................*/
+	/** When called the getModuleWindow() will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Character Groups"); 
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return groups;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof ListableVector) {
+			if (groups!=null)
+				groups.removeListener(this);
+			groups = (CharactersGroupVector)obj;
+			groups.addListener(this);
+			getTable().synchronizeRowSelection(groups);
+		}
+		super.setCurrentObject(obj);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean isRowNameEditable(int row){
+		CharactersGroup group = getCharGroup(row);
+		return (group!=null);
+	}
+	CharactersGroup getCharGroup(int row){
+		if (groups!=null) {
+			if (row>=0 && row<groups.size())
+				return(CharactersGroup)groups.elementAt(row);
+		}
+		return null;
+	}
+	public boolean interceptRowNameTouch(int row, int regionInCellH, int regionInCellV, int modifiers){
+		CharactersGroup group = getCharGroup(row);
+		if (group!=null){
+			getTable().editRowNameCell(row);
+		}
+		return true;
+	}
+	public void setRowName(int row, String name){
+		CharactersGroup group = getCharGroup(row);
+		if (group!=null){
+			group.setName(name);
+			resetAllTitles();
+			getOwnerModule().resetAllMenuBars();
+
+		}
+	}
+	public String getRowName(int row){
+		if (groups!=null){
+			if (row<0 && row >= groups.size())
+				return null;
+			return ((Listable)groups.elementAt(row)).getName();
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj ==groups)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		if (obj instanceof GroupLabel) {
+			getTable().repaintAll();
+		}
+		else if (obj instanceof ListableVector && (ListableVector)obj ==groups) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				getTable().redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) { //listable vector, not Associable, hence dont' synchronize
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				getTable().setNumRows(groups.size());
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else if (code!=MesquiteListener.ANNOTATION_CHANGED && code!=MesquiteListener.ANNOTATION_ADDED && code!=MesquiteListener.ANNOTATION_DELETED) {
+				getTable().setNumRows(groups.size());
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+			}
+			else  {
+				getTable().repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+
+	public void dispose(){
+		if (groups!=null)
+			groups.removeListener(this);
+		super.dispose();
+	}
+}
+
+
diff --git a/Source/mesquite/lists/CharGroupListColor/CharGroupListColor.java b/Source/mesquite/lists/CharGroupListColor/CharGroupListColor.java
new file mode 100644
index 0000000..b916617
--- /dev/null
+++ b/Source/mesquite/lists/CharGroupListColor/CharGroupListColor.java
@@ -0,0 +1,207 @@
+/* Mesquite source code.  Copyright 2001 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.CharGroupListColor;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Shape;
+
+import javax.swing.JColorChooser;
+import javax.swing.JFrame;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class CharGroupListColor extends CharGroupListAssistant  {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Set Color...", makeCommand("setColor", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Group Color in List";
+	}
+	public String getExplanation() {
+		return "Shows color assigned to character group." ;
+	}
+
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		Color c = getBackgroundColorOfCell(ic,selected);
+		Color oldColor = g.getColor();
+		Color highlightColor = Color.black;
+		if (c!=null)
+			highlightColor = ColorDistribution.getContrasting(c);
+		if (c!=null){ 
+			g.setColor(c);
+			g.fillRect(x+1, y+1, w-1, h-1);
+		}
+		if (selected) {
+			g.setColor(highlightColor);
+			g.drawRect(x+1, y+1, w-2, h-2);
+			g.drawRect(x+2, y+2, w-4,h-4);
+		}
+		g.setColor(oldColor);
+	}
+	/*.................................................................................................................*/
+	CharactersGroup getCharacterGroup(int ic){
+		CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		if (groups!=null) {
+			if (ic>=0 && ic<groups.size())
+				return(CharactersGroup)groups.elementAt(ic);
+		}
+		return null;
+	}
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		
+		CharactersGroup tg = getCharacterGroup(ic);
+		if (tg!=null){
+			return tg.getColor();
+
+		}
+		return null;
+
+	}
+	Color newColor = null;
+	/*.................................................................................................................*/
+	public boolean chooseColor(Color oldColor){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying Options"))  
+			return true;
+		JFrame guiFrame = new JFrame();
+		newColor = JColorChooser.showDialog(guiFrame, "Pick a Color", oldColor);
+		if (newColor!=null){
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the color", null, commandName, "setColor")) {
+			String newColorText = parser.getFirstToken(arguments);
+			if (StringUtil.blank(newColorText)){
+				CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+				if (groups!=null  && table != null) {
+					Color oldColor = null;
+					boolean variable = false;
+					for (int i = 0; i< groups.size(); i++){
+						if (groups.getSelected(i) || table.isRowSelected(i)){
+							CharactersGroup cg = getCharacterGroup(i);
+							if (cg!=null){
+								Color color = cg.getColor();
+								if (color!=null){
+									if (ColorDistribution.equalColors(color, oldColor))
+										variable=true;
+									oldColor = color;
+								}
+							}
+						}
+					}
+					if (variable==true)
+						oldColor=null;
+					if (chooseColor(oldColor)){
+						for (int i = 0; i< groups.size(); i++){
+							if (groups.getSelected(i) || table.isRowSelected(i)){
+								CharactersGroup cg = getCharacterGroup(i);
+								if (cg!=null){
+									cg.setColor(newColor);
+									MesquiteSymbol symbol = cg.getSymbol();
+									if (symbol!=null)
+										symbol.setColor(newColor);
+								}
+							}
+						}
+						if (table != null)
+							table.repaintAll();
+						parametersChanged();
+					}
+
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void specifyColor (int ic) {
+		CharactersGroup cg = getCharacterGroup(ic);
+		if (cg!=null){
+			Color oldColor = null;
+			if (chooseColor(oldColor)){
+				cg.setColor(newColor);
+				if (table != null)
+					table.repaintAll();
+				parametersChanged();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic, int x, int y, boolean doubleClick, int modifiers){
+		if (ic>=0 && doubleClick) {
+			specifyColor(ic);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	public String getWidestString(){
+		return "888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Color";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/** Returns whether to use the string from getStringForRow; otherwise call drawInCell*/
+	public boolean useString(int ic){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void setTableAndObject(MesquiteTable table, Object object) {
+		this.table = table;
+		
+	}
+	public String getStringForRow(int ic) {
+		CharactersGroup cg = getCharacterGroup(ic);
+		if (cg!=null){
+			return cg.getColor().toString();
+		}
+		return "";
+	}
+
+
+}
diff --git a/Source/mesquite/lists/CharInclSetList/CharInclSetList.java b/Source/mesquite/lists/CharInclSetList/CharInclSetList.java
new file mode 100644
index 0000000..81a8af0
--- /dev/null
+++ b/Source/mesquite/lists/CharInclSetList/CharInclSetList.java
@@ -0,0 +1,97 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharInclSetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharInclSetList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Character Inclusion Sets";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character sets." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharInclSetListAsst.class, "The List of Character Inclusion Sets window can display columns showing information for each character inclusion set.",
+		"You can request that columns be shown using the Columns menu of the List of Character Inclusion Sets Window. ");
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Inclusion Set...", makeCommand("newInclusionSet",  this));
+		return true;
+	}
+	public Class getItemType(){
+		return CharInclusionSet.class;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	public String getItemTypeName(){
+		return "Character inclusion set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character inclusion sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new CharInclusionSet("Inclusion Set", data.getNumChars(), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+		super.showListWindow(obj);
+		CharInclSetListAsst assistant = (CharInclSetListAsst)hireNamedEmployee(CharInclSetListAsst.class, "#CharInclSetListNum");
+		if (assistant!= null){
+			((ListWindow)getModuleWindow()).addListAssistant(assistant);
+			assistant.setUseMenubar(false);
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new character inclusion set", null, commandName, "newInclusionSet")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Partition", "To make a new character inclusion set, go to the List of Characters window, make sure that a column for Inclusion appears, edit the column, then save the inclusion set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListInclusion", checker);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lists/CharInclSetListNum/CharInclSetListNum.java b/Source/mesquite/lists/CharInclSetListNum/CharInclSetListNum.java
new file mode 100644
index 0000000..9229d01
--- /dev/null
+++ b/Source/mesquite/lists/CharInclSetListNum/CharInclSetListNum.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharInclSetListNum;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharInclSetListNum extends CharInclSetListAsst implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of characters in inclusion set";
+	}
+	public String getExplanation() {
+		return "Indicates number of characters in inclusion set in list window." ;
+	}
+
+	CharacterData data=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (data !=null)
+			data.removeListener(this);
+		if (obj instanceof CharacterData)
+			data = (CharacterData)obj;
+		if (data !=null)
+			data.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged();
+	}
+	public String getTitle() {
+		return "# chars. included";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (data == null)
+				return null;
+			SpecsSetVector tsets = data.getSpecSetsVector(CharInclusionSet.class);
+			if (tsets ==null || ic<0 || ic>= tsets.size())
+				return "";
+			return Integer.toString(((CharInclusionSet)tsets.elementAt(ic)).numberSelected());
+		}
+		catch (NullPointerException e){
+		}
+		return "";
+	}
+	public String getWidestString(){
+		return " # chars. included ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (data !=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/CharListAnnotPanel/CharListAnnotPanel.java b/Source/mesquite/lists/CharListAnnotPanel/CharListAnnotPanel.java
new file mode 100644
index 0000000..6ebff2c
--- /dev/null
+++ b/Source/mesquite/lists/CharListAnnotPanel/CharListAnnotPanel.java
@@ -0,0 +1,239 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListAnnotPanel;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListAnnotPanel extends CharListAssistantI implements AnnotPanelOwner{
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Annotation Panel module (list of characters)";
+	}
+	public String getExplanation() {
+		return "Provides tools with which to attach notes (including images) to characters and show them.";
+	}
+	/*.................................................................................................................*/
+	CharacterData data;
+	MesquiteTable table;
+	AnnotationsPanel panel = null;
+	String findString = null;
+	int findNumber = 0;
+	int currentColumn, currentRow, currentNoteNumber;
+	MesquiteSubmenuSpec annotMenu;
+	MesquiteBoolean showPanel;
+	MesquiteButton annotButton;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		showPanel = new MesquiteBoolean(false);
+		annotButton = new MesquiteButton(this, makeCommand("togglePanel",  this), null, true, MesquiteModule.getRootImageDirectoryPath()  + "annot.gif", 12, 16);
+		annotButton.setShowBackground(false);
+		annotButton.setButtonExplanation("Show/Hide Annotations Panel");
+		addCheckMenuItem(null, "Show Annotations Panel", makeCommand("togglePanel", this), showPanel);
+
+		annotMenu = addSubmenu(null, "Annotations");
+		MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Find Annotation", MesquiteModule.makeCommand("searchAnnotations", this));
+		mmi.setShortcut(KeyEvent.VK_3);
+		mmi = addItemToSubmenu(null, annotMenu, "Find Again", MesquiteModule.makeCommand("searchAgain", this));
+		mmi.setShortcut(KeyEvent.VK_8);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public MesquiteModule getModule(){
+		return this;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		setPanel();
+	}
+	/*.................................................................................................................*/
+	void setPanel(){
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof TableWindow){
+			((TableWindow)f).addControlButton(annotButton);
+			if (showPanel.getValue()){
+				if (panel == null) {
+					panel = new AnnotationsPanel(this);
+					addItemToSubmenu(null, annotMenu, "-", null);
+					MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Make Item Label", MesquiteModule.makeCommand("makeItemLabel", panel));
+					mmi.setShortcut(KeyEvent.VK_L);
+					addItemToSubmenu(null, annotMenu, "Recover Offscreen Labels", MesquiteModule.makeCommand("recoverLostLabels", panel));
+					resetContainingMenuBar();
+				}
+				((TableWindow)f).addSidePanel(panel, 300);
+				panel.setVisible(true);
+
+			}
+			else {
+				if (panel != null)
+					((TableWindow)f).removeSidePanel(panel);
+			}
+
+		}
+	}
+	public boolean hasDisplayModifications(){
+		return false;
+	}
+	public void panelGoAway(Panel p){
+		showPanel.setValue(false);
+		setPanel();
+	}
+	/*.................................................................................................................*/
+	void showNote(AttachedNotesVector aim, int row, int noteNumber){
+		if (row<-1 || data == null || panel == null || row>= data.getNumChars())
+			return;
+		currentRow = row;
+		String s = null;
+		String loc = null;
+		if (row >= 0){
+			if (data.characterHasName(row))
+				s = "character \"" + data.getCharacterName(row) + "\"";
+			else
+				s = data.getCharacterName(row);
+			loc = Integer.toString(row+1);
+		}
+		if (!panel.isVisible()){
+			showPanel.setValue(true);
+			setPanel();
+		}
+		panel.setNotes(aim, s, loc, -1, row, noteNumber);
+	}
+	void showNote(int row, int noteNumber){
+		if ( row < -1 || data == null || panel == null || row>= data.getNumChars())
+			return;
+		AttachedNotesVector hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, row);
+		showNote(hL, row, noteNumber);
+	}
+
+	boolean findAndShowNote(String searchString, int i){
+		int count = 0;
+		//search characters
+		for (int ic = 0; ic<data.getNumChars(); ic++) {
+			AttachedNotesVector hL = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+			if (hL != null){
+				for (int noteNum = 0; noteNum<hL.getNumNotes(); noteNum++){
+					AttachedNote note = hL.getAttachedNote(noteNum);
+					if (note.containsString(searchString)){
+						if (count == i) {
+							showNote(ic,  noteNum);
+							return true;
+						}
+						count++;
+					}
+				}
+			}
+		}
+		MesquiteMessage.println("There are no more occurrences of \"" + searchString + "\"");
+		MesquiteMessage.beep();
+		return false;
+
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		//removePanel;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("togglePanel " + showPanel.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not the annotations panel is shown", "[on = shown; off]", commandName, "togglePanel")) {
+			showPanel.toggleValue(parser.getFirstToken(arguments));
+			setPanel();
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAnnotations")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			String temp = MesquiteString.queryString(containerOfModule(), "Search annotations", "Search annotations of cells of matrix to find the following string.  Comments, references and labels of images will be searched.", findString, 2);
+			if (StringUtil.blank(temp)) {
+				return null;
+			}
+			findString = temp;
+			findNumber = 0;
+			if (!findAndShowNote(findString, findNumber))				findNumber = 0;
+			else
+				findNumber = 1;
+
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAgain")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			if (StringUtil.blank(findString))
+				return null;
+			if (!findAndShowNote(findString, findNumber))				findNumber = 0;
+			else
+				findNumber++;
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public AttachedNotesVector makeNotesVector(AnnotationsPanel w){
+		//attach image to window w
+		int row = currentRow;
+		AttachedNotesVector aiv  = (AttachedNotesVector)data.getAssociatedObject(notesNameRef, row);
+		if (aiv == null)
+			aiv = new AttachedNotesVector(data);
+		data.setAssociatedObject(notesNameRef, row, aiv);
+		return aiv;
+	}
+	public void chooseAndAttachImage(AttachedNote hL, boolean local){
+		if (hL == null)
+			return;
+		//attach image to window w
+
+		hL.attachImage(this, local);
+		showNote( currentRow, currentNoteNumber);
+		if (table != null)
+			table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public void focusInRow(int row){
+		if (data == null)
+			return;
+		if (panel == null || panel.isVisible())
+			showNote(row, 0);
+		return;
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+}
diff --git a/Source/mesquite/lists/CharListCodonPos/CharListCodonPos.java b/Source/mesquite/lists/CharListCodonPos/CharListCodonPos.java
new file mode 100644
index 0000000..aa112ad
--- /dev/null
+++ b/Source/mesquite/lists/CharListCodonPos/CharListCodonPos.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListCodonPos;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CharListCodonPos extends CharListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Current Codon Positions";
+	}
+	public String getExplanation() {
+		return "Supplies current codon positions applied to characters for character list window." ;
+	}
+
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mPos;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine;
+	static final int numMMIS = 8;
+	MesquiteMenuItemSpec[] setCodMMIS;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setCodMMIS = new MesquiteMenuItemSpec[numMMIS];
+		return true;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new RequiresAnyDNAData();
+	}
+	/*.................................................................................................................*/
+	private void setPositions(int position,  boolean calc, boolean notify){
+		if (table !=null && data!=null) {
+			boolean changed=false;
+			MesquiteNumber num = new MesquiteNumber();
+			num.setValue(position);
+			CodonPositionsSet modelSet = (CodonPositionsSet) data.getCurrentSpecsSet(CodonPositionsSet.class);
+			if (modelSet == null) {
+				modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+				modelSet.addToFile(data.getFile(), getProject(), findElementManager(CodonPositionsSet.class)); //THIS
+				data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+			}
+			boolean anySelected = table.anyCellSelectedAnyWay();
+			if (modelSet != null) {
+				if (employer!=null && employer instanceof ListModule) {
+					int c = ((ListModule)employer).getMyColumn(this);
+					for (int i=0; i<data.getNumChars(); i++) {
+						if (!anySelected || table.isCellSelectedAnyWay(c, i)) {
+							modelSet.setValue(i, num);
+							if (!changed)
+								outputInvalid();
+							if (calc) {
+								num.setValue(num.getIntValue()+1);
+								if (num.getIntValue()>3)
+									num.setValue(1);
+							}
+
+							changed = true;
+						}
+					}
+				}
+			}
+			if (notify) {
+				if (changed)
+					data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+				parametersChanged();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private void setPositionsMinStops(){
+		if (table !=null && data!=null) {
+			Taxa taxa = data.getTaxa();
+			int minStops = -1;
+			int posMinStops = 1;
+
+			for (int i = 1; i<=3; i++) {
+				int totNumStops = 0;
+				setPositions(i,true,false);  //set them temporarily
+
+				for (int it= 0; it<taxa.getNumTaxa(); it++) {
+					totNumStops += ((DNAData)data).getAminoAcidNumbers(it,ProteinData.TER);					 
+				}
+				
+				logln("Number of stops with first selected as codon position " + i + ": " + totNumStops);
+				if (minStops<0 || totNumStops<minStops) {
+					minStops = totNumStops;
+					posMinStops=i;
+				}
+			}
+			setPositions(posMinStops,true,true);
+		}
+
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to non-coding", null, commandName, "setPositionN")) {
+			setPositions(0, false,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to first position", null, commandName, "setPosition1")) {
+			setPositions(1, false,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to second position", null, commandName, "setPosition2")) {
+			setPositions(2, false,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to third position", null, commandName, "setPosition3")) {
+			setPositions(3, false,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to be 123123123...", null, commandName, "setPositionCalc123")) {
+			setPositions(1,true,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to be 23123123...", null, commandName, "setPositionCalc231")) {
+			setPositions(2,true,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to be 3123123...", null, commandName, "setPositionCalc312")) {
+			setPositions(3,true,true);
+		}
+		else  if (checker.compare(this.getClass(), "Sets the codon positions of the selected characters to minimize the number of stop codons", null, commandName, "setPositionCalcMinStops")) {
+			setPositionsMinStops();
+		}
+		else if (checker.compare(this.getClass(), "Stores current codon position set", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CodonPositionsSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CodonPositionsSet modelSet= new CodonPositionsSet("Codon Positions", data.getNumChars(), data);
+					modelSet.addToFile(data.getFile(), getProject(), findElementManager(CodonPositionsSet.class)); //THIS
+					data.setCurrentSpecsSet(modelSet, CodonPositionsSet.class);
+					ssv = data.getSpecSetsVector(CodonPositionsSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(CodonPositionsSet.class));
+					s.setName(ssv.getUniqueName("Codon Positions"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of codon positions to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replace stored codon position set by the current one", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CodonPositionsSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored codon positions to replace by current",MesquiteString.helpString, ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored codon positions to be the current one", "[number of codon position set to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(CodonPositionsSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); 
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mStc);
+		deleteMenuItem(mPos);
+		for (int i=0; i<numMMIS && i<setCodMMIS.length; i++)
+			deleteMenuItem(setCodMMIS[i]);
+		mPos = addSubmenu(null, "Set Codon Position");
+		setCodMMIS[0] = addItemToSubmenu(null, mPos, "N", makeCommand("setPositionN", this));
+		setCodMMIS[1] = addItemToSubmenu(null, mPos, "1", makeCommand("setPosition1", this));
+		setCodMMIS[2] = addItemToSubmenu(null, mPos, "2", makeCommand("setPosition2", this));
+		setCodMMIS[3] = addItemToSubmenu(null, mPos, "3", makeCommand("setPosition3", this));
+		setCodMMIS[4] = addItemToSubmenu(null, mPos, "123123...", makeCommand("setPositionCalc123", this));
+		setCodMMIS[5] = addItemToSubmenu(null, mPos, "231231...", makeCommand("setPositionCalc231", this));
+		setCodMMIS[6] = addItemToSubmenu(null, mPos, "312312...", makeCommand("setPositionCalc312", this));
+		setCodMMIS[7] = addItemToSubmenu(null, mPos, "Minimize Stop Codons", makeCommand("setPositionCalcMinStops", this));
+		mScs = addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load codon position set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(CodonPositionsSet.class));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Codon Position";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			CodonPositionsSet modelSet = (CodonPositionsSet)data.getCurrentSpecsSet(CodonPositionsSet.class);
+			if (modelSet != null) {
+				int i = modelSet.getInt(ic);
+				if (i==0)
+					return "N";
+				else if (i<4 && i>0)
+					return Integer.toString(i);
+				else
+					return "?";
+			}
+			else {
+				return "N";
+			}
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "Codon Position  ";
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+}
+
diff --git a/Source/mesquite/lists/CharListInclusion/CharListInclusion.java b/Source/mesquite/lists/CharListInclusion/CharListInclusion.java
new file mode 100644
index 0000000..f0f8d74
--- /dev/null
+++ b/Source/mesquite/lists/CharListInclusion/CharListInclusion.java
@@ -0,0 +1,248 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListInclusion;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListInclusion extends CharListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Inclusion";
+	}
+
+	public String getExplanation() {
+		return "Shows current character inclusion in character list window." ;
+	}
+
+	CharacterData data=null;
+	MesquiteTable table=null;
+	Image included, excluded;
+	MesquiteMenuItemSpec mss, mScs, mStc, mRssc, mLine;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Include", makeCommand("include", this));
+		addMenuItem("Exclude", makeCommand("exclude", this));
+		addMenuItem("Reverse", makeCommand("reverse", this));
+		addMenuItem("-", null);
+		return true;
+	}
+	void doChange(int which){
+		if (table !=null && data!=null) {
+			boolean changed=false;
+
+			CharInclusionSet inclusionSet = (CharInclusionSet) data.getCurrentSpecsSet(CharInclusionSet.class);
+			if (inclusionSet == null) {
+				inclusionSet= new CharInclusionSet("Inclusion Set", data.getNumChars(), data);
+				inclusionSet.selectAll();
+				inclusionSet.addToFile(data.getFile(), getProject(), findElementManager(CharInclusionSet.class)); //THIS
+				data.setCurrentSpecsSet(inclusionSet, CharInclusionSet.class);
+			}
+			if (inclusionSet != null) {
+				if (employer!=null && employer instanceof ListModule) {
+					int c = ((ListModule)employer).getMyColumn(this);
+					for (int i=0; i<data.getNumChars(); i++) {
+						if (table.isCellSelectedAnyWay(c, i)) {
+							if (which==0) //include
+								inclusionSet.setSelected(i, true);
+							else if (which==1) //exclude
+								inclusionSet.setSelected(i, false);
+							else //reverse
+								inclusionSet.setSelected(i, !inclusionSet.isBitOn(i));
+							changed = true;
+						}
+					}
+				}
+			}
+
+
+			if (changed)
+				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the selected characters to included", null, commandName, "include")) {
+			doChange(0);
+		}
+		else if (checker.compare(this.getClass(), "Sets the selected characters to excluded", null, commandName, "exclude")) {
+			doChange(1);
+		}
+		else if (checker.compare(this.getClass(), "Reverses the inclusion status of the selected characters", null, commandName, "reverse")) {
+			doChange(2);
+		}
+		else if (checker.compare(this.getClass(), "Stores the current inclusion status of all the characters as a character inclusion set", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharInclusionSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CharInclusionSet inclusionSet= new CharInclusionSet("Inclusion Set", data.getNumChars(), data);
+					inclusionSet.selectAll();
+					inclusionSet.addToFile(data.getFile(), getProject(), findElementManager(CharInclusionSet.class)); //THIS
+					data.setCurrentSpecsSet(inclusionSet, CharInclusionSet.class);
+					ssv = data.getSpecSetsVector(CharInclusionSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(CharInclusionSet.class));
+					s.setName(ssv.getUniqueName("Inclusion Set"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of character inclusion set to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replaces a stored character inclusion set by the current inclusion status of all the characters", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharInclusionSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored character inclusion set to replace by current set", MesquiteString.helpString,ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored inclusion set to be the current one", "[number of inclusion set to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(CharInclusionSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mStc);
+		mScs = addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(CharInclusionSet.class));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Inclusion";
+	}
+
+	int timesDrawn = 0;
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		if (data!=null) {
+			Color c = g.getColor();
+			CharInclusionSet inclusionSet = (CharInclusionSet) data.getCurrentSpecsSet(CharInclusionSet.class);
+			Shape clip = g.getClip();
+			g.setClip(x,y,w,h);
+			if (inclusionSet == null || inclusionSet.isBitOn(ic)) {
+				int pointX = x+(w)/2 - 2;
+				int pointY =y+ (h)/2 + 3;
+				if (selected)
+					g.setColor(ColorDistribution.darkGreen);
+				else
+					g.setColor(ColorDistribution.lightGreen);
+				g.fillRect(x+1,y+1,w,h);
+				if (selected)
+					g.setColor(Color.white);
+				else
+					g.setColor(Color.black);
+				thickLine(g,pointX,pointY, pointX+8, pointY-8);
+				thickLine(g,pointX,pointY, pointX-4, pointY-4);
+			}
+			else {
+				if (selected)
+					g.setColor(ColorDistribution.darkRed);
+				else
+					g.setColor(ColorDistribution.lightRed);
+				g.fillRect(x+1,y+1,w,h);
+				int pointX = x+(w)/2;
+				int pointY =y+ (h)/2;
+				if (selected)
+					g.setColor(Color.white);
+				else
+					g.setColor(Color.black);
+				thickLine(g,pointX-4,pointY+4, pointX+4, pointY-4);
+				thickLine(g,pointX+4,pointY+4, pointX-4, pointY-4);
+			}
+
+			if (c!=null) g.setColor(c);
+			g.setClip(clip);
+		}
+	}
+	void thickLine(Graphics g, int x1, int y1, int x2, int y2){
+		for (int i=0; i<2; i++) {
+			g.drawLine(x1+i,y1, x2+i, y2);
+			g.drawLine(x1,y1, x2, y2);
+			g.drawLine(x1,y1+i, x2, y2+i);
+			g.drawLine(x1+i,y1+i, x2+i, y2+i);
+		}
+	}
+	public  boolean useString(int ic){
+		return false;
+	}
+	public  String getStringForRow(int ic){
+		try{
+			CharInclusionSet inclusionSet = (CharInclusionSet) data.getCurrentSpecsSet(CharInclusionSet.class);
+			if (inclusionSet == null || inclusionSet.isBitOn(ic)) {
+				return "included";
+			}
+			else {
+				return "excluded";
+			}
+		}
+		catch (NullPointerException e){
+		}
+		return "";
+	}
+	public int getColumnWidth(){
+		return 16;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+}
+
diff --git a/Source/mesquite/lists/CharListPartition/CharListPartition.java b/Source/mesquite/lists/CharListPartition/CharListPartition.java
new file mode 100644
index 0000000..62d1a8b
--- /dev/null
+++ b/Source/mesquite/lists/CharListPartition/CharListPartition.java
@@ -0,0 +1,356 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListPartition;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListPartition extends CharListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Group Membership (characters)";
+	}
+	public String getExplanation() {
+		return "Lists and allows changes to group membership in the current partition of characters, for List of Characters window." ;
+	}
+	/*.................................................................................................................*/
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss, mEGC, mDGC, mEGN;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine, nNG, mLine2, mss2;
+	CharactersGroupVector groups;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+		groups.addListener(this);
+		return true;
+	}
+	public void endJob(){
+		if (data != null)
+			data.removeListener(this);
+		if (groups != null)
+			groups.removeListener(this);
+		super.endJob();
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	private void setPartition(CharactersGroup group, String arguments){
+		if (table !=null && data!=null) {
+			boolean changed=false;
+			String name = parser.getFirstToken(arguments);
+			if (group == null && StringUtil.blank(name))
+				return;
+			CharacterPartition partition = (CharacterPartition) data.getCurrentSpecsSet(CharacterPartition.class);
+			if (partition==null){
+				partition= new CharacterPartition("Partition", data.getNumChars(), null, data);
+				partition.addToFile(data.getFile(), getProject(), findElementManager(CharacterPartition.class));
+				data.setCurrentSpecsSet(partition, CharacterPartition.class);
+			}
+			if (group == null){
+				CharactersGroupVector groups = (CharactersGroupVector)getProject().getFileElement(CharactersGroupVector.class, 0);
+				Object obj = groups.getElement(name);
+				group = (CharactersGroup)obj;
+			}
+			if (group != null) {
+				if (partition != null) {
+					if (employer!=null && employer instanceof ListModule) {
+						int c = ((ListModule)employer).getMyColumn(this);
+						for (int i=0; i<data.getNumChars(); i++) {
+							if (table.isCellSelectedAnyWay(c, i)) {
+								partition.setProperty(group, i);
+								if (!changed)
+									outputInvalid();
+								changed = true;
+							}
+						}
+					}
+				}
+				if (changed)
+					data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+							outputInvalid();
+							parametersChanged();
+			}
+		}
+	}
+	private void removePartition(){
+		if (table !=null && data!=null) {
+			boolean changed=false;
+			CharacterPartition partition = (CharacterPartition) data.getCurrentSpecsSet(CharacterPartition.class);
+			if (partition!=null){
+				if (employer!=null && employer instanceof ListModule) {
+					int c = ((ListModule)employer).getMyColumn(this);
+					for (int i=0; i<data.getNumChars(); i++) {
+						if (table.isCellSelectedAnyWay(c, i)) {
+							partition.setProperty(null, i);
+							if (!changed)
+								outputInvalid();
+							changed = true;
+						}
+					}
+				}
+
+				if (changed)
+					data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+							outputInvalid();
+							parametersChanged();
+
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the character group of the selected characters", "[name of group]", commandName, "setPartition")) {
+			setPartition(null, arguments);
+		}
+		else if (checker.compare(this.getClass(), "Edits the name and color of a character group label", "[name of group]", commandName, "editGroup")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name))
+				return null;
+			String num = parser.getNextToken();
+			Object obj = CharListPartitionUtil.editGroup(this, data,containerOfModule(),name, num);
+			if (obj!=null) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deletes a character group label", "[name of group]", commandName, "deleteGroup")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name))
+				return null;
+			String num = parser.getNextToken();
+			boolean b = CharListPartitionUtil.deleteGroup(this, data,containerOfModule(),name, num);
+			if (b) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Creates a new group for use in character partitions", null, commandName, "newGroup")) {
+			MesquiteString ms = new MesquiteString("");
+			CharactersGroup group = CharListPartitionUtil.makeGroup(this,data,containerOfModule(), ms);
+			if (group==null) return null;
+			setPartition(group, ms.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Stores the current character partition set", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharacterPartition.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CharacterPartition partition= new CharacterPartition("Partition", data.getNumChars(), null, data);
+					partition.addToFile(data.getFile(), getProject(), findElementManager(CharacterPartition.class));
+					data.setCurrentSpecsSet(partition, CharacterPartition.class);
+					ssv = data.getSpecSetsVector(CharacterPartition.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(CharacterPartition.class));
+					s.setName(ssv.getUniqueName("Partition"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of character partition to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+			//return ((ListWindow)getModuleWindow()).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Replaces a stored character partition set by the current one", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharacterPartition.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored partition to replace by current set",MesquiteString.helpString, ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored character partition to be the current one", "[number of partition to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(CharacterPartition.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the group designation from the selected characters", null, commandName, "removeGroup")) {
+			removePartition();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		/* hire employees here */
+		deleteMenuItem(mss);
+		deleteMenuItem(mss2);
+		deleteMenuItem(mScs);
+	//	deleteMenuItem(mScsPF);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mLine2);
+		deleteMenuItem(mStc);
+		deleteMenuItem(nNG);
+		deleteMenuItem(mEGC);
+		deleteMenuItem(mDGC);
+		deleteMenuItem(mEGN);
+		deleteMenuItem(nNG);
+		mss = addSubmenu(null, "Set Group", makeCommand("setPartition", this));
+		mss.setList((StringLister)getProject().getFileElement(CharactersGroupVector.class, 0));
+		mss2 = addMenuItem("Remove Group Designation", makeCommand("removeGroup", this));
+		mLine2 = addMenuItem("-",null);
+		nNG = addMenuItem("New Group...", makeCommand("newGroup",  this));
+		mEGC = addSubmenu(null, "Edit Group...", makeCommand("editGroup", this));
+		mEGC.setList((StringLister)getProject().getFileElement(CharactersGroupVector.class, 0));
+		mDGC = addSubmenu(null, "Delete Group...", makeCommand("deleteGroup", this));
+		mDGC.setList((StringLister)getProject().getFileElement(CharactersGroupVector.class, 0));
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current partition...", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored partition by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(CharacterPartition.class));
+		//mScsPF = addMenuItem("Create Partition Based upon RAxML Format...", makeCommand("createByRAxML",  this));
+		this.data = data;
+		this.table = table;
+		if (data != this.data){
+			if (this.data != null)
+			this.data.removeListener(this);
+			data.addListener(this);
+		}
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (caller == this)
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Group";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			CharacterPartition partition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+			if (partition != null) {
+				CharactersGroup group = (CharactersGroup)partition.getProperty(ic);
+				if (group!=null) {
+					return group.getName();
+				}
+			}
+		}
+		return "?";
+	}
+	public boolean useString(int ic){
+		return false;
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		if (data==null || g==null)
+			return;
+		boolean colored = false;
+		Color c = g.getColor();
+		CharacterPartition part = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		if (part!=null) {
+			CharactersGroup tg = part.getCharactersGroup(ic);
+			if (tg!=null){
+				Color cT = tg.getColor();
+				if (cT!=null){
+					g.setColor(cT);
+					g.fillRect(x+1,y+1,w-1,h-1);
+					colored = true;
+				}
+			}
+		}
+		if (!colored){ 
+			if (selected)
+				g.setColor(Color.black);
+			else
+				g.setColor(Color.white);
+			g.fillRect(x+1,y+1,w-1,h-1);
+		}
+
+		String s = getStringForRow(ic);
+		if (s!=null){
+			FontMetrics fm = g.getFontMetrics(g.getFont());
+			if (fm==null)
+				return;
+			int sw = fm.stringWidth(s);
+			int sh = fm.getMaxAscent()+ fm.getMaxDescent();
+			if (selected)
+				g.setColor(Color.white);
+			else
+				g.setColor(Color.black);
+			g.drawString(s, x+(w-sw)/2, y+h-(h-sh)/2);
+			if (c!=null) g.setColor(c);
+		}
+	}
+	public String getWidestString(){
+		if (data!=null) {
+			int length = 20;
+			String longest = null;
+			CharacterPartition partition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+			if (partition != null) {
+				for (int ic= 0; ic< data.getNumChars(); ic++){
+					CharactersGroup group = (CharactersGroup)partition.getProperty(ic);
+					if (group!=null) {
+						String s = group.getName();
+						if (s != null)
+							if (s.length()> length) {  //just counting string length to avoid font metrics calculations
+								length = s.length();
+								longest = s;
+							}
+					}
+				}
+				if (longest !=null)
+					return longest;
+			}
+		}
+		return "Partition     ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+}
+
+
diff --git a/Source/mesquite/lists/CharListUniqueID/CharListUniqueID.java b/Source/mesquite/lists/CharListUniqueID/CharListUniqueID.java
new file mode 100644
index 0000000..07543ca
--- /dev/null
+++ b/Source/mesquite/lists/CharListUniqueID/CharListUniqueID.java
@@ -0,0 +1,140 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListUniqueID;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListUniqueID extends CharListAssistant  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Unique ID (characters)";
+	}
+	public String getExplanation() {
+		return "Shows unique id assigned to character." ;
+	}
+
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		addMenuItem("Replace Unique IDs", makeCommand("replaceIDs",  this));
+		addMenuItem("Fill Missing Unique IDs", makeCommand("fillMissingIDs",  this));
+		addMenuItem("Remove Unique IDs", makeCommand("removeIDs",  this));
+		return true;
+	}
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Replaces the uniqueIDs of selected", null, commandName, "replaceIDs")) {
+			if (data != null) {
+				stamp(true);
+			}
+			//outputInvalid();
+		}
+		else if (checker.compare(this.getClass(), "Removes the uniqueIDs of selected", null, commandName, "removeIDs")) {
+			if (data != null) {
+				remove();
+			}
+			//outputInvalid();
+		}
+		else if (checker.compare(this.getClass(), "Fills in any missing uniqueIDs of selected", null, commandName, "fillMissingIDs")) {
+			if (data != null)
+				stamp(false);
+			//outputInvalid();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	void stamp(boolean replace){
+		if (data ==null)
+			return;
+		boolean changed=false;
+		boolean noneSelected = !table.anyCellSelectedAnyWay();
+		if (employer!=null && employer instanceof ListModule) {
+			int c = ((ListModule)employer).getMyColumn(this);
+			for (int i=0; i<data.getNumChars(); i++) {
+				if (noneSelected || table.isCellSelectedAnyWay(c, i)) {
+					data.stampUniqueID(i, replace);
+					if (!changed)
+						outputInvalid();
+					changed = true;
+				}
+			}
+		}
+		if (changed)
+			parametersChanged();
+	}
+	void remove(){
+		if (data ==null)
+			return;
+		boolean changed=false;
+		boolean noneSelected = !table.anyCellSelectedAnyWay();
+		if (employer!=null && employer instanceof ListModule) {
+			int c = ((ListModule)employer).getMyColumn(this);
+			for (int i=0; i<data.getNumChars(); i++) {
+				if (noneSelected || table.isCellSelectedAnyWay(c, i)) {
+					data.setUniqueID(i, null);
+					if (!changed)
+						outputInvalid();
+					changed = true;
+				}
+			}
+		}
+		if (changed)
+			parametersChanged();
+	}
+	public String getStringForCharacter(int ic){
+		String s = null;
+		if (data != null)
+			s = data.getUniqueID(ic); //+1 because zero based
+		if (StringUtil.blank(s))
+			s = "?";
+		return s;
+	}
+	public String getWidestString(){
+		return "88888888888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "ID";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+
+}
+
diff --git a/Source/mesquite/lists/CharListWeights/CharListWeights.java b/Source/mesquite/lists/CharListWeights/CharListWeights.java
new file mode 100644
index 0000000..a2b9cb4
--- /dev/null
+++ b/Source/mesquite/lists/CharListWeights/CharListWeights.java
@@ -0,0 +1,193 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharListWeights;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListWeights extends CharListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Current Weights";
+	}
+	public String getExplanation() {
+		return "Supplies current weights applied to characters for character list window." ;
+	}
+
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine, mwt;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the weight of the selected characters", "[weight]", commandName, "setWeight")) {
+			if (table !=null && data!=null) {
+				boolean changed=false;
+				MesquiteNumber num = new MesquiteNumber();
+				num.setValue(arguments);
+				if (!num.isCombinable()) {
+					num.setValue(1);
+					num.setValue(MesquiteNumber.queryNumber(containerOfModule(), "Set Weight", "Set weight of selected characters", num));
+				}
+				if (!num.isCombinable())
+					return null;
+
+				CharWeightSet weightSet = (CharWeightSet) data.getCurrentSpecsSet(CharWeightSet.class);
+				if (weightSet == null) {
+					weightSet= new CharWeightSet("Weight Set", data.getNumChars(), data);
+					weightSet.addToFile(data.getFile(), getProject(), findElementManager(CharWeightSet.class)); //THIS
+					data.setCurrentSpecsSet(weightSet, CharWeightSet.class);
+				}
+				if (weightSet != null) {
+					if (employer!=null && employer instanceof ListModule) {
+						int c = ((ListModule)employer).getMyColumn(this);
+						for (int i=0; i<data.getNumChars(); i++) {
+							if (table.isCellSelectedAnyWay(c, i)) {
+								weightSet.setValue(i, num);
+								if (!changed)
+									outputInvalid();
+
+								changed = true;
+							}
+						}
+					}
+				}
+
+
+				if (changed)
+					data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Stores current weight set (WTSET)", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharWeightSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CharWeightSet weightSet= new CharWeightSet("Weight Set", data.getNumChars(), data);
+					weightSet.addToFile(data.getFile(), getProject(), findElementManager(CharWeightSet.class)); //THIS
+					data.setCurrentSpecsSet(weightSet, CharWeightSet.class);
+					ssv = data.getSpecSetsVector(CharWeightSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(CharWeightSet.class));
+					s.setName(ssv.getUniqueName("Weight Set"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of weight set to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replace stored weight set (WTSET) by the current one", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(CharWeightSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored weight set to replace by current set", MesquiteString.helpString,ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored weight set to be the current one", "[number of weight set to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(CharWeightSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mStc);
+		deleteMenuItem(mwt);
+		mwt = addMenuItem("Set Weight...", makeCommand("setWeight", this));
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load weight set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(CharWeightSet.class));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Weights";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			CharWeightSet weightSet = (CharWeightSet)data.getCurrentSpecsSet(CharWeightSet.class);
+			if (weightSet != null) {
+				return weightSet.toString(ic);
+			}
+			else {
+				return "1";
+			}
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "888888888  ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+}
+
diff --git a/Source/mesquite/lists/CharNumForList/CharNumForList.java b/Source/mesquite/lists/CharNumForList/CharNumForList.java
new file mode 100644
index 0000000..c0dde5d
--- /dev/null
+++ b/Source/mesquite/lists/CharNumForList/CharNumForList.java
@@ -0,0 +1,311 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharNumForList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharNumForList extends CharListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Character (in List of Characters window)";
+	}
+	public String getNameForMenuItem() {
+		return "Number for Character";
+	}
+	public String getExplanation() {
+		return "Supplies numbers for characters for a character list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharacter.class, getName() + " needs a method to calculate a value for each of the characters.",
+		"You can select a value to show in the Number For Characters submenu of the Columns menu of the List of Characters Window. ");
+		e.setPriority(1);
+	}
+	/*.................................................................................................................*/
+	CharacterData data=null;
+	MesquiteTable table=null;
+	NumberForCharacter numberTask;
+	Object dataCondition;
+	MesquiteBoolean shadeCells;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments!=null) {
+			numberTask = (NumberForCharacter)hireNamedEmployee(NumberForCharacter.class, arguments);
+			if (numberTask==null) {
+				return sorry("Number for character (for character list) could not start because the requested calculator module was not obtained");
+			}
+		}
+		if (!MesquiteThread.isScripting() && numberTask == null) {
+			numberTask = (NumberForCharacter)hireEmployee(NumberForCharacter.class, "Value to calculate for characters (for Character List)");
+			if (numberTask==null) {
+				return sorry("Number for character (for character list) could not start because no calculator module was obtained");
+			}
+		}
+		shadeCells = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Color Cells", makeCommand("toggleShadeCells",  this), shadeCells);
+		addMenuItem(null, "Select based on value...", makeCommand("selectBasedOnValue",  this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return NumberForCharacter.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", numberTask); 
+		temp.addLine("toggleShadeCells " + shadeCells.toOffOnString());
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public boolean querySelectBounds(MesquiteNumber lessThan, MesquiteNumber moreThan) {
+		if (lessThan==null || moreThan==null || numberTask==null)
+			return false;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Select based upon value",buttonPressed); 
+
+		dialog.addLargeOrSmallTextLabel("Select based upon value of " + numberTask.getNameOfValueCalculated());
+
+		SingleLineTextField moreThanField = dialog.addTextField("Select values greater than or equal to ","",20);
+		SingleLineTextField lessThanField = dialog.addTextField("Select values less than or equal to ","",20);
+
+
+		dialog.completeAndShowDialog(true);
+
+		if (buttonPressed.getValue()==0)  {
+			String s = moreThanField.getText();
+			moreThan.setValue(s);
+			s = lessThanField.getText();
+			lessThan.setValue(s);
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void SelectBasedOnValue() {
+		if (MesquiteThread.isScripting())
+			return;
+		if (table==null || data==null || na==null)
+			return;
+		MesquiteNumber lessThan = new MesquiteNumber();
+		MesquiteNumber moreThan = new MesquiteNumber();
+		if (!querySelectBounds(lessThan, moreThan))
+			return;
+		if (!lessThan.isCombinable() && ! moreThan.isCombinable())
+			return;
+		MesquiteNumber value = new MesquiteNumber();
+		for (int i=0; i<data.getNumChars(); i++) {
+			na.placeValue(i, value);
+
+			if (lessThan.isCombinable() && moreThan.isCombinable()) {
+				if ((lessThan.isMoreThan(value)|| lessThan.equals(value)) &&  (moreThan.isLessThan(value) ||  moreThan.equals(value))) {
+					table.selectRow(i);
+					data.setSelected(i, true);
+					table.redrawFullRow(i);
+				}
+			} else if (lessThan.isCombinable() && (lessThan.isMoreThan(value)|| lessThan.equals(value))) {
+				table.selectRow(i);
+				data.setSelected(i, true);
+				table.redrawFullRow(i);
+			} else if (moreThan.isCombinable() && (moreThan.isLessThan(value) ||  moreThan.equals(value))) {
+				table.selectRow(i);
+				data.setSelected(i, true);
+				table.redrawFullRow(i);
+			}
+		}
+		data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module to calculate a number for each character", "[name of module]", commandName, "setValueTask")) {
+			NumberForCharacter temp= (NumberForCharacter)replaceEmployee(NumberForCharacter.class, arguments, "Number for a character", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects list rows based on value of this column", null, commandName, "selectBasedOnValue")) {
+			SelectBasedOnValue();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to color cells", "[on or off]", commandName, "toggleShadeCells")) {
+			boolean current = shadeCells.getValue();
+			shadeCells.toggleValue(parser.getFirstToken(arguments));
+			if (current!=shadeCells.getValue()) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getTitle() {
+		if (numberTask==null)
+			return "";
+		return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == data)
+			data=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (code == AssociableWithSpecs.SPECSSET_CHANGED || code == MesquiteListener.VALUE_CHANGED ||code == MesquiteListener.DATA_CHANGED || code == MesquiteListener.PARTS_CHANGED || code == MesquiteListener.PARTS_ADDED || code == MesquiteListener.PARTS_DELETED || code == MesquiteListener.PARTS_MOVED){
+			if (!suppressed){
+				outputInvalid();
+				doCalcs();
+				parametersChanged(notification);
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (data==null)
+			return;
+		if (this.data !=null)
+			this.data.removeListener(this);
+		this.data = data;
+		this.table=table;
+		data.addListener(this);
+		if (!suppressed)
+			doCalcs();
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	NumberArray na = new NumberArray(0);
+	StringArray explArray = new StringArray(0);
+	MesquiteNumber min = new MesquiteNumber();
+	MesquiteNumber max = new MesquiteNumber();
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (numberTask==null || data == null || suppressed)
+			return;
+		int numChars = data.getNumChars();
+		na.resetSize(numChars);
+		explArray.resetSize(numChars);
+		MesquiteString expl = new MesquiteString();
+		na.deassignArrayToInteger();
+		MesquiteNumber mn = new MesquiteNumber();
+		for (int ic=0; ic<numChars; ic++) {
+
+			CommandRecord.tick("Number for character in character list; examining character " + ic);
+			CharacterDistribution states = data.getCharacterDistribution(ic);
+			mn.setToUnassigned();
+			numberTask.calculateNumber(states, mn, expl);
+			na.setValue(ic, mn);
+			explArray.setValue(ic, expl.getValue());
+		}
+		na.placeMinimumValue(min);
+		na.placeMaximumValue(max);
+	}
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		if (!shadeCells.getValue())
+			return null;
+		if (min.isCombinable() && max.isCombinable() && na != null && na.isCombinable(ic)){
+			return MesquiteColorTable.getGreenScale(na.getDouble(ic), min.getDoubleValue(), max.getDoubleValue(), false);
+		}
+		return null;
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+	public String getStringForCharacter(int ic){
+		if (na==null)
+			return "";
+		return na.toString(ic); 
+	}
+	public String getWidestString(){
+		if (numberTask==null)
+			return "888888";
+		return numberTask.getVeryShortName()+"   ";
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		if (data !=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/CharPartitionList/CharPartitionList.java b/Source/mesquite/lists/CharPartitionList/CharPartitionList.java
new file mode 100644
index 0000000..27a11f9
--- /dev/null
+++ b/Source/mesquite/lists/CharPartitionList/CharPartitionList.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharPartitionList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CharPartitionList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Character Partitions";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character partitions." ;
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Character Partition...", makeCommand("newCharPartition",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	public Class getItemType(){
+		return CharacterPartition.class;
+	}
+	public String getItemTypeName(){
+		return "Character partition";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character partitions";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new CharacterPartition("Partition", data.getNumChars(), null, data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new character partition", null, commandName, "newCharPartition")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Partition", "To make a new partition of characters, go to the List of Characters window, make sure that a column for Current Partition appears, edit the column, then save the partition.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListPartition", checker);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lists/CharSetList/CharSetList.java b/Source/mesquite/lists/CharSetList/CharSetList.java
new file mode 100644
index 0000000..f32b3a4
--- /dev/null
+++ b/Source/mesquite/lists/CharSetList/CharSetList.java
@@ -0,0 +1,97 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharSetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharSetList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Character Sets";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character sets." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSetListAsst.class, "The List of Character Sets window can display columns showing information for each character set.",
+		"You can request that columns be shown using the Columns menu of the List of Character Sets Window. ");
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	DataSpecsListWindow window;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Character Set...", makeCommand("newCharSet",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	/*.................................................................................................................*/
+	public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+		super.showListWindow(obj);
+		CharSetListAsst assistant = (CharSetListAsst)hireNamedEmployee(CharSetListAsst.class, "#CharSetListNum");
+		if (assistant!= null){
+			((ListWindow)getModuleWindow()).addListAssistant(assistant);
+			assistant.setUseMenubar(false);
+		}
+	}
+	public boolean usesCurrentSet(){
+		return false;
+	}
+	public Class getItemType(){
+		return CharSelectionSet.class;
+	}
+	public String getItemTypeName(){
+		return "Character set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new CharSelectionSet("Character Set", data.getNumChars(), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new character set (CHARSET)", null, commandName, "newCharSet")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Character Set", "To make a new character set (CHARSET), go to the List of Characters window, select the characters you want to be part of the set, and choose Save Selected As Set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lists/CharSetListNum/CharSetListNum.java b/Source/mesquite/lists/CharSetListNum/CharSetListNum.java
new file mode 100644
index 0000000..1e5894f
--- /dev/null
+++ b/Source/mesquite/lists/CharSetListNum/CharSetListNum.java
@@ -0,0 +1,101 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharSetListNum;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharSetListNum extends CharSetListAsst implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of characters in character set";
+	}
+
+	public String getExplanation() {
+		return "Indicates number of characters in character set in list window." ;
+	}
+	CharacterData data=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (data !=null)
+			data.removeListener(this);
+		if (obj instanceof CharacterData)
+			data = (CharacterData)obj;
+		if (data !=null)
+			data.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# chars. included";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (data == null)
+				return null;
+			SpecsSetVector tsets = data.getSpecSetsVector(CharSelectionSet.class);
+			if (tsets ==null || ic<0 || ic>= tsets.size())
+				return "";
+			return Integer.toString(((CharSelectionSet)tsets.elementAt(ic)).numberSelected());
+		}
+		catch (NullPointerException e){
+		}
+		return "";
+	}
+	public String getWidestString(){
+		return " # chars. included ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (data !=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/CharacterList/CharacterList.java b/Source/mesquite/lists/CharacterList/CharacterList.java
new file mode 100644
index 0000000..c304489
--- /dev/null
+++ b/Source/mesquite/lists/CharacterList/CharacterList.java
@@ -0,0 +1,586 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharacterList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CharacterList extends ListModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing characters and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharListAssistant.class, getName() + " uses various assistants to display columns showing information for each character.",
+				"You can request that columns be shown using the Columns menu of the List of Characters Window. ");
+		e.setEntryCommand("newAssistant");
+		EmployeeNeed e2 = registerEmployeeNeed(CharListAssistantI.class, getName() + " uses various assistants to display columns showing information for each character.",
+				"These are activated automatically. ");
+		EmployeeNeed e3 = registerEmployeeNeed(CharSelectCoordinator.class, getName() + " uses various criteria to select characters in the List of Characters window.",
+				"You can request selection methods using the List menu of the List of Characters Window. ");
+	}
+	/*.................................................................................................................*/
+	int currentDataSet = 0;
+	public CharacterData data = null;
+	CharacterListWindow window;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Rename Matrix...", MesquiteModule.makeCommand("renameMatrix",  this));
+		addMenuItem("Delete Matrix...", MesquiteModule.makeCommand("deleteMatrix",  this));
+		addMenuItem("Show Matrix", MesquiteModule.makeCommand("showMatrix",  this));
+		addMenuItem( "-", null);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean showing(Object obj){
+		if (obj instanceof String) {
+			String arguments = (String)obj;
+			int queryDataSet = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			return (queryDataSet == currentDataSet && window!=null);
+		}
+		if (obj instanceof CharacterData) {
+			if (data == null){
+				CharacterData d = (CharacterData)obj;
+				int queryDataSet = getProject().getMatrixNumber(d);
+				return (queryDataSet == currentDataSet && window!=null);
+			}
+			else {
+				return data == obj;
+			}
+		}
+		return false;
+	}
+
+	public Object getAddColumnCompatibility(){
+		if (data == null)
+			return null;
+		else 
+			return data.getStateClass();
+	}
+	/*.................................................................................................................*/
+	public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+		if (obj instanceof CharacterData) {
+			data = (CharacterData)obj;
+			currentDataSet = getProject().getMatrixNumber(data);
+		}
+		else 
+			data = getProject().getCharacterMatrix(currentDataSet); //todo: 
+		window = new CharacterListWindow(this);
+		((CharacterListWindow)window).setObject(data);
+		setModuleWindow(window);
+		makeMenu("List");
+
+		addMenuItem( "Save selected as set...", makeCommand("saveSelectedRows", this));
+		addMenuItem( "-", null);
+		if (!MesquiteThread.isScripting()){
+			CharListAssistant assistant= null;
+			if (!(data instanceof MolecularData)){ //added 1. 06
+				assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, "#DefaultCharOrder");
+				if (assistant!= null){
+					((CharacterListWindow)window).addListAssistant(assistant);
+					assistant.setUseMenubar(false);
+				}
+			}
+			assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, "#CharListInclusion");
+			if (assistant!= null){
+				((CharacterListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/**/
+			assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, "States");
+			if (assistant!= null){
+				((CharacterListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/* default columns*/
+			//	if (!(data instanceof MolecularData)){ //added 1. 06; removed after 2. 75
+			assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, StringUtil.tokenize("#CharListPartition"));
+			if (assistant!= null){
+				((CharacterListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			//	}
+			if (!(data instanceof MolecularData)){ 
+				assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, StringUtil.tokenize("#CharListParsModels"));
+				if (assistant!= null){
+					((CharacterListWindow)window).addListAssistant(assistant);
+					assistant.setUseMenubar(false);
+				}
+			}
+			/*
+			assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, StringUtil.tokenize("#CharListProbModels"));
+			if (assistant!= null){
+				((CharacterListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			 */
+			if (data instanceof DNAData) {
+				assistant = (CharListAssistant)hireNamedEmployee(CharListAssistant.class, StringUtil.tokenize("#CharListCodonPos"));
+				if (assistant!= null){
+					((CharacterListWindow)window).addListAssistant(assistant);
+					assistant.setUseMenubar(false);
+				}
+			}
+			/**/
+		}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	/*...............................................................................................................*/
+	public Undoer getSingleNameUndoInstructions(int row, String oldName, String s){
+		if (window!=null)
+			return new UndoInstructions(UndoInstructions.SINGLECHARACTERNAME, row, new MesquiteString(oldName), new MesquiteString(s),data,window.getTable());
+		else 
+			return new UndoInstructions(UndoInstructions.SINGLECHARACTERNAME, row, new MesquiteString(oldName), new MesquiteString(s),data,null);
+	}
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return true;
+	}
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return data;
+	}
+	public int getNumberOfRows(){
+		if (data==null)
+			return 0;
+		else
+			return data.getNumChars();
+	}
+	public Class getAssistantClass(){
+		return CharListAssistant.class;
+	}
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (data!=null) {
+			data.deleteCharacters(row, 1, notify);
+			data.deleteInLinked(row, 1, notify);
+			return true;
+		}
+		return false;
+	}
+	public boolean deleteRows(int first, int last, boolean notify){
+		if (data!=null) {
+			data.deleteCharacters(first, last-first+1, notify);
+			data.deleteInLinked(first, last-first+1, notify);
+			return true;
+		}
+		return false;
+	}
+	public void notifyRowDeletion(Object obj){
+		if (obj == data) {
+			((Listenable)obj).notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+			((CharacterData)obj).notifyInLinked(new Notification(MesquiteListener.PARTS_DELETED));
+		}
+	}
+	/** returns either a String (if not editable) or a MesquiteString (if to be editable) */
+	public String getAnnotation(int row){
+		if (data !=null) {
+			return data.getAnnotation(row);
+		}
+		return null;
+	}
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		if (data !=null) {
+			data.setAnnotation(row, s);
+		}
+	}
+
+	/** returns a String explaining the row */
+	public String getExplanation(int row){
+		return null;
+	}
+	public String getItemTypeName(){
+		return "Character";
+	}
+	public String getItemTypeNamePlural(){
+		return "Characters";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (window==null || !window.isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+
+		if (data != null)
+			currentDataSet = getProject().getMatrixNumber(data);
+
+		temp.addLine("setData " + currentDataSet); 
+
+		if (window!=null)
+			window.incorporateSnapshot(temp, file);
+		//if (window!=null && !window.isVisible())
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Renames the matrix", "[name of matrix]", commandName, "renameMatrix")) {
+			if (data == null)
+				return null;
+			String token = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+			if (StringUtil.blank(token) && !MesquiteThread.isScripting()) {
+				token = MesquiteString.queryString(containerOfModule(), "Rename matrix", "New Name of Matrix:", data.getName(), 2);
+				if (StringUtil.blank(token))
+					return null;
+			}
+			data.setName(token);
+			MesquiteWindow.resetAllTitles();
+
+		}
+		else if (checker.compare(this.getClass(), "Deletes the matrix", null, commandName, "deleteMatrix")) {
+			if (data == null)
+				return null;
+			if (!MesquiteThread.isScripting())
+				if (!AlertDialog.query(containerOfModule(), "Delete matrix?", "Are you sure you want to delete the matrix?  You cannot undo this."))
+					return null;
+			data.deleteMe(false);
+
+		}
+		else if (checker.compare(this.getClass(), "Shows the matrix", null, commandName, "showMatrix")) {
+			data.showMatrix();
+		}
+		else if (checker.compare(this.getClass(), "Sets data set whose characters are to be displayed in this list window", "[number of data set]", commandName, "setData")) {
+			int tempCurrDataSet = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (window!=null && MesquiteInteger.isCombinable(tempCurrDataSet) && tempCurrDataSet<getProject().getNumberCharMatrices()) {
+				currentDataSet = tempCurrDataSet;
+				data = getProject().getCharacterMatrix(currentDataSet);//checker.getFile(), 
+				((CharacterListWindow)window).setObject(data);
+				((CharacterListWindow)window).repaintAll();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns data set whose characters are listed", null, commandName, "getData")) {
+			return ((CharacterListWindow)window).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Saves the selected rows as a character set", null, commandName, "saveSelectedRows")) {
+			((CharacterListWindow)window).saveSelectedRows();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void endJob(){
+		if (data!=null) {
+			data.removeListener(this);
+			if (data.getTaxa()!=null)
+				data.getTaxa().removeListener(this);
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (data!=null) {
+			return "Character matrix: " + data.getName();
+		}
+		return "";
+	}
+
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+/* ======================================================================== */
+class CharacterListWindow extends ListWindow implements MesquiteListener {
+	private int currentDataSet = 0;
+	CharacterData data = null;
+	CharSelectCoordinator selectionCoordinator;
+	CharacterList listModule;
+	public CharacterListWindow (CharacterList ownerModule) {
+		super(ownerModule); //INFOBAR
+		this.listModule = ownerModule;
+		currentDataSet = ownerModule.currentDataSet;
+		data = ownerModule.getProject().getCharacterMatrix(currentDataSet);
+		getTable().setRowAssociable(data);
+		MesquiteButton matrixButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("showMatrix",  ownerModule), null, true, MesquiteModule.getRootImageDirectoryPath() + "matrix.gif", 12, 16);
+		matrixButton.setShowBackground(false);
+		matrixButton.setButtonExplanation("Show Character Matrix Editor");
+		setIcon(MesquiteModule.getRootImageDirectoryPath() + "windowIcons/listC.gif");
+
+		table.addControlButton(matrixButton);
+		ownerModule.hireAllCompatibleEmployees(CharTableAssistantI.class, data.getStateClass()); 
+		Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof CharTableAssistantI) {
+				CharTableAssistantI init = (CharTableAssistantI)obj;
+				init.setTableAndData(getTable(), data, true);
+			}
+		}
+		ownerModule.hireAllCompatibleEmployees(CharListAssistantI.class, data.getStateClass()); 
+		enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof CharListAssistantI) {
+				CharListAssistantI init = (CharListAssistantI)obj;
+				init.setTableAndData(getTable(), data);
+			}
+		}
+		if (getTable() != null)
+			getTable().setDropDown(-1, -1, true);
+		selectionCoordinator = (CharSelectCoordinator)ownerModule.hireEmployee(CharSelectCoordinator.class, null);
+		if (selectionCoordinator!=null)
+			selectionCoordinator.setTableAndObject(getTable(), data, true);
+	}
+	/*
+	protected ToolPalette makeToolPalette(){
+		return new CharListPalette((CharacterList)ownerModule, this);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (data!=null&& data.hasTitle()){
+			if (data.uniquelyNamed())
+
+				setTitle("Characters \"" + data.getName() + "\""); 
+			else
+				setTitle("Characters \"" + data.getName() + "\" [" + data.getID() + "]"); 
+
+		}
+		else if (data==null)
+			setTitle("Characters (DATA NULL)" ); 
+		else	if (data.uniquelyNamed())
+
+			setTitle("Characters" ); 
+		else
+			setTitle("Characters [" + data.getID() + "]"); 
+
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s) || data == null)
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		String listData = data.searchData(s, commandResult);
+
+		if (!StringUtil.blank(listData))
+			return "<h2>Matches to search string: \"" + s + "\"</h2>" + listData;
+		else
+			return "<h2>No matches found (searched: \"" + s + "\")</h2>";
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Selects character", "[number of character]", commandName, "selectCharacter")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+			if (which >= 0 && which < data.getNumChars()){
+				if (!table.isCellVisible(-1, which)){
+					table.setFocusedCell(-1, which, true);
+					table.repaintAll();
+				}
+				data.setSelected(which, !data.getSelected(which));
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public Object getCurrentObject(){
+		return data;
+	}
+
+	public void setCurrentObject(Object obj){
+		if (obj instanceof CharacterData) {
+			if (data == null || data != obj){
+				if (data!=null) {
+					data.removeListener(this);
+					if (data.getTaxa()!=null)
+						data.getTaxa().removeListener(this);
+				}
+				data = (CharacterData)obj;
+				data.addListener(this); //TODO: this needs to be done for taxon lists, etc.
+				data.getTaxa().addListener(this);
+			}
+			getTable().setRowAssociable(data);
+			getTable().setDropDown(-1, -1, true);
+			resetTitle();
+			if (selectionCoordinator!=null)
+				selectionCoordinator.setTableAndObject(getTable(), data, true);
+			Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()){
+				Object ct = enumeration.nextElement();
+				if (ct instanceof CharTableAssistantI) {
+					CharTableAssistantI init = (CharTableAssistantI)ct;
+					init.setTableAndData(getTable(), data, true);
+				}
+			}
+			enumeration=ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()){
+				Object ct = enumeration.nextElement();
+				if (ct instanceof CharListAssistantI) {
+					CharListAssistantI init = (CharListAssistantI)ct;
+					init.setTableAndData(getTable(), data);
+				}
+			}
+			getTable().synchronizeRowSelection(data);
+		}
+		super.setCurrentObject(obj);
+	}
+	public void focusInRow(int row){
+		Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof CharListAssistantI) {
+				CharListAssistantI init = (CharListAssistantI)obj;
+				init.focusInRow(row);
+			}
+		}
+	}
+	public String getItemTypeName(){
+		return "Character";
+	}
+	public String getItemTypeNamePlural(){
+		return "Characters";
+	}
+	/*.................................................................................................................*/
+	public void showSelectionPopup(Container cont, int x, int y) {
+		if (selectionCoordinator!=null)
+			selectionCoordinator.showPopUp(cont, x+5, y+5);
+	}
+	/*.................................................................................................................*/
+	public void setRowName(int row, String name){
+		if (data!=null) {
+			String warning = data.checkNameLegality(row, name);
+			if (warning == null)
+				data.setCharacterName(row, name);
+			else
+				ownerModule.discreetAlert( warning);
+		}
+	}
+	public String getRowName(int row){
+		if (data!=null && row<data.getNumChars())
+			return data.getCharacterName(row);
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		if (data!=null && row<data.getNumChars()){
+			if (!data.characterHasName(row))
+				return "";
+			return data.getCharacterName(row);
+		}
+		else
+			return null;
+	}
+	/*...............................................................................................................*/
+	public void setRowNameColor(Graphics g, int row){
+		//		g.setColor(Color.black);
+		if (data!=null) {
+			if (!data.characterHasName(row))
+				g.setColor(Color.gray);
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (data==null || (obj instanceof Taxa &&  (Taxa)obj ==data.getTaxa())||(obj instanceof CharacterData && (CharacterData)obj ==data)) {
+			data = null;
+			if (ownerModule!=null) {
+				ownerModule.iQuit();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				table.redrawRowNames();
+				setUndoer(undoReference);
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				table.synchronizeRowSelection(data);
+				table.repaintAll();
+				setUndoer();
+			}
+			else if (code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_ADDED) {
+				table.offAllEditsDontRecord(); //1. 12
+				table.setNumRows(data.getNumChars());
+				table.synchronizeRowSelection(data);
+				listModule.forceRecalculations();
+				table.repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.PARTS_ADDED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else {
+				table.setNumRows(data.getNumChars());
+				table.synchronizeRowSelection(data);
+				table.repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+
+	//have selection be done by changing selection of characters, and listening here for selection to change selection of table!!!!!
+	//likewise for data matrix 
+
+	public void saveSelectedRows() {
+		if (table.anyRowSelected()) {
+			String nameOfCharSet = MesquiteString.queryString(this, "Name of character set", "Name of character set:", "Stored char. set");
+			if (StringUtil.blank(nameOfCharSet))
+				return;
+			CharSelectionSet selectionSet= new CharSelectionSet(nameOfCharSet, data.getNumChars(), data);
+
+			data.storeSpecsSet(selectionSet, CharSelectionSet.class);
+
+			selectionSet.addToFile(data.getFile(), null, null);
+			selectionSet.setNexusBlockStored("SETS");
+			for (int ic= 0; ic< table.getNumRows(); ic++){
+				if (table.isRowSelected(ic)) { 
+					selectionSet.setSelected(ic, true);
+				}
+			}
+			data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));
+		}
+	}
+
+
+}
+
diff --git a/Source/mesquite/lists/CharacterStats/CharacterStats.java b/Source/mesquite/lists/CharacterStats/CharacterStats.java
new file mode 100644
index 0000000..9b2cd86
--- /dev/null
+++ b/Source/mesquite/lists/CharacterStats/CharacterStats.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CharacterStats;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharacterStats extends CharListAssistant implements MesquiteListener {
+	MesquiteMenuItemSpec selectedOnlyMenuItem;
+	MesquiteBoolean selectedOnly;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "States Information (in List of Characters window)";
+	}
+	public String getNameForMenuItem() {
+		return "States";
+	}
+	public String getExplanation() {
+		return "Supplies basic character state information for characters in character list window." ;
+	}
+	/*.................................................................................................................*/
+	CharacterData data=null;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		selectedOnly = new MesquiteBoolean(false);
+
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		deleteMenuItem(selectedOnlyMenuItem);
+		selectedOnlyMenuItem = addCheckMenuItem(null,"Selected Taxa Only", makeCommand("toggleSelectedOnly",  this), selectedOnly);
+		if (this.data !=null)
+			this.data.removeListener(this);
+		this.data = data;
+		data.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+ 	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	Snapshot temp = new Snapshot();
+		temp.addLine("toggleSelectedOnly " + selectedOnly.toOffOnString());
+ 	 	return temp;
+ 	 }
+	/*.................................................................................................................*/
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	 	if (checker.compare(this.getClass(), "Toggles whether only selected taxa are included in the calculation", "[on or off]", commandName, "toggleSelectedOnly")) {
+	 		boolean current = selectedOnly.getValue();
+	 		selectedOnly.toggleValue(parser.getFirstToken(arguments));
+	 		if (current!=selectedOnly.getValue())
+	 			parametersChanged();
+	 	}
+ 	else 
+	 		return  super.doCommand(commandName, arguments, checker);
+	return null;
+	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged();
+	}
+	public String getTitle() {
+		return "States";
+	}
+	public String getStringForCharacter(int ic){
+		return data.getStatesSummary(ic, selectedOnly.getValue());
+	}
+	public String getWidestString(){
+		return "88888888";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	public void endJob() {
+		if (data !=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/CodePosSetsList/CodePosSetsList.java b/Source/mesquite/lists/CodePosSetsList/CodePosSetsList.java
new file mode 100644
index 0000000..0057cb3
--- /dev/null
+++ b/Source/mesquite/lists/CodePosSetsList/CodePosSetsList.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.CodePosSetsList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CodePosSetsList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Codon Positions Sets";
+	}
+	public String getExplanation() {
+		return "Makes windows listing codon positions sets." ;
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+
+	public Class getItemType(){
+		return CodonPositionsSet.class;
+	}
+	public String getItemTypeName(){
+		return "Codon positions set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Codon positions sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new CodonPositionsSet("Model Set", data.getNumChars(), data);
+		return null;
+	}
+}
+
+
diff --git a/Source/mesquite/lists/ColorTaxon/32color.gif b/Source/mesquite/lists/ColorTaxon/32color.gif
new file mode 100644
index 0000000..a1a5104
Binary files /dev/null and b/Source/mesquite/lists/ColorTaxon/32color.gif differ
diff --git a/Source/mesquite/lists/ColorTaxon/64color.gif b/Source/mesquite/lists/ColorTaxon/64color.gif
new file mode 100644
index 0000000..0e501e2
Binary files /dev/null and b/Source/mesquite/lists/ColorTaxon/64color.gif differ
diff --git a/Source/mesquite/lists/ColorTaxon/ColorTaxon.java b/Source/mesquite/lists/ColorTaxon/ColorTaxon.java
new file mode 100644
index 0000000..7e32415
--- /dev/null
+++ b/Source/mesquite/lists/ColorTaxon/ColorTaxon.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.ColorTaxon;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ColorTaxon extends TaxaListAssistantI  {
+	Taxa taxa;
+	MesquiteTable table;
+	TableTool tool;
+	long currentColor = ColorDistribution.numberOfRed;
+	String colorString = "Color Red";
+	long savedColor = currentColor;
+	MesquiteBoolean removeColor;
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	public String getName() {
+		return "Color Taxa";
+	}
+	public String getExplanation() {
+		return "Provides paintbrush to color taxon names.";
+	}
+
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Cell paint color", makeCommand("setColor",  this), ColorDistribution.standardColorNames);
+		removeColor = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Remove color", makeCommand("removeColor",  this), removeColor);
+		addMenuItem(null, "Remove all color", makeCommand("removeAllColor",  this));
+		MesquiteSubmenuSpec mss2 = addSubmenu(null, "Set Color of Selected", makeCommand("setColorSelected",  this), ColorDistribution.standardColorNames);
+		//addMenuItem(null, "-", null);
+		//addMenuItem(null, "Color Selected", makeCommand("colorSelected",  this));
+		setUseMenubar(false); //menu available by touching button
+		return true;
+	}
+	private void removeColor(int it, boolean notify){
+		setColor( it, MesquiteLong.unassigned);
+		if (notify)
+			table.redrawCell(-1,it);
+	}
+	private void removeAllColor(boolean notify){
+			for (int it = 0; it<taxa.getNumTaxa(); it++)
+				setColor(it, MesquiteLong.unassigned);
+		if (notify)
+			table.repaintAll();
+	}
+	private void setColor(int it, long c){
+		if ( it<0)
+			return;
+		taxa.setAssociatedLong(colorNameRef, it, c);
+		table.redrawCell(-1,it);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setColor " + ColorDistribution.getStandardColorName(ColorDistribution.getStandardColor((int)currentColor)));
+		temp.addLine("removeColor " + removeColor.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/** A request for the MesquiteModule to perform a command.  It is passed two strings, the name of the command and the arguments.
+	This should be overridden by any module that wants to respond to a command.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(MesquiteModule.class, null, null, commandName, "paint")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(row)) {
+				if (!MesquiteLong.isCombinable(currentColor))
+					removeColor(row, true);
+				else
+					setColor(row, (int)currentColor);
+			}
+		}
+		else	if (checker.compare(this.getClass(), "Sets the color to be used to paint cells", "[name of color]", commandName, "setColor")) {
+			int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments)); 
+			if (bc >=0 && MesquiteLong.isCombinable(bc)){
+				removeColor.setValue(false);
+				currentColor = bc;
+				savedColor = bc;
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue(bc);
+			}
+		}
+		else	if (checker.compare(this.getClass(), "Sets the color of selected taxa", "[name of color]", commandName, "setColorSelected")) {
+			int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments)); 
+			if (bc >=0 && MesquiteLong.isCombinable(bc)){
+				for (int it = 0; it<taxa.getNumTaxa(); it++)
+					if (taxa.getSelected(it))
+						setColor(it, bc);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes color from all the cells", null, commandName, "removeAllColor")) {
+			removeAllColor(true);
+		}
+		else if (checker.compare(this.getClass(), "Sets the paint brush so that it removes colors from any cells touched", null, commandName, "removeColor")) {
+			if (StringUtil.blank(arguments))
+				removeColor.setValue(!removeColor.getValue());
+			else
+				removeColor.toggleValue(parser.getFirstToken(arguments));
+
+			if (removeColor.getValue()) {
+				colorString = "Remove color";
+				currentColor = MesquiteLong.unassigned;
+			}
+			else {
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue((int)currentColor);
+				currentColor = savedColor;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		this.table = table;
+		this.taxa = taxa;
+		if (containerOfModule() instanceof ListWindow && tool == null){
+			String sortExplanation = "Assigns colors to taxa. ";
+			tool = new TableTool(this, "sort", getPath(),"color.gif", 0,0,"Color taxon", sortExplanation, MesquiteModule.makeCommand("paint",  this) , null, null);
+			tool.setWorksOnRowNames(true);
+			((ListWindow)containerOfModule()).addTool(tool);
+			tool.setPopUpOwner(this);
+		}
+	}
+
+}
diff --git a/Source/mesquite/lists/ColorTaxon/color.gif b/Source/mesquite/lists/ColorTaxon/color.gif
new file mode 100644
index 0000000..417c483
Binary files /dev/null and b/Source/mesquite/lists/ColorTaxon/color.gif differ
diff --git a/Source/mesquite/lists/DatasetList/DatasetList.java b/Source/mesquite/lists/DatasetList/DatasetList.java
new file mode 100644
index 0000000..8cabaee
--- /dev/null
+++ b/Source/mesquite/lists/DatasetList/DatasetList.java
@@ -0,0 +1,194 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetList extends ListLVModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Matrices List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character data matrices and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DataSetsListAssistant.class, "The List of Character Matrices window can display columns showing information for each character matrix.",
+		"You can request that columns be shown using the Columns menu of the List of Character Matrices Window. ");
+	}
+	ListableVector datas;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		datas = getProject().getCharacterMatrices();
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null && obj == datas);
+	}
+
+	public boolean resetMenusOnNameChange(){
+		return true;
+	}
+	public void showListWindow(Object obj){
+		CharMatricesListWindow charMatricesListWindow = new CharMatricesListWindow(this);
+		charMatricesListWindow.setDatas(datas);
+		setModuleWindow(charMatricesListWindow); 
+		((ListableVectorWindow)getModuleWindow()).setObject(datas);
+		datas.addListener(this);
+		makeMenu("List");
+
+		MesquiteSubmenuSpec mss2 = addSubmenu(null, "Utilities", MesquiteModule.makeCommand("doUtility",  this));
+		mss2.setList(DatasetsListUtility.class);
+
+		if (!MesquiteThread.isScripting()){
+			DataSetsListAssistant assistant = (DataSetsListAssistant)hireNamedEmployee(DataSetsListAssistant.class, StringUtil.tokenize("Taxa of data matrix"));
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (DataSetsListAssistant)hireNamedEmployee(DataSetsListAssistant.class, StringUtil.tokenize("Number of characters of data matrix"));
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (DataSetsListAssistant)hireNamedEmployee(DataSetsListAssistant.class, "#DatasetsListClass");
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (DataSetsListAssistant)hireNamedEmployee(DataSetsListAssistant.class, "#MatrixListVisible");
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == datas && code == MesquiteListener.ELEMENT_CHANGED && getModuleWindow()!=null){
+			((TableWindow)getModuleWindow()).getTable().synchronizeRowSelection(datas);
+			((TableWindow)getModuleWindow()).getTable().repaintAll();
+		}
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return datas;
+	}
+	public int getNumberOfRows(){
+		if (datas==null)
+			return 0;
+		else
+			return datas.size();
+	}
+	public Class getAssistantClass(){
+		return DataSetsListAssistant.class;
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public void aboutToDeleteRow(int row){  //called just before superclass deletes rows, in case specific module needs to prepare for deletion
+		if (row<0 || row>= getNumberOfRows())
+			return;
+		CharacterData rdata = getProject().getCharacterMatrixDoomedOrNot(row);
+		if (rdata != null)
+			rdata.doom();
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return false;
+		CharacterData data = getProject().getCharacterMatrixDoomedOrNot(row);
+		getProject().removeFileElement(data);//must remove first, before disposing
+		data.dispose();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires utility module to operate on the data matrices", "[name of module]", commandName, "doUtility")) { //12 Jan 02
+			if (getProject().getCharacterMatrices() !=null){
+				DatasetsListUtility tda= (DatasetsListUtility)hireNamedEmployee(DatasetsListUtility.class, arguments);
+				if (tda!=null) {
+					MesquiteTable table = ((ListWindow)getModuleWindow()).getTable();
+					ListableVector datas = null;
+					if (table.anyRowSelected()){
+						ListableVector alldatas = getProject().getCharacterMatrices();
+						
+						datas = new ListableVector();
+						for (int i=0; i<alldatas.size(); i++){
+								
+							if (table.isRowSelected(i))
+								datas.addElement(alldatas.elementAt(i), true);
+						}
+					}
+					else {
+						ListableVector alldatas = getProject().getCharacterMatrices();
+						datas = new ListableVector();
+						for (int i=0; i<alldatas.size(); i++){
+							datas.addElement(alldatas.elementAt(i), true);
+						}
+					}
+					boolean a = tda.operateOnDatas(datas, table);
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getItemTypeName(){
+		return "Character matrix";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character matrices";
+	}
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/DatasetsListClass/DatasetsListClass.java b/Source/mesquite/lists/DatasetsListClass/DatasetsListClass.java
new file mode 100644
index 0000000..86cca49
--- /dev/null
+++ b/Source/mesquite/lists/DatasetsListClass/DatasetsListClass.java
@@ -0,0 +1,113 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetsListClass;
+/* created May 02 */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetsListClass extends DataSetsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Type of character data matrix";
+	}
+
+	public String getExplanation() {
+		return "Indicates type of character data matrix (e.g., continuous, DNA, etc.)." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (datas !=null)
+			datas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.datas = (ListableVector)obj;
+		datas.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Type";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (datas ==null || ic<0 || ic>= datas.size())
+				return "";
+			CharacterData data =((CharacterData)datas.elementAt(ic));
+			if (data==null)
+				return "";
+			return data.getDataTypeName();
+		}
+		catch (NullPointerException e){
+			return "";
+		}
+	}
+	public String getWidestString(){
+		String best = " 888888 ";
+		if (datas==null)
+			return best;
+		int m = 8;
+		for (int i=0; i< datas.size(); i++) {
+			CharacterData data= (CharacterData)datas.elementAt(i);
+			if (data!=null){
+				String s = data.getDataTypeName();
+				int n = s.length();
+				if (n>m) {
+					m=n;
+					best = s;
+				}
+			}
+		}
+		return best + "888";
+
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		if (datas !=null)
+			datas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/DatasetsListConcatenate/DatasetsListConcatenate.java b/Source/mesquite/lists/DatasetsListConcatenate/DatasetsListConcatenate.java
new file mode 100644
index 0000000..07a5533
--- /dev/null
+++ b/Source/mesquite/lists/DatasetsListConcatenate/DatasetsListConcatenate.java
@@ -0,0 +1,183 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetsListConcatenate;
+/* created May 02 */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetsListConcatenate extends DatasetsListUtility {
+	boolean concatExcludedCharacters = false;
+	boolean prefixGroupLabelNames = false;
+	boolean anyExcluded = false;
+	boolean removeConcatenated = false;
+	boolean preferencesSet=false;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Concatenate Selected Matrices";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Concatenate Selected Matrices...";
+	}
+
+	public String getExplanation() {
+		return "Concatenates selected matrices in List of Character Matrices window.  Only those compatible with first selected are concatenated into it." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference(String tag, String content) {
+		if ("prefixGroupLabelNames".equalsIgnoreCase(tag))
+			prefixGroupLabelNames = MesquiteBoolean.fromTrueFalseString(content);
+		if ("concatExcludedCharacters".equalsIgnoreCase(tag))
+			concatExcludedCharacters = MesquiteBoolean.fromTrueFalseString(content);
+		if ("removeConcatenated".equalsIgnoreCase(tag))
+			removeConcatenated = MesquiteBoolean.fromTrueFalseString(content);
+
+		preferencesSet = true;
+	}
+
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML() {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "concatExcludedCharacters", concatExcludedCharacters);
+		StringUtil.appendXMLTag(buffer, 2, "prefixGroupLabelNames", prefixGroupLabelNames);
+		StringUtil.appendXMLTag(buffer, 2, "removeConcatenated", removeConcatenated);
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		loadPreferences();
+
+		if (!MesquiteThread.isScripting()){
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Concatenation Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+			if (anyExcluded) {
+				dialog.appendToHelpString("During concatenation, characters that are currently excluded will be omitted entirely from the concatenated matrix if \"Remove excluded characters\" is checked.<BR>");
+			}
+			dialog.appendToHelpString("You may choose to have the original matrices deleted after concatenation. <BR>");
+			dialog.appendToHelpString("Any characters not currently assigned to groups will be assigned to a group whose name is the name of the matrix from which they came. ");
+			dialog.appendToHelpString("Those characters that where previously assigned to a group will still be assigned to that group, or, optionally, to a new group whose name is its existing group name with the matrix name prefixed to it. ");
+			Checkbox deleteExcludedBox=null;
+			if (anyExcluded)
+				deleteExcludedBox = dialog.addCheckBox("Remove excluded characters", !concatExcludedCharacters);
+			Checkbox deleteMatricesBox = dialog.addCheckBox("Delete original matrices", removeConcatenated);
+			Checkbox prefixGroupLabelNamesBox = dialog.addCheckBox("Prefix existing character group labels with matrix name", prefixGroupLabelNames);
+			dialog.completeAndShowDialog(true);
+			if (buttonPressed.getValue()==0)  {
+				removeConcatenated = deleteMatricesBox.getState();
+				prefixGroupLabelNames = prefixGroupLabelNamesBox.getState();
+				if (anyExcluded)
+					concatExcludedCharacters = !deleteExcludedBox.getState();
+				storePreferences();
+			}
+			dialog.dispose();
+			return (buttonPressed.getValue()==0);
+
+		}
+		return true;
+	}
+
+	/** if returns true, then requests to remain on even after operateOnTaxas is called.  Default is false*/
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/** Called to operate on the CharacterData blocks.  Returns true if taxa altered*/
+	public boolean operateOnDatas(ListableVector datas, MesquiteTable table){
+		for (int im = 0; im < datas.size(); im++){
+			CharacterData data = (CharacterData)datas.elementAt(im);
+			if (data.numCharsCurrentlyIncluded() < data.getNumChars())
+				anyExcluded = true;
+		}
+		if (!queryOptions())
+			return false;
+		CharacterData starter = null;   // this will be the new concatenated matrix
+		int count = 0;
+		int countFailed = 0;
+		String name = "";
+		boolean found = false;
+		if (getProject() != null)
+			getProject().incrementProjectWindowSuppression();
+		for (int im = 0; im < datas.size(); im++){
+			found = true;
+			CharacterData data = (CharacterData)datas.elementAt(im);
+			if (starter == null){
+				starter = data.makeCharacterData(data.getMatrixManager(), data.getTaxa());  
+
+				starter.addToFile(getProject().getHomeFile(), getProject(),  findElementManager(CharacterData.class));  
+			}
+
+			boolean success = starter.concatenate(data, false, concatExcludedCharacters, true, prefixGroupLabelNames, false, false);
+			if (success){
+				count++;
+				if (count > 1)
+					name = name + "+";
+				name = name + "(" + data.getName() + ")";
+				if (removeConcatenated)
+						data.deleteMe(false);
+			}
+			else 
+				countFailed++;
+
+
+		}
+		if (starter != null)
+			starter.setName(name);
+		if (! found)
+			discreetAlert("Two more more matrices should be selected first in order to concatenate them");
+		if (countFailed>0)
+			discreetAlert("Some matrices could not be concatenated into the first selected because they are of incompatible type or are linked to the first");
+		if (getProject() != null)
+			getProject().decrementProjectWindowSuppression();
+		resetAllMenuBars();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/DatasetsListDuplicate/DatasetsListDuplicate.java b/Source/mesquite/lists/DatasetsListDuplicate/DatasetsListDuplicate.java
new file mode 100644
index 0000000..aca9df6
--- /dev/null
+++ b/Source/mesquite/lists/DatasetsListDuplicate/DatasetsListDuplicate.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetsListDuplicate;
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetsListDuplicate extends DatasetsListUtility {
+	boolean duplicateExcludedCharacters = false;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Duplicate Selected Matrices";
+	}
+
+	public String getExplanation() {
+		return "Duplicates selected matrices in List of Character Matrices window." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		if (!MesquiteThread.isScripting()){
+
+			duplicateExcludedCharacters = !AlertDialog.query(containerOfModule(), "Remove excluded characters?","Remove excluded characters?", "Yes", "No");
+		}
+		return true;
+	}
+
+	/** if returns true, then requests to remain on even after operateOnTaxas is called.  Default is false*/
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/** Called to operate on the CharacterData blocks.  Returns true if taxa altered*/
+	public boolean operateOnDatas(ListableVector datas, MesquiteTable table){
+		boolean anyExcluded = false;
+		for (int im = 0; im < datas.size(); im++){
+			CharacterData data = (CharacterData)datas.elementAt(im);
+			if (data.numCharsCurrentlyIncluded() < data.getNumChars())
+				anyExcluded = true;
+		}
+		if (anyExcluded)
+			queryOptions();
+		if (getProject() != null)
+			getProject().incrementProjectWindowSuppression();
+		for (int im = 0; im < datas.size(); im++){
+			CharacterData data = (CharacterData)datas.elementAt(im);
+			CharacterData starter = data.makeCharacterData(data.getMatrixManager(), data.getTaxa());  
+
+			starter.addToFile(getProject().getHomeFile(), getProject(),  findElementManager(CharacterData.class));  
+
+			boolean success = starter.concatenate(data, false, duplicateExcludedCharacters, false, false, false, false);
+			if (success){
+				starter.setName(datas.getUniqueName(data.getName() + " (duplicate)"));
+			}
+
+
+		}
+		if (getProject() != null)
+			getProject().decrementProjectWindowSuppression();
+		resetAllMenuBars();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/DatasetsListNumChars/DatasetsListNumChars.java b/Source/mesquite/lists/DatasetsListNumChars/DatasetsListNumChars.java
new file mode 100644
index 0000000..5a2fcbd
--- /dev/null
+++ b/Source/mesquite/lists/DatasetsListNumChars/DatasetsListNumChars.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetsListNumChars;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetsListNumChars extends DataSetsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of characters of data matrix";
+	}
+	public String getExplanation() {
+		return "Indicates taxa of data matrix." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (datas !=null)
+			datas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.datas = (ListableVector)obj;
+		datas.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# Chars.";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (datas ==null || ic<0 || ic> datas.size())
+				return "";
+			return Integer.toString(((CharacterData)datas.elementAt(ic)).getNumChars());
+		}
+		catch (NullPointerException e){
+		}
+		return "";
+	}
+	public String getWidestString(){
+		return " 888888 ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (datas !=null)
+			datas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/DatasetsListTaxa/DatasetsListTaxa.java b/Source/mesquite/lists/DatasetsListTaxa/DatasetsListTaxa.java
new file mode 100644
index 0000000..88c4890
--- /dev/null
+++ b/Source/mesquite/lists/DatasetsListTaxa/DatasetsListTaxa.java
@@ -0,0 +1,119 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DatasetsListTaxa;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DatasetsListTaxa extends DataSetsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxa of data matrix";
+	}
+	public String getExplanation() {
+		return "Indicates taxa of data matrix." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (datas !=null)
+			datas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.datas = (ListableVector)obj;
+		datas.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Taxa";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (datas ==null || ic<0 || ic>= datas.size())
+				return "";
+			CharacterData data =((CharacterData)datas.elementAt(ic));
+			if (data==null)
+				return "";
+			Taxa t = data.getTaxa();
+			if (t == null)
+				return "";
+			else return t.getName();
+		}
+		catch (NullPointerException e){
+			return "";
+		}
+	}
+	public String getWidestString(){
+		String best = " 888888 ";
+		if (datas==null)
+			return best;
+		int m = 8;
+		for (int i=0; i< datas.size(); i++) {
+			Taxa t = ((CharacterData)datas.elementAt(i)).getTaxa();
+			if (t!=null && t.getName()!=null){
+				String s = t.getName();
+				int n = s.length();
+				if (n>m) {
+					m=n;
+					best = s;
+				}
+			}
+		}
+		return best + "888";
+
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (datas !=null)
+			datas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/DefaultCharOrder/DefaultCharOrder.java b/Source/mesquite/lists/DefaultCharOrder/DefaultCharOrder.java
new file mode 100644
index 0000000..eb5e3f6
--- /dev/null
+++ b/Source/mesquite/lists/DefaultCharOrder/DefaultCharOrder.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.DefaultCharOrder;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DefaultCharOrder extends CharListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Default Order (characters)";
+	 }
+	public String getExplanation() {
+		return "Shows default order of character." ;
+  	 }
+	CharacterData data=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		addMenuItem("Set Current Order as Default", makeCommand("setDefault",  this));
+		return true;
+  	 }
+  	 
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		if (this.data !=null)
+			this.data.removeListener(this);
+		this.data = data;
+		data.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the current order to be the default", null, commandName, "setDefault")) {
+			if (data != null)
+				data.resetDefaultOrderToCurrent();
+			parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged();
+	}
+	public String getStringForCharacter(int ic){
+		if (data != null)
+			return Integer.toString(data.getDefaultPosition(ic)+1); //+1 because zero based
+		return "?";
+	}
+	public String getWidestString(){
+		return "8888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Default Order";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+   	 
+	/*.................................................................................................................*/
+   	 public void endJob() {
+		if (data !=null)
+			data.removeListener(this);
+		super.endJob();
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/lists/DefaultTaxaOrder/DefaultTaxaOrder.java b/Source/mesquite/lists/DefaultTaxaOrder/DefaultTaxaOrder.java
new file mode 100644
index 0000000..739c1c0
--- /dev/null
+++ b/Source/mesquite/lists/DefaultTaxaOrder/DefaultTaxaOrder.java
@@ -0,0 +1,88 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.DefaultTaxaOrder;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class DefaultTaxaOrder extends TaxonListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Default Order (taxa)";
+	}
+	public String getExplanation() {
+		return "Shows default order of taxa." ;
+	}
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Set Current Order as Default", makeCommand("setDefault",  this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the current order to be the default", null, commandName, "setDefault")) {
+			if (taxa != null)
+				taxa.resetDefaultOrderToCurrent();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		/* hire employees here */
+		this.taxa = taxa;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Default Order";
+	}
+	public String getStringForTaxon(int ic){
+		if (taxa!=null) {
+			return Integer.toString(taxa.getDefaultPosition(ic)+1);//+1 because zero based
+		}
+		return "?";
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+
+	public String getWidestString(){
+		return "8888 ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
diff --git a/Source/mesquite/lists/MarkTaxonInList/MarkTaxonInList.java b/Source/mesquite/lists/MarkTaxonInList/MarkTaxonInList.java
new file mode 100644
index 0000000..9aae263
--- /dev/null
+++ b/Source/mesquite/lists/MarkTaxonInList/MarkTaxonInList.java
@@ -0,0 +1,355 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+
+package mesquite.lists.MarkTaxonInList;
+/*~~  */
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Graphics;
+
+import mesquite.lists.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.ManagerAssistant;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MarkTaxonInList extends TaxonListAssistant {
+	Taxa taxa;
+	MesquiteTable table=null;
+	String markName;
+	String markCode;
+	NameReference nameReference;
+	boolean startWithNew = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		markName = "+";
+		markCode = codeFromName(markName);
+		nameReference = NameReference.getNameReference(markCode);
+			
+		addMenuItem("Set Name of Mark...", makeCommand("setName", this));
+		addMenuItem("Mark Selected", makeCommand("markSelected", this));
+		addMenuItem("Unmark Selected", makeCommand("unmarkSelected", this));
+		addMenuItem("-", null);
+		addMenuItem("New Mark...", makeCommand("newMark", this));
+		addMenuItem("Select Other Mark...", makeCommand("selectMark", this));
+		addMenuItem("Delete Mark...", makeCommand("deleteMark", this));
+		return true;
+	}
+
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanationForRow(int ic){
+		if (taxa!=null ) {
+
+			if (isMarked(ic))
+				return "This taxon is MARKED.  To mark a taxon, touch on this cell with the arrow cursor";
+			else
+				return "This taxon is UNMARKED.  To mark a taxon, touch on this cell with the arrow cursor";
+		}
+		return null;
+	}
+
+	String codeFromName(String name){
+		return "mark*." + name;
+	}
+	String nameFromCode(String code){
+		if (code == null)
+			return "";
+		if (code.indexOf("mark*.")==0)
+			return code.substring(6, code.length());
+		return code;
+	}
+	boolean isMarked(int ic){
+		boolean c = taxa.getAssociatedBit(nameReference, ic);
+		if (!c && taxa.getWhichAssociatedBits(nameReference) == null){  //need to reset!  Mark has been deleted
+			markName = "+";
+			markCode = codeFromName(markName);
+			nameReference = NameReference.getNameReference(markCode);
+		}
+
+		return c;
+	}
+	void mark(int ic, boolean toMark){
+		taxa.setAssociatedBit(nameReference,  ic, toMark);
+	}
+	/*
+	boolean isMarked(int ic){
+		long c = taxa.getAssociatedLong(nameReference, ic);
+
+		return c== 1;
+	}
+	void mark(int ic, boolean toMark){
+		if (toMark)
+			taxa.setAssociatedLong(nameReference,  ic, 1);
+		else
+			taxa.setAssociatedLong(nameReference,  ic, 0);
+	}
+	 */
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int it, boolean selected){
+		if (isMarked(it))
+			return ColorDistribution.lightGreen;
+		else
+			return super.getBackgroundColorOfCell(it, selected);
+	}
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic, int x, int y, boolean doubleClick, int modifiers){
+		mark (ic, !isMarked(ic));
+		if (table != null)
+			table.repaintAll();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		this.taxa = taxa;
+		this.table = table;
+		if (MesquiteThread.isScripting())
+			return;
+		int count = 0;
+		for (int i=0; i<taxa.getNumberAssociatedBits(); i++){
+			String name = taxa.getAssociatedBits(i).getNameReference().getValue();
+			if (!name.equalsIgnoreCase("selected") && name.startsWith("mark*."))
+				count++;
+		}
+		if (count > 0){  //there are some available
+			if (AlertDialog.query(containerOfModule(), "New Mark?", "Do you want to define a new mark, or use an existing one?", "New", "Existing")){
+				doCommand("setName", null, CommandChecker.defaultChecker);
+				return;
+			}
+		}
+		
+		Bits bits = taxa.getWhichAssociatedBits(nameReference);  //see if there is already one linked here; if so, just rename;
+		if (bits == null){  //choosing which mark to show
+			selectMark(true, false, true, "show");
+
+		}
+
+	}
+
+	String selectMark(boolean queryIfNone, boolean queryIfOne, boolean setMark, String verb){
+		//select a bits and extract its name, otherwise use +/-
+		int count = 0;
+		String candidate = null;
+		for (int i=0; i<taxa.getNumberAssociatedBits(); i++){
+			String name = taxa.getAssociatedBits(i).getNameReference().getValue();
+			if (!name.equalsIgnoreCase("selected") && name.startsWith("mark*.")){
+				count++;
+				candidate = name;
+			}
+		}
+		if (count > 1 || (count == 1 && queryIfOne)){
+
+			String[] bitsNames = new String[count];
+			count = 0;
+			for (int i=0; i<taxa.getNumberAssociatedBits(); i++){
+				String name = taxa.getAssociatedBits(i).getNameReference().getValue();
+				if (!name.equalsIgnoreCase("selected") && name.startsWith("mark*."))
+					bitsNames[count++] = nameFromCode(name);
+			}
+			int ib = ListDialog.queryList(containerOfModule(), "Which mark?", "Select which mark to " + verb, null, bitsNames, 0);
+			if (ib>=0 && ib< bitsNames.length){
+				candidate = bitsNames[ib];
+				if (setMark){
+					markName = candidate;
+					markCode = codeFromName(markName);
+					nameReference = NameReference.getNameReference(markCode);
+				}
+				return codeFromName(candidate);
+			}
+		}
+		else if (count ==1) {
+			if (setMark){
+				markName = nameFromCode(candidate);
+				markCode = candidate;
+				nameReference = NameReference.getNameReference(markCode);
+			}
+			return markCode;
+		}
+		else if (count == 0 && queryIfNone) 
+			doCommand("setName", null, CommandChecker.defaultChecker);
+		else
+			discreetAlert("There are no marks available");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void dispose() {
+		super.dispose();
+		if (taxa!=null)
+			taxa.removeListener(this);
+	}
+
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("setName " + ParseUtil.tokenize(markCode)); 
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the name of the mark", null, commandName, "setName")) {
+			String code = parser.getFirstToken(arguments);
+			if (code == null){
+				if (!MesquiteThread.isScripting()){
+					String name = MesquiteString.queryString(containerOfModule(), "Name of mark", "What is the name of this mark?", markName);
+					if (name != null){
+						markCode = codeFromName(name);
+						markName = name;
+						Bits bits = taxa.getWhichAssociatedBits(nameReference);  //see if there is already one linked here; if so, just rename;
+						nameReference = NameReference.getNameReference(markCode);
+						if (bits != null)
+							bits.setNameReference(nameReference);
+						else
+							taxa.makeAssociatedBits(markCode);
+						if (table != null)
+							table.repaintAll();
+					}
+				}
+				return null;
+			}
+			markCode = code;
+			markName = nameFromCode(code);
+			nameReference = NameReference.getNameReference(markCode);
+		}
+		else if (checker.compare(this.getClass(), "Select Mark", null, commandName, "selectMark")) {
+			selectMark(false, true, true, "show");
+			if (table != null)
+				table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Delete Mark", null, commandName, "deleteMark")) {
+			String code = selectMark(false, true, false, "delete");
+			if (code == null)
+				return null;
+			taxa.removeAssociatedBits(NameReference.getNameReference(code));  //see if there is already one linked here; if so, just rename;
+			if (code.equals(markCode))
+				selectMark(false, true, true, "show");
+			if (table != null)
+				table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Make New Mark", null, commandName, "newMark")) {
+			if (!MesquiteThread.isScripting()){
+				String name = MesquiteString.queryString(containerOfModule(), "Name of new mark", "What is the name of the new mark?", "+");
+				if (name != null){
+					markCode = codeFromName(name);
+					markName = name;
+					nameReference = taxa.makeAssociatedBits(markCode);
+					if (table != null)
+						table.repaintAll();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Marks selected taxa", null, commandName, "markSelected")) {
+			if (taxa != null && table != null){
+				for (int i = 0; i< taxa.getNumTaxa(); i++){
+					if (taxa.getSelected(i) || table.isRowSelected(i))
+						mark(i, true);
+				}
+			}
+			else if (taxa != null){
+				for (int i = 0; i< taxa.getNumTaxa(); i++){
+					if (taxa.getSelected(i))
+						mark(i, true);
+				}
+			}
+			
+			if (table != null)
+				table.repaintAll();
+		}
+		else if (checker.compare(this.getClass(), "Unmarks selected taxa", null, commandName, "unmarkSelected")) {
+			if (taxa != null && table != null){
+				for (int i = 0; i< taxa.getNumTaxa(); i++){
+					if (taxa.getSelected(i) || table.isRowSelected(i))
+						mark(i, false);
+				}
+			}
+			else if (taxa != null){
+				for (int i = 0; i< taxa.getNumTaxa(); i++){
+					if (taxa.getSelected(i))
+						mark(i, false);
+				}
+			}
+			
+			if (table != null)
+				table.repaintAll();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public String getTitle() {
+		return "Mark";
+	}
+	public String getStringForTaxon(int ic){
+
+		if (taxa!=null) {
+			if (isMarked(ic))
+				return markName;
+			else
+				return "-";
+		}
+		return "-";
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int row){
+		return false;
+	}
+	/*...............................................................................................................*/
+	public boolean useString(int ic){
+		return true;
+	}
+
+	public String getWidestString(){
+		if (markName.length()> 5)
+			return markName;
+		return "88888";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Mark Taxa";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Permits user to mark taxa in the List of Taxa with a specific name." ;
+	}
+}
+
diff --git a/Source/mesquite/lists/MatrixListVisible/MatrixListVisible.java b/Source/mesquite/lists/MatrixListVisible/MatrixListVisible.java
new file mode 100644
index 0000000..52ef42c
--- /dev/null
+++ b/Source/mesquite/lists/MatrixListVisible/MatrixListVisible.java
@@ -0,0 +1,140 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.MatrixListVisible;
+/* created May 02 */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MatrixListVisible extends DataSetsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Visibility of Matrix";
+	}
+
+	public String getExplanation() {
+		return "Indicates whether character data matrix is hidden or not." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Toggle Visibility", makeCommand("toggleVisibility", this));
+		return true;
+	}
+	MesquiteTable table;
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		this.table = table;
+		if (datas !=null)
+			datas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.datas = (ListableVector)obj;
+		datas.addListener(this);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Toggles visibility of selected matrices", null, commandName, "toggleVisibility")) {
+			if (datas == null || table == null)
+				return null;
+			boolean changed = false;
+			for (int ir = 0; ir<table.getNumRows(); ir++){
+				if (table.isRowSelected(ir)){
+					if (ir>= datas.size())
+						return null;
+					CharacterData data =((CharacterData)datas.elementAt(ir));
+					data.setUserVisible(!data.isUserVisible());
+					changed = true;
+				}
+			}
+			if (changed){
+			parametersChanged(null);
+			getProject().getCoordinatorModule().refreshProjectWindow();
+			resetAllMenuBars();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Visible?";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (datas ==null || ic<0 || ic>= datas.size())
+				return "";
+			CharacterData data =((CharacterData)datas.elementAt(ic));
+			if (data==null)
+				return "";
+			if (data.isUserVisible())
+				return "Visible";
+			else
+				return "Hidden";
+		}
+		catch (NullPointerException e){
+			return "";
+		}
+	}
+	
+
+
+	public String getWidestString(){
+		
+		return " 888888";
+
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		if (datas !=null)
+			datas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/ModelsList/ModelsList.java b/Source/mesquite/lists/ModelsList/ModelsList.java
new file mode 100644
index 0000000..275dc7c
--- /dev/null
+++ b/Source/mesquite/lists/ModelsList/ModelsList.java
@@ -0,0 +1,301 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.ModelsList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ModelsList extends ListModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Models List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing character models and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ModelsListAssistant.class, "The List of Character Models window can display columns showing information for each character model.",
+		"You can request that columns be shown using the Columns menu of the List of Character Models Window. ");
+	}
+	ListableVector models;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null && obj == models);
+	}
+
+	public void showListWindow(Object obj){
+		setModuleWindow(new ModelsListWindow(this));
+		((ModelsListWindow)getModuleWindow()).setObject(models = getProject().getCharacterModels());
+		//makeMenu("Character_Models");
+		makeMenu("List");
+
+		if (!MesquiteThread.isScripting()){
+			ModelsListAssistant assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("#ModelsListType"));
+			if (assistant!= null){
+				((ModelsListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("#ModelsListParadigm"));
+			if (assistant!= null){
+				((ModelsListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("#ModelsListWhole"));
+			if (assistant!= null){
+				((ModelsListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/**/
+			assistant = (ModelsListAssistant)hireNamedEmployee(ModelsListAssistant.class, StringUtil.tokenize("Data type for model"));
+			if (assistant!= null){
+				((ModelsListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//getModuleWindow().setVisible(true);
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return getProject().getCharacterModels();
+	}
+	public int getNumberOfRows(){
+		if (getProject().getCharacterModels()==null)
+			return 0;
+		else
+			return getProject().getCharacterModels().size();
+	}
+	public Class getAssistantClass(){
+		return ModelsListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Character model";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character models";
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		CharacterModel model = ((ModelsListWindow)getModuleWindow()).getModel(row);
+		if (model!=null){
+			if (model.isBuiltIn()) {
+				alert("That character model cannot be deleted, because the model is built in");
+				return false;
+			}
+			else {
+				getProject().removeFileElement(model);//must remove first, before disposing
+				model.dispose();
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ 
+		if (row<0 || row>= getNumberOfRows())
+			return null;
+		CharacterModel model = ((ModelsListWindow)getModuleWindow()).getModel(row);
+		return model.getAnnotation();
+	}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return;
+		CharacterModel model = ((ModelsListWindow)getModuleWindow()).getModel(row);
+		model.setAnnotation(s, notify);
+	}
+	/** returns a String of explanation for a row*/
+	public String getExplanation(int row){
+		CharacterModel model = ((ModelsListWindow)getModuleWindow()).getModel(row);
+		if (model!=null)
+			return model.getExplanation();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		//if (getModuleWindow()!=null && !getModuleWindow().isVisible())
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Requests a getModuleWindow() to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		//Debug.println("disposing of getModuleWindow()");
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+/* ======================================================================== */
+class ModelsListWindow extends ListWindow implements MesquiteListener {
+	ListableVector models;
+	public ModelsListWindow (ModelsList ownerModule) {
+		super(ownerModule);
+		MesquiteTable t = getTable();
+		if (t!=null)
+			t.setAutoEditable(false, false, false, false);
+	}
+	/*.................................................................................................................*/
+	/** When called the getModuleWindow() will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Character models"); 
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return models;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof ListableVector) {
+			if (models!=null)
+				models.removeListener(this);
+			models = (ListableVector)obj;
+			models.addListener(this);
+			getTable().synchronizeRowSelection(models);
+		}
+		super.setCurrentObject(obj);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean isRowNameEditable(int row){
+		CharacterModel model = getModel(row);
+		if (model==null)
+			return false;
+		else
+			return !model.isBuiltIn();
+	}
+	CharacterModel getModel(int row){
+		if (models!=null) {
+			if (row>=0 && row<models.size())
+				return(CharacterModel)models.elementAt(row);
+		}
+		return null;
+	}
+	public boolean interceptRowNameTouch(int row, int regionInCellH, int regionInCellV, int modifiers){
+		CharacterModel model = getModel(row);
+		if (model!=null){
+			if (model.isBuiltIn()) {
+				((ListTable)getTable()).superRowNameTouched(row,  regionInCellH,  regionInCellV, modifiers,1);
+			}
+			else
+				getTable().editRowNameCell(row);
+		}
+		return true;
+	}
+	public void setRowName(int row, String name){
+		CharacterModel model = getModel(row);
+		if (model!=null){
+			if (model.isBuiltIn())
+				ownerModule.alert("The name of that character model cannot be changed, because the model is built in");
+			else {
+				model.setName(name);
+				resetAllTitles();
+				getOwnerModule().resetAllMenuBars();
+			}
+		}
+	}
+	public String getRowName(int row){
+		if (models!=null){
+			if (row<0 && row >= models.size())
+				return null;
+			return ((Listable)models.elementAt(row)).getName();
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj ==models)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		if (obj instanceof ListableVector && (ListableVector)obj ==models) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				getTable().redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) { //listable vector, not Associable, hence dont' synchronize
+				getTable().synchronizeRowSelection(models);
+				getTable().repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				getTable().setNumRows(models.size());
+				getTable().synchronizeRowSelection(models);
+				getTable().repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else if (code!=MesquiteListener.ANNOTATION_CHANGED && code!=MesquiteListener.ANNOTATION_ADDED && code!=MesquiteListener.ANNOTATION_DELETED) {
+				getTable().setNumRows(models.size());
+				getTable().synchronizeRowSelection(models);
+				getTable().repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+
+	public void dispose(){
+		if (models!=null)
+			models.removeListener(this);
+		super.dispose();
+	}
+}
+
+
diff --git a/Source/mesquite/lists/ModelsListDatatype/ModelsListDatatype.java b/Source/mesquite/lists/ModelsListDatatype/ModelsListDatatype.java
new file mode 100644
index 0000000..d55179e
--- /dev/null
+++ b/Source/mesquite/lists/ModelsListDatatype/ModelsListDatatype.java
@@ -0,0 +1,97 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.ModelsListDatatype;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ModelsListDatatype extends ModelsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Data type for model";
+	}
+	public String getExplanation() {
+		return "Indicates data type of model in list window." ;
+	}
+	ListableVector models=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (models !=null)
+			models.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.models = (ListableVector)obj;
+		models.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Data type";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (models ==null || ic<0 || ic> models.size())
+				return "";
+			return ((CharacterModel)models.elementAt(ic)).getStateClassName();
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " standard Categorical datadata ";
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (models !=null)
+			models.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/ModelsListParadigm/ModelsListParadigm.java b/Source/mesquite/lists/ModelsListParadigm/ModelsListParadigm.java
new file mode 100644
index 0000000..76fe5a6
--- /dev/null
+++ b/Source/mesquite/lists/ModelsListParadigm/ModelsListParadigm.java
@@ -0,0 +1,98 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.ModelsListParadigm;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ModelsListParadigm extends ModelsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Model Paradigm";
+	}
+	public String getExplanation() {
+		return "Indicates paradigm of model in list window." ;
+	}
+	ListableVector models=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (models !=null)
+			models.removeListener(this);
+		if (obj instanceof ListableVector)
+			models = (ListableVector)obj;
+		models.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Paradigm";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (models ==null || ic<0 || ic> models.size())
+				return "";
+			return ((CharacterModel)models.elementAt(ic)).getParadigm();
+		}
+		catch (NullPointerException e){}
+		return "";
+
+	}
+	public String getWidestString(){
+		return "ProbabilityProbability";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (models !=null)
+			models.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/ModelsListType/ModelsListType.java b/Source/mesquite/lists/ModelsListType/ModelsListType.java
new file mode 100644
index 0000000..b5dea11
--- /dev/null
+++ b/Source/mesquite/lists/ModelsListType/ModelsListType.java
@@ -0,0 +1,97 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.ModelsListType;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ModelsListType extends ModelsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Type of Model";
+	 }
+	 
+	public String getExplanation() {
+		return "Indicates type of model (e.g., Mk1, step-matrix) in list window." ;
+  	 }
+	ListableVector models=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+  	 }
+  	 
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (models !=null)
+			models.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.models = (ListableVector)obj;
+		models.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Type";
+	}
+	public String getStringForRow(int ic){
+		try {
+		if (models ==null || ic<0 || ic> models.size())
+			return "";
+		return ((CharacterModel)models.elementAt(ic)).getModelTypeName();
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " Generalized Generalized model ";  //nonsense string to be wide
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+   	 public void endJob() {
+		if (models !=null)
+			models.removeListener(this);
+		super.endJob();
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/lists/ModelsListWhole/ModelsListWhole.java b/Source/mesquite/lists/ModelsListWhole/ModelsListWhole.java
new file mode 100644
index 0000000..2c1f9c1
--- /dev/null
+++ b/Source/mesquite/lists/ModelsListWhole/ModelsListWhole.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.ModelsListWhole;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ModelsListWhole extends ModelsListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Whole or Submodel";
+	}
+	public String getExplanation() {
+		return "Indicates whether model is a complete or partial model of character evolution." ;
+	}
+	ListableVector models=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (models !=null)
+			models.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.models = (ListableVector)obj;
+		models.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Whole/Partial";
+	}
+	public String getStringForRow(int ic){
+		try {
+			if (models ==null || ic<0 || ic> models.size())
+				return "";
+			else {
+				CharacterModel m = (CharacterModel)models.elementAt(ic);
+				if (m instanceof WholeCharacterModel)
+					return "Whole";
+				else	if (m instanceof CharacterSubmodel)
+					return "Partial";
+				else
+					return "?";
+
+
+			}
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " Whole/Partial ";
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (models !=null)
+			models.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/NexusBlockList/NexusBlockList.java b/Source/mesquite/lists/NexusBlockList/NexusBlockList.java
new file mode 100644
index 0000000..c10a8a3
--- /dev/null
+++ b/Source/mesquite/lists/NexusBlockList/NexusBlockList.java
@@ -0,0 +1,107 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.NexusBlockList;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NexusBlockList extends ListLVModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "NEXUS Blocks List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing NEXUS blocks." ;
+	}
+	/*.................................................................................................................*/
+	public boolean deleteRow(int row, boolean notify){
+	return false;
+}
+
+	public int currentTaxa = 0;
+	ListableVector blocks;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean showing(Object obj){
+		if (obj instanceof ListableVector) {
+			return (blocks == blocks && getModuleWindow()!=null);
+		}
+		return false;
+	}
+
+	public void showListWindow(Object obj){
+		if (obj instanceof ListableVector)
+			blocks =(ListableVector)obj;
+		else
+			return;
+		setModuleWindow( new ListableVectorWindow(this));
+
+		((ListableVectorWindow)getModuleWindow()).setCurrentObject(blocks);
+		//makeMenu("NEXUS_Blocks");
+		makeMenu("List");
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return blocks;
+	}
+	public int getNumberOfRows(){
+		if (blocks==null)
+			return 0;
+		else
+			return blocks.size();
+	}
+	public Class getAssistantClass(){
+		return null;
+	}
+	public String getItemTypeName(){
+		return "NEXUS block";
+	}
+	public String getItemTypeNamePlural(){
+		return "NEXUS blocks";
+	}
+
+	/*.................................................................................................................*/
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){
+		if (blocks==null || row>=blocks.size())
+			return null;
+		NexusBlock nb = (NexusBlock)blocks.elementAt(row);
+		return "This block belongs to the file " + nb.getFile().getName();
+	}
+
+
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/NumForCharMatrixList/NumForCharMatrixList.java b/Source/mesquite/lists/NumForCharMatrixList/NumForCharMatrixList.java
new file mode 100644
index 0000000..68b36c5
--- /dev/null
+++ b/Source/mesquite/lists/NumForCharMatrixList/NumForCharMatrixList.java
@@ -0,0 +1,178 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.NumForCharMatrixList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NumForCharMatrixList extends DataSetsListAssistant  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Matrix (in List of Character Matrices window)";
+	}
+	public String getNameForMenuItem() {
+		return "Number for Matrix";
+	}
+	public String getExplanation() {
+		return "Supplies numbers for character matrcies for a character matrices list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForMatrix.class, getName() + " needs a method to calculate a value for each of the character matrices.",
+		"You can select a value to show in the Number For Character Matrices submenu of the Columns menu of the List of Character Matrices Window. ");
+	}
+	NumberForMatrix numberTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberForMatrix)hireNamedEmployee(NumberForMatrix.class, arguments);
+			if (numberTask==null) {
+				return sorry("Number for character matrix (for list) can't start because the requested module was not successfully hired");
+			}
+			return true;
+		}
+		numberTask = (NumberForMatrix)hireEmployee(NumberForMatrix.class, "Value to calculate for character matrix (for List of Matrices window)");
+		if (numberTask==null) {
+			return sorry("Number for character matrix (for list) can't start because the no calculating module was successfully hired");
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (datas !=null)
+			datas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.datas = (ListableVector)obj;
+		datas.addListener(this);
+		doCalcs();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		doCalcs();
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return NumberForMatrix.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setValueTask ", numberTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a number for a character matrix", "[name of module]", commandName, "setValueTask")) {
+			NumberForMatrix temp= (NumberForMatrix)hireNamedEmployee(NumberForMatrix.class, arguments);
+			if (temp!=null) {
+				numberTask = temp;
+				return temp;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getTitle() {
+		if (numberTask==null)
+			return "";
+		return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		doCalcs();
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	NumberArray na = new NumberArray(0);
+	StringArray explArray = new StringArray(0);
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (numberTask==null || datas == null)
+			return;
+		outputInvalid();
+		int numBlocks = datas.size();
+		explArray.resetSize(numBlocks);
+		MesquiteString expl = new MesquiteString();
+		na.resetSize(numBlocks);
+		MesquiteNumber mn = new MesquiteNumber();
+		for (int ic=0; ic<numBlocks; ic++) {
+			CharacterData data = (CharacterData)datas.elementAt(ic);
+			mn.setToUnassigned();
+			numberTask.calculateNumber(data.getMCharactersDistribution(), mn, expl);
+			na.setValue(ic, mn);
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public String getStringForRow(int ic){
+		if (na==null)
+			return "";
+
+		return na.toString(ic);
+	}
+	public String getWidestString(){
+		if (numberTask==null)
+			return "888888";
+		return numberTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (datas !=null)
+			datas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/NumForTaxaList/NumForTaxaList.java b/Source/mesquite/lists/NumForTaxaList/NumForTaxaList.java
new file mode 100644
index 0000000..8081503
--- /dev/null
+++ b/Source/mesquite/lists/NumForTaxaList/NumForTaxaList.java
@@ -0,0 +1,307 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.NumForTaxaList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NumForTaxaList extends TaxonListAssistant implements MesquiteListener {
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Taxon (in List of Taxa window)";
+	}
+	public String getNameForMenuItem() {
+		return "Number for Taxon";
+	}
+	public String getExplanation() {
+		return "Supplies numbers for taxa for a taxa list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTaxon.class, getName()  + " needs a method to calculate a value for each of the taxa.",
+		"You can select a value to show in the Number For Taxa submenu of the Columns menu of the List of Taxa Window. ");
+	}
+	/*.................................................................................................................*/
+	NumberForTaxon numberTask;
+	MesquiteBoolean shadeCells;
+	Taxa taxa;
+	boolean suppressed = false;
+	MesquiteTable table;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberForTaxon)hireNamedEmployee(NumberForTaxon.class, arguments);
+			if (numberTask==null) {
+				return sorry("Number for taxon (for list) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			numberTask = (NumberForTaxon)hireEmployee(NumberForTaxon.class, "Value to calculate for taxa (for taxa list)");
+			if (numberTask==null) {
+				return sorry("Number for taxon (for list) can't start because no calculator module was successfully hired");
+			}
+		}
+		shadeCells = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Color Cells", makeCommand("toggleShadeCells",  this), shadeCells);
+		addMenuItem(null, "Select based on value...", makeCommand("selectBasedOnValue",  this));
+		addMenuItem(null, "Recalculate", makeCommand("recalculate",  this));
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return NumberForTaxon.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", numberTask); 
+		temp.addLine("toggleShadeCells " + shadeCells.toOffOnString());
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	public boolean querySelectBounds(MesquiteNumber lessThan, MesquiteNumber moreThan) {
+		if (lessThan==null || moreThan==null || numberTask==null)
+			return false;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Select based upon value",buttonPressed); 
+
+		dialog.addLargeOrSmallTextLabel("Select based upon value of " + numberTask.getNameOfValueCalculated());
+
+		SingleLineTextField moreThanField = dialog.addTextField("Select values greater than or equal to ","",20);
+		SingleLineTextField lessThanField = dialog.addTextField("Select values less than or equal to ","",20);
+
+
+		dialog.completeAndShowDialog(true);
+
+		if (buttonPressed.getValue()==0)  {
+			String s = moreThanField.getText();
+			moreThan.setValue(s);
+			s = lessThanField.getText();
+			lessThan.setValue(s);
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void SelectBasedOnValue() {
+		if (MesquiteThread.isScripting())
+			return;
+		if (table==null || taxa==null || na==null)
+			return;
+		MesquiteNumber lessThan = new MesquiteNumber();
+		MesquiteNumber moreThan = new MesquiteNumber();
+		if (!querySelectBounds(lessThan, moreThan))
+			return;
+		if (!lessThan.isCombinable() && ! moreThan.isCombinable())
+			return;
+		MesquiteNumber value = new MesquiteNumber();
+		for (int i=0; i<taxa.getNumTaxa(); i++) {
+			na.placeValue(i, value);
+
+			if (lessThan.isCombinable() && moreThan.isCombinable()) {
+				if ((lessThan.isMoreThan(value)|| lessThan.equals(value)) &&  (moreThan.isLessThan(value) ||  moreThan.equals(value))) {
+					table.selectRow(i);
+					taxa.setSelected(i, true);
+					table.redrawFullRow(i);
+				}
+			} else if (lessThan.isCombinable() && (lessThan.isMoreThan(value)|| lessThan.equals(value))) {
+				table.selectRow(i);
+				taxa.setSelected(i, true);
+				table.redrawFullRow(i);
+			} else if (moreThan.isCombinable() && (moreThan.isLessThan(value) ||  moreThan.equals(value))) {
+				table.selectRow(i);
+				taxa.setSelected(i, true);
+				table.redrawFullRow(i);
+			}
+		}
+		
+			taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a number for a taxon", "[name of module]", commandName, "setValueTask")) {
+			NumberForTaxon temp= (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Number for a taxon", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Requests a recalculation of the numbers (this may be unnecessary)", null, commandName, "recalculate")) {
+			doCalcs();
+			parametersChanged();
+		}
+
+		else if (checker.compare(this.getClass(), "Selects list rows based on value of this column", null, commandName, "selectBasedOnValue")) {
+			SelectBasedOnValue();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to color cells", "[on or off]", commandName, "toggleShadeCells")) {
+			boolean current = shadeCells.getValue();
+			shadeCells.toggleValue(parser.getFirstToken(arguments));
+			if (current!=shadeCells.getValue()) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		this.table = table;
+		this.taxa = taxa;
+		if (!suppressed)
+			doCalcs();
+	}
+	public String getTitle() {
+		if (numberTask==null)
+			return "";
+		return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == taxa)
+			taxa=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	NumberArray na = new NumberArray(0);
+	StringArray explArray = new StringArray(0);
+	MesquiteNumber min = new MesquiteNumber();
+	MesquiteNumber max = new MesquiteNumber();
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (suppressed || numberTask==null || taxa == null)
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		na.resetSize(numTaxa);
+		na.deassignArrayToInteger();
+		explArray.resetSize(numTaxa);
+		MesquiteNumber mn = new MesquiteNumber();
+		MesquiteString expl = new MesquiteString();
+		
+		MesquiteTimer timer = new MesquiteTimer();
+		timer.start();
+		
+		for (int ic=0; ic<numTaxa; ic++) {
+			CommandRecord.tick("Number for taxon in taxon list; examining taxon " + ic);
+			Taxon taxon = taxa.getTaxon(ic);
+			mn.setToUnassigned();
+			numberTask.calculateNumber(taxon, mn, expl);
+			na.setValue(ic, mn);
+			explArray.setValue(ic, expl.getValue());
+		}
+		na.placeMinimumValue(min);
+		na.placeMaximumValue(max);
+	}
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		if (!shadeCells.getValue())
+			return null;
+		if (min.isCombinable() && max.isCombinable() && na != null && na.isCombinable(ic)){
+			return MesquiteColorTable.getGreenScale(na.getDouble(ic), min.getDoubleValue(), max.getDoubleValue(), false);
+		}
+		return null;
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+	public String getStringForTaxon(int ic){
+		if (na==null)
+			return "";
+		return na.toString(ic);
+	}
+	public String getWidestString(){
+		if (numberTask==null)
+			return "88888888";
+		String name = numberTask.getVeryShortName()+"   ";
+		if (StringUtil.blank(name) || name.length()<8)
+			return "88888888";
+		return name;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/NumForTreeList/NumForTreeList.java b/Source/mesquite/lists/NumForTreeList/NumForTreeList.java
new file mode 100644
index 0000000..577f525
--- /dev/null
+++ b/Source/mesquite/lists/NumForTreeList/NumForTreeList.java
@@ -0,0 +1,198 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.NumForTreeList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NumForTreeList extends TreeListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Tree (in List of Trees window)";
+	}
+	public String getNameForMenuItem() {
+		return "Number for tree";
+	}
+
+	public String getExplanation() {
+		return "Supplies numbers for trees for a trees list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " needs a method to calculate a value for each of the trees.",
+		"You can select a value to show in the Number For Trees submenu of the Columns menu of the List of Trees Window. ");
+		e.setPriority(1);
+	}
+	/*.................................................................................................................*/
+	NumberForTree numberTask;
+	TreeVector treesBlock;
+	boolean suppressed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberForTree)hireNamedEmployee(NumberForTree.class, arguments);
+			if (numberTask==null) {
+				return sorry("Number for tree (for list) can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			numberTask = (NumberForTree)hireEmployee(NumberForTree.class, "Value to calculate for trees (for tree list)");
+			if (numberTask==null) {
+				return sorry("Number for tree (for list) can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return NumberForTree.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress"); 
+		temp.addLine("setValueTask ", numberTask); 
+		temp.addLine("desuppress"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a number for a tree", "[name of module]", commandName, "setValueTask")) {
+			NumberForTree temp= (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Number for a tree", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				if (!suppressed){
+					doCalcs();
+					parametersChanged();
+				}
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculation", null, commandName, "suppress")) {
+			suppressed = true;
+		}
+		else if (checker.compare(this.getClass(), "Releases suppression of calculation", null, commandName, "desuppress")) {
+			if (suppressed){
+				suppressed = false;
+				outputInvalid();
+				doCalcs();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+		if (!suppressed)
+			doCalcs();
+	}
+	public String getTitle() {
+		if (numberTask==null)
+			return "";
+		return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!suppressed){
+			outputInvalid();
+			doCalcs();
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	NumberArray na = new NumberArray(0);
+	StringArray explArray = new StringArray(0);
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (suppressed || numberTask==null || treesBlock == null)
+			return;
+		
+		int numTrees = treesBlock.size();
+		na.resetSize(numTrees);
+		explArray.resetSize(numTrees);
+		MesquiteNumber mn = new MesquiteNumber();
+		MesquiteString expl = new MesquiteString();
+		for (int ic=0; ic<numTrees; ic++) {
+			CommandRecord.tick("Number for tree in tree list; examining tree " + ic);
+			Tree tree = treesBlock.getTree(ic);
+		//	if (tree instanceof MesquiteTree)
+		//		((MesquiteTree)tree).setAssignedNumber(ic);
+			mn.setToUnassigned();
+			numberTask.calculateNumber(tree, mn, expl);
+			na.setValue(ic, mn);
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public String getStringForTree(int ic){
+		if (na==null)
+			return "";
+
+		return na.toString(ic);
+	}
+	public String getWidestString(){
+		if (numberTask==null)
+			return "888888";
+		return numberTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/NumForTreeblockList/NumForTreeblockList.java b/Source/mesquite/lists/NumForTreeblockList/NumForTreeblockList.java
new file mode 100644
index 0000000..f7e2a5a
--- /dev/null
+++ b/Source/mesquite/lists/NumForTreeblockList/NumForTreeblockList.java
@@ -0,0 +1,178 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.NumForTreeblockList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NumForTreeblockList extends TreeblocksListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Tree Block (in List of Tree Blocks window)";
+	}
+	public String getNameForMenuItem() {
+		return "Number for Tree Block";
+	}
+	public String getExplanation() {
+		return "Supplies numbers for tree blocks for a tree blocks list window." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTreeBlock.class, getName() + " needs a method to calculate a value for each of the tree blocks.",
+		"You can select a value to show in the Number For Tree Blocks submenu of the Columns menu of the List of Tree Blocks Window. ");
+	}
+	/*.................................................................................................................*/
+	ListableVector treeBlocks=null;
+	NumberForTreeBlock numberTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberForTreeBlock)hireNamedEmployee(NumberForTreeBlock.class, arguments);
+			if (numberTask==null) {
+				return sorry("Number for tree block (for list) can't start because the requested module was not successfully hired");
+			}
+			return true;
+		}
+		numberTask = (NumberForTreeBlock)hireEmployee(NumberForTreeBlock.class, "Value to calculate for tree block (for tree block list)");
+		if (numberTask==null) {
+			return sorry("Number for tree block (for list) can't start because the no calculating module was successfully hired");
+		}
+		return true;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.treeBlocks = (ListableVector)obj;
+		treeBlocks.addListener(this);
+		doCalcs();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		doCalcs();
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return NumberForTreeBlock.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setValueTask ", numberTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a number for a block of trees", "[name of module]", commandName, "setValueTask")) {
+			NumberForTreeBlock temp= (NumberForTreeBlock)hireNamedEmployee(NumberForTreeBlock.class, arguments);
+			if (temp!=null) {
+				numberTask = temp;
+				return temp;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getTitle() {
+		if (numberTask==null)
+			return "";
+		return numberTask.getVeryShortName();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		doCalcs();
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	NumberArray na = new NumberArray(0);
+	StringArray explArray = new StringArray(0);
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		if (numberTask==null || treeBlocks == null)
+			return;
+		outputInvalid();
+		int numBlocks = treeBlocks.size();
+		explArray.resetSize(numBlocks);
+		MesquiteString expl = new MesquiteString();
+		na.resetSize(numBlocks);
+		MesquiteNumber mn = new MesquiteNumber();
+		for (int ic=0; ic<numBlocks; ic++) {
+			TreeVector trees = (TreeVector)treeBlocks.elementAt(ic);
+			mn.setToUnassigned();
+			numberTask.calculateNumber(trees, mn, expl);
+			na.setValue(ic, mn);
+			explArray.setValue(ic, expl.getValue());
+		}
+	}
+	public String getExplanationForRow(int ic){
+		if (explArray == null || explArray.getSize() <= ic)
+			return null;
+		return explArray.getValue(ic);
+	}
+	public String getStringForRow(int ic){
+		if (na==null)
+			return "";
+
+		return na.toString(ic);
+	}
+	public String getWidestString(){
+		if (numberTask==null)
+			return "888888";
+		return numberTask.getVeryShortName()+"   ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void endJob() {
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxaListUniqueID/TaxaListUniqueID.java b/Source/mesquite/lists/TaxaListUniqueID/TaxaListUniqueID.java
new file mode 100644
index 0000000..6aaad8a
--- /dev/null
+++ b/Source/mesquite/lists/TaxaListUniqueID/TaxaListUniqueID.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxaListUniqueID;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaListUniqueID extends TaxonListAssistant  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Unique ID (taxa)";
+	}
+	public String getExplanation() {
+		return "Shows unique id assigned to taxon." ;
+	}
+	Taxa taxa=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		addMenuItem("Replace Unique IDs", makeCommand("replaceIDs",  this));
+		addMenuItem("Fill Missing Unique IDs", makeCommand("fillMissingIDs",  this));
+		addMenuItem("Remove Unique IDs", makeCommand("removeIDs",  this));
+		return true;
+	}
+
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.taxa = taxa;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Replaces the uniqueIDs of selected", null, commandName, "replaceIDs")) {
+			if (taxa != null) {
+				stamp(true);
+			}
+			//outputInvalid();
+		}
+		else if (checker.compare(this.getClass(), "Removes the uniqueIDs of selected", null, commandName, "removeIDs")) {
+			if (taxa != null) {
+				remove();
+			}
+			//outputInvalid();
+		}
+		else if (checker.compare(this.getClass(), "Fills in any missing uniqueIDs of selected", null, commandName, "fillMissingIDs")) {
+			if (taxa != null)
+				stamp(false);
+			//outputInvalid();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	void stamp(boolean replace){
+		if (taxa ==null)
+			return;
+		boolean changed=false;
+		if (employer!=null && employer instanceof ListModule) {
+			int c = ((ListModule)employer).getMyColumn(this);
+			boolean noneSelected = !table.anyCellSelectedAnyWay();
+			for (int i=0; i<taxa.getNumTaxa(); i++) {
+				if (noneSelected || table.isCellSelectedAnyWay(c, i)) {
+					taxa.stampUniqueID(i, replace);
+					if (!changed)
+						outputInvalid();
+					changed = true;
+				}
+			}
+		}
+		if (changed)
+			parametersChanged();
+	}
+	void remove(){
+		if (taxa ==null)
+			return;
+		boolean changed=false;
+		if (employer!=null && employer instanceof ListModule) {
+			int c = ((ListModule)employer).getMyColumn(this);
+			boolean noneSelected = !table.anyCellSelectedAnyWay();
+			for (int i=0; i<taxa.getNumTaxa(); i++) {
+				if (noneSelected || table.isCellSelectedAnyWay(c, i)) {
+					taxa.setUniqueID(i, null);
+					if (!changed)
+						outputInvalid();
+					changed = true;
+				}
+			}
+		}
+		if (changed)
+			parametersChanged();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged();
+	}
+	 */
+	public String getStringForTaxon(int ic){
+		String s = null;
+		if (taxa != null)
+			s = taxa.getUniqueID(ic); //+1 because zero based
+		if (StringUtil.blank(s))
+			s = "?";
+		return s;
+	}
+	public String getWidestString(){
+		return "88888888888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "ID";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxaPartListNumGroups/TaxaPartListNumGroups.java b/Source/mesquite/lists/TaxaPartListNumGroups/TaxaPartListNumGroups.java
new file mode 100644
index 0000000..ffe6a8f
--- /dev/null
+++ b/Source/mesquite/lists/TaxaPartListNumGroups/TaxaPartListNumGroups.java
@@ -0,0 +1,100 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxaPartListNumGroups;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaPartListNumGroups extends TaxaPartListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of groups in taxa partition";
+	}
+	public String getExplanation() {
+		return "Indicates number of groups in taxa partition in list window." ;
+	}
+	Taxa taxa=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (taxa !=null)
+			taxa.removeListener(this);
+		if (obj instanceof Taxa)
+			taxa = (Taxa)obj;
+		if (taxa !=null)
+			taxa.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# groups";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (taxa == null)
+				return null;
+			SpecsSetVector partitions = taxa.getSpecSetsVector(TaxaPartition.class);
+			if (partitions ==null || ic<0 || ic>= partitions.size())
+				return "";
+			return Integer.toString(((TaxaPartition)partitions.elementAt(ic)).getNumberOfGroups());
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " 888888 ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (taxa !=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxaPartitionList/TaxaPartitionList.java b/Source/mesquite/lists/TaxaPartitionList/TaxaPartitionList.java
new file mode 100644
index 0000000..bcdc136
--- /dev/null
+++ b/Source/mesquite/lists/TaxaPartitionList/TaxaPartitionList.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxaPartitionList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaPartitionList extends TaxaSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Taxa Partitions";
+	}
+	public String getExplanation() {
+		return "Makes windows listing taxa partitions." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaPartListAssistant.class, "The List of Taxa Partitions window can display columns showing information for each taxa partition.",
+		"You can request that columns be shown using the Columns menu of the List of Taxa Partitions Window. ");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Taxa Partition...", makeCommand("newTaxaPartition",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	/*.................................................................................................................*/
+	public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+		super.showListWindow(obj);
+		TaxaPartListAssistant assistant = (TaxaPartListAssistant)hireNamedEmployee(TaxaPartListAssistant.class, "#TaxaPartListNumGroups");
+		if (assistant!= null){
+			((ListWindow)getModuleWindow()).addListAssistant(assistant);
+			assistant.setUseMenubar(false);
+		}
+	}
+	public Class getItemType(){
+		return TaxaPartition.class;
+	}
+	public Class getAssistantClass(){
+		return TaxaPartListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Taxa partition";
+	}
+	public String getItemTypeNamePlural(){
+		return "Taxa partitions";
+	}
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return taxa;
+	}
+	public SpecsSet makeNewSpecsSet(Taxa taxa){
+		if (taxa != null)
+			return new TaxaPartition("Partition", taxa.getNumTaxa(), null, taxa);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new taxa partition", null, commandName, "newTaxaPartition")){
+			if (taxa !=null &&AlertDialog.query(containerOfModule(), "New Partition", "To make a new partition of taxa, go to the List of Taxa window, make sure that a column for Current Partition appears, edit the column, then save the partition.  Would you like to go to the List of Taxa window now?", "OK", "Cancel")) {
+				Object obj = taxa.doCommand("showMe", null, checker);
+				if (obj !=null && obj instanceof Commandable){
+					Commandable c = (Commandable)obj;
+					c.doCommand("newAssistant", "#TaxonListCurrPartition", checker);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns taxa block in use", null, commandName, "getTaxa"))
+			return taxa;
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/lists/TaxaSetListNum/TaxaSetListNum.java b/Source/mesquite/lists/TaxaSetListNum/TaxaSetListNum.java
new file mode 100644
index 0000000..1def052
--- /dev/null
+++ b/Source/mesquite/lists/TaxaSetListNum/TaxaSetListNum.java
@@ -0,0 +1,96 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxaSetListNum;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaSetListNum extends TaxaSetListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of taxa in taxa set";
+	}
+	public String getExplanation() {
+		return "Indicates number of taxa in taxa set in list window." ;
+	}
+	Taxa taxa=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (taxa !=null)
+			taxa.removeListener(this);
+		if (obj instanceof Taxa)
+			taxa = (Taxa)obj;
+		if (taxa !=null)
+			taxa.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# taxa included";
+	}
+	public String getStringForRow(int ic){
+		if (taxa == null)
+			return null;
+		SpecsSetVector tsets = taxa.getSpecSetsVector(TaxaSelectionSet.class);
+		if (tsets ==null || ic<0 || ic>= tsets.size())
+			return "";
+		return Integer.toString(((TaxaSelectionSet)tsets.elementAt(ic)).numberSelected());
+	}
+	public String getWidestString(){
+		return " # taxa included ";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (taxa !=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxablockList/TaxablockList.java b/Source/mesquite/lists/TaxablockList/TaxablockList.java
new file mode 100644
index 0000000..ee2227f
--- /dev/null
+++ b/Source/mesquite/lists/TaxablockList/TaxablockList.java
@@ -0,0 +1,150 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxablockList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxablockList extends ListLVModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxa blocks list";
+	}
+	public String getExplanation() {
+		return "Makes windows listing blocks of Taxa and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaBlocksListAssistant.class, "The List of Taxa Blocks window can display columns showing information for each taxa block.",
+		"You can request that columns be shown using the Columns menu of the List of Taxa Blocks Window. ");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null  && getProject().getTaxas()==obj);
+	}
+
+	public boolean resetMenusOnNameChange(){
+		return true;
+	}
+	public void showListWindow(Object obj){
+		setModuleWindow(new ListableVectorWindow(this));
+		((ListableVectorWindow)getModuleWindow()).setObject(getProject().getTaxas());
+		makeMenu("List");
+
+		MesquiteSubmenuSpec mss2 = addSubmenu(null, "Utilities", MesquiteModule.makeCommand("doUtility",  this));
+		mss2.setList(TaxaBlocksListUtility.class);
+		if (!MesquiteThread.isScripting()){
+			TaxaBlocksListAssistant assistant = (TaxaBlocksListAssistant)hireNamedEmployee(TaxaBlocksListAssistant.class, StringUtil.tokenize("Number of taxa in set"));
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	public String getItemTypeName(){
+		return "Taxa block";
+	}
+	public String getItemTypeNamePlural(){
+		return "Taxa blocks";
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return getProject().getTaxas();
+	}
+	public int getNumberOfRows(){
+		if (getProject().getTaxas()==null)
+			return 0;
+		else
+			return getProject().getTaxas().size();
+	}
+	public Class getAssistantClass(){
+		return TaxaBlocksListAssistant.class;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires utility module to operate on the taxa blocks", "[name of module]", commandName, "doUtility")) {
+			if (getProject().getTaxas() !=null){
+				TaxaBlocksListUtility tda= (TaxaBlocksListUtility)hireNamedEmployee(TaxaBlocksListUtility.class, arguments);
+				if (tda!=null) {
+					boolean a = tda.operateOnTaxas(getProject().getTaxas());
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean rowDeletable(int row){
+		return true; //(getProject().getNumberTaxas()>1);
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return false;
+		Taxa taxa = getProject().getTaxa(row);
+		getProject().removeFileElement(taxa);//must remove first, before disposing
+		taxa.dispose();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == getProject().getTaxas() && code == MesquiteListener.ELEMENT_CHANGED && getModuleWindow()!=null){
+			((TableWindow)getModuleWindow()).getTable().synchronizeRowSelection(getProject().getTaxas());
+			((TableWindow)getModuleWindow()).getTable().repaintAll();
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Requests a getModuleWindow() to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/TaxablockListNumber/TaxablockListNumber.java b/Source/mesquite/lists/TaxablockListNumber/TaxablockListNumber.java
new file mode 100644
index 0000000..3ac6d90
--- /dev/null
+++ b/Source/mesquite/lists/TaxablockListNumber/TaxablockListNumber.java
@@ -0,0 +1,96 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxablockListNumber;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxablockListNumber extends TaxaBlocksListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of taxa in set";
+	}
+	public String getExplanation() {
+		return "Indicates number of taxa in list window." ;
+	}
+	ListableVector taxas=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (taxas !=null)
+			taxas.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.taxas = (ListableVector)obj;
+		taxas.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# taxa";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (taxas ==null || ic<0 || ic> taxas.size())
+				return "";
+			return Integer.toString( ((Taxa)taxas.elementAt(ic)).getNumTaxa());
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " 888888 ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (taxas !=null)
+			taxas.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxonGroupList/TaxonGroupList.java b/Source/mesquite/lists/TaxonGroupList/TaxonGroupList.java
new file mode 100644
index 0000000..a516e11
--- /dev/null
+++ b/Source/mesquite/lists/TaxonGroupList/TaxonGroupList.java
@@ -0,0 +1,353 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonGroupList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonGroupList extends ListModule {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxonGroupListAssistant.class, "The List of Taxon Groups window can display columns showing information for each taxon group.",
+				"You can request that columns be shown using the Columns menu of the List of Taxon Groups Window. ");
+	}
+	TaxaGroupVector groups;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("New Taxon Group...", MesquiteModule.makeCommand("newGroup",  this));
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null && obj == groups);
+	}
+	public void endJob(){
+	//	if (groups != null)
+	//		groups.removeListener(this);
+
+		super.endJob();
+	}
+	public void showListWindow(Object obj){
+		setModuleWindow(new TaxonGroupListWindow(this));
+		groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+//		groups.addListener(this);
+		((TaxonGroupListWindow)getModuleWindow()).setObject(groups);
+
+		makeMenu("List");
+
+
+		if (!MesquiteThread.isScripting()){
+			TaxonGroupListAssistant assistant = (TaxonGroupListAssistant)hireNamedEmployee(TaxonGroupListAssistant.class, StringUtil.tokenize("#TaxonGroupListColor"));
+			if (assistant!= null){
+				((TaxonGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TaxonGroupListAssistant)hireNamedEmployee(TaxonGroupListAssistant.class, StringUtil.tokenize("#TaxonGroupListSymbol"));
+			if (assistant!= null){
+				((TaxonGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TaxonGroupListAssistant)hireNamedEmployee(TaxonGroupListAssistant.class, StringUtil.tokenize("#TaxonGroupListSymbolSize"));
+			if (assistant!= null){
+				((TaxonGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TaxonGroupListAssistant)hireNamedEmployee(TaxonGroupListAssistant.class, StringUtil.tokenize("#TaxonGroupListVisibility"));
+			if (assistant!= null){
+				((TaxonGroupListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+		}
+
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		//getModuleWindow().setVisible(true);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Creates a new group", "[]", commandName, "newGroup")) {
+			MesquiteFile file = getProject().chooseFile( "Select file to which to add the new group label"); 
+			TaxaGroup group= TaxaListPartitionUtil.createNewTaxonGroup(this, file);   
+			if (group!=null){
+				((TaxonGroupListWindow)getModuleWindow()).getTable().repaint(); 
+				parametersChanged();
+			}
+			return group;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		TaxaGroupVector vector = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		MesquiteTable table = ((TaxonGroupListWindow)getModuleWindow()).getTable();
+		if (obj instanceof TaxaGroupVector) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				table.redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				table.synchronizeRowSelection(vector);
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				table.setNumRows(vector.size());
+				table.synchronizeRowSelection(vector);
+				table.repaintAll();
+			}
+			else {
+				table.repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return getProject().getFileElement(TaxaGroupVector.class, 0);
+	}
+	public int getNumberOfRows(){
+		if (getProject().getFileElement(TaxaGroupVector.class, 0)==null)
+			return 0;
+		else
+			return ((ListableVector)getProject().getFileElement(TaxaGroupVector.class, 0)).size();
+	}
+	public Class getAssistantClass(){
+		return TaxonGroupListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Taxon Group";
+	}
+	public String getItemTypeNamePlural(){
+		return "Taxon Groups";
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		TaxaGroup group = ((TaxonGroupListWindow)getModuleWindow()).getTaxonGroup(row);
+		if (group!=null){
+			group.deleteMe(false);
+			
+			group.dispose();
+			return true;
+
+		}
+		return false;
+	}
+
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ 
+		if (row<0 || row>= getNumberOfRows())
+			return null;
+		TaxaGroup group = ((TaxonGroupListWindow)getModuleWindow()).getTaxonGroup(row);
+		return group.getAnnotation();
+	}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return;
+		TaxaGroup group = ((TaxonGroupListWindow)getModuleWindow()).getTaxonGroup(row);
+		group.setAnnotation(s, notify);
+	}
+	/** returns a String of explanation for a row*/
+	public String getExplanation(int row){
+		TaxaGroup group = ((TaxonGroupListWindow)getModuleWindow()).getTaxonGroup(row);
+		if (group!=null)
+			return group.getExplanation();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		//if (getModuleWindow()!=null && !getModuleWindow().isVisible())
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Requests a getModuleWindow() to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		//Debug.println("disposing of getModuleWindow()");
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Taxon Group Labels";
+	}
+	public String getExplanation() {
+		return "Makes windows listing taxon groups and information about them." ;
+	}
+
+
+}
+
+/* ======================================================================== */
+class TaxonGroupListWindow extends ListWindow implements MesquiteListener {
+	TaxaGroupVector groups;
+	public TaxonGroupListWindow (TaxonGroupList ownerModule) {
+		super(ownerModule);
+		MesquiteTable t = getTable();
+		if (t!=null)
+			t.setAutoEditable(false, false, false, false);
+	}
+	/*.................................................................................................................*/
+	/** When called the getModuleWindow() will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Taxon Groups"); 
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return groups;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof ListableVector) {
+			if (groups!=null)
+				groups.removeListener(this);
+			groups = (TaxaGroupVector)obj;
+			groups.addListener(this);
+			getTable().synchronizeRowSelection(groups);
+		}
+		super.setCurrentObject(obj);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean isRowNameEditable(int row){
+		TaxaGroup group = getTaxonGroup(row);
+		return (group!=null);
+	}
+	TaxaGroup getTaxonGroup(int row){
+		if (groups!=null) {
+			if (row>=0 && row<groups.size())
+				return(TaxaGroup)groups.elementAt(row);
+		}
+		return null;
+	}
+	public boolean interceptRowNameTouch(int row, int regionInCellH, int regionInCellV, int modifiers){
+		TaxaGroup group = getTaxonGroup(row);
+		if (group!=null){
+			getTable().editRowNameCell(row);
+		}
+		return true;
+	}
+	public void setRowName(int row, String name){
+		TaxaGroup group = getTaxonGroup(row);
+		if (group!=null){
+			group.setName(name);
+			
+			resetAllTitles();
+			getOwnerModule().resetAllMenuBars();
+
+		}
+	}
+	public String getRowName(int row){
+		if (groups!=null){
+			if (row<0 && row >= groups.size())
+				return null;
+			return ((Listable)groups.elementAt(row)).getName();
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj ==groups)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		if (obj instanceof GroupLabel) {
+			getTable().repaintAll();
+		}
+		else if (obj instanceof ListableVector && (ListableVector)obj ==groups) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				getTable().redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) { //listable vector, not Associable, hence dont' synchronize
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				getTable().setNumRows(groups.size());
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else if (code!=MesquiteListener.ANNOTATION_CHANGED && code!=MesquiteListener.ANNOTATION_ADDED && code!=MesquiteListener.ANNOTATION_DELETED) {
+				getTable().setNumRows(groups.size());
+				getTable().synchronizeRowSelection(groups);
+				getTable().repaintAll();
+			}
+			else  {
+				getTable().repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+
+	public void dispose(){
+		if (groups!=null)
+			groups.removeListener(this);
+		super.dispose();
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/lists/TaxonGroupListColor/TaxonGroupListColor.java b/Source/mesquite/lists/TaxonGroupListColor/TaxonGroupListColor.java
new file mode 100644
index 0000000..fe9c439
--- /dev/null
+++ b/Source/mesquite/lists/TaxonGroupListColor/TaxonGroupListColor.java
@@ -0,0 +1,222 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.TaxonGroupListColor;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Shape;
+
+import javax.swing.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class TaxonGroupListColor extends TaxonGroupListAssistant  {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Set Color...", makeCommand("setColor", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Group Colors";
+	}
+	public String getExplanation() {
+		return "Shows color assigned to taxon group." ;
+	}
+
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	TaxaGroup getTaxonGroup(int ic){
+		TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		if (groups!=null) {
+			if (ic>=0 && ic<groups.size())
+				return(TaxaGroup)groups.elementAt(ic);
+		}
+		return null;
+	}
+
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			Color color = tg.getColor();
+			return color;
+		}
+		return null;
+
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		Color c = getBackgroundColorOfCell(ic,selected);
+		Color oldColor = g.getColor();
+		Color highlightColor = Color.black;
+		if (c!=null)
+			highlightColor = ColorDistribution.getContrasting(c);
+		if (c!=null){ 
+			g.setColor(c);
+			g.fillRect(x+1, y+1, w-1, h-1);
+		}
+		if (selected) {
+			g.setColor(highlightColor);
+			g.drawRect(x+1, y+1, w-2, h-2);
+			g.drawRect(x+2, y+2, w-4,h-4);
+		}
+		g.setColor(oldColor);
+	}
+	Color newColor = null;
+	/*.................................................................................................................*/
+	public boolean chooseColor(Color oldColor){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying Options"))  
+			return true;
+		JFrame guiFrame = new JFrame();
+		newColor = JColorChooser.showDialog(guiFrame, "Pick a Color", oldColor);
+		if (newColor!=null){
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void specifyColor () {
+		TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		if (groups!=null  && table != null) {
+			Color oldColor = null;
+			boolean variable = false;
+			for (int i = 0; i< groups.size(); i++){
+				if (groups.getSelected(i) || table.isRowSelected(i)){
+					TaxaGroup tg = getTaxonGroup(i);
+					if (tg!=null){
+						Color color = tg.getColor();
+						if (color!=null){
+							if (ColorDistribution.equalColors(color, oldColor))
+								variable=true;
+							oldColor = color;
+						}
+					}
+				}
+			}
+			if (variable==true)
+				oldColor=null;
+			if (chooseColor(oldColor)){
+				for (int i = 0; i< groups.size(); i++){
+					if (groups.getSelected(i) || table.isRowSelected(i)){
+						TaxaGroup tg = getTaxonGroup(i);
+						if (tg!=null){
+							tg.setColor(newColor);
+							MesquiteSymbol symbol = tg.getSymbol();
+							if (symbol!=null)
+								symbol.setColor(newColor);
+						}
+					}
+				}
+				if (table != null)
+					table.repaintAll();
+				parametersChanged();
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	public void specifyColor (int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			Color oldColor = null;
+			if (chooseColor(oldColor)){
+				tg.setColor(newColor);
+				MesquiteSymbol symbol = tg.getSymbol();
+				if (symbol!=null)
+					symbol.setColor(newColor);
+				if (table != null)
+					table.repaintAll();
+				parametersChanged();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the color", null, commandName, "setColor")) {
+			String newColorText = parser.getFirstToken(arguments);
+			if (StringUtil.blank(newColorText)){   //TODO: what if not blank???
+				specifyColor();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g,  int ic,  int x, int y, boolean doubleClick, int modifiers){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		if (ic>=0 && doubleClick) {
+			specifyColor(ic);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	public String getWidestString(){
+		return "888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Color";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/** Returns whether to use the string from getStringForRow; otherwise call drawInCell*/
+	public boolean useString(int ic){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void setTableAndObject(MesquiteTable table, Object object) {
+		this.table = table;
+
+	}
+	public String getStringForRow(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			return tg.getColor().toString();
+		}
+		return "";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+
+}
diff --git a/Source/mesquite/lists/TaxonGroupListSymbol/TaxonGroupListSymbol.java b/Source/mesquite/lists/TaxonGroupListSymbol/TaxonGroupListSymbol.java
new file mode 100644
index 0000000..3307e3e
--- /dev/null
+++ b/Source/mesquite/lists/TaxonGroupListSymbol/TaxonGroupListSymbol.java
@@ -0,0 +1,256 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.TaxonGroupListSymbol;
+
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.Shape;
+import java.awt.event.*;
+
+import javax.swing.JLabel;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class TaxonGroupListSymbol extends TaxonGroupListAssistant   {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Set Symbol...", makeCommand("setSymbol", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Group Symbol";
+	}
+	public String getExplanation() {
+		return "Shows symbol assigned to taxon group." ;
+	}
+
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	static final String chooseTemplate = "Choose Symbol";
+	MesquiteSymbol newSymbol = null;
+	MesquiteSymbol currentDialogSymbol = null;
+	String symbolOptionsButtonName = "Symbol Options...";
+	Button symbolOptionsButton;
+	Choice symbolsPopUp=null;
+	SymbolsVector symVector=null;
+	JLabel symbolLabel;
+
+	/*.................................................................................................................*/
+	public boolean queryOptions(MesquiteSymbol oldSymbol) {
+		if (!okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying Options")) 
+			return true;
+		GroupSymbolsDialog symbolsDialog = new GroupSymbolsDialog(getProject(), containerOfModule(), "Symbol Options", "", oldSymbol);
+		symbolsDialog.completeAndShowDialog();
+		String name = symbolsDialog.getName();
+		boolean ok = symbolsDialog.query()==0;
+		if (ok) {
+			newSymbol = symbolsDialog.getSymbol();
+		}
+		symbolsDialog.dispose();
+		if (!ok)
+			return false;
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void specifySymbol(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			MesquiteSymbol oldSymbol = tg.getSymbol();
+			if (queryOptions(oldSymbol)){
+				MesquiteSymbol groupSymbol = newSymbol.cloneMethod();
+				groupSymbol.setSize(oldSymbol.getSize());
+				tg.setSymbol(groupSymbol);
+				tg.setColor(tg.getColor());
+				if (table != null)
+					table.repaintAll();
+				parametersChanged();
+			}
+		}
+	}
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the symbol", null, commandName, "setSymbol")) {
+			String newSymbolName = parser.getFirstToken(arguments);
+			if (StringUtil.blank(newSymbolName)){
+				TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+				if (groups!=null  && table != null) {
+					String oldSymbolName = null;
+					MesquiteSymbol oldSymbol = null;
+					boolean variable = false;
+					for (int i = 0; i< groups.size(); i++){
+						if (groups.getSelected(i) || table.isRowSelected(i)){
+							TaxaGroup tg = getTaxonGroup(i);
+							if (tg!=null){
+								MesquiteSymbol symbol = tg.getSymbol();
+								if (symbol!=null){
+									String symbolName = symbol.getName();
+									if (oldSymbolName!=null && !oldSymbolName.equals(symbolName))
+										variable=true;
+									oldSymbolName=symbolName;
+									oldSymbol = symbol.cloneMethod();
+								}
+							}
+						}
+					}
+					if (variable==true)
+						oldSymbol=null;
+					if (queryOptions(oldSymbol)){
+						for (int i = 0; i< groups.size(); i++){
+							if (groups.getSelected(i) || table.isRowSelected(i)){
+								TaxaGroup tg = getTaxonGroup(i);
+								if (tg!=null){
+									MesquiteSymbol symbol = tg.getSymbol();
+									MesquiteSymbol groupSymbol = newSymbol.cloneMethod();
+									if (symbol!=null)
+										groupSymbol.setSize(symbol.getSize());
+									tg.setSymbol(groupSymbol);
+									tg.setColor(tg.getColor());
+								}
+							}
+
+						}
+						if (table != null)
+							table.repaintAll();
+						parametersChanged();
+					}
+
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	TaxaGroup getTaxonGroup(int ic){
+		TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		if (groups!=null) {
+			if (ic>=0 && ic<groups.size())
+				return(TaxaGroup)groups.elementAt(ic);
+		}
+		return null;
+	}
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. *
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			return tg.getColor();
+
+		}
+		return null;
+
+	}
+	/*.................................................................................................................*/
+
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		if (selected) {
+			g.setColor(Color.lightGray);
+		} else
+			g.setColor(Color.white);
+		g.fillRect(x+1, y+1, w-1, h-1);
+		MesquiteSymbol symbol = null;
+		TaxaGroup tg = getTaxonGroup(ic);
+		boolean colored = false;
+		if (tg!=null) {
+			symbol = tg.getSymbol();
+			if (symbol!=null) {
+				int size = symbol.getSize();
+				if (w-3<size)
+					size=w-3;
+				if (h/2-3<size)
+					size=h/2-3;
+				symbol.drawSymbol(g,x+w/2-size/2,y+h/2-size/2+3,size,size,false);
+			}
+
+		}
+	}
+	public String getStringForRow(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			MesquiteSymbol symbol = tg.getSymbol();
+			if (symbol!=null)
+				return ""+symbol.getName();
+		}
+		return "";
+	}
+
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic,  int x, int y, boolean doubleClick, int modifiers){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		if (ic>=0 && doubleClick) {
+			specifySymbol(ic);
+			return true;
+		}
+		return false;
+	}
+
+	/** Returns whether to use the string from getStringForRow; otherwise call drawInCell*/
+	public boolean useString(int ic){
+		return false;
+	}
+
+	public String getWidestString(){
+		return "888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Symbol";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void setTableAndObject(MesquiteTable table, Object object) {
+		this.table = table;
+
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+
+}
diff --git a/Source/mesquite/lists/TaxonGroupListSymbolSize/TaxonGroupListSymbolSize.java b/Source/mesquite/lists/TaxonGroupListSymbolSize/TaxonGroupListSymbolSize.java
new file mode 100644
index 0000000..4dd4b18
--- /dev/null
+++ b/Source/mesquite/lists/TaxonGroupListSymbolSize/TaxonGroupListSymbolSize.java
@@ -0,0 +1,214 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.TaxonGroupListSymbolSize;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Shape;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class TaxonGroupListSymbolSize extends TaxonGroupListAssistant  {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Set Size...", makeCommand("setSize", this));
+		return true;
+	}
+
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	TaxaGroup getTaxonGroup(int ic){
+		TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		if (groups!=null) {
+			if (ic>=0 && ic<groups.size())
+				return(TaxaGroup)groups.elementAt(ic);
+		}
+		return null;
+	}
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. *
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			return tg.getColor();
+
+		}
+		return null;
+
+	}
+	/*.................................................................................................................*
+
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		if (selected) {
+			g.setColor(Color.gray);
+		} else
+			g.setColor(Color.white);
+		g.fillRect(x+1, y+1, w-1, h-1);
+		MesquiteSymbol symbol = null;
+		TaxaGroup tg = getTaxonGroup(ic);
+		boolean colored = false;
+		if (tg!=null) {
+				symbol = tg.getSymbol();
+		if (symbol!=null) {
+			int size = symbol.getSize();
+			if (w-3<size)
+				size=w-3;
+			if (h/2-3<size)
+				size=h/2-3;
+			symbol.drawSymbol(g,x+w/2-size/2,y+h/2-size/2+3,size,size,true);
+		}
+			
+		}
+	}
+		/*.................................................................................................................*/
+	public void specifySymbolSize(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			MesquiteSymbol symbol = tg.getSymbol();
+			if (symbol!=null){
+				int oldSize = symbol.getSize();
+				int newSize = MesquiteInteger.queryInteger(containerOfModule(), "Symbol Size", "Symbol Size", oldSize, 1, 500, true);
+				if (MesquiteInteger.isCombinable(newSize)){
+					symbol.setSize(newSize);
+					if (table != null)
+						table.repaintAll();
+					parametersChanged();
+				}
+			}
+		}
+	}
+
+		/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the size of the symbol", null, commandName, "setSize")) {
+			String size = parser.getFirstToken(arguments);
+			if (StringUtil.blank(size)){
+				TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+				if (groups!=null  && table != null) {
+					int oldSize = -1;
+					boolean variableSize = false;
+					for (int i = 0; i< groups.size(); i++){
+						if (groups.getSelected(i) || table.isRowSelected(i)){
+							TaxaGroup tg = getTaxonGroup(i);
+							if (tg!=null){
+								MesquiteSymbol symbol = tg.getSymbol();
+								if (symbol!=null){
+									int symbolSize = symbol.getSize();
+									if (oldSize>-1 && oldSize!=symbolSize)
+										variableSize=true;
+									oldSize=symbolSize;
+								}
+							}
+						}
+					}
+					int newSize = MesquiteInteger.queryInteger(containerOfModule(), "Symbol Size", "Symbol Size", oldSize, 1, 500, true);
+					if (MesquiteInteger.isCombinable(newSize)){
+						for (int i = 0; i< groups.size(); i++){
+							if (groups.getSelected(i) || table.isRowSelected(i)){
+								TaxaGroup tg = getTaxonGroup(i);
+								if (tg!=null){
+									MesquiteSymbol symbol = tg.getSymbol();
+									if (symbol!=null)
+										symbol.setSize(newSize);
+								}
+							}
+						}
+						if (table != null)
+							table.repaintAll();
+					}
+
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	public String getStringForRow(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			MesquiteSymbol symbol = tg.getSymbol();
+			if (symbol!=null)
+				return ""+symbol.getSize();
+		}
+		return "";
+	}
+
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic,  int x, int y, boolean doubleClick, int modifiers){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		if (ic>=0 && doubleClick) {
+			specifySymbolSize(ic);
+			return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+
+	public String getWidestString(){
+		return "888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Symbol SIze";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object object) {
+		this.table = table;
+		
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Group Symbol Size";
+	}
+	public String getExplanation() {
+		return "Shows size of symbol assigned to taxon group." ;
+	}
+
+}
diff --git a/Source/mesquite/lists/TaxonGroupListVisibility/TaxonGroupListVisibility.java b/Source/mesquite/lists/TaxonGroupListVisibility/TaxonGroupListVisibility.java
new file mode 100644
index 0000000..252a7aa
--- /dev/null
+++ b/Source/mesquite/lists/TaxonGroupListVisibility/TaxonGroupListVisibility.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.TaxonGroupListVisibility;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Shape;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.table.MesquiteTable;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class TaxonGroupListVisibility extends TaxonGroupListAssistant  {
+	CharacterData data=null;
+	MesquiteTable table = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Show in Maps", makeCommand("showInMaps", this));
+		addMenuItem("Hide in Maps", makeCommand("hideInMaps", this));
+		return true;
+	}
+
+
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		this.data = data;
+		//data.addListener(this);
+		this.table = table;
+	}
+	/*.................................................................................................................*/
+	TaxaGroup getTaxonGroup(int ic){
+		TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		if (groups!=null) {
+			if (ic>=0 && ic<groups.size())
+				return(TaxaGroup)groups.elementAt(ic);
+		}
+		return null;
+	}
+		/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the visibility of the group in maps", null, commandName, "showInMaps")) {
+			TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+			for (int i = 0; i< groups.size(); i++){
+				if (groups.getSelected(i) || table.isRowSelected(i)){
+					TaxaGroup tg = getTaxonGroup(i);
+					if (tg!=null){
+						tg.setVisible(true);
+					}
+				}
+			}
+			if (table != null)
+				table.repaintAll();
+		}
+		else
+			if (checker.compare(this.getClass(), "Sets the group to be hidden in maps", null, commandName, "hideInMaps")) {
+				TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+				for (int i = 0; i< groups.size(); i++){
+					if (groups.getSelected(i) || table.isRowSelected(i)){
+						TaxaGroup tg = getTaxonGroup(i);
+						if (tg!=null){
+							tg.setVisible(false);
+						}
+					}
+				}
+				if (table != null)
+					table.repaintAll();
+			}
+			else
+				return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	public String getStringForRow(int ic) {
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			if (tg.isVisible())
+				return "show";
+			else 
+				return "HIDE";
+		}
+		return "";
+	}
+
+	/*.................................................................................................................*
+	public boolean arrowTouchInRow(Graphics g, int ic,  int x, int y, boolean doubleClick, int modifiers){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		TaxaGroup tg = getTaxonGroup(ic);
+		if (tg!=null){
+			tg.editMe();
+			parametersChanged();
+			return true;
+		}
+
+		return false;
+	}
+
+	/*.................................................................................................................*/
+
+	public String getWidestString(){
+		return "888888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "Show on Taxa Maps";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object object) {
+		this.table = table;
+		
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Group Visibility in Taxa Maps";
+	}
+	public String getExplanation() {
+		return "Shows whether or not a taxon group is shown on a taxa map." ;
+	}
+
+}
diff --git a/Source/mesquite/lists/TaxonList/TaxonList.java b/Source/mesquite/lists/TaxonList/TaxonList.java
new file mode 100644
index 0000000..6d804ce
--- /dev/null
+++ b/Source/mesquite/lists/TaxonList/TaxonList.java
@@ -0,0 +1,546 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonList;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonList extends ListModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing taxa and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e00 = registerEmployeeNeed(TaxaSelectCoordinator.class, "The List of Taxa window has facilities to select taxa.",
+				"This module is started automatically. ");
+		EmployeeNeed e0 = registerEmployeeNeed(TaxaListAssistantI.class, "The List of Taxa window can display columns showing information for each taxon.",
+				"This module is started automatically. ");
+		EmployeeNeed e = registerEmployeeNeed(TaxonListAssistant.class, "The List of Taxa window can display columns showing information for each taxon.",
+				"You can request that columns be shown using the Columns menu of the List of Taxa Window. ");
+		e.setEntryCommand("newAssistant");
+		EmployeeNeed e2 = registerEmployeeNeed(TaxonUtility.class, "Utilities operating on taxa can be used through the List of Taxa window.",
+				"You can request such a utility using the Taxon Utilities submenu of the List menu of the List of Taxa Window. ");
+		EmployeeNeed e3 = registerEmployeeNeed(TaxonNameAlterer.class, "Utilities to change taxon names can be used through the List of Taxa window.",
+				"You can request such a utility using the Taxon Names submenu of the List menu of the List of Taxa Window. ");
+	}
+	Taxa taxa;
+	TaxonListWindow window;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Rename Block of Taxa...", MesquiteModule.makeCommand("renameBlock",  this));
+		addMenuItem("Delete Block of Taxa...", MesquiteModule.makeCommand("deleteBlock",  this));
+		addMenuItem( "-", null);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*...............................................................................................................*/
+	public Undoer getSingleNameUndoInstructions(int row, String oldName, String s){
+		if (window!=null)
+			return new UndoInstructions(UndoInstructions.SINGLETAXONNAME, row, new MesquiteString(oldName), new MesquiteString(s),taxa,window.getTable());
+		else 
+			return new UndoInstructions(UndoInstructions.SINGLETAXONNAME, row, new MesquiteString(oldName), new MesquiteString(s),taxa, null);
+	}
+	public boolean showing(Object obj){
+		if (obj instanceof String) {
+			String arguments = (String)obj;
+			int query = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			return (query == getProject().getTaxaNumber(taxa) && getModuleWindow()!=null);
+		}
+		if (obj instanceof Taxa) {
+			return (this.taxa == obj && getModuleWindow()!=null);
+		}
+		return false;
+	}
+
+	public void showListWindow(Object obj){
+		if (obj instanceof Taxa) {
+			taxa = (Taxa)obj;
+			window = new TaxonListWindow(this);
+			setModuleWindow( window);
+
+			window.setObject(taxa);
+			//makeMenu("Taxon_List");
+			makeMenu("List");
+
+			MesquiteSubmenuSpec mss2 = addSubmenu(null, "Taxon Utilities", MesquiteModule.makeCommand("doUtility",  this));
+			mss2.setList(TaxonUtility.class);
+			MesquiteSubmenuSpec mss3 = addSubmenu(null, "Taxon Names", MesquiteModule.makeCommand("doNames",  this));
+			mss3.setList(TaxonNameAlterer.class);
+			addMenuItem( "Save selected as set...", makeCommand("saveSelectedRows", this));
+			addMenuItem( "-", null);
+
+			/* default columns*
+			TaxonListAssistant assistant = (TaxonListAssistant)hireNamedEmployee(TaxonListAssistant.class, StringUtil.tokenize("#DefaultTaxaOrder"));
+			if (assistant!= null){
+				((TaxonListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/* removed as default v. 2. 01; returned for v. 2. 5 */
+			TaxonListAssistant assistant = (TaxonListAssistant)hireNamedEmployee(TaxonListAssistant.class, StringUtil.tokenize("#TaxonListCurrPartition"));
+			if (assistant!= null){
+				((TaxonListWindow)window).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			/*	*/
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return taxa;
+	}
+	public int getNumberOfRows(){
+		if (taxa==null)
+			return 0;
+		else
+			return taxa.getNumTaxa();
+	}
+	public Class getAssistantClass(){
+		return TaxonListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Taxon";
+	}
+	public String getItemTypeNamePlural(){
+		return "Taxa";
+	}
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (taxa!=null && taxa.getNumTaxa() > 1) {
+			if (taxa.isEditInhibited()){
+				discreetAlert("You cannot delete taxa; the taxa block is locked.");
+				return false;
+			}
+
+			taxa.deleteTaxa(row,1, notify);
+			return true;
+		}
+		return false;
+	}
+	public boolean deleteRows(int first, int last, boolean notify){
+		if (taxa!=null) {
+			if (taxa.isEditInhibited()){
+				discreetAlert("You cannot delete taxa; the taxa block is locked.");
+				return false;
+			}
+			taxa.deleteTaxa(first, last-first+1, notify);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean rowsAddable(){
+		return true;
+	}
+	public boolean addRow(){
+		if (taxa!=null) {
+			if (taxa.isEditInhibited()){
+				discreetAlert("You cannot add taxa; the taxa block is locked.");
+				return false;
+			}
+			taxa.addTaxa(taxa.getNumTaxa(), 1, false);
+			return true;
+		}
+		return false;
+	}
+	public void focusInRow(int row){
+	}
+	/** returns either a String (if not editable) or a MesquiteString (if to be editable) */
+	public String getAnnotation(int row){
+		if (taxa !=null) {
+			return taxa.getAnnotation(row);
+		}
+		return null;
+	}
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		if (taxa !=null) {
+			taxa.setAnnotation(row, s);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+
+
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		//if (getModuleWindow()!=null && !getModuleWindow().isVisible())
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Renames the block of taxa", "[name of block]", commandName, "renameBlock")) {
+			if (taxa == null)
+				return null;
+			String token = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+			if (StringUtil.blank(token) && !MesquiteThread.isScripting()) {
+				token = MesquiteString.queryString(containerOfModule(), "Rename block of taxa", "New name for block of taxa:", taxa.getName(), 2);
+				if (StringUtil.blank(token))
+					return null;
+			}
+			taxa.setName(token);
+			MesquiteWindow.resetAllTitles();
+
+		}
+		else if (checker.compare(this.getClass(), "Deletes the block of taxa", null, commandName, "deleteBlock")) {
+			if (taxa == null)
+				return null;
+			if (!MesquiteThread.isScripting())
+				if (!AlertDialog.query(containerOfModule(), "Delete block of taxa?", "Are you sure you want to delete the block of taxa?  You cannot undo this."))
+					return null;
+			taxa.deleteMe(false);
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the taxa block used", "[block reference, number, or name]", commandName, "setTaxa")) {
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (getModuleWindow()!=null && t!=null){
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa = t;
+				if (taxa!=null)
+					taxa.addListener(this);
+				((TaxonListWindow)getModuleWindow()).setObject(taxa);
+				((TaxonListWindow)getModuleWindow()).repaintAll();
+				return taxa;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires utility module to operate on the taxa", "[name of module]", commandName, "doUtility")) {
+			if (taxa !=null){
+				TaxonUtility tda= (TaxonUtility)hireNamedEmployee(TaxonUtility.class, arguments);
+				if (tda!=null) {
+					boolean a = tda.operateOnTaxa(taxa);
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires utility module to alter names of the taxa", "[name of module]", commandName, "doNames")) {
+			if (taxa !=null && getModuleWindow() != null && ((TableWindow)getModuleWindow()).getTable()!=null){
+				TaxonNameAlterer tda= (TaxonNameAlterer)hireNamedEmployee(TaxonNameAlterer.class, arguments);
+				if (tda!=null) {
+					UndoReference undoReference = new UndoReference(new UndoInstructions(UndoInstructions.ALLTAXONNAMES,taxa, taxa), this);
+					boolean a = tda.alterTaxonNames(taxa, ((TableWindow)getModuleWindow()).getTable());
+					fireEmployee(tda);
+					if (a)
+						taxa.notifyListeners(this, new Notification(NAMES_CHANGED, undoReference));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns the taxa block shown", null, commandName, "getTaxa")) {
+			return taxa;
+		}
+		else if (checker.compare(this.getClass(), "Saves selected taxa as a TAXSET", null, commandName, "saveSelectedRows")) {
+			((TaxonListWindow)getModuleWindow()).saveSelectedRows();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+/* ======================================================================== */
+class TaxonListWindow extends ListWindow {
+	private Taxa taxa = null;
+	TaxaSelectCoordinator selectionCoordinator;
+	public TaxonListWindow (TaxonList ownerModule) {
+		super(ownerModule);
+
+		taxa = ownerModule.taxa;
+		if (taxa == null)
+			taxa = ownerModule.getProject().getTaxa(0);
+		ownerModule.hireAllEmployees(TaxaTableAssistantI.class); 
+		Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TaxaTableAssistantI) {
+				TaxaTableAssistantI init = (TaxaTableAssistantI)obj;
+				init.setTableAndTaxa(getTable(), taxa, true);
+			}
+		}
+		setIcon(MesquiteModule.getRootImageDirectoryPath() + "windowIcons/listT.gif");
+		ownerModule.hireAllEmployees(TaxaListAssistantI.class); 
+		enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TaxaListAssistantI) {
+				TaxaListAssistantI init = (TaxaListAssistantI)obj;
+				init.setTableAndTaxa(getTable(), taxa);
+			}
+		}
+		if (getTable() != null)
+			getTable().setDropDown(-1, -1, true);
+		selectionCoordinator = (TaxaSelectCoordinator)ownerModule.hireEmployee(TaxaSelectCoordinator.class, null);
+		if (selectionCoordinator!=null)
+			selectionCoordinator.setTableAndObject(getTable(), taxa, true);
+	}
+	public void focusInRow(int row){
+		try {
+			Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()){
+				Object obj = enumeration.nextElement();
+				if (obj instanceof TaxaListAssistantI) {
+					TaxaListAssistantI init = (TaxaListAssistantI)obj;
+					init.focusInRow(row);
+				}
+			}
+		}
+		catch (NullPointerException e){
+		}
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (taxa==null || StringUtil.blank(taxa.getName()) || "untitled".equalsIgnoreCase(taxa.getName()))
+			setTitle("Taxa"); 
+		else
+			setTitle("Taxa \"" + taxa.getName() + "\""); 
+	}
+	/*...............................................................................................................*/
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	public void setRowNameColor(Graphics g, int row){
+		//		g.setColor(Color.black);
+		if (taxa!=null ) {
+			long c = taxa.getAssociatedLong(colorNameRef, row);
+			if (MesquiteLong.isCombinable(c))
+				g.setColor(ColorDistribution.getStandardColor((int)c));
+		}
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s) || taxa == null)
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		String listData = taxa.searchData(s, commandResult);
+
+		if (!StringUtil.blank(listData))
+			return "<h2>Matches to search string: \"" + s + "\"</h2>" + listData;
+		else
+			return "<h2>No matches found (searched: \"" + s + "\")</h2>";
+	}
+	public void addRowsNotify(int first, int num) {
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, new int[] {first, num}));
+		//	this causes problems, as the taxa are added, AND numtaxa in CharacterData is incremented twice
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Selects taxa", "[number of taxon]", commandName, "selectTaxon")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+			if (which >= 0 && which < taxa.getNumTaxa()){
+				if (!table.isCellVisible(-1, which)){
+					table.setFocusedCell(-1, which, true);
+					table.repaintAll();
+				}
+				taxa.setSelected(which, !taxa.getSelected(which));
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows taxon", "[id of taxa block][number of taxon]", commandName, "showTaxon")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			long whichTaxaBlock = MesquiteInteger.fromString(arguments, pos);
+			if (whichTaxaBlock != taxa.getID())
+				return null;
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if (which >= 0 && which < taxa.getNumTaxa()){
+				if (!table.isCellVisible(-1, which)) {
+					table.setFocusedCell(-1, which, true);
+					table.repaintAll();
+				}
+			}
+			return null;
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return taxa;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof Taxa) {
+			if (taxa!=null)
+				taxa.removeListener(this);
+			taxa = (Taxa)obj;
+			getTable().setRowAssociable(taxa);
+			if (taxa!=null)
+				taxa.addListener(this);
+			Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()){
+				Object objc = enumeration.nextElement();
+				if (objc instanceof TaxaTableAssistantI) {
+					TaxaTableAssistantI init = (TaxaTableAssistantI)objc;
+					init.setTableAndTaxa(getTable(), taxa, true);
+				}
+			}
+			enumeration=ownerModule.getEmployeeVector().elements();
+			while (enumeration.hasMoreElements()){
+				Object objc = enumeration.nextElement();
+				if (objc instanceof TaxaListAssistantI) {
+					TaxaListAssistantI init = (TaxaListAssistantI)objc;
+					init.setTableAndTaxa(getTable(), taxa);
+				}
+			}
+			if (selectionCoordinator!=null)
+				selectionCoordinator.setTableAndObject(getTable(), taxa, true);
+			getTable().synchronizeRowSelection(taxa);
+			resetTitle();
+		}
+		super.setCurrentObject(obj);
+	}
+	/*.................................................................................................................*/
+	public void showSelectionPopup(Container cont, int x, int y) {
+		if (selectionCoordinator!=null)
+			selectionCoordinator.showPopUp(cont, x+5, y+5);
+	}
+	public String getItemTypeName(){
+		return "Taxon";
+	}
+	public void setRowName(int row, String name){
+		if (taxa!=null) {
+			String warning = taxa.checkNameLegality(row, name);
+			if (warning == null)
+				taxa.setTaxonName(row, name);
+			else
+				ownerModule.discreetAlert( warning);
+		}
+	}
+	public String getRowName(int row){
+		if (taxa!=null){
+			if (row>=0 && row<taxa.getNumTaxa())
+				return taxa.getTaxonName(row);
+			return null;
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	public void saveSelectedRows() {
+		if (table.anyRowSelected()) {
+			String nameOfTaxonSet = MesquiteString.queryString(this, "Name of taxon set", "Name of taxon set:", "Stored taxon set");
+			if (StringUtil.blank(nameOfTaxonSet))
+				return;
+			TaxaSelectionSet selectionSet= new TaxaSelectionSet(nameOfTaxonSet, taxa.getNumTaxa(), taxa);
+
+			taxa.storeSpecsSet(selectionSet, TaxaSelectionSet.class);
+
+			selectionSet.addToFile(taxa.getFile(), null, null);
+			selectionSet.setNexusBlockStored("SETS");
+			for (int ic= 0; ic< table.getNumRows(); ic++){
+				if (table.isRowSelected(ic)) { 
+					selectionSet.setSelected(ic, true);
+				}
+			}
+			taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa &&  (Taxa)obj ==taxa && ownerModule !=null)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+
+
+
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		if (obj instanceof Taxa && (Taxa)obj ==taxa) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				table.redrawRowNames();
+				setUndoer(undoReference);
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				table.offAllEditsDontRecord(); //1. 12
+				table.setNumRows(taxa.getNumTaxa());
+				table.synchronizeRowSelection(taxa);
+				table.repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.PARTS_ADDED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else {
+				table.repaintAll();
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+
+}
+
+
diff --git a/Source/mesquite/lists/TaxonListAnnotPanel/TaxonListAnnotPanel.java b/Source/mesquite/lists/TaxonListAnnotPanel/TaxonListAnnotPanel.java
new file mode 100644
index 0000000..cfaf34a
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListAnnotPanel/TaxonListAnnotPanel.java
@@ -0,0 +1,234 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonListAnnotPanel;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonListAnnotPanel extends TaxaListAssistantI  implements AnnotPanelOwner {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Annotation Panel module (list of taaa)";
+	}
+	public String getExplanation() {
+		return "Provides tools with which to attach notes (including images) to characters and show them.";
+	}
+	/*.................................................................................................................*/
+	Taxa taxa;
+	MesquiteTable table;
+	AnnotationsPanel panel = null;
+	String findString = null;
+	int findNumber = 0;
+	int currentColumn, currentRow, currentNoteNumber;
+	MesquiteSubmenuSpec annotMenu;
+	MesquiteBoolean showPanel;
+	MesquiteButton annotButton;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		showPanel = new MesquiteBoolean(false);
+		annotButton = new MesquiteButton(this, makeCommand("togglePanel",  this), null, true, MesquiteModule.getRootImageDirectoryPath()  + "annot.gif", 12, 16);
+		annotButton.setShowBackground(false);
+		annotButton.setButtonExplanation("Show/Hide Annotations Panel");
+		addCheckMenuItem(null, "Show Annotations Panel", makeCommand("togglePanel", this), showPanel);
+
+		annotMenu = addSubmenu(null, "Annotations");
+		MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Find Annotation", MesquiteModule.makeCommand("searchAnnotations", this));
+		mmi.setShortcut(KeyEvent.VK_3);
+		mmi = addItemToSubmenu(null, annotMenu, "Find Again", MesquiteModule.makeCommand("searchAgain", this));
+		mmi.setShortcut(KeyEvent.VK_8);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public MesquiteModule getModule(){
+		return this;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		this.table = table;
+		this.taxa = taxa;
+		setPanel();
+	}
+	/*.................................................................................................................*/
+	void setPanel(){
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof TableWindow){
+			((TableWindow)f).addControlButton(annotButton);
+			if (showPanel.getValue()){
+				if (panel == null) {
+					panel = new AnnotationsPanel(this);
+					addItemToSubmenu(null, annotMenu, "-", null);
+					MesquiteMenuItemSpec mmi = addItemToSubmenu(null, annotMenu, "Make Item Label", MesquiteModule.makeCommand("makeItemLabel", panel));
+					mmi.setShortcut(KeyEvent.VK_L);
+					addItemToSubmenu(null, annotMenu, "Recover Offscreen Labels", MesquiteModule.makeCommand("recoverLostLabels", panel));
+					resetContainingMenuBar();
+				}
+				((TableWindow)f).addSidePanel(panel, 300);
+				panel.setVisible(true);
+
+			}
+			else {
+				if (panel != null)
+					((TableWindow)f).removeSidePanel(panel);
+			}
+
+		}
+	}
+	public boolean hasDisplayModifications(){
+		return false;
+	}
+	public void panelGoAway(Panel p){
+		showPanel.setValue(false);
+		setPanel();
+	}
+	/*.................................................................................................................*/
+	void showNote(AttachedNotesVector aim, int row, int noteNumber){
+		if (row<-1 || taxa == null || panel == null || row>= taxa.getNumTaxa())
+			return;
+		currentRow = row;
+		String s = null;
+		String loc = null;
+		if (row >= 0){
+			s = "taxon \"" + taxa.getTaxonName(row) + "\"";
+			loc = Integer.toString(row+1);
+		}
+		if (!panel.isVisible()){
+			showPanel.setValue(true);
+			setPanel();
+		}
+		panel.setNotes(aim, s, loc, -1, row, noteNumber);
+	}
+	void showNote(int row, int noteNumber){
+		if ( row < -1 || taxa == null || panel == null || row>= taxa.getNumTaxa())
+			return;
+		AttachedNotesVector hL = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, row);
+		showNote(hL, row, noteNumber);
+	}
+	boolean findAndShowNote(String searchString, int i){
+		int count = 0;
+		//search characters
+		for (int ic = 0; ic<taxa.getNumTaxa(); ic++) {
+			AttachedNotesVector hL = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, ic);
+			if (hL != null){
+				for (int noteNum = 0; noteNum<hL.getNumNotes(); noteNum++){
+					AttachedNote note = hL.getAttachedNote(noteNum);
+					if (note.containsString(searchString)){
+						if (count == i) {
+							showNote(ic,  noteNum);
+							return true;
+						}
+						count++;
+					}
+				}
+			}
+		}
+		MesquiteMessage.println("There are no more occurrences of \"" + searchString + "\"");
+		MesquiteMessage.beep();
+		return false;
+
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		//removePanel;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("togglePanel " + showPanel.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	NameReference notesNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not the annotations panel is shown", "[on = shown; off]", commandName, "togglePanel")) {
+			showPanel.toggleValue(parser.getFirstToken(arguments));
+			setPanel();
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAnnotations")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			String temp = MesquiteString.queryString(containerOfModule(), "Search annotations", "Search annotations of cells of matrix to find the following string.  Comments, references and labels of images will be searched.", findString, 2);
+			if (StringUtil.blank(temp)) {
+				return null;
+			}
+			findString = temp;
+			findNumber = 0;
+			if (!findAndShowNote(findString, findNumber))				findNumber = 0;
+			else
+				findNumber = 1;
+
+		}
+		else if (checker.compare(this.getClass(),  "Searches for text within notes", null, commandName, "searchAgain")) {
+			if (MesquiteThread.isScripting()) //todo: should support argument passed
+				return null;
+			if (StringUtil.blank(findString))
+				return null;
+			if (!findAndShowNote(findString, findNumber))				findNumber = 0;
+			else
+				findNumber++;
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public AttachedNotesVector makeNotesVector(AnnotationsPanel w){
+		//attach image to window w
+		int row = currentRow;
+		AttachedNotesVector aiv  = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, row);
+		if (aiv == null)
+			aiv = new AttachedNotesVector(taxa);
+		taxa.setAssociatedObject(notesNameRef, row, aiv);
+		return aiv;
+	}
+	public void chooseAndAttachImage(AttachedNote hL, boolean local){
+		if (hL == null)
+			return;
+		//attach image to window w
+
+		hL.attachImage(this, local);
+		showNote( currentRow, currentNoteNumber);
+		if (table != null)
+			table.repaintAll();
+	}
+	/*.................................................................................................................*/
+	public void focusInRow(int row){
+		if (taxa == null)
+			return;
+		if (panel == null || panel.isVisible())
+			showNote(row, 0);
+		return;
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+
+}
diff --git a/Source/mesquite/lists/TaxonListArchivedName/TaxonListArchivedName.java b/Source/mesquite/lists/TaxonListArchivedName/TaxonListArchivedName.java
new file mode 100644
index 0000000..c24b447
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListArchivedName/TaxonListArchivedName.java
@@ -0,0 +1,303 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonListArchivedName;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.ProbabilityModelSet;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonListArchivedName extends TaxonListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Alternative Names";
+	}
+	public String getExplanation() {
+		return "Lists the alternative names for the taxon." ;
+	}
+	/*.................................................................................................................*/
+	Taxa taxa;
+	MesquiteTable table=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		if (this.taxa != null)
+			this.taxa.removeListener(this);
+		this.taxa = taxa;
+		if (this.taxa != null)
+			this.taxa.addListener(this);
+		this.table = table;
+		deleteAllMenuItems();
+		addMenuItem("Trade Taxon Names with Alternatives", makeCommand("trade",  this));
+		addMenuItem("Replace Alternatives by Taxon Names", makeCommand("copyToAlt",  this));
+		addMenuItem("Replace Taxon Names by Alternatives", makeCommand("replaceByAlt",  this));
+		addMenuItem("Replace Alternatives by List in File...", makeCommand("replaceByFileList",  this));
+		addMenuItem("-", null);
+		addMenuItem("Store Alternatives...", makeCommand("storeCurrent",  this));
+		addMenuItem("Replace Stored Alternatives...", makeCommand("replaceWithCurrent",  this));
+		if (taxa !=null){
+			taxa.prepareSpecsSetVector(TaxaStringsSet.class, "Alternative Names");
+			addSubmenu(null, "Load Alternatives", makeCommand("loadToCurrent",  this), taxa.getSpecSetsVector(TaxaStringsSet.class));
+		}
+		
+	}
+	
+	/*.................................................................................................................*/
+	private Object getAlternativesFromFile (int numTaxa) {
+
+		MesquiteString directoryName = new MesquiteString("");
+		MesquiteString fileName = new MesquiteString("");
+		String filePath = MesquiteFile.openFileDialog("Choose file containing list of taxa.",  directoryName,  fileName);
+		if (filePath != null) {
+			MesquiteFile file =MesquiteFile.open(true, filePath);
+			if (file!=null && (file.isLocal() && file.existingLength()<=0)) { 
+				alert("Error: File is empty.");
+				return null;
+			}
+
+			if (file.openReading()) {
+				TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+				if (part == null){
+					part= new TaxaStringsSet("Alternative Naming", taxa.getNumTaxa(), taxa);
+					part.setTypeName("Alternative Names");
+					part.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+					taxa.setCurrentSpecsSet(part, TaxaStringsSet.class);
+				}
+				if (part != null) {
+					String line="  ";
+					int it = 0;
+					while (line!=null && it<numTaxa) {
+						line = file.readLine();
+						if (StringUtil.notEmpty(line)){
+							part.setProperty(line, it);
+							it++;
+						}
+					}
+					return part;
+				}
+			}
+		}
+		return null;
+
+	}
+
+	
+	MesquiteInteger pos = new MesquiteInteger(0);
+	
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Copies the current names to the alternatives", null, commandName, "copyToAlt")) {
+			if (taxa !=null) {
+				TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+				if (part == null){
+					//create current specs set
+					part= new TaxaStringsSet("Alternative Naming", taxa.getNumTaxa(), taxa);
+					part.setTypeName("Alternative Names");
+					part.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+					taxa.setCurrentSpecsSet(part, TaxaStringsSet.class);
+				}
+				for (int it = 0; it< taxa.getNumTaxa(); it++){
+					if (!taxa.anySelected() || taxa.getSelected(it))
+						part.setProperty(taxa.getTaxonName(it), it);
+				}
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+				if (ssv != null)
+					ssv.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replaces the current names by the alternatives", null, commandName, "replaceByAlt")) {
+			if (taxa !=null) {
+				TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+				if (part == null){
+					discreetAlert("You need to load or make an alternative naming scheme before trading it with the current taxon names.  You can enter alternative names in the \"Alternative Names\" column, "
+							+ "or you can Replace Alternatives by Taxon Names and then edit the alternatives");
+					return null;
+				}
+				for (int it = 0; it< taxa.getNumTaxa(); it++) {
+					if (!taxa.anySelected() || taxa.getSelected(it)){
+					String alt = (String)part.getProperty(it);
+					if (!StringUtil.blank(alt))
+						taxa.setTaxonName(it, alt, false);
+					}
+				}
+				taxa.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replaces the alternatives with those in a list read in from a file", null, commandName, "replaceByFileList")) {
+			if (taxa !=null && !MesquiteThread.isScripting()) {
+					Object obj = getAlternativesFromFile(taxa.getNumTaxa());
+					if (obj!=null)
+						taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???			
+				}
+		}
+		else if (checker.compare(this.getClass(), "Trades the current names with the alternatives", null, commandName, "trade")) {
+			if (taxa !=null) {
+				TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+				if (part == null){
+					discreetAlert("You need to load or make an alternative naming scheme before trading it with the current taxon names.  You can enter alternative names in the \"Alternative Names\" column, "
+							+ "or you can Replace Alternatives by Taxon Names and then edit the alternatives");
+					return null;
+				}
+				for (int it = 0; it< taxa.getNumTaxa(); it++) {
+					if (!taxa.anySelected() || taxa.getSelected(it)){
+					String alt = (String)part.getProperty(it);
+					part.setProperty(taxa.getTaxonName(it), it);
+					if (!StringUtil.blank(alt))
+						taxa.setTaxonName(it, alt, false);
+					}
+					
+				}
+				taxa.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+				if (ssv != null)
+					ssv.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Stores the current taxa naming as a ALTTAXNAMES", null, commandName, "storeCurrent")) {
+			if (taxa!=null){
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					TaxaStringsSet partition= new TaxaStringsSet("Alternative Naming", taxa.getNumTaxa(), taxa);
+					partition.setTypeName("Alternative Names");
+					partition.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+					taxa.setCurrentSpecsSet(partition, TaxaStringsSet.class);
+					ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+					s.setName(ssv.getUniqueName("Alternative Naming"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name for alternative naming scheme to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+			//return ((ListWindow)getModuleWindow()).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Replaces a stored taxa naming by the current one", null, commandName, "replaceWithCurrent")) {
+			if (taxa!=null){
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored naming", "Choose alternative naming scheme to replace by current alternative", MesquiteString.helpString,ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+			//return ((ListWindow)getModuleWindow()).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored taxa naming scheme to be the current alternative", "[number of naming scheme to load]", commandName, "loadToCurrent")) {
+			if (taxa !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaStringsSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Alternative Names";
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int row){
+		return true;
+	}
+	/*...............................................................................................................*/
+	/** for those permitting editing, indicates user has edited to incoming string.*/
+	public void setString(int row, String s){
+		if (taxa!=null) {
+			TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+			if (part == null){
+//				create current specs set
+				part= new TaxaStringsSet("Alternative Naming", taxa.getNumTaxa(), taxa);
+				part.setTypeName("Alternative Names");
+				part.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaStringsSet.class));
+				taxa.setCurrentSpecsSet(part, TaxaStringsSet.class);
+				}
+			if (part != null)
+			part.setProperty(s, row);
+		}
+	}
+	public String getStringForTaxon(int ic){
+		if (taxa!=null) {
+			TaxaStringsSet part = (TaxaStringsSet)taxa.getCurrentSpecsSet(TaxaStringsSet.class);
+			if (part==null)
+				return "-";
+			String tg = (String)part.getProperty(ic);
+			if (tg==null)
+				return "-";
+			return tg;
+		}
+		return "?";
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+
+	public String getWidestString(){
+		return "88888888888888888  ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TaxonListCurrPartition/TaxonListCurrPartition.java b/Source/mesquite/lists/TaxonListCurrPartition/TaxonListCurrPartition.java
new file mode 100644
index 0000000..ae42017
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListCurrPartition/TaxonListCurrPartition.java
@@ -0,0 +1,349 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonListCurrPartition;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonListCurrPartition extends TaxonListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Group Membership (taxa)";
+	}
+	public String getExplanation() {
+		return "Lists and allows changes to group membership in the current partition of taxa, for List of Taxa window." ;
+	}
+	/*.................................................................................................................*/
+	Taxa taxa;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss, mEGC;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine, nNG, mLine2, ms2;
+	TaxaGroupVector groups;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+		groups.addListener(this);
+		return true;
+	}
+	public void endJob(){
+		if (taxa != null)
+			taxa.removeListener(this);
+		if (groups != null)
+			groups.removeListener(this);
+		super.endJob();
+	}
+	private void setGroup(TaxaGroup group, String arguments){
+		if (table !=null && taxa!=null) {
+			boolean changed=false;
+			String name = parser.getFirstToken(arguments);
+			if (group == null && StringUtil.blank(name))
+				return;
+			TaxaPartition partition = (TaxaPartition) taxa.getCurrentSpecsSet(TaxaPartition.class);
+			if (partition==null){
+				partition= new TaxaPartition("Partition", taxa.getNumTaxa(), null, taxa);
+				partition.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaPartition.class));
+				taxa.setCurrentSpecsSet(partition, TaxaPartition.class);
+			}
+			if (group == null){
+				TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+				Object obj = groups.getElement(name);
+				group = (TaxaGroup)obj;
+			}
+
+			if (group != null) {
+				if (partition != null) {
+					if (employer!=null && employer instanceof ListModule) {
+						int c = ((ListModule)employer).getMyColumn(this);
+						for (int i=0; i<taxa.getNumTaxa(); i++) {
+							if (table.isCellSelectedAnyWay(c, i)) {
+								partition.setProperty(group, i);
+								if (!changed)
+									outputInvalid();
+								changed = true;
+							}
+						}
+					}
+				}
+				if (changed)
+					taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				parametersChanged();
+			}
+		}
+	}
+	private void removeGroupDesigation(){
+		if (table !=null && taxa!=null) {
+			boolean changed=false;
+			TaxaPartition partition = (TaxaPartition) taxa.getCurrentSpecsSet(TaxaPartition.class);
+			if (partition!=null){
+				if (employer!=null && employer instanceof ListModule) {
+					int c = ((ListModule)employer).getMyColumn(this);
+					for (int i=0; i<taxa.getNumTaxa(); i++) {
+						if (table.isCellSelectedAnyWay(c, i)) {
+							partition.setProperty(null, i);
+							if (!changed)
+								outputInvalid();
+							changed = true;
+						}
+					}
+				}
+
+				if (changed)
+					taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							parametersChanged();
+
+			}
+		}
+	}
+	
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets to which group a taxon belongs in the current taxa partition", "[name of group]", commandName, "setPartition")) {
+			setGroup(null, arguments);
+		}
+		else if (checker.compare(this.getClass(), "Edits the name, color, and symbol of a taxon group label", "[name of group]", commandName, "editGroup")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name))
+				return null;
+			String num = parser.getNextToken();
+			int i = MesquiteInteger.fromString(num);
+			TaxaGroupVector groups = (TaxaGroupVector)getProject().getFileElement(TaxaGroupVector.class, 0);
+			Object obj;
+			if (MesquiteInteger.isCombinable(i) && i< groups.size())
+				obj = groups.elementAt(i);
+			else
+				obj = groups.getElement(name);
+			if (obj != null) {
+				TaxaGroup group = (TaxaGroup)obj;
+
+				GroupDialog d = new GroupDialog(getProject(),containerOfModule(), "Edit Taxon Group", group.getName(), group.getColor(), group.getSymbol(),group.supportsSymbols());
+				d.completeAndShowDialog();
+				name = d.getName();
+				boolean ok = d.query()==0;
+				Color c = d.getColor();
+				MesquiteSymbol symbol = d.getSymbol();
+				d.dispose();
+				if (!ok)
+					return null;
+
+
+				if (!StringUtil.blank(name)) {
+					group.setName(name);
+					group.setColor(c);
+					if (symbol!=null)
+						group.setSymbol(symbol);
+					taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+					group.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+				}
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Creates a new group for use in taxon partitions", null, commandName, "newGroup")) {
+			TaxaGroup group= TaxaListPartitionUtil.createNewTaxonGroup(this, taxa.getFile());
+			if (group!=null)
+				setGroup(group, group.getName());
+			return group;
+		}
+		else if (checker.compare(this.getClass(), "Stores the current taxa partition as a TAXAPARTITION", null, commandName, "storeCurrent")) {
+			if (taxa!=null){
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					TaxaPartition partition= new TaxaPartition("Partition", taxa.getNumTaxa(), null, taxa);
+					partition.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaPartition.class));
+					taxa.setCurrentSpecsSet(partition, TaxaPartition.class);
+					ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(taxa.getFile(), getProject(), findElementManager(TaxaPartition.class));
+					s.setName(ssv.getUniqueName("Partition"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of taxa partition to be stored", s.getName());
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+			//return ((ListWindow)getModuleWindow()).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Replaces a stored taxa partition by the current one", null, commandName, "replaceWithCurrent")) {
+			if (taxa!=null){
+				SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored partition", "Choose stored partition to replace by current partition", MesquiteString.helpString,ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+			//return ((ListWindow)getModuleWindow()).getCurrentObject();
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored taxa partition to be the current one", "[number of partition to load]", commandName, "loadToCurrent")) {
+			if (taxa !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = taxa.getSpecSetsVector(TaxaPartition.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes the group designation from the selected taxa", null, commandName, "removeGroup")) {
+			removeGroupDesigation();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		/* hire employees here */
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mLine2);
+		deleteMenuItem(mStc);
+		deleteMenuItem(ms2);
+		deleteMenuItem(mEGC);
+		deleteMenuItem(nNG);
+		mss = addSubmenu(null, "Set Group", makeCommand("setPartition", this));
+		mss.setList((StringLister)getProject().getFileElement(TaxaGroupVector.class, 0));
+
+		ms2 = addMenuItem("Remove Group Designation", makeCommand("removeGroup",  this));
+
+		mLine2 = addMenuItem("-",null);
+		nNG = addMenuItem("New Group...", makeCommand("newGroup",  this));
+		mEGC = addSubmenu(null, "Edit Group...", makeCommand("editGroup", this));
+		mEGC.setList((StringLister)getProject().getFileElement(TaxaGroupVector.class, 0));
+
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current partition...", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored partition by current", makeCommand("replaceWithCurrent",  this));
+		if (taxa !=null) {
+			mStc = addSubmenu(null, "Load partition", makeCommand("loadToCurrent",  this), taxa.getSpecSetsVector(TaxaPartition.class));
+		}
+		if (taxa != this.taxa){
+			if (this.taxa != null)
+				this.taxa.removeListener(this);
+			taxa.addListener(this);
+		}
+		this.taxa = taxa;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (caller == this)
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Group";
+	}
+	public String getStringForTaxon(int ic){
+		if (taxa!=null) {
+			TaxaPartition part = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+			if (part==null)
+				return "?";
+			TaxaGroup tg = part.getTaxaGroup(ic);
+			if (tg==null)
+				return "?";
+			return tg.getName();
+		}
+		return "?";
+	}
+	public boolean useString(int ic){
+		return false;
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+		if (taxa==null || g==null)
+			return;
+		TaxaPartition part = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+		Color c = g.getColor();
+		MesquiteSymbol symbol = null;
+		boolean colored = false;
+		if (part!=null) {
+			TaxaGroup tg = part.getTaxaGroup(ic);
+			if (tg!=null){
+				Color cT = tg.getColor();
+				if (cT!=null){
+					g.setColor(cT);
+					g.fillRect(x+1,y+1,w-1,h-1);
+					colored = true;
+				}
+				symbol = tg.getSymbol();
+			}
+		}
+		if (!colored){ 
+			if (selected)
+				g.setColor(Color.black);
+			else
+				g.setColor(Color.white);
+			g.fillRect(x+1,y+1,w-1,h-1);
+		}
+		if (symbol!=null) {
+			symbol.drawSymbol(g,x+w-h/2,y+h/2,w-3,h/2-3,true);
+		}
+
+		String s = getStringForRow(ic);
+		if (s!=null){
+			FontMetrics fm = g.getFontMetrics(g.getFont());
+			if (fm==null)
+				return;
+			int sw = fm.stringWidth(s);
+			int sh = fm.getMaxAscent()+ fm.getMaxDescent();
+			if (selected)
+				g.setColor(Color.white);
+			else
+				g.setColor(Color.black);
+			g.drawString(s, x+(w-sw)/2, y+h-(h-sh)/2);
+			if (c!=null) g.setColor(c);
+		}
+
+	}
+
+	public String getWidestString(){
+		return "88888888888  ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/lists/TaxonListShowAllHasData/TaxonListShowAllHasData.java b/Source/mesquite/lists/TaxonListShowAllHasData/TaxonListShowAllHasData.java
new file mode 100644
index 0000000..9058e18
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListShowAllHasData/TaxonListShowAllHasData.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */
package mesquite.lists.TaxonListShowAllHasData;
/*~~  */

import mesquite.lists.lib.*;
+
+import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
+
+import mesquite.lib.*;
import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
import mesquite.lib.table.*;

/* ======================================================================== */
public class TaxonListShowAllHasData extends TaxaListAssistantI  {
	Taxa taxa;
	MesquiteTable table;
	public String getName() {
		return "Show Columns for All Matrices";
	}
	public String getExplanation() {
		return "Shows the Has Data column for all matrices.";
	}
	/*.................................................................................................................*/
	public int getVersionOfFirstRelease(){
		return 304;  
	}
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		addMenuItem("Show Columns for All Matrices", new MesquiteCommand("showAll", this));
		return true;
	}
+	
+	void makeColumn(Puppeteer puppeteer, ListModule listModule, CharacterData data){
+		String commands = "newAssistant #TaxaListHasData; " +
+				"tell It; getMatrixSource #mesquite.charMatrices.CharMatrixCoordIndep.CharMatrixCoordIndep; " +
+				"tell It; setCharacterSource #mesquite.charMatrices.StoredMatrices.StoredMatrices; tell It; setDataSet " + getProject().getCharMatrixReferenceExternal(data) + "; " +
+				"endTell; endTell; endTell;";
+		puppeteer.execute(listModule,  commands, new MesquiteInteger(0), null, false);
+		
+	}
	/*.................................................................................................................*/
	/** A request for the MesquiteModule to perform a command.  It is passed two strings, the name of the command and the arguments.
	This should be overridden by any module that wants to respond to a command.*/
	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
		if (checker.compare(MesquiteModule.class, null, null, commandName, "showAll")) {
+			if (taxa == null)
+				return null;
+			int numMatrices = getProject().getNumberCharMatrices(taxa);
+			if (numMatrices<1)
+				return null;
+			Vector datas = new Vector();
+			for (int i = 0; i<numMatrices; i++){
+				CharacterData data = getProject().getCharacterMatrix(taxa, i);
+					datas.addElement(data);
+			}
			if (getEmployer() instanceof ListModule){
+				ListModule listModule = (ListModule)getEmployer();
+				Vector v = listModule.getAssistants();
+				for (int k = 0; k< v.size(); k++){
+					ListAssistant a = (ListAssistant)v.elementAt(k);
+					if (a instanceof mesquite.molec.TaxaListHasData.TaxaListHasData){
+						mesquite.molec.TaxaListHasData.TaxaListHasData tLHD = (mesquite.molec.TaxaListHasData.TaxaListHasData)a;
+						CharacterData data = tLHD.getCharacterData();
+						datas.removeElement(data);
+					}
+				}
+				Puppeteer puppeteer = new Puppeteer(this);
+				CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+				CommandRecord cRecord = new CommandRecord(true);
+				MesquiteThread.setCurrentCommandRecord(cRecord);
+				//at this point the vector should include only the ones not being shown.
+				for (int i = 0; i<datas.size(); i++)
+					makeColumn(puppeteer, listModule, (CharacterData)datas.elementAt(i));
+			
+				MesquiteThread.setCurrentCommandRecord(prevR);
+			}
		}
		else
			return  super.doCommand(commandName, arguments, checker);
		return null;
	}
	/*.................................................................................................................*/
	public boolean isSubstantive(){
		return false;
	}
	/*.................................................................................................................*/
	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
		this.table = table;
		this.taxa = taxa;
	}

}
\ No newline at end of file
diff --git a/Source/mesquite/lists/TaxonListVoucherCode/TaxonListVoucherCode.java b/Source/mesquite/lists/TaxonListVoucherCode/TaxonListVoucherCode.java
new file mode 100644
index 0000000..09c79f8
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListVoucherCode/TaxonListVoucherCode.java
@@ -0,0 +1 @@
+/* Mesquite  source code.  Copyright 2005 and onward, David Maddison and Wayne Maddison.
Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */

package mesquite.lists.TaxonListVoucherCode;
/*~~  */

import mesquite.lists.lib.*;
import mesquite.lib.characters.*;
import mesquite.lib.*;
import mesquite.lib.table.*;

/* ======================================================================== */
public class TaxonListVoucherCode extends TaxonListAssistant {
	Taxa taxa;
	MesquiteTable table=null;
	OTUIDCodeInfoCoord voucherInfoTask;
	MesquiteMenuItemSpec msSetID, fd, wpmMI;
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
		//temporary
		voucherInfoTask = (OTUIDCodeInfoCoord)hireEmployee(OTUIDCodeInfoCoord.class, null);
		return true;
	}
	//temporary
	public String getExplanationForRow(int ic){
		if (taxa!=null && voucherInfoTask != null) {
			VoucherInfoFromOTUIDDB vi= voucherInfoTask.getVoucherInfo((String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherDBRef, ic), (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, ic));
			if (vi != null)
				return vi.toGenBankString();
		}
		return null;
	}
	
	
	/*.................................................................................................................*/
	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
		if (this.taxa != null)
			this.taxa.removeListener(this);
		this.taxa = taxa;
		if (this.taxa != null)
			this.taxa.addListener(this);
		this.table = table;
		deleteMenuItem(msSetID);
		msSetID = addMenuItem("Get OTU ID code from last token of taxon name", makeCommand("setIDFromName", this));
		fd = addMenuItem("Select taxa with duplicate IDs", makeCommand("selectDuplicates", this));
//		wpmMI = addMenuItem("Find Voucher ID in taxon name (WPM Lab Only)", makeCommand("findWPMID", this));
}
	/*.................................................................................................................*/
	public void dispose() {
		super.dispose();
		if (taxa!=null)
			taxa.removeListener(this);
	}
	/*.................................................................................................................*/
	private void setIDFromTaxonName(){
		if (table !=null && taxa!=null) {
			boolean changed=false;
			String id = "";
			Parser parser = new Parser();
			boolean anySelected = table.anyCellSelectedAnyWay();
			parser.addToDefaultPunctuationString(".");
			if (employer!=null && employer instanceof ListModule) {
				int c = ((ListModule)employer).getMyColumn(this);
				for (int i=0; i<taxa.getNumTaxa(); i++) {
					if (!anySelected || table.isCellSelectedAnyWay(c, i)) {
						id = taxa.getName(i);
						
						parser.setString(id);
						id = parser.getLastToken();
						if (!StringUtil.blank(id)){
							taxa.setAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, i, id);
							if (!changed)
								outputInvalid();
							changed = true;
						}
					}
				}
			}

//			if (changed)
//				data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
			outputInvalid();
			parametersChanged();

		}
	}
	/*.................................................................................................................*/
	private void selectDuplicates(){
		if (table !=null && taxa!=null) {
			boolean changed=false;
			if (employer!=null && employer instanceof ListModule) {
				int c = ((ListModule)employer).getMyColumn(this);
				for (int i=0; i<taxa.getNumTaxa(); i++) {
					String target = (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, i);
					
					if (!StringUtil.blank(target))
						for (int k=i+1; k<taxa.getNumTaxa(); k++) {
						String id = (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, k);
						
						if (!StringUtil.blank(id)) {
							if (id.equalsIgnoreCase(target)){
								if (!taxa.getSelected(i))
									taxa.setSelected(i, true);
								if (!taxa.getSelected(k))
									taxa.setSelected(k, true);
								changed = true;
							}
							
						}
					}
				}
			}

		if (changed)
				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
			outputInvalid();
			parametersChanged();

		}
	}
	/*.................................................................................................................*/
	private void findIDInTaxonNameWPM(){
		if (table !=null && taxa!=null) {
			boolean changed=false;
			if (employer!=null && employer instanceof ListModule) {
				int c = ((ListModule)employer).getMyColumn(this);
				for (int i=0; i<taxa.getNumTaxa(); i++) {
					if (table.isCellSelectedAnyWay(c, i)) {
						String id = "";
						String name = taxa.getName(i);
						if (name.indexOf("JXZ") >=0)
							id = name.substring(name.indexOf("JXZ"), name.indexOf("JXZ")+6);
						else if (name.indexOf("MRB") >=0)
							id = name.substring(name.indexOf("MRB"), name.indexOf("MRB")+6);
						else if (name.indexOf(".DNA") >=0)
							id = name.substring(name.indexOf(".DNA")+1, name.indexOf(".DNA")+8);
						else if (name.indexOf(".d") >=0)
							id = name.substring(name.indexOf(".d")+1, name.indexOf(".d")+5);
						else if (name.indexOf(".s") >=0)
							id = name.substring(name.indexOf(".s")+1, name.indexOf(".s")+5);
						else if (name.indexOf(".S") >=0){
							int st = name.indexOf(".S");
							int lg = name.length();
							if (st+5<= lg)
								id = name.substring(name.indexOf(".S")+1, name.indexOf(".S")+5);
							else if (st+4<= lg)
								id = name.substring(name.indexOf(".S")+1, name.indexOf(".S")+4);
							else if (st+3<= lg)
								id = name.substring(name.indexOf(".S")+1, name.indexOf(".S")+3);
							else if (st+2<= lg)
								id = name.substring(name.indexOf(".S")+1, name.indexOf(".S")+2);
						}
						else if (name.indexOf(".GR") >=0)
							id = name.substring(name.indexOf(".GR")+1, name.indexOf(".GR")+6);
						else if (name.indexOf("d0") >=0)
							id = name.substring(name.indexOf("d0"), name.indexOf("d0")+4);
						else if (name.indexOf("d1") >=0)
							id = name.substring(name.indexOf("d1"), name.indexOf("d1")+4);
						else if (name.indexOf("d2") >=0)
							id = name.substring(name.indexOf("d2"), name.indexOf("d2")+4);
						else if (name.indexOf("d3") >=0)
							id = name.substring(name.indexOf("d3"), name.indexOf("d3")+4);
						else if (name.indexOf("d4") >=0)
							id = name.substring(name.indexOf("d4"), name.indexOf("d4")+4);
						
						if (!StringUtil.blank(id)){
							taxa.setAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, i, id);
							if (!changed)
								outputInvalid();
							changed = true;
						}
					}
				}
			}

//			if (changed)
//				data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
			outputInvalid();
			parametersChanged();

		}
	}
	/*.................................................................................................................*/
	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
		if (checker.compare(this.getClass(), "Sets the OTU ID code to be the last token of the taxon name", null, commandName, "setIDFromName")) {
			setIDFromTaxonName();	
		}
		else if (checker.compare(this.getClass(), "Finds the OTU ID code in the taxon name (WPM lab only)", null, commandName, "findWPMID")) {
			findIDInTaxonNameWPM();	
		}
		else if (checker.compare(this.getClass(), "Selects taxa with duplicate Names", null, commandName, "selectDuplicates")) {
			selectDuplicates();	
		}
		else
			return  super.doCommand(commandName, arguments, checker);
		return null;
	}
	public void changed(Object caller, Object obj, Notification notification){
		outputInvalid();
		parametersChanged(notification);
	}
	public String getTitle() {
		return "OTU ID code";
	}
	public String getStringForTaxon(int ic){
		
		if (taxa!=null) {
			Object n = (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, ic);
			if (n !=null)
				return ((String)n);
			
		}
		return "-";
	}
	/*...............................................................................................................*/
	/** returns whether or not a cell of table is editable.*/
	public boolean isCellEditable(int row){
		return true;
	}
	/*...............................................................................................................*/
	/** for those permitting editing, indicates user has edited to incoming string.*/
	public void setString(int row, String s){
		if (taxa!=null) {
			taxa.setAssociatedObject(VoucherInfoFromOTUIDDB.voucherCodeRef, row, s);
		}
		
	}
	public boolean useString(int ic){
		return true;
	}
	
	public String getWidestString(){
		return "88888888888888888  ";
	}
	/*.................................................................................................................*/
	public String getName() {
		return "OTU ID Code";
	}
	/*.................................................................................................................*/
	public boolean isPrerelease(){
		return false;  
	}
	/*.................................................................................................................*/
	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
	public int getVersionOfFirstRelease(){
		return -1;  
	}
	/*.................................................................................................................*/
	/** returns whether this module is requesting to appear as a primary choice */
	public boolean requestPrimaryChoice(){
		return true;  
	}
	
	/*.................................................................................................................*/
	/** returns an explanation of what the module does.*/
	public String getExplanation() {
		return "Lists the OTU ID code for a taxon." ;
	}
}
\ No newline at end of file
diff --git a/Source/mesquite/lists/TaxonListVoucherDB/TaxonListVoucherDB.java b/Source/mesquite/lists/TaxonListVoucherDB/TaxonListVoucherDB.java
new file mode 100644
index 0000000..5739edd
--- /dev/null
+++ b/Source/mesquite/lists/TaxonListVoucherDB/TaxonListVoucherDB.java
@@ -0,0 +1 @@
+/* Mesquite  source code.  Copyright 2005 and onward, David Maddison and Wayne Maddison.

Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
 */

package mesquite.lists.TaxonListVoucherDB;
/*~~  */

import mesquite.lists.lib.*;
import mesquite.lib.*;
import mesquite.lib.table.*;

/* ======================================================================== */
public class TaxonListVoucherDB extends TaxonListAssistant {
	Taxa taxa;
	MesquiteTable table=null;
	MesquiteMenuItemSpec msbrowseDB;
	MesquiteMenuItemSpec msSetDB;
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
		return true;
  	 }
 
	/*.................................................................................................................*/
	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
		if (this.taxa != null)
			this.taxa.removeListener(this);
		this.taxa = taxa;
		if (this.taxa != null)
			this.taxa.addListener(this);
		this.table = table;
		deleteMenuItem(msbrowseDB);
		msbrowseDB = addMenuItem("Browse for OTU ID code database...", makeCommand("browseDB", this));
		deleteMenuItem(msSetDB);
		msSetDB = addMenuItem("Set OTU ID code database...", makeCommand("setDB", this));
	}
	/*.................................................................................................................*/
	public void dispose() {
		super.dispose();
		if (taxa!=null)
			taxa.removeListener(this);
	}
	/*.................................................................................................................*/
	private void setDBURL(String arguments){
		if (table !=null && taxa!=null) {
			boolean changed=false;
			String path = arguments; //parser.getFirstToken(arguments);
			if (StringUtil.blank(path))
				return;
			if (employer!=null && employer instanceof ListModule) {
				int c = ((ListModule)employer).getMyColumn(this);
				for (int i=0; i<taxa.getNumTaxa(); i++) {
					if (table.isCellSelectedAnyWay(c, i)) {
						taxa.setAssociatedObject(VoucherInfoFromOTUIDDB.voucherDBRef, i, path);
						if (!changed)
							outputInvalid();
						changed = true;
					}
				}
			}

//			if (changed)
//				data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
			outputInvalid();
			parametersChanged();

		}
	}
	/*.................................................................................................................*/
	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
		if (checker.compare(this.getClass(), "Sets the OTU ID code database to the one you choose by browsing", null, commandName, "browseDB")) {
			MesquiteString directoryName = new MesquiteString();
			MesquiteString fileName = new MesquiteString();
			String urlString = MesquiteFile.openFileDialog("Choose OTU ID code database", directoryName, fileName);
			if (StringUtil.blank(urlString))
				return null;
			setDBURL("tdt:"+ urlString);	
		}
		else if (checker.compare(this.getClass(), "Sets the OTU ID code database to the one you enter", null, commandName, "setDB")) {
			if (table!=null){
				String urlString = MesquiteString.queryString(containerOfModule(), "VoucherDB", "URL of OTU ID code database:", "");
				if (StringUtil.blank(urlString))
					return null;
				setDBURL(urlString);	
			}
		}
		else
			return  super.doCommand(commandName, arguments, checker);
		return null;
	}
	public void changed(Object caller, Object obj, Notification notification){
		outputInvalid();
		parametersChanged(notification);
	}
	public String getTitle() {
		return "OTU ID code DB";
	}
	public String getStringForTaxon(int ic){


		if (taxa!=null) {
			Object n = (String)taxa.getAssociatedObject(VoucherInfoFromOTUIDDB.voucherDBRef, ic);
			if (n !=null)
				return ((String)n);

		}
		return "-";
	}
	/*...............................................................................................................*/
	/** returns whether or not a cell of table is editable.*/
	public boolean isCellEditable(int row){
		return true;
	}
	/*...............................................................................................................*/
	/** for those permitting editing, indicates user has edited to incoming string.*/
	public void setString(int row, String s){
		if (taxa!=null) {
			taxa.setAssociatedObject(VoucherInfoFromOTUIDDB.voucherDBRef, row, s);
		}
		
	}
	public boolean useString(int ic){
		return true;
	}
	
	public String getWidestString(){
		return "8888888888888888  ";
	}
	/*.................................................................................................................*/
    	 public String getName() {
		return "OTU ID Code Database";
   	 }
	/*.................................................................................................................*/
   	public boolean isPrerelease(){
   		return false;  
   	}
	/*.................................................................................................................*/
	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
	public int getVersionOfFirstRelease(){
		return -1;  
	}
	/*.................................................................................................................*/
	/** returns whether this module is requesting to appear as a primary choice */
   	public boolean requestPrimaryChoice(){
   		return true;  
   	}
   	 
	/*.................................................................................................................*/
 	/** returns an explanation of what the module does.*/
 	public String getExplanation() {
 		return "Lists the OTU code database for a taxon." ;
   	 }
}
\ No newline at end of file
diff --git a/Source/mesquite/lists/TaxonSetList/TaxonSetList.java b/Source/mesquite/lists/TaxonSetList/TaxonSetList.java
new file mode 100644
index 0000000..977c93d
--- /dev/null
+++ b/Source/mesquite/lists/TaxonSetList/TaxonSetList.java
@@ -0,0 +1,94 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TaxonSetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxonSetList extends TaxaSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Taxon Sets";
+	}
+	public String getExplanation() {
+		return "Makes windows listing taxon sets." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaSetListAssistant.class, "The List of Taxa Sets window can display columns showing information for each taxa set.",
+		"You can request that columns be shown using the Columns menu of the List of Taxa Sets Window. ");
+	}
+	/*.................................................................................................................*/
+	public int currentTaxa = 0;
+	public Taxa taxa = null;
+	TaxaSpecsListWindow window;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Taxon Set...", makeCommand("newTaxSet",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	/*.................................................................................................................*/
+	public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+		super.showListWindow(obj);
+		TaxaSetListAssistant assistant = (TaxaSetListAssistant)hireNamedEmployee(TaxaSetListAssistant.class, "#TaxaSetListNum");
+		if (assistant!= null){
+			((ListWindow)getModuleWindow()).addListAssistant(assistant);
+			assistant.setUseMenubar(false);
+		}
+	}
+	/*.................................................................................................................*/
+	public Class getItemType(){
+		return TaxaSelectionSet.class;
+	}
+	public String getItemTypeName(){
+		return "Taxon set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Taxon sets";
+	}
+	public SpecsSet makeNewSpecsSet(Taxa taxa){
+		if (taxa != null)
+			return new TaxaSelectionSet("Taxa Set", taxa.getNumTaxa(), taxa);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new taxon set (TAXSET)", null, commandName, "newTaxSet")){
+			if (taxa !=null &&AlertDialog.query(containerOfModule(), "New Taxon Set", "To make a new taxon set (TAXSET), go to the List of Taxa window, select the taxa you want in the set, then choose Save Selected As Set.  Would you like to go to the List of Taxa window now?", "OK", "Cancel")) {
+				Object obj = taxa.doCommand("showMe", null, checker);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns taxa block in use", null, commandName, "getTaxa"))
+			return taxa;
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/TreeListAttachment/TreeListAttachment.java b/Source/mesquite/lists/TreeListAttachment/TreeListAttachment.java
new file mode 100644
index 0000000..0f050aa
--- /dev/null
+++ b/Source/mesquite/lists/TreeListAttachment/TreeListAttachment.java
@@ -0,0 +1,138 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeListAttachment;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeListAttachment extends TreeListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Attachment";
+	}
+	public String getExplanation() {
+		return "Displays an item attached to trees." ;
+	}
+	TreeVector treesBlock;
+	String nameOfAttached = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (nameOfAttached==null)
+			return null;
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setAttached " + ParseUtil.tokenize(nameOfAttached));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets what attachment to show", "[name of attached to show]", commandName, "setAttached")) {
+			nameOfAttached = parser.getFirstToken(arguments);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+		if (!MesquiteThread.isScripting()){
+			ListableVector v = new ListableVector();
+			if (nameOfAttached == null && treesBlock !=null){
+				for (int itree =0; itree < treesBlock.size(); itree++){
+					Tree tree = treesBlock.getTree(itree);
+					if (tree !=null && tree instanceof Attachable){
+						Vector at = ((Attachable)tree).getAttachments();
+						if (at !=null) {
+							for (int i =0; i < at.size(); i++){
+								Object obj = at.elementAt(i);
+								if (obj instanceof Listable) {
+									String name = ((Listable)obj).getName();
+									if (v.indexOfByNameIgnoreCase(name)<0) {
+										MesquiteString ms = new MesquiteString(name);
+										ms.setName(name);
+										v.addElement(ms, false);
+									}
+								}
+							}
+						}
+					}
+				}
+				if (v.size()==0)
+					alert("Sorry, there is nothing attached to the trees to show");
+				else {
+					Listable L = ListDialog.queryList(containerOfModule(), "Select item", "What attachments to tree should be shown?", MesquiteString.helpString, v, 0);
+					if (L!=null)
+						nameOfAttached = L.getName();
+				} 
+			}
+		}
+	}
+	public String getTitle() {
+		if (nameOfAttached !=null)
+			return nameOfAttached;
+		return "Attached";
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getStringForTree(int ic){
+		if (treesBlock==null)
+			return "";
+		Tree tree = treesBlock.getTree(ic);
+		if (tree ==null || !(tree instanceof MesquiteTree))
+			return "";
+		Object a = ((MesquiteTree)tree).getAttachment(nameOfAttached);
+		if (a==null)
+			return "";
+		else
+			return "" + a;
+	}
+	public String getWidestString(){
+		return " 88888888.8888 ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TreeListPolyAssumption/TreeListPolyAssumption.java b/Source/mesquite/lists/TreeListPolyAssumption/TreeListPolyAssumption.java
new file mode 100644
index 0000000..220597f
--- /dev/null
+++ b/Source/mesquite/lists/TreeListPolyAssumption/TreeListPolyAssumption.java
@@ -0,0 +1,89 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeListPolyAssumption;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeListPolyAssumption extends TreeListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Polytomy Assumption";
+	}
+	public String getExplanation() {
+		return "Indicates whether the tree assumes that any polytomies, if present, are hard or soft.  If not, the default assumption is used." ;
+	}
+	/*.................................................................................................................*/
+	TreeVector treesBlock;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+	}
+	public String getTitle() {
+		return "Polytomy Assumption";
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public String getStringForTree(int ic){
+		if (treesBlock==null)
+			return "";
+		Tree tree = treesBlock.getTree(ic);
+		if (tree ==null)
+			return "";
+		if (tree.getPolytomiesAssumption()== 0)
+			return "Hard";
+		else if (tree.getPolytomiesAssumption()== 1)
+			return "Soft";
+		else
+			return "Default";
+	}
+	public String getWidestString(){
+		return " Polytomy Assumption ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/TreeListPolys/TreeListPolys.java b/Source/mesquite/lists/TreeListPolys/TreeListPolys.java
new file mode 100644
index 0000000..d52c990
--- /dev/null
+++ b/Source/mesquite/lists/TreeListPolys/TreeListPolys.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeListPolys;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeListPolys extends TreeListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Polytomies Present";
+	}
+	public String getExplanation() {
+		return "Indicates whether polytomies are present." ;
+	}
+	/*.................................................................................................................*/
+	TreeVector treesBlock;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+	}
+	public String getTitle() {
+		return "Polytomies?";
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public String getStringForTree(int ic){
+		if (treesBlock==null)
+			return "";
+		Tree tree = treesBlock.getTree(ic);
+		if (tree ==null)
+			return "";
+		if (tree.hasPolytomies(tree.getRoot()))
+			return "Yes";
+		else
+			return "No";
+	}
+	public String getWidestString(){
+		return " Polytomies? ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/TreeListRooted/TreeListRooted.java b/Source/mesquite/lists/TreeListRooted/TreeListRooted.java
new file mode 100644
index 0000000..586bba5
--- /dev/null
+++ b/Source/mesquite/lists/TreeListRooted/TreeListRooted.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeListRooted;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeListRooted extends TreeListAssistant {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Rooting status";
+	}
+	public String getExplanation() {
+		return "Indicates whether the tree is rooted or unrooted." ;
+	}
+	/*.................................................................................................................*/
+	TreeVector treesBlock;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		treesBlock = trees;
+	}
+	public String getTitle() {
+		return "Rooting";
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == treesBlock)
+			treesBlock=null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+	public String getStringForTree(int ic){
+		if (treesBlock==null)
+			return "";
+		Tree tree = treesBlock.getTree(ic);
+		if (tree ==null)
+			return "";
+		if (tree.getRooted())
+			return "Rooted";
+		else
+			return "Unrooted";
+	}
+	public String getWidestString(){
+		return " Unrooted ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/lists/TreeblockList/TreeblockList.java b/Source/mesquite/lists/TreeblockList/TreeblockList.java
new file mode 100644
index 0000000..abdaf2c
--- /dev/null
+++ b/Source/mesquite/lists/TreeblockList/TreeblockList.java
@@ -0,0 +1,167 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeblockList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeblockList extends ListLVModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Tree Blocks List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing tree blocks and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeblocksListAssistant.class, "The List of Tree Blocks window can display columns showing information for each tree block.",
+		"You can request that columns be shown using the Columns menu of the List of Tree Blocks Window. ");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeBlockListUtility.class, "Utilities operating on tree blocks can be used through the List of Tree Blocks window.",
+		"You can request such a utility using the Utilities submenu of the List menu of the List of Tree Blocks Window. ");
+	}
+	/*.................................................................................................................*/
+	TreesManager manager;
+	ListableVector treeBlocks;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		if (manager==null)
+			return sorry(getName() + " couldn't start because no tree manager module was found");
+		return true;
+	}
+	public boolean showing(Object obj){
+		return (getModuleWindow()!=null && obj == treeBlocks);
+	}
+
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean resetMenusOnNameChange(){
+		return true;
+	}
+	public void aboutToDeleteRow(int row){  //called just before superclass deletes rows, in case specific module needs to prepare for deletion
+		if (row<0 || row>= getNumberOfRows())
+			return;
+		TreeVector trees = (TreeVector)treeBlocks.elementAt(row);
+		if (trees != null)
+			trees.doom();
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (row<0 || row>= getNumberOfRows())
+			return false;
+		TreeVector trees = (TreeVector)treeBlocks.elementAt(row);
+		getProject().removeFileElement(trees);//must remove first, before disposing
+		trees.dispose();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires utility module to operate on the trees blocks", "[name of module]", commandName, "doUtility")) {
+			TreeBlockListUtility tda= (TreeBlockListUtility)hireNamedEmployee(TreeBlockListUtility.class, arguments);
+			if (tda!=null) {
+				int count = 0;
+				for (int i=0; i<treeBlocks.size() && i<getNumberOfRows(); i++)
+					if (isRowSelected(i))
+						count++;
+				boolean doAll = false;
+				if (count == 0) {
+					count = treeBlocks.size();
+					doAll = true;
+				}
+				TreeVector[] selected = new TreeVector[count];
+				count = 0;
+				for (int i=0; i<treeBlocks.size() && i<getNumberOfRows(); i++)
+					if (doAll || isRowSelected(i))
+						selected[count++] = (TreeVector)treeBlocks.elementAt(i);
+				boolean a = tda.operateOnTreeBlocks(selected);
+				if (!tda.pleaseLeaveMeOn())
+					fireEmployee(tda);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void showListWindow(Object obj){
+		setModuleWindow( new ListableVectorWindow(this));
+		treeBlocks = manager.getTreeBlockVector();
+		((ListableVectorWindow)getModuleWindow()).setObject(treeBlocks);
+		//makeMenu("Tree_Blocks");
+		makeMenu("List");
+		MesquiteSubmenuSpec mss2 = addSubmenu(null, "Utilities", MesquiteModule.makeCommand("doUtility",  this));
+		mss2.setList(TreeBlockListUtility.class);
+
+		if (!MesquiteThread.isScripting()){
+			TreeblocksListAssistant assistant = (TreeblocksListAssistant)hireNamedEmployee(TreeblocksListAssistant.class, "#TreeblocksListNumber");
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TreeblocksListAssistant)hireNamedEmployee(TreeblocksListAssistant.class, "#TreeblocksListTaxa");
+			if (assistant!= null){
+				((ListableVectorWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return treeBlocks;
+	}
+	public int getNumberOfRows(){
+		if (treeBlocks==null)
+			return 0;
+		else
+			return treeBlocks.size();
+	}
+	public Class getAssistantClass(){
+		return TreeblocksListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Tree block";
+	}
+	public String getItemTypeNamePlural(){
+		return "Tree blocks";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/TreeblocksListNumber/TreeblocksListNumber.java b/Source/mesquite/lists/TreeblocksListNumber/TreeblocksListNumber.java
new file mode 100644
index 0000000..3184bfc
--- /dev/null
+++ b/Source/mesquite/lists/TreeblocksListNumber/TreeblocksListNumber.java
@@ -0,0 +1,96 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeblocksListNumber;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeblocksListNumber extends TreeblocksListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of trees in tree block";
+	}
+	public String getExplanation() {
+		return "Indicates number of trees." ;
+	}
+	ListableVector treeBlocks=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.treeBlocks = (ListableVector)obj;
+		treeBlocks.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "# trees";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (treeBlocks ==null || ic<0 || ic> treeBlocks.size())
+				return "";
+			return Integer.toString( ((TreeVector)treeBlocks.elementAt(ic)).size());
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		return " 888888 ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TreeblocksListTaxa/TreeblocksListTaxa.java b/Source/mesquite/lists/TreeblocksListTaxa/TreeblocksListTaxa.java
new file mode 100644
index 0000000..b723591
--- /dev/null
+++ b/Source/mesquite/lists/TreeblocksListTaxa/TreeblocksListTaxa.java
@@ -0,0 +1,119 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreeblocksListTaxa;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreeblocksListTaxa extends TreeblocksListAssistant implements MesquiteListener {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxa of tree block";
+	}
+	public String getExplanation() {
+		return "Indicates taxa of tree block." ;
+	}
+	ListableVector treeBlocks=null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+	}
+
+	public void setTableAndObject(MesquiteTable table, Object obj){
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		if (obj instanceof ListableVector)
+			this.treeBlocks = (ListableVector)obj;
+		treeBlocks.addListener(this);
+		//table would be used if selection needed
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Taxa";
+	}
+	public String getStringForRow(int ic){
+		try{
+			if (treeBlocks ==null || ic<0 || ic> treeBlocks.size())
+				return "";
+			TreeVector trees = ((TreeVector)treeBlocks.elementAt(ic));
+			if (trees !=null) {
+				Taxa taxa = trees.getTaxa();
+				if (taxa !=null)
+					return taxa.getName();
+				else
+					return "?";
+			}
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+	public String getWidestString(){
+		String best = " 888888 ";
+		if (treeBlocks==null)
+			return best;
+		int m = 8;
+		for (int i=0; i< treeBlocks.size(); i++) {
+			Taxa t = ((TreeVector)treeBlocks.elementAt(i)).getTaxa();
+			if (t!=null && t.getName()!=null){
+				String s = t.getName();
+				int n = s.length();
+				if (n>m) {
+					m=n;
+					best = s;
+				}
+			}
+		}
+		return best + "888";
+
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (treeBlocks !=null)
+			treeBlocks.removeListener(this);
+		super.endJob();
+	}
+
+}
+
diff --git a/Source/mesquite/lists/TreesList/TreesList.java b/Source/mesquite/lists/TreesList/TreesList.java
new file mode 100644
index 0000000..ae2b5ca
--- /dev/null
+++ b/Source/mesquite/lists/TreesList/TreesList.java
@@ -0,0 +1,426 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.TreesList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TreesList extends ListLVModule {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Trees List";
+	}
+	public String getExplanation() {
+		return "Makes windows listing trees and information about them." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeListAssistant.class, "The List of Trees window can display columns showing information for each tree.",
+		"You can request that columns be shown using the List menu of the List of Trees Window. ");
+		e.setEntryCommand("newAssistant");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeListUtility.class, "Utilities operating on trees can be used through the List of Trees window.",
+		"You can request such a utility using the Utilities submenu of the List menu of the List of Trees Window. ");
+	}
+
+	/*.................................................................................................................*/
+	Taxa taxa;
+	TreeVector currentTreeBlock = null;
+	TreesManager manager;
+	MesquiteSubmenuSpec listSubmenu;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		if (manager==null)
+			return sorry(getName() + " couldn't start because no tree manager module found.");
+		if (manager.getNumberTreeBlocks()==0)
+			return sorry(getName() + " couldn't start because no stored trees available.");
+		hireAllEmployees(TreeListInit.class);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of the row.*/
+	public String getAnnotation(int row) {
+		if (currentTreeBlock !=null){
+			if (row >=0 && row < currentTreeBlock.size()) {
+				MesquiteTree t = (MesquiteTree)currentTreeBlock.getTree(row);
+				if (t!=null) {
+					return t.getAnnotation();
+				}
+			}
+		}
+		return null ;
+	}
+	/*.................................................................................................................*/
+	public boolean showing(Object obj){
+		if (obj instanceof TreeVector) {
+			return (obj == currentTreeBlock && getModuleWindow()!=null);
+		}
+		return false;
+	}
+
+	public void showListWindow(Object obj){
+		if (obj instanceof TreeVector) {
+			currentTreeBlock = (TreeVector)obj;
+		}
+		else
+			currentTreeBlock = manager.getTreeBlock(getProject().getTaxa(0), 0);
+		if (currentTreeBlock==null)
+			return;
+		if (taxa!=null)
+			taxa.removeListener(this);
+		taxa =currentTreeBlock.getTaxa();
+		if (taxa!=null)
+			taxa.addListener(this);
+		
+		setModuleWindow( new TreesListWindow(this));
+		((TreesListWindow)getModuleWindow()).setObject(currentTreeBlock);
+		makeMenu("List");
+		addMenuItem("Make New Tree...", makeCommand("newTree",  this));
+		listSubmenu = addSubmenu(null, "Tree Block", makeCommand("setTreeBlockInt",  this), manager.getTreeBlockVector());
+		listSubmenu.setCompatibilityCheck(taxa);
+
+		MesquiteSubmenuSpec mss2 = addSubmenu(null, "Utilities", MesquiteModule.makeCommand("doUtility",  this));
+		mss2.setList(TreeListUtility.class);
+		//addMenuItem( "Save selected set...", makeCommand("saveSelectedRows", this));
+		addMenuItem( "-", null);
+		if (!MesquiteThread.isScripting()){
+			TreeListAssistant assistant;
+			assistant = (TreeListAssistant)hireNamedEmployee(TreeListAssistant.class, "$ #NumForTreeList #NumberOfTaxa");
+			if (assistant!= null){
+				((ListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TreeListAssistant)hireNamedEmployee(TreeListAssistant.class, "#TreeListRooted");
+			if (assistant!= null){
+				((ListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+			}
+			assistant = (TreeListAssistant)hireNamedEmployee(TreeListAssistant.class, "#TreeListPolys");
+			if (assistant!= null){
+				((ListWindow)getModuleWindow()).addListAssistant(assistant);
+				assistant.setUseMenubar(false);
+				assistant = (TreeListAssistant)hireNamedEmployee(TreeListAssistant.class, "#TreeListPolyAssumption");
+				if (assistant!= null){
+					((ListWindow)getModuleWindow()).addListAssistant(assistant);
+					assistant.setUseMenubar(false);
+				}
+			}
+		}
+		for (int i = 0; i<getEmployeeVector().size(); i++){
+			Object mb = getEmployeeVector().elementAt(i);
+			if (mb instanceof TreeListInit){
+				((TreeListInit)mb).setTableAndTreeBlock(((TableWindow)getModuleWindow()).getTable(), currentTreeBlock);
+			}
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+	public Object getMainObject(){
+		return currentTreeBlock;
+	}
+	/* */
+	public TreeVector getTreeBlock(){
+		return currentTreeBlock;
+	}
+	public int getNumberOfRows(){
+		if (currentTreeBlock==null)
+			return 0;
+		else
+			return currentTreeBlock.size();
+	}
+	public Class getAssistantClass(){
+		return TreeListAssistant.class;
+	}
+	public String getItemTypeName(){
+		return "Tree";
+	}
+	public String getItemTypeNamePlural(){
+		return "Trees";
+	}
+	public void classFieldChanged (Class c, String fieldName) {
+		super.classFieldChanged(c, fieldName);
+		if (c== Tree.class)
+			forceRecalculations();
+	}
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (currentTreeBlock!=null) {
+			Listable obj = currentTreeBlock.getTree(row);
+			if (obj!=null) {
+				currentTreeBlock.removeElement(obj, notify);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		if (getModuleWindow()==null || !getModuleWindow().isVisible())
+			return null;
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("setTreeBlock " + TreeVector.toExternal(manager.getTreeBlockNumber(taxa, currentTreeBlock))); 
+		if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets tree block to use (for internal use; 0 based)", "[number of tree block]", commandName, "setTreeBlockInt")) { //need separate from setTreeBlock since this is used internally with 0-based menu response
+			int whichList = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				currentTreeBlock = manager.getTreeBlock(taxa, whichList);
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa =currentTreeBlock.getTaxa();
+				if (taxa!=null)
+					taxa.addListener(this);
+				listSubmenu.setCompatibilityCheck(taxa);
+				((TreesListWindow)getModuleWindow()).setObject(currentTreeBlock);
+				return currentTreeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets tree block to use", "[number of tree block]", commandName, "setTreeBlock")) {
+			int whichList = TreeVector.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				TreeVector t  = manager.getTreeBlock(taxa, whichList);
+				if (t==null)
+					return null;
+				currentTreeBlock = t;
+				if (taxa!=null)
+					taxa.removeListener(this);
+				taxa =currentTreeBlock.getTaxa();
+				if (taxa!=null)
+					taxa.addListener(this);
+				((TreesListWindow)getModuleWindow()).setObject(currentTreeBlock);
+				return currentTreeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Instructs the user how to make a new tree", null, commandName, "newTree")) {
+			alert("One way to create a new tree is to open a tree window, edit the tree, and choose Store Tree from the Tree menu"); 
+		}
+		else if (checker.compare(this.getClass(), "Hires utility module to operate on the trees", "[name of module]", commandName, "doUtility")) {
+			if (currentTreeBlock !=null){
+				TreeListUtility tda= (TreeListUtility)hireNamedEmployee(TreeListUtility.class, arguments);
+				if (tda!=null) {
+					boolean a = tda.operateOnTrees(currentTreeBlock);
+					if (!tda.pleaseLeaveMeOn())
+						fireEmployee(tda);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns taxa block used", null, commandName, "getTaxa")) {
+			return taxa;
+		}
+		else if (checker.compare(this.getClass(), "Returns current tree block", null, commandName, "getTreeBlock")) {
+			return currentTreeBlock;
+		}
+		else if (checker.compare(this.getClass(), "NOT USED YET", null, commandName, "saveSelectedRows")) {
+			//((TreesListWindow)getModuleWindow()).saveSelectedRows();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (currentTreeBlock==null)
+			return "";
+		return "Tree block: "  + currentTreeBlock.getName();
+	}
+
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		//Debug.println("disposing of window");
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+	}
+
+
+}
+
+/* ======================================================================== */
+class TreesListWindow extends ListableVectorWindow implements MesquiteListener {
+	private TreeVector currentTreeBlock;
+	TreesList treesListModule=null;
+	public TreesListWindow (TreesList ownerModule) {
+		super(ownerModule);
+		treesListModule = ownerModule;
+		currentTreeBlock = ownerModule.currentTreeBlock; //SHOULDN'T BE CURRENT FOR TWIG SINCE SHOULD ALLOW MORE THAN ONE WINDOW
+		if (currentTreeBlock!=null)
+			currentTreeBlock.addListener(this); 
+		getTable().setRowAssociable(currentTreeBlock);
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (treesListModule ==null)
+			setTitle("Trees"); 
+		else {
+			TreeVector trees = treesListModule.getTreeBlock();
+			if (trees==null)
+				setTitle("Trees"); 
+			else if (StringUtil.blank(trees.getName()) || "untitled".equalsIgnoreCase(trees.getName()))
+				setTitle("Trees of taxa " + trees.getTaxa().getName()); //TODO: name?
+			else 
+				setTitle("Trees \"" + trees.getName() + "\""); 
+		}
+	}
+	public Object getCurrentObject(){
+		return currentTreeBlock;
+	}
+	
+	public void setObject(Object o){
+		super.setObject(o);
+		TreeListInit assistant;
+		Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TreeListInit) {
+				assistant =  (TreeListInit)obj;
+				assistant.setTableAndTreeBlock(table, (TreeVector)o);
+			}
+		}	
+	}
+	/*.................................................................................................................*/
+	public void processPostSwap(Associable assoc){
+		if (assoc instanceof TreeVector) 
+			((TreeVector)assoc).resetAssignedNumbers();
+		super.processPostSwap(assoc);
+	}
+	/*.................................................................................................................*/
+	public void setCurrentObject(Object obj){
+		if (obj instanceof TreeVector) {
+			if (currentTreeBlock!=null)
+				currentTreeBlock.removeListener(this);
+			currentTreeBlock = (TreeVector)obj;
+			if (currentTreeBlock!=null)
+				currentTreeBlock.addListener(this);
+			getTable().setRowAssociable(currentTreeBlock);
+			getTable().synchronizeRowSelection(currentTreeBlock);
+			resetTitle();
+		}
+		super.setCurrentObject(obj);
+	}
+	public void setRowName(int row, String name){
+		if (currentTreeBlock!=null){
+			AdjustableTree tree = (AdjustableTree)currentTreeBlock.getTree(row);
+			if (tree!=null)
+				tree.setName(name);
+		}
+	}
+	public String getRowName(int row){
+		if (currentTreeBlock!=null) {
+			Tree tree = currentTreeBlock.getTree(row);
+			if (tree!=null)
+				return tree.getName();
+			else
+				return null;
+		}
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof TreeVector &&  (TreeVector)obj ==currentTreeBlock)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		UndoReference undoReference = Notification.getUndoReference(notification);
+		int code = Notification.getCode(notification);
+		if (obj instanceof TreeVector && (TreeVector)obj ==currentTreeBlock) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				getTable().redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				getTable().synchronizeRowSelection(currentTreeBlock);
+				getTable().repaintAll();
+			}
+			else if (code==MesquiteListener.ITEMS_ADDED ||code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_MOVED) {
+				getTable().setNumRows(currentTreeBlock.size());
+				getTable().synchronizeRowSelection(currentTreeBlock);
+				treesListModule.forceRecalculations();
+				getTable().repaintAll();
+				if (code==MesquiteListener.PARTS_MOVED)
+					setUndoer(undoReference);
+				else
+					setUndoer();
+			}
+			else if (code==MesquiteListener.PARTS_DELETED) {
+				getTable().setNumRows(currentTreeBlock.size());
+				getTable().synchronizeRowSelection(currentTreeBlock);
+				treesListModule.forceRecalculations();
+				getTable().repaintAll();
+			}
+			else if (code!=MesquiteListener.ANNOTATION_CHANGED && code!=MesquiteListener.ANNOTATION_ADDED && code!=MesquiteListener.ANNOTATION_DELETED) {
+				getTable().setNumRows(currentTreeBlock.size());
+				getTable().synchronizeRowSelection(currentTreeBlock);
+				getTable().repaintAll();
+			}
+		}
+		else
+			super.changed(caller, obj, notification);
+	}
+
+	public void dispose(){
+		if (currentTreeBlock!=null)
+			currentTreeBlock.removeListener(this);
+		super.dispose();
+	}
+
+}
+
+
diff --git a/Source/mesquite/lists/WeightSetList/WeightSetList.java b/Source/mesquite/lists/WeightSetList/WeightSetList.java
new file mode 100644
index 0000000..9fc00da
--- /dev/null
+++ b/Source/mesquite/lists/WeightSetList/WeightSetList.java
@@ -0,0 +1,87 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.WeightSetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class WeightSetList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Character Weight Sets";
+	}
+
+	public String getExplanation() {
+		return "Makes windows listing character weight sets." ;
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Weight Set...", makeCommand("newWeightSet",  this));
+		return true;
+	}
+
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+
+	public Class getItemType(){
+		return CharWeightSet.class;
+	}
+	public String getItemTypeName(){
+		return "Character weight set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Character weight sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new CharWeightSet("Weight Set", data.getNumChars(), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new character weight set", null, commandName, "newWeightSet")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Weight Set", "To make a new charcter weight set, go to the List of Characters window, make sure that a column for Current Weight Set appears, edit the column, then save the weight set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListWeights", checker);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+}
+
+
diff --git a/Source/mesquite/lists/aListsIntro/aListsIntro.java b/Source/mesquite/lists/aListsIntro/aListsIntro.java
new file mode 100644
index 0000000..f05235b
--- /dev/null
+++ b/Source/mesquite/lists/aListsIntro/aListsIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.aListsIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aListsIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aListsIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides List windows to manage taxa, characters and other information.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "List Windows Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "List Windows Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/lists/explanation.txt b/Source/mesquite/lists/explanation.txt
new file mode 100644
index 0000000..0051b9f
--- /dev/null
+++ b/Source/mesquite/lists/explanation.txt
@@ -0,0 +1,2 @@
+List Windows Package
+One of the core Mesquite packages.  Provides windows to display lists of characters, character matrices, taxa, trees, tree blocks, and other objects.  Also provides modules to supply informative columns for these windows.
diff --git a/Source/mesquite/lists/lib/ArchivedTaxonNamesListAssistant.java b/Source/mesquite/lists/lib/ArchivedTaxonNamesListAssistant.java
new file mode 100644
index 0000000..ddeee2d
--- /dev/null
+++ b/Source/mesquite/lists/lib/ArchivedTaxonNamesListAssistant.java
@@ -0,0 +1,13 @@
+package mesquite.lists.lib;
+
+public abstract class ArchivedTaxonNamesListAssistant extends ListAssistant {
+
+   	 public Class getDutyClass() {
+   	 	return ArchivedTaxonNamesListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Alternative names list assistant";
+   	 }
+
+}
+
diff --git a/Source/mesquite/lists/lib/CharGroupListAssistant.java b/Source/mesquite/lists/lib/CharGroupListAssistant.java
new file mode 100644
index 0000000..14be4e4
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharGroupListAssistant.java
@@ -0,0 +1,15 @@
+package mesquite.lists.lib;
+
+
+/* ======================================================================== */
+public abstract class CharGroupListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return CharGroupListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character group list assistant";
+   	 }
+
+}
+
diff --git a/Source/mesquite/lists/lib/CharInclSetListAsst.java b/Source/mesquite/lists/lib/CharInclSetListAsst.java
new file mode 100644
index 0000000..78d2fdb
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharInclSetListAsst.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class CharInclSetListAsst extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return CharInclSetListAsst.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Inclusion Set list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/CharListAssistant.java b/Source/mesquite/lists/lib/CharListAssistant.java
new file mode 100644
index 0000000..04d5f18
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharListAssistant.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class CharListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return CharListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character list assistant";
+   	 }
+	 /*public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/matrixEditor.gif";
+   	 }
+*/
+	public abstract void setTableAndData(MesquiteTable table, CharacterData data);
+	
+	public String getStringForCharacter(int ic){
+		return null;
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	}
+	public void setTableAndObject(MesquiteTable table, Object object){
+		if (object instanceof CharacterData)
+			setTableAndData(table, (CharacterData)object);
+	}
+	public String getStringForRow(int ic){
+		if (isDoomed())
+			return "";
+		try{
+			return getStringForCharacter(ic);
+		}
+		catch (NullPointerException e){
+		}
+		return "";
+	}
+}
+
diff --git a/Source/mesquite/lists/lib/CharListAssistantI.java b/Source/mesquite/lists/lib/CharListAssistantI.java
new file mode 100644
index 0000000..7e37783
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharListAssistantI.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/**This is superclass of modules to assist tables with characters (e.g., character List, data matrix editor).  
+These are INITs.*/
+
+public abstract class CharListAssistantI extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return CharListAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Character List";
+   	}
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new CharacterStateTest();
+	}
+  	/** method called by data window to inform assistant that data have changed*/
+	public abstract void setTableAndData(MesquiteTable table, CharacterData data);
+  	/** method called by data window to inform assistant that data have changed*/
+	public void focusInRow(int row){
+	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/CharListModel.java b/Source/mesquite/lists/lib/CharListModel.java
new file mode 100644
index 0000000..e11b4d2
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharListModel.java
@@ -0,0 +1,194 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class CharListModel extends CharListAssistant {
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/* hire employees here */
+		return true;
+  	 }
+  	 public abstract String getModelTypeName();
+  	public abstract Class getModelSetClass();
+	public abstract Class getModelClass();
+	public abstract String getParadigm();
+	public abstract ModelSet getNewModelSet(String name, int numChars, CharacterModel defaultModel, CharacterData data);
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the " + getModelTypeName() + " of the selected characters", "[number of model]", commandName, "setModel")) {
+    	 		if (table !=null && data!=null) {
+    	 			boolean changed=false;
+	      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+	      			if (!MesquiteInteger.isCombinable(whichModel))
+	      				return null;
+   	 			CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(getModelClass(), data.getStateClass()), whichModel); //TODO: would be better if passed name of model
+    	 			if (model != null) {
+					ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(getModelSetClass());
+	    	 			if (modelSet == null) {
+				 		CharacterModel defaultModel =  data.getDefaultModel(getParadigm());
+				 		modelSet= getNewModelSet("Model Set", data.getNumChars(), defaultModel, data);
+				 		modelSet.addToFile(data.getFile(), getProject(), findElementManager(getModelSetClass())); //THIS
+						data.setCurrentSpecsSet(modelSet, getModelSetClass());
+	    	 			}
+	    	 			if (modelSet != null) {
+	    	 				if (employer!=null && employer instanceof ListModule) {
+	    	 					int c = ((ListModule)employer).getMyColumn(this);
+		    	 				for (int i=0; i<data.getNumChars(); i++) {
+		    	 					if (table.isCellSelectedAnyWay(c, i)) {
+		    	 						modelSet.setModel(model, i);
+		    	 						if (!changed)
+										outputInvalid();
+		    	 						changed = true;
+	    	 						}
+	    	 					}
+	    	 				}
+	    	 			}
+    	 			}
+    	 			if (changed)
+    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));
+	     	 		parametersChanged();
+   	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Stores current " + getModelTypeName() + " set", null, commandName, "storeCurrent")) {
+    	 		if (data!=null){
+    	 			SpecsSetVector ssv = data.getSpecSetsVector(getModelSetClass());
+    	 			if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+			 		CharacterModel defaultModel =  data.getDefaultModel(getParadigm());
+			 		ModelSet modelSet= getNewModelSet("Model Set", data.getNumChars(), defaultModel, data);
+			 		modelSet.addToFile(data.getFile(), getProject(), findElementManager(getModelSetClass())); //THIS
+					data.setCurrentSpecsSet(modelSet, getModelSetClass());
+					ssv = data.getSpecSetsVector(getModelSetClass());
+    	 			}
+    	 			if (ssv!=null) {
+    	 				SpecsSet s = ssv.storeCurrentSpecsSet();
+    					if (s.getFile() == null)
+    						s.addToFile(data.getFile(), getProject(), findElementManager(getModelSetClass()));
+  	 				s.setName(ssv.getUniqueName("Model Set"));
+    	 				String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of " + getModelTypeName() + " set to be stored", s.getName());
+    	 				if (!StringUtil.blank(name))
+    	 					s.setName(name);
+    	 				ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+    	 			}
+     	 			else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+   	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Replaces stored " + getModelTypeName() + " set by current one", null, commandName, "replaceWithCurrent")) {
+    	 		if (data!=null){
+    	 				SpecsSetVector ssv = data.getSpecSetsVector(getModelSetClass());
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored " + getModelTypeName() + " set to replace by current set",MesquiteString.helpString, ssv, 0);
+		    	 			if (chosen!=null){
+		    	 				SpecsSet current = ssv.getCurrentSpecsSet();
+		    	 				ssv.replaceStoredSpecsSet(chosen, current);
+		    	 			}
+	    	 			}
+    	 			
+    	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Loads the stored " + getModelTypeName() + " set to be the current one", "[number of set to load]", commandName, "loadToCurrent")) {
+ 			if (data !=null) {
+ 				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+ 				if (MesquiteInteger.isCombinable(which)){
+		 			SpecsSetVector ssv = data.getSpecSetsVector(getModelSetClass());
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+		    	 			if (chosen!=null){
+		    	 				ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+		    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+		    	 				return chosen;
+		    	 			}
+			 		}
+ 				}
+	 		}
+	    	 }
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.data = data;
+		this.table = table;
+		if(mss !=null)
+			deleteMenuItem(mss);
+		if(mScs !=null)
+			deleteMenuItem(mScs);
+		if(mRssc !=null)
+			deleteMenuItem(mRssc);
+		if(mLine !=null)
+			deleteMenuItem(mLine);
+		if(mStc !=null)
+			deleteMenuItem(mStc);
+		mss = addSubmenu(null, getTitle(), makeCommand("setModel", this), getProject().getCharacterModels());
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load model set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(getModelSetClass()));
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(getModelClass(), data.getStateClass()));
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		//TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null){
+			ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(getModelSetClass());
+			if (modelSet != null) {
+				CharacterModel model = modelSet.getModel(ic);
+				if (model!=null)
+					return model.getName();
+			}
+			else {
+				CharacterModel model = data.getDefaultModel(getParadigm());
+				if (model!=null) {
+					return model.getName();
+				}
+			}
+		}
+		return "?";
+	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies current " + getModelTypeName() + "s applied to characters for character list window." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/lists/lib/CharListPartitionUtil.java b/Source/mesquite/lists/lib/CharListPartitionUtil.java
new file mode 100644
index 0000000..0e66bb9
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharListPartitionUtil.java
@@ -0,0 +1,129 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+/*~~  */
+
+import mesquite.lists.lib.*;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CharListPartitionUtil {
+
+	/*.................................................................................................................*/
+	public static Object editGroup(MesquiteModule ownerModule, CharacterData data, MesquiteWindow cont, String name, String num) {
+		int i = MesquiteInteger.fromString(num);
+		CharactersGroupVector groups = (CharactersGroupVector)(data.getProject()).getFileElement(CharactersGroupVector.class, 0);
+		Object obj;
+		if (MesquiteInteger.isCombinable(i) && i< groups.size())
+			obj = groups.elementAt(i);
+		else
+			obj = groups.getElement(name);
+		if (obj != null) {
+			CharactersGroup group = (CharactersGroup)obj;
+			GroupDialog d = new GroupDialog(ownerModule.getProject(),MesquiteWindow.windowOfItem(cont), "Edit Character Group", group.getName(), group.getColor(), group.getSymbol(), group.supportsSymbols());
+    	 		d.completeAndShowDialog();
+			name = d.getName();
+			boolean ok = d.query()==0;
+			Color c = d.getColor();
+			d.dispose();
+			if (!ok)
+				return null;
+
+
+			if (!StringUtil.blank(name)) {
+				group.setName(name);
+				group.setColor(c);
+    	 			data.notifyListeners(ownerModule, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+					group.notifyListeners(group, new Notification(MesquiteListener.DATA_CHANGED));
+			}
+		}
+		return obj;
+	}
+	public static boolean deleteGroup(MesquiteModule ownerModule, CharacterData data, MesquiteWindow cont, String name, String num) {
+		int i = MesquiteInteger.fromString(num);
+		CharactersGroupVector groups = (CharactersGroupVector)(data.getProject()).getFileElement(CharactersGroupVector.class, 0);
+		Object obj;
+		if (MesquiteInteger.isCombinable(i) && i< groups.size())
+			obj = groups.elementAt(i);
+		else
+			obj = groups.getElement(name);
+		if (obj != null) {
+			CharactersGroup group = (CharactersGroup)obj;
+			groups.removeElement(group, true);
+			group.doCommand("deleteMe", null, CommandChecker.defaultChecker);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public static CharactersGroup makeGroup(MesquiteModule ownerModule, CharacterData data, MesquiteWindow cont, MesquiteString ms) {
+ 		String n = "Untitled Group";
+ 		if (data.getFile()!=null)
+ 			n = data.getFile().getFileElements().getUniqueName(n);
+ 		GroupDialog d = new GroupDialog(ownerModule.getProject(),MesquiteWindow.windowOfItem(cont), "New Character Group", n, Color.white, null,CharactersGroup.supportsSymbols());
+ 		d.completeAndShowDialog();
+		String name = d.getName();
+		ms.setValue(name);
+		boolean ok = d.query()==0;
+		Color c = d.getColor();
+		d.dispose();
+		if (!ok)
+			return null;
+		//String name = MesquiteString.queryString(containerOfModule(), "New character group", "New character group label", "Untitled Group");
+		if (StringUtil.blank(name))
+			return null;
+		CharactersGroup group = new CharactersGroup();
+		group.setName(name);
+		group.addToFile(data.getFile(), data.getProject(), null);
+		if (c!=null) {
+			group.setColor(c);
+		}
+		return group;
+	}
+	/*.................................................................................................................*/
+	public static CharactersGroup makeGroup(MesquiteModule ownerModule, MesquiteFile file, MesquiteWindow cont, MesquiteString ms) {
+ 		String n = "Untitled Group";
+ 		if (file==null)
+ 			return null;
+ 		n = file.getFileElements().getUniqueName(n);
+ 		GroupDialog d = new GroupDialog(ownerModule.getProject(),MesquiteWindow.windowOfItem(cont), "New Character Group", n, Color.white, null,CharactersGroup.supportsSymbols());
+ 		d.completeAndShowDialog();
+		String name = d.getName();
+		ms.setValue(name);
+		boolean ok = d.query()==0;
+		Color c = d.getColor();
+		d.dispose();
+		if (!ok)
+			return null;
+		//String name = MesquiteString.queryString(containerOfModule(), "New character group", "New character group label", "Untitled Group");
+		if (StringUtil.blank(name))
+			return null;
+		CharactersGroup group = new CharactersGroup();
+		group.setName(name);
+		group.addToFile(file, file.getProject(), null);
+		if (c!=null) {
+			group.setColor(c);
+		}
+		return group;
+	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/CharMatricesListWindow.java b/Source/mesquite/lists/lib/CharMatricesListWindow.java
new file mode 100644
index 0000000..1a73387
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharMatricesListWindow.java
@@ -0,0 +1,35 @@
+package mesquite.lists.lib;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import mesquite.lib.ListableVector;
+import mesquite.lib.characters.CharacterData;
+
+public class CharMatricesListWindow extends ListableVectorWindow {
+	ListableVector datas;
+
+
+	public CharMatricesListWindow (ListModule ownerModule) {
+		super(ownerModule);
+	}
+
+	public ListableVector getDatas() {
+		return datas;
+	}
+
+	public void setDatas(ListableVector datas) {
+		this.datas = datas;
+	}
+
+	/*...............................................................................................................*/
+	public void setRowNameColor(Graphics g, int row){
+		super.setRowNameColor(g,row);
+		if (datas!=null) {
+			CharacterData data =(CharacterData)datas.elementAt(row);
+			if (data!=null && !data.isUserVisible())
+				g.setColor(Color.gray);
+		}
+	}
+
+}
diff --git a/Source/mesquite/lists/lib/CharSetListAsst.java b/Source/mesquite/lists/lib/CharSetListAsst.java
new file mode 100644
index 0000000..219a0f1
--- /dev/null
+++ b/Source/mesquite/lists/lib/CharSetListAsst.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class CharSetListAsst extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return CharSetListAsst.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character set list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/DataSetsListAssistant.java b/Source/mesquite/lists/lib/DataSetsListAssistant.java
new file mode 100644
index 0000000..0a4e69f
--- /dev/null
+++ b/Source/mesquite/lists/lib/DataSetsListAssistant.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class DataSetsListAssistant extends ListAssistant  {
+	protected ListableVector datas =null;
+
+   	 public Class getDutyClass() {
+   	 	return DataSetsListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Data sets list assistant";
+   	 }
+
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	}
+	
+	/** Gets text color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getTextColorOfCell(int ic, boolean selected){
+		if (datas ==null || ic<0 || ic>= datas.size())
+			return null;
+		CharacterData data =((CharacterData)datas.elementAt(ic));
+		if (data!=null && !data.isUserVisible())
+			return Color.gray;
+		return null;
+	}
+
+}
+
diff --git a/Source/mesquite/lists/lib/DataSpecsListWindow.java b/Source/mesquite/lists/lib/DataSpecsListWindow.java
new file mode 100644
index 0000000..90e5dce
--- /dev/null
+++ b/Source/mesquite/lists/lib/DataSpecsListWindow.java
@@ -0,0 +1,145 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class DataSpecsListWindow extends ListWindow implements MesquiteListener {
+	private int currentDataSet = 0;
+	private CharacterData data = null;
+	SpecsSetVector ssv;
+	public DataSpecsListWindow (DataSpecssetList ownerModule, int currentDataSet, CharacterData data) {
+		super(ownerModule); //INFOBAR
+		if (data==null) {
+			ownerModule.alert("Sorry, a list window failed because the data matrix was not found");
+			ownerModule.iQuit();
+			return;
+		}
+		this.currentDataSet = currentDataSet;
+		this.data = data;
+		checkSSV();
+		setCurrentObject(data);
+		data.addListener(this);
+		MesquiteTable table = getTable();
+		if (table !=null)
+			table.setRowNamesWidth(table.getRowNamesWidth()*2); //since not much else!
+	}
+	
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (data!=null&& data.hasTitle())
+			setTitle(((DataSpecssetList)ownerModule).getItemTypeNamePlural() + " of " + data.getName() ); //TODO: file???
+		else if (data==null)
+			setTitle(((DataSpecssetList)ownerModule).getItemTypeNamePlural() + " (DATA NULL)" ); 
+		else
+			setTitle(((DataSpecssetList)ownerModule).getItemTypeNamePlural()); 
+		
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return data;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof CharacterData) {
+			data = (CharacterData)obj;
+			resetTitle();
+		}
+		super.setCurrentObject(obj);
+	}
+	public void setRowName(int row, String name){
+		if (data!=null) {
+			SpecsSet ss = data.getSpecsSet(row, ((DataSpecssetList)ownerModule).getItemType());
+			if (ss!=null)
+				ss.setName(name);
+		}
+	}
+	public boolean rowHighlighted(int row) {
+		//SpecsSetVector ssv = data.getSpecSetsVector(((DataSpecssetList)ownerModule).getItemType());
+		//if (ssv!=null)
+		//	return ssv.indexOfCurrent()==row;
+		return false;
+	}
+	void checkSSV(){
+		if (data==null || ownerModule == null)
+			return;
+		SpecsSetVector ssvNow = data.getSpecSetsVector(((DataSpecssetList)ownerModule).getItemType());
+		if (ssv != ssvNow) {
+			if (ssv!=null)
+				ssv.removeListener(this);
+			ssv =ssvNow;
+			if (ssv!=null) {
+				ssv.addListener(this);
+			}
+		}
+	}
+	public String getRowName(int row){
+		if (data!=null) {
+			checkSSV();
+			SpecsSet ss = data.getSpecsSet(row, ((DataSpecssetList)ownerModule).getItemType());
+			if (ss!=null)
+				return ss.getName();
+			return null;
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (ownerModule!=null && ((obj instanceof Taxa &&  data!=null && (Taxa)obj ==data.getTaxa())||(obj instanceof CharacterData && (CharacterData)obj ==data)))
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof CharacterData && (CharacterData)obj ==data) {
+			checkSSV();
+			if (ownerModule instanceof ListModule)
+				table.setNumRows(((ListModule)ownerModule).getNumberOfRows());
+			table.repaintAll();
+			//fundamental change in data (only need to revise number of rows etc; employees will take care of data themselves
+		}
+		else if (obj instanceof SpecsSetVector && (SpecsSetVector)obj ==ssv){
+			checkSSV();
+			if (ownerModule instanceof ListModule)
+				table.setNumRows(((ListModule)ownerModule).getNumberOfRows());
+			table.repaintAll();
+		}
+		super.changed(caller, obj, notification);
+	}
+	
+	
+}
+
+
diff --git a/Source/mesquite/lists/lib/DataSpecssetList.java b/Source/mesquite/lists/lib/DataSpecssetList.java
new file mode 100644
index 0000000..d65cbff
--- /dev/null
+++ b/Source/mesquite/lists/lib/DataSpecssetList.java
@@ -0,0 +1,260 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public abstract class DataSpecssetList extends ListModule {
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//windows = new Vector();
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public boolean showing(Object obj){
+	 	if (obj instanceof String) {
+    	 		String arguments = (String)obj;
+    	 		int queryDataSet = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		return (queryDataSet == currentDataSet && getModuleWindow()!=null);
+	 	}
+	 	else if (obj instanceof CharacterData) {
+    	 		CharacterData data = (CharacterData)obj;
+    	 		int queryDataSet = getProject().getMatrixNumber(data);
+    	 		return (queryDataSet == currentDataSet && getModuleWindow()!=null);
+	 	}
+	 	return false;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+	 	if (obj instanceof CharacterData) {
+			data = (CharacterData)obj;
+    	 		currentDataSet = getProject().getMatrixNumber(data);
+	 	}
+	 	else
+	 		data = getProject().getCharacterMatrix(currentDataSet);
+ 		if (data==null){
+ 			alert("Sorry, no data set found for list window");
+ 			iQuit();
+  			return;
+ 		}
+ 		data.addListener(this);
+ 		data.getTaxa().addListener(this);
+ 		setModuleWindow(new DataSpecsListWindow(this, currentDataSet, data));
+
+		if (usesCurrentSet()){
+			addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+			addMenuItem("Set stored to current", makeCommand("setToCurrent",  this));
+			addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+ 		}
+ 		addMenuItem( "-", null);
+ 		resetContainingMenuBar();
+		resetAllWindowsMenus();
+  	 }
+  	public boolean usesCurrentSet(){
+  		return true;
+  	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && data!=null && (Taxa)obj == data.getTaxa()) {
+			iQuit();
+		}
+		else if (obj instanceof CharacterData && (CharacterData)obj == data) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (data!=null) {
+				data.removeListener(this);
+				if (data.getTaxa()!=null)
+			  		data.getTaxa().removeListener(this);
+			}
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+  	 public Object getMainObject(){
+  	 	return data;
+  	 }
+  	 public int getNumberOfRows(){
+  	 	if (data==null)
+  	 		return 0;
+  	 	else
+  	 		return data.getNumSpecsSets(getItemType());
+  	 }
+	public Class getAssistantClass(){
+		return null;//return CharListAssistant.class;
+	}
+	public abstract Class getItemType();
+	public abstract SpecsSet makeNewSpecsSet(CharacterData data);
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (data!=null) {
+			SpecsSet ss = data.getSpecsSet(row, getItemType());
+			if (ss!=null) {
+				data.removeSpecsSet(ss,getItemType());
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	if (getModuleWindow()==null || !getModuleWindow().isVisible())
+   	 		return null;
+   	 	Snapshot temp = new Snapshot();
+		
+
+  	 	temp.addLine("setData " + currentDataSet); 
+  	 	
+      	 	if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+  	 	//if (window!=null && !window.isVisible())
+  	 	temp.addLine("showWindow"); 
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the data matrix", "[number of matrix]", commandName, "setData")) {
+    	 		currentDataSet = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (getModuleWindow()!=null && MesquiteInteger.isCombinable(currentDataSet) && currentDataSet<getProject().getNumberCharMatrices(checker.getFile())) {
+				data = getProject().getCharacterMatrix(checker.getFile(), currentDataSet);
+    	 			((ListWindow)getModuleWindow()).setCurrentObject(data);
+    	 			((ListWindow)getModuleWindow()).repaintAll();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current data matrix", null, commandName, "getData")) {
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Stores the current specification set", null, commandName, "storeCurrent")) {
+    	 		if (data!=null){
+    	 			SpecsSetVector ssv = data.getSpecSetsVector(getItemType());
+    	 			if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+			 		SpecsSet specsSet= makeNewSpecsSet(data);
+			 		specsSet.addToFile(data.getFile(), getProject(), findElementManager(getItemType())); 
+					data.setCurrentSpecsSet(specsSet, getItemType());
+					ssv = data.getSpecSetsVector(getItemType());
+    	 			}
+    	 			if (ssv!=null) {
+    	 				SpecsSet s = ssv.storeCurrentSpecsSet();
+    					if (s.getFile() == null)
+    						s.addToFile(data.getFile(), getProject(), findElementManager(getItemType()));
+   	 				if (s!=null)
+    	 					s.setName(ssv.getUniqueName(getItemTypeName()));
+    	 				else {
+    	 					alert("Error: could not make " + getItemTypeName());
+    	 				}
+    	 				/*String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of " + whatsit + " to be stored", "Untitled " + whatsitCap);
+    	 				if (!StringUtil.blank(name))
+    	 					s.setName(name);
+    	 				*/
+    	 				ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+    	 				//MesquiteTable t = ((ListWindow)getModuleWindow()).getTable();
+    	 				//t.setNumRows(t.getNumRows()+1);
+    	 				//t.repaintAll();
+    	 			}
+     	 			else MesquiteMessage.warnProgrammer("storeCurrent in DataSpecs: sorry, can't store because no specssetvector");
+   	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Replaces a stored character specification set by the current one", null, commandName, "replaceWithCurrent")) {
+    	 		if (data!=null){
+    	 			MesquiteTable t = ((ListWindow)getModuleWindow()).getTable();
+    	 			int numRows = t.numRowsSelected();
+    	 			if (numRows>1) 
+    	 				alert("Exactly one row must be selected to indicate which stored " + getItemTypeName() + " is to be replaced by the current one");
+    	 			else  {
+    	 				SpecsSetVector ssv = data.getSpecSetsVector(getItemType());
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen;
+	  	 				if (numRows==0)
+    	 						chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored " + getItemTypeName() + " to replace by current set", MesquiteString.helpString,ssv, 0);
+	    	 				else {
+	    	 					int f = t.firstRowSelected();
+		    	 				if (f<0)
+		    	 					return null;
+		    	 				chosen = ssv.getSpecsSet(f);
+		    	 			}
+		    	 			if (chosen!=null){
+		    	 				SpecsSet current = ssv.getCurrentSpecsSet();
+		    	 				ssv.replaceStoredSpecsSet(chosen, current);
+		    	 				t.repaintAll();
+		    	 			}
+	    	 			}
+    	 			}
+    	 		}
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the selected specification set to be the current one", null, commandName, "setToCurrent")) {
+    	 		if (data!=null){
+    	 			MesquiteTable t = ((ListWindow)getModuleWindow()).getTable();
+    	 			int numRows = t.numRowsSelected();
+    	 			if (numRows>1) 
+    	 				alert("Exactly one row must be selected to indicate which stored " + getItemTypeName() + " is to be set as the current one");
+    	 			else  {
+    	 				SpecsSetVector ssv = data.getSpecSetsVector(getItemType());
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen;
+	  	 				if (numRows==0)
+    	 						chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Set to current", "Choose which stored " + getItemTypeName() + " is to be set as the current one", MesquiteString.helpString,ssv, 0);
+	    	 				else {
+	    	 					int f = t.firstRowSelected();
+		    	 				if (f<0)
+		    	 					return null;
+		    	 				chosen = ssv.getSpecsSet(f);
+		    	 			}
+		    	 			if (chosen!=null){
+		    	 				ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+		    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+    	 						t.repaintAll();
+		    	 				return chosen;
+		    	 			}
+	    	 			}
+    	 			}
+    	 		}
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+ 			//Debug.println("disposing of window");
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+	}
+   	 
+   	 
+}
+
+
+
diff --git a/Source/mesquite/lists/lib/DatasetsListUtility.java b/Source/mesquite/lists/lib/DatasetsListUtility.java
new file mode 100644
index 0000000..cc31b99
--- /dev/null
+++ b/Source/mesquite/lists/lib/DatasetsListUtility.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+public abstract class DatasetsListUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return DatasetsListUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Datasets list utility";
+   	 }
+
+   	/** if returns true, then requests to remain on even after operateOnTaxas is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the CharacterData blocks.  Returns true if taxa altered*/
+   	public abstract boolean operateOnDatas(ListableVector datas, MesquiteTable table);
+}
+
diff --git a/Source/mesquite/lists/lib/GroupDialog.java b/Source/mesquite/lists/lib/GroupDialog.java
new file mode 100644
index 0000000..3256bad
--- /dev/null
+++ b/Source/mesquite/lists/lib/GroupDialog.java
@@ -0,0 +1,156 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import java.awt.event.*;
+
+import javax.swing.JLabel;
+
+
+public class GroupDialog extends ExtensibleDialog implements Colorable, ItemListener, ActionListener {
+	ColorPickerPanel colors;
+	MesquiteWindow frame;
+	Color color;
+	MesquiteSymbol symbol, currentSymbol;
+	SingleLineTextField name;
+	Choice symbolsPopUp;
+	String symbolOptionsButtonName = "Symbol Options...";
+	SymbolsVector symVector;
+	int defaultSymbolElement = 0;
+	SymbolGraphicsPanel symbolsViewPanel;
+	boolean supportsSymbols=true;
+	Button symbolOptionsButton;
+	JLabel symbolLabel;
+	static final String chooseTemplate = "Choose Template";
+	
+	public GroupDialog(MesquiteProject proj, MesquiteWindow f, String title, String groupName, Color initColor, MesquiteSymbol initSymbol, boolean supportsSymbols){
+		super(f, title);
+		frame = f;
+		color = initColor;
+		this.supportsSymbols = supportsSymbols;
+		
+		
+		colors = new ColorPickerPanel(this, initColor, 30);
+		name = addTextField("Name:", groupName, 30);
+		addNewDialogPanel(colors);
+		if (isInWizard())
+			appendToHelpString("<h3>Name and Color</h3>Please enter a name for the group, and choose a color");
+
+
+		
+		if (supportsSymbols) {
+			Listable[] list = proj.getFileElements(SymbolsVector.class);
+			if (list != null && list.length>0){
+				symVector = (SymbolsVector)list[0];
+				String[] symbolNames = symVector.getStringArrayList();
+				symbolNames = StringArray.addToStart(symbolNames,chooseTemplate);
+				currentSymbol = initSymbol;
+	//			currentSymbol = (MesquiteSymbol)symVector.elementAt(defaultSymbolElement);
+		  		if (currentSymbol instanceof FillableMesquiteSymbol)
+		  			((FillableMesquiteSymbol)currentSymbol).setFillColor(getColor());
+				if (currentSymbol!=null) {
+					symbolLabel = addLabel("Current Symbol: " + currentSymbol.getName(), Label.LEFT);
+				}
+				else {
+					symbolLabel = addLabel("Current Symbol: none", Label.LEFT);
+				}
+				Panel panel = addNewDialogPanel();
+				symbolOptionsButton = addAButton(symbolOptionsButtonName, panel);
+				symbolsViewPanel = new SymbolGraphicsPanel(this,currentSymbol);
+				addGraphicsPanel(symbolsViewPanel);
+				symbolOptionsButton.addActionListener(this);
+				if (currentSymbol!=null) {
+					int symIndex = symVector.indexOfByName(currentSymbol.getName());
+					symbolsPopUp = addPopUpMenu("Symbol Templates: ", symbolNames, symIndex+1); // need to do +1 for symIndex because of "Choose Template" item
+					symbol = (MesquiteSymbol)symVector.elementAt(symIndex);
+					symbolOptionsButton.setEnabled(true);
+				}
+				else {
+					symbolsPopUp = addPopUpMenu("Symbol Templates: ", symbolNames, 0);
+					symbolOptionsButton.setEnabled(false);
+				}
+				symbolsPopUp.addItemListener(this);
+			}
+		}
+		
+	}
+	public void setColor(Color c){
+		color = c;
+  		if (currentSymbol instanceof FillableMesquiteSymbol)
+  			((FillableMesquiteSymbol)currentSymbol).setFillColor(color);
+		if (symbolsViewPanel != null)
+			symbolsViewPanel.setSymbol(currentSymbol);
+	}
+	
+	public Color getColor(){
+		return colors.getColor();
+	}
+	
+	public MesquiteSymbol getSymbol(){
+		if (symbol!=null)
+			symbol.setToCloned(currentSymbol);
+		return currentSymbol;
+	}
+	
+	public String getName(){
+		return name.getText();
+	}
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == symbolsPopUp){
+	  		String itemName = (String)e.getItem();
+	  		if (!itemName.equalsIgnoreCase(chooseTemplate)) {
+		  		symbol = (MesquiteSymbol)symVector.elementWithName(itemName);
+		  		symbolLabel.setText("Current Symbol: " + symbol.getName());
+		  		symbolLabel.invalidate();
+		  		
+		  		currentSymbol = symbol.cloneMethod();
+		  		if (currentSymbol instanceof FillableMesquiteSymbol)
+		  			((FillableMesquiteSymbol)currentSymbol).setFillColor(getColor());
+		  		if (symbolsViewPanel != null)
+		  			symbolsViewPanel.setSymbol(currentSymbol);
+		  		if (symbolOptionsButton != null)
+		  			symbolOptionsButton.setEnabled(true);
+	  		} 
+	  		else if (currentSymbol!=null) {  //switch popup back
+				int symIndex = symVector.indexOfByName(currentSymbol.getName());
+	  			symbolsPopUp.select(symIndex+1);  // need to do +1 because of "Choose Template" item
+	  		}
+  		}
+  	}
+/*.................................................................................................................*/
+	public void actionPerformed(ActionEvent e){
+		if (symbolOptionsButtonName.equalsIgnoreCase(e.getActionCommand())) {
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+    	 		ExtensibleDialog d = new ExtensibleDialog(frame, "Symbol Options: " + currentSymbol.getName(), buttonPressed);
+			currentSymbol.addDialogElements(d, true);
+    	 		d.completeAndShowDialog();
+			boolean ok = d.query()==0;
+			if (ok)
+    	 			currentSymbol.getDialogOptions();
+			d.dispose();
+	  		if (currentSymbol instanceof FillableMesquiteSymbol)
+	  			((FillableMesquiteSymbol)currentSymbol).setFillColor(getColor());
+			if (symbolsViewPanel != null)
+				symbolsViewPanel.setSymbol(currentSymbol);
+		}
+		else super.actionPerformed(e);
+	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/GroupSymbolsDialog.java b/Source/mesquite/lists/lib/GroupSymbolsDialog.java
new file mode 100644
index 0000000..9ad98c7
--- /dev/null
+++ b/Source/mesquite/lists/lib/GroupSymbolsDialog.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import java.awt.event.*;
+
+import javax.swing.JLabel;
+
+
+public class GroupSymbolsDialog extends ExtensibleDialog implements ItemListener, ActionListener {
+	MesquiteWindow frame;
+	MesquiteSymbol symbol, currentSymbol;
+	Choice symbolsPopUp;
+	String symbolOptionsButtonName = "Symbol Options...";
+	SymbolsVector symVector;
+	int defaultSymbolElement = 0;
+	Button symbolOptionsButton;
+	JLabel symbolLabel;
+	static final String chooseTemplate = "Choose Template";
+
+	public GroupSymbolsDialog(MesquiteProject proj, MesquiteWindow f, String title, String groupName, MesquiteSymbol initSymbol){
+		super(f, title);
+		frame = f;
+
+		Listable[] list = proj.getFileElements(SymbolsVector.class);
+		if (list != null && list.length>0){
+			symVector = (SymbolsVector)list[0];
+			String[] symbolNames = symVector.getStringArrayList();
+			symbolNames = StringArray.addToStart(symbolNames,chooseTemplate);
+			currentSymbol = initSymbol;
+			//			currentSymbol = (MesquiteSymbol)symVector.elementAt(defaultSymbolElement);
+			if (currentSymbol!=null) {
+				symbolLabel = addLabel("Current Symbol: " + currentSymbol.getName(), Label.LEFT);
+			}
+			else {
+				symbolLabel = addLabel("", Label.LEFT);
+			}
+			if (currentSymbol!=null) {
+				int symIndex = symVector.indexOfByName(currentSymbol.getName());
+				symbolsPopUp = addPopUpMenu("Symbol Templates: ", symbolNames, symIndex+1); // need to do +1 for symIndex because of "Choose Template" item
+				symbol = (MesquiteSymbol)symVector.elementAt(symIndex);
+			}
+			else {
+				symbolsPopUp = addPopUpMenu("Symbol Templates: ", symbolNames, 0);
+			}
+			Panel panel = addNewDialogPanel();
+			symbolOptionsButton = addAButton(symbolOptionsButtonName, panel);
+			symbolOptionsButton.addActionListener(this);
+			if (currentSymbol!=null) {
+				symbolOptionsButton.setEnabled(true);
+			}
+			else {
+				symbolOptionsButton.setEnabled(false);
+			}
+			symbolsPopUp.addItemListener(this);
+
+		}
+
+	}
+	
+	public MesquiteSymbol getSymbol(){
+		if (symbol!=null)
+			symbol.setToCloned(currentSymbol);
+		return currentSymbol;
+	}
+	
+/*.................................................................................................................*/
+  	public void itemStateChanged(ItemEvent e){
+  		if (e.getItemSelectable() == symbolsPopUp){
+	  		String itemName = (String)e.getItem();
+	  		if (!itemName.equalsIgnoreCase(chooseTemplate)) {
+		  		symbol = (MesquiteSymbol)symVector.elementWithName(itemName);
+		  		symbolLabel.setText("Current Symbol: " + symbol.getName());
+		  		symbolLabel.invalidate();
+		  		
+		  		currentSymbol = symbol.cloneMethod();
+		  		if (symbolOptionsButton != null)
+		  			symbolOptionsButton.setEnabled(true);
+	  		} 
+	  		else if (currentSymbol!=null) {  //switch popup back
+	  			int symIndex = symVector.indexOfByName(currentSymbol.getName());
+	  			symbolsPopUp.select(symIndex+1);  // need to do +1 because of "Choose Template" item
+	  		}
+  		}
+  	}
+  	/*.................................................................................................................*/
+  	public void actionPerformed(ActionEvent e){
+  		if (symbolOptionsButtonName.equalsIgnoreCase(e.getActionCommand())) {
+  			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+  			ExtensibleDialog d = new ExtensibleDialog(frame, "Symbol Options: " + currentSymbol.getName(), buttonPressed);
+  			currentSymbol.addDialogElements(d, false);
+  			d.completeAndShowDialog();
+  			boolean ok = d.query()==0;
+  			if (ok)
+  				currentSymbol.getDialogOptions();
+  			d.dispose();
+  		}
+  		else super.actionPerformed(e);
+  	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/ListAssistant.java b/Source/mesquite/lists/lib/ListAssistant.java
new file mode 100644
index 0000000..140b5fc
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListAssistant.java
@@ -0,0 +1,100 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+public abstract class ListAssistant extends MesquiteModule  {
+	
+   	 public Class getDutyClass() {
+   	 	return ListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "List assistant";
+   	 }
+	/**  Set the table and list's object (e.g, listable vector, data matrix for characters, etc.) */
+	public abstract void setTableAndObject(MesquiteTable table, Object object);
+	
+	/** Returns whether to use the string from getStringForRow; otherwise call drawInCell*/
+	public boolean useString(int ic){
+		return (getStringForRow(ic)!=null);
+	}
+	/** Returns string to be placed in cell for row */
+	public abstract String getStringForRow(int ic);
+
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int ic, boolean selected){
+		return null;
+	}
+	/** Gets text color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getTextColorOfCell(int ic, boolean selected){
+		return null;
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int row){
+		return false;
+	}
+	/*...............................................................................................................*/
+	/** for those permitting editing, indicates user has edited to incoming string.*/
+	public void setString(int row, String s){
+		
+	}
+
+	/** Draw cell for row ic */
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	}
+	/** Returns widest string in column; can return by default a long string for safety */
+	public String getWidestString(){
+		return "";
+	}
+	public String getExplanationForRow(int ic){
+		return null;
+	}
+	
+	public boolean canHireMoreThanOnce(){
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic, int x, int y, boolean doubleClick, int modifiers){ //so assistant can do something in response to arrow touch; return true if the event is to stop there, i.e. be intercepted
+		return false;
+	}
+	
+	/** following method is DEPRECATED */
+	public boolean arrowTouchInRow(int ic, boolean doubleClick){ 
+		return false;
+	}
+	
+
+	/*.................................................................................................................*/
+	public String moduleActiveWord() {
+		return "shown";
+	}
+	public int getColumnWidth(){
+		return 0;
+	}
+	/** Returns column title */
+	public abstract String getTitle();
+}
+
diff --git a/Source/mesquite/lists/lib/ListLVModule.java b/Source/mesquite/lists/lib/ListLVModule.java
new file mode 100644
index 0000000..702dd41
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListLVModule.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+
+public abstract class ListLVModule extends ListModule  {
+   	 public Class getDutyClass() {
+   	 	return ListLVModule.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "List Module for Listable Vectors";
+   	 }
+
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return true;
+	}
+	/** returns either a String (if not editable) or a MesquiteString (if to be editable) */
+	public String getAnnotation(int row){
+		Object mo = getMainObject();
+		if (mo instanceof ListableVector){
+			ListableVector myVector = (ListableVector)mo;
+			if (myVector!=null && row>=0 && row < myVector.size()){
+				Object obj = myVector.elementAt(row);
+				if (obj instanceof Annotatable){
+					return ((Annotatable)obj).getAnnotation();
+				}
+			}
+		}
+		return null;
+	}
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){
+		Object mo = getMainObject();
+		if (mo instanceof ListableVector){
+			ListableVector myVector = (ListableVector)mo;
+			if (myVector!=null && row>=0 && row < myVector.size()){
+				Object obj = myVector.elementAt(row);
+				if (obj instanceof Annotatable){
+					((Annotatable)obj).setAnnotation(s, notify);
+				}
+			}
+		}
+	}
+	/** returns a String explaining the row */
+	public String getExplanation(int row){
+		Object mo = getMainObject();
+		if (mo instanceof ListableVector){
+			ListableVector myVector = (ListableVector)mo;
+			if (myVector!=null && row>=0 && row < myVector.size()){
+				Object obj = myVector.elementAt(row);
+				if (obj instanceof Explainable){
+					return ((Explainable)obj).getExplanation();
+				}
+			}
+		}
+		return null;
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/lists/lib/ListModule.java b/Source/mesquite/lists/lib/ListModule.java
new file mode 100644
index 0000000..2a25531
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListModule.java
@@ -0,0 +1,202 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+/**Supplies a column for a character list window.*/
+
+public abstract class ListModule extends ManagerAssistant  {
+   	 public Class getDutyClass() {
+   	 	return ListModule.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "List Module";
+   	 }
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Sort Rows", "(A tool of the List Windows) Sorts the rows (taxa, characters, etc.) by the column touched", null, MesquiteModule.getRootImageDirectoryPath() +"sort.gif"));
+		registerSubfunction(new FunctionExplanation("Select Same", "(The magic wand tool of the List Windows) Selects rows (taxa, characters, etc.) that match in the column touched", null, MesquiteModule.getRootImageDirectoryPath() +"wand.gif"));
+		super.getSubfunctions();
+	}
+	
+	
+	public void employeeQuit(MesquiteModule m){
+		if (m instanceof ListAssistant){
+			ListWindow window = ((ListWindow)getModuleWindow());
+			window.reviewColumnNumber();
+				
+		}
+	}
+	
+	
+	public abstract Class getAssistantClass();
+	public abstract int getNumberOfRows();
+	public abstract Object getMainObject();
+	public abstract String getItemTypeName();
+	public abstract String getItemTypeNamePlural();
+	
+	public String getTextContentsPreface(){
+		String text = "";
+		text += "Window showing " + getItemTypeNamePlural();
+		Object obj = getMainObject();
+		if (obj != null && obj instanceof Listable){
+			text += " of ";
+			if (obj instanceof FileElement)
+				text += ((FileElement)obj).getTypeName() + " \'";
+			text += ((Listable)obj).getName();
+			if (obj instanceof FileElement)
+				text += "\'";
+		}
+		if (obj instanceof Annotatable){
+			Annotatable an = (Annotatable)obj;
+			String s = an.getAnnotation();
+			if (!StringUtil.blank(s))
+				text += "\n\n----------------\nNotes:\n" + s + "\n---------------\n\n";
+		}
+		return text;
+	}
+	/*.................................................................................................................*/
+	public boolean rowsMovable(){
+		return false;
+	}
+	/*...............................................................................................................*/
+	public Undoer getSingleNameUndoInstructions(int row, String oldName, String s){
+		return null;
+	}
+
+	public boolean resetMenusOnNameChange(){
+		return false;
+	}
+	public Vector getAssistants() {
+		Vector v = new Vector();
+		for (int i=0; i< getNumberOfEmployees(); i++) {
+			Object obj =  getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				v.addElement(obj);
+			}
+		}	
+  	 	return v;
+	}
+
+	public void forceRecalculations() {
+		if (getModuleWindow()== null)
+			return;
+		for (int i=0; i< getNumberOfEmployees(); i++) {
+			Object obj =  getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				((ListAssistant)obj).setTableAndObject(((TableWindow)getModuleWindow()).getTable(), ((TableWindow)getModuleWindow()).getCurrentObject());
+			}
+		}	
+  	 	((ListWindow)getModuleWindow()).pleaseUpdate();  //todo: why do steps go blank if prob models changed???
+	}
+	/** returns a String of annotation for a row*/
+	public abstract String getAnnotation(int row);
+
+	/** sets the annotation for a row*/
+	public abstract void setAnnotation(int row, String s, boolean notify);
+	/** returns a String of explanation for a row*/
+	public String getExplanation(int row){
+		return null;
+	}
+	
+	/** returns a String explaining a column*/
+	public String getColumnExplanation(int column){
+		return null;
+	}
+	public boolean rowsDeletable(){
+		return false;
+	}
+	public boolean rowsAddable(){
+		return false;
+	}
+	public boolean addRow(){
+		return false;
+	}
+	public Object getAddColumnCompatibility(){
+		return null;
+	}
+	/*.................................................................................................................*/
+  	 public int getMyColumn(ListAssistant module) {
+  	 	MesquiteWindow w =getModuleWindow();
+  	 	if (w!=null && w instanceof ListWindow) {
+  	 		return ((ListWindow)w).findAssistant(module);
+  	 	}
+  	 	return -1;
+  	 }
+	/*.................................................................................................................*/
+	public boolean rowDeletable(int row){
+		return rowsDeletable();
+	}
+	public abstract boolean deleteRow(int row, boolean notify);/*{
+		return false;
+	}
+	*/
+	public void aboutToDeleteRow(int row){  //called just before superclass deletes rows, in case specific module needs to prepare for deletion
+	}
+	public void aboutToDeleteRows(int first, int last, boolean notify){
+		for (int i=last; i>=first; i--){
+			aboutToDeleteRow(i);
+		}
+	}
+	public boolean deleteRows(int first, int last, boolean notify){
+		boolean touched = false;
+		for (int i=last; i>=first; i--){
+			if (deleteRow(i, notify))
+				touched = true;
+		}
+		return touched;
+	}
+	/*.................................................................................................................*/
+	public boolean isRowSelected(int row){
+  	 	if (getModuleWindow()!=null && getModuleWindow() instanceof ListWindow)
+  	 		return ((ListWindow)getModuleWindow()).isRowSelected(row);
+  	 	return false;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Hires a list assistant module", "[name of module]", commandName, "newAssistant")) {
+ 			if (getModuleWindow()!=null)
+ 				return getModuleWindow().doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	
+	/*.................................................................................................................*/
+  	 public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+  	 	MesquiteWindow w =getModuleWindow();
+  	 	if (w!=null && w instanceof ListWindow) {
+  	 		((ListWindow)w).blankColumn(employee);
+  	 	}
+  	 }
+	/*.................................................................................................................*/
+  	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+  	 	if (getModuleWindow()!=null && getModuleWindow() instanceof ListWindow) {
+  	 		((ListWindow)getModuleWindow()).reviewColumnWidths();
+  	 		((ListWindow)getModuleWindow()).pleaseUpdate();  //todo: why do steps go blank if prob models changed???
+  	 	}
+  	 }
+}
+
+
+
+
diff --git a/Source/mesquite/lists/lib/ListTable.java b/Source/mesquite/lists/lib/ListTable.java
new file mode 100644
index 0000000..19bcb45
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListTable.java
@@ -0,0 +1,534 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class ListTable extends MesquiteTable {
+	ListWindow window;
+	LTCellAnnotation cellAnnotatable;
+	ListModule ownerModule;
+	public ListTable (int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int columnNamesWidth, ListWindow window, ListModule ownerModule) {
+		super(numRowsTotal, numColumnsTotal, totalWidth, totalHeight, columnNamesWidth, window.getColorScheme(), true,false);
+		this.window = window;
+		cellAnnotatable = new LTCellAnnotation(ownerModule, window);
+		this.ownerModule = ownerModule;
+		showRowGrabbers=true;
+		showColumnGrabbers=true;
+		cornerIsHeading = true;
+		//setAutoEditable(false, true, false, false);
+		setEditable(true, true, false, false);
+		//setSelectable(false, true, true, true, false, false);
+		setSelectable(true, true, true, true, true, false);
+		setUserMove(true, true);
+		setMaximumRowNamesWidth(800);
+	}
+	
+	/* ............................................................................................................... */
+	/** Selects row */
+	public void selectRow(int row) {
+		super.selectRow(row);
+		if (false && rowLegal(row)){
+			if (getRowAssociable() != null) {
+				getRowAssociable().setSelected(row, true);
+				//getRowAssociable().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+	}
+
+	/* ............................................................................................................... */
+	/** Selects rows */
+	public void selectRows(int first, int last) {
+		super.selectRows(first, last);
+		if (false && rowLegal(first) && rowLegal(last)) {
+			int r1 = MesquiteInteger.minimum(first, last);
+			int r2 = MesquiteInteger.maximum(first, last);
+			for (int i = r1; i <= r2; i++) {
+				if (getRowAssociable() != null) {
+					getRowAssociable().setSelected(i, true);
+				}
+			}
+		}
+		if (false && getRowAssociable() != null) 
+			getRowAssociable().notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+	}
+	/*...............................................................................................................*/
+	public void selectedColumnsDropped(int after) {
+			window.selectedColumnsDropped(after+1, true);
+	}
+
+	/*...............................................................................................................*/
+	public void selectedRowsDropped(int after){
+		if (window.owner.rowsMovable() && after >= -1) {
+			if (after >= getNumRows())
+				after = getNumRows();
+			if (window.getCurrentObject() !=null && window.getCurrentObject() instanceof Associable){
+					
+				Bits b = getRowsSelected();
+				if (b.numBitsOn()==1 && b.firstBitOn() == after){
+					return;
+				}
+				Associable assoc = (Associable)window.getCurrentObject();
+				long[] fullChecksumBefore = null;
+				if (assoc instanceof CharacterData)
+					fullChecksumBefore = ((CharacterData)assoc).getIDOrderedFullChecksum();
+				
+				int i = 0;
+				boolean asked = false;
+
+				UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED,assoc);
+				undoInstructions.recordPreviousOrder(assoc);
+				UndoReference undoReference = new UndoReference(undoInstructions, ownerModule);
+
+				while (i<getNumRows()){
+					if (b.isBitOn(i)) {
+						if (assoc instanceof CharacterData && !asked && ((CharacterData)assoc).isMolecularSequence() && i!=after) {
+							if (!AlertDialog.query(window, "Move?", "These are molecular sequences.  Are you sure you want to move the sites to a different location?  It cannot be undone.", "Move", "Cancel"))
+								return;
+							asked = true;
+						}
+						deselectRow(i);
+						b.clearBit(i);
+						assoc.moveParts(i,1,after);
+						b.moveParts(i, 1, after);
+						if (i>after)
+							after++;
+						i=0;
+					}
+					else
+						i++;
+				}
+				
+				if (assoc instanceof TreeVector)
+					((TreeVector)assoc).resetAssignedNumbers();
+				if (assoc instanceof CharacterData){
+					long[] fullChecksumAfter = ((CharacterData)assoc).getIDOrderedFullChecksum();
+					 ((CharacterData)assoc).compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "character moving");
+				}
+				
+				/*
+				for (int i=0; i<getNumRows(); i++)
+					if (isRowSelected(i)) {
+						((Associable)window.getCurrentObject()).moveParts(i,1,after++);//TODO: not correct! need to adjust and see what new "after" is
+					}
+				*/
+				synchronizeRowSelection(((Associable)window.getCurrentObject()));
+				assoc.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+		 		repaintAll();
+	 		}
+ 		}
+	}
+	/* ............................................................................................................... */
+	/** repaints all components of the table */
+	public void repaintAll() {
+		// checkResetFont(getGraphics());
+		columnNames.repaint();
+		repaint();
+		rowNames.repaint();
+		cornerCell.repaint();
+		matrix.repaint();
+	}
+	public String getCornerText(){  
+		if (getNumRows()==0)
+			return "No " + window.owner.getItemTypeNamePlural();
+		return window.owner.getItemTypeName();
+	}
+	/*...............................................................................................................*/
+	/** Gets whether the cell is dimmed (true) or not (false).  Column -1 is for row names; row -1 is for column names.*/
+	public boolean getCellDimmed(int column, int row){
+		if (column == -1 && (row == -1))
+				return getNumRows()<=0;
+		return super.getCellDimmed(column, row);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cells of table editable by default.*/
+	public boolean cellsEditableByDefault(){
+		return false;
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean checkRowNameEditable(int row){
+		return super.isRowNameEditable(row);
+	}
+	/*...............................................................................................................*/
+	public void setRowNameColor(Graphics g, int row){
+		window.setRowNameColor(g,row);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a column name of table is editable.*/
+	public boolean checkColumnNameEditable(int column){
+		return super.isColumnNameEditable(column);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int column, int row){
+		return window.isCellEditable(column, row);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean isRowNameEditable(int row){
+		return window.isRowNameEditable(row);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a column name of table is editable.*/
+	public boolean isColumnNameEditable(int column){
+		return window.isColumnNameEditable(column);
+	}
+	public boolean useString(int column, int row){  
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null) {
+			return (assistant.useString(row));
+		}
+		return false;
+	}
+	public String getMatrixText(int column, int row){  
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null) {
+			try{
+				return assistant.getStringForRow(row);
+			}
+			catch (NullPointerException e){
+			}
+		}
+		return "?";
+	}
+	public Color getBackgroundColor(int column, int row, boolean selected){
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant == null)
+			return null;
+		return assistant.getBackgroundColorOfCell(row,selected);
+	}
+	
+	/* ............................................................................................................... */
+	public Color getTextColor(int column, int row, boolean selected){
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant == null)
+			return null;
+		return assistant.getTextColorOfCell(row,selected);
+	}
+
+	public void drawMatrixCell(Graphics g, int x, int y,  int w, int h, int column, int row, boolean selected){  
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null) {
+			String s = "";
+			try{
+				s = assistant.getStringForRow(row); 
+			}
+			catch (NullPointerException e){
+			}
+		
+		if (assistant.useString(row) && s!=null) {
+				FontMetrics fm = getFontMetrics(getFont());
+				int sw = fm.stringWidth(s);
+				int sh = fm.getMaxAscent()+ fm.getMaxDescent();
+				try{
+					Color old = g.getColor();
+					Color c = assistant.getBackgroundColorOfCell(row,selected);
+					if (c!=null)
+						if (selected)
+							c = Color.black;
+						else if (isCellEditable(column, row))
+							c = Color.cyan;
+						else
+							c = ColorDistribution.uneditable;
+					if (c!=null) g.setColor(c);
+					g.fillRect(x, y, w, h);
+					if (selected)
+						g.setColor(Color.red);
+					else
+						g.setColor(Color.black);
+					g.drawString(assistant.getStringForRow(row), x+(w-sw)/2, y+h-(h-sh)/2);
+					g.setColor(old);
+					
+				}
+				catch (NullPointerException e){
+					MesquiteMessage.printStackTrace("NPE");
+				}
+			}
+			else
+				assistant.drawInCell(row, g, x, y, w, h, selected);
+		}
+	}
+	
+	/*public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column){
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null)
+			g.drawString(assistant.getTitle(), x+getNameStartOffset(), y+h-2);
+	}
+	*/
+	public void drawRowNameCell(Graphics g, int x, int y,  int w, int h, int row){
+		String s = window.getRowName(row);
+		if (s == null)
+			return;
+		Shape clip = g.getClip();
+		g.setClip(x,y,w,h);
+		if (window.rowHighlighted(row)){
+			Color c = g.getColor();
+			g.setColor(ColorDistribution.straw);
+			g.fillRect(x,y,w,h);
+			if (c!=null) g.setColor(c);
+		}
+
+		Object wo = ownerModule.getAnnotation(row); 
+		if (wo != null && (wo instanceof String || wo instanceof MesquiteString)){
+			if (wo instanceof String && !StringUtil.blank((String)wo))
+				s = "*" + s;
+			else if (wo instanceof MesquiteString && !StringUtil.blank(((MesquiteString)wo).getValue()))
+				s = "*" + s;
+		}
+
+		int gnso = x+getNameStartOffset();
+		g.drawString(s, gnso, y+h-4);
+		g.setClip(clip);
+	}
+	/*...............................................................................................................*/
+	public void cellTouched(int column, int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		window.setAnnotation("", null);
+		if (!window.interceptCellTouch(column, row, modifiers)){
+		
+			if (window.getCurrentTool()== window.arrowTool)  {
+				
+					ListAssistant assistant = window.findAssistant(column);
+				if (assistant!=null) {
+						Graphics g = getGraphics();
+						if (!assistant.arrowTouchInRow(g, row, getLeftOfColumn(column), getTopOfRow(row), clickCount>1, modifiers)){
+							if (assistant.isCellEditable(row))
+								super.cellTouched(column, row, regionInCellH,  regionInCellV,  modifiers,  clickCount);
+							else
+								rowTouched(true,row,regionInCellH, regionInCellV, modifiers);
+						}
+				}
+				else
+					rowTouched(true,row,regionInCellH, regionInCellV, modifiers);
+				
+			}
+			else
+				((TableTool)window.getCurrentTool()).cellTouched(column, row, regionInCellH, regionInCellV, modifiers);
+		}
+	}
+	/*...............................................................................................................*/
+	public void cellDrag(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		if (window.getCurrentTool()== window.arrowTool) 
+			super.cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+		else
+		((TableTool)window.getCurrentTool()).cellDrag(column, row, regionInCellH,  regionInCellV, modifiers);
+	}
+	/*...............................................................................................................*/
+	public void cellDropped(int column, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		/*
+		if (window.getCurrentTool()== window.arrowTool) 
+			rowTouched(row, modifiers);
+		else  */
+		   	((TableTool)window.getCurrentTool()).cellDropped(column, row, regionInCellH, regionInCellV, modifiers);
+	}
+	public void rowTouched(boolean asArrow, int row, int regionInCellH, int regionInCellV, int modifiers) {
+		super.rowTouched(asArrow,  row, regionInCellH, regionInCellV, modifiers);
+		//if (getRowAssociable() != null) 
+		//	synchronizeRowSelection(getRowAssociable());
+		showAnnotationAndExplanation(row);
+	}
+	private void showAnnotationAndExplanation(int row){
+		if (row>=0){
+			cellAnnotatable.setRow(row);
+			window.setAnnotation(cellAnnotatable); 
+			window.focusInRow(row);
+		}
+		else {
+			window.setAnnotation("", null); 
+			window.focusInRow(-1);
+		}
+	}
+	public void setFocusedCell(int column, int row){
+		showAnnotationAndExplanation(row);
+		super.setFocusedCell(column, row);
+	}
+	/*...............................................................................................................*/
+	public void rowNameTouched(int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		showAnnotationAndExplanation(row);
+		if (window.getCurrentTool()== window.arrowTool) {
+			if (!window.interceptRowNameTouch(row, regionInCellH, regionInCellV, modifiers)) {
+				if (row >= 0 && MesquiteEvent.commandOrControlKeyDown(modifiers)){
+					Object a = ownerModule.getMainObject();
+					if (a instanceof ListableVector){
+						ListableVector v = (ListableVector)a;
+						if (row < v.size()){
+							Listable rObj = v.elementAt(row);
+							if (rObj instanceof FileElement){
+								FileElement hN = (FileElement)rObj;
+								MesquitePopup popup = new MesquitePopup(this);
+								hN.addToBrowserPopup(popup);
+								popup.showPopup(0, getTopOfRow(row) + getColumnNamesRowHeight() + 20);						
+								return;
+							}
+						}
+							
+					}
+					else if (a instanceof Vector){
+					}
+					else if (a instanceof Taxa){
+					}
+					else if (a instanceof CharacterData){
+					}
+				}
+				if (clickCount>1 && isRowNameEditable(row)){
+					window.setCurrentTool(window.ibeamTool);
+					window.getPalette().setCurrentTool(window.ibeamTool); 
+					((TableTool)window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers);
+				}
+				else {
+					super.rowNameTouched(row,  regionInCellH,  regionInCellV, modifiers,clickCount);
+				}
+			}
+		}
+		else
+		   ((TableTool)window.getCurrentTool()).cellTouched(-1, row, regionInCellH, regionInCellV, modifiers);
+		 
+	}
+	public void superRowNameTouched(int row, int regionInCellH, int regionInCellV, int modifiers, int clickCount){
+		super.rowNameTouched(row, regionInCellH, regionInCellV, modifiers,clickCount);
+	}
+	/*...............................................................................................................*/
+	public boolean getDropDown(int column, int row){
+		if (row != -1)
+			return false;
+		if (column==-1)
+			return super.getDropDown(column, row);
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null)
+			return assistant.needsMenu();
+		else
+			return false;
+	}
+	public boolean touchColumnNameEvenIfSelected(){
+		return true;
+	}
+	/*...............................................................................................................*/
+	public void columnNameTouched(int column, int regionInCellH, int regionInCellV, int modifiers, int clickCount) {
+		window.setAnnotation("", null);
+		ListAssistant assistant = window.findAssistant(column);
+
+		if (assistant!=null) {
+			assistant.showPopUp(getColumnNamesPanel(), getLeftOfColumn(column), getColumnNamesRowHeight()+8);
+		}
+	}
+	/*...............................................................................................................*/
+	/** Called if corner panel is touched.  Can be overridden in subclasses to respond to touch.*/
+   	public void cornerTouched(int x, int y, int modifiers) {
+		window.setAnnotation("", null);
+ 		if (x> getRowNamesWidth()-20)
+ 			window.showSelectionPopup(cornerCell, x, y);
+  		else
+  			super.cornerTouched(x,y,modifiers);
+   	}
+	/*...............................................................................................................*/
+	public void mouseInCell(int modifiers, int column,int subColumn, int row, int subRow, MesquiteTool tool){
+		if (row == -1 && column>=0){ //column names
+			ListAssistant assistant = window.findAssistant(column);
+			if (assistant !=null){
+				String ex = assistant.getName() + "\n" + assistant.getExplanation();
+				String par = assistant.accumulateParameters("   ");
+				if (!StringUtil.blank(par))
+					ex += "\nParameters:\n" + par;
+				window.setExplanation(ex);
+			}
+		}
+		else if (row >=0 && column>=0){ //internal cell
+			ListAssistant assistant = window.findAssistant(column);
+			if (assistant !=null){
+				String ex = assistant.getExplanationForRow(row);
+				if (StringUtil.blank(ex))
+					ex = assistant.getName();
+				window.setExplanation(ex);
+			}
+		}
+	}
+	/*...............................................................................................................*/
+	public void mouseExitedCell(int modifiers, int column,int subColumn,int row, int subRow,MesquiteTool tool){
+		if (row == -1 && column>=0){//column names
+				window.setExplanation("");
+		}
+	}
+	/*...............................................................................................................*/
+	/** Returns text in row name.  */
+	public String getColumnNameText(int column){
+		ListAssistant assistant = window.findAssistant(column);
+		if (assistant!=null)
+			return assistant.getTitle();
+		return "";
+	}
+	/*...............................................................................................................*/
+	/** Returns text in row name.  */
+	public String getRowNameText(int row){
+			return window.getRowName(row);
+	}
+	/*...............................................................................................................*/
+	public void returnedRowNameText(int row, String s){
+		if (s!=null && !s.equals(window.getRowName(row))) {
+			String oldName = window.getRowName(row);
+			window.setRowName(row, s);
+			window.setUndoer(ownerModule.getSingleNameUndoInstructions(row,oldName, s));
+		}
+		
+	}
+	/*...............................................................................................................*/
+	public void returnedMatrixText(int column, int row, String s){
+		if (s!=null){
+			ListAssistant assistant = window.findAssistant(column);
+			if (assistant!=null)
+				assistant.setString(  row, s);
+		}
+	}
+}
+
+/* ======================================================================== */
+class LTCellAnnotation implements Annotatable {
+	ListModule ownerModule;
+	int row;
+	ListWindow window;
+	public LTCellAnnotation(ListModule ownerModule, ListWindow window) {
+		this.ownerModule = ownerModule;
+		this.window = window;
+	}
+	
+	void setRow(int r){
+		row = r;
+	}
+	public String getName(){
+		if (ownerModule == null)
+			return "";
+		 return ownerModule.getItemTypeName() + " \"" + window.getRowName(row) + "\"" ;
+	}
+	public String getAnnotation(){
+		if (ownerModule == null)
+			return null;
+		return ownerModule.getAnnotation(row);
+	}
+	public void setAnnotation(String s, boolean notify){
+		if (ownerModule == null)
+			return;
+		ownerModule.setAnnotation(row, s, notify);
+	}
+ }
+
diff --git a/Source/mesquite/lists/lib/ListWindow.java b/Source/mesquite/lists/lib/ListWindow.java
new file mode 100644
index 0000000..ef236e5
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListWindow.java
@@ -0,0 +1,1027 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class ListWindow extends TableWindow implements KeyListener, MesquiteListener {
+	protected ListTable table;
+	private int windowWidth=360;
+	private int windowHeight=400;
+	ListModule owner;
+	TableTool arrowTool, ibeamTool, wandTool, sortTool;
+	MesquitePopup selectionPopup;
+	MesquiteBoolean equals, greaterThan, lessThan, withinExistingSelection, nonMatching, deselectWandTouched;
+	boolean defaultEquals = true;
+	boolean defaultGT = false;
+	boolean defaultLT = false;
+	boolean defaultWithinSelection = false;
+	boolean defaultNonMatching = false;
+	boolean defaultDeselectWandTouched = false;
+
+	MesquiteCollator collator;
+	MesquiteCommand deleteCommand, deleteColumnCommand;
+
+	/** constructor to be used only for accumulating list of commands*/
+	public ListWindow () {
+	}
+	public ListWindow (ListModule ownerModule) {
+		super(ownerModule, true); //INFOBAR
+		equals = new MesquiteBoolean(defaultEquals);
+		greaterThan = new MesquiteBoolean(defaultGT);
+		lessThan = new MesquiteBoolean(defaultLT);
+		withinExistingSelection = new MesquiteBoolean(defaultWithinSelection);
+		nonMatching = new MesquiteBoolean(defaultNonMatching);
+		deselectWandTouched = new MesquiteBoolean(defaultDeselectWandTouched);
+		setWindowSize(windowWidth, windowHeight);
+		ownerModule.setModuleWindow(this);
+		owner = ownerModule;
+		int numItems = owner.getNumberOfRows();
+		table = new ListTable (numItems, 0, windowWidth, windowHeight, 130, this, ownerModule);
+		setCurrentObject(owner.getMainObject());
+		if (getCurrentObject() instanceof Associable)
+			table.setRowAssociable((Associable)getCurrentObject());
+		collator = new MesquiteCollator();
+
+		//TODO:  note: strangely enough, the commands of the arrow tools are not used, since it uses default behavior of table
+		String selectExplanation = "Select items in table.  If a single cell in the table is touched, and that cell is editable, then you will be given a little box in which you can edit the ";
+		selectExplanation += "contents of the cell.  By holding down shift while clicking, the selection will be extended from the first to the last touched cell. ";
+		selectExplanation += " A block of cells can be selected either by using shift-click to extend a previous selection, or by clicking on a cell and dragging with the mouse button still down";
+		selectExplanation += " Discontinous selections are allowed, and can be obtained by a \"meta\"-click (right mouse button click, or command-click on a MacOS system). ";
+		arrowTool = new TableTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(),"arrow.gif", 4,2,"Select", selectExplanation, null, null, null); //MesquiteModule.makeCommand("arrowTouchCell",  this) , MesquiteModule.makeCommand("arrowDragCell",  this), MesquiteModule.makeCommand("arrowDropCell",  this));
+		arrowTool.setIsArrowTool(true);
+		addTool(arrowTool);
+		setCurrentTool(arrowTool);
+		ibeamTool = new TableTool(this, "ibeam", MesquiteModule.getRootImageDirectoryPath(),"ibeam.gif", 7,7,"Edit", "This tool can be used to edit elements in the table.", MesquiteModule.makeCommand("editCell",  (Commandable)table) , null, null);
+		ibeamTool.setWorksOnRowNames(true);
+		ibeamTool.setWorksOnMatrixPanel(false);
+		addTool(ibeamTool);
+		String wandExplanation = "Select rows in table according to whether they have the same value as the cell touched in that column.  ";
+		wandExplanation += "By holding down shift while clicking, the selection will be added to the previous selection. ";
+		wandTool = new TableTool(this, "wand", MesquiteModule.getRootImageDirectoryPath(),"wand.gif", 4,4,"Select rows with same", wandExplanation, MesquiteModule.makeCommand("wandTouch",  this) , null, null);
+		wandTool.setOptionsCommand(MesquiteModule.makeCommand("wandOptions", this));
+		addTool(wandTool);
+
+		if (owner.rowsMovable()){
+			String sortExplanation = "Sorts items (that is, rows) in table from lowest to highest values in the column touched. ";
+			sortExplanation += "By holding down option while clicking, items will be sorted from highest to lowest. ";
+			sortTool = new TableTool(this, "sort", MesquiteModule.getRootImageDirectoryPath(),"sort.gif", 4,4,"Sort rows", sortExplanation, MesquiteModule.makeCommand("sortTouch",  this) , null, null);
+			sortTool.setOptionImageFileName("revSort.gif", 8, 13);
+			sortTool.setWorksOnRowNames(true);
+			addTool(sortTool);
+		}
+
+		//System.out.println("number of chars " + numItems);
+		table.setColumnWidthsUniform(100);
+		table.setUserAdjust(MesquiteTable.RESIZE, MesquiteTable.RESIZE);
+		addToWindow(table);
+		table.setVisible(true);
+		table.setLocation(0,0);
+
+		MesquiteMenuSpec acm = ownerModule.addAuxiliaryMenu("Columns");
+		MesquiteMenuItemSpec mss = ownerModule.addModuleMenuItems(acm, ownerModule.makeCommand("newAssistant", this), owner.getAssistantClass());
+		if (mss != null)
+			mss.setCompatibilityCheck(ownerModule.getAddColumnCompatibility());
+		if (columnsRemovable()){
+			ownerModule.addMenuItem(acm, "-", null);
+			ownerModule.addMenuItem(acm, "Move Selected Columns...", ownerModule.makeCommand("moveSelectedColumns", this));
+			ownerModule.addMenuItem(acm, "Hide Selected Columns", deleteColumnCommand = ownerModule.makeCommand("deleteSelectedColumns", this));
+			
+		}
+
+
+
+		//ownerModule.addMenuItem( "-", null);
+		if (owner.rowsAddable())
+			ownerModule.addMenuItem( "Add " + owner.getItemTypeNamePlural() + "...", ownerModule.makeCommand("addRows", this));
+		if (owner.rowsDeletable()) {
+			ownerModule.addMenuItem( "Delete Selected " + owner.getItemTypeNamePlural(), deleteCommand = ownerModule.makeCommand("deleteSelectedRows", this));
+			MesquiteWindow.addKeyListener(this, this);
+		}
+		if (owner.rowsMovable()) {
+			MesquiteMenuItemSpec mm = ownerModule.addMenuItem( "Move Selected " + owner.getItemTypeNamePlural() + " To...", ownerModule.makeCommand("moveSelectedTo", this));
+			mm.setShortcut(KeyEvent.VK_M);
+		}
+		setShowExplanation(true);
+		setShowAnnotation(true);
+		table.requestFocusInWindow();
+		MesquiteWindow.addKeyListener(this, table);
+		resetTitle();
+	}
+
+	public String getFindLabel(){
+		return "Find String in Table...";
+	}
+	public void keyTyped(KeyEvent e){
+		int mod = MesquiteEvent.getModifiers(e);
+		if (!MesquiteEvent.commandOrControlKeyDown(mod)) {
+			if (getMode() != InfoBar.GRAPHICS || annotationHasFocus())
+				return;
+
+			if (owner.rowsDeletable() && (table == null || (table.anyRowSelected() && !table.editingAnything())) && (e.getKeyChar()== '\b' || e.getKeyCode()== KeyEvent.VK_BACK_SPACE || e.getKeyCode()== KeyEvent.VK_DELETE)) {
+				deleteCommand.doItMainThread(null, "", this);
+			}
+			else if (columnsRemovable() && (table == null || (table.anyColumnSelected() && !table.editingAnything())) && (e.getKeyChar()== '\b' || e.getKeyCode()== KeyEvent.VK_BACK_SPACE || e.getKeyCode()== KeyEvent.VK_DELETE)) {
+				deleteColumnCommand.doItMainThread(null, "", this);
+			}
+		}
+
+	}
+	public void keyPressed(KeyEvent e){
+	}
+
+	public void keyReleased(KeyEvent e){
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional integer (e.g. for character) (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == getCurrentObject() && getCurrentObject() instanceof Associable && caller != this && caller != table) {
+			table.synchronizeRowSelection((Associable)getCurrentObject());
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public abstract void resetTitle();
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (equals.getValue()!=defaultEquals)
+			temp.addLine("toggleEquals " + equals.toOffOnString());
+		if (greaterThan.getValue()!=defaultGT)
+			temp.addLine("toggleGT " + greaterThan.toOffOnString());
+		if (lessThan.getValue()!=defaultLT)
+			temp.addLine("toggleLT " + lessThan.toOffOnString());
+		if (withinExistingSelection.getValue()!=defaultWithinSelection)
+			temp.addLine("toggleWithinSelection " + withinExistingSelection.toOffOnString());
+		if (nonMatching.getValue()!=defaultNonMatching)
+			temp.addLine("toggleNonMatching " + nonMatching.toOffOnString());
+		if (deselectWandTouched.getValue()!=defaultDeselectWandTouched)
+			temp.addLine("toggleDeselectWandTouched " + deselectWandTouched.toOffOnString());
+
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) { //if employee is number for character list, then hire indirectly its 
+			MesquiteModule e=(MesquiteModule)ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof ListAssistant) {
+				temp.addLine("newAssistant ", e);
+			}
+		}
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	public abstract void setRowName(int row, String name);
+	public abstract String getRowName(int row);
+	public abstract String getRowNameForSorting(int row);
+	public int getSingleNameUndoConstant() {
+		return UndoInstructions.CANTUNDO;
+	}
+	public boolean columnsRemovable(){
+		return true;
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int column, int row){
+		ListAssistant assistant = findAssistant(column);
+		if (assistant != null)
+			return assistant.isCellEditable(row);
+		return table.cellsEditableByDefault();
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a row name of table is editable.*/
+	public boolean isRowNameEditable(int row){
+		return table.checkRowNameEditable(row);
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a column name of table is editable.*/
+	public boolean isColumnNameEditable(int column){
+		return table.checkColumnNameEditable(column);
+	}
+	/*...............................................................................................................*/
+	public void setRowNameColor(Graphics g, int row){
+	}
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	
+	public static void BubbleSort( int [ ] num )
+	{
+	     boolean swapOccurred = true;   
+	     int temp;  
+	     while (swapOccurred) {
+	    	 swapOccurred= false;    //set flag to false awaiting a possible swap
+	            for(int j=0;  j < num.length -1;  j++) {
+	                   if ( num[ j ] < num[j+1] )  {
+	                           temp = num[ j ];                //swap elements
+	                           num[ j ] = num[ j+1 ];
+	                           num[ j+1 ] = temp;
+	                           swapOccurred = true;              //shows a swap occurred  
+	                  } 
+	            } 
+	      } 
+	} 
+
+	/*.................................................................................................................*/
+	private void doWandTouch(String arguments){
+		MesquiteInteger io = new MesquiteInteger(0);
+		int column= MesquiteInteger.fromString(arguments, io);
+		int row= MesquiteInteger.fromString(arguments, io);
+		if (MesquiteInteger.isNonNegative(column)&& (MesquiteInteger.isNonNegative(row))) {  // it is in a real row and column that matters for the wand
+			boolean deselects =deselectWandTouched.getValue();
+			
+			if (getCurrentObject() instanceof Associable){
+				Associable assoc = (Associable)getCurrentObject();
+				boolean withinSelection = withinExistingSelection.getValue() && assoc.getSelected(row);
+				if (arguments.indexOf("shift")<0 && !withinSelection && !deselects)
+					assoc.deselectAll();
+				table.offAllEdits();
+				String text = table.getMatrixText(column, row);
+				for (int i=0; i<table.getNumRows(); i++){
+					boolean satisfies = satisfiesCriteria(text, table.getMatrixText(column, i));
+					if (nonMatching.getValue())
+						satisfies = !satisfies;
+					if (withinSelection) {
+						if (assoc.getSelected(i)){
+							if (!deselects)
+								assoc.setSelected(i, satisfies);
+							else if (satisfies)
+								assoc.setSelected(i, false);
+						}
+					}
+					else if (satisfies) {
+						assoc.setSelected(i, !deselects);
+					}
+				}
+				assoc.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+			else {
+				boolean withinSelection = withinExistingSelection.getValue() && table.isRowSelected(row);
+				if (arguments.indexOf("shift")<0 && !withinSelection && !deselects)
+					table.deselectAll();
+				table.offAllEdits();
+				String text = table.getMatrixText(column, row);
+				for (int i=0; i<table.getNumRows(); i++){
+					boolean satisfies = satisfiesCriteria(text, table.getMatrixText(column, i));
+					if (nonMatching.getValue())
+						satisfies = !satisfies;
+					if (withinSelection) {
+						if (table.isRowSelected(i)){
+							if (!deselects)
+								if (satisfies)
+									table.selectRow(i);
+								else
+									table.deselectRow(i);
+							else if (satisfies)
+								table.deselectRow(i);
+						}
+					}
+					else if (satisfies) {
+						if (!deselects)
+							table.selectRow(i);
+						else
+							table.deselectRow(i);
+					} 
+				}
+				table.repaintAll();
+			}
+		}
+	
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hides the list window", null, commandName, "hideWindow")) {
+			hide();
+		}
+		else if (checker.compare(this.getClass(), "Deletes the selected columns", null, commandName, "deleteSelectedColumns")) {
+			deleteSelectedColumns();
+		}
+		else if (checker.compare(this.getClass(), "Moves the selected columns", null, commandName, "moveSelectedColumns")) {
+			moveSelectedColumns();
+		}
+		else if (checker.compare(this.getClass(), "Present the popup menu to select options for magic wand", null, commandName, "wandOptions")) {
+			MesquiteButton button = wandTool.getButton();
+			if (button!=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x= MesquiteInteger.fromString(arguments, io); //getting x and y from arguments
+				int y= MesquiteInteger.fromString(arguments, io);
+				MesquitePopup popup = new MesquitePopup(button);
+				MesquiteCheckMenuItem equalsItem = new MesquiteCheckMenuItem("Equal", ownerModule, MesquiteModule.makeCommand("toggleEquals", this), null, null);
+				equalsItem.set(equals.getValue());
+				popup.add(equalsItem);
+				MesquiteCheckMenuItem greaterThanItem = new MesquiteCheckMenuItem("Greater than", ownerModule, MesquiteModule.makeCommand("toggleGT", this), null, null);
+				greaterThanItem.set(greaterThan.getValue());
+				popup.add(greaterThanItem);
+				MesquiteCheckMenuItem lessThanItem = new MesquiteCheckMenuItem("Less than", ownerModule, MesquiteModule.makeCommand("toggleLT", this), null, null);
+				lessThanItem.set(lessThan.getValue());
+				popup.add(lessThanItem);
+				popup.add(new MenuItem("-"));
+				MesquiteCheckMenuItem withinSelectionItem = new MesquiteCheckMenuItem("Within Existing Selection", ownerModule, MesquiteModule.makeCommand("toggleWithinSelection", this), null, null);
+				withinSelectionItem.set(withinExistingSelection.getValue());
+				popup.add(withinSelectionItem);
+				MesquiteCheckMenuItem notMatchingItem = new MesquiteCheckMenuItem("Choose Non-Matching", ownerModule, MesquiteModule.makeCommand("toggleNonMatching", this), null, null);
+				notMatchingItem.set(nonMatching.getValue());
+				popup.add(notMatchingItem);
+				MesquiteCheckMenuItem deselectWandTouchedItem = new MesquiteCheckMenuItem("Deselect rather than Select", ownerModule, MesquiteModule.makeCommand("toggleDeselectWandTouched", this), null, null);
+				deselectWandTouchedItem.set(deselectWandTouched.getValue());
+				popup.add(deselectWandTouchedItem);
+				popup.showPopup(x,y+6);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value equal to that in cell touched", "[on = selects equal; off]", commandName, "toggleEquals")) {
+			boolean current = equals.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			equals.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value greater than that in cell touched", "[on = selects greater than; off]", commandName, "toggleGT")) {
+			boolean current = greaterThan.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			greaterThan.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value less than that in cell touched", "[on = selects less than; off]", commandName, "toggleLT")) {
+			boolean current = lessThan.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			lessThan.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects within list items that are otherwise already selected", "[on = selects within; off]", commandName, "toggleWithinSelection")) {
+			boolean current = withinExistingSelection.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			withinExistingSelection.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects items that do NOT match that touched", "[on = selects non-matching; off]", commandName, "toggleNonMatching")) {
+			boolean current = nonMatching.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			nonMatching.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand deselects items rather than selects them", "[on = deselects; off]", commandName, "toggleDeselectWandTouched")) {
+			boolean current = deselectWandTouched.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			deselectWandTouched.toggleValue(ParseUtil.getFirstToken(arguments, io));
+		}
+		else if (checker.compare(this.getClass(), "Applies the magic wand tool to select like values", "[column touched] [row touched]", commandName, "wandTouch")) {
+			doWandTouch(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Sorts rows", "[column touched] [row touched]", commandName, "sortTouch")) {
+			if (!(getCurrentObject() instanceof Associable))
+				return null;
+			Associable assoc = (Associable)getCurrentObject();
+			MesquiteInteger io = new MesquiteInteger(0);
+			boolean gT = true;
+			if (arguments.indexOf("option")>=0)
+				gT = false;
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+			if (!MesquiteInteger.isCombinable(column) && !MesquiteInteger.isCombinable(row))
+				return null;
+			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED,assoc);
+			undoInstructions.recordPreviousOrder(assoc);
+			UndoReference undoReference = new UndoReference(undoInstructions, ownerModule);
+			if (column>=0 && row >=0) {
+				long[] fullChecksumBefore=null;
+				if (assoc instanceof CharacterData) {
+					fullChecksumBefore = ((CharacterData)assoc).getIDOrderedFullChecksum();
+					if (((CharacterData)assoc).isMolecularSequence())
+						if (!AlertDialog.query(this, "Sort Characters", "These are molecular sequences. Are you sure you want to reorder the sites?  It cannot be undone.", "Sort", "Cancel", 2))
+							return null;
+				}
+				
+				String[] text = new String[assoc.getNumberOfParts()];
+				for (int i=0; i<assoc.getNumberOfParts(); i++) {
+					text[i] = table.getMatrixText(column, i);
+				}
+
+				for (int i=1; i<assoc.getNumberOfParts(); i++) {
+					for (int j= i-1; j>=0 && compare(gT, text[j], text[j+1]); j--) {
+						swapParts(assoc, j, j+1, text);
+					}
+				}
+				
+				processPostSwap(assoc);
+				assoc.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+				if (assoc instanceof CharacterData){
+					long[] fullChecksumAfter = ((CharacterData)assoc).getIDOrderedFullChecksum();
+					((CharacterData)assoc).compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "sorting of characters");
+				}
+			}
+			else if (column == -1 && row >=0) { //row names selected; sort by name
+				long[] fullChecksumBefore=null;
+				if (assoc instanceof CharacterData) {
+					fullChecksumBefore = ((CharacterData)assoc).getIDOrderedFullChecksum();
+					if (((CharacterData)assoc).isMolecularSequence())
+						if (!AlertDialog.query(this, "Sort Characters", "Are you sure you want to reorder the sequences?  It cannot be undone.", "Sort", "Cancel", 2))
+							return null;
+				}
+				String[] text = new String[assoc.getNumberOfParts()];
+				for (int i=0; i<assoc.getNumberOfParts(); i++) {
+					text[i] = getRowNameForSorting(i);
+				}
+				for (int i=1; i<assoc.getNumberOfParts(); i++) {
+					for (int j= i-1; j>=0 && compare(gT, text[j], text[j+1]); j--) {
+						swapParts(assoc, j, j+1, text);
+					}
+				}
+				assoc.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+				if (assoc instanceof CharacterData){
+					long[] fullChecksumAfter = ((CharacterData)assoc).getIDOrderedFullChecksum();
+					((CharacterData)assoc).compareChecksums(fullChecksumBefore, fullChecksumAfter, true, "sorting of characters");
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deletes the selected rows", null, commandName, "deleteSelectedRows")) {
+			deleteSelectedRows(true);
+		}
+		else if (checker.compare(this.getClass(), "Moves the selected rows ", "[row to move after; -1 if at start]", commandName, "moveSelectedTo")) {
+			if (!owner.rowsMovable())
+				return null;
+			if (!table.anyRowSelected()){
+				owner.discreetAlert( "Sorry, to move " + owner.getItemTypeNamePlural() + " they must be selected first in the List window");
+				return null;
+			}
+			MesquiteInteger io = new MesquiteInteger(0);
+			int justAfter= MesquiteInteger.fromString(arguments, io);
+			if (!MesquiteInteger.isCombinable(justAfter))
+				justAfter = MesquiteInteger.queryInteger(this, "Move selected", "After which row should the selected rows be moved (enter 0 to move to first place)?", 0,  0, table.getNumRows()*10);
+			if (MesquiteInteger.isCombinable(justAfter))
+				table.selectedRowsDropped(justAfter-1); //-1 to convert to internal representation
+		}
+		else if (checker.compare(this.getClass(), "Adds rows (and their corresponding objects)", "[number of rows to add]", commandName, "addRows")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int num= MesquiteInteger.fromString(arguments, io);
+			int first = table.getNumRows();
+			if (!MesquiteInteger.isCombinable(num))
+				num = MesquiteInteger.queryInteger(this, "Add", "Add how many?", 1);
+			if (MesquiteInteger.isCombinable(num)){
+				addRows(num);
+				//					addRowsNotify(first, num);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects a row", "[number of row]", commandName, "selectRow")) { //TODO: should this use internal or external character numbers???
+			selectRow(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Selects a column", "[number of column]", commandName, "selectColumn")) {
+			selectColumn(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Hires a list assistant module", "[name of module]", commandName, "newAssistant")) {
+			ListAssistant assistant= (ListAssistant)ownerModule.hireNamedEmployee(owner.getAssistantClass(), arguments);
+			if (assistant!=null) {
+				assistant.setUseMenubar(false);
+				addListAssistant(assistant);
+				repaintAll();
+				ownerModule.resetContainingMenuBar();
+			}
+			else {
+				for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) { //if already hired then pass along commands
+					MesquiteModule e=(MesquiteModule)ownerModule.getEmployeeVector().elementAt(i);
+					if (e instanceof ListAssistant && owner.getAssistantClass() != null && owner.getAssistantClass().isAssignableFrom(e.getClass())) {
+						if (e.nameMatches(ParseUtil.getToken(arguments, new MesquiteInteger(0))) && !e.canHireMoreThanOnce())
+							return assistant;
+					}
+				}
+			}
+			return assistant;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	boolean compare(boolean greaterThan, String one, String two){
+		if (one == null || two == null)
+			return false;
+		double dOne = MesquiteDouble.fromString(one);
+		double dTwo = MesquiteDouble.fromString(two);
+		if (MesquiteDouble.isCombinable(dOne) && MesquiteDouble.isCombinable(dTwo)) {
+			if (greaterThan && (dTwo<dOne))
+				return true;
+			if (!greaterThan && (dTwo>dOne))
+				return true;
+			return false;
+		}
+		int order = collator.compare(one, two);
+		if ((order == 1 && greaterThan) ||(order == -1 && !greaterThan))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Swaps parts first and second*/
+	void swapParts(Associable assoc, int first, int second, String[] text){  
+		String temp = text[first];
+		text[first] = text[second];
+		text[second] = temp;
+		assoc.swapParts(first, second); 
+	}
+	public void processPostSwap(Associable assoc){
+	}
+	boolean satisfiesCriteria(String one, String two){
+		if (StringUtil.blank(one) && StringUtil.blank(two))
+			return true;
+		if (StringUtil.blank(one) || StringUtil.blank(two))
+			return false;
+		if (equals.getValue() && one.equals(two))
+			return true;
+		double dOne = MesquiteDouble.fromString(one);
+		double dTwo = MesquiteDouble.fromString(two);
+		if (MesquiteDouble.isCombinable(dOne) && MesquiteDouble.isCombinable(dTwo)) {
+			if (greaterThan.getValue() && (dTwo>dOne))
+				return true;
+			if (lessThan.getValue() && (dTwo<dOne))
+				return true;
+			return false;
+		}
+		int order = collator.compare(one, two);
+		if (greaterThan.getValue() && (order == -1))
+			return true;
+		if (lessThan.getValue() && (order == 1))
+			return true;
+		if (equals.getValue() && (order == 0))
+			return true;
+		return false;
+	}
+	public void addListAssistant(ListAssistant assistant) {
+		if (assistant !=null) {
+			assistant.setTableAndObject(table, getCurrentObject());
+			if (assistant.isDoomed() || ownerModule == null || ownerModule.getEmployeeVector().indexOf(assistant)<0)
+				return;
+			table.setNumColumns(table.getNumColumns()+1);
+			if (!table.columnAdjusted(table.getNumColumns()-1)) {
+				int w = assistant.getColumnWidth();
+				if (w==0) {
+					FontMetrics fm = table.getFontMetrics(table.getFont());
+					if (fm!=null)
+						w = fm.stringWidth(assistant.getWidestString());
+					else
+						w = 100;  // should something else be used as default?
+					w *= 1.5;
+				}
+				table.setColumnWidth(table.getNumColumns()-1, w);
+			}
+		}
+	}
+	public void reviewColumnNumber() {
+		ListAssistant assistant=null;
+		int column = 0;
+		for (int i=0; i< ownerModule.getNumberOfEmployees(); i++) {
+			Object obj =  ownerModule.getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				column++;
+			}
+		}
+
+		table.setNumColumns(column);
+		reviewColumnWidths();
+		table.repaintAll();
+
+
+	}
+	public void reviewColumnWidths() {
+		ListAssistant assistant=null;
+		int column = 0;
+		for (int i=0; i< ownerModule.getNumberOfEmployees(); i++) {
+			Object obj =  ownerModule.getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				if (!table.columnAdjusted(column)) {
+					assistant = (ListAssistant)obj;
+					int w = assistant.getColumnWidth();
+					if (w==0) {
+						FontMetrics fm = table.getFontMetrics(table.getFont());
+						w = fm.stringWidth(assistant.getWidestString()+table.getNameStartOffset()*2);
+					}
+					if (w!=table.getColumnWidth(column))
+						table.setColumnWidth(column, w);
+				}
+				column++;
+			}
+		}	
+	}
+	public ListAssistant findAssistant(int index) {
+		ListAssistant assistant=null;
+		int num=0;
+		if (ownerModule == null || ownerModule.getEmployeeVector() == null)
+			return null;
+		for (int i=0; i< ownerModule.getNumberOfEmployees(); i++) {
+			Object obj =  ownerModule.getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				if (num== index)
+					return (ListAssistant)obj;
+				num++;
+			}
+		}	
+		return null;
+	}
+
+	public int findAssistant(ListAssistant mb) {
+		int num=0;
+		for (int i=0; i< ownerModule.getNumberOfEmployees(); i++) {
+			Object obj =  ownerModule.getEmployeeVector().elementAt(i);
+			if (obj instanceof ListAssistant) {
+				if (mb == obj)
+					return num;
+				num++;
+			}
+		}	
+		return -1;
+	}
+	public void blankColumn(MesquiteModule mb){
+		if (mb instanceof ListAssistant) {
+			int which = findAssistant((ListAssistant)mb);
+			if (which>=0)
+				table.blankColumn(which);
+		}
+	}
+	public boolean rowHighlighted(int row) {
+		return false;
+	}
+	public void showSelectionPopup(Container cont, int x, int y) {
+	}
+	public void selectRow(int row) {
+		if (getCurrentObject() instanceof Associable){
+			((Associable)getCurrentObject()).setSelected(row, true);
+			((Associable)getCurrentObject()).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		}
+		else {
+			table.selectRow(row);
+		}
+	}
+
+	public boolean isRowSelected(int row){
+		return table.isRowSelected(row) || table.isRowNameSelected(row);  //note: new as of 2. 7 enough for row name to be selected!
+	}
+
+	public void selectColumn(int column) {
+		table.selectColumn(column);
+	}
+	/*.................................................................................................................*/
+	public void setCurrentTool(MesquiteTool tool){
+		super.setCurrentTool(tool);
+		if (tool.getEnabled())
+			if ((getCurrentTool()!=ibeamTool) && (table!=null))
+				table.offAllEdits();
+	}
+
+	public void focusInRow(int row){
+	}
+	/*.................................................................................................................*/
+	public boolean interceptCellTouch(int  column, int row, int modifiers){
+		return false;
+	}
+	public boolean interceptRowNameTouch(int row, int regionInCellH, int regionInCellV, int modifiers){
+		return false;
+	}
+	public void deleteSelectedColumns() {
+		int numSelected = 0;
+		for (int ic = table.getNumColumns()-1; ic>=0; ic--){
+			if (table.isColumnSelected(ic)) { 
+				numSelected++;
+			}
+		}
+		if (numSelected>0) {
+
+			int[] which = new int[numSelected];
+			int whichIs = 0;
+			for (int ic = table.getNumColumns()-1; ic>=0; ic--){
+				if (table.isColumnSelected(ic)) { //columns selected get deleted!
+					which[whichIs]=ic;
+					whichIs++;
+				}
+			}
+			for (int ic = 0; ic<numSelected; ic++){
+				table.deleteColumn(which[ic]);
+				ListAssistant assistant = findAssistant(which[ic]);
+				ownerModule.fireEmployee(assistant);
+			}
+			table.repaintAll();
+		}
+		else
+			ownerModule.alert("Columns must be selected before \"Hide\" command is given");
+	}
+
+	void moveSelectedColumns() {
+		int numSelected = 0;
+		for (int ic = table.getNumColumns()-1; ic>=0; ic--){
+			if (table.isColumnSelected(ic)) { 
+				numSelected++;
+			}
+		}
+		if (numSelected>0) {
+			String summary = "[Current columns: ";
+			for (int ic = 0; ic<table.getNumColumns(); ic++){
+				ListAssistant mb =findAssistant(ic);
+				mb.attachments.addElement(new MesquiteInteger("cwi", table.getColumnWidth(ic)), false);
+				mb.attachments.addElement(new MesquiteBoolean("cwb", table.columnAdjusted(ic)), false);
+				summary += " (" + (ic+1) + ") " + mb.getTitle() + ";";
+			}
+			summary += "]";
+
+			int whereToMove = MesquiteInteger.queryInteger(this, "Move column(s) where?", "Indicate the column after which the selected columns are to be moved.  If you want to move them to be the first columns, enter 0. " + summary, 0);  //1-based column number after which selected should be moved  
+			
+			
+			if (!MesquiteInteger.isCombinable(whereToMove))
+				return;
+			
+			selectedColumnsDropped(whereToMove, false);
+		}
+		else
+			ownerModule.alert("Columns must be selected before \"Move\" command is given");
+	}
+	void selectedColumnsDropped(int whereToMove, boolean mouseDrop){
+		if (!owner.rowsMovable())
+			return;
+		if (mouseDrop){
+			for (int ic = 0; ic<table.getNumColumns(); ic++){
+				ListAssistant mb =findAssistant(ic);
+				mb.attachments.addElement(new MesquiteInteger("cwi", table.getColumnWidth(ic)), false);
+				mb.attachments.addElement(new MesquiteBoolean("cwb", table.columnAdjusted(ic)), false);
+			}
+		}
+		int numSelected = 0;
+		for (int ic = table.getNumColumns()-1; ic>=0; ic--){
+			if (table.isColumnSelected(ic)) { 
+				numSelected++;
+			}
+		}
+		ListAssistant boundaryEmployee = null;  //this is the assistant after which the selected columns should be moved; if null then move to start
+		if (whereToMove>0) {
+			if (whereToMove >table.getNumColumns())
+				whereToMove = table.getNumColumns();
+
+			boundaryEmployee = findAssistant(whereToMove-1);
+		}
+
+
+		ListAssistant[] which = new ListAssistant[numSelected];
+		int count = 0;
+		for (int ic = 0; ic<table.getNumColumns(); ic++){
+			if (table.isColumnSelected(ic)) { //columns selected get deleted!
+				which[count++]=findAssistant(ic);
+			}
+		}
+		for (int ic = 0; ic<numSelected; ic++){
+			ListAssistant assistant = which[ic];
+			moveEmployeeAfter(assistant, boundaryEmployee);
+			boundaryEmployee = assistant;
+		}
+		for (int ic = 0; ic<table.getNumColumns(); ic++){
+			ListAssistant mb =findAssistant(ic);
+			MesquiteInteger cwi = (MesquiteInteger)mb.attachments.getElement("cwi");
+			MesquiteBoolean cwb = (MesquiteBoolean)mb.attachments.getElement("cwb");
+			if (cwi != null && cwb != null)
+				table.setColumnWidth(ic, cwi.getValue(), cwb.getValue());
+			if (cwi != null)
+				mb.attachments.removeElement(cwi, false);
+			if (cwb != null)
+				mb.attachments.removeElement(cwb, false);
+		}
+		table.deselectAllColumns(true);
+		for (int ic = 0; ic<numSelected; ic++){
+			int column = findAssistant(which[ic]);
+			table.selectColumns(column, column);
+		}
+		table.repaintAll();
+	}
+	void moveEmployeeAfter(ListAssistant toBeMoved, ListAssistant after){
+		//complex because want to keep column widths as is.  Thus, figure out 
+		ownerModule.moveEmployeeAfter(toBeMoved, after);
+	}
+	public void addRowsNotify(int first, int num) {
+	}
+
+	public void addRows(int num) {
+		MenuOwner.incrementMenuResetSuppression();
+		int count =0;
+		int currentNumRows = owner.getNumberOfRows();
+		UndoReference undoReference = null;
+		Associable assoc = (Associable)getCurrentObject();
+		if (assoc!=null) {
+			UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_ADDED, assoc);
+			assoc.resetJustAdded();
+			undoReference = new UndoReference(undoInstructions, null);
+		}
+
+		for (int ic = 0; ic<num; ic++){
+			if (owner.addRow())
+				count++;
+		}
+		table.setNumRows(currentNumRows+count);
+		Object obj = getCurrentObject();
+		if (obj instanceof Listenable)
+			((Listenable)obj).notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, undoReference));
+		table.repaintAll();
+
+		MenuOwner.decrementMenuResetSuppression();
+
+	}
+	public void deleteSelectedRows(boolean byCommand) {
+		int numSelected = 0;
+		for (int ic = table.getNumRows()-1; ic>=0; ic--){
+			if (table.isRowSelected(ic)) { 
+				numSelected++;
+			}
+		}
+		if (!byCommand && (table.editingAnything() || numSelected == 0))
+			return;
+		if (numSelected>0) {
+			String message;
+			if  (numSelected > 1)
+				message = "Are you sure you want to permanently delete " +  numSelected + " " + owner.getItemTypeNamePlural() + "?";
+			else
+				message = "Are you sure you want to permanently delete the selected " + owner.getItemTypeName() + "?";
+			if (!AlertDialog.query(this, "Delete?",message, "Yes", "No"))
+				return;
+			MenuOwner.incrementMenuResetSuppression();
+			if (ownerModule != null && ownerModule.getProject() != null)
+				ownerModule.getProject().incrementProjectWindowSuppression();
+			/*int[] which = new int[numSelected];
+			int howMany = 0;
+			for (int ic = table.getNumRows()-1; ic>=0; ic--){
+				if (table.isRowSelected(ic)) {
+		 			if (!owner.rowDeletable(ic)){
+			 			if (!MesquiteThread.isScripting())
+			 				owner.alert("Sorry, you can't delete that");
+			 		}
+			 		else {
+						which[howMany]=ic;
+						howMany++;
+					}
+				}
+			}
+			 */
+
+			int count =0;
+			int currentNumRows = owner.getNumberOfRows();
+			Object obj = getCurrentObject();
+
+			//NOTE: this code allows reporting of what contiguous blocks were deleted, but causes full recalculations for each discontiguity
+
+			int row = currentNumRows-1;
+			int firstInBlockDeleted = -1;
+			int lastInBlockDeleted = -1;
+			while(row>=0) {
+				if (table.isRowSelected(row) && owner.rowDeletable(row)){  // we've found a selected one
+					lastInBlockDeleted = row;
+					while(row>=0) {  // now let's look for the first non-selected one
+						if (table.isRowSelected(row) && owner.rowDeletable(row))
+							firstInBlockDeleted = row;
+						else break;
+						row--;
+					}
+					owner.aboutToDeleteRows(firstInBlockDeleted, lastInBlockDeleted, false);  // now prepare contiguous block for deletion
+				}
+				row--;
+			}
+			row = currentNumRows-1;
+			firstInBlockDeleted = -1;
+			lastInBlockDeleted = -1;
+			while(row>=0) {
+				if (table.isRowSelected(row) && owner.rowDeletable(row)){  // we've found a selected one
+					lastInBlockDeleted = row;
+					while(row>=0) {  // now let's look for the first non-selected one
+						if (table.isRowSelected(row) && owner.rowDeletable(row))
+							firstInBlockDeleted = row;
+						else break;
+						row--;
+					}
+					owner.deleteRows(firstInBlockDeleted, lastInBlockDeleted, false);  // now delete contiguous block
+					count += lastInBlockDeleted-firstInBlockDeleted+1;
+				}
+				row--;
+			}
+
+
+			/*				int firstInBlockDeleted = -1;
+				int lastInBlockDeleted = -1;
+				for (int ic = 0; ic<howMany; ic++){
+					if (lastInBlockDeleted < 0) {
+						lastInBlockDeleted = which[ic];
+						firstInBlockDeleted = lastInBlockDeleted;
+					}
+					else if (which[ic] == firstInBlockDeleted-1){ //still contiguous
+						firstInBlockDeleted = which[ic];					
+					}
+					else {
+						owner.deleteRows(firstInBlockDeleted, lastInBlockDeleted, false);
+						count += lastInBlockDeleted-firstInBlockDeleted+1;
+						lastInBlockDeleted = which[ic];
+						firstInBlockDeleted = lastInBlockDeleted;
+					}
+				}
+				if (lastInBlockDeleted>=0){
+					owner.deleteRows(firstInBlockDeleted, lastInBlockDeleted, false);
+					count += lastInBlockDeleted-firstInBlockDeleted+1;
+				}
+			 */
+
+			/*  old code pre-2. 02
+				int firstInBlockDeleted = -1;
+				for (int ic = 0; ic<howMany; ic++){
+					//NOTE: this code allows reporting of what contiguous blocks were deleted, but caused  full recalculations for each discontiguity
+					if (notifyInBlocks && obj instanceof Associable && firstInBlockDeleted < 0) {
+						firstInBlockDeleted = which[ic];
+					}
+			 		if (owner.deleteRow(which[ic], false))
+						count++;
+					//NOTE: this code allows reporting of what contiguous blocks were deleted, but caused  full recalculations for each discontiguity
+					if (notifyInBlocks && obj instanceof Associable && (ic+1 >= howMany || which[ic+1] != which[ic]-1)){ //next one is not adjacent; notify listeners
+						((Listenable)obj).notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED, new int[] {which[ic], firstInBlockDeleted - which[ic]+1}));
+						((Listenable)obj).decrementNotifySuppress();
+						((Listenable)obj).incrementNotifySuppress();
+						firstInBlockDeleted = -1;
+					}
+				}
+			 */
+
+			table.setNumRows(currentNumRows-count);
+			//NOTE: this code allows reporting of what contiguous blocks were deleted, but causes full recalculations for each discontiguity
+			notifyRowDeletion(obj);
+			table.repaintAll();
+			if (count>=0)
+				ownerModule.resetAllMenuBars();
+
+			if (ownerModule != null && ownerModule.getProject() != null)
+				ownerModule.getProject().decrementProjectWindowSuppression();
+			MenuOwner.decrementMenuResetSuppression();
+		}
+		else
+			ownerModule.alert("Rows must be selected before \"delete\" command is given");
+	}
+	public void notifyRowDeletion(Object obj){
+		if (obj instanceof Listenable) {
+			((Listenable)obj).notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+		}
+	}
+	public void setObject(Object object) {
+		setCurrentObject(object);
+		if (getCurrentObject() instanceof Associable)
+			table.setRowAssociable((Associable)getCurrentObject());
+		if (object instanceof Annotatable)
+			setDefaultAnnotatable((Annotatable)object);
+		ListAssistant assistant;
+		Enumeration enumeration=ownerModule.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof ListAssistant) {
+				assistant =  (ListAssistant)obj;
+				assistant.setTableAndObject(table, getCurrentObject());
+			}
+		}	
+		table.setNumRows(owner.getNumberOfRows());
+		table.repaintAll();
+	}
+
+	/*.................................................................................................................*/
+	public void windowResized() {
+		super.windowResized();
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		//if (true || (getHeight()!=windowHeight) || (getWidth()!=windowWidth)) {
+			windowHeight =getHeight();
+			windowWidth = getWidth();
+			if (table !=null)
+				table.setSize(windowWidth, windowHeight);
+	//	}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public String getTextContents() {
+		String text = owner.getTextContentsPreface();
+		text += "\n\n" + super.getTextContents();
+		return text;
+	}
+	/*.................................................................................................................*/
+	public MesquiteTable getTable() {
+		return table; 
+	}
+}
+
+
+
diff --git a/Source/mesquite/lists/lib/ListableVectorWindow.java b/Source/mesquite/lists/lib/ListableVectorWindow.java
new file mode 100644
index 0000000..9e51dd8
--- /dev/null
+++ b/Source/mesquite/lists/lib/ListableVectorWindow.java
@@ -0,0 +1,131 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class ListableVectorWindow extends ListWindow implements MesquiteListener {
+	ListableVector myVector;
+	ListModule listModule;
+	public ListableVectorWindow (ListModule ownerModule) {
+		super(ownerModule);
+		listModule = ownerModule;
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (listModule!=null)
+				setTitle(listModule.getItemTypeNamePlural()); 
+		else
+			setTitle(""); 
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return myVector;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof ListableVector) {
+			if (myVector!=null)
+				myVector.removeListener(this);
+			myVector = (ListableVector)obj;
+			myVector.addListener(this);
+		}
+	}
+	protected Listable getListable(int row){
+		if (myVector!=null) {
+			if (row>=0 && row<myVector.size())
+				return(Listable)myVector.elementAt(row);
+		}
+		return null;
+	}
+	public void setRowName(int row, String name){
+		Listable item = getListable(row);
+		if (item!=null && item instanceof Renamable){
+			((Renamable)item).setName(name);
+			if (listModule.resetMenusOnNameChange()){
+				resetAllTitles();
+				listModule.resetAllMenuBars();
+			}
+		}
+	}
+	public String getRowName(int row){
+		if (myVector!=null) {
+			Listable lR = getListable(row);
+			if (lR ==null)
+				return null;
+			return lR.getName();
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj ==myVector)
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (!disposing && obj instanceof ListableVector && (ListableVector)obj ==myVector) {
+			if (code==MesquiteListener.NAMES_CHANGED) {
+				getTable().redrawRowNames();
+			}
+			else if (code==MesquiteListener.SELECTION_CHANGED) {
+				getTable().synchronizeRowSelection(myVector);
+				getTable().repaintAll();
+			}
+			else if (code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_MOVED || code==MesquiteListener.PARTS_CHANGED) {
+				getTable().setNumRows(myVector.size());
+				getTable().synchronizeRowSelection(myVector);
+				getTable().repaintAll();
+			}
+			else if (code!=MesquiteListener.ANNOTATION_CHANGED && code!=MesquiteListener.ANNOTATION_ADDED && code!=MesquiteListener.ANNOTATION_DELETED) {
+				getTable().synchronizeRowSelection(myVector);
+				getTable().repaintAll();
+			}
+		}
+		else
+			super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	public void dispose(){
+		myVector.removeListener(this);
+		super.dispose();
+	}
+	
+}
+
+
+
+
diff --git a/Source/mesquite/lists/lib/ModelSetListAsst.java b/Source/mesquite/lists/lib/ModelSetListAsst.java
new file mode 100644
index 0000000..bfb26c3
--- /dev/null
+++ b/Source/mesquite/lists/lib/ModelSetListAsst.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class ModelSetListAsst extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return ModelSetListAsst.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Model set list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/ModelsListAssistant.java b/Source/mesquite/lists/lib/ModelsListAssistant.java
new file mode 100644
index 0000000..63928ab
--- /dev/null
+++ b/Source/mesquite/lists/lib/ModelsListAssistant.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class ModelsListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return ModelsListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Models list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaBlocksListAssistant.java b/Source/mesquite/lists/lib/TaxaBlocksListAssistant.java
new file mode 100644
index 0000000..434633a
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaBlocksListAssistant.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class TaxaBlocksListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaBlocksListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa blocks list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaBlocksListUtility.java b/Source/mesquite/lists/lib/TaxaBlocksListUtility.java
new file mode 100644
index 0000000..8042aee
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaBlocksListUtility.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class TaxaBlocksListUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaBlocksListUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa blocks list utility";
+   	 }
+
+   	/** if returns true, then requests to remain on even after operateOnTaxas is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the taxa blocks.  Returns true if taxa altered*/
+   	public abstract boolean operateOnTaxas(ListableVector taxa);
+}
+
diff --git a/Source/mesquite/lists/lib/TaxaListAssistantI.java b/Source/mesquite/lists/lib/TaxaListAssistantI.java
new file mode 100644
index 0000000..84dab9b
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaListAssistantI.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+/**This is superclass of modules to assist tables with taxa (e.g., taxa List, data matrix editor).  
+These are INITs.*/
+
+public abstract class TaxaListAssistantI extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaListAssistantI.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "INIT Assistant for Taxon List";
+   	}
+
+  	/** method called by list window to inform assistant that taxa have changed*/
+	public abstract void setTableAndTaxa(MesquiteTable table, Taxa taxa);
+	
+	public void focusInRow(int row){
+	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaListPartitionUtil.java b/Source/mesquite/lists/lib/TaxaListPartitionUtil.java
new file mode 100644
index 0000000..ba4a48b
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaListPartitionUtil.java
@@ -0,0 +1,43 @@
+package mesquite.lists.lib;
+
+import java.awt.Color;
+
+import mesquite.lib.MesquiteFile;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteSymbol;
+import mesquite.lib.StringUtil;
+import mesquite.lib.TaxaGroup;
+
+public class TaxaListPartitionUtil {
+
+	/*.................................................................................................................*/
+	public  static TaxaGroup createNewTaxonGroup(MesquiteModule module, MesquiteFile file) {
+		String n = "Untitled Group";
+		if (file==null)
+			return null;
+		n = file.getFileElements().getUniqueName(n);
+		GroupDialog d = new GroupDialog(module.getProject(),module.containerOfModule(), "New Taxon Group", n, Color.white, null, TaxaGroup.supportsSymbols());
+		d.completeAndShowDialog();
+		String name = d.getName();
+		boolean ok = d.query()==0;
+		Color c = d.getColor();
+		MesquiteSymbol symbol = d.getSymbol();
+
+		d.dispose();
+		if (!ok)
+			return null;
+		//String name = MesquiteString.queryString(containerOfModule(), "New character group", "New character group label", "Untitled Group");
+		if (StringUtil.blank(name))
+			return null;
+		TaxaGroup group = new TaxaGroup();
+		group.setName(name);
+		if (symbol!=null)
+			group.setSymbol(symbol);
+		group.addToFile(file, file.getProject(), null);
+		if (c!=null) {
+			group.setColor(c);
+		}
+		return group;
+	}
+
+}
diff --git a/Source/mesquite/lists/lib/TaxaPartListAssistant.java b/Source/mesquite/lists/lib/TaxaPartListAssistant.java
new file mode 100644
index 0000000..b43219b
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaPartListAssistant.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class TaxaPartListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaPartListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa partitions list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaSetListAssistant.java b/Source/mesquite/lists/lib/TaxaSetListAssistant.java
new file mode 100644
index 0000000..09c5c47
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaSetListAssistant.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public abstract class TaxaSetListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxaSetListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxa set list assistant";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaSpecsListWindow.java b/Source/mesquite/lists/lib/TaxaSpecsListWindow.java
new file mode 100644
index 0000000..6d59c58
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaSpecsListWindow.java
@@ -0,0 +1,136 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+public class TaxaSpecsListWindow extends ListWindow implements MesquiteListener {
+	private Taxa taxa = null;
+	SpecsSetVector ssv;
+	public TaxaSpecsListWindow (TaxaSpecssetList ownerModule, Taxa taxa) {
+		super(ownerModule); //INFOBAR
+		if (taxa==null) {
+			ownerModule.alert("Sorry, a list window failed because the taxa block was not found");
+			ownerModule.iQuit();
+			return;
+		}
+		this.taxa = taxa;
+		checkSSV();
+		setCurrentObject(taxa);
+		taxa.addListener(this);
+	}
+	
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (taxa!=null)
+			setTitle(((TaxaSpecssetList)ownerModule).getItemTypeNamePlural() + " of " + taxa.getName() ); //TODO: file???
+		else if (taxa==null)
+			setTitle(((TaxaSpecssetList)ownerModule).getItemTypeNamePlural() + " (taxa NULL)" ); 
+		
+	}
+	/*.................................................................................................................*/
+	public Object getCurrentObject(){
+		return taxa;
+	}
+	public void setCurrentObject(Object obj){
+		if (obj instanceof Taxa) {
+			taxa = (Taxa)obj;
+			resetTitle();
+		}
+	}
+	public void setRowName(int row, String name){
+		if (taxa!=null) {
+			SpecsSet ss = taxa.getSpecsSet(row, ((TaxaSpecssetList)ownerModule).getItemType());
+			if (ss!=null)
+				ss.setName(name);
+		}
+	}
+	public boolean rowHighlighted(int row) {
+		//SpecsSetVector ssv = taxa.getSpecSetsVector(((TaxaSpecssetList)ownerModule).getItemType());
+		//if (ssv!=null)
+		//	return ssv.indexOfCurrent()==row;
+		return false;
+	}
+	void checkSSV(){
+		if (taxa==null || ownerModule == null)
+			return;
+		SpecsSetVector ssvNow = taxa.getSpecSetsVector(((TaxaSpecssetList)ownerModule).getItemType());
+		if (ssv != ssvNow) {
+			if (ssv!=null)
+				ssv.removeListener(this);
+			ssv =ssvNow;
+			if (ssv!=null) {
+				ssv.addListener(this);
+			}
+		}
+	}
+	public String getRowName(int row){
+		if (taxa!=null) {
+			checkSSV();
+			SpecsSet ss = taxa.getSpecsSet(row, ((TaxaSpecssetList)ownerModule).getItemType());
+			if (ss!=null)
+				return ss.getName();
+			return null;
+		}
+		else
+			return null;
+	}
+	public String getRowNameForSorting(int row){
+		return getRowName(row);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (ownerModule!=null && (obj ==  taxa))
+			ownerModule.windowGoAway(this);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj ==taxa) {
+			if (Notification.appearsCosmetic(notification))
+				return;
+			checkSSV();
+			if (ownerModule instanceof ListModule)
+				table.setNumRows(((ListModule)ownerModule).getNumberOfRows());
+			table.repaintAll();
+			//fundamental change in taxa (only need to revise number of rows etc; employees will take care of taxa themselves
+		}
+		else if (obj instanceof SpecsSetVector && (SpecsSetVector)obj ==ssv){
+			checkSSV();
+			if (ownerModule instanceof ListModule)
+				table.setNumRows(((ListModule)ownerModule).getNumberOfRows());
+			table.repaintAll();
+		}
+		super.changed(caller, obj, notification);
+	}
+	
+	
+}
+
+
diff --git a/Source/mesquite/lists/lib/TaxaSpecssetList.java b/Source/mesquite/lists/lib/TaxaSpecssetList.java
new file mode 100644
index 0000000..589897c
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxaSpecssetList.java
@@ -0,0 +1,247 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import mesquite.lib.characters.ProbabilityModelSet;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class TaxaSpecssetList extends ListModule {
+	public Taxa taxa = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//windows = new Vector();
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public boolean showing(Object obj){
+	 	if (obj instanceof String) {
+    	 		String arguments = (String)obj;
+    	 		Taxa queryTaxa = getProject().getTaxa(null, parser.getFirstToken(arguments));
+    	 		return (queryTaxa == taxa && getModuleWindow()!=null);
+	 	}
+	 	else if (obj instanceof Taxa) {
+    	 		return (obj == taxa && getModuleWindow()!=null);
+	 	}
+	 	return false;
+  	 }
+  	 
+	public abstract SpecsSet makeNewSpecsSet(Taxa taxa);
+	/*.................................................................................................................*/
+  	 public void showListWindow(Object obj){ ///TODO: change name to makeLIstWindow
+	 	if (obj instanceof Taxa) {
+			taxa = (Taxa)obj;
+	 	}
+ 		if (taxa==null){
+ 			alert("Sorry, no taxa set found for list window");
+ 			iQuit();
+  			return;
+ 		}
+ 		taxa.addListener(this);
+ 		setModuleWindow(new TaxaSpecsListWindow(this, taxa));
+
+		addMenuItem("Store current set", makeCommand("storeCurrent",  this));
+		addMenuItem("Set stored to current", makeCommand("setToCurrent",  this));
+		addMenuItem("Replace stored set by current", makeCommand("replaceWithCurrent",  this));
+ 		addMenuItem( "-", null);
+ 		resetContainingMenuBar();
+		resetAllWindowsMenus();
+  	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (taxa== obj) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (taxa!=null) {
+				taxa.removeListener(this);
+			}
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/* following required by ListModule*/
+  	 public Object getMainObject(){
+  	 	return taxa;
+  	 }
+  	 public int getNumberOfRows(){
+  	 	if (taxa==null)
+  	 		return 0;
+  	 	else
+  	 		return taxa.getNumSpecsSets(getItemType());
+  	 }
+	public Class getAssistantClass(){
+		return null;//return CharListAssistant.class;
+	}
+	public abstract Class getItemType();
+	/*.................................................................................................................*/
+	public boolean rowsDeletable(){
+		return true;
+	}
+	public boolean deleteRow(int row, boolean notify){
+		if (taxa!=null) {
+			SpecsSet ss = taxa.getSpecsSet(row, getItemType());
+			if (ss!=null) {
+				taxa.removeSpecsSet(ss,getItemType());
+				return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	if (getModuleWindow()==null || !getModuleWindow().isVisible())
+   	 		return null;
+   	 	Snapshot temp = new Snapshot();
+		
+
+  	 	temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa)); 
+  	 	
+      	 	if (getModuleWindow()!=null)
+			getModuleWindow().incorporateSnapshot(temp, file);
+  	 	//if (window!=null && !window.isVisible())
+  	 	temp.addLine("showWindow"); 
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the taxa block", "[block reference, number, or name]", commandName, "setTaxa")) {
+   	 		Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+   	 		if (getModuleWindow()!=null && t!=null){
+	   	 		//if (taxa!=null)
+	   	 		//	taxa.removeListener(this);
+	   	 		taxa = t;
+	   	 		//if (taxa!=null)
+	   	 		//	taxa.addListener(this);
+    	 			((ListWindow)getModuleWindow()).setCurrentObject(taxa);
+    	 			((ListWindow)getModuleWindow()).repaintAll();
+	   	 		return taxa;
+   	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current taxa block", null, commandName, "getTaxa")) {
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Stores the current specification set", null, commandName, "storeCurrent")) {
+    	 		if (taxa!=null){
+    	 			SpecsSetVector ssv = taxa.getSpecSetsVector(getItemType());
+    	 			if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+			 		SpecsSet specsSet= makeNewSpecsSet(taxa);
+			 		specsSet.addToFile(taxa.getFile(), getProject(), findElementManager(getItemType())); 
+					taxa.setCurrentSpecsSet(specsSet, getItemType());
+					ssv = taxa.getSpecSetsVector(getItemType());
+    	 			}
+    	 			if (ssv!=null) {
+    	 				SpecsSet s = ssv.storeCurrentSpecsSet();
+    					if (s.getFile() == null)
+    						s.addToFile(taxa.getFile(), getProject(), findElementManager(getItemType()));
+   	 				if (s!=null)
+    	 					s.setName(ssv.getUniqueName(getItemTypeName()));
+    	 				else
+    	 					alert("Error: could not make " + getItemTypeName());
+    	 				ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+    	 				//MesquiteTable t = ((ListWindow)getModuleWindow()).getTable(); //handled via listeners
+    	 				//t.setNumRows(t.getNumRows()+1);
+    	 				//t.repaintAll();
+    	 			}
+     	 			else MesquiteMessage.warnProgrammer("storeCurrent in DataSpecs: sorry, can't store because no specssetvector");
+   	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Replaces a stored character specification set by the current one", null, commandName, "replaceWithCurrent")) {
+    	 		if (taxa!=null){
+    	 			MesquiteTable t = ((ListWindow)getModuleWindow()).getTable();
+    	 			int numRows = t.numRowsSelected();
+    	 			if (numRows>1) 
+    	 				alert("Exactly one row must be selected to indicate which stored " + getItemTypeName() + " is to be replaced by the current one");
+    	 			else  {
+    	 				SpecsSetVector ssv = taxa.getSpecSetsVector(getItemType());
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen;
+	  	 				if (numRows==0)
+    	 						chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored " + getItemTypeName() + " to replace by current set", MesquiteString.helpString,ssv, 0);
+	    	 				else {
+	    	 					int f = t.firstRowSelected();
+		    	 				if (f<0)
+		    	 					return null;
+		    	 				chosen = ssv.getSpecsSet(f);
+		    	 			}
+		    	 			if (chosen!=null){
+		    	 				SpecsSet current = ssv.getCurrentSpecsSet();
+		    	 				ssv.replaceStoredSpecsSet(chosen, current);
+		    	 				t.repaintAll();
+		    	 			}
+	    	 			}
+    	 			}
+    	 		}
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the selected specification set to be the current one", null, commandName, "setToCurrent")) {
+    	 		if (taxa!=null){
+    	 			MesquiteTable t = ((ListWindow)getModuleWindow()).getTable();
+    	 			int numRows = t.numRowsSelected();
+    	 			if (numRows>1) 
+    	 				alert("Exactly one row must be selected to indicate which stored " + getItemTypeName() + " is to be set as the current one");
+    	 			else  {
+    	 				SpecsSetVector ssv = taxa.getSpecSetsVector(getItemType());
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen;
+	  	 				if (numRows==0)
+    	 						chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Set to current", "Choose which stored " + getItemTypeName() + " is to be set as the current one",MesquiteString.helpString, ssv, 0);
+	    	 				else {
+	    	 					int f = t.firstRowSelected();
+		    	 				if (f<0)
+		    	 					return null;
+		    	 				chosen = ssv.getSpecsSet(f);
+		    	 			}
+		    	 			if (chosen!=null){
+		    	 				ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+		    	 				taxa.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not taxa???
+    	 						t.repaintAll();
+		    	 				return chosen;
+		    	 			}
+	    	 			}
+    	 			}
+    	 		}
+    	 		return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+ 			//Debug.println("disposing of window");
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+	}
+   	 
+   	 
+}
+
+
+
diff --git a/Source/mesquite/lists/lib/TaxonGroupListAssistant.java b/Source/mesquite/lists/lib/TaxonGroupListAssistant.java
new file mode 100644
index 0000000..9c8ef1a
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxonGroupListAssistant.java
@@ -0,0 +1,15 @@
+package mesquite.lists.lib;
+
+
+/* ======================================================================== */
+public abstract class TaxonGroupListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxonGroupListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon group list assistant";
+   	 }
+
+}
+
diff --git a/Source/mesquite/lists/lib/TaxonListAssistant.java b/Source/mesquite/lists/lib/TaxonListAssistant.java
new file mode 100644
index 0000000..c18c3f0
--- /dev/null
+++ b/Source/mesquite/lists/lib/TaxonListAssistant.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+
+/* ======================================================================== */
+/**Supplies a column for a taxa list window.*/
+
+public abstract class TaxonListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TaxonListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Taxon list assistant";
+   	 }
+
+	public abstract void setTableAndTaxa(MesquiteTable table, Taxa taxa);
+	public abstract String getStringForTaxon(int it);
+	public abstract String getWidestString();
+	public abstract String getTitle();
+	public void setTableAndObject(MesquiteTable table, Object object){
+		setTableAndTaxa(table, (Taxa)object);
+	}
+	public String getStringForRow(int ic){
+		try {
+			return getStringForTaxon(ic);
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+}
+
+
diff --git a/Source/mesquite/lists/lib/TreeBlockListUtility.java b/Source/mesquite/lists/lib/TreeBlockListUtility.java
new file mode 100644
index 0000000..7172cd8
--- /dev/null
+++ b/Source/mesquite/lists/lib/TreeBlockListUtility.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public abstract class TreeBlockListUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeBlockListUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree block list utility";
+   	 }
+
+   	/** if returns true, then requests to remain on even after operateOnTrees is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the tree blocks.  Returns true if tree blocks altered*/
+   	public abstract boolean operateOnTreeBlocks(TreeVector[] blocks);
+}
+
diff --git a/Source/mesquite/lists/lib/TreeListAssistant.java b/Source/mesquite/lists/lib/TreeListAssistant.java
new file mode 100644
index 0000000..5729c9c
--- /dev/null
+++ b/Source/mesquite/lists/lib/TreeListAssistant.java
@@ -0,0 +1,52 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class TreeListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree list assistant";
+   	 }
+
+	public abstract void setTableAndTreeBlock(MesquiteTable table, TreeVector trees);
+	
+	public String getStringForTree(int ic){
+		return null;
+	}
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	}
+	public void setTableAndObject(MesquiteTable table, Object object){
+		if (object instanceof TreeVector)
+			setTableAndTreeBlock(table, (TreeVector)object);
+	}
+	public String getStringForRow(int ic){
+		try{
+			return getStringForTree(ic);
+		}
+		catch (NullPointerException e){}
+		return "";
+	}
+}
+
diff --git a/Source/mesquite/lists/lib/TreeListInit.java b/Source/mesquite/lists/lib/TreeListInit.java
new file mode 100644
index 0000000..ab0fc5f
--- /dev/null
+++ b/Source/mesquite/lists/lib/TreeListInit.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public abstract class TreeListInit extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeListInit.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree list INIT";
+   	 }
+
+	public abstract void setTableAndTreeBlock(MesquiteTable table, TreeVector trees);
+	
+}
+
diff --git a/Source/mesquite/lists/lib/TreeListUtility.java b/Source/mesquite/lists/lib/TreeListUtility.java
new file mode 100644
index 0000000..37b2e23
--- /dev/null
+++ b/Source/mesquite/lists/lib/TreeListUtility.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public abstract class TreeListUtility extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeListUtility.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree list utility";
+   	 }
+	 public String getFunctionIconPath(){
+   		 return getRootImageDirectoryPath() + "functionIcons/treeWindowUtil.gif";
+   	 }
+   	/** if returns true, then requests to remain on even after operateOnTrees is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the trees in the block.  Returns true if trees altered*/
+   	public abstract boolean operateOnTrees(TreeVector trees);
+}
+
diff --git a/Source/mesquite/lists/lib/TreeblocksListAssistant.java b/Source/mesquite/lists/lib/TreeblocksListAssistant.java
new file mode 100644
index 0000000..ad745df
--- /dev/null
+++ b/Source/mesquite/lists/lib/TreeblocksListAssistant.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.lists.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class TreeblocksListAssistant extends ListAssistant  {
+
+   	 public Class getDutyClass() {
+   	 	return TreeblocksListAssistant.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Tree blocks list assistant";
+   	 }
+
+	public void drawInCell(int ic, Graphics g, int x, int y,  int w, int h, boolean selected){
+	}
+}
+
+
+
diff --git a/Source/mesquite/mb/BestBayesTree/BestBayesTree.java b/Source/mesquite/mb/BestBayesTree/BestBayesTree.java
new file mode 100644
index 0000000..306daa1
--- /dev/null
+++ b/Source/mesquite/mb/BestBayesTree/BestBayesTree.java
@@ -0,0 +1,177 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.mb.BestBayesTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies trees from tree blocks in a file.  Reads trees only when needed; hence suitable for files with too many trees to be held in memory at once, but slower than StoredTrees.*/
+public class BestBayesTree extends TreeSource implements MesquiteListener {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.trees.ManyTreesFromFile.ManyTreesFromFile.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	/*.................................................................................................................*/
+	int bestTree = -1;
+	String scoresPath = null;
+	boolean loaded = false;
+	String treename = null;
+	TreeSource treeSource;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeSource = (TreeSource)hireNamedEmployee(TreeSource.class, "#ManyTreesFromFile");
+		if (!MesquiteThread.isScripting())
+			scoresPath = obtainPath();
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 private String obtainPath(){
+ 		MainThread.incrementSuppressWaitWindow();
+		 alert("In the following dialog, choose the \".p\" (scores & parameters) file from MrBayes.  Its associated .t file with trees must be in its same directory and otherwise with the same name.");
+  		MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), "Choose scores file", FileDialog.LOAD);
+			fdlg.setResizable(true);
+			fdlg.setVisible(true);
+				String fName=fdlg.getFile();
+			String dName =fdlg.getDirectory();
+			// fdlg.dispose();
+			MainThread.decrementSuppressWaitWindow();
+			return dName + fName;
+  	 }
+  	 private double loadFile(){ 
+  	 	bestTree = -1;
+  	 	if (scoresPath == null)
+  	 		return MesquiteDouble.unassigned;
+  	 	
+		String[] lines = MesquiteFile.getFileContentsAsStrings(scoresPath);
+		if (lines == null)
+			return MesquiteDouble.unassigned;
+		MesquiteInteger pos = new MesquiteInteger();
+		double bestValue = -10000000000000000000.0;
+		for (int i= 2; i< lines.length; i++){
+			CommandRecord.tick("examining scores file line " + i);
+			pos.setValue(0);
+			int tree = MesquiteInteger.fromString(lines[i], pos);
+			double score = MesquiteDouble.fromString(lines[i], pos);
+			if (score > bestValue) {
+				bestValue = score;
+				bestTree = i-3;
+			}
+		}
+		StringBuffer treeFile = new StringBuffer(scoresPath);
+		treeFile.setCharAt(scoresPath.length()-1, 't');
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		MesquiteThread.setCurrentCommandRecord(new CommandRecord(true));
+		treeSource.doCommand("setFilePath", StringUtil.tokenize(treeFile.toString()), CommandChecker.defaultChecker);
+		MesquiteThread.setCurrentCommandRecord(cr);
+		loaded = true;
+  	 	return bestValue;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets path to scores file", null, commandName, "setScoresPath")) {
+    	 		scoresPath = parser.getFirstToken(arguments);
+    	 		loaded = false;
+    	 		if (scoresPath != null)
+    	 			scoresPath = MesquiteFile.composePath(getProject().getHomeDirectoryName(), scoresPath);
+    	 		parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+	return null;
+   	 }
+
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa) {
+  	}
+	/*.................................................................................................................*/
+  	public void initialize(Taxa taxa) {
+  	//	checkTreeBlock(taxa);
+  	}
+  	
+	/*.................................................................................................................*/
+   	public Tree getCurrentTree(Taxa taxa) {
+		double bestValue =  MesquiteDouble.unassigned;
+		if (!loaded)
+			bestValue = loadFile();
+		if (bestTree>0){
+			Tree t = treeSource.getTree(taxa, bestTree);
+			if (t instanceof Attachable){
+				double d = bestValue;
+				if (MesquiteDouble.isCombinable(d)){
+					MesquiteDouble s = new MesquiteDouble(-d);
+					s.setName("MrBayesScore");
+					((Attachable)t).attachIfUniqueName(s);
+				}
+			}
+			return t;
+		}
+   		return null;
+   	}
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int itree) {
+  		return getCurrentTree(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+		return 1; 
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return treename;
+   	}
+	/*.................................................................................................................*/
+   	public String getCurrentTreeNameString(Taxa taxa) {
+   		return treename;
+   	}
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "MrBayes Max. A-Post. Tree";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies tree from MrBayes with highest posterior probability (MAP tree).";
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Trees obtained from file " + scoresPath;
+   	}
+}
+
+
diff --git a/Source/mesquite/mb/ExportForMrBayes/ExportForMrBayes.java b/Source/mesquite/mb/ExportForMrBayes/ExportForMrBayes.java
new file mode 100644
index 0000000..d1c0fc6
--- /dev/null
+++ b/Source/mesquite/mb/ExportForMrBayes/ExportForMrBayes.java
@@ -0,0 +1,68 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.mb.ExportForMrBayes;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.mb.lib.*;
+
+
+
+public class ExportForMrBayes extends ExportForMrBayesLib {
+
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public  String getProgramName(){
+		return "MrBayes";
+	}
+
+	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	public int getVersionOfFirstRelease(){
+    		return 110;  
+    	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Export NEXUS for MrBayes";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Exports NEXUS files for use by MrBayes." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/mb/MrBayesScore/MrBayesScore.java b/Source/mesquite/mb/MrBayesScore/MrBayesScore.java
new file mode 100755
index 0000000..031bf04
--- /dev/null
+++ b/Source/mesquite/mb/MrBayesScore/MrBayesScore.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.mb.MrBayesScore;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* 
+ * Walks a Mesquite tree and calculates the number of taxa in it.
+ */
+
+public class MrBayesScore extends NumberForTree {
+
+    /* ................................................................................................................. */
+
+    public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+        return true;
+    }
+
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+
+    /* ................................................................................................................. */
+      public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+        if (result == null || tree == null)
+            return;
+	   	clearResultAndLastResult(result);
+       if (tree instanceof Attachable){
+        	Object obj = ((Attachable)tree).getAttachment("MrBayesScore");
+        	if (obj == null){
+        			if (resultString != null)
+        				resultString.setValue("No MrBayes score is associated with this tree.  To obtain a score, use as tree source \"Trees from MrBayes\".");
+        			return;
+        	}
+        	if (obj instanceof MesquiteDouble)
+        			result.setValue(((MesquiteDouble)obj).getValue());
+			else if (obj instanceof MesquiteNumber)
+				result.setValue((MesquiteNumber)obj);
+        }
+       
+        if (resultString != null) {
+            resultString.setValue("MrBayes score : " + result.toString());
+        }
+		saveLastResult(result);
+		saveLastResultString(resultString);
+      }
+
+  	/*.................................................................................................................*/
+   	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+   	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+   	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+      	public int getVersionOfFirstRelease(){
+      		return 110;  
+      	}
+  /* ................................................................................................................. */
+    /** Explains what the module does. */
+
+    public String getExplanation() {
+        return "Supplies posterior probability score from MrBayes";
+    }
+
+    /* ................................................................................................................. */
+    /** Name of module */
+    public String getName() {
+        return "MrBayes Score";
+    }
+}
diff --git a/Source/mesquite/mb/SimplifyTaxonNames/SimplifyTaxonNames.java b/Source/mesquite/mb/SimplifyTaxonNames/SimplifyTaxonNames.java
new file mode 100644
index 0000000..a0af0fa
--- /dev/null
+++ b/Source/mesquite/mb/SimplifyTaxonNames/SimplifyTaxonNames.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.mb.SimplifyTaxonNames;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class SimplifyTaxonNames extends TaxonNameAlterer {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	/** A stub method for doing any necessary cleanup after taxon names have been altered.*/
+   	public void cleanupAfterAlterTaxonNames(){
+    	}
+	/*.................................................................................................................*/
+   	/** Called to alter the taxon name in a single cell.  If you use the alterContentOfCells method of this class, 
+   	then you must supply a real method for this, not just this stub. */
+   	public boolean alterName(Taxa taxa, int it){
+//		String s=StringUtil.deletePunctuationAndSpaces(name);
+ 		boolean nameChanged = false;
+		String name = taxa.getTaxonName(it);
+		if (name!=null){
+			String modifiedName = StringUtil.simplifyIfNeededForOutput(name,true, true);
+			if (!modifiedName.equalsIgnoreCase(name)) {
+				taxa.setTaxonName(it, modifiedName, false);
+				nameChanged = true;
+			}
+		}
+		return nameChanged;
+   	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Simplifies taxon names", "[length]", commandName, "simplify")) {
+	   	 		if (taxa !=null){
+	   	 			alterTaxonNames(taxa,table);
+	   	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simplify Taxon Names";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Simplifies taxon names so that they will work with MrBayes, RAxML, etc..";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 273;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+
+}
+
+
+	
+
diff --git a/Source/mesquite/mb/TreesFromMrBayes/TreesFromMrBayes.java b/Source/mesquite/mb/TreesFromMrBayes/TreesFromMrBayes.java
new file mode 100644
index 0000000..5677aa8
--- /dev/null
+++ b/Source/mesquite/mb/TreesFromMrBayes/TreesFromMrBayes.java
@@ -0,0 +1,334 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.mb.TreesFromMrBayes;
+/*~~  */
+
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class TreesFromMrBayes extends TreeSource implements MesquiteListener {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.trees.ManyTreesFromFile.ManyTreesFromFile.class, getName() + "  needs a source of trees.",
+		"The source of trees is arranged initially");
+	}
+	TreeSource treeSource;
+	MesquiteFile file = null;
+	LongArray filePos;
+	DoubleArray scores;
+	MesquiteBoolean showLast;
+	int highestSuccessfulTree = -1;
+	int burnInIgnore = 0;
+	double burnInFraction = 0.0;
+	boolean ignoreEPC = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		filePos = new LongArray(100, 100);
+		scores = new DoubleArray(100, 100);
+		if (!MesquiteThread.isScripting()) 
+			alert("\"" + getName() + "\" is a special source of trees that reads from a MrBayes trees file.  Please select the \".t\" file from MrBayes.  For the MrBayes scores to be used subsequently, the associated .p file with parameters and scores MUST be in the same directory as the .t file and otherwise with the same name.");
+		treeSource = (TreeSource)hireNamedEmployee(TreeSource.class, "#ManyTreesFromFile");
+		if (treeSource==null)
+			return sorry(getName() + " couldn't start because no source of trees was obtained.");		
+		ignoreEPC = true;
+		treeSource.doCommand("toggleReread", "off", CommandChecker.defaultChecker);
+		ignoreEPC = false;
+		showLast = new MesquiteBoolean(false);
+		addMenuItem("Ignore MCMC Burn-in...", makeCommand("ignoreBurnIn",  this));
+		addCheckMenuItem( null, "Show Last MCMC Tree Only", makeCommand("toggleShowLast",  this), showLast);
+		if (!MesquiteThread.isScripting()){
+			int newBurn= MesquiteInteger.queryInteger(containerOfModule(), "Number of trees to ignore as burn-in", "Ignore:", burnInIgnore);
+			if (newBurn>=0 && MesquiteInteger.isCombinable(newBurn)) 
+				burnInIgnore = newBurn;
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (this.file == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("ignoreBurnIn " + burnInIgnore);  
+		temp.addLine("toggleShowLast " + showLast.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*
+ 	public boolean queryBurnin() {
+ 		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+ 		ExtensibleDialog queryFilesDialog = new ExtensibleDialog(containerOfModule(), "Burn-in Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+ 		queryFilesDialog.addLabel("MrBayes Trees Burn-in");
+
+ 		IntegerField burnInIgnoreField = queryFilesDialog.addIntegerField("Number of trees to ignore as burn-in", burnInIgnore, 8, 0, MesquiteInteger.infinite);
+		DoubleField burnInFractionField = queryFilesDialog.addDoubleField("Fraction of trees to ignore as burn-in", burnInFraction, 8, 0.0, 1.0);
+
+ 		queryFilesDialog.addLabel("(Mesquite will ignore whichever number of trees is largest.)");
+
+ 		queryFilesDialog.completeAndShowDialog(true);
+ 		if (buttonPressed.getValue()==0)  {
+ 			burnInIgnore = burnInIgnoreField.getValue();
+ 			burnInFraction = burnInFractionField.getValue();
+ 		}
+ 		queryFilesDialog.dispose();
+ 		return (buttonPressed.getValue()==0);
+ 	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets how many trees in burn-in to ignore", "[number of saved trees to ignore]", commandName, "ignoreBurnIn")) {
+			int newBurn = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newBurn))
+				newBurn= MesquiteInteger.queryInteger(containerOfModule(), "Number of trees to ignore as burn-in", "Ignore:", burnInIgnore);
+			if (newBurn>=0 && MesquiteInteger.isCombinable(newBurn)) {
+				burnInIgnore = newBurn;
+				parametersChanged();
+			}
+
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show just the last tree", "[on or off]", commandName, "toggleShowLast")) {
+			boolean current = showLast.getValue();
+			showLast.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showLast.getValue())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (file !=null){
+			file.closeReading();
+			file.dispose();
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		if (treeSource!=null)
+			treeSource.setPreferredTaxa(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		if (treeSource!=null)
+			treeSource.initialize(taxa);
+		scoreFileNotReadable = false;
+
+	}
+
+	/*.................................................................................................................*/
+	double getCachedScore( int itree){
+		return scores.getValue(itree);
+	}
+
+	/*.................................................................................................................*/
+	void goToFilePosition(long pos){
+		file.goToFilePosition(pos);
+
+	}
+	int getHighIndex(){
+		int high = -1;
+		double score = 0;
+		while (MesquiteDouble.isCombinable(score))
+			score = getCachedScore(++high);
+		return --high;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	boolean scoreFileNotReadable = false;
+
+	/*.................................................................................................................*/
+	double getScore(int itree){
+		//if score is cached, then get it
+		double score = getCachedScore( itree);
+		if (MesquiteDouble.isCombinable(score)){
+			return score;
+		}
+		if (scoreFileNotReadable)
+			return MesquiteDouble.unassigned;
+		long prevPosition = 0;
+		//initiate file if needed
+		if (file == null) {
+			String path = ((PathHolder)treeSource).getFilePath();
+			StringBuffer scoresPath = new StringBuffer(path);
+			if (!StringUtil.getLastItem(path, ".", MesquiteFile.fileSeparator).equalsIgnoreCase("t")) {
+				logln("\nWARNING: MrBayes tree file does not end in \".t\"; the score file may be unreadable.\n");
+			}
+			scoresPath.setCharAt(scoresPath.length()-1, 'p');
+			if (MesquiteFile.fileExists(scoresPath.toString()))
+				file = MesquiteFile.open(true, scoresPath.toString());
+			if (file==null) {
+				scoreFileNotReadable = true;
+				return MesquiteDouble.unassigned;
+			}
+			file.openReading();
+			file.readLine();
+			file.readLine();//skipping first two lines
+			prevPosition = file.getFilePosition();
+			filePos.setValue(0, prevPosition);
+		}
+		int highIndex = getHighIndex();	
+		if (highIndex>=0) {
+			long highPos = filePos.getValue(highIndex);
+			file.goToFilePosition(highPos);
+			file.readLine();//skipping old line
+			prevPosition = file.getFilePosition();
+		}
+		else {
+			file.goToFilePosition(0);
+			file.readLine();
+			file.readLine();//skipping first two lines
+			prevPosition = file.getFilePosition();
+			filePos.setValue(0, prevPosition);
+		}
+		score = 0;
+		for (int i=highIndex+1; i<=itree && MesquiteDouble.isCombinable(score); i++){
+			String line = file.readLine();
+			pos.setValue(0);
+			int tree = MesquiteInteger.fromString(line, pos);
+			double thisScore = MesquiteDouble.fromString(line, pos);
+			scores.setValue(i, thisScore);
+			filePos.setValue(i, prevPosition);
+			prevPosition = file.getFilePosition();
+
+		}
+
+		return getCachedScore( itree);
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		if (showLast.getValue())
+			return getLastTree(taxa);
+		if (treeSource == null)
+			return null;
+		Tree t = treeSource.getTree(taxa, itree+burnInIgnore);
+		if (t!= null && highestSuccessfulTree<itree)
+			highestSuccessfulTree = itree;
+		if (t !=null && t instanceof Attachable){
+			double d = getScore(itree + burnInIgnore);
+			if (MesquiteDouble.isCombinable(d)){
+				MesquiteDouble s = new MesquiteDouble(-d);
+				s.setName("MrBayesScore");
+				((Attachable)t).attachIfUniqueName(s);
+			}
+		}
+		return t;
+	}
+	/*.................................................................................................................*/
+
+	public Tree getLastTree(Taxa taxa){
+		int i = highestSuccessfulTree+1;
+		Tree tree = null;
+		Tree t = null;
+
+		while((tree = treeSource.getTree(taxa, i + burnInIgnore))!=null){
+			t = tree;
+			highestSuccessfulTree = i;
+			i++;
+		}
+		if (t != null && t instanceof Attachable){
+			double d = getScore(highestSuccessfulTree + burnInIgnore);
+			if (MesquiteDouble.isCombinable(d)){
+				MesquiteDouble s = new MesquiteDouble(-d);
+				s.setName("MrBayesScore");
+				((Attachable)t).attachIfUniqueName(s);
+			}
+		}
+		return t;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		if (showLast.getValue())
+			return 1;
+		if (treeSource == null)
+			return 0;
+		int nt = treeSource.getNumberOfTrees(taxa); 
+		if (MesquiteInteger.isCombinable(nt))
+			return nt-burnInIgnore;
+		else
+			return nt;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa, boolean determineNumberIfFinite) {
+		if (showLast.getValue())
+			return 1;
+		if (treeSource == null)
+			return 0;
+		int nt = treeSource.getNumberOfTrees(taxa, determineNumberIfFinite); 
+		if (MesquiteInteger.isCombinable(nt))
+			return nt-burnInIgnore;
+		else
+			return nt;
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		if (treeSource == null)
+			return null;
+		if (showLast.getValue()){
+			if (itree > 0)
+				return null;
+			getLastTree(taxa);
+			return treeSource.getTreeNameString(taxa, highestSuccessfulTree + burnInIgnore);
+		}
+		return treeSource.getTreeNameString(taxa, itree + burnInIgnore);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "MrBayes Trees from .t File";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies trees from a \".t\" file produced by MrBayes";
+	}
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (ignoreEPC)
+			return;
+		if (Notification.getCode(notification) != MesquiteListener.ITEMS_ADDED)
+			highestSuccessfulTree = -1;
+		if (showLast.getValue() && Notification.getCode(notification) == MesquiteListener.ITEMS_ADDED) {
+			parametersChanged(new Notification(MesquiteListener.PARTS_CHANGED));
+		}
+		else	
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "MrBayes Trees from .t File...";
+	}
+
+}
+
+
diff --git a/Source/mesquite/mb/aMBIntro/aMBIntro.java b/Source/mesquite/mb/aMBIntro/aMBIntro.java
new file mode 100644
index 0000000..f8f8a15
--- /dev/null
+++ b/Source/mesquite/mb/aMBIntro/aMBIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.mb.aMBIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aMBIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aMBIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides links to MrBayes analyses.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "MrBayes Package Introduction";
+   	 }
+    		/*.................................................................................................................*/
+    		/** Returns whether package is built-in (comes with default install of Mesquite)*/
+    		public boolean isBuiltInPackage(){
+    			return true;
+    		}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "MrBayes Interface Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/mb/lib/ExportForMrBayesLib.java b/Source/mesquite/mb/lib/ExportForMrBayesLib.java
new file mode 100644
index 0000000..7cf58c6
--- /dev/null
+++ b/Source/mesquite/mb/lib/ExportForMrBayesLib.java
@@ -0,0 +1,312 @@
+/* Mesquite (package mesquite.io).  Copyright 2000 and onward, D. Maddison and W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.mb.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public abstract class ExportForMrBayesLib extends FileInterpreterI implements ActionListener {
+
+
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;  //
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return (project.getNumberCharMatrices( CategoricalState.class) > 0) ;
+	}
+
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		 if ("defaultSearchString".equalsIgnoreCase(tag))
+			 defaultSearchString = StringUtil.cleanXMLEscapeCharacters(content);
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "defaultSearchString", defaultSearchString);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public  void actionPerformed(ActionEvent e) {
+		 if (e.getActionCommand().equalsIgnoreCase("defSearch")) {
+			String temp = MesquiteString.queryString(containerOfModule(), "Default Search String", "Default string setting search parameters for MCMC run", defaultSearchString, 5);
+			if (temp != null){
+				defaultSearchString = temp;
+				storePreferences();
+			}
+		}
+	}
+
+
+	/* ============================  exporting ============================*/
+	/*.................................................................................................................*/
+	protected boolean convertAmbiguities = false;
+	protected boolean simplifyNames = true;
+	protected boolean useData = true;
+	protected String addendum = "";
+	protected String fileName = "untitled.nex";
+	static String defaultSearchString = "mcmcp ngen= 10000000 relburnin=yes burninfrac=0.25 printfreq=1000  samplefreq=1000 nchains=4 savebrlens=yes;";
+	/*.................................................................................................................*/
+	public abstract String getProgramName();
+	/*.................................................................................................................*/
+
+	public boolean getExportOptions(CharacterData data, boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), getName(), buttonPressed);
+		exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		String helpString = "The MrBayes block shown will be added to the bottom of the exported file; you may wish to edit it before using the file. \n\n";
+		helpString += "If you check 'simplify names', then Mesquite will remove all characters from the taxon names ";
+		helpString += "that " + getProgramName() + " can not read, such as quotes, parentheses, etc.";
+		exportDialog.appendToHelpString(helpString);
+//		Checkbox convertToMissing = exportDialog.addCheckBox("convert partial ambiguities to missing", convertAmbiguities);
+		Checkbox simplifyNamesCheckBox = exportDialog.addCheckBox("simplify names as required for " + getProgramName(), simplifyNames);
+		exportDialog.addLabel("MrBayes block: ");
+
+
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,16);
+		exportDialog.addBlankLine();
+		Button setDefaultSearchStringButton = exportDialog.addAListenedButton("Set Default Search String...",null, this);
+		setDefaultSearchStringButton.setActionCommand("defSearch");
+
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+
+//		convertAmbiguities = convertToMissing.getState();
+		simplifyNames = simplifyNamesCheckBox.getState();
+
+		addendum = fsText.getText();
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	private String basicBlock(){
+		String sT = "begin mrbayes;\n\tset autoclose=yes nowarn=yes;";
+		sT +="\n\tlset nst=6 rates=invgamma;\n\tunlink statefreq=(all) revmat=(all) shape=(all) pinvar=(all); \n\tprset applyto=(all) ratepr=variable;\n\t" +
+				defaultSearchString + "\n\tmcmc;\n\tsumt;\nend;";
+
+		return sT;
+	}
+	private String getMrBayesBlock(CharacterData data){
+		boolean writeCodPosPartition = false;
+		boolean writeStandardPartition = false;
+		CharactersGroup[] parts =null;
+		if (data instanceof DNAData)
+			writeCodPosPartition = ((DNAData)data).someCoding();
+		CharacterPartition characterPartition = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class);
+		if (characterPartition == null && !writeCodPosPartition)
+			return basicBlock();
+		if (characterPartition!=null) {
+			parts = characterPartition.getGroups();
+			writeStandardPartition = parts!=null;
+		}
+
+		if (!writeStandardPartition && !writeCodPosPartition) {
+			return basicBlock();
+		}
+		String sT = "begin mrbayes;\n\tset autoclose=yes nowarn=yes;  ";
+		CharInclusionSet incl = null;
+		if (data !=null) {
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+			String exc = data.getExcludedCharactersList(incl);
+			exc = StringUtil.stripBoundingWhitespace(exc);
+			if (!StringUtil.blank(exc))
+				sT += "\n\n\texclude " + exc + ";";
+		}
+
+
+		String codPosPart = "";
+		boolean molecular = (data instanceof MolecularData);
+		boolean nucleotides = (data instanceof DNAData);
+		if (writeCodPosPartition) {
+			//codon positions if nucleotide
+			int numberCharSets = 0;
+			String list = "";
+			String names = "";
+			CodonPositionsSet codSet = (CodonPositionsSet)data.getCurrentSpecsSet(CodonPositionsSet.class);
+			for (int iw = 0; iw<4; iw++){
+				String locs = codSet.getListOfMatches(iw);
+				if (!StringUtil.blank(locs)) {
+					String charSetName = "";
+					if (iw==0) 
+						charSetName = StringUtil.tokenize("nonCoding");
+					else 
+						charSetName = StringUtil.tokenize("codonPos" + iw);			
+					numberCharSets++;
+					list += "\n\tcharset " + charSetName + " = " +  locs + ";";
+					if (!StringUtil.blank(names))
+						names += ", ";
+					names += charSetName;
+				}
+			}
+		//	String codPos = ((DNAData)data).getCodonsAsNexusCharSets(numberCharSets, charSetList); // equivalent to list
+			if (!StringUtil.blank(list)) {
+				codPosPart += "\n\n [codon positions if you wish to use these]";
+				codPosPart +=list;
+				codPosPart += "\n\tpartition currentPartition = " + numberCharSets + ": " + names + ";";
+				codPosPart +="\n\tset partition = currentPartition;\n\tlset applyto=(";
+				for (int i = 1; i<=numberCharSets; i++) {
+					codPosPart += i;
+					if (i<numberCharSets) 
+						codPosPart += ", ";
+				}
+				codPosPart += ");\n";
+			}			
+		}
+		String standardPart = "";
+		if (writeStandardPartition) {
+			int numCharSets = 0;
+			standardPart += "\n\n [currently specified groups if you wish to use these]";
+			for (int i=0; i<parts.length; i++) {
+				String q = ListableVector.getListOfMatches((Listable[])characterPartition.getProperties(), parts[i], CharacterStates.toExternal(0));
+				if (q != null) {
+					standardPart +=  "\n\tcharset " + StringUtil.simplifyIfNeededForOutput(parts[i].getName(),true) + " = " + q + ";";
+					numCharSets++;
+				}
+			}
+			if (numCharSets <=1)
+				standardPart = "";
+			else {
+				standardPart += "\n\tpartition currentPartition = " + numCharSets + ": ";
+				boolean firstTime = true;
+				String nums = "";
+				int num = 0;
+				for (int i=0; i<parts.length; i++) {
+					String q = ListableVector.getListOfMatches((Listable[])characterPartition.getProperties(), parts[i], CharacterStates.toExternal(0));
+					if (q != null) {
+						if (!firstTime){
+							standardPart += ", ";
+							nums += ", ";
+						}
+						firstTime = false;
+						standardPart += StringUtil.simplifyIfNeededForOutput(parts[i].getName(), true);
+						nums += Integer.toString(num+1);
+						num++;
+					}
+				}
+				standardPart +=";\n\tset partition = currentPartition;\n";  
+				String s=getPostPartitionCommands(data.getTaxa());  
+				if (StringUtil.notEmpty(s))
+					standardPart +=s + "\n";
+				standardPart +="\tlset applyto=(" + nums + ");\n";  
+			}
+		}
+		sT += codPosPart + standardPart;
+		if (nucleotides)
+			sT += "\n\tlset nst=6 " + "rates=invgamma;";
+		else if (!molecular)
+			sT += "\n\tlset nst=1 " + "rates=gamma coding=variable;";
+		if (data instanceof ProteinData)
+			sT += "\n\tprset aamodelpr=mixed;";
+		sT += "\n\tunlink statefreq=(all) revmat=(all) shape=(all) pinvar=(all); \n";
+		String s=getPostUNLINKCommands();  
+		if (StringUtil.notEmpty(s))
+			sT +=s + "\n";
+		sT += "\tprset applyto=(all) ratepr=variable;\n";
+		s=getPostPRSETCommands();  
+		if (StringUtil.notEmpty(s))
+			sT +=s + "\n";
+		sT += "\t" + defaultSearchString + "\n\tmcmc;\n\tsumt;\nend;";
+
+		return sT;
+	}
+	/*.................................................................................................................*/
+	public String getPostPartitionCommands(Taxa taxa) {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String getPostUNLINKCommands() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String getPostPRSETCommands() {
+		return "";
+	}
+	/*.................................................................................................................*/
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		Arguments args = new Arguments(new Parser(arguments), true);
+		boolean usePrevious = args.parameterExists("usePrevious");
+		CategoricalData data = (CategoricalData)getProject().chooseData(containerOfModule(), file, null, CategoricalState.class, "Select data to export");
+		if (data ==null) {
+			showLogWindow(true);
+			logln("WARNING: No suitable data available for export to a file of format \"" + getName() + "\".  The file will not be written.\n");
+			return false;
+		}
+		MesquiteString dir = new MesquiteString();
+		MesquiteString fn = new MesquiteString();
+		String suggested = fileName;
+		if (file !=null)
+			suggested = file.getFileName();
+		MesquiteFile f;
+		loadPreferences();
+		addendum = getMrBayesBlock(data);
+		if (!usePrevious){
+			if (!getExportOptions(data, data.anySelected(), data.getTaxa().anySelected()))
+				return false;
+		}
+		String path = getPathForExport(arguments, suggested, dir, fn);
+		if (path != null) {
+			f = MesquiteFile.newFile(dir.getValue(), fn.getValue());
+			if (f !=null){
+				f.useSimplifiedNexus = true;
+				f.useDataBlocks = useData;
+				f.ambiguityToMissing = convertAmbiguities;
+				f.simplifyNames =simplifyNames;
+				f.openWriting(true);
+				f.writeLine("#NEXUS" + StringUtil.lineEnding());
+				if (!useData)
+					f.writeLine(((TaxaManager)findElementManager(Taxa.class)).getTaxaBlock(data.getTaxa(), null, file));
+				data.getMatrixManager().writeCharactersBlock(data, null, f, null);
+				if (addendum != null)
+					f.writeLine(addendum);
+				f.closeWriting();
+				return true;
+			}
+		}
+		return false;
+	}
+
+
+
+}
+
diff --git a/Source/mesquite/meristic/InitMeristicParsimony/InitMeristicParsimony.java b/Source/mesquite/meristic/InitMeristicParsimony/InitMeristicParsimony.java
new file mode 100644
index 0000000..c51fe49
--- /dev/null
+++ b/Source/mesquite/meristic/InitMeristicParsimony/InitMeristicParsimony.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.meristic.InitMeristicParsimony;
+/*~~  */
+
+import mesquite.lib.duties.*;
+import mesquite.meristic.lib.*;
+
+/**/
+public class InitMeristicParsimony extends FileInit {
+	public String getName() {
+		return "Initialize predefined meristic parsimony models";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Initializes the predefined meristic parsimony models." ;
+	}
+	/*.................................................................................................................*/
+	MeristicLinearParsModel linearModel;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		linearModel = new MeristicLinearParsModel("Linear Meristic");
+		MeristicData.registerDefaultModel("Parsimony", "Linear Meristic");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been established but not yet read in.*/
+	public void projectEstablished() {
+		linearModel.addToFile(null, getProject(), null);
+		super.projectEstablished();
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+}
+
+
+
diff --git a/Source/mesquite/meristic/ManageMeristicChars/ManageMeristicChars.java b/Source/mesquite/meristic/ManageMeristicChars/ManageMeristicChars.java
new file mode 100644
index 0000000..9620445
--- /dev/null
+++ b/Source/mesquite/meristic/ManageMeristicChars/ManageMeristicChars.java
@@ -0,0 +1,351 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.ManageMeristicChars;
+/*~~  */
+
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.meristic.lib.*;
+
+/* ======================================================================== 
+Manages meristic data matrices  */
+public class ManageMeristicChars extends CharMatrixManager {
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+
+	/*.................................................................................................................*/
+	public Class getStateClass(){
+		return MeristicState.class;
+	}
+	/*.................................................................................................................*/
+	public Class getDataClass(){
+		return MeristicData.class;
+	}
+	/*.................................................................................................................*/
+	public  String getDataClassName(){
+		return MeristicData.DATATYPENAME;
+	}
+	/*.................................................................................................................*/
+	public  CharacterData getNewData(Taxa taxa, int numChars){
+		return new MeristicData(this, taxa.getNumTaxa(), numChars, taxa);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(Class dataClass){
+		return (dataClass == MeristicData.class);
+	}
+	/*.................................................................................................................*/
+	public boolean readsWritesDataType(String dataType){
+		return dataType.equalsIgnoreCase("Meristic");
+	}
+	public void fileReadIn(MesquiteFile f){
+		ListableVector datas = getProject().getCharacterMatrices();
+		for (int i=0; i<datas.size(); i++){
+			CharacterData data = (CharacterData)datas.elementAt(i);
+			if (data instanceof MeristicData && data.getFile() == f){
+				if (data.getInapplicableSymbol() == '-')  //not permitted because it causes problems for negative numbers
+					data.setInapplicableSymbol(MeristicState.inapplicableChar);
+					((MeristicData)data).hasNegatives = false;  //reset this just in case
+			}
+		}
+	}
+	public CharacterData processFormat(MesquiteFile file, Taxa taxa, String dataType, String formatCommand, MesquiteInteger stringPos, int numChars, String title, String fileReadingArguments) {
+
+		MeristicData data= null;
+		//@@@@@@@@@@@@@@@@@@@@
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+
+		if (fuse){
+			String message = "In the file being imported, there is a matrix called \"" + title + "\". Mesquite will either fuse this matrix into the matrix you select below, or it will import that matrix as new, separate matrix.";
+			data = (MeristicData)getProject().chooseData(containerOfModule(), null, taxa, getStateClass(), message,  true,"Fuse with Selected Matrix", "Add as New Matrix");
+			if (data != null && numChars > data.getNumChars())
+				data.addCharacters(data.getNumChars()-1, numChars - data.getNumChars(), false);
+			if (data != null)
+				file.characterDataNameTranslationTable.addElement(new MesquiteString(title, data.getName()), false);
+		}
+		if (data == null){
+			data= (MeristicData)getNewData(taxa,numChars);
+			if (fuse)
+				data.setName(title);  //because otherwise titles are not set for fused matrices within ManageCharacters, since on the outside they don't know if it's new
+		}
+		else {
+			if (fuse)
+				data.setSuppressSpecssetReading(true);
+			data.suppressChecksum = true;
+		}
+		data.interleaved = false;   //reset default in case this is fused
+
+		//@@@@@@@@@@@@@@@@@@@@
+		String tok = ParseUtil.getToken(formatCommand, stringPos);
+		while (!tok.equals(";")) {
+			if (tok.equalsIgnoreCase("ITEMS")) {
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting rid of "="
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting rid of "("
+				tok = ParseUtil.getToken(formatCommand, stringPos); //getting first item name
+				while (tok != null && !tok.equals(")")) {
+					if ("unnamed".equalsIgnoreCase(tok))
+						tok = null;
+					data.establishItem(tok);
+					tok = ParseUtil.getToken(formatCommand, stringPos); //getting item name
+				}
+
+			}
+			else if (tok.equalsIgnoreCase("format")) { 
+			}
+			else if (tok.equalsIgnoreCase("TRANSPOSE")) {
+				alert("Sorry, Transposed matrices of meristic characters can't yet be read");
+				return null;
+			}
+			else if (tok.equalsIgnoreCase("interleave")) {
+				int sp = stringPos.getValue();
+				String e = ParseUtil.getToken(formatCommand, stringPos); //eating up = ?
+				if ("=".equals(e)){
+					String y = ParseUtil.getToken(formatCommand, stringPos); //yes or no ?
+					data.interleaved = ("yes".equalsIgnoreCase(y));
+						
+				}
+				else {
+					stringPos.setValue(sp);
+					data.interleaved = true;
+				}
+			}
+			else if (tok.equalsIgnoreCase("MISSING")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setUnassignedSymbol(t.charAt(0));
+			}
+			else if (tok.equalsIgnoreCase("DATATYPE")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				ParseUtil.getToken(formatCommand, stringPos); //eating up datatype
+				//alert("Error in NEXUS file format: DATATYPE subcommand must appear as the first item in the FORMAT command");
+				//return null;
+			}
+			else if (tok.equalsIgnoreCase("GAP")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1) {
+					data.setInapplicableSymbol(t.charAt(0));
+					if (t.charAt(0) == '-' && !MesquiteThread.isScripting()){
+						if (AlertDialog.query(containerOfModule(), "Has negatives?", "Does this meristic matrix \"" + title + "\" have negative values?.  " +
+								"Explanation: A meristic matrix being read has GAP (inapplicable) symbol set to '-'.  This will be changed to 'x' to avoid possible confusion inapplicable and negative numbers.", "Yes, Negative values", "No"))
+							data.hasNegatives = true;
+					}
+				}
+			}
+			else if (tok.equalsIgnoreCase("MATCHCHAR")) { 
+				ParseUtil.getToken(formatCommand, stringPos); //eating up =
+				String t = ParseUtil.getToken(formatCommand, stringPos);
+				if (t!=null && t.length()==1)
+					data.setMatchChar(t.charAt(0));
+			}
+			else {
+				alert("Unrecognized token (\"" + tok+ "\") in FORMAT statement of meristic matrix; matrix will be stored as foreign, and not processed.");
+				return null;
+			}
+			tok = ParseUtil.getToken(formatCommand, stringPos);
+		}
+
+		return data;
+	}
+	/*.................................................................................................................*/
+	public boolean processCommand(CharacterData data, String commandName, String commandString) {
+		if ("CHARSTATELABELS".equalsIgnoreCase(commandName)){
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			String cN = ParseUtil.getToken(commandString, startCharT); //eating up command name
+			cN = ParseUtil.getToken(commandString, startCharT);
+			while (!StringUtil.blank(cN) && !cN.equals(";") ) {
+				int charNumber =MesquiteInteger.fromString(cN);
+				String charName = (ParseUtil.getToken(commandString, startCharT));
+				if (!charName.equals(",")) {
+					data.setCharacterName(charNumber-1, charName);
+					String stateName = ParseUtil.getToken(commandString, startCharT); // eat up slash
+					int stateNumber = 0;
+					while (stateName!=null && !stateName.equals(",") &&!stateName.equals(";")) { //skipping state names as they don't make any sense for meristic!
+						stateName = (ParseUtil.getToken(commandString, startCharT));
+						stateNumber++;
+					}
+				}
+				cN = ParseUtil.getToken(commandString, startCharT);
+			}
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getCharStateLabels(CharacterData data, MesquiteFile file) {
+		if (file.writeCharLabels){
+			String csl = "CHARLABELS " + StringUtil.lineEnding();
+			boolean found = false;
+			for (int i = 0; i<data.getNumChars(); i++) {
+				if (data.characterHasName(i)) {
+					found = true;
+					csl += " " + StringUtil.tokenize(data.getCharacterName(i));
+				}
+				else {
+					csl += " _";
+				}
+			}
+			if (found)
+				return csl + " ; " + StringUtil.lineEnding();
+			else
+				return "";
+		}
+		String csl = "CHARSTATELABELS " + StringUtil.lineEnding();
+		boolean found = false;
+		for (int i = 0; i<data.getNumChars(); i++) {
+			String cslC="";
+			if (i>0 && found)
+				cslC += "," + StringUtil.lineEnding();
+			cslC += "\t\t" + Integer.toString(i+1) + " ";    //i+1 to convert to 1 based
+			boolean foundInCharacter = false;
+			if (data.characterHasName(i)) {
+				foundInCharacter = true;
+				cslC += StringUtil.tokenize(data.getCharacterName(i));
+			}
+			if (foundInCharacter) {
+				csl += cslC;
+				found = true;
+			}
+		}
+		if (found)
+			return csl + " ; " + StringUtil.lineEnding();
+		else
+			return "";
+	}
+	/*.................................................................................................................*/
+	public String getDataTypeString() {
+		return "MERISTIC";
+	}
+	/*.................................................................................................................*/
+	public void writeCharactersBlock(CharacterData data, CharactersBlock cB, MesquiteFile file, ProgressIndicator progIndicator){
+		MeristicData cData = (MeristicData)data;
+		//StringBuffer blocks = new StringBuffer(cData.getNumChars()*cData.getNumTaxa()*10*cData.getNumItems());
+		StringBuffer line = new StringBuffer(cData.getNumChars()*10*cData.getNumItems());
+		file.write("BEGIN CHARACTERS");
+		if (data.getAnnotation()!=null && !file.useSimplifiedNexus) 
+			file.write("[!" + StringUtil.tokenize(data.getAnnotation()) + "]");
+		
+		file.write(";" + StringUtil.lineEnding());
+		if (cData.getName()!=null &&  (getProject().getNumberCharMatrices()>1 || ((file==null || (!file.useSimplifiedNexus &&  !file.useConservativeNexus)) && !NexusBlock.suppressTITLE))){
+			file.write("\tTITLE  " + StringUtil.tokenize(cData.getName()) + ";" + StringUtil.lineEnding());
+		}
+
+		if (cData.getTaxa().getName()!=null  && getProject().getNumberTaxas()>1){ //should have an isUntitled method??
+			file.write("\tLINK TAXA = " +  StringUtil.tokenize(cData.getTaxa().getName()) + ";" + StringUtil.lineEnding());
+		}
+		file.write("\tDIMENSIONS ");
+		int numCharsToWrite;
+		if (file.writeExcludedCharacters)
+			numCharsToWrite = cData.getNumChars();
+		else
+			numCharsToWrite = cData.getNumCharsIncluded();
+		file.write(" NCHAR=" + numCharsToWrite);
+		file.write(";" + StringUtil.lineEnding());
+		file.write("\tFORMAT");
+		file.write(" DATATYPE = " + getDataTypeString());
+		if (cData.getNumItems()>0 && !(cData.getNumItems()==1 && cData.getItemName(0) ==null)) {
+			file.write(" ITEMS = (");
+			for (int i=0; i<cData.getNumItems(); i++) {
+				String iName = cData.getItemName(i);
+				if (iName == null)
+					file.write("unnamed ");
+				else
+					file.write(iName + " ");
+			}
+			file.write(") ");
+		}
+		file.write(" GAP = " + data.getInapplicableSymbol() + " MISSING = " + data.getUnassignedSymbol());
+		file.write(";" + StringUtil.lineEnding());
+		if (data.isLinked() && !file.useSimplifiedNexus  && !file.useConservativeNexus){
+			file.write("\tOPTIONS ");
+			Vector ds = data.getDataLinkages();
+			for (int i = 0; i<ds.size(); i++) {
+				file.write(" LINKCHARACTERS = ");
+				file.write(StringUtil.tokenize(((CharacterData)ds.elementAt(i)).getName()));
+			}
+			file.write(";" + StringUtil.lineEnding());
+		}
+		file.write(getCharStateLabels(cData, file));
+		file.write("\tMATRIX" + StringUtil.lineEnding());
+		String taxonName="";
+		int maxNameLength = cData.getTaxa().getLongestTaxonNameLength();
+		for (int it=0; it<cData.getTaxa().getNumTaxa(); it++) {
+			if ((data.someApplicableInTaxon(it, false)|| file.writeTaxaWithAllMissing) && (!file.writeOnlySelectedTaxa || data.getTaxa().getSelected(it))){
+				taxonName = cData.getTaxa().getTaxon(it).getName();
+				if (file.useStandardizedTaxonNames)
+					taxonName = "t" + it;
+				else
+					taxonName = StringUtil.simplifyIfNeededForOutput(taxonName,file.simplifyNames);
+				if (taxonName!=null) {
+					file.write("\t"+ taxonName);
+					for (int i = 0; i<(maxNameLength-taxonName.length()+2); i++)
+						file.write(" ");
+				}
+				line.setLength(0);
+				for (int ic=0;  ic<cData.getNumChars(); ic++)  {
+					if (data.isCurrentlyIncluded(ic) || file.writeExcludedCharacters) {
+						line.append(' ');
+						cData.statesIntoNEXUSStringBuffer(ic, it, line);
+					}
+				}
+				file.write(line.toString());
+				file.write(StringUtil.lineEnding());
+			}
+		}
+		file.write(StringUtil.lineEnding()+ ";");
+		file.write( StringUtil.lineEnding());
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus){
+			String idsCommand = getIDsCommand(data);
+			if (!StringUtil.blank(idsCommand))
+				file.write("\t" + idsCommand + StringUtil.lineEnding());
+		}
+		if (cB != null) file.write(cB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		file.write("END");
+		file.write(";" + StringUtil.lineEnding());
+
+		//file.write( blocks.toString());
+	}
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage Meristic char. matrices";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages meristic data matrices (including read/write in NEXUS file)." ;
+   	 }
+}
+	
+	
+
diff --git a/Source/mesquite/meristic/MerItemsEditInfo/MerItemsEditInfo.java b/Source/mesquite/meristic/MerItemsEditInfo/MerItemsEditInfo.java
new file mode 100644
index 0000000..e861fc0
--- /dev/null
+++ b/Source/mesquite/meristic/MerItemsEditInfo/MerItemsEditInfo.java
@@ -0,0 +1,338 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.meristic.MerItemsEditInfo;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.meristic.lib.*;
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.lib.table.*;
+
+public class MerItemsEditInfo extends MatrixInfoPanelAssistantI  {
+	ItemsPanel panel;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new MeristicStateTest();
+		}
+
+	/*.................................................................................................................*/
+	public MatrixInfoExtraPanel getPanel(ClosablePanelContainer container){
+		panel =  new ItemsPanel(container, this);
+		return panel;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("panelOpen " + panel.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the panel open", null, commandName, "panelOpen")) {
+			if (panel != null)
+				panel.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Meristic Items Editor";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Edits items for meristic data matrix within the editor info panel.";
+	}
+}
+/*===========================================*/
+class ItemsPanel extends MatrixInfoExtraPanel  {
+	String message = null;
+	MerItemsEditInfo ownerModule;
+	StringInABox statesBox;
+	ItemsField itemsField;
+	MeristicData cData;
+	Image add, subtract, query;
+	public ItemsPanel(ClosablePanelContainer container, MerItemsEditInfo ownerModule){
+		super(container, "Items");
+		statesBox =  new StringInABox("", null, 50);
+		itemsField = new ItemsField(this);
+		itemsField.setBackground(getBackground());
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addGray.gif");
+		subtract = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "subtractGray.gif");
+		query = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "queryGray.gif");
+		currentHeight = 100 + MINHEIGHT + charNameHeight;
+		setLayout(null);
+		add(itemsField);
+		resetLocs();
+		this.ownerModule = ownerModule;
+	}
+	public int getRequestedHeight(int width){
+		if (isOpen())
+			return MINHEIGHT + itemsField.getDesiredHeight() + 30;
+		else
+			return MINHEIGHT;
+	}
+
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table){
+		super.setMatrixAndTable(data, table);
+		this.cData = (MeristicData)data;
+		itemsField.setData(cData);
+		resetLocs();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	void enterName(int item, String name){
+		if (item<0 || item>= cData.getNumItems())
+			return;
+		cData.setItemReference(item, NameReference.getNameReference(name));
+		((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+	}
+	public void setOpen(boolean open){
+		itemsField.setVisible(open);
+		resetLocs();
+		super.setOpen(open);
+	}
+	int charNameHeight = 24;
+	void resetLocs(){
+		if (itemsField == null)
+			return;
+		//itemsField.setBounds(0, 0, getWidth()-4, getHeight());
+		itemsField.setBounds(2, MINHEIGHT + 4, getWidth()-4, itemsField.getDesiredHeight());
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+	void changeFocus(int item, int change){
+		if (item+change >= 0 && item+change< cData.getNumItems())
+			itemsField.items[item+change].requestFocusInWindow();
+	}
+	public void paint(Graphics g){
+		super.paint(g);
+		int h = itemsField.getY() + itemsField.getHeight() + 4;
+		g.drawImage(add, 2, h, this);
+		g.drawImage(subtract, 24, h, this);
+		g.drawImage(query, getWidth()-20, 4, this);
+	}
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		int h = itemsField.getY() + itemsField.getHeight() + 4;
+		if (y>=h && y< h+19) {
+			if (x>=2 && x<20){
+				String d = MesquiteString.queryString(MesquiteWindow.windowOfItem(this), "New item", "Name of new item.", "");
+				if (StringUtil.blank(d))
+					return;
+				else {
+					cData.addItem(d);
+					itemsField.setData(cData);
+					((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					container.requestHeightChange(this);
+				}
+			}
+			else if (x>= 24 && x<=40){
+				String[] items = new String[cData.getNumItems()];
+				for (int i=0; i<items.length; i++){
+					items[i]= cData.getItemName(i);
+				}
+				int d = ListDialog.queryList(MesquiteWindow.windowOfItem(this), "Remove item", "Remove item:", MesquiteString.helpString, items, 0);
+				if (!MesquiteInteger.isCombinable(d) || d<0 || d>=cData.getNumItems())
+					return;
+				else {
+					cData.removeItem(d);
+					itemsField.setData(cData);
+					((CharacterData)cData).notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+					container.requestHeightChange(this);
+				}
+			}
+		}
+		else if (y<MINHEIGHT && (x> getWidth()- 20)) {
+			MesquiteTrunk.mesquiteTrunk.alert("These are the items of the meristic matrix.  A meristic matrix can have multiple items in each cell. Here you can control how many items there are, and their names.");  //query button hit
+		}
+		else
+			super.mouseUp(modifiers,  x,  y,  tool);
+	}
+}
+/*-----------------------------*/
+class ItemsField extends Panel {
+	NameField[] items;
+	ItemsPanel panel;
+	MeristicData data;
+	int ic = -1;
+	public ItemsField(ItemsPanel panel){
+		this.panel = panel;
+		setLayout(null);
+		resetLocs();
+	}
+	void setData(MeristicData data){
+		this.data = data;
+		resetItems();
+		resetLocs();
+
+	}
+	public void setVisible(boolean vis){
+		super.setVisible(vis);
+		if (items == null)
+			return;
+		for (int state = 0; state<items.length; state++)
+			items[state].setVisible(vis);
+	}
+	int w = 10;
+	void setContainingWidth(int w){
+		this.w = w-30;
+		resetLocs();
+	}
+	
+	public void resetItems(){
+		if (items == null || items.length != data.getNumItems()){
+			if (items != null)
+				for (int item = 0; item< items.length; item++){
+					remove(items[item]);
+				}
+			items = new NameField[data.getNumItems()];
+
+			for (int item = 0; item<data.getNumItems(); item++){
+				items[item] = new NameField(panel, item);
+				add(items[item]);
+				items[item].setVisible(true);
+			}
+		}
+		if (items == null)
+			return;
+		for (int item = 0; item<data.getNumItems() && item < items.length; item++){
+			items[item].setText(data.getItemName(item));
+		}
+	}
+	int charNameHeight = 24;
+	void resetLocs(){
+		if (items == null)
+			return;
+		for (int state = 0; state<items.length; state++){
+			items[state].setBounds(2, charNameHeight*state, getWidth()-4, charNameHeight);
+		}
+	}
+	int getDesiredHeight(){
+		if (data == null)
+			return  charNameHeight*2;
+		return charNameHeight*(data.getNumItems());
+	}
+
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+}
+class NameField extends TextField implements FocusListener {
+	ItemsPanel panel;
+	int item = -1;
+	boolean somethingTyped;
+
+	public NameField(ItemsPanel panel, int item){
+		this.panel = panel;
+		this.item = item;
+		setText("");
+		addKeyListener(new KListener());
+		addFocusListener(this);
+	}
+
+	public void focusGained(FocusEvent e){
+	}
+	public void focusLost(FocusEvent e){
+		if (somethingTyped)
+			panel.enterName(item, getText());
+	}
+	class KListener extends KeyAdapter {
+		MesquiteWindow window = null;
+		public KListener (){
+			super();
+		}
+		public void keyPressed(KeyEvent e){
+			//Event queue
+			if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+				if (somethingTyped){
+					panel.enterName(item, getText());
+					setSelectionStart(getText().length());
+					setSelectionEnd(getText().length());
+				}
+				panel.changeFocus(item, 1);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_UP) {
+				if (somethingTyped)
+					panel.enterName(item, getText());
+				panel.changeFocus(item, -1);
+			}
+			else if (e.getKeyCode()== KeyEvent.VK_DOWN || e.getKeyCode()== KeyEvent.VK_TAB){
+				if (somethingTyped)
+					panel.enterName(item, getText());
+				panel.changeFocus(item, 1);
+			}
+			else { 
+				somethingTyped=true;
+			}
+
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/meristic/ParsimonyMeristicLinear/ParsimonyMeristicLinear.java b/Source/mesquite/meristic/ParsimonyMeristicLinear/ParsimonyMeristicLinear.java
new file mode 100644
index 0000000..da13c16
--- /dev/null
+++ b/Source/mesquite/meristic/ParsimonyMeristicLinear/ParsimonyMeristicLinear.java
@@ -0,0 +1,365 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.meristic.ParsimonyMeristicLinear;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.meristic.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonyMeristicLinear extends ParsAncStatesForModel {
+	public String getName() {
+		return "Parsimony Meristic Linear";
+	}
+	public String getExplanation() {
+		return "Reconstructs the ancestral states of mersitic characters so as to minimize the sum of absolute values of changes (linear, Wagner, Farris or Manhattan parsimony).  If the meristic character has multiple items, then length is reported on only the first item." ;
+	}
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	MeristicHistory finalMin, finalMax, upMin, upMax, downMin, downMax;
+	MesquiteInteger dummy, temp1, temp2, NYLength;
+	int overallMin = MesquiteInteger.unassigned;
+	int overallMax = MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		dummy = new MesquiteInteger(0);
+		temp1 = new MesquiteInteger(0);
+		temp2 = new MesquiteInteger(0);
+		NYLength = new MesquiteInteger(0);
+		return true;
+	}
+
+	/*----------------------------------------------------------------------- */
+	/*----------------------------------------------------------------------- */
+	void combine (MesquiteInteger minA, MesquiteInteger maxA, int minD, int maxD, int minE, int maxE, MesquiteInteger  inc) {
+		/*This is the Meristic value state set operator; takes state ranges}
+	{[minD..maxD] and [minE..maxE] and combines them and outputs range [minA..maxA]}
+	{inc is the increment on length caused by the combining */
+		if (minD < minE) {
+			if (maxD < minE) {  //{DDDDD EEEEE}
+				minA.setValue(maxD);
+				maxA.setValue(minE);
+				inc.add(minE - maxD);
+			}
+			else if (maxD < maxE) {  //{DDDDDEDEDEEEEE}
+				minA.setValue(minE);
+				maxA.setValue(maxD);
+			}
+			else {  //{DDDDEDEDEDDDDD}
+				minA.setValue(minE);
+				maxA.setValue(maxE);
+			}
+		}
+		else {
+			if (maxE < minD) {	//{EEEEEEE   DDDDDDD}
+				minA.setValue(maxE);
+				maxA.setValue(minD);
+				inc.add(minD - maxE);
+			}
+			else if (maxE < maxD) {   //{EEEEEEDEDEDDDDDD}
+				minA.setValue(minD);
+				maxA.setValue(maxE);
+			}
+			else {   //{EEEEEEDEDEDEEEEE}
+				minA.setValue(minD);
+				maxA.setValue(maxD);
+			}
+		}
+	}
+
+	/*_____________________________________________________________________ */
+	void doCombineOneThenOther (MesquiteInteger minA, MesquiteInteger maxA, int min11,int  max11, int min22, int max22, int min33, int  max33) {
+		combine(minA, maxA, min11, max11, min22, max22, dummy);
+		combine(minA, maxA, minA.getValue(), maxA.getValue(), min33, max33, dummy);
+	}
+
+	/*_____________________________________________________________________ */
+	void combinefromGreatestMin (MesquiteInteger minA, MesquiteInteger maxA, int minG,int  maxG, int min22, int max22, int min33, int  max33) {
+		/*{here minG, maxG are min and max of set with rightmost minimum}
+	{First we find out which of the other sets' maximum is the furthest left of minG, if either is}*/
+		if (max33 < minG) {
+			if (max22 < max33) //{max22 furthest left, and is left of minG; Thus combine set G and set 22 first, then 33}
+				doCombineOneThenOther(minA, maxA, minG, maxG, min22, max22, min33, max33);
+			else //{max33 furthest left, and is left of minG; Thus combine set G and set 33 first, then 22}
+				doCombineOneThenOther(minA, maxA, minG, maxG, min33, max33, min22, max22);
+		}
+		else
+			/*{Either: max22 furthest left, and is left of minG; Thus combine set G and set 22 first, then 33}
+			{Or: Both max22 and max33 are right of minG, thus there must be triple intersection, and order doesn't matter}*/
+			doCombineOneThenOther(minA, maxA, minG, maxG, min22, max22, min33, max33);
+	}
+
+	/*_____________________________________________________________________ */
+	void tripleCombine (MesquiteInteger minA, MesquiteInteger maxA, int minD, int maxD, int minE, int maxE, int minF, int maxF) {
+		/*{This is the Meristic value state set operator for 3 SETS; takes state ranges}
+	{[minD..maxD], [minE..maxE] and [minF..maxF] and combines them and outputs range [minA..maxA]}
+	{Uses the trick of taking two most distant state sets, applying binary set operator on them, then}
+	{taking result and combine it with third set using binary set operator again}*/
+		if (minD < minE) {
+			if (minE < minF)  	//{� minF is greatest}
+				combinefromGreatestMin(minA, maxA, minF, maxF, minD, maxD, minE, maxE);
+			else 					//{� minE greatest}
+				combinefromGreatestMin(minA, maxA, minE, maxE, minD, maxD, minF, maxF);
+		}
+		else if (minF > minD) //{� minF greatest}
+			combinefromGreatestMin(minA, maxA, minF, maxF, minD, maxD, minE, maxE);
+		else  						//{� minD greatest}
+			combinefromGreatestMin(minA, maxA, minD, maxD, minF, maxF, minE, maxE);
+	}
+
+	/*_____________________________________________________________________ */
+	/*{find min max range among observed for missing data}*/
+	void NYsurvey (int numTaxa, MeristicDistribution observedStates,  int item) {
+		overallMin = MesquiteInteger.unassigned;
+		overallMax = MesquiteInteger.unassigned;
+		for (int i=0; i<numTaxa; i++) {
+			overallMin = MesquiteInteger.minimum(overallMin, observedStates.getState(i, item));
+			overallMax = MesquiteInteger.maximum(overallMax, observedStates.getState(i, item));
+		}
+	}
+	//TODO: allow missing data!
+	//TODO: handle multiple items better; should use min and max items if available
+	/*_____________________________________________________________________ */
+	/*{Downpass of linear parsimony on Meristic characters}*/
+	void NYdown (Tree tree, int N, int item) {
+		if (tree.nodeIsInternal(N)) {  
+			int L = tree.firstDaughterOfNode(N, deleted);
+			int R = tree.lastDaughterOfNode(N, deleted);
+			NYdown(tree, L, item);  //ASSUMES dichtomous
+			NYdown(tree, R, item);
+			//->downMin is minimum of state range; ->downMax is maximum}
+			//note here we let combine increment the NYlength during downpass}
+			combine(temp1, temp2, downMin.getState(L), downMax.getState(L), downMin.getState(R),downMax.getState(R), NYLength);
+			downMin.setState(N, temp1.getValue());
+			downMax.setState(N, temp2.getValue());
+		}
+		else { //terminal node
+			int ts = ((MeristicDistribution)observedStates).getState(tree.taxonNumberOfNode(N), item);
+			if (MesquiteInteger.isUnassigned(ts)) {
+				downMin.setState(N, overallMin);
+				downMax.setState(N, overallMax);
+			}
+			else {
+				downMin.setState(N, ts);
+				downMax.setState(N, downMin.getState(N)); 
+			}
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*This is combined UpPass and FinalPass for Meristic characters, linear parsimony}*/
+
+	void NYfinal (Tree tree, int N, MeristicHistory statesAtNodes, int itemMin, int itemMax) {
+		if (tree.nodeIsInternal(N)) {  
+			int L = tree.firstDaughterOfNode(N, deleted);
+			int R = tree.lastDaughterOfNode(N, deleted);
+			if (N == tree.getRoot(deleted))  {
+				finalMin.setState(N, downMin.getState(N));  //{use downpass states for root's final}
+				finalMax.setState(N, downMax.getState(N));  //{use downpass states for root's final}
+			}
+			else {
+				//{First calculate up states}
+				int anc = tree.motherOfNode(N, deleted);
+				int sis = tree.nextSisterOfNode(N, deleted);
+				if (!tree.nodeExists(sis))
+					sis = tree.previousSisterOfNode(N, deleted);
+				if (anc == tree.getRoot(deleted)) {
+					upMin.setState(N, downMin.getState(sis));
+					upMax.setState(N, downMax.getState(sis));
+				}
+				else {
+					dummy.setValue(0);
+					combine(temp1, temp2, upMin.getState(anc), upMax.getState(anc), downMin.getState(sis), downMax.getState(sis),dummy);
+					upMin.setState(N, temp1.getValue());
+					upMax.setState(N, temp2.getValue());
+				}
+				//{Then calculate final states}
+				tripleCombine(temp1, temp2, downMin.getState(L), downMax.getState(L), downMin.getState(R), downMax.getState(R), upMin.getState(N), upMax.getState(N));
+				finalMin.setState(N, temp1.getValue());
+				finalMax.setState(N, temp2.getValue());
+			}
+			NYfinal(tree, L, statesAtNodes, itemMin, itemMax);
+			NYfinal(tree, R, statesAtNodes, itemMin, itemMax);
+		}
+		else {
+			int ts = ((MeristicDistribution)observedStates).getState(tree.taxonNumberOfNode(N), 0); //just testing item 0?
+			if (MesquiteInteger.isUnassigned(ts)) {
+				finalMin.setState(N, finalMin.getState(tree.motherOfNode(N, deleted)));  //{Results stored in [finalMin .. finalMax]}
+				finalMax.setState(N, finalMax.getState(tree.motherOfNode(N, deleted)));  
+			}
+			else {
+				finalMin.setState(N, downMin.getState(N));  //{Results stored in [finalMin .. finalMax]}
+				finalMax.setState(N, downMax.getState(N));  
+			}
+		}
+
+		statesAtNodes.setState(N, itemMin, finalMin.getState(N));
+		statesAtNodes.setState(N, itemMax, finalMax.getState(N));
+	}
+	/*_____________________________________________________________________ */
+	/*{Reconstructs ancestral states for Meristic characters using linear parsimony.}
+	{nb->downMin, downMax store the minima and maxima of downpass ranges}
+	{nb->upMin, upMax store the minima and maxima of uppass ranges}
+	{nb->finalMin, finalMax store the minima and maxima of final pass ranges}
+	{	(final named C and D because finalMin doubly used; see MinSQReconstruct)}*/
+
+	/*.................................................................................................................*/
+	private void adjustStorage(Tree tree, CharacterDistribution observedStates) {
+		downMin=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downMin);
+		downMax=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downMax);
+		upMin=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upMin);
+		upMax=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upMax);
+		finalMin=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)finalMin);
+		finalMax=  (MeristicHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)finalMax);
+	}
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	boolean warnedPolytomies = false;
+	boolean[] deleted;
+	//boolean warnedMissing = false;
+	public boolean warn(Tree tree, MeristicDistribution observedStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+		if (tree.hasPolytomies(tree.getRoot())) {
+			String message = "Trees with polytomies not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedPolytomies) {
+				discreetAlert( message);
+				warnedPolytomies = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		/*if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())) {
+			String s ="Missing data, gaps are not currently supported by linear parsimony calculations.  Calculations for one or more characters were not completed.";
+			if (!warnedMissing) {
+				discreetAlert( s);
+				warnedMissing = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}*/
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched) {
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation) {
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())){
+			if (deleted == null || deleted.length <  tree.getNumNodeSpaces())
+				deleted = new boolean[tree.getNumNodeSpaces()];
+			for (int i = 0; i<deleted.length; i++) deleted[i] = false;
+			for (int it = 0; it< tree.getTaxa().getNumTaxa(); it++)
+				if (observedStates.isUnassigned(it) || observedStates.isInapplicable(it)) {
+					tree.virtualDeleteTaxon(it, deleted);
+				}
+		}
+		else
+			deleted = null;
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (MeristicDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		MeristicDistribution cObs = (MeristicDistribution)observedStates;
+		String[] items = new String[cObs.getNumItems()*2]; //todo: only do this if needed!!!!
+		for (int i= 0; i<cObs.getNumItems(); i++){
+			String n;
+			if (StringUtil.blank(cObs.getItemName(i)))
+				n = "";
+			else
+				n = cObs.getItemName(i);
+			items[i*2] = n + " (min.)";
+			items[i*2 + 1] = n + " (max.)";
+		}
+		((MeristicHistory)statesAtNodes).setItems(items);
+		((MeristicHistory)statesAtNodes).deassignStates();
+
+		adjustStorage(tree, observedStates);
+		NYLength.setValue(0); //not designed to be thread safe
+		for (int item =0; item<cObs.getNumItems(); item++) {
+			NYsurvey (tree.getTaxa().getNumTaxa(),(MeristicDistribution)observedStates,  item);
+			NYdown(tree, tree.getRoot(deleted), item);
+			NYfinal(tree, tree.getRoot(deleted), (MeristicHistory)statesAtNodes, item*2, item*2 +1);
+			if (item==0&& stepsObject!=null)
+				stepsObject.setValue(NYLength.getValue());
+		}
+		//place states from finalC and finalD into states at nodes
+		if (resultString!=null)
+			resultString.setValue("Parsimony reconstruction (Linear Meristic) [Length: " + stepsObject + "]");
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null ||stepsObject == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (MeristicDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		adjustStorage(tree, observedStates);
+		NYLength.setValue(0); //not designed to be thread safe
+		NYsurvey (tree.getTaxa().getNumTaxa(),(MeristicDistribution)observedStates,  0);
+		NYdown(tree, tree.getRoot(deleted), 0);
+		stepsObject.setValue(NYLength.getValue());
+		if (resultString!=null)
+			resultString.setValue("Parsimony length: " + stepsObject + " (Linear Meristic)");
+	}
+
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		if (model==null)
+			return false;
+		return (model.getName().equalsIgnoreCase("Linear Meristic")) && observedStates instanceof MeristicDistribution;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/meristic/RandomFillMeristic/RandomFillMeristic.java b/Source/mesquite/meristic/RandomFillMeristic/RandomFillMeristic.java
new file mode 100644
index 0000000..bd17671
--- /dev/null
+++ b/Source/mesquite/meristic/RandomFillMeristic/RandomFillMeristic.java
@@ -0,0 +1,90 @@
+package mesquite.meristic.RandomFillMeristic;
+
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.meristic.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class RandomFillMeristic extends MeristicDataAlterer {
+	CharacterState fillState;
+	RandomBetween rng;
+	MesquiteInteger max;
+	MesquiteInteger min;
+	double standardDeviation;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new RandomBetween(System.currentTimeMillis());
+		min = new MesquiteInteger(0);
+		max = new MesquiteInteger(10);
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+
+		boolean did=false;
+		if (!(data instanceof MeristicData))
+			return false;
+		MesquiteBoolean answer = new MesquiteBoolean(true);
+		MesquiteInteger.queryTwoIntegers(containerOfModule(), "Random fill (Meristic Uniform)", "Minimum of filled states", "Maximum of filled states", answer, min, max, 0, MeristicState.infinite, 0, MeristicState.infinite, "");
+		if (!(answer.getValue() && min.isCombinable() && (max.isCombinable()) && max.getValue()>=min.getValue()))
+			return false;
+		MeristicData cData = (MeristicData)data;
+		return alterContentOfCells(data,table, undoReference);
+	}
+
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData data, int ic, int it){
+		((MeristicData)data).setState(ic,it, 0, rng.randomIntBetween(min.getValue(),max.getValue()));
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Random Fill (Meristic Uniform)";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Random Fill (Meristic Uniform)...";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Fills cells with a random state, uniformly." ;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/meristic/aMeristicIntro/aMeristicIntro.java b/Source/mesquite/meristic/aMeristicIntro/aMeristicIntro.java
new file mode 100644
index 0000000..1d8ce24
--- /dev/null
+++ b/Source/mesquite/meristic/aMeristicIntro/aMeristicIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.aMeristicIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aMeristicIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aMeristicIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides basic facilities for handling meristic characters.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Meristic Data Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Meristic Data Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MMeristicAdjustable.java b/Source/mesquite/meristic/lib/MMeristicAdjustable.java
new file mode 100644
index 0000000..221dba3
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MMeristicAdjustable.java
@@ -0,0 +1,336 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.ItemContainer;
+
+/* ======================================================================== */
+/**A class for an array of  meristic character states for many characters, at each of the taxa or nodes.*/
+public class MMeristicAdjustable  extends MMeristicDistribution implements MAdjustableDistribution {
+	int numTaxa=0;
+	int numChars=0;
+	protected Integer2DArray firstMatrix; //other dimension for items (sample size, variance, etc., etc.)
+	protected Vector matrices;
+	String annotation;
+	public MMeristicAdjustable (Taxa taxa, int numChars, int numTaxa) {
+		super(taxa);
+		this.numTaxa= numTaxa;
+		this.numChars= numChars;
+		matrices = new Vector(0);
+		firstMatrix = new Integer2DArray(numChars, numTaxa); //no items yet
+		matrices.addElement(firstMatrix);
+	}
+	
+	public MMeristicAdjustable (Taxa taxa) {
+		super(taxa);
+		matrices = new Vector(0);
+	}
+	public MMeristicAdjustable () {
+		super(null);
+		matrices = new Vector(0);
+	}
+	public void setAnnotation(String s, boolean notify){
+		annotation = s;
+	}
+	public String getAnnotation(){
+		return annotation;
+	}
+	/*..........................................MMeristicAdjustable................*/
+	/**sets the parent CharacterData from which this CharacterDistribution is derived or related*/
+	public void setParentData (CharacterData cd){
+		data = cd;
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setSize(int numChars, int numTaxa) {
+		if (numChars!= this.numChars || numTaxa !=this.numTaxa) {
+			this.numTaxa= numTaxa;
+			this.numChars= numChars;
+			matrices = new Vector(0);
+			firstMatrix = new Integer2DArray(numChars, numTaxa); //no items yet
+			matrices.addElement(firstMatrix);
+			MeristicData data = (MeristicData)getParentData();
+			if (data!=null) {
+				for (int i=0; i<data.getNumItems(); i++)
+					establishItem(data.getItemReference(i));
+			}
+		}
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public Integer2DArray addItem(NameReference nr){
+		Integer2DArray matrix = new Integer2DArray(numChars, numTaxa);
+		if (firstMatrix == null)
+			firstMatrix = matrix;
+		if (nr!=null)
+			matrix.setNameReference(nr);
+		matrix.deassignArray();
+		matrices.addElement(matrix);
+		return matrix;
+	}
+	public Integer2DArray addItem(String name){
+		return addItem(NameReference.getNameReference(name));
+	}
+	public Integer2DArray establishItem(String name){
+		return establishItem(NameReference.getNameReference(name));
+	}
+	/*..........................................MMeristicAdjustable................*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Integer2DArray establishItem(NameReference nr){
+		if (firstMatrix != null && firstMatrix.getNameReference()==null  && matrices.size() ==1) {
+			if (nr!=null)
+				firstMatrix.setNameReference(nr);
+			return firstMatrix;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				Integer2DArray matrix = (Integer2DArray)matrices.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(nr);
+					return matrix;
+				}
+			}
+			return addItem(nr);
+		}
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public int getNumberOfItems(){
+		return matrices.size();
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public Integer2DArray getItem(int index){
+		if (index<0 || index >= getNumItems())
+			return null;
+		return (Integer2DArray)matrices.elementAt(index);
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public String getItemName(int index){
+		if (index<0 || index >= getNumItems())
+			return null;
+		return ((Integer2DArray)matrices.elementAt(index)).getName();
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((Integer2DArray)matrices.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+
+	}
+	/*..........................................MMeristicAdjustable................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		Integer2DArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		matrices.removeElement(matrix);
+		if (item == 0) {
+			firstMatrix = (Integer2DArray)matrices.elementAt(0);
+		}
+	}
+	/*..........................................MMeristicAdjustable................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+			Integer2DArray matrix =getItem(index);
+			matrix.setNameReference(nr);
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void deassignStates(){
+		for (int i=0; i<getNumItems(); i++){
+			Integer2DArray matrix = getItem(i);
+			if (matrix !=null)
+				for (int k=0; k<numChars; k++)
+					for (int j=0; j<numTaxa; j++)
+						matrix.setValue(k, j, MeristicState.unassigned); 
+		}
+	}
+	
+	/*..........................................MMeristicAdjustable................*/
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public void transferFrom(int ic, CharacterDistribution s) { 
+		if (s instanceof MeristicDistribution) {
+			setItemsAs(((MeristicDistribution)s));
+			for (int item=0; item<((MeristicDistribution)s).getNumItems(); item++) {
+				Integer2DArray matrix = getItem(item);
+				if (matrix !=null)
+					for (int j=0; j<getNumNodes(); j++)
+						matrix.setValue(ic, j,  ((MeristicDistribution)s).getState(j, item));
+			}
+		}
+	}
+	
+	/*..........................................MMeristicAdjustable................*/
+	public int getState (int ic, int N, int item) {
+		
+		if (getItem(item)!=null)
+			return getItem(item).getValue(ic, N);
+		else
+			return MesquiteInteger.unassigned;
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setStates (Vector matrices) {
+		if (matrices==null)
+			return;
+		this.matrices = matrices;
+		firstMatrix = (Integer2DArray)matrices.elementAt(0);
+		if (firstMatrix !=null) {
+			numTaxa = firstMatrix.getSizeT();
+			numChars = firstMatrix.getSizeC();
+		}
+		
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setStates (Integer2DArray matrix) {
+		if (matrix==null)
+			return;
+		matrices.removeAllElements();
+		matrices.addElement(matrix);
+		firstMatrix = matrix;
+		if (firstMatrix !=null) {
+			numTaxa = firstMatrix.getSizeT();
+			numChars = firstMatrix.getSizeC();
+		}
+		
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setState (int ic, int N,  int item, int d) {  //THIS SHOULD BE ic, it not it, ic
+		if (item>= matrices.size())
+			return;
+		Integer2DArray matrix = (Integer2DArray)matrices.elementAt(item);
+		matrix.setValue(ic,N, d);
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public int getState (int ic, int N) {
+		return firstMatrix.getValue(ic, N);
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public void setState (int ic, int N, int d) {
+		firstMatrix.setValue(ic,N, d);
+	}
+	
+	/*..........................................  MMeristicAdjustable  ..................................................*
+	/**sets the character state of character ic and taxon it to that in the passed CharacterState*
+   	public void setCharacterState(CharacterState s, int ic, int it){
+   		if (s instanceof MeristicState){
+   			MeristicState cs = ((MeristicState)s);
+			for (int item=0; item<getNumItems() && item<cs.getNumItems(); item++) {
+				Integer2DArray matrix = (Integer2DArray)matrices.elementAt(item);
+				matrix.setValue(ic, it, cs.getValue(item));
+			}
+   		}
+   	}
+	/*..........................................MMeristicAdjustable................*/
+   	/** sets the state of character ic in taxon it from CharacterState cs.  If incoming CharacterState has more items
+   	or items with names not seen in this MeristicData, then new items are created in the MeristicData*/
+   	public  void setCharacterState(CharacterState cs, int ic, int it){
+   		
+   		if (cs !=null && cs instanceof MeristicState) {
+   			MeristicState contS = (MeristicState)cs;
+   			if (contS.getNumItems()==1 && getNumItems()==1 && (contS.getItemReference(0) == null || getItemReference(0) == null || contS.getItemReference(0) == getItemReference(0))){
+	   			setState(ic, it, 0, contS.getValue(0));  
+   			}
+   			else {
+	   			int made = 0;
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+	   					establishItem(nr.getValue());
+	   					made++;
+	   				}
+	   			}
+	   			int numToMake = contS.getNumItems() - getNumItems();
+	   			for (int i=0; i< numToMake; i++)
+	   				addItem((NameReference)null);
+	   			int currentOpen = 0;
+	   			//unnamed items in incoming character state will be applied to first available items whose names are not in incoming character state
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (getItemNumber(nr)>=0) {//named item found; set state
+	   					setState(ic, it, getItemNumber(nr), contS.getValue(i));  
+	   				}
+	   				else { //put it in next slot in this that has no corresponding in contS
+	   					boolean found = false;
+	   					for (int item = currentOpen; item<getNumItems() && !found; item++){
+	   						NameReference nrM = getItemReference(item);
+	   						if (nrM == null || contS.getItemNumber(nrM) < 0){
+	   							setState(ic, it, item, contS.getValue(i));
+	   							currentOpen = item+1;
+	   							found = true;
+	   						}
+	   					}
+	   				}
+	   			}
+   			}
+  		}
+   	}
+	/*..........................................MMeristicAdjustable................*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) { 
+		if (checkIllegalNode(it, 9132) && checkIllegalNode(it, 9133) && ic <numChars)
+			return;
+		for (int item=0; item<getNumItems(); item++) {
+			Integer2DArray matrix = (Integer2DArray)matrices.elementAt(item);
+			int temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic,it2));
+			matrix.setValue(ic, it2, temp);
+		}
+	}
+	/*..........................................MMeristicAdjustable................*/
+	public CharacterDistribution getCharacterDistribution (int ic) {
+		MeristicAdjustable soc = new MeristicAdjustable(getTaxa(), numTaxa);
+		soc.setItemsAs(this);
+		for (int it = 0; it<numTaxa; it++) {
+			for (int item=0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(ic, it, item)); 
+		}
+		if (getParentData()!=null)
+			soc.setName("Character " + ic + " of " + getParentData().getName());
+		else
+			soc.setName("Character " + ic );
+		return soc;
+	}
+	public int getNumTaxa(){
+		return numTaxa;
+	}
+	public int getNumNodes(){ //TODO: a distinction should be made in Histories between taxa and nodes
+		return numTaxa;
+	}
+	public int getNumChars(){
+		return numChars;
+	}
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MMeristicDistribution.java b/Source/mesquite/meristic/lib/MMeristicDistribution.java
new file mode 100644
index 0000000..25e7144
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MMeristicDistribution.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.categ.lib.MDNAHistory;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  meristic character states for many characters, at each of the taxa or nodes.*/
+public abstract class MMeristicDistribution  extends MMeristicStates implements MCharactersDistribution {
+	public MMeristicDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................MMeristicDistribution................*/
+	public abstract CharacterDistribution getCharacterDistribution (int ic);
+	/*-----*/
+	/*..........................................MMeristicDistribution................*/
+	public abstract Integer2DArray getItem(int index);
+	/*..........................................MMeristicDistribution................*/
+	/**return blank adjustable MMeristicDistribution if this same type */
+	public MAdjustableDistribution makeBlankAdjustable(){
+		MMeristicAdjustable mca = new MMeristicAdjustable(getTaxa(), getNumChars(), getNumNodes()); 
+		mca.setItemsAs(this);
+		return mca;
+	}
+	/*..........................................MMeristicDistribution................*/
+	/**return CharacterData filled with same values as this matrix */
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){
+		MeristicData data = new MeristicData(manager, taxa.getNumTaxa(), getNumChars(), taxa);
+		data.setMatrix(this); 
+		if (this instanceof Annotatable && ((Annotatable)this).getAnnotation()!=null)
+			data.setAnnotation(((Annotatable)this).getAnnotation(), false);
+		else if (getParentData()!=null && getParentData().getAnnotation()!=null)
+			data.setAnnotation(getParentData().getAnnotation(), false);
+		return data;
+	}
+	/*..........................................MMeristicDistribution................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public MCharactersHistory adjustHistorySize(Tree tree, MCharactersHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		MCharactersHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MMeristicHistory.class)) 
+			soc = new MMeristicHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else if (numNodes!= charStates.getNumNodes() || charStates.getNumChars()!= getNumChars()) 
+			soc = new MMeristicHistory(tree.getTaxa(), getNumChars(), numNodes);
+		else {
+			soc =charStates;
+		}
+		((MMeristicHistory)soc).setItemsAs(this);
+		soc.setParentData(getParentData());
+		return soc;
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MMeristicEmbedded.java b/Source/mesquite/meristic/lib/MMeristicEmbedded.java
new file mode 100644
index 0000000..7fc5f65
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MMeristicEmbedded.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**A class for an array of  meristic character states for many characters, at each of the taxa or nodes.*/
+public class MMeristicEmbedded  extends MMeristicDistribution {
+	
+	public MMeristicEmbedded (CharacterData data) {
+		super(data.getTaxa());
+		this.data = data;
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public Integer2DArray getItem(int index){
+		return ((MeristicData)data).getItem(index);
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public String getItemName(int index){
+		return ((MeristicData)data).getItemName(index);
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public int getItemNumber(NameReference nr){
+		return ((MeristicData)data).getItemNumber(nr);
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public  int getNumberOfItems() {
+		return ((MeristicData)data).getNumItems();
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public  int getState (int ic, int N,  int item){
+		return ((MeristicData)data).getState(ic, N, item);
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public  int getState (int ic, int N){
+		return getState(ic, N, 0); 
+	}
+	/*..........................................MMeristicEmbedded................*/
+	public CharacterDistribution getCharacterDistribution (int ic){
+		return data.getCharacterDistribution(ic);
+	}
+	public int getNumTaxa(){
+		return data.getNumTaxa();
+	}
+	public int getNumNodes(){
+		return data.getNumTaxa();
+	}
+	public int getNumChars(){
+		return data.getNumChars();
+	}
+	public String getName(){
+		return data.getName();
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MMeristicHistory.java b/Source/mesquite/meristic/lib/MMeristicHistory.java
new file mode 100644
index 0000000..d90fbfb
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MMeristicHistory.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+
+/* ======================================================================== */
+/**A class for an array of  meristic character states for many characters, at each of the nodes.*/
+public class MMeristicHistory  extends MMeristicAdjustable implements MCharactersHistory {
+	
+	public MMeristicHistory (Taxa taxa, int numChars, int numNodes) {
+		super(taxa, numChars, numNodes);
+	}
+	
+	public MMeristicHistory (Taxa taxa) {
+		super(taxa);
+	}
+	
+	/*..........................................MMeristicHistory................*/
+	/** extract the states of character ic and return as CharacterHistory*/
+	public CharacterHistory getCharacterHistory (int ic){
+		MeristicHistory soc = new MeristicHistory(getTaxa(), getNumNodes(), (MeristicData)getParentData());
+		soc.setItemsAs(this);
+		for (int it = 0; it<getNumNodes(); it++) {
+			for (int item=0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(ic, it, item)); 
+		}
+		return soc;
+	}
+	/*..........................................MMeristicHistory................*/
+	/** obtain the states of character ic from the given CharacterDistribution*/
+	public void transferFrom(int ic, CharacterHistory s) { 
+		if (s instanceof MeristicHistory) {
+			setItemsAs(((MeristicHistory)s));
+			for (int j=0; j<getNumNodes(); j++)
+				for (int item=0; item<((MeristicHistory)s).getNumItems(); item++) {
+					if (getItem(item)!=null)
+						getItem(item).setValue(ic, j,  ((MeristicHistory)s).getState(j, item));
+				}
+		}
+	}
+	int minState = MesquiteInteger.unassigned;
+	int maxState = MesquiteInteger.unassigned;
+	/*..........................................MMeristicHistory................*/
+	private void calcMinMaxStates(Tree tree, int node, int item) {
+		for (int ic=0; ic<getNumChars(); ic++){
+			int s=getState(ic, node, item); 
+			minState = MesquiteInteger.minimum(s, minState);
+			maxState = MesquiteInteger.maximum(s, maxState);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				calcMinMaxStates(tree, d, item);
+	}
+	public void getMinMax(Tree tree, int root, int item, MesquiteInteger min, MesquiteInteger max){
+		if (min == null || max==null)
+			return;
+		minState = MesquiteInteger.unassigned;
+		maxState = MesquiteInteger.unassigned;
+		calcMinMaxStates(tree, root, item);
+		min.setValue(minState);
+		max.setValue(maxState);
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MMeristicStates.java b/Source/mesquite/meristic/lib/MMeristicStates.java
new file mode 100644
index 0000000..d7fafcd
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MMeristicStates.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.ItemContainer;
+
+
+/* ======================================================================== */
+/**A class for an array of  meristic character states for many characters, at each of the taxa or nodes.*/
+public abstract class MMeristicStates extends MCharactersStates implements ItemContainer {
+	long id;
+	static long totalCreated = 0;
+	public MMeristicStates (Taxa taxa) {
+		super(taxa);
+		totalCreated++;
+		id = totalCreated;
+	}
+	
+	public long getID(){
+		return id;
+	}
+	/*..........................................  MMeristicStates  ..................................................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return MeristicState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return MeristicData.class;
+	}
+	/*..........................................  MMeristicStates  ..................................................*/
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return MeristicData.DATATYPENAME;
+	}
+	/*..........................................  MMeristicStates  ..................................................*/
+	/**returns state of character ic in taxon/node it */
+	public abstract int getState (int ic, int it);
+
+	/*..........................................MMeristicStates................*/
+	/**returns state of item item of character ic in taxon/node it */
+	public abstract int getState (int ic, int it, int item);
+	
+	/*..........................................MMeristicStates................*/
+	public abstract Integer2DArray getItem(int index);
+	
+	/*..........................................MMeristicStates................*/
+	public int[][] getMatrix(int index){
+		Integer2DArray m2da = getItem(index);
+		if (m2da==null)
+			return null;
+		return m2da.getMatrix();
+	}
+	/*..........................................MMeristicStates................*/
+   	public int userQueryItem(String message, MesquiteModule module){
+		int numItems =getNumItems();
+		String[] items = new String[numItems];
+		for (int i=0; i<items.length; i++){
+			if (StringUtil.blank(getItemName(i)))
+				items[i] = "(unnamed)";
+			else
+				items[i]= getItemName(i);
+		}
+		return ListDialog.queryList(module.containerOfModule(), "Select item", message, MesquiteString.helpString,  items, 0);
+   	}
+	/*..........................................MMeristicStates................*/
+	public abstract String getItemName(int index);
+	/*..........................................MMeristicStates................*/
+	public abstract int getItemNumber(NameReference nr);
+	/*..........................................MMeristicStates................*/
+	public abstract int getNumberOfItems();
+	/*..........................................MMeristicStates................*/
+	public int getNumItems(){
+		return getNumberOfItems();
+	}
+	/*..........................................MMeristicStates................*/
+	public boolean allCombinable(){
+		for (int item = 0; item < getNumberOfItems(); item ++)
+			for (int ic = 0; ic < getNumChars(); ic++)
+				for (int it = 0; it<getNumNodes(); it++) {
+					if (!MesquiteInteger.isCombinable(getState(ic, it, item)))
+						return false;
+				}
+		return true;
+	}
+	/*..........................................MMeristicStates................*/
+	public boolean allCombinable(int item){
+		for (int ic = 0; ic < getNumChars(); ic++)
+			for (int it = 0; it<getNumNodes(); it++) {
+				if (!MesquiteInteger.isCombinable(getState(ic, it, item)))
+					return false;
+			}
+		return true;
+	}
+	/*..........................................MMeristicStates................*/
+	public NameReference getItemReference(int n){
+		return NameReference.getNameReference(getItemName(n));
+	}
+	/*..........................................MMeristicStates................*/
+	public NameReference getItemReference(String name){
+		return NameReference.getNameReference(name);
+	}
+	/*..........................................MMeristicStates................*/
+	/** get CharacterState at node N*/
+	public CharacterState getCharacterState (CharacterState cs, int ic, int it){  
+		MeristicState c;
+		if (cs !=null && cs instanceof MeristicState)
+			c = (MeristicState)cs;
+		else
+			c = new MeristicState(); 
+		c.setItemsAs(this);
+		for (int item = 0; item<getNumberOfItems(); item++)
+			c.setValue(item, getState(ic, it, item));
+		return c;
+	}
+	/*..........................................MMeristicDistribution................*/
+   	public String toString(){
+   		return "Meristic matrix (" + getClass().getName() + ") id: " + getID() + " chars: " + getNumChars() + " taxa: " + getNumTaxa() + " items " + getNumItems();
+   	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MeristicAdjustable.java b/Source/mesquite/meristic/lib/MeristicAdjustable.java
new file mode 100644
index 0000000..785da60
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicAdjustable.java
@@ -0,0 +1,289 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.ItemContainer;
+
+/* ======================================================================== */
+/** Contains an array of  meristic character states for one character, at each of the taxa or nodes */
+public class MeristicAdjustable  extends MeristicDistribution implements AdjustableDistribution {
+	protected IntegerArray firstItem; //other dimension for items (sample size, variance, etc., etc.)
+	protected Vector items;
+	protected int numNodes;
+	
+	public MeristicAdjustable (Taxa taxa, int numNodes) {
+		super(taxa);
+		items = new Vector();
+		this.numNodes= numNodes;
+		firstItem = new IntegerArray(numNodes); 
+		items.addElement(firstItem);
+		deassignStates();
+	}
+	
+	/*..........................................MeristicAdjustable................*/
+	public int getNumItems() {
+		return items.size();
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public int getNumTaxa() {
+		return numNodes;
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public int getNumNodes() {
+		return numNodes;
+	}
+	/*.........................................MeristicAdjustable...............*/
+	/* makes new item*/
+	public IntegerArray addItem(NameReference nr){
+		IntegerArray item = new IntegerArray(numNodes);
+			if (firstItem == null)
+				firstItem = item; 
+			if (nr!=null)
+				item.setNameReference(nr);
+			for (int it=0; it<numNodes; it++)
+					item.setValue(it, MeristicState.unassigned);
+			items.addElement(item);
+			return item;
+	}
+	
+	/*.........................................MeristicAdjustable...............*/
+	public IntegerArray establishItem(String name){
+		return establishItem(NameReference.getNameReference(name));
+	}
+	/*.........................................MeristicAdjustable...............*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public IntegerArray establishItem(NameReference nr){
+		if (firstItem != null && firstItem.getNameReference()==null && items.size() ==1) {
+			if (nr!=null)
+				firstItem.setNameReference(nr);
+			return firstItem;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				IntegerArray matrix = (IntegerArray)items.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(nr);
+					return matrix;
+				}
+			}
+			return addItem(nr);
+		}
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public IntegerArray addItem(String name){
+		return addItem(NameReference.getNameReference(name));
+	}
+	/*..........................................MeristicStates................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+
+	}
+	/*..........................................MeristicData................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		IntegerArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		items.removeElement(matrix);
+		if (item == 0) {
+			firstItem = (IntegerArray)items.elementAt(0);
+		}
+	}
+	/*..........................................MeristicStates................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+			IntegerArray matrix =getItem(index);
+			matrix.setNameReference(nr);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public void setItems(MeristicAdjustable s){
+		if (s==null)
+			setItems((String[])null);
+		else {
+			String[] names = new String[s.getNumItems()];
+			for (int i=0; i<s.getNumItems(); i++) {
+				NameReference nr = s.getItemReference(i);
+				if (nr==null)
+					names[i] = null;
+				else
+					names[i] = nr.getValue();
+			}
+			setItems(names);
+		}
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public void setItems(String[] names){
+		if (names == null) { //setting to a single item with null name
+			if (getNumItems() == 0) {
+				addItem((NameReference)null);
+			}
+			else if (getNumItems() == 1)
+				firstItem.setNameReference(null);
+			else {
+				items.removeAllElements();
+				firstItem = null;
+				establishItem((NameReference)null);
+			}
+		}
+		else {
+			if (getNumItems() == names.length) {
+				for (int i=0; i<getNumItems(); i++) {
+					IntegerArray item = (IntegerArray)items.elementAt(i);
+					item.setNameReference(NameReference.getNameReference(names[i])); //SHOULD pass string and change only if needed
+				}
+			}
+			else if (getNumItems()< names.length) {
+				for (int i=0; i<getNumItems(); i++) {
+					IntegerArray item = (IntegerArray)items.elementAt(i);
+					item.setNameReference(NameReference.getNameReference(names[i]));
+				}
+				for (int i=getNumItems(); i<names.length; i++)
+					addItem(names[i]);
+			}
+			else {
+				items.removeAllElements();
+				firstItem = null;
+				for (int i=getNumItems(); i<names.length; i++)
+					establishItem(names[i]);
+			}
+		}
+		
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public IntegerArray getItem(int index){
+		if (index<0 || index>= items.size())
+			return null;
+		return (IntegerArray)items.elementAt(index);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public String getItemName(int index){
+			if (items == null)
+				return null;
+			else
+				return ((IntegerArray)items.elementAt(index)).getName();
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public NameReference getItemReference(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		for (int i=0; i<getNumItems(); i++) {
+			IntegerArray item = (IntegerArray)items.elementAt(i);
+			if (nr.equals(item.getNameReference()))
+				return item.getNameReference();
+		}
+		return null;
+		
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public NameReference getItemReference(int index){
+			IntegerArray item = (IntegerArray)items.elementAt(index);
+			return item.getNameReference();
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((IntegerArray)items.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	
+	/*.........................................MeristicAdjustable...............*/
+	public void deassignStates(){
+		for (int i=0; i<getNumItems(); i++)
+			for (int j=0; j<numNodes; j++)
+				((IntegerArray)items.elementAt(i)).setValue(j, MeristicState.unassigned);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public int getState (int N, int item) {
+		if (item>=getNumItems()) //ERROR MESSAGE
+			return 0;
+		else if (N>=numNodes) {
+			return 0;
+		}
+		else
+			return ((IntegerArray)items.elementAt(item)).getValue(N);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public int getState (int N) {
+		return firstItem.getValue(N);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public void setState (int N, int item, int d) {
+		((IntegerArray)items.elementAt(item)).setValue(N, d);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public void setState (int N, int d) {
+		firstItem.setValue(N, d);
+	}
+	/*.........................................MeristicAdjustable...............*/
+	public void setCharacterState (int N, CharacterState cs) {
+		if (checkIllegalNode(N, 7))
+			return;
+		if (cs == null || !(cs instanceof MeristicState))
+			return; 
+		for(int i=0; i<getNumItems(); i++)
+			setState(N, i, ((MeristicState)cs).getValue(i));
+	}
+	/*..........................................  MeristicAdjustable ..................................................*/
+	/**Trade states of nodes it and it2*/
+	public void tradeStatesBetweenTaxa(int it, int it2) {
+		if (checkIllegalNode(it, 9128) && checkIllegalNode(it, 9129))
+			return;
+		for (int item=0; item<getNumItems(); item++) {
+			IntegerArray matrix = getItem(item);
+			int temp = matrix.getValue(it);
+			matrix.setValue(it, matrix.getValue(it2));
+			matrix.setValue(it2, temp);
+		}
+	}
+	/*.........................................MeristicAdjustable...............*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public AdjustableDistribution adjustSize(Taxa taxa) {
+		if (taxa.getNumTaxa() == this.getNumTaxa())
+			return this;
+		else {
+			MeristicAdjustable soc = new MeristicAdjustable(taxa, taxa.getNumTaxa());
+			soc.setItemsAs(this);
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			((CharacterStates)soc).setExplanation(getExplanation());
+			return soc;
+		}
+	}
+/**/
+}
+
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicData.java b/Source/mesquite/meristic/lib/MeristicData.java
new file mode 100644
index 0000000..6760039
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicData.java
@@ -0,0 +1,1174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import java.util.zip.*;
+
+import mesquite.cont.lib.ContinuousState;
+import mesquite.cont.lib.ItemContainer;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** A subclass of CharacterData for meristic-valued data.  Can handle more than one item per matrix of cell
+(e.g., for mean, variance, etc.)  Each item is stored in a separate matrix; new items can be added by adding matrices.   Items are refered to by
+their name (e.g., MEAN, VARIANCE, etc.); each item has a NameReference associated to speed up queries. NOTE: At present,
+the support for multiple items is only just beginning to be implemented, and is fragmentary.  Many methods currently use just the first item.*/
+public class MeristicData extends CharacterData implements ItemContainer {
+	private Integer2DArray firstMatrix;
+	public static String DATATYPENAME="Meristic Data";
+	protected Vector matrices;
+	private static Vector defaultModels;
+	public boolean hasNegatives = false; //temporary variable used just while reading from file
+	static {
+		defaultModels= new Vector(2);
+	}
+	public MeristicData(CharMatrixManager manager, int numTaxa, int numChars, Taxa taxa){
+		super(manager, numTaxa, numChars,taxa);
+		firstMatrix = new Integer2DArray(numChars, numTaxa);
+		matrices = new Vector(1);
+		matrices.addElement(firstMatrix);
+		firstMatrix.deassignArray();
+		setInapplicableSymbol(MeristicState.inapplicableChar);
+	}
+	public String getDefaultIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixMeristicSmall.gif";
+	}
+	
+/*..........................................  MeristicData  ..................................................*/
+	public void dispose(){
+		super.dispose();
+		if (matrices!=null){ //update size of specification sets
+			for (int i=0; i<matrices.size(); i++) {
+				Integer2DArray sv = (Integer2DArray)matrices.elementAt(i);
+				sv.dispose();
+			}
+		}
+		matrices = null;
+	}
+	/*..........................................  MeristicData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData, boolean allowDifferentSizes){
+		if ((sourceData.getNumTaxa()==getNumTaxa() && sourceData.getNumChars() == getNumChars()) || allowDifferentSizes) {
+			MeristicData cD = (MeristicData)sourceData;
+			int nItems = getNumItems();
+			setItemsAs(cD);
+			for (int i=0; i<nItems; i++){
+				Integer2DArray imatrix = cD.getItem(i);
+				Integer2DArray currentMatrix= getItem(i);
+				for (int ic = 0; ic< numChars; ic++)
+					for (int it = 0; it<numTaxa; it++)
+						if (it>=sourceData.getNumTaxa() || ic>=sourceData.getNumChars())
+							currentMatrix.setValue(ic, it, MeristicState.unassigned); 
+						else
+							currentMatrix.setValue(ic,it,imatrix.getValue(ic,it));
+			}
+		}
+	}
+	
+	public void copyDataBlock(CharacterData sourceData, int icStart, int icEnd, int itStart, int itEnd){
+			MeristicData cD = (MeristicData)sourceData;
+			int nItems = getNumItems();
+			setItemsAs(cD);
+			for (int i=0; i<nItems; i++){
+				Integer2DArray imatrix = null;
+					imatrix = cD.getItem(i);
+				Integer2DArray currentMatrix= getItem(i);
+				for (int ic=icStart; ic<=icEnd; ic++){
+					for (int it=itStart; it<=itEnd; it++) {
+						int itSource = it-itStart;
+						int icSource = ic-icStart;
+						if (itSource<sourceData.getNumTaxa() || icSource<sourceData.getNumChars())
+							currentMatrix.setValue(ic,it,imatrix.getValue(icSource,itSource));
+					}
+				}
+			}
+			resetCellMetadata();
+		
+	}
+
+	/*..........................................  MeristicData  ..................................................*/
+	/** copy the basic data.  Does not copy the associated specs sets etc.*/
+	public  void copyData(CharacterData sourceData){
+		copyData(sourceData,false);
+	}
+	/*..........................................MeristicData................*/
+	/** clones this ContinousData.  Does not include associated specsets etc. */
+	public CharacterData cloneData(){
+		MeristicData cD = new MeristicData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+		int nItems = getNumItems();
+		cD.setItemsAs(this);
+		for (int i=0; i<nItems; i++){
+			Integer2DArray imatrix = cD.getItem(i);
+			Integer2DArray oldMatrix= getItem(i);
+			for (int ic = 0; ic< numChars; ic++)
+				for (int it = 0; it<numTaxa; it++)
+					imatrix.setValue(ic,it,oldMatrix.getValue(ic,it));
+		}
+		for (int ic = 0; ic< numChars; ic++)
+			if (getSelected(ic))
+				cD.setSelected(ic, true);
+
+		return cD;
+	}
+	
+	/*..........................................  CategoricalData  ..................................................*/
+	/**clone a portion of CharacterData and return new copy.  Does not clone the associated specs sets etc.*/ //TODO: here should use super.setToClone(data) to handle specssets etc.???
+	public CharacterData cloneDataBlock(int icStart, int icEnd, int itStart, int itEnd){
+		int blockChars = icEnd-icStart+1;
+		int blockTaxa = itEnd-itStart+1;
+		boolean[] taxaToClone = new boolean[getNumTaxa()];
+		for (int it=0; it<getNumTaxa(); it++) {
+			taxaToClone[it] = it>=itStart && it<=itEnd;
+		}
+		Taxa taxa = getTaxa().cloneTaxa(taxaToClone);
+		
+		MeristicData cD = new MeristicData(getMatrixManager(), blockTaxa, blockChars, taxa);
+		int nItems = getNumItems();
+		cD.setItemsAs(this);
+		for (int i=0; i<nItems; i++){
+			Integer2DArray imatrix = cD.getItem(i);
+			Integer2DArray oldMatrix= getItem(i);
+			for (int ic=icStart; ic<=icEnd; ic++)
+				for (int it = itStart; it<=itEnd; it++)
+					imatrix.setValue(ic-icStart,it-itStart,oldMatrix.getValue(ic,it));
+		}
+		for (int ic = 0; ic< numChars; ic++)
+			if (getSelected(ic))
+				cD.setSelected(ic-icStart, true);
+
+		return cD;
+	}
+
+	public int getNumTaxa(){
+		return getNumTaxa(true);
+	}
+	public int getNumTaxa(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumTaxa(notifyIfError);
+		if (!notifyIfError)
+			return n;
+		if (firstMatrix == null)
+			dataIntegrityReportableAlert(getDataTypeName() + " with null internal matrix. getNumTaxa() = " + n);
+		else if (firstMatrix.getSizeT() != n)
+			dataIntegrityReportableAlert("Meristic matrix with incorrect record of number of taxa. getNumTaxa() = " + n + " firstMatrix.getSizeT() " + firstMatrix.getSizeT());
+		return n;
+	}
+	public int getNumChars(){
+		return getNumChars(true);
+	}
+	public int getNumChars(boolean notifyIfError){
+		if (disposed)
+			return 0;
+		int n = super.getNumChars(notifyIfError);
+		if (firstMatrix == null){
+			if (notifyIfError)
+				dataIntegrityReportableAlert(getDataTypeName() + " with null internal matrix. getNumChar() = " + n  + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return 0;
+		}
+		else if (firstMatrix.getSizeC() < n){
+			if (notifyIfError)
+				dataIntegrityReportableAlert("Meristic matrix with incorrect record of number of characters. getNumChar() = " + n + " firstMatrix.getSizeC() " + firstMatrix.getSizeC() + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return firstMatrix.getSizeC();
+		}
+		else if (firstMatrix.getSizeC() > n){
+			if (notifyIfError)
+				dataIntegrityReportableAlert("Meristic matrix with incorrect record of number of characters. getNumChar() = " + n + " firstMatrix.getSizeC() " + firstMatrix.getSizeC() + " nAdd = " + nAdd + " nDel = " + nDel + " nMove = " + nMove);
+			return n;
+		}
+		return n;
+	}
+	/*..........................................MeristicData................*/
+	/** Removes item.*/
+	public void removeItem(int item){
+		if (item<0 || item> getNumItems()-1)
+			return;
+		Integer2DArray matrix = getItem(item);
+		if (matrix==null)
+			return;
+		matrices.removeElement(matrix);
+		if (item == 0) {
+			firstMatrix = (Integer2DArray)matrices.elementAt(0);
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** Make an item with the passed name.  If the an item already made is not yet named,
+	then this will simply use this item and give it a new name.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Integer2DArray establishItem(String name){
+
+		setDirty(true);
+		incrementStatesVersion();
+		if (firstMatrix != null && firstMatrix.getNameReference()==null && name!=null && matrices.size() ==1) {
+			firstMatrix.setNameReference(NameReference.getNameReference(name));
+			return firstMatrix;
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				Integer2DArray matrix = (Integer2DArray)matrices.elementAt(i);
+				if (matrix.getNameReference()== null) {
+					matrix.setNameReference(NameReference.getNameReference(name));
+					return matrix;
+				}
+			}
+
+			return addItem(name);
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** Make an item with the passed name.  If the first item already made is not yet named and if it is the only item so far,
+	then makeItem is assumed to be simply applying a name to this first item, and no new item is made.  Otherwise, a new
+	matrix is made for a new item, and the name is attached to it.*/
+	public Integer2DArray addItem(String name){
+		setDirty(true);
+		incrementStatesVersion();
+		Integer2DArray matrix = new Integer2DArray(numChars, numTaxa);
+		if (firstMatrix == null)
+			firstMatrix = matrix;
+		matrix.setNameReference(NameReference.getNameReference(name));
+		matrix.deassignArray();
+		matrices.addElement(matrix);
+		return matrix;
+	}
+	/*..........................................MeristicData................*/
+	/**Get the name reference for the item of name "name".  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(String name){
+		NameReference nr = NameReference.getNameReference(name);
+		if (nr ==null) return null; //added 8 Dec 01
+		for (int i=0; i<getNumItems(); i++) {
+			Integer2DArray matrix = (Integer2DArray)matrices.elementAt(i);
+			if (nr.equals(matrix.getNameReference()))
+				return matrix.getNameReference();
+		}
+		return null;
+
+	}
+	/*..........................................MeristicData................*/
+	/**Get the name reference for the item number "index".  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(int index){
+		Integer2DArray matrix = (Integer2DArray)matrices.elementAt(index);
+		if (matrix ==null) return null; //added 8 Dec 01
+		return matrix.getNameReference();
+	}
+	/*..........................................MeristicState................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		for (int i=0; i<iCont.getNumItems(); i++) {
+			if (i<getNumItems() )
+				setItemReference(i, iCont.getItemReference(i));
+			else
+				addItem(iCont.getItemName(i));
+		}
+		if (getNumItems()>iCont.getNumItems())
+			for (int i = getNumItems(); i>=iCont.getNumItems(); i--)
+				removeItem(i);
+	}
+	/*..........................................MeristicData................*/
+	/**Sets the name reference for the item number "index".*/
+	public void setItemReference(int index, NameReference nr){
+		Integer2DArray matrix = (Integer2DArray)matrices.elementAt(index);
+		if (matrix ==null) return; //added 8 Dec 01
+		matrix.setNameReference(nr);
+		setDirty(true);
+	}
+	/*..........................................MeristicData................*/
+	/**Get the name reference for the item whose name matches the name in the passed NameReference.  This is done so that subsequent calls can compare name references,
+	which may be identical thus saving the effort of checking strings*/
+	public NameReference getItemReference(NameReference nr){
+		if (nr ==null) return null; //added 8 Dec 01
+		for (int i=0; i<getNumItems(); i++) {
+			Integer2DArray matrix = (Integer2DArray)matrices.elementAt(i);
+			if (matrix !=null && nr.equals(matrix.getNameReference())) //modified 8 Dec 01
+				return matrix.getNameReference();
+		}
+		return null;
+
+	}
+	/*..........................................MeristicData................*/
+	/** Get the item name of the item number "index" */
+	public String getItemName(int index){
+		Integer2DArray matrix;
+		if (matrices == null)
+			matrix = firstMatrix;
+		else
+			matrix = (Integer2DArray)matrices.elementAt(index);
+		if (matrix ==null) return null; //added 8 Dec 01
+
+		if (matrix.getNameReference()==null)
+			return null;
+		else
+			return matrix.getNameReference().getValue();
+	}
+	/*..........................................MeristicData................*/
+	/** Get which item has name matching the reference */
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<getNumItems(); i++)
+			if (nr.equals(((Integer2DArray)matrices.elementAt(i)).getNameReference()))
+				return i;
+		return -1;
+	}
+	/*..........................................MeristicData................*/
+	/** get the number of items. */
+	public int getNumItems(){
+		if (matrices == null)
+			return 0;
+		return matrices.size();
+	}
+	public String getCellContentsDescription(){
+		boolean nameFound = false;
+		for (int i=0; i<getNumItems() && !nameFound; i++)
+			nameFound= !StringUtil.blank(getItemName(i));
+		if (!nameFound)
+			return null;
+		String descr = "(";
+		boolean first = true;
+		for (int i=0; i<getNumItems(); i++) {
+			String iN = getItemName(i);
+			if (StringUtil.blank(iN))
+				iN = "unnamed";
+			if (first) {
+				descr += iN;
+				first = false;
+			}
+			else
+				descr += ", " + iN;
+		}
+		return descr + ")";
+	}
+	/*..........................................MeristicData................*/
+	/**Adds num characters after position "starting"; returns true iff successful.*/
+	public  boolean addParts(int starting, int num){
+		if (getMaxNumChars()!=MesquiteInteger.infinite && numChars+num>getMaxNumChars())
+			return false;
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numChars)
+			starting = numChars-1;
+		int newNumChars = numChars + num;
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray newMatrix = new Integer2DArray(newNumChars, numTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int it=0; it<numTaxa; it++) {
+				for (int ic=0; ic<=starting; ic++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+				for (int ic=0; ic<num; ic++)
+					newMatrix.setValue(ic + starting +1,it,MeristicState.unassigned); //filling new part with missing data
+				for (int ic=0; ic<numChars - starting -1 ; ic++)
+					newMatrix.setValue(ic + starting + num + 1,it,oldMatrix.getValue(starting + ic+1,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices = newMatrices;
+		return super.addParts(starting, num);
+	}
+	/*..........................................MeristicData................*/
+	/**Deletes num characters from position "starting"; returns true iff successful.*/
+	public boolean deleteParts(int starting, int num){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>numChars)
+			return false;
+		if (num+starting>numChars)
+			num = numChars-starting;
+		int newNumChars =numChars-num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray newMatrix = new Integer2DArray(newNumChars, numTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<starting; ic++){
+				for (int it=0; it<numTaxa; it++) 
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+			}
+			for (int ic=starting + num; ic<numChars ; ic++){
+				for (int it=0; it<numTaxa; it++) 
+					newMatrix.setValue(ic-num,it,oldMatrix.getValue(ic,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices.removeAllElements();
+		matrices = newMatrices;
+		return super.deleteParts(starting, num);
+	}
+	/*..........................................MeristicData................*/
+	/**swaps characters first and second.*/
+	public boolean swapParts(int first, int second){
+		if (first<0 || first >= numChars)
+			return false;
+		if (second<0 || second >= numChars)
+			return false;
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			Integer2DArray.swapColumns(oldMatrix.getMatrix(), first, second);
+		}
+		return super.swapParts(first, second);
+	}
+	/*..........................................MeristicData................*/
+	/**moves num characters from position "first" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveParts(int starting, int num, int justAfter){
+		if (!canMoveChars()) 
+			return false;
+		if (justAfter<0)
+			justAfter = -1;
+		else if (justAfter>=numChars)
+			justAfter = numChars-1;
+		if (starting<0 || starting >= numChars)
+			return false;
+		if (num<=0)
+			return false;
+		if (starting + num>numChars)
+			return false;
+
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			Integer2DArray.moveColumns(oldMatrix.getMatrix(), starting, num, justAfter);
+		}
+		return super.moveParts(starting, num, justAfter);
+	}
+	/*..........................................MeristicData................*/
+	/**Adds num taxa after position "starting"; returns true iff successful.*/
+	public boolean addTaxa(int starting, int num){
+		setDirty(true);
+		if (starting<0)
+			starting = -1;
+		else if (starting>=numTaxa)
+			starting = numTaxa-1;
+		int newNumTaxa = numTaxa + num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray newMatrix = new Integer2DArray(numChars, newNumTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<numChars; ic++){
+				for (int it=0; it<=starting; it++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+
+				for (int it=0; it<num; it++) 
+					newMatrix.setValue(ic,it + starting +1,MeristicState.unassigned); //filling new part with missing data
+
+				for (int it=0; it<numTaxa - starting -1; it++) 
+					newMatrix.setValue(ic,it + starting + num + 1,oldMatrix.getValue(ic,starting + it+1)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices.removeAllElements();
+		matrices = newMatrices;
+		numTaxa = newNumTaxa; 
+		incrementStatesVersion();
+		return super.addTaxa(starting, num);
+	}
+	/*..........................................MeristicData................*/
+	/**Deletes num taxa from position "starting"; returns true iff successful.*/
+	public boolean deleteTaxa(int starting, int num){
+		setDirty(true);
+
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		if (num+starting>numTaxa)
+			num = numTaxa-starting;
+		int newNumTaxa = numTaxa - num;
+
+		Vector newMatrices = new Vector();
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray newMatrix = new Integer2DArray(numChars, newNumTaxa);
+			if (item == 0)
+				firstMatrix = newMatrix;
+			Integer2DArray oldMatrix = ((Integer2DArray)matrices.elementAt(item));
+			newMatrix.setNameReference(oldMatrix.getNameReference());
+			for (int ic=0; ic<numChars; ic++){
+				for (int it=0; it<starting; it++)
+					newMatrix.setValue(ic,it,oldMatrix.getValue(ic,it)); //transferring old first part
+
+				for (int it=starting+num; it<numTaxa; it++) 
+					newMatrix.setValue(ic,it-num,oldMatrix.getValue(ic,it)); //transferring old second part
+			}
+			newMatrices.addElement(newMatrix);
+		}
+		matrices.removeAllElements();
+		matrices = newMatrices;
+		numTaxa = newNumTaxa; 
+		incrementStatesVersion();
+		return super.deleteTaxa(starting, num);
+	}
+	/*..........................................MeristicData................*/
+	/**moves num taxa from position "starting" to just after position "justAfter"; returns true iff successful.*/
+	public boolean moveTaxa(int starting, int num, int justAfter){
+		if (num<=0)
+			return false;
+		if (starting<0)
+			return false;
+		else if (starting>=numTaxa)
+			return false;
+		setDirty(true);
+		for (int item = 0; item<getNumItems(); item++){
+			Integer2DArray matrixA = ((Integer2DArray)matrices.elementAt(item));
+			int[][] matrix = matrixA.getMatrix();
+			for (int ic=0; ic<numChars; ic++)
+				matrix[ic] = IntegerArray.moveParts(matrix[ic], starting, num, justAfter);
+		}
+		incrementStatesVersion();
+		return super.moveTaxa(starting, num, justAfter);
+	}
+
+	/*..........................................MeristicData................*/
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return MeristicState.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return MeristicData.DATATYPENAME;
+	}
+
+	/*..........................................MeristicData................*/
+	public Integer2DArray getItem(int i){
+		if (matrices !=null && i>=0 && i<matrices.size())
+			return (Integer2DArray)matrices.elementAt(i);
+		return null;
+	}
+	/*..........................................MeristicData................*/
+	private Integer2DArray getItem(NameReference nr){
+		if (matrices == null)
+			return null;
+		for (int i=0; i<matrices.size(); i++) {
+			Integer2DArray matrix = (Integer2DArray)matrices.elementAt(i);
+			NameReference nRm = matrix.getNameReference();
+			if (nRm!=null && nRm.equals(nr))
+				return matrix;
+		}
+		return null;
+	}
+	/*..........................................MeristicData................*/
+	/** trades the states of character ic and ic2 in taxon it.  Used for reversing sequences (for example).*/
+	public void tradeStatesBetweenCharacters(int ic, int ic2, int it, boolean adjustCellLinked) { 
+		if (ic>=numChars || it>=numTaxa || ic < 0 || it < 0)
+			return;
+		super.tradeStatesBetweenCharacters(ic, ic2, it, adjustCellLinked);
+		for (int item=0; item<getNumItems(); item++) {
+			Integer2DArray matrix = getItem(item);
+			int temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic2,it));
+			matrix.setValue(ic2, it, temp);
+		}
+		incrementStatesVersion();
+		setDirty(true, ic, it);
+		setDirty(true, ic2, it);
+	}
+	/*..........................................MeristicData................*/
+	public void tradeStatesBetweenTaxa(int ic, int it, int it2) { 
+		if (ic>=numChars && it>=numTaxa &&  it2 >=numTaxa) 
+			return;
+		super.tradeStatesBetweenTaxa(ic, it, it2);
+		incrementStatesVersion();
+		setDirty(true);
+		for (int item=0; item<getNumItems(); item++) {
+			Integer2DArray matrix = getItem(item);
+			int temp = matrix.getValue(ic, it);
+			matrix.setValue(ic, it, matrix.getValue(ic,it2));
+			matrix.setValue(ic, it2, temp);
+		}
+		setDirty(true, ic, it);
+		setDirty(true, ic, it2);
+	}
+	/*..........................................MeristicData................*/
+	/** returns Color for state of character, scaled to maxState*/
+
+	public Color getColorOfState(int ic, int istate, int maxState){
+		return MesquiteColorTable.getDefaultColor(maxState,istate, MesquiteColorTable.COLORS_NO_BW); 
+	}
+	/*..........................................MeristicData................*/
+	public Color getColorOfState(int ic, int istate){
+		return MesquiteColorTable.getDefaultColor(10, istate, MesquiteColorTable.COLORS_NO_BW);
+	}
+	/*..........................................MeristicData................*/
+	protected String statesToString(int ic, int it, boolean forDisplay) {
+		String s = "";
+		boolean first = true;
+		for (int item = 0; item<getNumItems(); item++) {
+			if (!first)
+				s+=" ";
+			first = false;
+			int iState = getState(ic, it, item);
+			if (iState == MesquiteInteger.unassigned)
+				s += getUnassignedSymbol();
+			else if (iState == MesquiteInteger.inapplicable)
+				s += getInapplicableSymbol();
+			else {
+				if (forDisplay || !MesquiteInteger.isCombinable(iState))
+					s +=  MeristicState.toString(iState);
+				else
+					s +=  Integer.toString(iState);
+			}
+		}
+		if (getNumItems()>1)
+			return "(" + s + ")";
+		else
+			return s;
+	}
+
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay){
+		statesIntoStringBuffer(ic,it,sb,forDisplay,true,true);
+	}
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoStringBuffer(int ic, int it, StringBuffer sb, boolean forDisplay, boolean includeInapplicable, boolean includeUnassigned){
+		sb.append(statesToString(ic, it, forDisplay)); //TODO: use buffer
+	}
+	/** appends to buffer string describing the state(s) of character ic in taxon it.*/
+	public void statesIntoNEXUSStringBuffer(int ic, int it, StringBuffer sb){
+		sb.append(statesToString(ic, it, false));  //TODO: use buffer
+	}
+	float[] hsb = new float[3];
+	/*..........................................  MeristicData  ..................................................*/
+	/** Gets the color representing state(s) of character ic in taxon it */ 
+	public Color getColorOfStates(int ic, int it){
+
+		int s = getState(ic, it, 0);
+		if (MeristicState.isCombinable(s)) {
+			int minState=MesquiteInteger.unassigned;
+			int maxState=MesquiteInteger.unassigned;
+			for (int it2=0; it2<getNumTaxa(); it2++){
+				maxState = MesquiteInteger.maximum(maxState, getState(ic, it2, 0));
+				minState = MesquiteInteger.minimum(minState, getState(ic, it2, 0));
+			}
+			
+			int place = 0;
+			if (maxState!=minState)
+				place=(int)(((s-minState)/(maxState-minState))*10); 
+			return getColorOfState(ic, place, 10);
+		}
+		else 
+			return ColorDistribution.unassigned;
+	}
+
+	/*..........................................MeristicData................*/
+	public CharacterDistribution getCharacterDistribution(int ic){
+		MeristicEmbedded states =new MeristicEmbedded(this, ic);
+		return states;
+	}
+	/*..........................................  MeristicData  ..................................................*/
+	/** Fills matrix with data from passed StsOfCharacters object.*/
+	public void setMatrix(MCharactersDistribution states){ 
+		if (!(states instanceof MMeristicDistribution))
+			return;
+		setDirty(true);
+		incrementStatesVersion();
+		MMeristicDistribution cStates = (MMeristicDistribution)states;
+		setItemsAs(cStates);
+		for (int i = 0; i< getNumItems(); i++) {
+			Integer2DArray matrix =getItem(i);
+			matrix.setValues(cStates.getItem(i));
+		}
+		stampHistoryChange();
+	}
+	/*..........................................  MeristicData  ..................................................*/
+	/**get copy of matrix and return as MCharactersDistribution */
+	public MCharactersDistribution getMCharactersDistribution(){
+		MMeristicEmbedded states = new MMeristicEmbedded(this);
+		return states;
+	}
+	/*..........................................MeristicData................*/
+	public CharacterDistribution makeCharacterDistribution(){
+		MeristicAdjustable c = new MeristicAdjustable(getTaxa(), numTaxa);
+		c.setItemsAs(this);
+		c.setParentData(this);
+		return c;
+	}
+	/*..........................................MeristicData................*/
+	public CharacterState makeCharacterState() {
+		return new MeristicState();
+	}
+	/*..........................................MeristicData................*/
+	public CharacterData makeCharacterData() {
+		MeristicData data = new MeristicData(getMatrixManager(), getNumTaxa(), getNumChars(), getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................MeristicData................*/
+	public CharacterData makeCharacterData(int ntaxa, int nchars) {
+		MeristicData data = new MeristicData(getMatrixManager(), ntaxa, nchars,  getTaxa());
+		data.setItemsAs(this);
+		return data;
+	}
+	public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa){ 
+		MeristicData data =  new MeristicData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
+		data.setItemsAs(this);
+		return data;
+	}
+	/*..........................................MeristicData................*/
+	/** If incoming CharacterState has more items
+   	or items with names not seen in this MeristicData, then new items are created in the MeristicData*
+   	public  void reconcileItems(CharacterState cs){
+
+   		if (cs !=null && cs instanceof MeristicState) {
+   			MeristicState contS = (MeristicState)cs;
+   			if (contS.getNumItems()==1 && getNumItems()==1 && (contS.getItemReference(0) == null || getItemReference(0) == null || contS.getItemReference(0) == getItemReference(0))){
+   			}
+   			else {
+	   			int made = 0;
+	   			for (int i=0; i<contS.getNumItems(); i++) {
+	   				NameReference nr = contS.getItemReference(i);
+	   				if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+	   					establishItem(nr.getValue());
+	   					made++;
+	   				}
+	   			}
+	   			int numToMake = contS.getNumItems() - getNumItems();
+	   			for (int i=0; i< numToMake; i++)
+	   				addItem(null);
+   			}
+  		}
+   	}
+	/*..........................................MeristicData................*/
+	/** sets the state of character ic in taxon it from CharacterState cs.  If incoming CharacterState has more items
+   	or items with names not seen in this MeristicData, then new items are created in the MeristicData*/
+	public  void setState(int ic, int it, CharacterState cs){
+
+		if (cs !=null && cs instanceof MeristicState) {
+			MeristicState contS = (MeristicState)cs;
+			if (contS.getNumItems()==1 && getNumItems()==1 && (contS.getItemReference(0) == null || getItemReference(0) == null || contS.getItemReference(0) == getItemReference(0))){
+				setState(ic, it, 0, contS.getValue(0));  
+			}
+			else {
+				int made = 0;
+				for (int i=0; i<contS.getNumItems(); i++) {
+					NameReference nr = contS.getItemReference(i);
+					if (nr != null && getItemNumber(nr)<0){ //named item not found; make new one
+						establishItem(nr.getValue());
+						made++;
+					}
+				}
+				int numToMake = contS.getNumItems() - getNumItems();
+				for (int i=0; i< numToMake; i++)
+					addItem(null);
+				int currentOpen = 0;
+				//unnamed items in incoming character state will be applied to first available items whose names are not in incoming character state
+				for (int i=0; i<contS.getNumItems(); i++) {
+					NameReference nr = contS.getItemReference(i);
+					if (getItemNumber(nr)>=0) {//named item found; set state
+						setState(ic, it, getItemNumber(nr), contS.getValue(i));  
+					}
+					else { //put it in next slot in this that has no corresponding in contS
+						boolean found = false;
+						for (int item = currentOpen; item<getNumItems() && !found; item++){
+							NameReference nrM = getItemReference(item);
+							if (nrM == null || contS.getItemNumber(nrM) < 0){
+								setState(ic, it, item, contS.getValue(i));
+								currentOpen = item+1;
+								found = true;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	/*..........................................MeristicData................*/
+	public void setState(int ic, int it, int item, int states){
+		if (ic<numChars && it<numTaxa && item<getNumItems()) {
+			Integer2DArray m = ((Integer2DArray)matrices.elementAt(item));
+			if (m.getValue(ic, it)!= states){
+				m.setValue(ic, it, states);
+				setDirty(true, ic, it);
+				incrementStatesVersion();
+			}
+		}
+	}
+	/*..........................................MeristicData................*/
+	public void setState(int ic, int it, int states){
+		if (ic<numChars && it<numTaxa && 0<getNumItems()) {
+			Integer2DArray m = ((Integer2DArray)matrices.elementAt(0));
+			if (m.getValue(ic, it)!= states){
+				m.setValue(ic, it, states);
+				setDirty(true, ic, it);
+				incrementStatesVersion();
+			}
+		}
+	}
+	/*..........................................MeristicData................*/
+	public void setState(int ic, int it, String s){
+		MesquiteMessage.warnProgrammer("Error: simple set state used in " + getDataTypeName());
+		setState(ic, it, null, true, null);
+	}
+	/*..........................................    ..................................................*/
+	public boolean legalValue(int ic, int states){
+		return true;
+	}
+	/*..........................................MeristicData................*/
+	/** set the state of char ic and taxon it to that in string starting at position pos.  If pos==null,
+	assume that whole string is relevant*/
+	public int setState(int ic, int it, Parser parser, boolean fromEditor, MesquiteString result){ 
+		if (ic>=numChars || ic < 0 || it>=numTaxa ||it<0) {
+			if (result!=null)
+				result.setValue("Character or taxon number out of bounds in setState " + ic + "  " + it);
+			MesquiteMessage.printStackTrace("");
+			return OUTOFBOUNDS;
+		}
+		if (parser==null)
+			return ERROR;
+		if (parser.blank()) {
+			if (result!=null)
+				result.setValue("String blank in setState");
+			return ERROR;
+		}
+		StringBuffer s = parser.getBuffer();
+		boolean dirt = false;
+		if (s.length() == 1){
+			char c= s.charAt(0);
+			if (c ==getInapplicableSymbol()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=MesquiteInteger.inapplicable) {
+						setState(ic, it, i, MesquiteInteger.inapplicable);
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+			else if (c ==getUnassignedSymbol()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=MesquiteInteger.unassigned) {
+						setState(ic, it, i, MesquiteInteger.unassigned);
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+			else if (c ==getMatchChar()){
+				for (int i=0; i<getNumItems(); i++) {
+					if (getState(ic, it, i)!=getState(ic,  0, i)) {
+						setState(ic, it, i, getState(ic,  0, i));
+						dirt = true;
+					}
+				}
+				if (dirt)
+					setDirty(true, ic, it);
+				return OK;
+			}
+		}
+		boolean contin = false;
+		boolean wasNull = false;
+		if (fromEditor) { 
+			parser.setPosition(0);
+			contin = true;
+			wasNull = true;
+		}
+		boolean done = false;
+		int item = 0;
+		String t = null;
+		int prev = parser.getPosition();
+		//MesquiteInteger pos = new MesquiteInteger(parser.getPosition()); //how to avoid this instantiation but be reentrant safe?
+		while (!done){
+			parser.setPosition(prev);
+			t = parser.getNextToken();
+			if ("(".equals(t)) {
+				contin = true;
+				prev = parser.getPosition();
+			}
+			if (StringUtil.blank(t)|| ")".equals(t)) {
+				done = true;
+				prev = parser.getPosition();
+			}
+			else  {
+				if (!contin)
+					done = true;
+				parser.setPosition(prev);
+
+				String f =parser.getNextToken();
+
+				int d = 0;
+				prev = parser.getPosition();
+				boolean makeNegative = false;
+				if ((getInapplicableSymbol() != '-' || hasNegatives) && f != null && f.length() == 1 && f.charAt(0) == '-'){  //negative numbers possible only if gap is not '-'
+					char next = parser.getCharAt(prev);
+					d = MesquiteInteger.fromString("" + next, false); 
+					if (MesquiteInteger.isCombinable(d)){
+						f = parser.getNextToken();
+						prev = parser.getPosition();
+						makeNegative = true;
+					}
+				}
+				if (f != null && f.length() == 1 && f.charAt(0) == getInapplicableSymbol())
+					d = MeristicState.inapplicable; 
+				else
+					d = MesquiteInteger.fromString(f, false); 
+				if (d!=MeristicState.impossible && legalValue(ic,d)) {
+					if (makeNegative)
+						d = -d;
+					if (d != getState(ic, it, item)) {
+						setState(ic,it, item++,d);
+						dirt = true;
+					}
+					else
+						item++;
+				}
+				else {
+					if (result != null) {
+						result.setValue("Illegal state value for "+getDataTypeName());
+						return ERROR;
+					}
+				}
+				if (done)
+					parser.setPosition(prev);
+			}
+		}
+		if (dirt)
+			setDirty(true, ic, it);
+		return OK;
+	}
+
+	/*..........................................MeristicData................*/
+	/** returns the state of character ic in taxon it*/
+	public  CharacterState getCharacterState(CharacterState cs, int ic, int it){
+		if (cs==null || cs.getClass()!=MeristicState.class) {
+			cs =new MeristicState();
+		}
+		((MeristicState)cs).setItemsAs(this);
+		for (int i=0; i< getNumItems(); i++) {
+			((MeristicState)cs).setValue(i, getState(ic, it, i));
+		}
+		return cs; 
+	}
+
+	/*..........................................MeristicData................*/
+	/** returns the state of character ic in taxon it*/
+	public  int getState(int ic, int it){
+		if (matrices!=null && ic<numChars && it<numTaxa && 0<getNumItems()) {
+			Integer2DArray da = ((Integer2DArray)matrices.elementAt(0));
+			if (da!=null)
+				return da.getValue(ic, it);
+		}
+		return MesquiteInteger.unassigned;
+	}
+	/*..........................................MeristicData................*/
+	/** returns the state of character ic in taxon it*/
+	public  int getState(int ic, int it, int item){
+		if (matrices!=null && ic<numChars && it<numTaxa && item<getNumItems()) {
+			Integer2DArray da = ((Integer2DArray)matrices.elementAt(item));
+			if (da!=null)
+				return da.getValue(ic, it);
+		}
+		return MesquiteInteger.unassigned;
+	}
+	/** returns a String summarizing the states of a character (e.g., "2 states", "0.1-0.9").*/
+	/*..........................................MeristicData................*/
+	public String getStatesSummary(int ic, boolean selectedOnly){
+		MeristicState state=null;
+		int max = MesquiteInteger.unassigned;
+		int min = MesquiteInteger.unassigned;
+		//ITEMS: ask if more than one item, and if so list column for each
+		for (int it=0; it<numTaxa; it++) 
+			if (!selectedOnly || getTaxa().getSelected(it)) {
+				state = (MeristicState)getCharacterState(state, ic, it);
+				if (MesquiteInteger.greaterThan(state.getValue(0), max))
+					max = state.getValue(0);
+				if (MesquiteInteger.lessThan(state.getValue(0), min))
+					min = state.getValue(0);
+			}
+		return MeristicState.toString(min) + " - " + MeristicState.toString(max);	
+	}
+	/*..........................................MeristicData................*/
+	public  void setToInapplicable(int ic, int it){
+		for (int i=0; i< getNumItems(); i++) 
+			setState(ic,it,i,MeristicState.inapplicable);
+	}
+	/*..........................................MeristicData................*/
+	public  void setToUnassigned(int ic, int it){
+		for (int i=0; i< getNumItems(); i++) 
+			setState(ic,it,i,MeristicState.unassigned);
+	}
+	/** sets the state of character ic in taxon it to the default state (which in some circumstances may be inapplicable, e.g. gaps for molecular data)*/
+	public  void deassign(int ic, int it){
+		setToUnassigned(ic, it);	
+	}
+	/*..........................................MeristicData................*/
+	public String getStatesSummary(int ic){
+		return getStatesSummary(ic,false);
+	}
+	/*..........................................MeristicData................*/
+	/** returns whether the character ic is inapplicable to taxon it.   True if inapplicable in all items.*/
+	public  boolean isInapplicable(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)== MeristicState.inapplicable; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (!MeristicState.isInapplicable(getState(ic, it, i)));
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** returns whether the character ic,  taxon it has a valid state.   True if combinable in all items.*/
+	public  boolean isCombinable(int ic, int it){
+		if (getNumItems()==1)
+			return MeristicState.isCombinable(firstMatrix.getValue(ic,it)); 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (!MeristicState.isCombinable(getState(ic, it, i)));
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** returns whether the state of character ic is missing in taxon it.  True if unassigned in all items.*/
+	public  boolean isUnassigned(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)== MeristicState.unassigned; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (!MeristicState.isUnassigned(getState(ic, it, i)));
+				return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** returns whether the state of character ic is missing in taxon it.  True if unassigned in all items.*/
+	public  boolean isValid(int ic, int it){
+		if (getNumItems()==1)
+			return firstMatrix.getValue(ic,it)!= MeristicState.impossible; 
+		else {
+			for (int i=0; i< getNumItems(); i++) {
+				if (MeristicState.isImpossible(getState(ic, it, i)))
+					return false;
+			}
+			return true;
+		}
+	}
+	/*..........................................MeristicData................*/
+	/** dump the matrix to the log*/
+	public void logMatrix(){
+		StringBuffer matrixString= new StringBuffer();
+		for (int it=0; it<numTaxa; it++) {
+			matrixString.append(getTaxa().getTaxon(it).getName() + "  ");
+			for (int ic=0; ic<numChars; ic++)
+				statesIntoStringBuffer(ic,it, matrixString, true); 
+			matrixString.append(StringUtil.lineEnding());
+		}
+		MesquiteModule.mesquiteTrunk.logln(matrixString.toString());
+	}
+
+	/*.................................................................................................................*/
+	public String getChecksumSummaryString(){
+		MeristicState state=null;
+		int minValue = MesquiteInteger.unassigned;
+		int maxValue = MesquiteInteger.unassigned;
+		for (int ic = 0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++) {
+				state =(MeristicState)getCharacterState(state, ic, it);
+				if (!state.isUnassigned() && !state.isInapplicable())
+					for (int item = 0; item <getNumItems(); item ++) {
+						minValue = MesquiteInteger.minimum(minValue, state.getValue(item));
+						maxValue = MesquiteInteger.maximum(maxValue, state.getValue(item));
+					}
+			}
+		return "numChars " + getNumChars() + "   numItems " + getNumItems() + "   min  " + minValue + "   max  " + maxValue;
+	}
+	/*..........................................MeristicData................*/
+	public long calculateChecksum(CRC32 crc32){
+		byte[] bytes = new byte[8];
+		crc32.reset();
+		int numItems = getNumItems();
+		for (int ic=0; ic<numChars; ic++)
+			for (int it=0; it<numTaxa; it++) 
+				for (int item=0; item<numItems; item++) {
+					bytes = MesquiteNumber.longToBytes(getState(ic, it, item), bytes);
+					for (int i = 0; i<8; i++)
+						crc32.update(bytes[i]);
+				}
+
+		return crc32.getValue();
+	}
+	/*..........................................MeristicData................*/
+	/** returns default column width in editors..*/
+	public int getDefaultColumnWidth() {
+		return 70;
+	}
+	/*..........................................MeristicData................*/
+	public static DefaultReference findDefaultReference(NameReference paradigm){
+		if (defaultModels == null) {
+			MesquiteMessage.warnProgrammer("findDefaultReference with null default models ");
+			MesquiteMessage.printStackTrace();
+			return null;
+		}
+		for (int i=0; i<defaultModels.size(); i++){
+			DefaultReference dR = (DefaultReference)defaultModels.elementAt(i);
+			if (dR.getParadigm() != null && dR.getParadigm().equals(paradigm))
+				return dR;
+		}
+		return null;
+
+	}
+	/*..........................................MeristicData................*/
+	/** this should not be used except by modules INTENDING to steal away the defaults */
+	public static void registerDefaultModel(String paradigm, String name){
+		if (defaultModels == null)
+			return;
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR == null) {
+			dR = new DefaultReference(p);
+			defaultModels.addElement(dR);
+		}
+		dR.setDefault(name);
+	}
+	/*..........................................MeristicData................*/
+	public CharacterModel getDefaultModel(String paradigm){
+		NameReference p = NameReference.getNameReference(paradigm);
+		DefaultReference dR = findDefaultReference(p);
+		if (dR==null)
+			return null;
+		else {
+			CharacterModel cm = getProject().getCharacterModel(dR.getDefault());
+			if (cm==null) 
+				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+			return cm;
+		}
+	}
+	/*..........................................MeristicData................*/
+	public String toString(){
+		return "Meristic data matrix id: " + getID() + "; chars: " + numChars + "; taxa: " + numTaxa + "; items " + getNumItems() + "; name: " + getName();
+	}
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicDataAlterer.java b/Source/mesquite/meristic/lib/MeristicDataAlterer.java
new file mode 100644
index 0000000..bf6659f
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicDataAlterer.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.meristic.lib;
+
+import mesquite.categ.lib.RequiresAnyCategoricalData;
+import mesquite.lib.CompatibilityTest;
+import mesquite.lib.duties.DataAlterer;
+
+public abstract class MeristicDataAlterer extends DataAlterer  {
+  	 public Class getDutyClass() {
+  	 	return MeristicDataAlterer.class;
+  	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMeristicData();
+	}
+
+}
diff --git a/Source/mesquite/meristic/lib/MeristicDistribution.java b/Source/mesquite/meristic/lib/MeristicDistribution.java
new file mode 100644
index 0000000..50db2b6
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicDistribution.java
@@ -0,0 +1,148 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** Contains an array of  meristic character states for one character, at each of the taxa or nodes 
+ See notes under <a href = "MeristicData.html">MeristicData</a> regarding items */
+public abstract class MeristicDistribution  extends MeristicStates implements CharacterDistribution {
+	
+	public MeristicDistribution (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................MeristicDistribution................*/
+	public int getNumNodes(){
+		return getNumTaxa();
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data*/
+	public boolean hasMissing (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isUnassigned(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps)*/
+	public boolean hasInapplicable (){
+		for (int i=0; i< getNumNodes(); i++)
+			if (isInapplicable(i))
+				return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has missing (unassigned) data in the taxa of the tree*/
+	public boolean hasMissing(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isUnassigned(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasMissing(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character has inapplicable codings (gaps) in the taxa of the tree*/
+	public boolean hasInapplicable(Tree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			if (isInapplicable(tree.taxonNumberOfNode(node)))
+				return true;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (hasInapplicable(tree, d))
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same)*/
+	public boolean isConstant(){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = null;
+		for (int i=1; i< getNumNodes(); i++)
+			if (!cs.equals(cs2 = getCharacterState(cs2, i)))
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	private boolean isConstantRec(Tree tree, int node, CharacterState cs, CharacterState cs2){
+		if (tree.nodeIsTerminal(node)){
+			if (!cs.equals(cs2 = getCharacterState(cs2, tree.taxonNumberOfNode(node))))
+				return false;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (!isConstantRec(tree, d, cs, cs2))
+					return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns whether or not the character is constant (all states are the same) in the taxa of the tree*/
+	public boolean isConstant(Tree tree, int node){
+		if (getNumNodes()<1)
+			return true;
+		CharacterState cs = getCharacterState(null, 0);
+		CharacterState cs2 = getCharacterState(null, 0);
+		return isConstantRec(tree, node, cs, cs2);
+	}
+	/*..........................................MeristicDistribution................*/
+	/** returns a CharacterDistribution that is adjustable and has the same states*/
+	public AdjustableDistribution getAdjustableClone(){
+		MeristicAdjustable soc = new MeristicAdjustable(getTaxa(), getNumTaxa());
+		soc.setItemsAs(this);
+		for (int it = 0; it<getNumTaxa(); it++) {
+			for (int item = 0; item<getNumItems(); item++)
+				soc.setState(it, item, getState(it, item)); 
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+	/*..........................................MeristicDistribution................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustHistorySize(Tree tree, CharacterHistory charStates) {
+		int numNodes = tree.getNumNodeSpaces();
+		CharacterHistory soc =charStates;
+		if (charStates==null || ! (charStates.getClass() == MeristicHistory.class)) 
+			soc = new MeristicHistory(tree.getTaxa(), numNodes, (MeristicData)getParentData()); //should keep items!!! (since StsOfChar may have different number from parent data!
+		else if (numNodes!= charStates.getNumNodes()) 
+			soc = new MeristicHistory(tree.getTaxa(), numNodes, (MeristicData)getParentData());
+		else {
+			soc =charStates;
+		}
+		soc.setParentData(getParentData());
+		soc.setParentCharacter(getParentCharacter());
+		((CharacterStates)soc).setExplanation(getExplanation());
+		return soc;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicEmbedded.java b/Source/mesquite/meristic/lib/MeristicEmbedded.java
new file mode 100644
index 0000000..e440d2f
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicEmbedded.java
@@ -0,0 +1,77 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  meristic character states for one character, at each of the taxa or nodes */
+public class MeristicEmbedded  extends MeristicDistribution {
+	MeristicData data;
+	public MeristicEmbedded (MeristicData data, int ic) {
+		super(data.getTaxa());
+		this.data = data;
+		this.characterNumber = ic;
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return data.getStateClass();
+	}
+	/*..........................................MeristicEmbedded................*/
+	public CharacterData getParentData() {
+		return data;
+	}
+	/*..........................................MeristicEmbedded................*/
+	public int getNumItems() {
+		return data.getNumItems();
+	}
+	/*..........................................MeristicEmbedded................*/
+	public NameReference getItemReference(String name){
+		return data.getItemReference(name);
+		
+	}
+	/*..........................................MeristicEmbedded................*/
+	public NameReference getItemReference(int index){
+		return data.getItemReference(index);
+	}
+	/*..........................................MeristicEmbedded................*/
+	public int getItemNumber(NameReference nr){
+		return data.getItemNumber(nr);
+	}
+	/*..........................................MeristicEmbedded................*/
+	public String getItemName(int index){
+			return data.getItemName(index);
+	}
+	/*..........................................MeristicEmbedded................*/
+	public int getNumTaxa() {
+		return data.getNumTaxa();
+	}
+	/*..........................................MeristicEmbedded................*/
+	public int getState (int N, int item) {
+		return data.getState(characterNumber, N, item);
+	}
+	/*..........................................MeristicEmbedded................*/
+	public int getState (int N) {
+		return data.getState(characterNumber, N, 0);
+	}
+	public String getName(){
+		return data.getCharacterName(characterNumber);
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MeristicHistory.java b/Source/mesquite/meristic/lib/MeristicHistory.java
new file mode 100644
index 0000000..4559957
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicHistory.java
@@ -0,0 +1,278 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.cont.lib.ContColorTable;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Contains an array of  meristic character states for one character, at each of the taxa or nodes. 
+ See notes under <a href = "MeristicData.html">MeristicData</a> regarding items */
+public class MeristicHistory extends MeristicAdjustable  implements CharacterHistory {
+	private int minState = 0;
+	private boolean[] places = new boolean[11];
+	private int maxState = 100;
+	public MeristicHistory (Taxa taxa, int numNodes, MeristicData data) { 
+		super(taxa, numNodes);
+		setParentData(data);
+		if (data!=null) {
+			setItemsAs(data);
+		}
+	}
+	/*..........................................MeristicHistory................*/
+	public CharacterHistory clone(CharacterHistory s) {
+		MeristicHistory snew;
+		if ((s==null) || (s.getNumNodes()!=numNodes) || (!(s instanceof MeristicHistory)))
+			snew = new MeristicHistory(getTaxa(), numNodes, (MeristicData)data); 
+		else {
+			snew = (MeristicHistory)s;
+			snew.data = data;
+		}
+		snew.setItemsAs(this);
+		for (int i=0; i<numNodes; i++) {
+			for (int im = 0; im<getNumItems(); im++)
+				snew.setState(i, im, getState(i, im));
+		}
+		snew.characterNumber = characterNumber;
+		if (observedStates!=null)
+			snew.setObservedStates((CharacterDistribution)observedStates.getAdjustableClone());
+		((CharacterStates)snew).setExplanation(getExplanation());
+		return snew;
+	}
+	/*..........................................MeristicHistory................*/
+	/** for MPRs, etc., gets the ith resolution of the history */
+	public CharacterHistory getResolution(Tree tree, CharacterHistory resultStates, long i){
+		resultStates = adjustHistorySize(tree, resultStates);
+		clone(resultStates);
+		return resultStates;
+	}
+	/** for MPRs, etc., gets the number of resolutions of the history */
+	public long getNumResolutions(Tree tree){
+		return 1;
+	}
+	/*..........................................MeristicHistory................*/
+	/** Returns a new object indicating the states at the tips (used whether or not History is reconstruction)*/
+	public CharacterDistribution getStatesAtTips(Tree tree){
+		if (observedStates !=null)
+			return (CharacterDistribution)observedStates.getAdjustableClone();
+		else {
+			MeristicAdjustable d = new MeristicAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+			d.setItemsAs(this);
+			fillDistribution(tree, tree.getRoot(), d);
+			return d;
+		}
+	}
+	/*..........................................MeristicHistory................*/
+	private void fillDistribution(Tree tree, int node, MeristicAdjustable dist) {  
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			for (int i =0; i<getNumItems(); i++)
+				dist.setState(t, i, getState(node, i));
+		}
+		else for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			fillDistribution(tree, d, dist);
+	}
+	/*..........................................MeristicHistory................*/
+
+	CharacterDistribution observedStates;
+	/*..........................................MeristicHistory................*/
+	/** Returns the states in the terminal taxa (used if History is reconstruction)*/
+	public CharacterDistribution getObservedStates(){
+		return observedStates;
+	}
+	/*..........................................MeristicHistory................*/
+	/** Sets the states in the terminal taxa (used if History is reconstruction)*/
+	public void setObservedStates(CharacterDistribution observed){
+		this.observedStates = observed;
+	}
+	/*..........................................MeristicHistory................*/
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public CharacterHistory adjustSize(Tree tree) {
+		if (tree.getNumNodeSpaces() == this.getNumNodes())
+			return this;
+		else {
+			MeristicHistory soc = new MeristicHistory(tree.getTaxa(), tree.getNumNodeSpaces(), (MeristicData)getParentData());
+			soc.setItemsAs(this);
+			soc.setParentData(getParentData());
+			soc.setParentCharacter(getParentCharacter());
+			((CharacterStates)soc).setExplanation(getExplanation());
+			return soc;
+		}
+	}
+	/*..........................................MeristicHistory................*/
+	private void calcMinMaxStates(Tree tree, int node) {
+		for (int i=0; i<getNumItems(); i++) {
+			int s=getState(node, i); 
+			maxState = MesquiteInteger.maximum(maxState, s);
+			minState = MesquiteInteger.minimum(minState, s);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calcMinMaxStates(tree, d);
+	}
+	/*..........................................MeristicHistory................*/
+	private void calcPlaces(Tree tree, int node) {
+		for (int i=0; i<getNumItems(); i++) {
+			int s=getState(node, i); 
+			int place = (int)(((s-minState)*1.0/(maxState-minState))*10); 
+			if (place>=0 && place<places.length)
+				places[place] = true;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calcPlaces(tree, d);
+	}
+
+	/*..........................................MeristicHistory................*/
+	/** Must be called before a tree is shaded.  Goes through all nodes to find states present, to set
+	minima and maxima. */
+	public void prepareColors(Tree tree, int drawnRoot) {  
+		minState=MesquiteInteger.unassigned;
+		maxState=MesquiteInteger.unassigned;
+		calcMinMaxStates(tree, drawnRoot); 
+		if (getParentData()!=null && getParentCharacter()>=0){
+			int ic = getParentCharacter();
+			MeristicData data  = ((MeristicData)getParentData());
+			for (int it = 0; it<data.getNumTaxa(); it++) {
+				int s = data.getState(ic, it, 0);
+				maxState = MesquiteInteger.maximum(maxState, s);
+				minState = MesquiteInteger.minimum(minState, s);
+			}
+		}
+		else if (getObservedStates()!=null){
+			int ic = getParentCharacter();
+			MeristicDistribution data  = (MeristicDistribution)getObservedStates();
+			for (int it = 0; it<data.getNumNodes(); it++) {
+				int s = data.getState(it);
+				maxState = MesquiteInteger.maximum(maxState, s);
+				minState = MesquiteInteger.minimum(minState, s);
+			}
+		}
+		for (int i = 0; i<10; i++)
+			places[i] = false;
+		calcPlaces(tree, drawnRoot); 
+	}
+
+	/*..........................................  MeristicHistory  ..................................................*/
+	/** places into the already instantiated ColorDistribution the colors corresponding to the CharacterState, and returns the number of colors.  Uses default colors. 
+		Mode is MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass)*/
+	public int getColorsOfState(CharacterState state, ColorDistribution colors, MesquiteColorTable colorTable) {
+		if (colors==null || state == null || ! (state instanceof MeristicState))
+			return 0;
+		colors.initialize();
+		MeristicState cState = (MeristicState)state;
+		int colorCount=0;
+		if (cState.getNumItems() == 1) {
+			int s =cState.getValue(0); 
+			colors.setWeight(0, 1.0);
+			if (!MesquiteInteger.isCombinable(s))
+				colors.setColor(0, Color.white);
+			else {
+				int place = (int)(((s-minState)*1.0/(maxState-minState))*10); 
+				colors.setColor(0, colorTable.getColor(10, place));//bug fixed in 1. 12 that had been introduced in 1. 10
+				//colors.setColor(0, colorTable.getColor(s, minState, maxState));  1.10 to 1.11
+			}
+		}
+		else {
+			for (int i=0; i<cState.getNumItems() ; i++) {
+				int s = cState.getValue(i); 
+				colors.setWeight(i, 1.0/cState.getNumItems() );
+				if (!MesquiteInteger.isCombinable(s))
+					colors.setColor(0, Color.white);
+				else {
+					int place = (int)(((s-minState)*1.0/(maxState-minState))*10); 
+					colors.setColor(i, colorTable.getColor(10, place)); //bug fixed in 1. 12 that had been introduced in 1. 10
+					//colors.setColor(i, colorTable.getColor(s, minState, maxState));  1.10 to 1.11
+				}
+			}
+		}
+
+		return cState.getNumItems() ;
+	}
+	/*..........................................MeristicHistory................*/
+	public MesquiteColorTable getColorTable(MesquiteColorTable colorTable) {
+		//if (colorTable == null || !(colorTable instanceof ContColorTable))
+		//	colorTable =  new ContColorTable();
+		//colorTable.disableSetColor(true);
+		return colorTable;
+	}
+	/*..........................................MeristicHistory................*/
+	/** Places into Color array the colors at the node, and returns the number of colors.  Uses passed
+	stateColors as color key.  If null is passed, uses color system of parent data (using maxState of this
+	StsOfCharcter) or, if there is not parent data object, the default colors. */
+	public int getColorsAtNode(int node, ColorDistribution colors, MesquiteColorTable stateColors, boolean showWeights) {
+		for (int i=0; i<10; i++) colors.initialize();
+		if (getNumItems() == 1) {
+			int s =firstItem.getValue(node); 
+			colors.setWeight(0, 1.0);
+			if (!MesquiteInteger.isCombinable(s))
+				colors.setColor(0, ColorDistribution.unassigned);
+			else {
+				int place = (int)(((s-minState)*1.0/(maxState-minState))*10); 
+				colors.setColor(0, stateColors.getColor(10, place));  
+			}
+		}
+		else {
+			for (int i=0; i<getNumItems(); i++) {
+				int s = getState(node,i);
+				colors.setWeight(i, 1.0/getNumItems());
+				if (!MesquiteInteger.isCombinable(s))
+					colors.setColor(0, ColorDistribution.unassigned);
+				else {
+					int place = (int)(((s-minState)*1.0/(maxState-minState))*10); 
+					colors.setColor(i, stateColors.getColor(10, place));
+				}
+			}
+		}
+
+		return getNumItems();
+	}
+	/*..........................................MeristicHistory................*/
+	/** returns the vector of ColorEvents in order, e.g. for stochastic character mapping.  Return null if none.  Not yet supported for MeristicHistory */
+	public ColorEventVector getColorSequenceAtNode(int node, MesquiteColorTable stateColors){
+		return null;
+	}
+	/*..........................................MeristicHistory................*
+	public int getLegendStates(Color[] cs, String[] stateNames, MesquiteColorTable stateColors) {
+		return getLegendStates(cs, stateNames, stateColors, MesquiteColorTable.DEFAULT);
+	}
+
+
+	/*..........................................MeristicHistory................*/
+	public int getLegendStates(Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) {
+		int colorCount=0;
+
+		double rangeUnit = ((maxState-minState)/10.0); 
+		for (int e=0; e<=10; e++) {
+			if (places[e]){
+				cs[colorCount]= stateColors.getColor(10, e);
+				if (tableMappings != null)
+					tableMappings[colorCount] = new Point(10, e);
+				stateNames[colorCount++]=MesquiteInteger.toString((int)(minState + rangeUnit*e)) + " to " + MesquiteInteger.toString((int)(minState + rangeUnit*(e+1)));
+			}
+		}
+		return colorCount;
+	}
+	/*..........................................MeristicHistory................*
+	public int getLegendStates(Color[] cs, String[] stateNames, int mode) {
+		return getLegendStates(cs, stateNames, null, mode);
+	}
+	 */
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicLinearParsModel.java b/Source/mesquite/meristic/lib/MeristicLinearParsModel.java
new file mode 100644
index 0000000..93542df
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicLinearParsModel.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class MeristicLinearParsModel extends MeristicParsimonyModel {
+	public MeristicLinearParsModel (String name){
+		super(name);
+		setBuiltIn(true);
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "The cost of a change from x to y is |x-y|";
+	}
+	public String getNEXUSClassName(){
+		return "Linear Meristic";
+	}
+}
+
diff --git a/Source/mesquite/meristic/lib/MeristicParsimonyModel.java b/Source/mesquite/meristic/lib/MeristicParsimonyModel.java
new file mode 100644
index 0000000..a1176d4
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicParsimonyModel.java
@@ -0,0 +1,27 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** A character model for meristic characters to be used in parsimony calculations*/
+public abstract class MeristicParsimonyModel  extends ParsimonyModel {
+	
+	public MeristicParsimonyModel (String name) {
+		super(name, MeristicState.class);
+	}
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicState.java b/Source/mesquite/meristic/lib/MeristicState.java
new file mode 100644
index 0000000..590773e
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicState.java
@@ -0,0 +1,475 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+/* ======================================================================== */
+/**This class provides some basic utilities for Meristic characters.  It represents the entry for one character
+and one taxon.  Thus, it can contain more than one item (min, max, mean, variance, etc.).*/
+public class MeristicState extends CharacterState implements ItemContainer {
+	/** The state (MesquiteInteger.unassigned) that corresponds to missing data.*/
+	public static final int unassigned = MesquiteInteger.unassigned; 
+	/** The state (MesquiteInteger.inapplicable) that corresponds to a gap (inapplicable data).*/
+	public static final int inapplicable = MesquiteInteger.inapplicable;
+	/** The state (MesquiteInteger.infinite) that corresponds to infinite.*/
+	public static final int infinite = MesquiteInteger.infinite;
+	/** The state (MesquiteInteger.impossible) that corresponds to an impossible value.  
+	This is returned when a value is invalid, e.g. a string is parsed for a number but no valid number is found.*/
+	public static final int impossible = MesquiteInteger.impossible;
+	/** The maximum allowed number of items*/
+	public static final int MAXITEMS = 32;
+	/** The symbol that corresponds to a gap (inapplicable data).*/
+	public static final char inapplicableChar = 'x';
+	
+	/* the stored values (for the various items)*/
+	int[] values;
+	/* names of the items*/
+	NameReference[] names;
+	/*number of items*/
+	int numItems=0;
+	
+	public MeristicState () {
+		numItems = MAXITEMS;
+		values = new int[MAXITEMS];
+		names = new NameReference[MAXITEMS];
+		for (int i=0; i<MAXITEMS; i++) {
+			values[i] = MesquiteInteger.inapplicable;
+			names[i] = null;
+		}
+	}
+	public MeristicState (int value) {
+		numItems = MAXITEMS;
+		values = new int[MAXITEMS];
+		names = new NameReference[MAXITEMS];
+		for (int i=0; i<MAXITEMS; i++) {
+			values[i] = MesquiteInteger.inapplicable;
+			names[i] = null;
+		}
+		values[0] = value;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return MeristicData.DATATYPENAME;
+	}
+	/*..........................................MeristicState................*/
+	/** returns the maximum number of items (min, max, mean, variance, etc.) in this state*/
+//	public int getMaxItems(){
+//		return 32;
+//	}
+	/*..........................................MeristicState................*/
+	/** returns the number of items (min, max, mean, variance, etc.) in this state*/
+	public int getNumItems(){
+		return numItems;
+	}
+	/*..........................................MeristicState................*/
+	/** sets the number of items in this state*/
+	public void setNumItems(int n){
+		if (n<=MAXITEMS)
+			numItems = n;
+		else if (n>=0)
+			numItems = n;
+		for (int i=numItems; i<MAXITEMS; i++) {
+			values[i] = MesquiteInteger.unassigned;
+			names[i] = null;
+		}
+	}
+	/*..........................................MeristicState................*/
+	/** gets name of item n*/
+	public String getItemName(int n){
+		if (names != null && n>=0 && n<numItems) {
+			NameReference nr = names[n];
+			if (nr==null)
+				return null;
+			return nr.getValue();
+		}
+		else
+			return null;
+	}
+	/*..........................................MeristicState................*/
+	/** gets NameReferece of item n*/
+	public NameReference getItemReference(String name){
+		return NameReference.getNameReference(name);
+	}
+	/*..........................................MeristicState................*/
+	/** gets NameReferece of item n*/
+	public NameReference getItemReference(int n){
+		if (names != null && n>=0 && n<numItems)
+			return names[n];
+		else
+			return null;
+	}
+	/*..........................................MeristicState................*/
+	/** sets NameReference of item n*/
+	public void setItemReference(int n, NameReference nr){
+		if (n>=0 && n<numItems)
+			names[n] = nr;
+	}
+	/*..........................................MeristicState................*/
+	/** returns which item number has NameReference nr nr*/
+	public int getItemNumber(NameReference nr){
+		if (nr==null)
+			return -1;
+		for (int i=0; i<numItems; i++)
+			if (nr.equals(names[i]))
+				return i;
+		return -1;
+	}
+	/*..........................................MeristicState................*/
+	public void setItemsAs(ItemContainer iCont){
+		if (iCont == null)
+			return;
+		setNumItems(iCont.getNumItems());
+		for (int i=0; i<getNumItems(); i++)
+			setItemReference(i, iCont.getItemReference(i));
+	}
+	/*..........................................MeristicState................*/
+	public Class getCharacterDataClass() {
+		return MeristicData.class;
+	}
+	public Class getMCharactersDistributionClass(){
+		return MMeristicAdjustable.class;
+	}
+	public Class getCharacterDistributionClass(){
+		return MeristicAdjustable.class;
+	}
+	public Class getCharacterHistoryClass(){
+		return MeristicHistory.class;
+	}
+	public AdjustableDistribution makeAdjustableDistribution(Taxa taxa, int numNodes){
+		return new MeristicAdjustable(taxa, numNodes);
+	}
+	public CharacterHistory makeCharacterHistory(Taxa taxa, int numNodes){
+		return new MeristicHistory(taxa, numNodes, null);
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if missing data (unassigned)*/
+	public static boolean isUnassigned(int s) {
+		return s == unassigned;
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if all items have missing data (unassigned)*/
+	public boolean isUnassigned() {
+		for (int i=0; i<numItems; i++)
+			if (values[i] != MesquiteInteger.unassigned)
+				return false;
+		return true;
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if inapplicable*/
+	public static boolean isInapplicable(int s) {
+		return s == inapplicable;
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if all items are inapplicable*/
+	public boolean isInapplicable() { //check all items
+		boolean inappPresent = false;
+		for (int i=0; i<numItems; i++)
+			if (values[i] == MesquiteInteger.inapplicable)
+				inappPresent = true;
+			else if (values[i] != MesquiteInteger.unassigned)
+				return false;
+		return inappPresent;
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if value is invalid*/
+	public static boolean isImpossible(int s) {
+		return s == impossible;
+	}
+	/*..........................................MeristicState................*/
+	/** returns true if at least one item is invalid*/
+	public boolean isImpossible() { //check all items
+		for (int i=0; i<numItems; i++)
+			if (values[i] == MesquiteInteger.impossible)
+				return true;
+		return false;
+	}
+	/*..........................................MeristicState.....................................*/
+	/** returns true if at least one item is combinable (i.e. a valid assigned state).*/
+	public boolean isCombinable(){
+		for (int i=0; i<numItems; i++)
+			if (MesquiteInteger.isCombinable(values[i]))
+				return true;
+		return false;
+	}
+	/*..........................................MeristicState.....................................*/
+	/** returns whether value is combinable (i.e. a valid assigned state) or not.*/
+	public static boolean isCombinable(int d){
+		return MesquiteInteger.isCombinable(d);
+	}
+	/*..........................................MeristicState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s) {
+		return equals(s, false);
+	}
+	/*..........................................MeristicState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing) {
+		if (s==null)
+			return false;
+		if (!(s instanceof MeristicState))
+			return false;
+		if (allowMissing && (isUnassigned() || s.isUnassigned())) //fixed 13 Dec 01
+				return true;
+		MeristicState cS = (MeristicState)s;
+		if (cS.getNumItems()!=getNumItems())
+			return false;
+		for (int i=0; i<getNumItems(); i++)
+			if  (cS.getValue(i) != getValue(i))
+				return false;
+		return true;
+	}
+	/*..........................................MeristicState.....................................*/
+	/**returns true iff state sets are same */
+	public boolean equals(CharacterState s, boolean allowMissing, boolean allowNearExact) {
+		return equals(s,allowMissing);
+	}
+	/*..........................................MeristicState................*/
+	public static int absolute(int d) {
+		if (d== unassigned || d==inapplicable || d==impossible || d==infinite)
+			return d;
+		if (d<0)
+			return -d;  
+		else
+			return d;
+	}
+	/*..........................................MeristicState................*/
+	public static int maximum(int d1, int d2) {
+		if (d1==d2)
+			return d1;
+		if (d2==infinite)
+			return d2;
+		if (d1==infinite)
+			return d1;
+			
+		if (d1== unassigned || d1==inapplicable || d1==impossible) {
+			if (d2== unassigned || d2==inapplicable || d2==impossible)
+				return impossible;
+			else
+				return d2;
+		}
+		if (d2== unassigned || d2==inapplicable || d2==impossible)
+			return d1;
+		
+		if (d1<d2)
+			return d2;  
+		else
+			return d1;
+	}
+	/*..........................................MeristicState................*/
+	public static int minimum(int d1, int d2) { 
+		if (d1==d2)
+			return d1;
+		if (d1== unassigned || d1==inapplicable || d1==impossible  || d1==infinite) {
+			if (d2== unassigned || d2==inapplicable || d2==impossible  || d2==infinite)
+				return impossible;
+			else
+				return d2;
+		}
+		if (d2== unassigned || d2==inapplicable || d2==impossible  || d2==infinite)
+			return d1;
+		if (d1>d2)
+			return d2;  
+		else
+			return d1;
+	}
+	/*..........................................MeristicState................*/
+	/** sets the value to inapplicable*/
+	public void setToInapplicable() {
+			for (int i=0; i<numItems; i++) {
+				values[i] = inapplicable;
+			}
+	}
+	/*..........................................MeristicState................*/
+	/** sets the value to unassigned*/
+	public void setToUnassigned() {
+			for (int i=0; i<numItems; i++) {
+				values[i] = unassigned;
+			}
+	}
+	/*..........................................MeristicState................*/
+	/** sets value of item n */
+	public void setValue(int n, int d){
+		if (n>=0 && n<numItems)
+			values[n] = d;
+	}
+	/*..........................................MeristicState................*/
+	public void setValue(CharacterState cs){
+		if (cs!=null && cs instanceof MeristicState) {
+			MeristicState c = (MeristicState)cs;
+			setNumItems(c.getNumItems());
+			for (int i=0; i<numItems; i++) {
+				values[i] = c.getValue(i);
+				names[i] = c.getItemReference(i);
+			}
+		}
+	}
+	/*..........................................MeristicState................*
+	/** sets its value to the value given by the String passed to it starting at position pos*/
+	public void setValue(String st, CharacterData data){
+		if (StringUtil.blank(st)){
+			setNumItems(1);
+			setValue(0, MesquiteInteger.unassigned);
+			return;
+		}
+		MesquiteInteger pos = new MesquiteInteger(0);
+		int n= 0;
+		String s;
+		int status = 1;
+		while (pos.getValue()<st.length() && n < 32 && status>=0) { 
+			char c = st.charAt(pos.getValue());
+			if (c == '(') {
+				status = 0;
+				pos.increment();
+			}
+			else if (c == ')')
+				status = -1;
+			else if (c == ',' || c == ' ')
+				pos.increment();
+			else {
+				if (status !=0)
+					status = -1;
+				String f =ParseUtil.getToken(st,pos); 
+				char inapp = inapplicableChar;
+				if (data != null)
+					inapp = data.getInapplicableSymbol();
+				int result = 0;
+				if (f != null && f.length() == 1 && f.charAt(0) == inapp)
+					result = inapplicable; 
+				else
+					result = MesquiteInteger.fromString(f, false); 
+				setValue(n, result);
+				n++;
+			}
+		}
+		setNumItems(n);
+	}
+	/*..........................................MeristicState................*/
+	/** gets the value of item # n*/
+	public int getValue(int n){
+		if (n>=0 && n<numItems)
+			return values[n];
+		else
+			return unassigned;
+	}
+	/*..........................................MeristicState................*/
+	/** gets the name value of item with NameReference NR*/
+	public int getValue(NameReference nr){
+		if (nr==null)
+			return MesquiteInteger.unassigned;
+		for (int i=0; i<numItems; i++)
+			if (nr.equals(names[i]))
+				return values[i];
+		return MesquiteInteger.unassigned;
+	}
+	/*..........................................MeristicState................*
+	/** sets its value to the value given by the String passed to it starting at position pos*
+	public void setValue(String st, MesquiteInteger pos){
+		if (StringUtil.blank(st)){
+			setNumItems(1);
+			setValue(0, MesquiteInteger.unassigned);
+			return;
+		}
+		int n= 0;
+		String s;
+		int status = 1;
+		while (pos.getValue()<st.length() && n < 32 && status>=0) { 
+			char c = st.charAt(pos.getValue());
+			if (c == '(') {
+				status = 0;
+				pos.increment();
+			}
+			else if (c == ')')
+				status = -1;
+			else if (c == ',' || c == ' ')
+				pos.increment();
+			else {
+				if (status !=0)
+					status = -1;
+				setValue(n, fromString(st, pos));
+				n++;
+			}
+		}
+		setNumItems(n);
+	}
+	/** Returns integer parsed from given string, starting at string position given.
+	Assumes only first token from pos is to be parsed. *
+	public int fromString(String s, MesquiteInteger pos) {
+		String f =ParseUtil.getToken(s,pos); 
+		if ("-".equals(f))
+			return inapplicable; 
+		else
+			return MesquiteInteger.fromString(f, false); 
+	}
+	/*..........................................MeristicState................*/
+	private String valueToString(int v){
+		return MeristicState.toString(v);
+	}
+	/*..........................................MeristicState................*/
+	public static String toString(int v){
+		if (v == MesquiteInteger.unassigned)
+			return "?";
+		else if (v == MesquiteInteger.inapplicable)
+			return "" + MeristicState.inapplicableChar;
+		else
+			return MesquiteInteger.toString(v);
+	}
+	public String toString() {
+		String s = "";
+		boolean first = true;
+		for (int i=0; i<numItems; i++) {
+			String name = getItemName(i);
+			if (name == null || "unnamed".equalsIgnoreCase(name)) {
+				name = "";
+				if (!first)
+					s += " " + valueToString(values[i]);
+				else
+					s += valueToString(values[i]);
+			}
+			else {
+				if (!first)
+					s += " " + name + " " + valueToString(values[i]);
+				else
+					s += name + " " + valueToString(values[i]);
+			}
+			first = false;
+		}
+		return s;
+	}
+	/*..........................................MeristicState.....................................*/
+
+	/** Returns string as would be displayed to user (not necessarily internal shorthand).  */
+	public String toDisplayString(){
+		String s = "";
+		boolean first = true;
+		if (numItems>1)
+			s += "(";
+		for (int i=0; i<numItems; i++) {
+			if (!first)
+				s += ", " + valueToString(values[i]);
+			else
+				s +=  valueToString(values[i]);
+			first = false;
+		}
+		if (numItems>1)
+			s += ")";
+		return s;
+	}
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicStateTest.java b/Source/mesquite/meristic/lib/MeristicStateTest.java
new file mode 100644
index 0000000..9cc448e
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicStateTest.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class MeristicStateTest extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof MeristicStateTest)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!CharacterState.class.isAssignableFrom((Class)obj))
+			return true;
+		if (!(obj instanceof Class))
+			return true;
+		return ((((Class)obj).isAssignableFrom(MeristicData.class)) || (((Class)obj).isAssignableFrom(MeristicState.class)));
+	}
+	public Class getAcceptedClass(){
+		return MeristicState.class;
+	}
+}
+
+
diff --git a/Source/mesquite/meristic/lib/MeristicStates.java b/Source/mesquite/meristic/lib/MeristicStates.java
new file mode 100644
index 0000000..86c6a93
--- /dev/null
+++ b/Source/mesquite/meristic/lib/MeristicStates.java
@@ -0,0 +1,160 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.meristic.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.ItemContainer;
+
+/** Contains an array of  meristic character states for one character, at each of the taxa or nodes 
+ See notes under <a href = "MeristicData.html">MeristicData</a> regarding items */
+public abstract class MeristicStates  extends CharacterStates implements ItemContainer {
+	
+	public MeristicStates (Taxa taxa) {
+		super(taxa);
+	}
+	/*..........................................MeristicStates................*/
+	/**returns blank CharacterState object */
+	public CharacterState getCharacterState (){
+		return new MeristicState();
+	}
+	/** Indicates the type of character stored */ 
+	public Class getStateClass(){
+		return MeristicState.class;
+	}
+	/**returns the corresponding CharacterData subclass*/
+	public Class getCharacterDataClass (){
+		return MeristicData.class;
+	}
+	/** returns the name of the type of data stored */
+	public String getDataTypeName(){
+		return MeristicData.DATATYPENAME;
+	}
+	/*..........................................MeristicStates................*/
+	public abstract int getNumItems();
+	/*..........................................MeristicStates................*/
+	public abstract String getItemName(int index);
+	/*..........................................MeristicStates................*/
+	public abstract NameReference getItemReference(String name);
+	/*..........................................MeristicStates................*/
+	public abstract NameReference getItemReference(int index);
+	/*..........................................MeristicStates................*/
+	public abstract int getItemNumber(NameReference nr);
+	/*..........................................MeristicStates................*/
+	public CharacterModel getDefaultModel(MesquiteProject file, String paradigm){
+   		NameReference p = NameReference.getNameReference(paradigm);
+   		DefaultReference dR = MeristicData.findDefaultReference(p);
+   		if (dR==null)
+   			return null;
+   		else {
+   			CharacterModel cm = file.getCharacterModel(dR.getDefault());
+   			if (cm==null) 
+   				MesquiteMessage.println("Default model not found / " + dR.getDefault());
+   			return cm;
+   		}
+   	}
+	/*..........................................MeristicStates................*/
+	public void logStates(){
+		MesquiteModule.mesquiteTrunk.logln("States ");
+		String statesString="";
+		for (int ic=0; ic<getNumNodes(); ic++) {
+			for (int iitems=0; iitems<getNumItems(); iitems++)
+				statesString+=toString(ic, " ") + " ";
+		}
+		statesString+= '\r';
+		MesquiteModule.mesquiteTrunk.logln(statesString);
+	}
+	/*..........................................MeristicStates................*/
+	public abstract int getState (int N, int item);
+	/*..........................................MeristicStates................*/
+	public abstract int getState (int N);
+	/*..........................................MeristicStates................*/
+	
+   	public  boolean isInapplicable(int N){
+   		for (int item = 0; item< getNumItems(); item++)
+   			if ( getState(N, item)!= MeristicState.inapplicable)
+   				return false;
+   		return true; 
+   	}
+
+	/*..........................................MeristicStates................*/
+   	public  boolean isUnassigned(int N){
+   		for (int item = 0; item< getNumItems(); item++)
+   			if ( getState(N, item)!= MeristicState.unassigned)
+   				return false;
+   		return true; 
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** returns whether the state of character has uncertainty in node/taxon N*/
+   	public boolean isUncertain(int N){  //TODO: implement uncertainty for meristic data
+   		return false;
+   	}
+	/*..........................................MeristicStates................*/
+   	public int userQueryItem(String message, MesquiteModule module){
+		int numItems =getNumItems();
+		String[] items = new String[numItems];
+		for (int i=0; i<items.length; i++){
+			if (StringUtil.blank(getItemName(i)))
+				items[i] = "(unnamed)";
+			else
+				items[i]= getItemName(i);
+		}
+		return ListDialog.queryList(module.containerOfModule(), "Select item", message, MesquiteString.helpString,  items, 0);
+   	}
+	/*..........................................MeristicStates................*/
+	public CharacterState getCharacterState (CharacterState cs, int N){
+		MeristicState c;
+		if (cs==null || !(cs instanceof MeristicState))
+			c = new MeristicState();
+		else c = (MeristicState)cs;
+		c.setItemsAs(this);
+		for (int i=0; i<getNumItems(); i++)
+			c.setValue(i, getState(N, i));
+		return c;
+	}
+	/*..........................................MeristicStates................*/
+	/** Is the first state greater than second?  This uses only the first item! */
+	public boolean firstIsGreater (int N, int M){ 
+		if (getState(N) > getState(M))
+			return true;
+		return false;
+		
+	}
+	/*..........................................MeristicStates................*/
+	public boolean statesEqual(int N, int M) {
+   		for (int item = 0; item< getNumItems(); item++)
+   			if (getState(N, item)!= getState(M, item))
+   				return false;
+   		return true; 
+	}
+	/*..........................................MeristicStates................*/
+	public String toString (int node, String lineEnding) {
+		if (getNumItems() == 1)
+			return MeristicState.toString(getState(node)); 
+		else { //if min and max do special string
+			String s="";
+			for (int i=0; i<getNumItems(); i++) {
+				s += getItemName(i) + ":" + MeristicState.toString(getState(node, i)) + lineEnding;
+			}
+			return s;
+		}
+	}
+	
+}
+
+
diff --git a/Source/mesquite/meristic/lib/RequiresAnyMeristicData.java b/Source/mesquite/meristic/lib/RequiresAnyMeristicData.java
new file mode 100644
index 0000000..742dcda
--- /dev/null
+++ b/Source/mesquite/meristic/lib/RequiresAnyMeristicData.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.meristic.lib;
+
+import mesquite.meristic.lib.RequiresExactlyMeristicData;
+import mesquite.lib.CompatibilityTest;
+import mesquite.lib.EmployerEmployee;
+import mesquite.lib.MesquiteProject;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterState;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresAnyMeristicData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresExactlyMeristicData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) && !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return   (MeristicState.class.isAssignableFrom((Class)obj) || MeristicState.class.isAssignableFrom((Class)obj));
+	}
+	public Class getAcceptedClass(){
+		return MeristicState.class;
+	}
+}
diff --git a/Source/mesquite/meristic/lib/RequiresExactlyMeristicData.java b/Source/mesquite/meristic/lib/RequiresExactlyMeristicData.java
new file mode 100644
index 0000000..760abf5
--- /dev/null
+++ b/Source/mesquite/meristic/lib/RequiresExactlyMeristicData.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */package mesquite.meristic.lib;
+
+import mesquite.lib.CompatibilityTest;
+import mesquite.lib.EmployerEmployee;
+import mesquite.lib.MesquiteProject;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterState;
+
+/* ======================================================================== */
+/** An object a module can create and pass back to store in module info.  Tests whether module will be compatible with
+passed object.  Classes of modules will have known ways of responding to particular classes of objects, e.g. character sources
+should test whether they can handle given CharacterState types.*/
+public class RequiresExactlyMeristicData extends CompatibilityTest {
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (obj instanceof RequiresExactlyMeristicData)
+			return true;
+		if (obj instanceof CompatibilityTest)
+			return false;
+		if (!(obj instanceof Class))
+			return true;
+		if (!CharacterState.class.isAssignableFrom((Class)obj) &&  !CharacterData.class.isAssignableFrom((Class)obj))
+			return true;
+		return  (MeristicState.class == obj) || MeristicState.class == obj;
+	}
+	public Class getAcceptedClass(){
+		return MeristicState.class;
+	}
+}
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/BasicFileCoordinator.java b/Source/mesquite/minimal/BasicFileCoordinator/BasicFileCoordinator.java
new file mode 100644
index 0000000..9fa64b5
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/BasicFileCoordinator.java
@@ -0,0 +1,2128 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.BasicFileCoordinator;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/** The "vice president" of the Mesquite system (the MesquiteTrunk module "Mesquite" being the president).  One of these is hired to coordinate each project.
+Should actually be named ProjectCoordinator.*/
+public class BasicFileCoordinator extends FileCoordinator implements PackageIntroInterface {
+	public static long totalProjectPanelRefreshes = 0;
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(FileInit.class, "Modules assist with tasks connected to each project or file.",
+		"");
+		e2.setAsEntryPoint(null);
+		e2.setSuppressListing(true);
+		EmployeeNeed e3 = registerEmployeeNeed(FileElementManager.class, "Modules assist with management of taxa, matrices, trees and other data to each project or file.",
+		"");
+		e3.setAsEntryPoint(null);
+		e3.setSuppressListing(true);
+		EmployeeNeed e4 = registerEmployeeNeed(FileInterpreter.class, "Modules assist with reading and writing files of various formats.",
+		"");
+		e4.setAsEntryPoint(null);
+		e4.setSuppressListing(true);
+		EmployeeNeed e5 = registerEmployeeNeed(FileAssistant.class, "Modules assist with files.",
+		"");
+		e5.setAsEntryPoint("newAssistant");
+		//e5.setSuppressListing(true);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Basic File Coordinator";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the reading, maintenance and linkages of files, which include Taxa, Trees, CharacterData, and other objects." 
+		+ " This module is hired directly by the Mesquite trunk module.";
+	}
+	MesquiteMenuSpec elementsMenu;
+
+	boolean ready = false;
+	Vector firstToKnowModules;
+	ProjectWindow pw;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//	elementsMenu = makeMenu("Elements");
+
+		loadPreferences();
+		firstToKnowModules = new Vector();
+		MesquiteModule e;
+		hireAllEmployees(FileInterpreter.class);
+		hireInit( FileInit.class, "Manage Authors"); 
+		firstToKnowModules.addElement(hireInit( FileElementManager.class, "#mesquite.minimal.ManageTaxa.ManageTaxa")); 
+		firstToKnowModules.addElement(hireInit( FileElementManager.class, "#mesquite.trees.ManageTrees.ManageTrees"));
+		firstToKnowModules.addElement(hireInit( FileInit.class, "#mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord"));
+		firstToKnowModules.addElement(hireInit( FileInit.class, "#mesquite.charMatrices.BasicDataWindowCoord.BasicDataWindowCoord"));
+		firstToKnowModules.addElement(hireInit( FileElementManager.class, "#mesquite.charMatrices.ManageCharacters.ManageCharacters"));
+		hireInit( FileInit.class, "Manage Character Models"); 
+		hireInit( FileInit.class, "Manage parsimony model sets");
+		hireInit( FileInit.class, "Manage probability model sets");
+		hireInit( FileInit.class, "Manage character sets");
+		hireInit( FileInit.class, "Manage SETS blocks");
+		hireInit( FileInit.class, "Manage ASSUMPTIONS blocks");
+		hireInit( FileInit.class, "Manage NOTES blocks");
+		hireAllOtherEmployees(FileElementManager.class);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "suggestedDirectory", MesquiteTrunk.suggestedDirectory);  
+		return buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("suggestedDirectory".equalsIgnoreCase(tag)){
+			MesquiteTrunk.suggestedDirectory = StringUtil.cleanXMLEscapeCharacters(content);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			MesquiteTrunk.suggestedDirectory = prefs[0];
+		}
+	}
+	private MesquiteModule hireInit( Class dutyClass, String name){
+		if (mesquiteTrunk.mesquiteModulesInfoVector.findModule(dutyClass, name) == null)
+			return null;
+		MesquiteModule e = hireNamedEmployee(dutyClass, StringUtil.tokenize(name));
+		if (e!=null)
+			e.setPriorityFixed(true);
+		return e;
+	}
+	public void endJob() {
+		doomed = true;
+		incrementMenuResetSuppression();
+		disposeMenuSpecifications();
+		MesquiteProject p=getProject();
+		if (p!=null) {	
+			p.isDoomed = true;
+			int count = 0;
+			boolean done = false;
+			while (p.developing && !MesquiteThread.isScripting() && !done) {
+				count++;
+				if (count % 10000 == 0){
+					MesquiteMessage.printStackTrace("Failure to close project");
+					if (MesquiteThread.isScripting() || AlertDialog.query(containerOfModule(), "Force Close?", "The project is not responding to the request to close it.  Force it to close?", "Force Close", "Continue", 1))
+						done = true;
+				}
+			}
+			closeWindows();
+
+			doomEmployees(this);
+			p.dispose();
+			MesquiteTrunk.mesquiteTrunk.removeProject(p);
+		}
+		decrementMenuResetSuppression();
+		setProject(null);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		if (m instanceof FileAssistantC) {
+			resetAllMenuBars();
+		}
+		super.employeeQuit(m);
+	}
+	private void doomEmployees(MesquiteModule mb){
+		if (mb.getEmployeeVector()==null)
+			return;
+		Enumeration e = mb.getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteModule mbe = (MesquiteModule)obj;
+			if (mbe!=null) {
+				doomEmployees(mbe);
+				mbe.doom();
+			}
+		}
+	}
+	public void closeWindows(){
+		if (getModuleWindow() != null){
+			getModuleWindow().getParentFrame().setVisible(false);
+		}
+		Enumeration e = MesquiteTrunk.mesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw.isVisible() && mw.getOwnerModule()!=null && mw.getOwnerModule().getProject()== getProject())
+				mw.getParentFrame().setVisible(false);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject initiateProject(String pathName, MesquiteFile homeFile) {
+		MesquiteProject p = new MesquiteProject((FileCoordinator)this);
+		p.incrementProjectWindowSuppression();
+		setProject(p);
+		pw =  new ProjectWindow(this);
+		p.setFrame(pw.getParentFrame());
+		setModuleWindow(pw);
+		if (Thread.currentThread() instanceof ProjectReadThread)
+			pw.setWindowSize(2, 500);
+		else
+			pw.setWindowSize(700, 500);
+		pw.setWindowLocation(8,8, false); //TODO: should set staggered positions
+		MesquiteTrunk.mesquiteTrunk.addProject(getProject());
+		p.addFile(homeFile);
+		homeFile.setProject(p);
+		p.setHomeFile(homeFile);
+		for (int i = 0; i<firstToKnowModules.size(); i++){
+			MesquiteModule mb = (MesquiteModule)firstToKnowModules.elementAt(i);
+			if (mb != null)
+				mb.projectEstablished();
+		}
+		hireAllOtherEmployees(FileInitEarlyLoad.class);  //TODO: NOTSCRIPTING???
+		hireAllOtherEmployees(FileInit.class);  //TODO: NOTSCRIPTING???
+		if (getProject()==null)
+			alert("FILE NULL");
+
+		///THESE SHOULD BE ONLY AFTER Project made
+		addModuleMenuItems(MesquiteTrunk.windowsMenu, makeCommand("newAssistant",  this), FileAssistantN.class);
+		MesquiteMenuItemSpec mi;
+		mi = addMenuItem(MesquiteTrunk.analysisMenu, "Chart Wizard...", makeCommand("chartWizard",  this));
+		mi.setArgument("mesquite.charts.");
+
+		mi.setZone(0);
+		if (numCompatibleModulesAvailable(FileAssistantCH.class, null, this)>0) {
+			mi = addSubmenu(MesquiteTrunk.analysisMenu, "New Bar & Line Chart for", makeCommand("newAssistant",  this), FileAssistantCH.class);
+			mi.setZone(0);
+		}
+		if (numCompatibleModulesAvailable(FileAssistantCS.class, null, this)>0) {
+			mi = addSubmenu(MesquiteTrunk.analysisMenu, "New Scattergram for", makeCommand("newAssistant",  this), FileAssistantCS.class);
+			mi.setZone(0);
+		}
+		if (numCompatibleModulesAvailable(FileAssistantCP.class, null, this)>0) {
+			mi = addSubmenu(MesquiteTrunk.analysisMenu, "New Pairwise Chart for", makeCommand("newAssistant",  this), FileAssistantCP.class);
+			mi.setZone(0);
+		}
+		MesquiteSubmenuSpec mss = addSubmenu(MesquiteTrunk.analysisMenu, "Current Charts", makeCommand("showChart", this));
+		mss.setZone(1);
+		mi = addMenuItem(MesquiteTrunk.analysisMenu, "-", null);
+		mi.setZone(1);
+		Enumeration e = MesquiteTrunk.windowVector.elements();
+		mss.setList(MesquiteTrunk.windowVector);
+		mss.setListableFilter(ChartWindow.class);
+	//	MesquiteSubmenuSpec mss2 = addSubmenu(MesquiteTrunk.analysisMenu, "Other", makeCommand("newAssistant",  this), FileAssistantA.class);
+		addMenuItem(MesquiteTrunk.analysisMenu, "-", null);
+		addModuleMenuItems(MesquiteTrunk.analysisMenu, makeCommand("newAssistant",  this), FileAssistantA.class);
+
+		broadcastProjectEstablished(this);
+		p.refreshProjectWindow();
+		p.decrementProjectWindowSuppression();
+		return p;
+	}
+	/** Dumps list of available modules to System.out.*/
+	public void dumpModuleList () {
+		int num = MesquiteTrunk.mesquiteModulesInfoVector.size();
+		logln("\n\n=====All Modules Loaded=====");
+		MesquiteModuleInfo mbi;
+		for (int i=0; i<num; i++){
+			mbi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteModulesInfoVector.elementAt(i);
+			logln(mbi.getClassName() + "              duty class " + mbi.getDutyClass());
+		}
+		logln("=================\n\n");
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile createProject(String pathName, boolean createTaxaBlockIfNew) { 
+		//TODO: ALLOW THIS ONLY ONCE FOR A FILE COORDINATOR
+		MainThread.incrementSuppressWaitWindow();
+		incrementMenuResetSuppression();
+		String dirName;
+		String fileName;
+
+		boolean brandNew = false;
+		if (StringUtil.blank(pathName) && !MesquiteThread.isScripting()) {
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), "New file:", FileDialog.SAVE);
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setFile("untitled.nex");
+			fdlg.setVisible(true);
+			dirName= fdlg.getDirectory();
+			fileName= fdlg.getFile();
+			// fdlg.dispose();
+			if (StringUtil.blank(dirName) || StringUtil.blank(fileName)) {
+				decrementMenuResetSuppression();
+				MainThread.decrementSuppressWaitWindow();
+				if (StringUtil.blank(dirName) &&  StringUtil.blank(fileName))
+					logln("New Project cancelled by user");
+				else if ( StringUtil.blank(fileName))
+					logln("New Project not created because file name not supplied.");
+				else if ( StringUtil.blank(dirName))
+					logln("New Project not created because directory name not supplied.");
+				return null;
+			}
+			brandNew = true;
+		}
+		else {
+			dirName = StringUtil.getAllButLastItem(pathName, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			fileName = StringUtil.getLastItem(pathName, MesquiteFile.fileSeparator, "/");
+		}
+		MesquiteFile thisFile =MesquiteFile.newFile(dirName, fileName);
+
+		MesquiteProject p=null;
+		if (thisFile!=null) {
+			p = initiateProject(thisFile.getFileName(), thisFile);
+			p.incrementProjectWindowSuppression();
+			thisFile.setProject(p);
+			//add MesquiteBlock
+			afterProjectRead();
+			if (brandNew && createTaxaBlockIfNew) {
+				MesquiteInteger buttonPressed = new MesquiteInteger(1);
+				ExtensibleDialog makeFileDialog = new ExtensibleDialog(containerOfModule(), "New File Options",buttonPressed);
+				makeFileDialog.addLargeOrSmallTextLabel ("Do you want your new file to include taxa?");
+				Checkbox tx = makeFileDialog.addCheckBox("Make Taxa Block", true);
+				SingleLineTextField nameTaxa = makeFileDialog.addTextField("Name", "Taxa", 30);
+				IntegerField numberTaxa = makeFileDialog.addIntegerField("Number of Taxa", 3, 6);
+				makeFileDialog.addHorizontalLine(1);
+				//Checkbox showTree = makeFileDialog.addCheckBox("Show Tree Window", true);
+				//makeFileDialog.addHorizontalLine(1);
+				makeFileDialog.addLargeOrSmallTextLabel ("If your file includes taxa, do you want it to include a character matrix?");
+				Checkbox mcm = makeFileDialog.addCheckBox("Make Character Matrix", false);
+				makeFileDialog.completeAndShowDialog("OK",null,null,"OK");
+
+				CommandRecord oldCommandRec = MesquiteThread.getCurrentCommandRecord();
+				CommandRecord scriptRec = new CommandRecord(true);
+				MesquiteThread.setCurrentCommandRecord(scriptRec);
+				boolean showSubstantiveWindow = false;
+
+				if (buttonPressed.getValue()==0) {
+					if (tx.getState() && numberTaxa.isValidInteger()){
+						makeFileDialog.dispose();
+						TaxaManager mTaxa = (TaxaManager)findEmployeeWithDuty(TaxaManager.class);
+						Object t = null;
+						if (mTaxa!=null) 
+							t = mTaxa.doCommand("newTaxa",Integer.toString(numberTaxa.getValue()) + " " + ParseUtil.tokenize(nameTaxa.getText()), CommandChecker.defaultChecker); //treat as scripting so as not to complain if something not found 19Jan02
+						
+						if (t!=null){
+							if (mcm.getState()){
+								CharactersManager mChars = (CharactersManager)findEmployeeWithDuty(CharactersManager.class);
+								if (mChars!=null) {
+									mChars.doCommand("newMatrix",null, CommandChecker.defaultChecker); 
+									mChars.doCommand("showLastMatrixWindow",null, CommandChecker.defaultChecker);
+									showSubstantiveWindow = true;
+								}
+							}
+							if (!showSubstantiveWindow){
+								showProjectWindow();
+								mTaxa.doCommand("showTaxa","0", CommandChecker.defaultChecker);
+							}
+
+						}
+						else {
+							makeFileDialog.dispose();
+							showProjectWindow();
+						}
+					}
+					else {
+						makeFileDialog.dispose();
+						showProjectWindow();
+					}
+				}
+				else {
+					makeFileDialog.dispose();
+					showProjectWindow();
+				}
+				MesquiteThread.setCurrentCommandRecord(oldCommandRec);
+			}
+			MesquiteWindow w = getModuleWindow();
+			if (w != null){
+				if (!MesquiteThread.isScripting())
+					w.setWindowSizeForce(700, 500);
+				((ProjectWindow)w).resume(false);
+			}
+
+			p.decrementProjectWindowSuppression();
+			p.refreshProjectWindow();
+		}
+		MesquiteWindow.hideClock();
+		resetAllMenuBars();
+		if (p!=null)
+			p.developing = false;
+		if (getModuleWindow()!=null) {
+			getModuleWindow().getParentFrame().showFrontWindow();
+		}
+		decrementMenuResetSuppression();
+		MainThread.decrementSuppressWaitWindow();
+		return thisFile;
+	}
+	public void showProjectWindow(){
+		doCommand("showWindow", null, CommandChecker.defaultChecker); //treat as scripting so as not to complain if something not found 19Jan02
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile createBlankProject() { 
+		MainThread.incrementSuppressWaitWindow();
+		incrementMenuResetSuppression();
+		boolean brandNew = false;
+		MesquiteFile thisFile =MesquiteFile.newFile(MesquiteTrunk.userDirectory.toString(), "temp.nex");
+
+		MesquiteProject p=null;
+		if (thisFile!=null) {
+			p = initiateProject(thisFile.getFileName(), thisFile);
+			thisFile.setProject(p);
+			afterProjectRead();
+
+		}
+		MesquiteWindow.hideClock();
+		resetAllMenuBars();
+		if (p!=null)
+			p.developing = false;
+		decrementMenuResetSuppression();
+		MainThread.decrementSuppressWaitWindow();
+		return thisFile;
+	}
+
+	public void refreshProjectWindow(){
+		if (getProject().refreshSuppression == 0){
+			getProject().refreshPending = false;
+			MesquiteWindow w = getModuleWindow();
+			if (w != null && w instanceof ProjectWindow) {
+				((ProjectWindow)w).refresh();
+				((ProjectWindow)w).refreshGraphics();
+			}
+		}
+		else 
+			getProject().refreshPending = true;
+	}
+	public void refreshInProjectWindow(FileElement element){
+		MesquiteWindow w = getModuleWindow();
+		if (w != null && w instanceof ProjectWindow)
+			((ProjectWindow)w).refresh(element);
+	}
+	public void refreshGraphicsProjectWindow(){
+		MesquiteWindow w = getModuleWindow();
+		if (w != null && w instanceof ProjectWindow)
+			((ProjectWindow)w).refreshGraphics();
+	}
+
+	/*.................................................................................................................*/
+	public void elementAdded(FileElement e){
+		refreshProjectWindow();
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		refreshProjectWindow();
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile createFile(String pathName){
+		MainThread.incrementSuppressWaitWindow();
+		String dirName;
+		String fileName;
+		if (StringUtil.blank(pathName)) {
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), "New linked file:", FileDialog.SAVE);
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			fdlg.setFile("linked.nex");
+			fdlg.setVisible(true);
+			dirName= fdlg.getDirectory();
+			fileName= fdlg.getFile();
+			// fdlg.dispose();
+			if (StringUtil.blank(dirName) || StringUtil.blank(fileName)) {
+				decrementMenuResetSuppression();
+				MainThread.decrementSuppressWaitWindow();
+				if (StringUtil.blank(dirName) &&  StringUtil.blank(fileName))
+					logln("New File cancelled by user");
+				else if ( StringUtil.blank(fileName))
+					logln("New File not created because file name not supplied.");
+				else if ( StringUtil.blank(dirName))
+					logln("New File not created because directory name not supplied.");
+				return null;
+			}
+		}
+		else {
+			dirName = StringUtil.getAllButLastItem(pathName, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			fileName = StringUtil.getLastItem(pathName, MesquiteFile.fileSeparator, "/");
+		}
+		MainThread.decrementSuppressWaitWindow();
+		return MesquiteFile.newFile(dirName, fileName);
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile newLinkedFile(String pathName) {  //makes new linked file
+		incrementMenuResetSuppression();
+		MesquiteFile thisFile;
+		if (StringUtil.blank(pathName)){
+			MainThread.incrementSuppressWaitWindow();
+			MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), "New linked file:", FileDialog.SAVE);
+			fdlg.setFile("linked.nex");
+			fdlg.setBackground(ColorTheme.getInterfaceBackground());
+			String dirName;
+			String fileName;
+
+			fdlg.setVisible(true);
+			dirName= fdlg.getDirectory();
+			fileName= fdlg.getFile();
+			// fdlg.dispose();
+			MainThread.decrementSuppressWaitWindow();
+			if (StringUtil.blank(dirName) || StringUtil.blank(fileName)) {
+				decrementMenuResetSuppression();
+				if (StringUtil.blank(dirName) &&  StringUtil.blank(fileName))
+					logln("New File cancelled by user");
+				else if ( StringUtil.blank(fileName))
+					logln("New File not created because file name not supplied.");
+				else if ( StringUtil.blank(dirName))
+					logln("New File not created because directory name not supplied.");
+				return null;
+			}
+			thisFile = MesquiteFile.newFile(dirName, fileName);
+		}
+		else {
+			if (pathName.indexOf(MesquiteFile.fileSeparator)<0) {
+				thisFile =MesquiteFile.newFile(getProject().getHomeDirectoryName(), pathName);
+			}
+			else {
+				String dirName = StringUtil.getAllButLastItem(pathName, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+				String fileName = StringUtil.getLastItem(pathName, MesquiteFile.fileSeparator, "/");
+				thisFile =MesquiteFile.newFile(dirName, fileName);
+			}
+		}
+		if (thisFile!=null) {
+			getProject().addFile(thisFile);
+			thisFile.setProject(getProject());
+			broadcastFileRead(this, thisFile);
+		}
+		resetAllMenuBars();
+		decrementMenuResetSuppression();
+		return thisFile;
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile readProject(boolean local, String pathName, String arguments) { 
+
+		//ALLOW THIS ONLY ONCE FOR A FILE COORDINATOR
+		if (getProject()!=null) { 
+			alert("Error: attempt to read second project for single file coordinator");
+			return null;
+		}
+
+		incrementMenuResetSuppression();
+		MesquiteProject p=null;
+		String message;
+		if (local)
+			message = "Open file as independent project:";
+		else
+			message = "Open URL as independent project:";
+
+		MesquiteFile thisFile =MesquiteFile.open(local, pathName, message, MesquiteTrunk.suggestedDirectory);
+		if (thisFile!=null && (thisFile.isLocal() && thisFile.existingLength()<=0)) { 
+			alert("Error: File is empty.");
+			return null;
+		}
+
+		if (thisFile!=null){
+			MesquiteTrunk.suggestedDirectory = thisFile.getDirectoryName();
+			storePreferences();
+		}
+
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+
+		boolean imp = false; //was it imported???
+
+		if (thisFile!=null && !StringUtil.blank(thisFile.getFileName())) {
+
+			logln("Location: " + thisFile.getDirectoryName() + thisFile.getFileName());
+			logln("");
+
+			FileInterpreter fileInterp;
+
+
+
+			//first try nexus.  If can't be read, then make list and query user...
+			NexusFileInterpreter nfi = (NexusFileInterpreter)findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+			if (nfi!=null && nfi.canReadFile(thisFile))
+				fileInterp = nfi;
+			else {
+				imp = true;
+				fileInterp = findImporter(thisFile, 0, arguments);
+			}
+			if (fileInterp !=null) {
+				p = initiateProject(thisFile.getFileName(), thisFile);
+				p.timePreviouslySavedByFile = MesquiteFile.fileOrDirectoryLastModified(thisFile.getDirectoryName() + thisFile.getFileName());
+				p.incrementProjectWindowSuppression();
+				MesquiteFile sf = CommandRecord.getScriptingFileS();
+				if (MesquiteThread.isScripting())
+					CommandRecord.setScriptingFileS(thisFile);
+				pw.suppress();
+				if (parser.tokenIndexOfIgnoreCase(arguments, "useStandardizedTaxonNames")>=0)
+					thisFile.useStandardizedTaxonNames = true;
+				int tI = parser.tokenIndexOfIgnoreCase(arguments, "taxa");
+				if (tI>=0){
+					String ref = parser.getTokenNumber(arguments, tI+2);
+					Taxa taxa = getProject().getTaxa(ref);
+					thisFile.setCurrentTaxa(taxa);
+				}
+				fileInterp.readFile(getProject(), thisFile, arguments);
+				if (fileInterp != nfi)
+					pw.setWindowSize(700, 500);
+				pw.resume();
+				CommandRecord.setScriptingFileS(sf);
+				p.decrementProjectWindowSuppression();
+
+				if (thisFile.isClosed()){
+					if (p !=null)
+						p.developing = false;
+					resetAllMenuBars();
+					decrementMenuResetSuppression();
+					iQuit();
+					return null;
+				}
+				else {
+					p.fileSaved(thisFile);
+					if (imp && local && parser.tokenIndexOfIgnoreCase(arguments, "suppressImportFileSave")<0){//was imported; change name
+						thisFile.changeLocation(thisFile.getDirectoryName(), thisFile.getFileName()+".nex");
+						if (MesquiteThread.isScripting() || thisFile.changeLocation("Save imported file as NEXUS file")) {
+							afterProjectRead();
+							writeFile(thisFile); 
+						}
+						else {
+							if (p !=null)
+								p.developing = false;
+							resetAllMenuBars();
+							decrementMenuResetSuppression();
+							iQuit();
+							return null;
+						}
+					}
+					else
+						afterProjectRead();
+				}
+			}
+			else {
+				alert("Sorry, an interpreter was not found for this file");
+			}
+		}
+		resetAllMenuBars();
+		if (p!=null)
+			p.developing = false;
+		decrementMenuResetSuppression();
+		if (p!=null)
+			p.refreshProjectWindow();
+		if (noWindowsShowing()){
+			doCommand("showWindow", null, CommandChecker.defaultChecker); //TODO: will this always be non-scripting???
+			if (imp){
+				if (getProject().getNumberCharMatrices()>0){
+					MesquiteModule mbb = findEmployeeWithName("Data Window Coordinator");
+					if (mbb != null)
+						mbb.doCommand("showDataWindow", "0", CommandChecker.defaultChecker);
+				}
+				else if (getProject().getNumberTaxas()>0){
+					MesquiteModule mbb = findEmployeeWithName("Manage TAXA blocks");
+					if (mbb != null)
+						mbb.doCommand("showTaxa", "0", CommandChecker.defaultChecker);
+				}
+			}
+		}
+		
+		if (thisFile != null && thisFile.getCloseAfterReading()){
+			closeFile(thisFile);
+			MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+			return null;
+		}
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+		return thisFile;
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile readProjectGeneral(String arguments) { 
+		if (getProject()!=null) { 
+			alert("Error: attempt to read second project for single file coordinator");
+			return null;
+		}
+		incrementMenuResetSuppression();
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+		parser.setString(arguments);
+		//hire reader
+		String reader = parser.getFirstToken();
+		String extraArgs = parser.getNextToken();
+		GeneralFileMaker e = (GeneralFileMaker)hireNamedEmployee(GeneralFileMaker.class, ParseUtil.tokenize(reader));
+
+		MesquiteProject p = null;
+		if (e != null) {
+			p = e.establishProject(extraArgs);
+			if (p!=null){
+				p.incrementProjectWindowSuppression();
+				if (pw == null){
+					pw =  new ProjectWindow(this);
+					p.setFrame(pw.getParentFrame());
+					setModuleWindow(pw);
+				}
+				pw.setWindowSize(700, 500);
+				pw.setWindowLocation(8,8, false);
+
+				p.developing = false;
+				afterProjectRead();
+				refreshProjectWindow();
+				p.decrementProjectWindowSuppression();
+			}
+			resetAllMenuBars();
+		}
+		decrementMenuResetSuppression();
+		if (p==null){
+			fireEmployee(e);
+			iQuit();
+			return null;
+		}
+		MesquiteFile thisFile = p.getHomeFile();
+		if (noWindowsShowing())
+			doCommand("showWindow", null, CommandChecker.defaultChecker); //TODO: will this always be non-scripting???
+		if (thisFile != null && thisFile.getCloseAfterReading()){
+			closeFile(thisFile);
+			MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+			return null;
+		}
+		if (p.autosave){
+			saveAllFiles();
+			p.autosave = false;
+		}
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+		return thisFile;
+	}
+	/*.................................................................................................................*/
+	private boolean noWindowsShowing(){
+		Enumeration e = MesquiteTrunk.windowVector.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			MesquiteWindow mw = (MesquiteWindow)obj;
+			if (mw !=null && !mw.getMinimalMenus() && mw.isVisible() && mw.ownerModule!=null && mw.ownerModule.getProject()==getProject())
+				return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile readLinkedFile(String pathName, String importer, String arguments, int fileType, String fileDescriptionText){ //make new/read new linked file
+		if (MesquiteThread.isScripting()) {
+			ObjectContainer f = new ObjectContainer();
+			FileRead pt = new FileRead(pathName, importer, arguments, fileType,   this, 0, f, fileDescriptionText);
+			
+			pt.run();
+			MesquiteFile mf = (MesquiteFile)f.getObject();
+			f.setObject(null);
+			return mf;
+		}
+		else {
+			FileRead fr = new FileRead(pathName, importer, arguments, fileType,   this, 0, null, fileDescriptionText);
+
+			MesquiteThread pt = new MesquiteThread(fr);
+
+			pt.setCommandRecord(MesquiteThread.getCurrentCommandRecord());
+			pt.start();
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	public void includeFile(String pathName, String importer, String arguments, int fileType, String fileDescriptionText){ //make new/read new linked file
+		FileRead pt = new FileRead(pathName, importer, arguments, fileType,   this, 1, null, fileDescriptionText);
+		if (MesquiteThread.isScripting()) {
+			pt.run();
+		}
+		else {
+			MesquiteThread mt = new MesquiteThread(pt);
+			mt.start();
+		}
+	}
+	/*.................................................................................................................*/
+	public void includeFileFuse(String pathName, String importer, String arguments, int fileType, String fileDescriptionText){ //make new/read new linked file  DONE special to put on same thread
+		getProject().incrementProjectWindowSuppression();
+		FileRead pt = new FileRead(pathName, importer, arguments, fileType,   this, 1, null, fileDescriptionText);
+			pt.run();
+			cleanFusedReadingSuppressions();
+			getProject().decrementProjectWindowSuppression();
+	}
+	void cleanFusedReadingSuppressions(){
+		int num = getProject().getNumberCharMatrices();
+		for (int im = 0; im< num; im++){
+			CharacterData data = getProject().getCharacterMatrix(im);
+			data.setSuppressSpecssetReading(false);
+		}
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile getNEXUSFileForReading(String arguments, String message){ 
+		String path = parser.getFirstToken(arguments); //optional argument
+
+
+		MesquiteFile file = null;
+		if (StringUtil.blank(path)) {
+			file =MesquiteFile.open(true, (String)null, message, getProject().getHomeDirectoryName());
+		}
+		else if (path.indexOf(MesquiteFile.fileSeparator)<0) {
+			file =MesquiteFile.open(getProject().getHomeDirectoryName(), path);
+		}
+		else {
+			String dirName = StringUtil.getAllButLastItem(path, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			String fileName = StringUtil.getLastItem(path, MesquiteFile.fileSeparator, "/");
+			file =MesquiteFile.open(dirName, fileName);
+		}
+		if (file == null)
+			return null;
+		NexusFileInterpreter nfi = (NexusFileInterpreter)findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+		if (nfi==null || !nfi.canReadFile(file)) {
+			return null; //not a nexus file
+		}
+		return file;
+	}
+	/*.................................................................................................................*/
+	public FileBlock getNEXUSBlock(String blockType, String path){ 
+		MesquiteFile file = null;
+		if (StringUtil.blank(path)) {
+			String message = "Choose file from which to obtain " + blockType + " block";
+			file =MesquiteFile.open(true, (String)null, message, getProject().getHomeDirectoryName());
+		}
+		else if (path.indexOf(MesquiteFile.fileSeparator)<0) {
+			file =MesquiteFile.open(getProject().getHomeDirectoryName(), path);
+		}
+		else {
+			String dirName = StringUtil.getAllButLastItem(path, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			String fileName = StringUtil.getLastItem(path, MesquiteFile.fileSeparator, "/");
+			file =MesquiteFile.open(dirName, fileName);
+		}
+		if (file == null)
+			return null;
+		NexusFileInterpreter nfi = (NexusFileInterpreter)findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+		if (!nfi.canReadFile(file)) {
+			return null;
+		}
+		FileBlock block = nfi.readOneBlock(getProject(), file, blockType, 0);
+		file.dispose();
+		return block;
+	}
+	/*.................................................................................................................*/
+	public TextDisplayer displayText(String text, String title) {
+		TextDisplayer displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+		if (displayer!=null){
+			displayer.showText(text, title, true); 
+		}
+		return displayer;
+	}
+	/*.................................................................................................................*/
+	public TextDisplayer displayFile(MesquiteFile file, int maxCharacters) {
+		TextDisplayer displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+		if (displayer!=null) {
+			displayer.showFile(file, maxCharacters, true,9, true); 
+		}
+		return displayer;
+	}
+	/*.................................................................................................................*/
+	public TextDisplayer displayFile(String pathName, int maxCharacters) {
+		TextDisplayer displayer = (TextDisplayer)hireEmployee(TextDisplayer.class, null);
+		if (displayer!=null) {
+			displayer.showFile(pathName, maxCharacters, true,9, true); 
+		}
+		return displayer;
+	}
+	/*.................................................................................................................*/
+	void afterProjectRead() {
+		if (getModuleWindow()!=null) {
+			getModuleWindow().resetTitle(); //WHAT IF MULTIPLE LINKED FILES??
+		}
+		FileInit employee;
+		Enumeration enumeration=getEmployeeVector().elements();
+
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			((MesquiteModule)obj).setProject(getProject());
+		}
+		broadcastFileRead(this, getProject().getHomeFile());
+		ready = true;
+		if (getModuleWindow()!=null) {
+			getModuleWindow().getParentFrame().showFrontWindow();
+		//	getModuleWindow().getParentFrame().fixFrontness();
+		}
+
+		resetAllMenuBars();
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been established but not yet read in.*/
+	void broadcastProjectEstablished(MesquiteModule module) {
+		if (module==null)
+			return;
+
+		EmployeeVector e = module.getEmployeeVector();
+		if (e==null)
+			return;
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+
+			if (employee!=null){
+				if (firstToKnowModules.indexOf(employee)<0)
+					employee.projectEstablished();
+				broadcastProjectEstablished(employee);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after a file has been read in.*/
+	public void wrapUpAfterFileRead(MesquiteFile f) {
+				broadcastFileRead(this, f);
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after a file has been read in.*/
+	void broadcastFileRead(MesquiteModule module, MesquiteFile f) {
+		if (module==null)
+			return;
+		EmployeeVector e = module.getEmployeeVector();
+		if (e==null)
+			return;
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+			if (employee!=null){
+				employee.fileReadIn(f);
+				broadcastFileRead(employee, f);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately before a file is to be written.*/
+	void broadcastFileAboutToBeSaved(MesquiteModule module, MesquiteFile f) {
+		if (module==null)
+			return;
+		EmployeeVector e = module.getEmployeeVector();
+		if (e==null)
+			return;
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+			if (employee!=null){
+				employee.fileAboutToBeWritten(f);
+				broadcastFileAboutToBeSaved(employee, f);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** THIS APPEARS NO LONGER USED*/
+	public String userPutFile(){
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(containerOfModule(), "Save file", FileDialog.SAVE);
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setVisible(true);
+		String s = fdlg.getDirectory() + fdlg.getFile();
+		// fdlg.dispose();
+		MainThread.decrementSuppressWaitWindow();
+		return s;
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void saveLinkagesAs(String pathName){
+		MesquiteMessage.warnProgrammer("Oops: saving linkages not yet working");
+		//writes Nexus file with Mesquite script requesting all linked files to be opened
+		// needs home file and other files in order.
+		//(NEED vector of files)
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void saveAllFiles(){
+		if (getProject() ==null)
+			return;
+		Enumeration enumeration=getProject().getFiles().elements();
+		MesquiteFile fi;
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			if (obj instanceof MesquiteFile) {
+				fi = (MesquiteFile)obj;
+				if (fi.isLocal())
+					writeFile(fi);
+				else
+					MesquiteMessage.notifyUser("File \"" + fi.getName() + "\" cannot be written because it was accessed as a URL");
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public boolean closeFile(MesquiteFile fi){
+		if (getProject() ==null)
+			return false;
+		if (fi!=null) {
+			if (getProject().getHomeFile() == fi) { //should ask for all files
+				if (MesquiteThread.isScripting() || !getProject().isDirty()) {
+					waitWriting(null);
+					logln("Closing " + getProject().getName());
+					getProject().isDoomed = true;
+					iQuit();
+				}
+				else {
+					fileCloseRequested();
+					ListableVector files = getProject().getFiles();
+					if (files != null){
+
+						Enumeration enumeration=files.elements();
+						if (enumeration != null){
+							MesquiteFile fiP;
+							while (enumeration.hasMoreElements()){
+								Object obj = enumeration.nextElement();
+								if (obj instanceof MesquiteFile) {
+									fiP = (MesquiteFile)obj;
+
+									if (fiP!=null && fiP.isDirty() && fiP.isLocal()) {
+										String message = "Do you want to save changes to \"" + fiP.getName() + "\" before closing?";
+										int q = AlertDialog.query(containerOfModule(), "Save changes?",  message, "Save", "Cancel", "Don't Save");
+										if (q==0) {
+											logln("Writing " + fiP.getName());
+											writeFile(fiP);
+										}
+										else if (q==1) {
+											logln("File close cancelled by user");
+											return false;
+										}
+									}
+								}
+							}
+						}
+					}
+					logln("Closing " + getProject().getName());
+					iQuit();
+				}
+			}
+			else {
+				if (MesquiteThread.isScripting() || !fi.isDirty()) {
+					waitWriting(fi);
+					fi.close();
+				}
+				else if (fi.isLocal()){
+					fileCloseRequested();
+					String message = "Do you want to save changes to \"" + fi.getName() + "\" before closing?";
+					int q = AlertDialog.query(containerOfModule(), "Save changes?",  message, "Save", "Cancel", "Don't Save");
+					if (q==0) 
+						writeFile(fi);
+					else if (q==1) {
+						logln("File close cancelled by user");
+						return false;
+					}
+					logln("Closing file " + fi.getName());
+					fi.close();
+				}
+			}
+		}
+		return true;
+	}
+	private void waitWriting(MesquiteFile f){
+		try {
+			boolean done = false;
+			while (!done){
+				if (f == null) {
+					done = true;
+					ListableVector files = getProject().getFiles();
+					for (int i=0; i<files.size(); i++){
+						if (((MesquiteFile)files.elementAt(i)).isWriting())
+							done = false;
+					}
+				}
+				else
+					done = !f.isWriting();
+				if (!done)
+					Thread.sleep(50);
+			}
+		}
+		catch (InterruptedException e){
+		}
+	}
+	/*.................................................................................................................*/
+	public void revertToSaved(boolean queryIfDirty){
+		boolean siga = false;
+		if (!queryIfDirty)
+			siga = true;
+		else if (!MesquiteThread.isScripting()){
+			if (getProject() == null || getProject().getHomeFile() == null)
+				siga = false;
+			else if (getProject().isDirty()){
+				if (getProject().getNumberLinkedFiles()>1){
+					String hfn = getProject().getHomeFileName();
+					siga = AlertDialog.query(containerOfModule(), "Discard unsaved changes?", "Do you want to discard all unsaved changes in all linked files and revert to the saved version of the home file (" + hfn + ")?", "Discard Changes", "Cancel");
+				}
+				else
+					siga = AlertDialog.query(containerOfModule(), "Discard unsaved changes?", "Do you want to discard all unsaved changes and revert to the saved version of the file?", "Discard Changes", "Cancel");
+			}
+			else
+				siga = true;
+		}
+		if (siga){
+			MesquiteTrunk.mesquiteTrunk.openFile(getProject().getHomeFile().getPath());
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void closeFile(int id){
+		MesquiteFile fi = getProject().getFileByID(id);
+		closeFile(fi);
+	}
+	public void closeFile(String id){
+		if (getProject() == null)
+			return;
+		MesquiteFile fi = getProject().getFile(id);
+		closeFile(fi);
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public boolean export(FileInterpreterI exporter, MesquiteFile file, String arguments){
+		if (exporter!=null){
+			MainThread.incrementSuppressWaitWindow();
+			boolean success = exporter.exportFile(file, arguments); 
+			MainThread.decrementSuppressWaitWindow();
+			return success;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void saveFile(int id){
+		if (getProject() ==null)
+			return;
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFile fi;
+		if (!MesquiteInteger.isCombinable(id) && getProject().getNumberLinkedFiles()==1)
+			fi = getProject().getHomeFile();
+		else
+			fi = getProject().getFileByID(id);
+		if (fi != null) { 
+			saveFile(fi);
+
+		}
+		else 
+			MesquiteMessage.notifyUser("Request to save file id#" + MesquiteInteger.toString(id)+ "; file not found");
+		MainThread.decrementSuppressWaitWindow();
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void saveFile(MesquiteFile fi){
+		if (getProject() ==null)
+			return;
+		getProject().incrementProjectWindowSuppression();
+		MainThread.incrementSuppressWaitWindow();
+		if (fi != null) { 
+			if (fi.isLocal()){
+				writeFile(fi);
+				if (!MesquiteThread.isScripting())
+					MesquiteWindow.repaintAllWindows();
+			}
+			else
+				MesquiteMessage.notifyUser("File \"" + fi.getName() + "\" cannot be written because it was accessed as a URL");
+		}
+		MainThread.decrementSuppressWaitWindow();
+		getProject().decrementProjectWindowSuppression();
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void saveFileAs(int id){
+		if (getProject() ==null)
+			return;
+		getProject().incrementProjectWindowSuppression();
+		MesquiteFile fi;
+		if (!MesquiteInteger.isCombinable(id) && getProject().getNumberLinkedFiles()==1)
+			fi = getProject().getHomeFile();
+		else
+			fi = getProject().getFileByID(id);
+		saveFileAs(fi);
+		getProject().decrementProjectWindowSuppression();
+	}
+	public void saveFileAs(MesquiteFile fi){
+		getProject().incrementProjectWindowSuppression();
+		MainThread.incrementSuppressWaitWindow();
+		if (fi !=null){
+			/*if (!fi.isLocal())
+				MesquiteMessage.notifyUser("File \"" + fi.getName() + "\" cannot be written because it was accessed as a URL");
+			else */
+			if (fi.changeLocation("Save file")) {
+				fi.setWriteProtected(false);
+				writeFile(fi);
+			}
+		}
+		//TODO: change titles of windows and menu items!!!
+		MainThread.decrementSuppressWaitWindow();
+		getProject().decrementProjectWindowSuppression();
+	}
+	public void renameAndSaveFile(int id, String name){
+		if (StringUtil.blank(name))
+			return;
+		getProject().incrementProjectWindowSuppression();
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFile fi;
+		if (!MesquiteInteger.isCombinable(id) && getProject().getNumberLinkedFiles()==1)
+			fi = getProject().getHomeFile();
+		else
+			fi = getProject().getFileByID(id);
+		if (fi !=null){
+			fi.changeLocation(fi.getDirectoryName(), name);
+			fi.setWriteProtected(false);
+			writeFile(fi);
+		}
+		MainThread.decrementSuppressWaitWindow();
+		getProject().decrementProjectWindowSuppression();
+	}
+	/*.................................................................................................................*/
+	/*  */
+	public void writeFile(MesquiteFile nMF){
+		if (!MesquiteThread.isScripting() && nMF.getDirectoryName() == null){
+			nMF.changeLocation("Save file");
+		}
+		broadcastFileAboutToBeSaved(this, nMF);
+		Runtime rt = Runtime.getRuntime();
+		rt.gc();
+
+		NexusFileInterpreter nfi = (NexusFileInterpreter)findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+		if (nfi!=null) {
+			nfi.writeFile(getProject(), nMF);
+		}
+		else 
+			MesquiteMessage.println("File interpreter not found to write file " + nMF.getName());
+	}
+	/*.................................................................................................................*/
+	/** Finds the first employee in the heirarchy that manages a particular subclass of FileElement */
+	public ElementManager findManager(MesquiteModule m, Class fileElementClass) {
+		if (fileElementClass == null)
+			return null;
+		ElementManager r = findExactManager(m, fileElementClass);
+		if (r!=null)
+			return r;
+		else
+			return findCapableManager(m, fileElementClass);
+	}
+	/*.................................................................................................................*/
+	/** Finds the first employee in the heirarchy that manages a particular subclass of FileElement */
+	private ElementManager findExactManager(MesquiteModule m, Class fileElementClass) {
+		if (m instanceof ElementManager) {
+			ElementManager fEM = (ElementManager)m;
+			if (fEM!=null){
+				Class eC = fEM.getElementClass();
+				if (eC != null && eC ==fileElementClass) {  //manager must handle fileElementClass or its superclasses
+					return fEM;
+				}
+			}
+		}
+		EmployeeVector ev = m.getEmployeeVector();
+		if (ev==null)
+			return null;
+		Enumeration enumeration=ev.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			ElementManager fEM = findExactManager(mb, fileElementClass);
+			if (fEM != null)
+				return fEM;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Finds the first employee in the heirarchy that manages a particular subclass of FileElement */
+	public ElementManager findCapableManager(MesquiteModule m, Class fileElementClass) {
+		if (m instanceof ElementManager) {
+			ElementManager fEM = (ElementManager)m;
+			if (fEM != null) {
+				Class eC = fEM.getElementClass();
+				if (eC != null && eC.isAssignableFrom(fileElementClass)) {  //manager must handle fileElementClass or its superclasses
+					return fEM;
+				}
+			}
+		}
+		EmployeeVector ev =m.getEmployeeVector();
+		if (ev == null)
+			return null;
+		Enumeration enumeration=ev.elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			ElementManager fEM = findCapableManager(mb, fileElementClass);
+			if (fEM != null)
+				return fEM;
+		}
+		return null;
+	}
+	private String findImporterName(String arguments){  //hackathon
+		String fRA = parser.getFirstToken(arguments); //path
+		fRA = parser.getNextToken(); //extra arguments
+
+		while (!StringUtil.blank(fRA)) {
+			if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + "interpreter")) {
+				parser.getNextToken(); //eating up =
+				return parser.getNextToken();
+			}
+			fRA = parser.getNextToken();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public FileInterpreter findImporter(String fileContents, String fileName, int fileType, String arguments,boolean mustReadFromString, Class stateClass) {
+		//hackathon
+		String importerName = findImporterName(arguments);
+		if (importerName != null){
+			MesquiteModule mb= findEmployeeWithName( importerName, true);
+			if (mb instanceof FileInterpreterI){
+				FileInterpreterI importer = (FileInterpreterI)mb;
+				if (importer.canImport(arguments))
+					return importer;
+			}
+		}
+
+		TextDisplayer fd = displayText(fileContents, fileName);  //TODO: should say if scripting
+
+		MesquiteModule[] fInterpreters = null;
+		if (fileType == 0)
+			fInterpreters = getImmediateEmployeesWithDuty(FileInterpreterI.class);
+		else
+			fInterpreters = getImmediateEmployeesWithDuty(FileInterpreterITree.class);
+		if (fInterpreters==null)
+			return null;
+		int count = 0;
+		for (int i=0; i<fInterpreters.length; i++){
+			boolean stateOK = (stateClass==null || ((FileInterpreterI)fInterpreters[i]).canImport(stateClass));
+			if (((FileInterpreterI)fInterpreters[i]).canImport(arguments) && (fInterpreters[i] instanceof ReadFileFromString || !mustReadFromString) && stateOK)
+				count++;
+		}
+		if (count == 0 ){
+			if (fd!=null)
+				fireEmployee(fd);
+			return null;
+		}
+		MesquiteModule[] fInterpretersCanImport = new MesquiteModule[count];
+		count = 0;
+		for (int i=0; i<fInterpreters.length; i++){
+			boolean stateOK = (stateClass==null || ((FileInterpreterI)fInterpreters[i]).canImport(stateClass));
+			if (((FileInterpreterI)fInterpreters[i]).canImport(arguments) && (fInterpreters[i] instanceof ReadFileFromString || !mustReadFromString) && stateOK)
+				fInterpretersCanImport[count++] = fInterpreters[i];
+		}
+		fInterpretersCanImport = prioritize(fInterpretersCanImport, FileInterpreterI.class);
+		boolean fuse = parser.hasFileReadingArgument(arguments, "fuseTaxaCharBlocks");
+		String message = "Please choose an interpreter for this file";
+		if (fuse)
+			message += "\n(Only some file formats are supported, because this is a special merging operation)";
+		Listable fInt = ListDialog.queryList(fd.containerOfModule(), "Translate File", message, MesquiteString.helpString,fInterpretersCanImport, 0);
+
+		if (fInt instanceof FileInterpreterI && !MesquiteThread.isScripting())
+			((FileInterpreterI)fInt).getImportOptions(fuse);
+
+		if (fd!=null)
+			fireEmployee(fd);
+		return (FileInterpreter)fInt;
+	}
+	/*.................................................................................................................*/
+	public FileInterpreter findImporter(MesquiteFile f, int fileType, String arguments) {
+		String s = MesquiteFile.getFileContentsAsString(f.getPath(), 4000); 
+		if (StringUtil.blank(s))
+			return null;
+		return findImporter(s,f.getName(),fileType, arguments, false, null);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getIDSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		Snapshot fromProject = getProject().getSnapshot(file);
+		if (fromProject != null && fromProject.getNumLines() > 0) {
+			temp.addLine("getProject");
+			temp.addLine("tell It");
+			temp.incorporate(fromProject, true);
+			temp.addLine("endTell");
+		}
+		temp.addLine("timeSaved " + System.currentTimeMillis());
+		ListableVector files = getProject().getFiles();
+		for (int i = 0; i<files.size(); i++) {
+			MesquiteFile e=(MesquiteFile)files.elementAt(i);
+			if (e!=getProject().getHomeFile())
+				temp.addLine("linkFile " + StringUtil.tokenize(MesquiteFile.decomposePath(getProject().getHomeFile().getDirectoryName(), e.getPath())));  //quote //todo: should parse name relative to path to home file!!!!!
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		/*
+   	 	ListableVector files = getProject().getFiles();
+		for (int i = 0; i<files.size(); i++) {
+			MesquiteFile e=(MesquiteFile)files.elementAt(i);
+			if (e!=getProject().getHomeFile())
+				temp.addLine("linkFile " + StringUtil.tokenize(e.getName()));  //quote //todo: should parse name relative to path to home file!!!!!
+
+		}
+		 */
+		if (pw != null){
+			temp.addLine("getWindow");
+			temp.addLine("tell It");
+			temp.incorporate(pw.getSnapshot(file), true);
+			temp.addLine("endTell");
+
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (!(e instanceof FileAssistant)) {
+				temp.addLineIfAnythingToTell("getEmployee " , ((MesquiteModule)e));  //addLineIfAnythingToTell
+			}
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof FileAssistant) {
+				temp.addLine("newAssistant " , ((MesquiteModule)e)); 
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void showInitTreeWindow(Taxa taxa, boolean force){
+		MesquiteModule btwc = findEmployeeWithName("#BasicTreeWindowCoord", true);
+		if (btwc !=null) {
+			Commandable c = (Commandable)btwc.doCommand("makeTreeWindow","#" + taxa.getAssignedID(), CommandChecker.defaultChecker); 
+			if (c!=null) {
+				if (force)
+					c.doCommand("showWindowForce",null, CommandChecker.defaultChecker);
+				else c.doCommand("showWindow",null, CommandChecker.defaultChecker);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** these are the commands that shouldn't dirty the file */
+	public void fileDirtiedByCommand(MesquiteCommand command){
+		if (command !=null && command.getOwner() == this) {
+			if ("saveFiles".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("saveFile".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("saveFileAs".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("saveLinkagesAs".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("showFileOnDisk".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("closeFile".equalsIgnoreCase(command.getName()))
+				return;
+			else if ("closeProject".equalsIgnoreCase(command.getName()))
+				return;
+		}
+		super.fileDirtiedByCommand(command);
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	private String filterIfMarkedArgument(String s){
+		if (s == null || s.length() <1 || s.charAt(0) == StringUtil.argumentMarker)
+			return null;
+		return s;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the total number of character data matrices stored in the project", null, commandName, "getNumberOfDataSets")) {
+			return (new MesquiteInteger(getProject().getNumberCharMatrices()));
+		}
+		else if (checker.compare(this.getClass(), "Returns a vector of the character data matrices stored in the project", null, commandName, "getDataSets")) {
+			return (getProject().getCharacterMatrices());
+		}
+		else if (checker.compare(this.getClass(), "Sets the home file of the project so it is write protected", null, commandName, "writeProtect")) { //TODO: should use arguments to toggle
+			getProject().getHomeFile().setWriteProtected(true);
+		}
+		else if (checker.compare(this.getClass(), "Returns the number of sets of taxa stored in the project", null, commandName, "getNumberOfTaxas")) {
+			MesquiteInteger mi = new MesquiteInteger(getProject().getNumberTaxas());
+			return (mi);
+		}
+		else if (checker.compare(this.getClass(),  "Returns a vector of the sets of taxa stored in the project", null, commandName, "getTaxas")) {
+			return (getProject().getTaxas());
+		}
+		//TODO: getTaxa(id), getDataSet(id)
+		else if (checker.compare(this.getClass(), "Returns a character model stored in the project", "[name of character model", commandName, "getCharacterModel")) {
+			return getProject().getCharacterModel(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Reads from the file the time the file was last saved (used in IDSnapshot)", "[time in milliseconds]", commandName, "timeSaved")) {
+			long time = MesquiteLong.fromString(arguments);
+			if (MesquiteLong.isCombinable(time))
+				getProject().timePreviouslySavedAsRecorded = time;
+			double diff = Math.abs(getProject().timePreviouslySavedAsRecorded - getProject().timePreviouslySavedByFile)/1000.0;
+		}
+		else if (checker.compare(this.getClass(), "Reads a file as linked to a current file, so that they can share information, with an explanation as to what link is for, for error reporting", "[fileDescriptionText][path to file][importer]", commandName, "linkFileExp")) {
+			String fileDescriptionText = parser.getFirstToken(arguments);
+			String path = filterIfMarkedArgument(parser.getNextToken());
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			return readLinkedFile(path, importer, arguments, 0, fileDescriptionText);
+		}
+		else if (checker.compare(this.getClass(), "Reads a file as linked to a current file, so that they can share information", "[path to file][importer][failureText]", commandName, "linkFile")) {
+			String path = filterIfMarkedArgument(parser.getFirstToken(arguments));
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			return readLinkedFile(path, importer, arguments, 0, null);
+		}
+		else if (checker.compare(this.getClass(), "Reads a file at a URL as linked to a current file, so that they can share information", "[URL]", commandName, "linkURL")) {
+			MesquiteMessage.notifyUser("Sorry, can't yet read a linked URL");
+			//	return (readLinkedURL(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Reads a file and incorporates all of its information into the home file of the current project", "[path to file]", commandName, "includeFile")) {
+			String path = filterIfMarkedArgument(parser.getFirstToken(arguments));
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			includeFile(path, importer, arguments, 0, null);
+		}
+		else if (checker.compare(this.getClass(), "Reads a file and incorporates all of its information into the home file of the current project", "[path to file]", commandName, "includeFileFuse")) {
+			String path = filterIfMarkedArgument(parser.getFirstToken(arguments));
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			includeFileFuse(path, importer, arguments, 0, null);
+		}
+		else if (checker.compare(this.getClass(), "Reverts to saved by closing ALL files without saving then opening the home file of project", null, commandName, "revert")) {
+			revertToSaved(true);
+		}
+		else if (checker.compare(this.getClass(), "Opens a NEXUS file and returns it for reading", "[path to file]", commandName, "getNEXUSFileForReading")) {
+			return getNEXUSFileForReading(arguments, "Choose file to open");
+		}
+		else if (checker.compare(this.getClass(), "Opens a NEXUS file and returns the first block of a given type", "[block type][path to file]", commandName, "getNEXUSFileBlock")) {
+			String blockType = parser.getFirstToken(arguments); //required argument
+			String path = parser.getNextToken();//optional argument
+
+			return getNEXUSBlock(blockType, path);
+		}
+		else if (checker.compare(this.getClass(), "Reads a file at a URL and incorporates all of its information into the home file of the current project", "[URL]", commandName, "includeURL")) {
+			MesquiteMessage.notifyUser("Sorry, can't yet include a URL");
+			//	return (readLinkedURL(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Reads a tree file as linked to a current file, so that they can share information", "[path to file]", commandName, "linkTreeFile")) {
+			String path = filterIfMarkedArgument(parser.getFirstToken(arguments));
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			String failureText = parser.getNextToken();
+			return (readLinkedFile(path, importer, arguments, 1, failureText));
+		}
+		else if (checker.compare(this.getClass(), "Reads a tree file and incorporates all of its information into the home file of the current project", "[path to file]", commandName, "includeTreeFile")) {
+			String path = filterIfMarkedArgument(parser.getFirstToken(arguments));
+			String importer = filterIfMarkedArgument(parser.getNextToken());
+			String failureText = parser.getNextToken();
+			includeFile(path, importer, arguments, 1, failureText);
+		}
+		else if (checker.compare(this.getClass(), "Create a new linked file", "[path to file]", commandName, "newLinkedFile")) {
+			MesquiteFile file = (newLinkedFile(parser.getFirstToken(arguments)));
+			return file;
+		}
+		else if (checker.compare(this.getClass(), "Brings a current chart window to the fore", "[number of chart window]", commandName, "showChart")) {
+			pos.setValue(0);
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if ((which == 0 || MesquiteInteger.isPositive(which))) {
+				ListableVector ws = MesquiteTrunk.windowVector;
+				int count = 0;
+				for (int i=0; i<ws.size(); i++) {
+					Object obj = ws.elementAt(i);
+					if (obj instanceof ChartWindow){
+						if (which == count) {
+							((ChartWindow)obj).show();
+							return obj;
+						}
+						count++;
+					}
+				}
+			}
+			return null;
+
+		}
+		else if (checker.compare(this.getClass(), "Returns a reference to the file assistant module", "[name of module]", commandName, "getAssistant")) {
+			MesquiteModule mb = findEmployeeWithName(parser.getFirstToken(arguments), true);
+			return mb;
+		}
+		else if (checker.compare(this.getClass(), "Brings up the chart wizard", null, commandName, "chartWizard")) {
+
+			if (!MesquiteThread.isScripting()) {
+				showChartWizard(null);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Hires new file assistant module", "[name of module]", commandName, "newAssistant")) {
+			return (FileAssistant)hireNamedEmployee(FileAssistant.class, arguments);
+		}
+		else if (checker.compare(this.getClass(), "Save all files in project", null, commandName, "saveFiles")) {  //all files in project
+			String fileNames ="";
+			if (proj == null)
+				return null;
+			for (int i = 0; i< proj.getNumberLinkedFiles(); i++){
+				if (proj.getFile(i) != null)
+					fileNames += "\n\n   " + proj.getFile(i).getFileName();
+			}
+			if (MesquiteThread.isScripting() || AlertDialog.query(containerOfModule(), "Save All Files?", "Do you want to save all of the following files?" + fileNames + "\n\n(If you want to save only one, go to the submenu of the File menu.)"))
+				saveAllFiles();
+		}
+		else if (checker.compare(this.getClass(), "Saves file", "[number of file]", commandName, "saveFile")) {  //Single file only
+			saveFile(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Saves home file", "[number of file]", commandName, "saveHomeFile")) {  //Single file only
+			saveFile((int)getProject().getHomeFile().getID());
+		}
+		else if (checker.compare(this.getClass(), "Renames file", "[number of file]", commandName, "renameAndSaveFile")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int i = MesquiteInteger.fromString(arguments, pos);
+			String name = ParseUtil.getToken(arguments, pos);
+			renameAndSaveFile(i, name);
+		}
+		else if (checker.compare(this.getClass(), "Saves file as... to create a separate copy", "[number of file]", commandName, "saveFileAs")) {
+			saveFileAs(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Gives information about the project", null, commandName, "getInfo")) {
+			String st = "This represents a project, which currently represents information from ";
+			if (proj.getNumberLinkedFiles() == 1) {
+				st = "The current file is " + proj.getHomeFileName();
+				if (!StringUtil.blank(proj.getHomeDirectoryName()))
+					st += ", located at " + proj.getHomeDirectoryName() + ".";
+			}
+			else {
+				st = "The current project includes " + proj.getNumberLinkedFiles() + " files.  The home file of the project is " + proj.getHomeFileName();
+				if (!StringUtil.blank(proj.getHomeDirectoryName()))
+					st += ", located at " + proj.getHomeDirectoryName() + ".";
+				String[] s = proj.getFiles().getStrings();
+
+
+				st += "\n\nThe other files linked in the project are:\n";
+				for (int i=1; i<s.length; i++)
+					st += "     " + s[i] + "\n";
+			}
+			alert(st);
+		}
+		else if (checker.compare(this.getClass(), "Exports information to another format", null, commandName, "export")) {
+			String exporterName = parser.getFirstToken(arguments);
+			if (getProject() == null)
+				return null;
+			//which file?
+			MesquiteFile file =null;
+			int id = MesquiteInteger.fromString(parser.getNextToken());
+			if (MesquiteInteger.isCombinable(id) && getProject().getNumberLinkedFiles()>1)
+				file = getProject().getFileByID(id);
+			else
+				file = getProject().getHomeFile();
+			if (file == null)
+				return null;
+			FileInterpreterI exporter = (FileInterpreterI)findEmployeeWithName(exporterName);
+			if (exporter == null){
+				MesquiteModule[] fInterpreters = getImmediateEmployeesWithDuty(FileInterpreterI.class);
+				if (fInterpreters==null)
+					return null;
+				int count = 0;
+				for (int i=0; i<fInterpreters.length; i++){
+					try {
+						if (((FileInterpreterI)fInterpreters[i]).canExportProject(getProject()))
+							count++;
+					}
+					catch (Exception e){
+					}
+				}
+				if (count == 0){
+					discreetAlert( "Sorry, there are no exporters available that can handle the data types in this project.");
+					return null;
+				}
+				MesquiteModule[] fInterpretersCanExport = new MesquiteModule[count];
+				count = 0;
+				for (int i=0; i<fInterpreters.length; i++){
+					try {
+						if (((FileInterpreterI)fInterpreters[i]).canExportProject(getProject()))
+							fInterpretersCanExport[count++] = fInterpreters[i];
+					}
+					catch (Exception e){
+					}
+				}
+				//prioritize list
+				fInterpretersCanExport = prioritize(fInterpretersCanExport, FileInterpreterI.class);
+
+				exporter = (FileInterpreterI)ListDialog.queryList(containerOfModule(), "Export format", "Export part or all of the information as a file of the following format",MesquiteString.helpString, fInterpretersCanExport, 0);
+			}
+			export(exporter, file, arguments);
+		}
+		else if (checker.compare(this.getClass(), "NOT FUNCTIONING", null, commandName, "saveLinkagesAs")) {
+			saveLinkagesAs(parser.getFirstToken(arguments));
+			//writeFile(false, null);
+		}
+		else if (checker.compare(this.getClass(), "Closes file", "[number of file]", commandName, "closeFile")) {
+			closeFile(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+		}
+		else if (checker.compare(this.getClass(), "Closes all tabs", null, commandName, "closeAllWindows")) {
+			int safetyNet = 0;
+			while (safetyNet < 50 && closeEmployeeWindows(this))
+				safetyNet++;
+		}
+		else if (checker.compare(this.getClass(), "Show file on disk", "[number of file]", commandName, "showFileOnDisk")) {
+			if (getProject() == null)
+				return null;
+			String path = "";
+			int id = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			MesquiteFile fi = getProject().getFileByID(id);
+			if (fi == null && getProject().getNumberLinkedFiles()==1)
+				fi = getProject().getHomeFile();
+			if (fi != null) {
+				if (fi.isLocal()) {
+					path = fi.getDirectoryName();
+					MesquiteFile.showDirectory(path);
+					return null;
+				}
+				else if (fi.getURL()!= null){
+					
+					path = fi.getURL().toString();
+					showWebPage(path, false);
+					return null;
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes file", "[name of file]", commandName, "closeFileByName")) {
+			//query...
+			closeFile(arguments);
+		}
+		else if (checker.compare(this.getClass(), "Closes this project (which may consist of a single open file)", null, commandName, "closeProject")) {
+			MesquiteProject p=getProject();
+			if (MesquiteThread.isScripting()){
+				if (p != null)
+					p.developing = false; //so that project closes!
+			}
+			if (p != null)
+				closeFile(p.getHomeFile());
+			if (!MesquiteThread.isScripting() && MesquiteTrunk.getProjectList().getNumProjects()==0){
+				MesquiteWindow w = MesquiteTrunk.mesquiteTrunk.getModuleWindow();
+				if (w!=null)
+					w.setVisible(true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns path to this project", null, commandName, "getPathToProject")) {
+			return getProject().getHomeDirectoryName();
+		}
+		else if (checker.compare(this.getClass(), "Returns name of home file of this project", null, commandName, "getHomeFileName")) {
+			return getProject().getHomeFileName();
+		}
+		else if (checker.compare(this.getClass(), "Returns this project", null, commandName, "getProject")) {
+			return getProject();
+		}
+		else if (checker.compare(this.getClass(), "Returns identification number of this project", null, commandName, "getProjectID")) {
+			return new MesquiteInteger((int)getProject().getID());
+		}
+		else if (checker.compare(this.getClass(), "Brings all of the windows belonging to the project to the front.", null, commandName, "allToFront")) {
+			Enumeration e = MesquiteTrunk.mesquiteTrunk.windowVector.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				if (mw.isVisible() && mw.getOwnerModule()!=null && mw.getOwnerModule().getProject()== getProject())
+					mw.getParentFrame().toFront();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Not used; placed here to suppress warning that command \"end\" from Mesquite block not handled", null, commandName, "end")) { //this is end of MesquiteBlock; placed here to suppress warning that command not handled
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	void showChartWizard(String targetName){
+		int availableChartTypes = 0;
+		if (targetName != null){
+			MesquiteModuleInfo mb = null;
+			while ((mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCH.class, mb, null, null, this)) != null) {
+				if (targetName.equalsIgnoreCase(mb.getNameForMenuItem()))
+					availableChartTypes += 1;
+			}
+			mb = null;
+			while ((mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCS.class, mb, null, null, this)) != null){
+				if (targetName.equalsIgnoreCase(mb.getNameForMenuItem()))
+					availableChartTypes += 4;
+			}
+		}
+		else {
+			String explanation = "<h3>Entities?</h3>First, each <strong>data point</strong> of your chart refers to an <strong>entity</strong>.  For example, each data point might represent a <strong>character</strong>, and tells us a particular value for the character."
+				+ " Alternatively, the data points could refer to <strong>matrices</strong>, or <strong>taxa</strong>, or <strong>trees</strong>.  Thus, your chart will summarize values that apply to each of a series of different entities.  "
+				+ "(This could seem confusing, because some data points refer to both a character and a tree, for example.  However, if the chart shows a value for a character in each of multiple trees, "
+				+"then you want a Trees chart.  If it shows a value for each of many characters with a single tree, then you want a Characters chart.)";
+			String question = "What are the entities to which the data points of this chart refer?";
+			//
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Chart Wizard: Entities",  buttonPressed);
+			//dialog.addLargeTextLabel(explanation);
+			//dialog.addBlankLine();
+			dialog.appendToHelpString(explanation);
+			dialog.addLabel(question);
+
+			Vector v = new Vector();
+			Vector vW = new Vector();
+			MesquiteModuleInfo mb = null;
+			while ((mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCH.class, mb, null, null, this)) != null) {
+				v.addElement(mb.getNameForMenuItem());
+				vW.addElement(new MesquiteInteger(1));
+			}
+			mb = null;
+			while ((mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCS.class, mb, null, null, this)) != null){
+				String s = mb.getNameForMenuItem();
+				int inS = v.indexOf(s);
+				if (inS<0) {
+					v.addElement(s);
+					vW.addElement(new MesquiteInteger(4));
+				}
+				else if (inS < vW.size()) {
+					MesquiteInteger mi = (MesquiteInteger)vW.elementAt(inS);
+					mi.add(4); //will have value 5, there do both
+				}
+			}
+			/*
+			 * 	while ((mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCP.class, mb, null, null, this)) != null){
+			String s = mb.getNameForMenuItem();
+			if (v.indexOf(s)<0)
+				v.addElement(s);
+		}*/
+			dialog.addBlankLine();
+			String[] labels = new String[v.size()];
+			for (int i = 0; i<v.size(); i++)
+				labels[i] = (String)v.elementAt(i);
+			RadioButtons radio = dialog.addRadioButtons(labels, 0);
+			dialog.addBlankLine();
+
+			dialog.completeAndShowDialog(true);
+
+			boolean ok = (dialog.query()==0);
+			if (radio.getValue() < v.size() && radio.getValue() < vW.size()){
+				if (ok)
+					targetName = (String)v.elementAt(radio.getValue());
+				MesquiteInteger chartTypeAvailable = (MesquiteInteger)vW.elementAt(radio.getValue());
+				availableChartTypes = chartTypeAvailable.getValue();
+			}
+		}
+		if (!StringUtil.blank(targetName)) {
+			int whichChart = -1;
+			if (availableChartTypes== 1)//only histogram
+				whichChart = 0;
+			else if (availableChartTypes == 4)//only scattergram
+				whichChart = 1;
+			else {
+
+				String explanation2 = "<h3>One or Two Dimensions?</h3>Second, your chart could display a <strong>single variable</strong> (among multiple entities) or the relationship between <strong>two variables</strong>.  A one-variable chart will be a histogram/bar chart/line chart."
+					+" A two-variable chart will be a scatterplot or scattergram.";
+				String question2 = "Do you want a one-variable or two-variable chart?";
+				MesquiteInteger buttonPressed = new MesquiteInteger(1);
+				ExtensibleDialog dialog2 = new ExtensibleDialog(containerOfModule(), "Chart Wizard: Dimensions",  buttonPressed);
+				//dialog2.addLargeTextLabel(explanation2);
+				dialog2.appendToHelpString(explanation2);
+				dialog2.addLabel(question2);
+				dialog2.addBlankLine();
+				RadioButtons radio2 = dialog2.addRadioButtons(new String[]{"One (Bar chart, line chart, histogram)", "Two (Scattergram)"}, 0);
+				dialog2.addBlankLine();
+				dialog2.completeAndShowDialog(true);
+				boolean ok = (dialog2.query()==0);
+				if (ok)
+					whichChart = radio2.getValue();
+			}
+			if (whichChart >=0){
+				MesquiteModuleInfo mb = null;
+				mb = null;
+				String hireName = null;
+				if (whichChart == 0){
+					while (hireName == null && (mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCH.class, mb, null, null, this)) != null) 
+						if (mb.getNameForMenuItem().equalsIgnoreCase(targetName)){
+							hireName = "#" + mb.getClassName();
+
+						}
+				}
+				else {
+					while (hireName == null && (mb = MesquiteTrunk.mesquiteModulesInfoVector.findNextModule (FileAssistantCS.class, mb, null, null, this)) != null) 
+						if (mb.getNameForMenuItem().equalsIgnoreCase(targetName)){
+							hireName = "#" + mb.getClassName();
+						}
+				}
+				doCommand("newAssistant", hireName, CommandChecker.defaultChecker); 
+			}
+		}
+
+
+
+	}
+	/*.................................................................................................................*/
+	/**Returns command to hire employee if clonable*/
+	public String getClonableEmployeeCommand(MesquiteModule employee){
+		if (employee!=null && employee.getEmployer()==this) {
+			if (employee.getHiredAs()==FileAssistant.class)
+				return ("newAssistant " + StringUtil.tokenize(employee.getName()) + ";"); //quote
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		String s =""; 
+		if (getProject()!=null) 
+			s += "Project name: " + getProject().getName();
+		return s;
+	}
+	/*.................................................................................................................*/
+	/** Returns the URL of document shown when splash screen icon touched. By default, returns path to module's manual*/
+	public String getSplashURL(){
+		return null; //return getPath() + "index.html"; 
+	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+		return true; 
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+	public String getPackageName(){
+		return "Basic Mesquite Package";
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getPackageVersion() {
+		return null;//this causes defult Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	public String getPackageAuthors() {
+		return null; //this causes defult Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	public String getPackageDateReleased() {
+		return null; //this causes defult Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+	public String getPackageCitation(){
+		return null;//this causes default Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns version for a package of modules as an integer*/
+	public int getPackageVersionInt(){
+		return 0;//this causes default Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns build number for a package of modules as an integer*/
+	public int getPackageBuildNumber(){
+		return 0;//this causes default Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns the URL for the web page about the package*/
+	public String getPackageURL(){
+		return null;//this causes default Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns the integer version of Mesquite for which this package was first released*/
+	public int getVersionOfFirstRelease(){
+		return 0;//this causes default Mesquite info to be used
+	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Requests a window to close.  In the process, subclasses of MesquiteWindow might close down their owning MesquiteModules etc.*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		//Debug.println("disposing of window");
+		whichWindow.hide();
+		//whichWindow.dispose();
+	}
+
+	public boolean getHideable(){
+		return false;
+	}
+
+}
+
+/*======================================================================== */
+
+/* ======================================================================== */
+class FileRead implements CommandRecordHolder, Runnable {
+	String arguments, path;
+	CommandRecord comRec;
+	BasicFileCoordinator ownerModule;
+	ObjectContainer f;
+	String importer;
+	int category;
+	int fileType;
+		String fileDescriptionText = null;
+		public FileRead (String path, String importer, String arguments, int fileType,  BasicFileCoordinator ownerModule, int category, ObjectContainer f, String filePurposeText) {
+		this.f = f;
+		this.arguments = arguments;
+		this.path = path;
+		this.comRec =  MesquiteThread.getCurrentCommandRecord();
+		this.fileDescriptionText = filePurposeText;
+
+		this.ownerModule = ownerModule;
+		this.category = category;
+		this.importer = importer;
+		this.fileType = fileType;
+		//setCurrent(1);
+	}
+	/*
+	public MesquiteFile getFile(){
+	 	return linkedFile;
+	}
+	 */
+	public CommandRecord getCommandRecord(){
+
+		return comRec;
+	}
+	public void setCommandRecord(CommandRecord c){
+
+		comRec = c;
+	}
+	public String getCurrentCommandName(){
+		return "Reading file";
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	
+	private void warnLinkedNotFound(String pathName){
+		String warning = "";
+		if (fileDescriptionText != null){
+			warning = fileDescriptionText + " cannot be found. The file was expected by a script to be at the location \"" + pathName + "\". " +
+						"Because this file cannot be found, the remainder of the script might not execute properly, and various warning messages might be given.";
+		}
+		else
+			warning = "A script refers to a linked file \"" + pathName + "\" that cannot be found. Because this linked file cannot be found, the remainder of the script might not " +
+				"execute properly, and various warning messages might be given.  A possible cause of this is that someone saved a file with a second file linked, and then separated the two files." + 
+		" To avoid this problem in the future, either unlink files before saving, or maintain the linked file in the same relative position (e.g., in the same directory).";
+		
+		ownerModule.alert(warning);
+	}
+	/*.................................................................................................................*/
+	public MesquiteFile readLinkedFile(String pathName){ //make new/read new linked file//TODO: should say if scripting
+		MesquiteFile linkedFile;
+		if (ownerModule == null || ownerModule.getProject() == null)
+			return null;
+		ownerModule.incrementMenuResetSuppression();
+		if (StringUtil.blank(pathName)) {
+			String message = "Link file to existing project:";
+			if (category == MesquiteFile.INCLUDED)
+				message = "Include file into existing file:";
+			linkedFile =MesquiteFile.open(true, (String)null, message, ownerModule.getProject().getHomeDirectoryName());
+		}
+		else if (pathName.indexOf(MesquiteFile.fileSeparator)<0) {
+			if (MesquiteThread.isScripting() && !MesquiteFile.fileExists(ownerModule.getProject().getHomeDirectoryName(), pathName))
+				warnLinkedNotFound(pathName);
+			linkedFile =MesquiteFile.open(ownerModule.getProject().getHomeDirectoryName(), pathName);
+		}
+		else {
+			String dirName = StringUtil.getAllButLastItem(pathName, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			String fileName = StringUtil.getLastItem(pathName, MesquiteFile.fileSeparator, "/");
+			if (MesquiteThread.isScripting() && !MesquiteFile.fileExists(dirName, fileName))
+				warnLinkedNotFound(pathName);
+			linkedFile =MesquiteFile.open(dirName, fileName);
+		}
+		boolean imp = false;
+
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+		if (linkedFile!=null) {
+			linkedFile.fileReadingArguments = arguments;
+			Parser parser = new Parser();
+			if (parser.tokenIndexOfIgnoreCase(arguments, "useStandardizedTaxonNames")>=0)
+				linkedFile.useStandardizedTaxonNames = true;
+			int tI = parser.tokenIndexOfIgnoreCase(arguments, "taxa");
+			if (tI>=0){
+				String ref = parser.getTokenNumber(arguments, tI+2);
+				Taxa taxa = ownerModule.getProject().getTaxa(ref);
+				linkedFile.setCurrentTaxa(taxa);
+			}
+			linkedFile.setReadCategory(category);
+			if (f!=null)
+				f.setObject(linkedFile);
+			ownerModule.getProject().addFile(linkedFile);
+			linkedFile.setProject(ownerModule.getProject());
+			FileInterpreter fileInterp =null;
+			if (!StringUtil.blank(importer))
+				fileInterp = (FileInterpreter)ownerModule.findEmployeeWithName(importer);
+			NexusFileInterpreter nfi = (NexusFileInterpreter)ownerModule.findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+			if (fileInterp!=null) {
+				if (fileInterp != nfi)
+					imp = true;
+			}
+			else if (nfi!=null && nfi.canReadFile(linkedFile)) {
+				fileInterp = nfi;
+			}
+			else if (!StringUtil.blank(importer)) {
+				MesquiteModule mb = ownerModule.findEmployeeWithName(importer);
+				if (mb instanceof FileInterpreter) {
+					fileInterp = (FileInterpreter)mb;
+					imp = true;
+				}
+			}
+			else {
+
+				fileInterp = ownerModule.findImporter(linkedFile, fileType, arguments);
+				imp = true;
+			}
+			if (fileInterp !=null) {
+				MesquiteFile sf = CommandRecord.getScriptingFileS();
+
+				CommandRecord.setScriptingFileS(linkedFile);
+				ownerModule.pw.suppress();
+
+				if (fileType == 0 || fileInterp == nfi)
+					fileInterp.readFile(ownerModule.getProject(), linkedFile, arguments);
+				else 
+					((FileInterpreterITree)fileInterp).readTreeFile(ownerModule.getProject(), linkedFile, arguments);
+				ownerModule.pw.resume();
+				ownerModule.pw.getParentFrame().setAsFrontWindow(ownerModule.getProject().activeWindowOfProject);
+				CommandRecord.setScriptingFileS(sf);
+				linkedFile.fileReadingArguments = null;
+				ownerModule.broadcastFileRead(ownerModule, linkedFile);
+
+			}
+			else {
+				ownerModule.alert("Sorry, an interpreter was not found for this file");
+				ownerModule.getProject().removeFile(linkedFile);
+				ownerModule.decrementMenuResetSuppression();
+				MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+				linkedFile.fileReadingArguments = null;
+				return null;
+			}
+		}
+		else {
+			ownerModule.decrementMenuResetSuppression();
+			MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+			return null;
+		}
+
+		if (category == MesquiteFile.INCLUDED){
+			ownerModule.getProject().mergeFile(linkedFile);
+		}
+		else if (!linkedFile.isClosed()) {
+			ownerModule.getProject().fileSaved(linkedFile);
+			Parser parser = new Parser();
+			if (imp && parser.tokenIndexOfIgnoreCase(arguments, "suppressImportFileSave")<0){//was imported; change name
+				linkedFile.changeLocation(linkedFile.getDirectoryName(), linkedFile.getFileName()+".nex");
+				if (MesquiteThread.isScripting() || linkedFile.changeLocation("Save imported linked file as NEXUS file"))
+					ownerModule.writeFile(linkedFile);
+				else {
+					linkedFile.close();
+				}
+			}
+		}
+		ownerModule.resetAllMenuBars();
+		ownerModule.getProject().refreshProjectWindow();
+		MesquiteTrunk.mesquiteTrunk.refreshBrowser(MesquiteProject.class);
+		ownerModule.decrementMenuResetSuppression();
+		if (linkedFile !=null && linkedFile.getCloseAfterReading()){
+			ownerModule.closeFile(linkedFile);
+			return null;
+		}
+		return linkedFile;
+	}
+	/** DOCUMENT */
+	public void run() {
+		MesquiteThread.numFilesBeingRead++;
+		try {
+			if (ownerModule.getProject() != null)
+			ownerModule.getProject().incrementProjectWindowSuppression();
+
+			readLinkedFile(path);
+			if (ownerModule.getProject() != null)
+				ownerModule.getProject().decrementProjectWindowSuppression();
+
+		}
+		catch (Exception e){
+			MesquiteFile.throwableToLog(this, e);
+			MesquiteTrunk.mesquiteTrunk.alert("File reading could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + "). If you save any files, you might best use Save As... in case data were lost or file saving doesn't work properly. To report this as a bug, PLEASE send along the Mesquite_Log file from Mesquite_Support_Files.");
+
+		}
+		catch (Error e){
+			if (e instanceof OutOfMemoryError)
+				MesquiteMessage.println("OutofMemoryError.  See file startingMesquiteAndMemoryAllocation.txt in the Mesquite_Folder for information on how to increase memory allocated to Mesquite.");
+			if (!(e instanceof ThreadDeath)){
+				MesquiteDialog.closeWizard();
+				MesquiteFile.throwableToLog(this, e);
+				MesquiteTrunk.mesquiteTrunk.alert("File reading could not be completed because an exception or error occurred (i.e. a crash; " + e.getClass() + "). If you save any files, you might best use Save As... in case data were lost or file saving doesn't work properly. To report this as a bug, PLEASE send along the Mesquite_Log file from Mesquite_Support_Files.");
+			}
+			MesquiteThread.numFilesBeingRead--;
+			throw e;
+		}
+		MesquiteThread.numFilesBeingRead--;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/ProjectWindow.java b/Source/mesquite/minimal/BasicFileCoordinator/ProjectWindow.java
new file mode 100644
index 0000000..5172c31
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/ProjectWindow.java
@@ -0,0 +1,1860 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.BasicFileCoordinator;
+/*~~  */
+
+import java.io.File;
+import java.util.*;
+import java.util.List;
+import java.awt.*;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTarget;
+import java.awt.event.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.meristic.lib.*;
+import mesquite.assoc.lib.*;
+
+public class ProjectWindow extends MesquiteWindow implements MesquiteListener {
+	MesquiteProject proj;
+	boolean suppressed = false;
+	BasicFileCoordinator bfc;
+	ProjectPanel projPanel;
+	ScrollPanel scrollPanel;
+	int scrollHeight = 26;
+	int scrollWidth = 54;
+	/*.................................................................................................................*/
+	public ProjectWindow(FileCoordinator  ownerModule){
+		super(ownerModule, false);
+		bfc = (BasicFileCoordinator)ownerModule;
+		proj = ownerModule.getProject();
+		projPanel = new ProjectPanel(this, proj, bfc);
+		scrollPanel = new ScrollPanel(projPanel);
+		addToWindow(scrollPanel);
+		addToWindow(projPanel);
+		setBackground(ColorTheme.getExtInterfaceBackground());
+		proj.addListener(this);
+
+	}
+	public int getDefaultTileLocation(){
+		return MesquiteFrame.RESOURCES;
+	}
+	/*.................................................................................................................*/
+	/** Gets the content width of the window (excluding the insets) */
+	public int getContentsWidth(){
+		///return	 (outerContents.getBounds().width);
+		Insets insets = getInsets();
+		return (getParentFrame().getBounds().width-insets.left - insets.right);
+	}
+	/*.................................................................................................................*/
+	/** Gets basic snapshot for window, including size, location. */
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		MesquiteFrame f = getParentFrame();
+		temp.addLine("suppress");
+		temp.addLine("setResourcesState " + f.getResourcesFullWindow() + " " + f.getResourcesClosedWhenMinimized() + " "  + f.getResourcesWidth());
+		/*	if (f.getResourcesWidth() != MesquiteFrame.defaultResourcesWidth)
+			temp.addLine("setResourcesWidth " + f.getResourcesWidth());
+		 */
+		temp.addLine("setPopoutState " + f.getPopoutWidth());
+		temp.incorporate(super.getSnapshot(file), false);
+		temp.addLine("desuppress");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	Parser parser = new Parser();
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(MesquiteWindow.class, "Sets the state of the resources panel of the window", null, commandName, "setResourcesState")) {
+			MesquiteFrame f = getParentFrame();
+			String rfwt = parser.getFirstToken(arguments);
+			if (rfwt != null){
+				boolean rfw = rfwt.equalsIgnoreCase("true");
+				String rcwmt = parser.getNextToken();
+				if (rcwmt != null){
+					boolean rcwm = rcwmt.equalsIgnoreCase("true");
+					String rwt = parser.getNextToken();
+					int rw = MesquiteInteger.fromString(rwt);
+					if (!MesquiteFrame.respectFileSpecificResourceWidth || !MesquiteInteger.isCombinable(rw))
+						rw = f.getResourcesWidth();
+					f.setResourcesState(rfw, rcwm, rw);
+
+				}
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the width of the resources panel of the window", null, commandName, "setResourcesWidth")) {
+			if (MesquiteFrame.respectFileSpecificResourceWidth)
+				return null;
+			MesquiteFrame f = getParentFrame();
+			String rfwt = parser.getFirstToken(arguments);
+			if (rfwt != null){
+				int rw = MesquiteInteger.fromString(rfwt);
+				if (MesquiteInteger.isCombinable(rw))
+					f.setResourcesState( f.getResourcesFullWindow(), f.getResourcesClosedWhenMinimized(), rw);
+			}
+
+		}
+		else if (checker.compare(MesquiteWindow.class, "Sets the state of the popout panel of the window", null, commandName, "setPopoutState")) {
+			MesquiteFrame f = getParentFrame();
+			String rfwt = parser.getFirstToken(arguments);
+			if (rfwt != null){
+				int rw = MesquiteInteger.fromString(rfwt);
+				if (MesquiteInteger.isCombinable(rw)){
+					f.setPopoutWidth(rw);
+				}
+				String rcwmt = parser.getNextToken();
+				if (rcwmt != null){
+					int total = MesquiteInteger.fromString(rcwmt);
+					if (MesquiteInteger.isCombinable(total)){
+						//	f.setTotalMainPlusPopWidth(rfw, rcwm, rw);
+					}
+				}
+			}
+		}
+		else if (checker.compare(MesquiteWindow.class, "Explain the incorporation options", null, commandName, "explainIncorporate")) {
+			explainIncorporate();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Suppress refreshing the panels", null, commandName, "suppress")) {
+			proj.incrementProjectWindowSuppression();
+		}
+		else if (checker.compare(MesquiteWindow.class, "Desuppress refreshing the panels", null, commandName, "desuppress")) {
+			proj.decrementProjectWindowSuppression();
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public boolean setAsFrontOnClickAnyContent(){
+		return false;
+	}
+	public void explainIncorporate(){
+		String html = "<html><body>";
+		html += "<h2>Incorporating information from another file</h2>";
+		html += "There are several ways to incorporate information from another file.  Follow this key to decide what is appropriate for your needs:";
+		html += "<ol>";
+
+		html += "<li>Do you want to incorporate taxa and/or matrices from another file into this project?  (If you want to incorporate trees only, see the other options below.)";
+		html += "<ol>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileLink.gif") + "\"> Do you want the information incorporated to remain in the other file?  If so, then you want to use <b>Link File</b>. ";
+		html +="If you do this and you want to save the files linked together, you should keep them in the same relative position on disk, so that when you later open the home file, it can find the linked file.</li><br>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileIncludeBasic.gif") + "\"> Do you want the information incorporated to be copied into the home file of this project?";
+		html += " The other file will be read and then ignored; the other file will not remain linked and will not be re-written.";
+		html += "<ol>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileInclude.gif") + "\">  Do you want to incorporate taxa, matrices and trees, but in such a way that in general keeps the taxa blocks and matrices separate from those currently in the project?";
+		html += " Then use <b>Include File</b>.</li><br>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileMergeTM.gif") + "\">  Do you want to merge the taxa blocks and matrices from the other file into the taxa blocks and matrices currently in this project?";
+		html += " Then use <b>Merge Taxa/Matrices</b>.  This is a special system that permits you to fuse taxa and matrices from other files into existing taxa blocks and matrices.";
+		html += " This is useful for instance to add new sequences from another file into a DNA sequence matrix.</li>";
+		html += "</ol>";
+		html +="</li>";
+		html += "</ol>";
+		html +="</li>";
+
+		html += "<li>Do you want to incorporate only trees from another file?";
+		html += "<ol>";
+		html += "<li>Do you want to incorporate the trees only temporarily in a calculation, and so as to save memory?";
+		html += " If so then you can request one of the following two options as your Tree Source in the tree window or in various calculations:<ol>";
+		html += "<li><b>Use Trees from Separate File</b>: this reads in the trees from the file one at a time, as needed, and therefore saves memory with large tree files.</li>";
+		html += "<li><b>MrBayes Trees</b>: this is a special version of Use Trees from Separate File that can also read the associated .p file to recover tree scores.</li>";
+		html += "</ol>To use either of these, choose it as your <b>Tree Source</b> whenever you are using a Tree Window, Chart or other calculation that uses trees.  These do not bring the trees into the project, and therefore the trees are available only for the tree window or calculation requested.";
+		html +="</li><br>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileLinkTrees.gif") + "\">  Do you want the trees incorporated to remain in the other file?";
+		html += " Then use <b>Link Trees</b>.  ";
+		html +="If you do this and you want to save the files linked together, you should keep them in the same relative position on disk, so that when you later open the home file, it can find the linked file.</li><br>";
+		html += "<li><img src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "fileIncludeTrees.gif") + "\">  Do you want the trees to be copied into the home file of this project?";
+		html += " Then use <b>Include Trees</b>.  With this option you can choose whether to include all or only some of the trees.";
+		html += " By sampling only some of the trees, you can save memory.  The trees will be moved into the home file of this project, and will be saved there when you save the file.</li>";
+		html += "</ol>";
+
+		html += "</ol>";
+
+		html += "</html></body>";
+		bfc.alertHTML(html, "Incorporating File", "Incorporating File", 820, 700);
+	}
+	/*  From ManageTrees
+	 * 		MesquiteSubmenuSpec mss = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Import File with Trees");
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Link Contents...", makeCommand("linkTreeFile",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Include Contents...", makeCommand("includeTreeFile",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Include Partial Contents...", makeCommand("includePartialTreeFile",  this));
+
+	 */
+	public void windowResized(){
+		if (projPanel != null){
+			projPanel.setBounds(0,0,getBounds().width, getBounds().height);
+			scrollPanel.setBounds(0,getBounds().height-scrollHeight,getWidth(), scrollHeight);
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetTitle(){
+		if (ownerModule==null || ownerModule.getProject() == null)
+			setTitle("Project");
+		else if (ownerModule.getProject().hasName())
+			setTitle("Project: " + ownerModule.getProject().getName());
+		else
+			setTitle(ownerModule.getProject().getName());
+		repaint();
+	}
+	public boolean permitViewMode(){
+		return false;
+	}
+	public void dispose(){
+		projPanel.dispose();
+		super.dispose();
+	}
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == proj && !MesquiteThread.isScripting()&& Notification.getCode(notification)!= MesquiteListener.ELEMENT_CHANGED)
+			projPanel.refresh();
+
+	}
+	public void setFootnote(String heading, String text){
+		projPanel.setFootnote(heading, text);
+	}
+	public void refresh(FileElement element){
+		if (bfc.isDoomed() || bfc.getProject().refreshSuppression>0)
+			return;
+		BasicFileCoordinator.totalProjectPanelRefreshes++;
+		projPanel.refresh(element);
+	}
+	public void refresh(){
+		if (bfc.isDoomed() || bfc.getProject().refreshSuppression>0)
+			return;
+		BasicFileCoordinator.totalProjectPanelRefreshes++;
+		projPanel.refresh();
+	}
+	public void refreshGraphics(){
+		if (bfc.isDoomed())
+			return;
+		BasicFileCoordinator.totalProjectPanelRefreshes++;
+		projPanel.refreshGraphics();
+	}
+	void suppress(){
+		suppressed = true; 
+		proj.incrementProjectWindowSuppression();
+	}
+	void resume(){  //BECAUSE OF decPWS below, should call this only if suppress had been called previously
+		resume(true);
+	}
+	void resume(boolean dpws){  
+		suppressed = false;
+		if (dpws)
+			proj.decrementProjectWindowSuppression();
+		refresh();
+	}
+}
+
+class ProjectPanel extends MousePanel implements ClosablePanelContainer{
+	Vector elements = new Vector();
+	MesquiteProject proj;
+	BasicFileCoordinator bfc;
+	ProjectWindow w;
+	Image fileIm;
+	ScrollPanel scroll;
+	NotesPanel notesPanel = null;
+	public ProjectPanel(ProjectWindow w, MesquiteProject proj, BasicFileCoordinator bfc){ 
+		super();
+		this.w = w;
+		this.bfc = bfc;
+		this.proj = proj;
+		setLayout(null);
+		setBackground(ColorTheme.getExtInterfaceBackground());
+		fileIm = 	MesquiteImage.getImage(bfc.getPath()+ "projectHTML" + MesquiteFile.fileSeparator + "fileSmall.gif");
+		setSize(94, 500);
+
+	}
+	public void setFootnote(String heading, String text){
+		if (notesPanel != null)
+			notesPanel.setText(heading, text);
+	}
+	public void requestHeightChange(ClosablePanel panel){
+		resetSizes(getBounds().width, getBounds().height);
+	}
+	public void refreshGraphics(){
+		for (int e = 0; e< elements.size(); e++){
+			ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+			panel.refreshGraphics();
+		}
+	}
+
+	public void dispose(){
+		if (true)
+			return;
+		for (int i = 0; i<elements.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)elements.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+	}
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel){
+		return null;
+	}
+	public void explainProjectWindow(){
+		String html = "<html><body>";   
+		html += "<h3>Project with Home File \""  + StringUtil.protectForXML(proj.getHomeFileName()) + "\"</h3>";
+		html += "In Directory: " + StringUtil.protectForXML(proj.getHomeDirectoryName()) + "<p>";
+		html += "This panel summarizes your project, which may represent one or more files.  Listed are the files, and the objects within the project, such as taxa, character matrices, trees, models and others.";
+		html += "<ul><li>You can see more details for each object by touching on the triangles (<img src=\"" + MesquiteFile.massageFilePathToURL(MesquiteModule.getRootPath() +"images" + MesquiteFile.fileSeparator + "infoBarTriangle.gif") + "\">) to open them";
+		html += "</li>";
+
+		html += "<li>If you touch on the object's name, you will get a menu allowing you to perform various actions, such as renaming or deleting the object.";
+		html += "</li></ul>";
+		html += "<p align=\"center\"><img  src=\"" + MesquiteFile.massageFilePathToURL(bfc.getPath()+"projectHTML" + MesquiteFile.fileSeparator + "projectPanel.jpg") + "\">";
+		html += "</p></html></body>";
+		bfc.alertHTML(html, "Project", "Project", 500, 600);
+	}
+	void addExtraPanel(ProjPanelPanel p){
+		elements.addElement(p);
+		add(p);
+		p.setSize(getWidth(), p.getHeight());
+		resetSizes(getWidth(), getHeight());
+		p.setVisible(true);
+	}
+	public void paint(Graphics g){
+
+		super.paint(g);
+		/*int vertical = 2;
+		int w = getWidth();
+		for (int i = 0; i<elements.size(); i++){
+			ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(i));
+			int requestedlHeight = panel.getRequestedHeight(w);
+			if (
+				vertical += panel.requestSpacer();
+			panel.setBounds(0, vertical, w, requestedlHeight);
+			vertical += requestedlHeight;
+		}*/
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		resetSizes(w, h);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		resetSizes(w, h);
+	}	
+	
+	public static void checkSizes(Component c, int offset){
+		if (c==null)
+			return;
+		int thisOffset = c.getX() + offset;
+		int extent = thisOffset + c.getWidth();
+		if (c instanceof Container){
+			Component[] cc = ((Container)c).getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++)
+					checkSizes(cc[i], thisOffset);
+		}
+
+	}
+
+	int count = 0;
+	int sequenceUpToDate(){
+		if (bfc.isDoomed())
+			return 0;
+		MesquiteProject proj = bfc.getProject();
+		if (proj.refreshSuppression >0)
+			return 0;
+		int e = 0;
+		if (e>= elements.size())
+			return 11029;
+		ProjPanelPanel ppanel = ((ProjPanelPanel)elements.elementAt(e));
+		if (!(ppanel instanceof ProjectLabelPanel) || !ppanel.upToDate())
+			return 222;
+		((ProjectLabelPanel)ppanel).resetCommands();
+		e++;
+		Enumeration efi = bfc.getEmployeeVector().elements();
+		while (efi.hasMoreElements()) {
+			Object obj = efi.nextElement();
+			if (obj instanceof FileInit){
+				FileInit mbe = (FileInit)obj;
+				ProjPanelPanel ppp = mbe.getProjectPanelPanel();
+				if (ppp != null){
+					ProjPanelPanel eppp = ((ProjPanelPanel)elements.elementAt(e));
+					if (eppp.getOwnerModule() != mbe || !eppp.upToDate())
+						return 45601;
+					e++;
+				}
+			}
+		}
+		for (int i=0; i<proj.getNumberLinkedFiles(); i++){
+			MesquiteFile mf = proj.getFile(i);
+			if (e>= elements.size())
+				return 1;
+			ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+			if (!(panel instanceof FilePanel) || ((FilePanel)panel).mf != mf || !panel.upToDate())
+				return 2;
+			panel.resetTitle();
+			panel.repaint();
+			e++;
+		}
+		if (e>= elements.size())
+			return 21;
+		ProjPanelPanel fip;
+		/*ProjPanelPanel fip = ((ProjPanelPanel)elements.elementAt(e));
+		if (!(fip instanceof FileIncorporatePanel) || !fip.upToDate())
+			return 22;
+		e++;*/
+		if (e>= elements.size())
+			return 2001;
+		fip = ((ProjPanelPanel)elements.elementAt(e));
+		if (!(fip instanceof AddElementPanel) || !fip.upToDate())
+			return 2001;
+		e++;
+		if (proj.taxas.size()>0){
+			for (int i = 0; i< proj.taxas.size(); i++){
+				Taxa t = (Taxa)proj.taxas.elementAt(i);
+				if (e>= elements.size())
+					return 3;
+				ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+				if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != t || !panel.upToDate()){
+					return 4;
+				}
+				panel.resetTitle();
+				panel.repaint();
+				e++;
+				if (proj.getNumberCharMatricesVisible(t)>0){
+					for (int k = 0; k<proj.getNumberCharMatricesVisible(t); k++){
+						CharacterData data = proj.getCharacterMatrixVisible(t, k);
+						if (data.isUserVisible()){
+							if (e>= elements.size())
+								return 5;
+							panel = ((ProjPanelPanel)elements.elementAt(e));
+							if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != data || !panel.upToDate())
+								return 6;
+							panel.resetTitle();
+							panel.repaint();
+							e++;
+						}
+					}
+				}
+				if (proj.getNumberOfFileElements(TreeVector.class)>0){
+					for (int k = 0; k<proj.getNumberOfFileElements(TreeVector.class); k++){
+						TreeVector trees = (TreeVector)proj.getFileElement(TreeVector.class, k);
+						if (e>= elements.size())
+							return 7;
+						panel = ((ProjPanelPanel)elements.elementAt(e));
+						if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != trees || !panel.upToDate())
+							return 8;
+						panel.resetTitle();
+						panel.repaint();
+						e++;
+					}
+				}
+
+			}
+			/*if (bfc.getProject().getCharacterModels().getNumNotBuiltIn()>0){
+				if (e>= elements.size())
+					return 9;
+				ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+				if (!(panel instanceof CharModelsPanel) || !panel.upToDate())
+					return 10;
+				((CharModelsPanel)panel).refresh();
+				e++;
+			}*/
+			ListableVector others = bfc.getProject().getOtherElements();
+			if (others.size()>0){
+				for (int i=0; i<others.size(); i++){
+					FileElement f = (FileElement)others.elementAt(i);
+					/*if (f instanceof TaxaGroupVector || f instanceof CharactersGroupVector){
+						if (((ListableVector)f).size()>0){
+							if (e>= elements.size())
+								return 100;
+							ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+							if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != f || !panel.upToDate())
+								return 101;
+							((GroupsPanel)panel).refresh();
+							e++;
+						}
+					}
+					else */if (f instanceof TaxaAssociation){
+						if (e>= elements.size())
+							return 900;
+						ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+						if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != f || !panel.upToDate())
+							return 901;
+						panel.resetTitle();
+						panel.repaint();
+						e++;
+					}
+				}
+
+			}
+			if (e<elements.size())
+				return 11;
+			return 0;
+		}
+		else {
+			/*if (bfc.getProject().getCharacterModels().getNumNotBuiltIn()>0){
+				if (e>= elements.size())
+					return 12;
+				ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+				if (!(panel instanceof CharModelsPanel) || !panel.upToDate())
+					return 13;
+				((CharModelsPanel)panel).refresh();
+				e++;
+			}
+			*/
+			ListableVector others = bfc.getProject().getOtherElements();
+			if (others.size()>0){
+				for (int i=0; i<others.size(); i++){
+					FileElement f = (FileElement)others.elementAt(i);
+					/*if (f instanceof TaxaGroupVector || f instanceof CharactersGroupVector){
+						if (((ListableVector)f).size()>0){
+							if (e>= elements.size())
+								return 102;
+							ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+							if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != f || !panel.upToDate())
+								return 103;
+							((GroupsPanel)panel).refresh();
+							e++;
+						}
+					}
+					else */if (f instanceof TaxaAssociation){
+						if (e>= elements.size())
+							return 902;
+						ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(e));
+						if (!(panel instanceof ElementPanel) || ((ElementPanel)panel).element != f || !panel.upToDate())
+							return 903;
+						panel.resetTitle();
+						panel.repaint();
+						e++;
+					}
+				}
+
+			}
+			if (elements.size() != 0)
+				return 14;
+		}
+
+		return 0;
+	}
+	public void refresh(FileElement e){
+		for (int i = 0; i<elements.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)elements.elementAt(i));
+			if (panel instanceof ElementPanel && ((ElementPanel)panel).element == e){
+				((ElementPanel)panel).refreshIcon();
+				panel.repaint();
+			}
+		}
+	}
+	//boolean fipOpen = false;
+	//FileIncorporatePanel fip = null;
+	public void refresh(){
+		int sutd = sequenceUpToDate();  //integer passed to diagnose why not up to date, for debugging
+		if (sutd==0){
+			resetSizes();
+			return;
+		}
+		//if (fip != null)
+		//	fipOpen = fip.isOpen();
+		for (int i = 0; i<elements.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)elements.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		elements.removeAllElements();
+		ElementPanel panel = null;
+		MesquiteProject proj = bfc.getProject();
+
+		addExtraPanel(panel = new ProjectLabelPanel(bfc, this, w,proj));
+		Enumeration efi = bfc.getEmployeeVector().elements();
+		while (efi.hasMoreElements()) {
+			Object obj = efi.nextElement();
+			if (obj instanceof FileInit){
+				FileInit mbe = (FileInit)obj;
+				ProjPanelPanel ppp = mbe.getProjectPanelPanel();
+				if (ppp != null){
+					ppp.setContainer(this);
+					addExtraPanel(ppp);
+				}
+			}
+		}
+
+		panel.setLocation(0,0);
+		for (int i=0; i<proj.getNumberLinkedFiles(); i++){
+			MesquiteFile mf = proj.getFile(i);
+			addExtraPanel(panel = new FilePanel(bfc, this, w,mf));
+			panel.setSize(94, 10);
+			panel.setLocation(0,0);
+		}
+		//addExtraPanel(fip = new FileIncorporatePanel(bfc,this,w));
+		//fip.setOpen(fipOpen);
+		panel.setLocation(0,0);
+		addExtraPanel(panel = new AddElementPanel(bfc, this,w));
+		panel.setOpen(false);
+		panel.setLocation(0,0);
+		if (proj.taxas.size()>0){
+			for (int i = 0; i< proj.taxas.size(); i++){
+				Taxa t = (Taxa)proj.taxas.elementAt(i);
+				addExtraPanel(panel = new TaxaPanel(bfc, this, w, t));
+				panel.setLocation(0,0);
+				if (proj.getNumberCharMatricesVisible(t)>0){
+					for (int k = 0; k<proj.getNumberCharMatricesVisible(t); k++){
+						CharacterData data = proj.getCharacterMatrixVisible(t, k);
+						if (data.isUserVisible()){
+							if (data instanceof MolecularData)
+								addExtraPanel(panel = new MolecMPanel(bfc, this, w,data));
+							else if (data instanceof ContinuousData)
+								addExtraPanel(panel = new ContMPanel(bfc, this, w, data));
+							else if (data instanceof MeristicData)
+								addExtraPanel(panel = new MeristicMPanel(bfc, this, w, data));
+							else
+								addExtraPanel(panel = new CategMPanel(bfc, this, w, data));
+							panel.setLocation(0,0);
+						}
+					}
+				}
+				if (proj.getNumberOfFileElements(TreeVector.class)>0){
+					for (int k = 0; k<proj.getNumberOfFileElements(TreeVector.class); k++){
+						TreeVector trees = (TreeVector)proj.getFileElement(TreeVector.class, k);
+						if (trees.getTaxa() == t){
+							addExtraPanel(panel = new TreesRPanel(bfc, this, w, trees));
+							panel.setLocation(0,0);
+						}
+					}
+				}
+
+			}
+		}
+	/*	if (bfc.getProject().getCharacterModels().getNumNotBuiltIn()>0){
+			addExtraPanel(panel = new CharModelsPanel(bfc, this, w));
+			panel.setLocation(0,0);
+		}
+		*/
+		ListableVector others = bfc.getProject().getOtherElements();
+		if (others.size()>0){
+			for (int i=0; i<others.size(); i++){
+				FileElement f = (FileElement)others.elementAt(i);
+				/*if (f instanceof TaxaGroupVector || f instanceof CharactersGroupVector){
+					if (((ListableVector)f).size()>0){
+						addExtraPanel(panel = new GroupsPanel(bfc, this, w, (ListableVector)f));
+						panel.setLocation(0,0);
+					}
+				}
+				else */if (f instanceof TaxaAssociation){
+					addExtraPanel(panel = new AssocPanel(bfc, this, w, f));
+					panel.setLocation(0,0);
+				}
+			}
+
+		}
+		addExtraPanel(notesPanel = new NotesPanel(bfc, this, w));
+		resetSizes();
+	}
+	int scrollOffset = 0;
+	int lowestPanel = 0;
+	int highestTaxaPanel = 0;
+	void resetSizes(){
+		resetSizes(getBounds().width, getBounds().height);
+	}
+	void resetSizes(int w, int h){
+		if (bfc.isDoomed() ||  bfc.getProject().refreshSuppression>0)
+			return;
+		int max = getHeight();
+		int vertical = 2;
+		highestTaxaPanel = 0;
+		for (int i = 0; i<elements.size(); i++){
+			ProjPanelPanel panel = ((ProjPanelPanel)elements.elementAt(i));
+			if (i<scrollOffset){
+				panel.setBounds(0, 0, 0, 0);
+			}
+			else {
+				int requestedlHeight = panel.getRequestedHeight(w);
+				if(i>0)
+					vertical += panel.requestSpacer();
+				if (vertical < max && vertical+requestedlHeight<max) {
+					panel.setBounds(0, vertical, w, requestedlHeight);
+					panel.setVisible(true);
+				}
+				else if (vertical < max && vertical+requestedlHeight>max){
+					panel.setBounds(0, vertical, w, max-vertical);
+					panel.setVisible(true);
+				}
+				else if (vertical > max && vertical+requestedlHeight>max){
+					panel.setBounds(0, 0, 0, 0);
+					panel.setVisible(false);
+				}
+				else {
+					panel.setBounds(0, 0, 0, 0);
+					panel.setVisible(false);
+				}
+
+				if (panel instanceof TaxaPanel && highestTaxaPanel == 0)
+					highestTaxaPanel = vertical;
+				vertical += requestedlHeight;
+				lowestPanel = vertical;
+			}
+		}
+		if (scroll != null)
+			scroll.repaint();
+		MesquiteWindow.rpAll(this);
+	}
+	boolean canScrollUp(){
+		if (scrollOffset==0 && lowestPanel < getHeight())
+			return false;
+		return true;
+	}
+	boolean canScrollDown(){
+		if (scrollOffset == 0)
+			return false;
+		return true;
+	}
+	void scrollDown(){
+		int was = scrollOffset;
+		scrollOffset -= 1;
+		if (scrollOffset <0)
+			scrollOffset = 0;
+		if (was != scrollOffset)
+			resetSizes();
+	}
+	void scrollUp(){
+		if (scrollOffset==0 && lowestPanel < getHeight())
+			return;
+		int was = scrollOffset;
+		scrollOffset += 1;
+		if (scrollOffset > elements.size()-1)
+			scrollOffset = elements.size()-1;
+		if (was != scrollOffset)
+			resetSizes();
+	}
+
+}
+/*======================================================================== */
+class ScrollPanel extends MousePanel {
+	ProjectPanel p;
+	Image up, down, search; // query;
+	int scrollLeft = 38;
+	HelpSearchStrip searchStrip;
+
+	public ScrollPanel(ProjectPanel p){
+		super();
+		this.p = p;
+		p.scroll = this;
+		setLayout(null);
+		searchStrip = new HelpSearchStrip(p.w, true);
+		add(searchStrip);
+		searchStrip.setSize(120, 15);
+		searchStrip.setLocation(20, 0);
+		searchStrip.setVisible(true);
+		searchStrip.setText("");
+		search = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath()+ "search.gif");
+		up = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath()+ "uparrow.gif");
+		down = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath()+ "downarrow.gif");
+	//	query = MesquiteImage.getImage(p.bfc.getPath() + "projectHTML" + MesquiteFile.fileSeparator + "queryGray.gif");
+		setBackground(ColorTheme.getExtInterfaceBackground());
+	}
+	public void paint(Graphics g){
+		g.drawImage(search, 4, 0, this);
+		if (!p.canScrollUp() && !p.canScrollDown())
+			return;
+		g.setColor(ColorDistribution.veryLightGray);
+		g.fillRect(0,0,getWidth(), getHeight());
+	//	g.drawImage(query, 8, 8, this);
+		if (p.canScrollUp())
+			g.drawImage(up, scrollLeft, 18, this);
+		if (p.canScrollDown())
+			g.drawImage(down, scrollLeft+22, 18, this);
+		g.setColor(Color.gray);
+		g.fillRect(0,0,getWidth(), 3);
+		//g.fillRect(getWidth()-3,0,3, getHeight());
+	}
+	/*public void setSize(int w, int h){
+		super.setSize(w, h);
+		searchStrip.setSize(w, 15);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		searchStrip.setSize(w, 15);
+	}*/
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		//if modifiers include right click/control, then do dropdown menu
+		if (y<=16 && x < 20) {
+			searchStrip.search();
+		}
+		else if (y>=8 && y<=26 && x>= scrollLeft && x < scrollLeft + 18) {
+			p.scrollUp();
+		}
+		else if (y>=8 && y<=26 && x>= scrollLeft+22 && x < scrollLeft + 40) {
+			p.scrollDown();
+		}
+	}
+
+
+}
+/*======================================================================== */
+class AddElementPanel extends ElementPanel {
+
+	public AddElementPanel(BasicFileCoordinator bfc, ClosablePanelContainer container,MesquiteWindow w){
+		super(bfc, container, w, "Add...");
+		setShowTriangle(false);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		addCommand(true, null, "New Taxa Block...", "New Taxa Block...",  new MesquiteCommand("newTaxa", (Commandable)bfc.findElementManager(Taxa.class)));
+		addCommand(true, null, "New Character Matrix...", "New Character Matrix...",  new MesquiteCommand("newMatrix", (Commandable)bfc.findElementManager(CharacterData.class)));
+		addCommand(true, null, "New Trees Block...", "New Trees Block...",  new MesquiteCommand("newTreeBlock", (Commandable)bfc.findElementManager(TreeVector.class)));
+		addCommand(true, null, "-", "-",  null);
+		addCommand(true, null, "-", "Read Other File",  null);
+		addCommand(false, "queryGray.gif", null, "Explanation...",  new MesquiteCommand("explainIncorporate", bfc.getModuleWindow()));
+		addCommand(false, "fileLink.gif", "Link\nFile", "Link File...", new MesquiteCommand("linkFile", bfc));
+		addCommand(false, "fileInclude.gif", "Include\nFile", "Include File...", new MesquiteCommand("includeFile", bfc));
+		MesquiteCommand c = new MesquiteCommand("newAssistant", bfc);
+		c.setDefaultArguments("#mesquite.dmanager.FuseTaxaMatrices.FuseTaxaMatrices");
+		addCommand(false, "fileMergeTM.gif", "Merge Taxa\n& Matrices", "Merge Taxa/Matrices...", c);
+		ElementManager tm = bfc.findElementManager(TreeVector.class);
+		addCommand(false, "fileLinkTrees.gif", "Link\nTrees", "Link Trees...", new MesquiteCommand("linkTreeFile", ((MesquiteModule)tm)));
+		addCommand(false, "fileIncludeTrees.gif", "Include\nTrees", "Include Trees...", new MesquiteCommand("includeTreeFileAskPartial", ((MesquiteModule)tm)));
+	}
+
+}
+
+/*======================================================================== *
+class NewElementPanel extends ElementPanel {
+
+	public NewElementPanel(BasicFileCoordinator bfc, ClosablePanelContainer container,MesquiteWindow w){
+		super(bfc, container, w, "New...");
+		setShowTriangle(false);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		addCommand(true, null, "New Taxa Block...", "New Taxa Block...",  new MesquiteCommand("newTaxa", (Commandable)bfc.findElementManager(Taxa.class)));
+		addCommand(true, null, "New Character Matrix...", "New Character Matrix...",  new MesquiteCommand("newMatrix", (Commandable)bfc.findElementManager(CharacterData.class)));
+		addCommand(true, null, "New Trees Block...", "New Trees Block...",  new MesquiteCommand("newTreeBlock", (Commandable)bfc.findElementManager(TreeVector.class)));
+	}
+
+}
+
+/*======================================================================== *
+class FileIncorporatePanel extends ElementPanel {
+
+	public FileIncorporatePanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w){
+		super(bfc, container, w, "Read from File...");
+		//	setColors(ColorDistribution.veryVeryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, Color.black);
+		//	Color cLight = ColorTheme.getExtInterfaceBackground();
+		//		Color cDark = ColorTheme.getExtInterfaceElement();
+		//		setColors(cLight, cLight, cLight, cDark);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		addCommand(false, "queryGray.gif", null, "Explanation...",  new MesquiteCommand("explainIncorporate", bfc.getModuleWindow()));
+		addCommand(false, "fileLink.gif", "Link\nFile", "Link File...", new MesquiteCommand("linkFile", bfc));
+		addCommand(false, "fileInclude.gif", "Include\nFile", "Include File...", new MesquiteCommand("includeFile", bfc));
+		MesquiteCommand c = new MesquiteCommand("newAssistant", bfc);
+		c.setDefaultArguments("#mesquite.dmanager.FuseTaxaMatrices.FuseTaxaMatrices");
+		addCommand(false, "fileMergeTM.gif", "Merge Taxa\n& Matrices", "Merge Taxa/Matrices...", c);
+		ElementManager tm = bfc.findElementManager(TreeVector.class);
+		addCommand(false, "fileLinkTrees.gif", "Link\nTrees", "Link Trees...", new MesquiteCommand("linkTreeFile", ((MesquiteModule)tm)));
+		addCommand(false, "fileIncludeTrees.gif", "Include\nTrees", "Include Trees...", new MesquiteCommand("includeTreeFileAskPartial", ((MesquiteModule)tm)));
+		setWholeOpen(true);
+	}
+
+}
+/*======================================================================== */
+class ProjectLabelPanel extends ElementPanel {
+	MesquiteProject project;
+	String[] names;
+	public ProjectLabelPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, MesquiteProject project){
+		super(bfc, container, w, "Project");
+		setShowTriangle(false);
+		this.project = project;
+
+		resetCommands();
+	}
+
+	public boolean getBold(){
+		return true;
+	}
+	public String getFootnote(){
+		if (project == null)
+			return null;
+		String text = "Project with home file " + project.getHomeFileName();
+		int numTaxaBlocks = project.getNumberOfFileElements(Taxa.class);
+		int numMatrices = project.getNumberCharMatrices();
+		int numTreeBlocks = project.getNumberOfFileElements(TreeVector.class);
+		if (numTaxaBlocks>0){
+			text += ", with";
+			if (numTaxaBlocks == 1)
+				text += "\n  " + numTaxaBlocks + " taxa block";
+			else if (numTaxaBlocks > 1)
+				text += "\n  " + numTaxaBlocks + " taxa blocks";
+			if (numMatrices==1)
+				text += ";\n  " + numMatrices + " character matrix";
+			else if (numMatrices>1)
+				text += ";\n  " + numMatrices + " character matrices";
+			if (numTreeBlocks==1)
+				text += ";\n  "  + numTreeBlocks + " tree block";
+			else if (numTreeBlocks>1)
+				text += ";\n  "  + numTreeBlocks + " tree blocks";
+		}
+		return text;
+	}
+	protected String getMenuHeading(){
+		if (project.hasName())
+			return "Project: " + project.getName();
+		else
+			return project.getName();
+	}
+	public void resetCommands(){
+		deleteAllCommands();
+		addCommand(true, null, "Name of Project...", "Name of Project...", new MesquiteCommand("setName", project));
+		int numProjects = MesquiteTrunk.getProjectList().getNumProjects();
+		if (numProjects<2)
+			return;
+		names = new String[numProjects-1];
+		addCommand(true, null, "-", "-", null);
+		int k = 0;
+		addCommand(true, null, "Other Projects:", "Other Projects:", null);
+		for (int i = 0; i< numProjects; i++){
+			MesquiteProject proj = MesquiteTrunk.getProjectList().getProject(i);
+			if (proj != project && proj != null) {
+				addCommand(true, null, proj.getHomeFileName(), proj.getHomeFileName(), new MesquiteCommand("allToFront", proj.getCoordinatorModule()));
+				names[k++] = proj.getHomeFileName();
+			}
+		}
+	}
+
+
+}
+/*======================================================================== */
+class NotesPanel extends ProjPanelPanel {
+	StringInABox textBox, headingBox;
+	String text = null;
+	String heading = null;
+	public NotesPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w){
+		super(bfc, container, w, null, bfc);
+		headingBox =  new StringInABox("", new Font("SansSerif", Font.BOLD, MesquiteFrame.resourcesFontSize), getWidth());
+		textBox =  new StringInABox("", new Font("SansSerif", Font.PLAIN, MesquiteFrame.resourcesFontSize), getWidth());
+		setText(null, null);
+	}
+	public int getRequestedHeight(int width){
+		return 200;
+	}
+	void setText(String h, String t){
+		text = t;
+		heading = h;
+		headingBox.setString(h);
+		textBox.setString(t);
+		repaint();
+	}
+	protected void resetSizes(int w, int h){
+		if (textBox != null){
+			headingBox.setWidth(w-24);
+			textBox.setWidth(w-24);
+		}
+	}
+	
+	public void paint(Graphics g){
+		if (text != null){
+			g.setColor(Color.lightGray);
+			g.fillRect(8, 12, getWidth()-16, 2);
+			g.setColor(ColorTheme.getExtInterfaceTextMedium());
+			if (heading != null){
+				headingBox.draw(g, 16,16);
+				
+				textBox.draw(g, 16,headingBox.getHeight() + 16);
+			}
+			else
+				textBox.draw(g, 16,16);
+				
+		}
+	}
+}
+
+/*======================================================================== */
+class FilePanel extends ElementPanel {
+	MesquiteFile mf;
+	public FilePanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, MesquiteFile mf){
+		super(bfc, container, w,mf.getFileName());
+		setShowTriangle(false);
+		this.mf = mf;
+		if (mf == bfc.getProject().getHomeFile())
+			im = 	MesquiteImage.getImage(bfc.getPath()+ "projectHTML" + MesquiteFile.fileSeparator + "fileSmall.gif");
+		else
+			im = 	MesquiteImage.getImage(bfc.getPath()+ "projectHTML" + MesquiteFile.fileSeparator + "fileLinkedSmall.gif");
+		//	Color cLight = ColorDistribution.projectLight[bfc.getProject().getProjectColor()];
+		//	Color cDark = ColorDistribution.projectDark[bfc.getProject().getProjectColor()];
+		//	setColors(cLight, cLight, cLight, cDark);
+		//	setColors(ColorDistribution.veryVeryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, Color.black);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		if (mf.isLocal()){
+			addCommand(true, null, "Show File Location on Disk", "Show File Location on Disk", new MesquiteCommand("show", this));
+			addCommand(true, null, "-", "-", null);
+			addCommand(true, null, "Save File", "Save File", new MesquiteCommand("save", mf));
+		}
+		addCommand(true, null, "Save File As...", "Save File As...", new MesquiteCommand("saveAs", mf));
+		addCommand(true, null, "Close File", "Close File", new MesquiteCommand("close", mf));
+
+
+	}
+	public void resetTitle(){
+		setTitle(mf.getFileName());
+		repaint();
+	}
+	public String getFootnote(){
+		if (mf == null || mf.getDirectoryName() == null)
+			return null;
+		return "Location of file: " + mf.getDirectoryName();
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return "File";
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows file location on disk", null, commandName, "show")) {
+			if (mf == null || mf.getDirectoryName() == null)
+				return null;
+			MesquiteFile.showDirectory(mf.getDirectoryName());
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+}
+
+/*======================================================================== */
+class TaxaPanel extends ElementPanel {
+
+	public TaxaPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element);
+		//	setColors(ColorDistribution.veryLightGray, ColorDistribution.veryVeryLightGray, Color.lightGray, Color.black);
+		if (bfc.getProject().virginProject)
+			setOpen(true);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		addCommand(false, "list.gif", "List &\nManage\nTaxa", "List & Manage Taxa", new MesquiteCommand("showMe", element));
+		addCommand(false, "chart.gif", "Chart\nTaxa", "Chart Taxa", new MesquiteCommand("chart", this));
+		addCommand(true, null, "Show New\nTree Window", "Show New Tree Window", new MesquiteCommand("showInitTreeWindow", this));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Rename Taxa Block", "Rename Taxa Block", new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete Taxa Block", "Delete Taxa Block", new MesquiteCommand("deleteMe", element));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Edit Comment", "Edit Comment", new MesquiteCommand("editComment", element));
+		/*	Vector vv = ((FileElement)element).getSpecSetsVectorVector();
+		for (int i=0; i<vv.size(); i++){
+			SpecsSetVector v = (SpecsSetVector)vv.elementAt(i);
+			v.addListener(this);
+			for (int k=0; k<v.size(); k++){
+				FileElement fe = (FileElement)v.elementAt(k);
+				fe.addListener(this);
+			}
+		}
+		 */
+	}
+
+	public String getTitleAddition(){
+		int numTaxa = ((Taxa)element).getNumTaxa();
+		String heading = " (" + numTaxa + " tax";
+		if (numTaxa>1)
+			heading += "a)";
+		else
+			heading += "on)";
+		return heading;
+	}
+	
+	
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows an initial tree window", null, commandName, "showInitTreeWindow")) {
+			//CommandRecord oldCommandRec = MesquiteThread.getCurrentCommandRecord();
+			//CommandRecord scriptRec = new CommandRecord(true);
+			//MesquiteThread.setCurrentCommandRecord(scriptRec);
+			((BasicFileCoordinator)bfc).showInitTreeWindow((Taxa)element, true);
+			//MesquiteThread.setCurrentCommandRecord(oldCommandRec);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return "Taxa Block";
+	}
+	public int requestSpacer(){
+		return 16;
+	}
+	void chart(){
+		String mID = Long.toString(((FileElement)element).getID());
+		MesquiteThread.addHint(new MesquiteString("TaxonValuesChart", mID));
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.triggerWizard();
+		((BasicFileCoordinator)bfc).showChartWizard("Taxa");
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.detriggerWizard();
+	}
+	public String getNotes(){
+		if(element == null)
+			return "";
+		return Integer.toString(((Taxa)element).getNumTaxa()) + " Taxa";
+	}
+	
+}
+/*======================================================================== */
+class MElementPanel extends ElementPanel {
+	CharacterData data = null;
+
+	public MElementPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container,w, element);
+		addCommand(false, getShowMatrixIconFileName(), "Show\nMatrix", "Show Matrix", new MesquiteCommand("showMe", element));
+		addCommand(false, "list.gif", "List &\nManage\nCharacters", "List & Manage Characters", new MesquiteCommand("list", this));
+		addCommand(false, "chart.gif", "Chart\nCharacters", "Chart Characters", new MesquiteCommand("chart", this));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Rename Matrix", "Rename Matrix", new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete Matrix", "Delete Matrix", new MesquiteCommand("deleteMe", element));
+		addCommand(true, null, "Duplicate Matrix", "Duplicate Matrix", new MesquiteCommand("duplicateMe", element));
+		addCommand(true, null, "Export Matrix", "Export Matrix", new MesquiteCommand("exportMe", element));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Edit Comment", "Edit Comment", new MesquiteCommand("editComment", element));
+		if (bfc.getProject().virginProject)
+			setOpen(true);
+		if (element instanceof CharacterData)
+			data = (CharacterData)element;
+		//addCommand(true, null, "ID " + element.getID(), "ID " + element.getID(), new MesquiteCommand("id", this));
+
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Lists the characters", null, commandName, "list")) {
+			((CharacterData)element).showList();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getTitleAddition(){
+		int numChars = ((CharacterData)element).getNumChars();
+		String heading = " (" + numChars + " character";
+		if (numChars>1)
+			heading += "s";
+		heading += ")";
+		
+		return heading;
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return "Matrix";
+	}
+	public String getNotes(){
+		if (element == null)
+			return "";
+		return Integer.toString(((CharacterData)element).getNumChars()) + " Characters";
+	}
+	public String getShowMatrixIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixCateg.gif";
+	}
+	public void actUponDroppedFileContents(FileInterpreter fileInterpreter, String path) {
+		if (fileInterpreter!=null) {
+			Taxa taxa = data.getTaxa();
+			((ReadFileFromString)fileInterpreter).readFileFromString( data,  taxa,  MesquiteFile.getFileContentsAsString(path),  "");
+			taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED, null, null));
+			data.notifyInLinked(new Notification(MesquiteListener.PARTS_ADDED, null, null));
+			data.notifyListeners(this, new Notification(CharacterData.DATA_CHANGED, null, null));
+
+		}
+
+	}
+	public FileInterpreter findFileInterpreter(String droppedContents, String fileName) {
+		if (w!=null) {
+			FileCoordinator fileCoord = w.getOwnerModule().getFileCoordinator();
+			FileInterpreter fileInterpreter = fileCoord.findImporter(droppedContents, fileName,0, "",true, DNAState.class);  
+			return fileInterpreter;
+		} 
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void processFilesDroppedOnPanel(List files) {
+		int count = 0;
+		FileInterpreter fileInterpreter =null;
+		for (Iterator iter = files.iterator(); iter.hasNext();) {
+			File nextFile = (File) iter.next();
+			if (!askListenersToProcess(nextFile, true)) {
+				if (count==0) {
+					fileInterpreter = findFileInterpreter(MesquiteFile.getFileContentsAsString(nextFile.getAbsolutePath()), nextFile.getName());  
+					if (fileInterpreter== null)
+						return;
+				}
+				//system.out.println("next file dropped is: " + nextFile);
+				MesquiteMessage.println("\n\nReading file " + nextFile.getName());
+				CommandRecord.tick("\n\nReading file " + nextFile.getName());
+				actUponDroppedFileContents(fileInterpreter, nextFile.getAbsolutePath());
+				count++;
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void processFileStringDroppedOnPanel(String path) {
+		String contents = MesquiteFile.getURLContentsAsString(path, -1);
+		FileInterpreter fileInterpreter =null;
+		fileInterpreter = findFileInterpreter(contents, "File Contents");  
+		if (fileInterpreter!= null)
+			actUponDroppedFileContents(fileInterpreter, path);
+
+	}
+
+	void chart(){
+		String mID = Long.toString(((FileElement)element).getID());
+		String tID = Long.toString(((CharacterData)element).getTaxa().getID());
+		MesquiteThread.addHint(new MesquiteString("CharacterValuesChart", tID));
+		MesquiteThread.addHint(new MesquiteString("CharSrcCoordObed", "#StoredCharacters"));
+		MesquiteThread.addHint(new MesquiteString("StoredCharacters", mID));
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.triggerWizard();
+
+		((BasicFileCoordinator)bfc).showChartWizard("Characters");
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.detriggerWizard();
+	}
+
+}
+/*======================================================================== */
+class MeristicMPanel extends MElementPanel {
+
+	public MeristicMPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element);
+	}
+	public String getShowMatrixIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixMeristic.gif";
+	}
+}
+/*======================================================================== */
+class CategMPanel extends MElementPanel {
+
+	public CategMPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element);
+	}
+	public String getShowMatrixIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixCateg.gif";
+	}
+}
+/*======================================================================== */
+class MolecMPanel extends MElementPanel {
+
+	public MolecMPanel(BasicFileCoordinator bfc, ClosablePanelContainer container,MesquiteWindow w,  FileElement element){
+		super(bfc, container, w,element);
+
+	}
+	public String getShowMatrixIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixMolec.gif";
+	}
+}
+/*======================================================================== */
+class ContMPanel extends MElementPanel {
+
+	public ContMPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element);
+
+	}
+	public String getShowMatrixIconFileName(){ //for small 16 pixel icon at left of main bar
+		return "matrixCont.gif";
+	}
+}
+/*======================================================================== */
+class TreesRPanel extends ElementPanel {
+
+	public TreesRPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element);
+		addCommand(false, "treeView.gif", "View\nTrees", "View Trees", new MesquiteCommand("showTreesInWindow", element));
+		addCommand(false, "trees.gif", "List &\nManage\nTrees", "List & Manage Trees", new MesquiteCommand("showMe", element));
+		addCommand(false, "chart.gif", "Chart\nTrees", "Chart Trees", new MesquiteCommand("chart", this));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Rename Trees Block", "Rename Trees Block", new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete Trees Block", "Delete Trees Block", new MesquiteCommand("deleteMe", element));
+		addCommand(true, null, "Duplicate Trees Block", "Duplicate Trees Block", new MesquiteCommand("duplicateMe", element));
+		addCommand(true, null, "Export Trees Block", "Export Trees Block", new MesquiteCommand("exportMe", element));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Edit Comment", "Edit Comment", new MesquiteCommand("editComment", element));
+		if (bfc.getProject().virginProject)
+			setOpen(true);
+		//	addCommand(true, null, "ID " + element.getID(), "ID " + element.getID(), new MesquiteCommand("id", this));
+
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return "Trees Block";
+	}
+	void chart(){
+		String mID = Long.toString(((TreeVector)element).getID());
+		String tID = Long.toString(((TreeVector)element).getTaxa().getID());
+		MesquiteThread.addHint(new MesquiteString("TreeValuesChart", tID));
+		MesquiteThread.addHint(new MesquiteString("TreeValuesChart", "#StoredTrees"));
+		MesquiteThread.addHint(new MesquiteString("StoredTrees", mID));
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.triggerWizard();
+		((BasicFileCoordinator)bfc).showChartWizard("Trees");
+		if (MesquiteDialog.useWizards)
+			MesquiteThread.detriggerWizard();
+	}
+	public String getTitleAddition(){
+		int numTrees = ((TreeVector)element).size();
+		String heading = " (" + numTrees + " tree";
+		if (numTrees>1)
+			heading += "s";
+		heading += ")";
+		return heading;
+	}
+
+	public String getNotes(){
+		if (element == null)
+			return "";
+		return Integer.toString(((TreeVector)element).size()) + " Trees";
+	}
+}
+/*======================================================================== */
+class AssocPanel extends ElementPanel {
+	public AssocPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w,element);
+		setTitle("Association: " + element.getName());
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		addCommand(true, null, "Edit Associaton", "Edit Associaton", new MesquiteCommand("showMe", element));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Rename Association", "Rename Association", new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete Association", "Delete Association", new MesquiteCommand("deleteMe", element));
+		//	addCommand(true, null, "ID " + element.getID(), "ID " + element.getID(), new MesquiteCommand("id", this));
+
+	}
+	public void resetTitle(){
+		setTitle("Association: " + element.getName());
+		repaint();
+	}
+	public int requestSpacer(){
+		return 16;
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return "Taxa Assocation";
+	}
+
+	public String getNotes(){
+		if (element == null)
+			return "";
+		return "Association between " + ((TaxaAssociation)element).getTaxa(0).getName() + " and " +  ((TaxaAssociation)element).getTaxa(1).getName();
+	}
+}
+/*======================================================================== *
+class CharModelsPanel extends ElementPanel {
+	public CharModelsPanel(BasicFileCoordinator bfc, ClosablePanelContainer container,MesquiteWindow w){
+		super(bfc, container, w,"Character Models");
+		//	setColors(ColorDistribution.veryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, Color.lightGray, Color.darkGray);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		MesquiteProject proj = bfc.getProject();
+		proj.getCentralModelListener().addListener(this);
+		refresh();
+	}
+	//PUT COMMANDS AT TOP????
+
+	public void dispose(){
+		if (bfc != null && !bfc.isDoomed())
+			bfc.getProject().getCentralModelListener().removeListener(this);
+		super.dispose();
+	}
+	public String getNotes(){
+		return null;
+	}
+	public boolean upToDate(){
+		int e = 0;
+		MesquiteProject proj = bfc.getProject();
+		for (int i=0; i<proj.getNumModels(); i++){
+			CharacterModel m = proj.getCharacterModel(i);
+			if (!m.isBuiltIn() && m.isUserVisible()){
+				if (e>= subPanels.size())
+					return false;
+				ElementPanel panel = ((ElementPanel)subPanels.elementAt(e));
+				if (panel.element != m)
+					return false;
+				panel.resetTitle();
+				panel.repaint();
+				e++;
+			}
+		}
+		if (e<subPanels.size())
+			return false;
+		return true;
+	}
+	public void refresh(){
+		if (upToDate()) {
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			return;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		subPanels.removeAllElements();
+		MesquiteProject proj = bfc.getProject();
+		for (int i=0; i<proj.getNumModels(); i++){
+			CharacterModel m = proj.getCharacterModel(i);
+			if (!m.isBuiltIn() && m.isUserVisible()){
+				CharModelPanel panel = null;
+				addExtraPanel(panel = new CharModelPanel((BasicFileCoordinator)bfc, this, w,m), false);
+				panel.setBounds(0, 0, 0, 0);
+			}
+		}
+	}
+	public int requestSpacer(){
+		return 16;
+	}
+
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel){
+		return null;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+
+		refresh();
+	}
+}
+/*======================================================================== *
+class GroupPanel extends ElementPanel {
+	GroupLabel e;
+	public GroupPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, GroupLabel e){
+		super(bfc, container, w, e);
+		setShowTriangle(false);
+		this.e = e;
+		addCommand(true, null, "Edit Group", "Edit Group", new MesquiteCommand("showMe", e));
+		addCommand(true, null, "Delete Group", "Delete Group", new MesquiteCommand("deleteMe", e));
+		//	setColors(ColorDistribution.veryVeryVeryLightGray, e.getColor(), ColorDistribution.veryVeryVeryLightGray, Color.black);
+	}
+	public String getElementTypeName(){ 
+		return "Group";
+	}
+	public void setColors(Color bgTopColor, Color bgBottomColor, Color barColor, Color textColor){
+		setBackground(bgBottomColor);
+		if (e != null)
+			setBgTopColor(e.getColor());
+		this.bgBottomColor = bgBottomColor;
+		this.barColor = barColor;
+	}
+	public void setBgTopColor(Color bgTopColor){
+		this.bgTopColor = bgTopColor;
+		float[] hsb = new float[3];
+		hsb[0]=hsb[1]=hsb[2]= 1;
+		if (bgTopColor == null)
+			this.textColor = Color.black;
+		else {
+			Color.RGBtoHSB(bgTopColor.getRed(), bgTopColor.getGreen(), bgTopColor.getBlue(), hsb);
+			if (hsb[2]>0.5)
+				this.textColor = Color.black;
+			else
+				this.textColor = Color.white;
+		}
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == element && element != null) {
+			resetTitle();
+			if (getBgTopColor() == null ||  !getBgTopColor().equals(((GroupLabel)element).getColor())){
+				setBgTopColor(((GroupLabel)element).getColor());
+			}
+			repaint();
+		}
+	}
+
+}
+/*======================================================================== *
+class GroupsPanel extends ElementPanel {
+	MesquiteWindow w= null;
+	public GroupsPanel(BasicFileCoordinator bfc, ClosablePanelContainer container,MesquiteWindow w,  ListableVector v){
+		super(bfc, container, w, v);
+		this.w=w;
+		//	setColors(ColorDistribution.veryVeryLightGray, ColorDistribution.veryVeryVeryLightGray, Color.lightGray, Color.darkGray);
+		setColors(ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceElement(), ColorTheme.getExtInterfaceTextMedium());
+		refresh();
+	}
+	//PUT COMMANDS AT TOP????
+
+	public boolean upToDate(){
+		int e = 0;
+		ListableVector v = (ListableVector)element;
+		if (v==null) return false;
+		for (int i=0; i<v.size(); i++){
+			GroupLabel m = (GroupLabel)v.elementAt(i);
+			if (e>= subPanels.size())
+				return false;
+			ElementPanel panel = ((ElementPanel)subPanels.elementAt(e));
+			if (panel.element != m)
+				return false;
+			panel.resetTitle();
+			if (panel.getBgTopColor() == null ||  !panel.getBgTopColor().equals(m.getColor())){
+				panel.setBgTopColor(m.getColor());
+			}
+			panel.repaint();
+			e++;
+
+		}
+		if (e<subPanels.size())
+			return false;
+		return true;
+	}
+	static int countt = 0;
+	public void refresh(){
+		if (upToDate()) {
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			return;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		subPanels.removeAllElements();
+		ListableVector v = (ListableVector)element;
+		if (v!=null)
+			for (int i=0; i<v.size(); i++){
+				GroupLabel m = (GroupLabel)v.elementAt(i);
+
+				ElementPanel panel = null;
+				addExtraPanel(panel = new GroupPanel((BasicFileCoordinator)bfc, this, w,m), false);
+				panel.setBounds(0, 0, 0, 0);
+			}
+	}
+	public int requestSpacer(){
+		return 12;
+	}
+
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel){
+		return null;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+
+		refresh();
+	}
+}/*======================================================================== */
+
+/*======================================================================== *
+class CharModelPanel extends ElementPanel {
+
+	public CharModelPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w,element);
+		addCommand(true, null, "Edit Model", "Edit Model", new MesquiteCommand("editMe", element));
+		addCommand(true, null, "Rename Model", "Rename Model", new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete Model", "Delete Model", new MesquiteCommand("deleteMe", element));
+		addCommand(true, null, "-", "-", null);
+		addCommand(true, null, "Edit Comment", "Edit Comment", new MesquiteCommand("editComment", element));
+		//	addCommand(true, null, "ID " + element.getID(), "ID " + element.getID(), new MesquiteCommand("id", this));
+
+	}
+	public String getElementTypeName(){ 
+		if (element instanceof CharacterModel)
+			return ((CharacterModel)element).getTypeName();
+		return "Character Model";
+	}
+
+	public String getNotes(){
+		return null; //applicability
+	}
+}
+/*======================================================================== *
+class SpecsSetVectorPanel extends ElementPanel {  
+	private SpecsSetVector ssv;
+	public SpecsSetVectorPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, SpecsSetVector element, String name){
+		super(bfc, container, w,name);
+		ssv = (SpecsSetVector)element;
+		currentHeight = MINHEIGHT + 20;
+		for (int k=0; k<ssv.size(); k++){
+			FileElement fe = (FileElement)ssv.elementAt(k);
+			fe.addListener(this);
+		}
+		refresh();
+	}
+	public boolean upToDate(){
+		int e = 0;
+		if (ssv == null)
+			return true;
+
+		for (int k=0; k<ssv.size(); k++){
+			if (e>= subPanels.size())
+				return false;
+			ElementPanel panel = ((ElementPanel)subPanels.elementAt(e));
+			FileElement fe = (FileElement)ssv.elementAt(k);
+			if (panel.element != fe)
+				return false;
+
+			if (!StringUtil.stringsEqual(panel.element.getName(), panel.getTitle())){
+				panel.setTitle(panel.element.getName());
+			}
+			e++;
+		}
+
+
+		if (e<subPanels.size())
+			return false;
+		return true;
+	}
+	public void setColors(Color bgTopColor, Color bgBottomColor, Color barColor, Color textColor){
+		super.setColors(bgTopColor, bgBottomColor, barColor, textColor);
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			panel.setColors(bgBottomColor, bgBottomColor, bgBottomColor, textColor);
+		}
+	}
+	public void refresh(){
+		if (upToDate()) {
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			return;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		subPanels.removeAllElements();
+		ElementPanel panel;
+		for (int k=0; k<ssv.size(); k++){
+			FileElement fe = (FileElement)ssv.elementAt(k);
+			addExtraPanel(panel = new SpecsSetPanel((BasicFileCoordinator)bfc, this, w,fe), false);
+			panel.setBounds(0, 0, 0, 0);
+			panel.setColors(bgBottomColor, bgBottomColor, bgBottomColor, textColor);
+		}
+
+
+	}
+	public void dispose(){
+		if (ssv != null){
+			for (int k=0; k<ssv.size(); k++){
+				FileElement fe = (FileElement)ssv.elementAt(k);
+				fe.removeListener(this);
+			}
+
+		}
+		super.dispose();
+	}
+
+}
+/*======================================================================== *
+class SpecsSetPanel extends ElementPanel {
+	SpecsSet s;
+	public SpecsSetPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w,  FileElement element){
+		super(bfc, container, w, element);
+		s = (SpecsSet)element;
+		addCommand(true, null, "Rename " + s.getTypeName(), "Rename " + s.getTypeName(), new MesquiteCommand("renameMe", element));
+		addCommand(true, null, "Delete " + s.getTypeName(), "Delete " + s.getTypeName(), new MesquiteCommand("deleteMe", element));
+		currentHeight = MINHEIGHT + 20;
+	}
+	public String getNotes(){
+		if (s == null)
+			return null;
+		return s.getTypeName();
+	}
+	public String getElementTypeName(){ 
+		if (element instanceof SpecsSet)
+			return ((SpecsSet)element).getTypeName();
+		return null;
+	}
+
+}
+
+/*======================================================================== */
+class ElementPanel extends ProjPanelPanel {
+	Listable element;
+
+	public ElementPanel(BasicFileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, FileElement element){
+		super(bfc, container, w, element.getName(), bfc);
+		notes.setString(getNotes());
+		this.element = element;
+		if (element.getName() == null)
+			setTitle(element.getClass().getName());
+		setOpen(element.getResourcePanelIsOpen());
+		if (element !=null)
+			element.addListener(this);
+		/*if (element != null){
+			Vector vv = ((FileElement)element).getSpecSetsVectorVector();
+			if (vv != null)
+				for (int i=0; i<vv.size(); i++){
+					SpecsSetVector v = (SpecsSetVector)vv.elementAt(i);
+					v.addListener(this);
+				}
+		}*/
+		refreshIcon();
+		refresh();
+	}
+	public String getFootnoteHeading(){
+		if (element instanceof FileElement){
+			String an = ((FileElement)element).getAnnotation();
+			if (StringUtil.blank(an))
+				return null;
+			String text = ((FileElement)element).getTypeName();
+			if (element.getName() != null)
+				text += ":  " + element.getName();
+			return text;
+		}
+		return null;
+	}
+	public String getFootnote(){
+		if (element instanceof FileElement){
+			String an = ((FileElement)element).getAnnotation();
+			return an;
+		}
+		return null;
+	}
+	public String getTitle(){
+		String t = super.getTitle() + getTitleAddition();
+		return t;
+	}
+	public String getIconFileName(){ //for small 16 pixel icon at left of main bar
+		if (element != null && element instanceof FileElement){
+			String s = ((FileElement)element).getIconFileName();
+			return s;
+		}
+		return null;
+	}
+
+	public ElementPanel(FileCoordinator bfc, ClosablePanelContainer container, MesquiteWindow w, String name){
+		super(bfc, container, w, name, bfc);
+	}
+	public void resetTitle(){
+		if (element != null && element instanceof FileElement){
+			String newTitle = "";
+			if (element.getName() == null)
+				newTitle = element.getClass().getName();
+			else
+				newTitle = element.getName();
+			if (!StringUtil.stringsEqual(newTitle, getTitle())){
+				setTitle(newTitle);
+				repaint();
+			}
+		}
+	}
+
+	public String getTitleAddition(){
+		return "";
+	}
+	/*.................................................................................................................*/
+	public String getElementTypeName(){ 
+		return null;
+	}
+	public boolean upToDate(){
+		/*int e = 0;
+		if (element != null && element instanceof FileElement){
+			Vector vv = ((FileElement)element).getSpecSetsVectorVector();
+			if (vv != null)
+				for (int i=0; i<vv.size(); i++){
+					if (e>= subPanels.size())
+						return false;
+					SpecsSetVector v = (SpecsSetVector)vv.elementAt(i);
+					if (v.size()>0){
+						ElementPanel panel = ((ElementPanel)subPanels.elementAt(e));
+						if (panel.element != v)
+							return false;
+						e++;
+					}
+				}
+		}
+		if (e<subPanels.size())
+			return false;*/
+		return true;
+	}
+	public boolean checkSize(){
+		ProjectWindow pw = (ProjectWindow)w;
+		if (pw == null)
+			return true;
+		ProjectPanel pp = pw.projPanel;
+	
+		Component c = this;
+		int x = 0;
+		while (!(c instanceof ProjectPanel)){
+			x += c.getX();
+			c = c.getParent();
+			if (c == null)
+				return true;
+		}
+		if (pp == null)
+			return true;
+		int extent = x + getWidth();
+		if (extent != pp.getWidth()){
+			setSize(getWidth() - (extent - pp.getWidth()), getHeight());
+			return false;
+		}
+		return true;
+	}
+	public void paint(Graphics g){
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!checkSize()){
+			MesquiteWindow.uncheckDoomed(this);
+			repaint();
+			return;
+		}
+		super.paint(g);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void refresh(){
+		if (upToDate()) {
+			resetSizes(getWidth(), getHeight());
+			repaintAllPanels();
+			return;
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			remove(panel);
+			panel.dispose();
+		}
+		subPanels.removeAllElements();
+		/*if (element != null && element instanceof FileElement){
+			Vector vv = ((FileElement)element).getSpecSetsVectorVector();
+			if (vv != null){
+				ElementPanel panel;
+				for (int i=0; i<vv.size(); i++){
+					SpecsSetVector v = (SpecsSetVector)vv.elementAt(i);
+					if (v.size()>0){
+						addExtraPanel(panel = new SpecsSetVectorPanel((BasicFileCoordinator)bfc, this,w, v, v.getTypeName()), false);
+						panel.setBounds(0, 0, 0, 0);
+						panel.setColors(bgBottomColor, bgBottomColor, bgBottomColor, textColor);
+					}
+				}
+			}
+		}*/
+	}
+	public Listable getElement(){
+		return element;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == element && element != null) {
+			setTitle(element.getName());
+			notes.setString(getNotes());
+			repaint();
+		}
+		else {
+			refresh();
+		}
+	}
+
+
+	protected String getMenuHeading(){
+		String heading = getTitle();
+		if (getElementTypeName() != null)
+			heading = getElementTypeName() + ": " + heading;
+		return heading;
+	}
+
+	public void dispose(){
+		if (popup!=null)
+			remove(popup);
+		if (element != null && element instanceof FileElement){
+			((FileElement)element).removeListener(this);
+			((FileElement)element).setResourcePanelIsOpen(isOpen());
+			/*Vector vv = ((FileElement)element).getSpecSetsVectorVector();
+			if (vv != null){
+				for (int i=0; i<vv.size(); i++){
+					SpecsSetVector v = (SpecsSetVector)vv.elementAt(i);
+					v.removeListener(this);
+				}
+			}*/
+		}
+		for (int i = 0; i<subPanels.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)subPanels.elementAt(i));
+			panel.dispose();
+		}
+		super.dispose();
+	}
+
+}
+
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/index.html b/Source/mesquite/minimal/BasicFileCoordinator/index.html
new file mode 100644
index 0000000..7b655d6
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/index.html
@@ -0,0 +1,28 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Basic package</title>
+	</head>
+
+	<body bgcolor="#ffffcc">
+		<img height="64" width="164" src="splash.gif">
+		
+<h2>Basic packages of modules for Mesquite</h2>
+		<h4>W. & D. Maddison</h4>
+		
+<p>There more than 170 modules in the basic packages, not including specialized 
+  ones in the parsimony and search packages. Documentation is not yet written 
+  for these modules, although you can learn about them by using the Installed 
+  Modules menu item in the Help menu when Mesquite is running. You are strongly 
+  encouraged to view the example data files distributed with Mesquite for information 
+  about how to perform basic functions.</p>
+		<p>
+		<hr>
+		</p>
+		<p>© Wayne Maddison and David Maddison, 1999-2001
+	</body>
+
+</html>
+
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/base.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/base.html
new file mode 100644
index 0000000..14e9cdd
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/base.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Project Window</title>
+</head>
+
+<body>
+<p><font face="Arial">Project with home file @HOMEFILENAME</font></p>
+<p><font face="Arial" size = "-1">Location: in directory <a href = "showDirectory:">@HOMEDIRECTORYPATH</a></font></p>
+
+ at TAXABLOCKSECTION
+
+</body>
+</html>
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseMatrix.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseMatrix.html
new file mode 100644
index 0000000..70b0694
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseMatrix.html
@@ -0,0 +1,33 @@
+      <!-- START of MATRIX SECTION -->
+      <tr><td><p><font face="Arial" size = "-1"><em>Character Matrix</em></font></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+            <strong>@MATRIXNAME</strong><br>
+            @NUMBEROFCHARACTERS<br>
+            @TYPEOFMATRIX<br>
+            <br><a href="renameMatrix:@MATRIXID"><img border = 0 src="rename.gif"></a> <a href="deleteMatrix:@MATRIXID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="showMatrix:@MATRIXID"><img border = 0 src="@MATRIXICON" width="40" height="42"></a></td>
+            <td width="120"><p><a href="showMatrix:@MATRIXID"><font face="Arial" size = "-1">View &
+            Edit<br>Matrix</font></a></p>              </td>
+            
+            <td width="40"><a href="listMatrix:@MATRIXID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listMatrix:@MATRIXID"><font face="Arial" size = "-1">List &
+            Manage<br>Characters</font></a></p>              </td>
+            
+            <td width="40"><a href="chartCharacters:@MATRIXID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartCharacters:@MATRIXID"><font face="Arial" size = "-1">Chart<br>
+            Characters</font></a></p>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of MATRIX SECTION -->
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTaxaBlock.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTaxaBlock.html
new file mode 100644
index 0000000..9396145
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTaxaBlock.html
@@ -0,0 +1,46 @@
+<!-- START of TAXA BLOCK SECTION -->
+<table width="100%" border="1" cellpadding="0" cellspacing="4" bgcolor="#777777">
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%" border="0">
+      <tr><td><p><font face="Arial" size = "-1"><em>Block of Taxa</em></font></p></td>
+      </tr><tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%" border="0">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+                <strong>@TAXABLOCKNAME</strong><br>
+            @NUMBEROFTAXA<br>
+            <br><a href="renameTaxa:@TAXABLOCKID"><img border = 0 src="rename.gif"></a> <a href="deleteTaxa:@TAXABLOCKID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="320">
+          <tr>
+            <td width="40"><a href="listTaxa:@TAXABLOCKID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listTaxa:@TAXABLOCKID"><font face="Arial" size = "-1">List &
+            Manage<br>Taxa</font></a></p>              </td>
+            <td width="40"><a href="chartTaxa:@TAXABLOCKID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartTaxa:@TAXABLOCKID"><font face="Arial" size = "-1">Chart<br>
+            Taxa</font></a></p>              </td>
+          </tr>
+        </table></td>
+      </tr>
+    </table></td>
+  </tr>
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%" border="0">
+     @MATRIXSECTION
+      
+     
+      </table></td>
+  </tr>
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%" border="0">
+      
+     @TREESBLOCKSECTION
+     
+      </table></td>
+  </tr>
+</table>
+<br>
+<!-- END of TAXA BLOCK SECTION -->
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTreesBlock.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTreesBlock.html
new file mode 100644
index 0000000..f2b743a
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/baseTreesBlock.html
@@ -0,0 +1,33 @@
+
+      <!-- START of TREES BLOCK SECTION -->
+      <tr><td><p><font face="Arial" size = "-1"><em>Block of Trees</em></font></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+            <strong>@TREESBLOCKNAME</strong><br>
+            @NUMBEROFTREES<br>
+            <br><a href="renameTrees:@TREESBLOCKID"><img border = 0 src="rename.gif"></a> <a href="deleteTrees:@TREESBLOCKID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="viewTrees:@TREESBLOCKID"><img border = 0 src="treeView.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="viewTrees:@TREESBLOCKID"><font face="Arial" size = "-1">View, Explore &<br>
+            Edit Trees</font></a></p>              </td>
+            
+            <td width="40"><a href="listTrees:@TREESBLOCKID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listTrees:@TREESBLOCKID"><font face="Arial" size = "-1">List &
+            Manage<br>Trees</font></a></p>              </td>
+            
+            <td width="40"><a href="chartTrees:@TREESBLOCKID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartTrees:@TREESBLOCKID"><font face="Arial" size = "-1">Chart<br>
+            Trees</font></a></p>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of TREES BLOCK SECTION -->
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/charModelSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/charModelSmall.gif
new file mode 100644
index 0000000..afebf98
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/charModelSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/chart.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/chart.gif
new file mode 100644
index 0000000..17ea188
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/chart.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/delete.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/delete.gif
new file mode 100644
index 0000000..ffcb78f
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/delete.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileInclude.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileInclude.gif
new file mode 100644
index 0000000..8cc75d7
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileInclude.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeBasic.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeBasic.gif
new file mode 100644
index 0000000..1202e85
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeBasic.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeTrees.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeTrees.gif
new file mode 100644
index 0000000..50acb7b
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileIncludeTrees.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLink.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLink.gif
new file mode 100644
index 0000000..cb9ac68
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLink.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkTrees.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkTrees.gif
new file mode 100644
index 0000000..43af4e3
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkTrees.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkedSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkedSmall.gif
new file mode 100644
index 0000000..dcbdf22
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileLinkedSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileMergeTM.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileMergeTM.gif
new file mode 100644
index 0000000..ed7d67d
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileMergeTM.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileSmall.gif
new file mode 100644
index 0000000..3fac282
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/fileSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/list.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/list.gif
new file mode 100644
index 0000000..7463294
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/list.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCateg.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCateg.gif
new file mode 100644
index 0000000..1a8d84f
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCateg.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmall.gif
new file mode 100644
index 0000000..f295bb5
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallINREPOSITORY.gif
new file mode 100644
index 0000000..6aa2eef
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..8e65944
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCategSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCont.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCont.gif
new file mode 100644
index 0000000..f5742ca
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixCont.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmall.gif
new file mode 100644
index 0000000..d03a698
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallINREPOSITORY.gif
new file mode 100644
index 0000000..5943d21
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..f26d942
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixContSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristic.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristic.gif
new file mode 100644
index 0000000..961b2c0
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristic.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmall.gif
new file mode 100644
index 0000000..1c91d16
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallINREPOSITORY.gif
new file mode 100644
index 0000000..8e23b1c
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..071664c
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMeristicSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolec.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolec.gif
new file mode 100644
index 0000000..67a26de
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolec.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmall.gif
new file mode 100644
index 0000000..f1bedc9
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallINREPOSITORY.gif
new file mode 100644
index 0000000..4c341a9
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..abb53ff
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/matrixMolecSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/project.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/project.html
new file mode 100644
index 0000000..87b8e22
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/project.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Project Window</title>
+<style type="text/css">
+<!--
+.style2 {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 12px;
+	margin-bottom: 2px;
+	margin-top: 10px;
+
+}
+-->
+</style>
+<style type="text/css">
+<!--
+.style3 {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 18px;
+}
+-->
+</style>
+</head>
+
+<body>
+<p class="style3">Project with home file @HOMEFILENAME</p>
+<p class="style2">Location: in directory <a href = "showDirectory:">@HOMEDIRECTORYPATH</a></p>
+
+<!-- START of TAXA BLOCK SECTION -->
+<table width="100%" border="0" cellpadding="0" cellspacing="4" bgcolor="#777777">
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%">
+      <tr><td><p class="style2"><em>Block of Taxa</em></p></td>
+      </tr><tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p class="style2">
+                <strong>@TAXABLOCKNAME</strong><br />
+            @NUMBEROFTAXA<br />
+            <br /><a href="renameTaxa:@TAXABLOCKID"><img src="rename.gif" /></a> <a href="deleteTaxa:@TAXABLOCKID"><img src="delete.gif" /></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="320">
+          <tr>
+            <td width="40"><a href="listTaxa:@TAXABLOCKID"><img src="list.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="listTaxa:@TAXABLOCKID"><p class="style2">List &
+            Manage<br />Taxa</p></a>              </td>
+            <td width="40"><a href="chartTaxa:@TAXABLOCKID"><img src="chart.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="chartTaxa:@TAXABLOCKID"><p class="style2">Chart<br />
+            Taxa</p></a>              </td>
+          </tr>
+        </table></td>
+      </tr>
+    </table></td>
+  </tr>
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%">
+      <!-- START of MATRIX SECTION -->
+      <tr><td><p class="style2"><em>Character Matrix</em></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p class="style2">
+            <strong>@MATRIXNAME</strong><br />
+            @NUMBEROFCHARACTERS<br />
+            @TYPEOFMATRIX<br />
+            <br /><a href="renameMatrix:@MATRIXID"><img src="rename.gif" /></a> <a href="deleteMatrix:@MATRIXID"><img src="delete.gif" /></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="showMatrix:@MATRIXID"><img src="matrixCateg.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="showMatrix:@MATRIXID"><p class="style2">View &
+            Edit<br />Matrix</p></a>              </td>
+            
+            <td width="40"><a href="listMatrix:@MATRIXID"><img src="list.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="listMatrix:@MATRIXID"><p class="style2">List &
+            Manage<br />Characters</p></a>              </td>
+            
+            <td width="40"><a href="chartCharacters:@MATRIXID"><img src="chart.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="chartCharacters:@MATRIXID"><p class="style2">Chart<br />
+            Characters</p></a>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of MATRIX SECTION -->
+      
+       
+      <!-- START of TREES BLOCK SECTION -->
+      <tr><td><p class="style2"><em>Block of Trees</em></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p class="style2">
+            <strong>@TREESBLOCKNAME</strong><br />
+            @NUMBEROFTREES<br />
+            <br /><a href="renameTrees:@TREESBLOCKID"><img src="rename.gif" /></a> <a href="deleteTrees:@TREESBLOCKID"><img src="delete.gif" /></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="viewTrees:@TREESBLOCKID"><img src="treeView.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="viewTrees:@TREESBLOCKID"><p class="style2">View, Explore &<br />
+            Edit Trees</p></a>              </td>
+            
+            <td width="40"><a href="listTrees:@TREESBLOCKID"><img src="list.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="listTrees:@TREESBLOCKID"><p class="style2">List &
+            Manage<br />Trees</p></a>              </td>
+            
+            <td width="40"><a href="chartTrees:@TREESBLOCKID"><img src="chart.gif" width="40" height="42" /></a></td>
+            <td width="120"><a href="chartTrees:@TREESBLOCKID"><p class="style2">Chart<br />
+            Trees</p></a>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of TREES BLOCK SECTION -->
+     
+      </table></td>
+  </tr>
+</table>
+<br />
+<!-- END of TAXA BLOCK SECTION -->
+
+
+</body>
+</html>
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectPanel.jpg b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectPanel.jpg
new file mode 100644
index 0000000..198f645
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectPanel.jpg differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectSimple.html b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectSimple.html
new file mode 100644
index 0000000..c5b36ff
--- /dev/null
+++ b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/projectSimple.html
@@ -0,0 +1,117 @@
+<html>
+<head>
+<title>Project Window</title>
+</head>
+
+<body>
+<p><font face="Arial">Project with home file @HOMEFILENAME</font></p>
+<p><font face="Arial" size = "-1">Location: in directory <a href = "showDirectory:">@HOMEDIRECTORYPATH</a></font></p>
+
+<!-- START of TAXA BLOCK SECTION -->
+<table width="100%" border="1" cellpadding="0" cellspacing="4" bgcolor="#777777">
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%" border="0">
+      <tr><td><p><font face="Arial" size = "-1"><em>Block of Taxa</em></font></p></td>
+      </tr><tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%" border="0">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+                <strong>@TAXABLOCKNAME</strong><br>
+            @NUMBEROFTAXA<br>
+            <br><a href="renameTaxa:@TAXABLOCKID"><img border = 0 src="rename.gif"></a> <a href="deleteTaxa:@TAXABLOCKID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="320">
+          <tr>
+            <td width="40"><a href="listTaxa:@TAXABLOCKID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listTaxa:@TAXABLOCKID"><font face="Arial" size = "-1">List &
+            Manage<br>Taxa</font></a></p>              </td>
+            <td width="40"><a href="chartTaxa:@TAXABLOCKID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartTaxa:@TAXABLOCKID"><font face="Arial" size = "-1">Chart<br>
+            Taxa</font></a></p>              </td>
+          </tr>
+        </table></td>
+      </tr>
+    </table></td>
+  </tr>
+  <tr>
+    <td bgcolor="#dddddd"><table width="100%" border="0">
+      <!-- START of MATRIX SECTION -->
+      <tr><td><p><font face="Arial" size = "-1"><em>Character Matrix</em></font></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+            <strong>@MATRIXNAME</strong><br>
+            @NUMBEROFCHARACTERS<br>
+            @TYPEOFMATRIX<br>
+            <br><a href="renameMatrix:@MATRIXID"><img border = 0 src="rename.gif"></a> <a href="deleteMatrix:@MATRIXID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="showMatrix:@MATRIXID"><img border = 0 src="@MATRIXICON" width="40" height="42"></a></td>
+            <td width="120"><p><a href="showMatrix:@MATRIXID"><font face="Arial" size = "-1">View &
+            Edit<br>Matrix</font></a></p>              </td>
+            
+            <td width="40"><a href="listMatrix:@MATRIXID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listMatrix:@MATRIXID"><font face="Arial" size = "-1">List &
+            Manage<br>Characters</font></a></p>              </td>
+            
+            <td width="40"><a href="chartCharacters:@MATRIXID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartCharacters:@MATRIXID"><font face="Arial" size = "-1">Chart<br>
+            Characters</font></a></p>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of MATRIX SECTION -->
+      
+       
+      <!-- START of TREES BLOCK SECTION -->
+      <tr><td><p><font face="Arial" size = "-1"><em>Block of Trees</em></font></p></td>
+      </tr>
+      <tr>
+        <td bgcolor="#EEEEEE" width="200"><table width="100%">
+          <tr>
+            
+            <td width="78%"><p><font face="Arial" size = "-1">
+            <strong>@TREESBLOCKNAME</strong><br>
+            @NUMBEROFTREES<br>
+            <br><a href="renameTrees:@TREESBLOCKID"><img border = 0 src="rename.gif"></a> <a href="deleteTrees:@TREESBLOCKID"><img border = 0 src="delete.gif"></font></p>
+              </td>
+          </tr>
+        </table></td>
+        <td><table width="480">
+          <tr>
+            <td width="40"><a href="viewTrees:@TREESBLOCKID"><img border = 0 src="treeView.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="viewTrees:@TREESBLOCKID"><font face="Arial" size = "-1">View, Explore &<br>
+            Edit Trees</font></a></p>              </td>
+            
+            <td width="40"><a href="listTrees:@TREESBLOCKID"><img border = 0 src="list.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="listTrees:@TREESBLOCKID"><font face="Arial" size = "-1">List &
+            Manage<br>Trees</font></a></p>              </td>
+            
+            <td width="40"><a href="chartTrees:@TREESBLOCKID"><img border = 0 src="chart.gif" width="40" height="42"></a></td>
+            <td width="120"><p><a href="chartTrees:@TREESBLOCKID"><font face="Arial" size = "-1">Chart<br>
+            Trees</font></a></p>              </td>
+            
+          </tr>
+        </table></td>
+      </tr>
+      <!-- END of TREES BLOCK SECTION -->
+     
+      </table></td>
+  </tr>
+</table>
+<br>
+<!-- END of TAXA BLOCK SECTION -->
+
+
+</body>
+</html>
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/queryGray.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/queryGray.gif
new file mode 100644
index 0000000..324e0bd
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/queryGray.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/rename.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/rename.gif
new file mode 100644
index 0000000..059a381
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/rename.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmall.gif
new file mode 100644
index 0000000..18b3dc8
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallINREPOSITORY.gif
new file mode 100644
index 0000000..9123137
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..404b99e
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaAssocSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlock.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlock.gif
new file mode 100644
index 0000000..3f8f463
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlock.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmall.gif
new file mode 100644
index 0000000..c1293a2
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallINREPOSITORY.gif
new file mode 100644
index 0000000..5f90c69
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..76121b2
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/taxaBlockSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treeView.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treeView.gif
new file mode 100644
index 0000000..817ffa6
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treeView.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/trees.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/trees.gif
new file mode 100644
index 0000000..641e1af
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/trees.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmall.gif
new file mode 100644
index 0000000..88b3051
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmall.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallINREPOSITORY.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallINREPOSITORY.gif
new file mode 100644
index 0000000..97d0580
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallINREPOSITORY.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallUNCOMMITTED.gif b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallUNCOMMITTED.gif
new file mode 100644
index 0000000..7e95508
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/projectHTML/treesSmallUNCOMMITTED.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/splash.gif b/Source/mesquite/minimal/BasicFileCoordinator/splash.gif
new file mode 100644
index 0000000..1808b1a
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/splash.gif differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/splash.gif copy b/Source/mesquite/minimal/BasicFileCoordinator/splash.gif copy
new file mode 100644
index 0000000..7fdbce1
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/splash.gif copy differ
diff --git a/Source/mesquite/minimal/BasicFileCoordinator/splashSmall.gif b/Source/mesquite/minimal/BasicFileCoordinator/splashSmall.gif
new file mode 100644
index 0000000..09460ab
Binary files /dev/null and b/Source/mesquite/minimal/BasicFileCoordinator/splashSmall.gif differ
diff --git a/Source/mesquite/minimal/Defaults/Defaults.java b/Source/mesquite/minimal/Defaults/Defaults.java
new file mode 100644
index 0000000..d1a761c
--- /dev/null
+++ b/Source/mesquite/minimal/Defaults/Defaults.java
@@ -0,0 +1,574 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.Defaults;
+/*~~  */
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.InterfaceManager;
+import mesquite.stochchar.lib.MargLikelihoodForModel;
+
+/** Controls some of Mesquite's default settings (like fonts in windows). */
+
+public class Defaults extends MesquiteInit  {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Defaults";
+	}
+	/** returns the URL of the notices file for this module so that it can phone home and check for messages */
+	public String  getHomePhoneNumber(){ 
+		String pre = "";
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease())
+			pre = "_PRERELEASE";
+		return "http://mesquiteproject.org/mesquite/contact/mesquiteStartup?buildNumber=" + getBuildNumber()+pre;
+	}
+	public String getExplanation() {
+		return "Supervises some Mesquite-wide defaults";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(DefaultsAssistant.class, "Modules are used to assist with setting defaults.",
+		"The defaults are presented in the Defaults submenu of the File menu.");
+	}
+	/*.................................................................................................................*/
+	MesquiteBoolean respectFileSpecificResourceWidth, useOtherChoices, console, askSeed, errorReports, useReports, suppressXORMode,  taxonTruncTrees, taxonT0Trees, tabbedWindows, debugMode, wizards, logAll, phoneHome, secondaryChoicesOnInDialogs, subChoicesOnInDialogs, tilePopouts; //, useDotPrefs
+	MesquiteString themeName;
+	StringArray themes;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		useOtherChoices = new MesquiteBoolean(false);
+		askSeed = new MesquiteBoolean(false);
+		console = new MesquiteBoolean(MesquiteTrunk.mesquiteTrunk.logWindow.isConsoleMode());
+		logAll = new MesquiteBoolean(MesquiteCommand.logEverything);
+		suppressXORMode = new MesquiteBoolean(false);
+		wizards = new MesquiteBoolean(MesquiteDialog.useWizards);
+		tabbedWindows = new MesquiteBoolean(MesquiteWindow.compactWindows);
+		//tilePopouts = new MesquiteBoolean(MesquiteFrame.popIsTile);
+		taxonTruncTrees = new MesquiteBoolean(true);
+		taxonT0Trees = new MesquiteBoolean(true);
+		debugMode = new MesquiteBoolean(false);
+		phoneHome = new MesquiteBoolean(MesquiteTrunk.phoneHome);
+		errorReports = new MesquiteBoolean(MesquiteTrunk.reportErrors);
+		useReports = new MesquiteBoolean(MesquiteTrunk.reportUse);
+		secondaryChoicesOnInDialogs = new MesquiteBoolean(true);
+		subChoicesOnInDialogs = new MesquiteBoolean(true);
+		respectFileSpecificResourceWidth = new MesquiteBoolean(MesquiteFrame.respectFileSpecificResourceWidth);
+		//useDotPrefs = new MesquiteBoolean(MesquiteModule.prefsDirectory.toString().indexOf(".Mesquite_Prefs")>=0);
+		loadPreferences();
+		EmployerEmployee.useOtherChoices = useOtherChoices.getValue();
+		EmployerEmployee.secondaryChoicesOnInDialogs = secondaryChoicesOnInDialogs.getValue();
+		EmployerEmployee.subChoicesOnInDialogs = subChoicesOnInDialogs.getValue();
+		RandomBetween.askSeed = askSeed.getValue();
+		MesquiteTrunk.defaultsSubmenu = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.fileMenu, "Defaults");
+		MesquiteTrunk.defaultsSubmenu.setFilterable(false);
+		MesquiteTrunk.setupSubmenu = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.fileMenu, "Setup");
+		MesquiteTrunk.setupSubmenu.setFilterable(false);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Open Windows as Tabs", makeCommand("toggleTabbedWindows",  this), tabbedWindows);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Use Wizard-style Dialogs", makeCommand("toggleWizards",  this), wizards);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Check for Notices on Mesquite Web Site", makeCommand("togglePhoneHome",  this), phoneHome);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Send Error Reports to Mesquite Server", makeCommand("toggleErrorReports",  this), errorReports);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Send Usage Reports to Mesquite Server", makeCommand("toggleUseReports",  this), useReports);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Use Log Window for Commands", makeCommand("toggleConsoleMode",  this), console);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Log All Commands", makeCommand("toggleLogAll",  this), logAll);
+		MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Previous Logs Saved...", makeCommand("setNumPrevLog",  this));
+		
+		
+		MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "-", null);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Use \"Other Choices\" for Secondary Choices", makeCommand("toggleOtherChoices",  this), useOtherChoices);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Secondary Choices Shown By Default in Dialog Boxes", makeCommand("toggleSecondaryChoicesOnInDialogs",  this), secondaryChoicesOnInDialogs);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Show Subchoices in Module Dialogs", makeCommand("toggleSubChoicesOnInDialogs",  this), subChoicesOnInDialogs);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Use Stored Characters/Matrices by Default", makeCommand("toggleStoredAsDefault",  this), CharacterSource.storedAsDefault);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Close Calculations if Matrices Used are Deleted (req. restart)", makeCommand("toggleCloseIfMatrixDeleted",  this), CharacterSource.closeIfMatrixDeleted);
+//		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Close Tree Window if Tree Block Used is Deleted", makeCommand("toggleCloseIfTreeBlockDeleted",  this), TreeSource.closeIfTreeBlockDeleted);
+		MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "-", null);
+		if (!MesquiteTrunk.isMacOSX())
+			MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Forget Default Web Browser", makeCommand("forgetBrowser",  this));
+		themes = ColorTheme.getColorThemes();
+		MesquiteSubmenuSpec mTheme = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.defaultsSubmenu, "Color Theme", makeCommand("setColorTheme",  this), themes);
+		themeName = new MesquiteString(themes.getValue(ColorTheme.THEME));  //this helps the menu keep track of checkmenuitems
+		mTheme.setSelected(themeName);
+
+		
+		MesquiteSubmenuSpec sm = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.defaultsSubmenu, "Default Font", makeCommand("setDefaultFont",  this), MesquiteSubmenu.getFontList());
+		sm.setFilterable(false);
+		sm = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.defaultsSubmenu,"Default Font Size", makeCommand("setDefaultFontSize",  this), MesquiteSubmenu.getFontSizeList());		
+		sm.setFilterable(false);
+		MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "-", null);
+
+		sm = MesquiteTrunk.mesquiteTrunk.addSubmenu(MesquiteTrunk.defaultsSubmenu,"Project Panel Font Size", makeCommand("setProjectPanelFontSize",  this), MesquiteSubmenu.getFontSizeList());		
+		sm.setFilterable(false);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Use File-Specific Project Panel Width", makeCommand("respectFileSpecificResourceWidth",  this), respectFileSpecificResourceWidth);
+		if (MesquiteTrunk.isMacOSX()  && System.getProperty("os.version").indexOf("10.4")>=0)
+			MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Suppress Inverted Highlights", makeCommand("toggleXORMode",  this), suppressXORMode);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Ask for Random Number Seeds", makeCommand("toggleAskSeed",  this), askSeed);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Permit Partial Names in Tree Reading", makeCommand("togglePartNamesTrees",  this), taxonTruncTrees);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Permit t0, t1, Names in Tree Reading", makeCommand("toggleT0NamesTrees",  this), taxonT0Trees);
+		MesquiteTrunk.mesquiteTrunk.addItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu, "Matrix Limits for Undo...", makeCommand("setMaxMatrixSizeUndo",  this));
+
+		//comment out debug mode menu item for users 
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Debug Mode", makeCommand("toggleDebugMode",  this), debugMode);
+		MesquiteTrunk.mesquiteTrunk.addMenuItem(MesquiteTrunk.fileMenu, "-", null);
+
+
+		hireAllEmployees(DefaultsAssistant.class);
+		return true;
+	}
+
+	public void endJob(){
+		storePreferences();
+		super.endJob();
+	}
+	
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>1) {
+			int fontSize = MesquiteInteger.fromString(prefs[1]);
+			if (MesquiteInteger.isCombinable(fontSize)) {
+				Font fontToSet = new Font (prefs[0], MesquiteWindow.defaultFont.getStyle(), fontSize);
+				if (fontToSet!= null) {
+					MesquiteWindow.defaultFont = fontToSet;
+				}
+			}
+			//if (prefs.length>2 && prefs[2] !=null) //post 2. 01 changed name to switch factory default to false
+		//		useOtherChoices.setValue("useOther".equalsIgnoreCase(prefs[2]));
+			if (prefs.length>3 && prefs[3] !=null)
+				MesquiteTrunk.suggestedDirectory = prefs[3];
+			if (prefs.length>4 && prefs[4] !=null)
+				askSeed.setValue("askSeed".equalsIgnoreCase(prefs[4]));
+			if (prefs.length>5 && prefs[5] !=null){
+				if (MesquiteTrunk.isMacOSX()  && System.getProperty("os.version").indexOf("10.4")>=0){
+					suppressXORMode.setValue("suppressXORMode".equalsIgnoreCase(prefs[5]));
+					GraphicsUtil.useXOR = !suppressXORMode.getValue();
+				}
+			}
+			if (prefs.length>6 && prefs[6] !=null){
+				taxonTruncTrees.setValue("permitTruncTaxonNamesTrees".equalsIgnoreCase(prefs[6]));
+				MesquiteTree.permitTruncTaxNames = taxonTruncTrees.getValue();
+			}
+			if (prefs.length>7 && prefs[7] !=null){
+				tabbedWindows.setValue("tabbed".equalsIgnoreCase(prefs[7]));
+				MesquiteWindow.compactWindows = tabbedWindows.getValue();
+			}
+			if (prefs.length>8 && prefs[8] !=null){
+				debugMode.setValue("debug".equalsIgnoreCase(prefs[8]));
+				MesquiteTrunk.debugMode = debugMode.getValue();
+			}
+			if (prefs.length>9 && prefs[9] !=null){
+				wizards.setValue("useWizards".equalsIgnoreCase(prefs[9]));
+				MesquiteDialog.useWizards = wizards.getValue();
+			}
+			if (prefs.length>10 && prefs[10] !=null){
+				phoneHome.setValue("phoneHome".equalsIgnoreCase(prefs[10]));
+				MesquiteTrunk.phoneHome = phoneHome.getValue();
+			}
+			if (prefs.length>11 && prefs[11] !=null)
+				secondaryChoicesOnInDialogs.setValue("secondaryChoicesOnInDialogs".equalsIgnoreCase(prefs[11]));
+		}
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("useOtherChoicesInMenus".equalsIgnoreCase(tag)){  //post 2. 01 changed name to switch factory default to false
+			useOtherChoices.setValue(content);
+			EmployerEmployee.useOtherChoices = useOtherChoices.getValue();
+		}
+		else if ("askSeed".equalsIgnoreCase(tag)){
+			askSeed.setValue(content);
+			RandomBetween.askSeed = askSeed.getValue();
+		}
+		else if ("suppressXORMode".equalsIgnoreCase(tag)){
+			if (MesquiteTrunk.isMacOSX()  && System.getProperty("os.version").indexOf("10.4")>=0){
+				suppressXORMode.setValue(content);
+				GraphicsUtil.useXOR = !suppressXORMode.getValue();
+			}
+		}
+		else if ("taxonTruncTrees".equalsIgnoreCase(tag)){
+			taxonTruncTrees.setValue(content);
+			MesquiteTree.permitTruncTaxNames = taxonTruncTrees.getValue();
+		}
+		else if ("taxonT0Trees".equalsIgnoreCase(tag)){
+			taxonT0Trees.setValue(content);
+			MesquiteTree.permitT0Names = taxonT0Trees.getValue();
+		}
+	/*	else if ("tilePopouts".equalsIgnoreCase(tag)){
+			tilePopouts.setValue(content);
+			MesquiteFrame.popIsTile = tilePopouts.getValue();
+		}*/
+		else if ("tabbedWindows".equalsIgnoreCase(tag)){
+			tabbedWindows.setValue(content);
+			MesquiteWindow.compactWindows = tabbedWindows.getValue();
+		}
+		else if ("respectFileSpecificResourceWidth".equalsIgnoreCase(tag)){
+			respectFileSpecificResourceWidth.setValue(content);
+			MesquiteFrame.respectFileSpecificResourceWidth = respectFileSpecificResourceWidth.getValue();
+		}
+		else if ("debugMode".equalsIgnoreCase(tag)){
+			debugMode.setValue(content);
+			MesquiteTrunk.debugMode = debugMode.getValue();
+		}
+		else if ("wizards".equalsIgnoreCase(tag)){
+			wizards.setValue(content);
+			MesquiteDialog.useWizards = wizards.getValue();
+		}
+		else if ("phoneHome".equalsIgnoreCase(tag)){
+			phoneHome.setValue(content);
+			MesquiteTrunk.phoneHome = phoneHome.getValue();
+		}
+		else if ("errorReports".equalsIgnoreCase(tag)){
+			errorReports.setValue(content);
+			MesquiteTrunk.reportErrors = errorReports.getValue();
+		}
+		else if ("useReports".equalsIgnoreCase(tag)){
+			useReports.setValue(content);
+			MesquiteTrunk.reportUse= useReports.getValue();
+		}
+		else if ("showSecondaryChoicesInDialogs".equalsIgnoreCase(tag)){//post 2. 01 changed name to switch factory default to true
+			secondaryChoicesOnInDialogs.setValue(content);
+			EmployerEmployee.secondaryChoicesOnInDialogs = secondaryChoicesOnInDialogs.getValue();
+		}
+		else if ("consoleMode".equalsIgnoreCase(tag)){
+			console.setValue(content);
+			MesquiteTrunk.mesquiteTrunk.logWindow.setConsoleMode(console.getValue());
+		}
+		else if ("subChoicesOnInDialogs".equalsIgnoreCase(tag)){
+			subChoicesOnInDialogs.setValue(content);
+			EmployerEmployee.subChoicesOnInDialogs = subChoicesOnInDialogs.getValue();
+		}
+		else if ("storedAsDefault".equalsIgnoreCase(tag)){
+			CharacterSource.storedAsDefault.setValue(content);
+		}
+		else if ("closeIfMatrixDeleted".equalsIgnoreCase(tag)){
+			CharacterSource.closeIfMatrixDeleted.setValue(content);
+		}
+		/*
+		 * else if ("closeIfTreeBlockDeleted".equalsIgnoreCase(tag)){
+			TreeSource.closeIfTreeBlockDeleted.setValue(content);
+		}*/
+		else if ("defaultFont".equalsIgnoreCase(tag)){
+			String defFont = StringUtil.cleanXMLEscapeCharacters(content);
+			Font fontToSet = new Font (defFont, MesquiteWindow.defaultFont.getStyle(), MesquiteWindow.defaultFont.getSize());
+			if (fontToSet!= null) 
+				MesquiteWindow.defaultFont = fontToSet;
+		}
+		else if ("defaultFontSize".equalsIgnoreCase(tag)) {
+			int defFontSize = MesquiteInteger.fromString(content);
+			Font fontToSet = new Font (MesquiteWindow.defaultFont.getName(), MesquiteWindow.defaultFont.getStyle(), defFontSize);
+			if (fontToSet!= null) 
+				MesquiteWindow.defaultFont = fontToSet;
+		}
+		else if ("resourcesFontSize".equalsIgnoreCase(tag)) {
+			int defFontSize = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(defFontSize)) 
+				MesquiteFrame.resourcesFontSize = defFontSize;
+		}
+		else if ("suggestedDirectory".equalsIgnoreCase(tag)){
+			MesquiteTrunk.suggestedDirectory = StringUtil.cleanXMLEscapeCharacters(content);
+		}
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "defaultFont", MesquiteWindow.defaultFont.getName());  
+		StringUtil.appendXMLTag(buffer, 2, "defaultFontSize", MesquiteWindow.defaultFont.getSize());
+		StringUtil.appendXMLTag(buffer, 2, "resourcesFontSize", MesquiteFrame.resourcesFontSize);
+		StringUtil.appendXMLTag(buffer, 2, "useOtherChoicesInMenus", useOtherChoices);   
+		StringUtil.appendXMLTag(buffer, 2, "suggestedDirectory", MesquiteTrunk.suggestedDirectory);
+		StringUtil.appendXMLTag(buffer, 2, "askSeed", askSeed);   
+		StringUtil.appendXMLTag(buffer, 2, "suppressXORMode", suppressXORMode);   
+		StringUtil.appendXMLTag(buffer, 2, "taxonTruncTrees", taxonTruncTrees);   
+		StringUtil.appendXMLTag(buffer, 2, "taxonT0Trees", taxonT0Trees);   
+		StringUtil.appendXMLTag(buffer, 2, "tabbedWindows", tabbedWindows);   
+		StringUtil.appendXMLTag(buffer, 2, "respectFileSpecificResourceWidth", respectFileSpecificResourceWidth);   
+		StringUtil.appendXMLTag(buffer, 2, "tilePopouts", tilePopouts);   
+		StringUtil.appendXMLTag(buffer, 2, "debugMode", debugMode);   
+		StringUtil.appendXMLTag(buffer, 2, "wizards", wizards);   
+		StringUtil.appendXMLTag(buffer, 2, "phoneHome", phoneHome);   
+		StringUtil.appendXMLTag(buffer, 2, "errorReports", errorReports);   
+		StringUtil.appendXMLTag(buffer, 2, "useReports", useReports);   
+		StringUtil.appendXMLTag(buffer, 2, "showSecondaryChoicesInDialogs", secondaryChoicesOnInDialogs);   
+		StringUtil.appendXMLTag(buffer, 2, "subChoicesOnInDialogs", subChoicesOnInDialogs);   
+		StringUtil.appendXMLTag(buffer, 2, "consoleMode", console);   
+			StringUtil.appendXMLTag(buffer, 2, "storedAsDefault", CharacterSource.storedAsDefault);   
+			StringUtil.appendXMLTag(buffer, 2, "closeIfMatrixDeleted", CharacterSource.closeIfMatrixDeleted);   
+			//StringUtil.appendXMLTag(buffer, 2, "closeIfTreeBlockDeleted", TreeSource.closeIfTreeBlockDeleted);   
+		return buffer.toString();
+	}
+	/*.................................................................................................................*
+	public String[] preparePreferencesForFile () {
+		String[] prefs= new String[12];
+		prefs[0] = MesquiteWindow.defaultFont.getName();
+		prefs[1] = Integer.toString(MesquiteWindow.defaultFont.getSize());
+		if (useOtherChoices.getValue())
+			prefs[2] = "useOther";
+		else
+			prefs[2] = "dontUseOther";
+		prefs[3] = MesquiteTrunk.suggestedDirectory;
+		if (askSeed.getValue())
+			prefs[4] = "askSeed";
+		else
+			prefs[4] = "dontAskSeed";
+		if (xorMode.getValue())
+			prefs[5] = "suppressXORMode";
+		else
+			prefs[5] = "useXORMode";
+		if (taxonTruncTrees.getValue())
+			prefs[6] = "permitTruncTaxonNamesTrees";
+		else
+			prefs[6] = "noTruncTaxonNamesTrees";
+		if (tabbedWindows.getValue())
+			prefs[7] = "tabbed";
+		else
+			prefs[7] = "noTabbed";
+		if (debugMode.getValue())
+			prefs[8] = "debug";
+		else
+			prefs[8] = "noDebug";
+		if (wizards.getValue())
+			prefs[9] = "useWizards";
+		else
+			prefs[9] = "noUseWizards";
+		if (phoneHome.getValue())
+			prefs[10] = "phoneHome";
+		else
+			prefs[10] = "DontPhoneHome";
+		if (secondaryChoicesOnInDialogs.getValue())
+			prefs[11] = "secondaryChoicesOnInDialogs";
+		else
+			prefs[11] = "secondaryChoicesOffInDialogs";
+		return prefs;
+	}
+
+
+
+	/*.................................................................................................................*/
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Sets the default font of windows", "[name of font]", commandName, "setDefaultFont")) {
+			if (MesquiteWindow.defaultFont==null)
+				return null;
+			Font fontToSet = new Font (parser.getFirstToken(arguments), MesquiteWindow.defaultFont.getStyle(), MesquiteWindow.defaultFont.getSize());
+			if (fontToSet!= null) {
+				MesquiteWindow.defaultFont = fontToSet;
+				storePreferences();
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the default font size of windows", "[font size]", commandName, "setDefaultFontSize")) {
+			if (MesquiteWindow.defaultFont==null)
+				return null;
+			int fontSize = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+			if (!MesquiteInteger.isCombinable(fontSize))
+				fontSize = MesquiteInteger.queryInteger(containerOfModule(), "Font size", "Font size for window", MesquiteWindow.defaultFont.getSize(), 4, 256);
+			if (!MesquiteInteger.isCombinable(fontSize))
+				return null;
+			Font fontToSet = new Font (MesquiteWindow.defaultFont.getName(), MesquiteWindow.defaultFont.getStyle(), fontSize);
+			if (fontToSet!= null) {
+				MesquiteWindow.defaultFont = fontToSet;
+				storePreferences();
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the color theme", null, commandName, "setColorTheme")) {
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = themes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=ColorTheme.THEME_FOR_NEXT_STARTUP){
+				ColorTheme.THEME_FOR_NEXT_STARTUP = newMode; //change mode
+				MesquiteTrunk.mesquiteTrunk.storePreferences();
+				discreetAlert("The change in color theme will occur the next time you start Mesquite");
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the font size of project panel", "[font size]", commandName, "setProjectPanelFontSize")) {
+			int fontSize = MesquiteInteger.fromFirstToken(arguments, new MesquiteInteger(0));
+			if (!MesquiteInteger.isCombinable(fontSize))
+				fontSize = MesquiteInteger.queryInteger(containerOfModule(), "Font size", "Font size for window", MesquiteWindow.defaultFont.getSize(), 4, 256);
+			if (!MesquiteInteger.isCombinable(fontSize))
+				return null;
+				MesquiteFrame.resourcesFontSize = fontSize;
+				for (int i = 0; i< MesquiteTrunk.getProjectList().getNumProjects(); i++){
+					MesquiteProject proj = MesquiteTrunk.getProjectList().getProject(i);
+					proj.getCoordinatorModule().refreshGraphicsProjectWindow();
+				}
+				storePreferences();
+		}
+		else if (checker.compare(getClass(), "Forgets the default web browser", null, commandName, "forgetBrowser")) {
+			browserString = null;
+		}
+		else if (checker.compare(getClass(), "Sets the number of previous logs saved", "[num logs]", commandName, "setNumPrevLog")) {
+			int numLogs = MesquiteInteger.fromString(arguments);
+			if (!MesquiteInteger.isCombinable(numLogs))
+				numLogs = MesquiteInteger.queryInteger(containerOfModule(), "Number of Logs", "Number of previous log files retained", MesquiteTrunk.numPrevLogs, 2, 10000);
+			if (!MesquiteInteger.isCombinable(numLogs) || numLogs == MesquiteTrunk.numPrevLogs)
+				return null;
+			MesquiteTrunk.numPrevLogs = numLogs;
+			MesquiteTrunk.mesquiteTrunk.storePreferences();
+
+		}
+		else if (checker.compare(getClass(), "Sets the maximum number of taxa and characters for whole-matrix undos to work in data editor", "[num taxa][num chars]", commandName, "setMaxMatrixSizeUndo")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			parser.setString(arguments);
+			int maxTaxa = MesquiteInteger.fromString(parser.getFirstToken());
+			int maxChars = MesquiteInteger.fromString(parser.getNextToken());
+			if (!MesquiteInteger.isCombinable(maxTaxa)|| !MesquiteInteger.isCombinable(maxChars)) {
+				MesquiteBoolean answer= new MesquiteBoolean(false);
+				MesquiteInteger maxNumTaxa=new MesquiteInteger(MesquiteTrunk.maxNumMatrixUndoTaxa);
+				MesquiteInteger maxNumChars = new MesquiteInteger(MesquiteTrunk.maxNumMatrixUndoChars);
+				String helpString = "For some operations in the data editor to be undone, the entire data matrix needs to be remembered beforehand.  However, for large matrices, this can require more "
+					+"memory than Mesquite has.  By default, Mesquite disallows this whole-matrix undo capability if the number of taxa exceeds 1000 and the number of characters exceeds 15000. "
+					+" You can change these maxima here.  Note that BOTH values need to be exceeded for whole-matrix Undo to be disabled.  To specify that all matrices should fully undoable, enter a value of -1.";
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Maximum size of fully undoable matrix", "Maximum number of taxa", "Maximum number of characters",  answer,  maxNumTaxa,  maxNumChars,-1,Integer.MAX_VALUE,-1, Integer.MAX_VALUE, helpString);
+				if (!answer.getValue() || !maxNumTaxa.isCombinable() || ! maxNumChars.isCombinable()) 
+					return null;
+				MesquiteTrunk.maxNumMatrixUndoTaxa = maxNumTaxa.getValue();
+				MesquiteTrunk.maxNumMatrixUndoChars = maxNumChars.getValue();
+				MesquiteTrunk.mesquiteTrunk.storePreferences();
+			}
+
+		}
+		else if (checker.compare(getClass(), "Sets whether to show windows of each project as tabs within a single window", null, commandName, "toggleTabbedWindows")) {
+			tabbedWindows.toggleValue(null);
+			MesquiteWindow.compactWindows = tabbedWindows.getValue();
+			discreetAlert( "You need to close and reopen files to have the change in using tabs versus windows take effect");
+			storePreferences();
+		}
+		else if (checker.compare(getClass(), "Sets whether to use file-specific project panel widths", null, commandName, "respectFileSpecificResourceWidth")) {
+			respectFileSpecificResourceWidth.toggleValue(null);
+			MesquiteFrame.respectFileSpecificResourceWidth = respectFileSpecificResourceWidth.getValue();
+			storePreferences();
+		}
+	/*	else if (checker.compare(getClass(), "Sets whether to tile windows popped out, instead of pop them out to separate windows", null, commandName, "toggleTilePopouts")) {
+			tilePopouts.toggleValue(null);
+			MesquiteFrame.popIsTile = tilePopouts.getValue();
+			storePreferences();
+		}*/
+		else if (checker.compare(getClass(), "Sets whether to use log window as input console for commands", null, commandName, "toggleConsoleMode")) {
+			console.toggleValue(null);
+			MesquiteTrunk.mesquiteTrunk.logWindow.setConsoleMode(console.getValue());
+			if (!MesquiteThread.isScripting()) {
+				if (console.getValue()) {
+					logln("Command-line Mode On.  Type \"help\" for some console commands.  Note: command-line mode is experimental.  Currently it is not properly protected against simultaneous calculations, e.g. doing different modifications simultaneously of the same tree or data.");
+					MesquiteTrunk.mesquiteTrunk.logWindow.showPrompt();
+				}
+				else
+					logln("\nConsole Mode Off");
+			}
+			MesquiteTrunk.mesquiteTrunk.storePreferences();
+		}
+		else if (checker.compare(getClass(), "Sets whether to log all commands", null, commandName, "toggleLogAll")) {
+			logAll.toggleValue(null);
+			MesquiteCommand.logEverything = logAll.getValue();
+			if (!MesquiteThread.isScripting()) {
+				if (logAll.getValue()) {
+					logln("Highly verbose logging on (Logging all commands).");
+				}
+				else
+					logln("Normal logging in effect");
+			}
+			MesquiteTrunk.mesquiteTrunk.storePreferences();
+		}
+		else if (checker.compare(getClass(), "Sets whether to use debug mode", null, commandName, "toggleDebugMode")) {
+			debugMode.toggleValue(null);
+			MesquiteTrunk.debugMode = debugMode.getValue();
+			storePreferences();
+			return debugMode;
+		}
+		else if (checker.compare(getClass(), "Sets whether to check Mesquite web site for notices on startup", null, commandName, "togglePhoneHome")) {
+			phoneHome.toggleValue(null);
+			MesquiteTrunk.phoneHome = phoneHome.getValue();
+			storePreferences();
+			return phoneHome;
+		}
+		else if (checker.compare(getClass(), "Sets whether to send error reports to Mesquite server", null, commandName, "toggleErrorReports")) {
+			errorReports.toggleValue(null);
+			MesquiteTrunk.reportErrors = errorReports.getValue();
+			storePreferences();
+			return errorReports;
+		}
+		else if (checker.compare(getClass(), "Sets whether to send use reports to Mesquite server", null, commandName, "toggleUseReports")) {
+			useReports.toggleValue(null);
+			MesquiteTrunk.reportUse = useReports.getValue();
+			storePreferences();
+			return useReports;
+		}
+		else if (checker.compare(getClass(), "Sets whether to use wizard-style dialogs", null, commandName, "toggleWizards")) {
+			wizards.toggleValue(null);
+			MesquiteDialog.useWizards = wizards.getValue();
+			storePreferences();
+			return wizards;
+		}
+		else if (checker.compare(getClass(), "Sets whether to use xor mode", null, commandName, "toggleXORMode")) {
+			suppressXORMode.toggleValue(null);
+			GraphicsUtil.useXOR = !suppressXORMode.getValue();
+			resetAllMenuBars();
+			return suppressXORMode;
+		}
+		else if (checker.compare(getClass(), "Sets whether to permit taxon name truncation in trees", null, commandName, "togglePartNamesTrees")) {
+			taxonTruncTrees.toggleValue(null);
+			MesquiteTree.permitTruncTaxNames = taxonTruncTrees.getValue();
+			resetAllMenuBars();
+			storePreferences();
+			return taxonTruncTrees;
+		}
+		else if (checker.compare(getClass(), "Sets whether to permit taxon names being expressed as t0, t1, t2 in trees", null, commandName, "toggleT0NamesTrees")) {
+			taxonT0Trees.toggleValue(null);
+			MesquiteTree.permitT0Names = taxonTruncTrees.getValue();
+			resetAllMenuBars();
+			storePreferences();
+			return taxonT0Trees;
+		}
+		else if (checker.compare(getClass(), "Sets whether to place secondary choices for modules into an \"Other Choices...\" dialog box", null, commandName, "toggleOtherChoices")) {
+			useOtherChoices.toggleValue(null);
+			EmployerEmployee.useOtherChoices = useOtherChoices.getValue();
+			resetAllMenuBars();
+			storePreferences();
+			return useOtherChoices;
+		}
+		else if (checker.compare(getClass(), "Sets whether to have secondary choices shown by default in dialog boxes", null, commandName, "toggleSecondaryChoicesOnInDialogs")) {
+			secondaryChoicesOnInDialogs.toggleValue(null);
+			EmployerEmployee.secondaryChoicesOnInDialogs = secondaryChoicesOnInDialogs.getValue();
+			resetAllMenuBars();
+			storePreferences();
+			return secondaryChoicesOnInDialogs;
+		}
+		else if (checker.compare(getClass(), "Sets whether to have subchoices shown in module dialog boxes", null, commandName, "toggleSubChoicesOnInDialogs")) {
+			subChoicesOnInDialogs.toggleValue(null);
+			EmployerEmployee.subChoicesOnInDialogs = subChoicesOnInDialogs.getValue();
+			storePreferences();
+			return subChoicesOnInDialogs;
+		}
+		else if (checker.compare(getClass(), "Sets whether to use Stored Characters/Matrices by default", null, commandName, "toggleStoredAsDefault")) {
+			CharacterSource.storedAsDefault.toggleValue(null);
+			storePreferences();
+			return CharacterSource.storedAsDefault;
+		}
+		else if (checker.compare(getClass(), "Sets whether to close a calculation if the matrix it uses is deleted", null, commandName, "toggleCloseIfMatrixDeleted")) {
+			CharacterSource.closeIfMatrixDeleted.toggleValue(null);
+			storePreferences();
+			return CharacterSource.closeIfMatrixDeleted;
+		}
+	/*	else if (checker.compare(getClass(), "Sets whether to close a tree window automatically if the tree block it uses is deleted", null, commandName, "toggleCloseIfTreeBlockDeleted")) {
+			TreeSource.closeIfTreeBlockDeleted.toggleValue(null);
+			storePreferences();
+			return TreeSource.closeIfTreeBlockDeleted;
+		}*/
+		else if (checker.compare(getClass(), "Sets whether to place ask for random number seeds when calculations requested", null, commandName, "toggleAskSeed")) {
+			askSeed.toggleValue(null);
+			RandomBetween.askSeed = askSeed.getValue();
+			storePreferences();
+			return askSeed;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+}
+
diff --git a/Source/mesquite/minimal/DrawHierarchy/DrawHierarchy.java b/Source/mesquite/minimal/DrawHierarchy/DrawHierarchy.java
new file mode 100644
index 0000000..30bf6e6
--- /dev/null
+++ b/Source/mesquite/minimal/DrawHierarchy/DrawHierarchy.java
@@ -0,0 +1,584 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.minimal.DrawHierarchy;
+/*~~  */
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Draws the trees of HNode's in various places (e.g., module tree in Module tab of windows; Project element tree in 
+Projects & Files window). */
+
+public class DrawHierarchy extends BrowseHierarchy  {
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "DrawHierarchy";
+	 }
+		/*.................................................................................................................*/
+	 public String getExplanation() {
+	return "Draws project and module trees";
+	 }
+	 
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+ 	}
+ 	public HPanel makeHierarchyPanel(){
+ 		return new HierarchyPanel(this);
+ 	}
+}
+
+/* ======================================================================== */
+class HierarchyPanel extends HPanel {
+	FieldPanel ePane;
+	public HierarchyPanel (MesquiteModule ownerModule) {
+		//setFont(new Font ("SanSerif", Font.PLAIN, 10));
+		ePane = new FieldPanel(ownerModule, this);
+		addImpl(ePane, null, 0);
+		ePane.setVisible(true);
+	}
+	public void renew() {
+		ePane.renew();
+		setScrollPosition(0,0);
+	}
+	public void dispose() {
+		ePane.dispose();
+	}
+	public void disposeReferences() {
+		if (ePane !=null)
+			ePane.disposeReferences();
+	}
+	public void setRootNode(HNode node) {
+		ePane.setRootNode(node);
+	}
+	public void highlightNode(HNode node) {
+		ePane.highlightNode(node);
+	}
+	public void setTitle(String title) {
+		ePane.setTitle(title);
+	}
+	public void setBackground(Color color){
+		ePane.setBackground(color);
+	}
+	public void setDefaultDepth(int depth){
+		ePane.setDefaultDepth(depth);
+	}
+	public void showTypes(boolean s){
+		ePane.setShowTypes(s);
+	}
+}
+
+/* ======================================================================== */
+class FieldPanel extends Panel {
+	final static int HSpacer = 24;
+	int VSpacer = 22; 
+	HierarchyPanel pane;
+	int maximumRight, maximumDown;
+	NodeLabel rootLabel=null;
+	HNode  rootNode;
+	TextArea titleText;
+	public boolean showTypes;
+	String title;
+	int defaultDepth = -1;
+	int initialY = 22;
+	MesquiteModule ownerModule;
+	HNode highlighted=null;
+	public FieldPanel (MesquiteModule ownerModule, HierarchyPanel pane) {
+		super();
+		this.ownerModule = ownerModule;
+		this.pane = pane;
+		setLayout(null);
+		setSize(500, 500);
+		setBackground(Color.yellow);
+		pane.repaint();
+		repaint();
+	}
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public void setRootNode(HNode node) {
+		rootNode = node;
+		renew();
+	}
+	public void setDefaultDepth(int depth){
+		defaultDepth = depth;
+	}
+	public void setShowTypes(boolean s){
+		showTypes = s;
+	}
+	public void highlightNode(HNode node){
+		highlighted = node;
+	}
+	public void renew() {
+		if (rootLabel!= null)
+			disposeLabels(rootLabel);
+		if (rootNode == null)
+			return;
+		maximumDown = MesquiteInteger.unassigned; //forces recalculation of size
+		maximumRight = MesquiteInteger.unassigned;
+		MesquiteInteger yplace = new MesquiteInteger(0);
+		rootLabel = new NodeLabel(ownerModule, this, rootNode, null);
+		addClade(rootNode, rootLabel, 1);
+		if (title == null)
+			yplace.setValue(-12);
+		else
+			yplace.setValue(initialY-12);
+		//resetHighlights(rootLabel);
+		setLabelLocations(rootLabel, yplace, 0, 12);
+	}
+	public void dispose() {
+		disposeLabels(rootLabel);
+		rootLabel = null;
+		rootNode=null;
+		highlighted = null;
+		ownerModule = null;
+	}
+ 	public void disposeReferences() {
+		disposeRefsRec(rootLabel);
+	}
+	public void disposeRefsRec(NodeLabel label) {
+		try {
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					disposeRefsRec((NodeLabel)daughters[i]);
+		 		}
+	 		}
+	 		label.node = null;
+	 		label.motherNode = null;
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 	 }
+	public void disposeLabels(NodeLabel label) {
+		try {
+			if (label.getHShow()){
+				HNode[] daughters = label.getHDaughters();
+				if (daughters!=null) {
+					for (int i=0; i<daughters.length; i++) {
+						disposeLabels((NodeLabel)daughters[i]);
+			 		}
+		 		}
+		 		if (label.supplements!=null) {
+			 		for (int i=0; i<label.supplements.length; i++) {
+			 			label.supplements[i].setVisible(false);
+						remove(label.supplements[i]);
+			  			label.supplements[i] = null;
+			  		}
+		 		}
+	 		}
+	 		label.setVisible(false);
+	 		label.dispose();
+			remove(label);
+	  		label = null;
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 	 }
+ 	public void addClade(HNode node, NodeLabel label, int depth) {
+		try {
+			add(label);
+			label.setVisible(true);
+			if (label.supplements!=null) {
+				for (int i=0;i<label.supplements.length; i++){
+					add(label.supplements[i]);
+					label.supplements[i].setVisible(true);
+				}
+			}
+			HNode[] daughters = node.getHDaughters();
+			if (daughters!=null && (defaultDepth<0 || depth<=defaultDepth)) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i].getHShow()){
+						NodeLabel eL = label.setDaughter(daughters[i]);
+						addClade(daughters[i], eL, depth+1);
+					}
+		 		}
+	 		}
+ 		}
+ 		catch (NullPointerException e){
+ 			MesquiteMessage.warnProgrammer("NPE in addClade in DrawHierarchy " + node);
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+   	 }
+ 	/*public void resetHighlights(NodeLabel label) {
+ 		if (label.getNode() == highlighted)
+ 			label.setColor(Color.yellow);
+ 		else
+ 			label.setColor(ColorDistribution.straw);
+		HNode[] daughters = label.getHDaughters();
+		if (daughters!=null) {
+			for (int i=0; i<daughters.length; i++) {
+				if (daughters[i].getHShow()){
+					NodeLabel eL = (NodeLabel)daughters[i];
+					resetHighlights(eL);
+				}
+	 		}
+ 		}
+ 		// don't need to trim indent since not returned by reference
+   	 }
+   	 */
+ 	public boolean checkLabelLocations(NodeLabel label) {
+ 		try {
+	 		if (label == null)
+	 			return false;
+			Point d = label.getLocation();
+			if (d.y == 0)
+				return true;
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i]!=null && daughters[i].getHShow()){
+						NodeLabel eL = (NodeLabel)daughters[i];
+						if (checkLabelLocations(eL))
+							return true;
+					}
+		 		}
+	 		}
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+ 		return false;
+   	 }
+ 	public boolean checkSupplementLocations(NodeLabel label) {
+ 		try {
+	 		if (label == null)
+	 			return false;
+			if (label.supplements!=null) {
+				int prevX = label.getLocation().x + label.getBounds().width;
+				for (int i=0;i<label.supplements.length; i++){
+					Point d = label.supplements[i].getLocation();
+					if (d.x != prevX + 10) {
+						return true;
+					}
+					prevX = label.supplements[i].getLocation().x + label.supplements[i].getBounds().width;
+				}
+			}
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i]!=null && daughters[i].getHShow()){
+						NodeLabel eL = (NodeLabel)daughters[i];
+						if (checkSupplementLocations(eL))
+							return true;
+					}
+		 		}
+	 		}
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+ 		return false;
+   	 }
+ 	private void setLabelLocations(NodeLabel label, MesquiteInteger y, int employerY, int indent) {
+ 		try {
+	 		if (y==null || label == null)
+	 			return;
+	 		y.setValue( y.getValue()+VSpacer);
+			if ((indent + label.getBounds().width)> maximumRight)
+				maximumRight = (indent + label.getBounds().width);
+			if (y.getValue()> maximumDown)
+				maximumDown = y.getValue();
+	 		int myY = y.getValue() + VSpacer/2-4;
+			label.setLocation(indent, y.getValue());
+			
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i]!=null && daughters[i].getHShow()){
+						NodeLabel eL = (NodeLabel)daughters[i];
+						setLabelLocations(eL, y, myY, indent+HSpacer);
+					}
+		 		}
+	 		}
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+   	 }
+ 	private void setSupplementLocations(NodeLabel label) {
+ 		try {
+	 		if (label == null)
+	 			return;
+			if (label.supplements!=null) {
+				int prevX = label.getLocation().x + label.getBounds().width;
+				for (int i=0; i<label.supplements.length; i++) {
+					if (label.supplements[i]!=null){
+						label.supplements[i].setLocation(prevX + 10, label.getLocation().y);
+						prevX = label.supplements[i].getLocation().x + label.supplements[i].getBounds().width;
+					}
+				}
+			}
+			
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i]!=null && daughters[i].getHShow()){
+						NodeLabel eL = (NodeLabel)daughters[i];
+						setSupplementLocations(eL);
+					}
+		 		}
+	 		}
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+   	 }
+ 	public void drawTree(NodeLabel label, Graphics g, MesquiteInteger y, int employerY, int indent) {
+ 		try {
+	 		if (y==null || label == null)
+	 			return;
+	 		y.setValue( y.getValue()+VSpacer);
+			if ((indent + label.getBounds().width)> maximumRight)
+				maximumRight = (indent + label.getBounds().width);
+			if (y.getValue()> maximumDown)
+				maximumDown = y.getValue();
+	 		int myY = y.getValue() + VSpacer/2-4;
+	 		g.setColor(Color.blue);
+			if (label != rootLabel) {
+				g.drawLine(indent- HSpacer/2, myY, indent-HSpacer/2, employerY);
+				g.drawLine(indent- HSpacer/2+1, myY, indent-HSpacer/2+1, employerY);
+				g.drawLine(indent- HSpacer/2, myY, indent,myY);
+				g.drawLine(indent- HSpacer/2, myY+1, indent,myY+1);
+			}
+	 		g.setColor(Color.black);
+			
+			HNode[] daughters = label.getHDaughters();
+			if (daughters!=null) {
+				for (int i=0; i<daughters.length; i++) {
+					if (daughters[i]!=null && daughters[i].getHShow()){
+						NodeLabel eL = (NodeLabel)daughters[i];
+						drawTree(eL, g, y, myY, indent+HSpacer);
+					}
+		 		}
+	 		}
+	 		if (label.getHImage()!=null)
+	 			g.drawImage(label.getHImage(), indent- HSpacer/2 + label.getBounds().width + 16, myY-5, this);
+ 		}
+ 		catch (NullPointerException e){
+ 			//these just tend to happen!
+ 		}
+ 		// don't need to trim indent since not returned by reference
+   	 }
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+	   	if (rootNode != null) {
+	   		
+			FontMetrics fm = g.getFontMetrics();
+			VSpacer = fm.getAscent() + fm.getDescent() + 9;
+			if (title != null)
+				g.drawString(title, 10, VSpacer);
+			MesquiteInteger yplace = new MesquiteInteger(0);
+			int oldMaximumRight = maximumRight;
+			maximumRight = pane.getBounds().width;
+			int oldMaximumDown = maximumDown;
+			maximumDown = pane.getBounds().height;
+			if (title == null)
+				yplace.setValue(-12);
+			else
+				yplace.setValue(initialY-12);
+			//resetHighlights(rootLabel);
+			drawTree(rootLabel, g, yplace, 0, 12);
+			if (maximumDown!=oldMaximumDown || maximumRight != oldMaximumRight) {
+				setSize(maximumRight + 50, maximumDown + 50);
+				pane.setScrollPosition(0,0);
+				if (title == null)
+					yplace.setValue(-12);
+				else
+					yplace.setValue(initialY-12);
+				setLabelLocations(rootLabel, yplace, 0, 12);
+				setSupplementLocations(rootLabel);
+				pane.doLayout();
+				pane.repaint();
+				repaint();
+			}
+			if (checkLabelLocations(rootLabel)){
+				if (title == null)
+					yplace.setValue(-12);
+				else
+					yplace.setValue(initialY-12);
+				setLabelLocations(rootLabel, yplace, 0, 12);
+				pane.repaint();
+				repaint();
+			}
+			if (checkSupplementLocations(rootLabel))
+				setSupplementLocations(rootLabel);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*public void setSize(int width, int height){
+		MesquiteInteger yplace = new MesquiteInteger(0);
+		int oldMaximumRight = maximumRight;
+		maximumRight = pane.getBounds().width;
+		int oldMaximumDown = maximumDown;
+		maximumDown = pane.getBounds().height;
+		yplace.setValue(initialY);
+		resetHighlights(rootLabel);
+		drawTree(rootLabel, g, yplace, 0, 12);
+		if (maximumDown!=oldMaximumDown || maximumRight != oldMaximumRight) {
+			setSize(maximumRight + 50, maximumDown + 50);
+			pane.setScrollPosition(0,0);
+			pane.doLayout();
+			pane.repaint();
+		}
+		super.setSize(width, height);
+	}*/
+}
+/* ======================================================================== */
+class NodeLabel extends MesquiteLabel implements HNode {
+	HNode node;
+	public Vector daughterVector;
+	HNode motherNode;
+	public SupplementLabel[] supplements;
+	FieldPanel panel;
+	
+	public NodeLabel(MesquiteModule ownerModule, FieldPanel panel, HNode node, HNode motherNode){
+		super(ownerModule);
+		setCheckDoomed(false);
+		if (node !=null){
+			setBackground(node.getHColor());
+			setColor(node.getHColor());
+		}
+		setSize(10,10);
+		daughterVector = new Vector(1);
+		this.node = node;
+		this.panel = panel;
+		this.motherNode = motherNode;
+		if (node !=null){
+			int numSupp = node.getNumSupplements();
+			
+			if (numSupp>0) {
+				supplements = new SupplementLabel[numSupp];
+				for (int i = 0; i<numSupp; i++)
+					supplements[i] = new SupplementLabel(ownerModule, node, i);
+			}
+			if (panel.showTypes && !StringUtil.blank(node.getTypeName()))
+				setText(node.getTypeName() + ": " + node.getName());
+			else
+				setText(node.getName());
+		}
+	}
+	
+	public NodeLabel setDaughter(HNode node) {
+		NodeLabel eL = new NodeLabel(MesquiteTrunk.mesquiteTrunk, panel, node, motherNode);
+		if (daughterVector!=null)
+			daughterVector.addElement(eL);
+		return eL;
+	}
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (node!=null)
+			node.hNodeAction(this, x, y, HNode.MOUSEDOWN);   
+	}
+   	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (node!=null)
+			node.hNodeAction(this, x, y, HNode.MOUSEMOVE);   
+	}
+   	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (node!=null)
+			node.hNodeAction(this, x, y, HNode.MOUSEMOVE);   
+	}
+   	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (node!=null)
+			node.hNodeAction(this, x, y, HNode.MOUSEEXIT);   
+	}
+	/*.................................................................................................................*/
+	public void zapHDaughters(){
+		if (daughterVector == null || daughterVector.size() == 0)
+			return;
+		daughterVector.removeAllElements();
+		node = null;
+	}
+	public HNode[] getHDaughters(){
+		if (daughterVector == null || daughterVector.size() == 0)
+			return null;
+		int num = daughterVector.size();
+		HNode[] daughters = new HNode[num];
+		try {
+			for (int i= 0; i<num && i<daughters.length && daughterVector!=null && i<daughterVector.size(); i++)
+				daughters[i] = (HNode)daughterVector.elementAt(i);
+		}
+		catch (ArrayIndexOutOfBoundsException e){
+		}
+		catch (NullPointerException e){
+		}
+		return daughters;
+	}
+	public void dispose(){
+		daughterVector.removeAllElements();
+		daughterVector = null;
+		super.dispose();
+	}
+	/*.................................................................................................................*/
+	public HNode getHNode(){
+		return node;
+	}
+	/*.................................................................................................................*/
+	public HNode getHMother(){
+		return motherNode;
+	}
+	public int getNumSupplements(){
+		return node.getNumSupplements();
+	}
+	public String getSupplementName(int index){
+		return node.getSupplementName(index);
+	}
+	public void hNodeAction(Container c, int x, int y, int action){
+	}
+	public void hSupplementTouched(int index){}
+	public String getTypeName(){
+		return "Label for node in hierarchy";
+	}
+	public Image getHImage(){
+		return node.getHImage();
+	}
+	public Color getHColor(){
+		return node.getHColor();
+	}
+	public boolean getHShow(){
+		return node.getHShow();
+	}
+}
+/* ======================================================================== */
+class SupplementLabel extends MesquiteLabel {
+	HNode node;
+	int which;
+	public SupplementLabel(MesquiteModule ownerModule, HNode node, int which){
+		super(ownerModule);
+		setSize(10,10);
+		this.node = node;
+		this.which = which;
+		setText(node.getSupplementName(which)); //TODO: not just 0 in future
+		setColor(Color.white);
+		setVisible(true);
+		repaint();
+	}
+	
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		node.hSupplementTouched(which);   
+	}
+}
+
diff --git a/Source/mesquite/minimal/IDsDefaults/IDsDefaults.java b/Source/mesquite/minimal/IDsDefaults/IDsDefaults.java
new file mode 100644
index 0000000..eff17b2
--- /dev/null
+++ b/Source/mesquite/minimal/IDsDefaults/IDsDefaults.java
@@ -0,0 +1,125 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.IDsDefaults;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+public class IDsDefaults extends DefaultsAssistant {
+	public String getName() {
+		return "Unique IDs default";
+	}
+	public String getExplanation() {
+		return "Sets the preferences for storing unique ids.";
+	}
+	/*.................................................................................................................*/
+	MesquiteBoolean autoInventTaxaIDs, autoInventCharIDs;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		autoInventTaxaIDs = new MesquiteBoolean(Taxa.inventUniqueIDs);
+		autoInventCharIDs = new MesquiteBoolean(CharacterData.defaultInventUniqueIDs);
+		loadPreferences();
+		addCheckMenuItemToDefaults(null, "Invent Unique IDs for New Taxa", makeCommand("autoInventTaxaIDs",  this), autoInventTaxaIDs);
+		addCheckMenuItemToDefaults(null, "Invent Unique IDs for New Characters", makeCommand("autoInventCharIDs",  this), autoInventCharIDs);
+		return true;
+	}
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			Taxa.inventUniqueIDs = "store".equalsIgnoreCase(prefs[0]);
+			if (prefs.length>1){
+				CharacterData.defaultInventUniqueIDs = "store".equalsIgnoreCase(prefs[1]);
+			}
+
+		}
+	}
+	/*.................................................................................................................*
+	public String[] preparePreferencesForFile () {
+		if (!StringUtil.blank(MesquiteModule.author.getName())) {
+			if (Taxa.inventUniqueIDs) {
+				if (CharacterData.defaultInventUniqueIDs)
+					return (new String[] {"store", "store"});
+				else
+					return (new String[] {"store", "noStore"});
+			}
+			else {
+				if (CharacterData.defaultInventUniqueIDs)
+					return (new String[] {"noStore", "store"});
+				else
+					return (new String[] {"noStore", "noStore"});
+			}
+		}
+		return null;
+	}
+	*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("autoInventTaxaIDs".equalsIgnoreCase(tag)){
+			autoInventTaxaIDs.setValue(content);
+			Taxa.inventUniqueIDs = autoInventTaxaIDs.getValue();
+		
+		}
+		else if ("autoInventCharIDs".equalsIgnoreCase(tag)){
+			autoInventCharIDs.setValue(content);
+			CharacterData.defaultInventUniqueIDs = autoInventCharIDs.getValue();
+		}
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "autoInventTaxaIDs", autoInventTaxaIDs);  
+		StringUtil.appendXMLTag(buffer, 2, "autoInventCharIDs", autoInventCharIDs);  
+		return buffer.toString();
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(getClass(), "Toggles taxa id storage", null, commandName, "autoInventTaxaIDs")) {
+			autoInventTaxaIDs.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting() && autoInventTaxaIDs.getValue() != Taxa.inventUniqueIDs && !Taxa.inventUniqueIDs){
+				alert("Already existing taxa will not have new Unique ID's made for them automatically.  To assign ID's, show the column Unique IDs via the List menu of the List of Taxa, and use the column's drop down menu to adjust IDs");
+			}
+			Taxa.inventUniqueIDs = autoInventTaxaIDs.getValue();
+
+			storePreferences();
+
+			return null;
+
+		}
+		else if (checker.compare(getClass(), "Toggles character id storage", null, commandName, "autoInventCharIDs")) {
+			autoInventCharIDs.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting() && autoInventCharIDs.getValue() != CharacterData.defaultInventUniqueIDs && !CharacterData.defaultInventUniqueIDs){
+				alert("Already existing characters will not have new Unique ID's made for them automatically.  To assign ID's, show the column Unique IDs via the List menu of the List of Characters, and use the column's drop down menu to adjust IDs");
+			}
+			CharacterData.defaultInventUniqueIDs = autoInventCharIDs.getValue();
+			for (int ip = 0; ip<MesquiteTrunk.getProjectList().getNumProjects(); ip++){
+				MesquiteProject proj = MesquiteTrunk.getProjectList().getProject(ip);
+				for (int im = 0; im<proj.getNumberCharMatrices(); im++){
+					CharacterData m = proj.getCharacterMatrix(im);
+					m.setInventUniqueIDs(CharacterData.defaultInventUniqueIDs);
+				}
+			}
+			storePreferences();
+
+			return null;
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+}
+
+
diff --git a/Source/mesquite/minimal/Installer/Installer.java b/Source/mesquite/minimal/Installer/Installer.java
new file mode 100644
index 0000000..70cfef2
--- /dev/null
+++ b/Source/mesquite/minimal/Installer/Installer.java
@@ -0,0 +1,662 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.minimal.Installer;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import java.util.zip.*;
+import java.util.*;
+import java.io.*;
+
+import org.dom4j.Element;
+
+/*....+++++++++++++++Installer.  See also PhoneHomeUtil and NoticesAndInstallationExplanation.xml  ++++++++++++++++++++++++++..........*/
+/*
+ * The update/installation system relies on two sources of information: 
+ * (1) the notices of updates compiled by the Phone Home system, using getHomePhoneNumber() of modules to know where to call.  Packages can list these phone numbers
+ * for their own updating, but in addition we will maintain a central updates.xml in Mesquite so that newly released packages can be announced there.
+ * 
+ * (2) the local receipts for packages installed.  Most of these receipts may be acquired through the online
+ * installation process, but some may be acquired within packages installed by hand.  The file receipts.xml is compiled by Mesquite and stored in Mesquite_Folder/settings (it must be
+ * there as opposed to Mesquite_Support_Files because it belongs to the installation, not the user.
+ * 
+ * The main global variable are stored as statics in PhoneHomeUtil; the module managing the system is mesquite.minimal..Installer.
+ * 
+ * Update notices:  An update notice has messagetype "update".  See NoticesAndInstallationExplanation.xml in this package for examples.  A single update may make reference to multiple installation events.
+ * Key tags are as follows.  See NoticesAndInstallationExplanation.xml for a more complete list:
+ * -- the standard tags of notices from home (noticeNumber, messageType=update, explanation)
+ * -- identity: name that will uniquely identify your package; don't include version number , e.g. "PDAP"
+ * -- uniqueLocation: a location that should be unique to this package, to help mesquite know if a previous version is installed even if receipt is missing
+ * 			Must be within Mesquite_Folder, and relative to it.
+ * -- updateVersion: the version of the update, to determine if this or later update is already installed
+ * -- packageName: Human readable name of package or update
+ * -- explanation: note (if html, as CDATA) to display in notices dialog
+ * -- java: java version required
+ * -- requires:  human readable name of package this one needs to have already been installed.  MUST be paired with a requiredPath tag
+ * -- requiredPath: file or directory that is a litmus test as to whether the package on which this depends is already installed.  Mesquite merely check to see if this file or directory exists.  
+ * 			Must be within Mesquite_Folder, and relative to it.
+ * -- install:  each install element indicates one item to be installed.  There may be multiple (e.g. one for the package and one for a jar it needs)
+ *		within install:
+ *			-- location: the directory into which this item is to be put. Must be within Mesquite_Folder, and relative to it.
+ *			-- file: the file or directory that will be created within the above directory.  Used in part to retain prior copy in case something goes wrong in installation
+ *			-- url: the url from which to download the item.
+ *			-- treatment: either asis or unzip.  Note: zip files to be downloaded and unzipped must have been prepared by Mesquite itself as noted below
+ *			-- updateVersion: version of this particular item.  Not used, but might be in future
+ *			-- forOS: OS for which this item applies.  Accepts match if value occurs within "os.name" java System propery.  
+ *						There can be multiple forOS elements.  If none, it is assumed to apply to all OS's.
+ *					-- os: os name, e.g. "Windows" or "Mac OS X"
+ *					-- osVersion: optional.  If present must be an exact match.  Thus if you want an item to apply to Mac OS X 10.4 or 10.5, you must include two forOS elements
+ *	The above tags apply to all downloads.  In addition, if a download is an update only, e.g. a patch, then the following tag should be included:
+ * -- updateOnly, with values "false" (default), "true" a non critical update, and "critical" a critical update, e.g. a bug fix.
+ * 			If updateOnly is true or critical, then Mesquite will give notification of it only if the original package being updated appears to be installed.  This is judged by receipts or by the uniqueLocation tag
+ * 			If updateOnly is true, then Mesquite will give notification only once.
+ * 			If updateOnly is critical, then Mesquite will continue to give notification on each startup as long as original package being updated remains installed and critical update is not yet installed
+ * 
+ * Zip files must be prepared properly such that when unzipped they yield directly the directory stucture desired.  Zip files made by ZipIt on OS X do not work.  
+ * Installer can perform the zipping to ensure the zip files will work.  To enable this, select Debug Mode in File>Defaults and restart Mesquite.  
+ * Then, select File>Zip Folder.
+ * 
+ * 
+ * todo:
+ * GENERAL
+ * 
+ * INSTALL PIECE
+ * -- FUTURE (or in control of modules after they start): permit writing outside Mesquite
+ * -- FUTURE (or in control of modules after they start): permit scripts to run, e.g. to install outside of Mesquite_Folder
+ * 
+ * �-- Same protection in menu formation re java/dependencies
+ * �-- have dependency tag that indicates dependencies
+ * �-- make directories needed
+ * �-- permit OS-specific installs
+ * �-- what if dir not writable???
+ * �-- have require tag that indicates minimal Java version
+ * �-- receipt should contain more info
+ * �-- add tag "critical" to updates; these would get installed only if receipt and folders indicate installation already had been done
+ * �-- distinguish install and update, i.e. some do not give messages unless you already have older pakcage installed
+ * �-- check to see that receipts point to files that still exist; if not, then treat receipt as if it hadn't existed
+ * */
+public class Installer extends MesquiteInit {
+	public String getName() {
+		return "Installer";
+	}
+	public String getExplanation() {
+		return "Installs packages." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	/*.................................................................................................................*/
+	/** returns the URL of the notices file for this module so that it can phone home and check for messages */
+	public String  getHomePhoneNumber(){ 
+		if (!MesquiteTrunk.mesquiteTrunk.isPrerelease() && !MesquiteTrunk.debugMode)
+			return "http://mesquiteproject.org/mesquite/updates/updates.xml";
+		else
+			return "http://mesquiteproject.org/mesquite/prereleasenotices/updates.xml";   
+		//NOTE mesquite.minimal.Defaults.Defaults has own home phone number for server to record build numbers in use
+	}
+	/*.................................................................................................................*/
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (MesquiteTrunk.debugMode){
+			mesquiteTrunk.addMenuItem(MesquiteTrunk.fileMenu, "Zip Folder for Installer", makeCommand("zipDir", this));
+			//mesquiteTrunk.addMenuItem(MesquiteTrunk.fileMenu, "Zip File for Installer", makeCommand("zipFile", this));
+		}
+		readReceipts();
+		return true;
+	}
+	/*.................................................................................................................*/
+	void readReceipts(){
+		readReceipts(getInstallationSettingsPath() + "receipts.xml");
+		File mesquite = new File(getRootPath()+ "mesquite"); 
+		String[] folders = mesquite.list(); 
+		for (int i=0; i<folders.length; i++){
+			readReceipts(getRootPath() + "mesquite/" + folders[i] + "/receipts.xml");
+		}
+
+	}
+	void readReceipts(String path){
+		String receiptsContents = null;
+		try{
+			receiptsContents = MesquiteFile.getFileContentsAsString(path, 2000000, 100, false);
+		} catch (Exception e) {
+			return;
+		}
+		if (StringUtil.blank(receiptsContents))
+			return;
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite",receiptsContents);
+		if (root==null)
+			return;
+		List receipts = root.elements("installationReceipt");
+		boolean stillInstalled = true;
+		for (Iterator iter = receipts.iterator(); iter.hasNext();) {   // this is going through all of the notices
+			Element messageElement = (Element) iter.next();
+			ListableVector v = new ListableVector();
+			v.addElement(new MesquiteString("identity", messageElement.elementText("identity")), false);
+			v.addElement(new MesquiteString("updateVersion", messageElement.elementText("updateVersion")), false);
+			List locs = messageElement.elements("location");
+			for (Iterator locsIter = locs.iterator();  locsIter.hasNext();) {   // this is going through all of the notices
+				Element locElement = (Element) locsIter.next();
+				String p = locElement.elementText("path");
+				if (!MesquiteFile.fileOrDirectoryExists(MesquiteTrunk.getRootPath() + p))
+					stillInstalled = false;
+				v.addElement(new MesquiteString("location", locElement.elementText("path")), false);
+
+			}
+			v.addElement(new MesquiteString("explanation", messageElement.elementText("explanation")), false);
+			v.addElement(new MesquiteString("packageName", messageElement.elementText("packageName")), false);
+			v.addElement(new MesquiteString("uniqueLocation", messageElement.elementText("uniqueLocation")), false);
+			Element elup = messageElement.element("updateXML");
+			if (elup != null)
+				v.addElement(new MesquiteString("updateXML",  clean(XMLUtil.getElementAsXMLString(elup, "UTF-8", true)) ), false);
+			//	v.addElement(new MesquiteString("updateXML", "<updateXML>\n" + XMLUtil.getElementAsXMLString(elup, "UTF-8", true) + "</updateXML>" ), false);
+
+			if (!PhoneHomeUtil.alreadyInReceipts(v)){
+				if (stillInstalled)
+					PhoneHomeUtil.installedReceipts.addElement(v);
+			}
+		}
+		writeReceipts();  //rewrite into central
+	}
+
+	String clean(String ux){
+		ux = StringUtil.replace(ux, "\n", null);
+		ux = StringUtil.replace(ux, "\r", null);
+		ux = StringUtil.replace(ux, "\t", null);
+		ux = StringUtil.stripStuttered(ux, "  ");
+		return ux;
+	}
+	/*.................................................................................................................*/
+	void writeReceipts(){
+
+		StringBuffer buff = new StringBuffer();
+		buff.append("<?xml version=\"1.0\"?>\n<mesquite>\n");
+		for (int i=0; i< PhoneHomeUtil.installedReceipts.size(); i++){
+			ListableVector rec = (ListableVector)PhoneHomeUtil.installedReceipts.elementAt(i);
+			buff.append("\t<installationReceipt>\n");
+			buff.append("\t\t<identity>" + ((MesquiteString)rec.getElement("identity")).getValue() + "</identity>\n");
+			buff.append("\t\t<updateVersion>" + ((MesquiteString)rec.getElement("updateVersion")).getValue() + "</updateVersion>\n");
+			List locs = rec.getElements("location");
+			for (Iterator iter = locs.iterator();  iter.hasNext();) {   // this is going through all of the notices
+				MesquiteString loc = (MesquiteString) iter.next();
+				buff.append("\t\t<location><path>" + loc.getValue() + "</path></location>\n");
+
+			}
+
+			buff.append("\t\t<explanation><![CDATA[" + ((MesquiteString)rec.getElement("explanation")).getValue() + "]]></explanation>\n");
+			buff.append("\t\t<packageName>" + ((MesquiteString)rec.getElement("packageName")).getValue() + "</packageName>\n");
+			buff.append("\t\t<uniqueLocation>" + ((MesquiteString)rec.getElement("uniqueLocation")).getValue() + "</uniqueLocation>\n");
+			MesquiteString ux = (MesquiteString)rec.getElement("updateXML");
+			if (ux != null){
+				buff.append("\t\t" + clean(ux.getValue()) + "\n");
+			}
+			buff.append("\t</installationReceipt>\n");
+		}
+		buff.append("\n</mesquite>");
+		MesquiteFile.createDirectory(getInstallationSettingsPath() );  
+		MesquiteFile.putFileContents(getInstallationSettingsPath() + "receipts.xml", buff.toString(), true, false);
+	}
+
+	/*.................................................................................................................*/
+	void copy(InputStream in, OutputStream out) throws IOException {
+		byte[] buffer = new byte[1024];
+		int len;
+		while((len = in.read(buffer)) >= 0)
+			out.write(buffer, 0, len);
+		in.close();
+		out.close();
+	}
+
+	/*.................................................................................................................*/
+	boolean zipDirectory(String sourceBase, String source, String destination){
+		try { 
+			ZipOutputStream zipOutput = new ZipOutputStream(new FileOutputStream(destination)); 
+			String p = source;
+			String subst = p.substring(sourceBase.length(), p.length());
+			if (!subst.endsWith("/"))
+				subst += "/";
+			ZipEntry zentry = new ZipEntry(subst); 
+			zipOutput.putNextEntry(zentry); 
+			zipDir(sourceBase, source, zipOutput); 
+			zipOutput.close(); 
+			return true;
+		} 
+		catch(Exception e) { 
+			MesquiteMessage.warnProgrammer("ZIP FAILED");
+		} 
+		return false;
+	}
+	public void zipDir(String sourceBase, String directoryPath, ZipOutputStream zipOutput) { 
+		File zipDirec;
+		try { 
+			CommandRecord.tick("Zipping " + directoryPath);
+			logln("Zipping " + directoryPath);
+
+			zipDirec = new File(directoryPath); 
+
+			String[] files = zipDirec.list(); 
+			byte[] buff = new byte[2156]; 
+			int numbyes = 0; 
+
+			for(int i=0; i<files.length; i++)  { 
+				if (!files[i].startsWith(".")){
+					File f = new File(zipDirec, files[i]); 
+					if(f.isDirectory())  { 
+						String p = f.getPath();
+						String subst = p.substring(sourceBase.length(), p.length());
+						if (!subst.endsWith("/"))
+							subst += "/";
+						ZipEntry zEntry = new ZipEntry(subst); 
+						zipOutput.putNextEntry(zEntry); 
+						String filePath = f.getPath(); 
+						zipDir( sourceBase, filePath, zipOutput); 
+						continue; 
+					} 
+					FileInputStream instream = new FileInputStream(f); 
+					String p = f.getPath();
+					String subst = p.substring(sourceBase.length(), p.length());
+					if (!subst.endsWith("/") && f.isDirectory())
+						subst += "/";
+					ZipEntry zentry = new ZipEntry(subst); 
+					zipOutput.putNextEntry(zentry); 
+					while((numbyes = instream.read(buff)) != -1) { 
+						zipOutput.write(buff, 0, numbyes); 
+					} 
+					instream.close(); 
+				}
+			} 
+		} 
+		catch(Exception e) { 
+		} 
+	}
+	boolean unzip(String loc, String file){
+		ZipFile zipFile;
+		Enumeration entries;
+		try {
+			zipFile = new ZipFile(loc + file);
+
+			entries = zipFile.entries();
+
+			while(entries.hasMoreElements()) {
+				ZipEntry entry = (ZipEntry)entries.nextElement();
+				String name = entry.getName();
+				if (!name.startsWith(".")){
+					if(entry.isDirectory()) {					
+						(new File(loc + entry.getName())).mkdir();
+						continue;
+					}
+					copy(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(loc +entry.getName())));
+				}
+			}
+
+			zipFile.close();
+			return true;
+		} 
+		catch (IOException ioe) {
+			ioe.printStackTrace();
+		}
+		return false;
+	}
+
+	boolean applicableOS(Element installElement){
+		List osList = installElement.elements("forOS");
+		if (osList == null)
+			return true;
+		if (osList.size() == 0)
+			return true;
+		for (Iterator i = osList.iterator(); i.hasNext();) {   // this is going through all of the notices
+			Element osElement = (Element) i.next();
+			String os = osElement.elementText("os");
+			if (os == null)
+				return true;
+			String osVersion = osElement.elementText("osVersion");
+			String osArch = osElement.elementText("osArch");
+			boolean osArchMatches =(StringUtil.blank(osArch)|| System.getProperty("os.arch").indexOf(osArch)>=0);
+			boolean osMatches =(StringUtil.blank(os)|| System.getProperty("os.name").indexOf(os)>=0 || (os.equalsIgnoreCase("other") && !MesquiteTrunk.isWindows() && !MesquiteTrunk.isMacOSX()));
+
+			boolean osVersionMatches =(StringUtil.blank(osVersion)|| System.getProperty("os.version").startsWith(osVersion));
+			if (osMatches && osVersionMatches && osArchMatches)
+				return true;
+
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean executeScriptString(String script, boolean precedeWithCDToMesquiteFolder){
+		MesquiteBoolean b = new MesquiteBoolean();
+		String scriptPath  = createSupportDirectory(b) + MesquiteFile.fileSeparator + "script";
+		if (precedeWithCDToMesquiteFolder)
+			script = ShellScriptUtil.getChangeDirectoryCommand(getRootPath()) + script;
+		MesquiteFile.putFileContents(scriptPath, script, false);
+		return ShellScriptUtil.executeAndWaitForShell(scriptPath, "installScript");
+	}
+
+	//returns 1 if OK
+	// 0 if unknown problem in downloading/writing
+	// -1 if problem reading from server
+	// -2 if problem writing download
+	// -3 if user request to cancel
+	// -4 if unzipping problem
+	// -5, -6 if script execution problem
+	int install(Element installElement, ListableVector receipt){
+		if (!applicableOS(installElement))
+			return 1;  //return true because not considered failure if inapplicable OS
+		String url = installElement.elementText("url");
+		String fileName = installElement.elementText("file");
+		String pathInMesquiteFolder = installElement.elementText("location");
+		String locationInMesquiteFolder = installElement.elementText("location");
+		if (!StringUtil.blank(locationInMesquiteFolder))
+			locationInMesquiteFolder = locationInMesquiteFolder + MesquiteFile.fileSeparator;
+
+		String directoryLocation = getRootPath() + locationInMesquiteFolder;
+		if (pathInMesquiteFolder != null && pathInMesquiteFolder.equalsIgnoreCase(":query user")){
+			String dL = MesquiteFile.chooseDirectory("Choose location for " + fileName);
+			if (dL != null)
+				directoryLocation = dL + MesquiteFile.fileSeparator;
+			else
+				directoryLocation = getRootPath();
+		}
+		int version = MesquiteInteger.fromString(installElement.elementText("updateVersion"));  
+		String treatment = installElement.elementText("treatment");
+		String execute = installElement.elementText("execute");
+		String executeInMesquiteFolder = installElement.elementText("executeInMesquiteFolder");
+		String downloadAs = "installerDownload";
+		if (treatment == null || treatment.equalsIgnoreCase("asis"))
+			downloadAs = fileName;
+		String prevPackagePath = directoryLocation + fileName;
+		String tempPackagePath = directoryLocation  + fileName+ "PREVIOUSVERSION";
+		File prevPackage = new File(prevPackagePath);
+		boolean hadExisted = prevPackage.exists();
+		if (false && hadExisted){
+			String prevVString = MesquiteFile.getFileContentsAsString(getRootPath() +  locationInMesquiteFolder + fileName+ "/version.txt");
+			int prevVersion  = MesquiteInteger.fromString(prevVString);
+			if (false && prevVersion >= version){
+				if (!AlertDialog.query(containerOfModule(), "Replace?", "The version of the package " + fileName + " installed (" + prevVersion + ") is the same as or newer than the one to be downloaded (" + version + ") .  Do you want to replace it with the one to be downloaded?")){
+					return -3;
+				}
+			}
+		}
+		if (url != null){
+			logln("Downloading installation file from " + url);
+			if (!MesquiteFile.fileOrDirectoryExists(directoryLocation)){
+				MesquiteFile.createDirectory(directoryLocation);
+			}
+			if (hadExisted){
+				logln("Renaming old version of " + fileName + " to " + fileName + "PREVIOUSVERSION");
+				MesquiteFile.rename(prevPackagePath, tempPackagePath);
+			}
+			logln("Downloading installation file to " + directoryLocation + downloadAs);
+			int response = MesquiteFile.downloadURLContents(url, directoryLocation + downloadAs, true, true);
+			if (response == 1){
+				boolean fileReady = true;
+				if (treatment != null && treatment.equalsIgnoreCase("unzip")){
+					logln("Unzipping installation file");
+					fileReady = unzip(directoryLocation, downloadAs);
+					if (fileReady)
+						MesquiteFile.deleteFile(directoryLocation + downloadAs);
+				}
+				if (fileReady){
+					logln("Installation of " + fileName + " was successful.");
+					receipt.addElement(new MesquiteString("location", locationInMesquiteFolder + fileName), false);
+				}
+				else if (hadExisted){
+					logln("Installation unsuccessful; attempting to recover old version of " + fileName);
+					MesquiteFile.rename(tempPackagePath, prevPackagePath);
+					return -4;
+				}
+			}	
+			else {
+				MesquiteFile.deleteFile(directoryLocation + downloadAs);
+				return response;
+			}
+		}
+		if (execute != null){
+			String shortEx = execute;
+			if (execute.length() > 500)
+				shortEx = execute.substring(0, 500);
+			if (AlertDialog.query(containerOfModule(), "Execute Script?", "The installer has downloaded the following script to execute.  Is it OK to execute it?\n"+ shortEx)){
+				logln("Executing script");
+				if (!executeScriptString(execute, false)){
+					logln("Script execution unsuccessful");
+					return -5;
+				}
+			}
+		}
+		if (executeInMesquiteFolder != null){
+			String shortEx = executeInMesquiteFolder;
+			if (executeInMesquiteFolder.length() > 500)
+				shortEx = executeInMesquiteFolder.substring(0, 500);
+			shortEx = "<first, change directories into Mesquite_Folder>\n" + shortEx;
+			if (AlertDialog.query(containerOfModule(), "Execute Script?", "The installer has downloaded the following script to execute.  Is it OK to execute it?\n"+ shortEx)){
+				logln("Executing script");
+				if (!executeScriptString(executeInMesquiteFolder, true)){
+					logln("Script execution unsuccessful");
+					return -6;
+				}
+			}
+		}
+		return 1;
+	}
+	void cleanUp(Element installElement){
+		String pathInMesquiteFolder = installElement.elementText("location");
+		if (!StringUtil.blank(pathInMesquiteFolder))
+			pathInMesquiteFolder = pathInMesquiteFolder + "/";
+		String fileName = installElement.elementText("file");
+		File tempPackage = new File(getRootPath() + pathInMesquiteFolder   + fileName+ "PREVIOUSVERSION");
+		boolean hadExisted = tempPackage.exists();
+		if (hadExisted){
+			logln("Deleting old version of " + fileName);
+			if (tempPackage.isDirectory())
+				MesquiteFile.deleteDirectory(getRootPath() + pathInMesquiteFolder  + fileName+ "PREVIOUSVERSION");
+			else 
+				MesquiteFile.deleteFile(getRootPath() + pathInMesquiteFolder  + fileName+ "PREVIOUSVERSION");
+		}
+	}
+	void reverse(Element installElement){
+		String pathInMesquiteFolder = installElement.elementText("location");
+		if (!StringUtil.blank(pathInMesquiteFolder))
+			pathInMesquiteFolder = pathInMesquiteFolder + "/";
+		String fileName = installElement.elementText("file");
+		String prevPackagePath = getRootPath() + pathInMesquiteFolder  + fileName;
+		String tempPackagePath = getRootPath() + pathInMesquiteFolder   + fileName+ "PREVIOUSVERSION";
+		File prevPackage = new File(prevPackagePath);
+
+		File tempPackage = new File(tempPackagePath);
+		boolean hadExisted = tempPackage.exists();
+		if (hadExisted){
+			logln("Installation unsuccessful; attempting to recover old version of " + fileName);
+			if (prevPackage.isDirectory())
+				MesquiteFile.deleteDirectory(getRootPath() + pathInMesquiteFolder  + fileName);
+			else 
+				MesquiteFile.deleteFile(getRootPath() + pathInMesquiteFolder  + fileName);
+			MesquiteFile.rename(tempPackagePath, prevPackagePath);
+		}
+	}
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "phoneHomeLinkTouched", null, commandName, "phoneHomeLinkTouched") || checker.compare(this.getClass(), "phoneHomeLinkTouchedAdHoc", null, commandName, "phoneHomeLinkTouchedAdHoc")) {
+			boolean adHoc =  (commandName.equalsIgnoreCase("phoneHomeLinkTouchedAdHoc"));
+			if (!MesquiteFile.canWrite(getRootPath())){
+				discreetAlert("Sorry, you do not have the permissions required to modify the Mesquite_Folder.  Installation cannot proceed.");
+				return null;
+			}
+			String source = parser.getFirstToken(arguments);
+			ListableVector updateRecord = null;
+			if (adHoc)
+				updateRecord = PhoneHomeUtil.adHocRecord;
+			else
+				updateRecord = PhoneHomeUtil.getUpdateRecord(source.substring(source.indexOf(":")+1, source.length()));
+			if (updateRecord == null)
+				return null;
+			MesquiteString identity = (MesquiteString)updateRecord.getElement("identity");
+			MesquiteString versionString = (MesquiteString)updateRecord.getElement("updateVersion");
+			MesquiteString packageName = (MesquiteString)updateRecord.getElement("packageName");
+			MesquiteString explanation = (MesquiteString)updateRecord.getElement("explanation");
+			MesquiteString uniqueLocation = (MesquiteString)updateRecord.getElement("uniqueLocation");
+			MesquiteString updateXML = (MesquiteString)updateRecord.getElement("updateXML");
+			MesquiteString beforeMessage = (MesquiteString)updateRecord.getElement("beforeMessage");
+			MesquiteString afterMessage = (MesquiteString)updateRecord.getElement("afterMessage");
+			ListableVector receipt = new ListableVector();
+			receipt.addElement(identity, false);
+			receipt.addElement(versionString, false);
+			receipt.addElement(explanation, false);
+			receipt.addElement(packageName, false);
+			receipt.addElement(uniqueLocation, false);
+			if (updateXML != null)
+				receipt.addElement(updateXML, false);
+			boolean asked = false;
+			if (!adHoc && PhoneHomeUtil.alreadyInReceipts(identity.getValue(), versionString.getValue())){
+				if (!MesquiteThread.isScripting() && !AlertDialog.query(containerOfModule(), "Install?", "The package " + packageName + " of the same version already appears to be installed.  Do you want to reinstall?"))
+					return null;
+				else asked = true;
+			}
+			if ((adHoc || !asked) && !MesquiteThread.isScripting() && !AlertDialog.query(containerOfModule(), "Install?", "You have requested to install " + packageName + ".  Do you want to install it now?"))
+				return null;
+			if (beforeMessage != null && !StringUtil.blank(beforeMessage.getValue()))
+				discreetAlert(beforeMessage.getValue());
+			parser.setString(versionString.getValue());
+			int version = MesquiteInteger.fromString(parser);
+			ObjectContainer io = (ObjectContainer)updateRecord.getElement("install");
+			List installation = (List)io.getObject();
+			int count = 0;
+			boolean failed = false;
+			MesquiteTrunk.suppressMenuResponse = true;
+			try {
+				//hide all project windows
+				Enumeration e = MesquiteTrunk.mesquiteTrunk.windowVector.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					MesquiteWindow mw = (MesquiteWindow)obj;
+					if (!(mw instanceof SystemWindow) && !(mw instanceof mesquite.trunk.AboutWindow))
+						mw.getParentFrame().setVisible(false);
+				}
+				Projects projects = MesquiteTrunk.mesquiteTrunk.getProjectList();
+				for (int ip = 0; ip< projects.getNumProjects(); ip++){
+					MesquiteProject proj = projects.getProject(ip);
+
+				}
+				int failures = 0;
+				for (Iterator iter = installation.iterator(); !failed && iter.hasNext();) {   // this is going through all of the notices
+					Element installElement = (Element) iter.next();
+					//returns 1 if OK
+					// 0 if unknown problem in downloading/writing
+					// -1 if problem reading from server
+					// -2 if problem writing download
+					// -3 if user request to cancel
+					// -4 if unzipping problem
+					// -5, -6 if script execution problem
+					int response = install(installElement, receipt);
+					if (response == 1) 
+						count++;
+					else {
+						failed = true;
+						failures ++;
+						if (failures == 1){
+							if (response == 0)
+								discreetAlert("There was an unknown problem downloading and writing a file.");
+							else if (response == -1)
+								discreetAlert("There was a problem downloading the update from the server.  Your internet connection or the server may be down.");
+							else if (response == -2)
+								discreetAlert("There was a problem saving the downloaded files.  It is possible that Mesquite doesn’t have permission to make modifications within Mesquite_Folder.  This can happen, for example, if Mesquite_Folder is in the Applications or Program Files folder.  One possible fix is to move Mesquite_Folder to your own user directory, and try again to update.");
+							else if (response == -3)
+								discreetAlert("You have decided to cancel the update.");
+							else if (response == -4)
+								discreetAlert("There was a problem unzipping the downloaded update.");
+							else if (response == -5 || response == -6)
+								discreetAlert("There was a problem executing the install script (" + response + ")");
+						}
+					}
+				}
+			}
+			catch (Throwable t){
+				failed = true;
+			}
+			MesquiteTrunk.suppressMenuResponse = false;
+			int i = 0;
+			if (failed)
+				discreetAlert("Installation was UNSUCCESSFUL; Mesquite will attempt to restore any previous versions");
+			for (Iterator iter = installation.iterator(); iter.hasNext();) {   // this is going through all of the notices
+				Element installElement = (Element) iter.next();
+				if (failed){
+					if (i<=count)
+						reverse(installElement);
+				}
+				else 
+					cleanUp(installElement);
+				i++;
+			}
+			//show all project windows
+			Enumeration e2 = MesquiteTrunk.mesquiteTrunk.windowVector.elements();
+			while (e2.hasMoreElements()) {
+				Object obj = e2.nextElement();
+				MesquiteWindow mw = (MesquiteWindow)obj;
+				if (!(mw instanceof SystemWindow) && !(mw instanceof mesquite.trunk.AboutWindow))
+					mw.getParentFrame().setVisible(true);
+			}
+
+			if (!failed){
+				//Here mesquite should store a receipt that this update was installed.  Should store package reference and version reference.  
+				if (!PhoneHomeUtil.alreadyInReceipts(receipt))
+					PhoneHomeUtil.installedReceipts.addElement(receipt);
+				writeReceipts();
+				PhoneHomeUtil.refreshUpdateMenuItems();
+				discreetAlert("Installation was successful.  You will need to restart Mesquite to make use of the new installation.");
+				if (afterMessage != null && !StringUtil.blank(afterMessage.getValue()))
+					discreetAlert(afterMessage.getValue());
+				resetAllMenuBars();
+			}
+		}
+		else if (checker.compare(this.getClass(), "zip directory", null, commandName, "zipDir")) {
+			String source = MesquiteFile.chooseDirectory("Directory to Zip", null);
+			String destination = MesquiteFile.saveFileAsDialog("Save zip file", null);
+			if (zipDirectory(MesquiteFile.getDirectoryPathFromFilePath(source), source, destination))
+				alert("Zip successful");
+			else
+				alert("Zip unsuccessful!!!!");
+		}
+		else if (checker.compare(this.getClass(), "zip file", null, commandName, "zipFile")) {
+			String source = MesquiteFile.openFileDialog("File to Zip",  null,  null);
+			String destination = MesquiteFile.saveFileAsDialog("Save zip file", null);
+			if (zipDirectory(MesquiteFile.getDirectoryPathFromFilePath(source), source, destination))
+				alert("Zip successful");
+			else
+				alert("Zip unsuccessful!!!!");
+		}
+		else 		if (checker.compare(this.getClass(), "Unzips", null, commandName, "unzip")) {
+			//unzip();
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/minimal/Installer/NoticesAndInstallationExplanation.xml b/Source/mesquite/minimal/Installer/NoticesAndInstallationExplanation.xml
new file mode 100644
index 0000000..ef573a1
--- /dev/null
+++ b/Source/mesquite/minimal/Installer/NoticesAndInstallationExplanation.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0"?>
+<mesquite>
+	<MessagesFromHome>
+		<version>1</version>
+		<!--@@@@@@@@@@@@@@@@@@@@  THIS IS AN EXAMPLE and EXPLANATION of the notices, installation and update system (NoticesAndInstallationExplanation.xml)
+		Applicable for Mesquite 2.73 and up; not too different for earlier versions
+		
+		This format is used for notices, installs and updates.
+		These notices are processed in mesquite.lib.PhoneHomeUtil and mesquite.minimal.Installer.Installer.java.
+		
+		Typical use
+		For users to install your package: zip your package and put it on a website for http access.  See instructions below for zipping.  
+		  Create a file like this one named "install.xml" and include on website. 
+		  Tell users to point Check Now For Notices/Installs (in the File menu) to http://yourwebsite/install.xml.
+		For notices and updates for your package: in the package intro module of your package, include the method public String getHomePhoneNumber(), 
+		  returning the intended address for your notices file, e.g. "http://yourwebsite/notices.xml".  
+		  Mesquite will check that URL and process the file on your behalf on startup.  The user can be notified of an update, and
+		  the update installed on request.
+		  
+		These files have two fundamental elements:
+		
+		notice -- used for messages to users, installation and updating/patching.  This is described below with examples; also see other files in 
+		Mesquite_Folder/mesquite/minimal/Installer
+		
+		currentReleaseVersion -- indicates to Mesquite what is the current release version.  
+		This enables Mesquite to keep reminding the user that they don't have the most recent version.  This should be placed in file at the getHomePhoneNumber URL
+		so that it is checked on startup.  An example of this element is in updateExample.xml
+		
+		A single xml notices file can have multiple notices; each is treated separately.
+		
+		NOTE: this file is designed as an installation file, not as an update/patch.  See updateExample.xml for an example of an update file.
+		@@@@@@@@@@@@@@@@@@@@ -->
+		
+		<notice>
+		
+			<!-- ##################### HEADER SECTION: determines what type of message and whether it's applicable.
+			This section is not well designed, nor is the java code handling it.  It may be a bit flaky.
+			In theory the following elements determine whether the notice is applicable to this version, 
+			but the implicit boolean calculations may or may not be well handled in the java code.
+			
+			forMesquiteVersionLessOrEqual -- Integer (e.g. 250 for 2.50).  Intended for use only by Mesquite itself
+			forBuildNumberExactly -- Integer.  Refers to Mesquite build number (e.g., 528 for v. 2.72) intended to ensure compatibility or relevance
+			forBuildNumberEqualOrGreater -- Integer.  Refers to Mesquite build, intended to ensure compatibility or relevance
+			forBuildNumberEqualOrLess -- Integer.  Refers to Mesquite build, intended to ensure compatibility or relevance
+			forPackageVersionExactly -- Integer.  Refers to package build number, used for automatic phone home system of installed packages
+			forPackageVersionEqualOrGreater -- Integer.  Refers to package build number, used for automatic phone home system of installed packages
+			forPackageVersionEqualOrLess -- Integer.  Refers to package build number, used for automatic phone home system of installed packages
+			java -- Real number (decimal).  Refers to required java version, e.g. 1.4.
+			requiredPath -- Relative path within Mesquite_Folder.  If this path does not exist in Mesquite_Folder, then notice is ignored.  Can be used for dependencies.
+			requires -- Human readable name of required component. Used in explanation to user if requiredPath is not present.
+			 
+			noticeNumber -- REQUIRED.  This is critical; keep incrementing it for each new notice for your package.  Mesquite uses this to determine
+			if it has already notified the user; if it has give the user notice n then in the future it suppresses notices with numbers n or less,
+			unless it's a specific request using Check Now for Notices/Installs.  Mesquite stores its record of notices already given in
+			Mesquite_Support_Files/Mesquite_prefs/phoneRecords.xml.
+			
+ 			messageType -- REQUIRED.  If a simple notice then type should be "alert"; otherwise "update" is used for installs or updates
+ 			
+ 			updateOnly -- if has value "critical" then Mesquite will continue to pester user on startup even if the message has been seen before
+ 			
+			identity -- name that will uniquely identify your package; don't include version number. This is the tag that Mesquite
+			remembers in connection with the notice numbers already shown		
+ 			
+ 			uniqueLocation -- for installs/updates, this refers to a relative path within Mesquite_Folder that 
+ 			should be unique to this package, to help Mesquite know if a previous version is installed 
+ 			even if receipt is missing
+ 			
+ 			updateVersion -- the version of the install/update, to help determine if this or later update is already installed
+ 			
+ 			packageName -- Human readable name of package or update, for the dialog box when notices are shown to user
+ 			
+ 			beforeMessage -- a message to the user that is given before the installation starts, e.g. "This update may take a while to download; please wait until a message appears saying it's finished."
+  			afterMessage -- a message to the user that is given after the installation finishes, e.g. "The update is done.  Thank you."
+ 			
+			######################### -->
+			
+			<forBuildNumberEqualOrGreater>530</forBuildNumberEqualOrGreater>
+			<noticeNumber>1</noticeNumber>
+			<messageType>update</messageType>			
+			<identity>deleteMe</identity> 
+			<uniqueLocation>mesquite/deleteMe</uniqueLocation> 			
+			<updateVersion>000</updateVersion>			
+			<packageName>DeleteMe version 0.0</packageName>
+			
+			
+			<!-- ##################### EXPLANATION SECTION: This is the notice shown to the user. 
+			Should be in html.  Can have href links that then open up in a browser.  
+			########################## -->
+			
+			<explanation>
+			<![CDATA[<img src="http://mesquiteproject.org/packages/examples/deleteMe/splash.gif"><p>
+			DeleteMe is a small package that is installed to demonstrate Mesquite's installation features.
+			]]>
+			</explanation>
+			
+			
+			<!-- ##################### INSTALL SECTION: Used for installs and updates. 
+			The install sections are processed primarily by mesquite.minimal.Installer.Installer.  
+			
+			install -- Notice that a single notice can have multiple pieces installed.  Each piece is installed with a single
+			install statement.
+			
+			The install statement's elements are:
+			
+				location --  REQUIRED. Path to contain the installation, relative to and within Mesquite_Folder.  Thus, "mesquite" means the installation
+				is to occur within Mesquite_Folder/mesquite. The file at the URL specified by the url element is downloaded into this location.  If the path
+				does not exist, it will be created within Mesquite_Folder.  
+				NOTE: if the value of this is ":query user", then the user will be queried for a location.
+				This can be useful for components like example files or documentation.
+				
+				file -- REQUIRED. The file or folder within the location above that is to be installed or updated.  Thus, if you are installing or
+				updating the folder Mesquite_Folder/mesquite/deleteMe, then you indicate location as "mesquite" and file as "deleteMe".  This is important
+				to help Mesquite prepare for installation.  This file, if it already exists, is temporarily renamed by adding the suffix "PREVIOUSVERSION"
+				to save it in case the installation must be undone.
+				
+				url -- REQUIRED. The absolute url from which the item to be installed is to be obtained.  Must be a single file.  Before
+				
+				treatment -- REQUIRED. How to treat the file downloaded, either asis or unzip. "Asis" is typically used for jar files, 
+				scripts, and single class files.  "Unzip" is used for folders, e.g. a package.  
+				by the location element, then unzipped.  See PREPARING ZIP ARCHIVES for information on how to zip a folder or package.
+				
+				updateversion -- I'm not sure if this is used!!!
+				
+				forOS -- Indicates if this component is OS-specific. See applicableOS method of mesquite.minimal.Installer.Installer. Its elements are:
+				
+					os -- Usually, "Mac OS X", "Windows", or "other".  Value must be a substring of java's System.getProperty("os.name"), 
+					or if value is "other", then system must be one other than Windows or Mac OS X
+					
+					osVersion -- Value must be starting substring of java's System.getProperty("os.version")
+					
+					osArch -- Value must be a substring of java's System.getProperty("os.arch").indexOf(osArch).
+ 				
+ 				execute -- execute the string as a batch file/shell script.  This would probably be an os-specific element.
+ 				The user will be shown the script and asked to confirm that it is to be executed!!! 
+ 				Please be polite.  This was enabled to permit executable bits to be set on some components.
+ 				
+ 				executeInMesquiteFolder -- as for execute, but first change current directory to be Mesquite_Folder. For example:
+ 				<executeInMesquiteFolder>chmod +x myShellScript.sh</executeInMesquiteFolder>
+
+			PREPARING ZIP ARCHIVES
+			Packages and folders must be zipped with java.  Mesquite can zip the packages for you.
+			To zip a folder, first turn on Debug Mode (under Defaults in the File menu).  Then, restart Mesquite and you will see in the File menu
+			the item Zip Folder For Installer.  Zip the package folder itself.  For example, if you want to distribute the package myPackage,
+			that would normally reside at Mesquite_Folder/mesquite/myPackage, then zip just the folder myPackage ("Mesquite_Folder") and indicate in
+			the location element the location "mesquite", and for the file, "myPackage". 
+		
+			######################### -->
+			<install>
+				<location>mesquite</location>
+				<file>deleteMe</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/mesquite.deleteMe.zip</url>
+				<treatment>unzip</treatment>
+				<updateVersion>000</updateVersion>
+			</install>
+			<install>
+				<forOS>
+					<os>Mac OS X</os>
+					<osVersion>10.3</osVersion>
+				</forOS>
+				<forOS>
+					<os>Mac OS X</os>
+					<osVersion>10.4</osVersion>
+				</forOS>
+				<location>jars</location>
+				<file>deleteMe104.jar</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/deleteMe104.jar</url>
+				<treatment>asis</treatment>
+				<updateVersion>000</updateVersion>
+			</install>
+			<install>
+				<forOS>
+					<os>Mac OS X</os>
+					<osVersion>10.5</osVersion>
+					<osArch>86</osArch>
+				</forOS>
+				<location>jars</location>
+				<file>deleteMe105.jar</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/deleteMe105.jar</url>
+				<treatment>asis</treatment>
+				<updateVersion>000</updateVersion>
+			</install>
+			<install>
+				<forOS>
+					<os>Windows</os>
+				</forOS>
+				<location>jars</location>
+				<file>deleteMeWin.jar</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/deleteMeWin.jar</url>
+				<treatment>asis</treatment>
+				<updateVersion>000</updateVersion>
+			</install>
+		</notice>
+		
+		
+
+	</MessagesFromHome>
+</mesquite>
diff --git a/Source/mesquite/minimal/Installer/installExample.xml b/Source/mesquite/minimal/Installer/installExample.xml
new file mode 100644
index 0000000..3e4e22f
--- /dev/null
+++ b/Source/mesquite/minimal/Installer/installExample.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<mesquite>
+	<MessagesFromHome>
+		<version>1</version>
+
+		<notice><!--A simple installation -->
+			<forBuildNumberEqualOrGreater>537</forBuildNumberEqualOrGreater> <!-- this refers to Mesquite build, e.g. for compatibility -->
+			<noticeNumber>1</noticeNumber>
+			<messageType>update</messageType>
+			<identity>DeleteMe</identity>
+			<updateVersion>001</updateVersion>
+			<packageName>DeleteMe v. 1.01</packageName>
+			<explanation>
+			<![CDATA[<img src="http://mesquiteproject.org/packages/examples/deleteMe/splash.gif"><p>
+			DeleteMe is a package of Mesquite modules designed as an example, merely to be deleted.  
+			For more information about its, see the 
+			<a href = "http://mesquiteproject.org/packages/examples/deleteMe">MyPackage web page</a>.
+			]]>
+			</explanation>
+			<install>
+				<location>mesquite</location>
+				<file>deleteMe</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/mesquite.deleteMe.zip</url>
+				<treatment>unzip</treatment>
+				<updateVersion>001</updateVersion>
+			</install>
+		</notice>
+	</MessagesFromHome>
+</mesquite>
diff --git a/Source/mesquite/minimal/Installer/noticeExample.xml b/Source/mesquite/minimal/Installer/noticeExample.xml
new file mode 100644
index 0000000..f884b8c
--- /dev/null
+++ b/Source/mesquite/minimal/Installer/noticeExample.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<mesquite>
+	<MessagesFromHome>
+		<version>1</version>
+
+		<notice> <!-- A simple example notice.  This would be placed at a URL referred to by getHomePhoneNumber method of the package intro of your package. -->
+			<forPackageVersionEqualOrLess>102</forPackageVersionEqualOrLess>
+			<noticeNumber>3</noticeNumber>
+			<messageType>alert</messageType>
+			<message><![CDATA[<img src="http://mesquiteproject.org/packages/examples/deleteMe/splash.gif"><h2>DeleteMe</h2>Version 1.02 of DeleteMe, 
+			a silly package designed only to demonstrate the installation system, is now
+			 <a href = "http://mesquiteproject.org/packages/examples/deleteMe">available</a>.]]>
+			</message>
+		</notice>
+		
+	</MessagesFromHome>
+</mesquite>
diff --git a/Source/mesquite/minimal/Installer/updateExample.xml b/Source/mesquite/minimal/Installer/updateExample.xml
new file mode 100644
index 0000000..ae830b9
--- /dev/null
+++ b/Source/mesquite/minimal/Installer/updateExample.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<mesquite>
+	<MessagesFromHome>
+		<version>1</version>
+		<!-- This is a simple example of an update file that could be placed at the URL specified by the package's getHomePhoneNumber
+		
+		The currentReleaseVersion element will ensure that Mesquite notifies the user until the new version is installed
+		
+		The notice element will show up and offer to install the update.  If the user chooses not to install, it will be listed under
+		File > Available to Install or Update.
+		
+		-->
+		
+		
+		<currentReleaseVersion>
+			<versionString>1.01</versionString>
+			<version>101</version>
+			<downloadURL>http://mesquiteproject.org/packages/examples/deleteMe/</downloadURL>
+		</currentReleaseVersion>
+		<notice>
+			<forPackageVersionEqualOrLess>100</forPackageVersionEqualOrLess>
+			<noticeNumber>3</noticeNumber>
+			<messageType>update</messageType>
+			<identity>deleteMe</identity>
+			<updateVersion>101</updateVersion>
+			<packageName>DeleteMe version 1.01</packageName>
+			<beforeMessage>This update may take a while to download; please wait until a message appears saying it's finished.</beforeMessage>
+			<explanation><![CDATA[<h2>Bug fixes for DeleteMe</h2>An update to fix bugs in DeleteMe version 1 has been released.
+			]]>
+			</explanation>
+			<install>
+				<location>mesquite</location>
+				<file>deleteMe</file>
+				<url>http://mesquiteproject.org/packages/examples/deleteMe/mesquite.deleteMe.zip</url>
+				<treatment>unzip</treatment>
+				<updateVersion>001</updateVersion>
+			</install>
+		</notice>
+		
+		
+	</MessagesFromHome>
+</mesquite>
\ No newline at end of file
diff --git a/Source/mesquite/minimal/InterpretNEXUS/InterpretNEXUS.java b/Source/mesquite/minimal/InterpretNEXUS/InterpretNEXUS.java
new file mode 100644
index 0000000..d2983b5
--- /dev/null
+++ b/Source/mesquite/minimal/InterpretNEXUS/InterpretNEXUS.java
@@ -0,0 +1,692 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.InterpretNEXUS;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharactersBlock;
+import mesquite.lib.duties.*;
+
+
+/** A file interpreter for a NEXUS file format.  Sends blocks to various managing modules for reading.  */
+public class InterpretNEXUS extends NexusFileInterpreter {
+	public String getName() {
+		return "NEXUS file interpreter";
+	}
+	public String getNameForMenuItem() {
+		return "NEXUS file";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the reading and writing of NEXUS files." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.minimal.ManageForeignBlocks.ManageForeignBlocks.class, getName() + " needs a module to manage foreign blocks.",
+				"It is activated automatically. ");
+	}
+	/*.................................................................................................................*/
+	MesquiteModule foreignTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (mesquiteTrunk.mesquiteModulesInfoVector.findModule(mesquite.minimal.ManageForeignBlocks.ManageForeignBlocks.class, "Manage Foreign Blocks") != null)
+			foreignTask = hireNamedEmployee(mesquite.minimal.ManageForeignBlocks.ManageForeignBlocks.class, StringUtil.tokenize("Manage Foreign Blocks"));
+		return true;  //make this depend on taxa reader being found?)
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport(Class dataClass){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean canImport() {  
+		return true;
+	}
+	/** Returns whether the module can read (import) files so as to fuse taxa and matrices */
+	public boolean canImport(String arguments){
+		return true;
+	}
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		//getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu,"List of Nexus Blocks", makeCommand("showBlocks",  this));
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows list of NEXUS blocks", null, commandName, "showBlocks")) { //todo: this should use a real listwindow
+			//Check to see if already has lister for this
+			boolean found = false;
+			int numemp = getNumberOfEmployees();
+			for (int i = 0; i<numemp; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if (((ManagerAssistant)e).getName().equalsIgnoreCase("NEXUS blocks list")) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return e;
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("NEXUS Blocks List"));
+			if (lister==null){
+				alert("Sorry, no module was found to list the NEXUS blocks"); 
+				return null;
+			}
+			if (getProject().getNexusBlocks()!=null) {
+				lister.showListWindow(getProject().getNexusBlocks());
+				if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+					lister.getModuleWindow().setVisible(true);
+				return lister;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Sort blocks.*/
+	private boolean bubbleBlock(ListableVector blocks, NexusBlock nb){
+		if (nb==null)
+			return false;
+		/* pre-2. 02 version: bubbled downward if needed.  Problem: foreign blocks tend to drift upward.
+		boolean foundIncoming = false;
+		//make sure block is in OK place
+		for (int i = blocks.size()-1; i>=0; i--) {
+			NexusBlock nR = (NexusBlock)blocks.elementAt(i);
+			if (nb==nR)
+				foundIncoming = true;
+			else if (foundIncoming && (nR.mustBeAfter(nb) && (nb.getFile()==nR.getFile()))) {
+				blocks.removeElement(nR, false);
+				blocks.insertElementAt(nR, blocks.indexOf(nb)+1, false);
+				return true;
+			}
+		}
+		return false; */
+		int index = blocks.indexOf(nb); //find current height
+		if (index >=0){
+			int height = index;
+			//make sure block is in OK place
+			for (int i = index-1; i>=0; i--) { //now look to all higher to see if nb should jump above them
+				NexusBlock nR = (NexusBlock)blocks.elementAt(i);
+				if (!nb.mustBeAfter(nR) && (nb.getFile()==nR.getFile())) { //nb needs to jump above nR
+					height = i;  //remember height of nR
+				}
+			}
+			if (height < index){ //nb needs to jump to height; move it
+				blocks.removeElement(nb, false);
+				blocks.insertElementAt(nb, height, false);
+				return true;
+			}
+		}
+		return false;
+
+	}
+	/** Sort blocks.*/
+	private  void sortBlocks(ListableVector blocks){
+		if (blocks==null)
+			return;
+		Object[] bs = new Object[blocks.size()];
+		Enumeration e = blocks.elements();
+		int count=0;
+		while(e.hasMoreElements())
+			bs[count++]=e.nextElement();
+
+		for (int i=count-1; i>=0; i--) {
+			while (bubbleBlock(blocks, (NexusBlock)bs[i]))
+				;
+		}
+		//This is a kludge because of problems with mustBeAfter (as of 3. 03)
+		for (int i=count-1; i>=0; i--) {
+			if (bs[i] instanceof CharactersBlock){
+				blocks.removeElement((NexusBlock)bs[i], false);
+				blocks.insertElementAt((NexusBlock)bs[i], 0, false);
+			}
+			if (bs[i] instanceof TaxaBlock){
+				blocks.removeElement((NexusBlock)bs[i], false);
+				blocks.insertElementAt((NexusBlock)bs[i], 0, false);
+			}
+		}
+
+	}
+	/** Asks if block is sorted relative to other blocks in its file and before its file in file read order.
+	NOT USED as of 3. 02 */
+	private boolean needsToMove(ListableVector blocks, NexusBlock nb){
+		if (nb==null)
+			return false;
+		MesquiteFile fileOfBlock = nb.getFile();
+		ListableVector files = getProject().getFiles();
+		boolean done  = false;
+		for (int f = 0; f<files.size(); f++){  //for all files earier or same in list as file containing block
+			MesquiteFile fileToCheck = (MesquiteFile)files.elementAt(f);
+			boolean afterTarget = false;
+			NexusBlock nR = null;
+			//make sure block is in OK place
+			for (int i = 0; i<blocks.size(); i++) {  //look through blocks list
+				nR = (NexusBlock)blocks.elementAt(i);
+				if (nb!=nR && fileToCheck==nR.getFile()){
+					if (afterTarget){
+						if (nb.mustBeAfter(nR))
+							return true;
+					}
+					else {
+						if (nR.mustBeAfter(nb))
+							return true;
+					}
+				}
+				if (nb == nR) {
+					afterTarget = true;
+				}
+			}
+		}
+		return false;
+	}
+	/** Check to see if blocks sorted properly across all files in order of file saving.
+	NOT USED as of 3. 02 */
+	private  boolean sortedAcrossFiles(ListableVector blocks){
+		if (blocks==null)
+			return true;
+		Enumeration e = blocks.elements();
+		while(e.hasMoreElements()) {
+			NexusBlock nb = (NexusBlock)e.nextElement();
+			if (needsToMove(blocks, nb))
+				return false;
+		}
+
+		return true;
+	}
+	/** adds nexus block to given file.*/
+	public  void addBlock(NexusBlock nb){
+		if (nb==null)
+			return;
+		getProject().addNexusBlock(nb);
+		sortBlocks(getProject().getNexusBlocks());
+	}
+	/** adds nexus block to given file.*/
+	public  void removeBlock(NexusBlock nb){
+		if (nb==null)
+			return;
+		getProject().removeNexusBlock(nb);
+	}
+	/** adds nexus block to given file.*/
+	public  NexusBlock findBlock(FileElement e){
+		ListableVector blocks = getProject().getNexusBlocks();
+		if (e==null || blocks == null)
+			return null;
+		for (int i=0; i<blocks.size(); i++) {
+			NexusBlock nb = (NexusBlock)blocks.elementAt(i);
+			if (nb.contains(e)) 
+				return nb;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean canReadFile(MesquiteFile f) {
+
+		if (f ==null) {
+			return false;
+		}
+		else if (f.getFileName().endsWith(".nex")) {
+			return true;
+		}
+		else {
+			if (f.openReading()){
+				String s = parser.getFirstToken(f.firstToken(null));
+				f.closeReading();
+				if (s==null)
+					return false;
+				return s.equalsIgnoreCase("#NEXUS");
+			}
+		}
+		System.out.println("file can't be interpreted: " + f.getFileName());
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile mNF, String arguments) {
+		incrementMenuResetSuppression();
+		int length = (int)mNF.existingLength();
+		int readToNow = 0;
+		ProgressIndicator progIndicator = null;
+		Thread mt = Thread.currentThread();
+		boolean piMine = false;
+		if (mt instanceof MesquiteThread) 
+			progIndicator = ((MesquiteThread)mt).getProgressIndicator();
+		if (progIndicator ==null) {
+			progIndicator = new ProgressIndicator(mf,"Reading File "+ mNF.getName(), mNF.existingLength());
+			piMine = true;
+			if (mt instanceof MesquiteThread)
+				((MesquiteThread)mt).setProgressIndicator(progIndicator);
+		}
+		progIndicator.setButtonMode(ProgressIndicator.FLAG_AND_HIDE);
+		progIndicator.start();
+		mNF.linkProgressIndicator(progIndicator);
+		if (mNF.openReading()) {
+			try {
+				logln("Reading NEXUS file " + mNF.getFileName());
+				mNF.foreignElements = new Vector();
+				String token= mNF.firstToken(null);
+				if (token!=null) {
+					if (!token.equalsIgnoreCase("#NEXUS")) {
+						alert("Not a valid NEXUS file (first token is \"" + token + "\"");
+					}
+					else {
+						FileBlock block;
+						boolean abort = false;
+						boolean mesquiteBlockFound = false;
+						MesquiteString blockName = new MesquiteString();
+						StringBuffer fileComments = new StringBuffer(100);
+						StringBuffer blockComments = new StringBuffer(100);
+						MesquiteFile sF = progIndicator.getScriptingFile();
+						progIndicator.setScriptingFile(mNF);
+						int buttonMode = progIndicator.getButtonMode();
+						String buttonName = progIndicator.getStopButtonName();
+						while (!abort && !StringUtil.blank(block = mNF.getNextBlock( blockName, fileComments, blockComments))) {
+							CommandRecord.tick("Reading block " + blockName);
+							if ("Mesquite".equalsIgnoreCase(blockName.getValue())) {
+								mesquiteBlockFound = true;
+								mf.virginProject = false;
+								progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE_FORCEQUIT);
+								progIndicator.setStopButtonName("Emergency Stop");
+							}
+							else
+								progIndicator.setButtonMode(ProgressIndicator.FLAG_AND_HIDE);
+							progIndicator.setText("Processing block: " + blockName.getValue(), false, true);
+							NexusBlock nb = sendBlockToReader(mf, mNF, block, blockName.getValue(), length, readToNow, blockComments, arguments);
+							progIndicator.setText("Reading next block", false);
+							progIndicator.toFront();
+							readToNow += block.getNumCommands();
+							if (mNF.getFileAborted())
+								abort = true;
+						}
+						progIndicator.setScriptingFile(sF);
+						progIndicator.setButtonMode(buttonMode);
+						progIndicator.setStopButtonName(buttonName);
+						if (piMine)
+							progIndicator.setOwnerThread(null);
+
+						if (abort){ //���		
+							progIndicator.goAway();
+							mNF.closeReading();
+							mNF.close();
+							resetAllMenuBars();
+							decrementMenuResetSuppression();
+							return;
+						}
+						if (fileComments.length()>0) {
+							if (mNF.getAnnotation()!=null)
+								mNF.setAnnotation(mNF.getAnnotation() + fileComments.toString(), false);
+							else
+								mNF.setAnnotation(fileComments.toString(), false);
+						}
+						if (!mesquiteBlockFound && (mNF == mf.getHomeFile())) {
+							MesquiteModule mb = getProject().getCoordinatorModule();
+							if (mb != null){
+								MesquiteWindow mw = mb.getModuleWindow();
+								if (mw != null)
+									mw.setWindowSize(700, 500);
+								if (getProject().getNumberCharMatrices()>0){
+									MesquiteModule mbb = findNearestColleagueWithName("Data Window Coordinator");
+									if (mbb != null)
+										mbb.doCommand("showDataWindow", "0", CommandChecker.defaultChecker);
+								}
+								else if (getProject().getNumberTaxas()>0){
+									MesquiteModule mbb = findNearestColleagueWithName("Manage TAXA blocks");
+									if (mbb != null)
+										mbb.doCommand("showTaxa", "0", CommandChecker.defaultChecker);
+								}
+							}
+
+						}
+						progIndicator.goAway();
+						logln("File reading complete (file " + mNF.getFileName() + ")");
+					}
+				}
+			}
+			catch (MesquiteException e){
+			}
+			mNF.closeReading();
+			//mNF.reportTimes();
+			if (mNF.foreignElements.size()>0){
+
+
+				logln("");
+				logln("This file contained one or more blocks or commands not recognized; a list is written below.  It is possible that some packages of Mesquite that are not currently loaded might be able to recognize the commands; try rereading after choosing \"Use All Installed Modules\" under \"Activate/Deactivate Packages\".\n");
+				for (int i=0; i<mNF.foreignElements.size(); i++) {
+					logln("Unrecognized " + mNF.foreignElements.elementAt(i));
+				}
+				logln("");
+			}
+			mNF.foreignElements = null;
+		}
+		if (mf.windowToActivate !=null) {
+			MesquiteWindow w = mf.windowToActivate;
+			if (w.isPoppedOut() && !w.getPopAsTile()){
+				MesquiteFrame f = mf.getCoordinatorModule().getModuleWindow().getParentFrame();
+				MesquiteWindow pw = f.frontMostInLocation(MesquiteFrame.MAIN);
+				if (pw != null)
+					w = pw;
+			}
+
+			MesquiteFrame f = w.getParentFrame();
+			if (f != null){
+				f.setAsFrontWindow(w);
+				f.showFrontWindow();
+			}
+			mf.windowToActivate = null;
+		}
+		String s = null;
+		if ((s = mNF.getOpenAsUntitled())!=null ){
+			if (mNF.getReadCategory() == MesquiteFile.INCLUDED){
+				alert("File reading encountered the following issues.  Some components of the file might not have been read properly.  Please check any data in the file.\n" + s);
+			}
+			else {
+				alert("File reading encountered the following issues.  Some components of the file might not have been read properly, and could be lost upon resaving.  For safety's sake, you will be asked to choose another file name to avoid writing over the current file.\n" + s);
+				mNF.changeLocation(mNF.getDirectoryName(),"Untitled");
+				boolean newFilenameChosen = mNF.changeLocation("Please save the file under a new name");
+				mNF.setDirtiedByCommand(true);
+				getFileCoordinator().writeFile(mNF);
+			}
+		}
+		if (getProject() != null) {
+			resolveCharMatrixIDs();
+		}
+		decrementMenuResetSuppression();
+	}
+	/*.................................................................................................................*/
+	private int  getNumberCharMatricesWithAssignedID(long ref) {   //MOVE TO InterpretNEXUS
+		ListableVector datasVector = getProject().getCharacterMatrices();
+		int count = 0;
+		for (int i=0; i<datasVector.size(); i++) {
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datasVector.elementAt(i);
+			if (!data.isDoomed() && ref  == (data.getAssignedIDNumber())) {
+				count++;
+			}
+		}
+
+		return count;  
+	}
+	/*.................................................................................................................*/
+	/** resolves conflicts among assigned id's */
+	public void  resolveCharMatrixIDs() {  //MOVE TO InterpretNEXUS
+
+		ListableVector datasVector = getProject().getCharacterMatrices();
+		for (int i=datasVector.size()-1; i>=0; i--) {
+			mesquite.lib.characters.CharacterData data = (mesquite.lib.characters.CharacterData)datasVector.elementAt(i);
+			if (getNumberCharMatricesWithAssignedID(data.getAssignedIDNumber())>1) {
+				long a = MesquiteLong.unassigned;
+				while (!MesquiteLong.isCombinable(a))
+					a = Math.abs(FileElement.randomNumberGenerator.nextLong());
+				data.setAssignedIDNumber(a);
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** finds the ith block of a given type and returns it raw.*/
+	public FileBlock readOneBlock(MesquiteProject mf, MesquiteFile mNF, String blockType, int i){
+		if (blockType == null)
+			return null;
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator =  new ProgressIndicator(mf,"Processing File "+ mNF.getName() + " to find " + blockType + " block", mNF.existingLength());
+		progIndicator.start();
+		FileBlock blockSought = null;
+		if (mNF.openReading()) {
+			try {
+				logln("Processing File "+ mNF.getName() + " to find " + blockType + " block");
+				String token= mNF.firstToken(null);
+				if (token!=null) {
+					if (!token.equalsIgnoreCase("#NEXUS")) {
+						alert("Not a valid NEXUS file (first token is \"" + token + "\"");
+					}
+					else {
+						MesquiteString blockName = new MesquiteString();
+						StringBuffer blockComments = new StringBuffer(100);
+						int count = 0;
+						FileBlock block = null;
+						while (blockSought == null && !StringUtil.blank(block = mNF.getNextBlock( blockName, null, null))) {
+							if (blockType.equalsIgnoreCase(blockName.toString())){
+								if (count == i) {
+									//block found!
+									blockSought = block;
+									block.setFile(mNF);
+
+								}
+								count++;
+							}
+						}
+						progIndicator.goAway();
+						logln("File reading complete (file " + mNF.getFileName() + ")");
+					}
+				}
+			}
+			catch (MesquiteException e){
+			}
+			mNF.closeReading();
+		}
+		decrementMenuResetSuppression();
+		return blockSought;
+	}
+	/*.................................................................................................................*/
+	/** Finds the first employee in the heirarchy that  has a particular name.*/
+	private MesquiteModule findEmployeeThatCanRead(MesquiteModule module, FileBlock block, String blockName) {
+		if (blockName ==null || module == null)
+			return null;
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			MesquiteModuleInfo mbi = mb.getModuleInfo();
+			if (mbi.getNexusBlockTest()!=null && mbi.getNexusBlockTest().readsWritesBlock(blockName, block)) {
+				return mb;
+			}
+		}
+		//not found among immediate employees; look deeper
+		enumeration=module.getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()){
+			MesquiteModule mb = (MesquiteModule)enumeration.nextElement();
+			MesquiteModule result = findEmployeeThatCanRead(mb, block, blockName);
+			if (result != null)
+				return result;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	boolean isForeignBlock(String blockName){		//first check employees to see if they can understand block
+		if (blockName == null)
+			return true;
+		MesquiteModule rM = findEmployeeThatCanRead(getFileCoordinator(), null, blockName);
+		if (rM!=null) {
+			return false;
+		}
+
+		//then look for others to hire that might understand block
+		Enumeration enumeration=MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			MesquiteModuleInfo mbi = (MesquiteModuleInfo)obj;
+			if ((rM==null || rM.getModuleInfo()!=mbi) && mbi.getNexusBlockTest()!=null && mbi.getNexusBlockTest().readsWritesBlock(blockName, null)) {
+				return false;
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	private NexusBlock sendBlockToReader(MesquiteProject mp, MesquiteFile mf, FileBlock block, String blockName, int totalLength, int readToNow, StringBuffer blockComments, String fileReadingArguments) {
+		if (blockName == null)
+			return null;
+
+		//first check employees to see if they can understand block
+		MesquiteModule rM = findEmployeeThatCanRead(getFileCoordinator(), block, blockName);
+		ListableVector blocks = getProject().getNexusBlocks();
+		if (rM!=null) {
+			logln("Reading block: " + blockName);
+			long startTimeForBlock = System.currentTimeMillis();
+			NexusBlock nb = rM.readNexusBlock( mf, blockName, block, blockComments, fileReadingArguments);
+			if (MesquiteTrunk.debugMode)
+				logln("    time to read:  " + ((System.currentTimeMillis() - startTimeForBlock)/1000.00) + " sec.");
+			if (nb!=null){
+				if (blocks.indexOf(nb)<0) {
+					blocks.addElement(nb, false);
+				}
+				return nb;
+			}
+		}
+
+		//then look for others to hire that might understand block
+		Enumeration enumeration=MesquiteTrunk.mesquiteModulesInfoVector.elements();
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			MesquiteModuleInfo mbi = (MesquiteModuleInfo)obj;
+			if ((rM==null || rM.getModuleInfo()!=mbi) && mbi.getNexusBlockTest()!=null && mbi.getNexusBlockTest().readsWritesBlock(blockName, block)) {
+				logln("Reading special block: " + blockName);
+				MesquiteModule mb = hireEmployeeFromModuleInfo(mbi, MesquiteModule.class);
+				NexusBlock nb = mb.readNexusBlock( mf, blockName, block, blockComments, fileReadingArguments);
+				if (nb!=null){
+					if (blocks.indexOf(nb)<0) {
+						blocks.addElement(nb, false);
+					}
+					return nb;
+				}
+			}
+		}
+		if (mf.foreignElements!=null && !("paup".equalsIgnoreCase(blockName) || "macclade".equalsIgnoreCase(blockName)))
+			mf.foreignElements.addElement("Block: " + blockName);
+		if (foreignTask!=null) {
+			NexusBlock nb = foreignTask.readNexusBlock(mf, blockName, block, blockComments, fileReadingArguments);
+			logln("Storing foreign block: " + blockName);
+			if (nb!=null) {
+				blocks.addElement(nb, false);
+				return nb;
+			}
+		}
+		else
+			logln("No module found to read block: " + blockName);
+		return null;
+	}
+
+	String addendum = "";
+	public void getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog exportDialog = new ExtensibleDialog(containerOfModule(), "NEXUS Options", buttonPressed);
+		//exportDialog.setSuppressLineEndQuery(true);
+		exportDialog.setDefaultButton(null);
+		exportDialog.addLabel("Addendum to file: ");
+		TextArea fsText =exportDialog.addTextAreaSmallFont(addendum,4);
+
+		exportDialog.completeAndShowDialog();
+
+		boolean ok = (buttonPressed.getValue()==0);
+		if (ok)
+			addendum = fsText.getText();
+		exportDialog.dispose();
+	}	
+	/*.................................................................................................................*/
+	/** Called to see if file ready to be written.*/
+	void checkIntegrityForWriting(MesquiteModule module, MesquiteFile file) {
+		if (module==null)
+			return;
+
+		EmployeeVector e = module.getEmployeeVector();
+		if (e==null)
+			return;
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+
+			if (employee!=null){
+				employee.preWritingCheck(file, "NEXUS");
+				checkIntegrityForWriting(employee, file);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void writeFile(MesquiteProject mf, MesquiteFile mNF) {
+		//boolean setTC = !MesquiteFile.fileExists(mNF.getPath());
+		if (mNF.openWriting(true)) {
+			if (mNF.exporting == 1){
+				if (okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying about options"))
+					getExportOptions(false, false);
+			}
+			checkIntegrityForWriting(getFileCoordinator(), mNF);
+			mNF.setIsNexus(true);
+			ListableVector blocks = getProject().getNexusBlocks();
+			MesquiteTimer time = new MesquiteTimer();
+			time.start();
+			MesquiteBoolean finishedWriting = new MesquiteBoolean(false);
+
+			sortBlocks(blocks);
+			ProgressIndicator progIndicator = new ProgressIndicator(mf,"Writing File "+ mNF.getName(), blocks.size(), false);
+			progIndicator.start();
+
+			mNF.writeLine("#NEXUS");
+
+			Date d = new Date(System.currentTimeMillis());
+			String s = "";
+			String loc = "";
+			try {
+				loc = " at " + java.net.InetAddress.getLocalHost();
+			}
+			catch (java.net.UnknownHostException e){
+			}
+			if (!MesquiteModule.author.hasDefaultSettings())
+				loc += " (" + author.getName() + ")";
+			mNF.writeLine("[written " + d.toString() + " by Mesquite " + s + " version " + getMesquiteVersion()  + getBuildVersion() + loc + "]"); 
+			//mNF.writeLine("[!" + mNF.getAnnotation() + "]");
+
+			for (int i=0; i<blocks.size(); i++) {
+				NexusBlock nb = (NexusBlock)blocks.elementAt(i);
+				if (nb.getFile() == mNF && nb.getWritable()) {
+					progIndicator.setCurrentValue(i);
+					progIndicator.setText("Preparing to write " + nb.getName() );
+					//	logln("      Writing " + nb.getName());
+
+					nb.writeNEXUSBlock(mNF, progIndicator);
+				}
+			}
+			if (addendum != null)
+				mNF.writeLine(addendum);
+			mf.fileSaved(mNF);
+			progIndicator.goAway();
+			time.end();
+			logln("      File writing finished " + time.getAccumulatedTime());
+			mNF.closeWriting(NexusBlock.numBackups);
+			//if (setTC) setFileTypeCreator(mNF);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+		return "nex";
+	}
+	/*.................................................................................................................*/
+
+
+}
+
diff --git a/Source/mesquite/minimal/ManageForeignBlocks/ManageForeignBlocks.java b/Source/mesquite/minimal/ManageForeignBlocks/ManageForeignBlocks.java
new file mode 100644
index 0000000..005f6f2
--- /dev/null
+++ b/Source/mesquite/minimal/ManageForeignBlocks/ManageForeignBlocks.java
@@ -0,0 +1,218 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.ManageForeignBlocks;
+/*~~  */
+
+import java.util.*;
+import java.io.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages unrecognized blocks in NEXUS data files (storing for editing or later rewriting) */
+public class ManageForeignBlocks extends MesquiteModule {
+	public String getName() {
+		return "Manage Foreign Blocks";
+	}
+	public String getExplanation() {
+		return "Manages unrecognized blocks in a NEXUS file." ;
+	}
+	/*.................................................................................................................*/
+	ListableVector foreignBlocks;
+	ForeignBlock currentlyEdited = null;
+	MesquiteMenuItemSpec editSubmenu;
+	MesquiteMenuItemSpec newBlockMenu;
+	EditRawNexusBlock editor;  //TODO: allow editor for each block
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		foreignBlocks = new ListableVector();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		MesquiteMenuItemSpec mmis = getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu, "New Generic NEXUS block...", makeCommand("newBlock",  this));
+		super.projectEstablished();
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	public Class getDutyClass(){
+		return ManageForeignBlocks.class;
+	}
+
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		if (editSubmenu == null)
+			editSubmenu = getFileCoordinator().addSubmenu(MesquiteTrunk.editMenu, "Edit Foreign Block", makeCommand("editBlock", this), foreignBlocks);
+
+		Parser commandParser = new Parser();
+		String b = block.toString();
+
+		commandParser.setString(b);
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+
+		String s =commandParser.getNextCommand(startCharC);
+		s =parser.getFirstToken(commandParser.getNextCommand(startCharC));
+
+		ForeignBlock commentBlock =new ForeignBlock(file, this);
+		commentBlock.setName(name);
+		commentBlock.setBlockName(name);
+
+		commentBlock.setText(b + StringUtil.lineEnding() + "END;");
+		foreignBlocks.addElement(commentBlock, false);
+		return commentBlock; 
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (editor!=null) {
+			Snapshot temp = new Snapshot();
+			temp.addLine("editBlock " + foreignBlocks.indexOf(editor.getCurrentBlock()), editor);
+			return temp;
+		}
+		else return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Calls up a window in which to edit a NEXUS block foreign to the current modules of Mesquite", "[number of foreign block]", commandName, "editBlock")){
+			//find which block first
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			ForeignBlock toBeEdited = (ForeignBlock)foreignBlocks.elementAt(which);
+			if (toBeEdited == null)
+				return null;
+			if (editor==null)
+				editor = (EditRawNexusBlock)hireEmployee(EditRawNexusBlock.class, "To edit NEXUS block");
+			if (editor!=null) {
+				editor.editNexusBlock(toBeEdited, true);
+				toBeEdited.setEditor(editor);
+				if (!MesquiteThread.isScripting() && editor.getModuleWindow()!=null)
+					editor.getModuleWindow().setVisible(true);
+			}
+			return editor;
+		}
+		else if (checker.compare(this.getClass(), "Creates a new generic NEXUS block", null, commandName, "newBlock")) {
+			//which file to add to?
+			MesquiteFile file = getProject().chooseFile( "Select the file to which to add the new NEXUS block");
+			if (file == null)
+				return null;
+			String typeName = MesquiteString.queryShortString(containerOfModule(), "Block type name", "Enter name of type of NEXUS block (e.g., DISTRIBUTION):", "UNKNOWN");
+			if (StringUtil.blank(typeName))
+				return null;
+			ForeignBlock block =new ForeignBlock(file, this);
+			block.setName(typeName);
+			block.setBlockName(typeName);
+			block.setText("BEGIN " + typeName + ";" + StringUtil.lineEnding() + "[contents of block here]" + StringUtil.lineEnding() + "END;" + StringUtil.lineEnding());
+			foreignBlocks.addElement(block, false);
+			addNEXUSBlock(block);
+			if (editor==null)
+				editor = (EditRawNexusBlock)hireEmployee(EditRawNexusBlock.class, "To edit NEXUS block");
+			if (editor!=null) {
+				editor.editNexusBlock(block, true);
+				block.setEditor(editor);
+				if (!MesquiteThread.isScripting() && editor.getModuleWindow()!=null)
+					editor.getModuleWindow().setVisible(true);
+			}
+			if (editSubmenu == null)
+				editSubmenu = getFileCoordinator().addSubmenu(MesquiteTrunk.editMenu, "Edit Foreign Block", makeCommand("editBlock", this), foreignBlocks);
+			resetAllMenuBars();
+			return editor;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+}
+/* ======================================================================== */
+class ForeignBlock extends NexusBlockEditableRaw implements Explainable {  
+	String blockContents = "";
+	String blockName = "";
+	ManageForeignBlocks ownerModule = null;
+	public ForeignBlock(MesquiteFile f, ManageForeignBlocks mb){
+
+		super(f,mb);
+		ownerModule = mb;
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("written Foreign block");
+	}
+	public boolean contains(FileElement e){
+		return false;
+	}
+	private int getBlockID(NexusBlock block){
+		if ("MacClade".equalsIgnoreCase(getBlockName()))
+			return 3;
+		if ("PAUP".equalsIgnoreCase(getBlockName()))
+			return 2;
+		if ("MrBayes".equalsIgnoreCase(getBlockName()))
+			return 1;
+		return -1;
+
+	}
+	/** Returns true if this block must occur after the given block*/
+	public boolean mustBeAfter(NexusBlock block){
+		int mine = getBlockID(this);
+		int theirs = getBlockID(block);
+		if (mine < 0 || theirs <0) {
+			return getID()>block.getID();
+		}
+		return mine>theirs;
+	}
+	public void setBlockName(String bName){
+
+		blockName = bName;
+	}
+	/** Returns the offical NEXUS block name (e.g. "TAXA")*/
+	public String getBlockName(){
+		return blockName;
+	}
+
+	public void setText(String contents) {
+		blockContents = contents;
+	}
+	public String getText() {
+		return blockContents;
+	}
+	public String getName(){
+		if (super.getName() == null)
+			return  "Unrecognized block";
+		else
+			return super.getName() + " block";
+	}
+
+	public String getExplanation(){
+		return "This is a foreign block not understood by Mesquite";
+	}
+	public String getNEXUSBlock(){
+		if (getEditor()!=null)
+			getEditor().recordBlock(this);
+		if (blockContents==null)
+			return null;
+		else
+			return blockContents;
+	}
+}
+/* ======================================================================== 
+class FileCommentBlockTest extends NexusBlockTest  {
+	public FileCommentBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("FileComment");
+	}
+}
+
+ */
diff --git a/Source/mesquite/minimal/ManageMesquiteBlock/ManageMesquiteBlock.java b/Source/mesquite/minimal/ManageMesquiteBlock/ManageMesquiteBlock.java
new file mode 100644
index 0000000..59d1029
--- /dev/null
+++ b/Source/mesquite/minimal/ManageMesquiteBlock/ManageMesquiteBlock.java
@@ -0,0 +1,346 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.ManageMesquiteBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.assoc.lib.AssociationSource;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Manages the Mesquite block of a nexus file, which contains scripts for Mesquite and its modules. */
+public class ManageMesquiteBlock extends ScriptingManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(EditRawNexusBlock.class, getName() + " uses an assistant to edit file blocks.",
+		"This is arrange automatically.");
+	}
+
+	
+	public String getName() {
+		return "Manage MESQUITE block";
+	}
+	public String getExplanation() {
+		return "Manages MESQUITE block (including compose snapshot of current state of file in MESQUITE block \"Auto\" in NEXUS file)." ;
+	}
+	/*.................................................................................................................*/
+	static final int currentScriptVersion = 2;
+	MesquiteBlock currentBlock = null;  //TODO: must allow more than one, one for each file
+	EditRawNexusBlock editor;
+	static boolean warnVersion = true;
+	// need vector of MesquiteScript objects that are FileElements
+
+	boolean debugging = false;
+	Random rng;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		rng = new Random(System.currentTimeMillis());
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.editMenu, "Edit Mesquite script", makeCommand("showScript",  this));
+		MesquiteFile homeFile = getProject().getHomeFile();
+		MesquiteBlock b =makeBlock(homeFile, "");  //merely a placeholder
+		b.setName("AUTO*");
+		addNEXUSBlock(b);
+		//getFileCoordinator().addMenuItem("-", null);
+		super.projectEstablished();
+	}
+	public Class getElementClass(){
+		return MesquiteBlock.class;
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		//TODO:
+		if (e != null)
+			alert("Sorry, the " + e.getTypeName() + "  cannot be shown by this means yet.");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		//if (blocks !=null)
+		//	blocks.removeElement(e);
+
+		//todo: here should fire any editor employees currently editing this block
+	}
+	/*.................................................................................................................*/
+	public NexusBlock elementAdded(FileElement block){
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	private MesquiteBlock makeBlock(MesquiteFile file, String contents) {
+		MesquiteBlock b = new MesquiteBlock(file, this);
+		b.setName("Mesquite Block");
+		if (contents !=null)
+			b.setText(contents);
+		//	if (blocks==null)
+		//		blocks = new Vector();
+		//	blocks.addElement(b);
+		return b;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Calls up a window in which to display and edit a Mesquite script block", "[number of block]", commandName, "showScript")) {  
+			MesquiteBlock b = null;
+			NexusBlock[] blocks = getProject().getNexusBlocks(MesquiteBlock.class, null);
+			if (blocks == null || blocks.length == 0) {
+				b = makeBlock(null, "BEGIN MESQUITE;"+ StringUtil.lineEnding() + "END;"); //TODO: into which file assigned? (dialog box if more than one file opened)
+			}
+			else if (StringUtil.blank(arguments)) {
+				//have dialog requesting which??
+				b = ((MesquiteBlock)blocks[0]);
+			}
+			else {
+				int whichBlock = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+				if (whichBlock >=0 && whichBlock < blocks.length)
+					b = ((MesquiteBlock)blocks[whichBlock]);
+			}
+			if (b!=null) {
+				if (editor==null)
+					editor = (EditRawNexusBlock)hireEmployee(EditRawNexusBlock.class, "To edit Mesquite block");
+				if (editor!=null) {
+					editor.editNexusBlock(b, true);
+					b.setEditor(editor);
+					if (!MesquiteThread.isScripting() && editor.getModuleWindow()!=null)
+						editor.getModuleWindow().setVisible(true);
+				}
+				return editor;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Gets snapshots from module of given identification number", "[identification number of module]", commandName, "getSnapshots")) {  
+			int w = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			MesquiteModule mb = MesquiteTrunk.mesquiteTrunk.findEmployeeWithIDNumber(w);
+			if (mb!=null) {
+				return Snapshot.getSnapshotCommands(mb, null, "\t");
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new MesquiteBlockTest();}
+	/*.................................................................................................................*/
+	//this should pretty print the raw block
+	public String pretty(String raw){
+		return raw;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after a file has been read in.*/
+	void broadcastBeforeMesqBlock(MesquiteModule module, MesquiteFile f) {
+		if (module==null)
+			return;
+		EmployeeVector e = module.getEmployeeVector();
+		if (e==null)
+			return;
+		for (int i = 0; i<e.size(); i++) {
+			MesquiteModule employee = (MesquiteModule)e.elementAt(i);
+			if (employee!=null){
+				employee.aboutToReadMesquiteBlock(f);
+				broadcastBeforeMesqBlock(employee, f);
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+		boolean suppressRead = parser.hasFileReadingArgument(fileReadingArguments, "suppressMesquiteBlockRead") || !file.readMesquiteBlock;
+		
+		if (fuse || suppressRead)
+			return null;
+		
+		incrementMenuResetSuppression();
+		broadcastBeforeMesqBlock(getFileCoordinator(), file);
+		String blockString = block.toString();
+		MesquiteBlock b = makeBlock(file, blockString);
+		Parser commandParser = new Parser();
+		commandParser.setString(blockString);
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		int scriptVersion = -1;
+		boolean ignoreScriptVersion = true;
+		boolean forceIgnore = false;
+		String s;
+		int previousStart = startCharC.getValue();
+		while (!StringUtil.blank(s=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(s);
+			String commandArguments = s.substring(parser.getPosition(), s.length()-1);
+			if ("BEGIN".equalsIgnoreCase(commandName)) {
+
+			}
+			else if ("TITLE".equalsIgnoreCase(commandName)) {
+				b.setName(commandArguments);
+				if ("AUTO".equalsIgnoreCase(b.getName())) //warns about script version only if AUTO-saved script
+					ignoreScriptVersion = false;
+			}
+			else if ("SCRIPTVERSION".equalsIgnoreCase(commandName)) { 
+				scriptVersion = MesquiteInteger.fromString(commandArguments);
+			}
+			else if ("MESQUITESCRIPTVERSION".equalsIgnoreCase(commandName)) { 
+				scriptVersion = MesquiteInteger.fromString(commandArguments);
+			}
+			else if ("IGNORESCRIPTVERSION".equalsIgnoreCase(commandName)) { 
+				forceIgnore = true;
+			}
+			else {
+				startCharC.setValue(previousStart);
+				Puppeteer p = new Puppeteer(this);
+				CommandRecord cRecord = new CommandRecord(true);
+				cRecord.setScriptingFile(file);
+				Thread mt = Thread.currentThread();
+				if (mt instanceof CommandRecordHolder) 
+					((CommandRecordHolder)mt).setCommandRecord(cRecord);
+				if (mt instanceof MesquiteThread) {
+					ProgressIndicator pi = ((MesquiteThread)mt).getProgressIndicator();
+					if (pi !=null)
+						cRecord.setProgressIndicator(pi);
+				}
+				CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+				MesquiteThread.setCurrentCommandRecord(cRecord);
+				p.execute(getFileCoordinator(), blockString, startCharC, "", false, b, file);
+				MesquiteThread.setCurrentCommandRecord(prevR);
+			}
+			previousStart = startCharC.getValue();
+		}
+
+		if ("AUTO".equalsIgnoreCase(b.getName())){  //
+			boolean found = false;
+			if (getProject() == null)
+				return null;
+			NexusBlock[] blocks = getProject().getNexusBlocks(MesquiteBlock.class, null);
+			if (blocks !=null)
+				for (int i=0; i<blocks.length && !found; i++) {
+					MesquiteBlock bb = ((MesquiteBlock)blocks[i]);
+					if ("AUTO*".equalsIgnoreCase(bb.getName())) {
+						found = true;
+						removeNEXUSBlock(bb);
+					}
+				}
+		}
+		if (!ignoreScriptVersion && !forceIgnore && scriptVersion < currentScriptVersion) {
+			String warning = "The Mesquite script in this file appears to be of an older version.  Changes in the scripting language may cause some problems (e.g., traced characters may not appear).  If a problem appears, you may be able to solve it by using Save As to save the file, closing the file, then reopening it.";
+			if (MesquiteThread.isScripting() || !warnVersion)
+				logln("\n" + warning +"\n");
+			else if (!AlertDialog.query(containerOfModule(), "Old Script Version",warning + "\n\nYou may suppress future warnings of this type within this run of Mesquite.", "Continue", "Suppress warnings")){
+				warnVersion = false;
+			}
+		}
+		if (containerOfModule() != null)
+			containerOfModule().getParentFrame().showFrontWindow();
+		decrementMenuResetSuppression();
+		return b;
+	}
+
+	/*.................................................................................................................*/
+	public String getAutoBlock(MesquiteFile file){
+		if (file!= getProject().getHomeFile())
+			return "";
+		if (file.useConservativeNexus || file.useSimplifiedNexus)
+			return "";
+		FileCoordinator fCoord = getFileCoordinator();
+
+		String snapshot = ""; //here use getIDSnapshots for all FileElementManager employees of the fCoord; avoids problems of assigning character matrix ID after taxon list window shown
+		Snapshot idfcs = fCoord.getIDSnapshot(file);
+		if (idfcs != null)
+			snapshot += idfcs.toString(file, "\t\t");
+		EmployeeVector femps = fCoord.getEmployeeVector();
+		for (int i=0; i<femps.size(); i++){
+			if (femps.elementAt(i) instanceof FileElementManager){
+				FileElementManager fem = (FileElementManager)femps.elementAt(i);
+				String ids = Snapshot.getIDSnapshotCommands(fem, file, "\t\t");
+				if (!StringUtil.blank(ids)) {
+					snapshot +="\t\tgetEmployee " + StringUtil.tokenize(fCoord.getEmployeeReference(fem)) + ";" + StringUtil.lineEnding();//quote
+					snapshot += "\t\ttell It;" + StringUtil.lineEnding();
+					snapshot += ids;
+					snapshot += "\t\tendTell;" + StringUtil.lineEnding();
+				}
+
+
+			}
+		}
+		snapshot += Snapshot.getSnapshotCommands(fCoord, file, "\t");
+
+		if (!StringUtil.blank(snapshot))
+			return "Begin MESQUITE;" + StringUtil.lineEnding()  + "\t\t" + getVersionCommand() + StringUtil.lineEnding() + "\t\tTITLE AUTO;"+ StringUtil.lineEnding()  + "\t\ttell ProjectCoordinator;"+ StringUtil.lineEnding() +  snapshot+ "\t\tendTell;"+ StringUtil.lineEnding() + "end;" + StringUtil.lineEnding();
+		else return "";
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	private String getVersionCommand(){
+		return "MESQUITESCRIPTVERSION " + currentScriptVersion +";";
+	}
+
+}
+
+class MesquiteBlock extends NexusBlockEditableRaw {
+	String blockContents = "";
+	public MesquiteBlock(MesquiteFile f, MesquiteModule mb){
+		super(f,mb);
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("written Mesquiteblock");
+	}
+	public boolean contains(FileElement e) {
+		return false;
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		//TODO: ONLY if not read in from file or if AUTO
+		return true;
+
+	}
+	public String getBlockName(){
+		return "MESQUITE";
+	}
+	public void setText(String contents) {
+		blockContents = contents;
+	}
+	public String getText() {
+		return blockContents;
+	}
+
+	public String getNEXUSBlock(){
+		if (getEditor()!=null)
+			getEditor().recordBlock(this);
+		if (getName().equalsIgnoreCase("AUTO"))
+			return ((ManageMesquiteBlock)getManager()).getAutoBlock(getFile());
+		else if (getName().equalsIgnoreCase("AUTO*")) {
+			setName("AUTO");
+			return ((ManageMesquiteBlock)getManager()).getAutoBlock(getFile());
+		}
+		else {
+			return blockContents;
+		}
+
+	}
+}
+
+/* ======================================================================== */
+class MesquiteBlockTest extends NexusBlockTest  {
+	public MesquiteBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("MESQUITE");
+	}
+}
+
+
diff --git a/Source/mesquite/minimal/ManageTaxa/ManageTaxa.java b/Source/mesquite/minimal/ManageTaxa/ManageTaxa.java
new file mode 100644
index 0000000..f65e03d
--- /dev/null
+++ b/Source/mesquite/minimal/ManageTaxa/ManageTaxa.java
@@ -0,0 +1,1342 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.ManageTaxa;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/** Manages the blocks of TAXA, including reading and writing from a NEXUS file.*/
+public class ManageTaxa extends TaxaManager {
+	public String getName() {
+		return "Manage TAXA blocks"; //name must be updated in BasicFileCoord
+	}
+	public String getNameForMenuItem() {
+		return "Taxon Manager";
+	}
+	public String getExplanation() {
+		return "Manages sets of taxa (including read/write TAXA block in NEXUS file)." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e3 = registerEmployeeNeed(mesquite.lists.TaxonList.TaxonList.class, "The List of Taxa window permits viewing and modifying of taxon properties",
+				"The List of Taxa window is available in the Taxa&Trees menu.");
+	}
+	/*.................................................................................................................*/
+
+	MesquiteBoolean alerts;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setMenuToUse(MesquiteTrunk.treesMenu);
+		alerts = new MesquiteBoolean(true);
+
+		return true;
+	}
+	public void elementsReordered(ListableVector v){
+		if (v == getProject().taxas){
+			NexusBlock.equalizeOrdering(v, getProject().getNexusBlocks());
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "List of Taxa", makeCommand("showTaxa",  this),  (ListableVector)getProject().taxas);
+		//getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "New Block of Taxa...", makeCommand("newTaxa",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "List of Taxa Blocks", makeCommand("showTaxasList",  this));
+		//getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "Merge taxa blocks...", makeCommand("mergeTaxa",  this));
+		//	getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		for (int i= 0; i< getProject().getNumberTaxas(); i++){
+			Taxa t = getProject().getTaxa(i);
+			restoreOrderIfNeeded(t);
+		}
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof Taxa){
+			Taxa t = (Taxa)e;
+			return showTaxa(t);
+		}
+		return null;
+	}
+	public void deleteElement(FileElement e){
+		if (e instanceof Taxa){
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object ma=getEmployeeVector().elementAt(i);
+				if (ma instanceof ManagerAssistant)
+					if (((ManagerAssistant)ma).showing(e)) {
+						fireEmployee(((ManagerAssistant)ma));
+					}
+			}
+			Taxa taxa = (Taxa)e;
+			taxa.doom();
+			getProject().removeFileElement(taxa);//must remove first, before disposing
+			taxa.dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	public Taxa makeNewTaxa(String title, int numTaxa, boolean userQuery){
+		Taxa newTaxa=null;
+		if (userQuery) {
+			title= getProject().getTaxas().getUniqueName("Taxa");
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			MesquiteInteger ion = new MesquiteInteger(3);
+			MesquiteString ios = new MesquiteString(title);
+			String s = "Use this dialog box to create a new, named block of taxa.";
+			StringIntegerDialog dialog = new StringIntegerDialog(containerOfModule(), "New Block of Taxa", "Name of new block", "Number of taxa", ios,ion, 1, MesquiteInteger.unassigned, buttonPressed,s);
+
+			if (buttonPressed.getValue()!=0)
+				return null;
+			numTaxa= ion.getValue();
+			title= ios.getValue();
+
+			if (getProject().getTaxas().getElementIgnoreCase(title)!=null) {
+				title= getProject().getTaxas().getUniqueName("Taxa");
+				message("Sorry, that name is already taken.  The taxa block will be assigned the name " + title);
+			}
+		}
+		if (MesquiteInteger.isCombinable(numTaxa) && numTaxa >= Taxa.MAXNUMTAXA) {
+			message("Sorry, the maximum number of taxa in a taxa block is " + Taxa.MAXNUMTAXA);
+		}
+		else if (numTaxa>=0 && numTaxa< Taxa.MAXNUMTAXA) {
+			newTaxa = new Taxa(numTaxa);
+			if (title!=null)
+				newTaxa.setName(title);
+			String taxonName;
+			for (int it=0; it<numTaxa; it++) {
+				newTaxa.getTaxon(it).setName("taxon " + Taxon.toExternal(it));
+				newTaxa.getTaxon(it).setNameIsDefault(true);
+			}
+		}
+		return newTaxa;
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		if (e==null || !(e instanceof Taxa))
+			return;
+		NexusBlock nb = findNEXUSBlock(e);
+		if (nb!=null) {
+			removeNEXUSBlock(nb);
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object ma=getEmployeeVector().elementAt(i);
+			if (ma instanceof ManagerAssistant)
+				if (((ManagerAssistant)ma).showing(e)) {
+					fireEmployee(((ManagerAssistant)ma));
+				}
+		}
+	}
+	/*.................................................................................................................*/
+	public NexusBlock elementAdded(FileElement taxa){
+		if (taxa==null || !(taxa instanceof Taxa))
+			return null;
+		NexusBlock nb = findNEXUSBlock(taxa);
+		if (nb==null) {
+			TaxaBlock t = new TaxaBlock(taxa.getFile(), this);
+			t.setTaxa((Taxa)taxa);
+			addNEXUSBlock(t);
+			resetAllMenuBars();
+			return t;
+		}
+		else return nb;
+	}
+	/*.................................................................................................................*/
+	/** check if any adjustments are needed before writing, .e.g. resolve name conflicts.  Format is file type, e.g. NEXUS, NEXML. */
+	public void preWritingCheck(MesquiteFile file, String format){	
+		if (format.equalsIgnoreCase("NEXUS")){
+			int numSets = getProject().getNumberTaxas();
+			ListableVector taxas = getProject().getTaxas();
+			String[] names = new String[numSets];
+			boolean changed = false;
+			String changes = "";
+			for (int i=0; i<numSets; i++) {
+				Taxa taxa = getProject().getTaxa(i);
+				if (taxa.getFile() == file){
+					String cName = taxa.getName();
+					if (StringArray.indexOf(names, cName)>=0){
+						taxa.setName(taxas.getUniqueName(cName));
+						changed = true;
+						changes += " Taxa block " + cName + " renamed to " + taxa.getName();
+					}
+					else
+						names[i] = taxa.getName();
+
+				}
+			}
+			if (changed)
+				discreetAlert("Some taxa blocks had the same name (i.e., the same title).  This is not permitted in NEXUS files; some names were changed (" + changes + ")");
+		}
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new TaxaBlockTest();}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TAXANexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getIDSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (file == null || file == getProject().getHomeFile()){
+			for (int i = 0; i< getProject().getNumberTaxas(); i++) {
+				if (StringUtil.blank(getProject().getTaxa(i).getUniqueID()))
+					temp.addLine("setID " + i + " " + getProject().getTaxa(i).getAssignedIDNumber());
+				else
+					temp.addLine("setID " + i + " " + getProject().getTaxa(i).getAssignedIDNumber() + " " + getProject().getTaxa(i).getUniqueID());
+				Snapshot fromTaxa = getProject().getTaxa(i).getSnapshot(file);
+				if (fromTaxa != null && fromTaxa.getNumLines() > 0) {
+					temp.addLine("tell It");
+					temp.incorporate(fromTaxa, true);
+					temp.addLine("endTell");
+				}
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Taxa blocks list")) {
+				temp.addLine("showTaxasList ", e); 
+			}
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Taxon List")) {
+				Object o = e.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+
+				if (o !=null && o instanceof Taxa) {
+					//int wh =getProject().getTaxaReference((Taxa)o);
+					temp.addLine("showTaxa " + getProject().getTaxaReferenceExternal((Taxa)o), e); 
+				}
+			}
+		}
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Requests that a new taxa block be made", "[number of taxa] [title]", commandName, "newTaxa")) {
+			//ask user how many taxa
+			//create taxa block and add to file
+			//return taxa
+
+			incrementMenuResetSuppression();
+			Taxa newTaxa=null;
+			int numTaxa= 3;
+			String title= getProject().getTaxas().getUniqueName("Taxa");
+			MesquiteBoolean answer = new MesquiteBoolean(true);
+			MesquiteFile file = getProject().chooseFile( "Select file to which to add the new block of taxa"); //added 20 Dec 01
+			Object o = null;
+			if (StringUtil.blank(arguments)) {
+				newTaxa = makeNewTaxa(title, numTaxa, true);
+				if (newTaxa==null)
+					return null;
+				newTaxa.addToFile(file, getProject(), this);
+
+				if (!MesquiteThread.isScripting())
+					newTaxa.showMe(); //o = doCommand("showTaxa", getProject().getTaxaReferenceExternal(newTaxa), checker); //changed to scriptingRecord so as not to provoke alert 19Jan02
+			}
+			else {
+				MesquiteInteger io = new MesquiteInteger(0);
+				numTaxa= MesquiteInteger.fromString(arguments, io);
+				title= ParseUtil.getToken(arguments, io);
+				newTaxa = makeNewTaxa(title, numTaxa, false);
+				if (newTaxa==null)
+					return null;
+				newTaxa.addToFile(file, getProject(), this);
+				if (!MesquiteThread.isScripting())
+					newTaxa.showMe(); //o = doCommand("showTaxa", getProject().getTaxaReferenceExternal(newTaxa), checker);//changed to scriptingRecord so as not to provoke alert 19Jan02
+			}
+			/*
+			if (!MesquiteThread.isScripting() && o!=null && o instanceof MesquiteModule){  
+				MesquiteModule mb = (MesquiteModule)o;
+				mb.doCommand("showWindow", null, checker);
+			}
+			 */
+			decrementMenuResetSuppression();
+			return newTaxa;
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether alerts are on or off", "[on or off]", commandName, "alerts")) {
+			alerts.toggleValue(parser.getFirstToken(arguments));
+		}
+		else if (checker.compare(this.getClass(), "Shows list of taxa blocks", null, commandName, "showTaxasList")) {
+			//Check to see if already has lister for this
+			boolean found = false;
+			int numemp = getNumberOfEmployees();
+			for (int i = 0; i<numemp; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if (((ManagerAssistant)e).getName().equals("Taxa blocks list")) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return e;
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Taxa blocks list"));
+			if (lister==null){
+				message("Sorry, no module was found to list the sets of taxa");
+				return null;
+			}
+			lister.showListWindow(null);
+			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+				lister.getModuleWindow().setVisible(true);
+			return lister;
+		}
+		else if (checker.compare(this.getClass(), "Shows a taxa list window", "[number of taxa block]", commandName, "showTaxa")) {
+			if (StringUtil.blank(arguments)) {
+				for (int i = 0; i< getProject().getNumberTaxas(); i++) {
+					showTaxa(getProject().getTaxa(i));
+				}
+			}
+			else {
+				String id = parser.getFirstToken(arguments);
+				Taxa t = getProject().getTaxa(checker.getFile(), id);  //first try within file
+				if (t == null)
+					t = getProject().getTaxa(id);
+				if (t!=null) {
+					return showTaxa(t);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the ID number of a taxa block", "[id number of taxa block]", commandName, "setID")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberTaxas()) {
+				long id  = MesquiteLong.fromString(parser.getNextToken());
+				String uniqueID = parser.getNextToken();
+				if (!StringUtil.blank(uniqueID) && getProject().getNumberTaxas(uniqueID)==1){
+					Taxa tx = getProject().getTaxa(uniqueID, 0);
+					if (tx!=null) {
+						tx.setAssignedIDNumber(id);
+						return tx;
+					}
+				}
+				Taxa tx = getProject().getTaxa(t);
+				if (tx!=null) {
+					tx.setAssignedIDNumber(id);
+					return tx;
+				}
+			}
+
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public  MesquiteModule getListOfTaxaModule(Taxa taxa, boolean show){
+		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(taxa)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+		if (show)
+			return showTaxa(taxa);
+		return null;
+	}
+	MesquiteModule showTaxa(Taxa tx){
+		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(tx)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Taxon List"));
+		if (lister==null){
+			if (!MesquiteThread.isScripting()) 
+				message("Sorry, no module was found to list the taxa.");
+			return null;
+		}
+		lister.showListWindow(tx);
+		if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+			lister.getModuleWindow().setVisible(true);
+		return lister;
+	}
+	NameReference commentsRef = NameReference.getNameReference("comments");
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			StringBuffer s = new StringBuffer();
+			boolean found = false;
+			MesquiteProject project = file.getProject();
+			for (int i=0; i<project.getNumberTaxas(); i++){
+				Taxa taxa = getProject().getTaxa(i);
+				String taxonReference = "";
+				if (taxa.getName() != null && (project.getNumberTaxas()>1 || (  !file.useSimplifiedNexus && !file.useConservativeNexus &&  !NexusBlock.suppressTITLE)))
+					taxonReference = " TAXA = "+ StringUtil.tokenize(taxa.getName());
+				if (taxa.getFile() == file) {
+
+					//look through all attached bits 
+					int numBits = taxa.getNumberAssociatedBits();
+
+					for (int v = 0; v<numBits; v++){  //added September 2011
+						Bits array = taxa.getAssociatedBits(v);
+						if (!array.getNameReference().getValue().equals("selected")){
+							s.append("\tTAXABITS  "+ taxonReference);
+							s.append(" NAME = ");
+							s.append( ParseUtil.tokenize(array.getNameReference().getValue()));
+							s.append(" on = ");
+
+							String sT = "";
+							int continuing = 0;
+							int lastWritten = -1;
+							for (int ic=0; ic<taxa.getNumTaxa(); ic++) {
+								if (array.isBitOn(ic)) {
+									if (continuing == 0) {
+										sT += " " + Taxon.toExternal(ic);
+										lastWritten = ic;
+										continuing = 1;
+									}
+									else if (continuing == 1) {
+										sT += " - ";
+										continuing = 2;
+									}
+								}
+								else if (continuing>0) {
+									if (lastWritten != ic-1) {
+										sT += " " + Taxon.toExternal(ic-1);
+										lastWritten = ic-1;
+									}
+									else
+										lastWritten = -1;
+									continuing = 0;
+								}
+
+							}
+							if (continuing>1)
+								sT += " " + Taxon.toExternal(taxa.getNumTaxa()-1);
+							s.append(sT);
+							s.append( ";" + StringUtil.lineEnding());
+							found = true;
+						}
+
+					}
+
+					for (int it = 0; it<taxa.getNumTaxa(); it++){
+						String obj = taxa.getAnnotation(it);
+						if (!StringUtil.blank(obj)){
+							s.append("\tTEXT "+ taxonReference + " TAXON = " + Taxon.toExternal(it) + " TEXT = " + StringUtil.tokenize(obj) + ";" + StringUtil.lineEnding());
+							found = true;
+						}
+						//look through all attached longs 
+						int numLongs = taxa.getNumberAssociatedLongs();
+
+						for (int v = 0; v<numLongs; v++){
+							LongArray array = taxa.getAssociatedLongs(v);
+							long c = array.getValue(it);
+
+							if (MesquiteLong.isCombinable(c)){
+
+								s.append("\tSUT  "+ taxonReference);
+								s.append(" TAXON = ");
+								s.append(Integer.toString(it+1));
+								s.append(" NAME = ");
+								s.append( ParseUtil.tokenize(array.getNameReference().getValue()));
+								s.append(" INTEGER = ");
+								s.append(Long.toString(c));
+								s.append( ";" + StringUtil.lineEnding());
+								found = true;
+							}
+						}
+						//look through all attached doubles 
+						int numDoubs = taxa.getNumberAssociatedDoubles();
+
+						for (int v = 0; v<numDoubs; v++){
+							DoubleArray array = taxa.getAssociatedDoubles(v);
+							double c = array.getValue(it);
+
+							if (MesquiteDouble.isCombinable(c)){
+								s.append("\tSUT  "+ taxonReference);
+								s.append(" TAXON = ");
+								s.append(Integer.toString(it+1));
+								s.append(" NAME = ");
+								s.append( ParseUtil.tokenize(array.getNameReference().getValue()));
+								s.append(" REAL = ");
+								s.append(Double.toString(c));
+								s.append( ";" + StringUtil.lineEnding());
+								found = true;
+							}
+						}
+						//look through all attached objects 
+						int numObs = taxa.getNumberAssociatedObjects();
+						for (int v = 0; v<numObs; v++){
+							ObjectArray array = taxa.getAssociatedObjects(v);
+							if (!commentsRef.equals(array.getNameReference())){
+								Object c = array.getValue(it);
+
+								if (c != null && c instanceof String){
+									s.append("\tSUT  "+ taxonReference);
+									s.append(" TAXON = ");
+									s.append(Integer.toString(it+1));
+									s.append(" NAME = ");
+									s.append( ParseUtil.tokenize(array.getNameReference().getValue()));
+									s.append(" STRING = ");
+									s.append(StringUtil.tokenize((String)c));
+									s.append( ";" + StringUtil.lineEnding());
+									found = true;
+								}
+							}
+						}
+					}
+				}
+			}
+			if (found)
+				return s.toString();
+			else
+				return null;
+		}
+		return null;
+	}
+	/*...................................................................................................................*
+	Taxa defaultTaxa = null;
+	MesquiteFile lastFileTaxa = null;
+	Taxa getDefaultTaxa(MesquiteFile file){
+		if (lastFileTaxa == file && defaultTaxa != null){
+			return defaultTaxa;
+		}
+		if (lastFileTaxa != file)
+			lastFileTaxa = file;
+		defaultTaxa = getProject().getTaxa(0);
+		return defaultTaxa;
+	}
+	 */
+
+	int findWhichTaxon(int provisional, boolean fuse, Taxa taxa, MesquiteFile file){
+		int it = Taxon.toInternal(provisional);
+		if (!fuse)
+			return it;
+		IntegerArray translationTable = (IntegerArray)taxa.getAttachment("OrigIndex" + file.getFileName());
+		if (translationTable != null) {
+			int w = translationTable.getValue(it);
+			if (MesquiteInteger.isCombinable(w))
+				return w;
+		}
+		IntegerArray oi = (IntegerArray)taxa.getAttachment("originalIndicesDupRead", IntegerArray.class);
+		if (oi == null) //don't have translation; don't trust and indicate whichTaxon -1
+			return MesquiteInteger.unassigned;
+		int w = oi.getValue(it);
+		if (MesquiteInteger.isCombinable(w))
+			return w;
+		return MesquiteInteger.unassigned;
+	}
+	/*...................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			MesquiteProject project = file.getProject();
+			String commandName = parser.getFirstToken(command);
+			if (commandName.equalsIgnoreCase("TAXA")) {
+				String ttoken  = parser.getNextToken(); //=
+				ttoken  = parser.getNextToken(); //TAXA block (optional)
+				Taxa t = getProject().findTaxa(file, ttoken); 
+				/*getTaxaLastFirst(ttoken);
+				if (t==null){
+					int wt = MesquiteInteger.fromString(ttoken);
+					if (MesquiteInteger.isCombinable(wt))
+						t = getProject().getTaxa(wt-1);
+				}
+				if (t == null && getProject().getNumberTaxas(file)==1)
+					t = getProject().getTaxa(file, 0);
+				if (t == null && getProject().getNumberTaxas()==1)
+					t = getProject().getTaxa(0);
+				 */
+				if (t!=null) {
+					nBlock.setDefaultTaxa(t);
+					return true;
+				}
+				else
+					return false;
+			}
+			else if (commandName.equalsIgnoreCase("TEXT")) {
+				stringPos.setValue(parser.getPosition());
+				String[][] subcommands  = ParseUtil.getSubcommands(command, stringPos);
+				if (subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)
+					return false;
+				int whichTaxon = MesquiteInteger.unassigned;
+				String text = null;
+				Taxa taxa = nBlock.getDefaultTaxa();
+				for (int i=0; i<subcommands[0].length; i++){
+					String subC = subcommands[0][i];
+					if ("TAXON".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichTaxon = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichTaxon))
+							return false;
+						whichTaxon = findWhichTaxon(whichTaxon, fuse, taxa, file);
+					}
+					else if ("TAXA".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						Taxa t = getProject().findTaxa(file, token); /*getTaxa(token);
+						if (t==null){
+							int wt = MesquiteInteger.fromString(token);
+							if (MesquiteInteger.isCombinable(wt))
+								t = getProject().getTaxa(wt-1);
+						}
+						if (t == null && getProject().getNumberTaxas(file)==1)
+							t = getProject().getTaxa(file, 0);
+						if (t == null && getProject().getNumberTaxas()==1)
+							t = getProject().getTaxa(0);
+						 */
+						if (t!=null)
+							taxa = t;
+						else
+							return false;
+					}
+					else if ("TEXT".equalsIgnoreCase(subC)) {
+						text = subcommands[1][i];
+					}
+					else if ("CHARACTER".equalsIgnoreCase(subC)) {
+						return false;
+					}
+				}
+				if (!MesquiteInteger.isCombinable(whichTaxon))
+					return false;
+				if (taxa !=null && text !=null) {
+					/*&&& the following is a check in place because of a bug in 1.02 and previous in which copies of NOTES blocks would be written in all linked files; 
+					this allowed overwriting by old copies of the NOTES block */
+					if (taxa.getFile() != file && file != getProject().getHomeFile()){
+						String s = taxa.getAnnotation(whichTaxon);
+						if (s != null && !s.equals(text)) {
+							file.notesBugWarn = true;
+							file.notesBugVector.addElement("Taxon " + (whichTaxon+1));
+						}
+
+					}
+					/*&&&*/
+
+					taxa.setAnnotation(whichTaxon, text);
+					taxa.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+					return true;
+				}
+
+			}
+			else if (commandName.equalsIgnoreCase("INTEGER") || commandName.equalsIgnoreCase("SUPPLEMENTAL")  || commandName.equalsIgnoreCase("SUT")) {
+				stringPos.setValue(parser.getPosition());
+				String[][] subcommands  = ParseUtil.getSubcommands(command, stringPos);
+				if (subcommands == null || subcommands.length == 0 || subcommands[0] == null || subcommands[0].length == 0)
+					return false;
+				int whichTaxon = MesquiteInteger.unassigned;
+				int integer = MesquiteInteger.unassigned;
+				double doub = MesquiteDouble.unassigned;
+				String string = null;
+				String text = null;
+				String name = null;
+				Taxa taxa = getProject().getTaxa(0);
+				for (int i=0; i<subcommands[0].length; i++){
+					String subC = subcommands[0][i];
+					if ("TAXON".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						whichTaxon = MesquiteInteger.fromString(token);
+						if (!MesquiteInteger.isCombinable(whichTaxon))
+							return false;
+						whichTaxon = findWhichTaxon(whichTaxon, fuse, taxa, file);
+					}
+					else if ("NAME".equalsIgnoreCase(subC)) {
+						name = subcommands[1][i];
+					}
+					else if ("TAXA".equalsIgnoreCase(subC)) {
+						String token = subcommands[1][i];
+						Taxa t = getProject().findTaxa(file, token);
+						/*getTaxa(token);
+						if (t==null){
+							int wt = MesquiteInteger.fromString(token);
+							if (MesquiteInteger.isCombinable(wt))
+								t = getProject().getTaxa(wt-1);
+						}
+						if (t == null && getProject().getNumberTaxas(file)==1)
+							t = getProject().getTaxa(file, 0);
+						if (t == null && getProject().getNumberTaxas()==1)
+							t = getProject().getTaxa(0);
+						 */
+						if (t!=null)
+							taxa = t;
+						else
+							return false;
+					}
+					else if ("INTEGER".equalsIgnoreCase(subC)) {
+						String t = subcommands[1][i];
+						integer = MesquiteInteger.fromString(t);
+					}
+					else if ("REAL".equalsIgnoreCase(subC)) {
+						doub = MesquiteDouble.fromString(subcommands[1][i]);
+					}
+					else if ("STRING".equalsIgnoreCase(subC)) {
+						string = subcommands[1][i];
+					}
+					else if ("CHARACTER".equalsIgnoreCase(subC)) {
+						return false;
+					}
+				}
+				if (!MesquiteInteger.isCombinable(whichTaxon))
+					return false;
+				if (taxa !=null && name != null) {
+					if (MesquiteInteger.isCombinable(integer)){
+						taxa.setAssociatedLong(NameReference.getNameReference(name), whichTaxon, integer);
+						return true;
+					}
+					else if (MesquiteDouble.isCombinable(doub)){
+						taxa.setAssociatedDouble(NameReference.getNameReference(name), whichTaxon, doub);
+						return true;
+					}
+					else if (string != null){
+						taxa.setAssociatedObject(NameReference.getNameReference(name), whichTaxon, string);
+						return true;
+					}
+				}
+
+			}
+			else if (commandName.equalsIgnoreCase("TAXABITS")){
+				String ttoken  = parser.getNextToken(); //TAXA
+				Taxa t= getProject().getTaxa(getProject().getNumberTaxas()-1);  //last first
+				if ("taxa".equalsIgnoreCase(ttoken)){
+					ttoken  = parser.getNextToken(); //=
+				
+					ttoken  = parser.getNextToken(); //TAXA block id
+					t = getProject().findTaxa(file, ttoken); 
+					ttoken  = parser.getNextToken(); //NAME
+				}
+				if (t == null)
+					return false;
+				ttoken  = parser.getNextToken(); //=
+				ttoken  = parser.getNextToken(); //name of bits
+				NameReference nRef = NameReference.getNameReference(ttoken);
+				String token = parser.getNextToken(); 
+				int lastChar = -1;
+				boolean join = false;
+				while (!token.equals(";") && token.length()>0) {
+					if (token.equals("-")) {
+						if (lastChar!=-1)
+							join = true;
+					}
+					else if (token!=null) {
+						if (token != null && token.equals("."))
+							token = Integer.toString(t.getNumTaxa());
+					
+						if (token.startsWith("-")) {
+							if (lastChar!=-1)
+								join = true;
+							token = token.substring(1, token.length());
+						}
+						int whichChar = Taxon.toInternal(MesquiteInteger.fromString(token, false));
+						if (MesquiteInteger.isCombinable(whichChar)) {
+							if (join) {
+								for (int j = lastChar; j<= whichChar; j++)
+									t.setAssociatedBit(nRef,  j, true);
+								lastChar = -1;
+								join = false;
+							}
+							else {
+								t.setAssociatedBit(nRef,  whichChar, true);
+								lastChar = whichChar;
+							}
+						}
+					}
+					token = parser.getNextToken(); 
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+	//NameReference importSourceRef = NameReference.getNameReference("importsource");
+	//NameReference origIndexRef = NameReference.getNameReference("OrigIndex");
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		Parser commandParser = new Parser();
+
+		commandParser.setString(block.toString());
+		MesquiteInteger startCharC = new MesquiteInteger(0);
+		Taxa newTaxa=null;
+		String title=getProject().getTaxas().getUniqueName("Taxa");
+
+
+
+		boolean titleFound = false;
+		String s;
+		NexusBlock t=null;
+		Vector unrec = new Vector();
+		Vector unrecName = new Vector();
+		String blockID = null;
+		boolean fuse = parser.hasFileReadingArgument(fileReadingArguments, "fuseTaxaCharBlocks");
+		boolean hadDuplicateNames= false;
+		int firstNewTaxon = 0;
+		boolean nameProblems = false;
+		boolean merging = false;
+
+		while (!StringUtil.blank(s=commandParser.getNextCommand(startCharC))) {
+			String commandName = parser.getFirstToken(s);
+			if (commandName.equalsIgnoreCase("DIMENSIONS")) {
+				if (fuse){
+					String message = "In the file being imported, there is a taxa block called \"" + title + "\". Mesquite will either fuse this taxa block into the taxa block you select below, or it will import that taxa block as new, separate taxa block.";
+					newTaxa = getProject().chooseTaxa(containerOfModule(), message, true, "Fuse with Selected Taxa Block", "Add as New Taxa Block");
+					if (newTaxa != null){
+						firstNewTaxon = newTaxa.getNumTaxa();
+						merging = true;
+						//This taxa block is to be fused to an existing; thus add to translation table of taxa and characters block names
+						if (titleFound)
+							file.taxaNameTranslationTable.addElement(new MesquiteString(title, newTaxa.getName()), false);
+						hadDuplicateNames= !StringUtil.blank(newTaxa.hasDuplicateNames());
+
+					}
+				}
+				int numTaxa = MesquiteInteger.fromString(parser.getTokenNumber(4));
+				if (!MesquiteInteger.isCombinable(numTaxa) || numTaxa <0){
+					alert("Sorry, the DIMENSIONS statement of the TAXA block appears to be misformatted.  The number of taxa is not validly specified. File reading will fail.");
+					return null;
+				}
+				String inBlock = "";
+				if (titleFound)
+					inBlock = " in block " + title;
+				logln("   " + MesquiteInteger.toString(numTaxa) + " taxa" + inBlock);
+				if (newTaxa != null && fuse){
+
+					newTaxa.addTaxa( newTaxa.getNumTaxa()-1, numTaxa, true);
+					NameReference colorNameRef = NameReference.getNameReference("color");
+					for (int it = firstNewTaxon; it<newTaxa.getNumTaxa(); it++)
+						newTaxa.setAssociatedLong(colorNameRef, it, 10, true);
+				}
+				else {
+
+					newTaxa = new Taxa(numTaxa);
+
+					newTaxa.setName(title);
+					//t = newTaxa.addToFile(file, getProject(), this);
+					newTaxa.deleteUniqueIDs();
+					if (!StringUtil.blank(blockID))
+						newTaxa.setUniqueID(blockID);
+
+				}
+
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				title = parser.getTokenNumber(2);
+				if (fuse && merging && newTaxa != null)
+					file.taxaNameTranslationTable.addElement(new MesquiteString(title, newTaxa.getName()), false);
+				titleFound = true;
+			}
+			else if (commandName.equalsIgnoreCase("TAXLABELS") && newTaxa!=null) {
+				String taxonName;
+				boolean first = true;
+				IntegerArray translationTable = null;
+				if (fuse){
+					translationTable = new IntegerArray(newTaxa.getNumTaxa() - firstNewTaxon);  
+					translationTable.setNameReference(NameReference.getNameReference("OrigIndex" + file.getFileName()));
+					/*for (int it = 0; it<firstNewTaxon; it++){
+						Object o = newTaxa.getAssociatedObject(importSourceRef, it);
+						if (o == null){
+							newTaxa.setAssociatedObject(importSourceRef, it, newTaxa.getFile().getFileName());
+						}
+					}*/
+				}
+				int itNew = firstNewTaxon;
+				for (int it=firstNewTaxon; it<newTaxa.getNumTaxa() && !(taxonName=parser.getNextToken()).equals(";"); it++) {
+					if (!fuse){
+						String w = newTaxa.checkNameLegality(it, it, taxonName);
+						if (it != 0 &&  (it % 1000) == 999)
+							CommandRecord.tick("Taxon " + (it+1) + " name read: \"" + taxonName + "\"");
+						if (w!=null) {
+							nameProblems = true;
+							if (first) 
+								file.setOpenAsUntitled(w);
+
+							first = false;
+						}
+					}
+					/**/else if (translationTable != null) { 
+						// THIS SYSTEM had already existed as originalIndicesDupRead, but the latter seems not be working properly
+						//here find if name exists already; if so, then record which existing taxon and store as ORIGINDEX
+						int wT = newTaxa.whichTaxonNumber(taxonName, false);  //use reverse order lookup in case newly added taxa with identical names as previous
+						if (wT >= 0)
+							translationTable.setValue(it-firstNewTaxon, wT);
+						else 
+							translationTable.setValue(it-firstNewTaxon, itNew++);
+
+					}/**/
+					newTaxa.setTaxonNameNoWarnNoNotify(it, taxonName);
+					/*if (fuse){
+						newTaxa.setAssociatedObject(importSourceRef, it, file.getFileName());
+					}*/
+
+				}
+				/**/	if (fuse) {
+					newTaxa.attach(translationTable);
+
+				}
+				/**/
+				CommandRecord.tick("TAXLABELS statement read");
+			}
+			else if (commandName.equalsIgnoreCase("IDS")) {
+				String cN = parser.getNextToken();
+				int taxNumber = firstNewTaxon;
+				while (cN != null && !cN.equals(";") ) {
+					if (!StringUtil.blank(cN))
+						newTaxa.setUniqueID(taxNumber, cN);
+					taxNumber++;
+					cN = parser.getNextToken();
+				}
+				CommandRecord.tick("IDS statement read");
+			}
+			else if (commandName.equalsIgnoreCase("BLOCKID")) {
+				String cN = parser.getNextToken();
+				if (cN != null && !cN.equals(";")){
+					if (!StringUtil.blank(cN))
+						blockID = cN;
+					cN = parser.getNextToken();
+				}
+				if (newTaxa != null)
+					newTaxa.setUniqueID(blockID);
+			}
+			else if (!(commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK")))  {
+				unrec.addElement(s); //store unrecognized commands because they can't be stored until issue of duplicate taxa blocks is resolved
+				unrecName.addElement(commandName);
+			}
+		}
+		CommandRecord.tick("TAXA block read; checking");
+		if (newTaxa!=null) {
+
+			Taxa eT = existsInOtherFile(newTaxa, file, true, false);
+			if (eT !=null){  //block of taxa with same names found
+				boolean autoDelete = false;
+				String ftn = "";
+				String helpString ="";
+				if (newTaxa.getTaxon(0)!=null)
+					ftn = "; Name of first taxon: " + newTaxa.getTaxon(0).getName();
+				Taxa eTOrder = existsInOtherFile(newTaxa, file, false); //this is considering taxon order; if null then order must differ
+
+				String w = ("There is taxa block that appears to be a duplicate.  \n\nFirst block: \"" + eT.getName() + "\"; \nSecond block: \"" + newTaxa.getName() + "\"" + ftn + "."); 
+				helpString = "In deleting the second taxon block, any other information (e.g., character matrices) associated with that second block will be reattached to the first block";
+				String button = "Delete";
+				//if unique block IDs match AND order same, then delete this block and proceed without querying user
+				//if unique block IDs match and order different, then query with warning that ordering will change
+
+				if (newTaxa.getUniqueID()!= null && eT.getUniqueID() != null && eT.getUniqueID().equals(newTaxa.getUniqueID())){  //same id's; names must be same
+					w = "This file has a taxa block with same ID and taxon names and is thus a duplicate.  First block: \"" + eT.getName() + "\"; Second block: \"" + newTaxa.getName() + "\"" + ftn + ". ";
+					if (eTOrder != null)
+						autoDelete = true;
+				}
+				if (eTOrder == null) {
+					w += " The two taxa blocks have a different ordering of taxa.  If you delete the second block, the ordering of the first block will be maintained.";
+				}
+
+
+				if (!autoDelete && (alerts.getValue() && !MesquiteThread.isScripting())) {
+					if (AlertDialog.query(containerOfModule(), "Duplicate taxa block?", w + " \n\nDo you want to delete the second block?", button, "Keep", 1, helpString)){
+						if (eTOrder == null)
+							setOrder(eT, newTaxa);
+						newTaxa.dispose();
+						file.setCurrentTaxa(eT);
+						if (eTOrder == null) 
+							eT.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+						return new TaxaBlock(null, null);
+					}
+				}
+				else {
+					discreetAlert(w + "\nOnly the first block will be kept.  Any other information (e.g., character matrices) associated with that second block will be reattached to the first block. " +
+							" If you are reading a linked file and do not intend to delete this taxon block from the linked file, then do not save the file!");
+					if (eTOrder == null)
+						setOrder(eT, newTaxa);
+					newTaxa.dispose();
+					file.setCurrentTaxa(eT);
+					if (eTOrder == null) 
+						eT.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+					return new TaxaBlock(null, null);
+				}
+			}
+			if (eT == null){
+				eT = existsInOtherFileByID(newTaxa, file); 
+				if (eT != null) { //taxa block exists according to id, but has either different names or different number of taxa
+
+					if (eT.getNumTaxa() == newTaxa.getNumTaxa()){//same number of Taxa
+
+					}
+				}
+				//taxa claimed to be same ID but names have changed
+			}
+
+
+			if (t==null) {
+				if (fuse && merging)
+					t = newTaxa.getNexusBlock();
+				else
+					t = newTaxa.addToFile(file, getProject(), this);
+			}
+			file.setCurrentTaxa(newTaxa);
+			if (unrec.size()>0){
+				for (int i = 0; i<unrec.size(); i++){
+					String commandName = (String)unrecName.elementAt(i);
+					s = (String)unrec.elementAt(i);
+					readUnrecognizedCommand(file, t, name, block, commandName, s, blockComments, null);
+				}
+			}
+			if (almostExistsInOtherFile(newTaxa, file)) {
+				String ftn = "";
+				if (newTaxa.getTaxon(0)!=null)
+					ftn = "; name of first taxon: " + newTaxa.getTaxon(0).getName();
+				message("A taxa block (\"" + newTaxa.getName() + "\"" + ftn + ") has been found that has more than 80% overlap in taxon names with another taxa block.  If you had intended them to be the same, review them to see that they contain the same number of taxa, and that their taxon names are identical.");
+
+			}
+
+			if (!fuse) 
+				newTaxa.setName(title);
+		}
+		if (newTaxa!=null  && (nameProblems || fuse)){
+			String d = newTaxa.hasDuplicateNames();
+			if (d !=null){
+				if (fuse && !hadDuplicateNames){
+					if (AlertDialog.query(containerOfModule(), "Duplicated taxa", "Some taxon names in the file being read are the same as some already in the project for the taxa block \"" + newTaxa.getName() + "\". Do you want to merge these taxa? \n\n(duplicated names: " + d + ").  WARNING: if these taxa have data in matrices that you are fusing to existing matrices, then the taxon will take on the newly fused values. (mt)")){
+						IntegerArray originalIndices = new IntegerArray(newTaxa.getNumTaxa());
+						originalIndices.setNameReference(NameReference.getNameReference("originalIndicesDupRead"));
+						newTaxa.attach(originalIndices);
+
+						newTaxa.deleteTaxaWithDuplicateNames();
+
+						originalIndices.deleteParts(0, firstNewTaxon);
+
+					}
+				}
+				else {
+					message("A taxa block has duplicated taxon names.  You should fix this.  (duplicated names: " + d + ")  This message can be viewed again in the log.");
+					MesquiteTrunk.errorReportedDuringRun = true;
+				}
+			}
+		}
+		if (!fuse && newTaxa != null && blockComments!=null && blockComments.length()>0)
+			newTaxa.setAnnotation(blockComments.toString(), false);
+		if (fuse)
+			newTaxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+
+		return t;
+	}
+
+	void setOrder(Taxa taxa, Taxa oTaxa){  //sets order of taxa to be same as oTaxa
+		String[][] storedOrder = new String[taxa.getNumTaxa()][2];
+		for (int it = 0; it< storedOrder.length; it++){
+			storedOrder[it][0] = taxa.getUniqueID(it);
+			storedOrder[it][1] = taxa.getTaxonName(it);
+		}
+		taxa.attach(new ObjectContainer("restOrderAftRead", storedOrder));
+		boolean anyIDMoves = false;
+		for (int ic = 0; ic<taxa.getNumTaxa(); ic++){ //first reorder by id's
+			String id = oTaxa.getUniqueID(ic);
+			if (!StringUtil.blank(id)){
+				int whichTaxon = taxa.findByUniqueID(id);
+				if (whichTaxon >=0 && whichTaxon!= ic) {
+					taxa.swapParts(ic, whichTaxon);
+					anyIDMoves = true;
+					//logln("Taxon " + (whichTaxon+1) + " moved into position " + (ic+1) + " (a)");
+				}
+			}
+		}
+		if (!anyIDMoves){
+			for (int ic = 0; ic<taxa.getNumTaxa(); ic++){ //first reorder by id's
+				int whichTaxon = taxa.whichTaxonNumber(oTaxa.getTaxonName(ic));
+				if (whichTaxon >=0 && whichTaxon!= ic) {
+					taxa.swapParts(ic, whichTaxon);
+					//logln("Taxon " + (whichTaxon+1) + " moved into position " + (ic+1) + " (b)");
+				}
+			}
+		}
+	}
+	void restoreOrderIfNeeded(Taxa taxa){  //sets order of taxa to be same as uniqueID string vector attached to Taxa
+		Object obj = taxa.getAttachment("restOrderAftRead"); //if this exists, it had been temporary attached
+		if (obj == null || !(obj instanceof ObjectContainer))
+			return;
+
+		String[][] storedOrder = (String[][])((ObjectContainer)obj).getObject();
+		boolean anyIDMoves = false;
+		for (int ic = 0; ic<taxa.getNumTaxa(); ic++){ //first reorder by id's
+			String id = storedOrder[ic][0];
+			if (!StringUtil.blank(id)){
+				int whichTaxon = taxa.findByUniqueID(id);
+				if (whichTaxon >=0 && whichTaxon!= ic) {
+					taxa.swapParts(ic, whichTaxon);
+					anyIDMoves = true;
+					//logln("Taxon " + (whichTaxon+1) + " moved into position " + (ic+1) + " (a)");
+				}
+			}
+		}
+		if (!anyIDMoves){
+			for (int ic = 0; ic<taxa.getNumTaxa(); ic++){ //first reorder by id's
+				int whichTaxon = taxa.whichTaxonNumber(storedOrder[ic][1]);
+				if (whichTaxon >=0 && whichTaxon!= ic) {
+					taxa.swapParts(ic, whichTaxon);
+					//logln("Taxon " + (whichTaxon+1) + " moved into position " + (ic+1) + " (b)");
+				}
+			}
+		}
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED));
+	}
+	/** returns the Taxa object that is already contained in the project that matches the input Taxa in names, if there exists such a Taxa object in the project*/
+	/*.................................................................................................................*/
+	Taxa existsInOtherFile (Taxa taxa, MesquiteFile file, boolean ignoreOrder, boolean allowInputTaxaToBeSubset){
+		if (allowInputTaxaToBeSubset) 
+			return supersetExistsInOtherFile(taxa,file,ignoreOrder);
+		else
+			return existsInOtherFile(taxa,file,ignoreOrder);
+	}
+	/** returns the Taxa object that is already contained in the project that matches the input Taxa in names, if there exists such a Taxa object in the project*/
+	/*.................................................................................................................*/
+	Taxa existsInOtherFile (Taxa taxa, MesquiteFile file, boolean ignoreOrder){
+		for (int i =0; i<getProject().getNumberTaxas(); i++){
+			Taxa t = getProject().getTaxa(i);
+			if (t.getFile() != file &&  t != taxa && t.equals(taxa, true, ignoreOrder)) {
+				return t;
+			}
+		}
+		return null;
+	}
+	/** returns the Taxa object that is already contained in the project that matches the input Taxa in names, if there exists such a Taxa object in the project.  The input Taxa can have missing taxa.*/
+	/*.................................................................................................................*/
+	Taxa supersetExistsInOtherFile (Taxa taxa, MesquiteFile file, boolean ignoreOrder){
+		for (int i =0; i<getProject().getNumberTaxas(); i++){
+			Taxa t = getProject().getTaxa(i);
+			if (t.getFile() != file &&  t != taxa && t.contains(taxa, true, ignoreOrder)) {
+				return t;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	Taxa existsInOtherFileByID (Taxa taxa, MesquiteFile file){
+
+		for (int i =0; i<getProject().getNumberTaxas(); i++){
+			Taxa t = getProject().getTaxa(i);
+			if (t.getFile() != file && (t.getUniqueID()!= null && taxa.getUniqueID()!=null  && taxa.getUniqueID().equals(t.getUniqueID()))) {
+				return t;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	boolean almostExistsInOtherFile (Taxa taxa, MesquiteFile file){
+		if (taxa == null || taxa.getNumTaxa()==0)
+			return false;
+		for (int i =0; i<getProject().getNumberTaxas(); i++){
+			Taxa t = getProject().getTaxa(i);
+			if (t!=taxa && t.getFile()!=file){
+				if (t == null || t.getNumTaxa()==0)
+					return false;
+				double matches = 0.0;
+				for (int it=0; it<t.getNumTaxa(); it++){
+					if (t.getTaxonName(it).equals("Col.Ade.Bembidion_28S.orig")) {
+						matches = matches + 0.0;
+					}
+					if (taxa.getTaxon(t.getTaxonName(it))!=null)
+						matches+= 1.0;
+					//else logln("unmatched: " + t.getTaxonName(it));
+				}
+				double avg = matches/t.getNumTaxa();
+				double matches2 = 0.0;
+				for (int it=0; it<taxa.getNumTaxa(); it++)
+					if (t.getTaxon(taxa.getTaxonName(it))!=null)
+						matches2+= 1.0;
+					//else logln("unmatched: " + t.getTaxonName(it));
+				double avg2 = matches2/t.getNumTaxa();
+				if (MesquiteDouble.minimum( avg2, avg) > 0.8)
+					return true;
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	String fixDuplicateNames (Taxa taxa){
+		String list = "";
+		for (int i=0; i<taxa.getNumTaxa(); i++){
+			String name = taxa.getTaxonName(i);
+			for (int j=i+1; j<taxa.getNumTaxa(); j++){
+				String name2 = taxa.getTaxonName(j);
+				if (name!=null && name.equalsIgnoreCase(name2)) {
+					String s = taxa.getUniqueName(name2);
+					taxa.setTaxonName(j, s);
+					list += "Taxon \"" + name2 + "\" changed to \"" + s + "\"\n";
+				}
+			}
+		}
+		return list;
+	}
+	/*.................................................................................................................*/
+	String fixBlankNames (Taxa taxa){
+		String list = "";
+		for (int i=0; i<taxa.getNumTaxa(); i++){
+			String name = taxa.getTaxonName(i);
+			if (StringUtil.blank(name)) {
+				name = taxa.getUniqueName("Unnamed Taxon");
+				taxa.setTaxonName(i, name);
+				list += "Unnamed Taxon \"" + (i+1) + "\" named as \"" + name + "\"\n";
+			}
+		}
+		return list;
+	}
+	/*.................................................................................................................*/
+	boolean hasBlankNames (Taxa taxa){
+		for (int i=0; i<taxa.getNumTaxa(); i++){
+			String name = taxa.getTaxonName(i);
+			if (StringUtil.blank(name)) 
+				return true;
+		}
+		return false;
+	}
+	void message(String s){
+		if (alerts.getValue() && !MesquiteThread.isScripting())
+			alert(s);
+		else
+			logln(s);
+	}
+	/*.................................................................................................................*/
+	public String getTaxaBlock(Taxa taxa, TaxaBlock tB, MesquiteFile file){
+		//check first for file ready to write.  In future should have general call to modules, but for now just check for duplicate taxon names
+		if (hasBlankNames(taxa)){
+			discreetAlert("The block of taxa being saved (" + taxa.getName() + ") has blank taxon names.  This will cause problems in saving and reading trees and other functions, and will be fixed (Summary: " +fixBlankNames(taxa) + ")");
+		}
+		CommandRecord.tick("Checking for duplicate taxon names");
+		String d = taxa.hasDuplicateNames(true);
+		if (d !=null){
+			if (MesquiteThread.isScripting())
+				logln("Summary of name changes:\n" + fixDuplicateNames(taxa));
+			else if (AlertDialog.query(containerOfModule(), "Duplicate names!", "The block of taxa being saved (" + taxa.getName() + ") has duplicate taxon names.  This may cause problems in saving and reading trees and other functions.  Do you want Mesquite to fix this by generating unique names by suffixing a number to duplicate names?   (Duplicates: " +d + ")", "Fix", "Don't Fix"))
+				alert("Summary of name changes:\n" + fixDuplicateNames(taxa));
+		}
+
+		if (file == null)
+			file = taxa.getFile();
+		if (file!=null && file.useDataBlocks) //removed 19Jan02 so as not to make minimal dependent on categorical: &&  file.getFileElements().size(mesquite.categ.lib.CategoricalData.class)>0
+			return null;
+		StringBuffer block = new StringBuffer();
+		String end = StringUtil.lineEnding();
+		block.append(end);
+		CommandRecord.tick("Composing taxa block");
+		block.append("BEGIN TAXA");
+		if (taxa.getAnnotation()!=null) 
+			block.append("[!" + StringUtil.tokenize(taxa.getAnnotation()) + "]");
+		block.append(';');
+		block.append(end);
+
+		if (!file.useSimplifiedNexus){
+			if (getProject().getNumberTaxas()>1 || ( !file.useConservativeNexus && !NexusBlock.suppressTITLE))
+				block.append("\tTITLE " + StringUtil.tokenize(taxa.getName()) + ";" + end);
+		}
+		int numTaxaWrite = taxa.getNumTaxa();
+		if (file.writeOnlySelectedTaxa)
+			numTaxaWrite = taxa.numberSelected();
+		block.append("\tDIMENSIONS NTAX=" + numTaxaWrite + ";" + end + "\tTAXLABELS" + end + "\t\t");
+		String taxonName = "";
+		for (int it=0; it<taxa.getNumTaxa(); it++) {
+			if (!file.writeOnlySelectedTaxa || taxa.getSelected(it)){
+				taxonName = taxa.getTaxon(it).getName();
+				if (taxonName!=null){
+					if (file.useStandardizedTaxonNames)
+						block.append("t" + it);
+					else
+						block.append(StringUtil.simplifyIfNeededForOutput(taxonName,file.simplifyNames) + " ");
+				}
+				else
+					block.append(StringUtil.tokenize(" "));
+			}
+			CommandRecord.tick("Writing Taxon " + taxonName);
+		}
+		block.append(end + "\t;" + end);
+
+		CommandRecord.tick("Writing IDs ");
+		int last = lastID(taxa);
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus && last>-1){
+			block.append("\tIDS ");
+			for (int it=0; it<= last; it++) {
+
+				if (!file.writeOnlySelectedTaxa || taxa.getSelected(it)){
+					String id = taxa.getUniqueID(it);
+					if (StringUtil.blank(id))
+						block.append(" _ ");
+					else
+						block.append( id + " ");
+					CommandRecord.tick("Writing Taxon ID " + (it+1));
+				}
+			}
+			block.append(";" + end);
+		}
+		CommandRecord.tick("Taxa block composed ");
+		if (!file.useSimplifiedNexus  && !file.useConservativeNexus && !StringUtil.blank(taxa.getUniqueID()))
+			block.append("\tBLOCKID " + taxa.getUniqueID() + ";" + end);
+		if (tB != null) block.append( tB.getUnrecognizedCommands()+ end);
+		block.append("END;" + end+ end);
+		return block.toString();
+	}
+
+	int lastID(Taxa taxa){
+		for (int it=taxa.getNumTaxa()-1; it>=0; it--) {
+			String id = taxa.getUniqueID(it);
+			if (!StringUtil.blank(id))
+				return it;
+		}
+		return -1;
+	}
+}
+
+
+/* ======================================================================== */
+class TaxaBlockTest extends NexusBlockTest  {
+	public TaxaBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("TAXA");
+	}
+}
+
+/** An object of this kind can be returned by getNexusCommandTest that will be stored in the modulesinfo vector and used
+to search for modules that can read a particular command in a particular block.  (Much as the NexusBlockObject.)*/
+class TAXANexusCommandTest extends NexusCommandTest  {
+	MesquiteInteger pos = new MesquiteInteger();
+	/**returns whether or not the module can deal with command*/
+	public boolean readsWritesCommand(String blockName, String commandName, String command){
+		if (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("TAXA") || commandName.equalsIgnoreCase("TAXABITS")))
+			return true;
+		boolean b = (blockName.equalsIgnoreCase("NOTES")  && (commandName.equalsIgnoreCase("TEXT") || commandName.equalsIgnoreCase("SUPPLEMENTAL") || commandName.equalsIgnoreCase("SUT") |commandName.equalsIgnoreCase("INTEGER")));
+		if (b){
+			pos.setValue(0);
+			String firstToken = ParseUtil.getFirstToken(command,  pos);
+
+			String[][] subcommands  = ParseUtil.getSubcommands(command, pos);
+			if (subcommands == null)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "TAXON")<0 && StringArray.indexOfIgnoreCase(subcommands, 0, "T")<0)
+				return false;
+			if (StringArray.indexOfIgnoreCase(subcommands, 0, "CHARACTER")>=0 || StringArray.indexOfIgnoreCase(subcommands, 0, "C")>=0)
+				return false;
+			return true;
+		}
+		return false;
+	} 
+}
+
diff --git a/Source/mesquite/minimal/NEXUSDefaults/NEXUSDefaults.java b/Source/mesquite/minimal/NEXUSDefaults/NEXUSDefaults.java
new file mode 100644
index 0000000..2721407
--- /dev/null
+++ b/Source/mesquite/minimal/NEXUSDefaults/NEXUSDefaults.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.NEXUSDefaults;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NEXUSDefaults extends DefaultsAssistant {
+	public String getName() {
+		return "NEXUS Defaults";
+	}
+	public String getExplanation() {
+		return "Sets whether TITLE and LINK commands are to be suppressed where possible in saving NEXUS files.";
+	}
+	/*.................................................................................................................*/
+	MesquiteBoolean suppressTitleLink;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		suppressTitleLink = new MesquiteBoolean(false);
+		loadPreferences();
+		addMenuItemToDefaults( "Automatic NEXUS backups...", makeCommand("autobackup",  this));
+		addCheckMenuItemToDefaults( null, "Suppress TITLE in NEXUS files", makeCommand("toggleSuppress",  this), suppressTitleLink);
+		return true;
+	}
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			if (prefs[0].equals("suppress")) {
+				suppressTitleLink.setValue(true);
+				NexusBlock.suppressLINK = true;
+				NexusBlock.suppressTITLE = true;
+			}
+			else  {
+				suppressTitleLink.setValue(false);
+				NexusBlock.suppressLINK = false;
+				NexusBlock.suppressTITLE = false;
+			}
+			if (prefs.length>1){
+				int numBackups = MesquiteInteger.fromString(prefs[1]);
+				if (MesquiteInteger.isCombinable(numBackups))
+					NexusBlock.numBackups = numBackups;
+			}
+		}
+	}
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "suppressTitleLink", suppressTitleLink);   
+		StringUtil.appendXMLTag(buffer, 2, "numBackups", NexusBlock.numBackups);  
+		return buffer.toString();
+	}
+	
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("suppressTitleLink".equalsIgnoreCase(tag))
+			suppressTitleLink.setValue(content);
+		else if ("numBackups".equalsIgnoreCase(tag))
+			NexusBlock.numBackups = MesquiteInteger.fromString(content);
+	}
+	
+	
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether TITLE and LINK commands are to be suppressed where possible in saving NEXUS files", "[on = suppress; off = no]", commandName, "toggleSuppress")) {  
+			boolean current = suppressTitleLink.getValue();
+			suppressTitleLink.toggleValue(parser.getFirstToken(arguments));
+			if (current!=suppressTitleLink.getValue()) {
+				NexusBlock.suppressTITLE = suppressTitleLink.getValue();
+				NexusBlock.suppressLINK = NexusBlock.suppressTITLE;
+				storePreferences();
+			}
+			return suppressTitleLink;
+		}
+		else if (checker.compare(getClass(), "Sets the number of previous backups", "[num backups]", commandName, "autobackup")) {
+			int numBackups = MesquiteInteger.fromString(arguments);
+			if (!MesquiteInteger.isCombinable(numBackups))
+				numBackups = MesquiteInteger.queryInteger(containerOfModule(), "Number of backups", "Number of backups of NEXUS files saved automatically (enter 0 for no backups)", NexusBlock.numBackups, 0, 10000);
+			if (!MesquiteInteger.isCombinable(numBackups) || numBackups == NexusBlock.numBackups)
+				return null;
+			NexusBlock.numBackups = numBackups;
+			storePreferences();
+			return null;
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+}
+
+
diff --git a/Source/mesquite/minimal/OpenURL/OpenURL.java b/Source/mesquite/minimal/OpenURL/OpenURL.java
new file mode 100644
index 0000000..caddf26
--- /dev/null
+++ b/Source/mesquite/minimal/OpenURL/OpenURL.java
@@ -0,0 +1,109 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.OpenURL;
+/*~~  */
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class OpenURL extends GeneralFileMaker  {
+	public String getNameForMenuItem() {
+		return "URL...";
+	}
+	public String getName() {
+		return "Open URL";
+	}
+	public String getExplanation() {
+		return "Opens a file on the web as if it were a local data file";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** make a new    MesquiteProject.*/
+	/*.................................................................................................................*/
+	public MesquiteProject establishProject(String arguments){
+		FileCoordinator fileCoord = getFileCoordinator();
+		MesquiteFile thisFile = new MesquiteFile();
+		if (arguments ==null)
+			arguments = MesquiteString.queryString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Open URL", "URL to open:", "");
+		URL url=null;
+
+		String urlString = null;
+		if (!StringUtil.blank(arguments)) {
+			try {
+				url = new URL(arguments);
+				urlString = url.toString();
+				String fileName = StringUtil.getLastItem(urlString, MesquiteFile.fileSeparator, "/");
+				String dirName = StringUtil.getAllButLastItem(urlString, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+				thisFile.setLocs(false, url, fileName, dirName);
+
+			}
+			catch (MalformedURLException e) {MesquiteModule.mesquiteTrunk.discreetAlert( MesquiteThread.isScripting(),"Bad URL specified for data file: \"" + arguments + "\"");}
+		}
+		else return null;
+		MesquiteProject p = null;
+
+
+
+		if (thisFile!=null && !StringUtil.blank(thisFile.getFileName())) {
+			FileInterpreter fileInterp;
+			logln("Location: " + urlString);
+			logln("");
+			boolean imp = false; //was it imported???
+			//first try nexus.  If can't be read, then make list and query user...
+			NexusFileInterpreter nfi = (NexusFileInterpreter)fileCoord.findImmediateEmployeeWithDuty(NexusFileInterpreter.class);
+			if (nfi!=null && nfi.canReadFile(thisFile))
+				fileInterp = nfi;
+			else {
+				imp = true;
+				fileInterp = fileCoord.findImporter(thisFile, 0, arguments);
+			}
+			if (fileInterp !=null) {
+				p = fileCoord.initiateProject(thisFile.getFileName(), thisFile);
+				
+				MesquiteFile sf = CommandRecord.getScriptingFileS();
+				if (MesquiteThread.isScripting())
+					CommandRecord.setScriptingFileS(thisFile);
+				fileInterp.readFile(getProject(), thisFile, arguments);
+				CommandRecord.setScriptingFileS(sf);
+
+				if (thisFile.isClosed()){
+					if (p !=null)
+						p.developing = false;
+					return null;
+				}
+				else {
+					p.fileSaved(thisFile);
+				}
+			}
+			else {
+				alert("Sorry, an interpreter was not found for this file");
+			}
+		}
+		return p;
+	}
+}
+
diff --git a/Source/mesquite/minimal/ShowEmployeeTree/ShowEmployeeTree.java b/Source/mesquite/minimal/ShowEmployeeTree/ShowEmployeeTree.java
new file mode 100644
index 0000000..2cafaf6
--- /dev/null
+++ b/Source/mesquite/minimal/ShowEmployeeTree/ShowEmployeeTree.java
@@ -0,0 +1,110 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.ShowEmployeeTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Displays a window showing the employee tree of a module. */
+public class ShowEmployeeTree extends EmployeeTree {
+	public String getName() {
+		return "Show Employee Tree";
+	}
+	public String getExplanation() {
+		return "Shows the window listing the tree of employees of the module of a given window.";
+	}
+	/*.................................................................................................................*/
+	BrowseHierarchy drawTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		drawTask= (BrowseHierarchy)hireEmployee(BrowseHierarchy.class, null);
+		if (drawTask == null)
+			return sorry(getName() + " couldn't start because no Browse Hierarchy module obtained.");
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public  HPanel showEmployeeTreeWindow(MesquiteModule module){
+		if (getModuleWindow()== null)
+			setModuleWindow(new EmployeeTreeWindow(this, module, drawTask));
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		getModuleWindow().setVisible(true);
+		getModuleWindow().contentsChanged();
+		getModuleWindow().toFront();
+		return ((EmployeeTreeWindow)getModuleWindow()).getHPanel();
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public void refreshBrowser(Class c){
+		if (c == MesquiteModule.class && getModuleWindow()!=null)
+			((EmployeeTreeWindow)getModuleWindow()).renew();
+		super.refreshBrowser(c);
+	}
+}
+
+//TODO: in response to hiring changes, update the browser
+/*======================================================================== */
+class EmployeeTreeWindow extends MesquiteWindow {
+	HPanel  browser;
+	MesquiteModule focalModule, ownerModule;
+	public EmployeeTreeWindow (MesquiteModule ownerModule, MesquiteModule focalModule, BrowseHierarchy drawTask) {
+		super(ownerModule, false); //infobar
+		setWindowSize(300,300);
+		this.focalModule = focalModule;
+		this.ownerModule = ownerModule;
+		setFont(new Font ("SanSerif", Font.PLAIN, 10));
+
+		getGraphicsArea().setLayout(new BorderLayout());
+		//getGraphicsArea().setBackground(Color.cyan);
+		browser = drawTask.makeHierarchyPanel();
+		browser.setTitle("Employees of \"" + focalModule.getName() + "\"");
+		addToWindow(browser);
+		browser.setSize(getWidth(), getHeight());
+		browser.setVisible(true);
+		browser.setBackground(ColorDistribution.lightYellow);
+		browser.setRootNode(focalModule);
+		setShowExplanation(true);
+		setShowAnnotation(true);
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Employees of \"" + focalModule.getName() + "\""); 
+	}
+	public void renew() {
+		browser.renew();
+	}
+	public HPanel getHPanel(){
+		return browser;
+	}
+}
+
+
diff --git a/Source/mesquite/minimal/Simplicity/Simplicity.java b/Source/mesquite/minimal/Simplicity/Simplicity.java
new file mode 100644
index 0000000..ecdc611
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/Simplicity.java
@@ -0,0 +1,530 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.minimal.Simplicity;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.simplicity.*;
+
+import java.util.zip.*;
+import java.util.*;
+import java.awt.Font;
+import java.io.*;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+
+public class Simplicity extends SimplicityManagerModule {
+
+	/*todo
+	 *  --  have default.xml that is loaded if there is none in prefs yet
+	 *  -- all hidden; none hidden; 
+	 ���  -- accomodate packages with no intro
+	 * -- menu searching should say that item is hidden??? or at least warn some not found because simple interface?
+	 *  -- manual pages for simplification
+	 *  -- design several simplifications
+	 *  -- make sure submenus can be turned off
+	 *  -- how much of window to change colour; fix bugs
+	 *  -- David's bug comments 14 Dec
+	 *  --have package intros return pathtopackage which by default would be mesquite.XXXX
+	 *  */
+	MesquiteBoolean lockSimplicity;
+	String themeToLoad = null;
+	SimplifyControlWindow simplicityWindow;
+	boolean usingLockedSimplification = false;
+	public String getName() {
+		return "Simplicity Manager";
+	}
+	public String getExplanation() {
+		return "A small module to supervise the interface for simplification management." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	/*.................................................................................................................*/
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		lockSimplicity = new MesquiteBoolean(false);
+		
+		if (InterfaceManager.enabled)
+			MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.fileMenu, MesquiteTrunk.defaultsSubmenu,"Lock In Simple Mode", makeCommand("toggleLockSimplicity",  this), lockSimplicity);
+		InterfaceManager.simplicityModule = this;  //remember me
+		loadPreferences();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void init(){
+		importSettingsFiles();
+		addMissingPackageIntros(InterfaceManager.allPackages);
+		simplicityWindow = new SimplifyControlWindow(this, MesquiteTrunk.mesquiteTrunk.interfaceManager, InterfaceManager.allPackages);
+		setModuleWindow(simplicityWindow);
+		showLogWindow();
+
+//		simplicityWindow.addPackages(InterfaceManager.allPackages);
+		if (!usingLockedSimplification){
+			loadSettingsFileByName(themeToLoad);
+			lock(InterfaceManager.locked);
+		}
+		else {
+			InterfaceManager.setSimpleMode(true);
+			InterfaceManager.setLock(true);
+		}
+		resetSimplicity();
+	}
+
+	public  void resetSimplicity(){
+		if (simplicityWindow != null)
+			simplicityWindow.resetSimplicity();
+		storePreferences();
+	}
+	public void lock(boolean L){
+		lockSimplicity.setValue(L);
+		if (simplicityWindow != null)
+			simplicityWindow.lock(L);
+	}
+	boolean hasIntro(ObjectContainer module, Vector allPackages){
+		String[] sMOD = (String[])module.getObject();
+		if ("true".equals(sMOD[3]))  //is intro
+			return true;
+		String pathMOD = sMOD[0];
+		if (pathMOD.equals("mesquite"))
+			return true;
+		for (int i=0; i< allPackages.size(); i++){
+			ObjectContainer ms = (ObjectContainer)allPackages.elementAt(i);
+			if (ms !=module){
+				String[] s = (String[])ms.getObject();
+				String path = s[0];
+				if (!(path.equals("mesquite")) && pathMOD.startsWith(path))  //intro found
+					return true;
+			}
+		}
+		return false;
+	}
+	void addMissingPackageIntros(Vector allPackages){
+		for (int i=0; i< allPackages.size(); i++){
+			ObjectContainer ms = (ObjectContainer)allPackages.elementAt(i);
+			if (!hasIntro(ms, allPackages)){
+				String[] s = (String[])ms.getObject();
+				String path =  StringUtil.getAllButLastItem(s[0], ".");
+				InterfaceManager.addPackageToList(path + " Package", path, path + " Package", true, true);
+			}
+		}
+	}
+	/*---------------------------*/
+	public void importSettingsFiles(){
+		String basePath = 		getInstallationSettingsPath();
+		StringArray custom = null;
+		File f = new File(basePath);
+		if (f.exists() && f.isDirectory()){
+			String[] list = f.list();
+			if (list != null){
+				for (int i=0; i<list.length; i++){
+					StringArray ms = importFile(basePath + list[i], false);
+					if (ms != null){
+						if (list[i].equalsIgnoreCase("locked.xml")){
+							usingLockedSimplification = true;  //this will later be used as a cue to set to simple mode & lock
+							custom = ms;
+						}
+						InterfaceManager.settingsFiles.addElement(ms, false);
+					}
+				}
+
+			}
+		}
+		basePath = 		getPath() + "simplifications" + MesquiteFile.fileSeparator;
+		f = new File(basePath);
+		if (f.exists() && f.isDirectory()){
+			String[] list = f.list();
+			if (list != null){
+				for (int i=0; i<list.length; i++){
+					StringArray ms = importFile(basePath + list[i], true);
+					if (ms != null)
+						InterfaceManager.settingsFiles.addElement(ms, false);
+				}
+
+			}
+		}
+
+		if (custom == null)
+			custom = importFile(MesquiteTrunk.prefsDirectory.toString() + MesquiteFile.fileSeparator +  "Simplification.xml", false);
+		loadSettingsFile(custom);
+	}
+	StringArray importFile(String path, boolean isDefault){
+		if (!MesquiteFile.fileExists(path))
+			return null;
+		String settingsXML = MesquiteFile.getFileContentsAsString(path);
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite",settingsXML);
+		if (root==null)
+			return null;
+		Element element = root.element("simplicitySettings");
+		if (element != null) {
+			Element versionElement = element.element("version");
+			if (versionElement == null)
+				return null;
+			else {
+				int version = MesquiteInteger.fromString(element.elementText("version"));
+				boolean acceptableVersion = version==1;
+				if (acceptableVersion) {
+					String name = (element.elementText("name"));
+					StringArray s =  new StringArray(3);
+					s.setName(name);
+					s.setValue(XML, settingsXML);
+					s.setValue(PATH, path);
+					if (isDefault)
+						s.setValue(DEFAULTORNOT, "default");
+					else
+						s.setValue(DEFAULTORNOT, "nonDefault");
+					return s;
+				}
+			}
+		} 
+		return null;
+	}
+	public  void loadSettingsFileByName(String name){
+		if (name == null)
+			return;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.getElement(name);
+		if (s == null)
+			return;
+		loadSettingsFile(s);
+	}
+	public  void loadSettingsFile(int i){
+		if (!MesquiteInteger.isCombinable(i) || i<0 || i>= InterfaceManager.settingsFiles.size())
+			return;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.elementAt(i);
+		loadSettingsFile(s);
+	}
+	public  void deleteSettingsFile(int i){
+		if (!MesquiteInteger.isCombinable(i) || i<0 || i>= InterfaceManager.settingsFiles.size())
+			return;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.elementAt(i);
+		String path = s.getValue(PATH);
+		MesquiteFile.deleteFile(path);
+		InterfaceManager.settingsFiles.removeElement(s, false);
+	}
+	static final int XML = 0;
+	static final int PATH = 1;
+	static final int DEFAULTORNOT = 2;
+	public  void renameSettingsFile(int i, String newName){
+		if (!MesquiteInteger.isCombinable(i) || i<0 || i>= InterfaceManager.settingsFiles.size())
+			return;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.elementAt(i);
+		String path = s.getValue(PATH);
+		String settingsXML = s.getValue(XML);
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite",settingsXML);
+		if (root==null)
+			return;
+		Element element = root.element("simplicitySettings");
+		if (element != null) {
+			Element versionElement = element.element("version");
+			if (versionElement == null)
+				return ;
+			else {
+				int version = MesquiteInteger.fromString(element.elementText("version"));
+				boolean acceptableVersion = version==1;
+				if (acceptableVersion) {
+					Element name = element.element("name");
+
+					Element settingsFile = DocumentHelper.createElement("mesquite");
+					Document doc = DocumentHelper.createDocument(settingsFile);
+					Element hidden = DocumentHelper.createElement("simplicitySettings");
+					settingsFile.add(hidden);
+					XMLUtil.addFilledElement(hidden, "version","1");
+					XMLUtil.addFilledElement(hidden, "name",newName);
+					Element hp = element.element("hiddenPackages");
+					element.remove(hp);
+					hidden.add(hp);
+					hp = element.element("hiddenMenuItems");
+					element.remove(hp);
+					hidden.add(hp);
+					hp = element.element("hiddenTools");
+					element.remove(hp);
+					hidden.add(hp);
+					s.setName(newName);
+					MesquiteFile.putFileContents(path, XMLUtil.getDocumentAsXMLString(doc), false);
+				}
+			} 
+		}
+	}
+	public  String nameOfSettingsFile(int i){
+		if (!MesquiteInteger.isCombinable(i) || i<0 || i>= InterfaceManager.settingsFiles.size())
+			return null;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.elementAt(i);
+		return s.getName();
+	}
+
+	boolean settingsLoaded = false;
+	public void loadSettingsFile(StringArray s){
+		if (s == null)
+			return;
+		settingsLoaded = true;
+		InterfaceManager.hiddenPackages.removeAllElements(false);
+		InterfaceManager.hiddenMenuItems.removeAllElements(false);
+		InterfaceManager.hiddenTools.removeAllElements(false);
+		String settingsXML = s.getValue(XML);
+		Element root = XMLUtil.getRootXMLElementFromString("mesquite",settingsXML);
+		if (root==null)
+			return;
+		Element element = root.element("simplicitySettings");
+		if (element != null) {
+			Element versionElement = element.element("version");
+			if (versionElement == null)
+				return ;
+			else {
+				int version = MesquiteInteger.fromString(element.elementText("version"));
+				boolean acceptableVersion = version==1;
+				if (acceptableVersion) {
+					String name = (element.elementText("name"));
+					InterfaceManager.themeName = name;
+					Element packages = element.element("hiddenPackages");
+					if (packages != null){
+						List packageElements = packages.elements("package");
+						for (Iterator iter = packageElements.iterator(); iter.hasNext();) {   // this is going through all of the notices
+							Element hiddenPackage = (Element) iter.next();
+							String pkg = hiddenPackage.element("name").getText();
+							InterfaceManager.addPackageToHidden(pkg, false);						
+						}
+					}
+					Element menuItems = element.element("hiddenMenuItems");
+					if (menuItems != null){
+						List menuElements = menuItems.elements("menuItem");
+						for (Iterator iter = menuElements.iterator(); iter.hasNext();) {   // this is going through all of the notices
+							Element hiddenM = (Element) iter.next();
+							String label = XMLUtil.getTextFromElement(hiddenM, "label");
+							String arguments = XMLUtil.getTextFromElement(hiddenM, "arguments");
+							String command = XMLUtil.getTextFromElement(hiddenM, "command");
+							String commandableClass = XMLUtil.getTextFromElement(hiddenM, "commandableClass");
+							String dutyClass = XMLUtil.getTextFromElement(hiddenM, "dutyClass");
+							InterfaceManager.hiddenMenuItems.addElement(new MenuVisibility(label, arguments, command, commandableClass, dutyClass), false);
+						}
+					}
+					Element tools = element.element("hiddenTools");
+					if (tools != null){
+						List buttonElement = tools.elements("tool");
+						for (Iterator iter = buttonElement.iterator(); iter.hasNext();) {   // this is going through all of the notices
+							Element hiddenT = (Element) iter.next();
+							String n = XMLUtil.getTextFromElement(hiddenT,"name");
+							String d = XMLUtil.getTextFromElement(hiddenT,"description");
+							InterfaceManager.hiddenTools.addElement(new MesquiteString(n, d), false);
+						}
+					}
+					storePreferences();
+				}
+			}
+		} 
+		InterfaceManager.reset();
+
+	}
+	/*---------------------------*/
+	public void settingsChanged(){
+		MesquiteFile.putFileContents(MesquiteTrunk.prefsDirectory.toString() + MesquiteFile.fileSeparator +  "Simplification.xml", makeSettingsFile("Custom"), false);
+		InterfaceManager.themeName = null;
+		storePreferences();
+		if (simplicityWindow != null)
+			simplicityWindow.resetSimplicity();
+	}
+	/*---------------------------*/
+	public  String nameOfSimplification(int i){
+		if (!MesquiteInteger.isCombinable(i) || i<0 || i>= InterfaceManager.settingsFiles.size())
+			return null;
+		StringArray s = (StringArray)InterfaceManager.settingsFiles.elementAt(i);
+		String name = s.getName();
+		return name;
+
+	}
+	/*---------------------------*/
+	public String makeSettingsFile(String name){
+		Element settingsFile = DocumentHelper.createElement("mesquite");
+		Document doc = DocumentHelper.createDocument(settingsFile);
+		Element hidden = DocumentHelper.createElement("simplicitySettings");
+		settingsFile.add(hidden);
+		XMLUtil.addFilledElement(hidden, "version","1");
+		XMLUtil.addFilledElement(hidden, "name",name);
+
+		Element hiddenPkgs = DocumentHelper.createElement("hiddenPackages");
+		hidden.add(hiddenPkgs);
+		for (int i=0; i<InterfaceManager.hiddenPackages.size(); i++){
+			MesquiteString ms = (MesquiteString)InterfaceManager.hiddenPackages.elementAt(i);
+			Element elem = DocumentHelper.createElement("package");
+			hiddenPkgs.add(elem);
+			XMLUtil.addFilledElement(elem, "name",ms.getName());
+		}
+
+		Element hiddenMs = DocumentHelper.createElement("hiddenMenuItems");
+		hidden.add(hiddenMs);
+		for (int i=0; i<InterfaceManager.hiddenMenuItems.size(); i++){
+			MenuVisibility mv = (MenuVisibility)InterfaceManager.hiddenMenuItems.elementAt(i);
+			Element elem = DocumentHelper.createElement("menuItem");
+			hiddenMs.add(elem);
+			XMLUtil.addFilledElement(elem, "label",mv.label);
+			if (mv.arguments != null)
+				XMLUtil.addFilledElement(elem, "arguments",mv.arguments);
+			XMLUtil.addFilledElement(elem, "command",mv.command);
+			XMLUtil.addFilledElement(elem, "commandableClass",mv.commandableClassName);
+			XMLUtil.addFilledElement(elem, "dutyClass",mv.dutyClass);
+		}
+		Element hiddenT = DocumentHelper.createElement("hiddenTools");
+		hidden.add(hiddenT);
+		for (int i=0; i<InterfaceManager.hiddenTools.size(); i++){
+			MesquiteString s = (MesquiteString)InterfaceManager.hiddenTools.elementAt(i);
+			Element elem = DocumentHelper.createElement("tool");
+			hiddenT.add(elem);
+			XMLUtil.addFilledElement(elem, "name",s.getName());
+			XMLUtil.addFilledElement(elem, "description",s.getValue());
+		}
+		return XMLUtil.getDocumentAsXMLString(doc);
+	}
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("lockSimplicity".equalsIgnoreCase(tag)){
+			lockSimplicity.setValue(content);
+			InterfaceManager.setLock(lockSimplicity.getValue());
+		}
+		/*	else if ("editingMode".equalsIgnoreCase(tag)){
+			MesquiteBoolean c =new MesquiteBoolean();
+			c.setValue(content);
+			InterfaceManager.setEditingMode(c.getValue());
+		}
+		 */
+		else if ("simplicityMode".equalsIgnoreCase(tag)){
+			MesquiteBoolean c =new MesquiteBoolean();
+			c.setValue(content);
+			InterfaceManager.setSimpleMode(c.getValue());
+		}
+		else if ("theme".equalsIgnoreCase(tag)){
+			themeToLoad = content;
+		}
+		else if ("notheme".equalsIgnoreCase(tag)){
+			themeToLoad = null;
+		}
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "lockSimplicity", lockSimplicity);   
+		StringUtil.appendXMLTag(buffer, 2, "simplicityMode", InterfaceManager.isSimpleMode());   
+		if (InterfaceManager.themeName != null)
+			StringUtil.appendXMLTag(buffer, 2, "theme", InterfaceManager.themeName);   
+		else
+			StringUtil.appendXMLTag(buffer, 2, "notheme", "");   
+		//	StringUtil.appendXMLTag(buffer, 2, "editingMode", InterfaceManager.isEditingMode());   
+		return buffer.toString();
+	}
+	String instructions;
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets interface to FULL", null, commandName, "full")) {
+			InterfaceManager.setSimpleMode(false);
+			InterfaceManager.setEditingMode(false);
+			InterfaceManager.reset();
+			storePreferences();
+		}
+		else if (checker.compare(this.getClass(), "Sets interface to SIMPLE", null, commandName, "simple")) {
+			InterfaceManager.setSimpleMode(true);
+			InterfaceManager.setEditingMode(false);
+			if (!settingsLoaded){
+				Listable simp = ListDialog.queryList(containerOfModule(), "Choose simplification", "What simplification would you like to use?", null, InterfaceManager.settingsFiles, 0);
+				if (simp != null)
+					loadSettingsFile((StringArray)simp);
+			}
+			InterfaceManager.reset();
+			storePreferences();
+		}
+		else if (checker.compare(this.getClass(), "Turns on interface editing", null, commandName, "edit")) {
+			InterfaceManager.setEditingMode(true);
+			InterfaceManager.reset();
+		}
+		else if (checker.compare(this.getClass(), "Turns off interface editing", null, commandName, "offEdit")) {
+			InterfaceManager.setEditingMode(false);
+			InterfaceManager.reset();
+		}
+		else	if (checker.compare(getClass(), "Sets whether to lock the simplicity mode", null, commandName, "toggleLockSimplicity")) {
+			lockSimplicity.toggleValue(null);
+			InterfaceManager.setLock(lockSimplicity.getValue());
+			storePreferences();
+			return lockSimplicity;
+		}
+		/*else if (checker.compare(this.getClass(), "Toggles whether menu visibility is being edited.", null, commandName, "toggleEditMenuVisibility")) {
+			if (InterfaceManager.isEditingMode()) {
+				InterfaceManager.mode = InterfaceManager.SIMPLE;
+			}
+			else{
+				InterfaceManager.mode = InterfaceManager.EDITING;
+			}
+			InterfaceManager.reset();
+		}
+		else if (checker.compare(this.getClass(), "Saves the current simplification", null, commandName, "saveCurrent")) {
+			saveCurrentSettings();
+		}*/
+		else if (checker.compare(this.getClass(), "Saves the current simplification", null, commandName, "saveCurrent")) {
+			MesquiteString result = new MesquiteString("Custom Simplification");
+			if (QueryDialogs.queryString(containerOfModule(), "Simplification Name", "Name of �Simplification:", result)){
+				String contents =  makeSettingsFile(result.getValue());
+				String path = MesquiteFile.getUniqueModifiedFileName(getInstallationSettingsPath() + "simplification", "xml");
+
+				MesquiteFile.putFileContents(path, contents, false, false);
+				StringArray sa = new StringArray(3);
+				sa.setName(result.getValue());
+				sa.setValue(XML, contents);
+				sa.setValue(PATH, path);
+				InterfaceManager.settingsFiles.addElement(sa, false);
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads a simplification", null, commandName, "load")) {
+			int i = MesquiteInteger.fromString( new Parser(arguments));
+			loadSettingsFile(i);
+			if (!InterfaceManager.isEditingMode() && !InterfaceManager.isSimpleMode()){
+				InterfaceManager.setSimpleMode(true);
+				InterfaceManager.reset();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deletes a simplification", null, commandName, "delete")) {
+			int i = MesquiteInteger.fromString( new Parser(arguments));
+			if (MesquiteInteger.isCombinable(i))
+				deleteSettingsFile(i);
+		}
+		else if (checker.compare(this.getClass(), "Renames a simplification", null, commandName, "rename")) {
+			int i = MesquiteInteger.fromString( new Parser(arguments));
+			if (!MesquiteInteger.isCombinable(i))
+				return null;
+			//deleteSettingsFile(i);
+			MesquiteString ms = new MesquiteString(nameOfSettingsFile(i));
+			if (QueryDialogs.queryString(containerOfModule(), "Rename Simplification", "New Name of Simplification:", ms)){
+				renameSettingsFile(i, ms.getValue());
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isHideable() {
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/minimal/Simplicity/SimplifyControlWindow.java b/Source/mesquite/minimal/Simplicity/SimplifyControlWindow.java
new file mode 100644
index 0000000..b804c85
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/SimplifyControlWindow.java
@@ -0,0 +1,894 @@
+package mesquite.minimal.Simplicity;
+
+import mesquite.lib.*;
+import mesquite.lib.simplicity.InterfaceManager;
+
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+public class SimplifyControlWindow extends MesquiteWindow implements SystemWindow {
+	ClassesPane classesPane;
+	MessagePanel message;
+	PackagesPanel packagesPanel;
+	TrianglePanel trianglePanel;
+	ModePanel modePanel;
+	ClassHeadersPanel classesHeaderPanel;
+	JEditorPane instructionsPanel;
+	JScrollPane instructionsScrollPane;
+	int modePanelHeight = 96;
+	int classesHeight = 140;
+	public String instructions;
+	OuterPackagesPanel field;
+	MovePanel movePanel;
+	public SimplifyControlWindow(MesquiteModule module, InterfaceManager manager, Vector allPackages) {
+		super(module, false);
+		resetTitle();
+		setWindowSize(400, 450);
+
+		//instructions
+		String simpLoc = module.getPath() + "instructions.html";
+		instructions = MesquiteFile.getFileContentsAsString(simpLoc);
+		instructions = StringUtil.replace(instructions, "RPATH", MesquiteFile.massageFilePathToURL(MesquiteModule.getRootImageDirectoryPath()));
+		if (instructions == null)
+			instructions = "";
+		//saved settings... load, save
+		classesPane = new ClassesPane();
+		modePanel = new ModePanel(this);
+		modePanel.setBounds(0, 0, getWidth(), modePanelHeight);
+		modePanel.setVisible(true);
+		instructionsPanel = new MesqJEditorPane("text/html","<html></html>");
+		instructionsPanel.setEditable(false);
+		instructionsPanel.setBackground(Color.white);
+		instructionsPanel.setForeground(Color.black);
+		instructionsPanel.setText(instructions);
+		instructionsScrollPane = new  JScrollPane(); 
+		instructionsScrollPane.getViewport().add( instructionsPanel,  BorderLayout.CENTER ); 
+		instructionsScrollPane.setVisible(true);
+		instructionsScrollPane.setBounds(0, modePanelHeight, getWidth(), getHeight()-modePanelHeight);
+		classesHeaderPanel = new ClassHeadersPanel();
+		classesHeaderPanel.setBackground(Color.white);
+
+		classesHeaderPanel.setBounds(0, modePanelHeight, getWidth(), classesHeight - modePanelHeight);
+		classesHeaderPanel.setVisible(true);
+		packagesPanel = new PackagesPanel(this);
+		
+		packagesPanel.addPackages(allPackages);
+		field = new OuterPackagesPanel(packagesPanel);
+		field.setBackground(Color.white);
+		field.setLayout(null);
+		field.setSize(50, packagesPanel.getH());
+		field.add(packagesPanel);
+		packagesPanel.setSize(50, packagesPanel.getH());
+		packagesPanel.setLocation(18,0);
+		trianglePanel = new TrianglePanel(packagesPanel);
+		field.add(trianglePanel);
+		trianglePanel.setBounds(0, 0, 18, packagesPanel.getH());
+		
+		classesPane.addPanel(field);
+		movePanel = new MovePanel(this);
+		addToWindow(classesPane);
+		addToWindow(modePanel);
+		addToWindow(instructionsScrollPane);
+		addToWindow(classesHeaderPanel);
+		addToWindow(movePanel);
+		field.setVisible(true);
+		classesPane.setSize(getWidth(), getHeight()-classesHeight-20);
+		classesPane.setLocation(0, classesHeight);
+
+		classesPane.setVisible(true);
+
+		classesPane.doLayout();
+		message = new MessagePanel(ColorTheme.getExtInterfaceBackground(), false);
+		message.setTextColor(ColorTheme.getExtInterfaceTextContrast());
+		addToWindow(message);
+		
+		message.setBounds(0, getHeight()-20, getWidth(), 20);
+		if (InterfaceManager.themeName == null)
+			message.setMessage("Custom");
+		else
+			message.setMessage(InterfaceManager.themeName);
+		resetSizes();
+		resetTitle();
+		resetSimplicity();
+	}
+
+	public void lock(boolean L){
+		setVisible(!L);
+	}
+	public void setVisible(boolean vis){
+		if (InterfaceManager.locked && vis)
+			return;
+		super.setVisible(vis);
+	}
+	public void resetSimplicity(){
+		if (modePanel != null){
+			modePanel.resetStates();
+			packagesPanel.checkStates();
+
+		}
+		if (!InterfaceManager.isSimpleMode() && !InterfaceManager.isEditingMode())
+			message.setMessage("Using Full Interface");
+		else if (InterfaceManager.themeName!= null){
+			if (!InterfaceManager.isSimpleMode())
+				message.setMessage("Theme: " + InterfaceManager.themeName);
+			else 
+				message.setMessage("Current Theme: " + InterfaceManager.themeName);
+		}
+		else
+			if (!InterfaceManager.isSimpleMode())
+				message.setMessage("Theme: Custom");
+			else 
+				message.setMessage("Current Theme: Custom");
+		resetSizes();
+	}
+	/*.................................................................................................................*/
+	public void addPackages(Vector allPackages){
+		packagesPanel.addPackages(allPackages);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+		to be self-titling so that when things change (names of files, tree blocks, etc.)
+		they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Simplification");
+	}
+
+	/*.................................................................................................................*/
+	/** Gets the minimum height of the content area of the window */
+	public int getMinimumContentHeight(){
+		return 100;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows instructions", null, commandName, "showInstructions")) {
+			MesquiteModule.mesquiteTrunk.alertHTML(instructions, "Simplification Instructions", "Simplification Instructions", 600, 600);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	int smallInstructionsHeight = 120;
+
+	void resetSizes(){
+		if (classesPane!=null && field != null) {
+			modePanel.setBounds(0, 0, getWidth(), modePanelHeight);
+			message.setBounds(0, getHeight()-20, getWidth(), 20);
+
+			if (InterfaceManager.isEditingMode()){
+				classesHeaderPanel.setSize(getWidth(), classesHeight-modePanelHeight);
+				if (smallInstructionsHeight < 60)
+					smallInstructionsHeight = 60;
+				int cpheight = getHeight()-classesHeight-2 -smallInstructionsHeight;
+				if (cpheight < 100)
+					smallInstructionsHeight = getHeight()-classesHeight-2 -100;
+				
+				classesPane.setSize(getWidth(), getHeight()-classesHeight-2 -smallInstructionsHeight);
+				movePanel.setBounds(0,getHeight()- smallInstructionsHeight-2, getWidth(), 2);
+				packagesPanel.setSize(getWidth()-38, packagesPanel.getH());
+				trianglePanel.setSize(18, packagesPanel.getH());
+				field.setSize(getWidth()-20, packagesPanel.getH());
+				instructionsScrollPane.setBounds(0, getHeight()- smallInstructionsHeight, getWidth(), smallInstructionsHeight-20);
+				try{
+					classesPane.doLayout();
+					instructionsScrollPane.doLayout();
+				}
+				catch (Exception e){
+				}
+			}
+			else {
+				classesHeaderPanel.setSize(0,0);
+				classesPane.setSize(0, 0);
+				packagesPanel.setSize(0,0);
+				trianglePanel.setSize(0,0);
+				movePanel.setBounds(0,0,0,0);
+				field.setSize(0, 0);
+				instructionsScrollPane.setBounds(0,modePanelHeight,getWidth(), getHeight()- modePanelHeight-20);
+				try{
+					classesPane.doLayout();
+					instructionsScrollPane.doLayout();
+				}
+				catch (Exception e){
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowResized(){
+		resetSizes();
+	}
+}
+class MovePanel extends MousePanel {
+	SimplifyControlWindow window;
+	int touchY = -1;
+	public MovePanel(SimplifyControlWindow window){
+		setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
+		this.window = window;
+		setBackground(Color.darkGray);
+		setBackground(Color.blue);
+	}
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		touchY = y;
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		int movedY = y - touchY;
+		window.smallInstructionsHeight -= movedY;
+		window.resetSizes();
+		touchY = -1;
+	}
+}
+/* ======================================================================== */
+class ClassesPane extends ScrollPane{
+
+	public ClassesPane () {
+		super(ScrollPane.SCROLLBARS_AS_NEEDED);
+		Adjustable v = getVAdjustable();
+		if (v != null)
+			v.setUnitIncrement(20);
+	}
+	public void addPanel(Component c){
+		addImpl(c, null, 0);
+	}
+}
+
+class TrianglePanel extends MousePanel {
+	Image triangleRight, triangleDown;
+	PackagesPanel packagesPanel;
+	public TrianglePanel(PackagesPanel pp){
+		packagesPanel = pp;
+		triangleRight = MesquiteImage.getImage(MesquiteTrunk.getRootImageDirectoryPath() + "triangleRightOn.gif");
+		triangleDown = MesquiteImage.getImage(MesquiteTrunk.getRootImageDirectoryPath() + "triangleDownOn.gif");
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+	}
+	public void paint(Graphics g){
+		if (packagesPanel.v == null)
+			return;
+		g.setColor(Color.white);
+		g.fillRect(16, 0, getWidth(), getHeight());
+		g.setColor(Color.black);
+		for (int i=0; i<packagesPanel.v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)packagesPanel.v[i];
+			if (cb.isPackage){
+				if (cb.collapsed)
+					g.drawImage(triangleRight, 0, cb.getY()+6, this);
+				else 
+					g.drawImage(triangleDown, 0, cb.getY()+6, this);
+			}
+		}
+	}
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		packagesPanel.shown = packagesPanel.getCheckbox(y);
+		if (packagesPanel.shown != null){
+			if (packagesPanel.shown.late)
+				packagesPanel.explanation.setBounds(4,packagesPanel.getY(packagesPanel.shown)-80,340,40);
+			else 
+				packagesPanel.explanation.setBounds(4,packagesPanel.getY(packagesPanel.shown)+ packagesPanel.shown.getHeight(),340,40);
+			packagesPanel.explanation.setText(packagesPanel.shown.name +": " + packagesPanel.shown.expl);
+			packagesPanel.explanation.setVisible(true);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		packagesPanel.explanation.setVisible(false);
+		packagesPanel.shown = null;
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		PackageCheckbox nowshown = packagesPanel.getCheckbox(y);
+		if (nowshown != packagesPanel.shown){
+			packagesPanel.shown = nowshown;
+			if (packagesPanel.shown != null){
+				if (packagesPanel.shown.late)
+					packagesPanel.explanation.setBounds(4,packagesPanel.getY(packagesPanel.shown)-80,340,40);
+				else 
+					packagesPanel.explanation.setBounds(4,packagesPanel.getY(packagesPanel.shown)+ packagesPanel.shown.getHeight(),340,40);
+				packagesPanel.explanation.setText(packagesPanel.shown.name +": " + packagesPanel.shown.expl);
+				packagesPanel.explanation.setVisible(true);
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	/*.................................................................................................................*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool toolTouching) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (x<18){
+			PackageCheckbox cb = packagesPanel.getCheckbox(y);
+			if (cb != null && cb.isPackage){
+				cb.collapsed = !cb.collapsed;
+				packagesPanel.resetSizesInclParents();
+				repaint();
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+class OuterPackagesPanel extends Panel {
+	PackagesPanel packagesPanel;
+	public OuterPackagesPanel(PackagesPanel pp){
+		packagesPanel = pp;
+	}
+	public Dimension getPreferredSize(){
+		int h = packagesPanel.checkSizes();
+		return new Dimension(packagesPanel.getWidth() + 18, h); 
+	}
+}
+class PackagesPanel extends MousePanel implements ItemListener {
+	Listable[] v;
+	int h = 30;
+	TextArea explanation = new TextArea("", 20, 20, TextArea.SCROLLBARS_NONE);
+	Font fontBig = new Font("SanSerif", Font.BOLD, 14);
+	SimplifyControlWindow w;
+	public PackagesPanel(SimplifyControlWindow w){
+		super();
+		this.w = w;
+		add(explanation);
+		explanation.setBounds(0,0,0,0);
+		explanation.setVisible(false);
+		explanation.setBackground(ColorTheme.getActiveLight());
+		setBackground(Color.white);
+		setLayout(null);
+	}
+	PackageCheckbox shown = null;
+	public void mouseEntered(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		shown = getCheckbox(y);
+		mouseEnteredCheckbox(shown);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseExited(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		explanation.setVisible(false);
+		shown = null;
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseEnteredCheckbox(PackageCheckbox shown) {
+		if (shown != null){
+			this.shown = shown;
+			if (shown.late)
+				explanation.setBounds(4,getY(shown)-80,340,40);
+			else 
+				explanation.setBounds(4,getY(shown)+ shown.getHeight(),340,40);
+			explanation.setText(shown.name +": " + shown.expl);
+			explanation.setVisible(true);
+		}
+	}
+	public void mouseExitedCheckbox(PackageCheckbox shown) {
+		explanation.setVisible(false);
+		shown = null;
+	}
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		PackageCheckbox nowshown = getCheckbox(y);
+		if (nowshown != shown){
+			shown = nowshown;
+			if (shown != null){
+				if (shown.late)
+					explanation.setBounds(4,getY(shown)-80,340,40);
+				else 
+					explanation.setBounds(4,getY(shown)+ shown.getHeight(),340,40);
+				explanation.setText(shown.name +": " + shown.expl);
+				explanation.setVisible(true);
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	public void itemStateChanged(ItemEvent e){
+		if (	checkingStates)
+			return;
+		PackageCheckbox cb = (PackageCheckbox)e.getItemSelectable();
+		if (cb.isSelected())
+			InterfaceManager.removePackageFromHidden(cb.pkg, true);
+		else
+			InterfaceManager.addPackageToHidden(cb.pkg, true);
+		checkStates();
+		if (InterfaceManager.isEditingMode() || InterfaceManager.isSimpleMode()){
+			MesquiteTrunk.resetAllMenuBars();
+			MesquiteTrunk.resetAllToolPalettes();
+		}
+	}
+	
+	/*.................................................................................................................*/
+	void addPackages(Vector allPackages){
+
+		v = new Listable[allPackages.size()];
+		for (int i=0; i< allPackages.size(); i++){
+			ObjectContainer ms = (ObjectContainer)allPackages.elementAt(i);
+			String name = ms.getName();
+			String[] s = (String[])ms.getObject();
+
+			PackageCheckbox cb = new PackageCheckbox(this, name,  s[0], s[1],  "true".equals(s[2]), "true".equals(s[3]));
+			if (allPackages.size()-i<4)
+				cb.setLate(true);
+			cb.setSelected(!InterfaceManager.onHiddenClassListExactly(s[0]));
+			if (cb.isSelected() && InterfaceManager.onHiddenClassList(s[0]))
+				cb.setEnabled(false);
+			cb.addItemListener(this);
+			v[i] = cb;
+			cb.setVisible(true);
+		}
+
+		ListableVector.sort(v);
+
+		for (int i=0; i<v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)v[i];
+			add(cb);
+			cb.setVisible(true);
+		}
+	}
+	 public void resetSizesInclParents(){
+		 checkSizes();
+		 w.resetSizes();
+		w.field.invalidate();
+		w.field.doLayout();
+	}
+	
+	int getH(){
+		return 50 + deepest;
+	}
+	public Dimension getPreferredSize(){
+		int h = checkSizes();
+		return new Dimension(getWidth(), h); 
+	}
+	int deepest = 0;
+	int checkSizes(){
+		if (v == null)
+			return 0;
+		boolean on = true;
+		int count = 0;
+		for (int i=0; i<v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)v[i];
+			if (cb.isPackage){
+				on = !cb.collapsed;
+				cb.setBounds(0,count++*h, getWidth(), h);
+			}
+			else if (!on){
+				cb.setVisible(false);
+			}
+			else {
+				cb.setVisible(true);
+				cb.setBounds(20, count++*h, getWidth(), h);
+			}
+		}
+		deepest = count*h;
+		return deepest;
+	}
+	int getY(PackageCheckbox box){
+		if (v == null)
+			return 0;
+		boolean on = true;
+		int count = 0;
+		for (int i=0; i<v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)v[i];
+			if (cb.isPackage){
+				on = !cb.collapsed;
+				int k = count++;
+				if (box == v[i] && box.isVisible())
+					return (count-1)*h;
+			}
+			else if (on) {
+				int k = count++;
+				if (box == v[i] && box.isVisible())
+					return (count-1)*h;
+			}
+		}
+		return 0;
+	}
+	PackageCheckbox getCheckbox(int y){
+		if (v == null)
+			return null;
+		boolean on = true;
+		int count = 0;
+		for (int i=0; i<v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)v[i];
+			if (cb.isPackage){
+				on = !cb.collapsed;
+				int k = count++;
+				if (y< (1+k)*h)
+					return (PackageCheckbox)v[i];
+			}
+			else if (on) {
+				int k = count++;
+				if (y< (1+k)*h)
+					return (PackageCheckbox)v[i];
+			}
+		}
+		return null;
+	}
+	boolean checkingStates = false;
+	void checkStates(){
+		if (v == null)
+			return;
+		boolean changed = false;
+		for (int i=0; i<v.length; i++){
+			PackageCheckbox cb = (PackageCheckbox)v[i];
+			boolean was = cb.isSelected();
+			checkingStates = true;
+			cb.setSelected(!InterfaceManager.onHiddenClassListExactly(cb.pkg));
+			checkingStates = false;
+			if (was != cb.isSelected())
+				changed = true;
+			if (cb.isSelected() && InterfaceManager.onHiddenClassList(cb.pkg))
+				cb.setEnabled(false);
+			else if (!cb.hideable)
+				cb.setEnabled(false);
+			else
+				cb.setEnabled(true);
+		}
+		
+	if (changed)
+		getParent().doLayout();
+		repaint();
+	}
+	public void setSize( int w, int h){
+		super.setSize(w, h);
+		checkSizes();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		checkSizes();
+	}
+}
+
+/*.................................................................................................................*/
+
+class PackageCheckbox extends JCheckBox implements Listable, MouseListener {
+	String pkg = null;
+	String expl = null;
+	String name = null;
+	boolean late = false;
+	boolean isPackage = false;
+	boolean hideable = true;
+	boolean collapsed = true;
+	PackagesPanel packagesPanel;
+	public PackageCheckbox(PackagesPanel pp, String name, String pkg, String explanation, boolean isHideable, boolean isPackage){
+		super(name);
+		setBackground(Color.white);
+		this.packagesPanel = pp;
+		this.name = name;
+		this.pkg = pkg;
+		this.expl = explanation;
+		this.isPackage = isPackage;
+		this.hideable = isHideable;
+		addMouseListener(this);
+		setEnabled(hideable);
+	}
+	public String getName(){
+		return pkg;
+	}
+	void setLate(boolean late){
+		this.late = late;
+	}
+	public void mouseClicked(MouseEvent e){
+	}
+	public void mouseEntered(MouseEvent e){
+		packagesPanel.mouseEnteredCheckbox(this);
+	}
+	public void mouseExited(MouseEvent e){
+		packagesPanel.mouseExitedCheckbox(this);
+	}
+	public void mousePressed(MouseEvent e){
+	}
+	public void mouseReleased(MouseEvent e){
+	}
+}
+/*.................................................................................................................*/
+class SaveRenameDeleteButton extends LoadSaveDeleteButton {
+	public SaveRenameDeleteButton(){
+		super("Save/Rename/Delete");
+		setBackground(ColorTheme.getExtInterfaceBackground());
+		setForeground(ColorTheme.getExtInterfaceTextContrast());
+		//ColorTheme.getExtInterfaceElement());
+	}
+	void redoMenu() {// don't use this if can't save because don't have permissions
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		popup.removeAll(); 
+		popup.add(new MesquiteMenuItem("Save Current...", null, new MesquiteCommand("saveCurrent", InterfaceManager.simplicityModule), null));
+		MesquiteSubmenu ms = new MesquiteSubmenu("Rename...", popup, null);
+		InterfaceManager.addSettingsMenuItems(ms, "rename", false);
+		popup.add(ms);
+		MesquiteSubmenu ms2 = new MesquiteSubmenu("Delete...", popup, null);
+		InterfaceManager.addSettingsMenuItems(ms2, "delete", false);
+		popup.add(ms2);
+
+		add(popup);
+	}
+	public void resetSize(){
+		if (!InterfaceManager.isEditingMode() || !InterfaceManager.settingsWritable()){
+			setSize(0,0);
+			return;
+		}
+		super.resetSize();
+	}
+}
+/*.................................................................................................................*/
+class LoadButton extends LoadSaveDeleteButton {
+	public LoadButton(){
+		super("Load Simplification");
+		setForeground(Color.darkGray);
+	}
+	void redoMenu() {
+		if (popup==null)
+			popup = new MesquitePopup(this);
+		popup.removeAll();
+		InterfaceManager.addSettingsMenuItems(popup, "load", true);
+		add(popup);
+	}
+}
+/*.................................................................................................................*/
+abstract class LoadSaveDeleteButton extends MousePanel {
+	MesquitePopup popup;
+	Polygon dropDownTriangle;
+	String label;
+	public LoadSaveDeleteButton(String label){
+		dropDownTriangle=MesquitePopup.getDropDownTriangle();
+		this.label = label;
+		Font fontBig = new Font("SansSerif", Font.BOLD, 10);
+		setFont(fontBig);
+		resetSize();
+	}
+	public void resetSize(){
+		Graphics g = getGraphics();
+		if (g == null)
+			return;
+		Font font = g.getFont();
+		FontMetrics fontMet = g.getFontMetrics(font);
+		int w = fontMet.stringWidth(label)+17;
+		int h = fontMet.getAscent() +fontMet.getDescent()+6;
+		setSize(w, h);
+	}
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Font font = g.getFont();
+		FontMetrics fontMet = g.getFontMetrics(font);
+		int hA = fontMet.getAscent();
+		int w = fontMet.stringWidth(label)+16;
+		int h = hA +fontMet.getDescent()+4;
+		int y =16-hA-2;
+		w = getWidth() - 1;
+		h = getHeight() - 1;
+		y = 0;
+		g.setColor(getForeground());
+		g.drawString(label, 4, hA+2);
+		g.drawLine(4, hA+6, w-8, hA+6);
+
+		dropDownTriangle.translate(w - 10 ,8);
+		g.setColor(Color.white);
+		g.drawPolygon(dropDownTriangle);
+		g.setColor(getForeground());
+		g.fillPolygon(dropDownTriangle);
+		dropDownTriangle.translate(-w + 10 ,-8);
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		redoMenu();
+		popup.show(this, 0,20);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	abstract void redoMenu() ;
+}
+
+/*.................................................................................................................*/
+class EditModeButton extends Checkbox implements ItemListener {
+	MesquiteCommand command;
+	Image editing;
+
+	public EditModeButton(){
+		super("Editing Mode");
+		editing = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "notesTool.gif");  
+		setState(false);
+		setBackground(ColorTheme.getExtInterfaceElement());
+		setForeground(ColorTheme.getExtInterfaceTextContrast()); //ColorTheme.getExtInterfaceElement());
+		addItemListener(this);
+	}
+
+	void resetColors(){
+		if (InterfaceManager.isEditingMode()){
+			setBackground(ColorTheme.getExtInterfaceBackground());
+			setForeground(ColorTheme.getExtInterfaceTextContrast());
+		}
+		else {
+			setBackground(ColorTheme.getExtInterfaceElement());
+			setForeground(ColorTheme.getExtInterfaceTextMedium());
+		}
+	}
+	public void itemStateChanged(ItemEvent e){
+		if (InterfaceManager.isEditingMode() == getState())
+			return;
+		InterfaceManager.setEditingMode(getState());
+		resetColors();
+		repaint();
+		MesquiteModule.resetAllMenuBars();
+		MesquiteModule.resetAllToolPalettes();
+		MesquiteWindow.resetAllSimplicity();
+	}
+
+	
+	
+}
+
+/*.................................................................................................................*/
+class ModePanel extends Panel implements ItemListener {
+	CheckboxGroup cbg;
+	Checkbox powerCB, simplerCB;
+	SimplifyControlWindow w;
+	Image power, simple;
+	MesquitePopup popup;
+	LoadButton loadButton;
+	SaveRenameDeleteButton saveRenameDeleteButton;
+	EditModeButton editModeButton;
+	int cbwidth = 160;
+	Font fontBig = new Font("SansSerif", Font.BOLD, 12);
+	Font fontBig14 = new Font("SansSerif", Font.BOLD, 14);
+	int top = 24;
+	public ModePanel(SimplifyControlWindow w){
+		super();
+		this.w = w;
+		cbg = new CheckboxGroup();
+		powerCB = new Checkbox("Full Interface", cbg, true);
+		simplerCB = new Checkbox("Simple Interface", cbg, true);
+		cbg.setSelectedCheckbox(powerCB);
+		setLayout(null);
+		add(powerCB);
+		add(simplerCB);
+		powerCB.setBounds(22, top + 2, cbwidth, 16);
+		powerCB.setFont(fontBig14);
+		powerCB.setVisible(true);
+		simplerCB.setBounds(22, top + 22, cbwidth, 16);
+		simplerCB.setVisible(true);
+		simplerCB.setFont(fontBig14);
+		powerCB.addItemListener(this);
+		simplerCB.addItemListener(this);
+		power = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "simplification/power.gif");  
+		simple = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "simplification/simple.gif");  
+
+		loadButton = new LoadButton();
+		loadButton.setFont(fontBig);
+		loadButton.setVisible(true);
+		add(loadButton);
+
+		saveRenameDeleteButton = new SaveRenameDeleteButton();
+		saveRenameDeleteButton.setFont(fontBig);
+		saveRenameDeleteButton.setVisible(true);
+		add(saveRenameDeleteButton);
+
+		editModeButton = new EditModeButton();
+		resizeButtons();
+		editModeButton.setFont(fontBig);
+		editModeButton.setVisible(true);
+		add(editModeButton);
+		editModeButton.resetColors();
+
+	}
+
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.setFont(fontBig);
+		FontMetrics fontMet = g.getFontMetrics(fontBig);
+		int hA = fontMet.getAscent();
+		String title = "Simplification Control Panel";
+		int w = fontMet.stringWidth(title)+16;
+		g.drawString(title, (getWidth() - w)/2, 16);
+
+		g.drawLine(16, top-2, getWidth()-16, top-2);
+		Composite composite = ColorDistribution.getComposite(g);
+		if (InterfaceManager.isSimpleMode())
+			ColorDistribution.setTransparentGraphics(g,0.1f);
+		if (power != null)
+			g.drawImage(power, 4, top  + 2, this);
+
+		ColorDistribution.setComposite(g,composite);
+
+		if (!InterfaceManager.isSimpleMode())
+			ColorDistribution.setTransparentGraphics(g,0.1f);
+		if (simple != null)
+			g.drawImage(simple, 4, top  + 22, this);
+
+		ColorDistribution.setComposite(g,composite);
+		g.drawLine(0, getHeight()-1, getWidth(), getHeight()-1);
+		if (InterfaceManager.isEditingMode()){
+			g.setColor(Color.cyan);
+			if (InterfaceManager.settingsWritable())
+				g.fillRoundRect(getWidth()-editModeLeft-10, editModeTop + 4, editModeWidth +24, 58, 8, 8);
+			else
+				g.fillRoundRect(getWidth()-editModeLeft-10, editModeTop + 4, editModeWidth +24, 32, 8, 8);
+		}
+		if (editModeButton != null)
+			g.setColor(editModeButton.getBackground());
+		else
+			g.setColor(ColorTheme.getExtInterfaceElement());
+		if (InterfaceManager.isEditingMode() && InterfaceManager.settingsWritable()){
+			g.fillRoundRect(getWidth()-editModeLeft-8, editModeTop + 6, editModeWidth +20, 54, 8, 8);
+		}
+		else {
+			g.fillRoundRect(getWidth()-editModeLeft-8, editModeTop + 6, editModeWidth +20, 28, 8, 8);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	int editModeTop = top+4;
+	int editModeLeft = 170;
+	int editModeWidth = 140;
+
+	void resizeButtons(){
+		if (loadButton != null){
+			loadButton.resetSize();
+			saveRenameDeleteButton.resetSize();
+			loadButton.setLocation(50, top + 40);
+			editModeButton.setLocation(getWidth()-editModeLeft, editModeTop + 8);
+			editModeButton.setSize(140, 24);
+			saveRenameDeleteButton.setLocation(getWidth()-editModeLeft, editModeTop + 36);
+			editModeButton.resetColors();
+		}
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resizeButtons();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resizeButtons();
+	}
+	public void resetStates(){
+
+		if (!InterfaceManager.isSimpleMode())
+			powerCB.setState(true);
+		else if (InterfaceManager.isSimpleMode())
+			simplerCB.setState(true);
+		powerCB.setEnabled(!InterfaceManager.isEditingMode());
+		simplerCB.setEnabled(!InterfaceManager.isEditingMode());
+		repaint();
+		editModeButton.repaint();
+	}
+	
+	public void itemStateChanged(ItemEvent e){
+		MesquiteCommand com;
+		if (powerCB.getState())
+			 com = MesquiteModule.makeCommand("full", w.ownerModule);
+		else
+			 com = MesquiteModule.makeCommand("simple", w.ownerModule);
+		com.doItMainThread(null, null, this);
+		repaint();
+		
+	}
+}
+class ClassHeadersPanel extends Panel  {
+	Font fontBig = new Font("SansSerif", Font.BOLD, 12);
+	Font fontSmall = new Font("SansSerif", Font.PLAIN, 10);
+	/*.................................................................................................................*/
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawLine(0, 0, getWidth(), 0);
+		g.drawLine(0, 1, getWidth(), 1);
+		g.setFont(fontBig);
+		g.drawString("Packages Shown", 8, 18);
+		g.setFont(fontSmall);
+		g.drawString("Deslected packages are hidden when Simple interface is chosen.", 8, 34);
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+}
+
+
diff --git a/Source/mesquite/minimal/Simplicity/instructions.html b/Source/mesquite/minimal/Simplicity/instructions.html
new file mode 100644
index 0000000..a0be5ce
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/instructions.html
@@ -0,0 +1,21 @@
+<html>
+<h3>Simple vs. Full Interface</h3>
+<img src="RPATHsimplification/simple.gif"> Hide many menu items and buttons by choosing <strong>Simple Interface</strong> in the panel above or in the info bars at the top of most windows.
+<p><img src="RPATHsimplification/power.gif"> Use Mesquite's full interface with all menu items and buttons by choosing <strong>Full Interface</strong> in the panel above or in the info bars at the top of most windows.</p>
+<p><img src="RPATHsimplification/load.gif" alt="Load Simplification"> Mesquite comes with some built-in simplification themes. <strong>To load a simplification theme</strong>, touch on Load Simplification in the control panel above and choose a theme in the drop down menu. You can also create your own simplification themes when Editing Mode is on. For instructions of how to use the Editing Mode, see below. </p>
+<hr>
+<h3>Editing Simplification Themes</h3>
+A simplification theme specifies what menu items and tools are hidden. A menu item or tool is hidden if it has been specifically chosen to be hidden, or if the Mesquite package that controls it has been hidden.
+To create or modify your own simplification theme, turn on the <strong>Editing Mode</strong> by selecting it in the panel above.
+<p>To <strong>hide all the menu items and tools belonging to a Mesquite package or module</strong>, uncheck its box in the <strong>Packages Shown</strong> list here. (This list is visible only if Editing Mode is on.)</p>
+<p>To <strong>hide a single menu item</strong>, <u>select it</u> when Editing Mode is on.  Hidden <strong>menu items</strong> will be marked with "<strong>(OFF)</strong>" if you have chosen that particular item to hide, "<strong>(PACKAGE OFF)</strong>" if the item will be hidden because its module or package has been hidden.  Menu items that cannot be turned off are marked with "<strong>(*)</strong>". </p>
+<p>To <strong>hide a single  tool</strong>, <u>select it</u> when Editing Mode is on.
+<ul>
+<li><img src="RPATHsimplification/redRing.gif" alt="individually hidden tools"> Hidden tools are ringed in <font color = "#FF0000"><strong> red</strong></font> if you have chosen that particular tool to hide</li>
+<li><img src="RPATHsimplification/blueRing.gif" alt="package-hidden tools"> Hidden tools are ringed in <font color = "#0000FF"><strong> blue</strong></font> if hidden because its package has been hidden.</li></ul></p>
+<p>After you have edited what you want to hide, deselect "Editing Mode". Then, choose "Simple Interface"  to show the simplified interface.</p>
+<hr><h3>Saving  Simplification Themes</h3>
+Your current simplification theme is automatically saved for you, and loaded when you restart Mesquite. However, you can put aside simplification themes you've created for use later. To do this, make sure Editing Mode is on. Then select <strong>Save Current</strong> from the <strong>Save/Rename/Delete</strong> drop-down menu. (Note: this menu will not be available if your computer account is not permitted to modify the Mesquite_Folder directory.) You will get an opportunity to name the t [...]
+<p>Technical details: The simplifications you make are stored in Mesquite_Folder/settings/mesquite/minimal/Simplify. If your computer account does not have permission to modify this directory, you will be able to load simplification themes but not to store them for later. (The current simplifcation theme that is saved automatically for you is stored in Mesquite_Support_Files/Mesquite_Prefs/Simplification.xml. You could get an administrator to copy this file into Mesquite_Folder/settings/ [...]
+<p> </p>
+</html>
diff --git a/Source/mesquite/minimal/Simplicity/simplification.html b/Source/mesquite/minimal/Simplicity/simplification.html
new file mode 100644
index 0000000..dbfc407
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplification.html
@@ -0,0 +1,15 @@
+<html>
+<h2>Simple vs. Full Interface</h2>
+<p>The Mesquite interface can be shown in <strong>Simple</strong> mode, in which some menu items and tools are hidden or in <strong>Full</strong> mode, in which all available menu items and tools are shown. </p>
+<p>To toggle between <strong>Simple</strong> and <strong>Full</strong>, hit one of the buttons in the Simplify panel (which accompanies the Log window), or touch on the indicator saying "Full Interface" or "Simple Interface" at the top of most windows. </p>
+<h2>What is hidden in Simple mode?</h2>
+A menu item or tool is hidden if it has been specifically chosen to be hidden, or if the Mesquite package that controls it has been hidden.
+<p>To hide all the menu items and tools belonging to a Mesquite package, go to the Simplify panel of the main Mesquite system window, and  choose which packages are shown or hidden.</p>
+<p>To hide a menu item or tool, turn on "<strong>Edit Simple Interface</strong>" either in  the Simplify panel (which accompanies the Log window), or in the menu that drops down when you touch on the indicator saying "Full Interface" or "Simple Interface" at the top of most windows. In editing mode, when you select menu items or tools, they will be highlighted to show they will be hidden. Hidden menu items will be marked with "(OFF)" if you have ch [...]
+<p>After you have edited what you want to hide, choose "Simple Interface" in this menu to show the simplified interface.</p>
+<h2>Saving and loading simplifications</h2>
+You can save your current set of choices for hiding packages, menu items and tools by selecting <strong>Save Current Simplification</strong> either in the drop down menu labeled Save/Load in the Simplify panel, or in the menu that drops down when you touch on the indicator saying "Full Interface" or "Simple Interface" at the top of most windows.
+<p>You can load pre-existing settings for simplifications by selecting items from the <strong>Load Simplification</strong> submenu of the same drop down menu. </p>
+<p>The pre-existing simplifications are stored in Mesquite_Folder/extras/simplifications. If you want to customize and store your own simplification among the pre-existing ones, copy Simplification.xml from Mesquite_Support_Files/Mesquite_Prefs into Mesquite_Folder/extras/simplifications. You can rename this file, and you can also go into the file with a text editor and change "<name>Custom</name>" to a name your prefer, for example "<name>For Students&lt [...]
+<p> </p>
+</html>
diff --git a/Source/mesquite/minimal/Simplicity/simplifications/abMacclade.xml b/Source/mesquite/minimal/Simplicity/simplifications/abMacclade.xml
new file mode 100644
index 0000000..abb9cf7
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplifications/abMacclade.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<mesquite>
+  <simplicitySettings>
+    <version>1</version>
+    <name>MacClade-like</name>
+    <hiddenPackages>
+      <package>
+        <name>mesquite.assoc</name>
+      </package>
+      <package>
+        <name>mesquite.batchArch</name>
+      </package>
+      <package>
+        <name>mesquite.categ</name>
+      </package>
+      <package>
+        <name>mesquite.chromaseq</name>
+      </package>
+      <package>
+        <name>mesquite.coalesce</name>
+      </package>
+      <package>
+        <name>mesquite.consensus</name>
+      </package>
+      <package>
+        <name>mesquite.cont</name>
+      </package>
+      <package>
+        <name>mesquite.correl</name>
+      </package>
+      <package>
+        <name>mesquite.distance</name>
+      </package>
+      <package>
+        <name>mesquite.diverse</name>
+      </package>
+      <package>
+        <name>mesquite.dmanager</name>
+      </package>
+      <package>
+        <name>mesquite.genesis</name>
+      </package>
+      <package>
+        <name>mesquite.io</name>
+      </package>
+      <package>
+        <name>mesquite.mb</name>
+      </package>
+      <package>
+        <name>mesquite.meristic</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental</name>
+      </package>
+      <package>
+        <name>mesquite.pairwise</name>
+      </package>
+      <package>
+        <name>mesquite.rhetenor</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar</name>
+      </package>
+      <package>
+        <name>mesquite.tol</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm</name>
+      </package>
+      <package>
+        <name>mesquite.align.AlignScoreForTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.align.AlignScoreForTaxonRC</name>
+      </package>
+      <package>
+        <name>mesquite.align.ColorForAlignment</name>
+      </package>
+      <package>
+        <name>mesquite.align.ColorMisaligned</name>
+      </package>
+      <package>
+        <name>mesquite.align.SidePusher</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AAHydrophobicity</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AASize</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AminoAcidProperties</name>
+      </package>
+      <package>
+        <name>mesquite.molec.BLASTSearch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.CharacterGCBias</name>
+      </package>
+      <package>
+        <name>mesquite.molec.ColorByNumber</name>
+      </package>
+      <package>
+        <name>mesquite.molec.CompareBasesWithTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.molec.ConvertToRY</name>
+      </package>
+      <package>
+        <name>mesquite.molec.FetchGenBank</name>
+      </package>
+      <package>
+        <name>mesquite.molec.FillCharSelection</name>
+      </package>
+      <package>
+        <name>mesquite.molec.GCAsNumber</name>
+      </package>
+      <package>
+        <name>mesquite.molec.LowercaseEnds</name>
+      </package>
+      <package>
+        <name>mesquite.molec.MaintainClipMatch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.MeanValueLinked</name>
+      </package>
+      <package>
+        <name>mesquite.molec.NumberPolyInTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.molec.NumLowerCase</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PercentLowerCase</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropInternalGaps</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropTerminalGaps</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropUnambigSites</name>
+      </package>
+      <package>
+        <name>mesquite.molec.SequenceInfoEditor</name>
+      </package>
+      <package>
+        <name>mesquite.molec.SiteProperty</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TargetSeqMatch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TaxaListHasData</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TaxonGCBias</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TopBlastMatches</name>
+      </package>
+    </hiddenPackages>
+    <hiddenMenuItems/>
+    <hiddenTools/>
+  </simplicitySettings>
+</mesquite>
diff --git a/Source/mesquite/minimal/Simplicity/simplifications/acBasicPopGen.xml b/Source/mesquite/minimal/Simplicity/simplifications/acBasicPopGen.xml
new file mode 100644
index 0000000..78403a1
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplifications/acBasicPopGen.xml
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<mesquite>
+  <simplicitySettings>
+    <version>1</version>
+    <name>Basic Population Genetics</name>
+    <hiddenPackages>
+      <package>
+        <name>mesquite.batchArch</name>
+      </package>
+      <package>
+        <name>mesquite.cont</name>
+      </package>
+      <package>
+        <name>mesquite.correl</name>
+      </package>
+      <package>
+        <name>mesquite.distance</name>
+      </package>
+      <package>
+        <name>mesquite.diverse</name>
+      </package>
+      <package>
+        <name>mesquite.dmanager</name>
+      </package>
+      <package>
+        <name>mesquite.genesis</name>
+      </package>
+      <package>
+        <name>mesquite.leaves</name>
+      </package>
+      <package>
+        <name>mesquite.meristic</name>
+      </package>
+      <package>
+        <name>mesquite.pairwise</name>
+      </package>
+      <package>
+        <name>mesquite.rhetenor</name>
+      </package>
+      <package>
+        <name>mesquite.tol</name>
+      </package>
+      <package>
+        <name>mesquite.align.AlignScoreForTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.align.AlignScoreForTaxonRC</name>
+      </package>
+      <package>
+        <name>mesquite.align.ColorForAlignment</name>
+      </package>
+      <package>
+        <name>mesquite.align.ColorMisaligned</name>
+      </package>
+      <package>
+        <name>mesquite.align.SidePusher</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AAHydrophobicity</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AASize</name>
+      </package>
+      <package>
+        <name>mesquite.molec.AminoAcidProperties</name>
+      </package>
+      <package>
+        <name>mesquite.molec.BLASTSearch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.CharacterGCBias</name>
+      </package>
+      <package>
+        <name>mesquite.molec.ColorByNumber</name>
+      </package>
+      <package>
+        <name>mesquite.molec.CompareBasesWithTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.molec.ConvertToRY</name>
+      </package>
+      <package>
+        <name>mesquite.molec.FetchGenBank</name>
+      </package>
+      <package>
+        <name>mesquite.molec.FillCharSelection</name>
+      </package>
+      <package>
+        <name>mesquite.molec.GCAsNumber</name>
+      </package>
+      <package>
+        <name>mesquite.molec.LowercaseEnds</name>
+      </package>
+      <package>
+        <name>mesquite.molec.MaintainClipMatch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.MeanValueLinked</name>
+      </package>
+      <package>
+        <name>mesquite.molec.NumberPolyInTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.molec.NumLowerCase</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PercentLowerCase</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropInternalGaps</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropTerminalGaps</name>
+      </package>
+      <package>
+        <name>mesquite.molec.PropUnambigSites</name>
+      </package>
+      <package>
+        <name>mesquite.molec.SequenceInfoEditor</name>
+      </package>
+      <package>
+        <name>mesquite.molec.SiteProperty</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TargetSeqMatch</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TaxaListHasData</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TaxonGCBias</name>
+      </package>
+      <package>
+        <name>mesquite.molec.TopBlastMatches</name>
+      </package>
+      <package>
+        <name>mesquite.ancstates</name>
+      </package>
+      <package>
+        <name>mesquite.align</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.AnnotPanel</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectCharsWithProbP</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectRndCharacters</name>
+      </package>
+      <package>
+        <name>mesquite.io.ExportCharStateInfo</name>
+      </package>
+      <package>
+        <name>mesquite.lists.CharListAnnotPanel</name>
+      </package>
+      <package>
+        <name>mesquite.mb</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental.Constellation</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental.ManageHyperlinks</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental.PictureWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental.Projector</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.AsymmetryLR</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.AsymmMkExplorer</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.AsymmModelCurator</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.Brownian</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.CharLikelihood</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.GainLossRates</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.InterpretPagelFormat</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.InterpretPagelFormatM</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.LikelihoodInCharacter</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.MargProbAncStates</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.StochCharMapper</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar.zMargLikeCateg</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.AugmentTreeRandomly</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.AvgTaxonValueAmgTrees</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.CollessImbalance</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.EmailTree</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.MRPMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RandomBranchMoves</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RandomlyModifiedTrees</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RandomModifTree</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RandomResolve</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RarefyTree</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.RearrangedTree</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomModRespMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomModifMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomFillWithMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ShuffleStates</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleWTaxaByPart</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleWithinTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleMatrixByPart</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleCharacter</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RarefyMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectDiffering</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectMatchingTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectSame</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SprinkleMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.BootstrapResample</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomFillCateg</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortsManagerChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortsInCharList</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.EqualRatesSpSampled</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.ProbRndTreeModifier</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.NoiseToBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm.TerminalInstability</name>
+      </package>
+      <package>
+        <name>mesquite.trees.EquiprobableTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.EqualRatesMarkovSp</name>
+      </package>
+      <package>
+        <name>mesquite.categ.StateNamesEditor</name>
+      </package>
+    </hiddenPackages>
+    <hiddenMenuItems>
+      <menuItem>
+        <label>Add AUTHORS Block to File</label>
+        <command>addAuthorsBlock</command>
+        <commandableClass>mesquite.basic.ManageAuthors.ManageAuthors</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>New Generic NEXUS block...</label>
+        <command>newBlock</command>
+        <commandableClass>mesquite.minimal.ManageForeignBlocks.ManageForeignBlocks</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Edit Mesquite script</label>
+        <command>showScript</command>
+        <commandableClass>mesquite.minimal.ManageMesquiteBlock.ManageMesquiteBlock</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Add Note On Tree</label>
+        <arguments>Add_Note_On_Tree</arguments>
+        <command>newAssistant</command>
+        <commandableClass>mesquite.trees.BasicTreeWindowMaker.BasicTreeWindow</commandableClass>
+        <dutyClass>mesquite.lib.duties.TreeDisplayAssistantD</dutyClass>
+      </menuItem>
+      <menuItem>
+        <label>Assign Color to Selected</label>
+        <arguments>Assign_Color_to_Selected</arguments>
+        <command>assignColor</command>
+        <commandableClass>mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Remove Color from Selected</label>
+        <command>removeColor</command>
+        <commandableClass>mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Add Info Strip</label>
+        <arguments>Add_Info_Strip</arguments>
+        <command>hireDataInfoStrip</command>
+        <commandableClass>mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Show State Names Strip</label>
+        <command>showStrip</command>
+        <commandableClass>mesquite.categ.StateNamesStrip.StateNamesStrip</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Emphasize Less Degenerate Amino Acids</label>
+        <command>emphasizeDegeneracy</command>
+        <commandableClass>mesquite.molec.ColorByAA.ColorByAA</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Show Character Reference Strip</label>
+        <command>showStrip</command>
+        <commandableClass>mesquite.charMatrices.CharReferenceStrip.CharReferenceStrip</commandableClass>
+      </menuItem>
+      <menuItem>
+        <label>Color Text</label>
+        <arguments>Color_Text</arguments>
+        <command>colorText</command>
+        <commandableClass>mesquite.charMatrices.BasicDataWindowMaker.BasicDataWindow</commandableClass>
+      </menuItem>
+    </hiddenMenuItems>
+    <hiddenTools>
+      <tool>
+        <name>mesquite.charMatrices.MatrixInfoTool.MatrixInfoTool.matrixInfo</name>
+        <description>Data information</description>
+      </tool>
+      <tool>
+        <name>mesquite.charMatrices.AddDeleteData.AddDeleteData.addTaxa</name>
+        <description>Add Taxa</description>
+      </tool>
+      <tool>
+        <name>mesquite.charMatrices.AddDeleteData.AddDeleteData.addChars</name>
+        <description>Add Characters</description>
+      </tool>
+      <tool>
+        <name>mesquite.ornamental.BranchNotes.BranchNotesToolExtra.BranchNotes</name>
+        <description>Annotate Branch</description>
+      </tool>
+      <tool>
+        <name>mesquite.ornamental.TaxonLink.TaxonLinkToolExtra.taxonLink</name>
+        <description>Go to link</description>
+      </tool>
+      <tool>
+        <name>mesquite.treefarm.MakeRerootings.AllRerootToolExtra.allRerootings</name>
+        <description>Make All Rerootings of Clade</description>
+      </tool>
+    </hiddenTools>
+  </simplicitySettings>
+</mesquite>
diff --git a/Source/mesquite/minimal/Simplicity/simplifications/adMorphPhyl.xml b/Source/mesquite/minimal/Simplicity/simplifications/adMorphPhyl.xml
new file mode 100644
index 0000000..548b475
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplifications/adMorphPhyl.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<mesquite>
+  <simplicitySettings>
+    <version>1</version>
+    <name>Basic Morphological Phylogenetics</name>
+    <hiddenPackages>
+      <package>
+        <name>mesquite.align</name>
+      </package>
+      <package>
+        <name>mesquite.genesis</name>
+      </package>
+      <package>
+        <name>mesquite.assoc</name>
+      </package>
+      <package>
+        <name>mesquite.batchArch</name>
+      </package>
+      <package>
+        <name>mesquite.coalesce</name>
+      </package>
+      <package>
+        <name>mesquite.correl</name>
+      </package>
+      <package>
+        <name>mesquite.distance</name>
+      </package>
+      <package>
+        <name>mesquite.diverse</name>
+      </package>
+      <package>
+        <name>mesquite.molec</name>
+      </package>
+      <package>
+        <name>mesquite.pairwise</name>
+      </package>
+      <package>
+        <name>mesquite.rhetenor</name>
+      </package>
+      <package>
+        <name>mesquite.dmanager</name>
+      </package>
+      <package>
+        <name>mesquite.mb</name>
+      </package>
+      <package>
+        <name>mesquite.meristic</name>
+      </package>
+      <package>
+        <name>mesquite.tol</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar</name>
+      </package>
+    </hiddenPackages>
+    <hiddenMenuItems>
+      <menuItem>
+        <label>Plot Tree</label>
+        <arguments>Plot_Tree</arguments>
+        <command>setTreeDrawer</command>
+        <commandableClass>mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator</commandableClass>
+        <dutyClass>mesquite.lib.duties.DrawTree</dutyClass>
+      </menuItem>
+    </hiddenMenuItems>
+    <hiddenTools>
+      <tool>
+        <name>mesquite.treefarm.MakeRerootings.AllRerootToolExtra.allRerootings</name>
+        <description>Make All Rerootings of Clade</description>
+      </tool>
+    </hiddenTools>
+  </simplicitySettings>
+</mesquite>
diff --git a/Source/mesquite/minimal/Simplicity/simplifications/zaNoneHidden.xml b/Source/mesquite/minimal/Simplicity/simplifications/zaNoneHidden.xml
new file mode 100644
index 0000000..f66ddf1
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplifications/zaNoneHidden.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<mesquite>
+  <simplicitySettings>
+    <version>1</version>
+    <name>None Hidden</name>
+    <hiddenPackages>
+    </hiddenPackages>
+    <hiddenTools>
+    </hiddenTools>
+  </simplicitySettings>
+</mesquite>
diff --git a/Source/mesquite/minimal/Simplicity/simplifications/zzMinimal.xml b/Source/mesquite/minimal/Simplicity/simplifications/zzMinimal.xml
new file mode 100644
index 0000000..4a43342
--- /dev/null
+++ b/Source/mesquite/minimal/Simplicity/simplifications/zzMinimal.xml
@@ -0,0 +1,672 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<mesquite>
+  <simplicitySettings>
+    <version>1</version>
+    <name>Minimal Interface</name>
+    <hiddenPackages>
+      <package>
+        <name>mesquite.align</name>
+      </package>
+      <package>
+        <name>mesquite.ancstates</name>
+      </package>
+      <package>
+        <name>mesquite.assoc</name>
+      </package>
+      <package>
+        <name>mesquite.batchArch</name>
+      </package>
+      <package>
+        <name>mesquite.categ</name>
+      </package>
+      <package>
+        <name>mesquite.charts</name>
+      </package>
+      <package>
+        <name>mesquite.coalesce</name>
+      </package>
+      <package>
+        <name>mesquite.consensus</name>
+      </package>
+      <package>
+        <name>mesquite.basic.TruncTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.TextWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.basic.TaxaSelCoordinator</name>
+      </package>
+      <package>
+        <name>mesquite.basic.RemoveFromTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ReplaceInTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.SearchNameTaxonSelector</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ShowText</name>
+      </package>
+      <package>
+        <name>mesquite.basic.StoredTaxonPairs</name>
+      </package>
+      <package>
+        <name>mesquite.basic.SuffixTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.RawNexusBlockEditor</name>
+      </package>
+      <package>
+        <name>mesquite.basic.NextProject</name>
+      </package>
+      <package>
+        <name>mesquite.basic.MergeTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageTaxaSets</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageTaxaPartitions</name>
+      </package>
+      <package>
+        <name>mesquite.basic.AddToTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.AssignTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.AuthorDefaults</name>
+      </package>
+      <package>
+        <name>mesquite.basic.BasicParametersExplorer</name>
+      </package>
+      <package>
+        <name>mesquite.basic.CondenseTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.CurrentTaxaPartition</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageArchivedTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.basic.GoToWebPage</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ExamplesNavigator</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageAuthors</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageFileComments</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageLabelsBlock</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageNotesBlock</name>
+      </package>
+      <package>
+        <name>mesquite.basic.ManageSetsBlock</name>
+      </package>
+      <package>
+        <name>mesquite.cont</name>
+      </package>
+      <package>
+        <name>mesquite.correl</name>
+      </package>
+      <package>
+        <name>mesquite.distance</name>
+      </package>
+      <package>
+        <name>mesquite.diverse</name>
+      </package>
+      <package>
+        <name>mesquite.meristic</name>
+      </package>
+      <package>
+        <name>mesquite.mb</name>
+      </package>
+      <package>
+        <name>mesquite.lists</name>
+      </package>
+      <package>
+        <name>mesquite.io</name>
+      </package>
+      <package>
+        <name>mesquite.genesis</name>
+      </package>
+      <package>
+        <name>mesquite.dmanager</name>
+      </package>
+      <package>
+        <name>mesquite.treefarm</name>
+      </package>
+      <package>
+        <name>mesquite.tol</name>
+      </package>
+      <package>
+        <name>mesquite.stochchar</name>
+      </package>
+      <package>
+        <name>mesquite.search</name>
+      </package>
+      <package>
+        <name>mesquite.rhetenor</name>
+      </package>
+      <package>
+        <name>mesquite.parsimony</name>
+      </package>
+      <package>
+        <name>mesquite.pairwise</name>
+      </package>
+      <package>
+        <name>mesquite.ornamental</name>
+      </package>
+      <package>
+        <name>mesquite.molec</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.AddDeleteData</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.AlterData</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.AnnotPanel</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.BasicDataWindowCoord</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.BasicDataWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.BooleanForCharInfoStrip</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.BootstrapResample</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharGroupColor</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharMatrixCoordIndep</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharMatrixCoordObed</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharReferenceStrip</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharSelCoordinator</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharSrcCoordIndep</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CharSrcCoordObed</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.WandTaxon</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.WandChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.Wand</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.TaxonGroupColor</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.StoredMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.StoredCharacters</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SprinkleMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortsManagerChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortsInCharList</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SortChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ShuffleStates</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectVariableCharacters</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectSameVert</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectSame</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectRndCharacters</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectMatchingTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectDiffering</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SelectCharsWithProbP</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SearchSelect</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorByCharValue</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorByExcluded</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorByFootnote</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorByState</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorByTaxonValue</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ColorCells</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ConcatRespMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ConcatenateMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.CompareMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.DataPainter</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.DifferenceInNumsForChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.Fill</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.IncludedCharBoolean</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageAssumptionsBlock</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharacters</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharInclusion</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharModels</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharPartitions</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharsets</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCharWeights</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCodonPositions</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageCodonsBlock</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ManageDATAblock</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.MatrixFromClipboard</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.MatrixInfoTool</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.MatrixSelection</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.NoColor</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.NumApplicableNonMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.NumForCharWithChar</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.PercentGaps</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.PercentMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.QuickKeySelector</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomFillCateg</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomFillWithMissing</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomModifMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RandomModRespMatrices</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RarefyMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.RecodeCateg</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleCharacter</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SearchData</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.SaveMatrixCopies</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleWTaxaByPart</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleWithinTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleMatrixByPart</name>
+      </package>
+      <package>
+        <name>mesquite.charMatrices.ReshuffleMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.trees.MultiTreeWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.trees.MirrorTreeWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ValuesAtNodes</name>
+      </package>
+      <package>
+        <name>mesquite.trees.UtilityCoordinator</name>
+      </package>
+      <package>
+        <name>mesquite.trees.Ultrametricize</name>
+      </package>
+      <package>
+        <name>mesquite.trees.TreeValueUsingMatrix</name>
+      </package>
+      <package>
+        <name>mesquite.trees.TreeOfContext</name>
+      </package>
+      <package>
+        <name>mesquite.trees.TreeNotesMaker</name>
+      </package>
+      <package>
+        <name>mesquite.trees.TreeLegendMaker</name>
+      </package>
+      <package>
+        <name>mesquite.trees.TreeInfoValues</name>
+      </package>
+      <package>
+        <name>mesquite.trees.StoredTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.StoredTreeBlocks</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SquareTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SimulateTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SimulatedTreeBlocks</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ShadeNumbersOnTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetTreeDefaults</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetToUnrooted</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetToRooted</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetToLadderized</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetSelBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetBranchLengthsIfLessThan</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetBranchLengthsFromNames</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetAssumptionSoft</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetAssumptionHard</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SetAssumptionDefault</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SelectTaxaInClade</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SelectBranches</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SearchTreeToolAssistant</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SearchForBetterTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ScaleSelBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ScaleBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.SampleManyTreesFromFile</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ResolvePolytomiesToZero</name>
+      </package>
+      <package>
+        <name>mesquite.trees.RemoveTaxaFromTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.OtherTreeBlocks</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ObedientTreeWindow</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumsForNodesBrLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForTreeWithChar</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForTreeWith2Chars</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForTreeSelNodeValue</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForTreeCladeValue</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForNodesWithMat</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForNodesWithCharHist</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForNodesWithChar</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForMatCurrentTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForCharRespTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForCharOnTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumForCharCurrentTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumFor2CharCurrentTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NumberOfTaxa</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NodeNamer</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NodeLocsStandard</name>
+      </package>
+      <package>
+        <name>mesquite.trees.NegativeToZeroBL</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ManyTreesFromFile</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ManageTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ListedTreeBlocks</name>
+      </package>
+      <package>
+        <name>mesquite.trees.LabelBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.EquiprobableTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.EqualRatesMarkovSp</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DifferenceInNumsForTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DiagonalDrawTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DependentTreeWindow</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DefiniteTreeSource</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DefaultTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.DeassignBranchLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ColorBranches</name>
+      </package>
+      <package>
+        <name>mesquite.trees.CollapseZeroToPolys</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ClearBranchNames</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BranchLengthsAdjust</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BranchLengthFromRoot</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BranchInfo</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BooleanTreeValue</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BasicTreeWindowMaker</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BasicTreeWindowCoord</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BasicTreeDrawCoordinator</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BasicDrawTaxonNames</name>
+      </package>
+      <package>
+        <name>mesquite.trees.BallsNSticks</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AverageTreeValue</name>
+      </package>
+      <package>
+        <name>mesquite.trees.ArcTree</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AlterTrees</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AlterLengths</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AllUnassignBrLengths1</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AllBranchLengthsOne</name>
+      </package>
+      <package>
+        <name>mesquite.trees.AddTaxaToTree</name>
+      </package>
+    </hiddenPackages>
+    <hiddenMenuItems/>
+    <hiddenTools/>
+  </simplicitySettings>
+</mesquite>
diff --git a/Source/mesquite/minimal/StoredTaxa/StoredTaxa.java b/Source/mesquite/minimal/StoredTaxa/StoredTaxa.java
new file mode 100644
index 0000000..7ae06a6
--- /dev/null
+++ b/Source/mesquite/minimal/StoredTaxa/StoredTaxa.java
@@ -0,0 +1,163 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.StoredTaxa;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies taxa from taxa blocks stored in the project.*/
+public class StoredTaxa extends TaxonSource implements MesquiteListener {
+	public String getName() {
+		return "Stored Taxa";
+	}
+	public String getExplanation() {
+		return "Supplies taxa stored, for instance in a file.";
+	}
+	/*.................................................................................................................*/
+	int currentTaxon=0;
+	Taxa currentTaxa = null;
+	TreesManager manager;
+	MesquiteSubmenuSpec listSubmenu;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (getProject().getNumberTaxas()==0)
+			return sorry(getName() + " couldn't start because no blocks of taxa are available.");
+		//listSubmenu = addSubmenu(null, "Taxa", makeCommand("setTaxaInt",  this), getProject().getTaxas());
+		return true;
+	}
+	public void resetCurrentTaxa(Taxa taxa){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		currentTaxa = taxa;
+		if (currentTaxa!=null)
+			currentTaxa.addListener(this);
+	}
+	public void initialize(Taxa taxa){
+		if (taxa !=currentTaxa || currentTaxa == null)
+			resetCurrentTaxa(taxa);
+	}
+	public Selectionable getSelectionable(){
+		return currentTaxa;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(currentTaxa)); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		/*
+disabled in 1. 06 because wasn't working (too many functions made early commitment to taxa which couldn't be changed
+    	 	if (checker.compare(this.getClass(), "Sets which block of taxa to use (0 based, for internal use)", "[block number]", commandName, "setTaxaInt")) { //need separate from setTreeBlock since this is used internally with 0-based menu response
+    	 		int whichList = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (MesquiteInteger.isCombinable(whichList)) {
+	    	 		if (currentTaxa!=null)
+	    	 			currentTaxa.removeListener(this);
+	    	 		currentTaxa = getProject().getTaxa(checker.getFile(), whichList);
+	    	 		if (currentTaxa!=null)
+	    	 			currentTaxa.addListener(this);
+	    	 		parametersChanged();
+	 			return currentTaxa;
+ 			}
+    	 	}
+    	 	else */
+		if (checker.compare(this.getClass(), "Sets which block of taxa to use", "[block reference, number, or name]", commandName, "setTaxa")) {
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				resetCurrentTaxa(t);
+				parametersChanged();
+				return currentTaxa;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void endJob(){
+		if (currentTaxa !=null)
+			currentTaxa.removeListener(this);
+		super.endJob();
+	}
+	/** passes which object changed, along with optional integer (e.g. for character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (!doomed && obj==currentTaxa && !(code == MesquiteListener.SELECTION_CHANGED || code == MesquiteListener.ANNOTATION_CHANGED || code == MesquiteListener.ANNOTATION_ADDED || code == MesquiteListener.ANNOTATION_DELETED))
+			parametersChanged(notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)currentTaxa == obj)
+			iQuit();
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	boolean first = true;
+
+
+	/*.................................................................................................................*/
+	public Taxon getCurrentTaxon(Taxa taxa) {
+		if (taxa==null)
+			return null;
+		if (taxa !=currentTaxa || taxa == null){
+			resetCurrentTaxa(taxa);
+		}
+		if (currentTaxon<0 || currentTaxon>taxa.getNumTaxa())
+			return null;
+		return taxa.getTaxon(currentTaxon);
+	}
+	/*.................................................................................................................*/
+	public Taxon getFirstTaxon(Taxa taxa) {
+		currentTaxon=0;
+		return getCurrentTaxon(taxa);
+	}
+	/*.................................................................................................................*/
+	public Taxon getTaxon(Taxa taxa, int iTaxon) {
+		currentTaxon=iTaxon;
+		return getCurrentTaxon(taxa);
+	}
+	/*.................................................................................................................*/
+	public Taxon getNextTaxon(Taxa taxa) {
+		currentTaxon++;
+		return getCurrentTaxon(taxa);
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTaxa(Taxa taxa) {
+		if (taxa==null)
+			return 0;
+		else
+			return taxa.getNumTaxa();
+	}
+
+	/*.................................................................................................................*/
+	public String getTaxonName(Taxa taxa, int iTaxon) {
+		if (taxa==null)
+			return null;
+		else {
+			return taxa.getTaxonName(iTaxon);
+		}
+	}
+}
+
diff --git a/Source/mesquite/minimal/Utilities/Utilities.java b/Source/mesquite/minimal/Utilities/Utilities.java
new file mode 100644
index 0000000..2b5d43a
--- /dev/null
+++ b/Source/mesquite/minimal/Utilities/Utilities.java
@@ -0,0 +1,48 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.minimal.Utilities;
+/*~~  */
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class Utilities extends MesquiteInit  {
+	public String getName() {
+		return "Utilities";
+	}
+	public String getExplanation() {
+		return "Provides a menu for utilities";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(UtilitiesAssistant.class, "Utilities assistant modules perform various tasks.",
+		"These are activated automatically. ");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("Utilities");
+		hireAllEmployees(UtilitiesAssistant.class);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Respond to commands sent to the window. */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		return  super.doCommand(commandName, arguments, checker);
+	}
+}
+
diff --git a/Source/mesquite/minimal/WindowBabysitter/WindowBabysitter.java b/Source/mesquite/minimal/WindowBabysitter/WindowBabysitter.java
new file mode 100644
index 0000000..d1e6ad8
--- /dev/null
+++ b/Source/mesquite/minimal/WindowBabysitter/WindowBabysitter.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)*/
+package mesquite.minimal.WindowBabysitter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class WindowBabysitter extends WindowHolder {
+	public String getName() {
+		return "Window Holder";
+	}
+	public String getExplanation() {
+		return "Helps other modules by holding their windows." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true; 
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (getModuleWindow() == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(getModuleWindow().getSnapshot(file), true);
+		temp.addLine("endTell");
+		temp.addLine("showWindow");
+		return temp;
+	}
+
+
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+}
+
diff --git a/Source/mesquite/minimal/explanation.txt b/Source/mesquite/minimal/explanation.txt
new file mode 100644
index 0000000..5e13106
--- /dev/null
+++ b/Source/mesquite/minimal/explanation.txt
@@ -0,0 +1,2 @@
+Fundamental Modules
+The core Mesquite package; it must be loaded if Mesquite is to work.  
diff --git a/Source/mesquite/molec/AAHydrophobicity/AAHydrophobicity.java b/Source/mesquite/molec/AAHydrophobicity/AAHydrophobicity.java
new file mode 100644
index 0000000..4c00078
--- /dev/null
+++ b/Source/mesquite/molec/AAHydrophobicity/AAHydrophobicity.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.AAHydrophobicity; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+
+/* ======================================================================== */
+public class AAHydrophobicity extends AAProperty {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public void initialize(CharacterData data){
+	}
+	
+	//symbols = new char[] {		'A',  		'C', 	'D', 		'E', 		'F', 		'G', 		'H', 		'I', 		'K', 		'L', 		'M', 		'N', 		'P', 		'Q', 		'R', 		'S', 		'T', 		'V', 		'W', 		'Y', 		'*'};
+	double[] kyteDoolittle = new double[] {1.8,	2.5,	-3.5,	 -3.5, 	+2.8, 	-0.4, 	-3.2, 	+4.5, 	-3.9,	 +3.8, 	+1.9, 	-3.5,	-1.6,	-3.5,	-4.5,	-0.8,	-0.7,	+4.2,	-0.9,	-1.3};
+	//Kyte J and Doolittle RF Journal of Molecular Biology 157(6): 105-142, 1982
+
+	//http://blanco.biomol.uci.edu/hydrophobicity_scales.html  white octanol scale
+	
+	double[] hydrophobs = kyteDoolittle;
+
+	public double getProperty(int aa){
+
+		if (aa>=0 && aa<hydrophobs.length)
+			return hydrophobs[aa];
+		return MesquiteDouble.unassigned;
+   	 }
+
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Kyte & Doolittle Hydrophobicity";
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Returns hydrophobicity of amino acid using the scale of Kyte, J & R.F. Doolittle (1982) J. Mol. Biol. 157:105-142.  Numbers from http://www.whatislife.com/reader/protein/aa.html";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/AASize/AASize.java b/Source/mesquite/molec/AASize/AASize.java
new file mode 100644
index 0000000..b34a5da
--- /dev/null
+++ b/Source/mesquite/molec/AASize/AASize.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.AASize; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+
+/* ======================================================================== */
+public class AASize extends AAProperty {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+
+	//symbols = new char[] {		'A', 	'C', 	'D', 		'E', 		'F', 		'G', 		'H', 		'I', 		'K', 		'L', 		'M', 		'N', 		'P', 		'Q', 		'R', 		'S', 		'T', 		'V', 		'W', 		'Y', 		'*'};
+	double[] weights = new double[] {	89.1,	121.16,	133.11,	147.13,	165.19,	75.01, 	155.16, 	131.18, 	146.19,	 131.18, 	149.21, 	132.12,	151.13,	128.10,	174.2,	105.10,	119.12,	117.15,	204.23,	181.19};
+	//numbers from web page http://www.whatislife.com/reader/protein/aa.html which cites Kite & Doolittle, 1982
+	
+	
+	public double getProperty(int aa){
+		if (aa>=0 && aa<weights.length)
+			return weights[aa];
+		return MesquiteDouble.unassigned;
+   	 }
+
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Amino Acid Molecular Weight";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Returns molecular weight of amino acid";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/AminoAcidProperties/AminoAcidProperties.java b/Source/mesquite/molec/AminoAcidProperties/AminoAcidProperties.java
new file mode 100644
index 0000000..a647c77
--- /dev/null
+++ b/Source/mesquite/molec/AminoAcidProperties/AminoAcidProperties.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.AminoAcidProperties; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+
+/* ======================================================================== */
+public class AminoAcidProperties extends NumberForCharAndTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(AAProperty.class, getName() + "  needs to choose a particular amino acid property to report.",
+		"The amino acid property to report can be selected initially or in the Amino Acid Property submenu");
+	}
+	/*.................................................................................................................*/
+	AAProperty propertyTask;
+	MesquiteString propertyTaskName;
+	static String ptName = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+ 		if (!StringUtil.blank(ptName)) //remember last one used
+			propertyTask = (AAProperty)hireNamedEmployee(AAProperty.class, ptName);
+		if (propertyTask == null)
+			propertyTask = (AAProperty)hireEmployee(AAProperty.class, "Property of Amino Acid");
+		if (propertyTask == null)
+			return sorry(getName() + " couldn't start because no properties module was obtained.");
+ 		propertyTaskName = new MesquiteString();
+ 		ptName = "#" +propertyTask.getShortClassName();
+		if (numCompatibleModulesAvailable(AAProperty.class, condition, this)>0) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Amino Acid Property", makeCommand("setProperty", this), AAProperty.class);
+ 			mss.setSelected(propertyTaskName);
+		}
+		return true;
+	}
+	public void initialize(CharacterData data){
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setProperty ", propertyTask); 
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the module calculating the property", "[name of module]", commandName, "setProperty")) {
+    	 		AAProperty temp =   (AAProperty)replaceEmployee(AAProperty.class, arguments, "Property of Amino Acid", propertyTask);
+ 			if (temp!=null) {
+ 				propertyTask = temp;
+				propertyTaskName.setValue(propertyTask.getName());
+ 				ptName = "#" +propertyTask.getShortClassName();
+				parametersChanged();
+	 			return propertyTask;
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+    	 
+
+	public void calculateNumber(CharacterData data, int ic, int it, MesquiteNumber result, MesquiteString resultString){
+   	 	if (result == null || propertyTask == null)
+   	 		return;
+	   	clearResultAndLastResult(result);
+  	 	if (data == null || !(data instanceof ProteinData))
+   	 		return;
+   	 	CategoricalData dData = (CategoricalData)data;
+		long s = dData.getState(ic, it);
+
+		double loc = 0;
+		int ns = 0;
+		for (int is=0; is<=ProteinState.maxProteinState; is++){
+			if (CategoricalState.isElement(s, is)) {
+				double d = propertyTask.getProperty(is);
+				if (MesquiteDouble.isCombinable(d)){
+					loc += d;
+					ns++;
+				}
+			}
+		}
+		if (ns!=0)
+			result.setValue(loc/ns);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+  	 }
+
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Amino Acid Properties";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Returns property of amino acid";
+   	 }
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresProteinData();
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/AssignGeneticCode/AssignGeneticCode.java b/Source/mesquite/molec/AssignGeneticCode/AssignGeneticCode.java
new file mode 100644
index 0000000..ab26b44
--- /dev/null
+++ b/Source/mesquite/molec/AssignGeneticCode/AssignGeneticCode.java
@@ -0,0 +1,106 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.AssignGeneticCode; 
+
+import java.io.*;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class AssignGeneticCode extends DataWindowAssistantI {
+	MesquiteTable table;
+	CharacterData data;
+	//MesquiteSubmenuSpec mss= null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Genetic Code...", makeCommand("showListWithCode",  this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	private void showList(CharacterData data){
+		if (data == null && !(data instanceof DNAData))
+			return;
+		CharactersManager manageCharacters = (CharactersManager)findElementManager(CharacterData.class);
+
+	if (manageCharacters == null)
+		return;
+		MesquiteModule list = manageCharacters.getListOfCharactersModule(data, true);
+		if (list == null) 
+			return;
+		//here ask each list imployee if they have genetic codes shown; otherwise finish script
+		EmployeeVector e = list.getEmployeeVector();
+		if (e != null){
+			for (int i = 0; i< e.size(); i++)
+				if (e.elementAt(i) instanceof mesquite.molec.CharListGenCodeModels.CharListGenCodeModels) //is being shown
+					return;
+		}
+		Puppeteer p = new Puppeteer(this);
+		MesquiteInteger pos = new MesquiteInteger(0);
+
+		String commands =  "getWindow; tell It; newAssistant  #mesquite.molec.CharListGenCodeModels.CharListGenCodeModels; endTell;";
+
+		pos.setValue(0);
+		p.execute(list, commands, pos, "", false);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Shows the genetic code assignments", null, commandName, "showListWithCode")) {
+			if (table!=null && data !=null){
+				showList(data);
+			}
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Show List with Genetic Codes";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows the List of Character window with the genetic codes column on." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/AvgSequenceLengthMatrix/AvgSequenceLengthMatrix.java b/Source/mesquite/molec/AvgSequenceLengthMatrix/AvgSequenceLengthMatrix.java
new file mode 100644
index 0000000..536c28e
--- /dev/null
+++ b/Source/mesquite/molec/AvgSequenceLengthMatrix/AvgSequenceLengthMatrix.java
@@ -0,0 +1,75 @@
+package mesquite.molec.AvgSequenceLengthMatrix;
+
+
+
+import mesquite.categ.lib.MolecularData;
+import mesquite.categ.lib.RequiresAnyMolecularData;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class AvgSequenceLengthMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+
+		CharacterData parentData = data.getParentData();
+		if (parentData == null){
+			if (resultString != null)
+				resultString.setValue("Average sequence length can be calculated only for stored matrices");
+			return;
+		}
+		if (!(parentData instanceof MolecularData)){
+			if (resultString != null)
+				resultString.setValue("Average sequence length can be calculated only for molecular matrices");
+			return;
+		}
+		int numTaxa = parentData.getNumTaxa();
+		int numChars = parentData.getNumChars();
+		
+		int count = 0;
+		for (int it=0; it<numTaxa; it++)
+			for (int ic=0; ic<numChars; ic++)
+				if (!parentData.isInapplicable(ic,  it))
+					count ++;
+		
+		if (count>0) {
+			result.setValue(count*1.0/numTaxa); 
+		}  else
+			result.setValue(0.0); 
+
+		if (resultString!=null) {
+			resultString.setValue("Average sequence length: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	public boolean isPrerelease (){
+		return false;
+	}
+
+	public String getName() {
+		return "Average Sequence Length in Matrix";
+	} 
+
+	public String getExplanation(){
+		return "Calculates the average sequence length (non-gaps) in the matrix.";
+	} 
+
+} 
diff --git a/Source/mesquite/molec/BLASTSearch/BLASTSearch.java b/Source/mesquite/molec/BLASTSearch/BLASTSearch.java
new file mode 100644
index 0000000..533c398
--- /dev/null
+++ b/Source/mesquite/molec/BLASTSearch/BLASTSearch.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.BLASTSearch; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class BLASTSearch extends CategDataSearcher { 
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	/** Called to search on the data in selected cells.  Returns true if data searched*/
+   	public boolean searchData(CharacterData data, MesquiteTable table){
+		this.data = data;
+		if (!(data instanceof DNAData || data instanceof ProteinData)){
+			discreetAlert( "Only DNA or protein data can be searched using this module.");
+			return false;
+		}
+		return searchSelectedTaxa(data,table);
+	}
+	/*.................................................................................................................*/
+   	public boolean searchOneTaxon(CharacterData data, int it, int icStart, int icEnd){
+   		if (data==null)
+   			return false;
+   		String firstLine = data.getTaxa().getTaxonName(it);
+   		if (!StringUtil.blank(firstLine))
+   			firstLine ="%3E" + StringUtil.encodeForURL(firstLine) + "%0D%0A";  //to make it a FASTA format
+   		else
+   			firstLine ="%3Etaxon " + it + "%0D%0A";  //to make it a FASTA format
+   		StringBuffer searchBuffer = new StringBuffer(data.getNumChars());
+   		for (int ic = icStart; ic<=icEnd; ic++) {
+   			data.statesIntoStringBuffer(ic, it, searchBuffer, false, false, false);
+   		}
+   		String seq = searchBuffer.toString();
+   		if (MesquiteTrunk.debugMode){
+   			logln("BLAST query sequence ("+ data.getTaxa().getTaxonName(it)+"):");
+   			logln(seq);
+   		}
+		if (!StringUtil.blank(seq) && (seq.length()>2)) {
+			String url = "http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?"+ NCBIUtil.getMesquiteGenBankURLMarker();
+			url += "&DATABASE=nr&FORMAT_TYPE=HTML";
+			if (data instanceof ProteinData) 
+				url += "&PROGRAM=blastp";
+			else
+				url += "&PROGRAM=blastn";
+			url += "&CLIENT=web&SERVICE=plain&PAGE=Nucleotides&CMD=Put&QUERY=";
+			MesquiteModule.showWebPage(url + firstLine+ seq, true);
+			return true;
+		}
+		else 
+			discreetAlert( "Sorry, to use the BLAST search you need to have one or more stretches of sequence selected.");
+		return false;
+
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "BLAST in Web Browser";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "BLASTs selected data against GenBank.";
+   	 }
+ 	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+}
+
+/*
+Search string into Genbank Entrez:
+
+http://www.ncbi.nlm.nih.gov:80/entrez/query.fcgi?cmd=Search&db=nucleotide&dopt=GenBank&term=Bembidion
+
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?DATABASE=nr&FORMAT_TYPE=HTML&PROGRAM=blastn&CLIENT=web&SERVICE=plain&PAGE=Nucleotides&CMD=Put&QUERY= 
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?DATABASE=nr&HITLIST_SIZE=10&FILTER=L&EXPECT=10&FORMAT_TYPE=HTML&PROGRAM=blastn&CLIENT=web&SERVICE=plain&NCBI_GI=on&PAGE=Nucleotides&CMD=Put&QUERY= 
+
+
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?CMD=put&PAGE=Nucleotides&program=blast&QUERY_FILE=fasta&query="CCAAGTCCTTCTTGAAGGGGGCCATTTACCCATAGAGGGTGCCAGGCCCGTAGTGACCATTTATATATTTGGGTGAGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATGACTGCGAAACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACTGTTCAGGGGTAAACCTGTGGTGCCCGAAAGTTCGAAGGGGGAGATTC"
+
+*/
+	
+
+
diff --git a/Source/mesquite/molec/CGBiasOfTaxon/CGBiasOfTaxon.java b/Source/mesquite/molec/CGBiasOfTaxon/CGBiasOfTaxon.java
new file mode 100644
index 0000000..bf365f4
--- /dev/null
+++ b/Source/mesquite/molec/CGBiasOfTaxon/CGBiasOfTaxon.java
@@ -0,0 +1,160 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.CGBiasOfTaxon;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.EmployeeNeed;
+import mesquite.lib.MesquiteDouble;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteNumber;
+import mesquite.lib.MesquiteString;
+import mesquite.lib.Notification;
+import mesquite.lib.Taxa;
+import mesquite.lib.Taxon;
+import mesquite.lib.characters.CharInclusionSet;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.CharacterState;
+import mesquite.lib.characters.MCharactersDistribution;
+import mesquite.lib.duties.MatrixSourceCoord;
+import mesquite.lib.duties.NumberForTaxon;
+
+public class CGBiasOfTaxon extends NumberForTaxon {
+	long A = CategoricalState.makeSet(0);
+	long C = CategoricalState.makeSet(1);
+	long G = CategoricalState.makeSet(2);
+	long T = CategoricalState.makeSet(3);
+	long AT = A | T;
+	long CG =  C | G;
+	long ACGT = A | C | G | T;
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, DNAState.class, "DNA Matrix on which to calculate compositional bias"); //TODO: allow resetting of source (e.g., to simulation)
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean loadModule(){
+		return false;  
+	}
+
+	
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		DNAData data = (DNAData)observedStates.getParentData();
+		CharInclusionSet inclusion = null;
+		if (data !=null)
+			inclusion = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		int tot = 0;
+		int count = 0;
+		double value = 0.0;
+		if (numChars != 0) {
+			for (int ic = 0; ic<data.getNumChars(); ic++) {
+				if (inclusion == null || inclusion.isBitOn(ic)){
+					long s = data.getState(ic,it);
+					if (!CategoricalState.isUnassigned(s) && !CategoricalState.isInapplicable(s)) {
+							if (s == A || s == T || s == AT) //monomorphic A or T or A&T or uncertain A or T
+								tot++;
+							else if (s == C || s == G || s == CG) { //monomorphic C or G or C&G or uncertain C or G
+								tot++;
+								count++;
+							}
+						
+					}
+				} else
+					charExc++;
+			}
+			if (tot == 0)
+				value = MesquiteDouble.unassigned; //changed from 0,  26 jan '14
+			else
+				value = ((double)count)/tot;
+			result.setValue(value);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+
+		
+		if (resultString!=null)
+			resultString.setValue("Proportion of CG in taxon "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion CG in taxon";  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return true;
+	}
+	public String getParameters() {
+		return "Proportion CG in taxon in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the proportion of CG in a taxon for a DNA matrix." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/CharListGenCodeModels/CharListGenCodeModels.java b/Source/mesquite/molec/CharListGenCodeModels/CharListGenCodeModels.java
new file mode 100644
index 0000000..e0ab5aa
--- /dev/null
+++ b/Source/mesquite/molec/CharListGenCodeModels/CharListGenCodeModels.java
@@ -0,0 +1,262 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.CharListGenCodeModels;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import mesquite.molec.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CharListGenCodeModels extends CharListAssistant {
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine, mLine2;
+	MesquiteSubmenuSpec webPageSubmenu, toStringSubmenu;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof GenCodeModel) {
+			parametersChanged();
+		}
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the genetic code of the selected characters", "[number of model]", commandName, "setModel")) {
+			if (table !=null && data!=null) {
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()), whichModel);
+				/*
+				 *  				String genCodeName = parser.getFirstToken(arguments);
+  				genCodeName = parser.getNextToken();
+  				 CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()), genCodeName);
+				 */
+				if (model != null) {
+					ModelSet modelSet = (ModelSet) data.getCurrentSpecsSet(GenCodeModelSet.class);
+					if (modelSet == null) {
+						CharacterModel defaultModel =  data.getDefaultModel("GeneticCode");
+						modelSet= new GenCodeModelSet("Genetic Code Model Set", data.getNumChars(), defaultModel, data);
+						modelSet.addToFile(data.getFile(), getProject(), findElementManager(GenCodeModelSet.class)); 
+						data.setCurrentSpecsSet(modelSet, GenCodeModelSet.class);
+					}
+					if (modelSet != null) {
+						if (employer!=null && employer instanceof ListModule) {
+							int c = ((ListModule)employer).getMyColumn(this);
+							for (int i=0; i<data.getNumChars(); i++) {
+								if (table.isCellSelectedAnyWay(c, i)) {
+									modelSet.setModel(model, i);
+									if (!changed)
+										outputInvalid();
+
+									changed = true;
+								}
+							}
+						}
+					}
+				}
+
+				if (changed)
+					data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				//TODO: not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Stores current genetic code model set (CODESET)", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(GenCodeModelSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CharacterModel defaultModel =  data.getDefaultModel("GeneticCode");
+					ModelSet modelSet= new GenCodeModelSet("Genetic Code Set", data.getNumChars(), defaultModel, data);
+					modelSet.addToFile(data.getFile(), getProject(), findElementManager(GenCodeModelSet.class)); 
+					data.setCurrentSpecsSet(modelSet, GenCodeModelSet.class);
+					ssv = data.getSpecSetsVector(GenCodeModelSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(GenCodeModelSet.class));
+					s.setName(ssv.getUniqueName("Genetic Code Set"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of genetic code set to be stored", "Genetic Code Set");
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replace stored genetic code set (CODESET) by the current one", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(GenCodeModelSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored genetic code set to replace by current set", MesquiteString.helpString, ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored genetic code set to be the current one", "[number of genetic code set to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(GenCodeModelSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Displays the NCBI page for the genetic code", "", commandName, "showNCBIPage")) {
+			boolean changed=false;
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(whichModel))
+				return null;
+			CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()), whichModel);
+			if (model != null) {
+				GeneticCode theCode = ((GenCodeModel)model).getGeneticCode();
+				if (theCode!=null)
+					theCode.showNCBIPage();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Displays the genetic code in the log window", "", commandName, "showCodeInLog")) {
+			boolean changed=false;
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(whichModel))
+				return null;
+			CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()), whichModel);
+			if (model != null) {
+				GeneticCode theCode = ((GenCodeModel)model).getGeneticCode();
+
+				if (theCode!=null) {
+					String s = theCode.toNCBIString();
+					log(s);
+				}
+			}
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		/* hire employees here */
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mLine2);
+		deleteMenuItem(mStc);
+		deleteMenuItem(webPageSubmenu);
+		deleteMenuItem(toStringSubmenu);
+		mss = addSubmenu(null, "Genetic Code", makeCommand("setModel", this), getProject().getCharacterModels());
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current set...", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current...", makeCommand("replaceWithCurrent",  this));
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load genetic code set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(GenCodeModelSet.class));
+		mLine2 = addMenuItem("-",null);
+		webPageSubmenu = addSubmenu(null, "Show NCBI Web Page", makeCommand("showNCBIPage", this), getProject().getCharacterModels());
+		webPageSubmenu.setCompatibilityCheck(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()));
+		toStringSubmenu = addSubmenu(null, "List Code in Log Window", makeCommand("showCodeInLog", this), getProject().getCharacterModels());
+		toStringSubmenu.setCompatibilityCheck(new ModelCompatibilityInfo(GenCodeModel.class, data.getStateClass()));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Genetic Code";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(GenCodeModelSet.class);
+			if (modelSet != null) {
+				CharacterModel model = modelSet.getModel(ic);
+				if (model!=null) {
+					return model.getName();
+				}
+			}
+			else
+				MesquiteMessage.warnProgrammer("model set null in gsfc");
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "Invertebrate Mitochondrial ";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Current Genetic Codes ";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows current genetic codes applied to characters in character list window." ;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+}
+
diff --git a/Source/mesquite/molec/CharacterGCBias/CharacterGCBias.java b/Source/mesquite/molec/CharacterGCBias/CharacterGCBias.java
new file mode 100644
index 0000000..460a51d
--- /dev/null
+++ b/Source/mesquite/molec/CharacterGCBias/CharacterGCBias.java
@@ -0,0 +1,174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.CharacterGCBias;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CharacterGCBias extends NumberForCharacter implements NumForCharTreeIndep {
+	double resultNum;
+	boolean wrongType = false;
+	boolean first = true;
+	long A = CategoricalState.makeSet(0);
+	long C = CategoricalState.makeSet(1);
+	long G = CategoricalState.makeSet(2);
+	long T = CategoricalState.makeSet(3);
+	long AT = A | T;
+	long CG =  C | G;
+	long ACGT = AT | CG;
+	int whatFreq = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		ListableVector f  = new ListableVector();
+		f.addElement(new MesquiteString("GC Bias"), false);
+		f.addElement(new MesquiteString("A Frequency"), false);
+		f.addElement(new MesquiteString("C Frequency"), false);
+		f.addElement(new MesquiteString("G Frequency"), false);
+		f.addElement(new MesquiteString("T Frequency"), false);
+		addSubmenu(null, "Frequency Calculated", makeCommand("setMode", this), f);
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setMode " + whatFreq);  //TODO: note not snapshotting tree task
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+   	 	if (checker.compare(this.getClass(), "Sets what frequency is calculated", "[GC = 0, A = 1, C = 2, G = 3, T = 4]", commandName, "setMode")) {
+    	 		int w = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (w>=0 && w<=4) {
+    	 			whatFreq = w;
+    	 			if (!MesquiteThread.isScripting())
+    	 				parametersChanged();
+    	 		}
+    	 	}
+      	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+   
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+
+   	}
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new RequiresAnyDNAData();
+  	 }
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		int numT = charStates.getNumTaxa();
+		wrongType = !(DNAState.class.isAssignableFrom(charStates.getStateClass()));
+		if (wrongType) {
+			if (first)
+				alert("Error: non DNA-character in CharacterGCBias.  Unable to calculate the Compositional Bias.");
+			first = false;
+			return;
+		}
+		int total=0;
+		int count=0;
+		CategoricalDistribution dna = (CategoricalDistribution)charStates;
+		for (int it = 0; it<numT; it++) {
+			if (!charStates.isUnassigned(it) && !charStates.isInapplicable(it)) {
+				long s = dna.getState(it);
+				if (!CategoricalState.isUnassigned(s) && !CategoricalState.isInapplicable(s)) {
+					if (whatFreq == 0){ //CG bias; counts only if clearly a C/G versus A/T;  polymorphisms mixing A & G, C & G, A & T, C & T are not counted
+						if (s == A || s == T || s == AT) //monomorphic A or T or A&T or uncertain A or T
+							total++;
+						else if (s == C || s == G || s == CG) { //monomorphic C or G or C&G or uncertain C or G
+							total++;
+							count++;
+						}
+					}
+					else if (!CategoricalState.isUncertain(s) && (s & ACGT) != 0L){ //individual base frequency; counts only if monomorphic or polymorphic, not uncertain
+						total++;
+						if (whatFreq == 1 && ((A & s) != 0L)){ //A
+							count++;
+						}
+						else if (whatFreq == 2  && ((C & s) != 0L)){ //C
+							count++;
+						}
+						else if (whatFreq == 3  && ((G & s) != 0L)){ //G
+							count++;
+						}
+						else if (whatFreq == 4 && ((T & s) != 0L)){ //T
+							count++;
+						}
+					}
+				}
+			}
+		}
+		if (total == 0)
+			resultNum = MesquiteDouble.unassigned; //changed from 0,  26 jan '14
+		else
+			resultNum = 100.000*count/total;
+		if (wrongType)
+			result.setToUnassigned();
+		else
+			result.setValue(resultNum);
+			
+		if (resultString!=null)
+			resultString.setValue(getParameters() + ": "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		if (whatFreq == 0)
+ 			return "GC Bias";
+ 		else if (whatFreq == 1)
+ 			return "Frequency of A";
+ 		else if (whatFreq == 2)
+ 			return "Frequency of C";
+ 		else if (whatFreq == 3)
+ 			return "Frequency of G";
+ 		else if (whatFreq == 4)
+ 			return "Frequency of T";
+   		return null;  
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Compositional Bias";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the percent of taxa with particular nucleotides (GC bias, or individual frequency of A, C, G or T) for a character." ;
+   	 }
+}
+
diff --git a/Source/mesquite/molec/CleanUpMatrix/CleanUpMatrix.java b/Source/mesquite/molec/CleanUpMatrix/CleanUpMatrix.java
new file mode 100644
index 0000000..53917af
--- /dev/null
+++ b/Source/mesquite/molec/CleanUpMatrix/CleanUpMatrix.java
@@ -0,0 +1,185 @@
+package mesquite.molec.CleanUpMatrix;
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+import mesquite.align.lib.*;
+
+
+/*  Authors: David Maddison, Wayne Maddison
+ * 
+ * TODO:
+ * 	- store preferences?
+ *  
+ */
+/* ======================================================================== */
+public class CleanUpMatrix extends CategDataAlterer {
+	boolean reverseComplementIfNecessary = true;
+	boolean multipleSequenceAlignment = true;
+	int referenceSequence = 1;
+	boolean setCodonPositions = false;
+	CategDataAlterer aligner = null;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("matchFraction".equalsIgnoreCase(tag)) {
+			matchFraction = MesquiteDouble.fromString(content);
+		}
+	
+		preferencesSet = true;
+}
+/*.................................................................................................................*
+public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "matchFraction", matchFraction);  
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions(int numTaxa) {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Clean Up Matrix Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		queryDialog.addLabel("Clean Up Matrix Options");
+		
+		Checkbox reverseComplementBox = queryDialog.addCheckBox("reverse complement if necessary", reverseComplementIfNecessary);
+		RadioButtons alignRadios = queryDialog.addRadioButtons(new String[] {"multiple sequence alignment", "shift to match chosen sequence"}, 0);
+		IntegerField shiftToMatchField =  queryDialog.addIntegerField ("Reference sequence", 1, 4, 1, numTaxa);
+		Checkbox setCodPosBox = queryDialog.addCheckBox("set codon positions to minimize stop codons", setCodonPositions);
+
+		queryDialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			reverseComplementIfNecessary = reverseComplementBox.getState();
+			multipleSequenceAlignment = alignRadios.getValue()==0;
+			if (!multipleSequenceAlignment){
+				referenceSequence = shiftToMatchField.getValue()-1;
+				if (referenceSequence<0)
+					referenceSequence=0;
+			}
+			setCodonPositions = setCodPosBox.getState();
+			storePreferences();
+		}
+		queryDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public boolean isReverseComplementIfNecessary() {
+		return reverseComplementIfNecessary;
+	}
+	public void setReverseComplementIfNecessary(boolean reverseComplementIfNecessary) {
+		this.reverseComplementIfNecessary = reverseComplementIfNecessary;
+	}
+	public boolean isMultipleSequenceAlignment() {
+		return multipleSequenceAlignment;
+	}
+	public void setMultipleSequenceAlignment(boolean multipleSequenceAlignment) {
+		this.multipleSequenceAlignment = multipleSequenceAlignment;
+	}
+	public int getReferenceSequence() {
+		return referenceSequence;
+	}
+	public void setReferenceSequence(int referenceSequence) {
+		this.referenceSequence = referenceSequence;
+	}
+	public boolean isSetCodonPositions() {
+		return setCodonPositions;
+	}
+	public void setSetCodonPositions(boolean setCodonPositions) {
+		this.setCodonPositions = setCodonPositions;
+	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData data, int ic, int it){
+   	}
+	/*.................................................................................................................*/
+   	private void processData(DNAData data, Taxa taxa) {
+   		if (reverseComplementIfNecessary)
+  			MolecularDataUtil.reverseComplementSequencesIfNecessary(data, module, taxa, 0, taxa.getNumTaxa(), referenceSequence, false, false, false);
+   		if (multipleSequenceAlignment){
+   			if (aligner==null)
+   				aligner= (CategDataAlterer)hireNamedEmployee(CategDataAlterer.class, "#MultipleAlignService");
+   			if (aligner!=null)
+   				aligner.alterData(data, null,  null);
+   		} else
+   			MolecularDataUtil.pairwiseAlignMatrix(this, data, referenceSequence, false);
+   		if (setCodonPositions){
+   			MolecularDataUtil.setCodonPositionsToMinimizeStops(data, module, taxa, 0, taxa.getNumTaxa());
+   		}
+   		// then alter taxon names
+   		//open character matrix
+   		// color by amino acid if protein coding
+
+	}
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table,  UndoReference undoReference){
+		if (data==null)
+			return false;
+		if (okToInteractWithUser(CAN_PROCEED_ANYWAY, "Querying about options")){ //need to check if can proceed
+   			if (!queryOptions(data.getNumTaxa()))
+   				return false;
+		}
+
+		if (!(data instanceof DNAData))
+			return false;
+	//	try{
+		processData((DNAData)data,data.getTaxa());
+//		}
+//		catch (ArrayIndexOutOfBoundsException e){
+//			return false;
+//		}
+		return true;
+   	}
+   	
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	   /*.................................................................................................................*/
+   	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+   	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+   	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+      	public int getVersionOfFirstRelease(){
+      		return 300;  
+    }
+    	/*.................................................................................................................*/
+   	 public String getName() {
+		return "Clean Up Matrix";
+  	 }
+ 	/*.................................................................................................................*/
+	 public String getNameForMenuItem() {
+	return "Clean Up Matrix...";
+	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "This will adjust sequences according to the option chosen (e.g., by reverse complementing, aligning the matrix, and then adjusting the codon postions)." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/CodesetList/CodesetList.java b/Source/mesquite/molec/CodesetList/CodesetList.java
new file mode 100644
index 0000000..a84e1d0
--- /dev/null
+++ b/Source/mesquite/molec/CodesetList/CodesetList.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.CodesetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class CodesetList extends DataSpecssetList {
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Genetic Code Set...", makeCommand("newCodeset",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	public Class getItemType(){
+		return GenCodeModelSet.class;
+	}
+	public String getItemTypeName(){
+		return "Genetic code set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Genetic code sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new GenCodeModelSet("Genetic Code Set", data.getNumChars(),data.getDefaultModel("GeneticCode"), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new genetic code set (CODESET)", null, commandName, "newCodeset")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Model Set", "To make a new genetic code set, go to the List of Characters window, make sure that a column for Current Genetic Code appears, edit the column, then save the model set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListGenCodeModels", checker);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "List of Genetic Code Sets";
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Makes windows listing genetic code sets." ;
+	}
+	/*.................................................................................................................*/
+
+
+
+
+}
+
+
diff --git a/Source/mesquite/molec/CollapseEdges/CollapseEdges.java b/Source/mesquite/molec/CollapseEdges/CollapseEdges.java
new file mode 100644
index 0000000..dd08e6f
--- /dev/null
+++ b/Source/mesquite/molec/CollapseEdges/CollapseEdges.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.CollapseEdges;
+/*~~  */
+
+import java.util.*;
+import java.lang.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class CollapseEdges extends MolecularDataAlterer {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*
+   	public void alterCell(CharacterData cData, int ic, int it){
+   		if (cData instanceof CategoricalData) { //this does not do state names recoding!
+   		}
+   	}
+   	
+	/*.................................................................................................................*/
+   	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData cData, MesquiteTable table,  UndoReference undoReference){
+		if (!(cData instanceof MolecularData))
+			return false;
+		MolecularData data = (MolecularData)cData;
+		data.stripRightTerminalGaps(false);
+		data.stripLeftTerminalGaps(false);
+		return true;
+   	}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Trim Terminal Gap Characters";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Trim Terminal Gap Characters";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Trims characters at edges of matrix that are gaps only." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/ColorByAA/ColorByAA.java b/Source/mesquite/molec/ColorByAA/ColorByAA.java
new file mode 100644
index 0000000..4c7a454
--- /dev/null
+++ b/Source/mesquite/molec/ColorByAA/ColorByAA.java
@@ -0,0 +1,194 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.ColorByAA; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorByAA extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	protected DNAData data;
+	MesquiteBoolean emphasizeDegeneracy;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		emphasizeDegeneracy = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Emphasize Less Degenerate Amino Acids", makeCommand("emphasizeDegeneracy", this), emphasizeDegeneracy);
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; //TODO: check success
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("emphasizeDegeneracy " + emphasizeDegeneracy.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Turns on or off the emphasizing of less degenerate codons.", null, commandName, "emphasizeDegeneracy")) {
+			emphasizeDegeneracy.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data instanceof DNAData)
+			this.data = (DNAData)data;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color By Amino Acid";
+	}
+	public String getNameForMenuItem() {
+		return "Color Nucleotide by Amino Acid";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors the cells of a DNA matrix by the amino acids for which they code.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+
+		if (!isActive())
+			return null;
+		if (ic<0 || it<0)
+			return "Cells colored to show translated amino acids";
+		if (data == null)
+			return null;
+		else if (!data.isCoding(ic)) {
+			return "Cells colored to show translated amino acids";
+		}
+		else {
+			long s = data.getAminoAcid(ic,it,true);
+			if (!CategoricalState.isImpossible(s)) {
+				String st = "Translated amino acid: " + ProteinState.toString(s, false) + " (followed by ";
+				MesquiteInteger nextCharacter = new MesquiteInteger(ic);
+				for (int i = 0; i<20; i++){
+					s = data.getNextAminoAcid(nextCharacter, it, true);
+					if (s!=CategoricalState.inapplicable)
+						st += ProteinState.toString(s, false);
+				}
+				return st + ")";
+			}
+			else {
+				return "Cells colored to show translated amino acids";
+			}
+		}
+	}
+	ColorRecord[] legend;
+	/*.................................................................................................................*/
+	public ColorRecord[] getLegendColors(){
+		if (data == null)
+			return null;
+		legend = new ColorRecord[ProteinState.maxProteinState+1];
+		Color color;
+		for (int is = 0; is<=ProteinState.maxProteinState; is++) {
+			 if (emphasizeDegeneracy.getValue()) {
+				 color = ProteinData.getProteinColorOfState(is);
+				 color = ((DNAData)data).alterColorToDeemphasizeDegeneracy(is,color);
+			 } else
+				 color = ProteinData.getProteinColorOfState(is);
+			 legend[is] = new ColorRecord(color, ProteinData.getStateLongName(is));
+		}
+
+		return legend;
+	}
+	/*.................................................................................................................*/
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		/*  		if (data.getClass() == CategoricalData.class){
+   			return "Colors of states may vary from character to character";
+   		}
+		 */
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public Color getCellColor(int ic, int it){
+
+		if (ic<0 || it<0)
+			return null;
+		if (data == null)
+			return null;
+		else if (!data.isCoding(ic)) {
+			Color color = data.getColorOfStates(ic, it);
+			//return color;
+			return ColorDistribution.brighter(color, 0.6);
+		}
+		else {
+			long s = data.getAminoAcid(ic,it,true);
+			if (!CategoricalState.isImpossible(s)) {
+				Color color;
+				 if (emphasizeDegeneracy.getValue()) {
+					 color = ProteinData.getAminoAcidColor(s, Color.white);
+					 color = ((DNAData)data).alterColorToDeemphasizeDegeneracy(ic,s,color);
+				 } else
+					 color = ProteinData.getAminoAcidColor(s, ProteinData.multistateColor);
+				return color;
+			}
+			else {
+				return data.getColorOfStates(ic, it);
+
+			}
+		}
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/molec/ColorByNumber/ColorByNumber.java b/Source/mesquite/molec/ColorByNumber/ColorByNumber.java
new file mode 100644
index 0000000..eb779a3
--- /dev/null
+++ b/Source/mesquite/molec/ColorByNumber/ColorByNumber.java
@@ -0,0 +1,340 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.ColorByNumber; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ColorByNumber extends DataWindowAssistantID implements CellColorer, CellColorerCharacters, CellColorerMatrix {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharAndTaxon.class, getName() + "  needs a method to calculate a value for each cell.",
+		"The method to calculate values can be selected initially or in the Values for Colors submenu");
+	}
+	/*.................................................................................................................*/
+	MesquiteTable table;
+	CharacterData data;
+	NumberForCharAndTaxon numberTask;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	double[][] values;
+	int windowWidth = 1;
+	MesquiteSubmenuSpec mss;
+	Class stateClass;
+	String ntName = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		ntC =makeCommand("setNumberTask",  this);
+ 		numberTaskName = new MesquiteString();
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+   	 	setActive(true);
+ 		if (active){
+			if (numCompatibleModulesAvailable(NumberForCharAndTaxon.class, stateClass, this)>0) {
+				mss = addSubmenu(null, "Values for Colors", ntC, NumberForCharAndTaxon.class);
+	 			mss.setSelected(numberTaskName);
+	 			mss.setCompatibilityCheck(stateClass);
+				mss.setEnabled(false);
+			}
+			addMenuItem("Moving Window (for colors)...", makeCommand("setWindowWidth", this));
+	 		if (!StringUtil.blank(ntName)) //remember last one used
+				numberTask = (NumberForCharAndTaxon)hireNamedEmployee(NumberForCharAndTaxon.class, ntName, data.getStateClass());//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+			
+			if (numberTask == null)
+				numberTask = (NumberForCharAndTaxon)hireCompatibleEmployee(NumberForCharAndTaxon.class, data.getStateClass(), "Number for cell of matrix");//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+			
+	 		if (numberTask != null){
+		 		ntName = "#"+numberTask.getShortClassName();
+		 		numberTask.setHiringCommand(ntC);
+		 		numberTaskName.setValue(numberTask.getName());
+ 			} else
+ 				return false;
+ 			mss.setCompatibilityCheck(data.getStateClass());
+			mss.setEnabled(active);
+			calculateNums();
+		}
+		else {
+			fireEmployee(numberTask);
+			numberTask = null;
+			deleteMenuItem(mss);
+		}
+		resetContainingMenuBar();
+		return true; //TODO: check success
+		
+	}
+	public void endJob(){
+		if (data!=null)
+			data.removeListener(this);
+		super.endJob();
+	}
+	double minValue = 0;
+	double maxValue = 0;
+	boolean numsCalculated = false;
+	/*.................................................................................................................*/
+	void calculateNums(){
+		numsCalculated = false;
+   	 	if (data == null || !isActive())
+   	 		return;
+    	 	if (values == null || data.getNumChars() != values.length || (values.length < 1 || data.getNumTaxa() != values[0].length))
+   	 		values = new double[data.getNumChars()][data.getNumTaxa()];
+   	 	if (numberTask ==null)
+   	 		return;
+   	 	MesquiteNumber result = new MesquiteNumber();
+   	 	MesquiteNumber min = new MesquiteNumber();
+   	 	MesquiteNumber max = new MesquiteNumber();
+   	 	
+   	 	for (int ic= 0; ic < data.getNumChars(); ic++)
+   	 		for (int it= 0; it < data.getNumTaxa(); it++) {
+   	 			result.setToUnassigned();
+   	 			numberTask.calculateNumber(data, ic, it, result, null);
+   	 			values[ic][it] = result.getDoubleValue();
+   	 			min.setMeIfIAmMoreThan(result);
+   	 			max.setMeIfIAmLessThan(result);
+   	 		}
+   	 	if (windowWidth>1){
+   	 		double[][] win = new double[data.getNumChars()][data.getNumTaxa()];
+   	 		for (int it= 0; it < data.getNumTaxa(); it++) {
+		   	 	for (int ic= 0; ic < data.getNumChars(); ic++){
+		   	 		int left = windowWidth/2;
+		   	 		int n = 0;
+		   	 		//first go left, skipping gaps!
+		   	 		int iw = 0;
+		   	 		int is = ic; //start at current character
+		   	 		while (iw<left && is>0){
+		   	 			is--;
+	   	 				if (!data.isInapplicable(is, it)){
+	   	 					if (MesquiteDouble.isCombinable(values[is][it])){
+			   	 				win[ic][it] += values[is][it];
+			   	 				n++;
+			   	 				iw++;
+		   	 				}
+		   	 			}
+	   	 			}
+	   	 			is = ic-1;
+		   	 		while (iw<windowWidth && is<data.getNumChars()){
+		   	 			is++;
+	   	 				if (!data.isInapplicable(is, it)){
+	   	 					if (MesquiteDouble.isCombinable(values[is][it])){
+			   	 				win[ic][it] += values[is][it];
+			   	 				n++;
+			   	 				iw++;
+		   	 				}
+		   	 			}
+	   	 			}
+		   	 		/* old; has problems at edges of indels
+		   	 		for (int iw = 0; iw<windowWidth; iw++){
+	   	 				int is = ic -left + iw;
+	   	 				if (is >=0 && is<data.getNumChars() && MesquiteDouble.isCombinable(values[is][it])){
+		   	 				win[ic][it] += values[is][it];
+		   	 				n++;
+		   	 			}
+	   	 			}
+	   	 			*/
+	   	 			if (n!=0)
+	   	 				win[ic][it] /= n;
+	   	 		}
+	   	 	}
+   	 		values = win;
+ 			min.setToUnassigned();
+ 			max.setToUnassigned();
+   	 		for (int it= 0; it < data.getNumTaxa(); it++) {
+		   	 	for (int ic= 0; ic < data.getNumChars(); ic++){
+	   	 			result.setValue(values[ic][it]);
+	   	 			min.setMeIfIAmMoreThan(result);
+	   	 			max.setMeIfIAmLessThan(result);
+	   	 		}
+	   	 	}
+ 	 	}
+   	 	minValue = min.getDoubleValue();
+   	 	maxValue = max.getDoubleValue();
+		numsCalculated = true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (this.data!=data && this.data!=null)
+			this.data.removeListener(this);
+		this.data = data;
+		data.addListener(this);
+		stateClass = data.getStateClass();
+		if (mss !=null && mss.getCompatibilityCheck() == null) {
+ 			mss.setCompatibilityCheck(data.getStateClass());
+ 			resetContainingMenuBar();
+ 		}
+		calculateNums();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+ 	 	if (numberTask ==null)
+ 	 		return null;
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setNumberTask ", numberTask);  
+  	 	temp.addLine("setWindowWidth " + windowWidth);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+   	 	if (checker.compare(this.getClass(), "Sets the module that calculates numbers by which to color the cells", "[name of module]", commandName, "setNumberTask")) {
+    	 		NumberForCharAndTaxon temp =  (NumberForCharAndTaxon)replaceCompatibleEmployee(NumberForCharAndTaxon.class, arguments, numberTask, stateClass);
+ 			if (temp!=null) {
+ 				numberTask = temp;
+		 		ntName = "#"+numberTask.getShortClassName();
+		 		numberTask.setHiringCommand(ntC);
+		 		numberTaskName.setValue(numberTask.getName());
+				calculateNums();
+				table.repaintAll();
+	 			return numberTask;
+	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the width of the moving window", "[width]", commandName, "setWindowWidth")) {
+    	 		int w = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteInteger.isCombinable(w) && !MesquiteThread.isScripting()){
+    	 			w = MesquiteInteger.queryInteger(containerOfModule(), "Moving Window", "Width of Moving Window", windowWidth, 1, 1000);
+    	 		}
+    	 		if (!MesquiteInteger.isCombinable(w))
+    	 			return null;
+    	 		windowWidth = w;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+    	 	}
+      	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+			calculateNums();
+			if (table !=null && isActive())
+				table.repaintAll();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Color By Cell Value";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Cell Value";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Colors the cells of a character matrix according to a value for that cell or a moving window of cells.";
+   	 }
+	/*.................................................................................................................*/
+   	public void viewChanged(){
+   	}
+   	ColorRecord[] legend;
+   	
+   	public ColorRecord[] getLegendColors(){
+   		if (legend == null) 
+   			legend = new ColorRecord[12];
+   		if (minValue >= maxValue) {
+	   		return null;
+   		}
+   		double interval = (maxValue-minValue)/10;
+   		for (int i = 0; i< 10; i++){
+   			double startInterval = interval*i + minValue;
+   			legend[i] = new ColorRecord(MesquiteColorTable.getBlueScale(startInterval, minValue, maxValue, false), MesquiteDouble.toString(startInterval));
+   		}
+   		legend[10] = new ColorRecord(MesquiteColorTable.getBlueScale(maxValue, minValue, maxValue, false), MesquiteDouble.toString(maxValue));
+   		legend[11] = new ColorRecord(ColorDistribution.straw, "Gap/Inapplicable");
+   		return legend;
+   	}
+   	public String getColorsExplanation(){
+   		return null;
+   	}
+	public Color getCellColor(int ic, int it){
+		if (ic<0 || it<0)
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (data == null || values == null)
+			return null;
+		else if (data.isInapplicable(ic, it)){
+			return ColorDistribution.straw;
+		}
+		else {
+			
+			Color c = MesquiteColorTable.getBlueScale(values[ic][it], minValue, maxValue, false);
+			return c;
+		}
+	}
+   	public String getCellString(int ic, int it){
+		if (ic<0 || it<0 || !isActive())
+			return null;
+		if (!numsCalculated)
+			calculateNums();
+
+		//data version has changed!?
+		if (data == null || values == null)
+			return "No number calculated";
+		else if (data.isInapplicable(ic, it)){
+			return "Character is inapplicable for this taxon (e.g., gap)";
+		} else if (numberTask!=null)
+			return numberTask.getName() + ": " + values[ic][it];
+		return null;
+   	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof CharacterData){
+			if (Notification.appearsCosmetic(notification))
+				return;
+			calculateNums();
+			if (table!=null)
+				table.repaintAll();
+		}
+	}
+	
+	public String getParameters(){
+		if (numberTask!= null){
+			return "Value used for coloring: " + numberTask.getNameAndParameters();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	public CompatibilityTest getCompatibilityTest(){
+		return new CbNCompatibilityTest();
+	}
+}
+
+class CbNCompatibilityTest extends CharacterStateTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj == null)
+			return true;
+		if (!(super.isCompatible(obj, project, prospectiveEmployer)))
+			return false;
+		return (((MesquiteModule)prospectiveEmployer).numCompatibleModulesAvailable(NumberForCharAndTaxon.class, obj, (MesquiteModule)prospectiveEmployer)>0); 
+	}
+}
+
+
+
+	
+
+
diff --git a/Source/mesquite/molec/ColorOddAAs/ColorOddAAs.java b/Source/mesquite/molec/ColorOddAAs/ColorOddAAs.java
new file mode 100644
index 0000000..9b66a0d
--- /dev/null
+++ b/Source/mesquite/molec/ColorOddAAs/ColorOddAAs.java
@@ -0,0 +1,200 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.ColorOddAAs; 
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class ColorOddAAs extends DataWindowAssistantID implements CellColorer, CellColorerMatrix {
+	MesquiteTable table;
+	protected DNAData data;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public boolean setActiveColors(boolean active){
+		setActive(true);
+		return true; //TODO: check success
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		if (data instanceof DNAData)
+			this.data = (DNAData)data;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color AAs to Check";
+	}
+	public String getNameForMenuItem() {
+		return "Color AAs to Check";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Colors the cells of a DNA matrix by stop codons, partial triplets, and missing data.";
+	}
+	/*.................................................................................................................*/
+	public void viewChanged(){
+	}
+	public String getCellString(int ic, int it){
+
+		if (!isActive())
+			return null;
+		if (ic<0 || it<0)
+			return "Cells colored to show regions to check";
+		if (data == null)
+			return null;
+		else if (!data.isCoding(ic)) {
+			return "Cells colored to show regions to check";
+		}
+		else {
+			long s = data.getAminoAcid(ic,it,true);
+			if (!CategoricalState.isImpossible(s)) {
+				String st = "Translated amino acid: " + ProteinState.toString(s, false) + " (followed by ";
+				MesquiteInteger nextCharacter = new MesquiteInteger(ic);
+				for (int i = 0; i<20; i++){
+					s = data.getNextAminoAcid(nextCharacter, it, true);
+					if (s!=CategoricalState.inapplicable)
+						st += ProteinState.toString(s, false);
+				}
+				return st + ")";
+			}
+			else {
+				return "Cells colored to show regions to check";
+			}
+		}
+	}
+	ColorRecord[] legend;
+	Color stopColor = Color.black;
+	Color partTripletColor = Color.red;
+	Color missingColor = Color.blue;
+	Color terminalColor = ColorDistribution.veryLightGray;
+	Color immediateTerminusColor = Color.green;
+	/*.................................................................................................................*/
+	public ColorRecord[] getLegendColors(){
+		if (data == null)
+			return null;
+		legend = new ColorRecord[6];
+		legend[0] = new ColorRecord(stopColor, "stop");
+		legend[1] = new ColorRecord(partTripletColor, "incomplete codon triplet");
+		legend[2] = new ColorRecord(missingColor, "missing");
+		legend[3] = new ColorRecord(immediateTerminusColor, "start/end of sequence");
+		legend[4] = new ColorRecord(terminalColor, "terminal gaps");
+		legend[5] = new ColorRecord(Color.white, "other");
+
+		return legend;
+	}
+	/*.................................................................................................................*/
+	public String getColorsExplanation(){
+		if (data == null)
+			return null;
+		/*  		if (data.getClass() == CategoricalData.class){
+   			return "Colors of states may vary from character to character";
+   		}
+		 */
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public Color getCellColor(int ic, int it){
+		
+
+		if (ic<0 || it<0)
+			return null;
+		if (data == null)
+			return null;
+		boolean isStop = false;
+		Color color = null;
+		 if (!data.isCoding(ic)) {
+			color = data.getColorOfStates(ic, it);
+		}
+		else {
+			long s = data.getAminoAcid(ic,it,true);
+			
+			if (!CategoricalState.isImpossible(s)) {
+				color = ProteinData.getAminoAcidColor(s, ProteinData.multistateColor);
+				if (CategoricalState.isOnlyElement(s, ProteinData.TER))
+					isStop=true;
+			}
+			else {
+				color = data.getColorOfStates(ic, it);
+			}
+		}
+		  if (data.isInapplicable(ic,it)) {
+			  if (ic+1<data.getNumChars()){
+				  if (!data.anyApplicableBefore(ic,it)) 
+					 if (!data.isInapplicable(ic+1,it))
+						 return immediateTerminusColor;
+					 else
+						 return terminalColor;
+				  }
+			  if (ic-1>0){
+				  if (!data.anyApplicableAfter(ic,it)) 
+						 if (!data.isInapplicable(ic-1,it))
+							 return immediateTerminusColor;
+						 else
+							 return terminalColor;
+				  }
+		 }
+		 if (isStop) {
+			 return stopColor;
+		 } else if (data.isInPartialTriplet(ic, it, null)) {
+			 return partTripletColor;
+		 }
+		 else if (data.isUnassigned(ic,it)) {
+			 return missingColor;
+		 }
+		 color = ColorDistribution.brighter(color, 0.25);
+			
+		return color;
+		 
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	public String getParameters(){
+		if (isActive())
+			return getName();
+		return null;
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/molec/CompareBasesWithTaxon/CompareBasesWithTaxon.java b/Source/mesquite/molec/CompareBasesWithTaxon/CompareBasesWithTaxon.java
new file mode 100644
index 0000000..5a1fa91
--- /dev/null
+++ b/Source/mesquite/molec/CompareBasesWithTaxon/CompareBasesWithTaxon.java
@@ -0,0 +1,114 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.CompareBasesWithTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class CompareBasesWithTaxon extends DNADataUtility { 
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public boolean operateOnData(CharacterData data){
+		this.data = data;
+		Taxa taxa = data.getTaxa();
+		DNAData dnaData = (DNAData)data;
+		String s = "";
+		boolean anySelected = taxa.anySelected();
+		if (anySelected)
+			s = " selected";
+		Taxon taxon = taxa.userChooseTaxon(containerOfModule(), "With which taxon to compare the" + s + " taxa?");
+		if (taxon !=null){
+			int[][] count = new int[4][4];
+			Integer2DArray.zeroArray(count);
+			int referenceTaxon = taxa.whichTaxonNumber(taxon);
+			String names = null;
+			int numComp = 0;
+			for (int it=0; it<taxa.getNumTaxa(); it++){
+				if (!anySelected || taxa.getSelected(it)){
+					numComp++;
+					if (numComp>1)
+						names = "";
+					else
+						names = " (" + taxa.getTaxonName(it) + ")";	
+					for (int ic = 0; ic<dnaData.getNumChars(); ic++){
+						long referenceStates = dnaData.getState(ic, referenceTaxon);
+						long targetStates = dnaData.getState(ic, it);
+						//for each state in reference, if the state is also in target, then don't count
+						// if state is not in target, then count one difference from ref to target
+						for (int sRef = 0; sRef <4; sRef++){ //go through ACGT
+							if (CategoricalState.isElement(referenceStates, sRef)){
+								for (int sTarg = 0; sTarg <4; sTarg++){ //go through ACGT
+									if (CategoricalState.isElement(targetStates, sTarg)){
+										count[sRef][sTarg]++;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			String output = "\nComparing " + taxon.getName() + " (reference) to " + numComp + " species " + names + '\n';
+			output+= "Ref.\tStates In Compared Taxa\n\tA\tC\tG\tT            \n";
+			output += "A" + countsToString(count[0]) + '\n';
+			output += "C" + countsToString(count[1]) + '\n';
+			output += "G" + countsToString(count[2]) + '\n';
+			output += "T" + countsToString(count[3]) + '\n';
+			showLogWindow();
+			logln(output);
+			return true;
+		}
+		else
+			return false;
+	}
+	String countsToString(int[] c){
+		String s = "";
+		for (int i = 0; i<c.length; i++)
+			s += "\t" + Integer.toString(c[i]);
+		return s;
+	}
+	
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Compare Bases with Taxon";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Compares nucleotide bases of selected taxa with those of a chosen taxon.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/ConvertToRY/ConvertToRY.java b/Source/mesquite/molec/ConvertToRY/ConvertToRY.java
new file mode 100644
index 0000000..dc440bf
--- /dev/null
+++ b/Source/mesquite/molec/ConvertToRY/ConvertToRY.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.ConvertToRY;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ConvertToRY extends DNADataAlterer {
+	MesquiteTable table;
+	DNAState charState = new DNAState();
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		this.table = table;
+		if (!(data instanceof DNAData)){
+			MesquiteMessage.warnProgrammer("Can use " + getName() + " only on nucleotide data");
+			return false;
+		}
+		return alterContentOfCells(data,table, undoReference);
+	}
+	
+
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		DNAData data = (DNAData)ddata;
+		charState = (DNAState) data.getCharacterState(charState, ic, it);
+		long newSet = 0;
+		boolean hasData = false;
+		if (charState.hasPurine()) {
+			newSet = charState.addToSet(newSet, 0); //A
+			newSet = charState.addToSet(newSet, 2); //G
+			hasData = true;
+		}
+		if (charState.hasPyrimidine()) {
+			newSet = charState.addToSet(newSet, 1); //C
+			newSet = charState.addToSet(newSet, 3); //T
+			hasData = true;
+		}
+		if (hasData) {
+			newSet = charState.setUncertainty(newSet, true);
+			data.setState(ic, it, newSet);
+			if (charState.getValue()!=newSet) {
+				if (!MesquiteLong.isCombinable(numCellsAltered))
+					numCellsAltered = 0;
+				numCellsAltered++;
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Convert to RY";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts nucleotide data to RY data in selected region." ;
+	}
+
+}
+
diff --git a/Source/mesquite/molec/CurrentGenCodeModels/CurrentGenCodeModels.java b/Source/mesquite/molec/CurrentGenCodeModels/CurrentGenCodeModels.java
new file mode 100644
index 0000000..6cab65f
--- /dev/null
+++ b/Source/mesquite/molec/CurrentGenCodeModels/CurrentGenCodeModels.java
@@ -0,0 +1,307 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.CurrentGenCodeModels;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+/* Returns GenCode model currently assigned to a character. If none assigned, returns the default model. */
+public class CurrentGenCodeModels extends GenCodeModelSource implements MesquiteListener {
+	ModelSet currentModelSet;
+	String preferred = "GeneticCode";
+	Class defaultStateClass;
+	CharacterData currentData = null;
+	int currentChar;
+	boolean reassignable = false;
+	CharacterModel lastModel;
+	MesquiteSubmenuSpec smenu;
+	MesquiteMenuItemSpec aboutItem;
+	Class oldStateClass;
+	CharacterModel defaultModel;
+	MesquiteString modelName;
+	LongArray ids;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getProject().getCentralModelListener().addListener(this);
+		ids = new LongArray(20);
+		modelName = new MesquiteString();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		int code = Notification.getCode(notification);
+		if (obj instanceof GenCodeModel && code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED) {
+			if (!reassignable || obj == lastModel || (ids.indexOf(((ProbabilityModel)obj).getID())>=0)) {
+				outputInvalid();
+				parametersChanged(notification);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof GenCodeModel) {
+			if (!reassignable || obj == lastModel) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns model for character ic in data */
+	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+
+		currentData = data;
+		currentChar = ic;
+		if (data==null) {
+			MesquiteMessage.warnProgrammer("DATA NULL in Current Genetic Code Models;  getModelCurrentCharacter (a)");
+			lastModel = null;
+			modelName.setValue("");
+			if (reassignable)
+				MesquiteTrunk.resetCheckMenuItems();
+			return null;
+		}
+		else {
+
+			if (data.getStateClass()!=oldStateClass)
+				resetCurrent(data.getStateClass());
+			CharacterModel cm=null;
+			currentModelSet = (ModelSet)data.getCurrentSpecsSet(GenCodeModelSet.class);
+			if (currentModelSet == null) {
+				cm= data.getDefaultModel(preferred);
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (b)");
+			}
+			else {
+				cm = currentModelSet.getModel(ic);
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (c)");
+			}
+			if (reassignable && lastModel != cm)
+				MesquiteTrunk.resetCheckMenuItems();
+			lastModel = cm;
+			modelName.setValue(lastModel.getName());
+			if (ids.indexOf(cm.getID())<0)
+				if (!ids.fillNextUnassigned(cm.getID())){
+					ids.resetSize(ids.getSize()+10);
+					ids.fillNextUnassigned(cm.getID());
+				}
+			return cm;
+		}
+	}
+
+	/** returns model for character */
+	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		if (states==null) {
+			MesquiteMessage.warnProgrammer("STATES NULL in Current Genetic Code Models; getModelCurrentCharacter (d)");
+			lastModel = null;
+			modelName.setValue("");
+			if (reassignable)
+				MesquiteTrunk.resetCheckMenuItems();
+			return null;
+		}
+		else {
+			if (states.getStateClass()!=oldStateClass)
+				resetCurrent(states.getStateClass());
+
+			CharacterModel cm=null;
+			CharacterData data = states.getParentData();
+			currentData = data;
+			if (data == null) {
+				if (defaultModel == null || !defaultModel.getStateClass().isAssignableFrom(states.getStateClass()))
+					defaultModel = states.getDefaultModel(getProject(), preferred);
+				cm = defaultModel;
+
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (e)");
+			}
+			else {
+				int ic =  states.getParentCharacter(); 
+				currentChar = ic;
+				currentModelSet = (ModelSet)data.getCurrentSpecsSet(GenCodeModelSet.class);
+				if (currentModelSet == null) {
+					if (states!=null) {
+						cm= states.getDefaultModel(getProject(), preferred);
+						if (cm==null)
+							MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (f)");
+					}
+					else
+						MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (g)");
+				}
+				else {
+					cm = currentModelSet.getModel(ic);
+					if (cm==null && states!=null)
+						cm= states.getDefaultModel(getProject(), preferred);
+					if (cm==null) {
+						MesquiteMessage.warnProgrammer("MODEL NULL in Current Genetic Code Models; getModelCurrentCharacter (h) " + ic);
+						MesquiteMessage.warnProgrammer("data " + data.getName() + "  " + data);
+					}
+				}
+			}
+			if (reassignable && lastModel != cm)
+				MesquiteTrunk.resetCheckMenuItems();
+			lastModel = cm;
+			if (lastModel!=null)
+				modelName.setValue(lastModel.getName());
+			if (ids.indexOf(cm.getID())<0)
+				if (!ids.fillNextUnassigned(cm.getID())){
+					ids.resetSize(ids.getSize()+10);
+					ids.fillNextUnassigned(cm.getID());
+				}
+			return cm;
+		}
+	}
+	void resetCurrent(Class stateClass){
+		oldStateClass = stateClass;
+		if (smenu!=null) {
+			deleteMenuItem(smenu);
+			smenu=null;
+		}   		
+		if (reassignable) {
+			smenu = addSubmenu(null, "Genetic Code model", makeCommand("setModel", this), getProject().getCharacterModels());
+			smenu.setCompatibilityCheck(new ModelCompatibilityInfo(GenCodeModel.class, stateClass));
+			smenu.setSelected(modelName);
+		}
+		resetContainingMenuBar();
+		MesquiteTrunk.resetCheckMenuItems();
+	}
+	/*.................................................................................................................*/
+	/* If this is called passing true, module will assume that there will be an implicit "current character" (e.g., in trace character) and thus will allow user
+	to set model of this current character.  The "current" will be assumed the last character for which model requested. */
+	public void setOneCharacterAtATime(boolean chgbl){
+		if (!chgbl)
+			deleteMenuItem(aboutItem);
+		else if (aboutItem == null)
+			aboutItem = addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+
+		reassignable = chgbl;
+		Class stateClass = null;
+		if (currentData!=null)
+			stateClass = currentData.getStateClass();
+		resetCurrent(stateClass);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (defaultModel !=null)
+			temp.addLine("setDefaultModel "+ getProject().getWhichCharacterModel(null, defaultModel));
+		return temp;
+	}
+	/*.................................................................................................................*
+    	 public String getParameters() {
+		return "CurrentParsModels timer " + timer.getAccumulatedTime() + " timer2 " + timer2.getAccumulatedTime() + " timer3 " + timer3.getAccumulatedTime() + " timer4 " + timer4.getAccumulatedTime() + " timer5 " + timer5.getAccumulatedTime();
+   	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the genetic code, subject to compatibility with current state class", "[number of model]", commandName, "setModel")) {
+			if (currentData == null){
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				defaultModel = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, oldStateClass), whichModel);
+				parametersChanged();
+				return defaultModel;
+			}
+			else {
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(GenCodeModel.class, currentData.getStateClass()), whichModel);
+
+				ModelSet modelSet  = (ModelSet)currentData.getCurrentSpecsSet(GenCodeModelSet.class);
+				if (model!=null){
+					if (modelSet == null) {
+						CharacterModel defaultModel =  currentData.getDefaultModel("GeneticCode");
+						modelSet= new GenCodeModelSet("Model Set", currentData.getNumChars(), defaultModel, currentData);
+						currentData.storeSpecsSet(modelSet, GenCodeModelSet.class);
+						currentData.setCurrentSpecsSet(modelSet, GenCodeModelSet.class);
+						modelSet.addToFile(currentData.getFile(), getProject(), findElementManager(GenCodeModelSet.class)); 
+					}
+
+					if (modelSet != null) {
+						modelSet.setModel(model, currentChar); 
+						currentData.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //should notify via specs not data???
+					}
+					parametersChanged();
+				}
+				return model;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the genetic code", "[number of model]", commandName, "setDefaultModel")) {
+			boolean changed=false;
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(whichModel))
+				return null;
+			defaultModel = getProject().getCharacterModel(whichModel);
+			parametersChanged();
+			return defaultModel;
+		}
+		else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+			String s = "";
+			if (lastModel == null)
+				s = "Sorry, no reference to the last used-model was found";
+			else
+				s = "The most recently used model is \"" + lastModel.getName() + "\".\nExplanation: " + lastModel.getExplanation();
+			discreetAlert( s);
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Current Genetic Codes";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies the currently assigned genetic code (e.g., \"standard\") for a character." ;
+	}
+}
+
diff --git a/Source/mesquite/molec/FetchGenBank/FetchGenBank.java b/Source/mesquite/molec/FetchGenBank/FetchGenBank.java
new file mode 100644
index 0000000..6259051
--- /dev/null
+++ b/Source/mesquite/molec/FetchGenBank/FetchGenBank.java
@@ -0,0 +1,132 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.FetchGenBank; 
+
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class FetchGenBank extends DataUtility { 
+	CharacterData data;
+	String genBankNumbers;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryFilesDialog = new ExtensibleDialog(containerOfModule(), "Fetch & Add GenBank",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		queryFilesDialog.addLabel("Accession Numbers (separated by commas):");
+
+		genBankNumbers = "";
+		TextArea numbersArea = queryFilesDialog.addTextArea("",  5);
+
+		queryFilesDialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			genBankNumbers = numbersArea.getText();
+		}
+		queryFilesDialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	/** Called to operate on the data in all cells.  Returns true if data altered*/
+	public boolean operateOnData(CharacterData data){ 
+		this.data = data;
+
+		if (queryOptions()) {
+			logln("\nFetching GenBank entries: "  + genBankNumbers);
+
+			try {
+				String[] accessionNumbers = StringUtil.delimitedTokensToStrings(genBankNumbers,',');
+				for (int i=0; i<accessionNumbers.length; i++) 
+					if (!StringUtil.blank(accessionNumbers[i])) 				
+						logln ("Accession numbers " + accessionNumbers[i]);
+
+				logln("Querying for IDs of entries.");
+				String[] idList = NCBIUtil.getGenBankIDs(accessionNumbers, data instanceof DNAData,  this, true);
+				if (idList==null)
+					return false;
+				logln("IDs acquired.");
+					/*for (int i=0; i<idList.length; i++) 
+						if (!StringUtil.blank(idList[i])) 				
+							logln ("To Fetch " + idList[i]);*/
+
+				logln("\nRequesting sequences.\n");
+				StringBuffer report = new StringBuffer();
+				String fasta = NCBIUtil.fetchGenBankSequences(idList,data instanceof DNAData, this, true, report);
+				NCBIUtil.importFASTASequences(data, fasta, this, report, -1, -1, false, false);
+				log(report.toString());
+				return StringUtil.notEmpty(fasta);
+
+
+			} catch ( Exception e ){
+				// better warning
+				return false;
+			}
+		}
+		else
+			return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		return temp;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Fetch & Add GenBank Sequences...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Fetch & Add GenBank Sequences";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Fetches GenBank nucleotide sequences given their GenBank accession numbers and adds them to the matrix.";
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/molec/FillCharSelection/FillCharSelection.java b/Source/mesquite/molec/FillCharSelection/FillCharSelection.java
new file mode 100644
index 0000000..e8d0f57
--- /dev/null
+++ b/Source/mesquite/molec/FillCharSelection/FillCharSelection.java
@@ -0,0 +1,80 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.FillCharSelection;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+//new in 1. 06
+//need to have UI to specify tolerance
+
+/* ======================================================================== */
+public class FillCharSelection extends CharacterSelector {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	int THRESHOLD = 1; //allowed space between selections to fuse
+
+   	/** Called to select characters*/
+   	public void selectCharacters(CharacterData data){
+   		if (data!=null && data.getNumChars()>0){
+   			if (!data.anySelected()) //nothing to interpolate
+   				return;
+   			int numChars = data.getNumChars();
+   			int lastSel = -1;
+   			boolean prevUnselected = false;
+   			for (int i=0; i<numChars; i++) {
+   				if (data.getSelected(i)) {
+   					if (lastSel>=0 && i-lastSel>1 && i-lastSel<=THRESHOLD+1){ //hit selected after unselected; last selected near enough to interpolate
+						for (int i2=lastSel+1; i2<i; i2++)
+							data.setSelected(i2, true);
+   					}
+   					lastSel = i;
+   				}
+   			}
+   			data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   		}
+   	}
+   	public boolean requestPrimaryChoice(){
+   		return true;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Interpolate Character Selection";
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false; 
+   	 }
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects characters that are surrounded by characters selected." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/FindMissing/FindMissing.java b/Source/mesquite/molec/FindMissing/FindMissing.java
new file mode 100644
index 0000000..e6f721e
--- /dev/null
+++ b/Source/mesquite/molec/FindMissing/FindMissing.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.FindMissing;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class FindMissing extends FindSequenceCriterionG {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public boolean showOptions(CharacterData data, MesquiteTable table){
+		return true;
+	}
+   	public boolean findNext(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+  			length.setValue(0);
+  			int firstTaxon = taxonFound.getValue();
+  			int firstChar = charFound.getValue();
+  			int numTaxa = data.getNumTaxa();
+  			int numChars = data.getNumChars();
+			for (int it = firstTaxon; it< numTaxa; it++){
+	   			for (int ic = firstChar; ic< numChars; ic++) {
+	   				if (data.isUnassigned(ic, it)){
+  						charFound.setValue(ic);
+  						taxonFound.setValue(it);
+  						length.setValue(1);
+  						return true;
+	   				}
+   				}
+   			}
+   			return false;
+   	}
+
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Find Missing";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Finds the next occurrence of missing data in a matrix of molecular data." ;
+   	 }
+	public boolean showOptions(boolean findAll, CharacterData data, MesquiteTable table) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return  300;  
+	}
+
+}
+
diff --git a/Source/mesquite/molec/FindPartialTriplet/FindPartialTriplet.java b/Source/mesquite/molec/FindPartialTriplet/FindPartialTriplet.java
new file mode 100644
index 0000000..88c6ced
--- /dev/null
+++ b/Source/mesquite/molec/FindPartialTriplet/FindPartialTriplet.java
@@ -0,0 +1,100 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.FindPartialTriplet;
+/*~~  */
+
+import mesquite.categ.lib.DNAData;
+import mesquite.categ.lib.DNAState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class FindPartialTriplet extends FindSequenceCriterionG {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public boolean showOptions(CharacterData data, MesquiteTable table){
+		return true;
+	}
+	public boolean findNext(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+		length.setValue(0);
+		int firstTaxon = taxonFound.getValue();
+		int firstChar = charFound.getValue();
+		int numTaxa = data.getNumTaxa();
+		int numChars = data.getNumChars();
+		MesquiteInteger matchLength = new MesquiteInteger(3);
+		for (int it = firstTaxon; it< numTaxa; it++){
+			for (int ic = firstChar; ic< numChars; ic++) {
+				if (isPartialTriplet(data, table, ic, it, matchLength)){
+					charFound.setValue(ic);
+					taxonFound.setValue(it);
+					length.setValue(matchLength.getValue());
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean isPartialTriplet(CharacterData dData, MesquiteTable table,  int ic, int it, MesquiteInteger matchLength){
+		if (dData==null || table==null)
+			return false;
+
+		if (!(dData instanceof DNAData)){
+			MesquiteMessage.warnProgrammer(getName() + " requires DNA data");
+			return false;
+		}
+		DNAData data = (DNAData)dData;
+	
+		return data.isStartOfPartialTriplet(ic, it, matchLength);
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Find Incomplete Codons";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Finds the next occurrence of a partial codon triplet in a matrix of molecular data." ;
+	}
+	public boolean showOptions(boolean findAll, CharacterData data, MesquiteTable table) {
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return  300;  
+	}
+
+
+}
+
diff --git a/Source/mesquite/molec/FindSequence/FindSequence.java b/Source/mesquite/molec/FindSequence/FindSequence.java
new file mode 100644
index 0000000..48ff50a
--- /dev/null
+++ b/Source/mesquite/molec/FindSequence/FindSequence.java
@@ -0,0 +1,188 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.FindSequence;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import java.awt.event.*;
+import mesquite.molec.lib.*;
+import java.awt.datatransfer.*;
+/* ======================================================================== *
+
+*new in 1.05*
+
+/* ======================================================================== */
+public class FindSequence extends DataWindowAssistantI {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(FindSequenceCriterion.class, getName() + "  needs a criterion for finding sequences.",
+		"The criterion for finding sequences is chosen in the Find Sequence or Final All Sequences submenus of the Edit menu of the Character Matrix Editor");
+	}
+	/*.................................................................................................................*/
+	MesquiteTable table;
+	CharacterData data;
+	int firstTaxon = 0;
+	int firstChar = 0;
+	boolean findAll = false;
+	FindSequenceCriterion criterionTask;
+	MesquiteSubmenuSpec mss, mss3;
+	MesquiteString criterionName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		criterionName = new MesquiteString();
+		if (numModulesAvailable(FindSequenceCriterion.class)>0) {
+			mss3 = addSubmenu(MesquiteTrunk.editMenu, "Find Sequence", makeCommand("findSequence", this), FindSequenceCriterion.class);
+ 			mss = addSubmenu(MesquiteTrunk.editMenu, "Find All Sequences", makeCommand("findAllSequences", this), FindSequenceCriterionG.class);
+			mss.setSelected(criterionName);
+ 			mss3.setSelected(criterionName);
+			MesquiteMenuItemSpec mm2 =addMenuItem(MesquiteTrunk.editMenu, "Find Sequence Again", makeCommand("findSequenceAgain", this));
+			mm2.setShortcut(KeyEvent.VK_6);
+			MesquiteMenuItemSpec mm3 =addMenuItem(MesquiteTrunk.editMenu, "Copy Sequence", makeCommand("copySequence", this));
+			mm3.setShortcut(KeyEvent.VK_C);
+			mm3.setShortcutNeedsShift(true);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+	}
+	public void employeeQuit(MesquiteModule employee){
+		if (employee == criterionTask)
+			criterionTask = null;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Finds sequence",null, commandName, "findSequence")) {
+			//hire assistant
+			if (criterionTask == null || !criterionTask.nameMatches(parser.getFirstToken(arguments)))
+				criterionTask = (FindSequenceCriterion)replaceEmployee(FindSequenceCriterion.class, arguments, "Criterion", criterionTask);
+			boolean proceed= criterionTask.showOptions( data, table);
+			if (criterionTask == null || !proceed)
+				return null;
+			criterionName.setValue(criterionTask.getName());
+			firstChar = 0;
+			firstTaxon = 0;
+			if (criterionTask instanceof FindSequenceCriterionG)
+				seek("No instances found");
+   	 		
+		}
+    	 	else if (checker.compare(this.getClass(), "Finds all sequences matching a criterion",null, commandName, "findAllSequences")) {
+			//hire assistant
+			if (criterionTask == null || !criterionTask.nameMatches(parser.getFirstToken(arguments)))
+				criterionTask = (FindSequenceCriterionG)replaceEmployee(FindSequenceCriterionG.class, arguments, "Criterion", criterionTask);
+			boolean proceed= ((FindSequenceCriterionG)criterionTask).showOptions(true, data, table);
+			if (criterionTask == null || !proceed)
+				return null;
+			criterionName.setValue(criterionTask.getName());
+			firstChar = 0;
+			firstTaxon = 0;
+			seekAll("No instances found");
+   	 		
+		}
+    	 	else if (checker.compare(this.getClass(), "Finds sequence",null, commandName, "findSequenceAgain")) {
+    			if (criterionTask instanceof FindSequenceCriterionG)
+    				seek("No more instances found");
+    			else
+    				discreetAlert("Find Sequence Again is not applicable to the sequence finder you are currently using.  The sequence finder can be chosen under Edit>Find Sequence>");
+		}
+    	 	else if (checker.compare(this.getClass(), "Copies sequence without tabs",null, commandName, "copySequence")) {
+				StringBuffer sb = new StringBuffer(100);
+				table.copyIt(sb, false, false, true);
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(sb.toString());
+				clip.setContents(ss, ss);
+		}
+   	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	
+	}
+	
+	void seekAll(String failureMessage){
+			if (criterionTask == null)
+				return;
+			MesquiteInteger charFound = new MesquiteInteger(0);
+			MesquiteInteger length = new MesquiteInteger();
+			MesquiteInteger taxonFound = new MesquiteInteger(0);
+  	 		table.deselectAll();
+  	 		int numFound = 0;
+   	 		while (((FindSequenceCriterionG)criterionTask).findNext(data, table, charFound, length, taxonFound)){
+   	 			numFound++;
+				table.setFocusedSequence(charFound.getValue(), charFound.getValue() + length.getValue(), taxonFound.getValue());
+   	 			charFound.increment();
+   	 		}
+   	 		if (numFound==0) {
+   	 			alert(failureMessage);
+   	 		}
+   	 		else if (numFound > 1)
+   	 			logln(Integer.toString(numFound) + " instances found.");
+   	 		else logln("One instance found.");
+			table.repaintAll();
+ 	}
+	void seek(String failureMessage){
+			if (criterionTask == null)
+				return;
+			MesquiteInteger charFound = new MesquiteInteger(firstChar);
+			MesquiteInteger length = new MesquiteInteger();
+			MesquiteInteger taxonFound = new MesquiteInteger(firstTaxon);
+  	 		table.deselectAll();
+   	 		if (((FindSequenceCriterionG)criterionTask).findNext(data, table, charFound, length, taxonFound)){
+   	 			firstChar = charFound.getValue();
+   	 			firstTaxon = taxonFound.getValue();
+				table.setFocusedSequence(charFound.getValue(), charFound.getValue() + length.getValue(), taxonFound.getValue());
+   	 			firstChar++;
+   	 		}
+   	 		else {
+   	 			firstChar = 0;
+   	 			firstTaxon = 0;
+   	 			alert(failureMessage);
+   	 		}
+			table.repaintAll();
+ 	}
+   	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Find Sequence";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Finds the next occurrence of a sequence in a matrix of molecular data." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/GBLOCKSSelector/GBLOCKSSelector.java b/Source/mesquite/molec/GBLOCKSSelector/GBLOCKSSelector.java
new file mode 100644
index 0000000..1930e62
--- /dev/null
+++ b/Source/mesquite/molec/GBLOCKSSelector/GBLOCKSSelector.java
@@ -0,0 +1,110 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.GBLOCKSSelector;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class GBLOCKSSelector extends CharacterSelector {
+
+
+	MesquiteString xmlPrefs= new MesquiteString();
+	String xmlPrefsString = null;
+
+	GBLOCKSCalculator gblocksCalculator;
+
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences(xmlPrefs);
+		xmlPrefsString = xmlPrefs.getValue();
+		gblocksCalculator = new GBLOCKSCalculator(this, xmlPrefsString);
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		if (gblocksCalculator!=null){
+			String s = gblocksCalculator.preparePreferencesForXML();
+			if (StringUtil.notEmpty(s))
+				buffer.append(s);
+		}
+		return buffer.toString();
+	}
+
+
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+
+	/*.................................................................................................................*/
+	/** Called to select characters*/
+	public void selectCharacters(CharacterData data){
+		if (data!=null && data.getNumChars()>0){
+
+			if (!gblocksCalculator.queryOptions(this, "Select"))
+				return;
+
+			boolean[] setToSelect = new boolean[data.getNumChars()];
+
+			StringBuffer results = new StringBuffer();
+			if (gblocksCalculator.markCharacters(data, this, setToSelect, results)) {
+				logln(results.toString());
+
+				// ======  now select the characters chosen
+				for (int ic=0; ic<data.getNumChars() && ic<setToSelect.length; ic++)
+					if (setToSelect[ic]==gblocksCalculator.getChooseAmbiguousSites())
+						data.setSelected(ic, true);
+
+
+				data.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "GBLOCKS Selector";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "GBLOCKS Selector...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Selects characters according to an extended version of the GBLOCKS algorithm (Castresana, 2000)." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 303;  
+	}
+
+}
+
diff --git a/Source/mesquite/molec/GCAsNumber/GCAsNumber.java b/Source/mesquite/molec/GCAsNumber/GCAsNumber.java
new file mode 100644
index 0000000..2a099a0
--- /dev/null
+++ b/Source/mesquite/molec/GCAsNumber/GCAsNumber.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.GCAsNumber; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class GCAsNumber extends NumberForCharAndTaxon {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	long A = CategoricalState.makeSet(0);
+	long C = CategoricalState.makeSet(1);
+	long G = CategoricalState.makeSet(2);
+	long T = CategoricalState.makeSet(3);
+	long AT = A | T;
+	long GC = G | C;
+	public void initialize(CharacterData data){
+	}
+	public void calculateNumber(CharacterData data, int ic, int it, MesquiteNumber result, MesquiteString resultString){
+   	 	if (result == null)
+   	 		return;
+	   	clearResultAndLastResult(result);
+  	 	if (data == null || !(data instanceof DNAData))
+   	 		return;
+   	 	DNAData dData = (DNAData)data;
+   	 	long s = CategoricalState.statesBitsMask & dData.getState(ic, it);
+   	 	if (A == s || T == s || AT == s)
+   	 		result.setValue(0);
+   	 	else if (C == s || G == s || GC == s)
+   	 		result.setValue(1);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+  	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "GC";
+   	 }
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Returns 1 for G or C, 0 for A or T.";
+   	 }
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/GapsToMissing/GapsToMissing.java b/Source/mesquite/molec/GapsToMissing/GapsToMissing.java
new file mode 100644
index 0000000..fcd31cd
--- /dev/null
+++ b/Source/mesquite/molec/GapsToMissing/GapsToMissing.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.GapsToMissing;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class GapsToMissing extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		this.table = table;
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Can use " + getName() + " only on categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table, undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		if (data.isInapplicable(ic, it)) {
+			data.setState(ic, it, CategoricalState.unassigned);
+			if (!MesquiteLong.isCombinable(numCellsAltered))
+				numCellsAltered = 0;
+			numCellsAltered++;
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Gaps to Missing";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts gaps to missing data in selected region." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/GenBankNumber/GenBankNumber.java b/Source/mesquite/molec/GenBankNumber/GenBankNumber.java
new file mode 100644
index 0000000..fc7010f
--- /dev/null
+++ b/Source/mesquite/molec/GenBankNumber/GenBankNumber.java
@@ -0,0 +1,217 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.GenBankNumber;
+
+import mesquite.categ.lib.*;
+import mesquite.lists.lib.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.characters.MCharactersDistribution;
+import mesquite.lib.duties.MatrixSourceCoord;
+import mesquite.lib.table.*;
+
+
+/* ======================================================================== */
+public class GenBankNumber extends TaxonListAssistant {
+	Taxa taxa;
+	MesquiteTable table=null;
+	Taxa currentTaxa = null;
+	DNAData data = null;
+	MatrixSourceCoord matrixSourceTask;
+	MesquiteMenuItemSpec mss2;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, DNAState.class, "Source of DNA matrix (for " + getName() + ")"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void setData() {
+			matrixSourceTask.initialize(currentTaxa);
+			MCharactersDistribution observedStates = matrixSourceTask.getCurrentMatrix(currentTaxa);
+			CharacterData d = observedStates.getParentData();
+			if (d instanceof DNAData)
+				data = (DNAData)d;
+			else
+				data=null;
+		
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		deleteMenuItem(mss2);
+		mss2 = addMenuItem("Move Numbers from GenBank/FASTA Taxon Name", makeCommand("moveNumbersFromName", this));
+		if (this.taxa != null)
+			this.taxa.removeListener(this);
+		this.taxa = taxa;
+		if (this.taxa != null)
+			this.taxa.addListener(this);
+		if (taxa != currentTaxa || data == null ) {
+			currentTaxa = taxa;
+			setData();
+		}
+		this.table = table;
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		setData();
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public static String getGenBankNumber(MolecularData data, int it) {
+		if (data==null)
+			return null;
+		Taxon taxon = data.getTaxa().getTaxon(it);
+		Associable tInfo = data.getTaxaInfo(false);
+		if (tInfo != null && taxon != null) {
+			return (String)tInfo.getAssociatedObject(MolecularData.genBankNumberRef, it);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Acquires GenBank numbers from imported GenBank taxon names", null, commandName, "moveNumbersFromName")) {
+			moveNumberFromGenBankTaxonName();
+			return null;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	private void moveNumberFromGenBankTaxonName() {
+			if (table !=null && taxa!=null) {
+				boolean changed=false;
+				String id = "";
+				Parser parser = new Parser();
+				parser.setWhitespaceString("|");
+				if (employer!=null && employer instanceof ListModule) {
+					int c = ((ListModule)employer).getMyColumn(this);
+					for (int i=0; i<taxa.getNumTaxa(); i++) {
+						if (table.isCellSelectedAnyWay(c, i)) {
+							id = taxa.getName(i);
+							parser.setString(id);
+							String  token = parser.getFirstToken();
+							while (token!=null && !token.equalsIgnoreCase("gb") && !StringUtil.blank(token)){
+								token = parser.getNextToken();
+							}
+							if (token!= null && token.equalsIgnoreCase("gb")){
+								token = parser.getNextToken();
+								if (token.indexOf(".")>=0) {
+									token = token.substring(0,token.indexOf("."));
+									if (!StringUtil.blank(token)){
+										setString(i,token);
+										if (!changed)
+											outputInvalid();
+										changed = true;
+									}
+								}
+							}
+						}
+					}
+				}
+
+//				if (changed)
+//					data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
+				outputInvalid();
+				parametersChanged();
+
+			}
+		
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		return "GenBank Number";
+	}
+	public String getStringForTaxon(int it){
+		if (data==null || taxa==null)
+			return "-";
+		Taxon taxon = data.getTaxa().getTaxon(it);
+		Associable tInfo = data.getTaxaInfo(false);
+		if (tInfo != null && taxon != null) {
+			return (String)tInfo.getAssociatedObject(MolecularData.genBankNumberRef, it);
+		}
+		return "-";
+	}
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int row){
+		return true;
+	}
+	/*...............................................................................................................*/
+	/** for those permitting editing, indicates user has edited to incoming string.*/
+	public void setString(int row, String s){
+		if (data==null || taxa==null)
+			return;
+		Taxon taxon = data.getTaxa().getTaxon(row);
+		Associable tInfo = data.getTaxaInfo(true);
+		if (tInfo != null && taxon != null) {
+			tInfo.setAssociatedObject(MolecularData.genBankNumberRef, row, s);
+		}
+	}
+	public boolean useString(int ic){
+		return true;
+	}
+
+	public String getWidestString(){
+		return "8888888888888  ";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "GenBank Number";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Lists the primers used in the reads composing a sequence." ;
+	}
+}
diff --git a/Source/mesquite/molec/InitializeGenCode/InitializeGenCode.java b/Source/mesquite/molec/InitializeGenCode/InitializeGenCode.java
new file mode 100644
index 0000000..fcb50c6
--- /dev/null
+++ b/Source/mesquite/molec/InitializeGenCode/InitializeGenCode.java
@@ -0,0 +1,106 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.InitializeGenCode;
+/*~~  */
+
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.molec.lib.*;
+
+
+/* ======================================================================== */
+public class InitializeGenCode extends FileInit {
+	GenCodeModel standardModel, vertMitoModel, invertMitoModel, moldMitoModel, yeastMitoModel, ciliateModel;
+	GenCodeModel echinoModel,euplotidModel;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		standardModel = new GenCodeModelStandard();
+		vertMitoModel = new GenCodeModelVertMito();
+		invertMitoModel = new GenCodeModelInvertMito();
+		yeastMitoModel = new GenCodeModelYeastMito();
+		moldMitoModel =  new GenCodeModelMoldProtMito();
+		ciliateModel = new GenCodeModelCiliate();
+		echinoModel = new GenCodeModelEchino();
+		euplotidModel = new GenCodeModelEuplotid();
+		CategoricalData.registerDefaultModel("GeneticCode", "Standard");
+		DNAData.registerDefaultModel("GeneticCode", "Standard");
+		ProteinData.registerDefaultModel("GeneticCode", "Standard");
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been established but not yet read in.*/
+ 	public void projectEstablished() {
+ 		standardModel.addToFile(null, getProject(), null);
+		vertMitoModel.addToFile(null, getProject(), null);
+		invertMitoModel.addToFile(null, getProject(), null);
+		yeastMitoModel.addToFile(null, getProject(), null);
+		moldMitoModel.addToFile(null, getProject(), null);
+		ciliateModel.addToFile(null, getProject(), null);
+		echinoModel.addToFile(null, getProject(), null);
+		euplotidModel.addToFile(null, getProject(), null);
+//		xxx.addToFile(null, getProject(), null);
+		super.projectEstablished();
+ 	}
+	/*.................................................................................................................*/
+ 	public void fileElementAdded(FileElement element) {
+ 		if (element == null || getProject()==null)
+ 			return;
+		if (element instanceof MolecularData) {
+	 		CharacterModel defaultModel=null;
+			GenCodeModelSet currentGenCodeModels;
+	 		CharacterData data = (CharacterData)element;
+	 		if (data.getCurrentSpecsSet(GenCodeModelSet.class) == null) {
+		 		defaultModel =  data.getDefaultModel("GeneticCode");
+		 		currentGenCodeModels= new GenCodeModelSet("UNTITLED", data.getNumChars(), defaultModel, data);
+		 		currentGenCodeModels.addToFile(element.getFile(), getProject(), null);
+		 		data.setCurrentSpecsSet(currentGenCodeModels, GenCodeModelSet.class);
+	 		}
+	  		if (getProject().getCharacterModels()==null)
+	 			MesquiteMessage.warnProgrammer("charModels null in iMS Init GenCode");
+		}
+	}
+   
+	/*.................................................................................................................*/
+    	 public boolean isSubstantive() {
+		return false;
+   	 }
+    		/*.................................................................................................................*/
+    	 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    	 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    	 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	    	public int getVersionOfFirstRelease(){
+    	    		return 110;  
+    	    	}
+    	    	/*.................................................................................................................*/
+    	    	public boolean isPrerelease(){
+    	    		return true;
+    	    	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Initialize Genetic Code";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Initializes default genetic codes." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
diff --git a/Source/mesquite/molec/LowercaseEnds/LowercaseEnds.java b/Source/mesquite/molec/LowercaseEnds/LowercaseEnds.java
new file mode 100644
index 0000000..b3955d4
--- /dev/null
+++ b/Source/mesquite/molec/LowercaseEnds/LowercaseEnds.java
@@ -0,0 +1,142 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.LowercaseEnds;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+import java.awt.event.*;
+/* ======================================================================== *
+
+*new in 1.05*
+
+/* ======================================================================== */
+public class LowercaseEnds extends DataWSelectionAssistant {
+	MesquiteTable table;
+	CharacterData data;
+	int goodInARow = 3;
+	boolean findAll = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		int good = MesquiteInteger.queryInteger(containerOfModule(), "Selection criterion", "This selects the ends of a DNA sequence up to the first block of N sites in a row with uppercase (confident) symbols.  What value of N?  The larger the value, the more may be selected.", goodInARow);
+		if (!MesquiteInteger.isCombinable(good))
+			return false;
+		goodInARow = good;
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.table = table;
+		this.data = data;
+		select();
+	}
+   	void selectCells(int ic, int it, int length){
+   		if (table == null)
+   			return;
+   		for (int i = 0; i<length; i++)
+   			table.selectCell(ic + i, it);
+   	}
+
+
+   	/** Called to select characters*/
+   	public void select(){ //this should be passed boolean as to whether to notify re: selection?
+   		if (!(data instanceof CategoricalData)) {
+   			discreetAlert( "Sorry, Select Lowercase Ends can be applied only to categorical data");
+   		}
+   		else if ((table != null && data!=null && data.getNumChars()>0)){
+   			CategoricalData dData = (CategoricalData)data;
+   			boolean found = false;
+   			//find selected sequence, if only one
+			for (int it = 0; it< dData.getNumTaxa(); it++){
+				boolean done = false;
+				int goodToHere = 0;
+   				for (int ic = 0; ic< dData.getNumChars() && !done; ic++) {  //starting from left end
+   					long state = dData.getStateRaw(ic,it);
+   					if (!CategoricalState.isInapplicable(state)){
+   						if (CategoricalState.isLowerCase(state) || CategoricalState.isUnassigned(state)) {  //counts against
+   							selectCells(ic, it, 1);
+   							found = true;
+   							if (goodToHere>0){
+   								selectCells(ic-goodToHere, it, goodToHere);
+   								goodToHere = 0;
+   							}
+   						}
+   						else {
+   							goodToHere++;
+   							if (goodToHere>=goodInARow)
+   								done = true;
+   						}
+   					}
+   				}
+				done = false;
+				goodToHere = 0;
+   				for (int ic = dData.getNumChars() -1; ic>=0 && !done; ic--) {  //starting from right end
+   					long state = dData.getStateRaw(ic, it);
+   					if (!CategoricalState.isInapplicable(state)){
+   						if (CategoricalState.isLowerCase(state) || CategoricalState.isUnassigned(state)) {  //counts against
+   							selectCells(ic, it, 1);
+   							found = true;
+   							if (goodToHere>0){
+   								selectCells(ic+1, it, goodToHere);
+   								goodToHere = 0;
+   							}
+   						}
+   						else {
+   							goodToHere++;
+   							if (goodToHere>=goodInARow)
+   								done = true;
+   						}
+   					}
+   				}
+   			}
+   			if (!found)
+   				discreetAlert( "No lowercase ends were found to select");
+			table.repaintAll();
+   		}
+   	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Select Lowercase Ends";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Selects ends of a DNA sequence up to the first block of N sites in a row with uppercase (confident) symbols (the user chooses N).  Assuming that lowercase letters are used for less certain base calls, this can be used to select and then trim (by painting with gaps) poorly-sequenced terminal regions." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/MaintainClipMatch/MaintainClipMatch.java b/Source/mesquite/molec/MaintainClipMatch/MaintainClipMatch.java
new file mode 100644
index 0000000..b196bf4
--- /dev/null
+++ b/Source/mesquite/molec/MaintainClipMatch/MaintainClipMatch.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.MaintainClipMatch;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+/* ======================================================================== *
+
+*new in 1. 06*
+
+/* ======================================================================== */
+public class MaintainClipMatch extends MaintainSequenceMatch {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	public String getSequence() {
+   		String sequence = null;
+		 //  GET SEQUENCE FROM CLIPBOARD
+		Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+		Transferable t = clip.getContents(this);
+		try {
+			sequence = (String)t.getTransferData(DataFlavor.stringFlavor);
+			
+		}
+		catch(Exception e){
+			e.printStackTrace();
+		}
+		if (sequence == null)
+			return null;
+		sequence = StringUtil.stripWhitespace(sequence);
+		return sequence;
+   	}
+	public String getMessage(){
+		if (getTaxonNumber()<0)
+			return "No taxon has been selected for " + getName();
+		if (getSearchSequence() == null)
+			return "No text in clipboard";
+		if (getSequenceFound())
+			return "Showing this text from clipboard in \"" + getTaxonName() + "\": ";
+		return "Text from clipboard not found in \"" + getTaxonName() + "\": ";
+	}
+   	 
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Maintain Clipboard Match";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Finds the first occurrence of the sequence in  the clipboard, within a designated taxon, and maintains that match as the clipboard changes." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/ManageCodeSets/ManageCodeSets.java b/Source/mesquite/molec/ManageCodeSets/ManageCodeSets.java
new file mode 100644
index 0000000..08fa918
--- /dev/null
+++ b/Source/mesquite/molec/ManageCodeSets/ManageCodeSets.java
@@ -0,0 +1,150 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.ManageCodeSets;
+/*~~  */
+
+
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class ManageCodeSets extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.molec.CodesetList.CodesetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public Class getElementClass(){
+		return GenCodeModelSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Genetic Code Set";
+	}
+	public String lowerCaseTypeName(){
+		return "genetic code set";
+	}
+	public String nexusToken(){
+		return "CODESET";
+	}
+	public String alternativeNexusToken(){
+		return "GENCODESET";
+	}
+	public Object getSpecification(String token){
+		return getProject().getCharacterModel((token));
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof GenCodeModelSet) || !(specification instanceof CharacterModel))
+			return;
+		ObjectSpecsSet sS = (ObjectSpecsSet)specsSet;
+		sS.setProperty(specification,ic);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		CharacterModel defaultModel =  data.getDefaultModel("GeneticCode");
+ 		return new GenCodeModelSet(name, data.getNumChars(), defaultModel, data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("CODONS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("CODONS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof GenCodeModelSet))
+			return null;
+		ModelSet modelSet = (ModelSet)specsSet;
+			String s= "";
+			if (modelSet !=null && (modelSet.getFile()==file || (modelSet.getFile()==null && data.getFile()==file))) {
+				String sT = " ";
+				boolean firstTime = true;
+				Enumeration enumeration = file.getProject().getCharacterModels().elements();
+				while (enumeration.hasMoreElements()){
+					Object obj = enumeration.nextElement();
+					CharacterModel cm = (CharacterModel)obj;
+					String q = ListableVector.getListOfMatches(modelSet.getModels(), cm, CharacterStates.toExternal(0));
+					if (q != null) {
+						if (!firstTime)
+							sT += ", ";
+						sT += StringUtil.tokenize(cm.getNEXUSName()) + ": " + q ;
+						firstTime = false;
+					}
+				}
+				if (!StringUtil.blank(sT)) {
+					s+= "\tCODESET " ;
+					if (isCurrent)
+						s += "* ";
+					s+= StringUtil.tokenize(modelSet.getName()) + " ";
+					if (writeLinkWithCharacterMatrixName(file, data))
+						s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+					s+= "  = "+  sT + ";" + StringUtil.lineEnding();
+				}
+			}
+			return s;
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TypesetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public boolean isSubstantive() {
+		return false;
+   	 }
+    		/*.................................................................................................................*/
+    	 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    	 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    	 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    	    	public int getVersionOfFirstRelease(){
+    	    		return 110;  
+    	    	}
+    	    	/*.................................................................................................................*/
+    	    	public boolean isPrerelease(){
+    	    		return true;
+    	    	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage genetic code sets";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) genetic code sets (CODESETs)." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class TypesetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("CODONS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && commandName.equalsIgnoreCase("CODESET"));
+	}
+}
+
+
diff --git a/Source/mesquite/molec/MatchingSequence/MatchingSequence.java b/Source/mesquite/molec/MatchingSequence/MatchingSequence.java
new file mode 100644
index 0000000..20746e5
--- /dev/null
+++ b/Source/mesquite/molec/MatchingSequence/MatchingSequence.java
@@ -0,0 +1,221 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.MatchingSequence;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+import java.awt.event.*;
+/* ======================================================================== *
+
+*new in 1.05*
+
+/* ======================================================================== */
+public class MatchingSequence extends FindSequenceCriterionG {
+	String sequence = null;
+	String sequenceR = null;
+	String sequenceC = null;
+	String sequenceRC = null;
+	int numMismatch = 0;
+	boolean preferMinimal;
+	boolean asIs = true;
+	boolean reverse = false;
+	boolean complement = false;
+	boolean reverseComplement = false;
+	boolean findAll = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean showOptions(boolean findAll, CharacterData data, MesquiteTable table){
+	
+			MesquiteInteger buttonPressed = new MesquiteInteger(1);
+			ExtensibleDialog findDialog = new ExtensibleDialog(containerOfModule(), "Find Sequence",buttonPressed);
+			findDialog.addLargeOrSmallTextLabel ("Search for this sequence");
+			String s = sequence;
+			if (sequence == null)
+				s = "";
+			TextArea seq = findDialog.addTextArea(s, 3, 60, null);
+			
+			IntegerField nM = findDialog.addIntegerField("Number of allowed mismatches", numMismatch, 5);
+			Checkbox preferMinimalCB = null;
+			if (!findAll)
+				preferMinimalCB = findDialog.addCheckBox("Prefer minimal mismatches", preferMinimal);
+			else
+				preferMinimal = false;
+			Checkbox ai = findDialog.addCheckBox("Search for sequence as is", asIs);
+			Checkbox rc = findDialog.addCheckBox("Search for reverse complement", reverseComplement);
+			Checkbox r = findDialog.addCheckBox("Search for reverse", reverse);
+			Checkbox c = findDialog.addCheckBox("Search for complement", complement);
+			findDialog.setDefaultComponent(seq);
+			findDialog.completeAndShowDialog("OK","Cancel",null,"OK");
+			
+			if (buttonPressed.getValue()==0) {
+				this.findAll = findAll;
+				sequence = seq.getText();
+				sequence = StringUtil.stripWhitespace(sequence);
+				sequence = StringUtil.delete(sequence, '-');
+				if (sequence != null && sequence.length()>0 && nM.isValidInteger()){
+					if (!findAll)
+						preferMinimal = preferMinimalCB.getState();
+					numMismatch = nM.getValue();
+					sequenceR = DNAData.reverseString(sequence);
+					sequenceC = DNAData.complementString(sequence);
+					sequenceRC = DNAData.reverseString(sequenceC);
+					reverseComplement = rc.getState();
+					complement = c.getState();
+					asIs = ai.getState();
+					reverse = r.getState();
+				}
+				else sequence = null;
+				
+				findDialog.dispose();
+			}
+			else
+				return false;
+			if (sequence == null)
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	public boolean findNext(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+			if (!preferMinimal) {
+				if (findNext(data, table, sequence, numMismatch, charFound, length, taxonFound)){
+	   				if (!findAll)
+	   					logln("Sequence match found starting at site " + (charFound.getValue()+1) + " for taxon " + (taxonFound.getValue()+1));
+					return true;
+				}
+				return false;
+			}
+			else for (int nM = 0; nM<= numMismatch; nM++) {
+	   				if (findNext(data, table, sequence, nM, charFound, length, taxonFound)){
+		   				if (!findAll)
+		   					logln("Sequence match found allowing " + nM + " mismatches starting at site " + (charFound.getValue()+1) + " for taxon " + (taxonFound.getValue()+1));
+	   					return true;
+	   				}
+
+   			}
+   			return false;
+   		
+   	}
+/**/
+
+	int firstTaxon = 0;
+	int firstChar = 0;
+   	boolean findNext(CharacterData data, MesquiteTable table, String sequence, int numMismatch, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+  			length.setValue(0);
+  			firstTaxon = taxonFound.getValue();
+  			firstChar = charFound.getValue();
+			for (int it = firstTaxon; it< data.getNumTaxa(); it++){
+				CommandRecord.tick("Searching taxon " + data.getTaxa().getTaxonName(it));
+	   			for (int ic = firstChar; ic< data.getNumChars(); ic++) {
+	   				int extra = 0;
+	   				boolean found = false;
+	   				if (asIs && (extra = sequencesMatch(data, table,it, ic, sequence, numMismatch))>=0)  // v 1. 12 this had been greater than and thus would miss exact matches
+	   					found = true;
+   					else if (complement && (extra = sequencesMatch(data, table, it, ic, sequenceC, numMismatch))>=0)
+   						found = true;
+   					else if (complement && (extra = sequencesMatch(data, table,it, ic, sequenceR, numMismatch))>=0)
+   						found = true;
+   					else if (reverseComplement && (extra = sequencesMatch(data,table, it, ic, sequenceRC, numMismatch))>=0)
+   						found = true;
+   					
+   					
+   					if (found) {
+  						charFound.setValue(ic);
+  						taxonFound.setValue(it);
+				   		for (int i = 0; i<extra + sequence.length(); i++) 
+				   			table.selectCell(ic + i, it);
+						
+  						length.setValue(extra + sequence.length());
+  						
+   						return true;
+   					}
+   				}
+   			}
+   			return false;
+   		
+   	}
+	/*.................................................................................................................*/
+   	//-1 if not match, 0 or positive for number of extras if match
+   	int sequencesMatch(CharacterData data, MesquiteTable table, int it, int checkChar, String sequence, int numMismatch) {
+   		if (sequence == null || data == null || table == null)
+   			return -1;
+   		int length = sequence.length();
+   		if (checkChar + (length)>=data.getNumChars()){ //would extend past end of sequence; go to next taxon
+			firstTaxon++;
+			if (firstTaxon>= data.getNumTaxa())
+				firstTaxon = 0;
+			firstChar = 0;
+			return -1;
+   		}
+   		int mismatches = 0;
+   		int extra = 0;
+   		for (int site= 0; site < length; site++){
+   			String cell = null;
+   			while (data.isInapplicable(site+checkChar+extra, it) && site+checkChar+extra<data.getNumChars())
+   				extra++;
+   			if (length+checkChar+extra>=data.getNumChars()){//would extend past end of sequence
+				firstTaxon++;
+				if (firstTaxon>= data.getNumTaxa())
+					firstTaxon = 0;
+				firstChar = 0;
+   				return -1;
+   			}
+   			cell = table.getMatrixText(site+checkChar+extra, it);
+   			if (cell != null && !cell.equalsIgnoreCase(String.valueOf(sequence.charAt(site)))) {
+   				mismatches++;
+   				if (mismatches>numMismatch){
+	   				firstChar++;
+   					return -1;
+   				}
+   			}
+   		}
+	   	firstChar++;
+   		return extra;
+   		
+   	}
+
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Matching Sequence";
+	 }
+		/*.................................................................................................................*/
+	 public String getNameForMenuItem() {
+	return "Matching Sequence...";
+	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Finds the next occurrence of a sequence in a matrix of molecular data.  Allows a certain number of mismatches." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/MeanValueLinked/MeanValueLinked.java b/Source/mesquite/molec/MeanValueLinked/MeanValueLinked.java
new file mode 100644
index 0000000..f3eccac
--- /dev/null
+++ b/Source/mesquite/molec/MeanValueLinked/MeanValueLinked.java
@@ -0,0 +1,183 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.MeanValueLinked; 
+/*~~  */
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+
+public class MeanValueLinked extends NumberForCharacter implements NumberForCharacterIncr, NumForCharTreeIndep {   //CHANGE CLASS NAME TO WHAT YOU WANT and use same name for package (see above)
+	boolean warnedOnce = false;
+	int item = 0;
+	ContinuousData linkedData;
+	/*.................................................................................................................*/
+	/** a method called when the module is started up.  You can put initialization stuff here*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		/*if (condition !=null && condition!= ContinuousData.class && condition!=ContinuousState.class) {
+  	 		if (!MesquiteThread.isScripting()) alert("Mean Value of Character (Linked) could not start because it can be used only for continuous-valued characters");
+			return false;
+ 		}*/
+ 		return true;
+  	 }
+  	 
+   	 public void endJob() {
+   		if (linkedData!=null) linkedData.removeListener(this);
+   	 	super.endJob();
+   	 }
+  	 
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		if (obj == linkedData)
+			parametersChanged(notification);
+	}
+ 	public void setCurrent(long i){ //SHOULD NOT notify (e.g., parametersChanged)
+ 		item = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return item;
+ 	}
+ 	public String getItemTypeName(){
+ 		return "Item";
+ 	}
+ 	public long getMin(){
+ 		return 0;
+ 	}
+ 	public long getMax(){
+ 		if (linkedData !=null)
+ 			return linkedData.getNumItems();
+ 		return 0;
+ 	}
+ 	public long toInternal(long i){ //return whether 0 based or 1 based counting
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+   	boolean first = true;
+   	ContinuousDistribution getLinkedContinuousDistribution(Vector linked, int ic){
+   		linkedData = null;
+   		for (int i=0; i<linked.size(); i++){
+   			//TODO: some means to choose which linked if more than one
+   			CharacterData data = (CharacterData)linked.elementAt(i);
+   			if (data instanceof ContinuousData){
+   				if (linkedData!=null && linkedData!=data)
+					linkedData.removeListener(this);
+     				if (linkedData!=data)
+					data.addListener(this);
+ 				linkedData = (ContinuousData)data;
+   				return (ContinuousDistribution)data.getCharacterDistribution(ic);
+   			}
+   		}
+   		if (first)
+   			alert("No linked matrix was found.  The calculations could not be completed");
+   		first = false;
+   		return null;
+   	}
+	/*.................................................................................................................*/
+	/** the method that other modules call to tell this one to calculate the number for the character.  Note that the result is not immediately
+	returned, but rather is remembered and returned when getNumber is called (this requires care in use!; perhaps should be redesigned)*/
+	public  void calculateNumber(CharacterDistribution origStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (origStates==null ||  origStates.getParentData()==null || !MesquiteInteger.isNonNegative(origStates.getParentCharacter())){
+			linkedData = null;
+			result.setToUnassigned();
+		}
+		else {
+			CharacterData origData = origStates.getParentData();
+			int ic = origStates.getParentCharacter();
+			Vector linked = origData.getDataLinkages();
+			ContinuousDistribution linkedStates = getLinkedContinuousDistribution(linked, ic);
+			if (linkedStates==null)
+				result.setToUnassigned();
+			else if  (!(linkedStates instanceof ContinuousDistribution)){
+				String s = "Mean value of character can be calculated only for Continuous characters";
+				if (!warnedOnce)
+					discreetAlert(s);
+				warnedOnce = true;
+				result.setToUnassigned();
+				if (resultString != null)
+					resultString.setValue(s);
+			}
+			else {
+				warnedOnce = false;
+				ContinuousDistribution cStates = (ContinuousDistribution)linkedStates;
+				int numtaxa = cStates.getNumTaxa();
+				double sum= 0.0;
+				int n=0;
+				for (int i=0; i<numtaxa; i++){
+					double s = cStates.getState (i, item);
+					if (MesquiteDouble.isCombinable(s)) {
+						sum += s;
+						n++;
+					}
+				}
+				if (n==0)
+					result.setToUnassigned();
+				else
+					result.setValue(sum/n);
+			}
+		}
+		if (resultString!=null)
+			resultString.setValue("Mean value of linked character: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+		if (linkedData==null) {
+			discreetAlert("Sorry, no linked matrix was found.  The module \"" + getName() + "\" will quit.");
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	/** this method is called for a bit of an explanation of the number calculated*/
+    	 public String getParameters() {
+    	 	String s = "Linked matrix: ";
+    	 	if (linkedData!=null && linkedData.getItemName(item) !=null){
+			s+= linkedData.getName();
+    	 		if (linkedData!=null && linkedData.getItemName(item) !=null)
+				s+= "; item " + linkedData.getItemName(item);
+
+		}
+		return s;
+
+   	 }
+   	 
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** name of this module as it appears in menus, etc.*/
+    	 public String getName() {
+		return "Mean value of character (linked matrix)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the mean observed trait for continuous character in a linked matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/molec/MissingToGaps/MissingToGaps.java b/Source/mesquite/molec/MissingToGaps/MissingToGaps.java
new file mode 100644
index 0000000..f8f09bf
--- /dev/null
+++ b/Source/mesquite/molec/MissingToGaps/MissingToGaps.java
@@ -0,0 +1,76 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.MissingToGaps;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MissingToGaps extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numCellsAltered=MesquiteLong.unassigned;
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+		this.table = table;
+		if (!(data instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Can use " + getName() + " only on categorical data");
+			return false;
+		}
+		return alterContentOfCells(data,table, undoReference);
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		CategoricalData data = (CategoricalData)ddata;
+		if (data.isUnassigned(ic, it)) {
+			data.setState(ic, it, CategoricalState.inapplicable);
+			if (!MesquiteLong.isCombinable(numCellsAltered))
+				numCellsAltered = 0;
+			numCellsAltered++;
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Missing to Gaps";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts missing data to gaps in selected region." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/NCBIBlaster/NCBIBlaster.java b/Source/mesquite/molec/NCBIBlaster/NCBIBlaster.java
new file mode 100644
index 0000000..cffcb63
--- /dev/null
+++ b/Source/mesquite/molec/NCBIBlaster/NCBIBlaster.java
@@ -0,0 +1,72 @@
+package mesquite.molec.NCBIBlaster;
+
+import mesquite.categ.lib.DNAData;
+import mesquite.lib.*;
+import mesquite.molec.lib.BLASTResults;
+import mesquite.molec.lib.Blaster;
+import mesquite.molec.lib.NCBIUtil;
+
+public class NCBIBlaster extends Blaster {
+	MesquiteTimer timer = new MesquiteTimer();
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		timer.start();
+		return true;
+
+	}
+
+	public boolean initialize() {
+		return true;
+	}
+	
+	public  int getUpperLimitMaxHits(){
+		return 40;
+	}
+
+	/*.................................................................................................................*/
+	public String getDatabaseName () {
+		return "NCBI GenBank";
+	}
+
+	public void blastForMatches(String blastType, String sequenceName, String sequence, boolean isNucleotides, int numHits, int maxTime, double eValueCutoff, int wordSize, StringBuffer blastResponse, boolean writeCommand) {
+		timer.timeSinceLast();
+		NCBIUtil.blastForMatches(blastType, sequenceName, sequence, isNucleotides, numHits, 300, eValueCutoff, wordSize, blastResponse);
+		logln("BLAST completed in " +timer.timeSinceLastInSeconds()+" seconds");
+	}
+
+	public String getFastaFromIDs(String[] idList, boolean isNucleotides, StringBuffer fastaBlastResults) {
+		return NCBIUtil.fetchGenBankSequencesFromIDs(idList,  isNucleotides, null, false,  fastaBlastResults,  null);
+	}
+	
+	/*.................................................................................................................*/
+	public  String getTaxonomyFromID(String id, boolean isNucleotides, boolean writeLog, StringBuffer report){
+		 return NCBIUtil.fetchTaxonomyFromSequenceID(id, isNucleotides, writeLog, report);
+	}
+
+
+	/*.................................................................................................................*/
+	public  void postProcessingCleanup(BLASTResults blastResult){
+		blastResult.setIDFromElement("|", 2);
+	}
+
+	public  String[] getNucleotideIDsfromProteinIDs(String[] ID){
+		ID = NCBIUtil.cleanUpID(ID);
+		return NCBIUtil.getNucIDsFromProtIDs(ID);
+	}
+
+
+	public boolean isPrerelease() {
+		return false;
+	}
+
+
+	public String getName() {
+		return "BLAST NCBI GenBank Server";
+	}
+
+	public String getExplanation() {
+		return "BLASTs the NCBI GenBank server at NIH";
+	}
+
+
+}
diff --git a/Source/mesquite/molec/NucleotideComplement/NucleotideComplement.java b/Source/mesquite/molec/NucleotideComplement/NucleotideComplement.java
new file mode 100644
index 0000000..0983dd5
--- /dev/null
+++ b/Source/mesquite/molec/NucleotideComplement/NucleotideComplement.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.NucleotideComplement;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class NucleotideComplement extends DNADataAlterer {
+	MesquiteTable table;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+ 	/*.................................................................................................................*/
+  	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+ 			if (data == null)
+ 				return false;
+ 			if (!(data instanceof DNAData)){
+				MesquiteMessage.warnProgrammer("Attempt to complement non-DNA data");
+				return false;
+			}
+			return alterContentOfCells(data,table, undoReference);
+   	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+			if (!(ddata instanceof DNAData))
+				return;
+ 		
+		((DNAData)ddata).complement(ic, it);
+	}
+	
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Nucleotide Complement";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters nucleotide data to its complement." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/NumInternalGapsMatrix/NumInternalGapsMatrix.java b/Source/mesquite/molec/NumInternalGapsMatrix/NumInternalGapsMatrix.java
new file mode 100644
index 0000000..f0925b3
--- /dev/null
+++ b/Source/mesquite/molec/NumInternalGapsMatrix/NumInternalGapsMatrix.java
@@ -0,0 +1,78 @@
+package mesquite.molec.NumInternalGapsMatrix;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class NumInternalGapsMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+
+		long valid = 0;
+		long total = 0;
+		CharacterData parentData = data.getParentData();
+		if (parentData == null){
+			if (resultString != null)
+				resultString.setValue("Number of internal gaps can be calculated only for stored matrices");
+			return;
+		}
+		int numTaxa = parentData.getNumTaxa();
+		int numChars = parentData.getNumChars();
+
+		int confirmedInternal = 0;
+		for (int it=0; it<numTaxa; it++){
+			boolean stateFound = false;
+			int countGaps = 0;
+					
+			for (int ic=0; ic<numChars; ic++){
+				if (parentData.isInapplicable(ic,it)){
+					if (stateFound)  //to the right of sequence, just possibly an internal gap
+						countGaps++;
+				}
+				else {
+					stateFound = true;
+					if (countGaps >0){ // some gap counting accumulated; consider them confirmed as internal
+						confirmedInternal += countGaps;
+						countGaps = 0;
+					}
+				}
+				total++;
+			}
+		}
+		if (confirmedInternal>0) {
+			result.setValue(confirmedInternal); 
+		}  else
+			result.setValue(0.0); 
+
+		if (resultString!=null) {
+			resultString.setValue("Number of internal gaps: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+
+	public boolean isPrerelease (){
+		return false;
+	}
+
+	public String getName() {
+		return "Number of Internal Gaps in Matrix";
+	} 
+
+	public String getExplanation(){
+		return "Calculates the number of internal gaps in the matrix.";
+	} 
+
+} 
diff --git a/Source/mesquite/molec/NumLowerCase/NumLowerCase.java b/Source/mesquite/molec/NumLowerCase/NumLowerCase.java
new file mode 100644
index 0000000..9826883
--- /dev/null
+++ b/Source/mesquite/molec/NumLowerCase/NumLowerCase.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.NumLowerCase; 
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public class NumLowerCase extends NumberForCharAndTaxon {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public void initialize(CharacterData data){
+	}
+	public void calculateNumber(CharacterData data, int ic, int it, MesquiteNumber result, MesquiteString resultString){
+		if (result == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (data == null || !(data instanceof CategoricalData))
+			return;
+
+
+		CategoricalData dData = (CategoricalData)data;
+		if (CategoricalState.isLowerCase( dData.getStateRaw(ic, it)))
+			result.setValue(1);
+		else
+			result.setValue(0);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Lower Case";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Returns 1 if state symbol is a lower case letter.";
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/molec/NumStopCodonsMatrix/NumStopCodonsMatrix.java b/Source/mesquite/molec/NumStopCodonsMatrix/NumStopCodonsMatrix.java
new file mode 100644
index 0000000..9f0e55d
--- /dev/null
+++ b/Source/mesquite/molec/NumStopCodonsMatrix/NumStopCodonsMatrix.java
@@ -0,0 +1,73 @@
+package mesquite.molec.NumStopCodonsMatrix;
+
+
+import mesquite.categ.lib.DNAData;
+import mesquite.categ.lib.ProteinData;
+import mesquite.categ.lib.RequiresAnyDNAData;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+public class NumStopCodonsMatrix extends NumberForMatrix {
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	} 
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from happening at inopportune times (e.p., while a long chart calculation is in mid-progress*/
+	public void initialize(MCharactersDistribution data) {
+	} 
+
+	public void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || data == null)
+			return;
+		clearResultAndLastResult(result);
+
+		CharacterData parentData = data.getParentData();
+		if (parentData == null){
+			if (resultString != null)
+				resultString.setValue("Number of stop codons can be calculated only for stored matrices");
+			return;
+		}
+		if (!(parentData instanceof DNAData)){
+			if (resultString != null)
+				resultString.setValue("Number of stop codons can be calculated only for DNA matrices");
+			return;
+		}
+		DNAData dnaData = (DNAData)parentData;
+		int numTaxa = parentData.getNumTaxa();
+		
+		int count = 0;
+		for (int it=0; it<numTaxa; it++)
+			count += dnaData.getAminoAcidNumbers(it,ProteinData.TER, false);
+
+		if (count>0) {
+			result.setValue(count); 
+		}  else
+			result.setValue(0.0); 
+
+		if (resultString!=null) {
+			resultString.setValue("Number of stop codons: " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	} 
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	public boolean isPrerelease (){
+		return false;
+	}
+
+	public String getName() {
+		return "Number of Stop Codons in Matrix";
+	} 
+
+	public String getExplanation(){
+		return "Calculates the number of stop codons in the matrix.";
+	} 
+
+} 
diff --git a/Source/mesquite/molec/NumberPolyInTaxon/NumberPolyInTaxon.java b/Source/mesquite/molec/NumberPolyInTaxon/NumberPolyInTaxon.java
new file mode 100644
index 0000000..bed9b4c
--- /dev/null
+++ b/Source/mesquite/molec/NumberPolyInTaxon/NumberPolyInTaxon.java
@@ -0,0 +1,140 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.NumberPolyInTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class NumberPolyInTaxon extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	/*.................................................................................................................*/
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, CategoricalState.class, "Source of character matrix (for proportion missing)"); 
+ 		if (matrixSourceTask==null)
+ 			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		currentTaxa = taxa;
+   		matrixSourceTask.initialize(currentTaxa);
+   	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		if (numChars != 0) {
+			CategoricalState cs = null;
+			int count = 0;
+			int tot = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = (CategoricalState)observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable()) {
+						tot++;
+						if (CategoricalState.hasMultipleStates(cs.getValue()))
+							count++;
+					}
+				}
+				else
+					charExc++;
+			}
+			result.setValue(count);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+		
+		if (resultString!=null)
+			resultString.setValue("Number of polymorphisms/partial uncertainties in matrix "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	observedStates = null;
+   	 	super.employeeParametersChanged(employee, source, notification);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Multistate sites in taxon";  
+   	 }
+   	 
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+ 	public String getParameters() {
+ 		return "Number polymorphic/partially uncertain sites in taxon in matrix from: " + matrixSourceTask.getParameters();
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Reports the number of polymorphic/partially uncertain sites in a taxon for a data matrix." ;
+   	 }
+   	 
+}
+
+
+
+
diff --git a/Source/mesquite/molec/NumberStopsInTaxon/NumberStopsInTaxon.java b/Source/mesquite/molec/NumberStopsInTaxon/NumberStopsInTaxon.java
new file mode 100644
index 0000000..398a86d
--- /dev/null
+++ b/Source/mesquite/molec/NumberStopsInTaxon/NumberStopsInTaxon.java
@@ -0,0 +1,146 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.NumberStopsInTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class NumberStopsInTaxon extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of sequences.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	MesquiteBoolean countEvenIfOthers;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, DNAState.class, "Source of character matrix (for number of stops)"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		countEvenIfOthers = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Count for Ambiguous Sites even if Other AAs ", makeCommand("toggleCountEvenIfOthers", this), countEvenIfOthers);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		temp.addLine("toggleCountEvenIfOthers " + countEvenIfOthers.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not to count stops in regions with ambiguous nucleotides that imply a stop OR an amino acid", "[on; off]", commandName, "toggleCountEvenIfOthers")) {
+			countEvenIfOthers.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null || !(observedStates.getParentData() instanceof DNAData))
+			return;
+		DNAData data = (DNAData)observedStates.getParentData();
+		int count = data.getAminoAcidNumbers(it,ProteinData.TER,countEvenIfOthers.getValue());
+		if (result !=null)
+			result.setValue(count);
+		if (resultString!=null)
+			resultString.setValue("Number of stop codons in taxon "+ observedStates.getName() + ": " + count);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyDNAData();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of Stops";  
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public String getParameters() {
+		return "Number of stops coded by nucleotides in taxon in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the number of stops coded by nucleotides in a taxon for a data matrix." ;
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/molec/PercentGapsInTaxon/PercentGapsInTaxon.java b/Source/mesquite/molec/PercentGapsInTaxon/PercentGapsInTaxon.java
new file mode 100644
index 0000000..2492525
--- /dev/null
+++ b/Source/mesquite/molec/PercentGapsInTaxon/PercentGapsInTaxon.java
@@ -0,0 +1,192 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.PercentGapsInTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PercentGapsInTaxon extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	MesquiteBoolean countEdges;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of character matrix (for percent gaps)"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		countEdges = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Count Gaps at Edges", makeCommand("toggleEdges", this), countEdges);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		temp.addLine("toggleEdges " + countEdges.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not to count gaps at the edges of the matrix", "[on = cut; off]", commandName, "toggleEdges")) {
+			countEdges.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		boolean edges = countEdges.getValue();
+		if (numChars != 0) {
+			CharacterState cs = null;
+			boolean hitNonGap = edges;
+			int lastBase = numChars-1;
+			for (int ic=numChars-1; ic>=0 && !hitNonGap; ic--) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable()){
+						lastBase = ic;
+						hitNonGap = true;
+					}
+
+				}
+			}
+			numChars = lastBase +1;
+			int numGaps = 0;
+			int useNumChars = 0;
+			hitNonGap = edges;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+
+					if (cs.isInapplicable()){
+						if (hitNonGap || edges){
+							numGaps++;
+							useNumChars++;
+						}
+					}
+					else {
+						useNumChars++;
+						hitNonGap = true;
+					}
+
+				}
+			}
+
+			if (useNumChars == 0)
+				result.setValue(1.0);
+			else
+				result.setValue(((double)numGaps)/useNumChars);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+
+		if (resultString!=null)
+			resultString.setValue("Proportion of inapplicable codings (gaps) in matrix "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+			CharacterData d = observedStates.getParentData();
+			if (d != null && d.getName()!= null) {
+				String n =  d.getName();
+				if (n.length()>12)
+					n = n.substring(0, 12); 
+				return "Prop. Gaps (" + n + ")";
+			}
+		}
+		return "Prop. Gaps";  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion Gaps in Taxon";  
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public String getParameters() {
+		return "Proportion gaps in taxon in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the proportion of gaps (inapplicable codings) in a taxon for a data matrix." ;
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/molec/PercentLowerCase/PercentLowerCase.java b/Source/mesquite/molec/PercentLowerCase/PercentLowerCase.java
new file mode 100755
index 0000000..3993d39
--- /dev/null
+++ b/Source/mesquite/molec/PercentLowerCase/PercentLowerCase.java
@@ -0,0 +1,134 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.PercentLowerCase;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class PercentLowerCase extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, CategoricalState.class, "Source of character matrix (for percent lowercase)"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		if (!(data instanceof CategoricalData))
+			return;
+		CharacterState cs = null;
+		CategoricalData cData = (CategoricalData)data;
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		if (numChars != 0) {
+			int numLowerCase = 0;
+			int numAssigned = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable()){
+						numAssigned++;
+						long s = cData.getStateRaw(ic, it);
+						if (CategoricalState.isLowerCase(s))
+							numLowerCase++;
+
+					}
+				}
+			}
+			if (numAssigned>0)
+				result.setValue(((double)numLowerCase)/numAssigned);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+
+		if (resultString!=null)
+			resultString.setValue("Proportion of lower case codings in matrix "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion lower case codings in taxon";  
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public String getParameters() {
+		return "Proportion lower case codings in taxon in matrix from: " + matrixSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the percentage of lower case codings in a taxon for a data matrix." ;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/molec/PercentMissingInTaxon/PercentMissingInTaxon.java b/Source/mesquite/molec/PercentMissingInTaxon/PercentMissingInTaxon.java
new file mode 100644
index 0000000..33e08c6
--- /dev/null
+++ b/Source/mesquite/molec/PercentMissingInTaxon/PercentMissingInTaxon.java
@@ -0,0 +1,148 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.PercentMissingInTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PercentMissingInTaxon extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		matrixSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of character matrix (for " + getName() + ")"); 
+ 		if (matrixSourceTask==null)
+ 			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		currentTaxa = taxa;
+   		matrixSourceTask.initialize(currentTaxa);
+   	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		if (numChars != 0) {
+			CharacterState cs = null;
+			int numUnassigned = 0;
+			int tot = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable()) {
+						tot++;
+						if (cs.isUnassigned())
+							numUnassigned++;
+					}
+				}
+				else
+					charExc++;
+			}
+			if (tot == 0)
+				result.setValue(0);
+			else
+				result.setValue(((double)numUnassigned)/tot);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+		
+		if (resultString!=null)
+			resultString.setValue("Proportion of missing data in matrix "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	observedStates = null;
+   	 	super.employeeParametersChanged(employee, source, notification);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Proportion missing data in taxon";  
+   	 }
+    		/*.................................................................................................................*/
+    		public String getVeryShortName() {
+    			if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+    				CharacterData d = observedStates.getParentData();
+    				if (d != null && d.getName()!= null) {
+    					String n =  d.getName();
+    					if (n.length()>12)
+    						n = n.substring(0, 12); 
+    					return "Prop. Missing (" + n + ")";
+    				}
+    			}
+    			return "Prop. Missing";  
+    		}
+
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+ 	public String getParameters() {
+ 		return "Proportion missing data in taxon in matrix from: " + matrixSourceTask.getParameters();
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Reports the proportion of missing data in a taxon for a data matrix." ;
+   	 }
+   	 
+}
+
+
+
+
diff --git a/Source/mesquite/molec/PercentPolymorphic/PercentPolymorphic.java b/Source/mesquite/molec/PercentPolymorphic/PercentPolymorphic.java
new file mode 100644
index 0000000..70b67ba
--- /dev/null
+++ b/Source/mesquite/molec/PercentPolymorphic/PercentPolymorphic.java
@@ -0,0 +1,85 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.PercentPolymorphic;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class PercentPolymorphic extends NumberForCharacter  implements NumForCharTreeIndep { 
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || charStates == null)
+			return;
+		clearResultAndLastResult(result);
+		if (!(charStates instanceof CategoricalDistribution)){
+			if (resultString != null)
+				resultString.setValue("Polymorphism can be calculated only for categorical characters");
+			return;
+		}
+		CategoricalDistribution states = (CategoricalDistribution)charStates;
+		int numTaxa =states.getNumTaxa();
+		int tot = 0;
+		int count=0;
+		for (int it = 0; it<numTaxa; it++) {
+			long s = states.getState(it);
+			if (!CategoricalState.isInapplicable(s)){ //1. 06 changed to exclude inapplicable
+				tot++;
+				if (CategoricalState.hasMultipleStates(s))
+					count++;
+			}
+		}
+		resultNum = 1.0*count/tot;
+		result.setValue(resultNum);
+		if (resultString!=null)
+			resultString.setValue("Proportion Polymorphic: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion Polymorphic";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the proportion of taxa coded as polymorphic or partially uncertain in a character." ;
+	}
+
+}
+
diff --git a/Source/mesquite/molec/PropInternalGaps/PropInternalGaps.java b/Source/mesquite/molec/PropInternalGaps/PropInternalGaps.java
new file mode 100644
index 0000000..5b72b25
--- /dev/null
+++ b/Source/mesquite/molec/PropInternalGaps/PropInternalGaps.java
@@ -0,0 +1,125 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.PropInternalGaps;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PropInternalGaps extends NumberForCharacter  implements NumForCharTreeIndep { 
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		CharacterData data = charStates.getParentData();
+		int ic = charStates.getParentCharacter();
+		if (data == null || ic<0){
+			if (resultString != null)
+				resultString.setValue("Cannot calculate prop. internal gaps because no parent matrix associated with character");
+			return;
+		}
+
+		int numTaxa =charStates.getNumTaxa();
+		int tot = 0;
+		int count=0;
+		for (int it = 0; it<numTaxa; it++) {
+			if (!data.isInapplicable(ic, it)){
+				tot++;
+			}
+			else if (isInternalInapplicable(data, ic, it)){
+				count++;
+				//if (!charStates.isUnassigned(it))
+				tot++;
+			}
+		}
+		resultNum = 1.000*count/tot;
+		result.setValue(resultNum);
+		if (resultString!=null)
+			resultString.setValue("Proportion Internal Gaps: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	private boolean isInternalInapplicable(CharacterData data, int ic, int it){  //NOTE: there is now a method for this in CategoricalData
+		if (ic == 0 || ic == data.getNumChars()-1)
+			return false;
+		if (ic>data.getNumChars()/2){
+			if (clearRight(data, ic, it))
+				return false;
+			if (clearLeft(data, ic, it))
+				return false;
+		}
+		else {
+			if (clearLeft(data, ic, it))
+				return false;
+			if (clearRight(data, ic, it))
+				return false;
+		}
+		return true;
+
+	}
+	boolean clearLeft(CharacterData data, int ic, int it){
+		for (int i = ic-1; i>=0; i--)
+			if (!data.isInapplicable(i, it))
+				return false;
+		return true;
+	}
+	boolean clearRight(CharacterData data, int ic, int it){
+		for (int i = ic+1; i<data.getNumChars(); i++)
+			if (!data.isInapplicable(i, it))
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Proportion Internal Gaps";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the proportion of internal gaps (inapplicable codings) in a character across taxa.  Does not include missing (unassigned) data." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
+
diff --git a/Source/mesquite/molec/PropTerminalGaps/PropTerminalGaps.java b/Source/mesquite/molec/PropTerminalGaps/PropTerminalGaps.java
new file mode 100644
index 0000000..e4ec5a7
--- /dev/null
+++ b/Source/mesquite/molec/PropTerminalGaps/PropTerminalGaps.java
@@ -0,0 +1,121 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.PropTerminalGaps;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PropTerminalGaps extends NumberForCharacter  implements NumForCharTreeIndep { 
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		CharacterData data = charStates.getParentData();
+		int ic = charStates.getParentCharacter();
+		if (data == null || ic<0){
+			if (resultString != null)
+				resultString.setValue("Cannot calculate prop. terminal gaps because no parent matrix associated with character");
+			return;
+		}
+			
+		int numTaxa =charStates.getNumTaxa();
+		int tot = 0;
+		int count=0;
+		for (int it = 0; it<numTaxa; it++) {
+			tot++;
+			if (isTerminalInapplicable(data, ic, it))
+				count++;
+		}
+		resultNum = 1.000*count/tot;
+		result.setValue(resultNum);
+		if (resultString!=null)
+			resultString.setValue("Proportion Terminal Gaps: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	private boolean isTerminalInapplicable(CharacterData data, int ic, int it){
+		if (!data.isInapplicable(ic, it))
+			return false;
+		if (ic == 0 || ic == data.getNumChars()-1)
+			return true;
+		if (ic>data.getNumChars()/2){
+			if (clearRight(data, ic, it))
+				return true;
+			if (clearLeft(data, ic, it))
+				return true;
+		}
+		else {
+			if (clearLeft(data, ic, it))
+				return true;
+			if (clearRight(data, ic, it))
+				return true;
+		}
+		return false;
+		
+	}
+	boolean clearLeft(CharacterData data, int ic, int it){
+		for (int i = ic-1; i>=0; i--)
+			if (!data.isInapplicable(i, it))
+				return false;
+		return true;
+	}
+	boolean clearRight(CharacterData data, int ic, int it){
+		for (int i = ic+1; i<data.getNumChars(); i++)
+			if (!data.isInapplicable(i, it))
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Proportion Terminal Gaps";
+   	 }
+    		/*.................................................................................................................*/
+    		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    		public int getVersionOfFirstRelease(){
+    			return 200;  
+    		}
+	/*.................................................................................................................*/
+  	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the proportion of Terminal gaps (inapplicable codings) in a character across taxa.  Does not include missing (unassigned) data." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/molec/PropUnambigSites/PropUnambigSites.java b/Source/mesquite/molec/PropUnambigSites/PropUnambigSites.java
new file mode 100644
index 0000000..1b68dfc
--- /dev/null
+++ b/Source/mesquite/molec/PropUnambigSites/PropUnambigSites.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.PropUnambigSites;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PropUnambigSites extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, CategoricalState.class, "Source of character matrix (for " + getName() + ")"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		int charExc = 0;
+		if (numChars != 0) {
+			CharacterState cs = null;
+			int tot = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (incl == null || incl.isBitOn(ic)){
+					cs = observedStates.getCharacterState(cs, ic, it);
+					long s = ((CategoricalState)cs).getValue();
+					if (!CategoricalState.isInapplicable(s) && !CategoricalState.isUnassigned(s) && !CategoricalState.hasMultipleStates(s)) 
+						tot++;
+				}
+				else
+					charExc++;
+			}
+			result.setValue(tot);
+		}	
+		String exs = "";
+		if (charExc > 0)
+			exs = " (" + Integer.toString(charExc) + " characters excluded)";
+		
+		if (resultString!=null)
+			resultString.setValue("Number of Unambiguous Sites "+ observedStates.getName() + exs + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	observedStates = null;
+   	 	super.employeeParametersChanged(employee, source, notification);
+   	 }
+	
+ 	public String getParameters() {
+ 		return "Number of unambiguous sites in taxon in matrix from: " + matrixSourceTask.getParameters();
+   	 }	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of Unambiguous Sites in Sequence";  
+	}
+
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+			CharacterData d = observedStates.getParentData();
+			if (d != null && d.getName()!= null) {
+				String n =  d.getName();
+				if (n.length()>12)
+					n = n.substring(0, 12); 
+				return "Num. Unambig. (" + n + ")";
+			}
+		}
+		return "Num. Unambig. Sites";  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the number of unambiguous sites." ;
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/molec/ReverseComplement/ReverseComplement.java b/Source/mesquite/molec/ReverseComplement/ReverseComplement.java
new file mode 100644
index 0000000..2e96a21
--- /dev/null
+++ b/Source/mesquite/molec/ReverseComplement/ReverseComplement.java
@@ -0,0 +1,62 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.ReverseComplement;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+import mesquite.molec.lib.*;
+
+public class ReverseComplement extends DNADataAltererCon {
+
+
+	public boolean alterBlockInTaxon(CharacterData data, int icStart, int icEnd, int it) {
+		if (data==null || !(data instanceof DNAData))
+			return false;
+		((DNAData)data).reverseComplement(icStart, icEnd, it, false, true);
+		return true;
+	}
+	public boolean alterBlockOfCharacters(CharacterData data, int icStart, int icEnd) {
+		if (data==null || !(data instanceof DNAData))
+			return false;
+		
+		((DNAData)data).reverseComplement(icStart, icEnd, true);
+		return true;
+	}
+
+	public String getName() {
+		return "Reverse Complement";
+	}
+
+	 public String getExplanation() {
+ 		 return "Reverses the DNA sequence and complements the bases.";
+	}
+	public boolean requestPrimaryChoice() {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
diff --git a/Source/mesquite/molec/ReverseSequence/ReverseSequence.java b/Source/mesquite/molec/ReverseSequence/ReverseSequence.java
new file mode 100644
index 0000000..d9b64b3
--- /dev/null
+++ b/Source/mesquite/molec/ReverseSequence/ReverseSequence.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.ReverseSequence;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.categ.lib.MolecularData;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ReverseSequence extends DataAltererCon {
+
+	public boolean alterBlockInTaxon(CharacterData data, int icStart, int icEnd, int it) {
+		if (data==null)
+			return false; 
+
+		if (data instanceof MolecularData){
+			MolecularData mData = (MolecularData)data;
+			mData.reverse(icStart, icEnd, it, false, true);
+		}
+		else 
+			for (int i=0; i <= (icEnd-icStart)/2 && icStart+i< icEnd-i; i++) {  
+				data.tradeStatesBetweenCharacters(icStart+i, icEnd-i, it,true);
+			}
+
+		return true;
+	}
+
+	public boolean alterBlockOfCharacters(CharacterData data, int icStart, int icEnd) {
+		if (data==null)
+			return false; 
+		if (data instanceof MolecularData){
+			MolecularData mData = (MolecularData)data;
+			mData.reverse(icStart, icEnd, true);
+		}
+		else {
+			for (int it = 0; it< data.getNumTaxa(); it++)
+				for (int i=0; i <= (icEnd-icStart)/2 && icStart+i< icEnd-i; i++) {  
+					data.tradeStatesBetweenCharacters(icStart+i, icEnd-i, it,true);
+				}
+		}
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Reverse Sequence";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Alters data by reversing sequence of states." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/SequenceInfoEditor/SequenceInfoEditor.java b/Source/mesquite/molec/SequenceInfoEditor/SequenceInfoEditor.java
new file mode 100644
index 0000000..de11472
--- /dev/null
+++ b/Source/mesquite/molec/SequenceInfoEditor/SequenceInfoEditor.java
@@ -0,0 +1,283 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.molec.SequenceInfoEditor;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.charMatrices.lib.MatrixInfoExtraPanel;
+import mesquite.lib.table.*;
+
+public class SequenceInfoEditor extends MatrixInfoPanelAssistantI  {
+	SequenceInfoPanel panel;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*
+	public  Class getHireSubchoice(){
+		return NumberForTree.class;
+	}
+
+	/*.................................................................................................................*/
+	public MatrixInfoExtraPanel getPanel(ClosablePanelContainer container){
+		panel =  new SequenceInfoPanel(container, this);
+		return panel;
+	}
+
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+		}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("panelOpen " + panel.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the panel open", null, commandName, "panelOpen")) {
+			if (panel != null)
+				panel.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Sequence Information Editor";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Edits character state names within the editor info panel.";
+	}
+}
+/*===========================================*/
+class SequenceInfoPanel extends MatrixInfoExtraPanel  {
+	String message = null;
+	SequenceInfoEditor ownerModule;
+	NoteField infoArea;
+	CategoricalData cData;
+	Associable info;
+	NameReference siRef = NameReference.getNameReference("SequenceInfo");
+	public SequenceInfoPanel(ClosablePanelContainer container, SequenceInfoEditor ownerModule){
+		super(container, "Sequence Info");
+		infoArea = new NoteField(this);
+		currentHeight = 60 + MINHEIGHT;
+		setLayout(null);
+		add(infoArea);
+		infoArea.setVisible(true);
+		resetLocs();
+		this.ownerModule = ownerModule;
+		setOpen(false);
+	}
+	public boolean userExpandable(){
+		return true;
+	}
+	public void setMatrixAndTable(CharacterData data, MesquiteTable table){
+		super.setMatrixAndTable(data, table);
+		this.cData = (CategoricalData)data;
+		info = data.getTaxaInfo(true);
+		siRef = info.makeAssociatedObjects("SequenceInfo");
+		container.requestHeightChange(this);
+		repaint();
+	}
+	public void setCell(int ic, int it){
+		if (!isVisible())
+			return;
+		super.setCell(ic, it);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	private void adjustMessage(){
+		if (data == null)
+			infoArea.setText("", ic, it);
+		else if (it < 0 && ic < 0)
+			infoArea.setText("", ic, it);
+		else {
+			message = "";
+			if (it >= 0 && it < data.getNumTaxa()) {
+				Object o = info.getAssociatedObject(siRef, it);
+				if (o != null && o instanceof String){
+					infoArea.setText((String)o, ic, it);
+				}
+				else
+				infoArea.setText("", ic, it);
+			}
+			else {
+				infoArea.setText("", ic, it);
+			}
+		}
+	}
+
+	public void setOpen(boolean open){
+		infoArea.setVisible(open);
+		resetLocs();
+		super.setOpen(open);
+	}
+	void resetLocs(){
+		infoArea.setBounds(2, MINHEIGHT + 4, getWidth()-4, currentHeight- MINHEIGHT-4);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		resetLocs();
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		resetLocs();
+	}
+	public void enterText(NoteField n, String text, int rIC, int rIT, boolean warn){
+		if (data == null)
+			return;
+		else if (it < 0) {
+			if (warn)
+				infoArea.setText("A row must be touched or selected first to edit the sequence information");
+			return;
+		}
+		else {
+			if (rIT != it){
+				MesquiteMessage.warnProgrammer("rIT/it mismatch in seqinfopanel");
+				return;
+			}
+			info.setAssociatedObject(siRef, it, text);	
+		}
+	}
+	
+	boolean selectionInSingleRow(){
+		if (table.anyColumnNameSelected())
+			return false;
+		if (table.anyColumnSelected())
+			return false;
+
+		Dimension fC = table.getFirstTableCellSelected();
+		Dimension LC = table.getLastTableCellSelected();
+		int f = table.firstRowSelected();
+		int L = table.lastRowSelected();
+		if ( fC.height<0 && LC.height<0){
+			return (f>-1 && f==L);
+		}
+		else if (f<0 && L<0){
+			return (fC.height>-1 && fC.height == LC.height);
+		}
+		return  (f>-1 && f==L && f== fC.height && fC.height == LC.height);
+	}
+	public void cellEnter(int ic, int it){
+		// if a single column or cells within a single column are selected, then cut out
+		if (selectionInSingleRow())
+			return;
+		super.cellEnter(ic, it);
+	}
+	public void cellExit(int ic, int it){
+		if (selectionInSingleRow())
+			return;
+		super.cellExit(ic, it);
+
+	}
+
+
+}
+
+class NoteField extends TextArea implements FocusListener {
+	SequenceInfoPanel panel;
+	boolean somethingTyped;
+	int ic = -1;
+	int it= -1;
+
+	public NoteField(SequenceInfoPanel panel){
+		super("", 4, 40, TextArea.SCROLLBARS_NONE);
+		this.panel = panel;
+		setText("");
+		addKeyListener(new KListener(this));
+		addFocusListener(this);
+	}
+
+	public void setText(String s, int ic, int it){
+		setText(s);
+		this.ic = ic;
+		this.it = it;
+	}
+	public void focusGained(FocusEvent e){
+	}
+	public void focusLost(FocusEvent e){
+		
+		if (somethingTyped)
+			panel.enterText(this, getText(), ic, it, false);
+		somethingTyped = false;
+	}
+	class KListener extends KeyAdapter {
+		NoteField nf = null;
+		public KListener (NoteField nf){
+			super();
+			this.nf = nf;
+		}
+		public void keyPressed(KeyEvent e){
+			//Event queue
+			if (e.getKeyCode()== KeyEvent.VK_ENTER) {
+				if (somethingTyped){
+					String s = getText();
+					panel.enterText(nf, s, ic, it, true);
+					somethingTyped = false;
+					e.consume();
+					setSelectionStart(s.length());
+					setSelectionEnd(s.length());
+				}
+			}
+			else { 
+				somethingTyped=true;
+			}
+
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/molec/SequenceLength/SequenceLength.java b/Source/mesquite/molec/SequenceLength/SequenceLength.java
new file mode 100644
index 0000000..21fa75c
--- /dev/null
+++ b/Source/mesquite/molec/SequenceLength/SequenceLength.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.SequenceLength;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class SequenceLength extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of sequences.",
+		"The source of characters is arranged initially");
+	}
+	MatrixSourceCoord matrixSourceTask;
+	Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	MesquiteBoolean countExcluded = new MesquiteBoolean(false);
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, MolecularState.class, "Source of character matrix (for " + getName() + ")"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		addCheckMenuItem(null, "Count Excluded Characters", makeCommand("toggleCountExcluded",  this), countExcluded);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("toggleCountExcluded " + countExcluded.toOffOnString());
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		 if (checker.compare(this.getClass(), "Sets whether or not excluded characters are considered in the calculation", "[on or off]", commandName, "toggleCountExcluded")) {
+			boolean current = countExcluded.getValue();
+			countExcluded.toggleValue(parser.getFirstToken(arguments));
+			if (current!=countExcluded.getValue()) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		currentTaxa = taxa;
+		matrixSourceTask.initialize(currentTaxa);
+		observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+	}
+
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null)
+			return;
+		result.setToUnassigned();
+		clearResultAndLastResult(result);
+		Taxa taxa = taxon.getTaxa();
+		int it = taxa.whichTaxonNumber(taxon);
+		if (taxa != currentTaxa || observedStates == null ) {
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			currentTaxa = taxa;
+		}
+		if (observedStates==null)
+			return;
+		CharacterData data = observedStates.getParentData();
+		CharInclusionSet incl = null;
+		if (data !=null)
+			incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = observedStates.getNumChars();
+		if (numChars != 0) {
+			CharacterState cs = null;
+			int seqLen = 0;
+			for (int ic=0; ic<numChars; ic++) {
+				if (countExcluded.getValue() || (incl == null || incl.isBitOn(ic))){  // adjusted 2. 01 to consider inclusion  // added control in 3.0
+					cs = observedStates.getCharacterState(cs, ic, it);
+					if (!cs.isInapplicable())
+						seqLen++;
+				}
+			}
+			result.setValue(seqLen);
+		}	
+	
+		if (resultString!=null)
+			resultString.setValue("Length of sequence in matrix "+ observedStates.getName()  + ": " + result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		if (currentTaxa != null && observedStates == null)
+			observedStates = matrixSourceTask.getCurrentMatrix(currentTaxa);
+		if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+			CharacterData d = observedStates.getParentData();
+			if (d != null && d.getName()!= null) {
+				String n =  d.getName();
+				if (n.length()>12)
+					n = n.substring(0, 12); 
+				return "Seq.Length (" + n + ")";
+			}
+		}
+		return "Sequence Length";
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public String getParameters() {
+		String s="";
+		if (countExcluded.getValue())
+			s = "Excluded characters are counted.";
+		else
+			s="Excluded characters not counted.";
+		return "Sequence Length in matrix from: " + matrixSourceTask.getParameters() + ". " + s;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reports the length (total minus gaps) of a molecular sequence in a taxon." ;
+	}
+
+}
+
+
+
+
diff --git a/Source/mesquite/molec/SiteProperty/SiteProperty.java b/Source/mesquite/molec/SiteProperty/SiteProperty.java
new file mode 100644
index 0000000..3004330
--- /dev/null
+++ b/Source/mesquite/molec/SiteProperty/SiteProperty.java
@@ -0,0 +1,169 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.SiteProperty; 
+/*~~  */
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.ContinuousStateTest;
+import mesquite.molec.lib.*;
+
+
+public class SiteProperty extends NumberForCharacter implements NumForCharTreeIndep {   
+	boolean warnedOnce = false;
+	CategoricalDistribution cStates;
+	AAProperty propertyTask;
+	MesquiteString propertyTaskName;
+	/*.................................................................................................................*/
+	/** a method called when the module is started up.  You can put initialization stuff here*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null && condition!= ProteinData.class && condition!=ProteinState.class)
+			return sorry(getName() + " could not start because it works only with Protein data");
+		propertyTask = (AAProperty)hireEmployee(AAProperty.class, "Property of Amino Acid");
+		if (propertyTask == null)
+			return sorry(getName() + " couldn't start because no properties module was obtained.");
+ 		propertyTaskName = new MesquiteString();
+		if (numCompatibleModulesAvailable(AAProperty.class, condition, this)>0) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Amino Acid Property", makeCommand("setProperty", this), AAProperty.class);
+ 			mss.setSelected(propertyTaskName);
+		}
+ 		return true;
+  	 }
+  	 
+  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+ 	 	temp.addLine("setProperty ", propertyTask); 
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the module calculating the property", "[name of module]", commandName, "setProperty")) {
+    	 		AAProperty temp =   (AAProperty)replaceEmployee(AAProperty.class, arguments, "Property of Amino Acid", propertyTask);
+ 			if (temp!=null) {
+ 				propertyTask = temp;
+				propertyTaskName.setValue(propertyTask.getName());
+				parametersChanged();
+	 			return propertyTask;
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+    	 
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new ProteinStateTest();
+  	 //	return new ProteinStateTest();
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresProteinData();
+	}
+	/*.................................................................................................................*/
+	/** the method that other modules call to tell this one to calculate the number for the character.  Note that the result is not immediately
+	returned, but rather is remembered and returned when getNumber is called (this requires care in use!; perhaps should be redesigned)*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (charStates==null)
+			result.setToUnassigned();
+		else if  (!(charStates.getStateClass() == ProteinState.class)){
+			if (!warnedOnce)
+				discreetAlert( "Site properties can be calculated only for amino acid data");
+			warnedOnce = true;
+			result.setToUnassigned();
+		}
+		else {
+			warnedOnce = false;
+			cStates = (CategoricalDistribution)charStates;
+			int numtaxa = cStates.getNumTaxa();
+			double sum= 0.0;
+			int n=0;
+			for (int i=0; i<numtaxa; i++){
+				long s = cStates.getState (i);
+				double loc = 0;
+				int ns = 0;
+				for (int is=0; is<=ProteinState.maxProteinState; is++){
+					if (CategoricalState.isElement(s, is)) {
+						double d = propertyTask.getProperty(is);
+						if (MesquiteDouble.isCombinable(d)){
+							loc += d;
+							ns++;
+						}
+					}
+				}
+				if (ns!=0) {
+					sum+= loc/ns;
+					n++;
+				}
+			}
+			if (n==0)
+				result.setToUnassigned();
+			else
+				result.setValue(sum/n);
+		}
+		if (resultString!=null)
+			resultString.setValue("Site average for " + propertyTask.getName() + ": "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** name of this module as it appears in menus, etc.*/
+    	 public String getName() {
+		return "Protein Site Property";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameAndParameters() {
+		if (propertyTask == null)
+			return "Site Property";
+		else
+			return "Site Average for " + propertyTask.getName();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		if (propertyTask == null)
+			return "Site Property";
+		else
+			return propertyTask.getVeryShortName();
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the mean value of amino acid properties at a site across taxa." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/molec/StoredGenCodeModel/StoredGenCodeModel.java b/Source/mesquite/molec/StoredGenCodeModel/StoredGenCodeModel.java
new file mode 100644
index 0000000..d0dafe8
--- /dev/null
+++ b/Source/mesquite/molec/StoredGenCodeModel/StoredGenCodeModel.java
@@ -0,0 +1,219 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.StoredGenCodeModel;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+import mesquite.molec.lib.*;
+
+/* ======================================================================== */
+public class StoredGenCodeModel extends GenCodeModelSource {
+	MesquiteSubmenuSpec smenu;
+	GenCodeModel currentModel;
+	boolean initialized = false;
+	boolean responseSuppressed = false;
+	MesquiteString modelName;
+	Class currentStateClass = null;
+	int setModelNumber = MesquiteInteger.unassigned;
+	ModelCompatibilityInfo mci;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof Class)
+			currentStateClass = (Class)condition;
+		smenu = addSubmenu(null, "Stored Genetic Code", makeCommand("setModel", this), getProject().getCharacterModels());
+		mci = new GenCodeModelCompatInfo(currentStateClass);
+		smenu.setCompatibilityCheck(mci);
+		smenu.setListableFilter(WholeCharacterModel.class);
+		if ((GenCodeModel)getProject().getCharacterModel(mci, 0)==null)
+			return sorry("There are no suitable stored character models available");
+		modelName = new MesquiteString();
+		addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+		smenu.setList(getProject().getCharacterModels());
+		smenu.setSelected(modelName);
+
+		getProject().getCentralModelListener().addListener(this);//to listen for static changes to class of current model
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	GenCodeModel chooseModel(Class stateClass){
+		if (!MesquiteThread.isScripting()){
+			return (GenCodeModel)CharacterModel.chooseExistingCharacterModel(this, new GenCodeModelCompatInfo(stateClass), "Choose probability model (for " + getEmployer().getName() + ").  To make additional models, select New Character Model from the Characters menu.");
+		}
+		else
+			return (GenCodeModel)getProject().getCharacterModel(new GenCodeModelCompatInfo(stateClass), 0);
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (currentModel !=null && obj instanceof Class && ((Class)obj).isAssignableFrom(currentModel.getClass())) {
+			parametersChanged(notification);
+		}
+		else if (obj == currentModel) {
+			parametersChanged(notification);
+		}
+		super.changed(caller, obj, notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == currentModel) {
+			currentModel = null;
+			parametersChanged();
+		}
+	}
+
+	/** returns model for character ic in data */
+	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+		Class stateClass = currentStateClass;
+		if (data !=null) 
+			stateClass = data.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			currentStateClass = stateClass;
+			mci = new GenCodeModelCompatInfo(currentStateClass);
+			smenu.setCompatibilityCheck(mci);
+			resetContainingMenuBar();
+
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+	}
+	/** returns model for character */
+	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		Class stateClass = currentStateClass;
+		if (states !=null)
+			stateClass = states.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			currentStateClass = stateClass;
+			mci = new GenCodeModelCompatInfo(currentStateClass);
+			smenu.setCompatibilityCheck(mci);
+			resetContainingMenuBar();
+
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+	}
+	/*.................................................................................................................*/
+	boolean oneAtATime= false;
+	public void setOneCharacterAtATime(boolean chgbl){
+		oneAtATime = chgbl;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (currentModel==null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModel " + getProject().getWhichCharacterModel(mci, currentModel) + "   " + ParseUtil.tokenize(currentModel.getName()));  //TODO:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!should say which model
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the genetic code", "[number of model]", commandName, "setModel")) {
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			String name = ParseUtil.getToken(arguments, pos);
+			GenCodeModel model = null;
+			if (MesquiteInteger.isCombinable(whichModel))
+				model = (GenCodeModel)getProject().getCharacterModel(mci, whichModel);
+
+			if ((model !=null || !MesquiteInteger.isCombinable(whichModel)) && currentStateClass == null && name !=null && !(model.getName().equals(name))){ // not restricted state class; could be scripting without
+				model = (GenCodeModel)getProject().getCharacterModel(name);
+			}
+
+			if (model!=null) {
+				//if (currentModel!=null)
+				//	currentModel.removeListener(this);
+				currentModel = model;
+				modelName.setValue(currentModel.getName());
+				//currentModel.addListener(this);
+				parametersChanged();
+				return model;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+			String s = "";
+			if (currentModel == null)
+				s = "Sorry, no reference to the current model was found";
+			else
+				s = "The current model is \"" + currentModel.getName() + "\".\nExplanation: " + currentModel.getExplanation();
+			discreetAlert( s);
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (currentModel==null)
+			return "Model NULL";
+		return "Current model \"" + currentModel.getName();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stored Genetic Code";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies a user-specified genetic code, stored in the file." ;
+	}
+
+}
+
+class GenCodeModelCompatInfo extends ModelCompatibilityInfo {
+	public GenCodeModelCompatInfo(Class targetStateClass){
+		super(GenCodeModel.class, targetStateClass);
+	}
+	//obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa
+	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj instanceof DolloModel || obj instanceof IrreversibleModel) //since these can't yet be used in Mesquite calculations
+			return false;
+		return super.isCompatible(obj, project, prospectiveEmployer);
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/TargetSeqMatch/TargetSeqMatch.java b/Source/mesquite/molec/TargetSeqMatch/TargetSeqMatch.java
new file mode 100644
index 0000000..ff273bd
--- /dev/null
+++ b/Source/mesquite/molec/TargetSeqMatch/TargetSeqMatch.java
@@ -0,0 +1,78 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.TargetSeqMatch;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+/* ======================================================================== *
+
+*new in 1. 06*
+
+/* ======================================================================== */
+public class TargetSeqMatch extends MaintainSequenceMatch {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	public String getSequence() {
+   		return getSearchSequence();
+   	}
+	public String getMessage(){
+		if (getTaxonNumber()<0)
+			return "No taxon has been selected for " + getName();
+		if (StringUtil.blank(getSearchSequence()))
+			return "Enter text to search in \"" + getTaxonName() + "\": ";
+		if (getSequenceFound())
+			return "Showing this text in \"" + getTaxonName() + "\": ";
+		return "Text not found in \"" + getTaxonName() + "\": ";
+	}
+	public String getSearchSequence(){
+		
+		if (ledge == null)
+			return "";
+		else
+			return ledge.getText();
+	}
+   	 
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Maintain Target Match";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Finds the first occurrence of the sequence in  the text area below the matrix, within a designated taxon, and maintains that match as the text area changes." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/TaxaListHasData/TaxaListHasData.java b/Source/mesquite/molec/TaxaListHasData/TaxaListHasData.java
new file mode 100644
index 0000000..3b32df6
--- /dev/null
+++ b/Source/mesquite/molec/TaxaListHasData/TaxaListHasData.java
@@ -0,0 +1,683 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TaxaListHasData;
+/*~~  */
+
+
+import mesquite.categ.lib.MolecularData;
+import mesquite.categ.lib.MolecularState;
+import mesquite.lists.lib.*;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TaxaListHasData extends TaxonListAssistant  {
+	
+	Taxa taxa=null;
+	MesquiteTable table = null;
+	MatrixSourceCoord matrixSourceTask;
+	//Taxa currentTaxa = null;
+	MCharactersDistribution observedStates =null;
+	CharacterData data = null;
+	Associable tInfo = null;
+	static String localCopyDataClipboard = "";
+	static String localCopyDataTaxon = "";
+	static CharacterData localCopyData = null;
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Has Data in Matrix";
+	}
+	public String getExplanation() {
+		return "Indicates whether taxon has non-missing non-gap data in a given matrix." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of characters.",
+				"The source of characters is arranged initially");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		setSuppressEmployeeAutoRehiring(true);
+		matrixSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of character matrix (for " + getName() + ")"); 
+		if (matrixSourceTask==null)
+			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
+		//	addMenuItem("Delete Prepended Length", makeCommand("deletePrepended", this));  // for Wayne!!!!!!
+		//	addMenuItem("Delete *", makeCommand("deleteStar", this));  // for Wayne!!!!!!
+		addMenuItem("Delete Data For Selected Taxa", makeCommand("deleteData", this));
+		addMenuItem("Prepend Sequence Length", makeCommand("prependLength", this));
+		addMenuItem("Prepend Number of Non-missing Sites", makeCommand("prependNumSites", this));
+		addMenuItem("Delete Stored Annotation", makeCommand("deleteAnnotation", this));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
+ 	If false then is hired only once; second attempt fails.*/
+	public boolean canHireMoreThanOnce(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** endJob is called as a module is quitting; modules should put their clean up code here.*/
+	public void endJob() {
+		if (data != null)
+			data.removeListener(this);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource", matrixSourceTask);
+		return temp;
+	}
+
+	void captureCharacterDataFromObservedStates(){
+		if (observedStates ==null){
+			if (data != null)
+				data.removeListener(this);
+			data = null;
+		}
+		else {
+			CharacterData temp = observedStates.getParentData();
+			if (temp != data){
+				if (data != null)
+					data.removeListener(this);
+				if (temp != null)
+					temp.addListenerHighPriority(this);
+				data = temp;
+			}
+		}
+	}
+	public CharacterData getCharacterData(){
+		return data;
+	}
+
+
+	/* ................................................................................................................. */
+
+	public boolean clipBoardHasString() {
+
+		Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+		Transferable t = clip.getContents(this);
+		try {
+			String s = (String) t.getTransferData(DataFlavor.stringFlavor);
+			if (s != null) {
+				return true;
+			}
+		} catch (Exception e) {
+			MesquiteMessage.printStackTrace(e);
+		}
+		return false;
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean arrowTouchInRow(Graphics g, int ic, int x, int y, boolean doubleClick, int modifiers){
+		if (MesquiteEvent.rightClick(modifiers)) {
+			MesquitePopup popup = new MesquitePopup(table.getMatrixPanel());
+
+			String copyMenuText = "Copy ";
+			if (observedStates != null) {
+				CharacterData data = observedStates.getParentData();
+				if (data != null) {
+					copyMenuText += data.getName() + " Data";
+					copyMenuText += " [from " + data.getTaxa().getTaxonName(ic) + "]" ;
+					
+				}
+			}
+			MesquiteCommand mcCopy = makeCommand("copyData", this);
+			mcCopy.setDefaultArguments(""+ic);
+			MesquiteCheckMenuItem mCopyItem = new MesquiteCheckMenuItem(copyMenuText, this, mcCopy, null, null);
+			popup.add(mCopyItem);
+
+			String pasteMenuText = "Paste ";
+			if (StringUtil.notEmpty(localCopyDataClipboard) && localCopyData != null) {
+					pasteMenuText += localCopyData.getName() + " Data";
+					if (StringUtil.notEmpty(localCopyDataTaxon)) {
+						pasteMenuText += " [from " + localCopyDataTaxon + "] " ;
+					}
+			}
+			MesquiteCommand mcPaste = makeCommand("pasteData", this);  //only if something in clipboard
+			mcPaste.setDefaultArguments(""+ic);
+			MesquiteCheckMenuItem mPasteItem = new MesquiteCheckMenuItem(pasteMenuText, this, mcPaste, null, null);
+			mPasteItem.setEnabled(StringUtil.notEmpty(localCopyDataClipboard));
+			popup.add(mPasteItem);
+
+			MesquiteCommand mcDelete = makeCommand("deleteDataTouched", this);
+			mcDelete.setDefaultArguments(""+ic);
+			MesquiteCheckMenuItem mDeleteItem = new MesquiteCheckMenuItem("Delete Data", this, mcDelete, null, null);
+			popup.add(mDeleteItem);
+
+			popup.showPopup(x,y+18);
+
+			return true;
+		}
+		return false;
+	}
+
+
+
+	MesquiteInteger pos = new MesquiteInteger();
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Copies the data for selected taxon", null, commandName, "copyData")) {
+			if (observedStates == null)
+				return null;
+			CharacterData data = observedStates.getParentData();
+			if (data == null)
+				return null;
+			int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (MesquiteInteger.isCombinable(it)) {
+				StringBuffer sb = new StringBuffer();
+				data.copyDataFromRowIntoBuffer(it, sb);
+				if (StringUtil.notEmpty(sb.toString())) {
+					localCopyDataClipboard = sb.toString();
+					localCopyData = data;
+					localCopyDataTaxon= data.getTaxa().getTaxonName(it);
+				}
+				else {
+					localCopyDataClipboard = null;
+					localCopyData = null;
+					localCopyDataTaxon = null;
+				}
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Pastes the data for selected taxon", null, commandName, "pasteData")) {
+			if (observedStates == null)
+				return null;
+			CharacterData data = observedStates.getParentData();
+			if (data == null)
+				return null;
+			int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (MesquiteInteger.isCombinable(it) && StringUtil.notEmpty(localCopyDataClipboard)) {
+				data.pasteDataFromStringIntoTaxon(it, localCopyDataClipboard);
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Pastes the data for selected taxon", null, commandName, "deleteDataTouched")) {
+			if (observedStates == null)
+				return null;
+			CharacterData data = observedStates.getParentData();
+			if (data == null)
+				return null;
+			int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			Debugg.println("prepare to delete row: "+it);
+			if (MesquiteInteger.isCombinable(it)) {
+				if (!AlertDialog.query(containerOfModule(), "Delete Data?", "Are you sure you want to delete the data for taxon " +data.getTaxa().getTaxonName(it) + " in the matrix \"" + data.getName() + "\"", "No", "Yes")) {
+					zapData(data,it);
+				}
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Deletes the data for selected taxa", null, commandName, "deleteData")) {
+			if (observedStates == null)
+				return null;
+			captureCharacterDataFromObservedStates();
+			if (data == null)
+				return null;
+			if (!AlertDialog.query(containerOfModule(), "Delete Data?", "Are you sure you want to delete the data for these taxa in the matrix \"" + data.getName() + "\"", "No", "Yes"))
+				zapData(data);
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "deleteds () and anything between", null, commandName, "deletePrepended")) {
+			if (observedStates == null || taxa == null)
+				return null;
+			boolean anySelected = taxa.anySelected();
+			int myColumn = -1;
+			if (getEmployer() instanceof ListModule){
+
+				myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+				if (table != null)
+					anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
+			}
+
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if ((!anySelected || selected(taxa, it, myColumn))){
+					String note = getNote(it);
+					while (!StringUtil.blank(note) && note.indexOf("(")>=0){
+						int start = note.indexOf("(");
+						int end = note.indexOf(")");
+						String firstBit = "";
+						if (start>0)
+							firstBit = note.substring(0, start);
+						note = firstBit + note.substring(end+1, note.length());
+					}
+					setNote(it, note);
+
+				}
+			}
+			outputInvalid();
+			parametersChanged();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "deletes *", null, commandName, "deleteStar")) {
+			if (observedStates == null || taxa == null)
+				return null;
+			boolean anySelected = taxa.anySelected();
+			int myColumn = -1;
+			if (getEmployer() instanceof ListModule){
+
+				myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+				if (table != null)
+					anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
+			}
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if ((!anySelected || selected(taxa, it, myColumn))){
+					String note = getNote(it);
+					while (!StringUtil.blank(note) && note.indexOf("*")>=0){
+						int start = note.indexOf("*");
+						String firstBit = "";
+						if (start>0)
+							firstBit = note.substring(0, start);
+						note = firstBit + note.substring(start+1, note.length());
+					}
+					setNote(it, note);
+
+				}
+			}
+			outputInvalid();
+			parametersChanged();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Prepends to the note the sequence length (including N\'s and ?\'s) for the selected taxa", null, commandName, "prependLength")) {
+			if (observedStates == null || taxa == null)
+				return null;
+			boolean anySelected = taxa.anySelected();
+			int myColumn = -1;
+			if (getEmployer() instanceof ListModule){
+
+				myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+				if (table != null)
+					anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
+			}
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))){
+					String note = getNote(it);
+					if (StringUtil.blank(note))
+						note = "(" + sequenceLength(it) + ")";
+					else
+						note = "(" + sequenceLength(it) + ") " + note;
+					setNote(it, note);
+				}
+			}
+			outputInvalid();
+			parametersChanged();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Prepends to the note the number of non-missing sites (not including N\'s and ?\'s) for the selected taxa", null, commandName, "prependNumSites")) {
+			if (observedStates == null || taxa == null)
+				return null;
+			boolean anySelected = taxa.anySelected();
+			int myColumn = -1;
+			if (getEmployer() instanceof ListModule){
+
+				myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+				if (table != null)
+					anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
+			}
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))){
+					String note = getNote(it);
+					if (StringUtil.blank(note))
+						note = "(" + numSites(it) + ")";
+					else
+						note = "(" + numSites(it) + ") " + note;
+					setNote(it, note);
+				}
+			}
+			outputInvalid();
+			parametersChanged();
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Deletes the notes for the selected taxa", null, commandName, "deleteAnnotation")) {
+			if (observedStates == null || taxa == null)
+				return null;
+			boolean anySelected = taxa.anySelected();
+			int myColumn = -1;
+			if (getEmployer() instanceof ListModule){
+
+				myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+				if (table != null)
+					anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
+			}
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))){
+					setNote(it, null);
+				}
+			}
+			outputInvalid();
+			parametersChanged();
+			return null;
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*...............................................................................................................*/
+	/** returns whether or not a cell of table is editable.*/
+	public boolean isCellEditable(int row){
+		return true;
+	}
+	/*...............................................................................................................*/
+	/** for those permitting editing, indicates user has edited to incoming string.*/
+	public void setString(int row, String s){
+
+		if (StringUtil.blank(s))
+			setNote(row, null);
+		else if (s.equalsIgnoreCase("Yes") || s.equalsIgnoreCase("No Data"))
+			return;
+		else 
+			setNote(row, s);
+	}
+
+	void setNote(int row, String s){
+		if (tInfo == null)
+			return;
+		tInfo.setAssociatedObject(MolecularData.genBankNumberRef, row, s);
+	}
+	String getNote(int row){
+		if (tInfo == null)
+			return null;
+		Object obj = tInfo.getAssociatedObject(MolecularData.genBankNumberRef, row);
+		if (obj == null || !(obj instanceof String))
+			return null;
+		return (String)obj;
+	}
+	/*...............................................................................................................*/
+	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
+		//if (this.data !=null)
+		//	this.data.removeListener(this);
+		if (taxa != this.taxa)
+			observedStates =  null;
+		this.taxa = taxa;
+		matrixSourceTask.initialize(taxa);
+
+		this.table = table;
+
+		doCalcs();
+	}
+	/*...............................................................................................................*/
+	Bits bits;
+	public void doCalcs(){
+		if (bits != null)
+			bits.clearAllBits();
+		if (taxa == null)
+			return;
+		if (bits == null)
+			bits = new Bits(taxa.getNumTaxa());
+		else
+			bits.resetSize(taxa.getNumTaxa());
+		if (observedStates == null ) {
+			tInfo = null;
+			observedStates = matrixSourceTask.getCurrentMatrix(taxa);
+			if (observedStates != null) {
+				captureCharacterDataFromObservedStates();
+
+				if (data != null)
+					tInfo = data.getTaxaInfo(true);
+			}
+		}
+		if (observedStates==null)
+			return;
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+			if (hasData(it))
+				bits.setBit(it);
+		}
+	}
+	/*...............................................................................................................*/
+	int sequenceLength(int it){
+		CharacterState cs = null;
+		if (observedStates == null)
+			return 0;
+		int count = 0;
+		for (int ic=0; ic<observedStates.getNumChars(); ic++) {
+			cs = observedStates.getCharacterState(cs, ic, it);
+			if (cs == null)
+				return 0;
+			if (cs instanceof MolecularState){
+				if (!cs.isInapplicable())  //if Molecular, then count missing & with state
+					count++;
+			}
+			else
+				if (!cs.isInapplicable() && !cs.isUnassigned())  //if Molecular, then count missing & with state
+					count++;
+
+
+		}
+
+		return count;
+	}
+	/*...............................................................................................................*/
+	int numSites(int it){
+		CharacterState cs = null;
+		if (observedStates == null)
+			return 0;
+		int count = 0;
+		for (int ic=0; ic<observedStates.getNumChars(); ic++) {
+			cs = observedStates.getCharacterState(cs, ic, it);
+			if (cs == null)
+				return 0;
+			if (!cs.isInapplicable() && !cs.isUnassigned())
+				count++;
+
+		}
+
+		return count;
+	}	/*...............................................................................................................*/
+	boolean hasData(int it){
+		CharacterState cs = null;
+		try {
+			for (int ic=0; ic<observedStates.getNumChars(); ic++) {
+				cs = observedStates.getCharacterState(cs, ic, it);
+				if (cs == null)
+					return false;
+				if (!cs.isInapplicable() && !cs.isUnassigned()) 
+					return true;
+
+			}
+		}
+		catch (NullPointerException e){
+		}
+		return false;
+	}
+	/*...............................................................................................................*/
+
+	public String getExplanationForRow(int ic){
+		if (observedStates != null && observedStates.getParentData() != null){
+			captureCharacterDataFromObservedStates();
+
+			Associable tInfo = data.getTaxaInfo(false);
+			if (tInfo == null)
+				return null;
+			return "Notes: " + tInfo.toString(ic);
+		}
+		return null;
+	}
+	/*...............................................................................................................*/
+	boolean selected(Taxa taxa, int it, int myColumn){
+		if (taxa.getSelected(it)){
+			return true;
+		}
+		if (table != null && myColumn >=0){
+			if (table.isCellSelectedAnyWay(myColumn, it))
+				return true;
+		}
+		return false;
+	}
+
+	void zapData(CharacterData data){
+		Taxa taxa = data.getTaxa();
+		Associable tInfo = data.getTaxaInfo(false);
+		int myColumn = -1;
+		if (getEmployer() instanceof ListModule){
+
+			myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+		}
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+			if (selected(taxa, it, myColumn)){
+				if (tInfo != null)
+					tInfo.deassignAssociated(it);
+				for (int ic=0; ic<data.getNumChars(); ic++)
+					data.deassign(ic, it);
+
+			}
+		}
+		data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		outputInvalid();
+		parametersChanged();
+	}
+	/*.................................................................................................................*/
+	void zapData(CharacterData data, int it){
+		Taxa taxa = data.getTaxa();
+		if (it<0 || it>=taxa.getNumTaxa())
+			return;
+		Associable tInfo = data.getTaxaInfo(false);
+		int myColumn = -1;
+		if (getEmployer() instanceof ListModule){
+
+			myColumn = ((ListModule)getEmployer()).getMyColumn(this);
+		}
+		if (tInfo != null)
+			tInfo.deassignAssociated(it);
+		for (int ic=0; ic<data.getNumChars(); ic++)
+			data.deassign(ic, it);
+
+		data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
+		outputInvalid();
+		parametersChanged();
+	}
+	
+	
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		observedStates = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+
+	/*.................................................................................................................*/
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj != null && obj  == data)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	
+	/** Gets background color for cell for row ic.  Override it if you want to change the color from the default. */
+	public Color getBackgroundColorOfCell(int it, boolean selected){
+		if (observedStates == null){
+			doCalcs();
+			if (observedStates==null)
+				return null;
+		}
+		if (observedStates.getParentData() != null){
+			captureCharacterDataFromObservedStates();
+
+			Associable tInfo = data.getTaxaInfo(false);
+			NameReference genBankColor = NameReference.getNameReference("genbankcolor");
+			Object obj = tInfo.getAssociatedObject(genBankColor,  it);  //not saved to file
+			if (obj instanceof Color)
+				return (Color)obj;
+		}
+		if (bits ==null || it <0 || it > bits.getSize())
+			return null;
+		String note = getNote(it);
+		if (selected){
+			if (bits.isBitOn(it))
+				return ColorDistribution.darkGreen;
+			else
+				return ColorDistribution.darkRed;		}
+		else if (bits.isBitOn(it)){
+			if (StringUtil.blank(note))
+				return ColorDistribution.veryLightGreen;
+			if ( !(note.equalsIgnoreCase("x")))
+				return ColorDistribution.lightGreenYellowish;
+			return ColorDistribution.lightGreenYellow;
+		}
+		else {
+			if (StringUtil.blank(note))
+				return ColorDistribution.brown;
+			if ( !(note.equalsIgnoreCase("x"))) {
+				return Color.red;
+			}
+			return ColorDistribution.lightRed;
+		}
+	}
+	public String getStringForTaxon(int it){
+		String note = getNote(it);
+		if (note != null)
+			return note;
+		if (observedStates == null)
+			doCalcs();
+		if (bits ==null || it <0 || it > bits.getSize())
+			return "?";
+		if (bits.isBitOn(it))
+			return "Yes";
+		else
+			return "No Data";
+	}
+	public String getWidestString(){
+		return "88888888888";
+	}
+	/*.................................................................................................................*/
+	public String getTitle() {
+		if (observedStates == null)
+			doCalcs();
+		if (observedStates != null && getProject().getNumberCharMatricesVisible()>1){
+			CharacterData d = observedStates.getParentData();
+			if (d != null && d.getName()!= null) {
+				String n =  d.getName();
+				if (n.length()>12)
+					n = n.substring(0, 12); 
+				return "Has Data (" + n + ")";
+			}
+		}
+		return "Has Data in Matrix";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;  
+	}
+
+}
+
diff --git a/Source/mesquite/molec/TaxonGCBias/TaxonGCBias.java b/Source/mesquite/molec/TaxonGCBias/TaxonGCBias.java
new file mode 100644
index 0000000..6775b74
--- /dev/null
+++ b/Source/mesquite/molec/TaxonGCBias/TaxonGCBias.java
@@ -0,0 +1,271 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TaxonGCBias;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+
+/* Modified  9 July 07 to add GC Skew -  DRM */
+/* ======================================================================== */
+public class TaxonGCBias extends CharacterSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of sequences.",
+		"The source of sequences is arranged initially");
+	}
+	Taxa taxa=null;
+	MCategoricalDistribution matrix;
+	MatrixSourceCoord matrixSourceTask;
+	GCBiasCharacter states;
+	String[] items;
+	long A = CategoricalState.makeSet(0);
+	long C = CategoricalState.makeSet(1);
+	long G = CategoricalState.makeSet(2);
+	long T = CategoricalState.makeSet(3);
+	long AT = A | T;
+	long CG =  C | G;
+	long ACGT = A | C | G | T;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null && condition!= ContinuousData.class && condition!=ContinuousState.class) {
+			return sorry(getName() + " could not be used because it supplies only continuous-valued matrices");
+		}
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, DNAState.class, "DNA Matrix on which to calculate compositional bias"); //TODO: allow resetting of source (e.g., to simulation)
+		if (matrixSourceTask==null){
+			return sorry(getName() + " could not start because a suitable source of matrices was not obtained");
+		}
+		items = new String[1];
+		items[0] = "bias";
+		states = new GCBiasCharacter(null, 3);
+		states.setItems(items);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ContinuousStateTest();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		this.taxa = taxa;
+		matrixSourceTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initialize(Tree tree){
+		if (tree!=null)
+			taxa = tree.getTaxa();
+		matrixSourceTask.initialize(tree);
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (states!=null)
+			for (int it = 0; it<states.getNumNodes(); it++)
+				states.setState(it, 0, MesquiteDouble.unassigned);
+		parametersChanged(notification);
+	}
+	public boolean usesTree(){
+		if (matrixSourceTask==null)
+			return false;
+		else
+			return matrixSourceTask.usesTree();
+	}
+	/*.................................................................................................................*/
+	public CharacterDistribution getCharacter(Tree tree, int icn) {
+		if (tree!=null)
+			taxa = tree.getTaxa();
+		MCategoricalDistribution matrix = (MCategoricalDistribution)matrixSourceTask.getCurrentMatrix(tree);
+		return getCharacter(taxa, matrix, icn);
+	}
+	/*.................................................................................................................*/
+	public CharacterDistribution getCharacter(Taxa taxa, int icn) {
+		MCategoricalDistribution matrix = (MCategoricalDistribution)matrixSourceTask.getCurrentMatrix(taxa);
+		return getCharacter(taxa, matrix, icn);
+	}
+	/*.................................................................................................................*/
+	private CharacterDistribution getCharacter(Taxa taxa, MCategoricalDistribution matrix, int icn) {
+		if (matrix == null)
+			return null;
+		CharacterData data = matrix.getParentData();
+		CharInclusionSet inclusion = null;
+		if (data!=null)
+			inclusion = (CharInclusionSet) data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numTaxa = taxa.getNumTaxa();
+		states = (GCBiasCharacter)states.adjustSize( taxa);
+		for (int it = 0; it<numTaxa; it++) {
+			int tot = 0;
+			int count = 0;
+			double value = MesquiteDouble.unassigned;
+			if (icn==5) {
+				int cCount = 0;
+				int gCount = 0;
+				for (int ic = 0; ic<matrix.getNumChars(); ic++) {
+					if (inclusion == null || inclusion.isBitOn(ic)){
+						long s = matrix.getState(ic,it);
+						if (!CategoricalState.isUnassigned(s) && !CategoricalState.isInapplicable(s)) {
+							if (s == C) {
+								cCount++;
+								tot++;
+							}
+							if (s == G) {
+								gCount++;
+								tot++;
+							}
+
+						}
+					}
+				}
+				if (tot == 0)
+					value = MesquiteDouble.unassigned;  //changed from 0,  26 jan '14
+				else
+					value = (double)(gCount-cCount)/(gCount+cCount);
+
+			}
+			else {
+				for (int ic = 0; ic<matrix.getNumChars(); ic++) {
+					if (inclusion == null || inclusion.isBitOn(ic)){
+						long s = matrix.getState(ic,it);
+						if (!CategoricalState.isUnassigned(s) && !CategoricalState.isInapplicable(s)) {
+							if (icn == 0){ //CG bias; counts only if clearly a C/G versus A/T;  polymorphisms mixing A & G, C & G, A & T, C & T are not counted
+								if (s == A || s == T || s == AT) //monomorphic A or T or A&T or uncertain A or T
+									tot++;
+								else if (s == C || s == G || s == CG) { //monomorphic C or G or C&G or uncertain C or G
+									tot++;
+									count++;
+								}
+							}
+							else if (!CategoricalState.isUncertain(s) && (s & ACGT) != 0L){ //individual base frequency; counts only if monomorphic or polymorphic, not uncertain
+								tot++;
+								if (icn == 1 && ((A & s) != 0L)){ //A
+									count++;
+								}
+								else if (icn == 2  && ((C & s) != 0L)){ //C
+									count++;
+								}
+								else if (icn == 3  && ((G & s) != 0L)){ //G
+									count++;
+								}
+								else if (icn == 4 && ((T & s) != 0L)){ //T
+									count++;
+								}
+							}
+						}
+					}
+				}
+				if (tot == 0)
+					value = MesquiteDouble.unassigned; //changed from 0,  26 jan '14
+				else
+					value = ((double)count)/tot;
+			}
+
+
+			states.setState(it, 0, value);
+		}
+		states.setName( getCharacterName(taxa, icn) +  " in " + matrix.getName());  
+		return states;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfCharacters(Taxa taxa) {
+		this.taxa = taxa;
+		return 6;
+	}
+	/*.................................................................................................................*/
+	/** returns the name of character ic*/
+	public String getCharacterName(Taxa taxa, int ic){
+		if (ic==0)
+			return "Proportion G+C";
+		else if (ic == 1)
+			return "Proportion A";
+		else if (ic == 2)
+			return "Proportion C";
+		else if (ic == 3)
+			return "Proportion G";
+		else if (ic == 4)
+			return "Proportion T";
+		else if (ic == 5)
+			return "GC Skew";
+		else
+			return "?";
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		if (matrix == null || matrix.getParentData()==null)
+			return "";
+		return "Compositional Bias in " + matrix.getParentData().getName();  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "ACGT Compositional Bias";  
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Returns continuous characters which are the proportion G+C, and separately A, C, G, T, for each taxon in a DNA data set." ;
+	}
+
+}
+
+class GCBiasCharacter extends ContinuousAdjustable {
+	public GCBiasCharacter (Taxa taxa, int num) {
+		super(taxa, num);
+	}
+	public CharacterModel getDefaultModel(MesquiteProject file, String paradigm){
+		if (paradigm.equalsIgnoreCase("Parsimony")) {
+			CharacterModel cm = file.getCharacterModel("Squared");
+			if (cm==null) 
+				System.out.println("Default model not found /Squared");
+			return cm;
+		}
+		else if (paradigm.equalsIgnoreCase("Likelihood")) {
+			CharacterModel cm = file.getCharacterModel("Brownian");
+			if (cm==null) 
+				System.out.println("Default model not found /brownian");
+			return cm;
+		}
+		else
+			return super.getDefaultModel(file, paradigm);
+	}
+	/*..........................................................*/
+	//TODO: need one to make CharacterHistory also??????
+	/** This readjust procedure can be called to readjust the size of storage of
+	states of a character for nodes. */
+	public AdjustableDistribution adjustSize(Taxa taxa) {
+		if (taxa.getNumTaxa()!=getNumTaxa()) 
+			return new GCBiasCharacter(taxa, taxa.getNumTaxa()); 
+		else
+			return this;
+	}
+}
+
+
+
diff --git a/Source/mesquite/molec/TermGapsToMissing/TermGapsToMissing.java b/Source/mesquite/molec/TermGapsToMissing/TermGapsToMissing.java
new file mode 100644
index 0000000..2b9185f
--- /dev/null
+++ b/Source/mesquite/molec/TermGapsToMissing/TermGapsToMissing.java
@@ -0,0 +1,115 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TermGapsToMissing;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TermGapsToMissing extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData dData, MesquiteTable table,  UndoReference undoReference){
+		this.table = table;
+		if (!(dData instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Can use " + getName() + " only on categorical data");
+			return false;
+		}
+		CategoricalData data = (CategoricalData)dData;
+   		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+		boolean noRowsSelected =  table == null || !table.anyRowSelected() ;
+		for (int it = 0; it<data.getNumTaxa(); it++){
+			if (table==null || noRowsSelected || table.isRowSelected(it)) {
+				boolean done = false;
+				for (int ic = 0; ic<data.getNumChars() && !done; ic++){
+					if (data.isInapplicable(ic, it)) {
+						data.setState(ic, it, CategoricalState.unassigned);
+						if (!MesquiteLong.isCombinable(numCellsAltered))
+							numCellsAltered = 0;
+						numCellsAltered++;
+					}
+					else if (!data.isUnassigned(ic, it))
+						done = true;
+				}
+				if (done){
+					done = false;
+					for (int ic = data.getNumChars()-1; ic>=0 && !done; ic--){
+						if (data.isInapplicable(ic, it)) {
+							data.setState(ic, it, CategoricalState.unassigned);
+							if (!MesquiteLong.isCombinable(numCellsAltered))
+								numCellsAltered = 0;
+							numCellsAltered++;
+						}
+						else if (!data.isUnassigned(ic, it))
+							done = true;
+					}
+				}
+			}
+		}
+		if (undoInstructions!=null){
+			undoInstructions.setNewData(data);
+			if (undoReference!=null){
+				undoReference.setUndoer(undoInstructions);
+				undoReference.setResponsibleModule(this);
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		/*CategoricalData data = (CategoricalData)ddata;
+		if (data.isUnassigned(ic, it))
+			data.setState(ic, it, CategoricalState.inapplicable);
+		 */
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Terminal Gaps to ?";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts terminal gaps to missing data." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/TermMissingToGaps/TermMissingToGaps.java b/Source/mesquite/molec/TermMissingToGaps/TermMissingToGaps.java
new file mode 100644
index 0000000..d15bfd8
--- /dev/null
+++ b/Source/mesquite/molec/TermMissingToGaps/TermMissingToGaps.java
@@ -0,0 +1,114 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TermMissingToGaps;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class TermMissingToGaps extends CategDataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData dData, MesquiteTable table,  UndoReference undoReference){
+		this.table = table;
+		if (!(dData instanceof CategoricalData)){
+			MesquiteMessage.warnProgrammer("Can use " + getName() + " only on categorical data");
+			return false;
+		}
+		CategoricalData data = (CategoricalData)dData;
+   		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+		boolean noRowsSelected =  table == null || !table.anyRowSelected() ;
+		for (int it = 0; it<data.getNumTaxa(); it++){
+			if (table==null || noRowsSelected || table.isRowSelected(it)) {
+				boolean done = false;
+				for (int ic = 0; ic<data.getNumChars() && !done; ic++){
+					if (data.isUnassigned(ic, it)) {
+						data.setState(ic, it, CategoricalState.inapplicable);
+						if (!MesquiteLong.isCombinable(numCellsAltered))
+							numCellsAltered = 0;
+						numCellsAltered++;
+					}
+					else if (!data.isInapplicable(ic, it))
+						done = true;
+				}
+				if (done){
+					done = false;
+					for (int ic = data.getNumChars()-1; ic>=0 && !done; ic--){
+						if (data.isUnassigned(ic, it)) {
+							data.setState(ic, it, CategoricalState.inapplicable);
+							if (!MesquiteLong.isCombinable(numCellsAltered))
+								numCellsAltered = 0;
+							numCellsAltered++;
+						}
+						else if (!data.isInapplicable(ic, it))
+							done = true;
+					}
+				}
+			}
+		}
+		if (undoInstructions!=null) {
+			undoInstructions.setNewData(data);
+			if (undoReference!=null){
+				undoReference.setUndoer(undoInstructions);
+				undoReference.setResponsibleModule(this);
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+		/*CategoricalData data = (CategoricalData)ddata;
+		if (data.isUnassigned(ic, it))
+			data.setState(ic, it, CategoricalState.inapplicable);
+		 */
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Terminal ? to Gaps";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Converts terminal missing data codings to gaps." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/ToLowerCase/ToLowerCase.java b/Source/mesquite/molec/ToLowerCase/ToLowerCase.java
new file mode 100644
index 0000000..4d50479
--- /dev/null
+++ b/Source/mesquite/molec/ToLowerCase/ToLowerCase.java
@@ -0,0 +1,81 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.ToLowerCase;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ToLowerCase extends DNADataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+ 	/*.................................................................................................................*/
+  	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+ 			if (!(data instanceof DNAData)){
+				MesquiteMessage.warnProgrammer("Attempt to set non-DNA data to lower case");
+				return false;
+			}
+			return alterContentOfCells(data,table, undoReference);
+   	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		DNAData data = (DNAData)ddata;
+   		long state = data.getStateRaw(ic,it);
+   		if (!CategoricalState.isInapplicable(state) && !CategoricalState.isUnassigned(state) && !CategoricalState.isLowerCase(state)){
+   			state = CategoricalState.setLowerCase(state, true);
+   			data.setState(ic,it, state);
+   		}
+	}
+	
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set to Lower Case";
+   	 }
+    		/*.................................................................................................................*/
+    		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    		public int getVersionOfFirstRelease(){
+    			return 200;  
+    		}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters nucleotide data to lower case coding (e.g, to indicate less certain)." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/molec/ToUpperCase/ToUpperCase.java b/Source/mesquite/molec/ToUpperCase/ToUpperCase.java
new file mode 100644
index 0000000..52b0fac
--- /dev/null
+++ b/Source/mesquite/molec/ToUpperCase/ToUpperCase.java
@@ -0,0 +1,83 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.ToUpperCase;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ToUpperCase extends DNADataAlterer {
+	MesquiteTable table;
+	CharacterData data;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+		
+ 	/*.................................................................................................................*/
+  	/** Called to alter data in those cells selected in table*/
+   	public boolean alterData(CharacterData data, MesquiteTable table, UndoReference undoReference){
+ 			if (!(data instanceof DNAData)){
+				MesquiteMessage.warnProgrammer("Attempt to set non-DNA data to upper case");
+				return false;
+			}
+			return alterContentOfCells(data,table, undoReference);
+   	}
+	/*.................................................................................................................*/
+   	public void alterCell(CharacterData ddata, int ic, int it){
+   		DNAData data = (DNAData)ddata;
+		long state = data.getStateRaw(ic,it);
+		if (!CategoricalState.isInapplicable(state) && !CategoricalState.isUnassigned(state)) {
+			if (CategoricalState.isLowerCase(state)){
+				state = CategoricalState.setLowerCase(state, false);
+				data.setState(ic,it, state);
+			}
+		}
+   	}
+	
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set to Upper Case";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Alters nucleotide data to upper case coding (e.g, to indicate more certain)." ;
+   	 }
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+ 	 
+}
+
+
diff --git a/Source/mesquite/molec/TopBlastMatches/TopBlastMatches.java b/Source/mesquite/molec/TopBlastMatches/TopBlastMatches.java
new file mode 100644
index 0000000..dfcd353
--- /dev/null
+++ b/Source/mesquite/molec/TopBlastMatches/TopBlastMatches.java
@@ -0,0 +1,422 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TopBlastMatches; 
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.net.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.MatrixSourceCoord;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.ContinuousState;
+import mesquite.molec.lib.*;
+
+
+/* ======================================================================== */
+public class TopBlastMatches extends CategDataSearcher implements ItemListener { 
+	MesquiteTable table;
+	CharacterData data;
+	StringBuffer results;
+	String[] accessionNumbers;
+	String[] ID;
+	Blaster blasterTask;
+	
+	int blastType = Blaster.BLAST;
+
+	boolean importTopMatches = false;
+	boolean saveResultsToFile = true;
+	int maxHits = 1;
+	double  minimumBitScore = 0.0;
+	boolean preferencesSet = false;
+	boolean fetchTaxonomy = false;
+	boolean interleaveResults = false;
+	boolean adjustSequences = false;
+	boolean addInternalGaps = false;
+	boolean appendQueryName = false;
+//	boolean blastx = false;
+	int maxTime = 300;
+//	static int upperMaxHits = 30;
+
+	double eValueCutoff = 10.0;
+	int wordSize  = 11;
+
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(Blaster.class, getName() + "  needs a Blast module.","");
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		blasterTask = (Blaster)hireEmployee(Blaster.class, "Blaster (for " + getName() + ")"); 
+		if (blasterTask==null)
+			return sorry(getName() + " couldn't start because no Blast module could be obtained.");
+		else if (!blasterTask.initialize())
+			return false;
+		results = new StringBuffer();
+		loadPreferences();
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("fetchTaxonomy".equalsIgnoreCase(tag))
+			fetchTaxonomy = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("saveResultsToFile".equalsIgnoreCase(tag))
+			saveResultsToFile = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("importTopMatches".equalsIgnoreCase(tag))
+			importTopMatches = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("interleaveResults".equalsIgnoreCase(tag))
+			interleaveResults = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("adjustSequences".equalsIgnoreCase(tag))
+			adjustSequences = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("addInternalGaps".equalsIgnoreCase(tag))
+			addInternalGaps = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("appendQueryName".equalsIgnoreCase(tag))
+			appendQueryName = MesquiteBoolean.fromTrueFalseString(content);
+		else if ("blastType".equalsIgnoreCase(tag))
+			blastType = MesquiteInteger.fromString(content);
+		else if ("wordSize".equalsIgnoreCase(tag))
+			wordSize = MesquiteInteger.fromString(content);
+		else if ("eValueCutoff".equalsIgnoreCase(tag))
+			eValueCutoff = MesquiteDouble.fromString(content);
+		else if ("maxTime".equalsIgnoreCase(tag))
+			maxTime = MesquiteInteger.fromString(content);
+		else if ("maxHits".equalsIgnoreCase(tag))
+			maxHits = MesquiteInteger.fromString(content);		
+		preferencesSet = true;
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(60);	
+		StringUtil.appendXMLTag(buffer, 2, "fetchTaxonomy", fetchTaxonomy);  
+		StringUtil.appendXMLTag(buffer, 2, "maxTime", maxTime);  
+		StringUtil.appendXMLTag(buffer, 2, "importTopMatches", importTopMatches);  
+		StringUtil.appendXMLTag(buffer, 2, "interleaveResults", interleaveResults);  
+		StringUtil.appendXMLTag(buffer, 2, "addInternalGaps", addInternalGaps);  
+		StringUtil.appendXMLTag(buffer, 2, "appendQueryName", appendQueryName);  
+		StringUtil.appendXMLTag(buffer, 2, "adjustSequences", adjustSequences);  
+//		StringUtil.appendXMLTag(buffer, 2, "blastx", blastx);  
+		StringUtil.appendXMLTag(buffer, 2, "eValueCutoff", eValueCutoff);  
+		StringUtil.appendXMLTag(buffer, 2, "maxHits", maxHits);  
+		StringUtil.appendXMLTag(buffer, 2, "blastType", blastType);  
+		StringUtil.appendXMLTag(buffer, 2, "wordSize", wordSize);  
+		StringUtil.appendXMLTag(buffer, 2, "saveResultsToFile", saveResultsToFile);  
+
+		preferencesSet = true;
+		return buffer.toString();
+	}
+//	Checkbox blastXCheckBox ;
+	Choice blastTypeChoice ;
+	Checkbox saveFileCheckBox ;
+	Checkbox fetchTaxonomyCheckBox;
+	Checkbox importCheckBox;
+	Checkbox interleaveResultsCheckBox;
+	Checkbox adjustSequencesCheckBox;
+	Checkbox addInternalGapsCheckBox;
+	Checkbox appendQueryNameCheckBox;
+	/*.................................................................................................................*/
+	private void checkEnabling(){
+		//importCheckBox.setEnabled(!blastXCheckBox.getState());
+		fetchTaxonomyCheckBox.setEnabled( saveFileCheckBox.getState());
+	}
+	/*.................................................................................................................*/
+	public void itemStateChanged(ItemEvent e) {
+		checkEnabling();
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Top Blast Matches",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel("Options for Top Blast Matches");
+		int oldBlastType = blastType;
+
+		IntegerField maxHitsField = dialog.addIntegerField("Maximum number of matches:",  maxHits,5,1,blasterTask.getUpperLimitMaxHits());
+//		blastXCheckBox = dialog.addCheckBox("use blastx for nucleotides",blastx);
+		DoubleField eValueCutoffField = dialog.addDoubleField("Reject hits with eValues greater than: ", eValueCutoff, 20, 0.0, Double.MAX_VALUE);
+		IntegerField wordSizeField = dialog.addIntegerField("Word size:",  wordSize,5,0,Integer.MAX_VALUE);
+		saveFileCheckBox = dialog.addCheckBox("save summary report and BLAST responses",saveResultsToFile);
+		blastTypeChoice = dialog.addPopUpMenu("BLAST type for nucleotides", Blaster.getBlastTypeNames(), blastType);
+		fetchTaxonomyCheckBox = dialog.addCheckBox("fetch taxonomic lineage",fetchTaxonomy);
+		importCheckBox = dialog.addCheckBox("import top matches into matrix",importTopMatches);
+		interleaveResultsCheckBox = dialog.addCheckBox("insert hits after sequence that was BLASTed",interleaveResults);
+		adjustSequencesCheckBox = dialog.addCheckBox("reverse complement in needed and align imported sequences",adjustSequences);
+		addInternalGapsCheckBox = dialog.addCheckBox("allow new internal gaps during alignment",addInternalGaps);
+		appendQueryNameCheckBox = dialog.addCheckBox("append query name to hit name",appendQueryName);
+		
+		IntegerField maxTimeField = dialog.addIntegerField("Maximum time for BLAST response (seconds):",  maxTime,5);
+	//	blastXCheckBox.addItemListener(this);
+		saveFileCheckBox.addItemListener(this);
+		checkEnabling();
+
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			maxHits = maxHitsField.getValue();
+			saveResultsToFile = saveFileCheckBox.getState();
+			fetchTaxonomy = fetchTaxonomyCheckBox.getState();
+			eValueCutoff = eValueCutoffField.getValue();
+//			blastx = blastXCheckBox.getState();
+			blastType = blastTypeChoice.getSelectedIndex();
+			if (blastType<0) blastType=oldBlastType;
+			importTopMatches = importCheckBox.getState();
+			interleaveResults = interleaveResultsCheckBox.getState();
+			adjustSequences = adjustSequencesCheckBox.getState();
+			addInternalGaps = addInternalGapsCheckBox.getState();
+			wordSize = wordSizeField.getValue();
+			appendQueryName = appendQueryNameCheckBox.getState();
+			maxTime=maxTimeField.getValue();
+			storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public  void actionPerformed(ActionEvent e) {
+		if (e.getActionCommand().equalsIgnoreCase("defaults")) {
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;   
+	}
+	/*.................................................................................................................*/
+	/** message if search failed to find anything.  */
+	public void unsuccessfulSearchMessage(){
+		logln("BLAST database returned no sequences in response to query.");
+	}
+	/*.................................................................................................................*/
+	public boolean isNucleotides(CharacterData data){
+		return data instanceof DNAData;
+	}
+	/*.................................................................................................................*/
+	public boolean acceptableHit(int hitCount, double bitScore, double eValue) {
+		return hitCount<=maxHits;
+	}
+	/*.................................................................................................................*/
+	protected URL getESearchAddress(String s)
+	throws MalformedURLException {
+		return new URL(s);
+	}
+
+	String reportDirectoryPath=null;
+	/*.................................................................................................................*/
+	public boolean prepareReportDirectory() {
+		String folderName = "BLAST reports";
+		if (blasterTask!=null)
+			folderName = "BLAST to " + blasterTask.getDatabaseName();
+		reportDirectoryPath = MesquiteFileUtil.createDirectoryForFiles(this, MesquiteFileUtil.BESIDE_HOME_FILE, folderName,".");
+		return StringUtil.notEmpty(reportDirectoryPath);
+	}
+	/*.................................................................................................................*/
+	public void saveBLASTReport(String name, String contents) {
+		if (StringUtil.blank(reportDirectoryPath))
+			return;
+		
+		String blastReportPath = reportDirectoryPath + name;  // directory into which processed files go
+		blastReportPath = MesquiteFile.getUniqueNumberedPath(blastReportPath);
+		if (!StringUtil.blank(blastReportPath)) {
+			MesquiteFile.putFileContents(blastReportPath, contents, false);
+		}
+	}
+	/*.................................................................................................................*/
+	public void saveResults(StringBuffer results) {
+		if (StringUtil.blank(reportDirectoryPath))
+			return;
+		
+		String blastSummaryPath = reportDirectoryPath + "BLAST summary";  // directory into which processed files go
+		if (!StringUtil.blank(blastSummaryPath)) {
+			MesquiteFile.putFileContents(blastSummaryPath, results.toString(), false);
+		}
+	}
+	/*.................................................................................................................*/
+	/** Processing to be done after each search. Returns true if  */
+	public boolean processAfterEachTaxonSearch(CharacterData data, int it){
+		logln("\nSearch results: \n"+ results.toString());
+		//		logln("**** IDs: " +StringArray.toString(ID)); 
+		int numTaxaAdded =0;
+
+		if (importTopMatches ){  
+			int originalNumChars = data.getNumChars();
+			int insertAfterTaxon = data.getNumTaxa()-1;
+			if (interleaveResults)
+				insertAfterTaxon = it;
+			//NCBIUtil.getGenBankIDs(accessionNumbers, false,  this, false);
+			logln("About to import top matches.", true);
+
+			if (blastType==Blaster.BLASTX && data instanceof DNAData) {
+				//	ID = NCBIUtil.getNucIDsFromProtIDs(ID);
+				ID = blasterTask.getNucleotideIDsfromProteinIDs(ID);
+				//	logln("****AFTER NucToProt IDs: " +StringArray.toString(ID)); 
+			}
+			//String newSequencesAsFasta = NCBIUtil.fetchGenBankSequencesFromIDs(ID, data instanceof DNAData, this, true, report);	
+
+			StringBuffer blastResponse = new StringBuffer();
+			String newSequencesAsFasta = blasterTask.getFastaFromIDs(ID,  data instanceof DNAData, blastResponse);
+
+			String appendToTaxonName = "";
+			if (appendQueryName)
+				appendToTaxonName = " ["+data.getTaxa().getTaxonName(it)+"]";
+
+
+			numTaxaAdded = data.getNumTaxa();
+			if (StringUtil.notEmpty(newSequencesAsFasta))
+				NCBIUtil.importFASTASequences(data, newSequencesAsFasta, this, results, insertAfterTaxon, it, adjustSequences, addInternalGaps, appendToTaxonName);
+			else
+				logln("BLAST database returned no sequences in response to query.");
+			data.notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			data.getTaxa().notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+			logln(results.toString());
+			
+			numTaxaAdded = data.getNumTaxa()-numTaxaAdded;
+/*			if (lastSearched!=null && lastSearched.isCombinable()) {
+				if (interleaveResults) { 
+					//lastSearched.add(numTaxaAdded);
+				}
+			}
+			*/
+			return data.getNumChars()!=originalNumChars;
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean searchOneTaxon(CharacterData data, int it, int icStart, int icEnd){
+		if (data==null || blasterTask==null)
+			return false;
+		String sequenceName = data.getTaxa().getTaxonName(it);
+		results.append("\n   BLASTing "+ sequenceName+ "\n");
+		StringBuffer sequence = new StringBuffer(data.getNumChars());
+		for (int ic = icStart; ic<=icEnd; ic++) {
+			data.statesIntoStringBuffer(ic, it, sequence, false, false, false);
+		}
+		
+		StringBuffer response = new StringBuffer();
+		//blasterTask.setBlastx(blastx);
+		blasterTask.setBlastType(blastType);
+		if (data instanceof ProteinData)
+			blasterTask.blastForMatches("blastp", sequenceName, sequence.toString(), true, maxHits, maxTime, eValueCutoff,wordSize, response, true);
+		else {	
+			blasterTask.basicDNABlastForMatches(blastType, sequenceName, sequence.toString(), maxHits, maxTime, eValueCutoff, wordSize, response, true);
+		}
+
+		BLASTResults blastResults = new BLASTResults(maxHits);
+		
+		if (saveResultsToFile)
+			saveBLASTReport(sequenceName+" to " + blasterTask.getDatabaseName(),response.toString());
+		blastResults.processResultsFromBLAST(response.toString(), false, eValueCutoff);
+		blasterTask.postProcessingCleanup(blastResults);
+
+		if (blastResults.someHits())
+			results.append("   Top hits\n\tAccession [eValue] Definition): \n");
+		else
+			results.append("   No hits returned.\n");
+
+		for (int i=0; i<maxHits; i++) {
+			if (StringUtil.notEmpty(blastResults.getAccession(i))) {
+				results.append("\t"+blastResults.getAccession(i));
+				results.append("\t["+blastResults.geteValue(i)+"]");
+				results.append("\t"+blastResults.getDefinition(i));
+				String tax = "";
+				if (fetchTaxonomy) {
+					tax = NCBIUtil.fetchTaxonomyFromSequenceID(blastResults.getID(i), data instanceof DNAData, true, null);
+					//	tax = NCBIUtil.fetchTaxonomyFromSequenceID(blastResults.getID(i), data instanceof DNAData, true, null);
+					results.append("\t"+tax);
+				}
+				results.append("\n");
+			}
+		}
+		accessionNumbers = blastResults.getAccessions();
+		ID = blastResults.getIDs();
+		return blastResults.someHits();
+	}
+	/*.................................................................................................................*/
+	/** Called to search on the data in selected cells.  Returns true if data searched*/
+	public boolean searchData(CharacterData data, MesquiteTable table){
+		this.data = data;
+		results.setLength(0);
+		if (!(data instanceof DNAData || data instanceof ProteinData)){
+			discreetAlert( "Only DNA or protein data can be searched using this module.");
+			return false;
+		} 
+		else {
+			if (!queryOptions())
+				return false;
+			if (saveResultsToFile)
+				prepareReportDirectory();
+			logln("\nSearching for top BLAST hits (" + blasterTask.getName() + ")");
+			if (table!=null)
+				table.convertColumnSelectionToRows(true);
+			
+	
+			boolean searchOK = searchSelectedTaxa(data,table);
+			if (saveResultsToFile)
+				saveResults(results);
+			return searchOK;
+	
+		}
+	}
+
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyMolecularData();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Top BLAST Matches...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Top BLAST Matches";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Does a BLAST search against GenBank on selected data and returns the top BLAST matches for each sequence selected.";
+	}
+}
+
+/*
+Search string into Genbank Entrez:
+
+http://www.ncbi.nlm.nih.gov:80/entrez/query.fcgi?cmd=Search&db=nucleotide&dopt=GenBank&term=Bembidion
+
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?DATABASE=nr&FORMAT_TYPE=HTML&PROGRAM=blastn&CLIENT=web&SERVICE=plain&PAGE=Nucleotides&CMD=Put&QUERY= 
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?DATABASE=nr&HITLIST_SIZE=10&FILTER=L&EXPECT=10&FORMAT_TYPE=HTML&PROGRAM=blastn&CLIENT=web&SERVICE=plain&NCBI_GI=on&PAGE=Nucleotides&CMD=Put&QUERY= 
+
+
+http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?CMD=put&PAGE=Nucleotides&program=blast&QUERY_FILE=fasta&query="CCAAGTCCTTCTTGAAGGGGGCCATTTACCCATAGAGGGTGCCAGGCCCGTAGTGACCATTTATATATTTGGGTGAGTTTCTCCTTAGAGTCGGGTTGCTTGAGAGTGCAGCTCTAAGTGGGTGGTAAACTCCATCTAAGGCTAAATATGACTGCGAAACCGATAGCGAACAAGTACCGTGAGGGAAAGTTGAAAAGAACTTTGAAGAGAGAGTTCAAGAGTACGTGAAACTGTTCAGGGGTAAACCTGTGGTGCCCGAAAGTTCGAAGGGGGAGATTC"
+
+ */
+
+
+
diff --git a/Source/mesquite/molec/TranslateToProtein/TranslateToProtein.java b/Source/mesquite/molec/TranslateToProtein/TranslateToProtein.java
new file mode 100644
index 0000000..39649e2
--- /dev/null
+++ b/Source/mesquite/molec/TranslateToProtein/TranslateToProtein.java
@@ -0,0 +1,134 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.TranslateToProtein;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class TranslateToProtein extends CharMatrixSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.charMatrices.StoredMatrices.StoredMatrices.class, getName() + "  needs a source of sequences.",
+		"The source of sequences is arranged initially");
+	}
+	CharMatrixSource dataTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		
+		dataTask = (CharMatrixSource)hireNamedEmployee(CharMatrixSource.class, "#StoredMatrices", DNAState.class);
+		if (dataTask == null) {
+			return sorry(getName() + " can't be started because no source of matrices was obtained");
+		}
+		return true; 
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new CharacterStateTest();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", dataTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns employee that is matrix source", null, commandName, "getCharacterSource")) {
+			return dataTask;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		//return null;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		dataTask.initialize(taxa);
+	}
+	
+	private MCharactersDistribution translate(MCharactersDistribution mData){
+		if (mData != null && mData.getParentData() != null){
+			CharacterData data = mData.getParentData();
+			if (data instanceof DNAData){
+				DNAData dData = (DNAData)data;
+				ProteinData pData = dData.getProteinData(null, true);
+				if (pData!= null) {
+					pData.setName("Protein translation of " + dData.getName());
+					return pData.getMCharactersDistribution();
+				}
+			}
+		}
+		return null;
+		
+	}
+	
+	/** returns the number of character matrices that can be supplied for the given taxa*/
+	public int getNumberOfMatrices(Taxa taxa){
+		return dataTask.getNumberOfMatrices(taxa);
+	}
+	/** gets the current matrix.*/
+	public  MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		MCharactersDistribution orig = dataTask.getCurrentMatrix(taxa);
+		return translate(orig);
+	}
+	/** gets the indicated matrix.*/
+	public  MCharactersDistribution getMatrix(Taxa taxa, int im){
+		MCharactersDistribution orig = dataTask.getMatrix(taxa, im);
+		return translate(orig);
+	}
+	/** gets name of the indicated matrix.*/
+	public  String getMatrixName(Taxa taxa, int im){
+		return "Protein translation of " + dataTask.getMatrixName(taxa, im);
+	}
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return dataTask.getNumberCurrentMatrix();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Translate DNA to Protein";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Translates a stored DNA matrix to protein." ;
+	}
+	
+}
+
diff --git a/Source/mesquite/molec/TrimTermPartTriplets/TrimTermPartTriplets.java b/Source/mesquite/molec/TrimTermPartTriplets/TrimTermPartTriplets.java
new file mode 100644
index 0000000..d6966e3
--- /dev/null
+++ b/Source/mesquite/molec/TrimTermPartTriplets/TrimTermPartTriplets.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.TrimTermPartTriplets;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+
+public class TrimTermPartTriplets extends DNADataAlterer {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to alter data in those cells selected in table*/
+	public boolean alterData(CharacterData dData, MesquiteTable table,  UndoReference undoReference){
+		if (dData==null)
+			return false;
+	
+		if (!(dData instanceof DNAData)){
+			MesquiteMessage.warnProgrammer(getName() + " requires DNA data");
+			return false;
+		}
+		DNAData data = (DNAData)dData;
+		if (!data.someCoding()) 
+			return false;
+
+   		UndoInstructions undoInstructions = data.getUndoInstructionsAllMatrixCells(new int[] {UndoInstructions.NO_CHAR_TAXA_CHANGES});
+		boolean changed = false;
+		
+		for (int it = 0; it<data.getNumTaxa(); it++)
+			if (table == null || !table.anyRowSelected()||table.wholeRowSelectedAnyWay(it)) {
+				for (int ic = 0; ic<data.getNumChars(); ic++){  // check start
+					if (!data.isInapplicable(ic, it)) {
+						if (data.getCodonPosition(ic)==2) {
+							data.setState(ic, it, DNAState.inapplicable);
+							changed=true;
+							if (data.getCodonPosition(ic+1)==3)
+								data.setState(ic+1, it, DNAState.inapplicable);
+						}
+						else if (data.getCodonPosition(ic)==3) {
+							data.setState(ic, it, DNAState.inapplicable);
+							changed=true;
+						}
+						break;
+					}
+				}
+				for (int ic = data.getNumChars()-1; ic>=0; ic--){  // check end
+					if (!data.isInapplicable(ic, it)) {
+						if (data.getCodonPosition(ic)==2) {
+							data.setState(ic, it, DNAState.inapplicable);
+							changed=true;
+							if (data.getCodonPosition(ic-1)==1)
+								data.setState(ic-1, it, DNAState.inapplicable);
+						}
+						else if (data.getCodonPosition(ic)==1) {
+							data.setState(ic, it, DNAState.inapplicable);
+							changed=true;
+						}
+						break;
+					}
+				}
+			}
+		if (undoInstructions!=null) {
+			undoInstructions.setNewData(data);
+			if (undoReference!=null){
+				undoReference.setUndoer(undoInstructions);
+				undoReference.setResponsibleModule(this);
+			}
+		}
+		return changed;
+	}
+	/*.................................................................................................................*/
+	public void alterCell(CharacterData ddata, int ic, int it){
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Trim Terminal Incomplete Codons";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Trims any incomplete codons from the start and end of each sequence." ;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return  201;  
+	}
+
+}
+
diff --git a/Source/mesquite/molec/aMolecIntro/aMolecIntro.java b/Source/mesquite/molec/aMolecIntro/aMolecIntro.java
new file mode 100644
index 0000000..9d282c3
--- /dev/null
+++ b/Source/mesquite/molec/aMolecIntro/aMolecIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.aMolecIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aMolecIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aMolecIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides utilities for molecular data.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Molecular Utilities Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Molecular Utilities Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/molec/amino acid properties b/Source/mesquite/molec/amino acid properties
new file mode 100644
index 0000000..e511a3f
--- /dev/null
+++ b/Source/mesquite/molec/amino acid properties	
@@ -0,0 +1,831 @@
+http://www.sgi.sscc.ru/mgs/programs/crasp/texts/AA_Properties.htm
+
+1. Free energy of transfer to surface (Bull & Breese 1974)
+Arch. Bioch. Biophys. 1974 161 665-670
+610.0000�� A ALA
+690.0000�� R ARG
+890.0000�� N ASN
+610.0000�� D ASP
+360.0000�� C CYS
+970.0000�� Q GLN
+510.0000�� E GLU
+810.0000�� G GLY
+690.0000�� H HIS
+-1450.0000 I ILE
+-1650.0000 L LEU
+460.0000�� K LYS
+-660.0000� M MET
+-1520.0000 F PHE
+-170.0000� P PRO
+420.0000�� S SER
+290.0000�� T THR
+-1200.0000 W TRP
+-1430.0000 Y TYR
+-750.0000� V VAL
+
+2. Surrounding hydrophobicity in alpha-helix (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+13.6500 A ALA
+11.2800 R ARG
+12.2400 N ASN
+10.9800 D ASP
+14.4900 C CYS
+11.3000 Q GLN
+12.5500 E GLU
+15.3600 G GLY
+11.5900 H HIS
+14.6300 I ILE
+14.0100 L LEU
+11.9600 K LYS
+13.4000 M MET
+14.0800 F PHE
+11.5100 P PRO
+11.2600 S SER
+13.0000 T THR
+12.0600 W TRP
+12.6400 Y TYR
+12.8800 V VAL
+
+3. Surrounding hydrophobicity in beta-sheet (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+14.6000 A ALA
+13.2400 R ARG
+11.7900 N ASN
+13.7800 D ASP
+15.9000 C CYS
+12.0200 Q GLN
+13.5900 E GLU
+14.1800 G GLY
+15.3500 H HIS
+14.1000 I ILE
+16.4900 L LEU
+13.2800 K LYS
+16.2300 M MET
+14.1800 F PHE
+14.1000 P PRO
+13.3600 S SER
+14.5000 T THR
+13.9000 W TRP
+14.7600 Y TYR
+16.3000 V VAL
+
+4. Surrounding hydrophobicity in beta-turn (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+10.6700 A ALA
+11.0500 R ARG
+10.8500 N ASN
+10.2100 D ASP
+14.1500 C CYS
+11.7100 Q GLN
+11.7100 E GLU
+10.9500 G GLY
+12.0700 H HIS
+12.9500 I ILE
+13.0700 L LEU
+9.9300� K LYS
+15.0000 M MET
+13.2700 F PHE
+10.6200 P PRO
+11.1800 S SER
+10.5300 T THR
+11.4100 W TRP
+11.5200 Y TYR
+13.8600 V VAL
+
+5. Accessibility reduction ratio (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+3.7000 A ALA
+2.5300 R ARG
+2.1200 N ASN
+2.6000 D ASP
+3.0300 C CYS
+2.7000 Q GLN
+3.3000 E GLU
+3.1300 G GLY
+3.5700 H HIS
+7.6900 I ILE
+5.8800 L LEU
+1.7900 K LYS
+5.2100 M MET
+6.6000 F PHE
+2.1200 P PRO
+2.4300 S SER
+2.6000 T THR
+6.2500 W TRP
+3.0300 Y TYR
+7.1400 V VAL
+
+6. Average number of surrounding residues (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+6.0500 A ALA
+5.7000 R ARG
+5.0400 N ASN
+4.9500 D ASP
+7.8600 C CYS
+5.4500 Q GLN
+5.1000 E GLU
+6.1600 G GLY
+5.8000 H HIS
+7.5100 I ILE
+7.3700 L LEU
+4.8800 K LYS
+6.3900 M MET
+6.6200 F PHE
+5.6500 P PRO
+5.5300 S SER
+5.8100 T THR
+6.9800 W TRP
+6.7300 Y TYR
+7.6200 V VAL
+
+7. Volume (Chothia 1984)
+Annu. Rev. Biochem. (1984) 53 537-572
+91.5000 A ALA
+202.0000 R ARG
+135.2000 N ASN
+124.5000 D ASP
+118.0000 C CYS
+161.1000 Q GLN
+155.1000 E GLU
+66.4000� G GLY
+167.3000 H HIS
+168.8000 I ILE
+167.9000 L LEU
+171.3000 K LYS
+170.8000 M MET
+203.4000 F PHE
+129.3000 P PRO
+99.1000� S SER
+122.1000 T THR
+237.6000 W TRP
+203.6000 Y TYR
+141.7000 V VAL
+
+8. Local flexibility (Ragone et al. 1989)
+Prot. Engineering(1989) 2 497-504
+705.4200� A ALA
+1484.2800 R ARG
+513.4601� N ASN
+34.9600�� D ASP
+2412.5601 C CYS
+1087.8300 Q GLN
+1158.6600 E GLU
+33.1800�� G GLY
+1637.1300 H HIS
+5979.3701 I ILE
+4985.7300 L LEU
+699.6900� K LYS
+4491.6602 M MET
+5203.8599 F PHE
+431.9600� P PRO
+174.7600� S SER
+601.8800� T THR
+6374.0698 W TRP
+4291.1001 Y TYR
+4474.4199 V VAL
+
+9. Flexibility (Bhaskaran and Ponnuswamy 1988)
+Int. J. Peptide Protein Res.(1988) 32 241-255
+0.3570 A ALA
+0.5290 R ARG
+0.4630 N ASN
+0.5110 D ASP
+0.3460 C CYS
+0.4930 Q GLN
+0.4970 E GLU
+0.5440 G GLY
+0.3230 H HIS
+0.4620 I ILE
+0.3650 L LEU
+0.4660 K LYS
+0.2950 M MET
+0.3140 F PHE
+0.5090 P PRO
+0.5070 S SER
+0.4440 T THR
+0.3050 W TRP
+0.4200 Y TYR
+0.3860 V VAL
+
+10. Flexibility for no rigid neighbours (Karplus & Schulz 1985)
+Naturwissenschaften (1985) 72 212-213
+1.0410 A ALA
+1.0380 R ARG
+1.1170 N ASN
+1.0330 D ASP
+0.9600 C CYS
+1.1650 Q GLN
+1.0940 E GLU
+1.1420 G GLY
+0.9820 H HIS
+1.0020 I ILE
+0.9670 L LEU
+1.0930 K LYS
+0.9470 M MET
+0.9300 F PHE
+1.0550 P PRO
+1.1690 S SER
+1.0730 T THR
+0.9250 W TRP
+0.9610 Y TYR
+0.9820 V VAL
+
+11. Flexibility for one rigid neighbour (Karplus & Schulz 1985)
+Naturwissenschaften (1985) 72 212-213
+0.9460 A ALA
+1.0280 R ARG
+1.0060 N ASN
+1.0890 D ASP
+0.8780 C CYS
+1.0280 Q GLN
+1.0360 E GLU
+1.0420 G GLY
+0.9520 H HIS
+0.8920 I ILE
+0.9610 L LEU
+1.0820 K LYS
+0.8620 M MET
+0.9120 F PHE
+1.0850 P PRO
+1.0480 S SER
+1.0510 T THR
+0.9170 W TRP
+0.9300 Y TYR
+0.9270 V VAL
+
+12. Average accessibility surface area (Janin et al. 1978)
+J. Mol. Biol. (1978) 125 357-386
+27.8000 A ALA
+94.7000 R ARG
+60.1000 N ASN
+60.6000 D ASP
+15.5000 C CYS
+68.7000 Q GLN
+68.2000 E GLU
+24.5000 G GLY
+50.7000 H HIS
+22.8000 I ILE
+27.6000 L LEU
+103.000 K LYS
+33.5000 M MET
+25.5000 F PHE
+51.5000 P PRO
+42.0000 S SER
+45.0000 T THR
+34.7000 W TRP
+55.2000 Y TYR
+23.7000 V VAL
+
+13. Flexibility for two rigid neighbours (Karplus & Schulz 1985)
+Naturwissenschaften (1985) 72 212-213
+0.8920 A ALA
+0.9010 R ARG
+0.9300 N ASN
+0.9320 D ASP
+0.9250 C CYS
+0.8850 Q GLN
+0.9330 E GLU
+0.9230 G GLY
+0.8940 H HIS
+0.8720 I ILE
+0.9210 L LEU
+1.0570 K LYS
+0.8040 M MET
+0.9140 F PHE
+0.9320 P PRO
+0.9230 S SER
+0.9340 T THR
+0.8030 W TRP
+0.8370 Y TYR
+0.9130 V VAL
+
+14. Hydrophobicity (Eisenberg et al. 1984)
+J. Mol. Biol. (1984) 179 125-142
+0.2500� A ALA
+-1.7600 R ARG
+-0.6400 N ASN
+-0.7200 D ASP
+0.0400� C CYS
+-0.6900 Q GLN
+-0.6200 E GLU
+0.1600� G GLY
+-0.4000 H HIS
+0.7300� I ILE
+0.5300� L LEU
+-1.1000 K LYS
+0.2600� M MET
+0.6100� F PHE
+-0.0700 P PRO
+-0.2600 S SER
+-0.1800 T THR
+0.3700� W TRP
+0.0200� Y TYR
+0.5400� V VAL
+
+15. Accessible surface area in the standard state (Rose et al. 1985)
+Science (1975) 229 834-838
+118.1000 A ALA
+256.0000 R ARG
+165.5000 N ASN
+158.7000 D ASP
+146.1000 C CYS
+193.2000 Q GLN
+186.2000 E GLU
+88.1000� G GLY
+202.5000 H HIS
+181.0000 I ILE
+193.1000 L LEU
+225.8000 K LYS
+203.4000 M MET
+222.8000 F PHE
+146.8000 P PRO
+129.8000 S SER
+152.5000 T THR
+266.3000 W TRP
+236.8000 Y TYR
+164.5000 V VAL
+
+16. Average accessible surface area in folded proteins (Rose et al. 1985)
+Science (1975) 229 834-838
+31.5000 A ALA
+93.8000 R ARG
+62.2000 N ASN
+60.9000 D ASP
+13.9000 C CYS
+74.0000 Q GLN
+72.3000 E GLU
+25.2000 G GLY
+46.7000 H HIS
+23.0000 I ILE
+29.0000 L LEU
+110.300 K LYS
+30.5000 M MET
+28.7000 F PHE
+53.7000 P PRO
+44.2000 S SER
+46.0000 T THR
+41.7000 W TRP
+59.1000 Y TYR
+23.5000 V VAL
+
+17. Average surrounding hydrophobicity (Manavalan and Ponnuswamy 1978)
+Nature (1978) 275 673-674
+12.9700 A ALA
+11.7200 R ARG
+11.4200 N ASN
+10.8500 D ASP
+14.6400 C CYS
+11.7600 Q GLN
+11.8900 E GLU
+12.4300 G GLY
+12.1600 H HIS
+15.6700 I ILE
+14.9000 L LEU
+11.3600 K LYS
+14.3900 M MET
+14.0000 F PHE
+11.3700 P PRO
+11.2300 S SER
+11.6900 T THR
+13.9300 W TRP
+13.4200 Y TYR
+15.7100 V VAL
+
+18. Hydrophilicity (Hopp and Woods 1981)
+Proc. Natl. Acad. Sci. USA (1981) 78 3824-3828
+-0.5000 A ALA
+3.0000� R ARG
+0.2000� N ASN
+3.0000� D ASP
+-1.0000 C CYS
+0.2000� Q GLN
+3.0000� E GLU
+0.0000� G GLY
+-0.5000 H HIS
+-1.8000 I ILE
+-1.8000 L LEU
+3.0000� K LYS
+-1.3000 M MET
+-2.5000 F PHE
+0.0000� P PRO
+0.3000� S SER
+-0.4000 T THR
+-3.4000 W TRP
+-2.3000 Y TYR
+-1.5000 V VAL
+
+19. Hydropathy (Kyte and Doolittle 1982)
+J. Mol. Biol. (1982) 157 105-132
+1.8000� A ALA
+-4.5000 R ARG
+-3.5000 N ASN
+-3.5000 D ASP
+2.5000� C CYS
+-3.5000 Q GLN
+-3.5000 E GLU
+-0.4000 G GLY
+-3.2000 H HIS
+4.5000� I ILE
+3.8000� L LEU
+-3.9000 K LYS
+1.9000� M MET
+2.8000� F PHE
+-1.6000 P PRO
+-0.8000 S SER
+-0.7000 T THR
+-0.9000 W TRP
+-1.3000 Y TYR
+4.2000� V VAL
+
+20. Hydrophilicity from HPLC (Parker et al. 1986)
+Biochemistry (1986) 25 5425-5432
+2.1000 A ALA
+4.2000 R ARG
+7.0000 N ASN
+10.000 D ASP
+1.4000 C CYS
+6.0000 Q GLN
+7.8000 E GLU
+5.7000 G GLY
+2.1000 H HIS
+-8.000 I ILE
+-9.200 L LEU
+5.7000 K LYS
+-4.200 M MET
+-9.200 F PHE
+2.1000 P PRO
+6.5000 S SER
+5.2000 T THR
+-10.00 W TRP
+-1.900 Y TYR
+-3.700 V VAL
+
+21. Hydrophobicity (Jones 1975)
+J.theor.Biol.(1975) 50 167-183
+0.8700 A ALA
+0.8500 R ARG
+0.0900 N ASN
+0.6600 D ASP
+1.5200 C CYS
+0.0000 Q GLN
+0.6700 E GLU
+0.1000 G GLY
+0.8700 H HIS
+3.1500 I ILE
+2.1700 L LEU
+1.6400 K LYS
+1.6700 M MET
+2.8700 F PHE
+2.7700 P PRO
+0.0700 S SER
+0.0700 T THR
+3.7700 W TRP
+2.6700 Y TYR
+1.8700 V VAL
+
+22. Refractivity (Jones 1975)
+J.theor.Biol.(1975) 50 167-183
+4.3400� A ALA
+26.6600 R ARG
+13.2800 N ASN
+12.0000 D ASP
+35.7700 C CYS
+17.5600 Q GLN
+17.2600 E GLU
+0.0000� G GLY
+21.8100 H HIS
+19.0600 I ILE
+18.7800 L LEU
+21.2900 K LYS
+21.6400 M MET
+29.4000 F PHE
+10.9300 P PRO
+6.3500� S SER
+11.0100 T THR
+42.5300 W TRP
+31.5300 Y TYR
+13.9200 V VAL
+
+23. Percentage of buried residues (Janin et al. 1978)
+J. Mol. Biol. (1978) 125 357-386
+51.0000 A ALA
+5.0000� R ARG
+22.0000 N ASN
+19.0000 D ASP
+74.0000 C CYS
+16.0000 Q GLN
+16.0000 E GLU
+52.0000 G GLY
+34.0000 H HIS
+66.0000 I ILE
+60.0000 L LEU
+3.0000� K LYS
+52.0000 M MET
+58.0000 F PHE
+25.0000 P PRO
+35.0000 S SER
+30.0000 T THR
+49.0000 W TRP
+24.0000 Y TYR
+64.0000 V VAL
+
+24. Normalized frequency of alpha-helix with weights (Levitt 1978)
+Biochemistry (1978) 17 4277-4285
+1.2900 A ALA
+0.9600 R ARG
+0.9000 N ASN
+1.0400 D ASP
+1.1100 C CYS
+1.2700 Q GLN
+1.4400 E GLU
+0.5600 G GLY
+1.2200 H HIS
+0.9700 I ILE
+1.3000 L LEU
+1.2300 K LYS
+1.4700 M MET
+1.0700 F PHE
+0.5200 P PRO
+0.8200 S SER
+0.8200 T THR
+0.9900 W TRP
+0.7200 Y TYR
+0.9100 V VAL
+
+25. Normalized frequency of beta-sheet with weights (Levitt 1978)
+Biochemistry (1978) 17 4277-4285
+0.9000 A ALA
+0.9900 R ARG
+0.7600 N ASN
+0.7200 D ASP
+0.7400 C CYS
+0.8000 Q GLN
+0.7500 E GLU
+0.9200 G GLY
+1.0800 H HIS
+1.4500 I ILE
+1.0200 L LEU
+0.7700 K LYS
+0.9700 M MET
+1.3200 F PHE
+0.6400 P PRO
+0.9500 S SER
+1.2100 T THR
+1.1400 W TRP
+1.2500 Y TYR
+1.4900 V VAL
+
+26. Normalized frequency for reverse turn with weights (Levitt 1978)
+Biochemistry (1978) 17 4277-4285
+0.7800 A ALA
+0.8800 R ARG
+1.2800 N ASN
+1.4100 D ASP
+0.8000 C CYS
+0.9700 Q GLN
+1.0000 E GLU
+1.6400 G GLY
+0.6900 H HIS
+0.5100 I ILE
+0.5900 L LEU
+0.9600 K LYS
+0.3900 M MET
+0.5800 F PHE
+1.9100 P PRO
+1.3300 S SER
+1.0300 T THR
+0.7500 W TRP
+1.0500 Y TYR
+0.4700 V VAL
+
+27. Percentage of exposed residues (Janin et al. 1978)
+J. Mol. Biol. (1978) 125 357-386
+15.0000 A ALA
+67.0000 R ARG
+49.0000 N ASN
+50.0000 D ASP
+5.0000� C CYS
+56.0000 Q GLN
+55.0000 E GLU
+10.0000 G GLY
+34.0000 H HIS
+13.0000 I ILE
+16.0000 L LEU
+85.0000 K LYS
+20.0000 M MET
+10.0000 F PHE
+45.0000 P PRO
+32.0000 S SER
+32.0000 T THR
+17.0000 W TRP
+41.0000 Y TYR
+14.0000 V VAL
+
+28. Hydrophobic index (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+0.8700 A ALA
+0.8500 R ARG
+0.0900 N ASN
+0.6600 D ASP
+1.5200 C CYS
+0.0000 Q GLN
+0.6700 E GLU
+0.1000 G GLY
+0.8000 H HIS
+3.1500 I ILE
+2.1700 L LEU
+1.6400 K LYS
+1.6700 M MET
+2.8700 F PHE
+2.7700 P PRO
+0.0700 S SER
+0.0700 T THR
+3.7700 W TRP
+2.6700 Y TYR
+1.8700 V VAL
+
+29. Hydrophobicity in folded form (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+12.2800 A ALA
+11.4900 R ARG
+11.0000 N ASN
+10.9700 D ASP
+14.9300 C CYS
+11.2800 Q GLN
+11.1900 E GLU
+12.0100 G GLY
+12.8400 H HIS
+14.7700 I ILE
+14.1000 L LEU
+10.8000 K LYS
+14.3300 M MET
+13.4300 F PHE
+11.1900 P PRO
+11.2600 S SER
+11.6500 T THR
+12.9500 W TRP
+13.2900 Y TYR
+15.0700 V VAL
+
+30. Hydrophobicity in unfolded form (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+4.6600 A ALA
+4.6800 R ARG
+4.8700 N ASN
+4.7900 D ASP
+4.0000 C CYS
+4.6100 Q GLN
+4.8100 E GLU
+4.7000 G GLY
+4.9900 H HIS
+4.7800 I ILE
+4.7300 L LEU
+5.0800 K LYS
+4.5000 M MET
+4.4400 F PHE
+4.5500 P PRO
+4.3300 S SER
+4.7500 T THR
+4.5400 W TRP
+4.7600 Y TYR
+4.6900 V VAL
+
+31. Hydrophobicity gain (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+2.6300 A ALA
+2.4500 R ARG
+2.2700 N ASN
+2.2900 D ASP
+3.3600 C CYS
+2.4500 Q GLN
+2.3100 E GLU
+2.5500 G GLY
+2.5700 H HIS
+3.0800 I ILE
+2.9800 L LEU
+2.1200 K LYS
+3.1800 M MET
+3.0200 F PHE
+2.4600 P PRO
+2.6000 S SER
+2.5500 T THR
+2.8500 W TRP
+2.7900 Y TYR
+3.2100 V VAL
+
+32. Polarity (Ponnuswamy et al. 1980)
+Biochim.Biophys.Acta(1980) 623 301-316
+0.0000 A ALA
+52.000 R ARG
+3.3800 N ASN
+40.700 D ASP
+1.4800 C CYS
+3.5300 Q GLN
+49.910 E GLU
+0.0000 G GLY
+51.600 H HIS
+0.1500 I ILE
+0.4500 L LEU
+49.500 K LYS
+1.4300 M MET
+0.3500 F PHE
+1.5800 P PRO
+1.6700 S SER
+1.6600 T THR
+2.1000 W TRP
+1.6100 Y TYR
+0.1300 V VAL
+
+33. Average isotopic mass (Biemann, 1990)
+Meth.Enzimol. (1990) v.193, p.888
+70.079 A ALA 
+156.188 R ARG 
+114.104 N ASN 
+115.089 D ASP 
+103.144 C CYS 
+128.131 Q GLN 
+129.116 E GLU 
+57.052� G GLY 
+137.142 H HIS 
+113.160 I ILE 
+113.160 L LEU 
+128.174 K LYS 
+131.198 M MET 
+147.177 F PHE 
+97.177� P PRO 
+87.078� S SER 
+101.105 T THR 
+186.213 W TRP 
+163.170 Y TYR 
+99.133� V VAL 
+
+34.Isoelectric point (Zimmerman et al., 1968)
+J. Theor. Biol. (1968) v.21, p.170-201
+6.0000 A ALA
+10.7600 R ARG
+5.4100 N ASN
+2.7700 D ASP
+5.0500 C CYS
+5.6500 Q GLN
+3.2200 E GLU
+5.9700 G GLY
+7.5900 H HIS
+6.0200 I ILE
+5.9800 L LEU
+9.7400 K LYS
+5.7400 M MET
+5.4800 F PHE
+6.3000 P PRO
+5.6800 S SER
+5.6600 T THR
+5.8900 W TRP
+5.6600 Y TYR
+5.9600 V VAL
+
+35. pK of side chain (White et al., 1978)
+White A,Handler P,Smith EL,Hill RL,Lehman IR;Principles of Biochemistry;1978
+0.0000 A ALA
+12.480 R ARG
+0.0000 N ASN
+3.6500 D ASP
+8.1800 C CYS
+0.0000 Q GLN
+4.2500 E GLU
+0.0000 G GLY
+6.0000 H HIS
+0.0000 I ILE
+0.0000 L LEU
+10.530 K LYS
+0.0000 M MET
+0.0000 F PHE
+0.0000 P PRO
+0.0000 S SER
+0.0000 T THR
+0.0000 W TRP
+10.700 Y TYR
+0.0000 V VAL
+
+36. Energy of transfer from water to ethanol kcal/mol (Nozaki & Tanford, 1971)
+J.Biol.Chem. (1971) 246 2211-2217 
+-0.5000 A ALA
+-0.1000 R ARG
+0.1100� N ASN
+-0.2000 D ASP
+-0.5000 C CYS
+0.2000� Q GLN
+-0.3000 E GLU
+0.0000� G GLY
+-0.4000 H HIS
+-2.0000 I ILE
+-2.0000 L LEU
+-0.3000 K LYS
+-1.3000 M MET
+-2.5000 F PHE
+-1.0000 P PRO
+-0.2000 S SER
+-0.4000 T THR
+-3.0000 W TRP
+-2.2000 Y TYR
+-1.5000 V VAL
+
+
diff --git a/Source/mesquite/molec/explanation.txt b/Source/mesquite/molec/explanation.txt
new file mode 100644
index 0000000..01250eb
--- /dev/null
+++ b/Source/mesquite/molec/explanation.txt
@@ -0,0 +1,2 @@
+Miscellanous Molecular Utilities
+A collection of various utilities for use with molecular data.  Some calculate statistics about characters (percent gaps, GC bias, and so on); others manipulate sequences.
diff --git a/Source/mesquite/molec/lib/AAProperty.java b/Source/mesquite/molec/lib/AAProperty.java
new file mode 100644
index 0000000..fe6f1c0
--- /dev/null
+++ b/Source/mesquite/molec/lib/AAProperty.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib; 
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+public abstract class AAProperty extends MesquiteModule {
+   	 public Class getDutyClass() {
+   	 	return AAProperty.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Amino Acid Property";
+   	 }
+	/*.................................................................................................................*/
+	public abstract double getProperty(int aa);
+	
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresProteinData();
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/molec/lib/BLASTResults.java b/Source/mesquite/molec/lib/BLASTResults.java
new file mode 100644
index 0000000..0fdfa17
--- /dev/null
+++ b/Source/mesquite/molec/lib/BLASTResults.java
@@ -0,0 +1,319 @@
+package mesquite.molec.lib;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hivemind.util.PropertyUtils;
+import org.dom4j.*;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+
+public class BLASTResults {
+	protected double[] eValue;
+	protected double[] bitScore ;
+	protected String[] taxonomy;
+	protected String[] definition;
+	protected String[] accession;
+	protected String[] ID;
+	protected int[] frame;
+	protected String[] sequence;
+	protected boolean[] reversed;
+	protected int numHits = 0;
+	int maxHits = 1;
+
+	public BLASTResults (int maxHits) {
+		this.maxHits = maxHits;
+		initialize();
+	}
+	public void initialize() {
+		eValue = new double[maxHits];
+		bitScore = new double[maxHits];
+		taxonomy = new String[maxHits];
+		definition = new String[maxHits];
+		accession = new String[maxHits];
+		frame = new int[maxHits];
+		ID = new String[maxHits];
+		reversed = new boolean[maxHits];
+		zeroArrays();
+	}
+	public void zeroArrays() {
+		for (int i=0; i<maxHits; i++) {
+			eValue[i]= -1.0;
+			bitScore[i] = 0.0;
+			taxonomy[i] = "";
+			definition[i] = "";
+			accession[i] = "";
+			frame[i] = 0;
+			reversed[i] = false;
+			ID[i] = "";
+		}
+	}
+	public double geteValue(int index) {
+		return eValue[index];
+	}
+	public void seteValue(double eValue, int index) {
+		this.eValue[index] = eValue;
+	}
+	public double getBitScore(int index) {
+		return bitScore[index];
+	}
+	public void setBitScore(double bitScore, int index) {
+		this.bitScore[index] = bitScore;
+	}
+	public boolean getReversed(int index) {
+		return reversed[index];
+	}
+	public void setReversed(boolean reversed, int index) {
+		this.reversed[index] = reversed;
+	}
+	public String getTaxonomy(int index) {
+		return taxonomy[index];
+	}
+	public void setTaxonomy(String taxonomy, int index) {
+		this.taxonomy[index] = taxonomy;
+	}
+	public int getFrame(int index) {
+		return frame[index];
+	}
+	public void setFrame(int frame, int index) {
+		this.frame[index] = frame;
+	}
+	public String getDefinition(int index) {
+		return definition[index];
+	}
+	public void setDefinition(String definition, int index) {
+		this.definition[index] = definition;
+	}
+	public String getAccession(int index) {
+		return accession[index];
+	}
+	public void setAccession(String accession, int index) {
+		this.accession[index] = accession;
+	}
+	public String[] getAccessions() {
+		return accession;
+	}
+	public String getID(int index) {
+		return ID[index];
+	}
+	public void setID(String ID, int index) {
+		this.ID[index] = ID;
+	}
+	public String[] getIDs() {
+		return ID;
+	}
+	public void setNumHits(int numHits) {
+		this.numHits = numHits;
+	}
+	public int getNumHits() {
+		return numHits;
+	}
+	public String reversedToString() {
+		String s = "";
+		for (int i=0; i<maxHits && i<reversed.length; i++) {
+			if (reversed[i]) 
+				s+= " - ";
+			else 
+				s+= " + ";
+		}
+		return s;
+	}
+
+
+	public String getSequence(int index) {
+		return sequence[index];
+	}
+	public void setSequence(String sequence, int index) {
+		this.sequence[index] = sequence;
+	}
+
+	public String toString(int numHits) {
+		StringBuffer sb = new StringBuffer();
+		sb.append("   Top hits\n\tAccession\t[eValue]\tDefinition: \n");
+		for (int i=0; i<maxHits && i<numHits && i<accession.length; i++) {
+			if (StringUtil.notEmpty(accession[i])){
+				/*				if (reversed[i])
+					sb.append("\t-");
+				else 
+					sb.append("\t+");
+				 */				sb.append("\t"+ accession[i] + "\t[" + eValue[i]+ "]\t" + definition[i]+"\n");
+			}
+		}
+		return sb.toString();
+	}
+
+
+	/*.................................................................................................................*/
+	public boolean acceptableHit(int hitCount, double bitScore, double eValue) {
+		return hitCount<=maxHits;
+	}
+	/*.................................................................................................................*/
+	public boolean someHits() {
+		for (int i=0; i<maxHits; i++) {
+			if (StringUtil.notEmpty(getAccession(i))) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public  void setIDFromDefinition(String separator, int index){
+		String s="";
+		for (int i=0; i<maxHits && i<ID.length; i++) {
+			if (StringUtil.notEmpty(definition[i])){
+				s=StringUtil.getItem(definition[i],"|", index);
+				if (StringUtil.notEmpty(s))
+					ID[i] = s;
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public int hitsSatisfyMatches (String[] matchInDefinitions, int minNumToMatch, int maxNumToMatch, boolean noOthers, boolean onlyMatchOnce) {  
+		if (minNumToMatch==0 || matchInDefinitions==null)
+			return 0;
+		boolean[] alreadyMatched = new boolean[matchInDefinitions.length];
+		for (int j=0; j<alreadyMatched.length; j++){
+			alreadyMatched[j]=false;
+		}
+
+		int count = 0;
+		for (int i=0; i<maxHits && i<definition.length; i++) {  // go through the hits
+			if (StringUtil.notEmpty(definition[i])) {
+				boolean foundMatch = false;
+				for (int j=0; j<matchInDefinitions.length && !foundMatch; j++){ 
+					if (StringUtil.notEmpty(definition[i])&&StringUtil.notEmpty(matchInDefinitions[j])) {
+						int index = StringUtil.indexOfIgnoreCase(definition[i], matchInDefinitions[j]);
+						if (index>=0){
+							if (onlyMatchOnce && alreadyMatched[j])
+								return 0;
+							alreadyMatched[j]=true;
+							count++;
+							foundMatch=true;
+						}
+					}
+				}
+				if (!foundMatch) {  // here is something that is not in the match list
+					return 0;
+				}
+			}
+		}
+		if (count>=minNumToMatch && count <= maxNumToMatch)
+			return count;
+		return 0;
+	}
+
+	/*.................................................................................................................*/
+	public  void setIDFromDefinition(){
+		String s="";
+		for (int i=0; i<maxHits && i<ID.length; i++) {
+			if (StringUtil.notEmpty(definition[i])){
+				ID[i] = definition[i];
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public  void setIDFromElement(String separator, int index){
+		String s="";
+		for (int i=0; i<maxHits && i<ID.length; i++) {
+			if (StringUtil.notEmpty(ID[i])){
+				s=StringUtil.getItem(ID[i],"|", index);
+				if (StringUtil.notEmpty(s))
+					ID[i] = s;
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public  void setAccessionFromDefinition(String separator, int index){
+		String s="";
+		for (int i=0; i<maxHits && i<accession.length; i++) {
+			if (StringUtil.notEmpty(definition[i])){
+				s=StringUtil.getItem(definition[i],"|", index);
+				if (StringUtil.notEmpty(s))
+					accession[i] = s;
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public  void setAccessionsFromIDs(boolean nucleotides){
+		accession = NCBIUtil.getGenBankAccessionFromID(ID, nucleotides, null, false);
+	}
+
+	/*.................................................................................................................*/
+	public  boolean processResultsFromBLAST(String response, boolean storeSequences, double eValueCutoff){
+		if (accession==null)
+			return false;
+		zeroArrays();
+		Element blastOutputElement = XMLUtil.getRootXMLElementFromString("BlastOutput",response);
+		if (blastOutputElement==null)
+			return false;
+		numHits = 0;
+		Element blastIterationsElement = blastOutputElement.element("BlastOutput_iterations");
+		if (blastIterationsElement!=null) {
+			Element IterationsElement = blastIterationsElement.element("Iteration");
+			if (IterationsElement!=null) {
+				Element IterationHitElement = IterationsElement.element("Iteration_hits");
+				if (IterationHitElement!=null) {
+					List hitList = IterationHitElement.elements("Hit");
+					for (Iterator iter = hitList.iterator(); iter.hasNext() && numHits<maxHits;) {   // this is going through all of the hits
+						Element hitElement = (Element) iter.next();
+						if (hitElement!=null) {
+
+							String s = hitElement.elementText("Hit_def");
+							setDefinition(s, numHits);
+
+							s = hitElement.elementText("Hit_accession");
+							setAccession(s, numHits);
+
+							s = hitElement.elementText("Hit_id");
+							//s=StringUtil.getItem(s,"|", 2);
+							if (StringUtil.notEmpty(s))
+								setID(s, numHits);
+
+							Element hithsps = hitElement.element("Hit_hsps");
+							if (hithsps!=null) {
+								Element Hsp = hithsps.element("Hsp");
+								if (Hsp!=null) {
+									String eValue = Hsp.elementText("Hsp_evalue");
+									double eValueDouble = MesquiteDouble.fromString(eValue);
+									if (eValueCutoff< 0.0 || eValueDouble<=eValueCutoff) {
+										seteValue(eValueDouble, numHits);
+										setBitScore(MesquiteDouble.fromString(Hsp.elementText("Hsp_bit-score")), numHits);
+										setFrame(MesquiteInteger.fromString(Hsp.elementText("Hsp_hit-frame")), numHits);
+
+										int queryFrame = MesquiteInteger.fromString(Hsp.elementText("Hsp_query-frame"));
+										setReversed(queryFrame<0, numHits);
+
+										if (storeSequences)
+											setSequence(Hsp.elementText("Hsp_hseq"), numHits);
+									} else if (eValueCutoff>=0.0 && eValueDouble>eValueCutoff) {
+										setDefinition("", numHits);
+										setAccession("", numHits);
+										setID("", numHits);
+										setFrame(0, numHits);
+										numHits--;
+									}
+								}
+							}
+							numHits++;
+						}
+
+					}
+					return true;
+
+				}
+			}
+		}
+		return false;
+	}
+
+	//	Alternatively, You can look at the query start/end and subject start/end coordinates. If your query aligns to reverse of subject, then the subject end 
+	//coordinate will be smaller than the start coordinate. For example, if SeqA aligns to reverse of SeqB, you might see position 50-100 of SeqA 
+	// aligning to position 200-150 of SeqB.
+
+}
diff --git a/Source/mesquite/molec/lib/Blaster.java b/Source/mesquite/molec/lib/Blaster.java
new file mode 100644
index 0000000..b4192c6
--- /dev/null
+++ b/Source/mesquite/molec/lib/Blaster.java
@@ -0,0 +1,112 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import java.awt.*;
+
+import mesquite.categ.lib.DNAData;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+
+
+/* ======================================================================== */
+
+public abstract class Blaster extends MesquiteModule   {
+	public static final int DONTBLAST = -1;
+	public static final int BLAST = 0;
+	public static final int BLASTX = 1;
+	public static final int TBLASTX = 2;
+	static final String[] blastTypeNames = new String[] {"BLAST", "BLASTX", "TBLASTX"};
+	protected boolean blastx = false;
+	protected int blastType = BLAST;
+
+	public Class getDutyClass() {
+		return Blaster.class;
+	}
+	public String getDutyName() {
+		return "Blaster";
+	}
+
+	public String[] getDefaultModule() {
+		return new String[] {"#NCBIBlaster"};
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public abstract boolean initialize();
+
+	public abstract void blastForMatches(String blastType, String sequenceName, String sequence, boolean isNucleotides, int numHits, int maxTime, double eValueCutoff, int wordSize, StringBuffer blastResponse, boolean writeTime);
+
+	public abstract String getFastaFromIDs(String[] idList,  boolean isNucleotides, StringBuffer fastaBlastResults);
+
+	public abstract String getTaxonomyFromID(String id, boolean isNucleotides, boolean writeLog, StringBuffer report);
+
+	public abstract String[] getNucleotideIDsfromProteinIDs(String[] ID);
+
+	public abstract String getDatabaseName ();
+
+
+	public  void postProcessingCleanup(BLASTResults blastResult){
+	}
+
+	public  int getUpperLimitMaxHits(){
+		return 60;
+	}
+
+	public boolean isBlastx() {
+		return blastx;
+	}
+	public void setBlastx(boolean blastx) {
+		this.blastx = blastx;
+	}
+	 
+
+	public int getBlastType() {
+		return blastType;
+	}
+	public void setBlastType(int blastType) {
+		this.blastType = blastType;
+		setBlastx (blastType==BLASTX);
+	}
+
+	public  void basicDNABlastForMatches(int blastOption, String sequenceName, String sequence, int numHits, double eValueCutoff, int wordSize, StringBuffer blastResponse, boolean writeTime){
+		basicDNABlastForMatches(blastOption,  sequenceName,  sequence,  numHits, 300, eValueCutoff, wordSize, blastResponse,  writeTime);
+	}
+
+	public  void basicDNABlastForMatches(int blastOption, String sequenceName, String sequence, int numHits, int maxTime, double eValueCutoff, int wordSize, StringBuffer blastResponse, boolean writeTime){
+		switch (blastOption) {
+		case Blaster.BLAST: 
+			blastForMatches("blastn", sequenceName, sequence, true, numHits, maxTime, eValueCutoff, wordSize,blastResponse, writeTime);
+			break;
+		case Blaster.BLASTX: 
+			blastForMatches("blastx", sequenceName, sequence, true, numHits, maxTime, eValueCutoff, wordSize,blastResponse, writeTime);
+			break;
+		case Blaster.TBLASTX: 
+			blastForMatches("tblastx", sequenceName, sequence, true, numHits, maxTime, eValueCutoff, wordSize,blastResponse, writeTime);
+			break;
+		default: 
+			blastForMatches("blastn", sequenceName, sequence, true, numHits, maxTime, eValueCutoff, wordSize,blastResponse, writeTime);
+			break;
+		}
+	}
+	static public String getBlastTypeName(int blastOption) {
+		if (blastOption<0 || blastOption>=blastTypeNames.length) return "";
+		return blastTypeNames[blastOption];
+	}
+	
+	static public String[] getBlastTypeNames() {
+		return blastTypeNames;
+	}
+	
+}
+
diff --git a/Source/mesquite/molec/lib/DNADatabaseURLSource.java b/Source/mesquite/molec/lib/DNADatabaseURLSource.java
new file mode 100644
index 0000000..a028345
--- /dev/null
+++ b/Source/mesquite/molec/lib/DNADatabaseURLSource.java
@@ -0,0 +1,53 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import java.util.Hashtable;
+
+import mesquite.lib.*;
+
+public abstract class DNADatabaseURLSource extends DatabaseURLSource {
+	public static final int PRIMER_NAME = 1;
+	public static final int SAMPLE_CODE = 2;
+	public static final int EXTRACTION_CODE = 2;
+	public static final int PCR_REACTION_CODE = 3;
+	public static final int AUTHORIZATION_KEY = 4;
+	public static final int GENE = 5;
+	public static final int TAXON = 6;
+	public static final int NAME = 7;
+	public static final int EXTRACTION = 8;
+	public static final int FASTA=9;
+	public static final int COUNT=10;
+	
+	
+
+	
+	public static final int PRIMER_SERVICE = 1;
+	public static final int SEQUENCE_NAME_SERVICE = 2;
+	public static final int CONTRIBUTOR_SERVICE = 3;
+	public static final int CHROMATOGRAM_SEARCH_SERVICE = 4;
+	public static final int SEQUENCE_UPLOAD_SERVICE = 5;
+	public static final int FASTA_UPLOAD_SERVICE = 6;
+	public static final int CHROMATOGRAM_BATCH_CREATION_SERVICE = 7;
+	public static final int CHROMATOGRAM_DOWNLOAD_SERVICE = 8;
+
+	public static final int SEQUENCE_ELEMENT=1;
+	
+	public boolean includeSampleCodePrefixInSampleCode() {
+		return false;
+	}
+	
+	public abstract String getChromatogramDownloadURL(Hashtable args);
+
+}
diff --git a/Source/mesquite/molec/lib/FindSequenceCriterion.java b/Source/mesquite/molec/lib/FindSequenceCriterion.java
new file mode 100644
index 0000000..d6521a9
--- /dev/null
+++ b/Source/mesquite/molec/lib/FindSequenceCriterion.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+/* ======================================================================== *
+
+*new in 1.05*
+
+/* ======================================================================== */
+public abstract class FindSequenceCriterion extends MesquiteModule {
+   	 public Class getDutyClass() {
+   	 	return FindSequenceCriterion.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Criterion for finding sequences";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#MatchingSequence"};
+   	 }
+
+	public abstract boolean showOptions(CharacterData data, MesquiteTable table);
+	
+}
+
+
diff --git a/Source/mesquite/molec/lib/FindSequenceCriterionG.java b/Source/mesquite/molec/lib/FindSequenceCriterionG.java
new file mode 100644
index 0000000..43b5d69
--- /dev/null
+++ b/Source/mesquite/molec/lib/FindSequenceCriterionG.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.table.*;
+/* ======================================================================== *
+
+*new in 1.05*
+
+/* ======================================================================== */
+public abstract class FindSequenceCriterionG extends FindSequenceCriterion {
+   	 public Class getDutyClass() {
+   	 	return FindSequenceCriterionG.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Criterion for finding sequences";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#MatchingSequence"};
+   	 }
+
+	public abstract boolean showOptions(boolean findAll, CharacterData data, MesquiteTable table);
+	
+	public boolean showOptions(boolean findAll){
+		return showOptions(findAll, null, null);
+	}
+	public boolean showOptions(CharacterData data, MesquiteTable table){
+		return showOptions(false, data, table);
+	}
+	
+	//It is the responsibility of this module to select cells, but not to focus on them
+   	public abstract boolean findNext(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound);
+}
+
+
diff --git a/Source/mesquite/molec/lib/GBLOCKSCalculator.java b/Source/mesquite/molec/lib/GBLOCKSCalculator.java
new file mode 100644
index 0000000..c56811a
--- /dev/null
+++ b/Source/mesquite/molec/lib/GBLOCKSCalculator.java
@@ -0,0 +1,509 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.*;
+
+import mesquite.categ.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class GBLOCKSCalculator implements  XMLPreferencesProcessor, ActionListener {
+
+
+	static final double defaultIS = 0.50;   
+	static final double defaultFS = 0.85;  
+	static final int defaultCP=8;  
+	static final int defaultBL=10;  
+	static final double defaultGapThreshold = 0.0;
+	static final boolean defaultChooseAmbiguousSites = true;
+	static final boolean defaultCountWithinApplicable = false;
+
+	double IS = defaultIS;   // fraction of identical residues that is upper boundary for non-conserved sequences
+	int ISint=0;  // integral version of above
+	double FS = defaultFS;  // fraction of identical residues that is upper boundary for conserved sequences
+	int FSint = 0;  //integeral version of above
+	int CP=defaultCP;  //block size limit for non-conserved blocks
+	int BL=defaultBL;  //  small region block size limit 
+	double gapThreshold = defaultGapThreshold;   // the fraction of gaps allowed at a site
+	int gapThresholdInt = 0;
+	boolean removeAllGaps = true;
+	boolean chooseAmbiguousSites = defaultChooseAmbiguousSites;
+	boolean countWithinApplicable = defaultCountWithinApplicable;   // count fractions of identical residues only within those taxa without gaps at a site
+	boolean[] hasApplicable=null;
+
+	//boolean preferencesSet = false;
+
+
+	public GBLOCKSCalculator (MesquiteModule ownerModule, String xmlPrefsString){
+		XMLUtil.readXMLPreferences(ownerModule, this, xmlPrefsString);
+
+	}
+
+
+
+	public void processSingleXMLPreference (String tag, String flavor, String content){
+		processSingleXMLPreference(tag, null, content);
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("IS".equalsIgnoreCase(tag))
+			IS = MesquiteDouble.fromString(content);
+		if ("FS".equalsIgnoreCase(tag))
+			FS = MesquiteDouble.fromString(content);
+		if ("CP".equalsIgnoreCase(tag))
+			CP = MesquiteInteger.fromString(content);
+		if ("BL".equalsIgnoreCase(tag))
+			BL = MesquiteInteger.fromString(content);
+		if ("gapThreshold".equalsIgnoreCase(tag))
+			gapThreshold = MesquiteDouble.fromString(content);
+		if ("chooseAmbiguousSites".equalsIgnoreCase(tag))
+			chooseAmbiguousSites = MesquiteBoolean.fromTrueFalseString(content);
+		if ("countWithinApplicable".equalsIgnoreCase(tag))
+			countWithinApplicable = MesquiteBoolean.fromTrueFalseString(content);
+	}
+
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "IS", IS);  
+		StringUtil.appendXMLTag(buffer, 2, "FS", FS);  
+		StringUtil.appendXMLTag(buffer, 2, "CP", CP);  
+		StringUtil.appendXMLTag(buffer, 2, "BL", BL);  
+		StringUtil.appendXMLTag(buffer, 2, "gapThreshold", gapThreshold);  
+		StringUtil.appendXMLTag(buffer, 2, "chooseAmbiguousSites", chooseAmbiguousSites);  
+		StringUtil.appendXMLTag(buffer, 2, "countWithinApplicable", countWithinApplicable);  
+
+		return buffer.toString();
+	}
+	
+	public boolean getChooseAmbiguousSites() {
+		return chooseAmbiguousSites;
+	}
+
+	public void setChooseAmbiguousSites(boolean chooseAmbiguousSites) {
+		this.chooseAmbiguousSites = chooseAmbiguousSites;
+	}
+
+	
+	Button useDefaultsButton = null;
+	DoubleField ISfield = null;
+	DoubleField FSfield=null;
+	Checkbox countWithinApplicableCheckbox=null;
+	IntegerField CPfield =null;
+	IntegerField BLfield=null;
+	DoubleField gapThresholdField=null;
+	Checkbox chooseAmbiguousSitesCheckbox=null;
+	/*.................................................................................................................*/
+	public String getActionToUse(String action) {
+		String actionToUse = "Choose";
+		if (StringUtil.notEmpty(action))
+			actionToUse=action;
+		return actionToUse;
+	}
+
+	/*.................................................................................................................*/
+	/**This queryOptions is provided in case the module that uses this GBLOCKSCalculator doesn't want to add extra options, and just wants to use
+	 * a simple dialog box to query for options. If the ownermodule wishes, it can make its own dialog box; use this one as a template. */
+	public boolean queryOptions(MesquiteModule mb, String action) {
+		if (!mb.okToInteractWithUser(mb.CAN_PROCEED_ANYWAY, "Querying Options"))  //Debugg.println needs to check that options set well enough to proceed anyway
+			return true;
+		String actionToUse = getActionToUse(action);
+
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(mb.containerOfModule(),  actionToUse+ " using GBLOCKS Algorithm",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		String helpString = "This feature will " + actionToUse.toLowerCase() +  " characters using the GBLOCKS algorithm, as described in Castresana (2000).";
+
+		dialog.appendToHelpString(helpString);
+
+		dialog.addLabel(actionToUse + " Characters using Extended GBLOCKS Algorithm");
+
+		addToQueryOptions(dialog, action);
+
+		dialog.addNewDialogPanel();
+		useDefaultsButton = dialog.addAListenedButton("Set to Defaults", null, this);
+		useDefaultsButton.setActionCommand("setToDefaults");
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			processQueryOptions(dialog);
+			mb.storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public void actionPerformed(ActionEvent e) {
+		if (e.getActionCommand().equalsIgnoreCase("setToDefaults")) {
+			setToDefaults();
+		} 
+	}
+
+	/*.................................................................................................................*/
+	public void addToQueryOptions(ExtensibleDialog dialog, String action) {
+		ISfield = dialog.addDoubleField("Minimum fraction of identical residues for conserved positions", IS, 4);
+		FSfield = dialog.addDoubleField("Minimum fraction of identical residues for highly-conserved positions", FS, 4);
+		countWithinApplicableCheckbox = dialog.addCheckBox("count fraction only within taxa with non-gaps at that position", countWithinApplicable);
+		dialog.addHorizontalLine(1);
+		CPfield = dialog.addIntegerField("Maximum length of non-conserved blocks", CP, 4);
+		BLfield = dialog.addIntegerField("Minimum length of a block", BL, 4);
+
+		gapThresholdField = dialog.addDoubleField("Fraction of gaps allowed in a character", gapThreshold, 4);
+		
+		dialog.addHorizontalLine(1);
+		String actionToUse = getActionToUse(action);
+
+		chooseAmbiguousSitesCheckbox = dialog.addCheckBox(actionToUse.toLowerCase()+ " sites in ambiguously aligned regions", chooseAmbiguousSites);
+	}
+	/*.................................................................................................................*/
+	public void processQueryOptions(ExtensibleDialog dialog) {
+		IS = ISfield.getValue();
+		FS = FSfield.getValue();
+		CP = CPfield.getValue();
+		BL = BLfield.getValue();
+		gapThreshold = gapThresholdField.getValue();
+		countWithinApplicable = countWithinApplicableCheckbox.getState();
+		chooseAmbiguousSites = chooseAmbiguousSitesCheckbox.getState();
+	}
+	/*.................................................................................................................*/
+	public void setToDefaults() {
+		ISfield.setValue(defaultIS);	
+		FSfield.setValue(defaultFS);
+		CPfield.setValue(defaultCP);
+		BLfield.setValue(defaultBL);
+		gapThresholdField.setValue(defaultGapThreshold);
+		countWithinApplicableCheckbox.setState(defaultCountWithinApplicable);
+		chooseAmbiguousSitesCheckbox.setState(defaultChooseAmbiguousSites);
+	}
+
+
+	/*.................................................................................................................*/
+	int maxNumberIdenticalResidues (CategoricalData data, int ic) {
+		int[] numTaxaWithResidue = null;
+		if (data instanceof DNAData)
+			numTaxaWithResidue= new int[DNAState.maxDNAState+1];
+		else if (data instanceof ProteinData)
+			numTaxaWithResidue= new int[ProteinState.maxProteinState+1];
+
+		CategoricalState cs = null;
+		for (int it = 0; it<data.getNumTaxa(); it++) {   // calculate proportions
+			cs = (CategoricalState)data.getCharacterState(cs, ic, it);
+			if (!(cs.isUnassigned() || cs.isInapplicable() || !cs.isCombinable() || cs.cardinality()>1)) {  // single element
+				int state = cs.getOnlyElement(cs.getValue());
+				if (state>=0 && state<numTaxaWithResidue.length)
+					numTaxaWithResidue[state]++;
+			}
+		}
+
+		int maxCount=0;
+		for (int is=0; is<numTaxaWithResidue.length; is++){
+			if (numTaxaWithResidue[is]>maxCount)
+				maxCount=numTaxaWithResidue[is];
+		}
+
+		return maxCount;
+	}
+	/*.................................................................................................................*/
+	int numNonGaps (CategoricalData data, int ic) {
+		int count=0;
+		for (int it = 0; it<data.getNumTaxa(); it++) {   // calculate proportions
+			if (!data.isInapplicable(ic, it)) { 
+				count++;
+			}
+		}
+		return count;
+	}
+
+	/*.................................................................................................................*/
+	boolean tooManyGaps (CategoricalData data, int ic) {
+		if (hasApplicable==null)
+			return false;
+		if (removeAllGaps) {
+			for (int it = 0; it<data.getNumTaxa(); it++) {
+				if (data.isInapplicable(ic, it))
+					return true;
+			}
+		} else {
+			int count = 0;
+			for (int it = 0; it<data.getNumTaxa(); it++) {
+				if (data.isInapplicable(ic, it) && it<hasApplicable.length && hasApplicable[it])
+					count++;
+			}
+			if (count >gapThresholdInt)
+				return true;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	static final int STATUSUNSET=0;
+	static final int NONCONSERVED = 1;
+	static final int WITHGAP = 4;
+	static final int CONSERVED = 2;
+	static final int HIGHLYCONSERVED = 3;
+
+	/*.................................................................................................................*/
+	void setCharacterStatus(CategoricalData data, int[] status){
+		if (data==null || status == null )
+			return;
+		for (int ic=0; ic<data.getNumChars() && ic<status.length; ic++) {
+			if (tooManyGaps(data,ic))
+				status[ic] = NONCONSERVED; 
+			else {
+				int maxIdentical = maxNumberIdenticalResidues(data, ic);
+				if (!countWithinApplicable) {
+					if (maxIdentical<ISint)
+						status[ic] = NONCONSERVED; 
+					else if (maxIdentical<FSint)
+						status[ic] = CONSERVED; 
+					else 
+						status[ic] = HIGHLYCONSERVED; 
+				} else {
+					int totalResidues = numNonGaps(data,ic);
+					if (1.0*maxIdentical/totalResidues<IS)
+						status[ic] = NONCONSERVED; 
+					else if (1.0*maxIdentical/totalResidues<FS)
+						status[ic] = CONSERVED; 
+					else 
+						status[ic] = HIGHLYCONSERVED; 
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	void setToSelectRange(boolean[] setToSelect, int icStart, int icEnd){
+		if (setToSelect==null)
+			return;
+		for (int ic=icStart; ic<=icEnd && ic<setToSelect.length; ic++)
+			setToSelect[ic]=true;
+	}
+	/*.................................................................................................................*/
+	void examineRemainingBlock(int[] status, boolean[] setToSelect, int icStart, int icEnd){
+		for (int ic=icStart; ic<=icEnd && ic<setToSelect.length; ic++)
+			if (status[ic]!=HIGHLYCONSERVED)  // if it is not highly conserved, then need to select it
+				setToSelect[ic]=true;
+			else  // the moment we have a highly conserved one, get out of loop
+				break;
+		for (int ic=icEnd; ic>=icStart; ic--)
+			if (status[ic]!=HIGHLYCONSERVED)  // if it is not highly conserved, then need to select it
+				setToSelect[ic]=true;
+			else  // the moment we have a highly conserved one, get out of loop
+				break;
+	}
+	/*.................................................................................................................*/
+	void examineRegionAroundGap(int[] status, boolean[] setToSelect, int icGap){
+		setToSelect[icGap]=true;
+		for (int ic=icGap+1; ic<setToSelect.length; ic++){  // look up
+			if (setToSelect[ic])  // the moment we find one we have already excluded, break
+				break;
+			if (status[ic] == NONCONSERVED)  // if it is not highly conserved, then need to select it
+				setToSelect[ic]=true;
+		}
+		for (int ic=icGap-1; ic>=0; ic--) {
+			if (setToSelect[ic])  // the moment we find one we have already excluded, break
+				break;
+			if (status[ic] == NONCONSERVED)  // if it is not highly conserved, then need to select it
+				setToSelect[ic]=true;
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Called to mark characters*/
+	public boolean markCharacters(CharacterData data, MesquiteModule mb, boolean[] charToMark, StringBuffer results){
+		if (charToMark==null)
+			return false;
+		if (data!=null && data.getNumChars()>0){
+
+			hasApplicable = new boolean[data.getNumTaxa()];
+			for (int it = 0; it<data.getNumTaxa() && it<hasApplicable.length; it++) {
+				hasApplicable[it]=data.anyApplicableAfter(0, it);
+			}
+
+			int numTaxaWithApplicable = data.getNumTaxaWithAnyApplicable();
+			ISint= (int)(IS*numTaxaWithApplicable)+1;
+			FSint= (int)(FS*numTaxaWithApplicable);
+			gapThresholdInt = 	(int)(gapThreshold*numTaxaWithApplicable);
+			removeAllGaps=(gapThreshold==0.0);
+
+
+			//boolean[] charToMark = new boolean[data.getNumChars()];
+			int[] status = new int[data.getNumChars()];
+			for (int ic=0; ic<status.length; ic++) {
+				status[ic]=STATUSUNSET;
+				charToMark[ic] = false;
+			}
+
+			setCharacterStatus((CategoricalData)data, status);
+
+			// ======  first look for "stretches of contiguous nonconserved positions"
+			int blockStart=-1;
+			for (int ic=0; ic<data.getNumChars(); ic++) {
+				if (status[ic]==NONCONSERVED){
+					if (blockStart<0){  // start of block, so set the value
+						blockStart = ic;
+					}
+					if (ic==data.getNumChars()-1) {  // end of matrix, so need to check if block is big enough
+						if (ic-blockStart+1 > CP)  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic);
+					}
+				} else {  // let's check to see if we have reached the end of a non-conserved block
+					if (blockStart>=0){ // we were within a conserved block, now just one past it
+						if (ic-blockStart > CP)  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic-1);
+					}	
+					blockStart=-1;  // reset to make it clear we are no longer in a non-conserved block
+				}
+			}
+
+			// ======  examining flanks
+
+			blockStart=-1;
+
+			for (int ic=0; ic<data.getNumChars() && ic<charToMark.length; ic++){
+				if (!charToMark[ic]){  // we are in a remaining block
+					if (blockStart<0){  // start of block, so set the value
+						blockStart = ic;
+					}
+					if (ic==data.getNumChars()-1) {  // end of matrix, so need to check if block is big enough
+						examineRemainingBlock(status, charToMark,blockStart,ic);
+					}
+				} else {  // let's check to see if we have reached the end of a non-conserved block
+					if (blockStart>=0){ // we were within a conserved block, now just one past it
+						if (ic-blockStart > CP)  // block is big enough to be selected
+							examineRemainingBlock(status, charToMark,blockStart,ic-1);
+					}	
+					blockStart=-1;  // reset to make it clear we are no longer in a non-conserved block
+				}
+			}
+
+			// ======  checking for small blocks
+			blockStart=-1;
+
+			for (int ic=0; ic<data.getNumChars() && ic<charToMark.length; ic++){
+				if (!charToMark[ic]){
+					if (blockStart<0){  // start of block, so set the value
+						blockStart = ic;
+					}
+					if (ic==data.getNumChars()-1) {  // end of matrix, so need to check if block is big enough
+						if (ic-blockStart+1 < BL){  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic);
+						}
+					}
+				} else {  // let's check to see if we have reached the end of a non-conserved block
+					if (blockStart>=0){ // we were within a conserved block, now just one past it
+						if (ic-blockStart < BL){  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic-1);
+						}
+					}	
+					blockStart=-1;  // reset to make it clear we are no longer in a non-conserved block
+				}
+			}
+
+			// ======  checking for gaps and nearby non-conserved
+
+
+			for (int ic=0; ic<data.getNumChars() && ic<charToMark.length; ic++){
+				if (!charToMark[ic] && tooManyGaps((CategoricalData)data,ic)){  // let's start at any gap that is not yet excluded
+					examineRegionAroundGap(status, charToMark,ic);
+
+				}
+			}
+
+			// ======  checking for small blocks
+			blockStart=-1;
+
+			for (int ic=0; ic<data.getNumChars() && ic<charToMark.length; ic++){
+				if (!charToMark[ic]){
+					if (blockStart<0){  // start of block, so set the value
+						blockStart = ic;
+					}
+					if (ic==data.getNumChars()-1) {  // end of matrix, so need to check if block is big enough
+						if (ic-blockStart+1 < BL){  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic);
+						}
+					}
+				} else {  // let's check to see if we have reached the end of a non-conserved block
+					if (blockStart>=0){ // we were within a conserved block, now just one past it
+						if (ic-blockStart < BL){  // block is big enough to be selected
+							setToSelectRange(charToMark,blockStart,ic-1);
+						}
+					}	
+					blockStart=-1;  // reset to make it clear we are no longer in a non-conserved block
+				}
+			}
+
+			// ======  Now report the results
+
+			blockStart=-1;
+			StringBuffer blocks = new StringBuffer();
+			for (int ic=0; ic<data.getNumChars() && ic<charToMark.length; ic++){
+				if (!charToMark[ic]){
+					if (blockStart<0){  // start of block, so set the value
+						blockStart = ic;
+					}
+					if (ic==data.getNumChars()-1) {  // end of matrix
+						blocks.append(" [" + (blockStart+1)+" " + (ic+1)+ "]");
+					}
+				} else {  // let's check to see if we have reached the end of a  block
+					if (blockStart>=0){ // we were within the block, now just one past it
+						blocks.append(" [" + (blockStart+1)+" " + (ic)+ "]");
+					}	
+					blockStart=-1;  // reset to make it clear we are no longer in a non-conserved block
+				}
+			}
+
+			if (results!=null) {
+				results.append("\nGBLOCKS analysis\n");
+				if (countWithinApplicable) {
+					results.append("Minimum fraction of identical residues for a conserved position: " + IS+"\n");
+					results.append("Minimum fraction of identical residues for a highly-conserved position: " + FS+"\n");
+					results.append("Counting fraction within only those taxa that have non-gaps at that position\n");
+				} else {
+					results.append("Minimum number of identical residues for a conserved position: " + ISint+"\n");
+					results.append("Minimum number of identical residues for a highly-conserved position: " + FSint+"\n");
+					results.append("Counting fraction within all taxa\n");
+				}
+				results.append("Maximum number of contiguous non-conserved positions: " + CP+"\n");
+				results.append("Minimum length of a block: " + BL+"\n");
+				if (removeAllGaps)
+					results.append("Allowed gaps within a position: none\n");
+				else {
+					results.append("Allowed fraction of gaps within a position: " + gapThreshold+"\n");
+				}
+
+				results.append("Flank positions of the blocks chosen by the GBLOCKS algorithm: \n");
+				results.append(blocks.toString());
+
+				if (chooseAmbiguousSites)
+					results.append("\nNote:  selected characters are those that are the least conserved and more ambiguously aligned regions, and would typically be excluded before analysis.\n");
+				else 
+					results.append("\nNote:  selected characters are those that are the more conserved regions, and would typically be included in any analysis.\n");
+			}
+
+
+		}
+		return true;
+	}
+
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeBacteria.java b/Source/mesquite/molec/lib/GenCodeBacteria.java
new file mode 100644
index 0000000..196dd87
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeBacteria.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeBacteria extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+	}
+
+	public String getName (){
+		return "The Bacterial and Plant Plastid Code";
+	}
+
+	public static String getShortName (){
+		return "Bacteria and Plant Plastids";
+	}
+
+	public String getNEXUSName(){
+		return "bacterial";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 11;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeCiliate.java b/Source/mesquite/molec/lib/GenCodeCiliate.java
new file mode 100644
index 0000000..dc0629d
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeCiliate.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeCiliate extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(U,A,A, ProteinData.GLN);
+		setCode(U,A,G, ProteinData.GLN);
+	}
+
+	public String getName (){
+		return "The Ciliate, Dasycladacean and Hexamita Nuclear Code";
+	}
+
+	public static String getShortName (){
+		return "Ciliate Nuclear";
+	}
+
+	public String getNEXUSName(){
+		return "nuc.ciliate";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 6;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeEchino.java b/Source/mesquite/molec/lib/GenCodeEchino.java
new file mode 100644
index 0000000..345fa0b
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeEchino.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeEchino extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(A,A,A, ProteinData.ASN);
+		setCode(A,G,A, ProteinData.SER);
+		setCode(A,G,G, ProteinData.SER);
+		setCode(U,G,A, ProteinData.TRP);
+	}
+
+	public String getName() {
+		return "The Echinoderm and Flatworm Mitochondrial Code";
+	}
+
+	public static String getShortName (){
+		return "Echinoderm Mitochondrial";
+	}
+
+	public String getNEXUSName(){
+		return "mtdna.echino";
+	}
+	public int getNCBITranslationTableNumber(){
+		return 9;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeEuplotid.java b/Source/mesquite/molec/lib/GenCodeEuplotid.java
new file mode 100644
index 0000000..1779be3
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeEuplotid.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeEuplotid extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(U,G,A, ProteinData.CYS);
+	}
+
+	public String getName (){
+		return "The Euplotid Nuclear Code";
+	}
+
+	public static String getShortName (){
+		return "Euplotid Nuclear";
+	}
+
+	public String getNEXUSName(){
+		return "nuc.euplotid";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 10;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeInvertMito.java b/Source/mesquite/molec/lib/GenCodeInvertMito.java
new file mode 100644
index 0000000..dc74431
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeInvertMito.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeInvertMito extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(A,G,A, ProteinData.SER);
+		setCode(A,G,G, ProteinData.SER);
+		setCode(A,U,A, ProteinData.MET);
+		setCode(U,G,A, ProteinData.TRP);
+	}
+
+	public String getName() {
+		return "The Invertebrate Mitochondrial Genetic Code";
+	}
+
+	public static String getShortName (){
+		return "Invertebrate Mitochondrial";
+	}
+
+	public String getNEXUSName(){
+		return "mtdna.dros";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 5;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeModel.java b/Source/mesquite/molec/lib/GenCodeModel.java
new file mode 100644
index 0000000..8f5e726
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModel.java
@@ -0,0 +1,70 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Sublcass of models of character evolution for parsimony calculations.  It is expected
+that subclasses of this will be specialized for different classes of data (categorical, continuous, etc.)*/
+public abstract class GenCodeModel extends WholeCharacterModel implements Priority {
+	GeneticCode geneticCode;
+	public GenCodeModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+	public String getTypeName(){
+		return "Genetic code model";
+	}
+	public String getParadigm(){
+		return "GeneticCode";
+	}
+	/** returns nexus command introducing this model (e.g. "USERTYPE" or "CHARMODEL")*/
+	public String getNEXUSCommand() {
+		return "GENETICCODE";
+	}
+	public String getModelTypeName(){
+		return "Genetic code model";
+	}
+	public GeneticCode getGeneticCode(){
+		return geneticCode;
+	}
+	public String getNEXUSClassName(){
+		return "builtInGeneticCode";
+	}
+	public int getPriority(){
+		if (geneticCode!=null)
+			return geneticCode.getNCBITranslationTableNumber();
+		else
+			return 0;
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		if (geneticCode!=null)
+			return geneticCode.getName();
+		else
+			return "A genetic code model.";
+	}
+
+	public String getNEXUSName(){
+		if (geneticCode!=null)
+			return geneticCode.getNEXUSName();
+		else
+			return "";
+	}
+
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelBacteria.java b/Source/mesquite/molec/lib/GenCodeModelBacteria.java
new file mode 100644
index 0000000..81c0c32
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelBacteria.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelBacteria extends GenCodeModel{
+	public GenCodeModelBacteria(){
+		super(GenCodeBacteria.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeBacteria();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelCiliate.java b/Source/mesquite/molec/lib/GenCodeModelCiliate.java
new file mode 100644
index 0000000..1dee72c
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelCiliate.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelCiliate extends GenCodeModel{
+	public GenCodeModelCiliate(){
+		super(GenCodeCiliate.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeCiliate();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelEchino.java b/Source/mesquite/molec/lib/GenCodeModelEchino.java
new file mode 100644
index 0000000..6f9e831
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelEchino.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelEchino extends GenCodeModel{
+	public GenCodeModelEchino(){
+		super(GenCodeEchino.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeEchino();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelEuplotid.java b/Source/mesquite/molec/lib/GenCodeModelEuplotid.java
new file mode 100644
index 0000000..83c8860
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelEuplotid.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelEuplotid extends GenCodeModel{
+	public GenCodeModelEuplotid(){
+		super(GenCodeEuplotid.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeEuplotid();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelInvertMito.java b/Source/mesquite/molec/lib/GenCodeModelInvertMito.java
new file mode 100644
index 0000000..2548246
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelInvertMito.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelInvertMito extends GenCodeModel{
+	public GenCodeModelInvertMito(){
+		super(GenCodeInvertMito.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeInvertMito();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelMoldProtMito.java b/Source/mesquite/molec/lib/GenCodeModelMoldProtMito.java
new file mode 100644
index 0000000..b5e41b1
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelMoldProtMito.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelMoldProtMito extends GenCodeModel{
+	public GenCodeModelMoldProtMito(){
+		super(GenCodeMoldProtMito.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeMoldProtMito();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelSet.java b/Source/mesquite/molec/lib/GenCodeModelSet.java
new file mode 100644
index 0000000..88b0807
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelSet.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/*======================================================================== */
+/** a ModelSet for genetic codes. */
+public class GenCodeModelSet  extends ModelSet {
+	
+	public GenCodeModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Genetic Code Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		GenCodeModelSet ms = new GenCodeModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new GenCodeModelSet("Genetic Code Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet for character ic or new character added just after ic.  May take from current assignment*/
+	public CharacterModel getDefaultModel(int ic) {
+		return (CharacterModel)getDefaultProperty(ic);
+	}
+	 
+	
+	/*.................................................................................................................*/
+ 	/** Gets default model specified for ModelSet*/
+	public Object getDefaultProperty(int ic) {
+		if (getModel(ic) != null)
+			return getModel(ic);
+		int icLeft = ic;
+		while (--icLeft>=0 && getModel(icLeft) != null)  //looking left
+			return getModel(icLeft);
+		int icRight = ic;
+		while (++icRight< getNumChars() && getModel(icRight) != null)
+			return getModel(icRight);
+		return super.getDefaultModel(ic);
+	}
+
+}
+
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelSource.java b/Source/mesquite/molec/lib/GenCodeModelSource.java
new file mode 100644
index 0000000..37759a0
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelSource.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies character models for use in calculation routines.
+These methods must be passed a Data or a CharacterDistribution object because which models are appropriate will depend on these*/
+
+public abstract class GenCodeModelSource extends CharacterModelSource  {
+
+   	 public Class getDutyClass() {
+   	 	return GenCodeModelSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Genetic Code Model Source";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CurrentGenCodeModels"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelStandard.java b/Source/mesquite/molec/lib/GenCodeModelStandard.java
new file mode 100644
index 0000000..e577a1c
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelStandard.java
@@ -0,0 +1,31 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelStandard extends GenCodeModel{
+	public GenCodeModelStandard(){
+		super(GenCodeStandard.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeStandard();
+			}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelVertMito.java b/Source/mesquite/molec/lib/GenCodeModelVertMito.java
new file mode 100644
index 0000000..80ba592
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelVertMito.java
@@ -0,0 +1,31 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelVertMito extends GenCodeModel{
+	public GenCodeModelVertMito(){
+		super(GenCodeVertMito.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeVertMito();
+			}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeModelYeastMito.java b/Source/mesquite/molec/lib/GenCodeModelYeastMito.java
new file mode 100644
index 0000000..6bf61a4
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeModelYeastMito.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+
+
+import mesquite.categ.lib.*;
+
+
+
+public class GenCodeModelYeastMito extends GenCodeModel{
+	public GenCodeModelYeastMito(){
+		super(GenCodeYeastMito.getShortName(), MolecularState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+		geneticCode = new GenCodeYeastMito();
+	}
+}
+
diff --git a/Source/mesquite/molec/lib/GenCodeMoldProtMito.java b/Source/mesquite/molec/lib/GenCodeMoldProtMito.java
new file mode 100644
index 0000000..c772f37
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeMoldProtMito.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+
+public class GenCodeMoldProtMito extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(U,G,A, ProteinData.TRP);
+}
+
+	public String getName() {
+		return "The Mold, Protozoan, and Coelenterate Mitochondrial Code and the Mycoplasma/Spiroplasma Code";
+	}
+
+	public static String getShortName (){
+		return "Mold Mitochondrial";
+	}
+
+	public String getNEXUSName(){
+		return "mtdna.mold";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 4;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeStandard.java b/Source/mesquite/molec/lib/GenCodeStandard.java
new file mode 100644
index 0000000..65aa2f7
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeStandard.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+
+import mesquite.molec.lib.*;
+
+public class GenCodeStandard extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+	}
+
+	public String getName() {
+		return "The standard (\"universal\") genetic code";
+	}
+
+	public static String getShortName (){
+		return "Standard";
+	}
+
+	public String getNEXUSName(){
+		return "universal";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 1;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeVertMito.java b/Source/mesquite/molec/lib/GenCodeVertMito.java
new file mode 100644
index 0000000..b2995a4
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeVertMito.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeVertMito extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(A,G,A, ProteinData.TER);
+		setCode(A,G,G, ProteinData.TER);
+		setCode(A,U,A, ProteinData.MET);
+		setCode(U,G,A, ProteinData.TRP);
+	}
+
+	public String getName() {
+		return "The Vertebrate Mitochondrial Genetic Code";
+	}
+
+	public static String getShortName (){
+		return "Vertebrate Mitochondrial";
+	}
+
+	public String getNEXUSName(){
+		return "mtdna.mam";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 2;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GenCodeYeastMito.java b/Source/mesquite/molec/lib/GenCodeYeastMito.java
new file mode 100644
index 0000000..e96e91c
--- /dev/null
+++ b/Source/mesquite/molec/lib/GenCodeYeastMito.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib;
+
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+
+public class GenCodeYeastMito extends GeneticCode {
+
+	public void setCode() {
+		setStandardCode();
+		setCode(A,U,A, ProteinData.MET);
+		setCode(C,U,A, ProteinData.THR);
+		setCode(C,U,C, ProteinData.THR);
+		setCode(C,U,G, ProteinData.THR);
+		setCode(C,U,U, ProteinData.THR);
+		setCode(U,G,A, ProteinData.TRP);
+
+		setCode(C,G,A, ProteinData.ABSENT);
+		setCode(C,G,C, ProteinData.ABSENT);
+	}
+
+	public String getName() {
+		return "The Yeast Mitochondrial Genetic Code";
+	}
+
+	public static String getShortName (){
+		return "Yeast Mitochondrial";
+	}
+
+	public String getNEXUSName(){
+		return "mtdna.yeast";
+	}
+
+	public int getNCBITranslationTableNumber(){
+		return 3;
+	}
+
+}
diff --git a/Source/mesquite/molec/lib/GeneticCode.java b/Source/mesquite/molec/lib/GeneticCode.java
new file mode 100644
index 0000000..0246c58
--- /dev/null
+++ b/Source/mesquite/molec/lib/GeneticCode.java
@@ -0,0 +1,303 @@
+package mesquite.molec.lib;
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+import mesquite.lib.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+/**Provides a genetic code*/
+public abstract class GeneticCode implements Listable {
+	protected static int A=0;
+	protected static int C=1;
+	protected static int G=2;
+	protected static int T=3;
+	protected static int U=3;
+	public static final int CUSTOM_CODE=-1;
+	
+	protected int[][][] code = new int[4][4][4];
+	
+	public GeneticCode() {
+		setStandardCode();
+		setCode();
+	}
+	
+	/** This method sets the values in the translation table from triplets to amino acid.  
+	 * Use the setCode(int,int,int,int) method to set each element.  To initially set the 
+	 * translation table to match that of the standard code, use setStandardCode() */
+	public abstract void setCode();
+
+	/** Returns the NCBI translation table number for the code. Return -1 if not in GenBank.*/
+	public abstract int getNCBITranslationTableNumber();
+
+	public void setCode(int c1, int c2, int c3, int aminoAcid) {
+		code[c1][c2][c3] = aminoAcid;
+	}
+	/** Returns the int value of the amino acid that is specified by the codon c1-c2-c3 */
+	public int getCode(int c1, int c2, int c3) {
+		return code[c1][c2][c3];
+	}
+
+	/*.................................................................................................................*/
+  	/** Returns true if the GeneticCode objects are the same */
+ 		public boolean equals (GeneticCode otherGeneticCode) {
+ 			if (otherGeneticCode == null)
+ 				return false;
+ 	 		if (getNCBITranslationTableNumber() == CUSTOM_CODE ||  otherGeneticCode.getNCBITranslationTableNumber() == CUSTOM_CODE) {
+ 	 			for (int c1=0; c1<4; c1++) 
+ 	 				for (int c2=0; c2<4; c2++) 
+ 	 					for (int c3=0; c3<4; c3++)
+ 	 						if (getCode(c1,c2,c3) != otherGeneticCode.getCode(c1,c2,c3)) 
+ 	 							return false;
+	 			return true;
+ 	 		}
+ 	 		else
+ 	 			return (getNCBITranslationTableNumber() == otherGeneticCode.getNCBITranslationTableNumber());
+		}
+	/*.................................................................................................................*/
+  	/** Returns the maximum amino acid int value in the matrix */
+ 		public int getMaxAA () {
+ 	 		int value = 0;
+ 	 		for (int c1=0; c1<4; c1++) 
+ 	  			for (int c2=0; c2<4; c2++) 
+ 	  				for (int c3=0; c3<4; c3++)
+ 	  					value =MesquiteInteger.maximum(value, code[c1][c2][c3]);
+ 	 		return value;
+		}
+ 		/*.................................................................................................................*/
+ 		public int getDegeneracy (int aa) {
+ 			int count = 0;
+ 			for (int c1=0; c1<4; c1++) 
+ 				for (int c2=0; c2<4; c2++) 
+ 					for (int c3=0; c3<4; c3++) {
+ 						if (code[c1][c2][c3]==aa) {  //we've found the first aa
+ 							count++;
+ 						}
+ 					}
+ 			return count;
+ 		}
+	/*.................................................................................................................*/
+	public boolean[] getNearAAs (int aa) {
+		int numAAs = getMaxAA();
+		boolean[] nearAA = new boolean[numAAs];
+		for (int c1=0; c1<4; c1++) 
+			for (int c2=0; c2<4; c2++) 
+				for (int c3=0; c3<4; c3++) {
+					if (code[c1][c2][c3]==aa) {  //we've found the first aa
+						for (int mut=0; mut<4; mut++) {
+							if (mut!=c1 && code[mut][c2][c3] >=0 && code[mut][c2][c3]<numAAs) 
+								nearAA[code[mut][c2][c3]] = true;
+							if (mut!=c2 && code[c1][mut][c3] >=0 && code[c1][mut][c3]<numAAs) 
+								nearAA[code[c1][mut][c3]] = true;
+							if (mut!=c3 && code[c1][c2][mut] >=0 && code[c1][c2][mut]<numAAs) 
+								nearAA[code[c1][c2][mut]] = true;
+						}
+					}
+				}
+		return nearAA;
+		
+	}
+
+	/*.................................................................................................................*/
+	public boolean[] getTwoAwayAAs (int aa) {
+		boolean[] nearAA = getNearAAs(aa);
+
+ 		int numAAs = nearAA.length;
+		boolean[] twoAwayAA = getNearAAs(aa);
+
+		for (int j=0; j<numAAs; j++)
+			if (nearAA[j]){  // this is an aa that is 1 step away from aa1
+				boolean[] twoAway = getNearAAs(j);  //these are the aa's that are two steps away
+				for (int i=0; i<numAAs; i++)
+					if (twoAway[i])
+						twoAwayAA[i]=true;
+			}
+		return twoAwayAA;
+	}
+
+	/*.................................................................................................................*/
+  	/** Returns the  minimum number of replacement changes between two amino acids.
+	 * If the minimum number of replacement changes is >3, MesquiteInteger.unassigned is returned. */
+	  	public int getMinReplacementChanges(int aa1, int aa2){
+  		if (aa1==aa2)
+  			return 0;
+ 		boolean[] nearAA1 = getNearAAs(aa1);
+		boolean[] nearAA2 = getNearAAs(aa2);
+
+ 		int numAAs = nearAA1.length;
+		for (int aa=0; aa<numAAs; aa++)
+			if ((nearAA1[aa] && (aa==aa2)) || (nearAA2[aa] && (aa==aa1)))  // there is an amino acid that is just one step away from one of them
+				return 1;
+
+		for (int aa=0; aa<numAAs; aa++)
+			if (nearAA1[aa] && nearAA2[aa])  // there is an amino acid that is just one step away from each of them
+				return 2;
+
+		boolean[] twoAwayAA1 = getTwoAwayAAs(aa1);
+		boolean[] twoAwayAA2 = getTwoAwayAAs(aa2);
+
+		for (int aa=0; aa<numAAs; aa++)
+			if (nearAA1[aa] && twoAwayAA2[aa])  
+				return 3;
+
+		for (int aa=0; aa<numAAs; aa++)
+			if (nearAA2[aa] && twoAwayAA1[aa])  
+				return 3;
+		
+		return MesquiteInteger.unassigned;
+   	}
+
+	/*.................................................................................................................*/
+  	/** Returns a 2-D array containing the  minimum number of replacement changes between amino acids. 
+  	 * If the minimum number of replacement changes is >3, MesquiteInteger.unassigned is entered. */
+ 		public int[][] getMinReplacementMatrix () {
+ 			int numAAs = getMaxAA();
+ 			int[][] replacementMatrix = new int [numAAs][numAAs];
+ 			for (int i=0; i<numAAs; i++) {
+				for (int j=0; j<numAAs; j++)
+					replacementMatrix[i][j] = getMinReplacementChanges(i,j);
+			}
+ 			return replacementMatrix;
+ 		}
+
+		
+		
+  	public void setStandardCode() {
+			for (int j = 0; j<=3; j++) {			
+				setCode(C, C, j, ProteinData.PRO);
+				setCode(C, G, j, ProteinData.ARG);
+				setCode(G, C, j, ProteinData.ALA);
+				setCode(G, G, j, ProteinData.GLY);
+				setCode(G, T, j, ProteinData.VAL);
+				setCode(T, C, j, ProteinData.SER);
+				setCode(C, T, j, ProteinData.LEU);
+				setCode(A, C, j, ProteinData.THR);
+		}
+		setCode(A, A, T, ProteinData.ASN);
+		setCode(A, A, C, ProteinData.ASN);
+		setCode(A, A, A, ProteinData.LYS);
+		setCode(A, A, G, ProteinData.LYS);
+
+		setCode(C, A, T, ProteinData.HIS);
+		setCode(C, A, C, ProteinData.HIS);
+		setCode(C, A, G, ProteinData.GLN);
+		setCode(C, A, A, ProteinData.GLN);
+
+		setCode(G, A, T, ProteinData.ASP);
+		setCode(G, A, C, ProteinData.ASP);
+		setCode(G, A, A, ProteinData.GLU);
+		setCode(G, A, G, ProteinData.GLU);
+
+		setCode(T, T, T, ProteinData.PHE);
+		setCode(T, T, C, ProteinData.PHE);
+		setCode(T, T, A, ProteinData.LEU);
+		setCode(T, T, G, ProteinData.LEU);
+
+		setCode(T, G, T, ProteinData.CYS);
+		setCode(T, G, C, ProteinData.CYS);
+		setCode(T, G, G, ProteinData.TRP);
+		setCode(T, G, A, ProteinData.TER);
+
+
+		setCode(T, A, T, ProteinData.TYR);
+		setCode(T, A, C, ProteinData.TYR);
+		setCode(T, A, A, ProteinData.TER);
+		setCode(T, A, G, ProteinData.TER);
+
+// Davidv4.1: check this section as it is different from what I had: this warning is in 3.08 code
+		setCode(A, T, C, ProteinData.ILEU);
+		setCode(A, T, G, ProteinData.MET);
+		setCode(A, T, T, ProteinData.ILEU);
+		setCode(A, T, A, ProteinData.ILEU);
+
+		setCode(A, G, T, ProteinData.SER);
+		setCode(A, G, C, ProteinData.SER);
+		setCode(A, G, A, ProteinData.ARG);
+		setCode(A, G, G, ProteinData.ARG);
+		}
+	int reorderBase(int i){
+		switch (i) {
+			case 0: return 3;
+			case 1: return 1;
+			case 2: return 0;
+			case 3: return 2;
+			default: return i;
+		}
+	}
+	public String toNCBIString(){
+		StringBuffer sb = new StringBuffer();
+		sb.append("\n" + getName() + "\n");
+		sb.append("  AAs  = ");
+		for (int i = 0; i<=3; i++) {
+			for (int j = 0; j<=3; j++) {
+				for (int k = 0; k<=3; k++) {
+					int state = getCode(reorderBase(i),reorderBase(j),reorderBase(k));
+					sb.append(ProteinData.getAASymbol(state));
+				}
+			}
+		}
+		sb.append("\nBase1  = ");
+		for (int i = 0; i<=3; i++) {
+			for (int j = 0; j<=3; j++) {
+				for (int k = 0; k<=3; k++) {
+					int state = reorderBase(i);
+					sb.append(DNAData.getDefaultStateSymbol(state));
+				}
+			}
+		}
+		sb.append("\nBase2  = ");
+		for (int i = 0; i<=3; i++) {
+			for (int j = 0; j<=3; j++) {
+				for (int k = 0; k<=3; k++) {
+					int state = reorderBase(j);
+					sb.append(DNAData.getDefaultStateSymbol(state));
+				}
+			}
+		}
+		sb.append("\nBase3  = ");
+		for (int i = 0; i<=3; i++) {
+			for (int j = 0; j<=3; j++) {
+				for (int k = 0; k<=3; k++) {
+					int state = reorderBase(k);
+					sb.append(DNAData.getDefaultStateSymbol(state));
+				}
+			}
+		}
+		sb.append("\n");
+		return sb.toString();
+	}
+	
+	public String getNCBIURL(){
+		return "http://www.ncbi.nlm.nih.gov/Taxonomy/Utils/wprintgc.cgi#SG" + getNCBITranslationTableNumber();
+	}
+	public String getURLString(){
+		return getNCBIURL();
+	}
+	public void showNCBIPage(){
+		String s = getNCBIURL();
+		if (!StringUtil.blank(s))
+			MesquiteModule.showWebPage(s, false, false);
+	}
+	public abstract String getName() ;
+	public static String getShortName(){
+		return "Genetic Code";
+	}
+	public abstract String getNEXUSName();
+
+
+}
+
+
+
diff --git a/Source/mesquite/molec/lib/MaintainSequenceMatch.java b/Source/mesquite/molec/lib/MaintainSequenceMatch.java
new file mode 100644
index 0000000..60954e2
--- /dev/null
+++ b/Source/mesquite/molec/lib/MaintainSequenceMatch.java
@@ -0,0 +1,417 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.categ.lib.*;
+import mesquite.molec.lib.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+/* ======================================================================== *
+
+*new in 1. 06*
+
+/* ======================================================================== */
+public abstract class MaintainSequenceMatch extends FindSequenceCriterion {
+	String sequence = null;
+	int it = -1;
+	SeqCheckThread thread;
+	CharacterData data;
+	MesquiteTable table;
+	
+	Ledge panel;
+	protected SeqLedge ledge;
+	/*.................................................................................................................*/
+ 	public void endJob() {
+ 		if (thread != null)
+ 			thread.abort = true;
+ 		thread = null;
+ 		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			((MesquiteWindow)f).removeLedgePanel(panel);
+		}
+ 		super.endJob();
+   	 }
+   	 public void goAway(){
+   	 	iQuit();
+   	 }
+   	 
+   	 public void chooseTaxon(){
+   	 	if (data == null)
+   	 		return;
+		Taxa taxa = data.getTaxa();
+		Taxon taxon = taxa.userChooseTaxon(containerOfModule(), "Search within which taxon?");
+		int empit = taxa.whichTaxonNumber(taxon);
+		if (empit>=0)
+			it = empit;
+   	 }
+   	 
+	public boolean showOptions(CharacterData data, MesquiteTable table){
+		this.table = table;
+		if (data == null)
+			return false;
+		this.data = data;
+		sequence = null;
+		it = -1;
+		chooseTaxon();
+		MesquiteWindow f = containerOfModule();
+		if (f instanceof MesquiteWindow){
+			panel = new Ledge(this);
+			ledge = panel;
+			((MesquiteWindow)f).addLedgePanel(panel, 22);
+			panel.setVisible(true);
+		}
+		if (thread == null){
+			thread = new SeqCheckThread(this, panel);
+			thread.start();
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/*
+   	public boolean findNext(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+   		this.table = table;
+		findSeq(data, table, charFound, length, taxonFound);
+		return true;
+   	}
+   	*/
+   	public String checkSeq() {
+   		if (data != null && table != null)
+			findSeq(data, table, null, null, null);
+		return sequence;
+   	}
+   	
+   	public abstract String getSequence();
+   	
+   	boolean findSeq(CharacterData data, MesquiteTable table, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+ 		String temp = sequence;
+ 		sequence = getSequence();
+		if (sequence == null)
+			return false;
+		sequence = StringUtil.stripWhitespace(sequence);
+		if (temp != null && sequence != null && temp.equals(sequence))
+			return true;
+
+		return  (findFirst(data, table, sequence, charFound, length, taxonFound));
+   	}
+	int firstChar = 0;
+	boolean sequenceFound = false;
+   	boolean findFirst(CharacterData data, MesquiteTable table, String sequence, MesquiteInteger charFound, MesquiteInteger length, MesquiteInteger taxonFound) {
+			sequenceFound = false;
+  			if (it < 0)
+  				return false;
+  			if (sequence == null)
+  				return false;
+  			if (length != null)
+  				length.setValue(0);
+  			firstChar = 0;
+  			table.deselectAllCells(true, false);
+			StringBuffer sb = new StringBuffer(data.getNumChars());
+   			for (int ic = firstChar; ic< data.getNumChars(); ic++) {
+   				String cell = table.getMatrixText(ic, it);
+   				if (cell!= null && cell.length()>0)
+   					sb.append(cell.charAt(0));
+   			}
+   			t3.start();
+   			for (int ic = firstChar; ic< data.getNumChars(); ic++) {
+   				t4.start();
+   				int extra = sequencesMatch(data, sb,it, ic, sequence);
+				t4.end();
+				if (extra>=0) {
+					if (charFound != null)
+						charFound.setValue(ic);
+					if (taxonFound != null)
+						taxonFound.setValue(it);
+			   		for (int i = 0; i<extra + sequence.length(); i++) {
+			   			table.selectCell(ic + i, it);
+			   			table.redrawCell(ic + i, it);
+			   		}
+					table.setFocusedSequence(ic, ic + extra + sequence.length(), it);
+					
+					if (length != null)
+						length.setValue(extra + sequence.length());
+					t3.end();
+					sequenceFound = true;
+					return true;
+				}
+			}
+   			t3.end();
+   			return false;
+   		
+   	}
+   	MesquiteTimer t1 = new MesquiteTimer();
+   	MesquiteTimer t2 = new MesquiteTimer();
+   	MesquiteTimer t3 = new MesquiteTimer();
+   	MesquiteTimer t4 = new MesquiteTimer();
+   	
+	/*.................................................................................................................*/
+   	//-1 if not match, 0 or positive for number of extras if match
+   	int sequencesMatch(CharacterData data, StringBuffer matrixSequence, int it, int checkChar, String sequence) {
+   		int numChars = data.getNumChars();
+   		int numTaxa = data.getNumTaxa();
+   		int length = sequence.length();
+   		if (it< 0 || it >= numTaxa)
+   			return -1;
+   		if (checkChar + (length)>=numChars){ //would extend past end of sequence; but can't go to next taxon
+			return -1;
+   		}
+   		int mismatches = 0;
+   		int extra = 0;
+   		
+   		for (int site= 0; site < length; site++){
+   			String cell = null;
+   			t1.start();
+   			while (data.isInapplicable(site+checkChar+extra, it) && site+checkChar+extra<numChars)
+   				extra++;
+   			t1.end();
+   			if (length+checkChar+extra>=numChars){//would extend past end of sequence
+   				return -1;
+   			}
+   			//cell = table.getMatrixText(site+checkChar+extra, it);
+ 			
+ 			t2.start();
+   			if (site+checkChar+extra>= matrixSequence.length() || !siteMatch(matrixSequence.charAt(site+checkChar+extra), sequence, site)) {
+	 			t2.end();
+   				mismatches++;
+   				if (mismatches>0){
+	   				firstChar++;
+   					return -1;
+   				}
+   			}
+	 		else
+	 			t2.end();
+   		}
+	   	firstChar++;
+   		return extra;
+   		
+   	}
+	boolean siteMatch(char c, String sequence, int site){
+		char s = sequence.charAt(site);
+		if (c == s)
+			return true;
+		return matchchar(c, s) || matchchar(s,c);
+	}
+	boolean matchchar(char c, char s){
+		
+		if (s == 'a' && c == 'A')
+			return true;
+		if (s == 'c' && c == 'C')
+			return true;
+		if (s == 'g' && c == 'G')
+			return true;
+		if (s == 't' && c == 'T')
+			return true;
+		if (s == 'u' && c == 'U')
+			return true;
+		if (s == 'b' && c == 'B')
+			return true;
+		if (s == 'd' && c == 'D')
+			return true;
+		if (s == 'e' && c == 'E')
+			return true;
+		if (s == 'f' && c == 'F')
+			return true;
+		if (s == 'h' && c == 'H')
+			return true;
+		if (s == 'i' && c == 'I')
+			return true;
+		if (s == 'j' && c == 'J')
+			return true;
+		if (s == 'k' && c == 'K')
+			return true;
+		if (s == 'l' && c == 'L')
+			return true;
+		if (s == 'm' && c == 'M')
+			return true;
+		if (s == 'n' && c == 'N')
+			return true;
+		if (s == 'o' && c == 'O')
+			return true;
+		if (s == 'p' && c == 'P')
+			return true;
+		if (s == 'q' && c == 'Q')
+			return true;
+		if (s == 'r' && c == 'R')
+			return true;
+		if (s == 's' && c == 'C')
+			return true;
+		if (s == 'v' && c == 'V')
+			return true;
+		if (s == 'w' && c == 'W')
+			return true;
+		if (s == 'x' && c == 'X')
+			return true;
+		if (s == 'y' && c == 'Y')
+			return true;
+		if (s == 'z' && c == 'Z')
+			return true;
+		return false;
+	}
+	boolean playing = true;
+	public void togglePlay(){
+		playing = !playing;
+	}
+	public boolean isPlaying(){
+		return playing;
+	}
+	public String getTaxonName(){
+		if (data == null || it <0)
+			return null;
+		return data.getTaxa().getTaxonName(it);
+	}
+	public abstract String getMessage();
+	
+	protected int getTaxonNumber(){
+		return it;
+	}
+	protected boolean getSequenceFound(){
+		return sequenceFound;
+	}
+	public String getSearchSequence(){
+		if (sequence == null || it < 0)
+			return "";
+		else
+			return sequence;
+	}
+   	 
+}
+
+class SeqCheckThread  extends Thread {
+	MaintainSequenceMatch ownerModule;
+	boolean abort = false;
+	Ledge text;
+	public SeqCheckThread(MaintainSequenceMatch ownerModule, Ledge text){
+		this.ownerModule = ownerModule;
+		this.text = text;
+	}
+	public void run() {
+		while (!abort) { 
+			try {
+				Thread.sleep(200);
+				if (ownerModule.isPlaying()){
+					ownerModule.checkSeq();
+					if (text != null){
+						text.setMessage(ownerModule.getMessage());
+						text.setText(ownerModule.getSearchSequence());
+					}
+				}
+				else {
+					text.setMessage("Search is paused");
+				}
+			}
+			catch (InterruptedException e){
+			}
+		}
+	}
+}
+
+class Ledge extends MousePanel implements SeqLedge{
+	TextField text;
+	Label message;
+	int labelWidth = 200;
+	int messageLeng = 0;
+	MaintainSequenceMatch ownerModule;
+	Image goaway, play, pause, taxonButton;
+	int controlWidth = 52;
+	public Ledge(MaintainSequenceMatch ownerModule){
+		setLayout(null);
+		this.ownerModule = ownerModule;
+		text = new TextField(500);
+		add(text);
+		text.setBounds(labelWidth+controlWidth,0, 10,10);
+		text.setVisible(true);
+		text.setEditable(true);
+		text.setBackground(Color.white);
+		message = new Label("", Label.RIGHT);
+		message.setVisible(true);
+		add(message);
+		message.setBounds(controlWidth,1,labelWidth, 10);
+		message.setBackground(ColorDistribution.paleGoldenRod);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "goaway.gif");
+		play = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "play.gif");
+		pause = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "pause.gif");
+		taxonButton = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "taxon.gif");
+	}
+	public void setText(String s){
+		if (!StringUtil.stringsEqual(s, text.getText()))
+			text.setText(s);
+	}
+	public String getText(){
+		return text.getText();
+	}
+	public void setMessage(String s){
+		if (StringUtil.stringsEqual(s, message.getText()))
+			return;
+		messageLeng = 0;
+		if (s != null)
+			messageLeng = StringUtil.getStringDrawLength(message, s) + 10;
+		resetSizes(getBounds().width, getBounds().height);
+		message.setText(s);
+		
+	}
+	void resetSizes(int w, int h){
+		message.setBounds(controlWidth, 1, messageLeng, h-1);
+		text.setBounds(messageLeng+controlWidth,0, w-messageLeng-controlWidth, h);
+	}
+	public void setSize(int w, int h){
+		resetSizes(w, h);
+		super.setSize(w,h);
+	}
+	public void setBounds(int x, int y, int w, int h){
+		resetSizes(w, h);
+		super.setBounds(x, y, w,h);
+	}
+	public void paint(Graphics g){
+		g.setColor(ColorDistribution.paleGoldenRod); //paleGoldenRod);
+		g.fillRect(0,0, getBounds().width, getBounds().height);
+
+		g.setColor(Color.black);
+		g.drawRect(0,0, controlWidth-1, getBounds().height-1);
+	   	g.drawImage(goaway, 1,2, this);
+
+	   	if (ownerModule.isPlaying())
+	   		g.drawImage(pause, 17,2, this);
+	   	else
+	   		g.drawImage(play, 17,2, this);
+	   		
+	   	g.drawImage(taxonButton, 33,2, this);
+
+
+		
+	}
+	/* to be used by subclasses to tell that panel touched */
+   	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+   		if (x< 16)
+			ownerModule.goAway();
+   		else if (x< 32) {
+			ownerModule.togglePlay();
+			repaint();
+		}
+   		else if (x< 48)
+			ownerModule.chooseTaxon();
+		
+	}
+}
+
+
diff --git a/Source/mesquite/molec/lib/NCBIUtil.java b/Source/mesquite/molec/lib/NCBIUtil.java
new file mode 100644
index 0000000..3ee1806
--- /dev/null
+++ b/Source/mesquite/molec/lib/NCBIUtil.java
@@ -0,0 +1,1063 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.molec.lib; 
+
+
+import java.net.*;
+import java.util.Iterator;
+import java.util.List;
+import java.io.*;
+
+import org.dom4j.Element;
+
+import mesquite.lib.*;
+import mesquite.lib.Bits;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+import mesquite.io.InterpretFastaDNA.InterpretFastaDNA;   //is this guaranteed to be an installed package?
+import mesquite.io.InterpretFastaProtein.InterpretFastaProtein;   //is this guaranteed to be an installed package?
+import mesquite.io.lib.*;
+
+
+/* ======================================================================== */
+/** A set of static methods for NCBI*/
+public class NCBIUtil {
+	public final static NameReference EVALUE = new NameReference("BLASTeValue");
+	public final static NameReference BITSCORE = new NameReference("BLASTbitScore");
+	public final static NameReference DEFINITION = new NameReference("GenBankdefinition");
+	public final static NameReference ACCESSION = new NameReference("GenBankAccession");
+	public final static NameReference FRAME = new NameReference("GenBankFrame");
+	public final static NameReference TAXONOMY = new NameReference("GenBankTaxonomy");
+	/*.................................................................................................................*/
+	public static boolean responseSaysBLASTIsReady(String response) {
+		if (StringUtil.blank(response))
+			return false;
+		String  s = StringUtil.getAllAfterSubString(response, "QBlastInfoBegin");
+		if (!StringUtil.blank(s)) {
+			Parser parser = new Parser(s);
+			String token = parser.getNextToken();
+			while (!StringUtil.blank(token)) {
+				if ("Status".equalsIgnoreCase(token)) {
+					token = parser.getNextToken();  // =
+					token = parser.getNextToken();
+					return ("READY".equalsIgnoreCase(token));
+				}
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	protected static String getTaxID(String response){
+		Parser parser = new Parser();
+		//		String[] stringList=null;
+		parser.setString(response);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return null;
+		MesquiteString nextTag = new MesquiteString();
+		MesquiteString attributes = new MesquiteString();
+		String tagContent = parser.getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(nextTag.getValue())) {
+			if ("eSummaryResult".equalsIgnoreCase(nextTag.getValue())) {  //make sure it has the right root tag
+				parser.setString(tagContent);
+				tagContent = parser.getNextXMLTaggedContent(nextTag);
+				while (!StringUtil.blank(nextTag.getValue())) {
+					if ("DocSum".equalsIgnoreCase(nextTag.getValue())) {
+						parser.setString(tagContent);
+						tagContent = parser.getNextXMLTaggedContent(nextTag, attributes);
+						while (!StringUtil.blank(nextTag.getValue())) {
+							if ("Item".equalsIgnoreCase(nextTag.getValue()) && Parser.attributesContains(attributes.getValue(), "Name", "TaxID")) {
+								return tagContent;
+							}
+							tagContent = parser.getNextXMLTaggedContent(nextTag, attributes); 
+						}
+					}
+					tagContent = parser.getNextXMLTaggedContent(nextTag); 
+				}
+			} 
+			tagContent = parser.getNextXMLTaggedContent(nextTag);
+		}
+		return "";
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankTaxID(String id, boolean isNucleotides, boolean writeLog, StringBuffer report){ 
+		try {
+			URL queryURL = getFetchTaxIDAddress(id, isNucleotides);
+			URLConnection connection = queryURL.openConnection();
+			InputStream in = connection.getInputStream();
+
+			StringBuffer fetchBuffer = new StringBuffer();
+			int c;
+			int count = 0;
+			while ((c = in.read()) != -1) {
+				fetchBuffer.append((char) c);
+				count++;
+				if (count % 200==0 && writeLog)
+					MesquiteMessage.print(".");
+			}
+			in.close();
+			String taxID = getTaxID(fetchBuffer.toString());
+			return taxID;
+
+		} catch ( Exception e ){
+			// give warning
+			return "";
+		}
+	}
+	/*.................................................................................................................*/
+	protected static String getLineage(String response){
+		Parser parser = new Parser();
+		parser.setString(response);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return null;
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent = parser.getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(nextTag.getValue())) {
+			if ("TaxaSet".equalsIgnoreCase(nextTag.getValue())) {  //make sure it has the right root tag
+				parser.setString(tagContent);
+				tagContent = parser.getNextXMLTaggedContent(nextTag);
+				while (!StringUtil.blank(nextTag.getValue())) {
+					if ("Taxon".equalsIgnoreCase(nextTag.getValue())) {
+						parser.setString(tagContent);
+						tagContent = parser.getNextXMLTaggedContent(nextTag);
+						while (!StringUtil.blank(nextTag.getValue())) {
+							if ("Lineage".equalsIgnoreCase(nextTag.getValue())) {
+								return tagContent;
+							}
+							tagContent = parser.getNextXMLTaggedContent(nextTag); 
+						}
+					}
+					tagContent = parser.getNextXMLTaggedContent(nextTag); 
+				}
+			} 
+			tagContent = parser.getNextXMLTaggedContent(nextTag);
+		}
+		return "";
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankTaxonomy(String taxonomyID, boolean writeLog, StringBuffer report){ 
+		try {
+			URL queryURL = getFetchTaxonomyAddress(taxonomyID);
+			URLConnection connection = queryURL.openConnection();
+			InputStream in = connection.getInputStream();
+
+			StringBuffer fetchBuffer = new StringBuffer();
+			int c;
+			int count = 0;
+			while ((c = in.read()) != -1) {
+				fetchBuffer.append((char) c);
+				count++;
+				if (count % 200==0 && writeLog)
+					MesquiteMessage.print(".");
+			}
+			in.close();
+			return getLineage(fetchBuffer.toString());
+		} catch ( Exception e ){
+			// give warning
+			return "";
+		}
+	}
+	/*.................................................................................................................*/
+	public static String fetchTaxonomyFromAccession(String accession, boolean isNucleotides, boolean writeLog, StringBuffer report){ 
+		String id = getGenBankID(accession, isNucleotides,  null, false);
+		if (StringUtil.blank(id))
+			return "";
+		String taxID = fetchGenBankTaxID(id,isNucleotides, writeLog, report);
+		if (StringUtil.blank(taxID))
+			return "";
+		return fetchGenBankTaxonomy(taxID, writeLog, report);
+	}
+	/*.................................................................................................................*/
+	public static String fetchTaxonomyFromSequenceID(String id, boolean isNucleotides, boolean writeLog, StringBuffer report){ 
+		if (StringUtil.blank(id))
+			return "";
+		String taxID = fetchGenBankTaxID(id,isNucleotides, writeLog, report);
+		if (StringUtil.blank(taxID))
+			return "";
+		return fetchGenBankTaxonomy(taxID, writeLog, report);
+	}
+
+	/*.................................................................................................................*/
+	public static String getBlastPutQueryURL(String blastType, boolean isNucleotides, String sequenceName, StringBuffer sequence,  int maxHits,  double eValueCutoff, int wordSize, StringBuffer report){
+		if (sequence==null)
+			return null;
+
+		String seq = sequence.toString();
+		if (!StringUtil.blank(sequenceName))
+			seq = "%3E" + StringUtil.encodeForURL(sequenceName) + "%0D%0A"+seq;
+
+		if (!StringUtil.blank(seq) && (seq.length()>49)) {
+			String url = "http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?"+ getMesquiteGenBankURLMarker();
+			url += "&DATABASE=nr&FORMAT_TYPE=HTML";
+			url += "&PROGRAM=" + blastType;
+			url += "&CLIENT=web&SERVICE=plain&PAGE=";
+			if (isNucleotides)
+				url+="Nucleotides";
+			else
+				url+="Protein";
+			if (wordSize>0)
+				url += "&WORD_SIZE=" + wordSize;
+			if (eValueCutoff >= 0.0)
+				url += "&EXPECT=" + eValueCutoff;
+			url += "&HITLIST_SIZE="+ maxHits + "&CMD=Put&QUERY=";
+			return url+seq;
+		}
+		else {
+			if (report!=null)
+				report.append("Sorry, to use the BLAST search you need to have one or more regions of 50 or more nucleotides or amino acids selected.\n");
+			return null;
+		}
+	}
+	/*.................................................................................................................*
+	public static String getPutQueryURL(CharacterData data, int it, int icStart, int icEnd, int maxHits,  StringBuffer report){
+		if (data==null)
+			return null;
+		String sequenceName = data.getTaxa().getTaxonName(it);
+		StringBuffer sequence = new StringBuffer(data.getNumChars());
+		for (int ic = icStart; ic<=icEnd; ic++) {
+			data.statesIntoStringBuffer(ic, it, sequence, false, false, false);
+		}
+
+		if (data instanceof ProteinData) 
+			return getPutQueryURL("blastp", false, sequenceName, sequence, maxHits, report);
+		else
+			return getPutQueryURL("blastn", true, sequenceName,  sequence, maxHits, report);
+	}
+	/*.................................................................................................................*/
+	public static String getGetQueryURL(String rid, int numDesc, int maxHits, double eValueCutoff){
+		String url = "http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?"+NCBIUtil.getMesquiteGenBankURLMarker();
+		url += "&CMD=Get&RID="+rid+"&FORMAT_TYPE=XML";
+		if (eValueCutoff>-0.5)
+			url += "&EXPECT="+eValueCutoff;
+		url += "&DESCRIPTIONS="+numDesc + "&ALIGNMENTS="+ maxHits;
+		return url;
+	}
+	/*.................................................................................................................*/
+	public static boolean isNucleotides(CharacterData data){
+		return (data instanceof DNAData);
+	}
+	/*.................................................................................................................*/
+	public static String getMesquiteGenBankURLMarker(){
+		return "tool=mesquite" + MesquiteTrunk.mesquiteTrunk.getVersionInt() + "&email=info at mesquiteproject.org";
+	}
+	/*.................................................................................................................*/
+	public static URL getFetchTaxonomyAddress(String taxid)
+	throws MalformedURLException {
+		String query = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?"+getMesquiteGenBankURLMarker() +"&db=taxonomy&id="+taxid+"&retmode=xml";
+		return new URL(query);
+	}
+	/*.................................................................................................................*/
+	public static URL getFetchTaxIDAddress(String uid, boolean isNucleotides)
+	throws MalformedURLException {
+		String query = getMesquiteGenBankURLMarker() + "&db=" ;
+		if (isNucleotides)
+			query += "nucleotide";
+		else
+			query += "protein";
+		query += "&id="+uid+"&retmode=xml";
+
+		return new URL("http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?" + query);
+	}
+	/*.................................................................................................................*/
+	public static URL getFetchSequenceAddress(String uid, boolean isNucleotides)
+	throws MalformedURLException {
+		String query = getMesquiteGenBankURLMarker() + "&db=" ;
+		if (isNucleotides)
+			query += "nucleotide";
+		else
+			query += "protein";
+		query += "&id="+uid+"&rettype=fasta&retmax=1";
+
+		return new URL("http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?" + query);
+	}
+	/*.................................................................................................................*/
+	public static URL getESearchAddress(String accessionNumber, boolean nucleotides)
+	throws MalformedURLException {
+		String query = getMesquiteGenBankURLMarker() + "&db=" ;
+		if (nucleotides)
+			query += "nucleotide";
+		else
+			query += "protein";
+		query+= "&term="+accessionNumber;
+
+		return new URL("http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?" + query);
+	}
+	/*.................................................................................................................*/
+	public static URL getEUtilsAddressForIDToAccession(String ID, boolean nucleotides)
+	throws MalformedURLException {
+		String query = getMesquiteGenBankURLMarker() + "&db=" ;
+		if (nucleotides)
+			query += "nucleotide";
+		else
+			query += "protein";
+		query+= "&id="+ID;
+
+		//		http://eutils.ncbi.nlm.nih.gov/efetch.fcgi?db=nucleotide&id=91092690&retmode=xml
+		return new URL("http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?" + query + "&retmode=xml");
+	}
+	/*.................................................................................................................*/
+	public static URL getEUtilsAddressForProtToNuc(String id)
+	throws MalformedURLException {
+		String query = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/elink.fcgi?"+ getMesquiteGenBankURLMarker() + "&dbfrom=protein&db=nucleotide&id=\""+id +"\"";
+		return new URL(query);
+	}
+	/*.................................................................................................................*/
+	public static String[] requestGenBankIDs(String eSearchResponse){
+		Parser parser = new Parser();
+		String[] stringList=null;
+		parser.setString(eSearchResponse);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return null;
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent = parser.getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(nextTag.getValue())) {
+			if ("eSearchResult".equalsIgnoreCase(nextTag.getValue())) {  //make sure it has the right root tag
+				parser.setString(tagContent);
+				tagContent = parser.getNextXMLTaggedContent(nextTag);
+				while (!StringUtil.blank(tagContent)) {
+					if ("idList".equalsIgnoreCase(nextTag.getValue())) {
+						int count=0;
+						String idListContent=tagContent;
+						parser.setString(idListContent);
+						tagContent = parser.getNextXMLTaggedContent(nextTag);
+						while (!StringUtil.blank(tagContent)) {
+							if ("id".equalsIgnoreCase(nextTag.getValue())) {
+								count++;
+							}
+							tagContent = parser.getNextXMLTaggedContent(nextTag);
+						}
+						if (count>0)
+							stringList=new String[count];
+						if (stringList!=null) {
+							count=0;
+							parser.setString(idListContent);
+							tagContent = parser.getNextXMLTaggedContent(nextTag);
+							while (!StringUtil.blank(tagContent)) {
+								if ("id".equalsIgnoreCase(nextTag.getValue())) {
+									stringList[count]=tagContent;
+									count++;
+								}
+								tagContent = parser.getNextXMLTaggedContent(nextTag);
+							}
+						}
+					}
+					tagContent = parser.getNextXMLTaggedContent(nextTag); 
+				}
+				return stringList;
+			} 
+			tagContent = parser.getNextXMLTaggedContent(nextTag);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static String[] requestGenBankAccessions2(String eSearchResponse){
+		Parser parser = new Parser();
+		String[] stringList=null;
+		parser.setString(eSearchResponse);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return null;
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent = parser.getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(nextTag.getValue())) {
+			if ("eSearchResult".equalsIgnoreCase(nextTag.getValue())) {  //make sure it has the right root tag
+				parser.setString(tagContent);
+				tagContent = parser.getNextXMLTaggedContent(nextTag);
+				while (!StringUtil.blank(tagContent)) {
+					if ("idList".equalsIgnoreCase(nextTag.getValue())) {
+						int count=0;
+						String idListContent=tagContent;
+						parser.setString(idListContent);
+						tagContent = parser.getNextXMLTaggedContent(nextTag);
+						while (!StringUtil.blank(tagContent)) {
+							if ("accession".equalsIgnoreCase(nextTag.getValue())) {
+								count++;
+							}
+							tagContent = parser.getNextXMLTaggedContent(nextTag);
+						}
+						if (count>0)
+							stringList=new String[count];
+						if (stringList!=null) {
+							count=0;
+							parser.setString(idListContent);
+							tagContent = parser.getNextXMLTaggedContent(nextTag);
+							while (!StringUtil.blank(tagContent)) {
+								if ("id".equalsIgnoreCase(nextTag.getValue())) {
+									stringList[count]=tagContent;
+									count++;
+								}
+								tagContent = parser.getNextXMLTaggedContent(nextTag);
+							}
+						}
+					}
+					tagContent = parser.getNextXMLTaggedContent(nextTag); 
+				}
+				return stringList;
+			} 
+			tagContent = parser.getNextXMLTaggedContent(nextTag);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public static String[] requestGenBankAccessions(String eSearchResponse, int number){
+		if (eSearchResponse==null)
+			return null;
+		String[] accessions = new String[number];
+		Element gbSetElement = XMLUtil.getRootXMLElementFromString("GBSet",eSearchResponse);
+		if (gbSetElement==null)
+			return null;
+		int count=0;
+		String s = "";
+		List gbSeqList = gbSetElement.elements("GBSeq");
+		for (Iterator iter = gbSeqList.iterator(); iter.hasNext();) {   // this is going through all of the hits
+			Element gbSeqElement = (Element) iter.next();
+			if (gbSeqElement!=null) {
+				if (count<accessions.length){
+					accessions[count] = gbSeqElement.elementText("GBSeq_primary-accession");
+				}
+				else return accessions;
+				count++;
+			}
+
+		}
+		return accessions;
+	}
+
+
+	/*.................................................................................................................*/
+	public static String[] getGenBankIDs(String[] accessionNumbers, boolean nucleotides,  MesquiteModule mod, boolean writeLog){ 
+		try {
+			String searchString="";
+			for (int i=0; i<accessionNumbers.length;i++) {
+				searchString+=accessionNumbers[i];
+				if (i<accessionNumbers.length-1)
+					searchString+="+OR+";
+			}
+			if (writeLog && mod!=null)
+				mod.log(".");
+
+			StringBuffer sb = new StringBuffer();
+			URL queryURL = getESearchAddress(searchString, nucleotides);
+			if (writeLog && mod!=null)
+				mod.log(".");
+			URLConnection connection = queryURL.openConnection();
+			if (writeLog && mod!=null)
+				mod.log(".");
+			InputStream in = connection.getInputStream();
+
+			int c;
+			int count=0;
+			while ((c = in.read()) != -1) {
+				sb.append((char) c);
+				count++;
+				if (count % 100==0 && writeLog && mod!=null)
+					mod.log(".");
+			}
+			in.close();
+
+			String[] idList = requestGenBankIDs(sb.toString());
+
+			return idList;
+		} catch ( Exception e ){
+			// give warning
+			return null;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static String[] getGenBankAccessionFromID(String[] ID, boolean nucleotides,  MesquiteModule mod, boolean writeLog){ 
+		try {
+			String searchString="";
+			for (int i=0; i<ID.length;i++) {
+				searchString+=ID[i];
+				if (i<ID.length-1)
+					searchString+="+OR+";
+			}
+			if (writeLog && mod!=null)
+				mod.log(".");
+
+			StringBuffer sb = new StringBuffer();
+			URL queryURL = getEUtilsAddressForIDToAccession(searchString, nucleotides);
+			if (writeLog && mod!=null)
+				mod.log(".");
+			URLConnection connection = queryURL.openConnection();
+			if (writeLog && mod!=null)
+				mod.log(".");
+			InputStream in = connection.getInputStream();
+
+			int c;
+			int count=0;
+			while ((c = in.read()) != -1) {
+				sb.append((char) c);
+				count++;
+				if (count % 100==0 && writeLog && mod!=null)
+					mod.log(".");
+			}
+			in.close();
+
+			String[] idList = requestGenBankAccessions(sb.toString(), ID.length);
+
+			return idList;
+		} catch ( Exception e ){
+			// give warning
+			return null;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static String getGenBankGeneIDFromProteinID(String proteinID, MesquiteModule mod, boolean writeLog){ 
+		try {
+			String searchString="";
+			if (writeLog && mod!=null)
+				mod.log(".");
+
+			StringBuffer sb = new StringBuffer();
+			URL queryURL = getEUtilsAddressForProtToNuc(proteinID);
+			if (writeLog && mod!=null)
+				mod.log(".");
+			URLConnection connection = queryURL.openConnection();
+			if (writeLog && mod!=null)
+				mod.log(".");
+			InputStream in = connection.getInputStream();
+
+			int c;
+			int count=0;
+			while ((c = in.read()) != -1) {
+				sb.append((char) c);
+				count++;
+				if (count % 100==0 && writeLog && mod!=null)
+					mod.log(".");
+			}
+			in.close();
+
+			String geneID = getGenIDFromELinkResults(sb.toString());
+
+			return geneID;
+		} catch ( Exception e ){
+			// give warning
+			return null;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static String getGenBankID(String accessionNumber, boolean nucleotides,  MesquiteModule mod, boolean writeLog){ 
+		String[] accessionNumbers = new String[1];
+		accessionNumbers[0]=accessionNumber;
+		String[] idList = getGenBankIDs(accessionNumbers,nucleotides,mod, writeLog);
+		if (idList!=null && idList.length>0)
+			return idList[0];
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	public static void importFASTASequences(CharacterData data, String fastaSequences, MesquiteModule mod,StringBuffer report, int insertAfterTaxonRequested, int referenceTaxon, boolean adjustNewSequences, boolean addNewInternalGaps){
+		importFASTASequences(data, fastaSequences, mod, report, insertAfterTaxonRequested, referenceTaxon, adjustNewSequences, addNewInternalGaps, "");
+	}
+	/*.................................................................................................................*/
+	public static void importFASTASequences(CharacterData data, String fastaSequences, MesquiteModule mod,StringBuffer report, int insertAfterTaxonRequested, int referenceTaxon, boolean adjustNewSequences, boolean addNewInternalGaps, String appendToTaxonName){
+		if (data==null)
+			return;
+		
+		Taxa taxa = data.getTaxa();
+		int oldNumTaxa = taxa.getNumTaxa();
+		data.setCharNumChanging(true);
+		int insertAfterTaxon = taxa.getNumTaxa()-1;
+		if (insertAfterTaxonRequested>=0)
+			insertAfterTaxon = insertAfterTaxonRequested;
+		if (data instanceof ProteinData) {
+			InterpretFastaProtein importer = new InterpretFastaProtein();
+			importer.readString(data,fastaSequences, insertAfterTaxon,appendToTaxonName);
+		} else {
+			InterpretFastaDNA importer = new InterpretFastaDNA();
+			importer.readString(data,fastaSequences, insertAfterTaxon,appendToTaxonName);
+		}
+		data.setCharNumChanging(false);
+		taxa.notifyListeners(mod, new Notification(MesquiteListener.PARTS_ADDED));
+		data.notifyListeners(mod, new Notification(MesquiteListener.PARTS_ADDED));
+
+		Bits newTaxa = new Bits(taxa.getNumTaxa());
+		int taxaAdded = taxa.getNumTaxa()-oldNumTaxa;
+		int itStart = insertAfterTaxon+1;
+		int itEnd = itStart+taxaAdded-1;
+		for (int it=itStart; it<=itEnd; it++) {
+			newTaxa.setBit(it);
+		}
+		
+		
+		if (adjustNewSequences) {
+			MesquiteMessage.println("Adjusting sequences ");
+			if (!data.someApplicableInTaxon(insertAfterTaxon, false)){  
+				MesquiteMessage.println("The reference sequence contains no data; adjustment cancelled.");
+			    adjustNewSequences = false;
+			}
+			if (adjustNewSequences) {
+				
+				if (data instanceof DNAData){
+					MolecularDataUtil.reverseComplementSequencesIfNecessary((DNAData) data, mod, taxa, newTaxa, insertAfterTaxon, false, false);
+				}
+				
+				MolecularDataUtil.pairwiseAlignMatrix(mod, (MolecularData)data, referenceTaxon, newTaxa,0, addNewInternalGaps, true);
+				data.notifyListeners(mod, new Notification(CharacterData.DATA_CHANGED, null, null));
+			}
+		}
+
+
+		
+		String s;
+		if (report!=null){
+			report.append("Acquired: \n");
+			for (int it = itStart; it<= itEnd; it++){
+				s = taxa.getTaxon(it).getName();
+				report.append("  " + s + "\n");
+				report.append("  Length: " + data.getTotalNumApplicable(it,false)+ "\n");
+
+			}
+			report.append("\n");
+		}
+	}
+	/*.................................................................................................................*/
+	public static String createFastaString(CharacterData data, int icStart, int icEnd, int it){
+		if (data==null)
+			return null;
+		Taxa taxa = data.getTaxa();
+		StringBuffer sb = new StringBuffer();
+		sb.append(">"+ taxa.getTaxonName(it) + StringUtil.lineEnding());
+		int counter=0;
+		for (int ic=icStart; ic<=icEnd; ic++) {
+			if (data.isUnassigned(ic, it)){
+				if (data instanceof ProteinData)
+					sb.append("X");
+				else
+					sb.append("N");
+			}
+			else  {
+				data.statesIntoStringBuffer(ic, it, sb, false);
+				counter ++;
+				if ((counter % 50 == 1) && (counter > 1)) {    // modulo
+					sb.append(StringUtil.lineEnding());
+				}
+			}
+		}
+		sb.append(StringUtil.lineEnding());
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public static String createFastaString(String sequenceName, String sequence, boolean isNucleotides){
+		StringBuffer sb = new StringBuffer();
+		sb.append(">"+ sequenceName + StringUtil.lineEnding());
+		sb.append(sequence + StringUtil.lineEnding());
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequence(String id, boolean isNucleotides,  MesquiteModule mod, boolean writeLog, StringBuffer report){ 
+		try {
+			URL queryURL = getFetchSequenceAddress(id, isNucleotides);
+			URLConnection connection = queryURL.openConnection();
+			InputStream in = connection.getInputStream();
+
+			StringBuffer fetchBuffer = new StringBuffer();
+			int c;
+			int count = 0;
+			while ((c = in.read()) != -1) {
+				fetchBuffer.append((char) c);
+				count++;
+				if (count % 200==0 && writeLog && mod!=null)
+					mod.log(".");
+			}
+			in.close();
+			return fetchBuffer.toString();
+		} catch ( Exception e ){
+			// give warning
+			return null;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequenceAsFASTA(String id,  boolean isNucleotides, MesquiteModule mod, boolean writeLog, StringBuffer results, StringBuffer report){ 
+		if (results==null)
+			return null;
+		try {
+			URL queryURL = getFetchSequenceAddress(id, isNucleotides);
+			URLConnection connection = queryURL.openConnection();
+			InputStream in = connection.getInputStream();
+
+			StringBuffer fetchBuffer = new StringBuffer();
+			int c;
+			int count = 0;
+			while ((c = in.read()) != -1) {
+				fetchBuffer.append((char) c);
+				count++;
+				if (count % 200==0 && writeLog && mod!=null)
+					mod.log(".");
+			}
+			in.close();
+			results.append(fetchBuffer);
+			return fetchBuffer.toString();
+		} catch ( Exception e ){
+			// give warning
+			return null;
+		}
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequences(String[] idList, boolean isNucleotides,  MesquiteModule mod, boolean writeLog, StringBuffer report){ 
+		StringBuffer sequences = new StringBuffer();
+		for (int i=0; i<idList.length; i++) {
+			if (!StringUtil.blank(idList[i])) {
+
+				if (writeLog && mod!=null){
+					mod.log("Fetching " + idList[i]);
+					mod.log(".");
+				}
+				String seq = fetchGenBankSequence(idList[i], isNucleotides,  mod, writeLog, report);
+				if (StringUtil.notEmpty(seq))
+					sequences.append(seq);
+				else if (i==0)
+					return null;
+				mod.logln("");
+			}
+		}
+		return sequences.toString();
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequences(String[] idList, boolean isNucleotides,  MesquiteModule mod, boolean writeLog, StringBuffer results, StringBuffer report){ 
+		if (results==null)
+			return null;
+		StringBuffer sequences = new StringBuffer();
+		for (int i=0; i<idList.length; i++) {
+			if (!StringUtil.blank(idList[i])) {
+
+				if (writeLog && mod!=null){
+					mod.log("Fetching " + idList[i]);
+					mod.log(".");
+				}
+				String seq = fetchGenBankSequenceAsFASTA(idList[i], isNucleotides,  mod, writeLog, results, report);
+				if (StringUtil.notEmpty(seq)){
+					sequences.append(seq);
+				}
+				else if (i==0)
+					return null;
+				//	mod.logln("");
+			}
+		}
+		return sequences.toString();
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequencesFromIDs(String[] idList,  boolean isNucleotides, MesquiteModule mod, boolean writeLog, StringBuffer report){ 
+		String sequences = fetchGenBankSequences(idList,isNucleotides, mod, writeLog, report);
+		if (mod!=null && writeLog)
+			mod.logln("");
+		return sequences;
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequencesFromIDs(String[] idList,  boolean isNucleotides, MesquiteModule mod, boolean writeLog, StringBuffer results, StringBuffer report){ 
+		if (results==null || idList==null)
+			return null;
+		String sequences = fetchGenBankSequences(idList,isNucleotides, mod, writeLog, results, report);
+		if (mod!=null && writeLog)
+			mod.logln("");
+		return sequences;
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequencesFromAccessions(String[] accessionNumbers,  boolean isNucleotides, MesquiteModule mod, boolean writeLog, StringBuffer report){ 
+		String[] idList = getGenBankIDs(accessionNumbers, isNucleotides,  mod, writeLog);
+		if (idList==null)
+			return null;
+		String sequences = fetchGenBankSequences(idList,isNucleotides, mod, writeLog, report);
+		if (mod!=null && writeLog)
+			mod.logln("");
+		return sequences;
+
+	}
+	/*.................................................................................................................*/
+	public static String fetchGenBankSequencesFromAccessions(String[] accessionNumbers,  boolean isNucleotides, MesquiteModule mod, boolean writeLog, StringBuffer results, StringBuffer report){ 
+		if (results==null)
+			return null;
+		String[] idList = getGenBankIDs(accessionNumbers,  isNucleotides,  mod, writeLog);
+		if (idList==null)
+			return null;
+		String sequences = fetchGenBankSequences(idList,isNucleotides, mod, writeLog, results, report);
+		if (mod!=null && writeLog)
+			mod.logln("");
+		return sequences;
+
+	}
+	/*.................................................................................................................*/
+	public static String getRID(String response, MesquiteInteger responseTime) {
+		String  s = StringUtil.getAllAfterSubString(response, "!--QBlastInfoBegin");
+		responseTime.setValue(0);
+		if (!StringUtil.blank(s)) {
+			int valuesAcquired = 0;
+			String rid = null;
+			Parser parser = new Parser(s);
+			parser.setPunctuationString("=");
+			String token = parser.getNextToken();
+			while (!StringUtil.blank(token)) {
+				if ("RID".equalsIgnoreCase(token)) {
+					token = parser.getNextToken(); // = sign
+					rid = parser.getNextToken(); // RID
+					valuesAcquired++;
+				}
+				else if ("RTOE".equalsIgnoreCase(token)) {
+					token = parser.getNextToken(); // = sign
+					token = parser.getNextToken(); //response time
+
+					responseTime.setValue(token);
+					valuesAcquired++;
+				}
+				if (valuesAcquired>=2)
+					return rid;
+				token = parser.getNextToken();
+			}
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public static void blastForMatches(String blastType, String sequenceName, String sequence, boolean isNucleotides, int numHits, int maxTime, double eValueCutoff, int wordSize, StringBuffer blastResponse){
+		StringBuffer report = new StringBuffer();
+		String searchString = NCBIUtil.getBlastPutQueryURL(blastType, isNucleotides, sequenceName, new StringBuffer(sequence),numHits, eValueCutoff, wordSize, report);
+
+		if (!StringUtil.blank(searchString)) {
+			try {
+				URL queryURL = new URL(searchString);
+				URLConnection connection = queryURL.openConnection();
+				InputStream in = connection.getInputStream();
+
+				//logln("Processing initial response", true);
+				StringBuffer sb = new StringBuffer();
+				int c;
+				while ((c = in.read()) != -1) {
+					sb.append((char) c);
+				}
+				in.close();
+
+				MesquiteInteger responseTime = new MesquiteInteger();
+				String rid = getRID(sb.toString(), responseTime);
+				//		logln("   Expected time of completion of BLAST is " + responseTime.toString()+ " seconds.", true);
+
+				int checkInterval = responseTime.getValue();
+				if (checkInterval<10) checkInterval = 10;
+				//pauseForSeconds(responseTime.getValue()-checkInterval);
+				int count=0;
+				String response="";
+
+				String recoverURLString = NCBIUtil.getGetQueryURL(rid,1, 1, eValueCutoff);
+				MesquiteTimer timer = new MesquiteTimer();
+				timer.start(); 
+				int totalTime = 0;
+				if (!StringUtil.blank(recoverURLString)) {
+					while (!NCBIUtil.responseSaysBLASTIsReady(response) && totalTime<maxTime) {
+						int seconds = (int)(timer.timeSinceVeryStart()/1000);
+						//					if (count>0) logln(" Not done.  (" + seconds + " seconds.)");
+						int waitSeconds;
+						if (count==0) waitSeconds = checkInterval+2;
+						else if (count==1) waitSeconds = 3;
+						else waitSeconds = checkInterval;
+						for (int i = 0; i<waitSeconds*10; i++) {
+							Thread.sleep(100);
+							if (i%10==0) {
+								int sec = seconds+ i/10;
+								CommandRecord.tick("Waiting for BLAST. ("+sec + ")");
+							}
+						}
+						//					log("   Querying to see if BLAST has completed.  ", true);
+						queryURL = new URL(recoverURLString);
+						connection = queryURL.openConnection();
+						in = connection.getInputStream();
+
+						StringBuffer responseBuffer = new StringBuffer();
+						while ((c = in.read()) != -1) {
+							responseBuffer.append((char) c);
+						}
+						in.close();
+						response = responseBuffer.toString();
+						count++;
+						totalTime +=checkInterval;
+					}
+					CommandRecord.tick("");
+					//	if (NCBIUtil.responseSaysBLASTIsReady(response)) MesquiteMessage.println(" Done."); else MesquiteMessage.println(" Not completed in time.");
+					//					results.append("\n" + taxonName + "\t");
+					if (blastResponse!=null){
+						blastResponse.setLength(0);
+						blastResponse.append(response);
+					}
+				}
+				timer.end();
+			}
+			catch (Exception e) {
+				MesquiteMessage.println("Connection error");
+			}
+		}
+
+	}
+
+	/*.................................................................................................................*
+	public static void nearestMatch2(String blastType, String sequenceName, String sequence, boolean isNucleotides, int maxTime, StringBuffer matchReport){
+
+		NCBIUtil.nearestMatches("blastn", sequenceName, sequence.toString(), true, 300, matchReport);
+	}
+
+	/*.................................................................................................................*
+	public static void processResultsFromBLAST(String response, int maxHits, boolean fetchTaxonomy, boolean isNucleotides, StringArray topHitAccessions, BLASTResults blastResults){
+
+		Parser parser = new Parser();
+		parser.setString(response);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return;
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent;
+		String accession="";
+		double bitScore = 0.0;
+		double eValue = -1.0;
+		if (parser.resetToXMLTagContents("BLASTOUTPUT"))
+			if (parser.resetToXMLTagContents("BLASTOUTPUT_iterations")) 
+				if (parser.resetToXMLTagContents("Iteration") && parser.resetToXMLTagContents("Iteration_hits")){
+					tagContent = parser.getNextXMLTaggedContent(nextTag);
+					int hitCount = 0;
+					while (!StringUtil.blank(nextTag.getValue()) && hitCount<maxHits) {
+						if ("Hit".equalsIgnoreCase(nextTag.getValue())) {   // here is a hit
+							String tax=null;
+							StringBuffer tempBuffer = new StringBuffer();
+							Parser hitParser = new Parser(tagContent);
+							tagContent = hitParser.getNextXMLTaggedContent(nextTag);
+							String def = "";
+							while (!StringUtil.blank(nextTag.getValue())) {
+								if ("Hit_def".equalsIgnoreCase(nextTag.getValue())) {  
+									def=StringUtil.stripTrailingWhitespace(tagContent);
+								}
+								else if ("Hit_accession".equalsIgnoreCase(nextTag.getValue())) {  
+									tempBuffer.append(StringUtil.stripTrailingWhitespace(tagContent)+"\t");
+									accession=tagContent;
+									if (fetchTaxonomy) {
+										tax = NCBIUtil.fetchTaxonomyList(accession, isNucleotides, true, null);
+									}
+								}
+								else if ("Hit_hsps".equalsIgnoreCase(nextTag.getValue())) {  
+									Parser subParser = new Parser(tagContent);
+									tagContent = subParser.getNextXMLTaggedContent(nextTag);
+									while (!StringUtil.blank(nextTag.getValue())) {
+										if ("Hsp".equalsIgnoreCase(nextTag.getValue())) {
+											subParser.setString(tagContent);
+											tagContent = subParser.getNextXMLTaggedContent(nextTag);
+											while (!StringUtil.blank(nextTag.getValue())) {
+												if ("Hsp_bit-score".equalsIgnoreCase(nextTag.getValue())) {
+													tempBuffer.append(StringUtil.stripTrailingWhitespace(tagContent)+"\t");
+													bitScore = MesquiteDouble.fromString(tagContent);
+												}
+												else if ("Hsp_evalue".equalsIgnoreCase(nextTag.getValue())) {
+													tempBuffer.append(StringUtil.stripTrailingWhitespace(tagContent)+"\t");
+													eValue = MesquiteDouble.fromString(tagContent);
+												}
+												tagContent = subParser.getNextXMLTaggedContent(nextTag); 
+											}
+										}
+										tagContent = subParser.getNextXMLTaggedContent(nextTag); 
+									}
+								} 
+								tagContent = hitParser.getNextXMLTaggedContent(nextTag);
+							}
+							if (blastResults!=null) {
+								blastResults.setAccession(accession,hitCount);
+								blastResults.setBitScore(bitScore,hitCount);
+								blastResults.setDefinition(def,hitCount);
+								blastResults.seteValue(eValue,hitCount);
+								blastResults.setTaxonomy(tax,hitCount);
+							}
+							if (topHitAccessions!=null)
+								topHitAccessions.addAndFillNextUnassigned(accession);
+
+							hitCount++;
+						}
+						tagContent = parser.getNextXMLTaggedContent(nextTag);
+
+					}
+				}
+
+
+
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public static String[] cleanUpID(String[] ID){ 
+		String s = "";
+		for (int i =0; i<ID.length; i++){
+			if (ID[i].indexOf("gi|")>=0) {
+				s = StringUtil.getPiece(ID[i], "gi|", "|");
+				if (StringUtil.notEmpty(s))
+					ID[i] = s;
+			}
+		}
+		return ID;
+	}
+	/*.................................................................................................................*/
+	public static String cleanUpID(String ID){ 
+		if (StringUtil.blank(ID))
+			return ID;
+		String s = "";
+		if (ID.indexOf("gi|")>=0) {
+			s = StringUtil.getPiece(ID, "gi|", "|");
+			if (StringUtil.notEmpty(s))
+				ID = s;
+		}
+
+		return ID;
+	}
+	/*.................................................................................................................*/
+	public static String[] getNucIDsFromProtIDs(String[] ID){ 
+		String[] protID= new String[ID.length];
+		for (int i =0; i<protID.length; i++){
+			protID[i]=ID[i];
+			ID[i] = getGenBankGeneIDFromProteinID(protID[i], null, false);
+		}
+		return ID;
+	}
+
+	/*.................................................................................................................*/
+	public static String getGenIDFromELinkResults(String response){
+		if (response==null)
+			return null;
+		Element eLinkResultElement = XMLUtil.getRootXMLElementFromString("eLinkResult",response);
+		if (eLinkResultElement==null)
+			return null;
+		String s = "";
+		Element LinkSetElement = eLinkResultElement.element("LinkSet");
+		if (LinkSetElement!=null) {
+			//	Element LinkSetDBElement = LinkSetElement.element("LinkSetDb");
+			List hitList = LinkSetElement.elements("LinkSetDb");
+			for (Iterator iter = hitList.iterator(); iter.hasNext();) {   // this is going through all of the hits
+				Element hitElement = (Element) iter.next();
+				if (hitElement!=null) {
+					String linkName = hitElement.elementText("LinkName");
+					if ("protein_nuccore_mrna".equalsIgnoreCase(linkName)){
+						Element LinkElement = hitElement.element("Link");
+						if (LinkElement!=null) {
+							s = LinkElement.elementText("Id");
+							return s;
+						}
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+}
+
+
+
+
+
diff --git a/Source/mesquite/molec/lib/SeqLedge.java b/Source/mesquite/molec/lib/SeqLedge.java
new file mode 100644
index 0000000..12332e8
--- /dev/null
+++ b/Source/mesquite/molec/lib/SeqLedge.java
@@ -0,0 +1,30 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.molec.lib; 
+
+import java.util.*;
+import java.awt.*;
+
+
+/* ======================================================================== */
+public interface SeqLedge {
+   	 public void setText(String s);
+   	 public void setMessage(String s);
+   	 public String getText();
+}
+
+
+	
+
+
diff --git a/Source/mesquite/ornamental/BranchNotes/32asteriskTool.gif b/Source/mesquite/ornamental/BranchNotes/32asteriskTool.gif
new file mode 100644
index 0000000..b9afe09
Binary files /dev/null and b/Source/mesquite/ornamental/BranchNotes/32asteriskTool.gif differ
diff --git a/Source/mesquite/ornamental/BranchNotes/64asteriskTool.gif b/Source/mesquite/ornamental/BranchNotes/64asteriskTool.gif
new file mode 100644
index 0000000..a7a88d1
Binary files /dev/null and b/Source/mesquite/ornamental/BranchNotes/64asteriskTool.gif differ
diff --git a/Source/mesquite/ornamental/BranchNotes/BranchNotes.java b/Source/mesquite/ornamental/BranchNotes/BranchNotes.java
new file mode 100644
index 0000000..82877ae
--- /dev/null
+++ b/Source/mesquite/ornamental/BranchNotes/BranchNotes.java
@@ -0,0 +1,273 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.BranchNotes;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class BranchNotes extends TreeDisplayAssistantI {
+	public Vector extras;
+	public boolean first = true;
+	public Image asterisk;
+	MesquiteBoolean alwaysOn;
+	
+	public String getFunctionIconPath(){
+		return getPath() + "asteriskTool.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		asterisk = MesquiteImage.getImage(getPath() + "asterisk.gif", false);   //TODO:  add asterisk.gif!
+		alwaysOn = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Show Notes On Tree", makeCommand("setAlwaysOn",  this), alwaysOn);
+		setUseMenubar(false); //menu available by touching button
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		BranchNotesToolExtra newPj = new BranchNotesToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Annotate Branches";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setAlwaysOn " + alwaysOn.toOffOnString());
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets whether to show the node notes always, or only when the cursor passes over", "[on or off]", commandName, "setAlwaysOn")) {
+			if (StringUtil.blank(arguments))
+				alwaysOn.setValue(!alwaysOn.getValue());
+			else
+				alwaysOn.toggleValue(parser.getFirstToken(arguments));
+			for (int i =0; i<extras.size(); i++){
+				BranchNotesToolExtra e = (BranchNotesToolExtra)extras.elementAt(i);
+				e.setShowAlways(alwaysOn.getValue());
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies a tool for tree windows to attach and view footnotes for branches." ;
+   	 }
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+}
+
+/* ======================================================================== */
+class BranchNotesToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool branchNotesTool;
+	BranchNotes branchNotesModule;
+	MesquiteLabel message;
+	MesquiteCommand taxonCommand, branchCommand;
+	boolean showAlways;
+//	StringInABox
+	public BranchNotesToolExtra (BranchNotes ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		branchNotesModule = ownerModule;
+		showAlways = branchNotesModule.alwaysOn.getValue();
+		branchNotesTool = new TreeTool(this, "BranchNotes", ownerModule.getPath(), "asteriskTool.gif", 1,1,"Annotate Branch", "This tool allows you to edit footnotes attached to branches of the tree.."); //; hold down shift to enter a URL
+		taxonCommand = MesquiteModule.makeCommand("editTaxonNote",  this);
+		branchCommand = MesquiteModule.makeCommand("editBranchNote",  this);
+		branchNotesTool.setTouchedTaxonCommand(taxonCommand);
+		branchNotesTool.setTouchedCommand(branchCommand);
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(branchNotesTool);
+			branchNotesTool.setPopUpOwner(ownerModule);
+		}
+		message = new MesquiteLabel(null, 0);
+		message.setSize(4,4);
+		message.setColor(Color.yellow);
+		message.setVisible(false);
+		treeDisplay.addPanelPlease(message);
+	}
+	StringInABox box = new StringInABox( "", treeDisplay.getFont(),150);
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int node, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawOnTree(tree, d, g);
+		if (getNote(tree, node)!=null) {
+			if (showAlways){
+				String note = getNote(tree, node);
+				box.setColors(Color.red, Color.white);
+				box.setString("* " +note);
+				box.draw(g,  treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node]);
+			}
+			else if (branchNotesModule.asterisk == null)
+				StringUtil.highlightString(g, "*", treeDisplay.getTreeDrawing().x[node]-8, treeDisplay.getTreeDrawing().y[node]+8, Color.red, Color.white);
+			else
+				g.drawImage(branchNotesModule.asterisk, treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node], (ImageObserver)treeDisplay);
+		}
+	}
+	
+	void setShowAlways(boolean a){
+		showAlways = a;
+	   	treeDisplay.pleaseUpdate(false);
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (getNote(tree, node)!=null)
+			return "*(" + node + ")";
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	public void getNotes(Tree tree, int node, StringBuffer sb) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			getNotes(tree, d, sb);
+		String note = getNote(tree, node);
+		if (note!=null) {
+			sb.append("*(" + node + "): " + note + "\n");
+		}
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		StringBuffer sb = new StringBuffer(100);
+		getNotes(treeDisplay.getTree(), treeDisplay.getTree().getRoot(), sb);
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		//drawOnTree(tree, drawnRoot, g); //should draw numbered footnotes!
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	NameReference branchNotesRef = NameReference.getNameReference("note");
+	String getNote(Tree tree, int node){
+		return (String)tree.getAssociatedObject(branchNotesRef, node);
+	}
+	void setNote(Tree tree, int node, String note){
+		if (tree instanceof Associable){
+			((Associable)tree).setAssociatedObject(branchNotesRef, node, note);
+			((Associable)tree).notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+
+		}
+	}
+	boolean shown = false;
+	/**to inform TreeDisplayExtra that cursor has just entered name of terminal taxon M*/
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g){
+		if (branchNotesTool.getInUse()){
+			String link = (String)tree.getTaxa().getAnnotation(M);
+			if (link!=null) {
+				int tM = tree.nodeOfTaxonNumber(M);
+				shown = true;
+				message.setLocation(treeDisplay.getTreeDrawing().x[tM], treeDisplay.getTreeDrawing().y[tM]);
+				message.setText(link);
+				message.setVisible(true);
+				message.setCommand(taxonCommand);
+				message.setArguments(Integer.toString(tM));
+			}
+		}
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited name of terminal taxon M*/
+	public void cursorExitTaxon(Tree tree, int M, Graphics g){
+		if (shown) {
+			message.setVisible(false);
+			//message.setSize(4,4);
+		}
+		shown = false;
+	}
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){
+		if (branchNotesTool.getInUse()){
+			String link = getNote(tree, N);
+			if (link!=null) {
+				shown = true;
+				message.setLocation(treeDisplay.getTreeDrawing().x[N], treeDisplay.getTreeDrawing().y[N]);
+				message.setText(link);
+				message.setVisible(true);
+				message.setCommand(branchCommand);
+				message.setArguments(Integer.toString(N));
+			}
+		}
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited branch N*/
+	public void cursorExitBranch(Tree tree, int N, Graphics g){
+		if (shown) {
+			message.setVisible(false);
+			//message.setSize(4,4);
+		}
+		shown = false;
+	}
+	
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+    	 	if (checker.compare(this.getClass(), "Edits the annotation for the taxon", "[taxon number]", commandName, "editTaxonNote")) {
+    	 		Tree tree = treeDisplay.getTree();
+   	 		int M = MesquiteInteger.fromFirstToken(arguments, pos);
+   	 		if (M<0 || !MesquiteInteger.isCombinable(M) || M>=tree.getTaxa().getNumTaxa())
+   	 			return null;
+			Taxa taxa = tree.getTaxa();
+			
+   	 		String chosen = MesquiteString.queryMultiLineString(ownerModule.containerOfModule(), "Annotation for taxon", "Annotation for taxon " + taxa.getTaxonName(M), taxa.getAnnotation(M), 8, false, true);
+   	 		if (chosen==null)
+   	 			return null;
+			taxa.setAnnotation(M, chosen);
+   	 		ownerModule.outputInvalid();
+   	 		return null;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Edits the annotation for the branch", "[node number]", commandName, "editBranchNote")) {
+    	 		Tree tree = treeDisplay.getTree();
+    	 		if (!(tree instanceof Associable)){
+    	 			ownerModule.alert("Sorry, this is not a standard Mesquite tree, and you can't edit its branch notes");
+    	 			return null;
+    	 		}
+    	 		int edit = 0;
+   	 		int M = MesquiteInteger.fromFirstToken(arguments, pos);
+   	 		if (M<0 || !MesquiteInteger.isCombinable(M))
+   	 			return null;
+						
+   	 		String chosen = MesquiteString.queryMultiLineString(ownerModule.containerOfModule(), "Annotation for branch", "Annotation for branch", getNote(tree, M), 8, false, true);
+   	 		if (chosen==null)
+   	 			return null;
+   	 		setNote(tree, M, chosen);
+   	 		ownerModule.outputInvalid();
+   	 		return null;
+    	 	}
+    	 	/**
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	/**/
+
+ 		return null;
+ 	}
+	public void turnOff() {
+		branchNotesModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/BranchNotes/asteriskBIGTool.gif b/Source/mesquite/ornamental/BranchNotes/asteriskBIGTool.gif
new file mode 100644
index 0000000..32bfc8f
Binary files /dev/null and b/Source/mesquite/ornamental/BranchNotes/asteriskBIGTool.gif differ
diff --git a/Source/mesquite/ornamental/BranchNotes/asteriskTool.gif b/Source/mesquite/ornamental/BranchNotes/asteriskTool.gif
new file mode 100644
index 0000000..a1a6653
Binary files /dev/null and b/Source/mesquite/ornamental/BranchNotes/asteriskTool.gif differ
diff --git a/Source/mesquite/ornamental/CircularTree/CircularTree.java b/Source/mesquite/ornamental/CircularTree/CircularTree.java
new file mode 100644
index 0000000..a20af4e
--- /dev/null
+++ b/Source/mesquite/ornamental/CircularTree/CircularTree.java
@@ -0,0 +1,576 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.CircularTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.Arc2D;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CircularTree extends DrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsCircle.class, getName() + "  needs a method to calculate node locations.",
+		"The method to calculate node locations is arranged initially");
+	}
+	/*.................................................................................................................*/
+
+	NodeLocsCircle nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	Vector drawings;
+	int oldEdgeWidth = 6;
+	
+	/*----------------------------------------------------------------------------*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsCircle)hireEmployee(NodeLocsCircle.class, "Calculator of node locations");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node locations module obtained.");
+		drawings = new Vector();
+ 		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		return true;
+ 	 }
+ 	 public void employeeQuit(MesquiteModule m){
+ 	 	iQuit();
+ 	 }
+	/*----------------------------------------------------------------------------*/
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		CircleTreeDrawing treeDrawing =  new CircleTreeDrawing (treeDisplay, numTaxa, this);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*----------------------------------------------------------------------------*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the thickness of lines used for the branches", "[width in pixels]", commandName, "setEdgeWidth")) {
+			int newWidth = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth= MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 2, 99);
+	    	 	if (newWidth>1 && newWidth<100 && newWidth!=oldEdgeWidth) {
+	    	 		oldEdgeWidth = newWidth;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					CircleTreeDrawing treeDrawing = (CircleTreeDrawing)obj;
+			    	 			treeDrawing.setEdgeWidth(newWidth);
+			 	}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the module assigning node locations", null, commandName, "getNodeLocsEmployee")) {
+    	 		return nodeLocsTask;
+    	 	}
+ 		else
+ 			return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Circular tree";
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Draws trees in circular form." ;
+   	 }
+	/*.................................................................................................................*/
+}
+
+/* ======================================================================== */
+class CircleTreeDrawing extends TreeDrawing  {
+
+	public int highlightedBranch, branchFrom;
+	public int xFrom, yFrom, xTo, yTo;
+	public CircularTree ownerModule;
+	public int edgewidth = 6;
+	int oldNumTaxa = 0;
+ 	public static final int inset=1;
+	private boolean ready=false;
+	public Polygon[] branchPoly;
+	public Polygon[] fillBranchPoly;
+	BasicStroke defaultStroke;
+
+	private int foundBranch;
+	NameReference triangleNameRef;
+	
+	public CircleTreeDrawing (TreeDisplay treeDisplay, int numTaxa, CircularTree ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		try{
+			defaultStroke = new BasicStroke();
+		}
+		catch (Throwable t){
+		}
+		triangleNameRef = NameReference.getNameReference("triangled");
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		treeDisplay.setOrientation(TreeDisplay.CIRCULAR);
+		oldNumTaxa = numTaxa;
+		namesFollowLines = true;
+		ready = true;
+	}
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new Polygon[numNodes];
+		fillBranchPoly= new Polygon[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new Polygon();
+			branchPoly[i].xpoints = new int[16];
+			branchPoly[i].ypoints = new int[16];
+			branchPoly[i].npoints=16;
+			fillBranchPoly[i] = new Polygon();
+			fillBranchPoly[i].xpoints = new int[16];
+			fillBranchPoly[i].ypoints = new int[16];
+			fillBranchPoly[i].npoints=16;
+		}
+	}
+	/*----------------------------------------------------------------------------*/
+	private void nodePolarToLoc (double polarlength, double angle, Point center, Point loc){
+		loc.x = center.x + (int)Math.round(polarlength * Math.sin(angle));
+		loc.y = center.y - (int)Math.round(polarlength * Math.cos(angle));
+	}
+	/*----------------------------------------------------------------------------*/
+	private void nodeLocToPolar (Point loc, Point center, PolarCoord polar){
+		polar.length = Math.sqrt((loc.x-center.x) *(loc.x-center.x) + (center.y-loc.y)*(center.y-loc.y));
+		polar.angle = Math.asin((loc.x-center.x)/polar.length);
+}
+	private void makeSlantedRectangleOLD(Polygon poly, Point lowerCorner, double polarlength, double angle, int width){
+		Point loc = new Point();
+		poly.npoints=0;
+		poly.addPoint(lowerCorner.x, lowerCorner.y);
+		nodePolarToLoc (polarlength, angle, lowerCorner, loc);
+		poly.addPoint(loc.x, loc.y);
+		nodePolarToLoc (width, angle + Math.PI/2, loc, loc);
+		poly.addPoint(loc.x, loc.y);
+		nodePolarToLoc (polarlength, angle + Math.PI, loc, loc);
+		poly.addPoint(loc.x, loc.y);
+		poly.addPoint(lowerCorner.x, lowerCorner.y);
+		poly.npoints=5;
+	}
+//	makeSlantedRectangle(branchPoly[node], loc, polarLength[node]-polarLength[motherN]+edgewidth, angle[node], edgewidth);
+	private void makeSlantedRectangle(Polygon poly, double[] polarlength, double[] angle, int node, int motherN, int width){
+		Point loc = new Point();
+		Point w = new Point();
+		nodePolarToLoc (width, angle[node] + Math.PI/2, ownerModule.nodeLocsTask.treeCenter, w);
+		int wx2p = (w.x -ownerModule.nodeLocsTask.treeCenter.x)/2;
+		if (wx2p == 0)
+			wx2p = 1;
+		int wx2m = -wx2p;
+		int wy2p = (w.y -ownerModule.nodeLocsTask.treeCenter.y)/2;
+		if (wy2p == 0)
+			wy2p = 1;
+		int wy2m = -wy2p;
+		//if (wx2p == 0 && wy2p == 0)
+		//	wx2p = 1;
+		poly.npoints=0;
+		nodePolarToLoc(polarlength[node], angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+/**/
+		poly.addPoint(loc.x + wx2p, loc.y + wy2p);
+		poly.addPoint(loc.x + wx2m, loc.y + wy2m);
+		nodePolarToLoc(polarlength[motherN], angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+		poly.addPoint(loc.x + wx2m, loc.y + wy2m);
+		poly.addPoint(loc.x + wx2p, loc.y + wy2p);
+		nodePolarToLoc(polarlength[node], angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+		poly.addPoint(loc.x + wx2p, loc.y + wy2p);
+/**
+ 		poly.addPoint(loc.x + wx, loc.y + wy);
+		poly.addPoint(loc.x, loc.y);
+		nodePolarToLoc(polarlength[motherN], angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+		poly.addPoint(loc.x, loc.y);
+		poly.addPoint(loc.x + wx, loc.y + wy);
+		nodePolarToLoc(polarlength[node], angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+		poly.addPoint(loc.x + wx, loc.y + wy);
+/**/
+		poly.npoints=5;
+	}
+	private double findHighest(Tree tree, int node, double[] polarLength){
+		if (tree.nodeIsTerminal(node))
+			return polarLength[node];
+		
+		double highest = 0;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			double thisHeight = findHighest( tree, d, polarLength);
+			if (thisHeight>highest)
+				highest = thisHeight;
+		}
+		return highest;
+	}
+	/*----------------------------------------------------------------------------*/
+	private  void drawOneBranch(Tree tree, int node, Graphics g) {
+		int motherN= tree.motherOfNode(node);
+		Point loc = new Point();
+		double[] polarLength= ownerModule.nodeLocsTask.polarLength;
+		double[] angle= ownerModule.nodeLocsTask.angle;
+		
+		
+		lineTipX[node]= treeDisplay.getTreeDrawing().x[node];
+		lineTipY[node]= treeDisplay.getTreeDrawing().y[node];
+
+		nodePolarToLoc(polarLength[motherN]-edgewidth, angle[node], ownerModule.nodeLocsTask.treeCenter, loc);
+
+		lineBaseX[node]= loc.x;
+		lineBaseY[node]= loc.y;
+
+//		private void makeSlantedRectangle(Polygon poly, double[] polarlength, double[] angle, int node, int motherN, int width){
+			makeSlantedRectangle(branchPoly[node],polarLength, angle, node, motherN, edgewidth);
+			makeSlantedRectangle(fillBranchPoly[node],polarLength, angle, node, motherN, edgewidth-2);
+	//	makeSlantedRectangle(fillBranchPoly[node], loc, polarLength[node]-polarLength[motherN]+edgewidth-2, angle[node], edgewidth-2);
+		g.fillPolygon(branchPoly[node]);
+
+
+
+		
+		int L, R, T, B;
+		drawArc(g, polarLength, angle, node, motherN, 0);
+
+ 
+		if (tree.getAssociatedBit(triangleNameRef,node)) {
+			double highestTerminal = findHighest(tree, node, polarLength);
+			R = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x + highestTerminal);
+			L = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x - highestTerminal);
+			T =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y - highestTerminal);
+			B =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y + highestTerminal);
+
+			for (int i=0; i<3; i++)
+				g.drawArc(L+i, T+i, R-L-i-i, B-T-i-i, convertToDegrees(myAngleToTheirs(angle[tree.leftmostTerminalOfNode(node)])), convertToDegrees(-angle[tree.rightmostTerminalOfNode(node)] +angle[tree.leftmostTerminalOfNode(node)]));
+		
+			for (int j=0; j<2; j++)
+				for (int i=0; i<2; i++) {
+					g.drawLine(x[node]+i,y[node]+j, x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j);
+					//g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+					g.drawLine(x[node]+i,y[node]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+				}
+		}
+		if (emphasizeNodes()) {
+			Color prev = g.getColor();
+			g.setColor(Color.red);//for testing
+			g.fillRect(x[node]-2, y[node]-2, 4, 4);
+			//g.fillPolygon(nodePoly(node));
+			g.setColor(prev);
+		}
+	}
+	private void drawArc(Graphics g, double[] polarLength, double[] angle, int node, int motherN, int inset){
+
+		if (g instanceof Graphics2D)
+			try {
+				double L, W, T;
+				L = ownerModule.nodeLocsTask.treeCenter.x - polarLength[motherN];
+				T =  ownerModule.nodeLocsTask.treeCenter.y - polarLength[motherN];
+				
+				W = 2 * polarLength[motherN];
+				
+				
+//TODO:  This is all in bad shape!!!
+				double edgeAngle = 0;
+				/*Math.atan(edgewidth/polarLength[motherN])/2;
+				if (edgeAngle <0)
+					edgeAngle = -edgeAngle;*/
+			Arc2D arc;
+		/*
+		 * 	if (angle[motherN]>angle[node])
+				arc = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[motherN]+edgeAngle)), convertToDoubleDegrees(angle[motherN] -angle[node]), Arc2D.OPEN); 
+			else
+				arc = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[node]+edgeAngle)), convertToDoubleDegrees(angle[node] -angle[motherN]), Arc2D.OPEN); 
+		*/
+			if (angle[motherN]<angle[node])
+				arc = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[motherN]+edgeAngle)), convertToDoubleDegrees(angle[motherN] -angle[node]), Arc2D.OPEN); 
+			else
+				arc = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[node]+edgeAngle)), convertToDoubleDegrees(angle[node] -angle[motherN]), Arc2D.OPEN); 
+			//arc = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[motherN])), convertToDegrees(angle[motherN] -angle[node]), Arc2D.OPEN); 
+			if (arc!=null) {
+				BasicStroke wideStroke = new BasicStroke(edgewidth);
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setStroke(wideStroke);
+				g2.draw(arc);
+				g2.setStroke(defaultStroke);
+			}
+			/*
+			 * Arc2D arcE;
+			if (angle[motherN]>angle[node])
+				g.setColor(Color.red);
+			else
+				g.setColor(Color.green);
+				arcE= new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[node])), 0.01, Arc2D.OPEN); 
+				
+				if (angle[motherN]>angle[node])
+					arcE = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[motherN]-edgeAngle)), 0.1, Arc2D.OPEN); 
+				else
+					arcE = new Arc2D.Double(L, T, W, W, convertToDoubleDegrees(myAngleToTheirs(angle[node]-edgeAngle)), 0.1, Arc2D.OPEN); 
+				
+				
+			if (arcE!=null) {
+				BasicStroke wideStroke = new BasicStroke(edgewidth);
+				Graphics2D g2 = (Graphics2D)g;
+				
+				g2.setStroke(wideStroke);
+				g2.draw(arcE);
+				g2.setStroke(defaultStroke);
+			}
+			*/
+		}
+		catch (Throwable e){
+			int L, R, T, B;
+			R = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x + polarLength[motherN]);
+			L = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x - polarLength[motherN]);
+			T =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y - polarLength[motherN]);
+			B =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y + polarLength[motherN]);
+			
+		for (int i=inset; i<edgewidth-inset; i++)
+			g.drawArc(L+i, T+i, R-L-i-i, B-T-i-i, convertToDegrees(myAngleToTheirs(angle[motherN]))-1, convertToDegrees(angle[motherN] -angle[node]));
+		}
+	}
+	/*----------------------------------------------------------------------------*/
+	private double convertToDoubleDegrees(double angle){
+		if (angle<0)
+			return -Math.round((-angle/2/Math.PI) * 360);
+		else
+			return Math.round((angle/2/Math.PI) * 360);
+	}
+	/*----------------------------------------------------------------------------*/
+	private int convertToDegrees(double angle){
+		if (angle<0)
+			return (int)-Math.round((-angle/2/Math.PI) * 360);
+		else
+			return (int)Math.round((angle/2/Math.PI) * 360);
+	}
+	/*----------------------------------------------------------------------------*/
+	private double myAngleToTheirs(double myAngle) {
+		return (-myAngle +Math.PI/2);
+	}
+	/*----------------------------------------------------------------------------*/
+	private   void drawClade(Tree tree, int node, Graphics g) {
+		if (tree.nodeExists(node)) {
+			long c = tree.getAssociatedLong(ColorDistribution.colorNameReference, node);
+			g.setColor(treeDisplay.getBranchColor(node));
+			if (tree.getRooted() || tree.getRoot()!=node)
+				drawOneBranch(tree, node, g);
+
+			if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawClade( tree, d, g);
+		}
+	}
+	/*----------------------------------------------------------------------------*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+	        if (MesquiteTree.OK(tree)) {
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	g.setColor(treeDisplay.branchColor);
+	       	 	drawClade(tree, drawnRoot, g);  
+	       	 }
+	   }
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+	        if (MesquiteTree.OK(tree)) {
+			if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+			if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+			if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	if (!tree.nodeExists(getDrawnRoot()))
+	        		setDrawnRoot(tree.getRoot());
+			ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, getDrawnRoot(),  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		}
+	}
+	/*----------------------------------------------------------------------------*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+	}
+	/*----------------------------------------------------------------------------*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+	}
+	/*_________________________________________________*/
+	private boolean ancestorIsTriangled(Tree tree, int node) {
+		if (!tree.nodeExists(node))
+			return false;
+		if (tree.getAssociatedBit(triangleNameRef, tree.motherOfNode(node)))
+			return true;
+		if (tree.getRoot() == node || tree.getSubRoot() == node)
+			return false;
+		return ancestorIsTriangled(tree, tree.motherOfNode(node));
+	}
+	/*----------------------------------------------------------------------------*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node)) {
+			Color c = g.getColor();
+			if (treeDisplay.getOrientation()==TreeDisplay.CIRCULAR) {
+				int numColors = colors.getNumColors();
+				for (int i=0; i<numColors; i++) {
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(fillBranchPoly[node]);
+					int motherN= tree.motherOfNode(node);
+					double[] polarLength= ownerModule.nodeLocsTask.polarLength;
+					double[] angle= ownerModule.nodeLocsTask.angle;
+					drawArc(g, polarLength, angle, node, motherN, 1);
+					/*
+					int L, R, T, B;
+					R = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x + polarLength[motherN]);
+					L = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x - polarLength[motherN]);
+					T =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y - polarLength[motherN]);
+					B =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y + polarLength[motherN]);
+
+					for (int j=1; j<edgewidth-1; j++)
+						g.drawArc(L+j, T+j, R-L-j-j, B-T-j-j, convertToDegrees(myAngleToTheirs(angle[motherN])), convertToDegrees(angle[motherN] -angle[node]));
+					*/
+				}
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node)) {
+			g.fillPolygon(fillBranchPoly[node]);
+			int motherN= tree.motherOfNode(node);
+			double[] polarLength= ownerModule.nodeLocsTask.polarLength;
+			double[] angle= ownerModule.nodeLocsTask.angle;
+			drawArc(g, polarLength, angle, node, motherN, 1);
+			/*int L, R, T, B;
+			R = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x + polarLength[motherN]);
+			L = (int)Math.round(ownerModule.nodeLocsTask.treeCenter.x - polarLength[motherN]);
+			T =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y - polarLength[motherN]);
+			B =  (int)Math.round(ownerModule.nodeLocsTask.treeCenter.y + polarLength[motherN]);
+
+			for (int i=1; i<edgewidth-1; i++)
+				g.drawArc(L+i, T+i, R-L-i-i, B-T-i-i, convertToDegrees(myAngleToTheirs(angle[motherN])), convertToDegrees(angle[motherN] -angle[node]));
+			*/
+			}
+	}
+	   
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+		int motherNode = tree.motherOfNode(N);
+		xValue.deassignAllValues();
+		yValue.deassignAllValues();
+		angle.setToUnassigned();
+		if (tree.nodeExists(motherNode)) {
+			double[] angles= ownerModule.nodeLocsTask.angle;
+			double[] polarLength= ownerModule.nodeLocsTask.polarLength;
+			MesquiteInteger xN = new MesquiteInteger(this.x[N]);
+			MesquiteInteger yN = new MesquiteInteger(this.y[N]);
+			double thisAngle = 3*Math.PI/2+angles[N];
+			GraphicsUtil.translateAlongAngle(xN,yN, thisAngle,(int)(Math.abs(polarLength[N]-polarLength[motherNode])/2));
+			angle.setValue(angles[N]);
+			xValue.setValue(xN.getValue());
+			yValue.setValue(yN.getValue());
+		}
+	}
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		double[] angle= ownerModule.nodeLocsTask.angle;
+		
+		//drawArc(g, polarLength, angle, node, motherN, 1);
+
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int halfNodeWidth = getNodeWidth()/2;
+		MesquiteInteger startX = new MesquiteInteger(x[node]);
+		MesquiteInteger startY = new MesquiteInteger(y[node]);
+		GraphicsUtil.translateAlongAngle(startX,startY, angle[node],offset);
+		return GraphicsUtil.createAngledSquare(startX.getValue(),startY.getValue(),-angle[node],getNodeWidth());
+		}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (fillBranchPoly[node].contains(x, y) || inNode(node,x,y)) {
+
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							double[] angle= ownerModule.nodeLocsTask.angle;
+							double[] polarLength= ownerModule.nodeLocsTask.polarLength;
+							MesquiteInteger startX = new MesquiteInteger(this.x[node]);
+							MesquiteInteger startY = new MesquiteInteger(this.y[node]);
+							int offset = (getNodeWidth()-getEdgeWidth())/2;
+							double thisAngle = 3*Math.PI/2+angle[node];
+							GraphicsUtil.translateAlongAngle(startX,startY, thisAngle,(int)Math.abs(polarLength[node]-polarLength[motherNode]));
+							fraction.setValue(GraphicsUtil.fractionAlongLine(x, y, startX.getValue(), startY.getValue(), this.x[node], this.y[node],false,false));
+						}
+					}
+			}
+
+			if (!tree.getAssociatedBit(triangleNameRef,node))
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					ScanBranches(tree, d, x, y, fraction);
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+	        if (MesquiteTree.OK(tree) && ready) {
+	        	foundBranch=0;
+	       		 ScanBranches(tree, drawnRoot, x, y, fraction);
+	       		 if (foundBranch == tree.getRoot() && !tree.getRooted())
+	       		 	return 0;
+	       		 else
+	       		 return foundBranch;
+	       	}
+	       	return 0;
+	}
+	
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+	}
+/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+/*End new code Feb.22.07 oliver*/
+}
+class PolarCoord {
+	public double length, angle;
+}
+
+
diff --git a/Source/mesquite/ornamental/ColorTreeByPartition/ColorTreeByPartition.java b/Source/mesquite/ornamental/ColorTreeByPartition/ColorTreeByPartition.java
new file mode 100644
index 0000000..815fa6e
--- /dev/null
+++ b/Source/mesquite/ornamental/ColorTreeByPartition/ColorTreeByPartition.java
@@ -0,0 +1,292 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.ColorTreeByPartition;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ColorTreeByPartition extends TreeDisplayAssistantDI {
+	public Vector extras;
+	MesquiteBoolean colorByPartition;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		colorByPartition = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Color Branches by Partition", makeCommand("colorByPartition",  this), colorByPartition);
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		ColorByPartitionExtra newPj = new ColorByPartitionExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color Branches by Partition";
+	}
+
+	/*.................................................................................................................*/
+	/** return whether or not this module should have snapshot saved when saving a macro given the current snapshot mode.*/
+	public boolean satisfiesSnapshotMode(){
+		return (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL || MesquiteTrunk.snapshotMode == Snapshot.SNAPDISPLAYONLY);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("colorByPartition " + colorByPartition.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether to color the tree by the current taxon partition", "[on or off]", commandName, "colorByPartition")) {
+			if (StringUtil.blank(arguments))
+				colorByPartition.setValue(!colorByPartition.getValue());
+			else
+				colorByPartition.toggleValue(parser.getFirstToken(arguments));
+			for (int i =0; i<extras.size(); i++){
+				ColorByPartitionExtra e = (ColorByPartitionExtra)extras.elementAt(i);
+				e.setShowColors(colorByPartition.getValue());
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Colors the tree's branches by the taxon partition." ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
+/* ======================================================================== */
+class ColorByPartitionExtra extends TreeDisplayExtra implements MesquiteListener   {
+	ColorTreeByPartition branchNotesModule;
+	TaxaPartition partitions = null;
+	ColorDistribution[] colors;
+	TaxaGroup[][] groupsAtNode;
+	boolean showColors;
+	public ColorByPartitionExtra (ColorTreeByPartition ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		branchNotesModule = ownerModule;
+		showColors = branchNotesModule.colorByPartition.getValue();
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int node, Graphics g) {
+		if (showColors) {
+			if (needsReharvesting)
+				reharvest(tree);
+
+			if (partitions != null){
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					drawOnTree(tree, d, g);
+				treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  node, colors[node], g);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int node, Graphics g) {
+		drawOnTree(tree, node, g);
+	}
+
+	void setShowColors(boolean a){
+		showColors = a;
+		treeDisplay.pleaseUpdate(false);
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		return null;
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		return null;
+	}
+
+	void fillNext(TaxaGroup[] t, TaxaGroup group){
+		for (int i = 0; i<t.length; i++)
+			if (t[i] == group){ //already there
+				return;
+			}
+		for (int i = 0; i<t.length; i++)
+			if (t[i] == null){
+				t[i] = group;
+				return;
+			}
+
+	}
+	/*.................................................................................................................*/
+	public   void harvestColorsDOWN(Tree tree, int node) {
+		if (partitions != null){
+			int count = 0;
+			if (tree.nodeIsTerminal(node)){
+				int taxonNumber = tree.taxonNumberOfNode(node);
+				TaxaGroup mi = (TaxaGroup)partitions.getProperty(taxonNumber);
+				if (mi!=null) {
+					fillNext(groupsAtNode[node], mi);
+				}
+			}
+			else 	for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				harvestColorsDOWN(tree, d);
+
+				for (int i=0; i<groupsAtNode[d].length; i++){
+					if (groupsAtNode[d][i] != null)
+						fillNext(groupsAtNode[node], groupsAtNode[d][i]);
+				}
+			}
+			int counter = 0;
+			for (int i=0; i<groupsAtNode[node].length; i++){
+				if (groupsAtNode[node][i] != null)
+					colors[node].setColor(counter++, groupsAtNode[node][i].getColor());
+			}
+
+		}
+
+	}
+
+	boolean inArray(TaxaGroup[] gs, TaxaGroup g){
+		for (int i = 0; i<gs.length; i++)
+			if (gs[i] == g)
+				return true;
+		return false;
+	}
+
+	int numDescWithGroup(Tree tree, int node, TaxaGroup c){
+		int count = 0;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			if (inArray(groupsAtNode[d], c))
+				count++;
+		return count;
+	}
+	TaxaGroup[] tempGroups;
+	/*.................................................................................................................*/
+	public   void harvestColorsUP(Tree tree, int node) {
+		if (partitions != null){
+			if (tree.nodeIsInternal(node)){
+				//rule is: if color is found in more than one descendent, the color it
+
+				for (int i=0; i < tempGroups.length; i++)
+					tempGroups[i] = null;
+
+				for (int i=0; i<groupsAtNode[node].length; i++) //store groups in temporary space
+					fillNext(tempGroups, groupsAtNode[node][i]);
+
+				int count = 0;
+				colors[node].initialize();
+				for (int i=0; i < groupsAtNode[node].length; i++)
+					groupsAtNode[node][i] = null;
+
+				count = 0;
+				for (int i=0; i<tempGroups.length; i++){
+					if (tempGroups[i] != null){
+						int numDesc = numDescWithGroup(tree, node, tempGroups[i]);
+						if (numDesc>1 || (numDesc == 1 && node != tree.getRoot() && inArray(groupsAtNode[tree.motherOfNode(node)], tempGroups[i]))){
+							groupsAtNode[node][count] = tempGroups[i];
+							colors[node].setColor(count++, tempGroups[i].getColor());
+						}
+					}
+				}				
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					harvestColorsUP(tree, d);
+			}
+		}
+	}
+	Taxa taxa;
+	boolean needsReharvesting = false;
+	void reharvest(Tree tree){
+		if (tree == null)
+			return;
+		if (colors == null || colors.length != tree.getNumNodeSpaces())
+			colors = new ColorDistribution[ tree.getNumNodeSpaces()];
+		if (colors == null)
+			return;
+		for (int i= 0; i< colors.length; i++){
+			if (colors[i] == null)
+				colors[i] = new ColorDistribution();
+			colors[i].initialize();
+		}
+
+		if (taxa == null)
+			partitions = (TaxaPartition)tree.getTaxa().getCurrentSpecsSet(TaxaPartition.class);
+		else
+			partitions = (TaxaPartition)taxa.getCurrentSpecsSet(TaxaPartition.class);
+		if (groupsAtNode == null || groupsAtNode.length != tree.getNumNodeSpaces())
+			groupsAtNode = new TaxaGroup[tree.getNumNodeSpaces()][];
+		TaxaGroupVector groups = (TaxaGroupVector)ownerModule.getProject().getFileElement(TaxaGroupVector.class, 0);
+		int numGroups = groups.size();
+		if (tempGroups == null || tempGroups.length != numGroups)
+			tempGroups = new TaxaGroup[numGroups];
+		for (int i= 0; i< groupsAtNode.length; i++){
+			if (groupsAtNode[i] == null || groupsAtNode[i].length != numGroups)
+				groupsAtNode[i] = new TaxaGroup[numGroups];
+			else for (int k = 0; k<groupsAtNode[i].length; k++)
+				groupsAtNode[i][k] = null;
+		}
+
+
+		harvestColorsDOWN(tree, tree.getRoot());
+		harvestColorsUP(tree, tree.getRoot());
+		needsReharvesting = false;
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (taxa == null && tree != null){			
+			taxa = tree.getTaxa();
+			taxa.addListener(this);
+		}
+		needsReharvesting = true;
+	}
+	/** passes which object changed, along with optional Notification object with details (e.g., code number (type of change) and integers (e.g. which character))*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == taxa)
+			needsReharvesting = true;
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	public void turnOff() {
+		branchNotesModule.extras.removeElement(this);
+		if (taxa != null)
+			taxa.removeListener(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/Constellation/Constellation.java b/Source/mesquite/ornamental/Constellation/Constellation.java
new file mode 100644
index 0000000..f62cc4c
--- /dev/null
+++ b/Source/mesquite/ornamental/Constellation/Constellation.java
@@ -0,0 +1,382 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.Constellation;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.BallsNSticks.BallsNSticks;
+
+/* ======================================================================== */
+public class Constellation extends DrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsCircle.class, getName() + "  needs a method to calculate node locations.",
+		"The method to calculate node locations is arranged initially");
+	}
+
+	NodeLocs nodeLocsTask;
+	Vector drawings;
+	int oldSpotSize = 24;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsFree)hireEmployee(NodeLocsFree.class, "Calculator of node locations");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node locator module obtained");
+		drawings = new Vector();
+ 		addMenuItem( "Spot Size...", makeCommand("setSpotDiameter",  this));
+ 		return true;
+ 	 }
+  	 
+ 	 public void employeeQuit(MesquiteModule m){
+ 	 	iQuit();
+ 	 }
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		ConstellationDrawing treeDrawing=  new ConstellationDrawing (treeDisplay, numTaxa, this);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setSpotDiameter " + oldSpotSize); 
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the diameter of the spots", "[diameter]", commandName, "setSpotDiameter")) {
+			int newDiameter= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newDiameter))
+				newDiameter = MesquiteInteger.queryInteger(containerOfModule(), "Set spot diameter", "Spot Diameter:", oldSpotSize, 6, 100);
+    	 		if (newDiameter>6 && newDiameter<100 && newDiameter!=oldSpotSize) {
+    	 			oldSpotSize = newDiameter;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					ConstellationDrawing treeDrawing = (ConstellationDrawing)obj;
+    	 				treeDrawing.spotsize=newDiameter;
+    	 				treeDrawing.treeDisplay.setMinimumTaxonNameDistance(treeDrawing.spotsize/2, 4);
+    	 			}
+	 				parametersChanged();
+    	 		}
+    	 		
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the module assigning node locations", null, commandName, "getNodeLocsEmployee")) {
+    	 		return nodeLocsTask;
+    	 	}
+    	 	else {
+ 			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Constellation";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Draws trees with spots at the nodes in a more or less unrooted way." ;
+   	 }
+	/*.................................................................................................................*/
+}
+
+/* ======================================================================== */
+class ConstellationDrawing extends TreeDrawing  {
+
+	public Constellation ownerModule;
+	public int edgewidth = 4;
+	public int spotsize = 24;
+	int oldNumTaxa = 0;
+ 	public static final int inset=1;
+	private boolean ready=false;
+	public RotatedRectangle[] branchPoly;
+
+	private int foundBranch;
+	
+	public ConstellationDrawing (TreeDisplay treeDisplay, int numTaxa, Constellation ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+	    	treeDisplay.setMinimumTaxonNameDistance(spotsize/2, 4);
+		treeDisplay.setOrientation(TreeDisplay.FREEFORM);
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		ready = true;
+	}
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new RotatedRectangle[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new RotatedRectangle();
+		}
+	}
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		int m =tree.motherOfNode(node);
+		if (tree.motherOfNode(node) == tree.getRoot() && !tree.getRooted() && !tree.nodeIsPolytomous( tree.getRoot() )) {
+			int sisterNode = 0;
+			if (tree.nodeExists(tree.nextSisterOfNode(node)))
+				sisterNode = tree.nextSisterOfNode(node);
+			else if (tree.nodeExists(tree.previousSisterOfNode(node)))
+				sisterNode = tree.previousSisterOfNode(node);
+			if (sisterNode !=0) 
+				m = sisterNode;
+		}
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[m];
+		lineBaseX[node]=x[m];
+		branchPoly[node].setShape(x[node], y[node], x[m], y[m], edgewidth, y[node]<y[m], RotatedRectangle.RECTANGLE);
+	}
+	/*_________________________________________________*/
+	/** Draw highlight for branch node */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		Color tC = g.getColor();
+		if (flip)
+			g.setColor(Color.red);
+		else
+			g.setColor(Color.blue);
+		for (int i=1; i<4; i++)
+			g.drawOval( x[node]- spotsize/2 - 2 - i, y[node]- spotsize/2 - 2 - i, spotsize + 3 + i + i, spotsize + 3 + i + i);
+
+		g.setColor(tC);
+	}
+	/*_________________________________________________*/
+	private   void drawOneBranch(Tree tree, Graphics g, int node, int drawnRoot) {
+		if (tree.nodeExists(node)) {
+			//g.setColor(Color.black);//for testing
+			g.setColor(treeDisplay.getBranchColor(node));
+			if (tree.numberOfParentsOfNode(node)>1) {
+				for (int i=1; i<=tree.numberOfParentsOfNode(node); i++) {
+						int anc =tree.parentOfNode(node, i);
+						if (anc!= tree.motherOfNode(node)) {
+							g.drawLine(x[node],y[node], x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node]+1,y[node], x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node],y[node]+1, x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]+1);
+							g.drawLine(x[node]+1,y[node]+1, x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]+1);
+						}
+				}
+			}
+			if (node == tree.getRoot() || node == drawnRoot) {
+			}
+			else if (tree.motherOfNode(node) == tree.getRoot() && !tree.getRooted() && !tree.nodeIsPolytomous( tree.getRoot() )) {
+				int sisterNode = 0;
+				if (tree.nodeExists(tree.nextSisterOfNode(node)))
+					sisterNode = tree.nextSisterOfNode(node);
+				else if (tree.nodeExists(tree.previousSisterOfNode(node)))
+					sisterNode = tree.previousSisterOfNode(node);
+				if (sisterNode !=0) {
+					branchPoly[node].fill(g, true);
+				}
+			}
+			else {
+				branchPoly[node].fill(g, true);
+			}
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawOneBranch( tree, g, thisSister, drawnRoot);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+			if (node == tree.getRoot()) {
+				if (tree.getRooted() || tree.nodeIsPolytomous( tree.getRoot() )) {
+					drawSpot( g, node);
+					highlightSpot( g, node);
+				}
+			}
+			else if (node == drawnRoot) {
+				drawSpot( g, node);
+				Color c = g.getColor();
+				g.setColor(Color.gray);
+				highlightSpot( g, node);
+				if (c!=null) g.setColor(c);
+			}
+			else {
+				drawSpot( g, node);
+				
+				if (emphasizeNodes()) {
+					Color prev = g.getColor();
+					g.setColor(Color.red);//for testing
+					drawSpot(g,node);
+					g.setColor(prev);
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+	        if (MesquiteTree.OK(tree)) {
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	g.setColor(treeDisplay.branchColor);
+			calculateLines(tree, drawnRoot);
+	       	 	drawOneBranch(tree, g, drawnRoot, drawnRoot);  
+	       	 }
+	   }
+	
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+	        if (MesquiteTree.OK(tree)) {
+			if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+			if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+			if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	if (!tree.nodeExists(getDrawnRoot()))
+	        		setDrawnRoot(tree.getRoot());
+			ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, getDrawnRoot(),  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		}
+	}
+	/*_________________________________________________*/
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+
+		int mother = tree.motherOfNode(N);
+		if (tree.nodeExists(mother)) {
+			xValue.setValue(GraphicsUtil.xCenterOfLine(x[mother], y[mother], x[N], y[N]));
+			yValue.setValue(GraphicsUtil.yCenterOfLine(x[mother], y[mother], x[N], y[N]));
+			angle.setValue(GraphicsUtil.angleOfLine(x[mother], y[mother], x[N], y[N]));
+		}
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int h, int v){
+		if ((h-x[node])*(h-x[node]) + (v-y[node])*(v-y[node]) < spotsize*spotsize/4) //use radius
+			return true;
+		else
+			return false;
+		// ask if x, y is in node's spot    g.fillOval( x[node]- spotsize/2, y[node]- spotsize/2, spotsize, spotsize);
+	}
+	/*_________________________________________________*/
+	private void drawSpot(Graphics g, int node){
+		GraphicsUtil.fillOval(g, x[node]- spotsize/2, y[node]- spotsize/2, spotsize, spotsize, true);
+	}
+	/*_________________________________________________*/
+	private void highlightSpot(Graphics g, int node){
+		for (int diam = spotsize + 12; diam> spotsize + 8; diam --)
+			g.drawOval( x[node]- (int)((double)diam/2 + 0.5), y[node]- (int)((double)diam/2 + 0.5), diam, diam);
+	}
+	/*_________________________________________________*/
+	private void fillSpot(Graphics g, int node){
+		GraphicsUtil.fillOval(g, x[node]- spotsize/2 + 2, y[node]- spotsize/2 + 2, spotsize - 4, spotsize - 4, true);
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			Color c = g.getColor();
+			int numColors = colors.getNumColors();
+			if (numColors==1){
+				g.setColor(colors.getColor(0, !tree.anySelected()|| tree.getSelected(node)));
+				fillSpot(g,node);
+			}
+			else if (numColors>0) {
+				int startAngle=270;
+				double totalFreq=0;
+				for (int i=0; i<numColors; i++) totalFreq += colors.getWeight(i);
+				
+				int arcAngle = 360/(numColors);
+				for (int i=0; i<numColors; i++) {
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					
+					arcAngle = (int)((colors.getWeight(i)/totalFreq)*360);
+					GraphicsUtil.fillArc(g,  x[node]- spotsize/2 + 2, y[node]- spotsize/2 + 2, spotsize - 4, spotsize - 4, startAngle, arcAngle, true);
+					startAngle+=arcAngle;
+				}
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || node != tree.getRoot())) {
+			fillSpot(g,node);
+		}
+	}
+	   
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (branchPoly[node].contains(x, y) || inNode(node, x, y)) {
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							fraction.setValue(GraphicsUtil.fractionAlongLine(x, y, this.x[motherNode], this.y[motherNode], this.x[node], this.y[node],false,false));
+						}
+					}
+				
+			}
+			
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				ScanBranches(tree, thisSister, x, y,fraction);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+
+		}
+	}
+
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+	        if (MesquiteTree.OK(tree) && ready) {
+	        	foundBranch=0;
+	       		 ScanBranches(tree, drawnRoot, x, y,fraction);
+	       		 return foundBranch;
+	       	}
+	       	return 0;
+	}
+	
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+	}
+/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+/*End new code Feb.22.07 oliver*/
+}
+	
+
diff --git a/Source/mesquite/ornamental/DrawTreeAssocDoubles/DrawTreeAssocDoubles.java b/Source/mesquite/ornamental/DrawTreeAssocDoubles/DrawTreeAssocDoubles.java
new file mode 100644
index 0000000..188cf9e
--- /dev/null
+++ b/Source/mesquite/ornamental/DrawTreeAssocDoubles/DrawTreeAssocDoubles.java
@@ -0,0 +1,489 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.DrawTreeAssocDoubles;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CentralModelListener;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.AsymmModel;
+
+/* ======================================================================== */
+public class DrawTreeAssocDoubles extends TreeDisplayAssistantDI {
+	public Vector extras;
+	public boolean first = true;
+	MesquiteBoolean on, percentage, horizontal, centred, whiteEdges;
+	MesquiteInteger positionAlongBranch;
+	MesquiteSubmenuSpec positionSubMenu;
+	public static final boolean CENTEREDDEFAULT = false;
+	public ListableVector names;
+	static boolean asked= false;
+	int digits = 4;
+	int fontSize = 10;
+	int xOffset = 0;
+	int yOffset = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		names = new ListableVector();
+		if (!MesquiteThread.isScripting())
+			names.addElement(new MesquiteString("consensusFrequency", "consensusFrequency"), false);
+		on = new MesquiteBoolean(true);  //ON is currently true always
+		percentage = new MesquiteBoolean(false);
+		horizontal = new MesquiteBoolean(true);
+		centred = new MesquiteBoolean(CENTEREDDEFAULT);
+		whiteEdges = new MesquiteBoolean(true);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Node-Associated Values");
+		addItemToSubmenu(null, mss, "Choose Values To Show...", makeCommand("chooseValues",  this));
+		MesquiteSubmenuSpec mss2 =  addSubmenu(mss, "Styles");  //Wayne: here it is.   x123y
+		addItemToSubmenu(mss, mss2, "Percentage, Below Branch", makeCommand("setCorvallisStyle",  this));
+		addItemToSubmenu(null, mss, "Digits...", makeCommand("setDigits",  this));
+		addCheckMenuItemToSubmenu(null, mss, "Show As Percentage", makeCommand("writeAsPercentage",  this), percentage);
+		addItemToSubmenu(null, mss, "Font Size...", makeCommand("setFontSize",  this));
+		addCheckMenuItemToSubmenu(null, mss, "White Edges", makeCommand("toggleWhiteEdges",  this), whiteEdges);
+		addCheckMenuItemToSubmenu(null, mss, "Centered on Branch", makeCommand("toggleCentred",  this), centred);
+//		addItemToSubmenu(null, mss, "Position Along Branch...", makeCommand("setPositionAlongBranch",  this));
+		addItemToSubmenu(null, mss, "Locations...", makeCommand("setOffset",  this));
+		addCheckMenuItemToSubmenu(null, mss, "Horizontal", makeCommand("toggleHorizontal",  this), horizontal);
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		NodeAssocValuesExtra newPj = new NodeAssocValuesExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Node-Associated Values";
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (on.getValue()){
+			temp.addLine("setOn " + on.toOffOnString());
+			for (int i=0; i< names.size(); i++)
+				temp.addLine("toggleShow " + StringUtil.tokenize(((Listable)names.elementAt(i)).getName()));
+			temp.addLine("setDigits " + digits); 
+			temp.addLine("writeAsPercentage " + percentage.toOffOnString());
+			temp.addLine("toggleCentred " + centred.toOffOnString());
+//			temp.addLine("setPositionAlongBranch " + positionAlongBranch); 
+			temp.addLine("toggleHorizontal " + horizontal.toOffOnString());
+			temp.addLine("toggleWhiteEdges " + whiteEdges.toOffOnString());
+			temp.addLine("setFontSize " + fontSize); 
+			temp.addLine("setOffset " + xOffset + "  " + yOffset); 
+		}
+		return temp;
+	}
+	/*.................................................................................................................*
+	public void queryLocationAlongBranch(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog settingsDialog = new ExtensibleDialog(containerOfModule(), "Location Along Branch",  buttonPressed);
+		RadioButtons rb = settingsDialog.addRadioButtons(new String[]{"Just apical to node","Just basal to node","Centered on branch"}, positionAlongBranch.getValue());
+		settingsDialog.completeAndShowDialog(true);
+		boolean ok = (settingsDialog.query()==0);
+		
+		if (ok) {
+			positionAlongBranch.setValue(rb.getValue());
+			
+		}
+		settingsDialog.dispose();
+	 	storePreferences();
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether to show the node associated values", "[on or off]", commandName, "setOn")) {  //on always except if scripted off
+			if (StringUtil.blank(arguments))
+				on.setValue(!on.getValue());
+			else
+				on.toggleValue(parser.getFirstToken(arguments));
+			for (int i =0; i<extras.size(); i++){
+				NodeAssocValuesExtra e = (NodeAssocValuesExtra)extras.elementAt(i);
+				e.setOn(on.getValue());
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Shows dialog box to choose what values to display", null, commandName, "chooseValues")) {
+			if (extras.size() == 0)
+				return null;
+			showChoiceDialog((Associable)((NodeAssocValuesExtra)extras.elementAt(0)).lastTree, names);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the values as percentage", "[on or off]", commandName, "writeAsPercentage")) {
+			if (StringUtil.blank(arguments))
+				percentage.setValue(!percentage.getValue());
+			else
+				percentage.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the values with horizontally", "[on or off]", commandName, "toggleHorizontal")) {
+			if (StringUtil.blank(arguments))
+				horizontal.setValue(!horizontal.getValue());
+			else
+				horizontal.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the values white edges", "[on or off]", commandName, "toggleWhiteEdges")) {
+			if (StringUtil.blank(arguments))
+				whiteEdges.setValue(!whiteEdges.getValue());
+			else
+				whiteEdges.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the values centrally over the branches", "[on or off]", commandName, "toggleCentred")) {
+			if (StringUtil.blank(arguments))
+				centred.setValue(!centred.getValue());
+			else
+				centred.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets how many digits are shown", "[number of digits]", commandName, "setDigits")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set number of digits", "Number of digits (after decimal point) to display for values on tree:", digits, 0, 24);
+			if (newWidth>=0 && newWidth<24 && newWidth!=digits) {
+				digits = newWidth;
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Set's to David's style", "", commandName, "setCorvallisStyle")) {
+			whiteEdges.setValue(false);
+			percentage.setValue(true);
+			centred.setValue(false);
+			horizontal.setValue(true);
+			digits=0;
+			xOffset = 0;
+			yOffset = 9;
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets offset of label from nodes", "[offsetX] [offsetY]", commandName, "setOffset")) {
+			int newX= MesquiteInteger.fromFirstToken(arguments, pos);
+			int newY= MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newX)){
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger nX = new MesquiteInteger(xOffset);
+				MesquiteInteger nY = new MesquiteInteger(yOffset);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Location of Values", "X offset from node", "Y offset from node", answer, nX, nY,-200,200,-200,200, null);
+				if (!answer.getValue())
+					return null;
+				newX = nX.getValue();
+				newY = nY.getValue();
+			}
+			if (newX>-200 && newX <200 && newY>-200 && newY <200 && (newX!=xOffset ||   newY!=yOffset)) {
+				xOffset = newX;
+				yOffset = newY;
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets font size", "[font size]", commandName, "setFontSize")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set font size", "Font Size:", fontSize, 2, 96);
+			if (newWidth>1 && newWidth<96 && newWidth!=fontSize) {
+				fontSize = newWidth;
+				for (int i =0; i<extras.size(); i++){
+					NodeAssocValuesExtra e = (NodeAssocValuesExtra)extras.elementAt(i);
+					e.resetFontSize();
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+/*		else if (checker.compare(this.getClass(), "Sets the location of the value along the branch", "[location constant]", commandName, "setPositionAlongBranch")) {
+			int newPos= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newPos))
+				queryLocationAlongBranch();
+			else
+				positionAlongBranch.setValue(newPos);
+			
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+*/		
+		
+		else if (checker.compare(this.getClass(), "Sets whether to show a node associated values", "[on or off]", commandName, "toggleShow")) {
+			String name = parser.getFirstToken(arguments);
+			if (isShowing(name)){
+				names.removeElementAt(names.indexOfByName(name), false);
+			}
+			else
+				names.addElement(new MesquiteString(name, name), false);
+
+			for (int i =0; i<extras.size(); i++){
+				NodeAssocValuesExtra e = (NodeAssocValuesExtra)extras.elementAt(i);
+				e.update();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void showChoiceDialog(Associable tree, ListableVector names) {
+		if (tree == null)
+			return;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ListableVector v = new ListableVector();
+		int num = tree.getNumberAssociatedDoubles();
+		boolean[] shown = new boolean[num + names.size()]; //bigger than needed probably
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (da != null){
+				v.addElement(new MesquiteString(da.getName(), ""), false);
+			if (names.indexOfByName(da.getName())>=0)
+				shown[i] = true;
+			}
+		}
+		for (int i = 0; i<names.size(); i++){
+			String name = ((MesquiteString)names.elementAt(i)).getName();
+			if (v.indexOfByName(name)<0){
+				v.addElement(new MesquiteString(name, " (not in current tree)"), false);
+				if (v.size()-1>= shown.length)
+					shown[v.size()-1] = true;
+			}
+		}
+		if (v.size()==0)
+			alert("This Tree has no values associated with nodes");
+		else {
+			ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Values to show",  buttonPressed);
+			queryDialog.addLabel("Values to display on tree", Label.CENTER);
+			Checkbox[] checks = new Checkbox[v.size()];
+			for (int i=0; i<v.size(); i++){
+				MesquiteString ms = (MesquiteString)v.elementAt(i);
+				checks[i] = queryDialog.addCheckBox (ms.getName() + ms.getValue(), shown[i]);
+			}
+
+			queryDialog.completeAndShowDialog(true);
+
+			boolean ok = (queryDialog.query()==0);
+
+			if (ok) {
+				names.removeAllElements(false);
+				for (int i=0; i<checks.length; i++){
+					MesquiteString ms = (MesquiteString)v.elementAt(i);
+					if (checks[i].getState())
+						names.addElement(new MesquiteString(ms.getName(), ms.getName()), false);
+				}
+				for (int i =0; i<extras.size(); i++){
+					NodeAssocValuesExtra e = (NodeAssocValuesExtra)extras.elementAt(i);
+					e.setOn(on.getValue());
+				}
+			}
+
+			queryDialog.dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows values attached to nodes on the tree." ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+
+	boolean isShowing(String name){
+		boolean s = names.indexOfByName(name)>=0;
+		return s;
+	}
+}
+
+/* ======================================================================== */
+class NodeAssocValuesExtra extends TreeDisplayExtra  {
+	DrawTreeAssocDoubles assocDoublesModule;
+	MesquiteCommand taxonCommand, branchCommand;
+	boolean on;
+	Tree lastTree = null;
+//	StringInABox
+	public NodeAssocValuesExtra (DrawTreeAssocDoubles ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		assocDoublesModule = ownerModule;
+		on = assocDoublesModule.on.getValue();
+		resetFontSize();
+	}
+	StringInABox box = new StringInABox( "", treeDisplay.getFont(),1500);
+	public void resetFontSize(){
+		Font f = treeDisplay.getFont();
+		box.setFont(new Font(f.getName(),f.getStyle(), assocDoublesModule.fontSize)); 
+	}
+	/*.................................................................................................................*/
+	public   void myDraw(Tree tree, int node, Graphics g, DoubleArray[] arrays) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			myDraw(tree, d, g, arrays);
+		for (int i=0; i<arrays.length; i++){
+			double d = arrays[i].getValue(node);
+			if (MesquiteDouble.isCombinable(d)){
+				if (assocDoublesModule.percentage.getValue())
+					d *= 100;
+				if (assocDoublesModule.whiteEdges.getValue())
+					box.setColors(Color.black, Color.white);
+				else
+					box.setColors(Color.black, null);
+				box.setString(MesquiteDouble.toStringDigitsSpecified(d, assocDoublesModule.digits));
+
+				int x, y;
+				if (assocDoublesModule.centred.getValue()){   // center on branch
+					int centreBranchX = treeDisplay.getTreeDrawing().getBranchCenterX(node) + assocDoublesModule.xOffset;
+					int centreBranchY =  treeDisplay.getTreeDrawing().getBranchCenterY(node)+ assocDoublesModule.yOffset;
+					/*g.setColor(Color.yellow);
+					g.drawLine(treeDisplay.getTreeDrawing().lineBaseX[node], treeDisplay.getTreeDrawing().lineBaseY[node], treeDisplay.getTreeDrawing().lineTipX[node], treeDisplay.getTreeDrawing().lineTipY[node]);
+					/*g.setColor(Color.red);
+					g.drawRect(centreBranchX-10, centreBranchY-10, 20, 20);
+					g.drawString(Integer.toString(node), centreBranchX, centreBranchY);*/
+					int stringWidth = box.getMaxWidthMunched();
+					if (assocDoublesModule.horizontal.getValue()){
+						x = centreBranchX - stringWidth/2;
+						y = centreBranchY - assocDoublesModule.fontSize;
+					}
+					else {
+						x = centreBranchX - assocDoublesModule.fontSize*2;
+						y = centreBranchY + stringWidth/2;
+					}
+				}
+				else {
+					int stringWidth = box.getMaxWidthMunched();
+					x= treeDisplay.getTreeDrawing().getNodeValueTextBaseX(node, treeDisplay.getTreeDrawing().getEdgeWidth(), stringWidth, assocDoublesModule.fontSize, assocDoublesModule.horizontal.getValue()) + assocDoublesModule.xOffset;
+					y = treeDisplay.getTreeDrawing().getNodeValueTextBaseY(node, treeDisplay.getTreeDrawing().getEdgeWidth(), stringWidth,assocDoublesModule.fontSize,assocDoublesModule.horizontal.getValue()) + assocDoublesModule.yOffset;
+				}
+/*				else {
+					x= treeDisplay.getTreeDrawing().x[node] + assocDoublesModule.xOffset;
+					y = treeDisplay.getTreeDrawing().y[node] + assocDoublesModule.yOffset + i*assocDoublesModule.fontSize*2;
+				}
+	
+*/
+				if (assocDoublesModule.horizontal.getValue())
+					box.draw(g,  x, y);
+				else
+					box.draw(g,  x, y, 0, 1500, treeDisplay, false);
+
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int node, Graphics g) {
+		if (!on)
+			return;
+		int num = tree.getNumberAssociatedDoubles();
+		int total = 0;
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (assocDoublesModule.isShowing(da.getName()))
+				total++;
+		}
+		DoubleArray[] arrays = new DoubleArray[total];
+		int count = 0;
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (assocDoublesModule.isShowing(da.getName()))
+				arrays[count++] = da;
+		}
+
+		myDraw(tree, node, g, arrays);
+
+	}
+
+	void update(){
+		treeDisplay.pleaseUpdate(false);
+	}
+	void setOn(boolean a){
+		on = a;
+		treeDisplay.pleaseUpdate(false);
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (!on)
+			return null;
+		if (tree.getNumberAssociatedDoubles() == 0 || tree.getWhichAssociatedDouble(assocValueRef)==null)
+			return "";
+		double d = getValue(tree, node);
+		return MesquiteDouble.toString(d);
+	}
+	/**return a text version of information on tree, displayed on a text version of the tree*/
+	public String writeOnTree(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedDoubles() == 0)
+			return null;
+		return super.writeOnTree(tree, node);
+	}
+	/**return a text version of information on tree, displayed as list of nodes with information at each*/
+	public String infoAtNodes(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedDoubles() == 0)
+			return null;
+		return super.infoAtNodes(tree, node);
+	}
+	/**return a table version of information on tree, displayed as list of nodes with information at each*/
+	public String tableAtNodes(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedDoubles() == 0)
+			return null;
+		return super.tableAtNodes(tree, node);
+	}
+	MesquitePopup popup=null;
+	/*.................................................................................................................*/
+	void redoMenu(Associable tree) {
+
+		if (popup==null)
+			popup = new MesquitePopup(treeDisplay);
+		popup.removeAll();
+		popup.add(new MesquiteMenuItem("Display Node-Associated Values", null, null));
+		popup.add(new MesquiteMenuItem("-", null, null));
+		int num = tree.getNumberAssociatedDoubles();
+		if (num == 0)
+			popup.add(new MesquiteMenuItem("This Tree has no values associated with nodes", null, null));
+		else 
+			for (int i = 0; i< num; i++){
+				DoubleArray da = tree.getAssociatedDoubles(i);
+				MesquiteCommand mc = new MesquiteCommand("toggleShow", assocDoublesModule);
+				String selName = " ";
+				if (assocDoublesModule.isShowing(da.getName()))
+					selName = da.getName();
+				popup.add(new MesquiteCheckMenuItem(da.getName(), assocDoublesModule, mc, StringUtil.tokenize(da.getName()), new MesquiteString(selName )));
+			}
+		treeDisplay.add(popup);
+	}
+	public void cursorTouchField(Tree tree, Graphics g, int x, int y, int modifiers){
+		/*if (!on)  popup menu style disabled
+			return;
+		redoMenu((Associable)tree);
+		popup.show(treeDisplay, x, y);*/
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (!on)
+			return;
+		drawOnTree(tree, drawnRoot, g); //should draw numbered footnotes!
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		lastTree = tree;
+	}
+	NameReference assocValueRef = NameReference.getNameReference("consensusFrequency");
+	double getValue(Tree tree, int node){
+		return tree.getAssociatedDouble(assocValueRef, node);
+	}
+
+	public void turnOff() {
+		assocDoublesModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/DrawTreeAssocStrings/DrawTreeAssocStrings.java b/Source/mesquite/ornamental/DrawTreeAssocStrings/DrawTreeAssocStrings.java
new file mode 100644
index 0000000..87c6d9b
--- /dev/null
+++ b/Source/mesquite/ornamental/DrawTreeAssocStrings/DrawTreeAssocStrings.java
@@ -0,0 +1,405 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.DrawTreeAssocStrings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DrawTreeAssocStrings extends TreeDisplayAssistantDI {
+	public Vector extras;
+	public boolean first = true;
+	MesquiteBoolean on, horizontal, centred;
+	public ListableVector names;
+	static boolean asked= false;
+	int fontSize = 10;
+	int xOffset = 0;
+	int yOffset = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		names = new ListableVector();
+		on = new MesquiteBoolean(true);  //ON is currently true always
+		horizontal = new MesquiteBoolean(true);
+		centred = new MesquiteBoolean(true);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Node-Associated Text");
+		addItemToSubmenu(null, mss, "Choose Associated Text To Show...", makeCommand("chooseText",  this));
+		addCheckMenuItemToSubmenu(null, mss, "Centered on Branch", makeCommand("toggleCentred",  this), centred);
+		addCheckMenuItemToSubmenu(null, mss, "Horizontal", makeCommand("toggleHorizontal",  this), horizontal);
+		addItemToSubmenu(null, mss, "Font Size...", makeCommand("setFontSize",  this));
+		addItemToSubmenu(null, mss, "Locations...", makeCommand("setOffset",  this));
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 274;  
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		NodeAssocTextExtra newPj = new NodeAssocTextExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Node-Associated Text";
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (on.getValue()){
+			temp.addLine("setOn " + on.toOffOnString());
+			for (int i=0; i< names.size(); i++)
+				temp.addLine("toggleShow " + StringUtil.tokenize(((Listable)names.elementAt(i)).getName()));
+			temp.addLine("toggleCentred " + centred.toOffOnString());
+			temp.addLine("toggleHorizontal " + horizontal.toOffOnString());
+			temp.addLine("setFontSize " + fontSize); 
+			temp.addLine("setOffset " + xOffset + "  " + yOffset); 
+		}
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether to show the node associated text", "[on or off]", commandName, "setOn")) {  //on always except if scripted off
+			if (StringUtil.blank(arguments))
+				on.setValue(!on.getValue());
+			else
+				on.toggleValue(parser.getFirstToken(arguments));
+			for (int i =0; i<extras.size(); i++){
+				NodeAssocTextExtra e = (NodeAssocTextExtra)extras.elementAt(i);
+				e.setOn(on.getValue());
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Shows dialog box to choose what text to display", null, commandName, "chooseText")) {
+			if (extras.size() == 0)
+				return null;
+			showChoiceDialog((Associable)((NodeAssocTextExtra)extras.elementAt(0)).lastTree);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the text horizontally", "[on or off]", commandName, "toggleHorizontal")) {
+			if (StringUtil.blank(arguments))
+				horizontal.setValue(!horizontal.getValue());
+			else
+				horizontal.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to write the text centrally over the branches", "[on or off]", commandName, "toggleCentred")) {
+			if (StringUtil.blank(arguments))
+				centred.setValue(!centred.getValue());
+			else
+				centred.toggleValue(parser.getFirstToken(arguments));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets offset of label from nodes", "[offsetX] [offsetY]", commandName, "setOffset")) {
+			int newX= MesquiteInteger.fromFirstToken(arguments, pos);
+			int newY= MesquiteInteger.fromString(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newX)){
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger nX = new MesquiteInteger(xOffset);
+				MesquiteInteger nY = new MesquiteInteger(yOffset);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Location of Text", "X offset from node", "Y offset from node", answer, nX, nY,-200,200,-200,200, null);
+				if (!answer.getValue())
+					return null;
+				newX = nX.getValue();
+				newY = nY.getValue();
+			}
+			if (newX>-200 && newX <200 && newY>-200 && newY <200 && (newX!=xOffset ||   newY!=yOffset)) {
+				xOffset = newX;
+				yOffset = newY;
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets font size", "[font size]", commandName, "setFontSize")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set font size", "Font Size:", fontSize, 2, 96);
+			if (newWidth>1 && newWidth<96 && newWidth!=fontSize) {
+				fontSize = newWidth;
+				for (int i =0; i<extras.size(); i++){
+					NodeAssocTextExtra e = (NodeAssocTextExtra)extras.elementAt(i);
+					e.resetFontSize();
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to show a node associated text", "[on or off]", commandName, "toggleShow")) {
+			String name = parser.getFirstToken(arguments);
+			if (isShowing(name)){
+				names.removeElementAt(names.indexOfByName(name), false);
+			}
+			else
+				names.addElement(new MesquiteString(name, name), false);
+
+			for (int i =0; i<extras.size(); i++){
+				NodeAssocTextExtra e = (NodeAssocTextExtra)extras.elementAt(i);
+				e.update();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void showChoiceDialog(Associable tree) {
+		if (tree == null)
+			return;
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ListableVector v = new ListableVector();
+		int num = tree.getNumberAssociatedObjects();
+		boolean[] shown = new boolean[num + names.size()]; //bigger than needed probably
+		for (int i = 0; i< num; i++){
+			ObjectArray da = tree.getAssociatedObjects(i);
+			if (da != null){
+				v.addElement(new MesquiteString(da.getName(), ""), false);
+			if (names.indexOfByName(da.getName())>=0)
+				shown[i] = true;
+			}
+		}
+		for (int i = 0; i<names.size(); i++){
+			String name = ((MesquiteString)names.elementAt(i)).getName();
+			if (v.indexOfByName(name)<0){
+				v.addElement(new MesquiteString(name, " (not in current tree)"), false);
+				if (v.size()-1>= shown.length)
+					shown[v.size()-1] = true;
+			}
+		}
+		if (v.size()==0)
+			alert("This Tree has no text associated with nodes");
+		else {
+			ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Text to show",  buttonPressed);
+			queryDialog.addLabel("Text to display on tree", Label.CENTER);
+			Checkbox[] checks = new Checkbox[v.size()];
+			for (int i=0; i<v.size(); i++){
+				MesquiteString ms = (MesquiteString)v.elementAt(i);
+				checks[i] = queryDialog.addCheckBox (ms.getName() + ms.getValue(), shown[i]);
+			}
+
+			queryDialog.completeAndShowDialog(true);
+
+			boolean ok = (queryDialog.query()==0);
+
+			if (ok) {
+				names.removeAllElements(false);
+				for (int i=0; i<checks.length; i++){
+					MesquiteString ms = (MesquiteString)v.elementAt(i);
+					if (checks[i].getState())
+						names.addElement(new MesquiteString(ms.getName(), ms.getName()), false);
+				}
+				for (int i =0; i<extras.size(); i++){
+					NodeAssocTextExtra e = (NodeAssocTextExtra)extras.elementAt(i);
+					e.setOn(on.getValue());
+				}
+			}
+
+			queryDialog.dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Shows text attached to nodes on the tree." ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+
+	boolean isShowing(String name){
+		boolean s = names.indexOfByName(name)>=0;
+		return s;
+	}
+}
+
+/* ======================================================================== */
+class NodeAssocTextExtra extends TreeDisplayExtra  {
+	DrawTreeAssocStrings assocTextModule;
+	MesquiteCommand taxonCommand, branchCommand;
+	boolean on;
+	Tree lastTree = null;
+//	StringInABox
+	public NodeAssocTextExtra (DrawTreeAssocStrings ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		assocTextModule = ownerModule;
+		on = assocTextModule.on.getValue();
+		resetFontSize();
+	}
+	StringInABox box = new StringInABox( "", treeDisplay.getFont(),1500);
+	public void resetFontSize(){
+		Font f = treeDisplay.getFont();
+		box.setFont(new Font(f.getName(),f.getStyle(), assocTextModule.fontSize)); 
+	}
+	/*.................................................................................................................*/
+	public   void myDraw(Tree tree, int node, Graphics g, ObjectArray[] arrays) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			myDraw(tree, d, g, arrays);
+		for (int i=0; i<arrays.length; i++){
+			Object d = arrays[i].getValue(node);
+			String s = null;
+			if (d instanceof String)
+				s = (String)d;
+			else if (d instanceof MesquiteString)
+				s = ((MesquiteString)d).getValue();
+			if (!StringUtil.blank(s)){
+				box.setString(s);
+				box.setColors(Color.black, Color.white);
+				int x, y;
+				if (assocTextModule.centred.getValue()){
+					int centreBranchX = treeDisplay.getTreeDrawing().getBranchCenterX(node) + assocTextModule.xOffset;
+					int centreBranchY =  treeDisplay.getTreeDrawing().getBranchCenterY(node)+ assocTextModule.yOffset;
+					/*g.setColor(Color.yellow);
+					g.drawLine(treeDisplay.getTreeDrawing().lineBaseX[node], treeDisplay.getTreeDrawing().lineBaseY[node], treeDisplay.getTreeDrawing().lineTipX[node], treeDisplay.getTreeDrawing().lineTipY[node]);
+					/*g.setColor(Color.red);
+					g.drawRect(centreBranchX-10, centreBranchY-10, 20, 20);
+					g.drawString(Integer.toString(node), centreBranchX, centreBranchY);*/
+					int stringWidth = box.getMaxWidthMunched();
+					if (assocTextModule.horizontal.getValue()){
+						x = centreBranchX - stringWidth/2;
+						y = centreBranchY - assocTextModule.fontSize;
+					}
+					else {
+						x = centreBranchX - assocTextModule.fontSize*2;
+						y = centreBranchY + stringWidth/2;
+					}
+				}
+				else {
+					x= treeDisplay.getTreeDrawing().x[node] + assocTextModule.xOffset;
+					y = treeDisplay.getTreeDrawing().y[node] + assocTextModule.yOffset + i*assocTextModule.fontSize*2;
+				}
+				if (assocTextModule.horizontal.getValue())
+					box.draw(g,  x, y);
+				else
+					box.draw(g,  x, y, 0, 1500, treeDisplay, false);
+
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int node, Graphics g) {
+		if (!on)
+			return;
+		int num = tree.getNumberAssociatedObjects();
+		int total = 0;
+		for (int i = 0; i< num; i++){
+			ObjectArray da = tree.getAssociatedObjects(i);
+			if (assocTextModule.isShowing(da.getName()))
+				total++;
+		}
+		ObjectArray[] arrays = new ObjectArray[total];
+		int count = 0;
+		for (int i = 0; i< num; i++){
+			ObjectArray da = tree.getAssociatedObjects(i);
+			if (assocTextModule.isShowing(da.getName()))
+				arrays[count++] = da;
+		}
+
+		myDraw(tree, node, g, arrays);
+
+	}
+
+	void update(){
+		treeDisplay.pleaseUpdate(false);
+	}
+	void setOn(boolean a){
+		on = a;
+		treeDisplay.pleaseUpdate(false);
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (!on)
+			return null;
+		if (tree.getNumberAssociatedObjects() == 0 || tree.getWhichAssociatedObject(assocValueRef)==null)
+			return "";
+		return getValue(tree, node);
+	}
+	/**return a text version of information on tree, displayed on a text version of the tree*/
+	public String writeOnTree(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedObjects() == 0)
+			return null;
+		return super.writeOnTree(tree, node);
+	}
+	/**return a text version of information on tree, displayed as list of nodes with information at each*/
+	public String infoAtNodes(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedObjects() == 0)
+			return null;
+		return super.infoAtNodes(tree, node);
+	}
+	/**return a table version of information on tree, displayed as list of nodes with information at each*/
+	public String tableAtNodes(Tree tree, int node){
+		if (!on || tree.getNumberAssociatedObjects() == 0)
+			return null;
+		return super.tableAtNodes(tree, node);
+	}
+	MesquitePopup popup=null;
+	/*.................................................................................................................*/
+	void redoMenu(Associable tree) {
+
+		if (popup==null)
+			popup = new MesquitePopup(treeDisplay);
+		popup.removeAll();
+		popup.add(new MesquiteMenuItem("Display Node-Associated Text", null, null));
+		popup.add(new MesquiteMenuItem("-", null, null));
+		int num = tree.getNumberAssociatedObjects();
+		if (num == 0)
+			popup.add(new MesquiteMenuItem("This Tree has no text associated with nodes", null, null));
+		else 
+			for (int i = 0; i< num; i++){
+				ObjectArray da = tree.getAssociatedObjects(i);
+				MesquiteCommand mc = new MesquiteCommand("toggleShow", assocTextModule);
+				String selName = " ";
+				if (assocTextModule.isShowing(da.getName()))
+					selName = da.getName();
+				popup.add(new MesquiteCheckMenuItem(da.getName(), assocTextModule, mc, StringUtil.tokenize(da.getName()), new MesquiteString(selName )));
+			}
+		treeDisplay.add(popup);
+	}
+	public void cursorTouchField(Tree tree, Graphics g, int x, int y, int modifiers){
+		/*if (!on)  popup menu style disabled
+			return;
+		redoMenu((Associable)tree);
+		popup.show(treeDisplay, x, y);*/
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (!on)
+			return;
+		drawOnTree(tree, drawnRoot, g); //should draw numbered footnotes!
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		lastTree = tree;
+	}
+	NameReference assocValueRef = NameReference.getNameReference("consensusFrequency");
+	String getValue(Tree tree, int node){
+		Object obj  = tree.getAssociatedObject(assocValueRef, node);
+		if (obj instanceof String)
+			return (String)obj;
+		else if (obj instanceof MesquiteString)
+			return ((MesquiteString)obj).getValue();
+		return "";
+	}
+
+	public void turnOff() {
+		assocTextModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/ManageAttachedNotes/ManageAttachedNotes.java b/Source/mesquite/ornamental/ManageAttachedNotes/ManageAttachedNotes.java
new file mode 100644
index 0000000..cf3c880
--- /dev/null
+++ b/Source/mesquite/ornamental/ManageAttachedNotes/ManageAttachedNotes.java
@@ -0,0 +1,666 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.ManageAttachedNotes;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== 
+ *new in 1.02*  */
+public class ManageAttachedNotes extends FileInit /*implements ElementManager*/ {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return null;
+	}
+
+	private void writeToFile(MesquiteFile file,  MesquiteString pending, StringBuffer context, String s){
+		if (pending != null && !pending.isBlank()){
+			file.writeLine(pending.toString());
+			pending.setValue("");
+		}
+		if (context != null && context.length()>0){
+			file.writeLine(context.toString());
+			context.setLength(0);
+		}
+		file.writeLine(s);
+	}
+	/*.................................................................................................................*/
+	public boolean writeNexusCommands(MesquiteFile file, String blockName, MesquiteString pending){ 
+		boolean found = false;
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			StringBuffer s = new StringBuffer(100);
+			StringBuffer tokSB = new StringBuffer(100);
+			String eL =";" + StringUtil.lineEnding();
+			NameReference ref = NameReference.getNameReference("notes");
+			MesquiteProject project = file.getProject();
+			StringBuffer context = new StringBuffer();
+			for (int i=0; i<project.getNumberTaxas(); i++){
+				Taxa taxa = getProject().getTaxa(i);
+				if (taxa.getFile() == file) {
+					if (project.getNumberTaxas()>1) //note shift in 1. 06 to "current matrix and taxa" to avoid having to repeat in each note
+						context.append("\tTAXA = " +  StringUtil.tokenize(taxa.getName(), null, tokSB) + eL);
+					ObjectArray taxNotes = taxa.getWhichAssociatedObject(ref);
+					for (int it = 0; it<taxa.getNumTaxa(); it++){
+						if (taxNotes != null){
+							Object obj = taxNotes.getValue(it);
+							if (obj!=null && obj instanceof AttachedNotesVector){
+								AttachedNotesVector notes = (AttachedNotesVector)obj;
+								for (int iim=0; iim<notes.getNumNotes(); iim++){
+									AttachedNote im = notes.getAttachedNote(iim);
+									if (im.anythingNEXUStoWrite()){
+										s.append('\t');
+										s.append(AttachedNote.ANNOTATION);
+										s.append(' ');
+										s.append(AttachedNote.TAXON);
+										s.append(" = ");
+										s.append(Integer.toString(it+1));
+										s.append(' ');
+										im.getNexusString(s);
+										s.append(eL);
+										writeToFile(file, pending, context, s.toString());
+										s.setLength(0);
+										found = true;
+									}
+
+								}
+							}
+						}
+					}
+				}
+				context.setLength(0);
+			}
+			for (int i=0; i<project.getNumberCharMatrices(); i++){
+				CharacterData data = getProject().getCharacterMatrix(i);
+				if (data.getFile() == file && data.getWritable()){
+					if (project.getNumberCharMatrices()>1 || (!file.useSimplifiedNexus&&  !file.useConservativeNexus && !data.hasDefaultName() && !NexusBlock.suppressTITLE)) {
+						if (project.getNumberTaxas()>1) //note shift in 1. 06 to "current matrix and taxa" to avoid having to repeat in each note
+							context.append("\tCHARACTERS = " +  StringUtil.tokenize(data.getName(), null, tokSB) +" TAXA = " +  StringUtil.tokenize(data.getTaxa().getName(), null, tokSB) + eL);
+						else  //note shift in 1. 06 to "current matrix and taxa" to avoid having to repeat in each note
+							context.append("\tCHARACTERS = " +  StringUtil.tokenize(data.getName(), null, tokSB) + eL);
+					}
+					ObjectArray charImages = data.getWhichAssociatedObject(ref);
+					if (charImages !=null){
+						for (int ic = 0; ic<data.getNumChars(); ic++){
+							Object obj = charImages.getValue(ic);
+							if (obj!=null && obj instanceof AttachedNotesVector){
+								AttachedNotesVector notes = (AttachedNotesVector)obj;
+								for (int iim=0; iim<notes.getNumNotes(); iim++){
+									AttachedNote im = notes.getAttachedNote(iim);
+									if (im.anythingNEXUStoWrite()){
+										s.append('\t');
+										s.append(AttachedNote.ANNOTATION);
+										s.append(' ');
+										s.append(AttachedNote.CHARACTER);
+										s.append(" = ");
+										s.append(Integer.toString(ic+1));
+										s.append(' ');
+										im.getNexusString(s);
+										s.append(eL);
+										writeToFile(file, pending, context, s.toString());
+										s.setLength(0);
+										found = true;
+									}
+								}
+							}
+						}
+					}
+					Object2DArray cellImages = data.getWhichCellObjects(ref);
+					if (cellImages !=null){
+						for (int ic = 0; ic<data.getNumChars(); ic++){
+							for (int it = 0; it<data.getNumTaxa(); it++){
+								Object obj = cellImages.getValue(ic, it);
+								if (obj!=null && obj instanceof AttachedNotesVector){
+									AttachedNotesVector notes = (AttachedNotesVector)obj;
+									for (int iim=0; iim<notes.getNumNotes(); iim++){
+										AttachedNote im = notes.getAttachedNote(iim);
+										if (im.anythingNEXUStoWrite()){
+											s.append('\t');
+											s.append(AttachedNote.ANNOTATION);
+											s.append(' ');
+											s.append(AttachedNote.TAXON);
+											s.append(" = ");
+											s.append(Integer.toString(it+1));
+											s.append(' ');
+											s.append(AttachedNote.CHARACTER);
+											s.append(" = ");
+											s.append(Integer.toString(ic+1));
+											s.append(' ');
+											im.getNexusString(s);
+											s.append(eL);
+											writeToFile(file, pending, context, s.toString());
+											s.setLength(0);
+											found = true;
+										}
+									}
+								}
+							}
+						}
+					}
+					if (data instanceof CategoricalData){
+						CategoricalData cData = (CategoricalData)data;
+						for (int ic = 0; ic<cData.getNumChars(); ic++){
+							for (int st = 0; st<=CategoricalState.maxCategoricalState; st++){
+								AttachedNotesVector notes = cData.getStateAnnotationsVector(ic, st);
+								if (notes != null)
+									for (int iim=0; iim<notes.getNumNotes(); iim++){
+										AttachedNote im = notes.getAttachedNote(iim);
+										if (im.anythingNEXUStoWrite()){
+											s.append('\t');
+											s.append(AttachedNote.ANNOTATION);
+											s.append(' ');
+											s.append(AttachedNote.STATE);
+											s.append(" = ");
+											s.append(Integer.toString(st));
+											s.append(' ');
+											s.append(AttachedNote.CHARACTER);
+											s.append(" = ");
+											s.append(Integer.toString(ic+1));
+											s.append(' ');
+											im.getNexusString(s);
+											s.append(eL);
+											writeToFile(file, pending, context, s.toString());
+											s.setLength(0);
+											found = true;
+										}
+									}
+
+							}
+						}
+					}
+
+				}
+			}
+		}
+		return found;
+	}
+	private AttachedNote getNote(int ic, int it, int st, CharacterData data, Taxa taxa, AttachedNote n){
+		if (MesquiteInteger.isCombinable(it) || MesquiteInteger.isCombinable(ic)) {
+			//figure out if this is for character, cell, or taxon
+			if (MesquiteInteger.isCombinable(ic) && ic>=0){ // character or cell or state
+				if (MesquiteInteger.isCombinable(st) && st>=0) { //state
+					if (data == null)
+						return null; 
+					CategoricalData cData = (CategoricalData)data;
+					AttachedNotesVector aim = cData.getStateAnnotationsVector(ic, st);
+					if (aim == null) {
+						aim = new AttachedNotesVector(data);
+						try {
+						cData.setStateAnnotationsVector(ic, st, aim);
+						}
+						catch (ArrayIndexOutOfBoundsException e){
+							MesquiteMessage.println("ERROR: attempt to set state annotation for character " + (ic+1) + " of " + data.getNumChars() + "; state " + st);
+						}
+					}
+					AttachedNote hL = new AttachedNote();
+					hL.setAuthor((Author)null);
+					aim.addNote(hL, true);
+					return hL;
+				}
+				else  if (MesquiteInteger.isCombinable(it) && it>=0) { //cell
+					if (data == null)
+						return null; 
+					NameReference notesNameRef = NameReference.getNameReference("notes");
+
+					AttachedNotesVector aim = (AttachedNotesVector)data.getCellObject(notesNameRef, ic, it);
+					if (aim == null)
+						aim = new AttachedNotesVector(data);
+					AttachedNote hL = new AttachedNote();
+					hL.setAuthor((Author)null);
+					data.setCellObject(notesNameRef, ic, it, aim);
+					data.setCellObjectDisplay(ic, it);
+					aim.addNote(hL, true);
+					return hL;
+				}
+				else { //whole character
+					NameReference notesNameRef = data.makeAssociatedObjects("notes");
+
+					AttachedNotesVector aim =(AttachedNotesVector)data.getAssociatedObject(notesNameRef, ic);
+					if (aim == null)
+						aim = new AttachedNotesVector(data);
+					AttachedNote hL = new AttachedNote();
+					hL.setAuthor((Author)null);
+					data.setAssociatedObject(notesNameRef, ic, aim);
+					aim.addNote(hL, true);
+					return hL;
+				}
+			}
+			else { //taxon
+				if (taxa == null)
+					return null;
+				NameReference notesNameRef = taxa.makeAssociatedObjects("notes");
+
+				AttachedNotesVector aim = (AttachedNotesVector)taxa.getAssociatedObject(notesNameRef, it);
+				if (aim == null)
+					aim = new AttachedNotesVector(taxa);
+				AttachedNote hL = new AttachedNote();
+				hL.setAuthor((Author)null);
+				taxa.setAssociatedObject(notesNameRef, it, aim);
+				aim.addNote(hL, true);
+				return hL;
+			}
+		}
+		return null;
+
+	}
+	/*
+	writeNexusblock in annot block
+	readNexusBlock don't use block.toString
+	use abbreviated
+	 *
+	Author findAuthor(String authorCode){
+		if (authorCode == null)
+			return null;
+		if (MesquiteModule.author != null && authorCode.equals(MesquiteModule.author.getCode()))
+			return MesquiteModule.author;
+		if (getProject().numAuthors()>0){
+			ListableVector v = getProject().getAuthors();
+			for (int i = 0; i< v.size(); i++){
+				Author a = (Author)v.elementAt(i);
+				if (a.getCode()!= null && authorCode.equals(a.getCode()))
+					return a;
+			}
+		}
+		return null;
+	}
+	 */
+	long ancient = 500000000000L;
+	boolean oldWarnedM = false;
+	boolean oldWarned = false;
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			if (fuse)
+				return true;
+			MesquiteProject project = file.getProject();
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			String commandName = ParseUtil.getToken(command, startCharT);
+			Taxon taxon = null;
+
+			if (!commandName.equalsIgnoreCase("ANNOTATION") && !commandName.equalsIgnoreCase(AttachedNote.ANNOTATION))
+				return false;
+
+			String token = ParseUtil.getToken(command, startCharT); 
+			String dummy;
+			AttachedNote note = null;
+			long dateMod = -1;
+			boolean dateCreatedSet = false;
+			int taxonNumber=MesquiteInteger.unassigned;
+			Taxa taxa = nBlock.getDefaultTaxa();
+			int charNumber=MesquiteInteger.unassigned;
+			int stateNumber = MesquiteInteger.unassigned;
+			CharacterData data = nBlock.getDefaultCharacters();
+			while (!StringUtil.blank(token) && !token.equals(";")) {
+				if (token.equalsIgnoreCase(AttachedNote.TAXON) || token.equalsIgnoreCase("TAXON")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+					taxonNumber = MesquiteInteger.fromString(whichItem);
+					if (MesquiteInteger.isCombinable(taxonNumber))
+						taxonNumber--; //to convert to internal
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.TAXA) || token.equalsIgnoreCase("TAXA")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String taxaTitle = (ParseUtil.getToken(command, startCharT));
+					taxa = getProject().getTaxaLastFirst(taxaTitle);
+					if (taxa == null) {
+						taxa = getProject().getTaxa(0);
+					}
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.CHARACTER) || token.equalsIgnoreCase("CHARACTER")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+					charNumber = MesquiteInteger.fromString(whichItem);
+					if (MesquiteInteger.isCombinable(charNumber))
+						charNumber--; //to convert to internal
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.STATE)) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+					stateNumber = MesquiteInteger.fromString(whichItem);
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.CHARACTERS) || token.equalsIgnoreCase("CHARACTERS")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String matrixName = (ParseUtil.getToken(command, startCharT));
+					//logln("   for taxa " + taxaTitle);
+					data = getProject().getCharacterMatrixByReference(file, matrixName);
+					if (data == null) {
+						data = getProject().getCharacterMatrix(0);
+					}
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.COMMENT) || token.equalsIgnoreCase("COMMENT")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String commentString = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null)
+						note.setComment(commentString, false);
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.REFERENCE) || token.equalsIgnoreCase("REFERENCE")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String ref = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null)
+						note.setReference(ref, false);
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.TEXTFIELD) || token.equalsIgnoreCase("TEXTFIELD")) {
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note == null)
+						return true; //returns true without saving object so that the note is deleted from the file
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					if (dummy == null || !(";".equals(dummy))) {
+						dummy =ParseUtil.getToken(command, startCharT); // (
+						if (dummy == null || !(";".equals(dummy))) {
+							String fieldName = (ParseUtil.getToken(command, startCharT));
+							boolean parensDone = false;
+							if (fieldName == null || !(";".equals(fieldName))) {
+								if ("REFERENCE".equalsIgnoreCase(fieldName) || AttachedNote.REFERENCE.equalsIgnoreCase(fieldName)) {
+									String ref = (ParseUtil.getToken(command, startCharT));
+									if (")".equals(ref) || ";".equals(ref))
+										parensDone = true;
+									else
+										note.setReference(ref, false);
+								}
+								else if (AttachedNote.COMMENT.equalsIgnoreCase(fieldName) || "COMMENT".equalsIgnoreCase(fieldName)){
+									String commentString = (ParseUtil.getToken(command, startCharT));
+									if (")".equals(commentString) || ";".equals(commentString))
+										parensDone = true;
+									else
+										note.setComment(commentString, false);
+								}
+								else { 
+									//generic field
+									String field = (ParseUtil.getToken(command, startCharT));
+
+									if (")".equals(field) || ";".equals(field))
+										parensDone = true;
+									else
+										note.setTextField(fieldName, field, false);
+								}
+							}
+							else
+								MesquiteMessage.warnProgrammer("Warning: textfield with name null or ; in attached note. Command:\n\t"+ command);
+							if (!parensDone)
+								dummy =ParseUtil.getToken(command, startCharT); // )
+
+						}
+					}
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.AUTHOR) || token.equalsIgnoreCase("AUTHOR")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String author = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null)
+						note.setAuthor(author);
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.AUTHORCODE) || token.equalsIgnoreCase("AUTHORCODE")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String authorCode = (ParseUtil.getToken(command, startCharT));
+					Author author = getProject().findAuthor(authorCode, false);
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null) {
+						if (author == null)
+							note.setAuthorCode(authorCode);
+						else
+							note.setAuthor(author);
+					}
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.DATEMOD) || token.equalsIgnoreCase("DATEMOD")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String s = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null) {
+						note.setDateModified(s);
+						dateMod = note.getDateModifiedInMillis(); //this is done because subsequent calls will modify the note, and so this needs to be reset
+						if (dateMod < ancient) {
+							if (!oldWarnedM)
+								file.setOpenAsUntitled("Warning: an annotation's date modified appears to be incorrect (too old): " + s + " (" + dateMod + ").  The date will be reset to be unspecified.  This warning will not be given again, but may apply to more annotations.");
+							note.setDateModified(0L);
+							dateMod = 0L;
+							oldWarnedM = true;
+						}
+					}
+					else {
+						return true; //returns true without saving object so that the note is deleted from the file
+					}
+				}
+				else if (token.equalsIgnoreCase("DATECREATED")) { //OLD STYLE string; not easily parsible; read as string directly
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String s = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null) {
+						note.setDateCreatedString(s);
+						dateCreatedSet = true;
+					}
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.DATECREATED)) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String s = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null) {
+						long dc = NexusBlock.getTimeFromNEXUS(s);
+						if (dc > ancient){
+							note.setDateCreated(dc);
+							dateCreatedSet = true;
+						}
+						else {
+							if (!oldWarned)
+								file.setOpenAsUntitled("Warning: an annotation's date created appears to be incorrect (too old): " + s + " (" + dc + ").  The date will be reset to be unspecified.  This warning will not be given again, but may apply to more annotations.");
+							oldWarned = true;
+						}
+					}
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.ID)) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String s = (ParseUtil.getToken(command, startCharT));
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note != null) {
+						note.setID(s);
+					}
+					else
+						return true; //returns true without saving object so that the note is deleted from the file
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.IMAGELOC) || token.equalsIgnoreCase("IMAGELOC")) {
+					if (taxa!=null){
+						dummy =ParseUtil.getToken(command, startCharT); // 
+						String pathName = ParseUtil.getToken(command, startCharT);
+						if (pathName != null && pathName.indexOf(":\\")>=0 && MesquiteFile.fileExists(pathName)){ //to fix files written (by bug) with absolute paths in Windows
+							pathName = MesquiteFile.decomposePath(getProject().getHomeDirectoryName(), pathName);
+						}
+						if (note == null)
+							note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+						if (note != null){
+							if (!StringUtil.blank(pathName)) 
+								note.setImagePath(pathName, MesquiteFile.composePath(getProject().getHomeDirectoryName(),  pathName), false);
+						}
+						else
+							return true; //returns true without saving object so that the note is deleted from the file
+					}
+				}
+				else if (token.equalsIgnoreCase(AttachedNote.IMAGELABEL) || token.equalsIgnoreCase("IMAGELABEL")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					dummy =ParseUtil.getToken(command, startCharT); // (
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note == null)
+						return true; //returns true without saving object so that the note is deleted from the file
+					ImageLabel label = new ImageLabel();
+					note.addLabel(label);
+					String t = null;
+					while (!endOfSubcommand(t = ParseUtil.getToken(command, startCharT))) {
+						if (t.equalsIgnoreCase(AttachedNote.TEXT) || t.equalsIgnoreCase("TEXT")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setText(ParseUtil.getToken(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.FONT) || t.equalsIgnoreCase("FONT")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setFontName( ParseUtil.getToken(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.COLORNUMBER) || t.equalsIgnoreCase("COLORNUMBER")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setFontColor(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.COLOR) || t.equalsIgnoreCase("COLOR")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setFontColor(ParseUtil.getToken(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.SIZE) || t.equalsIgnoreCase("SIZE")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setFontSize(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase("X")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setX(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase("Y")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setY(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.POINTERX) || t.equalsIgnoreCase("POINTERX")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setPointerX(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.POINTERY) || t.equalsIgnoreCase("POINTERY")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setPointerY(MesquiteInteger.fromString(command, startCharT));
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.SHOWPOINTER) || t.equalsIgnoreCase("SHOWPOINTER")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							String d =ParseUtil.getToken(command, startCharT); // token
+							label.setShowPointer("true".equalsIgnoreCase(d));
+
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.FIXEDTOIMAGE) || t.equalsIgnoreCase("FixedToImage")){
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							String d =ParseUtil.getToken(command, startCharT); // token
+							label.setFixedToImage("true".equalsIgnoreCase(d));
+
+						}
+						else if (t.equalsIgnoreCase(AttachedNote.WIDTH) || t.equalsIgnoreCase("WIDTH")){ 
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							label.setWidth(MesquiteInteger.fromString(command, startCharT));
+						}
+						else { // save for forward compatibility in label.setExtraSubcommands()
+							dummy =ParseUtil.getToken(command, startCharT); // =
+							dummy =ParseUtil.getToken(command, startCharT); // token
+							label.addExtraSubcommand(t + " = " + ParseUtil.tokenize(dummy) );
+						}
+
+					}
+				}
+				else {  //save for forward compatibility in note.addExtraSubcommand()
+					if (note == null)
+						note = getNote(charNumber, taxonNumber, stateNumber, data, taxa, note);
+					if (note == null)
+						return true; //returns true without saving object so that the note is deleted from the file
+					String sE =ParseUtil.getToken(command, startCharT) + " "; // =
+					dummy = ParseUtil.getToken(command, startCharT) + " "; // token or ?
+					sE += dummy;
+					if ("(".equals(dummy)){
+						String t = null;
+						while (!endOfSubcommand(t = ParseUtil.getToken(command, startCharT))) {
+							sE += t + " ";
+							sE +=ParseUtil.getToken(command, startCharT) + " "; //token
+						}
+						sE += t + " "; //)
+					}
+					note.addExtraSubcommand(sE, false);
+
+				}
+				if (note != null){
+					if (dateMod>0)
+						note.setDateModified(dateMod);
+					if (!dateCreatedSet)
+						note.setDateCreated(0);
+				}
+
+				token = ParseUtil.getToken(command, startCharT); 
+			}
+			return true;
+
+		}
+		return false;
+	}
+	boolean endOfSubcommand(String t){
+		if (t == null)
+			return true;
+		if (")".equals(t))
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new ANCT();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage Attached Notes";
+	}
+
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages (including NEXUS read/write) notes attached to taxa, characters and cells of matrices." ;
+	}
+	/*.................................................................................................................*/
+
+}
+
+class ANCT  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return (blockName.equalsIgnoreCase("NOTES") && (commandName.equalsIgnoreCase("ANNOTATION") ||  commandName.equalsIgnoreCase(AttachedNote.ANNOTATION)));
+	}
+}
+
+
diff --git a/Source/mesquite/ornamental/ManageHyperlinks/ManageHyperlinks.java b/Source/mesquite/ornamental/ManageHyperlinks/ManageHyperlinks.java
new file mode 100644
index 0000000..c347044
--- /dev/null
+++ b/Source/mesquite/ornamental/ManageHyperlinks/ManageHyperlinks.java
@@ -0,0 +1,216 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.ManageHyperlinks;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ManageHyperlinks extends FileInit /*implements ElementManager*/ {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return null;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			String s ="";
+			boolean found = false;
+			MesquiteProject project = file.getProject();
+			for (int i=0; i<project.getNumberTaxas(); i++){
+				Taxa taxa = getProject().getTaxa(i);
+				if (taxa.getFile() == file) {
+					for (int it = 0; it<taxa.getNumTaxa(); it++){
+						Object obj = taxa.getAssociatedObject(linkNameRef, it);
+						if (obj!=null && obj instanceof String){
+							s += "\tHYPERLINK TAXA = " + StringUtil.tokenize(taxa.getName()) + " TAXON = " + it + " URL = " + StringUtil.tokenize((String)obj) + ";" + StringUtil.lineEnding();
+							found = true;
+						}
+					}
+					Clades clades = taxa.getClades();
+					for (int ic = 0; ic<clades.getNumClades(); ic++) {
+						Clade clade = clades.getClade(ic);
+						if (clade.getLink()!=null) {
+							s += "HYPERLINK TAXA = " + StringUtil.tokenize(taxa.getName()) + " CLADE = " + StringUtil.tokenize(clade.getName()) + " URL = " + StringUtil.tokenize(clade.getLink()) + ";" + StringUtil.lineEnding();
+							found = true;
+						}
+					}
+				}   
+			}
+			for (int i=0; i<project.getNumberCharMatrices(); i++){
+				CharacterData data = getProject().getCharacterMatrix(i);
+				if (data.getFile() == file  && data.getWritable()){
+					Object2DArray hyperLinks = data.getWhichCellObjects(NameReference.getNameReference("hyperlink"));
+					if (hyperLinks !=null){
+						for (int it = 0; it<data.getNumTaxa(); it++){
+							for (int ic = 0; ic<data.getNumChars(); ic++){
+								Object obj = hyperLinks.getValue(ic, it);
+								if (obj!=null && obj instanceof NexusWritable){
+									s += "\tCELLHYPERLINK TAXA = " + StringUtil.tokenize(data.getTaxa().getName()) + " CHARACTERS = " + StringUtil.tokenize(data.getName()) + " TAXON = " + it  + " CHARACTER = " + ic + " URL = " + StringUtil.tokenize(((NexusWritable)obj).getNexusString()) + ";" + StringUtil.lineEnding();
+									found = true;
+								}
+							}
+						}
+					}
+				}
+			}
+			if (found)
+				return s;
+			else
+				return null;
+		}
+		return null;
+	}
+	NameReference linkNameRef = NameReference.getNameReference("hyperlink");
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			if (fuse)
+				return true;
+			MesquiteProject project = file.getProject();
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			String commandName = ParseUtil.getToken(command, startCharT);
+			int code = 0;
+			if (commandName.equalsIgnoreCase("HYPERLINK"))
+				code = 1;
+			else if (commandName.equalsIgnoreCase("CELLHYPERLINK"))
+				code = 2;
+			if (code>0) {
+				String token = ParseUtil.getToken(command, startCharT); 
+				String dummy;
+				String pathName = "";
+				int taxonNumber=-1;
+				int charNumber=-1;
+				CharacterData data = null;
+				if (getProject().getNumberCharMatrices()>0)
+					data = getProject().getCharacterMatrix(0);
+				Clade clade = null;
+				Taxa	taxa = getProject().getTaxa(0);
+				while (!StringUtil.blank(token) && !token.equals(";")) {
+					if (token.equalsIgnoreCase("TAXON")) {
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+						taxonNumber = MesquiteInteger.fromString(whichItem);
+					}
+					else if (token.equalsIgnoreCase("CHARACTER")) {
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+						charNumber = MesquiteInteger.fromString(whichItem);
+					}
+					else if (token.equalsIgnoreCase("CLADE")) {
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						if (taxa!=null){
+							Clades clades = taxa.getClades();
+							String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+							if ((clade = clades.findClade(whichItem))==null)
+								clade = clades.addClade(whichItem);
+						}
+					}
+					else if (token.equalsIgnoreCase("TAXA")) {
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						String taxaTitle = (ParseUtil.getToken(command, startCharT));
+						//logln("   for taxa " + taxaTitle);
+						taxa = getProject().getTaxaLastFirst(taxaTitle);
+						if (taxa == null) {
+							taxa = getProject().getTaxa(0);
+						}
+					}
+					else if (token.equalsIgnoreCase("CHARACTERS")) {
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						String matrixName = (ParseUtil.getToken(command, startCharT));
+						//logln("   for taxa " + taxaTitle);
+						data = getProject().getCharacterMatrixByReference(file, matrixName);
+						if (data == null) {
+							data = getProject().getCharacterMatrix(0);
+						}
+					}
+					else if (token.equalsIgnoreCase("URL")) { //todo: this should be done by TaxonLink
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						pathName = ParseUtil.getToken(command, startCharT);
+						if (taxonNumber>-1) {
+							if (taxa!=null){
+								if (code == 2){
+									if (data !=null && charNumber>-1){
+										Object2DArray objs = data.getOrMakeCellObjects(NameReference.getNameReference("hyperlink"));
+										objs.setValue(charNumber, taxonNumber, new Hyperlink(pathName));
+										data.setCellObjectDisplay(charNumber, taxonNumber);
+									}
+								}
+								else {
+									if (taxa.getWhichAssociatedObject(linkNameRef)==null)
+										taxa.makeAssociatedObjects("hyperlink");
+									taxa.setAssociatedObject(linkNameRef, taxonNumber, pathName);
+								}
+							}
+						}
+						else if (clade != null){
+							clade.setLink(pathName);
+						}
+
+						
+					}
+					token = ParseUtil.getToken(command, startCharT); 
+				}
+				return true;
+						
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new HyperlinkNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage hyperlinks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) hyperlinks." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class HyperlinkNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return (blockName.equalsIgnoreCase("NOTES") && (commandName.equalsIgnoreCase("HYPERLINK") || commandName.equalsIgnoreCase("CELLHYPERLINK")));
+	}
+}
+
+
diff --git a/Source/mesquite/ornamental/ManagePictures/ManagePictures.java b/Source/mesquite/ornamental/ManagePictures/ManagePictures.java
new file mode 100644
index 0000000..6676b63
--- /dev/null
+++ b/Source/mesquite/ornamental/ManagePictures/ManagePictures.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.ManagePictures;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+public class ManagePictures extends FileInit /*implements ElementManager*/ {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+	public NexusBlock elementAdded(FileElement e){
+		return null;
+	}
+	public void elementDisposed(FileElement e){
+		//nothing needs doing since separate reference not stored locally
+	}
+	public Class getElementClass(){
+		return null;
+	}
+	/*.................................................................................................................*
+	public String getNexusCommands(MesquiteFile file, String blockName){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			String s ="";
+			boolean found = false;
+			NameReference ref = NameReference.getNameReference("image");
+			MesquiteProject project = file.getProject();
+			for (int i=0; i<project.getNumberTaxas(); i++){
+				Taxa taxa = getProject().getTaxa(i);
+				ObjectArray taxNotes = taxa.getWhichAssociatedObject(ref);
+				for (int it = 0; it<taxa.getNumTaxa(); it++){
+					String path = taxa.getTaxon(it).getIllustrationPath();
+					if (path!=null){
+						s += "\tPICTURE TAXA = " + StringUtil.tokenize(taxa.getName()) + " TAXON = " + (it+1) + " LOC = " + StringUtil.tokenize(MesquiteFile.decomposePath(getProject().getHomeDirectoryName(), path)) + ";" + StringUtil.lineEnding();
+						found = true;
+					}
+					if (taxNotes != null){
+						Object obj = taxNotes.getValue(it);
+						if (obj!=null && obj instanceof AttachedNotesVector){
+							AttachedNotesVector notes = (AttachedNotesVector)obj;
+							for (int iim=0; iim<notes.getNumNotes(); iim++){
+								AttachedNote im = notes.getAttachedNote(iim);
+								s += "\tNOTE TAXA = " + StringUtil.tokenize(taxa.getName()) + " TAXON = " + (it+1)  + " " + im.getNexusString() + ";" + StringUtil.lineEnding();
+								found = true;
+							}
+						}
+					}
+				}
+			}
+			for (int i=0; i<project.getNumberCharMatrices(); i++){
+				CharacterData data = getProject().getCharacterMatrix(i);
+				ObjectArray charImages = data.getWhichAssociatedObject(ref);
+				if (charImages !=null){
+					for (int ic = 0; ic<data.getNumChars(); ic++){
+						Object obj = charImages.getValue(ic);
+						if (obj!=null && obj instanceof AttachedNotesVector){
+							AttachedNotesVector notes = (AttachedNotesVector)obj;
+							for (int iim=0; iim<notes.getNumNotes(); iim++){
+								AttachedNote im = notes.getAttachedNote(iim);
+								s += "\tNOTE TAXA = " + StringUtil.tokenize(data.getTaxa().getName()) + " CHARACTERS = " + StringUtil.tokenize(data.getName()) + " CHARACTER = " + (ic+1) + " " + im.getNexusString() + ";" + StringUtil.lineEnding();
+								found = true;
+							}
+						}
+					}
+				}
+				Object2DArray cellImages = data.getWhichCellObjects(ref);
+				if (cellImages !=null){
+					for (int ic = 0; ic<data.getNumChars(); ic++){
+						for (int it = 0; it<data.getNumTaxa(); it++){
+							Object obj = cellImages.getValue(ic, it);
+							if (obj!=null && obj instanceof AttachedNotesVector){
+								AttachedNotesVector notes = (AttachedNotesVector)obj;
+								for (int iim=0; iim<notes.getNumNotes(); iim++){
+									AttachedNote im = notes.getAttachedNote(iim);
+									s += "\tNOTE TAXA = " + StringUtil.tokenize(data.getTaxa().getName()) + " CHARACTERS = " + StringUtil.tokenize(data.getName()) + " TAXON = " + (it+1)  + " CHARACTER = " + (ic+1) + " " + im.getNexusString() + ";" + StringUtil.lineEnding();
+									found = true;
+								}
+							}
+						}
+					}
+				}
+			}
+			if (found)
+				return s;
+			else
+				return null;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean readNexusCommand(MesquiteFile file, NexusBlock nBlock, String blockName, String command, MesquiteString comment){ 
+		if (blockName.equalsIgnoreCase("NOTES")) {
+			boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+			if (fuse)
+				return true;
+			MesquiteProject project = file.getProject();
+			MesquiteInteger startCharT = new MesquiteInteger(0);
+			String commandName = ParseUtil.getToken(command, startCharT);
+			Taxon taxon = null;
+			if (!commandName.equalsIgnoreCase("PICTURE"))
+				return false;
+			String token = ParseUtil.getToken(command, startCharT); 
+			String dummy;
+			String pathName = "";
+			String commentString = null;
+			int taxonNumber=MesquiteInteger.unassigned;
+			Taxa taxa = getProject().getTaxa(0);
+			int charNumber=MesquiteInteger.unassigned;
+			CharacterData data = null;
+			if (getProject().getNumberCharMatrices()>0)
+				data = getProject().getCharacterMatrix(0);
+			while (!StringUtil.blank(token) && !token.equals(";")) {
+				if (token.equalsIgnoreCase("TAXON")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+					taxonNumber = MesquiteInteger.fromString(whichItem);
+					if (MesquiteInteger.isCombinable(taxonNumber))
+						taxonNumber--; //to convert to internal
+				}
+				else if (token.equalsIgnoreCase("TAXA")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String taxaTitle = (ParseUtil.getToken(command, startCharT));
+					taxa = getProject().getTaxaLastFirst(taxaTitle);
+					if (taxa == null) {
+						taxa = getProject().getTaxa(0);
+					}
+				}
+				else if (token.equalsIgnoreCase("SOURCE")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String source = (ParseUtil.getToken(command, startCharT));
+					if (!("file".equalsIgnoreCase(source))) { //TODO:  what if it is "file"? why not deal with it?
+						file.setOpenAsUntitled("A picture source (\"" + source + "\", in NOTES block) was not recognized.  Mesquite may be unable to read and use the picture.");
+						if (taxon != null)
+							taxon.setIllustration(null, pathName);
+						return true; //returns true without saving object so that the note is deleted from the file
+					}
+				}
+				else if (token.equalsIgnoreCase("CHARACTER")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String whichItem = (ParseUtil.getToken(command, startCharT)); // name of taxon/etc
+					charNumber = MesquiteInteger.fromString(whichItem);
+					if (MesquiteInteger.isCombinable(charNumber))
+						charNumber--; //to convert to internal
+				}
+				else if (token.equalsIgnoreCase("CHARACTERS")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					String matrixName = (ParseUtil.getToken(command, startCharT));
+					//logln("   for taxa " + taxaTitle);
+					data = getProject().getCharacterMatrixByReference(file, matrixName);
+					if (data == null) {
+						data = getProject().getCharacterMatrix(0);
+					}
+				}
+				else if (token.equalsIgnoreCase("COMMENT")) {
+					dummy =ParseUtil.getToken(command, startCharT); // =
+					commentString = (ParseUtil.getToken(command, startCharT));
+				}
+				else if (token.equalsIgnoreCase("PICTURE")) {
+					if (taxa!=null){
+						dummy =ParseUtil.getToken(command, startCharT); // =
+						pathName = ParseUtil.getToken(command, startCharT);
+						if ((MesquiteInteger.isCombinable(taxonNumber) || MesquiteInteger.isCombinable(charNumber)) && !StringUtil.blank(pathName)) {
+							//figure out if this is for character, cell, or taxon
+							if (MesquiteInteger.isCombinable(charNumber) && charNumber>=0){ // character or cell
+								if (MesquiteInteger.isCombinable(taxonNumber) && taxonNumber>=0) { //cell
+									if (data == null)
+										return true; //returns true without saving object so that the note is deleted from the file
+									NameReference imageNameRef = NameReference.getNameReference("notes");
+						   	 		
+									AttachedNotesVector aim = (AttachedNotesVector)data.getCellObject(imageNameRef, charNumber, taxonNumber);
+									if (aim == null)
+										aim = new AttachedNotesVector(data);
+									AttachedNote hL = new AttachedNote();
+						   	 		aim.addNote(hL, false);
+						   	 		hL.setImagePath(pathName, MesquiteFile.composePath(getProject().getHomeDirectoryName(),  pathName), false);
+						   	 		hL.setComment(commentString, false);
+									data.setCellObject(imageNameRef, charNumber, taxonNumber, aim);
+									data.setCellObjectDisplay(charNumber, taxonNumber);
+								}
+								else { //whole character
+									NameReference imageNameRef = data.makeAssociatedObjects("notes");
+						   	 		
+									AttachedNotesVector aim =(AttachedNotesVector)data.getAssociatedObject(imageNameRef, charNumber);
+									if (aim == null)
+										aim = new AttachedNotesVector(data);
+									AttachedNote hL = new AttachedNote();
+						   	 		aim.addNote(hL, false);
+						   	 		hL.setImagePath(pathName, MesquiteFile.composePath(getProject().getHomeDirectoryName(),  pathName), false);
+						   	 		hL.setComment(commentString, false);
+									data.setAssociatedObject(imageNameRef, charNumber, aim);
+								}
+							}
+							else { //taxon
+									NameReference imageNameRef = taxa.makeAssociatedObjects("notes");
+						   	 		
+									AttachedNotesVector aim = (AttachedNotesVector)taxa.getAssociatedObject(imageNameRef, taxonNumber);
+									if (aim == null)
+										aim = new AttachedNotesVector(taxa);
+									AttachedNote hL = new AttachedNote();
+						   	 		aim.addNote(hL, false);
+						   	 		hL.setImagePath(pathName, MesquiteFile.composePath(getProject().getHomeDirectoryName(),  pathName), false);
+						   	 		hL.setComment(commentString, false);
+									taxa.setAssociatedObject(imageNameRef, taxonNumber, aim);
+								
+							}
+						}
+					}
+				}
+				token = ParseUtil.getToken(command, startCharT); 
+			}
+			return true;
+		
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new MPCT();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage pictures";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) pictures." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class MPCT  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return (blockName.equalsIgnoreCase("NOTES") && (commandName.equalsIgnoreCase("PICTURE")));
+	}
+}
+
+
diff --git a/Source/mesquite/ornamental/NodeLocsCircular/NodeLocsCircular.java b/Source/mesquite/ornamental/NodeLocsCircular/NodeLocsCircular.java
new file mode 100644
index 0000000..e71d035
--- /dev/null
+++ b/Source/mesquite/ornamental/NodeLocsCircular/NodeLocsCircular.java
@@ -0,0 +1,457 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.NodeLocsCircular;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodeLocsCircular extends NodeLocsCircle {
+	public TreeDrawing treeDrawing;
+	public Tree tree;
+	public TreeDisplay treeDisplay;
+	MesquiteBoolean showScale;
+	MesquiteBoolean showBranchLengths;
+	boolean resetShowBranchLengths = false;
+	int rootHeight=30;
+	Vector extras;
+	double angleBetweenTaxa;
+	double fractionCoverage = 0.96;
+	
+	double firsttx = 0.02;
+	int centerx, centery;
+	double circleSlice;
+	double radius;
+	Point[] location;
+	//DoublePt[] sLoc;
+	double lasttx;
+	Rectangle treeRectangle;
+	int emptyRootSlices;
+	int oldNumTaxa=0;
+	private MesquiteMenuItemSpec showScaleItem;
+	
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showBranchLengths = new MesquiteBoolean(false);
+		extras = new Vector();
+		showScale = new MesquiteBoolean(true);
+		addMenuItem("Fraction of Circle...", makeCommand("circleFraction", this));
+		addMenuItem("Start of Circle...", makeCommand("circleStart", this));
+		addCheckMenuItem(null, "Branches Proportional to Lengths", makeCommand("branchLengthsToggle", this), showBranchLengths);
+		if (showBranchLengths.getValue()) {
+			showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+			resetShowBranchLengths=true;
+		}
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	
+	public void endJob(){
+		if (extras!=null) {
+			for (int i=0; i<extras.size(); i++){
+				TreeDisplayExtra extra = (TreeDisplayExtra)extras.elementAt(i);
+				if (extra!=null){
+					TreeDisplay td = extra.getTreeDisplay();
+					extra.turnOff();
+					if (td!=null)
+						td.removeExtra(extra);
+				}
+			}
+			extras.removeAllElements();
+		}
+		super.endJob();
+	}
+	
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("branchLengthsToggle " + showBranchLengths.toOffOnString());
+		temp.addLine("toggleScale " + showScale.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not the branches are to be shown proportional to their lengths", "[on = proportional; off]", commandName, "branchLengthsToggle")) {
+			showBranchLengths.toggleValue(parser.getFirstToken(arguments));
+			if (showBranchLengths.getValue()) 
+				showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+			else
+				deleteMenuItem(showScaleItem);
+			resetContainingMenuBar();
+			resetShowBranchLengths=true;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to draw the scale for branch lengths", "[on or off]", commandName, "toggleScale")) {
+			showScale.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the fraction of the circle covered by the tree", "[number between 0 and 1]", commandName, "circleFraction")) {
+			double d = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(d))
+				d = MesquiteDouble.queryDouble(containerOfModule(), "Fraction of circle", "Enter a number between 0 and 1 to indicate the fraction of the circle covered by the tree", fractionCoverage);
+			if (MesquiteDouble.isCombinable(d))
+				fractionCoverage =d;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the position of the start of the circle (0 = bottom; 0.5 = top)", "[number between 0 and 1]", commandName, "circleStart")) {
+			double d = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteDouble.isCombinable(d))
+				d = MesquiteDouble.queryDouble(containerOfModule(), "Start position of circle", "Enter a number between 0 and 1 to indicate the start position of the circle", firsttx);
+			if (MesquiteDouble.isCombinable(d))
+				firsttx =d;
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getName() {
+		return "Node Locations (circle)";
+	}
+	
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the node locations for a tree drawn in circular fashion, with root at center." ;
+	}
+	
+	/*_________________________________________________*/
+	public boolean compatibleWithOrientation(int orientation) {
+		return orientation==TreeDisplay.CIRCULAR;
+	}
+	public void setDefaultOrientation(TreeDisplay treeDisplay) {
+		treeDisplay.setOrientation(TreeDisplay.CIRCULAR);
+	}
+	/*_________________________________________________*/
+	double scaling;
+	
+	private double getBranchLength (int N) {
+		if (tree.branchLengthUnassigned(N))
+			return 1;
+		else
+			return tree.getBranchLength(N);
+	}
+	/*{-----------------------------------------------------------------------------}*/
+	int numNodes;
+	private int findTaxa (int node){
+		if (tree.nodeIsInternal(node)){
+			int maxAbove = 0;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				int aboveThis = findTaxa(d);
+				if (aboveThis>maxAbove)
+					maxAbove = aboveThis;
+			}
+			return maxAbove+1;
+		}
+		else //  {terminal node; see if Daughter of N}
+			return 1;
+	}
+	private int mostNodesToTip (int node){  // returns number of nodes from the top of the tree}
+		numNodes = 0;
+		return findTaxa(node);
+	}
+//	{-----------------------------------------------------------------------------*/
+	private void nodePolarToLoc (double polarlength, double angle, Point loc){
+		loc.x = treeCenter.x + (int)Math.round(polarlength * Math.sin(angle));
+		loc.y = treeCenter.y - (int)Math.round(polarlength * Math.cos(angle));
+	}
+	/*{-----------------------------------------------------------------------------}
+	 private void nodePolarToSingleLoc (double polarlength, double angle, DoublePt loc){
+	 //{remember: sin = opp/hyp, cos = adj/hyp, tan = opp/adj}
+	  loc.x = treeCenter.x + polarlength * Math.sin(angle);
+	  loc.y = treeCenter.y - polarlength * Math.cos(angle);
+	  }
+	  /*----------------------------------------------------------------------------*/
+	private void nodeLocToPolar (Point loc, Point center, double targetAngle, PolarCoord polar){
+		polar.length = Math.sqrt((loc.x-center.x) *(loc.x-center.x) + (center.y-loc.y)*(center.y-loc.y));
+		polar.angle = Math.asin((loc.x-center.x)/polar.length);
+		if (targetAngle>Math.PI/2.0*3.0)
+			polar.angle = Math.PI*2.0+polar.angle;
+		else if (targetAngle>Math.PI/2.0)
+			polar.angle = Math.PI-polar.angle;
+		
+	}
+//	{-----------------------------------------------------------------------------}
+	private double nodeAngle (int left, int right){
+		double theAngle;
+		if (angle[left]<= angle[right])
+			theAngle = (angle[left] + angle[right]) / 2.0;
+		else {
+			theAngle = angle[left] + (2 * Math.PI - Math.abs(angle[left] - angle[right])) / 2.0;
+			if (theAngle > 2 * Math.PI)
+				theAngle = theAngle - 2 * Math.PI;
+		}
+		return theAngle;
+	}
+	boolean massageLoc = false;
+//	{-----------------------------------------------------------------------------}
+	PolarCoord polar = new PolarCoord();
+//	angle 0 = vertical up
+	private void calcterminalPosition (int node){
+		double firstangle;
+		massageLoc = false;
+		firstangle = Math.PI + angleBetweenTaxa/2; //TODO: {here need to use stored value}
+		
+			firstangle = angleBetweenTaxa;
+		angle[node] =firstangle + lasttx; // {angle in radians horizontal from vertical}
+		polarLength[node] =radius;
+		
+		nodePolarToLoc(polarLength[node], angle[node], location[node]);
+		if (massageLoc){
+			nodeLocToPolar(location[node], treeCenter, angle[node], polar);
+			polarLength[node] = polar.length;
+			angle[node] = polar.angle;
+			nodePolarToLoc(polarLength[node], angle[node], location[node]);  //convert back and forth to deal with roundoff
+		}
+		
+		int degrees = (int)(angle[node]/Math.PI/2*360) % 360;
+		if (degrees < 45)
+			treeDrawing.labelOrientation[node] = 270;
+		else if (degrees < 135)
+			treeDrawing.labelOrientation[node] = 0;
+		else if (degrees < 225)
+			treeDrawing.labelOrientation[node] = 90;
+		else if (degrees < 315)
+			treeDrawing.labelOrientation[node] = 180;
+		else 
+			treeDrawing.labelOrientation[node] = 270;
+		
+		//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+		lasttx = (angleBetweenTaxa + lasttx);
+		
+	}
+//	{-----------------------------------------------------------------------------}
+	
+	private void termTaxaRec (int node){		//{tree traversal to find locations}
+		if (tree.nodeIsTerminal(node)) 
+			calcterminalPosition(node);
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				termTaxaRec(d);
+		}
+	}
+	
+	private void terminalTaxaLocs (int node){
+		lasttx = firsttx*Math.PI * 2.0;
+		termTaxaRec(node);
+	}
+//	{-----------------------------------------------------------------------------}
+//	{-----------------------------------------------------------------------------}
+	private void calcNodeLocs (int node){
+		if (tree.nodeIsInternal(node)){
+			double min = MesquiteDouble.unassigned;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)){
+				calcNodeLocs(d);
+				min = MesquiteDouble.minimum(min, polarLength[d]);
+			}
+			int left = tree.firstDaughterOfNode(node);
+			int right = tree.lastDaughterOfNode(node);
+			angle[node] = nodeAngle(left, right);
+			polarLength[node] = min - circleSlice;
+			if (polarLength[node] < 0) 
+				polarLength[node] = 0;
+			//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+			nodePolarToLoc(polarLength[node], angle[node], location[node]);
+			if (massageLoc){
+				nodeLocToPolar(location[node], treeCenter, angle[node], polar);
+				polarLength[node] = polar.length;
+				angle[node] = polar.angle;
+				nodePolarToLoc(polarLength[node], angle[node], location[node]);  //convert back and forth for 
+			}
+		}
+	}
+	
+//	{-----------------------------------------------------------------------------}
+	private void adjustNodeLocsWithLengths (int node, double polarHeightToAncestor, int root){
+		if (node==root)
+			polarLength[node] = rootHeight;
+		else {
+			polarLength[node] = polarHeightToAncestor + getBranchLength(node) * scaling;
+		}
+		if (polarLength[node] < 0)
+			polarLength[node] = 0;
+		//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+		nodePolarToLoc(polarLength[node], angle[node], location[node]);
+		if (massageLoc){
+			nodeLocToPolar(location[node], treeCenter, angle[node],  polar);
+			polarLength[node] = polar.length;
+			angle[node] = polar.angle;
+			nodePolarToLoc(polarLength[node], angle[node], location[node]);  //convert back and forth for
+		}
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				adjustNodeLocsWithLengths(d, polarLength[node], root);
+		}
+	}
+	
+//	{-----------------------------------------------------------------------------}
+	private void adjustForLengths (int root){
+		int tpa;
+		tpa=(int)tree.tallestPathAboveNode(root, 1.0);
+		if (tpa!=0)
+			scaling=(radius-rootHeight)/tpa;
+		else // all assigned 0's give arbitrary scaling (not great solution!)
+			scaling=20;
+		adjustNodeLocsWithLengths(root, 0, root);
+	}
+	/*_________________________________________________*/
+	public void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect) { //Graphics g removed as parameter May 02
+		if (MesquiteTree.OK(tree)) {
+			this.tree = tree;
+			this.treeDisplay = treeDisplay;
+			if (treeDisplay.getExtras() !=null) {
+				if (treeDisplay.getExtras().myElements(this)==null) {  //todo: need to do one for each treeDisplay!
+					NodeLocsCircularExtra extra = new NodeLocsCircularExtra(this, treeDisplay);
+					treeDisplay.addExtra(extra); 
+					extras.addElement(extra);
+				}
+			}
+			int subRoot = tree.motherOfNode(drawnRoot);
+			treeCenter = new Point();
+			if (!compatibleWithOrientation(treeDisplay.getOrientation()))
+				setDefaultOrientation(treeDisplay);
+			int numNodes =tree.getNumNodeSpaces();
+			if (oldNumTaxa != tree.getNumTaxa() || location == null || location.length != numNodes) {
+				location = new Point[numNodes];
+				//sLoc = new DoublePt[numNodes];
+				for (int i=0; i<numNodes; i++) {
+					//sLoc[i]= new DoublePt();
+					location[i] = new Point(0,0);
+				}
+				angle = new double[numNodes];
+				polarLength  = new double[numNodes];
+				oldNumTaxa=tree.getNumTaxa();
+			}
+			else {
+				for (int i=0; i<location.length && location[i]!=null; i++) {
+					if (location[i]!=null){
+						location[i].y=0;
+						location[i].x=0;
+					}
+					polarLength[i] = 0;
+					angle[i] = 0;
+				}
+			}
+			if (resetShowBranchLengths)
+				treeDisplay.showBranchLengths=showBranchLengths.getValue();
+			else {
+				if (treeDisplay.showBranchLengths != showBranchLengths.getValue()) {
+					showBranchLengths.setValue(treeDisplay.showBranchLengths);
+					if (showBranchLengths.getValue()) 
+						showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+					else
+						deleteMenuItem(showScaleItem);
+					resetContainingMenuBar();
+				}
+			}
+			this.treeDrawing = treeDisplay.getTreeDrawing();
+			
+			emptyRootSlices=1;
+			angleBetweenTaxa=(2 * Math.PI*fractionCoverage) / tree.numberOfTerminalsInClade(drawnRoot);
+			treeRectangle = rect;
+			if (treeRectangle.width<treeRectangle.height)
+				radius=(treeRectangle.width * 3 )/ 8;
+			else
+				radius=(treeRectangle.height) * 3 / 8;
+			circleSlice = radius / (mostNodesToTip(drawnRoot) + emptyRootSlices);  //{v4: have it based upon an ellipse}
+			
+			
+			treeCenter.x = /*treeRectangle.x +*/ treeRectangle.width / 2;
+			treeCenter.y = /*treeRectangle.y +*/ treeRectangle.height / 2;
+//			centerx = treeCenter.x;
+//			centery = treeCenter.y;
+			location[drawnRoot].y=treeCenter.y;
+			location[drawnRoot].x=treeCenter.x;
+			location[subRoot].y=treeCenter.y;
+			location[subRoot].x=treeCenter.x;
+			polarLength[subRoot] = 0;
+			angle[subRoot] = 0;
+			terminalTaxaLocs(drawnRoot);
+			calcNodeLocs (drawnRoot);
+			if (showBranchLengths.getValue()) {
+				adjustForLengths(drawnRoot);
+				//if (showScale.getValue())
+				//	drawGrid(g, tree.tallestPathAboveNode(drawnRoot, 1.0), scaling, treeCenter);
+			}
+			for (int i=0; i<numNodes && i<treeDrawing.y.length; i++) {
+				treeDrawing.y[i] = location[i].y;
+				treeDrawing.x[i] = location[i].x;
+				
+			}
+		}
+	}
+	
+	public void drawGrid (Graphics g, double totalHeight, double scaling,  Point treeCenter) {
+		if (g == null)
+			return;
+		Color c=g.getColor();
+		double log10 = Math.log(10.0);
+		double hundredthHeight = Math.exp(log10* ((int) (Math.log(totalHeight)/log10)-1));
+		int countTenths = 0;
+		double thisHeight = totalHeight + hundredthHeight;
+		while ( thisHeight>=0) {
+			if (countTenths % 10 == 0)
+				g.setColor(Color.blue);
+			else
+				g.setColor(Color.cyan);
+			g.setColor(Color.red);
+			thisHeight -= hundredthHeight;
+			g.drawOval(treeCenter.x- (int)(thisHeight*scaling) - rootHeight,treeCenter.y- (int)(thisHeight*scaling) - rootHeight, 2*((int)(thisHeight*scaling) + rootHeight),  2*((int)(thisHeight*scaling) + rootHeight));
+			//if (countTenths % 10 == 0)
+			//	g.drawString(MesquiteDouble.toString(totalScaleHeight - thisHeight), rightEdge + buffer, (int)(base- (thisHeight*scaling)));
+			countTenths ++;
+		}
+		
+		if (c!=null) g.setColor(c);
+	}
+}
+
+class PolarCoord {
+	public double length, angle;
+}
+
+
+class NodeLocsCircularExtra extends TreeDisplayBkgdExtra {
+	NodeLocsCircular locsModule;
+	
+	public NodeLocsCircularExtra (NodeLocsCircular ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		locsModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+	public   String writeOnTree(Tree tree, int drawnRoot) {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (locsModule.showScale.getValue() && locsModule.showBranchLengths.getValue())
+			locsModule.drawGrid(g, tree.tallestPathAboveNode(drawnRoot, 1.0), locsModule.scaling, locsModule.treeCenter);
+		//g.setColor(Color.green);
+		//g.fillOval(locsModule.centerx-8, locsModule.centery-8, 16, 16);
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	
+}
+
+
diff --git a/Source/mesquite/ornamental/NodeLocsOval/NodeLocsOval.java b/Source/mesquite/ornamental/NodeLocsOval/NodeLocsOval.java
new file mode 100644
index 0000000..7ebd5f7
--- /dev/null
+++ b/Source/mesquite/ornamental/NodeLocsOval/NodeLocsOval.java
@@ -0,0 +1,430 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.NodeLocsOval;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodeLocsOval extends NodeLocsFree {
+	public TreeDrawing treeDrawing;
+	public Tree tree;
+	public TreeDisplay treeDisplay;
+	MesquiteBoolean showScale;
+	MesquiteBoolean showBranchLengths;
+	boolean resetShowBranchLengths = false;
+	int rootHeight=30;
+	Vector extras;
+	double angleBetweenTaxa;
+	double firsttx;
+	double circleSlice;
+	int radius;
+	int centralRoot;
+	Point[] location;
+	//DoublePt[] sLoc;
+	double lasttx;
+	Rectangle treeRectangle;
+	int emptyRootSlices;
+	int oldNumTaxa=0;
+	private MesquiteMenuItemSpec showScaleItem;
+	/**angle of each branch from 0 degrees (defined as direction of standard positive "x" axis).*/
+	public double [] angle;
+	/**length of each branch measured radially from center.*/
+	public double [] polarLength;
+	/**center of circle about which tree is drawn.*/
+	public Point treeCenter;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showBranchLengths = new MesquiteBoolean(false);
+		showScale = new MesquiteBoolean(true);
+		extras = new Vector();
+		addCheckMenuItem(null, "Branches Proportional to Lengths", makeCommand("branchLengthsToggle", this), showBranchLengths);
+		if (showBranchLengths.getValue()) {
+			showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+			resetShowBranchLengths=true;
+		}
+  		return true;
+  	 }
+  	 
+   
+  	/*.................................................................................................................*/
+	 
+   	public void endJob(){
+  	 	if (extras!=null) {
+	   		for (int i=0; i<extras.size(); i++){
+	   			TreeDisplayExtra extra = (TreeDisplayExtra)extras.elementAt(i);
+		   		if (extra!=null){
+		   			TreeDisplay td = extra.getTreeDisplay();
+		   			extra.turnOff();
+		   			if (td!=null)
+		   				td.removeExtra(extra);
+		   		}
+	   		}
+	   		extras.removeAllElements();
+  	 	}
+   		super.endJob();
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("branchLengthsToggle " + showBranchLengths.toOffOnString());
+  	 	temp.addLine("toggleScale " + showScale.toOffOnString());
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets whether or not the branches are to be shown proportional to their lengths", "[on = proportional; off]", commandName, "branchLengthsToggle")) {
+    	 		showBranchLengths.toggleValue(parser.getFirstToken(arguments));
+			if (showBranchLengths.getValue()) 
+				showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+			else
+				deleteMenuItem(showScaleItem);
+			resetContainingMenuBar();
+			resetShowBranchLengths=true;
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not to draw the scale for branch lengths", "[on or off]", commandName, "toggleScale")) {
+    	 		showScale.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+    	 public String getName() {
+		return "Node Locations (oval)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the node locations for a tree drawn in oval fashion, with root at center." ;
+   	 }
+  
+	/*_________________________________________________*/
+   	public boolean compatibleWithOrientation(int orientation) {
+   		return orientation==TreeDisplay.CIRCULAR;
+   	}
+   	public void setDefaultOrientation(TreeDisplay treeDisplay) {
+   		treeDisplay.setOrientation(TreeDisplay.CIRCULAR);
+   	}
+	/*_________________________________________________*/
+	double scaling;
+	
+	private double getBranchLength (int N) {
+		if (tree.branchLengthUnassigned(N))
+			return 1;
+		else
+			return tree.getBranchLength(N);
+	}
+/*{-----------------------------------------------------------------------------}*/
+	int numNodes;
+	private int findTaxa (int anc, int node){
+		if (tree.nodeIsInternal(node)){
+				int maxAbove = 0;
+				for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d); d = tree.nextSisterOfNodeUR(anc, node, d)) {
+					int aboveThis = findTaxa(node, d);
+					if (aboveThis>maxAbove)
+						maxAbove = aboveThis;
+				}
+				return maxAbove+1;
+		}
+		else //  {terminal node; see if Daughter of N}
+			return 1;
+	}
+	private int mostNodesToTip (int anc, int node){  // returns number of nodes from the top of the tree}
+		numNodes = 0;
+		return findTaxa(anc, node);
+	}
+//{-----------------------------------------------------------------------------*/
+	private void nodePolarToLoc (double polarlength, double angle, Point loc){
+		loc.x = treeCenter.x + (int)Math.round(polarlength * Math.sin(angle));
+		loc.y = treeCenter.y - (int)Math.round(polarlength * Math.cos(angle));
+	}
+//{-----------------------------------------------------------------------------}
+	private void nodePolarToSingleLoc (double polarlength, double angle, DoublePt loc){
+			//{remember: sin = opp/hyp, cos = adj/hyp, tan = opp/adj}
+		loc.x = treeCenter.x + polarlength * Math.sin(angle);
+		loc.y = treeCenter.y - polarlength * Math.cos(angle);
+	}
+//{-----------------------------------------------------------------------------}
+	private double nodeAngle (int left, int right){
+		double theAngle;
+		if (angle[left]<= angle[right])
+			theAngle = (angle[left] + angle[right]) / 2.0;
+		else {
+			theAngle = angle[left] + (2 * Math.PI - Math.abs(angle[left] - angle[right])) / 2.0;
+			if (theAngle > 2 * Math.PI)
+				theAngle = theAngle - 2 * Math.PI;
+		}
+		return theAngle;
+	}
+//{-----------------------------------------------------------------------------}
+//angle 0 = vertical up
+	private void calcterminalPosition (int node){
+		double firstangle;
+		firstangle = Math.PI + angleBetweenTaxa/2; //TODO: {here need to use stored value}
+		angle[node] =firstangle + lasttx; // {angle in radians horizontal from vertical}
+		polarLength[node] =radius;
+		nodePolarToLoc(polarLength[node], angle[node], location[node]);
+		int degrees = (int)(angle[node]/Math.PI/2*360) % 360;
+		if (degrees < 45)
+			treeDrawing.labelOrientation[node] = 270;
+		else if (degrees < 135)
+			treeDrawing.labelOrientation[node] = 0;
+		else if (degrees < 225)
+			treeDrawing.labelOrientation[node] = 90;
+		else if (degrees < 315)
+			treeDrawing.labelOrientation[node] = 180;
+		else 
+			treeDrawing.labelOrientation[node] = 270;
+		
+		//System.out.println(" loctn x " + location[node].x);
+		//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+		lasttx = (angleBetweenTaxa + lasttx);
+		
+	}
+//{-----------------------------------------------------------------------------}
+
+	private void termTaxaRec (int anc, int node){		//{tree traversal to find locations}
+		if (tree.nodeIsTerminal(node)) 
+			calcterminalPosition(node);
+		else {
+			for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d); d = tree.nextSisterOfNodeUR(anc, node, d))
+				termTaxaRec(node, d);
+		}
+	}
+	
+	private void terminalTaxaLocs (int anc, int node){
+		lasttx = 0;
+		termTaxaRec(anc, node);
+	}
+//{-----------------------------------------------------------------------------}
+//{-----------------------------------------------------------------------------}
+	private void calcNodeLocs (int anc, int node){
+		if (tree.nodeIsInternal(node)){
+			double min = MesquiteDouble.unassigned;
+			for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d); d = tree.nextSisterOfNodeUR(anc, node, d)) {
+				calcNodeLocs(node, d);
+				min = MesquiteDouble.minimum(min, polarLength[d]);
+			}
+			int left = tree.firstDaughterOfNodeUR(anc, node);
+			int right = tree.lastDaughterOfNodeUR(anc, node);
+			angle[node] = nodeAngle(left, right);
+			polarLength[node] = min - circleSlice;
+			if (polarLength[node] < 0) 
+				polarLength[node] = 0;
+			//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+			nodePolarToLoc(polarLength[node], angle[node], location[node]);
+		}
+	}
+	
+//{-----------------------------------------------------------------------------}
+	private void adjustNodeLocsWithLengths (int anc, int node, double polarHeightToAncestor, int root){
+		if (node==root)
+			polarLength[node] = rootHeight;
+		else {
+			polarLength[node] = polarHeightToAncestor + getBranchLength(node) * scaling;
+		}
+		if (polarLength[node] < 0)
+			polarLength[node] = 0;
+		//nodePolarToSingleLoc(polarLength[node], angle[node], sLoc[node]);
+		nodePolarToLoc(polarLength[node], angle[node], location[node]);
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d); d = tree.nextSisterOfNodeUR(anc, node, d))
+				adjustNodeLocsWithLengths(node, d, polarLength[node], root);
+		}
+	}
+	
+//{-----------------------------------------------------------------------------}
+	private void adjustForLengths (int root){
+		int tpa;
+		tpa=(int)tree.tallestPathAboveNodeUR(root, root, 1.0);
+		if (tpa!=0)
+			scaling=(radius-rootHeight)/tpa;
+		else // all assigned 0's give arbitrary scaling (not great solution!)
+			scaling=20;
+		adjustNodeLocsWithLengths(root, root, 0, root);
+	}
+//{-----------------------------------------------------------------------------}
+	private void squish (int anc, int node, int centerX, int centerY, int root, double xExpansion, double yExpansion){
+		int nodeX = treeDrawing.x[node];
+		int nodeY =treeDrawing.y[node];
+		
+		treeDrawing.x[node] = centerX + (int)(xExpansion*(nodeX-centerX));
+		treeDrawing.y[node] = centerY + (int)(yExpansion*(nodeY-centerY));
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d) && d!=root; d = tree.nextSisterOfNodeUR(anc, node, d)) {
+				squish(node, d, centerX, centerY, root, xExpansion, yExpansion);
+			}
+		}
+	}
+//{-----------------------------------------------------------------------------}
+	private int findSelected (int anc, int node, int root){
+		if (tree.getSelected(node))
+			return node;
+		if (tree.nodeIsInternal(node)) {
+			for (int d = tree.firstDaughterOfNodeUR(anc, node); tree.nodeExists(d) && d!=root; d = tree.nextSisterOfNodeUR(anc, node, d)) {
+				int s = findSelected(node, d, root);
+				if (s>0)
+					return s;
+			}
+		}
+		return 0;
+	}
+	/*_________________________________________________*/
+	public void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect) { //Graphics g removed as parameter May 02
+		if (MesquiteTree.OK(tree)) {
+			this.tree = tree;
+			this.treeDisplay = treeDisplay;
+			if (treeDisplay.getExtras() !=null) {
+				if (treeDisplay.getExtras().myElements(this)==null) {  //todo: need to do one for each treeDisplay!
+					NodeLocsOvalExtra extra = new NodeLocsOvalExtra(this, treeDisplay);
+					treeDisplay.addExtra(extra); 
+					extras.addElement(extra);
+				}
+			}
+			
+			centralRoot=0;
+			if (tree.anySelectedInClade(drawnRoot))
+				centralRoot = findSelected(drawnRoot, drawnRoot, drawnRoot);
+			if (centralRoot == 0) {
+				 centralRoot = drawnRoot;
+			}
+			//int subRoot = tree.motherOfNode(drawnRoot);
+			treeCenter = new Point();
+			if (!compatibleWithOrientation(treeDisplay.getOrientation()))
+				setDefaultOrientation(treeDisplay);
+			int numNodes =tree.getNumNodeSpaces();
+			if (oldNumTaxa != tree.getNumTaxa()) {
+				location = new Point[numNodes];
+				//sLoc = new DoublePt[numNodes];
+				for (int i=0; i<numNodes; i++) {
+					//sLoc[i]= new DoublePt();
+					location[i] = new Point(0,0);
+				}
+				angle = new double[numNodes];
+				polarLength  = new double[numNodes];
+				oldNumTaxa=tree.getNumTaxa();
+			}
+			if (resetShowBranchLengths)
+				treeDisplay.showBranchLengths=showBranchLengths.getValue();
+			else {
+				if (treeDisplay.showBranchLengths != showBranchLengths.getValue()) {
+					showBranchLengths.setValue(treeDisplay.showBranchLengths);
+					if (showBranchLengths.getValue()) 
+						showScaleItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+					else
+						deleteMenuItem(showScaleItem);
+					resetContainingMenuBar();
+				}
+			}
+			this.treeDrawing = treeDisplay.getTreeDrawing();
+
+			emptyRootSlices=1;
+			angleBetweenTaxa=2 * Math.PI / tree.numberOfTerminalsInClade(drawnRoot); //TODO: should deal with other centerings
+			treeRectangle = rect;
+			if (treeRectangle.width<treeRectangle.height)
+				radius=(treeRectangle.width * 3 )/ 8;
+			else
+				radius=(treeRectangle.height) * 3 / 8;
+			circleSlice = radius / (mostNodesToTip(centralRoot, centralRoot) + emptyRootSlices);  //{v4: have it based upon an ellipse}
+			treeCenter.x = /*treeRectangle.x +*/ treeRectangle.width / 2;
+			treeCenter.y = /*treeRectangle.y +*/ treeRectangle.height / 2;
+
+			location[centralRoot].y=treeCenter.y;
+			location[centralRoot].x=treeCenter.x;
+			//location[subRoot].y=treeCenter.y;
+			//location[subRoot].x=treeCenter.x;
+			terminalTaxaLocs(centralRoot, centralRoot);
+			calcNodeLocs (centralRoot, centralRoot);
+			if (showBranchLengths.getValue()) {
+				adjustForLengths(centralRoot);
+				//if (showScale.getValue())
+				//	drawGrid(g, tree.tallestPathAboveNodeUR(centralRoot, centralRoot, 1.0), scaling, treeCenter);
+			}
+			for (int i=0; i<numNodes && i<treeDrawing.y.length; i++) {
+				treeDrawing.y[i] = location[i].y;
+				treeDrawing.x[i] = location[i].x;
+				
+			}
+			squish(centralRoot, centralRoot, treeCenter.x, treeCenter.y, centralRoot, treeRectangle.width/3.0/radius, treeRectangle.height/3.0/radius);
+			if (tree.numberOfDaughtersOfNode(centralRoot) == 2 && !showBranchLengths.getValue()) {
+				int left = tree.firstDaughterOfNode(centralRoot);
+				int right = tree.lastDaughterOfNode(centralRoot);
+				treeDrawing.y[centralRoot] = (location[left].y + location[right].y)/2;
+				treeDrawing.x[centralRoot] =  (location[left].x + location[right].x)/2;
+			}
+		}
+	}
+	
+	public void drawGrid (Graphics g, double totalHeight, double scaling,  Point treeCenter) {
+		if (g == null)
+			return;
+		double xExpansion = treeRectangle.width/3.0/radius;
+		double yExpansion = treeRectangle.height/3.0/radius;
+		Color c=g.getColor();
+		double log10 = Math.log(10.0);
+		double hundredthHeight = Math.exp(log10* ((int) (Math.log(totalHeight)/log10)-1));
+		int countTenths = 0;
+		double thisHeight = totalHeight + hundredthHeight;
+		while ( thisHeight>=0) {
+			if (countTenths % 10 == 0)
+				g.setColor(Color.blue);
+			else
+				g.setColor(Color.cyan);
+			thisHeight -= hundredthHeight;
+			g.drawOval(treeCenter.x- (int)(xExpansion*((thisHeight*scaling))) - rootHeight,treeCenter.y- (int)(yExpansion*((thisHeight*scaling))) - rootHeight, (int)(xExpansion*2*((thisHeight*scaling) + rootHeight)),  (int)(yExpansion*2*((thisHeight*scaling) + rootHeight)));
+			//if (countTenths % 10 == 0)
+			//	g.drawString(MesquiteDouble.toString(totalScaleHeight - thisHeight), rightEdge + buffer, (int)(base- (thisHeight*scaling)));
+			countTenths ++;
+		}
+		
+		if (c!=null) g.setColor(c);
+	}
+}
+
+class DoublePt {
+	public double x, y;
+}
+class NodeLocsOvalExtra extends TreeDisplayBkgdExtra {
+	NodeLocsOval locsModule;
+
+	public NodeLocsOvalExtra (NodeLocsOval ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		locsModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+	public   String writeOnTree(Tree tree, int drawnRoot) {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (locsModule.showScale.getValue() && locsModule.showBranchLengths.getValue())
+			locsModule.drawGrid(g, tree.tallestPathAboveNodeUR(locsModule.centralRoot, locsModule.centralRoot, 1.0), locsModule.scaling, locsModule.treeCenter);
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	
+}
+
+
diff --git a/Source/mesquite/ornamental/NodeNumbers/NodeNumbers.java b/Source/mesquite/ornamental/NodeNumbers/NodeNumbers.java
new file mode 100644
index 0000000..d5ea5d9
--- /dev/null
+++ b/Source/mesquite/ornamental/NodeNumbers/NodeNumbers.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.NodeNumbers;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodeNumbers extends TreeDisplayAssistantD {
+	public MesquiteBoolean terminalShow;
+	SpotsDrawing spots;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		addMenuItem("Remove Node Numbers", makeCommand("offNumbers", this));
+		terminalShow = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show terminal numbers", MesquiteModule.makeCommand("showTerminals",  this), terminalShow);
+		
+		return true;
+	}
+ 	public boolean getUserChooseable(){
+ 		return false;  //this module is treated as defunct, now that the tree draw coordiantor does it directly, but is retained for compatibility with old scripts
+ 	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		spots = new SpotsDrawing(this, treeDisplay, 0); //TODO: should remember all of these
+		return spots;
+	}
+  	 
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+		temp.addLine("showTerminals " + terminalShow.toOffOnString()); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Turns off node numbers", null, commandName, "offNumbers")) {
+			iQuit();
+			resetContainingMenuBar();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether terminal nodes are numbered", "[on or off]", commandName, "showTerminals")) {
+    	 		terminalShow.toggleValue(parser.getFirstToken(arguments));
+    	 		if (spots!=null)
+    	 			spots.getTreeDisplay().pleaseUpdate(false);
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Show Node Numbers";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Shows the node numbers on a tree." ;
+   	 }
+   	 public void endJob(){
+	 	if (spots !=null)
+	 		spots.turnOff(); //should do all
+   	 	super.endJob();
+   	 }
+}
+
+/* ======================================================================== */
+class SpotsDrawing extends TreeDisplayDrawnExtra {
+	public int oldNumTaxa;
+	public int spotsize = 18;
+	public NodeNumbers nnModule;
+	public SpotsDrawing (NodeNumbers ownerModule, TreeDisplay treeDisplay, int numTaxa) {
+		super(ownerModule, treeDisplay);
+		nnModule = ownerModule;
+		oldNumTaxa = numTaxa;
+	}
+	/*_________________________________________________*/
+	private   void drawSpot(TreeDisplay treeDisplay, Tree tree, Graphics g, int N) {
+		if (tree.nodeExists(N)) {
+			if (tree.nodeIsInternal(N) || nnModule.terminalShow.getValue()){
+				int i=0;
+				int j=2;
+				String s = Integer.toString(N);
+				FontMetrics fm = g.getFontMetrics(g.getFont());
+				int width = fm.stringWidth(s) + 6;
+				int height = fm.getAscent()+fm.getDescent() + 6;
+				if (spotsize>width)
+					width = spotsize;
+				if (spotsize>height)
+					height = spotsize;
+		        	g.setColor(Color.yellow);
+				g.fillOval(treeDisplay.getTreeDrawing().x[N] +i - width/2 , treeDisplay.getTreeDrawing().y[N] +i - height/2, width-i-i, height-i-i);
+		        	g.setColor(Color.black);
+		        	
+				g.drawOval(treeDisplay.getTreeDrawing().x[N] +i - width/2 , treeDisplay.getTreeDrawing().y[N] +i - height/2, width-i-i, height-i-i);
+		        	
+				g.drawString(Integer.toString(N), treeDisplay.getTreeDrawing().x[N]+2- width/2, treeDisplay.getTreeDrawing().y[N]-4+ height/2);
+			}
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawSpot(treeDisplay, tree, g, d);
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawSpots(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Graphics g) {
+	        if (MesquiteTree.OK(tree)) {
+	        	g.setColor(Color.red);
+	        	//if (oldNumTaxa!= tree.getNumTaxa())
+	        	//	adjustNumTaxa(tree.getNumTaxa());
+	       	 	drawSpot(treeDisplay, tree, g, drawnRoot);  
+	       	 }
+	   }
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawSpots(treeDisplay, tree, drawnRoot, g);
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	public   void setTree(Tree tree) {
+	}
+}
+	
+
+
diff --git a/Source/mesquite/ornamental/NodePositionAdjust/32adjustPosition.gif b/Source/mesquite/ornamental/NodePositionAdjust/32adjustPosition.gif
new file mode 100644
index 0000000..69bcdfd
Binary files /dev/null and b/Source/mesquite/ornamental/NodePositionAdjust/32adjustPosition.gif differ
diff --git a/Source/mesquite/ornamental/NodePositionAdjust/64adjustPosition.gif b/Source/mesquite/ornamental/NodePositionAdjust/64adjustPosition.gif
new file mode 100644
index 0000000..ec82f16
Binary files /dev/null and b/Source/mesquite/ornamental/NodePositionAdjust/64adjustPosition.gif differ
diff --git a/Source/mesquite/ornamental/NodePositionAdjust/NodePositionAdjust.java b/Source/mesquite/ornamental/NodePositionAdjust/NodePositionAdjust.java
new file mode 100644
index 0000000..a7bf163
--- /dev/null
+++ b/Source/mesquite/ornamental/NodePositionAdjust/NodePositionAdjust.java
@@ -0,0 +1,306 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.NodePositionAdjust;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodePositionAdjust extends TreeDisplayAssistantI {
+	public Vector extras;
+	public String getFunctionIconPath(){
+		return getPath() + "adjustPosition.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		PAdjustToolExtra newPj = new PAdjustToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Node Position Adjust";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool to adjust the depth of a node in the tree";
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+}
+
+/* ======================================================================== */
+class PAdjustToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool adjustTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	NodePositionAdjust selectModule;
+	Tree tree;
+	int originalX, originalY, lastX, lastY;
+	double lastBL;	
+	boolean lineOn = true;
+	boolean editorOn = false;
+	int editorNode = -1;
+	boolean dragMode = true; //default mode - if true,then drags branch to extend; needs modifier keys for editor; if false, opposite
+	int ovalRadius = 8;
+	double upperLimit = 0.0;
+	double lowerLimit = 0.0;
+
+	public PAdjustToolExtra (NodePositionAdjust ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		selectModule = ownerModule;
+		adjustTool = new TreeTool(this,  "posadjustor", ownerModule.getPath(),"adjustPosition.gif", 7,7,"Adjust node position", "This tool adjusts branch lengths in such a way as to keep the relative positions of nodes constant, except for the node moved.");
+		adjustTool.setTouchedCommand(MesquiteModule.makeCommand("touchedPositionAdjust",  this));
+		adjustTool.setDroppedCommand(MesquiteModule.makeCommand("droppedPositionAdjust",  this));
+		adjustTool.setDraggedCommand(MesquiteModule.makeCommand("draggedPositionAdjust",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(adjustTool);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		this.tree = tree;
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+	}
+
+	public void drawThickLine(Graphics g, int fromX, int fromY, int toX, int toY){
+		g.drawLine(fromX, fromY, toX, toY);
+		g.drawLine(fromX+1, fromY, toX+1, toY);
+		g.drawLine(fromX+2, fromY, toX+2, toY);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		Tree trt = treeDisplay.getTree();
+		MesquiteTree t = null;
+		if (trt instanceof MesquiteTree)
+			t = (MesquiteTree)trt;
+		if (checker.compare(this.getClass(), "Adjust tool has touched branch", "[branch number][x coordinate touched][y coordinate touched][modifiers]", commandName, "touchedPositionAdjust")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+
+
+			Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+			originalX = newOnLine.x;
+			originalY = newOnLine.y;
+			//lastX= newOnLine.x;
+			//lastY = newOnLine.y;
+			Graphics g = null;
+			if (GraphicsUtil.useXORMode(null, false)){
+				g = treeDisplay.getGraphics();
+				g.setXORMode(Color.white);
+				g.setColor(Color.red);
+			}
+			//double bX = treeDisplay.getTreeDrawing().lineBaseX[node];
+			//double bY = treeDisplay.getTreeDrawing().lineBaseY[node];
+			//Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
+			lastBL = tree.getBranchLength(node);
+			double shortestAbove = MesquiteDouble.unassigned;
+			for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter))
+				shortestAbove = MesquiteDouble.minimum(shortestAbove, tree.getBranchLength(daughter));
+			if (shortestAbove == MesquiteDouble.unassigned)
+				upperLimit = MesquiteDouble.infinite;
+			else if (MesquiteDouble.isCombinable(lastBL))
+				upperLimit = shortestAbove + lastBL;
+			else
+				upperLimit = shortestAbove + 1.0;
+			int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
+			int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
+			lastX = treeDisplay.getTreeDrawing().lineTipX[node];
+			lastY = treeDisplay.getTreeDrawing().lineTipY[node];
+			if (GraphicsUtil.useXORMode(null, false)){
+				drawThickLine(g,ibX, ibY, lastX, lastY);
+				for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter))
+					drawThickLine(g,treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], lastX, lastY);
+				g.fillOval(lastX-ovalRadius, lastY-ovalRadius, ovalRadius+ovalRadius, ovalRadius+ovalRadius);
+				try {
+					g.drawString(MesquiteDouble.toString(lastBL), lastX+10, lastY);
+				}
+				catch(InternalError e){  //workaround for bug on windows java 1.7.
+				}
+				catch(Throwable e){
+				}
+				lineOn=true;
+				g.dispose();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Adjust tool has been dropped", "[branch number][x coordinate dropped][y coordinate dropped]", commandName, "droppedPositionAdjust")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+				double bX = treeDisplay.getTreeDrawing().lineBaseX[node];
+				double bY = treeDisplay.getTreeDrawing().lineBaseY[node];
+				double tX = treeDisplay.getTreeDrawing().lineTipX[node];
+				double tY = treeDisplay.getTreeDrawing().lineTipY[node];
+				double lengthLine =  Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
+				double bL;
+				if (lengthLine!=0) {
+					double extension =  Math.sqrt((newOnLine.y-bY)*(newOnLine.y-bY) + (newOnLine.x-bX)*(newOnLine.x-bX))/lengthLine;
+					if (t.getBranchLength(node)==0 || t.branchLengthUnassigned(node)) 
+						bL = extension;
+					else
+						bL = t.getBranchLength(node)*extension;
+				}
+				else
+					bL = 1;
+
+				if (bL> upperLimit) 
+					bL= upperLimit;
+				else if (bL<lowerLimit)
+					bL = lowerLimit;
+				double oldBL = t.getBranchLength(node);
+				if (!MesquiteDouble.isCombinable(oldBL))
+					oldBL = 1.0;
+				t.setBranchLength(node, bL, false);
+				double difference = oldBL - t.getBranchLength(node);
+				for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter))
+					if (MesquiteDouble.isCombinable(t.getBranchLength(daughter)))
+						t.setBranchLength(daughter, t.getBranchLength(daughter) + difference, false);
+				t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+				Graphics g = treeDisplay.getGraphics();
+				g.setPaintMode();
+				g.dispose();
+				treeDisplay.pleaseUpdate(true);
+				lineOn=false;
+			}
+		}
+
+
+		else if (checker.compare(this.getClass(), "Adjust tool is being dragged", "[branch number][x coordinate][y coordinate]", commandName, "draggedPositionAdjust")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+				//WARNING":  This shouldn't result in length increase if simple click and release with no drag; must subtract original X, Y
+				Graphics g = null;
+				if (GraphicsUtil.useXORMode(null, false)){
+					g = treeDisplay.getGraphics();
+					g.setXORMode(Color.white);
+					g.setColor(Color.red);
+				}
+				//g.fillOval(lastX-ovalRadius, lastY-ovalRadius, ovalRadius + ovalRadius, ovalRadius + ovalRadius);
+				//g.fillOval(newOnLine.x-ovalRadius, newOnLine.y -ovalRadius, ovalRadius + ovalRadius, ovalRadius + ovalRadius);
+
+				//g.drawLine(originalX, originalY, lastX, lastY);
+				//g.drawLine(originalX, originalY, newOnLine.x, newOnLine.y);
+
+//				if decreasing, & unassigned involved: push unassigned down and assign values to unassigned above; if increasing, push unassigne up
+				int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
+				int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
+				int itX = treeDisplay.getTreeDrawing().lineTipX[node];
+				int itY = treeDisplay.getTreeDrawing().lineTipY[node];
+
+				double bX = ibX;
+				double bY = ibY;
+				double tX =itX;
+				double tY = itY;
+				double lengthLine =  Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
+				if (lengthLine!=0) {
+					if (GraphicsUtil.useXORMode(null, false)){
+						if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>=1.5 && MesquiteTrunk.getJavaVersionAsDouble()<1.6)  //due to a JVM bug
+							g.fillRect(lastX, lastY-20, 100, 20);
+						g.drawString(MesquiteDouble.toString(lastBL), lastX+10, lastY);
+						if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>=1.5 && MesquiteTrunk.getJavaVersionAsDouble()<1.6)  //due to a JVM bug
+							g.fillRect(lastX, lastY-20, 100, 20);
+					}
+					double extension =  Math.sqrt((newOnLine.y-bY)*(newOnLine.y-bY) + (newOnLine.x-bX)*(newOnLine.x-bX))/lengthLine;
+					double bL;
+					if (t.getBranchLength(node)==0 || t.branchLengthUnassigned(node)) 
+						bL = extension;
+					else
+						bL = t.getBranchLength(node)*extension;
+					if (bL> upperLimit ) {
+						bL= upperLimit;
+						if (t.getBranchLength(node)==0 || t.branchLengthUnassigned(node))
+							extension = upperLimit;
+						else
+							extension = upperLimit/t.getBranchLength(node);
+					}
+					else if (bL<lowerLimit) {
+						bL = lowerLimit;
+						if (t.getBranchLength(node)==0 || t.branchLengthUnassigned(node))
+							extension = lowerLimit;
+						else
+							extension = lowerLimit/t.getBranchLength(node);
+					}
+					lastBL = bL;
+					if (GraphicsUtil.useXORMode(null, false)){
+						drawThickLine(g,ibX, ibY, lastX, lastY);
+						for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter))
+							drawThickLine(g,treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], lastX, lastY);
+						g.fillOval(lastX-ovalRadius, lastY-ovalRadius, ovalRadius+ovalRadius, ovalRadius+ovalRadius);
+					}
+					int newX =ibX+(int)(extension*(tX-bX));
+					int newY = ibY+(int)(extension*(tY-bY));
+					if (GraphicsUtil.useXORMode(null, false)){
+						g.drawString(MesquiteDouble.toString(bL), newX+10, newY);
+						drawThickLine(g,ibX, ibY, newX, newY);
+						for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter))
+							drawThickLine(g,treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], newX, newY);
+						g.fillOval(newX-ovalRadius, newY-ovalRadius, ovalRadius+ovalRadius, ovalRadius+ovalRadius);
+					}
+					lastX= newX;
+					lastY = newY;
+				}
+
+				//lastX= newOnLine.x;
+				//lastY = newOnLine.y;
+			}
+		}
+		return null;
+	}
+	public void turnOff() {
+
+		selectModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/NodePositionAdjust/adjustPosition.gif b/Source/mesquite/ornamental/NodePositionAdjust/adjustPosition.gif
new file mode 100644
index 0000000..c1f4d4a
Binary files /dev/null and b/Source/mesquite/ornamental/NodePositionAdjust/adjustPosition.gif differ
diff --git a/Source/mesquite/ornamental/PictureWindowMaker/PictureWindowMaker.java b/Source/mesquite/ornamental/PictureWindowMaker/PictureWindowMaker.java
new file mode 100644
index 0000000..ea4a4d5
--- /dev/null
+++ b/Source/mesquite/ornamental/PictureWindowMaker/PictureWindowMaker.java
@@ -0,0 +1,203 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.PictureWindowMaker;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class PictureWindowMaker extends FileAssistantN {
+	PictureWindow pictureWindow;
+	String pathToPicture;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { //todo: should behave differently depending on whether home file was url or not!!!
+		pictureWindow = new PictureWindow(this);
+		if (!MesquiteThread.isScripting()){ //file dialog to choose picture
+	 		setModuleWindow(pictureWindow);
+			MesquiteString dir = new MesquiteString();
+			MesquiteString f = new MesquiteString();
+			
+   	 		String path = MesquiteFile.openFileDialog("Picture to show", dir, f);
+   	 		String d = dir.getValue();
+   	 		if (!StringUtil.blank(d) && !StringUtil.blank(f.getValue())) {
+   	 			if (!d.endsWith("/")) 
+   	 				d += "/";
+   	 			boolean success;
+   	 			if (getProject().getHomeDirectoryName().equalsIgnoreCase(d)){
+   	 				pathToPicture = f.getValue();
+   	 				String p = MesquiteFile.composePath(getProject().getHomeDirectoryName(), pathToPicture);
+   	 				if (!MesquiteFile.fileExists(p))
+   	 					return sorry(getName() + " couldn't start because picture file not found.");
+   	 				success = pictureWindow.setPath(p);
+   	 			}
+   	 			else {
+   	 				pathToPicture = path;
+   	 				if (!MesquiteFile.fileExists(path))
+   	 					return sorry(getName() + " couldn't start because picture file not found.");
+					success = pictureWindow.setPath(pathToPicture);
+				}
+				if (!success)
+					return sorry(getName() + " couldn't start because of a problem obtaining the picture.");
+				else {
+			 		resetContainingMenuBar();
+			 		resetAllWindowsMenus();
+					pictureWindow.setVisible(true);
+				}
+   	 		}
+   	 		else 
+   	 			return sorry(getName() + " couldn't start because no picture was specified.");
+		}
+		else {
+	 		setModuleWindow(pictureWindow);
+	 		resetContainingMenuBar();
+	 		resetAllWindowsMenus();
+ 		}
+		return true;
+  	 }
+	 
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (pictureWindow ==null || !pictureWindow.isVisible())
+  	 		return null;
+  	 	Snapshot fromWindow = pictureWindow.getSnapshot(file);
+    	 	Snapshot temp = new Snapshot();
+  	 	
+		temp.addLine("setPicture " + StringUtil.tokenize(MesquiteFile.decomposePath(getProject().getHomeDirectoryName(), pathToPicture))); //TODO: this should do relative to home file, not absolute
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+		temp.addLine("showWindow");
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	 if (checker.compare(this.getClass(), "Sets the path to the picture to be shown", "[path to file; if relative, should be relative to home file of project]", commandName, "setPicture")){
+   	 		pathToPicture = ParseUtil.getFirstToken(arguments, pos);
+  			boolean success = pictureWindow.setPath(MesquiteFile.composePath(getProject().getHomeDirectoryName(), pathToPicture));
+  			if (!success)
+  				iQuit();
+  			else if (!MesquiteThread.isScripting())
+				pictureWindow.setVisible(true);
+    	 	 } 
+      	 	 
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	
+	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Picture Window";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "New Picture Window";
+   	 }
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+			whichWindow.hide();
+			whichWindow.dispose();
+			iQuit();
+	}
+	 public boolean isSubstantive(){
+	 	return false;
+	 }
+	 
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Displays a picture in a window." ;
+   	 }
+}
+	
+/* ======================================================================== */
+class PictureWindow extends MesquiteWindow implements Commandable  {
+	String path;
+	Image image;
+	ImagePanel imagePanel;
+	MediaTracker mt = null;
+		boolean errored = true;
+		int count =0;
+	
+	public PictureWindow (PictureWindowMaker ownerModule){
+		super(ownerModule, true); //infobar
+      		setWindowSize(64,64);
+      		setMinimalMenus(true);
+		//getGraphicsArea().setLayout(new BorderLayout());
+		addToWindow(imagePanel = new ImagePanel(this));
+		imagePanel.setSize(64, 64);
+		setLocation(0,0);
+		imagePanel.setVisible(true);
+		resetTitle();
+      		setWindowSize(64,64);
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Picture: " + path); //TODO: what tree?
+	}
+	public void checkSize(){
+		
+	}
+	public boolean setPath(String path){
+		this.path = path;
+		image = MesquiteImage.getImage(path);
+		if (MesquiteImage.waitForImageToLoad(image, this.getOuterContentsArea())){
+			imagePanel.setImage(image);
+			imagePanel.repaint();
+			setResizable(true);
+	      	if (image!=null) {
+	      		setWindowSize(image.getWidth(imagePanel),image.getHeight(imagePanel));
+	      		imagePanel.setSize(image.getWidth(imagePanel),image.getHeight(imagePanel));
+	      	}
+			setResizable(false);
+			resetTitle();
+			return true;
+		}
+		return false;
+	}
+}
+/* ======================================================================== */
+/** The Panel containing the Mesquite logo on the startup window */
+class ImagePanel extends Panel {
+	Image pic;
+	PictureWindow pw;
+	public ImagePanel (PictureWindow pw) {
+		setBackground(Color.white);
+		this.pw = pw;
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+			g.drawImage(pic,0,0,(ImageObserver)this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void setImage(Image i){
+		pic = i;
+	}
+}
+
+
diff --git a/Source/mesquite/ornamental/Projector/32projector.gif b/Source/mesquite/ornamental/Projector/32projector.gif
new file mode 100644
index 0000000..58471cb
Binary files /dev/null and b/Source/mesquite/ornamental/Projector/32projector.gif differ
diff --git a/Source/mesquite/ornamental/Projector/64projector.gif b/Source/mesquite/ornamental/Projector/64projector.gif
new file mode 100644
index 0000000..85511c2
Binary files /dev/null and b/Source/mesquite/ornamental/Projector/64projector.gif differ
diff --git a/Source/mesquite/ornamental/Projector/Projector.java b/Source/mesquite/ornamental/Projector/Projector.java
new file mode 100644
index 0000000..d13c111
--- /dev/null
+++ b/Source/mesquite/ornamental/Projector/Projector.java
@@ -0,0 +1,393 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.Projector;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class Projector extends TreeDisplayAssistantI {
+	public Vector extras;
+	public String getFunctionIconPath(){
+		return getPath() + "projector.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+   	public String getExpectedPath(){
+		return getPath() + "projector.gif";
+  	 }
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		ProjectorToolExtra newPj = new ProjectorToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+ 	 	int tot = 0;
+  	 	if (extras ==null || extras.size() == 0)
+  	 		return null;
+  	 	for (int i = 0; i<extras.size(); i++) {
+  	 		ProjectorToolExtra pte = (ProjectorToolExtra)extras.elementAt(i);
+  	 		if (pte != null)
+  	 			tot += 3 +pte.getNumPicturesShowing();
+  	 	}
+  	 	if (tot == 0)
+  	 		return null;
+    	 	Snapshot temp = new Snapshot();
+  	 	for (int i = 0; i<extras.size(); i++) {
+  	 		ProjectorToolExtra pte = (ProjectorToolExtra)extras.elementAt(i);
+    	 		if (pte != null) { 
+	  	 		Snapshot q = pte.getSnapshot(file);
+	  	 		if (q !=null) {
+			 		temp.addLine("getExtra " + i );
+		  	 		temp.addLine("tell It");
+		  	 		temp.incorporate(q, true);
+		  	 		temp.addLine("endTell");
+	  	 		}
+  	 		}
+  	 	}
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Returns a projector object", "[number of object]", commandName, "getExtra")) {  
+	  	 	int which = MesquiteInteger.fromFirstToken(arguments, pos);
+	  	 	if (MesquiteInteger.isCombinable(which) && which>=0 && which<extras.size()) 
+	  	 		return extras.elementAt(which);
+	  	 	else
+	  	 		return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Projector";
+   	 }
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies a projector tool for tree windows that allows pictures attached to taxa to be displayed." ;
+   	 }
+}
+
+/* ======================================================================== */
+class ProjectorToolExtra extends TreeDisplayDrawnExtra implements Commandable  {
+	TreeTool projectorTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	Projector projectorModule;
+	Image[] taxonImages=null;
+	 ProjectorPanel[] panels=null;
+	boolean usePanels = false;
+	boolean picturesOn = false;
+	
+	public ProjectorToolExtra (Projector ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		projectorModule = ownerModule;
+		projectorTool = new TreeTool(this, "projector", ownerModule.getPath(),"projector.gif", 8,1,"Show picture", "This tool displays a picture attached to a taxon.  By clicking again, the picture is hidden.  A terminal taxon has an available picture if there is a \"(i)\" after its name.");
+		projectorTool.setTouchedTaxonCommand(MesquiteModule.makeCommand("showTaxonPicture",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(projectorTool);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawNode(Tree tree, int node, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawNode(tree, d, g);
+		if (tree.nodeIsTerminal(node)) {
+			int taxonNumber =tree.taxonNumberOfNode(node);
+			Image im = taxonImages[taxonNumber];
+			if (im!=null) {
+				int imWidth = im.getWidth((ImageObserver)treeDisplay);
+				int imHeight = im.getHeight((ImageObserver)treeDisplay);
+				int taxonSpacing = treeDisplay.getTaxonSpacing();
+				if (taxonSpacing <80)
+					taxonSpacing = 80;
+				double scale = MesquiteImage.getScaleToReduce(imWidth, imHeight, taxonSpacing, taxonSpacing);
+		      		if (scale<1.0){
+		      			imWidth *= scale;
+		      			imHeight *= scale;
+		      		}
+				if (usePanels && panels!=null && panels[taxonNumber] != null) 
+					panels[taxonNumber].setLocation( treeDisplay.getTreeDrawing().x[node]-imWidth/2, treeDisplay.getTreeDrawing().y[node]-imHeight/2);
+				else
+					g.drawImage(im, treeDisplay.getTreeDrawing().x[node]-imWidth/2, treeDisplay.getTreeDrawing().y[node]-imHeight/2, imWidth, imHeight, (ImageObserver)treeDisplay);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree==null)
+			return;
+		//TODO: SHOUDLN"T DO THIS IF NO IMAGES SHOWN
+		if (picturesOn) {
+			checkNumTaxa(tree);
+			drawNode(tree, drawnRoot, g);
+		}
+	}
+	
+	private void checkNumTaxa(Tree tree) {
+		if (tree==null)
+			return;
+		if (taxonImages==null) {
+			taxonImages = new Image[tree.getNumTaxa()];
+		}
+		else if (taxonImages.length!= tree.getNumTaxa()) {
+			Image[] newTaxonImages = new Image[tree.getNumTaxa()];
+			for (int i=0; i< taxonImages.length && i<tree.getNumTaxa(); i++) {
+				newTaxonImages[i]=taxonImages[i];
+			}
+			taxonImages=newTaxonImages;
+		}
+		if (usePanels) {
+			if (panels==null) {
+				panels = new ProjectorPanel[tree.getNumTaxa()];
+				for (int i=0; i< panels.length; i++) {
+					panels[i] = new ProjectorPanel(treeDisplay);
+				}
+			}
+			else if (panels.length!= tree.getNumTaxa()) {
+				ProjectorPanel[] newPanels = new ProjectorPanel[tree.getNumTaxa()];
+				for (int i=0; i< panels.length && i<tree.getNumTaxa(); i++) {
+					newPanels[i] = panels[i];
+				}
+				for (int i=panels.length;i<tree.getNumTaxa(); i++) {
+					newPanels[i] = new ProjectorPanel(treeDisplay);
+				}
+				panels = newPanels;
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	/** Returns any strings to be appended to taxon name.*/
+	public String getTaxonStringAddition(Taxon taxon){
+		if (taxon == null)
+			return null;
+		Taxa taxa = taxon.getTaxa();
+		int M = taxa.whichTaxonNumber(taxon);
+		if (M<0  || M> taxa.getNumTaxa())
+			return null;
+		if (taxonImages != null && M<taxonImages.length && taxonImages[M] !=null)
+			return "(i)";
+		else {
+			Image image = null;
+			AttachedNotesVector aim = (AttachedNotesVector)taxa.getAssociatedObject(imageNameRef, M);
+			if (aim == null || aim.getNumNotes()==0)
+				return null;
+			AttachedNote hL = aim.getAttachedNote(0);
+			
+			
+			if (hL == null)
+				return null;
+			image = hL. getImage();
+			if (image != null) 
+				 return "(i)";
+			return null;
+		}
+	}
+
+	/*.................................................................................................................*/
+	private   void checkMenuStatus(boolean added) {
+		if (added) { //image shown; make sure menu says "turn off pictures"
+			if (hideMenuItem==null) {
+				hideMenuItem = ownerModule.addMenuItem("Hide pictures", MesquiteModule.makeCommand("hidePictures", this));
+				ownerModule.resetContainingMenuBar();
+				picturesOn = true;
+			}
+		}
+		else {
+    	 		boolean someLeft = false;
+    	 		for (int M = 0; M<taxonImages.length; M++)
+				if (taxonImages[M]!= null)
+					someLeft=true;
+			if (!someLeft) {
+				ownerModule.deleteMenuItem(hideMenuItem);
+				hideMenuItem = null;
+				ownerModule.resetContainingMenuBar();
+				picturesOn = false;
+			}
+		}
+		
+	}
+	/*.................................................................................................................*/
+  	 public int getNumPicturesShowing() {
+  	 	if (taxonImages== null)
+  	 		return 0;
+  	 	int n = 0;
+ 		for (int j=0; j<taxonImages.length; j++) {
+ 			if (taxonImages[j] !=null)
+ 				n++;
+ 		}
+  	 	return n;
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (getNumPicturesShowing() <=0 || taxonImages == null) 
+  	 		return null;
+    	 	Snapshot temp = new Snapshot();
+		for (int j=0; j<taxonImages.length; j++) {
+ 			if (taxonImages[j] !=null) {
+ 				temp.addLine("showTaxonPicture " + j );
+ 			}
+ 		}
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	public String chooseLink(){
+			MesquiteString dir = new MesquiteString();
+			MesquiteString f = new MesquiteString();
+			
+   	 		String path = MesquiteFile.openFileDialog("Choose Picture", dir, f);
+   	 		String d = dir.getValue();
+   	 		if (!StringUtil.blank(d) && !StringUtil.blank(f.getValue())) {
+   	 			if (!d.endsWith("/")) 
+   	 				d += "/";
+   	 			boolean success;
+   	 			if (ownerModule.getProject().getHomeDirectoryName().equalsIgnoreCase(d)){
+   	 				return f.getValue();
+   	 			}
+   	 			else {
+   	 				return path;
+				}
+			}
+			return null;
+	}
+	/*.................................................................................................................*/
+  	 MesquiteInteger pos = new MesquiteInteger();
+	NameReference imageNameRef = NameReference.getNameReference("notes");
+	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+    	 	if (checker.compare(this.getClass(), "Hides pictures of taxa", null, commandName, "hidePictures")) {
+    	 		for (int M = 0; M<taxonImages.length; M++) {
+				taxonImages[M]= null;
+				if (usePanels && M<panels.length && panels[M]!=null) {
+					panels[M].setVisible(false);
+					removePanelPlease(panels[M]);
+				}
+			}
+			checkMenuStatus(false);
+			treeDisplay.pleaseUpdate(false);
+   	 	}
+    	 	else if (checker.compare(this.getClass(), "Shows picture of taxon", "[taxon number][modifiers]", commandName, "showTaxonPicture")) {
+    	 		Tree tree = treeDisplay.getTree();
+    	 		Taxa taxa = tree.getTaxa();
+   	 		int M = MesquiteInteger.fromFirstToken(arguments, pos);
+   	 		if (M<0 || !MesquiteInteger.isCombinable(M))
+   	 			return null;
+
+			Image image = null;
+
+			AttachedNotesVector aim = (AttachedNotesVector)taxa.getAssociatedObject(imageNameRef, M);
+			if (aim == null) {
+				ownerModule.discreetAlert( "There are no images attached to that taxon to show.  To attach an image, use the annotations panel of a Character Matrix Editor to make an annotation and link in an image");
+				return null;
+			}
+			AttachedNote hL = aim.getAttachedNote(0);
+			
+			
+			if (hL != null){
+				image = hL. getImage();
+			}
+			else {
+				ownerModule.discreetAlert( "There are no images attached to that taxon to show.  To attach an image, use the annotations panel of a Character Matrix Editor to make an annotation and link in an image");
+				return null;
+			}
+			/*else {
+				image = tree.getTaxa().getTaxon(M).getIllustration();
+			}*/
+			if (image != null) {
+				checkNumTaxa(tree);
+				if (taxonImages[M] == null) {
+					checkMenuStatus(true);
+					taxonImages[M]=  image;
+					if (usePanels) {
+						panels[M].setImage(taxonImages[M]);
+						panels[M].setLocation( treeDisplay.getTreeDrawing().x[M]-taxonImages[M].getWidth((ImageObserver)treeDisplay)/2, treeDisplay.getTreeDrawing().y[M]-taxonImages[M].getHeight((ImageObserver)treeDisplay)/2);
+						panels[M].setSize(taxonImages[M].getWidth((ImageObserver)treeDisplay), taxonImages[M].getHeight((ImageObserver)treeDisplay));
+						addPanelPlease(panels[M]);
+
+						panels[M].setVisible(true);
+						panels[M].repaint();
+						//treeDisplay.fillTaxon();
+					}
+				}
+				else {
+					taxonImages[M]= null;
+					checkMenuStatus(false);
+					if (usePanels) {
+						panels[M].setVisible(false);
+						removePanelPlease(panels[M]);
+					}
+				}
+				treeDisplay.pleaseUpdate(false);
+			}
+			else {
+				ownerModule.discreetAlert( "There are no images attached to that taxon to show.  To attach an image, use the annotations panel of a Character Matrix Editor to make an annotation and link in an image");
+				return null;
+			}
+    	 	}
+ 		return null;
+ 	}
+	public void turnOff() {
+		projectorModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+class ProjectorPanel extends Panel {
+	Image im=null;
+	TreeDisplay treeDisplay;
+	
+	public ProjectorPanel (TreeDisplay treeDisplay) {
+		this.treeDisplay = treeDisplay;
+		setSize(10,10);
+		setBackground(Color.red);
+	}
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		
+		if (im!= null )
+			g.drawImage(im, 0, 0, this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	public void setImage(Image im) {
+		this.im = im;
+		//setSize(im.getWidth(this), im.getHeight(this));
+	}
+}
+	
+
+
diff --git a/Source/mesquite/ornamental/Projector/projector.gif b/Source/mesquite/ornamental/Projector/projector.gif
new file mode 100644
index 0000000..196c86a
Binary files /dev/null and b/Source/mesquite/ornamental/Projector/projector.gif differ
diff --git a/Source/mesquite/ornamental/TaxonLink/32link.gif b/Source/mesquite/ornamental/TaxonLink/32link.gif
new file mode 100644
index 0000000..6c2aa61
Binary files /dev/null and b/Source/mesquite/ornamental/TaxonLink/32link.gif differ
diff --git a/Source/mesquite/ornamental/TaxonLink/64link.gif b/Source/mesquite/ornamental/TaxonLink/64link.gif
new file mode 100644
index 0000000..95a26cc
Binary files /dev/null and b/Source/mesquite/ornamental/TaxonLink/64link.gif differ
diff --git a/Source/mesquite/ornamental/TaxonLink/TaxonLink.java b/Source/mesquite/ornamental/TaxonLink/TaxonLink.java
new file mode 100644
index 0000000..39c92a3
--- /dev/null
+++ b/Source/mesquite/ornamental/TaxonLink/TaxonLink.java
@@ -0,0 +1,363 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.ornamental.TaxonLink;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class TaxonLink extends TreeDisplayAssistantI {
+	public Vector extras;
+	public String getFunctionIconPath(){
+		return getPath() + "link.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		TaxonLinkToolExtra newPj = new TaxonLinkToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Taxon Link";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies a tool for tree windows that jumps to hypertext links for taxa." ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+}
+
+/* ======================================================================== */
+class TaxonLinkToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool taxonLinkTool;
+	TaxonLink taxonLinkModule;
+	MesquiteLabel message;
+	MesquiteCommand taxonCommand, cladeCommand;
+	public TaxonLinkToolExtra (TaxonLink ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		taxonLinkModule = ownerModule;
+		taxonLinkTool = new TreeTool(this, "taxonLink", ownerModule.getPath(), "link.gif", 4,0,"Go to link", "This tool follows a hypertext link to another file or to a web page.  Hold down Control when using to set the link to a local file; hold down shift to enter a URL.  If filename ends in .htm or .html or contains http:// or https://, it is opened in a web browser; otherwise it is opened in Mesquite."); //; hold down shift to enter a URL
+		taxonCommand = MesquiteModule.makeCommand("goToLinkedTaxon",  this);
+		cladeCommand = MesquiteModule.makeCommand("goToLinkedClade",  this);
+		taxonLinkTool.setTouchedTaxonCommand(taxonCommand);
+		taxonLinkTool.setTouchedCommand(cladeCommand);
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(taxonLinkTool);
+		}
+		message = new MesquiteLabel(null, 0);
+		message.setSize(4,4);
+		message.setColor(Color.yellow);
+		message.setVisible(false);
+		treeDisplay.addPanelPlease(message);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	NameReference taxonlinkRef = NameReference.getNameReference("hyperlink");
+	/** Returns true if this extra wants the taxon to have its name underlined */
+	public boolean getTaxonUnderlined(Taxon taxon){
+		Taxa taxa = taxon.getTaxa();
+		int m = taxa.whichTaxonNumber(taxon);
+		return (taxa.getAssociatedObject(taxonlinkRef, m) !=null);
+		//return (taxon.getLink()!=null);
+	}
+	/** Returns the color the extra wants the taxon name colored.*/
+	public Color getTaxonColor(Taxon taxon){
+		if (getTaxonUnderlined(taxon))
+			return Color.blue;
+		else
+			return null;
+	}
+	/** Returns true if this extra wants the clade to have its label underlined */
+	public boolean getCladeLabelUnderlined(String label, int N){
+		Clade c = treeDisplay.getTree().getTaxa().getClades().findClade(label);
+		return (c!=null && c.getLink()!=null);
+	}
+	/** Returns the color the extra wants the clade label colored.*/
+	public Color getCladeLabelColor(String label, int N){
+		Clade c = treeDisplay.getTree().getTaxa().getClades().findClade(label);
+		if (c!=null && c.getLink()!=null)
+			return Color.blue;
+		else
+			return null;
+	}
+
+	private void showLink(String link){
+		MesquiteWindow f = ownerModule.containerOfModule();
+		if (f !=null && f instanceof MesquiteWindow){
+			MesquiteWindow w = (MesquiteWindow)f;
+			if (link == null)
+				w.setAnnotation(null, null);
+			else
+				w.setAnnotation("Link to: " + link, "");
+		}
+	}
+
+	NameReference linkNameRef = NameReference.getNameReference("hyperlink");
+	boolean shown = false;
+	/**to inform TreeDisplayExtra that cursor has just entered name of terminal taxon M*/
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g){
+		if (taxonLinkTool.getInUse()){
+			String link = (String)tree.getTaxa().getAssociatedObject(linkNameRef, M);
+			if (link!=null) {
+
+				showLink(link);
+				shown = true;
+
+				int tM = tree.nodeOfTaxonNumber(M);
+				//message.setLocation(treeDisplay.getTreeDrawing().x[tM], treeDisplay.getTreeDrawing().y[tM]);
+				message.setLocation(0,0);
+				message.setText("Link to: " + link);
+				message.setVisible(true);
+				message.setCommand(taxonCommand);
+				message.setArguments(Integer.toString(M));
+				/**/
+			}
+		}
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited name of terminal taxon M*/
+	public void cursorExitTaxon(Tree tree, int M, Graphics g){
+		if (shown) {
+			showLink(null);
+			message.setVisible(false);
+		}
+		shown = false;
+	}
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){
+		if (taxonLinkTool.getInUse()){
+			String label = tree.getNodeLabel(N);
+			if (!StringUtil.blank(label)) {
+				Clade c = tree.getTaxa().getClades().findClade(label);
+				if (c!=null) {
+					String link = c.getLink();
+					if (link!=null) {
+						showLink(link);
+						shown = true;
+
+						//message.setLocation(treeDisplay.getTreeDrawing().x[N], treeDisplay.getTreeDrawing().y[N]);
+						message.setLocation(0,0);
+						message.setText("Link to: " + link);
+						message.setVisible(true);
+						message.setCommand(cladeCommand);
+						message.setArguments(Integer.toString(N));
+						/**/
+					}
+				}
+			}
+		}
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited branch N*/
+	public void cursorExitBranch(Tree tree, int N, Graphics g){
+		if (shown) {
+			showLink(null);
+			message.setVisible(false);
+			//message.setSize(4,4);
+		}
+		shown = false;
+	}
+
+	public String chooseLink(int from){
+		if (from == 1){
+			MesquiteString dir = new MesquiteString();
+			MesquiteString f = new MesquiteString();
+			String path = MesquiteFile.openFileDialog("Choose file to which to link", dir, f); // (if ends in .nex, link will take user to that file in Mesquite; if ends in .htm or .html, will take user to web browser)
+			String d = dir.getValue();
+			if (!StringUtil.blank(d) && !StringUtil.blank(f.getValue())) {
+				if (!d.endsWith("/")) 
+					d += "/";
+				boolean success;
+				if (ownerModule.getProject().getHomeDirectoryName().equalsIgnoreCase(d)){
+					return f.getValue();
+				}
+				else {
+					return path;
+				}
+			}
+		}
+		else if (from == 2) {
+			return MesquiteString.queryString(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "URL to which to link", "URL to which to link:", "");
+		}
+		return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Goes to the file or web page linked for the taxon", "[taxon number][modifiers]", commandName, "goToLinkedTaxon")) {
+			Tree tree = treeDisplay.getTree();
+			int M = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (M<0 || !MesquiteInteger.isCombinable(M) || M>=tree.getTaxa().getNumTaxa())
+				return null;
+			if (arguments.indexOf("shift")>=0) {  //url
+				String link = (String)tree.getTaxa().getAssociatedObject(linkNameRef, M);
+				if (link == null)
+					link = "";
+				String url = MesquiteString.queryShortString(ownerModule.containerOfModule(), "URL", "URL to which to link taxon", link);
+				if (StringUtil.blank(url))
+					return null;
+				Taxa taxa = tree.getTaxa();
+				if (taxa.getWhichAssociatedObject(linkNameRef)==null)
+					taxa.makeAssociatedObjects("hyperlink");
+				taxa.setAssociatedObject(linkNameRef, M, url);
+				ownerModule.outputInvalid();
+				return null;
+			}
+			else if (arguments.indexOf("control")>=0) {  //file
+				String chosen = chooseLink(1);
+				if (chosen==null)
+					return null;
+				Taxa taxa = tree.getTaxa();
+				if (taxa.getWhichAssociatedObject(linkNameRef)==null)
+					taxa.makeAssociatedObjects("hyperlink");
+				taxa.setAssociatedObject(linkNameRef, M, MesquiteFile.decomposePath(ownerModule.getProject().getHomeDirectoryName(), chosen));
+				ownerModule.outputInvalid();
+				return null;
+			}
+			else {
+				String link = (String)tree.getTaxa().getAssociatedObject(linkNameRef, M);
+				if (link!=null) {
+					if (StringUtil.startsWithIgnoreCase(link, "http:") || StringUtil.startsWithIgnoreCase(link, "https:") || link.endsWith(".html") || link.endsWith(".htm") || link.endsWith(".HTML") || link.endsWith(".HTM")) {  //assumed to be web page
+						if (StringUtil.startsWithIgnoreCase(link, "http")) 
+							taxonLinkModule.showWebPage(link, false);
+						else
+							taxonLinkModule.showWebPage(MesquiteFile.composePath(taxonLinkModule.getProject().getHomeDirectoryName(),  link), false);
+					}
+					else {
+						ownerModule.logln("Jumping to " + link);
+						String openCommand = "openFile ";
+						if (StringUtil.startsWithIgnoreCase(link, "http")|| !taxonLinkModule.getProject().getHomeFile().isLocal()) {
+							openCommand = "openGeneral  Open_URL ";
+						}
+
+						String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; closeProjectByID *Integer.id; " + openCommand;
+						commands +=  StringUtil.tokenize(MesquiteFile.composePath(taxonLinkModule.getProject().getHomeDirectoryName(),link)) + "; endTell;";
+						Puppeteer p = new Puppeteer(taxonLinkModule);
+						MesquiteInteger pos = new MesquiteInteger(0);
+						p.execute(taxonLinkModule.getFileCoordinator(), commands, pos, "", false);
+						taxonLinkModule.fireEmployee(taxonLinkModule);
+					}
+				}
+				else if (!MesquiteThread.isScripting()) {
+					ownerModule.alert("There is no link associated with that taxon.  If you want to attach a link, hold down the control key while you touch the taxon to select a local file, shift key to enter a URL.  If filename ends in .nex, it is opened in Mesquite; otherwise it is opened in a web browser.");
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to the file or web page linked for the clade", "[node number][modifiers]", commandName, "goToLinkedClade")) {
+			Tree tree = treeDisplay.getTree();
+			int edit = 0;
+			int M = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (M<0 || !MesquiteInteger.isCombinable(M))
+				return null;
+			String label = tree.getNodeLabel(M);
+			Clade c = tree.getTaxa().getClades().findClade(label);
+			if (arguments.indexOf("shift")>=0) {  //url
+				if (StringUtil.blank(label)) {
+					if (!MesquiteThread.isScripting()) 
+						ownerModule.alert("To establish a link on an internal branch, you must first assign a label or name to the branch (e.g., using the Name Nodes tool)");
+
+					return null;
+				}
+				if (c==null)
+					return null;
+				String link = c.getLink();
+				if (link == null)
+					link = "";
+				String url = MesquiteString.queryShortString(ownerModule.containerOfModule(), "URL", "URL to which to link branch", link);
+				if (url==null)
+					return null;
+				c.setLink(url);
+				ownerModule.outputInvalid();
+				return null;
+			}
+			else if (arguments.indexOf("control")>=0) {  //file
+				if (StringUtil.blank(label)) {
+					if (!MesquiteThread.isScripting()) 
+						ownerModule.alert("To establish a link on an internal branch, you must first assign a label or name to the branch (e.g., using the Name Nodes tool)");
+					return null;
+				}
+				if (c==null)
+					return null;
+				String chosen = chooseLink(1);
+				if (chosen==null)
+					return null;
+				c.setLink(chosen);
+				ownerModule.outputInvalid();
+				return null;
+			}
+			else {
+				if (c==null)
+					return null;
+				String link = c.getLink();
+				if (link!=null) {
+					if (!link.endsWith(".nex")) {  //assumed to be web page
+						if (StringUtil.startsWithIgnoreCase(link, "http")) 
+							taxonLinkModule.showWebPage(link, false);
+						else
+							taxonLinkModule.showWebPage(MesquiteFile.composePath(taxonLinkModule.getProject().getHomeDirectoryName(),  link), false);
+					}
+					else {
+						String openCommand = "openFile ";
+						if (StringUtil.startsWithIgnoreCase(link, "http")|| !taxonLinkModule.getProject().getHomeFile().isLocal()) {
+							openCommand = "openURL ";
+						}
+
+						String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; closeProjectByID *Integer.id; " + openCommand;
+
+						commands +=  StringUtil.tokenize(MesquiteFile.composePath(taxonLinkModule.getProject().getHomeDirectoryName(),link)) + "; endTell;";
+						Puppeteer p = new Puppeteer(taxonLinkModule);
+						MesquiteInteger pos = new MesquiteInteger(0);
+						p.execute(taxonLinkModule.getFileCoordinator(), commands, pos, "", false);
+						taxonLinkModule.fireEmployee(taxonLinkModule);
+					}
+				}
+				else if (!MesquiteThread.isScripting()) {
+					ownerModule.alert("There is no link associated with that branch.  To establish a link on an internal branch, hold down the control key while you touch the branch to select a local file, shift key to enter a URL.  If filename ends in .nex, it is opened in Mesquite; otherwise it is opened in a web browser.");
+				}
+			}
+		}
+		return null;
+	}
+	public void turnOff() {
+		if (treeDisplay != null && message !=null)
+			treeDisplay.removePanelPlease(message);
+		taxonLinkModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/ornamental/TaxonLink/link.gif b/Source/mesquite/ornamental/TaxonLink/link.gif
new file mode 100644
index 0000000..9ef2f58
Binary files /dev/null and b/Source/mesquite/ornamental/TaxonLink/link.gif differ
diff --git a/Source/mesquite/ornamental/aOrnamentalIntro/aOrnamentalIntro.java b/Source/mesquite/ornamental/aOrnamentalIntro/aOrnamentalIntro.java
new file mode 100644
index 0000000..19ac14d
--- /dev/null
+++ b/Source/mesquite/ornamental/aOrnamentalIntro/aOrnamentalIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.ornamental.aOrnamentalIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aOrnamentalIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aOrnamentalIntro.class;
+  	 }
+	/*.................................................................................................................*/
+     public String getExplanation() {
+		return "Has extra methods for drawing and decorating trees.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Ornamental Trees Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Ornamental Trees Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/ornamental/explanation.txt b/Source/mesquite/ornamental/explanation.txt
new file mode 100644
index 0000000..372a8e3
--- /dev/null
+++ b/Source/mesquite/ornamental/explanation.txt
@@ -0,0 +1,2 @@
+Ornaments for Tree Window
+Provides several special ways to draw trees (circular, constellation), facilities to attach extra information to trees (pictures, notes at branches, hyperlinks), and extra tree tools.
diff --git a/Source/mesquite/pairwise/PairsNoChars/PairsNoChars.java b/Source/mesquite/pairwise/PairsNoChars/PairsNoChars.java
new file mode 100644
index 0000000..9fdb11e
--- /dev/null
+++ b/Source/mesquite/pairwise/PairsNoChars/PairsNoChars.java
@@ -0,0 +1,461 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.pairwise.PairsNoChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.categ.lib.CategoricalDistribution;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.pairwise.lib.*;
+
+/* ======================================================================== */
+public class PairsNoChars extends PairMakerChars {
+	public String getName() {
+		return "Most Pairs";
+	}
+	public String getExplanation() {
+		return "Chooses taxon pairings regardless of contrast in a character, so as to maximize the number of pairs that are phylogenetically independent." ;
+	}
+	TaxaPairerChars pairer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){
+		if (pairer!=null)
+			pairer.setCharacters(statesA, statesB);
+	}
+	/*.................................................................................................................*/
+	public TaxaPairer getPairer(){
+		return pairer = new NoCharTaxaPairer(this);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	} 
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+/*Assumes  dichotomous.  On way down, store maximum numbers.  On way up, pass forward TaxaPath objects and state sought.  Each TaxaPath object should store
+two taxa which it should decide once it gets to tips.  A new TaxaPath object is formed each time an open clade is created by a lack of committed TaxaPath sought
+rising from below.  At each internal node must be stored the current choice at that internal node and the list of choices possible,
+ so that all possible choices can be cycled through.  A choice is whether to continue TaxaPath up right or left if one is coming from below, or, if none
+ is coming up, whether a TaxaPath can be started (which it always can be 
+ ======================================================================== */
+class NoCharTaxaPairer extends TaxaPairerChars {
+	private boolean firstTime=true;
+	int[][] maxPairs;
+	final static int pathFromBelow = 0;
+	final static int noPathFromBelow = 1;
+	final static int pathAcrossRoot =2;
+	final static int noPathAcrossRoot = 3;
+	final static int pathUpLeft = 4;
+	final static int pathUpRight = 5;
+	final static int numConditions = 6;
+
+	private int numPairs=0;
+	Tree tree;
+	private int[] currentChoice, numChoices;
+	private TaxaPath[] currentPath;
+	static final boolean lastChoice = true;
+	boolean done = false;
+	PairMaker ownerModule = null;
+	int currentPairing=0;
+
+	public NoCharTaxaPairer (PairMaker ownerModule) {
+		this.ownerModule = ownerModule;
+	}
+	public void init(){
+	}
+	/* ..................................................................................................................................... */
+	private void diagnoseDownPass(int node){
+		System.out.println("==== node " + node + " ==== ");
+		System.out.println("     max under noPathFromBelow " + maxPairs[noPathFromBelow][node]);
+		System.out.println("     max under pathFromBelow " + maxPairs[pathFromBelow][node]);
+		System.out.println("     max under pathAcrossRoot " + maxPairs[pathAcrossRoot][node]);
+		System.out.println("     max under noPathAcrossRoot " + maxPairs[noPathAcrossRoot][node]);
+		System.out.println("     max under pathUpLeft " + maxPairs[pathUpLeft][node]);
+		System.out.println("     max under pathUpRight " + maxPairs[pathUpRight][node]);
+	}
+	boolean warnedSomeIllegal = false;
+	int[] legality;
+	CharacterState csA, csB;
+	CharacterDistribution observedStatesA, observedStatesB;
+	/*.................................................................................................................*/
+	private void setLegality(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			csA =observedStatesA.getCharacterState(csA, tree.taxonNumberOfNode(node)); //get observed states
+			csB =observedStatesB.getCharacterState(csB, tree.taxonNumberOfNode(node)); //get observed states
+			if ((csA == null || csA.isUnassigned() || csA.isInapplicable()) ||  //either of the two characters is missing data
+					(csB == null || csB.isUnassigned() || csB.isInapplicable())) //either of the two characters is inapplicable
+				legality[node] = MesquiteTree.ILLEGAL;
+			else
+				legality[node] = MesquiteTree.LEGAL;
+			if (legality[node] == MesquiteTree.ILLEGAL)
+				warningMessage = "Some taxa excluded (had character states that are missing or inapplicable).";
+
+		}
+		else {
+			int left = tree.firstDaughterOfNode(node);  //assumes dichotomous tree, so get left and right daughter
+			int right = tree.lastDaughterOfNode(node);
+			setLegality(left, tree);
+			setLegality(right, tree);
+			if (legality[left] != MesquiteTree.ILLEGAL && legality[right] != MesquiteTree.ILLEGAL )
+				legality[node] = MesquiteTree.LEGAL;
+			else if (legality[left] != MesquiteTree.ILLEGAL || legality[right] != MesquiteTree.ILLEGAL)
+				legality[node] = MesquiteTree.SEMILEGAL;
+			else
+				legality[node] = MesquiteTree.ILLEGAL;
+		}
+	}
+	/*.................................................................................................................*/
+	private void legalityCheck(Tree tree) {
+		if (legality == null || legality.length != tree.getNumNodeSpaces())
+			legality = new int[tree.getNumNodeSpaces()];
+		for (int i = 0; i< legality.length; i++)
+			legality[i] = MesquiteTree.LEGAL;
+		warningMessage = "";
+		if (observedStatesA== null || observedStatesB == null)// not needed except to exclude taxa with missing/inapplicable
+			return;
+		setLegality(tree.getRoot(), tree);
+	}	/* ..................................................................................................................................... */
+	private void downPass(Tree tree, int node) {
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextLegalSisterOfNode(daughter, legality))
+			downPass(tree, daughter);
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+
+			if (tree.nodeIsInternal(left) && tree.nodeIsInternal(right)) {  // both are internal
+				maxPairs[noPathFromBelow][node] = MesquiteInteger.maximum(maxPairs[noPathFromBelow][left] + maxPairs[noPathFromBelow][right], maxPairs[pathFromBelow][left]  + maxPairs[pathFromBelow][right]  + 1);
+				maxPairs[pathFromBelow][node] = MesquiteInteger.maximum(maxPairs[noPathFromBelow][left] + maxPairs[pathFromBelow][right], maxPairs[pathFromBelow][left]  + maxPairs[noPathFromBelow][right]);
+				maxPairs[pathAcrossRoot][node] = maxPairs[pathFromBelow][left]  + maxPairs[pathFromBelow][right]  + 1;
+				maxPairs[noPathAcrossRoot][node] = MesquiteInteger.maximum(maxPairs[pathAcrossRoot][left], maxPairs[noPathAcrossRoot][left]) +  MesquiteInteger.maximum(maxPairs[pathAcrossRoot][right], maxPairs[noPathAcrossRoot][right]);
+				maxPairs[pathUpLeft][node] = maxPairs[pathFromBelow][left] + maxPairs[noPathFromBelow][right];
+				maxPairs[pathUpRight][node] = maxPairs[noPathFromBelow][left] + maxPairs[pathFromBelow][right];
+			}
+			else if (tree.nodeIsInternal(left)) {  //right only must be terminal
+				maxPairs[noPathFromBelow][node] = MesquiteInteger.maximum(maxPairs[noPathFromBelow][left], maxPairs[pathFromBelow][left]  + 1);
+				maxPairs[pathFromBelow][node] = MesquiteInteger.maximum(maxPairs[pathFromBelow][left], maxPairs[noPathFromBelow][left]);
+				maxPairs[pathAcrossRoot][node] = maxPairs[pathFromBelow][left]  +1;
+				maxPairs[noPathAcrossRoot][node] = MesquiteInteger.maximum(maxPairs[pathAcrossRoot][left], maxPairs[noPathAcrossRoot][left]);
+				maxPairs[pathUpLeft][node] = maxPairs[pathFromBelow][left];
+				maxPairs[pathUpRight][node] = maxPairs[noPathFromBelow][left];
+			}
+			else if (tree.nodeIsTerminal(right)) { //both be terminal
+				maxPairs[noPathFromBelow][node] = 1;
+				maxPairs[pathFromBelow][node] = 0;
+				maxPairs[pathAcrossRoot][node] = 1;
+				maxPairs[noPathAcrossRoot][node] = 0;
+				maxPairs[pathUpLeft][node] = 0;
+				maxPairs[pathUpRight][node] = 0;
+			}
+			else {	// left only must be terminal
+				maxPairs[noPathFromBelow][node] = MesquiteInteger.maximum(maxPairs[noPathFromBelow][right], maxPairs[pathFromBelow][right]  + 1);
+				maxPairs[pathFromBelow][node] = MesquiteInteger.maximum(maxPairs[pathFromBelow][right], maxPairs[noPathFromBelow][right]);
+				maxPairs[pathAcrossRoot][node] = maxPairs[pathFromBelow][right]  +1;
+				maxPairs[noPathAcrossRoot][node] = MesquiteInteger.maximum(maxPairs[pathAcrossRoot][right], maxPairs[noPathAcrossRoot][right]);
+				maxPairs[pathUpLeft][node] = maxPairs[noPathFromBelow][right];
+				maxPairs[pathUpRight][node] = maxPairs[pathFromBelow][right];
+			}
+			//diagnoseDownPass(node);
+		}
+	}
+
+	/* ..................................................................................................................................... */
+	public  void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){
+		observedStatesA = statesA;
+		observedStatesB = statesB;
+	}
+	/*.................................................................................................................*/
+	public TaxaPairing getFirstPairing(Tree tree) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		currentPairing = 0;
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+			return tp;
+		}
+		done=false;
+		int num = tree.getNumNodeSpaces();
+		currentChoice= new int[num];
+		numChoices = new int[num];
+		currentPath = new TaxaPath[num];
+		maxPairs = new int[numConditions][num];
+		legalityCheck(tree);
+		downPass(tree, tree.getRoot());
+		numPairs = maxPairs[noPathFromBelow][ tree.getRoot()];
+		firstPairingInClade(tree.getRoot(), tree);
+		firstTime=false;
+		harvestPaths(tree, tree.getRoot(), tp);
+		if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+			MesquiteMessage.println("Error: expected numpairs does not match number harvested, gFP" + tp.getNumPairs() + "  " + numPairs);
+			warnedNumPairs = true;
+		}
+		return tp;
+	}
+	/*.................................................................................................................*/
+	public TaxaPairing getNextPairing(Tree tree) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+			return tp;
+		}
+
+		if (!done) {
+			if (nextPairingInClade(tree, tree.getRoot())==lastChoice) 
+				done=true;
+			harvestPaths(tree, tree.getRoot(), tp);
+			if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+				MesquiteMessage.println("Error: expected numpairs does not match number harvested, gNP" + tp.getNumPairs() + "  " + numPairs);
+				warnedNumPairs = true;
+			}
+			currentPairing++;
+		}	
+		return tp;
+	}
+	boolean warnedNumPairs = false;
+	boolean warnedNumPairsI = false;
+	/*.................................................................................................................*/
+	public TaxaPairing getPairing(Tree tree, int index) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+			return tp;
+		}
+
+		int num = tree.getNumNodeSpaces();
+		currentChoice= new int[num];
+		numChoices = new int[num];
+		currentPath = new TaxaPath[num];
+
+		maxPairs = new int[numConditions][num];
+
+		legalityCheck(tree);
+		downPass(tree, tree.getRoot());
+		numPairs = maxPairs[noPathFromBelow][ tree.getRoot()];
+		firstPairingInClade(tree.getRoot(), tree);
+
+		int count=0;
+
+		while (count< index && count<(ownerModule.limitCheckOK(count)) && nextPairingInClade(tree, tree.getRoot())!=lastChoice) {
+			if (count % 100 == 0) CommandRecord.tick("Skipping pairing " + count);
+			count++;
+		}
+		harvestPaths(tree, tree.getRoot(), tp);
+		if (tp.getNumPairs()!= numPairs && !warnedNumPairsI){
+			MesquiteMessage.println("Error: expected numpairs does not match number harvested, gP " + index + "  / " + tp.getNumPairs() + "  " + numPairs);
+			warnedNumPairsI = true;
+		}
+		currentPairing= index;
+
+		return tp;
+	}
+	/*.................................................................................................................*/
+	public int getNumPairings(Tree tree){
+		if (tree == null)
+			return 0;
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			return 0;
+		}
+
+
+		int cur = currentPairing;
+		int num = tree.getNumNodeSpaces();
+		currentChoice= new int[num];
+		numChoices = new int[num];
+		currentPath = new TaxaPath[num];
+
+		maxPairs = new int[numConditions][num];
+		legalityCheck(tree);
+		downPass(tree, tree.getRoot());
+		numPairs = maxPairs[noPathFromBelow][ tree.getRoot()];
+		firstPairingInClade(tree.getRoot(), tree);
+
+		int count=1;
+		int limit;
+		while (count<(limit = ownerModule.limitCheckOK(count)) && (nextPairingInClade(tree, tree.getRoot())!=lastChoice)) {
+			count++;
+			if (count % 10000 ==0) MesquiteMessage.println("Number of pairings so far: " + count);
+			if (count % 1000 == 0) CommandRecord.tick("Counting pairings: " + count);
+		}
+		if (count > limit) 
+			count = limit;
+
+
+		getPairing(tree, cur);
+		return count;
+
+	}
+	/*.................................................................................................................*/
+	public int getCurrentPairingNumber(){
+		return currentPairing;
+	}
+	/*.................................................................................................................*/
+	private void goUpWithNewPath(Tree tree, int node, int left, int right) {
+		if (currentPath[node]==null) 
+			currentPath[node]=new TaxaPath();
+		currentPath[node].setBase(node);
+		currentPath[left]=currentPath[node];
+		currentPath[right]=currentPath[node];
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+	/*.................................................................................................................*/
+	private void goUpWithoutPath(Tree tree, int left, int right) {
+		currentPath[left]=null;
+		currentPath[right]=null;
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+	/*.................................................................................................................*/
+	private void goUpWithPath(Tree tree, int left, int right, TaxaPath pathLeft, TaxaPath pathRight) {
+		currentPath[left]=pathLeft;
+		currentPath[right]=pathRight;
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+
+	/*.................................................................................................................*/
+	/* Go up tree, choosing pairing in clade by taking first choices wherever a choice is available*/
+	private void firstPairingInClade(int node, Tree tree) {
+		currentChoice[node]=0;
+		numChoices[node]= 1;
+
+		if (tree.nodeIsTerminal(node)) { //terminal node
+			if (currentPath[node]!=null) {
+				currentPath[node].setNode(tree, node);
+			}
+		}
+		else {  //internal node
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (currentPath[node]==null) {  //no path coming from below; thus must see if time to invent new one based at node
+				//first, calculate how many choice are at node under the conditions
+
+				/* if no path from below, then must decide whether to begin path or not.  Should begin path if |pathAcrossRoot is as good as |noPathAcrossRoot */
+				if (maxPairs[pathAcrossRoot][node] == maxPairs[noPathAcrossRoot][node]) {
+					numChoices[node] = 2;
+					goUpWithNewPath(tree,  node, left, right);
+				}
+				else { 
+					numChoices[node] = 1;
+					if (maxPairs[pathAcrossRoot][node] > maxPairs[noPathAcrossRoot][node])
+						goUpWithNewPath(tree,  node, left, right);
+					else
+						goUpWithoutPath(tree, left, right);
+				}
+			}
+			else {  //path is being passed from below because it's not null; need only to choose which side to continue with path
+				if (maxPairs[pathUpLeft][node] == maxPairs[pathUpRight][node]) {
+					numChoices[node] = 2;
+					goUpWithPath(tree, left, right, currentPath[node], null);
+				}
+				else {
+					numChoices[node]=1;
+					if (maxPairs[pathUpLeft][node] > maxPairs[pathUpRight][node]) {
+						goUpWithPath(tree, left, right, currentPath[node], null);
+					}
+					else {
+						goUpWithPath(tree, left, right, null, currentPath[node]);
+					}
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/* Go to next choice at node, and continue up tree with first pairing given that choice */
+	private   void nextChoiceAtNode(int node, Tree tree) {  //this method needs to cover only those cases in which multiple choices could arise
+		currentChoice[node]++;
+		if (tree.nodeIsInternal(node) && currentChoice[node]<numChoices[node]) {  //(terminal nodes never with choice)
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (currentPath[node]==null ) {  
+				goUpWithoutPath(tree, left, right);  //path not coming from below; only choice is to go without path
+			}
+			else if (currentPath[node].getBase()==node) {  
+				currentPath[node]=null;
+				goUpWithoutPath(tree, left, right);  //path not coming from below; only choice is to go without path
+			}
+			else {  //path is not null; need only to make next choice as to which side to continue, i.e. right side
+				goUpWithPath(tree, left, right, null, currentPath[node]);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private boolean nextPairingInClade(Tree tree, int node){
+		boolean isItLastChoice = !lastChoice;
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			//check if all above on left are at last choice; this function goes to next choice if not yet at last choice
+			if (nextPairingInClade(tree, left) == lastChoice){  //reached last choice on left clade
+				//check if all above on right are at last choice; this function goes to next choice if not yet at last choice
+				if (nextPairingInClade(tree, right) == lastChoice){ //reached last choice on right clade
+					// left and right choices exhausted, thus go to next choice at node if there is one
+					if (currentChoice[node]+1 >=numChoices[node])  //at maximum choice; return lastChoice to indicate
+						isItLastChoice = lastChoice;
+					else  // still other choices available at this node; do next one
+						nextChoiceAtNode(node, tree);
+				}
+				else {  // if right wasn't at last choice it would have been incremented within the nextPairingInClade(right) call, thus reset left back to first choice
+					isItLastChoice = !lastChoice;
+					if (currentPath[left]!=null && currentPath[left].getBase() == left)   // need to delete path based at left so it won't think it's being passed up from below
+						currentPath[left] = null;
+					firstPairingInClade(left, tree);
+				}
+			}
+		}
+		else //terminal node with one choice only
+			isItLastChoice = lastChoice;
+		return isItLastChoice;
+	}
+	/*.................................................................................................................*/
+
+	private   void harvestPaths(Tree tree, int node, TaxaPairing tp) {
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			harvestPaths(tree, left, tp);
+			harvestPaths(tree, right, tp);
+			if (currentPath[node]!=null && currentPath[node].getBase()==node) 
+				tp.addPath(currentPath[node]);
+		}
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/pairwise/PairsOneChar/PairsOneChar.java b/Source/mesquite/pairwise/PairsOneChar/PairsOneChar.java
new file mode 100644
index 0000000..3484f57
--- /dev/null
+++ b/Source/mesquite/pairwise/PairsOneChar/PairsOneChar.java
@@ -0,0 +1,550 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.pairwise.PairsOneChar;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.pairwise.lib.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class PairsOneChar extends PairMakerChars {
+	public String getName() {
+		return "Pairs Contrasting in State of One Character";
+	}
+	public String getExplanation() {
+		return "Chooses taxon pairings so as to maximize the number of pairs that are phylogenetically independent, subject to the constraint that each pair shows a contrast the states of a binary character." ;
+	}
+	TaxaPairerChars pairer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){
+		if (pairer!=null)
+			pairer.setCharacters(statesA, statesB);
+	}
+	/*.................................................................................................................*/
+	public TaxaPairer getPairer(){
+		return pairer = new OneCharTaxaPairer(this);
+	}
+	/*.................................................................................................................*/
+	public String getAuthors() {
+		return "Wayne P. Maddison";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	} 
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+/* ======================================================================== */
+/*Objects of the following class create pairings that contrast the states of a binary character.  The tree is assumed dichotomous.
+Most of the relevant code starts with the downPass (find it by searching for "!!!")
+Explanation of some basic Mesquite classes:
+-- CategoricalAdjustable stores state sets at nodes; state sets are stored as long's with bits on and off to indicate elements present in set
+-- Tree objects store node relations as integer arrays; each node is represented by a number.  The node's parent, daughter and sisters can be found
+with methods within the Tree object.  For example, tree.motherOfNode(node) is passed a node number and returns the number of the 
+parent node.
+-- TaxaPath stores a path between terminal taxa
+-- TaxaPairing stores a set of such paths (a pairing)
+ */
+/* ======================================================================== */
+class OneCharTaxaPairer extends TaxaPairerChars {
+	private CategoricalDistribution observedStates;
+	private CharacterDistribution observedStatesB;
+	private CategoricalHistory downStates;
+	private CategoricalHistory allStatesInClade;
+	private int[] stateSought;
+	private boolean[] usingFirstChoice, oneChoiceOnly;
+	private TaxaPath[] currentPath;
+	static final long set0 = 1;  //Mesquite uses long variables with bits on and off for sets; thus the set {0} has bit 0 set, translating to long integer = 1
+	static final long set01 = 3; //{0,1} has bits 0 and 1 set, translating to integer = 3
+	static final long set1 = 2; //{1} has bit 1 set, translating to integer = 2
+	boolean done = false;
+	PairMaker ownerModule = null;
+	int currentPairing=0;
+	int numPairings =0;
+	boolean countNum = true;
+	private int numPairs=0;
+
+	/*.................................................................................................................*/
+	public OneCharTaxaPairer (PairMaker ownerModule) {
+		this.ownerModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+	public  void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){  //only the first of the two characters is used
+		if (statesA instanceof CategoricalDistribution)
+			observedStates = (CategoricalDistribution)statesA;
+		else {
+			ownerModule.alert("Warning: Character X for this pair selector must be a categorical-valued character.  An error may result");
+			observedStates = null;
+		}
+		observedStatesB = statesB;
+		countNum=true;
+	}
+	public void init(){
+		countNum=true;
+	}
+	/*.................................................................................................................*/
+	/* returns the first pairing*/
+	public TaxaPairing getFirstPairing(Tree tree) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+
+		currentPairing = 0;
+		countNum = true;
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else if (observedStates != null) {
+			done=false;
+			int numNodeSpaces = tree.getNumNodeSpaces();
+			usingFirstChoice= new boolean[numNodeSpaces];
+			oneChoiceOnly = new boolean[numNodeSpaces];
+			currentPath = new TaxaPath[numNodeSpaces];
+			stateSought = new int[numNodeSpaces];
+			downStates=(CategoricalHistory)observedStates.adjustHistorySize(tree,  (CharacterHistory)downStates);
+			allStatesInClade= (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)allStatesInClade);
+			numPairs = 0;
+			legalityCheck(tree);
+			downPass(tree.getRoot(), tree);
+			firstPairingInClade(tree.getRoot(), tree);
+			harvestPaths(tree, tree.getRoot(), tp);
+			if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+				MesquiteMessage.println("Error: expected numpairs does not match number harvested, gFP" + tp.getNumPairs() + "  " + numPairs);
+				warnedNumPairs = true;
+			}
+		}
+		return tp;
+	}
+	/*.................................................................................................................*/
+	/* returns the next pairing*/
+	public TaxaPairing getNextPairing(Tree tree) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else 		if (observedStates != null) {
+			if (!done) {
+				if (!nextPairingInClade(tree, tree.getRoot())) 
+					done=true;
+				harvestPaths(tree, tree.getRoot(), tp);
+				if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+					MesquiteMessage.println("Error: expected numpairs does not match number harvested, gNP" + tp.getNumPairs() + "  " + numPairs);
+					warnedNumPairs = true;
+				}
+				currentPairing++;
+			}	
+		}
+		return tp;
+	}
+	/*.................................................................................................................*/
+	/* returns the index'th pairing*/
+	public TaxaPairing getPairing(Tree tree, int index) {
+		if (tree == null)
+			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else 		if (observedStates != null) {
+			int numNodeSpaces = tree.getNumNodeSpaces();
+			usingFirstChoice= new boolean[numNodeSpaces];
+			oneChoiceOnly = new boolean[numNodeSpaces];
+			currentPath = new TaxaPath[numNodeSpaces];
+			stateSought = new int[numNodeSpaces];
+			downStates=(CategoricalHistory)observedStates.adjustHistorySize(tree,  (CharacterHistory)downStates);
+			allStatesInClade= (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)allStatesInClade);
+			numPairs = 0;
+			legalityCheck(tree);
+			downPass(tree.getRoot(), tree);
+			firstPairingInClade(tree.getRoot(), tree);
+			int count=0;
+
+			while (count< index && count<(ownerModule.limitCheckOK(count)) && nextPairingInClade(tree, tree.getRoot())) {
+				if (count % 100 == 0) CommandRecord.tick("Skipping pairing " + count);
+				count++;
+			}
+			harvestPaths(tree, tree.getRoot(), tp);
+			if (tp.getNumPairs()!= numPairs && !warnedNumPairsI){
+				MesquiteMessage.println("Error: expected numpairs does not match number harvested, gP " + index + "  / " + tp.getNumPairs() + "  " + numPairs);
+				warnedNumPairsI = true;
+			}
+			currentPairing= index;
+		}
+		return tp;
+	}
+	boolean warnedNumPairsI = false;
+	/*.................................................................................................................*/
+	/* this is a rather sad method that cycles through all the pairings to find out how many there are.  Hopefully,
+ 	someone will invent a way to calculate this number so they don't have to be enumerated.*/
+	public int getNumPairings(Tree tree){
+		if (tree == null)
+			return 0;
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			return 0;
+		}
+		if (!countNum)
+			return numPairings;
+		else if (observedStates != null && countNum) {
+			int cur = currentPairing;
+			int numNodeSpaces = tree.getNumNodeSpaces();
+			usingFirstChoice= new boolean[numNodeSpaces];
+			oneChoiceOnly = new boolean[numNodeSpaces];
+			currentPath = new TaxaPath[numNodeSpaces];
+			stateSought = new int[numNodeSpaces];
+
+			downStates=(CategoricalHistory)observedStates.adjustHistorySize(tree,  (CharacterHistory)downStates);
+			allStatesInClade= (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)allStatesInClade);
+
+			numPairs = 0;
+			legalityCheck(tree);
+			downPass(tree.getRoot(), tree);
+			firstPairingInClade(tree.getRoot(), tree);
+
+			int count=1;
+			int limit;
+			while (count<(limit = ownerModule.limitCheckOK(count)) && nextPairingInClade(tree, tree.getRoot())) {
+				count++;
+				if (count % 10000 ==0) MesquiteMessage.println("Number of pairings so far: " + count);
+				if (count % 1000 == 0) CommandRecord.tick("Counting pairings: " + count);
+			}
+			if (count > limit) 
+				count = limit;
+
+
+			getPairing(tree, cur);
+			numPairings = count;
+			countNum=false;
+			return count;
+		}
+		else
+			return 0;
+	}
+	/*.................................................................................................................*/
+	public int getCurrentPairingNumber(){
+		return currentPairing;
+	}
+	boolean warnedNumPairs = false;
+	CharacterState stateB = null;
+	int[] legality;
+	/*.................................................................................................................*/
+	private void setLegality(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node)); // get observed state for taxon
+			if (stateB!= null)
+				stateB.setToUnassigned();
+			if (observedStatesB != null)
+				stateB =observedStatesB.getCharacterState(stateB, tree.taxonNumberOfNode(node));
+			boolean poly = false;
+			if (stateB != null && stateB instanceof CategoricalState && ((CategoricalState)stateB).cardinality()>1)
+				poly = true;
+			if (CategoricalState.isInapplicable(observed) || CategoricalState.isUnassigned(observed) ||   //indep variable missing/inapplicable
+					CategoricalState.isUncertain(observed) || CategoricalState.cardinality(observed)!=1 || //indep variable uncertain/polymorphic
+					CategoricalState.maximum(observed)>1 || //indep variable not binary
+					stateB == null || stateB.isInapplicable() || stateB.isUnassigned() || poly){  //dep variable is missing/inapplicable or (if categorical) polymorphic/uncertain.  
+				warningMessage = "Some taxa excluded (had non-binary states in the independent variable, or missing data, or polymorphic states, or uncertain states).";
+				legality[node] = MesquiteTree.ILLEGAL;
+			}
+			else
+				legality[node] = MesquiteTree.LEGAL;
+
+		}
+		else {
+			int left = tree.firstDaughterOfNode(node);  //assumes dichotomous tree, so get left and right daughter
+			int right = tree.lastDaughterOfNode(node);
+			setLegality(left, tree);
+			setLegality(right, tree);
+			if (legality[left] != MesquiteTree.ILLEGAL && legality[right] != MesquiteTree.ILLEGAL )
+				legality[node] = MesquiteTree.LEGAL;
+			else if (legality[left] != MesquiteTree.ILLEGAL || legality[right] != MesquiteTree.ILLEGAL)
+				legality[node] = MesquiteTree.SEMILEGAL;
+			else
+				legality[node] = MesquiteTree.ILLEGAL;
+		}
+	}
+	/*.................................................................................................................*/
+	private void legalityCheck(Tree tree) {
+		if (legality == null || legality.length != tree.getNumNodeSpaces())
+			legality = new int[tree.getNumNodeSpaces()];
+		for (int i = 0; i< legality.length; i++)
+			legality[i] = MesquiteTree.LEGAL;
+		warningMessage = "";
+		setLegality(tree.getRoot(), tree);
+	}
+
+	/*.................................................................................................................*/
+	/*!!!*/
+	/* This traversal from tips to roots, does parsimony "downpass" and also accumulates allStates for each clade.  allStates records, for
+	each clade, whether 0 or 1 or both are observed among the terminal taxa of the clade*/
+	private void downPass(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node)); // get observed state for taxon
+
+			downStates.setState(node, observed); //set downstate to observed
+			allStatesInClade.setState(node, observed);//set allStates to observed
+		}
+		else {
+			int left = tree.firstLegalDaughterOfNode(node, legality);  //assumes dichotomous tree, so get left and right daughter
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			downPass(left, tree);
+			downPass(right, tree);
+
+			long sRight=downStates.getState(right);  //get downpass states already calculated for right daughter
+			long sLeft=downStates.getState(left);//get downpass states already calculated for left daughter
+			if (CategoricalState.isUnassigned(sRight)){
+				downStates.setState(node, sLeft);
+				allStatesInClade.setState(node, sLeft); 
+			}
+			else if (CategoricalState.isUnassigned(sLeft)) {
+				downStates.setState(node, sRight);
+				allStatesInClade.setState(node, sRight); 
+			}
+			else {
+				long intersection = sLeft & sRight;  //intersection
+				if (intersection == 0) {
+					downStates.setState(node, sLeft | sRight); //use union if intersection empty
+					numPairs++; //count a step which must also be counting number of pairs
+				}
+				else 
+					downStates.setState(node, intersection); //use intersection if not empty
+				allStatesInClade.setState(node, allStatesInClade.getState(left) | allStatesInClade.getState(right)); // take union for states in clade
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/* The following six methods do the second traversal upward through the tree, choosing pairs by 
+	creating and continuing paths between terminal taxa. 
+	The first four methods are called when traversal needs to take the next step up the tree.  They deal with
+	three circumstances, having to do with whether a path is being passed tipward, or a new path is to be formed,
+	or no path is to be used.*/
+	private void goUpWithNewPath(Tree tree, int node, int left, int right, int seekLeft, int seekRight) {
+		if (currentPath[node]==null) 
+			currentPath[node]=new TaxaPath();
+		currentPath[node].setBase(node);
+		goUp(tree, left, right, currentPath[node], currentPath[node], seekLeft, seekRight);
+	}
+	/*.................................................................................................................*/
+	private void goUpWithoutPaths(Tree tree, int left, int right) {
+		goUp(tree, left, right, null, null, 0, 0);
+	}
+	/*.................................................................................................................*/
+	private void goUpWithPathLeft(Tree tree, int node, int left, int right) {
+		goUp(tree, left, right, currentPath[node],null, stateSought[node], 0);
+	}
+	/*.................................................................................................................*/
+	private void goUpWithPathRight(Tree tree, int node, int left, int right) {
+		goUp(tree, left, right, null, currentPath[node],0, stateSought[node]);
+	}
+	/*.................................................................................................................*/
+	private void goUp(Tree tree, int left, int right, TaxaPath pathLeft, TaxaPath pathRight, int seekLeft, int seekRight) {
+		currentPath[left]=pathLeft;
+		currentPath[right]=pathRight;
+		stateSought[left]=seekLeft;
+		stateSought[right]=seekRight;
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+	/*.................................................................................................................*/
+	/* The method firstPairingInClade traverses the tree from root to tips ("up") and chooses a pairing in the clade.  If more than one
+	choice at a node allows a maximal pairing, the first choice is made and the fact that alternatives are available is noted
+	so that the alternatives may be constructed later.  It turns out that there are at most two choices at any node for the
+	one-character contrast pairing, and so booleans instead of integers are used to record how many choices there are and what is
+	the current choice.  The method firstPairingInClade is used along with nextPairingInClade to cycle through all maximal pairings.
+	To yield the first pairing, one simply calls the downPass method, followed by firstPairingInClade beginning at the root:
+			downPass(tree.getRoot(), tree);
+			firstPairingInClade(tree.getRoot(), tree);
+	To obtain subsequent pairings, one then calls
+			nextPairingInClade(tree, tree.getRoot());
+	until nextPairingInClade returns false, indicating that there are no more pairings   */
+
+	private void firstPairingInClade(int node, Tree tree) {
+		usingFirstChoice[node]= true; //keep a record of which choice is being made (in case of alternatives)-- in this case, the first choice
+		oneChoiceOnly[node]= true; //initialize count of choices to 1 (i.e., set boolean to true)
+
+		if (tree.nodeIsTerminal(node)) { //terminal node; tie any current path to the terminal taxon
+			if (currentPath[node]!=null) 
+				currentPath[node].setNode(tree, node);
+		}
+		else {  //internal node
+			int left = tree.firstLegalDaughterOfNode(node, legality); //tree assumed dichotomous; get left and right daughter nodes
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (currentPath[node]==null) {  //no path coming from below; thus must see if time to invent new one based at node
+				if (allStatesInClade.getState(node)==set01) {	//if clade uniform: don't need to continue since no need to create paths  (*)
+					if (downStates.getState(node)==set01) {  //downstates 01 thus 0/1 or 01/01 on left and right daughters
+						if (downStates.getState(left)==set0)   //must be 1 on right; path must cross node, up left and right to allow maximal
+							goUpWithNewPath(tree, node, left, right, 0, 1);
+						else if  (downStates.getState(left)==set1) //must be 0 on left, and path must go through node
+							goUpWithNewPath(tree, node, left, right, 1, 0);
+						else 	//else must be 01 on both sides, and path can't go through node
+							goUpWithoutPaths(tree, left, right);
+					}
+					else {  //downstate at node is either {0} or {1}
+						int s, notS;  //record state in downstate in s; the other state in notS
+						if (downStates.getState(node)==set0) {  // 0 downstate
+							s = 0;
+							notS = 1;
+						}
+						else {  // 1 downstate
+							s = 1;
+							notS = 0;
+						}
+						oneChoiceOnly[node]= false;  // in each of the circumstances below there must be two choices (create path, or wait)
+						if (downStates.getState(left)==set01)  //downstate on right must be {s}
+							goUpWithNewPath(tree, node, left, right, notS, s); // seek s on right, and seek notS up left into 01
+						else if  (downStates.getState(right)==set01)//downstate on left must be {s}; must exist choice
+							goUpWithNewPath(tree, node, left, right, s, notS); // seek s on left, and seek notS up right into 01
+						else {	//else downstate must be {s} on both sides
+							if (allStatesInClade.getState(left) == set01 )   //Left side contains notS, thus could cost one pair 
+								goUpWithNewPath(tree, node, left, right, notS, s); // for first pairing
+							else if (allStatesInClade.getState(right) == set01 ) //Right side contains notS, thus could cost one pair
+								goUpWithNewPath(tree, node, left, right, s, notS); // for first pairing
+							// else is not possible: if allstates uniform would have exited above (*)
+						}
+					}
+				}
+			}
+			else {  //path is being passed from below because it's not null; need only to choose which side to continue with path
+				long setSought;
+				if (stateSought[node]==0) //first, translate integer value of state sought into set notation
+					setSought = set0;
+				else 
+					setSought = set1;
+				long nodeDownState = downStates.getState(node);
+				long leftDownState = downStates.getState(left);
+				long rightDownState = downStates.getState(right);
+				if (nodeDownState==set01) {  // 01 downstate; must choose to send path up stateSought side if there is one
+					if (leftDownState == setSought) 
+						goUpWithPathLeft(tree, node, left, right); //must send stateSought into stateSought side
+					else if (rightDownState == setSought) 
+						goUpWithPathRight(tree, node, left, right); //must send stateSought into stateSought side
+					else  {  //must be 01 downstate on both sides
+						oneChoiceOnly[node]= false;
+						goUpWithPathLeft(tree, node, left, right);//first pairing choose left side
+					}
+				}
+				else if (nodeDownState==setSought) {  // stateSought downstate; choose either side that has stateSought downstate
+					if (rightDownState == setSought && leftDownState == setSought) { //both with stateSought; choose either to send path
+						oneChoiceOnly[node]= false;
+						goUpWithPathLeft(tree, node, left, right);//first pairing choose left side
+					}
+					else if (leftDownState == setSought) 
+						goUpWithPathLeft(tree, node, left, right);   //must send stateSought into stateSought side
+					else if (rightDownState == setSought) 
+						goUpWithPathRight(tree, node, left, right); //must send stateSought into stateSought side
+				}
+				else  {  // downstate is opposite of state sought; choose either side that has stateSought in it
+					if (allStatesInClade.getState(left)==set01 && allStatesInClade.getState(right)==set01) { //both have stateSought; choose either
+						oneChoiceOnly[node]= false;
+						goUpWithPathLeft(tree, node, left, right);//first pairing choose left side
+					}
+					else if (allStatesInClade.getState(left)==set01)  //only left has stateSought; choose it for passing path up
+						goUpWithPathLeft(tree, node, left, right);
+					else if (allStatesInClade.getState(right)==set01)  //only right has stateSought; choose it for passing path up
+						goUpWithPathRight(tree, node, left, right);
+				}
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/* This method makes the next choice at node, and continues up tree with first pairing given that choice*/
+	private   void nextChoiceAtNode(int node, Tree tree) {  //this method needs to cover only those cases in which multiple choices could arise
+		usingFirstChoice[node] =false; //record that no longer using first choice
+		if (tree.nodeIsInternal(node)) {  //terminal nodes never have choice
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (currentPath[node]==null || currentPath[node].getBase()==node) {  //no path coming from below or path based at node
+				//in firstPairingInClade, every case where new path created had as second choice going up without paths; thus destroy path
+				if (currentPath[node]!=null) 
+					currentPath[node]=null;
+				if (allStatesInClade.getState(node)==set01)	//clade not uniform, thus fruitful to continue
+					goUpWithoutPaths(tree, left, right);  // every possibility with multiple choices postpones pairing and thus goes up without path
+			}
+			else {  //path is not null; need only to choose which side to continue.
+				//In each case in firstPairingInClade, left path was followed first.  Now follow right.
+				long s = downStates.getState(node);
+				if (s==set01)  // 01 downstate; must choose stateSought side if there is one
+					goUpWithPathRight(tree, node, left, right);// second pairing for case of downstate 01 both sides
+				else if ((s==set0 && stateSought[node]==0)||(s==set1 && stateSought[node]==1))  //stateSought downstate; choose either side with stateSought
+					goUpWithPathRight(tree, node, left, right);// second pairing; both with stateSought				}
+				else if ((s==set0 && stateSought[node]==1)||(s==set1 && stateSought[node]==0))  //other downstate; choose either side with stateSought in it
+					goUpWithPathRight(tree, node, left, right);// second pairing; both with stateSought
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/*This is the central method that moves through the alternative pairings.  It returns false if there are no more pairings to be made in the clade.
+	It is rather a difficult recursion to comprehend (at least to me, even though I wrote it), and is based on the Equivocal cycling 
+	recursion in MacClade 3.
+	 */
+	private boolean nextPairingInClade(Tree tree, int node){
+		boolean moreChoices = true;
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (!nextPairingInClade(tree, left)){  //try going to next pairing on left; if false then had already reached last choice on left clade
+				if (!nextPairingInClade(tree, right)){ //try going to next pairing on right; if false then had already reached last choice on right clade
+					// left and right choices exhausted, thus go to next choice at node if there is one
+					if (oneChoiceOnly[node] || usingFirstChoice[node] ==oneChoiceOnly[node])  //at maximum choice; return false to indicate choices exhausted
+						moreChoices = false;
+					else  // still other choices available at this node; do next one
+						nextChoiceAtNode(node, tree);
+				}
+				else { //if right wasn't at last choice it would have been incremented within nextPairingInClade(right), thus reset left back to first choice
+					if (currentPath[left]!=null && currentPath[left].getBase() == left)  //delete path based at left so it won't think it's being passed from below
+						currentPath[left] = null;
+					firstPairingInClade(left, tree);
+				}
+			} //else had successfully incremented left side to next choice
+		}
+		else //terminal node with one choice only
+			moreChoices = false;
+		return moreChoices;
+	}
+	/*.................................................................................................................*/
+	/* harvest all the paths and put them in the pairing*/
+	private   void harvestPaths(Tree tree, int node, TaxaPairing tp) {
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			harvestPaths(tree, left, tp);
+			harvestPaths(tree, right, tp);
+			if (currentPath[node]!=null && currentPath[node].getBase()==node) 
+				tp.addPath(currentPath[node]);
+		}
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/pairwise/PairsTwoChars/PairsTwoChars.java b/Source/mesquite/pairwise/PairsTwoChars/PairsTwoChars.java
new file mode 100644
index 0000000..a01ffd1
--- /dev/null
+++ b/Source/mesquite/pairwise/PairsTwoChars/PairsTwoChars.java
@@ -0,0 +1,755 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.pairwise.PairsTwoChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.pairwise.lib.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class PairsTwoChars extends PairMakerChars {
+	public String getName() {
+		return "Pairs Contrasting in State of Two Characters";
+	}
+	public String getExplanation() {
+		return "Chooses taxon pairings so as to maximize the number of pairs that are phylogenetically independent, subject to the constraint that each pair shows a contrast the states of both of two binary characters." ;
+	}
+	TaxaPairerChars pairer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){
+		if (pairer!=null)
+			pairer.setCharacters(statesA, statesB);
+	}
+	/*.................................................................................................................*/
+	public TaxaPairer getPairer(){
+		return pairer = new TwoCharTaxaPairer(this);
+	}
+	/*.................................................................................................................*/
+	public String getAuthors() {
+		return "Wayne P. Maddison";
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	} 
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+/* ======================================================================== 
+
+The following classes create pairings that contrast the states of two binary characters.
+The tree is assumed dichotomous.
+At present, the code is probably rather inefficient, since on the traversal back up the tree recalculates things it could
+have stored on the way down.
+
+Explanation of some basic Mesquite classes:
+-- CategoricalDistribution stores state sets at nodes; state sets are stored as long's with bits on and off to indicate elements present in set
+-- Tree objects store node relations as integer arrays; each node is represented by a number.  The node's parent, daughter and sisters can be found
+with methods within the Tree object.  For example, tree.motherOfNode(node) is passed a node number and returns the number of the 
+parent node.
+-- TaxaPath stores a path between terminal taxa
+-- TaxaPairing stores a set of such paths (a pairing)
+ */
+
+/*  ======================================================================== */
+/*Scans to see what are best conditons at node (i.e., which free path condition maximizes number of 
+pairs (i.e., whether max given no free path is better than max given free path to 01)*/
+class BestConditionsAtNode {
+	boolean[] isItBest;
+	int bestValue=0;
+	int numBest = 0;
+	/*..................................................*/
+	public BestConditionsAtNode() {
+		isItBest = new boolean[5];
+	}
+	/*..................................................*/
+	/* Scans the maximum array for a given node to store which values are highest.
+	Rather inefficiently done (sorts array first).*/
+	public void scan(int[][] max, int node) {
+		int[] q = new int[5];
+		int swap;
+		for (int i=0; i<5; i++) { //initialize results
+			q[i] = max[i][node];
+			isItBest[i] = false;
+		}
+		for (int i = 1; i < 5; i++) { //sort array
+			for (int j= i-1; j>=0 && (q[j+1]>q[j]); j--) {
+				swap = q[j+1];
+				q[j+1] = q[j];
+				q[j] = swap;
+			}
+		}
+		numBest = 1; //find out how many are best
+		for (int i = 1; i < 5; i++) {
+			if (q[i] == q[0])
+				numBest++;
+		}
+		bestValue = q[0]; //record which is best
+		for (int i = 0; i < 5; i++) {
+			if (max[i][node] == bestValue)
+				isItBest[i] = true;
+		}
+	}
+	/*..................................................*/
+	public int getBestValue() {
+		return bestValue;
+	}
+	/*..................................................*/
+	public int getNumBest() {
+		return numBest;
+	}
+	/*..................................................*/
+	public boolean isBest(int which) {
+		return isItBest[which];
+	}
+}
+/*  ======================================================================== */
+/* For a given condition at a node, e.g. given free path to 01, there are various possible combinations
+of such conditions at the two descendants left and right that could allow such a conditon to be obtained at node.
+Which of those conditions allows the maximum number of pairs?  This is the best combination of left
+and right that serves as a basis for the condition at node.  Objects of this class determine these combinations
+and store them.*/
+class BestBasisCombos {
+	int[][] bestCombos;
+	final static int maxNumCombos=9;
+	int bestValue=0;
+	int numBest = 0;
+	int[][] max;
+	public BestBasisCombos() {
+		bestCombos = new int[2][maxNumCombos];
+	}
+	public void initialize (int[][] max) {
+		this.max = max;
+		bestValue = -1;
+		numBest = 0;
+		zeroCombos();
+	}
+	public void zeroCombos() {
+		for (int i= 0; i<2; i++) for (int j = 0; j<maxNumCombos; j++) bestCombos[i][j]=0;
+	}
+	/* Checks if the combination of conditionRight and conditionLeft is one of the best for these
+	two nodes left and right, taking into consideration the supplement (possible 1 extra pair between the two clades).
+	If so, records the combination as one of the best.*/
+	public void checkIfBest(int conditionLeft, int conditionRight, int left, int right, int supplement) {
+		if (max[conditionLeft][left]>=0 && max[conditionRight][right] >=0) {  
+			//note below in downPass that max =  -1 used as indication of terminal node without states corresponding to condition
+			int t = max[conditionLeft][left] + max[conditionRight][right] + supplement;
+
+			if (t>bestValue) {
+				zeroCombos();
+				bestValue = t;
+				bestCombos[0][0] = conditionLeft;
+				bestCombos[1][0] = conditionRight;
+				numBest = 1;
+			}
+			else if (t == bestValue) {
+				bestCombos[0][numBest] = conditionLeft;
+				bestCombos[1][numBest] = conditionRight;
+				numBest++;
+			}
+		}
+	}
+	public void checkIfBest(int conditionLeft, int conditionRight, int left, int right) {
+		checkIfBest(conditionLeft, conditionRight, left, right, 0);
+	}
+	public int getBestValue() {
+		return bestValue;
+	}
+	public int getNumBest() {
+		return numBest;
+	}
+	public int getBestLeft(int which) {
+		if (which>=numBest)
+			MesquiteMessage.println("error; ask for combo beyond bounds");
+		return bestCombos[0][which];
+	}
+	public int getBestRight(int which) {
+		if (which>=numBest)
+			MesquiteMessage.println("error; ask for combo beyond bounds");
+		return bestCombos[1][which];
+	}
+}
+/*This is the class that actually supplies the pairings.*/
+/* ======================================================================== */
+class TwoCharTaxaPairer extends TaxaPairerChars {
+	int[][] max;
+	//The following are constants for the various conditions on local pairings:  there is no free path to a terminal taxon,
+	//there is a free path to a taxon with states 0 and 0 in the two characters, there is a free path to 01, etc.
+	final static int noFree = 4;
+	final static int free00 = 0;
+	final static int free01 = 1;
+	final static int free10 = 2;
+	final static int free11 = 3;
+	final static int noCondition = -1;
+	final static int numConditions = 5;
+
+	Tree tree;
+	CharacterDistribution observedStatesA; CharacterDistribution observedStatesB;
+	BestConditionsAtNode surveyOfBestConditions;
+	private int[] currentChoice, numChoices;
+	private int[] conditionSought;
+	private TaxaPath[] currentPath;
+	static final long set0 = 1;
+	static final long set01 = 3;
+	static final long set1 = 2;
+	boolean done = false;
+	PairMaker ownerModule = null;
+	int currentPairing=0;
+	BestBasisCombos bestCombos;
+	private int numPairs=0;
+
+	/* ..................................................................................................................................... */
+	public TwoCharTaxaPairer (PairMaker ownerModule) {
+		this.ownerModule = ownerModule;
+		surveyOfBestConditions = new BestConditionsAtNode();
+		bestCombos = new BestBasisCombos();
+	}
+	/* ..................................................................................................................................... */
+	public  void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB){
+		boolean warned = false;
+		if (statesA instanceof CategoricalDistribution)
+			this.observedStatesA = statesA;
+		else {
+			warned = true;
+			ownerModule.alert("Warning: both characters for this Pair Selector must be categorical. An error may result.");
+			this.observedStatesA = null;
+		}
+		if (statesB instanceof CategoricalDistribution)
+			this.observedStatesB = statesB;
+		else {
+			if (!warned)
+				ownerModule.alert("Warning: both characters for this Pair Selector must be categorical. An error may result.");
+			this.observedStatesB = null;
+		}
+	}
+	/*.................................................................................................................*/
+	public int maximum (int a, int b, int c, int d, int e) {
+		return MesquiteInteger.maximum(a,MesquiteInteger.maximum(b,MesquiteInteger.maximum(c,MesquiteInteger.maximum(d,e))));
+	}
+	/*.................................................................................................................*/
+	public TaxaPairing getFirstPairing(Tree tree) {
+ 		if (tree == null)
+ 			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		currentPairing = 0;
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else if (observedStatesA != null && observedStatesB != null) {
+			done=false;
+			int num = tree.getNumNodeSpaces();
+			currentChoice= new int[num];
+			numChoices = new int[num];
+			currentPath = new TaxaPath[num];
+			conditionSought = new int[num];
+			conditionSought[tree.getRoot()] = noCondition;
+			max = new int[numConditions][num];
+			int root = tree.getRoot();
+			legalityCheck( tree);
+			downPass(tree, root);
+			numPairs = maximum(max[noFree][root] ,max[free00][root] ,max[free01][root],max[free11][root],max[free10][root]);
+
+			firstPairingInClade(tree.getRoot(), tree);
+			harvestPaths(tree, tree.getRoot(), tp);
+			if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+				MesquiteMessage.println("Error: expected numpairs does not match number harvested, gFP" + tp.getNumPairs() + "  " + numPairs);
+				warnedNumPairs = true;
+			}
+		}
+		return tp;
+	}
+	/*.................................................................................................................*/
+	public TaxaPairing getNextPairing(Tree tree) {
+ 		if (tree == null)
+ 			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else if (observedStatesA != null && observedStatesB != null) {
+			if (!done) {
+				if (!nextPairingInClade(tree, tree.getRoot())) 
+					done=true;
+				harvestPaths(tree, tree.getRoot(), tp);
+				if (tp.getNumPairs()!= numPairs && !warnedNumPairs){
+					MesquiteMessage.println("Error: expected numpairs does not match number harvested, gNP" + tp.getNumPairs() + "  " + numPairs);
+					warnedNumPairs = true;
+				}
+				currentPairing++;
+			}	
+		}
+		return tp;
+	}
+	boolean warnedNumPairs = false;
+	boolean warnedNumPairsI = false;
+	/*.................................................................................................................*/
+	public TaxaPairing getPairing(Tree tree, int index) {
+ 		if (tree == null)
+ 			return null;
+		TaxaPairing tp = new TaxaPairing(tree.getNumTaxa());
+		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			tp.setCalculationNotDone(true);
+		}
+		else if (observedStatesA != null && observedStatesB != null) {
+			int num = tree.getNumNodeSpaces();
+			currentChoice= new int[num];
+			numChoices = new int[num];
+			currentPath = new TaxaPath[num];
+
+			max = new int[numConditions][num];
+
+			int root = tree.getRoot();
+			legalityCheck(tree);
+			downPass(tree, root);
+			numPairs = maximum(max[noFree][root] ,max[free00][root] ,max[free01][root],max[free11][root],max[free10][root]);
+			firstPairingInClade(tree.getRoot(), tree);
+
+			int count=0;
+
+			while (count< index && count<(ownerModule.limitCheckOK(count)) && nextPairingInClade(tree, tree.getRoot())) {
+				if (count % 100 == 0) CommandRecord.tick("Skipping pairing " + count);
+				count++;
+			}
+			harvestPaths(tree, tree.getRoot(), tp);
+			if (tp.getNumPairs()!= numPairs && !warnedNumPairsI){
+				MesquiteMessage.println("Error: expected numpairs does not match number harvested, gP " + index + "  / " + tp.getNumPairs() + "  " + numPairs);
+				warnedNumPairsI = true;
+			}
+			currentPairing= index;
+		}
+		return tp;
+	}
+ 	public void init(){
+	}
+	/*.................................................................................................................*/
+	/* this is a rather sad method that cycles through all the pairings to find out how many there are.  Hopefully,
+ 	someone will invent a way to calculate this number so they don't have to be enumerated.*/
+	public int getNumPairings(Tree tree){
+ 		if (tree == null)
+ 			return 0;
+ 		if (tree.hasPolytomies(tree.getRoot())){
+			warningMessage = "The tree has polytomies; pairwise comparisons cannot be done";
+			return 0;
+		}
+		else if (observedStatesA != null && observedStatesB != null) {
+			int cur = currentPairing;
+			int num = tree.getNumNodeSpaces();
+			currentChoice= new int[num];
+			numChoices = new int[num];
+			currentPath = new TaxaPath[num];
+
+			max = new int[numConditions][num];
+			int root = tree.getRoot();
+			legalityCheck(tree);
+			downPass(tree, root);
+			numPairs = maximum(max[noFree][root] ,max[free00][root] ,max[free01][root],max[free11][root],max[free10][root]);
+			firstPairingInClade(tree.getRoot(), tree);
+
+			int count=1;
+			int limit;
+			while (count<(limit = ownerModule.limitCheckOK(count)) && nextPairingInClade(tree, tree.getRoot())) {
+				count++;
+				if (count % 10000 ==0) MesquiteMessage.println("Number of pairings so far: " + count);
+				if (count % 1000 == 0) CommandRecord.tick("Counting pairings: " + count);
+			}
+			if (count > limit) 
+				count = limit;
+
+
+			getPairing(tree, cur);
+			return count;
+		}
+		else
+			return 0;
+
+	}
+	/*.................................................................................................................*/
+	public int getCurrentPairingNumber(){
+		return currentPairing;
+	}
+	/* ..................................................................................................................................... */
+	/* At node with daughters left and right, finds the maximum number of pairs given the condition,
+	and stores the profile of the basis combinations in the "best" object for later use.
+	Under each condition, it needs to check all of the conditions at left and right that would yield the input condition.
+	For instance, consider the first condition (condition == noFree):
+		There are five ways to achieve no free path:  Either there are no free paths
+		up left or right, or there are free paths on both sides, but they are such that they allow a new path
+		to cross the root (hence the supplement of 1).  There are four ways that allow this -- free01 in left and free10 in right,
+		and three others.
+	 */
+	private int calculateBestGiven(int condition, int left, int right, BestBasisCombos best) {
+		best.initialize(max);
+
+		if (condition == noFree) { //
+			best.checkIfBest(noFree, noFree, left, right);
+			best.checkIfBest(free01, free10, left, right, 1);
+			best.checkIfBest(free10, free01, left, right, 1);
+			best.checkIfBest(free00, free11, left, right, 1);
+			best.checkIfBest(free11, free00, left, right, 1);
+			return best.getBestValue();
+		}
+		else if (condition == free00) {
+			best.checkIfBest(free00, noFree, left, right);
+			best.checkIfBest(free00, free00, left, right);
+			best.checkIfBest(free00, free01, left, right);
+			best.checkIfBest(free00, free11, left, right);
+			best.checkIfBest(free00, free10, left, right);
+			best.checkIfBest(noFree, free00, left, right);
+			best.checkIfBest(free01, free00, left, right);
+			best.checkIfBest(free10, free00, left, right);
+			best.checkIfBest(free11, free00, left, right);
+			return best.getBestValue();
+		}
+		else if (condition == free01) {
+			best.checkIfBest(free01, noFree, left, right);
+			best.checkIfBest(free01, free00, left, right);
+			best.checkIfBest(free01, free01, left, right);
+			best.checkIfBest(free01, free11, left, right);
+			best.checkIfBest(free01, free10, left, right);
+			best.checkIfBest(noFree, free01, left, right);
+			best.checkIfBest(free00, free01, left, right);
+			best.checkIfBest(free10, free01, left, right);
+			best.checkIfBest(free11, free01, left, right);
+			return best.getBestValue();
+		}
+		else if (condition == free11) {
+			best.checkIfBest(free11, noFree, left, right);
+			best.checkIfBest(free11, free00, left, right);
+			best.checkIfBest(free11, free01, left, right);
+			best.checkIfBest(free11, free11, left, right);
+			best.checkIfBest(free11, free10, left, right);
+			best.checkIfBest(noFree, free11, left, right);
+			best.checkIfBest(free01, free11, left, right);
+			best.checkIfBest(free10, free11, left, right);
+			best.checkIfBest(free00, free11, left, right);
+			return best.getBestValue();
+		}
+		else if (condition == free10) {
+			best.checkIfBest(free10, noFree, left, right);
+			best.checkIfBest(free10, free00, left, right);
+			best.checkIfBest(free10, free01, left, right);
+			best.checkIfBest(free10, free11, left, right);
+			best.checkIfBest(free10, free10, left, right);
+			best.checkIfBest(noFree, free10, left, right);
+			best.checkIfBest(free01, free10, left, right);
+			best.checkIfBest(free00, free10, left, right);
+			best.checkIfBest(free11, free10, left, right);
+			return best.getBestValue();
+		}
+		return 0;
+	}
+	boolean warnedOne = false;
+	static boolean staticwarnedOne = false;
+	int[] legality;
+	/*.................................................................................................................*/
+	private void setLegality(int node, Tree tree) {
+		if (tree.nodeIsTerminal(node)) {
+			long stateA =((CategoricalDistribution)observedStatesA).getState(tree.taxonNumberOfNode(node)); //get observed states
+			long stateB =((CategoricalDistribution)observedStatesB).getState(tree.taxonNumberOfNode(node));
+			if (CategoricalState.isUnassigned(stateA) || CategoricalState.isUnassigned(stateB) ||  //either of the two characters is missing data
+					CategoricalState.isInapplicable(stateA) || CategoricalState.isInapplicable(stateB) || //either of the two characters is inapplicable
+					CategoricalState.cardinality(stateA)!=1 || CategoricalState.cardinality(stateB)!=1 ||//either of the two characters is polymorphic/uncertain
+					(CategoricalState.maximum(stateA)>1))  //the independent variable is non-binary
+				legality[node] = MesquiteTree.ILLEGAL;
+			else
+				legality[node] = MesquiteTree.LEGAL;
+			if (legality[node] == MesquiteTree.ILLEGAL)
+				warningMessage = "Some taxa excluded (had non-binary states in the independent variable, or missing data, or polymorphic states, or uncertain states).";
+
+		}
+		else {
+			int left = tree.firstDaughterOfNode(node);  //assumes dichotomous tree, so get left and right daughter
+			int right = tree.lastDaughterOfNode(node);
+			setLegality(left, tree);
+			setLegality(right, tree);
+			if (legality[left] != MesquiteTree.ILLEGAL && legality[right] != MesquiteTree.ILLEGAL )
+				legality[node] = MesquiteTree.LEGAL;
+			else if (legality[left] != MesquiteTree.ILLEGAL || legality[right] != MesquiteTree.ILLEGAL)
+				legality[node] = MesquiteTree.SEMILEGAL;
+			else
+				legality[node] = MesquiteTree.ILLEGAL;
+		}
+	}
+	/*.................................................................................................................*/
+	private void legalityCheck(Tree tree) {
+		if (legality == null || legality.length != tree.getNumNodeSpaces())
+			legality = new int[tree.getNumNodeSpaces()];
+		for (int i = 0; i< legality.length; i++)
+			legality[i] = MesquiteTree.LEGAL;
+		warningMessage = "";
+		setLegality(tree.getRoot(), tree);
+	}
+	/* ..................................................................................................................................... */
+	/* This tree traversal from tips to root ("down") calculates the maximum numbers of pairs given various conditions at each node. */
+	private void downPass(Tree tree, int node) {
+		for (int daughter = tree.firstLegalDaughterOfNode(node, legality); tree.nodeExists(daughter); daughter = tree.nextLegalSisterOfNode(daughter, legality))
+			downPass(tree, daughter);
+		if (tree.nodeIsInternal(node)) {  //internal node
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			for (int i=0; i<numConditions; i++) 
+				max[i][node] = calculateBestGiven(i, left, right, bestCombos); //calculate maximum under each condition
+		}
+		else { //terminal node
+			long stateA =((CategoricalDistribution)observedStatesA).getState(tree.taxonNumberOfNode(node)); //get observed states
+			long stateB =((CategoricalDistribution)observedStatesB).getState(tree.taxonNumberOfNode(node));
+			
+			max[noFree][node] = -1;
+			max[free00][node] = -1;
+			max[free01][node] = -1;
+			max[free11][node] = -1;
+			max[free10][node]= -1;
+
+//			for (int i=0; i<numConditions; i++) //initialize to -1 (so as to know that observed states don't match these conditions)
+//			max[i][node] = -1;
+			if (stateA == set0) {  //set according to observed states
+				if (stateB == set0)
+					max[free00][node] = 0;
+				else if (stateB== set1) 
+					max[free01][node] = 0;
+			}
+			else if (stateA== set1) {
+				if (stateB== set0)
+					max[free10][node] = 0;
+				else if (stateB== set1) 
+					max[free11][node] = 0;
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/* takes the second tree traversal one more step up, creating new path and seeking the given states
+	on left and right sides*/
+	private void goUpWithNewPath(Tree tree, int node, int left, int right, int seekLeft, int seekRight) {
+		if (currentPath[node]==null) 
+			currentPath[node]=new TaxaPath();
+		currentPath[node].setBase(node);
+		currentPath[left]=currentPath[node];
+		currentPath[right]=currentPath[node];
+		conditionSought[left]=seekLeft;
+		conditionSought[right]=seekRight;
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+	/*.................................................................................................................*/
+	/* takes the second tree traversal one more step up, without any path*/
+	private void goUpWithoutPath(Tree tree, int left, int right, int seekLeft, int seekRight) {
+		currentPath[left]=null;
+		currentPath[right]=null;
+		conditionSought[left]=seekLeft;
+		conditionSought[right]=seekRight;
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+	/*.................................................................................................................*/
+	/* takes the second tree traversal one more step up, creating new path and seeking the given states
+	on left and right sides*/
+	private void goUpWithPath(Tree tree, int left, int right, TaxaPath pathLeft, TaxaPath pathRight, int statesToBeSought) {
+		currentPath[left]=pathLeft;
+		currentPath[right]=pathRight;
+		if (pathLeft == null) {
+			conditionSought[right]=statesToBeSought;
+			conditionSought[left]=noCondition;
+		}
+		else {
+			conditionSought[left]=statesToBeSought;
+			conditionSought[right]=noCondition;
+		}
+		firstPairingInClade(left, tree);
+		firstPairingInClade(right, tree);
+	}
+
+	/*.................................................................................................................*/
+	/* The method firstPairingInClade traverses the tree from root to tips ("up") and chooses a pairing in the clade.  If more than one
+	choice at a node allows a maximal pairing, the first choice is made and the fact that alternatives are available is noted
+	so that the alternatives may be constructed later.  The array numChoices used to record how many choices there are and 
+	the array currentChoice records what is the current choice.  
+	The method firstPairingInClade is used along with nextPairingInClade to cycle through all maximal pairings.
+	To yield the first pairing, one simply calls the downPass method, followed by firstPairingInClade beginning at the root:
+			downPass(tree.getRoot(), tree);
+			firstPairingInClade(tree.getRoot(), tree);
+	To obtain subsequent pairings, one then calls
+			nextPairingInClade(tree, tree.getRoot());
+	until nextPairingInClade returns false, indicating that there are no more pairings   */
+	private void firstPairingInClade(int node, Tree tree) {
+		currentChoice[node]=0; //0th choice is first one
+		numChoices[node]= 1; //initialize number of choices to 1 (may be more found later)
+		if (tree.nodeIsTerminal(node)) { //terminal node
+			if (currentPath[node]!=null)  //if path is being passed, attach it to the terminal taxon
+				currentPath[node].setNode(tree, node);
+		}
+		else {  //internal node
+			int left = tree.firstLegalDaughterOfNode(node, legality); //tree assumed dichotomous; get left and right daughter nodes
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			surveyOfBestConditions.scan(max, node); //scan the max array made on the downpass to find what conditions are best
+			if (currentPath[node]==null) {  //no path coming from below; thus must see if time to invent new one based at node
+				if (surveyOfBestConditions.getBestValue()!=0) {	//if clade uniform don't need to continue since no path being carried up
+					//first, calculate how many choices are at node under the conditions
+					numChoices[node]= 0;
+					if (conditionSought[node] != noCondition) { //(*) conditon imposed; calculate best you can do and find out how many choices are available in the basis
+						calculateBestGiven(conditionSought[node], left, right, bestCombos);  
+						numChoices[node]+= bestCombos.getNumBest();		
+					}
+					else { //no condition imposed, thus find the unconditionally best situations and add up how many choices total
+						for (int condition = 0; condition<numConditions; condition++) {
+							if (surveyOfBestConditions.isBest(condition)) { 
+								calculateBestGiven(condition, left, right, bestCombos);  
+								numChoices[node]+= bestCombos.getNumBest();		
+							}
+						}
+					}
+					// now go to first choice (number 0) by setting current to -1; in nextChoiceAtNode will increment to 0
+					currentChoice[node]= -1;
+					nextChoiceAtNode(node, tree);
+				}
+			}
+			else {  //path is being passed from below; need only to choose which side to continue with path
+				// Need to find best arrangements with free path of states sought, and pass along side with appropriate free path
+
+				//first, calculate how many choice are at node under the conditions
+				calculateBestGiven(conditionSought[node], left, right, bestCombos);  // in bestCombos will now be stored combos that gave maxima
+				int goLeft = 0;
+				int goRight = 0;
+				for (int combo = 0; combo<bestCombos.getNumBest(); combo++) {
+					if (bestCombos.getBestLeft(combo) == conditionSought[node]) //condition sought by path is compatible with left
+						goLeft = 1;
+					if (bestCombos.getBestRight(combo) == conditionSought[node]) //condition sought by path is compatible with right
+						goRight = 1;
+				}
+				numChoices[node] = goLeft + goRight; //1 will have been placed if left or right is good
+				if (goLeft ==1) //if left is possible, go there first (if more than one choice, right will be visited later)
+					goUpWithPath(tree, left, right, currentPath[node], null, conditionSought[node]);
+				else
+					goUpWithPath(tree, left, right, null, currentPath[node], conditionSought[node]); //otherwise go up right
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	/* This method makes the next choice at node, and continues up tree with first pairing given that choice*/
+	private   void nextChoiceAtNode(int node, Tree tree) {  //this method needs to cover only those cases in which multiple choices could arise
+		currentChoice[node]++; //going to next choice
+		if (tree.nodeIsInternal(node) && currentChoice[node]<numChoices[node]) {  //terminal nodes never with choice; make sure haven't run out of choices
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (currentPath[node]==null || currentPath[node].getBase()==node) {  //no path or path based at this node
+				currentPath[node] = null; //initialize path to null (may recreate new path)
+				/* first, have to find which conditon and left-right basis combination corresponds to current choice.  Pretty inefficient, this.*/
+				int whichCondition;
+				int whichCombo;
+				if (conditionSought[node] != noCondition) {
+					whichCondition = conditionSought[node];  //a particular condition is being sought, thus constrained to one set of choices (see (*) in firstPairingInClade)
+					whichCombo = currentChoice[node];
+				}
+				else {  /*no condition sought; thus have to cycle through the good conditions.  For instance, if we are seeking currentChoice number 8,
+					and condition 0 supplies 3 choices, condition 1 supplies 1 choice, and condition 2 supplies 2 choices, and conditon 3 supplies 4 choices,
+					then the 8th choice overall correspondes to the second choice of condition 3 (whichCondition = 3, whichCombo = 1 since first combo is numbered 0)*/
+					whichCondition = -5;
+					whichCombo = 0;
+					int choices = 0;
+					surveyOfBestConditions.scan(max, node);
+					for (int condition = 0; condition<numConditions && whichCondition<0; condition++) {
+						if (surveyOfBestConditions.isBest(condition)) { //if free-path condition at node is one of the ones that allows maximum number of pairs
+							calculateBestGiven(condition, left, right, bestCombos);  //calculate best combos at left and right that give such a condition
+							int previousChoices = choices;
+							choices+= bestCombos.getNumBest();   // how many combinations give the condition best?; keep running total of number of choices
+							if (choices>currentChoice[node]) {  //choicecount has surpassed current choice, thus, have found condition and combo to use for current choice
+								whichCondition = condition;
+								whichCombo = currentChoice[node]-previousChoices;
+							}
+						}	
+					}
+				}
+
+				calculateBestGiven(whichCondition, left, right, bestCombos);  // in bestCombos will now be stored combos that gave maxima
+				int bestLeft = bestCombos.getBestLeft(whichCombo);  
+				int bestRight = bestCombos.getBestRight(whichCombo);
+
+				// now have found the best combination of left and right conditions corresponding to this choice.
+				if (whichCondition != noFree) // there is a free path, hence can't make new path since that would cover the root of the clade and close the free path
+					goUpWithoutPath(tree, left, right, bestLeft, bestRight);
+				else if (bestLeft == noFree && bestRight == noFree) { //no free paths up either side, therefore continue without path
+					goUpWithoutPath(tree, left, right, bestLeft, bestRight);
+				}
+				else // there is no free path, and it's not because no free paths on either side.  Thus must be because path crosses root of clade.  Make it.
+					goUpWithNewPath(tree, node, left, right, bestLeft, bestRight);
+			}
+			else {  //path is not null; need only to make next choice as to which side to continue
+				goUpWithPath(tree, left, right, null, currentPath[node], conditionSought[node]);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/*This is the central method that moves through the alternative pairings.  It returns false if there are no more pairings to be made in the clade.
+	It is rather a difficult recursion to comprehend (at least to me, even though I wrote it), and is based on the Equivocal cycling 
+	recursion in MacClade 3.
+	 */
+	private boolean nextPairingInClade(Tree tree, int node){
+		boolean moreChoices = true;
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			if (!nextPairingInClade(tree, left)){  //try going to next pairing on left; if false then had already reached last choice on left clade
+				if (!nextPairingInClade(tree, right)){ //try going to next pairing on right; if false then had already reached last choice on right clade
+					// left and right choices exhausted, thus go to next choice at node if there is one
+					if (currentChoice[node]+1 >=numChoices[node])  //at maximum choice; thus return false to indicate choices exhausted
+						moreChoices = false;
+					else  // still other choices available at this node; do next one
+						nextChoiceAtNode(node, tree);
+				}
+				else {   // if right wasn't at last choice it would have been incremented within the nextPairingInClade(right) call, thus reset left back to first choice
+					if (currentPath[left]!=null && currentPath[left].getBase() == left)   // need to delete path based at left so it won't think it's being passed up from below
+						currentPath[left] = null;
+					firstPairingInClade(left, tree);
+				}
+			}//else had successfully incremented left side to next choice
+		}
+		else //terminal node with one choice only
+			moreChoices = false;
+		return moreChoices;
+	}
+	/*.................................................................................................................*/
+	/* harvest all the paths and put them in the pairing*/
+	private   void harvestPaths(Tree tree, int node, TaxaPairing tp) {
+		if (tree.nodeIsInternal(node)) {
+			int left = tree.firstLegalDaughterOfNode(node, legality);
+			int right = tree.lastLegalDaughterOfNode(node, legality);
+			harvestPaths(tree, left, tp);
+			harvestPaths(tree, right, tp);
+			if (currentPath[node]!=null && currentPath[node].getBase()==node) 
+				tp.addPath(currentPath[node]);
+		}
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/pairwise/PairwiseComparison/PairwiseComparison.java b/Source/mesquite/pairwise/PairwiseComparison/PairwiseComparison.java
new file mode 100644
index 0000000..9a5d503
--- /dev/null
+++ b/Source/mesquite/pairwise/PairwiseComparison/PairwiseComparison.java
@@ -0,0 +1,1026 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.pairwise.PairwiseComparison;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.pairwise.lib.*;
+
+/* ======================================================================== */
+public class PairwiseComparison extends TreeDisplayAssistantMA {
+	public String getName() {
+		return "Pairwise Comparison";
+	}
+	
+	/*  BUGS
+	 * cut taxa from tree; labels remain
+	 * 
+	 * 
+	 * 
+	 * 
+	 * *
+	 */
+	
+	
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Performs pairwise comparison character correlation tests. Phylogenetically independent pairs are chosen, and the states of two binary characters are compared to see if they are correlated among these pairs." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(PairMaker.class, "Pairwise Comparisons needs to choose which method is used for selecting pairs.",
+		"You can request the method for selecting pairs when Pairwise Comparisons starts, or later under the Pair Selector submenu.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, "Pairwise Comparisons needs to a sources of categorical characters on which to examine correlation.",
+		"You can request the source of characters (both independent and dependent) when Pairwise Comparisons starts, or later under the Character Source submenu.");
+		//e.setAsEntryPoint(true);
+	}
+	/*.................................................................................................................*/
+	Vector pairDisplayers;
+	PairMaker pairSelectorTask;
+	public Taxa currentTaxa=null;
+	public int currentCharA=0;
+	public int currentCharB=1;
+	int currentPairing = 0;
+	public MesquiteBoolean showStates;
+	int initialOffsetX = MesquiteInteger.unassigned;
+	int initialOffsetY = MesquiteInteger.unassigned;
+	public CharSourceCoordObed characterSourceTaskA, characterSourceTaskB;
+	MesquiteString pairSelectorName;
+	MesquiteCommand pstC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		showStates = new MesquiteBoolean(true);
+		pairDisplayers = new Vector();
+		pairSelectorTask= (PairMaker)hireEmployee(PairMaker.class, "Method to select pairs");
+		if (pairSelectorTask == null)
+			return sorry(getName() + " couldn't start because no pair selector module obtained.");
+		pairSelectorName = new MesquiteString(pairSelectorTask.getName());
+		pstC = makeCommand("setPairSelector",  this);
+		pairSelectorTask.setHiringCommand(pstC);
+		if (numModulesAvailable(PairMaker.class)>1){
+			MesquiteSubmenuSpec msPM = addSubmenu(null, "Pair selector", pstC, PairMaker.class);
+			msPM.setSelected(pairSelectorName);
+		}
+		characterSourceTaskA = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of independent (first) character");
+		if (characterSourceTaskA == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		characterSourceTaskB = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class,"Source of dependent (second) character");
+		if (characterSourceTaskB == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained");
+		makeMenu("Pairs");
+		addMenuItem( "Next Character (Indep.)", makeCommand("nextCharacterA",  this));
+		addMenuItem( "Previous Character (Indep.)", makeCommand("previousCharacterA",  this));
+		addMenuItem( "Next Character (Dep.)", makeCommand("nextCharacterB",  this));
+		addMenuItem( "Previous Character (Dep.)", makeCommand("previousCharacterB",  this));
+		addMenuItem( "-", null);
+		addMenuItem( "Next Pairing", makeCommand("nextPairing",  this));
+		addCheckMenuItem(null, "Show states", MesquiteModule.makeCommand("showStates",  this), showStates);
+		addMenuItem( "Close Pairwise Comparison", makeCommand("closeShowPairs",  this));
+		addMenuItem( "-", null);
+		resetContainingMenuBar();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTaskA || employee == characterSourceTaskB)  // character source quit and none rehired automatically
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		PairwiseDisplayer newDisplayer = new PairwiseDisplayer(this, treeDisplay, 0);
+		currentTaxa=treeDisplay.getTaxa();
+		characterSourceTaskA.initialize(currentTaxa);
+		characterSourceTaskB.initialize(currentTaxa);
+		characterSourceTaskA.getNumberOfCharacters(currentTaxa);
+		characterSourceTaskB.getNumberOfCharacters(currentTaxa);
+		newDisplayer.initiate();
+		pairDisplayers.addElement(newDisplayer);
+		return newDisplayer;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("requireCalculate"); 
+		temp.addLine("showStates " + showStates.toOffOnString()); 
+		temp.addLine("setPairSelector " , pairSelectorTask);
+		temp.addLine("getCharacterSourceA " , characterSourceTaskA);
+		temp.addLine("getCharacterSourceB " , characterSourceTaskB);
+		temp.addLine("setCharacterA " + CharacterStates.toExternal(currentCharA));
+		temp.addLine("setCharacterB " + CharacterStates.toExternal(currentCharB));
+		temp.addLine("setPairing " + (currentPairing+1) );
+		PairwiseDisplayer tco = (PairwiseDisplayer)pairDisplayers.elementAt(0);
+		if (tco!=null && tco.legend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.legend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.legend.getOffsetY());
+		}
+		temp.addLine("calculate");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	boolean requireCalculate = false;
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Goes to next pairing", null, commandName, "nextPairing")) {
+			nextPairingAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial horizontal offset of the legend", "[offset]", commandName, "setInitialOffsetX")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Sets the initial vertical offset of the legend", "[offset]", commandName, "setInitialOffsetY")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which pairing is shown", "[pairing number]", commandName, "setPairing")) {
+			int index = MesquiteInteger.fromFirstToken(arguments, pos); //pairing numbers are 0 based internally, 1 based externally
+			if (MesquiteInteger.isCombinable(index)) {
+				if (index == 0) //to accomodate old scripts
+					index = 1;
+				currentPairing = index;
+				setPairingAllOperators(index-1);
+				if (MesquiteThread.isScripting())
+					resetAllOperators();
+			}
+		}
+		/*else if (checker.compare(this.getClass(), nullxxx, null, commandName, "numPairings")) {
+			numPairingsAllOperators();
+    	 	}
+		 */
+		else if (checker.compare(this.getClass(), "Sets whether or not the states used as the basis for the pairing and tests are shown at the tips of the tree", "[on or off]", commandName, "showStates")) {
+			showStates.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module used to select pairs of taxa", "[name of module]", commandName, "setPairSelector")) {
+			PairMaker temp =  (PairMaker)replaceEmployee(PairMaker.class, arguments, "Method to choose pairs", pairSelectorTask);
+			if (temp!=null) {
+				pairSelectorTask=  temp;
+				pairSelectorTask.setHiringCommand(pstC);
+				pairSelectorName.setValue(pairSelectorTask.getName());
+				if (!MesquiteThread.isScripting()){
+					resetAllOperators();
+					parametersChanged();
+				}
+			}
+			return pairSelectorTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSourceA")) {//temporary, for data files using old system without coordinators
+			return characterSourceTaskA.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters A", null, commandName, "getCharacterSourceA")) {
+			return characterSourceTaskA;
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSourceB")) {//temporary, for data files using old system without coordinators
+			return characterSourceTaskB.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters B", null, commandName, "getCharacterSourceB")) {
+			return characterSourceTaskB;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next independent variable", null, commandName, "nextCharacterA")) {
+			if (currentCharA >= characterSourceTaskA.getNumberOfCharacters(currentTaxa)-1)
+				currentCharA=0;
+			else
+				currentCharA++;
+			setPairingAllOperators(0);
+			if (!MesquiteThread.isScripting())
+				resetAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous independent variable", null, commandName, "previousCharacterA")) {
+			if (currentCharA<=0)
+				currentCharA=characterSourceTaskA.getNumberOfCharacters(currentTaxa)-1;
+			else
+				currentCharA--;
+			setPairingAllOperators(0);
+			if (!MesquiteThread.isScripting())
+				resetAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Sets which character is used as independent variable", null, commandName, "setCharacterA")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromFirstToken(arguments, pos));
+			if ((ic>=0) && (ic<=characterSourceTaskA.getNumberOfCharacters(currentTaxa)-1)) {
+				currentCharA = ic;
+				setPairingAllOperators(0);
+				if (!MesquiteThread.isScripting())
+					resetAllOperators();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next dependent variable", null, commandName, "nextCharacterB")) {
+			if (currentCharB >= characterSourceTaskB.getNumberOfCharacters(currentTaxa)-1)
+				currentCharB=0;
+			else
+				currentCharB++;
+			setPairingAllOperators(0);
+			if (!MesquiteThread.isScripting())
+				resetAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous dependent variable", null, commandName, "previousCharacterB")) {
+			if (currentCharB<=0)
+				currentCharB=characterSourceTaskB.getNumberOfCharacters(currentTaxa)-1;
+			else
+				currentCharB--;
+			setPairingAllOperators(0);
+			if (!MesquiteThread.isScripting())
+				resetAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Sets which character is used as dependent variable", null, commandName, "setCharacterB")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromFirstToken(arguments, pos));
+			if ((ic>=0) && (ic<=characterSourceTaskB.getNumberOfCharacters(currentTaxa)-1)) { //TODO: should use external char numbers
+				currentCharB = ic;
+				setPairingAllOperators(0);
+				if (!MesquiteThread.isScripting())
+					resetAllOperators();
+			}
+		}    	 	
+		else if (checker.compare(this.getClass(), "For scripting", null, commandName, "requireCalculate")) {
+			requireCalculate = true;
+		}
+		else if (checker.compare(this.getClass(), "Requests calculations", null, commandName, "calculate")) {
+			requireCalculate = false;
+			resetAllOperators();
+		}
+		else if (checker.compare(this.getClass(), "Turn off pairwise comparison", null, commandName, "closeShowPairs")) {
+			iQuit();
+			resetContainingMenuBar();
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	long lastID = -1;
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (MesquiteThread.isScripting())
+			return;
+		if (notification != null){
+			if (lastID == notification.getID())
+				return;
+			lastID = notification.getID();
+		}
+		resetAllOperators();
+		outputInvalid();
+	}
+	/*.................................................................................................................*/
+	public void resetAllOperators() {
+		Enumeration e = pairDisplayers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+				tCO.initiate();
+				tCO.reset();
+				currentPairing = tCO.getPairing();
+			}
+		}
+	}
+	public String purposeOfEmployee(MesquiteModule employee){
+		if (employee == characterSourceTaskA)
+			return "for independent character for pairwise comparison";
+		else if (employee == characterSourceTaskB)
+			return "for dependent character for pairwise comparison";
+		else
+			return "for pairwise comparison";
+	}
+	public String nameForWritableResults(){
+		
+		return "Pairwise Comparisons";
+	}
+	
+	public boolean suppliesWritableResults(){
+		return true;
+	}
+	public Object getWritableResults(){
+		String results = "";
+		Enumeration e = pairDisplayers.elements();
+		
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+				if (results.length() > 0)
+					 results += "\t";
+				results += tCO.getWritableText(); 
+			}
+		}
+		
+		return results;
+	}
+	/*.................................................................................................................*/
+	public void setPairingAllOperators(int index) {
+		Enumeration e = pairDisplayers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+				tCO.setPairing(index);
+				currentPairing = tCO.getPairing();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void nextPairingAllOperators() {
+		Enumeration e = pairDisplayers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+				tCO.nextPairing();
+				currentPairing = tCO.getPairing();
+			}
+		}
+	}
+
+	/*.................................................................................................................
+ 	public void numPairingsAllOperators() {
+		Enumeration e = pairDisplayers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+	 			//System.out.println(tCO.numPairings());
+	 		}
+		}
+	}
+
+ 	/*.................................................................................................................*/
+	public void endJob() {
+		Enumeration e = pairDisplayers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PairwiseDisplayer) {
+				PairwiseDisplayer tCO = (PairwiseDisplayer)obj;
+				tCO.turnOff();
+			}
+		}
+		pairDisplayers.removeAllElements();
+		super.endJob();
+	}
+	public boolean isPrerelease(){
+		return false;
+	} 
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+/*Assumes binary & dichotomous.  On way down, store downstates and allstatesInClade.  On way up, pass forward Path objects and state sought.  Each Path object should store
+two taxa which it should decide once it gets to tips.  A new Path object is formed each time an open clade is created by a lack of committed path sought
+rising from below.  At each internal node must be stored the current choice at that internal node and the list of choices possible,
+ so that all possible choices can be cycled through.  A choice is whether to continue Path up right or left if one is coming from below, or, if none
+ is coming up, whether a path can be started (which it always can be 
+ ======================================================================== */
+class PairwiseDisplayer extends TreeDisplayDrawnExtra {
+	public TaxaPairing pairing;
+	TaxaPairerChars pairer;
+	public ShowPairsLegend legend;
+	private double pMax = 0;
+	private double pMin = 1;
+	public CharacterDistribution observedStatesA, observedStatesB;
+	private int numPairings;
+	private int numCharsA, numCharsB;
+	Color[] colors;
+	LabelsAtNodes labelsAtNodes;
+	private int[] cat;
+	PairwiseComparison pairModule;
+	static final int POSITIVE = 1;
+	static final int NEGATIVE = 0;
+	static final int NEUTRAL = 2;
+	static final int REMAINDER = 3;
+
+	public PairwiseDisplayer (PairwiseComparison ownerModule, TreeDisplay treeDisplay, int numTaxa) {
+		super(ownerModule, treeDisplay);
+		pairModule = ownerModule;
+		colors = new Color[64];
+	}
+	public void initiate() {
+		if (legend!=null)
+			legend.setMessage("Calculating...");
+		pairer =(TaxaPairerChars) pairModule.pairSelectorTask.getPairer();
+		cat = new int[4];
+		setPairing(0);
+		pairer.init();
+		pMax = 0;
+		pMin = 1;
+		for  (int j=0; j<4; j++) cat[j]=0;
+		treeDisplay.pleaseUpdate(false);
+		numCharsA = pairModule.characterSourceTaskA.getNumberOfCharacters(pairModule.currentTaxa);
+		numCharsB = pairModule.characterSourceTaskB.getNumberOfCharacters(pairModule.currentTaxa);
+		if (legend!=null) {
+			legend.adjustCharacterAScroll(pairModule.currentCharA, numCharsA);
+			legend.adjustCharacterBScroll(pairModule.currentCharB, numCharsB);
+		}
+		//reset();
+	}
+
+	public String textForLegend(){
+		return getWritableText();
+	}
+	
+	public String getWritableText(){
+		if (legend == null)
+			return null;
+		return legend.getTextVersion();
+	}
+	
+	public String textAtNode(Tree tree, int node){
+		if (pairing == null)
+			return " pairing null ";
+		if (pairing.getNumPairs() == 0)
+			return " no pairs ";
+		TaxaPath path = pairing.findPath(node);
+		if (path == null)
+			return "";
+		return describePathContrast(path);
+	}
+
+	/*.................................................................................................................*/
+	void calculatePRange (TaxaPairerChars pairer) {
+		Tree tree = treeDisplay.getTree();
+		int currentPairing = pairer.getCurrentPairingNumber();
+		int nP = pairer.getNumPairings(tree);
+		double max,  min;
+		TaxaPairing pairing = pairer.getFirstPairing(tree); 
+		long[][] freqs = new long[100][2]; // first is characterizaiton, second is frequency
+		for (int i = 0; i<100; i++) {
+			freqs[i][0]=0;
+			freqs[i][1]=0;
+		}
+		calculateCategories(pairing, tree);
+		storeCats(cat, freqs);
+		max = Binomial.bestTail(cat[1] + cat[0], cat[1], 0.5);
+		min = max;
+		for (int i = 1; i< nP; i++) {
+
+			pairing = pairer.getNextPairing(tree); 
+			if (i % 5000 ==0) MesquiteMessage.println("Pairings so far surveyed for p value: " + i);
+			if (i % 100 ==0) CommandRecord.tick("Pairings surveyed for p value: " + i);
+			//	if (i % 20000 ==0) MesquiteMessage.printStackTrace("Pairings so far surveyed for p value: " + i);
+			calculateCategories(pairing, tree);
+			storeCats(cat, freqs);
+			double p =Binomial.bestTail(cat[1] + cat[0], cat[1], 0.5);
+			if (p>max)
+				max = p;
+			else if (p<min)
+				min = p;
+		}
+		//	writeFreqs(freqs);
+		pMax = max;
+		pMin = min;
+		pairing = pairer.getPairing(tree, currentPairing);
+		if (legend != null)
+			legend.repaint();
+	}
+	/*.................................................................................................................*/
+	private void storeCats(int[] cat, long[][] freqs) {
+		long ispec = cat[0] + cat[1]*10 + cat[2]*100 + cat[3]*1000;
+		boolean found = false;
+		for (int i=0; i<100 && !found; i++) {
+			if (freqs[i][0]== ispec) {
+				found= true;
+				freqs[i][1]++;
+			}
+			else if  (freqs[i][0]== 0) {
+				freqs[i][0]= ispec;
+				freqs[i][1]= 1;
+				found= true;
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private void writeFreqs(long[][] freqs) {
+		boolean found = false;
+		for (int i=0; i<100 && !found; i++) {
+			if (freqs[i][0]== 0) {
+				found= true;
+			}
+			else {
+				System.out.println(" ispec " + freqs[i][0] + " num " + freqs[i][1]);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private void drawTerminalStuff(int N, Tree tree, Graphics g) {
+		if (tree == null || g == null || treeDisplay == null || treeDisplay.getTreeDrawing() == null || observedStatesA == null || observedStatesB == null)
+			return;
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawTerminalStuff(d, tree, g);
+		if (tree.nodeIsTerminal(N)) {
+			int t = tree.taxonNumberOfNode(N);
+
+			MesquiteLabel c = (MesquiteLabel)labelsAtNodes.getPanel(t);
+			if (c != null){
+				if (pairModule.showStates.getValue()) {
+					int nodeX = treeDisplay.getTreeDrawing().x[N];
+					int nodeY = treeDisplay.getTreeDrawing().y[N];
+					//	c.setText( observedStatesA.toString(t, " ") + "/" + observedStatesB.toString(t, " ")); 
+					c.setText("\2" + observedStatesA.toString(t, " "));  //\2=boldface
+					c.addLine(observedStatesB.toString(t, " ")); 
+					c.setLocation(nodeX, nodeY);
+					c.setVisible(true);
+
+					c.repaint();
+				}
+				else
+					c.setVisible(false);
+			}
+		}
+		g.setColor(Color.black);
+	}
+	/*.................................................................................................................*/
+	private void calculateCategories(TaxaPairing pairing, Tree tree) {
+		if (tree == null || pairing == null || cat == null || observedStatesA == null || observedStatesB == null)
+			return;
+		for  (int j=0; j<4; j++)
+			cat[j]=0;
+		int numTaxa = tree.getNumTaxa();
+		int numPaths = pairing.getNumPairs();
+		for (int i=0; i<numPaths; i++) {
+			TaxaPath path =pairing.getPath(i);
+			if (path == null)
+				return;
+			int tax1 =path.gettaxon1();
+			int tax2 = path.gettaxon2();
+
+			if (observedStatesA.firstIsGreater(tax1, tax2)) {
+				if (observedStatesB.firstIsGreater(tax1, tax2))
+					cat[POSITIVE]++;
+				else if (observedStatesB.firstIsGreater(tax2, tax1))
+					cat[NEGATIVE]++;
+				else 
+					cat[NEUTRAL]++;
+			}
+			else if (observedStatesA.firstIsGreater(tax2, tax1)) {
+				if (observedStatesB.firstIsGreater(tax1, tax2))
+					cat[NEGATIVE]++;
+				else if (observedStatesB.firstIsGreater(tax2, tax1))
+					cat[POSITIVE]++;
+				else 
+					cat[NEUTRAL]++;
+			}
+			else {
+				cat[REMAINDER]++;
+			}
+
+		}
+	}
+	
+	private String describePath(TaxaPath path){
+		if (observedStatesA == null)
+			return "";
+		Taxa taxa = observedStatesA.getTaxa();
+		
+		return taxa.getTaxonName(path.gettaxon1()) + " vs. "  + taxa.getTaxonName(path.gettaxon2()) + "; MRCA " + path.getBase();
+	}
+	private String describeContrast(int tax1, int tax2){
+		return "X = "+ observedStatesA.toString(tax1, "") + " vs. " + observedStatesA.toString(tax2, "") + "; Y = "+ observedStatesB.toString(tax1, "") + " vs. " + observedStatesB.toString(tax2, "");
+	}
+	/*.................................................................................................................*/
+	private String describePathContrast(TaxaPath path) {
+		if (path == null)
+			return "Remainder " + describePath(path);
+		if (observedStatesA == null || observedStatesB== null)
+			return "";
+		int tax1 =path.gettaxon1();
+		int tax2 = path.gettaxon2();
+
+		if (observedStatesA.firstIsGreater(tax1, tax2)) {
+			if (observedStatesB.firstIsGreater(tax1, tax2))
+				return "Positive: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+			else if (observedStatesB.firstIsGreater(tax2, tax1))
+				return "Negative: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+			else 
+				return "Neutral: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+		}
+		else if (observedStatesA.firstIsGreater(tax2, tax1)) {
+			if (observedStatesB.firstIsGreater(tax1, tax2))
+				return "Negative: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+			else if (observedStatesB.firstIsGreater(tax2, tax1))
+				return "Positive: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+			else 
+				return "Neutral: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+		}
+		else {
+			return "Remainder: "+ describeContrast(tax1, tax2) + " for " + describePath(path);
+		}
+	}
+	/*.................................................................................................................*/
+	private int categoryOfPath(TaxaPath path) {
+		if (path == null)
+			return REMAINDER;
+		int tax1 =path.gettaxon1();
+		int tax2 = path.gettaxon2();
+
+		if (observedStatesA.firstIsGreater(tax1, tax2)) {
+			if (observedStatesB.firstIsGreater(tax1, tax2))
+				return POSITIVE;
+			else if (observedStatesB.firstIsGreater(tax2, tax1))
+				return NEGATIVE;
+			else 
+				return NEUTRAL;
+		}
+		else if (observedStatesA.firstIsGreater(tax2, tax1)) {
+			if (observedStatesB.firstIsGreater(tax1, tax2))
+				return NEGATIVE;
+			else if (observedStatesB.firstIsGreater(tax2, tax1))
+				return POSITIVE;
+			else 
+				return NEUTRAL;
+		}
+		else {
+			return REMAINDER;
+		}
+	}
+	int dp = 0;
+	/*.................................................................................................................*/
+	private void drawPairs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Graphics g) {
+		int numTaxa = tree.getNumTaxa();
+		int numPaths = pairing.getNumPairs();
+		for (int i=0; i<numPaths; i++) {
+			TaxaPath path =pairing.getPath(i);
+			int category = categoryOfPath(path);
+			int t1 = tree.nodeOfTaxonNumber(path.gettaxon1());
+			int t2 =  tree.nodeOfTaxonNumber(path.gettaxon2());
+			if (category == POSITIVE)
+				g.setColor(Color.green);
+			else if (category == NEGATIVE)
+				g.setColor(Color.red);
+			else if (category == NEUTRAL)
+				g.setColor(ColorDistribution.lightBlue);
+			else
+				g.setColor(Color.blue);
+			//g.setColor(new Color(Color.HSBtoRGB((float)(i * 1.0 /numTaxa),(float)1.0,(float)1.0)));
+			int thisNode = t1;
+			while (tree.nodeExists(thisNode) && thisNode!= path.getBase() && thisNode!=drawnRoot) {
+				treeDisplay.getTreeDrawing().fillBranch(tree, thisNode, g);
+				thisNode=tree.motherOfNode(thisNode);
+			}
+			thisNode = t2;
+			while (tree.nodeExists(thisNode) && thisNode!= path.getBase() && thisNode!=drawnRoot) {
+				treeDisplay.getTreeDrawing().fillBranch(tree, thisNode, g);
+				thisNode=tree.motherOfNode(thisNode);
+			}
+		}
+	}
+	public void nextPairing() {
+		if (pairer == null)
+			return;
+		if (pairer.getCurrentPairingNumber()<= numPairings) {
+			pairing = pairer.getNextPairing(treeDisplay.getTree()); 
+			if (legend !=null)
+				legend.adjustPairingScroll(pairer.getCurrentPairingNumber(), numPairings);
+			calculateCategories(pairing, treeDisplay.getTree());
+			//legend.setResults(cat, pairing, new TwoCharPairing(tree, observedStatesA, observedStatesB));
+			if (legend != null)
+				legend.setResults(cat, pairing, pMin, pMax);
+		}
+		if (treeDisplay!=null)
+			treeDisplay.pleaseUpdate(false);
+	}
+	public void setPairing(int index) {
+		if (pairer == null)
+			return;
+		if (index< numPairings && index >= 0) {
+			pairing = pairer.getPairing(treeDisplay.getTree(), index); 
+			if (legend !=null)
+				legend.adjustPairingScroll(pairer.getCurrentPairingNumber(), numPairings);
+			calculateCategories(pairing, treeDisplay.getTree());
+			//legend.setResults(cat, pairing, new TwoCharPairing(tree, observedStatesA, observedStatesB));
+			if (legend != null)
+				legend.setResults(cat, pairing, pMin, pMax);
+		}
+		if (treeDisplay!=null)
+			treeDisplay.pleaseUpdate(false);
+	}
+	public int getPairing() {
+		if (pairer == null)
+			return 0;
+		return pairer.getCurrentPairingNumber();
+	}
+
+	public void reset(){
+		if (pairer == null)
+			return;
+		observedStatesA = pairModule.characterSourceTaskA.getCharacter(pairModule.currentTaxa, pairModule.currentCharA);
+		observedStatesB = pairModule.characterSourceTaskB.getCharacter(pairModule.currentTaxa, pairModule.currentCharB);
+		pairer.setCharacters(observedStatesA, observedStatesB);
+		pairing = pairer.getFirstPairing(treeDisplay.getTree());
+
+		numPairings = pairer.getNumPairings(treeDisplay.getTree());
+		calculatePRange(pairer);
+		if (legend !=null)
+			legend.adjustPairingScroll(pairer.getCurrentPairingNumber(), numPairings);
+		calculateCategories(pairing, treeDisplay.getTree());
+		//legend.setResults(cat, pairing, new TwoCharPairing(tree, observedStatesA, observedStatesB));
+		if (legend != null)
+			legend.setResults(cat, pairing, pMin, pMax);
+		treeDisplay.pleaseUpdate(false);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		boolean toShow = false;
+		if (legend == null) {
+			legend = new ShowPairsLegend(pairModule, this);
+			legend.adjustCharacterAScroll(pairModule.currentCharA, numCharsA);
+			legend.adjustCharacterBScroll(pairModule.currentCharB, numCharsB);
+			legend.setVisible(false);
+			addPanelPlease(legend);
+			toShow = true;
+		}
+		legend.adjustPairingScroll(pairer.getCurrentPairingNumber(), numPairings);  //dont do this without protection for loop
+		if (labelsAtNodes==null) {
+			labelsAtNodes = new LabelsAtNodes(ownerModule, tree.getNumTaxa(), treeDisplay);
+		}
+		else if (labelsAtNodes.getNumNodes()!=tree.getNumTaxa() ) {
+			labelsAtNodes.resetNumNodes(tree.getNumTaxa());
+		}
+		if (pairing !=null) {
+			drawTerminalStuff(drawnRoot, tree, g);
+			drawPairs(treeDisplay, tree, drawnRoot, g);
+			//	calculateCategories(pairing, tree);
+			//legend.setResults(cat, pairing, new TwoCharPairing(tree, observedStatesA, observedStatesB));
+			legend.setResults(cat, pairing, pMin, pMax);
+
+			legend.adjustLocation(); //dont do this without protection for loop
+			if (toShow || !legend.isVisible())
+				legend.setVisible(true);
+			legend.repaint();  // dont do this without protection for loop
+		}
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		reset();
+	}
+
+	public void turnOff() {
+		super.turnOff();
+		if (labelsAtNodes!=null)
+			labelsAtNodes.dispose();
+		if (treeDisplay!=null && legend!=null)
+			removePanelPlease(legend);
+	}
+}
+
+
+/* ======================================================================== */
+class ShowPairsLegend extends TreeDisplayLegend {
+	private PairwiseComparison ownerModule;
+	public MiniScroll pairingScroll = null;
+	public MiniScroll characterAScroll = null;
+	public MiniScroll characterBScroll = null;
+	private PairwiseDisplayer pD;
+	private static final int defaultLegendWidth=180;
+	private static final int defaultLegendHeight=340;
+
+	private int oldNumPairings = 0;
+	private int oldCurrentPairing = -1;
+	private int oldCharA=-1;
+	private int oldNumCharsA=0;
+	private int oldCharB=-1;
+	private int oldNumCharsB=0;
+	private boolean resizingLegend=false;
+	private TextArea pairingMessageBox;
+	private TextArea AMessageBox;
+	private TextArea BMessageBox;
+	private static int scrollStart = 24;
+	public ShowPairsLegend(PairwiseComparison ownerModule, PairwiseDisplayer pD) {
+		super(pD.treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		this.pD = pD;
+		this.ownerModule = ownerModule;
+		//setBackground(ColorDistribution.light);
+		setLayout(null);
+
+		setOffsetX(ownerModule.initialOffsetX);
+		setOffsetY(ownerModule.initialOffsetY);
+		setSize(legendWidth, legendHeight);
+
+		characterAScroll = new MiniScroll(MesquiteModule.makeCommand("setCharacterA",  ownerModule), false, 1, 1, 1, "character");
+		add(characterAScroll);
+		//characterAScroll.setBackground(Color.cyan);
+		characterAScroll.setLocation(2,scrollStart);
+		characterAScroll.setColor(Color.blue);
+		AMessageBox = new TextArea("", 1, 1, TextArea.SCROLLBARS_NONE);
+		AMessageBox.setVisible(false);
+		AMessageBox.setBackground(Color.white);
+		AMessageBox.setEditable(false);
+		add(AMessageBox);
+		AMessageBox.setBounds(4,characterAScroll.getBounds().y+characterAScroll.getBounds().height+4,legendWidth-8, 32);
+
+		characterBScroll = new MiniScroll(MesquiteModule.makeCommand("setCharacterB",  ownerModule), false, 1, 1, 1, "character");
+		add(characterBScroll);
+		//characterBScroll.setBackground(Color.cyan);
+		characterBScroll.setLocation(2,AMessageBox.getBounds().y+AMessageBox.getBounds().height+4);
+		characterBScroll.setColor(Color.blue);
+		BMessageBox = new TextArea("", 1, 1, TextArea.SCROLLBARS_NONE);
+		BMessageBox.setEditable(false);
+		BMessageBox.setVisible(false);
+		BMessageBox.setBackground(Color.white);
+		add(BMessageBox);
+		BMessageBox.setBounds(4,characterBScroll.getBounds().y+characterBScroll.getBounds().height+4,legendWidth-8, 32);
+
+		pairingScroll = new MiniScroll(MesquiteModule.makeCommand("setPairing",  ownerModule), false, 1,1,1,"");
+		add(pairingScroll);
+		//pairingScroll.setBackground(Color.cyan);
+		pairingScroll.setLocation(2,BMessageBox.getBounds().y+BMessageBox.getBounds().height+4); 
+		pairingScroll.setColor(Color.blue);
+		pairingMessageBox = new TextArea("", 1, 1, TextArea.SCROLLBARS_NONE);
+		pairingMessageBox.setVisible(false);
+		pairingMessageBox.setEditable(false);
+		pairingMessageBox.setBackground(Color.white);
+		add(pairingMessageBox);
+		pairingMessageBox.setBounds(4,pairingScroll.getBounds().y+pairingScroll.getBounds().height+4,legendWidth-8, legendHeight-(pairingScroll.getBounds().y+pairingScroll.getBounds().height+6));
+	}
+
+	public void adjustCharacterAScroll(int charA, int numCharsA) {
+		if (characterAScroll == null) {
+			characterAScroll = new MiniScroll(MesquiteModule.makeCommand("setCharacterA",  ownerModule), false, CharacterStates.toExternal(0), CharacterStates.toExternal(charA), CharacterStates.toExternal(numCharsA-1),"character");
+			add(characterAScroll);
+			//characterAScroll.setBackground(Color.cyan);
+			characterAScroll.setLocation(2,4);
+			characterAScroll.setColor(Color.blue);
+			repaint();
+			oldCharA = charA;
+			oldNumCharsA = numCharsA;
+		}
+		else {
+			characterAScroll.setVisible(true);
+			if (oldNumCharsA != numCharsA) {
+				characterAScroll.setMaximumValue(CharacterStates.toExternal(numCharsA -1));
+				oldNumCharsA = numCharsA;
+			}
+			if (oldCharA != charA) {
+				characterAScroll.setCurrentValue(CharacterStates.toExternal(charA));
+				oldCharA = charA;
+			}
+			repaint();
+		}
+	}
+	public void adjustCharacterBScroll(int charB, int numCharsB) {
+		if (characterBScroll == null) {
+			characterBScroll = new MiniScroll( MesquiteModule.makeCommand("setCharacterB",  ownerModule), false, CharacterStates.toExternal(0), CharacterStates.toExternal(charB), CharacterStates.toExternal(numCharsB-1),"character");
+			add(characterBScroll);
+			//characterBScroll.setBackground(Color.cyan);
+			characterBScroll.setLocation(2,characterAScroll.getBounds().y+characterAScroll.getBounds().height+4);
+			characterBScroll.setColor(Color.blue);
+			repaint();
+			oldCharB = charB;
+			oldNumCharsB = numCharsB;
+		}
+		else {
+			characterBScroll.setVisible(true);
+			if (oldNumCharsB != numCharsB) {
+				characterBScroll.setMaximumValue(CharacterStates.toExternal(numCharsB -1));
+				oldNumCharsB = numCharsB;
+			}
+			if (oldCharB != charB) {
+				characterBScroll.setCurrentValue(CharacterStates.toExternal(charB));
+				oldCharB = charB;
+			}
+			repaint();
+		}
+	}
+	public void adjustPairingScroll(int currentPairing, int numPairings) {
+		//currentPairing is in internal (0 based); convert to external where needed
+		if (pairingScroll == null) {
+			pairingScroll = new MiniScroll( MesquiteModule.makeCommand("setPairing",  ownerModule), false, 1, currentPairing+1, numPairings,"");
+			add(pairingScroll);
+			//pairingScroll.setBackground(Color.cyan);
+			pairingScroll.setLocation(2,characterBScroll.getBounds().y+characterBScroll.getBounds().height+4); 
+			pairingScroll.setColor(Color.blue);
+			repaint();
+			oldNumPairings = numPairings;
+			oldCurrentPairing = currentPairing;
+		}
+		else {
+			pairingScroll.setVisible(true);
+			if (oldNumPairings != numPairings) {
+				pairingScroll.setMaximumValue(numPairings);
+				oldNumPairings = numPairings;
+			}
+			if (oldCurrentPairing != currentPairing) {
+				pairingScroll.setCurrentValue(currentPairing+1);
+				oldCurrentPairing = currentPairing;
+			}
+			repaint();
+		}
+		pairingMessageBox.setBounds(4,pairingScroll.getBounds().y+pairingScroll.getBounds().height+4,legendWidth-8, legendHeight-(pairingScroll.getBounds().y+pairingScroll.getBounds().height+6));
+	}
+
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (pairingScroll !=null)
+			pairingScroll.setVisible(b);
+		if (pairingMessageBox != null)
+			pairingMessageBox.setVisible(b);
+		if (characterAScroll !=null)
+			characterAScroll.setVisible(b);
+		if (AMessageBox != null)
+			AMessageBox.setVisible(b);
+		if (characterBScroll !=null)
+			characterBScroll.setVisible(b);
+		if (BMessageBox != null)
+			BMessageBox.setVisible(b);
+	}
+	public void setLocation(int x, int y){
+		super.setLocation(x, y);
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Color c = g.getColor();
+		g.setColor(Color.blue);
+		g.drawString("Pairwise comparisons", 2, scrollStart-8);
+		g.drawRect(0,0, getBounds().width-1, getBounds().height -1);
+		Rectangle rect = pairingScroll.getBounds();
+		g.drawString("Pairing", rect.x+ rect.width, rect.y + rect.height-4);
+		rect = characterAScroll.getBounds();
+		g.drawString("Independent", rect.x+ rect.width, rect.y + rect.height-4);
+		rect = characterBScroll.getBounds();
+		g.drawString("Dependent", rect.x+ rect.width, rect.y + rect.height-4);
+		if (c!=null) g.setColor(c);
+		String A = ownerModule.characterSourceTaskA.getNameAndParameters();
+		String B = ownerModule.characterSourceTaskB.getNameAndParameters();
+		if (A !=null && !A.equals(AMessageBox.getText()))
+			AMessageBox.setText(A);
+		if (B !=null && !B.equals(BMessageBox.getText()))
+			BMessageBox.setText(B);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	String textVersion = "";
+	public void setResults(int[] results, TaxaPairing pairing, double pMin, double pMax) {
+		if(pairing.getCalculationNotDone()){
+			String s = "Calculation not done\n" + pD.pairer.getWarningMessage();
+			textVersion = s;
+			setMessage(s);
+			return;
+		}
+		
+		int numP = pairing.getNumPairs(); 
+		String s = "Pairing " + (oldCurrentPairing+1) +" of " + oldNumPairings;
+		if (ownerModule.pairSelectorTask.limitReached(oldNumPairings))
+			s += " (There may be more pairings; the limit of number of pairings allowed was reached.)";
+		if (!StringUtil.blank(pD.pairer.getWarningMessage()))
+			s += "\n" + pD.pairer.getWarningMessage();
+		s +="\nSelector: " + ownerModule.pairSelectorTask.getName() + "\n" + numP + " pairs\n";
+		s += "   Positive " + results[1] + "\n   Negative " + results[0] + "\n   Neutral " + results[2] + "\n   Remainder " + results[3];
+		s += "\n best tail p=" + MesquiteDouble.toString(Binomial.bestTail(results[0] + results[1], results[1], 0.5));
+		if (pMax>0 && pMin>0) {
+			s += "\nRange (" + oldNumPairings + " pairings):";
+			s += "\n" + MesquiteDouble.toString(pMin) + " - " + MesquiteDouble.toString(pMax);
+		}
+		
+		textVersion = "Pairing\t" + (oldCurrentPairing+1) +"\tof\t" + oldNumPairings + "\t";
+		if (ownerModule.pairSelectorTask.limitReached(oldNumPairings))
+			textVersion += " (There may be more pairings; the limit of number of pairings allowed was reached.) ";
+		textVersion += " " + pD.pairer.getWarningMessage();
+		textVersion +=" Selector: " + ownerModule.pairSelectorTask.getName() + "\t" + numP + "\tpairs. ";
+		textVersion += "   Positive\t" + results[1] + "\tNegative\t" + results[0] + "\tNeutral\t" + results[2] + "\tRemainder\t" + results[3];
+		textVersion += "\tbest tail p=\t" + MesquiteDouble.toString(Binomial.bestTail(results[0] + results[1], results[1], 0.5));
+		if (pMax>0 && pMin>0) {
+			textVersion += "\tRange (" + oldNumPairings + " pairings):";
+			textVersion += "\t" + MesquiteDouble.toString(pMin) + "\t" + MesquiteDouble.toString(pMax);
+		}
+		else {
+			textVersion += "\t \t  \t ";
+		}
+		setMessage(s);
+	}
+	String getTextVersion(){
+		return textVersion;
+	}
+	public void setMessage(String s) {
+		if (s==null || s.equals("")) {
+			pairingMessageBox.setText("");
+		}
+		else {
+			pairingMessageBox.setText(s);
+		}
+		pairingMessageBox.repaint();
+	}
+}
+
+
diff --git a/Source/mesquite/pairwise/aPairwiseIntro/aPairwiseIntro.java b/Source/mesquite/pairwise/aPairwiseIntro/aPairwiseIntro.java
new file mode 100644
index 0000000..dc3b957
--- /dev/null
+++ b/Source/mesquite/pairwise/aPairwiseIntro/aPairwiseIntro.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.pairwise.aPairwiseIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aPairwiseIntro extends PackageIntro {
+	public String getName() {
+		return "Pairwise Comparisons Package Introduction";
+	}
+	public String getExplanation() {
+		return "Performs pairwise comparisons character correlation analyses.";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public Class getDutyClass(){
+		return aPairwiseIntro.class;
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+	public String getPackageName(){
+		return "Pairwise Comparisons Package";
+	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+		return false; 
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+	public String getPackageCitation(){
+		return "Maddison, W.P. 2006.  Pairwise comparisons package for Mesquite, version 1.1.  http://mesquiteproject.org";
+	}
+	/*.................................................................................................................*/
+	/** Returns the URL of document shown when splash screen icon touched. By default, returns path to module's manual*/
+	public String getSplashURL(){
+		String splashP =getPath()+"index.html";
+		if (MesquiteFile.fileExists(splashP))
+			return splashP;
+		else
+			return getManualPath();
+	}
+}
+
diff --git a/Source/mesquite/pairwise/aPairwiseIntro/index.html b/Source/mesquite/pairwise/aPairwiseIntro/index.html
new file mode 100644
index 0000000..da6b9a6
--- /dev/null
+++ b/Source/mesquite/pairwise/aPairwiseIntro/index.html
@@ -0,0 +1,57 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Pairwise</title>
+	</head>
+
+	<body bgcolor="#ffeaab">
+		<h2>
+		<table border="4" cellpadding="0" cellspacing="2">
+			<tr>
+				<td></td>
+				<td>
+					<h2>Pairwise comparisons package for Mesquite</h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<h4>Wayne Maddison</h4>
+		
+<p>August 2005</p>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#modules">Modules</a>
+			<li><a href="#installation">Installation</a>
+		  <li><a href="#examples">Examples</a>            
+	</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		<p>This package performs the pairwise comparisons calculations of W. Maddison 2000 (Testing character correlation using pairwise comparisons on a phylogeny. Journal of Theoretical Biology. 202: 195-204).</p>
+		
+<p>This package and its source are free and modifiable under the terms of the 
+  GNU Lesser General Public License (see bottom of this page). The source is included 
+  with the Mesquite source, available from <a href="http://mesquiteproject.org">mesquiteproject.org</a>.</p>
+		<h3><a name="modules"></a>Modules</h3>
+		<p>The modules currently included are:</p>
+		<ul>
+			<li><b>PairwiseComparison</b> -- Supervises the calculation of pairwise comparisons, and displays results in a tree window.
+			<li><b>PairsTwoChars</b> -- Finds pairs of taxa contrasting the state of two binary characters.
+			<li><b>PairsOneChar</b> -- Finds pairs of taxa contrasting the state of one binary character.
+			<li><b>PairsNoChars</b> -- Finds pairs of taxa regardless of whether they contrast the states of two characters.
+		</ul>
+		<h3><a name="installation"></a>Installation</h3>
+		<p>To install the Pairwise comparisons package, the "pairwise" directory must be installed in the "mesquite" directory within "Mesquite Folder".</p>
+		<h3><a name="examples"></a>Examples</h3>
+		
+<p>A directory "Pairwise_Comparison" is included in the Mesquite examples 
+  folder in Mesquite_Folder/examples/.</p>
+		<p>
+		<hr>
+		</p>
+		
+<p>© Wayne Maddison, 2001-2005</p>
+		<p>
+	<p> 	</body>
+
+</html>
diff --git a/Source/mesquite/pairwise/explanation.txt b/Source/mesquite/pairwise/explanation.txt
new file mode 100644
index 0000000..3e81462
--- /dev/null
+++ b/Source/mesquite/pairwise/explanation.txt
@@ -0,0 +1,2 @@
+Pairwise Comparisons for Character Correlation
+Finds phylogenetically independent pairs of taxa and compares traits in two characters to explore character correlation (see W. Maddison 2000, Journal of Theoretical Biology, 202: 195-204)
diff --git a/Source/mesquite/pairwise/lib/PairMaker.java b/Source/mesquite/pairwise/lib/PairMaker.java
new file mode 100644
index 0000000..ed911d8
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/PairMaker.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class PairMaker extends MesquiteModule  {
+	protected int limit = MesquiteInteger.unassigned;
+	protected boolean limitSet = false;
+	static final int QUERYTRIGGER = 1000;
+	
+	public Class getDutyClass(){
+		return PairMaker.class;
+	}
+ 	public String getDutyName() {
+ 		return "Taxa Pair Maker";
+   	 }
+ 	public abstract TaxaPairer getPairer();
+ 	
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Max. Number of Pairings...", makeCommand("setLimit", this));
+ 		return true;
+ 	}
+	/*.................................................................................................................*/
+  	public void setLimit(int limit){
+  		this.limit = limit;
+  		limitSet = !MesquiteInteger.isUnassigned(limit);
+  	}
+	/*.................................................................................................................*/
+  	public int limitCheckOK(int count){  
+		if (limitSet){
+			return limit;
+		}
+		if (count>=QUERYTRIGGER){
+			if (MesquiteThread.isScripting()){
+				setLimit(QUERYTRIGGER);
+				return QUERYTRIGGER;
+			}
+			else {
+				int L = MesquiteInteger.queryInteger(containerOfModule(), "Number of pairs?", "The calculation has found " + QUERYTRIGGER + " pairings so far.  To set a limit on the number of pairings examined, enter it here; otherwise hit Cancel to continue until all pairings counted.", QUERYTRIGGER, 1, MesquiteInteger.infinite);
+				if (MesquiteInteger.isUnassigned(L)) 
+					L = MesquiteInteger.infinite;
+				setLimit(L);
+			}
+			return limit;
+		}
+  		return MesquiteInteger.infinite;
+  	}
+  	
+  	public boolean limitReached(int count){  
+			return limitSet && MesquiteInteger.isCombinable(limit) && count>= limit;
+  	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+		if (MesquiteInteger.isCombinable(limit))
+			temp.addLine("setLimit " + limit); 
+  	 	return temp;
+  	 }
+  	 
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(),  "Sets the limit of number of pairs to examine", "[limit]", commandName, "setLimit")) {
+			int L= MesquiteInteger.fromFirstToken(arguments, pos);
+			int lim = limit;
+			if (MesquiteInteger.isUnassigned(limit))
+				lim = QUERYTRIGGER;
+			if (!MesquiteInteger.isCombinable(L))
+				L = MesquiteInteger.queryInteger(containerOfModule(), "Number of pairs?", "Indicate the maximum number of pairings examined:", lim, 1, MesquiteInteger.infinite);
+			if (MesquiteInteger.isCombinable(L) || MesquiteInteger.infinite == L) {
+				setLimit(L);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/pairwise/lib/PairMakerChars.java b/Source/mesquite/pairwise/lib/PairMakerChars.java
new file mode 100644
index 0000000..4e89fdf
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/PairMakerChars.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class PairMakerChars extends PairMaker  {
+	public Class getDutyClass(){
+		return PairMakerChars.class;
+	}
+ 	public String getDutyName() {
+ 		return "Taxa Pair Maker using Characters";
+   	 }
+ 	public abstract void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB);
+ 	
+
+}
+
+
diff --git a/Source/mesquite/pairwise/lib/TaxaPairer.java b/Source/mesquite/pairwise/lib/TaxaPairer.java
new file mode 100644
index 0000000..bf5d1a3
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/TaxaPairer.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/***/
+public abstract class TaxaPairer   {
+ 	public abstract TaxaPairing getFirstPairing(Tree tree);
+ 	public abstract TaxaPairing getNextPairing(Tree tree);
+ 	public abstract TaxaPairing getPairing(Tree tree, int index);
+ 	public abstract int getNumPairings(Tree treek);
+ 	public abstract int getCurrentPairingNumber();
+ 	public abstract void init();
+ 	/*  */
+ 	protected String warningMessage = "";
+ 	public String getWarningMessage(){
+ 		return warningMessage;
+ 	}
+}
+
diff --git a/Source/mesquite/pairwise/lib/TaxaPairerChars.java b/Source/mesquite/pairwise/lib/TaxaPairerChars.java
new file mode 100644
index 0000000..5e88f9e
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/TaxaPairerChars.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/***/
+public abstract class TaxaPairerChars extends TaxaPairer   {
+ 	public abstract void setCharacters(CharacterDistribution statesA, CharacterDistribution statesB);
+ 	/*  */
+
+}
+
diff --git a/Source/mesquite/pairwise/lib/TaxaPairing.java b/Source/mesquite/pairwise/lib/TaxaPairing.java
new file mode 100644
index 0000000..365f6d8
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/TaxaPairing.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/***/
+public class TaxaPairing   {
+	private TaxaPath[] paths;
+	private int numPairs = 0;
+	private boolean calculationNotDone = false;
+	public TaxaPairing (int numTaxa) {
+		paths = new TaxaPath[numTaxa];
+	}
+	public boolean getCalculationNotDone() {
+		return calculationNotDone;
+	}
+	public void setCalculationNotDone(boolean cnd) {
+		calculationNotDone = cnd;
+	}
+	public int getNumPairs() {
+		return numPairs;
+	}
+	public void addPath (TaxaPath path) {
+		if (numPairs>=0 && numPairs <paths.length)
+			paths[numPairs]= path;
+		numPairs++;
+	}
+
+	public TaxaPath getPath (int index) {
+		if (index>=0 && index < numPairs) 
+			return paths[index];
+		MesquiteMessage.warnProgrammer("path out of range " + index + " " + numPairs);
+		return null;
+	}
+	public void addPath (int i, int j, int base) {
+		TaxaPath path = new TaxaPath();
+		path.setBase(base);
+		path.setTaxon(i, 1);
+		path.setTaxon(j, 2);
+		paths[numPairs]= path;
+		numPairs++;
+	}
+	
+	public TaxaPath findPath(int node){
+		if (paths == null)
+			return null;
+		for (int i=0; i<paths.length; i++)
+			if (paths[i]!= null && paths[i].getBase() == node)
+				return paths[i];
+		return null;
+	}
+	
+	
+ 	/*  */
+}
+
+
diff --git a/Source/mesquite/pairwise/lib/TaxaPath.java b/Source/mesquite/pairwise/lib/TaxaPath.java
new file mode 100644
index 0000000..f5702d9
--- /dev/null
+++ b/Source/mesquite/pairwise/lib/TaxaPath.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pairwise.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ----------------------------------------- */
+public class TaxaPath {
+	int taxon1, taxon2, baseN;
+	public TaxaPath () {
+		baseN=-1;
+		taxon1=-1;
+		taxon2=-1;
+	}
+	public int getBase() {
+		return baseN;
+	}
+	public void setBase(int b) {
+		baseN = b;
+	}
+	public  int gettaxon1() {
+		return taxon1;
+	}
+	public  int  gettaxon2() {
+		return taxon2;
+	}
+	
+	public void setTaxon (int taxon, int index) {
+		if (index==1)
+			taxon1= taxon;
+		else 
+			taxon2=taxon;
+	}
+	
+	public void setNode(Tree tree, int node) {
+		int tNN = tree.taxonNumberOfNode(node);
+		if (taxon1==-1)
+			taxon1= tNN;
+		else if (taxon2==-1)
+			taxon2=tNN;
+		else {
+			if (tree.whichDaughterDescendantOf(node, baseN) == tree.whichDaughterDescendantOf(tree.nodeOfTaxonNumber(taxon2), baseN))
+				taxon2 = tNN;  
+			else
+				taxon1 = tNN;
+		}
+	}
+}
+
diff --git a/Source/mesquite/pal/aPALIntro/aPALIntro.java b/Source/mesquite/pal/aPALIntro/aPALIntro.java
new file mode 100644
index 0000000..8aa60c6
--- /dev/null
+++ b/Source/mesquite/pal/aPALIntro/aPALIntro.java
@@ -0,0 +1,66 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+(for this source, not for PAL!). 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.pal.aPALIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aPALIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aPALIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Introduces the PAL library.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "PAL Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "PAL (Phylogenetic Analysis Library)";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns information about a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Drummond, A. & K. Strimmer, 2001.  PAL: Phylogenetic Analysis Library, version 1.3.  http://www.cebl.auckland.ac.nz/pal-project/";
+ 	}
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+	
+	public boolean getHideable(){
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/pal/aPALIntro/index.html b/Source/mesquite/pal/aPALIntro/index.html
new file mode 100644
index 0000000..e976428
--- /dev/null
+++ b/Source/mesquite/pal/aPALIntro/index.html
@@ -0,0 +1,43 @@
+<html>
+
+	<!--This file created 14/3/01 9:48 AM by Claris Home Page version 3.0-->
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>PAL</title>
+		<x-claris-window top="34" bottom="717" left="63" right="559"><x-claris-tagview mode="minimal">
+	</head>
+
+	<body bgcolor="#ffcc99">
+		<h2>
+		<table border="4" cellpadding="0">
+			<tr>
+				<td width="165"><img src="splash.gif" width="164" height="64" x-claris-useimagewidth x-claris-useimageheight align="bottom"></td>
+				<td>
+					<h2>Phylogenetic Analysis Library</h2>
+					<h2>Version 1.3</h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<h4>Alexei Drummond and Korbinian Strimmer</h4>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#installation">Installation</a>
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		<p>This page represents the Phylogenetic Analysis Library (PAL) by Drummond and Strimmer, as installed for use in Mesquite.  When installed, various modules in Mesquite have the option of using PAL methods for calculations. To find out what modules might be using PAL, look through their documentation.</p>
+		
+<p>PAL is distributed under the terms of the GNU <a href="http://www.gnu.org/copyleft/lesser.html">Lesser 
+  General Public License</a>. Source code and documentation of PAL are at the 
+  <a href="http://mesquiteproject.org/mesquite/pal/">Mesquite web site</a>. For 
+  the latest version of PAL, please go to <a href="http://www.cebl.auckland.ac.nz/pal-project/">http://www.cebl.auckland.ac.nz/pal-project/</a></p>
+		<h3><a name="installation"></a>Installation</h3>
+		<p>To install PAL, the "pal" directory must be installed within "Mesquite_Folder" directory.</p>
+		<p>
+		<hr>
+	</body>
+
+</html>
+
diff --git a/Source/mesquite/pal/aPALIntro/splash.gif b/Source/mesquite/pal/aPALIntro/splash.gif
new file mode 100644
index 0000000..260b571
Binary files /dev/null and b/Source/mesquite/pal/aPALIntro/splash.gif differ
diff --git a/Source/mesquite/pal/explanation.txt b/Source/mesquite/pal/explanation.txt
new file mode 100644
index 0000000..24133db
--- /dev/null
+++ b/Source/mesquite/pal/explanation.txt
@@ -0,0 +1,2 @@
+Introduction to PAL
+This package contains no substantive modules.  It has a single module that serves to introduce to the user the PAL package (Drummond & Strimmer) of molecular phylogenetic & population genetic routines.  If this package is deactivated, the PAL package is NOT deactivated.
diff --git a/Source/mesquite/parsimony/CharListParsModels/CharListParsModels.java b/Source/mesquite/parsimony/CharListParsModels/CharListParsModels.java
new file mode 100644
index 0000000..e0a0e57
--- /dev/null
+++ b/Source/mesquite/parsimony/CharListParsModels/CharListParsModels.java
@@ -0,0 +1,207 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.CharListParsModels;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class CharListParsModels extends CharListAssistant {
+	public String getName() {
+		return "Current Parsimony Models ";
+	}
+	public String getExplanation() {
+		return "Shows current parsimony models applied to characters in character list window." ;
+	}
+	/*.................................................................................................................*/
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof ParsimonyModel) {
+			parametersChanged();
+		}
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the parsimony model of the selected characters", "[number of model]", commandName, "setModel")) {
+			if (table !=null && data!=null) {
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(ParsimonyModel.class, data.getStateClass()), whichModel);
+				if (model != null) {
+					ModelSet modelSet = (ModelSet) data.getCurrentSpecsSet(ParsimonyModelSet.class);
+					if (modelSet == null) {
+						CharacterModel defaultModel =  data.getDefaultModel("Parsimony");
+						modelSet= new ParsimonyModelSet("Parsimony Model Set", data.getNumChars(), defaultModel, data);
+						modelSet.addToFile(data.getFile(), getProject(), findElementManager(ParsimonyModelSet.class)); 
+						data.setCurrentSpecsSet(modelSet, ParsimonyModelSet.class);
+					}
+					if (modelSet != null) {
+						if (employer!=null && employer instanceof ListModule) {
+							int c = ((ListModule)employer).getMyColumn(this);
+							for (int i=0; i<data.getNumChars(); i++) {
+								if (table.isCellSelectedAnyWay(c, i)) {
+									modelSet.setModel(model, i);
+									if (!changed)
+										outputInvalid();
+
+									changed = true;
+								}
+							}
+						}
+					}
+				}
+
+				if (changed)
+					data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  
+				//not quite kosher; HOW TO HAVE MODEL SET LISTENERS??? -- modelSource
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Stores current parsimony model set (TYPESET)", null, commandName, "storeCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(ParsimonyModelSet.class);
+				if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+					CharacterModel defaultModel =  data.getDefaultModel("Parsimony");
+					ModelSet modelSet= new ParsimonyModelSet("Parsimony Model Set", data.getNumChars(), defaultModel, data);
+					modelSet.addToFile(data.getFile(), getProject(), findElementManager(ParsimonyModelSet.class)); 
+					data.setCurrentSpecsSet(modelSet, ParsimonyModelSet.class);
+					ssv = data.getSpecSetsVector(ParsimonyModelSet.class);
+				}
+				if (ssv!=null) {
+					SpecsSet s = ssv.storeCurrentSpecsSet();
+					if (s.getFile() == null)
+						s.addToFile(data.getFile(), getProject(), findElementManager(ParsimonyModelSet.class));
+					s.setName(ssv.getUniqueName("Parsimony Model Set"));
+					String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of parsimony model set to be stored", "Parsimony Model Set");
+					if (!StringUtil.blank(name))
+						s.setName(name);
+					ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+				}
+				else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+			}
+		}
+		else if (checker.compare(this.getClass(), "Replace stored parsimony model set (TYPESET) by the current one", null, commandName, "replaceWithCurrent")) {
+			if (data!=null){
+				SpecsSetVector ssv = data.getSpecSetsVector(ParsimonyModelSet.class);
+				if (ssv!=null) {
+					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored parsimony model set to replace by current set", MesquiteString.helpString, ssv, 0);
+					if (chosen!=null){
+						SpecsSet current = ssv.getCurrentSpecsSet();
+						ssv.replaceStoredSpecsSet(chosen, current);
+					}
+				}
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Loads the stored parsimony model set to be the current one", "[number of parsimony set to load]", commandName, "loadToCurrent")) {
+			if (data !=null) {
+				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+				if (MesquiteInteger.isCombinable(which)){
+					SpecsSetVector ssv = data.getSpecSetsVector(ParsimonyModelSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+						if (chosen!=null){
+							ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+							data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //should notify via specs not data???
+							return chosen;
+						}
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		/* hire employees here */
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mStc);
+		mss = addSubmenu(null, "Parsimony model", makeCommand("setModel", this), getProject().getCharacterModels());
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current set...", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current...", makeCommand("replaceWithCurrent",  this));
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(ParsimonyModel.class, data.getStateClass()));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load parsimony model set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(ParsimonyModelSet.class));
+		this.data = data;
+		this.table = table;
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Parsimony Model";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null) {
+			ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(ParsimonyModelSet.class);
+			if (modelSet != null) {
+				CharacterModel model = modelSet.getModel(ic);
+				if (model!=null) {
+					return model.getName();
+				}
+			}
+			else
+				MesquiteMessage.warnProgrammer("model set null in gsfc");
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "Parsimony Model  ";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
diff --git a/Source/mesquite/parsimony/CharStepsDifference/CharStepsDifference.java b/Source/mesquite/parsimony/CharStepsDifference/CharStepsDifference.java
new file mode 100644
index 0000000..4b35070
--- /dev/null
+++ b/Source/mesquite/parsimony/CharStepsDifference/CharStepsDifference.java
@@ -0,0 +1,211 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.CharStepsDifference;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.pairwise.lib.PairMaker;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class CharStepsDifference extends NumberForTree {
+	public String getName() {
+		return "Difference in steps in two characters";
+	}
+	public String getExplanation() {
+		return "Calculates the difference between two characters in parsimony steps for a given tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters from which to calculate a difference in parsimony steps.",
+				"You can request a source of characters when " + getName() + " starts, or later under the Source of Characters submenu.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(CharacterSteps.class, getName() + " uses a module to calculate parsimony steps.",
+				"The parsimony steps module is employed automatically; you don't have to do anything to choose it.");
+		//e.setAsEntryPoint(true);
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber stepsA, stepsB;
+	CharSourceCoordObed characterSourceTask;
+	CharacterSteps charStepsTask;
+	Taxa oldTaxa = null;
+	CharacterDistribution charStatesA, charStatesB;
+	int currentCharA = 0;
+	int currentCharB = 1;
+	long oldTreeID;
+	long oldTreeVersion;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		stepsA=new MesquiteNumber();
+		stepsB=new MesquiteNumber();
+		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		charStepsTask = (CharacterSteps)hireEmployee(CharacterSteps.class, null);
+		if (charStepsTask == null)
+			return sorry(getName() + " couldn't start because no steps counting module was obtained.");
+		addMenuItem( "Choose First Character...", makeCommand("chooseCharacterA",  this));
+		addMenuItem( "Choose Second Character...", makeCommand("chooseCharacterB",  this));
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m==charStepsTask || m == characterSourceTask)
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		characterSourceTask.initialize(tree.getTaxa());
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		stepsA.setValue((int)0);
+		stepsB.setValue((int)0);
+		Taxa taxa = tree.getTaxa();
+		if (taxa != oldTaxa && oldTaxa!=null || (characterSourceTask.usesTree() && (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion))) {
+			currentCharA = 0;
+			charStatesA = null;
+			currentCharB = 1;
+			charStatesB = null;
+			oldTreeID = tree.getID();
+			oldTreeVersion = tree.getVersionNumber();
+		}
+		if (charStatesA == null) {
+			if (currentCharA<0 || currentCharA>=characterSourceTask.getNumberOfCharacters(tree))
+				currentCharA = 0;
+			charStatesA = characterSourceTask.getCharacter(tree, currentCharA);
+		}
+		result.setToUnassigned();
+		charStepsTask.calculateNumber(tree, charStatesA, result, resultString);
+		if (charStatesB == null) {
+			if (currentCharB<0 || currentCharB>=characterSourceTask.getNumberOfCharacters(tree))
+				currentCharB = 0;
+			charStatesB = characterSourceTask.getCharacter(tree, currentCharB);
+		}
+		stepsA.setToUnassigned();
+		stepsB.setToUnassigned();
+		charStepsTask.calculateNumber(tree, charStatesA, stepsA, resultString);
+		charStepsTask.calculateNumber(tree, charStatesB, stepsB, resultString);
+		oldTaxa = taxa;
+		result.setValue(stepsA);
+		result.subtract(stepsB);
+		if (resultString!=null)
+			resultString.append("Difference in steps: " + result + " (char. " + CharacterStates.toExternal(currentCharA) + " - " + CharacterStates.toExternal(currentCharB) + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			//currentCharA = 0;
+			charStatesA = null;
+			//currentCharB = 1;
+			charStatesB = null;
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacters " + CharacterStates.toExternal(currentCharA) + " " + CharacterStates.toExternal(currentCharB));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what first character to use", null, commandName, "chooseCharacterA")) {
+			int ic=characterSourceTask.queryUserChoose(oldTaxa, " to count steps ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentCharA = ic;
+				charStatesA = null;
+				parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what second character to use", null, commandName, "chooseCharacterB")) {
+			int ic=characterSourceTask.queryUserChoose(oldTaxa, " to count steps ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentCharB = ic;
+				charStatesB = null;
+				parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the characters to use", "[first character number] [second character number]", commandName, "setCharacters")) {
+			String a = parser.getFirstToken(arguments);
+			String b = parser.getNextToken();
+			int icNumA = MesquiteInteger.fromString(a);
+			int icNumB = MesquiteInteger.fromString(b);
+			if (!MesquiteInteger.isCombinable(icNumA) || !MesquiteInteger.isCombinable(icNumB))
+				return null;
+			int icA = CharacterStates.toInternal(icNumA);
+			if ((icA>=0) && characterSourceTask.getNumberOfCharacters(oldTaxa)==0) {
+				currentCharA = icA;
+				charStatesA = null;
+			}
+			else if ((icA>=0) && (icA<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+				currentCharA = icA;
+				charStatesA = null;
+				parametersChanged(); 
+			}
+			int icB = CharacterStates.toInternal(icNumB);
+			if ((icB>=0) && characterSourceTask.getNumberOfCharacters(oldTaxa)==0) {
+				currentCharB = icB;
+				charStatesB = null;
+			}
+			else if ((icB>=0) && (icB<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+				currentCharB = icB;
+				charStatesB = null;
+				parametersChanged(); 
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (characterSourceTask==null)
+			return "Char. " + CharacterStates.toExternal(currentCharA) + " - char. " + CharacterStates.toExternal(currentCharB);
+		else
+			return "Char. " + CharacterStates.toExternal(currentCharA) + " - char. " + CharacterStates.toExternal(currentCharB) + " from " + characterSourceTask.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		return "Steps difference";
+	}
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/ConsistIndexChar/ConsistIndexChar.java b/Source/mesquite/parsimony/ConsistIndexChar/ConsistIndexChar.java
new file mode 100644
index 0000000..316695c
--- /dev/null
+++ b/Source/mesquite/parsimony/ConsistIndexChar/ConsistIndexChar.java
@@ -0,0 +1,119 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ConsistIndexChar;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class ConsistIndexChar extends NumberForCharAndTree {
+	public String getName() {
+		return "Consistency Index for Character";
+	}
+	public String getExplanation() {
+		return "Calculates the Consistency Index (CI) for a tree and character." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(mesquite.parsimony.ParsCharSteps.ParsCharSteps.class, getName() + " needs parsimony character steps calculated.",
+		"This is hired automatically.");
+
+	}
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	/*.................................................................................................................*/
+	CharacterSteps stepsTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		stepsTask = (CharacterSteps)hireNamedEmployee(CharacterSteps.class, "#ParsCharSteps");
+		if (stepsTask == null)
+			return sorry(getName() + " couldn't start because no calculator of parsimony steps could be obtained.");
+		return true; //false if no appropriate employees!
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==stepsTask)
+			iQuit();
+	}
+
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, CharacterDistribution observedStates){
+	}
+	MesquiteTree bush;
+	MesquiteNumber onTree = new MesquiteNumber();
+	MesquiteNumber onSoftBush = new MesquiteNumber();
+	/*.................................................................................................................*/
+	/*in future this will farm out the calculation to the modules that deal with appropriate character model*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (observedStates==null || tree == null || !(tree instanceof MesquiteTree)) {
+			return;
+		}
+		onTree.setToUnassigned();
+		onSoftBush.setToUnassigned();
+		stepsTask.calculateNumber(tree, observedStates, onTree, resultString);
+
+		if (bush == null)
+			bush = new MesquiteTree(observedStates.getTaxa());
+		bush.setToClone((MesquiteTree)tree);  //this used rather than setToDefaultBush in case incoming tree doesn't include all taxa
+		bush.collapseAllBranches(bush.getRoot(), false, false);
+		/** Sets the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+
+		bush.setPolytomiesAssumption(1, false);  //soft
+		stepsTask.calculateNumber(bush, observedStates, onSoftBush, resultString);
+
+		result.setValue(onSoftBush);
+		if (onTree.isZero())
+			result.setValue(0);
+		else
+			result.divideBy(onTree);
+
+		//(minimum)/(steps)
+		saveLastResult(result);
+		if (resultString != null)
+			resultString.setValue("C.I.: " + result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module in very short form.  For use for column headings and other constrained places.  Unless overridden returns getName()*/
+	public String getVeryShortName(){
+		return "C.I.";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/ConsistIndexMatrix/ConsistIndexMatrix.java b/Source/mesquite/parsimony/ConsistIndexMatrix/ConsistIndexMatrix.java
new file mode 100644
index 0000000..5ea5e46
--- /dev/null
+++ b/Source/mesquite/parsimony/ConsistIndexMatrix/ConsistIndexMatrix.java
@@ -0,0 +1,111 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ConsistIndexMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class ConsistIndexMatrix extends NumberForMatrixAndTree {
+	public String getName() {
+		return "Consistency Index for Matrix ";
+	}
+	public String getExplanation() {
+		return "Calculates the Consistency Index (CI) for a tree and matrix.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix.class, getName() + " uses a module to calculate treelength.",
+		"The treelength module is employed automatically; you don't have to do anything to choose it.");
+		//e.setAsEntryPoint(true);
+	}
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	/*.................................................................................................................*/
+	NumberForMatrixAndTree lengthTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		lengthTask = (NumberForMatrixAndTree)hireNamedEmployee(NumberForMatrixAndTree.class, "#TreelengthForMatrix");
+		if (lengthTask == null)
+			return sorry(getName() + " couldn't start because no calculator of treelength could be obtained.");
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, MCharactersDistribution matrix){
+	}
+	MesquiteTree bush;
+	MesquiteNumber onTree = new MesquiteNumber();
+	MesquiteNumber onSoftBush = new MesquiteNumber();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MCharactersDistribution matrix, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || tree == null || matrix == null)
+			return;
+		if (resultString !=null)
+			resultString.setValue("");
+	   	clearResultAndLastResult(result);
+
+		if (matrix==null || tree == null || !(tree instanceof MesquiteTree)) {
+			return;
+		}
+		onTree.setToUnassigned();
+		onSoftBush.setToUnassigned();
+
+		lengthTask.calculateNumber(tree, matrix, onTree, resultString);
+
+		if (bush == null)
+			bush = new MesquiteTree(matrix.getTaxa());
+		bush.setToClone((MesquiteTree)tree);  //this used rather than setToDefaultBush in case incoming tree doesn't include all taxa
+		bush.collapseAllBranches(bush.getRoot(), false, false);
+		/** Sets the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+
+		bush.setPolytomiesAssumption(1, false);  //soft
+		lengthTask.calculateNumber(bush, matrix, onSoftBush, resultString);
+
+		result.setValue(onSoftBush);
+		if (onTree.isZero())
+			result.setValue(0);
+		else
+			result.divideBy(onTree);
+
+		//(minimum)/(steps)
+		saveLastResult(result);
+		if (resultString != null)
+			resultString.setValue("C.I.: " + result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/CurrentParsModels/CurrentParsModels.java b/Source/mesquite/parsimony/CurrentParsModels/CurrentParsModels.java
new file mode 100644
index 0000000..8b12b8a
--- /dev/null
+++ b/Source/mesquite/parsimony/CurrentParsModels/CurrentParsModels.java
@@ -0,0 +1,299 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.CurrentParsModels;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/* Returns parsimony model currently assigned to a character. If none assigned, returns the default model. */
+public class CurrentParsModels extends ParsModelSource implements MesquiteListener {
+	public String getName() {
+		return "Current Parsimony Models";
+	}
+	public String getExplanation() {
+		return "Supplies the currently assigned parsimony model (e.g., \"unordered\") for a character." ;
+	}
+	/*.................................................................................................................*/
+	ModelSet currentModelSet;
+	String preferred = "Parsimony";
+	Class defaultStateClass;
+	CharacterData currentData = null;
+	int currentChar;
+	boolean reassignable = false;
+	CharacterModel lastModel;
+	MesquiteSubmenuSpec smenu;
+	MesquiteMenuItemSpec aboutItem;
+	Class oldStateClass;
+	CharacterModel defaultModel;
+	MesquiteString modelName;
+	LongArray ids;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getProject().getCentralModelListener().addListener(this);
+		ids = new LongArray(20);
+		modelName = new MesquiteString();
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		int code = Notification.getCode(notification);
+		if (obj instanceof ParsimonyModel && code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED) {
+			if (!reassignable || obj == lastModel || (ids.indexOf(((ParsimonyModel)obj).getID())>=0)) {
+				outputInvalid();
+				parametersChanged(notification);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof ParsimonyModel) {
+			if (!reassignable || obj == lastModel) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** returns model for character ic in data */
+	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+
+		currentData = data;
+		currentChar = ic;
+		if (data==null) {
+			MesquiteMessage.warnProgrammer("DATA NULL in Current Parsimony Models;  getModelCurrentCharacter (a)");
+			lastModel = null;
+			modelName.setValue("");
+			if (reassignable)
+				MesquiteTrunk.resetCheckMenuItems();
+			return null;
+		}
+		else {
+
+			if (data.getStateClass()!=oldStateClass)
+				resetCurrent(data.getStateClass());
+			CharacterModel cm=null;
+			currentModelSet = (ModelSet)data.getCurrentSpecsSet(ParsimonyModelSet.class);
+			if (currentModelSet == null) {
+				cm= data.getDefaultModel(preferred);
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (b)");
+			}
+			else {
+				cm = currentModelSet.getModel(ic);
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (c)");
+			}
+			if (reassignable && lastModel != cm)
+				MesquiteTrunk.resetCheckMenuItems();
+			lastModel = cm;
+			modelName.setValue(lastModel.getName());
+			if (ids.indexOf(cm.getID())<0)
+				if (!ids.fillNextUnassigned(cm.getID())){
+					ids.resetSize(ids.getSize()+10);
+					ids.fillNextUnassigned(cm.getID());
+				}
+			return cm;
+		}
+	}
+
+	/** returns model for character */
+	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		if (states==null) {
+			MesquiteMessage.warnProgrammer("STATES NULL in Current Parsimony Models; getModelCurrentCharacter (d)");
+			lastModel = null;
+			modelName.setValue("");
+			if (reassignable)
+				MesquiteTrunk.resetCheckMenuItems();
+			return null;
+		}
+		else {
+			if (states.getStateClass()!=oldStateClass)
+				resetCurrent(states.getStateClass());
+
+			CharacterModel cm=null;
+			CharacterData data = states.getParentData();
+			currentData = data;
+			if (data == null) {
+				if (defaultModel == null || !defaultModel.getStateClass().isAssignableFrom(states.getStateClass()))
+					defaultModel = states.getDefaultModel(getProject(), preferred);
+				cm = defaultModel;
+
+				if (cm==null)
+					MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (e)");
+			}
+			else {
+				int ic =  states.getParentCharacter(); 
+				currentChar = ic;
+				currentModelSet = (ModelSet)data.getCurrentSpecsSet(ParsimonyModelSet.class);
+				if (currentModelSet == null) {
+					if (states!=null) {
+						cm= states.getDefaultModel(getProject(), preferred);
+						if (cm==null)
+							MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (f)");
+					}
+					else
+						MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (g)");
+				}
+				else {
+					cm = currentModelSet.getModel(ic);
+					if (cm==null && states!=null)
+						cm= states.getDefaultModel(getProject(), preferred);
+					if (cm==null) {
+						MesquiteMessage.warnProgrammer("MODEL NULL in Current Parsimony Models; getModelCurrentCharacter (h) " + ic);
+						MesquiteMessage.warnProgrammer("data " + data.getName() + "  " + data);
+					}
+				}
+			}
+			if (reassignable && lastModel != cm)
+				MesquiteTrunk.resetCheckMenuItems();
+			lastModel = cm;
+			if (lastModel!=null)
+				modelName.setValue(lastModel.getName());
+			if (cm == null)
+				return null;
+			if (ids.indexOf(cm.getID())<0)
+				if (!ids.fillNextUnassigned(cm.getID())){
+					ids.resetSize(ids.getSize()+10);
+					ids.fillNextUnassigned(cm.getID());
+				}
+			return cm;
+		}
+	}
+	void resetCurrent(Class stateClass){
+		oldStateClass = stateClass;
+		if (smenu!=null) {
+			deleteMenuItem(smenu);
+			smenu=null;
+		}   		
+		if (reassignable) {
+			smenu = addSubmenu(null, "Parsimony model", makeCommand("setModel", this), getProject().getCharacterModels());
+			smenu.setCompatibilityCheck(new ModelCompatibilityInfo(ParsimonyModel.class, stateClass));
+			smenu.setSelected(modelName);
+		}
+		resetContainingMenuBar();
+		MesquiteTrunk.resetCheckMenuItems();
+	}
+	/*.................................................................................................................*/
+	/* If this is called passing true, module will assume that there will be an implicit "current character" (e.g., in trace character) and thus will allow user
+	to set model of this current character.  The "current" will be assumed the last character for which model requested. */
+	public void setOneCharacterAtATime(boolean chgbl){
+		if (!chgbl)
+			deleteMenuItem(aboutItem);
+		else if (aboutItem == null)
+			aboutItem = addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+
+		reassignable = chgbl;
+		Class stateClass = null;
+		if (currentData!=null)
+			stateClass = currentData.getStateClass();
+		resetCurrent(stateClass);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (defaultModel !=null)
+			temp.addLine("setDefaultModel "+ getProject().getWhichCharacterModel(null, defaultModel));
+		return temp;
+	}
+	/*.................................................................................................................*
+    	 public String getParameters() {
+		return "CurrentParsModels timer " + timer.getAccumulatedTime() + " timer2 " + timer2.getAccumulatedTime() + " timer3 " + timer3.getAccumulatedTime() + " timer4 " + timer4.getAccumulatedTime() + " timer5 " + timer5.getAccumulatedTime();
+   	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the parsimony character model, subject to compatibility with current state class", "[number of model]", commandName, "setModel")) {
+			if (currentData == null){
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				defaultModel = getProject().getCharacterModel(new ModelCompatibilityInfo(ParsimonyModel.class, oldStateClass), whichModel);
+				parametersChanged();
+				return defaultModel;
+			}
+			else {
+				boolean changed=false;
+				int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (!MesquiteInteger.isCombinable(whichModel))
+					return null;
+				CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(ParsimonyModel.class, currentData.getStateClass()), whichModel);
+
+				ModelSet modelSet  = (ModelSet)currentData.getCurrentSpecsSet(ParsimonyModelSet.class);
+				if (model!=null){
+					if (modelSet == null) {
+						CharacterModel defaultModel =  currentData.getDefaultModel("Parsimony");
+						modelSet= new ParsimonyModelSet("Parsimony Model Set", currentData.getNumChars(), defaultModel, currentData);
+						currentData.storeSpecsSet(modelSet, ParsimonyModelSet.class);
+						currentData.setCurrentSpecsSet(modelSet, ParsimonyModelSet.class);
+						modelSet.addToFile(currentData.getFile(), getProject(), findElementManager(ParsimonyModelSet.class)); 
+					}
+
+					if (modelSet != null) {
+						modelSet.setModel(model, currentChar); 
+						currentData.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //should notify via specs not data???
+					}
+					parametersChanged();
+				}
+				return model;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the parsimony character model", "[number of model]", commandName, "setDefaultModel")) {
+			boolean changed=false;
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(whichModel))
+				return null;
+			defaultModel = getProject().getCharacterModel(whichModel);
+			parametersChanged();
+			return defaultModel;
+		}
+		else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+			String s = "";
+			if (lastModel == null)
+				s = "Sorry, no reference to the last used-model was found";
+			else
+				s = "The most recently used model is \"" + lastModel.getName() + "\".\nExplanation: " + lastModel.getExplanation();
+			discreetAlert( s);
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/parsimony/InitCategParsimony/InitCategParsimony.java b/Source/mesquite/parsimony/InitCategParsimony/InitCategParsimony.java
new file mode 100644
index 0000000..3d1fc27
--- /dev/null
+++ b/Source/mesquite/parsimony/InitCategParsimony/InitCategParsimony.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.parsimony.InitCategParsimony;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+import mesquite.categ.lib.*;
+
+public class InitCategParsimony extends FileInit {
+	public String getName() {
+		return "Initialize predefined categorical parsimony models";
+	}
+	public String getExplanation() {
+		return "Initializes the predefined categorical parsimony models." ;
+	}
+	/*.................................................................................................................*/
+	CharacterModel unorderedModel,orderedModel,irreversibleModel, dolloModel;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+
+		unorderedModel = new UnorderedModel();
+		orderedModel = new OrderedModel();
+		irreversibleModel = new IrreversibleModel();
+		dolloModel = new DolloModel();
+		CategoricalData.registerDefaultModel("Parsimony", "Unordered");
+		DNAData.registerDefaultModel("Parsimony", "Unordered");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been established but not yet read in.*/
+	public void projectEstablished() {
+		unorderedModel.addToFile(null, getProject(), null);
+		orderedModel.addToFile(null, getProject(), null);
+		irreversibleModel.addToFile(null, getProject(), null);
+		dolloModel.addToFile(null, getProject(), null);
+		super.projectEstablished();
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/InitContParsimony/InitContParsimony.java b/Source/mesquite/parsimony/InitContParsimony/InitContParsimony.java
new file mode 100644
index 0000000..e191b70
--- /dev/null
+++ b/Source/mesquite/parsimony/InitContParsimony/InitContParsimony.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.InitContParsimony;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.parsimony.lib.*;
+
+/**/
+public class InitContParsimony extends FileInit {
+	public String getName() {
+		return "Initialize predefined continuous parsimony models";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Initializes the predefined continuous parsimony models." ;
+	}
+	/*.................................................................................................................*/
+	ContParsimonyModel linearModel, squaredModel;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		linearModel = new LinearModel("Linear", ContinuousState.class);
+		squaredModel = new SquaredModel("Squared", ContinuousState.class);
+		ContinuousData.registerDefaultModel("Parsimony", "Squared");
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been established but not yet read in.*/
+	public void projectEstablished() {
+		linearModel.addToFile(null, getProject(), null);
+		squaredModel.addToFile(null, getProject(), null);
+		super.projectEstablished();
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+	/*.................................................................................................................*/
+}
+
+
+
diff --git a/Source/mesquite/parsimony/InitializeParsimony/InitializeParsimony.java b/Source/mesquite/parsimony/InitializeParsimony/InitializeParsimony.java
new file mode 100644
index 0000000..19efebf
--- /dev/null
+++ b/Source/mesquite/parsimony/InitializeParsimony/InitializeParsimony.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.InitializeParsimony;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class InitializeParsimony extends FileInit {
+	public String getName() {
+		return "Initialize Parsimony";
+	}
+	public String getExplanation() {
+		return "Initializes default character models for parsimony." ;
+	}
+	/*.................................................................................................................*/
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public void fileElementAdded(FileElement element) {
+		if (element == null || getProject()==null)
+			return;
+		if (element instanceof CharacterData) {
+			CharacterModel defaultModel=null;
+			ParsimonyModelSet currentParsimonyModels;
+			CharacterData data = (CharacterData)element;
+			if (data.getCurrentSpecsSet(ParsimonyModelSet.class) == null) {
+				defaultModel =  data.getDefaultModel("Parsimony");
+				currentParsimonyModels= new ParsimonyModelSet("UNTITLED", data.getNumChars(), defaultModel, data);
+				currentParsimonyModels.addToFile(element.getFile(), getProject(), null);
+				data.setCurrentSpecsSet(currentParsimonyModels, ParsimonyModelSet.class);
+			}
+			if (getProject().getCharacterModels()==null)
+				MesquiteMessage.warnProgrammer("charModels null in iMS Init Pars");
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/parsimony/ManageTypesets/ManageTypesets.java b/Source/mesquite/parsimony/ManageTypesets/ManageTypesets.java
new file mode 100644
index 0000000..323a1e8
--- /dev/null
+++ b/Source/mesquite/parsimony/ManageTypesets/ManageTypesets.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ManageTypesets;
+/*~~  */
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class ManageTypesets extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.parsimony.TypesetList.TypesetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	public String getName() {
+		return "Manage parsimony model sets";
+	}
+	public String getExplanation() {
+		return "Manages (including NEXUS read/write) parsimony model sets (TYPESETs)." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+
+	public void elementsReordered(ListableVector v){
+	}
+	/*.................................................................................................................*/
+	public Class getElementClass(){
+		return ParsimonyModelSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Parsimony Model Set";
+	}
+	public String lowerCaseTypeName(){
+		return "parsimony model set";
+	}
+	public String nexusToken(){
+		return "TYPESET";
+	}
+	public String alternativeNexusToken(){
+		return "PARSMODELSET";
+	}
+	public Object getSpecification(String token){
+		return getProject().getCharacterModel((token));
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof ParsimonyModelSet) || !(specification instanceof CharacterModel))
+			return;
+		ObjectSpecsSet sS = (ObjectSpecsSet)specsSet;
+		sS.setProperty(specification,ic);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		CharacterModel defaultModel =  data.getDefaultModel("Parsimony");
+		return new ParsimonyModelSet(name, data.getNumChars(), defaultModel, data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS");
+	}
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		if (specsSet ==null || !(specsSet instanceof ParsimonyModelSet))
+			return null;
+		ModelSet modelSet = (ModelSet)specsSet;
+		String s= "";
+		if (modelSet !=null && (modelSet.getFile()==file || (modelSet.getFile()==null && data.getFile()==file))) {
+			String sT = " ";
+			boolean firstTime = true;
+			Enumeration enumeration = file.getProject().getCharacterModels().elements();
+			while (enumeration.hasMoreElements()){
+				Object obj = enumeration.nextElement();
+				CharacterModel cm = (CharacterModel)obj;
+				String q = ListableVector.getListOfMatches(modelSet.getModels(), cm, CharacterStates.toExternal(0));
+				if (q != null) {
+					if (!firstTime)
+						sT += ", ";
+					sT += StringUtil.tokenize(cm.getNEXUSName()) + ": " + q ;
+					firstTime = false;
+				}
+			}
+			if (!StringUtil.blank(sT)) {
+				s+= "TYPESET " ;
+				if (isCurrent)
+					s += "* ";
+				s+= StringUtil.tokenize(modelSet.getName()) + " ";
+				if (writeLinkWithCharacterMatrixName(file, data))
+					s+= " (CHARACTERS = " +  StringUtil.tokenize(data.getName()) + ")";
+				s+= "  = "+  sT + ";" + StringUtil.lineEnding();
+			}
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new TypesetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+
+}
+
+class TypesetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS")) && commandName.equalsIgnoreCase("TYPESET"));
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsAncestralStates/ParsAncestralStates.java b/Source/mesquite/parsimony/ParsAncestralStates/ParsAncestralStates.java
new file mode 100644
index 0000000..a6c221a
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsAncestralStates/ParsAncestralStates.java
@@ -0,0 +1,286 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsAncestralStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.categ.lib.CategoricalHistory;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class ParsAncestralStates extends CharStatesForNodes {
+	public String getName() {
+		return "Parsimony Ancestral States";
+	}
+	public String getExplanation() {
+		return "Coordinates the parsimony reconstruction of ancestral states." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(ParsAncStatesForModel.class, getName() + " uses various parsimony calculators to handle different assumptions (unordered, ordered, etc.).",
+				"The parsimony calculator used depends on the parsimony model assigned to the character, " + 
+		"for instance the model assigned in the List of Characters window (parsimony model column), which is called the Stored Parsimony Model for the character.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(ParsModelSource.class, getName() + " needs parsimony models to use as assumptions for calculations.",
+				"You can request the source of parsimony models when " + getName() + " starts, or later under the submenu \"Source of parsimony models\".");
+		//e.setAsEntryPoint(true);
+
+	}
+	/*.................................................................................................................*/
+//	CharacterDistribution observedStates;
+	ParsAncStatesForModel reconstructTask;
+	CharacterModelSource modelTask;
+	CharacterModel model = null;
+	boolean oneCharAtTime = false;
+	CharacterHistory statesAtNodes;
+	MesquiteNumber steps;
+	int oldNumTaxa;
+	MesquiteString modelTaskName;
+	boolean firstWarning = true;
+	MesquiteBoolean useMPRsMode;
+	MesquiteCMenuItemSpec mprsModeItem;
+	MesquiteMenuItemSpec mprNumberItem;
+	boolean mprsPermissive = false;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(ParsAncStatesForModel.class);
+		modelTask = (ParsModelSource)hireNamedEmployee(ParsModelSource.class, "#CurrentParsModels");
+		if (modelTask == null)
+			modelTask = (ParsModelSource)hireEmployee(ParsModelSource.class, "Source of parsimony character models");
+		if (modelTask == null)
+			return sorry(getName() + " couldn't start because no source of models of character evolution found.");
+		steps = new MesquiteNumber();
+		modelTaskName = new MesquiteString(modelTask.getName());
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Source of parsimony models", makeCommand("setModelSource", this), ParsModelSource.class);
+		useMPRsMode = new MesquiteBoolean(false);
+		resetMode();
+		mss.setSelected(modelTaskName);
+		return true;  
+	}
+	public  void prepareForMappings(boolean permissiveOfNoSeparateMappings) {
+		useMPRsMode.setValue(true);
+		mprsPermissive = permissiveOfNoSeparateMappings;
+		resetMode();
+
+	}
+	public String getMappingTypeName(){
+		return "MPR";
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModelSource ",modelTask);
+		temp.addLine("toggleMPRsMode " + useMPRsMode.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to supply character models", "[name of module]", commandName, "setModelSource")) {
+			ParsModelSource temp=  (ParsModelSource)replaceEmployee(ParsModelSource.class, arguments, "Source of parsimony character models", modelTask);
+			if (temp!=null) {
+				modelTask= temp;
+				incrementMenuResetSuppression();
+				modelTaskName.setValue(modelTask.getName());
+				modelTask.setOneCharacterAtATime(oneCharAtTime);
+				parametersChanged();
+				decrementMenuResetSuppression();
+			}
+			return modelTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to use MPRs Mode", "[on; off]", commandName, "toggleMPRsMode")) {
+			useMPRsMode.toggleValue(parser.getFirstToken(arguments));
+			resetMode();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Shows the number of MPRs for the character", "", commandName, "calcNumMPRs")) {
+			boolean oldMode = useMPRsMode.getValue();
+			useMPRsMode.setValue(true);
+			resetMode();
+			parametersChanged();
+			long numMPRs = getNumberOfMappings();
+			MesquiteMessage.discreetNotifyUser("Number of MPRs: " + numMPRs);
+			useMPRsMode.setValue(oldMode);
+			resetMode();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void resetMode(){
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ParsAncStatesForModel)
+				((ParsAncStatesForModel)e).setCalcConditionalMPRSets(useMPRsMode.getValue());
+		}
+
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m == modelTask)
+			iQuit();
+	}
+	public boolean allowsStateWeightChoice(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void setOneCharacterAtATime(boolean chgbl){
+		oneCharAtTime = chgbl;
+		modelTask.setOneCharacterAtATime(chgbl);
+		if (chgbl){
+			if (mprsModeItem == null) {
+				mprsModeItem = addCheckMenuItem(null, "MPRs Mode", makeCommand("toggleMPRsMode", this), useMPRsMode);
+				mprNumberItem= addMenuItem( "Number of MPRs...", makeCommand("calcNumMPRs",  this));
+
+			}
+		}
+		else {
+			if (mprsModeItem != null)
+				deleteMenuItem(mprsModeItem);
+			if (mprNumberItem != null)
+				deleteMenuItem(mprNumberItem);
+		}
+
+	}
+
+
+
+
+
+	/*.................................................................................................................*/
+	public  boolean calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory resultStates, MesquiteString resultString) {  
+		this.observedStates = observedStates;
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree==null)
+			return false; 
+		else if (observedStates==null)
+			return false; 
+		else if (resultStates==null)
+			return false; 
+
+		//
+		model = modelTask.getCharacterModel(observedStates);
+		if (model==null) {
+			String mes = "Parsimony calculations could not be completed; no model is available for character: " + observedStates.getName();
+			discreetAlert( mes);
+			statesAtNodes.deassignStates();
+			if (resultString!=null)
+				resultString.setValue(mes);
+			return false;
+		}
+
+
+		//finding a module that can do parsimony calculations for this model 
+		if (reconstructTask == null || !reconstructTask.compatibleWithContext(model, observedStates)) {
+			reconstructTask = null;
+			for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ParsAncStatesForModel)
+					if (((ParsAncStatesForModel)e).compatibleWithContext(model, observedStates)) {
+						reconstructTask=(ParsAncStatesForModel)e;
+					}
+			}
+		}
+		boolean success = false;
+		resultStates.deassignStates();
+		if (reconstructTask != null) {
+			reconstructTask.calculateStates( tree,  observedStates,  resultStates, model, resultString, steps);
+			success = true;
+		}
+		else {
+			if (resultString!=null)
+				resultString.setValue("Ancestral states unassigned.  No compatible module found for model: " + model.getName());
+			if (firstWarning && !MesquiteThread.isScripting()) {
+				String s ="Parsimony ancestral states: NO COMPATIBLE RECONSTRUCTOR FOUND for a character " + observedStates.getName() + " (model = ";
+				s += model.getName() + ") ";
+				alert(s);
+			}
+			if (!MesquiteThread.isScripting())
+				firstWarning = false;
+			
+		}
+		statesAtNodes=resultStates;
+		((CharacterStates)statesAtNodes).setExplanation("Most parsimonious state(s)");
+		if (reconstructTask !=null && reconstructTask.calculatingConditionalMPRSets()){
+			numMappings = statesAtNodes.getNumResolutions(tree);
+			mprsAvailable = true;
+		}
+		else {
+			numMappings =1;
+			mprsAvailable = false;
+		}
+		return success;
+	}
+	/*.................................................................................................................*/
+	long numMappings = 1;
+	boolean mprsAvailable = false;
+	MesquiteString prevResult = new MesquiteString();
+	public  void setObservedStates(Tree tree, CharacterDistribution observedStates){
+		this.tree = tree;
+		this.observedStates = observedStates;
+		statesAtNodes = observedStates.adjustHistorySize(tree, statesAtNodes);
+		calculateStates(tree, observedStates, statesAtNodes, prevResult);
+
+	}
+	public  boolean getMapping(long i, CharacterHistory resultStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+
+		if (useMPRsMode.getValue() && !mprsAvailable && !mprsPermissive){
+			statesAtNodes.deassignStates();
+			if (resultString != null)
+				resultString.setValue("MPRs mode not available for this character type");
+			return false;
+		}
+		else {
+			if (!useMPRsMode.getValue() || !mprsAvailable)
+				statesAtNodes.clone(resultStates);
+			else
+				resultStates = statesAtNodes.getResolution(tree, resultStates, i);
+			if (resultString != null)
+				resultString.setValue(prevResult);
+			return resultStates!=null;
+		}
+	}	
+
+
+
+	public  long getNumberOfMappings(){
+		if (useMPRsMode.getValue() && mprsAvailable)
+			return numMappings;
+		return 1;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsCharSteps/ParsCharSteps.java b/Source/mesquite/parsimony/ParsCharSteps/ParsCharSteps.java
new file mode 100644
index 0000000..14a3d73
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsCharSteps/ParsCharSteps.java
@@ -0,0 +1,173 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsCharSteps;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class ParsCharSteps extends CharacterSteps {
+	public String getName() {
+		return "Parsimony Character Steps";
+	}
+	public String getExplanation() {
+		return "Calculates the number of parsimony steps in a character." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(ParsAncStatesForModel.class, getName() + " uses various parsimony calculators to handle different assumptions (unordered, ordered, etc.).",
+				"The parsimony calculator used depends on the parsimony model assigned to the character, " + 
+		"for instance the model assigned in the List of Characters window (parsimony model column), which is called the Stored Parsimony Model for the character.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(ParsModelSource.class, getName() + " needs parsimony models to use as assumptions for calculations.",
+				"You can request the source of parsimony models when " + getName() + " starts, or later under the submenu \"Source of parsimony models\".");
+		//e.setAsEntryPoint(true);
+
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	MesquiteNumber steps;
+	CharacterModelSource modelTask;
+	MesquiteString modelTaskName;
+	boolean firstWarning = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(ParsAncStatesForModel.class);
+		modelTask = (ParsModelSource)hireNamedEmployee(ParsModelSource.class, "#CurrentParsModels");
+		if (modelTask == null)
+			modelTask = (ParsModelSource)hireEmployee(ParsModelSource.class, "Source of parsimony character models");
+		if (modelTask == null)
+			return sorry(getName() + " couldn't start because no source of models of character evolution obtained.");
+		modelTaskName = new MesquiteString(modelTask.getName());
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Source of parsimony models", makeCommand("setModelSource", this), ParsModelSource.class);
+		mss.setSelected(modelTaskName);
+		steps = new MesquiteNumber();
+		return true; //false if no appropriate employees!
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==modelTask)
+			iQuit();
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModelSource ",modelTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to supply character models", "[name of module]", commandName, "setModelSource")) {
+			ParsModelSource temp=  (ParsModelSource)replaceEmployee(ParsModelSource.class, arguments, "Source of parsimony character models", modelTask);
+			if (temp!=null) {
+				modelTask= temp;
+				incrementMenuResetSuppression();
+				modelTaskName.setValue(modelTask.getName());
+					parametersChanged();
+				decrementMenuResetSuppression();
+			}
+			return modelTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, CharacterDistribution observedStates){
+	}
+	ParsAncStatesForModel reconstructTask = null;
+	boolean  warned = false;
+	/*.................................................................................................................*/
+	/*in future this will farm out the calculation to the modules that deal with appropriate character model*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree==null || observedStates==null) {
+			steps.setToUnassigned();
+			return;
+		}
+
+		this.observedStates = observedStates;
+
+		CharacterModel model = modelTask.getCharacterModel(observedStates);
+
+		if (model==null) {
+			if (!warned){
+				discreetAlert( "Sorry, there is no parsimony model of evolution available for the character; Parsimony character steps cannot be calculated");
+				warned = true;
+			}
+			if (resultString!=null)
+				resultString.setValue("Parsimony calculations could not be completed; no model available for character");
+			result.setToUnassigned();
+			return;
+		}
+
+		//finding a module that can do parsimony calculations for this model 
+		if (reconstructTask == null || !reconstructTask.compatibleWithContext(model, observedStates)) { 
+			reconstructTask = null;
+			for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ParsAncStatesForModel)
+					if (((ParsAncStatesForModel)e).compatibleWithContext(model, observedStates))
+						reconstructTask=(ParsAncStatesForModel)e;
+			}
+		}
+		if (reconstructTask != null) {
+			reconstructTask.calculateSteps( tree,  observedStates, model, resultString, steps);
+		}
+		else {
+			String s = "Parsimony calculations cannot be performed because no module was found to perform the calculations for the model \"" + model.getName() + "\" with the character specified: " +  observedStates.getName();
+			if (firstWarning) {
+				discreetAlert( s);
+				firstWarning = false;
+			}
+			steps.setToUnassigned();
+			if (resultString!=null)
+				resultString.setValue("Steps unassigned because no compatible reconstructor found");
+		}
+		result.setValue(steps);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module in very short form.  For use for column headings and other constrained places.  Unless overridden returns getName()*/
+	public String getVeryShortName(){
+		return "Steps";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsimonyCostMatrix/ParsimonyCostMatrix.java b/Source/mesquite/parsimony/ParsimonyCostMatrix/ParsimonyCostMatrix.java
new file mode 100644
index 0000000..cea3975
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsimonyCostMatrix/ParsimonyCostMatrix.java
@@ -0,0 +1,440 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsimonyCostMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonyCostMatrix extends ParsAncStatesForModel {
+	public String getName() {
+		return "Parsimony Stepmatrix";
+	}
+	public String getExplanation() {
+		return "Reconstructs ancestral states of categorical characters using a stepmatrix (cost matrix)." ;
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	int maxState = CategoricalState.maxCategoricalState;
+	Number2DArray downCost, upCost, finalCost;
+	MesquiteNumber tempNum1, tempNum2, tempNum3, tempNum4, tempNum5;
+	CostMatrixModel model;
+	static boolean alertSoft = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		tempNum1 = new MesquiteNumber(0);
+		tempNum2 = new MesquiteNumber(0);
+		tempNum3 = new MesquiteNumber(0);
+		tempNum4 = new MesquiteNumber(0);
+		tempNum5 = new MesquiteNumber(0);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/*Calculates best cost from ancestral node A through descendant N and above, given the downpass costs stored in costsAbove
+	and given that stateA is at node A*/
+	private MesquiteNumber bestAbove(int stateA, int N, Number2DArray costsAbove, MesquiteNumber result) {
+		result.setToInfinite();
+		for (int state = 0; state <= maxState; state++) {
+			tempNum1 = model.getTransitionValue(stateA, state, tempNum1);
+			costsAbove.placeValue(N, state, tempNum2);
+			tempNum1.add(tempNum2);
+			result.setMeIfIAmMoreThan(tempNum1);
+		}
+		return result;
+	}
+	/*.................................................................................................................*/
+	//returns distance from state1 to 2 to 3, or 1 to 3 to 2, or 1 to 3 and 1 to 2, whichever is shortest
+	private void cascadeDistance(int state1, int state2, int state3, MesquiteNumber result, MesquiteNumber temp1, MesquiteNumber temp2){
+		if (state1==state2) {
+			model.getTransitionValue(state2, state3, result);
+		}
+		else if (state1==state3){
+			model.getTransitionValue(state3, state2, result);
+		}
+		else {
+			model.getTransitionValue(state1, state2, temp1);
+			model.getTransitionValue(state2, state3, temp2);
+			temp2.add(temp1);
+
+			model.getTransitionValue(state1, state3, temp1);
+			model.getTransitionValue(state3, state2, result);
+			result.add(temp1);
+
+			result.setMeIfIAmMoreThan(temp2);
+
+			model.getTransitionValue(state1, state2, temp1);
+			model.getTransitionValue(state1, state3, temp2);
+			temp2.add(temp1);
+
+			result.setMeIfIAmMoreThan(temp2);
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber minToOthers = new MesquiteNumber();
+	/*Sets downpass costs at terminal nodes.  Uses rules as in MacClade*/
+	private void setTerminalDownCosts(int N, Tree tree, MesquiteBoolean dangerousPolymorphism){
+		long stateSetObserved = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+		if (CategoricalState.isUnassigned(stateSetObserved) || CategoricalState.isInapplicable(stateSetObserved))
+			for (int i = 0; i<=maxState; i++)
+				downCost.setToZero(N, i);
+		else {
+			//uncertainty: allow any of possible states with cost 0
+			if (CategoricalState.isUncertain(stateSetObserved)){
+				//for all states in state set observed, place 0 in cost; otherwise place infinite
+				for (int i = 0; i<=maxState; i++)
+					if (CategoricalState.isElement(stateSetObserved, i))
+						downCost.setToZero(N, i);
+					else 
+						downCost.setToInfinite(N, i);
+			}
+			else {
+				int card = CategoricalState.cardinality(stateSetObserved);
+				//polymorphism of two states; for each state put cost to other or other two states
+				if (card == 2) {
+					//two in set; in one, put cost to two
+					int min = CategoricalState.minimum(stateSetObserved);
+					int max = CategoricalState.maximum(stateSetObserved);
+					for (int i = 0; i<=maxState; i++) {
+						cascadeDistance(i, min, max, minToOthers, tempNum2, tempNum3);
+						downCost.setValue(N, i, minToOthers);
+					}
+				}
+				else  if (card == 1) {
+					//monomorphic in set; put infinite except for that state
+					for (int i = 0; i<=maxState; i++)
+						downCost.setToInfinite(N, i);
+					int min = CategoricalState.minimum(stateSetObserved);
+					downCost.setToZero(N, min);
+				}
+				else {
+					dangerousPolymorphism.setValue(true);
+					//2 or more in state set; for each of states, put minimum to states observed, as done by MacClade
+					for (int i = 0; i<=maxState; i++) {
+						if (CategoricalState.isElement(stateSetObserved, i)){
+							minToOthers.setToInfinite();
+							for (int j=0; j<=maxState; j++)
+								if (i!=j && CategoricalState.isElement(stateSetObserved, j)) {
+									tempNum1 = model.getTransitionValue(i, j, tempNum1);
+									minToOthers.setMeIfIAmMoreThan(tempNum1);
+								}
+							downCost.setValue(N, i, minToOthers);
+						}
+						else {
+							minToOthers.setToInfinite();
+							for (int j=0; j<=maxState; j++)
+								if (i!=j && CategoricalState.isElement(stateSetObserved, j)) {
+									for (int k=0;k<=maxState; k++)
+										if (i!=k && k!=j && CategoricalState.isElement(stateSetObserved, k)) {
+											cascadeDistance(i, j, k, tempNum1, tempNum2, tempNum3);
+											minToOthers.setMeIfIAmMoreThan(tempNum1);
+										}
+								}
+							downCost.setValue(N, i, minToOthers);
+						}
+					}
+				}
+			}
+
+		}
+	}
+	/*.................................................................................................................*/
+	private   void downPass(int N, Tree tree, MesquiteBoolean dangerousPolymorphism, MesquiteBoolean softPolys) {
+
+		if (tree.nodeIsTerminal(N)) 
+			setTerminalDownCosts(N, tree, dangerousPolymorphism);
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				downPass(d, tree, dangerousPolymorphism, softPolys);
+
+				for (int state = 0; state <= maxState; state++)
+					downCost.addValue(N, state, bestAbove(state, d, downCost, tempNum3));
+			}
+
+			if (tree.nodeIsSoft(N))
+				softPolys.setValue(true);  //record that soft polys found
+
+			if (N == tree.getRoot())
+				downCost.placeMinimum2nd(N, tempNum1); 
+		}
+
+	}
+	/*.................................................................................................................*/
+	private   void upPass(int N, Tree tree) {
+		if ((tree.nodeIsInternal(N)) && (N!=tree.getRoot())) {
+			for (int stateN = 0; stateN <= maxState; stateN++) { //try each state at N
+				tempNum3.setToInfinite();  //best so far
+				for (int stateA = 0; stateA <= maxState; stateA++) { //try each state at ancestor
+					tempNum4 = model.getTransitionValue(stateA, stateN, tempNum4);  //cost from mother to N
+					for (int d = tree.firstDaughterOfNode(tree.motherOfNode(N)); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+						if (d!=N) {
+							tempNum5 = bestAbove(stateA, d, downCost, tempNum5);  //cost from mother of node to d and above if A at mother
+							tempNum4.add(tempNum5);  
+						}
+					}
+					//get upstate from ancestor
+					if (tree.motherOfNode(N)!=tree.getRoot()) {
+						upCost.placeValue(tree.motherOfNode(N), stateA, tempNum5);
+						tempNum4.add(tempNum5);  
+					}
+					tempNum3.setMeIfIAmMoreThan(tempNum4);  //if best so far, remember it
+				}
+				upCost.setValue(N, stateN, tempNum3);
+			}
+		}
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			upPass(d, tree);
+	}
+	/*.................................................................................................................*/
+	/*Assigning final states using uppass and downpass results*/
+	public   void finalPass(int N, Tree tree, CategoricalHistory statesAtNodes) {
+		if (N==tree.getRoot()){
+			downCost.placeMinimum2nd(N, tempNum1); 
+			long best=0;
+			for (int state = 0; state<= maxState; state++) {
+				if (downCost.equals(N,state, tempNum1))
+					best = CategoricalState.addToSet(best, state);
+			}
+			statesAtNodes.setState(N, best);
+		}
+		else if (tree.nodeIsTerminal(N)) {
+			long stateSetObserved = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+			if (CategoricalState.isUnassigned(stateSetObserved) || CategoricalState.isInapplicable(stateSetObserved))
+				statesAtNodes.setState(N, statesAtNodes.getState(tree.motherOfNode(N)));
+			else {
+				if (CategoricalState.isUncertain(stateSetObserved)){
+					long ancStates = statesAtNodes.getState(tree.motherOfNode(N));
+					tempNum1.setToUnassigned();
+					long result = 0L;
+					// find the states in observed closest to state set below
+					for (int desc = 0; desc<=maxState; desc++) {
+						if (CategoricalState.isElement(stateSetObserved, desc ))
+							for (int anc =0; anc<=maxState; anc++)
+								if (CategoricalState.isElement(ancStates, anc)) {
+									tempNum2 = model.getTransitionValue(anc, desc, tempNum2);
+									if (tempNum2.equals(tempNum1)) {
+										result = CategoricalState.addToSet(result, anc);
+									}
+									else if (tempNum2.isLessThan(tempNum1)) {
+										result = CategoricalState.makeSet(anc);
+										tempNum1.setValue(tempNum2);
+									}
+								}
+
+					}
+					statesAtNodes.setState(N,result);
+				}
+				else
+					statesAtNodes.setState(N,stateSetObserved);
+			}
+		}
+		else {
+			// accumulate downstates from daughters
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				for (int state = 0; state <= maxState; state++)
+					finalCost.addValue(N, state, bestAbove(state, d, downCost, tempNum3));
+			}
+			for (int state = 0; state <= maxState; state++)
+				finalCost.addValue(N, state, bestAbove(state, N, upCost, tempNum3));
+			//find all with minimal final cost
+			finalCost.placeMinimum2nd(N, tempNum1);
+			long best=0;
+			for (int state = 0; state<= maxState; state++) {
+				if (finalCost.equals(N,state, tempNum1))
+					best = CategoricalState.addToSet(best, state);
+			}
+			statesAtNodes.setState(N, best);
+		}
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			finalPass(d, tree, statesAtNodes);
+	}
+	/*...................................................FOR DEBUGGING..............................................................*/
+	private   void resetStates(int N, Tree tree, CategoricalHistory statesAtNodes, CategoricalHistory fromStates) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			resetStates(d, tree, statesAtNodes, fromStates);
+		}
+		statesAtNodes.setState(N, fromStates.getState(N));
+	}
+	/*.................................................................................................................*
+	//for debugging
+	private void showStates(Number2DArray s){
+		for (int node = 2; node<8; node++){
+			logln("node " + node);
+			String m = "";
+			for (int i=0; i<6; i++){
+				m += "(" + i + " = " + s.toString(node, i) + ") ";
+			}
+			logln("   " + m);
+
+		}
+	}
+	/*.................................................................................................................*/
+	/*Resizing matrices as needed for tree size*/
+	void adjustStorage(Tree tree) {
+		if (downCost==null)
+			downCost = new Number2DArray(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+		else if (downCost.getSizeC()!=tree.getNumNodeSpaces()) //had been getlengthx
+			downCost.resetSize(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+		if (upCost==null)
+			upCost = new Number2DArray(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+		else if (upCost.getSizeC()!=tree.getNumNodeSpaces())
+			upCost.resetSize(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+		if (finalCost==null)
+			finalCost = new Number2DArray(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+		else if (finalCost.getSizeC()!=tree.getNumNodeSpaces())
+			finalCost.resetSize(tree.getNumNodeSpaces(), CategoricalState.maxCategoricalState+1);
+	}
+	/*.................................................................................................................*/
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	boolean warnedSoftPoly = false;
+	boolean warnedUnrooted = false;
+	/*Checking that situation allows calculations to proceed*/
+	public boolean warn(Tree tree, CharacterDistribution observedStates, CostMatrixModel model, MesquiteString resultString){
+		if (tree == null || observedStates == null || model == null)
+			return false;
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in step matrix parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched){
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (!tree.getRooted() && !model.isSymmetrical()) {
+			String message = "Unrooted trees not allowed in calculations with asymmetrical stepmatrices.  Calculations for one or more trees were not completed.";
+			if (!warnedUnrooted){
+				discreetAlert( message);
+				warnedUnrooted = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in step matrix parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation){
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasSoftPolytomies(tree.getRoot())) {
+			String message = "Trees with soft polytomies not allowed in step matrix parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedSoftPoly){
+				discreetAlert( message);
+				warnedSoftPoly = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber steps) {  
+		if (model==null || observedStates==null || tree == null)
+			return;
+		if (steps!=null)
+			steps.setToUnassigned();
+		if (warn(tree, observedStates, (CostMatrixModel)model, resultString))
+			return;
+		if (resultString!=null)
+			resultString.setValue("");
+		this.model = (CostMatrixModel)model;
+		this.observedStates = observedStates;
+		//maxState, tempnums may give reentrancy problems, but best not to reinstantiate tempnums for each call
+		maxState = this.model.getMaxState();
+		adjustStorage(tree);
+		downCost.deassignArray();
+		upCost.deassignArray();
+		finalCost.deassignArray();
+
+		MesquiteBoolean softPolys = new MesquiteBoolean(false);
+		MesquiteBoolean dangerousPolymorphism = new MesquiteBoolean(false);
+		downPass(tree.getRoot(), tree, dangerousPolymorphism, softPolys);
+
+		if (steps!=null)
+			downCost.placeMinimum2nd(tree.getRoot(), steps);
+		upPass(tree.getRoot(), tree);
+		finalPass(tree.getRoot(), tree, (CategoricalHistory)statesAtNodes);
+		((CategoricalHistory)statesAtNodes).polymorphToUncertainties(tree.getRoot(), tree);
+		if (resultString!=null) {
+			resultString.setValue("Parsimony reconstruction (stepmatrix: " + model.getName() + ") [Steps: " + steps + "]");
+			if (softPolys.getValue())
+				resultString.append(" NOTE: Soft polytomies encountered; reconstruction may be incorrect.");  //in fact, not reached because soft polys not allowed
+			if (dangerousPolymorphism.getValue())
+				resultString.append(" NOTE: Some terminal taxa polymorphic with more than two states; reconstruction may be incorrect.");
+		}
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber steps) {  
+		if (model==null || observedStates==null || tree == null || steps == null)
+			return;
+		if (steps!=null)
+			steps.setToUnassigned();
+		if (warn(tree, observedStates,  (CostMatrixModel)model, resultString))
+			return;
+		if (resultString!=null)
+			resultString.setValue("");
+		this.model = (CostMatrixModel)model;
+		this.observedStates = observedStates;
+		maxState = this.model.getMaxState();
+		adjustStorage(tree);
+		downCost.deassignArray();
+
+		MesquiteBoolean softPolys = new MesquiteBoolean(false);
+		MesquiteBoolean dangerousPolymorphism = new MesquiteBoolean(false);
+		downPass(tree.getRoot(), tree, dangerousPolymorphism, softPolys);
+		downCost.placeMinimum2nd(tree.getRoot(), steps);
+		if (resultString!=null) {
+			resultString.setValue("Parsimony steps: " + steps + " (stepmatrix: " + model.getName() + ")");
+			if (softPolys.getValue())
+				resultString.append(" NOTE: Soft polytomies encountered; steps may be incorrectly counted."); //in fact, not reached because soft polys not allowed
+			if (dangerousPolymorphism.getValue())
+				resultString.append(" NOTE: Some terminal taxa polymorphic with more than two states; steps may be incorrectly counted.");
+		}
+	}
+
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return (model instanceof CostMatrixModel) && observedStates instanceof CategoricalDistribution;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+
+	public String getModelTypeName(){
+		return "Stepmatrix model";
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsimonyLinear/ParsimonyLinear.java b/Source/mesquite/parsimony/ParsimonyLinear/ParsimonyLinear.java
new file mode 100644
index 0000000..82ff27a
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsimonyLinear/ParsimonyLinear.java
@@ -0,0 +1,362 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsimonyLinear;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonyLinear extends ParsAncStatesForModel {
+	public String getName() {
+		return "Parsimony Linear";
+	}
+	public String getExplanation() {
+		return "Reconstructs the ancestral states of continuous characters so as to minimize the sum of absolute values of changes (linear, Wagner, Farris or Manhattan parsimony).  If the continuous character has multiple items, then length is reported on only the first item." ;
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	ContinuousHistory finalMin, finalMax, upMin, upMax, downMin, downMax;
+	MesquiteDouble dummy, temp1, temp2, NYLength;
+	double overallMin = MesquiteDouble.unassigned;
+	double overallMax = MesquiteDouble.unassigned;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		dummy = new MesquiteDouble(0);
+		temp1 = new MesquiteDouble(0);
+		temp2 = new MesquiteDouble(0);
+		NYLength = new MesquiteDouble(0);
+		return true;
+	}
+
+	/*----------------------------------------------------------------------- */
+	/*----------------------------------------------------------------------- */
+	void combine (MesquiteDouble minA, MesquiteDouble maxA, double minD, double maxD, double minE, double maxE, MesquiteDouble  inc) {
+		/*This is the continuous value state set operator; takes state ranges}
+	{[minD..maxD] and [minE..maxE] and combines them and outputs range [minA..maxA]}
+	{inc is the increment on length caused by the combining */
+		if (minD < minE) {
+			if (maxD < minE) {  //{DDDDD EEEEE}
+				minA.setValue(maxD);
+				maxA.setValue(minE);
+				inc.add(minE - maxD);
+			}
+			else if (maxD < maxE) {  //{DDDDDEDEDEEEEE}
+				minA.setValue(minE);
+				maxA.setValue(maxD);
+			}
+			else {  //{DDDDEDEDEDDDDD}
+				minA.setValue(minE);
+				maxA.setValue(maxE);
+			}
+		}
+		else {
+			if (maxE < minD) {	//{EEEEEEE   DDDDDDD}
+				minA.setValue(maxE);
+				maxA.setValue(minD);
+				inc.add(minD - maxE);
+			}
+			else if (maxE < maxD) {   //{EEEEEEDEDEDDDDDD}
+				minA.setValue(minD);
+				maxA.setValue(maxE);
+			}
+			else {   //{EEEEEEDEDEDEEEEE}
+				minA.setValue(minD);
+				maxA.setValue(maxD);
+			}
+		}
+	}
+
+	/*_____________________________________________________________________ */
+	void doCombineOneThenOther (MesquiteDouble minA, MesquiteDouble maxA, double min11,double  max11, double min22, double max22, double min33, double  max33) {
+		combine(minA, maxA, min11, max11, min22, max22, dummy);
+		combine(minA, maxA, minA.getValue(), maxA.getValue(), min33, max33, dummy);
+	}
+
+	/*_____________________________________________________________________ */
+	void combinefromGreatestMin (MesquiteDouble minA, MesquiteDouble maxA, double minG,double  maxG, double min22, double max22, double min33, double  max33) {
+		/*{here minG, maxG are min and max of set with rightmost minimum}
+	{First we find out which of the other sets' maximum is the furthest left of minG, if either is}*/
+		if (max33 < minG) {
+			if (max22 < max33) //{max22 furthest left, and is left of minG; Thus combine set G and set 22 first, then 33}
+				doCombineOneThenOther(minA, maxA, minG, maxG, min22, max22, min33, max33);
+			else //{max33 furthest left, and is left of minG; Thus combine set G and set 33 first, then 22}
+				doCombineOneThenOther(minA, maxA, minG, maxG, min33, max33, min22, max22);
+		}
+		else
+			/*{Either: max22 furthest left, and is left of minG; Thus combine set G and set 22 first, then 33}
+			{Or: Both max22 and max33 are right of minG, thus there must be triple intersection, and order doesn't matter}*/
+			doCombineOneThenOther(minA, maxA, minG, maxG, min22, max22, min33, max33);
+	}
+
+	/*_____________________________________________________________________ */
+	void tripleCombine (MesquiteDouble minA, MesquiteDouble maxA, double minD, double maxD, double minE, double maxE, double minF, double maxF) {
+		/*{This is the continuous value state set operator for 3 SETS; takes state ranges}
+	{[minD..maxD], [minE..maxE] and [minF..maxF] and combines them and outputs range [minA..maxA]}
+	{Uses the trick of taking two most distant state sets, applying binary set operator on them, then}
+	{taking result and combine it with third set using binary set operator again}*/
+		if (minD < minE) {
+			if (minE < minF)  	//{� minF is greatest}
+				combinefromGreatestMin(minA, maxA, minF, maxF, minD, maxD, minE, maxE);
+			else 					//{� minE greatest}
+				combinefromGreatestMin(minA, maxA, minE, maxE, minD, maxD, minF, maxF);
+		}
+		else if (minF > minD) //{� minF greatest}
+			combinefromGreatestMin(minA, maxA, minF, maxF, minD, maxD, minE, maxE);
+		else  						//{� minD greatest}
+			combinefromGreatestMin(minA, maxA, minD, maxD, minF, maxF, minE, maxE);
+	}
+
+	/*_____________________________________________________________________ */
+	/*{find min max range among observed for missing data}*/
+	void NYsurvey (int numTaxa, ContinuousDistribution observedStates,  int item) {
+		overallMin = MesquiteDouble.unassigned;
+		overallMax = MesquiteDouble.unassigned;
+		for (int i=0; i<numTaxa; i++) {
+			overallMin = MesquiteDouble.minimum(overallMin, observedStates.getState(i, item));
+			overallMax = MesquiteDouble.maximum(overallMax, observedStates.getState(i, item));
+		}
+	}
+	//TODO: allow missing data!
+	//TODO: handle multiple items better; should use min and max items if available
+	/*_____________________________________________________________________ */
+	/*{Downpass of linear parsimony on continuous characters}*/
+	void NYdown (Tree tree, int N, int item) {
+		if (tree.nodeIsInternal(N)) {  
+			int L = tree.firstDaughterOfNode(N, deleted);
+			int R = tree.lastDaughterOfNode(N, deleted);
+			NYdown(tree, L, item);  //ASSUMES dichtomous
+			NYdown(tree, R, item);
+			//->downMin is minimum of state range; ->downMax is maximum}
+			//note here we let combine increment the NYlength during downpass}
+			combine(temp1, temp2, downMin.getState(L), downMax.getState(L), downMin.getState(R),downMax.getState(R), NYLength);
+			downMin.setState(N, temp1.getValue());
+			downMax.setState(N, temp2.getValue());
+		}
+		else { //terminal node
+			double ts = ((ContinuousDistribution)observedStates).getState(tree.taxonNumberOfNode(N), item);
+			if (MesquiteDouble.isUnassigned(ts)) {
+				downMin.setState(N, overallMin);
+				downMax.setState(N, overallMax);
+			}
+			else {
+				downMin.setState(N, ts);
+				downMax.setState(N, downMin.getState(N)); 
+			}
+		}
+	}
+	/*_____________________________________________________________________ */
+	/*This is combined UpPass and FinalPass for continuous characters, linear parsimony}*/
+
+	void NYfinal (Tree tree, int N, ContinuousHistory statesAtNodes, int itemMin, int itemMax) {
+		if (tree.nodeIsInternal(N)) {  
+			int L = tree.firstDaughterOfNode(N, deleted);
+			int R = tree.lastDaughterOfNode(N, deleted);
+			if (N == tree.getRoot(deleted))  {
+				finalMin.setState(N, downMin.getState(N));  //{use downpass states for root's final}
+				finalMax.setState(N, downMax.getState(N));  //{use downpass states for root's final}
+			}
+			else {
+				//{First calculate up states}
+				int anc = tree.motherOfNode(N, deleted);
+				int sis = tree.nextSisterOfNode(N, deleted);
+				if (!tree.nodeExists(sis))
+					sis = tree.previousSisterOfNode(N, deleted);
+				if (anc == tree.getRoot(deleted)) {
+					upMin.setState(N, downMin.getState(sis));
+					upMax.setState(N, downMax.getState(sis));
+				}
+				else {
+					dummy.setValue(0);
+					combine(temp1, temp2, upMin.getState(anc), upMax.getState(anc), downMin.getState(sis), downMax.getState(sis),dummy);
+					upMin.setState(N, temp1.getValue());
+					upMax.setState(N, temp2.getValue());
+				}
+				//{Then calculate final states}
+				tripleCombine(temp1, temp2, downMin.getState(L), downMax.getState(L), downMin.getState(R), downMax.getState(R), upMin.getState(N), upMax.getState(N));
+				finalMin.setState(N, temp1.getValue());
+				finalMax.setState(N, temp2.getValue());
+			}
+			NYfinal(tree, L, statesAtNodes, itemMin, itemMax);
+			NYfinal(tree, R, statesAtNodes, itemMin, itemMax);
+		}
+		else {
+			double ts = ((ContinuousDistribution)observedStates).getState(tree.taxonNumberOfNode(N), 0); //just testing item 0?
+			if (MesquiteDouble.isUnassigned(ts)) {
+				finalMin.setState(N, finalMin.getState(tree.motherOfNode(N, deleted)));  //{Results stored in [finalMin .. finalMax]}
+				finalMax.setState(N, finalMax.getState(tree.motherOfNode(N, deleted)));  
+			}
+			else {
+				finalMin.setState(N, downMin.getState(N));  //{Results stored in [finalMin .. finalMax]}
+				finalMax.setState(N, downMax.getState(N));  
+			}
+		}
+
+		statesAtNodes.setState(N, itemMin, finalMin.getState(N));
+		statesAtNodes.setState(N, itemMax, finalMax.getState(N));
+	}
+	/*_____________________________________________________________________ */
+	/*{Reconstructs ancestral states for continuous characters using linear parsimony.}
+	{nb->downMin, downMax store the minima and maxima of downpass ranges}
+	{nb->upMin, upMax store the minima and maxima of uppass ranges}
+	{nb->finalMin, finalMax store the minima and maxima of final pass ranges}
+	{	(final named C and D because finalMin doubly used; see MinSQReconstruct)}*/
+
+	/*.................................................................................................................*/
+	private void adjustStorage(Tree tree, CharacterDistribution observedStates) {
+		downMin=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downMin);
+		downMax=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downMax);
+		upMin=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upMin);
+		upMax=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upMax);
+		finalMin=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)finalMin);
+		finalMax=  (ContinuousHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)finalMax);
+	}
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	boolean warnedPolytomies = false;
+	boolean[] deleted;
+	//boolean warnedMissing = false;
+	public boolean warn(Tree tree, ContinuousDistribution observedStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+		if (tree.hasPolytomies(tree.getRoot())) {
+			String message = "Trees with polytomies not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedPolytomies) {
+				discreetAlert( message);
+				warnedPolytomies = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		/*if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())) {
+			String s ="Missing data, gaps are not currently supported by linear parsimony calculations.  Calculations for one or more characters were not completed.";
+			if (!warnedMissing) {
+				discreetAlert( s);
+				warnedMissing = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}*/
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched) {
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in linear parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation) {
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())){
+			if (deleted == null || deleted.length <  tree.getNumNodeSpaces())
+				deleted = new boolean[tree.getNumNodeSpaces()];
+			for (int i = 0; i<deleted.length; i++) deleted[i] = false;
+			for (int it = 0; it< tree.getTaxa().getNumTaxa(); it++)
+				if (observedStates.isUnassigned(it) || observedStates.isInapplicable(it)) {
+					tree.virtualDeleteTaxon(it, deleted);
+				}
+		}
+		else
+			deleted = null;
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (ContinuousDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		ContinuousDistribution cObs = (ContinuousDistribution)observedStates;
+		String[] items = new String[cObs.getNumItems()*2]; //todo: only do this if needed!!!!
+		for (int i= 0; i<cObs.getNumItems(); i++){
+			String n;
+			if (StringUtil.blank(cObs.getItemName(i)))
+				n = "";
+			else
+				n = cObs.getItemName(i);
+			items[i*2] = n + " (min.)";
+			items[i*2 + 1] = n + " (max.)";
+		}
+		((ContinuousHistory)statesAtNodes).setItems(items);
+		((ContinuousHistory)statesAtNodes).deassignStates();
+
+		adjustStorage(tree, observedStates);
+		NYLength.setValue(0); //not designed to be thread safe
+		for (int item =0; item<cObs.getNumItems(); item++) {
+			NYsurvey (tree.getTaxa().getNumTaxa(),(ContinuousDistribution)observedStates,  item);
+			NYdown(tree, tree.getRoot(deleted), item);
+			NYfinal(tree, tree.getRoot(deleted), (ContinuousHistory)statesAtNodes, item*2, item*2 +1);
+			if (item==0&& stepsObject!=null)
+				stepsObject.setValue(NYLength.getValue());
+		}
+		//place states from finalC and finalD into states at nodes
+		if (resultString!=null)
+			resultString.setValue("Parsimony reconstruction (Linear) [Length: " + stepsObject + "]");
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null ||stepsObject == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (ContinuousDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		adjustStorage(tree, observedStates);
+		NYLength.setValue(0); //not designed to be thread safe
+		NYsurvey (tree.getTaxa().getNumTaxa(),(ContinuousDistribution)observedStates,  0);
+		NYdown(tree, tree.getRoot(deleted), 0);
+		stepsObject.setValue(NYLength.getValue());
+		if (resultString!=null)
+			resultString.setValue("Parsimony length: " + stepsObject + " (Linear)");
+	}
+
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		if (model==null)
+			return false;
+		return (model.getName().equalsIgnoreCase("Linear")) && observedStates instanceof ContinuousDistribution;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsimonyOrdered/ParsimonyOrdered.java b/Source/mesquite/parsimony/ParsimonyOrdered/ParsimonyOrdered.java
new file mode 100644
index 0000000..1a0324d
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsimonyOrdered/ParsimonyOrdered.java
@@ -0,0 +1,588 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsimonyOrdered;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonyOrdered extends ParsAncStatesForModel  {
+	public String getName() {
+		return "Parsimony Ordered";
+	}
+	public String getExplanation() {
+		return "Reconstructs the ancestral states of categorical characters using parsimony, under the assumption that states are ordered (ordered, Farris or Wagner parsimony; additive).  Also counts parsimony steps." ;
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	CategoricalHistory downStates;
+	CategoricalHistory upStates;
+	int steps;
+	MesquiteInteger  tempStepsObj;
+	int show = 0;
+	int[] toLeft, toRight;
+	long fullSet;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		tempStepsObj  = new MesquiteInteger(0);
+		/* debugging only  		
+ 		addMenuItem( "Final States", makeCommand("showFinalStates",  this));
+ 		addMenuItem( "Down States", makeCommand("showDownStates",  this));
+ 		addMenuItem( "Up States", makeCommand("showUpStates",  this));
+		 */
+		toLeft = new int[CategoricalState.maxCategoricalState+1];
+		toRight = new int[CategoricalState.maxCategoricalState+1];
+		return true;
+	}
+ 	public boolean calculatingConditionalMPRSets(){
+ 		return calcConditionalMPRs;
+ 	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets output to be the final MPR sets", null, commandName, "showFinalStates")) {
+			show = 0;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets output to be downpass sets", null, commandName, "showDownStates")) {
+			show = 1;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets output to be uppass sets", null, commandName, "showUpStates")) {
+			show = 2;
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	private long orderedOperator3 (long set1, long set2, long set3) {  // assumes continuous sets
+		int min1 = CategoricalState.minimum(set1);
+		int max1 = CategoricalState.maximum(set1);
+		int min2 = CategoricalState.minimum(set2);
+		int max2 = CategoricalState.maximum(set2);
+		int min3 = CategoricalState.minimum(set3);
+		int max3 = CategoricalState.maximum(set3);
+
+		/*Two most distant sets found then between-space intersected with remaining set */
+		if ((min1 > min2) && (min1 > min3)) { //set1 minimum furthest right}
+			if (max2 < max3) //most distant are 2 and 1}
+				return (CategoricalState.span(max2, min1)  & set3);  //{[--2-(-]--3--)  [--1--] }
+			else  //most distant are 3 and 1}
+				return (CategoricalState.span(max3, min1)  & set2); //{[--3-(-]--2--)  [--1--] }
+		}
+		else if (min2 > min3) { // {set2 minimum furthest right}
+			if (max1 < max3) //  {most distant are 1 and 2}
+				return (CategoricalState.span(max1, min2)  & set3);   //{[--1-(-]--3--)  [--2--] }
+			else  //{most distant are 3 and 2}
+				return (CategoricalState.span(max3, min2)  & set1);   //{[--3-(-]--1--)  [--2--] }
+		}
+		else { //  {set3 furthest right}
+			if (max1 < max2) // {most distant are 1 and 3}
+				return (CategoricalState.span(max1, min3)  & set2);   //{[--1-(-]--2--)  [--3--] }
+			else  //{most distant are 2 and 3}
+				return (CategoricalState.span(max2, min3)  & set1); //{[--2-(-]--1--)  [--3--] }
+		}
+	}
+	/*.................................................................................................................*/
+	private long orderedOperator2 (long set1, long set2, MesquiteInteger o) {  // assumes continuous sets
+		long result = set1 & set2;
+		if (result !=0)
+			return result;
+		else {
+			if (set1>set2) { // use maximum of set2 to minimum of set1
+				int m1, m2;
+				m1=CategoricalState.minimum(set1);
+				m2=CategoricalState.maximum(set2);
+				o.setValue(m1-m2);
+				return CategoricalState.span(m2,m1);
+			}
+			else {// use maximum of set1 to minimum of set2
+				int m1, m2;
+				m1=CategoricalState.maximum(set1);
+				m2=CategoricalState.minimum(set2);
+				o.setValue(m2-m1);
+				return CategoricalState.span(m1,m2);
+			}
+		}
+	}
+	private void setTerminalDownStates(int N, Tree tree){
+		long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+		if (CategoricalState.isUnassigned(observed) || CategoricalState.isInapplicable(observed))
+			downStates.setState(N, fullSet);
+		else {
+			int card = CategoricalState.cardinality(observed);
+			if (card>1){
+				int min = CategoricalState.minimum(observed);
+				int max = CategoricalState.maximum(observed);
+				if (!CategoricalState.isUncertain(observed))
+					steps += max-min;
+				downStates.setState(N, CategoricalState.span(min, max));
+			}
+			else
+				downStates.setState(N, observed & CategoricalState.statesBitsMask);
+		}
+	}
+	private long getFromSoftPolytomous(int N, int excluding, Tree tree, boolean addToCount){
+		int minOfMaxs = CategoricalState.maxCategoricalState;
+		int maxOfMins = 0;
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (d!=excluding){
+				long s = downStates.getState(d);
+				minOfMaxs = MesquiteInteger.minimum(minOfMaxs, CategoricalState.maximum(s));
+				maxOfMins = MesquiteInteger.maximum(maxOfMins, CategoricalState.minimum(s));
+			}
+		}
+		if (N!=tree.getRoot()){
+			int anc = tree.motherOfNode(N);
+			if (anc !=excluding) {
+				long s = upStates.getState(N);
+				minOfMaxs = MesquiteInteger.minimum(minOfMaxs, CategoricalState.maximum(s));
+				maxOfMins = MesquiteInteger.maximum(maxOfMins, CategoricalState.minimum(s));
+			}
+		}
+		if (addToCount)
+			steps+= maxOfMins - minOfMaxs;
+		return CategoricalState.span(minOfMaxs, maxOfMins);
+	}
+	private long getFromHardPolytomous(int N, int excluding, Tree tree, boolean addToCount){
+		for (int i=0; i< toLeft.length; i++){
+			toLeft[i]=0;
+			toRight[i]=0;
+		}
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (d!=excluding){
+				long s = downStates.getState(d);
+				for (int i=0; i< toLeft.length; i++){
+					int max = CategoricalState.maximum(s);
+					int min = CategoricalState.minimum(s);
+					if (max<i)
+						toLeft[i]++;
+					if (min>i)
+						toRight[i]++;
+				}
+			}
+		}
+		if (tree.getRoot()!=N){  //get from mother
+			int anc = tree.motherOfNode(N);
+			if (anc!=excluding) {
+				long s=upStates.getState(N);
+				for (int i=0; i< toLeft.length; i++){
+					int max = CategoricalState.maximum(s);
+					int min = CategoricalState.minimum(s);
+					if (max<i)
+						toLeft[i]++;
+					if (min>i)
+						toRight[i]++;
+				}
+			}
+		}
+		long result = 0L;
+		if (toRight[0]<= toLeft[1])
+			result = CategoricalState.addToSet(result, 0);
+		if (toLeft[toLeft.length-1] <= toRight[toLeft.length-2])
+			result = CategoricalState.addToSet(result, toLeft.length-1);
+		for (int i=1; i< toLeft.length-1; i++){
+			if (toLeft[i] <= toRight[i-1] && toRight[i]<= toLeft[i+1])
+				result = CategoricalState.addToSet(result, i);
+		}
+		if (addToCount){
+			int target = CategoricalState.minimum(result);
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				long s = downStates.getState(d);
+				int max = CategoricalState.maximum(s);
+				int min = CategoricalState.minimum(s);
+				if (target>max)
+					steps += target-max;
+				else if (target<min)
+					steps += min-target;
+			}
+			if (tree.getRoot()!=N){  //get from mother
+				int anc = tree.motherOfNode(N);
+				if (anc!=excluding) {
+					long s=upStates.getState(N);
+					int max = CategoricalState.maximum(s);
+					int min = CategoricalState.minimum(s);
+					if (target>max)
+						steps += target-max;
+					else if (target<min)
+						steps += min-target;
+				}
+			}
+		}
+		return result;
+
+	}
+	/*.................................................................................................................*/
+	/* at present not good with polytomies */
+	private   void downPass(int N, Tree tree) {
+		if (tree.nodeIsTerminal(N)) {
+			setTerminalDownStates(N, tree);
+		}
+		else {
+			if (tree.nodeIsPolytomous(N)) {
+				long intersection = fullSet;
+				long union = 0;
+				for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+					downPass(d, tree);
+					long s=downStates.getState(d);
+					intersection &= s;  //intersection
+				}
+				if (intersection == 0) {
+					if (tree.nodeIsSoft(N)){
+						downStates.setState(N, getFromSoftPolytomous(N, tree.motherOfNode(N), tree, true));
+					}
+					else {
+						downStates.setState(N, getFromHardPolytomous(N, tree.motherOfNode(N), tree, true));
+					}
+				}
+				else
+					downStates.setState(N, intersection);
+			}
+			else {   //dichotomous
+				long s1=0;
+				long s2=0;
+				for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+					downPass(d, tree);
+					if (d==tree.firstDaughterOfNode(N))
+						s1 = downStates.getState(d);
+					else
+						s2 = downStates.getState(d);
+				}
+				long intersection = s1 & s2;  //intersection
+				if (intersection == 0) {
+					downStates.setState(N, orderedOperator2(s1, s2, tempStepsObj));
+					steps+= tempStepsObj.getValue();
+				}
+				else 
+					downStates.setState(N, intersection);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/* at present not good with polytomies */
+	private   void upPass(int N, Tree tree) {
+		long intersection = fullSet;
+		if (N!=tree.getRoot()) {
+			long s=0; long t=0;
+			// accumulate downstates from sisters
+			for (int d = tree.firstDaughterOfNode(tree.motherOfNode(N)); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (d!=N) {
+					s = downStates.getState(d);
+					intersection &= s;  //intersection
+				}
+			}
+			//get upstate from ancestor
+			if (tree.motherOfNode(N)!=tree.getRoot()) {
+				t = upStates.getState(tree.motherOfNode(N));
+				intersection &= t;  //intersection
+			}
+			if (intersection == 0) {
+				if (tree.nodeIsPolytomous(tree.motherOfNode(N))) {
+					if (tree.nodeIsSoft(tree.motherOfNode(N))){
+						upStates.setState(N, getFromSoftPolytomous(tree.motherOfNode(N), N, tree, false));
+					}
+					else
+						upStates.setState(N, getFromHardPolytomous(tree.motherOfNode(N), N, tree, false));
+				}
+				else {
+					upStates.setState(N, orderedOperator2(t, s, tempStepsObj));
+				}
+			}
+			else 
+				upStates.setState(N, intersection);
+		}
+
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			upPass(d, tree);
+	}
+	/*.................................................................................................................*/
+	public   void finalPass(int N, Tree tree, CategoricalHistory statesAtNodes) {
+		if (show == 1) {
+			statesAtNodes.setState(N, downStates.getState(N));
+		}
+		else if (show == 2) {
+			statesAtNodes.setState(N, upStates.getState(N));
+		}
+		else if (N==tree.getRoot())
+			statesAtNodes.setState(N, downStates.getState(N));
+		else if (tree.nodeIsTerminal(N)) {
+			long observed =  ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+			if (CategoricalState.isUnassigned(observed) || CategoricalState.isInapplicable(observed)) {
+				statesAtNodes.setState(N, statesAtNodes.getState(tree.motherOfNode(N)));
+				if (calcConditionalMPRs){
+					for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){ //for each possible state at immediate ancestor
+						statesAtNodes.setConditionalStateSet(CategoricalState.makeSet(ist), N, ist);
+					}
+				}
+			}
+			else {
+				if (CategoricalState.isUncertain(observed)){
+					long ancState = statesAtNodes.getState(tree.motherOfNode(N));
+					
+					long result = CategoricalState.unassigned;
+					if ((observed & ancState) != 0)
+						result = observed & ancState;
+					else {
+						observed = CategoricalState.span(observed);
+						if ((observed & ancState ) !=0)
+							result = observed & ancState;
+						else {
+							if (observed>ancState)
+								result = CategoricalState.makeSet(CategoricalState.minimum(observed));
+							else
+								result = CategoricalState.makeSet(CategoricalState.maximum(observed));
+						}
+					}
+					statesAtNodes.setState(N, result);
+					if (calcConditionalMPRs){
+						for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+							result = CategoricalState.unassigned;
+							if ((observed & ancState) != 0)
+								result = observed & ancState;
+							else {
+								observed = CategoricalState.span(observed);
+								if ((observed & ancState ) !=0)
+									result = observed & ancState;
+								else {
+									if (observed>ancState)
+										result = CategoricalState.makeSet(CategoricalState.minimum(observed));
+									else
+										result = CategoricalState.makeSet(CategoricalState.maximum(observed));
+								}
+							}
+							statesAtNodes.setConditionalStateSet(result, N, ist);
+						}
+					}
+				}
+				else {
+					statesAtNodes.setState(N,observed);
+					if (calcConditionalMPRs){
+						for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+							statesAtNodes.setConditionalStateSet(observed, N, ist);
+						}
+					}
+				}
+			}
+		}
+		else if (tree.nodeIsPolytomous(N))  {
+			if (tree.nodeIsSoft(N)){
+				long result = CategoricalState.unassigned;
+				long uS = upStates.getState(N);
+				
+				long dS = downStates.getState(N);
+				if ((dS & uS) != 0L)
+					result = dS & uS;
+				else
+					result = orderedOperator2(dS, uS, tempStepsObj);
+				statesAtNodes.setState(N, result);
+				if (calcConditionalMPRs){
+					for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+						result = CategoricalState.unassigned;
+						uS = CategoricalState.makeSet(ist);
+
+						if ((dS & uS) != 0L)
+							result = dS & uS;
+						else
+							result = orderedOperator2(dS, uS, tempStepsObj);
+						statesAtNodes.setConditionalStateSet(result, N, ist);
+					}
+				}
+			}
+			else {
+				long intersection = fullSet;
+				// accumulate downstates from daughters
+				long s1 = downStates.getState(tree.firstDaughterOfNode(N));
+				long s=0;
+				for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+					s = downStates.getState(d);
+					intersection &= s;  //intersection
+				}
+				long downAccumulated = intersection;
+				
+				long sU = upStates.getState(N);
+				long result = CategoricalState.unassigned;
+				intersection &= sU;  //intersection
+				if (intersection == 0) 
+					result = getFromHardPolytomous(N, -1, tree, false);
+				else 
+					result = intersection;
+				statesAtNodes.setState(N, result);
+				if (calcConditionalMPRs){
+					for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+						result = CategoricalState.unassigned;
+						sU = CategoricalState.makeSet(ist);
+						intersection = downAccumulated;
+						intersection &= sU;  //intersection
+						if (intersection == 0) 
+							result = getFromHardPolytomous(N, -1, tree, false);
+						else 
+							result = intersection;
+						statesAtNodes.setConditionalStateSet(result, N, ist);
+					}
+				}
+			}
+		}
+		else  {
+			long intersection = fullSet;
+			// accumulate downstates from daughters
+			long s1 = downStates.getState(tree.firstDaughterOfNode(N));
+			long s=0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				s = downStates.getState(d);
+				intersection &= s;  //intersection
+			}
+			long downAccumulated = intersection;
+			
+			long sU = upStates.getState(N);
+			long result = CategoricalState.unassigned;
+			intersection &= sU;  //intersection
+			if (intersection == 0)
+				result = orderedOperator3(s, s1, sU);
+			else 
+				result = intersection;
+			statesAtNodes.setState(N, result);
+			
+			if (calcConditionalMPRs){
+				for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+					result = CategoricalState.unassigned;
+					sU = CategoricalState.makeSet(ist);
+					intersection = downAccumulated;
+					intersection &= sU;  //intersection
+					if (intersection == 0)
+						result = orderedOperator3(s, s1, sU);
+					else 
+						result = intersection;
+					statesAtNodes.setConditionalStateSet(result, N, ist);
+				}
+			}
+		}
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			finalPass(d, tree, statesAtNodes);
+	}
+	
+	/*...................................................FOR DEBUGGING..............................................................*/
+	private   void resetStates(int N, Tree tree, CategoricalHistory statesAtNodes, CategoricalHistory fromStates) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			resetStates(d, tree, statesAtNodes, fromStates);
+		}
+		statesAtNodes.setState(N, fromStates.getState(N));
+	}
+
+	/*.................................................................................................................*/
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	public boolean warn(Tree tree, CharacterDistribution observedStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in ordered state parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched) {
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in ordered state parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation) {
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (resultString!=null)
+			resultString.setValue("");
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (observedStates==null || tree == null || statesAtNodes == null)
+			return;
+		if (warn(tree, observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+
+		fullSet = ((CategoricalDistribution)observedStates).fullSet();
+		steps = 0;  //note: not thread safe!
+		downStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downStates);
+		upStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upStates);
+		downPass(tree.getRoot(), tree);
+		upPass(tree.getRoot(), tree);
+		finalPass(tree.getRoot(), tree, (CategoricalHistory)statesAtNodes);
+		((CategoricalHistory)statesAtNodes).polymorphToUncertainties(tree.getRoot(), tree);
+		if (stepsObject != null)
+			stepsObject.setValue(steps);
+		if (resultString!=null)
+			resultString.setValue("Parsimony reconstruction (ordered) [Steps: " + stepsObject + "]");
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (resultString!=null)
+			resultString.setValue("");
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (observedStates==null || tree == null || stepsObject == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		fullSet = ((CategoricalDistribution)observedStates).fullSet();
+		downStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downStates);
+		steps = 0;  //note: not designed to be thread safe!!
+		downPass(tree.getRoot(), tree);
+		stepsObject.setValue(steps);
+		if (resultString!=null)
+			resultString.setValue("Parsimony steps: " + stepsObject + " (ordered)");
+	}
+
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return (model.getName().equalsIgnoreCase("Ordered")) && observedStates instanceof CategoricalDistribution;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether or not the module does substantive calculations and thus should be cited.  If true, its citation will
+ 	appear in the citations panel of the windows */
+	public boolean showCitation()  {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getModelTypeName(){
+		return "Parsimony model";
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsimonySquared/ParsimonySquared.java b/Source/mesquite/parsimony/ParsimonySquared/ParsimonySquared.java
new file mode 100644
index 0000000..fe5f286
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsimonySquared/ParsimonySquared.java
@@ -0,0 +1,213 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsimonySquared;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonySquared extends ParsAncStatesForModel {
+	public String getName() {
+		return "Parsimony Squared-change";
+	}
+	public String getExplanation() {
+		return "Reconstructs the ancestral states of continuous characters so as to minimize the sum of squared changes (squared-change or least squares parsimony; Brownian motion likelihood)." ;
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	ContinuousHistory downA, downB, upA, upB, finalC, finalD;
+	double minSQLength;
+	MesquiteBoolean useWeights; 
+	boolean rootedMode = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (useWeights == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		temp.addLine("toggleWeight " + useWeights.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not branch lengths are used in weighting the squared changes", "[on = weight; off]", commandName, "toggleWeight")) {
+			if (useWeights==null) {
+				useWeights = new MesquiteBoolean(true);
+				addCheckMenuItem(null, "Weight branches (sq. change)", makeCommand("toggleWeight", this), useWeights);
+				useWeights.toggleValue(parser.getFirstToken(arguments));
+				resetContainingMenuBar();
+			}
+			else
+				useWeights.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void checkWeights() {
+		if (useWeights==null) {
+			useWeights = new MesquiteBoolean(true);
+			addCheckMenuItem(null, "Weight branches (sq. change)", makeCommand("toggleWeight", this), useWeights);
+			useWeights.setValue(true);
+			resetContainingMenuBar();
+		}
+	}
+	/*.................................................................................................................*/
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	boolean warnedSoftPoly = false;
+	boolean warnedMissing = false;
+	boolean warnedUnrooted = false;
+	public boolean warn(Tree tree, ContinuousDistribution observedStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+		if (tree.hasSoftPolytomies(tree.getRoot())) {
+			String message = "Trees with soft polytomies not allowed in squared-change parsimony calculations.  Calculations for one or more trees were not completed.  To change polytomies to hard, change the default setting in the Tree Defaults submenu of the Defaults submenu of the File menu, or use the Tree window's Alter/Transform Tree submenu";
+			if (!warnedSoftPoly){
+				discreetAlert( message);
+				warnedSoftPoly = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (!tree.getRooted()) {
+			String message = "Unrooted trees not allowed in squared-change parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnrooted){
+				discreetAlert( message);
+				warnedUnrooted = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		/*	if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())) {
+			String s ="Missing data, gaps are not currently supported by squared-change parsimony calculations.  Calculations for one or more characters were not completed.";
+			if (!warnedMissing) {
+				discreetAlert( s);
+				warnedMissing = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		 */
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in squared-change parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched) {
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in squared-change parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation) {
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	/* Calculations assume tree is rooted. (i.e. gives same results as "rooted" option in MacClade*/
+	SquaredReconstructor reconstructor= new SquaredReconstructor();
+	boolean[] deleted;
+
+	void calculateDeleted(Tree tree, CharacterDistribution observedStates){
+		if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())){
+			if (deleted == null || deleted.length <  tree.getNumNodeSpaces())
+				deleted = new boolean[tree.getNumNodeSpaces()];
+			for (int i = 0; i<deleted.length; i++) deleted[i] = false;
+			for (int it = 0; it< tree.getTaxa().getNumTaxa(); it++)
+				if (observedStates.isUnassigned(it) || observedStates.isInapplicable(it)) {
+					tree.virtualDeleteTaxon(it, deleted);
+				}
+		}
+		else
+			deleted = null;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (ContinuousDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		((ContinuousHistory)statesAtNodes).setItemsAs((ContinuousDistribution)observedStates);
+		((ContinuousHistory)statesAtNodes).deassignStates();
+		minSQLength = 0; //not designed to be thread safe
+		checkWeights();
+		calculateDeleted(tree, observedStates);
+		reconstructor.reconstruct(tree, (ContinuousDistribution)observedStates, useWeights.getValue(), true, deleted);
+		reconstructor.placeReconstructedStates((ContinuousHistory)statesAtNodes);
+		minSQLength = reconstructor.getSumSquaredLengths()[0];
+		if (stepsObject != null)
+			stepsObject.setValue(minSQLength);
+		if (resultString!=null)
+			resultString.setValue("Parsimony reconstruction (Squared) [Squared length: " + stepsObject + "]");
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (observedStates==null || tree == null || stepsObject == null)
+			return;
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (warn(tree, (ContinuousDistribution)observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		minSQLength = 0; //not designed to be thread safe
+		checkWeights();
+
+		calculateDeleted(tree, observedStates);
+		reconstructor.reconstruct(tree, (ContinuousDistribution)observedStates, useWeights.getValue(), true, deleted);
+		minSQLength = reconstructor.getSumSquaredLengths()[0];
+		stepsObject.setValue(minSQLength);
+		if (resultString!=null)
+			resultString.setValue("Parsimony squared length: " + stepsObject + " (Squared)");
+	}
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return (model.getName().equalsIgnoreCase("Squared")) && observedStates instanceof ContinuousDistribution;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false; 
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/ParsimonyUnordered/ParsimonyUnordered.java b/Source/mesquite/parsimony/ParsimonyUnordered/ParsimonyUnordered.java
new file mode 100644
index 0000000..ef7f97c
--- /dev/null
+++ b/Source/mesquite/parsimony/ParsimonyUnordered/ParsimonyUnordered.java
@@ -0,0 +1,479 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.ParsimonyUnordered;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+/** Based largely on, and tested against, MacClade's code for ordered categorical characters*/
+public class ParsimonyUnordered extends ParsAncStatesForModel {
+	public String getName() {
+		return "Parsimony Unordered";
+	}
+	public String getExplanation() {
+		return "Reconstructs the ancestral states of categorical characters using parsimony, under the assumption that states are unordered (unordered or Fitch parsimony; nonadditive).  Also counts parsimony steps." ;
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	CategoricalHistory downStates;
+	CategoricalHistory upStates;
+	int steps;
+	int[] commonnest;
+	long fullSet;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		commonnest = new int[64];
+		zeroCommonnest();
+		return true;
+	}
+	public boolean calculatingConditionalMPRSets(){
+		return calcConditionalMPRs;
+	}
+	/*.................................................................................................................*/
+	private void zeroCommonnest() {
+		for (int i=0; i<64; i++)
+			commonnest[i]=0;
+	}
+	private void addSetToCommonnest(long s) {
+		for (int i=0; i<64; i++)
+			if (CategoricalState.isElement(s, i))
+				commonnest[i]++;
+	}
+	private long commonnestToSet() {
+		int max = 0;
+		long result=CategoricalState.emptySet();
+
+		for (int i=0; i<64; i++)
+			if (max<commonnest[i])
+				max=commonnest[i];
+		if (max>0)
+			for (int i=0; i<64; i++)
+				if (max==commonnest[i])
+					result=CategoricalState.addToSet(result, i);
+		return result;
+	}
+	/*.................................................................................................................*/
+	private boolean covers(int N, int excluding, Tree tree, long test){
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (d!=excluding){
+				long s=downStates.getState(d);
+				if ((test & s)==0) {
+					return false;
+				}
+			}
+		}
+		if (tree.getRoot()!=N){
+			int anc = tree.motherOfNode(N);
+			if (anc!=excluding) {
+				long s=upStates.getState(N);
+				if ((test & s)==0) {
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	private long getFromSoftPolytomous(int N, int excluding, Tree tree, long union, boolean addToCount){
+
+		if (union==0)
+			return fullSet;
+		int max = CategoricalState.maximum(union);
+		long lucky = 0;
+		int numInSet;
+		int numLucky = 0;
+		for (numInSet = 2; numInSet<=max+1 && lucky==0; numInSet++) {
+			lucky = 0;
+			long test = CategoricalState.firstSet(numInSet);
+			while (test!=0) {
+				if (covers(N, excluding, tree, test)) {
+					lucky |= test;
+					numLucky = numInSet;
+				}
+				test = CategoricalState.nextSet(test, max);
+			}
+		}
+		if (addToCount)
+			steps+= numLucky-1;
+		return lucky;
+
+	}
+	private long getFromHardPolytomous(int N, int excluding, Tree tree, long union, boolean addToCount){
+		if (union==0)
+			return fullSet;
+		zeroCommonnest();
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) { // get from daughters
+			if (d!=excluding){
+				long s=downStates.getState(d);
+				addSetToCommonnest(s);
+			}
+		}
+		if (tree.getRoot()!=N){  //get from mother
+			int anc = tree.motherOfNode(N);
+			if (anc!=excluding) {
+				long s=upStates.getState(N);
+				addSetToCommonnest(s);
+			}
+		}
+		long c = commonnestToSet();
+		if (addToCount){
+			long cMin = CategoricalState.makeSet(CategoricalState.minimum(c));
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) { //steps to daughters
+				if (d!=excluding && (downStates.getState(d) & cMin) == 0)
+					steps++;
+			}
+			if (tree.getRoot()!=N){ //steps to mother
+				int anc = tree.motherOfNode(N);
+				if (anc!=excluding) {
+					long s=upStates.getState(N);
+					if ((s & cMin) == 0)
+						steps++;
+				}
+			}
+		}
+		return c;
+
+	}
+	private void setTerminalDownStates(int N, Tree tree){
+		long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+		if (CategoricalState.isUnassigned(observed) || CategoricalState.isInapplicable(observed))
+			downStates.setState(N, fullSet);
+		else {
+			if (!CategoricalState.isUncertain(observed)){
+				int card = CategoricalState.cardinality(observed);
+				if (card>1)
+					steps += card-1;
+			}
+			downStates.setState(N, observed & CategoricalState.statesBitsMask);
+		}
+	}
+	/*.................................................................................................................*/
+	/* Seems to count polytomies ok, but not used on uppass.  Also, terminal uncertainties/polymorphisms not dealt with well */
+	private   void downPass(int N, Tree tree) {
+		if (tree.nodeIsTerminal(N)) {
+			setTerminalDownStates(N, tree);
+		}
+		else {
+			long intersection = fullSet;
+			long union = 0;
+			long unionNonMissing = 0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				downPass(d, tree);
+				long s=downStates.getState(d);
+				intersection &= s;  //intersection
+				union |= s;  //union
+				if (s!=fullSet)
+					unionNonMissing |= s;  //union
+			}
+			if (intersection == 0) {
+				if (tree.nodeIsPolytomous(N)) {
+					if (tree.nodeIsSoft(N))
+						downStates.setState(N, getFromSoftPolytomous(N, tree.motherOfNode(N), tree, unionNonMissing, true));
+					else
+						downStates.setState(N, getFromHardPolytomous(N, tree.motherOfNode(N), tree, unionNonMissing, true));
+				}
+				else {
+					downStates.setState(N, union); 
+					steps++;
+				}
+			}
+			else {
+				downStates.setState(N, intersection);
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	private   void upPass(int N, Tree tree) {
+		if (N!=tree.getRoot()) {
+			long intersection = fullSet;
+			long union = 0;
+			// accumulate downstates from sisters
+			for (int d = tree.firstDaughterOfNode(tree.motherOfNode(N)); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (d!=N) {
+					long s = downStates.getState(d);
+					intersection &= s;  //intersection
+					union |= s;  //union
+				}
+			}
+			//get upstate from ancestor
+			if (tree.motherOfNode(N)!=tree.getRoot()) {
+				long s = upStates.getState(tree.motherOfNode(N));
+				intersection &= s;  //intersection
+				union |= s;  //union
+			}
+			if (intersection == 0) {
+				if (tree.nodeIsPolytomous(tree.motherOfNode(N))) {
+					if (tree.nodeIsSoft(tree.motherOfNode(N)))
+						upStates.setState(N, getFromSoftPolytomous(tree.motherOfNode(N), N, tree, union, false));
+					else
+						upStates.setState(N, getFromHardPolytomous(tree.motherOfNode(N), N, tree, union, false));
+				}
+				else
+					upStates.setState(N, union);
+			}
+			else 
+				upStates.setState(N, intersection);
+		}
+
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			upPass(d, tree);
+	}
+	/*.................................................................................................................*/
+	public   void finalPass(int N, Tree tree, CategoricalHistory statesAtNodes) {
+		if (N==tree.getRoot())
+			statesAtNodes.setState(N, downStates.getState(N));
+		else if (tree.nodeIsTerminal(N)) {
+			long observed =  ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(N));
+			if (CategoricalState.isUnassigned(observed) || CategoricalState.isInapplicable(observed)) {
+				statesAtNodes.setState(N, statesAtNodes.getState(tree.motherOfNode(N)));
+				if (calcConditionalMPRs){
+					for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){ //for each possible state at immediate ancestor
+						statesAtNodes.setConditionalStateSet(CategoricalState.makeSet(ist), N, ist);
+					}
+				}
+			}
+			else {
+				if (CategoricalState.isUncertain(observed)){
+					// if ancestor state is entirely contained within this, use ancestor state
+					// otherwise use this directly
+					long result = CategoricalState.unassigned;
+					long ancState =statesAtNodes.getState(tree.motherOfNode(N));
+					if (CategoricalState.isSubset(ancState, observed))
+						result = ancState;
+					else
+						result = observed;
+					statesAtNodes.setState(N, result);
+					if (calcConditionalMPRs){
+						for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+							result = CategoricalState.unassigned;
+							ancState = CategoricalState.makeSet(ist);
+							if (CategoricalState.isSubset(ancState, observed))
+								result = ancState;
+							else
+								result = observed;
+							statesAtNodes.setConditionalStateSet(result, N, ist);
+						}
+					}
+				}
+				else {
+					statesAtNodes.setState(N,observed);
+					if (calcConditionalMPRs){
+						for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+							statesAtNodes.setConditionalStateSet(observed, N, ist);
+						}
+					}
+				}
+			}
+		}
+		else 	if (tree.nodeIsPolytomous(N) && tree.nodeIsSoft(N)) {
+			long result = CategoricalState.unassigned;
+			long uS = upStates.getState(N);
+
+			long dS = downStates.getState(N);
+			if ((dS & uS) != 0L)
+				result = dS & uS;
+			else
+				result = dS | uS;
+			statesAtNodes.setState(N, result);
+			if (calcConditionalMPRs){
+				dS = downStates.getState(N);
+				for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+					result = CategoricalState.unassigned;
+					uS = CategoricalState.makeSet(ist);
+
+					if ((dS & uS) != 0L)
+						result = dS & uS;
+					else
+						result = dS | uS;
+					statesAtNodes.setConditionalStateSet(result, N, ist);
+				}
+			}
+		}
+		else {
+			long result = CategoricalState.unassigned;
+			long sU = upStates.getState(N);
+
+			long intersection = fullSet;
+			long union = 0;
+			// accumulate downstates from daughters
+			long s1 = downStates.getState(tree.firstDaughterOfNode(N));
+			long s=0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				s = downStates.getState(d);
+				intersection &= s;  //intersection
+				union |= s;  //union
+			}
+			long unionDownStates = union;
+			long intersectionDownStates = intersection;
+			intersection &= sU;  //intersection
+			union |= sU;  //union
+
+			if (intersection == 0) {
+				if (tree.nodeIsPolytomous(N)) {
+					result = getFromHardPolytomous(N, -1, tree, union, false);
+				}
+				else {
+					intersection=(s1&s)|(s1&sU)|(s&sU);
+					if (intersection==0)
+						result = union;
+					else
+						result = intersection;
+				}
+			}
+			else 
+				result = intersection;
+			statesAtNodes.setState(N, result);
+			if (calcConditionalMPRs){
+				for (int ist = 0; ist <= CategoricalState.maxCategoricalState; ist++){//for each possible state at immediate ancestor
+					result = CategoricalState.unassigned;
+					sU = CategoricalState.makeSet(ist);
+					union = unionDownStates;
+					intersection = intersectionDownStates;
+
+					intersection &= sU;  //intersection
+					union |= sU;  //union
+
+					if (intersection == 0) {
+						if (tree.nodeIsPolytomous(N)) {
+							result = getFromHardPolytomous(N, -1, tree, union, false);
+						}
+						else {
+							intersection=(s1&s)|(s1&sU)|(s&sU);
+							if (intersection==0)
+								result = union;
+							else
+								result = intersection;
+						}
+					}
+					else 
+						result = intersection;
+					statesAtNodes.setConditionalStateSet(result, N, ist);
+				}
+			}
+
+		}
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			finalPass(d, tree, statesAtNodes);
+	}
+	/*...................................................FOR DEBUGGING..............................................................*/
+	private   void resetStates(int N, Tree tree, CategoricalHistory statesAtNodes, CategoricalHistory fromStates) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			resetStates(d, tree, statesAtNodes, fromStates);
+		}
+		statesAtNodes.setState(N, fromStates.getState(N));
+	}
+	/*.................................................................................................................*/
+	boolean warnedReticulation = false;
+	boolean warnedUnbranched = false;
+	public boolean warn(Tree tree, CharacterDistribution observedStates, MesquiteString resultString){
+		if (tree == null || observedStates == null)
+			return false;
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String message = "Trees with unbranched internal nodes not allowed in unordered state parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedUnbranched) {
+				discreetAlert( message);
+				warnedUnbranched = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String message = "Trees with reticulations not allowed in unordered state parsimony calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedReticulation) {
+				discreetAlert( message);
+				warnedReticulation = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (resultString!=null)
+			resultString.setValue("");
+		if (observedStates==null || tree == null)
+			return;
+		if (warn(tree, observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		fullSet = ((CategoricalDistribution)observedStates).fullSet();
+		steps = 0;  //note: not designed to be thread safe!!
+		downStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downStates);
+		upStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)upStates);
+
+		downPass(tree.getRoot(), tree);
+
+		if (stepsObject!=null)
+			stepsObject.setValue(steps);
+		upPass(tree.getRoot(), tree);
+		finalPass(tree.getRoot(), tree, (CategoricalHistory)statesAtNodes);
+		((CategoricalHistory)statesAtNodes).polymorphToUncertainties(tree.getRoot(), tree);
+		if (resultString!=null)
+			resultString.setValue("Parsimony reconstruction (Unordered) [Steps: " + stepsObject + "]");
+	}
+	/*.................................................................................................................*/
+	public  void calculateSteps(Tree tree, CharacterDistribution observedStates, CharacterModel model, MesquiteString resultString, MesquiteNumber stepsObject) {  
+		if (stepsObject!=null)
+			stepsObject.setToUnassigned();
+		if (resultString!=null)
+			resultString.setValue("");
+		if (observedStates==null || tree == null || stepsObject == null)
+			return;
+		if (warn(tree, observedStates, resultString))
+			return;
+		this.observedStates = observedStates;
+		fullSet = ((CategoricalDistribution)observedStates).fullSet();
+		downStates=  (CategoricalHistory)observedStates.adjustHistorySize(tree, (CharacterHistory)downStates);
+		steps = 0;//note: not designed to be thread safe!!
+		downPass(tree.getRoot(), tree);
+		stepsObject.setValue(steps);
+		if (resultString!=null)
+			resultString.setValue("Parsimony steps: " + stepsObject + " (unordered)");
+	}
+
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return (model.getName().equalsIgnoreCase("Unordered")) && observedStates instanceof CategoricalDistribution;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is a prerelease version */
+	public boolean isPrerelease(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** Returns whether or not the module does substantive calculations and thus should be cited.  If true, its citation will
+ 	appear in the citations panel of the windows */
+	public boolean showCitation()  {
+		return true;
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/RetentionIndexChar/RetentionIndexChar.java b/Source/mesquite/parsimony/RetentionIndexChar/RetentionIndexChar.java
new file mode 100644
index 0000000..9e2085b
--- /dev/null
+++ b/Source/mesquite/parsimony/RetentionIndexChar/RetentionIndexChar.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.RetentionIndexChar;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class RetentionIndexChar extends NumberForCharAndTree {
+	public String getName() {
+		return "Retention Index for Character";
+	}
+	public String getExplanation() {
+		return "Calculates the Retention Index (RI) for a tree and character." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(mesquite.parsimony.ParsCharSteps.ParsCharSteps.class, getName() + " needs parsimony character steps calculated.",
+		"This is hired automatically.");
+
+	}
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	/*.................................................................................................................*/
+	CharacterSteps stepsTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		stepsTask = (CharacterSteps)hireNamedEmployee(CharacterSteps.class, "#ParsCharSteps");
+		if (stepsTask == null)
+			return sorry(getName() + " couldn't start because no calculator of parsimony steps could be obtained.");
+		return true; //false if no appropriate employees!
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==stepsTask)
+			iQuit();
+	}
+
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, CharacterDistribution observedStates){
+	}
+	MesquiteTree bush;
+	MesquiteNumber onTree = new MesquiteNumber();
+	MesquiteNumber onSoftBush = new MesquiteNumber();
+	MesquiteNumber onHardBush = new MesquiteNumber();
+	/*.................................................................................................................*/
+	/*in future this will farm out the calculation to the modules that deal with appropriate character model*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (observedStates==null || tree == null || !(tree instanceof MesquiteTree)) {
+			return;
+		}
+		onTree.setToUnassigned();
+		onSoftBush.setToUnassigned();
+		onHardBush.setToUnassigned();
+		stepsTask.calculateNumber(tree, observedStates, onTree, resultString);
+
+		if (bush == null)
+			bush = new MesquiteTree(observedStates.getTaxa());
+		bush.setToClone((MesquiteTree)tree);  //this used rather than setToDefaultBush in case incoming tree doesn't include all taxa
+		bush.collapseAllBranches(bush.getRoot(), false, false);
+		/** Sets the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+		bush.setPolytomiesAssumption(0, false);  //hard
+		stepsTask.calculateNumber(bush, observedStates, onHardBush, resultString);
+
+		bush.setPolytomiesAssumption(1, false);  //soft
+		stepsTask.calculateNumber(bush, observedStates, onSoftBush, resultString);
+
+		result.setValue(onHardBush);
+		result.subtract(onTree);
+
+		onHardBush.subtract(onSoftBush);
+		if (onHardBush.isZero())
+			result.setValue(0);
+		else
+			result.divideBy(onHardBush);
+
+		//(maximum-steps)/(maximum-minimum)
+		saveLastResult(result);
+		if (resultString != null)
+			resultString.setValue("R.I.: " + result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/** Returns the name of the module in very short form.  For use for column headings and other constrained places.  Unless overridden returns getName()*/
+	public String getVeryShortName(){
+		return "R.I.";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
+
diff --git a/Source/mesquite/parsimony/RetentionIndexMatrix/RetentionIndexMatrix.java b/Source/mesquite/parsimony/RetentionIndexMatrix/RetentionIndexMatrix.java
new file mode 100644
index 0000000..e299c12
--- /dev/null
+++ b/Source/mesquite/parsimony/RetentionIndexMatrix/RetentionIndexMatrix.java
@@ -0,0 +1,117 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.RetentionIndexMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class RetentionIndexMatrix extends NumberForMatrixAndTree {
+	public String getName() {
+		return "Retention Index for Matrix ";
+	}
+	public String getExplanation() {
+		return "Calculates the Retention Index (RI) for a tree and matrix.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix.class, getName() + " uses a module to calculate treelength.",
+		"The treelength module is employed automatically; you don't have to do anything to choose it.");
+		//e.setAsEntryPoint(true);
+	}
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	/*.................................................................................................................*/
+	NumberForMatrixAndTree lengthTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		lengthTask = (NumberForMatrixAndTree)hireNamedEmployee(NumberForMatrixAndTree.class, "#TreelengthForMatrix");
+		if (lengthTask == null)
+			return sorry(getName() + " couldn't start because no calculator of treelength could be obtained.");
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, MCharactersDistribution matrix){
+	}
+	MesquiteTree bush;
+	MesquiteNumber onTree = new MesquiteNumber();
+	MesquiteNumber onSoftBush = new MesquiteNumber();
+	MesquiteNumber onHardBush = new MesquiteNumber();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MCharactersDistribution matrix, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || tree == null || matrix == null)
+			return;
+		if (resultString !=null)
+			resultString.setValue("");
+	   	clearResultAndLastResult(result);
+
+		if (matrix==null || tree == null || !(tree instanceof MesquiteTree)) {
+			return;
+		}
+		onTree.setToUnassigned();
+		onSoftBush.setToUnassigned();
+		onHardBush.setToUnassigned();
+		lengthTask.calculateNumber(tree, matrix, onTree, resultString);
+
+		if (bush == null)
+			bush = new MesquiteTree(matrix.getTaxa());
+		bush.setToClone((MesquiteTree)tree);  //this used rather than setToDefaultBush in case incoming tree doesn't include all taxa
+		bush.collapseAllBranches(bush.getRoot(), false, false);
+		/** Sets the polytomies assumption for this tree; 0= hard; 1 = soft; 2 = unassigned.*/
+		bush.setPolytomiesAssumption(0, false);  //hard
+		lengthTask.calculateNumber(bush, matrix, onHardBush, resultString);
+
+		bush.setPolytomiesAssumption(1, false);  //soft
+		lengthTask.calculateNumber(bush, matrix, onSoftBush, resultString);
+
+		result.setValue(onHardBush);
+		result.subtract(onTree);
+
+		onHardBush.subtract(onSoftBush);
+		if (onHardBush.isZero())
+			result.setValue(0);
+		else
+			result.divideBy(onHardBush);
+
+		//(maximum-steps)/(maximum-minimum)
+		saveLastResult(result);
+		if (resultString != null)
+			resultString.setValue("R.I.: " + result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/StepMatrixCurator/StepMatrixCurator.java b/Source/mesquite/parsimony/StepMatrixCurator/StepMatrixCurator.java
new file mode 100644
index 0000000..2c5e753
--- /dev/null
+++ b/Source/mesquite/parsimony/StepMatrixCurator/StepMatrixCurator.java
@@ -0,0 +1,499 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.StepMatrixCurator;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class StepMatrixCurator extends WholeCharModelCurator implements EditingCurator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(WindowHolder.class, getName() + " need assistance to hold a window" ,
+		"This is arranged automatically");
+	}
+	public String getName() {
+		return "Stepmatrix";
+	}
+	public String getExplanation() {
+		return "Supplies editor for and manages stepmatrices (cost matrices).";
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Step (Cost) Matrix";
+	}
+
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof CharacterModel){
+			int i = getModelNumber((CharacterModel)obj);
+			if (i>=0) {
+				CategTModelEditWindow window = (CategTModelEditWindow)getWindow(i);
+				if (window!=null)
+					window.setModel((CategTModel)obj);
+			}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule editModelNonModal(CharacterModel model, ObjectContainer w){
+		if (model!=null && model instanceof StepMatrixModel) {
+			StepMatrixModel modelToEdit = (StepMatrixModel)model;
+			MesquiteModule windowServer = hireNamedEmployee(WindowHolder.class, "#WindowBabysitter");
+			if (windowServer == null)
+				return null;
+
+			CategTModelEditWindow window = new CategTModelEditWindow(this, windowServer);
+			windowServer.makeMenu("Step_Matrix");
+			windowServer.addMenuItem("Set maximum state...", makeCommand("setMaxState", modelToEdit));
+			if (modelToEdit.isDNA()) {
+				windowServer.addMenuItem("Select Transversions", makeCommand("selectTransversions", modelToEdit));
+				windowServer.addMenuItem("Select Transitions", makeCommand("selectTransitions", modelToEdit));
+			}
+			modelToEdit.setWindow(window);
+
+			window.setDefaultAnnotatable(model);
+			window.setModel((StepMatrixModel)model);
+
+			if (w!=null)
+				w.setObject(window);
+			return windowServer;
+		}
+		return this;
+	}
+	public boolean curatesModelClass(Class modelClass){
+		return StepMatrixModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Stepmatrix";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "Stepmatrix";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return StepMatrixModel.class;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public CharacterModel makeNewModel(String name) {
+		StepMatrixModel model = new StepMatrixModel(name, getProject());
+		return model;
+	}
+	/*.................................................................................................................*/
+	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+		StepMatrixModel model = new StepMatrixModel(name, getProject());
+		model.fromString(description, stringPos, format);
+		return model;
+	}
+	/*.................................................................................................................*/
+
+	public String getNexusCommands(MesquiteFile file, String blockName){ return "";}
+}
+
+/*=======================================================*/
+class StepmatrixNexusCmdTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return (blockName.equalsIgnoreCase("ASSUMPTIONS") && commandName.equalsIgnoreCase("stepmatrix"));
+	}
+}
+
+/* ======================================================================== */
+/** A character model for categorical characters to be used in parsimony calculations*/
+class StepMatrixModel  extends CostMatrixModel implements CategTModel {
+	int[] states;
+	NumberArray costs;
+	int numStates;
+	MesquiteNumber utilityNumber;
+	MesquiteProject project;
+	int maxNumStates = CategoricalState.maxCategoricalState+1;
+	boolean isDNA=false;
+
+	CategTModelEditWindow window = null;
+
+	public StepMatrixModel (String name, MesquiteProject project) {
+		super(name, CategoricalState.class);
+		this.project = project;
+		costs = new NumberArray(maxNumStates*maxNumStates);
+		states = new int[maxNumStates];
+		for (int i=0; i< maxNumStates*maxNumStates; i++) {
+			costs.setValue(i, 1);
+		}
+		for (int i=0; i< maxNumStates; i++) {
+			costs.setValue(i*maxNumStates + i, 0);
+		}
+		numStates = 10;
+		if (project != null && project.getNumberCharMatrices(CategoricalState.class) ==1) {
+			CategoricalData data = (CategoricalData)project.getCharacterMatrix(0, CategoricalState.class);
+			if (data!=null) {
+				numStates = data.getMaxPossibleState()+1;
+				isDNA = data instanceof DNAData;
+			}
+
+		}
+		for (int i=0; i< maxNumStates; i++) {
+			states[i]=i;
+		}
+		utilityNumber = new MesquiteNumber();
+	}
+
+	/** returns whether or not size can be changed externally*/
+	public boolean canChangeSize() {
+		return true;
+	}
+	/** returns whether or not model is default (unordered, initial Jukes-Cantor; if so, then doesn't need to be written to file*/
+	public boolean isBuiltIn() {
+		return false;
+	}
+	/** returns name of model class (e.g. "stepmatrix")*/
+	public String getNEXUSClassName() {
+		return "Stepmatrix";
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the maximum state value handled by the step matrix", "[state number]", commandName, "setMaxState")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int maxState = MesquiteInteger.fromString(arguments, io);
+			int previous = getMaxStateDefined();
+
+			if (!MesquiteInteger.isCombinable(maxState) || maxState<0 || maxState> CategoricalState.maxCategoricalState){
+				maxState = MesquiteInteger.queryInteger(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Set Maximum state", "Maximum state value handled by the step matrix", getMaxStateDefined());
+			}
+			if (maxState !=getMaxStateDefined() && !(!MesquiteInteger.isCombinable(maxState) || maxState<0 || maxState> CategoricalState.maxCategoricalState)){
+				if (previous< maxState){  //fill in with 1's
+					for (int beginState= previous+1; beginState <= maxState; beginState++) {
+						for (int endState = 0; endState <= maxState; endState++)
+							costs.setValue(beginState*maxNumStates+endState, 1);
+					}
+					for (int beginState= 0; beginState <= maxState; beginState++) {
+						for (int endState = previous+1; endState <= maxState; endState++)
+							costs.setValue(beginState*maxNumStates+endState, 1);
+					}
+					for (int beginState= previous+1; beginState <= maxState; beginState++) {
+						costs.setValue(beginState*maxNumStates+beginState, 1);
+					}
+				}
+				setMaxStateDefined(maxState);
+			}
+		} else if (checker.compare(this.getClass(), "Selects the cells corresponding to tranversions", "[]", commandName, "selectTransversions")) {
+			if (window!=null) {
+				window.getTable().selectAndRedrawCell(0,1);
+				window.getTable().selectAndRedrawCell(0,3);
+				window.getTable().selectAndRedrawCell(1,0);
+				window.getTable().selectAndRedrawCell(1,2);
+				window.getTable().selectAndRedrawCell(2,1);
+				window.getTable().selectAndRedrawCell(2,3);
+				window.getTable().selectAndRedrawCell(3,0);
+				window.getTable().selectAndRedrawCell(3,2);
+
+			}
+		} else if (checker.compare(this.getClass(), "Selects the cells corresponding to transitions", "[]", commandName, "selectTransitions")) {
+			if (window!=null) {
+				window.getTable().selectAndRedrawCell(0,2);
+				window.getTable().selectAndRedrawCell(1,3);
+				window.getTable().selectAndRedrawCell(2,0);
+				window.getTable().selectAndRedrawCell(3,1);
+
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void setMaxState(int maxState){
+		if (maxState>0 && maxState<=CategoricalState.maxCategoricalState) {
+			numStates = maxState+1;
+			notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, true);
+			notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, false);
+		}
+	}
+	public void setMaxStateDefined(int maxState){
+		setMaxState(maxState);
+	}
+	public boolean isDNA(){
+		return isDNA;
+	}
+	public int getMaxStateDefined(){
+		return numStates -1;
+	}
+
+	public String getStateSymbol(int state){
+		if (symbols != null) {
+			if (state >= 0 && state < symbols.length && !StringUtil.blank(symbols[state]))
+				return symbols[state];
+			if (state < 0)
+				return CategoricalData.getDefaultStateSymbol(state);
+
+			return Integer.toString(state);
+		}
+
+		if (project != null && project.getNumberCharMatrices(CategoricalState.class) ==1) {
+			CategoricalData data = (CategoricalData)project.getCharacterMatrix(0, CategoricalState.class);
+			String s = getDataSymbol(data, state);
+			if (StringUtil.blank(s))
+				return Integer.toString(state);
+			return s;
+		}
+		return CategoricalData.getDefaultStateSymbol(state);
+	}
+
+	private String getDataSymbol(CategoricalData data, int state){
+		try{
+			return "" + data.getSymbol(state);
+		}
+		catch(Exception e){
+		}
+		return "";
+	}
+
+	String[] symbols;
+	private boolean symbolsMatch(String[] symbolsFound, CategoricalData data){
+		if (symbolsFound == null || data == null)
+			return false;
+		for (int i = 0; i< symbolsFound.length; i++)
+			if (symbolsFound[i]!= null && !symbolsFound[i].equals(getDataSymbol(data, i)))
+				return false;
+		return true;
+	}
+	private boolean symbolsProtein(String[] symbolsFound){
+		if (symbolsFound == null)
+			return false;
+		for (int i = 0; i< symbolsFound.length; i++) {
+			if (symbolsFound[i]!= null && !symbolsFound[i].equals(ProteinData.getDefaultStateSymbol(i)))
+				return false;
+		}
+		return true;
+	}
+	private boolean symbolsDNA(String[] symbolsFound){
+		if (symbolsFound == null)
+			return false;
+		for (int i = 0; i< symbolsFound.length; i++)
+			if (symbolsFound[i]!= null && !symbolsFound[i].equals(DNAData.getDefaultStateSymbol(i)))
+				return false;
+		return true;
+	}
+	private boolean symbolsRNA(String[] symbolsFound){
+		if (symbolsFound == null)
+			return false;
+		for (int i = 0; i< symbolsFound.length; i++)
+			if (symbolsFound[i]!= null && !symbolsFound[i].equals(RNAData.getDefaultStateSymbol(i)))
+				return false;
+		return true;
+	}
+
+	//this is a workaround of NEXUS difficulty of stepmatrix using symbols but not referring to which matrix!  This will not work at times with multiple matrix files
+	private void determineSymbols(String description, int currentPos, int matrixSize){
+		if (matrixSize > CategoricalState.maxCategoricalState+1)
+			matrixSize = CategoricalState.maxCategoricalState + 1;
+		symbols = new String[CategoricalState.maxCategoricalState+1];
+		MesquiteInteger stringPos = new MesquiteInteger(currentPos);
+		for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+			symbols[i] = null;
+		boolean multiFound = false;
+		String[] symbolsFound = new String[CategoricalState.maxCategoricalState+1];
+		for (int i=0; i<matrixSize; i++) {
+			symbolsFound[i] =  ParseUtil.getToken(description, stringPos);
+			if (symbolsFound[i]  != null && symbolsFound[i].length() >1)
+				multiFound = true; //multichar symbol; must be state; can't use matrix symbol
+		}
+
+		if (project != null && project.getNumberCharMatrices(CategoricalState.class) >=1) {
+			//check last read matrix
+			CategoricalData data = (CategoricalData)project.getCharacterMatrix(project.getNumberCharMatrices(CategoricalState.class)-1, CategoricalState.class);
+			if (symbolsMatch(symbolsFound, data)) {
+				for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+					symbols[i] = getDataSymbol(data, i);
+				return;
+			}
+			//check other matrices for symbols match
+			for (int iD = 0; iD< project.getNumberCharMatrices(CategoricalState.class); iD++){
+				CategoricalData data2 = (CategoricalData)project.getCharacterMatrix(iD, CategoricalState.class);
+				if (symbolsMatch(symbolsFound, data2)) {
+					for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+						symbols[i] = getDataSymbol(data2, i);
+					return;
+				}
+			}
+		}
+		if (symbolsProtein(symbolsFound)) {
+			for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+				symbols[i] = ProteinData.getDefaultStateSymbol(i);
+		}
+		else if (symbolsRNA(symbolsFound)){
+			for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+				symbols[i] = RNAData.getDefaultStateSymbol(i);
+		}
+		else if (symbolsDNA(symbolsFound)){
+			for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+				symbols[i] = DNAData.getDefaultStateSymbol(i);
+		}
+		else if (!multiFound && project != null && project.getNumberCharMatrices(CategoricalState.class) >=1) {
+			//use last read matrix
+			CategoricalData data = (CategoricalData)project.getCharacterMatrix(project.getNumberCharMatrices(CategoricalState.class)-1, CategoricalState.class);
+			for (int i=0; i<=CategoricalState.maxCategoricalState; i++)
+				symbols[i] = getDataSymbol(data, i);
+		}
+		else {
+			for (int i=0; i<=CategoricalState.maxCategoricalState && i<symbolsFound.length; i++){
+				if (symbolsFound[i] != null && symbolsFound[i].equals("2147483646")){  //workaround for file improperly written because of an old bug...
+					if (project.getNumberCharMatrices(CategoricalState.class) >0){
+						CategoricalData data = (CategoricalData)project.getCharacterMatrix(project.getNumberCharMatrices(CategoricalState.class)-1, CategoricalState.class);
+						symbolsFound[i] = data.getStateSymbol(0, i);
+					}
+					else
+						symbolsFound[i] = CategoricalData.getDefaultStateSymbol(CategoricalData.class, i);
+				}
+				symbols[i] = symbolsFound[i];  
+			}
+		}
+
+	}
+
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+		costs.deassignArray();
+		for (int i=0; i<states.length; i++)
+			states[i]=-1;
+		int matrixSize = MesquiteInteger.fromString(description, stringPos);
+		int maxS = matrixSize-1;
+		determineSymbols(description, stringPos.getValue(), matrixSize);
+		CategoricalState cs = new CategoricalState();
+		for (int i=0; i<matrixSize; i++) {
+			String s = ParseUtil.getToken(description, stringPos);
+			int state = -1;
+			if (s !=null && s.length()==1) {  //single state; symbol
+				state = StringArray.indexOf(symbols, s);
+				if (state<0)
+					cs.whichState(s.charAt(0));
+			}
+			else
+				state = MesquiteInteger.fromString(s);
+			if (MesquiteInteger.isCombinable(state) && state>=0 && state<=CategoricalState.maxCategoricalState)
+				states[i] = state;
+			else
+				states[i] = i;
+
+			if (states[i]>maxS)
+				maxS = states[i];
+		}
+		for (int i=0; i<matrixSize; i++) {
+			if (states[i]>=0){
+				for (int j=0; j<matrixSize; j++) {
+					if (states[j]>=0){
+						String costString = ParseUtil.getToken(description, stringPos);
+						if (costString != null){
+							if (costString.equals("."))
+								costs.setValue(states[i]*maxNumStates + states[j], 0);
+							else {
+								utilityNumber.setValue(costString);
+								costs.setValue(states[i]*maxNumStates + states[j], utilityNumber);
+							}
+						}
+					}
+				}
+			}
+		}
+		numStates = maxS+1;
+	}
+
+	//	HERE use saved symbols!  NOTE that if symbols change of matrix, this will cause problems, but so far Mesquite doesn't allow changing of symbols!
+	public String getNexusSpecification () {
+		String s= " ";
+		if (!StringUtil.blank(getAnnotation()))
+			s +=" [!" + getAnnotation() + "] ";
+
+		s += numStates + StringUtil.lineEnding();
+		for (int i=0; i<numStates; i++) 
+			s += "\t" + getStateSymbol(states[i]);
+
+		s+= StringUtil.lineEnding();
+		for (int i=0; i<numStates; i++) {
+			for (int j=0; j<numStates; j++) {
+				int loc = i*maxNumStates + j;
+				if (costs.isInfinite(loc))
+					s+= "\ti";
+				else
+					s+= "\t" + costs.toString(loc);
+			}
+			s+=  StringUtil.lineEnding();
+		}
+		return s;
+	}
+	/** Returns cost to change from beginning to ending state.  Returned value may be undefined
+	if either the begin or end states are not in list of states for which matrix defined*/
+	public MesquiteNumber getTransitionValue (int beginState, int endState, MesquiteNumber result){
+		if (result ==null)
+			result = new MesquiteNumber();
+		if (beginState>=numStates || endState>=numStates)
+			result.setToInfinite();
+		else
+			costs.placeValue(beginState*maxNumStates+endState, result);
+		return result;
+	}
+
+	public boolean isSymmetrical(){
+		for (int i=0; i< numStates; i++){
+			for (int j=i+1; j< numStates; j++)
+				if (!costs.equal(i*maxNumStates+j, j*maxNumStates+i))
+					return false;
+		}
+		return true;
+	}
+
+	/** Returns cost to change from beginning to ending state.  Returned value may be undefined
+	if either the begin or end states are not in list of states for which matrix defined*/
+	public void setTransitionValue (int beginState, int endState, MesquiteNumber result, boolean notify){
+		if (beginState>=numStates || endState>=numStates)
+			return;
+		costs.setValue(beginState*maxNumStates+endState, result);
+		if (notify){
+			notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, true);
+			notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, false);
+		}
+	}
+	/** To set what are the states available for transitions*/
+	public long getStatesDefined () {
+		long sd = CategoricalState.compressFromList(states);
+		return sd & (CategoricalState.span(0, numStates-1));
+	}
+
+	public void setWindow(CategTModelEditWindow window){
+		this.window = window;
+	}
+
+	/** returns the highest state for which the values are defined*/
+	public int getMaxState (){
+		return CategoricalState.maximum(getStatesDefined());
+	}
+
+	public String getExplanation(){	
+		return "Cost of change from state to state is given by a matrix";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/StepsInCharacter/StepsInCharacter.java b/Source/mesquite/parsimony/StepsInCharacter/StepsInCharacter.java
new file mode 100644
index 0000000..ba11b20
--- /dev/null
+++ b/Source/mesquite/parsimony/StepsInCharacter/StepsInCharacter.java
@@ -0,0 +1,241 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.StepsInCharacter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class StepsInCharacter extends NumberForTree implements Incrementable {
+	public String getName() {
+		return "Steps in Character";
+	}
+	public String getExplanation() {
+		return "Calculates the parsimony steps in a character for a given tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + " needs a source of characters from which to calculate parsimony steps.",
+				"You can request a source of characters when " + getName() + " starts, or later under the Source of Characters submenu.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(CharacterSteps.class, getName() + " uses a module to calculate parsimony steps.",
+		"The parsimony steps module is employed automatically; you don't have to do anything to choose it.");
+		//e.setAsEntryPoint(true);
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber steps;
+	CharSourceCoordObed characterSourceTask;
+	CharacterSteps charStepsTask;
+	Taxa oldTaxa = null;
+	CharacterDistribution charStates;
+	int currentChar = 0;
+	long oldTreeID;
+	long oldTreeVersion;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		steps=new MesquiteNumber();
+		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of characters for parsimony steps");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		charStepsTask = (CharacterSteps)hireEmployee(CharacterSteps.class, null);
+		if (charStepsTask == null)
+			return sorry(getName() + " couldn't start because no steps counting module was obtained.");
+		addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==charStepsTask || m == characterSourceTask)
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree == null)
+			return;
+		oldTaxa = tree.getTaxa();
+		characterSourceTask.initialize(tree.getTaxa());
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree == null)
+			return;
+		steps.setValue((int)0);
+		Taxa taxa = tree.getTaxa();
+		if (taxa != oldTaxa && oldTaxa!=null || (characterSourceTask.usesTree() && (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion))) {
+			currentChar = 0;
+			charStates = characterSourceTask.getCharacter(tree, currentChar);
+			oldTreeID = tree.getID();
+			oldTreeVersion = tree.getVersionNumber();
+		}
+		else if (charStates == null) {
+			if (currentChar<0 || currentChar>=characterSourceTask.getNumberOfCharacters(tree))
+				currentChar = 0;
+			charStates = characterSourceTask.getCharacter(tree, currentChar);
+		}
+		
+		result.setToUnassigned();
+		charStepsTask.calculateNumber(tree, charStates, result, resultString);
+		steps.setValue(result);
+		oldTaxa = taxa;
+		result.setValue(steps);
+		if (resultString!=null)
+			resultString.append(" (char. " + CharacterStates.toExternal(currentChar) + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			if (currentChar<0 || currentChar>=characterSourceTask.getNumberOfCharacters(oldTaxa))
+				currentChar = 0;
+			charStates = null;
+			parametersChanged(notification);
+		}
+		else
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public void setCurrent(long i){
+		if (characterSourceTask==null || oldTaxa==null)
+			return;
+		if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+			currentChar = (int)i;
+			charStates=null;
+			//parametersChanged();
+		}
+	}
+	public String getItemTypeName(){
+		return "Character";
+	}
+	/*.................................................................................................................*/
+	public long toInternal(long i){
+		return(CharacterStates.toInternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long toExternal(long i){
+		return(CharacterStates.toExternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long getCurrent(){
+		return currentChar;
+	}
+	/*.................................................................................................................*/
+	public long getMin(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public long getMax(){
+		if (characterSourceTask==null || oldTaxa==null)
+			return 0;
+		return characterSourceTask.getNumberOfCharacters(oldTaxa)-1;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+			if (currentChar>=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			charStates = null;
+			parametersChanged(); 
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=characterSourceTask.getNumberOfCharacters(oldTaxa)-1;
+			else
+				currentChar--;
+			charStates = null;
+			parametersChanged(); 
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(oldTaxa, " to count steps ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				charStates = null;
+				parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(oldTaxa)==0) {
+				currentChar = ic;
+				charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+				currentChar = ic;
+				charStates = null;
+				parametersChanged(); 
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (characterSourceTask == null)
+			return null;
+		return "Current character: " + CharacterStates.toExternal(currentChar) + " from: " + characterSourceTask.getNameAndParameters() ;
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		return "Steps";
+	}
+	public boolean showCitation(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/StoredParsModel/StoredParsModel.java b/Source/mesquite/parsimony/StoredParsModel/StoredParsModel.java
new file mode 100644
index 0000000..6974e48
--- /dev/null
+++ b/Source/mesquite/parsimony/StoredParsModel/StoredParsModel.java
@@ -0,0 +1,210 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.StoredParsModel;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class StoredParsModel extends ParsModelSource {
+  	 public String getName() {
+ 		return "Stored Parsimony Model";
+    	 }
+  	public String getExplanation() {
+  		return "Supplies a user-specified model of character evolution, for parsimony calculations, stored in the file.  This can be different from the model assigned to the character as current in the List of Characters window." ;
+    	 }
+	/*.................................................................................................................*/
+  	 	MesquiteSubmenuSpec smenu;
+	ParsimonyModel currentModel;
+	boolean initialized = false;
+	boolean responseSuppressed = false;
+	MesquiteString modelName;
+	Class currentStateClass = null;
+	int setModelNumber = MesquiteInteger.unassigned;
+	ModelCompatibilityInfo mci;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof Class)
+			currentStateClass = (Class)condition;
+		smenu = addSubmenu(null, "Stored Parsimony Model", makeCommand("setModel", this), getProject().getCharacterModels());
+		mci = new ParsModelCompatInfo(currentStateClass);
+		smenu.setCompatibilityCheck(mci);
+		smenu.setListableFilter(WholeCharacterModel.class);
+		if ((ParsimonyModel)getProject().getCharacterModel(mci, 0)==null)
+			return sorry("There are no suitable stored character models available");
+		modelName = new MesquiteString();
+   		addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+		smenu.setList(getProject().getCharacterModels());
+		smenu.setSelected(modelName);
+		
+		getProject().getCentralModelListener().addListener(this);//to listen for static changes to class of current model
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 ParsimonyModel chooseModel(Class stateClass){
+		if (!MesquiteThread.isScripting()){
+			return (ParsimonyModel)CharacterModel.chooseExistingCharacterModel(this, new ParsModelCompatInfo(stateClass), "Choose probability model (for " + getEmployer().getName() + ").  To make additional models, select New Character Model from the Characters menu.");
+		}
+ 		else
+ 			return (ParsimonyModel)getProject().getCharacterModel(new ParsModelCompatInfo(stateClass), 0);
+  	 }
+	/*.................................................................................................................*/
+  	 public void endJob(){
+		getProject().getCentralModelListener().removeListener(this);
+  	 	super.endJob();
+  	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (currentModel !=null && obj instanceof Class && ((Class)obj).isAssignableFrom(currentModel.getClass())) {
+			parametersChanged(notification);
+		}
+		else if (obj == currentModel) {
+			parametersChanged(notification);
+		}
+		super.changed(caller, obj, notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == currentModel) {
+			currentModel = null;
+			parametersChanged();
+		}
+	}
+  	 
+   	/** returns model for character ic in data */
+   	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+		Class stateClass = currentStateClass;
+		if (data !=null) 
+			stateClass = data.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			currentStateClass = stateClass;
+			mci = new ParsModelCompatInfo(currentStateClass);
+			smenu.setCompatibilityCheck(mci);
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+   	/** returns model for character */
+   	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		Class stateClass = currentStateClass;
+		if (states !=null)
+			stateClass = states.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			currentStateClass = stateClass;
+			mci = new ParsModelCompatInfo(currentStateClass);
+			smenu.setCompatibilityCheck(mci);
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+	/*.................................................................................................................*/
+   	boolean oneAtATime= false;
+   	public void setOneCharacterAtATime(boolean chgbl){
+  		oneAtATime = chgbl;
+   	}
+   	
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (currentModel==null)
+  	 		return null;
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setModel " + getProject().getWhichCharacterModel(mci, currentModel) + "   " + ParseUtil.tokenize(currentModel.getName()));  //TODO:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!should say which model
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the parsimony model of character evolution", "[number of model]", commandName, "setModel")) {
+      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+      			String name = ParseUtil.getToken(arguments, pos);
+ 			ParsimonyModel model = null;
+ 			if (MesquiteInteger.isCombinable(whichModel))
+ 				model = (ParsimonyModel)getProject().getCharacterModel(mci, whichModel);
+ 			
+ 			if ((model !=null || !MesquiteInteger.isCombinable(whichModel)) && currentStateClass == null && name !=null && !(model.getName().equals(name))){ // not restricted state class; could be scripting without
+ 				model = (ParsimonyModel)getProject().getCharacterModel(name);
+ 			}
+ 			
+	     	 	if (model!=null) {
+	     	 		//if (currentModel!=null)
+	     	 		//	currentModel.removeListener(this);
+	     	 		currentModel = model;
+		 		modelName.setValue(currentModel.getName());
+	     	 		//currentModel.addListener(this);
+	     	 		parametersChanged();
+     	 			return model;
+     	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+				String s = "";
+				if (currentModel == null)
+					s = "Sorry, no reference to the current model was found";
+				else
+					s = "The current model is \"" + currentModel.getName() + "\".\nExplanation: " + currentModel.getExplanation();
+				discreetAlert( s);
+				return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (currentModel==null)
+			return "Model NULL";
+		return "Current model \"" + currentModel.getName();
+   	 }
+	/*.................................................................................................................*/
+    	 
+}
+
+class ParsModelCompatInfo extends ModelCompatibilityInfo {
+	public ParsModelCompatInfo(Class targetStateClass){
+		super(ParsimonyModel.class, targetStateClass);
+	}
+	 //obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+ 		if (obj instanceof DolloModel || obj instanceof IrreversibleModel) //since these can't yet be used in Mesquite calculations
+ 			return false;
+ 		return super.isCompatible(obj, project, prospectiveEmployer);
+ 	}
+	
+}
+
+
diff --git a/Source/mesquite/parsimony/Treelength/Treelength.java b/Source/mesquite/parsimony/Treelength/Treelength.java
new file mode 100644
index 0000000..3964552
--- /dev/null
+++ b/Source/mesquite/parsimony/Treelength/Treelength.java
@@ -0,0 +1,134 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.Treelength;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class Treelength extends NumberForTree {
+	public String getName() {
+		return "Treelength";
+	}
+	public String getExplanation() {
+		return "Calculates the parsimony length of a tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+
+		EmployeeNeed e = registerEmployeeNeed(mesquite.parsimony.TreelengthForMatrix.TreelengthForMatrix.class, getName() + " coordinates treelength calculation, and uses another module to help.",
+				"You don't need to do anything to arrange this.");
+		//e.setAsEntryPoint(true);
+		EmployeeNeed e2 = registerEmployeeNeed(MatrixSourceCoord.class, getName() + " needs a character matrix on which to calculate treelength.",
+				"You can request the source of character matrices when " + getName() + " starts, or later under the submenu \"Matrix Source\" or the submenu \"Source of character matrices\".");
+		//e.setAsEntryPoint(true);
+
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber treelength;
+	NumberForMatrixAndTree lengthTask;
+	MatrixSourceCoord characterSourceTask;
+	Taxa oldTaxa = null;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treelength=new MesquiteNumber();
+		lengthTask = (NumberForMatrixAndTree)hireNamedEmployee(NumberForMatrixAndTree.class, "#TreelengthForMatrix");
+		if (lengthTask == null)
+			return sorry(getName() + " couldn't start because no treelength calculator was obtained.");
+		characterSourceTask = (MatrixSourceCoord)hireEmployee(MatrixSourceCoord.class, "Source of characters (for treelength)");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==lengthTask || m == characterSourceTask)
+			iQuit();
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		characterSourceTask.initialize(tree.getTaxa());
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		if (tree == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+
+		Taxa taxa = tree.getTaxa();
+
+		MCharactersDistribution matrix = characterSourceTask.getCurrentMatrix(tree);
+
+
+		if (matrix == null) {
+			if (resultString!=null)
+				resultString.setValue("Treelength not calculated; no matrix supplied");
+			return;
+		}
+		lengthTask.calculateNumber(tree, matrix, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) { //temporary, for data files using old system without coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public boolean biggerIsBetter() {
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			parametersChanged(notification);
+		}
+		else if (employee==lengthTask) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return characterSourceTask.getParameters();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+}
+
diff --git a/Source/mesquite/parsimony/TreelengthForMatrix/TreelengthForMatrix.java b/Source/mesquite/parsimony/TreelengthForMatrix/TreelengthForMatrix.java
new file mode 100644
index 0000000..0fb7438
--- /dev/null
+++ b/Source/mesquite/parsimony/TreelengthForMatrix/TreelengthForMatrix.java
@@ -0,0 +1,121 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.TreelengthForMatrix;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+
+/* ======================================================================== */
+public class TreelengthForMatrix extends NumberForMatrixAndTree {
+	public String getName() {
+		return "Treelength ";
+	}
+	public String getExplanation() {
+		return "Calculates the parsimony treelength of a given tree and matrix.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(CharacterSteps.class, getName() + " uses a module to calculate parsimony steps.",
+		"The parsimony steps module is employed automatically; you don't have to do anything to choose it.");
+		//e.setAsEntryPoint(true);
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber treelength;
+	CharacterSteps charStepsTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treelength=new MesquiteNumber();
+		charStepsTask = (CharacterSteps)hireEmployee(CharacterSteps.class, null);
+		if (charStepsTask ==null)
+			return sorry(getName() + " couldn't start because no step counting module was obtained.");
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, MCharactersDistribution matrix){
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MCharactersDistribution matrix, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || tree == null || matrix == null)
+			return;
+		if (resultString !=null)
+			resultString.setValue("");
+	   	clearResultAndLastResult(result);
+
+		treelength.setValue((int)0);
+		int count=0; 
+		Taxa taxa = tree.getTaxa();
+		MesquiteNumber cNum = new MesquiteNumber();
+		MesquiteNumber wt = new MesquiteNumber();
+		boolean someExcluded = false;
+		CharWeightSet weightSet = null;
+		CharacterData data = matrix.getParentData();
+		if (data !=null)
+			weightSet = (CharWeightSet)data.getCurrentSpecsSet(CharWeightSet.class);
+		for (int ic=0;  ic<matrix.getNumChars(); ic++) {
+			if (matrix.isCurrentlyIncluded(ic)){
+				CharacterDistribution charStates = matrix.getCharacterDistribution(ic);
+				if (charStates!=null){
+					cNum.setToUnassigned();
+					charStepsTask.calculateNumber(tree, charStates, cNum, null);
+					if (cNum.isCombinable()){
+						if (weightSet!=null) {
+							weightSet.placeValue(ic, wt);
+							if (wt.isCombinable())
+								cNum.multiplyBy(wt);
+						}
+						treelength.add(cNum);
+						count++;
+					}
+					else
+						someExcluded = true;
+				}
+			}
+			else
+				someExcluded = true;
+		}
+		String exclString = null;
+		if (someExcluded)
+			exclString = " (" + count + " characters included)";
+		else
+			exclString = "";
+		result.setValue(treelength);
+		if (resultString!=null)
+			resultString.setValue("Treelength: "+ result.toString() + exclString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	public boolean showCitation(){
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/TypesetList/TypesetList.java b/Source/mesquite/parsimony/TypesetList/TypesetList.java
new file mode 100644
index 0000000..a0b2ace
--- /dev/null
+++ b/Source/mesquite/parsimony/TypesetList/TypesetList.java
@@ -0,0 +1,92 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.parsimony.TypesetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.parsimony.lib.*;
+
+/* ======================================================================== */
+public class TypesetList extends DataSpecssetList {
+	public String getName() {
+		return "List of Parsimony Model Sets";
+	}
+	public String getExplanation() {
+		return "Makes a window listing parsimony model sets." ;
+	}
+	/*.................................................................................................................*/
+	public int currentDataSet = 0;
+	public CharacterData data = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Parsimony Model Set...", makeCommand("newTypeset",  this));
+		return true;
+	}
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	public Class getItemType(){
+		return ParsimonyModelSet.class;
+	}
+	public String getItemTypeName(){
+		return "Parsimony model set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Parsimony model sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new ParsimonyModelSet("Parsimony Model Set", data.getNumChars(),data.getDefaultModel("Parsimony"), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new parsimony model set (TYPESET)", null, commandName, "newTypeset")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Model Set", "To make a new parsimony model set, go to the List of Characters window, make sure that a column for Current Parsimony Model appears, edit the column, then save the model set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListParsModels", checker);
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+
+
+
+
+}
+
+
diff --git a/Source/mesquite/parsimony/aParsimonyIntro/aParsimonyIntro.java b/Source/mesquite/parsimony/aParsimonyIntro/aParsimonyIntro.java
new file mode 100644
index 0000000..a03ede5
--- /dev/null
+++ b/Source/mesquite/parsimony/aParsimonyIntro/aParsimonyIntro.java
@@ -0,0 +1,65 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.aParsimonyIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aParsimonyIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aParsimonyIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Preforms parsimony calculations to count steps and treelength of characters on trees.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Parsimony Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Parsimony Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	 public String getAuthors() {
+		return "W.P. Maddison and D.R. Maddison";
+   	 }
+	/*.................................................................................................................*/
+	/** 
+ 	public String getPackageCitation()
+  	public String getPackageVersion()
+  	public String getPackageDateReleased()
+  	public String getPackageAuthors()
+	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation */
+}
+
diff --git a/Source/mesquite/parsimony/explanation.txt b/Source/mesquite/parsimony/explanation.txt
new file mode 100644
index 0000000..762ad38
--- /dev/null
+++ b/Source/mesquite/parsimony/explanation.txt
@@ -0,0 +1,2 @@
+Parsimony Package
+Reconstructs character evolution and assess treelength using the parsimony criterion.  Different models of character evolution are provided for both categorical (unordered, ordered, step matrix) and continuous (squared change, linear) characters.
diff --git a/Source/mesquite/parsimony/lib/CategParsimonyModel.java b/Source/mesquite/parsimony/lib/CategParsimonyModel.java
new file mode 100644
index 0000000..5716283
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/CategParsimonyModel.java
@@ -0,0 +1,28 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** A character model for Categorical characters to be used in parsimony calculations*/
+public abstract class CategParsimonyModel  extends ParsimonyModel {
+	
+	public CategParsimonyModel (String name, Class dataClass) {
+		super(name, dataClass);
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/CharacterSteps.java b/Source/mesquite/parsimony/lib/CharacterSteps.java
new file mode 100644
index 0000000..e65da19
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/CharacterSteps.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Calculates the parsimony steps in a character for a tree.*/
+
+public abstract class CharacterSteps extends NumberForCharAndTree  {
+   	 public Class getDutyClass() {
+   	 	return CharacterSteps.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Steps";
+   	 }
+}
+
+
diff --git a/Source/mesquite/parsimony/lib/ContParsimonyModel.java b/Source/mesquite/parsimony/lib/ContParsimonyModel.java
new file mode 100644
index 0000000..501bd07
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/ContParsimonyModel.java
@@ -0,0 +1,29 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** A character model for continuous characters to be used in parsimony calculations*/
+public abstract class ContParsimonyModel  extends ParsimonyModel {
+	
+	public ContParsimonyModel (String name, Class dataClass) {
+		super(name, dataClass);
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/lib/CostMatrixModel.java b/Source/mesquite/parsimony/lib/CostMatrixModel.java
new file mode 100644
index 0000000..b635439
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/CostMatrixModel.java
@@ -0,0 +1,45 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** A character model for Categorical characters to be used in parsimony calculations*/
+public abstract class CostMatrixModel  extends CategParsimonyModel {
+	
+	public CostMatrixModel (String name, Class dataClass) {
+		super(name, dataClass);
+		allowUseOnDataSubclasses(true);
+	}
+	
+	/** Returns cost to change from beginning to ending state.  Returned value may be undefined
+	if either the begin or end states are not in list of states for which matrix defined.  Passed a
+	MesquiteNumber so doesn't need to create one if instantiated.*/
+	public abstract MesquiteNumber getTransitionValue (int beginState, int endState, MesquiteNumber result);
+	
+	public abstract boolean isSymmetrical();
+	
+	/** returns the set of states for which the values are defined*/
+	public abstract long getStatesDefined ();
+	
+	/** To set what are the states available for transitions*/
+	public int getMaxState (){
+		return 0;
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/DolloModel.java b/Source/mesquite/parsimony/lib/DolloModel.java
new file mode 100644
index 0000000..3514d9f
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/DolloModel.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class DolloModel extends CategParsimonyModel{
+	public DolloModel(){
+		super("Dollo", CategoricalState.class);
+		setBuiltIn(true);
+	}
+	public String getNEXUSName(){
+		return "dollo";
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "Higher valued states must be homologous";
+	}
+	public String getNEXUSClassName(){
+		return "Dollo";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/IrreversibleModel.java b/Source/mesquite/parsimony/lib/IrreversibleModel.java
new file mode 100644
index 0000000..b8be1fd
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/IrreversibleModel.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class IrreversibleModel extends CategParsimonyModel{
+	public IrreversibleModel(){
+		super("Irreversible", CategoricalState.class);
+		setBuiltIn(true);
+	}
+	public String getNEXUSName(){
+		return "irrev";
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "Cost of change from state i to stage j is |i-j|, and only increases in state are allowed";
+	}
+	public String getNEXUSClassName(){
+		return "Irreversible";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/LinearModel.java b/Source/mesquite/parsimony/lib/LinearModel.java
new file mode 100644
index 0000000..6cad675
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/LinearModel.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class LinearModel extends ContParsimonyModel {
+	public LinearModel (String name, Class stateClass){
+		super(name, stateClass);
+		setBuiltIn(true);
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "The cost of a change from x to y is |x-y|";
+	}
+	public String getNEXUSClassName(){
+		return "Linear";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/MPRProcessor.java b/Source/mesquite/parsimony/lib/MPRProcessor.java
new file mode 100644
index 0000000..3ec1424
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/MPRProcessor.java
@@ -0,0 +1,274 @@
+package mesquite.parsimony.lib;
+
+import mesquite.categ.lib.CategoricalHistory;
+import mesquite.categ.lib.CategoricalState;
+import mesquite.lib.Long2DArray;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteMessage;
+import mesquite.lib.MesquiteTrunk;
+import mesquite.lib.Tree;
+import mesquite.lib.characters.*;
+import java.math.*;
+
+
+/* Note:  the switch over to using BigIntegers is only partway done. */
+
+
+public class MPRProcessor {
+	CharacterHistory history = null;
+	long[][] numMPRsForStates = null;
+	BigInteger[][] numMPRsForStatesBigInteger = null;
+	boolean overflow = false;
+
+	public MPRProcessor(CharacterHistory history) {
+		this.history = history;
+		overflow=false;
+	}
+
+	/*.................................................................................................................*/
+	private void assignMPRNumberArray(Tree tree, int node) {
+		checkArrayIntegrity(tree);
+
+		long nodeSet = ((CategoricalHistory)history).getState(node);
+		for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+			if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+				numMPRsForStates[node][ist]=1;
+			}
+		}
+		if (!tree.nodeIsTerminal(node)){
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				assignMPRNumberArray(tree,d);
+				for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+					if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+						long daughterMPR = ((CategoricalHistory)history).getConditionalStateSet(d,ist);
+						long fixedNum = 0;
+						for (int e = 0; e<= CategoricalState.maxCategoricalState; e++){
+							if (CategoricalState.isElement(daughterMPR,e)) {   // e is in the MPR set
+								fixedNum+=numMPRsForStates[d][e];
+							}
+						}
+						
+						numMPRsForStates[node][ist]=numMPRsForStates[node][ist]*fixedNum;
+						if (numMPRsForStates[node][ist]<0)
+							overflow=true;
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private void assignMPRNumberArrayBigInteger(Tree tree, int node) {
+		checkArrayIntegrity(tree);
+
+		long nodeSet = ((CategoricalHistory)history).getState(node);
+		for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+			if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+				numMPRsForStatesBigInteger[node][ist]=new BigInteger("1");
+			}
+		}
+		if (!tree.nodeIsTerminal(node)){
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				assignMPRNumberArray(tree,d);
+				for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+					if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+						long daughterMPR = ((CategoricalHistory)history).getConditionalStateSet(d,ist);
+						BigInteger fixedNum = new BigInteger("0");
+						for (int e = 0; e<= CategoricalState.maxCategoricalState; e++){
+							if (CategoricalState.isElement(daughterMPR,e)) {   // e is in the MPR set
+								fixedNum.add(numMPRsForStatesBigInteger[d][e]);
+							}
+						}
+						
+						numMPRsForStatesBigInteger[node][ist].multiply(fixedNum);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private long numMPRsForNode(Tree tree, int node) {
+		assignMPRNumberArray(tree,node);
+		long nodeMPRs=0;
+		for (int e = 0; e<= CategoricalState.maxCategoricalState; e++){
+			nodeMPRs+=numMPRsForStates[node][e];
+		}
+		if (nodeMPRs<0)
+			overflow=true;
+		if (overflow) {
+			MesquiteMessage.println("Number of MPRs exceeds that allowed.");
+			return Long.MAX_VALUE;
+		}
+
+		return nodeMPRs;
+	}
+	/*.................................................................................................................*/
+	private BigInteger numMPRsForNodeBigInteger(Tree tree, int node) {
+		assignMPRNumberArray(tree,node);
+		BigInteger nodeMPRs = new BigInteger("0");
+		for (int e = 0; e<= CategoricalState.maxCategoricalState; e++){
+			nodeMPRs.add(numMPRsForStatesBigInteger[node][e]);
+		}
+		return nodeMPRs;
+	}
+	private void checkArrayIntegrity (Tree tree) {
+		if (numMPRsForStates==null || numMPRsForStates.length!= tree.getNumNodeSpaces())
+			numMPRsForStates = new long[tree.getNumNodeSpaces()][CategoricalState.maxCategoricalState+1];
+		if (numMPRsForStatesBigInteger==null || numMPRsForStatesBigInteger.length!= tree.getNumNodeSpaces()){
+			numMPRsForStatesBigInteger = new BigInteger[tree.getNumNodeSpaces()][CategoricalState.maxCategoricalState+1];
+			for (int i=0; i<tree.getNumNodeSpaces(); i++) 
+				for (int j=0; j<=CategoricalState.maxCategoricalState; j++) 
+					numMPRsForStatesBigInteger[i][j] = new BigInteger("0");
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public long getNumResolutions(Tree tree) {
+		return getNumResolutions(tree, tree.getRoot());
+	}
+
+	/*.................................................................................................................*/
+	public long getNumResolutions(Tree tree, int node) {
+		overflow=false;
+		checkArrayIntegrity(tree);
+		Long2DArray.zeroArray(numMPRsForStates);
+		if (((CategoricalHistory)history).hasConditionalStateSets()) {
+			return numMPRsForNode(tree,node);
+		}
+		return MesquiteInteger.unassigned;
+	}
+	/*.................................................................................................................*/
+	public BigInteger getNumResolutionsBigInteger(Tree tree, int node) {
+		overflow=false;
+		checkArrayIntegrity(tree);
+		Long2DArray.zeroArray(numMPRsForStates);
+		if (((CategoricalHistory)history).hasConditionalStateSets()) {
+			return numMPRsForNodeBigInteger(tree,node);
+		}
+		return null;
+	}
+
+	/*.................................................................................................................*/
+
+	long numMPRs = 0;
+	BigInteger numMPRsBigInteger = new BigInteger("0");
+	/** Note:  whichMPR is 1-based! */
+
+	private long totalMPRsAtNodeGivenMPRSet(int node, long nodeSet) {
+		long mprTotalInNode = 0;
+		for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+			if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+				mprTotalInNode +=numMPRsForStates[node][ist];
+			}
+		}
+		if (mprTotalInNode<0)
+			overflow=true;
+		if (overflow) {
+			MesquiteMessage.println("Number of MPRs exceeds that allowed.");
+			return Long.MAX_VALUE;
+		}
+		return mprTotalInNode;
+	}
+
+	/*.................................................................................................................*/
+	public void setMPR(Tree tree, CategoricalHistory results, long whichMPR, long totalRemaining, int node) {
+//		first, let's figure out the MPRset for this node given what it's mother is fixed to
+		int stateOfNode = MesquiteInteger.unassigned;
+		int lastState = MesquiteInteger.unassigned;
+		long nodeSet;
+		if (node!=tree.getRoot()) {
+			long motherNodeSet = results.getState(tree.motherOfNode(node));
+			int motherNodeState = CategoricalState.getOnlyElement(motherNodeSet);
+			nodeSet = ((CategoricalHistory)history).getConditionalStateSet(node,motherNodeState);
+		} else
+			nodeSet = results.getState(node);
+
+//		now let's figure out in which of the states of the MPRset our chosen MPR resides
+		long totalMPRsInCladeIfFixed = 0;
+		long numMPRsInStatesCumulative = 0;
+		long whichMPROnceFixed = 0;
+		for (int ist = 0; ist<= CategoricalState.maxCategoricalState; ist++){
+			if (CategoricalState.isElement(nodeSet,ist)) {   // ist is in the MPR set
+				lastState=ist;
+				numMPRsInStatesCumulative +=numMPRsForStates[node][ist];
+
+				if (numMPRsInStatesCumulative>=whichMPR) {
+					numMPRsInStatesCumulative = numMPRsInStatesCumulative - numMPRsForStates[node][ist];
+					totalMPRsInCladeIfFixed = numMPRsForStates[node][ist];
+					whichMPROnceFixed = whichMPR-numMPRsInStatesCumulative;
+					results.setState(node, CategoricalState.makeSet(ist));
+					stateOfNode = ist;
+					break;
+				}
+			}
+		}
+
+//		if our MPR is in the last bin, then we need to calculate the values for it		
+		if (!MesquiteInteger.isCombinable(stateOfNode) && MesquiteInteger.isCombinable(lastState)) {
+			numMPRsInStatesCumulative = numMPRsInStatesCumulative - numMPRsForStates[node][lastState];
+			totalMPRsInCladeIfFixed = numMPRsForStates[node][lastState];
+			whichMPROnceFixed = whichMPR-numMPRsInStatesCumulative;
+			results.setState(node, CategoricalState.makeSet(lastState));
+			stateOfNode = lastState;
+		}
+
+		// now let's cycle through the daughters, and figure out how much each daughter gets out of the pie, and which MPR to use within each daughter
+		long totalMPRsPerMPRInNode = totalMPRsInCladeIfFixed;
+		if (!tree.nodeIsTerminal(node)){
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				long daughterNodeSet = ((CategoricalHistory)history).getConditionalStateSet(d,stateOfNode);
+				long mprsInDaughter = totalMPRsAtNodeGivenMPRSet(d,daughterNodeSet);
+
+				if (mprsInDaughter==0) {
+					totalMPRsPerMPRInNode = Long.MAX_VALUE;
+					MesquiteTrunk.mesquiteTrunk.logln("Number of MPRs exceeds that allowed - calculations can not be completed.");
+					return;
+				}
+				else 
+					totalMPRsPerMPRInNode = totalMPRsPerMPRInNode/mprsInDaughter;
+
+				long whichMPRInDaughter;
+				if (totalMPRsPerMPRInNode==0) {
+					whichMPRInDaughter = Long.MAX_VALUE;
+					MesquiteTrunk.mesquiteTrunk.logln("Number of MPRs exceeds that allowed - calculations can not be completed.");
+					return;
+				}
+				else{
+					whichMPRInDaughter = whichMPROnceFixed / totalMPRsPerMPRInNode;  
+					if (whichMPROnceFixed % totalMPRsPerMPRInNode!=0) 
+						whichMPRInDaughter++;
+				}
+				setMPR(tree,results, whichMPRInDaughter, mprsInDaughter, d);
+				if (totalMPRsPerMPRInNode==0) {
+					whichMPROnceFixed = Long.MAX_VALUE;
+					MesquiteTrunk.mesquiteTrunk.logln("Number of MPRs exceeds that allowed - calculations can not be completed.");
+					return;
+				}
+				whichMPROnceFixed=whichMPROnceFixed % totalMPRsPerMPRInNode+1;   // have to take the remainder and convert it to 1-based; this is for the next daughter
+			}
+		} 
+
+	}
+	
+
+	/** Returns in results the character history that is the resolution "resolutionNumber" */
+	/*.................................................................................................................*/
+	public CharacterHistory getResolution(Tree tree, int node, CharacterHistory results, long resolutionNumber) {
+		if (tree==null || resolutionNumber<0) 
+			return null;
+		long numMPRs = getNumResolutions(tree, node);
+		if (resolutionNumber>=numMPRs || overflow)
+			return null;
+		results=((CategoricalHistory)history).adjustHistorySize(tree,results);
+		history.clone(results);
+		setMPR(tree, (CategoricalHistory)results,resolutionNumber+1, numMPRs, node);
+		return results;
+
+	}
+	/** Returns in results the character history that is the resolution "resolutionNumber" */
+	/*.................................................................................................................*/
+	public CharacterHistory getResolution(Tree tree, CharacterHistory results, long resolutionNumber) {
+	 return getResolution(tree,tree.getRoot(), results, resolutionNumber);
+	}
+	
+
+}
diff --git a/Source/mesquite/parsimony/lib/OrderedModel.java b/Source/mesquite/parsimony/lib/OrderedModel.java
new file mode 100644
index 0000000..e412539
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/OrderedModel.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class OrderedModel extends CategParsimonyModel{
+	public OrderedModel(){
+		super("Ordered", CategoricalState.class);
+		setBuiltIn(true);
+	}
+	public String getNEXUSName(){
+		return "ord";
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "Cost of change from state i to stage j is |i-j|";
+	}
+	public String getNEXUSClassName(){
+		return "Ordered";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/ParsAncStatesForModel.java b/Source/mesquite/parsimony/lib/ParsAncStatesForModel.java
new file mode 100644
index 0000000..0366443
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/ParsAncStatesForModel.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+/**Reconstructs the ancestral states for a character using parsimony, for a specific character model.
+Also counts steps*/
+
+public abstract class ParsAncStatesForModel extends MesquiteModule  {
+	protected boolean calcConditionalMPRs = false;
+   	 public Class getDutyClass() {
+   	 	return ParsAncStatesForModel.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Ancestral states for parsimony model";
+   	 }
+ 	public boolean calculatingConditionalMPRSets(){
+ 		return false;
+ 	}
+ 	public void setCalcConditionalMPRSets(boolean calc){
+ 		calcConditionalMPRs = calc;
+ 	}
+ 	public boolean getCalcConditionalMPRSets(){
+ 		return calcConditionalMPRs;
+ 	}
+	public  abstract void calculateStates(Tree tree, CharacterDistribution charStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber steps);
+	
+	public  abstract void calculateSteps(Tree tree, CharacterDistribution charStates, CharacterModel model, MesquiteString resultString, MesquiteNumber steps);
+	
+	/*Returns whether the module can do its calculation with that character and that model*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return false;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/parsimony/lib/ParsModelSource.java b/Source/mesquite/parsimony/lib/ParsModelSource.java
new file mode 100644
index 0000000..1a37cb7
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/ParsModelSource.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies character models for use in calculation routines.
+These methods must be passed a Data or a CharacterDistribution object because which models are appropriate will depend on these*/
+
+public abstract class ParsModelSource extends CharacterModelSource  {
+
+   	 public Class getDutyClass() {
+   	 	return ParsModelSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Parsimony Model Source";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CurrentParsModels"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/parsimony/lib/ParsimonyModel.java b/Source/mesquite/parsimony/lib/ParsimonyModel.java
new file mode 100644
index 0000000..02ee0e4
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/ParsimonyModel.java
@@ -0,0 +1,42 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/* ======================================================================== */
+/** Sublcass of models of character evolution for parsimony calculations.  It is expected
+that subclasses of this will be specialized for different classes of data (categorical, continuous, etc.)*/
+public abstract class ParsimonyModel extends WholeCharacterModel {
+	public ParsimonyModel (String name, Class stateClass) {
+		super(name, stateClass);
+	}
+	public String getTypeName(){
+		return "Parsimony model";
+	}
+	public String getParadigm(){
+		return "Parsimony";
+	}
+	/** returns nexus command introducing this model (e.g. "USERTYPE" or "CHARMODEL")*/
+	public String getNEXUSCommand() {
+		return "USERTYPE";
+	}
+	public String getModelTypeName(){
+		return "Parsimony model";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/ParsimonyModelSet.java b/Source/mesquite/parsimony/lib/ParsimonyModelSet.java
new file mode 100644
index 0000000..c5c826f
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/ParsimonyModelSet.java
@@ -0,0 +1,44 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+/*======================================================================== */
+/** a ModelSet for parsimony models. */
+public class ParsimonyModelSet  extends ModelSet {
+	
+	public ParsimonyModelSet (String name, int numChars, CharacterModel defaultModel, CharacterData data) {
+		super(name, numChars, defaultModel, data);
+	}
+	public String getTypeName(){
+		return "Parsimony Model set";
+	}
+	public SpecsSet cloneSpecsSet(){
+		ParsimonyModelSet ms = new ParsimonyModelSet(new String(name), getNumberOfParts(), (CharacterModel)getDefaultProperty(), data);
+		for (int i=0; i<getNumberOfParts(); i++) {
+			ms.setModel(getModel(i), i);
+		}
+		return ms;
+	}
+	public SpecsSet makeSpecsSet(AssociableWithSpecs parent, int numParts){
+		if (!(parent instanceof CharacterData))
+			return null;
+		return new ParsimonyModelSet("Parsimony Model Set", numParts, (CharacterModel)getDefaultProperty(), (CharacterData)parent);
+	}
+}
+
+
diff --git a/Source/mesquite/parsimony/lib/SquaredModel.java b/Source/mesquite/parsimony/lib/SquaredModel.java
new file mode 100644
index 0000000..45d4e63
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/SquaredModel.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.categ.lib.*;
+
+
+
+public class SquaredModel extends ContParsimonyModel {
+	public SquaredModel (String name, Class stateClass){
+		super(name, stateClass);
+		setBuiltIn(true);
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "The cost of a change from x to y is (x-y) squared|";
+	}
+	public String getNEXUSClassName(){
+		return "Squared-change";
+	}
+}
+
diff --git a/Source/mesquite/parsimony/lib/UnorderedModel.java b/Source/mesquite/parsimony/lib/UnorderedModel.java
new file mode 100644
index 0000000..5bd1cb4
--- /dev/null
+++ b/Source/mesquite/parsimony/lib/UnorderedModel.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.parsimony.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+
+public class UnorderedModel extends CategParsimonyModel{
+	public UnorderedModel(){
+		super("Unordered", CategoricalState.class);
+		allowUseOnDataSubclasses(true);
+		setBuiltIn(true);
+	}
+	
+	public String getNEXUSName(){
+		return "unord";
+	}
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "Cost of change of state is 1";
+	}
+	public String getNEXUSClassName(){
+		return "Unordered";
+	}
+}
+
diff --git a/Source/mesquite/rhetenor/CanonicalVariates/CanonicalVariates.java b/Source/mesquite/rhetenor/CanonicalVariates/CanonicalVariates.java
new file mode 100644
index 0000000..4948015
--- /dev/null
+++ b/Source/mesquite/rhetenor/CanonicalVariates/CanonicalVariates.java
@@ -0,0 +1,84 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.CanonicalVariates;
+/*~~  */
+
+////import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class CanonicalVariates extends Ordinator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaPartitionSource.class, getName() + "  needs a source for a taxon partition.",
+		"The source of taxon partition is selected initially");
+	}
+	/*.................................................................................................................*/
+	CVAOrdination ord;
+	TaxaPartitionSource partitionSource;
+	boolean first = true;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		partitionSource = (TaxaPartitionSource)hireEmployee(TaxaPartitionSource.class, "Source of Taxa Partitions");
+ 		if (partitionSource == null)
+ 			return sorry(getName() + " couldn't start because no source of taxa partition obtained.");
+ 		return true;
+ 	}
+ 	
+	/*.................................................................................................................*/
+ 	public Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa){
+		TaxaPartition part = partitionSource.getPartition(taxa);
+		if (part== null) {
+			if (first)
+				discreetAlert( "Sorry, Canonical Variates Analysis cannot be performed because there is no available partition of the taxa");
+			first = false;
+			iQuit();
+			return null;
+		}
+		double[][] x = matrix.getMatrix(item);//gets first 2Dmatrix from original
+ 		return new CVAOrdination(x, part);
+ 	}
+	/*.................................................................................................................*/
+    	public String getName() {
+		return "Canonical Variates Analysis";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs canonical variates analysis on a continous-valued matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*
+    	 public String getParameters() {
+   		if (ord==null)
+   			return null;
+   		else
+   			return "Canonical Variates\n"+ ord.report();
+   	 }
+   	 */
+}
+
diff --git a/Source/mesquite/rhetenor/CharFromOrdinations/CharFromOrdinations.java b/Source/mesquite/rhetenor/CharFromOrdinations/CharFromOrdinations.java
new file mode 100644
index 0000000..a4b1deb
--- /dev/null
+++ b/Source/mesquite/rhetenor/CharFromOrdinations/CharFromOrdinations.java
@@ -0,0 +1,353 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.rhetenor.CharFromOrdinations;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+/** this is a quick and dirty intermediary module which uses Ordinators to supply new character matrices.  It currently
+doesn't allow you to choose the source matrix, or to choose which Ordinator is used.  */
+
+public class CharFromOrdinations extends CharacterSource {
+	public String getName() {
+		return "Characters from Ordinations";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies a character from an ordination of an existing matrix." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"The source of matrices can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(Ordinator.class, getName() + "  needs a method to ordinate matrices.",
+		"The method to ordinate matrices can be selected initially or in the Ordination submenu");
+	}
+	/*.................................................................................................................*/
+	MatrixSourceCoord dataTask;
+	Ordinator ordTask;
+	Ordination ord;
+	Taxa oldTaxa = null;
+	long oldTreeID;
+	long oldTreeVersion;
+	MContinuousDistribution originalMatrix = null;
+	MContinuousAdjustable transformedMatrix = null;
+	int currentItem = 0;
+	String itemString = "";
+	int currentChar = 0;
+	MesquiteString ordinatorName;
+	MesquiteCommand otC;
+	/*.................................................................................................................*/
+	/** condition passed to this module must be subclass of CharacterState */
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { 
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+		if (condition!=null && !(condition instanceof Class && ContinuousState.class.isAssignableFrom((Class)condition))){
+			return sorry("Characters from Ordinations cannot be used because it supplies only continuous-valued characters");
+		}
+		otC = makeCommand("setOrdinator",  this);
+		dataTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, ContinuousState.class, "Source of matrices to be ordinated");
+		if (dataTask == null) {
+			return sorry("Can't start Characters from Ordinations because no source of characters found");
+		}
+
+		ordinatorName = new MesquiteString();
+		if (!MesquiteThread.isScripting()) {
+			firstHireOrdinator();
+			if (ordTask==null) {
+				return sorry("Can't start Characters from Ordinations because no ordinator module was obtained");
+			}
+		}
+		if (numModulesAvailable(Ordinator.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Ordination ( for " + employer.getName() + ")", otC, Ordinator.class);
+			mss.setSelected(ordinatorName);
+		}
+		addMenuItem("Item for Ordination...", MesquiteModule.makeCommand("setItem",  this));
+
+		if (numModulesAvailable(OrdinationAssistant.class)>0) {
+			addMenuItem( "-", null);
+			addModuleMenuItems(null, makeCommand("hireAssistant",  this), OrdinationAssistant.class);  //for assistants like Show Char Loadings
+			addMenuItem( "-", null);
+		}
+		return true; 
+	}
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == ordTask || employee == dataTask)
+			iQuit();
+	}
+	private void firstHireOrdinator(){
+		ordTask = (Ordinator)hireEmployee( Ordinator.class, "Ordination ( for " + employer.getName() + ")");
+		if (ordTask == null) {
+			discreetAlert("Can't start Characters from Ordinations because no ordinator found");
+			return;
+		}
+		ordTask.setHiringCommand(otC);
+		ordinatorName.setValue(ordTask.getName());
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource", dataTask);
+		temp.addLine("setOrdinator", ordTask);
+		temp.addLine("setItem " + (currentItem));
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof OrdinationAssistant) {
+				temp.addLine("hireAssistant " , ((MesquiteModule)e));
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the source of matrices on which to do ordinations", null, commandName, "setCharacterSource")) { //TEMPORARY while old files exist
+			if (dataTask != null)
+				return dataTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns the source of matrices on which to do ordinations", null, commandName, "getCharacterSource")) {
+			return dataTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module performing the ordinations", "[name of module]", commandName, "setOrdinator")) {
+			Ordinator newOrdTask=  (Ordinator)replaceEmployee(Ordinator.class, arguments,"Ordinator", ordTask);
+			if (newOrdTask!=null) {
+				ordTask = newOrdTask;
+				ordTask.setHiringCommand(otC);
+				ordinatorName.setValue(ordTask.getName());
+				originalMatrix = null;
+				transformedMatrix = null;
+				parametersChanged(); 
+				return ordTask;
+			}
+			else {
+				discreetAlert( "Unable to activate character source \"" + arguments + "\"  for use by " + getName());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the item to use (in a multi-item continuous data matrix)", "[item number]", commandName, "setItem")) {
+			int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (!MesquiteInteger.isCombinable(ic) && originalMatrix!=null){
+				ic = originalMatrix.userQueryItem("Select item for Characters from Ordination", this);
+			}
+			if (!MesquiteInteger.isCombinable(ic))
+				return null;
+			if (originalMatrix==null) {
+				currentItem = ic;
+			}
+			else if (originalMatrix !=null) {
+				if ((ic>=0) && (ic<originalMatrix.getNumItems())) {
+					currentItem = ic;
+					transformedMatrix = null;
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires an ordination assistant module", "[name of module]", commandName, "hireAssistant")) {
+			OrdinationAssistant assistant=  (OrdinationAssistant)hireNamedEmployee(OrdinationAssistant.class, arguments);
+			if (assistant!=null) {
+				if (ord!=null)
+					assistant.setOrdination(ord, oldTaxa, dataTask);
+				return assistant;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ContinuousStateTest();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		if (dataTask!=null)
+			dataTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		originalMatrix = null;//to force recalculation
+		transformedMatrix = null;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	boolean firstWarning = true;
+	private String allCombinable(MContinuousStates originalMatrix, int item){
+		for (int ic = 0; ic < originalMatrix.getNumChars(); ic++)
+			for (int it = 0; it<originalMatrix.getNumNodes(); it++) {
+				if (!MesquiteDouble.isCombinable(originalMatrix.getState(ic, it, item))){
+					return "State " + MesquiteDouble.toString(originalMatrix.getState(ic, it, item)) + " taxon " + (it+1) + " character " + (ic+1);
+				}
+			}
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void getM(Taxa taxa, Tree tree){
+		originalMatrix = null;
+		transformedMatrix = null;
+		if (dataTask==null)
+			return;
+		if (ordTask==null){
+			if (MesquiteThread.isScripting())
+				return;
+			firstHireOrdinator();
+			if (ordTask==null)
+				return;
+		}
+		if (tree != null) {
+			oldTreeID = tree.getID();
+			oldTreeVersion = tree.getVersionNumber();
+		}
+		MCharactersDistribution input;
+		if (tree==null)
+			input = dataTask.getCurrentMatrix(taxa); 
+		else
+			input = dataTask.getCurrentMatrix(tree); 
+		if (input==null || !(input instanceof MContinuousDistribution)) {
+			return;
+		}
+		MesquiteBoolean wasStripped = new MesquiteBoolean(false);
+		originalMatrix = MatrixUtil.stripExcluded(((MContinuousDistribution)input), wasStripped);  //new after 2. 75
+		
+		if (currentItem<0 || currentItem>= originalMatrix.getNumItems()) {
+			discreetAlert( "Request to use item that doesn't exist for ordination.  Item to be used will be reset to 0.");
+			currentItem = 0;
+		}
+		if (originalMatrix.getNumItems()>1) {
+			if (StringUtil.blank(originalMatrix.getItemName(currentItem)))
+				itemString = " using item #" + (currentItem+1);
+			else
+				itemString = " using item " + originalMatrix.getItemName(currentItem);
+		}
+		else
+			itemString = "";
+		String response = allCombinable(originalMatrix, currentItem);
+		if (response != null) {
+			if (firstWarning) {
+				discreetAlert( "Matrix to be ordinated has missing data or other illegal values.  Ordination cannot be performed. " + response);
+			}
+			firstWarning = false;
+			return;
+		}
+		ord = ordTask.getOrdination(originalMatrix, currentItem, taxa);
+		if (ord==null) {
+			return;
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof OrdinationAssistant) {
+				((OrdinationAssistant)e).setOrdination(ord, taxa,dataTask);
+			}
+		}
+		transformedMatrix = new MContinuousAdjustable(taxa); //making an empty matrix to be filled
+		transformedMatrix.setStates(new Double2DArray(ord.getScores()));
+		String tName = "Ordination from " + originalMatrix.getName();
+		if (wasStripped.getValue())
+			tName += "(excluded characters deleted)";
+		transformedMatrix.setName(tName);
+	}
+	/*.................................................................................................................*/
+	private void dataCheck(Taxa taxa, Tree tree) {
+		if (taxa==null)
+			return;
+		if (transformedMatrix == null || originalMatrix==null  || oldTaxa != taxa || (dataTask.usesTree() && tree!=null && (tree.getID()!=oldTreeID || tree.getVersionNumber()!=oldTreeVersion))) {
+			originalMatrix = null;
+			transformedMatrix = null;
+			getM(taxa, tree);
+			currentChar = 0;
+			oldTaxa = taxa;
+
+		}
+	}
+	/** returns character numbered ic*/
+	public CharacterDistribution getCharacter(Taxa taxa, int ic){
+		currentChar= ic;
+		dataCheck(taxa, null);
+		if (transformedMatrix==null)
+			return null;
+		return transformedMatrix.getCharacterDistribution(ic);
+	}
+	/** returns number of characters for given Taxa*/
+	public int getNumberOfCharacters(Taxa taxa){
+		dataCheck(taxa, null);
+		if (originalMatrix==null)
+			return 0;
+		return originalMatrix.getNumChars();
+	}
+	public boolean usesTree(){
+		if (dataTask==null)
+			return false;
+		else
+			return dataTask.usesTree();
+	}
+	/** returns character numbered ic*/
+	public CharacterDistribution getCharacter(Tree tree, int ic){
+		if (tree ==null)
+			return null;
+		currentChar= ic;
+		dataCheck(tree.getTaxa(), tree);
+		if (transformedMatrix==null)
+			return null;
+		return transformedMatrix.getCharacterDistribution(ic);
+	}
+	/** returns number of characters for given Taxa*/
+	public int getNumberOfCharacters(Tree tree){
+		if (tree ==null)
+			return 0;
+		dataCheck(tree.getTaxa(), tree);
+		if (originalMatrix==null)
+			return 0;
+		return originalMatrix.getNumChars();
+	}
+	/** returns the name of character ic*/
+	public String getCharacterName(Taxa taxa, int ic){ //
+		return "Axis " + ic;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (dataTask==null)
+			return "";
+		if (ordTask == null)
+			return "Matrix source: " + dataTask.getName();
+		else {
+			return "Ordination: " + ordTask.getName() + ";  Matrix source: " + dataTask.getName();
+		}
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters() {
+		if (ordTask == null)
+			return super.getNameAndParameters();
+		else 
+			return "Ordination: " + ordTask.getNameAndParameters() + ";  Original matrix from: " + dataTask.getNameAndParameters() + itemString;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
+
diff --git a/Source/mesquite/rhetenor/CharLoadings/CharLoadings.java b/Source/mesquite/rhetenor/CharLoadings/CharLoadings.java
new file mode 100644
index 0000000..43dcf45
--- /dev/null
+++ b/Source/mesquite/rhetenor/CharLoadings/CharLoadings.java
@@ -0,0 +1,109 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.CharLoadings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class CharLoadings extends CharacterLoadings {
+	Ordination ord;
+	int currentAxis = 0;
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(CharacterDistribution charStates){
+   	}
+   	public void setOrdination(Ordination ord, Taxa taxa){
+   		this.ord = ord;
+   		this.taxa = taxa;
+   	}
+   	public void setCurrentAxis(int i){
+   		if (MesquiteInteger.isPositive(i) || i==0) {
+	   		if (ord==null) 
+	   			currentAxis = i;
+	   		else {
+	   			if (i>= ord.getNumberOfAxes())
+	   				currentAxis = ord.getNumberOfAxes()-1;
+	   			else
+	   				currentAxis = i;
+	   		}
+   		}
+   	}
+   	public int getCurrentAxis(){
+   		return currentAxis;
+   	}
+   	public int getNumberOfAxes(){
+   		if (ord==null) 
+   			return 0;
+   		else
+   			return ord.getNumberOfAxes();
+   	}
+   	public boolean getUserChooseable(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || ord == null || charStates == null)
+    	 		return;
+    	 	
+    	   	clearResultAndLastResult(result);
+    	   	double[][] loads = ord.getEigenvectors();
+    	 	if (loads==null){
+    	 		MesquiteMessage.warnProgrammer("sorry, loadings null");
+    	 		return;
+    	 	}
+    	 	if (charStates instanceof CharacterStates && currentAxis < loads.length && currentAxis>=0 && charStates.getParentCharacter()< loads[currentAxis].length)
+       	 		result.setValue(loads[currentAxis][charStates.getParentCharacter()]);
+       	 	else
+       	 		result.setToUnassigned();
+		if (resultString!=null)
+			resultString.setValue("Loading: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (ord==null)
+			return "";
+		return "Character loadings on " + ord.getAxisName(currentAxis); 
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Character Loadings";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Returns loadings of a character in an ordination" ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/rhetenor/CharsFromMatrices/CharsFromMatrices.java b/Source/mesquite/rhetenor/CharsFromMatrices/CharsFromMatrices.java
new file mode 100644
index 0000000..701a411
--- /dev/null
+++ b/Source/mesquite/rhetenor/CharsFromMatrices/CharsFromMatrices.java
@@ -0,0 +1,384 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.CharsFromMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+/* This is a character source used privately by Rhetenor for ShowCharLoadings.  Note that it is not user chooseable. */
+public class CharsFromMatrices extends CharsFromMatrixSource implements Selectionable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"The source of matrices is selected initially");
+	}
+	/*.................................................................................................................*/
+	int currentChar=0;
+	MatrixSourceCoord matrixSource;
+	MCharactersDistribution matrix;
+	Vector indirectListeners;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		indirectListeners = new Vector();
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+	public boolean startJob(Object condition) {
+		indirectListeners = new Vector();
+  	 	return false; 
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == matrixSource)  // character source quit and none rehired automatically
+ 			iQuit();
+	}
+   	public boolean getUserChooseable(){
+   		return false;
+   	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+ 	public void setMatrixSource(MatrixSourceCoord source){
+ 		matrixSource = source;
+ 	}
+	/*.................................................................................................................*/
+   	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+   		currentChar =ic;
+		matrix = matrixSource.getCurrentMatrix(taxa); //TODO: don't do this every time!
+		if (matrix == null)
+			return null;
+		
+		//
+  		CharacterDistribution dist =  matrix.getCharacterDistribution(ic);
+  		if (dist == null)
+  			return null;
+  		if (dist instanceof CharacterStates)
+  			((CharacterStates)dist).setParentCharacter(ic);
+  		return dist;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfCharacters(Taxa taxa) {
+   		if (matrix==null) {
+   			if (matrixSource==null)
+   				return 0;
+			matrix = matrixSource.getCurrentMatrix(taxa); //TODO: don't do this every time!
+   		}
+  		return countIncludedCharacters(matrix); //matrix.getNumChars();
+   	}
+   	public boolean usesTree(){
+   		if (matrixSource==null)
+   			return false;
+   		else
+   			return matrixSource.usesTree();
+   	}
+	/*.................................................................................................................*/
+   	public CharacterDistribution getCharacter(Tree tree, int ic) {
+   		currentChar =ic;
+		matrix = matrixSource.getCurrentMatrix(tree); //TODO: don't do this every time!
+  		CharacterDistribution dist =  matrix.getCharacterDistribution(ic);
+  		if (dist instanceof CharacterStates)
+  			((CharacterStates)dist).setParentCharacter(ic);
+  		return dist;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfCharacters(Tree tree) {
+   		if (matrix==null) {
+   			if (matrixSource==null)
+   				return 0;
+			matrix = matrixSource.getCurrentMatrix(tree); //TODO: don't do this every time!
+   		}
+  		return countIncludedCharacters(matrix); //matrix.getNumChars();
+   	}
+   	
+  	/** zzzzzzzzzzzz*/
+	/*.................................................................................................................*/
+	CharacterPartition colorSet;
+	public void prepareItemColors(Taxa taxa){
+   		if (matrix==null) {
+   			if (matrixSource==null)
+   				return;
+			matrix = matrixSource.getCurrentMatrix(taxa); //TODO: don't do this every time!
+   		}
+   		if (matrix ==null)
+   			return;
+   		CharacterData data = matrix.getParentData();
+   		if (data ==null)
+   			return;
+		if (taxa==null || data == null || data.getTaxa()!=taxa)
+			colorSet=null;
+		else
+			colorSet = (CharacterPartition)data.getCurrentSpecsSet(CharacterPartition.class); 
+	}
+	boolean respectExclusion = true;
+	public int countIncludedCharacters(MCharactersDistribution matrix){
+		if (matrix == null)
+			return 0;
+   		CharacterData data = matrix.getParentData();
+		if (data==null)
+			return 0;
+		if (!respectExclusion)
+			return data.getNumChars();
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return numChars;
+		int count = 0;
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i))
+				count++;
+		return count;
+
+	}
+	public int countIncludedCharacters(CharacterData data){
+		if (data==null)
+			return 0;
+		if (!respectExclusion)
+			return data.getNumChars();
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return numChars;
+		int count = 0;
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i))
+				count++;
+		return count;
+
+	}
+	public int findIncludedCharacter(CharacterData data, int ic){
+		if (!respectExclusion)
+			return ic;
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return ic;
+		int count = 0;
+		for (int i=0; i<numChars; i++){
+			if (incl.isBitOn(i)){
+				if (count == ic)
+					return i;
+				count++;
+			}
+		}
+		return -1;
+
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (taxa ==null || matrix == null || colorSet == null)
+			return null;
+		
+		if (colorSet!=null){
+			int whichCharacter = ic;
+	   		CharacterData data = matrix.getParentData();
+	   		if (data ==null)
+	   			return null;
+			if (respectExclusion)
+				whichCharacter = findIncludedCharacter(data, ic);
+			CharactersGroup mi = (CharactersGroup)colorSet.getProperty(whichCharacter);
+			if (mi!=null && mi.getColor()!=null) {
+				return mi.getColor();
+			}
+			return null;
+		}
+		return null;
+	}
+
+	public Selectionable getSelectionable(){
+		return this;  //data or this
+	}
+	
+	CharacterData getData(){
+		if (matrix == null)
+			return null;
+		
+		return matrix.getParentData();
+	}
+	/** Sets whether or not the part is selected */
+	public void setSelected(int part, boolean select){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		int ic = findIncludedCharacter(data, part);
+		if (ic>=0)
+			data.setSelected(ic, select);
+	}
+
+	/** Returns whether the part is selected */
+	public boolean getSelected(int part){
+		CharacterData data = getData();
+		if (data == null)
+			return false;
+		int ic = findIncludedCharacter(data, part);
+		if (ic>=0)
+			return data.getSelected(ic);
+		return false;
+	}
+
+	/** Deselects all parts */
+	public void deselectAll(){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.deselectAll();
+	}
+
+	/** Selects all parts */
+	public void selectAll(){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.selectAll();
+	}
+
+
+
+	/** Returns whether there are any selected parts */
+	public boolean anySelected(){
+		CharacterData data = getData();
+		if (data == null)
+			return false;
+		if (!respectExclusion)
+			return data.anySelected();
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return data.anySelected();
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i)  && data.getSelected(i))
+				return true;
+		return false;
+	}
+
+	/** Returns number of selected parts */
+	public int numberSelected(){
+		CharacterData data = getData();
+		if (data == null)
+			return 0;
+
+		CharInclusionSet incl = (CharInclusionSet)data.getCurrentSpecsSet(CharInclusionSet.class);
+		int numChars = data.getNumChars();
+		if (incl==null)
+			return numChars;
+		int count = 0;
+		for (int i=0; i<numChars; i++)
+			if (incl.isBitOn(i) && data.getSelected(i)) //included and selected
+				count++;
+		return count;
+	}
+
+	/** Returns number of parts that can be selected*/
+	public int getNumberOfSelectableParts(){
+		CharacterData data = getData();
+		if (data == null)
+			return 0;
+		return countIncludedCharacters(data);
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** lists listeners of element*/
+	public boolean amIListening(MesquiteListener obj) {
+		CharacterData data = getData();
+		if (data == null)
+			return false;
+		return data.amIListening(obj);
+	}
+	/** lists listeners of element*/
+	public void listListeners() {
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.listListeners();
+	}
+	/** notifies listeners that element has changed*/
+	public void notifyListeners(Object caller, Notification notification){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.notifyListeners(caller, notification);
+	}
+	/** adds a listener to notify if the element changes*/
+	public void addListener(MesquiteListener listener){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		if (indirectListeners.indexOf(listener)<0)
+			indirectListeners.addElement(listener);
+		data.addListener(listener);
+	}
+	/** adds a listener to notify if the element changes; add to start of listener vector so it will be notified early*/
+	public void addListenerHighPriority(MesquiteListener listener){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		if (indirectListeners.indexOf(listener)<0)
+			indirectListeners.addElement(listener);
+		data.addListenerHighPriority(listener);
+	}
+	/** removes a listener*/
+	public void removeListener(MesquiteListener listener){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		indirectListeners.removeElement(listener);
+		data.removeListener(listener);
+	}
+	/** Increments the suppression of listener notification*/
+	public void incrementNotifySuppress(){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.incrementNotifySuppress();
+	}
+	/** Decrements the suppression of listener notification*/
+	public void decrementNotifySuppress(){
+		CharacterData data = getData();
+		if (data == null)
+			return;
+		data.decrementNotifySuppress();
+	}
+
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Taxa taxa, int ic){
+   		return "Character #" + CharacterStates.toExternal(ic) ;
+   	}
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new CharacterStateTest();
+  	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Characters from Matrix Source";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies characters from source of matrices." ;
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/rhetenor/EvolutionaryPCA/EvolutionaryPCA.java b/Source/mesquite/rhetenor/EvolutionaryPCA/EvolutionaryPCA.java
new file mode 100644
index 0000000..7ec90a2
--- /dev/null
+++ b/Source/mesquite/rhetenor/EvolutionaryPCA/EvolutionaryPCA.java
@@ -0,0 +1,81 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.EvolutionaryPCA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class EvolutionaryPCA extends Ordinator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of a current tree.",
+		"The source of current tree is selected initially");
+	}
+	/*.................................................................................................................*/
+	OneTreeSource treeTask;
+	EPCAOrdination ord;
+	String treeString;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree for ePCA");
+ 		if (treeTask == null)
+ 			return sorry(getName() + " couldn't start because no source of trees was obtained.");
+ 		return true;
+ 	}
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+ 	public Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa){
+ 		double[][] x = matrix.getMatrix(item);//gets first 2Dmatrix from original
+		Tree tree;
+		ord =  new EPCAOrdination(x, tree = treeTask.getTree(taxa), true); //only one!
+ 		if (tree !=null)
+ 			treeString = tree.getName();
+ 		else
+ 			treeString = "NO TREE";
+ 		return ord;
+ 	}
+	/*.................................................................................................................*/
+    	public String getName() {
+		return "Evolutionary Principal Components";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs Maddison and Dyreson's evolutionary principal components analysis on a continous-valued matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+   		return "Evolutionary principal components analysis with tree: " + treeString;
+   	 }
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/rhetenor/LandmarkDrawings/32landmark.gif b/Source/mesquite/rhetenor/LandmarkDrawings/32landmark.gif
new file mode 100644
index 0000000..a2a0776
Binary files /dev/null and b/Source/mesquite/rhetenor/LandmarkDrawings/32landmark.gif differ
diff --git a/Source/mesquite/rhetenor/LandmarkDrawings/64landmark.gif b/Source/mesquite/rhetenor/LandmarkDrawings/64landmark.gif
new file mode 100644
index 0000000..7afc2cf
Binary files /dev/null and b/Source/mesquite/rhetenor/LandmarkDrawings/64landmark.gif differ
diff --git a/Source/mesquite/rhetenor/LandmarkDrawings/LandmarkDrawings.java b/Source/mesquite/rhetenor/LandmarkDrawings/LandmarkDrawings.java
new file mode 100644
index 0000000..b9941dd
--- /dev/null
+++ b/Source/mesquite/rhetenor/LandmarkDrawings/LandmarkDrawings.java
@@ -0,0 +1,831 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.rhetenor.LandmarkDrawings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+//todo: move plots via offset
+public class LandmarkDrawings extends TreeDisplayAssistantMA implements LegendHolder {
+	public String getName() {
+		return "Landmark Drawings";
+	}
+
+	public String getExplanation() {
+		return "Places drawing of landmarks at each node in tree." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharsStatesForNodes.class, getName() + "  needs a method to reconstruct ancestral landmarks.",
+		"The method to reconstruct landmarks is selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of character matrices.",
+		"The source of character matrices is selected initially");
+	}
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Show/hide Drawing", "(A tool of the Tree Window when Landmark Drawings is shown) Shows or hides the drawing at the node touched", null, getPath() +"landmark.gif"));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	private Vector plotters;
+	CharsStatesForNodes allCharsTask;
+	MatrixSourceCoord characterSourceTask;
+	int drawingWidth = 100;
+	int drawingHeight = 60;
+	int firstItem = 0;
+	int secondItem = 1;
+	String[] itemNames;
+	int initialOffsetX=MesquiteInteger.unassigned;
+	int initialOffsetY= MesquiteInteger.unassigned;
+	MesquiteBoolean joinLastToFirst = new MesquiteBoolean(true);
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		plotters = new Vector();
+		characterSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, ContinuousState.class,"Source of characters");
+		if (characterSourceTask == null){
+			return sorry(getName() + " couldn't start because no suitable source of characters was obtained");
+		}
+		//TODO: allow choices & use setHIringCommand
+		allCharsTask = (CharsStatesForNodes)hireEmployee(CharsStatesForNodes.class, "Reconstruction method");
+		if (allCharsTask == null){
+			return sorry(getName() + " couldn't start because a suitable reconstructor of ancestral states was not obtained");
+		}
+		makeMenu("Landmarks");
+		addMenuItem("Choose Items...", makeCommand("setItems",  this));
+		addMenuItem("Drawing Sizes...", makeCommand("sizeDrawing",  this));
+		addCheckMenuItem(null, "Join last to first", MesquiteModule.makeCommand("toggleLastToFirst",  this), joinLastToFirst);
+		addMenuItem("Close Landmark Drawings", makeCommand("close",  this));
+		addMenuItem("-", null);
+		return true;
+	}
+
+	public String getExpectedPath(){
+		return getPath() + "landmark.gif";
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("sizeDrawing " + drawingWidth + " " + drawingHeight);
+		PlotOperator tco = (PlotOperator)plotters.elementAt(0);
+		if (tco!=null && tco.legend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.legend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.legend.getOffsetY());
+		}
+		temp.addLine("setItems " + firstItem + " " + secondItem);
+		temp.addLine("toggleLastToFirst " + joinLastToFirst.toOffOnString());
+		temp.addLine("getCharacterSource ", characterSourceTask);
+		temp.addLine("getReconstructor ", allCharsTask);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns source of matrices for Landmark Drawings", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns reconstructor module for Landmark Drawings", null, commandName, "getReconstructor")) {
+			return allCharsTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the source of matrices on which to do Landmark Drawings", null, commandName, "setCharacterSource")) { //TEMPORARY while old files are still around
+			if (characterSourceTask != null)
+				return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Sets initial horizontal offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetX")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+				Enumeration e = plotters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof PlotOperator) {
+						PlotOperator tCO = (PlotOperator)obj;
+						if (tCO.legend!=null)
+							tCO.legend.setOffsetX(offset);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets initial vertical offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetY")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+				Enumeration e = plotters.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof PlotOperator) {
+						PlotOperator tCO = (PlotOperator)obj;
+						if (tCO.legend!=null)
+							tCO.legend.setOffsetY(offset);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of the landmark drawings", "[width in pixels] [height in pixels]", commandName, "sizeDrawing")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			int h = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(h)  && MesquiteInteger.isCombinable(w)) {
+				if (w>10 && h>10) {
+					drawingWidth = w;
+					drawingHeight = h;
+					resizeAllPlotOperators();
+				}
+			}
+			else { 
+				MesquiteBoolean answer = new MesquiteBoolean(false);
+				MesquiteInteger newWidth = new MesquiteInteger(drawingWidth);
+				MesquiteInteger newHeight =new MesquiteInteger(drawingHeight);
+				MesquiteInteger.queryTwoIntegers(containerOfModule(), "Size of drawings ", "Width (Pixels)",  "Height (Pixels)", answer,  newWidth, newHeight,10,MesquiteInteger.unassigned,10, MesquiteInteger.unassigned,MesquiteString.helpString);
+				if (answer.getValue() && newWidth.getValue()>10 && newHeight.getValue()>10) {
+					drawingWidth = newWidth.getValue();
+					drawingHeight = newHeight.getValue();
+					resizeAllPlotOperators();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the size of the landmark drawings", "[x item number] [y item number]", commandName, "setItems")) {
+			pos.setValue(0);
+			int x = MesquiteInteger.fromString(arguments, pos);
+			int y = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(x)  && MesquiteInteger.isCombinable(y)) {
+				if ((itemNames == null || x<itemNames.length) && (itemNames == null || y<itemNames.length)){
+					firstItem = x;
+					secondItem = y;
+					resizeAllPlotOperators();
+					parametersChanged();
+				}
+				return null;
+			}
+			else if (itemNames == null || itemNames.length <2){
+				discreetAlert( "Sorry, you cannot choose items for Landmark Drawings because a matrix has not yet been chosen or it has fewer than two items");
+				return null;
+			}
+			else { 
+				int d = ListDialog.queryList(containerOfModule(), "X axis", "Choose item for X axis of Landmark Drawings:", MesquiteString.helpString, itemNames, firstItem);
+				if (!MesquiteInteger.isCombinable(d))
+					return null;
+				if (d<0 || d>=itemNames.length)
+					d = 0;
+				int dX = d;
+				while (d == dX){
+					d = ListDialog.queryList(containerOfModule(), "Y axis", "Choose item for Y axis of Landmark Drawings:", MesquiteString.helpString, itemNames, secondItem);
+				}
+				if (!MesquiteInteger.isCombinable(d))
+					return null;
+				if (d<0 || d>=itemNames.length) {
+					if (dX == 0)
+						d = 1;
+					else
+						d = 0;
+				}
+				firstItem = dX;
+				secondItem =d;
+				resizeAllPlotOperators();
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to draw a line linking the last to the first landmark", "[on or off]", commandName, "toggleLastToFirst")) {
+			joinLastToFirst.toggleValue(parser.getFirstToken(arguments));
+			resizeAllPlotOperators();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Turn off the landmark drawings", null, commandName, "close")) {
+			iQuit();
+			resetContainingMenuBar();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		PlotOperator newPlotter = new PlotOperator(this, treeDisplay);
+		plotters.addElement(newPlotter);
+		return newPlotter;
+	}
+	/*.................................................................................................................*/
+	public void resizeAllPlotOperators() {
+		Enumeration e = plotters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PlotOperator) {
+				PlotOperator tCO = (PlotOperator)obj;
+				tCO.resize();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void closeAllPlotOperators() {
+		Enumeration e = plotters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PlotOperator) {
+				PlotOperator tCO = (PlotOperator)obj;
+				tCO.turnOff();
+			}
+		}
+	}
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		recalcAllPlotOperators();
+	}
+	/*.................................................................................................................*/
+	public void recalcAllPlotOperators() {
+		Enumeration e = plotters.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof PlotOperator) {
+				PlotOperator tCO = (PlotOperator)obj;
+				tCO.recalculate();
+				if (tCO.getTreeDisplay()!=null)
+					tCO.getTreeDisplay().pleaseUpdate(false);
+			}
+		}
+	}
+	public boolean showLegend(){
+		return true;
+	}
+	public int getInitialOffsetX(){
+		return initialOffsetX;
+	}
+	public int getInitialOffsetY(){
+		return initialOffsetY;
+	}
+	public void endJob() {
+		closeAllPlotOperators();
+		super.endJob();
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+/* ======================================================================== */
+class PlotOperator extends TreeDisplayDrawnExtra implements Commandable {
+	private DrawingsAtNodes plotsAtNodes;
+	private MesquiteNumber resultX, resultY;
+	private MesquiteNumber minX, minY, maxX, maxY;
+	private LandmarkDrawings plotModule;
+	private Tree tree;
+	MContinuousHistory charsStates=null;
+	TreeTool showTool;
+	boolean first = true;
+	LandmarkLegend legend;
+	MesquiteString resultString = new MesquiteString("");
+	MesquiteString messageString = new MesquiteString("");
+
+	public PlotOperator (LandmarkDrawings ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		plotModule = ownerModule;
+		showTool = new TreeTool(this, "ShowDrawing", ownerModule.getPath(), "landmark.gif", 5,2,"Show or hide drawing", "This tool is used to show or hide Landmark Drawings at nodes.");
+		showTool.setTouchedCommand(MesquiteModule.makeCommand("toggleShow",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(showTool);
+		}
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Toggles whether or not the landmark drawing at a node is displayed", "[node number]", commandName, "toggleShow")) {
+			int i = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(i))
+				plotsAtNodes.toggleShowPanel(i);
+
+		}
+		/* *  	 	
+		else return  super.doCommand(commandName, arguments, checker);
+
+    	 /**/
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   void checkPlotStorage(Tree tree){
+		if (tree!=null) {
+			if (plotsAtNodes==null) {
+				plotsAtNodes = new DrawingsAtNodes(plotModule, tree.getNumNodeSpaces(), treeDisplay, this);
+				resize();
+			}
+			else if (plotsAtNodes.getNumNodes()!=tree.getNumNodeSpaces()) {
+				plotsAtNodes.resetNumNodes(tree.getNumNodeSpaces());
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree){
+		this.tree = tree;
+		recalculate();
+
+	}
+	/*.................................................................................................................*/
+	public   void recalculate(){
+		if (legend==null) {
+			legend = new LandmarkLegend(plotModule, treeDisplay, messageString, "Landmark Drawings", Color.black);
+			addPanelPlease(legend);
+			legend.setVisible(true);
+		}
+
+		//check for missing and fail if missing?
+		charsStates = (MContinuousHistory)plotModule.allCharsTask.calculateStates(tree, plotModule.characterSourceTask.getCurrentMatrix(tree), charsStates, resultString);
+		messageString.setValue("Ancestral forms reconstructed by: " + plotModule.allCharsTask.getNameAndParameters() + "\n\nCharacters from: " + plotModule.characterSourceTask.getNameAndParameters());
+		if (charsStates == null)
+			return;
+		messageString.append("\n" + resultString);
+		checkPlotStorage(tree);
+		String[] items = new String[charsStates.getNumItems()];
+		for (int i=0; i<items.length; i++){
+			items[i]= charsStates.getItemName(i);
+		}
+		if (charsStates.getNumItems()==1){
+			if (first)
+				plotModule.discreetAlert( "Sorry, the drawings cannot be shown properly because the characters supplied don't have two components (e.g. x and y components");
+			first = false;
+			plotModule.itemNames = null;
+			plotsAtNodes.hideAllPanels();
+			messageString.setValue("Drawings cannot be shown properly because the characters supplied don't have two components (e.g. x and y components");
+		}
+		else {
+			//harvest item names for later use in user choice
+			plotModule.itemNames = new String[charsStates.getNumItems()];
+			for (int i=0; i<plotModule.itemNames.length; i++){
+				plotModule.itemNames[i]= charsStates.getItemName(i);
+				if (plotModule.itemNames[i] == null)
+					plotModule.itemNames[i] = "#" + (i+1) + " (unnamed)";
+			}
+			plotsAtNodes.setCharsStates(charsStates, tree, plotModule.firstItem, plotModule.secondItem);
+			messageString.setValue("Characters from: " + plotModule.characterSourceTask.getNameAndParameters());
+			if (checkLegalValues(charsStates, tree, tree.getRoot(), plotModule.firstItem))
+				messageString.append("\nHorizontal axis: item " + plotModule.itemNames[plotModule.firstItem]);
+			else
+				messageString.append("\nValues on horizontal axis (item " +plotModule.itemNames[plotModule.firstItem] + ") not shown because reconstruction invalid, possibly because of missing data");
+			if (checkLegalValues(charsStates, tree, tree.getRoot(), plotModule.secondItem))
+				messageString.append("\nVertical axis: item " + plotModule.itemNames[plotModule.secondItem]);
+			else
+				messageString.append("\nValues on vertical axis (item " +plotModule.itemNames[plotModule.secondItem] + ") not shown because reconstruction invalid, possibly because of missing data");
+			messageString.append("\n\nAncestral forms reconstructed by: " + plotModule.allCharsTask.getNameAndParameters());
+		}
+		if (legend != null)
+			legend.repaint();
+
+	}
+	private boolean checkLegalValues(MContinuousHistory history, Tree tree, int node, int item) {
+		boolean illegalValue = false;
+		for (int ic=0; ic<history.getNumChars(); ic++)
+			if (!ContinuousState.isCombinable(charsStates.getState(ic, node, item)))
+				return false;
+
+
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			if (!checkLegalValues(history, tree, daughter, item))
+				return false;
+		return true;
+	}
+	public void resize(){
+		if (plotsAtNodes==null)
+			return;
+		plotsAtNodes.repaintPanels(tree, tree.getRoot());
+		for (int i=0; i<plotsAtNodes.getNumNodes(); i++) {
+			Panel p = plotsAtNodes.getPanel(i);
+			if (p!=null)
+				p.setSize(plotModule.drawingWidth,plotModule.drawingHeight);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		checkPlotStorage(tree);
+		if (plotsAtNodes!=null) {
+			if (treeDisplay!= plotsAtNodes.getTreeDisplay())
+				plotsAtNodes.setTreeDisplay(treeDisplay);
+			plotsAtNodes.locatePanels(tree, drawnRoot);
+			plotsAtNodes.showPanels(tree, drawnRoot);
+		}
+		if (legend!=null)
+			legend.adjustLocation();
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public void turnOff(){
+		if (plotsAtNodes!=null)
+			plotsAtNodes.dispose();
+		if (plotModule!=null && plotModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)plotModule.containerOfModule()).removeTool(showTool);
+		}
+		if (legend!=null)
+			removePanelPlease(legend);
+		super.turnOff();
+	}
+}
+
+/* ======================================================================== */
+/** A class to hold an array of charts for the nodes of a tree. */
+class DrawingsAtNodes extends PanelsAtNodes  {
+	MContinuousHistory history;
+	double minX, maxX, minY, maxY;
+	MesquiteNumber minColor, maxColor;
+	private static final int initialWidth = 100;
+	private static final int initialHeight = 60;
+	double[][] colors;
+	LandmarkDrawings plotModule;
+	int firstItemNumber = 0;
+	int secondItemNumber = 1;
+	PlotOperator plotOperator;
+	Tree tree;
+	double [][][] tGrids, configs;
+	MesquiteColorTable colorTable = new ContColorTable();
+	int steps = 8;
+	public DrawingsAtNodes(LandmarkDrawings ownerModule, int numNodes, TreeDisplay treeDisplay, PlotOperator plotOperator){
+		super(ownerModule, numNodes, treeDisplay);
+		this.plotOperator = plotOperator;
+		plotModule = ownerModule;
+		minColor = new MesquiteNumber();
+		maxColor = new MesquiteNumber();
+
+	}
+
+	public void setCharsStates(MContinuousHistory charsStates, Tree tree, int firstItem, int secondItem){
+		history = charsStates;
+		this.tree = tree;
+		if (tGrids==null || tree.getNumNodeSpaces()< tGrids.length) {
+			tGrids = new double[tree.getNumNodeSpaces()][][];
+			configs = new double[tree.getNumNodeSpaces()][][];
+		}
+		if (configs[0] == null)
+			for (int i=0; i<configs.length; i++) {
+				configs[i] = new double[2][];
+			}
+		int numChars = history.getNumChars();
+		if (configs[0][0]== null || configs[0][0].length!=numChars)
+			for (int i=0; i<configs.length; i++)
+				for (int dim=0; dim<2;dim++) {
+					configs[i][dim] = new double[numChars];
+				}
+		for (int i=0; i<configs.length; i++)
+			Double2DArray.deassignArray(configs[i]);
+		firstItemNumber = firstItem;
+		secondItemNumber = secondItem;
+
+		MesquiteDouble max = new MesquiteDouble();
+		MesquiteDouble min = new MesquiteDouble();
+		history.getMinMax(tree, tree.getRoot(), firstItemNumber, min, max);
+		minX = min.getValue();
+		maxX = max.getValue();
+		history.getMinMax(tree, tree.getRoot(), secondItemNumber, min, max);
+		minY =min.getValue();
+		maxY = max.getValue();
+
+		//calculate squared difference 
+		if (colors==null || colors.length!=numChars || colors.length<1 || colors[0].length!=history.getNumNodes())
+			colors = new double[numChars][history.getNumNodes()];
+		minColor.setToUnassigned();
+		maxColor.setToUnassigned();
+
+		contrastAncestor(tree, tree.getRoot());
+		repaintPanels(tree, tree.getRoot());
+		for (int i=0; i<getNumNodes(); i++) {
+			Panel p =getPanel(i);
+			if (p!=null) {
+				if (tree.nodeIsTerminal(i))
+					p.setBackground(ColorDistribution.lightBlue);
+			}
+
+		}
+	}
+	MesquiteDouble dub = new MesquiteDouble();
+	private void contrastAncestor (Tree tree, int node) {
+		boolean illegalValue = false;
+		for (int ic=0; ic<history.getNumChars(); ic++){
+			configs[node][0][ic]= history.getState(ic, node, firstItemNumber); //seems reversed???
+			configs[node][1][ic]= history.getState(ic, node, secondItemNumber);
+		}
+		if (node != tree.getRoot()) {
+			double[][] grid = MatrixUtil.makeGrid(configs[node], steps);
+			tGrids[node] =  MatrixUtil.tps(grid, configs[tree.motherOfNode(node)], configs[node]);
+		}
+		else
+			tGrids[node]  = MatrixUtil.makeGrid(configs[node], steps);
+
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			contrastAncestor(tree, daughter);
+		if (node != tree.getRoot()) {
+			for (int ic=0; ic<history.getNumChars(); ic++){
+				dub.setValue(0);
+				dub.add(MesquiteDouble.squaredDifference(history.getState(ic, node, firstItemNumber), history.getState(ic, tree.motherOfNode(node), firstItemNumber)));
+				dub.add(MesquiteDouble.squaredDifference(history.getState(ic, node, secondItemNumber), history.getState(ic, tree.motherOfNode(node), secondItemNumber)));
+				colors[ic][node]= dub.getValue();
+				minColor.setMeIfIAmMoreThan(colors[ic][node]);
+				maxColor.setMeIfIAmLessThan(colors[ic][node]);
+			}
+		}
+
+	}
+
+	public Panel makePanel(int i){
+		NodeDrawing c = new NodeDrawing(this, i);
+		if (plotModule==null)
+			c.setSize(initialWidth,initialHeight);
+		else
+			c.setSize(plotModule.drawingWidth,plotModule.drawingHeight);
+		c.setBackground(ColorDistribution.lightGreen);
+		return c;
+	}
+	public void setSizes(int w, int h){
+		for (int i=0; i<numNodes; i++) {
+			Panel p =getPanel(i);
+			if (p !=null) {
+				p.setSize(w, h);
+			}
+		}
+	}
+}
+/* ======================================================================== */
+class NodeDrawing extends MesquitePanel  {
+	DrawingsAtNodes drawings;
+	int whichNode =0;
+	ContinuousState cs=null;
+	ContinuousState ancCs = null;
+	int radius = 4;
+	public NodeDrawing(DrawingsAtNodes drawings, int whichNode){
+		super();
+		this.drawings = drawings;
+		this.whichNode = whichNode;
+	}
+	// -----------------------minimum--------------------;
+	public static double minimum(double[][] matrix, int firstIndex){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		double result = MesquiteDouble.unassigned;
+		for (int j=0; j<numRows; j++) {
+			result = MesquiteDouble.minimum(matrix[firstIndex][j],result);
+		}
+		return result;
+	}
+	// -----------------------maximum--------------------;
+	public static double maximum(double[][] matrix, int firstIndex){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		double result = MesquiteDouble.unassigned;
+		for (int j=0; j<numRows; j++) {
+			result = MesquiteDouble.maximum(matrix[firstIndex][j],result);
+		}
+		return result;
+	}
+	/*............................................................................................*/
+	public void plotGrid(Graphics g, double[][] grid, int steps, int width, int height){
+		if (grid[0].length==0){
+			MesquiteMessage.warnProgrammer("plot grid[0] length 0 ");
+			return;
+		}
+		int[][] rescaled = new int[grid.length][grid[0].length];
+
+		double minX = minimum(grid, 0);
+		double maxX = maximum(grid, 0);
+		double minY = minimum(grid,1);
+		double maxY =maximum(grid, 1);
+		for (int i=0; i<grid[0].length; i++) {
+			rescaled[0][i]=  getX(grid[0][i], minX, maxX, width);
+			rescaled[1][i]=  getY(grid[1][i], minY, maxY, height);
+		}
+
+		for ( int i=0; i<grid[0].length - steps; i++) {
+			int ir = i+1;
+			int ib = i+steps;
+			if (i==0 || (i % steps) != (steps-1))
+				g.drawLine(rescaled[0][i],rescaled[1][i], rescaled[0][ir], rescaled[1][ir]);
+			g.drawLine(rescaled[0][i],rescaled[1][i], rescaled[0][ib], rescaled[1][ib]);	     
+		} 
+		for ( int k=0; k<(steps-1); k++) {
+			int i  = steps*(k);
+			int ir = i+steps;
+			g.drawLine(rescaled[0][i], rescaled[1][i], rescaled[0][ir], rescaled[1][ir]);
+		} 	
+		for ( int l=0; l<(steps-1); l++) {
+			int i  = steps*(steps-1)+(l);
+			int ib = i+1;
+			g.drawLine( rescaled[0][i], rescaled[1][i], rescaled[0][ib], rescaled[1][ib]);
+		} 
+	} 
+	/*	*/
+	int getX(double x, double minX, double maxX, int width){
+		return (int)( (x-minX)/(maxX-minX /*+ 0.1*maxX*/) * width);
+	}
+	int getY(double y, double minY, double maxY, int height){
+		return (int)(height - (int)(((y-minY)/(maxY-minY /*+ 0.1*maxY*/))* height));
+	}
+//	............................................................................................	*/
+	public void drawOutline(Graphics g, double[][]x, double[][]y, double[][]colors,double minX, double maxX, double minY, double maxY, double minColor, double maxColor, Rectangle bounds){
+		if (g==null || bounds==null || x==null || y== null)
+			return;
+		Color c = g.getColor();
+		if (whichNode!=drawings.tree.getRoot()){
+			g.setColor(Color.white);
+			plotGrid(g, drawings.tGrids[whichNode], drawings.steps, bounds.width, bounds.height);
+			if (c!=null) g.setColor(c);
+		}
+		int firstX = MesquiteInteger.unassigned;
+		int firstY = MesquiteInteger.unassigned;
+		int lastX = MesquiteInteger.unassigned;
+		int lastY = MesquiteInteger.unassigned;
+
+		for (int i=0; i<x.length; i++) {
+			int thisX =getX(x[i][whichNode], minX, maxX, bounds.width);
+			int thisY =getY(y[i][whichNode], minY, maxY,  bounds.height);
+			if (MesquiteInteger.isCombinable(lastX))
+				g.drawLine(thisX,thisY,lastX, lastY);
+			else {
+				firstX =thisX;
+				firstY = thisY;
+			}
+			lastX =thisX;
+			lastY = thisY;
+		}
+		if (MesquiteInteger.isCombinable(firstX) && drawings.plotModule.joinLastToFirst.getValue())
+			g.drawLine(firstX,firstY,lastX, lastY);
+
+		Color orig = g.getColor();
+		for (int i=0; i<x.length; i++) {
+			int thisX =getX(x[i][whichNode], minX, maxX, bounds.width);
+			int thisY =getY(y[i][whichNode], minY, maxY,  bounds.height);
+			if (!MesquiteDouble.isUnassigned(x[i][whichNode]) && !MesquiteDouble.isUnassigned(y[i][whichNode])) {
+				g.fillOval(thisX-radius, thisY-radius, radius*2, radius*2);
+				if (colors != null && MesquiteDouble.isCombinable(colors[i][whichNode]) && colors[i][whichNode]!=0) {
+					g.setColor(drawings.colorTable.getColor(colors[i][whichNode], minColor, maxColor));
+					g.fillOval(thisX-radius+1, thisY-radius+1, radius*2-2, radius*2-2);
+					g.setColor(orig);
+				}
+				g.drawString(Integer.toString(CharacterStates.toExternal(i)), thisX+10, thisY);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (tool == drawings.plotOperator.showTool) {
+			drawings.hidePanel(this);
+		}
+	}
+
+	public void paint(Graphics g){
+		if (drawings.history!=null) {
+			g.drawRect(0,0, getBounds().width-1, getBounds().height-1);
+			int height = getBounds().height-radius*2;
+			int width = getBounds().width-radius*2;
+			int firstX = MesquiteInteger.unassigned;
+			int firstY = MesquiteInteger.unassigned;
+			int lastX = MesquiteInteger.unassigned;
+			int lastY = MesquiteInteger.unassigned;
+			Double2DArray dX = drawings.history.getItem(drawings.firstItemNumber);
+			Double2DArray dY = drawings.history.getItem(drawings.secondItemNumber);
+			if (dX==null || dY == null){
+				return;
+			}
+			double[][] x = dX.getMatrix();
+			double[][] y = dY.getMatrix();
+
+			drawOutline(g, x, y, drawings.colors, drawings.minX, drawings.maxX, drawings.minY, drawings.maxY, drawings.minColor.getDoubleValue(), drawings.maxColor.getDoubleValue()*2, new Rectangle(0,0, width, height));
+		}
+	}
+}
+
+
+class LandmarkLegend extends TreeDisplayLegend {
+	private LegendHolder traceModule;
+	private MesquiteString resultString;
+	private static final int defaultLegendWidth=184;
+	private static final int defaultLegendHeight=120;
+	TextArea specsBox;
+	private boolean holding = false;
+	final int defaultSpecsHeight = (114 + MesquiteModule.textEdgeCompensationHeight) * 1;
+	private int specsHeight = defaultSpecsHeight;
+	private int e = 22;
+	private String title;
+	private Color titleColor;
+
+	public LandmarkLegend(LegendHolder traceModule, TreeDisplay treeDisplay, MesquiteString resultString, String title, Color titleColor) {
+		super(treeDisplay,defaultLegendWidth, defaultLegendHeight);
+		setVisible(false);
+		this.title = title;
+		this.titleColor = titleColor;
+		this.resultString = resultString;
+		legendWidth=defaultLegendWidth;
+		legendHeight=defaultLegendHeight;
+		setOffsetX(traceModule.getInitialOffsetX());
+		setOffsetY(traceModule.getInitialOffsetY());
+		this.traceModule = traceModule;
+		setBackground(ColorDistribution.lightGreen);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+
+		specsBox = new TextArea(" ", 2, 2, TextArea.SCROLLBARS_NONE);
+		specsBox.setEditable(false);
+		if (traceModule.showLegend())// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(false);
+		specsBox.setBounds(3, e, legendWidth-6, specsHeight);
+		add(specsBox);
+		specsBox.setBackground(Color.white);
+		reviseBounds();
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public void setVisible(boolean b) {
+		super.setVisible(b);
+		if (specsBox!=null)// && traceModule.showReconstruct.getValue())
+			specsBox.setVisible(b);
+	}
+
+	public void refreshSpecsBox(){
+		if (resultString!=null)
+			specsBox.setText(resultString.getValue()); 
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (!holding) {
+			g.setColor(Color.black);
+			g.setColor(Color.cyan);
+			g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+			g.fillRect(legendWidth-6, legendHeight-6, 6, 6);
+			g.drawLine(0, 0, legendWidth-1, 0);
+
+			g.setColor(titleColor);
+			g.drawString(title, 4, 14);
+			g.setColor(Color.black);
+			if (resultString!=null  && resultString.getValue()!=null && !resultString.getValue().equals(specsBox.getText())){
+				specsBox.setText(resultString.getValue()); 
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void printAll(Graphics g) {
+		g.setColor(Color.black);
+		g.drawString(title, 4, 14);
+		int QspecsHeight = 0;
+		if (resultString!=null) {
+			String info = resultString.getValue();
+			StringInABox sib = new StringInABox(info, g.getFont(), legendWidth);
+			sib.draw(g, 4, 16);
+			QspecsHeight = sib.getHeight();
+		}
+	}
+
+	public void legendResized(int widthChange, int heightChange){
+		if ((specsHeight + heightChange)>= defaultSpecsHeight)
+			specsHeight += heightChange;
+		else
+			specsHeight  = defaultSpecsHeight;
+		checkComponentSizes();
+	}
+
+	public void reviseBounds(){
+		checkComponentSizes();
+		Point where = getLocation();
+		Rectangle bounds = getBounds();
+		if (bounds.width!=legendWidth || bounds.height!=legendHeight) //make sure a change is really needed
+			setBounds(where.x,where.y,legendWidth, legendHeight);
+	}
+	public void checkComponentSizes(){
+		specsBox.setBounds(3,e,legendWidth-6, specsHeight);
+		specsBox.setVisible(true);
+		legendHeight=specsHeight + e + 4;
+	}
+
+	public void onHold() {
+		holding = true;
+	}
+
+	public void offHold() {
+		holding = false;
+	}
+}
+
+
+
+
+
diff --git a/Source/mesquite/rhetenor/LandmarkDrawings/landmark.gif b/Source/mesquite/rhetenor/LandmarkDrawings/landmark.gif
new file mode 100644
index 0000000..ecbae0d
Binary files /dev/null and b/Source/mesquite/rhetenor/LandmarkDrawings/landmark.gif differ
diff --git a/Source/mesquite/rhetenor/MatricesFromOrdinations/MatricesFromOrdinations.java b/Source/mesquite/rhetenor/MatricesFromOrdinations/MatricesFromOrdinations.java
new file mode 100644
index 0000000..32e0d42
--- /dev/null
+++ b/Source/mesquite/rhetenor/MatricesFromOrdinations/MatricesFromOrdinations.java
@@ -0,0 +1,298 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.rhetenor.MatricesFromOrdinations;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+/** this is a quick and dirty intermediary module which uses Ordinators to supply new character matrices.  It currently
+doesn't allow you to choose the source matrix, or to choose which Ordinator is used.  */
+
+public class MatricesFromOrdinations extends CharMatrixSource {
+	public String getName() {
+		return "Matrices from Ordinations";
+	}
+	public String getExplanation() {
+		return "Supplies character matrices from ordinations of existing matrices." ;
+	}
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"The source of matrices can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(Ordinator.class, getName() + "  needs a method to ordinate matrices.",
+		"The method to ordinate matrices can be selected initially or in the Ordination submenu");
+	}
+	MatrixSourceCoord dataTask;
+	Ordinator ordTask;
+	MesquiteString ordinatorName;
+	Ordination ord;
+	Taxa oldTaxa;
+	MesquiteCommand  otC;
+	MContinuousDistribution originalMatrix = null;
+	int currentItem = 0;
+	String itemString = "";
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) { //todo: if tries to hire for non-continous, reject
+		if (condition!=null && condition!= ContinuousData.class && condition!=ContinuousState.class){
+			return sorry("Matrices from Ordinations cannot be used because it supplies only continuous-valued characters");
+		}
+		ordinatorName = new MesquiteString();
+		otC = makeCommand("setOrdinator",  this);
+
+		dataTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, ContinuousState.class, "Source of matrices to be ordinated");
+		if (dataTask == null) 
+			return sorry("Matrices from ordination could not start because not source of characters was obtained");
+
+		if (!MesquiteThread.isScripting()) {
+			ordTask = (Ordinator)hireEmployee( Ordinator.class, "Ordination ( for " + employer.getName() + ")");
+			if (ordTask == null) {
+				return sorry("Matrices from Ordinations cannot be used because no ordinator module was hired successfully");
+			}
+			ordTask.setHiringCommand(otC);
+		}
+		if (numModulesAvailable(Ordinator.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Ordination ( for " + employer.getName() + ")", otC, Ordinator.class);
+			mss.setSelected(ordinatorName);
+		}
+		addMenuItem("Item for Ordination...", MesquiteModule.makeCommand("setItem",  this));
+		if (numModulesAvailable(OrdinationAssistant.class)>0) {
+			addMenuItem( "-", null);
+			addModuleMenuItems(null, makeCommand("hireAssistant",  this), OrdinationAssistant.class);
+			addMenuItem( "-", null);
+		}
+		return true; 
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		oldTaxa = taxa;
+		if (dataTask!=null)
+			dataTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", dataTask);
+		temp.addLine("setOrdinator ", ordTask);
+		temp.addLine("setItem " + (currentItem));
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof OrdinationAssistant) {
+				temp.addLine("hireAssistant " , ((MesquiteModule)e));
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns source of matrices for ordination", null, commandName, "getCharacterSource")) {
+			return dataTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the source of matrices on which to do ordinations", null, commandName, "setCharacterSource")) { //TEMPORARY while old files exist
+			if (dataTask != null)
+				return dataTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Sets the module that performs the ordinations", "[name of module]", commandName, "setOrdinator")) {
+			Ordinator newOrdTask=  (Ordinator)replaceEmployee(Ordinator.class, arguments,"Ordinator", ordTask);
+			if (newOrdTask!=null) {
+				ordTask = newOrdTask;
+				ordTask.setHiringCommand(otC);
+				ordinatorName.setValue(ordTask.getName());
+				parametersChanged(); //?
+				return ordTask;
+			}
+			else {
+				discreetAlert( "Unable to activate character source \"" + arguments + "\"  for use by " + getName());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the item to use (in a multi-item continuous data matrix)", "[item number]", commandName, "setItem")) {
+			int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (!MesquiteInteger.isCombinable(ic) && originalMatrix!=null){
+				ic = originalMatrix.userQueryItem("Select item for Matrices from Ordination", this);
+			}
+			if (!MesquiteInteger.isCombinable(ic))
+				return null;
+			if (originalMatrix==null) {
+				currentItem = ic;
+			}
+			else if (originalMatrix !=null) {
+				if ((ic>=0) && (ic<=originalMatrix.getNumItems()-1)) {
+					currentItem = ic;
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires an ordination assistant module", "name of module", commandName, "hireAssistant")) {
+			OrdinationAssistant assistant=  (OrdinationAssistant)hireNamedEmployee(OrdinationAssistant.class, arguments);
+			if (assistant!=null) {
+				if (ord!=null)
+					assistant.setOrdination(ord, oldTaxa, dataTask);
+
+				return assistant;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	boolean firstWarning = true;
+	private String allCombinable(MContinuousStates originalMatrix, int item){
+		for (int ic = 0; ic < originalMatrix.getNumChars(); ic++)
+			for (int it = 0; it<originalMatrix.getNumNodes(); it++) {
+				if (!MesquiteDouble.isCombinable(originalMatrix.getState(ic, it, item))){
+					return "State " + MesquiteDouble.toString(originalMatrix.getState(ic, it, item)) + " taxon " + (it+1) + " character " + (ic+1);
+				}
+			}
+		return null;
+	}
+	/*.................................................................................................................*/
+	private MCharactersDistribution getM(Taxa taxa, Tree tree){
+		if (dataTask==null)
+			return null;
+		if (ordTask==null) {
+			if (MesquiteThread.isScripting())
+				return null;
+			ordTask = (Ordinator)hireEmployee( Ordinator.class, "Ordination ( for " + employer.getName() + ")");
+			ordTask.setHiringCommand(otC);
+			if (ordTask == null)
+				return null;
+		}
+		oldTaxa =taxa;
+
+		MCharactersDistribution input;
+		if (tree==null)
+			input = dataTask.getCurrentMatrix(taxa); 
+		else
+			input = dataTask.getCurrentMatrix(tree); 
+
+		if (input==null || !(input instanceof MContinuousDistribution))
+			return null;
+		originalMatrix = (MContinuousDistribution)input;
+		if (currentItem<0 || currentItem>= originalMatrix.getNumItems()) {
+			discreetAlert( "Request to use item that doesn't exist for ordination.  Item to be used will be reset to 0.");
+			currentItem = 0;
+		}
+		if (originalMatrix.getNumItems()>1){
+			if (StringUtil.blank(originalMatrix.getItemName(currentItem)))
+				itemString = " using item #" + (currentItem+1);
+			else
+				itemString = " using item " + originalMatrix.getItemName(currentItem);
+		}
+		else
+			itemString = "";
+		String response = allCombinable(originalMatrix, currentItem);
+		if (response != null) {
+			if (firstWarning) {
+				discreetAlert( "Matrix to be ordinated has missing data or other illegal values.  Ordination cannot be performed. " + response);
+			}
+			firstWarning = false;
+			return null;
+		}
+		ord = ordTask.getOrdination(originalMatrix, currentItem, taxa);
+		if (ord==null)
+			return null;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof OrdinationAssistant) {
+				((OrdinationAssistant)e).setOrdination(ord, taxa, dataTask);
+			}
+		}
+		MContinuousAdjustable transformedMatrix = new MContinuousAdjustable(taxa); //making an empty matrix to be filled
+		if (originalMatrix.getName()!=null)
+			transformedMatrix.setName( "Ordination " + ordTask.getName() + " of  matrix " + originalMatrix.getName());
+		else
+			transformedMatrix.setName( "Ordination " + ordTask.getName() + " of  unknown matrix ");
+		transformedMatrix.setStates(new Double2DArray(ord.getScores()));
+		return  transformedMatrix;
+	}
+	/*.................................................................................................................*/
+	public String getMatrixName(Taxa taxa, int ic) {
+		return "Ordination " + ordTask.getName() + " of  matrix ";
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		return getM(taxa, null);
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+		return getM(taxa, null);
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Taxa taxa){
+		return 1; 
+	}
+	public boolean usesTree(){
+		if (dataTask==null)
+			return false;
+		else
+			return dataTask.usesTree();
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getCurrentMatrix(Tree tree){
+		if (tree==null)
+			return null;
+		return getM(tree.getTaxa(), tree);
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getMatrix(Tree tree, int im){
+		if (tree==null)
+			return null;
+		return getM(tree.getTaxa(), tree);
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Tree tree){
+		return 1; 
+	}
+	/*.................................................................................................................*/
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() { 
+		if (ordTask==null || dataTask==null)
+			return "";
+		return "Ordination " + ordTask.getName() + " of  matrix from " + dataTask.getName() + itemString;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ContinuousStateTest();
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/rhetenor/NodeLocs3DPlot/NodeLocs3DPlot.java b/Source/mesquite/rhetenor/NodeLocs3DPlot/NodeLocs3DPlot.java
new file mode 100644
index 0000000..7b860f1
--- /dev/null
+++ b/Source/mesquite/rhetenor/NodeLocs3DPlot/NodeLocs3DPlot.java
@@ -0,0 +1,1267 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.rhetenor.NodeLocs3DPlot;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class NodeLocs3DPlot extends NodeLocsPlot3D {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodesIncr.class, getName() + "  needs a method to calculate positions of nodes.",
+		"The method to calculate positions can be selected initially or in the Node Values submenu");
+	}
+	/*.................................................................................................................*/
+	Point[] location;
+	double[] z;
+	boolean[] badLocs;
+	NumbersForNodesIncr numbersForNodesTask;
+	int margin = 40;
+	TextRotator textRotator;
+	MesquiteString numberTaskName;
+	MesquiteNumber tempNum;
+	Vector extras;
+	boolean veryFirstTime=true;
+	int initialOffsetH = MesquiteInteger.unassigned;
+	int initialOffsetV = MesquiteInteger.unassigned;
+	public MesquiteBoolean showLegend, showAxes, showAxisPlanes;
+	int currentX = 0;
+	int currentY=1;
+	int currentZ=2;
+	String xString, yString, zString;
+	boolean hide = false;
+	MesquiteCommand nfntC;
+	double phi, theta, rho, D;
+	MesquiteCommand setThetaCommand, setPhiCommand, setDCommand;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		extras = new Vector();
+		phi =   theta = Math.PI/4;
+		D = MesquiteDouble.unassigned;
+		numbersForNodesTask= (NumbersForNodesIncr)hireEmployee(NumbersForNodesIncr.class, "Values to calculate for axes");
+		if (numbersForNodesTask == null )
+			return sorry(getName() + " couldn't start because no modules calculating numbers for nodes obtained.");
+		nfntC = makeCommand("setAxis",  this);
+		numbersForNodesTask.setHiringCommand(nfntC);
+		showLegend = new MesquiteBoolean(true);
+		showAxes = new MesquiteBoolean(true);
+		showAxisPlanes = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Plot Legend", makeCommand("toggleShowLegend",  this), showLegend);
+		addCheckMenuItem(null, "Show Axes", makeCommand("toggleShowAxes",  this), showAxes);
+		addCheckMenuItem(null, "Show Axis Planes", makeCommand("toggleShowAxisPlanes",  this), showAxisPlanes);
+		makeMenu("Plot");
+		numberTaskName = new MesquiteString(numbersForNodesTask.getName());
+		if (numModulesAvailable(NumbersForNodesIncr.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Values", nfntC, NumbersForNodesIncr.class);
+			mss.setSelected(numberTaskName);
+		}
+		addMenuItem("Theta", makeCommand("setTheta",  this));
+		addMenuItem("Phi", makeCommand("setPhi",  this));
+
+		setThetaCommand = makeCommand("setTheta",  this);
+		setPhiCommand = makeCommand("setPhi",  this);
+
+		setDCommand =makeCommand("setD",  this);
+
+		tempNum = new MesquiteNumber();
+		MesquiteSubmenuSpec xsub = addSubmenu(null, "X Axis");
+		addItemToSubmenu(null, xsub, "Next", makeCommand("nextX",  this));
+		addItemToSubmenu(null, xsub, "Previous", makeCommand("previousX",  this));
+		addItemToSubmenu(null, xsub, "Choose", makeCommand("setX",  this));
+
+		MesquiteSubmenuSpec ysub = addSubmenu(null, "Y Axis");
+		addItemToSubmenu(null, ysub, "Next", makeCommand("nextY",  this));
+		addItemToSubmenu(null, ysub, "Previous", makeCommand("previousY",  this));
+		addItemToSubmenu(null, ysub, "Choose", makeCommand("setY",  this));
+
+		MesquiteSubmenuSpec zsub = addSubmenu(null, "Z Axis");
+		addItemToSubmenu(null, zsub, "Next", makeCommand("nextZ",  this));
+		addItemToSubmenu(null, zsub, "Previous", makeCommand("previousZ",  this));
+		addItemToSubmenu(null, zsub, "Choose", makeCommand("setZ",  this));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+
+	public void endJob(){
+		if (extras!=null) {
+			for (int i=0; i<extras.size(); i++){
+				TreeDisplayExtra extra = (TreeDisplayExtra)extras.elementAt(i);
+				if (extra!=null){
+					TreeDisplay td = extra.getTreeDisplay();
+					extra.turnOff();
+					if (td!=null)
+						td.removeExtra(extra);
+				}
+			}
+			extras.removeAllElements();
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		adjustScrolls();
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	public NodeLocs3DPlotExtra getFirstExtra(){
+		if (extras!=null) {
+			for (int i=0; i<extras.size(); i++){
+				NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+				if (extra!=null){
+					return extra;
+				}
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine( "hide");
+		temp.addLine( "setAxis " , numbersForNodesTask);
+		temp.addLine("toggleShowLegend " + showLegend.toOffOnString());
+		temp.addLine("toggleShowAxes " + showAxes.toOffOnString());
+		temp.addLine("toggleShowAxisPlanes " + showAxisPlanes.toOffOnString());
+		if (getFirstExtra()!=null && getFirstExtra().legend!=null) {
+			temp.addLine("setInitialOffsetH " + getFirstExtra().legend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetV " + getFirstExtra().legend.getOffsetY());
+		}
+		if (MesquiteDouble.isCombinable(theta))
+			temp.addLine( "setTheta " +  MesquiteDouble.toString(theta));
+		if (MesquiteDouble.isCombinable(phi))
+			temp.addLine( "setPhi " +  MesquiteDouble.toString(phi));
+		if (MesquiteDouble.isCombinable(D))
+			temp.addLine( "setD " + MesquiteDouble.toString(D));
+		temp.addLine( "setCurrentX " + CharacterStates.toExternal(currentX));
+		temp.addLine( "setCurrentY " + CharacterStates.toExternal(currentY));
+		temp.addLine( "setCurrentZ " + CharacterStates.toExternal(currentZ));
+		temp.addLine( "show");
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates coordinates for the nodes", "[name of module]", commandName, "setAxis")) {
+			NumbersForNodesIncr temp =  (NumbersForNodesIncr)replaceEmployee(NumbersForNodesIncr.class, arguments, "Value for axes", numbersForNodesTask);
+			if (temp!=null) {
+				numbersForNodesTask = temp;
+				numbersForNodesTask.setHiringCommand(nfntC);
+				numberTaskName.setValue(numbersForNodesTask.getName());
+				resetContainingMenuBar();
+				parametersChanged();
+			}
+			return temp;
+		}
+
+		else if (checker.compare(this.getClass(), "Hides the plot", null, commandName, "hide")) {
+			hide = true;
+		}
+		else if (checker.compare(this.getClass(), "Shows the plot", null, commandName, "show")) {
+			hide = false;
+		}
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the x axis (used by scripting, before display)", "[number of item]", commandName, "setCurrentX")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			currentX = ic;
+			numbersForNodesTask.setCurrent(ic);
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the y axis (used by scripting, before display)", "[number of item]", commandName, "setCurrentY")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			currentY = ic;
+			numbersForNodesTask.setCurrent(ic);
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the z axis (used by scripting, before display)", "[number of item]", commandName, "setCurrentZ")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			currentZ = ic;
+			numbersForNodesTask.setCurrent(ic);
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets theta", "[angle in radians]", commandName, "setTheta")) {
+			pos.setValue(0);
+			double w = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(w))
+				w = MesquiteDouble.queryDouble(containerOfModule(), "Theta", "Set theta", theta);
+			if (MesquiteDouble.isCombinable(w)) {
+				theta = w;
+				if (extras!=null) {
+					for (int i=0; i<extras.size(); i++){
+						NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+						if (extra!=null && extra.legend !=null){
+							extra.legend.horizSlider.setCurrentValue(theta);
+						}
+					}
+				}
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets phi", "[angle in radians]", commandName, "setPhi")) {
+			pos.setValue(0);
+			double w = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(w))
+				w = MesquiteDouble.queryDouble(containerOfModule(), "Phi", "Set phi", phi);
+			if (MesquiteDouble.isCombinable(w)) {
+				phi = w;
+				if (extras!=null) {
+					for (int i=0; i<extras.size(); i++){
+						NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+						if (extra!=null && extra.legend !=null){
+							extra.legend.vertSlider.setCurrentValue(phi);
+						}
+					}
+				}
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets D", "[distance (>0)]", commandName, "setD")) {
+			pos.setValue(0);
+			double w = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(w))
+				w = MesquiteDouble.queryDouble(containerOfModule(), "D", "Set D", D);
+			if (MesquiteDouble.isCombinable(w)) {
+				D = w;
+				if (extras!=null) {
+					for (int i=0; i<extras.size(); i++){
+						NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+						if (extra!=null && extra.legend !=null){
+							extra.legend.magSlider.setCurrentValue(D);
+						}
+					}
+				}
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the x axis", "[number of item]", commandName, "setX")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (!MesquiteInteger.isCombinable(ic))
+				ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose item (X axis)", "Item to map", 1);
+			if (MesquiteInteger.isCombinable(ic) && (ic>=numbersForNodesTask.getMin()) && (ic<=numbersForNodesTask.getMax())) {
+				currentX = ic;
+				numbersForNodesTask.setCurrent(ic);
+				adjustScrolls();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the y axis", "[number of item]", commandName, "setY")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (!MesquiteInteger.isCombinable(ic))
+				ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose item (Y axis)", "Item to map", 1);
+			if (MesquiteInteger.isCombinable(ic) && (ic>=numbersForNodesTask.getMin()) && (ic<=numbersForNodesTask.getMax())) {
+				currentY = ic;
+				numbersForNodesTask.setCurrent(ic);
+				adjustScrolls();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the current item displayed on the z axis", "[number of item]", commandName, "setZ")) {
+			int ic = CharacterStates.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (!MesquiteInteger.isCombinable(ic))
+				ic = MesquiteInteger.queryInteger(containerOfModule(), "Choose item (Z axis)", "Item to map", 1);
+			if (MesquiteInteger.isCombinable(ic) && (ic>=numbersForNodesTask.getMin()) && (ic<=numbersForNodesTask.getMax())) {
+				currentZ = ic;
+				numbersForNodesTask.setCurrent(ic);
+				adjustScrolls();
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next item for X axis", null, commandName, "nextX")) {
+			if (currentX<numbersForNodesTask.getMax()) {
+				currentX++;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentX);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next item for Y axis", null, commandName, "nextY")) {
+			if (currentY<numbersForNodesTask.getMax()) {
+				currentY++;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentY);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next item for Z axis", null, commandName, "nextZ")) {
+			if (currentZ<numbersForNodesTask.getMax()) {
+				currentZ++;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentZ);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous item for X axis", null, commandName, "previousX")) {
+			if (currentX>numbersForNodesTask.getMin()) {
+				currentX--;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentX);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous item for Y axis", null, commandName, "previousY")) {
+			if (currentY>numbersForNodesTask.getMin()) {
+				currentY--;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentY);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous item for Z axis", null, commandName, "previousZ")) {
+			if (currentZ>numbersForNodesTask.getMin()) {
+				currentZ--;
+				adjustScrolls();
+				numbersForNodesTask.setCurrent(currentZ);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial horizontal offset from home position for the legend", "[offset in pixels]", commandName, "setInitialOffsetH")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetH = offset;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial vertical offset from home position for the legend", "[offset in pixels]", commandName, "setInitialOffsetV")) {
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetV = offset;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show the legend", "[on or off]", commandName, "toggleShowLegend")) {
+			showLegend.toggleValue(parser.getFirstToken(arguments));
+			if (extras!=null) {
+				for (int i=0; i<extras.size(); i++){
+					NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+					if (extra!=null && extra.legend !=null){
+						extra.legend.setVisible(showLegend.getValue());
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show the axes", "[on or off]", commandName, "toggleShowAxes")) {
+			showAxes.toggleValue(parser.getFirstToken(arguments));
+			if (extras!=null) {
+				for (int i=0; i<extras.size(); i++){
+					NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+					if (extra!=null && extra.legend !=null){
+						extra.treeDisplay.pleaseUpdate();
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show the axis planes", "[on or off]", commandName, "toggleShowAxisPlanes")) {
+			showAxisPlanes.toggleValue(parser.getFirstToken(arguments));
+			if (extras!=null) {
+				for (int i=0; i<extras.size(); i++){
+					NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+					if (extra!=null && extra.legend !=null){
+						extra.treeDisplay.pleaseUpdate();
+					}
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	private void adjustScrolls(){
+		if (extras!=null) {
+			for (int i=0; i<extras.size(); i++){
+				NodeLocs3DPlotExtra extra = (NodeLocs3DPlotExtra)extras.elementAt(i);
+				if (extra!=null){
+					extra.adjustScrolls();
+				}
+			}
+		}
+	}
+	public String getName() {
+		return "Node Locations (3D plot)";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the node locations for a tree plotted in a three dimensional space." ;
+	}
+	/*_________________________________________________*/
+	public boolean compatibleWithOrientation(int orientation) {
+		return false;
+	}
+	/*_________________________________________________*/
+	boolean first=true;
+	MesquiteNumber minX, maxX, minY, maxY, minZ, maxZ, sumX, sumY, sumZ, sumSqX, sumSqY, sumSqZ;
+	int nX, nY, nZ;
+	MesquiteNumber xNumber = new MesquiteNumber();
+	MesquiteNumber yNumber = new MesquiteNumber();
+	MesquiteNumber zNumber = new MesquiteNumber();
+
+	private void surveyValues (Tree tree, int node, NumberArray numbersX, NumberArray numbersY, NumberArray numbersZ, MesquiteBoolean illegalValue){
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			surveyValues(tree, d, numbersX, numbersY, numbersZ, illegalValue);
+		if (badLocs[node])
+		return;
+		numbersX.placeValue(node, xNumber);
+		numbersY.placeValue(node, yNumber);
+		numbersZ.placeValue(node, zNumber);
+		boolean thisLocBad = false;
+		if (xNumber.isCombinable()) {
+			sumX.add(xNumber);
+			nX++;
+		}
+		else thisLocBad = true;
+
+		if (yNumber.isCombinable()) {
+			sumY.add(yNumber);
+			nY++;
+		}
+		else thisLocBad = true;
+
+		if (zNumber.isCombinable()) {
+			sumZ.add(zNumber);
+			nZ++;
+		}
+		else thisLocBad = true;
+
+		if (illegalValue != null){
+			if (thisLocBad){
+				illegalValue.setValue(true);
+				badLocs[node] = true;
+			}
+			else {
+				badLocs[node] = false;
+			}
+		}
+
+		if (!thisLocBad){
+			if (first) {
+				maxX.setValue(xNumber);
+				minX.setValue(xNumber);
+				maxY.setValue(yNumber);
+				minY.setValue(yNumber);
+				maxZ.setValue(zNumber);
+				minZ.setValue(zNumber);
+				first = false;
+			}
+			else {
+				maxX.setMeIfIAmLessThan(xNumber);
+				minX.setMeIfIAmMoreThan(xNumber);
+				maxY.setMeIfIAmLessThan(yNumber);
+				minY.setMeIfIAmMoreThan(yNumber);
+				maxZ.setMeIfIAmLessThan(zNumber);
+				minZ.setMeIfIAmMoreThan(zNumber);
+			}
+		}
+		/**/
+	}
+	private void surveyValues2 (Tree tree, int node, NumberArray numbersX, NumberArray numbersY, NumberArray numbersZ){
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			surveyValues2(tree, d, numbersX, numbersY, numbersZ);
+		if (!badLocs[node]){
+			numbersX.placeValue(node, xNumber);
+			numbersY.placeValue(node, yNumber);
+			numbersZ.placeValue(node, zNumber);
+			if (xNumber.isCombinable()) {
+				double x = xNumber.getDoubleValue();
+				sumSqX.add((sumX.getDoubleValue()/nX-x)*(sumX.getDoubleValue()/nX-x));
+			}
+			if (yNumber.isCombinable()) {
+				double y = yNumber.getDoubleValue();
+				sumSqY.add((sumY.getDoubleValue()/nY-y)*(sumY.getDoubleValue()/nY-y));
+			}
+			if (zNumber.isCombinable()) {
+				double z = zNumber.getDoubleValue();
+				sumSqZ.add((sumZ.getDoubleValue()/nZ-z)*(sumZ.getDoubleValue()/nZ-z));
+			}
+		}
+
+	}
+	/*_________________________________________________*/
+	private void fill3Dlocs (Tree tree, int node, MesquiteInteger n, double[][] XYZ, NumberArray numbersX, NumberArray numbersY, NumberArray numbersZ){
+		if (!badLocs[node]){
+			numbersX.placeValue(node, xNumber);
+		XYZ[0][n.getValue()] = xNumber.getDoubleValue();
+		numbersY.placeValue(node, xNumber);
+		XYZ[1][n.getValue()] = xNumber.getDoubleValue();
+		numbersZ.placeValue(node, xNumber);
+		XYZ[2][n.getValue()] = xNumber.getDoubleValue();
+		}
+		n.increment();
+
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			fill3Dlocs(tree, d, n, XYZ, numbersX, numbersY, numbersZ);
+	}
+	/*_________________________________________________*/
+	private void fill2Dlocs (Tree tree, int node, MesquiteInteger n, double[][] XrYr, NumberArray numbersH, NumberArray numbersV, NumberArray numbersD){
+		if (!badLocs[node]){
+			numbersH.setValue(node, XrYr[0][n.getValue()]);
+		numbersV.setValue(node, XrYr[1][n.getValue()]);
+		numbersD.setValue(node, XrYr[2][n.getValue()]);
+		}
+		n.increment();
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			fill2Dlocs(tree, d, n, XrYr, numbersH, numbersV, numbersD);
+	}
+
+	/*_________________________________________________*/
+	private void calcNodeLocs (Tree tree, int node, int pixels, NumberArray numbersX, NumberArray numbersY, NumberArray numbersD){
+		if (location==null|| xNumber==null|| yNumber==null)
+			return;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calcNodeLocs(tree, d, pixels, numbersX, numbersY, numbersD);
+		if (badLocs[node]){
+			location[node].x = MesquiteInteger.unassigned;
+			location[node].y = MesquiteInteger.unassigned;
+		}
+		else {
+			numbersX.placeValue(node, xNumber);
+			numbersY.placeValue(node, yNumber);
+			if (xNumber!=null)
+				location[node].x = xNumber.setWithinBounds(minX, maxX, pixels) /*+ rect.x*/+ margin;
+			if (yNumber!=null)
+				location[node].y = yNumber.setWithinBounds(minY, maxY, pixels) /*+ rect.y*/ + margin;
+			numbersD.placeValue(node, xNumber);
+			z[node] = xNumber.getDoubleValue();
+		}
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		if (employee == numbersForNodesTask)
+			return "for axes";
+		else
+			return "";
+	}
+	// *-------------------standardardize ----------------------------------------;
+	public void standardize(double[][] matrix, double xMean, double yMean, double zMean, double xSD, double ySD, double zSD){
+		int numRows    = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0 )
+			return; 
+
+		for (int j=0; j<numRows; j++) {
+			matrix[0][j] = (matrix[0][j]-xMean)/xSD;
+			matrix[1][j] = (matrix[1][j]-yMean)/ySD;
+			matrix[2][j] = (matrix[2][j]-zMean)/zSD;
+		}
+
+	}
+	/*_________________________________________________*/
+	public void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect) { 
+		if (hide ||  isDoomed())
+			return;
+		if (MesquiteTree.OK(tree)) {
+			if (veryFirstTime) {
+				veryFirstTime=false;
+				numbersForNodesTask.initialize(tree);
+			}
+			NodeLocs3DPlotExtra extra = null;
+			if (treeDisplay.getExtras() !=null) {
+				if (treeDisplay.getExtras().myElements(this)==null) {  //todo: need to do one for each treeDisplay!
+					extra = new NodeLocs3DPlotExtra(this, treeDisplay); 
+
+					treeDisplay.addExtra(extra); 
+					extras.addElement(extra);
+				}
+				else {
+					Listable[] mine = treeDisplay.getExtras().myElements(this);
+					if (mine !=null && mine.length>0)
+						extra =(NodeLocs3DPlotExtra) mine[0];
+				}
+			}
+			extra.setTree(tree);
+			NumberArray numbersX= new NumberArray(tree.getNumNodeSpaces());
+			NumberArray numbersY=new NumberArray(tree.getNumNodeSpaces());
+			NumberArray numbersZ=new NumberArray(tree.getNumNodeSpaces());
+
+			NumberArray numbersH = new NumberArray(tree.getNumNodeSpaces());
+			NumberArray numbersV = new NumberArray(tree.getNumNodeSpaces());
+			NumberArray numbersD = new NumberArray(tree.getNumNodeSpaces());
+
+			numbersForNodesTask.setCurrent(currentX);
+			numbersForNodesTask.calculateNumbers(tree, numbersX, null);
+			xString = "#" + (currentX+1) + " from " + numbersForNodesTask.getNameAndParameters();
+
+			numbersForNodesTask.setCurrent(currentY);
+			numbersForNodesTask.calculateNumbers(tree, numbersY, null);
+			yString = "#" + (currentY+1) + " from " + numbersForNodesTask.getNameAndParameters();
+
+			numbersForNodesTask.setCurrent(currentZ);
+			numbersForNodesTask.calculateNumbers(tree, numbersZ, null);
+			zString = "#" + (currentZ+1) + " from " + numbersForNodesTask.getNameAndParameters();
+			extra.textPositions.setLength(0);
+			nodePositions(tree.getRoot(),  tree, extra.textPositions,  numbersX,  numbersY, numbersZ);
+
+			if (extra!=null)
+				extra.parameters = numbersForNodesTask.getParameters();
+			first = true;
+			int subRoot = tree.motherOfNode(drawnRoot);
+			location = new Point[tree.getNumNodeSpaces()];
+			z = new double[tree.getNumNodeSpaces()];
+			badLocs = new boolean[tree.getNumNodeSpaces()];
+			for (int i=0; i<location.length; i++) {
+				location[i]= new Point();
+				badLocs[i] = false;
+			}
+			minX = new MesquiteNumber();
+			maxX = new MesquiteNumber();
+			minY = new MesquiteNumber();
+			maxY = new MesquiteNumber();
+			minZ = new MesquiteNumber();
+			maxZ = new MesquiteNumber();
+			sumX = new MesquiteNumber(0);
+			nX = 0;
+			sumY = new MesquiteNumber(0);
+			nY = 0;
+			sumZ = new MesquiteNumber(0);
+			nZ = 0;
+			sumSqX = new MesquiteNumber(0);
+			sumSqY = new MesquiteNumber(0);
+			sumSqZ = new MesquiteNumber(0);
+			MesquiteBoolean illegalValue = new MesquiteBoolean(false);
+
+			surveyValues(tree, drawnRoot, numbersX, numbersY, numbersZ, illegalValue); // getting min and max values of X,Y,Z
+			if (illegalValue.getValue()) {
+				/*for (int i=0; i<tree.getNumNodeSpaces() && i<treeDisplay.getTreeDrawing().y.length; i++) {
+						treeDisplay.getTreeDrawing().y[i] = 0;
+						treeDisplay.getTreeDrawing().x[i] = 0;
+						treeDisplay.getTreeDrawing().z[i] = 0;
+					}*/
+				if (extra!=null)
+					extra.addWarning(true);
+				//return;
+			}
+			else 	if (extra!=null)
+				extra.addWarning(false);
+			summarizeBad(0);
+			surveyValues2(tree, drawnRoot, numbersX, numbersY, numbersZ); // getting min and max values of X,Y,Z
+			numNodes = tree.numberOfNodesInClade(drawnRoot);
+			double[][] XYZ = new double[3][numNodes +4 + 6]; //array to hold positions of nodes; extra for center, x, y, z AND rotator points
+			MesquiteInteger n = new MesquiteInteger(0);
+			fill3Dlocs(tree, drawnRoot, n, XYZ, numbersX, numbersY, numbersZ); //filling array with node positions
+			summarizeBad(1);
+			double xCenter;
+			if (nX>0) {
+				xCenter =(sumX.getDoubleValue())/nX; 
+			}
+			else
+				xCenter =(maxX.getDoubleValue()+minX.getDoubleValue())/2; 
+			double yCenter;
+			if (nY>0)
+				yCenter =(sumY.getDoubleValue())/nY; 
+			else
+				yCenter =(maxY.getDoubleValue()+minY.getDoubleValue())/2;
+			double zCenter;
+			if (nZ>0)
+				zCenter =(sumZ.getDoubleValue())/nZ; 
+			else
+				zCenter =(maxZ.getDoubleValue()+minZ.getDoubleValue())/2;
+			double xSpan, ySpan, zSpan;
+			xSpan = Math.sqrt(sumSqX.getDoubleValue()/(nX-1));
+			ySpan = Math.sqrt(sumSqY.getDoubleValue()/(nY-1));
+			zSpan = Math.sqrt(sumSqZ.getDoubleValue()/(nZ-1));
+			XYZ[0][numNodes] = xCenter; //center
+			XYZ[1][numNodes] = yCenter; //center
+			XYZ[2][numNodes] = zCenter; //center
+
+			XYZ[0][numNodes+1] = xSpan; //axis
+			XYZ[1][numNodes+1] = yCenter; //axis
+			XYZ[2][numNodes+1] = zCenter; //axis
+
+			XYZ[0][numNodes+2] =xCenter; //axis
+			XYZ[1][numNodes+2] = ySpan; //axis
+			XYZ[2][numNodes+2] = zCenter; //axis
+
+			XYZ[0][numNodes+3] = xCenter; //axis
+			XYZ[1][numNodes+3] = yCenter; //axis
+			XYZ[2][numNodes+3] = zSpan; //axis
+
+			XYZ[0][numNodes+4] = xSpan; //rotator top
+			XYZ[1][numNodes+4] = yCenter; //rotator was 0
+			XYZ[2][numNodes+4] =zCenter; //rotator
+
+			XYZ[0][numNodes+5] =-xSpan; //rotator bottom
+			XYZ[1][numNodes+5] = yCenter; //rotator
+			XYZ[2][numNodes+5] = zCenter; //rotator
+
+			double sr2 = 1.0/Math.sqrt(2.0);
+			XYZ[0][numNodes+6] = xCenter; //rotator corner
+			XYZ[1][numNodes+6] = ySpan*sr2; //rotator
+			XYZ[2][numNodes+6] = zSpan*sr2; //rotator
+
+			XYZ[0][numNodes+7] = xCenter; //rotator corner
+			XYZ[1][numNodes+7] = -ySpan*sr2; //rotator
+			XYZ[2][numNodes+7] = zSpan*sr2; //rotator
+
+			XYZ[0][numNodes+8] = xCenter; //rotator corner
+			XYZ[1][numNodes+8] = ySpan*sr2; //rotator
+			XYZ[2][numNodes+8] = -zSpan*sr2; //rotator
+
+			XYZ[0][numNodes+9] = xCenter; //rotator corner
+			XYZ[1][numNodes+9] = -ySpan*sr2; //rotator
+			XYZ[2][numNodes+9] = -zSpan*sr2; //rotator
+
+			standardize(XYZ, xCenter, xCenter, xCenter, xSpan, ySpan, zSpan);
+			summarizeBad(2);
+
+			double rangeX = Double2DArray.maximumInColumn(XYZ, 0)-Double2DArray.minimumInColumn(XYZ, 0);
+			double rangeY = Double2DArray.maximumInColumn(XYZ, 1)-Double2DArray.minimumInColumn(XYZ, 1);
+			double rangeZ = Double2DArray.maximumInColumn(XYZ, 2)-Double2DArray.minimumInColumn(XYZ, 2);
+			double longAxis = Math.sqrt(rangeX*rangeX + rangeY*rangeY + rangeZ*rangeZ);
+			double rho = 1.1*longAxis;
+
+			double useD;
+			if (D == MesquiteDouble.unassigned)
+				useD = rho;
+			else
+				useD = D;
+
+			XrYr  = MatrixUtil.transform3Dto2D(XYZ, theta, phi, rho, useD);  //transform to 2D
+			if (extra!=null && extra.legend!=null)
+				extra.legend.setRotatorPoints(XrYr, numNodes, numNodes+4);
+
+			n.setValue(0);
+			fill2Dlocs(tree, drawnRoot, n, XrYr, numbersH, numbersV, numbersD); //taking 2D matrix and setting NumberArrays to store them
+			first = true;
+			summarizeBad(3);
+			surveyValues(tree, drawnRoot, numbersH, numbersV, numbersZ, null); //finding new (transformed) maxX and maxY
+			rangeX = maxX.getDoubleValue()-minX.getDoubleValue();
+			rangeY = maxY.getDoubleValue()-minY.getDoubleValue();
+			rangeZ = maxZ.getDoubleValue()-minZ.getDoubleValue();
+			double corrScaling = (1.1*Math.sqrt(rangeX*rangeX + rangeY*rangeY + rangeZ*rangeZ))/rho; 
+			double midX = XrYr[0][numNodes];
+
+			minX.setValue(midX - (longAxis/2));
+			maxX.setValue(midX + (longAxis/2));
+			double midY = XrYr[1][numNodes];
+			minY.setValue(midY - (longAxis/2));
+			maxY.setValue(midY + (longAxis/2));
+			pixels = MesquiteInteger.minimum(rect.width, rect.height) - 2*margin;
+			summarizeBad(4);
+			calcNodeLocs(tree, drawnRoot, pixels, numbersH, numbersV, numbersD); //calculate pixel node locations from NumberArrays
+			summarizeBad(5);
+			location[subRoot].x = location[drawnRoot].x;
+			location[subRoot].y = location[drawnRoot].y;
+			for (int i=0; i<tree.getNumNodeSpaces() && i<treeDisplay.getTreeDrawing().y.length; i++) {
+				treeDisplay.getTreeDrawing().y[i] = location[i].y;
+				treeDisplay.getTreeDrawing().x[i] = location[i].x;
+				treeDisplay.getTreeDrawing().z[i] = z[i];
+			}
+
+		}
+	}
+	private void summarizeBad(int p){
+		int bad = 0;
+		for (int i=0; i<badLocs.length; i++)
+			if (badLocs[i])
+				bad++;
+	}
+	/*.................................................................................................................*/
+	double[][] XrYr;
+	int numNodes;
+	int pixels;
+	/*.................................................................................................................*/
+	public void nodePositions(int N,  Tree tree, StringBuffer sb, NumberArray numbersX, NumberArray numbersY, NumberArray numbersZ) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			nodePositions(d, tree, sb, numbersX, numbersY, numbersZ);
+		if (tree.nodeIsTerminal(N))
+			sb.append(tree.getTaxa().getName(tree.taxonNumberOfNode(N)) + '\t');
+		else
+			sb.append("node " + N +  '\t');
+		sb.append(numbersX.toString(N) + '\t' + numbersY.toString(N) + '\t' + numbersZ.toString(N) + "\n");
+	}
+
+	private void drawString(Graphics g, String s, int x, int y){
+		if (g == null || StringUtil.blank(s))
+			return;
+		try {
+			g.drawString(s, x, y);
+		}
+		catch (Exception e){
+		}
+	}
+	void drawAxes(Graphics g, NodeLocs3DPlotExtra extra){
+		if (XrYr == null)
+			return;
+		if (showAxes.getValue())
+			drawGrid(g, pixels, XrYr[0][numNodes], XrYr[1][numNodes], XrYr[0][numNodes+1], XrYr[1][numNodes+1], XrYr[0][numNodes+2], XrYr[1][numNodes+2], XrYr[0][numNodes+3], XrYr[1][numNodes+3]);
+	}
+	public void drawGrid (Graphics g, int pixels, double centerXd, double centerYd, double xTipXd, double xTipYd, double yTipXd, double yTipYd, double zTipXd, double zTipYd) {
+		if (hide)
+			return;
+		//double factor = 1;
+		//xTipXd *= factor; xTipYd *= factor; yTipXd *= factor; yTipYd *= factor; zTipXd *= factor; zTipYd *= factor;
+		xNumber.setValue(xTipXd);
+		int xTipX = xNumber.setWithinBounds(minX, maxX, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(xTipYd);
+		int xTipY = xNumber.setWithinBounds(minY, maxY, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(yTipXd);
+		int yTipX = xNumber.setWithinBounds(minX, maxX, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(yTipYd);
+		int yTipY = xNumber.setWithinBounds(minY, maxY, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(zTipXd);
+		int zTipX = xNumber.setWithinBounds(minX, maxX, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(zTipYd);
+		int zTipY = xNumber.setWithinBounds(minY, maxY, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(centerXd);
+		int centerX = xNumber.setWithinBounds(minX, maxX, pixels) /*+ rect.x*/+ margin;
+		xNumber.setValue(centerYd);
+		int centerY = xNumber.setWithinBounds(minY, maxY, pixels) /*+ rect.x*/+ margin;
+		Color c=g.getColor();
+
+		if (showAxisPlanes.getValue()) {
+			//xy rectangle
+			Composite comp = ((Graphics2D)g).getComposite();
+			ColorDistribution.setTransparentGraphics(g,0.5f);		
+			g.setColor(Color.orange);
+			Polygon xyPoly = new Polygon();
+			xyPoly.addPoint(centerX, centerY);
+			xyPoly.addPoint(xTipX, xTipY);
+			//xyPoly.addPoint(xTipX, yTipY);
+			xyPoly.addPoint(yTipX, yTipY);
+			xyPoly.addPoint(centerX, centerY);
+			g.fillPolygon(xyPoly);
+			Polygon xzPoly = new Polygon();
+			xzPoly.addPoint(centerX, centerY);
+			xzPoly.addPoint(xTipX, xTipY);
+			//xyPoly.addPoint(xTipX, yTipY);
+			xzPoly.addPoint(zTipX, zTipY);
+			xzPoly.addPoint(centerX, centerY);
+			g.fillPolygon(xzPoly);
+			Polygon zyPoly = new Polygon();
+			zyPoly.addPoint(centerX, centerY);
+			zyPoly.addPoint(zTipX, zTipY);
+			//xyPoly.addPoint(xTipX, yTipY);
+			zyPoly.addPoint(yTipX, yTipY);
+			zyPoly.addPoint(centerX, centerY);
+			g.fillPolygon(zyPoly);
+			((Graphics2D)g).setComposite(comp);
+		}
+
+		g.setColor(Color.blue);
+		g.drawLine(centerX, centerY, xTipX, xTipY);
+		g.drawLine(centerX+1, centerY, xTipX+1, xTipY);
+		g.drawLine(centerX, centerY+1, xTipX, xTipY+1);
+		g.drawLine(centerX+1, centerY+1, xTipX+1, xTipY+1);
+		drawString(g, "X", xTipX+20, xTipY +20);
+
+
+		g.drawLine(centerX, centerY, yTipX, yTipY);
+		g.drawLine(centerX+1, centerY, yTipX+1, yTipY);
+		g.drawLine(centerX, centerY+1, yTipX, yTipY+1);
+		g.drawLine(centerX+1, centerY+1, yTipX+1, yTipY+1);
+		drawString(g, "Y", yTipX+20, yTipY +20);
+
+
+		g.drawLine(centerX, centerY, zTipX, zTipY);
+		g.drawLine(centerX+1, centerY, zTipX+1, zTipY);
+		g.drawLine(centerX, centerY+1, zTipX, zTipY+1);
+		g.drawLine(centerX+1, centerY+1, zTipX+1, zTipY+1);
+		drawString(g, "Z", zTipX+20, zTipY +20);
+
+
+		if (c!=null) g.setColor(c);
+	}
+
+}
+
+
+
+class NodeLocs3DPlotExtra extends TreeDisplayBkgdExtra {
+	public NodeLocs3DPlotLegend legend;
+	NodeLocs3DPlot locsModule;
+	public String parameters = "";
+	boolean doWarn = false;
+	StringBuffer textPositions;
+
+	public NodeLocs3DPlotExtra (NodeLocs3DPlot ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		locsModule = ownerModule;
+		textPositions = new StringBuffer();
+	}
+	/*.................................................................................................................*/
+	public   String infoAtNodes(Tree tree, int drawnRoot) {
+		return parameters + "\n\nNodes with X, Y, Z positions\n\n" + textPositions.toString();
+	}
+	/*.................................................................................................................*/
+	public   String additionalText(Tree tree, int drawnRoot) {
+		return parameters;
+	}
+
+	public void addWarning(boolean warn){
+		if (legend!=null)
+			legend.addWarning(warn);
+		doWarn = warn;
+	}
+	/*.................................................................................................................*/
+	boolean legendMade = false;
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		locsModule.drawAxes(g, this);
+		if (legend!=null){
+			legend.adjustLocation();
+			legend.repaint();
+		}
+	}
+	public void adjustScrolls(){
+		if (legend!=null){
+			legend.resetScrolls((int)locsModule.numbersForNodesTask.getMin()+1, (int)locsModule.numbersForNodesTask.getMax()+1);
+			legend.resetScrollCurrent(CharacterStates.toExternal(locsModule.currentX), CharacterStates.toExternal(locsModule.currentY), CharacterStates.toExternal(locsModule.currentZ));
+		}
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (!legendMade && legend == null) {
+			legendMade= true;
+			legend = new NodeLocs3DPlotLegend(locsModule, this);
+			legend.setVisible(locsModule.showLegend.getValue());
+			legend.resetScrolls((int)locsModule.numbersForNodesTask.getMin()+1, (int)locsModule.numbersForNodesTask.getMax()+1);
+			legend.resetScrollCurrent(CharacterStates.toExternal(locsModule.currentX), CharacterStates.toExternal(locsModule.currentY), CharacterStates.toExternal(locsModule.currentZ));
+			legend.addWarning(doWarn);
+			addPanelPlease(legend);
+		}
+	}
+
+	public void turnOff() {
+		if (treeDisplay!=null && legend!=null)
+			removePanelPlease(legend);
+		super.turnOff();
+	}
+}
+
+/* ======================================================================== */
+class NodeLocs3DPlotLegend extends TreeDisplayLegend {
+	private NodeLocs3DPlot ownerModule;
+	private NodeLocs3DPlotExtra pD;
+	boolean doWarn = false;
+	int edgeTop = 8;
+	int edgeLeft = 24;
+	int scrollWidth = 62;
+	int scrollHeight = 20;
+	private int oldX=-1;
+	private int oldMaxX=0;
+	private int oldY=-1;
+	private int oldMaxY=0;
+	MesquiteCommand setVertical;
+	MesquiteCommand setHorizontal;
+	MesquiteCommand setMagnification;
+	int[] polyOrder;
+	double[][] points;
+	int[][] triangles;
+	double[] centerPoint;
+	Polygon[] polys;
+	TextArea text;
+	MiniSlider vertSlider, horizSlider, magSlider;
+	MiniScroll xScroll, yScroll, zScroll;
+	public NodeLocs3DPlotLegend(NodeLocs3DPlot ownerModule, NodeLocs3DPlotExtra pD) {
+		super(pD.treeDisplay, 240, 170);
+		this.setVertical = ownerModule.setPhiCommand;
+		this.setHorizontal =ownerModule.setThetaCommand;
+		this.setMagnification =ownerModule.setDCommand;
+		this.pD = pD;
+		text = new TextArea("", 3, 3, TextArea.SCROLLBARS_VERTICAL_ONLY);
+		add(text);
+		text.setLocation(30, 4);
+		text.setSize(legendWidth-30-4, legendHeight -80);
+		points = new double[3][7];
+		centerPoint = new double[3];
+		polyOrder = new int[8];
+		polys = new Polygon[8];
+		for (int i=0; i<8; i++) {
+			polys[i] = new Polygon();
+			polys[i].xpoints = new int[3];
+			polys[i].ypoints = new int[3];
+		}
+		triangles = new int[3][8];
+		centerPoint[0] = legendWidth/2;
+		centerPoint[1] = legendHeight/2;
+		//setBackground(Color.cyan);
+		centerPoint[2] = 0;
+		this.ownerModule = ownerModule;
+		setLayout(null);
+		setOffsetX(ownerModule.initialOffsetH);
+		setOffsetY(ownerModule.initialOffsetV);
+		magSlider = new MiniSlider(setMagnification, true, ownerModule.D, 0.0, 100.0, 0.0, 100.0);
+		vertSlider = new MiniSlider(setVertical, false, ownerModule.phi, 0.0, Math.PI*2, 0.0, Math.PI*2);
+		horizSlider = new MiniSlider(setHorizontal, true, ownerModule.theta, 0.0, Math.PI*2, 0.0, Math.PI*2);
+		add(vertSlider);
+		vertSlider.setLocation(4, edgeTop);
+		vertSlider.setRangeInPixels(legendHeight-edgeTop-edgeTop-edgeTop);
+		vertSlider.setColor(Color.green);
+		add(horizSlider);
+		horizSlider.setLocation(edgeLeft, legendHeight-55);
+		horizSlider.setRangeInPixels(legendWidth-edgeLeft-edgeLeft - scrollWidth);
+		horizSlider.setColor(Color.green);
+		add(magSlider);
+		magSlider.setLocation(edgeLeft, legendHeight-20);
+		magSlider.setRangeInPixels(legendWidth-edgeLeft-edgeLeft - scrollWidth);
+		magSlider.setVisible(true);
+		magSlider.setColor(Color.red);
+		vertSlider.setVisible(true);
+		horizSlider.setVisible(true);
+		setSize(legendWidth, legendHeight);
+		xScroll = new MiniScroll(MesquiteModule.makeCommand("setX",  ownerModule), false, 1, 1, 1,"");
+		add(xScroll);
+		xScroll.setLocation(legendWidth-edgeLeft - scrollWidth, legendHeight-(scrollHeight+5)*3);
+		xScroll.setColor(Color.blue);
+		xScroll.setVisible(true);
+		yScroll = new MiniScroll(MesquiteModule.makeCommand("setY",  ownerModule), false, 1, 1, 1,"");
+		add(yScroll);
+		yScroll.setLocation(legendWidth-edgeLeft - scrollWidth, legendHeight-(scrollHeight+5)*2);
+		yScroll.setColor(Color.blue);
+		yScroll.setVisible(true);
+		zScroll = new MiniScroll(MesquiteModule.makeCommand("setZ",  ownerModule), false, 1, 1, 1,"");
+		add(zScroll);
+		zScroll.setLocation(legendWidth-edgeLeft - scrollWidth, legendHeight-scrollHeight-5);
+		zScroll.setColor(Color.blue);
+		zScroll.setVisible(true);
+	}
+	void resetScrolls(int min, int max){
+		resetScroll(xScroll, min, max);
+		resetScroll(yScroll, min, max);
+		resetScroll(zScroll, min, max);
+	}
+	void resetScrollCurrent(int x, int y, int z){
+		xScroll.setCurrentValue(x);
+		yScroll.setCurrentValue(y);
+		zScroll.setCurrentValue(z);
+	}
+	void resetScroll(MiniScroll scroll, int min, int max){
+		if (scroll == null)
+			return;
+		scroll.setMinimumValue(min);
+		scroll.setMaximumValue(max);
+		if (scroll.getCurrentValue()<min)
+			scroll.setCurrentValue(min);
+		else if (scroll.getCurrentValue()>max)
+			scroll.setCurrentValue(max);
+	}
+	public void addWarning(boolean warn){
+		doWarn = warn;
+	}
+	public void adjustRotation() {
+	}
+	double distance(int p0, int p1){
+		double vertSpanX = points[0][p0]-points[0][p1];
+		double vertSpanY = points[1][p0]-points[1][p1];
+		double vertSpanZ = points[2][p0]-points[2][p1];
+		return Math.sqrt(vertSpanX*vertSpanX + vertSpanY*vertSpanY + vertSpanZ*vertSpanZ);
+	}
+	void makePoly(int whichPoly, int p0, int p1, int p2){
+		triangles[0][whichPoly]=p0;
+		triangles[1][whichPoly]=p1;
+		triangles[2][whichPoly]=p2;
+		polys[whichPoly].npoints=0;
+		polys[whichPoly].addPoint((int)(points[0][p0]+0.5), (int)(points[1][p0]+0.5));
+		polys[whichPoly].addPoint((int)(points[0][p1]+0.5), (int)(points[1][p1]+0.5));
+		polys[whichPoly].addPoint((int)(points[0][p2]+0.5), (int)(points[1][p2]+0.5));
+		polys[whichPoly].npoints=3;
+	}
+	boolean isCorner(int poly, int corner){
+		for (int i=0; i<3; i++)
+			if (triangles[i][poly]== corner)
+				return true;
+		return false;		
+	}
+	boolean shareEdge(int poly1, int poly2){
+		int count = 0;
+		for (int i=0; i<3; i++)
+			if (isCorner(poly2, triangles[i][poly1]))
+				count++;
+		return count==2;		
+	}
+	boolean sharePoint(int poly1, int poly2){
+		for (int i=0; i<3; i++)
+			if (isCorner(poly2, triangles[i][poly1]))
+				return true;
+		return false;		
+	}
+	int cornerTouching(int poly1, int poly2){ //returns the first corner touching found
+		for (int i=0; i<3; i++)
+			if (isCorner(poly2, triangles[i][poly1]))
+				return triangles[i][poly1];
+		return -1;		
+	}
+	int cornerNotTouching(int poly1, int poly2){ //returns the first corner touching found
+		for (int i=0; i<3; i++)
+			if (!isCorner(poly2, triangles[i][poly1]))
+				return triangles[i][poly1];
+		return -1;		
+	}
+	boolean inFront(int poly1, int poly2){
+		if (shareEdge(poly1, poly2)) {
+			//1 is in front if third point (which they are *not* sharing) of 1 is in front of that of 2
+			int poly1Off = cornerNotTouching(poly1, poly2);
+			int poly2Off = cornerNotTouching(poly2, poly1);
+			boolean q= points[2][poly1Off]<points[2][poly2Off];
+			return q;
+		}
+		else if (sharePoint(poly1, poly2)) {
+			//1 is in front if closest point belonging to 1 of the two they don't share is behind that of 2;
+			int polyTouch = cornerTouching(poly1, poly2);
+			double closeness1 = MesquiteDouble.unassigned;
+			for (int i=0; i<3; i++)
+				if (triangles[i][poly1]!=polyTouch)
+					if (MesquiteDouble.lessThan(points[2][triangles[i][poly1]], closeness1, 0)) {
+						closeness1 = points[2][triangles[i][poly1]];
+					}
+			double closeness2 = MesquiteDouble.unassigned;
+			for (int i=0; i<3; i++)
+				if (triangles[i][poly2]!=polyTouch)
+					if (MesquiteDouble.lessThan(points[2][triangles[i][poly2]], closeness2, 0)) {
+						closeness2 = points[2][triangles[i][poly2]];
+					}
+			boolean q =closeness1<closeness2;
+			return q;
+		}
+		else {
+			//test which has closest point
+			double closeness1 = MesquiteDouble.unassigned;
+			for (int i=0; i<3; i++)
+				if (MesquiteDouble.lessThan(points[2][triangles[i][poly1]], closeness1, 0)) {
+					closeness1 = points[2][triangles[i][poly1]];
+				}
+			double closeness2 = MesquiteDouble.unassigned;
+			for (int i=0; i<3; i++)
+				if (MesquiteDouble.lessThan(points[2][triangles[i][poly2]], closeness2, 0)) {
+					closeness2 = points[2][triangles[i][poly2]];
+				}
+			boolean q =closeness1<closeness2;
+			return q;
+		}
+	}
+	/*--------------------------------*/
+	void sortPolys(){
+		for (int i =0; i<8; i++)
+			polyOrder[i] = i;
+		for (int i=1; i<8; i++) {
+			for (int j= i-1; j>=0  &&  inFront(polyOrder[j],polyOrder[j+1]); j--) {
+				int temp = polyOrder[j];
+				polyOrder[j] = polyOrder[j+1];
+				polyOrder[j+1]=temp;
+			}
+		}
+	}
+	/*--------------------------------*/
+	void setRotatorPoints(double[][] XrYr, int centerIndex, int firstIndex){
+		try {
+			for (int i=0; i<3; i++){
+			points[i][0] = XrYr[i][centerIndex];
+			for (int j =1; j<7; j++)
+				points[i][j] = XrYr[i][firstIndex +j-1];
+		}
+
+		double span = MesquiteDouble.maximum(MesquiteDouble.maximum(distance(1,2), distance(3,6)), distance(5 ,4));
+		double scaling = 1.0;
+		if (span!=0)
+			scaling = MesquiteDouble.minimum(legendHeight,legendWidth)*0.8/span;
+		for (int i=0; i<3; i++){
+			for (int j =0; j<7; j++)
+				points[i][j] = (points[i][j] - XrYr[i][centerIndex])*scaling + centerPoint[i];
+		}
+		makePoly(0, 1, 3, 4);
+		makePoly(1, 1, 4, 6);
+		makePoly(2, 1, 6, 5);
+		makePoly(3, 1, 5, 3);
+		makePoly(4, 2, 3, 4);
+		makePoly(5, 2, 4, 6);
+		makePoly(6, 2, 6, 5);
+		makePoly(7, 2, 5, 3);
+		sortPolys();
+		repaint();
+		}
+		catch(Exception e){
+			MesquiteMessage.warnUser("Oops, setRotatorPoints in NodeLocs3DPlot with exception " + e);
+		}
+
+	}	
+	void doPoly(Graphics g,  int index){
+		if (index<4)
+			g.setColor(Color.lightGray);
+		else
+			g.setColor(Color.darkGray);
+		g.fillPolygon(polys[index]);
+		g.setColor(Color.black);
+		g.drawPolygon(polys[index]);
+	}
+	void fillHandle(Graphics g, double[][] p, int index, Color c, boolean onTop){
+		if (points[2][index]>=points[2][0] && onTop)
+			return;
+		double s = 4;
+		if (c!=null) g.setColor(c);
+		g.fillOval((int)(points[0][index] - s+0.5), (int)(points[1][index] - s+0.5), (int)(s*2), (int)(s*2));
+		g.setColor(Color.black);
+		g.drawOval((int)(points[0][index] - s+0.5), (int)(points[1][index] - s+0.5), (int)(s*2), (int)(s*2));  
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Color c = g.getColor();
+		g.setColor(Color.blue);
+		g.drawRect(0,0, legendWidth-1, legendHeight-1);
+		if (doWarn)
+			text.setText("3D plot MISSING VALUES\nX:  " + ownerModule.xString +"\nY:  " + ownerModule.yString + "\nZ:  " + ownerModule.zString);
+		else	
+			text.setText("3D plot\nX:  " + ownerModule.xString +"\nY:  " + ownerModule.yString + "\nZ:  " + ownerModule.zString);
+
+		g.setColor(Color.green);
+		g.drawString("Rotation", 30, legendHeight-57);
+		g.setColor(Color.red);
+		g.drawString("Magnification", 20, legendHeight-22);
+		if (c!=null) g.setColor(c);
+		super.paint(g);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+
+}
+
+
+
+
diff --git a/Source/mesquite/rhetenor/PlotTree3D/PlotTree3D.java b/Source/mesquite/rhetenor/PlotTree3D/PlotTree3D.java
new file mode 100644
index 0000000..027c62f
--- /dev/null
+++ b/Source/mesquite/rhetenor/PlotTree3D/PlotTree3D.java
@@ -0,0 +1,519 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.PlotTree3D;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class PlotTree3D extends AnalyticalDrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsPlot3D.class, getName() + "  needs a method to calculate positions of nodes.",
+		"The method to calculate positions is arranged initially");
+	}
+
+	NodeLocsPlot3D nodeLocsTask;
+	Vector drawings;
+	int spotSize = 16;
+	public MesquiteBoolean showInternals, showFog, showTree, showTerminals;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsPlot3D)hireEmployee(NodeLocsPlot3D.class, "Method to choose node locations");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node location plotter module was obtained.");
+		drawings = new Vector();
+ 		addMenuItem( "Spot Size...", makeCommand("setSpotDiameter",  this));
+		showInternals = new MesquiteBoolean(true);
+		showTerminals = new MesquiteBoolean(true);
+		showTree = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Terminal Nodes", makeCommand("toggleShowTerminals",  this), showTerminals);
+		addCheckMenuItem(null, "Show Internal Nodes", makeCommand("toggleShowInternals",  this), showInternals);
+		addCheckMenuItem(null, "Show Branches", makeCommand("toggleShowTree",  this), showTree);
+		showFog = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Use Fog", makeCommand("toggleFog",  this), showFog);
+ 		return true;
+ 	 }
+  	 
+ 	public void employeeQuit(MesquiteModule m){
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		PlotTreeDrawing treeDrawing =  new PlotTreeDrawing (treeDisplay, numTaxa, this, spotSize);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+  
+	/** Returns true if other modules can control the orientation */
+	public boolean allowsReorientation(){
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setNodeLocs " , nodeLocsTask);
+  	 	temp.addLine("setSpotDiameter " + spotSize);
+  	 	temp.addLine("toggleShowTerminals " + showTerminals.toOffOnString());
+  	 	temp.addLine("toggleShowInternals " + showInternals.toOffOnString());
+   	 	temp.addLine("toggleShowTree " + showTree.toOffOnString());
+  	 	temp.addLine("toggleFog " + showFog.toOffOnString());
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets diameter of spots at nodes", "[diameter]", commandName, "setSpotDiameter")) {
+			int newDiameter = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newDiameter))
+				newDiameter = MesquiteInteger.queryInteger(containerOfModule(), "Set spot diameter", "Spot Diameter:", spotSize, 6, 100);
+    	 			
+    	 		if (newDiameter>6 && newDiameter<100 && newDiameter!=spotSize) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+		    	 			spotSize = newDiameter;
+		    	 			treeDrawing.spotsize=newDiameter;
+		    	 			treeDrawing.treeDisplay.setMinimumTaxonNameDistance(treeDrawing.spotsize/2, 4);
+		    	 			parametersChanged();
+	    	 		}
+    	 		}
+    	 		
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not internal nodes are shown", "[on = show;  off]", commandName, "toggleShowInternals")) {
+    	 		showInternals.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+   	 	else if (checker.compare(this.getClass(), "Sets whether or not terminal nodes are shown", "[on = show;  off]", commandName, "toggleShowTerminals")) {
+    	 		showTerminals.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not the tree is shown", "[on = show;  off]", commandName, "toggleShowTree")) {
+    	 		showTree.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether or not to show distant nodes as if in fog", "[on = show;  off]", commandName, "toggleFog")) {
+    	 		showFog.toggleValue(parser.getFirstToken(arguments));
+	 		 parametersChanged();
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+				treeDrawing.treeDisplay.repaint();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module that calculates the node locations", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsPlot3D temp= (NodeLocsPlot3D)replaceEmployee(NodeLocsPlot3D.class, arguments, "Method choose node locations", nodeLocsTask);
+    	 		if (temp!=null) {
+    	 		 	nodeLocsTask=temp;
+    	 		 	parametersChanged();
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					PlotTreeDrawing treeDrawing = (PlotTreeDrawing)obj;
+					treeDrawing.treeDisplay.repaint();
+	    	 		}
+    	 		 }
+	    	 	return temp;
+ 		}
+    	 	else {
+ 			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Plot Tree 3D";
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Draws trees plotted in a three dimensional space." ;
+   	 }
+	/*.................................................................................................................*/
+   	public boolean isSubstantive(){
+   		return true;
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+}
+
+/* ======================================================================== */
+class PlotTreeDrawing extends TreeDrawing  {
+
+	public PlotTree3D ownerModule;
+	public int edgewidth = 4;
+	public int spotsize = 24;
+	int oldNumTaxa = 0;
+ 	public static final int inset=1;
+	private boolean ready=false;
+	private int foundBranch;
+	double[] zScores;
+	int[] nodes;
+	private NameReference colorNameRef;
+	public PlotTreeDrawing (TreeDisplay treeDisplay, int numTaxa, PlotTree3D ownerModule, int spotSize) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		this.spotsize = spotSize;
+		colorNameRef = NameReference.getNameReference("Color");
+	    	treeDisplay.setMinimumTaxonNameDistance(spotsize/2, 4);
+		treeDisplay.setOrientation(TreeDisplay.FREEFORM);
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		ready = true;
+	}
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[tree.motherOfNode(node)];
+		lineBaseX[node]=x[tree.motherOfNode(node)];
+	}
+	
+	double minimumZ, maximumZ;
+	private Color applyFog(Color c, int node){
+		if (!ownerModule.showFog.getValue())
+			return c;
+		double fog = 0;
+		double beyondMax = maximumZ*1.1;
+		if (MesquiteDouble.isCombinable(z[node]) && (beyondMax-minimumZ)!=0)
+			fog = (beyondMax - z[node])/(beyondMax-minimumZ);
+		if (fog==0)
+			return c;
+		else
+			return ColorDistribution.brighter(c, fog);
+	}
+	private int getSpotSize(int node){
+		if (MesquiteDouble.isCombinable(z[node]) && z[node]>0 && (maximumZ-minimumZ)!=0) {
+			int s = spotsize - (int)(spotsize*((z[node]-minimumZ)/(maximumZ-minimumZ) - 0.5));
+			return s;
+		}
+		else
+			return spotsize;
+	}
+	private void survey(Tree tree, int node, double[] zScores, int[] nodes, MesquiteInteger count){
+		if (MesquiteDouble.isCombinable(z[node]) && z[node]>=0) {
+			minimumZ = MesquiteDouble.minimum(minimumZ, z[node]);
+			maximumZ = MesquiteDouble.maximum(maximumZ, z[node]);
+			zScores[count.getValue()] = z[node];
+			nodes[count.getValue()] = node;
+			count.increment();
+			
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			survey(tree, d, zScores, nodes, count);
+	}
+	
+	/*_________________________________________________*/
+	/** Draw highlight for branch node */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			Color tC = g.getColor();
+			if (flip)
+				g.setColor(Color.red);
+			else
+				g.setColor(Color.blue);
+			int s = getSpotSize(node);
+			for (int i=1; i<4; i++)
+				g.drawOval( x[node]- s/2 - 2 - i, y[node]- s/2 - 2 - i, s + 3 + i + i, s + 3 + i + i);
+
+			g.setColor(tC);
+		}
+	}
+	/*_________________________________________________*/
+	private   void drawLine(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(applyFog(treeDisplay.getBranchColor(node), node));
+				
+			if (node == tree.getRoot()) {
+			}
+			else if (tree.motherOfNode(node) == tree.getRoot() && !tree.getRooted() && !tree.nodeIsPolytomous( tree.getRoot() )) {
+				int sisterNode = 0;
+				if (tree.nodeExists(tree.nextSisterOfNode(node)))
+					sisterNode = tree.nextSisterOfNode(node);
+				else if (tree.nodeExists(tree.previousSisterOfNode(node)))
+					sisterNode = tree.previousSisterOfNode(node);
+				if (sisterNode !=0) {
+					if (MesquiteInteger.isCombinable(lineTipX[node]) && MesquiteInteger.isCombinable(lineTipY[node]) && MesquiteInteger.isCombinable(lineTipX[sisterNode]) && MesquiteInteger.isCombinable(lineTipY[sisterNode])) {
+						g.drawLine(lineTipX[node]+1, lineTipY[node], lineTipX[sisterNode]+1, lineTipY[sisterNode]);
+						g.drawLine(lineTipX[node], lineTipY[node], lineTipX[sisterNode], lineTipY[sisterNode]);
+						g.drawLine(lineTipX[node], lineTipY[node]+1, lineTipX[sisterNode], lineTipY[sisterNode]+1);
+						g.drawLine(lineTipX[node]+1, lineTipY[node]+1, lineTipX[sisterNode]+1, lineTipY[sisterNode]+1);
+					}
+				}
+			}
+			else  if (MesquiteInteger.isCombinable(lineTipX[node]) && MesquiteInteger.isCombinable(lineBaseX[node]) && MesquiteInteger.isCombinable(lineTipY[node]) && MesquiteInteger.isCombinable(lineBaseY[node])) {
+				g.drawLine(lineTipX[node]+1, lineTipY[node], lineBaseX[node]+1, lineBaseY[node]);
+				g.drawLine(lineTipX[node], lineTipY[node], lineBaseX[node], lineBaseY[node]);
+				g.drawLine(lineTipX[node], lineTipY[node]+1, lineBaseX[node], lineBaseY[node]+1);
+				g.drawLine(lineTipX[node]+1, lineTipY[node]+1, lineBaseX[node]+1, lineBaseY[node]+1);
+			}
+			
+		}
+	}
+	/*_________________________________________________*/
+	private boolean getDrawNode(Tree tree, int node) {
+		return (tree.nodeIsTerminal(node) && ownerModule.showTerminals.getValue())|| (!tree.nodeIsTerminal(node) && ownerModule.showInternals.getValue());
+	}
+	/*_________________________________________________*/
+	private   void drawSpots(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(applyFog(treeDisplay.getBranchColor(node), node));
+				
+			if (getDrawNode(tree,node)){
+				if (node == tree.getRoot()) {
+					if (tree.getRooted()) {
+						drawSpot( g, node);
+						highlightSpot( g, node);
+					}
+				}
+				else  {
+					drawSpot( g, node);
+				}
+			}
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawSpots( tree, g, thisSister);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+		}
+	}
+	private int bumpUp(int i){
+		return i + (255-i)/4;
+	}
+int count = 0;
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+	        if (MesquiteTree.OK(tree) && !ownerModule.isDoomed()) {
+	        	if (tree.getNumNodeSpaces()!=numNodes)
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	if (!tree.nodeExists(getDrawnRoot()))
+	        		setDrawnRoot(tree.getRoot());
+			ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, getDrawnRoot(),  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+	        if (MesquiteTree.OK(tree)) {
+	        	if (tree.getNumNodeSpaces()!=numNodes) {
+	        		resetNumNodes(tree.getNumNodeSpaces());
+	        	}
+	        	if (zScores == null || zScores.length !=tree.getNumNodeSpaces()){
+	        		zScores = new double[tree.getNumNodeSpaces()];
+	        		nodes = new int[tree.getNumNodeSpaces()];
+	        	}
+	        	DoubleArray.deassignArray(zScores);
+	        	IntegerArray.deassignArray(nodes);
+	        	g.setColor(treeDisplay.branchColor);
+			//ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+			minimumZ = MesquiteDouble.unassigned;
+			maximumZ = MesquiteDouble.unassigned;
+			MesquiteInteger count = new MesquiteInteger(0);
+			survey(tree, drawnRoot, zScores, nodes, count);
+			
+			for (int i=1; i<zScores.length; i++) {
+				for (int j= i-1; j>=0  &&  zScores[j]<zScores[j+1]; j--) {
+					if (MesquiteDouble.isCombinable(zScores[j]) && MesquiteDouble.isCombinable(zScores[j+1])){
+						double temp = zScores[j];
+						zScores[j] = zScores[j+1];
+						zScores[j+1]=temp;
+						int tempN = nodes[j];
+						nodes[j] = nodes[j+1];
+						nodes[j+1]=tempN;
+					}
+				}
+			}
+			calculateLines(tree, drawnRoot);
+	       	 	//drawSpots(tree, g, drawnRoot);  
+
+			for (int i=0; i<nodes.length; i++) {
+				if (tree.nodeExists(nodes[i])) {
+					g.setColor(applyFog(treeDisplay.branchColor, nodes[i]));
+					if (ownerModule.showTree.getValue())
+						drawLine(tree, g, nodes[i]);
+					if (getDrawNode(tree,nodes[i])){
+						if (nodes[i] == tree.getRoot()) {
+							if (tree.getRooted()) {
+								drawSpot( g, nodes[i]);
+								highlightSpot( g, nodes[i]);
+							}
+						}
+						else  {
+							drawSpot( g, nodes[i]);
+						}
+					}
+				}
+			}
+
+	       	 }
+	   }
+	
+	/*_________________________________________________*/
+	private boolean inSpot(int node, int h, int v){
+		int s = getSpotSize(node);
+		if ((h-x[node])*(h-x[node]) + (v-y[node])*(v-y[node]) < s*s/4) //use radius
+			return true;
+		else
+			return false;
+		// ask if x, y is in node's spot    g.fillOval( x[node]- spotsize/2, y[node]- spotsize/2, spotsize, spotsize);
+	}
+	/*_________________________________________________*/
+	private void drawSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			Color c = g.getColor();
+			int s = getSpotSize(node);
+			g.setColor(Color.white);
+			g.drawOval( x[node]- s/2-1, y[node]- s/2-1, s+2, s+2);
+			if (c!=null) g.setColor(c);
+			g.fillOval( x[node]- s/2, y[node]- s/2, s, s);
+		}
+	}
+	/*_________________________________________________*/
+	private void highlightSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			int s = getSpotSize(node);
+			for (int diam = s + 12; diam> s + 8; diam --)
+				g.drawOval( x[node]- (int)((double)diam/2 + 0.5), y[node]- (int)((double)diam/2 + 0.5), diam, diam);
+		}
+	}
+	/*_________________________________________________*/
+	private void fillSpot(Graphics g, int node){
+		if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+			int s = getSpotSize(node);
+			g.fillOval( x[node]- s/2 + 2, y[node]- s/2 + 2, s - 4, s - 4);
+		}
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && (getDrawNode(tree,node))) {
+			if (MesquiteInteger.isCombinable(x[node]) && MesquiteInteger.isCombinable(y[node])) {
+				Color c = g.getColor();
+				int numColors = colors.getNumColors();
+				if (numColors==1){
+					g.setColor(applyFog(colors.getColor(0, !tree.anySelected()|| tree.getSelected(node)), node));
+					fillSpot(g,node);
+				}
+				else if (numColors>0) {
+					int startAngle=90;
+					double totalFreq=0;
+					for (int i=0; i<numColors; i++) totalFreq += colors.getWeight(i);
+					
+					int arcAngle = 360/(numColors);
+					int s = getSpotSize(node);
+					for (int i=0; i<numColors; i++) {
+						Color color;
+						if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+							g.setColor(applyFog(color, node));
+						
+						arcAngle = (int)((colors.getWeight(i)/totalFreq)*360);
+						g.fillArc( x[node]- s/2 + 2, y[node]- s/2 + 2, s - 4, s - 4, startAngle, arcAngle);
+						startAngle+=arcAngle;
+					}
+				}
+				if (c!=null) g.setColor(c);
+			}
+		}
+	}
+
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || node != tree.getRoot()) && (getDrawNode(tree,node))) {
+			fillSpot(g,node);
+		}
+	}
+	   
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y)
+	{
+		if (foundBranch==0) {
+			if ( inSpot(node, x, y))
+				foundBranch = node;
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				ScanBranches(tree, thisSister, x, y);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+	        if (MesquiteTree.OK(tree) && ready) {
+	        	foundBranch=0;
+	       		 ScanBranches(tree, drawnRoot, x, y);
+	       		 return foundBranch;
+	       	}
+	       	return 0;
+	}
+	
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+	}
+/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+/*End new code Feb.22.07 oliver*/
+}
+	
+
+
diff --git a/Source/mesquite/rhetenor/PrincipalComponents/PrincipalComponents.java b/Source/mesquite/rhetenor/PrincipalComponents/PrincipalComponents.java
new file mode 100644
index 0000000..487da75
--- /dev/null
+++ b/Source/mesquite/rhetenor/PrincipalComponents/PrincipalComponents.java
@@ -0,0 +1,67 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.PrincipalComponents;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+
+public class PrincipalComponents extends Ordinator {
+	PCAOrdination ord;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+ 	}
+ 	
+	/*.................................................................................................................*/
+ 	public Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa){
+		double[][] x = matrix.getMatrix(item);//gets first 2Dmatrix from original
+ 		ord=  new PCAOrdination(x);
+		return ord;
+ 	}
+	/*.................................................................................................................*/
+    	public String getName() {
+		return "Principal Components Analysis";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs principal components analysis on a continous-valued matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*
+    	 public String getParameters() {
+   		if (ord==null)
+   			return null;
+   		else
+   			return "Principal Components Analysis\n"+ ord.report();
+   	 }
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/rhetenor/ShowCharLoadings/ShowCharLoadings.java b/Source/mesquite/rhetenor/ShowCharLoadings/ShowCharLoadings.java
new file mode 100644
index 0000000..0e90a4b
--- /dev/null
+++ b/Source/mesquite/rhetenor/ShowCharLoadings/ShowCharLoadings.java
@@ -0,0 +1,181 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.rhetenor.ShowCharLoadings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class ShowCharLoadings extends OrdinationAssistant {
+	public String getName() {
+		return "Display Character Loadings";
+	}
+	public String getExplanation() {
+		return "Shows character loadings in ordination." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ItemsCharter.class, getName() + "  needs a module to draw the chart.",
+		"The module to draw the chart is arranged automatically");
+		EmployeeNeed e2 = registerEmployeeNeed(CharacterLoadings.class, getName() + "  needs a source of character loadings.",
+		"The source of character loadings is arranged initially");
+		EmployeeNeed e3 = registerEmployeeNeed(CharsFromMatrixSource.class, getName() + "  needs a module to extract characters from a matrix.",
+		"The module to extract characters froma matrix is arranged initially");
+	}
+	/*.................................................................................................................*/
+	ChartWindow cWindow;
+	ItemsCharter chartWindowTask;
+	CharacterLoadings loadingsTask;
+	CharsFromMatrixSource charSourceConverter;
+	MiniScroll axisScroll;
+	boolean firstTime = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("Loadings");
+		chartWindowTask = (ItemsCharter)hireEmployee(ItemsCharter.class, null);
+		if (chartWindowTask == null) {
+			return sorry(getName() + " couldn't start because no charting module obtained.");
+		}
+		cWindow = chartWindowTask.makeChartWindow(this);
+		cWindow.doCommand("valuesByItems", null, CommandChecker.defaultChecker);
+
+		setModuleWindow( cWindow);
+
+		//needs to be same set of characters!!!!
+		loadingsTask =  (CharacterLoadings)hireNamedEmployee(CharacterLoadings.class, StringUtil.tokenize("Character Loadings"));
+		if (loadingsTask==null) {
+			return sorry(getName() + " couldn't start because no character loadings module obtained.");
+		}
+		charSourceConverter = (CharsFromMatrixSource)hireNamedEmployee(CharsFromMatrixSource.class, StringUtil.tokenize("Characters from Matrix Source"));
+		if (charSourceConverter==null) {
+			return sorry(getName() + " couldn't start because no character source module obtained.");
+		}
+		addMenuItem(null, "Next Axis", makeCommand("nextAxis",  this));
+		addMenuItem(null, "Previous Axis", makeCommand("prevAxis",  this));
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public boolean canHireMoreThanOnce(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setOrdination(Ordination ordination, Taxa taxa, MatrixSourceCoord matrixSourceTask){
+		if (ordination!=null) {
+			chartWindowTask.setTaxa(taxa);
+			charSourceConverter.setMatrixSource(matrixSourceTask);
+			chartWindowTask.setItemsSource(charSourceConverter);
+
+			loadingsTask.setOrdination(ordination, taxa);
+			int curr = loadingsTask.getCurrentAxis();
+			if (curr <0 || curr >= loadingsTask.getNumberOfAxes())
+				loadingsTask.setCurrentAxis(0);
+			chartWindowTask.setNumberTask(loadingsTask);
+			if (firstTime){
+				cWindow.setScroller(axisScroll = new MiniScroll(makeCommand("setAxis",  this), true, true, 1, 1, loadingsTask.getNumberOfAxes(),"axis"));
+				cWindow.setChartTitle("Character Loadings");
+				cWindow.resetTitle();
+				if (!MesquiteThread.isScripting()) {
+					cWindow.setChartVisible();
+					if (!cWindow.isVisible())
+						cWindow.setVisible(true);
+				}
+				firstTime = false;
+			}
+			else {
+				if (axisScroll != null && loadingsTask != null){
+					axisScroll.setMaximumValue(loadingsTask.getNumberOfAxes());
+				}
+			}
+			chartWindowTask.doCounts();
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharter", chartWindowTask); 
+		temp.addLine("setChartVisible"); 
+		temp.addLine("doCounts"); 
+		temp.addLine("showWindow"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Goes to next axis from ordination", null, commandName, "nextAxis")) {
+			int curr = loadingsTask.getCurrentAxis();
+			int max = loadingsTask.getNumberOfAxes();
+			if (curr+1<max) {
+				loadingsTask.setCurrentAxis(curr+1);
+				chartWindowTask.doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous axis from ordination", null, commandName, "prevAxis")) {
+			int curr = loadingsTask.getCurrentAxis();
+			if (curr>0) {
+				loadingsTask.setCurrentAxis(curr-1);
+				chartWindowTask.doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets which axis from ordination is shown", "[axis number]", commandName, "setAxis")) {
+			int i = MesquiteInteger.fromFirstToken(arguments, pos) -1;
+			int max = loadingsTask.getNumberOfAxes();
+			if (MesquiteInteger.isCombinable(i) && i<max) {
+				loadingsTask.setCurrentAxis(i);
+				chartWindowTask.doCounts();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns chart drawing module", null, commandName, "getCharter")) {
+			return chartWindowTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the chart to visible", null, commandName, "setChartVisible")) {
+			if (cWindow!=null)
+				cWindow.setChartVisible();
+		}
+		else if (checker.compare(this.getClass(), "Requests counts of chart", null, commandName, "doCounts")) {
+			if (chartWindowTask!=null)
+				chartWindowTask.doCounts();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+
+}
+
+
diff --git a/Source/mesquite/rhetenor/aPCA/aPCA.java b/Source/mesquite/rhetenor/aPCA/aPCA.java
new file mode 100644
index 0000000..7d6907e
--- /dev/null
+++ b/Source/mesquite/rhetenor/aPCA/aPCA.java
@@ -0,0 +1,77 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.aPCA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class aPCA extends Ordinator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaPartitionSource.class, getName() + "  needs a source for a taxon partition.",
+		"The source of taxon partition is selected initially");
+	}
+	/*.................................................................................................................*/
+	aPCAOrdination ord;
+	boolean first = true;
+	
+	TaxaPartitionSource partitionSource;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		partitionSource = (TaxaPartitionSource)hireEmployee(TaxaPartitionSource.class, "Source of Taxa Partitions");
+ 		if (partitionSource == null)
+ 			return sorry(getName() + " couldn't start because no source of taxa partition obtained.");
+ 		return true;
+ 	}
+ 	
+	/*.................................................................................................................*/
+ 	public Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa){
+		TaxaPartition part = partitionSource.getPartition(taxa);
+		if (part== null) {
+			if (first)
+				discreetAlert( "Sorry, aPCA cannot be performed because there is no available partition of the taxa");
+			first = false;
+			iQuit();
+			return null;
+		}
+		double[][] x = matrix.getMatrix(item);//gets first 2Dmatrix from original
+ 		ord=  new aPCAOrdination(x, part);
+		return ord;
+ 	}
+	/*.................................................................................................................*/
+    	public String getName() {
+		return "Among-group PCA"; //ERIC: this is the name that appears in menus
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs among-group principal components analysis on a continous-valued matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+}
+
+
diff --git a/Source/mesquite/rhetenor/aRhetenorIntro/aRhetenorIntro.java b/Source/mesquite/rhetenor/aRhetenorIntro/aRhetenorIntro.java
new file mode 100644
index 0000000..432673b
--- /dev/null
+++ b/Source/mesquite/rhetenor/aRhetenorIntro/aRhetenorIntro.java
@@ -0,0 +1,71 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.aRhetenorIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aRhetenorIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aRhetenorIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Multivariate analyses and morphometrics.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Rhetenor Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Rhetenor Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Dyreson, E. & W.P. Maddison. 2006.  Rhetenor package for morphometrics, version 1.11.";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "1.11";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "E. Dyreson and W. Maddison";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+}
+
diff --git a/Source/mesquite/rhetenor/aRhetenorIntro/index.html b/Source/mesquite/rhetenor/aRhetenorIntro/index.html
new file mode 100644
index 0000000..c9e96ae
--- /dev/null
+++ b/Source/mesquite/rhetenor/aRhetenorIntro/index.html
@@ -0,0 +1,67 @@
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 4">
+		<title>Rhetenor</title>
+	</head>
+
+	<body bgcolor="#afeeee">
+		<h2>
+		<table border="4" cellpadding="0" cellspacing="2">
+			<tr>
+				<td><img height="64" width="164" src="splash.gif"></td>
+				<td bgcolor="blue">
+					<h2><font color="#fffafa">Rhetenor</font><font color="lime">: a package of morphometrics modules for the Mesquite system</font></h2>
+				</td>
+			</tr>
+		</table>
+		</h2>
+		<h4>Eric Dyreson & Wayne Maddison</h4>
+		
+<p>contact: e_dyreson at umwestern.edu</p>
+		
+<p>August 2005</p>
+		<p>This package of modules and library classes demonstrates the use of the
+	  Mesquite system to do morphometrics calculations. </p>
+		<ul>
+			<li><a href="#overview">Overview</a>
+			<li><a href="#installation">Installation</a>
+			<li><a href="#examples">Examples</a>
+			<li><a href="#acknowledgments">Acknowledgments</a>
+		</ul>
+		<h3><a name="overview"></a>Overview</h3>
+		<p>The Rhetenor package of morphometrics modules includes:</p>
+		<ul>
+			<li>Ordinations, including
+			<ul>
+				<li>Principal Components Analysis
+				<li>Canonical Variates Analysis
+				<li>Evolutionary Principal Components Analysis
+			</ul>
+			<li>Landmark reconstructions
+			<li>Plotting a tree in a 3 dimensional space
+		</ul>
+		<p>In conjuction with the standard modules in Mesquite, including Plot Tree, the charting modules, and character evolution simulations, these calculations can be used to do standard morphometric analyses, or morphometrics in a phylogenetic context.</p>
+		<p>By the way, "Evolutionary Principal Components Analysis" is a new method by W. Maddison & E. Dyreson that does PCA on reconstructed changes along branches of a tree. This results in a rotation whose first axis maximizes evolutionary change along the branches, and avoids problems of non-independence of species in a cross-species PCA. Because of the reliance on a reconstruction, it has some statistical problems as compared to related methods like Garland's ordinations on [...]
+		<h3><a name="installation"></a>Installation</h3>
+		<p>To install Rhetenor, the "rhetenor" directory must be installed in the "mesquite" directory within "Mesquite_Folder".</p>
+		<h3><a name="examples"></a>Examples</h3>
+		
+<p>There is a series of example data files in the directory "Multivariate_Continuous". 
+  The files are self explanatory; begin with the file whose name begins with "00".</p>
+		<h3><a name="acknowledgments"></a>Acknowledgments</h3>
+		<p>Rhetenor currently makes use of JAMA (<a href="http://math.nist.gov/javanumerics/jama/">http://math.nist.gov/javanumerics/jama/</a>) for some of its matrix manipulations.</p>
+		<p>
+		<hr>
+		</p>
+		<p><u>About the name Rhetenor</u>: Rhetenor was an incidental character in Ovid's Metamorphosis, but more importantly "rhetenor" is the specific epithet for a member of the butterfly genus Morpho (<b>morpho</b>metrics...). Coincidentally, it is also the generic name of a little-known neotropical jumping spider.</p>
+		<p>
+		<hr>
+		</p>
+		
+<p>© Eric Dyreson and Wayne Maddison, 2002-2005
+</body>
+
+</html>
+
diff --git a/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif b/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif
new file mode 100644
index 0000000..f23628d
Binary files /dev/null and b/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif differ
diff --git a/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif copy b/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif copy
new file mode 100644
index 0000000..5afb273
Binary files /dev/null and b/Source/mesquite/rhetenor/aRhetenorIntro/splash.gif copy differ
diff --git a/Source/mesquite/rhetenor/aRhetenorIntro/splashSmall.gif b/Source/mesquite/rhetenor/aRhetenorIntro/splashSmall.gif
new file mode 100644
index 0000000..da74035
Binary files /dev/null and b/Source/mesquite/rhetenor/aRhetenorIntro/splashSmall.gif differ
diff --git a/Source/mesquite/rhetenor/explanation.txt b/Source/mesquite/rhetenor/explanation.txt
new file mode 100644
index 0000000..5c75511
--- /dev/null
+++ b/Source/mesquite/rhetenor/explanation.txt
@@ -0,0 +1,2 @@
+Rhetenor Package for Morphometrics
+Performs some basic multivariate analyses such as ordinations (Principal Components Analysis and others), as well as some geometric morphometrics (reconstructing of ancestral form from landmark data).  Also plots a tree in a 3 dimensional character space.
diff --git a/Source/mesquite/rhetenor/lib/CVAOrdination.java b/Source/mesquite/rhetenor/lib/CVAOrdination.java
new file mode 100644
index 0000000..c4b56c7
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/CVAOrdination.java
@@ -0,0 +1,39 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+  /*==================================================*/
+	public class CVAOrdination extends Ordination{
+		public CVAOrdination(double[][] original, TaxaPartition partition){
+			Ordination wpcaResults	=   new wPCAOrdination(original,partition); 
+			double[][] rotated 	=  	wpcaResults.getScores();  
+			double[][] rescaled = 	MatrixUtil.rescalesqrt(rotated, wpcaResults.getEigenvalues() ); 
+			Ordination apcaResults =  new aPCAOrdination(rescaled,partition);
+			setResults(apcaResults);
+		}
+	 	public String getAxisName(int i){
+	 		if (percentExplained==null || i>=percentExplained.length || i<0)
+	 			return "Error in Canonical Variates";
+	 		else
+	 			return "CVA" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100*percentExplained[i], 3) +"%)";
+	 	}
+  	}
+
diff --git a/Source/mesquite/rhetenor/lib/CharacterLoadings.java b/Source/mesquite/rhetenor/lib/CharacterLoadings.java
new file mode 100644
index 0000000..822079e
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/CharacterLoadings.java
@@ -0,0 +1,42 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class CharacterLoadings extends NumberForCharacter implements NumForCharTreeIndep  {
+
+	public Class getDutyClass(){
+		return CharacterLoadings.class;
+	}
+ 	public String getDutyName() {
+ 		return "Character Loadings";
+   	 }
+ 	public abstract void setOrdination(Ordination ord, Taxa taxa);
+   	public abstract void setCurrentAxis(int i);
+   	public abstract int getCurrentAxis();
+   	public abstract int getNumberOfAxes();
+}
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/CharsFromMatrixSource.java b/Source/mesquite/rhetenor/lib/CharsFromMatrixSource.java
new file mode 100644
index 0000000..d424244
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/CharsFromMatrixSource.java
@@ -0,0 +1,39 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class CharsFromMatrixSource extends CharacterSource  {
+
+	public Class getDutyClass(){
+		return CharsFromMatrixSource.class;
+	}
+ 	public String getDutyName() {
+ 		return "Characters from Matrix Source";
+   	 }
+ 	public abstract void setMatrixSource(MatrixSourceCoord source);
+}
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/EPCAOrdination.java b/Source/mesquite/rhetenor/lib/EPCAOrdination.java
new file mode 100644
index 0000000..13fd325
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/EPCAOrdination.java
@@ -0,0 +1,92 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+	public class EPCAOrdination extends Ordination   {
+	     	double[] sqLengths, transformedSqLengths;
+		double sumSqLengths, transformedSumSqLengths;
+		public EPCAOrdination (double[][] original, Tree tree, boolean weightByBranchLengths){
+			if (original!=null && tree != null){
+				//First, reconstruct ancestral states for all characters
+				SquaredReconstructor reconstructor = new SquaredReconstructor();
+				reconstructor.reconstruct(tree, original, weightByBranchLengths, true, null);
+				double[][] reconstructed =reconstructor.getReconstructedStates(0);   //todo: uses only first item
+				sqLengths = reconstructor.getSumSquaredLengths();
+				sumSqLengths =0;
+				for (int i=0; i<sqLengths.length; i++)
+					sumSqLengths+= sqLengths[i];
+
+				//Second, construct a new matrix implicitly for a set of taxa, one for each node, assigning change as character states
+				double[][] changeMatrix = new double[original.length][ tree.numberOfNodesInClade(tree.getRoot())-1];  //not including root
+				Double2DArray.zeroArray(changeMatrix);
+				nodeNumber = 0;
+				fillMatrix(tree, tree.getRoot(), changeMatrix, reconstructed);
+				
+				//Third, do PCA on the new matrix of changes.
+		  		doEigenAnalysis(MatrixUtil.covariance(changeMatrix), original);
+								
+				//Fourth, calculate how much of squared change is accounted for by each new axis
+				if (eigenValues!=null){
+					reconstructor.reconstruct(tree, getScores(), weightByBranchLengths, true, null);
+					transformedSqLengths = reconstructor.getSumSquaredLengths();
+					transformedSumSqLengths =0;
+					for (int i=0; i<transformedSqLengths.length; i++)
+						transformedSumSqLengths+= transformedSqLengths[i];
+					percentExplained = MatrixUtil.percentage(transformedSqLengths);
+				}
+			}
+		}
+		/*...............................................................................................................*/
+		/** This method takes the reconstructed matrix, whose elements are numbered as the nodes of the tree
+			(which could have unused elements), and compacts it into a matrix consisting of just as many elements
+			as there are nodes in the tree (excluding the root).*/
+		int nodeNumber;
+		private void fillMatrix(Tree tree, int node, double[][] compacted, double[][] reconstructed ){
+			if (node!=tree.getRoot()) {
+				int mother = tree.motherOfNode(node);
+				for (int ic = 0; ic<reconstructed.length; ic++) {
+					compacted[ic][nodeNumber]= reconstructed[ic][node] - reconstructed[ic][mother];  //item = 0
+				}
+				nodeNumber++;
+			}
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				fillMatrix(tree, daughter, compacted, reconstructed);
+		}
+		/*...............................................................................................................*/
+		public String report(){
+			if (sqLengths==null) return null;
+			String s ="Original square lengths\n" + MatrixUtil.toString(sqLengths) + "\nSum: " + sumSqLengths;
+			if (transformedSqLengths==null)
+				return s+"\n Error: no transformed matrix calculated";
+			s+="\nTransformed square lengths\n" + MatrixUtil.toString(transformedSqLengths) + "\nSum: " + transformedSumSqLengths;
+			return s;
+		}
+		/*.................................................................................................................*/
+	 	public String getAxisName(int i){
+	 		if (sqLengths==null || i>=sqLengths.length || i<0)
+	 			return "EPC" + CharacterStates.toExternal(i) ;  
+	 		else
+	 			return "EPC" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100.0*(percentExplained[i]), 3) +"%)";
+	 	}
+}
+
+
diff --git a/Source/mesquite/rhetenor/lib/MatrixUtil.java b/Source/mesquite/rhetenor/lib/MatrixUtil.java
new file mode 100644
index 0000000..b12b02e
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/MatrixUtil.java
@@ -0,0 +1,1098 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+import Jama.*;  
+
+/* ======================================================================== 
+This library contains a utility class (MatrixUtil) with static methods for manipulating matrices.  
+Some of these methods are very basic (e.g., matrix multiplication) while others are a bit fancier,
+designed to help with the ordination procedures.
+*/
+
+// *********************** MATRIX UTILITIES ********************************* //
+public class MatrixUtil {
+
+// -----------------MatrixUtil  Version 2.01  By Eric Dyreson and Wayne Maddison
+// --- stripExcluded added
+
+
+
+// ..........COMMENTARY, ERROR CHECKING, and OUTPUT STYLE ...............................................................................//
+public static boolean writeMistakes = false;
+public static boolean writeCommentary = false;
+public static boolean writeIntermediates = false;
+//...................
+public static void mistakesWereMade(String c){
+        if (writeMistakes)
+                System.out.println(" .......OOPS!............ " +c);
+}
+//...................
+public static void runningCommentary(String c){
+        if (writeCommentary)
+                System.out.println("....."  +c +"......");
+}
+//...................
+public static void intermediates(String c){
+        if (writeIntermediates)
+                System.out.println(c);
+}
+//...................
+public static String dimensions(double[][] matrix){
+		int numRows   	  = MatrixUtil.numFullRows(matrix);
+		int numColumns  = MatrixUtil.numFullColumns(matrix);
+            return "...."  +Integer.toString(numRows) +"x"  + Integer.toString(numColumns) +"...." ;
+}
+//...................
+public static String dimensions(double[][] matrix1,double[][] matrix2){
+            return dimensions(matrix1) +"-->"  +dimensions(matrix2);
+}
+//...................
+public static String dimensions(double[][] matrix1,double[][] matrix2,double[][] matrix3){
+            return dimensions(matrix1) +","  +dimensions(matrix2) +"-->"  +dimensions(matrix3) ;
+}
+//...................
+ public static boolean checkDimensions(double[][] matrix1, double[][] matrix2){
+		int numRows1    = MatrixUtil.numFullRows(matrix1);
+		int numRows2    = MatrixUtil.numFullRows(matrix2);
+		int numColumns1 = MatrixUtil.numFullColumns(matrix1);
+		int numColumns2 = MatrixUtil.numFullColumns(matrix2);
+		boolean flag = (numRows1!= numRows2 || numRows1==0 || numColumns1!=numColumns2 || numColumns1==0) ;
+		if (flag) mistakesWereMade("Once again, your dimensions don't match up:   " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  
+		             +" by  " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  ); 
+		return flag;
+		}
+/*...........................................................*/
+	public static String toString(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		StringBuffer result = new StringBuffer(2*numRows*numColumns);
+		for (int j=0; j<numRows; j++) {
+			result.append('[');
+			for (int i=0; i<numColumns; i++) {
+				
+				MesquiteDouble.toString(matrix[i][j], result);
+				result.append(' ');
+			}
+			result.append(']');
+			result.append('\n');
+		}
+		return result.toString();
+	}
+	/*...........................................................*/
+	public static String toString(double[] vector){
+		if (vector==null ||  vector.length==0)
+			return null;  
+		StringBuffer result = new StringBuffer(vector.length*2);
+		result.append('[');
+		for (int i=0; i<vector.length; i++) {
+			MesquiteDouble.toString(vector[i], result);
+			result.append(' ');
+		}
+		result.append(']');
+		return result.toString();
+	}
+	/*...........................................................*/
+	public static String toString(int[] vector){
+		if (vector==null ||  vector.length==0)
+			return null;  
+		StringBuffer result = new StringBuffer(vector.length*2);
+		result.append('[');
+		for (int i=0; i<vector.length; i++) {
+			result.append(Integer.toString(vector[i]));
+			result.append(' ');
+		}
+		result.append(']');
+		return result.toString();
+	}
+//..................................................................................................................................................................................//
+
+	public static MContinuousDistribution stripExcluded(MContinuousDistribution original, MesquiteBoolean wasStripped){
+		CharacterData data = original.getParentData();
+		if (data ==null)
+			return original;
+		
+		CharInclusionSet incl = (CharInclusionSet) data.getCurrentSpecsSet(CharInclusionSet.class);
+		if (incl == null || incl.numberSelected() == data.getNumChars())
+			return original;
+		MContinuousAdjustable stripped = new MContinuousAdjustable(data.getTaxa());
+		stripped.setItemsAs(original);
+		int strippedNumChars = incl.numberSelected();
+		int numTaxa = data.getNumTaxa();
+		stripped.setSize(strippedNumChars, numTaxa);
+		int count = 0;
+		ContinuousState cs = null;
+		for (int ic = 0; ic<data.getNumChars(); ic++){
+			if (incl.isBitOn(ic)){
+				for (int it = 0; it<numTaxa; it++){
+					cs = (ContinuousState)data.getCharacterState(cs, ic, it);
+					stripped.setState(count, it, cs);
+				}
+				count++;
+			}
+		}
+		if (wasStripped != null)
+			wasStripped.setValue(true);
+		return stripped;
+	}
+
+
+//.............ROW AND COLUMN MANIPTULATIONS............................................................................................................//
+	/*...........................................................*/
+	public static int numFullRows(double[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public static int numFullRows(int[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return n;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(double[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public static int numFullColumns(int[][] matrix){
+		if (matrix==null || matrix.length==0 || matrix[0] == null  || matrix[0].length == 0 )
+			return 0;
+		int n = matrix[0].length;
+		for (int i=0; i<matrix.length; i++) {
+			if (matrix[i]==null || n!= matrix[i].length)
+				return 0;
+		}
+		return matrix.length;
+	}
+	/*...........................................................*/
+	public static double[][] getRow(double[][] matrix,int which){
+		if (MatrixUtil.numFullColumns(matrix)==0)
+			return null;
+		double[][] selected = new double[matrix.length][1];
+		for (int i=0; i<matrix.length; i++) {
+			 selected[i][0]=matrix[i][which];
+		}
+		if (writeCommentary) runningCommentary("getRow " +MesquiteInteger.toString(which) +dimensions(matrix,selected));  
+		if (writeIntermediates) intermediates(MatrixUtil.toString(selected)); 
+		return selected;
+	}
+	/*...........................................................*/
+      public static double[][] getColumn(double[][] matrix,int which){
+		int rows=MatrixUtil.numFullRows(matrix);
+	      if (rows==0)  mistakesWereMade("Hey, I can't get blood from a turnip! This matrix has no columns to select!!");
+	      if (rows==0)
+  			return null;
+	      double[][] selected = new double[1][rows];
+		for (int i=0; i<rows; i++) {
+				selected[0][i]=matrix[which][i];
+		}
+		if (writeCommentary) runningCommentary("getColumn " +MesquiteInteger.toString(which) +dimensions(matrix,selected));   
+		if (writeIntermediates) intermediates(MatrixUtil.toString(selected));  
+		return selected;
+	}
+	/*...........................................................*/
+	public static double[][] columnAverages(double[][] matrix){
+		if (numFullColumns(matrix)==0)
+			return null;
+		double[][] avg = new double[matrix.length][1];
+		for (int i=0; i<matrix.length; i++) {
+			double sum = 0;
+			for (int j=0; j<matrix[i].length; j++)
+				sum+=matrix[i][j];
+			avg[i][0]= sum/matrix[i].length;
+		}
+		if (writeCommentary) runningCommentary("columnAverages: " +dimensions(matrix,avg) ); 
+		if (writeIntermediates) intermediates(MatrixUtil.toString(avg));  
+		return avg;
+	}
+	/*...........................................................*/
+	public static double[][] rowAverages(double[][] matrix){ 
+		if (numFullRows(matrix)==0)
+			return null;
+		double[][] avg = new double[1][matrix[0].length]; //don't count unassigned values?
+		for (int j=0; j<matrix[0].length; j++) {
+			double sum = 0;
+			for (int i=0; i<matrix.length; i++) {
+				if (j<matrix[i].length)
+					sum=sum+matrix[i][j];
+			}
+			avg[0][j]= sum/matrix.length;
+		}
+		if (writeCommentary) runningCommentary("rowAverages" +dimensions(matrix,avg)); 
+		if (writeIntermediates) intermediates(MatrixUtil.toString(avg));  
+		return avg;
+	}
+	/*...........................................................*/
+	public static double[] reverse(double[] matrix){
+		if (matrix == null)
+			return null;
+		double[] result = new double[matrix.length];
+		for (int i=0; i<result.length; i++) {
+			result[result.length-i-1]=matrix[i];
+		}
+		return result;
+	}
+	/*...........................................................*/
+	public static double[][] horizontalFlip(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numRows][numColumns];
+		for (int i=0; i<numColumns; i++) {
+			result[numColumns-i-1]=matrix[i];
+		}
+		if (writeCommentary) runningCommentary("horizontalFlip"   +dimensions(matrix,result) );
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+	/*...........................................................*/
+	public static double[][] transpose(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numRows][numColumns];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[j][i]=matrix[i][j];
+			}
+		}
+		if (writeCommentary) runningCommentary("transpose"   +dimensions(matrix,result) );
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+// *-------------------------------------------------------------Haugment--------;
+	public static double[][] Haugment(double[][] matrix1, double[][] matrix2){
+		int numRows1 = numFullRows(matrix1);
+		int numColumns1 = numFullColumns(matrix1);
+	      int numRows2 = numFullRows(matrix2);
+		int numColumns2 = numFullColumns(matrix2);
+	      boolean flag =  (numRows1!=numRows2)  ;
+		if (flag) System.out.println("Oh No! You are trying to horizontally augment a:   " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  
+		             +" to a  " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  ); 
+		if (flag)
+		    return null; 		
+    		double[][] result = new double[numColumns1+numColumns2][numRows1];
+		for (int i=0; i<numColumns1; i++) {
+			for (int j=0; j<numRows1; j++) {
+				result[i][j]=matrix1[i][j];
+			}
+		}
+		for (int i=0; i<numColumns2; i++) {
+			for (int j=0; j<numRows2; j++) {
+				result[i+numColumns1][j]=matrix2[i][j];
+			}
+		}
+		if (writeCommentary) runningCommentary("Haugment" +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+  	}
+// *-------------------------------------------------------------Vaugment--------;
+	public static double[][] Vaugment(double[][] matrix1, double[][] matrix2){
+		int numRows1 = numFullRows(matrix1);
+		int numColumns1 = numFullColumns(matrix1);
+		if (numRows1==0 ||  numColumns1==0)
+			return null; 
+ 		int numRows2 = numFullRows(matrix2);
+		int numColumns2 = numFullColumns(matrix2);
+		if (numRows2==0 ||  numColumns2==0)
+			return null; 
+		boolean flag =  (numColumns1!=numColumns2) ;
+		if (flag) System.out.println("Oh No! You are trying to vertically augment a:   " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  
+		             +" to a  " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  ); 
+		if (flag)
+		    return null; 						
+	  		double[][] result = new double[numColumns1][numRows1+numRows2];
+		for (int i=0; i<numColumns1; i++) {
+			for (int j=0; j<numRows1; j++) {
+				result[i][j]=matrix1[i][j];
+			}
+		}
+		for (int i=0; i<numColumns2; i++) {
+			for (int j=0; j<numRows2; j++) {
+				result[i][j+numRows1]=matrix2[i][j];
+			}
+		}
+		if (writeCommentary) runningCommentary("Vaugment"  +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;																										
+  	}
+//..................................................................................................................................................................................//
+  	
+
+
+//..........................................CREATING NEW MATRICIES.................................................................................................//
+	/*...........................................................*/
+	public static double[][] identityMatrix(int rc){
+		double[][] result = new double[rc][rc];
+		for (int i=0; i<rc; i++)
+			for (int j=0; j<rc; j++){
+				result[i][j]=0;
+				if (i==j) result[i][j]=1.0;
+		}
+	if (writeCommentary) runningCommentary("identityMatrix "  +dimensions(result));
+	if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+	return result;
+	}
+	/*...........................................................*/
+	public static double[][] fillMatrix(int row,int col,double number){
+		double[][] result = new double[row][col];
+		for (int i=0; i<row; i++)
+			for (int j=0; j<col; j++){
+				result[i][j]=number;
+		}
+		if (writeCommentary) runningCommentary("fillMatrix" +dimensions(result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}	
+//.........................................................................................................................................................................................//
+	
+
+
+
+// ...............BASIC MATRIX ALGEBRA ...................................................................................................................................//
+	/*...........................................................*/
+	public static double[][] add(double[][] matrix1, double[][] matrix2){
+	if (MatrixUtil.checkDimensions(matrix1,matrix2))
+			return null;  
+	      int numRows1 = numFullRows(matrix1);
+		int numRows2 = numFullRows(matrix2);
+		int numColumns1 = numFullColumns(matrix1);
+		int numColumns2 = numFullColumns(matrix2);
+		if (numRows1!= numRows2 || numRows1==0 || numColumns1!=numColumns2 || numColumns1==0)
+			return null;  
+		
+		double[][] sum = new double[numColumns1][numRows1];
+		for (int i=0; i<numColumns1; i++) {
+			for (int j=0; j<numRows1; j++) {
+				sum[i][j]=matrix1[i][j] + matrix2[i][j];
+			}
+		}
+		if (writeCommentary) runningCommentary("add " +dimensions(matrix1,matrix2,sum));
+	      if (writeIntermediates) intermediates(MatrixUtil.toString(sum)); 
+	      return sum;
+	}	
+	 /*...........................................................*/
+	public static double[][] subtract(double[][] matrix1, double[][] matrix2){
+		if (MatrixUtil.checkDimensions(matrix1,matrix2))
+			return null;  
+   		int numRows1 = numFullRows(matrix1);
+		int numColumns1 = numFullColumns(matrix1);
+		double[][] sub = new double[numColumns1][numRows1];
+		for (int i=0; i<numColumns1; i++) {
+			for (int j=0; j<numRows1; j++) {
+				sub[i][j]=matrix1[i][j] - matrix2[i][j];
+			}
+		}
+		if (writeCommentary) runningCommentary("subtract " +dimensions(matrix1,matrix2,sub));
+	     if (writeIntermediates) intermediates(MatrixUtil.toString(sub)); 
+	      return sub;
+		}
+	 // ------------------------multiplyElementwise--------------------;
+    	public static double[][] multiplyElementwise(double[][] matrix1, double[][] matrix2){
+		if (MatrixUtil.checkDimensions(matrix1,matrix2))
+			return null;  
+		int numRows1 = MatrixUtil.numFullRows(matrix1);
+		int numColumns1 = MatrixUtil.numFullColumns(matrix1);
+		int numRows2 = MatrixUtil.numFullRows(matrix2);
+		int numColumns2 = MatrixUtil.numFullColumns(matrix2);
+		if (numRows1==0 ||  numColumns1==0)
+			return null; 
+		if (numRows1 != numRows2 ||  numColumns1 != numColumns2)
+			return null; 
+		double[][] result = new double[numColumns1][numRows1];
+		for (int i=0; i<numColumns1; i++) {
+			for (int j=0; j<numRows1; j++) {
+				result[i][j]=(matrix1[i][j])*(matrix2[i][j]);
+			}
+		}
+		if (writeCommentary) runningCommentary("multiplyElementwise" +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+ 		return result;
+	}
+      /*...........................................................*/
+	public static double[][] multiply(double[][] matrix1, double[][] matrix2){
+		int numRows1 = MatrixUtil.numFullRows(matrix1);
+		int numRows2 = MatrixUtil.numFullRows(matrix2);
+		int numColumns1 = MatrixUtil.numFullColumns(matrix1);
+		int numColumns2 = MatrixUtil.numFullColumns(matrix2);
+		boolean flag = (numColumns1!= numRows2 || numRows1*numRows2*numColumns1*numColumns2 ==0);
+		if (flag) System.out.println("Wow! You are trying to multiply a:   " 
+		        +Integer.toString(numRows1) +"x" +Integer.toString(numColumns1)  
+		             +" by a  " 
+		        +Integer.toString(numRows2) +"x" +Integer.toString(numColumns2)  ); 
+		if (flag)
+		    return null; 
+		double[][] result = new double[numColumns2][numRows1];
+		for (int i=0; i<numColumns2; i++) {
+			for (int j=0; j<numRows1; j++) {
+				double sum =0;
+				for (int k=0; k<numColumns1; k++) {
+					sum += matrix1[k][j]* matrix2[i][k];
+				}
+				result[i][j]=sum;
+			}
+		}
+		if (writeCommentary) runningCommentary("multiply" +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+     /*...........................................................*/
+	public static double[][] multiply(double scalar, double[][] matrix){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+            if (numRows*numColumns==0) 
+               return null;
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numRows; i++) {
+			for (int j=0; j<numColumns; j++) {
+					result[j][i] = scalar* matrix[j][i] ;	
+			}
+		}
+		if (writeCommentary) runningCommentary("multiply by scalar" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+//............................................................................................................................................................................................//
+
+
+
+
+//........................OPERATIONS ON MATRICES.............................................................................................................................//
+   // ------------------------abs--------------------;
+	public static double[][] abs(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=Math.abs(matrix[i][j]);
+			}
+		}
+		if (writeCommentary) runningCommentary("abs " +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	  }
+	 // -----------------------minimum--------------------;
+	public static double minimum(double[][] matrix){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		double result = matrix[0][0];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+//eric: Mesquite has the concept of numbers having the value "unassigned", and this can screw up min/max calculations
+// either we should check for unassigned values first, or we should use Mesquite's minimum method
+				result = Math.min(matrix[i][j],result);
+			}
+		}		
+		if (writeCommentary) runningCommentary("minimum" +MatrixUtil.dimensions(matrix)); 
+		if (writeIntermediates) intermediates(Double.toString(result)); 
+		return result;
+	}
+  // -----------------------maximum--------------------;
+	public static double maximum(double[][] matrix){
+		int numRows 	= MatrixUtil.numFullRows(matrix);
+		int numColumns 	= MatrixUtil.numFullColumns(matrix);
+		double result = matrix[0][0];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result = Math.max(matrix[i][j],result); 
+			}
+		}		
+		if (writeCommentary) runningCommentary("maximum" +MatrixUtil.dimensions(matrix)); 
+		if (writeIntermediates) intermediates(Double.toString(result)); 
+		return result;
+	}
+	// ----------square elements of matrix---------------------------------square--;
+	public static double[][] square(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=(matrix[i][j])*(matrix[i][j]);
+			}
+		}
+		if (writeCommentary) runningCommentary("square " +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+	// ------------------------log--------------------;
+	public static double[][] log(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=Math.log(matrix[i][j]);
+			}
+		}
+		if (writeCommentary) runningCommentary("log" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}	
+// -----------------------logprotected--------------------;
+	public static double[][] logprotected(double[][] matrix){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				if (matrix[i][j] == 0) result[i][j]=0.0;				
+				if (matrix[i][j] != 0) result[i][j]=Math.log(matrix[i][j]);
+			}
+		}		
+		if (writeCommentary) runningCommentary("logprotected" +dimensions(matrix,result)); 
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+//..................................................................................................................................................................................//
+
+
+
+ 
+ 
+//......................................BASIC STATISTICAL PROCEDURES.........................................................................................//
+// Design matix	 ----- ------ ;
+		public static double[][] design(TaxaPartition partition){
+			Taxa taxa = partition.getTaxa();
+			int numTaxa = taxa.getNumTaxa();
+			int numPartitions = partition.getNumberOfGroups();
+			
+			double[][] g = new double[numPartitions][numTaxa];      	
+			for (int i=0; i<numPartitions;i++)
+				for (int j=0; j<numTaxa; j++)		// fill with zeros
+					 g[i][j] = 0;
+			TaxaGroup[] groups = partition.getGroups();
+			if (groups==null)
+				return null;
+			int ccc=0;							
+			for (int i=0; i<numPartitions;i++) {
+			        int nGroup = partition.getNumberInGroup(groups[i]);
+			        for (int j=0; j<nGroup;j++) {
+			                g[i][ccc] = 1;
+			        	ccc=ccc+1;			    			      
+				}
+			} 
+                  if (writeCommentary) runningCommentary("design" +dimensions(g));
+                  if (writeIntermediates) intermediates(MatrixUtil.toString(g));
+			return g;
+		}
+// ----------inverse of matrix ---------------------------------------inv---;
+	 public static double[][] inverse(double[][] matrix){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+
+		Matrix m = new Matrix(matrix);    
+		Matrix r = m.inverse();
+		double[][] result  = r.getArrayCopy();
+                  if (writeCommentary) runningCommentary("inverse" +dimensions(matrix,result));
+                  if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+			return result;
+		/**/
+		/**/
+	}
+// *----------------zero centers matrix by column---------------------zerocenter----;
+	public static double[][] zeroCenter(double[][] matrix){
+		int numRows = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null; 
+		double[][] colmeans = MatrixUtil.columnAverages(matrix); 
+		double[][] result   = new double[numColumns][numRows];
+		for (int i=0; i<numRows; i++) {
+			for (int j=0; j<numColumns; j++) {
+				result[j][i]=matrix[j][i]-colmeans[j][0];
+			}
+		}	
+		if (writeCommentary) runningCommentary("zeroCenter" +MatrixUtil.dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result;
+  	}
+// *-------------------standard deviation----------------------------------------;
+	public static double[][] standardDeviation(double[][] matrix){
+		int numRows    = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null; 
+		double[][] zerocentered  = MatrixUtil.zeroCenter(matrix);
+   		double[][] result = new double[numColumns][1];
+		double     divisor =  numRows-1;
+		for (int i=0; i<numColumns; i++) {
+			double sum = 0;
+			for (int j=0; j<numRows; j++)
+				sum+=(zerocentered[i][j])*(zerocentered[i][j]);
+			result[i][0]= Math.sqrt(sum/divisor);
+		}
+		if (writeCommentary) runningCommentary("standardDeviation" +MatrixUtil.dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result;
+  	}
+// *------------------group meansMatrix----------------------------------------groupMeansMatrix----------;
+ 	public static double[][] groupMeans(double[][] matrix, TaxaPartition partition){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+	  	double[][] G  = design(partition);
+	  	double[][] GT = transpose(G);
+	    	double[][] mean_w = multiply(multiply(inverse(multiply(GT,G)), GT), matrix);  
+		double[][] result = multiply(G,mean_w);		 		 								
+		if (writeCommentary) runningCommentary("groupMeans" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result;
+	}
+// *------------------Within group means ----------------------------------------WithingroupMeans----------;
+ 	public static double[][] withinGroupMeans(double[][] matrix, TaxaPartition partition){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  
+	  	  double[][] G  = design(partition);
+	  	  double[][] GT = transpose(G);
+	    	double[][] mean_w = multiply(multiply(inverse(multiply(GT,G)), GT), matrix);  
+		double[][] result = mean_w;
+		if (writeCommentary) runningCommentary("withinGroupMeans" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));						
+		return result;
+	}
+// *-------------------------------------------------------------pool----------;
+	 public static double[][] pool(double[][] matrix, TaxaPartition partition){
+	    	double[][] gmeans  = groupMeans(matrix,partition);  
+		double[][] result  = subtract(matrix,gmeans);
+		if (writeCommentary) runningCommentary("pool" +dimensions(result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result;
+	}
+// *-------------------------------------------------------------zscores--------;
+	public static double[][] zScores(double[][] matrix){
+		int numRows     = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			 return null; 
+		double[][] zerocentered  =  MatrixUtil.zeroCenter(matrix);
+		double[][] stdevs            =  MatrixUtil.standardDeviation(matrix);
+   		double[][] result             =  new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=zerocentered[i][j]/stdevs[i][0];
+			}
+		}
+		if (writeCommentary) runningCommentary("zscores" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result;
+  	}
+ // *-------------------correlation matrix-------------------------------correlation---------;
+	public static double[][] correlation(double[][] matrix1){
+		int numRows1    = MatrixUtil.numFullRows(matrix1);
+		int numColumns1 = MatrixUtil.numFullColumns(matrix1);
+		if (numRows1==0 ||  numColumns1==0)
+			return null; 
+     		double[][] zscores1 = MatrixUtil.zScores(matrix1);
+     		double[][] result   = MatrixUtil.multiply(1.0/(numRows1-1.0),(MatrixUtil.multiply(MatrixUtil.transpose(zscores1),zscores1)));
+     		if (writeCommentary) runningCommentary("correlation" +MatrixUtil.dimensions(matrix1,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 	
+            return result;
+    }
+   // *-------------------correlation for 2 different matrices------------------------------correlation2---------;
+	public static double[][] correlation(double[][] matrix1, double[][] matrix2){
+		int numRows1 = numFullRows(matrix1);
+		int numColumns1 = numFullColumns(matrix1);
+		if (numRows1==0 ||  numColumns1==0)
+			return null; 
+ 		int numRows2 = numFullRows(matrix2);
+		int numColumns2 = numFullColumns(matrix2);
+		if (numRows2==0 ||  numColumns2==0)
+			return null; 
+		if (numRows1!=numRows2 ||  numColumns1!=numColumns2) 
+			return null; 						
+     		double[][] zscores1  =   zScores(matrix1);
+     		double[][] zscores2  =   zScores(matrix2);
+     		double[][] result = multiply(1.0/(numRows1-1.0),(multiply(transpose(zscores1),zscores2)));
+  	  	if (writeCommentary) runningCommentary("correlation" +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+		return result; 
+  	}
+ // *-------------------covariance matrix-------------------------------covariance---------;
+	public static double[][] covariance(double[][] matrix){  
+		int numRows    = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null; 					
+      		double[][] zcent  =   zeroCenter(matrix);
+      		double[][] result =   MatrixUtil.multiply(1.0/(numRows-1.0),(MatrixUtil.multiply(MatrixUtil.transpose(zcent),zcent)));
+      	if (writeCommentary) runningCommentary("covariance" +MatrixUtil.dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+  	}
+ // *-------------------covariance matrix from two different matrices----------------------covariance2---------;
+	public static double[][] covariance(double[][] matrix1, double[][] matrix2){  
+		int numRows1 = numFullRows(matrix1);
+		int numColumns1 = numFullColumns(matrix1);
+		if (numRows1==0 ||  numColumns1==0)
+			return null; 
+ 		int numRows2 = numFullRows(matrix2);
+		int numColumns2 = numFullColumns(matrix2);
+		if (numRows2==0 ||  numColumns2==0)
+			return null; 
+		if (numRows1!=numRows2 ||  numColumns1!=numColumns2)
+			return null; 						
+     		double[][] zcent1  =   zeroCenter(matrix1);
+     		double[][] zcent2  =   zeroCenter(matrix2);
+            double[][] result = multiply(1.0/(numRows1-1.0),(multiply(transpose(zcent1),zcent2)));
+     		if (writeCommentary) runningCommentary("covariance" +dimensions(matrix1,matrix2,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+  	}
+// *------------------Pooled within-group covariance matrix---------------pwc---------;
+	public static double[][] pooledWithinGroupCovariance(double[][] matrix, TaxaPartition partition){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null; 
+		double[][] G  = 	design(partition);
+		int numGroups = numFullColumns(G);  		
+		double[][] pooled  = 	pool(matrix,partition); 
+		double[][] result = multiply(1.0/(numRows-numGroups),(multiply(transpose(pooled),pooled)));
+     		if (writeCommentary) runningCommentary("pooledWithinGroupCovariance" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+  	}
+// *----------------vector correlations---------------------------------vec_corr------;  
+	public static double[][] vectorCorrelation(double[][] matrix,double[][] evec){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null; 
+		double[][] rotated       = multiply(matrix,evec);
+   		double[][] result         = correlation(matrix,rotated);
+		if (writeCommentary) runningCommentary("vectorCorrelations" +dimensions(matrix,evec,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+  	}
+	// *-----rescale matrix by vector-----------------------------------rescale--------;
+	public static double[][] rescale(double[][] matrix, double[] vector){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  				 
+   		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=(matrix[i][j])*(vector[i]);
+			}
+		}
+ 		if (writeCommentary) runningCommentary("rescale" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;	
+	}
+	// *-----rescale matrix by 1/ sqrt of vector-----------------------------rescalesqrt-----------;
+	public static double[][] rescalesqrt(double[][] matrix, double[] vector){
+		int numRows = numFullRows(matrix);
+		int numColumns = numFullColumns(matrix);
+		if (numRows==0 ||  numColumns==0)
+			return null;  			
+		double[][] result = new double[numColumns][numRows];
+		for (int i=0; i<numColumns; i++) {
+			for (int j=0; j<numRows; j++) {
+				result[i][j]=(matrix[i][j])*Math.sqrt(1.0/vector[i]);
+			}
+		}
+		if (writeCommentary) runningCommentary("rescalesqrt" +dimensions(matrix,result));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;
+	}
+	// *-----percent explained-----------------------------percentage-----------;
+	//  This is the one utility that uses a double[] because the PCA, ePCA code depends on it //
+	public static double[] percentage(double[] vector){
+		double[] result = new double[vector.length];
+		double sum = 0;
+		for (int i=0; i<vector.length; i++) {
+			sum +=vector[i];
+		}
+		for (int j=0; j<vector.length; j++) {
+			result[j]=vector[j]/sum;
+		}
+		if (writeCommentary) runningCommentary("percentage" );
+		if (writeIntermediates) intermediates(MatrixUtil.toString(result)); 
+		return result;	
+	}
+//..................................................................................................................................................................................//
+
+
+
+
+
+//....................GENERAL LINEAR MODEL (GLM)..................................................................................................................//
+//.................................
+	public static double[][] GLMslopes(double[][] X,double[][] Y){
+		int numRowsX    = MatrixUtil.numFullRows(X);
+		int numColumnsX = MatrixUtil.numFullColumns(X);
+		if (numRowsX==0 ||  numColumnsX==0)
+			return null; 
+		int numRowsY    = MatrixUtil.numFullRows(Y);
+		int numColumnsY = MatrixUtil.numFullColumns(Y);
+		if (numRowsX==0 ||  numColumnsX==0)
+			return null; 
+		if (numRowsX != numRowsY)
+			return null; 
+		double[][] Xaug = MatrixUtil.Haugment(X,MatrixUtil.fillMatrix(1,numRowsX,1.0)); 
+   		double[][] TXaug = MatrixUtil.transpose(Xaug);
+		double[][] slopeMatrix = MatrixUtil.multiply( MatrixUtil.multiply( MatrixUtil.inverse(MatrixUtil.multiply(TXaug,Xaug)),TXaug), Y);
+		double[][] predMatrix  = MatrixUtil.multiply(Xaug,slopeMatrix);
+		double[][] residMatrix = MatrixUtil.subtract(Y,predMatrix);
+	   	if (writeCommentary) runningCommentary("GLMslopes" +MatrixUtil.dimensions(X,Y,slopeMatrix));
+  	    	if (writeIntermediates) intermediates(MatrixUtil.toString(slopeMatrix));
+  	    	return slopeMatrix;
+  	} 
+//.................................
+	public static double[][] GLMresiduals(double[][] Y, double[][] predMatrix){
+		double[][] residMatrix = MatrixUtil.subtract(Y,predMatrix);
+	    	if (writeCommentary) runningCommentary("GLMresiduals" +MatrixUtil.dimensions(Y,predMatrix,residMatrix));
+  	    	if (writeIntermediates) intermediates(MatrixUtil.toString(residMatrix));
+  	     	return residMatrix;
+  	} 
+//.................................
+	public static double[][] GLMpredicted(double[][] X, double[][] slopeMatrix){
+		int numRowsX    = MatrixUtil.numFullRows(X);	
+		double[][] Xaug = MatrixUtil.Haugment(X,MatrixUtil.fillMatrix(1,numRowsX,1.0)); 
+		double[][] predMatrix  = MatrixUtil.multiply(Xaug,slopeMatrix);
+	   	if (writeCommentary) runningCommentary("GLMpredicted"  +MatrixUtil.dimensions(X,slopeMatrix,predMatrix));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(predMatrix));
+  	    	return predMatrix;
+  	} 
+ //..................................................................................................................................................................................//
+
+
+
+
+
+//..............................THIN-PLATE SPLINES.....................................................................................................................//
+//...........................principal warps...................................
+	public static double[][] pwarps(double[][] matrix){
+		int numRows    = MatrixUtil.numFullRows(matrix);
+		int numColumns = MatrixUtil.numFullColumns(matrix);
+		double [][] xvector = MatrixUtil.getColumn(matrix,0);
+		double [][] yvector = MatrixUtil.getColumn(matrix,1);
+		// function evaluation for weighting 
+			double[][] postvector= MatrixUtil.fillMatrix(numRows,1,1.0);
+			double[][] prevector= MatrixUtil.fillMatrix(1,numRows,1.0);
+			double[][] R1= MatrixUtil.square(MatrixUtil.subtract(MatrixUtil.multiply(xvector,postvector),MatrixUtil.multiply(prevector,MatrixUtil.transpose(xvector))));
+			double[][] R2= MatrixUtil.square(MatrixUtil.subtract(MatrixUtil.multiply(yvector,postvector),MatrixUtil.multiply(prevector,MatrixUtil.transpose(yvector))));
+			double[][] Re=MatrixUtil.abs(MatrixUtil.add(R1,R2)); 
+			double [][] logr2 = MatrixUtil.log( MatrixUtil.add(Re, MatrixUtil.identityMatrix(numRows)) );  
+   		// Construct L matrix ;
+			double[][]  K = MatrixUtil.multiplyElementwise(Re,logr2);
+			double[][]  P = MatrixUtil.Haugment(prevector,matrix);
+			double[][]  L = MatrixUtil.Vaugment(MatrixUtil.Haugment(K,P),MatrixUtil.Haugment(MatrixUtil.transpose(P),MatrixUtil.fillMatrix(3,3,0.0) ));	        
+			double[][] Linv = MatrixUtil.inverse(L); 	
+		// solve for Warp matrix, if one wants it, not necessary for transformation;
+		// Lin = Linv[1:n,1:n];
+		// Warp=MatrixUtil.multiply( Lin, MatrixUtil.multiply(K,Lin));
+		// eigenanalysis of Warp matrix;
+		// call eigen(eval,evec,Warp);
+		if (writeCommentary) runningCommentary("pwarps" +MatrixUtil.dimensions(matrix,Linv));
+		if (writeIntermediates) intermediates("pwarps" +MatrixUtil.toString(Linv)); 
+	    return Linv;
+	}
+    // ....................thin-plate spline transformation................................................
+   		// ...................takes any collection of points (points) and transforms them to new points (transformed);
+   		// ...................must include base and target landmark configurations to calculate transformation; 
+   public static double[][] tps(double[][] points, double[][] base_config,double[][]targ_config){
+   	     int numRows = MatrixUtil.numFullRows(points);   
+   	     int numRowsBase = MatrixUtil.numFullRows(base_config);  
+		// mapping uses base configuration
+			double[][] Linv = pwarps(base_config);
+           // add in offset to target configuration
+			double[][] LV=MatrixUtil.multiply(Linv,MatrixUtil.Vaugment(targ_config,MatrixUtil.fillMatrix(2,3, 0.0)));
+			if (writeIntermediates) intermediates("LV" +MatrixUtil.toString(LV)); 
+		// make some necessary ones vectors 
+			double[][] ones2x1  = MatrixUtil.fillMatrix(1, 2, 1.0);
+			double[][] onesrx1  = MatrixUtil.fillMatrix(1,numRowsBase,1.0);
+			double[][] ones1x1  = MatrixUtil.fillMatrix(1, 1, 1.0);
+		// calculate weighting function from base configuration
+			double[][] transformed = new double[2][numRows];
+			double[][] transF= new double[1][2];
+			for (int i=0; i<numRows; i++) { 
+				double[][] xy = MatrixUtil.getRow(points,i);
+		  		double[][] Ud = MatrixUtil.multiply(
+		 			 MatrixUtil.square(
+					    MatrixUtil.subtract(base_config,
+			    		        MatrixUtil.multiply(onesrx1,xy)
+	  							)
+		  					) 
+		  				 , ones2x1);
+				double[][] Ud1 = MatrixUtil.multiplyElementwise(Ud,MatrixUtil.logprotected(Ud));
+				//Log-protected in case there are zeros.  
+				// Ud2 is a weighting function, then a 1, then the point (xy) all appended together to form column vector  	
+				double[][] Ud2 = MatrixUtil.transpose(MatrixUtil.Vaugment(Ud1,MatrixUtil.Vaugment(ones1x1,MatrixUtil.transpose(xy))));
+                 		// transform arbitrary point (xy) according to LV matrix and append to transformed
+				transF =MatrixUtil.multiply(Ud2,LV);
+				transformed[0][i]=transF[0][0];
+				transformed[1][i]=transF[1][0];
+		  	}
+		if (writeCommentary) runningCommentary("tps" +MatrixUtil.dimensions(points,transformed));
+		if (writeIntermediates) intermediates("tps" +MatrixUtil.toString(transformed)); 
+	  	return transformed;
+	}
+//......................................................................................................................................................................................//
+
+
+
+//....................GRAPHING ROUTINES......................................................................................................................................//
+//................................ transform 3D coordinates to 2D coordinates..............................//
+		//  ...................................uses three viewing angles: theta, phi, and rho, and one viewing distance: D 
+		 // .................................. angles are in radians, D is non-zero and generally positive 
+public static double[][] transform3Dto2D (double[][] ABC, 
+        		  double theta, // angle of viewpoint
+                    double phi, // angle of viewpoint
+                    double rho, //distance from viewpoint to 0,0,0
+                    double D){ //  distance to viewplane
+	double S1 = Math.sin(theta);
+	double C1 = Math.cos(theta);
+	double S2 = Math.sin(phi);
+	double C2 = Math.cos(phi);
+	double[][] XYZ  =   zeroCenter(ABC); 
+	int numRows  = MatrixUtil.numFullRows(XYZ);
+	double[][] result = new double[3][numRows];
+	for (int i=0; i<3; i++) {
+		for (int j=0; j<numRows; j++) {
+			double X = XYZ[0][j];
+			double Y = XYZ[1][j];
+			double Z = XYZ[2][j];
+			double ZE=   rho  -  Z*C2 - Y*S1*S2   - X*S2*C1;
+			result[0][j] = D*(Y*C1 - X*S1)/ZE;
+			result[1][j] = D*(Z*S2 - Y*C2*S1 - X*C1*C2)/ZE;
+			result[2][j] = ZE;
+		}
+	}	 
+ 	if (writeCommentary) runningCommentary("transform3Dto2D" +MatrixUtil.dimensions(XYZ,result));
+ 	if (writeIntermediates) intermediates(MatrixUtil.toString(XYZ));
+ 	if (writeIntermediates) intermediates(MatrixUtil.toString(result));
+ 	return result;
+}
+ //........................................................
+//...........................making and plotting grids for tps visualization...................................//
+	//............................here's how I make a grid to transform. there is probably a better way in java
+	//.......................... .basically, the idea is to make a grid to the base points, 
+	// ...........................then use the trans function above to warp it to show the deformation produced by the tps transformation 
+	public static double[][] makeGrid(double[][] points,int steps){
+	    double[][] x = MatrixUtil.getColumn(points,0);
+          double[][] y = MatrixUtil.getColumn(points,1);
+	    double minx = minimum(x);
+	    double miny = minimum(y);	    	    
+	    double rangex = Math.abs(maximum(x) - minx);
+	    double rangey = Math.abs(maximum(y) - miny);	   
+	    double basex  = minx-rangex/10.0; // make visually pleasing
+	    double basey  = miny-rangey/10.0;  // make visually pleasing
+	    double stepx  = 1.2*rangex/steps;
+	    double stepy  = 1.2*rangey/steps; 		
+          double[][] grid = new double[2][steps*steps];
+		    for ( int j=0; j<steps; j++) {
+		      for ( int i=0; i<steps; i++) {
+	   	        grid[0][j*steps+i]= (j+1)*stepx+basex ;
+	  	         grid[1][j*steps+i]= (i+1)*stepy+basey ;        
+	 	     }
+		    }  		
+		if (writeCommentary) runningCommentary("makeGrid"  +dimensions(grid));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(grid));
+		return grid; 
+	}
+  //........................................................
+  //........ here's a line drawing substitute I used for testing purposes........
+	public static void drawLine(Graphics g, double x1, double y1, double x2, double y2){
+		if (g!=null)
+			g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
+		else if (writeIntermediates) intermediates(" draw   ("
+		   							+Double.toString(x1)  +", "
+		   							+Double.toString(y1)  +")  to  ("
+		   							+Double.toString(x2)  +", "
+		   							+Double.toString(y2)  +")  " ) ;
+     return;
+     }
+//............................................................................................	
+	public static double[][] plotGrid(Graphics g, double[][] grid, int steps){
+		for ( int k=0; k<(steps-1); k++) {
+	 	   	for ( int l=0; l<(steps-1); l++) {
+	 	   	     int i  = steps*(k)+1;
+	 	   	     int ir = i+1;
+	 	   	     int ib = i+steps-1;
+                       drawLine(g, grid[0][i],grid[1][i], grid[0][ir], grid[1][ir]);
+	                 drawLine(g, grid[0][i],grid[1][i], grid[0][ib], grid[1][ib]);	     
+	    		} 
+	    	} 
+		for ( int k=0; k<(steps-1); k++) {
+	 	   	     int i  = steps*(k);
+	 	   	     int ir = i+steps;
+                 		drawLine(g, grid[0][i],grid[1][i], grid[0][ir], grid[1][ir]);
+	    	} 		
+		for ( int l=0; l<(steps-1); l++) {
+	 	   	     int i  = steps*(steps-1)+(l);
+	 	   	     int ib = i+1;
+		        	drawLine(g, grid[0][i],grid[1][i], grid[0][ib], grid[1][ib]);
+	   	 } 
+		if (writeCommentary) runningCommentary("gridPlot" +MatrixUtil.dimensions(grid));
+		if (writeIntermediates) intermediates(MatrixUtil.toString(grid));
+		return grid; 
+		} 
+}
+//..................................................................................................................................................................................//
+
+
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/NodeLocsPlot3D.java b/Source/mesquite/rhetenor/lib/NodeLocsPlot3D.java
new file mode 100644
index 0000000..621c914
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/NodeLocsPlot3D.java
@@ -0,0 +1,40 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**This class of modules assigns node locations for plotting.
+Example module: NodeLocsPlot3D*/
+
+public abstract class NodeLocsPlot3D extends NodeLocs  {
+	
+ 	public String getDutyName() {
+ 		return "Node Location (3D Plot)";
+   	 }
+   	 public Class getDutyClass() {
+   	 	return NodeLocsPlot3D.class;
+   	 }
+}
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/Ordination.java b/Source/mesquite/rhetenor/lib/Ordination.java
new file mode 100644
index 0000000..50d19f3
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/Ordination.java
@@ -0,0 +1,89 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+/* ======================================================================== 
+This contains the Ordination class, whose subclasses (PCAOrdination, CVAOrdination) 
+perform analyses such as Principal Components and Canonical Variates analyses.
+/* ======================================================================== */
+
+	public abstract class Ordination implements StringLister{
+		protected double[][] eigenVectors;
+		protected double[] eigenValues;
+		protected double[][] scores;
+		protected double[] percentExplained;
+		
+		protected void doEigenAnalysis(double[][] matrix, double[][] original){
+			EigenAnalysis eA = new EigenAnalysis(matrix, true, true, true);
+	     		eigenValues = eA.getEigenvalues();  
+			eigenVectors = eA.getEigenvectors();
+			if (eigenVectors!=null)
+				scores = MatrixUtil.multiply(original,eigenVectors);	
+			if (eigenValues!=null)
+				percentExplained = MatrixUtil.percentage(eigenValues);
+		}
+	 	public double[][] transformAnother(double[][] matrix){			
+				return MatrixUtil.multiply(matrix, eigenVectors); 
+	 	}
+		/*----------setting results to be same as passed Ordination ----------*/
+		public void setResults(Ordination ordRes){
+			eigenValues = ordRes.getEigenvalues();
+			eigenVectors = ordRes.getEigenvectors();
+			scores = ordRes.getScores();
+			percentExplained = ordRes.getPercentExplained();
+	  	}
+		/*----------getEigenvalues ----------*/
+		public double[] getEigenvalues(){
+			return eigenValues;
+	  	}
+		/* ----------getEigenvectors  ----------*/
+		public double[][] getEigenvectors(){
+			return eigenVectors;
+		}
+		public double[][] getScores(){
+			return scores;
+		}
+		public double[] getPercentExplained(){
+			return percentExplained;
+		}
+		public String report(){
+			if (scores==null)
+				return "";
+			String s = "";
+			s+=("eigenValues\n" + MatrixUtil.toString(eigenValues) + "\n\n");
+			s+=("Percent variance Explained\n" + MatrixUtil.toString(percentExplained) + "\n\n");
+			s+=("PCA scores\n" + MatrixUtil.toString(scores) + "\n\n");
+			return s;
+		}
+	 	public int getNumberOfAxes(){
+	 		if (eigenValues==null)
+	 			return 0;
+	 		else
+	 			return eigenValues.length;
+	 	}
+	 	public abstract String getAxisName(int i);
+	 	
+	 	public String[] getStrings(){
+	 		String[] s = new String[getNumberOfAxes()];
+	 		for (int i=0; i<getNumberOfAxes(); i++)
+	 			s[i]= getAxisName(i);
+	 		return s;
+	 	}
+ }
+
diff --git a/Source/mesquite/rhetenor/lib/OrdinationAssistant.java b/Source/mesquite/rhetenor/lib/OrdinationAssistant.java
new file mode 100644
index 0000000..8264739
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/OrdinationAssistant.java
@@ -0,0 +1,38 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class OrdinationAssistant extends MesquiteModule  {
+
+	public Class getDutyClass(){
+		return OrdinationAssistant.class;
+	}
+ 	public String getDutyName() {
+ 		return "Ordination Assistant";
+   	 }
+ 	public abstract void setOrdination(Ordination ordination, Taxa taxa, MatrixSourceCoord matrixSourceTask);
+}
+
+
diff --git a/Source/mesquite/rhetenor/lib/Ordinator.java b/Source/mesquite/rhetenor/lib/Ordinator.java
new file mode 100644
index 0000000..eb19848
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/Ordinator.java
@@ -0,0 +1,41 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+/* ======================================================================== */
+/***/
+
+public abstract class Ordinator extends MesquiteModule  {
+
+	public Class getDutyClass(){
+		return Ordinator.class;
+	}
+ 	public String getDutyName() {
+ 		return "Ordinator";
+   	 }
+   	 public String[] getDefaultModule() {
+ 		return new String[] {"#PrincipalComponents"};
+   	 }
+ 	public abstract Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa);
+}
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/PCACorrelOrdination.java b/Source/mesquite/rhetenor/lib/PCACorrelOrdination.java
new file mode 100644
index 0000000..987ae00
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/PCACorrelOrdination.java
@@ -0,0 +1,36 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+ /*==================================================*/
+	public class PCACorrelOrdination extends Ordination{
+		public PCACorrelOrdination(double[][] original){
+			doEigenAnalysis(MatrixUtil.correlation(original), original);
+		}
+	 	public String getAxisName(int i){
+	 		if (percentExplained==null || i>=percentExplained.length || i<0)
+	 			return "Error in Principal Components (correl.)";
+	 		else
+	 			return "PC(correl.)" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100*percentExplained[i], 3) +"%)";
+	 	}
+  	}
+
+
diff --git a/Source/mesquite/rhetenor/lib/PCAOrdination.java b/Source/mesquite/rhetenor/lib/PCAOrdination.java
new file mode 100644
index 0000000..bf29b5d
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/PCAOrdination.java
@@ -0,0 +1,37 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+   /*==================================================*/
+	public class PCAOrdination extends Ordination{
+		public PCAOrdination(double[][] original){
+			doEigenAnalysis(MatrixUtil.covariance(original), original);
+		}
+	 	public String getAxisName(int i){
+	 		if (percentExplained==null || i>=percentExplained.length || i<0)
+	 			return "Error in Principal Components";
+	 		else
+	 			return "PC" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100*percentExplained[i], 3) +"%)";
+	 	}
+  	}
+
+
+
diff --git a/Source/mesquite/rhetenor/lib/aPCAOrdination.java b/Source/mesquite/rhetenor/lib/aPCAOrdination.java
new file mode 100644
index 0000000..a17f49a
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/aPCAOrdination.java
@@ -0,0 +1,36 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+  /*==================================================*/
+	public class aPCAOrdination extends Ordination{
+		public aPCAOrdination(double[][] original, TaxaPartition partition){
+			doEigenAnalysis(MatrixUtil.covariance(MatrixUtil.withinGroupMeans(original, partition)), original);
+		}
+	 	public String getAxisName(int i){
+	 		if (percentExplained==null || i>=percentExplained.length || i<0)
+	 			return "Error in aPrincipal Components";
+	 		else
+	 			return "aPC" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100*percentExplained[i], 3) +"%)";
+	 	}
+  	}
+ 
+
diff --git a/Source/mesquite/rhetenor/lib/wPCAOrdination.java b/Source/mesquite/rhetenor/lib/wPCAOrdination.java
new file mode 100644
index 0000000..06e442f
--- /dev/null
+++ b/Source/mesquite/rhetenor/lib/wPCAOrdination.java
@@ -0,0 +1,36 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.lib; 
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+
+
+  /*==================================================*/
+	public class wPCAOrdination extends Ordination{
+		public wPCAOrdination(double[][] original, TaxaPartition partition){
+			doEigenAnalysis(MatrixUtil.pooledWithinGroupCovariance(original, partition), original);
+		}
+	 	public String getAxisName(int i){
+	 		if (percentExplained==null || i>=percentExplained.length || i<0)
+	 			return "Error in wPrincipal Components";
+	 		else
+	 			return "wPC" + CharacterStates.toExternal(i) + " (" +MesquiteDouble.toStringDigitsSpecified(100*percentExplained[i], 3) +"%)";
+	 	}
+  	}
+
+
diff --git a/Source/mesquite/rhetenor/wPCA/wPCA.java b/Source/mesquite/rhetenor/wPCA/wPCA.java
new file mode 100644
index 0000000..62d9d98
--- /dev/null
+++ b/Source/mesquite/rhetenor/wPCA/wPCA.java
@@ -0,0 +1,86 @@
+/* Mesquite source code (Rhetenor package).  Copyright 1997 and onward E. Dyreson and W. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.rhetenor.wPCA;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.rhetenor.lib.*;
+
+/* ======================================================================== */
+public class wPCA extends Ordinator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TaxaPartitionSource.class, getName() + "  needs a source for a taxon partition.",
+		"The source of taxon partition is selected initially");
+	}
+	/*.................................................................................................................*/
+	wPCAOrdination ord;
+	boolean first = true;
+	TaxaPartitionSource partitionSource;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		partitionSource = (TaxaPartitionSource)hireEmployee(TaxaPartitionSource.class, "Source of Taxa Partitions");
+ 		if (partitionSource == null)
+ 			return sorry(getName() + " couldn't start because no source of taxa partition obtained.");
+ 		return true;
+ 	}
+ 	
+	/*.................................................................................................................*/
+ 	public Ordination getOrdination(MContinuousDistribution matrix, int item, Taxa taxa){
+		TaxaPartition part = partitionSource.getPartition(taxa);
+		if (part== null) {
+			if (first)
+				discreetAlert( "Sorry, wPCA cannot be performed because there is no available partition of the taxa");
+			first = false;
+			iQuit();
+			return null;
+		}
+		double[][] x = matrix.getMatrix(item);
+ 		ord=  new wPCAOrdination(x, part);
+		return ord;
+ 	}
+	/*.................................................................................................................*/
+    	public String getName() {
+		return "Within-group PCA"; //ERIC: this is the name that appears in menus
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Performs within-group principal components analysis on a continous-valued matrix." ;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*
+    	 public String getParameters() {
+   		if (ord==null)
+   			return null;
+   		else
+   			return "Within-group PCA\n"+ ord.report();
+   	 }
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/search/AddAndRearrange/AddAndRearrange.java b/Source/mesquite/search/AddAndRearrange/AddAndRearrange.java
new file mode 100644
index 0000000..77b4032
--- /dev/null
+++ b/Source/mesquite/search/AddAndRearrange/AddAndRearrange.java
@@ -0,0 +1,349 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.AddAndRearrange;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+/* ======================================================================== */
+public class AddAndRearrange extends TreeSearcher implements Incrementable {
+	public String getName() {
+		return "Mesquite Heuristic (Add & rearrange)";
+	}
+	public String getExplanation() {
+		return "Searches for optimal trees by adding taxa then rearranging the tree.";
+	}
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + "  needs a method to evaluate tree optimality.",
+		"The method to evaluate tree optimality can be selected initially");
+		EmployeeNeed ew = registerEmployeeNeed(TreeSwapper.class, getName() + "  needs a method to rearrange branches on the trees.",
+		"The method to rearrange branches can be selected initially");
+	}
+	/*.................................................................................................................*/
+	int currentTree=0;
+	NumberForTree treeValueTask;
+	static int numTrees = 1;
+	boolean minimize = true;
+	MesquiteString treeValueName;
+	TreeSwapper swapTask;
+	int MAXTREES = 100;
+	TreeOptimizer treeOptimizer;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeValueTask= (NumberForTree)hireEmployee(NumberForTree.class, "Criterion for tree search");
+		if (treeValueTask==null) return sorry(getName() + " couldn't start because no criterion-calculating module was obtained");
+		treeValueName = new MesquiteString(treeValueTask.getName());
+		minimize = !treeValueTask.biggerIsBetter();
+		swapTask = (TreeSwapper)hireEmployee(TreeSwapper.class, "Tree Rearranger");
+		if (swapTask==null)
+			return sorry(getName() + " couldn't start because no branch rearranger module was obtained");
+		if (!MesquiteThread.isScripting()){
+			int s = MesquiteInteger.queryInteger(containerOfModule(), "MAXTREES", "Maximum number of equally good trees to store during search (MAXTREES)", MAXTREES);
+			if (MesquiteInteger.isCombinable(s))
+				MAXTREES = s;
+			else
+				return false;
+		}
+		treeOptimizer = new TreeOptimizer(this,treeValueTask, swapTask);
+		addMenuItem("MAXTREES...", makeCommand("setMAXTREES",  this));
+		return true;
+		//TODO: if this is made to be persistent, need setHiringCommand for both
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCriterion " , treeValueTask);
+		temp.addLine("toggleMinimize " + minimize);
+		temp.addLine("setMAXTREES " + MAXTREES);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets criterion for tree search", "[name of module calculating objective function]", commandName, "setCriterion")) {
+			NumberForTree temp= (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Criterion for tree choice", treeValueTask);
+			if (temp!=null){
+				treeValueTask=  temp;
+				treeValueName.setValue(treeValueTask.getName());
+				minimize = !treeValueTask.biggerIsBetter();
+				parametersChanged(); //?
+				return treeValueTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum number of trees stored", "[number]", commandName, "setMAXTREES")) {
+			int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(s)){
+				s = MesquiteInteger.queryInteger(containerOfModule(), "MAXTREES", "Maximum number of equally good trees to store during search (MAXTREES)", MAXTREES);
+			}
+			if (MesquiteInteger.isCombinable(s)){
+				MAXTREES = s;
+				parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether or not the score is to minimized or maximized", "[on = minimize; off = maximize]", commandName, "toggleMinimize")) {
+			//TODO: use MesquiteBoolean checkmark
+			if (StringUtil.blank(arguments))
+				minimize = !minimize;
+			else {
+				String s = ParseUtil.getFirstToken(arguments, pos);
+				if ("on".equalsIgnoreCase(s))
+					minimize = true;
+				else if  ("off".equalsIgnoreCase(s))
+					minimize = false;
+			}
+			parametersChanged(); //?
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+		if (treeValueTask instanceof Incrementable)
+			((Incrementable)treeValueTask).setCurrent(i);
+	}
+	public long getCurrent(){
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).getCurrent();
+		return 0;
+	}
+	public String getItemTypeName(){
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).getItemTypeName();
+		return "";
+	} 
+	public long getMin(){
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).getMin();
+		return 0;
+	}
+	public long getMax(){
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).getMax();
+		return 0;
+	}
+	public long toInternal(long i){
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).toInternal(i);
+		return i-1;
+	}
+	public long toExternal(long i){ //return whether 0 based or 1 based counting
+		if (treeValueTask instanceof Incrementable)
+			return ((Incrementable)treeValueTask).toExternal(i);
+		return i+1;
+	}
+
+	/*.................................................................................................................*/
+	int whichNode = 0;
+	MesquiteNumber bestValue;
+
+	boolean better(MesquiteNumber value, MesquiteNumber bestValue){
+		return ((minimize && value.isLessThan(bestValue)) || (!minimize && value.isMoreThan(bestValue)));
+	}
+	boolean justAsGood(MesquiteNumber value, MesquiteNumber bestValue){
+		return ((minimize && !value.isMoreThan(bestValue)) || (!minimize && !value.isLessThan(bestValue)));
+	}
+	/*.................................................................................................................*/
+	private TreeVector getTrees(Taxa taxa) {
+		TreeVector trees = new TreeVector(taxa);
+		logln("Tree search: Adding taxa");
+		CommandRecord.tick("Tree Search in progress " );
+		bestValue = new MesquiteNumber(0);
+		ProgressIndicator progIndicator = new ProgressIndicator(getProject(),"Tree Search", "Tree Search in progress", 0, "Stop Search");
+		progIndicator.setButtonMode(ProgressIndicator.FLAG_AND_HIDE);
+		progIndicator.setText("Tree Search in progress ");
+		progIndicator.setTertiaryMessage(getParameters());
+		progIndicator.start();
+		Runtime rt = Runtime.getRuntime();
+		rt.gc();
+	
+		
+		treeOptimizer.setSwapTask(swapTask);
+		treeOptimizer.setNumberTask(treeValueTask);
+		treeOptimizer.setBiggerIsBetter(!minimize);
+		treeOptimizer.setProgIndicator(progIndicator);
+		treeOptimizer.setWriteToLog(true);
+		
+		MesquiteTree initialTree = treeOptimizer.getStepwiseAdditionTree(taxa);
+		
+//		public static MesquiteTree getStepwiseAdditionTree(Taxa taxa, NumberForTree treeValueTask, ProgressIndicator progIndicator, MesquiteModule module, boolean writeToLog, double defaultBranchLengths) {
+
+		treeValueTask.calculateNumber(initialTree, bestValue, null);
+
+/*		initialTree.setToDefaultBush(2, false);
+
+		//alternative: allow user to choose OneTreeSource for starting tree, instead of from addition sequence
+		MesquiteTree tempTree = initialTree.cloneTree();
+
+		for (int taxon = 2; taxon < taxa.getNumTaxa() && !progIndicator.isAborted(); taxon++) {
+			bestValue.setToUnassigned();
+			progIndicator.setSecondaryMessage("Adding taxon " + (taxon +1));
+			whichNode = 0;
+			MesquiteNumber value = new MesquiteNumber();
+			int numNodes = initialTree.getNumNodeSpaces();
+			for (int node = 0; node<numNodes && !progIndicator.isAborted(); node++) {   
+				if (initialTree.nodeInTree(node)) {
+					tempTree.setToClone(initialTree);
+					tempTree.graftTaxon(taxon, node, false);
+					value.setToUnassigned();
+					treeValueTask.calculateNumber(tempTree, value, null);
+					if (better(value,bestValue)) {
+						bestValue.setValue(value);
+						whichNode = node;
+					}
+				}
+			}
+			initialTree.graftTaxon(taxon, whichNode, false);
+			logln("   Tree search: " + taxon + " added.");
+		}
+		
+*/		
+		
+		trees.addElement(initialTree, false);
+		if (minimize)
+			initialTree.setName("Tree " + 1 + " from search (criterion: minimize " + treeValueTask.getName() + ")");
+		else
+			initialTree.setName("Tree " + 1 + " from search (criterion: maximimize " + treeValueTask.getName() + ")");
+
+		if (progIndicator.isAborted()) {
+			progIndicator.goAway();
+			return null;
+		}
+		logln("Tree search: About to swap.  Score = "+ bestValue.toString() + "  Rearranging tree using " + swapTask.getName());
+		String bestString = "Best tree found so far of score " + bestValue.toString();
+		boolean firstWarning = true;
+		long totalSwaps = 0;
+		if (swapTask!=null) {
+			CommandRecord rec = CommandRecord.getRecNSIfNull();
+			for (int swapTree = 0; swapTree< trees.size(); swapTree++){
+				MesquiteTree tree = (MesquiteTree)trees.getTree(swapTree);
+				MesquiteTree sTree = tree.cloneTree();
+				boolean better = true;
+				while (better&& !progIndicator.isAborted() && !rec.isCancelled()  && !isDoomed()) { 
+					better = false;
+					
+					long swaps = swapTask.numberOfRearrangements(tree);
+					MesquiteNumber value = new MesquiteNumber();
+					for (int i = 0; i<swaps && !better && !progIndicator.isAborted() && !rec.isCancelled(); i++) {
+						
+						progIndicator.setSecondaryMessage(bestString + ";  Now examining rearrangement #" + i + " of " + swaps + " on tree " + (swapTree + 1));
+						sTree.setToClone(tree);
+						swapTask.rearrange(sTree, i);
+
+						if (trees.indexOfByTopology(sTree, false)<0){ //new tree
+							totalSwaps++;
+							value.setToUnassigned();
+							treeValueTask.calculateNumber(sTree, value, null);
+							if (better(value, bestValue)) {
+								bestValue.setValue(value);
+								bestString = "Best tree found so far of score " + bestValue.toString();
+								logln("    Tree search: Better tree found, score = " + value.toString());
+								progIndicator.setSecondaryMessage("Better tree found, score = " + value.toString());
+								tree.setToClone(sTree);
+								trees.removeAllElements(false);
+								trees.addElement(tree, false);
+								if (minimize)
+									tree.setName("Tree " + 1 + " from search (criterion: minimize " + treeValueTask.getName() + ")");
+								else
+									tree.setName("Tree " + 1 + " from search (criterion: maximimize " + treeValueTask.getName() + ")");
+								better = true;
+								swapTree = 0;
+							}
+							else if(justAsGood(value, bestValue) && trees.size()<MAXTREES){
+								if (trees.size()>=MAXTREES){
+									if (firstWarning){
+										progIndicator.setTertiaryMessage("MAXTREES of " + MAXTREES + " hit in tree search.\n\n" + getParameters());
+										logln(" MAXTREES of " + MAXTREES + " hit in tree search.");
+									}
+									firstWarning = false;
+								}
+								else {
+									MesquiteTree sTree2 = sTree.cloneTree();
+									trees.addElement(sTree2, false);
+									bestString = Integer.toString(trees.size()) + " trees found so far of score " + bestValue.toString();
+									progIndicator.setSecondaryMessage("Equally good tree found, score = " + value.toString());
+									if (minimize)
+										sTree2.setName("Tree " + trees.size() + " from search (criterion: minimize " + treeValueTask.getName() + ")");
+									else
+										sTree2.setName("Tree " + trees.size() + " from search (criterion: maximimize " + treeValueTask.getName() + ")");
+									logln("    Tree search: Equally good tree found, total number of trees found = " + trees.size());
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		if (progIndicator.isAborted()) {
+			if (!AlertDialog.query(containerOfModule(), "Keep trees?", "Tree search stopped before rearranging complete.  Best tree found has score = " + bestValue.toString() + ".  Do you want to keep the trees?", "Keep", "Discard", 1))
+				return null;
+			//rename all trees//sn = "Tree from incomplete search";
+			for (int i = 0; i< trees.size(); i++){
+				MesquiteTree tree = (MesquiteTree)trees.getTree(i);
+				if (minimize)
+					tree.setName("Tree " + (i+1) + " from INCOMPLETE search (criterion: minimize " + treeValueTask.getName() + ")");
+				else
+					tree.setName("Tree " + (i+1) + " from INCOMPLETE search (criterion: maximimize " + treeValueTask.getName() + ")");
+			}
+		}
+		else {
+			logln("    Tree search: Swapping completed.  Best tree found has score = " + bestValue.toString() + ". Total number of rearrangements examined: " + totalSwaps);
+		}
+		if (progIndicator!=null)
+			progIndicator.goAway();
+		return trees;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public boolean initialize(Taxa taxa){
+		treeValueTask.initialize(taxa.getDefaultTree());
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void fillTreeBlock(TreeVector treeList){
+		if (treeList==null)
+			return;
+		Taxa taxa = treeList.getTaxa();
+		TreeVector trees = getTrees(taxa);
+		treeList.setName("Trees from Mesquite's heuristic search");
+		treeList.setAnnotation ("Parameters: "  + getParameters(), false);
+		if (trees!=null)
+			treeList.addElements(trees, false);
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (minimize)
+			return("Tree search criterion: minimize " + treeValueTask.getName());
+		else
+			return("Tree search criterion: maximimize " + treeValueTask.getName());
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
diff --git a/Source/mesquite/search/DistanceTreeSearch/DistanceTreeSearch.java b/Source/mesquite/search/DistanceTreeSearch/DistanceTreeSearch.java
new file mode 100644
index 0000000..2eb39ce
--- /dev/null
+++ b/Source/mesquite/search/DistanceTreeSearch/DistanceTreeSearch.java
@@ -0,0 +1,39 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.DistanceTreeSearch;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.search.lib.*;
+
+/* ======================================================================== */
+public class DistanceTreeSearch extends TreeSearch  {
+	public String getName() {
+		return "Distance Analysis";
+	}
+	public String getExplanation() {
+		return "Supplies trees resulting from a tree inference based upon distances.";
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return DistanceAnalysis.class;  
+	}
+
+}
+
diff --git a/Source/mesquite/search/LikelihoodTreeSearch/LikelihoodTreeSearch.java b/Source/mesquite/search/LikelihoodTreeSearch/LikelihoodTreeSearch.java
new file mode 100644
index 0000000..7ed20d1
--- /dev/null
+++ b/Source/mesquite/search/LikelihoodTreeSearch/LikelihoodTreeSearch.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.LikelihoodTreeSearch;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.search.lib.*;
+
+/* ======================================================================== */
+public class LikelihoodTreeSearch extends TreeSearch  {
+	public String getName() {
+		return "Likelihood Tree Inference";
+	}
+	public String getExplanation() {
+		return "Supplies trees resulting from a search for maximum likelihood trees.";
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return LikelihoodAnalysis.class;  
+	}
+
+}
+
diff --git a/Source/mesquite/search/NNIRearranger/NNIRearranger.java b/Source/mesquite/search/NNIRearranger/NNIRearranger.java
new file mode 100644
index 0000000..8a7818d
--- /dev/null
+++ b/Source/mesquite/search/NNIRearranger/NNIRearranger.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified: 25 Aug 01 (WPM) added "|| tree.hasPolytomies(tree.getRoot())" in check at start of rearrange().  NOTE: should allow polytomies
+ */
+package mesquite.search.NNIRearranger;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NNIRearranger extends TreeSwapper {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	public long numberOfRearrangements(AdjustableTree tree, int baseNode) {
+		if (tree.hasPolytomies(baseNode))
+			return 0; //TODO: need to deal better with polytomies, or give warning
+		else if (!tree.getRooted()){
+			int total = 2*tree.numberOfInternalsInClade(baseNode) - 2;
+			if (tree.nodeIsInternal(tree.firstDaughterOfNode(tree.getRoot())))
+					total -= 2;
+			if (tree.nodeIsInternal(tree.lastDaughterOfNode(tree.getRoot())))
+				total -= 2;
+			return total;
+		}
+		else
+			return 2*tree.numberOfInternalsInClade(baseNode) - 2; //root doesn't count, thus 2(n-1) rearrangements
+	}
+	/*.................................................................................................................*/
+	/** Returns the number of rearrangments.*/
+	public long numberOfRearrangements(AdjustableTree tree){
+		return numberOfRearrangements(tree, tree.getRoot());
+	}
+
+	/*.................................................................................................................*/
+	boolean availableNode(AdjustableTree tree, int N){
+		if (!tree.nodeIsInternal(N))
+			return false;
+		if (tree.getRooted())
+			return true;
+		return (tree.motherOfNode(N) != tree.getRoot());  //NNI rearrangements on daughter of root yield same unrooted tree
+	}
+	/*.................................................................................................................*/
+	int count = 0;
+
+	public  int findInternalInTraversal(AdjustableTree tree, int N, int target) {
+		if (tree.nodeIsInternal(N)){
+			if (availableNode(tree, N)){
+				if (count == target)
+					return N;
+				count++;
+			}
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				int found =  findInternalInTraversal(tree, d, target);
+				if (MesquiteInteger.isCombinable(found))
+					return found;
+			}
+		}
+		return MesquiteInteger.unassigned;
+	}
+	/*.................................................................................................................*/
+	/* TODO: currently this only works if baseNode = root */
+	/** Rearranges the tree to the i'th rearrangment. */
+	public void rearrange(AdjustableTree tree, int baseNode, long i) {
+		if (tree==null || i<0 || i>= numberOfRearrangements(tree, baseNode) || tree.hasPolytomies(baseNode))
+			return;
+
+		int numInTraversal = (int)(i/2 + 1); //rearrangements 0 & 1 are for node 1; 2 & 3 for node 2, etc.
+		count = 0;
+		int node = findInternalInTraversal(tree, baseNode, numInTraversal);
+		int nodeSister = tree.nextSisterOfNode(node);
+		if (nodeSister == 0)
+			nodeSister = tree.previousSisterOfNode(node);
+		if (nodeSister > 0) {
+			int left = tree.firstDaughterOfNode(node);
+			if (i%2 == 0){ //even rearrangment; use left descendant of node
+				tree.moveBranch(left, nodeSister, false);
+			}
+			else {
+				int right = tree.nextSisterOfNode(left);
+				tree.moveBranch(right, nodeSister, false);
+			}
+		}
+	}
+	public void rearrange(AdjustableTree tree, long i){
+		rearrange(tree,tree.getRoot(),i);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "NNI Rearranger";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Rearranges a tree by nearest neighbor interchange (NNI).  Does not handle trees with polytomies.";
+	}
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+
+
+}
+
diff --git a/Source/mesquite/search/OldStyleTreeSearch/OldStyleTreeSearch.java b/Source/mesquite/search/OldStyleTreeSearch/OldStyleTreeSearch.java
new file mode 100644
index 0000000..42828d8
--- /dev/null
+++ b/Source/mesquite/search/OldStyleTreeSearch/OldStyleTreeSearch.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.OldStyleTreeSearch;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.CharStatesForNodes;
+import mesquite.lib.duties.TreeSearcher;
+import mesquite.search.lib.*;
+
+/* ======================================================================== */
+public class OldStyleTreeSearch extends TreeSearch  {
+	public String getName() {
+		return "Tree Searchers (old arrangement)";
+	}
+	public String getNameForMenuItem() {
+			return "Tree Search";
+	}
+	public String getExplanation() {
+		return "Supplies trees resulting from tree searches.";
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return TreeSearcher.class;  
+	}
+	/*.................................................................................................................*/
+	public Class[] getDontHireSubchoice(){
+		return new Class[]{LikelihoodAnalysis.class, DistanceAnalysis.class, ParsimonyAnalysis.class, BayesianAnalysis.class};  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+			return true;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new OStyleCompatibilityTest();
+		}
+		
+	//This is treated as compatible only with installations in which there are no Zephyr 2 style modules, in which case this menu behaves in the old style
+	 class OStyleCompatibilityTest extends CompatibilityTest {  
+		public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (numModulesAvailable(LikelihoodAnalysis.class) + numModulesAvailable(DistanceAnalysis.class) + numModulesAvailable(ParsimonyAnalysis.class) + numModulesAvailable(BayesianAnalysis.class)==0);
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/search/OtherTreeSearch/OtherTreeSearch.java b/Source/mesquite/search/OtherTreeSearch/OtherTreeSearch.java
new file mode 100644
index 0000000..d93ee7e
--- /dev/null
+++ b/Source/mesquite/search/OtherTreeSearch/OtherTreeSearch.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.OtherTreeSearch;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.CharStatesForNodes;
+import mesquite.lib.duties.TreeSearcher;
+import mesquite.search.lib.*;
+
+/* ======================================================================== */
+public class OtherTreeSearch extends TreeSearch  {
+	public String getName() {
+		return "Other Tree Inference";
+	}
+	public String getNameForMenuItem() {
+			return "Other Tree Inference";
+	}
+	public String getExplanation() {
+		return "Supplies trees resulting from other criteria.";
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return TreeSearcher.class;  
+	}
+	/*.................................................................................................................*/
+	public Class[] getDontHireSubchoice(){
+		return new Class[]{LikelihoodAnalysis.class, DistanceAnalysis.class, ParsimonyAnalysis.class, BayesianAnalysis.class};  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+			return false;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		return new OTSCompatibilityTest();
+		}
+		
+	//This is treated as compatible only with installations in which there ARE Zephyr 2 style modules, in which case this menu behaves in the new style
+	 class OTSCompatibilityTest extends CompatibilityTest {
+		public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (numModulesAvailable(LikelihoodAnalysis.class) + numModulesAvailable(DistanceAnalysis.class) + numModulesAvailable(ParsimonyAnalysis.class) + numModulesAvailable(BayesianAnalysis.class)>1);
+		}
+	}
+
+}
+
diff --git a/Source/mesquite/search/ParsimonyTreeSearch/ParsimonyTreeSearch.java b/Source/mesquite/search/ParsimonyTreeSearch/ParsimonyTreeSearch.java
new file mode 100644
index 0000000..7ee2e63
--- /dev/null
+++ b/Source/mesquite/search/ParsimonyTreeSearch/ParsimonyTreeSearch.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.ParsimonyTreeSearch;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.search.lib.*;
+
+/* ======================================================================== */
+public class ParsimonyTreeSearch extends TreeSearch  {
+	public String getName() {
+		return "Parsimony Tree Inference";
+	}
+	public String getExplanation() {
+		return "Supplies trees resulting from a search for most parsimonious trees.";
+	}
+
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return ParsimonyAnalysis.class;  
+	}
+
+}
+
diff --git a/Source/mesquite/search/SPRRearranger/SPRRearranger.java b/Source/mesquite/search/SPRRearranger/SPRRearranger.java
new file mode 100644
index 0000000..ad78be7
--- /dev/null
+++ b/Source/mesquite/search/SPRRearranger/SPRRearranger.java
@@ -0,0 +1,205 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.search.SPRRearranger;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SPRRearranger extends TreeSwapper {
+	boolean nodeIsRoot = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+  	 
+	/*.................................................................................................................*
+	private void findAttach(AdjustableTree tree, int node, int whichNode, int cutNode, MesquiteInteger total, MesquiteInteger attach){
+		if (node == cutNode)
+			return;
+		if (tree.motherOfNode(cutNode)!=node && !tree.nodesAreSisters(cutNode, node))
+			total.increment();
+		if (total.getValue()==whichNode) {
+			attach.setValue(node);
+			return;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && attach.isUnassigned(); d = tree.nextSisterOfNode(d)) {
+			findAttach(tree, d, whichNode, cutNode, total, attach);
+		}
+	}
+	/*.................................................................................................................*
+	private void findBranchesOfRearrangement(AdjustableTree tree, int node,  MesquiteInteger total, int target, MesquiteInteger cut, MesquiteInteger attach, int numNodesTotal){
+		if (!cut.isUnassigned())
+			return;
+		int current = total.getValue();
+		if (tree.nodeIsTerminal(node)){
+			total.add(numNodesTotal-3); //TODO: -2 if node is polytomous
+			if (total.getValue()>=target) {
+				cut.setValue(node);
+				MesquiteInteger counter = new MesquiteInteger(0);
+				findAttach(tree, tree.getRoot(), target-current, node, counter, attach);
+			}
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && cut.isUnassigned(); d = tree.nextSisterOfNode(d)) {
+				findBranchesOfRearrangement(tree, d, total, target, cut, attach, numNodesTotal);
+			}
+			if (!cut.isUnassigned())
+				return;
+			total.add(numNodesTotal-tree.numberOfNodesInClade(node)-2);//TODO: -1 if node is polytomous
+			if (total.getValue()>=target) {
+				cut.setValue(node);
+				MesquiteInteger counter = new MesquiteInteger(-1);
+				findAttach(tree, tree.getRoot(), target-current, node, counter, attach);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** This method is more for insurance = it guarantees that the root is used if that is what is needed.  Will avoid problems if root node has its number changed. */
+	private int getBaseNode(AdjustableTree tree, int baseNode) {
+		if (nodeIsRoot)
+			return tree.getRoot();
+		else
+			return baseNode;
+	}
+	/*.................................................................................................................*/
+	/** finding the cut node for rearrangement # target, by checking total number of moves a branch can make*/
+	private void findCutNode(AdjustableTree tree,int baseNode,  int node,MesquiteInteger cut, MesquiteInteger whichMove, MesquiteLong total, long target){
+		if (!cut.isUnassigned())
+			return;
+		long currentCount = total.getValue();
+		total.add(numberOfMovesNodeCanMake(tree, getBaseNode(tree,baseNode), node));
+		if (currentCount<=target && total.getValue()>target) {
+			cut.setValue(node);
+			whichMove.setValue((int)(target-currentCount));
+			return;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && cut.isUnassigned(); d = tree.nextSisterOfNode(d)) {
+			findCutNode(tree, getBaseNode(tree,baseNode), d, cut, whichMove, total, target);
+		}
+	}
+	/*.................................................................................................................*/
+	/** finding the cut node for rearrangement # target, by checking total number of moves a branch can make*/
+	private void findAttachNode(AdjustableTree tree,int baseNode, int node,int cutNode,  MesquiteInteger attach, MesquiteLong total, long target){
+		if (!attach.isUnassigned())
+			return;
+		//seeing if valid attach node for given cutNode
+		if (node==cutNode) //don't even go into that clade
+			return;
+		int motherOfCut = tree.motherOfNode(cutNode);
+		if ((node!=motherOfCut && motherOfCut!=tree.motherOfNode(node)) || tree.nodeIsPolytomous(motherOfCut)) {
+			//can move only if not mother or sister, unless polytomous
+			//is a legitimate target; see if it's the index wanted
+			if (total.getValue() == target) {
+				attach.setValue(node);
+				return;
+			}
+			total.add(1);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && attach.isUnassigned(); d = tree.nextSisterOfNode(d)) {
+			findAttachNode(tree, getBaseNode(tree,baseNode), d, cutNode, attach, total, target);
+		}
+	}
+	/*.................................................................................................................*/
+	private void upCountTotal(AdjustableTree tree, int baseNode, int node,MesquiteLong total, int numNodesTotal){
+		total.add(numberOfMovesNodeCanMake(tree, getBaseNode(tree,baseNode), node));
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			upCountTotal(tree, getBaseNode(tree,baseNode), d, total, numNodesTotal);
+		}
+	}
+	
+	/*.................................................................................................................*/
+	/** Returns the number of moves a node can make.  Is number of nodes in the tree outside of its own clade (since node can't move into its own
+	clade) and, if its mother is dichotomous, minus 2 (if dichtomous, it can't move onto its own ancestor since it's already there, and 
+	it can move onto a sister only if it has more than one sister).*/
+	private long numberOfMovesNodeCanMake(AdjustableTree tree,int baseNode,  int node){
+		int root = getBaseNode(tree,baseNode);
+		if (!tree.nodeExists(node) || root==node)
+			return 0;
+		int numInClade = tree.numberOfNodesInClade(node);
+		int numInTree = tree.numberOfNodesInClade(root);
+		int mother = tree.motherOfNode(node);
+		if (!tree.nodeIsPolytomous(mother))
+			return numInTree-numInClade-2;
+		else
+			return numInTree-numInClade;
+	}
+	/* TODO: currently this only works if baseNode = root */
+	//  Bad things (e.g. thread death) can happen if baseNode != tree.getRoot(). J.C. Oliver 2013.
+	/** baseNode <strong>must</strong> be the root of {@code tree}.*/
+	public long numberOfRearrangements(AdjustableTree tree, int baseNode) {
+		nodeIsRoot = baseNode == tree.getRoot();
+		MesquiteLong counter = new MesquiteLong(0); 
+		upCountTotal(tree, baseNode, baseNode, counter, tree.numberOfNodesInClade(baseNode));
+		return counter.getValue();
+	}
+
+	/*.................................................................................................................*/
+	/** Returns the number of rearrangments.*/
+	public long numberOfRearrangements(AdjustableTree tree){
+		nodeIsRoot = true;
+		return numberOfRearrangements(tree, tree.getRoot());
+	}
+	int count = 0;
+	int rearrangement=0;
+	/*.................................................................................................................*/
+	/* TODO: currently this only works if baseNode = root */
+	/** Rearranges the tree to the i'th rearrangment. */
+	public void rearrange(AdjustableTree tree, int baseNode, long i) {
+		if (tree==null) // || i<0 || i> 2*tree.numberOfInternalsInClade(tree.getRoot())-1  //TODO: check to see that not out of bounds
+			return;
+		nodeIsRoot = baseNode == tree.getRoot();
+		count = 0;
+		MesquiteLong total = new MesquiteLong(0);
+		MesquiteInteger cut = new MesquiteInteger();
+		MesquiteInteger whichMove = new MesquiteInteger(0);
+		cut.setToUnassigned();
+		findCutNode(tree, baseNode,  baseNode, cut, whichMove,  total, i);
+		
+		MesquiteInteger attach = new MesquiteInteger();
+		attach.setToUnassigned();
+		total.setValue(0);
+		findAttachNode(tree, baseNode, baseNode,cut.getValue(),  attach, total, whichMove.getValue());
+		if (!cut.isUnassigned() && !attach.isUnassigned()) {
+			tree.moveBranch(cut.getValue(), attach.getValue(), false);
+		}
+	}
+	public void rearrange(AdjustableTree tree, long i){
+		nodeIsRoot = true;
+		rearrange(tree,tree.getRoot(),i);
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "SPR Rearranger";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Rearranges a tree by subtree pruning and regrafting (SPR).";
+   	 }
+   	 public boolean requestPrimaryChoice(){
+   	 	return true;
+   	 }
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+
+}
+
diff --git a/Source/mesquite/search/aSearchIntro/aSearchIntro.java b/Source/mesquite/search/aSearchIntro/aSearchIntro.java
new file mode 100644
index 0000000..9f63ccb
--- /dev/null
+++ b/Source/mesquite/search/aSearchIntro/aSearchIntro.java
@@ -0,0 +1,58 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.search.aSearchIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aSearchIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aSearchIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Coordinates simple searches for optimal trees.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree Search Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Tree Search Package";
+ 	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/search/explanation.txt b/Source/mesquite/search/explanation.txt
new file mode 100644
index 0000000..0ab613b
--- /dev/null
+++ b/Source/mesquite/search/explanation.txt
@@ -0,0 +1,2 @@
+Tree Search Package
+Provides a slow but generalized search engine for optimal trees.  Uses a simple heuristic search (addition sequence plus NNI or SPR rearrangments) to find trees optimal according to whatever criteria can be supplied by other modules.
diff --git a/Source/mesquite/search/lib/TreeSearch.java b/Source/mesquite/search/lib/TreeSearch.java
new file mode 100644
index 0000000..31ea6b7
--- /dev/null
+++ b/Source/mesquite/search/lib/TreeSearch.java
@@ -0,0 +1,195 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.search.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class TreeSearch extends TreeInferer implements Incrementable {
+	public String getExplanation() {
+		return "Supplies trees resulting from a search to optimize some value.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSearcher.class, getName() + "  needs a method to search for trees.",
+		"The method to search for trees can be selected initially");
+	}
+	/*.................................................................................................................*/
+	protected TreeSearcher searchTask;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (arguments !=null) {
+			searchTask = (TreeSearcher)hireNamedEmployee(TreeSearcher.class,arguments);
+			if (searchTask==null) {
+				return sorry(getName() + " couldn't start because the requested tree searching module not obtained");
+			}
+		}
+		else {
+			searchTask= (TreeSearcher)hireEmployee(TreeSearcher.class, "Tree Searcher");
+			if (searchTask==null) return sorry(getName() + " couldn't start because tree searching module not obtained.");
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public String getHTMLDescriptionOfStatus(){
+		if (searchTask != null){
+			return searchTask.getHTMLDescriptionOfStatus();
+		}
+		return getName();
+	}
+   	public Reconnectable getReconnectable(){
+   		if (searchTask instanceof Reconnectable)
+   			return (Reconnectable)searchTask;
+   		return null;
+   	}
+   	
+	 public String getExtraTreeWindowCommands (){
+		 if (searchTask!=null)
+			 return searchTask.getExtraTreeWindowCommands();
+		 else
+			 return "";
+   	 }
+	 
+	 public String getExtraIntermediateTreeWindowCommands (){
+		 if (searchTask!=null)
+			 return searchTask.getExtraIntermediateTreeWindowCommands();
+		 else
+			 return "";
+   	 }
+
+  
+   	 public boolean canGiveIntermediateResults(){
+   		 return searchTask.canGiveIntermediateResults();
+   	 }
+ 	public Tree getLatestTree(Taxa taxa, MesquiteNumber score, MesquiteString titleForWindow){
+   		return searchTask.getLatestTree(taxa, score, titleForWindow);
+   	 }
+
+	/*.................................................................................................................*/
+	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+		if (searchTask instanceof Incrementable)
+			((Incrementable)searchTask).setCurrent(i);
+	}
+	public long getCurrent(){
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).getCurrent();
+		return 0;
+	}
+	public String getItemTypeName(){
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).getItemTypeName();
+		return "";
+	}
+	public long getMin(){
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).getMin();
+		return 0;
+	}
+	public long getMax(){
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).getMax();
+		return 0;
+	}
+	public long toInternal(long i){
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).toInternal(i);
+		return i-1;
+	}
+	public long toExternal(long i){ //return whether 0 based or 1 based counting
+		if (searchTask instanceof Incrementable)
+			return ((Incrementable)searchTask).toExternal(i);
+		return i+1;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return TreeSearcher.class;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setSearcher " , searchTask);
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module performing the tree searching", "[name of module]", commandName, "setSearcher")) {
+			TreeSearcher temp= (TreeSearcher)replaceEmployee(TreeSearcher.class, arguments, "Tree Searcher", searchTask);
+			if (temp!=null){
+				searchTask=  temp;
+				parametersChanged(); //?
+			}
+			return searchTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		searchTask.initialize(taxa);
+		searchTask.setTreeInferer(this);
+
+	}
+	/*.................................................................................................................*/
+	public void fillTreeBlock(TreeVector treeList, int numberIfUnlimited){
+		//DISCONNECTABLE
+		searchTask.setTreeInferer(this);
+		searchTask.fillTreeBlock(treeList);
+	}
+	/*.................................................................................................................*/
+	public void retrieveTreeBlock(TreeVector treeList, int numberIfUnlimited){
+		if (searchTask instanceof CanRetrieveTreeBlock)
+			((CanRetrieveTreeBlock)searchTask).retrieveTreeBlock(treeList);
+	}
+/*.................................................................................................................*/
+	public String getParameters() {
+		if (searchTask==null)
+			return("");
+		else
+			return "Searcher: " + searchTask.getName();
+	}
+	/*.................................................................................................................*/
+	public boolean hasLimitedTrees(Taxa taxa){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+
+}
+
diff --git a/Source/mesquite/stochchar/AsymmMkExplorer/AsymmMkExplorer.java b/Source/mesquite/stochchar/AsymmMkExplorer/AsymmMkExplorer.java
new file mode 100644
index 0000000..0ad7398
--- /dev/null
+++ b/Source/mesquite/stochchar/AsymmMkExplorer/AsymmMkExplorer.java
@@ -0,0 +1,238 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.AsymmMkExplorer;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.AsymmModel;
+import mesquite.stochchar.lib.MargLikelihoodForModel;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+public class AsymmMkExplorer extends TreeWindowAssistantOA implements ParametersExplorable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.stochchar.zMargLikeCateg.zMargLikeCateg.class, getName() + "  needs a module to calculate likelihoods.",
+		"The module to calculate likelihoods is arranged automatically");
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	//Vector traces;
+	CharSourceCoordObed characterSourceTask;
+	ParametersExplorer explorer;
+	int currentChar = 0;
+	Taxa taxa;
+	MargLikelihoodForModel likelihoodTask = null;
+	MesquiteBoolean showAsRateBias = new MesquiteBoolean(true);
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		//traces = new Vector();
+		explorer = (ParametersExplorer)hireEmployee(ParametersExplorer.class, "Parameters explorer");
+		if (explorer == null)
+			return sorry(getName() + " couldn't start because no parameters explorer module was obtained.");
+		likelihoodTask = (MargLikelihoodForModel)hireNamedEmployee(MargLikelihoodForModel.class, "#zMargLikeCateg");
+		if (likelihoodTask == null)
+			return sorry(getName() + " couldn't start because no likelihood calculator obtained");
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, new RequiresExactlyCategoricalData(), "Source of characters (for " + getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		explorer.addCheckMenuItem( null, "Use Rate-Bias Notation", makeCommand("toggleRateBias",  this), showAsRateBias);
+		explorer.addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		explorer.addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		explorer.addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		resetContainingMenuBar();
+		if (!MesquiteThread.isScripting()){
+			currentChar = characterSourceTask.queryUserChoose(taxa, "Choose character for likelihood surface exploration");
+			if (currentChar <0 || !MesquiteInteger.isCombinable(currentChar))
+				currentChar = 0;
+		}
+		asymmModel = new AsymmModel("Estimating Asymm", CategoricalState.class);
+		asymmModel.setUseRateBiasNotation(true);
+
+		param0 = new MesquiteParameter("Rate", "Rate of state change", MesquiteDouble.unassigned, 0, MesquiteDouble.infinite, 0.000, 0.1);
+		param1 = new MesquiteParameter("Bias", "Bias of gains (0 to 1) versus loses (1 to 0)", MesquiteDouble.unassigned, 0, MesquiteDouble.infinite, 0.1, 10.0);
+		parameters = new MesquiteParameter[]{param0, param1};
+		explorer.setExplorable(this);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		iQuit();
+	}
+
+	
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		temp.addLine("toggleRateBias " + showAsRateBias.toOffOnString());
+		return temp;
+	}
+	boolean suspendCommandReceived = false;
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "toggleRateBias")) {
+			showAsRateBias.toggleValue(parser.getFirstToken(arguments));
+			setNotation(showAsRateBias.getValue());
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+			if (currentChar>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentChar--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentChar = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+
+		doCalculations(true);
+	}
+	AsymmModel asymmModel;
+	MesquiteParameter param0, param1;
+	MesquiteParameter[] parameters;
+	Tree tree;
+	boolean useRateBias = true;;
+	CharacterDistribution observedStates;
+	MesquiteNumber likelihood = new MesquiteNumber();
+	void setNotation(boolean useRateBias){
+		if (this.useRateBias == useRateBias)
+			return;
+		if (useRateBias){
+			param0.setName("Rate");
+			param0.setExplanation("Rate of state change");
+			param1.setName("Bias");
+			param1.setExplanation("Bias of gains (0 to 1) versus loses (1 to 0)");
+		}
+		else {
+			param0.setName("Forward Rate");
+			param0.setExplanation("Rate of 0 to 1 change");
+			param1.setName("Backward Rate");
+			param1.setExplanation("Rate of 1 to 0 change");
+		}
+		asymmModel.setUseRateBiasNotation(useRateBias);
+		this.useRateBias = useRateBias;
+	}
+	/*.................................................................................................................*/
+	public  void setTree(Tree tree){
+		taxa = tree.getTaxa();
+		this.tree = tree;
+		doCalculations(true);
+
+	}
+	public MesquiteParameter[] getExplorableParameters(){
+		return parameters;
+	}
+
+	public double calculate(MesquiteString resultString){
+		asymmModel.deassignParameters();
+		asymmModel.setParam0(param0.getValue());
+		asymmModel.setParam1(param1.getValue());
+		likelihoodTask.calculateLogProbability( tree,  observedStates, asymmModel, resultString, likelihood);
+		return likelihood.getDoubleValue();
+	}
+	public void restoreAfterExploration(){
+	}
+
+	MesquiteString resultString = new MesquiteString();
+	/*.................................................................................................................*/
+	public void doCalculations(boolean doPreps) {
+		observedStates = characterSourceTask.getCharacter(tree, currentChar);
+		explorer.explorableChanged(this);
+	}
+
+
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		setModuleWindow(null);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Likelihood Surface AsymmMk Model";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Shows the likelihood surface for the AsymmMk Model.";
+	}
+}
+
diff --git a/Source/mesquite/stochchar/AsymmModelCurator/AsymmModelCurator.java b/Source/mesquite/stochchar/AsymmModelCurator/AsymmModelCurator.java
new file mode 100644
index 0000000..8799713
--- /dev/null
+++ b/Source/mesquite/stochchar/AsymmModelCurator/AsymmModelCurator.java
@@ -0,0 +1,275 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.AsymmModelCurator;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+/* ======================================================================== */
+public class AsymmModelCurator extends CategProbModelCurator  implements EditingCurator, CuratorWithSettings {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		
+		 EmployeeNeed e = registerEmployeeNeed(WindowHolder.class, getName() + " needs assistance to hold a window" ,
+				 "This is arranged automatically");
+	}
+	MesquiteBoolean rbNotation; //, flatPrior;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		rbNotation = new MesquiteBoolean(true);
+	//	flatPrior = new MesquiteBoolean(false);
+		return true;
+  	 }
+  	 public void endJob(){
+		if (getProject()!=null && getProject().getCentralModelListener() !=null)
+			getProject().getCentralModelListener().removeListener(this);
+  	 	super.endJob();
+  	 }
+  	 
+  	 public boolean isPrerelease(){
+  		 return true;
+  	 }
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			int mode = MesquiteInteger.fromString(prefs[0]);
+			if (MesquiteInteger.isCombinable(mode))
+				AsymmModel.optimizationMode = mode;
+		}
+	}
+	
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "optimizationMode", AsymmModel.optimizationMode);   
+		return buffer.toString();
+	}
+	
+	public void processSingleXMLPreference (String tag, String content) {
+		 if ("optimizationMode".equalsIgnoreCase(tag))
+			AsymmModel.optimizationMode = MesquiteInteger.fromString(content);
+	}
+
+	
+	/*.................................................................................................................*/
+  	 public void projectEstablished(){
+		getProject().getCentralModelListener().addListener(this);
+		 AsymmModel model;
+ 		model = new AsymmModel("Asymm. 2 param. (estimate)", CategoricalState.class);
+    		model.setBuiltIn(true);
+    		model.addToFile(null, getProject(), null);
+    		super.projectEstablished();
+  	 }
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof AsymmModel){
+	 		AsymmModel model = (AsymmModel)obj;
+	 		int i = getModelNumber(model);
+	 		if (i>=0) {
+	 			AsymmModelEditor dsw = (AsymmModelEditor)getWindow(i);
+	 			if (dsw==null)
+	 				return;
+	 			
+	 			dsw.setAllowEstimation(model instanceof CModelEstimator);
+				if (!model.getUseRateBiasNotation()){
+					dsw.setText(1, "Forward");
+					dsw.setText(2, "Backward");
+				}
+				else {
+					dsw.setText(1, "Bias");
+					dsw.setText(2, "Rate");
+				}
+				dsw.setUseEquil(model.getUseEquilFreqAsPrior());
+				dsw.setValue(1, model.getParam1());
+				dsw.setValue(2, model.getParam0());
+	 		}
+		}
+		super.changed(caller, obj, notification);
+	}
+	public void editSettings(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog settingsDialog = new ExtensibleDialog(containerOfModule(), "AsymmMk Optimization Settings",  buttonPressed);
+		settingsDialog.addLargeOrSmallTextLabel("Settings for optimizing parameters in " + getName() + ". These settings are used when both parameters of the model are unspecified and need to be estimated.");
+		RadioButtons rb = settingsDialog.addRadioButtons(new String[]{"Use estimated rate from Mk1 model as basis","Try even and two asymmetries","Try both of the above (Mk1 plus even and two asymmetries)"}, AsymmModel.optimizationMode);
+		settingsDialog.completeAndShowDialog(true);
+		boolean ok = (settingsDialog.query()==0);
+		
+		if (ok) {
+			AsymmModel.optimizationMode = rb.getValue();
+			
+		}
+		
+		settingsDialog.dispose();
+		if (ok)
+			CentralModelListener.staticChanged(this, AsymmModel.class, new Notification());
+
+	 	storePreferences();
+	}
+   
+	/*.................................................................................................................*/
+   	public MesquiteModule editModelNonModal(CharacterModel model, ObjectContainer w){
+		if (model!=null && model instanceof AsymmModel) {
+	   		AsymmModel modelToEdit =  ((AsymmModel)model);
+			String param0Name, param1Name;
+			if (modelToEdit.getUseRateBiasNotation()) {
+				param0Name = "Rate";
+				param1Name = "Bias";
+				rbNotation.setValue(true);
+			}
+			else {
+				param0Name = "Backward";
+				param1Name = "Forward";
+				rbNotation.setValue(false);
+			}
+			MesquiteModule windowServer = hireNamedEmployee(WindowHolder.class, "#WindowBabysitter");
+			if (windowServer == null)
+				return null;
+			
+			AsymmModelEditor dsw = new AsymmModelEditor(windowServer, "Edit model " + modelToEdit.getName(), param1Name, makeCommand("setParam1", modelToEdit), modelToEdit.getParam1(), 0, MesquiteDouble.infinite, 0, 1, param0Name, makeCommand("setParam0", modelToEdit), modelToEdit.getParam0(), 0, MesquiteDouble.infinite, 0, 1); 
+			dsw.setPrior(modelToEdit.getUseEquilFreqAsPrior(), makeCommand("toggleEquilibPrior", modelToEdit));
+			dsw.setAllowEstimation(modelToEdit instanceof CModelEstimator);
+			dsw.useExponentialScale(true);
+			windowServer.makeMenu("AsymmMk_Model");
+		//	windowServer.addCheckMenuItem(null, "Use Flat Prior", makeCommand("toggleEquilibPrior",  (Commandable)modelToEdit), flatPrior);
+		//	flatPrior.setValue(!modelToEdit.getUseEquilFreqAsPrior());
+			windowServer.addCheckMenuItem(null, "Use Rate-Bias Notation", makeCommand("toggleNotation",  (Commandable)modelToEdit), rbNotation);
+		//as of 1. 1, can be binary only	windowServer.addMenuItem("Set Maximum Allowed State...", makeCommand("setMaxState",  modelToEdit));
+			MesquiteWindow.centerWindow(dsw);
+			if (w!=null)
+				w.setObject(dsw);
+			
+			return windowServer;
+		}
+		return null;
+   	}
+	/*.................................................................................................................*/
+ 		/*if (modal && false){
+			MesquiteDouble r = new MesquiteDouble(modelToEdit.getParam0());
+			MesquiteDouble b = new MesquiteDouble(modelToEdit.getParam1());
+			if (MesquiteDouble.queryTwoDoubles(containerOfModule(), "Asymmetrical model", "Set " + param0Name, r, "Set " + param1Name, b)){
+				if (r.getValue()>0 && b.getValue()>0) {
+					modelToEdit.setParam0(r.getValue());
+					modelToEdit.setParam1(b.getValue());
+				}
+			}
+		}
+		 */
+		
+	public boolean curatesModelClass(Class modelClass){
+		return AsymmModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Asymmetrical 2-param. Markov-k Model";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "AsymmMk";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return AsymmModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		AsymmModel model = new AsymmModel(name, CategoricalState.class);
+ 		model.setMaxStateDefined(1);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		AsymmModel model = new AsymmModel( name, CategoricalState.class);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Asymmetrical 2-param. Markov-k Model";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains simple Markov k-state asymmetrical 2-parameter stochastic models of character evolution." ;
+   	 }
+ 	
+ 	
+}
+
+class AsymmModelEditor extends DoubleSliderWindow implements ItemListener {
+	Checkbox useEquilFreq,useFlat;
+	CheckboxGroup cbg;
+	MesquiteCommand setPriorCommand;
+	Label label;
+	int topLabel = 100;
+	public AsymmModelEditor(MesquiteModule module, String title, String name1, MesquiteCommand command1, double initialValue1, double min1, double max1,  double minSweet1, double maxSweet1, String name2, MesquiteCommand command2, double initialValue2, double min2, double max2, double minSweet2, double maxSweet2) {
+		super(module, title, name1, command1, initialValue1, min1, max1,   minSweet1,  maxSweet1,  name2,  command2,  initialValue2,  min2,  max2,  minSweet2,  maxSweet2);
+		cbg = new CheckboxGroup();
+		label = new Label("Calculate Likelihoods and Simulate assuming:");
+		addToWindow(label);
+		addToWindow(useEquilFreq = new Checkbox("Root State Frequencies same as Equilibrium", cbg, false));
+		addToWindow(useFlat = new Checkbox("Root State Frequencies Equal", cbg, true));
+		topLabel = getHeight() - 94;
+		sliderArea.setBounds(0, 10, getBounds().width, topLabel - 10);
+		label.setBounds(0, topLabel, getBounds().width, 24);
+		useEquilFreq.setBounds(10, topLabel + 24, getBounds().width, 30);
+		useEquilFreq.addItemListener(this);
+		useFlat.setBounds(10, topLabel + 54, getBounds().width, 30);
+		useFlat.addItemListener(this);
+	//	useEquilFreq.setBackground(Color.green);
+	}
+	
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		topLabel = getHeight() - 94;
+		if (sliderArea != null) {
+			sliderArea.setBounds(0, 10, getBounds().width, topLabel - 10);
+			label.setBounds(10, topLabel, getBounds().width, 20);
+			useEquilFreq.setBounds(16, topLabel + 16, getBounds().width, 24);
+			useFlat.setBounds(16, topLabel + 42, getBounds().width, 24);
+		}
+	}
+	void setPrior(boolean useEquil, MesquiteCommand setPriorCommand){
+		useEquilFreq.setState(useEquil);
+		this.setPriorCommand= setPriorCommand;
+	}
+	void setUseEquil(boolean useEquil){
+		useEquilFreq.setState(useEquil);
+	}
+
+	public void itemStateChanged(ItemEvent e){
+		if (setPriorCommand == null)
+			return;
+		if (e.getSource() == useEquilFreq){
+			if (useEquilFreq.getState())
+				setPriorCommand.doItMainThread("on", null, this);
+			else
+				setPriorCommand.doItMainThread("off", null, this);
+		}
+		else if (e.getSource() == useFlat){
+			if (useFlat.getState())
+				setPriorCommand.doItMainThread("off", null, this);
+			else
+				setPriorCommand.doItMainThread("on", null, this);
+		}
+	}
+}
+
diff --git a/Source/mesquite/stochchar/AsymmetryLR/AsymmetryLR.java b/Source/mesquite/stochchar/AsymmetryLR/AsymmetryLR.java
new file mode 100644
index 0000000..062312d
--- /dev/null
+++ b/Source/mesquite/stochchar/AsymmetryLR/AsymmetryLR.java
@@ -0,0 +1,158 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.AsymmetryLR;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+import mesquite.categ.lib.*;
+import JSci.maths.statistics.ChiSqrDistribution;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public class AsymmetryLR extends NumberForCharAndTree  {
+	   ChiSqrDistribution chiSquare;
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.stochchar.zMargLikeCateg.zMargLikeCateg.class, getName() + "  needs a module to calculate likelihoods.",
+		"The module to calculate likelihoods is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	MargLikelihoodForModel reconstructTask = null;
+	AsymmModel asymmModel;
+	MkModel mk1Model;
+	MesquiteNumber likelihood = new MesquiteNumber();
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		reconstructTask = (MargLikelihoodForModel)hireNamedEmployee(MargLikelihoodForModel.class, "#zMargLikeCateg");
+ 		if (reconstructTask == null)
+ 			return sorry(getName() + " couldn't start because no likelihood calculator obtained");
+ 		asymmModel = new AsymmModel("Estimating Asymm", CategoricalState.class);
+ 		mk1Model = new MkModel("Estimating mk1", CategoricalState.class);
+		getProject().getCentralModelListener().addListener(this);
+		chiSquare = new ChiSqrDistribution(1);
+ 		return true; 
+ 	}
+ 	
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj instanceof Class && (MkModel.class.isAssignableFrom((Class)obj) || AsymmModel.class.isAssignableFrom((Class)obj))) {
+				parametersChanged(notification);
+		}
+	}
+ 	
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree, CharacterDistribution charStates){
+   	}
+	MesquiteString resultStringMk1 = new MesquiteString();
+	MesquiteString resultStringAsymmMk = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree==null || observedStates==null) {
+			if (resultString!=null)
+				resultString.setValue("Likelihood ratio unassigned because no tree or no character supplied");
+			return;
+		}
+	
+
+		if (reconstructTask != null) {
+			asymmModel.deassignParameters();
+			mk1Model.deassignParameters();
+			reconstructTask.calculateLogProbability( tree,  observedStates, mk1Model, resultStringMk1, likelihood);
+			result.setValue(likelihood);
+			reconstructTask.calculateLogProbability( tree,  observedStates, asymmModel, resultStringAsymmMk, likelihood);
+			result.subtract(likelihood);
+			likelihood.setValue(2.0);
+			result.multiplyBy(likelihood);
+			likelihood.setValue(result);
+			if (resultString!=null) {
+				if (result.isCombinable() && !result.isNegative()) {
+					String p = " [Assuming chi-square 1 d.f., p = " + MesquiteDouble.toStringDigitsSpecified(1.0-chiSquare.cumulative(result.getDoubleValue()), 4) + "]";
+				/*	double d = result.getDoubleValue();
+					if (d <2.706)
+						p+= "> 0.10";
+					else if (d < 3.841)
+						p+= "< 0.10";
+					else if (d < 5.024)
+						p+= "< 0.05";
+					else if (d < 6.635)
+						p+= "< 0.01";
+					else if (d < 7.879)
+						p+= "<0.005";
+					else 
+						p+= "< 0.001";
+						*/
+					resultString.setValue("2*ln(likelihood ratio) of asymmetrical vs. symmetrical model: " + result + p);
+				}
+				else
+					resultString.setValue("Problem calculating likelihood ratio.  Details from symmetrical calculation: " + resultStringMk1.getValue() + " Details from asymmetrical calculation     " + resultStringAsymmMk.getValue());
+			}
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Asymmetry 2ln(LR)";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Asymmetry Likelihood Ratio Test";
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+ 	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the test statistic for the likelihood ratio test comparing the asymmetrical and one parameter models [2ln(L(Asymm.)/L(Mk1)], on a tree for a given character." ;
+   	 }
+  	 
+ 	public String getParameters(){
+   		if (asymmModel !=null)
+   			return " AsymmMk Model settings: " +  asymmModel.getSettingsString();
+   		return null;
+   	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+
+}  
+
diff --git a/Source/mesquite/stochchar/Brownian/Brownian.java b/Source/mesquite/stochchar/Brownian/Brownian.java
new file mode 100644
index 0000000..81ad1f7
--- /dev/null
+++ b/Source/mesquite/stochchar/Brownian/Brownian.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.Brownian;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class Brownian extends WholeCharModelCurator implements EditingCurator  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		 EmployeeNeed e = registerEmployeeNeed(WindowHolder.class, getName() + " needs assistance to hold a window" ,
+				 "This is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	
+  	 public void projectEstablished(){
+ 		BrownianMotionModel brownianModel = new BrownianMotionModel("Brownian default", ContinuousState.class);
+    		brownianModel.setRate(1.0);
+    		brownianModel.setBuiltIn(true);
+    		brownianModel.addToFile(null, getProject(), null);
+		ContinuousData.registerDefaultModel("Likelihood", "Brownian default");
+    		super.projectEstablished();
+  	 }
+	/*.................................................................................................................*/
+   	public MesquiteModule editModelNonModal(CharacterModel model, ObjectContainer w){
+		if (model!=null && model instanceof BrownianMotionModel) {
+	   		BrownianMotionModel modelToEdit =  ((BrownianMotionModel)model);
+			double a = modelToEdit.getRate();
+			MesquiteModule windowServer = hireNamedEmployee(WindowHolder.class, "#WindowBabysitter");
+			if (windowServer == null)
+				return null;
+			SliderWindow sw = new SliderWindow(windowServer, "Edit model", "Model \"" + modelToEdit.getName() + "\"", makeCommand("setRate", modelToEdit), modelToEdit.getRate(),0.0, MesquiteDouble.infinite, 1.0, 5.0);  //MesquiteDouble.infinite
+			sw.setAllowEstimation(modelToEdit instanceof CModelEstimator);
+			windowServer.makeMenu("Brownian");
+			MesquiteWindow.centerWindow(sw);
+			if (w!=null)
+				w.setObject(sw);
+			return windowServer;
+		}
+		return null;
+   	}
+   	
+   	
+   	
+			/*if (modal){
+				a = MesquiteDouble.queryDouble(containerOfModule(), "Jukes Cantor rate", "Set rate of Jukes Cantor model", a);
+				modelToEdit.setRate(a);
+			}
+			else */
+
+	/*.................................................................................................................*/
+	public boolean curatesModelClass(Class modelClass){
+		return BrownianMotionModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Brownian Motion";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "Brownian";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return BrownianMotionModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		BrownianMotionModel brownianModel = new BrownianMotionModel(name, ContinuousState.class);
+    		brownianModel.setRate(1.0);
+       		return brownianModel;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		BrownianMotionModel brownianModel = new BrownianMotionModel(name, ContinuousState.class);
+   		ParseUtil.getToken(description, stringPos);
+   		double a =  MesquiteDouble.fromString(ParseUtil.getToken(description, stringPos));
+ 		if (a>=0 && MesquiteDouble.isCombinable(a)) {
+ 			brownianModel.setRate(a);
+ 		}
+  		return brownianModel;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Brownian Model";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Brownian Model...";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Initializes Brownian motion character model for likelihood and other probability calculations." ;
+   	 }
+}
+
+
+
+
diff --git a/Source/mesquite/stochchar/CharLikelihood/CharLikelihood.java b/Source/mesquite/stochchar/CharLikelihood/CharLikelihood.java
new file mode 100644
index 0000000..95d425c
--- /dev/null
+++ b/Source/mesquite/stochchar/CharLikelihood/CharLikelihood.java
@@ -0,0 +1,206 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.CharLikelihood;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+import mesquite.stochchar.CurrentProbModels.*;
+
+/* ======================================================================== */
+public class CharLikelihood extends CharacterLikelihood {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ProbModelSourceLike.class, getName() + " needs an indication of what probabilistic model to apply to the character.",
+		"The indicator of probabilistic models can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(MargLikelihoodForModel.class, getName() + "  needs methods to calculate likelihoods.",
+		"The methods to calculate likelihoods are chosen automatically according to the probability model used in the calculation");
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	MesquiteNumber likelihood;
+	ProbModelSourceLike modelTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(MargLikelihoodForModel.class);
+		modelTask = (ProbModelSourceLike)hireEmployee(ProbModelSourceLike.class, "Source of probability models (for Character Likelihood)");
+		if (modelTask == null)
+			return sorry(getName() + " couldn't start because no source of models of character evolution obtained");
+		likelihood = new MesquiteNumber();
+		getProject().getCentralModelListener().addListener(this);//to listen for changes to model or static changes to class of current model
+		return true; //TODO: false if no appropriate employees!
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+	}
+	public void changed(Object caller, Object obj, Notification notification) { //this is a suboptimal way to do this; should it be responsibility of modelTask????
+		if (obj instanceof ProbabilityModel) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModelSource ",modelTask);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to supply character models", "[name of module]", commandName, "setModelSource")) {
+			ProbModelSourceLike temp=  (ProbModelSourceLike)replaceEmployee(ProbModelSourceLike.class, arguments, "Source of probability character models", modelTask);
+			if (temp!=null) {
+				modelTask= temp;
+				parametersChanged();
+			}
+			return modelTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == modelTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void initialize(Tree tree, CharacterDistribution observedStates){
+	}
+	boolean warned = false;
+	boolean warnedNoCalc = false;
+	CharacterData oldData = null;
+	MargLikelihoodForModel reconstructTask = null;
+	/*.................................................................................................................*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (tree==null || observedStates==null) {
+			if (resultString!=null)
+				resultString.setValue("Log Likelihood unassigned");
+			return;
+		}
+
+		result.setToUnassigned();
+		this.observedStates = observedStates;
+
+		//a barrier (temporary) while likelihood calculations support only simple categorical
+		Class stateClass = observedStates.getStateClass();
+		if (DNAState.class.isAssignableFrom(stateClass) || ProteinState.class.isAssignableFrom(stateClass) || ContinuousState.class.isAssignableFrom(stateClass)) {
+			String s = "Likelihood calculations cannot be performed ";
+			if (DNAState.class.isAssignableFrom(stateClass))
+				s += "currently with DNA or RNA data.  The calculations were not done.";
+			else if (ProteinState.class.isAssignableFrom(stateClass))
+				s += "currently with protein data.  The calculations were not done.";
+			else if (ContinuousState.class.isAssignableFrom(stateClass))
+				s += "currently with continuous valued data.  The calculations were not done.";
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return;
+		}
+
+		CharacterModel model = modelTask.getCharacterModel(observedStates);
+
+		if (model == null){
+			if (observedStates.getParentData()!= oldData)
+				warned = false;
+			if (!warned){
+				if (observedStates.getParentData()!=null && modelTask instanceof CurrentProbModels  && !MesquiteThread.isScripting()) {
+					oldData = observedStates.getParentData();
+					if (AlertDialog.query(containerOfModule(), "Assign models?", "There are currently no probability models assigned to the characters.  Do you want to assign a model to all characters unassigned?")) {
+						((CurrentProbModels)modelTask).chooseAndFillUnassignedCharacters(observedStates.getParentData());
+						model = modelTask.getCharacterModel(observedStates);
+					}
+					else {
+					}
+				}
+				else {
+					if (resultString!=null)
+						resultString.setValue("Likelihood calculations cannot be accomplished because no probabilistic model of evolution is available for the character");
+					discreetAlert( "Sorry, there is no probabilistic model of evolution available for the character; Char. likelihood cannot be calculated.");
+				}
+			}
+			warned = true;
+		}
+
+
+		if (reconstructTask == null || !reconstructTask.compatibleWithContext(model, observedStates)) { 
+			reconstructTask = null;
+			for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof MargLikelihoodForModel)
+					if (((MargLikelihoodForModel)e).compatibleWithContext(model, observedStates))
+						reconstructTask=(MargLikelihoodForModel)e;
+			}
+		}
+		if (reconstructTask != null) {
+			reconstructTask.calculateLogProbability( tree,  observedStates, model, resultString, likelihood);
+			result.setValue(likelihood);
+			result.copyAuxiliaries(likelihood.getAuxiliaries());
+			result.setName("-lnLikelihood");
+		}
+		else {
+			String s = "Likelihood calculations cannot be performed because no module was found to perform the calculations for the probability model \"" + model.getName() + "\" with the characters specified.";
+
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public boolean returnsMultipleValues(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		return "Char. -ln Likelihood";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Character Likelihood";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the negative log likelihood of a tree for a given character." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/stochchar/CharListProbModels/CharListProbModels.java b/Source/mesquite/stochchar/CharListProbModels/CharListProbModels.java
new file mode 100644
index 0000000..9c7163c
--- /dev/null
+++ b/Source/mesquite/stochchar/CharListProbModels/CharListProbModels.java
@@ -0,0 +1,215 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.CharListProbModels;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+import mesquite.stochchar.lib.*;
+
+
+/* ======================================================================== */
+public class CharListProbModels extends CharListAssistant implements MesquiteListener {
+	CharacterData data=null;
+	MesquiteTable table=null;
+	MesquiteSubmenuSpec mss;
+	MesquiteMenuItemSpec mScs, mStc, mRssc, mLine;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+  	 }
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof ProbabilityModel) {
+				parametersChanged();
+		}
+	}
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the probability model of the selected characters", "[number of model]", commandName, "setModel")) {
+    	 		if (table !=null && data!=null) {
+    	 			boolean changed=false;
+	      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+	      			if (!MesquiteInteger.isCombinable(whichModel))
+	      				return null;
+   	 			CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(ProbabilityModel.class, data.getStateClass()), whichModel); //TODO: would be better if passed name of model
+    	 			if (model != null) {
+					ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(ProbabilityModelSet.class);
+	    	 			if (modelSet == null) {
+				 		CharacterModel defaultModel =  data.getDefaultModel("Likelihood");
+				 		modelSet= new ProbabilityModelSet("Probability Model Set", data.getNumChars(), defaultModel, data);
+				 		modelSet.addToFile(data.getFile(), getProject(), findElementManager(ProbabilityModelSet.class)); //THIS
+						data.setCurrentSpecsSet(modelSet, ProbabilityModelSet.class);
+	    	 			}
+	    	 			if (modelSet != null) {
+	    	 				if (employer!=null && employer instanceof ListModule) {
+	    	 					int c = ((ListModule)employer).getMyColumn(this);
+		    	 				for (int i=0; i<data.getNumChars(); i++) {
+		    	 					if (table.isCellSelectedAnyWay(c, i)) {
+		    	 						modelSet.setModel(model, i);
+		    	 						if (!changed)
+										outputInvalid();
+		    	 						changed = true;
+	    	 						}
+	    	 					}
+	    	 				}
+	    	 			}
+    	 			}
+    	 			if (changed)
+    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));
+	     	 		parametersChanged();
+   	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Stores current probability model set", null, commandName, "storeCurrent")) {
+    	 		if (data!=null){
+    	 			SpecsSetVector ssv = data.getSpecSetsVector(ProbabilityModelSet.class);
+    	 			if (ssv == null || ssv.getCurrentSpecsSet() == null) {
+			 		CharacterModel defaultModel =  data.getDefaultModel("Likelihood");
+			 		ModelSet modelSet= new ProbabilityModelSet("Model Set", data.getNumChars(), defaultModel, data);
+			 		modelSet.addToFile(data.getFile(), getProject(), findElementManager(ProbabilityModelSet.class)); //THIS
+					data.setCurrentSpecsSet(modelSet, ProbabilityModelSet.class);
+					ssv = data.getSpecSetsVector(ProbabilityModelSet.class);
+    	 			}
+    	 			if (ssv!=null) {
+    	 				SpecsSet s = ssv.storeCurrentSpecsSet();
+    					if (s.getFile() == null)
+    						s.addToFile(data.getFile(), getProject(), findElementManager(ProbabilityModelSet.class));
+    					s.setName(ssv.getUniqueName("Probability Model Set"));
+    	 				String name = MesquiteString.queryString(containerOfModule(), "Name", "Name of probability model set to be stored", "Probability Model Set");
+    	 				if (!StringUtil.blank(name))
+    	 					s.setName(name);
+    	 				ssv.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));  
+    	 			}
+     	 			else MesquiteMessage.warnProgrammer("sorry, can't store because no specssetvector");
+   	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Replaces stored probability model set by current one", null, commandName, "replaceWithCurrent")) {
+    	 		if (data!=null){
+    	 				SpecsSetVector ssv = data.getSpecSetsVector(ProbabilityModelSet.class);
+  	 				if (ssv!=null) {
+  	 					SpecsSet chosen = (SpecsSet)ListDialog.queryList(containerOfModule(), "Replace stored set", "Choose stored probability model set to replace by current set",MesquiteString.helpString,  ssv, 0);
+		    	 			if (chosen!=null){
+		    	 				SpecsSet current = ssv.getCurrentSpecsSet();
+		    	 				ssv.replaceStoredSpecsSet(chosen, current);
+		    	 			}
+	    	 			}
+    	 			
+    	 		}
+    	 		//return ((ListWindow)getModuleWindow()).getCurrentObject();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Loads the stored probability model set to be the current one", "[number of probability set to load]", commandName, "loadToCurrent")) {
+ 			if (data !=null) {
+ 				int which = MesquiteInteger.fromFirstToken(arguments, stringPos);
+ 				if (MesquiteInteger.isCombinable(which)){
+		 			SpecsSetVector ssv = data.getSpecSetsVector(ProbabilityModelSet.class);
+					if (ssv!=null) {
+						SpecsSet chosen = ssv.getSpecsSet(which);
+		    	 			if (chosen!=null){
+		    	 				ssv.setCurrentSpecsSet(chosen.cloneSpecsSet()); 
+		    	 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED)); //TODO: bogus! should notify via specs not data???
+		    	 				return chosen;
+		    	 			}
+			 		}
+ 				}
+	 		}
+	    	 }
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	public void setTableAndData(MesquiteTable table, CharacterData data){
+		this.data = data;
+		this.table = table;
+		deleteMenuItem(mss);
+		deleteMenuItem(mScs);
+		deleteMenuItem(mRssc);
+		deleteMenuItem(mLine);
+		deleteMenuItem(mStc);
+		mss = addSubmenu(null, "Probability model", makeCommand("setModel", this), getProject().getCharacterModels());
+		mLine = addMenuItem("-",null);
+		mScs = addMenuItem("Store current set...", makeCommand("storeCurrent",  this));
+		mRssc = addMenuItem("Replace stored set by current...", makeCommand("replaceWithCurrent",  this));
+		if (data !=null)
+			mStc = addSubmenu(null, "Load set", makeCommand("loadToCurrent",  this), data.getSpecSetsVector(ProbabilityModelSet.class));
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(ProbabilityModel.class, data.getStateClass()));
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		outputInvalid();
+		parametersChanged(notification);
+	}
+	public String getTitle() {
+		return "Probability Model";
+	}
+	public String getStringForCharacter(int ic){
+		if (data!=null){
+			ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(ProbabilityModelSet.class);
+			if (modelSet != null) {
+				CharacterModel model = modelSet.getModel(ic);
+				if (model!=null)
+					return model.getName();
+			}
+			else {
+				CharacterModel model = data.getDefaultModel("Likelihood");
+				if (model!=null) {
+					return model.getName();
+				}
+			}
+		}
+		return "?";
+	}
+	public String getWidestString(){
+		return "Probability Model  ";
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Current Probability Models";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies current stochastic models applied to characters for character list window." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/stochchar/CurrentProbModels/CurrentProbModels.java b/Source/mesquite/stochchar/CurrentProbModels/CurrentProbModels.java
new file mode 100644
index 0000000..23ffb89
--- /dev/null
+++ b/Source/mesquite/stochchar/CurrentProbModels/CurrentProbModels.java
@@ -0,0 +1,302 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.CurrentProbModels;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class CurrentProbModels extends ProbModelSourceLike {
+	ModelSet currentModelSet;
+	String preferred =  "Likelihood";
+	boolean reassignable = false;
+	MesquiteSubmenuSpec smenu;
+	MesquiteMenuItemSpec aboutItem;
+	CharacterData currentData = null;
+	int currentChar;
+	Class oldStateClass;
+   	CharacterModel defaultModel, lastModel;
+   	MesquiteString modelName;
+   	LongArray ids;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		modelName = new MesquiteString();
+		ids = new LongArray(20);
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+  	 }
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+  	 }
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj instanceof ProbabilityModel && code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED && code != MesquiteListener.NAMES_CHANGED) {
+			if (!reassignable || obj == lastModel || (ids.indexOf(((ProbabilityModel)obj).getID())>=0)) {
+				parametersChanged(notification);
+			}
+		}
+		else if (obj instanceof Class && ProbabilityModel.class.isAssignableFrom((Class)obj)) {
+				parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void disposing(Object obj){
+		if (obj instanceof ProbabilityModel) {
+			if (!reassignable || obj == lastModel) {
+				outputInvalid();
+				parametersChanged();
+			}
+		}
+	}
+  	 
+	/*.................................................................................................................*/
+    	 public void chooseAndFillUnassignedCharacters(CharacterData data) {
+ 			Listable[] models = getProject().getCharacterModels(new ModelCompatibilityInfo(ProbabilityModel.class, data.getStateClass()), data.getStateClass()); //TODO: would be better if passed name of model
+ 			CharacterModel model = (CharacterModel)ListDialog.queryList(containerOfModule(), "Choose model", "Select model to assigned to all characters without an assigned model", MesquiteString.helpString, models, 0);
+ 			boolean ch = false;
+ 			if (model != null) {
+				ModelSet modelSet = (ModelSet)data.getCurrentSpecsSet(ProbabilityModelSet.class);
+	 			if (modelSet == null) {
+			 		CharacterModel defaultModel =  data.getDefaultModel("Likelihood");
+			 		modelSet= new ProbabilityModelSet("Probability Model Set", data.getNumChars(), defaultModel, data);
+			 		modelSet.addToFile(data.getFile(), getProject(), findElementManager(ProbabilityModelSet.class)); 
+					data.setCurrentSpecsSet(modelSet, ProbabilityModelSet.class);
+	 			}
+	 			if (modelSet != null) {
+    	 				for (int i=0; i<data.getNumChars(); i++) {
+    	 					if (modelSet.getModel(i) == null)  {
+    	 						modelSet.setModel(model, i);
+    	 						ch = true;
+    	 					}
+	 				}
+	 			}
+ 			}
+ 			if (ch)
+ 				data.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));
+ 		
+   	 }
+   	/** returns model for character ic in data */
+   	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+   		currentData = data;
+   		currentChar = ic;
+   		if (data==null) {
+   			System.out.println("DATA NULL in model source file getModelCurrentCharacter (a)");
+   			lastModel = null;
+   			modelName.setValue("");
+   			return null;
+   		}
+   		else {
+	   		if (data.getStateClass()!=oldStateClass)
+	   			resetCurrent(data.getStateClass());
+  			CharacterModel cm=null;
+  			currentModelSet = (ModelSet)data.getCurrentSpecsSet(ProbabilityModelSet.class);
+  			if (currentModelSet == null) {
+	   			cm= data.getDefaultModel(preferred);
+	   			if (cm==null)
+	   				System.out.println("MODEL NULL in model source file getModelCurrentCharacter (b)");
+  			}
+   			else {
+   				cm = currentModelSet.getModel(ic);
+	   			if (cm==null)
+	   				System.out.println("MODEL NULL in model source file getModelCurrentCharacter (c)");
+   			}
+ 			if (reassignable && lastModel != cm)
+  				MesquiteTrunk.resetCheckMenuItems();
+   			lastModel = cm;
+   			if (lastModel != null && lastModel.getName() != null && !lastModel.getName().equals(modelName.getValue())){
+   				modelName.setValue(lastModel.getName());
+   			}
+   			if (cm != null && ids.indexOf(cm.getID())<0)
+   				if (!ids.fillNextUnassigned(cm.getID())){
+   					ids.resetSize(ids.getSize()+10);
+   					ids.fillNextUnassigned(cm.getID());
+   				}
+   			return cm;
+   		}
+   	}
+   	/** returns model for character */
+   	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+   		if (states==null) {
+   			System.out.println("STATES NULL in model source file getModelCurrentCharacter (d)");
+   			lastModel = null;
+   			modelName.setValue("");
+   			return null;
+   		}
+   		else {
+	   		if (states.getStateClass()!=oldStateClass)
+	   			resetCurrent(states.getStateClass());
+   			CharacterModel cm=null;
+   			CharacterData data = states.getParentData();
+	   		currentData = data;
+   			if (data == null) {
+   				cm = states.getDefaultModel(getProject(), preferred);
+	   			if (cm==null)
+	   				System.out.println("MODEL NULL in model source file getModelCurrentCharacter (e)");
+   			}
+   			else {
+   				int ic =  states.getParentCharacter(); 
+		   		currentChar = ic;
+  				currentModelSet = (ModelSet)data.getCurrentSpecsSet(ProbabilityModelSet.class);
+	  			if (currentModelSet == null) {
+		   			if (states!=null) {
+		   				cm= states.getDefaultModel(getProject(), preferred);
+			   			if (cm==null)
+			   				System.out.println("MODEL NULL in model source file getModelCurrentCharacter (f)");
+		   			}
+		   			else
+			   			System.out.println("MODEL NULL in model source file getModelCurrentCharacter (g)");
+	  			}
+	   			else {
+	   				
+	   				cm = currentModelSet.getModel(ic);
+			   		if (cm==null && states!=null)
+		   				cm= states.getDefaultModel(getProject(), preferred);
+		   			if (cm==null)
+		   				System.out.println("MODEL NULL in model source file getModelCurrentCharacter (h) " + ic);
+	   			}
+   			}
+ 			if (reassignable && lastModel != cm)
+  				MesquiteTrunk.resetCheckMenuItems();
+   			lastModel = cm;
+   			if (lastModel != null && lastModel.getName() != null && !lastModel.getName().equals(modelName.getValue())){
+   				modelName.setValue(lastModel.getName());
+   			}
+   			if (cm != null && ids.indexOf(cm.getID())<0)
+   				if (!ids.fillNextUnassigned(cm.getID())){
+   					ids.resetSize(ids.getSize()+10);
+   					ids.fillNextUnassigned(cm.getID());
+   				}
+   			return cm;
+  		}
+   	}
+	/*.................................................................................................................*/
+	void resetCurrent(Class stateClass){
+		oldStateClass = stateClass;
+		 if (smenu!=null) {
+			deleteMenuItem(smenu);
+			smenu=null;
+		}   		
+		if (reassignable) {
+			smenu = addSubmenu(null, "Probability model", makeCommand("setModel", this), getProject().getCharacterModels());
+			smenu.setCompatibilityCheck(new ModelCompatibilityInfo(ProbabilityModel.class, stateClass));
+			smenu.setSelected(modelName);
+		}
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+   	public void setOneCharacterAtATime(boolean chgbl){
+   		if (aboutItem == null)
+   			aboutItem = addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+   		reassignable = chgbl;
+   		Class stateClass = null;
+   		if (currentData!=null)
+   			stateClass = currentData.getStateClass();
+   		resetCurrent(stateClass);
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	if (defaultModel !=null)
+  	 		temp.addLine("setDefaultModel "+ getProject().getWhichCharacterModel(null, defaultModel));
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the probabiliy character model ", "[number of model]", commandName, "setModel")) {
+	 		if (currentData == null){
+		 		boolean changed=false;
+	      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+	      			if (!MesquiteInteger.isCombinable(whichModel))
+	      				return null;
+	 			defaultModel = getProject().getCharacterModel(new ModelCompatibilityInfo(ProbabilityModel.class, oldStateClass), whichModel);
+		     	 	parametersChanged();
+	     	 		return defaultModel;
+	 		}
+	      		else {
+		 		boolean changed=false;
+	      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+	      			if (!MesquiteInteger.isCombinable(whichModel))
+	      				return null;
+	 			CharacterModel model = getProject().getCharacterModel(new ModelCompatibilityInfo(ProbabilityModel.class, currentData.getStateClass()), whichModel);
+	 			
+				ModelSet modelSet = (ModelSet)currentData.getCurrentSpecsSet(ProbabilityModelSet.class);  
+	 			if (model!=null){
+		 			if (modelSet == null) {
+				 		CharacterModel defaultModel =  currentData.getDefaultModel("Likelihood");
+				 		modelSet= new ProbabilityModelSet("Probability Model Set", currentData.getNumChars(), defaultModel, currentData);
+				 		currentData.storeSpecsSet(modelSet, ProbabilityModelSet.class);
+						currentData.setCurrentSpecsSet(modelSet, ProbabilityModelSet.class);
+				 		modelSet.addToFile(currentData.getFile(), getProject(), findElementManager(ProbabilityModelSet.class)); //THIS
+		 			}
+
+		 			if (modelSet != null) {
+						modelSet.setModel(model, currentChar); 
+		 				currentData.notifyListeners(this, new Notification(AssociableWithSpecs.SPECSSET_CHANGED));  //TODO: not quite kosher
+		 			}
+		     	 		parametersChanged();
+	     	 		}
+	     	 		return model;
+ 	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the probability character model", "[number of model]", commandName, "setDefaultModel")) {
+		 		boolean changed=false;
+	      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+	      			if (!MesquiteInteger.isCombinable(whichModel))
+	      				return null;
+	 			defaultModel = getProject().getCharacterModel(whichModel);
+		     	 	parametersChanged();
+	     	 		return defaultModel;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+				String s = "";
+				if (lastModel == null)
+					s = "Sorry, no reference to the last used-model was found";
+				else
+					s = "The most recently used model is \"" + lastModel.getName() + "\".\nExplanation: " + lastModel.getExplanation();
+				discreetAlert( s);
+				return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Current probability models";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies the currently assigned stochastic (likelihood, probability) model for a character." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/stochchar/EvolveCategChars/EvolveCategChars.java b/Source/mesquite/stochchar/EvolveCategChars/EvolveCategChars.java
new file mode 100644
index 0000000..c96203a
--- /dev/null
+++ b/Source/mesquite/stochchar/EvolveCategChars/EvolveCategChars.java
@@ -0,0 +1,338 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.EvolveCategChars;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class EvolveCategChars extends CharacterSimulator implements MesquiteListener {
+	CategoricalHistory evolvingStates;
+	ProbPhenCategCharModel probabilityModel, originalProbabilityModel;
+	MesquiteString modelName;
+	long rootStateSim = 0L;  //state set for simulations; 0 = no state, use model's prior
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null && condition!= CategoricalData.class && condition!=CategoricalState.class){
+  	 		return sorry("Evolve Categorical cannot be used because it supplies only categorical characters");
+		}
+        loadPreferences();
+		ProbPhenCategCharModel m = null;
+		m = chooseModel();
+		if (m==null) {
+			return sorry("Evolve Categorical Characters could not start because no appropriate stochastic model of character evolution was found for use to simulate categorical character evolution");
+		}
+		setModel(m,  false); 
+		
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Model (for simulation)", makeCommand("setModelByNumber", this), getProject().getCharacterModels());
+		mss.setCompatibilityCheck(new SimModelCompatInfo(ProbPhenCategCharModel.class, null));
+		modelName = new MesquiteString(m.getName());
+		mss.setSelected(modelName);
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+  	 }
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "rootStateSim", (int)rootStateSim);   
+		return buffer.toString();
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("rootStateSim".equalsIgnoreCase(tag))
+			rootStateSim = MesquiteLong.fromString(content);
+	}
+ 	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+  	private ProbPhenCategCharModel chooseModel(){
+		if (MesquiteThread.isScripting())
+			return (ProbPhenCategCharModel)getProject().getCharacterModel(new SimModelCompatInfo(ProbPhenCategCharModel.class, CategoricalState.class),0);
+		else
+			return (ProbPhenCategCharModel)CharacterModel.chooseExistingCharacterModel(this, new SimModelCompatInfo(ProbPhenCategCharModel.class, CategoricalState.class), "Choose probability model for simulations");
+  	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		storePreferences();
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == originalProbabilityModel) {
+			setModel(chooseModel(), false);
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+  	 private void setModel(ProbPhenCategCharModel m,  boolean notify){
+  	 	originalProbabilityModel = m;
+  	 	if (probabilityModel !=null)
+  	 		probabilityModel.dispose();
+    	 	if (m ==null)
+    	 		probabilityModel = null;
+    	 	else {
+    	 		probabilityModel = (ProbPhenCategCharModel)m.cloneModelWithMotherLink(probabilityModel); //use a copy in case fiddled with
+    	 		probabilityModel.setUserVisible(false);
+   	 	}
+  	 	if (notify)
+  	 		parametersChanged();
+  	 }
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == originalProbabilityModel) {
+			setModel((ProbPhenCategCharModel)obj,  true);
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setModelByName " + StringUtil.tokenize(probabilityModel.getName()));
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets character model for simulation", "[name of model]", commandName, "setModelByName")) {
+    	 		pos.setValue(0);
+    	 		CharacterModel m = getProject().getCharacterModel(ParseUtil.getFirstToken(arguments, pos));
+    	 		if (m!=null && m instanceof ProbPhenCategCharModel) {
+    	 			setModel((ProbPhenCategCharModel)m,  true);
+    	 			modelName.setValue(m.getName());
+    	 			return m;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries use for model for simulation", null, commandName, "userQueryModel")) {
+			ProbPhenCategCharModel m =(ProbPhenCategCharModel)CharacterModel.chooseExistingCharacterModel(this, ProbPhenCategCharModel.class, "Choose probability model for simulations");
+			if (m!=null)
+				setModel(m,  true); 
+			return m;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets character model for simulation", "[name of model]", commandName, "setModelByNumber")) {
+    	 		pos.setValue(0);
+      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+      			if (!MesquiteInteger.isCombinable(whichModel))
+      				return null;
+ 			CharacterModel m = getProject().getCharacterModel(new SimModelCompatInfo(ProbPhenCategCharModel.class, null), whichModel);
+    	 		if (m!=null && m instanceof ProbPhenCategCharModel) {
+    	 			setModel((ProbPhenCategCharModel)m,  true);
+    	 			modelName.setValue(m.getName());
+    	 			return m;
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 CharacterState statesAtAncestor=null;
+   	 CharacterState endStates=null;
+ 	/*.................................................................................................................*/
+	private void evolve(Tree tree, CategoricalAdjustable statesAtTips, int node) {
+   		if (node!=tree.getRoot()) {
+   			long statesAtAncestor = evolvingStates.getState(tree.motherOfNode(node));
+   			int stateAtAncestor = CategoricalState.minimum(statesAtAncestor);
+   			long statesAtNode = CategoricalState.makeSet(probabilityModel.evolveState(stateAtAncestor, tree, node));
+   			evolvingStates.setState(node, statesAtNode);  
+   			if (tree.nodeIsTerminal(node)) {
+   				statesAtTips.setState(tree.taxonNumberOfNode(node), statesAtNode);
+   			}
+   		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				evolve(tree, statesAtTips, daughter);
+	}
+ 	/*.................................................................................................................*/
+	private void evolve (Tree tree, CategoricalHistory statesAtNodes, int node) {
+   		if (node!=tree.getRoot()) {
+   			long statesAtAncestor = statesAtNodes.getState(tree.motherOfNode(node));
+   			int stateAtAncestor = CategoricalState.minimum(statesAtAncestor);
+   			int stateAtNode = probabilityModel.evolveState(stateAtAncestor, tree, node);
+   			long statesAtNode = CategoricalState.makeSet(stateAtNode);
+   			statesAtNodes.setState(node, statesAtNode);
+   		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				evolve(tree, (CategoricalHistory)statesAtNodes, daughter);
+	}
+	boolean failed = false;
+	int warnedNoModel = 0;
+	/*.................................................................................................................*/
+   	public CharacterDistribution getSimulatedCharacter(CharacterDistribution statesAtTips, Tree tree, MesquiteLong seed){
+   		if (tree == null) {
+   			//MesquiteMessage.warnProgrammer("tree null in Evolve categorical chars simple ");
+   			return null;
+   		}
+   		else if (statesAtTips == null || !(statesAtTips instanceof CategoricalAdjustable)){
+   			statesAtTips =  new CategoricalAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+   		}
+   		else	
+   			statesAtTips = (CharacterDistribution)((AdjustableDistribution)statesAtTips).adjustSize(tree.getTaxa());
+		if (statesAtTips instanceof CategoricalAdjustable)
+			((CategoricalAdjustable)statesAtTips).deassignStates();
+		if (probabilityModel == null){
+			if (warnedNoModel++<10) {
+				discreetAlert( "Sorry, the simulation cannot continue because no model of character evolution has been specified.");
+				if (!MesquiteThread.isScripting())
+					warnedNoModel = 10;
+			}
+			return statesAtTips;
+   		}	
+		
+		probabilityModel.setMaxStateSimulatable(probabilityModel.getMaxStateDefined()); //should allow user to set # states
+   		if (!probabilityModel.isFullySpecified()) {
+   			if (failed) {
+   				return statesAtTips;
+   			}	
+   			CharModelCurator mb = findModelCurator(probabilityModel.getClass());
+   			mb.showEditor(probabilityModel);  //MODAL
+   			if (!probabilityModel.isFullySpecified()) {
+   				discreetAlert( "Sorry, the simulation cannot continue because the model of character evolution ("  + probabilityModel.getName() + ") doesn't have all of its parameters specified.");
+   				failed = true;
+   				return statesAtTips;
+   			}
+   		}
+   		failed = false;
+   		evolvingStates =(CategoricalHistory) statesAtTips.adjustHistorySize(tree, evolvingStates);
+   		if (seed!=null)
+   			probabilityModel.setSeed(seed.getValue());
+   		long rootstate = probabilityModel.getRootState(tree);
+   		if (rootStateSim != 0L)
+   			rootstate = rootStateSim;
+   		evolvingStates.setState(tree.getRoot(), rootstate);  //starting rootCategoricalState.makeSet(0)); //
+   		evolve(tree, (CategoricalAdjustable)statesAtTips, tree.getRoot());
+   		if (seed!=null)
+   			seed.setValue(probabilityModel.getSeed());
+  		return statesAtTips; 
+   	}
+  
+	/*............................................. ....................................................................*/
+   	public CharacterHistory getSimulatedHistory(CharacterHistory statesAtNodes, Tree tree, MesquiteLong seed){
+   		if (tree == null) {
+   			//MesquiteMessage.warnProgrammer("tree null in Evolve continuous chars simple ");
+   			return null;
+   		}
+   		else if (statesAtNodes == null || !(statesAtNodes instanceof CategoricalHistory)){
+   			statesAtNodes =  new CategoricalHistory(tree.getTaxa(), tree.getNumNodeSpaces());
+   		}
+   		else	
+   			statesAtNodes = statesAtNodes.adjustSize(tree);
+
+		if (probabilityModel == null){
+			if (statesAtNodes instanceof CategoricalAdjustable)
+				((CategoricalAdjustable)statesAtNodes).deassignStates();
+			if (warnedNoModel++<10) {
+				discreetAlert( "Sorry, the simulation cannot continue because no model of character evolution has been specified.");
+				if (!MesquiteThread.isScripting())
+					warnedNoModel = 10;
+			}
+			return statesAtNodes;
+   		}	
+		probabilityModel.setMaxStateSimulatable(probabilityModel.getMaxStateDefined()); //should allow user to set # states
+   		if (!probabilityModel.isFullySpecified()) {
+   			if (failed) {
+   				statesAtNodes.deassignStates();
+   				return statesAtNodes;
+   			}	
+   			CharModelCurator mb = findModelCurator(probabilityModel.getClass());
+   			mb.showEditor(probabilityModel); //MODAL???
+   			if (!probabilityModel.isFullySpecified()) {
+   				alert("Sorry, the simulation cannot continue because the model of character evolution ("  + probabilityModel.getName() + ") doesn't have all of its parameters specified.");
+   				statesAtNodes.deassignStates();
+   				failed = true;
+   				return statesAtNodes;
+   			}
+   		}
+   		failed = false;
+   		if (seed!=null)
+   			probabilityModel.setSeed(seed.getValue());
+   		long rootstate = probabilityModel.getRootState(tree);
+
+  		((CategoricalHistory)statesAtNodes).setState(tree.getRoot(), rootstate);  
+   		evolve(tree, (CategoricalHistory)statesAtNodes, tree.getRoot());
+   		if (seed!=null)
+   			seed.setValue(probabilityModel.getSeed());
+  		return statesAtNodes;
+   	}
+	/*.................................................................................................................*/
+	/** Indicates the type of character created */ 
+	public Class getStateClass(){
+		return CategoricalState.class;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Evolve Categorical Characters";
+   	 }
+   	 
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (probabilityModel == null)
+			return "Model not available or specified.";
+		else
+			return "Markovian evolution using model: " + probabilityModel.getName() + " (" + probabilityModel.getParameters() + ")";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Simulates character evolution for categorical characters on a tree." ;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new ECCCategoricalStateTest();
+  	 }
+}
+
+class ECCCategoricalStateTest extends OffersCategoricalData{
+	ModelCompatibilityInfo mci;
+	public ECCCategoricalStateTest (){
+		super();
+		mci = new ModelCompatibilityInfo(ProbPhenCategCharModel.class, CategoricalState.class);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			if (project==null){
+			 	return super.isCompatible(obj, project, prospectiveEmployer);
+			}
+			 Listable[] models = project.getCharacterModels(mci, CategoricalState.class);
+			 if (models == null || models.length == 0)
+			 	return false;
+			 boolean oneFound = false;
+			 for (int i=0; i<models.length; i++)
+			 	if (((ProbPhenCategCharModel)models[i]).isFullySpecified()) {
+			 		oneFound = true;
+			 		break;
+			 	}
+			 if (oneFound){
+			 	return super.isCompatible(obj, project, prospectiveEmployer);
+			 }
+			 return false;
+	}
+}
+
+
+
diff --git a/Source/mesquite/stochchar/EvolveContinuous/EvolveContinuous.java b/Source/mesquite/stochchar/EvolveContinuous/EvolveContinuous.java
new file mode 100644
index 0000000..519e186
--- /dev/null
+++ b/Source/mesquite/stochchar/EvolveContinuous/EvolveContinuous.java
@@ -0,0 +1,310 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.EvolveContinuous;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+
+
+/* ======================================================================== */
+public class EvolveContinuous extends CharacterSimulator implements MesquiteListener {
+	ContinuousHistory evolvingStates;
+	ProbabilityContCharModel probabilityModel, originalProbabilityModel;
+	MesquiteString modelName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition!=null && condition!= ContinuousData.class && condition!=ContinuousState.class){
+			return sorry("Evolve Continuous cannot be used because it supplies only continuous-valued characters");
+		}
+		ProbabilityContCharModel m = chooseModel();
+		if (m==null) {
+			return sorry("Evolve Continuous Characters could not start because no appropriate stochastic model of character evolution was found for use to simulate continuous character evolution");
+		}
+		setModel(m,  false); 
+
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Model (for simulation)", makeCommand("setModelByNumber", this), getProject().getCharacterModels());
+		mss.setCompatibilityCheck(new SimModelCompatInfo(ProbabilityContCharModel.class, null));
+		modelName = new MesquiteString(m.getName());
+		mss.setSelected(modelName);
+		getProject().getCentralModelListener().addListener(this);
+		return true;
+	}
+
+	private ProbabilityContCharModel chooseModel(){
+		ProbabilityContCharModel m = null;
+		if (MesquiteThread.isScripting())
+			return (ProbabilityContCharModel)getProject().getCharacterModel(new SimModelCompatInfo(ProbabilityContCharModel.class, ContinuousState.class),0);
+		else
+			return (ProbabilityContCharModel)CharacterModel.chooseExistingCharacterModel(this, new SimModelCompatInfo(ProbabilityContCharModel.class, ContinuousState.class), "Choose probability model for simulations of continuous character evolution");
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		if (probabilityModel !=null)
+			probabilityModel.dispose();
+		super.endJob();
+	}
+	private void setModel(ProbabilityContCharModel m,  boolean notify){
+		originalProbabilityModel = m;
+		if (probabilityModel !=null)
+			probabilityModel.dispose();
+		if (m!=null){
+			probabilityModel = (ProbabilityContCharModel)m.cloneModelWithMotherLink(probabilityModel); //use a copy in case fiddled with
+			probabilityModel.setUserVisible(false);
+		}
+		if (notify)
+			parametersChanged();
+	}
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj == originalProbabilityModel) {
+			setModel((ProbabilityContCharModel)obj,  true);
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj == originalProbabilityModel) {
+			setModel(chooseModel(), true);
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModelByName " + StringUtil.tokenize(probabilityModel.getName()));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets character model for simulation", "[name of model]", commandName, "setModelByName")) {
+			pos.setValue(0);
+			CharacterModel m = getProject().getCharacterModel(parser.getFirstToken(arguments));
+			if (m!=null && m instanceof ProbabilityContCharModel) {
+				setModel((ProbabilityContCharModel)m,  true);
+				modelName.setValue(m.getName());
+				return m;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets character model for simulation", "[number of model]", commandName, "setModelByNumber")) {
+			pos.setValue(0);
+			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(whichModel))
+				return null;
+			CharacterModel m = getProject().getCharacterModel(new ModelCompatibilityInfo(ProbabilityContCharModel.class, null), whichModel);
+			if (m!=null && m instanceof ProbabilityContCharModel) {
+				setModel((ProbabilityContCharModel)m,  true);
+				modelName.setValue(m.getName());
+				return m;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void evolve (Tree tree, ContinuousAdjustable statesAtTips, int node) {
+		if (node!=tree.getRoot()) {
+			double stateAtAncestor = evolvingStates.getState(tree.motherOfNode(node));
+			double stateAtNode = probabilityModel.evolveState(stateAtAncestor, tree, node);
+			evolvingStates.setState(node, stateAtNode);  
+			if (tree.nodeIsTerminal(node)) {
+				statesAtTips.setState(tree.taxonNumberOfNode(node), stateAtNode);
+			}
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			evolve(tree, statesAtTips, daughter);
+	}
+	/*.................................................................................................................*/
+	private void evolve (Tree tree, ContinuousHistory statesAtNodes, int node) {
+		if (node!=tree.getRoot()) {
+			double stateAtAncestor = statesAtNodes.getState(tree.motherOfNode(node));
+			double stateAtNode = probabilityModel.evolveState(stateAtAncestor, tree, node);
+			statesAtNodes.setState(node, stateAtNode);
+		}
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			evolve(tree, (ContinuousHistory)statesAtNodes, daughter);
+	}
+	Tree oldTree=null;
+	boolean failed = false;
+	int warnedNoModel = 0;
+	/*.................................................................................................................*/
+	public CharacterDistribution getSimulatedCharacter(CharacterDistribution statesAtTips, Tree tree, MesquiteLong seed){
+		if (tree == null) {
+			//System.out.println("tree null in Evolve continuous chars ");
+			return null;
+		}
+		else if (statesAtTips == null || !(statesAtTips instanceof ContinuousAdjustable)){
+			statesAtTips =  new ContinuousAdjustable(tree.getTaxa(), tree.getTaxa().getNumTaxa());
+		}
+		else	
+			statesAtTips = (CharacterDistribution)((AdjustableDistribution)statesAtTips).adjustSize(tree.getTaxa());
+		if (statesAtTips instanceof ContinuousAdjustable)
+			((ContinuousAdjustable)statesAtTips).deassignStates();
+
+		if (probabilityModel == null){
+			if (warnedNoModel++<10) {
+				discreetAlert( "Sorry, the simulation cannot continue because no model of character evolution has been specified.");
+				if (!MesquiteThread.isScripting())
+					warnedNoModel = 10;
+			}
+			return statesAtTips;
+		}	
+		probabilityModel.setCharacterDistribution(statesAtTips);
+		if (!probabilityModel.isFullySpecified()) {
+			if (failed) {
+				return statesAtTips;
+			}	
+			CharModelCurator mb = findModelCurator(probabilityModel.getClass());
+			mb.showEditor(probabilityModel); //MODAL
+			if (!probabilityModel.isFullySpecified()) {
+				alert("Sorry, the simulation cannot continue because the model of character evolution ("  + probabilityModel.getName() + ") doesn't have all of its parameters specified.");
+				failed = true;
+				return statesAtTips;
+			}
+		}
+		failed = false;
+		evolvingStates =(ContinuousHistory) statesAtTips.adjustHistorySize(tree, evolvingStates);
+		if (seed!=null)
+			probabilityModel.setSeed(seed.getValue());
+		evolvingStates.setState(tree.getRoot(), probabilityModel.getRootState(tree));  //starting root at ancestral state
+		evolve(tree, (ContinuousAdjustable)statesAtTips, tree.getRoot());
+		if (seed!=null)
+			seed.setValue(probabilityModel.getSeed());
+		oldTree = tree;
+		return statesAtTips;
+	}
+	/*.................................................................................................................*/
+	public CharacterHistory getSimulatedHistory(CharacterHistory statesAtNodes, Tree tree, MesquiteLong seed){
+		if (tree == null) {
+			//System.out.println("tree null in Evolve continuous chars ");
+			return null;
+		}
+		else if (statesAtNodes == null || !(statesAtNodes instanceof ContinuousHistory)){
+			statesAtNodes =  new ContinuousHistory(tree.getTaxa(), tree.getNumNodeSpaces(), null);
+		}
+		else	
+			statesAtNodes = statesAtNodes.adjustSize(tree);
+
+		if (probabilityModel == null){
+			if (statesAtNodes instanceof ContinuousAdjustable)
+				((ContinuousAdjustable)statesAtNodes).deassignStates();
+			if (warnedNoModel++<10) {
+				discreetAlert( "Sorry, the simulation cannot continue because no model of character evolution has been specified.");
+				if (!MesquiteThread.isScripting())
+					warnedNoModel = 10;
+			}
+			return statesAtNodes;
+		}	
+		probabilityModel.setCharacterDistribution(statesAtNodes);
+		if (seed!=null)
+			probabilityModel.setSeed(seed.getValue());
+		if (!probabilityModel.isFullySpecified()) {
+			if (failed) {
+				statesAtNodes.deassignStates();
+				return statesAtNodes;
+			}	
+			CharModelCurator mb = findModelCurator(probabilityModel.getClass());
+			mb.showEditor(probabilityModel); //MODAL
+			if (!probabilityModel.isFullySpecified()) {
+				alert("Sorry, the simulation cannot continue because the model of character evolution ("  + probabilityModel.getName() + ") doesn't have all of its parameters specified.");
+				statesAtNodes.deassignStates();
+				failed = true;
+				return statesAtNodes;
+			}
+		}
+		failed = false;
+		((ContinuousHistory)statesAtNodes).setState(tree.getRoot(), probabilityModel.getRootState(tree));  //starting root at ancestral state
+		evolve(tree, (ContinuousHistory)statesAtNodes, tree.getRoot());
+		if (seed!=null)
+			seed.setValue(probabilityModel.getSeed());
+		oldTree = tree;
+		return statesAtNodes;
+	}
+	/*.................................................................................................................*/
+	/** Indicates the type of character created */ 
+	public Class getStateClass(){
+		return ContinuousState.class;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Evolve Continuous Characters";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return "Markovian evolution using model: " + probabilityModel.getName() + " (" + probabilityModel.getParameters() + ")";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Simulates character evolution for continuous characters on a tree." ;
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ECoCCategoricalStateTest();
+	}
+}
+class ECoCCategoricalStateTest extends ContinuousStateTest{
+	ModelCompatibilityInfo mci;
+	public ECoCCategoricalStateTest (){
+		super();
+		mci = new ModelCompatibilityInfo(ProbabilityContCharModel.class, ContinuousState.class);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (project==null){
+			return super.isCompatible(obj, project, prospectiveEmployer);
+		}
+		Listable[] models = project.getCharacterModels(mci, ContinuousState.class);
+		if (models == null || models.length == 0)
+			return false;
+		boolean oneFound = false;
+		for (int i=0; i<models.length; i++)
+			if (((ProbabilityContCharModel)models[i]).isFullySpecified()) {
+				oneFound = true;
+				break;
+			}
+		if (oneFound){
+			return super.isCompatible(obj, project, prospectiveEmployer);
+		}
+		return false;
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/stochchar/GainLossRates/GainLossRates.java b/Source/mesquite/stochchar/GainLossRates/GainLossRates.java
new file mode 100644
index 0000000..1cae365
--- /dev/null
+++ b/Source/mesquite/stochchar/GainLossRates/GainLossRates.java
@@ -0,0 +1,173 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.GainLossRates;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public class GainLossRates extends NumberForCharAndTree  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.stochchar.zMargLikeCateg.zMargLikeCateg.class, getName() + "  needs a module to calculate likelihoods.",
+		"The module to calculate likelihoods is arranged automatically");
+	}
+	MargLikelihoodForModel reconstructTask = null;
+	AsymmModel asymmModel;
+	MesquiteNumber likelihood = new MesquiteNumber();
+	static final int BIAS = 0;
+	static final int GAIN = 1;  
+	static final int LOSS = 2;
+	static final int RATE = 3;
+	StringArray reportModes;
+	int reportMode = BIAS;
+	MesquiteString reportModeName;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		reconstructTask = (MargLikelihoodForModel)hireNamedEmployee(MargLikelihoodForModel.class, "#zMargLikeCateg");
+ 		if (reconstructTask == null)
+ 			return sorry(getName() + " couldn't start because no likelihood calculator obtained");
+ 		asymmModel = new AsymmModel("Estimating Asymm", CategoricalState.class);
+		reportModes = new StringArray(4);  
+			reportModes.setValue(BIAS, "Bias");  //the strings passed will be the menu item labels
+			reportModes.setValue(GAIN, "Forward Rate");
+			reportModes.setValue(LOSS, "Backward Rate");
+			reportModes.setValue(RATE, "Overall Rate");
+			reportModeName = new MesquiteString(reportModes.getValue(reportMode));  //this helps the menu keep track of checkmenuitems
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Show", makeCommand("setReportMode", this), reportModes); 
+			mss.setSelected(reportModeName);
+			
+		getProject().getCentralModelListener().addListener(this);
+ 		return true; 
+ 	}
+ 	
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj instanceof Class && (AsymmModel.class.isAssignableFrom((Class)obj))) {
+				parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree, CharacterDistribution charStates){
+   	}
+	/*.................................................................................................................*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree==null || observedStates==null) {
+			if (resultString!=null)
+				resultString.setValue("Gain or loss rate estimates unassigned because no tree or no character supplied");
+			return;
+		}
+	
+
+		if (reconstructTask != null) {
+			asymmModel.deassignParameters();
+			//asymmModel.setUseRateBiasNotation(reportMode == BIAS || reportMode == RATE);
+			asymmModel.setUseRateBiasNotation(reportMode == BIAS || reportMode == RATE);
+			reconstructTask.estimateParameters(tree, observedStates, asymmModel, resultString);
+			if (reportMode == BIAS || reportMode == GAIN) {
+				result.setValue(asymmModel.getParam1());
+			}
+			else if ( reportMode == RATE ||  reportMode == LOSS){
+				result.setValue(asymmModel.getParam0());
+			}
+
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	 public Snapshot getSnapshot(MesquiteFile file) {
+	 		
+		Snapshot temp = new Snapshot();
+		 temp.addLine("setReportMode " + ParseUtil.tokenize(reportModes.getValue(reportMode)));
+	 	return temp;
+	 }
+
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(getClass(), "Sets the report mode", null, commandName, "setReportMode")) {
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = reportModes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=reportMode){
+				reportMode = newMode; //change mode
+	    			reportModeName.setValue(reportModes.getValue(reportMode)); //so that menu item knows to become checked
+	    	 		parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+		 	}
+	 	}
+	 	else
+	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+   
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return reportModes.getValue(reportMode);
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Forward/Backward Rates";
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	/*.................................................................................................................*/
+  	 public String getParameters() {
+  	 	String s = "Reporting  " + reportModes.getValue(reportMode);
+		if (asymmModel !=null)
+   			return s + "; AsymmMk Model settings: " +  asymmModel.getSettingsString();
+   		return s;
+   	}
+ 	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Uses maximum likelihood to estmate the rates of forward and backward changes (0 to 1 and 1 to 0 changes respectively), or alternatively the overall rate and the bias in gains versus losses, using the AsymmMk model on a tree for a given character." ;
+   	 }
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+	 
+}
+
+
diff --git a/Source/mesquite/stochchar/InterpretPagelFormat/InterpretPagelFormat.java b/Source/mesquite/stochchar/InterpretPagelFormat/InterpretPagelFormat.java
new file mode 100644
index 0000000..73152a6
--- /dev/null
+++ b/Source/mesquite/stochchar/InterpretPagelFormat/InterpretPagelFormat.java
@@ -0,0 +1,237 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.InterpretPagelFormat;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+import mesquite.categ.lib.*;
+
+/* ============  a file interpreter for Pagel's ppy files ============*/
+
+public class InterpretPagelFormat extends PagelFormatI {
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+	public boolean readTreeAndCharacters(MesquiteFile file, String line, Vector nodes, MesquiteInteger nC){
+		int numChars = 1;
+		boolean abort = false;
+
+		String token;
+		int nt = 0;
+			StringBuffer sb = new StringBuffer(1000);
+		while (line !=null && !abort) {  //first pull in all the nodes
+			if (!StringUtil.blank(line)){
+				parser.setString(line);
+				if (parser.firstDarkChar() != '#') {
+					String node = parser.getNextToken();
+					token = parser.getNextToken();  //comma ?
+					if (",".equalsIgnoreCase(token))
+						token = parser.getNextToken();
+					String ancestor =token;  //node number of ancestor
+					token = parser.getNextToken();  //comma ?
+					if (",".equalsIgnoreCase(token))
+						token = parser.getNextToken();
+					double branchLength = MesquiteDouble.fromString(token, false);  //branch length
+					token = parser.getNextToken();  //comma ?
+					if (",".equalsIgnoreCase(token))
+						token = parser.getNextToken();
+					int state1 = MesquiteInteger.fromString(token, false);  //state of character 1
+					token = parser.getNextToken();  //comma ?
+					if (",".equalsIgnoreCase(token))
+						token = parser.getNextToken();
+					int state2 = MesquiteInteger.fromString(token, false);  //state of character 2
+					int taxonNumber = -1;
+					if (MesquiteInteger.isCombinable(state1))
+						taxonNumber = nt++;
+					if (MesquiteInteger.isCombinable(state2))
+						numChars = 2;
+					PagNodeRecord pnr = new PagNodeRecord(taxonNumber, node, ancestor, branchLength, new int[]{state1, state2});
+					nodes.addElement(pnr);
+				}
+			}
+			boolean continuing = file.readLine(sb);
+			if (continuing)
+					line = sb.toString();
+			else
+				line = null;
+			if (file.getFileAborted()) {
+				abort = true;
+			}
+		}
+		nC.setValue(numChars);
+		return !abort; 
+	}
+	/*.................................................................................................................*/
+
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		CharacterData data = getProject().chooseData(containerOfModule(), null, CategoricalState.class, "Data Matrix to export");
+		if (data ==null)
+			return false;
+		Taxa taxa = data.getTaxa();
+		OneTreeSource treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree to be exported to Pagel format (ppy) file");
+		Tree tree = null;
+		if (treeTask != null) {
+   			treeTask.initialize(taxa);
+			tree = treeTask.getTree(taxa);
+		}
+		if (tree == null) {
+			Listable[] treeVectors = getProject().getCompatibleFileElements(TreeVector.class, taxa);
+			if (treeVectors == null) {
+				fireEmployee(treeTask);
+				return false;//MESSAGE
+			}
+			TreeVector trees;
+			if (treeVectors.length ==1)
+				trees = (TreeVector)treeVectors[0];
+			else
+				trees = (TreeVector)ListDialog.queryList(containerOfModule(), "Choose Trees Block", "Choose block of trees from which to choose a tree for export to  Pagel format (ppy) file", MesquiteString.helpString, treeVectors, 0);
+			if (trees == null) {
+				fireEmployee(treeTask);
+				return false; //MESSAGE
+			}
+			tree = (Tree)ListDialog.queryList(containerOfModule(), "Choose Tree", "Choose tree for export to Pagel format (ppy) file", MesquiteString.helpString, trees, 0);
+		}
+		if (tree == null) {
+			fireEmployee(treeTask);
+			return false; //MESSAGE
+		}
+			
+			
+		// convert polytomies to zeroLengthBranches
+		sanitizeTree(tree);
+		
+		//choose two binary character distributions
+		String[] charNames = new String[data.getNumChars()];
+		for (int i=0; i<data.getNumChars(); i++)
+			charNames[i]= data.getCharacterName(i);
+ 			
+		int numCharacters = 2;
+		int numSelected = 0;
+		String which = "first";
+		CategoricalDistribution[] chosenChars = new CategoricalDistribution[numCharacters];
+		while (numSelected<numCharacters){
+ 			int chosen = ListDialog.queryList(containerOfModule(), "Choose character", "Choose " + which + " character for export to Pagel format (ppy) file", MesquiteString.helpString, charNames, 0);
+			if (chosen >=0 ){
+				CategoricalDistribution distn = (CategoricalDistribution)data.getCharacterDistribution(chosen);
+				long allStates = 0L;
+				boolean uncombinableState = false;
+				boolean polymorphisms = false;
+				for (int it = 0; it < distn.getNumTaxa() && !uncombinableState; it++) {
+					long state = distn.getState(it);
+					if (!CategoricalState.isCombinable(state))
+						uncombinableState = true;
+					if (CategoricalState.cardinality(state)>1)
+						polymorphisms = true;
+					allStates |= state;
+				}
+				if (uncombinableState)
+					alert("Sorry, that character can't be used because it has missing or inapplicable codings");
+				else if (polymorphisms)
+					alert("Sorry, that character can't be used because it has polymorphisms or uncertainties.");
+				else if (CategoricalState.maximum(allStates)>1) 
+					alert("Sorry, that character can't be used because it has a state other than 0 or 1");
+				else {
+					chosenChars[numSelected] = distn;
+					numSelected++;
+					which = "second";
+				}
+			}
+			else {
+				fireEmployee(treeTask);
+				return false; //MESSAGE
+			}
+		}
+		
+		int numTaxa = tree.numberOfTerminalsInClade(tree.getRoot());
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*12);
+		outputBuffer.append("#Translated to Pagel format for Discrete from project with home file " + getProject().getHomeFileName());
+		outputBuffer.append("\r\n");
+		outputBuffer.append("# Block of taxa: " + taxa.getName());
+		outputBuffer.append("\r\n");
+		outputBuffer.append("# First Character: " + chosenChars[0].getName() + " of data matrix " + data.getName());
+		outputBuffer.append("\r\n");
+		outputBuffer.append("# Second Character: " + chosenChars[1].getName() + " of data matrix " + data.getName());
+		outputBuffer.append("\r\n");
+		outputBuffer.append("# Tree: " + tree.getName());
+		outputBuffer.append("\r\n");
+		int[] numbers = new int[tree.getNumNodeSpaces()];
+		MesquiteInteger nodeCount = new MesquiteInteger(numTaxa+1);
+		numberNodes(tree, tree.getRoot(), numbers, nodeCount);
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (tree.taxonInTree(it)) {
+					int node = tree.nodeOfTaxonNumber(it);
+					outputBuffer.append('t'); //t for taxon
+					outputBuffer.append(Integer.toString(it+1)); //taxon number
+					outputBuffer.append(','); 
+					outputBuffer.append(numbers[tree.motherOfNode(node)]);  //ancestor node
+					outputBuffer.append(','); 
+					outputBuffer.append(MesquiteDouble.toStringNoNegExponential(tree.getBranchLength(node, 1.0)));
+					outputBuffer.append(','); 
+					for (int ic = 0; ic<numCharacters; ic++){ //writing out character states
+						long cs1 = chosenChars[ic].getState(it);
+						if (CategoricalState.isElement(cs1, 0))
+							outputBuffer.append('0'); 
+						else if (CategoricalState.isElement(cs1, 1))
+							outputBuffer.append('1'); 
+
+						if (ic<numCharacters-1)
+							outputBuffer.append(','); 
+					}
+					outputBuffer.append("\r\n");
+				}
+		}
+
+		StringBuffer equivalenceBuffer = new StringBuffer(50);
+		equivalenceBuffer.append("#Table of equivalencies of nodes with Mesquite's node numbering system\r\n");
+		outputInternals(tree, tree.getRoot(), numbers, outputBuffer, equivalenceBuffer);
+
+//table of equivalencies of nodes
+		outputBuffer.append("\r\n");
+		outputBuffer.append("\r\n");
+		outputBuffer.append(equivalenceBuffer.toString());
+		String output = outputBuffer.toString();
+		
+		String name = getProject().getHomeFileName();
+		if (name==null)
+			name = "untitled.ppy";
+		else 
+			name = stripNex(name) + ".ppy";
+		saveExportedFile(output, arguments, name);
+		fireEmployee(treeTask);
+		return true;
+		
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Pagel format (ppy) file for Discrete";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports files formatted for Pagel's Discrete program." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/stochchar/InterpretPagelFormatM/InterpretPagelFormatM.java b/Source/mesquite/stochchar/InterpretPagelFormatM/InterpretPagelFormatM.java
new file mode 100644
index 0000000..f0df7c3
--- /dev/null
+++ b/Source/mesquite/stochchar/InterpretPagelFormatM/InterpretPagelFormatM.java
@@ -0,0 +1,261 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.InterpretPagelFormatM;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ============  a file interpreter for Pagel's ppy files ============*/
+
+public class InterpretPagelFormatM extends PagelFormatI {
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  //make this depend on taxa reader being found?)
+  	 }
+  	 
+	public boolean readTreeAndCharacters(MesquiteFile file, String line, Vector nodes, MesquiteInteger nC){
+		int numChars = 1;
+		boolean abort = false;
+		//first line gives number of taxa and number of characters
+		parser.setString(line);
+		parser.getNextToken(); //taxa
+		numChars = MesquiteInteger.fromString(parser.getNextToken()); //taxa
+		if (!MesquiteInteger.isCombinable(numChars) || numChars == 0)
+			return false;
+		StringBuffer sb = new StringBuffer(1000);
+		file.readLine(sb);
+		line = sb.toString();
+		
+		String token;
+		int nt = 0;
+		while (!StringUtil.blank(line)&& !abort) {  //first pull in all the nodes
+			parser.setString(line);
+			if (parser.firstDarkChar() != '#') {
+				String node = parser.getNextToken();
+				token = parser.getNextToken();  //comma ?
+				if (",".equalsIgnoreCase(token))
+					token = parser.getNextToken();
+				String ancestor =token;  //node number of ancestor
+				token = parser.getNextToken();  //comma ?
+				if (",".equalsIgnoreCase(token))
+					token = parser.getNextToken();
+				double branchLength = MesquiteDouble.fromString(token, false);  //branch length
+				token = parser.getNextToken();  //comma ?
+				if (",".equalsIgnoreCase(token))
+					token = parser.getNextToken();
+				int[] states = new int[numChars];
+				states[0] = MesquiteInteger.fromString(token, false);  //state of character 
+				token = parser.getNextToken();  //comma ?
+				if (",".equalsIgnoreCase(token))
+					token = parser.getNextToken();
+				int taxonNumber = -1;
+				if (MesquiteInteger.isCombinable(states[0])) {  //appears to be terminal; get other characters
+					taxonNumber = nt++;
+					for (int ic = 1; ic<numChars; ic++){
+						states[ic] = MesquiteInteger.fromString(token, false);  //state of character 
+						token = parser.getNextToken();  //comma ?
+						if (",".equalsIgnoreCase(token))
+							token = parser.getNextToken();
+					}
+				}
+				PagNodeRecord pnr = new PagNodeRecord(taxonNumber, node, ancestor, branchLength, states);
+				nodes.addElement(pnr);
+			}
+			file.readLine(sb);
+			line = sb.toString();		
+			if (file.getFileAborted()) {
+				abort = true;
+			}
+		}
+		nC.setValue(numChars);
+		return !abort; 
+	}
+	
+	/*.................................................................................................................*/
+
+	public boolean exportFile(MesquiteFile file, String arguments) { //if file is null, consider whole project open to export
+		CharacterData data = getProject().chooseData(containerOfModule(), null, CategoricalState.class, "Data matrix to export");
+		if (data ==null)
+			return false;
+		Taxa taxa = data.getTaxa();
+		OneTreeSource treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree to be exported to Pagel format (ppy) file");
+		Tree tree = null;
+		if (treeTask != null) {
+   			treeTask.initialize(taxa);
+			tree = treeTask.getTree(taxa);
+		}
+		if (tree == null) {
+			Listable[] treeVectors = getProject().getCompatibleFileElements(TreeVector.class, taxa);
+			if (treeVectors == null) {
+				fireEmployee(treeTask);
+				return false; //MESSAGE
+			}
+			TreeVector trees;
+			if (treeVectors.length ==1)
+				trees = (TreeVector)treeVectors[0];
+			else
+				trees = (TreeVector)ListDialog.queryList(containerOfModule(), "Choose Trees Block", "Choose block of trees from which to choose a tree for export to  Pagel format (ppy) file", MesquiteString.helpString, treeVectors, 0);
+			if (trees == null) {
+				fireEmployee(treeTask);
+				return false; //MESSAGE
+			}
+			tree = (Tree)ListDialog.queryList(containerOfModule(), "Choose Tree", "Choose tree for export to Pagel format (ppy) file", MesquiteString.helpString, trees, 0);
+		}
+		if (tree == null) {
+			fireEmployee(treeTask);
+			return false; //MESSAGE
+		}
+			
+			
+		// convert polytomies to zeroLengthBranches
+		sanitizeTree(tree);
+		
+		//choose two binary character distributions
+		String[] charNames = new String[data.getNumChars()];
+		for (int i=0; i<data.getNumChars(); i++)
+			charNames[i]= data.getCharacterName(i);
+ 			
+		int numCharacters = 1;
+		int nc = MesquiteInteger.queryInteger(containerOfModule(), "How many characters?", "How many characters to put into ppy file?", 1, 1, data.getNumChars(), false);
+		if (MesquiteInteger.isCombinable(nc))
+			numCharacters = nc;
+		
+		int numSelected = 0;
+		String which = "first";
+		CategoricalDistribution[] chosenChars = new CategoricalDistribution[numCharacters];
+		while (numSelected<numCharacters){
+ 			int chosen = ListDialog.queryList(containerOfModule(), "Choose character", "Choose " + which + " character for export to Pagel format (ppy) file", MesquiteString.helpString, charNames, 0);
+			if (chosen >=0 ){
+				CategoricalDistribution distn = (CategoricalDistribution)data.getCharacterDistribution(chosen);
+				long allStates = 0L;
+				boolean uncombinableState = false;
+				boolean polymorphisms = false;
+				for (int it = 0; it < distn.getNumTaxa() && !uncombinableState; it++) {
+					long state = distn.getState(it);
+					if (!CategoricalState.isCombinable(state))
+						uncombinableState = true;
+					if (CategoricalState.cardinality(state)>1)
+						polymorphisms = true;
+					allStates |= state;
+				}
+				if (uncombinableState)
+					alert("Sorry, that character can't be used because it has missing or inapplicable codings");
+				else if (polymorphisms)
+					alert("Sorry, that character can't be used because it has polymorphisms or uncertainties.");
+				else if (CategoricalState.maximum(allStates)>5) //allow multistate output for MultiState!
+					alert("Sorry, that character can't be used because it has a state other than 0, 1, 2, 3, 4, or 5");
+				else {
+					chosenChars[numSelected] = distn;
+					numSelected++;
+					which = "next";
+				}
+			}
+			else {
+				fireEmployee(treeTask);
+				return false; //MESSAGE
+			}
+		}
+		
+		int numTaxa = tree.numberOfTerminalsInClade(tree.getRoot());
+		StringBuffer outputBuffer = new StringBuffer(numTaxa*12);
+		outputBuffer.append(Integer.toString(numTaxa) + " " + numCharacters + "\r\n");
+
+		outputBuffer.append("#Translated to Pagel format for Multistate from project with home file " + getProject().getHomeFileName());
+		outputBuffer.append("\r\n");
+		outputBuffer.append("# Block of taxa: " + taxa.getName());
+		outputBuffer.append("\r\n");
+
+		for (int i=0; i<numCharacters; i++){
+			outputBuffer.append("# Character " + (i+1) + ": " + chosenChars[i].getName() + " of data matrix " + data.getName());
+			outputBuffer.append("\r\n");
+		}
+
+		outputBuffer.append("# Tree: " + tree.getName());
+		outputBuffer.append("\r\n");
+		int[] numbers = new int[tree.getNumNodeSpaces()];
+		MesquiteInteger nodeCount = new MesquiteInteger(numTaxa+1);
+		numberNodes(tree, tree.getRoot(), numbers, nodeCount);
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (tree.taxonInTree(it)) {
+					int node = tree.nodeOfTaxonNumber(it);
+					outputBuffer.append('t'); //t for taxon
+					outputBuffer.append(Integer.toString(it+1)); //taxon number
+					outputBuffer.append(','); 
+					outputBuffer.append(numbers[tree.motherOfNode(node)]);  //ancestor node
+					outputBuffer.append(','); 
+					outputBuffer.append(MesquiteDouble.toStringNoNegExponential(tree.getBranchLength(node, 1.0)));
+					outputBuffer.append(','); 
+					for (int ic = 0; ic<numCharacters; ic++){ //writing out character states
+						long cs1 = chosenChars[ic].getState(it);
+						if (CategoricalState.isElement(cs1, 0))
+							outputBuffer.append('0'); 
+						else if (CategoricalState.isElement(cs1, 1))
+							outputBuffer.append('1'); 
+						else if (CategoricalState.isElement(cs1, 2))
+							outputBuffer.append('2'); 
+						else if (CategoricalState.isElement(cs1, 3))
+							outputBuffer.append('3'); 
+						else if (CategoricalState.isElement(cs1, 4))
+							outputBuffer.append('4'); 
+						else if (CategoricalState.isElement(cs1, 5))
+							outputBuffer.append('5'); 
+
+						if (ic<numCharacters-1)
+							outputBuffer.append(','); 
+					}
+					outputBuffer.append("\r\n");
+				}
+		}
+
+		StringBuffer equivalenceBuffer = new StringBuffer(50);
+		equivalenceBuffer.append("#Table of equivalencies of nodes with Mesquite's node numbering system\r\n");
+		outputInternals(tree, tree.getRoot(), numbers, outputBuffer, equivalenceBuffer);
+
+//table of equivalencies of nodes
+		outputBuffer.append("\r\n");
+		outputBuffer.append("\r\n");
+		outputBuffer.append(equivalenceBuffer.toString());
+		String output = outputBuffer.toString();
+		
+		String name = getProject().getHomeFileName();
+		if (name==null)
+			name = "untitled.ppy";
+		else 
+			name = stripNex(name) + ".ppy";
+		saveExportedFile(output, arguments, name);
+		fireEmployee(treeTask);
+		return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Pagel format (ppy) file for Multistate";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Imports and exports files formatted for Pagel's Multistate program." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+}
+	
+
diff --git a/Source/mesquite/stochchar/LikelihoodInCharacter/LikelihoodInCharacter.java b/Source/mesquite/stochchar/LikelihoodInCharacter/LikelihoodInCharacter.java
new file mode 100644
index 0000000..32e04bd
--- /dev/null
+++ b/Source/mesquite/stochchar/LikelihoodInCharacter/LikelihoodInCharacter.java
@@ -0,0 +1,225 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.LikelihoodInCharacter;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+
+
+/* ======================================================================== */
+public class LikelihoodInCharacter extends NumberForTree implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharacterLikelihood.class, getName() + "  needs a method to calculate likelihoods.",
+		"The method to calculate likelihoods can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"The source of characters is arranged initially");
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber steps;
+	CharSourceCoordObed characterSourceTask;
+	CharacterLikelihood charLikelihoodTask;
+	Taxa oldTaxa = null;
+	long oldTreeID = 0;
+	long oldTreeVersion = 0;
+	CharacterDistribution charStates;
+	int currentChar = 0;
+	MesquiteCommand cltC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+    	 	steps=new MesquiteNumber();
+ 		characterSourceTask = (CharSourceCoordObed)hireEmployee(CharSourceCoordObed.class, "Source of character");
+ 		if (characterSourceTask == null)
+ 			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+ 		charLikelihoodTask = (CharacterLikelihood)hireEmployee(CharacterLikelihood.class, null);
+ 		if (charLikelihoodTask == null)
+ 			return sorry(getName() + " couldn't start because no likelihood calculator module was obtained.");
+		addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	if (m==charLikelihoodTask || m == characterSourceTask)
+  	 		iQuit();
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		characterSourceTask.initialize(tree.getTaxa());
+   	}
+   	/*.................................................................................................................*/
+   	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) { 
+   		if (result==null || tree == null || charLikelihoodTask == null)
+   			return;
+	   	clearResultAndLastResult(result);
+  		steps.setValue((int)0);
+   		Taxa taxa = tree.getTaxa();
+   		if (taxa != oldTaxa || (characterSourceTask.usesTree() && (tree.getID() != oldTreeID || tree.getVersionNumber() != oldTreeVersion))) {
+   			currentChar = 0;
+   			charStates = characterSourceTask.getCharacter(tree, currentChar);
+   			oldTreeID = tree.getID();
+   			oldTreeVersion = tree.getVersionNumber();
+   		}
+   		else if (charStates == null) {
+   			charStates = characterSourceTask.getCharacter(tree, currentChar);
+   		}
+
+   		MesquiteNumber num=new MesquiteNumber();
+   		charLikelihoodTask.calculateNumber(tree, charStates, num, resultString);
+   		steps.setValue(num);
+   		oldTaxa = taxa;
+   		result.setValue(steps);
+   		if (resultString!=null) {
+   			resultString.append(" (char. " + CharacterStates.toExternal(currentChar) + ")");
+   		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+  	}
+   	/*.................................................................................................................*/
+   	public boolean biggerIsBetter() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	if (employee==characterSourceTask) {
+			if (currentChar<0 || currentChar>=characterSourceTask.getNumberOfCharacters(oldTaxa))
+				currentChar = 0;
+   			charStates = null;
+			parametersChanged(notification);
+   	 	}
+   	 	else 
+   	 		parametersChanged(notification);
+   	 }
+	/*.................................................................................................................*/
+   	 public void setCurrent(long i){
+ 		if (characterSourceTask==null || oldTaxa==null)
+ 			return;
+ 		if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+ 			currentChar = (int)i;
+			charStates=null;
+			//parametersChanged();
+		}
+   	 }
+ 	public String getItemTypeName(){
+ 		return "Character";
+ 	}
+	/*.................................................................................................................*/
+ 	public long toInternal(long i){
+ 		return(CharacterStates.toInternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+ 	public long toExternal(long i){
+ 		return(CharacterStates.toExternal((int)i));
+ 	}
+	/*.................................................................................................................*/
+   	 public long getCurrent(){
+   	 	return currentChar;
+   	 }
+	/*.................................................................................................................*/
+ 	public long getMin(){
+ 		return 0;
+ 	}
+	/*.................................................................................................................*/
+ 	public long getMax(){
+ 		if (characterSourceTask==null || oldTaxa==null)
+ 			return 0;
+ 		return characterSourceTask.getNumberOfCharacters(oldTaxa)-1;
+ 	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getCharacterSource ", characterSourceTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+ 			return characterSourceTask.doCommand(commandName, arguments, checker);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+ 			return characterSourceTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) { 
+    	 		if (currentChar>=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)
+    	 			currentChar=0;
+    	 		else
+    	 			currentChar++;
+			charStates = null;
+ 			parametersChanged(); 
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+    	 		if (currentChar<=0)
+    	 			currentChar=characterSourceTask.getNumberOfCharacters(oldTaxa)-1;
+    	 		else
+    	 			currentChar--;
+   			charStates = null;
+ 			parametersChanged(); 
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Queries the user about which character to use", null, commandName, "chooseCharacter")) {
+    	 		int ic=characterSourceTask.queryUserChoose(oldTaxa, " for likelihood calculation ");
+    	 		if (MesquiteInteger.isCombinable(ic)) {
+	   			currentChar = ic;
+	   			charStates = null;
+	 			parametersChanged();
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the character to be used", "[number of character]", commandName, "setCharacter")) {
+    	 		int ic = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+    	 		if (!MesquiteInteger.isCombinable(ic))
+    	 			return null;
+    	 		if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(oldTaxa)-1)) {
+    	 			currentChar = ic; //shouldn't this be internal????
+	   			charStates = null;
+	 			parametersChanged(); 
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		return "Character Source: " + characterSourceTask.getNameAndParameters();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "-ln Likelihood";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Likelihood in Character";
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates the negative log likelihood of a tree with respect to a single character." ;
+   	 }
+}
+
diff --git a/Source/mesquite/stochchar/ManageCharModelsBlock/ManageCharModelsBlock.java b/Source/mesquite/stochchar/ManageCharModelsBlock/ManageCharModelsBlock.java
new file mode 100644
index 0000000..6a5c6a3
--- /dev/null
+++ b/Source/mesquite/stochchar/ManageCharModelsBlock/ManageCharModelsBlock.java
@@ -0,0 +1,155 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.ManageCharModelsBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== 
+Manages the block with stochastic models of evolutoin */
+public class ManageCharModelsBlock extends FileInit {
+	int numBlocks =0;
+	public Class getDutyClass(){
+		return ManageCharModelsBlock.class;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	/*.................................................................................................................*/
+ 	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+ 	public void fileReadIn(MesquiteFile f) {
+ 		NexusBlock[] bs = getProject().getNexusBlocks(ProbCharModelsBlock.class, f);
+		if (bs == null || bs.length ==0){ 
+			ProbCharModelsBlock ab = new ProbCharModelsBlock(f, this);
+			numBlocks++;
+			addNEXUSBlock(ab);
+		}
+		
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new ProbCharModelsBlockTest();}
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		int c = 0;
+		String s;
+		ProbCharModelsBlock ab;
+ 		NexusBlock[] bs = getProject().getNexusBlocks(ProbCharModelsBlock.class, file);  //only one per file
+ 		if (bs == null || bs.length == 0)
+ 			ab = new ProbCharModelsBlock(file, this);
+ 		else
+ 			ab = (ProbCharModelsBlock)bs[0];
+		MesquiteString comment = new MesquiteString();
+		while (!StringUtil.blank(s=block.getNextFileCommand(comment))) {
+			String commandName = parser.getFirstToken(s);
+			if (!commandName.equalsIgnoreCase("BEGIN") && !commandName.equalsIgnoreCase("END") && !commandName.equalsIgnoreCase("ENDBLOCK"))
+				readUnrecognizedCommand(file, ab, "MESQUITECHARMODELS", block, commandName, s, blockComments, comment);
+		}
+		numBlocks++;
+		return ab; 
+	}
+
+	/*.................................................................................................................*/
+	public String employeesGetCommands(MesquiteModule module, MesquiteFile mf) {
+		Enumeration enumeration=module.getEmployeeVector().elements();
+		MesquiteModule employee;
+		String commands="";
+		while (enumeration.hasMoreElements()){
+			Object obj = enumeration.nextElement();
+			employee = (MesquiteModule)obj;
+			String command =employee.getNexusCommands(mf, "MESQUITECHARMODELS");
+			if (!StringUtil.blank(command))
+				commands+="\t"+command + StringUtil.lineEnding();
+			commands+=employeesGetCommands(employee, mf);
+		}
+		return commands;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage MESQUITECHARMODELS blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages MESQUITECHARMODELS block in NEXUS file." ;
+   	 }
+}
+	
+	
+	
+class ProbCharModelsBlock extends NexusBlock {
+	public ProbCharModelsBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+ 	/*.................................................................................................................*/
+ 	/** gets the explanation of this matrix*/
+	public String getExplanation() {
+		return "This character models block belongs to the file \"" + getFile().getName() + "\"";
+
+	}
+	public boolean contains(FileElement e) {
+		return false;  //always false; needs to use other means to determine if need to create block
+	}
+	public void written() {
+		MesquiteMessage.warnProgrammer("probcharmodels block clean");
+	}
+	public String getName(){
+		return "MESQUITECHARMODELS block";
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		return (block.getBlockName().equalsIgnoreCase("TAXA") ||  block.getBlockName().equalsIgnoreCase("SETS") ||  block.getBlockName().equalsIgnoreCase("CHARACTERS") ||  block.getBlockName().equalsIgnoreCase("SETS") ||  block.getBlockName().equalsIgnoreCase("LABELS"));
+		
+	}
+	public String getBlockName(){
+		return "MESQUITECHARMODELS";
+	}
+	public String getNEXUSBlockContents(){
+		return ((ManageCharModelsBlock)getManager()).employeesGetCommands(getManager().getFileCoordinator(), getFile());
+	}
+	public String getNEXUSBlock(){
+		String contents = getNEXUSBlockContents();
+		contents=contents.trim();
+		String unrec = getUnrecognizedCommands();
+		unrec = unrec.trim();
+		if (StringUtil.blank(contents) && StringUtil.blank(unrec))
+			return null;
+		String blocks="BEGIN " + getBlockName() + ";" + StringUtil.lineEnding()+ "\t"+contents + StringUtil.lineEnding();
+		if (!StringUtil.blank(unrec)) {
+			blocks += StringUtil.lineEnding()+ "\t" + unrec + StringUtil.lineEnding();
+		}
+		blocks += "END;" + StringUtil.lineEnding();
+		return blocks;
+	}
+}/* ======================================================================== */
+class ProbCharModelsBlockTest extends NexusBlockTest  {
+	public ProbCharModelsBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("MESQUITECHARMODELS");
+	}
+}
+
+
diff --git a/Source/mesquite/stochchar/ManageProbModelSets/ManageProbModelSets.java b/Source/mesquite/stochchar/ManageProbModelSets/ManageProbModelSets.java
new file mode 100644
index 0000000..e4a61b7
--- /dev/null
+++ b/Source/mesquite/stochchar/ManageProbModelSets/ManageProbModelSets.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.ManageProbModelSets;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ManageProbModelSets extends CharSpecsSetManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.stochchar.ProbModelSetList.ProbModelSetList.class, getName() + "  uses an assistant to display a list window.",
+		"The assistant is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	
+	/*.................................................................................................................*/
+ 	public void fileElementAdded(FileElement element) {
+		
+ 		if (element instanceof CharacterData) {
+	 		if (getProject()==null)
+	 			System.out.println("project is null in iMS Init Prob");
+			ProbabilityModelSet currentLikelihoodModels;
+	 		CharacterModel defaultModel=null;
+	 		CharacterData data = (CharacterData)element;
+	 		if (data.getCurrentSpecsSet(ProbabilityModelSet.class) == null) {
+		 		defaultModel =  data.getDefaultModel("Likelihood");
+		 		currentLikelihoodModels= new ProbabilityModelSet("UNTITLED", data.getNumChars(), defaultModel, data);
+		 		currentLikelihoodModels.addToFile(element.getFile(), getProject(), null);
+		 		data.setCurrentSpecsSet(currentLikelihoodModels, ProbabilityModelSet.class);
+		 	}
+	 		if (getProject().getCharacterModels()==null)
+	 			System.out.println("charModels null in iMS Init Prob");
+		 }
+ 		 
+	}
+	/*.................................................................................................................*/
+	public void elementsReordered(ListableVector v){
+	}
+	public Class getElementClass(){
+		return ProbabilityModelSet.class;
+	}
+	public String upperCaseTypeName(){
+		return "Probability Model Set";
+	}
+	public String lowerCaseTypeName(){
+		return "probability model set";
+	}
+	public String nexusToken(){
+		return "ProbModelSet";
+	}
+	public String alternativeNexusToken(){
+		return "MODELSET";
+	}
+	public Object getSpecification(String token){
+		return getProject().getCharacterModel((token));
+	}
+	public void setSpecification(SpecsSet specsSet, Object specification, int ic){
+		if (specsSet==null || !(specsSet instanceof ProbabilityModelSet) || !(specification instanceof CharacterModel))
+			return;
+		ObjectSpecsSet sS = (ObjectSpecsSet)specsSet;
+		sS.setProperty(specification,ic);
+	}
+	public SpecsSet getNewSpecsSet(String name, CharacterData data){
+		CharacterModel defaultModel =  data.getDefaultModel("Probability");
+ 		return new ProbabilityModelSet(name, data.getNumChars(), defaultModel, data);
+	}
+	public boolean appropriateBlockForWriting(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("MESQUITECHARMODELS");
+	}
+	public boolean appropriateBlockForReading(String blockName){
+		if (blockName == null)
+			return false;
+		return blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS") || blockName.equalsIgnoreCase("MESQUITECHARMODELS");
+	}
+	/*.................................................................................................................*/
+	public String nexusStringForSpecsSet(CharSpecsSet specsSet, CharacterData data, MesquiteFile file, boolean isCurrent){
+		return nexusStringForSpecsSetStandard(specsSet,data,file,isCurrent);
+   	}
+	/*.................................................................................................................*/
+	public NexusCommandTest getNexusCommandTest(){ 
+		return new ModelsetNexusCommandTest();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Manage probability model sets";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Manages (including NEXUS read/write) probability model sets (PROBMODELSETs)." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+class ModelsetNexusCommandTest  extends NexusCommandTest{
+	public boolean readsWritesCommand(String blockName, String commandName, String command){  //returns whether or not can deal with command
+		return ((blockName.equalsIgnoreCase("SETS") || blockName.equalsIgnoreCase("ASSUMPTIONS") || blockName.equalsIgnoreCase("MESQUITECHARMODELS")) && (commandName.equalsIgnoreCase("MODELSET") || commandName.equalsIgnoreCase("PROBMODELSET")));
+	}
+}
+
+
diff --git a/Source/mesquite/stochchar/MargProbAncStates/MargProbAncStates.java b/Source/mesquite/stochchar/MargProbAncStates/MargProbAncStates.java
new file mode 100644
index 0000000..ffec136
--- /dev/null
+++ b/Source/mesquite/stochchar/MargProbAncStates/MargProbAncStates.java
@@ -0,0 +1,248 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.MargProbAncStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+import mesquite.stochchar.CurrentProbModels.*;
+
+/* ======================================================================== */
+public class MargProbAncStates extends CharStatesForNodes {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ProbModelSourceLike.class, getName() + " needs an indication of what probabilistic model to apply to the character.",
+		"The indicator of probabilistic models can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(MargLikeAncStForModel.class, getName() + "  needs methods to calculate likelihoods.",
+		"The methods to calculate likelihoods are chosen automatically according to the probability model used in the calculation");
+	}
+	/*.................................................................................................................*/
+	CharacterDistribution observedStates;
+	MargLikeAncStForModel reconstructTask;
+	ProbModelSourceLike modelTask;
+	MesquiteString modelTaskName;
+	CharacterModel model;
+	MesquiteNumber likelihood;
+	boolean warnedNoCalc = false;
+	CharacterHistory statesAtNodes;
+	int oldNumTaxa;
+	boolean oneAtATime = false;
+	boolean oneAtATimeCHGBL = false;
+	
+	public String getMappingTypeName(){
+		return "Realization";
+	}
+	/*  following is for showing likelihood surfaces; not yet working
+	double[] inputBounds, outputBounds;
+	MatrixCharter surfaceTask;
+	MesquiteCMenuItemSpec showSurfaceItem=null;
+	MesquiteBoolean showSurface;
+	*/
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		hireAllEmployees(MargLikeAncStForModel.class);
+ 		if (modelTask == null)
+ 			modelTask = (ProbModelSourceLike)hireEmployee(ProbModelSourceLike.class, "Source of probability character models (for likelihood calculations)");
+ 		if (modelTask == null)
+ 			return sorry(getName() + " couldn't start because no source of models of character evolution obtained.");
+ 		modelTaskName = new MesquiteString(modelTask.getName());
+ 		likelihood = new MesquiteNumber();
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Source of probability models", makeCommand("setModelSource", this), ProbModelSourceLike.class);
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(ProbabilityCategCharModel.class, null));
+		mss.setSelected(modelTaskName);
+		//showSurface = new MesquiteBoolean(false); this is for showing likelihood surfaces; not yet working
+ 		return true;
+ 	}
+
+ 	
+   	public void setOneCharacterAtATime(boolean chgbl){
+		oneAtATimeCHGBL = chgbl;
+		oneAtATime = true;
+   		modelTask.setOneCharacterAtATime(chgbl);
+		/* this is for showing likelihood surfaces; not yet working
+		if (oneAtATime){
+			if (showSurfaceItem==null) {
+				showSurfaceItem = addCheckMenuItem(null, "Show Likelihood Surface", makeCommand("showSurface", this), showSurface);
+ 				resetContainingMenuBar();
+ 			}
+		}
+		else if (showSurfaceItem !=null){
+			deleteMenuItem(showSurfaceItem);
+			showSurfaceItem = null;
+		}
+		*/
+   	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setModelSource ",modelTask);
+  	 	return temp;
+  	 }
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets module used to supply character models", "[name of module]", commandName, "setModelSource")) {
+    	 		ProbModelSourceLike temp=  (ProbModelSourceLike)replaceEmployee(ProbModelSourceLike.class, arguments, "Source of probability character models", modelTask);
+ 			if (temp!=null) {
+ 				modelTask= temp;
+ 				incrementMenuResetSuppression();
+ 				modelTaskName.setValue(modelTask.getName());
+ 				if (oneAtATime)
+ 					modelTask.setOneCharacterAtATime(oneAtATimeCHGBL);
+				parametersChanged();
+ 				decrementMenuResetSuppression();
+ 			}
+ 			return modelTask;
+    	 	}
+    	 	/*  this is for showing likelihood surfaces; not yet working
+    	 	else if (checker.compare(this.getClass(), "Shows likelihood surface", null, commandName, "showSurface")) {
+ 			surfaceTask = (MatrixCharter)hireEmployee(MatrixCharter.class, "Display method for likelihood surface");
+ 			outputBounds = new double[4];
+ 			return surfaceTask;
+    	 	}
+    	 	*/
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+ 	
+	/*.................................................................................................................*/
+ 	public void employeeQuit(MesquiteModule m){
+ 		if (m == modelTask)
+ 			iQuit();
+ 	}
+	public boolean allowsStateWeightChoice(){
+		return true;
+	}
+ 	boolean warned = false;
+ 	CharacterData oldData = null;
+	/*.................................................................................................................*/
+	public  boolean calculateStates(Tree tree, CharacterDistribution observedStates, CharacterHistory resultStates, MesquiteString resultString) {  
+		this.observedStates = observedStates;
+		if (tree==null || observedStates==null || resultStates == null)
+			return false;
+		resultStates.deassignStates();
+		likelihood.setToUnassigned();
+		
+		//a barrier (temporary) while likelihood calculations support only simple categorical
+		Class stateClass = observedStates.getStateClass();
+		if (DNAState.class.isAssignableFrom(stateClass) || ProteinState.class.isAssignableFrom(stateClass) || ContinuousState.class.isAssignableFrom(stateClass)) {
+			String s = "Likelihood calculations cannot be performed ";
+			if (DNAState.class.isAssignableFrom(stateClass))
+				s += "currently with DNA or RNA data.  The calculations were not done for some characters.";
+			else if (ProteinState.class.isAssignableFrom(stateClass))
+				s += "currently with protein data.  The calculations were not done for some characters.";
+			else if (ContinuousState.class.isAssignableFrom(stateClass))
+				s += "currently with continuous valued data.  The calculations were not done for some characters.";
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return false;
+		}
+
+
+		boolean success = false;
+		model = modelTask.getCharacterModel(observedStates);
+		if (model == null && !MesquiteThread.isScripting()){
+			if (observedStates.getParentData()!= oldData)
+				warned = false;
+			if (!warned){
+				if (observedStates.getParentData()!=null && modelTask instanceof CurrentProbModels) {
+					oldData = observedStates.getParentData();
+					if (AlertDialog.query(containerOfModule(), "Assign models?", "There are currently no probability models assigned to the characters.  Do you want to assign a model to all characters unassigned?")) {
+						((CurrentProbModels)modelTask).chooseAndFillUnassignedCharacters(observedStates.getParentData());
+						model = modelTask.getCharacterModel(observedStates);
+					}
+				}
+				else {
+					if (resultString!=null)
+						resultString.setValue("Likelihood calculations cannot be accomplished because no probabilistic model of evolution is available for the character");
+					discreetAlert( "Sorry, there is no probabilistic model of evolution available for the character; likelihood calculations cannot be accomplished.  Please make sure that the source of models chosen is compatible with this character type.");
+					warned = true;
+					return false;
+				}
+			}
+			warned = true;
+		}
+		
+		if (reconstructTask == null || !reconstructTask.compatibleWithContext(model, observedStates)) { 
+			reconstructTask = null;
+			for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof MargLikeAncStForModel)
+					if (((MargLikeAncStForModel)e).compatibleWithContext(model, observedStates)) {
+						reconstructTask=(MargLikeAncStForModel)e;
+					}
+			}
+		}
+		if (reconstructTask != null) { 
+			reconstructTask.calculateStates( tree,  observedStates,  resultStates, model, resultString, likelihood);
+			/*   this is for showing likelihood surfaces; not yet working
+			if (oneAtATime && surfaceTask!=null && !((ProbabilityModel)model).isFullySpecified() && showSurface.getValue()){
+				Object surface = reconstructTask.getLikelihoodSurface(tree,  observedStates, model, inputBounds, outputBounds);
+				surfaceTask.setMatrix((double[][])surface, outputBounds[0], outputBounds[1], outputBounds[2], outputBounds[3]);
+			}
+			*/
+			if (resultString!=null)
+				resultString.append(" Calc. by " + reconstructTask);
+			success=true;
+		}
+		else {
+			String s = "Likelihood calculations cannot be performed because no module was found to perform the calculations for the probability model \"" + model.getName() + "\" with the characters specified.";
+				
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+		}
+		statesAtNodes=resultStates;
+		return success;
+	}
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Likelihood Ancestral States";
+   	 }
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Coordinates reconstruction of ancestral states by maximum likelihood.  Currently each node is estimated independently (i.e., corresponding to PAUP's marginal reconstruction)." ;
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/stochchar/Mk1Rate/Mk1Rate.java b/Source/mesquite/stochchar/Mk1Rate/Mk1Rate.java
new file mode 100644
index 0000000..ba721e8
--- /dev/null
+++ b/Source/mesquite/stochchar/Mk1Rate/Mk1Rate.java
@@ -0,0 +1,127 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.Mk1Rate;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+/**Calculates a number for a character and a tree.*/
+
+public class Mk1Rate extends NumberForCharAndTree  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.stochchar.zMargLikeCateg.zMargLikeCateg.class, getName() + "  needs a module to calculate likelihoods.",
+		"The module to calculate likelihoods is arranged automatically");
+	}
+	MargLikelihoodForModel reconstructTask = null;
+	MkModel mk1Model;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		reconstructTask = (MargLikelihoodForModel)hireNamedEmployee(MargLikelihoodForModel.class, "#zMargLikeCateg");
+ 		if (reconstructTask == null)
+ 			return sorry(getName() + " couldn't start because no likelihood calculator obtained");
+ 		mk1Model = new MkModel("Estimating mk1", CategoricalState.class);
+		getProject().getCentralModelListener().addListener(this);
+ 		return true; 
+ 	}
+ 	
+	/*.................................................................................................................*/
+	public void endJob() {
+		getProject().getCentralModelListener().removeListener(this);
+		super.endJob();
+  	 }
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj instanceof Class && MkModel.class.isAssignableFrom((Class)obj)) {
+				parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+ 	/*.................................................................................................................*/
+ 	/** returns whether this module is requesting to appear as a primary choice */
+    	public boolean requestPrimaryChoice(){
+    		return true;  
+    	}
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree, CharacterDistribution charStates){
+   	}
+	MesquiteString resultStringMk1 = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(Tree tree, CharacterDistribution observedStates, MesquiteNumber result, MesquiteString resultString) {  
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree==null || observedStates==null) {
+			if (resultString!=null)
+				resultString.setValue("Likelihood ratio unassigned because no tree or no character supplied");
+			return;
+		}
+	
+
+		if (reconstructTask != null) {
+			
+			mk1Model.setInstantaneousRate(MesquiteDouble.unassigned, false);
+			reconstructTask.estimateParameters( tree,  observedStates, mk1Model, resultStringMk1);
+			result.setValue(mk1Model.getInstantaneousRate());
+			if (resultString!=null) {
+				resultString.setValue("Rate assuming mk1 model: " + resultStringMk1.getValue());
+			}
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+   
+	/*.................................................................................................................*/
+    	 public boolean showCitation() {
+		return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Mk1 Rate";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Mk1 Estimated Rate";
+   	 }
+ 	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Estimates the rate of a character's evolution under the simple Mk1 model." ;
+   	 }
+   	 
+   	public String getParameters(){
+   		if (mk1Model !=null)
+   			return " Mk1 Model settings: " +  mk1Model.getSettingsString();
+   		return null;
+   	}
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresExactlyCategoricalData();
+	}
+ 
+}
+
+
diff --git a/Source/mesquite/stochchar/MkModelCurator/MkModelCurator.java b/Source/mesquite/stochchar/MkModelCurator/MkModelCurator.java
new file mode 100644
index 0000000..94b9252
--- /dev/null
+++ b/Source/mesquite/stochchar/MkModelCurator/MkModelCurator.java
@@ -0,0 +1,165 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.MkModelCurator;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+/* ======================================================================== */
+public class MkModelCurator extends CategProbModelCurator implements EditingCurator, CuratorWithSettings  {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		
+		 EmployeeNeed e = registerEmployeeNeed(WindowHolder.class, getName() + " needs assistance to hold a window" ,
+				 "This is arranged automatically");
+	}
+		 MkModel defaultModel;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+ 		defaultModel = new MkModel("Mk1 (est.)", CategoricalState.class);
+    		defaultModel.setBuiltIn(true);
+		CategoricalData.registerDefaultModel("Likelihood", defaultModel.getName());
+		return true;
+  	 }
+	/*.................................................................................................................*/
+  	 public void projectEstablished(){
+    		defaultModel.addToFile(null, getProject(), null);
+    		super.projectEstablished();
+  	 }
+   
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			double mode = MesquiteDouble.fromString(prefs[0]);
+			if (MesquiteDouble.isCombinable(mode))
+				MkModel.optWidth = mode;
+		}
+	}
+	
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "optWidth", MkModel.optWidth);  
+		return buffer.toString();
+	}
+	
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("optWidth".equalsIgnoreCase(tag))
+			MkModel.optWidth = MesquiteDouble.fromString(content);
+	}
+
+
+	/*.................................................................................................................*/
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof MkModel){
+	 		MkModel model = (MkModel)obj;
+	 		int i = getModelNumber(model);
+	 		if (i>=0) {
+	 			SliderWindow dsw = (SliderWindow)getWindow(i);
+	 			if (dsw==null)
+	 				return;
+	 			dsw.setAllowEstimation(model instanceof CModelEstimator);
+				dsw.setText(model.getName() + " (max.State: " + model.getMaxState() + ")");
+				dsw.getSlider().setCurrentValue(model.getInstantaneousRate());
+	 		}
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+   	public MesquiteModule editModelNonModal(CharacterModel model, ObjectContainer w){
+		if (model!=null && model instanceof MkModel) {
+	   		MkModel modelToEdit =  ((MkModel)model);
+			double a = modelToEdit.getInstantaneousRate();
+			
+			MesquiteModule windowServer = hireNamedEmployee(WindowHolder.class, "#WindowBabysitter");
+			if (windowServer == null)
+				return null;
+			SliderWindow sw = new SliderWindow(windowServer, "Edit model", modelToEdit.getName() + " (max.State: " + ((MkModel)modelToEdit).getMaxState() + ")", makeCommand("setRate", modelToEdit), modelToEdit.getInstantaneousRate(), 0, MesquiteDouble.infinite,0, 1); //should allow more than one????
+			windowServer.setModuleWindow(sw);
+			windowServer.makeMenu("Mk1_Model");
+			windowServer.addMenuItem("Set Maximum Allowed State...", makeCommand("setMaxState",  modelToEdit));
+			sw.useExponentialScale(true);
+			sw.setAllowEstimation(modelToEdit instanceof CModelEstimator);
+			
+			//setModuleWindow(new JCEditor(this, modelToEdit)); //should allow more than one????
+			MesquiteWindow.centerWindow(sw);
+			if (w!=null)
+				w.setObject(sw);
+				
+			return windowServer;
+		}
+		return this;
+   	}
+		/*if (modal){
+			a = MesquiteDouble.queryDouble(containerOfModule(), "Markov k-state model rate", "Set rate of Markov k-state model", a);
+			modelToEdit.setInstantaneousRate(a);
+		}
+		else */
+
+	public void editSettings(){
+		double d = MesquiteDouble.queryDouble(containerOfModule(), "Mk1 Optimization Settings", "By default, optimization of parameter of Mk1 model surveys across intervals of width 1, then of width 10, then chooses best result.  Otherwise, you can indicate a single width to survey.  Wider interval may mean finding optimum more quickly when rates are high, but may make less accurate when rates are low.  Suggested: 1.0 to 20.0.  To use the default method, enter 0.0", MkModel.optWidth, 0, 100);
+		if (MesquiteDouble.isCombinable(d)) {
+			MkModel.optWidth = d;
+			Notification nn = null;
+			CentralModelListener.staticChanged(this, MkModel.class, nn = new Notification());
+			CentralModelListener.staticChanged(this, AsymmModel.class, nn); //temporary; while AsymmModel might use MkModel.optWidth
+		 	storePreferences();
+		}
+		
+	}
+	public boolean curatesModelClass(Class modelClass){
+		return MkModel.class.isAssignableFrom(modelClass);
+	}
+	/*.................................................................................................................*/
+	public String getNameOfModelClass() {
+		return "Mk1 (Markov 1 parameter)";
+	}
+	/*.................................................................................................................*/
+	public String getNEXUSNameOfModelClass() {
+		return "Mk1";
+	}
+	/*.................................................................................................................*/
+	public Class getModelClass() {
+		return MkModel.class;
+	}
+	/*.................................................................................................................*/
+   	public CharacterModel makeNewModel(String name) {
+ 		MkModel model = new MkModel(name, CategoricalState.class);
+ 		model.setMaxStateDefined(1);
+       		return model;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterModel readCharacterModel(String name, MesquiteInteger stringPos, String description, int format) {
+ 		MkModel model = new MkModel( name, CategoricalState.class);
+   		model.fromString(description, stringPos, format);
+  		return model;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Mk1 Model (Markov 1 parameter)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Defines and maintains simple Markov k-state 1-parameter stochastic models (Lewis, 2001) of character evolution." ;
+   	 }
+}
+
+
diff --git a/Source/mesquite/stochchar/ProbModelSetList/ProbModelSetList.java b/Source/mesquite/stochchar/ProbModelSetList/ProbModelSetList.java
new file mode 100644
index 0000000..264b989
--- /dev/null
+++ b/Source/mesquite/stochchar/ProbModelSetList/ProbModelSetList.java
@@ -0,0 +1,96 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.ProbModelSetList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.*;
+
+
+
+/* ======================================================================== */
+public class ProbModelSetList extends DataSpecssetList {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("List");
+		addMenuItem("Make New Probability Model Set...", makeCommand("newProbModelSet",  this));
+		return true;
+  	 }
+	/** returns a String of annotation for a row*/
+	public String getAnnotation(int row){ return null;}
+
+	/** sets the annotation for a row*/
+	public void setAnnotation(int row, String s, boolean notify){}
+	public Class getItemType(){
+		return ProbabilityModelSet.class;
+	}
+	public String getItemTypeName(){
+		return "Probability model set";
+	}
+	public String getItemTypeNamePlural(){
+		return "Probability model sets";
+	}
+	public SpecsSet makeNewSpecsSet(CharacterData data){
+		if (data!=null)
+			return new ProbabilityModelSet("Probability Model Set", data.getNumChars(), data.getDefaultModel("Likelihood"), data);
+		return null;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Instructs user as how to make new probability model set", null, commandName, "newProbModelSet")){
+			Object obj = getMainObject();
+			if (!(obj instanceof CharacterData))
+				return null;
+			CharacterData data = (CharacterData)obj;
+			if (data !=null &&AlertDialog.query(containerOfModule(), "New Model Set", "To make a new probability model set, go to the List of Characters window, make sure that a column for Current Probability Model appears, edit the column, then save the model set.  Would you like to go to the List of Characters window now?", "OK", "Cancel")) {
+				Object obj2 = data.doCommand("showMe", null, checker);
+				if (obj2 !=null && obj2 instanceof Commandable){
+					Commandable c = (Commandable)obj2;
+					c.doCommand("newAssistant", "#CharListProbModels", checker);
+				}
+			}
+		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "List of Probability Model Sets";
+   	 }
+ 	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+  	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Makes windows listing probability model sets." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+   	 
+   	 
+   	 
+}
+
+
diff --git a/Source/mesquite/stochchar/SimAncestralStates/SimAncestralStates.java b/Source/mesquite/stochchar/SimAncestralStates/SimAncestralStates.java
new file mode 100644
index 0000000..75ca24d
--- /dev/null
+++ b/Source/mesquite/stochchar/SimAncestralStates/SimAncestralStates.java
@@ -0,0 +1,230 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.SimAncestralStates;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimAncestralStates extends CharHistorySource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharacterSimulator.class, getName() + "  needs a particular method to simulate character evolution.",
+		"The method to simulate character evolution can be selected initially or in the Character Simulator submenu");
+	}
+	/*.................................................................................................................*/
+	int currentChar=0;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	CharacterSimulator simulatorTask;
+	CharacterHistory states;
+	Random rng;
+	MesquiteLong seed;
+	MesquiteString simulatorName;
+	Tree lastTree;
+	Taxa lastTaxa;	
+	Object dataCondition;
+	MesquiteCommand stC;
+
+	/*.................................................................................................................*/  
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+		if (condition!=null)
+			simulatorTask= (CharacterSimulator)hireCompatibleEmployee(CharacterSimulator.class, condition, "Character simulator");
+		else {
+			simulatorTask= (CharacterSimulator)hireEmployee(CharacterSimulator.class, "Character simulator");
+		}
+		if (simulatorTask == null) {
+			return sorry("Simulated Characters module could not be started because an appropriate simulator module could not be hired");
+		}
+		stC = makeCommand("setCharacterSimulator",  this);
+		simulatorTask.setHiringCommand(stC);
+		seed = new MesquiteLong(1);
+		seed.setValue(originalSeed);
+		dataCondition = condition;
+		simulatorName = new MesquiteString(simulatorTask.getName());
+		if (numCompatibleModulesAvailable(CharacterSimulator.class, condition, this)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character Simulator",stC, CharacterSimulator.class);
+			mss.setSelected(simulatorName);
+			mss.setCompatibilityCheck(condition);
+		}
+
+		rng = new Random(originalSeed);
+		addMenuItem("Set Seed (Anc. States simulation)...", makeCommand("setSeed",  this));
+		return true; 
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean allowsStateWeightChoice(){
+		return false;
+	}
+	public String getMappingTypeName(){
+		return "Mapping";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCharacterSimulator ", simulatorTask);
+		temp.addLine("setSeed " + originalSeed);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module used to simulate character evolution", "[name of module]", commandName, "setCharacterSimulator")) {
+			CharacterSimulator temp;
+			if (dataCondition==null)
+				temp =  (CharacterSimulator)replaceEmployee(CharacterSimulator.class, arguments, "Character simulator", simulatorTask);
+			else
+				temp =  (CharacterSimulator)replaceCompatibleEmployee(CharacterSimulator.class, arguments, simulatorTask, dataCondition);
+			if (temp!=null) {
+				simulatorTask=  temp;
+				simulatorTask.setHiringCommand(stC);
+				simulatorName.setValue(simulatorTask.getName());
+				seed.setValue(originalSeed);
+				parametersChanged(); 
+				return simulatorTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+			long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteLong.isCombinable(s)){
+				s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+			}
+			if (MesquiteLong.isCombinable(s)){
+				originalSeed = s;
+				seed.setValue(originalSeed);
+				parametersChanged(); 
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == simulatorTask)
+			iQuit();
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		if (simulatorTask.isDoomed())
+			return;
+		simulatorTask.initialize(taxa);
+	}
+	Tree tree = null;
+	public  void prepareHistory(Tree tree, int ic){
+		this.tree = tree;
+		if (ic<0)
+			return;
+		currentChar =ic;
+	}
+	/*.................................................................................................................*/
+	public CharacterHistory getMapping(long im, CharacterHistory history, MesquiteString resultString) {
+		if (currentChar<0 || tree == null){
+			System.out.println("current char " + currentChar);
+			return null;
+		}
+		if (simulatorTask==null) {
+			System.out.println("Simulator task null");
+			return null;
+		}
+		if (simulatorTask.isDoomed())
+			return null;
+		rng.setSeed(originalSeed);
+
+		long rnd = originalSeed;
+		for (int it = 0; it<currentChar; it++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		seed.setValue(rnd + 1); //v. 1. 1, October 05: changed so as to avoid two adjacent characteres differing merely by a frameshift of random numbers
+
+		history = simulatorTask.getSimulatedHistory(states, tree, seed);
+		if (simulatorTask.isDoomed())
+			return null;
+		if (history!=null)
+			history.setName(getHistoryName(tree, currentChar));
+		if (resultString!=null)
+			resultString.setValue(getHistoryName(tree, currentChar));
+		return history;
+	}
+	/** returns the name of history ic*/
+	public String getHistoryName(Taxa taxa, int ic){
+		return getHistoryName((Tree)null, ic);
+	}
+	/** returns the name of history ic*/
+	public String getHistoryName(Tree tree, int ic){
+		return "Character History #" + Integer.toString(CharacterStates.toExternal(ic))  + " simulated by " + simulatorTask.getName();
+	}
+	public int getNumberOfHistories(Tree tree){
+		return MesquiteInteger.infinite;
+	}
+	public int getNumberOfHistories(Taxa taxa){
+		return MesquiteInteger.infinite;
+	}
+	public long getNumberOfMappings(Tree tree,  int ic){
+		return 1;
+	}
+	public long getNumberOfMappings(Taxa taxa,  int ic){
+		return 1;
+	}
+	/** returns the name of history ic and mapping im*/
+	public String getMappingName(Taxa taxa, int ic, long im){
+		return getHistoryName(taxa, ic);
+	}
+	/** returns the name of history ic and mapping im*/
+	public String getMappingName(Tree tree, int ic, long im){
+		return getHistoryName(tree, ic);
+	}
+	/** returns the name of histories for menu items, e.g. if each history represents a character, return "Character"*/
+	public  String getHistoryTypeName(){
+		return "Character";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Simulate Ancestral States";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (simulatorTask !=null) {
+			String s =  "Simulator: " + simulatorTask.getName();
+			if (lastTree !=null)
+				s+= "; most recent tree: " + lastTree.getName();
+			return s + " [seed " + originalSeed + "]";
+		}
+		else
+			return "";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Simulates ancestral states on the nodes of a tree.";
+	}
+}
+
+
diff --git a/Source/mesquite/stochchar/SimCharsOnTrees/SimCharsOnTrees.java b/Source/mesquite/stochchar/SimCharsOnTrees/SimCharsOnTrees.java
new file mode 100644
index 0000000..9175794
--- /dev/null
+++ b/Source/mesquite/stochchar/SimCharsOnTrees/SimCharsOnTrees.java
@@ -0,0 +1,317 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.SimCharsOnTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimCharsOnTrees extends CharacterSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially or in the Tree Source submenu");
+	}
+	/*.................................................................................................................*/
+	int currentChar=0;
+	long originalSeed=System.currentTimeMillis(); 
+	CharacterSimulator simulatorTask;
+	CharacterDistribution states;
+	Random rng;
+	MesquiteLong seed;
+	TreeSource treeTask;
+	MesquiteString simulatorName;
+	Tree lastTree;
+	Taxa lastTaxa;	
+	int numChars = MesquiteInteger.infinite;
+	Object dataCondition;
+	MesquiteCommand stC, ttC;
+	MesquiteString treeTaskName;
+	/*.................................................................................................................*/  
+ 	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+    	 	if (condition!=null)
+    	 		simulatorTask= (CharacterSimulator)hireCompatibleEmployee(CharacterSimulator.class, condition, "Character simulator");
+    	 	else
+    	 		simulatorTask= (CharacterSimulator)hireEmployee(CharacterSimulator.class, "Character simulator");
+    	 	if (simulatorTask == null) {
+    	 		return sorry("Simulated Characters could not be started because an appropriate simulator module could not be hired");
+    	 	}
+    	 	stC = makeCommand("setCharacterSimulator",  this);
+		ttC =  makeCommand("setTreeSource",  this);
+    	 	simulatorTask.setHiringCommand(stC);
+    	 	
+		if (RandomBetween.askSeed && !MesquiteThread.isScripting()){
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for character simulation", "Set Random Number seed for character simulation:", originalSeed);
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+		}
+    	 	seed = new MesquiteLong(1);
+
+    	 	seed.setValue(originalSeed);
+ 		dataCondition = condition; 
+ 		simulatorName = new MesquiteString(simulatorTask.getName());
+		if (numCompatibleModulesAvailable(CharacterSimulator.class, condition, this)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character Simulator",stC, CharacterSimulator.class);
+ 			mss.setSelected(simulatorName);
+ 			mss.setCompatibilityCheck(condition);
+ 		}
+ 		
+ 		rng = new Random(originalSeed);
+  		addMenuItem("Set Seed (Char. on Trees simulation)...", makeCommand("setSeed",  this));
+	 	if (MesquiteThread.isScripting())
+	 		treeTask= (TreeSource)hireNamedEmployee(TreeSource.class, StringUtil.tokenize("#SimulateTree"));
+    	 	if (treeTask == null)
+	 		treeTask= (TreeSource)hireEmployee(TreeSource.class, "Source of trees on which to simulate character evolution");
+    	 	if (treeTask == null) {
+    	 		return sorry(getName() + " can't start because not appropiate tree source module was obtained");
+    	 	}
+ 		treeTaskName = new MesquiteString();
+	    	treeTaskName.setValue(treeTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", ttC);
+			mss.setSelected(treeTaskName);
+			mss.setList(TreeSource.class);
+		}
+    	 	treeTask.setHiringCommand(ttC);
+  	 	return true; 
+   	 }
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (lastTaxa!=null)
+				lastTaxa.removeListener(this);
+	  	 storePreferences();
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == simulatorTask || employee == treeTask)
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (!MesquiteThread.isScripting() && (employee != treeTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED))
+ 			super.employeeParametersChanged(employee, source, notification);
+   	 }
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == lastTaxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	if (MesquiteInteger.isCombinable(numChars))
+   	 		temp.addLine("setNumChars " + numChars);
+   	 	temp.addLine("setSeed " + originalSeed);
+ 	 	temp.addLine("setCharacterSimulator ", simulatorTask);
+  	 	temp.addLine("setTreeSource ", treeTask);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the number of characters (if indefinite number allowed)", "[number of characters]", commandName, "setNumChars")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of characters", "Number of characters available from simulations:", numChars);
+    	 		if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numChars) {
+    	 			numChars=newNum;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module used to simulate character evolution", "[name of module]", commandName, "setCharacterSimulator")) {
+    	 		CharacterSimulator temp;
+    	 		if (dataCondition==null)
+    	 			temp =  (CharacterSimulator)replaceEmployee(CharacterSimulator.class, arguments, "Character simulator", simulatorTask);
+    	 		else
+    	 			temp =  (CharacterSimulator)replaceCompatibleEmployee(CharacterSimulator.class, arguments, simulatorTask, dataCondition);
+	    	 	if (temp!=null) {
+	    	 		simulatorTask=  temp;
+		    	 	simulatorTask.setHiringCommand(stC);
+	    	 		simulatorName.setValue(simulatorTask.getName());
+	    	 		states = null;
+	    	 		seed.setValue(originalSeed);
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); //?
+ 				return simulatorTask;
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module used to supply trees for character simulation", "[name of module]", commandName, "setTreeSource")) {
+    	 		TreeSource temp=  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees on which to simulate characters", treeTask);
+	    	 	if (temp!=null) {
+	    	 		treeTask = temp;
+				treeTask.setHiringCommand(ttC);
+	    	 		treeTaskName.setValue(treeTask.getName());
+	    	 		seed.setValue(originalSeed);
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+ 			return temp;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the bock of taxa used", "[block number]", commandName, "setTaxa")) {
+    	 		int setNumber = MesquiteInteger.fromFirstToken(arguments, stringPos); 
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.removeListener(this);
+   	 		lastTaxa = getProject().getTaxa(checker.getFile(), setNumber);
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.addListener(this);
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current tree", null, commandName, "getTree")) {
+    	 		if (lastTree==null && lastTaxa!=null && treeTask!=null) {
+				return treeTask.getTree(lastTaxa, currentChar);
+    	 		}
+    	 		else 
+    	 			return lastTree;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+		if (simulatorTask.isDoomed())
+				return;
+		treeTask.initialize(taxa);
+		simulatorTask.initialize(taxa);
+   	}
+   	
+   	private long charSeed(int ic){
+		rng.setSeed(originalSeed);
+
+		long rnd = originalSeed;
+		for (int i = 0; i<ic; i++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		return rnd + 1;
+   	}
+	/*.................................................................................................................*/
+   	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+   		lastTaxa = taxa;
+   		if (ic<0)
+   			return null;
+   		currentChar =ic;
+		if (treeTask == null) {
+			System.out.println("Tree task null");
+			return null;
+		}
+		else if (simulatorTask==null) {
+			System.out.println("Simulator task null");
+			return null;
+		}
+		if (simulatorTask.isDoomed())
+				return null;
+   		CommandRecord.tick("Simulating character " + ic);
+
+		seed.setValue(charSeed(currentChar));
+		lastTree = treeTask.getTree(taxa, currentChar);
+		CharacterDistribution states = simulatorTask.getSimulatedCharacter(null, lastTree, seed);
+		if (simulatorTask.isDoomed())
+				return null;
+   		if (states!=null) {
+   			states.setName("Character #" + Integer.toString(CharacterStates.toExternal(currentChar))  + " simulated by " + simulatorTask.getName() + " on tree " + lastTree.getID());
+  			if (states instanceof AdjustableDistribution)
+  				((AdjustableDistribution)states).setParentCharacter(ic);
+  		}
+  		return states;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfCharacters(Taxa taxa) {
+    		if (treeTask ==null)
+    			return numChars; 
+    		int numTrees = treeTask.getNumberOfTrees(taxa);
+    		if (MesquiteInteger.isFinite(numTrees))
+    			numChars = numTrees;
+    		return numChars;
+   	}
+   
+	/*.................................................................................................................*/
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Taxa taxa, int ic){
+     		return "Character #" + Integer.toString(CharacterStates.toExternal(ic))  + " simulated by " + simulatorTask.getName() + " (seed: " + charSeed(ic) + ") on a tree from " + treeTask.getName();
+   	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+			if (simulatorTask !=null) {
+				String s =  "Simulator: " + simulatorTask.getName();
+				if (lastTree !=null)
+					s+= "; most recent tree: " + lastTree.getName();
+				return s + " [seed for char sim. " + originalSeed + "]";
+			}
+			else
+				return "";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simulated Characters on Trees";
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies simulated characters each from a respective tree.";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new SCCompatibilityTest();
+  	 }
+}
+
+class SCCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (null!=MesquiteTrunk.mesquiteModulesInfoVector.findModule (CharacterSimulator.class, obj, project, prospectiveEmployer));
+	}
+}
+
+
diff --git a/Source/mesquite/stochchar/SimMatricesOnTrees/SimMatricesOnTrees.java b/Source/mesquite/stochchar/SimMatricesOnTrees/SimMatricesOnTrees.java
new file mode 100644
index 0000000..8f58a7c
--- /dev/null
+++ b/Source/mesquite/stochchar/SimMatricesOnTrees/SimMatricesOnTrees.java
@@ -0,0 +1,374 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.SimMatricesOnTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimMatricesOnTrees extends CharMatrixSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially or in the Tree Source submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(CharacterSimulator.class, getName() + "  needs a method to simulate character evolution.",
+		"The method to simulate character evolution can be selected initially or in the Character Simulator submenu");
+	}
+
+	int currentDataSet=0;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	CharacterSimulator charSimulatorTask;
+	CharacterDistribution states;
+	Random rng;
+	MesquiteLong seed;
+	TreeSource treeTask;
+	int numChars = 100;
+	int numMatrices = MesquiteInteger.infinite;
+	MesquiteString simulatorName;
+	MesquiteString treeTaskName;
+	Tree tree;
+	Taxa lastTaxa;	
+	Object dataCondition;
+	MesquiteCommand stC, ttC;
+	/*.................................................................................................................*/
+ 	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+    	 	if (condition!=null)
+    	 		charSimulatorTask= (CharacterSimulator)hireCompatibleEmployee(CharacterSimulator.class, condition, "Character simulator");
+    	 	else
+    	 		charSimulatorTask= (CharacterSimulator)hireEmployee(CharacterSimulator.class, "Character simulator");
+    	 	if (charSimulatorTask == null) {
+    	 		return sorry("Simulated Matrices on Trees can't start because not appropiate character simulator module was obtained");
+    	 	}
+		stC =  makeCommand("setCharacterSimulator",  this);
+		ttC =  makeCommand("setTreeSource",  this);
+		charSimulatorTask.setHiringCommand(stC);
+		if (RandomBetween.askSeed && !MesquiteThread.isScripting()){
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for Matrix simulation", "Set Random Number seed for Matrix on Trees simulation:", originalSeed);
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+		}
+    	 	seed = new MesquiteLong(1);
+    	 	seed.setValue(originalSeed);
+  		
+ 		rng = new Random(originalSeed);
+ 		simulatorName = new MesquiteString(charSimulatorTask.getName());
+		if (numModulesAvailable(CharacterSimulator.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character Simulator",stC, CharacterSimulator.class);
+ 			mss.setSelected(simulatorName);
+ 		}
+ 		if (!MesquiteThread.isScripting()){
+			numChars = MesquiteInteger.queryInteger(containerOfModule(), "Number of characters in matrix", "Number of characters to simulate:", 100, 1, 10000);
+	 		if (MesquiteInteger.isUnassigned(numChars))
+	 			return false;
+	 		if (!MesquiteInteger.isCombinable(numChars))
+	 			numChars = 100;
+ 		}
+  	 	if (getHiredAs() != CharMatrixObedSource.class) {
+			MesquiteMenuItemSpec mm = addMenuItem(null, "Next Simulated Matrix", makeCommand("nextMatrix",  this));
+			mm.setShortcut(KeyEvent.VK_RIGHT); //right
+			mm = addMenuItem(null, "Previous Simulated Matrix", makeCommand("prevMatrix",  this));
+			mm.setShortcut(KeyEvent.VK_LEFT); //right
+ 		}
+ 		addMenuItem( "Number of characters...",makeCommand("setNumChars",  this));
+  		addMenuItem("Set Seed (Matrix simulation)...", makeCommand("setSeed",  this));
+		
+	 	if (MesquiteThread.isScripting())
+	 		treeTask= (TreeSource)hireNamedEmployee(TreeSource.class, StringUtil.tokenize("#SimulateTree"));
+    	 	if (treeTask == null)
+	 		treeTask= (TreeSource)hireEmployee(TreeSource.class, "Source of trees on which to simulate character evolution for matrices");
+    	 	if (treeTask == null) {
+    	 		return sorry("Simulated Matrices on Trees can't start because not appropiate tree source module was obtained");
+    	 	}
+ 		treeTaskName = new MesquiteString();
+	    	treeTaskName.setValue(treeTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", ttC);
+			mss.setSelected(treeTaskName);
+			mss.setList(TreeSource.class);
+		}
+    	 	treeTask.setHiringCommand(ttC);
+    	 	
+  	 	return true; 
+  	 }
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 public void employeeQuit(MesquiteModule m){
+  	 	if (m==treeTask)
+  	 		iQuit();
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (lastTaxa!=null)
+				lastTaxa.removeListener(this);
+	  	 storePreferences();
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == lastTaxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (!MesquiteThread.isScripting() && (employee != treeTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED))
+ 			super.employeeParametersChanged(employee, source, notification);
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	if (getHiredAs() != CharMatrixObedSource.class)
+  	 		temp.addLine("setMatrix " + CharacterStates.toExternal(currentDataSet));
+   	 	temp.addLine("setNumChars " + numChars);
+   	 	if (MesquiteInteger.isCombinable(numMatrices))
+   	 		temp.addLine("setNumMatrices " + numMatrices);
+ 	 	temp.addLine("setCharacterSimulator ", charSimulatorTask);
+  	 	temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setTreeSource ", treeTask);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	  if (checker.compare(this.getClass(), "Sets the module used to simulate character evolution", "[name of module]", commandName, "setCharacterSimulator")) {
+    	 		CharacterSimulator temp;
+    	 		if (dataCondition==null)
+    	 			temp =  (CharacterSimulator)replaceEmployee(CharacterSimulator.class, arguments, "Character simulator", charSimulatorTask);
+    	 		else
+    	 			temp =  (CharacterSimulator)replaceCompatibleEmployee(CharacterSimulator.class, arguments, charSimulatorTask, dataCondition);
+	    	 	if (temp!=null) {
+	    	 		charSimulatorTask=  temp;
+				charSimulatorTask.setHiringCommand(stC);
+	    	 		simulatorName.setValue(charSimulatorTask.getName());
+	    	 		seed.setValue(originalSeed);
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 				return charSimulatorTask;
+ 			}
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module used to supply trees for matrix simulation", "[name of module]", commandName, "setTreeSource")) {
+    	 		TreeSource temp=  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees on which to simulate matrices", treeTask);
+	    	 	if (temp!=null) {
+	    	 		treeTask = temp;
+				treeTask.setHiringCommand(ttC);
+	    	 		treeTaskName.setValue(treeTask.getName());
+	    	 		seed.setValue(originalSeed);
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+ 			}
+ 			return temp;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the number of characters simulated in each matrix", "[number of characters]", commandName, "setNumChars")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of characters", "Number of characters to simulate:", numChars);
+    	 		if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numChars) {
+    	 			numChars=newNum;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the number of matrices (if indefinite number allowed)", "[number of matrices]", commandName, "setNumMatrices")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of matrices", "Number of matrices available from simulations:", numMatrices);
+    	 		if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numMatrices) {
+    	 			numMatrices=newNum;
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); 
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block number]", commandName, "setTaxa")) {
+    	 		int setNumber = MesquiteInteger.fromFirstToken(arguments, pos);
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.removeListener(this);
+   	 		lastTaxa = getProject().getTaxa(checker.getFile(), setNumber);
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.addListener(this);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current tree", null, commandName, "getTree")) {
+    	 		if (tree==null && lastTaxa!=null && treeTask!=null) {
+				return null;
+    	 		}
+    	 		else 
+    	 			return tree;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Simulates the next matrix", null, commandName, "nextMatrix")) {
+    	 		currentDataSet++;
+    	 		parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Simulates the previous matrix", null, commandName, "prevMatrix")) {
+    	 		currentDataSet--;
+    	 		if (currentDataSet>=0) {
+    	 			parametersChanged();
+    	 		}
+    	 		else
+    	 			currentDataSet=0;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets which character matrix to simulate", "[matrix number]", commandName, "setMatrix")) {
+    	 		pos.setValue(0);
+    	 		int icNum = MesquiteInteger.fromString(arguments, pos);
+    	 		if (!MesquiteInteger.isCombinable(icNum))
+    	 			return null;
+    	 		int ic = CharacterStates.toInternal(icNum);
+    	 		if ((ic>=0) && (MesquiteInteger.isCombinable(ic))) {
+    	 			currentDataSet = ic;
+    	 			parametersChanged();
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	public void initialize(Taxa taxa){
+		treeTask.initialize(taxa);
+		charSimulatorTask.initialize(taxa);
+   	}
+	/*.................................................................................................................*/
+  	private MCharactersDistribution getM(Taxa taxa){
+		if (treeTask == null) {
+			System.out.println("Tree task null");
+			return null;
+		}
+		else if (charSimulatorTask==null) {
+			System.out.println("Simulator task null");
+			return null;
+		}
+		else if (taxa==null){
+			System.out.println("taxa null");
+			return null;
+		}
+		
+		MAdjustableDistribution matrix = null;
+		Class c = charSimulatorTask.getStateClass();//getDataClass from simulator and get it to make matrix
+		if (c==null)
+			return null;
+		try {
+			CharacterState s = (CharacterState)c.newInstance();
+			if (s!=null) {
+				matrix = s.makeMCharactersDistribution(taxa, numChars, taxa.getNumTaxa());
+				if (matrix == null)
+					return null;
+			}
+		}
+		catch (IllegalAccessException e){alert("iae getM"); return null; }
+		catch (InstantiationException e){alert("ie getM");  return null;}
+		
+
+		rng.setSeed(originalSeed);
+		long rnd = originalSeed;
+		for (int it = 0; it<=currentDataSet; it++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		seed.setValue(rnd + 1);//v. 1. 1, October 05: changed so as to avoid two adjacent matrices differing merely by a frameshift of random numbers
+		
+		tree = treeTask.getTree(taxa, currentDataSet);
+		//if (tree instanceof MesquiteTree)
+		//	((MesquiteTree)tree).setName("Tree # " + MesquiteTree.toExternal(currentDataSet)  + " from " + treeTask.getName());
+		CharacterDistribution states = null;
+
+		for (int ic = 0; ic<numChars; ic++) {
+			states = charSimulatorTask.getSimulatedCharacter(states, tree, seed); 
+ 	 		matrix.transferFrom(ic, states);
+ 	 	}
+   		matrix.setName("Matrix #" + (currentDataSet)  + " simulated by " + charSimulatorTask.getName());
+   		matrix.setAnnotation(accumulateParameters(" "), false);
+   		matrix.setBasisTree(tree);
+ 
+  		return matrix;
+   	}
+	/*.................................................................................................................*/
+    	 public String getMatrixName(Taxa taxa, int ic) {
+   		return "Matrix #" + CharacterStates.toExternal(ic)  + " simulated by " + charSimulatorTask.getName() + " on trees from " + treeTask.getName();
+   	 }
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+   		currentDataSet = im;
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+    	public  int getNumberOfMatrices(Taxa taxa){
+    		if (treeTask ==null)
+    			return numMatrices; 
+    		int numTrees = treeTask.getNumberOfTrees(taxa);
+    		if (MesquiteInteger.isFinite(numTrees))
+    			numMatrices = numTrees;
+    		return numMatrices;
+    	}
+	/*.................................................................................................................*/
+   	/** returns the number of the current matrix*/
+   	public int getNumberCurrentMatrix(){
+   		return currentDataSet;
+   	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		String s = null;
+		if (getHiredAs() != CharMatrixObedSource.class)
+			s = "Matrix #" + CharacterStates.toExternal(currentDataSet) + " simulated by " + charSimulatorTask.getName() + " on trees from " + treeTask.getName();
+		else
+			s = "Matrix simulated by " + charSimulatorTask.getName() + " on trees from " + treeTask.getName();
+		return s + " [seed for matrix sim. " + originalSeed + "]";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simulated Matrices on Trees";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies simulated character matrices, each evolved on a different of a series of trees.";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new SMoSTCompatibilityTest();
+  	 }
+}
+
+class SMoSTCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (null!=MesquiteTrunk.mesquiteModulesInfoVector.findModule (CharacterSimulator.class, obj, project, prospectiveEmployer));
+	}
+}
+
diff --git a/Source/mesquite/stochchar/SimulatedCharacters/SimulatedCharacters.java b/Source/mesquite/stochchar/SimulatedCharacters/SimulatedCharacters.java
new file mode 100644
index 0000000..b56511b
--- /dev/null
+++ b/Source/mesquite/stochchar/SimulatedCharacters/SimulatedCharacters.java
@@ -0,0 +1,264 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.SimulatedCharacters;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimulatedCharacters extends CharacterSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharacterSimulator.class, getName() + "  needs a particular method to simulate character evolution.",
+		"The method to simulate character evolution can be selected initially or in the Character Simulator submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a current tree.",
+		"The source of current tree is arranged initially");
+	}
+	/*.................................................................................................................*/
+	int currentChar=0;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	CharacterSimulator simulatorTask;
+	CharacterDistribution states;
+	Random rng;
+	MesquiteLong seed;
+	OneTreeSource treeTask;
+	MesquiteString simulatorName;
+	Tree lastTree;
+	Taxa lastTaxa;	
+	Object dataCondition;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/  
+ 	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+    	 	if (condition!=null)
+    	 		simulatorTask= (CharacterSimulator)hireCompatibleEmployee(CharacterSimulator.class, condition, "Character simulator");
+    	 	else
+    	 		simulatorTask= (CharacterSimulator)hireEmployee(CharacterSimulator.class, "Character simulator");
+    	 	if (simulatorTask == null) {
+    	 		return sorry("Simulated Characters could not be started because an appropriate simulator module could not be hired");
+    	 	}
+    	 	stC = makeCommand("setCharacterSimulator",  this);
+    	 	simulatorTask.setHiringCommand(stC);
+    	 	
+		if (RandomBetween.askSeed && !MesquiteThread.isScripting()){
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for character simulation", "Set Random Number seed for character simulation:", originalSeed);
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+		}
+    	 	seed = new MesquiteLong(1);
+
+    	 	seed.setValue(originalSeed);
+ 		dataCondition = condition; 
+ 		simulatorName = new MesquiteString(simulatorTask.getName());
+		if (numCompatibleModulesAvailable(CharacterSimulator.class, condition, this)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character Simulator",stC, CharacterSimulator.class);
+ 			mss.setSelected(simulatorName);
+ 			mss.setCompatibilityCheck(condition);
+ 		}
+ 		
+ 		rng = new Random(originalSeed);
+ 		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree on which to simulate character evolution");
+ 		if (treeTask == null)  {
+ 			return sorry("Simulated Characters could not be started because no tree was found on which to simulate");
+ 		}
+  		addMenuItem("Set Seed (Character simulation)...", makeCommand("setSeed",  this));
+ 	 	return true; 
+   	 }
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (lastTaxa!=null)
+				lastTaxa.removeListener(this);
+	  	 storePreferences();
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == simulatorTask || employee == treeTask)
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == lastTaxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	temp.addLine("setSeed " + originalSeed);
+ 	 	temp.addLine("setCharacterSimulator ", simulatorTask);
+ 	 	temp.addLine("getTreeSource ", treeTask);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    		 if (checker.compare(this.getClass(), "Sets the module used to simulate character evolution", "[name of module]", commandName, "setCharacterSimulator")) {
+    	 		CharacterSimulator temp;
+    	 		if (dataCondition==null)
+    	 			temp =  (CharacterSimulator)replaceEmployee(CharacterSimulator.class, arguments, "Character simulator", simulatorTask);
+    	 		else
+    	 			temp =  (CharacterSimulator)replaceCompatibleEmployee(CharacterSimulator.class, arguments, simulatorTask, dataCondition);
+	    	 	if (temp!=null) {
+	    	 		simulatorTask=  temp;
+		    	 	simulatorTask.setHiringCommand(stC);
+	    	 		simulatorName.setValue(simulatorTask.getName());
+	    	 		states = null;
+	    	 		seed.setValue(originalSeed);
+ 				if (!MesquiteThread.isScripting())
+ 					parametersChanged(); //?
+ 				return simulatorTask;
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the source of trees", null, commandName, "getTreeSource")) {
+    	 		return treeTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the bock of taxa used", "[block number]", commandName, "setTaxa")) {
+    	 		int setNumber = MesquiteInteger.fromFirstToken(arguments, stringPos); //TODO: should use just first token
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.removeListener(this);
+   	 		lastTaxa = getProject().getTaxa(checker.getFile(), setNumber);
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.addListener(this);
+    	 	}
+     	 else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current tree", null, commandName, "getTree")) {
+    	 		if (lastTree==null && lastTaxa!=null && treeTask!=null) {
+				return treeTask.getTree(lastTaxa);
+    	 		}
+    	 		else 
+    	 			return lastTree;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+		if (simulatorTask.isDoomed())
+				return;
+		treeTask.initialize(taxa);
+		simulatorTask.initialize(taxa);
+   	}
+   	
+   	private long charSeed(int ic){
+		rng.setSeed(originalSeed);
+
+		long rnd = originalSeed;
+		for (int i = 0; i<ic; i++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		return rnd + 1; //v. 1. 1, October 05: changed so as to avoid two adjacent characters differing merely by a frameshift of random numbers
+   	}
+	/*.................................................................................................................*/
+   	public CharacterDistribution getCharacter(Taxa taxa, int ic) {
+   		lastTaxa = taxa;
+   		if (ic<0)
+   			return null;
+   		currentChar =ic;
+		if (treeTask == null) {
+			System.out.println("Tree task null");
+			return null;
+		}
+		else if (simulatorTask==null) {
+			System.out.println("Simulator task null");
+			return null;
+		}
+		if (simulatorTask.isDoomed())
+				return null;
+   		CommandRecord.tick("Simulating character " + ic);
+
+		seed.setValue(charSeed(currentChar));
+		lastTree = treeTask.getTree(taxa);
+		CharacterDistribution states = simulatorTask.getSimulatedCharacter(null, lastTree, seed); //1. 06: had passed states back in, which caused problems for employers requiring multiple
+		if (simulatorTask.isDoomed())
+				return null;
+   		if (states!=null)
+   			states.setName("Character #" + Integer.toString(CharacterStates.toExternal(currentChar))  + " simulated by " + simulatorTask.getName());
+  		return states;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfCharacters(Taxa taxa) {
+   		return MesquiteInteger.infinite;
+   	}
+   
+	/*.................................................................................................................*/
+   	/** returns the name of character ic*/
+   	public String getCharacterName(Taxa taxa, int ic){
+     		return "Character #" + Integer.toString(CharacterStates.toExternal(ic))  + " simulated by " + simulatorTask.getName() + " (seed: " + charSeed(ic) + ")";
+   	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+			if (simulatorTask !=null) {
+				String s =  "Simulator: " + simulatorTask.getName();
+				if (lastTree !=null)
+					s+= "; most recent tree: " + lastTree.getName();
+				return s + " [seed for char sim. " + originalSeed + "]";
+			}
+			else
+				return "";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simulated Characters";
+   	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies simulated characters.";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new SCCompatibilityTest();
+  	 }
+}
+
+class SCCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (null!=MesquiteTrunk.mesquiteModulesInfoVector.findModule (CharacterSimulator.class, obj, project, prospectiveEmployer));
+	}
+}
+
+
diff --git a/Source/mesquite/stochchar/SimulatedMatrix/SimulatedMatrix.java b/Source/mesquite/stochchar/SimulatedMatrix/SimulatedMatrix.java
new file mode 100644
index 0000000..d4299e8
--- /dev/null
+++ b/Source/mesquite/stochchar/SimulatedMatrix/SimulatedMatrix.java
@@ -0,0 +1,392 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.SimulatedMatrix;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimulatedMatrix extends CharMatrixSource implements Incrementable {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharacterSimulator.class, getName() + "  needs a particular method to simulate character evolution.",
+		"The method to simulate character evolution can be selected initially or in the Character Simulator submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a current tree on which to simulate character evolution.",
+		"The source of a current tree is arranged initially");
+	}
+	/*.................................................................................................................*/
+	int currentDataSet=0;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	CharacterSimulator simulatorTask;
+	Random rng;
+	MesquiteLong seed;
+	OneTreeSource treeTask;
+	int numChars = 100;
+	int numMatrices = MesquiteInteger.infinite;
+	MesquiteString simulatorName;
+	Tree lastTree;
+	Taxa lastTaxa;	
+	Object dataCondition;
+	MesquiteCommand stC;
+	boolean initialized = false;
+	boolean numCharsSet = false;
+	/*.................................................................................................................*/
+ 	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (condition !=null && condition instanceof CompatibilityTest)
+			condition = ((CompatibilityTest)condition).getAcceptedClass();
+    	 	if (condition!=null)
+    	 		simulatorTask= (CharacterSimulator)hireCompatibleEmployee(CharacterSimulator.class, condition, "Character simulator");
+    	 	else
+    	 		simulatorTask= (CharacterSimulator)hireEmployee(CharacterSimulator.class, "Character simulator");
+    	 	if (simulatorTask == null) {
+    	 		return sorry("Simulated Matrices could not start because no appropriate simulator module could be obtained");
+    	 	}
+    	 	stC = makeCommand("setCharacterSimulator",  this);
+    	 	simulatorTask.setHiringCommand(stC);
+		dataCondition = condition;
+		if (RandomBetween.askSeed && !MesquiteThread.isScripting()){
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for Matrix simulation", "Set Random Number seed for Matrix simulation:", originalSeed);
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+		}
+    	 	seed = new MesquiteLong(1);
+    	 	seed.setValue(originalSeed);
+ 		simulatorName = new MesquiteString(simulatorTask.getName());
+		if (numCompatibleModulesAvailable(CharacterSimulator.class, condition, this)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Character Simulator", stC, CharacterSimulator.class);
+ 			mss.setSelected(simulatorName);
+ 			mss.setCompatibilityCheck(condition);
+ 		}
+  	 	if (getHiredAs() != CharMatrixObedSource.class) {
+			MesquiteMenuItemSpec mm = addMenuItem(null, "Next Simulated Matrix", makeCommand("nextMatrix",  this));
+			mm.setShortcut(KeyEvent.VK_RIGHT); //right
+			mm = addMenuItem(null, "Previous Simulated Matrix", makeCommand("prevMatrix",  this));
+			mm.setShortcut(KeyEvent.VK_LEFT); //right
+ 		}
+ 		addMenuItem( "Number of characters...",makeCommand("setNumChars",  this));
+ 		
+  		addMenuItem("Set Seed (Matrix simulation)...", makeCommand("setSeed",  this));
+ 		rng = new Random(originalSeed);
+ 		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree on which to simulate character evolution");
+ 		if (treeTask == null) {
+ 			return sorry("Simulated Matrices could not start because no source of trees was obtained");
+ 		}
+  	 	return true; 
+  	 }
+  	 
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+			if (lastTaxa!=null)
+				lastTaxa.removeListener(this);
+	  	 storePreferences();
+			super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == lastTaxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+ 	public void employeeQuit(MesquiteModule employee) {
+ 		if (employee == simulatorTask)
+ 			iQuit();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	if (getHiredAs() != CharMatrixObedSource.class)
+  	 		temp.addLine("setMatrix " + CharacterStates.toExternal(currentDataSet));
+   	 	temp.addLine("setNumChars " + numChars);
+   	 	if (MesquiteInteger.isCombinable(numMatrices))
+   	 		temp.addLine("setNumMatrices " + numMatrices);
+ 	 	temp.addLine("setCharacterSimulator ", simulatorTask);
+  	 	temp.addLine("setSeed " + originalSeed);
+ 	 	temp.addLine("getTreeSource ", treeTask);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the module used to simulate character evolution", "[name of module]", commandName, "setCharacterSimulator")) {
+   	 		CharacterSimulator temp;
+    	 		if (dataCondition==null)
+    	 			temp =  (CharacterSimulator)replaceEmployee(CharacterSimulator.class, arguments, "Character simulator", simulatorTask);
+    	 		else
+    	 			temp =  (CharacterSimulator)replaceCompatibleEmployee(CharacterSimulator.class, arguments, simulatorTask, dataCondition);
+	    	 	if (temp!=null) {
+	    	 		simulatorTask=  temp;
+		    	 	simulatorTask.setHiringCommand(stC);
+	    	 		simulatorName.setValue(simulatorTask.getName());
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 				return simulatorTask;
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the source of trees", null, commandName, "getTreeSource")) {
+    	 		return treeTask;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the number of characters simulated in each matrix", "[number of characters]", commandName, "setNumChars")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of characters", "Number of characters to simulate:", numChars);
+    	 		if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numChars) {
+    	 			numChars=newNum;
+    				numCharsSet = true;
+    	 			parametersChanged();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the number of matrices to be simulated", "[number of matrices]", commandName, "setNumMatrices")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of matrices", "Number of matrices available from simulations:", numMatrices);
+    	 		if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numMatrices) {
+    	 			numMatrices=newNum;
+    	 			parametersChanged();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the taxa block used", "[block number]", commandName, "setTaxa")) {
+    	 		int setNumber = MesquiteInteger.fromFirstToken(arguments, pos); //TODO: should use just first token
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.removeListener(this);
+   	 		lastTaxa = getProject().getTaxa(checker.getFile(), setNumber);
+    	 		if (lastTaxa!=null)
+    	 			lastTaxa.addListener(this);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the current tree", null, commandName, "getTree")) {
+    	 		if (lastTree==null && lastTaxa!=null && treeTask!=null) {
+				return treeTask.getTree(lastTaxa);
+    	 		}
+    	 		else 
+    	 			return lastTree;
+    	 	}
+     	 	else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Simulates the next matrix", null, commandName, "nextMatrix")) {
+    	 		currentDataSet++;
+    	 		parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Simulates the previous matrix", null, commandName, "prevMatrix")) {
+    	 		currentDataSet--;
+    	 		if (currentDataSet>=0) {
+    	 			parametersChanged();
+    	 		}
+    	 		else
+    	 			currentDataSet=0;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets which character matrix to simulate", "[matrix number]", commandName, "setMatrix")) {
+    	 		pos.setValue(0);
+    	 		int icNum = MesquiteInteger.fromString(arguments, pos);
+    	 		if (!MesquiteInteger.isCombinable(icNum))
+    	 			return null;
+    	 		int ic = CharacterStates.toInternal(icNum);
+    	 		if ((ic>=0) && (MesquiteInteger.isCombinable(ic))) {
+    	 			currentDataSet = ic;
+    	 			parametersChanged();
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	public void initialize(Taxa taxa){
+		if (simulatorTask.isDoomed())
+				return;
+		initialized = true;
+		treeTask.initialize(taxa);
+		simulatorTask.initialize(taxa);
+		if (!numCharsSet){
+			numChars = simulatorTask.getMaximumNumChars(taxa); //not quite right; should have separate maxnum
+	 		if (!MesquiteThread.isScripting() && !MesquiteInteger.isCombinable(numChars)){
+	 		
+				int defaultNumChars = simulatorTask.getDefaultNumChars();
+				numChars = MesquiteInteger.queryInteger(containerOfModule(), "Number of characters in matrix", "Number of characters to simulate:", defaultNumChars, 1, 1000000, false);
+
+		 		if (!MesquiteInteger.isCombinable(numChars))
+		 			numChars = defaultNumChars;
+		 		if (!MesquiteInteger.isCombinable(numChars))
+		 			numChars = 100;
+	 		}
+	 		else if (!MesquiteInteger.isCombinable(numChars))
+	 			numChars = 100;
+ 		}
+   	}
+   	int countt = 0;
+	/*.................................................................................................................*/
+  	private MCharactersDistribution getM(Taxa taxa){
+		if (treeTask == null) {
+			System.out.println("Tree task null");
+			return null;
+		}
+		else if (simulatorTask==null) {
+			System.out.println("Simulator task null");
+			return null;
+		}
+		else if (taxa==null){
+			System.out.println("taxa null");
+			return null;
+		}
+		else if (simulatorTask.isDoomed()) {
+			System.out.println("sim task doomed " + simulatorTask);
+				return null;
+		}
+		if (!initialized)
+			initialize(taxa);
+		MAdjustableDistribution matrix = null;
+		Class c = simulatorTask.getStateClass();//getDataClass from simulator and get it to make matrix
+		if (c==null)
+			return null;
+		try {
+			CharacterState s = (CharacterState)c.newInstance();
+			if (s!=null) {
+				matrix = s.makeMCharactersDistribution(taxa, numChars, taxa.getNumTaxa());
+				if (matrix == null)
+					return null;
+			}
+		}
+		catch (IllegalAccessException e){alert("iae getM"); return null; }
+		catch (InstantiationException e){alert("ie getM");  return null;}
+		
+		Tree tree = treeTask.getTree(taxa);
+		lastTree = tree;
+		CharacterDistribution states = null;
+		
+		rng.setSeed(originalSeed);
+		long rnd = originalSeed;
+		for (int it = 0; it<=currentDataSet; it++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		seed.setValue(rnd + 1); //v. 1. 1, October 05: changed so as to avoid two adjacent matrices differing merely by a frameshift of random numbers
+		
+		for (int ic = 0; ic<numChars; ic++) {
+			if (simulatorTask.isDoomed()) {
+				return null;
+			}
+			//TODO: getSimulatedCharacter should be passed scripting and should be initializable
+			if (states!=null && states instanceof AdjustableDistribution)
+				((AdjustableDistribution)states).setParentCharacter(ic);
+			states = simulatorTask.getSimulatedCharacter(states, tree, seed); 
+ 	 		matrix.transferFrom(ic, states);
+ 	 	}
+   		matrix.setName("Matrix #" + CharacterStates.toExternal(currentDataSet)  + " simulated by " + simulatorTask.getName());
+   		matrix.setAnnotation(accumulateParameters(" "), false);
+   		matrix.setBasisTree(tree);
+  		return matrix;
+   	}
+	/*.................................................................................................................*/
+    	 public String getMatrixName(Taxa taxa, int ic) {
+   		return "Matrix #" + CharacterStates.toExternal(ic)  + " simulated by " + simulatorTask.getName();
+   	 }
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+  	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+   		CommandRecord.tick("Simulating matrix " + im);
+   		currentDataSet = im;
+   		return getM(taxa);
+   	}
+	/*.................................................................................................................*/
+    	public  int getNumberOfMatrices(Taxa taxa){
+    		return numMatrices; 
+    	}
+	/*.................................................................................................................*/
+   	/** returns the number of the current matrix*/
+   	public int getNumberCurrentMatrix(){
+   		return currentDataSet;
+   	}
+	/*.................................................................................................................*/
+ 	public void setCurrent(long i){  //SHOULD NOT notify (e.g., parametersChanged)
+ 		currentDataSet = (int)i;
+ 	}
+ 	public long getCurrent(){
+ 		return currentDataSet;
+ 	}
+ 	public long getMin(){
+		return 0;
+ 	}
+ 	public long getMax(){
+		return numMatrices;
+ 	}
+ 	public long toInternal(long i){
+ 		return i-1;
+ 	}
+ 	public long toExternal(long i){ //return whether 0 based or 1 based counting
+ 		return i+1;
+ 	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+			if (simulatorTask !=null) {
+				String s =  "";
+				if (getHiredAs() != CharMatrixObedSource.class)
+					s += "Matrix #" + CharacterStates.toExternal(currentDataSet) + "; "; 
+				s += "Simulator: " + simulatorTask.getName();
+				if (lastTree !=null)
+					s+= "; most recent tree: " + lastTree.getName();
+				
+				return s + " [seed for matrix sim. " + originalSeed + "]";
+			}
+			else
+				return "";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simulated Matrices on Current Tree";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies simulated character matrices.";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new SMCompatibilityTest();
+  	 }
+}
+
+class SMCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+			return (null!=MesquiteTrunk.mesquiteModulesInfoVector.findModule (CharacterSimulator.class, obj, project, prospectiveEmployer));
+	}
+}
+
diff --git a/Source/mesquite/stochchar/StochCharMapper/StochCharMapper.java b/Source/mesquite/stochchar/StochCharMapper/StochCharMapper.java
new file mode 100644
index 0000000..d2edccb
--- /dev/null
+++ b/Source/mesquite/stochchar/StochCharMapper/StochCharMapper.java
@@ -0,0 +1,549 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison & Peter Midford. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.StochCharMapper;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.meristic.lib.MeristicState;
+import mesquite.categ.lib.*;
+import mesquite.cont.lib.*;
+import mesquite.stochchar.lib.*;
+import mesquite.stochchar.CurrentProbModels.*;
+
+/* ======================================================================== */
+public class StochCharMapper extends CharMapper {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(ProbModelSourceLike.class, getName() + " needs an indication of what probabilistic model to apply to the character.",
+		"The indicator of probabilistic models can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(MargLikeAncStCLForModel.class, getName() + "  needs methods to calculate likelihoods.",
+		"The methods to calculate likelihoods are chosen automatically according to the probability model used in the calculation");
+	}
+	CharacterDistribution observedStates;
+	MargLikeAncStCLForModel reconstructTask;
+	ProbModelSourceLike modelTask;
+	MesquiteString modelTaskName;
+	ProbPhenCategCharModel model;  //CharacterModel model;  - temporary restriction to nonMolecular models PEM 6-Jan-2006
+	MesquiteNumber likelihood;
+	boolean warnedNoCalc = false;
+	CharacterHistory statesAtNodes;
+	int oldNumTaxa;
+	boolean oneAtATime = false;
+	boolean oneAtATimeCHGBL = false;
+	Random generator;
+	double pi_s[];
+	private MesquiteLong seed;
+	private long originalSeed=System.currentTimeMillis(); //0L;
+	int MAXEVENTS = 1000; 
+	/*  	
+get prior from model
+enable prior editing within models
+handle models needing estimation
+	 */
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		hireAllEmployees(MargLikeAncStCLForModel.class);
+		for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof MargLikeAncStCLForModel){
+				((MargLikeAncStCLForModel)e).setReportCladeLocalValues(true);
+			}
+
+
+		}
+		String purpose = whatIsMyPurpose();
+		if (StringUtil.blank(purpose))
+			purpose = "for " + getName();
+		if (modelTask == null)
+			modelTask = (ProbModelSourceLike)hireEmployee(ProbModelSourceLike.class, "Source of probability character models ("+ purpose + ")");
+		if (modelTask == null)
+			return sorry(getName() + " couldn't start because no source of models of character evolution obtained.");
+		modelTaskName = new MesquiteString(modelTask.getName());
+		likelihood = new MesquiteNumber();
+		seed = new MesquiteLong(1);
+
+		seed.setValue(originalSeed);
+		generator = new Random(originalSeed);  //seed?
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Source of probability models", makeCommand("setModelSource", this), ProbModelSourceLike.class);
+		mss.setCompatibilityCheck(new ModelCompatibilityInfo(ProbabilityCategCharModel.class, null));
+		mss.setSelected(modelTaskName);
+		addMenuItem("Set Seed (" + purpose + ")...", makeCommand("setSeed",  this));
+		addMenuItem("Max. Events per Branch (Stoch. Char. Map.)...", makeCommand("setMax",  this));
+		return true;
+	}
+
+	public void setOneCharacterAtATime(boolean chgbl){
+		oneAtATimeCHGBL = chgbl;
+		oneAtATime = true;
+		modelTask.setOneCharacterAtATime(chgbl);
+	}
+
+	/*.................................................................................................................*/
+	/** Returns citation for a modules*/
+	public String getCitation(){
+		return "Midford, P.E. & W.P. Maddison. 2006.  Stochastic character mapping module for Mesquite. Version 1.1.";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setModelSource ",modelTask);
+		temp.addLine("setSeed " + originalSeed);
+		temp.addLine("setMax " + MAXEVENTS);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module used to supply character models", "[name of module]", commandName, "setModelSource")) {
+			ProbModelSourceLike temp=  (ProbModelSourceLike)replaceEmployee(ProbModelSourceLike.class, arguments, "Source of probability character models", modelTask);
+			if (temp!=null) {
+				modelTask= temp;
+				incrementMenuResetSuppression();
+				modelTaskName.setValue(modelTask.getName());
+				if (oneAtATime)
+					modelTask.setOneCharacterAtATime(oneAtATimeCHGBL);
+				parametersChanged();
+				decrementMenuResetSuppression();
+			}
+			return modelTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+			long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteLong.isCombinable(s)){
+				String purpose = whatIsMyPurpose();
+				if (StringUtil.blank(purpose))
+					purpose = "for " + getName();
+				s = MesquiteLong.queryLong(containerOfModule(), "Random number seed " + purpose, "Enter an integer value for the random number seed for character evolution simulation", originalSeed);
+			}
+			if (MesquiteLong.isCombinable(s)){
+				originalSeed = s;
+				seed.setValue(originalSeed);
+				parametersChanged(); //?
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum number of events per branch", "[ integer]", commandName, "setMax")) {
+			int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(s)){
+				s = MesquiteInteger.queryInteger(containerOfModule(), "Maximum Number of Events", "Maximum number of events per branch permitted in character evolution simulation", MAXEVENTS, 1, 1000000, true);
+			}
+			if (MesquiteInteger.isCombinable(s)){
+				MAXEVENTS = s;
+
+				parametersChanged(); //?
+			}
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		if (m == modelTask)
+			iQuit();
+	}
+	public boolean allowsStateWeightChoice(){
+		return false;
+	}
+	private long loopSeed(long ic){
+		generator.setSeed(originalSeed);
+
+		long rnd = originalSeed;
+		for (int i = 0; i<ic; i++)
+			rnd =  generator.nextInt();
+		generator.setSeed(rnd+1);
+		return rnd + 1; 
+	}
+	boolean warned = false;
+	boolean verbose = false;
+	CharacterData oldData = null;
+	CategoricalHistory cladeLikelihoods = null;
+	ProbabilityCategCharModel tempModel;
+	Tree tree;
+	/*.................................................................................................................*/
+	public  long getNumberOfMappings(){
+		return MesquiteLong.infinite;
+	}
+  	public  void prepareForMappings(boolean permissiveOfNoSeparateMappings) {
+  	}
+
+	/*.................................................................................................................*/
+	public  void setObservedStates(Tree tree, CharacterDistribution observedStates){
+		if(verbose) MesquiteMessage.println("setObservedStates ");			
+		this.observedStates = observedStates;
+		if (tree==null || observedStates==null)
+			return;
+		this.tree = tree;
+		likelihood.setToUnassigned();
+
+		/* At present this redoes the likelihood calculations each time before sampling a history.  
+		 * In future the likelihood calculations should be done once and cached, and redone only if tree or observedStates have changed
+		 * since last request */
+
+		//a barrier (temporary) while likelihood calculations support only simple categorical
+		Class stateClass = observedStates.getStateClass();
+		if (MeristicState.class.isAssignableFrom(stateClass) || DNAState.class.isAssignableFrom(stateClass) || ProteinState.class.isAssignableFrom(stateClass) || ContinuousState.class.isAssignableFrom(stateClass)) {
+			String s = "Likelihood calculations cannot be performed ";
+			if (DNAState.class.isAssignableFrom(stateClass))
+				s += "currently with DNA or RNA data.  The calculations were not done for some characters.";
+			else if (ProteinState.class.isAssignableFrom(stateClass))
+				s += "currently with protein data.  The calculations were not done for some characters.";
+			else if (ContinuousState.class.isAssignableFrom(stateClass))
+				s += "currently with continuous valued data.  The calculations were not done for some characters.";
+			else if (MeristicState.class.isAssignableFrom(stateClass))
+				s += "currently with meristic data.  The calculations were not done for some characters.";
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+			cladeLikelihoods = null;
+			return;
+		}
+
+		cladeLikelihoods = (CategoricalHistory)observedStates.adjustHistorySize(tree, cladeLikelihoods);
+		ProbPhenCategCharModel origModel = null;
+		//getting the model
+		if (modelTask.getCharacterModel(observedStates) instanceof ProbPhenCategCharModel )
+			origModel = (ProbPhenCategCharModel)modelTask.getCharacterModel(observedStates);
+		if (origModel == null && !MesquiteThread.isScripting()){
+			if (observedStates.getParentData()!= oldData)
+				warned = false;
+			if (!warned){
+				if (observedStates.getParentData()!=null && modelTask instanceof CurrentProbModels) {
+					oldData = observedStates.getParentData();
+					if (AlertDialog.query(containerOfModule(), "Assign models?", "There are currently no probability models assigned to the characters.  Do you want to assign a model to all characters unassigned?")) {
+						((CurrentProbModels)modelTask).chooseAndFillUnassignedCharacters(observedStates.getParentData());
+						if (modelTask.getCharacterModel(observedStates) instanceof ProbPhenCategCharModel )
+							origModel = (ProbPhenCategCharModel)modelTask.getCharacterModel(observedStates);
+						else AlertDialog.notice(containerOfModule(),"Incompatible model","The model you selected is not compatible with Stochastic Character Mapping at this time.");
+					}
+				}
+				else {
+					discreetAlert( "Sorry, there is no probabilistic model of evolution available for the character; likelihood calculations cannot be accomplished.  Please make sure that the source of models chosen is compatible with this character type.");
+					warned = true;
+					return;
+				}
+			}
+			warned = true;
+		}
+
+
+		//getting the reconstructing module
+		if (reconstructTask == null || !reconstructTask.compatibleWithContext(origModel, observedStates)) { 
+			reconstructTask = null;
+			for (int i = 0; i<getNumberOfEmployees() && reconstructTask==null; i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof MargLikeAncStCLForModel)
+					if (((MargLikeAncStCLForModel)e).compatibleWithContext(origModel, observedStates)) {
+						reconstructTask=(MargLikeAncStCLForModel)e;
+					}
+			}
+		}
+
+		if (reconstructString != null)
+			reconstructString.setValue("");
+		//doing the likelihood calculations
+		if (reconstructTask != null) { 
+			//========  1 ===========
+			if (verbose) MesquiteMessage.println("Step 1");
+			//Nielsen's Step 1:  calculate the clade likelihoods.  In the future this will be done once and cached
+			if (tempModel == null || tempModel.getClass() != origModel.getClass()){
+				tempModel = (ProbabilityCategCharModel)origModel.cloneModelWithMotherLink(null);
+    	 		tempModel.setUserVisible(false);
+			}
+			origModel.copyToClone(tempModel);
+			model = (ProbPhenCategCharModel)tempModel;
+			cladeLikelihoods.deassignStates();
+			reconstructTask.estimateParameters( tree,  observedStates,  model, null);
+			reconstructTask.calculateStates( tree,  observedStates,  cladeLikelihoods, model, reconstructString, likelihood);
+
+		}
+		else {
+			String s = "Stochastic mapping cannot be performed because no module was found to perform the calculations for the probability model \"" + model.getName() + "\" with the characters specified.";
+
+			if (!warnedNoCalc) {
+				discreetAlert( s);
+				warnedNoCalc = true;
+			}
+		}
+	}
+	MesquiteString reconstructString = new MesquiteString();
+	public   boolean getMapping(long im, CharacterHistory resultStates, MesquiteString resultString){
+	if (tree==null || observedStates==null || resultStates == null || !(resultStates instanceof CategoricalHistory))
+			return false;
+
+		resultStates.deassignStates();
+		if (cladeLikelihoods == null || !cladeLikelihoods.frequenciesExist()){
+			if (resultString!=null)
+				resultString.append("Stochastic Character Mapping could not be done because likeihoods could not be calculated");
+			return false;
+		}
+		if (verbose) MesquiteMessage.println("Step 2a");
+		loopSeed(im);
+		if (verbose) MesquiteMessage.println("mapping " + im);			
+		//now take clade likelihoods and make a sampled history
+		//get a copy of the results; we will then modify them into the sampled history
+		resultStates = cladeLikelihoods.clone(resultStates);
+		CategoricalHistory sampledHistory = (CategoricalHistory)resultStates;
+		sampledHistory.disposeFrequencies(); //don't want to remember these
+		//========  2a ===========
+		//Nielsen's Step 2a: choose a state at the root based on prior at root and root likelihood's
+		int stateCount = cladeLikelihoods.getMaxState()+1;
+		if (stateCount>model.getMaxState()+1)
+			stateCount= model.getMaxState()+1;
+		//if (verbose) MesquiteMessage.println("cladeLikelihoods thinks maxState is" + maxState);
+
+
+		pi_s = new double[stateCount];  //these are the pi(i)'s
+
+		for (int i = 0;i<stateCount;i++)
+			pi_s[i]=model.priorProbability(i);  //getting the prior from the model
+
+		double denominator = 0.0;
+
+		for (int possibleState = 0; possibleState<stateCount;possibleState++){
+			double stateFrequency = cladeLikelihoods.getFrequency(tree.getRoot(),possibleState);
+			if (verbose) MesquiteMessage.println("At root; stateFrequency for state " + possibleState + " is " + stateFrequency);
+			if (MesquiteDouble.isCombinable(stateFrequency))
+				denominator += pi_s[possibleState]*stateFrequency;
+		}
+		if (denominator == 0){  // something's gone wrong
+			MesquiteMessage.printStackTrace("2a Bad denominator in root likelihood calculations " );
+			if (resultString!=null)
+				resultString.append("Stochastic Character Mapping failed:  2a Bad denominator in root likelihood calculations");
+			return false;
+		}
+		if (verbose) MesquiteMessage.println("Denominator is " + denominator);
+		double sum = 0.0;
+		double randomValue = generator.nextDouble();
+
+
+		for (int candidate = 0;candidate<stateCount;candidate++) {
+			double candidateFrequency = cladeLikelihoods.getFrequency(tree.getRoot(),candidate);
+			if (MesquiteDouble.isCombinable(candidateFrequency)) {
+				sum += (pi_s[candidate]*candidateFrequency)/denominator;
+				if (sum > randomValue) {
+					sampledHistory.setState(tree.getRoot(),CategoricalState.makeSet(candidate));
+					sampledHistory.addInternodeEvent(tree.getRoot(), new CategInternodeEvent(CategoricalState.makeSet(candidate), 0, false));
+					if (verbose) MesquiteMessage.println("I picked " + candidate + " at the root.");
+					break;
+				}
+			}
+		}
+
+
+		if (verbose) MesquiteMessage.println("sampledHistory at root is set to " + sampledHistory.getState(tree.getRoot()));
+
+		//========  2b ===========
+		//Nielsen's Step 2b: then go up through the tree recursively choosing a state at each node based on its clade likelihoods and the state chosen for its immediate ancestor 
+		if (verbose) MesquiteMessage.println("Step 2b");
+		if (!sampleStatesUp(tree,tree.getRoot(),cladeLikelihoods,sampledHistory,model)){
+			if (resultString!=null)
+				resultString.append("Stochastic Character Mapping failed:  2b Bad denominator in root likelihood calculations");
+			
+			return false;
+		}
+
+		//========  3 ===========
+		//Nielsen's Step 3:  sample changes along the internodes 
+		if (verbose) MesquiteMessage.println("Step 3");
+		boolean success = sampleInternodeChanges(tree,tree.getRoot(),sampledHistory,model);
+		if (!success){
+			if (resultString!=null)
+				resultString.append(" Number of events in sampled character history on a branch exceeds maximum allowed (" + MAXEVENTS + ")");
+			resultStates.deassignStates();
+		}
+		else {
+			if (resultString!=null)
+				resultString.append("Stochastic Character Mapping\nBased on: " + reconstructString);
+		}
+		statesAtNodes=resultStates;
+		return success;
+	}
+
+	// This implements the recursion for Nielsen's step 2b
+	private boolean sampleStatesUp(Tree tree,int node,CategoricalHistory cladeLikelihoods,CategoricalHistory sampledHistory,ProbPhenCategCharModel model){
+		int stateCount = cladeLikelihoods.getMaxState()+1;  // Pass this in?
+		if (stateCount>model.getMaxState()+1)
+			stateCount= model.getMaxState()+1;
+		if (node != tree.getRoot()) {
+			int motherSampledState = CategoricalState.getOnlyElement(sampledHistory.getState(tree.motherOfNode(node)));
+			sampledHistory.addInternodeEvent(node, new CategInternodeEvent(sampledHistory.getState(tree.motherOfNode(node)), 0, false));
+
+			// ask the model for transition values from the mother's state to each of the candidate states
+			if (verbose) MesquiteMessage.println("Mother is " + tree.motherOfNode(node)+ " SampledState is "+ sampledHistory.getState(tree.motherOfNode(node)));
+			double Pij[] = new double[stateCount];
+			for (int j=0;j<stateCount;j++){
+				Pij[j]= model.transitionProbability(motherSampledState,j,tree,node);
+				if (verbose) MesquiteMessage.println("Pij["+node+","+j+"] set to "+ Pij[j]);
+			}
+			double denominator = 0.0;
+			for (int possibleState = 0; possibleState < stateCount;possibleState++){
+				double stateFrequency = cladeLikelihoods.getFrequency(node,possibleState); //Peter: this had been tree.getRoot() instead of node -- should be node?
+				if (MesquiteDouble.isCombinable(stateFrequency))
+					denominator += Pij[possibleState]*stateFrequency;
+			}
+			if (denominator == 0){  // something's gone wrong
+				MesquiteMessage.printStackTrace("2b Bad denominator in node likelihood calculations " + stateCount);
+				return false;
+			}
+			if (verbose) MesquiteMessage.println("denominator " + denominator);
+			double sum = 0.0;
+			double randomValue = generator.nextDouble();
+			for (int candidate = 0;candidate<stateCount;candidate++) {
+				double candidateFrequency = cladeLikelihoods.getFrequency(node,candidate);
+				if (MesquiteDouble.isCombinable(candidateFrequency)) {
+					sum += (Pij[candidate]*candidateFrequency)/denominator;
+					if (verbose) MesquiteMessage.println("candidateFrequency " + candidateFrequency + " for state " + candidate + " at node " +node + " sum " + sum);
+					if (sum > randomValue) {
+						sampledHistory.setState(node,CategoricalState.makeSet(candidate));
+						if (verbose) MesquiteMessage.println("I picked " + candidate + " at node " + node);
+						break;
+					}
+				}
+			}
+		}
+		if (tree.nodeIsInternal(node)){
+			for(int d=tree.firstDaughterOfNode(node);tree.nodeExists(d);d=tree.nextSisterOfNode(d)) {
+				if (!sampleStatesUp(tree,d,cladeLikelihoods,sampledHistory,model))
+					return false;
+			}
+
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** This implements the recursion for Nielsen's step 3 */
+	MesquiteInteger numChanges = new MesquiteInteger(0);
+	private boolean sampleInternodeChanges(Tree tree,int node,CategoricalHistory sampledHistory,ProbPhenCategCharModel model) {
+
+		if (node != tree.getRoot()) {
+			int startState = CategoricalState.getOnlyElement(sampledHistory.getState(tree.motherOfNode(node)));
+			int endState = CategoricalState.getOnlyElement(sampledHistory.getState(node));
+			double iRate = model.instantaneousRate(startState,endState,tree,node);
+			double branchLength = tree.getBranchLength(node, 1.0);
+			Vector internodeEvents = null;
+			numChanges.setValue(0);
+
+			internodeEvents = doSimulation(tree,node,startState,endState,model,cladeLikelihoods, numChanges);
+			if (numChanges.getValue()<0)
+				return false;
+
+			if (internodeEvents != null) {
+				Iterator eventIterator = internodeEvents.iterator();
+				while(eventIterator.hasNext()){
+					CategInternodeEvent event = (CategInternodeEvent)eventIterator.next();
+					sampledHistory.addInternodeEvent(node,event);
+
+				}
+			}
+		}
+		if (tree.nodeIsInternal(node)){
+			for(int d=tree.firstDaughterOfNode(node);tree.nodeExists(d);d=tree.nextSisterOfNode(d)) 
+				if (!sampleInternodeChanges(tree,d,sampledHistory, model))
+					return false;
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	private Vector doSimulation(Tree tree, int node, int start, int end, ProbPhenCategCharModel model,CategoricalHistory cladeLikelihoods, MesquiteInteger numChanges){
+		double nextLength;
+		double totalLength;
+		double branchLength = tree.getBranchLength(node, 1.0);
+		Vector result;
+		int nextState;
+		int stateCount = cladeLikelihoods.getMaxState()+1;
+
+		do {
+			result = null;
+			nextState = start;
+			totalLength = 0.0;
+
+			while (totalLength < branchLength){
+				// currentRate is negative (negative values on main diagonal); indicates when the currentState will change to something else
+				double currentRate = model.instantaneousRate(nextState,nextState,tree,node);
+				double randomValue = generator.nextDouble();
+				nextLength = Math.log(randomValue)/currentRate;  //generate a number from exponential distribution
+                                                                  //negative value in currentRate cancels the negative value from log(0<x<1)
+				if (nextLength+totalLength<branchLength) { // a state change has been simulated to happen before the end of the branch
+					if (result == null) result = new Vector();  // start recording changes if haven't already started
+					double denominator = -1*currentRate;        // must equal -1* sum of the other transitions
+					double stateChoice = generator.nextDouble();
+					double sum = 0.0;
+					for (int candidate = 0;candidate<stateCount;candidate++) {
+						if (candidate != nextState){
+							double candidateRate = model.instantaneousRate(nextState,candidate,tree,node);
+							if (MesquiteDouble.isCombinable(candidateRate)) {
+
+								sum += model.instantaneousRate(nextState,candidate,tree,node)/denominator;
+								if (sum > stateChoice) {
+									nextState = candidate;
+									if (verbose) MesquiteMessage.println("I picked " + candidate + " at time " + (nextLength+totalLength)/branchLength + " from node " + node);
+									CategInternodeEvent thisEvent = new CategInternodeEvent(CategoricalState.makeSet(candidate), (totalLength+nextLength)/branchLength, true);
+									result.addElement(thisEvent);
+									if (result.size() > MAXEVENTS){
+										numChanges.setValue(-1);
+										return null;
+									}
+									break;
+								}
+							}
+						}
+					}
+				}
+				totalLength +=nextLength;
+			}
+		} while(nextState != end);    
+		return result;
+	}
+
+
+	/*.................................................................................................................*/
+	/** Returns CompatibilityTest so other modules know if this is compatible with some object. */
+	public CompatibilityTest getCompatibilityTest(){
+		return new RequiresAnyCategoricalData();
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stochastic Character Mapping (Categorical)";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() { 
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates reconstruction of ancestral states using stochastic character mapping. " ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/stochchar/StoredProbModel/StoredProbModel.java b/Source/mesquite/stochchar/StoredProbModel/StoredProbModel.java
new file mode 100644
index 0000000..cb7e80a
--- /dev/null
+++ b/Source/mesquite/stochchar/StoredProbModel/StoredProbModel.java
@@ -0,0 +1,214 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.StoredProbModel;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class StoredProbModel extends ProbModelSourceLike {
+	MesquiteSubmenuSpec smenu;
+	ProbabilityModel currentModel;
+	boolean initialized = false;
+	boolean responseSuppressed = false;
+	MesquiteString modelName;
+	Class currentStateClass = null;
+	int setModelNumber = MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof Class)
+			currentStateClass = (Class)condition;
+		smenu = addSubmenu(null, "Stored Probabilistic Model", makeCommand("setModel", this), getProject().getCharacterModels());
+		smenu.setCompatibilityCheck(getCompatibilityInfo(currentStateClass));
+		smenu.setListableFilter(WholeCharacterModel.class);
+		if ((ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(currentStateClass), 0)==null)
+			return sorry("There are no suitable stored character models available");
+		modelName = new MesquiteString();
+   		addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+		smenu.setList(getProject().getCharacterModels());
+		smenu.setSelected(modelName);
+		
+		getProject().getCentralModelListener().addListener(this);//to listen for static changes to class of current model
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+  	 
+	/*.................................................................................................................*/
+  	 ProbabilityModel chooseModel(Class stateClass){
+		if (!MesquiteThread.isScripting()){
+			return (ProbabilityModel)CharacterModel.chooseExistingCharacterModel(this, getCompatibilityInfo(stateClass), "Choose probability model (for " + getEmployer().getName() + ").  To make additional models, select New Character Model from the Characters menu.");
+		}
+ 		else
+ 			return (ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(stateClass), 0);
+  	 }
+	/*.................................................................................................................*/
+  	 public void endJob(){
+		getProject().getCentralModelListener().removeListener(this);
+  	 	super.endJob();
+  	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (currentModel !=null && obj instanceof Class && ((Class)obj).isAssignableFrom(currentModel.getClass())) {
+			parametersChanged(notification);
+		}
+		else if (obj == currentModel) {
+			parametersChanged(notification);
+		}
+		super.changed(caller, obj, notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == currentModel) {
+			currentModel = null;
+			parametersChanged();
+		}
+	}
+  	 
+   	/** returns model for character ic in data */
+   	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+		Class stateClass = currentStateClass;
+		if (data !=null) 
+			stateClass = data.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			smenu.setCompatibilityCheck(getCompatibilityInfo(stateClass));
+			currentStateClass = stateClass;
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+   	/** returns model for character */
+   	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		Class stateClass = currentStateClass;
+		if (states !=null)
+			stateClass = states.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			smenu.setCompatibilityCheck(getCompatibilityInfo(stateClass));
+			currentStateClass = stateClass;
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+	/*.................................................................................................................*/
+   	boolean oneAtATime= false;
+   	public void setOneCharacterAtATime(boolean chgbl){
+  		oneAtATime = chgbl;
+   	}
+   	
+   	private ModelCompatibilityInfo getCompatibilityInfo(Class stateClass){
+   		return new LikeModelCompatInfo(ProbabilityModel.class, stateClass);
+   	}
+   	
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (currentModel==null)
+  	 		return null;
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setModel " + getProject().getWhichCharacterModel(getCompatibilityInfo(currentStateClass), currentModel) + "   " + ParseUtil.tokenize(currentModel.getName()));  //TODO:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!should say which model
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the probabilistic model of character evolution", "[number of model]", commandName, "setModel")) {
+      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+      			String name = ParseUtil.getToken(arguments, pos);
+ 			ProbabilityModel model = null;
+ 			if (MesquiteInteger.isCombinable(whichModel))
+ 				model = (ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(currentStateClass), whichModel);
+ 			
+ 			if (((model !=null && model instanceof ProbabilityModel) || !MesquiteInteger.isCombinable(whichModel)) && currentStateClass == null && name !=null && !(model.getName().equals(name))){ // not restricted state class; could be scripting without
+ 				model = (ProbabilityModel)getProject().getCharacterModel(name);
+ 			}
+ 			
+	     	 	if (model!=null) {
+	     	 		//if (currentModel!=null)
+	     	 		//	currentModel.removeListener(this);
+	     	 		currentModel = model;
+		 		modelName.setValue(currentModel.getName());
+	     	 		//currentModel.addListener(this);
+	     	 		parametersChanged();
+     	 			return model;
+     	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+				String s = "";
+				if (currentModel == null)
+					s = "Sorry, no reference to the current model was found";
+				else
+					s = "The current model is \"" + currentModel.getName() + "\".\nExplanation: " + currentModel.getExplanation();
+				discreetAlert( s);
+				return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (currentModel==null)
+			return "Model NULL";
+		return "Current model \"" + currentModel.getName() + "\": "+currentModel.getParameters() ;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stored Probability Model";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies a user-specified model of character evolution stored in the file." ;
+   	 }
+   	 
+}
+/* ======================================================================== */
+class LikeModelCompatInfo extends ModelCompatibilityInfo {
+	public LikeModelCompatInfo(Class targetModelSubclass, Class targetStateClass){
+		super(targetModelSubclass, targetStateClass);
+	}
+	 //obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa; added Apr 02
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (obj instanceof ProbabilityModel && !(((ProbabilityModel)obj).isFullySpecified() || obj instanceof CModelEstimator)){
+ 			return false;
+ 		}
+		return  super.isCompatible(obj, project, prospectiveEmployer);
+ 	}
+	
+}
+
+
+
diff --git a/Source/mesquite/stochchar/StoredProbModelSim/StoredProbModelSim.java b/Source/mesquite/stochchar/StoredProbModelSim/StoredProbModelSim.java
new file mode 100644
index 0000000..39c1a25
--- /dev/null
+++ b/Source/mesquite/stochchar/StoredProbModelSim/StoredProbModelSim.java
@@ -0,0 +1,239 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.StoredProbModelSim;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class StoredProbModelSim extends ProbModelSourceSim {
+	MesquiteSubmenuSpec smenu;
+	ProbabilityModel currentModel;
+	boolean initialized = false;
+	boolean responseSuppressed = false;
+	MesquiteString modelName;
+	Class currentStateClass = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof Class)
+			currentStateClass = (Class)condition;
+		smenu = addSubmenu(null, "Stored Probabilistic Model (for simulation)", makeCommand("setModel", this), getProject().getCharacterModels());
+		smenu.setCompatibilityCheck(getCompatibilityInfo(currentStateClass));
+		smenu.setListableFilter(WholeCharacterModel.class);
+		if ((ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(currentStateClass), 0)==null)
+			return sorry("There are no stored character models available of the appropriate type for the simulation.");
+		currentModel = chooseModel(currentStateClass);
+		if (currentModel == null) {
+			if (MesquiteThread.isScripting())
+				logln("No model of character evolution appropriate for the simulation was obtained.");
+			//if not scripting then probably by user cancel, thus no message
+			return false;
+		}
+		modelName = new MesquiteString();
+		modelName.setValue(currentModel.getName());
+   		addMenuItem("About the Model (for " + getEmployer().getName() + ")...", makeCommand("aboutModel", this));
+		smenu.setList(getProject().getCharacterModels());
+		smenu.setSelected(modelName);
+		
+		getProject().getCentralModelListener().addListener(this); //to listen for static changes to class of current model
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+  	 	return false;
+  	 }
+	/*.................................................................................................................*/
+ 	 ProbabilityModel chooseModel(Class stateClass){
+		if (!MesquiteThread.isScripting()){
+			return (ProbabilityModel)CharacterModel.chooseExistingCharacterModel(this, getCompatibilityInfo(stateClass), "Choose probability model (for " + getEmployer().getName() + ").  To make additional models, select New Character Model from the Characters menu");
+		}
+ 		else
+ 			return (ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(stateClass), 0);
+  	 }
+	/*.................................................................................................................*/
+  	 public void endJob(){
+		getProject().getCentralModelListener().removeListener(this);
+  	 	super.endJob();
+  	 }
+   	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (currentModel !=null && obj instanceof Class && ((Class)obj).isAssignableFrom(currentModel.getClass())) {
+			parametersChanged(notification);
+		}
+		super.changed(caller, obj, notification);
+	}
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (obj == currentModel) {
+			currentModel = null;
+			parametersChanged();
+		}
+	}
+  	 
+   	/** returns model for character ic in data */
+   	public CharacterModel getCharacterModel(CharacterData data, int ic) {
+		Class stateClass = currentStateClass;
+		if (data !=null) 
+			stateClass = data.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			smenu.setCompatibilityCheck(getCompatibilityInfo(stateClass));
+			currentStateClass = stateClass;
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+   	/** returns model for character */
+   	public CharacterModel getCharacterModel(CharacterStatesHolder states){
+		Class stateClass = currentStateClass;
+		if (states !=null)
+			stateClass = states.getStateClass();
+		if (stateClass !=null && stateClass != currentStateClass && oneAtATime){
+			smenu.setCompatibilityCheck(getCompatibilityInfo(stateClass));
+			currentStateClass = stateClass;
+			resetContainingMenuBar();
+			
+		}
+		if (currentModel == null)
+			currentModel = chooseModel(stateClass);
+		if (currentModel == null)
+			return null;
+		return currentModel;
+   	}
+	/*.................................................................................................................*/
+   	boolean oneAtATime= false;
+   	public void setOneCharacterAtATime(boolean chgbl){
+  		oneAtATime = chgbl;
+   	}
+   	
+   	private ModelCompatibilityInfo getCompatibilityInfo(Class stateClass){
+   		return new SimModelCompatInfo(ProbabilityModel.class, stateClass);
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (currentModel==null)
+  	 		return null;
+   	 	Snapshot temp = new Snapshot();
+   	 	if (currentModel != null)
+  	 	temp.addLine("setModelInt " + getProject().getWhichCharacterModel(getCompatibilityInfo(currentStateClass), currentModel) + " " + ParseUtil.tokenize(currentModel.getName()));  //TODO:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!should say which model
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the probabilistic model of character evolution", "[number of model]", commandName, "setModel")) {
+      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+      			String expectedName  = ParseUtil.getToken(arguments, pos);
+      			ProbabilityModel model = null;
+      			if (!MesquiteInteger.isCombinable(whichModel)) {
+ 				model = (ProbabilityModel)getProject().getCharacterModel(parser.getFirstToken(arguments));
+ 			}
+ 			else {
+ 				//prefer the name if available
+	 			if (expectedName !=null) {
+	 				model = (ProbabilityModel)getProject().getCharacterModel(expectedName);
+	 				if (!model.isCompatible(getCompatibilityInfo(currentStateClass), getProject(), this))
+	 					model = null;
+	 			}
+	 			
+	 			if (model == null)
+	 				model = (ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(currentStateClass), whichModel);
+ 			}
+ 			
+	     	 	if (model!=null) {
+	     	 		if (model.getName() != null && !StringUtil.blank(expectedName) && !model.getName().equals(expectedName))
+	     	 			MesquiteMessage.warnProgrammer("Error: model set not one expected (set: " + model.getName() + "; expected: " + expectedName + ")");
+	     	 		if (currentModel!=null)
+	     	 			currentModel.removeListener(this);
+	     	 		currentModel = model;
+		 		modelName.setValue(currentModel.getName());
+	     	 		currentModel.addListener(this);
+	     	 		parametersChanged();
+     	 			return model;
+     	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the probabilistic model of character evolution (internal, for scripting use)", "[number of model]", commandName, "setModelInt")) {
+      			int whichModel = MesquiteInteger.fromFirstToken(arguments, pos);
+      			String expectedName  = ParseUtil.getToken(arguments, pos);
+      			ProbabilityModel model = null;
+ 			if (expectedName !=null) { //choose the name first whether or not compatible
+ 				model = (ProbabilityModel)getProject().getCharacterModel(expectedName);
+ 			}
+      			if (model == null ){
+	      			if (!MesquiteInteger.isCombinable(whichModel)) { //just the name
+	 				model = (ProbabilityModel)getProject().getCharacterModel(parser.getFirstToken(arguments));
+	 			}
+	 			else if (whichModel >= 0) {
+		 			model = (ProbabilityModel)getProject().getCharacterModel(getCompatibilityInfo(currentStateClass), whichModel);
+	 			}
+ 			}
+ 			
+	     	 	if (model!=null) {
+	     	 		if (model.getName() != null && !StringUtil.blank(expectedName) && !model.getName().equals(expectedName))
+	     	 			MesquiteMessage.warnProgrammer("Error: model set not one expected (set: " + model.getName() + "; expected: " + expectedName + ")");
+	     	 		if (currentModel!=null)
+	     	 			currentModel.removeListener(this);
+	     	 		currentModel = model;
+		 		modelName.setValue(currentModel.getName());
+	     	 		currentModel.addListener(this);
+	     	 		parametersChanged();
+     	 			return model;
+     	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Displays a dialog about the last model returned", null, commandName, "aboutModel")) {
+				String s = "";
+				if (currentModel == null)
+					s = "Sorry, no reference to the current model was found";
+				else
+					s = "The current model is \"" + currentModel.getName() + "\".\nExplanation: " + currentModel.getExplanation();
+				discreetAlert( s);
+				return null;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (currentModel==null)
+			return "Model NULL";
+		return "Current model \"" + currentModel.getName() + "\": "+currentModel.getParameters() ;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stored Probability Model for Simulation";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies a user-specified model of character evolution stored in the file for simulation." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/stochchar/aStochCharIntro/aStochCharIntro.java b/Source/mesquite/stochchar/aStochCharIntro/aStochCharIntro.java
new file mode 100644
index 0000000..eb8815c
--- /dev/null
+++ b/Source/mesquite/stochchar/aStochCharIntro/aStochCharIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.aStochCharIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aStochCharIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aStochCharIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides stochastic models and simulations of character evolution.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stochastic Character Evolution Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Stochastic Character Evolution Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, W.P. & D.R. Maddison. 2006.  StochChar: A package of Mesquite modules for stochastic models of character evolution.  Version 1.1.";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/stochchar/explanation.txt b/Source/mesquite/stochchar/explanation.txt
new file mode 100644
index 0000000..eb04444
--- /dev/null
+++ b/Source/mesquite/stochchar/explanation.txt
@@ -0,0 +1,2 @@
+Stochastic Character Evolution Package
+Provides basic services for managing and studying stochastic models of character evolution.  Character evolution can be simulated on a tree.  Except for the Brownian motion model for continuous data, this package does NOT contain specifics of models, which reside in other packages (e.g.,  Genesis Package).
diff --git a/Source/mesquite/stochchar/lib/AsymmModel.java b/Source/mesquite/stochchar/lib/AsymmModel.java
new file mode 100644
index 0000000..54ac1c4
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/AsymmModel.java
@@ -0,0 +1,883 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.lib;
+
+/* ~~ */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+import Jama.*;
+
+public class AsymmModel extends ProbPhenCategCharModel implements CModelEstimator, Evaluator {
+	double param0 = MesquiteDouble.unassigned;
+
+	double param1 = MesquiteDouble.unassigned;
+
+	double[][] probMatrix, rateMatrix, eigenVectors, inverseEigenVectors;
+
+	double[] eigenValues;
+
+	boolean hasDefaultValues = true;
+
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	boolean recalcProbsNeeded = true;
+
+	boolean needToPrepareMatrices = true;
+
+	double previousBranchLength = MesquiteDouble.unassigned;
+
+	boolean unassigned = true;
+
+	boolean param0Unassigned = true;
+
+	boolean param1Unassigned = true;
+
+	private boolean useRateBiasNotation = false;
+
+	private boolean useEquilFreqAsPrior = true;
+
+	public AsymmModel(String name, Class dataClass) {
+		super(name, dataClass);
+		maxStateDefined = 1; // restriction new as of 1. 1
+		maxState = 1; // restriction new as of 1. 1
+		// maxStateDefined = CategoricalState.maxCategoricalState;
+		// maxState = CategoricalState.maxCategoricalState;
+		needToPrepareMatrices = true;
+		recalcProbsNeeded = true;
+		prepareMatrices();
+	}
+
+	/* --------------------------------------------- */
+	public double evaluate(MesquiteDouble param, Object param2) { // used when a single parameter is being estimated
+		if (param2 instanceof TreeDataModelBundle && param != null) {
+			TreeDataModelBundle b = (TreeDataModelBundle) param2;
+			CommandRecord cr = b.getCommandRecord();
+			if (param0Unassigned) {
+				if (param.getValue() < 0) // param0
+					return MesquiteDouble.veryLargeNumber;
+				param0 = param.getValue();
+				prepareMatrices();
+				double result = -b.getLikelihoodCalculator().logLikelihoodCalc(b.getTree(), this, b.getCharacterDistribution());
+				if (cr != null)
+					cr.tick("Estimating asymm model:  param0 " + param0 + " -logL " + result);
+				return result;
+			}
+			else {
+				if (param.getValue() <= 0) // param1
+					return MesquiteDouble.veryLargeNumber;
+				param1 = param.getValue();
+				prepareMatrices();
+				double result = -b.getLikelihoodCalculator().logLikelihoodCalc(b.getTree(), this, b.getCharacterDistribution());
+				if (cr != null)
+					cr.tick("Estimating asymm model:  param1 " + param1 + " -logL " + result);
+				return result;
+			}
+		}
+		else
+			return 0;
+	}
+
+	/* --------------------------------------------- */
+	double limit = 10000;
+
+	int allowedEdgeHits = 0; // to stop the optimization from wandering if very high rates; edge allowed to be hit only a certain number of tiems
+
+	int beginningAllowed = 6;
+
+	public double evaluate(double[] x, Object param) {// used when both parameters are being estimated
+		if (param instanceof TreeDataModelBundle && x != null && x.length == 2) {
+			TreeDataModelBundle b = (TreeDataModelBundle) param;
+			Tree t = b.getTree();
+			CommandRecord cr = b.getCommandRecord();
+			double height = t.tallestPathAboveNode(t.getRoot()); // to stop the optimization from wandering if very high rates
+			if (x[1] * height > limit && allowedEdgeHits-- < 0) { // param1
+				return MesquiteDouble.veryLargeNumber;
+			}
+			if (x[0] * height > limit && allowedEdgeHits-- < 0) { // param0
+				return MesquiteDouble.veryLargeNumber;
+			}
+			if (x[1] <= 0) { // param1 //parameters shouldn't be 0 or negative unless constant, but constant filtered out before this
+				return MesquiteDouble.veryLargeNumber;
+			}
+			if (x[0] <= 0) { // param0
+				return MesquiteDouble.veryLargeNumber;
+			}
+			param0 = x[0];
+			param1 = x[1];
+
+			prepareMatrices();
+			double result = -b.getLikelihoodCalculator().logLikelihoodCalc(b.getTree(), this, b.getCharacterDistribution());
+			if (cr != null)
+				cr.tick("Estimating asymm model:  params " + param0 + " " + param1 + " -logL " + result);
+			return result;
+		}
+		else
+			return 0;
+	}
+
+	/*
+	 * public Object getLikelihoodSurface(Tree tree, CharacterDistribution observedStates, CLikelihoodCalculator lc, int divisions, double[] outputBounds){ //also pass upper & lower bounds //THIS DOESN:T work at present Optimizer opt = new Optimizer(this); TreeDataModelBundle bundle = new TreeDataModelBundle(tree, this, observedStates, null, lc, null); boolean rU = param0Unassigned; boolean bU = param1Unassigned; double r = param0; double b = param1; param0Unassigned = true; param1Unassigne [...]
+	 * (param0Unassigned && param1Unassigned) { double[] params = new double[2]; params[0] = 0.1; params[1]=1.0; opt.optimize(params, bundle); double[] lower = opt.getLowerBoundsSearched(); double[] upper = opt.getUpperBoundsSearched(); double lowParam0 = lower[0]; double upperParam0 = upper[0]; double lowParam1 = lower[1]; double upperParam1 = upper[1]; if (lowParam0<0) lowParam0 =0; if (lowParam1<0) lowParam1=0; double[][] surface = opt.grid(lowParam0, upperParam0, lowParam1, upperParam1, [...]
+	 * null & big enough! outputBounds[1]= upperParam0; outputBounds[2]= lowParam1; outputBounds[3]= upperParam1; param0Unassigned = rU; param1Unassigned = bU; param0 = r; param1 = b; return surface; } param0Unassigned = rU; param1Unassigned = bU; param0 = r; param1 = b; return null; }
+	 */
+	/* --------------------------------------------- */
+	public void deassignParameters() {
+		param0 = MesquiteDouble.unassigned;
+		param1 = MesquiteDouble.unassigned;
+		unassigned = true;
+		param0Unassigned = true;
+		param1Unassigned = true;
+	}
+
+	/* --------------------------------------------- */
+	MkModel mkHelper = new MkModel("asymm helper", CategoricalState.class); // used to provide preliminary guess at rate
+
+	// Optimization settings
+	public static final int BASE_ON_MK1 = 0;
+
+	public static final int FLIP_FLOP = 1;
+
+	public static final int MK1_AND_FLIP_FLOP = 2; // conservative and slow
+
+	public static int optimizationMode = MK1_AND_FLIP_FLOP;
+
+	static final boolean scaleRescale = true;
+
+	/* --------------------------------------------- */
+	public void estimateParameters(Tree originalTree, CharacterDistribution observedStates, CLikelihoodCalculator lc) {
+		boolean constant = (observedStates.isConstant(originalTree, originalTree.getRoot()));
+		if (constant) {
+			if (param0Unassigned && param1Unassigned) {
+				if (useRateBiasNotation) {
+					param0 = 0; // rate
+					param1 = 1.0; // bias
+				}
+				else {
+					param0 = 0; // backward
+					param1 = 0; // forward
+				}
+			}
+			else if (param0Unassigned) { // 0 is rate or backwards
+				param0 = 0;
+			}
+			else { // 1 is bias or forwards
+				if (useRateBiasNotation)
+					param1 = 1.0; // bias
+				else
+					param1 = 0; // forward
+			}
+			prepareMatrices();
+		}
+		else {
+			if (param0Unassigned && param1Unassigned) { // both parameters need to be estimated
+				boolean wasURBN = useRateBiasNotation;
+				useRateBiasNotation = false; // turn this off in this case
+				Tree tree = null;
+				double height = 0;
+				if (scaleRescale) { // rescales tree to 1.0 height to help optimization, which takes longer with larger numbers
+					MesquiteTree mTree = originalTree.cloneTree();
+					mTree.setAllUnassignedBranchLengths(1.0, false);
+					height = mTree.tallestPathAboveNode(mTree.getRoot(), 1.0); // to adjust start point depending on how tall is tree
+					if (height != 0)
+						mTree.scaleAllBranchLengths(1.0 / height, false);
+					tree = mTree;
+				}
+				else
+					tree = originalTree;
+				Optimizer opt = new Optimizer(this);
+				TreeDataModelBundle bundle = new TreeDataModelBundle(tree, this, observedStates, null, lc);
+				double best = Double.MAX_VALUE;
+				if (optimizationMode != FLIP_FLOP) {
+					/* here use Mk1 to yield rate that is used as starting value for estimation */
+					mkHelper.deassignParameters();
+					mkHelper.estimateParameters(tree, observedStates, lc);
+					double rate = mkHelper.getInstantaneousRate();
+
+					double[] params = new double[2];
+					// initialize parameters using rate estimated from mk1
+					if (useRateBiasNotation) {
+						params[0] = rate; // rate
+						params[1] = 1.0; // bias
+					}
+					else {
+						params[0] = rate; // backward
+						params[1] = rate; // forward
+					}
+					allowedEdgeHits = beginningAllowed;
+
+					best = opt.optimize(params, bundle);
+					param0 = params[0];
+					param1 = params[1];
+				}
+
+				if (optimizationMode != BASE_ON_MK1) {
+					/*
+					 * here use flipflop method, which tries three separate starting points for estimation of forward and backward rates: 1.0 - 1.0 1.0 - 0.1 0.1 - 1.0
+					 */
+					double[] params = new double[2];
+					params[0] = 1;
+					params[1] = 1;
+					double b0;
+					double b1;
+					if (optimizationMode != MK1_AND_FLIP_FLOP) {
+						b0 = params[0];
+						b1 = params[1];
+					}
+					else {
+						b0 = param0;
+						b1 = param1;
+					}
+
+					double next = opt.optimize(params, bundle);
+
+					if (!acceptableResults(next, params[0], params[1])) {
+						MesquiteMessage.println("Warning: NaN encountered in AsymmModel optimization");
+					}
+					else if ((next < best || optimizationMode == FLIP_FLOP)) {
+						best = next;
+						b0 = params[0];
+						b1 = params[1];
+
+					}
+					if (useRateBiasNotation) {
+						params[0] = 0.316227755; // rate
+						params[1] = 10; // bias
+					}
+					else {
+						params[0] = 0.1; // backward
+						params[1] = 1; // forward
+					}
+					param0 = params[0];
+					param1 = params[1];
+					allowedEdgeHits = beginningAllowed;
+					next = opt.optimize(params, bundle);
+					if (!acceptableResults(next, params[0], params[1])) {
+						MesquiteMessage.println("Warning: NaN encountered in AsymmModel optimization");
+					}
+					else if (next < best) {
+						best = next;
+						b0 = params[0];
+						b1 = params[1];
+					}
+					if (useRateBiasNotation) {
+						params[0] = 0.316227755; // rate
+						params[1] = .1; // bias
+					}
+					else {
+						params[0] = 1; // backward
+						params[1] = 0.1; // forward
+					}
+					param0 = params[0];
+					param1 = params[1];
+					allowedEdgeHits = beginningAllowed;
+					next = opt.optimize(params, bundle);
+					if (!acceptableResults(next, params[0], params[1])) {
+						MesquiteMessage.println("Warning: NaN encountered in AsymmModel optimization");
+					}
+					else if (next < best) {
+						best = next;
+						b0 = params[0];
+						b1 = params[1];
+					}
+					param0 = b0;
+					param1 = b1;
+				}
+
+				if (scaleRescale && height != 0) {
+					if (useRateBiasNotation) { // UNDO the scaling of the tree
+						param0 *= 1.0 / height; // rate
+					}
+					else {
+						param0 *= 1.0 / height; // backward
+						param1 *= 1.0 / height; // forward
+					}
+				}
+				if (wasURBN) {
+					double bias = param1 / param0;
+					double rate = Math.sqrt(bias) * param0;
+					param0 = rate;
+					param1 = bias;
+					useRateBiasNotation = true;
+				}
+			}
+			else { // only one parameter needs estimation
+				Tree tree = originalTree;
+				Optimizer opt = new Optimizer(this);
+				TreeDataModelBundle bundle = new TreeDataModelBundle(tree, this, observedStates, null, lc);
+				if (param0Unassigned) { // 0 is rate or backwards
+					MesquiteDouble param = new MesquiteDouble(1.0);
+					// changed from 0.993
+					progressiveOptimize(tree, bundle, opt, param, 0, MkModel.optWidth);
+					param0 = param.getValue();
+				}
+				else { // 1 is bias or forwards
+					MesquiteDouble param = new MesquiteDouble(1.0);
+					if (!useRateBiasNotation) { // param is forwards
+						progressiveOptimize(tree, bundle, opt, param, 0, MkModel.optWidth);
+					}
+					else { // param is bias
+						progressiveOptimize(tree, bundle, opt, param, 0, MkModel.optWidth);
+					}
+					param1 = param.getValue();
+
+				}
+			}
+			prepareMatrices();
+		}
+	}
+
+	private boolean acceptableResults(double like, double b, double c) {
+		return !(Double.isNaN(like) || Double.isNaN(b) || Double.isNaN(c));
+	}
+
+	/* --------------------------------------------- */
+	public double getParam0() {
+		return param0;
+	}
+
+	/* --------------------------------------------- */
+	public void setParam0(double r) {
+		hasDefaultValues = false;
+		param0 = r;
+		if (MesquiteDouble.isCombinable(param0))
+			param0Unassigned = false;
+		prepareMatrices();
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, true);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, false);
+	}
+
+	/* --------------------------------------------- */
+	public double getParam1() {
+		return param1;
+	}
+
+	/* --------------------------------------------- */
+	public void setParam1(double r) {
+		hasDefaultValues = false;
+		param1 = r;
+		if (MesquiteDouble.isCombinable(param1))
+			param1Unassigned = false;
+		prepareMatrices();
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, true);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, false);
+	}
+
+	/* --------------------------------------------- */
+	private void prepareMatrices() {
+		if (maxState < 0)
+			return;
+		if (MesquiteDouble.isUnassigned(param0) || MesquiteDouble.isUnassigned(param1)) {
+			unassigned = true;
+			return;
+		}
+		needToPrepareMatrices = false;
+		double biasRoot = Math.sqrt(param1);
+		boolean changed = false;
+		unassigned = false;
+		if (rateMatrix == null || rateMatrix.length != maxState + 1) {
+			rateMatrix = new double[maxState + 1][maxState + 1];
+			changed = true;
+		}
+		// filling off diagonal elements
+		// NOTE: this may not need to be so complex now that maxstate is restricted to 1
+		for (int i = 0; i < maxState + 1; i++)
+			for (int j = 0; j < maxState + 1; j++) {
+				double r = MesquiteDouble.unassigned;
+				if (i == j)
+					;
+				else {
+					if (j > i) {
+						if (useRateBiasNotation)
+							r = MesquiteDouble.multiply(param0, biasRoot);
+						else
+							r = param1;
+					}
+					else {
+						if (useRateBiasNotation)
+							r = MesquiteDouble.divide(param0, biasRoot);
+						else
+							r = param0;
+					}
+					if (rateMatrix[i][j] != r) {
+						rateMatrix[i][j] = r;
+						changed = true;
+						if (!MesquiteDouble.isCombinable(r))
+							unassigned = true;
+					}
+				}
+			}
+		// adjusting the diagonal to make row sum to 0
+		for (int i = 0; i < maxState + 1; i++) {
+			double rowSum = 0;
+			for (int j = 0; j < maxState + 1; j++)
+				if (i != j)
+					rowSum += rateMatrix[j][i]; // why is this j i? -- seems to be what works!
+			double r = -rowSum;
+			if (rateMatrix[i][i] != r) {
+				rateMatrix[i][i] = r;
+				changed = true;
+			}
+		}
+		if (changed) {
+			recalcProbsNeeded = true;
+			if (unassigned) {
+				if (eigenVectors == null)
+					eigenVectors = new double[maxState + 1][maxState + 1];
+				if (eigenValues == null)
+					eigenValues = new double[maxState + 1];
+				DoubleArray.deassignArray(eigenValues);
+				Double2DArray.deassignArray(eigenVectors);
+			}
+			else {
+				EigenAnalysis e = new EigenAnalysis(rateMatrix, true, false, true);
+				eigenValues = e.getEigenvalues();
+				eigenVectors = e.getEigenvectors();
+				Matrix m = new Matrix(eigenVectors);
+				Matrix r = m.inverse();
+				inverseEigenVectors = r.getArrayCopy();
+			}
+		}
+
+	}
+
+	private double getEquilFreq0() {
+		double r01, r10;
+		if (!MesquiteDouble.isCombinable(param1) || !MesquiteDouble.isCombinable(param0))
+			return MesquiteDouble.unassigned;
+
+		if (useRateBiasNotation) { // had been forward/backward
+			r01 = Math.sqrt(param1) * param0;
+			r10 = param0 / Math.sqrt(param1);
+		}
+		else {
+			r01 = param1;
+			r10 = param0;
+		}
+
+		double f0 = r10 / (r01 + r10);
+		return f0;
+
+	}
+	double[][] p, tprobMatrix;
+	/* --------------------------------------------- */
+	public void recalcProbabilities(double branchLength) {
+
+		if (unassigned)
+			return;
+		previousBranchLength = branchLength;
+		double[][] tent = new double[maxState + 1][maxState + 1];
+		for (int i = 0; i < maxState + 1; i++)
+			for (int j = 0; j < maxState + 1; j++) {
+				if (i == j)
+					tent[i][j] = Math.exp(eigenValues[i] * branchLength);
+				else
+					tent[i][j] = 0;
+			}
+		p = Double2DArray.multiply(eigenVectors, tent, p);
+		tprobMatrix = Double2DArray.multiply(p, inverseEigenVectors, tprobMatrix);
+		probMatrix = Double2DArray.squnch(tprobMatrix, probMatrix);
+		recalcProbsNeeded = false;
+	}
+
+	/* --------------------------------------------- */
+	public void setCharacterDistribution(CharacterStatesHolder cStates) {
+		super.setCharacterDistribution(cStates);
+		prepareMatrices();
+	}
+
+	/* --------------------------------------------- */
+	public int evolveState(int beginState, Tree tree, int node) {
+		double r = randomNumGen.nextDouble();
+		double branchLength = tree.getBranchLength(node, 1.0);
+		if (needToPrepareMatrices)
+			prepareMatrices();
+		if (recalcProbsNeeded || previousBranchLength != branchLength)
+			recalcProbabilities(branchLength);
+
+		double accumProb = 0;
+
+		if (probMatrix == null)
+			return -1;
+		else if (beginState > probMatrix.length)
+			return -1;
+
+		for (int i = 0; i < probMatrix[beginState].length && i < maxState + 1; i++) {
+			accumProb += probMatrix[beginState][i];
+			if (r < accumProb)
+				return i;
+		}
+		return maxState;
+	}
+
+	/* --------------------------------------------- */
+	public double transitionProbability(int beginState, int endState, Tree tree, int node) {
+		if (!inStates(beginState) || !inStates(endState)) {
+			return 0;
+		}
+		else {
+			if (tree == null)
+				return 0;
+			if (needToPrepareMatrices)
+				prepareMatrices();
+			double branchLength = tree.getBranchLength(node, 1.0);
+			if (recalcProbsNeeded || previousBranchLength != branchLength)
+				recalcProbabilities(branchLength);
+			if (probMatrix == null)
+				return 0;
+			return probMatrix[beginState][endState];
+		}
+	}
+
+	/* --------------------------------------------- */
+	public double instantaneousRate(int beginState, int endState, Tree tree, int node) {
+		if (beginState < 0 || beginState > maxState || endState < 0 || endState > maxState) {
+			return 0;
+		}
+		else {
+			if (rateMatrix == null || needToPrepareMatrices)
+				prepareMatrices();
+			if (rateMatrix == null)
+				return 0;
+			return rateMatrix[beginState][endState];
+		}
+	}
+
+	public boolean priorAlwaysFlat(){
+		return false;
+	}
+	/* --------------------------------------------- */
+	public double priorProbability(int state) {
+		if (!inStates(state))
+			return 0;
+
+		if (useEquilFreqAsPrior && MesquiteDouble.isCombinable(getEquilFreq0())) {
+
+			if (state == 0)
+				return getEquilFreq0();
+			else if (state == 1)
+				return 1 - getEquilFreq0();
+			MesquiteMessage.warnProgrammer("Error: asymmMk model requested priorProb on state > 1");
+			return 0;
+		}
+		else {
+			if (maxState == 0)
+				return (0.5); // flat prior
+			else
+				return (1.0 / (maxState + 1)); // flat prior
+		}
+
+	}
+
+	/* --------------------------------------------- */
+	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md) {
+		if (md == null || !(md instanceof AsymmModel))
+			return;
+		super.copyToClone(md);
+		AsymmModel model = (AsymmModel) md;
+		model.param0 = param0;
+		model.param1 = param1;
+		model.param0Unassigned = param0Unassigned;
+		model.param1Unassigned = param1Unassigned;
+		model.recalcProbsNeeded = true;
+		model.needToPrepareMatrices = true;
+		model.useRateBiasNotation = useRateBiasNotation;
+		model.useEquilFreqAsPrior = useEquilFreqAsPrior;
+		model.prepareMatrices();
+		model.notifyListeners(model, new Notification(MesquiteListener.UNKNOWN));
+	}
+
+	/* --------------------------------------------- */
+	public String getExplanation() {
+		return "Asymmetrical 2-parameter Markov k-state model, with two different rates of change (one for increases in state, one for decreases in state).  Can be expressed either as forward vs. backward rates, or as rate plus bias.";
+	}
+
+	/* --------------------------------------------- */
+	/** Returns whether parameters of model are fully specified. If so, it can be used for evolving states. */
+	public boolean isFullySpecified() {
+		return !param0Unassigned && !param1Unassigned && param0 != MesquiteDouble.unassigned && param1 != MesquiteDouble.unassigned;
+	}
+
+	/* ................................................................................................................. */
+	/** Performs command (for Commandable interface) */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the instantaneous rate of change in the model (if using rate/bias notation) or backward rate of change (if using forward/backward notation)", "[rate of change; must be > 0]", commandName, "setParam0")) {
+			pos.setValue(0);
+			String token = ParseUtil.getToken(arguments, pos);
+			if (MesquiteString.explicitlyUnassigned(token)) {
+				param0Unassigned = true;
+				setParam0(MesquiteDouble.unassigned);
+				return null;
+			}
+			pos.setValue(0);
+			double newRate = MesquiteDouble.fromString(arguments, pos);
+			double a = getParam0();
+			if (newRate >= 0 && newRate != a && MesquiteDouble.isCombinable(newRate))
+				setParam0(newRate);
+		}
+		else if (checker.compare(this.getClass(), "Sets the bias of change (gains over loses) in the model (if using rate/bias notation) or forward rate of change (if using forward/backward notation)", "[rate of change; must be > 0]", commandName, "setParam1")) {
+			pos.setValue(0);
+			String token = ParseUtil.getToken(arguments, pos);
+			if (MesquiteString.explicitlyUnassigned(token)) {
+				param1Unassigned = true;
+				setParam1(MesquiteDouble.unassigned);
+				return null;
+			}
+			pos.setValue(0);
+			double newBias = MesquiteDouble.fromString(arguments, pos);
+			double a = getParam1();
+			if (newBias >= 0 && newBias != a && MesquiteDouble.isCombinable(newBias))
+				setParam1(newBias);
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the asymmetrical model is described in terms of a rate and a bias, or a backward and forward rate", "[on or off to indicate whether uses rate-bias]", commandName, "toggleNotation")) {
+			boolean onOff = !useRateBiasNotation;
+			if (!StringUtil.blank(arguments))
+				onOff = MesquiteBoolean.fromOffOnString(ParseUtil.getFirstToken(arguments, pos));
+			if (useRateBiasNotation != onOff) {
+				setUseRateBiasNotation(onOff);
+				notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), null, true);
+				return null;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the asymmetrical model uses the equilibrium frequencies as prior at the root", "[on or off to indicate whether uses equilibrium frequencies]", commandName, "toggleEquilibPrior")) {
+			boolean onOff = !useEquilFreqAsPrior;
+			if (!StringUtil.blank(arguments))
+				onOff = MesquiteBoolean.fromOffOnString(ParseUtil.getFirstToken(arguments, pos));
+			if (useEquilFreqAsPrior != onOff) {
+				setUseEquilFreqAsPrior(onOff);
+				notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), null, true);
+				return null;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum allowed state for this model", "[0...maxCategoricalState]", commandName, "setMaxState")) {
+			if (isBuiltIn())
+				return null;
+			int m = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(m))
+				m = MesquiteInteger.queryInteger(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Set maximum allowed state", "Maximum allowed state for this model:", maxStateDefined);
+			if (m > 0 && m <= CategoricalState.maxCategoricalState && m != maxStateDefined) {
+				maxState = m;
+				maxStateDefined = m;
+				prepareMatrices();
+				notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+			}
+
+		}
+
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/* --------------------------------------------- */
+	/** returns name of model class (e.g. "stepmatrix") SHOULD MATCH NAME returned by getNEXUSNameOfModelClass of module */
+	public String getNEXUSClassName() {
+		return "AsymmMk";
+	}
+
+	/* --------------------------------------------- */
+	public boolean getUseEquilFreqAsPrior() {
+		return useEquilFreqAsPrior;
+	}
+
+	/* --------------------------------------------- */
+	public void setUseEquilFreqAsPrior(boolean u) {
+		useEquilFreqAsPrior = u;
+	}
+
+	/* --------------------------------------------- */
+	public boolean getUseRateBiasNotation() {
+		return useRateBiasNotation;
+	}
+
+	/* --------------------------------------------- */
+	public void setUseRateBiasNotation(boolean u) {
+		if (u != useRateBiasNotation) {
+			useRateBiasNotation = u;
+			if (param0Unassigned && param1Unassigned)
+				return;
+			else {
+				if (param0Unassigned)
+					param0 = 1.0;
+				if (param1Unassigned)
+					param1 = 1.0;
+				param0Unassigned = false; // added after 1.03
+				param1Unassigned = false; // added after 1.03
+				if (useRateBiasNotation) { // had been forward/backward
+					double bias = param1 / param0;
+					double rate = Math.sqrt(bias) * param0;
+					param0 = rate;
+					param1 = bias;
+				}
+				else { // had been forward/backward
+					double forward = Math.sqrt(param1) * param0;
+					double backward = param0 / Math.sqrt(param1);
+					param0 = backward;
+					param1 = forward;
+				}
+				prepareMatrices();
+			}
+		}
+	}
+
+	/* --------------------------------------------- */
+	public void fromString(String description, MesquiteInteger stringPos, int format) {
+		hasDefaultValues = false;
+		String s = ParseUtil.getToken(description, stringPos);
+		useRateBiasNotation = !("backward".equalsIgnoreCase(s) || "forward".equalsIgnoreCase(s));
+		double first = MesquiteDouble.fromString(description, stringPos);
+		if ("backward".equalsIgnoreCase(s) || "rate".equalsIgnoreCase(s))
+			param0 = first;
+		else
+			param1 = first;
+		s = ParseUtil.getToken(description, stringPos);
+		double second = MesquiteDouble.fromString(description, stringPos);
+		if ("forward".equalsIgnoreCase(s) || "bias".equalsIgnoreCase(s))
+			param1 = second;
+		else
+			param0 = second;
+
+		s = ParseUtil.getToken(description, stringPos);
+		if ("maxState".equalsIgnoreCase(s)) {
+			int m = MesquiteInteger.fromString(description, stringPos);
+			if (m != 1)
+				MesquiteMessage.warnUser("WARNING: asymmMk model has maxState set to other than 1.  This is no longer permitted");
+			s = ParseUtil.getToken(description, stringPos);
+		}
+		/*
+		 * in 1. 1 no longer permit maxState as anything other than 1 if (MesquiteInteger.isCombinable(m) && "maxState".equalsIgnoreCase(s)) { maxState = m; maxStateDefined = m; } else { maxState = CategoricalState.maxCategoricalState; maxStateDefined = CategoricalState.maxCategoricalState; }
+		 */
+		useEquilFreqAsPrior = !("flatPrior".equalsIgnoreCase(s));
+
+		if (MesquiteDouble.isCombinable(param0))
+			param0Unassigned = false;
+		if (MesquiteDouble.isCombinable(param1))
+			param1Unassigned = false;
+		prepareMatrices();
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, true);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN), CharacterModel.class, false);
+	}
+
+	/* --------------------------------------------- */
+	/** Return an explanation of the settings used in calculations (e.g., optimization settings). These are not the parameters of the model. */
+	public String getSettingsString() {
+		if (optimizationMode == BASE_ON_MK1)
+			return "(Opt.:  Mk1 base)";
+		else if (optimizationMode == FLIP_FLOP)
+			return "(Opt.:  Sym + 2 Asymm)";
+		else
+			return "(Opt.:  Mk1 + Sym + 2 Asymm)";
+	}
+
+	/* --------------------------------------------- */
+	private String paramToString(double param, boolean unassigned) {
+		if (unassigned) {
+			if (MesquiteDouble.isCombinable(param))
+				return MesquiteDouble.toString(param) + " [est.]";
+			else
+				return " ? ";
+		}
+		else
+			return MesquiteDouble.toString(param);
+	}
+
+	/* --------------------------------------------- */
+	public String toString() {
+		return "AsymmMk model (id " + getID() + ") " + getParameters();
+	}
+
+	/* --------------------------------------------- */
+	public String paramString() {
+		String priorString;
+		if (useEquilFreqAsPrior)
+			priorString = " equilibAsPrior";
+		else
+			priorString = " flatPrior";
+		if (useRateBiasNotation)
+			return "rate " + paramToString(param0, param0Unassigned) + " bias " + paramToString(param1, param1Unassigned) + priorString;
+		else
+			return "forward " + paramToString(param1, param1Unassigned) + " backward " + paramToString(param0, param0Unassigned) + priorString;
+	}
+
+	/* --------------------------------------------- */
+	public String getNexusSpecification() {
+		String s = " ";
+		if (!StringUtil.blank(getAnnotation()))
+			s += " [!" + getAnnotation() + "] ";
+		s += paramString();
+		/*
+		 * as of 1. 1 no longer pfermits maxState other than 1 if (maxStateDefined != CategoricalState.maxCategoricalState && maxStateDefined>=0) s += " maxState " + maxStateDefined;
+		 */
+		return s;
+	}
+
+	/* --------------------------------------------- */
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone) {
+		AsymmModel j = new AsymmModel(name, getStateClass());
+		j.recalcProbsNeeded = true;
+		j.needToPrepareMatrices = true;
+		completeDaughterClone(formerClone, j);
+		j.prepareMatrices();
+		return j;
+
+	}
+	MesquiteNumber[] forExport;
+	/* --------------------------------------------- */
+	public MesquiteNumber[] getParameterValues() {
+		if (forExport == null){
+			forExport = new MesquiteNumber[2];
+			forExport[0] = new MesquiteNumber();
+			forExport[1] = new MesquiteNumber();
+		}
+
+		if (useRateBiasNotation) {
+			forExport[0].setName("bias");
+			forExport[0].setValue(param1);
+			forExport[1].setName("rate");
+			forExport[1].setValue(param0);
+		}
+		else {
+			forExport[0].setName("forward");
+			forExport[0].setValue(param1);
+			forExport[1].setName("backward");
+			forExport[1].setValue(param0);
+		}
+		return forExport;
+	}
+	/* --------------------------------------------- */
+	public String getParameters() {
+		String priorString;
+		if (useEquilFreqAsPrior)
+			priorString = " root: equilibrium";
+		else
+			priorString = " root: flat prior";
+		if (useRateBiasNotation)
+			return "bias: " + param1 + " rate: " + param0 + priorString;
+		else
+			return "forward rate: " + param1 + " backward rate: " + param0 + priorString;
+	}
+
+	public String getModelTypeName() {
+		return "Asymm. 2-par. Markov";
+	}
+}
+
diff --git a/Source/mesquite/stochchar/lib/BrownianMotionModel.java b/Source/mesquite/stochchar/lib/BrownianMotionModel.java
new file mode 100644
index 0000000..35e7342
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/BrownianMotionModel.java
@@ -0,0 +1,120 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class BrownianMotionModel  extends ProbabilityContCharModel {
+	Random rng = new Random(System.currentTimeMillis());
+	double rate = 1.0;
+	long seedSet = 0;
+	public BrownianMotionModel (String name, Class dataClass) {
+		super(name, dataClass);
+	}
+ 	/*.................................................................................................................*/
+	/** Randomly generates according to model an end state on branch from beginning states*/
+	public double evolveState (double beginState, Tree tree, int node){
+		return beginState + rate* rng.nextGaussian()*Math.sqrt(tree.getBranchLength(node, 1.0));   //pre-1.05 this failed to take the sqrt!!!!
+	}
+ 	/*.................................................................................................................*/
+	/** Returns (possibly by randomly generating) according to model an ancestral state for root of tree*/
+	public double getRootState (Tree tree){
+		return 0;  //todo: stochastic?
+	}
+ 	/*.................................................................................................................*/
+	public void fromString (String description, MesquiteInteger stringPos, int format) {
+   		ParseUtil.getToken(description, stringPos); //eating token "rate"
+   		rate =  MesquiteDouble.fromString(description, stringPos);
+	}
+	
+ 	/*.................................................................................................................*/
+	public String getParameters() {
+		return "rate " + MesquiteDouble.toString(rate);
+	}
+ 	/*.................................................................................................................*/
+	public String getNexusSpecification () {
+		return "rate " + MesquiteDouble.toString(rate);
+	}
+ 	/*.................................................................................................................*/
+	public void setRate(double rate){
+		this.rate = rate;
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+ 	/*.................................................................................................................*/
+	public double getRate(){
+		return rate;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+ 	/*.................................................................................................................*/
+ 	/** Performs command (for Commandable interface) */
+   	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+    	 	if (checker.compare(this.getClass(), "Sets the instantaneous rate of change in the model", "[rate of change; must be > 0]", commandName, "setRate")) {
+    	 		pos.setValue(0);
+			double newRate = MesquiteDouble.fromString(arguments, pos);
+			double a = getRate();
+			if (!MesquiteDouble.isCombinable(newRate)) {
+				newRate= MesquiteDouble.queryDouble(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Set Rate", "Rate of change:", a);
+    	 		}
+    	 		if (newRate>=0  && newRate!=a && MesquiteDouble.isCombinable(newRate)) {
+    	 			setRate(newRate);
+    	 		}
+		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+ 	}
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		BrownianMotionModel bmm = new BrownianMotionModel(name, getStateClass());
+		completeDaughterClone(formerClone, bmm);
+		return bmm;
+	}
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof BrownianMotionModel))
+			return;
+		BrownianMotionModel model = (BrownianMotionModel)md;
+		model.setRate(rate);
+		super.copyToClone(md);
+	}
+	public boolean isFullySpecified(){
+		return rate != MesquiteDouble.unassigned;
+	}
+	public void setSeed(long seed){
+		seedSet = seed;
+		rng.setSeed(seed);
+	}
+	
+	public long getSeed(){
+		return rng.nextLong();
+	}
+	
+	/** return an explanation of the model. */
+	public String getExplanation (){
+		return "A stochastic model in which expected change is distributed normally with mean 0 and variance proportional to branch length times the rate.  The current rate is " + MesquiteDouble.toString(rate);
+	}
+	public String getNEXUSClassName(){
+		return "Brownian";
+	}
+	public String getModelTypeName(){
+		return "Brownian motion model";
+	}
+}
+
diff --git a/Source/mesquite/stochchar/lib/CategProbModelCurator.java b/Source/mesquite/stochchar/lib/CategProbModelCurator.java
new file mode 100644
index 0000000..061fc92
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/CategProbModelCurator.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules curates a subclass of character models for use in calculation routines.*/
+
+public abstract class CategProbModelCurator extends WholeCharModelCurator  {
+	protected CategoricalData data = null;
+
+   	 public Class getDutyClass() {
+   	 	return CategProbModelCurator.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Categorical Probability Model Curator";
+   	 }
+
+}
+
+
diff --git a/Source/mesquite/stochchar/lib/CharacterLikelihood.java b/Source/mesquite/stochchar/lib/CharacterLikelihood.java
new file mode 100644
index 0000000..a445a09
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/CharacterLikelihood.java
@@ -0,0 +1,34 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**Calculates the likelihood of a tree and character.*/
+
+public abstract class CharacterLikelihood extends NumberForCharAndTree  {
+   	 public Class getDutyClass() {
+   	 	return CharacterLikelihood.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Character Likelihood";
+   	 }
+}
+
+
diff --git a/Source/mesquite/stochchar/lib/JointLikeAncStForModel.java b/Source/mesquite/stochchar/lib/JointLikeAncStForModel.java
new file mode 100644
index 0000000..bd1ed3c
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/JointLikeAncStForModel.java
@@ -0,0 +1,47 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Reconstructs the ancestral states for a character using stochastic model (joint reconstruction), for a specific character model.
+Also returns posterior probability.
+
+CURRENTLY NOT extended by any active modules*/
+
+public abstract class JointLikeAncStForModel extends MesquiteModule  {
+	public int oldNumTaxa = 0;
+
+   	 public Class getDutyClass() {
+   	 	return JointLikeAncStForModel.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Joint likelihood ancestral state reconsturction";
+   	 }
+
+	public abstract void calculateStates(Tree tree, CharacterDistribution charStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber prob);
+	
+	public  abstract void calculateLogProbability(Tree tree, CharacterDistribution charStates, CharacterModel model, MesquiteString resultString, MesquiteNumber prob) ;
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return false;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/stochchar/lib/MargLikeAncStCLForModel.java b/Source/mesquite/stochchar/lib/MargLikeAncStCLForModel.java
new file mode 100644
index 0000000..27e7512
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/MargLikeAncStCLForModel.java
@@ -0,0 +1,43 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Reconstructs the ancestral states for a character using likelihood, for a specific character model.
+Also calculates likelihood by virtue of extending MargLikelihoodForModel.  Can be set to report only clade local values*/
+
+public abstract class MargLikeAncStCLForModel extends MargLikeAncStForModel  {
+
+   	 public Class getDutyClass() {
+   	 	return MargLikeAncStCLForModel.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Maximum Likelihood ancestral states (marginal reconstruction) with clade-local ability";
+   	 }
+
+	public abstract void setReportCladeLocalValues(boolean reportCladeValues);
+	public abstract boolean getReportCladeLocalValues();
+	//public abstract void setRootMode(int rootMode);
+	//public abstract int getRootMode();
+	
+
+}
+
+
+
diff --git a/Source/mesquite/stochchar/lib/MargLikeAncStForModel.java b/Source/mesquite/stochchar/lib/MargLikeAncStForModel.java
new file mode 100644
index 0000000..67a61c5
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/MargLikeAncStForModel.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Reconstructs the ancestral states for a character using likelihood, for a specific character model.
+Also calculates likelihood by virtue of extending MargLikelihoodForModel.*/
+
+public abstract class MargLikeAncStForModel extends MargLikelihoodForModel  {
+
+   	 public Class getDutyClass() {
+   	 	return MargLikeAncStForModel.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Maximum Likelihood ancestral states (marginal reconstruction)";
+   	 }
+
+	public abstract void calculateStates(Tree tree, CharacterDistribution charStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber prob);
+	
+
+}
+
+
+
diff --git a/Source/mesquite/stochchar/lib/MargLikelihoodForModel.java b/Source/mesquite/stochchar/lib/MargLikelihoodForModel.java
new file mode 100644
index 0000000..9299bfc
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/MargLikelihoodForModel.java
@@ -0,0 +1,46 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+/**Assesses likelihood for a character using likelihood, for a specific character model.*/
+
+public abstract class MargLikelihoodForModel extends MesquiteModule  {
+
+   	 public Class getDutyClass() {
+   	 	return MargLikelihoodForModel.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Maximum Likelihood using Character Model";
+   	 }
+
+	public  abstract void calculateLogProbability(Tree tree, CharacterDistribution charStates, CharacterModel model, MesquiteString resultString,  MesquiteNumber prob);
+	
+	//not yet working: public  abstract Object getLikelihoodSurface(Tree tree, CharacterDistribution charStates, CharacterModel model, double[] inputBounds, double[] outputBounds);
+
+	public  abstract void estimateParameters(Tree tree, CharacterDistribution charStates, CharacterModel model, MesquiteString resultString);
+
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		return false;
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/stochchar/lib/MkModel.java b/Source/mesquite/stochchar/lib/MkModel.java
new file mode 100644
index 0000000..97ad07d
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/MkModel.java
@@ -0,0 +1,316 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+public class MkModel extends ProbPhenCategCharModel implements CModelEstimator, Evaluator {
+	double rate = MesquiteDouble.unassigned;  
+	boolean hasDefaultValues=true;
+	boolean unassigned = true;
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public MkModel (String name, Class dataClass){
+		super(name, dataClass);
+		maxStateDefined = CategoricalState.maxCategoricalState;
+		maxState = CategoricalState.maxCategoricalState;
+	}
+
+	public CharacterModel cloneModelWithMotherLink(CharacterModel formerClone){
+		MkModel j = new MkModel(name, getStateClass());
+		completeDaughterClone(formerClone, j);
+		return j;
+
+	}
+
+	public void deassignParameters(){
+		rate = MesquiteDouble.unassigned;
+		unassigned = true;
+	}
+	public double evaluate(MesquiteDouble param, Object param2){
+		if (param2 instanceof TreeDataModelBundle) {
+			TreeDataModelBundle b = (TreeDataModelBundle)param2;
+			rate = param.getValue();
+			double result =  - b.getLikelihoodCalculator().logLikelihoodCalc(b.getTree(), this, b.getCharacterDistribution());
+			return result;
+		}
+		else
+			return 0;
+	}
+
+	public double evaluate(double[] x, Object param){
+		if (x == null || x.length != 1)
+			return 0;
+		if (param instanceof TreeDataModelBundle) {
+			TreeDataModelBundle b = (TreeDataModelBundle)param;
+			rate = x[0];
+			double result =  - b.getLikelihoodCalculator().logLikelihoodCalc(b.getTree(), this, b.getCharacterDistribution());
+			return result;
+		}
+		else
+			return 0;
+	}
+	/*.................................................................................................................*/
+	MesquiteTimer timer = new MesquiteTimer();
+	MesquiteInteger steps = new MesquiteInteger();
+	public static double optWidth = 0.0;
+	public void estimateParameters(Tree tree, CharacterDistribution observedStates, CLikelihoodCalculator lc){
+		boolean constant = (observedStates.isConstant(tree, tree.getRoot()));
+
+		if (constant || !(observedStates instanceof CategoricalDistribution)){
+			rate = 0;
+		}
+		else {
+
+			timer.start();
+			Optimizer opt = new Optimizer(this);
+			TreeDataModelBundle bundle = new TreeDataModelBundle(tree, this, observedStates, null, lc);
+			MesquiteDouble r = new MesquiteDouble(0.1);
+
+			if (optWidth > 0.0000001)
+				progressiveOptimize(tree, bundle, opt, r, 0, optWidth);
+			else {
+				r.setValue(0.1);
+				double best = progressiveOptimize(tree, bundle, opt, r, 0, 1);
+				double b1Rate = r.getValue();
+
+				r.setValue(0.1);
+				double b10 = progressiveOptimize(tree, bundle, opt, r, 0, 10);
+
+				if (best < b10)
+					r.setValue(b1Rate);
+
+				/*
+	 			r.setValue(0.1);
+				double best = progressiveOptimize(tree, bundle, opt, r, 0, 1);
+	 			double b1Rate = r.getValue();
+
+	 			r.setValue(0.1);
+				double b10 = progressiveOptimize(tree, bundle, opt, r, 0, 10);
+
+				if (best > b10)
+					best = b10;
+
+	 			r.setValue(10);
+				double b1010 = progressiveOptimize(tree, bundle, opt, r, 0, 10);
+				if (best > b1010)
+					best = b1010;
+				r.setValue(best);
+				 */
+			}
+
+			rate = r.getValue();
+			timer.end();
+		}
+	}
+
+
+	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null || !(md instanceof MkModel))
+			return;
+		super.copyToClone(md);
+		MkModel model = (MkModel)md;
+		if (unassigned) {
+			model.rate = MesquiteDouble.unassigned;
+			model.unassigned = true;
+		}
+		else
+			model.setInstantaneousRate(rate);
+	}
+
+	/** Returns whether parameters of model are fully specified.  If so, it can be used for evolving states.*/
+	public boolean isFullySpecified(){
+		return !unassigned && rate != MesquiteDouble.unassigned;
+	}
+	/*.................................................................................................................*/
+	/** Performs command (for Commandable interface) */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker){
+		if (checker.compare(this.getClass(), "Sets the instantaneous rate of change in the model", "[rate of change; must be > 0]", commandName, "setRate")) {
+			if (isBuiltIn())
+				return null;
+			pos.setValue(0);
+			String token = ParseUtil.getToken(arguments, pos);
+			if (MesquiteString.explicitlyUnassigned(token)) {
+				setInstantaneousRate(MesquiteDouble.unassigned);
+				return null;
+			}
+			pos.setValue(0);
+			double newRate = MesquiteDouble.fromString(arguments, pos);
+			double a = getInstantaneousRate();
+			if (!MesquiteDouble.isCombinable(newRate)) {
+				newRate= MesquiteDouble.queryDouble(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Set Rate", "Rate of change:", a);
+			}
+			if (newRate>=0  && newRate!=a && MesquiteDouble.isCombinable(newRate)) {
+				setInstantaneousRate(newRate);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the maximum allowed state for this model", "[0...maxCategoricalState]", commandName, "setMaxState")) {
+			if (isBuiltIn())
+				return null;
+			int m = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(m))
+				m = MesquiteInteger.queryInteger(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "Set maximum allowed state", "Maximum allowed state for this model:", maxStateDefined);
+			if (m>0 && m<=CategoricalState.maxCategoricalState  && m!=maxStateDefined) {
+				maxState = m;
+				maxStateDefined = m;
+				notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+			}
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/** returns name of model class (e.g. "stepmatrix")  SHOULD MATCH NAME returned by getNEXUSNameOfModelClass of module*/
+	public String getNEXUSClassName() {
+		return "Mk1";
+	}
+	public void fromString (String description, MesquiteInteger stringPos, int format) { 
+		hasDefaultValues = false;
+		ParseUtil.getToken(description, stringPos);
+		rate =  MesquiteDouble.fromString(description, stringPos);
+		unassigned = !MesquiteDouble.isCombinable(rate);
+		String s = ParseUtil.getToken(description, stringPos);
+		int m =  MesquiteInteger.fromString(description, stringPos);
+		if (MesquiteInteger.isCombinable(m) && "maxState".equalsIgnoreCase(s)) {
+			maxState = m;
+			maxStateDefined = m;
+		}
+		else {
+			maxState = CategoricalState.maxCategoricalState;
+			maxStateDefined = CategoricalState.maxCategoricalState;
+		}
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, true);
+		notifyListeners(this, new Notification(MesquiteListener.UNKNOWN),CharacterModel.class, false);
+	}
+
+	public String getParameters () {
+		String result ="rate " + MesquiteDouble.toString(rate);
+		if (unassigned)
+			result += " [est.]";
+		return result;
+	}
+	public String toString () {
+		return "Mk1 model (" + getID() + ") " + getParameters();
+	}
+	MesquiteNumber[] forExport;
+	/* --------------------------------------------- */
+	public MesquiteNumber[] getParameterValues() {
+		if (forExport == null){
+			forExport = new MesquiteNumber[1];
+			forExport[0] = new MesquiteNumber();
+		}
+
+		forExport[0].setName("rate");
+		forExport[0].setValue(rate);
+		return forExport;
+	}
+	public String getExplanation () {
+		return "One-parameter Markov k-state model (Lewis, 2001); a generalization of the Jukes-Cantor model.";
+	}
+	public String getNexusSpecification() {
+		String s= " ";
+		if (!StringUtil.blank(getAnnotation()))
+			s +=" [!" + getAnnotation() + "] ";
+		if (unassigned)
+			s += "rate ? ";
+		else
+			s += "rate " + MesquiteDouble.toString(rate);
+		if (maxStateDefined != CategoricalState.maxCategoricalState && maxStateDefined>=0)
+			s += " maxState " + maxStateDefined;
+		return s;
+	}
+	/** Return an explanation of the settings used in calculations (e.g., optimization settings).  These are not the parameters of the model. */
+	public String getSettingsString(){
+		return "(Opt.:  width " + MesquiteDouble.toString(optWidth) + ")";
+	}
+	/* ---------------------------------------------*/
+	public double instantaneousRate (int beginState, int endState, Tree tree, int node){
+		if (beginState <0 || beginState> maxState || endState < 0 || endState> maxState) {
+			return 0;
+		}
+		else {
+			if (beginState == endState)
+				return -(maxState)*rate; //so row of rate matrix adds to 0
+			return rate;
+		}
+	}
+	/* ---------------------------------------------*/
+	public double getInstantaneousRate() {
+		return rate;
+	}
+	public void setInstantaneousRate(double r) {
+		setInstantaneousRate(r, true);
+	}
+	public void setInstantaneousRate(double r, boolean notify) {
+		hasDefaultValues = false;
+		rate = r;
+		unassigned = !MesquiteDouble.isCombinable(r);
+		if (notify)
+			notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+	}
+	private double instantaneousToProb(double instantaneous, double branchLength, int numStates) {
+		if (MesquiteDouble.isUnassigned(instantaneous)) {
+			MesquiteMessage.warnProgrammer("Instantaneous rate is unassigned in model " + getName());
+			return 0;
+		}
+		return 1.0/(numStates)*(1.0- Math.exp(-instantaneous*numStates*branchLength));
+
+		/* in 0.994 and before the following was used:
+		return 1.0/(numStates)*(1.0- Math.exp(-instantaneous*numStates/(numStates-1)*branchLength));
+		This assumes "instantaneous" is the overall rate of change, regardless of to what state the chance occurs,
+		as opposed to rate of each particular change (the latter in the style of the q's of Schluter et al & Pagel)
+		 */
+	}
+
+	public int evolveState (int beginState, Tree tree, int node) {
+		double r = randomNumGen.nextDouble();
+		double probChangeEach =instantaneousToProb(rate, tree.getBranchLength(node, 1.0), (maxState +1));
+		double probStasis =1.0 -(probChangeEach * (maxState));
+		double accumProb = 0;
+		for (int i=0; i<=maxState; i++) {
+			if (i== beginState)
+				accumProb +=  probStasis;
+			else
+				accumProb +=  probChangeEach;
+			if (r< accumProb)
+				return i;
+		}
+		return maxState;
+	}
+	public double transitionProbability (int beginState, int endState, Tree tree, int node){
+		if (!inStates(beginState) || !inStates(endState)) {
+			return 0;
+		}
+		else if (beginState == endState) {
+			if (maxState == -1)
+				return 1.0;
+			else
+				return (1.0 -(instantaneousToProb(rate, tree.getBranchLength(node, 1.0), (maxState+1)) * (maxState)));
+		}
+		else {
+			return (instantaneousToProb(rate, tree.getBranchLength(node, 1.0), (maxState+1)));
+		}
+	}
+
+	public String getModelTypeName(){
+		return "Markov k-state 1 param.";
+	}
+}
+
diff --git a/Source/mesquite/stochchar/lib/PagNodeRecord.java b/Source/mesquite/stochchar/lib/PagNodeRecord.java
new file mode 100644
index 0000000..42d20d8
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/PagNodeRecord.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+public class PagNodeRecord {
+	public String node, ancestor;
+	public int[] states;
+	public double length;
+	public int taxonNumber = -1;
+	
+	public PagNodeRecord(int taxonNumber, String node, String ancestor, double length, int[] states){
+		this.taxonNumber = taxonNumber;
+		this.node = node;
+		this.ancestor = ancestor;
+		this.length = length;
+		this.states = states;
+	}
+	public String toString(){
+		return "node " + node + " ancestor " + ancestor;
+	}
+}
diff --git a/Source/mesquite/stochchar/lib/PagelFormatI.java b/Source/mesquite/stochchar/lib/PagelFormatI.java
new file mode 100644
index 0000000..85efdaf
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/PagelFormatI.java
@@ -0,0 +1,288 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ============  a file interpreter for Pagel's format files; extended to handle files for programs Discrete and Multistate ============*/
+
+public abstract class PagelFormatI extends FileInterpreterI {
+/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;  
+  	 }
+  	 
+/*.................................................................................................................*/
+	public String preferredDataFileExtension() {
+ 		return "ppy";
+   	 }
+/*.................................................................................................................*/
+	public boolean isPrerelease() {  
+		 return false; 
+	}
+	/*.................................................................................................................*/
+	public boolean canExportEver() {  
+		 return true;
+	}
+/*.................................................................................................................*/
+	public boolean canExportData(Class dataClass) {  
+		return (dataClass==CategoricalState.class);
+	}
+/*.................................................................................................................*/
+	public boolean canExportProject(MesquiteProject project) {  
+		return project.getNumberCharMatrices(CategoricalState.class) > 0; 
+	}
+/*.................................................................................................................*/
+	public boolean canImport() {  
+		 return true;
+	}
+	public abstract boolean readTreeAndCharacters(MesquiteFile file, String line, Vector nodes, MesquiteInteger nC);
+/*.................................................................................................................*/
+	public void readFile(MesquiteProject mf, MesquiteFile file, String arguments) {
+		incrementMenuResetSuppression();
+		ProgressIndicator progIndicator = new ProgressIndicator(mf,"Importing File "+ file.getName(), file.existingLength());
+		progIndicator.start();
+		file.linkProgressIndicator(progIndicator);
+		if (file.openReading()) {
+			boolean abort = false;
+			TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+			 CharactersManager charTask = (CharactersManager)findElementManager(CharacterData.class);
+			
+			Taxa taxa = taxaTask.makeNewTaxa(getProject().getTaxas().getUniqueName("Taxa from Pagel format file"), 0, false);
+			taxa.addToFile(file, getProject(), taxaTask);
+			CategoricalData data = (CategoricalData)charTask.newCharacterData(taxa, 0, CategoricalData.DATATYPENAME);
+			data.addToFile(file, getProject(), null);
+			boolean wassave = data.saveChangeHistory;
+			data.saveChangeHistory = false;
+
+			TreeVector trees = new TreeVector(taxa);
+			trees.setName("Trees imported from Pagel file");
+			int numChars = 1;
+			StringBuffer sb = new StringBuffer(1000);
+			file.readLine(sb);
+			String line = sb.toString();
+			Vector nodes = new Vector();
+			MesquiteInteger nC = new MesquiteInteger(1);
+			MesquiteInteger nT = new MesquiteInteger(1);
+			
+			abort = !readTreeAndCharacters(file, line, nodes, nC);
+			
+			numChars = nC.getValue();
+			
+			//Now parse the nodes to count taxa
+			int numTaxa = 0;
+			String root = null;
+			data.addCharacters(data.getNumChars()-1, numChars, false);   // add at least one character
+			for (int i=0; i< nodes.size(); i++){
+				PagNodeRecord pnr = (PagNodeRecord)nodes.elementAt(i);
+				if (!nodeIsAncestor(nodes, pnr.node)) {
+					taxa.addTaxa(numTaxa-1, 1, true);
+					Taxon t = taxa.getTaxon(numTaxa);
+					if (t!=null) {
+						t.setName(pnr.node);
+						for (int ic=0; ic<numChars; ic++){
+							if (pnr.states != null && ic < pnr.states.length && MesquiteInteger.isCombinable(pnr.states[ic]))
+								data.setState(ic, numTaxa, CategoricalState.makeSet(pnr.states[ic]));
+						}
+					}
+					numTaxa++;
+				}
+				if (getNodeWithName(nodes, pnr.ancestor)==null){ //ancestor doesn't have node; ancestor must be root
+					root = pnr.ancestor;
+				}
+					
+			}
+			PagNodeRecord pnrRoot = null;
+			if (root!=null){
+				pnrRoot = new PagNodeRecord(-1, root, null, 1, null);
+				nodes.addElement(pnrRoot);
+			}
+			if (nodes.size() == 0) {
+				discreetAlert( "Reading of the Pagel format file failed because tree could not be read");
+				finishImport(progIndicator, file, true); //change this to true
+				decrementMenuResetSuppression();
+				return;
+			}
+			
+			MesquiteTree tree = new MesquiteTree(taxa);
+			buildTree(tree, tree.getRoot(), pnrRoot, nodes);
+			
+			tree.setAsDefined(true);
+			tree.setName("Imported tree");
+			trees.addElement(tree, false);
+			trees.addToFile(file,file.getProject(), findElementManager(TreeVector.class));
+			data.saveChangeHistory = wassave;
+			data.resetChangedSinceSave();
+
+			finishImport(progIndicator, file, abort);
+	 		MesquiteModule treeWindowCoord = getFileCoordinator().findEmployeeWithName("#BasicTreeWindowCoord");
+			if (treeWindowCoord!=null){
+				String commands = "makeTreeWindow " + getProject().getTaxaReferenceExternal(taxa) + "  #BasicTreeWindowMaker; tell It; ";
+				commands += "setTreeSource  #StoredTrees; tell It; setTaxa " + getProject().getTaxaReferenceExternal(taxa) + " ;  setTreeBlock 1; endTell; ";
+				commands += "getTreeDrawCoordinator #BasicTreeDrawCoordinator; tell It; suppress; setTreeDrawer #BallsNSticks; ";
+				commands += "tell It;  getEmployee #NodeLocsStandard; tell It; branchLengthsToggle on; ";
+				commands += " endTell; endTell; desuppress; endTell; getTreeWindow; tell It; setLocation 200 60; ";
+				commands += "newAssistant  #TraceCharacterHistory; tell It; suspend; setHistorySource  #RecAncestralStates;";
+				commands += "tell It; getCharacterSource  #CharSrcCoordObed; tell It; setCharacterSource #StoredCharacters; endTell;";
+				commands += "setMethod  #MargProbAncStates; tell It; setModelSource  #StoredProbModel; tell It; setModel 0 'Mk1 (est.)'; endTell;";
+				commands += "endTell; endTell; resume; endTell; endTell; ";
+				commands += "  showWindow; endTell; ";
+				MesquiteInteger pos = new MesquiteInteger(0);
+				Puppeteer p = new Puppeteer(this);
+				p.execute(treeWindowCoord, commands, pos, null, false);
+			}
+		}
+		decrementMenuResetSuppression();
+	}
+	
+	protected void buildTree(MesquiteTree tree, int node, PagNodeRecord pagNode, Vector nodes){ //if terminal then
+		if (nodes == null || pagNode == null || pagNode.node == null)
+			return;
+		boolean daughtersBuilt = false;
+		for (int i=0; i<nodes.size(); i++) {
+			PagNodeRecord pnr = (PagNodeRecord)nodes.elementAt(i);
+			if (pagNode.node.equals(pnr.ancestor)) {//this is a daughter node!
+				int daughter = tree.sproutDaughter(node, false);
+				buildTree(tree, daughter, pnr, nodes);
+				daughtersBuilt = true;
+			}
+		}
+		if (!daughtersBuilt){
+			tree.setTaxonNumber(node, pagNode.taxonNumber, false);
+		}
+		tree.setBranchLength(node, pagNode.length, false);
+	}
+	protected PagNodeRecord getNodeWithName(Vector nodes, String node){
+		if (node == null)
+			return null;
+		for (int i=0; i<nodes.size(); i++) {
+			PagNodeRecord pnr = (PagNodeRecord)nodes.elementAt(i);
+			if (node.equals(pnr.node))
+				return pnr;
+		}
+		return null;
+	}
+	protected boolean nodeIsAncestor(Vector nodes, String node){
+		if (node == null)
+			return false;
+		for (int i=0; i<nodes.size(); i++) {
+			PagNodeRecord pnr = (PagNodeRecord)nodes.elementAt(i);
+			if (node.equals(pnr.ancestor))
+				return true;
+		}
+		return false;
+	}
+	protected boolean nodeHasAncestor(Vector nodes, String node){
+		PagNodeRecord pnr = getNodeWithName(nodes, node);
+		if (pnr == null)
+			return false;
+		return (getNodeWithName(nodes, pnr.ancestor)!=null);
+	}
+
+/* ============================  exporting ============================*/
+	boolean includeGaps = false;
+	/*.................................................................................................................*/
+	
+	public boolean getExportOptions(boolean dataSelected, boolean taxaSelected){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExporterDialog exportDialog = new ExporterDialog(this,containerOfModule(), "Export Pag-format Options", buttonPressed);
+		
+		exportDialog.completeAndShowDialog(dataSelected, taxaSelected);
+			
+		boolean ok = (exportDialog.query(dataSelected, taxaSelected)==0);
+		
+		exportDialog.dispose();
+		return ok;
+	}	
+
+	/*-----------------------------------------*/
+	/** Outputs internal nodes.*/
+	protected void numberNodes(Tree tree, int node, int[] numbers, MesquiteInteger nodeCount) {
+		if (tree.nodeIsTerminal(node))
+			numbers[node] = tree.taxonNumberOfNode(node);
+	else  {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				 numberNodes(tree, d, numbers, nodeCount);
+			numbers[node] = nodeCount.getValue();
+			nodeCount.increment();
+		}
+	}
+	/** Outputs internal nodes.*/
+	protected void outputInternals(Tree tree, int node, int[] numbers, StringBuffer buffer, StringBuffer equivalenceBuffer) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			 outputInternals(tree, d, numbers, buffer, equivalenceBuffer);
+		if (tree.nodeIsInternal(node)) {
+			if (node != tree.getRoot()){
+				buffer.append(Integer.toString(numbers[node]));
+				buffer.append(',');
+				buffer.append(Integer.toString(numbers[tree.motherOfNode(node)]));
+				buffer.append(',');
+				buffer.append(MesquiteDouble.toStringNoNegExponential(tree.getBranchLength(node, 1.0)));
+				buffer.append("\r\n");
+			}
+			equivalenceBuffer.append("# node " + numbers[node] + " = Mesquite node " + node + "\r\n");
+		}
+		
+	}
+	/*-----------------------------------------*/
+	/** Returns a polytomous node.*/
+	protected void unassignedToOne(AdjustableTree tree, int node) {
+		if (!MesquiteDouble.isCombinable(tree.getBranchLength(node)))
+			tree.setBranchLength(node, 1.0, false);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			 unassignedToOne(tree, d);
+	}
+	/*-----------------------------------------*/
+	/** Returns a polytomous node.*/
+	protected int findPolytomy(AdjustableTree tree, int node) {
+		if (tree.nodeIsTerminal(node))
+			return -1;
+		if (tree.nodeIsPolytomous(node))
+			return node;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (tree.hasPolytomies(d))
+					return findPolytomy(tree, d);
+		return -1;
+	}
+
+	/*-----------------------------------------*/
+	/** converts polytomies to zero length branches, and unassigned lengths to 1*/
+	protected boolean sanitizeTree(Tree ptree){
+		if (ptree.hasPolytomies(ptree.getRoot()) && !(ptree instanceof AdjustableTree))
+			return false;
+		AdjustableTree tree = (AdjustableTree)ptree;
+		while (tree.hasPolytomies(tree.getRoot())){
+			int p = findPolytomy(tree, tree.getRoot());
+			int d = tree.firstDaughterOfNode(p);
+			double origDL = tree.getBranchLength(d);
+			int ns = tree.nextSisterOfNode(d);
+			double origNSL = tree.getBranchLength(ns);
+			tree.moveBranch(d, ns, false);
+			tree.setBranchLength(d, origDL, false);
+			tree.setBranchLength(ns, origNSL, false);
+			tree.setBranchLength(tree.firstDaughterOfNode(p), 0, false);
+		}
+		tree.setBranchLength(tree.getRoot(), 0, false); //setting branch length to zero of root
+		unassignedToOne(tree, tree.getRoot());
+		return true;
+	}
+   	 
+}
+
diff --git a/Source/mesquite/stochchar/lib/ProbModelSource.java b/Source/mesquite/stochchar/lib/ProbModelSource.java
new file mode 100644
index 0000000..9e05bf6
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbModelSource.java
@@ -0,0 +1,40 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+This class of modules supplies character models for use in calculation routines.
+These methods must be passed a Data or a CharacterDistribution object because which models are appropriate will depend on these*/
+
+public abstract class ProbModelSource extends CharacterModelSource  {
+
+   	 public Class getDutyClass() {
+   	 	return ProbModelSource.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Probability Model Source";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CurrentProbModels"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/stochchar/lib/ProbModelSourceLike.java b/Source/mesquite/stochchar/lib/ProbModelSourceLike.java
new file mode 100644
index 0000000..d33198f
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbModelSourceLike.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+Subclass of ProbModelSource to indicate used for likelihood*/
+
+public abstract class ProbModelSourceLike extends ProbModelSource  {
+
+   	 public Class getDutyClass() {
+   	 	return ProbModelSourceLike.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Probability Model Source (For likelihood)";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#CurrentProbModels", "#StoredProbModel"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/stochchar/lib/ProbModelSourceSim.java b/Source/mesquite/stochchar/lib/ProbModelSourceSim.java
new file mode 100644
index 0000000..6217eb1
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbModelSourceSim.java
@@ -0,0 +1,38 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+/**
+Subclass of ProbModelSource to indicate used for simulations*/
+
+public abstract class ProbModelSourceSim extends ProbModelSource  {
+
+   	 public Class getDutyClass() {
+   	 	return ProbModelSourceSim.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Probability Model Source (For simulations)";
+   	 }
+   	 public String[] getDefaultModule() {
+   	 	return new String[] {"#StoredProbModelSim"};
+   	 }
+}
+
+
diff --git a/Source/mesquite/stochchar/lib/ProbPhenCategCharModel.java b/Source/mesquite/stochchar/lib/ProbPhenCategCharModel.java
new file mode 100644
index 0000000..5c70f4b
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbPhenCategCharModel.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+/** A character model for Categorical characters OTHER THAN MOLECULAR to be used in stochastic simulations and in likelihood calculations.
+It must serve both for calculating probabilities (via the transitionProbability method) and for simulating character evolution
+(via the evolveState method).*/
+public abstract class ProbPhenCategCharModel  extends ProbabilityCategCharModel {
+	public ProbPhenCategCharModel (String name, Class dataClass) {
+		super(name, dataClass);
+	}
+	//this should be pushed deeper into the superclasses
+	public String[] parameterNames(){
+		return null;
+	}
+ 
+    // This is supported by both current subclasses and is needed for stochastic character mapping
+    // PEM 6-Jan-2006 
+    /** Returns instanteous rate from beginning to ending state in given tree on the given node */
+   public abstract double instantaneousRate(int beginState, int endState, Tree tree, int node);
+	
+	/* NOT READY YET; depends on instantaneousRate
+	public String showMatrix(){
+		String s = "";
+		for (int iFrom = 0; iFrom<=maxState; iFrom++){
+			s += "[";
+			for (int iTo = 0; iTo<=maxState; iTo++){
+				if (iTo == iFrom)
+					s += " -";
+				else
+					s += " " + MesquiteDouble.toString(instantaneousRate(iFrom, iTo, null, 0));
+			}
+			s += " ]\n";
+		}
+		return s;
+	}
+	*/
+	public String[] estimatedParameterNames(){
+		return null;
+	}
+	public abstract void deassignParameters();
+}
+
diff --git a/Source/mesquite/stochchar/lib/ProbabilityCategCharModel.java b/Source/mesquite/stochchar/lib/ProbabilityCategCharModel.java
new file mode 100644
index 0000000..ea8e289
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbabilityCategCharModel.java
@@ -0,0 +1,218 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/* ======================================================================== */
+/** A character model for Categorical characters to be used in stochastic simulations and in likelihood calculations.
+It must serve both for calculating probabilities (via the transitionProbability method) and for simulating character evolution
+(via the evolveState method).*/
+public abstract class ProbabilityCategCharModel  extends ProbabilityModel {
+	protected long allStates = 0L;
+	protected int maxState = -1;  //maximum state to be used
+	protected int maxStateDefined = -1; //maximum state for which this model is defined
+	//protected int numStates = 0;
+	protected Random randomNumGen;
+	
+	public ProbabilityCategCharModel (String name, Class dataClass) {
+		super(name, dataClass);
+ 		randomNumGen = new Random();
+	}
+	/** Returns natural log of the transition probability from beginning to ending state in the given tree on the given node*/
+	public double transitionLnProbability (int beginState, int endState, Tree tree, int node){
+		return Math.log(transitionProbability(beginState, endState, tree, node));
+	}
+    /** Returns instanteous rate from beginning to ending state in given tree on the given node */
+	// Broken until issues with this method in ProbabilityDNAModel are resolved PEM 6-Jan-2006
+    // public abstract double instantaneousRate(int beginState, int endState, Tree tree, int node);
+	/** Returns transition probability from beginning to ending state in the given tree on the given node*/
+	public abstract double transitionProbability (int beginState, int endState, Tree tree, int node);
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	public void evolveState (CharacterState beginState, CharacterState endState, Tree tree, int node){
+		if (endState==null) {
+			return;
+		}
+		if (beginState==null || !(beginState instanceof CategoricalState) || !(endState instanceof CategoricalState)){
+			endState.setToUnassigned();
+			return;
+		}
+		CategoricalState bState = (CategoricalState)beginState;
+		CategoricalState eState = (CategoricalState)endState;
+		int r = evolveState(CategoricalState.minimum(bState.getValue()), tree, node); //todo: issue error if beginning is polymorphic?  choose randomly among beginning?
+		eState.setValue(CategoricalState.makeSet(r));
+	}
+	/** Randomly generates a character state according to model, on branch on tree, from beginning state*/
+	public abstract int evolveState (int beginState, Tree tree, int node);
+	
+	/** Returns instantaneous rate of change from beginState to endState along branch in tree
+	NOT READY YET
+	public abstract double instantaneousRate (int beginState, int endState, Tree tree, int node);
+	*/
+	
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public CharacterState getRootState (CharacterState state, Tree tree){
+		if (state==null || !(state instanceof CategoricalState))
+			state = new CategoricalState();
+		((CategoricalState)state).setValue(getRootState(tree));
+		return state;
+	}
+	/** Reports current parameters*/
+	public abstract String getParameters ();
+	/** Reports current parameters*/
+	public abstract MesquiteNumber[] getParameterValues ();
+
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public long getRootState (Tree tree){
+		if (maxState <= 0) 
+			return (1L);  //if only state 0 allowed, return it
+		else {
+			double r = randomNumGen.nextDouble();
+			double probEach =1.0/(maxState+1);
+			double accumProb = 0;
+			for (int i=0; i<maxState; i++) {
+				accumProb +=  priorProbability(i);
+				if (r< accumProb)
+					return CategoricalState.makeSet(i);
+			}
+			return CategoricalState.makeSet(maxState);
+		}
+	}
+	public boolean priorAlwaysFlat(){
+		return true;
+	}
+	public double priorProbability (int state){
+		if (!inStates(state)) 
+			return 0;
+		if (maxState == 0)
+			return (0.5);  // flat prior
+		else
+			return (1.0/(maxState+1));  // flat prior
+		
+	}
+	
+	/* ---------------------------------------------*/
+	public boolean inStates(int state) { //todo: these should be part of standard categ models
+		if (state>maxState || state<0)
+			return false;
+		else
+			return (CategoricalState.isElement(allStates, state));
+	}
+	/* ---------------------------------------------*/
+	public void setMaxStateDefined(int m) {  
+			maxState = m;
+			maxStateDefined = m;
+			allStates = CategoricalState.span(0,maxState);
+	}
+	/* ---------------------------------------------*/
+	public void setMaxStateSimulatable(int m) {  
+			maxState = m;
+			if (m>maxStateDefined)
+				maxState = maxStateDefined;
+			allStates = CategoricalState.span(0,maxState);
+	}
+	/* ---------------------------------------------*/
+	public void setCharacterDistribution(CharacterStatesHolder cStates) { 
+		super.setCharacterDistribution(cStates);
+	//This expansion costs a lot of time.  Perhaps use allStates based calculations instead of states[] based calculations?
+		if (DNAState.class == cStates.getStateClass() || DNAState.class.isAssignableFrom(cStates.getStateClass())) {
+			maxState = 3;
+			if (maxState>maxStateDefined)
+				maxState = maxStateDefined;
+			allStates = CategoricalState.span(0,maxState);
+		}
+		else {
+			allStates = ((CategoricalDistribution)cStates).getAllStates();
+			maxState = CategoricalState.maximum(allStates);
+			if (maxState>maxStateDefined) {
+				maxState = maxStateDefined;
+				allStates = allStates & CategoricalState.span(0,maxState);
+			}
+			else if (maxState < 1) {
+				allStates = CategoricalState.span(0,1);
+				maxState = 1;
+			}
+		}
+	}
+	/* ---------------------------------------------*/
+	public int getMaxStateDefined() {
+		return maxStateDefined;
+	}
+	/* ---------------------------------------------*/
+	public int getMaxState() {
+		return maxState;
+	}
+	/* ---------------------------------------------*/
+ 	/* copy information from this to model passed (used in cloneModelWithMotherLink to ensure that superclass info is copied); should call super.copyToClone(pm) */
+	public void copyToClone(CharacterModel md){
+		if (md == null)
+			return;
+		super.copyToClone(md);
+		ProbabilityCategCharModel model = (ProbabilityCategCharModel)md;
+		model.allStates = allStates;
+		model.maxState = maxState;
+		model.maxStateDefined = maxStateDefined;
+		if (model.allStates == 0L)
+			model.allStates = CategoricalState.span(0,maxState);
+	}
+	/* ---------------------------------------------*/
+	public void setSeed(long seed){
+		randomNumGen.setSeed(seed);
+	}
+	
+	/* ---------------------------------------------*/
+	public long getSeed(){
+		return randomNumGen.nextLong();
+	}
+	
+	protected double progressiveOptimize(Tree tree, TreeDataModelBundle bundle, Optimizer opt, MesquiteDouble param, double min, double optWidth){
+		double max = optWidth/tree.tallestPathAboveNode(tree.getRoot(), 1.0);
+		if (max <= min)
+			max = min + 0.1;
+ 		param.setValue((max-min)/2);
+ 		double best = opt.optimize(param, min, max, bundle);
+ 		double mult = optWidth;
+ 		if (optWidth < 2)
+ 			mult = 2;
+ 		int count = 1;
+		if (param.getValue()< min*1.00001){ //parameter very close to minimum; try narrowing the range to see if get better answer
+			while (param.getValue()< min*1.00001 && min> 0.00000001 && count<10) { 
+				double oldMin = min;
+				min = min/mult; 
+	 			best = opt.optimize(param,min, (oldMin - min)*0.5 + min, bundle);
+	 			count++;
+	 		}
+		}
+		else { 
+			double oldBest = 0;
+			
+			//check if parameter is near maximum; if near enough then expand range and try again.  Keep trying as long as -ln likelihood improves a bit
+			while (param.getValue() > max*0.999 && max<100000 && count<10 && (oldBest == 0 || (best<oldBest && Math.abs(best/oldBest)<0.999))) { //trying again in case seems to be bumping up against max
+				double oldMax = max;
+				max = max*mult; 
+				oldBest = best;
+	 			best = opt.optimize(param, (oldMax-min)*0.8 + min, max, bundle);
+	 			count++;
+	 		}
+ 		}
+ 		return best;
+	}
+	
+}
+
diff --git a/Source/mesquite/stochchar/lib/ProbabilityContCharModel.java b/Source/mesquite/stochchar/lib/ProbabilityContCharModel.java
new file mode 100644
index 0000000..0e802c5
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/ProbabilityContCharModel.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.cont.lib.*;
+/*==========================  Mesquite Basic Class Library ==========================*/
+/*===  the basic classes used by the kernel of Mesquite (i.e. the trunk object) and available to the modules
+
+/* ======================================================================== */
+/** A character model for continuous characters to be used in stochastic simulations and in likelihood calculations.
+Needs to include other methods, such as ones dealing with pdf for transitions*/
+public abstract class ProbabilityContCharModel  extends ProbabilityModel {
+	public ProbabilityContCharModel (String name, Class dataClass) {
+		super(name, dataClass);
+	}
+	/** Randomly generates according to model an end state on branch from beginning states*/
+	public abstract double evolveState (double beginState, Tree tree, int node);
+	
+	public void evolveState (CharacterState beginState, CharacterState endState, Tree tree, int node){
+		if (beginState==null || endState==null || !(beginState instanceof ContinuousState) || !(endState instanceof ContinuousState))
+			return;
+		ContinuousState bState = (ContinuousState)beginState;
+		ContinuousState eState = (ContinuousState)endState;
+		double b = bState.getValue(0);
+		eState.setValue(0,evolveState(b, tree, node));
+	}
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public abstract double getRootState (Tree tree);
+	
+	/** Randomly generates according to model an ancestral state for root of tree*/
+	public CharacterState getRootState (CharacterState state, Tree tree){
+		if (state==null || !(state instanceof ContinuousState))
+			state = new ContinuousState();
+		((ContinuousState)state).setValue(0,getRootState(tree));
+		return state;
+	}
+	
+}
+
diff --git a/Source/mesquite/stochchar/lib/SimModelCompatInfo.java b/Source/mesquite/stochchar/lib/SimModelCompatInfo.java
new file mode 100644
index 0000000..901ff6b
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/SimModelCompatInfo.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib; 
+
+import java.awt.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+public class SimModelCompatInfo extends ModelCompatibilityInfo {
+	public SimModelCompatInfo(Class targetModelSubclass, Class targetStateClass){
+		super(targetModelSubclass, targetStateClass);
+	}
+	 //obj to be passed here is model, so that requester of model can check for compatibility as well as vice versa; added Apr 02
+ 	public boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+ 		if (obj instanceof ProbabilityModel && !((ProbabilityModel)obj).isFullySpecified()){
+ 			return false;
+ 		}
+ 		return super.isCompatible(obj, project, prospectiveEmployer);
+ 	}
+	
+}
+
+
+
diff --git a/Source/mesquite/stochchar/lib/TreeDataModelBundle.java b/Source/mesquite/stochchar/lib/TreeDataModelBundle.java
new file mode 100644
index 0000000..dbe774e
--- /dev/null
+++ b/Source/mesquite/stochchar/lib/TreeDataModelBundle.java
@@ -0,0 +1,59 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.stochchar.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+
+
+/* ======================================================================== */
+
+public class TreeDataModelBundle   {
+	Tree tree;
+	ProbabilityModel model;
+	CharacterDistribution distribution;
+	CLikelihoodCalculator calc;
+	Object params; //a list of which parameters are to be estimated
+	CommandRecord comRec;
+	
+	public TreeDataModelBundle(Tree t, ProbabilityModel m, CharacterDistribution d, Object params, CLikelihoodCalculator lc){
+		tree = t;
+		model = m;
+		distribution = d;
+		calc = lc;
+		this.params = params;
+		this.comRec = MesquiteThread.getCurrentCommandRecord();
+	}
+	public Tree getTree(){
+		return tree;
+	}
+	public ProbabilityModel getProbabilityModel(){
+		return model;
+	}
+	public CharacterDistribution getCharacterDistribution(){
+		return distribution;
+	}
+	public CLikelihoodCalculator getLikelihoodCalculator(){
+		return calc;
+	}
+	public Object getParams(){
+		return params;
+	}
+	public CommandRecord getCommandRecord(){
+		return comRec;
+	}
+}
+
+
+
diff --git a/Source/mesquite/stochchar/zMargLikeCateg/zMargLikeCateg.java b/Source/mesquite/stochchar/zMargLikeCateg/zMargLikeCateg.java
new file mode 100644
index 0000000..a1be4f8
--- /dev/null
+++ b/Source/mesquite/stochchar/zMargLikeCateg/zMargLikeCateg.java
@@ -0,0 +1,894 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.stochchar.zMargLikeCateg;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+import mesquite.stochchar.lib.*;
+
+/* ======================================================================== */
+public class zMargLikeCateg extends MargLikeAncStCLForModel implements MesquiteListener, CLikelihoodCalculator {
+	//CategoricalDistribution observedStates;
+	double[][] downProbs, upProbs, finalProbs;  // probability at node N given state s at base
+	double[] underflowCompDown, underflowCompUp;  // ln of compensation for underflow
+	double[] empirical;
+	MesquiteNumber probabilityValue;
+	int numStates;
+	ProbabilityCategCharModel tempModel;
+	ProbabilityCategCharModel passedModel;
+	long underflowCheckFrequency = 2;  //how often to check that not about to underflow; 1 checks every time
+	long underflowCheck = 1;
+	MesquiteNumber minChecker;
+
+	//In version 1.1. the assumption about the root prior for model estimation, ancestral state reconstruction and simulation is assumed to be embedded in the model
+	//Thus, the control is removed here
+	public static final int ROOT_IGNOREPRIOR = 0;  // likelihoodignore's model's prior
+	public static final int ROOT_USEPRIOR = 1;  // calculates ancesteral states imposing model's prior
+	public boolean showRootModeChoices = false; 
+	int rootMode = ROOT_USEPRIOR; //what if anything is done with prior probabilities of states at subroot?  
+	StringArray rootModes;
+	MesquiteString rootModeName;
+
+	static final int REPORT_Proportional = 0;  
+	static final int REPORT_Raw = 1;
+	static final int REPORT_Log = 2;
+	StringArray reportModes;
+	int reportMode = REPORT_Proportional;
+	MesquiteString reportModeName;
+
+	boolean fillFrequencies = true;
+	double decisionThreshold = 2.0;
+	boolean reportRootMode = true;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		probabilityValue = new MesquiteNumber();
+		minChecker = new MesquiteNumber(MesquiteDouble.unassigned);
+
+
+		reportModes = new StringArray(3);  
+		if (getHiredAs() == MargLikeAncStForModel.class){
+			reportModes.setValue(REPORT_Proportional, "Proportional Likelihoods");  //the strings passed will be the menu item labels
+			reportModes.setValue(REPORT_Raw, "Raw Likelihoods");
+			reportModes.setValue(REPORT_Log, "Negative Log Likelihoods");
+			reportModeName = new MesquiteString(reportModes.getValue(reportMode));  //this helps the menu keep track of checkmenuitems
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Report Likelihoods As", makeCommand("setReportMode", this), reportModes); 
+			mss.setSelected(reportModeName);
+
+		}
+		addMenuItem("Likelihood Decision Threshold...", makeCommand("setDecision", this));
+		rootModes = new StringArray(2);  
+		rootModes.setValue(ROOT_IGNOREPRIOR, "Ignore Root State Frequencies");  //the strings passed will be the menu item labels
+		rootModes.setValue(ROOT_USEPRIOR, "Use Root State Frequencies as Prior");
+		rootModeName = new MesquiteString(rootModes.getValue(rootMode));  //this helps the menu keep track of checkmenuitems
+
+		if (showRootModeChoices && getHiredAs() != MargLikeAncStCLForModel.class){
+			/*Treatment of prior at root; currently user interface hidden unless preferences file put in place*/
+			MesquiteSubmenuSpec mssr = addSubmenu(null, "Root Reconstruction", makeCommand("setRootMode", this), rootModes); 
+			mssr.setSelected(rootModeName);
+			/**/
+		}
+
+		MesquiteSubmenuSpec mLO = addSubmenu(null, "Likelihood Optimization", null); 
+		addItemToSubmenu(null, mLO, "Underflow Checking...", makeCommand("setUnderflowCheckFreq", this));
+
+		return true;
+	}
+	boolean reportCladeValues = false;
+	public void setReportCladeLocalValues(boolean reportCladeValues){
+		this.reportCladeValues = reportCladeValues;
+	}
+	public boolean getReportCladeLocalValues(){
+		return reportCladeValues;
+	}
+	/*public void setRootMode(int newMode){
+		if (newMode >=0 && newMode!=rootMode){
+			rootMode = newMode; //change mode
+			rootModeName.setValue(rootModes.getValue(rootMode)); //so that menu item knows to become checked
+			parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+		}
+	}
+	public int getRootMode(){
+		return rootMode;
+	}
+	/*.................................................................................................................*
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0 && prefs[0] !=null  && prefs[0].length()>0) {
+			showRootModeChoices = ('y' == prefs[0].charAt(0));
+		}
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+
+		Snapshot temp = new Snapshot();
+		if (getHiredAs() == MargLikeAncStForModel.class){
+			temp.addLine("setReportMode " + ParseUtil.tokenize(reportModes.getValue(reportMode)));
+			temp.addLine("setRootMode "  + ParseUtil.tokenize(rootModes.getValue(rootMode)));
+			/**/
+		}
+		temp.addLine("setDecision " + decisionThreshold);
+		/**/
+		temp.addLine("setUnderflowCheckFreq " + underflowCheckFrequency);
+		return temp;
+	}
+
+
+	/*.................................................................................................................*/
+	/*  the main command handling method.  */
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the threshold T for deciding whether ancestral state is included among estimates; states with likelihoods T times less than best are not included in estimate", "[threshold]", commandName, "setDecision")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			double T = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(T))
+				T = MesquiteDouble.queryDouble(containerOfModule(), "Likelihood Decision Threshold", "Indicate the threshold T for deciding whether ancestral state is included among estimates; states with log likelihoods higher (worse) than the best by T or more are not included in estimate.  This is relevant when likelihoods are not merely reported but a decision is made, e.g. in Trace Character History if Display Proportional To Weights is not selected, or in Trace Character Over Trees.", decision [...]
+			if (!MesquiteDouble.isCombinable(T))
+				return null;
+			if (decisionThreshold != T) {
+				decisionThreshold = T;
+				if (!reportCladeValues)
+					parametersChanged(); 
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the report mode", null, commandName, "setReportMode")) {
+			if (getHiredAs() == MargLikelihoodForModel.class)
+				return null;
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = reportModes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=reportMode){
+				reportMode = newMode; //change mode
+				reportModeName.setValue(reportModes.getValue(reportMode)); //so that menu item knows to become checked
+				if (!reportCladeValues)
+					parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the root mode", null, commandName, "setRootMode")) {
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = rootModes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=rootMode){
+				rootMode = newMode; //change mode
+				rootModeName.setValue(rootModes.getValue(rootMode)); //so that menu item knows to become checked
+				parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else if (checker.compare(getClass(), "Sets the frequency of checking for underflow", "[integer, 1 or greater]", commandName, "setUnderflowCheckFreq")) {
+			int freq = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(freq) && !MesquiteThread.isScripting())
+				freq = MesquiteInteger.queryInteger(containerOfModule(), "Checking frequency", "Frequency at which underflow checking is performed in likelihood calculations.  A value of n means checking is performed on each nth calculation; higher numbers mean the calculations go faster but are at risk of underflow problems.  Values over 10 are not recommended", (int)underflowCheckFrequency, 1, 10000);
+
+			if (MesquiteInteger.isCombinable(freq) && freq >=0 && freq!=underflowCheckFrequency){
+				underflowCheckFrequency = freq; //change mode
+				parametersChanged(); //this tells employer module that things changed, and recalculation should be requested
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void initProbs(int nodes, int numStates) {
+		this.numStates = numStates;
+		if (downProbs==null || downProbs.length!=nodes || downProbs[0].length!=numStates){
+			downProbs = new double[nodes][numStates];
+			upProbs = new double[nodes][numStates];
+			finalProbs = new double[nodes][numStates];
+			underflowCompDown = new double[nodes];
+			underflowCompUp = new double[nodes];
+			empirical = new double[numStates];
+		}
+		Double2DArray.zeroArray(downProbs);
+		Double2DArray.zeroArray(upProbs);
+		Double2DArray.zeroArray(finalProbs);
+		DoubleArray.zeroArray(underflowCompDown);
+		DoubleArray.zeroArray(underflowCompUp);
+		DoubleArray.zeroArray(empirical);
+	}
+	/*.................................................................................................................*/
+	/* calculates for each i at node N, the sum of probabilities for all possible j that can be placed at d*/
+	private double probFromSection (Tree tree, int d, int i, double[] ProbsD, ProbabilityCategCharModel model, boolean downwards) {
+		double prob = 0;
+		if (downwards){
+			for (int j=0; j< numStates; j++) 
+				prob += model.transitionProbability(i, j, tree, d)*ProbsD[j]; 
+		}
+		else {
+			for (int j=0; j< numStates; j++) 
+				prob += model.transitionProbability(j,i, tree, d)*ProbsD[j]; 
+		}
+		return prob;
+	}
+	/*.................................................................................................................*/
+	private double checkUnderflow(double[] probs){
+		minChecker.setValue(MesquiteDouble.unassigned);
+		for (int i=0; i<probs.length; i++)
+			minChecker.setMeIfIAmMoreThan(probs[i]);
+		double q = minChecker.getDoubleValue();
+		if (q == 0)
+			return 0;
+		else {
+			for (int i=0; i<probs.length; i++)
+				probs[i] /= q;
+		}
+		return -Math.log(q);
+	}
+	/*.................................................................................................................*/
+	/* assumes hard polytomies */
+	private   void downPass(int node, Tree tree, ProbabilityCategCharModel model, CategoricalDistribution observedStates) {
+		if (tree.nodeIsTerminal(node)) {
+			long observed = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node));
+/*Uncertain multistate starts here OliverZMarg*/
+			int[] states = CategoricalState.expand(observed);
+			DoubleArray.zeroArray(downProbs[node]);
+			if(states.length > 0 && !CategoricalState.isUnassigned(observed) && !CategoricalState.isInapplicable(observed)){
+				for(int i = 0; i < states.length; i++){
+					downProbs[node][states[i]] = 1; //Assign probability of 1 for all observed states at tips.
+				}
+			}/*Polymorphism ends here*/
+			
+/*Original Implementation:
+			int obs = CategoricalState.minimum(observed); //NOTE: just minimum observed!
+			DoubleArray.zeroArray(downProbs[node]);
+			if (obs>=0 && obs < downProbs[node].length && !CategoricalState.isUnassigned(observed) && !CategoricalState.isInapplicable(observed)) 
+				downProbs[node][obs] = 1;
+/*End Original Implementation*/
+		}
+		else {
+			DoubleArray.zeroArray(downProbs[node]);
+			underflowCompDown[node] =0;
+			for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+				downPass(d, tree, model, observedStates);
+				underflowCompDown[node] += underflowCompDown[d];
+			}
+
+			for (int i=0; i<numStates; i++) {
+				double prob = 1.0;
+				for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+					double scnProb = probFromSection(tree, d, i, downProbs[d], model, true); 
+					prob *= scnProb; 
+				}
+				downProbs[node][i] = prob;
+			}
+			if (++underflowCheck % underflowCheckFrequency == 0){
+				underflowCompDown[node] += checkUnderflow(downProbs[node]);
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	/* assumes hard polytomies */
+	private   void upPass(int node, Tree tree,  ProbabilityCategCharModel model, CategoricalDistribution observedStates) {
+		underflowCompUp[node] = 0;
+		if (node == tree.getRoot(deleted)) {  
+			if (tree.rootIsReal(deleted)){
+				/*~~~~~~~~~~~~~~ upPass ~~~~~~~~~~~~~~*
+				if (rootMode == SUBROOT_PRIOR) {
+					for (int i=0; i<numStates; i++) 
+						upProbs[node][i] = model.priorProbability(i);
+				}
+				else if (rootMode == SUBROOT_EMPIRICAL) {
+					calculateEmpirical(tree, observedStates, empirical);
+					for (int i=0; i<numStates && i<empirical.length; i++) 
+						upProbs[node][i] = empirical[i]; 
+				}
+				 */
+			}
+		}
+		else {
+			DoubleArray.zeroArray(upProbs[node]);
+			if (tree.motherOfNode(node, deleted) == tree.getRoot(deleted) && !tree.rootIsReal(deleted) && !tree.nodeIsPolytomous(tree.getRoot(deleted))) {  //special case of node just above dichotomous ghost root
+				int sister;
+				if (tree.nodeExists(tree.nextSisterOfNode(node, deleted)))
+					sister = tree.nextSisterOfNode(node, deleted);
+				else
+					sister = tree.previousSisterOfNode(node, deleted);
+
+				for (int i=0; i<numStates; i++) 
+					upProbs[node][i] = downProbs[sister][i];
+			}
+			else if (tree.nodeIsInternal(node)) {
+				int mother = tree.motherOfNode(node, deleted);
+				for (int i=0; i<numStates; i++) {
+					double prob = 1.0;
+
+					// accumulate downstates from sisters
+					for (int d = tree.firstDaughterOfNode(mother, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+						if (d!=node) {
+							prob *= probFromSection(tree, d, i, downProbs[d], model, true);
+						}
+					}
+
+					/*~~~~~~~~~~~~~~ upPass ~~~~~~~~~~~~~~*/
+					if (mother != tree.getRoot(deleted)){
+						//get upstate from ancestor
+						prob *= probFromSection(tree, mother, i, upProbs[mother], model, false);  //pass mother because that's the branch length
+					}
+					//mother is the root.  Do we use a prior also for the recontruction?
+					else if (rootMode == ROOT_USEPRIOR){
+						prob *= model.priorProbability(i);
+					}
+					upProbs[node][i] = prob;
+				}
+				// accumulate compensations from sisters
+				for (int d = tree.firstDaughterOfNode(mother, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+					if (d!=node)
+						underflowCompUp[node] += underflowCompDown[d];
+				}
+
+				//accumulate compensations from ancestor
+				if (mother!=tree.getRoot(deleted))
+					underflowCompUp[node] += underflowCompUp[mother];
+			}
+			if (++underflowCheck % underflowCheckFrequency == 0){
+				underflowCompUp[node] += checkUnderflow(upProbs[node]);
+			}
+		}
+		for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+			upPass(d, tree, model, observedStates);
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   void finalPass(int node, Tree tree, CategoricalHistory statesAtNodes, ProbabilityCategCharModel model, CategoricalDistribution observedStates) {
+		if (node==tree.getRoot(deleted) && (!tree.rootIsReal(deleted))) { //root isn't real; skip
+
+		}
+		/*~~~~~~~~~~~~~~ finalPass ~~~~~~~~~~~~~~*/
+		else if (node==tree.getRoot(deleted)){
+			if (rootMode == ROOT_IGNOREPRIOR) { //root but not using subroot prior; just use downprobs
+				DoubleArray.zeroArray(finalProbs[node]);
+				for (int i=0; i<numStates; i++) 
+					finalProbs[node][i] = downProbs[node][i]; 
+			}
+			else if (rootMode == ROOT_USEPRIOR) { //root  using root prior
+				DoubleArray.zeroArray(finalProbs[node]);
+				for (int i=0; i<numStates; i++) 
+					finalProbs[node][i] = downProbs[node][i]*model.priorProbability(i); 
+			}
+		}
+		else if (!tree.nodeIsTerminal(node)) { //internal, including root with subroot prior
+			DoubleArray.zeroArray(finalProbs[node]);
+			for (int i=0; i<numStates; i++) 
+				finalProbs[node][i] = downProbs[node][i]*probFromSection(tree, node, i, upProbs[node], model, false); //POLARITY
+		}
+		for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) {
+			finalPass(d, tree, statesAtNodes, model, observedStates);
+		}
+	}
+	/*.................................................................................................................*/
+	double[] readjustComp(Tree tree, int node, double[] compensated, boolean log){
+		double[] d = new double[compensated.length];
+		double comp = underflowCompDown[node];
+		if (tree.getRoot(deleted)!=node)
+			comp += underflowCompUp[node];
+		if (log){
+			for (int i=0; i<d.length; i++)
+				d[i] = comp - Math.log(compensated[i]);
+		}
+		else {
+			for (int i=0; i<d.length; i++)
+				d[i] = compensated[i]*Math.exp(-comp);
+		}
+		return d;
+	}
+	/*.................................................................................................................*/
+	public   void storeFinal(int node, Tree tree, CategoricalHistory statesAtNodes, CategoricalDistribution observedStates, double dThresh) {
+		if (tree.nodeIsTerminal(node)) {
+			long st = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node));
+			statesAtNodes.setState(node, st);
+			if (fillFrequencies) {
+				int numSt = CategoricalState.cardinality(st);
+				for (int i=0; i<numStates; i++) {
+					if (CategoricalState.isElement(st, i))
+						finalProbs[node][i] = 1.0/numSt;
+					else
+						finalProbs[node][i] =0;
+				}
+				statesAtNodes.setFrequencies(node, finalProbs[node]);
+			}
+		}
+		else if (tree.rootIsReal(deleted) || node!=tree.getRoot(deleted)) {
+			statesAtNodes.setState(node, CategoricalState.chooseHighestWithinFactor(finalProbs[node],dThresh));
+			if (fillFrequencies) {
+				if (reportMode == REPORT_Proportional){
+					double[] f = new double[numStates];
+					double sum = 0;
+					for (int i=0; i<numStates; i++)
+						sum+= finalProbs[node][i];
+					for (int i=0; i<numStates; i++)
+						f[i] = finalProbs[node][i]/sum;  
+					statesAtNodes.setFrequencies(node, f);
+				}
+				else if (reportMode == REPORT_Raw)
+					statesAtNodes.setFrequencies(node, readjustComp(tree, node, finalProbs[node], false));
+				else { //REPORT_Log
+					double[] f = readjustComp(tree, node, finalProbs[node], false);
+					for (int i=0; i<numStates; i++)
+						f[i] = -Math.log(f[i]);  
+					statesAtNodes.setFrequencies(node, f);
+				}
+			}
+		}
+		for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) 
+			storeFinal(d, tree, statesAtNodes,observedStates, dThresh);
+	}
+	/*.................................................................................................................*/
+	public   void storeDown(int node, Tree tree, CategoricalHistory statesAtNodes, CategoricalDistribution observedStates) {
+		if (tree.nodeIsTerminal(node)) {
+			long st = ((CategoricalDistribution)observedStates).getState(tree.taxonNumberOfNode(node));
+			statesAtNodes.setState(node, st);
+
+			int numSt = CategoricalState.cardinality(st);
+			for (int i=0; i<numStates; i++) {
+				if (CategoricalState.isElement(st, i))
+					downProbs[node][i] = 1.0/numSt;
+				else
+					downProbs[node][i] =0;
+			}
+			statesAtNodes.setFrequencies(node, downProbs[node]);
+
+		}
+		else  {  
+			statesAtNodes.setFrequencies(node, readjustComp(tree, node, downProbs[node], false));
+		}
+		for (int d = tree.firstDaughterOfNode(node, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted)) 
+			storeDown(d, tree, statesAtNodes,observedStates);
+	}
+	/*.................................................................................................................*/
+	private boolean hasZeroOrNegLengthBranches(Tree tree, int N, boolean countRoot) {
+		if (tree.getBranchLength(N) <= 0.0 && (countRoot || tree.getRoot() != N))
+			return true;
+		if (tree.nodeIsInternal(N)){
+			for (int d = tree.firstDaughterOfNode(N, deleted); tree.nodeExists(d); d = tree.nextSisterOfNode(d, deleted))
+				if (hasZeroOrNegLengthBranches(tree, d, countRoot))
+					return true;
+		}
+		return false;
+	}
+	//boolean warnedMissing = false;
+	boolean warnedPolymorphic = false;
+	boolean warnedMaxState = false;
+	boolean warnedUnbranchedInternals = false;
+	boolean warnedReticulations = false;
+	boolean warnedNotContiguous = false;
+	boolean warnedSoftPoly = false;
+	boolean warnedZeroLength = false;
+	boolean warnedUnrootedCladeValuesMode = false;
+	boolean[] deleted;
+
+	boolean warn(CategoricalDistribution observedStates, ProbabilityCategCharModel model, Tree tree, MesquiteString resultString){
+/*  OliverZMarg had commented this out; re-enforced for polymorphisms (but not uncertainties) in 3.04 */
+		if (observedStates.hasPolymorphicStatesInTaxon(tree, tree.getRoot())) {
+			String s = "Polymorphic taxa are not currently supported by Categorical data likelihood calculations.  Calculations for one or more characters were not completed.";
+			if (!warnedPolymorphic) {
+				discreetAlert( s);
+				warnedPolymorphic = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		} 
+		if (tree.hasSoftPolytomies(tree.getRoot())) {
+			String message = "Trees with soft polytomies not allowed by Categorical data likelihood calculations.  Calculations for one or more trees were not completed.";
+			if (!warnedSoftPoly){
+				discreetAlert( message);
+				warnedSoftPoly = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (hasZeroOrNegLengthBranches(tree, tree.getRoot(), ROOT_IGNOREPRIOR != rootMode && ROOT_USEPRIOR != rootMode) ) {
+			String message = "Trees with zero or negative length branches are not allowed by Categorical data likelihood calculations.  You can collapse these to polytomies using the Collapse zero-length branches in the Alter/Transform tree submenu.  Calculations for one or more trees were not completed.";
+			message += " TREE: " + tree.writeTree();
+
+			if (!warnedZeroLength){
+				discreetAlert( message);
+				warnedZeroLength = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		if (!tree.rootIsReal() && reportCladeValues) {
+			String message = "Unrooted trees are not allowed by Categorical data likelihood calculations when used to report clade values only.  Calculations for one or more trees were not completed.";
+			message += " TREE: " + tree.writeTree();
+
+			if (!warnedUnrootedCladeValuesMode){
+				discreetAlert( message);
+				warnedUnrootedCladeValuesMode = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(message);
+			return true;
+		}
+		long allStates = observedStates.getAllStates(tree, tree.getRoot());
+		int max = CategoricalState.maximum(allStates);
+		if (max > model.getMaxStateDefined()) {
+			String s = "Character distibution includes state values larger than allowed by current model of character evolution.  Calculations for one or more characters were not completed.";
+			if (!warnedMaxState) {
+				discreetAlert( s);
+				warnedMaxState = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (allStates != CategoricalState.span(0, CategoricalState.maximum(allStates))) {  //fixed in 1. 12; had been min - max, not 0 - max
+			String s = "Categorical data likelihood calculations currently require state distribution to include only contiguous states starting at 0 (e.g., character with only states 2 and 3 not allowed, and should instead be recoded to states 0 and 1).  Calculations for one or more characters were not completed.";
+			if (!warnedNotContiguous) {
+				if (!MesquiteThread.isScripting())
+					alert(s);
+				else
+					logln(s);
+				warnedNotContiguous = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (tree.hasUnbranchedInternals(tree.getRoot())) {
+			String s = "Likelihood calculations cannot be done because tree has unbranched internal nodes.";
+			if (!warnedUnbranchedInternals) {
+				discreetAlert( s);
+				warnedUnbranchedInternals = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (tree.hasReticulations()) {
+			String s = "Likelihood calculations cannot be done because tree has reticulations.";
+			if (!warnedReticulations) {
+				discreetAlert( s);
+				warnedReticulations = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}
+		if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())){
+			if (deleted == null || deleted.length <  tree.getNumNodeSpaces())
+				deleted = new boolean[tree.getNumNodeSpaces()];
+			for (int i = 0; i<deleted.length; i++) deleted[i] = false;
+			for (int it = 0; it< tree.getTaxa().getNumTaxa(); it++)
+				if (observedStates.isUnassigned(it) || observedStates.isInapplicable(it)) {
+					tree.virtualDeleteTaxon(it, deleted);
+				}
+		}
+		else
+			deleted = null;
+		/*	if (observedStates.hasMissing(tree, tree.getRoot()) || observedStates.hasInapplicable(tree, tree.getRoot())) {
+			String s ="Missing data & Gaps are not currently supported by Categorical data likelihood calculations.  Calculations for one or more characters were not completed.";
+			if (!warnedMissing) {
+				discreetAlert( s);
+				warnedMissing = true;
+			}
+			if (resultString!=null)
+				resultString.setValue(s);
+			return true;
+		}*/
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	void calculateEmpirical(Tree tree, CategoricalDistribution observedStates, double[] empirical){
+		DoubleArray.zeroArray(empirical);
+		int n = 0;
+		for (int it =0; it<observedStates.getNumTaxa(); it++) {
+			if (tree.taxonInTree(it)){
+				long s = observedStates.getState(it);
+				if (CategoricalState.isCombinable(s)) {
+					n++;
+					for (int i=0; i<empirical.length; i++){
+						if (CategoricalState.isElement(s, i))
+							empirical[i]++;
+					}
+				}
+			}
+		}	
+		if (n>0)
+			for (int i=0; i<empirical.length; i++){
+				empirical[i] /= n;
+			}
+	}
+
+	/*.................................................................................................................*/
+	public  void calculateStates(Tree tree, CharacterDistribution obsStates, CharacterHistory statesAtNodes, CharacterModel model, MesquiteString resultString, MesquiteNumber prob) {  
+		if (model==null || statesAtNodes==null || obsStates==null || !(model instanceof ProbabilityCategCharModel) || !(obsStates instanceof CategoricalDistribution))
+			return;
+		estCount =0;
+		zeroHit = false;
+		if (prob !=null)
+			prob.setToUnassigned();
+		this.passedModel = (ProbabilityCategCharModel)model;
+		if (tempModel == null || tempModel.getClass() != model.getClass()){
+			tempModel = (ProbabilityCategCharModel)passedModel.cloneModelWithMotherLink(null);
+	 		tempModel.setUserVisible(false);
+		}
+		CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+		if (warn(observedStates, passedModel, tree, resultString))
+			return;
+		int root = tree.getRoot(deleted);
+		ProbabilityCategCharModel useModel;
+		double comp;
+		boolean estimated = false;
+		if (((ProbabilityModel)model).isFullySpecified()) {
+			useModel = passedModel;
+			useModel.setCharacterDistribution(observedStates);
+		}
+		else if (model instanceof CModelEstimator) {
+			passedModel.copyToClone(tempModel);
+			useModel = tempModel;
+			useModel.setCharacterDistribution(observedStates);
+			((CModelEstimator)useModel).estimateParameters(tree, observedStates, this);
+			estimated = true;
+		}
+		else {
+			if (prob!=null)
+				prob.setToUnassigned();
+			if (resultString!=null)
+				resultString.setValue("Model with parameters incompletely specified.");
+			return;
+		}
+		initProbs(tree.getNumNodeSpaces(), useModel.getMaxState()+1); //todo: the model should use the observedStates to set this; observedStates should carry info about its maximun conceivable number of states?
+		downPass(root, tree, useModel, observedStates);
+		comp = underflowCompDown[root];
+		statesAtNodes.deassignStates();
+
+		if (reportCladeValues){
+			storeDown(root, tree, (CategoricalHistory)statesAtNodes,  observedStates);
+			if (getHiredAs() == MargLikeAncStForModel.class)
+				((CharacterStates)statesAtNodes).setExplanation("Clade values for " + reportModes.getValue(reportMode));
+			else
+				((CharacterStates)statesAtNodes).setExplanation("" );
+				
+			reportRootMode = false;
+		}
+		else {
+			upPass(root, tree,  useModel, observedStates);
+			finalPass(root, tree, (CategoricalHistory)statesAtNodes,  useModel, observedStates);
+			storeFinal(root, tree, (CategoricalHistory)statesAtNodes,  observedStates, Math.exp(decisionThreshold));
+			((CharacterStates)statesAtNodes).setExplanation(reportModes.getValue(reportMode));
+			reportRootMode = !useModel.priorAlwaysFlat();
+		}
+		String rep = passedModel.getName() + " [" + useModel.getParameters() + "]";
+		double likelihood = 0.0;
+
+		/*~~~~~~~~~~~~~~ calculateStates ~~~~~~~~~~~~~~*/
+		for (int i=0;  i<=useModel.getMaxState(); i++) 
+			likelihood += downProbs[root][i] * useModel.priorProbability(i);
+
+		double negLogLikelihood = -(Math.log(likelihood) - comp);
+		if (prob!=null)
+			prob.setValue(negLogLikelihood);
+		if (resultString!=null) {
+			String s = "Marginal prob. recon. with model " + rep + "  -log L.:" + MesquiteDouble.toString(negLogLikelihood);
+			if (estimated){
+				String set = passedModel.getSettingsString();
+				if (set !=null)
+					s += " " + set;
+			}
+			s += "  " + getParameters();
+			if (reportMode == REPORT_Log)
+				s += "\nNOTE: Because neg. log likelihoods are being reported, larger values imply lower support.  This may cause graphic displays to be confusing for internal nodes.";
+			resultString.setValue(s);
+		}
+	}
+	/*.................................................................................................................*
+	// not yet working
+	public Object getLikelihoodSurface(Tree tree, CharacterDistribution obsStates, CharacterModel model, double[] inputBounds, double[] outputBounds) {  
+		if (((ProbabilityCategCharModel)model).isFullySpecified())
+			return null;
+		ProbabilityCategCharModel useModel = (ProbabilityCategCharModel)tempModel;
+		CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+		tempModel.setCharacterDistribution( observedStates);
+		return tempModel.getLikelihoodSurface(tree, observedStates, this, 100, outputBounds); //also pass upper & lower bounds
+
+
+	}
+
+	/*.................................................................................................................*/
+	public  void estimateParameters(Tree tree, CharacterDistribution obsStates, CharacterModel model, MesquiteString resultString) {  
+		if (model==null || obsStates==null || !(obsStates instanceof CategoricalDistribution) || !(model instanceof ProbabilityCategCharModel))
+			return;
+		estCount =0;
+		reportRootMode = false;
+		zeroHit = false;
+		ProbabilityCategCharModel useModel;
+		this.passedModel = (ProbabilityCategCharModel)model;
+		CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+		if (warn(observedStates, passedModel, tree, resultString))
+			return;
+		String rep;
+		double comp;
+		int root = tree.getRoot(deleted);
+
+		if (((ProbabilityModel)model).isFullySpecified()) {
+			if (resultString!=null)
+				resultString.setValue("Parameters already fully specified in " + passedModel.getName() + " [" + passedModel.getParameters() + "]");
+			return;
+		}
+		else if (model instanceof CModelEstimator) {
+			useModel = (ProbabilityCategCharModel)passedModel;
+			useModel.setCharacterDistribution(observedStates);
+			((CModelEstimator)useModel).estimateParameters(tree, observedStates, this);
+			if (resultString!=null) {
+				String s = "Model as estimated: " + useModel.getName() + " [" + useModel.getParameters() + "]";
+				String set = useModel.getSettingsString();
+				if (set !=null)
+					s += " " + set;
+
+				s += "  " + getParameters();
+				resultString.setValue(s);
+			}
+		}
+		else {
+			if (resultString!=null)
+				resultString.setValue("Model does not support estimation of parameters.");
+			return;
+		}
+	}
+
+	/*.................................................................................................................*/
+	public  void calculateLogProbability(Tree tree, CharacterDistribution obsStates, CharacterModel model, MesquiteString resultString, MesquiteNumber prob) {  
+		if (model==null || obsStates==null || prob == null || !(model instanceof ProbabilityCategCharModel) || !(obsStates instanceof CategoricalDistribution))
+			return;
+		estCount =0;
+		zeroHit = false;
+		reportRootMode = false;
+		prob.setToUnassigned();
+		ProbabilityCategCharModel useModel;
+		this.passedModel = (ProbabilityCategCharModel)model;
+		if (tempModel == null || tempModel.getClass() != model.getClass()){
+			tempModel = (ProbabilityCategCharModel)passedModel.cloneModelWithMotherLink(null);
+	 		tempModel.setUserVisible(false);
+		}
+		CategoricalDistribution observedStates = (CategoricalDistribution)obsStates;
+		if (warn(observedStates, passedModel, tree, resultString))
+			return;
+		String rep;
+		double comp;
+		int root = tree.getRoot(deleted);
+		boolean estimated = false;
+
+		if (((ProbabilityModel)model).isFullySpecified()) {
+			useModel = (ProbabilityCategCharModel)passedModel;
+			passedModel.setCharacterDistribution( observedStates);
+			initProbs(tree.getNumNodeSpaces(), passedModel.getMaxState()+1); //the model should use the observedStates to set this; observedStates should carry info about its maximun conceivable number of states?
+			downPass(root, tree, passedModel, observedStates);
+			comp = underflowCompDown[root];
+			rep = passedModel.getName() + " [" + useModel.getParameters() + "]";
+		}
+		else if (model instanceof CModelEstimator) {
+			passedModel.copyToClone(tempModel);
+			useModel = (ProbabilityCategCharModel)tempModel;
+			tempModel.setCharacterDistribution(observedStates);
+			((CModelEstimator)useModel).estimateParameters(tree, observedStates, this);
+			estimated = true;
+			rep = passedModel.getName() + " [" + useModel.getParameters() + "]";
+			initProbs(tree.getNumNodeSpaces(), useModel.getMaxState()+1); //the model should use the observedStates to set this; observedStates should carry info about its maximun conceivable number of states?
+			downPass(root, tree, useModel, observedStates);
+			comp = underflowCompDown[root];
+		}
+		else {
+			if (prob!=null)
+				prob.setToUnassigned();
+			if (resultString!=null)
+				resultString.setValue("Model with parameters incompletely specified.");
+			return;
+		}
+		double likelihood = 0.0;
+		/*~~~~~~~~~~~~~~ calculateLogProbability ~~~~~~~~~~~~~~*/
+
+		for (int i=0;  i<=useModel.getMaxState(); i++) 
+			likelihood += downProbs[root][i] * useModel.priorProbability(i);
+
+
+		double negLogLikelihood = -(Math.log(likelihood) - comp);
+		if (prob!=null){
+			prob.setValue(negLogLikelihood);
+			if (estimated)
+				prob.copyAuxiliaries(useModel.getParameterValues());
+			else
+				prob.copyAuxiliaries((MesquiteNumber[])null);
+			prob.setName("-lnLikelihood");
+		}
+		if (resultString!=null) {
+			String s = "Marginal prob. with model " + rep + " -log L.:"+ MesquiteDouble.toString(negLogLikelihood) + " [L. "+ MesquiteDouble.toString(likelihood * Math.exp(-comp)) + "]";
+			if (estimated){
+				String set = passedModel.getSettingsString();
+				if (set !=null)
+					s += " " + set;
+			}
+			s += "  " + getParameters();
+			resultString.setValue(s);
+		}
+	}
+	int estCount =0;
+	boolean zeroHit = false;
+	/*.................................................................................................................*/
+	public double logLikelihoodCalc(Tree tree, ProbabilityModel pModel, CharacterDistribution states){
+		if (zeroHit)
+			return -0.001*(++estCount);  // to shortcircuit the optimizer wandering around zero with very high rates
+		reportRootMode = false;
+		CategoricalDistribution observedStates = (CategoricalDistribution)states;
+		ProbabilityCategCharModel model = (ProbabilityCategCharModel)pModel;
+		model.setCharacterDistribution(observedStates);
+		initProbs(tree.getNumNodeSpaces(), model.getMaxState()+1); //the model should use the observedStates to set this; observedStates should carry info about its maximun conceivable number of states?
+		estCount++;
+		int root = tree.getRoot(deleted);
+		downPass(root, tree,model, observedStates);
+		double likelihood = 0.0;
+		double comp;
+		/*~~~~~~~~~~~~~~ logLikelihoodCalc ~~~~~~~~~~~~~~*/
+
+		for (int i=0;  i<=model.getMaxState(); i++) 
+			likelihood += downProbs[root][i]*model.priorProbability(i);
+
+		comp = underflowCompDown[root];
+		double logLike = Math.log(likelihood) - comp;
+		if (logLike> -0.00001) {
+			zeroHit = true;
+		}
+
+		return (logLike);
+	}
+	/*.................................................................................................................*/
+	public boolean compatibleWithContext(CharacterModel model, CharacterDistribution observedStates) {
+		boolean allowedType = observedStates instanceof CategoricalDistribution;
+		if (allowedType && observedStates !=null){
+			Class sc = observedStates.getStateClass();
+			allowedType = allowedType &&  !(DNAState.class.isAssignableFrom(sc) || ProteinState.class.isAssignableFrom(sc));  //disallow molecular characters for now
+		}
+		return (allowedType && model instanceof ProbabilityCategCharModel);
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Maximum likelihood reconstruct (Generic categorical)";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation() {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Assesses likelihood for categorical characters, and r econstructs ancestral states by the maximum marginal probability (\"MLE\") criterion" ;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		String s = "";
+		if (showRootModeChoices && getHiredAs() != MargLikeAncStCLForModel.class && reportRootMode) {
+			s += "Using root mode " + rootModes.getValue(rootMode);
+		}
+		if (getHiredAs() == MargLikeAncStForModel.class) {
+			if (showRootModeChoices)
+				s += "; ";
+			s += "Reporting likelihoods as " + reportModes.getValue(reportMode);
+		}
+		s += "; Threshold when decisions made: " + MesquiteDouble.toString(decisionThreshold);
+		return s;
+	}
+}
+
diff --git a/Source/mesquite/tol/CatalogueOfLifeURLServer/CatalogueOfLifeURLServer.java b/Source/mesquite/tol/CatalogueOfLifeURLServer/CatalogueOfLifeURLServer.java
new file mode 100644
index 0000000..20aeed6
--- /dev/null
+++ b/Source/mesquite/tol/CatalogueOfLifeURLServer/CatalogueOfLifeURLServer.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.CatalogueOfLifeURLServer;
+
+
+	import mesquite.lib.*;
+import mesquite.tol.lib.TaxonOnWebServer;
+
+	public class CatalogueOfLifeURLServer extends TaxonOnWebServer {
+
+		public String getURL(String taxonName) {
+			String openName = StringUtil.encodeForURL(StringUtil.replace(taxonName,' ', '+'));
+			return "http://www.catalogueoflife.org/annual-checklist/search_results.php?search_string=" + openName + "&match_whole_words=on";
+		
+		}
+
+		public String getName() {
+			return "Catalogue of Life";
+		}
+
+		public String getExplanation() {
+			return "Provides a URL to a taxon in the Catalogue of Life";
+		}
+
+	}
diff --git a/Source/mesquite/tol/GenBankTaxonURLServer/GenBankTaxonURLServer.java b/Source/mesquite/tol/GenBankTaxonURLServer/GenBankTaxonURLServer.java
new file mode 100644
index 0000000..7bbe47f
--- /dev/null
+++ b/Source/mesquite/tol/GenBankTaxonURLServer/GenBankTaxonURLServer.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.GenBankTaxonURLServer;
+
+import mesquite.lib.*;
+import mesquite.tol.lib.*;
+
+public class GenBankTaxonURLServer extends TaxonOnWebServer {
+
+	public String getURL(String taxonName) {
+		String openName = StringUtil.encodeForURL(StringUtil.replace(taxonName,' ', '+'));
+		return "http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Undef&name=" + openName + "&lvl=0&srchmode=1";
+
+	}
+
+	public String getName() {
+		return "GenBank Taxon";
+	}
+
+	public String getExplanation() {
+		return "Provides a URL to a taxon in NCBI GenBank";
+	}
+
+}
diff --git a/Source/mesquite/tol/GetToLTree/GetToLTree.java b/Source/mesquite/tol/GetToLTree/GetToLTree.java
new file mode 100644
index 0000000..755e312
--- /dev/null
+++ b/Source/mesquite/tol/GetToLTree/GetToLTree.java
@@ -0,0 +1,104 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.tol.GetToLTree;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.tol.lib.*;
+
+
+public class GetToLTree extends GeneralFileMaker  {
+	protected int pageDepth = 1;
+	protected String cladeName = "";
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getDialogLabel() {
+		return "Clade in Tree of Life Web Project";
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Tree from ToL Web Project...";
+	}
+	public String getExplanation() {
+		return "Gets the tree for the page of the Tree of Life Web Project for the group specified.";
+	}
+	public boolean isSubstantive(){
+		return true;
+	} 	
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	public String getExtraArguments() {
+		return null;
+	}
+
+	/** make a new  MesquiteProject.*/
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Obtain Tree from ToLWeb",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel(getDialogLabel());
+		String helpString = "Enter the name of the clade in the Tree of Life Web Project you wish to examine. Enter into \"Number of descendent pages\" the size of the tree to be acquired, "
+			+ "measured in terms of extent of descendent pages. If this number is 1, then only the single page's tree will be acquired; if the number is 2, then the single pages's tree plus all nodes on the "
+			+ " immediate descendent pages will be acquired, and so on.  If the number is 0, or very large, then all descendent nodes will be acquired. \nNOTE: currently only values of 1 or 0 are supported!!";
+
+		dialog.appendToHelpString(helpString);
+
+
+		SingleLineTextField cladeNameField = dialog.addTextField(getDialogLabel(), "", 20);		
+		IntegerField pageDepthField = dialog.addIntegerField("Number of descendent pages:", pageDepth, 4, 1, 20);
+		dialog.setDefaultTextComponent(cladeNameField);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			cladeName = cladeNameField.getText();
+			pageDepth = pageDepthField.getValue();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public MesquiteProject establishProject(String arguments){
+		if (arguments ==null) {
+			if (queryOptions())
+				arguments=cladeName;
+		}
+		if (arguments == null)
+			return null;
+		ToLProjectOpener po = new ToLProjectOpener();
+		return po.establishProject(this, arguments, pageDepth, getExtraArguments());
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+}
+
diff --git a/Source/mesquite/tol/SearchToLTaxon/32ToL.gif b/Source/mesquite/tol/SearchToLTaxon/32ToL.gif
new file mode 100644
index 0000000..1c8e15c
Binary files /dev/null and b/Source/mesquite/tol/SearchToLTaxon/32ToL.gif differ
diff --git a/Source/mesquite/tol/SearchToLTaxon/64ToL.gif b/Source/mesquite/tol/SearchToLTaxon/64ToL.gif
new file mode 100644
index 0000000..f4f99fc
Binary files /dev/null and b/Source/mesquite/tol/SearchToLTaxon/64ToL.gif differ
diff --git a/Source/mesquite/tol/SearchToLTaxon/SearchToLTaxon.java b/Source/mesquite/tol/SearchToLTaxon/SearchToLTaxon.java
new file mode 100644
index 0000000..7784109
--- /dev/null
+++ b/Source/mesquite/tol/SearchToLTaxon/SearchToLTaxon.java
@@ -0,0 +1,76 @@
+/* Mesquite (package mesquite.ornamental).  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.SearchToLTaxon;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.tol.lib.*;
+
+/* ======================================================================== */
+public class SearchToLTaxon extends BaseSearchToLTaxon {
+	/*.................................................................................................................*/
+	public String getBaseURLForUser() {
+		return "tolweb.org";
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		SearchToLTaxonToolExtra newPj = new SearchToLTaxonToolExtra(this, treeDisplay);
+		if (extras!=null)
+			extras.addElement(newPj);
+		return newPj;
+	}
+
+}
+
+/* ======================================================================== */
+class SearchToLTaxonToolExtra extends BaseSearchToLToolTaxonExtra  {
+	public SearchToLTaxonToolExtra (SearchToLTaxon ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule,treeDisplay);
+	}
+	/*.................................................................................................................*/
+	public  String getToolName() {
+		return "Go To ToL";
+	}
+	
+	public String getToolExplanation() {
+		return "This tool downloads the tree from the page of the Tree of Life Web Project for the taxon touched.";
+	}
+
+	/*.................................................................................................................*/
+	public  String getToolScriptName() {
+		return "goToToLTaxon";
+	}
+
+	/*.................................................................................................................*/
+	public String getBaseURL() {
+		return "tolweb.org";
+	}
+	/*.................................................................................................................*/
+	public String getGetToLTreeModuleName() {
+		return "GetToLTree";
+	}
+	/*.................................................................................................................*/
+	public String getBaseURLForUser() {
+		return "tolweb.org";
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/tol/SearchToLTaxon/ToL.gif b/Source/mesquite/tol/SearchToLTaxon/ToL.gif
new file mode 100644
index 0000000..bc3af03
Binary files /dev/null and b/Source/mesquite/tol/SearchToLTaxon/ToL.gif differ
diff --git a/Source/mesquite/tol/TaxonOnWebDB/32TaxonOnWeb.gif b/Source/mesquite/tol/TaxonOnWebDB/32TaxonOnWeb.gif
new file mode 100644
index 0000000..344efc8
Binary files /dev/null and b/Source/mesquite/tol/TaxonOnWebDB/32TaxonOnWeb.gif differ
diff --git a/Source/mesquite/tol/TaxonOnWebDB/64TaxonOnWeb.gif b/Source/mesquite/tol/TaxonOnWebDB/64TaxonOnWeb.gif
new file mode 100644
index 0000000..ef97e49
Binary files /dev/null and b/Source/mesquite/tol/TaxonOnWebDB/64TaxonOnWeb.gif differ
diff --git a/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWeb.gif b/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWeb.gif
new file mode 100644
index 0000000..306f631
Binary files /dev/null and b/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWeb.gif differ
diff --git a/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWebDB.java b/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWebDB.java
new file mode 100644
index 0000000..6c5c0fb
--- /dev/null
+++ b/Source/mesquite/tol/TaxonOnWebDB/TaxonOnWebDB.java
@@ -0,0 +1,195 @@
+/* Mesquite (package mesquite.ornamental).  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.TaxonOnWebDB;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.tol.lib.*;
+
+/* ======================================================================== */
+public class TaxonOnWebDB extends TreeDisplayAssistantI {
+	public Vector extras;
+	TaxonOnWebServer URLTask;
+	TaxonOnWebDBToolExtra extra;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		if (arguments ==null)
+			URLTask = (TaxonOnWebServer)hireNamedEmployee(TaxonOnWebServer.class, "#ToLURLServer");
+		else {
+			URLTask = (TaxonOnWebServer)hireNamedEmployee(TaxonOnWebServer.class, arguments);
+			if (URLTask == null)
+				URLTask = (TaxonOnWebServer)hireEmployee(TaxonOnWebServer.class, "Taxon on Web URL Provider");
+		}
+		if (URLTask == null) {
+			return sorry(getName() + " couldn't start because providing of server URL could not be obtained.");
+		}
+		
+		loadPreferences();
+
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		TaxonOnWebDBToolExtra newPj = new TaxonOnWebDBToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		extra = newPj;
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public TaxonOnWebServer getURLTask() {
+		return URLTask;
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "urlTask", "#" + URLTask.getClass().getName());
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("urlTask".equalsIgnoreCase(tag)) {
+			String URLTaskName = StringUtil.cleanXMLEscapeCharacters(content);
+			URLTask = (TaxonOnWebServer)hireNamedEmployee(TaxonOnWebServer.class, URLTaskName);
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		 if (checker.compare(this.getClass(), "Set the URL task", "[module name]", commandName, "setURLTask")) {
+			 TaxonOnWebServer temp=  (TaxonOnWebServer)replaceEmployee(TaxonOnWebServer.class, arguments, "URL Provider", URLTask);
+			if (temp!=null)
+				URLTask= temp;
+			if (extra!=null && extra.getTreeTool()!=null)
+				extra.getTreeTool().setEnabled(URLTask!=null);
+			storePreferences();
+
+			return URLTask;
+		}
+		else if (checker.compare(this.getClass(), "Present the popup menu to select options for search web tool", null, commandName, "taxonOnWebToolOptions")) {
+			if (extra==null || extra.getTreeTool()==null)
+				return null;
+			MesquiteButton button = extra.getTreeTool().getButton();
+			if (button!=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x= MesquiteInteger.fromString(arguments, io); //getting x and y from arguments
+				int y= MesquiteInteger.fromString(arguments, io);
+				MesquitePopup popup = new MesquitePopup(button);
+
+				Listable[] moduleList = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(TaxonOnWebServer.class, null, this);
+				for (int i=0; i<moduleList.length; i++) {
+					MesquiteModuleInfo m = (MesquiteModuleInfo)moduleList[i];
+					MesquiteCommand mc = makeCommand("setURLTask", this);
+					mc.setDefaultArguments(StringUtil.tokenize(m.getName()));
+					MesquiteCheckMenuItem mItem = new MesquiteCheckMenuItem(m.getName(), this, mc, null, null);
+					if (URLTask!=null)
+						mItem.set(URLTask.getName().equalsIgnoreCase(m.getName()));
+					popup.add(mItem);
+				}
+				popup.showPopup(x,y+6);
+			}
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Get Taxon's tree from a web site";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies a tool for tree windows that gets tree for taxon touched from a web site." ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+}
+
+/* ======================================================================== */
+class TaxonOnWebDBToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool taxonOnWebTool;
+	TaxonOnWebDB taxonOnWebModule;
+	MesquiteCommand taxonCommand;
+	public TaxonOnWebDBToolExtra (TaxonOnWebDB ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		taxonOnWebModule = ownerModule;
+		taxonCommand = MesquiteModule.makeCommand("goToTaxonOnWeb",  this);
+		enableTool();
+	}
+	public void enableTool(){
+		if (taxonOnWebTool == null){
+			taxonOnWebTool = new TreeTool(this, "goToTaxonOnWeb", ownerModule.getPath(), "TaxonOnWeb.gif", 4,0,"Go to Taxon on Web Site", "This tool searches for the taxon touched on a web site."); //; hold down shift to enter a URL
+			taxonOnWebTool.setTouchedTaxonCommand(taxonCommand);
+			taxonOnWebTool.setPopUpOwner(taxonOnWebModule);
+			taxonOnWebTool.setOptionsCommand(MesquiteModule.makeCommand("taxonOnWebToolOptions", taxonOnWebModule));
+
+			if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+				((MesquiteWindow)ownerModule.containerOfModule()).addTool(taxonOnWebTool);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public   TreeTool getTreeTool(){
+		return taxonOnWebTool;
+	}
+
+	
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public void goToPage(String arguments) {   // only do this if has page!
+		Tree tree = treeDisplay.getTree();
+		int M = MesquiteInteger.fromFirstToken(arguments, pos);
+		if (M<0 || !MesquiteInteger.isCombinable(M) || M>=tree.getTaxa().getNumTaxa())
+			return;
+		String s = "";
+		if (taxonOnWebModule.getURLTask()!=null)
+			s = taxonOnWebModule.getURLTask().getURL(tree.getTaxa().getTaxonName(M));
+		if (!StringUtil.blank(s))
+			MesquiteModule.showWebPage(s, true);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Gets tree for that taxon from ToLweb.org", "[taxon number][modifiers]", commandName, "goToTaxonOnWeb")) {
+			goToPage(arguments);
+		}
+		return null;
+	}
+	public void turnOff() {
+		taxonOnWebModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
diff --git a/Source/mesquite/tol/ToLURLServer/ToLURLServer.java b/Source/mesquite/tol/ToLURLServer/ToLURLServer.java
new file mode 100644
index 0000000..7e7981f
--- /dev/null
+++ b/Source/mesquite/tol/ToLURLServer/ToLURLServer.java
@@ -0,0 +1,35 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.ToLURLServer;
+
+import mesquite.lib.*;
+import mesquite.tol.lib.TaxonOnWebServer;
+
+public class ToLURLServer extends TaxonOnWebServer {
+
+	public String getURL(String taxonName) {
+		String openName = StringUtil.encodeForURL(taxonName);
+		return "http://tolweb.org/" + openName;
+	}
+
+	public String getName() {
+		return "Tree of Life Web Project";
+	}
+	
+	public String getExplanation() {
+		return "Provides a URL to a taxon on the Tree of Life Web Project";
+	}
+
+
+}
diff --git a/Source/mesquite/tol/TreeBaseURLServer/TreeBaseURLServer.java b/Source/mesquite/tol/TreeBaseURLServer/TreeBaseURLServer.java
new file mode 100644
index 0000000..8c355fa
--- /dev/null
+++ b/Source/mesquite/tol/TreeBaseURLServer/TreeBaseURLServer.java
@@ -0,0 +1,37 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.TreeBaseURLServer;
+
+	
+
+import mesquite.lib.*;
+import mesquite.tol.lib.*;
+
+public class TreeBaseURLServer extends TaxonOnWebServer {
+
+	public String getURL(String taxonName) {
+		String openName = StringUtil.encodeForURL(StringUtil.replace(taxonName,' ', '+'));
+		return "http://www.treebase.org/cgi-bin/treebase.pl?Name=" + openName + "&Submit=Taxon+Name";
+	
+	}
+
+	public String getName() {
+		return "TreeBase";
+	}
+
+	public String getExplanation() {
+		return "Provides a URL to a taxon in TreeBase";
+	}
+
+}
diff --git a/Source/mesquite/tol/aTolIntro/aTolIntro.java b/Source/mesquite/tol/aTolIntro/aTolIntro.java
new file mode 100644
index 0000000..18781e6
--- /dev/null
+++ b/Source/mesquite/tol/aTolIntro/aTolIntro.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.aTolIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aTolIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aTolIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Provides interfaces to the Tree of Life Web Project.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree of Life Web Project Interface Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Tree of Life Web Project Interface Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/tol/iSpeciesURLServer/iSpeciesURLServer.java b/Source/mesquite/tol/iSpeciesURLServer/iSpeciesURLServer.java
new file mode 100644
index 0000000..ad91898
--- /dev/null
+++ b/Source/mesquite/tol/iSpeciesURLServer/iSpeciesURLServer.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.iSpeciesURLServer;
+
+import mesquite.lib.*;
+import mesquite.tol.lib.TaxonOnWebServer;
+
+public class iSpeciesURLServer extends TaxonOnWebServer {
+
+	public String getURL(String taxonName) {
+		String openName = StringUtil.encodeForURL(StringUtil.replace(taxonName,' ', '+'));
+		return "http://darwin.zoology.gla.ac.uk/~rpage/ispecies/?q=" + openName + "&submit=Go";
+	
+	}
+
+	public String getName() {
+		return "iSpecies";
+	}
+	
+	public String getExplanation() {
+		return "Provides a URL to a taxon in iSpecies";
+	}
+
+
+}
diff --git a/Source/mesquite/tol/lib/BaseHttpRequestMaker.java b/Source/mesquite/tol/lib/BaseHttpRequestMaker.java
new file mode 100644
index 0000000..554203c
--- /dev/null
+++ b/Source/mesquite/tol/lib/BaseHttpRequestMaker.java
@@ -0,0 +1,422 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.httpclient.*;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.lang.StringEscapeUtils;
+
+import org.dom4j.*;
+import org.dom4j.io.*;
+
+import mesquite.tol.lib.*;
+import mesquite.lib.*;
+
+
+
+/**
+ * Utility class for http communication, built originally for TreeGrow 
+ * @author dmandel
+ *
+ */
+public class BaseHttpRequestMaker {
+    private static final int MAX_BYTES = 5000000;   
+
+	public static final String MESQUITE_VERSION_URI = "http://mesquiteproject.org/pyMesquiteStartup";
+
+	public static boolean contactServer(String s, String URI, StringBuffer response) {
+		HttpClient client = new HttpClient();
+		GetMethod method = new GetMethod(URI);
+		NameValuePair[] pairs = new NameValuePair[1];
+		pairs[0] = new NameValuePair("build", StringEscapeUtils.escapeHtml("\t" + s + "\tOS =\t" + System.getProperty("os.name") + "\t" + System.getProperty("os.version") + "\tjava =\t" + System.getProperty("java.version") +"\t" + System.getProperty("java.vendor")));
+		method.setQueryString(pairs);
+
+		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
+	    		new DefaultHttpMethodRetryHandler(3, false));
+		
+		return executeMethod(client, method, response);
+	}
+	public static boolean postToServer(String s, String URI, StringBuffer response) {
+		HttpClient client = new HttpClient();
+		PostMethod method = new PostMethod(URI);
+		method.addParameter("OS", StringEscapeUtils.escapeHtml(System.getProperty("os.name") + "\t" + System.getProperty("os.version")));
+		method.addParameter("JVM", StringEscapeUtils.escapeHtml(System.getProperty("java.version") +"\t" + System.getProperty("java.vendor")));
+		NameValuePair post = new NameValuePair();
+		post.setName("post");
+		post.setValue(StringEscapeUtils.escapeHtml(s));
+		method.addParameter(post);
+
+		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
+	    		new DefaultHttpMethodRetryHandler(3, false));
+		
+		return executeMethod(client, method, response);
+	}
+	public static boolean sendInfoToServer(NameValuePair[] pairs, String URI, StringBuffer response, int retryCount) {
+		HttpClient client = new HttpClient();
+		GetMethod method = new GetMethod(URI);
+		method.setQueryString(pairs);
+
+	//	if (retryCount>0)
+			method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(retryCount, false));
+		
+		return executeMethod(client, method, response);
+	}
+	public static boolean sendInfoToServer(NameValuePair[] pairs, String URI, StringBuffer response) {
+		return sendInfoToServer(pairs, URI, response, 3);
+	}
+	protected static boolean executeMethod(HttpClient client, HttpMethod method, StringBuffer response) {
+		boolean success = true;
+	    try {
+	        // Execute the method.
+	        int statusCode = client.executeMethod(method);
+
+	        if (statusCode != HttpStatus.SC_OK) {
+	          System.err.println("Method failed: " + method.getStatusLine());
+	        }
+
+	        // Read the response body.
+	        byte[] responseBody = method.getResponseBody();
+	       if (response != null)
+	    	   response.append(new String(responseBody));
+	        // Deal with the response.
+	        // Use caution: ensure correct character encoding and is not binary data
+	        System.out.println(new String(responseBody));
+
+	      } catch (HttpException e) {
+	      //  System.err.println("Fatal protocol violation: " + e.getMessage());
+	       // e.printStackTrace();
+	        success = false;
+	      } catch (IOException e) {
+	      //  System.err.println("Fatal transport error: " + e.getMessage());
+	      //  e.printStackTrace();
+	        success = false;
+	      } finally {
+	        // Release the connection.
+	        method.releaseConnection();
+	      } 		
+	        return success;
+	}
+   public static String getTap4ExternalUrlString(String prefix, String pageName, Map additionalArgs) {
+    	return getExternalUrlString(pageName, additionalArgs, prefix, null, null);
+    }
+    public static Document getTap4ExternalUrlDocument(String prefix, String pageName, Map additionalArgs) {
+    	return getTap4ExternalUrlDocument(prefix, pageName, additionalArgs, false);
+    }
+    public static Document getTap4ExternalUrlDocument(String prefix, String pageName, Map additionalArgs, boolean isPost) {
+    	if (!isPost) {
+    		String url = getTap4ExternalUrlString(prefix, pageName, additionalArgs);    		
+    		return getHttpResponseAsDocument(url);
+    	} else {
+    		String url = getTap4ExternalUrlString(prefix, pageName, null);
+    		return doPostGetDocument(url, additionalArgs);
+    	}
+    }
+    /**
+     * Execute a multipart post method to a tapestry page
+     * @param prefix The base url to open
+     * @param pageName The name of the tapestry page
+     * @param stringArgs Post arguments that have string keys and values
+     * @param fileArgs Post arguments that have string keys and file values
+     * @return
+     */
+    public static Document getTap4ExternalUrlDocumentMultipart(String prefix, String pageName, 
+    		Map stringArgs, Map fileArgs) {
+    	String url = getTap4ExternalUrlString(prefix, pageName, null);
+    	return doMultipartPostGetDocument(url, stringArgs, fileArgs);
+    }
+    public static String doPostGetString(String url, Map additionalParameters) {
+    	return new String(doPost(url, additionalParameters));
+    }
+    
+    public static Document doPostGetDocument(String url, Map additionalParameters) {
+    	byte[] response = doPost(url, additionalParameters);
+    	return getDocumentFromBytes(response);
+    }
+    
+    public static Document doMultipartPostGetDocument(String url, Map stringParams, Map fileParams) {
+    	byte[] response = doMultipartPost(url, stringParams, fileParams);
+    	return getDocumentFromBytes(response);
+    }
+    
+    public static byte[] doMultipartPost(String url, Map stringParams, Map fileParams) { 
+    	 PostMethod filePost = new PostMethod(url);
+    	 Part[] parts = new Part[stringParams.size() + fileParams.size()];
+    	 int i = 0;
+    	 if (stringParams != null) {
+    		 for (Iterator iter = stringParams.keySet().iterator(); iter.hasNext();) {
+				String nextKey = (String) iter.next();
+				String nextValue = stringParams.get(nextKey).toString();
+				parts[i++] = new StringPart(nextKey, nextValue);
+    		 }
+    	 }
+    	 if (fileParams != null) {
+    		 for (Iterator iter = fileParams.keySet().iterator(); iter.hasNext();) {
+				String nextKey = (String) iter.next();
+				File nextValue = (File) fileParams.get(nextKey);
+				try {
+					parts[i++] = new FilePart(nextKey, nextValue);
+				} catch (FileNotFoundException e) {
+					e.printStackTrace();
+				}
+			}
+    	 } 
+    	 /*System.out.println("going to post multipart to url: " + url + " with parts: " + parts);
+    	 for (int j = 0; j < parts.length; j++) {
+			Part part = parts[j];
+			System.out.println("current part is: " + part);
+		 }*/
+    	 filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()) );
+    	 //System.out.println("just set request entity");
+    	 return executePost(filePost);
+    }
+    
+    public static byte[] doPost(String url, Map additionalParameters) {
+        PostMethod xmlPost = new PostMethod(url);
+        NameValuePair[] argsArray = new NameValuePair[additionalParameters.keySet().size()];
+        int i = 0;
+        for (Iterator iter = additionalParameters.keySet().iterator(); iter.hasNext();) {
+            String nextParamName = (String) iter.next();
+            String nextValue = (String) additionalParameters.get(nextParamName);
+            argsArray[i++] = new NameValuePair(nextParamName, nextValue);
+        }
+        xmlPost.setRequestBody(argsArray);
+        return executePost(xmlPost);
+    }
+	private static byte[] executePost(PostMethod xmlPost) {
+		HttpClient client = new HttpClient();
+        client.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+        int status = -1;
+        try {
+            status = client.executeMethod(xmlPost);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        byte[] bytes = null;
+        if (status == HttpStatus.SC_OK) {
+            try {
+				bytes = xmlPost.getResponseBody();
+			} catch (IOException e) {
+				e.printStackTrace();
+				return null;
+			}
+        } else {
+        	try {
+				throw new RuntimeException("bad status is: " + status);
+			} catch (RuntimeException e) {
+				e.printStackTrace();
+			}
+            return null;
+        }
+        return bytes;
+	}
+    
+    public static String getExternalUrlString(String pageName, Map additionalArgs, String prefix, String userId, String password) {
+        String returnString = prefix;
+        returnString += pageName;
+        if (additionalArgs != null) {
+	        if (!StringUtil.blank(userId)) {
+		        if (additionalArgs.get(ToLRequestParameters.USER_ID) == null) {
+		            returnString = addParameter(returnString, ToLRequestParameters.USER_ID, URLEncoder.encode(userId));
+		        }
+		        if (additionalArgs.get(ToLRequestParameters.PASSWORD) == null) {
+		            returnString = addParameter(returnString, ToLRequestParameters.PASSWORD, password);
+		        }
+	        }
+	        returnString = addAdditionalArgsToUrl(additionalArgs, returnString);
+        }
+        return returnString;        
+    }
+	private static String addAdditionalArgsToUrl(Map additionalArgs, String returnString) {
+		for (Iterator iter = additionalArgs.keySet().iterator(); iter.hasNext();) {
+		    String key = (String) iter.next();
+		    String value = additionalArgs.get(key).toString();
+		    returnString = addParameter(returnString, key, value);
+		}
+		return returnString;
+	}
+    
+    protected static String addParameter(String originalString, String paramName, String value) {
+    	if (!StringUtil.blank(originalString)) {
+    		String separatorChar = "&";
+    		if (originalString.indexOf('?') < 0) {
+    			separatorChar = "?";
+    		}
+	        originalString += separatorChar;
+	        originalString += paramName;
+	        originalString += "=";
+	        originalString += URLEncoder.encode(value);
+	        return originalString;
+    	} else {
+    		return "";
+    	}
+    }
+    
+    public static Document getHttpResponseAsDocument(String url) {
+        byte[] bytes = makeHttpRequest(url);
+        return getDocumentFromBytes(bytes);
+    }
+    
+    public static Document getDocumentFromBytes(byte[] bytes) {
+        Document doc;
+        try {
+            doc = new SAXReader().read(new ByteArrayInputStream(bytes));
+            return doc;
+        } catch (Exception e) {
+        	System.err.println(" bad bytes are: " + new String(bytes));
+            return null;
+        }    	
+    }
+
+    public static byte[] makeHttpRequest(String url) {
+    	return makeHttpRequest(url, null, "");
+    }
+    
+    public static byte[] makeHttpRequest(String url, Credentials c, String realm) {
+        return (byte[]) makeHttpRequest(url, c, realm, true);
+    }
+
+    
+    public static Object[] makeHttpRequestAsStream(String url, Credentials c, String realm) {
+        return (Object[]) makeHttpRequest(url, c, realm, false);
+    }
+    
+    public static Object[] makeHttpRequestAsStream(String url) {
+    	return makeHttpRequestAsStream(url, null, null);
+    }
+    
+    public static Object[] makeHttpRequestAsStream(String url, Map args) {
+    	url = addAdditionalArgsToUrl(args, url);
+    	return makeHttpRequestAsStream(url);
+    }
+    
+    //public static InputStream makeHttpRequest
+    
+    /**
+     * Make the http request to the specified url
+     * @return If returnArray is true, a byte array containing the response bytes,
+     * if false, we return an ObjectArray with the first argument being an 
+     * InputStream and the second being the GetMethod that was used to make the
+     * request.  The GetMethod must have releaseConnection() called on it after
+     * all of the InputStream has been read.
+     */
+    public static Object makeHttpRequest(String url, Credentials c, String realm, boolean returnArray) {    	
+        GetMethod getMethod = new GetMethod(url);
+        Object returnValue = null;
+        HttpClient client;
+        try {
+            client = new HttpClient();
+            if (c != null) {
+            	client.getParams().setAuthenticationPreemptive(true);
+                //client.getState().set
+                //client.getState().setCredentials(new HttpAuthRealm(null, realm), c);
+                //client.getState().setCredentials(realm, null, c);
+                client.getState().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME), c);
+            }
+            int statusCode = -1;
+            // We will retry up to 3 times.
+            for (int attempt = 0; statusCode == -1 && attempt < 3; attempt++) {
+                try {
+                    // execute the method.
+                    statusCode = client.executeMethod(getMethod);
+                } catch (HttpRecoverableException e) {
+                    System.err.println("A recoverable exception occurred, retrying.  " + e.getMessage());
+                } catch (IOException e) {
+                    System.err.println("Failed to download file.");
+                    e.printStackTrace();
+                    break;
+                }
+            }
+            if (statusCode == HttpStatus.SC_OK) {
+                if (returnArray) {
+                    returnValue = getMethod.getResponseBodyAsStream();
+                    InputStream stream = (InputStream) returnValue;
+                    byte[] bytes;
+                    long contentLength = getMethod.getResponseContentLength();
+                    if (contentLength >= 0) {
+                    	bytes = new byte[(int) contentLength];
+                    }  else {
+                    	// it returned -1, so it doesn't know how long the
+                    	// length is.  We'll allocate a 5mb buffer in this case
+                        bytes = new byte[MAX_BYTES];                    	
+                    }
+                    int offset = 0;
+                    int nextByte = 0;
+                    try {
+                        while ((nextByte = stream.read()) != -1) {
+                            bytes[offset++] = (byte) nextByte;
+                        }
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    } finally {
+                        if (stream != null) {
+                            stream.close();
+                        }
+                    }
+                    byte[] newBytes = new byte[offset];
+                    System.arraycopy(bytes, 0, newBytes, 0, offset);
+                    returnValue = newBytes;
+                    // make sure these get garbage collected
+                    bytes = null;
+                } else {
+                    InputStream stream = getMethod.getResponseBodyAsStream();
+                    returnValue = new Object[] {stream, getMethod};
+                }
+            } else {
+                System.err.println("bad status code is: " + statusCode);
+                returnValue = null;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                getMethod.getResponseBody();
+            } catch (Exception e2) {
+                e2.printStackTrace();
+            } finally {
+            	if (returnArray) {
+            		getMethod.releaseConnection();
+            	}
+            }
+            returnValue = null;
+        } finally {
+        	if (returnArray) {
+                getMethod.releaseConnection();
+        	}
+        }
+        return returnValue;
+    }
+
+}
+
+
diff --git a/Source/mesquite/tol/lib/BaseSearchToLTaxon.java b/Source/mesquite/tol/lib/BaseSearchToLTaxon.java
new file mode 100644
index 0000000..2b39032
--- /dev/null
+++ b/Source/mesquite/tol/lib/BaseSearchToLTaxon.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib;
+
+import java.util.Vector;
+
+import mesquite.lib.CommandChecker;
+import mesquite.lib.TreeDisplay;
+import mesquite.lib.TreeDisplayExtra;
+import mesquite.lib.duties.TreeDisplayAssistantI;
+import mesquite.tol.lib.*;
+
+public abstract class BaseSearchToLTaxon extends TreeDisplayAssistantI {
+		public Vector extras;
+		/*.................................................................................................................*/
+		public boolean startJob(String arguments, Object condition, boolean hiredByName){
+			extras = new Vector();
+			return true;
+		} 
+		
+		/*.................................................................................................................*/
+		public abstract String getBaseURLForUser();
+
+
+		/*.................................................................................................................*/
+		public String getName() {
+			return "Get Taxon's tree from "+getBaseURLForUser();
+		}
+		
+		/*.................................................................................................................*/
+		public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+			if (checker.compare(this.getClass(), "Turns on tools", null, commandName, "enableTools")) {
+				for (int i=0; i<extras.size(); i++){
+					BaseSearchToLToolTaxonExtra e = (BaseSearchToLToolTaxonExtra)extras.elementAt(i);
+					e.enableTool();
+				}
+			}
+			else
+				return  super.doCommand(commandName, arguments, checker);
+			return null;
+		}
+
+
+		/*.................................................................................................................*/
+		/** returns an explanation of what the module does.*/
+		public String getExplanation() {
+			return "Supplies a tool for tree windows that gets tree for taxon touched from "+getBaseURLForUser();
+		}
+		public boolean isSubstantive(){
+			return false;
+		}   	 
+	}
diff --git a/Source/mesquite/tol/lib/BaseSearchToLToolTaxonExtra.java b/Source/mesquite/tol/lib/BaseSearchToLToolTaxonExtra.java
new file mode 100644
index 0000000..2840c85
--- /dev/null
+++ b/Source/mesquite/tol/lib/BaseSearchToLToolTaxonExtra.java
@@ -0,0 +1,129 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib;
+
+import java.awt.Graphics;
+
+import mesquite.lib.CommandChecker;
+import mesquite.lib.Commandable;
+import mesquite.lib.MesquiteBoolean;
+import mesquite.lib.MesquiteCommand;
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteModule;
+import mesquite.lib.MesquiteWindow;
+import mesquite.lib.NameReference;
+import mesquite.lib.ParseUtil;
+import mesquite.lib.Puppeteer;
+import mesquite.lib.Taxa;
+import mesquite.lib.Tree;
+import mesquite.lib.TreeDisplay;
+import mesquite.lib.TreeDisplayExtra;
+import mesquite.lib.TreeTool;
+import mesquite.tol.lib.*;
+
+public abstract class BaseSearchToLToolTaxonExtra  extends TreeDisplayExtra implements Commandable  {
+		TreeTool tolTool;
+		BaseSearchToLTaxon taxonToLModule;
+		MesquiteCommand taxonCommand;
+		NameReference tolLeavesNameRef = NameReference.getNameReference("ToLLeaves");
+		NameReference tolHasChildrenNameRef = NameReference.getNameReference("ToLHasChildren");
+		public BaseSearchToLToolTaxonExtra (BaseSearchToLTaxon ownerModule, TreeDisplay treeDisplay) {
+			super(ownerModule, treeDisplay);
+			taxonToLModule = ownerModule;
+			taxonCommand = MesquiteModule.makeCommand("goToToLTaxon",  this);
+		}
+		public void enableTool(){
+			if (tolTool == null){
+				tolTool = new TreeTool(this, getToolScriptName(), ownerModule.getPath(), "ToL.gif", 4,0,getToolName(), getToolExplanation()); //; hold down shift to enter a URL
+				tolTool.setTouchedTaxonCommand(taxonCommand);
+
+				if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+					((MesquiteWindow)ownerModule.containerOfModule()).addTool(tolTool);
+				}
+			}
+		}
+		/*.................................................................................................................*/
+		public abstract String getToolName() ;
+		/*.................................................................................................................*/
+		public abstract String getToolScriptName() ;
+		/*.................................................................................................................*/
+		public abstract String getToolExplanation() ;
+		/*.................................................................................................................*/
+		public abstract String getBaseURL() ;
+		/*.................................................................................................................*/
+		public abstract String getGetToLTreeModuleName() ;
+		/*.................................................................................................................*/
+		public abstract String getBaseURLForUser() ;
+		/*.................................................................................................................*/
+		public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		}
+
+		/*.................................................................................................................*/
+		public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+			drawOnTree(tree, drawnRoot, g);
+		}
+		/*.................................................................................................................*/
+		public   void setTree(Tree tree) {
+		}
+		MesquiteInteger pos = new MesquiteInteger();
+		/*.................................................................................................................*/
+		public boolean hasDescendants(Taxa taxa, int taxonNumber){
+			boolean children = true;
+			MesquiteBoolean n = (MesquiteBoolean)taxa.getAssociatedObject(tolHasChildrenNameRef, taxonNumber);
+			if (n !=null)
+				children=n.getValue();
+			return children;   // test if it is a leaf etc. 
+		}
+		/*.................................................................................................................*/
+		public void goToToLPage(String arguments) {   // only do this if has page!
+			Tree tree = treeDisplay.getTree();
+			int M = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (M<0 || !MesquiteInteger.isCombinable(M) || M>=tree.getTaxa().getNumTaxa())
+				return;
+			String openName = ParseUtil.tokenize(tree.getTaxa().getTaxonName(M));
+			String s = "http://" +getBaseURL() + "/" + openName;
+			MesquiteModule.showWebPage(s, true);
+		}
+		/*.................................................................................................................*/
+		public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+			if (checker.compare(this.getClass(), "Gets tree for that taxon from "+getBaseURLForUser(), "[taxon number][modifiers]", commandName, "goToToLTaxon")) {
+				Tree tree = treeDisplay.getTree();
+				int M = MesquiteInteger.fromFirstToken(arguments, pos);
+				if (M<0 || !MesquiteInteger.isCombinable(M) || M>=tree.getTaxa().getNumTaxa())
+					return null;
+				if (!hasDescendants(tree.getTaxa(), M)) 
+					return null;
+				while (ownerModule.getProject().developing)
+					;
+				String openName = ParseUtil.tokenize(tree.getTaxa().getTaxonName(M));
+				String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; openGeneral #" + getGetToLTreeModuleName() +" " + openName;
+				commands +=  "; ifNotExists It;  showAbout; endIf; windowAutoShow *String.was; endTell;";
+
+				//String commands = "newThread; getProjectID; Integer.id *It; tell Mesquite; getWindowAutoShow; String.was *It; windowAutoShow off; closeProjectByID *Integer.id; " + openCommand;
+				//commands +=  StringUtil.tokenize(MesquiteFile.composePath(getProject().getHomeDirectoryName(), nextProjectName)) + "; ifNotExists It;  debug; showAbout; endIf; windowAutoShow *String.was; endTell;";
+
+
+				Puppeteer p = new Puppeteer(ownerModule);
+				MesquiteInteger pos = new MesquiteInteger(0);
+				p.execute(ownerModule.getFileCoordinator(), commands, pos, "", false);
+				ownerModule.iQuit();
+			}
+			return null;
+		}
+		public void turnOff() {
+			taxonToLModule.extras.removeElement(this);
+			super.turnOff();
+		}
+	}
diff --git a/Source/mesquite/tol/lib/MesquiteXMLToLUtilities.java b/Source/mesquite/tol/lib/MesquiteXMLToLUtilities.java
new file mode 100644
index 0000000..277df6d
--- /dev/null
+++ b/Source/mesquite/tol/lib/MesquiteXMLToLUtilities.java
@@ -0,0 +1,50 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib;
+
+import mesquite.lib.MesquiteXMLUtilities;
+
+public class MesquiteXMLToLUtilities extends MesquiteXMLUtilities {
+	private static final String APP_URL = "onlinecontributors/app";
+
+	public static String getTOLBaseDatabaseURL(String URL) {
+		// make sure it starts with the proper protocol
+		if (!URL.startsWith(HTTP)) {
+			URL = HTTP + URL; 
+		}
+		// check to see if it ends in a slash
+		if (!URL.endsWith("/")) {
+			URL += "/";
+		}
+		URL += APP_URL;
+		//baseDatabaseURL = URL;
+		//databaseURL = baseDatabaseURL + "?page=";
+		return URL ;
+	}
+	public static String getTOLPageDatabaseURL(String URL) {
+		// make sure it starts with the proper protocol
+		if (!URL.startsWith(HTTP)) {
+			URL = HTTP + URL; 
+		}
+		// check to see if it ends in a slash
+		if (!URL.endsWith("/")) {
+			URL += "/";
+		}
+		URL += APP_URL;
+		//baseDatabaseURL = URL;
+		//databaseURL = baseDatabaseURL + "?page=";
+		return URL + "?page=";
+	}
+
+}
diff --git a/Source/mesquite/tol/lib/TaxonOnWebServer.java b/Source/mesquite/tol/lib/TaxonOnWebServer.java
new file mode 100644
index 0000000..71e07bd
--- /dev/null
+++ b/Source/mesquite/tol/lib/TaxonOnWebServer.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib; 
+
+import mesquite.lib.*;
+
+
+
+/* ======================================================================== */
+/**.*/
+public abstract class TaxonOnWebServer extends MesquiteModule  {
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+/*.................................................................................................................*/
+	public Class getDutyClass() {
+		return TaxonOnWebServer.class;
+	}
+	public String getDutyName() {
+		return "Taxon On Web Server";
+	}
+  	 public String[] getDefaultModule() {
+    	 	return new String[] {"#ToLURLServer"};
+    	 }
+
+  	 
+	/*.................................................................................................................*/
+	public abstract  String getURL(String taxonName);
+	
+	
+	
+}
+
diff --git a/Source/mesquite/tol/lib/ToLProjectOpener.java b/Source/mesquite/tol/lib/ToLProjectOpener.java
new file mode 100644
index 0000000..e239861
--- /dev/null
+++ b/Source/mesquite/tol/lib/ToLProjectOpener.java
@@ -0,0 +1,189 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.tol.lib;
+
+/*~~  */
+
+import java.net.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import org.dom4j.*;
+
+public class ToLProjectOpener  {
+
+	public static final String GROUP_SEARCH_SRV_URL = "/onlinecontributors/app?service=external&page=xml/GroupSearchService&group=";
+	public static final String TREE_STRUCTURE_SRV_URL = "/onlinecontributors/app?service=external&page=xml/TreeStructureService";
+	
+	/*.................................................................................................................*/
+	public String getBaseURL() {
+		return "http://tolweb.org";
+	}
+	/*.................................................................................................................*/
+	public String getToolModule() {
+		return "mesquite.tol.SearchToLTaxon.SearchToLTaxon";
+	}
+	/*.................................................................................................................*/
+	public String getTreeDrawingModule() {
+		return "mesquite.trees.SquareTree.SquareTree";
+	}
+
+	/*.................................................................................................................*/
+	public String getSetToolScript() {
+		return "setTool mesquite.tol.SearchToLTaxon.SearchToLTaxonToolExtra.goToToLTaxon";
+	}
+	
+	/*.................................................................................................................*/
+	public MesquiteProject establishProject(MesquiteModule ownerModule, String arguments, int pageDepth, String extraArguments){
+		FileCoordinator fileCoord = ownerModule.getFileCoordinator();
+		MesquiteFile thisFile = new MesquiteFile();		
+		
+		// the tol web services requires us to look up the nodeId via the Group Search before getting the tree structure
+		int nodeId = retrieveNodeIdFromGroupSearchResults(arguments, ownerModule);
+		
+		// if a nodeId was not found, nodeId < 0 is true
+		// TODO handle the case when we fail to retrieve the nodeId from the group search service 
+		
+		String treeServiceURL = getBaseURL() + TREE_STRUCTURE_SRV_URL;
+		if (MesquiteInteger.isCombinable(pageDepth)&& pageDepth>0)
+			treeServiceURL += "&page_depth=" + pageDepth;
+		treeServiceURL += "&node_id=" +  nodeId;
+		if (StringUtil.notEmpty(extraArguments))
+			treeServiceURL += extraArguments;
+		MesquiteMessage.println("Request to the Tree of Life Web Project for the following URL:\n"+ treeServiceURL + "\n");
+		
+		// verifyURLValid wraps the MesquiteFile call that was here previously
+		thisFile = verifyURLValid(treeServiceURL, arguments, ownerModule);
+		
+		if (thisFile == null) {
+			// if verifyURLValid failed, the Exception will already be reported through the owner-module and the debugg output
+			MesquiteMessage.println("URL for request for tree from ToL not valid");
+			return null;
+		}
+	
+		
+		Element root = XMLUtil.getRootXMLElementFromURL(treeServiceURL);
+		// if call fails, the exception will likely be reported twice 
+		if (root == null) {
+			ownerModule.discreetAlert( "Sorry, no tree was obtained from the database");
+			return null;
+		}
+		
+		int numTaxa = ToLUtil.countTerminals(root, "  ");
+		if (numTaxa == 0) {
+			ownerModule.discreetAlert( "Sorry, no tree was obtained from the database");
+			return null;
+		}	
+
+		//looks as if tree was recovered properly; prepare project
+		MesquiteProject p = fileCoord.initiateProject(thisFile.getFileName(), thisFile);
+		MesquiteFile sf = CommandRecord.getScriptingFileS();
+		if (MesquiteThread.isScripting())
+			CommandRecord.setScriptingFileS(thisFile);
+
+		//getting taxon names & building Taxa block
+		String[] names= new String[numTaxa];
+		boolean[] leaves = new boolean[numTaxa];
+		boolean[] hasChildren = new boolean[numTaxa];
+		ToLUtil.getTerminals(root, names, leaves, hasChildren, new MesquiteString(), new MesquiteInteger(0));
+		TaxaManager taxaTask = (TaxaManager)ownerModule.findElementManager(Taxa.class);
+		Taxa taxa = taxaTask.makeNewTaxa("Taxa from ToL", numTaxa, false);
+		NameReference notesRef = NameReference.getNameReference("notes");
+//		NameReference leavesRef = NameReference.getNameReference("ToLLeaves");
+//		NameReference hasChildrenRef = NameReference.getNameReference("ToLHadChildren");
+		for (int i = 0; i<numTaxa; i++){
+			Taxon t = taxa.getTaxon(i);
+			t.setName(names[i]);
+			//taxa.setAnnotation(i, names[i]);				
+			//AttachedNotesVector attachedNotes = new AttachedNotesVector(taxa);
+			//AttachedNote newNote = new AttachedNote();
+			//newNote.setAuthor("tolweb.org");
+			//newNote.setComment(names[i], true);
+			//attachedNotes.addNote(newNote, true);
+			taxa.setAssociatedObject(NameReference.getNameReference("ToLLeaves"), i, new MesquiteBoolean(leaves[i]));
+			taxa.setAssociatedObject(NameReference.getNameReference("ToLHasChildren"), i, new MesquiteBoolean(hasChildren[i]));
+		}
+		taxa.addToFile(thisFile, p, taxaTask);
+
+		//getting tree structure
+		MesquiteTree tree = new MesquiteTree(taxa);
+		ToLUtil.buildTree(true,root, tree, tree.getRoot(), names, new MesquiteInteger(0));
+		tree.setName("Tree for " + arguments);
+		TreeVector trees = new TreeVector(taxa);
+		trees.addElement(tree, false);
+		trees.addToFile(thisFile,p,ownerModule.findElementManager(TreeVector.class));	
+		trees.setName("Trees for " + arguments);
+
+		//cleaning up and scripting the windows to show the tree
+		CommandRecord.setScriptingFileS(sf);
+
+		MesquiteModule treeWindowCoord = ownerModule.getFileCoordinator().findEmployeeWithName("#BasicTreeWindowCoord");
+		if (treeWindowCoord!=null){
+			String commands = "makeTreeWindow " + p.getTaxaReference(taxa) + "  #BasicTreeWindowMaker; tell It; ";
+			commands += "getEmployee #" + getToolModule() + "; tell It; enableTools; endTell;";
+			commands += "setTreeSource  #StoredTrees; tell It; setTaxa " + p.getTaxaReference(taxa) + " ;  setTreeBlock 1; endTell; ";
+			commands += "getTreeDrawCoordinator #mesquite.trees.BasicTreeDrawCoordinator.BasicTreeDrawCoordinator;";
+			commands += "tell It; suppress; setTreeDrawer  #" + getTreeDrawingModule()+"; tell It; orientRight; endTell; desuppress; endTell;";
+			commands += "getWindow; tell It; setActive; setSize 600 600; getToolPalette; tell It; " + getSetToolScript()+ "; endTell; endTell;";
+			commands += "  showWindow; endTell; ";
+			MesquiteInteger pos = new MesquiteInteger(0);
+			Puppeteer pup = new Puppeteer(ownerModule);
+			CommandRecord oldCR = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(new CommandRecord(true));
+			pup.execute(treeWindowCoord, commands, pos, null, false);
+			MesquiteThread.setCurrentCommandRecord(oldCR);
+		}
+		return p;
+	}
+
+	/*--------------------------*/
+	private int retrieveNodeIdFromGroupSearchResults(String groupName, MesquiteModule ownerModule) {
+		String serviceURL = getBaseURL() + GROUP_SEARCH_SRV_URL + groupName;
+		MesquiteFile theFile = verifyURLValid(serviceURL, groupName, ownerModule);
+		if (theFile == null) {
+			return Integer.MIN_VALUE;
+		}
+		Element root = XMLUtil.getRootXMLElementFromURL(serviceURL);
+		try {
+			int count = Integer.parseInt(root.attributeValue("COUNT"));
+			if (count == 1) {
+				Element element = (Element)root.elements().get(0);
+				return Integer.parseInt(element.attributeValue("ID"));
+				//return Integer.parseInt(((Element)root.getChildren().get(0)).getAttributeValue("ID"));
+			} else {
+				return Integer.MIN_VALUE;
+			}
+		} catch (Exception e) {
+			ownerModule.discreetAlert("Sorry, the Group ID Service appears to have failed");
+			MesquiteMessage.println("Exception " + e);
+			return Integer.MIN_VALUE;
+		}
+	}
+	/*--------------------------*/
+	private MesquiteFile verifyURLValid(String url, String groupName, MesquiteModule ownerModule) {
+		MesquiteFile theFile = new MesquiteFile();
+	
+		//the following shouldn't be needed but reflects inertia in the MesquiteFile class
+		try {
+			theFile.setLocs(false, new URL(url), groupName, null);
+			return theFile;
+		}
+		catch (MalformedURLException e){
+			ownerModule.discreetAlert( "Sorry, the URL appears malformed");
+			return null;
+		}		
+	}
+	/*--------------------------*/
+}
+
diff --git a/Source/mesquite/tol/lib/ToLRequestParameters.java b/Source/mesquite/tol/lib/ToLRequestParameters.java
new file mode 100644
index 0000000..06f3bc6
--- /dev/null
+++ b/Source/mesquite/tol/lib/ToLRequestParameters.java
@@ -0,0 +1,91 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*
+ * Created on Nov 8, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package mesquite.tol.lib;
+
+/**
+ * @author dmandel
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface ToLRequestParameters {
+    public static final String CHECKED_IDS = "checked_ids";
+    public static final String OPTYPE = "optype";
+    public static final String USER_VALIDATION = "user_validation";
+    public static final String EDITING_ROOTNODE_ID = "editing_rootnode_id";
+    public static final String USER_ID = "user_id";
+    public static final String PASSWORD = "password";
+    public static final String NEW_PASSWORD = "new_password";
+    public static final String BATCH_ID = "batch_id";
+    public static final String DOWNLOAD_ID = "download_id";
+    public static final String ROOTNODE_ID = "root_node_id";
+    public static final String FETCH_SUBTREE = "fetch_subtree";
+    public static final String FROM_EDITOR = "from_editor";
+    public static final String NODE_ID = "node_id";
+    public static final String GROUP = "group";
+    public static final String EXACT = "exact";
+    public static final String VERBOSITY = "verbosity";
+    public static final String COMPLETE = "complete";
+    public static final String SKELETAL = "skeletal";
+    public static final String DEPTH = "depth";
+    public static final String XML = "xml";
+    public static final String IMAGE_ID = "image_id";
+    public static final String UNSUBMIT = "unsubmit";
+    public static final String CURRENT_DOWNLOAD = "current_download";
+    public static final String CHECKED_OUT_FILES = "checked_out_files";
+    public static final String SEARCH_CONTRIBUTORS = "search_contributors";
+    public static final String FIRST_NAME = "first_name";
+    public static final String SURNAME = "surname";
+    public static final String EMAIL = "email";
+    public static final String ADDRESS = "address";
+    public static final String INSTITUTION = "institution";
+    public static final String FILENAME = "filename";
+    public static final String SCIENTIFIC_NAME = "sciname";
+    public static final String NODE_NAME = "nodename";
+    public static final String COPYOWNER = "copyowner";
+    public static final String CONTRIBUTOR_ID = "contributor_id";
+    public static final String SEARCH_IMAGES = "search_images";
+    public static final String CHECKOUT_CONTRIBUTOR = "checkout_contributor";
+    public static final String CHECKIN = "checkin";
+    public static final String PAGE_ID = "page_id";
+    public static final String TITLE_ILLUSTRATIONS = "title_illustrations";
+    public static final String NODE_IMAGES = "node_images";
+    public static final String UPLOAD_BATCH = "upload_batch";
+    public static final String ACC_PAGES = "accessory_pages";
+    public static final String NODES_WITH_PAGES = "nodes_with_pages";
+    public static final String OPEN_SUBGROUPS = "open_subgroups";
+    public static final String EMAIL_UPLOAD_PROBLEM = "email_upload_problem";
+    public static final String ERROR_MESSAGE = "error_message";
+    public static final String TREEGROW_VERSION = "tgv";
+    public static final String ACCESSORY_PAGE_ID = "acc_page_id";
+    public static final String SOURCE_DB = "source_db";
+    public static final String PROJECT_ID = "project_id";
+    public static final String NO_TREE = "no_tree";
+    public static final String LIMIT_RESPONSE = "single_page";
+    public static final String NAME = "name";
+    public static final String DESCRIPTION = "description";
+    public static final String TAXON = "taxon";
+    public static final String USE_WORKING = "use_working";
+    public static final String PAGE_DEPTH = "page_depth";
+    public static final String FILE = "file";
+
+}
+
+
diff --git a/Source/mesquite/tol/lib/ToLUtil.java b/Source/mesquite/tol/lib/ToLUtil.java
new file mode 100644
index 0000000..6a8e0b8
--- /dev/null
+++ b/Source/mesquite/tol/lib/ToLUtil.java
@@ -0,0 +1,207 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.tol.lib;
+
+import java.util.Iterator;
+import java.util.List;
+
+import mesquite.lib.MesquiteInteger;
+import mesquite.lib.MesquiteString;
+import mesquite.lib.MesquiteTree;
+import mesquite.lib.Taxa;
+
+import org.dom4j.*;
+
+public class ToLUtil {
+
+	/*--------------------------*/
+	public static int countTerminals(Element element, String spacer) {
+		boolean isNode = isNode(element);
+		List children = element.content();
+		Iterator iterator = children.iterator();
+		int terms = 0;
+		while (iterator.hasNext()) {
+			Object o = iterator.next();
+			if (o instanceof Element) {
+				Element e = (Element)o;
+				if (isContinuable(e))
+					terms += countTerminals(e, spacer + "   ");
+			}
+		}
+		if (isNode && terms == 0) {
+			return 1;
+		}
+		else  {
+			return terms;
+		}
+
+	}  
+	
+	/* Node Attributes
+	 *       <NODE EXTINCT="0" ID="8882" CONFIDENCE="0" PHYLESIS="0" LEAF="0" HASPAGE="1" ITALICIZENAME="0" INCOMPLETESUBGROUPS="0" SHOWAUTHORITY="0" SHOWAUTHORITYCONTAINING="0" IS_NEW_COMBINATION="0" COMBINATION_DATE="null">
+
+	 * 
+	 */
+	  /*--------------------------*/
+	public static boolean isLeaf(Element element){
+		if (!isNode(element))
+			return false;
+		Attribute leafAttribute = element.attribute("LEAF");
+		try { 
+			return leafAttribute.getValue().equals("1");
+		}
+		catch (Exception e) {
+			return false;
+		}
+	}
+	  /*--------------------------*/
+	public static boolean hasChildren(Element element){
+		if (!isNode(element))
+			return false;
+		Attribute childcountAttribute = element.attribute("CHILDCOUNT");
+		try { 
+			return MesquiteInteger.fromString(childcountAttribute.getValue()) > 0; 
+		}
+		catch (Exception e) {
+			return false;
+		}
+	}
+	/*--------------------------*/
+	static boolean isNode(Element element){
+		return "Node".equalsIgnoreCase(element.getName());
+	}
+	static boolean isAncestor(Element element){
+		return "Ancestor".equalsIgnoreCase(element.getName()) || "Ancestors".equalsIgnoreCase(element.getName()) || "Ancestors_INFO".equalsIgnoreCase(element.getName());
+	}
+	static boolean isContinuable(Element element){
+		return "TREE".equalsIgnoreCase(element.getName())|| "NAME".equalsIgnoreCase(element.getName()) || "NODES".equalsIgnoreCase(element.getName()) || "NODE".equalsIgnoreCase(element.getName());
+	}
+	static boolean isName(Element element) {
+		//return XMLConstants.NAME.equalsIgnoreCase(element.getName());
+		return "Name".equalsIgnoreCase(element.getName());
+	}
+	/*--------------------------*/
+	public static int getTerminals(Element element, String[] names, boolean[] leaves, boolean[] hasChildren, MesquiteString termName, MesquiteInteger c) {
+		boolean isNode = isNode(element);
+		boolean isName = "Name".equalsIgnoreCase(element.getName());
+		List children = element.content();
+		Iterator iterator = children.iterator();
+		int terms = 0;
+		while (iterator.hasNext()) {
+			Object o = iterator.next();
+			if (isName){
+				if (o instanceof CDATA) {
+					termName.setValue(((CDATA)o).getText());
+				}
+			}
+			else if (o instanceof Element) {
+				Element e = (Element)o;
+				if (isContinuable(e))
+					terms += getTerminals((Element) o, names, leaves,hasChildren, termName, c);
+			}
+		}
+		if (isNode && terms == 0) {
+
+			names[c.getValue()] =  new String(termName.getValue()); //element.getAttributeValue("NAME");
+			if (isLeaf(element))
+				leaves[c.getValue()] = true;
+			else
+				leaves[c.getValue()] = false;
+			if (hasChildren(element))
+				hasChildren[c.getValue()] = true;
+			else
+				hasChildren[c.getValue()] = false;
+			c.increment();
+			return 1;
+		}
+		else 
+			return terms;
+
+	}  
+	/*--------------------------*/
+	public static int getTerminalsWithAuthors(Element element, String[] names, String[] authors, boolean[] leaves, boolean[] hasChildren, MesquiteString termName,MesquiteString authorName, MesquiteInteger c) {
+		boolean isNode = isNode(element);
+		boolean isName = "Name".equalsIgnoreCase(element.getName());
+		boolean isAuthor = "Authority".equalsIgnoreCase(element.getName());
+		List children = element.content();
+		Iterator iterator = children.iterator();
+		int terms = 0;
+		while (iterator.hasNext()) {
+			Object o = iterator.next();
+			if (isName){
+				if (o instanceof CDATA) {
+					termName.setValue(((CDATA)o).getText());
+				}
+			}
+			else if (isAuthor){
+				if (o instanceof CDATA) {
+					authorName.setValue(((CDATA)o).getText());
+				}
+			}
+			else if (o instanceof Element) {
+				Element e = (Element)o;
+				if (isContinuable(e))
+					terms += getTerminals((Element) o, names, leaves,hasChildren, termName, c);
+			}
+		}
+		if (isNode && terms == 0) {
+
+			names[c.getValue()] =  new String(termName.getValue()); //element.getAttributeValue("NAME");
+			authors[c.getValue()] =  new String(authorName.getValue()); //element.getAttributeValue("NAME");
+			if (isLeaf(element))
+				leaves[c.getValue()] = true;
+			else
+				leaves[c.getValue()] = false;
+			if (hasChildren(element))
+				hasChildren[c.getValue()] = true;
+			else
+				hasChildren[c.getValue()] = false;
+			c.increment();
+			return 1;
+		}
+		else 
+			return terms;
+
+	}  
+
+	public static void buildTree(boolean isRoot, Element element, MesquiteTree tree, int node, String[] names, MesquiteInteger c) {
+		if (ToLUtil.countTerminals(element, "  ") == 1 && ToLUtil.isNode(element)) {
+			tree.setTaxonNumber(node, c.getValue(), false); //StringArray.indexOf(names, element.getAttributeValue("NAME")), false);
+			Taxa taxa = tree.getTaxa();
+			c.increment();
+		}
+		else {
+			List children = element.content();
+			Iterator iterator = children.iterator();
+			while (iterator.hasNext()) {
+				Object o = iterator.next();
+				if (o instanceof Element) {
+					Element e = (Element)o;
+					if (ToLUtil.isNode(e)){ // is a node
+						if (isRoot){
+							isRoot = false;
+							buildTree(isRoot,(Element) o, tree, node, names, c);
+						}
+						else
+							buildTree(isRoot,(Element) o, tree, tree.sproutDaughter(node, false), names, c);
+					}
+					else if (ToLUtil.isContinuable(e))
+						buildTree(isRoot,(Element) o, tree, node, names, c);
+				}
+			}
+		}
+
+	}
+
+}
diff --git a/Source/mesquite/tol/lib/XMLConstants.java b/Source/mesquite/tol/lib/XMLConstants.java
new file mode 100644
index 0000000..36f0840
--- /dev/null
+++ b/Source/mesquite/tol/lib/XMLConstants.java
@@ -0,0 +1,399 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+/*
+ * XMLConstants.java
+ *
+ * Created on June 20, 2003, 8:09 AM
+ */
+
+package mesquite.tol.lib;
+
+/**
+ * Constants interface that has the names of XML tags and attributes for the ToL Project
+ * @author dmandel
+ *
+ */
+public interface XMLConstants {
+    public static final String OTHER_ACTIVE_DOWNLOAD = "OTHER_ACTIVE_DOWNLOAD";
+    public static final String CHARSET_NAME = "ISO-8859-1";
+    public static final String DONTPUBLISH = "DONTPUBLISH";
+    public static final String DONTPUBLISHCHANGED = "DONTPUBLISHCHANGED";    
+	public static final String ISEDITOR = "ISEDITOR";
+    public static final String DOWNLOADS = "DOWNLOADS";
+    public static final String DOWNLOAD_ID = "DOWNLOAD_ID";
+    public static final String TREESTRUCTURE = "TREESTRUCTURE";
+    public static final String FILENAME = "FILENAME";
+    public static final String NODEID = "NODEID";
+    public static final String NODES = "NODES";
+    public static final String NODE = "NODE";
+    public static final String NAME = "NAME";
+    public static final String NAMECOMMENT = "NAMECOMMENT";
+    public static final String FIRSTNAME = "FIRSTNAME";
+    public static final String LASTNAME = "LASTNAME";
+    public static final String NAMECHANGED = "NAMECHANGED";
+    public static final String TRUE = "TRUE";
+    public static final String FALSE = "FALSE";
+    public static final String ID = "ID";
+    public static final String LOCKED = "LOCKED";
+    public static final String ONE = "1";
+    public static final String ZERO = "0";
+    public static final String LOCK_INFO = "LOCK_INFO";
+    public static final String TIMESTAMP = "TIMESTAMP";
+    public static final String IPADDR = "IPADDR";
+    public static final String DATE_TIME = "DATE_TIME";
+    public static final String USER = "USER";
+    public static final String TYPE = "TYPE";
+    public static final String EXTINCT = "EXTINCT";
+    public static final String EXTINCTCHANGED = "EXTINCTCHANGED";
+    public static final String CONFIDENCE = "CONFIDENCE";
+    public static final String CONFIDENCECHANGED = "CONFIDENCECHANGED";
+    public static final String PHYLESIS = "PHYLESIS";
+    public static final String PHYLESISCHANGED = "PHYLESISCHANGED";
+    public static final String LEAF = "LEAF";
+    public static final String LEAFCHANGED = "LEAFCHANGED";
+    public static final String NODERANK = "NODERANK";
+    public static final String NODERANKCHANGED = "NODERANKCHANGED";
+    public static final String PAGE = "PAGE";
+    public static final String PAGES = "PAGES";
+    public static final String PAGECHANGED = "PAGECHANGED";
+    public static final String DESCRIPTION = "DESCRIPTION";
+    public static final String DESCRIPTIONCHANGED = "DESCRIPTIONCHANGED";
+    public static final String OTHERNAMES = "OTHERNAMES";
+    public static final String OTHERNAMESCHANGED = "OTHERNAMESCHANGED";
+    public static final String OTHERNAME = "OTHERNAME";
+    public static final String ISLABEL = "ISLABEL";
+    public static final String CHILDRENCHANGED = "CHILDRENCHANGED";
+    public static final String FIRSTONLINECHANGED = "FIRSTONLINECHANGED";
+    public static final String FIRSTONLINE = "FIRSTONLINE";
+    public static final String OPTIONSCHANGED = "OPTIONSCHANGED";
+    public static final String OPTIONS = "OPTIONS";
+    public static final String STATUS = "STATUS";
+    public static final String STATUSCHANGED = "STATUSCHANGED";
+    public static final String WRITEASLIST = "WRITEASLIST";
+    public static final String WRITECHANGED = "WRITECHANGED";
+    public static final String GENBANKCHANGED = "GENBANKCHANGED";
+    public static final String GENBANK = "GENBANK";
+    public static final String TREEBASECHANGED = "TREEBASECHANGED";
+    public static final String TREEBASE = "TREEBASE";
+    public static final String TITLECHANGED = "TITLECHANGED";
+    public static final String TITLE = "TITLE";
+    public static final String SUBTITLECHANGED = "SUBTITLECHANGED";
+    public static final String SUBTITLE = "SUBTITLE";
+    public static final String PRETREETEXTCHANGED = "PRETREETEXTCHANGED";
+    public static final String PRETREETEXT = "PRETREETEXT";
+    public static final String POSTTREETEXTCHANGED = "POSTTREETEXTCHANGED";
+    public static final String POSTTREETEXT = "POSTTREETEXT";
+    public static final String IMGCAPTIONCHANGED = "IMGCAPTIONCHANGED";
+    public static final String IMGCAPTION = "IMGCAPTION";
+    public static final String TAGGED_IMGCAPTIONCHANGED = "TAGGED_IMGCAPTIONCHANGED";
+    public static final String TAGGED_IMGCAPTION = "TAGGED_IMGCAPTION";
+    public static final String ACKSCHANGED = "ACKSCHANGED";
+    public static final String ACKS = "ACKS";
+    public static final String CONTENTCHANGEDDATECHANGED = "CONTENTCHANGEDDATECHANGED";
+    public static final String CONTENTCHANGEDDATE = "CONTENTCHANGEDDATE";
+    public static final String COPYRIGHTCHANGED = "COPYRIGHTCHANGED";
+    public static final String COPYRIGHT = "COPYRIGHT";
+    public static final String COPYRIGHTOWNER = "COPYRIGHTOWNER";
+    public static final String COPYRIGHTURL = "COPYRIGHTURL";
+    public static final String COPYRIGHTEMAIL = "COPYRIGHTEMAIL";
+    public static final String COPYRIGHTDATE = "COPYRIGHTDATE";    
+    public static final String DATE = "DATE";
+    public static final String DATECHANGED = "DATECHANGED";
+    public static final String HOLDER = "HOLDER";
+    public static final String HOLDERCHANGED = "HOLDERCHANGED";
+    public static final String IMAGECHANGED = "IMAGECHANGED";
+    public static final String IMAGELIST = "IMAGELIST";
+    public static final String IMAGE = "IMAGE";
+    public static final String IMAGES = "IMAGES";   
+    public static final String FOSSIL = "FOSSIL";
+    public static final String SEX = "SEX";
+    public static final String COLLECTIONDATE = "COLLECTIONDATE";
+    public static final String COLLECTION = "COLLECTION";
+    public static final String COLLECTIONAC = "COLLECTIONAC";
+    public static final String LOCATION = "LOCATION";
+    public static final String GEOLOCATION = "GEOLOCATION";
+    public static final String CAPTION = "CAPTION";
+    public static final String SCIENTIFICNAME = "SCIENTIFICNAME";
+    public static final String SCIENTIFICNAMETWO = "SCIENTIFICNAMETWO";
+    public static final String COMMONNAME = "COMMONNAME";
+    public static final String COMMONNAMETWO = "COMMONNAMETWO";    
+    public static final String CREATOR = "CREATOR";
+    public static final String IDENTIFIER = "IDENTIFIER";
+    public static final String STAGE = "STAGE";
+    public static final String BODYPART = "BODYPART";
+    public static final String SIZE = "SIZE";
+    public static final String VIEW = "VIEW";
+    public static final String PERIOD = "PERIOD";
+    public static final String COLLECTOR = "COLLECTOR";    
+    public static final String URL = "URL";
+    public static final String USECONTENT = "USECONTENT";
+    public static final String LINKED_MENU = "LINKED_MENU";
+    public static final String LINKED_NODE_ID = "LINKED_NODE_ID";
+    public static final String LINKED_ACC_ID = "LINKED_ACC_ID";
+    public static final String ORDER = "ORDER";
+    public static final String LISTCHANGED = "LISTCHANGED";
+    public static final String TEXTLIST = "TEXTLIST";
+    public static final String CHANGED = "CHANGED";
+    public static final String HEADING = "HEADING";
+    public static final String TEXT = "TEXT";
+   // public static final String SEQUENCE = "SEQUENCE";
+    public static final String ACCESSORYCHANGED = "ACCESSORYCHANGED";
+    public static final String ACCESSORYPAGES = "ACCESSORYPAGES";
+    public static final String ACCESSORYPAGE = "ACCESSORYPAGE";
+    public static final String LINKCHANGED = "LINKCHANGED";
+    public static final String LINK = "LINK";    
+    public static final String LINKS = "LINKS";
+    public static final String AUTHORCHANGED = "AUTHORCHANGED";
+    public static final String AUTHORLIST = "AUTHORLIST";
+    public static final String FULLNAME = "FULLNAME";
+    public static final String EMAIL = "EMAIL"; 
+    public static final String CONTACT = "CONTACT";
+    public static final String AUTHOR = "AUTHOR";
+    public static final String IS_AUTHOR = "IS_AUTHOR";
+    public static final String ADDRESS = "ADDRESS";
+    public static final String ERROR = "ERROR";
+    public static final String ERRORNUM = "ERRORNUM";
+    public static final String ERRORTEXT = "ERRORTEXT";
+    public static final String ANCESTORS = "ANCESTORS";
+    public static final String ANCESTORS_INFO = "ANCESTORS_INFO";
+    public static final String ANCESTOR_INFO = "ANCESTOR_INFO";
+    public static final String TREE = "TREE";
+    public static final String DEPTH = "DEPTH";
+    public static final String HASPAGE = "HASPAGE";
+    public static final String ANCESTORPAGEID = "ANCESTORWITHPAGE";
+    public static final String FILECHANGED = "FILECHANGED";
+    public static final String UNLOCKED = "UNLOCKED";   
+    public static final String SEQUENCECHANGED = "SEQUENCECHANGED";
+    public static final String CHILDCOUNT = "CHILDCOUNT";
+    public static final String IMAGEURL = "IMAGEURL";
+    public static final String TEXTSECTION = "TEXTSECTION";
+    public static final String INDENT = "INDENT";
+    public static final String REFERENCES = "REFERENCES";
+    public static final String REFERENCESCHANGED = "REFERENCESCHANGED";
+    public static final String INTERNETLINKS = "INTERNETLINKS";
+    public static final String INTERNETLINKSCHANGED = "INTERNETLINKSCHANGED";   
+    public static final String USERNAME = "USERNAME";
+    public static final String SETTINGS = "SETTINGS";
+    public static final String CUSTOM_CURSORS = "CUSTOM_CURSORS";
+    public static final String EDITORJAR_TIMESTAMP = "EDITORJAR_TIMESTAMP";
+    public static final String SUPPORTJAR_TIMESTAMP = "SUPPORTJAR_TIMESTAMP";   
+    public static final String MESSAGE = "message";
+    public static final String MESSAGENAME = "name";
+    public static final String MESSAGETEXT = "text";
+    public static final String SKELETAL = "Skeletal";
+    public static final String TEMPORARY = "Temporary";
+    public static final String UNDER_CONSTRUCTION = "Under Construction";
+    public static final String COMPLETE = "Complete";
+    public static final String TOL_REVIEWED = "ToL Reviewed";
+    public static final String PEER_REVIEWED = "Peer Reviewed";
+    public static final String MENU = "MENU";
+    public static final String MENUONSERVER = "MENUONSERVER";
+    public static final String PAGETITLE = "PAGETITLE";
+    public static final String AUTHORS = "AUTHORS";
+    public static final String AUTHDATE = "AUTHDATE";
+    public static final String SHOW = "SHOW";
+    public static final String SHOWAUTHORITYCHANGED = "SHOWAUTHORITYCHANGED";
+    public static final String SHOWAUTHORITY = "SHOWAUTHORITY";
+    public static final String SHOWAUTHORITYCONTAINING = "SHOWAUTHORITYCONTAINING";
+    public static final String SHOWPREFAUTHORITYCHANGED = "SHOWPREFAUTHORITYCHANGED";
+    public static final String SHOWPREFAUTHORITY = "SHOWPREFAUTHORITY";
+    public static final String SHOWIMPAUTHORITYCHANGED = "SHOWIMPAUTHORITYCHANGED";
+    public static final String SHOWIMPAUTHORITY = "SHOWIMPAUTHORITY";
+    public static final String AUTHORITY = "AUTHORITY";
+    public static final String ISPREFERRED = "ISPREFERRED";
+    public static final String ISIMPORTANT = "ISIMPORTANT";
+    public static final String MATCH = "MATCH";
+    public static final String MATCHES = "MATCHES";
+    public static final String ROOT = "ROOT";
+    public static final String MODIFIEDDATE = "MODIFIEDDATE";
+    public static final String UPLOADDATE = "UPLOADDATE";
+    public static final String DOWNLOADDATE = "DOWNLOADDATE";
+    public static final String CHECKED_OUT_FILE = "CHECKED_OUT_FILE";
+    public static final String UPLOAD_BATCH = "UPLOAD_BATCH";
+    public static final String UPLOAD_BATCHES = "UPLOAD_BATCHES";    
+    public static final String BATCHID = "BATCHID";
+    public static final String SUBMITTED = "SUBMITTED";
+    public static final String DOWNLOADED = "DOWNLOADED";
+    public static final String LAST_USER = "LAST_USER";
+    public static final String LAST_DATE = "LAST_DATE";
+    public static final String ROOT_GROUP = "ROOT_GROUP";    
+    public static final String ROOT_GROUP_ID = "ROOT_GROUP_ID";    
+    public static final String ROOTNODE_ID = "ROOTNODE_ID";
+    public static final String PERMISSIONS = "PERMISSIONS";
+    public static final String PERMISSION = "PERMISSION";    
+    public static final String SUCCESS = "SUCCESS";
+    public static final String FAILURE = "FAILURE";    
+    public static final String UNDOABLE_UPLOAD = "UNDOABLE_UPLOAD";
+    public static final String usermessages = "usermessages";
+    public static final String NOID = "NOID";
+    public static final String WRONG_PASSWORD = "WRONG_PASSWORD";
+    public static final String PASSWORD = "PASSWORD";
+    public static final String CAN_PUSH_PUBLIC = "CAN_PUSH_PUBLIC";
+    public static final String IS_SOLE_AUTHOR = "IS_SOLE_AUTHOR";
+    public static final String NEW_FROM_SERVER = "NEW_FROM_SERVER";
+    public static final String PARENTPAGE_NAME = "PARENTPAGE_NAME";
+    public static final String PARENTPAGE_NODE_ID = "PARENTPAGE_NODE_ID";
+    public static final String CONTRIBUTOR = "CONTRIBUTOR";
+    public static final String ORGANIZATION = "ORGANIZATION";
+    public static final String HOMEPAGE = "HOMEPAGE";
+    public static final String CONTRIBUTORLIST = "CONTRIBUTORLIST";
+    public static final String CONTRIBUTORCHANGED = "CONTRIBUTORCHANGED";
+    public static final String WIDTH = "WIDTH";
+    public static final String HEIGHT = "HEIGHT";
+    public static final String IMAGEID = "IMAGEID";
+    public static final String REMOVED = "REMOVED";
+    public static final String ALTTEXT = "ALTTEXT";
+    public static final String COMMENTS = "COMMENTS";
+    public static final String DONTSHOWCLOSE = "DONTSHOWCLOSE";
+    public static final String PUBLICDOMAIN = "PUBLICDOMAIN";
+    public static final String PREFERENCES = "PREFERENCES";
+    public static final String PREFERENCE = "PREFERENCE";   
+    public static final String PRINTIMAGEDATA = "PRINTIMAGEDATA";
+    public static final String PRINTIMAGECAPTION = "PRINTIMAGECAPTION";
+    public static final String INSTITUTION = "INSTITUTION";
+    public static final String NOTES = "NOTES";
+    public static final String NOEMAIL = "NOEMAIL";
+    public static final String NOADDRESS = "NOADDRESS";
+    public static final String PHONE = "PHONE";
+    public static final String FAX = "FAX";
+    public static final String SPECIMEN = "SPECIMEN";
+    public static final String BODYPARTS = "BODYPARTS";
+    public static final String ULTRASTRUCTURE = "ULTRASTRUCTURE";
+    public static final String HABITAT = "HABITAT";
+    public static final String EQUIPMENT = "EQUIPMENT";
+    public static final String PEOPLE = "PEOPLE";
+    public static final String CREATIONDATE = "CREATIONDATE";
+    public static final String ALIVE = "ALIVE";
+    public static final String BEHAVIOR = "BEHAVIOR";
+    public static final String VOUCHERNUMBER = "VOUCHERNUMBER";
+    public static final String VOUCHERNUMBERCOLLECTION = "VOUCHERNUMBERCOLLECTION";
+    public static final String IMAGETYPE = "IMAGETYPE";
+    public static final String UPLOADRESULTS = "UPLOADRESULTS";
+    public static final String VERSIONS = "VERSIONS";
+    public static final String VERSION = "VERSION";
+    public static final String IS_ARTICLE = "IS_ARTICLE";
+    public static final String IS_TREEHOUSE = "IS_TREEHOUSE";
+    public static final String NEW_VERSION = "NEW_VERSION";
+    public static final String PAGEREMOVED = "PAGEREMOVED";
+    public static final String PAGEADDED = "PAGEADDED";
+    public static final String INCOMPLETESUBGROUPS = "INCOMPLETESUBGROUPS";
+    public static final String INCOMPLETESUBGROUPSCHANGED = "INCOMPLETESUBGROUPSCHANGED";
+    public static final String PRIORITY = "PRIORITY";
+    public static final String PRIORITYCHANGED = "PRIORITYCHANGED";
+    public static final String CHARACTER = "CHARACTER";
+    public static final String TAXON = "TAXON";
+    public static final String NEWID = "NEWID";
+    public static final String image = "image";
+    public static final String filename = "filename";
+    public static final String copyrightowner = "copyrightowner";
+    public static final String copyrightemail = "copyrightemail";
+    public static final String copyrighturl = "copyrighturl";
+    public static final String copyrightdate = "copyrightdate";
+    public static final String license = "license";
+    public static final String restricted = "1";
+    public static final String tolusenomod = "2n";
+    public static final String tolusemod = "2y";
+    public static final String tolsharenomod = "3n";
+    public static final String tolsharemod = "3y";
+    public static final String cc = "4";
+    public static final String pd = "pd";
+    public static final String reference = "reference";
+    public static final String creator = "creator";
+    public static final String acknowledgements = "acknowledgements";
+    public static final String group = "group";
+    public static final String y = "y";
+    public static final String n = "n";
+    public static final String specimen = "specimen";
+    public static final String bodyparts = "bodyparts";
+    public static final String ultrastructure = "ultrastructure";
+    public static final String habitat = "habitat";
+    public static final String equipment = "equipment";
+    public static final String people = "people";
+    public static final String subject = "subject";
+    public static final String keywords = "keywords";
+    public static final String geolocation = "geolocation";
+    public static final String time = "time";
+    public static final String condition = "condition";
+    public static final String live = "live";
+    public static final String l = "l";
+    public static final String dead = "dead";
+    public static final String d = "d";
+    public static final String model = "model";
+    public static final String m = "m";
+    public static final String fossil = "fossil";
+    public static final String f = "f";
+    public static final String period = "period";
+    public static final String scientificname = "scientificname";
+    public static final String identifier = "identifier";
+    public static final String behavior = "behavior";
+    public static final String sex = "sex";
+    public static final String stage = "stage";
+    public static final String partofbody = "partofbody";
+    public static final String view = "view";
+    public static final String size = "size";
+    public static final String collection = "collection";
+    public static final String type = "type";
+    public static final String vouchernumber = "vouchernumber";
+    public static final String vouchercollection = "vouchercollection";
+    public static final String collector = "collector";
+    public static final String comments = "comments";
+    public static final String alt = "alt";
+    public static final String imagetype = "imagetype";
+    public static final String artistic = "artistic";
+    public static final String technical = "technical";
+    public static final String notes = "notes";
+    public static final String photo = "photo";
+    public static final String painting = "painting";
+    public static final String drawing = "drawing";
+    public static final String diagram = "diagram";
+    public static final String person = "person";
+    public static final String surname = "surname";
+    public static final String firstname = "firstname";
+    public static final String email = "email";
+    public static final String dontpublishemail = "dontpublishemail";
+    public static final String webpageurl = "webpageurl";
+    public static final String institution = "institution";
+    public static final String address = "address";
+    public static final String bio = "bio";
+    public static final String grouphaspermission = "grouphaspermission";
+    public static final String groupnopermission = "groupnopermission";
+    public static final String coordinator = "coordinator";
+    public static final String phone = "phone";
+    public static final String fax = "fax";
+	public static final String interests = "interests";
+	public static final String geographicareainterest = "geographicareainterest";
+	public static final String otherinterests = "otherinterests";
+	public static final String permission = "permission"; 
+	public static final String sendemail = "sendemail";
+	public static final String direction = "direction";
+	public static final String genename = "genename";
+	public static final String sequence = "sequence";
+	public static final String branch = "branch";
+	public static final String attribute = "attribute";
+	public static final String name = "name";
+	public static final String value = "value";
+	public static final String PARENTGROUP = "PARENTGROUP";
+	public static final String COUNT = "COUNT";
+	public static final String OBSOLETEMESSAGE = "OBSOLETEMESSAGE";
+	public static final String VMVERSION = "VMVERSION";
+	public static final String ITALICIZE_NAME = "ITALICIZENAME";
+	public static final String IS_NEW_COMBINATION = "IS_NEW_COMBINATION";
+	public static final String COMBINATION_AUTHOR = "COMBINATION_AUTHOR";
+	public static final String COMBINATION_DATE = "COMBINATION_DATE";
+	public static final String SOURCE_DB = "SOURCE_DB";
+	public static final String SOURCE_DB_ID = "SOURCE_DB_ID";
+	
+}
+
+
diff --git a/Source/mesquite/tol/uBioURLServer/uBioURLServer.java b/Source/mesquite/tol/uBioURLServer/uBioURLServer.java
new file mode 100644
index 0000000..f05ea88
--- /dev/null
+++ b/Source/mesquite/tol/uBioURLServer/uBioURLServer.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.tol.uBioURLServer;
+
+import mesquite.lib.*;
+import mesquite.tol.lib.TaxonOnWebServer;
+
+public class uBioURLServer extends TaxonOnWebServer {
+
+	public String getURL(String taxonName) {
+		String openName = StringUtil.encodeForURL(StringUtil.replace(taxonName,' ', '+'));
+		return "http://www.ubio.org/browser/search.php?search_all=" + openName;
+	
+	}
+
+	public String getName() {
+		return "uBio";
+	}
+
+	
+	public String getExplanation() {
+		return "Provides a URL to a taxon in uBio";
+	}
+
+}
diff --git a/Source/mesquite/treefarm/AddSelectedTaxaToTree/AddSelectedTaxaToTree.java b/Source/mesquite/treefarm/AddSelectedTaxaToTree/AddSelectedTaxaToTree.java
new file mode 100644
index 0000000..ab109b8
--- /dev/null
+++ b/Source/mesquite/treefarm/AddSelectedTaxaToTree/AddSelectedTaxaToTree.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.AddSelectedTaxaToTree;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AddSelectedTaxaToTree extends TreeAltererMult {
+	public String getName() {
+		return "Add Selected Taxa To Tree";
+	}
+	public String getExplanation() {
+		return "To a tree with some taxa excluded, adds those taxa that are selected." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	boolean unselectedAlreadyWarned = false;
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree==null)
+			return false;
+		Taxa taxa = tree.getTaxa();
+		if (!taxa.anySelected()) {
+ 			if (!unselectedAlreadyWarned)
+ 				discreetAlert("You must select taxa to indicate which ones are to be added to the tree or trees");
+ 			unselectedAlreadyWarned = true;
+			return false;
+		}
+		boolean changed = false;
+		for (int i = 0; i< taxa.getNumTaxa(); i++){
+			int node = tree.nodeOfTaxonNumber(i);
+			if (!tree.nodeExists(node) && taxa.getSelected(i)){
+				tree.graftTaxon(i, tree.getRoot(), false);
+				changed = true;
+			}
+		}
+		if (notify && changed && tree instanceof Listened) {
+			((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.PARTS_ADDED));
+		}
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/AllRerootings/AllRerootings.java b/Source/mesquite/treefarm/AllRerootings/AllRerootings.java
new file mode 100644
index 0000000..35202d8
--- /dev/null
+++ b/Source/mesquite/treefarm/AllRerootings/AllRerootings.java
@@ -0,0 +1,83 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.AllRerootings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class AllRerootings extends DetTreeModifier {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree original, MesquiteTree modified, int ic){
+   		if (original == null || modified == null)
+   			return;
+   		int root = original.getRoot();
+   		int numReroots = original.numberOfNodesInClade(root)-2;
+   		if (ic<0 | ic>=numReroots)
+   			return;
+   		int r = findRootingNode(original, root, ic);
+   		
+   		if (!modified.nodeExists(r))
+   			return;
+		modified.reroot(modified.nodeInTraversal(r, root), root, false);
+		modified.setName("Rooting " + (ic+1) + " of " + original.getName());
+		
+   	}
+   	int findRootingNode(Tree original, int cladeRoot, int target){
+    	 	int numReroots = original.numberOfNodesInClade(cladeRoot)-1;
+		int count = -1;
+ 		for (int i = 1; i<=numReroots; i++) {
+ 			int atNode = original.nodeInTraversal(i, cladeRoot);
+ 			if (original.nodeIsPolytomous(cladeRoot) || original.motherOfNode(atNode)!= cladeRoot) {
+ 				count++;
+	 			if (count == target)
+	 				return i;
+ 			}
+ 		}
+ 		return -1;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Tree tree) {
+		if (tree ==null)
+			return 0;
+		else
+			return  tree.numberOfNodesInClade(tree.getRoot())-2;
+   	}
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "All Rerootings";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Reroots tree at all nodes.";
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/AllTrees/AllTrees.java b/Source/mesquite/treefarm/AllTrees/AllTrees.java
new file mode 100644
index 0000000..4af4cc8
--- /dev/null
+++ b/Source/mesquite/treefarm/AllTrees/AllTrees.java
@@ -0,0 +1,209 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.AllTrees;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.TreeSimulate;
+import mesquite.lib.duties.TreeSource;
+
+public class AllTrees extends TreeSource {
+	int currentTree=0; 
+	Taxa currentTaxa;
+	static final int maxNumTaxa = 11;
+	boolean warned= false;
+
+	MesquiteBoolean rooted = new MesquiteBoolean(true);   // set control for this
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem( "Rooting Options...", makeCommand("rootingOptions",  this));
+		if (!MesquiteThread.isScripting()){
+			boolean b = queryRootings();
+			if (!b) 
+				return false;
+		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("toggleRooted "+ rooted.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not the trees created are rooted.", "[on or off]", commandName, "toggleRooted")) {
+			boolean current = rooted.getValue();
+			rooted.toggleValue(parser.getFirstToken(arguments));
+			if (current!=rooted.getValue())
+				parametersChanged();
+		}
+		else  if (checker.compare(this.getClass(), "Allows user the choice of rooting options", "[]", commandName, "rootingOptions")) {
+			boolean current = rooted.getValue();
+			if (queryRootings() && current!=rooted.getValue())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	private boolean queryRootings(){
+		String help = "If you select \"rooted trees\", then Mesquite will produce all possible rooted trees. ";
+		help+="If you turn this option off, then Mesquite will produce unrooted trees. ";
+		MesquiteBoolean mb = MesquiteBoolean.queryCheckBox(containerOfModule(), "Rooting of Trees", "Do you wish Mesquite to create rooted trees or unrooted trees?" , "rooted trees", help, rooted.getValue());
+		if (mb.isUnassigned())
+			return false;
+		rooted.setValue(mb.getValue());
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void addTaxon(MesquiteTree tree, int taxonToAdd, MesquiteInteger treesInPiece, MesquiteInteger treeNum) {
+		int numPlacesToAdd = taxonToAdd*2-1;
+		if (!rooted.getValue())
+			numPlacesToAdd-=2;
+		int treesInThisPiece = treesInPiece.getValue();
+		int treesInNextPiece = treesInThisPiece/ numPlacesToAdd;
+
+		int whichPlace = treeNum.getValue() / treesInNextPiece;
+		if (!rooted.getValue())
+			whichPlace +=2;
+
+		tree.graftTaxon(taxonToAdd, tree.nodeInTraversal(whichPlace,tree.getRoot()), false);
+
+		treeNum.setValue(treeNum.getValue() % treesInNextPiece);
+		treesInPiece.setValue(treesInNextPiece);
+	}
+
+
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		if (taxa==null)
+			return null;
+		if (taxa.getNumTaxa()>maxNumTaxa) {
+			if (!warned)
+				MesquiteMessage.discreetNotifyUser("There are too many taxa to create all trees, as there will be too many trees.");
+			warned=true;
+			return null;
+		}
+		currentTree = itree;
+		int numTaxa = taxa.getNumTaxa();
+
+		MesquiteTree tree = new MesquiteTree(taxa);
+
+		tree.graftTaxon(0, tree.getRoot(), false);
+		tree.graftTaxon(1, tree.getRoot(), false);
+		tree.deleteClade(2,false);
+
+		//we now have a tree with just two taxa in it
+		MesquiteInteger treeNum = new MesquiteInteger(itree);
+		MesquiteInteger treesInPiece;
+		treesInPiece = new MesquiteInteger(getNumberOfTrees(numTaxa));
+
+		for (int i = 2; i<numTaxa; i++){
+			addTaxon(tree, i, treesInPiece, treeNum);
+		}
+
+		if (!rooted.getValue())
+			tree.setRooted(false, false);  //deroot tree
+		return tree;
+	}
+
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(int numTaxa) {
+		if (!rooted.getValue())
+			numTaxa--;
+		// maximum value of an int is 2,147,483,647; number of rooted trees for 11 taxa is  654,729,075
+		if (numTaxa==2) 
+			return 1;
+		else if (numTaxa<=maxNumTaxa) { // then we can do this without worrying about overflow
+			int numTrees = 3;  // number of rooted trees for 3 taxa
+			if (numTaxa>3)
+				for (int i = 3; i<numTaxa; i++) {
+					numTrees *= (2*i-1);
+				}
+			return numTrees;
+		}	
+		if (numTaxa>maxNumTaxa) {
+			if (!warned)
+				MesquiteMessage.discreetNotifyUser("There are too many taxa to create all trees, as there will be too many trees.");
+			warned=true;
+		}
+		return 0;
+	}
+
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		int numTaxa = taxa.getNumTaxa();
+		return getNumberOfTrees(numTaxa);
+	}
+
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmeticOrSelection(notification))
+			return;
+		if (obj == currentTaxa) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		currentTaxa = taxa;
+		if (currentTaxa!=null)
+			currentTaxa.addListener(this);
+	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		super.endJob();
+	}
+
+
+	public String getTreeNameString(Taxa taxa, int i) {
+		return null;
+	}
+
+	public void initialize(Taxa taxa) {
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies all possible dichotomous rooted or unrooted trees (only works if number of taxa is <=" + maxNumTaxa + ").";
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+	public String getName() {
+		return "All Trees";
+	}
+
+
+}
diff --git a/Source/mesquite/treefarm/AugmentTreeRandomly/AugmentTreeRandomly.java b/Source/mesquite/treefarm/AugmentTreeRandomly/AugmentTreeRandomly.java
new file mode 100644
index 0000000..ce8b567
--- /dev/null
+++ b/Source/mesquite/treefarm/AugmentTreeRandomly/AugmentTreeRandomly.java
@@ -0,0 +1,256 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.AugmentTreeRandomly;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class AugmentTreeRandomly extends RndTreeModifier {
+	int mode = addToAnyIgnoreLengths;
+	static final int addToAnyIgnoreLengths = 0;
+	static final int addToAnyConsiderLengths = 1;
+	static final int addOnlyToOriginalBranches = 2;
+	StringArray modes;
+	MesquiteString modeName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		modes = new StringArray(3);
+		modes.setValue(addToAnyIgnoreLengths, "To Any, Ignoring Length");
+		modes.setValue(addToAnyConsiderLengths, "To Any, Considering Length");
+		modes.setValue(addOnlyToOriginalBranches, "Only To Original Branches");
+		modeName = new MesquiteString(modes.getValue(mode));
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Augment on Which Branches", makeCommand("setMode",  this), modes);
+		mss.setSelected(modeName);
+		if (!MesquiteThread.isScripting()){
+			int newMode = ListDialog.queryList(containerOfModule(), "Augment on Which Branches?", "On which branches should taxa be added?", MesquiteString.helpString, modes.getStrings(), 0);
+			if (MesquiteInteger.isCombinable(newMode)) {
+				mode = newMode;
+	    			modeName.setValue(modes.getValue(mode));
+	    		}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	temp.addLine("setMode " + mode);
+ 	 	return temp;
+  	 }
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	private void setColor(Tree tree, int node, boolean[] added){
+		if (tree == null || !(tree instanceof Associable))
+			return;
+		Associable aTree = (Associable)tree;
+		if (aTree.getWhichAssociatedLong(colorNameRef)==null)
+			aTree.makeAssociatedLongs("color");
+		aTree.setAssociatedLong(colorNameRef, node, ColorDistribution.numberOfGreen, true);
+		added[node] = true;
+	}
+	/** goes through the tree returning which node is the nodeNumberTH found in the traversal */
+	private boolean colorClades(Tree tree, int node, boolean[] added){
+		if (tree.nodeIsTerminal(node)) {
+			return added[node];
+		}
+		boolean allDescendants = true;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			boolean desc = colorClades(tree, d, added);
+			allDescendants = allDescendants && desc;
+		}
+		if (allDescendants) {
+			setColor(tree, node, added);
+		}
+		return allDescendants;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	/**/
+    	 	if (checker.compare(this.getClass(), "Sets where to add taxa in augmentation", "[0 = add to any branches, ignoring length; " +
+    	 				"1 = add to any branches, considering branch length; 2 = add only to original branches]", commandName, "setMode")) {
+			String name = parser.getFirstToken(arguments);
+			int newMode = modes.indexOf(name);
+			if (newMode >=0 && newMode!=mode){
+				mode = newMode;
+	    			modeName.setValue(modes.getValue(mode));
+	    			if (!MesquiteThread.isScripting())
+	    				parametersChanged();
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	 
+   	 boolean warned = false;
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree tree, MesquiteTree augmented, RandomBetween rng){
+   		if (tree == null)
+   			return;
+   		Taxa taxa = tree.getTaxa();
+   		if (mode == addOnlyToOriginalBranches) {
+   			augmented.deselectAll();
+   			selectAllNodes(augmented, augmented.getRoot());
+   		}
+   		boolean found = false;
+   		boolean[] added = new boolean[tree.getNumNodeSpaces()];
+   		for (int i = 0; i<added.length; i++) 
+   			added[i] = false;
+   		for (int it = 0; it<taxa.getNumTaxa(); it++)
+   			if (!tree.taxonInTree(it)) {
+   				found = true;
+   				if (mode == addToAnyConsiderLengths) {
+   					double totalLength = totalBranchLength(augmented, augmented.getRoot(), false);
+   					double choice = (rng.nextDouble() * totalLength);
+   					int recipientNode = selectedNodeInTraversalByLength(augmented, choice, false);
+   					if (!augmented.nodeExists(recipientNode))
+   						MesquiteMessage.warnProgrammer("Error: recipient node doesn't exist; choice " + choice + " recipientNode " + recipientNode);
+   					else {
+	  					augmented.graftTaxon(it, recipientNode, false);
+	  					setColor(augmented, augmented.nodeOfTaxonNumber(it), added);
+	  					augmented.setBranchLength(augmented.motherOfNode(augmented.nodeOfTaxonNumber(it)), augmented.getBranchLength(recipientNode, 1.0) - excessLength, false);
+	   					augmented.setBranchLength(recipientNode, excessLength, false);
+	   					double shortest = augmented.shortestPathAboveNode(recipientNode, 1.0);
+	   					double tallest = augmented.tallestPathAboveNode(recipientNode, 1.0);
+	   					//set length of grafted to randomly between highest and lowest in sister clade
+	   					augmented.setBranchLength(augmented.nodeOfTaxonNumber(it), excessLength+(shortest+(tallest-shortest)*rng.nextDouble()), false); 
+   					}
+  				}
+   				else {
+	   				if (mode == addOnlyToOriginalBranches){
+	   					int numChoices = tree.numberOfNodesInClade(tree.getRoot());
+	   					// choose one and add it in augmented
+	   					int choice = rng.randomIntBetween(0, numChoices-1);
+	   					int recipientNode = selectedNodeInTraversal(augmented, choice, true);
+	   					if (!augmented.nodeExists(recipientNode))
+   							MesquiteMessage.warnProgrammer("Error: recipient node doesn't exist; choice " + choice + " numChoices " + numChoices + " recipientNode " + recipientNode + " tree " + augmented.writeTree() + " (a)");
+	   					else {
+	   						augmented.graftTaxon(it, recipientNode, false);
+	  						setColor(augmented, augmented.nodeOfTaxonNumber(it), added);
+	  					}
+	   					
+	   				}
+	   				else if (mode == addToAnyIgnoreLengths) {
+	   					int numChoices = augmented.numberOfNodesInClade(augmented.getRoot());
+	   					int choice = rng.randomIntBetween(0, numChoices-1);
+	   					int recipientNode = selectedNodeInTraversal(augmented, choice, false);
+	   					if (!augmented.nodeExists(recipientNode))
+   							MesquiteMessage.warnProgrammer("Error: recipient node doesn't exist; choice " + choice + " numChoices " + numChoices + " recipientNode " + recipientNode + " tree " + augmented.writeTree() + " (b)");
+	   					else {
+	   						augmented.graftTaxon(it, recipientNode, false);
+	  						setColor(augmented, augmented.nodeOfTaxonNumber(it), added);
+	  					}
+	   				}
+   				}
+   			}
+   		if (!found && !warned){
+   			discreetAlert( getName() + " was not able to augment the tree because all taxa in the taxa block are already in the base tree being used.");
+   			warned = true;
+   		}
+   		colorClades(augmented, augmented.getRoot(), added);
+   		if (mode == addOnlyToOriginalBranches)
+   			augmented.deselectAll();
+   	}
+	/*-----------------------------------------*/
+	private int countNodes;
+	private int nodeFound;
+	/** goes through the tree returning which node is the nodeNumberTH found in the traversal */
+	private void findSelectedNodeInTraversal(Tree tree, int node, int nodeNumber, boolean selectedOnly){
+		if (tree.getSelected(node) || !selectedOnly) {
+			countNodes++;
+			if ((countNodes==nodeNumber) && (nodeFound==0)) {
+				nodeFound=node;
+				return;
+			}
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && nodeFound==0; d = tree.nextSisterOfNode(d))
+				findSelectedNodeInTraversal(tree, d, nodeNumber, selectedOnly);
+	}
+	/*-----------------------------------------*/
+	/**Returns indexTH selected node in tree traversal*/
+	private int selectedNodeInTraversal(Tree tree, int index, boolean selectedOnly){
+		countNodes=-1;
+		nodeFound=0;
+		findSelectedNodeInTraversal(tree, tree.getRoot(), index, selectedOnly);
+		return nodeFound;
+	}
+
+	private void selectAllNodes(MesquiteTree tree, int node){
+		tree.setSelected(node, true);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				selectAllNodes(tree, d);
+	}
+	private double totalBranchLength(Tree tree, int node, boolean selectedOnly){
+		double tot = 0;
+		if (tree.getSelected(node) || !selectedOnly)
+			tot = tree.getBranchLength(node, 1.0);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			tot += totalBranchLength(tree, d, selectedOnly);
+		return tot;
+	}
+	/** goes through the tree returning which node is the nodeNumberTH found in the traversal */
+	double countLength;
+	double excessLength;
+	private void findSelectedNodeInTraversalByLength(Tree tree, int node, double targetLength, boolean selectedOnly){
+		if (tree.getSelected(node) || !selectedOnly){
+			countLength+= tree.getBranchLength(node, 1.0);
+		}
+		if ((countLength>=targetLength) && (nodeFound==0)) {
+			nodeFound=node;
+			excessLength = countLength-targetLength;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && nodeFound==0; d = tree.nextSisterOfNode(d))
+				findSelectedNodeInTraversalByLength(tree, d, targetLength, selectedOnly);
+	}
+	/*-----------------------------------------*/
+	/**Returns indexTH selected node in tree traversal*/
+	private int selectedNodeInTraversalByLength(Tree tree, double targetLength, boolean selectedOnly){
+		countLength=0;
+		excessLength = 0;
+		nodeFound=0;
+		findSelectedNodeInTraversalByLength(tree, tree.getRoot(), targetLength, selectedOnly);
+		return nodeFound;
+	}
+
+
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return "Random augmentation #" + itree;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Augment Tree Randomly";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Augments tree by random placement of excluded taxa.  There are three modes: adding only to original branches, ignoring lengths; adding to any branch, considering branch length; adding to any branch, ignoring branch length.  With lengths considered, probability of placing taxon on a branch is proportional to the branch's length.";
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Placement of added taxa: " + modes.getValue(mode);
+   	}
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/AverageNodeAssociatedDifference/AverageNodeAssociatedDifference.java b/Source/mesquite/treefarm/AverageNodeAssociatedDifference/AverageNodeAssociatedDifference.java
new file mode 100644
index 0000000..1d5ba5d
--- /dev/null
+++ b/Source/mesquite/treefarm/AverageNodeAssociatedDifference/AverageNodeAssociatedDifference.java
@@ -0,0 +1,317 @@
+
+
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.AverageNodeAssociatedDifference;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+
+
+/* ======================================================================== */
+public class AverageNodeAssociatedDifference extends DistanceBetween2Trees {
+	String valueToConsider = "";
+	StringBuffer nodeByNodeValues = new StringBuffer();
+	MesquiteBoolean verboseOutput= new MesquiteBoolean(false);
+	String[] associatedValueNames;
+
+	MesquiteBoolean absoluteDifference= new MesquiteBoolean(false);
+	MesquiteBoolean listAllNodes= new MesquiteBoolean(false);
+	StringArray terminalsAbove, terminalsBelow, otherTerminalsAbove, otherTerminalsBelow;
+	boolean isDistance = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		isDistance = (getHiredAs() == DistanceBetween2Trees.class);
+		addMenuItem(null, "Choose Values To Show...", makeCommand("chooseValues",  this));
+		addCheckMenuItem(null, "Absolute Value", makeCommand("absoluteValue",  this), absoluteDifference);
+		addCheckMenuItem(null, "List All Nodes", makeCommand("toggleListAllNodes",  this), listAllNodes);
+		addCheckMenuItem(null, "Verbose Output to Log", makeCommand("toggleVerboseOutput",  this), verboseOutput);
+		valueToConsider = "";
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public boolean largerIsFurther(){  
+		return false;
+	}
+		/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("absoluteValue " + absoluteDifference.toOffOnString());
+		temp.addLine("toggleListAllNodes " + listAllNodes.toOffOnString());
+		temp.addLine("toggleVerboseOutput " + verboseOutput.toOffOnString());
+		temp.addLine("setValueToConsider " + StringUtil.tokenize(valueToConsider));
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	private void visitOriginal(Tree tree,int node,  Tree otherTree, MesquiteInteger numConsistent, DoubleArray array1, DoubleArray array2, MesquiteDouble totalDiff){
+		if (tree.nodeIsInternal(node)){
+			Bits b = tree.getTerminalTaxaAsBits(node);
+
+			double d1 = array1.getValue(node);
+			if (otherTree.isClade(b)){  // has same clade
+				numConsistent.increment();
+				int node2 = otherTree.mrca(b);
+				if (tree.getRoot()!=node && otherTree.getRoot()!=node2) {   // only do it if neither is the root
+					double d2 = array2.getValue(node2);
+					double diff = 0.0;
+					if (MesquiteDouble.isCombinable(d1) && MesquiteDouble.isCombinable(d2)){
+						if (absoluteDifference.getValue()) {
+							if (d1>d2)
+								diff = d1-d2;
+							else
+								diff= d2-d1;
+						}
+						else
+							diff = d1-d2;
+						//if (verboseOutput.getValue())
+						nodeByNodeValues.append("" + node + "\t"+MesquiteDouble.toStringNoNegExponential(diff)+"\t"+d1+"\t"+d2+"\n");
+						totalDiff.add(diff);
+					} else if (listAllNodes.getValue())
+						if (MesquiteDouble.isCombinable(d1))
+							nodeByNodeValues.append("" + node + "\t-\t" + d1 + "\t-"+"\n");
+						else
+							nodeByNodeValues.append("" + node + "\t-\t-\t-"+"\n");
+				}
+			} else if (listAllNodes.getValue()) {
+				if (tree.getRoot()!=node) {   // only do it if neither is the root
+					nodeByNodeValues.append("" + node + "\t-\t" + d1 + "\t-"+"\n");
+				}
+			}
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginal(tree, daughter, otherTree, numConsistent, array1, array2, totalDiff);
+
+		}
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether verbose output is listed to the log file or not", "", commandName, "toggleVerboseOutput")) {
+			boolean current = verboseOutput.getValue();
+			verboseOutput.toggleValue(parser.getFirstToken(arguments));
+			if (current!=verboseOutput.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Shows dialog box to choose what values to display", null, commandName, "chooseValues")) {
+			showAssociatedChoiceDialog(associatedValueNames, "Values to Average Differences", this);
+		}
+		else if (checker.compare(this.getClass(), "Sets which value to use for calculation", "", commandName, "setValueToConsider")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.notEmpty(name) && !valueToConsider.equalsIgnoreCase(name)) {
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether absolute value is shown or raw value", "", commandName, "absoluteValue")) {
+			boolean current = absoluteDifference.getValue();
+			absoluteDifference.toggleValue(parser.getFirstToken(arguments));
+			if (current!=absoluteDifference.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether all nodes are listed in the verbose output, or just the ones in both trees and both with associated values", "", commandName, "toggleListAllNodes")) {
+			boolean current = listAllNodes.getValue();
+			listAllNodes.toggleValue(parser.getFirstToken(arguments));
+			if (current!=listAllNodes.getValue())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public  boolean showAssociatedChoiceDialog(String[] associatedValueNames, String message, MesquiteModule module) {
+		if (associatedValueNames == null)
+			return false;
+		int num = associatedValueNames.length;
+		if (num==0) {
+			module.alert("This Tree has no values associated with nodes");
+			return false;
+		}
+		else if (MesquiteThread.isScripting()) {
+			valueToConsider = associatedValueNames[0];
+			return true;
+		}
+/*		else if (num==1){
+			valueToConsider = associatedValueNames[0];
+			module.alert("This Tree has no values associated with nodes");
+			return true;
+		}
+		*/
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		int valueShown = -1;
+		for (int i = 0; i< num; i++){
+			if (valueToConsider.equalsIgnoreCase(associatedValueNames[i]))
+				valueShown=i;
+		}
+		ExtensibleDialog queryDialog = new ExtensibleDialog(module.containerOfModule(), message,  buttonPressed);
+		queryDialog.addLabel(message, Label.CENTER);
+
+		RadioButtons radios = queryDialog.addRadioButtons(associatedValueNames, valueShown); 			
+
+		queryDialog.completeAndShowDialog(true);
+
+		boolean ok = (queryDialog.query()==0);
+
+		if (ok) {
+			valueToConsider = associatedValueNames[radios.getValue()];
+		}
+
+		queryDialog.dispose();
+		return ok;
+	}
+	/*.................................................................................................................*/
+	public String[]  acquireAssociatedValueNames(Associable tree) {
+		if (tree == null)
+			return null;
+		ListableVector v = new ListableVector();
+		int num = tree.getNumberAssociatedDoubles();
+		String[] associatedValueNames = new String[num];
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (da != null){
+				v.addElement(new MesquiteString(da.getName(), ""), false);
+				associatedValueNames[i] = da.getName();
+			}
+		}
+		return associatedValueNames;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree t1, Tree t2) {
+	}
+
+
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (tree1 == null)
+			return;
+		if (tree2 == null)
+			return;
+		if (associatedValueNames==null)
+			associatedValueNames = acquireAssociatedValueNames((Associable)tree1);
+		if (StringUtil.blank(valueToConsider)) {
+			boolean ok = showAssociatedChoiceDialog(associatedValueNames, "Values to Average Differences", this);
+			if (!ok) {
+				iQuit();
+				return;
+			}
+		}
+		if (nodeByNodeValues==null)
+			nodeByNodeValues = new StringBuffer();
+		nodeByNodeValues.setLength(0);
+
+		DoubleArray array1 = null;
+		DoubleArray array2 = null;
+
+		boolean found = false;
+		int num = tree1.getNumberAssociatedDoubles();
+		for (int i = 0; i< num; i++){
+			array1 = tree1.getAssociatedDoubles(i);
+			if (valueToConsider.equalsIgnoreCase(array1.getName())) {
+				found=true;
+				break;
+			}
+		}
+		if (!found)
+			return;
+		found=false;
+		num = tree2.getNumberAssociatedDoubles();
+		for (int i = 0; i< num; i++){
+			array2 = tree2.getAssociatedDoubles(i);
+			if (valueToConsider.equalsIgnoreCase(array2.getName())){
+				found=true;
+				break;
+			}
+		}
+		if (!found)
+			return;
+
+		nodeByNodeValues.append("\n\n\n======================================"+"\n");
+		nodeByNodeValues.append(" Average Difference of Values Associated with Nodes"+"\n");
+		nodeByNodeValues.append("   Tree A: \"" + tree1.getName() + "\""+"\n");
+		nodeByNodeValues.append("   Tree B: \"" + tree2.getName() + "\""+"\n");
+		nodeByNodeValues.append("   [Node number listed below is the node number within Tree A]\n"+"\n");
+		if (absoluteDifference.getValue()) 
+			nodeByNodeValues.append("\nNode\t|Tree A - Tree B|    \tValue 1\t Value B"+"\n");
+		else
+			nodeByNodeValues.append("\nNode\tTree A - Tree B    \tValue 1\t Value B"+"\n");
+
+
+		MesquiteInteger numCon = new MesquiteInteger(0);
+		MesquiteDouble totalDiff = new MesquiteDouble(0.0);
+
+	//	int numCladeTree1 = tree1.numberOfInternalsInClade(tree1.getRoot());
+	//	int numCladeTree2 = tree2.numberOfInternalsInClade(tree2.getRoot());
+
+		visitOriginal(tree1, tree1.getRoot(), tree2, numCon, array1, array2, totalDiff);
+		if (tree1.getTerminalTaxaAsBits(tree1.getRoot()).equals(tree2.getTerminalTaxaAsBits(tree2.getRoot()))){   // remove root value
+			numCon.decrement();
+		}
+		
+		if (verboseOutput.getValue())
+			log(nodeByNodeValues.toString());
+
+		int numC = numCon.getValue();
+		double totalD = totalDiff.getValue();
+
+
+		double avg = 0.0;
+		if (numC>0)
+			avg = totalD/numC;
+
+		result.setValue(avg);
+		if (resultString!=null) {
+			resultString.setValue("Average Difference of Node Values: "+ result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Average Difference of Values Associated with Nodes";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Calculates the average differences in values associated with nodes across those clades shared between two trees (excludes the clade consisting of all taxa).";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+}
diff --git a/Source/mesquite/treefarm/AvgTaxonValueAmgTrees/AvgTaxonValueAmgTrees.java b/Source/mesquite/treefarm/AvgTaxonValueAmgTrees/AvgTaxonValueAmgTrees.java
new file mode 100644
index 0000000..ee7c116
--- /dev/null
+++ b/Source/mesquite/treefarm/AvgTaxonValueAmgTrees/AvgTaxonValueAmgTrees.java
@@ -0,0 +1,165 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.AvgTaxonValueAmgTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+public class AvgTaxonValueAmgTrees extends NForTaxonWithTrees {
+	public String getName() {
+		return "Average Taxon Value among Trees";
+	}
+	public String getExplanation() {
+		return "Averages among trees a value calculated for a taxon using a tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NForTaxonWithTree.class, getName() + "  needs values for the taxa from each of the trees to average.",
+		"The method to calculate values to be averaged over trees can be chosen initially or via the Values for Taxa submenu ");
+	}
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	MesquiteSubmenuSpec mss;
+	NForTaxonWithTree numberTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		ntC =makeCommand("setNumberTask",  this);
+		numberTaskName = new MesquiteString();
+		if (numberTask == null)
+			numberTask = (NForTaxonWithTree)hireEmployee(NForTaxonWithTree.class, "Value for taxa to average over trees");//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+
+		if (numberTask != null){
+			numberTask.setHiringCommand(ntC);
+			numberTaskName.setValue(numberTask.getName());
+		}
+		else 
+			return false;
+		if (numModulesAvailable(NForTaxonWithTree.class)>0) {
+			mss = addSubmenu(null, "Values for Taxa", ntC, NForTaxonWithTree.class);
+			mss.setSelected(numberTaskName);
+			mss.setEnabled(false);
+		}
+
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers to be averaged among trees", "[name of module]", commandName, "setNumberTask")) {
+			NForTaxonWithTree temp =  (NForTaxonWithTree)replaceEmployee(NForTaxonWithTree.class, arguments, "Module to calculate numbers to be averaged among trees", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	NumberArray results2;
+	/*.................................................................................................................*/
+	public void calculateNumbers(Taxa taxa, NumberArray results, MesquiteString resultsString){
+		if (results==null|| taxa == null)
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		results.resetSize(numTaxa);
+	   	clearResultAndLastResult(results);
+		results.zeroArray();
+		if (results2 == null)
+			results2 = new NumberArray();
+		results2.resetSize(numTaxa);
+		results2.zeroArray();
+		int numTrees = getNumTrees(taxa);
+
+		int[] nums = new int[numTaxa];
+		double[] sums = new double[numTaxa];
+		for (int itr = 0; itr< numTrees; itr++){ //get tree for comparison
+			Tree tree = getTree(taxa, itr);
+			CommandRecord.tick(getVeryShortName() + ": tree " + (itr+1));
+			numberTask.calculateNumbers(taxa, tree, results2, null);
+//			CommandRecord.tick(getVeryShortName() + ": done tree " + (itr+1));
+			for (int it = 0; it<taxa.getNumTaxa(); it++){
+				if (!results2.isUnassigned(it)){
+					nums[it]++;
+					sums[it] += results2.getDouble(it);
+				}
+			}
+
+		}
+		double sum= 0;
+		int num = 0;
+		for (int it = 0; it<taxa.getNumTaxa(); it++){
+			if (nums[it] ==0)
+				results.setToUnassigned(it);
+			else {
+				double avg = sums[it]/nums[it];
+				sum += avg;
+				num++;
+				results.setValue(it, avg);
+			}
+		}
+		if (resultsString != null){
+			if (num == 0)
+				resultsString.setValue("Avg. " + getVeryShortName() + ": No results obtained");
+			else		
+				resultsString.setValue("Avg. " + getVeryShortName() + ": " + (sum/num));
+		}
+		saveLastResult(results);
+		saveLastResultString(resultsString);
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (numberTask != null)
+			return "Avg. " + numberTask.getVeryShortName();
+		return "Avg. Among Trees";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+}
+
+
diff --git a/Source/mesquite/treefarm/BLfromDivergenceTimes/BLfromDivergenceTimes.java b/Source/mesquite/treefarm/BLfromDivergenceTimes/BLfromDivergenceTimes.java
new file mode 100644
index 0000000..8d23dab
--- /dev/null
+++ b/Source/mesquite/treefarm/BLfromDivergenceTimes/BLfromDivergenceTimes.java
@@ -0,0 +1,122 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.BLfromDivergenceTimes;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class BLfromDivergenceTimes extends BranchLengthsAltererMult {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Branch Lengths from current, reinterpreted as Divergence Times";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Reassigns branch lengths under the assumption that currently assigned branch lengths are actually divergence times.";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+	}
+	/*.................................................................................................................*/
+	public double visitNodes(int node, AdjustableTree tree) {
+		double depth = tree.getBranchLength(node);
+		if (tree.nodeIsTerminal(node)){
+			if (!MesquiteDouble.isCombinable(depth))
+				depth = 0;
+			return depth;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			double daughterDepth = visitNodes(d, tree);
+			if (MesquiteDouble.isCombinable(daughterDepth) && MesquiteDouble.isCombinable(depth))
+				tree.setBranchLength(d, depth-daughterDepth, false);
+			else
+				tree.setBranchLength(d, MesquiteDouble.unassigned, false);
+		}
+		return depth;
+	}
+	/*.................................................................................................................*/
+	public double cleanInversions(int node, AdjustableTree tree, MesquiteBoolean clean) {
+		if (!clean.isUnassigned() && !clean.getValue())
+			return 0;
+		double depth = tree.getBranchLength(node);
+		if (tree.nodeIsTerminal(node)){
+			if (!MesquiteDouble.isCombinable(depth))
+				depth = 0;
+			return depth;
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && (clean.getValue() || clean.isUnassigned()); d = tree.nextSisterOfNode(d)) {
+			double daughterDepth = cleanInversions(d, tree, clean);
+			boolean 	inverted = MesquiteDouble.isCombinable(daughterDepth) && MesquiteDouble.isCombinable(depth) && daughterDepth>depth;
+			boolean missing = MesquiteDouble.isCombinable(daughterDepth) && !MesquiteDouble.isCombinable(depth);
+
+			if (inverted || missing){
+					if (clean.isUnassigned()){
+						if (!MesquiteThread.isScripting()){
+							if (AlertDialog.query(containerOfModule(), "Clean up divergences?", "This tree has inverted divergence times (with a daughter node older than a parent node) or missing divergence times.  Do you want to interpret branch lengths with these problems cleaned up, if possible?", "Clean Up", "Don't Clean Up"))
+								clean.setValue(true);
+							else
+								clean.setValue(false);
+						}
+					}
+					if (!clean.isUnassigned() && !clean.getValue())
+						return 0;
+					tree.setBranchLength(node, daughterDepth, false);
+					depth = daughterDepth;
+				}
+
+
+		}
+		return depth;
+	}
+	/*.................................................................................................................*/
+	//Should be overridden; when previous version is deleted in future, this will be abstract.  returns whether successfully transformed.
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree == null)
+			return false;
+		MesquiteBoolean clean = new MesquiteBoolean(true);
+		clean.setToUnassigned();
+		
+		cleanInversions(tree.getRoot(), tree, clean);
+
+		visitNodes(tree.getRoot(), tree);
+
+		if (notify && tree instanceof Listened)
+			((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+		return true;
+
+
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 274;  
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/BlockDirectlyFromFile/BlockDirectlyFromFile.java b/Source/mesquite/treefarm/BlockDirectlyFromFile/BlockDirectlyFromFile.java
new file mode 100644
index 0000000..52c1487
--- /dev/null
+++ b/Source/mesquite/treefarm/BlockDirectlyFromFile/BlockDirectlyFromFile.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.BlockDirectlyFromFile;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.treefarm.lib.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies tree blocks from other sources.*/
+public class BlockDirectlyFromFile extends BlockFromTreeSource { //BlockFromTreeSource
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.trees.ManyTreesFromFile.ManyTreesFromFile.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially");
+	}
+	/*.................................................................................................................*/
+ 	 public String getSource(){
+ 		 return "#ManyTreesFromFile";
+ 	 }
+	/*.................................................................................................................*/
+	 public boolean enableNumTreesChoice(){
+ 	 	return false;
+   	 }
+
+	/*.................................................................................................................*/
+    public String getName() {
+		return "Tree Block Directly From File";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies a block of trees directly from a file";
+   	 }
+ 	/*.................................................................................................................*/
+  	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+  	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+  	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+     	public int getVersionOfFirstRelease(){
+     		return 110;  
+     	}
+     	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+     		return false;
+     	}
+}
+
diff --git a/Source/mesquite/treefarm/CladeInTree/CladeInTree.java b/Source/mesquite/treefarm/CladeInTree/CladeInTree.java
new file mode 100644
index 0000000..a9bda65
--- /dev/null
+++ b/Source/mesquite/treefarm/CladeInTree/CladeInTree.java
@@ -0,0 +1,95 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CladeInTree;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** this is a little module that deterimines whether or not a set of taxa is a clade in a tree */
+public class CladeInTree extends BooleanForTree implements MesquiteListener {
+	Taxa currentTaxa = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+  	 public void endJob(){
+  	 	if (currentTaxa != null)
+  	 		currentTaxa.removeListener(this);
+  	 	super.endJob();
+  	 }
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && code == MesquiteListener.SELECTION_CHANGED){
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString) {
+    	 	if (result==null || tree==null)
+    	 		return;
+		Taxa taxa = tree.getTaxa();
+		if (currentTaxa != taxa){
+			if (currentTaxa != null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+		
+		if (!taxa.anySelected()) {
+ 			return;
+		}
+		boolean bt = tree.isClade(taxa.getSelectedBits());
+		result.setValue(bt);
+		if (resultString!=null)
+			if (bt)
+				resultString.setValue("Clade present");
+			else
+				resultString.setValue("Clade absent");
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Selected Taxa Form Clade";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Clade?";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Determines if the selected taxa form a clade in a tree." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/CladeMatch/CladeMatch.java b/Source/mesquite/treefarm/CladeMatch/CladeMatch.java
new file mode 100755
index 0000000..5c626bb
--- /dev/null
+++ b/Source/mesquite/treefarm/CladeMatch/CladeMatch.java
@@ -0,0 +1,165 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.CladeMatch;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class CladeMatch extends NumbersForNodes {
+	public String getExplanation() {
+		return "Calculates a number relating each clade in the tree to another current tree (e.g., a tree-to-tree distance metric).";
+	}
+	public String getName() {
+		return "Clade Match with Another Current Tree";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of a comparison tree.",
+		"The source of comparison tree is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(NumberFor2Trees.class, getName() + "  needs a method to compare trees.",
+		"The method to compare trees can be chosen initially or in the Tree-Tree Value submenu");
+	}
+	Tree otherTree = null;
+	OneTreeSource otherTreeTask;
+	NumberFor2Trees treeDifferenceTask;		// module that calculates inter-tree distances
+	MesquiteString treeDifferenceTaskName;	// String for use in subment for distance metric
+	MesquiteCommand tdC;					// Command to react to menu choice of tree difference metric
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		otherTreeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree for comparison");
+		if (otherTreeTask == null) {
+			return sorry(getName() + " couldn't start because no source of a comparison tree was obtained.");
+		}
+		treeDifferenceTask = (NumberFor2Trees)hireEmployee(NumberFor2Trees.class, "Value to calculate between tree and other tree");
+		if (treeDifferenceTask == null) {
+			return sorry(getName() + " couldn't start because no module to calculate a number for 2 trees was obtained.");
+		}
+		tdC = makeCommand("setTreeDifferenceTask",  this);
+		treeDifferenceTask.setHiringCommand(tdC);
+		treeDifferenceTaskName = new MesquiteString(treeDifferenceTask.getName());
+		if (numModulesAvailable(NumberFor2Trees.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree-Tree Value", tdC, NumberFor2Trees.class);
+			mss.setSelected(treeDifferenceTaskName);
+		}
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeSource ", otherTreeTask); 
+		temp.addLine("setTreeDifferenceTask ", treeDifferenceTask);
+		return temp;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree-to-tree value calculator", "[name of module]", commandName, "setTreeDifferenceTask")) {
+			NumberFor2Trees temp = (NumberFor2Trees)replaceEmployee(NumberFor2Trees.class, arguments, "Tree-to-tree value", treeDifferenceTask);
+			if (temp != null) {
+				treeDifferenceTask = temp;
+				treeDifferenceTask.setHiringCommand(tdC);
+				treeDifferenceTaskName.setValue(treeDifferenceTask.getName());
+				parametersChanged();
+			}
+			return treeDifferenceTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of the comparison tree", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of other tree", otherTreeTask);
+			if (temp !=null){
+				otherTreeTask = temp;
+				parametersChanged();
+				return otherTreeTask;
+			}
+		}
+		else 
+			 super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (otherTreeTask!=null)
+			otherTreeTask.initialize(tree.getTaxa());
+		if (treeDifferenceTask!=null)
+			treeDifferenceTask.initialize(tree, otherTree);
+	}
+	/*.................................................................................................................*/
+	MesquiteTree tempTree;
+	public   void visitNodes(int node, Tree tree, Tree otherTree, NumberArray result) {
+		if (tree.nodeIsInternal(node)){// && tree.numberOfTerminalsInClade(node)>3){
+			tempTree.readTree(tree.writeClade(node, MesquiteTree.BY_NUMBERS, false));
+			MesquiteNumber mN = new MesquiteNumber();
+			mN.setToUnassigned();
+			treeDifferenceTask.calculateNumber(tempTree, otherTree, mN, null);
+			result.setValue(node, mN);
+
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			visitNodes(d, tree, otherTree, result);
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree == null || otherTreeTask==null)
+			return;
+
+		otherTree = otherTreeTask.getTree(tree.getTaxa());
+		if (otherTree == null||treeDifferenceTask == null)
+			return;
+		tempTree = new MesquiteTree(tree.getTaxa());
+		visitNodes(tree.getRoot(), tree, otherTree, result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (treeDifferenceTask ==null)
+			return null;
+		String s = "Comparison: " + treeDifferenceTask.getName(); 
+		if (otherTree !=null)
+			s += "; comparison tree: " + otherTree;
+		return s;
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (treeDifferenceTask ==null)
+			return getName();
+		String s = treeDifferenceTask.getName(); 
+		if (otherTree !=null)
+			s += "; comparison tree: " + otherTree;
+		return s; 
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/CollessImbalance/CollessImbalance.java b/Source/mesquite/treefarm/CollessImbalance/CollessImbalance.java
new file mode 100644
index 0000000..4a0a7d9
--- /dev/null
+++ b/Source/mesquite/treefarm/CollessImbalance/CollessImbalance.java
@@ -0,0 +1,85 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CollessImbalance;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class CollessImbalance extends NumberForTree {
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+	}
+	
+	/** Calculates asymmetry*/
+	private double asymmetry(Tree tree, int node) {
+		double asymm = 0;
+		if (tree.nodeIsInternal(node)) { 
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+	  			asymm += asymmetry(tree, daughter);
+  	 		if (!tree.nodeIsPolytomous(node)){
+	  	 		double numLeft =tree.numberOfTerminalsInClade(tree.firstDaughterOfNode(node));
+	   	 		double numRight =tree.numberOfTerminalsInClade(tree.lastDaughterOfNode(node));
+	 	 		if (numRight>numLeft)
+	 	 			asymm +=(numRight-numLeft);
+	 	 		else
+	 	 			asymm +=(numLeft-numRight);
+ 	 		}
+ 	
+  		}
+  		return asymm;
+  	 }
+  	 
+	/** (called in case this module needs to initialize anything; this module doesn't) */
+   	public void initialize(Tree tree){
+   	}
+   	
+	/** The key method of ObjFcnForTree modules have, called to return a number*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		double asymm = asymmetry(tree, tree.getRoot());
+		int n = tree.numberOfTerminalsInClade(tree.getRoot());
+		asymm = asymm*2.0/((n-1)*(n-2)); //Colless indicated to divide by (n(n-3)+1)/2 but that's in error: it is not the maximum asymmetry
+		result.setValue(asymm);
+		if (resultString!=null)
+			resultString.setValue("Colless's Imbalance: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	
+	/** Explains what the module does.*/
+    	 public String getExplanation() {
+		return "Calculates Colless's Imbalance statistic for tree asymmetry, normalized by maximum asymmetry.  Polytmous nodes are ignored in the calculation.";
+   	 }
+   	 
+	/** Returns the name of the module in very short form, for use for column headings and other constrained places.*/
+ 	public String getVeryShortName(){
+ 		return "Imbalance";
+ 	}
+ 	
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/** Name of module*/
+    	 public String getName() {
+		return "Colless's Imbalance";
+   	 }
+
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/CompareOtherTree/CompareOtherTree.java b/Source/mesquite/treefarm/CompareOtherTree/CompareOtherTree.java
new file mode 100644
index 0000000..8b7aa2a
--- /dev/null
+++ b/Source/mesquite/treefarm/CompareOtherTree/CompareOtherTree.java
@@ -0,0 +1,151 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CompareOtherTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class CompareOtherTree extends NumberForTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of a comparison tree.",
+		"The source of comparison tree is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(NumberFor2Trees.class, getName() + "  needs a method to compare trees.",
+		"The method to compare trees can be chosen initially or in the Tree-Tree Value submenu");
+	}
+	Tree otherTree = null;
+	OneTreeSource otherTreeTask;
+	NumberFor2Trees treeDifferenceTask;		// module that calculates inter-tree distances
+	MesquiteString treeDifferenceTaskName;	// String for use in subment for distance metric
+	MesquiteCommand tdC;					// Command to react to menu choice of tree difference metric
+	MesquiteNumber lastValue;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		otherTreeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree for comparison");
+ 		if (otherTreeTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of a comparison tree was obtained.");
+ 		}
+		treeDifferenceTask = (NumberFor2Trees)hireEmployee(NumberFor2Trees.class, "Value to calculate between tree and other tree");
+		if (treeDifferenceTask == null) {
+			return sorry(getName() + " couldn't start because no module to calculate a number for 2 trees was obtained.");
+		}
+		tdC = makeCommand("setTreeDifferenceTask",  this);
+		treeDifferenceTask.setHiringCommand(tdC);
+		treeDifferenceTaskName = new MesquiteString(treeDifferenceTask.getName());
+		if (numModulesAvailable(NumberFor2Trees.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree-Tree value", tdC, NumberFor2Trees.class);
+			mss.setSelected(treeDifferenceTaskName);
+		}
+		lastValue = new MesquiteNumber();
+ 		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", otherTreeTask); 
+  	 	temp.addLine("setTreeDifferenceTask ", treeDifferenceTask);
+		return temp;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree-to-tree value calculator", "[name of module]", commandName, "setTreeDifferenceTask")) {
+			NumberFor2Trees temp = (NumberFor2Trees)replaceEmployee(NumberFor2Trees.class, arguments, "Tree-to-tree value", treeDifferenceTask);
+			if (temp != null) {
+				treeDifferenceTask = temp;
+				treeDifferenceTask.setHiringCommand(tdC);
+				treeDifferenceTaskName.setValue(treeDifferenceTask.getName());
+				parametersChanged();
+			}
+			return treeDifferenceTask;
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the source of the comparison tree", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of other tree", otherTreeTask);
+			if (temp !=null){
+				otherTreeTask = temp;
+				parametersChanged();
+    	 			return otherTreeTask;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns most recent value calculated", null, commandName, "getMostRecentNumber")) {
+ 			return lastValue;
+    	 	}
+		else 
+			 super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (otherTreeTask!=null)
+   			otherTreeTask.initialize(tree.getTaxa());
+   		if (treeDifferenceTask!=null)
+   			treeDifferenceTask.initialize(tree, otherTree);
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		lastValue.setToUnassigned();
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree == null || otherTreeTask==null)
+			return;
+		otherTree = otherTreeTask.getTree(tree.getTaxa());
+		if (otherTree == null||treeDifferenceTask == null)
+			return;
+		treeDifferenceTask.calculateNumber(tree, otherTree, result, resultString);
+		if (resultString!=null)
+			resultString.setValue(resultString.toString() + " with tree: " + otherTree.getName());
+		lastValue.setValue(result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (treeDifferenceTask ==null)
+			return null;
+		String s = "Comparison: " + treeDifferenceTask.getName(); 
+		if (otherTree !=null)
+			s += "; comparison tree: " + otherTree;
+		return s;
+   	 }
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (treeDifferenceTask ==null)
+			return getName();
+		String s = treeDifferenceTask.getName(); 
+		if (otherTree !=null)
+			s += "; comparison tree: " + otherTree;
+		return s; 
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Compare with Another Current Tree";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates a number relating a tree and another current tree (e.g., a tree-to-tree distance metric).";
+   	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+}
+
diff --git a/Source/mesquite/treefarm/CompareOtherTrees/CompareOtherTrees.java b/Source/mesquite/treefarm/CompareOtherTrees/CompareOtherTrees.java
new file mode 100644
index 0000000..08faa87
--- /dev/null
+++ b/Source/mesquite/treefarm/CompareOtherTrees/CompareOtherTrees.java
@@ -0,0 +1,148 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CompareOtherTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class CompareOtherTrees extends NumberForTree {
+ 	 public String getName() {
+ 		return "Compare with Other Trees";
+    	 }
+   	 public String getExplanation() {
+ 		return "Calculates a number relating one tree to another in a sequence (e.g., a tree-to-tree distance metric), such that the i'th tree is compared to the i'th other tree in the sequence.";
+    	 }
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of comparison trees.",
+		"The source of comparison tree is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(NumberFor2Trees.class, getName() + "  needs a method to compare trees.",
+		"The method to compare trees can be chosen initially or in the Tree-Tree Value submenu");
+		//e2.setDivertChainMessage("testing");
+	}
+	Tree otherTree = null;
+	TreeSource otherTreeTask;
+	NumberFor2Trees treeDifferenceTask;		// module that calculates inter-tree distances
+	MesquiteString treeDifferenceTaskName;	// String for use in subment for distance metric
+	MesquiteCommand tdC;					// Command to react to menu choice of tree difference metric
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		otherTreeTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees for comparison");
+ 		if (otherTreeTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of a comparison tree was obtained.");
+ 		}
+		treeDifferenceTask = (NumberFor2Trees)hireEmployee(NumberFor2Trees.class, "Value to calculate between tree and other tree");
+		if (treeDifferenceTask == null) {
+			return sorry(getName() + " couldn't start because no module to calculate a number for 2 trees was obtained.");
+		}
+		tdC = makeCommand("setTreeDifferenceTask",  this);
+		treeDifferenceTask.setHiringCommand(tdC);
+		treeDifferenceTaskName = new MesquiteString(treeDifferenceTask.getName());
+		if (numModulesAvailable(NumberFor2Trees.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree-Tree Value", tdC, NumberFor2Trees.class);
+			mss.setSelected(treeDifferenceTaskName);
+		}
+ 		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", otherTreeTask); 
+  	 	temp.addLine("setTreeDifferenceTask ", treeDifferenceTask);
+		return temp;
+	}
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree-to-tree value calculator", "[name of module]", commandName, "setTreeDifferenceTask")) {
+			NumberFor2Trees temp = (NumberFor2Trees)replaceEmployee(NumberFor2Trees.class, arguments, "Tree-to-tree value", treeDifferenceTask);
+			if (temp != null) {
+				treeDifferenceTask = temp;
+				treeDifferenceTask.setHiringCommand(tdC);
+				treeDifferenceTaskName.setValue(treeDifferenceTask.getName());
+				parametersChanged();
+			}
+			return treeDifferenceTask;
+		}
+    	 	else if (checker.compare(this.getClass(), "Sets the source of the comparison trees", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of other trees", otherTreeTask);
+			if (temp !=null){
+				otherTreeTask = temp;
+				parametersChanged();
+    	 			return otherTreeTask;
+    	 		}
+    	 	}
+		else 
+			 super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		if (otherTreeTask!=null)
+   			otherTreeTask.initialize(tree.getTaxa());
+   		if (treeDifferenceTask!=null)
+   			treeDifferenceTask.initialize(tree, otherTree);
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+
+		if (tree == null || otherTreeTask==null || !(tree instanceof MesquiteTree))
+			return;
+		int i = ((MesquiteTree)tree).getAssignedNumber();
+		if (i<0)
+			return;
+		otherTree = otherTreeTask.getTree(tree.getTaxa(), i);
+		if (otherTree == null||treeDifferenceTask == null)
+			return;
+		treeDifferenceTask.calculateNumber(tree, otherTree, result, resultString);
+		if (resultString!=null)
+			resultString.setValue(resultString.toString() + " with tree: " + otherTree.getName());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (employee != otherTreeTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+ 			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (treeDifferenceTask ==null)
+			return null;
+		String s = "Comparison: " + treeDifferenceTask.getName() + "; Source of comparison trees: " + otherTreeTask.getName(); 
+		return s;
+   	 }
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (treeDifferenceTask ==null)
+			return getName();
+		return treeDifferenceTask.getName() + "; compared to: " + otherTreeTask.getNameAndParameters(); 
+	}
+	/*.................................................................................................................*/
+     	public boolean isPrerelease(){
+   		return false;
+   	}
+}
+
diff --git a/Source/mesquite/treefarm/Concat2TreeSources/Concat2TreeSources.java b/Source/mesquite/treefarm/Concat2TreeSources/Concat2TreeSources.java
new file mode 100644
index 0000000..e2f094e
--- /dev/null
+++ b/Source/mesquite/treefarm/Concat2TreeSources/Concat2TreeSources.java
@@ -0,0 +1,332 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.Concat2TreeSources;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class Concat2TreeSources extends TreeSource {
+	public String getName() {
+		return "Concatenate Two Tree Sources";
+	}
+	public String getNameForMenuItem() {
+		return "Concatenate 2 Tree Sources...";
+	}
+	public String getExplanation() {
+		return "Concatenates two tree sources to yield a tree source first supplying trees from one source, then supplying trees from another.  The trees are marked with values 1 and 2 to indicate the source.";
+	}
+
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		super.getEmployeeNeeds();
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a method to modify trees.",
+		"The method to modify trees can be chosen initially or in the Transformer of Trees submenu");
+	}
+	TreeSource treeSourceA, treeSourceB;
+	MesquiteString sourceAName, sourceBName;
+	MesquiteCommand stA, stB;
+	Taxa taxa;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeSourceA = (TreeSource)hireEmployee(TreeSource.class, "First source of trees to be concatenated");
+		if (treeSourceA == null) {
+			return sorry(getName() + " couldn't start because no source of trees was obtained.");
+		}
+		treeSourceB = (TreeSource)hireEmployee(TreeSource.class, "Second source of trees to be concatenated");
+		if (treeSourceB == null) {
+			return sorry(getName() + " couldn't start because no source of trees was obtained.");
+		}
+		sourceAName = new MesquiteString();
+		sourceAName.setValue(treeSourceA.getName());
+		sourceBName = new MesquiteString();
+		sourceBName.setValue(sourceBName.getName());
+		stA = makeCommand("setTreeSourceA",  this);
+		treeSourceA.setHiringCommand(stA);
+		stB = makeCommand("setTreeSourceB",  this);
+		treeSourceA.setHiringCommand(stB);
+		if (numModulesAvailable(TreeSource.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "First source of trees to be concatenated", stA, TreeSource.class);
+			mss.setSelected(sourceAName);
+			MesquiteSubmenuSpec mss2 = addSubmenu(null, "Second source of trees to be concatenated", stB, TreeSource.class);
+			mss2.setSelected(sourceBName);
+		}
+
+		return true;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee) {
+		if (employee == treeSourceA)
+			return "First source of trees"; //transfers info to employer, as ithis is coordinator
+		else if (employee == treeSourceB)
+			return "Second source of trees";	
+		else
+			return  "for " + getName();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setTreeSourceA ", treeSourceA); 
+		temp.addLine("setTreeSourceB ", treeSourceB); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the first source of trees", "[name of module]", commandName, "setTreeSourceA")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "First source of trees", treeSourceA);
+			if (temp !=null){
+				treeSourceA = temp;
+				sourceAName.setValue(treeSourceA.getName());
+				treeSourceA.setHiringCommand(stA);
+				resetContainingMenuBar();
+				parametersChanged();
+				return treeSourceA;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the second source of trees", "[name of module]", commandName, "setTreeSourceB")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Second source of trees", treeSourceB);
+			if (temp !=null){
+				treeSourceB = temp;
+				sourceBName.setValue(treeSourceB.getName());
+				treeSourceB.setHiringCommand(stB);
+				resetContainingMenuBar();
+				parametersChanged();
+				return treeSourceB;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees for the first source", "[number of trees]", commandName, "assignNumTreesA")) {
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(newNum) && newNum>0 ) {
+				numTreesAssignedA = newNum;
+				assignedA = true;
+			}
+			else {
+				assignedA = false;
+				resetTreeSource(taxa, true);
+			}
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees for the second source", "[number of trees]", commandName, "assignNumTreesB")) {
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(newNum) && newNum>0 ) {
+				numTreesAssignedB = newNum;
+				assignedB = true;
+			}
+			else {
+				assignedB = false;
+				resetTreeSource(taxa, true);
+			}
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	int defaultNumberOfItems = 100;
+	int numTreesAssignedA = MesquiteInteger.unassigned;
+	int numTreesAssignedB = MesquiteInteger.unassigned;
+	boolean assignedA = false;
+	boolean assignedB = false;
+	MesquiteMenuItemSpec numTreesAItem = null;
+	MesquiteMenuItemSpec numTreesBItem = null;
+	/*.................................................................................................................*/
+	public void resetTreeSource( Taxa taxa, boolean queryPlease){
+		int numItems=treeSourceA.getNumberOfTrees(taxa, true); //this can't be infinite; if so then ask for number
+		if (!MesquiteInteger.isCombinable(numItems) && MesquiteInteger.finite != numItems) { //not specified; need to set
+			if (queryPlease || (!assignedA)) {
+				numTreesAssignedA = defaultNumberOfItems;
+				if (!MesquiteThread.isScripting()) {
+					numTreesAssignedA = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees from first source.", numTreesAssignedA);
+					if (!MesquiteInteger.isCombinable(numTreesAssignedA)) 
+						numTreesAssignedA = defaultNumberOfItems;
+				}
+			}
+			assignedA = true;
+			if (numTreesAItem == null) {
+				numTreesAItem = addMenuItem( "Number of  Trees from First Source...", makeCommand("assignNumTreesA",  this));
+				resetContainingMenuBar();
+			}
+		}
+		else  {
+			if (numTreesAItem!= null) {
+				deleteMenuItem(numTreesAItem);
+				resetContainingMenuBar();
+				numTreesAItem = null;
+			}
+			assignedA = false;
+			numTreesAssignedA = numItems;
+
+		}
+		numItems=treeSourceB.getNumberOfTrees(taxa, true); //this can't be infinite; if so then ask for number
+		if (!MesquiteInteger.isCombinable(numItems) && MesquiteInteger.finite != numItems) { //not specified; need to set
+			if (queryPlease || (!assignedB)) {
+				numTreesAssignedB = defaultNumberOfItems;
+				if (!MesquiteThread.isScripting()) {
+					numTreesAssignedB = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees from second source.", numTreesAssignedB);
+					if (!MesquiteInteger.isCombinable(numTreesAssignedB)) 
+						numTreesAssignedB = defaultNumberOfItems;
+				}
+			}
+			assignedB = true;
+			if (numTreesBItem == null) {
+				numTreesBItem = addMenuItem( "Number of  Trees from Second Source...", makeCommand("assignNumTreesB",  this));
+				resetContainingMenuBar();
+			}
+		}
+		else  {
+			if (numTreesBItem!= null) {
+				deleteMenuItem(numTreesBItem);
+				resetContainingMenuBar();
+				numTreesBItem = null;
+			}
+			assignedB = false;
+			numTreesAssignedB = numItems;
+
+		}
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		this.taxa = taxa;
+		treeSourceA.setPreferredTaxa(taxa);
+		treeSourceB.setPreferredTaxa(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		treeSourceA.initialize(taxa);
+		treeSourceB.initialize(taxa);
+		
+	}
+
+	/*.................................................................................................................*/
+	MesquiteColorTable colorTable;
+  	public void prepareItemColors(Taxa taxa){
+  		colorTable = new MesquiteColorTable();
+  		colorTable.setMode(MesquiteColorTable.COLORS_NO_BW);
+   	}
+  	
+   	public Color getItemColor(Taxa taxa, int itree){
+   		int whichSource = findSource(taxa, itree);
+   		if (whichSource <0 || colorTable == null)
+   			return Color.lightGray;
+   		else
+   			return colorTable.getColor(2, whichSource);
+
+   	}
+   	private int findSource(Taxa taxa, int itree){
+		setPreferredTaxa(taxa);
+		Tree t = null;
+		if (numTreesAssignedA != MesquiteInteger.finite) {
+			if (itree <numTreesAssignedA)
+				return 1;
+			else
+				return 2;
+		}
+		else {
+			t = treeSourceA.getTree(taxa, itree);
+			if (t == null){
+				int nA = treeSourceA.getNumberOfTrees(taxa, true);
+				if (!MesquiteInteger.isCombinable(nA))
+					return -1;
+				numTreesAssignedA = nA;
+				if (itree>= nA)
+					return 2;
+			}
+			else
+				return 1;
+		}
+		return -1;
+ 	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		int whichSource = 0;
+		Tree t;
+		if (numTreesAssignedA != MesquiteInteger.finite) {
+			if (itree <numTreesAssignedA){
+				t = treeSourceA.getTree(taxa, itree);
+				whichSource = 1;
+			}
+			else{
+				t= treeSourceB.getTree(taxa, itree - numTreesAssignedA);
+				whichSource = 2;
+			}
+		}
+		else {
+			t = treeSourceA.getTree(taxa, itree);
+			if (t == null){
+				int nA = treeSourceA.getNumberOfTrees(taxa, true);
+				if (!MesquiteInteger.isCombinable(nA))
+					return null;
+				numTreesAssignedA = nA;
+				if (itree>= nA){
+					t = treeSourceB.getTree(taxa, itree - numTreesAssignedA);
+					whichSource = 2;
+				}
+			}
+			else
+				whichSource = 1;
+		}
+		if (t == null)
+			return null;
+		MesquiteTree tree = new MesquiteTree(taxa);
+		if (t instanceof MesquiteTree)
+			tree.setToClone((MesquiteTree)t);
+		else 
+			tree.setToCloneFormOnly(t);
+		tree.attach(new MesquiteLong("Which Source",  whichSource));
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		resetTreeSource(taxa, false);
+		if (numTreesAssignedA == MesquiteInteger.finite || numTreesAssignedB == MesquiteInteger.finite)
+			return MesquiteInteger.finite;
+		return numTreesAssignedA + numTreesAssignedB;
+	}
+	int numTreesA = MesquiteInteger.unassigned;
+	int numTreesB = MesquiteInteger.unassigned;
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		Tree t = getTree(taxa, itree);
+		if (t == null)
+			return "NO TREE";
+		return t.getName();
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return"Trees from two sources: " + treeSourceA.getNameAndParameters() + " AND " + treeSourceB.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/treefarm/ConcatMultTreeSources/ConcatMultTreeSources.java b/Source/mesquite/treefarm/ConcatMultTreeSources/ConcatMultTreeSources.java
new file mode 100644
index 0000000..d341b42
--- /dev/null
+++ b/Source/mesquite/treefarm/ConcatMultTreeSources/ConcatMultTreeSources.java
@@ -0,0 +1,320 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.ConcatMultTreeSources;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class ConcatMultTreeSources extends TreeSource {
+	public String getName() {
+		return "Concatenate Multiple Tree Sources";
+	}
+	public String getNameForMenuItem() {
+		return "Concatenate Multiple Tree Sources...";
+	}
+	public String getExplanation() {
+		return "Concatenates multiple tree sources to yield a tree source supplying trees from each source.  The trees are marked with values to indicate the source.";
+	}
+
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+	public boolean isPrerelease(){
+		return false;  
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		super.getEmployeeNeeds();
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a method to modify trees.",
+		"The method to modify trees can be chosen initially or in the Transformer of Trees submenu");
+	}
+	Vector sources = new Vector();
+	Vector assignedNumbers = new Vector();
+	Vector isAssigned = new Vector();
+	Taxa taxa;
+	int defaultNumberOfItems = 100;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (!MesquiteThread.isScripting()){
+			TreeSource treeSourceA = (TreeSource)hireEmployee(TreeSource.class, "First source of trees to be concatenated");
+			if (treeSourceA == null) {
+				return sorry(getName() + " couldn't start because no source of trees was obtained.");
+			}
+			sources.addElement(treeSourceA);
+			assignedNumbers.addElement(new MesquiteInteger());
+			isAssigned.addElement(new MesquiteBoolean(false));
+			TreeSource treeSourceB = (TreeSource)hireEmployee(TreeSource.class, "Second source of trees to be concatenated");
+			if (treeSourceB == null) {
+				return sorry(getName() + " couldn't start because a second source of trees was not obtained.");
+			}
+			sources.addElement(treeSourceB);
+			assignedNumbers.addElement(new MesquiteInteger());
+			isAssigned.addElement(new MesquiteBoolean(false));
+			TreeSource source = null;
+			int i = 3;
+			do {
+				acceptEmployeeHireCancel(true);
+				source = (TreeSource)hireEmployee(TreeSource.class, "Next source of trees to be concatenated (#" + i + ").  Hit Cancel to indicate no more sources needed.");
+				acceptEmployeeHireCancel(false);
+				if (source != null) {
+					sources.addElement(source);
+					assignedNumbers.addElement(new MesquiteInteger());
+					isAssigned.addElement(new MesquiteBoolean(false));
+				}
+				
+				i++;
+			}
+			while (source != null);
+		}
+		return true;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee) {
+		int w = sources.indexOf(employee);
+		if (w>=0)
+			return "Source of trees #"  + (w+1); 
+		else
+			return  "for " + getName();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+
+	/*.................................................................................................................*/
+	boolean isNumberAssigned(TreeSource source){
+		int which = sources.indexOf(source);
+		if (which >=0 && which < isAssigned.size())
+			return ((MesquiteBoolean)isAssigned.elementAt(which)).getValue();
+		return false;
+	}
+	void setIsNumberAssigned(int i, boolean assigned){
+		if (i >=0 && i < isAssigned.size())
+			((MesquiteBoolean)isAssigned.elementAt(i)).setValue(assigned);
+	}
+	void setIsNumberAssigned(TreeSource source, boolean assigned){
+		int which = sources.indexOf(source);
+		setIsNumberAssigned(which, assigned);
+	}
+	int getNumberAssigned(int i){
+		if (i >=0 && i < assignedNumbers.size())
+			return ((MesquiteInteger)assignedNumbers.elementAt(i)).getValue();
+		return MesquiteInteger.unassigned;
+	}
+	void setNumberAssigned(int i, int num){
+		if (i >=0 && i < assignedNumbers.size())
+			((MesquiteInteger)assignedNumbers.elementAt(i)).setValue(num);
+	}
+	void setNumberAssigned(TreeSource source,  int num){
+		int which = sources.indexOf(source);
+		setNumberAssigned(which, num);
+	}
+	/*.................................................................................................................*/
+	MesquiteColorTable colorTable;
+  	public void prepareItemColors(Taxa taxa){
+  		colorTable = new MesquiteColorTable();
+  		colorTable.setMode(MesquiteColorTable.COLORS_NO_BW);
+   	}
+  	
+   	public Color getItemColor(Taxa taxa, int itree){
+   		int whichSource = findSource(taxa, itree);
+   		if (whichSource <0 || sources == null || colorTable == null)
+   			return Color.lightGray;
+   		else
+   			return colorTable.getColor(sources.size(), whichSource);
+
+   	}
+   	private int findSource(Taxa taxa, int itree){
+		setPreferredTaxa(taxa);
+		Tree t = null;
+		int sum = 0;
+		for (int i= 0; i<sources.size() && t == null; i++){
+			int nta = getNumberAssigned(i);
+			TreeSource source = (TreeSource)sources.elementAt(i);
+			if (nta != MesquiteInteger.finite) {
+				if (itree <nta + sum)
+					return i;
+				sum += nta;
+			}
+			else {
+				t = source.getTree(taxa, itree);
+
+				if (t == null){
+					nta = source.getNumberOfTrees(taxa, true);
+					if (!MesquiteInteger.isCombinable(nta))
+						return -1;
+					if (itree  < nta + sum)
+						return i;
+					sum += nta;
+				}
+			}
+		}
+		return -1;
+ 	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		for (int i = 0; i<sources.size(); i++){
+			temp.addLine("addTreeSource ", (TreeSource)sources.elementAt(i)); 
+			if (isNumberAssigned((TreeSource)sources.elementAt(i)))
+				temp.addLine("assignNumTrees " + i + "  " + getNumberAssigned(i)); 
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Adds a source of trees", "[name of module]", commandName, "addTreeSource")) {
+			TreeSource temp = (TreeSource)hireNamedEmployee(TreeSource.class, arguments, null);
+			if (temp !=null){
+				sources.addElement(temp);
+				assignedNumbers.addElement(new MesquiteInteger());
+				isAssigned.addElement(new MesquiteBoolean(false));
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees for the first source", "[number of trees]", commandName, "assignNumTrees")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			int newNum = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(which) && MesquiteInteger.isCombinable(newNum) && newNum>0 ) {
+				setNumberAssigned(which, newNum);
+				setIsNumberAssigned(which, true);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	void resetSource(TreeSource source, Taxa taxa, boolean queryPlease){
+		int numItems = source.getNumberOfTrees(taxa, true); //this can't be infinite; if so then ask for number
+		if (!MesquiteInteger.isCombinable(numItems) && MesquiteInteger.finite != numItems) { //not specified; need to set
+			if (!isNumberAssigned(source) || queryPlease) {
+				int numTreesAssigned = defaultNumberOfItems;
+				if (!MesquiteThread.isScripting()) {
+					numTreesAssigned = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees from source #" + (sources.indexOf(source)+1) + " [" + source.getNameAndParameters() + "]", numTreesAssigned);
+					if (!MesquiteInteger.isCombinable(numTreesAssigned)) 
+						numTreesAssigned = defaultNumberOfItems;
+				}
+				setNumberAssigned(source, numTreesAssigned);
+			}
+			setIsNumberAssigned(source, true);
+		}
+		else {
+			setNumberAssigned(source, numItems);
+			setIsNumberAssigned(source, false);
+
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetTreeSource( Taxa taxa, boolean queryPlease){
+		for (int i = 0; i<sources.size(); i++)
+			resetSource((TreeSource)sources.elementAt(i), taxa, queryPlease);
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		this.taxa = taxa;
+		for (int i = 0; i<sources.size(); i++)
+			((TreeSource)sources.elementAt(i)).setPreferredTaxa(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		for (int i = 0; i<sources.size(); i++)
+			((TreeSource)sources.elementAt(i)).initialize(taxa);
+	}
+
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		int whichSource = 0;
+		Tree t = null;
+		int sum = 0;
+		for (int i= 0; i<sources.size() && t == null; i++){
+			int nta = getNumberAssigned(i);
+			TreeSource source = (TreeSource)sources.elementAt(i);
+			if (nta != MesquiteInteger.finite) {
+				if (itree <nta + sum){
+					t = source.getTree(taxa, itree-sum);
+					whichSource = i;
+				}
+				sum += nta;
+			}
+			else {
+				t = source.getTree(taxa, itree);
+
+				if (t == null){
+					nta = source.getNumberOfTrees(taxa, true);
+					if (!MesquiteInteger.isCombinable(nta))
+						return null;
+					setNumberAssigned(source, nta);
+					setIsNumberAssigned(source, true);
+					if (itree  < nta + sum){
+						t = source.getTree(taxa, itree - sum);
+						whichSource = i;
+					}
+					sum += nta;
+				}
+			}
+		}
+		if (t == null)
+			return null;
+		MesquiteTree tree = new MesquiteTree(taxa);
+		if (t instanceof MesquiteTree)
+			tree.setToClone((MesquiteTree)t);
+		else 
+			tree.setToCloneFormOnly(t);
+		tree.attach(new MesquiteLong("Which Source",  whichSource));
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		resetTreeSource(taxa, false);
+		int sum = 0;
+		for (int i = 0; i<sources.size(); i++){
+			int nta = getNumberAssigned(i);
+			if (nta == MesquiteInteger.finite)
+				return MesquiteInteger.finite;
+			sum += nta;
+		}
+		return sum;
+	}
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		Tree t = getTree(taxa, itree);
+		if (t == null)
+			return "NO TREE";
+		return t.getName();
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		String s = "Trees from sources: ";
+		for (int i = 0; i<sources.size(); i++){
+			if (i != 0)
+				s += " &";
+			s += " " + ((TreeSource)sources.elementAt(i)).getNameAndParameters();
+		}
+		return s;
+	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/treefarm/ConcatTreeBlocks/ConcatTreeBlocks.java b/Source/mesquite/treefarm/ConcatTreeBlocks/ConcatTreeBlocks.java
new file mode 100644
index 0000000..235646b
--- /dev/null
+++ b/Source/mesquite/treefarm/ConcatTreeBlocks/ConcatTreeBlocks.java
@@ -0,0 +1,99 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.ConcatTreeBlocks;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+
+
+/* ======================================================================== */
+public class ConcatTreeBlocks extends TreeBlockListUtility  {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+   	/** if returns true, then requests to remain on even after operateOnTrees is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the tree blocks.  Returns true if tree blocks altered*/
+   	public boolean operateOnTreeBlocks(TreeVector[] blocks){
+   		if (blocks == null || blocks.length <=1 || blocks[0]==null) {
+   			alert("Sorry, no tree blocks are were chosen or available for concatenation.");
+   			return false;
+   		}
+   		TreeVector block = blocks[0];
+    		Taxa taxa = block.getTaxa();
+   		int count = 0;
+   		for (int i=0; i<blocks.length; i++){
+   			if (blocks[i].getTaxa() == taxa)
+   				count++;
+   		}
+   		if (count<=1) {
+   			discreetAlert( "Sorry, there is only one block of trees for the set of taxa (concatenation uses only tree blocks with the same the taxa block as the first tree block selected).");
+   			return false;
+   		}
+  		boolean otherTaxaBlockFound = false;
+    	 	MesquiteFile file = getProject().chooseFile( "Select file to which to add the concatenated tree block");
+		incrementMenuResetSuppression();
+		getProject().incrementProjectWindowSuppression();
+		TreeVector concat = new TreeVector(taxa);
+   		for (int i=0; i<blocks.length; i++){
+   			if (blocks[i].getTaxa() == taxa) {
+				for (int j=0; j<blocks[i].size(); j++){
+						Tree tree = blocks[i].getTree(j);
+						if (tree!=null)
+							concat.addElement(tree.cloneTree(), false);
+				}
+   			}
+   			else
+   				otherTaxaBlockFound = true;
+   		}
+
+		concat.setName("Concatenated");
+		concat.addToFile(file, getProject(), findElementManager(TreeVector.class));  
+		if (otherTaxaBlockFound)
+			discreetAlert( "Not all of the tree blocks were concatenated, because some were for different taxon blocks.  Only those tree blocks referring to the same taxa as the first were concatenated.");
+		getProject().decrementProjectWindowSuppression();
+		decrementMenuResetSuppression();
+		resetAllMenuBars();
+		return true;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Concatenate tree blocks...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Concatenate tree blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Concatenates selected tree blocks into a new tree block.";
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/CondensedTreeSource/CondensedTreeSource.java b/Source/mesquite/treefarm/CondensedTreeSource/CondensedTreeSource.java
new file mode 100644
index 0000000..9f81953
--- /dev/null
+++ b/Source/mesquite/treefarm/CondensedTreeSource/CondensedTreeSource.java
@@ -0,0 +1,214 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CondensedTreeSource;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class CondensedTreeSource extends TreeSource {
+	TreeSourceDefinite treeSourceTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand tstC;
+	Taxa currentTaxa = null;
+	boolean suspend = false;
+
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSourceDefinite.class, getName() + " needs a source of trees which will then be condensed.",
+		"The source of other trees is indicated initially.");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeSourceTask = (TreeSourceDefinite)hireEmployee(TreeSourceDefinite.class, "Tree Source");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSourceDefinite.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tstC, TreeSourceDefinite.class);
+			mss.setSelected(treeSourceName);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend");
+        temp.addLine("getTreeSource",treeSourceTask);
+		temp.addLine("resume");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+	 	 if (checker.compare(this.getClass(), "Returns treeSourceTask", null, commandName, "getTreeSource")) 
+	 		return treeSourceTask;
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			parametersChanged();
+		}
+		else 
+			super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	
+	public String getExplanation() {
+		return "Produces a block of trees that are a condensed version of another block of trees, with duplicate trees removed.";
+	}
+	public String getName() {
+		return "Condensed Tree Source";
+	}
+
+	public int[] getIntegerArrayOfIdentities(Taxa taxa, MesquiteInteger numCondensedTrees) {
+		if (treeSourceTask==null)
+			return null;
+		if (taxa!=currentTaxa) {
+			initialize(taxa);
+			treeSourceTask.initialize(currentTaxa);
+		}
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		if (numTrees<=0)
+			return null;
+		int[] identities = new int[numTrees];
+		for (int i=0; i<numTrees; i++) 
+			identities[i]=-1;
+		int treeType = -1;
+		for (int i=0; i<numTrees; i++){
+			if (identities[i]<0) {// we haven't encountered this one before
+				treeType++;
+				identities[i] = treeType;
+				Tree tree = treeSourceTask.getTree(taxa, i);
+				for (int candidate=i+1; candidate<numTrees; candidate++) {
+					if (identities[candidate]<0) {// we haven't encountered this one before
+						Tree candidateTree = treeSourceTask.getTree(taxa, candidate);
+						if (candidateTree.equalsTopology(tree, false))
+							identities[candidate] = treeType;
+					}
+				}
+			}
+		}
+		if (numCondensedTrees !=null)
+			numCondensedTrees.setValue(treeType+1);
+		return identities;
+		
+	}
+
+	public int getNumberOfTrees(Taxa taxa) {
+		if (treeSourceTask==null)
+			return 0;
+		MesquiteInteger numTrees = new MesquiteInteger();
+		getIntegerArrayOfIdentities(taxa,numTrees);
+		return numTrees.getValue();
+	}
+
+	public Tree getTree(Taxa taxa, int itree) {
+		if (treeSourceTask==null)
+			return null;
+		MesquiteInteger numTrees = new MesquiteInteger();
+		int[] identities = getIntegerArrayOfIdentities(taxa,numTrees);
+		int count = 0;
+		int numOriginalTrees = treeSourceTask.getNumberOfTrees(taxa);
+		for (int it=0; it<numOriginalTrees; it++){
+			if (identities[it]==itree) 
+				count++;
+		}
+
+		for (int i=0; i<numOriginalTrees; i++)
+			if (identities[i]==itree) {
+				Tree tree =  treeSourceTask.getTree(taxa, i).cloneTree();
+				if (tree instanceof AdjustableTree)
+					((AdjustableTree)tree).setName("tree " + (i+1) + " (" + count + ")");
+				if (tree instanceof Attachable){
+					MesquiteString s = new MesquiteString(""+count);
+					s.setName("NumberOfOriginalTrees");
+					((Attachable)tree).attachIfUniqueName(s);
+				}
+				return tree;
+			}
+		return null;
+	}
+
+	public String getTreeNameString(Taxa taxa, int i) {
+		if (treeSourceTask==null)
+			return null;
+		MesquiteInteger numTrees = new MesquiteInteger();
+		int[] identities = getIntegerArrayOfIdentities(taxa,numTrees);
+		int numOriginalTrees = treeSourceTask.getNumberOfTrees(taxa);
+		int count = 0;
+		for (int it=0; it<numOriginalTrees; it++){
+			if (identities[it]==i) 
+				count++;
+		}
+		return "tree " + (i+1)+ " (" + count + ")";
+
+/*		for (int it=0; it<numOriginalTrees; it++)
+			if (identities[it]==i) {
+				//Tree tree = treeSourceTask.getTree(taxa, it);;
+			}
+		return null;
+		*/
+	}
+
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		setPreferredTaxa(taxa);
+   	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+	  	 storePreferences();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+		}
+	}
+
+	/*.................................................................................................................*/
+  	 
+  	public void setPreferredTaxa(Taxa taxa){
+   		if (taxa !=currentTaxa) {
+	 		if (currentTaxa!=null)
+	  			currentTaxa.removeListener(this);
+	  		currentTaxa = taxa;
+  			currentTaxa.addListener(this);
+  		}
+  		
+  	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+	/*.................................................................................................................*/
+ 	 
+  	public boolean isPrerelease(){
+  		return false;
+  	}
+
+
+}
diff --git a/Source/mesquite/treefarm/ConsensusTreesFromBlocks/ConsensusTreesFromBlocks.java b/Source/mesquite/treefarm/ConsensusTreesFromBlocks/ConsensusTreesFromBlocks.java
new file mode 100644
index 0000000..d8f15c8
--- /dev/null
+++ b/Source/mesquite/treefarm/ConsensusTreesFromBlocks/ConsensusTreesFromBlocks.java
@@ -0,0 +1,230 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.ConsensusTreesFromBlocks;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class ConsensusTreesFromBlocks extends TreeSource {
+	public String getName() {
+		return "Consensus Trees from Tree Blocks";
+	}
+	public String getExplanation() {
+		return "Supplies consensus trees from Tree blocks.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeBlockSource.class, getName() + "  needs a source of tree blocks of which to do the consensus.",
+		"The source of tree blocks can be chosen initially or in the Tree Block Source submenu");
+		//e.setDivertChainMessage("testing");
+		EmployeeNeed e2 = registerEmployeeNeed(Consenser.class, getName() + "  needs a method to make consensus trees.",
+		"The method to make consensus trees can be chosen initially or in the Consensus Method submenu");
+	}
+
+	/*.................................................................................................................*/
+	int currentTree=0;
+	TreeBlockSource treeListSource;
+	Taxa oldTaxa=null;
+	TreeVector treeList=null;
+	int defaultNumberOfTreeBlocks = 100;
+	int numberOfTreeBlocks;
+	IntegerArray notes;
+	Consenser consenser = null;
+	private MesquiteMenuItemSpec numListsItem;
+	MesquiteString treeSourceName, consenserName;
+	MesquiteCommand tlsC, cC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments ==null) {
+			treeListSource= (TreeBlockSource)hireNamedEmployee(TreeBlockSource.class, StringUtil.tokenize("Stored Tree Blocks"));
+			if (treeListSource==null)
+				treeListSource= (TreeBlockSource)hireEmployee(TreeBlockSource.class, "Source of Tree blocks for consensus");
+		}
+		else {
+			treeListSource= (TreeBlockSource)hireNamedEmployee(TreeBlockSource.class, arguments);
+			if (treeListSource == null) {
+				treeListSource= (TreeBlockSource)hireNamedEmployee(TreeBlockSource.class, StringUtil.tokenize("Stored Tree Blocks"));
+				if (treeListSource==null)
+					treeListSource= (TreeBlockSource)hireEmployee(TreeBlockSource.class, "Source of Tree blocks for consensus");
+			}
+		}
+		tlsC = makeCommand("setTreeBlockSource",  this);
+		if (treeListSource==null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+
+		treeListSource.setHiringCommand(tlsC);
+		treeSourceName = new MesquiteString();
+		if (numModulesAvailable(TreeBlockSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Block Source", tlsC, TreeBlockSource.class);
+			mss.setSelected(treeSourceName);
+		}
+		cC = makeCommand("setConsenser",  this);
+		consenser= (Consenser)hireEmployee(Consenser.class, "Consensus calculator");
+		if (consenser==null)
+			return sorry(getName() + " couldn't start because no consensus module obtained.");
+		consenser.setHiringCommand(cC);
+		consenserName = new MesquiteString();
+		if (numModulesAvailable(Consenser.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Consensus Method", cC, Consenser.class);
+			mss.setSelected(consenserName);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return TreeBlockSource.class;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeBlockSource ", treeListSource); 
+		temp.addLine("setConsenser ", consenser); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module supplying tree blocks", "[name of module]", commandName, "setTreeBlockSource")) {
+			TreeBlockSource temp = (TreeBlockSource)replaceEmployee(TreeBlockSource.class, arguments, "Source of tree blocks", treeListSource);
+			if (temp!=null) {
+				treeListSource = temp;
+				treeListSource.setHiringCommand(tlsC);
+				treeSourceName.setValue(treeListSource.getName());
+				int numLists=treeListSource.getNumberOfTreeBlocks(oldTaxa);
+				if (numLists==MesquiteInteger.infinite) {
+					numberOfTreeBlocks = defaultNumberOfTreeBlocks;
+					if (numListsItem==null)
+						numListsItem = addMenuItem( "Number of Tree Blocks...", makeCommand("setNumberTreeBlocks",  this));
+					resetContainingMenuBar();
+				}
+				else {
+					numberOfTreeBlocks = numLists;
+					if (numListsItem!=null)
+						deleteMenuItem(numListsItem);
+					numListsItem=null;
+				}
+				parametersChanged();
+			}
+			return temp;
+		}
+		else
+			if (checker.compare(this.getClass(), "Sets the module doing a consensus", "[name of module]", commandName, "setConsenser")) {
+				Consenser temp = (Consenser)replaceEmployee(Consenser.class, arguments, "Consensus module", consenser);
+				if (temp!=null) {
+					consenser = temp;
+					consenser.setHiringCommand(tlsC);
+					consenserName.setValue(consenser.getName());
+					parametersChanged();
+				}
+				return temp;
+			}
+			else if (checker.compare(this.getClass(), "Sets the number of tree blocks from which consensuses are derived (useful if the source of tree blocks has an indefinite number)", "[number of blocks]", commandName, "setNumberTreeBlocks")) {
+				int newNum= MesquiteInteger.fromFirstToken(arguments,pos);
+				if (!MesquiteInteger.isCombinable(newNum))
+					MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Tree Blocks", "Number of Tree Blocks:", numberOfTreeBlocks, 0, MesquiteInteger.infinite);
+				if (newNum>0  && newNum!=numberOfTreeBlocks) {
+					numberOfTreeBlocks = newNum;
+				}
+			}
+			else
+				return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa){
+		oldTaxa = taxa;
+	}
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		if (treeListSource!=null)
+			treeListSource.initialize(taxa); //WHEN this module takes in tree from a source, should ask to initialize that source
+	}
+	int numTreesUsed = 0;
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int ic) {  
+		oldTaxa = taxa;
+		if (treeListSource == null)
+			return null;
+		treeList = treeListSource.getBlock(taxa, ic);
+		if (treeList == null)
+			return null;
+		currentTree = ic;
+		numTreesUsed = treeList.size();
+		Tree tree = consenser.consense(treeList);
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		int numLists=treeListSource.getNumberOfTreeBlocks(taxa);
+		if (numLists==MesquiteInteger.infinite) {
+			numLists = defaultNumberOfTreeBlocks;
+			if (numListsItem==null)
+				numListsItem = addMenuItem( "Number of Tree Blocks...", makeCommand("setNumberTreeBlocks",  this));
+		}
+		else {
+			numberOfTreeBlocks = numLists;
+			deleteMenuItem(numListsItem);
+			numListsItem=null;
+		}
+		return numLists; //one consensus for each list
+	}
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee == treeListSource)
+			parametersChanged();
+
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		if (itree == currentTree)
+			return "Consensus tree " + (itree+1) + " from " + numTreesUsed + " trees";
+		return "Consensus tree " + (itree+1);
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return"Consensus tree of trees from " + treeListSource.getName();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new ConsCompatibilityTest();
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  //This is basically the old Consensus Tree module renamed and changed slightly
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean requestPrimaryChoice() { return false; } 
+}
+
+class ConsCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		if (prospectiveEmployer != null)
+			return prospectiveEmployer.numModulesAvailable(Consenser.class)>0;
+			else
+				return MesquiteTrunk.mesquiteTrunk.numModulesAvailable(Consenser.class)>0;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/ConvexInTree/ConvexInTree.java b/Source/mesquite/treefarm/ConvexInTree/ConvexInTree.java
new file mode 100644
index 0000000..1799fa4
--- /dev/null
+++ b/Source/mesquite/treefarm/ConvexInTree/ConvexInTree.java
@@ -0,0 +1,94 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.ConvexInTree;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** this is a little module that deterimines whether or not a set of taxa is a clade in a tree */
+public class ConvexInTree extends BooleanForTree implements MesquiteListener {
+	Taxa currentTaxa = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+  	 public void endJob(){
+  	 	if (currentTaxa != null)
+  	 		currentTaxa.removeListener(this);
+  	 	super.endJob();
+  	 }
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && code == MesquiteListener.SELECTION_CHANGED){
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString) {
+    	 	if (result==null || tree==null)
+    	 		return;
+		Taxa taxa = tree.getTaxa();
+		if (currentTaxa != taxa){
+			if (currentTaxa != null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+		if (!taxa.anySelected()) {
+ 			return;
+		}
+		boolean bt = tree.isConvex(taxa.getSelectedBits());
+		result.setValue(bt);
+		if (resultString!=null)
+			if (bt)
+				resultString.setValue("Taxa convex");
+			else
+				resultString.setValue("Taxa not convex");
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Selected Taxa Convex in Tree";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Convex?";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Determines if the selected taxa are convex in a tree.  That is, does there exist a rooting of the tree in which the selected taxa form a clade?" ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/Correlation2Trees/Correlation2Trees.java b/Source/mesquite/treefarm/Correlation2Trees/Correlation2Trees.java
new file mode 100644
index 0000000..337b6c6
--- /dev/null
+++ b/Source/mesquite/treefarm/Correlation2Trees/Correlation2Trees.java
@@ -0,0 +1,152 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.Correlation2Trees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+
+public class Correlation2Trees extends DistanceBetween2Trees {
+	PatristicDistances p1, p2;
+	boolean isDistance = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		p1 = new PatristicDistances();
+		p2 = new PatristicDistances();
+		isDistance = (getHiredAs() == DistanceBetween2Trees.class);
+		
+ 		return true;
+  	 }
+	public boolean largerIsFurther(){
+		return false;
+	}
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree t1, Tree t2) {
+	
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree1 == null)
+			return;
+		if (tree2 == null)
+			return;
+
+		int numTaxa = tree1.getTaxa().getNumTaxa();
+		
+		double[][] patristic1 = null;
+		patristic1 = p1.calculatePatristic(tree1, numTaxa, patristic1); //for this tree calculate patristic distances (number of nodes separating terminals; no branch lengths)
+		double[][] patristic2 = null;
+		patristic2 =  p2.calculatePatristic(tree2, numTaxa, patristic2); //for this tree calculate patristic distances (number of nodes separating terminals; no branch lengths)
+		
+		
+		double correl = offDiagonalPMCorrelationFILTERED(patristic1, patristic2);
+		if (isDistance && (MesquiteDouble.isCombinable(correl)))
+			correl = -correl + 1.0;  //shifting 1 to -1 to be 0 to 2 to act as distance
+		result.setValue(correl);
+		if (resultString!=null){
+			if (isDistance)
+				resultString.setValue("Patristic correlation (converted to distance): "+ result.toString());
+			else
+				resultString.setValue("Patristic correlation: "+ result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+		
+	}
+	
+	//by filtered means -ve and uncombinable numbers excluded
+	double offDiagonalPMCorrelationFILTERED(double[][] m1, double[][] m2){
+		if (m1==null || m2 == null)
+			return MesquiteDouble.unassigned;
+			
+		double mean1 = meanFILTERED(m1);
+		double mean2 = meanFILTERED(m2);
+		if (!MesquiteDouble.isCombinable(mean1) || !MesquiteDouble.isCombinable(mean2))
+			return MesquiteDouble.unassigned;
+		
+		double sumSq1 = sumSqFILTERED(m1, mean1);
+		double sumSq2 = sumSqFILTERED(m2,mean2);
+		double sumProd = 0;
+		for (int i= 0; i<m1.length; i++)
+			for (int j= 0; j<i; j++) {
+				double d1 = m1[i][j];
+				double d2 = m2[i][j];
+				if (d1>=-0.0000000001 && MesquiteDouble.isCombinable(d1) && d2>=-0.0000000001 && MesquiteDouble.isCombinable(d2))
+					sumProd += (d1-mean1)*(d2-mean2);
+			}
+		if (sumSq1 == 0 || sumSq2 == 0)
+			return MesquiteDouble.unassigned;
+		
+		return sumProd/Math.sqrt(sumSq1*sumSq2);
+	}
+	double meanFILTERED(double[][] m){
+		double sum = 0;
+		int n = 0;
+		for (int i= 0; i<m.length; i++)
+			for (int j= 0; j<i; j++) {
+				double d = m[i][j];
+				if (d>=-0.0000000001 && MesquiteDouble.isCombinable(d)) {
+					sum += d;
+					n++;
+				}
+			}
+		if (n==0)
+			return MesquiteDouble.unassigned;
+		return sum/n;
+	}
+	double sumSqFILTERED(double[][] m, double mean){
+		double sumSq = 0;
+		for (int i= 0; i<m.length; i++)
+			for (int j= 0; j<i; j++) {
+				double d = m[i][j];
+				if (d>=-0.0000000001 && MesquiteDouble.isCombinable(d))
+					sumSq += (d-mean)*(d-mean);
+			}
+		return sumSq;
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	 
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (isDistance)
+			return "Correlation converted to distance (1 to -1 becomes 0 to 2)";
+		else
+			return "Correlation in natural form (i.e., not converted to distance)";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Patristic distance correlation";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the product moment correlation coefficient among the off-diagonal elements of the patristic distances matrices of two trees.  Ignores unassigned and negative values in the matrices.  If employed as a distance, converts scores from 1 to -1 to scores from 0 to 2";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/CurrentTree/CurrentTree.java b/Source/mesquite/treefarm/CurrentTree/CurrentTree.java
new file mode 100644
index 0000000..d1290a9
--- /dev/null
+++ b/Source/mesquite/treefarm/CurrentTree/CurrentTree.java
@@ -0,0 +1,121 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.CurrentTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies a tree from a current tree window.*/
+public class CurrentTree extends TreeSource {
+	 public String getName() {
+	return "Current Tree";
+	 }
+	 public String getExplanation() {
+	return "Supplies a single tree currently shown in a tree window.";
+	 }
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of the current tree.",
+		"");
+	}
+	OneTreeSource currentTreeSource;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		currentTreeSource = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of current tree");
+ 		if (currentTreeSource == null) {
+ 			return sorry(getName() + " couldn't start because no source of a current tree was obtained.");
+ 		}
+ 		if (currentTreeSource.getUltimateSource() == this)
+ 			return sorry(getName() + " couldn't start because it would be attempting to obtained its own tree, resulting in an infinite recursion.");
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	 public boolean permitSeparateThreadWhenFilling(){
+		 return false;
+	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", currentTreeSource); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of the tree", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of tree", currentTreeSource);
+			if (temp !=null){
+				currentTreeSource = temp;
+				parametersChanged();
+    	 			return currentTreeSource;
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+ 		if (currentTreeSource.getUltimateSource() == this) {
+ 			alert("A tree source had to quit because it would be attempting to obtain its own trees, resulting in an infinite recursion.");
+ 			iQuit();
+ 		}
+   		if (currentTreeSource!=null)
+   			currentTreeSource.initialize(taxa);
+   	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int ic) {  
+   		if (ic != 0)
+   			return null;
+   		Tree t =  currentTreeSource.getTree(taxa);
+ 		if (currentTreeSource.getUltimateSource() == this) {
+ 			alert("A tree source had to quit because it would be attempting to obtain its own trees, resulting in an infinite recursion.");
+ 			iQuit();
+ 			return null;
+ 		}
+ 		return t;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return 1;
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return "Tree from " + currentTreeSource.getParameters();
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return currentTreeSource.getParameters();
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
diff --git a/Source/mesquite/treefarm/CutSelectedTaxa/CutSelectedTaxa.java b/Source/mesquite/treefarm/CutSelectedTaxa/CutSelectedTaxa.java
new file mode 100644
index 0000000..22e2cfb
--- /dev/null
+++ b/Source/mesquite/treefarm/CutSelectedTaxa/CutSelectedTaxa.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+/* December 2003  D.R. Maddison */
+
+package mesquite.treefarm.CutSelectedTaxa;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CutSelectedTaxa extends TreeAltererMult {
+	boolean unselectedAlreadyWarned = false;
+	Taxa currentTaxa = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	public void endJob() {
+  	 	if (currentTaxa != null)
+  	 		currentTaxa.removeListener(this);
+ 		super.endJob();
+   	 }
+
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && code == MesquiteListener.SELECTION_CHANGED){
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	
+   	
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree==null)
+			return false;
+		Taxa taxa = tree.getTaxa();
+		if (currentTaxa != taxa){
+			if (currentTaxa != null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+		if (!taxa.anySelected()) {
+ 			if (!unselectedAlreadyWarned)
+ 				discreetAlert("Before trees can be rerooted using the selected taxa as outgroups, some taxa must be selected");
+ 			unselectedAlreadyWarned = true;
+			return false;
+		}
+		boolean changed = false;
+		for (int i = 0; i< taxa.getNumTaxa(); i++){
+			int node = tree.nodeOfTaxonNumber(i);
+			if (tree.nodeExists(node) && taxa.getSelected(i)){
+				tree.deleteClade(node, false);
+				changed = true;
+			}
+		}
+		if (notify && changed && tree instanceof Listened) {
+			((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Cut Selected Taxa from Tree";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Cuts the selected taxa from the tree." ;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/DeleteReticulations/DeleteReticulations.java b/Source/mesquite/treefarm/DeleteReticulations/DeleteReticulations.java
new file mode 100644
index 0000000..e1c4b66
--- /dev/null
+++ b/Source/mesquite/treefarm/DeleteReticulations/DeleteReticulations.java
@@ -0,0 +1,61 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.DeleteReticulations;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DeleteReticulations extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+  	 
+  	void zap(AdjustableTree tree, int node){
+  	 	if (tree.nodeIsInternal(node)) { 
+  	 		if (tree.numberOfParentsOfNode(node)>1)
+  	 			tree.snipReticulations(node);
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			zap(tree, daughter);
+	   	 	}
+ 		}
+  	}
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+			zap(tree, tree.getRoot());
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Delete Reticulations";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Deletes secondary parents of nodes with more than one immediate ancestor.  There is no control over which parents get deleted." ;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/DetermModifTree/DetermModifTree.java b/Source/mesquite/treefarm/DetermModifTree/DetermModifTree.java
new file mode 100644
index 0000000..b348764
--- /dev/null
+++ b/Source/mesquite/treefarm/DetermModifTree/DetermModifTree.java
@@ -0,0 +1,131 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.DetermModifTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class DetermModifTree extends SourceModifiedTree {
+  	 public String getName() {
+ 		return "Modify Current Tree";
+    	 }
+    	 public String getExplanation() {
+ 		return "Modifies current tree.";
+    	 }
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DetTreeModifier.class, getName() + "  needs a method to modify the tree.",
+		"The method to modify the tree can be selected initially, or later under the Modifier of Tree submenu");
+	}
+	int currentTree=0;
+	DetTreeModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		if (!super.startJob(arguments, condition, hiredByName))
+ 			return false;
+ 		if (arguments ==null)
+ 			modifierTask = (DetTreeModifier)hireEmployee(DetTreeModifier.class, "Modifier of tree");
+	 	else {
+	 		modifierTask = (DetTreeModifier)hireNamedEmployee(DetTreeModifier.class, arguments);
+ 			if (modifierTask == null)
+ 				modifierTask = (DetTreeModifier)hireEmployee(DetTreeModifier.class, "Modifier of tree");
+ 		}
+ 		if (modifierTask == null) {
+ 			return sorry(getName() + " couldn't start because no tree modifier was obtained.");
+ 		}
+ 	 	stC = makeCommand("setModifier",  this);
+ 	 	modifierTask.setHiringCommand(stC);
+ 		modifierName = new MesquiteString();
+	    	modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(DetTreeModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Modifier of Tree", stC, DetTreeModifier.class);
+ 			mss.setSelected(modifierName);
+  		}
+  		return true;
+  	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return DetTreeModifier.class;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the tree modifier", "[name of module]", commandName, "setModifier")) {
+				DetTreeModifier temp = (DetTreeModifier)replaceEmployee(DetTreeModifier.class, arguments, "Modifier of tree", modifierTask);
+				if (temp !=null){
+					modifierTask = temp;
+	    	 		modifierName.setValue(modifierTask.getName());
+			 	 	modifierTask.setHiringCommand(stC);
+					parametersChanged();
+	    	 			return modifierTask;
+	    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int ic) {  
+   		Tree tree = getBasisTree(taxa);
+   		currentTree = ic;
+   		if (tree == null)
+   			return null;
+   		MesquiteTree modified =  tree.cloneTree();
+   		modifierTask.modifyTree(tree, modified, currentTree);
+   		modified.setName("Modified from " + tree.getName() + " (#" + (currentTree + 1) + ")");
+   		return modified;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		Tree tree = getBasisTree(taxa);
+		if (tree ==null)
+			return 0;
+		else
+			return modifierTask.getNumberOfTrees(tree);
+   	}
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return "Modification #" + (itree +1);
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Modifying trees from: " + getBasisTreeSource().getParameters();
+   	}
+	/*.................................................................................................................*/
+    	 
+}
+
diff --git a/Source/mesquite/treefarm/DuplicateTreeBlocks/DuplicateTreeBlocks.java b/Source/mesquite/treefarm/DuplicateTreeBlocks/DuplicateTreeBlocks.java
new file mode 100644
index 0000000..433fc11
--- /dev/null
+++ b/Source/mesquite/treefarm/DuplicateTreeBlocks/DuplicateTreeBlocks.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.DuplicateTreeBlocks;
+
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+
+
+/* ======================================================================== */
+public class DuplicateTreeBlocks extends TreeBlockListUtility  {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+
+   	/** if returns true, then requests to remain on even after operateOnTrees is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+   	/** Called to operate on the tree blocks.  Returns true if tree blocks altered*/
+   	public boolean operateOnTreeBlocks(TreeVector[] blocks){
+   		if (blocks == null || blocks.length <=1 || blocks[0]==null) {
+   			alert("Sorry, no tree blocks are were chosen or available for duplication.");
+   			return false;
+   		}
+		incrementMenuResetSuppression();
+		getProject().incrementProjectWindowSuppression();
+   		for (int i=0; i<blocks.length; i++){
+   			blocks[i].doCommand("duplicateMe", null, CommandChecker.defaultChecker);
+   		}
+
+		getProject().decrementProjectWindowSuppression();
+		decrementMenuResetSuppression();
+		resetAllMenuBars();
+		return true;
+   	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Duplicate tree blocks...";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Duplicate tree blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Duplicates selected tree blocks into a new tree block.";
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/EmailTree/EmailTree.java b/Source/mesquite/treefarm/EmailTree/EmailTree.java
new file mode 100644
index 0000000..09ff0d1
--- /dev/null
+++ b/Source/mesquite/treefarm/EmailTree/EmailTree.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.EmailTree;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import java.net.*;
+
+/** ======================================================================== */
+
+public class EmailTree extends TreeUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  
+ 	}
+ 	
+	public  void useTree(Tree tree) {
+		TextTree tt = new TextTree(tree);
+		StringBuffer buff = new StringBuffer(50);
+		tt.drawTreeAsText(tree, buff);
+		String origTree = buff.toString();
+		buff.insert(0, "\nTree: " + tree.getName() + "\n\n\n");
+		replaceSpacesByTabs(buff);
+		String treeString = URLEncoder.encode(buff.toString());
+		buff.setLength(0);
+		buff.append(treeString);
+		replaceURLTabsByURLSpaces(buff);
+		String file = MesquiteModule.prefsDirectory + MesquiteFile.fileSeparator + "emailTree.html";
+		buff.insert(0, "<html><body><h3>Mesquite tree e-mailer</h3><a href= \"mailto:Recipient?Subject=tree&Body=");
+		buff.append("\">E-mail tree</a><pre>"+ origTree +"</pre></body></html>" );
+		MesquiteFile.putFileContents(file, buff.toString(), true);
+		
+		showWebPage(file, false);
+	}
+	
+	void replaceSpacesByTabs(StringBuffer buff){
+		String ns = buff.toString().replace(' ', '\t');
+		buff.setLength(0);
+		buff.append(ns);
+	}
+	void replaceURLTabsByURLSpaces(StringBuffer buff){
+	 //09 by 20
+	 	String s = buff.toString();
+	 	int i = 0;
+	 	int loc;
+	 	while ((loc = s.indexOf("%09", i))>=0){
+	 		buff.setCharAt(loc+1, '2');
+	 		buff.setCharAt(loc+2, '0');
+	 		i = loc+3;
+	 	}
+	}
+	
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "E-mail Tree";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calls mailto: to email a text image of the tree.";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/treefarm/EqualRatesSpSampled/EqualRatesSpSampled.java b/Source/mesquite/treefarm/EqualRatesSpSampled/EqualRatesSpSampled.java
new file mode 100644
index 0000000..36e08da
--- /dev/null
+++ b/Source/mesquite/treefarm/EqualRatesSpSampled/EqualRatesSpSampled.java
@@ -0,0 +1,349 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.EqualRatesSpSampled;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class EqualRatesSpSampled extends TreeSimulate {
+	RandomBetween randomTaxon;
+	ExponentialDistribution waitingTime;
+	double scaling = 10.0;
+	int totalSpecies = 1000;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		randomTaxon= new RandomBetween(1);
+ 		waitingTime = new ExponentialDistribution(1);
+ 		if (!MesquiteThread.isScripting()) {
+ 			scaling = MesquiteDouble.queryDouble(containerOfModule(), "Total tree depth", "Total tree depth", scaling);
+ 			totalSpecies = MesquiteInteger.queryInteger(containerOfModule(), "Total Species", "Total number of species from which observed number sampled", totalSpecies);
+ 		}
+ 		if (!MesquiteDouble.isCombinable(scaling))
+ 			return false;
+   		addMenuItem("Total tree depth (simulation)...", makeCommand("setTime",  this));
+   		addMenuItem("Total Species...", makeCommand("setTotalSpecies",  this));
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTime " + scaling);
+  	 	temp.addLine("setTotalSpecies " + totalSpecies);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the total tree depth", "[number]", commandName, "setTime")) {
+    	 		pos.setValue(0);
+ 			double s = MesquiteDouble.fromString(arguments, pos);
+	 		if (!MesquiteDouble.isCombinable(s))
+ 				s = MesquiteDouble.queryDouble(containerOfModule(), "Total tree depth", "Total tree depth", scaling);
+	 		if (MesquiteDouble.isCombinable(s)) {
+	 			scaling = s;
+	 			parametersChanged();
+	 		}
+    		}
+    	 	else if (checker.compare(this.getClass(), "Sets the total number of species from which observed number sampled", "[number]", commandName, "setTotalSpecies")) {
+    	 		pos.setValue(0);
+ 			int s = MesquiteInteger.fromString(arguments, pos);
+	 		if (!MesquiteInteger.isCombinable(s))
+ 				s = MesquiteInteger.queryInteger(containerOfModule(), "Total Species", "Total number of species from which observed number sampled", totalSpecies);
+	 		if (MesquiteInteger.isCombinable(s)) {
+	 			totalSpecies = s;
+	 			parametersChanged();
+	 		}
+    		}
+   	 	else return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+  	 private void addLengthToAllTerminals(QuickTree tree, int node, double increment){
+  	 	if (tree.taxon[node]>=0) {
+  	 		double current = tree.getBranchLength(node);
+  	 		if (MesquiteDouble.isCombinable(current))
+  	 			tree.setBranchLength(node, current + increment);
+  	 		else
+  	 			tree.setBranchLength(node, increment);  	 		
+		}
+		else {
+			addLengthToAllTerminals(tree, tree.left[node], increment);
+			addLengthToAllTerminals(tree, tree.right[node], increment);
+		}
+  	 }
+  	private double getWaitingTime(int numTaxa){
+  		return waitingTime.nextExponential(1.0/numTaxa);
+  	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return MesquiteInteger.infinite;
+   	}
+	/*.................................................................................................................*/
+   	public Tree getSimulatedTree(Taxa taxa, Tree tree, int treeNumber, ObjectContainer extra, MesquiteLong seed) { //todo: should be two seeds passed!
+   			//save random seed used to make tree under tree.seed for use in recovering later
+  			randomTaxon.setSeed(seed.getValue());
+  			waitingTime.setSeed(seed.getValue());
+  			if (tree==null || !(tree instanceof MesquiteTree))
+  				 tree = new MesquiteTree(taxa);
+  			MesquiteTree mTree = ((MesquiteTree)tree);
+			
+			//Operate on a simple tree class with given total number of species, then subsample from this quick tree
+			QuickTree qTree = new QuickTree(totalSpecies);
+			qTree.init();
+			
+			//Evolving tree by simple Yule process
+			int whichTaxon;
+			for (int taxon = 2; taxon < totalSpecies; taxon++) {
+				whichTaxon=randomTaxon.randomIntBetween(0, taxon-1);
+				addLengthToAllTerminals(qTree, qTree.root, getWaitingTime(taxon));
+				qTree.splitTerminal(whichTaxon, taxon);
+			}
+			
+			//adding to all terminals waiting time uniformly distributed between 0 and waiting time to next speciation
+			addLengthToAllTerminals(qTree, qTree.root, waitingTime.nextDouble()*getWaitingTime(taxa.getNumTaxa()));
+			
+			//sampling species
+			if (totalSpecies>taxa.getNumTaxa()){
+				int toCut = totalSpecies-taxa.getNumTaxa();
+				for (int i= 0; i< toCut; i++){
+					int unlucky=randomTaxon.randomIntBetween(0, totalSpecies-i -1);
+					int cut = qTree.findTaxon(unlucky);
+					qTree.cutTerminalNode(cut);
+					qTree.renumberTaxaAbove(qTree.root, unlucky);
+				}
+			}
+			//rescale to make it desired total depth
+			qTree.scaleTree(scaling);
+			
+			//write tree in Newick form and then reread into MesquiteTree
+			mTree.readTree(qTree.writeTree(qTree.root) + ";");
+			
+			mTree.reshuffleTerminals(randomTaxon); //added after 1.03 to fix bug
+			
+			seed.setValue(randomTaxon.nextLong());  //seed for next time
+	   		return mTree;
+   	}
+   
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Uniform Speciation with Sampling";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Generates tree by simple uniform probability speciation (a Yule process), with subsequent sampling of species." ;
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Trees constrained to branch length depth: " + scaling + "; total number of species from which observed number sampled: " + totalSpecies;
+   	}
+	/*.................................................................................................................*/
+}
+
+
+class QuickTree {
+	int root =0;
+	int[] left, right, taxon;
+	double[] lengths;
+	int numTaxa;
+	int numNodes;
+	int open = 0;
+	public QuickTree(int numTaxa){
+		this.numTaxa = numTaxa;
+		numNodes = numTaxa*2+4;
+		left = new int[numNodes];
+		right = new int[numNodes];
+		taxon = new int[numNodes];
+		lengths = new double[numNodes];
+	}
+	void init(){
+		for (int i=0; i<numNodes; i++) {
+			left[i] = 0;
+			right[i] = 0;
+			lengths[i] = 0;
+			taxon[i] = -1;
+		}
+		left[0] = 1;
+		taxon[1] = 0;
+		right[0] = 2;
+		taxon[2] = 1;
+		open = 3;
+	}
+	
+	int recfindTaxon(int node, int t){
+		if (taxon[node]>=0) {
+			if (taxon[node]==t)
+				return node;
+			return -1;
+		}
+		else {
+			int nodeFound = recfindTaxon(left[node],t);
+			if (nodeFound<0)
+				nodeFound = recfindTaxon(right[node],t);
+			return nodeFound;
+		}
+	}
+	int findTaxon(int t){
+		return recfindTaxon(root, t);
+	}
+	/** Branches a terminal node off taxon number taxonNum, and assigns it taxon newNumber  */
+	void splitTerminal(int taxonNum, int newNumber){
+		int node = findTaxon(taxonNum);
+		if (node>=0){
+			left[node]=open++;
+			right[node]=open++;
+			taxon[node]=-1;
+			taxon[left[node]] = taxonNum;
+			taxon[right[node]] = newNumber;
+		}
+	}
+	
+	int findAncestor(int node, int anc, int target){
+		if (taxon[node]>=0) {
+			if (node==target)
+				return anc;
+			return -1;
+		}
+		else {
+			if (node==target)
+				return anc;
+			int nodeFound = findAncestor(left[node],node, target);
+			if (nodeFound<0)
+				nodeFound = findAncestor(right[node],node, target);
+			return nodeFound;
+		}
+	}
+	int diagfindAncestor(int node, int anc, int target){
+		if (taxon[node]>=0) {
+			if (node==target)
+				return anc;
+			return -1;
+		}
+		else {
+			if (node==target)
+				return anc;
+			int nodeFound = diagfindAncestor(left[node],node, target);
+			if (nodeFound<0)
+				nodeFound = diagfindAncestor(right[node],node, target);
+			return nodeFound;
+		}
+	}
+
+	void cutTerminalNode(int toCut){
+		int anc = findAncestor(root, -1, toCut);
+		int sister;
+		if (left[anc] == toCut) 
+			sister = right[anc];
+		else 
+			sister = left[anc];
+		if (anc == root){
+			root = sister;
+		}
+		else {
+			int ancAnc = findAncestor(root, -1, anc);
+			lengths[sister] += lengths[anc];
+			if (left[ancAnc] == anc)
+				left[ancAnc] = sister;
+			else
+				right[ancAnc] = sister;
+		}
+		
+	}
+	
+	void renumberTaxaAbove(int node, int t){
+		if (taxon[node]>=0) {
+			if (taxon[node]>=t)
+				taxon[node]--;
+		}
+		else {
+			renumberTaxaAbove(left[node], t);
+			renumberTaxaAbove(right[node], t);
+		}
+	}
+	void setBranchLength(int node,double d){
+		lengths[node] = d;
+	}
+	
+	double getBranchLength(int node) {
+		return lengths[node];
+	}
+	double tallestPathAboveNode(int node){
+		if (taxon[node]>=0)
+			return 0;
+		double leftWay = tallestPathAboveNode(left[node]) + lengths[left[node]];
+		double rightWay = tallestPathAboveNode(right[node]) + lengths[right[node]];
+		if (leftWay > rightWay)
+			return leftWay;
+		else
+			return rightWay;
+	}
+	void recScale(int node, double scaleFactor){
+		lengths[node] *= scaleFactor;
+		if (taxon[node]<0) {
+			recScale(left[node], scaleFactor);
+			recScale(right[node], scaleFactor);
+		}
+	}
+	void scaleTree(double targetDepth){
+		double depth = tallestPathAboveNode(root);
+		if (depth!=0)
+			recScale(root, targetDepth/depth);
+		lengths[root] = 1.0;
+	}
+
+	boolean writeLengths = true;
+	String writeTree(int node){
+		if (!writeLengths){
+			if (taxon[node]>=0)
+				return Integer.toString(taxon[node] + 1);
+			return "(" + writeTree(left[node]) + "," + writeTree(right[node]) + ")";
+		}
+		else {
+			if (taxon[node]>=0)
+				return Integer.toString(taxon[node] + 1) + ":" + lengths[node];
+			return "(" + writeTree(left[node]) + "," + writeTree(right[node]) + "):" + lengths[node];
+		}
+	}
+	String writeTreeWithNodeNumbers(int node){
+			if (taxon[node]>=0)
+				return Integer.toString(taxon[node] + 1) + "[" + node + "]";
+			return "(" + writeTreeWithNodeNumbers(left[node]) + "," + writeTreeWithNodeNumbers(right[node]) + ")" + "[" + node + "]";
+	}
+}
+
diff --git a/Source/mesquite/treefarm/ExtractTreeBlock/ExtractTreeBlock.java b/Source/mesquite/treefarm/ExtractTreeBlock/ExtractTreeBlock.java
new file mode 100644
index 0000000..d40f702
--- /dev/null
+++ b/Source/mesquite/treefarm/ExtractTreeBlock/ExtractTreeBlock.java
@@ -0,0 +1,95 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.ExtractTreeBlock;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class ExtractTreeBlock extends TreeListUtility { 
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public boolean operateOnTrees(TreeVector trees){
+   		if (trees == null)
+   			return false;
+   		Taxa taxa = trees.getTaxa();
+   		int numTrees = trees.size();
+   		if (!trees.anySelected()) {
+   			discreetAlert( "Sorry, no trees are selected.");
+   			return false;
+   		}
+
+		int treeCount = 0;
+    	 	MesquiteFile file = getProject().chooseFile( "Select file to which to add the extracted tree block");
+		incrementMenuResetSuppression();
+		getProject().incrementProjectWindowSuppression();
+
+		TreeVector fragment = new TreeVector(taxa);
+		fragment.setName("Copied from " + trees.getName());
+		
+		for (int j=0; j<trees.size(); j++){
+			if (trees.getSelected(j)){
+				Tree tree = trees.getTree(j);
+				if (tree!=null)
+				fragment.addElement(tree.cloneTree(), false);
+			}
+		}
+		
+		fragment.addToFile(file, getProject(), findElementManager(TreeVector.class));  
+		fragment.show();
+		
+		getProject().decrementProjectWindowSuppression();
+		decrementMenuResetSuppression();
+		resetAllMenuBars();
+		return true;
+		
+	}
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Extract selection as tree block";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Extract tree block";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Extracts selected trees and places them in a new tree block.";
+   	 }
+}
+
+
+	
+
+
diff --git a/Source/mesquite/treefarm/FAFillTreeBlock/FAFillTreeBlock.java b/Source/mesquite/treefarm/FAFillTreeBlock/FAFillTreeBlock.java
new file mode 100644
index 0000000..7aa7d46
--- /dev/null
+++ b/Source/mesquite/treefarm/FAFillTreeBlock/FAFillTreeBlock.java
@@ -0,0 +1,130 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.FAFillTreeBlock; 
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class FAFillTreeBlock extends FileProcessor {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(TreeBlockFiller.class, getName() + " needs a particular method to make tree blocks.",
+				null);
+		e2.setPriority(2);
+	}
+	MesquiteSubmenuSpec mss= null;
+	TreeBlockFiller treeFillerTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			treeFillerTask = (TreeBlockFiller)hireNamedEmployee(TreeBlockFiller.class, arguments);
+			if (treeFillerTask == null)
+				return sorry(getName() + " couldn't start because the requested tree block filler wasn't successfully hired.");
+		}
+		else {
+			treeFillerTask = (TreeBlockFiller)hireEmployee(TreeBlockFiller.class, "Tree supplier");
+			if (treeFillerTask == null)
+				return sorry(getName() + " couldn't start because no tree block filler module obtained.");
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true; //not really, but to force checking of prerelease
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeBlockFiller ", treeFillerTask);  
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that alters data", "[name of module]", commandName, "setTreeBlockFiller")) {
+			TreeBlockFiller temp =  (TreeBlockFiller)replaceEmployee(TreeBlockFiller.class, arguments, "Tree supplier", treeFillerTask);
+			if (temp!=null) {
+				treeFillerTask = temp;
+				return treeFillerTask;
+			}
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** if returns true, then requests to remain on even after alterFile is called.  Default is false*/
+	public boolean pleaseLeaveMeOn(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** Called to alter file. */
+	public boolean processFile(MesquiteFile file){
+		MesquiteProject proj = file.getProject();
+		if (proj == null)
+			return false;
+		boolean success = true;
+		Taxa taxa = proj.getTaxa(0);
+		if (taxa == null)
+			return false;
+		TreeVector trees = new TreeVector(taxa);
+		int howManyTrees =0;
+		if (treeFillerTask instanceof TreeSource)
+			howManyTrees =((TreeSource)treeFillerTask).getNumberOfTrees(trees.getTaxa());
+		if (!treeFillerTask.hasLimitedTrees(trees.getTaxa())){
+			howManyTrees = MesquiteInteger.fromString(parser.getNextToken());
+			if (!MesquiteInteger.isCombinable(howManyTrees)) {
+				return false;
+			}
+		}
+
+
+		int before = trees.size();
+		mesquite.lib.characters.CharacterData data = proj.getCharacterMatrix(0);
+		treeFillerTask.initialize(data.getTaxa());
+		treeFillerTask.fillTreeBlock(trees, howManyTrees);
+
+		if (trees.size()==before) {
+			logln("Sorry, no trees were returned by " + treeFillerTask.getName());
+			return false;
+		}
+
+		logln(Integer.toString(trees.size()) + " trees stored in tree block, from " + treeFillerTask.getName());
+		trees.addToFile(file, getProject(), findElementManager(TreeVector.class));
+		return true;
+
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Add and Fill Tree Block";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages tree block filling as an alteration to a file." ;
+	}
+
+}
+
+
diff --git a/Source/mesquite/treefarm/FilterTreesOtherSrc/FilterTreesOtherSrc.java b/Source/mesquite/treefarm/FilterTreesOtherSrc/FilterTreesOtherSrc.java
new file mode 100644
index 0000000..3efe334
--- /dev/null
+++ b/Source/mesquite/treefarm/FilterTreesOtherSrc/FilterTreesOtherSrc.java
@@ -0,0 +1,180 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.FilterTreesOtherSrc;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class FilterTreesOtherSrc extends SourceFromTreeSource {
+	public String getName() {
+		return "Filter Trees from Other Source";
+	}
+	public String getNameForMenuItem() {
+		return "Filter Trees from Other Source...";
+	}
+	public String getExplanation() {
+		return "Filters trees from another source.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		super.getEmployeeNeeds();
+		EmployeeNeed e = registerEmployeeNeed(BooleanForTree.class, getName() + "  needs a criterion by which to filter trees.",
+		"The criterion to filter trees can be chosen initially or in the Filter of Trees submenu");
+	}
+	int currentTree=0;
+	int lastGoodTree = -1;
+	int lastTreeRequested = -1;
+	int maxAvailable = -2;
+	BooleanForTree booleanTask;
+	MesquiteString booleanName;
+	MesquiteCommand stC;
+	MesquiteBoolean positiveFilter;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (!super.startJob(arguments, condition, hiredByName))
+			return false;
+		booleanTask = (BooleanForTree)hireEmployee(BooleanForTree.class, "Filter of trees");
+		if (booleanTask == null) {
+			return sorry(getName() + " couldn't start because no tree filter was obtained.");
+		}
+		positiveFilter = new MesquiteBoolean(true);
+		stC = makeCommand("setBoolean",  this);
+		booleanTask.setHiringCommand(stC);
+		booleanName = new MesquiteString();
+		booleanName.setValue(booleanTask.getName());
+		if (numModulesAvailable(BooleanForTree.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Filter of Trees", stC, BooleanForTree.class);
+			mss.setSelected(booleanName);
+		}
+		if (!MesquiteThread.isScripting())
+			positiveFilter.setValue(AlertDialog.query(containerOfModule(), "Keep Trees that Satisfy?", "The filter can either keep those trees that satisfy the criterion, or those trees that fail the criterion.  Which to keep?", 
+					"Satisfy", "Fail", 0, null));
+					
+		addCheckMenuItem(null, "Keep Trees Satisfying Criterion", makeCommand("togglePositiveFilter", this), positiveFilter);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setBoolean ", booleanTask); 
+		temp.addLine("togglePositiveFilter " + positiveFilter.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree filter", "[name of module]", commandName, "setBoolean")) {
+			BooleanForTree temp = (BooleanForTree)replaceEmployee(BooleanForTree.class, arguments, "Filter of trees", booleanTask);
+			if (temp !=null){
+				booleanTask = temp;
+				booleanName.setValue(booleanTask.getName());
+				booleanTask.setHiringCommand(stC);
+				lastGoodTree = -1;
+				lastTreeRequested = -1;
+				maxAvailable = -2;
+				parametersChanged();
+				return booleanTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to keep those trees that satisfy the criterion, or not", "[on or off]", commandName, "togglePositiveFilter")) {
+			positiveFilter.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		lastGoodTree = -1;
+		lastTreeRequested = -1;
+		maxAvailable = -2;
+		super.employeeParametersChanged(this, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int ic) {  
+		int iTry = 0;
+		int count = -1;
+		if (ic>maxAvailable && maxAvailable>-2)
+			return null;
+		if (lastTreeRequested == ic)  //recently requested same; return it without checking filter (since change in filter would have reset lastTreeRequested etc.)
+			return getBasisTree(taxa, lastGoodTree);
+		else if (lastTreeRequested >= 0 && lastTreeRequested == ic-1) {
+			//go from last requested
+			iTry = lastGoodTree+1;
+			count = lastTreeRequested;
+
+		}
+		Tree tree = null;
+		MesquiteBoolean result = new MesquiteBoolean(false);
+		TreeSource ts = getBasisTreeSource();
+		int numTrees = ts.getNumberOfTrees(taxa); 
+		while (count<ic) {
+			tree = getBasisTree(taxa, iTry);
+			if (tree == null)  {
+				maxAvailable = count;
+				return null;
+			}
+			booleanTask.calculateBoolean(tree, result, null);	
+			if ((result.getValue() && positiveFilter.getValue()) || (!result.getValue() && !positiveFilter.getValue())){
+				count++;
+			}		
+			else
+				tree = null;
+			iTry++;
+		}
+		currentTree = ic;
+		lastGoodTree = iTry-1;
+		lastTreeRequested = ic;
+		return tree.cloneTree();
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		if (maxAvailable<-1) {
+			if (getBasisTreeSource().getNumberOfTrees(taxa) == MesquiteInteger.infinite)
+				return MesquiteInteger.infinite;
+			return MesquiteInteger.finite; //don't know how many will be filtered
+		}
+		else
+			return maxAvailable+1;
+	}
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		return "Tree #" + (itree +1) + " filtered";
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (getBasisTreeSource() == null || booleanTask == null)
+			return null;
+		return"Filtering trees from: " + getBasisTreeSource().getNameAndParameters() + " using the filter " + booleanTask.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/treefarm/FractionCladesShared2Trees/FractionCladesShared2Trees.java b/Source/mesquite/treefarm/FractionCladesShared2Trees/FractionCladesShared2Trees.java
new file mode 100644
index 0000000..26b36af
--- /dev/null
+++ b/Source/mesquite/treefarm/FractionCladesShared2Trees/FractionCladesShared2Trees.java
@@ -0,0 +1,155 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.FractionCladesShared2Trees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class FractionCladesShared2Trees extends DistanceBetween2Trees {
+	StringArray terminalsAbove, terminalsBelow, otherTerminalsAbove, otherTerminalsBelow;
+	MesquiteBoolean verboseOutput= new MesquiteBoolean(false);
+
+	boolean isDistance = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		isDistance = (getHiredAs() == DistanceBetween2Trees.class);
+		addCheckMenuItem(null, "Verbose Output to Log", makeCommand("toggleVerboseOutput",  this), verboseOutput);
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public boolean largerIsFurther(){  
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("toggleVerboseOutput " + verboseOutput.toOffOnString());
+		return temp;
+	}
+
+	private void visitOriginal(Tree tree,int node,  Tree otherTree, MesquiteInteger numConsistent){
+		if (tree.nodeIsInternal(node)){
+			Bits b = tree.getTerminalTaxaAsBits(node);
+			if (otherTree.isClade(b)) {
+				int otherNode = otherTree.mrca(b);
+				numConsistent.increment();
+			}
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginal(tree, daughter, otherTree, numConsistent);
+
+		}
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree t1, Tree t2) {
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether verbose output is listed to the log file or not", "", commandName, "toggleVerboseOutput")) {
+			boolean current = verboseOutput.getValue();
+			verboseOutput.toggleValue(parser.getFirstToken(arguments));
+			if (current!=verboseOutput.getValue())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	MesquiteTree tree1eq, tree2eq;
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (tree1 == null)
+			return;
+		if (tree2 == null)
+			return;
+		if (tree1.numberOfTerminalsInClade(tree1.getRoot()) == tree2.numberOfTerminalsInClade(tree2.getRoot())) {
+
+			MesquiteInteger numCon = new MesquiteInteger(0);
+
+			int numCladeTree1 = tree1.numberOfInternalsInClade(tree1.getRoot())-1;  //remove the root
+			int numCladeTree2 = tree2.numberOfInternalsInClade(tree2.getRoot())-1;
+
+			visitOriginal(tree1, tree1.getRoot(), tree2, numCon);
+			if (tree1.getTerminalTaxaAsBits(tree1.getRoot()).equals(tree2.getTerminalTaxaAsBits(tree2.getRoot())))
+				numCon.decrement();
+
+			int numC = numCon.getValue();
+			double fraction = 0.0;
+			if (numCladeTree1+numCladeTree2>0)
+				fraction  = (numC*2.0)/(numCladeTree1+numCladeTree2);
+
+
+			if (verboseOutput.getValue()) {
+				logln("\nnumber of clades in "+tree1.getName() + ": "+numCladeTree1);
+				logln("number of clades in "+tree2.getName() + ": "+numCladeTree2);
+				logln("number of clades in common: "+numC);
+				logln("fraction: "+fraction);
+			}
+
+			result.setValue(fraction);
+			if (resultString!=null) {
+				resultString.setValue("Fraction Shared Clades: "+ result.toString());
+			}
+		} else {
+			result.setValue(MesquiteDouble.inapplicable);
+			if (resultString!=null) {
+				resultString.setValue("Trees differ in size and cannot be compared.");
+			}
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*
+    	 public String getParameters() {
+		return "Shared Clades";
+   	 }
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Fraction of Clades that are Shared";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Calculates the fraction of the total number of clades in two trees that are shared between the trees (excludes the clade consisting of all taxa).";
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+}
diff --git a/Source/mesquite/treefarm/GraftTree/GraftTree.java b/Source/mesquite/treefarm/GraftTree/GraftTree.java
new file mode 100644
index 0000000..2a6c39b
--- /dev/null
+++ b/Source/mesquite/treefarm/GraftTree/GraftTree.java
@@ -0,0 +1,133 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.GraftTree;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class GraftTree extends TreeAltererMult {
+	public String getName() {
+		return "Graft Other Tree";
+	}
+	public String getExplanation() {
+		return "Grafts a tree in a tree window onto given tree; requires that the other tree includes none of the same terminal taxa.  If a taxon in receiving tree is selected, graft occurs there; otherwise, graft occurs at root." ;
+	}
+	OneTreeSource currentTreeSource;
+	int[] termsG = null;
+	String graftTreeDescription = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		currentTreeSource = (OneTreeSource)hireCompatibleEmployee(OneTreeSource.class, new MesquiteBoolean(false), "Source of tree to be modified");
+		if (currentTreeSource == null) {
+			return sorry(getName() + " couldn't start because no source of a graftable tree was obtained.");
+		}
+		if (currentTreeSource == getEmployer())
+			return sorry(getName() + " couldn't start because it would be attempting to graft a tree onto itself, resulting in an infinite recursion.");
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeSource ", currentTreeSource); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the source of the tree to be grafted", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceCompatibleEmployee(OneTreeSource.class, "Source of tree to be grafted", currentTreeSource, new MesquiteBoolean(false));
+			if (temp !=null){
+				currentTreeSource = temp;
+				parametersChanged();
+				return currentTreeSource;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean overlap(int[] a, int[] b){
+		if (a == null || b == null)
+			return false;
+		for (int ia = 0; ia<a.length; ia++){
+			int v = a[ia];
+			for (int ib = 0; ib<b.length; ib++)
+				if (b[ib] == v)
+					return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		Taxa taxa = tree.getTaxa();
+		if (getHiredAs() != TreeAltererMult.class || graftTreeDescription == null){  // if mult, use last one saved
+			Tree t =  currentTreeSource.getTree(taxa);
+			if (t == null)
+				return false;
+			termsG = t.getTerminalTaxa(t.getRoot());
+			graftTreeDescription = t.writeTree(Tree.BY_NAMES);
+			}
+		int[] termsR = tree.getTerminalTaxa(tree.getRoot());
+		if (overlap(termsR, termsG)){
+			if (getHiredAs() != TreeAltererMult.class)
+				discreetAlert("Sorry, to graft a tree, it must share NO terminal taxa with the receiving tree");
+			else
+				MesquiteMessage.warnUser("Sorry, to graft a tree onto " + tree.getName() + ", it must share NO terminal taxa with the receiving tree");
+			return false;
+		}
+ 		int node;
+		if (taxa.numberSelected() ==1 && tree.taxonInTree(taxa.firstSelected())){  
+			//node = tree.nodeOfTaxonNumber(taxa.firstSelected());
+			node = tree.insertNode(tree.nodeOfTaxonNumber(taxa.firstSelected()), false);
+			node = tree.sproutDaughter(node, false);
+		}
+		else {
+			node = tree.insertNode(tree.getRoot(), false);
+			node = tree.sproutDaughter(node, false);
+		}
+		if (!tree.graftCladeFromDescription(graftTreeDescription, node, new MesquiteInteger(0), null))
+			return false;
+
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+
+}
+
diff --git a/Source/mesquite/treefarm/MRPMatrices/MRPMatrices.java b/Source/mesquite/treefarm/MRPMatrices/MRPMatrices.java
new file mode 100644
index 0000000..19a9e72
--- /dev/null
+++ b/Source/mesquite/treefarm/MRPMatrices/MRPMatrices.java
@@ -0,0 +1,259 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.MRPMatrices;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.categ.lib.*;
+
+/** 
+
+ *new in 1.02*
+
+
+/* ======================================================================== */
+public class MRPMatrices extends CharMatrixSource {
+	public String getName() {
+		return "MRP Matrices from Trees";
+	}
+	public String getExplanation() {
+		return "Supplies matrices which represent trees for MRP (Matrix Representation with Parsimony) supertree analyses.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees from which to make MRP matrices.",
+		"The source of trees can be chosen initially or in the Tree Source for MRP submenu");
+	}
+	CharacterDistribution states;
+	MesquiteLong seed;
+	TreeSource treeTask;
+	MesquiteString treeTaskName;
+	Taxa lastTaxa;	
+	MesquiteCommand stC, ttC;
+	boolean numTreesSet = false;
+	int numTrees = 100;
+	boolean initialized = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		ttC =  makeCommand("setTreeSource",  this);
+
+		treeTask= (TreeSource)hireEmployee(TreeSource.class, "Source of trees from which to make MRP matrices");
+		if (treeTask == null) {
+			return sorry(getName() + " can't start because not appropiate tree source module was obtained");
+		}
+		treeTaskName = new MesquiteString();
+		treeTaskName.setValue(treeTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source for MRP", ttC);
+			mss.setSelected(treeTaskName);
+			mss.setList(TreeSource.class);
+		}
+		treeTask.setHiringCommand(ttC);
+
+		return true; 
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		if (m==treeTask)
+			iQuit();
+	}
+
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (lastTaxa!=null)
+			lastTaxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == lastTaxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (!MesquiteThread.isScripting() && (employee != treeTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED))
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (MesquiteInteger.isCombinable(numTrees))
+			temp.addLine("setNumTrees " + numTrees);
+		temp.addLine("setTreeSource ", treeTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module used to supply trees for matrix simulation", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp=  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees on which to simulate matrices", treeTask);
+			if (temp!=null) {
+				treeTask = temp;
+				treeTask.setHiringCommand(ttC);
+				treeTaskName.setValue(treeTask.getName());
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+			return temp;
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees (if indefinite number of trees allowed)", "[number of trees]", commandName, "setNumTrees")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set number of trees", "Number of trees used to make MRP matrix:", numTrees);
+			if (MesquiteInteger.isCombinable(newNum) && newNum>0 && newNum<1000000 && newNum!=numTrees) {
+				numTrees=newNum;
+				numTreesSet = true;
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the block of taxa used", "[block number]", commandName, "setTaxa")) {
+			int setNumber = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (lastTaxa!=null)
+				lastTaxa.removeListener(this);
+			lastTaxa = getProject().getTaxa(checker.getFile(), setNumber);
+			if (lastTaxa!=null)
+				lastTaxa.addListener(this);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void initialize(Taxa taxa){
+		treeTask.initialize(taxa);
+		initialized = true;
+		if (!numTreesSet){
+			int nT = treeTask.getNumberOfTrees(taxa); 
+			if (!MesquiteThread.isScripting() && !MesquiteInteger.isCombinable(nT)){
+
+				int tempNumTrees = MesquiteInteger.queryInteger(containerOfModule(), "Number of trees", "Number of trees with which to make MRP matrix:", numTrees, 1, 1000000, false);
+
+				if (MesquiteInteger.isCombinable(tempNumTrees)) {
+					numTrees = tempNumTrees;
+					numTreesSet = true;
+				}
+				if (!MesquiteInteger.isCombinable(numTrees))
+					numTrees = 100;
+			}
+			else if (!MesquiteInteger.isCombinable(numTrees))
+				numTrees = 100;
+		}
+	}
+	/*.................................................................................................................*/
+	void assignCharacters(Tree tree, int node, int[] allTermsInTree, CategoricalData data){
+		if (tree.nodeIsInternal(node)) { 
+			if (node != tree.getRoot()){
+				int ic = data.getNumChars()-1;
+				data.addParts(ic, 1);
+				ic++;
+				int[] terms = tree.getTerminalTaxa(node);
+				for (int it = 0; it<allTermsInTree.length; it++)
+					data.setState(ic, allTermsInTree[it], 1L);  //state 0 to all in tree
+				for (int iti = 0; iti<terms.length; iti++)
+					data.setState(ic, terms[iti], 2L);  //state 1
+			}
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				assignCharacters(tree, daughter, allTermsInTree, data);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private MCharactersDistribution getM(Taxa taxa){
+		if (treeTask == null) {
+			System.out.println("Tree task null");
+			return null;
+		}
+		else if (taxa==null){
+			System.out.println("taxa null");
+			return null;
+		}
+		if (!initialized)
+			initialize(taxa);
+		int useNumTrees = treeTask.getNumberOfTrees(taxa);
+		if (!MesquiteInteger.isCombinable(useNumTrees))
+			useNumTrees = numTrees;
+		CategoricalData data = new CategoricalData(null, taxa.getNumTaxa(), 0, taxa);
+		data.addParts(-1, 1);
+
+
+		for (int it = 0; it<taxa.getNumTaxa(); it++)
+			data.setToUnassigned(0, it);  //changed 2. 01
+			//data.setState(0, it, 2L);  //state 1 to all as first dummy character
+
+
+		for (int i=0; i<useNumTrees; i++){
+			Tree tree = treeTask.getTree(taxa, i);
+			int[] terms = tree.getTerminalTaxa(tree.getRoot());
+			assignCharacters(tree, tree.getRoot(), terms, data);
+		}
+		
+		data.removeCharactersThatAreEntirelyUnassigned(false);  //added 2. 01
+
+		MCategoricalAdjustable matrix = new MCategoricalAdjustable(taxa, data.getNumChars(), data.getNumTaxa());
+		for (int ic = 0; ic<data.getNumChars(); ic++)
+			matrix.transferFrom(ic, data.getCharacterDistribution(ic));
+		String n = "MRP Matrix from " + useNumTrees + " tree";
+		if (useNumTrees !=1)
+			n += "s";
+		matrix.setName(n);
+		data.setAnnotation(accumulateParameters(" "), false);
+		
+
+		return matrix;
+	}
+	/*.................................................................................................................*/
+	public String getMatrixName(Taxa taxa, int ic) {
+		return "MRP Matrix from trees from " + treeTask.getName() + " (#" + (ic+1) + ")";
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getCurrentMatrix(Taxa taxa){
+		return getM(taxa);
+	}
+	/*.................................................................................................................*/
+	public MCharactersDistribution getMatrix(Taxa taxa, int im){
+		return getM(taxa);
+	}
+	/*.................................................................................................................*/
+	public  int getNumberOfMatrices(Taxa taxa){
+		return 1;
+	}
+	/*.................................................................................................................*/
+	/** returns the number of the current matrix*/
+	public int getNumberCurrentMatrix(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		String s = "MRP Matrix from trees from " + treeTask.getName();
+		return s;
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/treefarm/MakeRerootings/32allRerootings.gif b/Source/mesquite/treefarm/MakeRerootings/32allRerootings.gif
new file mode 100644
index 0000000..3049e91
Binary files /dev/null and b/Source/mesquite/treefarm/MakeRerootings/32allRerootings.gif differ
diff --git a/Source/mesquite/treefarm/MakeRerootings/64allRerootings.gif b/Source/mesquite/treefarm/MakeRerootings/64allRerootings.gif
new file mode 100644
index 0000000..927b847
Binary files /dev/null and b/Source/mesquite/treefarm/MakeRerootings/64allRerootings.gif differ
diff --git a/Source/mesquite/treefarm/MakeRerootings/MakeRerootings.java b/Source/mesquite/treefarm/MakeRerootings/MakeRerootings.java
new file mode 100644
index 0000000..d157c86
--- /dev/null
+++ b/Source/mesquite/treefarm/MakeRerootings/MakeRerootings.java
@@ -0,0 +1,100 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.MakeRerootings;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class MakeRerootings extends TreeDisplayAssistantI {
+	public String getFunctionIconPath(){
+		return getPath() + "allRerootings.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		AllRerootToolExtra newPj = new AllRerootToolExtra(this, treeDisplay);
+		return newPj;
+	}
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return false; //as init, the citation would show up even if this had not been used
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Make Rerootings of Clade";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Presents a tool by which you can touch on a tree;  a tree block is made consisting of trees representing all rerootings of the clade of the node touched.";
+	}
+
+}
+
+/* ======================================================================== */
+class AllRerootToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool rerootingsTool;
+	public AllRerootToolExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		rerootingsTool = new TreeTool(this, "allRerootings", ownerModule.getPath(), "allRerootings.gif", 11,5,"Make All Rerootings of Clade", "This tool constructs all rerootings within clade of node touched");
+		rerootingsTool.setTouchedCommand(MesquiteModule.makeCommand("makeAllRerootings",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(rerootingsTool);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawNode(Tree tree, int node, Graphics g) {}
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {}
+	public   void setTree(Tree tree) {}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Makes and adds to file a tree block of all rerootings of current tree", "[node]", commandName, "makeAllRerootings")) {
+			Tree tree = treeDisplay.getTree();
+			int M = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (tree.nodeIsUnbranchedInternal(M) || tree.nodeIsUnbranchedInternal(tree.motherOfNode(M))){
+				ownerModule.discreetAlert("Sorry, you can't chose an unbranched internal node or a descendant of one for making rerootings");
+				return null;
+			}
+			String name = MesquiteString.queryString(ownerModule.containerOfModule(), "Rerooted clade", "Name of tree block:", "Rerootings");
+			if (!StringUtil.blank(name)){
+
+				TreeVector trees = new TreeVector(tree.getTaxa());
+				trees.setName(name);
+				tree.makeAllRootings(M, trees);
+
+				trees.addToFile(null, ownerModule.getProject(), null);
+				ownerModule.resetAllMenuBars();
+				return trees;
+			}
+		}
+		return null;
+	}
+}
+
+
+
diff --git a/Source/mesquite/treefarm/MakeRerootings/allRerootings.gif b/Source/mesquite/treefarm/MakeRerootings/allRerootings.gif
new file mode 100644
index 0000000..a08e399
Binary files /dev/null and b/Source/mesquite/treefarm/MakeRerootings/allRerootings.gif differ
diff --git a/Source/mesquite/treefarm/ModTreesOtherSource/ModTreesOtherSource.java b/Source/mesquite/treefarm/ModTreesOtherSource/ModTreesOtherSource.java
new file mode 100644
index 0000000..9da1584
--- /dev/null
+++ b/Source/mesquite/treefarm/ModTreesOtherSource/ModTreesOtherSource.java
@@ -0,0 +1,253 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.ModTreesOtherSource;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class ModTreesOtherSource extends SourceFromTreeSource {
+	public String getName() {
+		return "Transform Trees from Other Source";
+	}
+	public String getNameForMenuItem() {
+		return "Transform Trees from Other Source...";
+	}
+	public String getExplanation() {
+		return "Transforms trees from another source.";
+	}
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		super.getEmployeeNeeds();
+		EmployeeNeed e = registerEmployeeNeed(TreeTransformer.class, getName() + "  needs a method to modify trees.",
+		"The method to modify trees can be chosen initially or in the Transformer of Trees submenu");
+	}
+	int currentTree=0;
+	int lastGoodTree = -1;
+	int lastTreeRequested = -1;
+	int maxAvailable = -2;
+	boolean noProblemsYet = true;
+	boolean queried = false;
+	TreeTransformer modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	MesquiteBoolean discardUntransformable;
+	boolean valueSpecified = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (!super.startJob(arguments, condition, hiredByName))
+			return false;
+		modifierTask = (TreeTransformer)hireEmployee(TreeTransformerMult.class, "Transformer of trees (transforms trees " + whatIsMyPurpose() + ")");
+		if (modifierTask == null) {
+			return sorry(getName() + " couldn't start because no tree transformer was obtained.");
+		}
+		discardUntransformable = new MesquiteBoolean(true);
+		stC = makeCommand("setModifier",  this);
+		modifierTask.setHiringCommand(stC);
+		modifierName = new MesquiteString();
+		modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(TreeTransformerMult.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Transformer of Trees (" + whatIsMyPurpose() + ")", stC, TreeTransformerMult.class);
+			mss.setSelected(modifierName);
+		}
+		addCheckMenuItem(null, "Discard Untransformable Trees", makeCommand("discardUntransformable", this), discardUntransformable);
+
+		return true;
+	}
+	/* ................................................................................................................. */
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis"). */
+	public String purposeOfEmployee(MesquiteModule employee) {
+		if (employee == currentTreeSource || employee instanceof TreeSource)
+			return "to supply trees to be transformed";
+		else if (employee == modifierTask)
+		return "to transform trees"; // to be overridden
+		else return super.purposeOfEmployee(employee);
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa){
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setModifier ", modifierTask); 
+		temp.addLine("discardUntransformable " + discardUntransformable.toOffOnString()); 
+		return temp;
+	}
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		lastGoodTree = -1;
+		lastTreeRequested = -1;
+		maxAvailable = -2;
+		noProblemsYet = true;
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree transformer", "[name of module]", commandName, "setModifier")) {
+			TreeTransformer temp = (TreeTransformer)replaceEmployee(TreeTransformerMult.class, arguments, "Transformer of trees", modifierTask);
+			if (temp !=null){
+				modifierTask = temp;
+				modifierName.setValue(modifierTask.getName());
+				modifierTask.setHiringCommand(stC);
+				lastGoodTree = -1;
+				lastTreeRequested = -1;
+				maxAvailable = -2;
+				noProblemsYet = true;
+				parametersChanged();
+				return modifierTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not untransformable trees are discarded or retained", "[on = discard; off=retain]", commandName, "discardUntransformable")) {
+			boolean current =discardUntransformable.getValue();
+			discardUntransformable.toggleValue(parser.getFirstToken(arguments));
+			if (current != discardUntransformable.getValue()){
+				noProblemsYet = true;
+				lastGoodTree = -1;
+				lastTreeRequested = -1;
+				maxAvailable = -2;
+			}
+			valueSpecified = true;
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public MesquiteTree getTreeSimple(Taxa taxa, int ic, MesquiteBoolean success, MesquiteString message, MesquiteString originalTreeName) {  
+		Tree tree = getBasisTree(taxa, ic);
+		currentTree = ic;
+		if (tree == null) {
+			return null;
+		}
+		MesquiteTree modified =  tree.cloneTree();
+		success.setValue(modifierTask.transformTree(modified, message, false));
+		if (success.getValue())
+			modified.setName("Transformed from " + tree.getName() + " (#" + (currentTree + 1) + ")");
+		else
+			modified.setName("Untransformed tree [" + tree.getName() + "] (#" + (currentTree + 1) + ")");
+		originalTreeName.setValue(tree.getName());
+		return modified;
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int ic) {  
+		MesquiteBoolean success = new MesquiteBoolean(false);
+		MesquiteString message = new MesquiteString();
+		MesquiteString originalTreeName = new MesquiteString();
+		MesquiteTree modified = null;
+		if (noProblemsYet){
+			modified = getTreeSimple(taxa, ic, success, message, originalTreeName);
+			if (modified == null)
+				return null;
+			else if (success.getValue())
+				return modified;
+			else {
+				if (!queried && !MesquiteThread.isScripting() && !valueSpecified){  
+					if (AlertDialog.query(containerOfModule(), "Untransformable tree", "A tree ("  + originalTreeName.getValue() + ") could not be transformed as requested (reason given: " + message + ").  Do you want to discard untransformable trees, or include them untransformed?", "Discard", "Include Untransformed")) {
+						//usetrees anyway
+						discardUntransformable.setValue(true);
+
+					}
+					else
+						discardUntransformable.setValue(false);
+					queried = true;
+					valueSpecified = true;
+				}
+				if (!discardUntransformable.getValue()) {
+					logln(originalTreeName.getValue() + " could not be transformed, and is included untransformed.");
+					return modified;
+				}
+				lastGoodTree = -1;
+				lastTreeRequested = -1;
+				maxAvailable = -2;
+				noProblemsYet = false;
+
+			}
+		}
+		else 
+			modified = new MesquiteTree(taxa);
+
+
+		int iTry = 0;
+		int count = -1;
+		if (ic>maxAvailable && maxAvailable>-2)
+			return null;
+		if (lastTreeRequested == ic)  //recently requested same; return it without checking filter (since change in filter would have reset lastTreeRequested etc.)
+			return getBasisTree(taxa, lastGoodTree);
+		else if (lastTreeRequested >= 0 && lastTreeRequested == ic-1) {
+			//go from last requested
+			iTry = lastGoodTree+1;
+			count = lastTreeRequested;
+
+		}
+		Tree tree = null;
+
+		TreeSource ts = getBasisTreeSource();
+		int numTrees = ts.getNumberOfTrees(taxa); 
+		while (count<ic) {
+			tree = getBasisTree(taxa, iTry);
+			if (tree == null)  {
+				maxAvailable = count;
+				return null;
+			}
+			modified.setToClone((MesquiteTree)tree);
+			if (modifierTask.transformTree(modified, message, false)){
+				count++;
+			}		
+			else {
+				tree = null;
+			}
+			iTry++;
+		}
+		currentTree = ic;
+		lastGoodTree = iTry-1;
+		lastTreeRequested = ic;
+		return modified;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		if (noProblemsYet || !discardUntransformable.getValue())
+			return getBasisTreeSource().getNumberOfTrees(taxa);
+		if (maxAvailable<-1) {
+			if (getBasisTreeSource().getNumberOfTrees(taxa) == MesquiteInteger.infinite)
+				return MesquiteInteger.infinite;
+			return MesquiteInteger.finite; //don't know how many will be discarded
+		}
+		else
+			return maxAvailable+1;
+	}
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		return "Transformation of tree #" + (itree +1);
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return"Transforming trees from: " + getBasisTreeSource().getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/treefarm/NNAssocValues/NNAssocValues.java b/Source/mesquite/treefarm/NNAssocValues/NNAssocValues.java
new file mode 100644
index 0000000..29bf00a
--- /dev/null
+++ b/Source/mesquite/treefarm/NNAssocValues/NNAssocValues.java
@@ -0,0 +1,97 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.NNAssocValues;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class NNAssocValues extends BranchLengthsAlterer {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Obtain Branch Lengths from Values Attached to Nodes";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Assigns branch lengths to the tree taken from values already attached to nodes, for instance support values or divergence times from other programs.";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+	}
+	/*.................................................................................................................*/
+	public   void visitNodes(int node, AdjustableTree tree, NameReference nr) {
+		double value = tree.getAssociatedDouble(nr,node);
+		if (MesquiteDouble.isCombinable(value))
+			tree.setBranchLength(node, value, false);
+		else
+			tree.setBranchLength(node, MesquiteDouble.unassigned, false);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			visitNodes(d, tree, nr);
+	}
+	/*.................................................................................................................*/
+	//Should be overridden; when previous version is deleted in future, this will be abstract.  returns whether successfully transformed.
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree == null)
+			return false;
+		ListableVector v = new ListableVector();
+		int num = tree.getNumberAssociatedDoubles();
+		boolean[] shown = new boolean[num]; //bigger than needed probably
+		for (int i = 0; i< num; i++){
+			DoubleArray da = tree.getAssociatedDoubles(i);
+			if (da != null)
+				v.addElement(new MesquiteString(da.getName(), ""), false);
+		}
+		if (v.size()==0)
+			alert("This Tree has no values attached to nodes");
+		else {
+			Listable result = ListDialog.queryList(containerOfModule(), "Choose attached value", "Choose attached value to transfer to branch lengths", null, v, 0);
+			if (result != null){
+				MesquiteString name = (MesquiteString)result;
+				String sName = name.getName();
+				NameReference nr = NameReference.getNameReference(sName);
+
+				visitNodes(tree.getRoot(), tree, nr);
+
+				if (notify && tree instanceof Listened)
+					((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+				return true;
+			}
+
+		}
+
+		return false;
+
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 274;  
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/NodeDepth/NodeDepth.java b/Source/mesquite/treefarm/NodeDepth/NodeDepth.java
new file mode 100755
index 0000000..d4a5c54
--- /dev/null
+++ b/Source/mesquite/treefarm/NodeDepth/NodeDepth.java
@@ -0,0 +1,77 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.NodeDepth;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class NodeDepth extends NumbersForNodes {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+    	}
+	/*.................................................................................................................*/
+	public   void visitNodes(int node, Tree tree, NumberArray result) {
+		result.setValue(node, tree.tallestPathAboveNode(node, 0));
+
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			visitNodes(d, tree, result);
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree == null )
+			return;
+
+		visitNodes(tree.getRoot(), tree, result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+
+	}
+	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Node Depth";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the depth of each node from the highest terminal in its clade.";
+   	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+}
+
diff --git a/Source/mesquite/treefarm/NoiseToBranchLengths/NoiseToBranchLengths.java b/Source/mesquite/treefarm/NoiseToBranchLengths/NoiseToBranchLengths.java
new file mode 100644
index 0000000..f33d989
--- /dev/null
+++ b/Source/mesquite/treefarm/NoiseToBranchLengths/NoiseToBranchLengths.java
@@ -0,0 +1,122 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.NoiseToBranchLengths;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* TODO: put in options beyond simple Normal noise (e.g., binary?)  */
+public class NoiseToBranchLengths extends RndTreeModifier {
+	double variance = 0.1;
+	MesquiteBoolean proport;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		proport = new MesquiteBoolean(true);
+  		if (!MesquiteThread.isScripting()){
+    	 		double s = queryVariance();
+ 	 		if (MesquiteDouble.isCombinable(s) && s>=0)
+ 	 			variance = s;
+ 	 		else
+ 				return false;
+  		}
+  		addMenuItem("Variance of Noise...", makeCommand("setNoise",  this));
+		addCheckMenuItem(null,"Variance of Noise Proportional to Length", makeCommand("toggleProport",  this), proport);
+  		return true;
+  	 }
+  	 private double queryVariance(){
+		if (proport.getValue())
+			return MesquiteDouble.queryDouble(containerOfModule(), "Variance of noise", "Enter the variance multiplier of noise to add to branch lengths (variance of noise = multiplier * branch length)", variance);
+		else
+			return MesquiteDouble.queryDouble(containerOfModule(), "Variance of noise", "Enter the variance of noise to add to branch lengths", variance);
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setNoise " + variance);
+  	 	temp.addLine("toggleProport " + proport.toOffOnString());
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	if (checker.compare(this.getClass(), "Sets the variance of noise to add to branch lengths", "[real number]", commandName, "setNoise")) {
+    	 		double s = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteDouble.isCombinable(s)){
+    	 			s = queryVariance();
+    	 		}
+    	 		if (MesquiteDouble.isCombinable(s) && s>=0){
+    	 			variance = s;
+ 					parametersChanged(); 
+ 				}
+    	 	}
+		else if (checker.compare(getClass(), "Sets whether variance is to be proportional to current branch length", null, commandName, "toggleProport")) {
+    	 		proport.toggleValue(parser.getFirstToken(arguments));
+ 			parametersChanged(); 
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+	
+	void addNoise(MesquiteTree tree, int node, RandomBetween rng, double sd){
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			addNoise(tree, d, rng, sd);
+		double bL = tree.getBranchLength(node);		
+		if (MesquiteDouble.isCombinable(bL)){ //add noise only if defined
+			if (proport.getValue())
+				bL += bL*rng.nextGaussian()*sd;
+			else
+				bL += rng.nextGaussian()*sd;
+			if (bL<0)
+				bL = 0;
+			tree.setBranchLength(node, bL, false);
+		}
+	}
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng){
+   		if (tree == null || modified == null)
+   			return;
+		double sd = Math.sqrt(variance);
+		addNoise(modified, modified.getRoot(), rng, sd);
+		
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		if (proport.getValue())
+   			return"Variance multiplier of noise added to branch lengths proportionately: " + variance;
+   		else
+   			return"Variance of noise added to branch lengths: " + variance;
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add Noise to Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Adds noise to branch lengths of tree.  Noise is Normally distributed, with variance as selected.  By default the variance is be proportional to current branch length, so that if branch length is 10 and you've indicated a variance multiplier of 0.1, the noise added will have a variance of 1.0.  Negative branch lengths are not allowed, and are changed to zero.";
+   	 }
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/NumTopologyCongruent/NumTopologyCongruent.java b/Source/mesquite/treefarm/NumTopologyCongruent/NumTopologyCongruent.java
new file mode 100644
index 0000000..9186095
--- /dev/null
+++ b/Source/mesquite/treefarm/NumTopologyCongruent/NumTopologyCongruent.java
@@ -0,0 +1,141 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.NumTopologyCongruent;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.NumberForTree;
+import mesquite.lib.duties.TreeSourceDefinite;
+
+public class NumTopologyCongruent extends NumberForTree {
+	TreeSourceDefinite treeSourceTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand tstC;
+	Taxa currentTaxa = null;
+	boolean suspend = false;
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSourceDefinite.class, getName() + " needs a source of trees which will then be condensed.",
+		"The source of other trees is indicated initially.");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeSourceTask = (TreeSourceDefinite)hireEmployee(TreeSourceDefinite.class, "Tree Source");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSourceDefinite.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tstC, TreeSourceDefinite.class);
+			mss.setSelected(treeSourceName);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend");
+		temp.addLine("getTreeSource",treeSourceTask);
+		temp.addLine("resume");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns treeSourceTask", null, commandName, "getTreeSource")) 
+			return treeSourceTask;
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			parametersChanged();
+		}
+		else 
+			super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		setPreferredTaxa(taxa);
+	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		storePreferences();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+		}
+	}
+
+	/*.................................................................................................................*/
+
+	public void setPreferredTaxa(Taxa taxa){
+		if (taxa !=currentTaxa) {
+			if (currentTaxa!=null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+
+	}
+	/*.................................................................................................................*/
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (tree==null || result==null || treeSourceTask==null)
+			return;
+		clearResultAndLastResult(result);
+		Taxa taxa = tree.getTaxa();
+		int numOriginalTrees = treeSourceTask.getNumberOfTrees(taxa);
+
+		int count=0;
+		for (int i=0; i<numOriginalTrees; i++){
+			Tree comparisonTree =  treeSourceTask.getTree(taxa, i);
+			if (tree.equalsTopology(comparisonTree,false))
+				count++;
+		}
+		result.setValue(count);
+		if (resultString!=null)
+			resultString.setValue("" + count + " trees congruent");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+	public String getName() {
+		return "Number of Congruent Trees";
+	}
+	public String getExplanation() {
+		return "For the given tree, returns the number of trees in the tree source that are congruent with it.";
+	}
+
+	/*........................................................*/
+    public int getVersionOfFirstRelease(){
+        return 260;
+    }
+
+
+}
diff --git a/Source/mesquite/treefarm/NumTreesMatchingCriterion/NumTreesMatchingCriterion.java b/Source/mesquite/treefarm/NumTreesMatchingCriterion/NumTreesMatchingCriterion.java
new file mode 100755
index 0000000..40ce420
--- /dev/null
+++ b/Source/mesquite/treefarm/NumTreesMatchingCriterion/NumTreesMatchingCriterion.java
@@ -0,0 +1,99 @@
+package mesquite.treefarm.NumTreesMatchingCriterion;
+/* Mesquite source code, NumTreesMatchingCriterion.  J.C. Oliver.  July 2010.
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.ProbModelSourceLike;
+
+public class NumTreesMatchingCriterion extends NumberForTreeBlock {
+	BooleanForTree treeCriterionTask;
+	MesquiteCommand criterionCommand;
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e1 = registerEmployeeNeed(BooleanForTree.class, getName() + " needs a criterion for trees.", "The criterion for trees trees is indicated initially.");
+	}
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeCriterionTask = (BooleanForTree)hireEmployee(BooleanForTree.class, "Criterion for Trees");
+		if(treeCriterionTask == null)
+			return sorry(getName() + " could not start because no tree criterion module was found.");
+		criterionCommand =makeCommand("setCriterion",  this);
+		treeCriterionTask.setHiringCommand(criterionCommand);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Criterion for Trees", criterionCommand);
+		mss.setList(BooleanForTree.class);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCriterion ",treeCriterionTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(TreeVector trees, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || trees ==null)
+			return;
+		clearResultAndLastResult(result);
+		int metCriterion = 0;
+		MesquiteBoolean criterionHolder = new MesquiteBoolean();
+		for(int it = 0; it < trees.size(); it++){
+			Tree tree = trees.getTree(it);
+			criterionHolder.setToUnassigned();
+			treeCriterionTask.calculateBoolean(tree, criterionHolder, null);
+			if(criterionHolder.getValue()){
+				metCriterion++;
+			}
+		}
+
+		result.setValue(metCriterion);
+		if (resultString!=null)
+			resultString.setValue(result.toString() + " of " + trees.size() + " met the specified criterion (" + treeCriterionTask.getName() + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if(checker.compare(this.getClass(), "Sets module for tree criterion", "[name of module]", commandName, "setCriterion")){
+			BooleanForTree tempCriterion = (BooleanForTree)replaceEmployee(BooleanForTree.class, arguments, "Criterion for trees", treeCriterionTask);
+			if(tempCriterion != null){
+				treeCriterionTask = tempCriterion;
+				parametersChanged();
+			}
+			return treeCriterionTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public void initialize(TreeVector trees) {
+		treeCriterionTask.initialize(trees.getTree(0));
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number of Trees Matching Criterion";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation(){
+		return "Counts the number of trees in a tree block that match a user-specified criterion.  For example, it could " +
+				"count the number of trees in a tree block which are congruent with a particular tree topology (by " +
+				"selecting the \"Tree Congruent with Constraint Tree Topology\" module in the Criterion for Trees dialog).";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+    /*........................................................*/
+    public int getVersionOfFirstRelease(){
+        return 273;
+    }
+}
diff --git a/Source/mesquite/treefarm/OutgroupRoot/OutgroupRoot.java b/Source/mesquite/treefarm/OutgroupRoot/OutgroupRoot.java
new file mode 100644
index 0000000..49d0c48
--- /dev/null
+++ b/Source/mesquite/treefarm/OutgroupRoot/OutgroupRoot.java
@@ -0,0 +1,130 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+/* December 2003  D.R. Maddison */
+
+package mesquite.treefarm.OutgroupRoot;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class OutgroupRoot extends TreeAltererMult {
+	int warnings = 0;
+	int treeNumber = 0;
+	boolean unselectedAlreadyWarned = false;
+	static final int warningsLimit = 10;
+	String notRooted = "";
+	Taxa currentTaxa = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	public void endJob() {
+ 		if (warnings>warningsLimit) 
+ 			logln("  (In addition, among the chosen trees,  numbers " + notRooted + " among others could not be rerooted)");
+ 		else if (warnings>1)
+ 			logln("  (In addition, among the chosen trees,  numbers " + notRooted + " could not be rerooted)");
+  	 	if (currentTaxa != null)
+  	 		currentTaxa.removeListener(this);
+ 		super.endJob();
+   	 }
+
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && code == MesquiteListener.SELECTION_CHANGED){
+			parametersChanged();
+		}
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree==null)
+			return false;
+		Taxa taxa = tree.getTaxa();
+		if (currentTaxa != taxa){
+			if (currentTaxa != null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+		if (!taxa.anySelected()) {
+ 			if (!unselectedAlreadyWarned)
+ 				discreetAlert("Before trees can be rerooted using the selected taxa as outgroups, some taxa must be selected");
+ 			unselectedAlreadyWarned = true;
+			return false;
+		}
+		treeNumber ++;
+		MesquiteInteger descendantNode = new MesquiteInteger(-1);
+		tree.setRooted(true, notify);
+		boolean isconvex = tree.isConvex(taxa.getSelectedBits(), descendantNode);
+		if (isconvex && descendantNode.getValue() >=0) {
+			double oldBL = tree.getBranchLength(descendantNode.getValue());
+			if (tree.reroot(descendantNode.getValue(), tree.getRoot(), false)) {
+				if (MesquiteDouble.isCombinable(oldBL)) {
+					int node = tree.getRoot();
+					int rootDescendants = tree.numberOfDaughtersOfNode(node);
+					double newBL = oldBL/rootDescendants;
+					for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+	   					tree.setBranchLength(daughter, newBL, notify);
+					}
+				}
+			}
+			if (resultString != null)
+				resultString.setValue("Tree rerooted");
+		}
+		else {
+			String w = "Tree " + treeNumber + " among chosen trees could not be rerooted between the selected and unselected taxa, as the unselected taxa cannot be made monophyletic";
+			if (resultString != null)
+				resultString.setValue(w);
+			warnings++;
+			if (warnings<2)
+				logln(w);
+			else if (warnings<=warningsLimit)
+				notRooted += " " + treeNumber;
+			return false;
+
+		}
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Root tree with selected taxa as outgroup";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Roots the tree between the selected taxa and the remainder, if possible." ;
+   	 }
+ 	public String getKeywords(){
+ 		return "reroots";
+ 	}
+}
+
diff --git a/Source/mesquite/treefarm/ProbRndTreeModifier/ProbRndTreeModifier.java b/Source/mesquite/treefarm/ProbRndTreeModifier/ProbRndTreeModifier.java
new file mode 100644
index 0000000..038a809
--- /dev/null
+++ b/Source/mesquite/treefarm/ProbRndTreeModifier/ProbRndTreeModifier.java
@@ -0,0 +1,131 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.ProbRndTreeModifier;
+
+import java.util.Random;
+import mesquite.lib.*;
+import mesquite.lib.duties.CharSourceCoordObed;
+import mesquite.lib.duties.NumberFor2CharAndTree;
+import mesquite.treefarm.lib.*;
+
+/** This module is basically a random tree modifier, but it works by hiring another one, and only invoking it on a tree with a particular probability */
+public class ProbRndTreeModifier extends RndTreeModifier {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(RndTreeModifier.class, getName() + "  needs a method to modify trees.",
+		"The method to modify the tree can be selected initially or in the Random Modifier of Tree submenu");
+	}
+	Random probModifyRNG = new RandomBetween(System.currentTimeMillis()); ;
+	RndTreeModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	double defaultProbability = 0.5;
+	MesquiteDouble prob = new MesquiteDouble(defaultProbability);
+	
+	public boolean startJob(String arguments, Object condition,boolean hiredByName) {
+		if (arguments ==null)
+			modifierTask = (RndTreeModifier)hireEmployee(RndTreeModifier.class, "Random modifier of tree");
+		else {
+			modifierTask = (RndTreeModifier)hireNamedEmployee(RndTreeModifier.class, arguments);
+			if (modifierTask == null)
+				modifierTask = (RndTreeModifier)hireEmployee(RndTreeModifier.class, "Random modifier of tree");
+		}
+		if (modifierTask == null) {
+			return sorry(getName() + " couldn't start because no random tree modifier was obtained.");
+		}
+		stC = makeCommand("setModifier",  this);
+		modifierTask.setHiringCommand(stC);
+		modifierName = new MesquiteString();
+		modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(RndTreeModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Random Modifier of Tree (used by Occasionally Modify)", stC, RndTreeModifier.class);
+			mss.setSelected(modifierName);
+		}
+  		addMenuItem("Set Probability of Random Tree Modification...", makeCommand("setProbability",  this));
+  		if (!MesquiteThread.isScripting()) {
+			double s = MesquiteDouble.queryDouble(containerOfModule(), "Random number seed", "Enter a value for the probability a tree will be randomly modified", prob.getValue());
+	 		 if (MesquiteDouble.isCombinable(s)){
+	 			 prob.setValue(s);
+	 		 }
+  		}
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return RndTreeModifier.class;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setProbability " + prob.getValue());
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the tree modifier", "[name of module]", commandName, "setModifier")) {
+			RndTreeModifier temp = (RndTreeModifier)replaceEmployee(RndTreeModifier.class, arguments, "Random modifier of tree", modifierTask);
+			if (temp !=null){
+				modifierTask = temp;
+				modifierName.setValue(modifierTask.getName());
+				modifierTask.setHiringCommand(stC);
+				parametersChanged();
+				return modifierTask;
+			}
+		}
+  	 	 else if (checker.compare(this.getClass(), "Sets the probability of modification", "[probability (a double)]", commandName, "setProbability")) {
+	 		 double s = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+	 		 if (!MesquiteDouble.isCombinable(s)){
+	 			 s = MesquiteDouble.queryDouble(containerOfModule(), "Random number seed", "Enter a value for the probability a tree will be randomly modified", prob.getValue());
+	 		 }
+	 		 if (MesquiteDouble.isCombinable(s)){
+	 			 prob.setValue(s);
+	 			 parametersChanged(); //?
+	 		 }
+	 	 }
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	int count=0;
+	
+	public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng) {
+		if (modifierTask==null || tree==null)
+			return;
+		probModifyRNG.setSeed(rng.nextInt());
+		if (probModifyRNG.nextDouble()<=prob.getValue())
+			modifierTask.modifyTree(tree,modified, rng);
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	
+	public String getName() {
+		return "Occasionally Randomly Modify";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	public String getExplanation() {
+		return "With specified probabililty, will ask random tree modifier to modify current tree.";
+	}
+
+}
diff --git a/Source/mesquite/treefarm/RandomBranchMoves/RandomBranchMoves.java b/Source/mesquite/treefarm/RandomBranchMoves/RandomBranchMoves.java
new file mode 100644
index 0000000..782059c
--- /dev/null
+++ b/Source/mesquite/treefarm/RandomBranchMoves/RandomBranchMoves.java
@@ -0,0 +1,124 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.RandomBranchMoves;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class RandomBranchMoves extends RndTreeModifier {
+	int numMoves=1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		if (!MesquiteThread.isScripting()){
+	    	 	int s = MesquiteInteger.queryInteger(containerOfModule(), "Number of random branch moves", "Enter the number of random branch moves", numMoves);
+ 	 		if (MesquiteInteger.isCombinable(s))
+ 	 			numMoves = s;
+ 	 		else
+ 				return false;
+  		}
+  		addMenuItem("Number of Random branch moves...", makeCommand("setNumberMoves",  this));
+  		return true;
+  	 }
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setNumberMoves " + numMoves);
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	if (checker.compare(this.getClass(), "Sets the number of random branch moves", "[number]", commandName, "setNumberMoves")) {
+    	 		int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteInteger.isCombinable(s)){
+    	 			s = MesquiteInteger.queryInteger(containerOfModule(), "Number of moves", "Enter the number of random branch moves", numMoves);
+    	 		}
+    	 		if (MesquiteInteger.isCombinable(s)){
+    	 			numMoves = s;
+ 				parametersChanged(); 
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	private void setColor(Tree tree, int node){
+		if (tree == null || !(tree instanceof Associable))
+			return;
+		Associable aTree = (Associable)tree;
+		if (aTree.getWhichAssociatedLong(colorNameRef)==null)
+			aTree.makeAssociatedLongs("color");
+		aTree.setAssociatedLong(colorNameRef, node, ColorDistribution.numberOfRed, true);
+	}
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng){
+   		if (tree == null || modified == null)
+   			return;
+		int numBranches =tree.numberOfNodesInClade(tree.getRoot());
+		int numTerm =tree.numberOfTerminalsInClade(tree.getRoot());
+		
+		if (numBranches == 1)
+			return;
+   		for (int it = 0; it<numMoves; it++) {
+   			int branchFrom;
+   			int branchTo;
+   			int count = 0;
+   			boolean success = false;
+   			do {
+   				branchFrom = modified.nodeInTraversal(rng.randomIntBetween(0, numBranches), modified.getRoot());
+   				branchTo = modified.nodeInTraversal(rng.randomIntBetween(0, numBranches), modified.getRoot());
+   				count++;
+   				if (count%10000 == 0){
+   					MesquiteMessage.printStackTrace("Possible problem: in Random Branch Moves,  count >10000");
+   				}
+   				if (count<20001)
+   					success = modified.moveBranch(branchFrom, branchTo, false);
+   				if (success)
+   					setColor(modified, branchFrom);
+   			}
+   			while (count<20001 && !success); //each attempt at a move is guaranteed to make a real move; thus from a 2-2 symm tree of four, 1 move is guaranteed to make 1-3 asymm
+		//	modified.moveBranch(branchFrom, branchTo, false);
+   		}
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Number of random branch moves: " + numMoves;
+   	}
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Random Branch Moves";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Rearranges tree by random branch moves.";
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/RandomModifTree/RandomModifTree.java b/Source/mesquite/treefarm/RandomModifTree/RandomModifTree.java
new file mode 100644
index 0000000..2de64e6
--- /dev/null
+++ b/Source/mesquite/treefarm/RandomModifTree/RandomModifTree.java
@@ -0,0 +1,178 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.RandomModifTree;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class RandomModifTree extends SourceModifiedTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(RndTreeModifier.class, getName() + "  needs a method to randomly modify trees.",
+		"The method to randomly modify trees can be selected initially or in the Random Modifier of Tree submenu");
+	}
+	int currentTree=0;
+
+	MesquiteLong seed;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	RandomBetween rng = new RandomBetween();
+	RndTreeModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	  MesquiteTimer timer = new MesquiteTimer();
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		   timer.start();
+		if (!super.startJob(arguments, condition, hiredByName))
+ 			return false;
+ 		if (arguments ==null)
+ 			modifierTask = (RndTreeModifier)hireEmployee(RndTreeModifier.class, "Random modifier of tree");
+	 	else {
+	 		modifierTask = (RndTreeModifier)hireNamedEmployee(RndTreeModifier.class, arguments);
+ 			if (modifierTask == null)
+ 				modifierTask = (RndTreeModifier)hireEmployee(RndTreeModifier.class, "Random modifier of tree");
+ 		}
+ 		if (modifierTask == null) {
+ 			return sorry(getName() + " couldn't start because no random tree modifier was obtained.");
+ 		}
+ 	 	stC = makeCommand("setModifier",  this);
+ 	 	modifierTask.setHiringCommand(stC);
+ 		modifierName = new MesquiteString();
+	   	 modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(RndTreeModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Random Modifier of Tree", stC, RndTreeModifier.class);
+ 			mss.setSelected(modifierName);
+  		}
+ 	 	seed = new MesquiteLong(1);
+ 	 	seed.setValue(originalSeed);
+  		addMenuItem("Set Seed (Random tree modification)...", makeCommand("setSeed",  this));
+  		return true;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return RndTreeModifier.class;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = super.getSnapshot(file);
+  	 	temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the tree modifier", "[name of module]", commandName, "setModifier")) {
+			RndTreeModifier temp = (RndTreeModifier)replaceEmployee(RndTreeModifier.class, arguments, "Random modifier of tree", modifierTask);
+			if (temp !=null){
+				modifierTask = temp;
+    	 			modifierName.setValue(modifierTask.getName());
+		 	 	modifierTask.setHiringCommand(stC);
+				parametersChanged();
+    	 			return modifierTask;
+    	 		}
+    	 	}
+    	 	 else if (checker.compare(this.getClass(), "Sets the random number seed", "[long integer seed]", commandName, "setSeed")) {
+    	 		 long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		 if (!MesquiteLong.isCombinable(s)){
+    	 			 s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for random modification of tree", originalSeed);
+    	 		 }
+    	 		 if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+    	 			 parametersChanged(); //?
+    	 		 }
+    	 	 }
+    	 	 else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+    	 
+		
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int ic) {  
+   		MesquiteTree modified = null;
+   		int code = 0;
+   		try {
+   			code = 1;
+	   		Tree tree = getBasisTree(taxa);
+   			code = 2;
+	   		currentTree = ic;
+   			code = 3;
+	   		if (tree == null)
+	   			return null;
+	   		code = 4;
+	   		rng.setSeed(originalSeed);
+	   		code = 5;
+	   		long rnd = originalSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+	   		code = 6;
+	   		for (int it = 0; it<=currentTree; it++) 
+	   			rnd =  rng.nextInt();
+	   		rng.setSeed(rnd+1);
+	   		seed.setValue(rnd + 1);  //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+	   		code = 8;
+	   		modified =  tree.cloneTree();
+  			code = 9;
+	   		modifierTask.modifyTree(tree, modified, rng);
+  			code = 10;
+	   		modified.setName("Randomly modified from " + tree.getName() + " (#" + currentTree + ")");
+	   		MesquiteDouble md = new MesquiteDouble(0.2);
+	   		md.setName("test");
+	   		modified.attachIfUniqueName(md);
+	   		
+   		}
+   		catch (Error e){
+   			System.out.println("Error " + e + " ===== " + code);
+   		}
+   		return modified;
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		Tree tree = getBasisTree(taxa);
+		if (tree ==null)
+			return 0;
+		else
+			return MesquiteInteger.infinite;
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return "Random modification #" + (itree+1);
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		return"Randomly modifying tree from: " + getBasisTreeSource().getParameters() + ". [seed: " + originalSeed + "]";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Randomly Modify Current Tree";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Modifies current tree by random changes.";
+   	 }
+   	 
+}
+
+
+
diff --git a/Source/mesquite/treefarm/RandomResolve/RandomResolve.java b/Source/mesquite/treefarm/RandomResolve/RandomResolve.java
new file mode 100644
index 0000000..5a025db
--- /dev/null
+++ b/Source/mesquite/treefarm/RandomResolve/RandomResolve.java
@@ -0,0 +1,113 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.RandomResolve;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class RandomResolve extends RndTreeModifier {
+	double proportion = 0.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		if (!MesquiteThread.isScripting()){
+    	 	double s = query();
+	 		if (MesquiteDouble.isCombinable(s))
+	 			proportion = s;
+	 		else
+				return false;
+		}
+		addMenuItem("Height Proportion for Polytomy Resolutions...", makeCommand("setProportion",  this));
+  		return true;
+  	 }
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	double query(){
+   	 	double s = MesquiteDouble.queryDouble(containerOfModule(), "Proportion of Height from Polytomy", "How high should resolved branches be moved?  In resolving polytomies, sister branches are joined together.  " +
+	 			" If 0 is entered, then they are joined together such that they retain their full length, and the new ancestral branch is of 0 length.  This effectively is not resolving the polytomy, but may help permit some calculations. "
+	 			+ " If 0.5 is entered, then they are joined together such that the new ancestral branch is half the length of the shorter of the two sister branches, and each sister branch is shortened accordingly to maintain height from root.", proportion, 0.0, 1.0);
+   	 	return s;
+	}
+	/*.................................................................................................................*/
+ 	 public Snapshot getSnapshot(MesquiteFile file) { 
+  	 	Snapshot temp = super.getSnapshot(file);
+ 	 	temp.addLine("setProportion " + proportion);
+ 	 	return temp;
+ 	 }
+	/*.................................................................................................................*/
+   	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Height Proportion for Polytomy Resolutions", "[number]", commandName, "setProportion")) {
+   	 		double s = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+   	 		if (!MesquiteDouble.isCombinable(s)){
+   	 			s = query();
+   	 		}
+   	 		if (MesquiteDouble.isCombinable(s)){
+   	 			proportion = s;
+ 				if (!MesquiteThread.isScripting())
+					parametersChanged(); 
+			}
+   	 	}
+   	 	else
+   	 		return  super.doCommand(commandName, arguments, checker);
+   	 	return null;
+   	 }
+ 	/*.................................................................................................................*/
+	void visitPolytomies(MesquiteTree tree, int node, RandomBetween rng){
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			visitPolytomies(tree, d, rng);
+		while (tree.nodeIsPolytomous(node)){
+			int numDaughters = tree.numberOfDaughtersOfNode(node);
+			int sisterOne = rng.randomIntBetween(0, numDaughters-1);
+			int sisterTwo = rng.randomIntBetween(0, numDaughters-2);
+			if (sisterTwo>=sisterOne)
+				sisterTwo++;
+			int dOne = tree.indexedDaughterOfNode(node, sisterOne);
+			int dTwo = tree.indexedDaughterOfNode(node, sisterTwo);
+			tree.moveBranch(dOne, dTwo, false, true, proportion);  //
+			
+		}
+		
+	}
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng){
+   		if (tree == null || modified == null)
+   			return;
+     	// visit each polytomy.  For each, choose pair of descendants to join.  Do repeatedly until polytomy is resolved
+		visitPolytomies(modified, modified.getRoot(), rng);
+   	}
+	/*.................................................................................................................*/
+  	  public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	  public String getName() {
+		return "Randomly Resolve Polytomies";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Randomly resolves polytomies in tree.  All possible resolutions are equiprobable. Thus, if the tree is a polytomous bush, the resulting resolved trees will be distributed equivalently to that from the Equiprobable Trees module.";
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/treefarm/RandomlyModifiedTrees/RandomlyModifiedTrees.java b/Source/mesquite/treefarm/RandomlyModifiedTrees/RandomlyModifiedTrees.java
new file mode 100644
index 0000000..6de1fba
--- /dev/null
+++ b/Source/mesquite/treefarm/RandomlyModifiedTrees/RandomlyModifiedTrees.java
@@ -0,0 +1,202 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.RandomlyModifiedTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class RandomlyModifiedTrees extends TreeSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(RndTreeModifier.class, getName() + "  needs a method to randomly modify trees.",
+		"The method to randomly modify trees can be selected initially or in the Random Modifier of Tree submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees to modify randomly.",
+		"The source of trees can be selected initially");
+		//e2.setDivertChainMessage("testing");
+	}
+	/*.................................................................................................................*/
+	TreeSource treeSourceTask;
+	RandomBetween rng = new RandomBetween();
+	RndTreeModifier modifierTask;
+	MesquiteString modifierName;
+	MesquiteCommand stC;
+	int currentTree;
+	MesquiteLong seed;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees to be modified");
+ 		if (treeSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of a current tree to serve as a basis for modification was obtained.");
+ 		}
+	 	modifierTask = (RndTreeModifier)hireNamedEmployee(RndTreeModifier.class, arguments);
+		if (modifierTask == null)
+			modifierTask = (RndTreeModifier)hireEmployee(RndTreeModifier.class, "Random modifier of tree");
+ 		if (modifierTask == null) {
+ 			return sorry(getName() + " couldn't start because no random tree modifier was obtained.");
+ 		}
+ 	 	stC = makeCommand("setModifier",  this);
+ 	 	modifierTask.setHiringCommand(stC);
+ 		modifierName = new MesquiteString();
+	   	 modifierName.setValue(modifierTask.getName());
+		if (numModulesAvailable(RndTreeModifier.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Random Modifier of Tree", stC, RndTreeModifier.class);
+ 			mss.setSelected(modifierName);
+  		}
+ 	 	seed = new MesquiteLong(1);
+ 	 	seed.setValue(originalSeed);
+  		addMenuItem("Set Seed (Random tree modification)...", makeCommand("setSeed",  this));
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", treeSourceTask); 
+  	 	temp.addLine("setSeed " + originalSeed);
+  	 	temp.addLine("setModifier ", modifierTask); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of the trees to be modified", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees to be modified", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+    	 			return treeSourceTask;
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the tree modifier", "[name of module]", commandName, "setModifier")) {
+			RndTreeModifier temp = (RndTreeModifier)replaceEmployee(RndTreeModifier.class, arguments, "Random modifier of tree", modifierTask);
+			if (temp !=null){
+				modifierTask = temp;
+    	 			modifierName.setValue(modifierTask.getName());
+		 	 	modifierTask.setHiringCommand(stC);
+				parametersChanged();
+    	 			return modifierTask;
+    	 		}
+    	 	}
+     	 	 else if (checker.compare(this.getClass(), "Sets the random number seed", "[long integer seed]", commandName, "setSeed")) {
+    	 		long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+    	 		if (!MesquiteLong.isCombinable(s)){
+    	 			s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for random modification of tree", originalSeed);
+    	 		}
+    	 		if (MesquiteLong.isCombinable(s)){
+    	 			originalSeed = s;
+ 				parametersChanged(); //?
+ 			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		if (treeSourceTask!=null)
+   			treeSourceTask.initialize(taxa);
+   	}
+	/*.................................................................................................................*/
+	protected Tree getBasisTree(Taxa taxa, int i){
+   		Tree t =  treeSourceTask.getTree(taxa, i);
+ 		return t;
+	}
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int ic) {  
+   		MesquiteTree modified = null;
+   		int code = 0;
+   		try {
+   			code = 1;
+	   		Tree tree = getBasisTree(taxa, ic);
+   			code = 2;
+	   		currentTree = ic;
+   			code = 3;
+	   		if (tree == null)
+	   			return null;
+	   		code = 4;
+	   		rng.setSeed(originalSeed);
+	   		code = 5;
+	   		long rnd = originalSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+	   		code = 6;
+
+	   		for (int it = 0; it<=ic; it++) 
+	   			rnd =  rng.nextInt();
+	   		code = 7;
+	   		rng.setSeed(rnd+1);
+	   		seed.setValue(rnd + 1); //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+	   		code = 8;
+	   		modified =  tree.cloneTree();
+	   		code = 9;
+	   		modifierTask.modifyTree(tree, modified, rng);
+   			code = 10;
+	   		modified.setName("Randomly modified from " + tree.getName() + " (#" + currentTree + ")");
+	   		MesquiteDouble md = new MesquiteDouble(0.2);
+	   		md.setName("test");
+	   		modified.attachIfUniqueName(md);
+	   		
+   		}
+   		catch (Error e){
+   			MesquiteMessage.warnProgrammer("Error " + e + " ===== " + code);
+   		}
+   		return modified;
+   	}
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+ 		if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+ 			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return  treeSourceTask.getNumberOfTrees(taxa);
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		return "Random modification of tree #" +  (itree+1);
+   	}
+	/*.................................................................................................................*/
+   	public String getParameters() {
+   		if (treeSourceTask == null || modifierTask == null)
+   			return "Randomly modifying trees";
+   		return"Randomly modifying trees from: " + treeSourceTask.getParameters() + ". Modifications: " + modifierTask.getParameters() + ". [seed: " + originalSeed + "]";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Randomly Modify Trees";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Modifies each of a series of trees by random changes; the i'th tree from this module comes by modifying the i'th tree from the original source of trees.";
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/RarefyTree/RarefyTree.java b/Source/mesquite/treefarm/RarefyTree/RarefyTree.java
new file mode 100644
index 0000000..068e146
--- /dev/null
+++ b/Source/mesquite/treefarm/RarefyTree/RarefyTree.java
@@ -0,0 +1,138 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.RarefyTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* ======================================================================== */
+public class RarefyTree extends RndTreeModifier {
+	int numExcluded=1;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (!MesquiteThread.isScripting()){
+			int s = MesquiteInteger.queryInteger(containerOfModule(), "Number of taxa to exclude", "Enter the number of randomly chosen taxa to exclude", numExcluded);
+			if (MesquiteInteger.isCombinable(s))
+				numExcluded = s;
+			else
+				return false;
+		}
+		addMenuItem("Number of Taxa Excluded...", makeCommand("setNumberExcluded",  this));
+		return true;
+	}
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setNumberExcluded " + numExcluded);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the number of randomly chosen taxa to exclude", "[number]", commandName, "setNumberExcluded")) {
+			int s = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteInteger.isCombinable(s)){
+				s = MesquiteInteger.queryInteger(containerOfModule(), "Number of taxa to exclude", "Enter the number of randomly chosen taxa to exclude", numExcluded);
+			}
+			if (MesquiteInteger.isCombinable(s)){
+				numExcluded = s;
+				parametersChanged(); 
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng){
+		if (tree == null || modified == null)
+			return;
+		if (tree.getTaxa().anySelected()){  //error fixed in 1. 12
+			int[] terminals =tree.getTerminalTaxa(tree.getRoot());
+			if (terminals == null)
+				return;
+			int numTerminals = 0;
+			for (int i= 0; i< terminals.length; i++)
+				if (tree.getTaxa().getSelected(terminals[i]))
+					numTerminals++;
+			if (numTerminals>numExcluded){
+				int[] selTerminals =new int[numTerminals];
+				int icount = 0;
+				for (int i= 0; i< terminals.length; i++)
+					if (tree.getTaxa().getSelected(terminals[i])){
+						selTerminals[icount] = terminals[i];
+						icount++;
+					}
+				terminals = selTerminals;
+				for (int it = 0; it<numExcluded; it++) {
+					int taxon = -1;
+					int count = 0;
+					int ntries = 100000;
+					while (terminals[taxon=rng.randomIntBetween(0, numTerminals-1)] <0 && count<ntries){  
+						count++;
+					}
+					if (count>= ntries)
+						discreetAlert( "ERROR: Rarefy tree failed to find taxon to delete in " + ntries + " tries.");
+					else {
+						int nT = modified.nodeOfTaxonNumber(terminals[taxon]);
+						modified.deleteClade(nT, false);
+						terminals[taxon] = -1;
+					}
+
+				}
+			}
+			else
+				MesquiteMessage.warnUser("Sorry, the tree could not be rarefied because more taxa are to be excluded than those available");
+		}
+		else {
+			int numTerminals =tree.numberOfTerminalsInClade(tree.getRoot());
+			if (numTerminals>numExcluded){
+				for (int it = 0; it<numExcluded; it++) {
+					int taxon = rng.randomIntBetween(0, numTerminals-it-1);
+					int nT = modified.getTerminalNode(modified.getRoot(), taxon);
+					modified.deleteClade(nT, false);
+				}
+			}
+			else
+				MesquiteMessage.warnUser("Sorry, the tree could not be rarefied because more taxa are to be excluded than those available");
+		}
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		return"Number of taxa excluded randomly: " + numExcluded;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Rarefy Tree";
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Rarefies tree by randomly excluding taxa.  If some taxa are selected, random exclusion is limited to the selected taxa.";
+	}
+
+}
+
diff --git a/Source/mesquite/treefarm/RearrangedTree/RearrangedTree.java b/Source/mesquite/treefarm/RearrangedTree/RearrangedTree.java
new file mode 100644
index 0000000..d19f231
--- /dev/null
+++ b/Source/mesquite/treefarm/RearrangedTree/RearrangedTree.java
@@ -0,0 +1,105 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.RearrangedTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/* TODO: dichotomize tree before giving to swapper, in case swapper can't handle polytomies?  */
+public class RearrangedTree extends DetTreeModifier {
+	public String getName() {
+		return "Rearranged tree";
+	}
+	public String getExplanation() {
+		return "Supplies trees that are rearrangments of a given tree.  The original tree is NOT included among the rearrangements.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSwapper.class, getName() + "  needs a method to rearrange the tree.",
+		"The method to rearrange the tree can be selected initially or in the Branch Rearranger submenu");
+	}
+	int currentTree=0;
+	TreeSwapper swapTask;
+	MesquiteString swapName;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		swapTask = (TreeSwapper)hireEmployee(TreeSwapper.class, "Tree Rearranger");
+		if (swapTask==null)
+			return sorry(getName() + " couldn't start because no tree rearranging module was obtained");
+		stC = makeCommand("setSwapper",  this);
+		swapTask.setHiringCommand(stC);
+		swapName = new MesquiteString();
+		swapName.setValue(swapTask.getName());
+		if (numModulesAvailable(TreeSwapper.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Branch Rearranger", stC, TreeSwapper.class);
+			mss.setSelected(swapName);
+		}
+		return true;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setSwapper ", swapTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the branch swapper", "[name of module]", commandName, "setSwapper")) {
+			TreeSwapper temp = (TreeSwapper)replaceEmployee(TreeSwapper.class, arguments, "Branch Rearranger", swapTask);
+			if (temp !=null){
+				swapTask = temp;
+				swapName.setValue(swapTask.getName());
+				swapTask.setHiringCommand(stC);
+				parametersChanged();
+				return swapTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void modifyTree(Tree original, MesquiteTree modified, int ic){
+		swapTask.rearrange(modified, ic);
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Tree tree) {
+		if (tree == null) 
+			return 0;
+		if (!(tree instanceof AdjustableTree))
+			return 0;
+
+		int i = (int)swapTask.numberOfRearrangements((AdjustableTree)tree);
+		return i;
+	}
+
+
+
+}
+
diff --git a/Source/mesquite/treefarm/ReinterpretBranchLabels/ReinterpretBranchLabels.java b/Source/mesquite/treefarm/ReinterpretBranchLabels/ReinterpretBranchLabels.java
new file mode 100644
index 0000000..8566d0f
--- /dev/null
+++ b/Source/mesquite/treefarm/ReinterpretBranchLabels/ReinterpretBranchLabels.java
@@ -0,0 +1,138 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.ReinterpretBranchLabels;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ReinterpretBranchLabels extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Reinterpret Internal Node Labels...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Reinterprets labels from all internal nodes as numbers or text attached to nodes or branches." ;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+	boolean appliesToBranch = true;
+	boolean isNumber = true;
+	boolean deleteAfter = true;
+	NameReference nameRef = null;
+	String name = "";
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (!showOptions())
+			return false;
+		return true;
+	}
+	boolean showOptions(){
+
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Reinterpret Node Labels",  buttonPressed);
+		queryDialog.addLargeOrSmallTextLabel("Some programs write information as node labels; e.g. MrBayes writes posterior probabilities as if they were the names of clades (= node labels)." +
+		"\nHere you can reintepret such information.");
+		//name for information (e.g., "posteriorProbability", "bootstrapFrequency")
+		queryDialog.addLabel("Name for information? (e.g., \"posteriorProbability\", \"bootstrapFrequency\")", Label.LEFT);
+		TextField nameField = queryDialog.addTextField(name, 30);
+
+		queryDialog.addHorizontalLine(2);
+
+		//where to attach
+		queryDialog.addLabel("Applies to branch or node?", Label.LEFT);
+		String[] where  = new String[] {"Information applies to branch (e.g., posterior probability, bootstrap frequency)", "Information applies to node (e.g., clade name)"};
+		RadioButtons whereButtons = queryDialog.addRadioButtons (where, 0);
+		queryDialog.addLabel("(This determines how the information will behave when the tree is rerooted.)", Label.LEFT);
+		queryDialog.addHorizontalLine(2);
+
+		//how to treat
+		queryDialog.addLabel("Number or text?", Label.LEFT);
+		String[] what  = new String[] {"Treat as number (e.g., posterior probability)", "Treat as text (e.g., clade name)"};
+		RadioButtons whatButtons = queryDialog.addRadioButtons (what, 0);
+		queryDialog.addHorizontalLine(2);
+
+		//delete internal node labels after reinterpreting?
+		Checkbox delete = queryDialog.addCheckBox ("Delete internal node labels after reinterpreting?", deleteAfter);
+		queryDialog.addHorizontalLine(2);
+
+
+		queryDialog.completeAndShowDialog(true);
+
+		boolean ok = (queryDialog.query()==0);
+
+		if (ok) {
+			if (StringUtil.blank(nameField.getText())){
+				ok = false;
+				alert("A name must be entered for the information");
+			}
+			else {
+				name = nameField.getText();
+				nameRef = NameReference.getNameReference(name);
+				appliesToBranch = whereButtons.getValue() == 0;
+				isNumber = whatButtons.getValue() == 0;
+				deleteAfter = delete.getState();
+			}
+		}
+
+		queryDialog.dispose();
+		return ok;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+
+	void reinterpret(MesquiteTree tree, int node){
+		if (tree.nodeIsInternal(node)){
+			if (tree.nodeHasLabel(node)){
+				String label = tree.getNodeLabel(node);
+				if (isNumber){
+					double d = MesquiteDouble.fromString(label);
+					if (MesquiteDouble.isCombinable(d))
+						tree.setAssociatedDouble(nameRef, node, d, appliesToBranch);
+				}
+				else {
+					tree.setAssociatedObject(nameRef, node, label, appliesToBranch);
+				}
+				if (deleteAfter)
+					tree.setNodeLabel(null, node);
+			}
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				reinterpret(tree, daughter);
+			}
+		}
+
+	}
+
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (!(tree instanceof MesquiteTree))
+			return false;
+		reinterpret((MesquiteTree)tree, tree.getRoot());
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/RemoveAllBranchLabels/RemoveAllBranchLabels.java b/Source/mesquite/treefarm/RemoveAllBranchLabels/RemoveAllBranchLabels.java
new file mode 100644
index 0000000..96f6779
--- /dev/null
+++ b/Source/mesquite/treefarm/RemoveAllBranchLabels/RemoveAllBranchLabels.java
@@ -0,0 +1,66 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.RemoveAllBranchLabels;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class RemoveAllBranchLabels extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+
+	void zap(AdjustableTree tree, int node){
+		if (tree.nodeIsInternal(node)){
+			if (tree.nodeHasLabel(node))
+				tree.setNodeLabel(null, node);
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				zap(tree, daughter);
+			}
+		}
+
+	}
+
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		zap(tree, tree.getRoot());
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Remove Internal Node Labels";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Deletes labels from all internal nodes." ;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/ReshuffleTaxa/ReshuffleTaxa.java b/Source/mesquite/treefarm/ReshuffleTaxa/ReshuffleTaxa.java
new file mode 100644
index 0000000..1cea522
--- /dev/null
+++ b/Source/mesquite/treefarm/ReshuffleTaxa/ReshuffleTaxa.java
@@ -0,0 +1,74 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.ReshuffleTaxa;
+/*~~ */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+
+/* This module shuffles (permutes) the terminal taxa of the tree.  Because it doesn't
+   need any values from the user, its interface is pretty simple. */
+/* ======================================================================== */
+
+public class ReshuffleTaxa extends RndTreeModifier {
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng){
+   		if (tree == null || modified == null)
+   			return;
+		int[] terminals = tree.getTerminalTaxa(tree.getRoot());
+		int numTerminals =tree.numberOfTerminalsInClade(tree.getRoot());
+		int taxon  = 0;
+		for (int fT = 0; fT < numTerminals-1; fT++) {
+			int firstTerminal = terminals[fT];
+			int secondTerminal = terminals[rng.randomIntBetween(fT,numTerminals-1)];
+			
+		    	int firstTaxonNode = modified.nodeOfTaxonNumber(firstTerminal);
+			int secondTaxonNode = modified.nodeOfTaxonNumber(secondTerminal);
+			modified.setTaxonNumber(secondTaxonNode,firstTerminal,false);
+			modified.setTaxonNumber(firstTaxonNode,secondTerminal,false);
+		
+		}
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Reshuffle Terminal Taxa";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Shuffles (permutes) the taxa among the terminal nodes.";
+   	 }
+   	 
+}
+
+
+
+
+
diff --git a/Source/mesquite/treefarm/SharedClades2Trees/SharedClades2Trees.java b/Source/mesquite/treefarm/SharedClades2Trees/SharedClades2Trees.java
new file mode 100644
index 0000000..3661b44
--- /dev/null
+++ b/Source/mesquite/treefarm/SharedClades2Trees/SharedClades2Trees.java
@@ -0,0 +1,101 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.SharedClades2Trees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class SharedClades2Trees extends DistanceBetween2Trees {
+	StringArray terminalsAbove, terminalsBelow, otherTerminalsAbove, otherTerminalsBelow;
+	boolean isDistance = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		isDistance = (getHiredAs() == DistanceBetween2Trees.class);
+ 		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	public boolean largerIsFurther(){  
+		return false;
+	}
+  	 private void visitOriginal(Tree tree,int node,  Tree otherTree, MesquiteInteger numConsistent){
+		if (tree.nodeIsInternal(node)){
+			Bits b = tree.getTerminalTaxaAsBits(node);
+			if (otherTree.isClade(b))
+				numConsistent.increment();
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginal(tree, daughter, otherTree, numConsistent);
+			
+		}
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree t1, Tree t2) {
+	
+	}
+	
+	MesquiteTree tree1eq, tree2eq;
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree1 == null)
+			return;
+		if (tree2 == null)
+			return;
+
+		MesquiteInteger numCon = new MesquiteInteger(0);
+		visitOriginal(tree1, tree1.getRoot(), tree2, numCon);
+		if (tree1.getTerminalTaxaAsBits(tree1.getRoot()).equals(tree2.getTerminalTaxaAsBits(tree2.getRoot())))
+			numCon.decrement();
+		int numC = numCon.getValue();
+		result.setValue(numC);
+		if (resultString!=null) {
+			resultString.setValue("Shared Clades: "+ result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	 
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		return "Shared Clades";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Shared Clades";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the number of shared clades between two trees (excludes the clade consisting of all taxa).";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/SharedPartitions2Trees/SharedPartitions2Trees.java b/Source/mesquite/treefarm/SharedPartitions2Trees/SharedPartitions2Trees.java
new file mode 100644
index 0000000..8e88d76
--- /dev/null
+++ b/Source/mesquite/treefarm/SharedPartitions2Trees/SharedPartitions2Trees.java
@@ -0,0 +1,246 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.SharedPartitions2Trees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+
+/* ======================================================================== */
+public class SharedPartitions2Trees extends DistanceBetween2Trees {
+	StringArray terminalsAbove, terminalsBelow, otherTerminalsAbove, otherTerminalsBelow;
+	boolean isDistance = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		isDistance = (getHiredAs() == DistanceBetween2Trees.class);
+ 		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	public boolean largerIsFurther(){  
+		return false;
+	}
+	/*.................................................................................................................*/
+  	 private boolean arraysMatch(StringArray one, StringArray two){
+   	 	return arrayIsSubset(one, two) && arrayIsSubset(two, one);
+ 	 }
+	/*.................................................................................................................*/
+  	 private boolean arrayIsSubset(StringArray one, StringArray two){
+  	 	if (one==null || two == null)
+  	 		return false;
+  	 	for (int i=0; i<one.getSize(); i++){
+  	 		if (one.getValue(i)!=null && two.indexOf(one.getValue(i))<0)
+  	 			return false;
+  	 	}
+  	 	return true;
+  	 }
+	/*.................................................................................................................*/
+  	 private void accumulateTerminals(Tree tree,int node, int target, boolean aboveTarget, StringArray terminalsAbove, StringArray terminalsBelow){
+		if (tree.nodeIsTerminal(node)){
+			if (aboveTarget)
+				terminalsAbove.fillNextUnassigned(tree.getTaxa().getTaxonName(tree.taxonNumberOfNode(node)));
+			else
+				terminalsBelow.fillNextUnassigned(tree.getTaxa().getTaxonName(tree.taxonNumberOfNode(node)));
+			
+		}
+		else for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				accumulateTerminals(tree, daughter, target, (node==target || aboveTarget), terminalsAbove, terminalsBelow);
+  	 }
+	/*.................................................................................................................*/
+  	 /* Returns true if partitions are consistent (same taxa in each subset in each tree, or group in tree1 is subset of
+  	 group in tree 2 AND other group in 1 is subset of other group in 2*/
+  	 private boolean partitionsConsistent(Tree tree, int node, Tree otherTree, int otherNode){
+		terminalsAbove.deassignArray();
+		terminalsBelow.deassignArray();
+		otherTerminalsAbove.deassignArray();
+		otherTerminalsBelow.deassignArray();
+		// first, load arrays with node numbers in taxa on either side of partition defined by above and below node
+		accumulateTerminals(tree, tree.getRoot(), node, false, terminalsAbove, terminalsBelow);
+		accumulateTerminals(otherTree, otherTree.getRoot(), otherNode, false, otherTerminalsAbove, otherTerminalsBelow);
+		
+		// Next, compare arrays to see that same
+		if (arraysMatch(terminalsAbove, otherTerminalsAbove)){
+			return (arraysMatch(terminalsBelow, otherTerminalsBelow)|| arrayIsSubset(terminalsBelow, otherTerminalsBelow) || arrayIsSubset(otherTerminalsBelow, terminalsBelow));
+		}
+		else if (arraysMatch(terminalsBelow, otherTerminalsBelow)){
+			return (arrayIsSubset(terminalsAbove, otherTerminalsAbove) || arrayIsSubset(otherTerminalsAbove, terminalsAbove));
+		}
+		else if (arraysMatch(terminalsAbove, otherTerminalsBelow)){
+			return (arraysMatch(terminalsBelow, otherTerminalsAbove)|| arrayIsSubset(terminalsBelow, otherTerminalsAbove) || arrayIsSubset(otherTerminalsAbove, terminalsBelow));
+		}
+		else if (arraysMatch(terminalsBelow, otherTerminalsAbove)){
+			return (arraysMatch(terminalsAbove, otherTerminalsBelow)|| arrayIsSubset(terminalsAbove, otherTerminalsBelow) || arrayIsSubset(otherTerminalsBelow, terminalsAbove));
+		}
+		else if (arrayIsSubset(terminalsAbove, otherTerminalsAbove)){
+			return (arrayIsSubset(terminalsBelow, otherTerminalsBelow));
+		}
+		else if (arrayIsSubset(otherTerminalsAbove, terminalsAbove)){
+			return (arrayIsSubset(otherTerminalsBelow, terminalsBelow));
+		}
+		else
+			return false;
+  	 }
+  	 
+  	 
+	/*.................................................................................................................*/
+  	 private boolean consistentPartitionFound(Tree tree,int node,  Tree otherTree, int otherNode){
+		if (otherTree.nodeIsInternal(otherNode)){
+			if (otherNode != otherTree.getRoot() && partitionsConsistent(tree, node, otherTree, otherNode)) {
+				return true;
+			}
+			
+			boolean found = false;
+			for (int daughter = otherTree.firstDaughterOfNode(otherNode); otherTree.nodeExists(daughter) && !found; daughter = otherTree.nextSisterOfNode(daughter)) {
+				found = consistentPartitionFound(tree, node, otherTree, daughter);
+				if (found)
+					return true;
+			}
+			
+		}
+		return false;
+  	 }
+  	 private void visitOriginal(Tree tree,int node,  Tree otherTree, MesquiteInteger numConsistent){
+		if (tree.nodeIsInternal(node)){
+			boolean count = (node != tree.getRoot() && tree.numberOfDaughtersOfNode(tree.motherOfNode(node))!=1);
+			boolean dichotDescOfRoot =tree.motherOfNode(node)==tree.getRoot() &&  !tree.nodeIsPolytomous(tree.getRoot());
+			if (dichotDescOfRoot) {
+				count = count && !(tree.nodeIsFirstDaughter(node));
+				int sis = tree.nextSisterOfNode(node);
+				if (!tree.nodeExists(sis))
+					sis = tree.previousSisterOfNode(node);
+				count = count && !tree.nodeIsTerminal(sis);
+			}
+			if (count && consistentPartitionFound(tree, node, otherTree, otherTree.getRoot()))
+				numConsistent.increment();
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+				visitOriginal(tree, daughter, otherTree, numConsistent);
+			
+		}
+  	 }
+  	 
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree t1, Tree t2) {
+	
+	}
+	
+	MesquiteTree tree1eq, tree2eq;
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		if (tree1 == null)
+			return;
+		if (tree2 == null)
+			return;
+			
+		Tree use1, use2;
+		int numTaxa1 = tree1.getTaxa().getNumTaxa();
+		int numTaxa2 = tree2.getTaxa().getNumTaxa();
+		
+		if (numTaxa1==numTaxa2 && numTaxa1 == tree1.numberOfTerminalsInClade(tree1.getRoot()) && numTaxa2 == tree2.numberOfTerminalsInClade(tree2.getRoot())){ //trees have full set of taxa)
+			use1 = tree1;
+			use2 = tree2;
+		}
+		else {  //this section added 1.02, April 2004 because was miscounting partitions if two trees had different terminals included
+			if (tree1eq == null || tree1eq.getTaxa()!= tree1.getTaxa())
+				tree1eq = new MesquiteTree(tree1.getTaxa());
+			tree1eq.setToCloneFormOnly(tree1);
+			if (tree2eq == null || tree2eq.getTaxa()!= tree2.getTaxa())
+				tree2eq = new MesquiteTree(tree2.getTaxa());
+			tree2eq.setToCloneFormOnly(tree2);
+			
+			int[] termsIn1 = tree1eq.getTerminalTaxa(tree1eq.getRoot());
+		
+			int[] termsIn2  = tree2eq.getTerminalTaxa(tree2eq.getRoot());
+			for (int i=0; i<termsIn2.length; i++)
+				if (IntegerArray.indexOf(termsIn1, termsIn2[i])<0) //terminal in 2 not found in 1; delete it from tree 2
+					tree2eq.deleteClade(tree2eq.nodeOfTaxonNumber(termsIn2[i]), false);
+			
+			for (int i=0; i<termsIn1.length; i++)
+				if (IntegerArray.indexOf(termsIn2, termsIn1[i])<0) //terminal in 1 not found in 2; delete it from tree 1
+					tree1eq.deleteClade(tree1eq.nodeOfTaxonNumber(termsIn1[i]), false);
+			//CHECK THAT BOTH TREES STILL EXIST
+			use1 = tree1eq;
+			use2 = tree2eq;
+		}
+		
+		int numTerms = MesquiteInteger.maximum(use1.getTaxa().getNumTaxa(), use2.getTaxa().getNumTaxa());
+		if (terminalsAbove==null || numTerms > terminalsAbove.getSize()) {
+			terminalsAbove = new StringArray(numTerms);
+			terminalsBelow = new StringArray(numTerms);
+			otherTerminalsAbove = new StringArray(numTerms);
+			otherTerminalsBelow = new StringArray(numTerms);
+		}
+		
+		
+		MesquiteInteger numCon = new MesquiteInteger(0);
+		visitOriginal(use1, use1.getRoot(), use2, numCon);
+		int numC = numCon.getValue();
+		if (isDistance) {
+			int numInt1 = use1.numberOfInternalsInClade(use1.getRoot());
+			if (!use1.nodeIsPolytomous(use1.getRoot()))
+				numInt1--;
+			int numInt2 = use2.numberOfInternalsInClade(use2.getRoot());
+			if (!use2.nodeIsPolytomous(use2.getRoot()))
+				numInt2--;
+			int maxPart = MesquiteInteger.maximum(numInt1, numInt2);
+			numC = maxPart-1 - numC;  //to convert to a distance
+		}
+		result.setValue(numC);
+		if (resultString!=null) {
+			if (isDistance)
+				resultString.setValue("Shared Partitions (converted to distance): "+ result.toString());
+			else
+				resultString.setValue("Shared Partitions: "+ result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	 
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		if (isDistance)
+			return "Shared Partitions converted to distance (Max. possible - observed)";
+		else
+			return "Shared Partitions in natural form (i.e., not converted to distance, but instead indicating number of partitions shared between trees)";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Shared Partitions";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getAuthors() {
+		return "W. P. Maddison (slightly adjusted by J. Klingner)";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the number of shared partitions between two trees.  If used as a distance, then converted by subtracting shared partitions from the maximum possible, i.e. the number of partitions in the subtree of shared taxa in the tree with the most partitions.";
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/SortTaxaByTree/SortTaxaByTree.java b/Source/mesquite/treefarm/SortTaxaByTree/SortTaxaByTree.java
new file mode 100644
index 0000000..01a3488
--- /dev/null
+++ b/Source/mesquite/treefarm/SortTaxaByTree/SortTaxaByTree.java
@@ -0,0 +1,86 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.SortTaxaByTree;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+import java.net.*;
+
+/** ======================================================================== */
+
+public class SortTaxaByTree extends TreeUtility {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  
+ 	}
+ 	
+	public  void useTree(Tree treeT) {
+		MesquiteTree tree = (MesquiteTree)treeT;
+		if (tree == null)
+			return;
+		Taxa taxa = tree.getTaxa();
+		UndoInstructions undoInstructions = new UndoInstructions(UndoInstructions.PARTS_MOVED, taxa);
+		undoInstructions.recordPreviousOrder(taxa);
+		UndoReference undoReference = new UndoReference(undoInstructions, this);
+		MesquiteInteger target = new MesquiteInteger();
+		MesquiteInteger count = new MesquiteInteger(0);
+		int numTaxa = taxa.getNumTaxa();
+		for (int k = 0; k<numTaxa; k++){
+			target.setValue(k);
+			count.setValue(0);
+			moveOne(tree, tree.getRoot(), taxa, target, count);
+			tree.reconcileTaxa(MesquiteListener.PARTS_MOVED, null, false);
+		}
+		taxa.notifyListeners(this, new Notification(MesquiteListener.PARTS_MOVED, undoReference));
+	}
+	
+	
+	/** These two methods adjust the vertical positions relative to the leftmost terminal taxon.*/
+	void moveOne (Tree tree, int node, Taxa taxa, MesquiteInteger target, MesquiteInteger count){
+		if (target.getValue()<0)
+			return;
+		if (tree.nodeIsTerminal(node)){
+			int taxon = tree.taxonNumberOfNode(node);
+			if (count.getValue() == target.getValue()) {
+				taxa.moveTaxa(taxon, 1, target.getValue()-1, false);
+				target.setValue(-1);
+				return;
+			}
+			count.increment();
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d) && target.getValue()>=0; d = tree.nextSisterOfNode(d))
+				moveOne(tree, d, taxa, target, count);
+		}
+	}
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Reorder Taxa By Tree";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Reorders taxa to match the order in the tree.";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/treefarm/SplitFrequencies/SplitFrequencies.java b/Source/mesquite/treefarm/SplitFrequencies/SplitFrequencies.java
new file mode 100644
index 0000000..347ca3f
--- /dev/null
+++ b/Source/mesquite/treefarm/SplitFrequencies/SplitFrequencies.java
@@ -0,0 +1,270 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.SplitFrequencies;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.consensus.lib.Bipartition;
+import mesquite.consensus.lib.BipartitionVector;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class SplitFrequencies extends NumbersForNodes {
+	Tree otherTree = null;
+	TreeSource treeSourceTask;
+	MesquiteString treeSourceName;
+	MesquiteCommand tstC;
+	Taxa taxa;
+	boolean suspend = false;
+	int startingTree = 0;
+	int sampleSize = MesquiteInteger.unassigned;
+	MesquiteBoolean useWeights = new MesquiteBoolean(true);
+
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + " needs a source of trees whose split frequencies will be assessed.",
+				"The source of other trees can be indicated initially or later under the Tree Source submenu.");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+
+		addCheckMenuItem(null, "Consider Tree Weights", makeCommand("toggleUseWeights", this), useWeights);
+		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Tree Source");
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		tstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(tstC);
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+		return true;
+	}
+
+	public boolean getDefaultShowLabels() {
+		return true;
+	}
+	public boolean getDefaultShadeBranches() {
+		return false;
+	}
+	public boolean getDefaultShadeInColor() {
+		return false;
+	}
+	public boolean getDefaultLabelTerminals() {
+		return false;
+	}
+
+
+	/*.................................................................................................................*/
+	public void setUseWeights(boolean useWeights){
+		this.useWeights.setValue(useWeights);
+	}
+	/*.................................................................................................................*/
+	public boolean getUseWeights(){
+		return useWeights.getValue();
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("suspend");
+		temp.addLine("setTreeSource",treeSourceTask);
+		temp.addLine("resume");
+  	 	temp.addLine("toggleUseWeights " + useWeights.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module supplying tree blocks", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees", treeSourceTask);
+			if (temp!=null) {
+				treeSourceTask = temp;
+				startingTree = 0;
+				treeSourceTask.setHiringCommand(tstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				parametersChanged();
+			}
+			return temp;
+		}
+		else if (checker.compare(this.getClass(), "Returns treeSourceTask", null, commandName, "getTreeSource")) 
+			return treeSourceTask;
+		else if (checker.compare(this.getClass(), "Returns treeSourceTask", null, commandName, "toggleUseWeights")) {
+	 		useWeights.toggleValue(parser.getFirstToken(arguments));  
+	 		parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Suspends calculations", null, commandName, "suspend")) {
+			suspend = true;
+		}
+		else if (checker.compare(this.getClass(), "Resumes calculations", null, commandName, "resume")) {
+			suspend = false;
+			parametersChanged();
+		}
+		else 
+			super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's initialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree ==null)
+			return;
+		Taxa taxa = tree.getTaxa();
+		if (this.taxa!=taxa) {
+			this.taxa = taxa;
+		}
+		if (treeSourceTask!=null)
+			treeSourceTask.initialize(tree.getTaxa());
+	}
+	/*.................................................................................................................*/
+	public void setStartingTree(int startingTree) {
+		this.startingTree = startingTree;
+	}
+	/*.................................................................................................................*/
+	public void setSampleSize(int sampleSize) {
+		this.sampleSize = sampleSize;
+	}
+	/*.................................................................................................................*/
+	public int getNumTrees(Tree tree) {
+		if (treeSourceTask==null)
+			return 0;
+		if (taxa!=tree.getTaxa()) {
+			taxa = tree.getTaxa();
+			treeSourceTask.initialize(taxa);
+		}
+		return treeSourceTask.getNumberOfTrees(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initBipartitionVector(Taxa taxa, BipartitionVector bipartitions){
+		if (bipartitions!=null) {
+			bipartitions.setMode(BipartitionVector.MATCHMODE);
+			bipartitions.setTaxa(taxa);
+			bipartitions.zeroFrequencies();
+		}
+	}
+	/*.................................................................................................................*/
+	public   void harvestResults(int node, Tree tree, BipartitionVector bipartitions, NumberArray result) {
+		if (tree.nodeIsInternal(node)){
+			Bipartition bp = Bipartition.getBipartitionFromNode(tree, node);
+			double freq = bipartitions.getDecimalFrequencyOfNode(tree, node, true);
+			result.setValue(node, freq);
+		} else
+			result.setValue(node, 0.0);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) 
+			harvestResults(d, tree, bipartitions, result);
+	}
+	public void addTree(BipartitionVector bipartitions, Tree t){
+		if (t==null)
+			return;
+		if (useWeights.getValue()) {
+			bipartitions.setUseWeights(useWeights.getValue());
+			MesquiteDouble md = (MesquiteDouble)((Attachable)t).getAttachment(TreesManager.WEIGHT);
+			if (md != null) {
+				if (md.isCombinable())
+					bipartitions.setWeight(md.getValue());
+				else
+					bipartitions.setWeight(1.0);
+			} else
+				bipartitions.setWeight(1.0);
+
+		}
+		bipartitions.addTree(t);
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (resultString!=null)
+			resultString.setValue("");
+		if (tree == null || treeSourceTask==null)
+			return;
+		if (taxa!=tree.getTaxa()) {
+			taxa = tree.getTaxa();
+			treeSourceTask.initialize(taxa);
+		}
+		Tree otherTree;
+		BipartitionVector bipartitions = BipartitionVector.getBipartitionVector(tree);  //start the bipartition vector with all the bipartitions in the tree;
+			
+		initBipartitionVector(taxa, bipartitions);
+		bipartitions.setRooted(false);
+
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		startingTree = 0;
+		if (MesquiteInteger.isCombinable(sampleSize)) {
+			startingTree = numTrees - sampleSize;
+			if (startingTree<0)
+				startingTree = 0;
+		} 
+		boolean done=false;
+		int count = 0;
+		
+		if (numTrees>0 && startingTree <numTrees) {	
+			for (int iTree = startingTree; iTree<numTrees && !done; iTree++){
+				otherTree = treeSourceTask.getTree(taxa,iTree); 
+				if (otherTree!=null) {
+					addTree(bipartitions, otherTree);   //now just adjust bipartitions in the vector if they are present in this otherTree
+					count++;
+				} else
+					done = true;
+			}
+			harvestResults(tree.getRoot(), tree, bipartitions, result);
+		}
+		logln("Number of trees examined: " + count);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (treeSourceTask ==null)
+			return null;
+		return "Tree Source: " + treeSourceTask.getTreesDescriptiveString(taxa); 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (treeSourceTask ==null)
+			return getName();
+		return getName()+", Tree Source: " +  treeSourceTask.getTreesDescriptiveString(taxa); 
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	public String getExplanation() {
+		return "Calculates, for each clade in the tree, the frequency of that split among the trees in a specified tree source.";
+	}
+	public String getName() {
+		return "Clade Frequencies in Trees";
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 300;  
+	}
+}
diff --git a/Source/mesquite/treefarm/TaxonValueFromTree/TaxonValueFromTree.java b/Source/mesquite/treefarm/TaxonValueFromTree/TaxonValueFromTree.java
new file mode 100644
index 0000000..0438f34
--- /dev/null
+++ b/Source/mesquite/treefarm/TaxonValueFromTree/TaxonValueFromTree.java
@@ -0,0 +1,222 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.TaxonValueFromTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/** ======================================================================== */
+/*
+provides a superclass for NumberForTaxon that use a tree;
+*/
+
+public class TaxonValueFromTree extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a current tree.",
+		"The source of a current tree is arranged initially");
+		EmployeeNeed e2 = registerEmployeeNeed(NForTaxonWithTree.class, getName() + "  needs a method to calculate values for taxa based on a tree.",
+		"The method to calculate values for taxa can be chosen initially or in the Values for Taxa Using Tree submenu");
+	}
+	protected boolean needsRecalculation = true;
+	protected Taxa currentTaxa;
+	MesquiteString treeSourceName;
+	MesquiteCommand cstC;
+	OneTreeSource treeSourceTask;
+	NumberArray results;
+	MesquiteString resultsString;
+	protected NForTaxonWithTree numberTask;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	MesquiteSubmenuSpec mss;
+	public Class getNumberTaskClass(){
+		return NForTaxonWithTree.class;
+	}
+	public String getHiringString(){
+		return "Value for taxa using tree";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		ntC =makeCommand("setNumberTask",  this);
+		numberTaskName = new MesquiteString();
+		if (numberTask == null)
+			numberTask = (NForTaxonWithTree)hireEmployee(getNumberTaskClass(), getHiringString());//shouldn't ask as this is an init and might not be needed.  "Value to calculate for character state in taxon"
+
+		if (numberTask != null){
+			numberTask.setHiringCommand(ntC);
+			numberTaskName.setValue(numberTask.getName());
+		}
+		else 
+			return false;
+		if (numModulesAvailable(getNumberTaskClass())>0) {
+			mss = addSubmenu(null, getHiringString(), ntC, getNumberTaskClass());
+			mss.setSelected(numberTaskName);
+			//mss.setEnabled(false);
+		}
+		treeSourceTask = (OneTreeSource)hireEmployee(OneTreeSource.class,  "Source of tree for " + getName());
+ 		if (treeSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of tree obtained");
+ 		}
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		
+
+		cstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(TreeSource.class)>1){ 
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree source",cstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+
+		results = new NumberArray(1);
+		resultsString = new MesquiteString();
+		needsRecalculation = MesquiteThread.isScripting();
+		return true;  
+ 	}
+ 	
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+ 	public void employeeQuit(MesquiteModule m){
+ 		if (m!=treeSourceTask)
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+	 	//if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED) {
+				needsRecalculation = true;
+				super.employeeParametersChanged(employee, source, notification);
+		//	}
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource " , treeSourceTask);
+		temp.addLine("setNumberTask ", numberTask);  
+  	 	temp.addLine("doCalc");
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    			if (checker.compare(this.getClass(), "Sets the module that calculates numbers using a tree", "[name of module]", commandName, "setNumberTask")) {
+    				NForTaxonWithTree temp =  (NForTaxonWithTree)replaceEmployee(getNumberTaskClass(), arguments, "Module to calculate numbers using a tree", numberTask);
+    				if (temp!=null) {
+    					numberTask = temp;
+    					numberTask.setHiringCommand(ntC);
+    					numberTaskName.setValue(numberTask.getName());
+    					needsRecalculation = true;
+    					parametersChanged();
+    					return numberTask;
+    				}
+    			}
+    			else if (checker.compare(this.getClass(), "Sets the source of trees for taxon value", "[name of module]", commandName, "setTreeSource")) {
+    	 		OneTreeSource temp =  (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of trees", treeSourceTask);
+ 			if (temp!=null) {
+	    	 		treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(cstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				treeSourceTask.initialize(currentTaxa);
+				
+				if (!MesquiteThread.isScripting()) {
+					needsRecalculation = true;
+					parametersChanged();
+				}
+ 			}
+ 			return temp;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Requests calculations", null, commandName, "doCalc")) {
+			needsRecalculation = true;
+			parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+ 	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		currentTaxa = taxa;
+   		needsRecalculation = true;
+   		treeSourceTask.initialize(currentTaxa);
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null|| taxon == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxon.getTaxa()!= currentTaxa) {
+			initialize(taxon.getTaxa());
+			needsRecalculation = true;
+		}
+		if (needsRecalculation)
+			doCalcs();
+		int it = currentTaxa.whichTaxonNumber(taxon);
+		results.placeValue(it, result);
+		
+		if (resultString !=null) {
+			resultString.setValue(resultsString.getValue());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		needsRecalculation = false;
+		int numTaxa = currentTaxa.getNumTaxa();
+		results.resetSize(numTaxa);
+		results.zeroArray();
+		Tree tree = treeSourceTask.getTree(currentTaxa);
+		if (resultsString != null)
+			resultsString.setValue(numberTask.getName());
+		
+		numberTask.calculateNumbers(currentTaxa,  tree, results,  resultsString);
+	}
+	/*.................................................................................................................*/
+	/** Explains what the module does.*/
+	 public String getExplanation() {
+	return "Calculates a value for each taxon using a tree.";
+	 }
+	 
+/** Returns the name of the module in very short form, for use for column headings and other constrained places.*/
+public String getVeryShortName(){
+	if (numberTask != null)
+		return numberTask.getVeryShortName();
+	return "Value with tree";
+}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+/** Name of module*/
+	 public String getName() {
+	return "Value from Tree";
+	 }
+		/*.................................................................................................................*/
+		/** returns the name of character ic*/
+		public String getNameAndParameters(){
+			if (numberTask != null)
+				return numberTask.getNameAndParameters();
+		return  getName();
+		}
+
+}
+
+
diff --git a/Source/mesquite/treefarm/TerminalInstability/TerminalInstability.java b/Source/mesquite/treefarm/TerminalInstability/TerminalInstability.java
new file mode 100644
index 0000000..88e33f1
--- /dev/null
+++ b/Source/mesquite/treefarm/TerminalInstability/TerminalInstability.java
@@ -0,0 +1,241 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.TerminalInstability;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/** ======================================================================== */
+/*
+Terminal instability -- the difference in the position of a particular target taxon is measured by the 
+sum of the weighted differences between the trees in path lengths between that taxon and each of the other taxa.  
+The path length between taxa is the number of nodes intervening on the path between the one taxon and the other 
+(branch lengths not considered, hence scaling not yet needed). 
+Thus if on tree 1 the path length between the target taxon and another taxon i is pti1 and the length on tree 2 is pti2, 
+then the weighted difference is Math.abs(pti1 - pti2)/sqr(pti1 + pti2).  The weighting by sqr(pti1 + pti2) 
+means that the emphasis on another taxon i fades away as it is farther from the target taxon in on or the other tree.  
+This weighted difference is summed over all other taxa i to get the difference in the target taxon's position in the two trees.
+
+*/
+
+public class TerminalInstability extends NForTaxonWithTrees {
+	double exponent = 2.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem("Exponent for Instability...", makeCommand("setExponent", this));
+		return true;  
+ 	}
+ 	
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setExponent " + exponent);
+  	 	temp.incorporate(super.getSnapshot(file), false);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the exponent used in the denominator of the instability calculations", "[number]", commandName, "setExponent")) {
+			pos.setValue(0);
+			double newNum= MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(newNum))
+				newNum = MesquiteDouble.queryDouble(containerOfModule(), "Set exponent", "Enter the exponent used in the denominatory of the instability calculations.  Default is 2.  Larger exponents emphasize near neighbors more strongly relative to distant taxa.", exponent, 0.9999, 4);
+    	 		if (newNum>0  && newNum!=exponent) {
+    	 			exponent = newNum;
+				if (!MesquiteThread.isScripting()) {
+					needsRecalculation = true;
+					parametersChanged();
+				}
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+	/*.................................................................................................................*/
+	public void calculateNumbers(Taxa taxa, NumberArray results, MesquiteString resultsString){
+		if (results==null|| taxa == null)
+			return;
+		int numTaxa = taxa.getNumTaxa();
+		results.resetSize(numTaxa);
+	   	clearResultAndLastResult(results);
+		results.zeroArray();
+		
+		int numTrees = getNumTrees(taxa);
+		
+		MesquiteInteger minDiscord = new MesquiteInteger();
+		MesquiteNumber b = new MesquiteNumber();
+		double[][] originalDistances = new double[numTaxa][numTaxa];
+		double[][] comparisonDistances = new double[numTaxa][numTaxa];
+		double[][] heights = new double[MesquiteTree.standardNumNodeSpaces(numTaxa)][numTaxa];
+
+		int numComparisons = numTrees*(numTrees-1)/2;
+		ProgressIndicator progIndicator = null;
+		if (numTrees>10){
+			progIndicator = new ProgressIndicator(getProject(),getName(), "Calculating Terminal Instability by comparing to other trees", numComparisons, true);
+			progIndicator.start();
+		}
+		int num = 0;
+		PatristicDistances pdistTarget = new PatristicDistances();
+		PatristicDistances pdistCompare = new PatristicDistances();
+		
+		for (int it = 0; it< numTrees  && (progIndicator==null || !progIndicator.isAborted()); it++){ //get tree for comparison
+				Tree targetTree = getTree(taxa, it);
+				if (targetTree != null) {
+					
+					if (heights == null || heights.length < targetTree.getNumNodeSpaces())
+						heights = new double[targetTree.getNumNodeSpaces()][numTaxa];
+					//calculatePatristic(targetTree, taxa, originalDistances); //for this tree calculate patristic distances (number of nodes separating terminals; no branch lengths)
+					if (progIndicator !=null) {
+						progIndicator.setCurrentValue(num);
+						progIndicator.setText("Comparing tree " + (it+1) + " (of " + numTrees + ") to other trees");
+					}
+					CommandRecord.tick("Comparing tree " + (it+1) + " (of " + numTrees + ") to other trees");
+					originalDistances = pdistTarget.calculatePatristic(targetTree, numTaxa, originalDistances); //for this tree calculate patristic distances (number of nodes separating terminals; no branch lengths)
+					for (int it2 = 0; it2< it && (progIndicator==null || !progIndicator.isAborted()); it2++){ //get tree for comparison
+							num++;
+							
+							Tree comparison = getTree(taxa, it2);
+							if (heights == null || heights.length < comparison.getNumNodeSpaces())
+								heights = new double[comparison.getNumNodeSpaces()][numTaxa];
+							comparisonDistances = pdistTarget.calculatePatristic(comparison, numTaxa, comparisonDistances); //for this tree calculate patristic distances (number of nodes separating terminals; no branch lengths)
+							//calculatePatristic(comparison, numTaxa, heights, comparisonDistances);
+							for (int i = 0; i < numTaxa; i++){ //For each of the taxa, add to its score how unstable it is on this tree
+								for (int j = 0; j < numTaxa; j++)  //for each of the OTHER taxa, calculate how much original and comparison distances differ
+									if (j!=i) {
+										b.setValue(strain(originalDistances[i][j], comparisonDistances[i][j]));
+										results.addValue(i, b); //add difference in distances to running total
+									}
+						
+					}
+				}
+			}
+		}
+		String s = getVeryShortName() + " calculated";
+		
+		if (resultsString != null){
+			if (progIndicator!=null && progIndicator.isAborted()) 
+				resultsString.setValue(s + " INCOMPLETE CALCULATION (only " + num + " of " + numComparisons + " counted).");
+			else {
+				resultsString.setValue(s);
+			}
+		}
+		saveLastResult(results);
+		saveLastResultString(resultsString);
+		if (progIndicator!=null) 
+			progIndicator.goAway();
+	}
+	/*-----------------------------------------*/
+	private double strain(double orig, double comp){
+		double div = Math.abs(orig)+ Math.abs(comp);
+		if (div == 0)
+			return 0;
+		if (exponent >= 1.9999999 && exponent < 2.0000001)
+			return Math.abs(orig - comp)/(div*div); //downweights distant taxa
+		else
+			return Math.abs(orig - comp)/Math.pow(div, exponent); //downweights distant taxa
+	}
+	/*-----------------------------------------*
+	private void calculatePatristic(Tree tree, int numTaxa, double[][] heights, double[][] distances){
+		for (int i = 0; i < numTaxa; i++){
+			for (int j = 0; j < numTaxa; j++)
+				if (i!=j)
+					distances[i][j] = -1;
+				else
+					distances[i][j] = 0;
+		}
+		for (int i = 0; i < tree.getNumNodeSpaces(); i++){
+			for (int j = 0; j < numTaxa; j++)
+				heights[i][j] = -1;
+		}
+		getHeights(tree, tree.getRoot(), heights);
+		getDistances(tree, tree.getRoot(), numTaxa, heights, distances);
+  	 }
+	/*-----------------------------------------*
+	/** Finds heights to taxa for each node.  Beforehand initialize heights to -1*
+	void getHeights(Tree tree, int node, double[][] heights) { 
+  	 	if (tree.nodeIsTerminal(node)){
+  	 		int taxon = tree.taxonNumberOfNode(node);
+  	 		heights[node][taxon]=0;
+  	 	}
+  	 	else {
+  	 		boolean firstDaughter = true;
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			getHeights(tree, daughter, heights);
+  	 			for (int i=0; i<heights[daughter].length; i++)
+  	 				if (heights[daughter][i] >= 0){ //taxon i is in daughter clade
+  	 					if (heights[node][i]<0)
+  	 						heights[node][i] = 0;
+  	 					if (tree.getRoot()==node && !firstDaughter && !tree.nodeIsPolytomous(node))
+  	 						heights[node][i] += heights[daughter][i];
+  	 					else
+  	 						heights[node][i] += heights[daughter][i] + 1;
+		    	 			firstDaughter = false;
+	 				}
+   	 		}
+   	 	}
+	}
+	/** Finds distances among taxa.  Beforehand initialize distances to -1*
+	void getDistances(Tree tree, int node,  int numTaxa, double[][] heights, double[][] distances) { 
+  	 	if (tree.nodeIsInternal(node)){
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			getDistances(tree, daughter, numTaxa, heights, distances);
+  	 		}
+  	  	 	for (int i= 0; i< numTaxa; i++)
+	  	 		for (int j= 0; j< i; j++)
+	  	 			if (distances[i][j]<=0) { //not yet assigned
+	  	 				if (heights[node][i]>= 0 && heights[node][j] >=0){ //first common ancestor found
+	  	 					distances[i][j] = heights[node][i] + heights[node][j];
+	  	 					distances[j][i] = distances[i][j];
+	  	 				}
+	  	 			}
+  	 	}
+	}
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Instability Among Trees";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Taxon Instability Among Trees";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getVersion() {
+		return null;
+   	 }
+	/*.................................................................................................................*/
+  	 public boolean isPrerelease() {
+		return false;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Calculates for each taxon the degree to which its implied unweighted patristic distances between that taxon and others differs among trees. "
+ 		+ " For each taxon i this sums over all tree pairs x and y and over all other taxa j:  | Dijx - Dijy |/(Dijx + Dijy)^^z where Dijq is the distance between taxa i and j on tree q. "
+ 		+ "Close relationships are emphasized if the exponent z is higher (default is 2).";
+   	 }
+   	 
+}
+
+
diff --git a/Source/mesquite/treefarm/TopologyCongruent/TopologyCongruent.java b/Source/mesquite/treefarm/TopologyCongruent/TopologyCongruent.java
new file mode 100644
index 0000000..91cba1b
--- /dev/null
+++ b/Source/mesquite/treefarm/TopologyCongruent/TopologyCongruent.java
@@ -0,0 +1,147 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.TopologyCongruent;
+
+/*New October 7, '08. oliver
+ * Modified 16 October 2008  to use the built-in Tree.equalsTopology method - DRM 
+ * January 2012: added non-exact match. */
+import java.awt.*;
+
+import mesquite.consensus.lib.StrictConsenser;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class TopologyCongruent extends BooleanForTree {
+	OneTreeSource constraintTreeSource;
+	Tree constraintTree;
+	MesquiteBoolean exactMatch = new MesquiteBoolean(false);
+	StrictConsenser strictConsenser = new StrictConsenser();
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		constraintTreeSource = (OneTreeSource)hireEmployee(OneTreeSource.class, "One Tree Source");
+		if(constraintTreeSource==null){
+			return sorry(getName() + " couldn't start because no constraint tree was obtained.");
+		}
+		loadPreferences();
+		MesquiteMenuItemSpec exactMatchItem = addCheckMenuItem( null, "Topologies must be exactly equal", makeCommand("exactMatch",  this), exactMatch);
+
+		if (!MesquiteThread.isScripting()) 
+			if (!queryOptions()) 
+				return false;
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void processMorePreferences (String tag, String content) {
+		if ("exactMatch".equalsIgnoreCase(tag))
+			exactMatch.setFromTrueFalseString(content);
+	}
+	/*.................................................................................................................*/
+	public String prepareMorePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "exactMatch", exactMatch);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("exactMatch "+ exactMatch.toOffOnString()); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), getName() + " Options",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.addLabel(getName() + " Options");
+
+		Checkbox exactMatchCheck = dialog.addCheckBox("Topology must be exact match", exactMatch.getValue());
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			exactMatch.setValue(exactMatchCheck.getState());
+			storePreferences();
+
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets whether or not exact matching should be used", "[on off]", commandName, "exactMatch")) {
+			boolean oldValue = exactMatch.getValue();
+			exactMatch.toggleValue(arguments);
+			if (oldValue != exactMatch.getValue()) {
+				parametersChanged();
+			}
+			return exactMatch;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*..............................................................................*/
+	public void calculateBoolean(Tree tree, MesquiteBoolean result,	MesquiteString resultString) {
+		if(tree==null || result==null || constraintTreeSource == null){
+			return;
+		}
+		Tree sourceTree = constraintTreeSource.getTree(tree.getTaxa());
+		if (sourceTree==null)
+			return;
+		constraintTree = sourceTree.cloneTree();
+		if(constraintTree==null || constraintTree.getTaxa()!=tree.getTaxa())
+			return;
+		MesquiteBoolean isConsistent = new MesquiteBoolean(true);
+
+		if (exactMatch.getValue()) {
+			isConsistent.setValue(tree.equalsTopology(constraintTree, false));
+
+			result.setValue(isConsistent.getValue());
+			if (resultString!=null)
+				if (isConsistent.getValue())
+					resultString.setValue("Tree identical");
+				else
+					resultString.setValue("Tree different");
+		} else {
+			strictConsenser.reset(tree.getTaxa());
+			strictConsenser.addTree(tree);
+			strictConsenser.addTree(constraintTree);
+			Tree strict = strictConsenser.getConsensus();
+			isConsistent.setValue(strict.equalsTopology(constraintTree, false));
+
+			result.setValue(isConsistent.getValue());
+			if (resultString!=null)
+				if (isConsistent.getValue())
+					resultString.setValue("Tree consistent");
+				else
+					resultString.setValue("Tree inconsistent");
+		}
+	}
+	/*..............................................................................*/
+	public String getName() {
+		return "Tree Congruent with Constraint Tree Topology";
+	}
+	/*..............................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation(){
+		return "Determines if tree matches topology of a given constraint tree.  This module does not handle backbone constraints; all trees must have the same taxa present.  For backbone constraint trees, where the constraint tree need not contain all taxa, use the 'Tree Congruent with Backbone Constraint Tree Topology' module.";
+	}
+	/*........................................................*/
+	public int getVersionOfFirstRelease(){
+		return 260;
+	}
+	/*........................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/TreeSatisfiesValue/TreeSatisfiesValue.java b/Source/mesquite/treefarm/TreeSatisfiesValue/TreeSatisfiesValue.java
new file mode 100644
index 0000000..d0e4940
--- /dev/null
+++ b/Source/mesquite/treefarm/TreeSatisfiesValue/TreeSatisfiesValue.java
@@ -0,0 +1,213 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.TreeSatisfiesValue;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import java.awt.*;
+
+/** this is a module that deterimines whether or not a tree has a value the same as, greater than or less than a specified value */
+public class TreeSatisfiesValue extends BooleanForTree implements MesquiteListener {
+	public String getVeryShortName() {
+		return "Tree Satisfies Value?";
+	}
+	public String getName() {
+		return "Tree Value Satisfies Criterion";
+	}
+	public String getExplanation() {
+		return "Determines if the tree has a value either greater than, less than or equal to one specified." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + "  needs a method to calculate values for trees.",
+		"The method to calculate values for trees can be selected initially or in the Type of Value submenu");
+	}
+	MesquiteBoolean equals, greaterThan, lessThan;
+	boolean defaultEquals = true;
+	boolean defaultGT = false;
+	boolean defaultLT = false;
+	NumberForTree numberTask = null;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	MesquiteNumber target = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask = (NumberForTree)hireEmployee(NumberForTree.class, "Values for trees to satisfy");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculating module obtained for values for trees.");
+		target = new MesquiteNumber(0);
+		equals = new MesquiteBoolean(defaultEquals);
+		greaterThan = new MesquiteBoolean(defaultGT);
+		lessThan = new MesquiteBoolean(defaultLT);
+		if (!MesquiteThread.isScripting()) 
+			if (!presentOptions())				return false;
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue("Criterion for Tree Values");
+		numberTask.setHiringCommand(ntC);
+		MesquiteSubmenuSpec mss = addSubmenu(null, getName());
+		if (numModulesAvailable(NumberForTree.class)>1) {
+			addItemToSubmenu(null, mss,"Type of Value...", MesquiteModule.makeCommand("setValues",  this));
+		}
+		addItemToSubmenu(null, mss, "Set Target Value...", MesquiteModule.makeCommand("setTarget",  this));
+
+		addItemToSubmenu(null, mss, "-", null);
+
+		addCheckMenuItemToSubmenu(null, mss, "Equals", MesquiteModule.makeCommand("toggleEquals",  this), equals);
+		addCheckMenuItemToSubmenu(null, mss, "Greater Than", MesquiteModule.makeCommand("toggleGT",  this), greaterThan);
+		addCheckMenuItemToSubmenu(null, mss, "Less Than", MesquiteModule.makeCommand("toggleLT",  this), lessThan);
+		return true;
+	}
+	public boolean presentOptions(){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(containerOfModule(), "Criteria",  buttonPressed);
+		queryDialog.addLabel("Value trees need to satisfy", Label.CENTER);
+		DoubleField df = queryDialog.addDoubleField("Target Value", target.getDoubleValue(), 10);
+		Checkbox E = queryDialog.addCheckBox ("Equal to target", true);
+		Checkbox GT = queryDialog.addCheckBox ("Greater than target", false);
+		Checkbox LT = queryDialog.addCheckBox ("Less than target", false);
+
+		queryDialog.completeAndShowDialog(true);
+
+		boolean ok = (queryDialog.query()==0);
+
+		if (ok) {
+			target.setValue(df.getValue());
+			equals.setValue(E.getState());
+			greaterThan.setValue(GT.getState());
+			lessThan.setValue(LT.getState());
+		}
+
+		queryDialog.dispose();
+		return ok;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setValues ", numberTask);
+
+		temp.addLine("setTarget " + target);
+		if (equals.getValue()!=defaultEquals)
+			temp.addLine("toggleEquals " + equals.toOffOnString());
+		if (greaterThan.getValue()!=defaultGT)
+			temp.addLine("toggleGT " + greaterThan.toOffOnString());
+		if (lessThan.getValue()!=defaultLT)
+			temp.addLine("toggleLT " + lessThan.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the target value trees must satisfy", "[target value]", commandName, "setTarget")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			double T = MesquiteDouble.fromString(arguments, pos);
+			if (!MesquiteDouble.isCombinable(T))
+				T = MesquiteDouble.queryDouble(containerOfModule(), "Target Value", "Sets the target value that trees must satisfy.", target.getDoubleValue());
+			if (!MesquiteDouble.isCombinable(T))
+				return null;
+			if (target.getDoubleValue() != T) {
+				target.setValue(T);
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value equal to that in cell touched", "[on = selects equal; off]", commandName, "toggleEquals")) {
+			boolean current = equals.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			equals.toggleValue(ParseUtil.getFirstToken(arguments, io));
+			if (current != equals.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value greater than that in cell touched", "[on = selects greater than; off]", commandName, "toggleGT")) {
+			boolean current = greaterThan.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			greaterThan.toggleValue(ParseUtil.getFirstToken(arguments, io));
+			if (current != equals.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the wand selects taxa with value less than that in cell touched", "[on = selects less than; off]", commandName, "toggleLT")) {
+			boolean current = lessThan.getValue();
+			MesquiteInteger io = new MesquiteInteger(0);
+			lessThan.toggleValue(ParseUtil.getFirstToken(arguments, io));
+			if (current != equals.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to calculate the value for trees to satisfy", "[name of module]", commandName, "setValues")) {
+			NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Values for trees to satisfy", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting()) {
+					parametersChanged();
+				}
+
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void calculateBoolean(Tree tree, MesquiteBoolean result, MesquiteString resultString) {
+		if (result==null || tree==null)
+			return;
+		MesquiteNumber r = new MesquiteNumber();
+
+		numberTask.calculateNumber(tree, r, null);
+		boolean bt = ((greaterThan.getValue() && r.isMoreThan(target)) || (lessThan.getValue() && r.isLessThan(target)) || (equals.getValue() && r.equals(target)));
+		result.setValue(bt);
+		boolean first = true;
+		String s = "";
+		if (greaterThan.getValue()) {
+			s += " greater than";
+			first = false;
+		}
+		if (lessThan.getValue()) {
+			if (!first)
+				s += " or";
+			s += " less than";
+			first = false;
+		}
+		if (equals.getValue()) {
+			if (!first)
+				s += " or";
+			s += " equal to";
+		}
+		if (resultString!=null)
+			if (bt)
+				resultString.setValue("Tree's value for " + numberTask.getName() + " is " + s + " the target value of " + target + ", and thus satisfies the criterion");
+			else
+				resultString.setValue("Tree's value for " + numberTask.getName() + " is NOT " + s + " the target value of " + target + ", and thus fails the criterion");
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return true;
+	}
+
+
+}
+
diff --git a/Source/mesquite/treefarm/TreeTotalPathLength/TreeTotalPathLength.java b/Source/mesquite/treefarm/TreeTotalPathLength/TreeTotalPathLength.java
new file mode 100644
index 0000000..4b46544
--- /dev/null
+++ b/Source/mesquite/treefarm/TreeTotalPathLength/TreeTotalPathLength.java
@@ -0,0 +1,90 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison. 
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.TreeTotalPathLength;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class TreeTotalPathLength extends NumberForTree {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 
+  	 public double totalPath(Tree tree, int node) {
+  	 	if (tree.nodeIsTerminal(node)) { 
+  	 		if (tree.branchLengthUnassigned(node))
+  	 			return 0;
+  	 		else
+  	 			return tree.getBranchLength(node);
+  	 	}
+  	 	else {
+	  	 	double sum = 0;
+		  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			sum += totalPath(tree, daughter);
+	  		}
+	 	 	if (!tree.branchLengthUnassigned(node))
+	  	 			sum += tree.getBranchLength(node);
+ 	 		return sum;
+  		}
+  	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+    	if (tree == null)
+    		return;
+		if (tree.hasBranchLengths())
+			result.setValue(totalPath(tree, tree.getRoot()));
+		else
+			result.setValue(0);
+		if (resultString!=null)
+			resultString.setValue("Sum of Branch Lengths: "+ result.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Sum of Branch Lengths";
+   	 }
+    		/*.................................................................................................................*/
+    		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+    		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+    		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+    		public int getVersionOfFirstRelease(){
+    			return 200;  
+    		}
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates the sum of branch lengths of the tree, treating unassigned lengths as 0.  The length of the root is counted.";
+   	 }
+}
+
diff --git a/Source/mesquite/treefarm/aTreeFarmIntro/aTreeFarmIntro.java b/Source/mesquite/treefarm/aTreeFarmIntro/aTreeFarmIntro.java
new file mode 100644
index 0000000..4dfbb0e
--- /dev/null
+++ b/Source/mesquite/treefarm/aTreeFarmIntro/aTreeFarmIntro.java
@@ -0,0 +1,112 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.aTreeFarmIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/*
+To do:
+o If only single tree window, these modifying tree sources should not be available, since they will recursively look internally
+
+======== Random adjustments of current tree ========
+++ Randomly rearrange tree (makes n randomly chosen branch moves)
+
+++ Augment tree randomly
+
+++ Rarefy tree randomly
+
+++ Random resolutions of polytomy
+
+++ Add noise to branch lengths (uniform normal; binary noise; biased normal, e.g. increase variance deeper)
+
+-- Reshuffling terminals
+
+======== Determinate adjustments ========
+
+++ All rerootings
+
+++ Rearrangements (using tree search rearrangments)
+
+-- Adjust branch lengths of trees (uses branch lengths adjusters available)
+
+-- Partition tree depending on taxa partition
+
+======== Simulations of evolution/ Fully random trees ========
+++ All dichotomous trees
+
+++ Equiprobable speciation (pure birth process -- conditioned on what?  terminal branch lengths?)
+
+++ Equiprobable trees
+
+-- Constant birth/death process
+
+-- Randomly varying birth/death parameters
+
+-- b/d depends of simulation of evolution of character affecting diversification rates
+
+-- b/d depends on age of lineage
+
+*/
+/* ======================================================================== */
+public class aTreeFarmIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aTreeFarmIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Extra utilities for trees, including comparisons, randomizations and manipulations.";
+   	 }
+   
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree Farm Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Tree Farm";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*/
+ 	public String getPackageCitation(){
+ 		return "Maddison, W.P.,  D.R. Maddison and P. Midford, 2014.  Tree Farm package for Mesquite, version 3.0.";
+ 	}
+	/*.................................................................................................................*/
+  	 public String getPackageVersion() {
+		return "3.00";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getPackageAuthors() {
+		return "W. Maddison, D. Maddison and P. Midford.";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return true; 
+	}
+}
+
diff --git a/Source/mesquite/treefarm/aTreeFarmIntro/splash.gif b/Source/mesquite/treefarm/aTreeFarmIntro/splash.gif
new file mode 100644
index 0000000..6bc9297
Binary files /dev/null and b/Source/mesquite/treefarm/aTreeFarmIntro/splash.gif differ
diff --git a/Source/mesquite/treefarm/aTreeFarmIntro/splash.psd b/Source/mesquite/treefarm/aTreeFarmIntro/splash.psd
new file mode 100644
index 0000000..f584391
Binary files /dev/null and b/Source/mesquite/treefarm/aTreeFarmIntro/splash.psd differ
diff --git a/Source/mesquite/treefarm/explanation.txt b/Source/mesquite/treefarm/explanation.txt
new file mode 100644
index 0000000..72fef17
--- /dev/null
+++ b/Source/mesquite/treefarm/explanation.txt
@@ -0,0 +1,2 @@
+Tree Farm Package
+Supplies trees, some of which are modifications of existing trees (e.g. modified by random branch moves).  Also provides specialized utilities to edit existing trees.
diff --git a/Source/mesquite/treefarm/lib/BlockFromTreeSource.java b/Source/mesquite/treefarm/lib/BlockFromTreeSource.java
new file mode 100644
index 0000000..c7a48da
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/BlockFromTreeSource.java
@@ -0,0 +1,155 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.charMatrices.lib.RandomMatrixModifier;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies tree blocks from other sources.*/
+public abstract class BlockFromTreeSource extends TreeBlockSource { 
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeBlockFiller.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially");
+	}
+	/*.................................................................................................................*/
+	int currentTreeBlockIndex=MesquiteInteger.unassigned;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	TreeBlockFiller fillerTask = null;
+	Taxa preferredTaxa =null;
+	
+	int numTrees = 100;
+	MesquiteMenuItemSpec ntreesItem = null;
+	boolean nTreesSet = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		fillerTask = (TreeBlockFiller)hireNamedEmployee(TreeBlockFiller.class, getSource());
+ 		if (fillerTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		if (enableNumTreesChoice())
+			ntreesItem = addMenuItem( "Number of Trees...", makeCommand("setNumberTrees",  this));
+		return true;
+  	 }
+	/*.................................................................................................................*/
+ 	 public abstract String getSource();
+ 	/*.................................................................................................................*/
+ 	 public abstract boolean enableNumTreesChoice();
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean requestPrimaryChoice(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa) {
+  		preferredTaxa = taxa;
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		setPreferredTaxa(taxa);
+   		fillerTask.initialize(taxa);
+		if (!fillerTask.hasLimitedTrees(taxa)){
+			if (!MesquiteThread.isScripting()  && !nTreesSet){
+				int n = MesquiteInteger.queryInteger(containerOfModule(), "Trees per block?", "How many trees to include per tree block?", numTrees);
+				if (MesquiteInteger.isCombinable(n) && n>0)
+					numTrees = n;
+				nTreesSet = true;
+			}
+		}
+		if (enableNumTreesChoice() && ntreesItem==null)
+			ntreesItem = addMenuItem( "Number of Trees...", makeCommand("setNumberTrees",  this));
+		if (ntreesItem!=null && fillerTask!=null)
+			ntreesItem.setEnabled(!fillerTask.hasLimitedTrees(taxa));
+		MesquiteTrunk.resetMenuItemEnabling();
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("getTreeFiller ", fillerTask);
+   	 	if (enableNumTreesChoice())
+   	 		temp.addLine("setNumberTrees " + numTrees);
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the number of trees included in each tree block", "[number of trees]", commandName, "setNumberTrees")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees:", numTrees, 0, MesquiteInteger.infinite);
+    	 		if (newNum>0  && newNum!=numTrees) {
+    	 			numTrees = newNum;
+				parametersChanged();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the module supplying trees", "[name of module]", commandName, "getTreeFiller")) {
+    	 		return fillerTask;
+}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+   	public TreeVector getFirstBlock(Taxa taxa) {
+   		currentTreeBlockIndex=0;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getBlock(Taxa taxa, int ic) {
+   		currentTreeBlockIndex=ic;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getCurrentBlock(Taxa taxa) {
+   		if (fillerTask instanceof Incrementable)
+   			((Incrementable)fillerTask).setCurrent(currentTreeBlockIndex);
+   		setPreferredTaxa(taxa);
+   		TreeVector treeList = new TreeVector(taxa);
+   		fillerTask.fillTreeBlock(treeList, numTrees); 
+   		return treeList;
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getNextBlock(Taxa taxa) {
+   		currentTreeBlockIndex++;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTreeBlocks(Taxa taxa) {
+   		if (fillerTask instanceof Incrementable)
+   			return (int)( ((Incrementable)fillerTask).getMax() -  ((Incrementable)fillerTask).getMin() + 1);
+		return 1;
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeBlockNameString(Taxa taxa, int index) {
+		return fillerTask.getName() + "  " + currentTreeBlockIndex;//todo!  not right
+   	}
+	/*.................................................................................................................*/
+   	public String getCurrentTreeBlockNameString(Taxa taxa) {
+		return fillerTask.getName() + "  " + currentTreeBlockIndex; //todo!  not right
+  	}
+}
+
diff --git a/Source/mesquite/treefarm/lib/DetTreeModifier.java b/Source/mesquite/treefarm/lib/DetTreeModifier.java
new file mode 100644
index 0000000..831b50d
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/DetTreeModifier.java
@@ -0,0 +1,34 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class DetTreeModifier extends MesquiteModule {
+   	 public Class getDutyClass() {
+   	 	return DetTreeModifier.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Determinate Tree Modifier";
+   	 }
+   	 
+   	 public abstract void modifyTree(Tree original, MesquiteTree modified, int whichModification);
+   	public abstract int getNumberOfTrees(Tree tree);
+}
+
diff --git a/Source/mesquite/treefarm/lib/LiveTreeBlocks.java b/Source/mesquite/treefarm/lib/LiveTreeBlocks.java
new file mode 100644
index 0000000..ef12afa
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/LiveTreeBlocks.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.lib;
+/*~~  */
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class LiveTreeBlocks extends FileAssistantT {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSourceDefinite.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially");
+	}
+	/*.................................................................................................................*/
+	TreeVector treeBlock;
+	TreeSourceDefinite treeSource;
+	TreesManager manager;
+	Taxa taxa =null;
+	MesquiteTextWindow window;
+
+	MesquiteBoolean checkIfTreesAreSame;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("LiveTrees");
+		checkIfTreesAreSame = new MesquiteBoolean(false);
+		addCheckMenuItem( null, "Recheck Tree Identity", makeCommand("toggleCheckSame",  this), checkIfTreesAreSame);
+		//"$ #NumForTreeList #NumberOfTaxa"
+		treeSource = (TreeSourceDefinite)hireNamedEmployee(TreeSourceDefinite.class, "$ #DefiniteTreeSource");
+		if (treeSource == null) {
+			return sorry(getName() + " couldn't start because no source of trees to serve as a basis for modification or filtering was obtained.");
+		}
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		window = new MesquiteTextWindow(this, "Live Tree Block", true); //infobar
+		setModuleWindow(window);
+		window.setEditable(false);
+		window.setWindowSize(200,200);
+		if (manager==null)
+			return sorry(getName() + " couldn't start because no tree manager module was found.");
+		if (!MesquiteThread.isScripting())
+			return establishBlock(null);
+		if (window != null){
+			window.setText(getTextForWindow());
+			resetAllMenuBars();
+		}
+		if (!MesquiteThread.isScripting()){
+			window.setVisible(true);
+			window.show();
+		}
+		return true;
+	}
+	public String getTreeSourceName(){
+		return "#DefiniteTreeSource";
+	}
+	/*.........................................................................................................h........*/
+	public void settaxa(Taxa taxa) {
+		if (taxa !=null && taxa.isDoomed())
+			return;
+		if (taxa!=this.taxa) {
+			if (this.taxa !=null)
+				this.taxa.removeListener(this);
+			this.taxa = taxa;
+			taxa.addListener(this);
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (treeBlock !=null) {
+			treeBlock.removeListener(this);
+			//remove other listners!!!!!!!!!
+		}
+
+		super.endJob();
+	}
+	private String getTextForWindow(){
+		if (treeBlock == null)
+			return "There is no live tree block yet.";
+		if (treeSource == null)
+			return "There is no tree source";
+		String s = "Live Tree Block\nThe tree block \"" + treeBlock.getName() + "\" is linked to the tree source " + treeSource.getNameAndParameters();
+		s += "\nThe tree block will be available as a stored tree block (e.g., using Stored Trees as a tree source).\nIf The tree source changes its output, the tree block will be updated.";
+		s += "However, when you save the file, the trees will be saved as a block in the file.";
+		return s;
+	}
+	private int whichTreeBlock(){
+		int total = manager.getNumberTreeBlocks(taxa, getProject().getHomeFile());
+		for (int i=0; i<total; i++){
+			TreeVector trees = manager.getTreeBlock(taxa, getProject().getHomeFile(), i);
+			if (treeBlock == trees)
+				return i;
+		}
+		return -1;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (taxa!=null && getProject().getNumberTaxas()>1)
+			temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa));
+		temp.addLine("getTreeSource ", treeSource); 
+		temp.addLine("toggleCheckSame " + checkIfTreesAreSame.toOffOnString());
+		if (treeBlock != null){
+			int treeblockNumber = whichTreeBlock();
+			if (treeblockNumber>=0)
+				temp.addLine("linkToTreeBlock " + TreeVector.toExternal(treeblockNumber)); 
+		}
+		Snapshot fromWindow = window.getSnapshot(file);
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("showWindow");
+		temp.addLine("endTell");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the source of the tree to be converted to live tree block", null, commandName, "getTreeSource")) {
+			return treeSource;
+		}
+		else if (checker.compare(this.getClass(),  "Sets which block of trees to use", "[block number]", commandName, "linkToTreeBlock")) {
+			int whichList = TreeVector.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				if (taxa==null && getProject().getNumberTaxas()==1)
+					taxa = getProject().getTaxa(0);
+				treeBlock = manager.getTreeBlock(taxa, getProject().getHomeFile(), whichList);  //must add to home file
+				if (treeBlock ==null){
+					discreetAlert( "No tree block found for linking"); 
+					return null;
+				}
+				treeSource.initialize(taxa);
+
+				window.setText(getTextForWindow());
+				return treeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to show just the last tree", "[on or off]", commandName, "toggleCheckSame")) {
+			boolean current = checkIfTreesAreSame.getValue();
+			checkIfTreesAreSame.toggleValue(parser.getFirstToken(arguments));
+			if (current!=checkIfTreesAreSame.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets which block of taxa to use", "[block reference, number, or name]", commandName, "setTaxa")) { 
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				establishBlock(t);
+				window.setText(getTextForWindow());
+				return t;
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Returns current tree block", null, commandName, "getTreeBlock")) {
+			return treeBlock;
+		}
+		else if (checker.compare(this.getClass(),  "Returns the window", null, commandName, "getWindow")) {
+			return window;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	private boolean establishBlock(Taxa tx){
+
+		if (tx != null)
+			taxa = tx;
+		else 
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa for which to establish a live tree block");
+		if (taxa == null)
+			return false;
+		settaxa(taxa);
+		treeSource.initialize(taxa);
+		treeBlock = manager.makeNewTreeBlock(taxa, "Trees from " + treeSource.getName(), getProject().getHomeFile());
+		int numTrees = treeSource.getNumberOfTrees(taxa);
+		for (int i = 0; i< numTrees; i++){
+			Tree t = treeSource.getTree(taxa, i);
+			treeBlock.addElement(t.cloneTree(), false);
+		}
+		window.setText(getTextForWindow());
+		return true;
+	}
+
+	private void synchTreeBlock(){
+		if (treeBlock == null)
+			return;
+		boolean changed = false;
+		boolean added = false;
+		int numTrees = treeSource.getNumberOfTrees(taxa);
+
+		int numTreesInBlock = treeBlock.size();
+		if (numTreesInBlock>numTrees){
+			int numExcess = numTreesInBlock-numTrees;
+			for (int i=0; i<numExcess; i++) {
+				treeBlock.removeElementAt(treeBlock.size()-1, false);
+				changed = true;
+			}
+		}
+
+		if (checkIfTreesAreSame.getValue())
+			for (int i = 0; i< numTrees && i < treeBlock.size(); i++){
+				Tree t = treeSource.getTree(taxa, i);
+				Tree tPresent = (Tree)treeBlock.elementAt(i);
+				if (!t.equals(tPresent)) {
+					treeBlock.replaceElement(tPresent, t.cloneTree(), false);
+					changed = true;
+				}
+			}
+		for (int i= treeBlock.size(); i<numTrees; i++){
+			Tree t = treeSource.getTree(taxa, i);
+			treeBlock.addElement(t.cloneTree(), false);
+			added = true;
+		}
+		if (changed)
+			treeBlock.notifyListeners(this, new Notification(MesquiteListener.ELEMENT_CHANGED));
+		else if (added)
+			treeBlock.notifyListeners(this, new Notification(MesquiteListener.ITEMS_ADDED, new int[]{numTreesInBlock, MesquiteInteger.finite }));
+
+		window.setText(getTextForWindow());
+	}
+
+
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee == treeSource)
+			synchTreeBlock();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() { 
+		return true; //checkIfTreesAreSame
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Live Tree Block...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Live Tree Block";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 111;  
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Establishes a tree block from a source and maintains it as a live tree block." ;  
+	}
+
+}
+
+
diff --git a/Source/mesquite/treefarm/lib/NForTaxonWithTree.java b/Source/mesquite/treefarm/lib/NForTaxonWithTree.java
new file mode 100644
index 0000000..a4f8042
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/NForTaxonWithTree.java
@@ -0,0 +1,39 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** ======================================================================== */
+/*
+provides a superclass for NumberForTaxon that use a tree;
+*/
+
+public abstract class NForTaxonWithTree extends MesquiteModule {
+ 	 public Class getDutyClass() {
+    	 	return NForTaxonWithTree.class;
+    	 }
+  	public String getDutyName() {
+  		return "Number for Taxon using Tree";
+    	 }
+ 
+	public abstract void calculateNumbers(Taxa taxa, Tree tree, NumberArray results, MesquiteString resultString);
+
+}
+
+
diff --git a/Source/mesquite/treefarm/lib/NForTaxonWithTrees.java b/Source/mesquite/treefarm/lib/NForTaxonWithTrees.java
new file mode 100644
index 0000000..8f0f2dd
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/NForTaxonWithTrees.java
@@ -0,0 +1,237 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** ======================================================================== */
+/*
+provides a superclass for NumberForTaxon that use a series of trees, by taking care of use of trees;
+*/
+
+public abstract class NForTaxonWithTrees extends NumberForTaxon {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially or in the Tree Source submenu");
+	}
+	/*.................................................................................................................*/
+	protected boolean needsRecalculation = true;
+	protected Taxa currentTaxa;
+	MesquiteString treeSourceName;
+	MesquiteCommand cstC;
+	TreeSource treeSourceTask;
+	NumberArray results;
+	MesquiteString resultsString;
+	MesquiteMenuItemSpec numTreesItem = null;
+	boolean numTreesSet = false;
+	int defNumTrees = 100;
+	int skipTrees = 1;
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName){
+ 		treeSourceTask = (TreeSource)hireEmployee(TreeSource.class,  "Source of trees for " + getName());
+ 		if (treeSourceTask == null) {
+ 			return sorry(getName() + " couldn't start because no source of trees obtained");
+ 		}
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		
+
+		cstC =  makeCommand("setTreeSource",  this);
+		treeSourceTask.setHiringCommand(cstC);
+		if (numModulesAvailable(TreeSource.class)>1){ 
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source",cstC, TreeSource.class);
+			mss.setSelected(treeSourceName);
+		}
+		numTreesItem = addMenuItem("Number of Trees (for " + getVeryShortName() + ")...", makeCommand("setNumTrees", this));
+		numTreesItem.setEnabled(false);
+		addMenuItem("Skip trees (" + getVeryShortName() + ")...", makeCommand("setSkipping", this));
+		results = new NumberArray(1);
+		resultsString = new MesquiteString();
+		needsRecalculation = MesquiteThread.isScripting();
+		return true;  
+ 	}
+ 	
+	/*.................................................................................................................*/
+ 	public void employeeQuit(MesquiteModule m){
+ 		if (m!=treeSourceTask)
+ 			iQuit();
+ 	}
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+	 		if (employee != treeSourceTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED) {
+				needsRecalculation = true;
+				if (!MesquiteThread.isScripting())
+					super.employeeParametersChanged(employee, source, notification);
+			}
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource " , treeSourceTask);
+  	 	temp.addLine("setNumTrees " + defNumTrees);
+  	 	temp.addLine("setSkipping " + skipTrees);
+  	 	temp.addLine("doCalc");
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the source of trees for comparison", "[name of module]", commandName, "setTreeSource")) {
+    	 		TreeSource temp =  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees for " + getName(), treeSourceTask);
+ 			if (temp!=null) {
+	    	 		treeSourceTask = temp;
+				treeSourceTask.setHiringCommand(cstC);
+				treeSourceName.setValue(treeSourceTask.getName());
+				treeSourceTask.initialize(currentTaxa);
+				numTreesSet = false;
+				if (!MesquiteThread.isScripting()) {
+					needsRecalculation = true;
+					parametersChanged();
+				}
+ 			}
+ 			return temp;
+    	 	}
+
+    	 	else if (checker.compare(this.getClass(), "Sets the number of trees", "[number]", commandName, "setNumTrees")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for " + getName() +  "):", defNumTrees, 0, MesquiteInteger.infinite);
+    	 		if (newNum>0  && newNum!=defNumTrees) {
+    	 			defNumTrees = newNum;
+    	 			numTreesSet = true;
+				if (!MesquiteThread.isScripting()) {
+					needsRecalculation = true;
+					parametersChanged();
+				}
+    	 		}
+    	 		else if (defNumTrees == newNum)
+    	 			numTreesSet = true;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether trees are skipped (every nth tree compared)", "[n]", commandName, "setSkipping")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Skip", "Enter n where every nth tree is compared (for " + getName() +  ").  By entering 2 for example, every other tree is skipped. Enter 1 to indicate that every tree is examined.", skipTrees, 1, MesquiteInteger.infinite);
+    	 		if (newNum>0  && newNum!=skipTrees) {
+    	 			skipTrees = newNum;
+				if (!MesquiteThread.isScripting()) {
+					needsRecalculation = true;
+					parametersChanged();
+				}
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Requests calculations", null, commandName, "doCalc")) {
+			needsRecalculation = true;
+			parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+   	 }
+   	 private int getNumTrees(){
+   	 	if (MesquiteThread.isScripting() || numTreesSet)
+   	 		return defNumTrees;
+		int newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees (for " + getName() + "):", defNumTrees, 0, MesquiteInteger.infinite);
+ 		if (newNum>0) {
+ 			defNumTrees = newNum;
+ 			numTreesSet = true;
+ 		}
+ 		return defNumTrees;
+   	 }
+	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		currentTaxa = taxa;
+   		needsRecalculation = true;
+   		treeSourceTask.initialize(currentTaxa);
+   	}
+	/*.................................................................................................................*/
+	public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString){
+		if (result==null|| taxon == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxon.getTaxa()!= currentTaxa) {
+			initialize(taxon.getTaxa());
+			needsRecalculation = true;
+		}
+		if (needsRecalculation)
+			doCalcs();
+		int it = currentTaxa.whichTaxonNumber(taxon);
+		results.placeValue(it, result);
+		
+		if (resultString !=null) {
+			resultString.setValue(resultsString.getValue());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	protected int getNumTrees(Taxa taxa){
+		int sourceNumTrees = treeSourceTask.getNumberOfTrees(currentTaxa);
+		int numTrees;
+		if (MesquiteInteger.isCombinable(sourceNumTrees)) {
+			numTrees = sourceNumTrees;
+		}
+		else
+			numTrees = getNumTrees();
+		if (skipTrees >=1)
+			numTrees = (numTrees+ (skipTrees-1)) / skipTrees; 
+		return numTrees;
+	}
+	/*.................................................................................................................*/
+	protected Tree getTree(Taxa taxa, int it){
+		if (treeSourceTask == null)
+			return null;
+		if (skipTrees<=1)
+			return treeSourceTask.getTree(taxa, it);
+		return treeSourceTask.getTree(taxa, skipTrees * it);
+	}
+	/*.................................................................................................................*/
+	public void doCalcs(){
+		needsRecalculation = false;
+		int numTaxa = currentTaxa.getNumTaxa();
+		results.resetSize(numTaxa);
+		results.zeroArray();
+		int sourceNumTrees = treeSourceTask.getNumberOfTrees(currentTaxa);
+		numTreesItem.setEnabled(!MesquiteInteger.isCombinable(sourceNumTrees));
+		MesquiteTrunk.resetMenuItemEnabling();
+		int numTrees;
+		if (MesquiteInteger.isCombinable(sourceNumTrees)) {
+			numTrees = sourceNumTrees;
+		}
+		else
+			numTrees = getNumTrees();
+		int numTreesUsed = numTrees;
+		if (skipTrees >=1)
+			numTreesUsed = (numTrees+ (skipTrees-1)) / skipTrees; 
+		
+		
+		calculateNumbers(currentTaxa,  results,  resultsString);
+		
+		
+		if (skipTrees >1)
+			resultsString.append( ".  Calculated using " + numTreesUsed + " out of a total of " + numTrees + " trees. ");
+		else
+			resultsString.append( ".  Calculated using " + numTrees + " trees. ");
+	}
+	/*-----------------------------------------*/
+	public abstract void calculateNumbers(Taxa taxa, NumberArray results, MesquiteString resultString);
+	/*-----------------------------------------*/
+	/*.................................................................................................................*/
+}
+
+
diff --git a/Source/mesquite/treefarm/lib/PatristicDistances.java b/Source/mesquite/treefarm/lib/PatristicDistances.java
new file mode 100644
index 0000000..9ed7927
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/PatristicDistances.java
@@ -0,0 +1,93 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+
+
+public class PatristicDistances {
+	double[][] heights;
+
+	/*-----------------------------------------*/
+	public double[][] calculatePatristic(Tree tree, int numTaxa, double[][] distances){
+		if (distances == null || distances.length != numTaxa)
+			distances = new double[numTaxa][numTaxa];
+		if (heights == null || heights.length != tree.getNumNodeSpaces() || heights[0].length != numTaxa)
+			heights = new double[tree.getNumNodeSpaces()][numTaxa];
+		for (int i = 0; i < numTaxa; i++){
+			for (int j = 0; j < numTaxa; j++)
+				if (i!=j)
+					distances[i][j] = -1;
+				else
+					distances[i][j] = 0;
+		}
+		for (int i = 0; i < tree.getNumNodeSpaces(); i++){
+			for (int j = 0; j < numTaxa; j++)
+				heights[i][j] = -1;
+		}
+		getHeights(tree, tree.getRoot(), heights);
+		getDistances(tree, tree.getRoot(), numTaxa, heights, distances);
+		return distances;
+	}
+	/*-----------------------------------------*/
+	/** Finds heights to taxa for each node.  Beforehand initialize heights to -1*/
+	void getHeights(Tree tree, int node, double[][] heights) { 
+		if (tree.nodeIsTerminal(node)){
+			int taxon = tree.taxonNumberOfNode(node);
+			if (node < heights.length && taxon >= 0 && taxon< heights[node].length)
+				heights[node][taxon]=0;
+		}
+		else {
+			boolean firstDaughter = true;
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				getHeights(tree, daughter, heights);
+				if (daughter<heights.length)
+					for (int i=0; i<heights[daughter].length; i++)
+						if (heights[daughter][i] >= 0){ //taxon i is in daughter clade
+							if (node < heights.length && i< heights[node].length){
+								if (heights[node][i]<0)
+									heights[node][i] = 0;
+								if (tree.getRoot()==node && !firstDaughter && !tree.nodeIsPolytomous(node))
+									heights[node][i] += heights[daughter][i];
+								else
+									heights[node][i] += heights[daughter][i] + 1;
+							}
+							firstDaughter = false;
+						}
+			}
+		}
+	}
+	/** Finds distances among taxa.  Beforehand initialize distances to -1*/
+	void getDistances(Tree tree, int node,  int numTaxa, double[][] heights, double[][] distances) { 
+		if (tree.nodeIsInternal(node)){
+			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+				getDistances(tree, daughter, numTaxa, heights, distances);
+			}
+			for (int i= 0; i< numTaxa; i++)
+				for (int j= 0; j< i; j++)
+					if (distances[i][j]<=0) { //not yet assigned
+						if (heights[node][i]>= 0 && heights[node][j] >=0){ //first common ancestor found
+							distances[i][j] = heights[node][i] + heights[node][j];
+							distances[j][i] = distances[i][j];
+						}
+					}
+		}
+	}
+
+}
+
+
diff --git a/Source/mesquite/treefarm/lib/RndTreeModifier.java b/Source/mesquite/treefarm/lib/RndTreeModifier.java
new file mode 100644
index 0000000..f224dbb
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/RndTreeModifier.java
@@ -0,0 +1,33 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class RndTreeModifier extends MesquiteModule {
+  	 public Class getDutyClass() {
+   	 	return RndTreeModifier.class;
+   	 }
+ 	public String getDutyName() {
+ 		return "Random Tree Modifier";
+   	 }
+   	 
+   	 public abstract void modifyTree(Tree tree, MesquiteTree modified, RandomBetween rng);
+}
+
diff --git a/Source/mesquite/treefarm/lib/SourceFromTreeSource.java b/Source/mesquite/treefarm/lib/SourceFromTreeSource.java
new file mode 100644
index 0000000..f47cdea
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/SourceFromTreeSource.java
@@ -0,0 +1,80 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class SourceFromTreeSource extends TreeSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+		"The source of trees can be selected initially");
+	}
+	/*.................................................................................................................*/
+	protected TreeSource currentTreeSource;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		currentTreeSource = (TreeSource)hireEmployee(TreeSource.class, "Source of trees to be transformed or filtered (" + whatIsMyPurpose() + ")");
+ 		if (currentTreeSource == null) {
+ 			return sorry(getName() + " couldn't start because no source of trees to serve as a basis for modification or filtering was obtained.");
+ 		}
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", currentTreeSource); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of the tree to be transformed or filtered", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of tree to be transformed or filtered", currentTreeSource);
+			if (temp !=null){
+				currentTreeSource = temp;
+				parametersChanged();
+    	 			return currentTreeSource;
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		if (currentTreeSource!=null)
+   			currentTreeSource.initialize(taxa);
+   	}
+	/*.................................................................................................................*/
+	protected Tree getBasisTree(Taxa taxa, int i){
+   		Tree t =  currentTreeSource.getTree(taxa, i);
+ 		return t;
+	}
+	/*.................................................................................................................*/
+	protected TreeSource getBasisTreeSource(){
+   		return currentTreeSource;
+	}
+}
+
diff --git a/Source/mesquite/treefarm/lib/SourceModifiedTree.java b/Source/mesquite/treefarm/lib/SourceModifiedTree.java
new file mode 100644
index 0000000..2b2300a
--- /dev/null
+++ b/Source/mesquite/treefarm/lib/SourceModifiedTree.java
@@ -0,0 +1,90 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.treefarm.lib;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public abstract class SourceModifiedTree extends TreeSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of of a current tree.",
+		"The source of trees can be selected initially");
+	}
+	OneTreeSource currentTreeSource;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		currentTreeSource = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree to be modified");
+ 		if (currentTreeSource == null) {
+ 			return sorry(getName() + " couldn't start because no source of a current tree to serve as a basis for modification was obtained.");
+ 		}
+ 		if (currentTreeSource.getUltimateSource() == this)
+ 			return sorry(getName() + " couldn't start because it would be attempting to modify its own trees, resulting in an infinite recursion.");
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 	iQuit();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) { 
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSource ", currentTreeSource); 
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	 if (checker.compare(this.getClass(), "Sets the source of the tree to be modified", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of tree to be modified", currentTreeSource);
+			if (temp !=null){
+				currentTreeSource = temp;
+				parametersChanged();
+    	 			return currentTreeSource;
+    	 		}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+ 		if (currentTreeSource.getUltimateSource() == this && !MesquiteThread.isScripting()) {
+ 			alert("A tree modifier had to quit because it would be attempting to modify its own trees, resulting in an infinite recursion.");
+ 			iQuit();
+ 		}
+   		if (currentTreeSource!=null)
+   			currentTreeSource.initialize(taxa);
+   	}
+	/*.................................................................................................................*/
+	protected Tree getBasisTree(Taxa taxa){
+   		Tree t =  currentTreeSource.getTree(taxa);
+ 		if (currentTreeSource.getUltimateSource() == this && !MesquiteThread.isScripting()) {
+ 			alert("A tree modifier had to quit because it would be attempting to modify its own trees, resulting in an infinite recursion.");
+ 			iQuit();
+ 			return null;
+ 		}
+ 		return t;
+	}
+	/*.................................................................................................................*/
+	protected OneTreeSource getBasisTreeSource(){
+   		return currentTreeSource;
+	}
+}
+
diff --git a/Source/mesquite/trees/AddTaxaToTree/AddTaxaToTree.java b/Source/mesquite/trees/AddTaxaToTree/AddTaxaToTree.java
new file mode 100644
index 0000000..b4b36dd
--- /dev/null
+++ b/Source/mesquite/trees/AddTaxaToTree/AddTaxaToTree.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.AddTaxaToTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AddTaxaToTree extends TreeAlterer {
+	public String getName() {
+		return "Add Taxa To Tree";
+	}
+	public String getExplanation() {
+		return "To a tree with some taxa excluded, adds taxa." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		Taxa taxa = tree.getTaxa();
+		//counting how many excluded
+		int count = 0;
+		for (int i=0; i< taxa.getNumTaxa(); i++){
+			if (!tree.taxonInTree(i))
+				count++;
+		}
+		if (count == 0) {
+			discreetAlert( "The tree contains all of the taxa available in the block of taxa.  There are none available to be added");
+			return true;
+		}
+		//getting list of excluded
+		ListableVector excluded = new ListableVector(count);
+		count = 0;
+		for (int i=0; i< taxa.getNumTaxa(); i++){
+			if (!tree.taxonInTree(i)) {
+				excluded.addElement(taxa.getTaxon(i), false);
+			}
+		}
+
+		//presenting choice
+		Listable[] toInclude = ListDialog.queryListMultiple(containerOfModule(), "Add taxa to tree", "Select taxa to be added to the tree", MesquiteString.helpString,"Add", false, excluded, null);
+		if (toInclude == null || toInclude.length ==0)
+			return true;
+
+		for (int i=0; i<toInclude.length; i++){
+			int taxon = taxa.whichTaxonNumber((Taxon)toInclude[i]);
+			tree.graftTaxon(taxon, tree.getRoot(), false);
+		}
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+		return true;
+	}
+}
+
diff --git a/Source/mesquite/trees/AllBranchLengthsOne/AllBranchLengthsOne.java b/Source/mesquite/trees/AllBranchLengthsOne/AllBranchLengthsOne.java
new file mode 100644
index 0000000..6f7fe0c
--- /dev/null
+++ b/Source/mesquite/trees/AllBranchLengthsOne/AllBranchLengthsOne.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.AllBranchLengthsOne;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AllBranchLengthsOne extends BranchLengthsAltererMult {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "All Branch Lengths to 1.0";
+	}
+	public String getExplanation() {
+		return "Assigns a value of 1.0 for branch length for all of a tree's branches." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree instanceof MesquiteTree) {
+			((MesquiteTree)tree).setAllBranchLengths(1.0, false);
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+
+			return true;
+		}
+		return false;
+
+	}
+}
+
diff --git a/Source/mesquite/trees/AllUnassignBrLengths1/AllUnassignBrLengths1.java b/Source/mesquite/trees/AllUnassignBrLengths1/AllUnassignBrLengths1.java
new file mode 100644
index 0000000..100cfd8
--- /dev/null
+++ b/Source/mesquite/trees/AllUnassignBrLengths1/AllUnassignBrLengths1.java
@@ -0,0 +1,60 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.AllUnassignBrLengths1;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class AllUnassignBrLengths1 extends BranchLengthsAltererMult {
+	public String getName() {
+		return "All Unassigned Branch Lengths to 1.0";
+	}
+	public String getExplanation() {
+		return "Assigns a value of 1.0 for branch length for all of a tree's branches that have not yet had a branch length assigned." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree instanceof MesquiteTree) {
+			//((MesquiteTree)tree).doCommand("setAllUnassignedBranchLengths", "1.0", CommandChecker.defaultChecker);
+			((MesquiteTree)tree).setAllUnassignedBranchLengths(1.0, false);
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+
+			return true;
+		}
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/trees/AlterLengths/AlterLengths.java b/Source/mesquite/trees/AlterLengths/AlterLengths.java
new file mode 100644
index 0000000..211e6b0
--- /dev/null
+++ b/Source/mesquite/trees/AlterLengths/AlterLengths.java
@@ -0,0 +1,106 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.AlterLengths;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class AlterLengths extends TreeListUtility { 
+    	 public String getName() {
+		return "Alter Branch Lengths";
+   	 }
+   	 public String getExplanation() {
+		return "Alters branch lengths of selected trees.";
+   	 }
+ 	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BranchLengthsAltererMult.class, getName() + "  needs a method to alter branch lengths.",
+		"The method to alter branch lengths can be chosen from the Alter Branch Lengths submenu");
+	}
+	BranchLengthsAltererMult alterTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+ 		if (arguments ==null)
+			alterTask = (BranchLengthsAltererMult)hireEmployee(BranchLengthsAltererMult.class, "Module to alter branch lengths");
+	 	else {
+			alterTask = (BranchLengthsAltererMult)hireNamedEmployee(BranchLengthsAltererMult.class, arguments);
+ 			if (alterTask == null)
+				alterTask = (BranchLengthsAltererMult)hireEmployee(BranchLengthsAltererMult.class, "Module to alter branch lengths");
+ 		}
+ 		if (alterTask == null) {
+ 			return sorry(getName() + " couldn't start because no branch lengths alterer was obtained.");
+ 		}
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return BranchLengthsAltererMult.class;
+	}
+	
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public boolean operateOnTrees(TreeVector trees){
+   		if (trees == null)
+   			return false;
+   		Taxa taxa = trees.getTaxa();
+   		int numTrees = trees.size();
+   		boolean doAll = !trees.anySelected();
+   		log("\nAltering Branch Lengths ");
+   		int dotFreq = 1;
+   		if (numTrees >100 && numTrees<500)
+   			dotFreq=5;
+   		else if (numTrees>500)
+   			dotFreq=10;
+
+
+		
+		for (int j=0; j<numTrees; j++){
+			if (doAll || trees.getSelected(j)){
+				Tree tree = trees.getTree(j);
+				if (tree!=null && tree instanceof MesquiteTree) {
+					CommandRecord.tick("Altering tree " + j + " of " + numTrees);
+			   		if (j % dotFreq == 0)
+			   			log(".");
+ 					boolean success = alterTask.transformTree((MesquiteTree)tree, null, false);
+ 				}
+			}
+		}
+			trees.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+			
+		
+		return true;
+		
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/trees/AlterTrees/AlterTrees.java b/Source/mesquite/trees/AlterTrees/AlterTrees.java
new file mode 100644
index 0000000..4448e6c
--- /dev/null
+++ b/Source/mesquite/trees/AlterTrees/AlterTrees.java
@@ -0,0 +1,104 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.AlterTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lists.lib.*;
+
+/* ======================================================================== */
+public class AlterTrees extends TreeListUtility { 
+    	 public String getName() {
+		return "Alter Trees";
+   	 }
+   	 public String getExplanation() {
+		return "Alters selected trees.";
+   	 }
+ 	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeAltererMult.class, getName() + "  needs a method to alter trees.",
+		"The method to alter trees is selected initially.");
+	}
+	/*.................................................................................................................*/
+	TreeAltererMult alterTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+ 		if (arguments ==null)
+			alterTask = (TreeAltererMult)hireEmployee(TreeAltererMult.class, "Module to alter trees");
+	 	else {
+			alterTask = (TreeAltererMult)hireNamedEmployee(TreeAltererMult.class, arguments);
+ 			if (alterTask == null)
+				alterTask = (TreeAltererMult)hireEmployee(TreeAltererMult.class, "Module to alter trees");
+ 		}
+ 		if (alterTask == null) {
+ 			return sorry(getName() + " couldn't start because no tree alterer was obtained.");
+ 		}
+		return true;
+	}
+	
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return TreeAltererMult.class;
+	}
+	
+   	/** if returns true, then requests to remain on even after operateData is called.  Default is false*/
+   	public boolean pleaseLeaveMeOn(){
+   		return false;
+   	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean isPrerelease(){
+   		return false;
+   	}
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+   	/** Called to operate on the data in all cells.  Returns true if data altered*/
+   	public boolean operateOnTrees(TreeVector trees){
+   		if (trees == null)
+   			return false;
+   		Taxa taxa = trees.getTaxa();
+   		int numTrees = trees.size();
+   		boolean doAll = !trees.anySelected();
+   		log("\nAltering Trees ");
+   		int dotFreq = 1;
+   		if (numTrees >100 && numTrees<500)
+   			dotFreq=5;
+   		else if (numTrees>500)
+   			dotFreq=10;
+		for (int j=0; j<numTrees; j++){
+			if (doAll || trees.getSelected(j)){
+				Tree tree = trees.getTree(j);
+
+				if (tree!=null && tree instanceof MesquiteTree)  {
+					CommandRecord.tick("Altering tree " + j + " of " + numTrees);
+			   		if (j % dotFreq == 0)
+			   			log(".");
+					boolean success = alterTask.transformTree((MesquiteTree)tree, null, false);
+ 				}
+			}
+		}
+		logln("");
+		trees.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+		return true;
+		
+	}
+}
+
+
+	
+
+
diff --git a/Source/mesquite/trees/ArcTree/ArcTree.java b/Source/mesquite/trees/ArcTree/ArcTree.java
new file mode 100644
index 0000000..308cdee
--- /dev/null
+++ b/Source/mesquite/trees/ArcTree/ArcTree.java
@@ -0,0 +1,552 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite is distributed under the terms of the GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ArcTree;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+import java.awt.geom.*;
+/* ======================================================================== */
+public class ArcTree extends DrawTree {
+	public String getName() {
+		return "Curvogram";
+	}
+	public String getExplanation() {
+		return "Draws trees with curved branches (as PHYLIP's 'Curvogram')." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsVH.class, getName() + "  needs the locations of nodes to be calculated.",
+				"The calculator for node locations is chosen automatically or initially");
+	}
+	/*.................................................................................................................*/
+
+	NodeLocsVH nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteString orientationName;
+	Vector drawings;
+	int oldEdgeWidth = 8;
+	int ornt;
+	MesquiteString nodeLocsName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsVH)hireNamedEmployee(NodeLocsVH.class, "#NodeLocsStandard");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node locator module was obtained");
+
+		nodeLocsName = new MesquiteString(nodeLocsTask.getName());
+		if (numModulesAvailable(NodeLocsVH.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Locations Calculator", makeCommand("setNodeLocs", this), NodeLocsVH.class);
+			mss.setSelected(nodeLocsName);
+		}
+		drawings = new Vector();
+		orientationName = new MesquiteString("Up");
+		ornt = TreeDisplay.UP;
+		MesquiteSubmenuSpec orientationSubmenu = addSubmenu(null, "Orientation");
+		orientationSubmenu.setSelected(orientationName);
+		addItemToSubmenu(null, orientationSubmenu, "Up", makeCommand("orientUp",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Right", makeCommand("orientRight",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Down", makeCommand("orientDown",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Left", makeCommand("orientLeft",  this));
+
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		return true;
+
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		ArcTreeDrawing treeDrawing =  new ArcTreeDrawing (treeDisplay, numTaxa, this);
+		if (legalOrientation(treeDisplay.getOrientation())){
+			orientationName.setValue(orient(treeDisplay.getOrientation()));
+			ornt = treeDisplay.getOrientation();
+		}
+		else
+			treeDisplay.setOrientation(ornt);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	public boolean legalOrientation (int orientation){
+		return (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN || orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT);
+	}
+
+	public String orient (int orientation){
+		if (orientation == TreeDisplay.UP)
+			return "Up";
+		else if (orientation == TreeDisplay.DOWN)
+			return "Down";
+		else if (orientation == TreeDisplay.RIGHT)
+			return "Right";
+		else if (orientation == TreeDisplay.LEFT)
+			return "Left";
+		else return "other";
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNodeLocs", nodeLocsTask);
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		if (ornt== TreeDisplay.UP)
+			temp.addLine("orientUp"); 
+		else if (ornt== TreeDisplay.DOWN)
+			temp.addLine("orientDown"); 
+		else if (ornt== TreeDisplay.LEFT)
+			temp.addLine("orientLeft"); 
+		else if (ornt== TreeDisplay.RIGHT)
+			temp.addLine("orientRight"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the node locations calculator", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsVH temp = (NodeLocsVH)replaceEmployee(NodeLocsVH.class, arguments, "Node Locations Calculator", nodeLocsTask);
+			if (temp != null) {
+				nodeLocsTask = temp;
+				nodeLocsName.setValue(nodeLocsTask.getName());
+				parametersChanged();
+			}
+			return nodeLocsTask;
+		}
+		else 	if (checker.compare(this.getClass(), "Sets the width of lines for drawing the tree", "[width in pixels]", commandName, "setEdgeWidth")) {
+
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, 99);
+			if (newWidth>0 && newWidth<100 && newWidth!=oldEdgeWidth) {
+				oldEdgeWidth=newWidth;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					ArcTreeDrawing treeDrawing = (ArcTreeDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+					treeDrawing.treeDisplay.setMinimumTaxonNameDistance(newWidth, 6); 
+				}
+				if ( !MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Returns the employee module that assigns node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are on top", null, commandName, "orientUp")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ArcTreeDrawing treeDrawing = (ArcTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.UP);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at the bottom", null, commandName, "orientDown")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ArcTreeDrawing treeDrawing = (ArcTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.DOWN);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at right", null, commandName, "orientRight")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ArcTreeDrawing treeDrawing = (ArcTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.RIGHT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at left", null, commandName, "orientLeft")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				ArcTreeDrawing treeDrawing = (ArcTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.LEFT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
+/* ======================================================================== */
+class ArcTreeDrawing extends TreeDrawing  {
+
+	private int lastleft;
+	private int taxspacing;
+	public int highlightedBranch, branchFrom;
+	public int xFrom, yFrom, xTo, yTo;
+	public ArcTree ownerModule;
+	public int edgewidth = 8;
+	public int preferredEdgeWidth = 8;
+	int oldNumTaxa = 0;
+	public static final int inset=2;
+	private boolean ready=false;
+	BasicStroke defaultStroke;
+
+	private int foundBranch;
+
+	public ArcTreeDrawing (TreeDisplay treeDisplay, int numTaxa, ArcTree ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		treeDisplay.setMinimumTaxonNameDistance(edgewidth, 6); //better if only did this if tracing on
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		try{
+			defaultStroke = new BasicStroke();
+		}
+		catch (Throwable t){
+		}
+		ready = true;
+		treeDisplay.setOrientation(ownerModule.nodeLocsTask.getDefaultOrientation());
+	}
+
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node] = y[tree.motherOfNode(node)];
+		lineBaseX[node] =  x[tree.motherOfNode(node)];
+	}
+
+	public int getBranchCenterX(int node){
+		int bX =lineBaseX[node];
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT)
+			return (bX-x[node])/3 + x[node];
+		else 
+			return x[node]; 
+	}
+	public int getBranchCenterY(int node){
+		int bY = lineBaseY[node];
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT)
+			return y[node];
+		else 
+			return (bY-y[node])/3 + y[node];
+	}
+	/*_________________________________________________*/
+	private void calcBranchStuff(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		calculateLines(tree, drawnRoot);
+		edgewidth = preferredEdgeWidth;
+		if (treeDisplay.getTaxonSpacing()<edgewidth+2) {
+			edgewidth= treeDisplay.getTaxonSpacing()-2;
+			if (edgewidth<2)
+				edgewidth=2;
+		}
+	}
+
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		Color tC = g.getColor();
+		if (flip)
+			g.setColor(Color.yellow);
+		else
+			g.setColor(Color.blue);
+
+		if (treeDisplay.getOrientation()==TreeDisplay.DOWN || treeDisplay.getOrientation()==TreeDisplay.UP){
+			g.fillOval(x[node]-4, y[node], 8, 8);
+		}
+		else {
+			g.fillOval(x[node], y[node]-4, 8,8);
+		}
+
+		g.setColor(tC);
+	}
+	/*_________________________________________________*/
+	private   void drawClade(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(treeDisplay.getBranchColor(node));
+			if (tree.getRooted() || tree.getRoot()!=node) {
+				DrawTreeUtil.drawOneCurvedBranch(treeDisplay, x, y, getEdgeWidth(), tree, g, node, 0, edgewidth,0, emphasizeNodes(), nodePoly(node), defaultStroke);
+			}
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawClade( tree, g, thisSister);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			g.setColor(treeDisplay.branchColor);
+			drawClade(tree, g, drawnRoot);  
+		}
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			calcBranchStuff(tree, getDrawnRoot());
+		}
+	}
+	/*_________________________________________________*/
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		int ew = edgewidth;
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]-ew-3 && yPos < y[node]-3;
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) 
+				return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]+2 && yPos < y[node]+ew+2;
+				else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) 
+					return xPos> x[node]+1 && xPos < x[node]+ew +1 && yPos > y[node] && yPos < y[node] + ew;
+					else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT) 
+						return xPos> x[node]-ew-3 && xPos < x[node]-3 && yPos > y[node] && yPos < y[node] + ew;
+						else 
+							return xPos> x[node] && xPos < x[node]+ew && yPos > y[node] && yPos < y[node] + ew;
+	}
+
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		Rectangle box;
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+			box = new Rectangle(x[node], y[node]-edgewidth/2-2, edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 0, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 180);
+			g.drawLine(box.x, box.y+ edgewidth/2, box.x+edgewidth,  box.y+ edgewidth/2);
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+			box = new Rectangle(x[node], y[node] + 2, edgewidth, edgewidth);
+			g.fillArc(box.x, box.y -  box.height/2, box.width, box.height, 180, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y -  box.height/2, box.width, box.height, 180, 180);
+			g.drawLine(box.x, box.y , box.x+edgewidth,  box.y);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			box = new Rectangle(x[node] + 2, y[node], edgewidth, edgewidth);
+			g.fillArc(box.x- box.width/2, box.y, box.width, box.height, 270, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x- box.width/2, box.y, box.width, box.height, 270, 180);
+			g.drawLine(box.x, box.y, box.x ,  box.y+edgewidth);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+			box = new Rectangle(x[node]-edgewidth/2-2, y[node], edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 90, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 90, 180);
+			g.drawLine(box.x+edgewidth/2, box.y, box.x+edgewidth/2,  box.y+edgewidth);
+		}
+		else {
+			box = new Rectangle(x[node], y[node], edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 0, 360);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 360);
+		}
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		Rectangle box;
+		int numColors = colors.getNumColors();
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+			box = new Rectangle(x[node], y[node]-edgewidth/2-2, edgewidth, edgewidth);
+			for (int i=0; i<numColors; i++) {
+				g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+				g.fillArc(box.x, box.y, box.width, box.height, 0+ (i*180/numColors), 180- (i*180/numColors));
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 180);
+			g.drawLine(box.x, box.y+ edgewidth/2, box.x+edgewidth,  box.y+ edgewidth/2);
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+			box = new Rectangle(x[node], y[node] + 2, edgewidth, edgewidth);
+			for (int i=0; i<numColors; i++) {
+				g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+				g.fillArc(box.x, box.y -  box.height/2, box.width, box.height, 180+ (i*180/numColors), 180- (i*180/numColors));
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y -  box.height/2, box.width, box.height, 180, 180);
+			g.drawLine(box.x, box.y , box.x+edgewidth,  box.y);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			box = new Rectangle(x[node] + 2, y[node], edgewidth, edgewidth);
+			for (int i=0; i<numColors; i++) {
+				g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+				g.fillArc(box.x- box.width/2, box.y, box.width, box.height, 270+ (i*180/numColors), 180- (i*180/numColors));
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x- box.width/2, box.y, box.width, box.height, 270, 180);
+			g.drawLine(box.x, box.y, box.x ,  box.y+edgewidth);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+			box = new Rectangle(x[node]-edgewidth/2-2, y[node], edgewidth, edgewidth);
+			for (int i=0; i<numColors; i++) {
+				g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+				g.fillArc(box.x, box.y, box.width, box.height, 90+ (i*180/numColors), 180- (i*180/numColors));
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 90, 180);
+			g.drawLine(box.x+edgewidth/2, box.y, box.x+edgewidth/2,  box.y+edgewidth);
+		}
+		else {
+			box = new Rectangle(x[node], y[node], edgewidth, edgewidth);
+			for (int i=0; i<numColors; i++) {
+				g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+				g.fillArc(box.x, box.y, box.width, box.height, 0, 360);
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 360);
+		}
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			Color c = g.getColor();
+			int fillWidth = edgewidth-2*inset;
+			int numColors = colors.getNumColors();
+			for (int i=0; i<numColors; i++) {
+				Color color;
+				if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+					g.setColor(color);
+				//			public static   void drawOneBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, Graphics g, int node, int start, int width, int adj, boolean emphasizeNodes, Polygon nodePoly, BasicStroke defaultStroke) {
+
+				DrawTreeUtil.drawOneCurvedBranch(treeDisplay,x,y,getEdgeWidth(), treeDisplay.getTree(), g, node, inset + i*fillWidth/numColors,  (i+1)*fillWidth/numColors -i*fillWidth/numColors, 4,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			DrawTreeUtil.drawOneCurvedBranch(treeDisplay,x,y,getEdgeWidth(), tree, g, node, inset, edgewidth-inset*2, 4,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+		}
+	}
+
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int doubleOffset = (getNodeWidth()-getEdgeWidth());
+		int startX = x[node] - offset;
+		int startY= y[node] - offset;
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT){
+			startX -= getNodeWidth()-doubleOffset;
+		} else if (treeDisplay.getOrientation()==TreeDisplay.DOWN)
+			startY -= getNodeWidth()-doubleOffset;
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(startX,startY);
+		poly.addPoint(startX+getNodeWidth(),startY);
+		poly.addPoint(startX+getNodeWidth(),startY+getNodeWidth());
+		poly.addPoint(startX,startY+getNodeWidth());
+		poly.addPoint(startX,startY);
+		poly.npoints=5;
+		return poly;
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (DrawTreeUtil.inBranch(treeDisplay, this.x, this.y, getEdgeWidth(), tree, node, x,y) || inNode(node,x,y)){
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							if (treeDisplay.getOrientation()==TreeDisplay.UP|| treeDisplay.getOrientation()==TreeDisplay.DOWN)  {
+								fraction.setValue( Math.abs(1.0*(y-this.y[motherNode])/(this.y[node]-this.y[motherNode])));
+							}
+							else if (treeDisplay.getOrientation()==TreeDisplay.LEFT || treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+								fraction.setValue( Math.abs(1.0*(x-this.x[motherNode])/(this.x[node]-this.x[motherNode])));
+							}
+						}
+					}
+			}
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				ScanBranches(tree, thisSister, x, y, fraction);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, drawnRoot, x, y, fraction);
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+		preferredEdgeWidth = edw;
+	}
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+}
+
+
diff --git a/Source/mesquite/trees/AverageTreeValue/AverageTreeValue.java b/Source/mesquite/trees/AverageTreeValue/AverageTreeValue.java
new file mode 100644
index 0000000..22535d9
--- /dev/null
+++ b/Source/mesquite/trees/AverageTreeValue/AverageTreeValue.java
@@ -0,0 +1,126 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.AverageTreeValue;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class AverageTreeValue extends NumberForTreeBlock {
+	public String getName() {
+		return "Average Tree Value";
+	}
+	public String getVeryShortName() {
+		if (treeValueTask==null)
+			return getName();
+		return "Average " + treeValueTask.getName();
+	}
+	public String getExplanation() {
+		return "Calculates the average of some value for trees in a tree block." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + "  needs a method to calculate values for the trees.",
+		"The method to calculate values can be selected initially or from the Values submenu");
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber average;
+	MesquiteNumber treeValue;
+	NumberForTree treeValueTask;
+	Taxa oldTaxa = null;
+	MesquiteString charSourceName;
+	MesquiteCommand mc;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeValue=new MesquiteNumber();
+		average=new MesquiteNumber();
+		treeValueTask = (NumberForTree)hireEmployee(NumberForTree.class, "Value to calculate for trees");
+		if (treeValueTask == null)
+			return sorry(getName() + " couldn't start because no calculator module was obtained");
+		mc =makeCommand("setCalculator",  this);
+		treeValueTask.setHiringCommand(mc);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Values", mc);//TODO: checkmark
+
+		mss.setList(NumberForTree.class);
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void initialize(TreeVector trees) {
+		treeValueTask.initialize(trees.getTree(0));
+	}
+	/*.................................................................................................................*/
+	public void calculateNumber(TreeVector trees, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		average.setValue((int)0);
+		int count = 0;
+		MesquiteNumber tl = new MesquiteNumber();
+		for (int itr = 0; itr<trees.size(); itr++) {
+			Tree tree = trees.getTree(itr);
+			tl.setToUnassigned();
+			treeValueTask.calculateNumber(tree, tl, null);
+			if (tl.isCombinable()) {
+				average.add(tl);
+				count++;
+			}
+		}
+		average.divideBy(count);
+		result.setValue(average);
+		if (resultString!=null)
+			resultString.setValue("Average "+ treeValueTask.getName() + ": " + average.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setCalculator ", treeValueTask);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module to calculate numbers for the trees", "[name of module]", commandName, "setCalculator")) {
+			NumberForTree temp =   (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Which value to calculate?", treeValueTask);
+			if (temp!=null) {
+				treeValueTask = temp;
+				treeValueTask.setHiringCommand(mc);
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (treeValueTask==null)
+			return null;
+		return "Average for " + treeValueTask.getName();
+	}
+}
+
diff --git a/Source/mesquite/trees/BLFromNodeAgeConstraints/BLFromNodeAgeConstraints.java b/Source/mesquite/trees/BLFromNodeAgeConstraints/BLFromNodeAgeConstraints.java
new file mode 100644
index 0000000..aaf7ed6
--- /dev/null
+++ b/Source/mesquite/trees/BLFromNodeAgeConstraints/BLFromNodeAgeConstraints.java
@@ -0,0 +1,138 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.trees.BLFromNodeAgeConstraints;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class BLFromNodeAgeConstraints extends BranchLengthsAltererMult {
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		double[] minAges = new double[tree.getNumNodeSpaces()];
+		double[] maxAges = new double[tree.getNumNodeSpaces()];
+		setByDeepest(tree, tree.getRoot(), minAges, maxAges);
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	NameReference nodeAgeConstrRef = NameReference.getNameReference("nodeAgeConstraints");
+	void getConstraint(Tree tree, int node, MesquiteDouble min, MesquiteDouble max){
+		min.setToUnassigned();
+		max.setToUnassigned();
+		String constraint = (String)tree.getAssociatedObject(nodeAgeConstrRef, node);
+		// one number: fixed age
+		// 0-max
+		// min+
+		// min-max
+		if (!StringUtil.blank(constraint)){
+			String token = parser.getFirstToken(constraint);
+			double first = MesquiteDouble.fromString(token);
+			double second = MesquiteDouble.unassigned;
+			if (!MesquiteDouble.isCombinable(first)) {
+				return;
+			}
+			token = parser.getNextToken();
+			if (StringUtil.blank(token))
+				second = first;
+			else {
+				if (token.equals("+"))
+					second = MesquiteDouble.infinite;
+				else if (token.equals("-")){
+					token = parser.getNextToken();
+					if (StringUtil.blank(token))
+						second = MesquiteDouble.infinite;
+					else {
+						second = MesquiteDouble.fromString(token);
+						if (!MesquiteDouble.isCombinable(second))
+							second = MesquiteDouble.infinite;
+					}
+				}
+			}
+			min.setValue(first);
+			max.setValue(second);
+		}
+	}
+	/*.................................................................................................................*/
+	private void setByDeepest(AdjustableTree tree, int node, double[] minAges, double[] maxAges){
+		MesquiteDouble min = new MesquiteDouble();
+		MesquiteDouble max = new MesquiteDouble();
+		getConstraint(tree, node, min, max);
+		minAges[node] = min.getValue();
+		maxAges[node] = max.getValue();
+		if (tree.nodeIsTerminal(node) && !MesquiteDouble.isCombinable(minAges[node])  && !MesquiteDouble.isCombinable(maxAges[node])) {
+			minAges[node] = 0;
+			maxAges[node] = 0;
+		}
+		double maxDepth = 0;
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			setByDeepest(tree, daughter, minAges, maxAges);
+			if (maxDepth<minAges[daughter])  //minages push down
+				maxDepth = minAges[daughter];
+		}
+		if (tree.nodeIsInternal(node) && !MesquiteDouble.isCombinable(minAges[node])) {
+			double spacer = (1.0 + 1.0/tree.numberOfTerminalsInClade(node));
+			if (spacer > 1.1)
+				spacer = 1.1;
+			minAges[node] = maxDepth*spacer;
+		}
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			tree.setBranchLength(daughter, minAges[node] - minAges[daughter], false);
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Enforce Minimum Node Age Constraints";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Uses minimum node age constraints to set the branch lengths on the tree." ;
+	}
+	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 273;  
+	}
+
+}
diff --git a/Source/mesquite/trees/BallsNSticks/BallsNSticks.java b/Source/mesquite/trees/BallsNSticks/BallsNSticks.java
new file mode 100644
index 0000000..4c235c8
--- /dev/null
+++ b/Source/mesquite/trees/BallsNSticks/BallsNSticks.java
@@ -0,0 +1,789 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BallsNSticks;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+import java.awt.geom.*;
+
+/* ======================================================================== */
+public class BallsNSticks extends DrawTree {
+	public String getName() {
+		return "Balls & Sticks";
+	}
+
+	public String getExplanation() {
+		return "Draws trees with spots and the nodes and thin lines for branches." ;
+	}
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsVH.class, getName() + "  needs the locations of nodes to be calculated.",
+		"The calculator for node locations is chosen automatically or initially");
+	}
+	NodeLocsVH nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteString orientationName, lineStyleName;
+	Vector drawings;
+	int oldEdgeWidth = 2;
+	int oldSpotSize = 22;
+	int ornt, style;
+	static final int DIAGONAL = 0;
+	static final int SQUARE = 1;
+	static final int CURVED = 2;
+	public MesquiteBoolean cosmic = new MesquiteBoolean(false);
+	public MesquiteBoolean ballsInternal = new MesquiteBoolean(true);
+	MesquiteSubmenuSpec orientationSubmenu;
+	MesquiteSubmenuSpec lineStyleSubmenu;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsVH)hireEmployee(NodeLocsVH.class, "Calculator of node locations");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node location module was obtained.");
+		drawings = new Vector();
+		//addMenuItem("Display", "Edge width...", makeCommand("edgeWidth"));
+		defineMenus(false);
+		ornt = NodeLocsVH.defaultOrientation;  //should take out of preferences
+		orientationName = new MesquiteString(orient(ornt));
+		orientationSubmenu.setSelected(orientationName);
+		lineStyleName = new MesquiteString("Diagonal");
+		style = DIAGONAL;
+		lineStyleSubmenu.setSelected(lineStyleName);
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public void defineMenus(boolean accumulating){
+		orientationSubmenu = addSubmenu(null, "Orientation");
+		addItemToSubmenu(null, orientationSubmenu, "Up", makeCommand("orientUp",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Right", makeCommand("orientRight",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Down", makeCommand("orientDown",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Left", makeCommand("orientLeft",  this));
+		lineStyleSubmenu = addSubmenu(null, "Line Style");
+		addItemToSubmenu(null, lineStyleSubmenu, "Diagonal", makeCommand("useDiagonal",  this));
+		addItemToSubmenu(null, lineStyleSubmenu, "Square", makeCommand("useSquare",  this));
+		addItemToSubmenu(null, lineStyleSubmenu, "Curved", makeCommand("useCurved",  this));
+		//		addCheckMenuItem( null, "Curved Lines", makeCommand("toggleArc",  this), useArc);
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		addMenuItem( "Preferred Spot Size...", makeCommand("setSpotDiameter",  this));
+		addCheckMenuItem( null, "Balls On Internal Nodes", makeCommand("toggleBallsInternal",  this), ballsInternal);
+		addCheckMenuItem( null, "Cosmic", makeCommand("toggleCosmic",  this), cosmic);
+	}
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		BallsNSticksDrawing treeDrawing =  new BallsNSticksDrawing (treeDisplay, numTaxa, this);
+		if (legalOrientation(treeDisplay.getOrientation())){
+			orientationName.setValue(orient(treeDisplay.getOrientation()));
+			ornt = treeDisplay.getOrientation();
+		}
+		else
+			treeDisplay.setOrientation(ornt);
+		drawings.addElement(treeDrawing);
+		//	treeDisplay.inhibitStretchByDefault = false;
+		return treeDrawing;
+	}
+	public boolean legalOrientation (int orientation){
+		return (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN || orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT);
+	}
+	/*.................................................................................................................
+ 	public void endJob() {
+ 		if (MesquiteTrunk.trackActivity) logln ("MesquiteModule " + getName() + "  closing down ");
+ 		//dtd.disposePolys(coordTask.treeDisplay.getTree(), coordTask.treeDisplay.getTree().getRoot());
+		closeDownAllEmployees (this);
+ 		employees.removeElement(nodeLocsTask);
+ 		nodeLocsTask= null;
+   	 }
+
+	/*.................................................................................................................*/
+	public String orient (int orientation){
+		if (orientation == TreeDisplay.UP)
+			return "Up";
+		else if (orientation == TreeDisplay.DOWN)
+			return "Down";
+		else if (orientation == TreeDisplay.RIGHT)
+			return "Right";
+		else if (orientation == TreeDisplay.LEFT)
+			return "Left";
+		else return "other";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setSpotDiameter " + oldSpotSize); 
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		if (ornt== TreeDisplay.UP)
+			temp.addLine("orientUp"); 
+		else if (ornt== TreeDisplay.DOWN)
+			temp.addLine("orientDown"); 
+		else if (ornt== TreeDisplay.LEFT)
+			temp.addLine("orientLeft"); 
+		else if (ornt== TreeDisplay.RIGHT)
+			temp.addLine("orientRight"); 
+		if (style== DIAGONAL)
+			temp.addLine("useDiagonal"); 
+		else if (style== SQUARE)
+			temp.addLine("useSquare"); 
+		else if (style== CURVED)
+			temp.addLine("useCurved"); 
+
+		temp.addLine("toggleBallsInternal " + ballsInternal.toOffOnString());
+		temp.addLine("toggleCosmic " + cosmic.toOffOnString());
+
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the diameter of the spots", "[diameter in pixels]", commandName, "setSpotDiameter")) {
+			int newDiameter= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newDiameter))
+				newDiameter = MesquiteInteger.queryInteger(containerOfModule(), "Set spot diameter", "Enter preferred diameter of spots at nodes.  This sets the preferred spot size; if there is not room in the drawing for spots so large, then the actual spot size may be smaller.", oldSpotSize, 6, 100);
+			if (newDiameter>=6 && newDiameter<100 && newDiameter!=oldSpotSize) {
+				Enumeration e = drawings.elements();
+				oldSpotSize = newDiameter;
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+					treeDrawing.spotSize=newDiameter;
+					treeDrawing.preferredSpotSize = newDiameter;
+					treeDrawing.treeDisplay.setMinimumTaxonNameDistance(0, treeDrawing.spotSize/2  + 4);
+				}
+				parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets how wide the branches of the tree are drawn", "[width in pixels]", commandName, "setEdgeWidth")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, 24);
+			if (newWidth>0 && newWidth<24 && newWidth!=oldEdgeWidth) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+				}
+				oldEdgeWidth = newWidth;
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not \"cosmic\" mode is on", "[on or off]", commandName, "toggleCosmic")) {
+			boolean current = cosmic.getValue();
+			cosmic.toggleValue(parser.getFirstToken(arguments));
+			if (current!=cosmic.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not balls are shown on internal nodes", "[on or off]", commandName, "toggleBallsInternal")) {
+			boolean current = ballsInternal.getValue();
+			ballsInternal.toggleValue(parser.getFirstToken(arguments));
+			if (current!=ballsInternal.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not arcs are to be used", "[on or off]", commandName, "toggleArc")) {
+			MesquiteBoolean useArc = new MesquiteBoolean(style == CURVED);  //here for compatibility with 1. 06 scripts
+			boolean current = useArc.getValue();
+			useArc.toggleValue(parser.getFirstToken(arguments));
+			if (useArc.getValue()){
+				style = CURVED;
+				lineStyleName.setValue("Curved");
+			}
+			if (current!=useArc.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets line style", null, commandName, "useDiagonal")) {
+			int current = style;
+			style = DIAGONAL;
+			lineStyleName.setValue("Diagonal");
+			if (current!=style)
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets line style", null, commandName, "useSquare")) {
+			int current = style;
+			style = SQUARE;
+			lineStyleName.setValue("Square");
+			if (current!=style)
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets line style", null, commandName, "useCurved")) {
+			int current = style;
+			style = CURVED;
+			lineStyleName.setValue("Curved");
+			if (current!=style)
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Returns the module employed to set the node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree so that the terminals are pointing up", null, commandName, "orientUp")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.UP);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree so that the terminals are pointing down", null, commandName, "orientDown")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.DOWN);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at right", null, commandName, "orientRight")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.RIGHT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at left", null, commandName, "orientLeft")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				BallsNSticksDrawing treeDrawing = (BallsNSticksDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.LEFT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+}
+
+/* ======================================================================== */
+
+/* ======================================================================== */
+class BallsNSticksDrawing extends TreeDrawing  {
+	public Polygon[] branchPoly;
+	public Polygon[] touchPoly;
+
+	public BallsNSticks ownerModule;
+	int spotSize;
+	int edgeWidth;
+	public int preferredSpotSize = 22;
+	int oldNumTaxa = 0;
+	public static final int inset=1;
+	private boolean ready=false;
+
+	private int foundBranch;
+	NameReference triangleNameRef;
+	BasicStroke defaultStroke;
+
+	public BallsNSticksDrawing (TreeDisplay treeDisplay, int numTaxa, BallsNSticks ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		triangleNameRef = NameReference.getNameReference("triangled");
+		this.ownerModule = ownerModule;
+		spotSize = ownerModule.oldSpotSize;
+		edgeWidth = ownerModule.oldEdgeWidth;
+		if (ownerModule.cosmic.getValue())
+			edgeWidth = 8;
+		try{
+			defaultStroke = new BasicStroke();
+		}
+		catch (Throwable t){
+		}
+		treeDisplay.setMinimumTaxonNameDistance(0, spotSize/2+ 4);
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		treeDisplay.setOrientation(ownerModule.nodeLocsTask.getDefaultOrientation());
+		ready = true;
+	}
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new Polygon[numNodes];
+		touchPoly= new Polygon[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new Polygon();
+			touchPoly[i] = new Polygon();
+		}
+	}
+	private boolean isUP(){
+		return treeDisplay.getOrientation()==TreeDisplay.UP;
+	}
+	private boolean isDOWN(){
+		return treeDisplay.getOrientation()==TreeDisplay.DOWN;
+	}
+	private boolean isLEFT(){
+		return treeDisplay.getOrientation()==TreeDisplay.LEFT;
+	}
+	private boolean isRIGHT(){
+		return treeDisplay.getOrientation()==TreeDisplay.RIGHT;
+	}
+
+	/*_________________________________________________*/
+	private void UPCalcBranchPolys(Tree tree, int node, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcBranchPolys(tree, d, polys, width);
+		if (ownerModule.style == BallsNSticks.DIAGONAL)
+			DrawTreeUtil.UPdefineDiagonalPoly(this,polys[node], width, tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		else
+			DrawTreeUtil.UPdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],0);
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcBranchPolys(Tree tree, int node, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcBranchPolys(tree, d, polys, width);
+		//DOWNdefinePoly(polys[node], width, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		if (ownerModule.style == BallsNSticks.DIAGONAL)
+			DrawTreeUtil.DOWNdefineDiagonalPoly(this,polys[node], width, tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		else
+			DrawTreeUtil.DOWNdefineSquarePoly(this,polys[node], width,(node==tree.getRoot()), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],0);
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcBranchPolys(Tree tree, int node, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcBranchPolys(tree, d, polys, width);
+		if (ownerModule.style == BallsNSticks.DIAGONAL)
+			DrawTreeUtil.RIGHTdefineDiagonalPoly(this,polys[node], width, tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		else
+			DrawTreeUtil.RIGHTdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],0);
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcBranchPolys(Tree tree, int node, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcBranchPolys(tree, d, polys, width);
+		if (ownerModule.style == BallsNSticks.DIAGONAL)
+			DrawTreeUtil.LEFTdefineDiagonalPoly(this,polys[node], width, tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		else
+			DrawTreeUtil.LEFTdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],0);
+	}
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		if (ownerModule.style == BallsNSticks.SQUARE) {
+			if (treeDisplay.getOrientation()==TreeDisplay.UP || treeDisplay.getOrientation()==TreeDisplay.DOWN){
+				lineBaseY[node]=y[tree.motherOfNode(node)];
+				lineBaseX[node]=x[node];
+			} else {
+				lineBaseY[node]=y[node];
+				lineBaseX[node]=x[tree.motherOfNode(node)];
+			}
+		} else {
+			lineBaseY[node]=y[tree.motherOfNode(node)];
+			lineBaseX[node]=x[tree.motherOfNode(node)];
+		}
+	}
+	/*_________________________________________________*/
+	private void calcBranchPolys(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		calculateLines(tree, drawnRoot);
+		spotSize = preferredSpotSize;
+		if (treeDisplay.getTaxonSpacing()<spotSize+2) {
+			spotSize= treeDisplay.getTaxonSpacing()-2;
+			if (spotSize<2)
+				spotSize=2;
+		}
+		treeDisplay.setMinimumTaxonNameDistance(0, spotSize/2+ 4);
+		if (treeDisplay.getTaxonSpacing()<edgeWidth+2) {
+			edgeWidth = treeDisplay.getTaxonSpacing()-2;
+			if (edgeWidth<2)
+				edgeWidth =2;
+		}
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+			UPCalcBranchPolys(tree, drawnRoot, branchPoly, getEdgeWidth());
+			UPCalcBranchPolys(tree, drawnRoot, touchPoly, getNodeWidth());
+		}
+
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+			DOWNCalcBranchPolys(tree, drawnRoot, branchPoly, getEdgeWidth());
+			DOWNCalcBranchPolys(tree, drawnRoot, touchPoly, getNodeWidth());
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			RIGHTCalcBranchPolys(tree, drawnRoot, branchPoly, getEdgeWidth());
+			RIGHTCalcBranchPolys(tree, drawnRoot, touchPoly, getNodeWidth());
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){
+			LEFTCalcBranchPolys(tree, drawnRoot, branchPoly, getEdgeWidth());
+			LEFTCalcBranchPolys(tree, drawnRoot, touchPoly, getNodeWidth());
+		}
+	}
+
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		if (tree.nodeIsInternal(node) && !ownerModule.ballsInternal.getValue())
+			return;
+		Color tC = g.getColor();
+		if (flip)
+			g.setColor(Color.red);
+		else
+			g.setColor(Color.blue);
+
+		for (int i=1; i<4; i++)
+			GraphicsUtil.drawOval(g, x[node]- spotSize/2 - 2 - i, y[node]- spotSize/2 - 2 - i, spotSize + 3 + i + i, spotSize + 3 + i + i);
+
+
+		g.setColor(tC);
+	}
+
+
+	/*_________________________________________________*/
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+
+		int mother = tree.motherOfNode(N);
+		if (ownerModule.style == BallsNSticks.SQUARE) {
+			if (treeDisplay.getOrientation()==TreeDisplay.UP){
+				xValue.setValue(x[N]);
+				yValue.setValue(y[mother]+(y[N]-y[mother])/2);
+				angle.setValue(-Math.PI/2.0);
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+				xValue.setValue(x[N]);
+				yValue.setValue(y[N]+(y[mother]-y[N])/2);
+				angle.setValue(Math.PI/2.0);
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.RIGHT){
+				xValue.setValue(x[mother]+(x[N]-x[mother])/2);
+				yValue.setValue(y[N]);
+				angle.setValue(0.0);
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.LEFT){
+				xValue.setValue(x[N]+(x[mother]-x[N])/2);
+				yValue.setValue(y[N]);
+				angle.setValue(Math.PI);
+			}
+		}
+		else if (ownerModule.style == BallsNSticks.CURVED){
+			xValue.deassignAllValues();
+			yValue.deassignAllValues();
+		}
+		else {
+			xValue.setValue(GraphicsUtil.xCenterOfLine(x[mother], y[mother], x[N], y[N]));
+			yValue.setValue(GraphicsUtil.yCenterOfLine(x[mother], y[mother], x[N], y[N]));
+			angle.setValue(GraphicsUtil.angleOfLine(x[mother], y[mother], x[N], y[N]));
+		}
+	}
+	/*_________________________________________________*/
+	private   void drawJustOneBranch(Tree tree, Graphics g, int node) {
+		g.setColor(treeDisplay.getBranchColor(node));
+		if (ownerModule.style == BallsNSticks.SQUARE) {
+			if (SHOWTOUCHPOLYS) {  //fordebugging
+				Color prev = g.getColor();
+				g.setColor(ColorDistribution.burlyWood);
+				g.fillPolygon(touchPoly[node]); 
+				g.setColor(prev);
+			}
+
+			g.fillPolygon(branchPoly[node]);  //TODO: no longer supports cosmic!
+		}
+		else if (ownerModule.style == BallsNSticks.CURVED)
+			DrawTreeUtil.drawOneCurvedBranch(treeDisplay, x, y, getEdgeWidth(), tree, g, node, 0, getEdgeWidth(),0, emphasizeNodes(), null, defaultStroke);
+
+		else {  //diagonal lines
+			if (SHOWTOUCHPOLYS) {  //fordebugging
+				Color prev = g.getColor();
+				g.setColor(ColorDistribution.burlyWood);
+				g.fillPolygon(touchPoly[node]); 
+				g.setColor(prev);
+			}
+			g.fillPolygon(branchPoly[node]);  //TODO: no longer supports cosmic!
+
+			// if (drawnRoot==node && tree.getRoot()!=node)
+			if (tree.numberOfParentsOfNode(node)>1) { //for reticulate trees
+				for (int i=1; i<=tree.numberOfParentsOfNode(node); i++) {
+					int anc =tree.parentOfNode(node, i);
+					if (anc!= tree.motherOfNode(node)) {
+						g.drawLine(x[node],y[node], x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]);
+						g.drawLine(x[node]+1,y[node], x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]);
+						g.drawLine(x[node],y[node]+1, x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]+1);
+						g.drawLine(x[node]+1,y[node]+1, x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]+1);
+					}
+				}
+			}
+		}
+		if (tree.getAssociatedBit(triangleNameRef,node)) {
+			for (int j=0; j<2; j++)
+				for (int i=0; i<2; i++) {
+					g.drawLine(x[node]+i,y[node]+j, x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j);
+					g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+					g.drawLine(x[node]+i,y[node]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+				}
+		}
+	}
+	/*_________________________________________________*/
+	private   void drawBranches(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			if (!tree.getAssociatedBit(triangleNameRef,node))
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					drawBranches( tree, g, d);
+			if (tree.getRooted() || tree.getRoot()!=node) {
+				drawJustOneBranch(tree,g,node);
+				if (!tree.nodeIsInternal(node) || ownerModule.ballsInternal.getValue()){
+					drawSpot( g, node);
+					if (emphasizeNodes()) {
+						Color prev = g.getColor();
+						g.setColor(Color.red);
+						drawSpot( g, node);
+						g.setColor(prev);
+					}
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			g.setColor(treeDisplay.branchColor);
+			drawBranches(tree, g, drawnRoot);  
+		}
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			calcBranchPolys(tree, getDrawnRoot());
+		}
+	}
+
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		if ((x-this.x[node])*(x-this.x[node]) + (y-this.y[node])*(y-this.y[node]) < spotSize*spotSize/4) //use radius
+			return true;
+		else
+			return false;
+		// ask if x, y is in node's spot    g.fillOval( x[node]- spotSize/2, y[node]- spotSize/2, spotSize, spotSize);
+	}
+	/*_________________________________________________*/
+	private void drawSpot(Graphics g, int node){
+		GraphicsUtil.fillOval(g, x[node]- spotSize/2, y[node]- spotSize/2, spotSize, spotSize, ownerModule.cosmic.getValue());
+	}
+	/*_________________________________________________*/
+	private void fillSpot(Graphics g, int node){
+		GraphicsUtil.fillOval(g, x[node]- spotSize/2 + 2, y[node]- spotSize/2 + 2, spotSize - 4, spotSize - 4, ownerModule.cosmic.getValue());
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		fillBranch(tree, node, g);
+		// need to show more informative terminal information
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		fillBranchWithColors(tree, node, colors, g);
+	}
+	/*_________________________________________________*/
+	private boolean ancestorIsTriangled(Tree tree, int node) {
+		if (!tree.nodeExists(node))
+			return false;
+		if (tree.getAssociatedBit(triangleNameRef, tree.motherOfNode(node)))
+			return true;
+		if (tree.getRoot() == node || tree.getSubRoot() == node)
+			return false;
+		return ancestorIsTriangled(tree, tree.motherOfNode(node));
+	}
+
+	/*_________________________________________________*
+	public void fillBranchWithMissingData(Tree tree, int node, Graphics g) {
+		
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node)) {
+			Color c = g.getColor();
+			if (g instanceof Graphics2D){
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setPaint(GraphicsUtil.missingDataTexture);
+			}
+			else
+				g.setColor(Color.lightGray);
+			GraphicsUtil.fillOval(g, x[node]- spotSize/2, y[node]- spotSize/2, spotSize, spotSize, false);
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node)) {
+			Color c = g.getColor();
+			int numColors = colors.getNumColors();
+			if (numColors==1){
+				g.setColor(colors.getColor(0, !tree.anySelected()|| tree.getSelected(node)));
+				if (!tree.nodeIsInternal(node) || ownerModule.ballsInternal.getValue())
+					fillSpot(g,node);
+			}
+			else if (numColors>0) {
+				int startAngle=90;//was 270
+				double totalFreq=0;
+				for (int i=0; i<numColors; i++) totalFreq += colors.getWeight(i);
+				int arcAngle = 0;
+				for (int i=0; i<numColors; i++) {
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+
+					arcAngle = (int)((colors.getWeight(i)/totalFreq)*360);
+					GraphicsUtil.fillArc(g, x[node]- spotSize/2 + 2, y[node]- spotSize/2 + 2, spotSize - 4, spotSize - 4, startAngle, arcAngle, ownerModule.cosmic.getValue());
+					startAngle+=arcAngle; 
+				}
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	/** Does the basic inverting of the color of a branch **/
+	public  void fillBranchInverted (Tree tree, int node, Graphics g) {
+		if (tree.nodeIsInternal(node) && !ownerModule.ballsInternal.getValue())
+			return;
+		if (GraphicsUtil.useXORMode(g, true))  {
+			g.setColor(Color.black);
+			g.setXORMode(Color.white);  //for some reason color makes no difference in MacOS, but is inversion color in Win95 
+			//GraphicsUtil.setToXOR(g);
+			GraphicsUtil.drawOval(g,x[node]- spotSize/2 + 2, y[node]- spotSize/2 + 2, spotSize - 4, spotSize - 4);
+			GraphicsUtil.drawOval(g,x[node]- spotSize/2 + 3, y[node]- spotSize/2 + 3, spotSize - 6, spotSize - 6);
+
+			g.setPaintMode();
+			g.setColor(Color.black);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node)) {
+			//drawJustOneBranch(tree,g,node);
+			if (!tree.nodeIsInternal(node) || ownerModule.ballsInternal.getValue())
+				fillSpot(g,node);
+		}
+	}
+
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		return inBranch(tree, touchPoly, node, xPos, yPos);
+	}
+	/*_________________________________________________*/
+	private boolean inBranch(Tree tree, Polygon[] polys, int node, int x, int y){
+		if (ownerModule.style == BallsNSticks.DIAGONAL||ownerModule.style == BallsNSticks.SQUARE) {
+			if (polys!=null && polys[node]!=null && polys[node].contains(x, y))
+				return true;
+		}
+		else  if (ownerModule.style == BallsNSticks.CURVED)
+			if (DrawTreeUtil.inBranch(treeDisplay, this.x, this.y, getEdgeWidth(), tree, node, x, y))
+				return true;
+
+		return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree,Polygon[] polys, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (inBranch(tree,polys,node,x,y) || inNode(node, x, y)) {
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							fraction.setValue(GraphicsUtil.fractionAlongLine(x, y, this.x[motherNode], this.y[motherNode], this.x[node], this.y[node],isRIGHT()||isLEFT(), isUP()||isDOWN()));
+						}
+					}
+
+			}
+			if (!tree.getAssociatedBit(triangleNameRef, node)) {
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					ScanBranches(tree, polys, d, x, y, fraction);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) {
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, branchPoly, drawnRoot, x, y, fraction);
+			if (foundBranch==0 && getEdgeWidth()<ACCEPTABLETOUCHWIDTH && ownerModule.style != BallsNSticks.CURVED)
+				ScanBranches(tree, touchPoly, drawnRoot, x, y, fraction);  //then scan through thicker versions
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgeWidth = edw;
+	}
+	/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgeWidth;
+	}
+	/*End new code Feb.22.07 oliver*/
+	/*_________________________________________________*/
+	public   void dispose() { 
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = null;
+			touchPoly[i] = null;
+		}
+		super.dispose();
+	}
+
+}
+
+
diff --git a/Source/mesquite/trees/BasicDrawTaxonNames/BasicDrawTaxonNames.java b/Source/mesquite/trees/BasicDrawTaxonNames/BasicDrawTaxonNames.java
new file mode 100644
index 0000000..f12a980
--- /dev/null
+++ b/Source/mesquite/trees/BasicDrawTaxonNames/BasicDrawTaxonNames.java
@@ -0,0 +1,996 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BasicDrawTaxonNames;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+
+/** Draws the taxon names in a tree drawing */
+public class BasicDrawTaxonNames extends DrawNamesTreeDisplay {
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Basic Draw Names for Tree Display";
+	}
+
+	public String getExplanation() {
+		return "Draws taxon names on a tree.  Chooses orientation of names according to orientation of tree." ;
+	}
+	/*.................................................................................................................*/
+
+
+	protected TreeDisplay treeDisplay;
+	protected TreeDrawing treeDrawing;
+	public TaxonPolygon[] namePolys;
+	protected TextRotator textRotator;
+	protected Tree tree;
+	protected Graphics gL;
+	protected int separation = 10;
+	protected Font currentFont = null;
+	protected String myFont = null;
+	protected int myFontSize = -1;
+	protected FontMetrics fm;
+	protected int rise;
+	protected int descent;
+	protected int oldNumTaxa=0;
+	protected MesquiteString fontSizeName, fontName;
+	protected MesquiteBoolean colorPartition, colorAssigned, shadePartition, showFootnotes;
+	/*New code added Feb.15.07 centerNodeLabels oliver*/ //TODO: delete new code comments
+	protected MesquiteBoolean showNodeLabels, showTaxonNames, centerNodeLabels; /*deleted centerNodeLables declaration Feb.26.07 oliver*/
+	/*end new code added Feb.15.07 oliver*/
+	protected MesquiteString fontColorName;
+	protected Color fontColor=Color.black;
+	protected Color fontColorLight = Color.gray;
+	protected NumberForTaxon shader = null;
+	protected int longestString = 0;
+	protected MesquiteMenuItemSpec offShadeMI = null;
+	/* New code added Feb.26.07 oliver*/ //TODO: delete new code comments
+	protected MesquiteMenuItemSpec centerNodeLabelItem = null;
+	/* End new code Feb.26.07 oliver*/
+	protected double[] shades = null;
+	protected double minValue, maxValue;
+	double namesAngle = MesquiteDouble.unassigned;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		currentFont = MesquiteWindow.defaultFont;
+		fontName = new MesquiteString(MesquiteWindow.defaultFont.getName());
+		fontSizeName = new MesquiteString(Integer.toString(MesquiteWindow.defaultFont.getSize()));
+		MesquiteSubmenuSpec namesMenu = addSubmenu(null, "Names");
+		addItemToSubmenu(null, namesMenu, "Taxon Name Angle...", makeCommand("namesAngle", this));
+		MesquiteSubmenuSpec msf = addSubmenu(null, "Font", makeCommand("setFont", this), MesquiteSubmenu.getFontList());
+		msf.setList(MesquiteSubmenu.getFontList());
+		msf.setDocumentItems(false);
+		msf.setSelected(fontName);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Font Size", makeCommand("setFontSize", this), MesquiteSubmenu.getFontSizeList());
+		mss.setList(MesquiteSubmenu.getFontSizeList());
+		mss.setDocumentItems(false);
+		mss.setSelected(fontSizeName);
+		fontColorName = new MesquiteString("Black");
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Default Font Color", makeCommand("setColor",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		mmis.setSelected(fontColorName);
+
+		//MesquiteSubmenuSpec mssNames = addSubmenu(null, "Names");
+		colorPartition = new MesquiteBoolean(false);
+		colorAssigned = new MesquiteBoolean(true);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Color by Taxon Group", makeCommand("toggleColorPartition", this), colorPartition);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Color by Assigned Color", makeCommand("toggleColorAssigned",  this), colorAssigned);
+		addItemToSubmenu(null, namesMenu, "Shade by Value...", makeCommand("shadeByNumber",  this));
+		offShadeMI = addItemToSubmenu(null, namesMenu, "Turn off Shading", makeCommand("offShading",  this));
+		offShadeMI.setEnabled(false);
+		shadePartition = new MesquiteBoolean(false);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Background Color by Taxon Group", makeCommand("toggleShadePartition", this), shadePartition);
+		showFootnotes = new MesquiteBoolean(true);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Show Footnotes Etc.", makeCommand("toggleShowFootnotes", this), showFootnotes);
+		showNodeLabels = new MesquiteBoolean(true);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Show Branch Names", makeCommand("toggleNodeLabels", this), showNodeLabels);
+		/*New code added Feb.15.07 oliver*/ //TODO: delete new code comments
+		centerNodeLabels = new MesquiteBoolean(false);
+		centerNodeLabelItem = addCheckMenuItemToSubmenu(null, namesMenu, "Center Branch Names", makeCommand("toggleCenterNodeNames", this), centerNodeLabels);
+		centerNodeLabelItem.setEnabled(true);
+
+		/*End new code added Feb.15.07 oliver*/
+		showTaxonNames = new MesquiteBoolean(true);
+		addCheckMenuItemToSubmenu(null, namesMenu, "Show Taxon Names", makeCommand("toggleShowNames", this), showTaxonNames);
+		addSubmenu(namesMenu, "Alter Names", makeCommand("alterBranchNames",  this), BranchNamesAlterer.class);
+
+		return true;
+	}
+
+	public void endJob(){
+		treeDisplay = null;
+		treeDrawing = null;
+		textRotator = null;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in or completely set up (if a new file).*/
+	public void fileReadIn(MesquiteFile f) {
+		if (treeDisplay != null)
+			treeDisplay.forceRepaint();
+	}
+	/*.................................................................................................................*/
+	/** return whether or not this module should have snapshot saved when saving a macro given the current snapshot mode.*/
+	public boolean satisfiesSnapshotMode(){
+		return (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL || MesquiteTrunk.snapshotMode == Snapshot.SNAPDISPLAYONLY);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (myFont!=null)
+			temp.addLine("setFont " + myFont);  //TODO: this causes problem since charts come before tree window
+		if (myFontSize>0)
+			temp.addLine("setFontSize " + myFontSize);  //TODO: this causes problem since charts come before tree window
+		temp.addLine("setColor " + ParseUtil.tokenize(fontColorName.toString()));  //TODO: this causes problem since charts come before tree window
+		temp.addLine("toggleColorPartition " + colorPartition.toOffOnString());
+		temp.addLine("toggleColorAssigned " + colorAssigned.toOffOnString());
+		if (shader != null)
+			temp.addLine("shadeByNumber ", shader);
+		temp.addLine("toggleShadePartition " + shadePartition.toOffOnString());
+		temp.addLine("toggleShowFootnotes " + showFootnotes.toOffOnString());
+		temp.addLine("toggleNodeLabels " + showNodeLabels.toOffOnString());
+		/*New code added Feb.15.07 oliver*/ //TODO: delete new code comments
+		temp.addLine("toggleCenterNodeNames " + centerNodeLabels.toOffOnString());
+		/*End new code added Feb.15.07 oliver*/
+		temp.addLine("toggleShowNames " + showTaxonNames.toOffOnString());
+		temp.addLine("namesAngle " + MesquiteDouble.toString(namesAngle));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a number for a taxon by which to shade", "[name of module]", commandName, "shadeByNumber")) {
+			NumberForTaxon temp= (NumberForTaxon)replaceEmployee(NumberForTaxon.class, arguments, "Value by which to shade taxon names", shader);
+			if (temp!=null) {
+				shader = temp;
+				offShadeMI.setEnabled(true);
+				MesquiteTrunk.resetMenuItemEnabling();
+				shades = null;
+				calcShades(tree);
+
+				parametersChanged();
+				return temp;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the angle names are shown at in default UP orientation", "[angle in degrees clockwise from horizontal; ? = default]", commandName, "namesAngle")) {
+			if (arguments == null && !MesquiteThread.isScripting()){
+				double current;
+				if (!MesquiteDouble.isCombinable(namesAngle))
+					current = namesAngle;
+				else
+					current = namesAngle/2/Math.PI*360;
+				MesquiteDouble d = new MesquiteDouble(current);
+				if (!QueryDialogs.queryDouble(containerOfModule(), "Names Angle", "Angle of taxon names, in degrees clockwise from horizontal.  Use \"?\" to indicate default.  Typical settings are between 0 degrees and -90 degrees.  0 = text reads from left to right (long dash = �); -90 = text reads from bottom to top (long dash = |); -45 = text angled diagonally (long dash = /).  This setting applies only when tree is in UP orientation", d))
+					return null;
+				namesAngle = d.getValue();
+				if (MesquiteDouble.isCombinable(namesAngle))
+					namesAngle = namesAngle/360*2*Math.PI;
+				parametersChanged();
+			}
+			else {
+
+				double angle = MesquiteDouble.fromString(parser.getFirstToken(arguments));
+				namesAngle = angle;
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Turns of shading by number", null, commandName, "offShading")) {
+			if (shader != null)
+				fireEmployee(shader);
+			shader = null;
+			shades = null;
+			offShadeMI.setEnabled(false);
+			MesquiteTrunk.resetMenuItemEnabling();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether taxon names are colored according to their group in the current taxa partition", "[on or off]", commandName, "toggleColorPartition")) {
+			boolean current = colorPartition.getValue();
+
+			colorPartition.toggleValue(parser.getFirstToken(arguments));
+			if (colorAssigned.getValue() && colorPartition.getValue())
+				colorAssigned.setValue(false);
+			if (current!=colorPartition.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether taxon names are colored according to their current assigned color", "[on or off]", commandName, "toggleColorAssigned")) {
+			boolean current = colorAssigned.getValue();
+
+			colorAssigned.toggleValue(parser.getFirstToken(arguments));
+			if (colorAssigned.getValue() && colorPartition.getValue())
+				colorPartition.setValue(false);
+			if (current!=colorAssigned.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether taxon names are given a background color according to their group in the current taxa partition", "[on or off]", commandName, "toggleShadePartition")) {
+			boolean current = shadePartition.getValue();
+			shadePartition.toggleValue(parser.getFirstToken(arguments));
+			if (current!=shadePartition.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether asterisks (for footnotes) and other indications are shown with taxon names", "[on or off]", commandName, "toggleShowFootnotes")) {
+			boolean current = showFootnotes.getValue();
+			showFootnotes.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showFootnotes.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to alter or transform branch names", "[name of module]", commandName, "alterBranchNames")) {
+			BranchNamesAlterer bna = (BranchNamesAlterer)hireNamedEmployee(BranchNamesAlterer.class, arguments);
+			if (bna!=null && tree instanceof AdjustableTree) {
+				boolean success = bna.transformTree((AdjustableTree)tree, null, true);
+				if (success){
+					//					if (treeSourceLocked())
+					//						((AdjustableTree)tree).setName("Untitled Tree");
+					//					treeEdited(false);
+				}
+				fireEmployee(bna); //todo: for branch length estimators, might be good to keep it around, and remembering it if user wants to change parameters
+			}
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether names of internal branches (clades) are shown", "[on or off]", commandName, "toggleNodeLabels")) {
+			boolean current = showNodeLabels.getValue();
+			showNodeLabels.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showNodeLabels.getValue())
+				parametersChanged();
+		}
+		/*New code added Feb.15.07 oliver*/ //TODO: delete new code comments
+		else if (checker.compare(this.getClass(), "Toggles whether names of internal branches (clades) are centered", "[on or off]", commandName, "toggleCenterNodeNames")){
+			boolean current = centerNodeLabels.getValue();
+			centerNodeLabels.toggleValue(parser.getFirstToken(arguments));
+			if (current!=centerNodeLabels.getValue())
+				parametersChanged();
+		}
+		/*End new code added Feb.15.07 oliver*/
+		else if (checker.compare(this.getClass(), "Toggles whether names of terminal taxa are shown", "[on or off]", commandName, "toggleShowNames")) {
+			boolean current = showTaxonNames.getValue();
+			showTaxonNames.toggleValue(parser.getFirstToken(arguments));
+			if (current!=showTaxonNames.getValue())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the font used for the taxon names", "[name of font]", commandName, "setFont")) {
+			String t = parser.getFirstToken(arguments);
+			if (currentFont==null){
+				myFont = t;
+				fontName.setValue(t);
+			}
+			else {
+				Font fontToSet = new Font (t, currentFont.getStyle(), currentFont.getSize());
+				if (fontToSet!= null) {
+					myFont = t;
+					fontName.setValue(t);
+					currentFont = fontToSet;
+					parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the font size used for the taxon names", "[size of font]", commandName, "setFontSize")) {
+			int fontSize = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (currentFont==null){
+				if (!MesquiteThread.isScripting() && !MesquiteInteger.isPositive(fontSize))
+					fontSize = MesquiteInteger.queryInteger(containerOfModule(), "Font Size", "Font Size", 12);
+				if (MesquiteInteger.isPositive(fontSize)) {
+					myFontSize = fontSize;
+					fontSizeName.setValue(Integer.toString(fontSize));
+				}
+			}
+			else {
+				if (!MesquiteThread.isScripting() && !MesquiteInteger.isPositive(fontSize))
+					fontSize = MesquiteInteger.queryInteger(containerOfModule(), "Font Size", "Font Size", currentFont.getSize());
+				if (MesquiteInteger.isPositive(fontSize)) {
+					myFontSize = fontSize;
+					Font fontToSet = new Font (currentFont.getName(), currentFont.getStyle(), fontSize);
+					if (fontToSet!= null) {
+						currentFont = fontToSet;
+						fontSizeName.setValue(Integer.toString(fontSize));
+						parametersChanged(new Notification(TreeDisplay.FONTSIZECHANGED));
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets color of taxon names", "[name of color]", commandName, "setColor")) {
+			String token = ParseUtil.getFirstToken(arguments, stringPos);
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			fontColor = bc;
+			fontColorLight = ColorDistribution.brighter(bc, ColorDistribution.dimmingConstant);
+			fontColorName.setValue(token);
+			parametersChanged();
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public Font getFont(){
+		return currentFont;
+	}
+	public void invalidateNames(TreeDisplay treeDisplay){
+		if (textRotator!=null)
+			textRotator.invalidateAll();
+	}
+	public float getTaxonShade(double value){
+		if (!MesquiteDouble.isCombinable(value) || !MesquiteDouble.isCombinable(minValue) || !MesquiteDouble.isCombinable(maxValue) || minValue == maxValue)
+			return 1.0f;
+		//return (float)((value-minValue)/(maxValue-minValue)*0.8 + 0.2);  //todo: need to distinguish polarity
+		return (float)((maxValue - value)/(maxValue-minValue)*0.8 + 0.2);
+	}
+	public void setTree(Tree tree) {
+		if (shader != null ){
+			calcShades(tree);
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		calcShades(tree);
+		parametersChanged(notification);
+
+	}
+	private void calcShades(Tree tree){
+		if (tree == null)
+			return;
+		minValue = MesquiteDouble.unassigned;
+		maxValue = MesquiteDouble.unassigned;
+		Taxa taxa = tree.getTaxa();
+		if (shades == null || shades.length < taxa.getNumTaxa())
+			shades = new double[taxa.getNumTaxa()];
+		for (int i = 0; i<shades.length; i++)
+			shades[i] = MesquiteDouble.unassigned;
+		MesquiteNumber n = new MesquiteNumber();
+		for (int i = 0; i< taxa.getNumTaxa(); i++){
+			shader.calculateNumber(taxa.getTaxon(i), n, null);
+			if (n.isCombinable()) {
+				shades[i] = n.getDoubleValue();
+				if (minValue == MesquiteDouble.unassigned)
+					minValue = shades[i];
+				else if (minValue > shades[i])
+					minValue = shades[i];
+				if (maxValue == MesquiteDouble.unassigned)
+					maxValue = shades[i];
+				else if (maxValue < shades[i])
+					maxValue = shades[i];
+			}
+		}
+	}
+	Color bgTransparent = new Color(255,255,255,0);  //make transparent so as not to overwrite boxes and branches if font big
+	boolean nameIsVisible(TreeDisplay treeDisplay, int taxonNumber){
+		boolean vis = treeDisplay.getVisRect() == null || namePolys[taxonNumber].intersects(treeDisplay.getVisRect());
+		/*if (vis){
+			if (triangleBase >=0 ){
+				Tree tree = treeDisplay.getTree();
+				if (tree != null){
+					int node = tree.nodeOfTaxonNumber(taxonNumber);
+					if (!tree.nodeExists(node))
+						return false;
+					return (tree.leftmostTerminalOfNode(triangleBase)==node) || tree.rightmostTerminalOfNode(triangleBase)==node;
+
+				}
+			}
+		}*/
+		return vis;
+	}
+	boolean nameExposedOnTree(Tree tree, int taxonNumber, int triangleBase){
+		if (triangleBase >=0 ){
+			int node = tree.nodeOfTaxonNumber(taxonNumber);
+			return (tree.leftmostTerminalOfNode(triangleBase)==node) || tree.rightmostTerminalOfNode(triangleBase)==node;
+		}
+
+		return true;
+	}
+	NameReference colorNameRef = NameReference.getNameReference("color");
+	/*.................................................................................................................*/
+	protected void drawNamesOnTree(Tree tree, int N, TreeDisplay treeDisplay, TaxaPartition partitions, int triangleBase) {
+		if (triangleBase < 0 && tree.getAssociatedBit(triangleNameRef, N))
+			triangleBase = N;
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+			if (!showTaxonNames.getValue())
+				return;
+			Color bgColor = null;
+			//Color bgColor = bgTransparent;
+
+			textRotator.assignBackground(bgColor);
+			int horiz=treeDrawing.x[N];
+			int vert=treeDrawing.y[N];
+			int lengthString;
+			boolean warn = true;
+			Taxa taxa = tree.getTaxa();
+			int taxonNumber = tree.taxonNumberOfNode(N);
+			if (taxonNumber<0) {
+				if (warn)
+					MesquiteMessage.warnProgrammer("error: negative taxon number found in DrawNamesTreeDisplay " + taxonNumber + "  tree: " + tree.writeTree());
+				return;
+			}
+			else if (taxonNumber>=taxa.getNumTaxa()) {
+				if (warn)
+					MesquiteMessage.warnProgrammer("error: taxon number too high found in DrawNamesTreeDisplay " + taxonNumber + "  tree: " + tree.writeTree());
+				return;
+			}
+			if (taxonNumber>= namePolys.length) {
+				if (warn)
+					MesquiteMessage.warnProgrammer("error: taxon number " + taxonNumber + " / name polys " + namePolys.length);
+				return;
+			}
+			String s=taxa.getName(taxonNumber);
+			if (s== null){
+				if (warn)
+					MesquiteMessage.warnProgrammer("error: taxon name null");
+				return;
+			}
+			Taxon taxon = taxa.getTaxon(taxonNumber);
+			if (taxon== null){
+				if (warn)
+					MesquiteMessage.warnProgrammer("error: taxon null");
+				return;
+			}
+			boolean selected = taxa.getSelected(taxonNumber);
+			//check all extras to see if they want to add anything
+			boolean underlined = false;
+			Color taxonColor;
+			if (!tree.anySelected() || tree.getSelected(N))
+				taxonColor = fontColor;
+			else
+				taxonColor = fontColorLight;
+
+			if (partitions!=null && (colorPartition.getValue() || shadePartition.getValue())){
+				TaxaGroup mi = (TaxaGroup)partitions.getProperty(taxonNumber);
+				if (mi!=null) {
+					if (colorPartition.getValue() && mi.getColor() != null)
+						taxonColor = mi.getColor();
+					if (shadePartition.getValue()){
+						bgColor =mi.getColor();
+						textRotator.assignBackground(bgColor);
+					}
+				}
+			}
+			if (colorAssigned.getValue()){
+				long c = taxa.getAssociatedLong(colorNameRef, taxonNumber);
+				if (MesquiteLong.isCombinable(c))
+					taxonColor= ColorDistribution.getStandardColor((int)c);
+			}
+			if (showFootnotes.getValue()){
+				ListableVector extras = treeDisplay.getExtras();
+				if (extras!=null){
+					Enumeration e = extras.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+						if (ex.getTaxonUnderlined(taxon))
+							underlined = true;
+						Color tc = ex.getTaxonColor(taxon);
+						if (tc!=null) {
+							taxonColor = tc;
+						}
+						String es = ex.getTaxonStringAddition(taxon);
+						if (!StringUtil.blank(es))
+							s+= es;
+					}
+				}
+			}
+
+			Composite composite =null;
+			if(shades != null && taxonNumber < shades.length) {
+				composite = ColorDistribution.getComposite(gL);
+				ColorDistribution.setTransparentGraphics(gL,getTaxonShade(shades[taxonNumber]));		
+			}
+			gL.setColor(taxonColor); 
+
+			lengthString = fm.stringWidth(s); //what to do if underlined?
+			int centeringOffset = 0;
+			if (treeDisplay.centerNames)
+				centeringOffset = (longestString-lengthString)/2;
+
+
+			if (treeDrawing.namesFollowLines ){
+				double slope = (treeDrawing.lineBaseY[N]*1.0-treeDrawing.lineTipY[N])/(treeDrawing.lineBaseX[N]-treeDrawing.lineTipX[N]);
+				//setBounds(namePolys[taxonNumber], horiz+separation, vert, lengthString, rise+descent);
+				boolean upper = treeDrawing.lineTipY[N]>treeDrawing.lineBaseY[N];
+				boolean right = treeDrawing.lineTipX[N]>treeDrawing.lineBaseX[N];
+				double radians = Math.atan(slope);
+				Font font = gL.getFont();
+				FontMetrics fontMet = gL.getFontMetrics(font);
+				double height = fontMet.getHeight(); //0.667
+				int length = fontMet.stringWidth(s)+ separation;
+				int textOffsetH = 0; //fontMet.getHeight()*2/3;
+				int textOffsetV = 0;
+				if (!right) {
+					textOffsetH = -(int)(Math.cos(radians)*length);
+
+					textOffsetV = -(int)(Math.sin(radians)*length);
+				}
+				else {
+					textOffsetH = (int)(Math.cos(radians + Math.atan(height*0.6/separation))*separation*1.4);  //1.0
+
+					textOffsetV = (int)(Math.sin(radians + Math.atan(height*0.6/separation))*separation*1.4);
+				}
+
+				int horizPosition = treeDrawing.lineTipX[N];
+				int vertPosition = treeDrawing.lineTipY[N];
+
+				textRotator.drawFreeRotatedText(s, gL, horizPosition, vertPosition, radians, new Point(textOffsetH, textOffsetV), false, namePolys[taxonNumber]);
+
+			}
+			else if ((treeDrawing.labelOrientation[N]==270) || treeDisplay.getOrientation()==TreeDisplay.UP) {
+				horiz += treeDrawing.getEdgeWidth()/2;
+				if (Math.abs(treeDrawing.namesAngle)<0.01) {
+					horiz -= StringUtil.getStringDrawLength(gL,"A");
+				}
+				if (MesquiteDouble.isCombinable(treeDrawing.namesAngle) && treeDrawing.labelOrientation[N]!=270){
+					textRotator.drawFreeRotatedText(s,  gL, horiz-rise/2, vert-separation, treeDrawing.namesAngle, null, true, namePolys[taxonNumber]);
+				}
+				else {
+					vert -= centeringOffset;
+					if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+						setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+					else
+						setBounds(namePolys[taxonNumber], horiz-rise/2, vert-separation-lengthString, rise+descent, lengthString);
+					if (nameIsVisible(treeDisplay, taxonNumber))
+						textRotator.drawRotatedText(s, taxonNumber, gL, treeDisplay, horiz-rise/2, vert-separation);
+
+					if (underlined){
+						Rectangle b =namePolys[taxonNumber].getB();
+						gL.drawLine(b.x+b.width, b.y, b.x+b.width, b.y+b.height);
+						//gL.fillPolygon(namePolys[taxonNumber]);
+					}
+				}
+			}
+			else if ((treeDrawing.labelOrientation[N]==90) || treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+				horiz += treeDrawing.getEdgeWidth()/2;
+				/*if (MesquiteWindow.Java2Davailable && (MesquiteDouble.isCombinable(treeDrawing.namesAngle) || treeDrawing.labelOrientation[N]!=90)){
+					textRotator.drawFreeRotatedText(s,  gL, horiz-rise*2, vert+separation, treeDrawing.namesAngle, null, false, namePolys[taxonNumber]); // /2
+				}
+				else */
+				{
+					vert += centeringOffset;
+					if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+						setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+					else
+					setBounds(namePolys[taxonNumber], horiz-rise/2, vert+separation, rise+descent, lengthString);
+					if (nameIsVisible(treeDisplay, taxonNumber))
+						textRotator.drawRotatedText(s, taxonNumber, gL, treeDisplay, horiz-rise/2, vert+separation, false);
+					if (underlined){
+						Rectangle b =namePolys[taxonNumber].getB();
+						gL.drawLine(b.x+b.width, b.y, b.x+b.width, b.y+b.height);
+						//gL.fillPolygon(namePolys[taxonNumber]);
+					}
+				}
+			}
+			else if ((treeDrawing.labelOrientation[N]==0) || treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+				vert += treeDrawing.getEdgeWidth()/2;
+				/*if (MesquiteWindow.Java2Davailable && (MesquiteDouble.isCombinable(treeDrawing.namesAngle) || treeDrawing.labelOrientation[N]!=0)){
+					textRotator.drawFreeRotatedText(s,  gL, horiz+separation, vert-rise*2, treeDrawing.namesAngle, null, false, namePolys[taxonNumber]); ///2
+				}
+				else */{
+					horiz += centeringOffset;
+					if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+						setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+					else
+					setBounds(namePolys[taxonNumber], horiz+separation, vert-rise/2, lengthString, rise+descent);
+
+					if (nameIsVisible(treeDisplay, taxonNumber)){
+						if (bgColor!=null) {
+							gL.setColor(bgColor);
+							gL.fillRect(horiz+separation, vert-rise/2, lengthString, rise+descent);
+							gL.setColor(taxonColor);
+						}
+						gL.drawString(s, horiz+separation, vert+rise/2);
+						if (underlined){
+							Rectangle b =namePolys[taxonNumber].getB();
+							gL.drawLine(b.x, b.y+b.height, b.x+b.width, b.y+b.height);
+							//gL.fillPolygon(namePolys[taxonNumber]);
+						}
+					}
+				}
+			}
+			else if ((treeDrawing.labelOrientation[N]==180) || treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+				vert += treeDrawing.getEdgeWidth()/2;
+				/*if (MesquiteWindow.Java2Davailable && (MesquiteDouble.isCombinable(treeDrawing.namesAngle) || treeDrawing.labelOrientation[N]!=0)){
+					textRotator.drawFreeRotatedText(s,  gL, horiz - separation, vert-rise*2, treeDrawing.namesAngle, null, true, namePolys[taxonNumber]);
+				}
+				else */{
+					horiz -= centeringOffset;
+					if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+						setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+					else
+					setBounds(namePolys[taxonNumber], horiz - separation - lengthString, vert-rise/2, lengthString, rise+descent);
+					if (nameIsVisible(treeDisplay, taxonNumber)){
+						if (bgColor!=null) {
+							gL.setColor(bgColor);
+							gL.fillRect(horiz - separation - lengthString, vert-rise/2, lengthString, rise+descent);
+							gL.setColor(taxonColor);
+						}
+						gL.drawString(s, horiz - separation - lengthString, vert+rise/2);
+						if (underlined){
+							Rectangle b =namePolys[taxonNumber].getB();
+							gL.drawLine(b.x, b.y+b.height, b.x+b.width, b.y+b.height);
+							//gL.fillPolygon(namePolys[taxonNumber]);
+						}
+					}
+				}
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.FREEFORM) {
+				if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+					setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+				else
+				setBounds(namePolys[taxonNumber], horiz+separation, vert-rise/2, lengthString, rise+descent);
+				if (nameIsVisible(treeDisplay, taxonNumber)){
+					if (bgColor!=null) {
+						gL.setColor(bgColor);
+						gL.fillRect(horiz+separation, vert-rise/2, lengthString, rise+descent);
+						gL.setColor(taxonColor);
+					}
+					gL.drawString(s, horiz+separation, vert+rise/2);
+					if (underlined){
+						Rectangle b =namePolys[taxonNumber].getB();
+						gL.drawLine(b.x, b.y+b.height, b.x+b.width, b.y+b.height);
+						//gL.fillPolygon(namePolys[taxonNumber]);
+					}
+				}
+			}
+			else { 
+				double slope = (treeDrawing.lineBaseY[N]*1.0-treeDrawing.lineTipY[N])/(treeDrawing.lineBaseX[N]-treeDrawing.lineTipX[N]);
+				if (slope>=-1 && slope <= 1) {  //right or left side
+					if (treeDrawing.lineTipX[N]> treeDrawing.lineBaseX[N]) { // right
+						if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+							setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+						else
+						setBounds(namePolys[taxonNumber], horiz+separation, vert, lengthString, rise+descent);
+						if (nameIsVisible(treeDisplay, taxonNumber)){
+							if (bgColor!=null) {
+								gL.setColor(bgColor);
+								gL.fillRect(horiz+separation, vert, lengthString, rise+descent);
+								gL.setColor(taxonColor);
+							}
+							gL.drawString(s, horiz+separation, vert + rise);
+							if (underlined){
+								Rectangle b =namePolys[taxonNumber].getB();
+								gL.drawLine(b.x, b.y+b.height, b.x+b.width, b.y+b.height);
+								//gL.fillPolygon(namePolys[taxonNumber]);
+							}
+						}
+					}
+					else {
+						if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+							setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+						else
+						setBounds(namePolys[taxonNumber], horiz - separation - lengthString, vert, lengthString, rise+descent);
+						if (nameIsVisible(treeDisplay, taxonNumber)){
+							if (bgColor!=null) {
+								gL.setColor(bgColor);
+								gL.fillRect(horiz - separation - lengthString, vert, lengthString, rise+descent);
+								gL.setColor(taxonColor);
+							}
+							gL.drawString(s, horiz - separation - lengthString, vert + rise);
+							if (underlined){
+								Rectangle b =namePolys[taxonNumber].getB();
+								gL.drawLine(b.x, b.y+b.height, b.x+b.width, b.y+b.height);
+								//gL.fillPolygon(namePolys[taxonNumber]);
+							}
+						}
+					}
+				}
+				else {//top or bottom
+					if (treeDrawing.lineTipY[N]> treeDrawing.lineBaseY[N]) { // bottom
+						if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+							setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+						else
+						setBounds(namePolys[taxonNumber], horiz, vert+separation, rise+descent, lengthString);
+						if (nameIsVisible(treeDisplay, taxonNumber)){
+							textRotator.drawRotatedText(s, taxonNumber, gL, treeDisplay, horiz, vert+separation, false);
+							if (underlined){
+								Rectangle b =namePolys[taxonNumber].getB();
+								gL.drawLine(b.x+b.width, b.y, b.x+b.width, b.y+b.height);
+								//gL.fillPolygon(namePolys[taxonNumber]);
+							}
+						}
+					}
+					else { // top
+						if (!nameExposedOnTree(tree, taxonNumber, triangleBase))
+							setBounds(namePolys[taxonNumber], 0, 0, 0, 0);
+						else
+						setBounds(namePolys[taxonNumber], horiz, vert-separation-lengthString, rise+descent, lengthString);
+						if (nameIsVisible(treeDisplay, taxonNumber)){
+							textRotator.drawRotatedText(s, taxonNumber, gL, treeDisplay, horiz, vert-separation);
+							if (underlined){
+								Rectangle b =namePolys[taxonNumber].getB();
+								gL.drawLine(b.x+b.width, b.y, b.x+b.width, b.y+b.height);
+								//gL.fillPolygon(namePolys[taxonNumber]);
+							}
+						}
+					}
+				}
+			}
+			textRotator.assignBackground(null);
+			gL.setColor(Color.black);
+			ColorDistribution.setComposite(gL,composite);		
+			if (selected  && !namePolys[taxonNumber].isHidden()){ //&& GraphicsUtil.useXORMode(gL, false)
+				//gL.setXORMode(Color.white);
+				//gL.fillPolygon(namePolys[taxonNumber]);
+				GraphicsUtil.fillTransparentBorderedSelectionPolygon(gL, namePolys[taxonNumber]);
+
+			//	gL.setPaintMode();
+			}
+
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawNamesOnTree(tree, d, treeDisplay, partitions, triangleBase);
+
+			String label = null;
+			if (showNodeLabels.getValue())
+				label = tree.getNodeLabel(N);
+			if (label!=null && label.length() >0 && label.charAt(0)!='^') {
+				//check all extras to see if they want to add anything
+				boolean underlined = false;
+				Color taxonColor = Color.black;
+				if (!tree.anySelected()|| tree.getSelected(N))
+					taxonColor = fontColor;
+				else
+					taxonColor = fontColorLight;
+				String s = StringUtil.deTokenize(label);
+				ListableVector extras = treeDisplay.getExtras();
+				if (extras!=null){
+					Enumeration e = extras.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+						if (ex.getCladeLabelUnderlined(label, N))
+							underlined = true;
+						Color tc = ex.getCladeLabelColor(label, N);
+						if (tc!=null)
+							taxonColor = tc;
+						String es = ex.getCladeLabelAddition(label, N);
+						if (!StringUtil.blank(es))
+							s+= es;
+					}
+				}
+				/*New code added Feb.15.07 oliver*/ //TODO: delete new code comments
+				//				TODO: Currently only really works for square trees, and an ugly hack at that
+				if (!centerNodeLabels.getValue() || !(MesquiteModule.getShortClassName(treeDrawing.getClass()).toString().equalsIgnoreCase("SquareTreeDrawing"))){
+					StringUtil.highlightString(gL,s, treeDrawing.x[N], treeDrawing.y[N], taxonColor, Color.white);
+					if (MesquiteModule.getShortClassName(treeDrawing.getClass()).toString().equalsIgnoreCase("SquareTreeDrawing"))
+						centerNodeLabelItem.setEnabled(true);
+					else centerNodeLabelItem.setEnabled(false); // TODO: these conditionals don't work right.  Should work now April.03.07 oliver
+				}
+				else {
+					centerNodeLabelItem.setEnabled(true);
+					int edgeWidth = treeDrawing.getEdgeWidth();
+					int parentN = tree.motherOfNode(N);
+					int centerH, centerV, startH, startV;
+					int nameDrawLength = StringUtil.getStringDrawLength(gL, s);
+					int nameDrawHeight = StringUtil.getTextLineHeight(gL);
+					if (treeDisplay.getOrientation()==TreeDisplay.UP){
+						startV = treeDrawing.y[N] + (int)((treeDrawing.y[parentN] - treeDrawing.y[N])/2) + edgeWidth; 
+						startH = treeDrawing.x[N] + edgeWidth;
+						StringUtil.highlightString(gL, s, startH, startV, taxonColor, Color.white);
+					}
+					else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+						startV = treeDrawing.y[N] - (int)((treeDrawing.y[N] - treeDrawing.y[parentN])/2); 
+						startH = treeDrawing.x[N] + edgeWidth;
+						StringUtil.highlightString(gL, s, startH, startV, taxonColor, Color.white);
+					}
+					else if (treeDisplay.getOrientation()==TreeDisplay.RIGHT){
+						centerH = treeDrawing.x[N] - (int)((treeDrawing.x[N] - treeDrawing.x[parentN])/2) - edgeWidth; 
+						startH = centerH -(int)(nameDrawLength/2);
+						// this conditional tests for overlap between branch and names, and shifts name accordingly.
+						if((centerH + (int)nameDrawLength/2) > treeDrawing.x[N] - edgeWidth){
+							startH -= (centerH + (int)nameDrawLength/2) - (treeDrawing.x[N] - edgeWidth);
+						}
+						startV = (int)(treeDrawing.y[N] - 1);
+						StringUtil.highlightString(gL, s, startH, startV, taxonColor, Color.white);
+					}
+					else if (treeDisplay.getOrientation()==TreeDisplay.LEFT){
+						centerH = treeDrawing.x[N] + (int)((treeDrawing.x[parentN] - treeDrawing.x[N])/2) + edgeWidth; 
+						startH = centerH -(int)(nameDrawLength/2);
+						// this conditional tests for overlap between branch and names, and shifts name accordingly.
+						if((centerH - (int)nameDrawLength/2 < treeDrawing.x[N] + edgeWidth)){
+							startH += (treeDrawing.x[N] + edgeWidth) - (centerH - (int)nameDrawLength/2);
+						}
+						startV = (int)(treeDrawing.y[N] - 1);
+						StringUtil.highlightString(gL, s, startH, startV, taxonColor, Color.white);
+					}
+					// TODO: figure out how to check for initialization of startH & startV, then pull the highlightString method out of the four conditionals above and put it here
+					// StringUtil.highlightString(gL, s, startH, startV, taxonColor, Color.white);
+				}
+				/*end new code added Feb.15.07 oliver*/
+				gL.setColor(taxonColor);
+				if (underlined)
+					gL.drawLine(treeDrawing.x[N], treeDrawing.y[N]+1,treeDrawing.x[N] +  fm.stringWidth(s), treeDrawing.y[N]+1);
+			}
+		}
+	}
+	protected void setBounds(TaxonPolygon poly, int x, int y, int w, int h){
+		//		poly.getBounds();
+		poly.setB(x,y,w,h);
+		//int[] xs = poly.xpoints;
+		//int[] ys = poly.ypoints;
+		//if (true || xs == null || xs.length !=4 || ys == null || ys.length !=4){
+		poly.reset();
+		poly.addPoint(x, y);
+		poly.addPoint(x+w, y);
+		poly.addPoint(x+w, y+h);
+		poly.addPoint(x, y+h);
+		//poly.npoints=4;
+		/*}
+			else {
+				xs[0] = x;
+				xs[1] = x+w;
+				xs[2] = x+w;
+				xs[3] = x;
+				ys[0] = y;
+				ys[1] = y;
+				ys[2] = y+h;
+				ys[3] = y+h;
+			}*/
+	}
+
+	int count=0;
+	NameReference triangleNameRef = NameReference.getNameReference("triangled");
+	/*.................................................................................................................*/
+	public void drawNames(TreeDisplay treeDisplay,  Tree tree, int drawnRoot, Graphics g) {
+		if (treeDisplay==null)
+			return; // alert("tree display null in draw taxon names");
+		if (tree==null)
+			return; // alert("tree null in draw taxon names");
+		if (g==null)
+			return; // alert("graphics null in draw taxon names");
+		int totalNumTaxa = tree.getTaxa().getNumTaxa();
+		if (textRotator == null)
+			textRotator = new TextRotator(totalNumTaxa);
+		if (namePolys==null) {
+			namePolys = new TaxonPolygon[totalNumTaxa];
+			oldNumTaxa=totalNumTaxa;
+			for (int i = 0; i<totalNumTaxa; i++) {
+				namePolys[i] = new TaxonPolygon();
+				namePolys[i].xpoints = new int[4];
+				namePolys[i].ypoints = new int[4];
+				namePolys[i].npoints=4;
+			}
+		}
+		else if (oldNumTaxa<totalNumTaxa) {
+			for (int i = 0; i<oldNumTaxa; i++)
+				namePolys[i]=null;
+			namePolys = new TaxonPolygon[totalNumTaxa];
+			for (int i = 0; i<totalNumTaxa; i++) {
+				namePolys[i] = new TaxonPolygon();
+				namePolys[i].xpoints = new int[4];
+				namePolys[i].ypoints = new int[4];
+				namePolys[i].npoints=4;
+			}
+			oldNumTaxa=totalNumTaxa;
+		}
+		treeDisplay.getTreeDrawing().namePolys = namePolys;
+
+		this.treeDisplay =treeDisplay;
+		this.treeDrawing =treeDisplay.getTreeDrawing();
+		treeDrawing.namesAngle = namesAngle;
+
+		this.tree =tree;
+		this.gL =g;
+		if (treeDrawing==null)
+			alert("node displays null in draw taxon names");
+		try{
+			if (MesquiteTree.OK(tree)) {
+				if (currentFont ==null) {
+					currentFont = g.getFont();
+					if (myFont==null)
+						myFont = currentFont.getName();
+					if (myFontSize<=0)
+						myFontSize = currentFont.getSize();
+					Font fontToSet = new Font (myFont, currentFont.getStyle(), myFontSize);
+					if (fontToSet==null)
+						currentFont = g.getFont();
+					else
+						currentFont = fontToSet;
+				}
+				Font tempFont = g.getFont();
+				g.setFont(currentFont);
+				fm=g.getFontMetrics(currentFont);
+				rise= fm.getMaxAscent();
+				descent = fm.getMaxDescent();
+				separation = treeDisplay.getTaxonNameDistance();
+
+				TaxaPartition part = null;
+				if (colorPartition.getValue() || shadePartition.getValue())
+					part = (TaxaPartition)tree.getTaxa().getCurrentSpecsSet(TaxaPartition.class);
+				if (treeDisplay.centerNames) {
+					longestString = 0;
+					findLongestString(tree, drawnRoot);
+				}
+				int triangleBase;
+				if (tree.getAssociatedBit(triangleNameRef, drawnRoot))
+					triangleBase = drawnRoot;
+				else
+					triangleBase = -1;
+				drawNamesOnTree(tree, drawnRoot, treeDisplay, part, triangleBase);
+		
+				g.setFont(tempFont);
+			}
+		}
+		catch (Exception e){
+			MesquiteMessage.warnProgrammer("Exception in draw taxon names");
+			e.printStackTrace();
+		}
+	}
+
+	/*.................................................................................................................*/
+	private void findLongestString(Tree tree,  int N) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+
+			int taxonNumber = tree.taxonNumberOfNode(N);
+			if (taxonNumber<0 || taxonNumber>=tree.getTaxa().getNumTaxa()) 
+				return;
+
+			int lengthString = fm.stringWidth(tree.getTaxa().getTaxonName(taxonNumber)); 
+			if (lengthString>longestString)
+				longestString = lengthString;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				findLongestString(tree, d);
+		}
+	}
+	/*.................................................................................................................*/
+	int foundTaxon;
+	/*.................................................................................................................*/
+	private void findNameOnTree(Tree tree,  int N, int x, int y) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+
+			int taxonNumber = tree.taxonNumberOfNode(N);
+			if (taxonNumber<0) {
+				//MesquiteMessage.warnProgrammer("error: negative taxon number found in findNameOnTree");
+				return;
+			}
+			if (taxonNumber>=tree.getTaxa().getNumTaxa()) {
+				MesquiteMessage.warnProgrammer("error:  taxon number too large found in findNameOnTree (" + taxonNumber + ") node: " + N); 
+				return;
+			}
+			if (taxonNumber>= namePolys.length) {
+				MesquiteMessage.warnProgrammer("error in draw taxon names: Name polys not big enough; taxon number " + taxonNumber + " / name boxes " + namePolys.length);
+				return;
+			}
+			if (namePolys[taxonNumber]!=null && namePolys[taxonNumber].contains(x,y)) {
+				foundTaxon=taxonNumber;
+			}
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d) && foundTaxon==-1; d = tree.nextSisterOfNode(d))
+				findNameOnTree(tree, d, x, y);
+		}
+	}
+	/*.................................................................................................................*/
+	public   int findTaxon(Tree tree, int drawnRoot, int x, int y) { 
+
+		foundTaxon=-1;
+		if (tree!=null && namePolys!=null) {
+			if (tree.getTaxa().isDoomed())
+				return -1;
+			findNameOnTree(tree, drawnRoot, x, y);
+		}
+		return foundTaxon; }
+
+	/*.................................................................................................................*/
+	public   void fillTaxon(Graphics g, int M) {
+		try {
+			if ((namePolys!=null) && (namePolys[M]!=null) && !namePolys[M].isHidden()) {
+				GraphicsUtil.fillTransparentBorderedSelectionPolygon(g,namePolys[M]);
+			}
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+			alert("taxon flash out of getBounds");}
+	}
+}
+
+
diff --git a/Source/mesquite/trees/BasicTreeDrawCoordinator/BasicTreeDrawCoordinator.java b/Source/mesquite/trees/BasicTreeDrawCoordinator/BasicTreeDrawCoordinator.java
new file mode 100644
index 0000000..f097e0c
--- /dev/null
+++ b/Source/mesquite/trees/BasicTreeDrawCoordinator/BasicTreeDrawCoordinator.java
@@ -0,0 +1,1080 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BasicTreeDrawCoordinator;
+/*~~  */
+
+import java.util.*;
+
+import mesquite.assoc.lib.*;
+
+import java.awt.*;
+import java.io.*;
+import java.awt.image.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+import com.lowagie.text.pdf.PdfGraphics2D;
+
+/** Coordinates the drawing of trees in windows (e.g., used in the Tree Window and other places) */
+public class BasicTreeDrawCoordinator extends DrawTreeCoordinator {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DrawTree.class, "A specific Tree Drawer is needed to yield the desired style of tree.",
+		"You can choose the style in the Tree Form submenu of the Drawing menu.");
+		e.setSuppressListing(true);
+		EmployeeNeed e2 = registerEmployeeNeed(DrawNamesTreeDisplay.class, "A Tree drawing shows the names of taxa.",
+		"This is activated automatically.");
+		e2.setSuppressListing(true);
+	}
+	private DrawTree treeDrawTask;
+	private DrawNamesTreeDisplay terminalNamesTask;
+	MesquiteString treeDrawName, bgColorName, brColorName;
+	public Color bgColor=Color.white;
+	public Color brColor=Color.black;
+	boolean suppression = false;
+	MesquiteCommand tdC;
+	static String defaultDrawer = null;
+	MesquiteBoolean showNodeNumbers, labelBranchLengths, showBranchColors;
+
+	MesquiteBoolean centerBrLenLabels = new MesquiteBoolean(true);
+	MesquiteBoolean showBrLensUnspecified = new MesquiteBoolean(true);
+	MesquiteBoolean showBrLenLabelsOnTerminals = new MesquiteBoolean(true);
+	MesquiteInteger numBrLenDecimals = new MesquiteInteger(6);
+	public Color brLenColor=Color.blue;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		//addMenuItem("-", null);
+		makeMenu("Display");
+		if (defaultDrawer !=null && (condition == null || !(condition instanceof MesquiteBoolean) || ((MesquiteBoolean)condition).getValue() )) {
+			treeDrawTask= (DrawTree)hireNamedEmployee(DrawTree.class, defaultDrawer);
+			if (treeDrawTask == null)
+				treeDrawTask= (DrawTree)hireEmployee(DrawTree.class, null);
+		}
+		else
+			treeDrawTask= (DrawTree)hireEmployee(DrawTree.class, null);
+		if (treeDrawTask==null)
+			return sorry(getName() + " couldn't start because no tree drawing module was obtained");
+		setAutoSaveMacros(true);
+		treeDrawName = new MesquiteString(treeDrawTask.getName());
+		bgColorName = new MesquiteString("White");
+		brColorName = new MesquiteString("Black");
+		terminalNamesTask = (DrawNamesTreeDisplay)hireEmployee(DrawNamesTreeDisplay.class, null);
+		//TODO: if choice of terminalNamesTask, use setHriingCommand
+		tdC = makeCommand("setTreeDrawer",  this);
+		treeDrawTask.setHiringCommand(tdC);
+		MesquiteSubmenuSpec mmis = addSubmenu(null, "Tree Form", tdC);
+		addMenuItem("Set Current Form as Default", makeCommand("setFormToDefault",  this));
+		mmis.setList(DrawTree.class);
+		mmis.setSelected(treeDrawName);
+
+
+		mmis = addSubmenu(null, "Background Color", makeCommand("setBackground",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		mmis.setSelected(bgColorName);
+		mmis = addSubmenu(null, "Default Branch Color", makeCommand("setBranchColor",  this));
+		mmis.setList(ColorDistribution.standardColorNames);
+		mmis.setSelected(brColorName);
+		showNodeNumbers = new MesquiteBoolean(false);
+		labelBranchLengths = new MesquiteBoolean(false);
+		showBranchColors = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Node Numbers", MesquiteModule.makeCommand("showNodeNumbers",  this), showNodeNumbers);
+		addCheckMenuItem(null, "Show Branch Colors", MesquiteModule.makeCommand("showBranchColors",  this), showBranchColors);
+
+		mmis = addSubmenu(null, "Branch Length Labels");
+		addCheckMenuItemToSubmenu(null, mmis, "Show Labels", MesquiteModule.makeCommand("labelBranchLengths",  this), labelBranchLengths);
+		addCheckMenuItemToSubmenu(null, mmis, "Center Labels", MesquiteModule.makeCommand("centerBrLenLabels",  this), centerBrLenLabels);
+		addCheckMenuItemToSubmenu(null, mmis, "Label Terminal Taxa", MesquiteModule.makeCommand("showBrLenLabelsOnTerminals",  this), showBrLenLabelsOnTerminals);
+		addItemToSubmenu(null, mmis, "Label Color...", MesquiteModule.makeCommand("chooseBrLenLabelColor",  this));
+		addItemToSubmenu(null, mmis, "Number of Decimal Places...", MesquiteModule.makeCommand("setNumBrLenDecimals",  this));
+		addCheckMenuItemToSubmenu(null, mmis, "Include Missing Values", MesquiteModule.makeCommand("showBrLensUnspecified",  this), showBrLensUnspecified);
+		return true;
+	}
+
+	public boolean getShowBrLensUnspecified(){
+		return showBrLensUnspecified.getValue();
+	}
+	public boolean getCenterBrLenLabels(){
+		return centerBrLenLabels.getValue();
+	}
+	public boolean getShowBrLenLabelsOnTerminals() {
+		return showBrLenLabelsOnTerminals.getValue();
+	}
+	public int getNumBrLenDecimals() {
+		return numBrLenDecimals.getValue();
+	}
+	public Color getBrLenColor() {
+		return brLenColor;
+	}
+	public boolean hasPreferredSize(){
+		return treeDrawTask.hasPreferredSize();
+	}
+	public Dimension getPreferredSize(){
+		return treeDrawTask.getPreferredSize();
+	}
+	/*.................................................................................................................*/
+	MesquiteModule getTreeWindowMaker() {
+		TreeWindowMaker tw = (TreeWindowMaker) findEmployerWithDuty(TreeWindowMaker.class);
+		if (tw!=null)
+			return tw;
+		TWindowMaker tw2 = (TWindowMaker) findEmployerWithDuty(TWindowMaker.class);
+		return tw2;
+	}
+
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			defaultDrawer = prefs[0];
+		}
+	}
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "defaultDrawer", defaultDrawer);   
+		return buffer.toString();
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("defaultDrawer".equalsIgnoreCase(tag))
+			defaultDrawer = StringUtil.cleanXMLEscapeCharacters(content);
+	}
+
+
+	/*.................................................................................................................*
+	public Snapshot getSnapshotForMacro(MesquiteFile file) {
+		treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(DrawTreeCoordinator.class, null);
+		if (treeDrawCoordTask== null) {
+			sorry(getName() + " couldn't start because no tree draw coordinating module was obtained.");
+			return null;
+		}
+		treeDrawCoordTask.setToLastEmployee(true);
+		hireAllEmployees(TreeDisplayAssistantI.class);
+		hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration enumeration = getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistantDI init = (TreeDisplayAssistantDI) obj;
+				treeDrawCoordTask.requestGuestMenuPlacement(init);
+			}
+		}
+		resetContainingMenuBar();
+		return treeDrawCoordTask;
+	}
+	/*.................................................................................................................*/
+	/** return whether or not this module should have snapshot saved when saving a macro given the current snapshot mode.*/
+	public boolean satisfiesSnapshotMode(){
+		return (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL || MesquiteTrunk.snapshotMode == Snapshot.SNAPDISPLAYONLY);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress");
+
+		temp.addLine("setTreeDrawer " , treeDrawTask);
+		if (bgColor !=null) {
+			String bName = ColorDistribution.getStandardColorName(bgColor);
+			if (bName!=null)
+				temp.addLine("setBackground " + StringUtil.tokenize(bName));//quote
+		}
+		if (brColor !=null) {
+			String bName = ColorDistribution.getStandardColorName(brColor);
+			if (bName!=null)
+				temp.addLine("setBranchColor " + StringUtil.tokenize(bName));//quote
+		}
+		temp.addLine("showNodeNumbers " + showNodeNumbers.toOffOnString()); 
+		temp.addLine("showBranchColors " + showBranchColors.toOffOnString()); 
+		temp.addLine("labelBranchLengths " + labelBranchLengths.toOffOnString()); 
+		temp.addLine("centerBrLenLabels " + centerBrLenLabels.toOffOnString()); 
+		temp.addLine("showBrLensUnspecified " + showBrLensUnspecified.toOffOnString());
+		temp.addLine("showBrLenLabelsOnTerminals " + showBrLenLabelsOnTerminals.toOffOnString()); 
+		temp.addLine("setBrLenLabelColor " + ColorDistribution.getColorStringForSnapshot(brLenColor));
+		temp.addLine("setNumBrLenDecimals " + numBrLenDecimals.getValue());
+		temp.addLine("desuppress");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	/** return the value of items to be snapshotted when saving a macro.*/
+	public int getMacroSnapshotMode(){
+		return Snapshot.SNAPDISPLAYONLY;
+	}
+	/*.................................................................................................................*/
+	/** return the module responsible for snapshotting when saving a macro.*/
+	public MesquiteModule getMacroSnapshotModule(){
+		return getTreeWindowMaker();
+	}
+	/*.................................................................................................................*/
+	/** return the command string to get the module responsible for snapshotting when saving a macro.*/
+	public String getMacroSnapshotModuleCommand(){
+		return "getTreeWindowMaker";
+	}
+
+	public DrawNamesTreeDisplay getNamesTask(){
+		return terminalNamesTask;
+	}
+	/*.................................................................................................................*/
+	public void setBranchColor(Color c) {
+		brColor = c;
+	}
+	/*.................................................................................................................*/
+	public TreeDisplay createOneTreeDisplay(Taxa taxa, MesquiteWindow window) {
+		treeDisplay = new BasicTreeDisplay(this, taxa);
+		treeDisplay.setTreeDrawing(treeDrawTask.createTreeDrawing(treeDisplay, taxa.getNumTaxa()));
+		treeDisplay.setDrawTaxonNames(terminalNamesTask);
+		treeDisplay.suppressDrawing(suppression);
+		return treeDisplay;
+	}
+	/*.................................................................................................................*/
+	public TreeDisplay[] createTreeDisplays(int numDisplays, Taxa taxa, MesquiteWindow window) {
+		int numTaxa = 100;
+		if (taxa != null)
+			numTaxa = taxa.getNumTaxa();
+		treeDisplays = new BasicTreeDisplay[numDisplays];
+		this.numDisplays=numDisplays;
+		for (int i=0; i<numDisplays; i++) {
+			treeDisplays[i] = new BasicTreeDisplay(this, taxa);
+			treeDisplays[i].setDrawTaxonNames(terminalNamesTask);
+			treeDisplays[i].setTreeDrawing(treeDrawTask.createTreeDrawing(treeDisplays[i], numTaxa));
+			treeDisplays[i].suppressDrawing(suppression);
+		}
+		return treeDisplays;
+	}
+	/*.................................................................................................................*/
+	public TreeDisplay[] createTreeDisplays(int numDisplays, Taxa[] taxas, MesquiteWindow window) {
+		treeDisplays = new BasicTreeDisplay[numDisplays];
+		this.numDisplays=numDisplays;
+		for (int i=0; i<numDisplays; i++) {
+			treeDisplays[i] = new BasicTreeDisplay(this, taxas[i]);
+			treeDisplays[i].setTreeDrawing(treeDrawTask.createTreeDrawing(treeDisplays[i], taxas[i].getNumTaxa()));
+			treeDisplays[i].suppressDrawing(suppression);
+		}
+		return treeDisplays;
+	}
+	/*.................................................................................................................
+ 	public void endJob() {
+ 		if (MesquiteTrunk.trackActivity) logln ("MesquiteModule " + getName() + "  closing down ");
+		closeDownAllEmployees (this);
+ 		employees.removeElement(treeDrawTask);
+ 		if (treeDisplay != null)
+ 			treeDisplay.suppressDrawing(true);
+ 		treeDisplay = null;
+   	 }
+
+	/*.................................................................................................................*/
+	private void updateTreeDisplays () {
+
+		if (treeDisplay != null) {
+			while (treeDisplay.getDrawingInProcess())
+				;		
+			if (!suppression)
+				treeDisplay.pleaseUpdate(false);
+		}
+		else if (treeDisplays != null) {
+			for (int i=0; i<numDisplays; i++) {
+				while (treeDisplays[i].getDrawingInProcess())
+					;		
+				if (!suppression)
+					treeDisplays[i].pleaseUpdate(false);
+			}
+		}
+	}
+
+	long progress   = 0;
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the current tree form to be the default", null, commandName, "setFormToDefault")) {
+			defaultDrawer = " #" + MesquiteModule.getShortClassName(treeDrawTask.getClass());
+			storePreferences();
+		}
+		else if (checker.compare(this.getClass(), "Sets the module to be used to draw the tree", "[name of tree draw module]", commandName, "setTreeDrawer")) {
+			incrementMenuResetSuppression();
+			DrawTree temp = null;
+			if (treeDisplay != null) {
+				boolean vis = true;
+
+				while (treeDisplay.getDrawingInProcess()) {
+					;		
+				}
+				vis = treeDisplay.isVisible();
+				treeDisplay.setVisible(false);
+				treeDisplay.suppressDrawing(true);
+				int currentOrientation = treeDisplay.getOrientation();
+				temp = (DrawTree)replaceEmployee(DrawTree.class, arguments, "Form of tree?", treeDrawTask);
+				if (temp!=null) {
+					treeDrawTask = temp;
+					if (treeDisplay.getTreeDrawing()!=null)
+						treeDisplay.getTreeDrawing().dispose();
+					treeDisplay.setTreeDrawing(null);
+					treeDrawName.setValue(treeDrawTask.getName());
+					treeDrawTask.setHiringCommand(tdC);
+					treeDisplay.setTreeDrawing(treeDrawTask.createTreeDrawing(treeDisplay, treeDisplay.getTaxa().getNumTaxa()));
+					treeDisplay.suppressDrawing(suppression);
+					if (temp.allowsReorientation())
+						treeDisplay.setOrientation(currentOrientation);
+					else
+						currentOrientation = treeDisplay.getOrientation();
+					if (!suppression)
+						treeDisplay.pleaseUpdate(true);
+					treeDisplay.setVisible(vis);
+				}
+				else {
+					treeDisplay.setVisible(vis);
+					treeDisplay.suppressDrawing(suppression);
+					decrementMenuResetSuppression();
+					return null;
+			}
+			}
+			else if (treeDisplays != null) { //many tree displays
+				boolean[] vis = new boolean[numDisplays];
+				int[] currentOrientations = new int[numDisplays];
+				for (int i=0; i<numDisplays; i++) {
+					while (treeDisplays[i].getDrawingInProcess())
+						;		
+					vis[i] = treeDisplays[i].isVisible();
+					treeDisplays[i].setVisible(false);
+					treeDisplays[i].suppressDrawing(true);
+					if (treeDisplays[i].getTreeDrawing() != null)
+						treeDisplays[i].getTreeDrawing().dispose();
+					treeDisplays[i].setTreeDrawing(null);
+					currentOrientations[i] = treeDisplays[i].getOrientation();
+				}
+				temp = (DrawTree)replaceEmployee(DrawTree.class, arguments, "Form of tree?", treeDrawTask);
+				if (temp!=null) {
+					treeDrawTask = temp;
+					treeDrawName.setValue(treeDrawTask.getName());
+					treeDrawTask.setHiringCommand(tdC);
+				}
+				for (int i=0; i<numDisplays; i++) {
+					treeDisplays[i].setTreeDrawing(treeDrawTask.createTreeDrawing(treeDisplays[i], treeDisplays[i].getTaxa().getNumTaxa()));
+				}
+				for (int i=0; i<numDisplays; i++) {
+					if (temp.allowsReorientation())
+						treeDisplays[i].setOrientation(currentOrientations[i]);
+					else
+						currentOrientations[i] = treeDisplays[i].getOrientation();
+					treeDisplays[i].suppressDrawing(suppression);
+					if (!suppression)
+						treeDisplays[i].repaint();
+					treeDisplays[i].setVisible(vis[i]);
+				}
+			}
+
+
+			decrementMenuResetSuppression();
+			if (temp == null)
+				return null;
+			else {
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+				return treeDrawTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Suppresses tree drawing", null, commandName, "suppress")) {
+			suppression=true;
+			if (treeDisplay != null) {
+				treeDisplay.suppressDrawing(suppression);
+			}
+			else if (treeDisplays != null) {
+				for (int i=0; i<numDisplays; i++) {
+					treeDisplays[i].suppressDrawing(suppression);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes suppression of tree drawing", null, commandName, "desuppress")) {
+			suppression=false;
+			if (treeDisplay != null) {
+				treeDisplay.suppressDrawing(suppression);
+				treeDisplay.pleaseUpdate(true);
+			}
+			else if (treeDisplays != null) {
+				for (int i=0; i<numDisplays; i++) {
+					treeDisplays[i].suppressDrawing(suppression);
+					treeDisplays[i].pleaseUpdate(true);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Gets current tree window maker", null, commandName, "getTreeWindowMaker")) {
+			return getTreeWindowMaker();
+		}
+		else if (checker.compare(this.getClass(), "Sets background color of tree display", "[name of color]", commandName, "setBackground")) {
+			String token = ParseUtil.getFirstToken(arguments, stringPos);
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			bgColor = bc;
+			bgColorName.setValue(token);
+			if (treeDisplay != null) {
+				while (treeDisplay.getDrawingInProcess())
+					;		
+				treeDisplay.setBackground(bc);
+				Container c = treeDisplay.getParent();
+				if (c!=null)
+					c.setBackground(bc);
+				terminalNamesTask.invalidateNames(treeDisplay);
+				if (!suppression)
+					treeDisplay.repaintAll();
+			}
+			else if (treeDisplays != null) {
+				for (int i=0; i<numDisplays; i++) {
+					while (treeDisplays[i].getDrawingInProcess())
+						;		
+					treeDisplays[i].setBackground(bc);
+					Container c = treeDisplays[i].getParent();
+					if (c!=null)
+						c.setBackground(bc);
+					terminalNamesTask.invalidateNames(treeDisplays[i]);
+					if (!suppression)
+						treeDisplays[i].repaintAll();
+				}
+			}
+			if (!MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets default color of branches of tree in tree display", "[name of color]", commandName, "setBranchColor")) {
+			String token = ParseUtil.getFirstToken(arguments, stringPos);
+			Color bc = ColorDistribution.getStandardColor(token);
+			if (bc == null)
+				return null;
+			Color bcD = ColorDistribution.getStandardColorDimmed(ColorDistribution.getStandardColorNumber(bc));
+			brColor = bc;
+			brColorName.setValue(token);
+			if (treeDisplay != null) {
+				while (treeDisplay.getDrawingInProcess())
+					;		
+				treeDisplay.branchColor = bc;
+				treeDisplay.branchColorDimmed = bcD;
+				Container c = treeDisplay.getParent();
+				if (c!=null)
+					c.setBackground(bc);
+				if (!suppression)
+					treeDisplay.pleaseUpdate(false);
+			}
+			else if (treeDisplays != null) {
+				for (int i=0; i<numDisplays; i++) {
+					while (treeDisplays[i].getDrawingInProcess())
+						;		
+					treeDisplays[i].branchColor = bc;
+					treeDisplays[i].branchColorDimmed = bcD;
+					if (!suppression)
+						treeDisplays[i].pleaseUpdate(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of decimals in the branch length label", "[number]", commandName, "setNumBrLenDecimals")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Decimal Places Displayed", "Number of decimal places displayed in branch length labels:", numBrLenDecimals.getValue(), 0, 25);
+			if (newNum>=0  && newNum!=numBrLenDecimals.getValue()) {
+				numBrLenDecimals.setValue(newNum);
+				updateTreeDisplays();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows node numbers on tree", "[on or off]", commandName, "showNodeNumbers")) {
+			showNodeNumbers.toggleValue(arguments);
+			updateTreeDisplays();
+
+		}
+		else if (checker.compare(this.getClass(), "Shows branch colors on tree", "[on or off]", commandName, "showBranchColors")) {
+			showBranchColors.toggleValue(arguments);
+			updateTreeDisplays();
+		}
+
+		else if (checker.compare(this.getClass(), "Specifies whether or not branch length labels, if shown, are centered along a branch", "[on or off]", commandName, "centerBrLenLabels")) {
+			centerBrLenLabels.toggleValue(arguments);
+			updateTreeDisplays();
+
+		}
+		else if (checker.compare(this.getClass(), "Specifies whether or not ? is shown or not for branches whose length is unspecified", "[on or off]", commandName, "showBrLensUnspecified")) {
+			showBrLensUnspecified.toggleValue(arguments);
+			updateTreeDisplays();
+
+		}
+		else if (checker.compare(this.getClass(), "Allows user to choose the color for branch length labels", "[on or off]", commandName, "chooseBrLenLabelColor")) {
+			if (!MesquiteThread.isScripting()) {
+				Color color = ColorDialog.queryColor(this.containerOfModule(), "Choose Color", "Color for state", brLenColor);
+				if (color!=null){
+					brLenColor = color;
+					updateTreeDisplays();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Specifies the color", "[on or off]", commandName, "setBrLenLabelColor")) {
+			pos.setValue(0); 
+			brLenColor = ColorDistribution.getColorFromArguments(arguments, pos);
+			updateTreeDisplays();
+		}
+
+
+		else if (checker.compare(this.getClass(), "Specifies whether or not branch length labels, if shown, are also shown on terminal branches of tree", "[on or off]", commandName, "showBrLenLabelsOnTerminals")) {
+			showBrLenLabelsOnTerminals.toggleValue(arguments);
+			updateTreeDisplays();
+		}
+		else if (checker.compare(this.getClass(), "Shows branch lengths on tree", "[on or off]", commandName, "labelBranchLengths")) {
+			labelBranchLengths.toggleValue(arguments);
+			updateTreeDisplays();
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree drawing module in use", null, commandName, "getTreeDrawer")) {
+			return treeDrawTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void endJob(){
+		treeDrawTask=null;
+		terminalNamesTask=null;
+		if (treeDisplay != null) {
+			treeDisplay=null;
+		}
+		else if (treeDisplays != null) {
+			for (int i=0; i<treeDisplays.length; i++) {
+				treeDisplays[i]=null;
+			}
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (MesquiteThread.isScripting())
+			return;
+		if (source instanceof DrawNamesTreeDisplay && Notification.getCode(notification) == TreeDisplay.FONTSIZECHANGED ){
+			MesquiteWindow w = null;
+			if (treeDisplay != null) 
+				w =MesquiteWindow.windowOfItem(treeDisplay);
+
+			else if (treeDisplays != null && numDisplays>0) 
+				w =MesquiteWindow.windowOfItem(treeDisplays[0]);
+			if (w != null){
+				w.windowResized();  //this is a hack to force them to update sizes
+				return;
+		}
+		}
+		
+		if (treeDisplay != null) {
+			((BasicTreeDisplay)treeDisplay).pleaseUpdate(true);
+		}
+		else if (treeDisplays != null) {
+			for (int i=0; i<numDisplays; i++) {
+				((BasicTreeDisplay)treeDisplays[i]).pleaseUpdate(true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Basic Tree Draw Coordinator";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Tree Drawing";
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the drawing of a tree by maintaining the basic TreeDisplay and by hiring a DrawTree module." ;
+	}
+
+}
+
+/* ======================================================================== */
+class BasicTreeDisplay extends TreeDisplay  {
+	boolean showPixels = false;//for debugging
+	BasicTreeDrawCoordinator ownerDrawModule;
+	public BasicTreeDisplay (BasicTreeDrawCoordinator ownerModule, Taxa taxa) {
+		super(ownerModule, taxa);
+		ownerDrawModule = ownerModule;
+		suppress = true;
+		setBackground(Color.white);
+	}
+	public void setTree(Tree tree) {
+		if (ownerModule.isDoomed())
+			return;
+		boolean wasNull = (this.tree == null);
+		((DrawTreeCoordinator)ownerModule).getNamesTask().setTree(tree);
+		super.setTree(tree);//here ask for nodelocs to be calculated
+		if (wasNull)
+			repaint();
+
+	}
+	/* */
+	public boolean autoFontSubmenu () {
+		return false;
+	}
+	public void setOrientation(int o){
+		boolean transpose =  (o == TreeDisplay.UP || o == TreeDisplay.DOWN) &&(getOrientation() == TreeDisplay.RIGHT || getOrientation() == TreeDisplay.LEFT);
+		transpose = transpose ||  (getOrientation() == TreeDisplay.UP || getOrientation() == TreeDisplay.DOWN) &&(o == TreeDisplay.RIGHT || o == TreeDisplay.LEFT);
+		super.setOrientation(o);
+		if (transpose) {
+			TreeWindowMaker tw = (TreeWindowMaker) ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+			if (tw != null)
+				tw.transposeField();
+		}
+
+	}
+	/**/
+	public void forceRepaint(){
+		if (ownerModule.isDoomed())
+			return;
+		repaintsPending = 0;
+		repaint(MesquiteThread.isScripting());
+	}
+	static int cr = 0;
+	public void repaint(boolean resetTree) {  //TODO: this whole system needs revamping.  
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+
+		if (tree!=null && resetTree) {
+			recalculatePositions();
+		}
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null && (!w.isVisible() || !w.isFrontMostInLocation()))
+			return;
+		repaintRequests++;
+		if (repaintRequests>1000){
+			repaintRequests = 0;
+			MesquiteMessage.warnProgrammer("more than 1000 repaint requests in Tree Display");
+			MesquiteMessage.printStackTrace("more than 1000 repaint requests in Tree Display");
+		}
+		super.repaint();
+	}
+
+	public void repaint(){
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w != null && (!w.isVisible() || !w.isFrontMostInLocation()))
+			return;
+		repaintRequests++;
+		if (repaintRequests>1000){
+			repaintRequests = 0;
+			MesquiteMessage.warnProgrammer("more than 1000 repaint requests in Tree Display");
+			MesquiteMessage.printStackTrace("more than 1000 repaint requests in Tree Display");
+		}
+
+		super.repaint();
+	}
+	/*_________________________________________________*/
+	long repaintRequests = 0;
+	int retry =0;
+	/*_________________________________________________*/
+	public void paint(Graphics g) {
+		if (getPrintingInProcess())
+			return;
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		setShowBranchColors(ownerDrawModule.showBranchColors.getValue());
+		if (MesquiteWindow.checkDoomed(this)) 
+			return;
+		setDrawingInProcess(true);
+		int initialPending = repaintsPending;
+		which =0;
+		if (bailOut(initialPending)) return;
+		if (getParent().getBackground()!=getBackground())
+			getParent().setBackground(getBackground());
+		if (bailOut(initialPending)) return;
+
+		if (getFieldWidth()==0 || getFieldHeight()==0)
+			setFieldSize(getBounds().width, getBounds().height);
+		if (bailOut(initialPending)) return;
+		if (getTipsMargin()<0 && getTreeDrawing()!=null && tree !=null)
+			getTreeDrawing().recalculatePositions(tree);
+		if (bailOut(initialPending)) return;
+		if (getTipsMargin()<0)
+			setTipsMargin(0);
+		if (bailOut(initialPending)) return;
+		super.paint(g);
+		if (bailOut(initialPending)) return;
+		Tree tempTree = getTree();
+		if (bailOut(initialPending)) return;
+		if (tree==null) {
+			//repaint();
+		}
+		else if (getTreeDrawing()==null) {
+			repaint();
+		}
+		else if (suppress) {
+			if (retry>500)
+				System.out.println("Error: retried " + retry + " times to draw tree; remains suppressed");
+			else {
+				retry++;
+				repaint();
+			}
+		}
+		else if (!tree.isLocked() && tree.isDefined()) {
+			int stage = -1;
+			try {
+				if (tree == null || tree.getTaxa().isDoomed()) {
+					setDrawingInProcess(false);
+					MesquiteWindow.uncheckDoomed(this);
+					return;
+				}
+				if (bailOut(initialPending)) return;
+				retry = 0;
+				if (showPixels){
+					for (int h=0; h<getFieldWidth() &&  h<getFieldHeight(); h += 50) {
+						g.setColor(Color.red);
+						g.drawString(Integer.toString(h), h, h);
+					}
+				}
+				int dRoot = getTreeDrawing().getDrawnRoot();
+				if (!tree.nodeExists(dRoot))
+					dRoot = tree.getRoot();
+				//getTreeDrawing().setHighlightsOn(tree.anySelectedInClade(dRoot));
+				if (bailOut(initialPending)) return;
+				stage = 0;
+				drawAllBackgroundExtras(tree, dRoot, g);
+				stage = 1;	
+
+				if (bailOut(initialPending)) return;
+				getTreeDrawing().drawTree(tree, dRoot, g); //ALLOW other drawnRoots!
+
+				//showNodeLocations(tree, g, tree.getRoot());
+				stage = 2;
+
+				if (bailOut(initialPending)) return;
+				drawAllExtras(tree, dRoot, g);
+				if (bailOut(initialPending)) return;
+				stage = 3;
+				if (ownerDrawModule.labelBranchLengths.getValue())
+					drawBranchLengthsOnTree(tree, dRoot, g);
+				stage = 4;
+				if (ownerDrawModule.showNodeNumbers.getValue())
+					drawNodeNumbersOnTree(tree, dRoot, g);
+				stage = 5;
+				if (bailOut(initialPending)) return;
+
+				if (!suppressNames && ownerModule!=null && ((DrawTreeCoordinator)ownerModule).getNamesTask()!=null)
+					((DrawTreeCoordinator)ownerModule).getNamesTask().drawNames(this, tree, dRoot, g);
+				stage = 6;
+				if (bailOut(initialPending)) return;
+				if (getTreeDrawing()!=null && tree !=null && getHighlightedBranch() > 0) 
+					getTreeDrawing().highlightBranch(tree, getHighlightedBranch(),g); 
+				stage = 7;
+				if (bailOut(initialPending)) return;
+			}
+			catch (Throwable e){
+				MesquiteMessage.println("Error or Exception in tree drawing (stage " + stage +") (" + e.toString() + ")");
+				//				MesquiteMessage.println("Error or Exception in tree drawing (stage " + stage +")");
+				MesquiteFile.throwableToLog(this, e);
+			}
+		}
+		setDrawingInProcess(false);
+		if (tempTree != tree) {
+			repaint();
+		}
+		else if (bailOut(initialPending))
+			return;
+		else if (!isVisible())
+			repaint();
+		else
+			repaintsPending = 0;
+		repaintRequests = 0;
+		MesquiteWindow.uncheckDoomed(this);
+		setInvalid(false);
+
+	}
+	public void update(Graphics g){
+		super.update(g);
+	}
+	private int which = 0;
+
+	private boolean bailOut(int initialPending){
+		which++;
+		if (getPrintingInProcess() || repaintsPending>initialPending){
+			setDrawingInProcess(false);
+			repaintsPending  = 0;
+			repaint();
+			return true;
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	private   void showNodeLocations(Tree tree, Graphics g, int N) {
+		if (tree.nodeExists(N)) {
+			g.setColor(Color.red);
+			g.fillOval(getTreeDrawing().x[N], getTreeDrawing().y[N], 4, 4);
+			g.setColor(branchColor);
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				showNodeLocations( tree, g, d);
+		}
+	}
+
+	/*_________________________________________________*/
+	public void print(Graphics g) {
+		printAll(g);
+	}
+	/*_________________________________________________*/
+	public void printAll(Graphics g) {
+		if (g == null)
+			return;
+		setPrintingInProcess(true);
+		if (getFieldWidth()==0 || getFieldHeight()==0)
+			setFieldSize(getBounds().width, getBounds().height);
+		int ww = getWidth();
+		int hh = getHeight();
+
+		setSize(getFieldWidth(), getFieldHeight());
+		//super.paint(g);
+		if (tree==null)
+			MesquiteMessage.warnProgrammer("tree NULL in tree draw coord");
+		else if ((!suppress) && (!tree.isLocked())) {
+			repaintsPending = 0;
+
+			/* NEEDS TO DRAW BACKGROUND EXTRAS */
+			int dRoot = getTreeDrawing().getDrawnRoot();
+			if (!tree.nodeExists(dRoot))
+				dRoot = tree.getRoot();
+			printAllBackgroundExtras(tree, dRoot, g);
+			getTreeDrawing().drawTree(tree, dRoot, g); //OTHER ROOTS
+			printAllExtras(tree, dRoot, g);
+			if (ownerDrawModule.labelBranchLengths.getValue())
+				drawBranchLengthsOnTree(tree, dRoot, g);
+			if (ownerDrawModule.showNodeNumbers.getValue())
+				drawNodeNumbersOnTree(tree, dRoot, g);
+			if (!suppressNames && ownerModule!=null && ((DrawTreeCoordinator)ownerModule).getNamesTask()!=null)
+				((DrawTreeCoordinator)ownerModule).getNamesTask().drawNames(this, tree, dRoot, g);
+			if (g instanceof PdfGraphics2D) 	//headless:  comment out
+				printComponentsPDF(g);		//headless:  comment out
+			else										//headless:  comment out
+				printComponents(g);
+		} 
+		else MesquiteMessage.warnProgrammer("tree drawing suppressed");
+		setSize(ww, hh);
+		setPrintingInProcess(false);
+	}
+	void printComponentsPDF(Graphics g){
+		Component[] comps = getComponents();
+		for (int i = 0; i<comps.length; i++){
+			Component comp = comps[i];
+			g.translate(comp.getX(), comp.getY());
+			comp.print(g);
+			g.translate(-comp.getX(), -comp.getY());
+		}
+	}
+	private int spotsize = 18;
+	/*_________________________________________________*/
+	private   void drawSpot(TreeDisplay treeDisplay, Tree tree, Graphics g, int N) {
+		if (tree.nodeExists(N)) {
+			if (treeDisplay.getVisRect() == null || treeDisplay.getVisRect().contains(treeDisplay.getTreeDrawing().x[N], treeDisplay.getTreeDrawing().y[N])){
+			if (tree.nodeIsInternal(N) || true){  //replace true by show terminal
+				//int i=0;
+				//int j=2;
+				String s = Integer.toString(N);
+				FontMetrics fm = g.getFontMetrics(g.getFont());
+				int width = fm.stringWidth(s) + 6;
+				int height = fm.getAscent()+fm.getDescent() + 6;
+				if (spotsize>width)
+					width = spotsize;
+				if (spotsize>height)
+					height = spotsize;
+				g.setColor(Color.white);
+				int x = treeDisplay.getTreeDrawing().x[N] - width/2;
+				int y = treeDisplay.getTreeDrawing().y[N] - height/2;
+				g.fillOval(x , y, width, height);
+			/*	g.setColor(Color.red);
+				Graphics2D g2 = (Graphics2D)g;
+				GraphicsConfiguration gc;
+				java.awt.geom.AffineTransform at, at0, nt;
+				String ss = "";
+				gc = g2.getDeviceConfiguration();
+				 at0 = g2.getTransform();
+				 at = gc.getDefaultTransform();
+				 nt = gc.getNormalizingTransform();
+				ss += " " +  at0.getTranslateX() + " " +  at.getTranslateX() + " " + nt.getTranslateX() + "/ ";
+				g.fillRect(x, y, width, height);
+				gc = g2.getDeviceConfiguration();
+				 at0 = g2.getTransform();
+				 at = gc.getDefaultTransform();
+				 nt = gc.getNormalizingTransform();
+				ss += " " +  at0.getTranslateX() + " " +  at.getTranslateX() + " " + nt.getTranslateX() + "/ ";
+				*/
+				g.setColor(Color.black);
+			   g.drawString(Integer.toString(N), x+2, y-4+ height);
+				/*g.drawRect(x , y, width, height);
+				gc = g2.getDeviceConfiguration();
+				 at0 = g2.getTransform();
+				 at = gc.getDefaultTransform();
+				 nt = gc.getNormalizingTransform();
+				ss += " " +  at0.getTranslateX() + " " +  at.getTranslateX() + " " + nt.getTranslateX() + "/ ";
+				*/
+				g.drawOval(x , y, width, height);
+				/*gc = g2.getDeviceConfiguration();
+				 at0 = g2.getTransform();
+				 at = gc.getDefaultTransform();
+				 nt = gc.getNormalizingTransform();
+				ss += " " +  at0.getTranslateX() + " " +  at.getTranslateX() + " " + nt.getTranslateX() + "/ ";
+				*/
+			}
+			}
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				drawSpot(treeDisplay, tree, g, d);
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawSpots(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Graphics g) {
+		if (MesquiteTree.OK(tree)) {
+			drawSpot(treeDisplay, tree, g, drawnRoot);  
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawNodeNumbersOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawSpots(this, tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public void writeLengthAtNode(Graphics g, int N,  Tree tree) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			writeLengthAtNode(g, d, tree);
+
+		if (!MesquiteDouble.isCombinable(tree.getBranchLength(N)) && !ownerDrawModule.getShowBrLensUnspecified())
+			return;
+
+		if (ownerDrawModule.getShowBrLenLabelsOnTerminals() || !tree.nodeIsTerminal(N)) {
+			StringBuffer sb = new StringBuffer();
+			MesquiteDouble.toStringDigitsSpecified(tree.getBranchLength(N), ownerDrawModule.getNumBrLenDecimals(), sb);
+			int shiftX = 10;
+			int shiftY = 10;
+			int nameLength = 0;
+			int nameHeight = 0;
+			int nodeX = getTreeDrawing().x[N];
+			int nodeY = getTreeDrawing().y[N];
+			MesquiteDouble angle = new MesquiteDouble();
+			if (ownerDrawModule.getCenterBrLenLabels()){
+				int motherNode = tree.motherOfNode(N);
+				if (tree.nodeExists(motherNode)){
+					shiftX = 0;
+					shiftY = 0;
+					nameLength = StringUtil.getStringDrawLength(g,sb.toString());
+					nameHeight = StringUtil.getTextLineHeight(g);
+					MesquiteNumber centeredNodeX = new MesquiteNumber();
+					MesquiteNumber centeredNodeY = new MesquiteNumber();
+					getTreeDrawing().getMiddleOfBranch(tree,N,centeredNodeX,centeredNodeY,angle);
+					if (centeredNodeX.isCombinable() && centeredNodeY.isCombinable()){
+						nodeX = centeredNodeX.getIntValue();
+						nodeY = centeredNodeY.getIntValue();
+					}
+				}
+			}
+
+			if (getOrientation() == TreeDisplay.UP) {
+				nodeY+=shiftY+ nameHeight/2;
+				nodeX-=nameLength/2;
+			}
+			else if (getOrientation() == TreeDisplay.DOWN) {
+				nodeY-=shiftY;
+				nodeX-=nameLength/2;
+			}
+			else if (getOrientation() == TreeDisplay.RIGHT) {
+				nodeX-=shiftX+ nameLength/2;
+				nodeY-=2;
+			}
+			else if (getOrientation() == TreeDisplay.LEFT) {
+				nodeX+=shiftX+getTreeDrawing().getEdgeWidth()-nameLength/2;
+			}
+
+			StringUtil.highlightString(g, sb.toString(), nodeX, nodeY, ownerDrawModule.getBrLenColor(), Color.white);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawBranchLengthsOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree!=null) {
+			g.setColor(Color.blue);
+			writeLengthAtNode(g, drawnRoot, tree);
+			g.setColor(Color.black);
+		}
+	}
+	/*_________________________________________________*/
+	public void fillTaxon(Graphics g, int M) {
+		((DrawTreeCoordinator)ownerModule).getNamesTask().fillTaxon(g, M);
+	}
+	/*_________________________________________________*/
+	public void redrawTaxa(Graphics g, int M) {
+	((DrawTreeCoordinator)ownerModule).getNamesTask().drawNames(this, tree, getTreeDrawing().getDrawnRoot(), g);
+		
+	}
+	/*_________________________________________________*/
+	private boolean responseOK(){
+		return (!getDrawingInProcess() && (tree!=null) && (!tree.isLocked()) && ownerModule!=null &&  (ownerModule.getEmployer() instanceof TreeDisplayActive));
+	}
+	/*_________________________________________________*/
+	public void mouseMoved(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (responseOK()) {
+			try{
+				Graphics g = getGraphics();
+				boolean dummy = ((TreeDisplayActive)ownerModule.getEmployer()).mouseMoveInTreeDisplay(modifiers,x,y,this, g);
+				if (g!=null)
+					g.dispose();
+			}
+			catch(Exception e){
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+		super.mouseMoved(modifiers,x,y, tool);
+	}
+	/*_________________________________________________*/
+	public void mouseDown(int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		boolean somethingTouched = false;
+		if (responseOK()) {
+			try{
+				Graphics g = getGraphics();
+				somethingTouched = ((TreeDisplayActive)ownerModule.getEmployer()).mouseDownInTreeDisplay(modifiers,x,y,this, g);
+				if (g!=null)
+					g.dispose();
+			}
+			catch(Exception e){
+			}
+		}
+		if (!somethingTouched)
+			super.panelTouched(modifiers, x,y, true);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	/*_________________________________________________*/
+	public void mouseDrag(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (responseOK()) {
+			try {
+				Graphics g = getGraphics();
+				boolean dummy = ((TreeDisplayActive)ownerModule.getEmployer()).mouseDragInTreeDisplay(modifiers,x,y,this, g);
+				if (g!=null)
+					g.dispose();
+			}
+			catch(Exception e){
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+		super.mouseDrag(modifiers,x,y, tool);
+	}
+	/*_________________________________________________*/
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (responseOK()) {
+			try {Graphics g = getGraphics();
+			boolean dummy = ((TreeDisplayActive)ownerModule.getEmployer()).mouseUpInTreeDisplay(modifiers,x,y,this, g);
+			if (g!=null)
+				g.dispose();
+			}
+			catch(Exception e){
+			}
+		}
+		MesquiteWindow.uncheckDoomed(this);
+		super.mouseUp(modifiers,x,y, tool);
+	}
+}
+
diff --git a/Source/mesquite/trees/BasicTreeWindowCoord/BasicTreeWindowCoord.java b/Source/mesquite/trees/BasicTreeWindowCoord/BasicTreeWindowCoord.java
new file mode 100644
index 0000000..4815683
--- /dev/null
+++ b/Source/mesquite/trees/BasicTreeWindowCoord/BasicTreeWindowCoord.java
@@ -0,0 +1,233 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BasicTreeWindowCoord;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Coordinates the display of the basic Tree Windows (BasicTreeWindowMaker actually makes the window) */
+public class BasicTreeWindowCoord extends FileInit {
+	ListableVector treeWindows;
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeWindowMaker.class, "Tree windows display trees to the user.", 
+				"You may request a tree window by selecting the Tree Window item under the Taxa&Trees menu");
+		e.setAsEntryPoint("makeTreeWindow");
+	}
+	MesquiteMenuItemSpec catw = null;
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Tree Window Coordinator"; 
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the creation of basic tree windows." ;
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		MesquiteSubmenuSpec mss = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "New Tree Window");
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "With Trees from Source", makeCommand("makeTreeWindow",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "With Tree To Edit By Hand", makeCommand("editingTreeWindow",  this));
+//		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "New Tree Window", makeCommand("makeTreeWindow",  this));
+		treeWindows = new ListableVector();
+		MesquiteSubmenuSpec mms = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Current Tree Windows", makeCommand("showTreeWindow",  this));
+		mms.setList(treeWindows);
+		catw = getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "Close All Tree Windows", makeCommand("closeAllTreeWindows",  this));
+		catw.setEnabled(false);
+
+		return true;
+	}
+
+	String taxaRef(Taxa d, boolean internal){
+		if (internal)
+			return getProject().getTaxaReferenceInternal(d);
+		else
+			return getProject().getTaxaReferenceExternal(d);
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		if (m instanceof TreeWindowMaker) {
+			for (int i=0; i<treeWindows.size(); i++){
+				MesquiteWindow w = (MesquiteWindow)treeWindows.elementAt(i);
+				if (w.getOwnerModule() == m || w.getOwnerModule() == null) {
+					treeWindows.removeElement(w, false);
+					if (catw != null) catw.setEnabled(treeWindows.size()>0);
+					resetAllMenuBars();
+					return;
+				}
+			}
+			resetAllMenuBars();
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof TreeWindowMaker) {
+				TreeWindowMaker dwm = (TreeWindowMaker)e;
+				Taxa d = (Taxa)dwm.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+				if (d != null) {
+					temp.addLine("makeTreeWindow " + taxaRef(d, false) + " ", dwm ); //TODO: must pass treeWindowTask
+				}
+			}
+		}
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public TreeWindowMaker showTreeWindow(Taxa taxa){
+		if (taxa==null)
+			return null;
+		TreeWindowMaker treeWindowTask= (TreeWindowMaker)hireCompatibleEmployee(TreeWindowMaker.class, taxa, null);
+		if (treeWindowTask !=null){
+			treeWindowTask.doCommand("makeTreeWindow", getProject().getTaxaReferenceInternal(taxa), CommandChecker.defaultChecker);
+			treeWindows.addElement(treeWindowTask.getModuleWindow(), false);
+			if (catw != null) catw.setEnabled(treeWindows.size()>0);
+			resetAllMenuBars();
+			return treeWindowTask;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public TreeWindowMaker makeWindowShowingTrees(Taxa taxa, TreeVector trees){
+		if (taxa==null)
+			return null;
+		TreeWindowMaker treeWindowTask = (TreeWindowMaker)hireNamedEmployee(TreeWindowMaker.class, "$ #BasicTreeWindowMaker edit", taxa);
+		if (treeWindowTask !=null){
+			boolean wasScrip = MesquiteThread.isScripting();
+			CommandRecord rec = MesquiteThread.getCurrentCommandRecord();
+			if (rec != null)
+				rec.setScripting(true);
+			treeWindowTask.doCommand("makeTreeWindow", getProject().getTaxaReferenceInternal(taxa), CommandChecker.defaultChecker);
+			if (rec != null)
+				rec.setScripting(wasScrip);
+			treeWindows.addElement(treeWindowTask.getModuleWindow(), false);
+			if (catw != null) catw.setEnabled(treeWindows.size()>0);
+			TreesManager manager = (TreesManager)findElementManager(TreeVector.class);
+			int whichBlock = manager.getTreeBlockNumber(trees.getTaxa(), trees);
+			TreeSource ts = (TreeSource)treeWindowTask.getTreeSource();
+			ts.doCommand("setTreeBlockInt", Integer.toString(whichBlock), CommandChecker.defaultChecker);
+			resetAllMenuBars();
+		}
+		return treeWindowTask;
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Requests that a tree window be made", "[number of taxa block]", commandName, "makeTreeWindow") || checker.compare(this.getClass(), "Requests that a tree window be made for hand editing", "[number of taxa block]", commandName, "editingTreeWindow")) {
+			Taxa taxa = null;
+			MesquiteFile file = null;
+			if (getProject() == null)
+				return null;
+			if (getProject().getNumberTaxas()==0){
+				discreetAlert("A taxa block must be created first before a tree window can be shown");
+				return null;
+			}
+			if (checker != null)
+				file = checker.getFile();
+			if (!StringUtil.blank(arguments)) //rearranged to attempt to get some taxa to be used
+				taxa =  getProject().getTaxa(file, parser.getFirstToken(arguments));
+			if (taxa == null && !StringUtil.blank(arguments)) //rearranged to attempt to get some taxa to be used
+				taxa =  getProject().getTaxa(parser.getFirstToken(arguments));
+			if (taxa == null){
+				int numTaxas = getProject().getNumberTaxas(file);
+				//if only one taxa block, use it
+				if (numTaxas<=0){
+					return null;
+				}
+				else if (numTaxas==1){
+					taxa =  getProject().getTaxa(file, 0);
+				}
+				else {
+					taxa =  getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show trees in the tree window?");
+					//else, query user
+				}
+			}
+			if (taxa==null)
+				return null;
+			TreeWindowMaker treeWindowTask= null;
+			if (commandName.equalsIgnoreCase("editingTreeWindow"))
+				treeWindowTask = (TreeWindowMaker)hireNamedEmployee(TreeWindowMaker.class, "$ #BasicTreeWindowMaker edit", taxa);
+			else
+				treeWindowTask= (TreeWindowMaker)hireCompatibleEmployee(TreeWindowMaker.class, taxa, "Tree window style");
+
+			if (treeWindowTask !=null){
+				treeWindowTask.doCommand("makeTreeWindow", getProject().getTaxaReferenceInternal(taxa), checker);
+				treeWindows.addElement(treeWindowTask.getModuleWindow(), false);
+				if (catw != null) catw.setEnabled(treeWindows.size()>0);
+				resetAllMenuBars();
+				return treeWindowTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes all tree windows", null, commandName, "closeAllTreeWindows")) {
+			for (int i = treeWindows.size()-1; i>=0; i--){
+				MesquiteWindow win = (MesquiteWindow)treeWindows.elementAt(i);
+				TreeWindowMaker t = (TreeWindowMaker)win.getOwnerModule();
+				t.windowGoAway(win);
+			}
+			if (catw != null) catw.setEnabled(treeWindows.size()>0);
+			resetAllMenuBars();
+
+		}
+		else if (checker.compare(this.getClass(), "Shows an existing tree window", "[number of tree window as employee of coordinator]", commandName, "showTreeWindow")) {
+			pos.setValue(0);
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if ((which == 0 || MesquiteInteger.isPositive(which)) && which<treeWindows.size()) {
+				MesquiteWindow win = (MesquiteWindow)treeWindows.elementAt(which);
+				win.show();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Returns module controlling i'th tree window", "[i]", commandName, "getTreeWindow")) {
+			pos.setValue(0);
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if ((which == 0 || MesquiteInteger.isPositive(which)) && which<treeWindows.size()) {
+				MesquiteWindow win = (MesquiteWindow)treeWindows.elementAt(which);
+				return win.getOwnerModule();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	/**Returns command to hire employee if clonable*/
+	public String getClonableEmployeeCommand(MesquiteModule employee){
+		if (employee!=null && employee.getEmployer()==this) {
+			if (employee.getHiredAs()==TreeWindowMaker.class) {
+				Taxa d = (Taxa)employee.doCommand("getTaxa", null, CommandChecker.defaultChecker);
+				if (d != null) {
+					return ("makeTreeWindow " + taxaRef(d, true) + "  " + StringUtil.tokenize(employee.getName()) + ";");//quote
+				}
+			}
+		}
+		return null;
+	}
+
+}
+
+
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32collapse.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32collapse.gif
new file mode 100644
index 0000000..3b642b4
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32collapse.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32collapseAllBelow.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32collapseAllBelow.gif
new file mode 100644
index 0000000..adddb02
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32collapseAllBelow.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32collapseall.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32collapseall.gif
new file mode 100644
index 0000000..bd4d1da
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32collapseall.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32interchange.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32interchange.gif
new file mode 100644
index 0000000..bafef38
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32interchange.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32ladderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32ladderize.gif
new file mode 100644
index 0000000..38a307c
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32ladderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32magnify.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32magnify.gif
new file mode 100644
index 0000000..b6cbca8
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32magnify.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32reroot.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32reroot.gif
new file mode 100644
index 0000000..547fed0
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32reroot.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32reverseLadderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32reverseLadderize.gif
new file mode 100644
index 0000000..46566fe
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32reverseLadderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32scissors.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32scissors.gif
new file mode 100644
index 0000000..13c582b
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32scissors.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32triangle.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32triangle.gif
new file mode 100644
index 0000000..98b865d
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32triangle.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32zoom.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32zoom.gif
new file mode 100644
index 0000000..94345ed
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32zoom.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/32zoomOut.gif b/Source/mesquite/trees/BasicTreeWindowMaker/32zoomOut.gif
new file mode 100644
index 0000000..d2854ee
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/32zoomOut.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64collapse.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64collapse.gif
new file mode 100644
index 0000000..cbe994b
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64collapse.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64collapseAllBelow.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64collapseAllBelow.gif
new file mode 100644
index 0000000..cbed623
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64collapseAllBelow.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64collapseall.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64collapseall.gif
new file mode 100644
index 0000000..17adae2
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64collapseall.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64interchange.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64interchange.gif
new file mode 100644
index 0000000..f67cbaa
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64interchange.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64ladderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64ladderize.gif
new file mode 100644
index 0000000..7cdd14d
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64ladderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64magnify.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64magnify.gif
new file mode 100644
index 0000000..2cd6bd2
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64magnify.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64reroot.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64reroot.gif
new file mode 100644
index 0000000..e82124a
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64reroot.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64reverseLadderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64reverseLadderize.gif
new file mode 100644
index 0000000..cd6522c
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64reverseLadderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64scissors.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64scissors.gif
new file mode 100644
index 0000000..e221729
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64scissors.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64triangle.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64triangle.gif
new file mode 100644
index 0000000..13a609e
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64triangle.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64zoom.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64zoom.gif
new file mode 100644
index 0000000..f81cdf5
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64zoom.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/64zoomOut.gif b/Source/mesquite/trees/BasicTreeWindowMaker/64zoomOut.gif
new file mode 100644
index 0000000..f208c52
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/64zoomOut.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/BasicTreeWindowMaker.java b/Source/mesquite/trees/BasicTreeWindowMaker/BasicTreeWindowMaker.java
new file mode 100644
index 0000000..b81df2c
--- /dev/null
+++ b/Source/mesquite/trees/BasicTreeWindowMaker/BasicTreeWindowMaker.java
@@ -0,0 +1,5847 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BasicTreeWindowMaker;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+
+import mesquite.categ.lib.CategDataEditorInitD;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+import java.awt.datatransfer.*;
+
+import mesquite.tol.lib.TaxonOnWebServer;
+import mesquite.trees.lib.TreeInfoExtraPanel;
+
+/** Makes and manages a Tree Window for tree editing and visualization */
+public class BasicTreeWindowMaker extends TreeWindowMaker implements CommandableOwner, TreeContext, TreeDisplayActive{
+
+
+	public String getName() {
+		return "Tree Window";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Makes a basic tree window, which contains a tool palette.  Hires assistants for the tree window (e.g., Trace Character)." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeDisplayAssistantA.class, "A Tree Window displays trees, and can use various assistants to do analyses.",
+				"You can request this under the <strong>Analysis</strong> menu of the <strong>Tree Window.</strong>");
+		e.setPriority(2);
+		e.setAsEntryPoint("newAssistant");
+		EmployeeNeed e111 = registerEmployeeNeed(TreeDisplayAssistantAO.class, "A Tree Window displays trees, and can use various assistants to do analyses.",
+				"You can request this under the <strong>Analysis (Other)</strong> submenu of the <strong>Tree Window.</strong>");
+		e111.setPriority(2);
+		e111.setAsEntryPoint("newAssistant");
+
+		EmployeeNeed e2 = registerEmployeeNeed(TreeDisplayAssistantD.class, "A Tree Window displays trees, and can use various assistants to modify the display.",
+				"You can request this under the <strong>Tree</strong> menu of the <strong>Tree Window.</strong>");
+		e2.setAsEntryPoint("newAssistant");
+
+
+		EmployeeNeed e3 = registerEmployeeNeed(TreeWindowAssistantA.class, "A Tree Window displays trees, and can use various assistants to do analyses.",
+				"You can request this under the <strong>Analysis</strong> menu of the <strong>Tree Window.</strong>");
+		e3.setAsEntryPoint("newWindowAssistant");
+
+
+		EmployeeNeed e4 = registerEmployeeNeed(TreeWindowAssistantC.class, "A Tree Window displays trees, and can use various assistants to do analyses.",
+				"You can request this under the <strong>New Chart for Tree submenu of the Analysis</strong> menu of the <strong>Tree Window. </strong>");
+		e4.setAsEntryPoint("newWindowAssistant");
+
+
+		EmployeeNeed e5 = registerEmployeeNeed(TreeWindowAssistantN.class, "A Tree Window displays trees, and can use various assistants.",
+				"You can request this under the <strong>Tree</strong> menu of the <strong>Tree Window.</strong>");
+		e5.setAsEntryPoint("newWindowAssistant");
+
+
+
+		EmployeeNeed e6 = registerEmployeeNeed(TreeSource.class, "A Tree Window needs a source of trees.",
+				"You can request the source of trees when the Tree Window starts, or later using the Tree Source submenu of the Tree menu of the Tree Window.");
+		e6.setPriority(2);
+		e6.setAsEntryPoint("setTreeSource");
+		EmployeeNeed e20 = registerEmployeeNeed(TreeDisplayAssistantDI.class, "A Tree Window uses various assistants.",
+				"This is activated automatically.");
+		EmployeeNeed e7 = registerEmployeeNeed(TreeDisplayAssistantI.class, "A Tree Window uses various assistants.",
+				"This is activated automatically.");
+		EmployeeNeed e8 = registerEmployeeNeed(TreeWindowAssistantI.class, "A Tree Window uses various assistants.",
+				"This is activated automatically.");
+		EmployeeNeed e9 = registerEmployeeNeed(DrawTreeCoordinator.class, "A Tree Window displays a tree drawn in various possible styles.",
+				"This is activated automatically.");
+		e9.setPriority(2);
+		EmployeeNeed e10 = registerEmployeeNeed(TreeAlterer.class, "Trees can be altered within the Tree Window.",
+				"Tree altering methods are available in the Alter/Transform Tree submenu of the Tree menu of the Tree Window.<br>");
+		e10.setAsEntryPoint("alterTree");
+		e10.setPriority(3);
+		EmployeeNeed e11 = registerEmployeeNeed(BranchLengthsAlterer.class, "The branch lengths of trees can be altered within the Tree Window.",
+				"Methods to alter branch lengths are available in the Alter/Transform Branch Lengths submenu of the Tree menu of the Tree Window.<br>");
+		e11.setAsEntryPoint("alterBranchLengths");
+		e11.setPriority(3);
+
+	}
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Interchange branches", "(A tool of the Tree Window) Exchanges the position of two branches in a tree in a tree window", null, getPath() + "interchange.gif"));
+		registerSubfunction(new FunctionExplanation("Collapse branch", "(A tool of the Tree Window) Destroys a branch, thus collapsing its daughter branches into a polytomy", null, getPath() + "collapse.gif"));
+		registerSubfunction(new FunctionExplanation("Collapse all branches", "(A tool of the Tree Window) Destroys all internal branches in a clade, thus collapsing the entire clade to a polytomous bush", null, getPath() + "collapseall.gif"));
+		registerSubfunction(new FunctionExplanation("Reroot at branch", "(A tool of the Tree Window) Reroots the tree along the branch touched", null, getPath() + "reroot.gif"));
+		registerSubfunction(new FunctionExplanation("Prune clade", "(A tool of the Tree Window) Deletes the clade of the node touched.  Only the tree being operated on is affected (that is, the terminal taxa are not deleted from the data file)", "scissors delete", getPath() + "scissors.gif"));
+		registerSubfunction(new FunctionExplanation("Ladderize clade", "(A tool of the Tree Window) Ladderizes a clade by rotating branches until largest of sister clades on right (or left, if the Option key is held down)", null, getPath() + "ladderize.gif"));
+		super.getSubfunctions();
+	}
+	/*.................................................................................................................*/
+	public DrawTreeCoordinator treeDrawCoordTask;
+	public TreeSource treeSourceTask;
+	public Vector contextListeners;
+	Taxa taxa;
+	static boolean warnUnsaved;
+	boolean 	editMode = false;
+	MesquiteBoolean printNameOnTree;
+
+	BasicTreeWindow basicTreeWindow;
+	MesquiteString treeSourceName;
+	MagnifyExtra magnifyExtra;
+	MesquiteString xmlPrefs= new MesquiteString();
+	boolean useXORForBranchMoves = true;
+	String xmlPrefsString = null;
+	static {
+		warnUnsaved = true;
+	}
+
+	/*...................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences(xmlPrefs);
+		xmlPrefsString = xmlPrefs.getValue();
+		makeMenu("Tree");
+		if (condition !=null && condition instanceof Taxa) {
+			taxa = (Taxa)condition;
+		}
+		resetContainingMenuBar();
+		if (MesquiteThread.isScripting() || (arguments == null || !arguments.equalsIgnoreCase("edit")))
+			treeSourceTask= (TreeSource)hireCompatibleEmployee(TreeSource.class, condition, "Source of trees (Tree window)");
+		else {
+			treeSourceTask= (TreeSource)hireNamedEmployee(TreeSource.class, "$ #StoredTrees laxMode", taxa, false);
+			editMode = true;
+		}
+
+		if (treeSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of trees was obtained.");
+		treeSourceName = new MesquiteString(treeSourceTask.getName());
+		//			treeSourceTask.setHiringCommand(makeCommand("setTreeSource",  this));
+		defineMenus(false);
+		if (MesquiteThread.isScripting() && getProject().developing)
+			respondToWindowResize = false;  //this prevents a lot of tree/window resizing when file being re-read
+
+		contextListeners = new Vector();
+		//setAutoSaveMacros(true);
+		return true;
+	}
+	public Taxa getTaxa(){
+		return taxa;
+	}
+	/*.................................................................................................................*/
+	public DrawTreeCoordinator hireTreeDrawCoordTask() {
+		treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(DrawTreeCoordinator.class, null);
+		if (treeDrawCoordTask== null) {
+			sorry(getName() + " couldn't start because no tree draw coordinating module was obtained.");
+			return null;
+		}
+		treeDrawCoordTask.setToLastEmployee(true);
+		hireAllEmployees(TreeDisplayAssistantI.class);
+		hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration enumeration = getEmployeeVector().elements();
+		while (enumeration.hasMoreElements()) {
+			Object obj = enumeration.nextElement();
+			if (obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistantDI init = (TreeDisplayAssistantDI) obj;
+				treeDrawCoordTask.requestGuestMenuPlacement(init);
+			}
+		}
+		resetContainingMenuBar();
+		return treeDrawCoordTask;
+	}
+	/*--------------------------------------*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	boolean respondToWindowResize = true;
+	public void fileReadIn(MesquiteFile f) {
+		respondToWindowResize = true;
+		if (basicTreeWindow != null)
+			basicTreeWindow.sizeDisplay();
+	}
+
+	public String getExpectedPath(){
+		return getPath() + "recent";
+	}
+	/*--------------------------------------*/
+	/*Menus defined in this method are visible to Mesquite's automatic documentation system  <b>(overrides method of MesquiteModule)</b>*/
+	public void defineMenus(boolean accumulating){
+		if (accumulating || numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", makeCommand("setTreeSource",  this));
+			if (!accumulating){
+				mss.setSelected(treeSourceName);
+				mss.setList(TreeSource.class);
+				if (taxa !=null)
+					mss.setCompatibilityCheck(taxa);
+			}
+		}
+	}
+	public  Commandable[] getCommandablesForAccumulation(){
+		Commandable[] cs = new Commandable[1];
+		cs[0]= new BasicTreeWindow();
+		return cs;
+	}
+	/*.................................................................................................................*/
+	boolean handlingQuitTreeSource = false;
+
+	void disconnectFromTreeBlock(boolean fireCurrentTask){
+		handlingQuitTreeSource = true;
+		
+		String d = basicTreeWindow.getTreeDescription();
+		String n = "Tree recovered from: " + basicTreeWindow.getTreeNameAndDetails();
+		if (fireCurrentTask)
+			fireEmployee(treeSourceTask);
+		TreeSource temp = (TreeSource)hireNamedEmployee(TreeSource.class, "$ #StoredTrees laxMode", taxa, false);
+		if (temp !=null){
+			treeSourceTask = temp;
+			treeSourceName.setValue(treeSourceTask.getName());
+			if (basicTreeWindow!=null) {
+				basicTreeWindow.setTreeSource(treeSourceTask);
+				basicTreeWindow.showTree();
+			}
+			treeSourceTask.setPreferredTaxa(taxa);
+			editMode = true;
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+		basicTreeWindow.setStoreTreeAsMenuItems(true);
+		basicTreeWindow.resetForTreeSource(true, false, true, 0);
+		basicTreeWindow.setTreeDescription(d, n);
+		basicTreeWindow.treeEdited = false;
+		basicTreeWindow.setHighlighted(false);
+		handlingQuitTreeSource = false;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		if (m instanceof TreeSource && !handlingQuitTreeSource){
+			disconnectFromTreeBlock(false);
+		}
+		else if (basicTreeWindow!=null)
+			basicTreeWindow.contentsChanged();
+	}
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			if (prefs[0].equals("warned")) {
+				warnUnsaved = false;
+			}
+		}
+	}
+	/*.................................................................................................................*/
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "warnUnsaved", warnUnsaved);   
+		if (basicTreeWindow!=null){
+			String s = basicTreeWindow.preparePreferencesForXML();
+			if (StringUtil.notEmpty(s))
+				buffer.append(s);
+		}
+		return buffer.toString();
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("warnUnsaved".equalsIgnoreCase(tag))
+			warnUnsaved = MesquiteBoolean.fromTrueFalseString(content);
+	}
+
+	public boolean treeIsEdited(){
+		if (basicTreeWindow == null)
+			return false;
+		return basicTreeWindow.treeEdited;
+	}
+
+	/*....................................................THIS SHOULD not normally be called within Mesquite.  It is here for use of Mesquite as library, e.g. for R-java.............................................................*/
+	public void showTree(Tree tree){
+		if (basicTreeWindow==null)
+			return;
+		MesquiteBoolean editStatusToSet = new MesquiteBoolean();
+		basicTreeWindow.setCloneOfTree(tree, true, editStatusToSet);
+		basicTreeWindow.treeEdited = editStatusToSet.getValue();
+	}
+	/*.................................................................................................................*/
+	/** return whether or not this module should have snapshot saved when saving a macro given the current snapshot mode.*/
+	public boolean satisfiesSnapshotMode(){
+		return (MesquiteTrunk.snapshotMode == Snapshot.SNAPALL || MesquiteTrunk.snapshotMode == Snapshot.SNAPDISPLAYONLY);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (basicTreeWindow==null)
+			return null;
+		//		if (MesquiteTrunk.snapshotMode==Snapshot.SNAPDISPLAYONLY)
+		//			return null;
+
+		Snapshot temp = new Snapshot();
+		Snapshot fromWindow = basicTreeWindow.getSnapshot(file);
+		temp.addLine("suppressEPCResponse");
+
+		if (MesquiteTrunk.snapshotMode!=Snapshot.SNAPDISPLAYONLY){
+			if (!editMode)
+				temp.addLine("setTreeSource " , treeSourceTask);
+			else
+				temp.addLine("setTreeSourceEditMode",  treeSourceTask);
+
+			temp.addLine("setAssignedID " + getPermanentIDString());  //for tree context
+		}
+		temp.addLine("getTreeWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+
+		if (MesquiteTrunk.snapshotMode==Snapshot.SNAPDISPLAYONLY){
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof TreeDisplayAssistantDI) {
+					temp.addLine("\tnewAssistant " , ((MesquiteModule)e));
+				}
+			}
+		} else {
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof TreeDisplayAssistantD || e instanceof TreeDisplayAssistantA || e instanceof TreeDisplayAssistantAO) {
+					temp.addLine("\tnewAssistant " , ((MesquiteModule)e));
+				}
+			}
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof TreeWindowAssistantC || e instanceof TreeWindowAssistantN || e instanceof TreeWindowAssistantA) {
+					temp.addLine("\tnewWindowAssistant " , ((MesquiteModule)e));
+				}
+			}
+		}
+		temp.addLine("endTell");
+		if (MesquiteTrunk.snapshotMode!=Snapshot.SNAPDISPLAYONLY && editMode){
+				temp.addLine("setEditMode " + StringUtil.tokenize(basicTreeWindow.getTreeNameAndDetails()));
+				temp.addLine("desuppressEPCResponseNORESET");
+		}
+		else
+			temp.addLine("desuppressEPCResponse");
+
+		return temp;
+	}
+	/*.................................................................................................................*
+	public void getSnapshotForMacro(Snapshot temp) {
+		temp.addLine("getTreeWindow");
+		temp.addLine("tell It");
+//		temp.incorporate(fromWindow, true);
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof TreeDisplayAssistantDI) {
+				temp.addLine("\tnewAssistant " , ((MesquiteModule)e));
+			}
+		}
+		temp.addLine("endTell");
+	}
+	/*.................................................................................................................*/
+	/** Query module as to whether conditions are such that it will have to quit soon -- e.g. if its taxa block has been doomed.  The tree window, data window, 
+	etc. override this to return true if their object is doomed. This is useful in case MesquiteListener disposing method is not called for an employer before one of its
+	employees discovers that it needs to quit.  If the employer is going to quit anyway,there is no use to use auto rehire for the quit employee.*/
+	public boolean quittingConditions(){
+		return (taxa.isDoomed());
+	}
+
+	boolean suppressEPCResponse = false;
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns the block of taxa associated with this tree window", null, commandName, "getTaxa")) {
+			return taxa;
+		}
+		else if (checker.compare(this.getClass(), "Displays the tree window", null, commandName, "show")) {
+			displayTreeWindow();
+		}
+		else if (checker.compare(this.getClass(), "Suppresses responding to parameters changed.", null, commandName, "suppressEPCResponse")) {
+			suppressEPCResponse = true;
+		}
+		else if (checker.compare(this.getClass(), "Suppresses responding to parameters changed.", null, commandName, "desuppressEPCResponse")) {
+			suppressEPCResponse = false;
+			if (basicTreeWindow != null)
+				basicTreeWindow.resetForTreeSource(false, false, false, MesquiteInteger.inapplicable);
+		}
+		else if (checker.compare(this.getClass(), "Suppresses responding to parameters changed.", null, commandName, "desuppressEPCResponseNORESET")) {
+			suppressEPCResponse = false;
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree in the window to the description passed", "[standard tree description]", commandName, "setTree")) { //added 10 Jan 02 for use in Send Script dialog
+			if (basicTreeWindow!=null){
+				basicTreeWindow.doCommand(commandName, arguments, checker);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the mode to that of With Trees To Edit By Hand", null, commandName, "setEditMode")) {
+			String mssage = parser.getFirstToken(arguments);
+			editMode = true;
+			basicTreeWindow.treeEdited = false;
+			basicTreeWindow.forceRenameTree(mssage);
+			basicTreeWindow.originalTree = null;
+			basicTreeWindow.setHighlighted(false);
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of trees for edit mode", null, commandName, "setTreeSourceEditMode")) {
+			if (basicTreeWindow!=null)
+				basicTreeWindow.hideTree();
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, "$ #StoredTrees laxMode", "Source of trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				treeSourceName.setValue(treeSourceTask.getName());
+				if (basicTreeWindow!=null) {
+					basicTreeWindow.setTreeSource(treeSourceTask);
+					basicTreeWindow.showTree();
+					basicTreeWindow.resetForTreeSource(true, false, true, 0);
+				}
+				treeSourceTask.setPreferredTaxa(taxa);
+
+				resetContainingMenuBar();
+				resetAllWindowsMenus();
+				return treeSourceTask;
+			}
+			else if (basicTreeWindow!=null)
+				basicTreeWindow.showTree();
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of trees", "[name of tree source module]", commandName, "setTreeSource")) {
+			if (basicTreeWindow!=null)
+				basicTreeWindow.hideTree();
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees", treeSourceTask);
+			if (temp !=null){
+				treeSourceTask = temp;
+				//					treeSourceTask.setHiringCommand(makeCommand("setTreeSource",  this));
+				treeSourceName.setValue(treeSourceTask.getName());
+				if (basicTreeWindow!=null) {
+					basicTreeWindow.setTreeSource(treeSourceTask);
+					basicTreeWindow.showTree();
+				}
+				treeSourceTask.setPreferredTaxa(taxa);
+
+				resetContainingMenuBar();
+				resetAllWindowsMenus();
+				return treeSourceTask;
+			}
+			else if (basicTreeWindow!=null)
+				basicTreeWindow.showTree();
+		}
+		else if (checker.compare(this.getClass(), "Constructs a tree window referring to a block of taxa, or returns the existing window if this module has already made one.", "[number of block of taxa, 0 based]", commandName, "makeTreeWindow")) {
+			if (basicTreeWindow != null)
+				return basicTreeWindow;
+			String tRef = parser.getFirstToken(arguments);
+
+			int setNumber = MesquiteInteger.fromString(tRef);
+			Taxa taxa = null;
+			if (!MesquiteInteger.isCombinable(setNumber)) {
+				taxa = getProject().getTaxaLastFirst(tRef); 
+			}
+			else
+				taxa = getProject().getTaxa(checker.getFile(), setNumber);
+			if (taxa !=null) {
+				makeTreeWindow(taxa);
+				return basicTreeWindow;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree draw coordinating module", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree window", null, commandName, "getTreeWindow")) {
+			return basicTreeWindow;
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree", null, commandName, "getTree")) {
+			return getTree();
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree as having been edited (thus showing it as \"untitled\"", null, commandName, "treeEdited")) {
+			basicTreeWindow.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Hires a tree display assistant module", "[name of assistant module]", commandName, "newAssistant")) {
+			return basicTreeWindow.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Hires a tree window assistant module", "[name of assistant module]", commandName, "newWindowAssistant")) {
+			return basicTreeWindow.doCommand(commandName, arguments, checker);
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+		if (basicTreeWindow==null)
+			return;
+		basicTreeWindow.contentsChanged();
+		basicTreeWindow.treeDisplay.pleaseUpdate(false);
+
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee calling its dearEmployerShouldIHandleThis method.  The MesquiteModule should respond false if the employer wants to handle it itself. */
+	public boolean employeeRequestingIndependenceOfAction(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof TreeSource) {
+			int code = Notification.getCode(notification);
+			if (code == MesquiteListener.BLOCK_DELETED && (employee.nameMatches("StoredTrees") || (employee.nameMatches("ConsensusTree"))))
+				return false;
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (basicTreeWindow==null)
+			return;
+		if (employee instanceof DrawTreeCoordinator){ 
+			if (source instanceof DrawNamesTreeDisplay && Notification.getCode(notification) == TreeDisplay.FONTSIZECHANGED ){
+				basicTreeWindow.sizeDisplay();
+				basicTreeWindow.treeDisplay.pleaseUpdate(true);
+				return;
+			}
+			if (basicTreeWindow.drawSizeSubmenu != null){
+				if (basicTreeWindow.drawSizeSubmenu.isEnabled() != !treeDrawCoordTask.hasPreferredSize()){
+					basicTreeWindow.drawSizeSubmenu.setEnabled(!treeDrawCoordTask.hasPreferredSize());
+					basicTreeWindow.sizeDisplay();
+					basicTreeWindow.treeDisplay.pleaseUpdate(true);
+					return;
+				}
+			}
+			Dimension d = treeDrawCoordTask.getPreferredSize();
+			if (d == null && basicTreeWindow.oldPreferred == null)
+				return;
+			if ((d == null && basicTreeWindow.oldPreferred !=null)|| (basicTreeWindow.oldPreferred == null && d != null) || (d.width != basicTreeWindow.oldPreferred.width && d.height != basicTreeWindow.oldPreferred.height)) {
+				//if (basicTreeWindow.drawingSizeMode != BasicTreeWindow.FIXEDSIZE){
+				//basicTreeWindow.setSuggestedSize(false, true);
+				basicTreeWindow.sizeDisplay();
+				basicTreeWindow.treeDisplay.pleaseUpdate(true);
+				//}
+			}
+
+		}
+		else if (employee instanceof TreeSource) {
+			if (suppressEPCResponse)
+				return;
+			int code = Notification.getCode(notification);
+			if (code == MesquiteListener.BLOCK_DELETED && (employee.nameMatches("StoredTrees") || (employee.nameMatches("ConsensusTree")))){
+				disconnectFromTreeBlock(true);
+			}
+			else 
+				if (code == MesquiteListener.ITEMS_ADDED){
+					if (basicTreeWindow.usingDefaultTree){
+						basicTreeWindow.resetForTreeSource(false, false, false, Notification.getCode(notification)); 
+						basicTreeWindow.contentsChanged();
+					}
+					else
+						basicTreeWindow.numTreesChanged();   
+				}
+				else if (code == MesquiteListener.NUM_ITEMS_CHANGED){
+					basicTreeWindow.numTreesChanged(); 
+				}
+				else if (!(notification != null && notification.getObjectClass() == Taxa.class)){  //if notification came from TAxa changes, don't respond, as that will be handled otherwise
+					if (code != MesquiteListener.SELECTION_CHANGED ){ 
+						if (basicTreeWindow.originalTree != null && basicTreeWindow.originalTree instanceof MesquiteTree && basicTreeWindow.taxa != null)
+							basicTreeWindow.taxa.removeListener((MesquiteTree)basicTreeWindow.originalTree);
+						basicTreeWindow.originalTree = null;  //otree
+
+						basicTreeWindow.resetForTreeSource(false, false, MesquiteThread.isDuringNotification(), Notification.getCode(notification)); //if switching between tree blocks, should reset to zero!  If storing tree in tree block, shouldn't!
+						basicTreeWindow.contentsChanged();
+					}
+				}
+		}
+		else  {
+			if (suppressEPCResponse)
+				return;
+			if (basicTreeWindow.treeDisplay!=null) {
+				basicTreeWindow.contentsChanged();
+				TreeDisplayExtra[] ee = basicTreeWindow.treeDisplay.getMyExtras(employee);
+				if (ee != null)
+					for (int i=0; i<ee.length; i++)
+						ee[i].setTree(basicTreeWindow.treeDisplay.getTree()); //done to force recalculations
+				basicTreeWindow.treeDisplay.pleaseUpdate(false);
+			}
+		}
+
+	}
+	/*.................................................................................................................*/
+	public TreeDisplay getTreeDisplay(){
+		return basicTreeWindow.treeDisplay;
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public Tree getTree(){
+		if (basicTreeWindow==null)
+			return null;
+		else
+			return basicTreeWindow.tree;
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public String getContextName(){
+		if (basicTreeWindow==null)
+			return "Tree Window";
+		return basicTreeWindow.getTitle();
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public void addTreeContextListener (TreeContextListener listener){
+		if (listener!=null && contextListeners.indexOf(listener)<0)
+			contextListeners.addElement(listener);
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public void removeTreeContextListener (TreeContextListener listener){
+		contextListeners.removeElement(listener);
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public MesquiteModule getTreeSource(){
+		return treeSourceTask;
+	}
+	/*.................................................................................................................*/
+	private void makeTreeWindow(Taxa taxa){
+		incrementMenuResetSuppression();
+		this.taxa = taxa;
+		treeSourceTask.setPreferredTaxa(taxa);
+		BasicTreeWindow btw = new BasicTreeWindow( this, treeSourceTask, taxa, xmlPrefsString, editMode);
+		setModuleWindow(btw);
+		basicTreeWindow = (BasicTreeWindow) getModuleWindow();
+		Enumeration e = getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeDisplayAssistantI || obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistant tca = (TreeDisplayAssistant)obj;
+				basicTreeWindow.addAssistant(tca);
+			}
+		}
+		btw.sizeDisplay();
+		MesquiteMenuSpec aux = addAuxiliaryMenu("Analysis:Tree");
+		MesquiteCommand mC = makeCommand("newWindowAssistant",  basicTreeWindow);
+		MesquiteSubmenuSpec mms = addSubmenu(aux, "New Chart for Tree", mC); 
+		mms.setZone(0);
+		mms.setList(TreeWindowAssistantC.class);
+		addMenuItem(aux, "-", null);
+		addModuleMenuItems( aux, makeCommand("newAssistant",  basicTreeWindow), TreeDisplayAssistantA.class);
+		addModuleMenuItems( aux, makeCommand("newWindowAssistant",  basicTreeWindow), TreeWindowAssistantA.class);
+		addMenuItem(aux, "-", null);
+		MesquiteSubmenuSpec mmsO = addSubmenu(aux, "Other Analyses with Tree", makeCommand("newWindowAssistant", basicTreeWindow)); 
+		mmsO.setList(TreeWindowAssistantOA.class);
+		addMenuItem(aux, "-", null);
+		MesquiteSubmenuSpec mmis = addSubmenu(aux, "Visual Tree Analysis", makeCommand("setTreeDrawer",  treeDrawCoordTask));
+		mmis.setList(AnalyticalDrawTree.class);
+		//	addMenuItem(aux, "-", null);
+		//	addMenuItem(null, "Force Repaint", makeCommand("forceRepaint", basicTreeWindow));
+
+
+		if (!MesquiteThread.isScripting()) {
+			displayTreeWindow();
+		}
+		decrementMenuResetSuppression();
+	}
+	void displayTreeWindow(){
+		if (getModuleWindow() == null)
+			return;
+		getModuleWindow().setVisible(true);
+		basicTreeWindow.showTree();
+		getModuleWindow().toFront();
+	}
+	public Tree goToTreeNumber(int index){
+		if (basicTreeWindow == null)
+			return null;
+		return basicTreeWindow.goToTreeNumber(index, true);
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		iQuit();
+	}
+	public void endJob(){
+		if (contextListeners!=null){
+			Enumeration e = contextListeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeContextListener) {
+					TreeContextListener tce = (TreeContextListener)obj;
+					tce.disposing(this);
+				}
+			}
+
+			contextListeners.removeAllElements();
+		}
+		treeDrawCoordTask=null;
+		treeSourceTask=null;
+		basicTreeWindow = null;
+
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		String s = "";
+		;
+		if (getModuleWindow()!=null){
+			if (((BasicTreeWindow)getModuleWindow()).treeEdited)
+				s +=  "Tree shown is not directly from source, but rather is an edited tree. ";
+			if (((BasicTreeWindow)getModuleWindow()).getTaxa()!=null)
+				s+= "Taxa: " + ((BasicTreeWindow)getModuleWindow()).getTaxa().getName();
+		}
+		return s ;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	boolean downInTree = false;
+	public boolean mouseDownInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (x>2000000 || y> 2000000)
+			return true; //here because of bug in Mac OS X 10.0.4
+		if (!treeDisplay.getTree().isLocked()) {
+			downInTree = true;
+			Shape c = g.getClip();
+			g.setClip(0,0,99999, 99999);
+			if (basicTreeWindow.isFauxScrollPane())
+				g.setClip(basicTreeWindow.getTreeViewport());
+
+			boolean st = basicTreeWindow.ScanTouch(g, x, y, modifiers);
+			g.setClip(c);
+			return st;
+		}
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseUpInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+
+		if (x>2000000 || y> 2000000){
+			downInTree = false;
+			return true; //here because of bug in Mac OS X 10.0.4
+		}
+		if (!treeDisplay.getTree().isLocked()) {
+			if (!downInTree)
+				return false;
+			Shape c = g.getClip();
+			g.setClip(0,0,99999, 99999);
+			if (basicTreeWindow.isFauxScrollPane())
+				g.setClip(basicTreeWindow.getTreeViewport());
+			basicTreeWindow.ScanDrop( g, x, y, modifiers);
+			g.setClip(c);
+			basicTreeWindow.branchFrom=0;
+		}
+		downInTree = false;
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseMoveInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (x>2000000 || y> 2000000)
+			return true; //here because of bug in Mac OS X 10.0.4
+		if (!treeDisplay.getTree().isLocked()) {
+			Shape c = g.getClip();
+			g.setClip(0,0,99999, 99999);
+			if (basicTreeWindow.isFauxScrollPane()){
+				g.setClip(basicTreeWindow.getTreeViewport());
+			}
+			//	g.setClip(0,0,99999, 99999);
+			basicTreeWindow.ScanFlash(g, x, y, modifiers);
+			g.setClip(c);
+		}
+		//basicTreeWindow.setExplanation(basicTreeWindow.baseExplanation, false);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDragInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (x>2000000 || y> 2000000)
+			return true; //here because of bug in Mac OS X 10.0.4
+		if (!treeDisplay.getTree().isLocked()) {
+			if (!downInTree)
+				return false;
+			Shape c = g.getClip();
+			g.setClip(0,0,99999, 99999);
+			if (basicTreeWindow.isFauxScrollPane())
+				g.setClip(basicTreeWindow.getTreeViewport());
+			//	g.setClip(0,0,99999, 99999);
+			basicTreeWindow.ScanDrag(g, x, y, modifiers);
+			g.setClip(c);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/**Returns command to hire employee if clonable*/
+	public String getClonableEmployeeCommand(MesquiteModule employee){
+		if (employee!=null && employee.getEmployer()==this) {
+			if (employee.getHiredAs()==TreeWindowAssistant.class)
+				return ("newWindowAssistant " + StringUtil.tokenize(employee.getName()) + ";");//quote
+			if (employee.getHiredAs()==TreeDisplayAssistant.class)
+				return ("newAssistant " + StringUtil.tokenize(employee.getName()) + ";");//quote
+		}
+		return null;
+	}
+	public void transposeField(){
+		if (basicTreeWindow == null)
+			return;
+		int w =basicTreeWindow.totalTreeFieldWidth;
+		basicTreeWindow.totalTreeFieldWidth = basicTreeWindow.totalTreeFieldHeight ;
+		basicTreeWindow.totalTreeFieldHeight = w;
+		basicTreeWindow.sizeDisplay();
+	}
+	/*.................................................................................................................*
+  	 public CompatibilityTest getCompatibilityTest() {
+  	 	return new BTWCompatibilityTest();
+  	 }
+	/*.................................................................................................................*/
+	public boolean getUseXORForBranchMoves() {
+		return useXORForBranchMoves;
+	}
+	public void setUseXORForBranchMoves(boolean useXORForBranchMoves) {
+		this.useXORForBranchMoves = useXORForBranchMoves;
+	}
+}
+
+/*class BTWCompatibilityTest extends CompatibilityTest{
+	//should find out if available matrices of chosen sort
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return true;
+	}
+}
+
+/* ======================================================================== */
+class BasicTreeWindow extends MesquiteWindow implements Fittable, MesquiteListener, AdjustmentListener, XMLPreferencesProcessor {
+	MesquiteTree tree;  
+	MesquiteTree oldTree = null;  //used just to determine if version number of current tree matches; not used otherwise
+	MesquiteTree undoTree = null;  //listens to taxa directly 
+	MesquiteTree previousTree = null; //listens to taxa directly
+	Tree previousEditedTree;  //listens to taxa directly
+	Tree originalTree;
+	TreeVector recentEditedTrees;
+	int maxRecentEditedTrees = 20;
+
+	TreeDisplay treeDisplay;
+	Taxa taxa;
+	DrawTreeCoordinator treeDrawCoordTask;
+	boolean treeEdited = false;
+	boolean  editedByHand = false;
+	//private Rectangle treeRect;
+	//MesquiteScrollbar hScroll, vScroll;
+
+	TreeScrollPane treePane;
+	Adjustable hScroll, vScroll;
+
+	int scanLineThickness = 3;
+
+	boolean usingPane = false;
+	TreeSource treeSourceTask;
+	boolean warningGivenForTreeSource = false;
+	static final int scrollWidth = 16;
+	static final int initalWindowHeight = 400;
+	static final int initalWindowWidth = 520;
+	static final int baseMessageWidth = 256;
+	int messageWidth = 256;
+	int totalTreeFieldWidth = 800;
+	int totalTreeFieldHeight  = 800;
+	TreeWindowPalette palette;
+	MessagePanel messagePanel;
+	/*New code added Feb.07 oliver*/ //TODO: delete new code comments
+	ControlStrip controlStrip;
+	/*End new code added Feb.07 oliver*/	
+	boolean canUndo = true;
+	MesquiteCommand setTreeNumberCommand;
+	TreeTool currentTreeTool;
+
+	MesquiteBoolean ladderizeAfterReroot = new MesquiteBoolean (true);
+	MesquiteCMenuItemSpec toggleRerootLadderizeMSpec = null;
+	MesquiteCheckMenuItem toggleRerootLadderizeMenuItem = null;
+
+	//boolean initiating = true;
+	//MesquiteBoolean sizeToFit;
+	//MesquiteBoolean useSuggestedSize;
+
+	TreeTool toolMAG ;
+	TreeTool rerootTool;
+	int drawingSizeMode;
+	final static int AUTOSIZE = 0;
+	final static int SCALETOFIT = 1;
+	final static int FIXEDSIZE = 2;
+	StringArray sizeModes;
+	MesquiteString sizeModeName;
+
+	MesquiteBoolean infoPanelOn;
+	MesquiteBoolean floatLegends;
+	MesquiteBoolean textVersionDrawOnTree;
+	BasicTreeWindowMaker windowModule;
+	MesquiteInteger dropHighlightedBranch = new MesquiteInteger(0);
+	MesquiteInteger highlightedBranch = null;
+	int branchFrom;
+	int highlightedTaxon=-1;
+	int taxonTouched = -1;
+	int xFrom, yFrom, xTo, yTo, fieldTouchX, fieldTouchY, lastFieldDragX, lastFieldDragY;
+	static final int CONTINUE_WITH_EDITED = 1;
+	static final int CHANGE_TREE_WITH_SOURCE = 0;
+	static final int ASK_USER_TREE_CHANGE = 2;
+
+	static int editedTreeMODE = ASK_USER_TREE_CHANGE;
+
+	boolean usingDefaultTree = false;
+	private int currentTreeNumber = 0;
+	//MesquiteMenuItemSpec sizeItem;
+	static int numWindows=0;
+	private int windowNum=0;
+	MagnifyExtra magnifyExtra;
+	//	int setPosX = MesquiteInteger.unassigned;
+	//	int setPosY = MesquiteInteger.unassigned;
+	long treeVersion = 0;
+
+
+	MesquiteCommand undoCommand, copyCommand, pasteCommand;
+	MesquiteString baseExplanation;
+	TreeReference treeReference = new TreeReference();
+	//MesquiteString currentTreeFootnote;
+	boolean baseExplanationUsed=false;
+	boolean treeAnnotationShown = false;
+	MesquiteMenuItemSpec storeTreeMenuItem, storeTreeAsMenuItem, storeTreeAsOtherMenuItem, recoverEditedMenuItem;
+	MesquiteMenuItemSpec floatLegendsItem;
+	int oldH = 0;
+	int oldV = 0;
+	boolean showTreeListOnSave = false;  //have preference for this?
+	Dimension oldPreferred = null;
+	TreeInfoPanel treeInfoPanel;
+	boolean treeInfoPanelEverShown = false;
+	MesquiteSubmenuSpec drawSizeSubmenu;
+	/*When lockStoredTrees is true (MacClade mode), editing a stored tree causes the tree to be treated as unsaved, and for the new tree to be saved, Store Tree or Replace Stored Tree must
+	be called.  When false, editing a stored tree changes the original in storage.*/ 
+	//boolean lockStoredTrees = false;
+
+	//LockPanel lockPanel;
+
+	public BasicTreeWindow(){
+	}
+	public BasicTreeWindow ( BasicTreeWindowMaker ownerModule, TreeSource tsT,  Taxa taxa, String xmlPrefsString, boolean editMode){
+		super(ownerModule, true); //INFOBAR
+		windowModule = ownerModule;
+		//this.ownerModule = ownerModule;
+		setWindowSize(initalWindowWidth,initalWindowHeight);
+		ownerModule.setModuleWindow(this);
+		baseExplanation = new MesquiteString("");
+
+		numWindows++;
+		windowNum=numWindows;
+		this.taxa=taxa;
+
+		//1
+		treeDrawCoordTask = windowModule.hireTreeDrawCoordTask();  // do this here to ensure that any modules hired by the task have a window into which to put things
+		if (treeDrawCoordTask==null)
+			return;
+		setIcon(MesquiteModule.getRootImageDirectoryPath() + "windowIcons/tree.gif");
+
+		recentEditedTrees = new TreeVector(taxa);
+		this.ownerModule = ownerModule;
+		this.treeSourceTask=tsT;
+		//useSuggestedSize = new MesquiteBoolean(true);
+		infoPanelOn = new MesquiteBoolean(false);
+		//sizeToFit = new MesquiteBoolean(true);
+		floatLegends = new MesquiteBoolean(true);
+		ownerModule.printNameOnTree = new MesquiteBoolean(true);
+		textVersionDrawOnTree = new MesquiteBoolean(false);
+		controlStrip = new ControlStrip((BasicTreeWindowMaker)ownerModule);
+		MesquiteButton listButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("showTaxaList",  this), null, true, MesquiteModule.getRootImageDirectoryPath() + "listT.gif", 12, 16);
+		listButton.setShowBackground(false);
+		listButton.setUseWaitThread(false);
+		listButton.setButtonExplanation("Show List of Taxa window");
+		controlStrip.addButton(listButton);
+		MesquiteButton infoButton = new MesquiteButton(ownerModule, MesquiteModule.makeCommand("toggleInfoPanel",  this), null, true, MesquiteModule.getRootImageDirectoryPath() + "showInfo.gif", 12, 16);
+		//infoBar.addExtraButton(MesquiteModule.getRootImageDirectoryPath() + "showInfo.gif", MesquiteModule.makeCommand("toggleInfoPanel",  this));
+		infoButton.setUseWaitThread(false);
+		infoButton.setShowBackground(false);
+		infoButton.setButtonExplanation("Show Tree Info Panel");
+		controlStrip.addButton(infoButton);
+		addToWindow(controlStrip);
+		ownerModule.addCheckMenuItem(null, "Show Tree Info Panel", ownerModule.makeCommand("toggleInfoPanel",  this), infoPanelOn);
+		treeDrawCoordTask.addCheckMenuItem(null, "Add Name to Printed Tree", ownerModule.makeCommand("togglePrintName",  this), ownerModule.printNameOnTree);
+		tree = null;
+		if (originalTree != null && originalTree instanceof MesquiteTree)
+			taxa.removeListener((MesquiteTree)originalTree);
+		Tree tempTree = null;
+		if (!editMode){
+			tempTree = treeSourceTask.getTree(taxa, 0);
+			//in case treeSourceTask quits at this point, will reset tree source task
+			if (tempTree == null || treeSourceTask != ownerModule.treeSourceTask){
+				treeSourceTask = ownerModule.treeSourceTask;
+				tempTree = treeSourceTask.getTree(taxa, 0);
+			}
+		originalTree = tempTree;  //otree
+		}
+		else{
+			tempTree = taxa.getDefaultDichotomousTree(null);
+			usingDefaultTree = true;
+		}
+
+		if (originalTree != null && originalTree instanceof MesquiteTree)
+			taxa.addListener((MesquiteTree)originalTree);
+		if (tempTree == null) {
+			tree = taxa.getDefaultTree();
+			usingDefaultTree = true;
+			ownerModule.discreetAlert(MesquiteThread.isScripting() || warningGivenForTreeSource,"Tree source \"" +treeSourceTask.getName() +  "\" is not supplying a tree; a default tree may be shown in Tree Window (c).");
+			if (!MesquiteThread.isScripting())
+				warningGivenForTreeSource = true;
+		}
+		else 
+			tree = tempTree.cloneTree();
+		//currentTreeFootnote = new MesquiteString(tree.getAnnotation());
+		//currentTreeFootnote.addListener(this);
+		treeAnnotationShown = true; //so that the base Explanation can refer to the annotation
+		treeVersion = tree.getVersionNumber();
+		oldTree = tree;
+		if (undoTree != null)
+			taxa.removeListener(undoTree);
+		if (previousTree != null)
+			taxa.removeListener(previousTree);
+		undoTree = tree.cloneTree();
+		previousTree = tree.cloneTree();
+		taxa.addListenerHighPriority(undoTree);
+		taxa.addListenerHighPriority(previousTree);
+		hookCurrentTree();
+		if (taxa!=null) {
+			taxa.addListener(this);
+		}
+		messagePanel=new MessagePanel(ownerModule);
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+		treeDisplay =treeDrawCoordTask.createOneTreeDisplay(taxa, this);
+
+		treeDisplay.textVersionDrawOnTree = textVersionDrawOnTree.getValue();
+
+		treeDisplay.setLocation(0, 0);
+		/*treeRect = treeDisplay.getVisRect();
+		hScroll = new TWScroll(this, Scrollbar.HORIZONTAL, 0, 2, 0, 0);
+		vScroll = new TWScroll(this, Scrollbar.VERTICAL, 0, 2, 0, 0);
+		treeDisplay.translatePoint = new Point(0,0);
+		addToWindow(hScroll);
+		addToWindow(vScroll);
+		 */
+		treePane = new TreeScrollPane(this);
+		hScroll = treePane.getHAdjustable();
+		vScroll = treePane.getVAdjustable();
+		hScroll.addAdjustmentListener(this);
+		vScroll.addAdjustmentListener(this);
+
+		addToWindow(treeDisplay);
+		highlightedBranch = treeDisplay.getHighlightedBranchMI();
+		palette.setUpBirdsEye();
+		//	setSuggestedSize(false, false);
+
+		storeTreeMenuItem = ownerModule.addMenuItem( "Store Tree", ownerModule.makeCommand("storeTree",  this));
+		storeTreeAsMenuItem = ownerModule.addMenuItem( "Store Tree As...", ownerModule.makeCommand("storeTreeAs",  this));
+		storeTreeAsOtherMenuItem = ownerModule.addMenuItem( "Store Tree In Tree Block As...", ownerModule.makeCommand("storeTreeAsOther",  this));
+		setStoreTreeAsMenuItems(editMode);
+
+		ownerModule.addMenuItem( "-", null);
+		recoverEditedMenuItem = ownerModule.addMenuItem( "Recover Last Edited Tree", ownerModule.makeCommand("recoverLastEditedTree",  this));
+		ownerModule.addMenuItem( "Edited Tree Handling Options...", ownerModule.makeCommand("queryEditedTreeMode",  this));
+		ownerModule.addMenuItem( "-", null);
+
+		ownerModule.addMenuItem( "Choose Tree...", ownerModule.makeCommand("chooseTree",  this));
+		MesquiteMenuItemSpec mm = ownerModule.addMenuItem( "Next Tree", ownerModule.makeCommand("nextTree",  this)); //DOES THIS WORK??
+		mm.setShortcut(KeyEvent.VK_UP); //right
+		mm = ownerModule.addMenuItem( "Previous Tree", ownerModule.makeCommand("previousTree",  this));
+		mm.setShortcut(KeyEvent.VK_DOWN); //right
+		ownerModule.addMenuItem( "Step Through Trees...", ownerModule.makeCommand("stepThroughTrees",  this));
+		ownerModule.addMenuItem( "-", null);
+		ownerModule.addSubmenu(null, "Alter/Transform Tree", ownerModule.makeCommand("alterTree",  this), TreeAlterer.class);
+		ownerModule.addSubmenu(null, "Alter/Transform Branch Lengths", ownerModule.makeCommand("alterBranchLengths",  this), BranchLengthsAlterer.class);
+		ownerModule.addMenuItem( "Cut Selected Taxa", ownerModule.makeCommand("cutSelectedTaxa",  this));
+		ownerModule.addMenuItem( "-", null);
+		ownerModule.addModuleMenuItems(null, ownerModule.makeCommand("newWindowAssistant", this), TreeWindowAssistantN.class);
+		ownerModule.addModuleMenuItems(null, ownerModule.makeCommand("newAssistant",  this), TreeDisplayAssistantD.class);
+		ownerModule.addMenuItem( "-", null);
+
+
+		MesquiteSubmenuSpec mBringToFrontAsst = ownerModule.addSubmenu(null, "Bring To Front");
+		mBringToFrontAsst.setList(treeDisplay.getExtras());
+		mBringToFrontAsst.setListableFilter(TreeDisplayDrawnExtra.class);
+		mBringToFrontAsst.setCommand(ownerModule.makeCommand("bringToFront",  this));
+		MesquiteSubmenuSpec mSaveMacroAsst = ownerModule.addSubmenu(null, "Save Tree Analysis as Macro");
+		mSaveMacroAsst.setList(ownerModule.getEmployeeVector());
+		mSaveMacroAsst.setListableFilter(TreeDisplayAssistantAD.class);
+		mSaveMacroAsst.setCommand(ownerModule.makeCommand("saveMacroDisplayAssistant",  this));
+
+		MesquiteSubmenuSpec mCloseAsst = ownerModule.addSubmenu(null, "Close/Remove");
+		mCloseAsst.setList(ownerModule.getEmployeeVector());
+		mCloseAsst.setListableFilter(TreeDisplayAssistantAD.class);
+		mCloseAsst.setCommand(ownerModule.makeCommand("closeDisplayAssistant",  this));
+
+
+		treeDrawCoordTask.addMenuItem("-", null);
+
+		drawingSizeMode = AUTOSIZE;
+		if (treeDrawCoordTask.hasPreferredSize())
+			sizeModes = new StringArray(1);
+		else
+			sizeModes = new StringArray(3);
+		sizeModes.setValue(AUTOSIZE, "Size Automatically");  //the strings passed will be the menu item labels
+		sizeModes.setValue(SCALETOFIT, "Scale to Fit");
+		sizeModes.setValue(FIXEDSIZE, "Fixed Drawing Size...");
+
+		sizeModeName = new MesquiteString(sizeModes.getValue(drawingSizeMode));  //this helps the menu keep track of checkmenuitems
+		drawSizeSubmenu = treeDrawCoordTask.addSubmenu(null, "Drawing Size", MesquiteModule.makeCommand("setDrawingSizeMode", this), sizeModes); 
+		drawSizeSubmenu.setSelected(sizeModeName);
+		drawSizeSubmenu.setEnabled(!treeDrawCoordTask.hasPreferredSize());
+		floatLegendsItem = treeDrawCoordTask.addCheckMenuItem(null, "Float Legends", ownerModule.makeCommand("toggleLegendFloat",  this), floatLegends);
+		treeDrawCoordTask.addMenuItem("Legends To Default Positions", ownerModule.makeCommand("legendsToHome",  this));
+		treeDrawCoordTask.addCheckMenuItem(null, "Text Extras On Trees", ownerModule.makeCommand("toggleTextOnTree",  this), textVersionDrawOnTree);
+		treeDrawCoordTask.addMenuItem("-", null);
+
+		undoCommand = MesquiteModule.makeCommand("undo", this);
+		copyCommand =MesquiteModule.makeCommand("copyTree", this);
+		pasteCommand = MesquiteModule.makeCommand("paste", this);
+
+		treeDisplay.setTaxonNameBuffer(30);
+
+		/*
+		lockPanel=new LockPanel(this);
+		addToWindow(lockPanel);
+		lockPanel.setLocation(0, getHeight()-scrollWidth);
+		lockPanel.setVisible(true);
+		 */
+
+
+		setBackground(Color.white);
+		/*Edited Feb.06 was (see commented out line below) oliver*/ //TODO: Delete new code comments	
+		//		messagePanel.setLocation(0, getHeight()-scrollWidth);
+		messagePanel.setLocation(25, getHeight()-scrollWidth);
+		controlStrip.setLocation(0, getHeight()-scrollWidth);
+		/*End edited Feb.06 oliver*/
+
+
+		TreeTool tool1 = new TreeTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(), "arrow.gif", 4,2,"Move branch", "This tool is used for rearranging the tree by moving branches.  By clicking on one branch, then holding the mouse button down, one can drag the branch and drop it on another branch.  If a legal move, the first branch will be cut and grafted on the second branch.  A move is illegal if the first branch is a descendant of the second branch.");
+		tool1.setTransferredCommand(MesquiteModule.makeCommand("moveBranch",  this));
+		//tool1.setTouchedTaxonCommand(MesquiteModule.makeCommand("touchTaxon",  this)); //cut as of 1.02
+		currentTreeTool = tool1;
+		addTool(tool1);
+		setCurrentTool(currentTreeTool);
+		currentTreeTool.setInUse(true);
+		currentTreeTool.setIsArrowTool(true);
+
+
+		toolMAG = new TreeTool(this, "zoom", ownerModule.getPath(), "zoom.gif",  4,4,"Zoom image", "This tool magnifies (or shrinks, if Option/Alt is held down) the image of the whole tree.  It is enabled only if the Drawing Size is set to Size Automatically");
+		toolMAG.setTouchedCommand(MesquiteModule.makeCommand("zoomBT",  this));
+		toolMAG.setTouchedFieldCommand(MesquiteModule.makeCommand("zoom",  this));
+		toolMAG.setTouchedTaxonCommand(MesquiteModule.makeCommand("zoomBT",  this));
+		toolMAG.setOptionImageFileName("zoomOut.gif", 4, 4);
+		addTool(toolMAG);
+		toolMAG.setEnabled(drawingSizeMode == AUTOSIZE);
+		toolMAG.setOptionsCommand(new MesquiteCommand("zoomOptions", this));
+		/**/
+
+		TreeTool tool2 = new TreeTool(this, "interchange", ownerModule.getPath(),"interchange.gif", 7,13,"Interchange branches", "This tool is used as is the Move Branch (arrow) tool, except that the result is to interchange the locations of the two branches.  It can be used to rotate a node.");
+		tool2.setTransferredCommand(MesquiteModule.makeCommand("exchangeBranches",  this));
+		addTool(tool2);
+
+		TreeTool tool3 = new TreeTool(this, "collapse", ownerModule.getPath(),"collapse.gif",  7,12, "Collapse branch", "This tool destroys a branch, thus collapsing its daughter branches into a polytomy.  It cannot be used on terminal branches.");
+		tool3.setTouchedCommand(MesquiteModule.makeCommand("collapseBranch",  this));
+		addTool(tool3);
+
+		TreeTool tool4 = new TreeTool(this, "collapseall", ownerModule.getPath(), "collapseall.gif", 8,13,"Collapse all branches", "This tool destroys all internal branches in a clade, thus collapsing the entire clade to a polytomous bush.");
+		tool4.setTouchedCommand(MesquiteModule.makeCommand("collapseAll",  this));
+		tool4.setOptionImageFileName("collapseAllBelow.gif", 14, 4);
+		addTool(tool4);
+
+		rerootTool = new TreeTool(this, "reroot", ownerModule.getPath(), "reroot.gif",  3,4,"Reroot at branch", "This tool reroots the tree along the branch touched.");
+		rerootTool.setTouchedCommand(MesquiteModule.makeCommand("rootAlongBranch",  this));
+		addTool(rerootTool);
+		rerootTool.setOptionsCommand(new MesquiteCommand("rerootOptions", this));
+		toggleRerootLadderizeMSpec = ownerModule.addCheckMenuItem(null, "Ladderize After Reroot", MesquiteModule.makeCommand("toggleRerootLadderize", this), ladderizeAfterReroot);
+		toggleRerootLadderizeMenuItem = new MesquiteCheckMenuItem(toggleRerootLadderizeMSpec);
+
+
+		TreeTool tool5 = new TreeTool(this, "scissors", ownerModule.getPath(), "scissors.gif" , 6,5,"Prune clade", "This tool deletes the clade of the node touched.  Only the tree being operated on is affected (that is, the terminal taxa are not deleted from the data file).");
+		tool5.setTouchedCommand(MesquiteModule.makeCommand("cutClade",  this));
+		addTool(tool5);
+
+		TreeTool tool7 = new TreeTool(this, "ladderize", ownerModule.getPath(), "ladderize.gif",  3,13,"Ladderize clade", "This tool ladderizes a clade by rotating branches until largest of sister clades on right (except if option key is held down, in which case, left).");
+		tool7.setTouchedCommand(MesquiteModule.makeCommand("ladderize",  this));
+		tool7.setTouchedTaxonCommand(MesquiteModule.makeCommand("focalLadderize",  this));
+		tool7.setOptionImageFileName("reverseLadderize.gif", 13, 13);
+		addTool(tool7);
+
+		TreeTool tool8 = new TreeTool(this, "triangle", ownerModule.getPath(), "triangle.gif", 7,13,"Draw clade as triangle", "This tool designates the clade of the node touched to be drawn in compact form, for instance as a triangle.  This affects only drawing; it does not affect calculations, as the clade (with its phylogenetic structure) is still present in the tree.  This can be used for large trees to hide temporarily details within some clades.");
+		tool8.setTouchedCommand(MesquiteModule.makeCommand("drawAsTriangle",  this)); 
+		addTool(tool8);
+		TreeTool tool9 = new TreeTool(this, "magnify", ownerModule.getPath(), "magnify.gif", 4,4,"Magnify Clade", "This tool fills the tree window with the clade of the node touched.  The rest of the tree is present, but not shown.  This can be use for large trees to focus on individual clades");
+		tool9.setTransferredCommand(MesquiteModule.makeCommand("magnifyClade",  this));
+		addTool(tool9);
+		magnifyExtra = new MagnifyExtra(ownerModule, treeDisplay, tool9);
+		ownerModule.magnifyExtra = magnifyExtra;
+		treeDisplay.addExtra(magnifyExtra); 
+		treeDisplay.setTree(tree);
+		treeDisplay.setVisible(true);
+		treeInfoPanel = new TreeInfoPanel(this);
+		TreeInfoPanelAssistant valuesAssistant = (TreeInfoPanelAssistant)ownerModule.hireNamedEmployee(TreeInfoPanelAssistant.class, "#TreeInfoValues");
+		treeInfoPanel.addExtraPanel(valuesAssistant.getPanel(treeInfoPanel));
+
+		XMLUtil.readXMLPreferences(ownerModule, this, xmlPrefsString);
+
+		setTreeName(tree);
+		sizeDisplay();
+		ownerModule.hireAllEmployees(TreeWindowAssistantI.class); 
+		Enumeration em = ownerModule.getEmployeeVector().elements();
+		if (tree != null)
+			while (em.hasMoreElements()) {
+				Object obj = em.nextElement();
+				MesquiteModule mb = (MesquiteModule)obj;
+				if (mb instanceof TreeWindowAssistant) {
+					((TreeWindowAssistant)mb).setTree(tree);  
+				}
+			}
+		setShowExplanation(true);
+		setShowAnnotation(true);
+		baseExplanation.setValue("This is a tree window.  In it you can view trees from various tree sources, edit trees, and store trees.");
+		setExplanation(baseExplanation, true);
+		resetTitle();
+		//initiating = false;
+
+	}
+	
+	void setStoreTreeAsMenuItems(boolean editMode){
+		if (treeSourceTask.nameMatches("StoredTrees")){
+			if (editMode){
+				storeTreeAsMenuItem.setName( "Store Tree As...");
+				storeTreeAsMenuItem.setEnabled(false);
+				storeTreeAsOtherMenuItem.setName( "Store Tree In Tree Block As...");
+				storeTreeAsOtherMenuItem.setEnabled(true);
+			}
+			else {
+				storeTreeAsMenuItem.setName( "Store Tree In Current Block As...");
+				storeTreeAsMenuItem.setEnabled(true);
+				storeTreeAsOtherMenuItem.setName( "Store Tree In Other Block As...");
+				storeTreeAsOtherMenuItem.setEnabled(true);
+			}
+		}
+		else {
+			storeTreeAsMenuItem.setName( "Store Tree As...");
+			storeTreeAsMenuItem.setEnabled(false);
+			storeTreeAsOtherMenuItem.setName( "Store Copy of Tree As...");
+			storeTreeAsOtherMenuItem.setEnabled(true);
+		}
+		storeTreeMenuItem.setEnabled(!treeSourceLocked());
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("toggleRerootLadderize".equalsIgnoreCase(tag))
+			ladderizeAfterReroot.setValue(MesquiteBoolean.fromTrueFalseString(content));
+		else if ("editedTreeRetainMode".equalsIgnoreCase(tag)){
+			int x = MesquiteInteger.fromString(content);
+			if (MesquiteInteger.isCombinable(x))
+				editedTreeMODE = x;
+		}
+	}
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String flavor, String content) {
+	}
+
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "toggleRerootLadderize", ladderizeAfterReroot);   
+		StringUtil.appendXMLTag(buffer, 2, "editedTreeRetainMode", editedTreeMODE);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*/
+	void setTreeInfoPanel(boolean show){
+		infoPanelOn.setValue(show);
+		if (show){
+			treeInfoPanelEverShown = true;
+			addSidePanel(treeInfoPanel, TreeInfoPanel.width);
+			treeInfoPanel.setVisible(true);
+			treeInfoPanel.setTree(tree);
+			String title = "Tree Information";
+			treeInfoPanel.repaint();
+		}
+		else {
+			if (treeInfoPanel != null)
+				removeSidePanel(treeInfoPanel);
+		}
+	}
+	void treeInfoPanelGoAway(){
+		setTreeInfoPanel(false);
+	}
+	/*.................................................................................................................*/
+	public String searchData(String s, MesquiteString commandResult) {
+		if (StringUtil.blank(s) || taxa == null)
+			return "<h2>Nothing to search for (searched: \"" + s + "\")</h2>";
+		if (commandResult != null)
+			commandResult.setValue((String)null);
+		String listData = taxa.searchData(s, commandResult);
+
+		if (!StringUtil.blank(listData))
+			return "<h2>Matches to search string: \"" + s + "\"</h2>" + listData;
+		else
+			return "<h2>No matches found (searched: \"" + s + "\")</h2>";
+	}
+	/*.................................................................................................................*/
+	private void makeTaxonVisible(int i){
+		if (drawingSizeMode == SCALETOFIT)
+			return;
+		if (usingPane){
+			TreeDrawing td = treeDisplay.getTreeDrawing();
+			int x = td.x[treeDisplay.getTree().nodeOfTaxonNumber(i)];
+			int y = td.y[treeDisplay.getTree().nodeOfTaxonNumber(i)];
+			int w = getTreePaneWidth();
+			int h = getTreePaneHeight();
+			setOrigin(x - w/2, y - h/2, true);
+			treeDisplay.pleaseUpdate(true);
+			sizeDisplay();
+		}
+	}
+	/*.................................................................................................................*/
+	protected ToolPalette makeToolPalette(){
+		setTreeNumberCommand = ownerModule.makeCommand("setTreeNumber",  this);
+		palette = new TreeWindowPalette((BasicTreeWindowMaker)ownerModule, this);
+		palette.setFirstToolHeight(76);
+		return palette;
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		String t;
+		if (treeSourceTask==null)
+			t = "Tree Window " + windowNum + " for taxa \"" +taxa.getName() + "\"";
+		else
+			t = treeSourceTask.getTreesDescriptiveString(taxa);
+		if (StringUtil.blank(t)){
+			if (treeEdited || editedByHand)
+				t = "Edited Tree";
+			else
+				t = "Tree";
+		}
+		setTitle(t);
+	}
+
+
+
+	public MesquiteCommand getUndoCommand() {
+		return undoCommand; 
+	}
+	public MesquiteCommand getCopySpecialCommand() {
+		return copyCommand; 
+	}
+	public String getCopySpecialName() {
+		return "Copy Tree"; 
+	}
+	public MesquiteCommand getPasteSpecialCommand() {
+		return pasteCommand; 
+	}
+	public String getPasteSpecialName() {
+		return "Paste Tree"; 
+	}
+
+	/*@@@@@@@@@@@@@@@@@@@@@@=========  pane/scrolling ==========@@@@@@@@@@@@@@@@@@@@@*/
+	private void toggleLegendFloat(){  //called only when recently changed
+		if (false && usingPane) { //turning off float; adjust offsets
+			//get bounds on visible part of treeDisplay  
+			Point pt = getTreeScrollPoint();
+			Dimension dim = getTreeViewportSize();
+			//cycle through all components getting those that are Legends 
+			Component[] cc = treeDisplay.getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++) {
+					if (cc[i] instanceof Legend){
+						Legend legend = (Legend)cc[i];
+						Rectangle rect  = legend.getBounds();
+
+						//	int deltaBaseX = (treeDisplay.getBounds().width + hScroll.getValue()) - (treePane.getWidth());
+						int deltaBaseY = (treeDisplay.getBounds().height + vScroll.getValue()) - (treePane.getHeight());
+						if (!floatLegends.getValue()){
+							//legend.setOffsetX(legend.getOffsetX()-deltaBaseX);
+							legend.setOffsetY(legend.getOffsetY()-deltaBaseY);
+						}
+						else {
+							//legend.setOffsetX(legend.getOffsetX()+deltaBaseX);
+							legend.setOffsetY(legend.getOffsetY()+deltaBaseY);
+						}
+					}
+				}
+		}
+		checkPanelPositionsLegal();
+	}
+	private void OLDtoggleLegendFloat(){  //called only when recently changed
+		if (!usingPane || drawingSizeMode == SCALETOFIT || floatLegends.getValue()) { //legends can't float
+			checkPanelPositionsLegal();
+		}
+		else {  //undoing floating
+			//get bounds on visible part of treeDisplay  
+			Point pt = getTreeScrollPoint();
+			Dimension dim = getTreeViewportSize();
+
+			//cycle through all components getting those that are Legends 
+			Component[] cc = treeDisplay.getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++) {
+					if (cc[i] instanceof Legend){
+						//use getOffsetX(); for current and 
+						//adjustLocation
+						Legend legend = (Legend)cc[i];
+						Rectangle rect  = legend.getBounds();
+						legend.setConstrainingRectangle(treeDisplay.getBounds());
+
+						//switching from float to non-float.  
+						if (rect.x - pt.x > dim.width /2) {
+							//move legend to right border
+							//	legend.setOffsetX(treeDisplay.getBounds().width - dim.width + legend.getOffsetX());
+							legend.setOffsetX(-treeDisplay.getBounds().width - treeDisplay.getBounds().x + dim.width - rect.width);
+						}
+						else {
+							//move legend to left border
+							legend.setOffsetX(-treeDisplay.getBounds().width - treeDisplay.getBounds().x);
+							//	legend.setOffsetX(legend.getOffsetX() - pt.x);
+						}
+						if (rect.y - pt.y > dim.height/2){
+							//move legend to bottom border
+							//	legend.setOffsetY(treeDisplay.getBounds().height - dim.height + legend.getOffsetY());
+							legend.setOffsetY(-treeDisplay.getBounds().height- treeDisplay.getBounds().y + dim.height - rect.height);
+						}
+						else {
+							//move legend to top border
+							//	legend.setOffsetY(legend.getOffsetY() - pt.y);
+							legend.setOffsetY(-treeDisplay.getBounds().height- treeDisplay.getBounds().y);
+						}
+						legend.adjustLocation();
+					}
+				}
+			checkPanelPositionsLegal();
+		}
+	}
+	public void checkPanelPositionsLegal(){
+		if (treeDisplay == null)
+			return;
+		try {
+			//if (true || !usingPane || drawingSizeMode == SCALETOFIT || !floatLegends.getValue()) { //legends can't float or aren't floating
+			Component[] cc = treeDisplay.getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++) {
+					if (cc[i] instanceof Legend){ //make sure legends are in bounds
+						//adjustLocation
+						Legend legend = (Legend)cc[i];
+						if (usingPane && floatLegends.getValue()){
+							legend.setConstrainingRectangle(treeDisplay.getBounds());
+						}
+						else {
+							legend.setConstrainingRectangle(treeDisplay.getBounds()); //treeDisplay.getBounds()
+						}
+						legend.adjustLocation();
+					}
+				}
+			//}
+		}
+		catch (Exception ex){
+		}
+	}
+	public void adjustmentValueChanged(AdjustmentEvent e){
+		if (e.getSource() == hScroll)
+			scrollTouched(Scrollbar.HORIZONTAL, hScroll.getValue());
+		else
+			scrollTouched(Scrollbar.VERTICAL, vScroll.getValue());
+	}
+	/*.................................................................................................................*/
+	void scrollTouched(int orientation, int value) {
+		if (usingPane)
+			resetLegends();
+		/*if (usingPane){
+			if (orientation == Scrollbar.HORIZONTAL){
+				treeRect.x = value;
+			}
+			else {
+				treeRect.y = value;
+			}
+
+			setOrigin(treeRect.x, treeRect.y);
+			//sizeDisplay();
+			treeDisplay.pleaseUpdate(false);
+
+		}*/
+		checkPanelPositionsLegal();
+	}
+	/*.................................................................................................................*/
+	void resetLegends() {
+
+		if (usingPane && drawingSizeMode != SCALETOFIT && treeDisplay!=null && floatLegends.getValue() && hScroll != null){
+			int changeH = hScroll.getValue() - oldH;
+			int changeV = vScroll.getValue() - oldV;
+			if (changeH !=0 || changeV != 0){
+				Component[] cc = treeDisplay.getComponents();
+				if (cc!=null && cc.length>0)
+					for (int i=0; i<cc.length; i++) {
+						if (cc[i] instanceof Legend){
+							Legend legend = (Legend)cc[i];
+							legend.setOffsetX( legend.getOffsetX() + changeH);
+							legend.setOffsetY( legend.getOffsetY() + changeV);
+							legend.adjustLocation();
+						}
+					}
+
+			}
+
+			oldH = hScroll.getValue();
+			oldV = vScroll.getValue();
+		}
+		else
+			checkPanelPositionsLegal();
+	}
+	boolean isFauxScrollPane(){
+		if (usingPane)
+			return treePane.isFauxScrollPane();
+		return false;
+	}
+	Dimension getTreeViewportSize(){
+		if (usingPane)
+			return treePane.getViewportSize();
+		//SCROLLPANEreturn treePane.getViewportSize();
+		else
+			return new Dimension(treeDisplay.getWidth(),treeDisplay.getHeight());
+	}
+
+	Rectangle getTreeViewport(){
+		if (usingPane && hScroll != null){
+			if (!isFauxScrollPane() && MesquiteTrunk.isMacOSX())
+				return new Rectangle(0,0,treeDisplay.getWidth(),treeDisplay.getHeight());
+			hScroll = treePane.getHAdjustable();
+			vScroll = treePane.getVAdjustable();
+			return new Rectangle(hScroll.getValue(), vScroll.getValue(), treePane.getContentsWidth(), treePane.getContentsHeight());
+			//SCROLLPANEreturn treePane.getViewportSize();
+		}
+		else
+			return new Rectangle(0,0,treeDisplay.getWidth(),treeDisplay.getHeight());
+	}
+	Point getTreeScrollPoint(){
+		if (usingPane)
+			return treePane.getScrollPosition();
+		//SCROLLPANEreturn treePane.getScrollPosition();
+		else
+			return new Point(0,0);
+	}
+	int getTreePaneWidth(){
+		if (usingPane)
+			return treePane.getBounds().width;
+		else
+			return treeDisplay.getBounds().width;
+
+	}
+	int getTreePaneHeight(){
+		if (usingPane)
+			return treePane.getBounds().height;
+		else
+			return treeDisplay.getBounds().height;
+	}
+	/*.................................................................................................................*/
+	public void togglePane(boolean paneOn, boolean resetOrigin) {
+
+		if (paneOn) {
+			if (!usingPane) {
+				//SCROLLPANEif (!initiating)
+				//SCROLLPANE	removeFromWindow(treeDisplay);
+				//SCROLLPANEif (treePane != null)
+				//SCROLLPANE	removeFromWindow(treePane);
+				messageWidth=baseMessageWidth;
+				if (palette !=null && palette.birdsEyeBox!=null)
+					palette.birdsEyeBox.setVisible(true);
+				removeFromWindow(treeDisplay);
+				addToWindow(treePane);
+				treePane.setLocation(0,0);
+				treePane.addTreeDisplay(treeDisplay);
+				usingPane = true;
+
+				hScroll = treePane.getHAdjustable();
+				vScroll = treePane.getVAdjustable();
+
+				hScroll.setUnitIncrement(10);
+				hScroll.setBlockIncrement((getWidth()-scrollWidth)/10);
+				/*hScroll.setBounds(0, getHeight()-scrollWidth-scrollWidth, getWidth()-scrollWidth, scrollWidth);  
+				vScroll.setBounds(getWidth()-scrollWidth, 0, scrollWidth, getHeight()-scrollWidth-scrollWidth);  
+				 */
+				vScroll.setBlockIncrement((getHeight()-scrollWidth)/10);
+				vScroll.setUnitIncrement(10);
+				resetScrolls();
+				oldH = hScroll.getValue();
+				oldV = vScroll.getValue();
+				/*vScroll.doLayout();
+				hScroll.doLayout();
+				hScroll.setVisible(true);  
+				vScroll.setVisible(true);  
+				 */
+				//	treePane.setSize(getWidth(), getHeight());
+				treePane.setSize(getWidth(),getHeight()-scrollWidth);
+				//SCROLLPANEaddToWindow(treePane);
+				//sizeDisplay();
+				//	if (MesquiteInteger.isCombinable(setPosX))
+				//		treePane.setScrollPosition(-setPosX, -setPosY);
+				//	else treePane.setScrollPosition(0, 0);
+				if (palette!=null)
+					palette.setFieldSize(totalTreeFieldWidth, totalTreeFieldHeight);
+				//sizeItem.setEnabled(true);
+				floatLegendsItem.setEnabled(true);
+				//if (!initiating) {
+				ownerModule.resetContainingMenuBar();
+				//treePane.setVisible(true);
+				treeDisplay.pleaseUpdate(true);
+				messagePanel.repaint();
+				//lockPanel.repaint();
+				//}
+				setOrigin(0, 0, true);
+				//initiating = false;
+				treePane.doLayout();
+			}
+		}
+		else {
+			if (usingPane)  {
+				usingPane = false;
+				removeFromWindow(treePane);
+				addToWindow(treeDisplay);
+				//	if (!initiating)
+				//		removeFromWindow(treePane);
+				/*hScroll.setVisible(false);
+				vScroll.setVisible(false);
+				hScroll.setLocation(getWidth(), getHeight());  //off screen
+				vScroll.setLocation(getWidth(), getHeight());  //off screen*/
+				//treePane = null;
+				//SCROLLPANEtreeDisplay.setLocation(0, 0);
+				//SCROLLPANEaddToWindow(treeDisplay);
+				palette.birdsEyeBox.setVisible(false);
+				//	if (sizeItem!=null)
+				//		sizeItem.setEnabled(false);
+				if (floatLegendsItem!=null)
+					floatLegendsItem.setEnabled(false);
+				//if (!initiating) {
+				ownerModule.resetContainingMenuBar();
+				treeDisplay.pleaseUpdate(true);
+				messagePanel.repaint();
+				/*New code added Feb.07 oliver*/ //TODO: Delete new code comments
+				controlStrip.repaint();
+				treeDisplay.setLocation(0,0);
+				/*End new code added Feb.07 oliver*/
+				//lockPanel.repaint();
+				//}
+				//initiating = false;
+			}
+			if (resetOrigin)
+				setOrigin(0, 0, true);
+		}
+		treeDisplay.setVisRect(getTreeViewport());
+	}
+	public void setOrigin(int x, int y, boolean setScrolls) {
+		if (x < 0)
+			x = 0;
+		if (y < 0)
+			y = 0;
+		if (usingPane){
+			treeDisplay.setLocation(-x, -y);
+			if (setScrolls){
+				hScroll.setValue(x);
+				vScroll.setValue(y);
+
+			}
+			treeDisplay.setVisRect(getTreeViewport());
+		}
+
+
+		resetLegends();
+	}
+	public void resetScrolls(){
+		if (hScroll.getValue()<0)
+			hScroll.setValue(0);
+		if (vScroll.getValue()<0){
+			vScroll.setValue(0);
+		}
+	}
+	public int getOriginX() {
+		if (!usingPane)
+			return 0;
+		Point p = getTreeScrollPoint();
+		return p.x;
+		//	Adjustable h = treePane.getHAdjustable();
+		//	return -(int)( ((1.0*(h.getValue()- h.getMinimum()))/(h.getMaximum()-h.getMinimum()))*treeDisplay.getBounds().width);
+	}
+	public int getOriginY() {
+		if (!usingPane)
+			return 0;
+
+		Point p = getTreeScrollPoint();
+		return p.y;
+		//Adjustable v = treePane.getVAdjustable();
+		//	return -(int)( ((1.0*(v.getValue()- v.getMinimum()))/(v.getMaximum()-v.getMinimum()))*treeDisplay.getBounds().height);
+	}
+	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  pane/scrolling @@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+	/*.................................................................................................................*/
+	/** Called in some circumstances (not all) when a component is added to a container in the window.  Currently used so that
+	the Tree window knows that a component has been added to the TreeDisplay.*/
+	public void componentAdded(Container cont, Component comp){
+		checkPanelPositionsLegal();
+	}
+
+	public void setVisible(boolean v){
+		super.setVisible(v);
+		if (v && treeDisplay != null){
+			treeDisplay.redoCalculations(89);
+			treeDisplay.repaint(true);
+		}
+
+	}
+
+	/*.................................................................................................................*/
+	int countSizes = 0;
+	void sizeDisplay(){
+		if (palette==null|| treeDisplay==null  ||messagePanel==null)
+			return;
+		if (treeDrawCoordTask.hasPreferredSize()){
+			drawingSizeMode = AUTOSIZE;
+		}
+		if (drawSizeSubmenu != null)
+			drawSizeSubmenu.setEnabled(!treeDrawCoordTask.hasPreferredSize());
+		treeDisplay.autoStretchIfNeeded = true;  //this is always true at moment; delete?
+		palette.setFieldSize(totalTreeFieldWidth,totalTreeFieldHeight);
+		if (drawingSizeMode == SCALETOFIT) {
+			togglePane(false, true);
+			treeDisplay.setSize(getWidth(),getHeight()-scrollWidth);
+			treeDisplay.setFieldSize(getWidth(),getHeight()-scrollWidth);
+			treeDisplay.autoStretchIfNeeded = true;
+			scale = 0;
+			treeDisplay.redoCalculations(8813);
+		}
+		else if (drawingSizeMode == AUTOSIZE) {
+			int w = getWidth()-scrollWidth;
+			int h = getHeight()-scrollWidth-scrollWidth;
+			Dimension s = treeDrawCoordTask.getPreferredSize();
+			if (s != null){
+				togglePane(true, false);
+				//	treeDisplay.setSize(w,h);
+				if (treePane != null)
+					treePane.setSize(getWidth(),getHeight()-scrollWidth);
+				treeDisplay.setSize(s.width,s.height);
+				treeDisplay.setFieldSize(s.width,s.height);
+				treeDisplay.redoCalculations(88173);
+			}
+			else {
+
+				if (taxa == null ){
+					treeDisplay.setSize(w,h);
+
+					treeDisplay.setFieldSize(w, h);
+					treeDisplay.redoCalculations(28813);
+					togglePane(false, false);
+				}
+				else {
+					int basicMinSpacing = 12;
+					Graphics g = treeDisplay.getGraphics();
+					if (g != null){
+						FontMetrics fm = g.getFontMetrics(treeDisplay.getTaxonNamesFont());
+						if (fm!=null) {
+							basicMinSpacing = fm.getMaxAscent()+ fm.getMaxDescent();
+						}
+					}
+					boolean canFit = true;
+					Tree tree = treeDisplay.getTree();
+					int numTaxa = 0;
+					if (tree != null)
+						numTaxa = tree.numberOfTerminalsInClade(tree.getRoot());
+					else
+						numTaxa = taxa.getNumTaxa();
+					//	canFit =  numTaxa<50;
+
+					//	if (!canFit){
+					if (treeDisplay.getOrientation()== TreeDisplay.UP || treeDisplay.getOrientation()== TreeDisplay.DOWN) 
+						canFit = numTaxa*basicMinSpacing<w;
+					else if (treeDisplay.getOrientation()== TreeDisplay.RIGHT || treeDisplay.getOrientation()== TreeDisplay.LEFT) 
+						canFit =  numTaxa*basicMinSpacing<h;
+					else
+						canFit = numTaxa*6<(w+h)/2;
+					//		}
+
+
+					if (canFit && scale<=0){
+						treeDisplay.setSize(w,h);
+
+						treeDisplay.setFieldSize(w, h);
+						treeDisplay.redoCalculations(8813);
+						togglePane(false, false);
+					}
+					else {
+						treeDisplay.autoStretchIfNeeded = true;
+						if (treeDisplay.getOrientation()== TreeDisplay.UP || treeDisplay.getOrientation()== TreeDisplay.DOWN) {
+							totalTreeFieldWidth = numTaxa*basicMinSpacing;  
+							totalTreeFieldHeight  = h-scrollWidth-4;
+						}
+						else if (treeDisplay.getOrientation()== TreeDisplay.RIGHT || treeDisplay.getOrientation()== TreeDisplay.LEFT) {
+							totalTreeFieldWidth = w-scrollWidth-4;  
+							totalTreeFieldHeight  = numTaxa*basicMinSpacing;
+						}
+						else  {
+							totalTreeFieldWidth = numTaxa*8;  
+							totalTreeFieldHeight  = numTaxa*8;
+						}
+						if (scale > 0){
+							for (int i=0; i<scale; i++){
+								totalTreeFieldWidth *= 2;
+								totalTreeFieldHeight *= 2;
+							}
+						}
+						else if (scale < 0){
+							for (int i=0; i>scale; i--){
+								totalTreeFieldWidth /= 2;
+								totalTreeFieldHeight /= 2;
+							}
+						}
+						//treeDisplay.setSize(w, h);
+						treeDisplay.setSize(totalTreeFieldWidth,totalTreeFieldHeight);
+						treeDisplay.setFieldSize(totalTreeFieldWidth,totalTreeFieldHeight);
+						treeDisplay.redoCalculations(881153);
+						togglePane(true, false);
+						treePane.setSize(getWidth(),getHeight()-scrollWidth);
+						//toggleLegendFloat();
+					}
+				}
+			}
+		}
+		else {  // fixed size
+			int useWidth = MesquiteInteger.maximum(totalTreeFieldWidth, getWidth());
+			int useHeight = MesquiteInteger.maximum(totalTreeFieldHeight, getHeight()-scrollWidth);
+			//	treeDisplay.setFieldSize(totalTreeFieldWidth, totalTreeFieldHeight);
+			treeDisplay.setFieldSize(totalTreeFieldWidth,totalTreeFieldHeight);
+			treeDisplay.setSize(useWidth,useHeight);
+			treeDisplay.redoCalculations(88);
+			togglePane(true, false);
+			treePane.setSize(getWidth(),getHeight()-scrollWidth);
+		}
+		int CONTROLWIDTH = 42;
+		messageWidth = getWidth() - CONTROLWIDTH;
+		if (usingPane){
+			//treeDisplay.setSize(getWidth()-scrollWidth, getHeight()-scrollWidth-scrollWidth);
+			//hScroll.setBounds(0, getHeight()-scrollWidth-scrollWidth+1, getWidth()-scrollWidth, scrollWidth);  
+			//vScroll.setBounds(getWidth()-scrollWidth, 0, scrollWidth, getHeight()-scrollWidth-scrollWidth);  
+			//hScroll.setValue(treePane.x);
+			treePane.setHMinMax(0, treeDisplay.getFieldWidth()-treePane.getWidth()-scrollWidth);
+
+			vScroll.setBlockIncrement(treePane.getHeight()/10);
+			hScroll.setBlockIncrement(treePane.getWidth()/10);
+			vScroll.setUnitIncrement(10);
+			hScroll.setUnitIncrement(10);
+			resetScrolls();
+			treePane.setVMinMax(0, treeDisplay.getFieldHeight()-treePane.getHeight()-scrollWidth-scrollWidth);
+			treePane.doLayout();
+			//	vScroll.doLayout();
+			//	hScroll.doLayout();
+			//	setOrigin(treeRect.x, treeRect.y);
+		}
+		else {
+			treeDisplay.setSize(getWidth(), getHeight()-scrollWidth);
+			setOrigin(0,0, true);
+			//	hScroll.setLocation(getWidth(), getHeight());  //off screen
+			//	vScroll.setLocation(getWidth(), getHeight());  //off screen
+		}
+		treeDisplay.setVisRect(getTreeViewport());
+		messagePanel.setLocation(CONTROLWIDTH, getHeight()-scrollWidth);
+		controlStrip.setLocation(0, getHeight()-scrollWidth);
+		controlStrip.setSize(CONTROLWIDTH, scrollWidth);
+		messagePanel.setSize(messageWidth,scrollWidth);
+		checkPanelPositionsLegal();
+		treeDisplay.forceRepaint();
+
+	}
+	/*.................................................................................................................*/
+	public Taxa getTaxa() {
+		return taxa;
+	}
+	/*.................................................................................................................*/
+	public void hideTree() {
+		treeDisplay.setVisible(false);
+	}
+	/*.................................................................................................................*/
+	public void showTree() {
+		treeDisplay.setVisible(true);
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public String getTreeDescription() {
+		if (tree == null)
+			return null;
+		return tree.writeTree(Tree.BY_NAMES, false);
+	}
+	public void setTreeDescription(String s){
+		setTreeDescription(s, null);
+	}
+	public void setTreeDescription(String s, String name) {
+		originalTree = null;
+		Tree tr = setTree(s, name);
+
+		if (tr!=null) {
+			treeEdited(true);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setTreeSource(TreeSource tsTask) {
+		boolean setToZero = tsTask != treeSourceTask;
+		treeSourceTask = tsTask;
+		setStoreTreeAsMenuItems(windowModule.editMode);
+
+		resetTitle();
+		if (!MesquiteThread.isScripting()){
+			resetForTreeSource(setToZero, true, false, MesquiteInteger.inapplicable);
+			contentsChanged();
+			treeDisplay.repaint();
+		}
+		else {
+			resetForTreeSource(setToZero, true, false, MesquiteInteger.inapplicable);
+		}
+	}
+	private void zapPreviousEdited(boolean resetEnabling){
+		boolean wasEnabled = false;
+		if (resetEnabling){
+			if (recoverEditedMenuItem!= null)
+				wasEnabled = recoverEditedMenuItem.isEnabled();
+		}
+		if (previousEditedTree != null)
+			previousEditedTree.dispose();
+		if (previousEditedTree != null && previousEditedTree instanceof MesquiteTree)
+			taxa.removeListener((MesquiteTree)previousEditedTree);
+		previousEditedTree = null;
+		if (recoverEditedMenuItem!= null)
+			recoverEditedMenuItem.setEnabled(false);
+		if (resetEnabling){
+			if (recoverEditedMenuItem != null && wasEnabled != recoverEditedMenuItem.isEnabled())
+				MesquiteTrunk.resetMenuItemEnabling();
+		}
+	}
+	/*.................................................................................................................*/
+	private void queryEditedTreeRetentionPreference() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(this, "Retain Edited Tree?",buttonPressed);  
+		queryDialog.addLabel("Retain Edited Tree?");
+		queryDialog.addLargeOrSmallTextLabel("If you have edited a tree in the tree window, then you ask for a change in the tree source, do you want retain the edited tree, or go immediately " +
+				" to the new tree implied by the change in the tree source?  Choose an option:");
+		RadioButtons alignRadios = queryDialog.addRadioButtons(new String[] {"Switch to new tree, but remember edited tree for later recovery", 
+				"Continue to show edited tree", "Ask each time whether to continue with the edited tree, or switch to the new tree"}, editedTreeMODE);
+
+		queryDialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			int oldMode = editedTreeMODE;
+			editedTreeMODE = alignRadios.getValue();
+			if (oldMode != editedTreeMODE)
+				ownerModule.storePreferences();
+		}
+		queryDialog.dispose();
+	}
+
+	private boolean askAboutRetainingEditedTree(){  //return true if to retain
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		ExtensibleDialog queryDialog = new ExtensibleDialog(this, "Retain Edited Tree?",buttonPressed);  
+		queryDialog.addLabel("Retain Edited Tree?");
+		queryDialog.addLargeOrSmallTextLabel("The tree in the window \"" + getTitle() + "\" has been edited but not saved.  " +
+				"Do you want to go to the new tree, or do you want to continue to show the edited tree in the window?\n\nIf you continue to show the edited tree, remember that the tree " 
+				+ "shown might not come from the source of trees currently used by the window.");
+
+		queryDialog.appendToHelpString( "If you choose to go to the new tree, you may be able to recover the edited tree by selecting Recover Last Edited Tree in the Tree menu. " 
+				+ "\n\nIf you choose to continue showing the edited tree, you can store the edited tree by selecting Store Tree As from the Tree menu."
+				+ " To see a tree that belongs to the source of trees used by the window, hit the Enter arrow of the " 
+				+ "Tree scroll in the upper left of the tree window.");
+		Checkbox dontAsk = queryDialog.addCheckBox("Don't ask again. (To change preference, choose Edited Tree Handling Options from the Tree menu.)", false);		
+		queryDialog.completeAndShowDialog("Switch to new tree",  "Continue showing edited tree", null, (String)null);
+		if (dontAsk.getState()){
+			int oldMode = editedTreeMODE;
+			if (buttonPressed.getValue()==0)   //switch to new tree
+				editedTreeMODE = CHANGE_TREE_WITH_SOURCE;
+			else
+				editedTreeMODE = CONTINUE_WITH_EDITED;
+			if (oldMode != editedTreeMODE)
+				ownerModule.storePreferences();
+		}
+
+		queryDialog.dispose();
+
+		return buttonPressed.getValue() != 0;
+		/*return !AlertDialog.query(this, "Retain edited tree?", "The tree in the window has been edited but not saved.  " 
+				+ "Do you want to go to the new tree, or do you want to continue to show the edited tree in the window?\n\nIf you continue, remember that it " 
+				+ "does not come from the source of trees currently used by the window.  "
+				+ "To see the first tree that does belong to the source, hit the Enter arrow of the " 
+				+ "Tree scroll in the upper left of the tree window. To store your edited tree first, ask to continue and then choose Store Tree As from the Tree menu."
+				+ " (To change whether or not Mesquite asks you about this each time, choose Edited Tree Handling Options from the Tree menu.)", "Switch to new tree", "Continue showing edited tree", 0);
+		 */
+	}
+	/* Three modes:
+	 * verbose: if the tree source changes, or its parameters change, and there is an edited tree, then user is pestered to retain edited tree or not UNLESS change was trees added or deleted,
+	 * 		in which case the edited tree is retained
+	 * quiet retain (old style): continue to show edited tree even though it may not match source
+	 * quiet shift: always discard edited tree, but 
+	 * 
+	static final int CONTINUE_WITH_EDITED = 1;
+	static final int CHANGE_TREE_WITH_SOURCE = 0;
+	static final int ASK_USER_TREE_CHANGE = 2;
+	static int editedTreeMODE = CHANGE_TREE_WITH_SOURCE;
+	 */
+	/*.................................................................................................................*/
+
+
+	void resetForTreeSource(boolean setToZero, boolean firstTimeTreeSource, boolean retainEditedRegardless, int notificationCode) {
+		if (disposing)
+			return;
+		resetTitle();
+		if (firstTimeTreeSource)
+			warningGivenForTreeSource = false;
+		MesquiteTree editedTree = null;
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return;
+		}
+
+		if (tree!=null) {
+			boolean retainTree = false;
+			if (retainEditedRegardless || MesquiteThread.isScripting() || editedTreeMODE == CONTINUE_WITH_EDITED || notificationCode == MesquiteListener.ITEMS_ADDED  ||  notificationCode == MesquiteListener.PARTS_ADDED  || notificationCode == MesquiteListener.PARTS_DELETED  || notificationCode == MesquiteListener.PARTS_MOVED )
+				retainTree = true;
+			else if (editedTreeMODE == ASK_USER_TREE_CHANGE && treeEdited && editedByHand)
+				retainTree = askAboutRetainingEditedTree();
+			else
+				retainTree = false;
+
+			boolean wasEnabled = false;
+			if (recoverEditedMenuItem!= null)
+				wasEnabled = recoverEditedMenuItem.isEnabled();
+			if (treeEdited){
+				if (retainTree) {
+					editedTree = tree;  // if this is done, and the tree is unot disposed, then it will be remembered
+					zapPreviousEdited(false);
+				}
+				else {
+					if (previousEditedTree != null && previousEditedTree instanceof MesquiteTree)
+						taxa.removeListener((MesquiteTree)previousEditedTree);
+					previousEditedTree = tree.cloneTree();
+					if (previousEditedTree instanceof MesquiteTree)
+						taxa.addListener((MesquiteTree)previousEditedTree);
+					if (recoverEditedMenuItem!= null)
+						recoverEditedMenuItem.setEnabled(true);
+				}
+			}
+			else {
+				zapPreviousEdited(false);
+			}
+			if (recoverEditedMenuItem != null && wasEnabled != recoverEditedMenuItem.isEnabled())
+				MesquiteTrunk.resetMenuItemEnabling();
+			unhookPreviousTree();
+			if (!retainTree)
+				tree.dispose();
+
+		}
+		treeAnnotationShown = false;
+		//	tree=null; //done to catch spurious redraws
+		treeVersion = 0;
+		treeDisplay.setTree(null); //done to catch spurious redraws
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		if (numTrees == 0){
+			currentTreeNumber = 0;
+			palette.paletteScroll.setCurrentValue(0); 
+			palette.paletteScroll.setMinimumValue(0); 
+			palette.paletteScroll.setMaximumValue(0); 
+			palette.paletteScroll.setEnableEnter(false); 
+			palette.paletteScroll.setEnterLock(true); 
+		}
+		else{
+			palette.paletteScroll.setEnterLock(false); 
+			palette.paletteScroll.setEnableEnter(true); 
+			palette.paletteScroll.setMinimumValue(MesquiteTree.toExternal(0)); 
+			palette.paletteScroll.setMaximumValue(MesquiteTree.toExternal(numTrees-1)); 
+			if (setToZero || currentTreeNumber>= numTrees)
+				goToTreeNumber(0, false);
+			else
+				goToTreeNumber(currentTreeNumber, false);
+		}
+
+
+
+		if (editedTree!=null) {
+			//originalTree = null;
+			setTree(editedTree);
+			if (firstTimeTreeSource){
+				if (originalTree != null && originalTree instanceof MesquiteTree)
+					taxa.removeListener((MesquiteTree)originalTree);
+				originalTree = null;  //otree
+			}
+			treeEdited(false);
+		}
+
+		storeTreeMenuItem.setEnabled(!treeSourceLocked());
+		MesquiteTrunk.resetMenuItemEnabling();
+		//resetLockImage();
+		checkPanelPositionsLegal();
+		resetBaseExplanation();
+	}
+	public void numTreesChanged() {
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return;
+		}
+		palette.paletteScroll.setMinimumValue(MesquiteTree.toExternal(0)); 
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		palette.paletteScroll.setMaximumValue(MesquiteTree.toExternal(numTrees-1)); 
+		if (currentTreeNumber>= numTrees && MesquiteInteger.isCombinable(numTrees)) {
+			currentTreeNumber = numTrees -1;
+			goToTreeNumber(currentTreeNumber, true);
+		}
+		checkPanelPositionsLegal();
+		resetBaseExplanation();
+	}
+	/*.................................................................................................................*/
+	public void addAssistant(TreeDisplayAssistant tda) {
+		tda.setEmployeesInStartup(true);  // normally used only within EmployerEmployee, this helps assistants know they are still in startup phase
+		treeDrawCoordTask.addAssistantTask(tda);
+
+		TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplay);
+
+
+		if (tce==null) 
+			return;
+		if (tree != null)
+			tce.setTree(tree);
+		treeDisplay.addExtra(tce);
+		checkPanelPositionsLegal();
+		treeDisplay.pleaseUpdate(false);
+		if (getMode()>0)
+			updateTextPage();
+		tda.setEmployeesInStartup(false);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.incorporate(super.getSnapshot(file), false);
+
+		if (MesquiteTrunk.snapshotMode!=Snapshot.SNAPDISPLAYONLY) {
+			temp.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
+			temp.addLine("setTreeNumber " +(MesquiteTree.toExternal(currentTreeNumber)));  
+			if ((treeEdited || windowModule.editMode) && tree!=null) {
+				temp.addLine("setTree " + StringUtil.tokenize(tree.writeTree(Tree.BY_NUMBERS, false))); 
+				if (!StringUtil.blank(tree.getAnnotation()))
+					temp.addLine("setTreeAnnotation " + StringUtil.tokenize(tree.getAnnotation())); 
+
+				if (file !=null && BasicTreeWindowMaker.warnUnsaved){
+					BasicTreeWindowMaker.warnUnsaved = false;
+					ownerModule.storePreferences();
+					String s = "The tree in a tree window has been edited, and is a temporary tree associated with the window.  ";
+					s += "The fact that it is a temporary tree is indicated by the tree window\'s bar toward the bottom that indicates the tree name with a black diamond.  ";
+					s += "If you haven\'t stored it in the file using Store Tree from the Tree menu, then this temporary tree won't be stored in a public part of the file, ";
+					s += "and other programs won't be able to see the tree.\nIf you want other programs to see a temporary tree in a tree window, use Store Tree then resave the file.";
+					ownerModule.alert(s);
+				}
+			}
+		}
+		if (drawingSizeMode != FIXEDSIZE){
+			temp.addLine("setDrawingSizeMode " + drawingSizeMode);
+			temp.addLine("toggleLegendFloat " + floatLegends.toOffOnString());
+		}
+		else if (drawingSizeMode == FIXEDSIZE){
+			temp.addLine("setDrawingSizeMode " + drawingSizeMode + " " + totalTreeFieldWidth + " " + totalTreeFieldHeight + "  " + getOriginX() + " " + getOriginY());
+			temp.addLine("toggleLegendFloat " + floatLegends.toOffOnString());
+		}
+		if (drawingSizeMode == AUTOSIZE){
+			temp.addLine("scale " + scale);
+		}
+
+		temp.addLine("toggleTextOnTree " + textVersionDrawOnTree.toOffOnString());
+		if (treeInfoPanelEverShown){
+			if (treeInfoPanel != null){
+				temp.addLine("getInfoPanel");
+				temp.addLine("tell It");
+				temp.incorporate(treeInfoPanel.getSnapshot(file), true);
+				temp.addLine("endTell");
+			}
+			temp.addLine("toggleInfoPanel " + infoPanelOn.toOffOnString());
+		}
+		temp.addLine("togglePrintName " + windowModule.printNameOnTree.toOffOnString());
+		temp.addLine("showWindow");
+		return temp;
+	}
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public String getPrintMenuItem() {
+		return "Print Tree...";
+	}
+	/*.................................................................................................................*/
+	public String getPrintToFitMenuItemName() {
+		return "Print Tree To Fit Page...";
+	}
+	/*.................................................................................................................*/
+	/**
+	 * @author Peter Midford 
+	 */
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			if (infoBar.getMode()>0)
+				super.windowToPDF(pdfFile, fitToPage);
+			else {
+				Dimension oldTreeDisplaySize =  treeDisplay.getSize();
+				treeDisplay.setPrintingInProcess(true);
+				treeDisplay.setSize(treeDisplay.getFieldWidth(), treeDisplay.getFieldHeight());
+				Rectangle r = treeDisplay.getVisRect();
+				treeDisplay.setVisRect(null);
+
+				Graphics g2 = pdfFile.getPDFGraphicsForComponent(treeDisplay,null);
+				treeDisplay.printAll(g2);
+				treeDisplay.setSize(oldTreeDisplaySize.width, oldTreeDisplaySize.height);
+				treeDisplay.setVisRect(r);
+				treeDisplay.setPrintingInProcess(false);
+				treeDisplay.repaintAll();
+				pdfFile.end();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/**
+	 * @author Peter Midford
+	 */
+	public String getPrintToPDFMenuItemName() {
+		return "Save Tree as PDF...";
+	}
+
+	protected void pdfWindow(int fitToPage) {
+		super.pdfWindow(fitToPage);
+	}
+	/*.................................................................................................................*/
+	public void printWindow(MesquitePrintJob pjob) {
+		if (pjob != null) {
+			if (infoBar.getMode()>0) 
+				super.printWindow(pjob);
+			else 
+				pjob.printComponent(treeDisplay, null, currentFont);
+		}
+	}
+	/*.................................................................................................................*/
+	public void setCurrentTool(MesquiteTool tool){
+		if (tool!=null && !tool.getEnabled())
+			return;
+		if (tool instanceof TreeTool)
+			currentTreeTool = (TreeTool)tool;
+		super.setCurrentTool(tool);
+	}
+	/*...............................................................................................................*/
+	protected void setContentsCursor(Cursor c){
+		if (c == null)
+			MesquiteMessage.printStackTrace("Error: cursor of tree window null");
+		else if (treeDisplay !=null)
+			treeDisplay.setCursor(c);
+	}
+
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger();
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires a tree display assistant module", "[name of assistant module]", commandName, "newAssistant")) {
+			ownerModule.incrementMenuResetSuppression();
+			TreeDisplayAssistant tda= (TreeDisplayAssistant)ownerModule.hireNamedEmployee(TreeDisplayAssistant.class, arguments);
+			if (tda!=null) {
+				addAssistant(tda);
+				if (!MesquiteThread.isScripting())
+					ownerModule.resetContainingMenuBar();
+			}
+			ownerModule.decrementMenuResetSuppression();
+			return tda;
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree info panel", null, commandName, "getInfoPanel")) {
+			return treeInfoPanel;
+		}
+		else if (checker.compare(this.getClass(), "Returns analyses at nodes as a table", null, commandName, "getAsTable")) {
+			if (treeDisplay == null)
+				return null;
+			String s = treeDisplay.getTableVersion();
+			return s;
+		}
+		else if (checker.compare(this.getClass(), "Shows analyses at nodes as a table", null, commandName, "showAsTable")) {
+			if (treeDisplay == null)
+				return null;
+			String s = treeDisplay.getTableVersion();
+			ownerModule.logln(s);
+		}
+		else if (checker.compare(this.getClass(), "Shows taxon", "[id of taxa block][number of taxon]", commandName, "showTaxon")) {
+			pos.setValue(0);
+			long whichTaxaBlock = MesquiteInteger.fromString(arguments, pos);
+			if (whichTaxaBlock != taxa.getID())
+				return null;
+			int which = MesquiteInteger.fromString(arguments, pos);
+			if (which >= 0 && which < taxa.getNumTaxa()){
+				makeTaxonVisible(which);
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Selects taxon", "[number of taxon]", commandName, "selectTaxon")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (which >= 0 && which < taxa.getNumTaxa()){
+				taxa.setSelected(which, !taxa.getSelected(which));
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				makeTaxonVisible(which);
+			}
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Puts legends in default position", null, commandName, "legendsToHome")) {
+			Component[] cc = treeDisplay.getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++) {
+					if (cc[i] instanceof Legend){
+						Legend legend = (Legend)cc[i];
+						legend.setOffsetX( 0);
+						legend.setOffsetY( 0);
+						legend.adjustLocation();
+					}
+				}
+
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree draw coordinating module", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else if (checker.compare(this.getClass(), "Forces a repaint", null, commandName, "forceRepaint")) {
+			treeDisplay.redoCalculations(33);
+			treeDisplay.forceRepaint();
+		}
+		else if (checker.compare(this.getClass(), "Hires a tree window assistant module", "[name of assistant module]", commandName, "newWindowAssistant")) {
+			TreeWindowAssistant tda= (TreeWindowAssistant)ownerModule.hireNamedEmployee(TreeWindowAssistant.class, arguments);
+			if (tda!=null && tree != null)
+				tda.setTree(tree);
+			return tda;
+		}
+		else if (checker.compare(this.getClass(), "Returns the tree", null, commandName, "getTree")) {
+			return tree;
+		}
+		else if (checker.compare(this.getClass(), "Brings the graphics of an assistant module to the front", "[number of assistant module among TreeDisplayDrawnExtra owners]", commandName, "bringToFront")) {
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			ListableVector ev = treeDisplay.getExtras();
+			int count =0;
+			for (int i=0; i< ev.size(); i++){
+				TreeDisplayExtra extra = (TreeDisplayExtra)ev.elementAt(i);
+				if (extra!=null && extra instanceof TreeDisplayDrawnExtra) {
+					if (count== which) {
+						TreeDisplayExtra found = extra;
+						ownerModule.moveEmployeeToFront(extra.getOwnerModule());
+						treeDisplay.moveExtraToFront(extra);
+						ownerModule.resetContainingMenuBar();
+						return null;
+					}
+					count++;
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Closes an assistant module", "[number of assistant module]", commandName, "closeDisplayAssistant")) {
+			EmployeeVector ev = ownerModule.getEmployeeVector();
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			int count =0;
+			for (int i=0; i< ev.size(); i++){
+				MesquiteModule mb = (MesquiteModule)ev.elementAt(i);
+				if (mb!=null && mb instanceof TreeDisplayAssistantAD) {
+					if (count== which) {
+						ownerModule.fireEmployee(mb);
+						return null;
+					}
+					count++;
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Saves a macro to redo the analysis of an assistant module", "[number of assistant module]", commandName, "saveMacroDisplayAssistant")) {
+			EmployeeVector ev = ownerModule.getEmployeeVector();
+			int which = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(which))
+				return null;
+			int count =0;
+			for (int i=0; i< ev.size(); i++){
+				MesquiteModule mb = (MesquiteModule)ev.elementAt(i);
+				if (mb!=null && mb instanceof TreeDisplayAssistantAD) {
+					if (count== which) {
+						String recipe = "newAssistant #" + mb.getClass().getName() + ";" + StringUtil.lineEnding() + "tell It;"+ StringUtil.lineEnding();
+						recipe += Snapshot.getSnapshotCommands(mb, null, "");
+						recipe += "endTell;"+ StringUtil.lineEnding();
+						MesquiteMacro.saveMacro(ownerModule, "Macro to start " + mb.getNameForMenuItem(), 0, recipe);
+						return null;
+					}
+					count++;
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree as having been edited (e.g. so that it can be treated as \"untitled\")", null, commandName, "treeEdited")) {
+			treeEdited(true);
+			treeChanged( true);
+			setTreeName(tree);
+			setExplanation(baseExplanation, true);
+			if (getMode()>0)
+				updateTextPage();
+		}
+		/*   	 	else if (checker.compare(this.getClass(), "Sets the tree to that described by the string passed, and presented in a standard rotation.", null, commandName, "setStandardizedTree")) { 
+    	 		Tree t = setTree(ParseUtil.getFirstToken(arguments, pos));
+    	 		if (t instanceof MesquiteTree)
+    	 			((MesquiteTree)t).standardize(t.getRoot(),false);
+    	 		if (t!=null){
+    	 			treeEdited(true);
+    	 			setTreeName();
+    	 			return t;
+    	 		}
+    	 	}
+		 */
+		else if (checker.compare(this.getClass(), "Sets the tree to that described by the string passed", "[Parenthesis notation string of tree]", commandName, "queryEditedTreeMode")) {
+			queryEditedTreeRetentionPreference();
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree to that described by the string passed", "[Parenthesis notation string of tree]", commandName, "setTree")) {
+			String descr = ParseUtil.getFirstToken(arguments, pos);
+
+			Tree t = setTree(descr);  // process the tree fully, including [%color = 4]
+			if (t!=null){
+				treeEdited(true);
+				setTreeName(t);
+				return t;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree to a recently edited tree", "[number of edited tree]", commandName, "showRecentEdited")) {
+			int r = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(r) && r < recentEditedTrees.size()) {
+				MesquiteBoolean editStatusToSet = new MesquiteBoolean();
+				Tree t = setCloneOfTree(recentEditedTrees.getTree(r), false, editStatusToSet);
+				treeEdited(editStatusToSet.getValue());
+				setTreeName(t);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Recovers the last edited tree", null, commandName, "recoverLastEditedTree")) {
+			if (previousEditedTree !=null) {
+				MesquiteBoolean editStatusToSet = new MesquiteBoolean();
+				Tree t = setCloneOfTree(previousEditedTree, false, editStatusToSet);
+				treeEdited(editStatusToSet.getValue());
+				setTreeName(t);
+			}
+		}
+
+		else if (checker.compare(this.getClass(), "Shows the window", null, commandName, "showWindow")) {
+			sizeDisplay();
+			setVisible(true);
+			//if (useSuggestedSize.getValue())
+			//	setSuggestedSize(false, true);
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the annotation for the current tree", "[Annotation for tree in window]", commandName, "setTreeAnnotation")) {
+			String note = ParseUtil.getFirstToken(arguments, pos);
+			if (tree!=null && treeEdited) {
+				tree.setAnnotation(note, true);
+				showTreeAnnotation();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Returns the number of trees", null, commandName, "getNumTrees")) {
+			return new MesquiteInteger(treeSourceTask.getNumberOfTrees(taxa));
+		}
+		else if (checker.compare(this.getClass(), "Returns the current tree number", null, commandName, "getTreeNumber")) {
+			return new MesquiteInteger(currentTreeNumber);
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree to be the i'th one from the current tree source", "[number of tree to be shown]", commandName, "setTreeNumber")) {
+			return goToTreeNumber(MesquiteTree.toInternal(MesquiteInteger.fromFirstToken(arguments, pos)), true);
+		}
+		else if (checker.compare(this.getClass(), "Present a dialog box to choose a tree from the current tree source", null, commandName, "chooseTree")) {
+			int ic=treeSourceTask.queryUserChoose(taxa, "for tree window");
+			if (MesquiteInteger.isCombinable(ic)) {
+				return goToTreeNumber(ic, true);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Stores the current tree as a new stored tree in a tree block", null, commandName, "storeTreeAs") || checker.compare(this.getClass(), "Stores the current tree as a new stored tree in another tree block", null, commandName, "storeTreeAsOther")) {
+			boolean inOther = commandName.equalsIgnoreCase("storeTreeAsOther");
+			MesquiteTree tree = treeDisplay.getTree().cloneTree();
+
+			//if treeSourceTask is Stored Trees, and tree is saved into same block as being shown, then should change current tree to that one and jump to there???
+
+			String s = ParseUtil.getFirstToken(arguments, new MesquiteInteger(0));
+
+			if (StringUtil.blank(s))
+				s = MesquiteString.queryString(this, "Store Tree As" , "Name of tree: ", tree.getName() );
+			if (s!=null) {
+				tree.setName(s);
+				TreeVector trees =  null;
+				if (!inOther && originalTree!=null && ((MesquiteTree)originalTree).getTreeVector() !=null){
+					trees = ownerModule.getProject().storeTree(this, ((MesquiteTree)originalTree).getTreeVector(), tree,true);
+				}
+				else
+					trees = ownerModule.getProject().storeTree(this, null, tree,true);
+				if (trees!=null) {
+					TreesManager manager = (TreesManager)ownerModule.findElementManager(TreeVector.class);
+					if (manager !=null){
+						int listNum = manager.getTreeBlockNumber(trees);
+						if (showTreeListOnSave)
+							manager.doCommand("showTrees", Integer.toString(listNum), checker);
+						showTreeListOnSave = false;
+
+						if (treeSourceTask!=null && "Stored Trees".equalsIgnoreCase(treeSourceTask.getName())){
+							boolean oldSuppress = ((BasicTreeWindowMaker)ownerModule).suppressEPCResponse;
+							((BasicTreeWindowMaker)ownerModule).suppressEPCResponse		= true;
+							TreeVector v = (TreeVector)treeSourceTask.doCommand("setTreeBlockByID", "" + trees.getID(), CommandChecker.defaultChecker);
+							((BasicTreeWindowMaker)ownerModule).suppressEPCResponse = oldSuppress;
+							if (v == trees) {
+								resetForTreeSource(false, false, false, MesquiteInteger.inapplicable);
+								goToTreeNumber(trees.size()-1, true);
+							}
+							if (windowModule.editMode){
+								treeSourceTask.doCommand("laxOff", null, checker);
+								windowModule.editMode = false;
+								editedByHand = false;
+							}
+								resetBaseExplanation();
+								resetTitle();
+						}
+						setStoreTreeAsMenuItems(windowModule.editMode);
+						numTreesChanged();
+						return trees;
+					}
+				}
+
+
+
+
+			} 
+		}
+		else if (checker.compare(this.getClass(), "Stores the current tree back into the original stored tree from which it came", null, commandName, "storeTree")) {
+			//Tree tree = basicTreeWindow.tree; //should get this straight from tree window!!!!!!!
+			if (treeSourceLocked())
+				return null;
+			if (originalTree!=null && treeEdited) {
+				((MesquiteTree)originalTree).setToClone(tree);
+				if (originalTree!=null)
+					((MesquiteTree)originalTree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+				if (originalTree!=null && ((MesquiteTree)originalTree).getTreeVector() !=null)
+					((MesquiteTree)originalTree).getTreeVector().notifyListeners(this, new Notification(MesquiteListener.PARTS_CHANGED));
+				treeEdited = false;
+				zapPreviousEdited(true);
+				editedByHand = false;
+				messagePanel.setHighlighted(false); 
+				if (treeInfoPanel != null)
+					treeInfoPanel.setHighlighted(!treeSourceLocked());
+				resetBaseExplanation();
+				resetTitle();
+			}
+			return originalTree;
+		}
+		else if (checker.compare(this.getClass(), "Gets tree vector being shown.", null, commandName, "getTreeVector")) {
+			if (originalTree!=null && ((MesquiteTree)originalTree).getTreeVector() !=null)
+				return ((MesquiteTree)originalTree).getTreeVector();
+
+		}
+		else if (checker.compare(this.getClass(), "Goes to the next tree in the tree source.  THIS RUNS ON GUI THREAD.", null, commandName, "nextTree")) {
+			palette.paletteScroll.increment();
+		}
+		else if (checker.compare(this.getClass(), "Goes to the previous tree in the tree source.  THIS RUNS ON GUI THREAD.", null, commandName, "previousTree")) {
+			palette.paletteScroll.decrement();
+		}
+		else if (checker.compare(this.getClass(), "Steps through the trees.", null, commandName, "stepThroughTrees")) {
+			stepThroughTrees();
+		}
+		else if (checker.compare(this.getClass(), "Goes to the next tree in the tree source.", null, commandName, "goToNextTree")) {
+			incrementTreeNumber();
+		}
+		else if (checker.compare(this.getClass(), "Undoes the previous tree change", null, commandName, "undo")) {
+			if (undoTree !=null && canUndo && undoTree.upToDateWithTaxa()) {
+				MesquiteBoolean editStatusToSet = new MesquiteBoolean();
+				setCloneOfTree(undoTree, false, editStatusToSet);
+				treeEdited(editStatusToSet.getValue());
+				return tree;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Copies a description of the tree", null, commandName, "copyTree")) {
+			if (tree != null) {
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				StringSelection ss = new StringSelection(tree.writeTree(Tree.BY_NAMES, false));
+				clip.setContents(ss, ss);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Pastes a description of the tree", null, commandName, "Paste")) {
+			if (tree != null) {
+				Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+				Transferable t = clip.getContents(this);
+				try {
+					String s = (String)t.getTransferData(DataFlavor.stringFlavor);
+					Tree tr = setTree(s);
+
+					if (tr!=null) {
+						treeEdited(true);
+						return tr;
+					}
+
+				}
+				catch (Exception e){
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to alter or transform branch lengths", "[name of module]", commandName, "alterBranchLengths")) {
+			BranchLengthsAlterer ble = (BranchLengthsAlterer)ownerModule.hireNamedEmployee(BranchLengthsAlterer.class, arguments);
+			if (ble!=null) {
+				boolean success = ble.transformTree(tree, null, true);
+				if (success){
+					if (treeSourceLocked())
+						tree.setName("Untitled Tree");
+					treeEdited(false);
+				}
+				ownerModule.fireEmployee(ble); //todo: for branch length estimators, might be good to keep it around, and remembering it if user wants to change parameters
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to alter the tree", "[name of module]", commandName, "alterTree")) {
+			TreeAlterer ble = (TreeAlterer)ownerModule.hireNamedEmployee(TreeAlterer.class, arguments);
+			if (ble!=null) {
+				boolean success = ble.transformTree(tree, null, true);
+				if (success){
+					if (treeSourceLocked())
+						tree.setName("Untitled Tree");
+					treeEdited(false);
+					treeDisplay.pleaseUpdate(true);
+				}
+				ownerModule.fireEmployee(ble); 
+			}
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether the info panel is on", null, commandName, "toggleInfoPanel")) {
+			infoPanelOn.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			setTreeInfoPanel(infoPanelOn.getValue());
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether to add the name of the tree when printing", null, commandName, "togglePrintName")) {
+			windowModule.printNameOnTree.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+		}
+		else if (checker.compare(this.getClass(), "(For old scripts only) Requests that the tree is drawn to a default (suggested) size", null, commandName, "useSuggestedSize")) {
+			MesquiteBoolean useSuggestedSize = new MesquiteBoolean(drawingSizeMode == AUTOSIZE);
+			useSuggestedSize.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+
+			if (useSuggestedSize.getValue()) {
+				drawingSizeMode = AUTOSIZE;
+			}
+			else
+				drawingSizeMode = SCALETOFIT;
+
+			sizeModeName.setValue(sizeModes.getValue(drawingSizeMode)); //so that menu item knows to become checked
+			if (!MesquiteThread.isScripting()){
+				sizeDisplay();
+				treeDisplay.pleaseUpdate(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "(For old scripts only) Sets whether or not the tree is drawn so as to fit within the window, or so as to fit within a scrollable pane", "[on or off to indicate whether constrained to window]", commandName, "toggleSizeToFit")) {
+			MesquiteBoolean sizeToFit = new MesquiteBoolean(drawingSizeMode == SCALETOFIT);
+
+			pos.setValue(0);
+			sizeToFit.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (sizeToFit.getValue()) {
+				drawingSizeMode = SCALETOFIT;
+				toolMAG.setEnabled(false);
+			}
+			else{
+				drawingSizeMode = AUTOSIZE;
+				toolMAG.setEnabled(true);
+			}
+			sizeModeName.setValue(sizeModes.getValue(drawingSizeMode)); //so that menu item knows to become checked
+			if (!MesquiteThread.isScripting()){
+				sizeDisplay();
+				treeDisplay.pleaseUpdate(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "(For old scripts only) Sets the size of the drawing pane area (and implicitly sets to fixed size)", "[width in pixels of drawing area] [height in pixels of drawing area]", commandName, "sizeDrawing")) {
+			pos.setValue(0);
+			int w = MesquiteInteger.fromString(arguments, pos);
+			int h = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(h)  ||  MesquiteInteger.isCombinable(w)) {
+				drawingSizeMode = FIXEDSIZE;
+				sizeModeName.setValue(sizeModes.getValue(drawingSizeMode)); //so that menu item knows to become checked
+				toolMAG.setEnabled(false);
+				boolean resize = false;
+				if (MesquiteInteger.isCombinable(h) && h>10) {
+					totalTreeFieldHeight = h;
+					resize = true;
+				}
+				if (MesquiteInteger.isCombinable(w) && w>10) {
+					totalTreeFieldWidth = w;
+					resize = true;
+				}
+				if (resize) {
+					sizeDisplay();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "(For old scripts only) Sets the origin for the scrolling area", "[origin x] [origin y]", commandName, "setOrigin")) {
+			pos.setValue(0);
+			int horiz = MesquiteInteger.fromString(arguments, pos);
+			int vert = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(horiz) && MesquiteInteger.isCombinable(vert)) {
+				setOrigin(horiz, vert, true);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets zoom scale", "[log base 2 of scale]", commandName, "scale")) {
+			pos.setValue(0);
+			int s = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(s)) {
+				scale = s;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the drawing size mode", "[mode] [width in pixels of drawing area] [height in pixels of drawing area] [x origin] [y origin]", commandName, "setDrawingSizeMode")) {
+			pos.setValue(0);
+			int mode = MesquiteInteger.fromString(arguments, pos); //sets the mode
+
+			if (!MesquiteInteger.isCombinable(mode)){  // || drawingSizeMode == mode
+				Parser parser = new Parser();
+				String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+				mode = sizeModes.indexOf(name); //see if the option is recognized by its name
+				if (mode < 0){
+					sizeModeName.setValue(sizeModes.getValue(drawingSizeMode)); //so that menu item knows to become checked
+					return null;
+				}
+			}
+			drawingSizeMode = mode;
+			sizeModeName.setValue(sizeModes.getValue(mode)); //so that menu item knows to become checked
+			MesquiteTrunk.resetCheckMenuItems();
+			toolMAG.setEnabled(drawingSizeMode == AUTOSIZE);
+			if (drawingSizeMode != AUTOSIZE)
+				scale = 0;
+			if (drawingSizeMode == FIXEDSIZE){
+				int w = MesquiteInteger.fromString(arguments, pos);
+				int h = MesquiteInteger.fromString(arguments, pos);
+				if (MesquiteInteger.isCombinable(h)  ||  MesquiteInteger.isCombinable(w)) {
+					boolean resize = false;
+					if (MesquiteInteger.isCombinable(h) && h>10) {
+						totalTreeFieldHeight = h;
+						resize = true;
+					}
+					if (MesquiteInteger.isCombinable(w) && w>10) {
+						totalTreeFieldWidth = w;
+						resize = true;
+					}
+					if (resize && !MesquiteThread.isScripting()) {
+						sizeDisplay();
+					}
+					int horiz = MesquiteInteger.fromString(arguments, pos);
+					int vert = MesquiteInteger.fromString(arguments, pos);
+					if (MesquiteInteger.isCombinable(horiz) && MesquiteInteger.isCombinable(vert)) {
+						setOrigin(horiz, vert, true);
+					}
+				}
+				else { 
+					MesquiteBoolean answer = new MesquiteBoolean(false);
+					MesquiteInteger newWidth = new MesquiteInteger(totalTreeFieldWidth);
+					MesquiteInteger newHeight =new MesquiteInteger(totalTreeFieldHeight);
+					MesquiteInteger.queryTwoIntegers(ownerModule.containerOfModule(), "Size of tree drawing", "Width (Pixels)",  "Height (Pixels)", answer,  newWidth, newHeight,10,MesquiteInteger.unassigned,10, MesquiteInteger.unassigned,"Enter the width and height of the tree drawing.  These values must be at least 10 pixels each.");
+					if (answer.getValue() && newWidth.getValue()>10 && newHeight.getValue()>10) {
+						totalTreeFieldWidth = newWidth.getValue();
+						totalTreeFieldHeight = newHeight.getValue();
+						if (!MesquiteThread.isScripting())
+							sizeDisplay();
+					}
+				}
+			}
+			else if (!MesquiteThread.isScripting())
+				sizeDisplay();
+		}
+		else if (checker.compare(this.getClass(), "When Size to Window is false, brings legends into view", null, commandName, "toggleLegendFloat")) {
+			boolean current = floatLegends.getValue();
+			pos.setValue(0);
+			floatLegends.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (current != floatLegends.getValue())
+				toggleLegendFloat();
+			else
+				checkPanelPositionsLegal();
+
+		}
+		else if (checker.compare(this.getClass(), "In Text version of window, controls whether extras like trace character show their information directly on a tree or as a list of nodes", null, commandName, "toggleTextOnTree")) {
+			boolean current = textVersionDrawOnTree.getValue();
+			pos.setValue(0);
+			textVersionDrawOnTree.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (current != textVersionDrawOnTree.getValue()) {
+				treeDisplay.textVersionDrawOnTree = textVersionDrawOnTree.getValue();
+				if (getMode()>0)
+					updateTextPage();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets size of tree window", "[width in pixels of window] [height in pixels of window]", commandName, "setSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int width= MesquiteInteger.fromString(arguments, io);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(width) && MesquiteInteger.isCombinable(height)) {
+				fromScriptCommand = true;  //this is needed to counteract difficulties with popping in/out and size setting in window constructors
+
+				setWindowSize(width, height);
+				fromScriptCommand = false;
+				if (!MesquiteThread.isScripting()){
+					sizeDisplay();
+					treeDisplay.redoCalculations(355);
+					treeDisplay.forceRepaint();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the current tool", "[name of tool]", commandName, "setTool")) {
+			ToolPalette palette = getPalette();
+			if (palette ==null)
+				return null;
+			currentTreeTool = (TreeTool)palette.getToolWithName(arguments);
+			setCurrentTool(currentTreeTool);
+			setExplanation(currentTreeTool.getDescription());
+		}
+		else if (checker.compare(this.getClass(), "Root current tree along branch", "[branch number]", commandName, "rootAlongBranch")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int atBranch= MesquiteInteger.fromString(arguments, io);
+			if (atBranch >0 &&  tree.reroot(atBranch, tree.getRoot(), true)) {
+				treeEdited(false);
+				if (ladderizeAfterReroot.getValue())
+					tree.standardize(tree.getRoot(), true, true);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Move one branch onto another", "[branch being moved] [branch onto which first will be attached]", commandName, "moveBranch")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int branchFrom= MesquiteInteger.fromString(arguments, io);
+			int branchTo= MesquiteInteger.fromString(arguments, io);
+			if (branchFrom >0 && branchTo >0 &&  (tree.moveBranch(branchFrom, branchTo, true))) {
+				treeEdited(false);
+			}
+
+		}
+		/* cut out as of 1.02; shifted to SelectTaxaInClade
+    	 	else if (checker.compare(this.getClass(), "Touch a taxon in the tree window", "[taxon touched] [branch onto which first will be attached]", commandName, "touchTaxon")) {
+   	 		MesquiteInteger io = new MesquiteInteger(0);
+   			int touched= MesquiteInteger.fromString(arguments, io);
+   			if (touched >=0 && MesquiteInteger.isCombinable(touched)) {
+   				if (arguments.indexOf("shift") >=0) {
+  					taxa.setSelected(touched, !taxa.getSelected(touched));  //reverse selection of touched taxon
+   					taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   				}
+   				else {
+   					taxa.deselectAll();
+   					taxa.setSelected(touched, true);
+   					taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+   				}
+   			}
+
+
+    	 	}*/
+		else if (checker.compare(this.getClass(), "Exchange two branches", "[first branch number] [second branch number]", commandName, "exchangeBranches")) {
+			pos.setValue(0);
+			int branchFrom= MesquiteInteger.fromString(arguments,pos);
+			int branchTo= MesquiteInteger.fromString(arguments,pos);
+			boolean preserveHeights = (arguments.indexOf("option")>=0);
+			if (branchFrom >0 && branchTo >0 &&  (tree.interchangeBranches(branchFrom, branchTo, preserveHeights, true)))
+				treeEdited(false);
+
+		}
+		else if (checker.compare(this.getClass(), "Magnify clade descendant from node", "[node number]", commandName, "magnifyClade")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+
+			if (branchFound >0 && tree.nodeIsInternal(branchFound)) {
+				if (branchFound == treeDisplay.getTreeDrawing().getDrawnRoot())
+					treeDisplay.getTreeDrawing().setDrawnRoot(-1);
+				else
+					treeDisplay.getTreeDrawing().setDrawnRoot(branchFound);
+				treeDisplay.pleaseUpdate(true);
+				messagePanel.repaint();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Zoom image", "[branch][x][y]", commandName, "zoomBT")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			int x= MesquiteInteger.fromString(arguments, pos);
+			int y= MesquiteInteger.fromString(arguments, pos);
+			boolean zoomIn = (arguments.indexOf("option")<0);
+			zoom(x,y, zoomIn);
+		}
+		else if (checker.compare(this.getClass(), "Zoom image", "[x][y]", commandName, "zoom")) {
+			int x= MesquiteInteger.fromFirstToken(arguments, pos);
+			int y= MesquiteInteger.fromString(arguments, pos);
+			boolean zoomIn = (arguments.indexOf("option")<0);
+			zoom(x,y, zoomIn);
+		}
+		else if (checker.compare(this.getClass(), "Resets zoom scale to normal", null, commandName, "zoomReset")) {
+			scale = 0;
+			setOrigin(0,0, true);
+			sizeDisplay();
+		}
+		else if (checker.compare(this.getClass(), "Toggles whether or not to ladderize after rerooting", null, commandName, "toggleRerootLadderize")) {
+			pos.setValue(0);
+			ladderizeAfterReroot.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+		}
+		else if (checker.compare(this.getClass(), "Show popup for options for zoom", "[x][y]", commandName, "zoomOptions")) {
+			MesquiteButton button = toolMAG.getButton();
+			if (button!=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x= MesquiteInteger.fromFirstToken(arguments, pos);
+				int y= MesquiteInteger.fromString(arguments, pos);
+				MesquitePopup popup = new MesquitePopup(button);
+				MesquiteMenuItem mItem = new MesquiteMenuItem("Reset Scale to Normal", ownerModule, new MesquiteCommand("zoomReset", this));
+				popup.add(mItem);
+				popup.showPopup(x,y+6);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Show popup for options for reroot", "[x][y]", commandName, "rerootOptions")) {
+			MesquiteButton button = rerootTool.getButton();
+			if (button!=null){
+				MesquiteInteger io = new MesquiteInteger(0);
+				int x= MesquiteInteger.fromFirstToken(arguments, pos);
+				int y= MesquiteInteger.fromString(arguments, pos);
+				MesquitePopup popup = new MesquitePopup(button);
+				popup.add(toggleRerootLadderizeMenuItem);
+				popup.showPopup(x,y+6);
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Ladderizes the clade", "[branch number]", commandName, "ladderize")) {
+			Parser parser = new Parser();
+			String s = parser.getFirstToken(arguments);
+			int branchFound= MesquiteInteger.fromString(s);
+			if (s.equalsIgnoreCase("root"))
+				branchFound = tree.getRoot();
+			else
+				branchFound= MesquiteInteger.fromString(s);
+			if (branchFound >0) {
+				boolean direction = true;
+				if (arguments.indexOf("option")>=0)
+					direction = false;
+				if (tree.standardize(branchFound, direction, true)){
+					treeEdited(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Ladderizes the clade with focal taxon at left or right", "[taoxn number]", commandName, "focalLadderize")) {
+			int taxonFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (taxonFound >=0) {
+				boolean direction = true;
+				if (arguments.indexOf("option")>=0)
+					direction = false;
+				if (tree.focalStandardize(taxonFound, direction, true)){
+					treeEdited(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Collapse branch to yield polytomy", "[branch number]", commandName, "collapseBranch")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (branchFound >0 && (tree.collapseBranch(branchFound, true)))
+				treeEdited(false);
+		}
+		else if (checker.compare(this.getClass(), "Collapse all internal branches in clade descendant from node", "[node number]", commandName, "collapseAll")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (branchFound >0) {
+				boolean below = false;
+				if (arguments.indexOf("option")>=0)
+					below = true;
+				if (tree.collapseAllBranches(branchFound, below,true))
+					treeEdited(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Draw clade descendant from node compactly as a triangle", "[node number]", commandName, "drawAsTriangle")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			boolean isRoot = tree.getRoot()== branchFound;
+			if (branchFound >0 && tree.nodeIsInternal(branchFound)) {
+				NameReference triangleNameRef = NameReference.getNameReference("triangled");
+				if (isRoot){
+					if (tree.getWhichAssociatedBits(triangleNameRef) != null && tree.getAssociatedBit(triangleNameRef, branchFound)){
+						tree.setAssociatedBit(triangleNameRef, branchFound, false);
+						treeDisplay.pleaseUpdate(true);
+					}
+				}
+				else {
+					if (tree.getWhichAssociatedBits(triangleNameRef) == null)
+						tree.makeAssociatedBits("triangled");
+
+					tree.setAssociatedBit(triangleNameRef, branchFound, !(tree.getAssociatedBit(triangleNameRef, branchFound)));
+					treeDisplay.pleaseUpdate(true);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Cut clade descendant from node", "[node number]", commandName, "cutClade")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (branchFound >0) {
+				if (tree.deleteClade(branchFound, true)) {
+					treeEdited(false);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Cuts selected taxa from the tree", null, commandName, "cutSelectedTaxa")) {
+			boolean changed = false;
+			for (int i = 0; i< taxa.getNumTaxa(); i++){
+				int node = tree.nodeOfTaxonNumber(i);
+				if (tree.nodeExists(node) && taxa.getSelected(i)){
+					tree.deleteClade(node, false);
+					changed = true;
+				}
+			}
+			if (changed) {
+				tree.notifyListeners(this, new Notification(MesquiteListener.PARTS_DELETED));
+				treeEdited(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows the list of taxa", null, commandName, "showTaxaList")) {
+			tree.getTaxa().showMe();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	void stepThroughTrees(){
+		int numW = numberWritable();
+		if (numW == 0) {
+			ownerModule.discreetAlert("Step Through Trees summarizes calculations over a series of trees, but you currently have no calculations active that can be summarized.  \"Values\" in the tree info panel, \"Values for Current Tree\", \"Trace Character History\" and some other calculations can be summarized. (Not all calculations have been enabled for summarizing.)");
+			return;
+		}
+		if (treeSourceTask == null)
+			return;
+		//if tree is edited, save it
+		String returnTree = null;
+		int iCT = currentTreeNumber;
+		if (treeEdited && tree != null){
+			returnTree = tree.writeTree(Tree.BY_NUMBERS, false);
+		}
+		Listable[] list = null;
+		//ask to choose results if multiple writables; if only 1 explain that trees will be cycled. 
+		if (numW>1){
+			ListableVector lv = new ListableVector();
+			for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+				Object e=ownerModule.getEmployeeVector().elementAt(i);
+				if (e instanceof TreeWDIAssistant) {
+					TreeWDIAssistant ta = (TreeWDIAssistant)e;
+					if (ta.suppliesWritableResults()){
+						ObjectContainer oc = new ObjectContainer();
+						oc.setObject(ta);
+						oc.setName(ta.nameForWritableResults());
+						lv.addElement(oc, false);
+
+					}
+				}
+			}
+
+			list = ListDialog.queryListMultiple(this, "Whose results to save?", "You have asked to step through the trees, storing the results of calculations in a text file.  Whose results should be saved in this way?  Choose one or more.", null, lv, null);
+
+		}
+		else {
+			list = new Listable[1];
+			for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+				Object e=ownerModule.getEmployeeVector().elementAt(i);
+				if (e instanceof TreeWDIAssistant) {
+					TreeWDIAssistant ta = (TreeWDIAssistant)e;
+					if (ta.suppliesWritableResults()){
+						ObjectContainer oc = new ObjectContainer();
+						oc.setObject(ta);
+						list[0] = oc;
+						break;
+
+					}
+				}
+			}
+			ownerModule.discreetAlert("You have asked to step through the trees, storing the results of calculations in a text file.  The results that will be stored are from " + list[0].getName());
+		}
+		if (list == null)
+			return;
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		//if infinite number of trees, ask how many
+		if (MesquiteInteger.isInfinite(numTrees)){
+			numTrees = MesquiteInteger.queryInteger(this, "How many trees?", "The tree source for this tree window has unlimited trees.  How many trees do you want to step through?", 100);
+			if (!MesquiteInteger.isCombinable(numTrees))
+				return;
+		}
+		//choose output file
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(this, "Output File for Step Through Trees", FileDialog.SAVE);
+		fdlg.setBackground(ColorTheme.getInterfaceBackground());
+		fdlg.setVisible(true);
+		String fileName=fdlg.getFile();
+		String directory=fdlg.getDirectory();
+		// fdlg.dispose();
+		if (StringUtil.blank(fileName) || StringUtil.blank(directory))
+			return;
+		MesquiteFile.putFileContents(MesquiteFile.composePath(directory, fileName), "Output from Step Through Trees" + StringUtil.lineEnding(), false);
+
+		//write heading
+		for (int i = 0; i<list.length; i++) {
+			ObjectContainer econtainer = (ObjectContainer)list[i];
+
+			Object e=econtainer.getObject();
+			if (e instanceof TreeWDIAssistant) {
+				TreeWDIAssistant ta = (TreeWDIAssistant)e;
+				if (ta.suppliesWritableResults()){
+					Object tH = ta.getResultsHeading();
+					String s = "";
+					if (tH != null){
+						if (tH instanceof String)
+							s = (String)tH;
+						else if (tH instanceof MesquiteNumber){
+							MesquiteNumber mn = (MesquiteNumber)tH;
+							s = mn.toStringNames();
+						}
+						else
+							s = tH.toString();
+					}						
+					MesquiteFile.appendFileContents(MesquiteFile.composePath(directory, fileName), "\t" + s, false);
+
+
+				}
+			}
+		}
+		MesquiteFile.appendFileContents(MesquiteFile.composePath(directory, fileName), StringUtil.lineEnding(), false);
+		for (int iTree = 0; iTree<numTrees; iTree++){
+			goToTreeNumber(iTree, false);
+			MesquiteFile.appendFileContents(MesquiteFile.composePath(directory, fileName), "Tree " + (iTree+1), false);
+			for (int i = 0; i<list.length; i++) {
+				ObjectContainer econtainer = (ObjectContainer)list[i];
+
+				Object e=econtainer.getObject();
+				if (e instanceof TreeWDIAssistant) {
+					TreeWDIAssistant ta = (TreeWDIAssistant)e;
+					if (ta.suppliesWritableResults()){
+						Object tO = ta.getWritableResults();
+						String s = "";
+						if (tO != null){
+							if (tO instanceof String)
+								s = (String)tO;
+							else if (tO instanceof MesquiteNumber){
+								MesquiteNumber mn = (MesquiteNumber)tO;
+								s = mn.toStringWithDetails();
+							}
+							else if (tO instanceof MesquiteNumber[]){
+								MesquiteNumber[] mn = (MesquiteNumber[])tO;
+								for (int k =0; k< mn.length; k++){
+									if (k!=0)
+										s += "\t";
+									s += mn[k].toStringWithDetails();
+								}
+							}
+							else
+								s = tO.toString();
+						}
+						MesquiteFile.appendFileContents(MesquiteFile.composePath(directory, fileName), "\t" + s, false);
+
+					}
+				}
+			}
+			MesquiteFile.appendFileContents(MesquiteFile.composePath(directory, fileName), StringUtil.lineEnding(), false);
+			if (!MesquiteInteger.isCombinable(numTrees))
+				numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		}
+		//return tree to former state
+		goToTreeNumber(iCT, false);
+		if (returnTree != null) {
+			setTree(returnTree);
+			treeEdited(false);
+			treeChanged(true);
+		}
+		treeDisplay.redoCalculations(6519);
+		treeDisplay.repaint();
+
+	}
+	int numberWritable(){
+		int count = 0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+			Object e=ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof TreeWDIAssistant) {
+				TreeWDIAssistant ta = (TreeWDIAssistant)e;
+				if (ta.suppliesWritableResults()){
+					count++;
+				}
+			}
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	int scale = 0;
+	void zoom(int x, int y, boolean zoomIn){
+		int oX =  x;//point touched in old coordinates
+		int oY =  y;
+		if (zoomIn) {
+			scale++;
+			oX *= 2;  //point touched in new coordinates
+			oY *= 2;
+		}
+		else {
+			scale--;
+			oX /= 2;  //point touched in new coordinates
+			oY /= 2;
+		}
+
+		// new origin should center point touched in new coordinates
+		int setX = oX - treeDisplay.getWidth()/2;
+		int setY = oY - treeDisplay.getHeight()/2;
+
+		setOrigin(setX, setY, true);
+		sizeDisplay();
+
+	}
+
+	void setHighlighted(boolean edited){
+		messagePanel.setHighlighted(edited);
+	}
+	/*.................................................................................................................*/
+	public void treeEdited(boolean rememberEditedTree){
+		boolean wasEdited = treeEdited;
+		if (!MesquiteThread.isScripting())
+			editedByHand = true;
+		treeEdited = true;
+		zapPreviousEdited(true);
+		if (wasEdited && treeSourceLocked()) {
+			showTreeAnnotation();
+		}
+		if (rememberEditedTree){
+
+			recentEditedTrees.addElement(tree.cloneTree(), false);
+			if (recentEditedTrees.size()>=maxRecentEditedTrees)
+				recentEditedTrees.removeElementAt(0, false);
+			palette.recentButton.repaint();
+		}
+		if (!treeSourceLocked() && originalTree !=null) {
+			tree.setName(originalTree.getName());
+		}
+		messagePanel.setHighlighted(true);
+		if (treeInfoPanel != null)
+			treeInfoPanel.setHighlighted(!treeSourceLocked());
+		palette.paletteScroll.setEnableEnter(true);
+		if (tree!=null)
+			treeVersion = tree.getVersionNumber();
+		//resetLockImage();
+		highlightedBranch.setValue(0);
+		dropHighlightedBranch.setValue(0);
+		branchFrom = 0;
+		storeTreeMenuItem.setEnabled(!treeSourceLocked());
+		MesquiteTrunk.resetMenuItemEnabling();
+		checkPanelPositionsLegal();
+		resetBaseExplanation();
+	}
+
+	/*
+   	 void lockTouched(){
+   	 	if (!treeSourceTask.nameMatches("StoredTrees") || !(originalTree instanceof MesquiteTree) ) {
+   	 		lockStoredTrees = true;
+   	 		ownerModule.alert("You cannot unlock the trees, because trees are being supplied by \"" + treeSourceTask.getName() + "\" and are not editable Stored Trees.  Because the trees are locked, they can be viewed but not modified.  Attempts to modify the tree will yield an unsaved temporary tree, which can be stored permanently using the Store Tree menu item.");
+   	 	}
+   	 	else if (lockStoredTrees) {
+   	 		lockStoredTrees = false;  //Need to do a save as
+   	 		ownerModule.alert("The stored trees are now unlocked for editing.  Any editing of the tree being browsed will change the original copy stored in the file.");
+   	 	}
+   	 	else {
+   	 		lockStoredTrees = true;
+   	 		ownerModule.alert("The stored trees are now locked.  Attempts to modify the tree being browsed will yield an unsaved temporary tree, which can be stored permanently using the Store Tree menu item.");
+   	 	}
+   	 	resetLockImage();
+   	 }
+   	void resetLockImage(){
+   	   	if (!treeSourceTask.nameMatches("StoredTrees"))
+   	   		lockPanel.setLockState(0);
+   	   	else if (!(originalTree instanceof MesquiteTree) || lockStoredTrees)
+   	   		lockPanel.setLockState(1);
+   	   	else 
+   	   		lockPanel.setLockState(2);
+
+   	}
+	 */
+	boolean treeSourceLocked(){
+		return (originalTree == null || !(originalTree instanceof MesquiteTree) || !(treeSourceTask.nameMatches("StoredTrees") && treeSourceTask.getNumberOfTrees(taxa)> 0)); //lockStoredTrees || 
+	}
+	/*.................................................................................................................*/
+	public Tree incrementTreeNumber(){
+		int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+		if (currentTreeNumber+1 >= numTrees)
+			return null;
+		return goToTreeNumber(currentTreeNumber+1, true);
+	}
+	/*.................................................................................................................*/
+	public Tree goToTreeNumber(int index, boolean rememberEdited){
+		if (disposing)
+			return null;
+		currentTreeNumber = index;
+		if (MesquiteThread.isScripting() && ((BasicTreeWindowMaker)ownerModule).suppressEPCResponse)
+			return null;
+		if (rememberEdited){
+			boolean wasEnabled = false;
+			if (recoverEditedMenuItem!= null)
+				wasEnabled = recoverEditedMenuItem.isEnabled();
+			if (treeEdited){
+				if (previousEditedTree != null && previousEditedTree instanceof MesquiteTree)
+					taxa.removeListener((MesquiteTree)previousEditedTree);
+				previousEditedTree = tree.cloneTree();
+				if (previousEditedTree instanceof MesquiteTree)
+					taxa.addListener((MesquiteTree)previousEditedTree);
+				if (recoverEditedMenuItem!= null)
+					recoverEditedMenuItem.setEnabled(true);
+			}
+			if (recoverEditedMenuItem != null && wasEnabled != recoverEditedMenuItem.isEnabled())
+				MesquiteTrunk.resetMenuItemEnabling();
+		}
+
+		Tree treeT = treeSourceTask.getTree(taxa, index);
+		if (disposing)
+			return null;
+		if (treeT == null){  //source may have not known how many trees; ask if it would revise its current number of trees
+			int numTrees = treeSourceTask.getNumberOfTrees(taxa);
+			if (currentTreeNumber>= numTrees && MesquiteInteger.isCombinable(numTrees)) {
+				currentTreeNumber = numTrees -1;
+				treeT = treeSourceTask.getTree(taxa, currentTreeNumber);
+				palette.paletteScroll.setMaximumValue(MesquiteTree.toExternal(numTrees-1)); 
+
+			}
+		}
+		if (disposing)
+			return null;
+		MesquiteBoolean editStatusToSet = new MesquiteBoolean();
+		Tree t = setCloneOfTree(treeT, true, editStatusToSet);
+		treeEdited = editStatusToSet.getValue();
+		editedByHand = false;
+		setTreeName(t);
+		messagePanel.setHighlighted(treeEdited); 
+		if (treeInfoPanel != null)
+			treeInfoPanel.setHighlighted(!treeSourceLocked());
+
+		palette.paletteScroll.setCurrentValue(MesquiteTree.toExternal(currentTreeNumber));
+
+		//resetLockImage();
+		storeTreeMenuItem.setEnabled(!treeSourceLocked());
+		MesquiteTrunk.resetMenuItemEnabling();
+		resetBaseExplanation();
+		checkPanelPositionsLegal();
+
+		return t;
+	}
+	/*.................................................................................................................*/
+	public String getTextContents() {
+		if (treeDisplay==null)
+			return "";
+		String s = "Tree window";
+		if (taxa!=null)
+			s += " for taxa \"" + taxa.getName() + "\"\n";
+		s += "\n";
+		if (treeSourceTask !=null)
+			s += "----------------\nShowing " + treeSourceTask.getNotesAboutTrees(taxa) + "\n----------------\n";
+		if (originalTree!=null)
+			s += "\nOriginal Tree:  " + originalTree;
+		
+		
+		s += "\n\n"  + treeDisplay.getTextVersion();
+		return s;
+	}
+	/*.................................................................................................................*/
+	public void paintContents(Graphics g) {
+		if (treeDisplay==null)
+		{
+			MesquiteMessage.warnProgrammer("Oh no, tree display is null");
+		}
+		else {
+			//			^^^			sizeDisplay();
+			treeDisplay.repaint();
+			checkPanelPositionsLegal();
+			palette.repaintBirdsEye();
+			g.setColor(Color.black);
+		}
+	}
+	//for java 1.1 printing
+	public Object fit(Dimension dim){
+		/*int w;
+		int h;
+		int currentWidth = treeDisplay.getFieldWidth();
+		int currentHeight = treeDisplay.getFieldHeight();
+		if (currentHeight == 0 || currentWidth == 0) {
+			w = dim.width;
+			h = dim.height;
+		}
+		else if (((double)dim.width)/currentWidth > ((double)dim.height)/currentHeight) {
+			w = (int)(((double)dim.height)/currentHeight * currentWidth);
+			h = dim.height;
+		}
+		else {
+			w = dim.width;
+			h = (int)(((double)dim.width)/currentWidth * currentHeight);
+		}
+		 */
+		Dimension d = new Dimension(getOriginX(), getOriginY());
+		treeDisplay.setFieldSize(dim.width,dim.height);
+		setOrigin(0,0, true);
+		treeDisplay.getTreeDrawing().recalculatePositions(treeDisplay.getTree()); //to force node locs recalc
+		return d;
+	}
+	public void unfit(Object o){
+		int oX = 0;
+		int oY = 0;
+		if (o instanceof Dimension) {
+			oX = ((Dimension)o).width;
+			oY =  ((Dimension)o).height;
+		}
+		setOrigin(oX,oY, true);
+		sizeDisplay();
+	}
+
+	/*_________________________________________________*/
+
+	public   void InvertTaxon(Graphics g, int M) {
+
+		if (findTaxon(treeDisplay.getMouseX(), treeDisplay.getMouseY()) == M){ //still in taxon
+			if (windowModule.getUseXORForBranchMoves() && false) {
+				g.setColor(Color.black);
+				if (GraphicsUtil.useXORMode(g, true)) {
+					g.setXORMode(Color.white);
+					try{
+						treeDisplay.fillTaxon(g, M);
+					}
+					catch (InternalError e){ //workaround to bug in Windows Java 1.7_45
+					}
+					g.setPaintMode();
+					g.setColor(Color.black);
+				}
+			} else {
+				//		g.setColor(Color.black);
+				//		if (GraphicsUtil.useXORMode(g, true)) {
+				//g.setXORMode(Color.white);
+				try{
+					treeDisplay.fillTaxon(g, M);
+				}
+				catch (InternalError e){ //workaround to bug in Windows Java 1.7_45
+				}
+				//			g.setPaintMode();
+				g.setColor(Color.black);
+				//		}
+			}
+			highlightedTaxon=M;
+		}
+		Tree t = treeDisplay.getTree();
+		if (t!=null && t.getTaxa() !=null) {
+			if (t.getTaxa().getAnnotation(M)!=null)
+				setAnnotation(t.getTaxa().getAnnotation(M), "Footnote above refers to taxon \"" + t.getTaxa().getTaxonName(M) + "\"");
+			else {
+				setExplanation("Taxon: " + t.getTaxa().getTaxonName(M));
+				setAnnotation("", null);
+			}
+			treeAnnotationShown = false; //so that the base Explanation can know whether to refer to the annotation
+		}
+	}
+
+	/*_________________________________________________*/
+	public   void RevertTaxon(Graphics g, int M) {
+		if (highlightedTaxon >= 0){
+			g.setColor(Color.black);
+
+			if (windowModule.getUseXORForBranchMoves() && false) {
+
+				if (GraphicsUtil.useXORMode(g, true)) {
+					g.setXORMode(Color.white);
+					try{
+						treeDisplay.redrawTaxa(g, highlightedTaxon);
+					}
+					catch (InternalError e){ //workaround to bug in Windows Java 1.7_45
+					}
+					g.setPaintMode();
+					treeDisplay.repaint();  //TODO: just redraw the taxon
+				}
+			} else {
+
+				//		if (GraphicsUtil.useXORMode(g, true)) {
+				//			g.setXORMode(Color.white);
+				try{
+					//			treeDisplay.redrawTaxa(g, highlightedTaxon);
+				}
+				catch (InternalError e){ //workaround to bug in Windows Java 1.7_45
+				}
+				//			g.setPaintMode();
+				treeDisplay.repaint();  //TODO: just redraw the taxon
+				//			}
+			}
+
+			highlightedTaxon=-1;
+			g.setColor(Color.black);
+		}
+		showTreeAnnotation();
+
+	}
+	/*_________________________________________________*/
+	private int findBranch(int x, int y, MesquiteDouble fraction){
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot(); //TODO: remember drawnRoot!!!
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		return treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, fraction); //check that still in branch
+	}
+	private int findTaxon(int x, int y){
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot(); //TODO: remember drawnRoot!!!
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		return treeDrawCoordTask.getNamesTask().findTaxon(tree, drawnRoot, x, y);
+	}
+	/*_________________________________________________*/
+	NameReference branchNotesRef = NameReference.getNameReference("note");
+	private int countinvert = 0;
+
+	public   void InvertBranchOld(Graphics g, int N, MesquiteInteger highlight) {
+		InvertBranchOld(g,N,highlight, true);
+	}
+	public   void InvertBranchOld(Graphics g, int N, MesquiteInteger highlight, boolean onlyIfStillInBranch) {
+		Tree t = treeDisplay.getTree();
+		if (t!=null){
+			MesquiteDouble fraction = new MesquiteDouble();
+			if (!onlyIfStillInBranch || findBranch(treeDisplay.getMouseX(), treeDisplay.getMouseY(), fraction) == N){ //still in N
+				TreeDrawing treeDrawing = treeDisplay.getTreeDrawing();
+				highlight.setValue(N);   // sets the highlighed branch
+				if (treeDrawing!=null && !treeDisplay.repaintPending()){
+					treeDrawing.fillBranchInverted(t, N, g);
+				}
+				//colorInvertBranch(t,N,g);
+				showBranchExplanation(N);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public   void HighlightBranch(Graphics g, int N, MesquiteInteger highlight) {
+		if (windowModule.getUseXORForBranchMoves())
+			InvertBranchOld(g,N,highlight);
+		else
+			HighlightBranch(g,N,highlight, true);
+	}
+	public   void HighlightBranch(Graphics g, int N, MesquiteInteger highlight, boolean onlyIfStillInBranch) {
+		Tree t = treeDisplay.getTree();
+		if (t!=null){
+			MesquiteDouble fraction = new MesquiteDouble();
+			if (!onlyIfStillInBranch || findBranch(treeDisplay.getMouseX(), treeDisplay.getMouseY(), fraction) == N){ //still in N
+				TreeDrawing treeDrawing = treeDisplay.getTreeDrawing();
+				highlight.setValue(N);   // sets the highlighed branch
+				if (treeDrawing!=null && !treeDisplay.repaintPending()){
+					treeDrawing.highlightBranch(t, N, g);
+				}
+				//colorInvertBranch(t,N,g);
+				showBranchExplanation(N);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void showBranchExplanation(int node){
+		String s = "";
+		if (tree.numberOfParentsOfNode(node)>1) 
+			s = " (Node represents reticulation; has " + tree.numberOfParentsOfNode(node) + " immediate ancestors)";//added 4 feb 02
+		if (tree.nodeIsTerminal(node)) {
+			Taxon t = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(node));
+			if (t!=null)
+				setExplanation("Taxon: " + t.getName() + s);  
+			else
+				setExplanation("Unknown taxon (the tree description may have been malformed or with undefined taxa)" + s);
+		}
+		else {
+			Taxon t1 = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(tree.leftmostTerminalOfNode(node)));
+			Taxon t2 = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(tree.rightmostTerminalOfNode(node)));
+			String n1, n2;
+			if (t1 == null)
+				n1 = "Unknown taxon";
+			else
+				n1 = t1.getName();
+			if (t2 == null)
+				n2 = "Unknown taxon";
+			else
+				n2 = t2.getName();
+			setExplanation(" " + tree.numberOfTerminalsInClade(node) + " taxa in clade (" + n1 + " to " + n2 + ").  Node is number " + node + ". " + s);  
+		}
+	}
+	/*_________________________________________________*/
+	public   void RevertBranchOld(Graphics g, MesquiteInteger highlight) {
+		//treeDisplay.deletePendingMoveDrag();
+
+		int wasHighlighted = highlight.getValue();
+		highlight.setValue(0);
+		if (wasHighlighted> 0 && !treeDisplay.repaintPending()){
+			treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), wasHighlighted, g);
+			//		treeDisplay.getTreeDrawing().fillBranchInverted(t, N, g);
+		}
+		showTreeAnnotation();
+		//setAnnotation("", null);
+		//treeAnnotationShown = false; //so that the base Explanation can know whether to refer to the annotation
+	}
+	/*_________________________________________________*/
+	public   void UnhighlightBranchNew(Graphics g, MesquiteInteger highlight) {
+		//treeDisplay.deletePendingMoveDrag();
+
+		int wasHighlighted = highlight.getValue();
+		highlight.setValue(0);
+		if (wasHighlighted> 0 && !treeDisplay.repaintPending()){
+			//treeDisplay.repaint();  // need to do it this way as XOR mode no good
+			treeDisplay.getTreeDrawing().unhighlightBranch(treeDisplay.getTree(), wasHighlighted, g);
+			//treeDisplay.getTreeDrawing().fillBranchInverted(t, N, g);
+		}
+		showTreeAnnotation();
+		//setAnnotation("", null);
+		//treeAnnotationShown = false; //so that the base Explanation can know whether to refer to the annotation
+	}
+	/*_________________________________________________*/
+	public   void UnhighlightBranch(Graphics g, MesquiteInteger highlight) {
+		if (windowModule.getUseXORForBranchMoves())
+			RevertBranchOld(g, highlight);
+		else
+			UnhighlightBranchNew(g,highlight);
+	}
+	/*_________________________________________________*/
+	public void ScanFlash(Graphics g, int x, int y, int modifiers) {
+		if (treeDisplay == null || tree == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return;
+		if (treeDisplay.getInvalid())
+			return;
+		MesquiteDouble fraction = new MesquiteDouble();
+		int branchFound =findBranch(x, y, fraction);
+
+		/*
+  		if (fraction.isCombinable())
+			if (treeDisplay.getTreeDrawing().isAtNode(fraction))
+				System.out.println("in node " + branchFound + ", fraction: " + fraction.getValue());
+			else 
+				System.out.println("  " + fraction.getValue() + "   " + branchFound);
+		 */
+		if (highlightedBranch.getValue() != 0) {  // we are already in a branch
+			int wasHighlighted = highlightedBranch.getValue();
+			if (branchFound==0) {
+				UnhighlightBranch(g, highlightedBranch);
+				notifyExtrasOfBranchExit(g, wasHighlighted);
+
+				setTreeName(tree);  
+				setExplanation(baseExplanation, false);
+			}
+			else if (branchFound!=highlightedBranch.getValue())  {
+				UnhighlightBranch(g, highlightedBranch); 
+				HighlightBranch(g, branchFound, highlightedBranch);
+				notifyExtrasOfBranchExit(g, wasHighlighted);
+				notifyExtrasOfBranchEnter(g, branchFound);
+			}
+		}
+		else if (branchFound!=0) {   // we weren't in a branch, but now we found one
+			HighlightBranch(g, branchFound, highlightedBranch); 
+			notifyExtrasOfBranchEnter(g, branchFound);
+			if (tree.nodeIsTerminal(branchFound)) {
+				Taxon t = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(branchFound));
+				if (t!=null)
+					setExplanation("Taxon: " + t.getName());  
+				else
+					setExplanation("Unknown taxon (the tree description may have been malformed or with undefined taxa)");
+			}
+			else {
+				Taxon t1 = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(tree.leftmostTerminalOfNode(branchFound)));
+				Taxon t2 = tree.getTaxa().getTaxon(tree.taxonNumberOfNode(tree.rightmostTerminalOfNode(branchFound)));
+				String n1, n2;
+				if (t1 == null)
+					n1 = "Unknown taxon";
+				else
+					n1 = t1.getName();
+				if (t2 == null)
+					n2 = "Unknown taxon";
+				else
+					n2 = t2.getName();
+				setExplanation(" " + tree.numberOfTerminalsInClade(branchFound) + " taxa in clade (" + n1 + " to " + n2 + ").  Node is number " + branchFound + ". ");  
+			}
+		}
+		else {
+			int nameFound = findTaxon(x, y);
+			if (highlightedTaxon >= 0) {
+				if (nameFound==-1) {
+					int wasHighlighted = highlightedTaxon;
+					RevertTaxon(g, highlightedTaxon);
+					notifyExtrasOfTaxonExit(g, wasHighlighted);
+					setExplanation(baseExplanation, false);
+				}
+				else if (nameFound!=highlightedTaxon)  {
+					int wasHighlighted = highlightedTaxon;
+					RevertTaxon(g, highlightedTaxon); 
+					InvertTaxon(g, nameFound);
+					notifyExtrasOfTaxonExit(g, wasHighlighted);
+					notifyExtrasOfTaxonEnter(g, nameFound);
+					setExplanation(" Taxon: " + taxa.getTaxonName(nameFound));
+				}
+			}
+			else if (nameFound!=-1) {
+				InvertTaxon(g, nameFound); 
+				notifyExtrasOfTaxonEnter(g, nameFound);
+				setExplanation(" Taxon: " + taxa.getTaxonName(nameFound));
+			}
+			else {
+				currentTreeTool.moved(x,y,tree,modifiers);
+				notifyExtrasOfCursorMove(g, x, y);
+				//notify extras?
+			}
+		}
+
+	}
+
+	/*_________________________________________________*/
+	public void drawBranchTouchSpot(Graphics g, int x, int y) {
+		int spotSize=8;
+		Color oldColor = g.getColor();
+		g.setColor(Color.yellow);
+		GraphicsUtil.fillOval(g,x-spotSize/2, y-spotSize/2, spotSize, spotSize,false);
+		g.setColor(Color.black);
+		GraphicsUtil.drawOval(g,x-spotSize/2, y-spotSize/2, spotSize, spotSize);
+		g.setColor(oldColor);
+	}
+
+	/*_________________________________________________*/
+	public   boolean ScanTouch(Graphics g, int x, int y, int modifiers) {
+		if (treeDisplay == null || tree == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return false;
+		if (treeDisplay.getInvalid())
+			return false;
+		xFrom = -1;
+		yFrom = -1;
+		xTo = -1;
+		yTo = -1;
+		fieldTouchX = -1;
+		fieldTouchY = -1;
+		lastFieldDragX = -1;
+		lastFieldDragY = -1;
+		taxonTouched = -1;
+		MesquiteDouble fraction = new MesquiteDouble();
+		int branchFound =findBranch(x, y, fraction);
+		if (branchFound!=0) {  // in a branch
+			branchFrom=branchFound;
+			if (currentTreeTool.informTransfer()) {  
+				//branchFrom=branchFound;
+				xFrom=x;
+				yFrom= y;
+				xTo=x;
+				yTo= y;
+				if (GraphicsUtil.useXORMode(g, true)){
+					if (windowModule.getUseXORForBranchMoves()){
+						GraphicsUtil.drawXORLine(g, xFrom,yFrom,xTo,yTo, scanLineThickness, Color.lightGray);
+					} else
+						drawBranchTouchSpot(g,xFrom,yFrom);
+				}
+			}
+			else {
+				if (highlightedBranch.getValue() != 0) {
+					notifyExtrasOfBranchExit(g, highlightedBranch.getValue());
+					UnhighlightBranch(g, highlightedBranch);
+				}
+				currentTreeTool.branchTouched(branchFound, x, y, tree, modifiers);
+				//branchFrom = 0;
+			}
+			notifyExtrasOfBranchTouch(g, branchFound);
+			return true;
+		}
+		else {  // not in a branch
+			int nameFound = findTaxon(x,y);
+			if (nameFound!=-1) {  // it is in a taxon
+				currentTreeTool.taxonTouched(nameFound, tree, modifiers);
+				taxonTouched = nameFound;
+				notifyExtrasOfTaxonTouch(g, nameFound);
+				if (highlightedTaxon >= 0 )
+					RevertTaxon(g, highlightedTaxon);
+				return true;
+			}
+			else {  //not in a taxon
+				if (currentTreeTool.isArrowTool()){
+					fieldTouchX = x;
+					fieldTouchY = y;
+					lastFieldDragX = x;
+					lastFieldDragY = y;
+					if (!windowModule.getUseXORForBranchMoves()){
+						GraphicsUtil.drawCross(g,fieldTouchX, fieldTouchY, 10);
+						treeDisplay.setCrossDrawn(true);
+					}
+				}
+
+				boolean fieldTouchAccepted = currentTreeTool.fieldTouched(x,y,tree,modifiers);
+				//notify extras?
+				return fieldTouchAccepted;
+			}
+		}
+		//return false;
+	}
+	/*_________________________________________________*/
+	public   void ScanDrop(Graphics g, int x, int y, int modifiers) {
+		if (treeDisplay == null || tree == null || treeDisplay.getTreeDrawing()==null)
+			return;
+		if (treeDisplay.getInvalid())
+			return;
+		if (currentTreeTool.isArrowTool() && fieldTouchX >= 0 && fieldTouchY >=0){
+			g.setColor(Color.blue);
+			if (GraphicsUtil.useXORMode(g, false) && windowModule.getUseXORForBranchMoves()){
+				g.setXORMode(Color.white); //for some reason color doesn't matter in MacOS, but does in Win95
+				GraphicsUtil.drawRect(g, fieldTouchX,fieldTouchY,lastFieldDragX-fieldTouchX,lastFieldDragY-fieldTouchY);
+			}
+			highlightedNodes = null;
+			highlightedTaxa = null;
+
+			if (!dragSelect(modifiers, fieldTouchX, fieldTouchY, x-fieldTouchX,y-fieldTouchY)){
+				if (taxa.anySelected()){
+					taxa.deselectAll();
+					taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+				if (tree.anySelected()){
+					tree.deselectAll();
+					tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+				if (Math.abs(x-fieldTouchX)< 4 && Math.abs(y-fieldTouchY)< 4)
+					notifyExtrasOfFieldTouch(g, x, y, modifiers);
+
+			}
+
+			fieldTouchX = -1;
+			fieldTouchY = -1;
+
+			lastFieldDragX = -1;
+			lastFieldDragY = -1;
+			if (treeDisplay.isCrossDrawn())
+				treeDisplay.update(g);
+			return;
+		}
+		if ((!treeDisplay.getTree().isLocked()) &&  (branchFrom!=0)) {
+			MesquiteDouble fraction = new MesquiteDouble();
+			if (currentTreeTool.informTransfer()) {
+				int branchTo=findBranch(x, y, fraction);
+				if (branchTo != 0 && !windowModule.getUseXORForBranchMoves()) {
+					GraphicsUtil.drawArrow((Graphics2D)g,xFrom,yFrom,xTo,yTo,2); //only if drawn
+					drawBranchTouchSpot(g,xFrom,yFrom);
+					MesquiteThread.pauseForSeconds(0.5);
+				}
+
+			}
+			if (highlightedBranch.getValue() != 0) {
+				notifyExtrasOfBranchExit(g, highlightedBranch.getValue());
+				UnhighlightBranch(g, highlightedBranch);
+			}
+			else if (highlightedTaxon >=0)
+				RevertTaxon(g, highlightedTaxon);
+			g.setColor(Color.black); 
+			if (GraphicsUtil.useXORMode(g, false) && windowModule.getUseXORForBranchMoves()){
+				GraphicsUtil.drawXORLine(g, xFrom,yFrom,xTo,yTo, scanLineThickness, Color.lightGray);
+			}
+
+			if (currentTreeTool.informTransfer()) {
+				int branchTo=findBranch(x, y, fraction);
+				if (branchTo != 0) {
+					if (branchTo == branchFrom && currentTreeTool.isArrowTool()){
+						selectBranch(modifiers, branchTo);
+					}
+					else {
+						currentTreeTool.branchTransferred(branchFrom, branchTo, tree, modifiers);
+					}
+				}
+			}
+			else if (currentTreeTool.informDrop()) {
+				//g.drawLine(xFrom,yFrom,xTo,yTo); //only if drawn  
+				currentTreeTool.branchDropped(branchFrom, x, y, tree, modifiers);
+			}
+			branchFrom = 0;
+		}
+		else {
+			int nameFound = findTaxon(x,y);
+			if (nameFound!=-1) {
+				if (taxonTouched == nameFound && currentTreeTool.isArrowTool())
+					selectTaxon(modifiers, taxonTouched);
+				currentTreeTool.taxonMouseUp(nameFound,x,y,tree, modifiers);
+				notifyExtrasOfTaxonTouch(g, nameFound);
+				if (highlightedTaxon >= 0 )
+					RevertTaxon(g, highlightedTaxon);
+				taxonTouched = -1;
+				return;
+			}
+			else currentTreeTool.fieldMouseUp(x,y,tree,modifiers);
+			//notify extras?
+		}
+		taxonTouched = -1;
+	}
+	/*_________________________________________________*/
+	public   void ScanDrag(Graphics g, int x, int y, int modifiers) {
+		if (treeDisplay == null || tree == null)
+			return;
+		if (treeDisplay.getInvalid())
+			return;
+		if (currentTreeTool.isArrowTool() && fieldTouchX >= 0 && fieldTouchY >=0){
+			g.setColor(Color.blue);
+			if (GraphicsUtil.useXORMode(g, false) && windowModule.getUseXORForBranchMoves()){
+				g.setXORMode(Color.white); //for some reason color doesn't matter in MacOS, but does in Win95
+				GraphicsUtil.drawRect(g, fieldTouchX,fieldTouchY,lastFieldDragX-fieldTouchX,lastFieldDragY-fieldTouchY);
+				GraphicsUtil.drawRect(g, fieldTouchX,fieldTouchY,x-fieldTouchX,y-fieldTouchY);
+				//			g.drawRect(fieldTouchX,fieldTouchY,lastFieldDragX-fieldTouchX,lastFieldDragY-fieldTouchY);
+				//			g.drawRect(fieldTouchX,fieldTouchY,x-fieldTouchX,y-fieldTouchY);
+			} else
+				dragHighlight(g,modifiers, fieldTouchX,fieldTouchY,x-fieldTouchX,y-fieldTouchY);
+			lastFieldDragX = x;
+			lastFieldDragY = y;
+			return;
+		}
+		MesquiteDouble fraction = new MesquiteDouble();
+		int branchFound =findBranch(x, y, fraction);
+		if (branchFound > 0) {
+			if (branchFound != dropHighlightedBranch.getValue()) {
+				UnhighlightBranch(g, dropHighlightedBranch);
+				HighlightBranch(g, branchFound, dropHighlightedBranch);
+			}
+		}
+		else if (dropHighlightedBranch.getValue()>0)
+			UnhighlightBranch(g, dropHighlightedBranch);
+
+		if (branchFrom!=0) {
+			if (currentTreeTool.informTransfer()) {
+				g.setColor(Color.black);
+				if (GraphicsUtil.useXORMode(g, false) && windowModule.getUseXORForBranchMoves()){
+					GraphicsUtil.drawXORLine(g, xFrom,yFrom,xTo,yTo, scanLineThickness, Color.lightGray);
+				}
+				xTo=x;
+				yTo= y;
+				if (GraphicsUtil.useXORMode(g, false) && windowModule.getUseXORForBranchMoves())
+					GraphicsUtil.drawXORLine(g, xFrom,yFrom,xTo,yTo, scanLineThickness, Color.lightGray);
+			}
+			else if (currentTreeTool.informDrag()) {
+				currentTreeTool.branchDragged(branchFrom, x, y, tree, modifiers);
+			}
+		}
+	}
+	public void findContained(Tree tree, int N, int x, int y, int w, int h, Vector nodes, Vector taxons) {
+		TreeDrawing drawing = treeDisplay.getTreeDrawing();
+		int dX = drawing.x[N];
+		int dY = drawing.y[N];
+
+		if (dX >= x && dX <= x+w && dY>=y && dY <= y+h)
+			nodes.addElement(new MesquiteInteger(N));
+
+		if (tree.nodeIsTerminal(N) && drawing.namePolys != null){
+			Polygon term = drawing.namePolys[tree.taxonNumberOfNode(N)];
+			if (term != null && term.intersects(x, y, w, h))
+				taxons.addElement(new MesquiteInteger(tree.taxonNumberOfNode(N)));
+		}
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			findContained(tree, d, x, y, w, h, nodes, taxons);
+		}
+
+	}
+	public boolean shrinkWrapNodes(MesquiteTree tree, int N, boolean selBelow) {
+		int pathsSelAbove = 0;
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			boolean selAbove = shrinkWrapNodes(tree, d, selBelow || tree.getSelected(N));
+			if (selAbove)
+				pathsSelAbove++;
+		}
+		if (pathsSelAbove>1 || tree.getSelected(N))
+			tree.selectAllInClade(N);
+		return pathsSelAbove>0 || tree.getSelected(N);
+	}
+	/*-----------------------------------------*/
+	/** SelectsAllNodes in the clade */
+	public void selectAllTaxaInClade(Tree tree, int node) {
+		if (tree.nodeIsTerminal(node))
+			taxa.setSelected(tree.taxonNumberOfNode(node), true);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			selectAllTaxaInClade(tree, d);
+		}
+	}
+	public boolean shrinkWrapTaxa(MesquiteTree tree, int N) {
+		int pathsSelAbove = 0;
+		boolean thisIsSelected = tree.nodeIsTerminal(N) && tree.getTaxa().getSelected(tree.taxonNumberOfNode(N));
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			boolean selAbove = shrinkWrapTaxa(tree, d);
+			if (selAbove)
+				pathsSelAbove++;
+		}
+		if (pathsSelAbove>1)
+			selectAllTaxaInClade(tree, N);
+		return pathsSelAbove>0 || thisIsSelected;
+	}
+
+	/*-----------------------------------------*/
+	Vector highlightedNodes = new Vector();
+	Vector highlightedTaxa = new Vector();
+
+	private Vector vectorElementsInFirstButNotSecond(Vector firstVector, Vector secondVector){
+		if (secondVector==null)
+			return firstVector;
+		if (firstVector==null)
+			return null;
+		Vector vector = new Vector();
+		for (int i=0; i<firstVector.size(); i++){
+			boolean found=false;
+			for (int j=0; j<secondVector.size() && !found; j++){
+				if (((MesquiteInteger) firstVector.elementAt(i)).getValue()==((MesquiteInteger) secondVector.elementAt(j)).getValue()){
+					found=true;
+				}
+			}
+			if (!found)
+				vector.add(firstVector.elementAt(i));
+		}
+		return vector;
+	}
+	private void dragHighlight(Graphics g, int modifiers, int x, int y, int w, int h){
+		Vector nodes = new Vector();
+		Vector taxons = new Vector();
+
+		if (w < 0){
+			int nx = x + w;
+			x = nx;
+			w = -w;
+		}
+		if (h < 0){
+			int ny = y + h;
+			y = ny;
+			h = -h;
+		}
+		findContained(tree, tree.getRoot(), x, y, w, h, nodes, taxons);
+
+		Vector nodesToUnselect= vectorElementsInFirstButNotSecond(highlightedNodes, nodes);
+		Vector taxaToUnselect= vectorElementsInFirstButNotSecond(highlightedTaxa, taxons);
+
+		Vector nodesToSelect= null;
+		Vector taxaToSelect= null;
+
+		if ((nodesToUnselect!=null && nodesToUnselect.size()>0) || (taxaToUnselect!=null && taxaToUnselect.size()>0)){
+			treeDisplay.update(g);
+			if (!windowModule.getUseXORForBranchMoves()){
+				GraphicsUtil.drawCross(g,fieldTouchX, fieldTouchY, 10);
+				treeDisplay.setCrossDrawn(true);
+			}
+			nodesToSelect= nodes;
+			taxaToSelect= taxons;
+		} else {
+			nodesToSelect= vectorElementsInFirstButNotSecond(nodes, highlightedNodes);
+			taxaToSelect= vectorElementsInFirstButNotSecond(taxons, highlightedTaxa);
+		}
+		if (nodesToSelect.size()>0){
+			for (int i=0; i<nodesToSelect.size(); i++){
+				MesquiteInteger mi = (MesquiteInteger) nodesToSelect.elementAt(i);
+				HighlightBranch(g, mi.getValue(), highlightedBranch, false);
+			}
+		}
+		if (taxaToSelect.size()>0){
+			for (int i=0; i<taxaToSelect.size(); i++){
+				MesquiteInteger mi = (MesquiteInteger) taxaToSelect.elementAt(i);
+				try{
+					treeDisplay.fillTaxon(g, mi.getValue());  
+				}
+				catch (InternalError e){ //workaround to bug in Windows Java 1.7_45
+				}
+			}
+		}
+		highlightedNodes = new Vector(nodes);
+		highlightedTaxa = new Vector(taxons);
+	}
+	/*-----------------------------------------*/
+
+	private boolean dragSelect(int modifiers, int x, int y, int w, int h){
+		Vector nodes = new Vector();
+		Vector taxons = new Vector();
+		if (w < 0){
+			int nx = x + w;
+			x = nx;
+			w = -w;
+		}
+		if (h < 0){
+			int ny = y + h;
+			y = ny;
+			h = -h;
+		}
+		boolean selectionChanged = false;
+		boolean shiftDown = MesquiteEvent.shiftKeyDown(modifiers);
+		boolean commandDown = MesquiteEvent.commandOrControlKeyDown(modifiers);
+		findContained(tree, tree.getRoot(), x, y, w, h, nodes, taxons);
+		if (nodes.size()>0){
+			if (!shiftDown && !commandDown)
+				tree.deselectAll();
+			for (int i=0; i<nodes.size(); i++){
+				MesquiteInteger mi = (MesquiteInteger) nodes.elementAt(i);
+				if (commandDown)
+					tree.setSelected(mi.getValue(), !tree.getSelected(mi.getValue()));
+				else
+					tree.setSelected(mi.getValue(), true);
+			}
+			if (shiftDown)
+				shrinkWrapNodes(tree, tree.getRoot(), false);
+			tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			selectionChanged = true;
+		}
+		if (taxons.size()>0){
+			if (!shiftDown && !commandDown)
+				taxa.deselectAll();
+			for (int i=0; i<taxons.size(); i++){
+				MesquiteInteger mi = (MesquiteInteger) taxons.elementAt(i);
+				if (commandDown)
+					taxa.setSelected(mi.getValue(), !taxa.getSelected(mi.getValue()));
+				else
+					taxa.setSelected(mi.getValue(), true);
+			}
+			if (shiftDown)
+				shrinkWrapTaxa(tree, tree.getRoot());
+			taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+			selectionChanged = true;
+		}
+		return selectionChanged;
+	}
+	private void selectBranch(int modifiers, int node){
+		boolean shiftDown = MesquiteEvent.shiftKeyDown(modifiers);
+		boolean commandDown = MesquiteEvent.commandOrControlKeyDown(modifiers);
+		if (!shiftDown && !commandDown)
+			tree.deselectAll();
+		if (commandDown)
+			tree.setSelected(node, !tree.getSelected(node));
+		else
+			tree.setSelected(node, true);
+		if (shiftDown)
+			shrinkWrapNodes(tree, tree.getRoot(), false);
+		tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	}
+
+	private void selectTaxon(int modifiers, int taxon){
+		boolean shiftDown = MesquiteEvent.shiftKeyDown(modifiers);
+		boolean commandDown = MesquiteEvent.commandOrControlKeyDown(modifiers);
+		if (!shiftDown && !commandDown)
+			taxa.deselectAll();
+		if (commandDown)
+			taxa.setSelected(taxon, !taxa.getSelected(taxon));
+		else
+			taxa.setSelected(taxon, true);
+		if (shiftDown)
+			shrinkWrapTaxa(tree, tree.getRoot());
+		taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+	}
+
+	/*................................................................................................*/
+	public void notifyExtrasOfCursorMove(Graphics g, int x, int y) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorMove(tree, x, y, g);
+				}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfTaxonEnter(Graphics g, int M) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorEnterTaxon(tree, M, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.taxonEnter(M);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfTaxonExit(Graphics g, int M) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorExitTaxon(tree, M, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.taxonExit(M);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfTaxonTouch(Graphics g, int M) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorTouchTaxon(tree, M, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.taxonTouch(M);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchEnter(Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorEnterBranch(tree, N, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.branchEnter(N);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchExit(Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorExitBranch(tree, N, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.branchExit(N);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchTouch(Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorTouchBranch(tree, N, g);
+				}
+			}
+		}
+		if(treeInfoPanel != null && infoPanelOn.getValue())
+			treeInfoPanel.branchTouch(N);
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfFieldTouch(Graphics g, int x, int y, int modifiers) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorTouchField(tree, g, x, y, modifiers);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	private void treeChanged( boolean notifyContextListeners){ 
+		if (tree == null || previousTree == null || undoTree == null)
+			return;
+
+		if (tree.upToDateWithTaxa() && previousTree.upToDateWithTaxa()){
+			canUndo = true;
+		}
+		undoTree.setToClone(previousTree);
+
+		undoTree.setName("Untitled Tree");
+
+		previousTree.setToClone(tree);
+		if (tree!=oldTree) {
+			treeVersion = tree.getVersionNumber();
+			oldTree=tree;
+		}
+		else if (treeVersion!=tree.getVersionNumber()){
+			treeEdited(false);
+		}
+		if (treeDisplay!=null) {
+			treeDisplay.setTree(tree); 
+
+			treeDisplay.getTreeDrawing().setDrawnRoot(tree.getRoot());
+			//rooted.setValue(tree.getRooted());
+			setTreeName(tree);
+			setExplanation(baseExplanation, false);
+		}
+		else ownerModule.alert("Tree display null in treeChanged");
+		if (treeInfoPanel != null)
+			treeInfoPanel.setTree(tree);
+		if (notifyContextListeners && windowModule.contextListeners !=null) {
+			Enumeration e = windowModule.contextListeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeContextListener) {
+					TreeContextListener tce = (TreeContextListener)obj;
+					tce.treeChanged(tree);
+				}
+			}
+		}
+		if (treeDisplay!=null) {
+			treeDisplay.setTreeAllExtras(tree);
+			treeDisplay.pleaseUpdate(true);
+			if (getMode()>0)
+				updateTextPage();
+		}
+
+		Enumeration em = ownerModule.getEmployeeVector().elements();
+		while (em.hasMoreElements()) {
+			Object obj = em.nextElement();
+			MesquiteModule mb = (MesquiteModule)obj;
+			if (mb instanceof TreeWindowAssistant) {
+				((TreeWindowAssistant)mb).setTree(tree);  
+			}
+		}
+		storeTreeMenuItem.setEnabled(!treeSourceLocked());
+		MesquiteTrunk.resetMenuItemEnabling();
+		showTreeAnnotation();
+		sizeDisplay();
+		contentsChanged();
+	}
+	/*.................................................................................................................*/
+	void showTreeAnnotation(){
+		Tree t = annotatableTree();
+		if (t!=null) {
+			setDefaultAnnotatable((Annotatable)t); 
+			setAnnotation((Annotatable)t); 
+			treeAnnotationShown = true; //so that the base Explanation can refer to the annotation
+			resetCursor();
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa &&  (Taxa)obj ==taxa) {
+			ownerModule.iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof Taxa &&  (Taxa)obj ==taxa) {
+			if (code==MesquiteListener.PARTS_CHANGED || code ==MesquiteListener.PARTS_ADDED || code == MesquiteListener.PARTS_MOVED || code == MesquiteListener.PARTS_DELETED) {
+				canUndo = false;
+			}
+			else if (code==MesquiteListener.NAMES_CHANGED || code == MesquiteListener.SELECTION_CHANGED) 
+				treeDisplay.pleaseUpdate(true);
+			if (getMode()>0)
+				updateTextPage();
+		}
+		else if (obj instanceof Tree && (Tree)obj == tree){ // && code!=MesquiteListener.ANNOTATION_CHANGED){
+			treeEdited(true);
+			treeChanged( code!=MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED); 
+		}
+		/*
+		else if (obj instanceof Tree && (Tree)obj == tree && code==MesquiteListener.ANNOTATION_CHANGED){
+    	 		treeEdited();
+			setTreeName();
+			setExplanation(baseExplanation, true);
+			if (getMode()>0)
+				updateTextPage();
+		}
+		 */
+		/*else if (obj == currentTreeFootnote){
+			//footnoteToTreeAnnotation();
+		}*/
+		super.changed(caller, obj, notification);
+	}
+
+	/*.................................................................................................................*/
+
+	void resetBaseExplanation(){
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		String td = "";
+		String td2 = "";
+		if (tree!=null) {
+			if (treeAnnotationShown && !StringUtil.blank(tree.getAnnotation()))
+				td = "Footnote above refers to the current tree. \nTree has " +tree.numberOfTerminalsInClade(tree.getRoot()) + " terminal taxa.";
+			else
+				td = "The current tree has " +tree.numberOfTerminalsInClade(tree.getRoot()) + " terminal taxa.";
+
+			if (tree.hasPolytomies(tree.getRoot())){
+				if (tree.getPolytomiesAssumption() ==0)
+					td += " Polytomies in this tree are assumed hard.";
+				else if (tree.getPolytomiesAssumption() ==1)
+					td += " Polytomies in this tree are assumed soft.";
+			}
+			if (!tree.getRooted())
+				td += " This tree is unrooted.";
+			if (tree.anySelectedInClade(tree.getRoot()))
+				td += " " + tree.numberSelectedInClade(tree.getRoot()) + " branch(es) selected.";
+			td += "\n";
+		}
+		if (ownerModule.getProject().getNumberTaxas()>1 && tree != null)
+			td += "Tree window shows trees for taxa \"" + tree.getTaxa().getName() + "\"\n";
+		if (treeEdited)
+			baseExplanation.setValue(td + "Editing Mode.  " + td2 + "When in browsing mode, the trees shown are from " + treeSourceTask.getName() + " [" + treeSourceTask.getParameters() + "]");
+		else
+			baseExplanation.setValue(td + "Browsing Mode.  " + td2 + "The trees shown are from " + treeSourceTask.getName() + " [" + treeSourceTask.getParameters() + "]");
+		setExplanation(baseExplanation, true);
+	}
+	/*.................................................................................................................*/
+	public void setExplanation(String exp){
+		baseExplanationUsed = false;
+		super.setExplanation(exp);
+	}
+	/*.................................................................................................................*/
+	void setExplanation(MesquiteString exp, boolean setEvenIfAlreadyBase){
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		if (exp == null)
+			return;
+		if (exp != baseExplanation || !(baseExplanationUsed && !setEvenIfAlreadyBase)) {
+			baseExplanationUsed = true;
+			super.setExplanation(exp.toString());
+		}
+	}
+	/*.................................................................................................................*/
+	private Tree annotatableTree(){
+		Tree t;
+		if (treeEdited) {
+			t = tree;
+			if (t !=null && t instanceof Annotatable && (t != originalTree || treeSourceTask.nameMatches("StoredTrees")))
+				return t;
+		}
+		else {
+			t = originalTree;
+			if (t !=null && t instanceof Annotatable && treeSourceTask.nameMatches("StoredTrees"))
+				return t;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	private void hookCurrentTree(){
+		tree.addListener(this);
+		tree.getTaxa().addListenerHighPriority(tree); //just in case tree isn't part of TreeVector that will notify it; added 14 Feb 02
+		showTreeAnnotation();
+	}
+	/*.................................................................................................................*/
+	private void unhookPreviousTree(){
+		tree.removeListener(this);
+		tree.getTaxa().removeListener(tree); //just in case tree isn't part of TreeVector that will notify it; added 14 Feb 02
+	}
+
+	String getTreeNameAndDetails(){
+		return messagePanel.getFullMessage();
+	}
+	/*.................................................................................................................*/
+	public void setTreeName(Tree t){
+		String treename;
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		if (treeEdited && treeSourceLocked()) {
+			if (t!=null) {
+				treename= tree.getName();
+			}
+			else
+				treename = "Untitled Tree";
+		}
+		else if (usingDefaultTree)
+			treename = "DEFAULT TREE SHOWN BECAUSE TREE SOURCE NOT SUPPLYING TREE";
+		else {
+			if (t != null && t.hasName())
+				treename = t.getName();
+			else
+				treename = treeSourceTask.getTreeNameString(taxa, MesquiteTree.toInternal(palette.paletteScroll.getCurrentValue())); 
+		}
+		messagePanel.setMessage(treename);  
+		if (treeInfoPanel != null)
+			treeInfoPanel.setTreeAndSourceName(treename, treeSourceTask.getName());
+
+	}
+	/*.................................................................................................................*/
+	public Tree setTree(String TreeDescription){
+		return setTree(TreeDescription, null);
+	}
+	/*.................................................................................................................*/
+	Tree setTree(String TreeDescription, String name){
+		if (ownerModule == null || ownerModule.isDoomed())
+			return null;
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return null;
+		}
+		if (treeDisplay!=null) {
+			if (taxa == null){
+				Tree displayTree =treeDisplay.getTree();
+				if (displayTree== null)
+					displayTree = tree;
+				if (displayTree == null)
+					return null;
+				Taxa newTaxa = displayTree.getTaxa();
+				taxa = newTaxa;
+			}
+			if (taxa == null)
+				return null;
+			MesquiteTree t = new MesquiteTree(taxa);
+			if (!t.readTree(TreeDescription)) {
+				ownerModule.discreetAlert( "That tree description is invalid (" + TreeDescription + ")");
+				return null;
+			}	
+			//t.warnRetIfNeeded();
+			if (tree !=null) {
+				unhookPreviousTree();
+			}
+
+			treeDisplay.setTree(t);
+			if (tree !=null)
+				tree.dispose();
+			tree = t;
+			if (name == null)
+				name = "Untitled Tree";
+			tree.setName(name);
+			treeEdited = true;
+			zapPreviousEdited(true);
+			hookCurrentTree();
+			treeChanged( true);
+			palette.paletteScroll.setEnableEnter(true);
+			return tree;
+		}
+		return null;
+	}
+	void forceRenameTree(String n){
+		if (ownerModule == null || ownerModule.isDoomed())
+			return;
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return;
+		}
+		tree.setName(n);
+		setTreeName(tree);
+		}
+	/*.................................................................................................................*/
+	Tree setCloneOfTree(Tree treeToClone, boolean resetOriginal, MesquiteBoolean editStatusToSet){  // displays copy for editing
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return null;
+		}
+		usingDefaultTree = false;
+		originalTree = null;
+		if (treeDisplay!=null) {
+			if (treeToClone == null) {
+				if (!treeEdited){
+					if (tree !=null) {
+						unhookPreviousTree();
+						tree.dispose();
+					}
+					if (windowModule.editMode)
+						treeToClone = taxa.getDefaultDichotomousTree(null);
+					else 
+						treeToClone = taxa.getDefaultTree();
+					usingDefaultTree = true;
+					resetOriginal = true;
+					ownerModule.discreetAlert(MesquiteThread.isScripting() || warningGivenForTreeSource,"Tree source \"" +treeSourceTask.getName() +  "\" is not supplying a tree; a default tree may be shown in Tree Window (b).");
+					if (!MesquiteThread.isScripting())
+						warningGivenForTreeSource = true;
+					editStatusToSet.setValue(false);
+				}
+				else {
+					treeToClone = tree;
+					resetOriginal = true;
+					editStatusToSet.setValue(true);
+				}
+			}
+			else
+				editStatusToSet.setValue(false);
+
+
+			if (treeToClone != null)  {
+				if (tree !=null) {
+					unhookPreviousTree();
+					tree.dispose();
+				}
+				if (resetOriginal){ // && !treeEdited){
+					if (originalTree != null && originalTree instanceof MesquiteTree)
+						taxa.removeListener((MesquiteTree)originalTree);
+					this.originalTree = treeToClone;  //otree
+					if (originalTree != null && originalTree instanceof MesquiteTree)
+						taxa.addListener((MesquiteTree)originalTree);
+				}
+				tree = treeToClone.cloneTree();
+			}
+			hookCurrentTree();
+			treeChanged( true);
+			return tree;
+		}
+		else if (ownerModule != null)
+			ownerModule.alert("Tree display null in setCloneOfTree");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Tree setTree(MesquiteTree originalTree){  // displays tree; only used in resetForTreeSource for editedTree
+		if (taxa !=null && taxa.isDoomed()) {
+			ownerModule.iQuit();
+			return null;
+		}
+		if (treeDisplay!=null) {
+			if (tree !=null) {
+				unhookPreviousTree();
+				tree.dispose();
+			}
+			if (originalTree == null) {
+				if (windowModule.editMode)
+					tree = taxa.getDefaultDichotomousTree(null);
+				else 
+					tree = taxa.getDefaultTree();
+				usingDefaultTree = true;
+				ownerModule.discreetAlert(MesquiteThread.isScripting() || warningGivenForTreeSource,"Tree source \"" +treeSourceTask.getName() +  "\" is not supplying a tree; a default tree may be shown in Tree Window (a).");
+				if (!MesquiteThread.isScripting())
+					warningGivenForTreeSource = true;
+			}
+			else  {
+				usingDefaultTree = false;
+				tree = originalTree;
+			}
+			hookCurrentTree();
+			treeChanged( true);
+			return tree;
+		}
+		else ownerModule.alert("Tree display null in showTree");
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void windowResized(){
+		super.windowResized();
+		if (!MesquiteThread.isScripting() || (windowModule  != null && windowModule.respondToWindowResize))
+			sizeDisplay();
+	}
+	/*.................................................................................................................*/
+	public void dispose(){
+		disposing = true;
+		waitUntilDisposable();
+
+		if (taxa != null){
+			if (originalTree != null && originalTree instanceof MesquiteTree)
+				taxa.removeListener((MesquiteTree)originalTree);
+			if (previousEditedTree != null && previousEditedTree instanceof MesquiteTree)
+				taxa.removeListener((MesquiteTree)previousEditedTree);
+			if (previousTree != null)
+				taxa.removeListener(previousTree);
+			if (undoTree != null)
+				taxa.removeListener(undoTree);
+			if (oldTree != null)
+				taxa.removeListener(oldTree);
+			if (recentEditedTrees != null){
+				taxa.removeListener(recentEditedTrees);
+			}
+		}
+
+		if (tree!=null) {
+			unhookPreviousTree();
+			tree.dispose();
+		}
+		if (taxa!=null)
+			taxa.removeListener(this);
+		if (magnifyExtra!=null)
+			magnifyExtra.dispose();
+		tree = null;
+		if (palette!=null)
+			palette.dispose();
+		windowModule = null; 
+		if (currentTreeTool!=null) {
+			currentTreeTool.dispose();
+			currentTreeTool = null;
+		}
+		treeDrawCoordTask = null;
+		treeSourceTask = null;
+		try{
+			if (treeDisplay !=null){
+				removeFromWindow(treeDisplay);
+				treeDisplay.dispose();
+			}
+			treeDisplay=null;
+			if (setTreeNumberCommand!=null)
+				setTreeNumberCommand.setOwner(null);
+			setTreeNumberCommand = null;
+			//if (rooted!=null)
+			//	rooted.releaseMenuItem();
+		}
+		catch (NullPointerException e){
+		}
+		super.dispose();
+	}
+}
+
+/* ======================================================================== */
+class REALTreeScrollPane extends ScrollPane implements AdjustmentListener { //REALTreeScrollPane
+	BasicTreeWindow window;
+	Component treeDisplay;
+	public REALTreeScrollPane (BasicTreeWindow window) {
+		super();
+		this.window = window;
+	}
+	public void addTreeDisplay(Component c){
+		addImpl(c, null, 0);
+		treeDisplay = c;
+	}
+	public void adjustmentValueChanged(AdjustmentEvent e){
+		Adjustable hScroll = getHAdjustable();
+		Adjustable vScroll = getHAdjustable();
+
+		window.setOrigin(hScroll.getValue(), vScroll.getValue(), false);
+	}
+	public boolean isFauxScrollPane(){
+		return false;
+	}
+	public void setHMinMax(int min, int max){
+		//ignore for real scrollpane
+	}
+	public void setVMinMax(int min, int max){
+		//ignore for real scrollpane
+	}
+	public Dimension getViewportSize(){
+		return new Dimension(getContentsWidth(), getContentsHeight());
+	}
+	public int getContentsWidth(){
+		return getWidth() - window.scrollWidth;
+	}
+	public int getContentsHeight(){
+		return getHeight() - window.scrollWidth;
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		//doLayout();
+		window.checkPanelPositionsLegal();
+
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		//doLayout();
+		window.checkPanelPositionsLegal();
+
+	}
+}
+/* ======================================================================== */
+/* this is an attempt to get around the bug in OS X java 1.4+ in which ScrollPane scrollbars don't return their position and don't notify of adjustments. 
+ * This faux-ScrollPane works reasonably well but is slower and has some graphical artifacts */
+
+class TreeScrollPane extends Panel{ //HANDMADETreeScrollPane
+	BasicTreeWindow window;
+	TWScroll hScroll, vScroll;
+	Panel port;
+	Component treeDisplay;
+	public TreeScrollPane (BasicTreeWindow window) {
+		super();
+		hScroll = new TWScroll(this, Scrollbar.HORIZONTAL, 0, 2, 0, 0);
+		vScroll = new TWScroll(this, Scrollbar.VERTICAL, 0, 2, 0, 0);
+		setLayout(new BorderLayout());
+		add(hScroll, BorderLayout.SOUTH);
+		add(vScroll, BorderLayout.EAST);
+		add(port = new Panel(), BorderLayout.CENTER);
+		port.setLayout(null);
+		doLayout();
+
+		this.window = window;
+	}
+	public void addTreeDisplay(Component c){
+		port.add(c);
+		treeDisplay = c;
+	}
+	public boolean isFauxScrollPane(){
+		return true;
+	}
+	public Adjustable getHAdjustable(){
+		return hScroll;
+	}
+	public Adjustable getVAdjustable(){
+		return vScroll;
+	}
+	public void setHMinMax(int min, int max){
+		if (min < 0)
+			min = 0;
+		if (max < min)
+			max = min;
+		boolean touch = hScroll.setMinimumWithResetWarning(min);
+		touch = hScroll.setMaximumWithResetWarning(max) || touch;
+		if (touch)
+			scrollTouched(null, 0);
+		hScroll.setVisible(min != max);
+
+		if(min == max)
+			treeDisplay.setLocation(0, treeDisplay.getLocation().y);
+
+	}
+	public void setVMinMax(int min, int max){
+		if (min < 0)
+			min = 0;
+		if (max < min)
+			max = min;
+		boolean touch = vScroll.setMinimumWithResetWarning(min);
+		touch = vScroll.setMaximumWithResetWarning(max) || touch;
+		if (touch)
+			scrollTouched(null, 0);
+
+		vScroll.setVisible(min != max);
+
+		if(min == max)
+			treeDisplay.setLocation(treeDisplay.getLocation().x, 0);
+	}
+
+	public void scrollTouched(TWScroll scroll, int value){
+		window.setOrigin(hScroll.getValue(), vScroll.getValue(), false);
+		constrainTreeDisplay();
+	}
+	public Dimension getViewportSize(){
+		return new Dimension(port.getWidth(), port.getHeight());
+	}
+	public int getContentsWidth(){
+		return port.getWidth();
+	}
+	public int getContentsHeight(){
+		return port.getHeight();
+	}
+	public Point getScrollPosition(){
+		return new Point(hScroll.getValue(), vScroll.getValue());
+	}
+	public void constrainTreeDisplay(){  //post 2. 6 needed at least for OS X as workaround for JVM failure to respect bounds of containing panel
+		if (treeDisplay == null)
+			return;
+		int w = port.getWidth();
+		int h = port.getHeight();
+		int wReduce =0;
+		int hReduce =0;
+
+		if (treeDisplay.getWidth()+treeDisplay.getX()!= w)
+			wReduce = treeDisplay.getWidth()+treeDisplay.getX()- w;
+		if (treeDisplay.getHeight()+treeDisplay.getY()!= h)
+			hReduce = treeDisplay.getHeight()+treeDisplay.getY()- h;
+		if (wReduce!= 0 || hReduce != 0)
+			treeDisplay.setSize(treeDisplay.getWidth() - wReduce, treeDisplay.getHeight() - hReduce);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w, h);
+		doLayout();
+		constrainTreeDisplay();
+		window.checkPanelPositionsLegal();
+
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x, y, w, h);
+		doLayout();
+		constrainTreeDisplay();
+		window.checkPanelPositionsLegal();
+
+	}
+}
+/* ======================================================================== */
+class TWScroll extends MesquiteScrollbar {
+	TreeScrollPane tsp;
+	int orientation;
+	public TWScroll (TreeScrollPane tsp, int orientation, int value, int visible, int min, int max){
+		super(orientation, value, visible, min, max);
+
+		this.orientation = orientation;
+		this.tsp=tsp;
+	}
+	public void setValue(int v){
+		super.setValue(v);
+	}
+	public boolean setMinimumWithResetWarning(int m){
+		boolean resetNeeded = false;
+		if (getValue()<m){
+			setValue(m);
+			resetNeeded = true;
+		}
+		super.setMinimum(m);
+		return resetNeeded;
+	}
+	public boolean setMaximumWithResetWarning(int m){
+		boolean resetNeeded = false;
+		if (getValue()>m){
+			setValue(m);
+			resetNeeded = true;
+		}
+		super.setMaximum(m);
+		return resetNeeded;
+	}
+	public void scrollTouched(){
+		int currentValue = getValue();
+		tsp.scrollTouched(this, currentValue);
+	}
+	public boolean processDuringAdjustment() {
+		return true;
+	}
+	public void print(Graphics g){
+	}
+}
+/* ======================================================================== *
+class LockPanel extends MousePanel {
+	Image lockClosed, lockOpen, lockImage;
+	BasicTreeWindow window;
+	int state;
+	public LockPanel(BasicTreeWindow window){
+		super();
+		this.window = window;
+		lockClosed  = MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/lockClosed.gif");
+		lockOpen  = MesquiteImage.getImage(MesquiteModule.getRootPath() + "images/lockOpen.gif");
+		setLockState(0);
+	}
+	public void setLockState(int state){
+		this.state = state;
+		if (state == 0)
+			lockImage = lockClosed;
+		else if (state ==1)
+			lockImage = lockClosed;
+		else if (state == 2)
+			lockImage = lockOpen;
+	}
+
+	public void paint(Graphics g) { //^^^
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+ 		g.drawImage(lockImage, 0, -1, this);
+ 		g.drawLine(0, getBounds().height-1, getBounds().width, getBounds().height-1);
+
+		MesquiteWindow.uncheckDoomed(this);
+ 	}
+    	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+    		window.lockTouched();
+    		repaint();
+   	}
+}
+ */
+
+/* ======================================================================== */
+class MessagePanel extends Panel {
+	String treeMessage = "";
+	String treeSourceAddendum = "";
+	BasicTreeWindowMaker ownerModule;
+	boolean showDiamond = false;
+	boolean indicateModified;
+	String modifiedString = "";
+	Polygon poly;
+	int left = 4;
+	int top = 4;
+	int s = 8;
+	public MessagePanel(BasicTreeWindowMaker ownerModule) {  //in future pass general MesquiteWindow
+		super();
+		treeMessage="";
+		poly = new Polygon();
+		poly.xpoints = new int[4];
+		poly.ypoints = new int[4];
+		poly.npoints=0;
+		poly.addPoint(left, top+s/2);
+		poly.addPoint(left + s/2, top);
+		poly.addPoint(left + s, top+s/2);
+		poly.addPoint(left + s/2, top+s);
+		poly.npoints=4;
+		this.ownerModule = ownerModule;
+		setBackground(ColorTheme.getInterfaceElement());
+
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawRect(0,0, getBounds().width -1, getBounds().height-1);
+		if (showDiamond){
+			g.fillPolygon(poly);
+			if (treeMessage != null)
+				g.drawString(modifiedString + treeMessage + treeSourceAddendum,  left + s + 4, 12);
+		}
+		else if (treeMessage != null)
+			g.drawString(modifiedString + treeMessage + treeSourceAddendum,  4, 12);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setMessage(String s) {
+		treeMessage = s;
+		repaint();
+	}
+	public String getFullMessage() {
+		return modifiedString + treeMessage + treeSourceAddendum;
+	}
+
+	void setHighlighted(boolean edited) {
+		this.showDiamond = edited;
+		if (edited){
+			if (!MesquiteThread.isScripting())
+				modifiedString ="Edited, based on ";
+			else
+				modifiedString ="Modified, based on ";
+		}
+		else
+			modifiedString = "";
+		if (edited)
+			setBackground(ColorDistribution.lightGreen);
+		else
+			setBackground(ColorTheme.getInterfaceElement());
+			
+		if (treeMessage != null)
+			ownerModule.magnifyExtra.name = modifiedString + treeMessage;
+		else
+			ownerModule.magnifyExtra.name = null;
+		if (ownerModule.treeSourceTask != null && !edited){
+			String s = ownerModule.treeSourceTask.getNameAndParameters();
+			if (!StringUtil.blank(s))
+				treeSourceAddendum =  "   [" + s + "]";
+		}
+		else
+			treeSourceAddendum = "";
+		repaint();
+	}
+}
+
+/* ======================================================================== */
+/*New code added Feb.07 oliver*/ // TODO: delete new code comments
+/** A panel at the bottom of a tree window that can be used for buttons & messages. */
+class ControlStrip extends Panel {
+	BasicTreeWindowMaker ownerModule;
+	Vector buttons;
+	int left = 4;
+	int top = 4;
+	int s = 8;
+
+	public ControlStrip(BasicTreeWindowMaker ownerModule) {  //in future pass general MesquiteWindow
+		super();
+		setLayout(null);
+		buttons = new Vector();
+		this.ownerModule = ownerModule;
+		setBackground(ColorTheme.getInterfaceElement());
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawRect(0,0, getBounds().width -1, getBounds().height-1);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void addButton(MesquiteButton s) {
+		if (buttons.indexOf(s) < 0) {
+			buttons.addElement(s);
+			add(s);
+		}
+		s.setVisible(true);
+		resetLocs();
+		repaint();
+	}
+
+	public void removeButton(MesquiteButton s) {
+		buttons.removeElement(s);
+		remove(s);
+		s.setVisible(false);
+		resetLocs();
+		repaint();
+	}
+
+	private void resetLocs() {
+		int x = 4;
+		for (int i = 0; i < buttons.size(); i++) {
+			MesquiteButton b = (MesquiteButton) buttons.elementAt(i);
+			b.setLocation(x, 2);
+			x += 20;
+		}
+	}	
+}	
+/*End new code added Feb.07 oliver*/
+/* ======================================================================== */
+class RecentButton extends MousePanel {
+	BasicTreeWindow window;
+	static int width = 9; //40;
+	static int height = 36;
+	static Image[] recentImage;
+	static int numImages = 11;
+
+	public RecentButton (BasicTreeWindow w){
+		this.window = w;
+		//setBackground(ColorDistribution.lightBlue);
+		setSize(width, height);
+		if (recentImage == null){
+			recentImage = new Image[numImages];
+			for (int i=0; i<numImages; i++)
+				recentImage[i] = MesquiteImage.getImage(window.getOwnerModule().getPath() + "recent" + MesquiteFile.fileSeparator + "recent" + (i) + ".gif");
+		}
+	}
+
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		MesquitePopup popup = new MesquitePopup(this);
+		popup.addItem("Recent Edited Trees", (MesquiteCommand)null, null);
+		popup.addItem("-", (MesquiteCommand)null, null);
+		if (window.recentEditedTrees.size()==0)
+			popup.addItem("None Available", (MesquiteCommand)null, null);
+		else {
+			popup.addItem("(Newest)", (MesquiteCommand)null, null);
+			for (int i = window.recentEditedTrees.size()-1; i>=0; i--){
+				Tree t = window.recentEditedTrees.getTree(i);
+				popup.addItem(Integer.toString(i+1) + "  " + t.getName(), MesquiteModule.makeCommand("showRecentEdited", window), Integer.toString(i));
+			}
+			popup.addItem("(Oldest)", (MesquiteCommand)null, null);
+		}
+		popup.showPopup(x+4,y+6);
+	}
+	public void paint (Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		int i = window.recentEditedTrees.size();
+		if (i>=numImages)
+			i = numImages-1;
+		g.drawImage(recentImage[i],0,0,this);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+}
+/* ======================================================================== */
+class TreeWindowPalette extends ToolPalette {
+	BasicTreeWindow treeWindow;
+	MiniScroll paletteScroll;
+	RecentButton recentButton ;
+	public BirdsEyePanel birdsEyeBox;
+	BirdsEyeExtra birdsEyeExtra;
+	int fieldWidth, fieldHeight;
+	int scrollHeight = 20;
+
+	public TreeWindowPalette(BasicTreeWindowMaker ownerModule, BasicTreeWindow containingWindow) {  //in future pass general MesquiteWindow
+		super( ownerModule,  containingWindow, 2);
+		treeWindow = containingWindow;
+		Taxa taxa = treeWindow.taxa;
+		if (taxa == null)
+			taxa = ownerModule.taxa;
+		add(paletteScroll = new MiniScroll(treeWindow.setTreeNumberCommand, true, 1, 1, MesquiteTree.toExternal(ownerModule.treeSourceTask.getNumberOfTrees(taxa)-1),"tree"));
+		paletteScroll.setBackground(Color.green);
+		paletteScroll.setLocation((getWidth()-paletteScroll.totalWidth+RecentButton.width)/2, scrollHeight);
+		paletteScroll.setVisible(true);
+		add(recentButton = new RecentButton(containingWindow));
+		recentButton.setLocation(paletteScroll.getBounds().x-12, paletteScroll.getBounds().y);
+
+		recentButton.setVisible(true);
+		setFieldSize(treeWindow.totalTreeFieldWidth,treeWindow.totalTreeFieldHeight);
+	}
+
+	/*.................................................................................................................*/
+	public void setCurrentTool(MesquiteTool tool){
+		if (tool!=null && !tool.getEnabled())
+			return;
+		if (tool instanceof TreeTool)
+			treeWindow.currentTreeTool = (TreeTool)tool;
+		super.setCurrentTool(tool);
+	}
+	void setUpBirdsEye(){
+		birdsEyeBox = new BirdsEyePanel(treeWindow, treeWindow.treeDisplay.getTreeDrawing());
+		add(birdsEyeBox);
+		if (treeWindow.usingPane)
+			birdsEyeBox.setVisible(true);
+		else
+			birdsEyeBox.setVisible(false);
+		birdsEyeExtra = new BirdsEyeExtra(ownerModule, treeWindow.treeDisplay, treeWindow);
+		treeWindow.treeDisplay.addExtra(birdsEyeExtra); //TODO: need to remove later?
+	}
+
+	public int minWidth(){
+		int w = super.minWidth();
+		int w2 = paletteScroll.getBounds().width + recentButton.width + 20;
+		if (w< w2)
+			return w2;
+		return w;
+	}
+	public void setFieldSize(int width, int height){
+		if (treeWindow== null || birdsEyeBox == null)
+			return;
+		paletteScroll.setLocation((getWidth()-paletteScroll.totalWidth+RecentButton.width)/2, scrollHeight);
+
+		recentButton.setLocation(paletteScroll.getBounds().x-12, paletteScroll.getBounds().y);
+
+		if (width != 0 && height !=0){
+			int birdWidth = getWidth()-8; 
+			int birdHeight = height*birdWidth/width;
+			int deepest = getDeepestButton();
+			if (deepest>getBounds().height-8-birdHeight) { //need to shrink birdsEyeBox to fit
+				birdHeight = getBounds().height-8 - deepest;
+				birdWidth = width*birdHeight/height;
+			}
+			birdsEyeBox.setBounds(4, getBounds().height-8-birdHeight, birdWidth, birdHeight);
+		}
+	}
+	public void paint(Graphics g) { //^^^
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		super.paint(g);
+
+		g.setColor(Color.black);
+		g.drawString("Tree #", paletteScroll.getBounds().x, paletteScroll.getBounds().y-3);
+		MesquiteWindow.uncheckDoomed(this);
+
+	}
+	public void repaintBirdsEye(){
+		birdsEyeBox.repaint();
+	}
+	public void dispose(){
+		MesquiteWindow w = MesquiteWindow.windowOfItem(this);
+		if (w!=null)
+			w.waitUntilDisposable();
+		birdsEyeExtra.dispose();
+		birdsEyeBox.dispose();
+		treeWindow = null;
+		remove(paletteScroll);
+		remove(birdsEyeBox);
+		super.dispose();
+	}
+
+}
+/*===========================================*/
+/*===========================================*/
+
+class BasicTreeStatisticsPanel extends TreeInfoExtraPanel {
+	StringInABox statsBox;
+	String treeStats = null;
+	int neededHeight = 20;
+	public BasicTreeStatisticsPanel(ClosablePanelContainer container){
+		super(container, "Basic Tree Stats");
+		statsBox =  new StringInABox("", null, 50);
+		setOpen(true);
+	}
+	public void setTree(Tree tree){
+		super.setTree(tree);
+		//number of terminal taxa
+		//any polytomies
+		//zero length branches (but only if present)
+		//total path length
+		//branch lengths absent
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	public void setNode(int node){
+		super.setNode(node);
+		repaint();
+	}
+	void adjustMessage(){
+		if (tree == null)
+			treeStats = "no tree";
+		else {
+			int numTerms = tree.numberOfTerminalsInClade(tree.getRoot());
+			int numTermsTotal = tree.getTaxa().getNumTaxa();
+			if (numTermsTotal == numTerms)
+				treeStats = "All " + numTerms + " taxa included.\n";
+			else
+				treeStats = "" + numTerms + " of " + numTermsTotal + " taxa included.\n";
+			if (tree.hasPolytomies(tree.getRoot()))
+				treeStats += "Has polytomies.\n";
+			if (!tree.hasBranchLengths())
+				treeStats += "No branch lengths specified.\n";
+			else {
+
+			}
+		}
+	}
+	public int getRequestedHeight(int width){
+		if (!isOpen())
+			return MINHEIGHT;
+		statsBox.setFont(getFont());
+		statsBox.setString(treeStats);
+		statsBox.setWidth(width-4);
+		neededHeight = statsBox.getHeight();
+		return neededHeight + MINHEIGHT;
+	}
+	public void paint(Graphics g){
+		super.paint(g);
+		//g.drawString("hello", 8, MINHEIGHT+20);
+		statsBox.setWidth(getBounds().width-4);
+		statsBox.setFont(g.getFont());
+		statsBox.setString(treeStats);
+		statsBox.draw(g,4, MINHEIGHT);
+	}
+}
+/*===========================================*/
+class BranchInfoPanel extends TreeInfoExtraPanel {
+	StringInABox statsBox;
+	String message = null;
+	int neededHeight = 20;
+	String attachmentsMessage = "";
+	Image query;
+	public BranchInfoPanel(ClosablePanelContainer container){
+		super(container, "Branch/Node Info");
+		query = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "queryGray.gif");
+		statsBox =  new StringInABox("", null, 50);
+	}
+	public void setTree(Tree tree){
+		super.setTree(tree);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	public void setNode(int node){
+		super.setNode(node);
+		adjustMessage();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	private void adjustMessage(){
+		attachmentsMessage = "";
+		if (tree == null)
+			message = "no tree";
+		else {
+			message = "";
+			if (tree.nodeExists(node)){
+				if (!tree.branchLengthUnassigned(node))
+					attachmentsMessage += "Branch length: " + MesquiteDouble.toString(tree.getBranchLength(node)) + "\n";
+
+				for (int i=0; i<tree.getNumberAssociatedDoubles(); i++){
+					DoubleArray d = tree.getAssociatedDoubles(i);
+					NameReference nr = d.getNameReference();
+					attachmentsMessage += nr.getValue();
+					attachmentsMessage += ": " + MesquiteDouble.toString(d.getValue(node));
+					attachmentsMessage += "\n";
+
+				}
+				for (int i=0; i<tree.getNumberAssociatedLongs(); i++){
+					LongArray d = tree.getAssociatedLongs(i);
+					NameReference nr = d.getNameReference();
+					attachmentsMessage += nr.getValue();
+					attachmentsMessage += ": " + MesquiteLong.toString(d.getValue(node));
+					attachmentsMessage += "\n";
+				}
+				for (int i=0; i<tree.getNumberAssociatedObjects(); i++){
+					ObjectArray d = tree.getAssociatedObjects(i);
+					NameReference nr = d.getNameReference();
+					if (d.getValue(node) instanceof String){
+						attachmentsMessage += nr.getValue();
+						attachmentsMessage += ": " + (d.getValue(node));
+						attachmentsMessage += "\n";
+					}
+				}
+				if (StringUtil.blank(attachmentsMessage)) {
+					message = "\n ";
+				}
+				message += attachmentsMessage;
+			}
+		}
+	}
+	public int getRequestedHeight(int width){
+		if (!isOpen())
+			return MINHEIGHT;
+		statsBox.setFont(getFont());
+		statsBox.setString(message);
+		statsBox.setWidth(width-4);
+		neededHeight = statsBox.getHeight();
+		return neededHeight + MINHEIGHT;
+	}
+	public void paint(Graphics g){
+		super.paint(g);
+		super.paint(g);
+		g.drawImage(query, getWidth()-20, 4, this);
+		statsBox.setWidth(getBounds().width-4);
+		statsBox.setFont(g.getFont());
+		statsBox.setString(message);
+		statsBox.draw(g,4, MINHEIGHT);
+	}
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (y<MINHEIGHT && (x> getWidth()- 20)) {
+			MesquiteTrunk.mesquiteTrunk.alert("Attachments:  Attachments to the tree or its nodes are pieces of information like branch lengths, lineage widths, assigned colors, and so on. Move cursor over nodes to see information attached there.");  //query button hit
+		}
+		else
+			super.mouseUp(modifiers,  x,  y,  tool);
+	}
+}
+/*===========================================*/
+
+/* ======================================================================== */
+class TreeInfoPanel extends MousePanel implements ClosablePanelContainer {
+	static final int width = 200;
+	//static final int height = 66;
+	String title = null;
+	String explanation = null;
+	StringInABox titleBox, explanationBox;
+	int[] locs;
+	BasicTreeWindow w;
+	Image goaway;
+	Tree tree;
+	Vector extras = new Vector();
+	Font titleFont;
+	String treeName, sourceName;
+	boolean storedTrees;
+	Image add = null;
+	BasicTreeStatisticsPanel btsp;
+	BranchInfoPanel ap;
+
+	public TreeInfoPanel (BasicTreeWindow w){
+		super();
+		this.w = w;
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addGray.gif");
+		setLayout(null);
+		addExtraPanel(btsp = new BasicTreeStatisticsPanel(this));
+		addExtraPanel(ap = new BranchInfoPanel(this));
+		setBackground(ColorDistribution.veryLightGray);
+		setFont(new Font("SansSerif", Font.PLAIN, 12));
+		titleFont = new Font("SansSerif", Font.BOLD, 12);
+		titleBox =  new StringInABox("", null, width);
+		explanationBox =  new StringInABox("", null, width);
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "minimizeTransparent.gif");
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("btspOpen " + btsp.isOpen());
+		temp.addLine("apOpen " + ap.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets attachment panel open", null, commandName, "apOpen")) {
+			ap.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else if (checker.compare(this.getClass(), "Sets the basic statistics panel open", null, commandName, "btspOpen")) {
+			btsp.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public ClosablePanel getPrecedingPanel(ClosablePanel panel){
+		int i = extras.indexOf(panel);
+		if (i >0)
+			return (ClosablePanel)extras.elementAt(i-1);
+		return null;
+	}
+	void addExtraPanel(TreeInfoExtraPanel p){
+		extras.addElement(p);
+		add(p);
+		resetSizes(getWidth(), getHeight());
+		p.setVisible(true);
+		if (tree != null)
+			p.setTree(tree);
+	}
+	void setTree(Tree tree){
+		if (tree == null)
+			return;
+		this.tree = tree;
+		title = "Tree: " + tree.getName();
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			if (tree != null)
+				panel.setTree(tree);
+		}
+		setHighlighted(storedTrees);
+	}
+	void taxonEnter(int it){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.taxonEnter(it);
+		}
+	}
+	void taxonExit(int it){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.taxonExit(it);
+		}
+	}
+	void taxonTouch(int it){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.taxonTouch(it);
+		}
+	}
+	void branchEnter(int node){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.branchEnter(node);
+		}
+	}
+	void branchExit(int node){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.branchExit(node);
+		}
+	}
+	void branchTouch(int node){
+		for (int i = 0; i<extras.size(); i++){
+			TreeInfoExtraPanel panel = ((TreeInfoExtraPanel)extras.elementAt(i));
+			panel.branchTouch(node);
+		}
+	}
+	void setTreeAndSourceName(String treeName, String sourceName){
+		this.treeName = treeName;
+		this.sourceName = sourceName;
+		setHighlighted(storedTrees);
+	}
+	public void setHighlighted(boolean storedTrees) {
+		this.storedTrees = storedTrees;
+		boolean edited = w.treeEdited;
+		if (edited && storedTrees)
+			title = "Tree: Edited, based on " + treeName;
+		else if (edited)
+			title = "Tree: Edited, based on " + treeName;
+		else 
+			title = "Tree: " + treeName;
+		if (edited){
+			if (storedTrees)
+				explanation = "Tree is modified from one of the stored trees ";
+			else
+				explanation = "Tree has been edited; it is not directly from the tree source.";
+		}
+		else {
+			if (storedTrees)
+				explanation = "Tree is stored in the project.";
+			else
+				explanation = "Tree is not stored in the project.  The tree is from: " + sourceName;
+		}
+		resetSizes(getWidth(), getHeight());
+		repaint();
+	}
+	public void requestHeightChange(ClosablePanel panel){
+		resetSizes(getWidth(), getHeight());
+		repaint();
+	}
+
+	public void paint(Graphics g){
+		Color c = g.getColor();
+
+		int vertical = 2;
+		if (title != null){
+			g.setColor(ColorTheme.getInterfaceElement());
+			g.fillRect(0, 0, getBounds().width, titleBox.getHeight()+8);
+			g.setColor(ColorTheme.getInterfaceTextContrast());
+			titleBox.draw(g,20, vertical);
+			g.setColor(Color.black);
+			vertical += 8 + titleBox.getHeight();
+		}
+
+		g.drawImage(goaway, 2, 2, this);
+		g.drawLine(0, vertical-4, getBounds().width, vertical-4);
+		if (explanation != null){
+			g.setColor(Color.white);
+			g.fillRect(0, vertical, getBounds().width, 8 + explanationBox.getHeight());
+			g.setColor(Color.black);
+			explanationBox.draw(g,4, vertical);
+			vertical += 8 + explanationBox.getHeight();
+		}
+		g.setColor(Color.darkGray);
+		g.fillRect(0, totalVertical, getBounds().width, 2);
+		//WHEN CALCULATIONS CAN BE ADDED
+		//	g.drawImage(add, 2, totalVertical+4, this);
+		g.setColor(c);
+
+
+
+
+
+	}
+
+	int totalVertical = 0;
+
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (x<30 && y > totalVertical+4 && y < totalVertical + 20){
+			//WHEN CALCULATIONS CAN BE ADDED
+			//MesquiteTrunk.mesquiteTrunk.alert("Sorry, doesn't do anything yet");
+		}
+	}
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (x< 16 && y<16)
+			w.treeInfoPanelGoAway();
+
+	}
+	void resetSizes(int w, int h){
+		int vertical = 2;
+		if (title != null){
+			titleBox.setWidth(w-20);
+			titleBox.setFont(titleFont);
+			titleBox.setString(title);
+			vertical += 8 + titleBox.getHeight();
+		}
+		if (explanation != null){
+			explanationBox.setWidth(w-4);
+			explanationBox.setFont(getFont());
+			explanationBox.setString(explanation);
+			vertical += 8 + explanationBox.getHeight();
+		}
+		for (int i = 0; i<extras.size(); i++){
+			ClosablePanel panel = ((ClosablePanel)extras.elementAt(i));
+			int requestedlHeight = panel.getRequestedHeight(w);
+
+			panel.setBounds(0, vertical, w, requestedlHeight);
+			vertical += requestedlHeight;
+		}
+		totalVertical = vertical;
+	}
+	public void setBounds(int x, int y, int w, int h){
+		super.setBounds(x,y,w,h);
+		resetSizes(w, h);
+	}
+	public void setSize(int w, int h){
+		super.setSize(w,h);
+		resetSizes(w, h);
+	}
+}
+
+
+/* ======================================================================== */
+/* scrollbar for tree */
+class TreeScroll extends MesquiteScrollbar {
+	BasicTreeWindow basicTreeWindow;
+	public TreeScroll (BasicTreeWindow basicTreeWindow, int orientation, int value, int visible, int min, int max){
+		super(orientation, value, visible, min, max);
+		this.basicTreeWindow=basicTreeWindow;
+	}
+
+	public void scrollTouched() {
+		int currentValue = getValue();
+	}
+	public void dispose(){
+		basicTreeWindow = null;
+		//super.dispose();
+	}
+}
+
+/* ======================================================================== */
+class BirdsEyeExtra extends TreeDisplayExtra {
+	BasicTreeWindow treeWindow;
+	public BirdsEyeExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay, BasicTreeWindow treeWindow) {
+		super(ownerModule, treeDisplay);
+		this.treeWindow = treeWindow;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (treeWindow.usingPane && treeWindow.palette != null && treeWindow.palette.birdsEyeBox != null)
+			treeWindow.palette.birdsEyeBox.repaint();
+	}
+	public   void setTree(Tree tree) {
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+	public void dispose(){
+		treeWindow = null;
+		super.dispose();
+	}
+}
+/* ======================================================================== */
+class MagnifyExtra extends TreeDisplayExtra {
+	Image image;
+	BasicTreeWindowMaker om;
+	String name = "";
+	public MagnifyExtra (BasicTreeWindowMaker ownerModule, TreeDisplay treeDisplay, TreeTool tool) {
+		super(ownerModule, treeDisplay);
+		om = ownerModule;
+		image = MesquiteImage.getImage(tool.getImagePath());
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (drawnRoot!= tree.getRoot()) {
+			TreeDrawing td = treeDisplay.getTreeDrawing();
+			g.drawImage(image, td.x[drawnRoot], td.y[drawnRoot], treeDisplay);
+		}
+	}
+	public   void setTree(Tree tree) {
+	}
+	/** Returns any strings to be appended to taxon name.*/
+	public String getTaxonStringAddition(Taxon taxon){
+		Taxa taxa = taxon.getTaxa();
+		int which = taxa.whichTaxonNumber(taxon);
+		String s = taxa.getAnnotation(which);
+		if (!StringUtil.blank(s))
+			return "*";
+		return null;
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+
+		if (name!=null && om.printNameOnTree.getValue())
+			g.drawString(name, 50, treeDisplay.getBounds().height - 20);
+	}
+}
+/* ======================================================================== */
+class BirdsEyePanel extends MesquitePanel {
+	TreeDrawing treeDrawing;
+	BasicTreeWindow treeWindow;
+	int offsetX = 0;
+	int offsetY=0;
+	int origTouchX, origTouchY, dragOffsetX, dragOffsetY;
+	int rootX, rootY;
+	Rectangle vis;
+	public BirdsEyePanel (BasicTreeWindow treeWindow, TreeDrawing treeDrawing) {
+		this.treeDrawing=treeDrawing;
+		origTouchX = origTouchY = -1;
+		this.treeWindow = treeWindow;
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+		vis = new Rectangle();
+	}
+
+	public void dispose(){
+		treeWindow = null;
+		treeDrawing = null;
+		//super.dispose();
+	}
+	public void sketchTree(Tree tree, int N, Graphics g) {
+		int nodeX=getTransformedX(N);
+		int nodeY=getTransformedY(N);
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			int daughterX=getTransformedX(d);
+			int daughterY=getTransformedY(d);
+			g.drawLine(nodeX, nodeY, daughterX, daughterY);
+			sketchTree(tree, d, g);
+		}
+
+	}
+
+	public void setFieldSize(int width, int height){
+
+	}
+	private int getTransformedX(int node){
+		return getBounds().width *treeDrawing.x[node] /(treeWindow.treeDisplay.getFieldWidth());
+	}
+	private int getTransformedY(int node){
+		return getBounds().height *treeDrawing.y[node] /(treeWindow.treeDisplay.getFieldHeight());
+	}
+	public void paint(Graphics g) {
+		if (treeWindow == null || treeWindow.treeDisplay == null)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Tree tree = treeWindow.treeDisplay.getTree();
+		if (tree == null){
+			MesquiteWindow.uncheckDoomed(this);
+			return;
+		}
+		treeDrawing = treeWindow.treeDisplay.getTreeDrawing();
+		int drawnRoot = treeDrawing.getDrawnRoot();
+		if (tree != null && !tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		g.setColor(Color.white);
+		rootX=getTransformedX(drawnRoot);
+		rootY=getTransformedY(drawnRoot);
+		recalcVis();
+		/*int oX = -treeWindow.getOriginX();
+		int oY = -treeWindow.getOriginY();
+		vis.x=getBounds().width *oX /(treeWindow.treeDisplay.getFieldWidth());
+		vis.y=getBounds().height *oY /(treeWindow.treeDisplay.getFieldHeight());
+		if (treeWindow.treePane==null) {
+			vis.width = getBounds().width*treeWindow.treeDisplay.getBounds().width/(treeWindow.treeDisplay.getFieldWidth());
+			vis.height = getBounds().height*treeWindow.treeDisplay.getBounds().height/(treeWindow.treeDisplay.getFieldHeight());
+		}
+		else {
+			vis.width = getBounds().width*treeWindow.treePane.getBounds().width/(treeWindow.treeDisplay.getFieldWidth());
+			vis.height = getBounds().height*treeWindow.treePane.getBounds().height/(treeWindow.treeDisplay.getFieldHeight());
+		}
+		 */
+		g.fillRoundRect(vis.x, vis.y, vis.width, vis.height, 8, 8);
+		g.setColor(Color.gray);
+		sketchTree(tree, drawnRoot, g);
+		g.setColor(Color.black);
+		g.drawRoundRect(vis.x, vis.y, vis.width, vis.height,8,8);
+		g.drawRect(0,0, getBounds().width-1, getBounds().height-1);
+		g.drawRect(1,1, getBounds().width-3, getBounds().height-3);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	boolean recalcVis(){
+		Rectangle oldV = new Rectangle(vis);
+		int oX = treeWindow.getOriginX();
+		int oY = treeWindow.getOriginY();
+		vis.x=getBounds().width *oX /(treeWindow.treeDisplay.getFieldWidth());
+		vis.y=getBounds().height *oY /(treeWindow.treeDisplay.getFieldHeight());
+		vis.width = getBounds().width*treeWindow.getTreePaneWidth()/(treeWindow.treeDisplay.getFieldWidth());
+		vis.height = getBounds().height*treeWindow.getTreePaneHeight()/(treeWindow.treeDisplay.getFieldHeight());
+		vis.width = getBounds().width*treeWindow.getTreePaneWidth()/(treeWindow.treeDisplay.getFieldWidth());
+		vis.height = getBounds().height*treeWindow.getTreePaneHeight()/(treeWindow.treeDisplay.getFieldHeight());
+		return (oldV.x != vis.x || oldV.y != vis.y || oldV.width != vis.width || oldV.height != vis.height);
+	}
+	public void mouseDrag (int modifiers, int x, int y, MesquiteTool tool) {
+		if (origTouchX<0 || origTouchY<0)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Graphics g = null;
+		if (GraphicsUtil.useXORMode(null, false)){
+			g=getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.green);
+			g.drawRoundRect(vis.x + dragOffsetX, vis.y + dragOffsetY, vis.width, vis.height, 8 ,8);
+		}
+		dragOffsetX=x-origTouchX;
+		dragOffsetY=y-origTouchY;
+		if (GraphicsUtil.useXORMode(null, false)){
+			g.drawRoundRect(vis.x + dragOffsetX, vis.y + dragOffsetY, vis.width, vis.height, 8 ,8);
+			g.dispose();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		origTouchX=x;
+		origTouchY=y;
+		dragOffsetX=0;
+		dragOffsetY=0;
+
+		boolean changed = recalcVis();
+		if (changed){
+			Graphics g=getGraphics();
+			update(g);
+			g.dispose();
+		}
+		if (GraphicsUtil.useXORMode(null, false)){		
+			Graphics g=getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.green);
+			g.drawRoundRect(vis.x, vis.y, vis.width, vis.height, 8 ,8);
+			g.dispose();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void mouseUp (int modifiers, int x, int y, MesquiteTool tool) {
+		if (origTouchX<0 || origTouchY<0)
+			return;
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		offsetX=offsetX + dragOffsetX;
+		offsetY=offsetY + dragOffsetY;
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g=getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.green);
+			g.drawRoundRect(vis.x + dragOffsetX, vis.y + dragOffsetY, vis.width, vis.height, 8, 8);
+			g.setPaintMode();
+			g.dispose();
+		}
+		int oX = (vis.x + dragOffsetX)*(treeWindow.treeDisplay.getFieldWidth())/(getBounds().width);
+		int oY = (vis.y + dragOffsetY)*(treeWindow.treeDisplay.getFieldHeight())/(getBounds().height);
+		if (oX<0)
+			oX=0;
+		if (oY<0)
+			oY=0;
+		treeWindow.setOrigin(oX,oY, true);
+
+		treeWindow.treeDisplay.pleaseUpdate(true);
+		treeWindow.sizeDisplay();
+		origTouchX=-1;
+		origTouchY=-1;
+
+		repaint();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+/* ======================================================================== */
+class TreeWindowSelectionRectangle  {
+	Rectangle selectionRect;
+
+	public TreeWindowSelectionRectangle(Graphics2D g2, int x, int y, int w, int h){
+		this.selectionRect = new Rectangle(x,y,w,h);
+	}
+
+	public static Area createAreaFromRectangle(Rectangle rect) {
+
+		MesquitePath2DFloat path = new MesquitePath2DFloat();
+		if (path.OK()){
+			path.moveTo(rect.x, rect.y);
+			path.lineTo(rect.x+rect.width, rect.y);
+			path.lineTo(rect.x+rect.width, rect.y+rect.height);
+			path.lineTo(rect.x, rect.y+rect.height);
+			path.lineTo(rect.x, rect.y);
+			path.closePath();
+			return path.getArea();
+		}
+		else{
+			return null;
+		}
+
+	}
+	public void drawSelectionDifference(Graphics2D g2, Component comp, int x, int y, int w, int h) {
+		Rectangle newRect = new Rectangle(x,y,w,h);
+		GraphicsUtil.fixRectangle(newRect);
+		Area newArea = createAreaFromRectangle(newRect);
+		Area differenceArea = createAreaFromRectangle(selectionRect);
+
+		if (differenceArea!=null) {
+			differenceArea.exclusiveOr(newArea);
+			Shape oldClip = g2.getClip();
+			g2.setClip(differenceArea);
+			if (selectionRect.contains(newRect)) { // original rect is bigger
+				comp.repaint(selectionRect.x, selectionRect.y, selectionRect.width, selectionRect.height);
+				GraphicsUtil.fillTransparentSelectionRectangle(g2, x,y,w,h);
+			} else if (newRect.contains(selectionRect)) { // new rect is bigger
+				GraphicsUtil.fillTransparentSelectionArea(g2, differenceArea);
+			}
+			g2.setClip(oldClip);
+		}
+
+
+		selectionRect.setRect(newRect);
+
+
+	}
+}
+
+
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/collapse.gif b/Source/mesquite/trees/BasicTreeWindowMaker/collapse.gif
new file mode 100644
index 0000000..1a635ad
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/collapse.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/collapseAllBelow.gif b/Source/mesquite/trees/BasicTreeWindowMaker/collapseAllBelow.gif
new file mode 100644
index 0000000..43091e2
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/collapseAllBelow.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/collapseall.gif b/Source/mesquite/trees/BasicTreeWindowMaker/collapseall.gif
new file mode 100644
index 0000000..5fe2bc4
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/collapseall.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/interchange.gif b/Source/mesquite/trees/BasicTreeWindowMaker/interchange.gif
new file mode 100644
index 0000000..f58adcc
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/interchange.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/ladderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/ladderize.gif
new file mode 100644
index 0000000..22e3918
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/ladderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/magnify.gif b/Source/mesquite/trees/BasicTreeWindowMaker/magnify.gif
new file mode 100644
index 0000000..ca32fd9
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/magnify.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent0.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent0.gif
new file mode 100644
index 0000000..92d515c
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent0.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent1.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent1.gif
new file mode 100644
index 0000000..412e765
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent1.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent10.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent10.gif
new file mode 100644
index 0000000..4227957
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent10.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent2.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent2.gif
new file mode 100644
index 0000000..843808f
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent2.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent3.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent3.gif
new file mode 100644
index 0000000..b1345ff
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent3.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent4.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent4.gif
new file mode 100644
index 0000000..7a672f4
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent4.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent5.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent5.gif
new file mode 100644
index 0000000..babaa7b
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent5.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent6.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent6.gif
new file mode 100644
index 0000000..85fba8c
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent6.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent7.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent7.gif
new file mode 100644
index 0000000..0678e3b
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent7.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent8.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent8.gif
new file mode 100644
index 0000000..035f965
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent8.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent9.gif b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent9.gif
new file mode 100644
index 0000000..b674111
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/recent/recent9.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/reroot.gif b/Source/mesquite/trees/BasicTreeWindowMaker/reroot.gif
new file mode 100644
index 0000000..b1c586c
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/reroot.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/reverseLadderize.gif b/Source/mesquite/trees/BasicTreeWindowMaker/reverseLadderize.gif
new file mode 100644
index 0000000..7960366
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/reverseLadderize.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/scissors.gif b/Source/mesquite/trees/BasicTreeWindowMaker/scissors.gif
new file mode 100644
index 0000000..dcdab9e
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/scissors.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/triangle.gif b/Source/mesquite/trees/BasicTreeWindowMaker/triangle.gif
new file mode 100644
index 0000000..929b5dd
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/triangle.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/zoom.gif b/Source/mesquite/trees/BasicTreeWindowMaker/zoom.gif
new file mode 100644
index 0000000..8cb501f
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/zoom.gif differ
diff --git a/Source/mesquite/trees/BasicTreeWindowMaker/zoomOut.gif b/Source/mesquite/trees/BasicTreeWindowMaker/zoomOut.gif
new file mode 100644
index 0000000..ab986bb
Binary files /dev/null and b/Source/mesquite/trees/BasicTreeWindowMaker/zoomOut.gif differ
diff --git a/Source/mesquite/trees/BooleanTreeValue/BooleanTreeValue.java b/Source/mesquite/trees/BooleanTreeValue/BooleanTreeValue.java
new file mode 100644
index 0000000..b4895c5
--- /dev/null
+++ b/Source/mesquite/trees/BooleanTreeValue/BooleanTreeValue.java
@@ -0,0 +1,131 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BooleanTreeValue;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class BooleanTreeValue extends NumberForTree {
+	public String getName() {
+		return "Boolean Tree Value";
+	}
+	public String getVeryShortName() {
+		if (booleanTask==null)
+			return getName();
+		return "1 if " + booleanTask.getName();
+	}
+	public String getExplanation() {
+		return "Gives a tree a value of 1 if it satisfies the criterion, 0 otherwise." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(BooleanForTree.class, getName() + " needs a method to calculate a boolean (yes/no) value for each of the trees.",
+		"You can select the method to calculate yes/no values initially. ");
+		e.setPriority(1);
+	}
+	/*.................................................................................................................*/
+
+	BooleanForTree booleanTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			booleanTask = (BooleanForTree)hireNamedEmployee(BooleanForTree.class, arguments);
+			if (booleanTask==null) {
+				return sorry("Boolean for tree can't start because the requested calculator module wasn't successfully hired");
+			}
+		}
+		else {
+			booleanTask = (BooleanForTree)hireEmployee(BooleanForTree.class, "Value to calculate for trees");
+			if (booleanTask==null) {
+				return sorry("Boolean for tree can't start because no calculator module was successfully hired");
+			}
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setValueTask ", booleanTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		outputInvalid();
+		parametersChanged();
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == booleanTask)  
+			iQuit();
+		super.employeeQuit(employee);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module that calculates a boolean for a tree", "[name of module]", commandName, "setValueTask")) {
+			BooleanForTree temp= (BooleanForTree)replaceEmployee(BooleanForTree.class, arguments, "Boolean for a tree", booleanTask);
+			if (temp!=null) {
+				booleanTask = temp;
+				parametersChanged();
+				return temp;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (booleanTask==null)
+			return null;
+		return "1 if " + booleanTask.getName();
+	}
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (tree==null || booleanTask==null || result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		MesquiteBoolean mb = new MesquiteBoolean();
+		booleanTask.calculateBoolean(tree,mb, resultString);
+		if (mb.getValue()) {
+			result.setValue(1);
+		}
+		else if (!mb.getValue()) {
+			result.setValue(0);
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+
+	}
+}
+
diff --git a/Source/mesquite/trees/BranchInfo/32branchInfo.gif b/Source/mesquite/trees/BranchInfo/32branchInfo.gif
new file mode 100644
index 0000000..881fc31
Binary files /dev/null and b/Source/mesquite/trees/BranchInfo/32branchInfo.gif differ
diff --git a/Source/mesquite/trees/BranchInfo/64branchInfo.gif b/Source/mesquite/trees/BranchInfo/64branchInfo.gif
new file mode 100644
index 0000000..f6fefa5
Binary files /dev/null and b/Source/mesquite/trees/BranchInfo/64branchInfo.gif differ
diff --git a/Source/mesquite/trees/BranchInfo/BranchInfo.java b/Source/mesquite/trees/BranchInfo/BranchInfo.java
new file mode 100644
index 0000000..4e702d1
--- /dev/null
+++ b/Source/mesquite/trees/BranchInfo/BranchInfo.java
@@ -0,0 +1,281 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.BranchInfo;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class BranchInfo extends TreeDisplayAssistantI {
+	public Vector extras;
+	 public String getFunctionIconPath(){
+   		 return getPath() + "branchInfo.gif";
+   	 }
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		InfoToolExtra newPj = new InfoToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Branch Information";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Provides a tool that shows information about branches.";
+   	 }
+}
+
+/* ======================================================================== */
+class InfoToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool infoTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	BranchInfo infoModule;
+	Tree tree;
+	MesquiteCommand respondCommand;
+
+	public InfoToolExtra (BranchInfo ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		respondCommand = ownerModule.makeCommand("respond", this);
+		infoModule = ownerModule;
+		infoTool = new TreeTool(this, "BranchInfo", ownerModule.getPath(), "branchInfo.gif", 5,2,"Branch Info", "This tool is used to show information about a branch.");
+		infoTool.setTouchedCommand(MesquiteModule.makeCommand("query",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(infoTool);
+			//infoTool.setPopUpOwner(ownerModule);
+			//ownerModule.setUseMenubar(false); //menu available by touching button
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		this.tree = tree;
+	}
+	
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+	}
+	MesquitePopup popup;
+	MesquiteInteger pos = new MesquiteInteger();
+	void addToPopup(String s, int node, int response){
+		if (popup==null)
+			return;
+		popup.addItem(s, ownerModule, respondCommand, Integer.toString(node) + " " + Integer.toString(response));
+	}
+	void respondToPopup(String s,  int responseRequested,  int response){
+		if (responseRequested == response)
+			ownerModule.alert(s);
+	}
+	/*.................................................................................................................*/
+ 	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+    	 	if (checker.compare(this.getClass(), "Shows popup menu with information about the branch", "[branch number]", commandName, "query")) {
+  			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+  			if (branchFound >0 && MesquiteInteger.isCombinable(branchFound)) {
+				if (popup==null)
+					popup = new MesquitePopup(treeDisplay);
+				popup.removeAll();
+				int responseNumber = 0;
+				addToPopup("Branch/node number: " + branchFound, branchFound, responseNumber++);
+				addToPopup("-", branchFound, responseNumber++);
+				addToPopup("Length: " + MesquiteDouble.toString(tree.getBranchLength(branchFound)), branchFound, responseNumber++);
+				int num = tree.getNumberAssociatedLongs();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						LongArray lo = tree.getAssociatedLongs(i);
+						NameReference nr = lo.getNameReference();
+						if (nr==null)
+							addToPopup("?: " + MesquiteLong.toString(lo.getValue(branchFound)), branchFound, responseNumber++);
+						else
+							addToPopup(nr.getValue() + ": " + MesquiteLong.toString(lo.getValue(branchFound)), branchFound, responseNumber++);
+					}
+				num = tree.getNumberAssociatedDoubles();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						DoubleArray lo = tree.getAssociatedDoubles(i);
+						NameReference nr = lo.getNameReference();
+						if (nr==null)
+							addToPopup("?: " + MesquiteDouble.toString(lo.getValue(branchFound)), branchFound, responseNumber++);
+						else
+							addToPopup(nr.getValue() + ": " + MesquiteDouble.toString(lo.getValue(branchFound)), branchFound, responseNumber++);
+					}
+				num = tree.getNumberAssociatedObjects();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						ObjectArray lo = tree.getAssociatedObjects(i);
+						Object obj = lo.getValue(branchFound);
+						if (obj != null && (obj instanceof String || obj instanceof Listable)){
+							String s = "";
+							if (obj instanceof String)
+								s = (String)obj;
+							else if (obj instanceof Listable)
+								s = ((Listable)obj).getName();
+							NameReference nr = lo.getNameReference();
+							if (nr==null)
+								addToPopup("?: " + s, branchFound, responseNumber++);
+							else
+								addToPopup(nr.getValue() + ": " + s, branchFound, responseNumber++);
+						}
+					}
+				
+			Enumeration e = treeDisplay.getExtras().elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+					String strEx =ex.textAtNode(tree, branchFound);
+		 			if (!StringUtil.blank(strEx)) {
+			 			if (ex.ownerModule!=null)
+			 				strEx = ex.ownerModule.getName() + ": " + strEx;
+		 				addToPopup(strEx, branchFound, responseNumber++);
+		 			}
+		 		}
+			popup.showPopup(treeDisplay.getTreeDrawing().x[branchFound], treeDisplay.getTreeDrawing().y[branchFound]);
+   			}
+ 	 	}
+    	 	else if (checker.compare(this.getClass(), "Responds to choice of popup menu with information about the branch", "[branchNumber][choice number]", commandName, "respond")) {
+  			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+  			if (branchFound >0 && MesquiteInteger.isCombinable(branchFound)) {
+	  			int responseRequested = MesquiteInteger.fromString(arguments, pos);
+				int responseNumber = 2 ;
+				if (responseRequested == responseNumber++)
+					ownerModule.alert("This represents the length of the branch (stored in the primary branch length storage of the tree)");
+				int num = tree.getNumberAssociatedLongs();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						if (responseRequested == responseNumber++) {
+							LongArray lo = tree.getAssociatedLongs(i);
+							NameReference nr = lo.getNameReference();
+							String name = "?";
+							if (nr!=null)
+								name = nr.getValue();
+							ownerModule.alert("This represents an integral (long) value attached to the branch of the tree, named " + name);
+						//todo: allow user to change value
+						}
+					}
+				num = tree.getNumberAssociatedDoubles();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						if (responseRequested == responseNumber++) {
+							DoubleArray lo = tree.getAssociatedDoubles(i);
+							NameReference nr = lo.getNameReference();
+							String name = "?";
+							if (nr!=null)
+								name = nr.getValue();
+							ownerModule.alert("This represents a floating-point (double) value attached to the branch of the tree, named " + name);
+						//todo: allow user to change value
+						}
+					}
+				
+				num = tree.getNumberAssociatedObjects();
+				if (num>0)
+					for (int i=0; i<num; i++) {
+						if (responseRequested == responseNumber++) {
+							ObjectArray lo = tree.getAssociatedObjects(i);
+							Object obj = lo.getValue(branchFound);
+							if (obj != null && (obj instanceof String || obj instanceof Listable)){
+								NameReference nr = lo.getNameReference();
+								String name = "?";
+								if (nr!=null)
+									name = nr.getValue();
+								String s = "";
+								if (obj instanceof String) {
+									s = (String)obj;
+									if (tree instanceof MesquiteTree){
+										String message = "This represents a String attached to the branch of the tree, with name " + name + " and value \"" + s + "\".  Do you want to change the string?";
+										if (AlertDialog.query(ownerModule.containerOfModule(), "String at node", message)){
+											String newString = MesquiteString.queryString(ownerModule.containerOfModule(), "Change String", "Change string to", s);
+											if (newString !=null)
+												((MesquiteTree)tree).setAssociatedObject(nr, branchFound, newString);
+										}
+									}
+									else {
+										ownerModule.alert("This represents a String attached to the branch of the tree, with name " + name + " and value \"" + s + "\"");
+									}
+								}
+								else if (obj instanceof Listable) {
+									s = ((Listable)obj).getName();
+									ownerModule.alert("This represents an object attached to the branch of the tree, of category " + name + " and with name " + s);
+								}
+							}
+						}
+					}
+				Enumeration e = treeDisplay.getExtras().elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					TreeDisplayExtra ex = (TreeDisplayExtra)obj;
+					String strEx =ex.textAtNode(tree, branchFound);
+		 			if (!StringUtil.blank(strEx)) {
+			 			String name = "";
+			 			if (ex.ownerModule!=null)
+			 				name = ex.ownerModule.getName();
+						if (responseRequested == responseNumber++){
+							if (tree instanceof MesquiteTree){
+								String message ="This represents the output of a tree display assistant named " + name + ". Do you want to store the result at this and other nodes in the tree as strings?";
+								if (AlertDialog.query(ownerModule.containerOfModule(), "Tree display assistant output", message)){
+									String stringName = MesquiteString.queryString(ownerModule.containerOfModule(), "Name", "Name to give to strings attached to nodes (single token please)", StringUtil.tokenize(name));
+									if (!StringUtil.blank(stringName)){
+										NameReference nr = NameReference.getNameReference(StringUtil.tokenize(stringName));
+										transferToStrings((MesquiteTree)tree, tree.getRoot(), ex, nr);
+								   		((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+									}
+								}
+							}
+							else
+								ownerModule.alert("This represents the output of a tree display assistant named " + name + ".");
+						}
+		 			}
+		 		}
+   			}
+ 	 	}
+ 		return null;
+ 	}
+	/*.................................................................................................................*/
+ 	private void transferToStrings(MesquiteTree tree, int node, TreeDisplayExtra ex, NameReference nr){
+		String s = ex.textAtNode(tree, node);
+		if (!StringUtil.blank(s))
+			tree.setAssociatedObject(nr, node, s);
+		
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+			transferToStrings(tree, daughter, ex, nr);
+						
+ 	}
+	/*.................................................................................................................*/
+	public void turnOff() {
+		if (infoModule.extras != null)
+			infoModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+	
+
+
diff --git a/Source/mesquite/trees/BranchInfo/branchInfo.gif b/Source/mesquite/trees/BranchInfo/branchInfo.gif
new file mode 100644
index 0000000..72c03ca
Binary files /dev/null and b/Source/mesquite/trees/BranchInfo/branchInfo.gif differ
diff --git a/Source/mesquite/trees/BranchLengthFromRoot/BranchLengthFromRoot.java b/Source/mesquite/trees/BranchLengthFromRoot/BranchLengthFromRoot.java
new file mode 100644
index 0000000..33547b1
--- /dev/null
+++ b/Source/mesquite/trees/BranchLengthFromRoot/BranchLengthFromRoot.java
@@ -0,0 +1,76 @@
+/* Mesquite source code, Treefarm package.  Copyright 1997 and onward, W. Maddison, D. Maddison and P. Midford. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BranchLengthFromRoot;
+/*~~  */
+
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.treefarm.lib.*;
+
+/** ======================================================================== */
+public class BranchLengthFromRoot extends NForTaxonWithTree {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Taxa taxa, Tree tree, NumberArray results, MesquiteString resultsString){
+		if (tree == null)
+			return;
+		clearResultAndLastResult(results);
+		results.zeroArray();
+		for (int it=0; it<taxa.getNumTaxa(); it++) {
+			if (tree.taxonInTree(it))
+				results.setValue(it, tree.distanceToRoot(tree.nodeOfTaxonNumber(it), false, 0.0));
+		}
+		saveLastResult(results);
+		saveLastResultString(resultsString);
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		return "Branch Length from Root";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Branch Length from Root";
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease() {
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "For each taxon, calculates the sum of the branch lengths from that taxon to the root of the tree.";
+	}
+
+}
+
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/32adjustLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/32adjustLengths.gif
new file mode 100644
index 0000000..415aac5
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/32adjustLengths.gif differ
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/32dragLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/32dragLengths.gif
new file mode 100644
index 0000000..dd184e0
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/32dragLengths.gif differ
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/64adjustLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/64adjustLengths.gif
new file mode 100644
index 0000000..ed81a26
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/64adjustLengths.gif differ
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/64dragLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/64dragLengths.gif
new file mode 100644
index 0000000..80a1d82
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/64dragLengths.gif differ
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/BranchLengthsAdjust.java b/Source/mesquite/trees/BranchLengthsAdjust/BranchLengthsAdjust.java
new file mode 100644
index 0000000..17bca2f
--- /dev/null
+++ b/Source/mesquite/trees/BranchLengthsAdjust/BranchLengthsAdjust.java
@@ -0,0 +1,480 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.BranchLengthsAdjust;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class BranchLengthsAdjust extends TreeDisplayAssistantI {
+	public Vector extras;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		AdjustToolExtra newPj = new AdjustToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires a module to alter or transform branch lengths", "[name of module]", commandName, "alterBranchLengths")) {
+			BranchLengthsAlterer ble = (BranchLengthsAlterer)hireNamedEmployee(BranchLengthsAlterer.class, arguments);
+			if (ble!=null) {
+				transformTree(ble);
+
+				fireEmployee(ble); //todo: might be good to keep it around, and remembering it if user wants to change parameters
+			}
+			//if arguments have name of estimator then use it, passing it the trees
+		}
+		else if (checker.compare(this.getClass(), "Sets branch length of selected nodes", null, commandName, "acceptBranchLengths")) {
+			Enumeration e = extras.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				AdjustToolExtra tCO = (AdjustToolExtra)obj;
+				tCO.doCommand("setLength", arguments, checker);
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	void transformTree(TreeTransformer ble){
+		Enumeration e = extras.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			AdjustToolExtra tCO = (AdjustToolExtra)obj;
+			Tree t = tCO.getTree();
+			if (t instanceof AdjustableTree) {
+				boolean success = ble.transformTree((AdjustableTree)t, null, true);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Branch Lengths Adjust";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool to adjust branch lengths of trees.";
+	}
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Set Branch Lengths", "(A tool of the Tree Window) Allows you to set length of touched branch", null, getPath() + "adjustLengths.gif"));
+		registerSubfunction(new FunctionExplanation("Adjust Branch Lengths by Stretching", "(A tool of the Tree Window) By dragging, stretches branch touched", null, getPath() + "dragLengths.gif"));
+		super.getSubfunctions();
+	}
+
+}
+
+/* ======================================================================== */
+class AdjustToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool adjustTool, stretchTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	BranchLengthsAdjust selectModule;
+	Tree tree;
+	int originalX, originalY, lastX, lastY;
+	boolean lineOn = true;
+	MiniNumberEditor miniEditor;
+	double lastBL;	
+	boolean editorOn = false;
+	int editorNode = -1;
+	boolean dragMode = false; //default mode - if true,then drags branch to extend; needs modifier keys for editor; if false, opposite
+
+	public AdjustToolExtra (BranchLengthsAdjust ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		selectModule = ownerModule;
+		adjustTool = new TreeTool(this,  "adjustor", ownerModule.getPath() , "adjustLengths.gif", 2,1,"Adjust branch length", "This tool adjusts branch lengths.  When a branch is touched, a small text editing box appears in which a new branch length can be entered; touching the little blue button enters the length.  If a modifier key such as Control is held down or the Right Mouse button is used as the branch is touched, you can drag to change the length of the branch.");
+		adjustTool.setTouchedCommand(MesquiteModule.makeCommand("touchedLengthsAdjust",  this));
+		adjustTool.setDroppedCommand(MesquiteModule.makeCommand("droppedLengthsAdjust",  this));
+		adjustTool.setDraggedCommand(MesquiteModule.makeCommand("draggedLengthsAdjust",  this));
+		stretchTool = new TreeTool(this,  "stretchAdjustor", ownerModule.getPath() , "dragLengths.gif", 2,2,"Stretch branch", "This tool adjusts branch lengths by grabbing and stretching.");
+		stretchTool.setTouchedCommand(MesquiteModule.makeCommand("touchedLengthsStretch",  this));
+		stretchTool.setDroppedCommand(MesquiteModule.makeCommand("droppedLengthsStretch",  this));
+		MesquiteCommand dragCommand = MesquiteModule.makeCommand("draggedLengthsStretch",  this);
+		stretchTool.setDraggedCommand(dragCommand);
+		dragCommand.setDontDuplicate(true);
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(stretchTool);
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(adjustTool);
+		}
+	}
+	public void doTreeCommand(String command, String arguments){
+		Tree tree = treeDisplay.getTree();
+		if (!(tree instanceof MesquiteTree)){
+			MesquiteMessage.warnProgrammer("Action can't be completed since tree is not a native Mesquite tree");
+		}
+		else if (tree!=null) {
+			((MesquiteTree)tree).doCommand(command, arguments, CommandChecker.defaultChecker);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		this.tree = tree;
+		if (editorOn) {
+			if (tree.nodeExists(editorNode))
+				miniEditor.setLocation(treeDisplay.getTreeDrawing().x[editorNode], treeDisplay.getTreeDrawing().y[editorNode]);
+			else hideMiniEditor();
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+	}
+	/*.................................................................................................................*/
+	public Tree getTree() {
+		return treeDisplay.getTree();
+	}
+
+	private void setMiniEditor(int node, int x,int y){
+		Tree t = treeDisplay.getTree();
+		if (t==null)
+			return;
+		editorNode = node;
+		if (miniEditor == null) {
+			miniEditor = new MiniNumberEditor(ownerModule, ownerModule.makeCommand("acceptLength", this));
+			addPanelPlease(miniEditor);
+		}
+		miniEditor.setLocation(treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node]);
+		miniEditor.setNumber(t.getBranchLength(node));
+		miniEditor.setVisible(true);
+		editorOn = true;
+	}
+	private void hideMiniEditor(){
+		miniEditor.setVisible(false);
+		editorOn = false;
+	}
+	public void changeLengthsSelected(AdjustableTree tree, int node, double length) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			changeLengthsSelected(tree, d, length);
+		if (tree.getSelected(node))
+			tree.setBranchLength(node, length, false);
+	}
+	void stretchTouched(int node, int x, int y, String mod) {
+		Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+		originalX = newOnLine.x;
+		originalY = newOnLine.y;
+		lastBL = tree.getBranchLength(node);
+		lastX = treeDisplay.getTreeDrawing().lineTipX[node];
+		lastY = treeDisplay.getTreeDrawing().lineTipY[node];
+		int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
+		int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+			g.drawString(MesquiteDouble.toString(lastBL), lastX+10, lastY);
+			drawLine(g,ibX, ibY, lastX, lastY);
+			drawLine(g,ibX+1, ibY, lastX+1, lastY);
+			drawLine(g,ibX+2, ibY, lastX+2, lastY);
+			g.dispose();
+		}
+		lineOn=true;
+	}
+	void drawLine(Graphics g, int x, int y, int x2, int y2){
+		if (g==null)
+			return;
+		if (x==x2 && y>y2)
+			g.drawLine( x2, y2, x, y);
+		else
+			g.drawLine(x, y, x2, y2);
+	}
+	int count=0;
+	void stretchDragged(Tree t, int node, int x, int y){
+		Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+		//WARNING":  This shouldn't result in length increase if simple click and release with no drag; must subtract original X, Y
+		int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
+		int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
+		int itX = treeDisplay.getTreeDrawing().lineTipX[node];
+		int itY = treeDisplay.getTreeDrawing().lineTipY[node];
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+
+
+			double bX = ibX;
+			double bY = ibY;
+			double tX =itX;
+			double tY = itY;
+			double lengthLine =  Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
+			if (lengthLine!=0) {
+				double extension =  Math.sqrt((newOnLine.y-bY)*(newOnLine.y-bY) + (newOnLine.x-bX)*(newOnLine.x-bX))/lengthLine;
+				double bL;
+				if (t.getBranchLength(node)==0) {
+					bL = extension;
+				}
+				else{
+					if (t.branchLengthUnassigned(node))
+						bL = extension;
+					else
+						bL = t.getBranchLength(node)*extension;
+				}
+
+				drawLine(g,ibX, ibY, lastX, lastY);
+				drawLine(g,ibX+1, ibY, lastX+1, lastY);
+				drawLine(g,ibX+2, ibY, lastX+2, lastY);
+				int newX =ibX+(int)(extension*(tX-bX));
+				int newY = ibY+(int)(extension*(tY-bY));
+				if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>=1.5 && MesquiteTrunk.getJavaVersionAsDouble()<1.6)  //due to a JVM bug
+					g.fillRect(lastX, lastY-20, 100, 20);
+				g.drawString(MesquiteDouble.toString(lastBL), lastX+10, lastY);
+				if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble()>=1.5 && MesquiteTrunk.getJavaVersionAsDouble()<1.6)  //due to a JVM bug
+					g.fillRect(lastX, lastY-20, 100, 20);
+				g.drawString(MesquiteDouble.toString(bL), newX+10, newY);
+				count++;
+				lastBL = bL;
+				lastX= newX;
+				lastY = newY;
+				drawLine(g,ibX, ibY, newX, newY);
+				drawLine(g,ibX+1, ibY, newX+1, newY);
+				drawLine(g,ibX+2, ibY, newX+2, newY);
+			}
+			g.setPaintMode();
+			g.dispose();
+		}
+	}
+	void stretchDropped(MesquiteTree t, int node, int x, int y){
+		Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
+		double bX = treeDisplay.getTreeDrawing().lineBaseX[node];
+		double bY = treeDisplay.getTreeDrawing().lineBaseY[node];
+		double tX = treeDisplay.getTreeDrawing().lineTipX[node];
+		double tY = treeDisplay.getTreeDrawing().lineTipY[node];
+		double lengthLine =  Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
+		if (lengthLine!=0) {
+			double extension =  Math.sqrt((newOnLine.y-bY)*(newOnLine.y-bY) + (newOnLine.x-bX)*(newOnLine.x-bX))/lengthLine;
+			if (t.getBranchLength(node)==0) {
+				t.setBranchLength(node, extension, false);
+			}
+			else{
+				if (t.branchLengthUnassigned(node))
+					t.setBranchLength(node, extension, false);
+				else
+					t.setBranchLength(node, t.getBranchLength(node)*extension, false);
+			}
+		}
+		else
+			t.setBranchLength(node, 1, false);
+		t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+		Graphics g = treeDisplay.getGraphics();
+		g.setPaintMode(); //why is this done? getGraphics creates a new graphics object.
+		treeDisplay.pleaseUpdate(true);
+		lineOn=false;
+		if (g!=null)
+			g.dispose();
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		MesquiteTree t=null; //
+		if (treeDisplay!=null) {
+			Tree trt = treeDisplay.getTree();
+			if (trt instanceof MesquiteTree)
+				t = (MesquiteTree)trt;
+			else
+				t = null;
+		}
+		if (checker.compare(this.getClass(), "Enter the branch length of the current branch", "[length]", commandName, "acceptLength")){
+			if (t==null)
+				return null;
+			if (editorOn) {
+				if (StringUtil.blank(arguments)){
+					hideMiniEditor();
+					return null;
+				}
+
+				if ("?".equalsIgnoreCase(arguments) || "unassigned".equalsIgnoreCase(arguments)) {
+					if (t.getSelected(editorNode)) {
+						changeLengthsSelected(t, t.getRoot(), MesquiteDouble.unassigned);
+						t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+					}
+					else
+						t.setBranchLength(editorNode, MesquiteDouble.unassigned, true);
+					MesquiteModule mb = ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+					mb.doCommand("treeEdited", null, checker);
+				}
+				else {
+					double d = MesquiteDouble.fromString(arguments);
+					if (MesquiteDouble.isCombinable(d)) {
+						if (t.getSelected(editorNode)) {
+							changeLengthsSelected(t, t.getRoot(), d);
+							t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+						}
+						else {
+							t.setBranchLength(editorNode, d, true);
+						}
+						MesquiteModule mb = ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+						mb.doCommand("treeEdited", null, checker);
+					}
+				}
+			}
+			hideMiniEditor();
+		}
+		else if (checker.compare(this.getClass(), "Sets the branch length of the current branch", "[length]", commandName, "setLength")){
+			if (t==null)
+				return null;
+			if (editorNode>=0) {
+				if (StringUtil.blank(arguments))
+					return null;
+				if ("unassigned".equalsIgnoreCase(arguments)) {
+					if (t.getSelected(editorNode)) {
+						changeLengthsSelected(t, t.getRoot(), MesquiteDouble.unassigned);
+						t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+					}
+					else
+						t.setBranchLength(editorNode, MesquiteDouble.unassigned, true);
+					MesquiteModule mb = ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+					mb.doCommand("treeEdited", null, checker);
+				}
+				else {
+					double d = MesquiteDouble.fromString(arguments);
+					if (MesquiteDouble.isCombinable(d)) {
+						if (t.getSelected(editorNode)) {
+							changeLengthsSelected(t, t.getRoot(), d);
+							t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+						}
+						else {
+							t.setBranchLength(editorNode, d, true);
+						}
+						MesquiteModule mb = ownerModule.findEmployerWithDuty(TreeWindowMaker.class);
+						mb.doCommand("treeEdited", null, checker);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Touch on branch to stretch it", "[branch number] [x coordinate touched] [y coordinate touched] [modifiers]", commandName, "touchedLengthsStretch")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+			stretchTouched(node, x, y, mod);
+
+		}
+		else if (checker.compare(this.getClass(), "Touch on branch to change its length", "[branch number] [x coordinate touched] [y coordinate touched] [modifiers]", commandName, "touchedLengthsAdjust")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+
+
+			if (!treeDisplay.showBranchLengths) {
+				setMiniEditor(node, x,y);
+				return null;
+			}
+			else if (!dragMode && (mod == null || (mod.indexOf("control")<=0 && mod.indexOf("command")<=0))) { //not dragMode, no modifiers
+				setMiniEditor(node, x,y);
+				return null;
+			}
+			else if (dragMode && !(mod == null || (mod.indexOf("control")<=0 && mod.indexOf("command")<=0))) { //dragMode, modifiers
+				setMiniEditor(node, x,y);
+				return null;
+			}
+			else if (editorOn && node != editorNode)
+				return null;
+			stretchTouched(node, x, y, mod);
+
+		}
+		else if (checker.compare(this.getClass(), "Drop branch whose length is being changed.", "[branch number] [x coordinate dropped] [y coordinate dropped] ", commandName, "droppedLengthsAdjust")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				stretchDropped(t, node, x, y);
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Drop branch being stretched.", "[branch number] [x coordinate dropped] [y coordinate dropped] ", commandName, "droppedLengthsStretch")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				stretchDropped(t, node, x, y);
+			}
+		}
+
+
+		else if (checker.compare(this.getClass(),  "Drag branch whose length is being changed.", "[branch number] [current x coordinate] [current y coordinate] ", commandName, "draggedLengthsAdjust")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				stretchDragged(t, node, x, y);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Drag branch being stretched.", "[branch number] [current x coordinate] [current y coordinate] ", commandName, "draggedLengthsStretch")) {
+			if (t==null)
+				return null;
+			if (editorOn)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOn) {
+				stretchDragged(t, node, x, y);
+			}
+		}
+		return null;
+	}
+	public void turnOff() {
+
+		selectModule.extras.removeElement(this);
+		if (miniEditor != null)
+			treeDisplay.removePanelPlease(miniEditor);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/adjustLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/adjustLengths.gif
new file mode 100644
index 0000000..8759f22
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/adjustLengths.gif differ
diff --git a/Source/mesquite/trees/BranchLengthsAdjust/dragLengths.gif b/Source/mesquite/trees/BranchLengthsAdjust/dragLengths.gif
new file mode 100644
index 0000000..59c8b1f
Binary files /dev/null and b/Source/mesquite/trees/BranchLengthsAdjust/dragLengths.gif differ
diff --git a/Source/mesquite/trees/ClearBranchNames/ClearBranchNames.java b/Source/mesquite/trees/ClearBranchNames/ClearBranchNames.java
new file mode 100644
index 0000000..592f782
--- /dev/null
+++ b/Source/mesquite/trees/ClearBranchNames/ClearBranchNames.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ClearBranchNames;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ClearBranchNames extends BranchNamesAltererMult {
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+ 	/*.................................................................................................................*/
+ 	public int getVersionOfFirstRelease(){
+ 		return 250;  
+ 	}
+ 
+ 	private void convertLabels(AdjustableTree tree, int node) { 
+ 		if (tree.nodeIsInternal(node))
+ 			for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter))
+ 				convertLabels(tree, daughter);
+		tree.setNodeLabel("", node);
+ 	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+convertLabels(tree,tree.getRoot());
+	if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+				return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Clear All Node Names";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Clears all node names from the tree." ;
+   	 }
+}
diff --git a/Source/mesquite/trees/CollapseZeroToPolys/CollapseZeroToPolys.java b/Source/mesquite/trees/CollapseZeroToPolys/CollapseZeroToPolys.java
new file mode 100644
index 0000000..9ff522d
--- /dev/null
+++ b/Source/mesquite/trees/CollapseZeroToPolys/CollapseZeroToPolys.java
@@ -0,0 +1,63 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.CollapseZeroToPolys;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class CollapseZeroToPolys extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+  	void collapseZero(AdjustableTree tree, int node){
+  	 	if (tree.nodeIsInternal(node)) { 
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			collapseZero(tree, daughter);
+	  			if (tree.nodeIsInternal(daughter) && tree.getBranchLength(daughter)==0.0)
+	  				tree.collapseBranch(daughter, false);
+	   	 	}
+ 		}
+  	}
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+			collapseZero(tree, tree.getRoot());
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Collapse Zero-length Branches";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Collapses zero-length branches to yield polytomes." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/ColorBranches/32color.gif b/Source/mesquite/trees/ColorBranches/32color.gif
new file mode 100644
index 0000000..a1a5104
Binary files /dev/null and b/Source/mesquite/trees/ColorBranches/32color.gif differ
diff --git a/Source/mesquite/trees/ColorBranches/64color.gif b/Source/mesquite/trees/ColorBranches/64color.gif
new file mode 100644
index 0000000..0e501e2
Binary files /dev/null and b/Source/mesquite/trees/ColorBranches/64color.gif differ
diff --git a/Source/mesquite/trees/ColorBranches/ColorBranches.java b/Source/mesquite/trees/ColorBranches/ColorBranches.java
new file mode 100644
index 0000000..ae5f862
--- /dev/null
+++ b/Source/mesquite/trees/ColorBranches/ColorBranches.java
@@ -0,0 +1,300 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ColorBranches;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ColorBranches extends TreeDisplayAssistantI {
+	Vector extras;
+	long branchColor = ColorDistribution.numberOfRed;
+	String colorString = "Color Red";
+	long savedColor = branchColor;
+	MesquiteBoolean removeColor;
+	public String getFunctionIconPath(){
+		return getPath() + "color.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Branch paint color", makeCommand("setColor",  this), ColorDistribution.standardColorNames);
+		removeColor = new MesquiteBoolean(false);
+		addCheckMenuItem(null, "Remove color", makeCommand("removeColor",  this), removeColor);
+		addMenuItem(null, "Remove all color from branches", makeCommand("removeAllColor",  this));
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		ColorToolExtra newPj = new ColorToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setColor " + ColorDistribution.getStandardColorName(ColorDistribution.getStandardColor((int)branchColor)));
+		temp.addLine("removeColor " + removeColor.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the color to be used to paint branches", "[name of color]", commandName, "setColor")) {
+			int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments)); 
+			if (bc >=0 && MesquiteInteger.isCombinable(bc)){
+				removeColor.setValue(false);
+				branchColor = bc;
+				savedColor = bc;
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue(bc);
+				for (int i =0; i<extras.size(); i++){
+					ColorToolExtra e = (ColorToolExtra)extras.elementAt(i);
+					e.setToolText(colorString);
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Removes color from all the branches", null, commandName, "removeAllColor")) {
+			for (int i =0; i<extras.size(); i++){
+				ColorToolExtra e = (ColorToolExtra)extras.elementAt(i);
+				e.removeAllColor();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the paint brush so that it removes colors from any branches touched", null, commandName, "removeColor")) {
+			if (StringUtil.blank(arguments))
+				removeColor.setValue(!removeColor.getValue());
+			else
+				removeColor.toggleValue(parser.getFirstToken(arguments));
+
+			if (removeColor.getValue()) {
+				colorString = "Remove color";
+				branchColor = MesquiteLong.unassigned;
+			}
+			else {
+				colorString = "Color " + ColorDistribution.standardColorNames.getValue((int)branchColor);
+				branchColor = savedColor;
+			}
+			for (int i =0; i<extras.size(); i++){
+				ColorToolExtra e = (ColorToolExtra)extras.elementAt(i);
+				e.setToolText(colorString);
+			}
+
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Color Branches";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to color branches in a tree window.";
+	}
+}
+
+/* ======================================================================== */
+class ColorToolExtra extends TreeDisplayExtra implements Commandable  {
+	public TreeTool colorTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	ColorBranches colorModule;
+	MesquiteTree tree;
+	NameReference colorNameRef;
+	public ColorToolExtra (ColorBranches ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		colorModule = ownerModule;
+		colorNameRef = NameReference.getNameReference("color");
+		colorTool = new TreeTool(this, "ColorBranches", ownerModule.getPath(), "color.gif", 1,1,colorModule.colorString, "This tool colors the branches of the tree.  This has cosmetic effect only.  The color painted can be changed using the Branch Colors submenu.  Control-click colors the branch and the clade desdendant from it; Shift-click shrink wraps the color. ");
+		colorTool.setTouchedCommand(MesquiteModule.makeCommand("colorBranch",  this));
+		colorTool.setTouchedTaxonCommand(MesquiteModule.makeCommand("colorTaxon",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(colorTool);
+			colorTool.setPopUpOwner(ownerModule);
+			ownerModule.setUseMenubar(false); //menu available by touching button
+		}
+	}
+	/*.................................................................................................................*/
+	private boolean anyColored(Tree tree, int node, long targetColor){
+		if (tree.getAssociatedLong(colorNameRef, node)== targetColor)
+			return true;
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			if (anyColored(tree, daughter, targetColor))
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	private void wrapColors(MesquiteTree tree, int node, boolean coloredBelow, long targetColor){
+		if (coloredBelow)
+			tree.setAssociatedLong(colorNameRef, node, colorModule.branchColor, true);
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			wrapColors(tree, daughter, coloredBelow || tree.getAssociatedLong(colorNameRef, node) == targetColor, targetColor);
+		}
+	}
+	/*.................................................................................................................*/
+	private void coloredTwiceAbove(MesquiteTree tree, int node, long targetColor){
+		int numColoredAbove = 0;
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			coloredTwiceAbove(tree, daughter, targetColor);
+			if (anyColored(tree, daughter, targetColor))
+				numColoredAbove ++;
+		}
+		if (numColoredAbove>1)
+			tree.setAssociatedLong(colorNameRef, node, colorModule.branchColor, true);
+	}
+	/*.................................................................................................................*/
+	void setToolText(String s){
+		colorTool.setDescription(s);
+		if (colorModule.containerOfModule() instanceof MesquiteWindow) 
+			((MesquiteWindow)colorModule.containerOfModule()).toolTextChanged();
+
+	}
+	/*.................................................................................................................*/
+	private void shrinkWrapSelections(MesquiteTree tree, int node){
+		coloredTwiceAbove(tree, node, colorModule.branchColor);
+		wrapColors(tree, node, false, colorModule.branchColor);
+	}
+	/*.................................................................................................................*/
+	private void removeColorClade(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			removeColorClade(tree, daughter);
+		}
+		removeColor(node);
+	}
+	/*.................................................................................................................*/
+	private void colorClade(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			colorClade(tree, daughter);
+		}
+		setColor(node);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		//remember which colored
+		return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	void removeAllColor(){
+		if (tree == null)
+			return;
+		removeColorClade(tree, tree.getRoot());
+		tree.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+		treeDisplay.pleaseUpdate(false);
+
+	}
+	private void setColor(int node){
+		if (tree == null)
+			return;
+		if (tree.getWhichAssociatedLong(colorNameRef)==null)
+			tree.makeAssociatedLongs("color");
+		if (!colorModule.removeColor.getValue())
+			tree.setAssociatedLong(colorNameRef, node, colorModule.branchColor, true);
+		else
+			tree.setAssociatedLong(colorNameRef, node, MesquiteLong.unassigned, true);
+	}
+	private void removeColor(int node){
+		tree.setAssociatedLong(colorNameRef, node, MesquiteLong.unassigned, true);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Color branch with current paint color", "[branch number][x coordinate touched][y coordinate touch][modifiers]", commandName, "colorBranch")) {
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (branchFound<=0)
+				return null;
+			if (arguments.indexOf("shift")>=0) {  //color smallest containing clade
+				if (tree.getAssociatedLong(colorNameRef, branchFound)!=colorModule.branchColor) {
+					setColor(branchFound);
+					shrinkWrapSelections(tree, tree.getRoot());
+				}
+				else
+					tree.deassignAllAssociatedLongs(colorNameRef);
+				tree.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (arguments.indexOf("control")>=0) {  //color clade
+				colorClade(tree, branchFound);
+				tree.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (branchFound >0) {
+				if (tree.getAssociatedLong(colorNameRef, branchFound)!=colorModule.branchColor)
+					setColor(branchFound);
+				else
+					removeColor(branchFound);
+				tree.notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Color taxon with current paint color", "[taxon number][x coordinate touched][y coordinate touch][modifiers]", commandName, "colorTaxon")) {
+			int taxon= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (taxon<=0)
+				return null;
+			setTaxonColor(taxon);
+			
+			tree.getTaxa().notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+			treeDisplay.pleaseUpdate(false);
+			
+		}
+		return null;
+	}
+	private void setTaxonColor(int taxon){
+		if (tree == null)
+			return;
+		Taxa taxa = tree.getTaxa();
+		if (taxa.getWhichAssociatedLong(colorNameRef)==null)
+			taxa.makeAssociatedLongs("color");
+		if (!colorModule.removeColor.getValue())
+			taxa.setAssociatedLong(colorNameRef, taxon, colorModule.branchColor, true);
+		else
+			taxa.setAssociatedLong(colorNameRef, taxon, MesquiteLong.unassigned, true);
+	}
+	public void turnOff() {
+		colorModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/trees/ColorBranches/color.gif b/Source/mesquite/trees/ColorBranches/color.gif
new file mode 100644
index 0000000..417c483
Binary files /dev/null and b/Source/mesquite/trees/ColorBranches/color.gif differ
diff --git a/Source/mesquite/trees/ConstrainNodeAge/32anchorTool.gif b/Source/mesquite/trees/ConstrainNodeAge/32anchorTool.gif
new file mode 100644
index 0000000..1c2ac5b
Binary files /dev/null and b/Source/mesquite/trees/ConstrainNodeAge/32anchorTool.gif differ
diff --git a/Source/mesquite/trees/ConstrainNodeAge/64anchorTool.gif b/Source/mesquite/trees/ConstrainNodeAge/64anchorTool.gif
new file mode 100644
index 0000000..3d7cbc5
Binary files /dev/null and b/Source/mesquite/trees/ConstrainNodeAge/64anchorTool.gif differ
diff --git a/Source/mesquite/trees/ConstrainNodeAge/ConstrainNodeAge.java b/Source/mesquite/trees/ConstrainNodeAge/ConstrainNodeAge.java
new file mode 100644
index 0000000..949803b
--- /dev/null
+++ b/Source/mesquite/trees/ConstrainNodeAge/ConstrainNodeAge.java
@@ -0,0 +1,299 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ConstrainNodeAge;
+/*~~  */
+import java.awt.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ConstrainNodeAge extends TreeDisplayAssistantI {
+	public Vector extras;
+	public boolean first = true;
+	static NameReference nodeAgeConstrRef = NameReference.getNameReference("nodeAgeConstraints");
+
+	public int getVersionOfFirstRelease(){
+		return 270;  
+	}
+	public String getFunctionIconPath(){
+		return getPath() + "anchorTool.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		setUseMenubar(false); //menu available by touching button
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		BranchNotesToolExtra newPj = new BranchNotesToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Node Age Constraints";
+	}
+	public boolean isPrerelease(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Supplies a tool for tree windows to set node age constraints.  A short text string summarizes constraints.  E.g. to say minimum age is 2.0, enter \"2.0+\".  To say range is 2.0 to 4.0, enter \"2.0-4.0\".  To say maximum is 4.0, enter \"0.0-4.0\".  To say age is exactly 3.0, enter \"3.0\"" ;
+	}
+	public boolean isSubstantive(){
+		return false;
+	}   	 
+}
+
+/* ======================================================================== */
+class BranchNotesToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool nodeAgeConstrTool;
+	ConstrainNodeAge nodeAgeConstrModule;
+	//MesquiteLabel message;
+	MesquiteCommand branchCommand;
+	MiniStringEditor miniEditor;
+	boolean editorOn = false;
+	int editorNode = -1;
+	Image anchor;
+	Font small = new Font("SanSerif", Font.PLAIN, 9);
+
+	public BranchNotesToolExtra (ConstrainNodeAge ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		anchor = MesquiteImage.getImage(ownerModule.getPath() + "anchor.gif");
+		nodeAgeConstrModule = ownerModule;
+		nodeAgeConstrTool = new TreeTool(this, "NodeAgeConstraint", ownerModule.getPath(), "anchorTool.gif", 1,1,"Node Age Constraints", "This tool allows you to edit constraints on the ages of nodes of the tree.  Enter one number for fixed age; 0-max for maximum age; min+ for minimum; min-max for range."); 		branchCommand = MesquiteModule.makeCommand("editNodeAgeConstraint",  this);
+		nodeAgeConstrTool.setTouchedCommand(branchCommand);
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(nodeAgeConstrTool);
+		//	nodeAgeConstrTool.setPopUpOwner(ownerModule);
+		}
+	
+	}
+	StringInABox box = new StringInABox( "", treeDisplay.getFont(),150);
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int node, Graphics g) {
+		if (editorOn && node == editorNode) {
+			if (tree.nodeExists(editorNode))
+				miniEditor.setLocation(treeDisplay.getTreeDrawing().x[editorNode], treeDisplay.getTreeDrawing().y[editorNode]);
+			else hideMiniEditor();
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			drawOnTree(tree, d, g);
+		drawAtNode(tree, node, g, false);
+	}
+	void drawHS(Graphics g, String s, int x, int y){
+		g.setColor(Color.white);
+		g.drawString(s, x+1,y+1);
+		g.drawString(s, x-1,y+1);
+		g.drawString(s, x+1,y-1);
+		g.drawString(s, x-1,y-1);
+		g.setColor(Color.black);
+		g.drawString(s, x,y);
+	}
+	void drawAtNode(Tree tree, int node, Graphics g, boolean mouse){
+		if (getConstraints(tree, node)!=null) {
+			Font f = g.getFont();
+			g.setFont(small);
+			int x = treeDisplay.getTreeDrawing().x[node];
+			int y = treeDisplay.getTreeDrawing().y[node];
+			g.drawImage(anchor, x, y, treeDisplay);
+			//if (mouse){
+			//	g.drawString("age", x+11, y + 8);
+			//}
+			//else {
+			String constraint = getConstraints(tree, node);
+			drawHS(g, constraint, x+11, y + 9);
+			//}
+			//StringUtil.highlightString(g, constraint, x+10, y + 10, Color.black, Color.white);
+			g.setFont(f);
+			//box.setColors(Color.red, Color.white);
+			//box.setString("^ " +note);
+			//box.draw(g,  x, y);
+		}
+	}
+	private void setMiniEditor(int node, int x,int y){
+		Tree t = treeDisplay.getTree();
+		if (t==null)
+			return;
+		editorNode = node;
+		if (miniEditor == null) {
+			miniEditor = new MiniStringEditor(ownerModule, ownerModule.makeCommand("acceptAge", this));
+			addPanelPlease(miniEditor);
+		}
+		miniEditor.setLocation(treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node]);
+		miniEditor.setText(getConstraints(t, node));
+		miniEditor.setVisible(true);
+		miniEditor.prepare();
+		editorOn = true;
+	}
+	private void hideMiniEditor(){
+		miniEditor.setVisible(false);
+		editorOn = false;
+	}
+
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (getConstraints(tree, node)!=null)
+			return "*(" + node + ")";
+		else
+			return null;
+	}
+	/*.................................................................................................................*/
+	void getAllConstraints(Tree tree, int node, StringBuffer sb) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			getAllConstraints(tree, d, sb);
+		String note = getConstraints(tree, node);
+		if (note!=null) {
+			sb.append("*(" + node + "): " + note + "\n");
+		}
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		StringBuffer sb = new StringBuffer(100);
+		getAllConstraints(treeDisplay.getTree(), treeDisplay.getTree().getRoot(), sb);
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		//drawOnTree(tree, drawnRoot, g); //should draw numbered footnotes!
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	String getConstraints(Tree tree, int node){
+		return (String)tree.getAssociatedObject(ConstrainNodeAge.nodeAgeConstrRef, node);
+	}
+	Parser parser = new Parser();
+
+	void setNote(Tree tree, int node, String note){
+		if (tree instanceof Associable){
+			((Associable)tree).setAssociatedObject(ConstrainNodeAge.nodeAgeConstrRef, node, note);
+			((Associable)tree).notifyListeners(this, new Notification(MesquiteListener.ANNOTATION_CHANGED));
+
+		}
+	}
+	//boolean shown = false;
+	/**to inform TreeDisplayExtra that cursor has just entered name of terminal taxon M*/
+	public void cursorEnterTaxon(Tree tree, int M, Graphics g){
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited name of terminal taxon M*/
+	public void cursorExitTaxon(Tree tree, int M, Graphics g){
+	}
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){
+		drawAtNode(tree, N, g, true);
+		/**
+		if (nodeAgeConstrTool.getInUse()){
+			String link = getConstraints(tree, N);
+			if (link!=null) {
+				shown = true;
+				message.setLocation(treeDisplay.getTreeDrawing().x[N], treeDisplay.getTreeDrawing().y[N]);
+				message.setText(link);
+				message.setVisible(true);
+				message.setCommand(branchCommand);
+				message.setArguments(Integer.toString(N));
+			}
+		}
+		/**/
+	}
+	/**to inform TreeDisplayExtra that cursor has just exited branch N*/
+	public void cursorExitBranch(Tree tree, int N, Graphics g){
+		drawAtNode(tree, N, g, false);
+		/*if (shown) {
+			message.setVisible(false);
+			//message.setSize(4,4);
+		}
+		shown = false;*/
+	}
+
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(this.getClass(), "Edits the node age constraints for the node", "[node number]", commandName, "editNodeAgeConstraint")) {
+			Tree tree = treeDisplay.getTree();
+			if (!(tree instanceof Associable)){
+				ownerModule.alert("Sorry, this is not a standard Mesquite tree, and you can't edit its node age constraints");
+				return null;
+			}
+			int M = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (M<0 || !MesquiteInteger.isCombinable(M))
+				return null;
+			int x= MesquiteInteger.fromString(arguments, pos);
+			int y= MesquiteInteger.fromString(arguments, pos);
+			String mod= ParseUtil.getRemaining(arguments, pos);
+			setMiniEditor(M, x,y);
+			return null;
+		}
+		else if (checker.compare(this.getClass(), "Enter the constraint of the current node", "[age]", commandName, "acceptAge")){
+			Tree tree = treeDisplay.getTree();
+			if (!(tree instanceof Associable)){
+				ownerModule.alert("Sorry, this is not a standard Mesquite tree, and you can't edit its node age constraints");
+				return null;
+			}
+			if (tree==null)
+				return null;
+			if (editorOn) {
+				if (StringUtil.blank(arguments)){
+					setNote(tree, editorNode, null);
+					hideMiniEditor();
+					return null;
+				}
+
+				if (arguments == null || "".equalsIgnoreCase(arguments) || "?".equalsIgnoreCase(arguments) || "unassigned".equalsIgnoreCase(arguments)) {
+					setNote(tree, editorNode, null);
+				}
+				else {
+					String minS = parser.getFirstToken(arguments);
+					String to = parser.getNextToken();
+
+					String maxS = parser.getNextToken();
+					if (to != null && to.equals("+")){
+						double min = MesquiteDouble.fromString(minS);
+						if (MesquiteDouble.isCombinable(min)) {
+							setNote(tree, editorNode, minS + "+");
+						}
+					}
+					else {
+						if (to != null && to.length()>1 && to.charAt(0) == '-')
+							maxS = to.substring(1, to.length());
+						double min = MesquiteDouble.fromString(minS);
+						double max = MesquiteDouble.fromString(maxS);
+						if (MesquiteDouble.isCombinable(min)) {
+							if (MesquiteDouble.isCombinable(max))
+								setNote(tree, editorNode, minS + "-" + maxS);
+							else
+								setNote(tree, editorNode, minS);
+						}
+					}
+				}
+			}
+			hideMiniEditor();
+		}
+		/**
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	/**/
+
+		return null;
+	}
+	public void turnOff() {
+		nodeAgeConstrModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
diff --git a/Source/mesquite/trees/ConstrainNodeAge/anchor.gif b/Source/mesquite/trees/ConstrainNodeAge/anchor.gif
new file mode 100644
index 0000000..4b249bc
Binary files /dev/null and b/Source/mesquite/trees/ConstrainNodeAge/anchor.gif differ
diff --git a/Source/mesquite/trees/ConstrainNodeAge/anchorTool.gif b/Source/mesquite/trees/ConstrainNodeAge/anchorTool.gif
new file mode 100644
index 0000000..1bd49b4
Binary files /dev/null and b/Source/mesquite/trees/ConstrainNodeAge/anchorTool.gif differ
diff --git a/Source/mesquite/trees/ConstrainNodeAge/anchorWide.gif b/Source/mesquite/trees/ConstrainNodeAge/anchorWide.gif
new file mode 100644
index 0000000..31ebbaa
Binary files /dev/null and b/Source/mesquite/trees/ConstrainNodeAge/anchorWide.gif differ
diff --git a/Source/mesquite/trees/DeassignBranchLengths/DeassignBranchLengths.java b/Source/mesquite/trees/DeassignBranchLengths/DeassignBranchLengths.java
new file mode 100644
index 0000000..a67608a
--- /dev/null
+++ b/Source/mesquite/trees/DeassignBranchLengths/DeassignBranchLengths.java
@@ -0,0 +1,57 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.DeassignBranchLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DeassignBranchLengths extends BranchLengthsAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+  	 		if (tree instanceof MesquiteTree) {
+   				((MesquiteTree)tree).doCommand("deassignAllBranchLengths", null, CommandChecker.defaultChecker);
+				if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+			
+				return true;
+			}
+			return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Deassign Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets lengths of a tree's branches to unassigned." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/DefaultTrees/DefaultTrees.java b/Source/mesquite/trees/DefaultTrees/DefaultTrees.java
new file mode 100644
index 0000000..0e037a2
--- /dev/null
+++ b/Source/mesquite/trees/DefaultTrees/DefaultTrees.java
@@ -0,0 +1,153 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.DefaultTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies default trees (e.g., ladder, bush).  Used as a last resort tree source. */
+public class DefaultTrees extends TreeSource {  
+	int currentTree=0; //AS OF 1. 06 the default is symmetrical to prevent deepest recursions with large trees (StackOverflowError)
+	Taxa currentTaxa;
+	static int BUSH = 1;
+	static int LADDER = 2;
+	static int SYMM = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmeticOrSelection(notification))
+			return;
+		if (obj == currentTaxa) {
+				parametersChanged(notification);
+		}
+	}
+	 public boolean permitSeparateThreadWhenFilling(){
+		 return false;
+	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   	 
+   	 void formSymmetricalClade(MesquiteTree tree, int minTaxon, int maxTaxon){
+ 		int range = maxTaxon-minTaxon + 1;
+ 		if (range > 1) {
+ 			int newRight = minTaxon + range/2;
+ 			tree.splitTerminal(minTaxon, newRight, false);
+ 			formSymmetricalClade(tree, minTaxon, newRight -1);
+ 			formSymmetricalClade(tree, newRight, maxTaxon);
+ 		}
+   	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+	 		if (currentTaxa!=null)
+	  			currentTaxa.removeListener(this);
+	  		currentTaxa = taxa;
+  			if (taxa != null)
+  				currentTaxa.addListener(this);
+  	}
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		super.endJob();
+	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+   	public Tree getTree(Taxa taxa, int itree) {
+   		if (taxa == null)
+   			return null;
+   		currentTree = itree;
+   		if (itree==BUSH) {
+			MesquiteTree tree = new MesquiteTree(taxa);
+			tree.setToDefaultBush(taxa.getNumTaxa(), false);
+			tree.setName("Default bush");
+	   		return tree;
+   		}
+   		else if (itree==LADDER) {
+			MesquiteTree tree = new MesquiteTree(taxa);
+			tree.setToDefaultLadder(taxa.getNumTaxa(), false);
+			tree.setName("Default ladder");
+	   		return tree;
+   		}
+   		else { //Symmetrical
+   			int numTaxa = taxa.getNumTaxa();
+			MesquiteTree tree = new MesquiteTree(taxa);
+			if (numTaxa == 1){
+				tree.setToDefaultBush(1, false);
+				return tree;
+			}
+			tree.setToDefaultBush(2, false);
+			int secondHalf = numTaxa/2;
+			int rightNode = tree.nextSisterOfNode(tree.firstDaughterOfNode(tree.getRoot()));
+			tree.setTaxonNumber(rightNode, secondHalf, false);
+			formSymmetricalClade(tree, 0, secondHalf-1);
+			formSymmetricalClade(tree, secondHalf, tree.getTaxa().getNumTaxa()-1);
+			tree.setName("Default symmetrical");
+	   		return tree;
+   		}
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return 3;
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeNameString(Taxa taxa, int itree) {
+   		if (itree==BUSH)
+			return "Default bush";
+		else if (itree==LADDER)
+			return "Default ladder";
+		else
+			return "Default symmetrical";
+   	}
+	/*.................................................................................................................*/
+   	public String getCurrentTreeNameString() {
+   		if (currentTree==BUSH)
+			return "Default bush";
+		else if (currentTree==LADDER)
+			return "Default ladder";
+		else
+			return "Default symmetrical";
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Default Trees";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies simple default trees (bush, ladder).";
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/trees/DefiniteTreeSource/DefiniteTreeSource.java b/Source/mesquite/trees/DefiniteTreeSource/DefiniteTreeSource.java
new file mode 100644
index 0000000..fc16320
--- /dev/null
+++ b/Source/mesquite/trees/DefiniteTreeSource/DefiniteTreeSource.java
@@ -0,0 +1,259 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.DefiniteTreeSource;
+/*~~  */
+
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class DefiniteTreeSource extends TreeSourceDefinite implements NameHolder {
+	public String getName() {
+		return "Definite Tree Source";
+	}
+	public String getNameForMenuItem() {
+		return "Source of trees...";
+	}
+	public String getExplanation() {
+		return "Supplies trees from from a tree source, arranged to be a definite number";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSource.class, getName() + " presents a source of trees as if it had a definite number of trees.",
+		"The source of trees can be chosen initially, or using the Tree Source submenu");
+	}
+	/*.................................................................................................................*/
+	TreeSource treeSource;
+	MesquiteString treeSourceName;
+	MesquiteCommand cstC;
+	Taxa taxa = null;
+	int numTreesAssigned = MesquiteInteger.unassigned;
+	int defaultNumberOfItems = 100;
+	boolean wasDefinite = true;
+	boolean assigned = false;
+	private MesquiteMenuItemSpec numTreesItem;
+	MesquiteSubmenuSpec mss;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		String exp, mexp;
+		if (getExplanationByWhichHired()!=null) {
+			exp = getExplanationByWhichHired();
+			mexp = exp;
+		}
+		else {
+			exp = "Source of trees  (for " + getEmployer().getName() + ")";
+			mexp = "Tree Source  (for " + getEmployer().getName() + ")";
+		}
+		if (arguments != null)
+			treeSource = (TreeSource)hireNamedEmployee(TreeSource.class, arguments);
+		if (treeSource == null)
+			treeSource = (TreeSource)hireEmployee(TreeSource.class, exp);
+		if (treeSource == null)
+			return sorry(getName() + " couldn't start because no source of trees was obtained.");
+		treeSourceName = new MesquiteString(treeSource.getName());
+		cstC = makeCommand("setTreeSource",  this);
+		treeSource.setHiringCommand(cstC);
+		if (numModulesAvailable(TreeSource.class)>1){
+			mss = addSubmenu(null, mexp, cstC, TreeSource.class);
+			mss.setNameHolder(this);
+			mss.setSelected(treeSourceName);
+		}
+		return true;
+	}
+	public String getMyName(Object obj){
+		if (obj == mss)
+			return "Source of Trees " + whatIsMyPurpose();
+		return null;
+	}
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis").*/
+	public String purposeOfEmployee(MesquiteModule employee){
+		return whatIsMyPurpose(); //transfers info to employer, as ithis is coordinator
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == treeSource)  // character source quit and none rehired automatically
+			iQuit();
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeSource", treeSource);
+		if (MesquiteInteger.isCombinable(numTreesAssigned))
+			temp.addLine("assignNumTrees " + numTreesAssigned);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void resetTreeSource(Taxa taxa, boolean queryPlease){
+		int numItems=treeSource.getNumberOfTrees(taxa, true);
+
+		if (!MesquiteInteger.isCombinable(numItems)) { //not specified; need to set
+			if (queryPlease || (wasDefinite && !assigned)) {
+				if (!assigned)
+					numTreesAssigned = defaultNumberOfItems;
+				if (!MesquiteThread.isScripting()) {
+					numTreesAssigned = MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees", "Number of trees  (for " + getEmployer().getName() + ")", numTreesAssigned);
+					if (!MesquiteInteger.isCombinable(numTreesAssigned)) 
+						numTreesAssigned = defaultNumberOfItems;
+				}
+			}
+			wasDefinite = false;
+			assigned = true;
+			if (numTreesItem == null) {
+				numTreesItem = addMenuItem( "Number of  Trees...", makeCommand("assignNumTrees",  this));
+				resetContainingMenuBar();
+			}
+		}
+		else  {
+			if (numTreesItem!= null) {
+				deleteMenuItem(numTreesItem);
+				resetContainingMenuBar();
+				numTreesItem = null;
+			}
+			wasDefinite = true;
+			assigned = false;
+			numTreesAssigned = numItems;
+
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying trees", "[name of module]", commandName, "setTreeSource")) {
+			TreeSource newtreeSource;
+			newtreeSource =  (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees", treeSource);
+			if (newtreeSource!=null) {
+				treeSource = newtreeSource;
+				treeSource.setHiringCommand(cstC);
+				treeSourceName.setValue(treeSource.getName());
+				parametersChanged(); 
+				return treeSource;
+			}
+			else {
+				discreetAlert( "Unable to activate tree source \"" + arguments + "\"  for use by " + employer.getName());
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of trees", "[number of trees]", commandName, "assignNumTrees")) {
+			int newNum = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(newNum) && newNum>0 ) {
+				numTreesAssigned = newNum;
+				assigned = true;
+			}
+			else {
+				resetTreeSource(taxa, true);
+			}
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		this.taxa = taxa;
+		treeSource.setPreferredTaxa(taxa);
+	}
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		treeSource.initialize(taxa);
+	}
+
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		return treeSource.getTree(taxa, itree);
+	}
+
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		resetTreeSource(taxa, false);
+		return numTreesAssigned;
+	}
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		return treeSource.getTreeNameString(taxa, itree);
+	}
+	public Selectionable getSelectionable() {
+		if (treeSource!=null)
+			return treeSource.getSelectionable();
+		else
+			return null;
+	}
+	public void setEnableWeights(boolean enable){
+		if (treeSource!=null)
+			treeSource.setEnableWeights(enable);
+	}
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (treeSource!=null)
+			return treeSource.itemsHaveWeights(taxa);
+		return false;
+	}
+	public double getItemWeight(Taxa taxa, int ic){
+		if (treeSource!=null)
+			return treeSource.getItemWeight(taxa, ic);
+		return MesquiteDouble.unassigned;
+	}
+	public void prepareItemColors(Taxa taxa){
+		if (treeSource!=null)
+			treeSource.prepareItemColors(taxa);
+	}
+	public Color getItemColor(Taxa taxa, int ic){
+		if (treeSource!=null)
+			return treeSource.getItemColor(taxa, ic);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (treeSource==null)
+			return null;
+		return treeSource.getName() + " (" + treeSource.getParameters() + ")";
+	}
+	public String getNameAndParameters() {
+		return treeSource.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		parametersChanged(notification);
+	}
+	/*.................................................................................................................*/
+
+}
+
+
diff --git a/Source/mesquite/trees/DependentTreeWindow/DependentTreeWindow.java b/Source/mesquite/trees/DependentTreeWindow/DependentTreeWindow.java
new file mode 100644
index 0000000..7338a08
--- /dev/null
+++ b/Source/mesquite/trees/DependentTreeWindow/DependentTreeWindow.java
@@ -0,0 +1,567 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.DependentTreeWindow;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DependentTreeWindow extends TreeWindowAssistantN implements TreeDisplayActive {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DrawTreeCoordinator.class, getName() + "  needs a module to coordinate tree drawing.",
+		"This is arranged automatically");
+	}
+	/*.................................................................................................................*/
+	public DrawTreeCoordinator treeDrawCoordTask;
+	DepTreeWindow dependentTreeWindow;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(DrawTreeCoordinator.class, null);
+		if (treeDrawCoordTask == null)
+			return sorry(getName() + " couldn't start because no tree draw coordinator module found");
+		makeMenu("Dependent");
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m==treeDrawCoordTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (source instanceof DrawTreeCoordinator){ //ignores since this should have directly called to update tree display
+			return;
+		}
+		if (dependentTreeWindow != null)
+			dependentTreeWindow.refresh();
+
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (dependentTreeWindow == null){
+			dependentTreeWindow= new DepTreeWindow( this, treeDrawCoordTask, tree.getTaxa());
+			setModuleWindow(dependentTreeWindow);
+			resetContainingMenuBar();
+			employer.resetContainingMenuBar();
+			resetAllWindowsMenus();
+			dependentTreeWindow.sizeDisplays();
+			if (!MesquiteThread.isScripting())
+				dependentTreeWindow.setVisible(true);
+		}
+		dependentTreeWindow.setTree(tree);
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (dependentTreeWindow ==null)
+			return null;
+		Snapshot fromWindow = dependentTreeWindow.getSnapshot(file);
+		if (fromWindow == null || fromWindow.getNumLines() ==0)
+			return null;
+		Snapshot sn = new Snapshot();
+		sn.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
+		sn.addLine("getWindow");
+		sn.addLine("tell It");
+		sn.incorporate(fromWindow, true);
+		sn.addLine("endTell");
+		sn.addLine("showWindow");
+
+		return sn;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module coordinating tree drawing", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDownInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (!treeDisplay.getTree().isLocked())
+			return dependentTreeWindow.ScanTouch(treeDisplay, g, x, y, modifiers);
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseUpInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseMoveInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (!treeDisplay.getTree().isLocked())
+			dependentTreeWindow.ScanFlash(treeDisplay, g, x, y, modifiers);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDragInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Dependent Tree Window";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Displays a single tree (the same as in a tree window)." ;
+	}
+
+
+}
+
+/* ======================================================================== */
+class DepTreeWindow extends MesquiteWindow implements Commandable, MesquiteListener  {
+	public TreeDisplay treeDisplay;
+	public DrawTreeCoordinator treeDrawCoordTask;
+	int totalWidth;
+	int totalHeight;
+	int firstTree=0;
+	public MessagePanel messagePanel;
+	Taxa taxa;
+	DepTreeExtra extra;
+	public int highlightedBranch=0;
+	TreeTool arrowTool;
+	String defaultExplanation;
+	public DepTreeWindow ( MesquiteModule ownerModule, DrawTreeCoordinator treeDrawCoordTask, Taxa taxa){
+		super(ownerModule, true); //infobar
+		this.treeDrawCoordTask = treeDrawCoordTask;
+		setShowExplanation(true);
+		defaultExplanation = "This window shows the same tree as seen in ";
+		MesquiteWindow eW = ownerModule.getEmployer().getModuleWindow();
+		if (eW !=null)
+			defaultExplanation += eW.getTitle();
+		else
+			defaultExplanation += "a Tree Window";
+		setExplanation(defaultExplanation);
+		setWindowSize(500,400);
+		this.ownerModule = ownerModule;
+		//setLayout( null );
+		arrowTool = new TreeTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(),"arrow.gif", 4,2,"Select", null);
+		arrowTool.setIsArrowTool(true);
+		arrowTool.setTouchedCommand(MesquiteModule.makeCommand("arrowTouch",  this));
+		addTool(arrowTool);
+		setCurrentTool(arrowTool);
+		if (arrowTool!=null)
+			arrowTool.setInUse(true);
+		setBackground(Color.white);
+		messagePanel=new MessagePanel(getColorScheme());
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+		this.taxa =taxa;
+		taxa.addListener(this);
+		MesquiteSubmenuSpec mss = ownerModule.addSubmenu(null, "Analysis", MesquiteModule.makeCommand("newAssistant",  this), TreeDisplayAssistantA.class);
+		mss = ownerModule.addSubmenu(null, "Display", MesquiteModule.makeCommand("newAssistantD",  this), TreeDisplayAssistantD.class);
+		treeDisplay =treeDrawCoordTask.createOneTreeDisplay(taxa, this); //TODO: set tree display when tree is set for first time
+		sizeDisplays();
+		addToWindow(treeDisplay);
+		extra = new DepTreeExtra(ownerModule, treeDisplay, this);
+		treeDisplay.addExtra(extra);
+		addAssistantsDI(ownerModule);
+		resetTitle();
+	}
+	protected void addAssistantsDI(MesquiteModule ownerModule){
+		ownerModule.hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration e = ownerModule.getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistant tda = (TreeDisplayAssistant)obj;
+				treeDrawCoordTask.addAssistantTask(tda);
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplay);
+				if (tce!=null) { 
+					treeDisplay.addExtra(tce);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Dependent Tree Window"); //TODO: what tree?
+	}
+	/*.................................................................................................................*/
+	public int getNumSnapshotLines(MesquiteFile file) {
+		int tot = 0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+			Object e=ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof TreeDisplayAssistantA) {
+				tot++;
+			}
+		}
+		return tot;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.incorporate(super.getSnapshot(file), false);
+		ListableVector extras = treeDisplay.getExtras();
+		if (extras!=null) {
+			Enumeration enumeration=extras.elements();
+			while (enumeration.hasMoreElements()){
+				TreeDisplayExtra tde = (TreeDisplayExtra)enumeration.nextElement();
+				MesquiteModule mb = tde.getOwnerModule();
+				if (mb instanceof TreeDisplayAssistantA) {
+					temp.addLine("newAssistant", mb);
+				}
+				else if (mb instanceof TreeDisplayAssistantD) {
+					temp.addLine("newAssistantD", mb);
+				}
+			}
+		}
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires new assistant module (TreeDisplayAssistantA)", "[name of module]", commandName, "newAssistant")) {
+			TreeDisplayAssistantA tda= (TreeDisplayAssistantA)ownerModule.hireNamedEmployee(TreeDisplayAssistantA.class, arguments);
+			if (tda!=null){
+				treeDrawCoordTask.addAssistantTask(tda);
+
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplay);
+				tce.setTree(treeDisplay.getTree());
+				treeDisplay.addExtra(tce);
+				treeDisplay.repaint();
+				return tda;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires new assistant module (TreeDisplayAssistantA)", "[name of module]", commandName, "newAssistantD")) {
+			TreeDisplayAssistantD tda= (TreeDisplayAssistantD)ownerModule.hireNamedEmployee(TreeDisplayAssistantD.class, arguments);
+			if (tda!=null){
+				treeDrawCoordTask.addAssistantTask(tda);
+
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplay);
+				tce.setTree(treeDisplay.getTree());
+				treeDisplay.addExtra(tce);
+				treeDisplay.repaint();
+				return tda;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets size of window", "[width in pixels of window] [height in pixels of window]", commandName, "setSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int width= MesquiteInteger.fromString(arguments, io);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(width) && MesquiteInteger.isCombinable(height)) {
+				fromScriptCommand = true;//this is needed to counteract difficulties with popping in/out and size setting in window constructors
+				setWindowSize(width, height);
+				fromScriptCommand = false;
+				sizeDisplays();
+				treeDisplay.redoCalculations(354);
+				treeDisplay.forceRepaint();
+
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void sizeDisplays(){
+		if (treeDisplay == null)
+			return;
+		totalWidth = getWidth();
+		totalHeight = getHeight() - 16;
+		treeDisplay.setLocation(0,0);
+		treeDisplay.setSize(totalWidth,totalHeight);
+		treeDisplay.setFieldSize(totalWidth,totalHeight);
+		treeDisplay.setVisRect(new Rectangle(0, 0, totalWidth,totalHeight));
+		messagePanel.setSize(totalWidth, 16);
+		messagePanel.setLocation(0, totalHeight);
+		Component[] cc = treeDisplay.getComponents();
+		if (cc!=null && cc.length>0)
+			for (int i=0; i<cc.length; i++) {
+				if (cc[i] instanceof Legend){ //make sure legends are in bounds
+					//adjustLocation
+					Legend legend = (Legend)cc[i];
+				
+						legend.setConstrainingRectangle(treeDisplay.getBounds()); //treeDisplay.getBounds()
+				
+					legend.adjustLocation();
+				}
+			}
+		treeDisplay.redoCalculations(4417);
+		treeDisplay.forceRepaint();
+	}
+	public void refresh(){
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*.................................................................................................................*/
+	public void setTree(Tree newTree){
+		Tree tree;
+		if (newTree!=null) {
+			if (treeDisplay.getTree()!=null)
+				treeDisplay.getTree().dispose();
+			if (taxa != newTree.getTaxa()){
+				if (taxa != null)
+					taxa.removeListener(this);
+				taxa = newTree.getTaxa();
+				taxa.addListener(this);
+			}
+			/*if (newTree.getTaxa() != taxa) {
+				taxa = newTree.getTaxa();
+				treeDisplay.setTaxa(taxa);
+			}*/
+			tree = newTree.cloneTree();
+			treeDisplay.setTree(tree);
+			treeDisplay.suppressDrawing(false);
+			treeDisplay.setVisible(true);
+			treeDisplay.repaint();
+			treeDisplay.setTreeAllExtras(tree);
+			MesquiteModule employer = ownerModule.getEmployer();
+			if (employer instanceof TreeWindowMaker && employer.getModuleWindow()!=null)
+				messagePanel.setMessage(tree.getName() + " in " + employer.getModuleWindow().getName());
+			else
+				messagePanel.setMessage(tree.getName());  
+		}
+		else messagePanel.setMessage("Error: source tree is null");  
+		messagePanel.repaint();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed (from MesquiteListener interface)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		int[] parameters = Notification.getParameters(notification);
+		if (obj instanceof Taxa &&  (Taxa)obj ==taxa) {
+			if (code==MesquiteListener.NAMES_CHANGED || code == MesquiteListener.SELECTION_CHANGED || code == MesquiteListener.ANNOTATION_CHANGED || code == MesquiteListener.ANNOTATION_DELETED || code == MesquiteListener.ANNOTATION_ADDED) 
+				treeDisplay.pleaseUpdate(true);
+		}
+		super.changed(caller, obj, notification);
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;  //TODO: respond
+	}
+	/*_________________________________________________*/
+	public   void InvertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void RevertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void HighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().highlightBranch(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void UnhighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().unhighlightBranch(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void ScanFlash(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot(); //TODO: remember drawnRoot!!!
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble d = new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, d);
+		if (highlightedBranch != 0) {
+			if (branchFound==0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+			else if (branchFound!=highlightedBranch)  {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch); 
+				notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+				HighlightBranch(treeDisplay, g, branchFound);
+			}
+		}
+		else if (branchFound!=0) {
+			notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+			HighlightBranch(treeDisplay, g, branchFound); 
+		}
+
+	}
+	/*_________________________________________________*/
+	public   boolean ScanTouch(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return false;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble d = new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, d);
+		if (branchFound!=0) {
+			if (highlightedBranch != 0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+			notifyExtrasOfBranchTouch(treeDisplay, g, branchFound);
+			return true;
+		}
+		else {
+			if (getCurrentTool() instanceof TreeTool){
+			boolean fieldTouchAccepted = ((TreeTool)getCurrentTool()).fieldTouched(x,y,tree,modifiers);
+			//notify extras?
+			return fieldTouchAccepted;
+			}
+		}
+		return false;
+	}
+	/*................................................................................................*/
+	private void notifyExtrasOfBranchTouch(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorTouchBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchEnter(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorEnterBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchExit(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorExitBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	public void windowResized(){
+		sizeDisplays();
+	}
+	/*.................................................................................................................*/
+	public void paintContents(Graphics g) {
+		if (treeDisplay==null){
+			MesquiteMessage.warnProgrammer("Oh no, tree display is null");
+		}
+		else {
+			sizeDisplays();
+		}
+
+	}
+	/*.................................................................................................................*/
+	public String getTextContents() {
+		if (treeDisplay==null)
+			return "";
+		String s = "Dependent tree window\n";
+		if (messagePanel !=null)
+			s += "Showing " + messagePanel.getMessage();
+		if (taxa!=null)
+			s += " for taxa \"" + taxa.getName() + "\"";
+		s += "\n\n"  + treeDisplay.getTextVersion();
+		return s;
+	}
+	public void dispose(){
+		if (taxa != null)
+			taxa.removeListener(this);
+
+		if (treeDisplay!=null){
+			if (treeDisplay.getTree()!=null)
+				treeDisplay.getTree().dispose();
+			treeDisplay.dispose();
+		}
+		super.dispose();
+	}
+}
+/* ======================================================================== */
+class DepMessagePanel extends Panel {
+	String message;
+
+	public DepMessagePanel(MesquiteWindow w) {  //in future pass general MesquiteWindow
+		super();
+		message="";
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawRect(0,0, getBounds().width, getBounds().height);
+		g.drawString(message,  4, 12);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setMessage(String s) {
+		message = s;
+		repaint();
+	}	
+
+	public String getMessage(){
+		return message;
+	}
+}
+/* ======================================================================== */
+class DepTreeExtra extends TreeDisplayExtra {
+	DepTreeWindow treeWindow;
+	public DepTreeExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay, DepTreeWindow treeWindow) {
+		super(ownerModule, treeDisplay);
+		this.treeWindow = treeWindow;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		//treeWindow.sizeDisplays();
+	}
+	public   void setTree(Tree tree) {
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+}
+
+
diff --git a/Source/mesquite/trees/DiagonalDrawTree/DiagonalDrawTree.java b/Source/mesquite/trees/DiagonalDrawTree/DiagonalDrawTree.java
new file mode 100644
index 0000000..6d61a4b
--- /dev/null
+++ b/Source/mesquite/trees/DiagonalDrawTree/DiagonalDrawTree.java
@@ -0,0 +1,1222 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.DiagonalDrawTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Draws trees in a basic diagonal-branch style.  See SquareTree and others in mesquite.basic and mesquite.ornamental. */
+public class DiagonalDrawTree extends DrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsVH.class, getName() + "  needs the locations of nodes to be calculated.",
+		"The calculator for node locations is chosen automatically or initially");
+	}
+
+	NodeLocsVH nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteString orientationName;
+	Vector drawings;
+	int oldEdgeWidth =12;
+	int ornt;
+	MesquiteString nodeLocsName;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsVH)hireNamedEmployee(NodeLocsVH.class, "#NodeLocsStandard");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node locator module obtained");
+		nodeLocsName = new MesquiteString(nodeLocsTask.getName());
+		if (numModulesAvailable(NodeLocsVH.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Locations Calculator", makeCommand("setNodeLocs", this), NodeLocsVH.class);
+			mss.setSelected(nodeLocsName);
+		}
+		drawings = new Vector();
+		MesquiteSubmenuSpec orientationSubmenu = addSubmenu(null, "Orientation");
+		ornt = NodeLocsVH.defaultOrientation;  //should take out of preferences
+		orientationName = new MesquiteString(orient(ornt));
+		orientationSubmenu.setSelected(orientationName);
+		addItemToSubmenu(null, orientationSubmenu, "Up", makeCommand("orientUp",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Right", makeCommand("orientRight",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Down", makeCommand("orientDown",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Left", makeCommand("orientLeft",  this));
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		return true;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		DiagonalTreeDrawing treeDrawing =  new DiagonalTreeDrawing (treeDisplay, numTaxa, this);
+		if (legalOrientation(treeDisplay.getOrientation())){
+			orientationName.setValue(orient(treeDisplay.getOrientation()));
+			ornt = treeDisplay.getOrientation();
+		}
+		else
+			treeDisplay.setOrientation(ornt);
+		drawings.addElement(treeDrawing);
+		//treeDisplay.inhibitStretchByDefault = false;
+		return treeDrawing;
+	}
+	public boolean legalOrientation (int orientation){
+		return (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN || orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT);
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		nodeLocsTask= null;
+		drawings.removeAllElements();
+		super.endJob();
+	}
+
+	/*.................................................................................................................*/
+	public String orient (int orientation){
+		if (orientation == TreeDisplay.UP)
+			return "Up";
+		else if (orientation == TreeDisplay.DOWN)
+			return "Down";
+		else if (orientation == TreeDisplay.RIGHT)
+			return "Right";
+		else if (orientation == TreeDisplay.LEFT)
+			return "Left";
+		else return "other";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNodeLocs", nodeLocsTask);
+
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		if (ornt== TreeDisplay.UP)
+			temp.addLine("orientUp"); 
+		else if (ornt== TreeDisplay.DOWN)
+			temp.addLine("orientDown"); 
+		else if (ornt== TreeDisplay.LEFT)
+			temp.addLine("orientLeft"); 
+		else if (ornt== TreeDisplay.RIGHT)
+			temp.addLine("orientRight"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the node locations calculator", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsVH temp = (NodeLocsVH)replaceEmployee(NodeLocsVH.class, arguments, "Node Locations Calculator", nodeLocsTask);
+			if (temp != null) {
+				nodeLocsTask = temp;
+				nodeLocsName.setValue(nodeLocsTask.getName());
+				parametersChanged();
+			}
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets thickness of lines used to draw tree", "[width in pixels]", commandName, "setEdgeWidth")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, 99);
+			if (newWidth>0 && newWidth<100 && newWidth!=oldEdgeWidth) {
+				oldEdgeWidth=newWidth;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					DiagonalTreeDrawing treeDrawing = (DiagonalTreeDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+					treeDrawing.treeDisplay.setMinimumTaxonNameDistance(newWidth, 5); //better if only did this if tracing on
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Returns module calculating node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are on top", null, commandName, "orientUp")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.UP;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				DiagonalTreeDrawing treeDrawing = (DiagonalTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.UP);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at the bottom", null, commandName, "orientDown")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.DOWN;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				DiagonalTreeDrawing treeDrawing = (DiagonalTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.DOWN);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at right", null, commandName, "orientRight")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.RIGHT;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				DiagonalTreeDrawing treeDrawing = (DiagonalTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.RIGHT);
+				if (treeDrawing.treeDisplay != null)
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at left", null, commandName, "orientLeft")) {
+			Enumeration e = drawings.elements();
+			ornt =TreeDisplay.LEFT;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				DiagonalTreeDrawing treeDrawing = (DiagonalTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.LEFT);
+				if (treeDrawing.treeDisplay != null)
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Diagonal tree";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Draws trees with standard diagonal branches (\"cladogram\")" ;
+	}
+	/*.................................................................................................................*/
+}
+
+/* ======================================================================== */
+
+/* ======================================================================== */
+class DiagonalTreeDrawing extends TreeDrawing  {
+	public Polygon[] branchPoly;
+	public Polygon[] touchPoly;
+	public Polygon[] fillBranchPoly;
+
+	private int lastleft;
+	private int taxspacing;
+	public int highlightedBranch, branchFrom;
+	public int xFrom, yFrom, xTo, yTo;
+	public DiagonalDrawTree ownerModule;
+	public int edgeWidth = 12;
+	public int preferredEdgeWidth = 12;
+	int oldNumTaxa = 0;
+	Polygon utilityPolygon;
+	public static final int inset=1;
+	private boolean ready=false;
+
+	private int foundBranch;
+	NameReference triangleNameRef;
+	NameReference widthNameReference;
+	DoubleArray widths = null;
+	double maxWidth = 0;
+	public DiagonalTreeDrawing (TreeDisplay treeDisplay, int numTaxa, DiagonalDrawTree ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		widthNameReference = NameReference.getNameReference("width");
+		treeDisplay.setMinimumTaxonNameDistance(edgeWidth, 5); //better if only did this if tracing on
+		triangleNameRef = NameReference.getNameReference("triangled");
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		ready = true;
+		treeDisplay.setOrientation(ownerModule.nodeLocsTask.getDefaultOrientation());
+		utilityPolygon=new Polygon();
+		utilityPolygon.xpoints = new int[16];
+		utilityPolygon.ypoints = new int[16];
+		utilityPolygon.npoints=16;
+	}
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new Polygon[numNodes];
+		touchPoly= new Polygon[numNodes];
+		fillBranchPoly= new Polygon[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new Polygon();
+			branchPoly[i].xpoints = new int[16];
+			branchPoly[i].ypoints = new int[16];
+			branchPoly[i].npoints=16;
+			touchPoly[i] = new Polygon();
+			touchPoly[i].xpoints = new int[16];
+			touchPoly[i].ypoints = new int[16];
+			touchPoly[i].npoints=16;
+			fillBranchPoly[i] = new Polygon();
+			fillBranchPoly[i].xpoints = new int[16];
+			fillBranchPoly[i].ypoints = new int[16];
+			fillBranchPoly[i].npoints=16;
+		}
+	}
+	private boolean isUP(){
+		return treeDisplay.getOrientation()==TreeDisplay.UP;
+	}
+	private boolean isDOWN(){
+		return treeDisplay.getOrientation()==TreeDisplay.DOWN;
+	}
+	private boolean isLEFT(){
+		return treeDisplay.getOrientation()==TreeDisplay.LEFT;
+	}
+	private boolean isRIGHT(){
+		return treeDisplay.getOrientation()==TreeDisplay.RIGHT;
+	}
+	int branchEdgeWidth(int node, boolean isTouch){
+		if (widths !=null && maxWidth!=0 && MesquiteDouble.isCombinable(maxWidth)) {
+			double w = widths.getValue(node);
+			if (MesquiteDouble.isCombinable(w))
+				if (isTouch)
+					return (int)((w/maxWidth) * getNodeWidth());
+				else
+					return (int)((w/maxWidth) * edgeWidth);
+		}	
+		if (isTouch)
+			return getNodeWidth();
+		else
+			return edgeWidth;
+	}
+	private int getOffset(int width, int node) {
+		return (width-branchEdgeWidth(node,false))/2;
+	}
+	/*_________________________________________________*/
+	private void UPdefineFillPoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices) {
+		if (poly!=null) {
+			int sliceWidth=branchEdgeWidth(node, isTouch);
+			if (numSlices>1) {
+				Nx+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+				mNx+= (sliceNumber-1)*(branchEdgeWidth(node,isTouch)-inset)/numSlices;
+				sliceWidth=(branchEdgeWidth(node, isTouch)-inset)-((sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices);
+			}
+			if ((internalNode) && (numSlices==1)){ 
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny);
+				poly.addPoint(Nx+sliceWidth/2, Ny-sliceWidth/2-inset);
+				poly.addPoint(Nx+sliceWidth-inset, Ny);
+				poly.addPoint(mNx+sliceWidth-inset, mNy);
+				poly.addPoint(mNx+inset, mNy);
+				poly.addPoint(Nx+inset, Ny);
+				poly.npoints=6;
+			}
+			else {
+				if (Nx==mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Ny-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx+inset, Ny+inset);
+					poly.addPoint(Nx+sliceWidth-inset, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx+inset, Ny+inset);
+					poly.npoints=5;
+				}
+				else if (Nx>mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Nx+=(branchEdgeWidth(node, isTouch)-inset)/4;
+						Ny-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx, Ny+inset);
+					poly.addPoint(Nx+sliceWidth-inset-inset, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx, Ny+inset);
+					poly.npoints=5;
+				}
+				else if (Nx<mNx) {
+					if ((internalNode) && (numSlices>1)) {
+						Nx-=(branchEdgeWidth(node, isTouch)-inset)/4;
+						Ny-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					}
+					poly.npoints=0;
+					poly.addPoint(Nx+inset+inset, Ny+inset);
+					poly.addPoint(Nx+sliceWidth, Ny+inset);
+					poly.addPoint(mNx+sliceWidth-inset, mNy);
+					poly.addPoint(mNx+inset, mNy);
+					poly.addPoint(Nx+inset+inset, Ny+inset);
+					poly.npoints=5;
+				}
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void UPCalcFillBranchPolys(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcFillBranchPolys(tree, d);
+		UPdefineFillPoly(node, fillBranchPoly[node], false, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0);
+	}
+	/*_________________________________________________*/
+	private void UPdefinePoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Nx -= getOffset(branchEdgeWidth(node,isTouch), node);
+			mNx -= getOffset(branchEdgeWidth(node,isTouch), node);
+			if (internalNode)  {
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch)/2, Ny-branchEdgeWidth(node, isTouch)/2);//Ny+branchEdgeWidth(node, isTouch)/2 for down
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node, isTouch), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else {
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node, isTouch), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void UPCalcBranchPolys(Tree tree, int node, Polygon[] polys, boolean isTouch)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcBranchPolys(tree, d, polys, isTouch);
+			UPdefinePoly(node, polys[node], isTouch, tree.nodeIsInternal(node), x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		}
+		else {
+			Polygon poly = polys[node];
+			poly.npoints=0;
+			int mN = tree.motherOfNode(node);
+			int leftN = tree.leftmostTerminalOfNode(node);
+			int rightN = tree.rightmostTerminalOfNode(node);
+			poly.addPoint(x[node], y[node]);
+			poly.addPoint(x[leftN], y[leftN]);
+			poly.addPoint(x[rightN]+branchEdgeWidth(node, isTouch), y[rightN]);
+			poly.addPoint(x[node]+branchEdgeWidth(node, isTouch), y[node]);
+			poly.addPoint(x[mN]+branchEdgeWidth(node, isTouch), y[mN]);
+			poly.addPoint(x[mN], y[mN]);
+			poly.addPoint(x[node], y[node]);
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	/*_________________________________________________*/
+	private void DOWNdefineFillPoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices) {
+		int sliceWidth=branchEdgeWidth(node, isTouch);
+		if (numSlices>1) {
+			Nx+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+			mNx+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+			sliceWidth=(branchEdgeWidth(node, isTouch)-inset)-((sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices);
+		}
+		if ((internalNode) && (numSlices==1)){ 
+			poly.npoints=0;
+			poly.addPoint(Nx+inset, Ny);
+			poly.addPoint(Nx+sliceWidth/2, Ny+sliceWidth/2+inset);
+			poly.addPoint(Nx+sliceWidth-inset, Ny);
+			poly.addPoint(mNx+sliceWidth-inset, mNy);
+			poly.addPoint(mNx+inset, mNy);
+			poly.addPoint(Nx+inset, Ny);
+			poly.npoints=6;
+		}
+		else {
+			if (Nx==mNx) {
+				if ((internalNode) && (numSlices>1)) {
+					Ny+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny-inset);
+				poly.addPoint(Nx+sliceWidth-inset, Ny-inset);
+				poly.addPoint(mNx+sliceWidth-inset, mNy);
+				poly.addPoint(mNx+inset, mNy);
+				poly.addPoint(Nx+inset, Ny-inset);
+				poly.npoints=5;
+			}
+			else if (Nx>mNx) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx+=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny-inset);
+				poly.addPoint(Nx+sliceWidth-inset-inset, Ny-inset);
+				poly.addPoint(mNx+sliceWidth-inset, mNy);
+				poly.addPoint(mNx+inset, mNy);
+				poly.addPoint(Nx, Ny-inset);
+				poly.npoints=5;
+			}
+			else if (Nx<mNx) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx+inset+inset, Ny-inset);
+				poly.addPoint(Nx+sliceWidth, Ny-inset);
+				poly.addPoint(mNx+sliceWidth-inset, mNy);
+				poly.addPoint(mNx+inset, mNy);
+				poly.addPoint(Nx+inset+inset, Ny-inset);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcFillBranchPolys(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcFillBranchPolys(tree, d);
+		DOWNdefineFillPoly(node, fillBranchPoly[node], false, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0);
+	}
+	/*_________________________________________________*/
+	private void DOWNdefinePoly(int node, Polygon poly,boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null){
+			Nx -= getOffset(branchEdgeWidth(node,isTouch), node);
+			mNx -= getOffset(branchEdgeWidth(node,isTouch), node);
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch)/2, Ny+branchEdgeWidth(node, isTouch)/2);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node, isTouch), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch), Ny);
+				poly.addPoint(mNx+branchEdgeWidth(node, isTouch), mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcBranchPolys(Tree tree, int node, Polygon[] polys, boolean isTouch)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcBranchPolys(tree, d, polys, isTouch);
+			DOWNdefinePoly(node, polys[node], isTouch, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		}
+		else {
+			Polygon poly = polys[node];
+			poly.npoints=0;
+			int mN = tree.motherOfNode(node);
+			int leftN = tree.leftmostTerminalOfNode(node);
+			int rightN = tree.rightmostTerminalOfNode(node);
+			poly.addPoint(x[node], y[node]);
+			poly.addPoint(x[leftN], y[leftN]);
+			poly.addPoint(x[rightN]+branchEdgeWidth(node, isTouch), y[rightN]);
+			poly.addPoint(x[node]+branchEdgeWidth(node, isTouch), y[node]);
+			poly.addPoint(x[mN]+branchEdgeWidth(node, isTouch), y[mN]);
+			poly.addPoint(x[mN], y[mN]);
+			poly.addPoint(x[node], y[node]);
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	/*_________________________________________________*/
+	private void RIGHTdefineFillPoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices) {
+		int sliceWidth=branchEdgeWidth(node, isTouch);
+		if (numSlices>1) {
+			Ny+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+			mNy+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+			sliceWidth=(branchEdgeWidth(node, isTouch)-inset)-((sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices);
+		}
+		if ((internalNode) && (numSlices==1)){ 
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny+inset);
+			poly.addPoint(Nx+sliceWidth/2+inset, Ny+sliceWidth/2);
+			poly.addPoint(Nx, Ny+sliceWidth-inset);
+			poly.addPoint(mNx, mNy+sliceWidth-inset);
+			poly.addPoint(mNx, mNy+inset);
+			poly.addPoint(Nx, Ny+inset);
+			poly.npoints=6;
+		}
+		else {
+			if (Ny==mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx-inset, Ny+inset);
+				poly.addPoint(Nx-inset, Ny+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx-inset, Ny+inset);
+				poly.npoints=5;
+			}
+			else if (Ny>mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx+=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx-inset, Ny);
+				poly.addPoint(Nx-inset, Ny+sliceWidth-inset-inset);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx-inset, Ny);
+				poly.npoints=5;
+			}
+			else if (Ny<mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx+=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny-=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx-inset, Ny+inset+inset);
+				poly.addPoint(Nx-inset, Ny+sliceWidth);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx-inset, Ny+inset+inset);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcFillBranchPolys(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcFillBranchPolys(tree, d);
+		RIGHTdefineFillPoly(node, fillBranchPoly[node], false, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0);
+	}
+	/*_________________________________________________*/
+	private void RIGHTdefinePoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Ny -= getOffset(branchEdgeWidth(node,isTouch), node);
+			mNy -= getOffset(branchEdgeWidth(node,isTouch), node);
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+branchEdgeWidth(node, isTouch)/2, Ny+branchEdgeWidth(node, isTouch)/2);
+				poly.addPoint(Nx, Ny+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx, Ny+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcBranchPolys(Tree tree, int node, Polygon[] polys, boolean isTouch)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcBranchPolys(tree, d, polys, isTouch);
+			RIGHTdefinePoly(node, polys[node], isTouch, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		}
+		else {
+			Polygon poly = polys[node];
+			poly.npoints=0;
+			int mN = tree.motherOfNode(node);
+			int leftN = tree.leftmostTerminalOfNode(node);
+			int rightN = tree.rightmostTerminalOfNode(node);
+			poly.addPoint(x[node], y[node]);
+			poly.addPoint(x[leftN], y[leftN]);
+			poly.addPoint(x[rightN], y[rightN]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[node], y[node]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[mN], y[mN]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[mN], y[mN]);
+			poly.addPoint(x[node], y[node]);
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	/*_________________________________________________*/
+	private void LEFTdefineFillPoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices) {
+		int sliceWidth=branchEdgeWidth(node, isTouch);
+		if (numSlices>1) {
+			Ny+= (sliceNumber-1)*((branchEdgeWidth(node, isTouch)-inset)-inset-inset)/numSlices;
+			mNy+= (sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices;
+			sliceWidth=(branchEdgeWidth(node, isTouch)-inset)-((sliceNumber-1)*(branchEdgeWidth(node, isTouch)-inset)/numSlices);
+		}
+		if ((internalNode) && (numSlices==1)){ 
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny+inset);
+			poly.addPoint(Nx-sliceWidth/2-inset, Ny+sliceWidth/2);
+			poly.addPoint(Nx, Ny+sliceWidth-inset);
+			poly.addPoint(mNx, mNy+sliceWidth-inset);
+			poly.addPoint(mNx, mNy+inset);
+			poly.addPoint(Nx, Ny+inset);
+			poly.npoints=6;
+		}
+		else {
+			if (Ny==mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx-=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny+inset);
+				poly.addPoint(Nx+inset, Ny+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx+inset, Ny+inset);
+				poly.npoints=5;
+			}
+			else if (Ny>mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny+=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny);
+				poly.addPoint(Nx+inset, Ny+sliceWidth-inset-inset);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx+inset, Ny);
+				poly.npoints=5;
+			}
+			else if (Ny<mNy) {
+				if ((internalNode) && (numSlices>1)) {
+					Nx-=(branchEdgeWidth(node, isTouch)-inset)/4;
+					Ny-=(branchEdgeWidth(node, isTouch)-inset)/4;
+				}
+				poly.npoints=0;
+				poly.addPoint(Nx+inset, Ny+inset+inset);
+				poly.addPoint(Nx+inset, Ny+sliceWidth);
+				poly.addPoint(mNx, mNy+sliceWidth-inset);
+				poly.addPoint(mNx, mNy+inset);
+				poly.addPoint(Nx+inset, Ny+inset+inset);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcFillBranchPolys(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node))
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcFillBranchPolys(tree, d);
+		LEFTdefineFillPoly(node, fillBranchPoly[node], false, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0);
+	}
+	/*_________________________________________________*/
+	private void LEFTdefinePoly(int node, Polygon poly, boolean isTouch, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Ny -= getOffset(branchEdgeWidth(node,isTouch), node);
+			mNy -= getOffset(branchEdgeWidth(node,isTouch), node);
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx-branchEdgeWidth(node, isTouch)/2, Ny+branchEdgeWidth(node, isTouch)/2);
+				poly.addPoint(Nx, Ny+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx, Ny+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy+branchEdgeWidth(node, isTouch));
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcBranchPolys(Tree tree, int node, Polygon[] polys, boolean isTouch)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcBranchPolys(tree, d, polys, isTouch);
+			LEFTdefinePoly(node, polys[node], isTouch, tree.nodeIsInternal(node),x[node],y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]);
+		}
+		else {
+			Polygon poly = polys[node];
+			poly.npoints=0;
+			int mN = tree.motherOfNode(node);
+			int leftN = tree.leftmostTerminalOfNode(node);
+			int rightN = tree.rightmostTerminalOfNode(node);
+			poly.addPoint(x[node], y[node]);
+			poly.addPoint(x[leftN], y[leftN]);
+			poly.addPoint(x[rightN], y[rightN]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[node], y[node]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[mN], y[mN]+branchEdgeWidth(node, isTouch));
+			poly.addPoint(x[mN], y[mN]);
+			poly.addPoint(x[node], y[node]);
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[tree.motherOfNode(node)];
+		lineBaseX[node]=x[tree.motherOfNode(node)];
+	}
+	/*_________________________________________________*/
+	private void calcBranchPolys(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField());  //Graphics g removed as parameter May 02
+
+		calculateLines(tree, drawnRoot);
+		edgeWidth = preferredEdgeWidth;
+		if (treeDisplay.getTaxonSpacing()<edgeWidth+2) {
+			edgeWidth= treeDisplay.getTaxonSpacing()-2;
+			if (edgeWidth<2)
+				edgeWidth=2;
+		}
+		treeDisplay.setMinimumTaxonNameDistance(edgeWidth, 5);
+		if (isUP()) {
+			UPCalcBranchPolys(tree, drawnRoot, branchPoly, false);
+			UPCalcBranchPolys(tree, drawnRoot, touchPoly, true);
+			UPCalcFillBranchPolys(tree, drawnRoot);
+		}
+
+		else if (isDOWN()){
+			DOWNCalcBranchPolys(tree, drawnRoot, branchPoly, false);
+			DOWNCalcBranchPolys(tree, drawnRoot, touchPoly, true);
+			DOWNCalcFillBranchPolys(tree, drawnRoot);
+		}
+		else  if (isRIGHT()) {
+			RIGHTCalcBranchPolys(tree, drawnRoot, branchPoly, false);
+			RIGHTCalcBranchPolys(tree, drawnRoot, touchPoly, true);
+			RIGHTCalcFillBranchPolys(tree, drawnRoot);
+		}
+		else  if (isLEFT()){
+			LEFTCalcBranchPolys(tree, drawnRoot, branchPoly, false);
+			LEFTCalcBranchPolys(tree, drawnRoot, touchPoly, true);
+			LEFTCalcFillBranchPolys(tree, drawnRoot);
+		}
+	}
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		tC = g.getColor();
+		if (flip)
+			g.setColor(Color.red);
+		else
+			g.setColor(Color.blue);
+		if (isDOWN() || isUP()){
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node]-2 - i, y[node], x[tree.motherOfNode(node)]-2 - i, y[tree.motherOfNode(node)]);
+		}
+		else {
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node], y[node]-2 - i, x[tree.motherOfNode(node)], y[tree.motherOfNode(node)]-2 - i);
+		}
+		g.setColor(tC);
+	}
+	/*_________________________________________________*/
+	private boolean ancestorIsTriangled(Tree tree, int node) {
+		if (!tree.nodeExists(node))
+			return false;
+		if (tree.getAssociatedBit(triangleNameRef, tree.motherOfNode(node)))
+			return true;
+		if (tree.getRoot() == node || tree.getSubRoot() == node)
+			return false;
+		return ancestorIsTriangled(tree, tree.motherOfNode(node));
+	}
+	Color tC;
+	public boolean branchIsVisible(int node){
+		try {
+			if (node >=0 && node <  branchPoly.length)
+				return treeDisplay.getVisRect() == null || branchPoly[node].intersects(treeDisplay.getVisRect());
+		}
+		catch(Throwable t){
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	private   void drawBranches(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			//g.setColor(Color.black);//for testing
+			boolean draw = branchIsVisible(node);
+			if (draw){
+				g.setColor(treeDisplay.getBranchColor(node));
+			if ((tree.getRooted() || tree.getRoot()!=node) && branchPoly[node]!=null) {
+				if (SHOWTOUCHPOLYS) {  //fordebugging
+					Color prev = g.getColor();
+					g.setColor(ColorDistribution.burlyWood);
+					g.fillPolygon(touchPoly[node]);
+					g.setColor(prev);
+				}
+				g.fillPolygon(branchPoly[node]);
+				if (tree.numberOfParentsOfNode(node)>1) {
+					for (int i=1; i<=tree.numberOfParentsOfNode(node); i++) {
+						int anc =tree.parentOfNode(node, i);
+						if (anc!= tree.motherOfNode(node)) {
+							g.drawLine(x[node],y[node], x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node]+1,y[node], x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node],y[node]+1, x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]+1);
+							g.drawLine(x[node]+1,y[node]+1, x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]+1);
+						}
+					}
+				}
+			}
+			if (tree.getAssociatedBit(triangleNameRef,node)) {
+				if (isUP()) {
+					/*g.setColor(Color.red);
+					for (int i=0; i<edgeWidth; i++) 
+						g.drawLine(x[node]+i,y[node], x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]);
+
+					g.setColor(Color.blue);
+					for (int i=0; i<edgeWidth; i++)
+						g.drawLine(x[node]+i,y[node], x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]);
+
+						g.setColor(Color.green);
+					for (int i=0; i<edgeWidth*0.71; i++) {
+						g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+i, x[tree.rightmostTerminalOfNode(node)]-i,y[tree.rightmostTerminalOfNode(node)]+i);
+					}*/
+				}
+				else if (isDOWN()) {
+					/*g.setColor(Color.blue);
+					for (int i=0; i<edgeWidth; i++) {
+						g.drawLine(x[node]+i,y[node], x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]);
+						g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]-i, x[tree.rightmostTerminalOfNode(node)]-i,y[tree.rightmostTerminalOfNode(node)]-i);
+						g.drawLine(x[node]+i,y[node], x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]);
+					}
+					 */
+				}
+				/*	for (int j=0; j<2; j++)
+				for (int i=0; i<2; i++) {
+					g.drawLine(x[node]+i,y[node]+j, x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j);
+					g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+					g.drawLine(x[node]+i,y[node]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+				}*/
+			}
+			}
+			if (!tree.getAssociatedBit(triangleNameRef,node))
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					drawBranches( tree, g, d);
+			if (draw && emphasizeNodes()) {
+				Color prev = g.getColor();
+				g.setColor(Color.red);//for testing
+				g.fillPolygon(nodePoly(node));
+				g.setColor(prev);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	private double findMaxWidth(Tree tree, int node) {
+		if (!tree.getAssociatedBit(triangleNameRef,node)) {
+			if (tree.nodeIsTerminal(node))
+				return widths.getValue(node);
+
+			double mw = MesquiteDouble.unassigned;
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				mw = MesquiteDouble.maximum(mw, findMaxWidth(tree, d));
+			return mw;
+		}
+		return (MesquiteDouble.unassigned);
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+		if (MesquiteTree.OK(tree)) {
+
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			widths = tree.getWhichAssociatedDouble(widthNameReference);
+			if (widths!=null)
+				maxWidth = findMaxWidth(tree, getDrawnRoot());
+			calcBranchPolys(tree, getDrawnRoot());
+
+		}
+	}
+	/*_________________________________________________*/
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+		int mother = tree.motherOfNode(N);
+		xValue.setValue(GraphicsUtil.xCenterOfLine(x[mother], y[mother], x[N], y[N]));
+		yValue.setValue(GraphicsUtil.yCenterOfLine(x[mother], y[mother], x[N], y[N]));
+		angle.setValue(GraphicsUtil.angleOfLine(x[mother], y[mother], x[N], y[N]));
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+		
+		if (MesquiteTree.OK(tree) && treeDisplay != null && g!= null) {
+			//if (tree.getNumNodeSpaces()!=numNodes)
+			//	resetNumNodes(tree.getNumNodeSpaces());
+			g.setColor(treeDisplay.branchColor);
+			drawBranches(tree, g, drawnRoot);  
+		}
+	}
+
+	/*_________________________________________________*/
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		int ew = branchEdgeWidth(node, false)-2;
+		if (isUP()){ 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]-ew-3 && yPos < y[node]-3;
+		}
+		else if (isDOWN())
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]+2 && yPos < y[node]+ew+2;
+		else  if (isRIGHT()) 
+			return xPos> x[node]+1 && xPos < x[node]+ew +1 && yPos > y[node] && yPos < y[node] + ew;
+		else  if (isLEFT())
+			return xPos> x[node]-ew-3 && xPos < x[node]-3 && yPos > y[node] && yPos < y[node] + ew;
+		else 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node] && yPos < y[node] + ew;
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		Rectangle box;
+		int ew = branchEdgeWidth(node, false)-2;
+		if (isUP()) 
+			box = new Rectangle(x[node], y[node]-ew-3, ew, ew);
+		else if (isDOWN())
+			box = new Rectangle(x[node], y[node]+2, ew, ew);
+		else  if (isRIGHT()) 
+			box = new Rectangle(x[node]+1, y[node], ew, ew);
+		else  if (isLEFT())
+			box = new Rectangle(x[node]-ew-3, y[node], ew, ew);
+		else 
+			box = new Rectangle(x[node], y[node], ew, ew);
+		g.fillRect(box.x, box.y, box.width, box.height);
+		g.setColor(treeDisplay.getBranchColor(node));
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		Rectangle box;
+		int numColors = colors.getNumColors();
+		if (numColors == 0) numColors = 1;
+		int ew = branchEdgeWidth(node, false)-2;
+		if (isUP()) 
+			box = new Rectangle(x[node], y[node]-ew-3, ew, ew);
+		else if (isDOWN())
+			box = new Rectangle(x[node], y[node]+2, ew, ew);
+		else  if (isRIGHT()) 
+			box = new Rectangle(x[node]+1, y[node], ew, ew);
+		else  if (isLEFT())
+			box = new Rectangle(x[node]-ew-3, y[node], ew, ew);
+		else 
+			box = new Rectangle(x[node], y[node], ew, ew);
+		for (int i=0; i<colors.getNumColors(); i++) {
+			Color color;
+			if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+				g.setColor(color);
+			g.fillRect(box.x + (i*box.width/colors.getNumColors()), box.y, box.width-  (i*box.width/numColors), box.height);
+		}
+		g.setColor(treeDisplay.getBranchColor(node));
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+	/*_________________________________________________*
+	public void fillBranchWithMissingData(Tree tree, int node, Graphics g) {
+
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			Color c = g.getColor();
+			if (g instanceof Graphics2D){
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setPaint(GraphicsUtil.missingDataTexture);
+			}
+			else
+				g.setColor(Color.lightGray);
+			//					UPdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+
+			if (isUP())
+				UPdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1);
+			else if (isDOWN()) 
+				DOWNdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1);
+			else if (isRIGHT()) 
+				RIGHTdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1);
+			else if (isLEFT())
+				LEFTdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1);
+
+			g.fillPolygon(utilityPolygon);
+			if (c!=null) g.setColor(c);
+		}	
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			int numColors = colors.getNumColors();
+			if (isUP()) {
+				for (int i=0; i<numColors; i++) {
+					UPdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isDOWN()) {
+				for (int i=0; i<numColors; i++) {
+					DOWNdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isRIGHT()) {
+				for (int i=0; i<numColors; i++) {
+					RIGHTdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isLEFT()){
+				for (int i=0; i<numColors; i++) {
+					LEFTdefineFillPoly(node, utilityPolygon, false, tree.nodeIsInternal(node), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, colors.getNumColors());
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			g.setColor(treeDisplay.getBranchColor(node));
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (fillBranchPoly[node] !=null && node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			g.fillPolygon(fillBranchPoly[node]);
+		}
+	}
+
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int halfNodeWidth = getNodeWidth()/2;
+		int startX =0;
+		int startY =0;
+		if (isUP() || isDOWN()){
+			startX = x[node]+halfNodeWidth-offset;
+			startY= y[node] -halfNodeWidth;
+		}	else if (isRIGHT() || isLEFT()){
+			startX = x[node];
+			startY= y[node]-offset;
+		}
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(startX,startY);
+		poly.addPoint(startX+halfNodeWidth,startY+halfNodeWidth);
+		poly.addPoint(startX,startY+getNodeWidth());
+		poly.addPoint(startX-halfNodeWidth,startY+halfNodeWidth);
+		poly.addPoint(startX,startY);
+		poly.npoints=5;
+		return poly;
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree,Polygon polys[], int node, int x, int y, MesquiteDouble fraction){
+		if (foundBranch==0) {
+			if (polys != null && polys[node] != null && polys[node].contains(x, y) || inNode(node,x,y)){
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							fraction.setValue(GraphicsUtil.fractionAlongLine(x, y, this.x[motherNode], this.y[motherNode], this.x[node], this.y[node],isRIGHT()||isLEFT(), isUP()||isDOWN()));
+						}
+					}
+			}
+			if (!tree.getAssociatedBit(triangleNameRef, node)) 
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					ScanBranches(tree, polys, d, x, y, fraction);
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, branchPoly, drawnRoot, x, y, fraction);  //first scan through thin branches
+			if (foundBranch==0 && getEdgeWidth()<ACCEPTABLETOUCHWIDTH)
+				ScanBranches(tree, touchPoly, drawnRoot, x, y, fraction);  //then scan through thicker versions
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		preferredEdgeWidth = edw;
+		edgeWidth = edw;
+		treeDisplay.setMinimumTaxonNameDistance(edgeWidth, 5);
+	}
+	/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgeWidth;
+	}
+	/*End new code Feb.22.07 oliver*/
+	/*_________________________________________________*/
+	public void dispose(){
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = null;
+			fillBranchPoly[i] = null;
+		}
+		ownerModule=null;
+		super.dispose(); //calls cleanup
+	}
+
+}
+
+
diff --git a/Source/mesquite/trees/DifferenceInNumsForTree/DifferenceInNumsForTree.java b/Source/mesquite/trees/DifferenceInNumsForTree/DifferenceInNumsForTree.java
new file mode 100644
index 0000000..04ce8c9
--- /dev/null
+++ b/Source/mesquite/trees/DifferenceInNumsForTree/DifferenceInNumsForTree.java
@@ -0,0 +1,167 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.DifferenceInNumsForTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class DifferenceInNumsForTree extends NumberForTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " compares two different values for each tree.",
+		"You can request what values to compare initially, or later under the First Value for Difference submenu and the Second Value for Difference submenu.");
+	}
+	public String getName() {
+		return "Difference in two values for tree";
+	}
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the calculation of the difference in two numbers for a tree." ;
+	}
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	/*.................................................................................................................*/
+	NumberForTree numberTask1, numberTask2;
+	MesquiteString numberTask1Name, numberTask2Name;
+	MesquiteCommand ntC1, ntC2;
+	MesquiteNumber[] numbers = new MesquiteNumber[2];
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numberTask1 = (NumberForTree)hireEmployee(NumberForTree.class, "First value to calculate for tree");
+		if (numberTask1 == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		numberTask2 = (NumberForTree)hireEmployee(NumberForTree.class, "Second value to calculate for tree");
+		if (numberTask2 == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		numbers[0] = new MesquiteNumber();
+		numbers[1] = new MesquiteNumber();
+
+		ntC1 =makeCommand("setNumberTask1",  this);
+		ntC2 =makeCommand("setNumberTask2",  this);
+		numberTask1.setHiringCommand(ntC1);
+		numberTask1Name = new MesquiteString();
+		numberTask1Name.setValue(numberTask1.getName());
+		numberTask2.setHiringCommand(ntC2);
+		numberTask2Name = new MesquiteString();
+		numberTask2Name.setValue(numberTask2.getName());
+		if (numModulesAvailable(NumberForTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "First Value for Difference", ntC1, NumberForTree.class);
+			mss.setSelected(numberTask1Name);
+			mss = addSubmenu(null, "Second Value for Difference", ntC2, NumberForTree.class);
+			mss.setSelected(numberTask2Name);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask1 ", numberTask1);  
+		temp.addLine("setNumberTask2 ", numberTask2);  
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates the first number for trees", "[name of module]", commandName, "setNumberTask1")) {
+			NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Number for tree (first in difference)", numberTask1);
+			if (temp!=null) {
+				numberTask1 = temp;
+				numberTask1.setHiringCommand(ntC1);
+				numberTask1Name.setValue(numberTask1.getName());
+				parametersChanged();
+				return numberTask1;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module that calculates the second number for trees", "[name of module]", commandName, "setNumberTask2")) {
+			NumberForTree temp =  (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Number for tree (second in difference)", numberTask2);
+			if (temp!=null) {
+				numberTask2 = temp;
+				numberTask2.setHiringCommand(ntC2);
+				numberTask2Name.setValue(numberTask2.getName());
+				parametersChanged();
+				return numberTask2;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (numberTask1 !=null)
+			numberTask1.initialize(tree);
+		if (numberTask2 !=null)
+			numberTask2.initialize(tree);
+	}
+	public boolean returnsMultipleValues(){
+		return true;
+	}
+	MesquiteString rs1 = new MesquiteString();
+	MesquiteString rs2 = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null || tree == null)
+			return;
+		clearResultAndLastResult(result);
+		rs1.setValue("");
+		rs2.setValue("");
+		MesquiteNumber r = new MesquiteNumber();
+		numberTask1.calculateNumber(tree, r, rs1);
+		numberTask2.calculateNumber(tree, result, rs2);
+		numbers[0].setName(r.getName());
+		numbers[0].setValue(r);
+		numbers[1].setName(result.getName());
+		numbers[1].setValue(result);
+
+		result.subtract(r);
+		result.copyAuxiliaries(numbers);
+		if (resultString!=null) {
+			resultString.setValue("Difference: " + result + " [" + rs1 + "] - [" + rs2 + "]");
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Difference between: " + numberTask1.getName() + " and " + numberTask2.getName(); 
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (numberTask1 ==null | numberTask2 == null)
+			return "Difference in two values";
+		else
+			return "Difference [" + numberTask1.getVeryShortName() + "] - [" + numberTask2.getVeryShortName() + "]";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/EqualRatesMarkovSp/EqualRatesMarkovSp.java b/Source/mesquite/trees/EqualRatesMarkovSp/EqualRatesMarkovSp.java
new file mode 100644
index 0000000..ef674bd
--- /dev/null
+++ b/Source/mesquite/trees/EqualRatesMarkovSp/EqualRatesMarkovSp.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.EqualRatesMarkovSp;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class EqualRatesMarkovSp extends TreeSimulate {
+	RandomBetween randomTaxon;
+	ExponentialDistribution waitingTime;
+	double scaling = 10.0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		randomTaxon= new RandomBetween(1);
+ 		waitingTime = new ExponentialDistribution(1);
+ 		if (!MesquiteThread.isScripting())
+ 			scaling = MesquiteDouble.queryDouble(containerOfModule(), "Total tree depth", "Total tree depth", scaling);
+ 		if (!MesquiteDouble.isCombinable(scaling))
+ 			return false;
+   		addMenuItem("Total tree depth (simulation)...", makeCommand("setTime",  this));
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;  
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTime " + scaling);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the total tree depth", "[number]", commandName, "setTime")) {
+    	 		pos.setValue(0);
+ 			double s = MesquiteDouble.fromString(arguments, pos);
+	 		if (!MesquiteDouble.isCombinable(s))
+ 				s = MesquiteDouble.queryDouble(containerOfModule(), "Total tree depth", "Total tree depth", scaling);
+	 		if (MesquiteDouble.isCombinable(s)) {
+	 			scaling = s;
+	 			parametersChanged();
+	 		}
+    		}
+   	 	else return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+  	 private void addLengthToAllTerminals(MesquiteTree tree, int node, double increment){
+  	 	if (tree.nodeIsTerminal(node)) {
+  	 		double current = tree.getBranchLength(node, MesquiteDouble.unassigned);
+  	 		if (MesquiteDouble.isCombinable(current))
+  	 			tree.setBranchLength(node, current + increment, false);
+  	 		else
+  	 			tree.setBranchLength(node, increment, false);  	 		
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			addLengthToAllTerminals(tree, d, increment);
+		}
+  	 }
+  	private double getWaitingTime(int numTaxa){
+  		return waitingTime.nextExponential(1.0/numTaxa);
+  	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return MesquiteInteger.infinite;
+   	}
+	/*.................................................................................................................*/
+   	public Tree getSimulatedTree(Taxa taxa, Tree tree, int treeNumber, ObjectContainer extra, MesquiteLong seed) { //todo: should be two seeds passed!
+   	//save random seed used to make tree under tree.seed for use in recovering later
+  			randomTaxon.setSeed(seed.getValue());
+  			waitingTime.setSeed(seed.getValue());
+  			if (tree==null || !(tree instanceof MesquiteTree))
+  				 tree = new MesquiteTree(taxa);
+  			MesquiteTree mTree = ((MesquiteTree)tree);
+			mTree.setToDefaultBush(2, false);
+			int whichTaxon;
+
+			for (int taxon = 2; taxon < taxa.getNumTaxa(); taxon++) {
+				whichTaxon=randomTaxon.randomIntBetween(0, taxon-1);
+				addLengthToAllTerminals(mTree, tree.getRoot(), getWaitingTime(taxon));
+				mTree.splitTerminal(whichTaxon, taxon, false);
+			}
+ /*			if (positions == null || positions.length != mTree.numberOfTerminalsInClade(mTree.getRoot()))
+ 				positions = new double[mTree.numberOfTerminalsInClade(mTree.getRoot())];*/
+			mTree.reshuffleTerminals(randomTaxon); //added after 1.03
+ 		
+			//adding to all terminals waiting time uniformly distributed between 0 and waiting time to next speciation
+			addLengthToAllTerminals(mTree, tree.getRoot(), waitingTime.nextDouble()*getWaitingTime(taxa.getNumTaxa()));
+			double depth = mTree.tallestPathAboveNode(tree.getRoot());
+			if (depth>0) {
+				double scaleFactor = scaling/depth;
+	 			for (int i=0; i<mTree.getNumNodeSpaces(); i++)
+	 				if (mTree.nodeExists(i)) {
+	 					double b = mTree.getBranchLength(i, MesquiteDouble.unassigned);
+	 					if (MesquiteDouble.isCombinable(b))
+	 						mTree.setBranchLength(i, b*scaleFactor, false);
+	 				}
+			}
+			seed.setValue(randomTaxon.nextLong());  //see for next time
+	   		return mTree;
+   	}
+   
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Uniform speciation (Yule)";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Generates tree by simple uniform probability speciation (a Yule process) as done by Harding (1971).  The"
+ 		+" chance of speciation is equal for all tips." ;
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		return "Trees constrained to branch length depth: " + scaling;
+   	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/trees/EquiprobableTrees/EquiprobableTrees.java b/Source/mesquite/trees/EquiprobableTrees/EquiprobableTrees.java
new file mode 100644
index 0000000..cf3ce39
--- /dev/null
+++ b/Source/mesquite/trees/EquiprobableTrees/EquiprobableTrees.java
@@ -0,0 +1,84 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.EquiprobableTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Creates a random tree such that each distinct labelled topology is equally probable. */
+public class EquiprobableTrees extends TreeSimulate {
+	RandomBetween randomTaxon;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		randomTaxon= new RandomBetween(1);
+ 		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	public int getNumberOfTrees(Taxa taxa) {
+   		return MesquiteInteger.infinite;
+   	}
+	/*.................................................................................................................*/
+   	public Tree getSimulatedTree(Taxa taxa, Tree tree, int treeNumber, ObjectContainer extra, MesquiteLong seed) {
+   	//save random seed used to make tree under tree.seed for use in recovering later
+  			randomTaxon.setSeed(seed.getValue());
+  			if (tree==null || !(tree instanceof MesquiteTree))
+  				 tree = new MesquiteTree(taxa);
+			((MesquiteTree)tree).setToDefaultBush(2, false);
+			int whichNode;
+			
+			for (int taxon = 2; taxon < taxa.getNumTaxa(); taxon++) {
+				whichNode=randomTaxon.randomIntBetween(0, tree.numberOfNodesInClade(tree.getRoot())-1);
+				((MesquiteTree)tree).graftTaxon(taxon, tree.nodeInTraversal(whichNode), false);
+			}
+
+			seed.setValue(randomTaxon.nextLong());  //see for next time
+	   		return tree;
+   	}
+   
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Equiprobable Trees";
+   	 }
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Generates trees randomly so that each possible labelled tree topology is equally likely." ;
+   	 }
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/trees/LabelBranchLengths/LabelBranchLengths.java b/Source/mesquite/trees/LabelBranchLengths/LabelBranchLengths.java
new file mode 100644
index 0000000..684252d
--- /dev/null
+++ b/Source/mesquite/trees/LabelBranchLengths/LabelBranchLengths.java
@@ -0,0 +1,265 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.LabelBranchLengths;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class LabelBranchLengths extends TreeDisplayAssistantD {
+	Vector labelers;
+	static boolean warningGiven = false;
+	boolean useLabels = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		labelers = new Vector();
+		addMenuItem( "Float length labels", makeCommand("floatLabels",  this));
+		addMenuItem( "Remove Length Labels", makeCommand("hideLabels",  this));
+ 		return true;  //should make conditional on whether branch lengths shown
+ 	}
+ 	public boolean getUserChooseable(){
+ 		return false;  //this module is treated as defunct, now that the tree draw coordiantor does it directly, but is retained for compatibility with old scripts
+ 	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		BranchLengthsLabeler bLA = new BranchLengthsLabeler(this, treeDisplay);
+		labelers.addElement(bLA);
+		return bLA;
+	}
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Turns off labeling of branch lengths", null, commandName, "hideLabels")) {
+			iQuit();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Toggles whether the branch length labels are on their own little panels", null, commandName, "floatLabels")) {
+    	 		useLabels = !useLabels;
+			Enumeration e = labelers.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof BranchLengthsLabeler) {
+					BranchLengthsLabeler tCO = (BranchLengthsLabeler)obj;
+		 			tCO.setUseLabels(useLabels);
+		 		}
+			}
+			parametersChanged();
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Label Branch Lengths";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "An assistant to a tree display that labels branches to show their lengths." ;
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns current parameters, for logging etc..*/
+ 	public String getParameters() {
+ 		return "";
+   	 }
+   	 
+   	 public void endJob(){
+		Enumeration e = labelers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof BranchLengthsLabeler) {
+				BranchLengthsLabeler tCO = (BranchLengthsLabeler)obj;
+	 			tCO.turnOff();
+	 		}
+		}
+		super.endJob();
+   	 }
+}
+
+/* ======================================================================== */
+class BranchLengthsLabeler extends TreeDisplayDrawnExtra   {
+	TreeTool adjustTool;
+	HandlesAtNodes handlesAtNodes;
+	int originalX, originalY, lastX, lastY;
+	int idNumber;
+	boolean lineOn = false;
+	boolean useLabels = false;
+	public BranchLengthsLabeler (MesquiteModule ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+	}
+	/*.................................................................................................................*/
+	public void writeLengthAtNode(Graphics g, int N,  Tree tree) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				writeLengthAtNode(g, d, tree);
+				
+		int nodeX = treeDisplay.getTreeDrawing().x[N];
+		int nodeY = treeDisplay.getTreeDrawing().y[N];
+		if (treeDisplay.getOrientation() == treeDisplay.UP) {
+			nodeY+=10;
+			//nodeX+=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.DOWN) {
+			nodeY-=10;
+			//nodeX+=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.RIGHT) {
+			//nodeY=20;
+			nodeX-=10;
+		}
+		else if (treeDisplay.getOrientation() == treeDisplay.LEFT) {
+			//nodeY+=20;
+			nodeX+=10;
+		}
+		StringUtil.highlightString(g, MesquiteDouble.toString(tree.getBranchLength(N)), nodeX, nodeY, Color.blue, Color.white);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (treeDisplay!=null && tree!=null) {
+ 			if (useLabels) {
+	 			if (handlesAtNodes==null)
+	 				handlesAtNodes = new HandlesAtNodes(ownerModule, tree.getNumNodeSpaces(), treeDisplay);
+	 			else if (handlesAtNodes.getTreeDisplay()!=treeDisplay)
+	 				handlesAtNodes = new HandlesAtNodes(ownerModule, tree.getNumNodeSpaces(), treeDisplay);
+	 			else if (handlesAtNodes.getNumNodes()!=tree.getNumNodeSpaces())
+	 				handlesAtNodes.resetNumNodes(tree.getNumNodeSpaces());
+				handlesAtNodes.locatePanels(tree, drawnRoot);
+				handlesAtNodes.showPanels(tree, drawnRoot);
+			}
+			else {
+				g.setColor(Color.blue);
+				writeLengthAtNode(g, drawnRoot, tree);
+				g.setColor(Color.black);
+			}
+		}
+	}
+	public void setUseLabels(boolean use){
+		if (use==useLabels)
+			return;
+		useLabels = use;
+		if (!useLabels) {
+			if (handlesAtNodes!=null)
+			 	handlesAtNodes.dispose();
+			 handlesAtNodes=null;
+			 
+		}
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	
+	public   void setTree(Tree tree) {
+	}
+	public void turnOff() {
+		if (handlesAtNodes!=null)
+			handlesAtNodes.dispose();
+		super.turnOff();
+	}
+}
+	
+
+/* ======================================================================== */
+class HandlesAtNodes extends PanelsAtNodes  {
+	
+	
+	public HandlesAtNodes(MesquiteModule ownerModule, int numNodes, TreeDisplay treeDisplay){
+		super(ownerModule, numNodes, treeDisplay);
+	} 
+	
+	public Panel makePanel(int i){
+		HandlePanel c = new HandlePanel(ownerModule, getTreeDisplay(), i);
+		return c;
+	}
+}
+
+class HandlePanel extends MesquitePanel {
+	MesquiteModule ownerModule;
+	int idNumber;
+	TreeDisplay treeDisplay;
+	int originalX, originalY, lastX, lastY;
+	boolean lineOn = false;
+	
+	public HandlePanel (MesquiteModule ownerModule, TreeDisplay treeDisplay, int idNumber) {
+		this.ownerModule=ownerModule;
+		this.idNumber=idNumber;
+		this.treeDisplay=treeDisplay;
+		setSize(8,8);
+	}
+	
+	public void setTreeDisplay(TreeDisplay treeDisplay){
+		this.treeDisplay=treeDisplay;
+	}
+	public void paint (Graphics g) {//^^^
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		if (treeDisplay==null)  {
+			System.out.println("tree display null in label branch lengths panel");
+			return;
+		}
+		else if (treeDisplay.getTree()==null) {
+			System.out.println("tree null in label branch lengths panel");
+			return;
+		}
+		String s = MesquiteDouble.toStringDigitsSpecified(treeDisplay.getTree().getBranchLength(idNumber), 3);
+		Font font = g.getFont();
+		FontMetrics fontMet = g.getFontMetrics(font);
+		int handleHeight = fontMet.getHeight()+2;
+		int handleWidth = fontMet.stringWidth(s)+8;
+		if (getBounds().width!= handleWidth || getBounds().height!= handleHeight) {
+			setSize(handleWidth,handleHeight);
+		}
+		
+		setBackground(getParent().getBackground());
+		
+		g.setColor( Color.blue);
+		g.drawRoundRect(0,0,getBounds().width, getBounds().height,6,6);
+		for (int green=1; green<9; green++) {
+			g.setColor( new Color((((green*10) & 0xFF)<<16)| (((green*16+100) & 0xFF)<<8)| (255&0xFF)));
+			g.drawRoundRect(green,green,getBounds().width-green-green, getBounds().height-green-green,6, 6);
+		}
+		g.setColor(Color.white);
+		g.fillOval(2,2, 2, 2);
+		g.setColor(Color.black);
+		g.drawString(s,4, getBounds().height-3);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	
+	
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (MesquiteEvent.controlKeyDown(modifiers)) {
+			if (!(treeDisplay.getTree() instanceof AdjustableTree))
+				return;
+			AdjustableTree t = (AdjustableTree)treeDisplay.getTree();
+			double oldLength =t.getBranchLength(idNumber);
+			double newLength = MesquiteDouble.queryDouble(ownerModule.containerOfModule(), "Set Branch length", "Branch Length:", oldLength);
+    	 		if (newLength>=0.0 && newLength!=oldLength) {
+    	 			t.setBranchLength(idNumber, newLength, true);
+    	 			repaint();
+    	 			treeDisplay.pleaseUpdate(false);
+    	 		}
+		}
+	}
+	
+}
+
diff --git a/Source/mesquite/trees/ListedTreeBlocks/ListedTreeBlocks.java b/Source/mesquite/trees/ListedTreeBlocks/ListedTreeBlocks.java
new file mode 100644
index 0000000..3f0ae0b
--- /dev/null
+++ b/Source/mesquite/trees/ListedTreeBlocks/ListedTreeBlocks.java
@@ -0,0 +1,214 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ListedTreeBlocks;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ListedTreeBlocks extends TreeBlockSource {
+	int currentTreeBlockIndex=0;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	Taxa preferredTaxa =null;
+	Taxa currentTaxa = null;
+	MesquiteInteger pos = new MesquiteInteger(0);
+	String pathToList = null;
+	String directoryOfList = "";
+	Vector fileList = null;
+	String exporter = null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+	    	currentTreeBlockIndex = 0;
+		if (!MesquiteThread.isScripting()){ //file dialog to choose picture
+			MesquiteString dir = new MesquiteString();
+			MesquiteString f = new MesquiteString();
+			
+   	 		String path = MesquiteFile.openFileDialog("File with list of tree files", dir, f);
+   	 		String d = dir.getValue();
+   	 		if (!StringUtil.blank(d) && !StringUtil.blank(f.getValue())) {
+   	 			if (!d.endsWith("/")) 
+   	 				d += "/";
+   	 			directoryOfList = d;
+   	 			boolean success;
+   	 			if (getProject().getHomeDirectoryName().equalsIgnoreCase(d)){
+   	 				pathToList = f.getValue();
+   	 				String fullPathToList = MesquiteFile.composePath(getProject().getHomeDirectoryName(), pathToList);
+   	 				if (!MesquiteFile.fileExists(fullPathToList))
+   	 					return sorry(getName() + " couldn't start because file listing tree files not found.");
+   	 				success = readListFile(fullPathToList);
+   	 			}
+   	 			else {
+   	 				pathToList = path;
+   	 				if (!MesquiteFile.fileExists(path))
+   	 					return sorry(getName() + " couldn't start because file listing tree files not found.");
+					success = readListFile(pathToList);
+				}
+				if (!success)
+					return sorry(getName() + " couldn't start because of a problem with the file listing tree files.");
+   	 		}
+   	 		else 
+   	 			return sorry(getName() + " couldn't start because no file listing tree files was specified.");
+   	 	}
+		return true;
+  	 }
+	private boolean readListFile(String path){
+		String list = MesquiteFile.getFileContentsAsString(path);
+		if (list==null)
+			return false;
+		exporter = parser.getFirstToken(list);
+		fileList = new Vector();
+		String token;
+		while (!StringUtil.blank(token = parser.getNextToken())) {
+			fileList.addElement(token);
+		}
+		return fileList.size()>0;
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+    	 	Snapshot temp = new Snapshot();
+  	 	
+		temp.addLine("setList " + StringUtil.tokenize(directoryOfList + pathToList)); //TODO: this should do relative to home file, not absolute
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+     	 	 if (checker.compare(this.getClass(), "Sets the path to the file listing tree files", "[path to file; if relative, should be relative to home file of project]", commandName, "setList")){
+   	 		pathToList = ParseUtil.getFirstToken(arguments, pos);
+  			boolean success = readListFile(MesquiteFile.composePath(getProject().getHomeDirectoryName(), pathToList));
+  			if (!success)
+  				iQuit();
+    	 	 } 
+      	 	 
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	
+	return null;
+   	 }
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+   		if (taxa !=currentTaxa) {
+	  		currentTaxa = taxa;
+  		}
+  		
+  	}
+   	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		setPreferredTaxa(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getFirstBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex=0;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getBlock(Taxa taxa, int ic) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex=ic;
+   		return getCurrentBlock(taxa);
+   	}
+   	private String fileName(int ic){
+   		if (fileList == null || ic >= fileList.size())
+   			return "";
+   		else
+   			return (String)fileList.elementAt(ic);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getCurrentBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		if (taxa == null)
+   			return null;
+ 		incrementMenuResetSuppression();
+		TreeVector newTrees = new TreeVector(taxa);
+ 		MesquiteModule fCoord = getFileCoordinator();
+ 		CommandRecord cr = new CommandRecord(true);
+ 		CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+ 		MesquiteThread.setCurrentCommandRecord(cr);
+ 		MesquiteFile file = (MesquiteFile)fCoord.doCommand("linkTreeFile", StringUtil.tokenize(directoryOfList+fileName(currentTreeBlockIndex)) + "  " + StringUtil.tokenize(exporter), CommandChecker.defaultChecker);
+		MesquiteThread.setCurrentCommandRecord(prevR);
+		if (file == null) {
+			MesquiteMessage.warnProgrammer("file not found, directory (" + directoryOfList + ")  file (" + fileName(currentTreeBlockIndex) + ") currentTreeBlockIndex " + currentTreeBlockIndex);
+	 		decrementMenuResetSuppression();
+			return newTrees;
+		}
+		ListableVector vectors = file.getFileElements();
+		if (vectors !=null && vectors.size()>0) {
+	   		for (int i = 0; i<vectors.size(); i++){
+	   			if (vectors.elementAt(i) instanceof TreeVector){
+		   			TreeVector trees =  (TreeVector)vectors.elementAt(i);
+		   			if (trees.getTaxa().equals(taxa)) {
+				 		for (int t=0; t<trees.size(); t++){
+				 			newTrees.addElement(trees.elementAt(t), false);
+				 		}
+				 		getProject().removeFile(file);
+				 		decrementMenuResetSuppression();
+		   				return newTrees;
+		   			}
+	   			}
+			}
+		}
+		
+ 		decrementMenuResetSuppression();
+		return newTrees;
+		
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getNextBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex++;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTreeBlocks(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		if (fileList == null)
+   			return 0;
+   		return fileList.size();
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeBlockNameString(Taxa taxa, int index) {
+   		setPreferredTaxa(taxa);
+		return "Tree block from " + fileName(index);
+   	}
+		/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree Blocks from Files Listed In File";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Supplies tree blocks in files listed in a file." ;
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+			return "File containing list of tree files: " + pathToList;
+   	}
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/trees/ManageTrees/ManageTrees.java b/Source/mesquite/trees/ManageTrees/ManageTrees.java
new file mode 100644
index 0000000..9f9fb2e
--- /dev/null
+++ b/Source/mesquite/trees/ManageTrees/ManageTrees.java
@@ -0,0 +1,1989 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ManageTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/** Manages blocks of trees, including reading the NEXUS blocks of trees */
+public class ManageTrees extends TreesManager {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(mesquite.lists.TreesList.TreesList.class, "This manages the List of Trees windows.",
+				"It is activated automatically. ");
+		EmployeeNeed e3 = registerEmployeeNeed(mesquite.lists.TreeblockList.TreeblockList.class, "This manages the List of Tree Blocks windows.",
+				"It is activated automatically. ");
+
+
+
+		EmployeeNeed e2 = registerEmployeeNeed(TreeBlockFiller.class, "Tree blocks can be generated and added to the file.",
+				"To create and fill a new tree block, select Make New Trees Block From... in the Taxa&Trees menu. ");
+		e2.setPriority(2);
+		e2.setAlternativeEmployerLabel("Trees block manager");
+		e2.setEntryCommand("newFilledTreeBlockInt");
+		EmployeeNeed e4 = registerEmployeeNeed(TreeInferer.class, "Tree blocks can come from a tree inference method and be added to the file.",
+				"To request a tree inference method, select Tree Inference... in the Taxa&Trees menu. ");
+		e4.setPriority(2);
+		e4.setAlternativeEmployerLabel("Trees block manager");
+		e4.setEntryCommand("newFilledTreeBlockInferenceInt");
+	}
+	ListableVector treesVector;
+	ListableVector taxas;
+	TreeBlockFiller treeFillerTask;  //For make new trees block from  
+	String treeFillerTaxaAssignedID = null;  
+	Vector blockListeners = null;
+	boolean fillingTreesNow = false;
+	MesquiteBoolean separateThreadFill; 
+	MesquiteBoolean autoSaveInference ;
+	//todo: have a single TreeBlockFiller employee belong to the module causes re-entrancy problems, if several long searches are on separate threads.
+	//The searches themselves should work fine, but there is a possibility of user-interface confuses.
+
+	boolean showTreeFiller = false; //adds menu item that can be used to set default tree filler; an aid in writing scripts, for then the tree filler snapshot is put into files
+	Vector fillerThreads;  // for the TreeBlockThread and TreeMonitorThreads, to be able to shut them off as needed
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treesVector = new ListableVector();
+		fillerThreads = new Vector();
+		blockListeners = new Vector();
+		setMenuToUse(MesquiteTrunk.treesMenu);
+		separateThreadFill = new MesquiteBoolean(true);
+		autoSaveInference = new MesquiteBoolean(false);
+		loadPreferences();
+		return true;
+	}
+
+	public void elementsReordered(ListableVector v){
+		if (v == treesVector){
+			NexusBlock.equalizeOrdering(v, getProject().getNexusBlocks());
+		}
+	}
+	public void addBlockListener(MesquiteListener ml){
+		blockListeners.addElement(ml);
+		for (int i= 0; i<treesVector.size(); i++)
+			((TreeVector)treesVector.elementAt(i)).addListener(ml);
+	}
+	public void removeBlockListener(MesquiteListener ml){
+		blockListeners.removeElement(ml);
+		for (int i= 0; i<treesVector.size(); i++)
+			((TreeVector)treesVector.elementAt(i)).removeListener(ml);
+	}
+	/*.................................................................................................................*/
+	public MesquiteModule showElement(FileElement e){
+		if (e instanceof TreeVector)
+			return showTreesList((TreeVector)e);
+		return null;
+	}
+	public void deleteElement(FileElement e){
+		if (e instanceof TreeVector){
+			TreeVector trees = (TreeVector)e;
+
+			trees.doom();
+			getProject().removeFileElement(trees);//must remove first, before disposing
+
+			trees.dispose();
+		}
+	}
+	/*.................................................................................................................*/
+	MesquiteModule showTreesList(TreeVector trees){
+		//Check to see if already has lister for this
+		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(trees)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Trees List"));
+		if (lister==null){
+			alert("Sorry, no module was found to list the trees");
+			return null;
+		}
+		lister.showListWindow(trees);
+		if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+			lister.getModuleWindow().setVisible(true);
+		return lister;
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (fillerThreads != null){
+			int numThreads = fillerThreads.size();
+			for (int i = numThreads-1; i>=0; i--){
+				FillerThread thread = (FillerThread)fillerThreads.elementAt(i);
+				thread.stopFilling();
+				thread.threadGoodbye();
+				thread.interrupt();
+			}
+		}
+		if (taxas!=null) {
+			int numTaxas = taxas.size();
+			for (int i=0; i<numTaxas; i++){
+				Taxa taxa = (Taxa)taxas.elementAt(i);
+				taxa.removeListener(this);
+			}
+			taxas.removeListener(this);
+		}
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa) {
+			Taxa taxa = (Taxa)obj;
+			taxa.removeListener(this);
+			int numSets = treesVector.size();
+			for (int i=0; i<numSets ; i++) {
+				TreeVector treeBlock = (TreeVector)treesVector.elementAt( i);
+				if (treeBlock!=null && treeBlock.getTaxa()==taxa) {
+					getProject().removeFileElement(treeBlock);//must remove first, before disposing
+				}
+			}
+
+			boolean someDeleted = true;
+			while (someDeleted){
+				someDeleted = false;
+				for (int i=numSets; i>=0 && !someDeleted ; i--) {
+					TreeVector treeBlock = (TreeVector)treesVector.elementAt( i);
+					if (treeBlock!=null && treeBlock.getTaxa()==taxa) {
+						treesVector.removeElement(treeBlock, true);
+						someDeleted = true;
+						treeBlock.dispose();
+					}
+				}
+			}
+			resetAllMenuBars();
+
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (obj instanceof ListableVector && obj == taxas) {
+			reviseListeners();
+		}
+		else if (obj instanceof Taxa) {
+		}
+	}
+	/*.................................................................................................................*/
+	void reviseListeners(){
+		if (taxas==null)
+			return;
+		int numTaxas = taxas.size();
+		for (int i=0; i<numTaxas; i++){
+			Taxa taxa = (Taxa)taxas.elementAt(i);
+			if (taxa!=null && !taxa.amIListening(this))
+				taxa.addListener(this);
+		}
+	}
+	/*.................................................................................................................*/
+	/** A method called immediately after the file has been read in.*/
+	public void projectEstablished() {
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		MesquiteSubmenuSpec mmis = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "List of Trees", makeCommand("showTrees",  this), treesVector);
+		mmis.setBehaviorIfNoChoice(MesquiteSubmenuSpec.ONEMENUITEM_ZERODISABLE);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "List of Tree Blocks", makeCommand("showTreeBlocks",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "Delete Tree Blocks...", makeCommand("deleteTreeBlocks",  this));
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "New Empty Block of Trees...", makeCommand("newTreeBlock",  this));
+		getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Make New Trees Block from", makeCommand("newFilledTreeBlockInt",  this), TreeBlockFiller.class);
+		if (numModulesAvailable(TreeInferer.class)>0 && MesquiteTrunk.mesquiteModulesInfoVector.findModule(null, "#TreeInferenceCoordinator")==null)  //ExternalTreeSearcher
+			getFileCoordinator().addSubmenu(MesquiteTrunk.analysisMenu, "Tree Inference", makeCommand("newFilledTreeBlockInferenceInt",  this), TreeInferer.class);
+		MesquiteSubmenuSpec mss = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Import File with Trees");
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Link Contents...", makeCommand("linkTreeFile",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Include Contents...", makeCommand("includeTreeFile",  this));
+		getFileCoordinator().addItemToSubmenu(MesquiteTrunk.treesMenu, mss, "Include Partial Contents...", makeCommand("includePartialTreeFile",  this));
+		MesquiteSubmenuSpec mmis2 = getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Save Copy of Tree Block...", makeCommand("exportTreesBlock",  this),  treesVector);
+		mmis2.setBehaviorIfNoChoice(MesquiteSubmenuSpec.SHOW_SUBMENU);
+		getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Save Copies of Tree Blocks", makeCommand("exportTreesBlocks",  this), TreeBlockSource.class);
+		if (showTreeFiller)
+			getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "SetTreeFillerTask", makeCommand("setTreeSource",  this), TreeBlockFiller.class);
+		getFileCoordinator().addSubmenu(MesquiteTrunk.treesMenu, "Save Trees To File from", makeCommand("saveDrectTreeFileInt",  this), TreeSource.class);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+		getFileCoordinator().addModuleMenuItems( MesquiteTrunk.treesMenu, makeCommand("newAssistant",  getFileCoordinator()), FileAssistantT.class);
+		getFileCoordinator().addMenuItem(MesquiteTrunk.treesMenu, "-", null);
+
+		taxas = getProject().getTaxas();
+		taxas.addListener(this);
+		reviseListeners();
+		super.projectEstablished();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		if (file == null || file == getProject().getHomeFile()){
+			for (int i = 0; i< treesVector.size(); i++) {
+				TreeVector trees = (TreeVector)treesVector.elementAt(i);
+				Snapshot fromTrees = trees.getSnapshot(file);
+				if (fromTrees != null && fromTrees.getNumLines() > 0) {
+					temp.addLine("getTreeBlock " + i);  // a bit of a danger here that treeblock misidentified
+					temp.addLine("tell It");
+					temp.incorporate(fromTrees, true);
+					temp.addLine("endTell");
+				}
+			}
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Trees List")) {
+				Object o = e.doCommand("getTreeBlock", null, CommandChecker.defaultChecker);
+				if (o !=null && o instanceof TreeVector) {
+					int wh = getTreeBlockNumber((TreeVector)o);
+					temp.addLine("showTrees " + wh, e); 
+				}
+			}
+		}
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			MesquiteModule e=(MesquiteModule)getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant && (e.getModuleWindow()!=null) && e.getModuleWindow().isVisible() && e.getName().equals("Tree Blocks List")) {
+				temp.addLine("showTreeBlocks ", e); 
+			}
+		}
+
+		if (fillingTreesNow && treeFillerTask !=null && treeFillerTask.getReconnectable()!=null){  //Defunct when new system in place
+			temp.addLine("restartTreeSource ", treeFillerTask);
+			temp.addLine("reconnectTreeSource " + StringUtil.tokenize(treeFillerTaxaAssignedID));
+		}
+		else if (showTreeFiller && treeFillerTask !=null)  
+			temp.addLine("setTreeSource ", treeFillerTask);
+
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	MesquiteModule showTrees(TreeVector tx){
+		boolean found = false;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof ManagerAssistant)
+				if (((ManagerAssistant)e).showing(tx)) {
+					((ManagerAssistant)e).getModuleWindow().setVisible(true);
+					return ((ManagerAssistant)e);
+				}
+		}
+
+		ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, "#TreesList");
+		if (lister==null){
+			discreetAlert("Sorry, no module was found to list the trees");
+			return null;
+		}
+		lister.showListWindow(tx);
+		if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+			lister.getModuleWindow().setVisible(true);
+		return lister;
+	}
+
+	/*.................................................................................................................*/
+	public void exportTreesBlock(TreeVector trees, String path) {
+		if (trees==null)
+			return;
+		incrementMenuResetSuppression();
+
+		FileCoordinator coord = getFileCoordinator();
+		MesquiteFile tempDataFile = (MesquiteFile)coord.doCommand("newLinkedFile", StringUtil.tokenize(path), CommandChecker.defaultChecker); //TODO: never scripting???
+		trees.attachCloneToFile(tempDataFile,this);
+		coord.writeFile(tempDataFile);
+
+		decrementMenuResetSuppression();
+		tempDataFile.close();
+	}
+	/* ................................................................................................................. */
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis"). */
+	public String purposeOfEmployee(MesquiteModule employee) {
+		if (employee instanceof TreeBlockFiller)
+			return "to make block of trees";
+		return "for the trees manager"; // to be overridden
+	}
+
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns a trees block", "[number of trees block; 0 based]", commandName, "getTreeBlock")) {
+			int t = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(t) && t<treesVector.size()) {
+				TreeVector tx = (TreeVector)treesVector.elementAt(t);
+				return tx;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows lists of trees in a trees block", "[number of trees block; 0 based]", commandName, "showTrees")) {
+			int t = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (StringUtil.blank(arguments) || !MesquiteInteger.isCombinable(t) || t>treesVector.size()) {
+				for (int i = 0; i< treesVector.size(); i++) {
+					showTrees((TreeVector)treesVector.elementAt(i));
+				}
+			}
+			else {
+				TreeVector tx = (TreeVector)treesVector.elementAt(t);
+				return showTrees(tx);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows a tree window showing a particular trees block", "[number of tree block to show]", commandName, "showTreesInWindow")) {
+			int t = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(t) && t<getProject().getNumberOfFileElements(TreeVector.class)) {
+				MesquiteModule fCoord = getFileCoordinator();
+				MesquiteModule treeWindowCoord = null;
+				if (fCoord!=null)
+					treeWindowCoord = fCoord.findEmployeeWithName("Tree Window Coordinator");
+				if (treeWindowCoord!=null){
+					TreeVector trees = (TreeVector)getProject().getFileElement(TreeVector.class, t);
+					if (trees == null)
+						return null;
+					Taxa taxa = trees.getTaxa();
+					//send script to tree window coord to makeTreeWindow with set of taxa and then set to stored trees and this tree vector
+					int whichTreeBlock = getTreeBlockNumber(taxa, trees);
+
+					//first, find if there is a tree window showing these trees
+					MesquiteModule twm = null;
+					ListableVector v = treeWindowCoord.getEmployeeVector();
+					for (int i = 0; i< v.size(); i++){
+						if (v.elementAt(i) instanceof TreeWindowMaker){
+							MesquiteWindow tw = ((MesquiteModule)v.elementAt(i)).getModuleWindow();
+							if (tw != null){
+								Object obj = tw.doCommand("getTreeVector", null, CommandChecker.defaultChecker);
+								if (obj != null && obj == trees)
+									twm = (MesquiteModule)v.elementAt(i);
+							}
+						}
+					}
+					if (twm != null){  // trees block is being shown; go there
+						MesquiteWindow tw = twm.getModuleWindow();
+						tw.setVisible(true);
+						tw.getParentFrame().showFrontWindow();
+						return null;
+					}
+
+					//not shown; need to make new tree window
+					String commands = "makeTreeWindow " + getProject().getTaxaReferenceInternal(taxa) + "  #BasicTreeWindowMaker; tell It; setTreeSource  #StoredTrees;";
+					commands += " tell It; setTaxa " + getProject().getTaxaReferenceInternal(taxa) + " ;  setTreeBlock " + TreeVector.toExternal(whichTreeBlock)  + "; endTell; getWindow; tell It; setSize 400 300; endTell; showWindowForce; endTell; ";
+					MesquiteInteger pos = new MesquiteInteger(0);
+					Puppeteer p = new Puppeteer(this);
+					p.execute(treeWindowCoord, commands, pos, null, false);
+					/*
+					 */
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Saves copy of a trees block to a separate file", "[index of trees block]", commandName, "exportTreesBlock")) {
+			int t = MesquiteInteger.fromString(parser.getFirstToken(arguments));
+			if (MesquiteInteger.isCombinable(t) && t< getProject().getNumberOfFileElements(TreeVector.class)) {
+				String path = parser.getNextToken();
+				int id = MesquiteInteger.fromString(path);
+				if (MesquiteInteger.isCombinable(id))
+					path = parser.getNextToken();
+				TreeVector d = (TreeVector)getProject().getFileElement(TreeVector.class, t);
+				if (d!=null) {
+					if (StringUtil.blank(path))
+						path = MesquiteFile.saveFileAsDialog("Save copy of tree block to file");
+					else
+						path = MesquiteFile.composePath(getProject().getHomeDirectoryName(), path);
+					if (!StringUtil.blank(path))
+						exportTreesBlock(d, path);
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Saves copies of a series of tree blocks to files", "[name of module to fill the trees blocks]", commandName, "exportTreesBlocks")) {
+			//ask user how which taxa, how many characters
+			//create chars block and add to file
+			//return chars
+			if (fillingTreesNow){
+				discreetAlert( "Sorry, a new tree block is currently being filled.  You must wait for that to finish before asking for exporting trees blocks.");
+				return null;
+			}
+
+			TreeVector newTrees=null;
+			Taxa taxa = null;
+			if (getProject().getNumberTaxas()==0) {
+				alert("Trees blocks cannot be created until taxa exist in file.");
+				return null;
+			}
+			else 
+				taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to save copies of trees blocks?");
+			if (taxa == null)
+				return null;
+			TreeBlockSource treeBlocksForExportTask;
+			treeFillerTaxaAssignedID = getProject().getTaxaReferenceExternal(taxa);
+			if (StringUtil.blank(arguments))
+				treeBlocksForExportTask = (TreeBlockSource)hireEmployee(TreeBlockSource.class, "Save copies of trees blocks from:");
+			else
+				treeBlocksForExportTask = (TreeBlockSource)hireNamedEmployee(TreeBlockSource.class, arguments);
+			if (treeBlocksForExportTask != null) {
+				String basePath = MesquiteFile.saveFileAsDialog("Base name for files (files will be named <name>1.nex, <name>2.nex, etc.)");
+				if (StringUtil.blank(basePath)) {
+					fireEmployee(treeBlocksForExportTask);
+					resetAllMenuBars();
+					return null;
+				}
+				treeBlocksForExportTask.initialize(taxa);
+
+				int num = treeBlocksForExportTask.getNumberOfTreeBlocks(taxa);
+				if (!MesquiteInteger.isCombinable(num))
+					num = MesquiteInteger.queryInteger(containerOfModule(), "How many trees blocks?", "How many trees blocks of which to save copies?", 10);
+				if (!MesquiteInteger.isCombinable(num)) {
+					fireEmployee(treeBlocksForExportTask);
+					resetAllMenuBars();
+					return null;
+				}
+				for (int iBlock = 0; iBlock<num; iBlock++){
+					TreeVector trees = treeBlocksForExportTask.getBlock(taxa, iBlock);
+					if (trees!=null)
+						exportTreesBlock(trees, basePath + iBlock + ".nex");
+				}
+				if (!showTreeFiller){
+					fireEmployee(treeBlocksForExportTask);
+					treeFillerTaxaAssignedID = null;
+				}
+				resetAllMenuBars();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Shows a list of the stored tree blocks", null, commandName, "showTreeBlocks")) {
+			//Check to see if already has lister for this
+			boolean found = false;
+			for (int i = 0; i<getNumberOfEmployees(); i++) {
+				Object e=getEmployeeVector().elementAt(i);
+				if (e instanceof ManagerAssistant)
+					if ( ((ManagerAssistant)e).getName().equals("Tree Blocks List")) {
+						((ManagerAssistant)e).getModuleWindow().setVisible(true);
+						return e;
+					}
+			}
+			ManagerAssistant lister= (ManagerAssistant)hireNamedEmployee(ManagerAssistant.class, StringUtil.tokenize("Tree Blocks List"));
+			if (lister==null){
+				alert("Sorry, no module was found to list the tree blocks");
+				return null;
+			}
+			lister.showListWindow(null);
+			if (!MesquiteThread.isScripting() && lister.getModuleWindow()!=null)
+				lister.getModuleWindow().setVisible(true);
+			return lister;
+		}
+		else if (checker.compare(this.getClass(), "Deletes tree blocks from the project", null, commandName, "deleteTreeBlocks")) {
+			Listable[] chosen = ListDialog.queryListMultiple(containerOfModule(), "Select Tree Blocks to Delete", "Select one or more tree blocks to be deleted", (String)null, "Delete", false, getProject().getTreeVectors(), (boolean[])null);
+			if (chosen != null){
+				for (int i = chosen.length-1; i>=0; i--) {  
+					((FileElement)chosen[i]).doom();
+				}
+				getProject().incrementProjectWindowSuppression();
+				for (int i = chosen.length-1; i>=0; i--) {  
+					logln("Deleting " + chosen[i].getName());
+					deleteElement((FileElement)chosen[i]);
+				}
+				getProject().decrementProjectWindowSuppression();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Restarts to unfinished tree block filling", "[name of tree block filler module]", commandName, "restartTreeSource")) { 
+			TreeBlockFiller temp=  (TreeBlockFiller)replaceEmployee(TreeBlockFiller.class, arguments, "Source of trees", treeFillerTask);
+			if (temp!=null) {
+				treeFillerTask = temp;
+			}
+			return treeFillerTask;
+		}
+		else if (checker.compare(this.getClass(), "Reconnects to unfinished tree block filling", "[name of tree block filler module]", commandName, "reconnectTreeSource")) { 
+			TreeBlockMonitorThread thread = new TreeBlockMonitorThread(this, parser.getFirstToken(arguments), treeFillerTask);
+			fillingTreesNow = true;
+			fillerThreads.addElement(thread);
+
+			thread.start();
+			return null;
+		}
+
+		else if (checker.compare(this.getClass(), "Informs Manage trees that trees are ready", "[ID of tree block filler module]", commandName, "treesReady")) { 
+			// may need to pass more info to be able to connect to right filltask etc, especially if multithreading
+			if (treeFillerTask != null){
+				String taxaID = parser.getFirstToken(arguments);
+				Taxa taxa = null;
+				if (taxaID !=null)
+					taxa = getProject().getTaxa(taxaID);
+				if (taxa == null)
+					taxa = getProject().getTaxa(0);
+				TreeVector trees = new TreeVector(taxa); 
+				treeFillerTask.retrieveTreeBlock(trees, 100);
+				trees.addToFile(getProject().getHomeFile(), getProject(), this);
+				doneQuery(treeFillerTask, trees.getTaxa(), trees, true);
+				fireTreeFiller();
+				resetAllMenuBars();
+			}
+			return null;
+		}
+
+		else if (checker.compare(this.getClass(), "Fires the tree source for use in filling newly created tree blocks",null, commandName, "fireTreeSource")) { 
+			if (treeFillerTask!=null) {
+				fireTreeFiller();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree source for use in filling newly created tree blocks", "[name of tree block filler module]", commandName, "setTreeSource")) { 
+			if (fillingTreesNow){
+				discreetAlert( "Sorry, a new tree block is currently being filled.  You must wait for that to finish before setting a new tree source.");
+				return null;
+			}
+			TreeBlockFiller temp=  (TreeBlockFiller)replaceEmployee(TreeBlockFiller.class, arguments, "Source of trees", treeFillerTask);
+			if (temp!=null) {
+				treeFillerTask = temp;
+			}
+			return treeFillerTask;
+		}
+		else if (checker.compare(this.getClass(), "Links file with trees", null, commandName, "linkTreeFile")) { 
+			MesquiteModule fCoord = getFileCoordinator();
+			fCoord.doCommand("linkTreeFile", StringUtil.argumentMarker + "fuseTreeBlocks", checker);
+		}
+		else if (checker.compare(this.getClass(), "Includes file with trees", null, commandName, "includeTreeFile")) { 
+			MesquiteModule fCoord = getFileCoordinator();
+			fCoord.doCommand("includeTreeFile", null, checker);
+		}
+		else if (checker.compare(this.getClass(), "Includes file with trees (partial)", null, commandName, "includePartialTreeFile")) { 
+			includeTreeFile(commandName, arguments, checker, true);
+		}
+		else if (checker.compare(this.getClass(), "Includes file with trees (ask if partial)", null, commandName, "includeTreeFileAskPartial")) {
+			boolean all = AlertDialog.query(containerOfModule(), "Read All Trees?", "Read all trees, or only a sample of the trees?", "All", "Sample");
+
+			includeTreeFile(commandName, arguments, checker, !all);
+		}
+		else if (checker.compare(this.getClass(), "Creates a new tree block", "[reference of taxa block] [identification number of file to which tree block will belong] [name of tree block]", commandName, "newTreeBlock")) { 
+			//first argument: taxa; second argument: id of file to which to add; third argument name of tree block
+			Taxa taxa=null;
+			MesquiteFile file=null;
+			String listName = null;
+			if (getProject().getNumberTaxas()==0){
+				discreetAlert("A taxa block must be created first before making a tree block");
+				return null;
+			}
+			if (StringUtil.blank(arguments)){ //no taxa specified && no file specified
+				if (getProject().getNumberTaxas()==1 || MesquiteThread.isScripting()) {
+					taxa = getProject().getTaxa(0);
+				}
+				else {
+					ListableVector taxas = getProject().getTaxas();
+					taxa = (Taxa)ListDialog.queryList(containerOfModule(), "Select taxa", "Select taxa (for new tree block)", MesquiteString.helpString,taxas, 0);
+				}
+				file = chooseFile( taxa);
+			}
+			else {
+				taxa = getProject().getTaxaLastFirst(parser.getFirstToken(arguments));
+				int fileID = MesquiteInteger.fromString(parser.getNextToken());
+				if (!MesquiteInteger.isCombinable(fileID))
+					file = getProject().getHomeFile();
+				else
+					file = getProject().getFileByID(fileID);
+				listName = parser.getNextToken();
+			}
+			if (taxa==null || file == null)
+				return null;
+			if (StringUtil.blank(listName)) {
+				if (!MesquiteThread.isScripting()) 
+					listName = MesquiteString.queryShortString(containerOfModule(), "Name of trees block", "Name of trees block", treesVector.getUniqueName("Trees"));
+
+				if (StringUtil.blank(listName))
+					return null;
+			}
+			TreeVector trees = makeNewTreeBlock(taxa, listName, file);
+
+			resetAllMenuBars();
+
+			return trees;
+		}
+		else if (checker.compare(this.getClass(), "Concatenates the last tree block into the second last", null, commandName, "concatLastTwo")) { 
+			int n = treesVector.size();
+			if (n<2)
+				return null;
+			TreeVector ultimate = (TreeVector)treesVector.elementAt(n-1);
+			TreeVector penultimate = (TreeVector)treesVector.elementAt(n-2);
+			int target = n-3;
+			while (penultimate.getTaxa()!=ultimate.getTaxa() && target>0)
+				penultimate = (TreeVector)treesVector.elementAt(target);
+			if (penultimate.getTaxa()!=ultimate.getTaxa())
+				return null;
+			for (int j=0; j<ultimate.size(); j++){
+				Tree tree = ultimate.getTree(j);
+				if (tree!=null)
+					penultimate.addElement(tree.cloneTree(), false);
+			}
+			getProject().removeFileElement(ultimate);//must remove first, before disposing
+			ultimate.dispose();
+		}
+		else if (checker.compare(this.getClass(), "Disposes the last block of trees", null, commandName, "disposeLastTreeBlock")) { 
+			int n = treesVector.size();
+			if (n<1)
+				return null;
+			TreeVector ultimate = (TreeVector)treesVector.elementAt(n-1);
+			getProject().removeFileElement(ultimate);
+			ultimate.dispose();
+		}
+		else if (checker.compare(this.getClass(), "Creates a new filled tree block (internally called, used for scripting)", "[reference of taxa block] [optional -- if id then next token is id not number][number of file in which the tree block should be stored] [name of tree block] [how many trees to make]", commandName, "newFilledTreeBlockIntS")) { 
+			if (treeFillerTask == null) //needs to have been previously set
+				return null;
+			Taxa taxa = getProject().getTaxa(parser.getFirstToken(arguments));
+			if (taxa == null)
+				return null;
+			if (fillingTreesNow){
+				discreetAlert( "Sorry, another new tree block is currently being filled.  You must wait for that to finish before asking for another new tree block.");
+				return null;
+			}
+			treeFillerTaxaAssignedID = getProject().getTaxaReferenceExternal(taxa);
+			boolean useID = false;
+			MesquiteFile file=null;
+			String idd = parser.getNextToken();
+			if ("home".equalsIgnoreCase(idd))
+				file = getProject().getHomeFile();
+			else {
+				if ("id".equalsIgnoreCase(idd)) {
+					idd = parser.getNextToken();
+					useID = true;
+				}
+
+				int whichFile = MesquiteInteger.fromString(idd);
+				if (!MesquiteInteger.isCombinable(whichFile))
+					return null;
+				if (useID)
+					file = getProject().getFileByID(whichFile);
+				else
+					file = getProject().getFile(whichFile);
+			}
+			if (file == null)
+				return null;
+			String name = parser.getNextToken();
+
+
+			TreeVector trees = new TreeVector(taxa);
+			if (trees == null)
+				return null;
+			int howManyTrees =0;
+			if (treeFillerTask instanceof TreeSource)
+				howManyTrees =((TreeSource)treeFillerTask).getNumberOfTrees(trees.getTaxa());
+			if (!treeFillerTask.hasLimitedTrees(trees.getTaxa())){
+				howManyTrees = MesquiteInteger.fromString(parser.getNextToken());
+				if (!MesquiteInteger.isCombinable(howManyTrees)) {
+					return null;
+				}
+			}
+
+			int separateThread = 0;
+			MesquiteBoolean autoSave = new MesquiteBoolean(false);
+			if (!MesquiteThread.isScripting() && treeFillerTask.permitSeparateThreadWhenFilling())
+				separateThread= separateThreadQuery("Fill tree block", autoSave, false);
+			if (separateThread==1) {  //separateThread
+				fillingTreesNow = true;
+				TreeBlockThread tLT = new TreeBlockThread(this, treeFillerTask, trees, howManyTrees, autoSave, file);
+				fillerThreads.addElement(tLT);
+				/*DISCONNECTABLE: have third option, Run and Come Back (Disconnect).  This is available only for some tree block fillers that say they can do it.
+				Add to tree block filler a method startTreeFilling(TreesDoneListener this) that is called 
+				(not on a separate thread -- that is the responsibility of the tree block filler, as sometimes it will be the filler's own time involved, sometimes
+				an external program, and it will be the tree block filler's responsibility to poll for the external being done, and it will have to do that on its own thread.)
+
+				When the tree block filler detects the trees are ready, it calls a method to notify the TreesDoneListener that the trees are ready.  
+				This perhaps will be done via an intermediary command on the main thread so that the response is on the main thread.  
+				ManageTrees will therefore get notified that the trees are ready, and will therefore ask the tree block filler to actually fill the block of trees, and continue.
+
+				If the file is saved and closed before it's done, ManageTrees should snapshot setOngoingTreeBlockFiller in which it hires the tree block filler and then
+				re-registers as the TreesDoneListener.  The tree block filler would save a snapshot to remember what are the locations of the files and external searcher, 
+				and the criteria for its being done (e.g. the presence of a file).  When rehired it would load all that and check to see if the criterion was met, starting
+				a thread to check, and when done, would notify the TreesDoneListener
+
+
+				 */
+				tLT.start();
+			}
+			else if (separateThread == 0) {// same thread
+				long s = System.currentTimeMillis();
+				int before = trees.size();
+				treeFillerTask.fillTreeBlock(trees, howManyTrees);
+
+				if (trees.size()==before) {
+					logln("Sorry, no trees were returned by " + treeFillerTask.getName());
+					return null;
+				}
+
+				trees.setName(name);
+				logln(Integer.toString(trees.size()) + " trees stored in tree block, from " + treeFillerTask.getName());
+				trees.addToFile(file, getProject(), this);
+				if (autoSave != null && autoSave.getValue()){
+					FileCoordinator fCoord = getFileCoordinator();
+					fCoord.writeFile(file);
+				}
+				return trees;
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Creates a new filled tree block (internally called from menu item)", "[name of tree source module]", commandName, "newFilledTreeBlockInt")) {
+			if (getProject().getNumberTaxas()==0){
+				discreetAlert("A taxa block must be created first before making a tree block");
+				return null;
+			}
+			newTreeBlockFilledInt(commandName, arguments, checker, false, "Fill tree block", false);
+		}
+		else if (checker.compare(this.getClass(), "Creates a new tree file written directly from a tree source (internally called from menu item)", "[name of tree source module]", commandName, "saveDrectTreeFileInt")) {
+			saveDirectTreeFileCoord(commandName, arguments, checker, false);
+		}
+		else if (checker.compare(this.getClass(), "Creates a new filled tree block (internally called from menu item) using a tree inference procedure", "[name of tree source module]", commandName, "newFilledTreeBlockInferenceInt")) {
+			if (getProject().getNumberTaxas()==0){
+				discreetAlert("A taxa block must be created first before making a tree block");
+				return null;
+			}
+			newTreeBlockFilledInt(commandName, arguments, checker, true, "Do tree inference", true);  //This handler will be Defunct when new system in place
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*-----------------------------------------------------------------*/
+	void includeTreeFile(String commandName, String arguments, CommandChecker checker, boolean partial){
+		if (!partial){
+			MesquiteModule fCoord = getFileCoordinator();
+			fCoord.doCommand("includeTreeFile", null, checker);
+			return;
+		}
+		//this changed considerably between 1.0 and 1.01, using ManyTreesFromFile to avoid memory overflow
+		if (!MesquiteThread.isScripting()){  //only non-scripting
+			MesquiteInteger buttonPressed = new MesquiteInteger();
+			ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Trees to Include",  buttonPressed);
+			IntegerField firstTree = dialog.addIntegerField("First Tree to Read:", 1, 16);
+			IntegerField lastTree = dialog.addIntegerField("Last Tree to Read:", MesquiteInteger.infinite, 16);
+			IntegerField everyNth = dialog.addIntegerField("Sample Every nth tree:", 1, 16);
+			dialog.completeAndShowDialog(true);
+			dialog.dispose();
+			if (buttonPressed.getValue()!=0) 
+				return;
+			arguments = "";
+
+			TreeSource temp = (TreeSource)hireNamedEmployee(TreeSource.class, "#mesquite.trees.ManyTreesFromFile.ManyTreesFromFile");
+			if (temp == null)
+				discreetAlert( "Sorry, the file could not be read because the module \"Trees Directly from File\" could not be started");
+			else {
+				int start = 0;
+				int last = MesquiteInteger.infinite;
+				int every = 1;
+				if (MesquiteInteger.isCombinable(firstTree.getValue()) && firstTree.getValue() != 1)
+					start = firstTree.getValue() - 1;
+				if (MesquiteInteger.isCombinable(lastTree.getValue()))
+					last = (lastTree.getValue() - 1);
+				if (MesquiteInteger.isCombinable(everyNth.getValue()) && everyNth.getValue() != 1)
+					every = (everyNth.getValue());
+				Tree first = temp.getTree(null, 0);  //get first tree to figure out taxa block!
+				if (first == null) {
+					fireEmployee(temp);
+					discreetAlert( "Sorry, no tree was obtained");
+					return;
+				}
+				Taxa taxa = first.getTaxa();
+				MesquiteFile file = chooseFile( taxa);
+				if (file == null){
+					fireEmployee(temp);
+					return;
+				}
+				TreeVector trees = new TreeVector(taxa);
+				Tree tree = null;
+				for (int i= start; (i < last) && (i == start || tree !=null); i+= every){
+					tree = temp.getTree(taxa, i);
+					if (tree !=null)
+						trees.addElement(tree, false);
+				}
+
+				trees.setName(temp.getParameters());
+				trees.addToFile(file, getProject(), this);
+
+				fireEmployee(temp);
+				resetAllMenuBars();
+			}
+		}
+
+	}
+
+	void fireTreeFiller(){
+		fireEmployee(treeFillerTask);  
+		treeFillerTask = null;
+		treeFillerTaxaAssignedID = null;
+		fillingTreesNow = false;
+	}
+	/*-----------------------------------------------------------------*/
+	//isInference argument will presumably be defunct when inference switches to new module
+	Object newTreeBlockFilledInt(String commandName, String arguments, CommandChecker checker, boolean suppressAsk, String taskName, boolean isInference){
+		//arguments that should be accepted: (1) tree source, (2) which taxa, (3)  file id, (4) name of tree block, (5) how many trees  [number of taxa block] [identification number of file in which the tree block should be stored] [name of tree block] [how many trees to make]
+		if (fillingTreesNow){
+			discreetAlert( "Sorry, another new tree block or tree file is currently being filled.  You must wait for that to finish before asking for another new tree block.");
+			return null;
+		}
+		Taxa taxa=null;
+		MesquiteFile file=null;
+
+		if (getProject().getNumberTaxas()==1) 
+			taxa = getProject().getTaxa(0);
+		else {
+			ListableVector taxas = getProject().getTaxas();
+			taxa = (Taxa)ListDialog.queryList(containerOfModule(), "Select taxa", "Select taxa (for new trees block)",MesquiteString.helpString, taxas, 0);
+		}
+
+		doCommand("setTreeSource", arguments, checker);  
+
+		if (treeFillerTask==null)  
+			return null;
+		file = chooseFile( taxa);
+		if (taxa==null || file == null)
+			return null;
+
+		treeFillerTaxaAssignedID = getProject().getTaxaReferenceExternal(taxa);   //don't use the treeFillerTaxaAssignedID of themodule
+		TreeVector trees = new TreeVector(taxa);
+		if (trees == null)
+			return null;
+		int howManyTrees = 0;
+		if (!treeFillerTask.hasLimitedTrees(trees.getTaxa())){
+			if (treeFillerTask instanceof TreeSource)
+				howManyTrees =((TreeSource)treeFillerTask).getNumberOfTrees(trees.getTaxa());
+			if (!MesquiteInteger.isCombinable(howManyTrees))
+				howManyTrees = MesquiteInteger.queryInteger(containerOfModule(), "How many trees?", "How many trees?", 100, 1, 100000000);
+			if (!MesquiteInteger.isCombinable(howManyTrees)) {
+				return null;
+			}
+		}
+		int separateThread = 0;
+		MesquiteBoolean autoSave = new MesquiteBoolean(false);
+		if (!MesquiteThread.isScripting() && treeFillerTask.permitSeparateThreadWhenFilling())
+			separateThread= separateThreadQuery(taskName, autoSave, isInference);
+		if (separateThread==1) {   // separate
+			fillingTreesNow = true;
+			TreeBlockThread tLT = new TreeBlockThread(this, treeFillerTask, trees, howManyTrees, autoSave, file);
+			fillerThreads.addElement(tLT); //Defunct: note!  already multiple threads remembered!
+			tLT.suppressAsk = suppressAsk;
+			tLT.start();
+		}
+		else if (separateThread == 0) {// same thread
+			long s = System.currentTimeMillis();
+			int before = trees.size();
+			treeFillerTask.fillTreeBlock(trees, howManyTrees);
+			if (trees.size()==before) {
+				alert("Sorry, no trees were returned by " + treeFillerTask.getName());
+				return null;
+			}
+			if (trees.getName()==null || "Untitled".equalsIgnoreCase(trees.getName()))
+				trees.setName("Trees from " + treeFillerTask.getName());
+			trees.addToFile(file, getProject(), this);
+
+			doneQuery(treeFillerTask, taxa, trees, suppressAsk);
+			if (!showTreeFiller){
+				fireTreeFiller();
+			}
+			if (autoSave != null && autoSave.getValue()){
+				FileCoordinator fCoord = getFileCoordinator();
+				fCoord.writeFile(file);
+			}
+			resetAllMenuBars();
+		}
+		return null;
+	}
+	/*-----------------------------------------------------------------*/
+	Object saveDirectTreeFileCoord(String commandName, String arguments, CommandChecker checker, boolean suppressAsk){
+		//arguments that should be accepted: (1) tree source, (2) which taxa, (3)  file id, (4) name of tree block, (5) how many trees  [number of taxa block] [identification number of file in which the tree block should be stored] [name of tree block] [how many trees to make]
+		Taxa taxa=null;
+
+		if (getProject().getNumberTaxas()==1) 
+			taxa = getProject().getTaxa(0);
+		else {
+			ListableVector taxas = getProject().getTaxas();
+			taxa = (Taxa)ListDialog.queryList(containerOfModule(), "Select taxa", "Select taxa (for new trees block)",MesquiteString.helpString, taxas, 0);
+		}
+		if (taxa==null)
+			return null;
+		TreeSource treeSourceTask =  null;
+		if (arguments == null)
+			treeSourceTask = (TreeSource)hireEmployee(TreeSource.class, "Source of Trees for File");
+		else
+			treeSourceTask =  (TreeSource)hireNamedEmployee(TreeSource.class, arguments, null);
+
+		if (treeSourceTask==null)
+			return null;
+		treeSourceTask.setUseMenubar(false);
+
+		int howManyTrees = 0;
+		if (!treeSourceTask.hasLimitedTrees(taxa)){
+			if (treeSourceTask instanceof TreeSource)
+				howManyTrees =((TreeSource)treeSourceTask).getNumberOfTrees(taxa);
+			if (!MesquiteInteger.isCombinable(howManyTrees))
+				howManyTrees = MesquiteInteger.queryInteger(containerOfModule(), "How many trees?", "How many trees?", 100, 1, 100000000);
+			if (!MesquiteInteger.isCombinable(howManyTrees)) {
+				return null;
+			}
+		}
+		else
+			howManyTrees = treeSourceTask.getNumberOfTrees(taxa);
+		int separateThread = 0; 
+		if (!MesquiteThread.isScripting() && treeSourceTask.permitSeparateThreadWhenFilling())
+			separateThread= AlertDialog.query(containerOfModule(), "Separate Thread?", "Save tree file on separate thread? (Beware! If you use a separate thread, be careful not to reorder, delete, add or rename taxa while this calculation is in progress)","No", "Separate", "Cancel", 0, null);
+		MainThread.incrementSuppressWaitWindow();
+		MesquiteFileDialog fdlg= new MesquiteFileDialog(MesquiteTrunk.mesquiteTrunk.containerOfModule(), "File in which to Save Trees", FileDialog.SAVE);   // Save File dialog box
+		fdlg.setVisible(true);
+		String tempFileName=fdlg.getFile();
+		String tempDirectoryName=fdlg.getDirectory();
+		MainThread.decrementSuppressWaitWindow();
+		MesquiteFile file = MesquiteFile.newFile(tempDirectoryName, tempFileName);
+		if (separateThread==1) {   // separate
+			DirectTreeFileThread tLT = new DirectTreeFileThread(this, treeSourceTask, taxa, howManyTrees, file);
+			fillerThreads.addElement(tLT);
+			tLT.suppressAsk = suppressAsk;
+			tLT.start();
+		}
+		else if (separateThread == 0) {// same thread
+			if (!saveDirectTreeFile(treeSourceTask, taxa, howManyTrees, file))
+
+				alert("Sorry, no trees were returned by " + treeSourceTask.getName());
+			return null;
+		}
+
+		return null;
+	}	
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("separateThreadFill".equalsIgnoreCase(tag))
+			separateThreadFill.setValue(MesquiteBoolean.fromTrueFalseString(content));
+
+		if ("autoSaveInference".equalsIgnoreCase(tag))
+			autoSaveInference.setValue(MesquiteBoolean.fromTrueFalseString(content));
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "separateThreadFill", separateThreadFill);  
+		StringUtil.appendXMLTag(buffer, 2, "autoSaveInference", autoSaveInference);  
+		return buffer.toString();
+	}
+	int separateThreadQuery(String taskName, MesquiteBoolean autoSave, boolean isInference){
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		String title = "Separate Thread?";
+		if (isInference)
+			title = "Separate Thread & Auto-Save?";
+		ExtensibleDialog id = new ExtensibleDialog(containerOfModule(), title,buttonPressed);
+		id.addLabel (taskName + " on separate thread?", Label.LEFT, true, false);
+		id.addLargeTextLabel("Beware! If you use a separate thread, be careful not to reorder, delete, add or rename taxa while this calculation is in progress");
+		String s = "This dialog box establishes basic running options for this calculation. ";
+		s += "<h3>" + StringUtil.protectForXML("Separate Thread?") + "</h3>Mesquite can do multi-tasking (i.e., do multiple things at once) by placing different tasks on different computational \"threads\".";
+		s += " There is one main thread that controls the user interface. You can place the calculation you are about to do on this thread, ";
+		s += " or you can place it on a separate thread.  If you place it on the main thread you will not have control over the user interface, ";
+		s += " and you thus cannot interact fully with Mesquite.  If you place it on a separate thread, you will be able to interact fully with Mesquite.";
+		s += " The danger in placing it on a separate thread is that you might (while the calculations are proceeding) change your taxa in such a way";
+		s += " that the taxa in your file will differ from those used in the running calculation and there will be an unrecoverable conflict. ";
+		s += " Thus, placing the calculation on a separate thread is more convenient, put has potential risks if you are not careful. ";
+		s += "<h3>" + StringUtil.protectForXML("Auto-save?") + "</h3>If you choose the option to auto-save,  Mesquite will save your file as soon as the calculation completes.";
+		s += " This is of benefit should you be worried that something might happen (e.g., unexpected computer shutdown) before you have a chance to manually save the file.";
+		id.appendToHelpString(s);
+		int choice = 0;
+		if (separateThreadFill.getValue())
+			choice = 1;
+		RadioButtons radio = id.addRadioButtons (new String[]{"NOT separate thread", "Separate Thread"}, choice);
+		id.addBlankLine();
+		if (isInference){
+			id.addBlankLine();
+			id.addLabel ("Save file automatically after trees are finished?", Label.LEFT, true, false);
+			choice = 0;
+			if (!autoSaveInference.getValue())
+				choice = 1;
+			RadioButtons radio2 = id.addRadioButtons (new String[]{"Auto-Save", "Don't Save"}, choice);
+
+
+			id.addBlankLine();
+			id.completeAndShowDialog("OK", null, null, "OK");
+			id.dispose();
+			if (autoSave != null){
+				autoSave.setValue(radio2.getValue() == 0);
+				autoSaveInference.setValue(autoSave.getValue());
+			}
+		}
+		else {
+			id.completeAndShowDialog("OK", null, null, "OK");
+			id.dispose();
+		}
+		separateThreadFill.setValue(radio.getValue() == 1);   
+		storePreferences();
+		return radio.getValue();
+	}
+	/*.................................................................................................................*/
+	boolean saveDirectTreeFile(TreeSource treeSourceTask, Taxa taxa, int howManyTrees, MesquiteFile file){
+		String endLine = ";" + StringUtil.lineEnding();
+		MainThread.incrementSuppressWaitWindow();
+		ProgressIndicator progIndicator = null;
+		boolean done = false;
+		int treesWritten = 0;
+		for (int i=0; i< howManyTrees && !done; i++){
+			Tree t = treeSourceTask.getTree(taxa, i);
+			if (i == 0) {
+				if (t == null){
+					fireEmployee(treeSourceTask);
+					resetAllMenuBars();
+					return false;
+				}
+				else {
+					//=== Preparation, done only once first tree successfully found
+					progIndicator = new ProgressIndicator(getProject(),getName(), "Saving trees", howManyTrees, true);
+					if (progIndicator!=null){
+						progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+						progIndicator.setOfferContinueMessageString("Are you sure you want to stop the tree saving?");
+						progIndicator.start();
+					}
+
+					file.openWriting(true);
+					file.write("#NEXUS");
+					Date d = new Date(System.currentTimeMillis());
+					String s = "";
+					String loc = "";
+					try {
+						loc = " at " + java.net.InetAddress.getLocalHost();
+					}
+					catch (java.net.UnknownHostException e){
+					}
+					if (!MesquiteModule.author.hasDefaultSettings())
+						loc += " (" + author.getName() + ")";
+					file.writeLine("[written " + d.toString() + " by Mesquite " + s + " version " + getMesquiteVersion()  + getBuildVersion() + loc + "]"); 
+					file.write("BEGIN TREES");
+					file.write(endLine);
+					if (taxa!=null && (getProject().getNumberTaxas()>1 || !NexusBlock.suppressLINK)) {
+						file.write("\tLINK Taxa = " + StringUtil.tokenize(taxa.getName()));
+						file.write(endLine);
+					}
+					file.write("[! Trees from source: " + StringUtil.tokenize(treeSourceTask.getNameAndParameters()) + "]");
+					file.write(StringUtil.lineEnding());
+					file.write("\tTRANSLATE" + StringUtil.lineEnding());
+					String tt = "";
+					if (taxa!=null)
+						for(int k=0; k<taxa.getNumTaxa(); k++) {
+							if (k>0)
+								tt += ","+ StringUtil.lineEnding();
+							tt += "\t\t" + Taxon.toExternal(k) + "\t" + StringUtil.tokenize(taxa.getTaxonName(k)) ;
+						}
+					file.write( tt);
+					file.write(endLine);
+					//======== end Preparation
+				}
+			}
+			else if (t == null)
+				done = true;
+			if (file == null)
+				return false;
+			if (t != null){
+				file.write("\tTREE ");
+				if (t instanceof MesquiteTree && !StringUtil.blank(((MesquiteTree)t).getAnnotation())) {
+					String s = ((MesquiteTree)t).getAnnotation();
+					s= StringUtil.replace(s, '\n', ' ');
+					s=StringUtil.replace(s, '\r', ' ');
+					file.write(" [!" + s + "] ");
+				}
+
+				file.write(StringUtil.tokenize(t.getName() )+ " = " +  t.writeTree(Tree.BY_NUMBERS) + StringUtil.lineEnding());
+				treesWritten++;
+			}
+			if (progIndicator != null) {
+				if (progIndicator.isAborted()) {
+					progIndicator.goAway();
+					done = true;
+				}
+				progIndicator.setText("Saved: tree " + (i+1) +  " of " + MesquiteInteger.toString(howManyTrees));
+				progIndicator.setCurrentValue(i);
+			}
+
+		}
+		if (file == null)
+			return false;
+		if (progIndicator != null)
+			progIndicator.goAway();
+		file.write("END;" + StringUtil.lineEnding()+ StringUtil.lineEnding());
+		file.closeWriting();
+		fireEmployee(treeSourceTask);
+		discreetAlert( "Tree file saving is complete.  " + treesWritten + " trees written.");
+		MainThread.decrementSuppressWaitWindow();
+
+		resetAllMenuBars();
+		return true;
+	}
+	/*.................................................................................................................*/
+	MesquiteFile chooseFile( Taxa taxa){
+		if (getProject().getNumberLinkedFiles()==1 || taxa == null)
+			return getProject().getHomeFile();
+		else if (MesquiteThread.isScripting())
+			return taxa.getFile();
+		else {
+			Listable[] files = getProject().getFiles().getElementArray();
+			if (files.length >1) {
+				int count = 0;
+				boolean taxaFound = false;
+				for (int i=0; i<files.length; i++) {
+					if (!taxaFound && files[i] == taxa.getFile())
+						taxaFound = true;
+					if (taxaFound)
+						count++;
+				}
+				if (count!=files.length){
+					Listable[] legalFiles = new Listable[count];
+					count = 0;
+					taxaFound = false;
+					for (int i=0; i<files.length; i++) {
+						if (!taxaFound && files[i] == taxa.getFile())
+							taxaFound = true;
+
+						if (taxaFound) {
+							legalFiles[count] = files[i];
+							count++;
+						}
+					}
+					files = legalFiles;
+				}
+
+			}
+			if (files.length == 1)
+				return (MesquiteFile)files[0];
+			return (MesquiteFile)ListDialog.queryList(containerOfModule(), "Select file", "Select file to which to add the new block of trees",MesquiteString.helpString, files, 0);
+		}
+	}
+	/*.................................................................................................................*/
+
+	void doneQuery(TreeBlockFiller fillTask, Taxa taxa, TreeVector trees, boolean suppressAsk){
+		MesquiteModule fCoord = getFileCoordinator();
+		MesquiteModule treeWindowCoord = null;
+		if (fCoord!=null)
+			treeWindowCoord = fCoord.findEmployeeWithName("Tree Window Coordinator");
+		if (treeWindowCoord==null && fCoord!=null)
+			treeWindowCoord = fCoord.findEmployeeWithName("#BasicTreeWindowCoord");
+
+		if (treeWindowCoord==null){
+			discreetAlert(MesquiteThread.isScripting(), "The trees are now ready [" + fillTask.getNameAndParameters() + "].");
+		}
+		else if (!MesquiteThread.isScripting() && (suppressAsk || AlertDialog.query(containerOfModule(), "Trees ready", "The trees are now ready [" + fillTask.getName() + "; name of tree block: \"" + trees.getName()+ "\"].  Would you like to open a tree window to display them?", "Yes", "No"))){
+			//send script to tree window coord to makeTreeWindow with set of taxa and then set to stored trees and this tree vector
+			int whichTreeBlock = getTreeBlockNumber(taxa, trees);
+			String extraWindowCommands = fillTask.getExtraTreeWindowCommands();
+			if (StringUtil.blank(extraWindowCommands))
+				extraWindowCommands="";
+			String commands = "makeTreeWindow " + getProject().getTaxaReferenceInternal(taxa) + "  #BasicTreeWindowMaker; tell It; setTreeSource  #StoredTrees;";
+			commands += " tell It; setTaxa " + getProject().getTaxaReferenceInternal(taxa) + " ;  setTreeBlock " + TreeVector.toExternal(whichTreeBlock)  + "; endTell;  getWindow; tell It; setSize 400 300; " + extraWindowCommands + " endTell; showWindowForce; endTell; ";
+			MesquiteInteger pos = new MesquiteInteger(0);
+			Puppeteer p = new Puppeteer(this);
+			CommandRecord prev = MesquiteThread.getCurrentCommandRecord();
+			CommandRecord cRec = new CommandRecord(true);
+			MesquiteThread.setCurrentCommandRecord(cRec);
+			p.execute(treeWindowCoord, commands, pos, null, false, null, null);
+			MesquiteThread.setCurrentCommandRecord(prev);
+
+
+		}
+	}
+	/*.................................................................................................................*/
+	public TreeVector getTreeVectorByID(int id){  //OK for doomed
+		for (int j = 0; j< treesVector.size(); j++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(j);
+			if (trees!= null && trees.getID() ==id)
+				return trees;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public ListableVector getTreeBlockVector(){
+		return treesVector;
+	}
+	/*.................................................................................................................*/
+	public TreeVector getTreeBlock(Taxa taxa, int i){  //OK for doomed
+		if (treesVector==null)
+			return null;
+		int count = 0;
+		for (int j = 0; j< treesVector.size(); j++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(j);
+			if ((taxa == null || taxa.equals(trees.getTaxa(), false)) && !trees.isDoomed()) { 
+				if (count==i)
+					return trees;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public TreeVector getTreeBlockByID(long id){  //this uses the temporary run-time id of the tree vector
+		if (treesVector==null)
+			return null;
+		for (int j = 0; j< treesVector.size(); j++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(j);
+			if (trees.getID() == id)
+				return trees;
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public TreeVector getTreeBlock(Taxa taxa, MesquiteFile file, int i){  //OK for doomed
+		if (treesVector==null)
+			return null;
+		int count = 0;
+		for (int j = 0; j< treesVector.size(); j++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(j);
+			if ((file==null || trees.getFile()==file) && !trees.isDoomed()  && (taxa == null || taxa.equals(trees.getTaxa(), false))){
+				if (count==i)
+					return trees;
+				count++;
+			}
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public int getTreeBlockNumber(Taxa taxa, TreeVector trees){ //OK for doomed
+		int count = 0;
+		for (int j = 0; j< treesVector.size(); j++) {
+			TreeVector t = (TreeVector)treesVector.elementAt(j);
+			if ((taxa == null || taxa.equals(t.getTaxa(), false)) && !t.isDoomed()) { 
+				if (t == trees)
+					return count;
+				count++;
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	public int getTreeBlockNumber(TreeVector trees){//OK for doomed
+			return getTreeBlockNumber(null, trees);
+	}
+	/*.................................................................................................................*/
+	public int getNumberTreeBlocks(Taxa taxa){ //OK for doomed
+		if (treesVector == null)
+			return 0;
+		int count = 0;
+		for (int i = 0; i< treesVector.size(); i++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(i);
+			if (!trees.isDoomed() && (taxa == null || taxa.equals(trees.getTaxa(), false)))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int getNumberTreeBlocks(Taxa taxa, MesquiteFile file){ //OK for doomed
+		if (treesVector == null)
+			return 0;
+		int count = 0;
+		for (int i = 0; i< treesVector.size(); i++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(i);
+			if ((file==null || trees.getFile()==file) && !trees.isDoomed() && (taxa == null || taxa.equals(trees.getTaxa(), false)))
+				count++;
+		}
+		return count;
+	}
+	/*.................................................................................................................*/
+	public int getNumberTreeBlocks(){ //OK for doomed
+		if (treesVector == null)
+			return 0;
+		int count = 0;
+		for (int i = 0; i< treesVector.size(); i++) {
+			TreeVector trees = (TreeVector)treesVector.elementAt(i);
+			if (!trees.isDoomed())
+				count++;
+		}
+	return count;
+	}
+	/*.................................................................................................................*/
+	public TreeVector makeNewTreeBlock(Taxa taxa, String name, MesquiteFile f){
+		return makeNewTreeBlock(taxa, name, false, f);
+	}
+	/*.................................................................................................................*/
+	public TreeVector makeNewTreeBlock(Taxa taxa, String name, boolean writeWeights, MesquiteFile f){
+		TreeVector trees = new TreeVector(taxa);
+		trees.setName(name);
+		trees.addToFile(f, getProject(), this); 
+		trees.setWriteWeights(writeWeights);
+		return trees;
+	}
+	/*.................................................................................................................*/
+	public NexusBlock elementAdded(FileElement trees){
+		if (trees ==null || !(trees instanceof TreeVector))
+			return null;
+		if (treesVector.indexOf(trees) <0) {
+			treesVector.addElement(trees, true);
+			for (int i=0; i<blockListeners.size(); i++){
+				MesquiteListener ml = (MesquiteListener)blockListeners.elementAt(i);
+				trees.addListener(ml);
+				ml.changed(this, trees, new Notification(MesquiteListener.ELEMENT_CHANGED));
+			}
+
+			resetAllMenuBars();
+		}
+		NexusBlock nb = findNEXUSBlock(trees);
+		if (nb==null) {
+			TreeBlock t = new TreeBlock(trees.getFile(), this);
+			t.setTreeBlock((TreeVector)trees);
+			addNEXUSBlock(t);
+
+			return t;
+		}
+		else return nb;
+	}
+	/*.................................................................................................................*/
+	public void elementDisposed(FileElement e){
+		if (e==null || !(e instanceof TreeVector))
+			return;
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object ma=getEmployeeVector().elementAt(i);
+			if (ma instanceof ManagerAssistant)
+				if (((ManagerAssistant)ma).showing(e)) {
+					fireEmployee((ManagerAssistant)ma);
+				}
+		}
+		NexusBlock nb = findNEXUSBlock(e);
+		if (nb!=null) {
+			removeNEXUSBlock(nb);
+		}
+		if (treesVector.indexOf(e)>=0){
+			while(treesVector.indexOf(e)>=0) {
+				treesVector.removeElement(e, true);
+			}
+		}
+		else
+			resetAllMenuBars();
+	}
+	/*.................................................................................................................*/
+	public Taxa findTaxaMatchingTable(TreeVector trees, MesquiteProject proj, MesquiteFile file, Vector table) {
+		ListableVector candidates = new ListableVector();
+		for (int itx=0; itx< proj.getNumberTaxas(file); itx++) { //first check in this file
+			Taxa tempTaxa = proj.getTaxa(file, itx);
+			if (trees.tableMatchesTaxa(tempTaxa, table)) {
+				candidates.addElement(tempTaxa, false);
+			}
+		}
+		for (int itx=0; itx< proj.getNumberTaxas(); itx++) {//then in project as a whole
+			Taxa tempTaxa = proj.getTaxa(itx);
+			if (candidates.indexOf(tempTaxa)<0 && trees.tableMatchesTaxa(tempTaxa, table)) {
+				candidates.addElement(tempTaxa, false);
+			}
+		}
+		if (candidates.size() == 0)
+			return null;
+		if (candidates.size() == 1)
+			return (Taxa)candidates.elementAt(0);
+		Listable result = ListDialog.queryList(containerOfModule(), "Choose taxa block", "There is a tree block (" + trees.getName() + ") that does not specify the taxa block to which it pertains." + 
+				" There is more than one taxa block with which it would be compatible.  Please choose its taxa block.", 
+				"", candidates, 0);
+
+		if (result == null)
+			return (Taxa)candidates.elementAt(0);
+
+		return (Taxa)result;
+	}
+	/*.................................................................................................................*/
+	public NexusBlockTest getNexusBlockTest(){ return new TreeBlockTest();}
+
+	/*.................................................................................................................*/
+	public NexusBlock readNexusBlock(MesquiteFile file, String name, FileBlock block, StringBuffer blockComments, String fileReadingArguments){
+		boolean fuse = parser.hasFileReadingArgument(file.fileReadingArguments, "fuseTaxaCharBlocks");
+		boolean fuseTreeBlocks = false;
+		int firstTree = 0;
+		int lastTree = MesquiteInteger.infinite;
+		int everyNth = 1;
+		String fRA = parser.getFirstToken(fileReadingArguments);
+		while (!StringUtil.blank(fRA)) {
+			if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + "fuseTreeBlocks"))
+				fuseTreeBlocks = true;
+			else if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + "firstTree")) {
+				fRA = parser.getNextToken();  // =
+				fRA = parser.getNextToken();
+				firstTree = MesquiteInteger.fromString(fRA);
+			}
+			else if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + "lastTree")) {
+				fRA = parser.getNextToken();  // =
+				fRA = parser.getNextToken();
+				lastTree = MesquiteInteger.fromString(fRA);
+			}
+			else if (fRA.equalsIgnoreCase(StringUtil.argumentMarker + "everyNth")) {
+				fRA = parser.getNextToken();  // =
+				fRA = parser.getNextToken();
+				everyNth = MesquiteInteger.fromString(fRA);
+			}
+			fRA = parser.getNextToken();
+		}
+		Parser commandParser = new Parser();
+
+		MesquiteInteger cPos = new MesquiteInteger(0);
+		MesquiteString comment = new MesquiteString();
+		String s;
+		int treeNum=-1;
+		boolean treeRead = false;
+		Taxa taxa=null;
+		if (file.getProject().getNumberTaxas()==1)
+			taxa = file.getProject().getTaxa(0); //as default)
+
+		TreeVector trees = new TreeVector( taxa);
+		trees.setTaxa(taxa);
+		if (getNumberTreeBlocks(taxa)>1)
+			trees.setName("Tree block " + (getNumberTreeBlocks(taxa)+1) + " from \"" + file.getName() + "\"");
+		else
+			trees.setName("Trees from \"" + file.getName() + "\"");
+		boolean nameSet = false;
+		boolean translationTableRead = false;
+		NexusBlock t =trees.addToFile(file, getProject(), this);
+		while (!StringUtil.blank(s=block.getNextFileCommand(comment))) {
+			String punc = ",";
+			String commandName = parser.getFirstToken(s);
+			if (commandName.equalsIgnoreCase("BEGIN") || commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK")) {
+			}
+			//todo: here, allow figuring of taxa by first tree string and taxon names
+			else if (commandName.equalsIgnoreCase("TRANSLATE")) {
+				translationTableRead = true;
+				Vector table = null;
+				if (taxa == null)
+					table = new Vector();
+				String label =  parser.getNextToken();
+				while (punc !=null && !punc.equalsIgnoreCase(";")) {
+					String taxonName = parser.getNextToken();
+					if (file.useStandardizedTaxonNames){
+						if (taxa == null)
+							taxa = file.getCurrentTaxa();
+						if (taxa == null)
+							taxa = getProject().getTaxa(0);
+						String numS = taxonName.substring(1, taxonName.length());
+						int it = MesquiteInteger.fromString(numS);
+						if (MesquiteInteger.isCombinable(it))
+							taxonName = taxa.getTaxonName(it);
+					}
+					if (taxa==null) 
+						table.addElement(StringUtil.tokenize(taxonName) + " " + StringUtil.tokenize(label));
+					else
+						trees.setTranslationLabel(label, taxonName, false);
+					punc =  parser.getNextToken(); 
+					if (punc !=null && !punc.equals(";")) {
+						label =  parser.getNextToken();
+						if (";".equalsIgnoreCase(label))
+							punc = label;  //to pop out of loop
+					}
+				}
+
+
+				if (taxa==null) {
+					int tI = parser.tokenIndexOfIgnoreCase(fileReadingArguments, "taxa");//DRM added this 8 April 2012 so that one can specify which taxa block it should belong to
+					if (tI>=0){
+						String ref = parser.getTokenNumber(fileReadingArguments, tI+2);
+						taxa = getProject().getTaxa(ref);
+					}
+
+					if (taxa==null) 
+						taxa = findTaxaMatchingTable(trees, getProject(), file, table);
+					if (taxa!=null) {
+						trees.setTaxa(taxa);
+						trees.setTranslationTable(table);
+					}
+					else if (table.size()>0) {
+						taxa = new Taxa(table.size());
+						taxa.setName(getProject().getTaxas().getUniqueName("Untitled Block of Taxa"));
+						taxa.addToFile(file, getProject(), findElementManager(Taxa.class));
+						MesquiteInteger ppos = new MesquiteInteger();
+						for (int it=0; it<taxa.getNumTaxa(); it++) {
+							String taxonName = ParseUtil.getFirstToken((String)table.elementAt(it), ppos);
+							taxa.setTaxonName(it,taxonName);
+						}
+						trees.setTaxa(taxa);
+						trees.setTranslationTable(table);
+						String st = "A block of trees has been read for which no corresponding block of taxa is available;  a new block of taxa has been created for it.";
+						st += "  If you had expected that the trees would have applied to an existing block of taxa, it is possible that the taxa no longer correspond because of changes in names or in which taxa are included.";
+						discreetAlert( st);
+					}
+
+				}
+				else {
+					if (table!=null)
+						trees.setTranslationTable(table);
+				}
+				trees.checkTranslationTable();
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				trees.setName(parser.getTokenNumber(2));
+				nameSet = true;
+			}
+			else if (commandName.equalsIgnoreCase("LINK")) {
+				if ("taxa".equalsIgnoreCase(parser.getTokenNumber(2))) {
+					String taxaTitle = parser.getTokenNumber(4);
+					taxa = getProject().getTaxa(file, taxaTitle);
+					if (taxa == null)
+						taxa = getProject().getTaxaLastFirst(taxaTitle);
+					if (taxa == null) {
+						if (getProject().getNumberTaxas(file)==1) //if translation table should search for match
+							taxa = getProject().getTaxa(file, 0);
+						else if (getProject().getNumberTaxas(file)==0 && getProject().getNumberTaxas()==1) //if translation table should search for match
+							taxa = getProject().getTaxa(0);
+						else
+							discreetAlert( "LINK command in TREES block refers to taxa block, but taxa block not found");
+					}
+					trees.setTaxa(taxa);
+					if (!nameSet)
+						trees.setName("Trees block " + (getNumberTreeBlocks(taxa)+1) + " from " + file.getName());
+				}
+			}
+			else { //if (taxa !=null || getProject().getNumberTaxas()>1) {
+				int whichType = 0;
+				if (commandName.equalsIgnoreCase("TREE")) 
+					whichType = 1;
+				else if (commandName.equalsIgnoreCase("UTREE")) 
+					whichType =2;
+				else if (commandName.equalsIgnoreCase("RTREE")) 
+					whichType = 1;
+
+				if (whichType > 0 && (!fuse || translationTableRead || (taxa!= null && taxa.getFile() == file))) {
+					//if (fuseTaxaCharBlocks && !translationTableRead)
+					treeNum++;
+					if (treeNum >= firstTree && (!MesquiteInteger.isCombinable(lastTree) || treeNum<=lastTree) && (!MesquiteInteger.isCombinable(everyNth) || everyNth == 1 || (treeNum-firstTree) % everyNth == 0)) {
+						boolean permitTaxaBlockEnlargement = false;
+						if (taxa == null) { 
+							TaxaManager taxaTask = (TaxaManager)findElementManager(Taxa.class);
+							taxa = taxaTask.makeNewTaxa("Taxa", 0, false);
+							taxa.addToFile(file, getProject(), taxaTask);
+							trees.setTaxa(taxa);
+							permitTaxaBlockEnlargement = true;
+							/*String st = "A block of trees has been read for which the corresponding block of taxa is not identified.  If you would like to attempt to read the block of trees as belonging to one of these taxa blocks, select the taxa.";
+							st+= "  Command: " + s;
+							taxa = getProject().chooseTaxa(containerOfModule(), st);
+							if (taxa == null) {
+								trees.dispose();
+								return null;
+							}
+							else
+								trees.setTaxa(taxa);
+							 */
+						}
+						if (!translationTableRead && file.useStandardizedTaxonNames){
+							for (int it = 0; it<taxa.getNumTaxa(); it++)
+								trees.setTranslationLabel(Integer.toString(it+1), "t" + it, false);
+							trees.checkTranslationTable();
+						}
+						String treeDescription;
+						String treeName;
+						treeName=parser.getNextToken();
+
+						if (treeName.equals("*"))
+							treeName=parser.getNextToken();
+						parser.getNextToken(); //eat up "equals"
+						treeDescription=s.substring(parser.getPosition(), s.length());
+
+						MesquiteTree thisTree =new MesquiteTree(taxa);
+						thisTree.setPermitTaxaBlockEnlargement(permitTaxaBlockEnlargement);
+						String commentString = comment.getValue();
+
+						if (commentString!=null && commentString.length()>1){
+							if (commentString.charAt(0)=='!')
+								thisTree.setAnnotation(commentString.substring(1, commentString.length()), false);
+							else {
+								int wpos = commentString.indexOf("&W");
+								if (wpos <0)
+									wpos = commentString.indexOf("&w");
+								if (wpos>=0) {
+									cPos.setValue(wpos+2);
+									String num = ParseUtil.getToken(commentString, cPos);
+									String slash = ParseUtil.getToken(commentString, cPos);
+									String denom = ParseUtil.getToken(commentString, cPos);
+									double w = 0;
+									if (slash !=null && "/".equals(slash))
+										w = 1.0*(MesquiteInteger.fromString(num))/(MesquiteInteger.fromString(denom));
+									else
+										w = MesquiteDouble.fromString(num);
+									if (MesquiteDouble.isCombinable(w)) {
+										MesquiteDouble d = new MesquiteDouble(w);
+										d.setName(WEIGHT);
+										thisTree.attachIfUniqueName(d);
+									}
+								}
+							}
+						}
+						thisTree.setTreeVector(trees);
+						trees.addElement(thisTree, false);
+						treeRead = true;
+						thisTree.readTree(treeDescription);
+						//thisTree.warnRetIfNeeded();
+						thisTree.setName(treeName);
+						if (whichType ==2) 
+							thisTree.setRooted(false, false);
+						if (treeNum>1 && treeNum % 100 == 0) 
+							logln("   " + Integer.toString(treeNum) + " trees read ");
+
+						if (treeNum>1 && treeNum % 1000 == 0) {
+							Runtime rt = Runtime.getRuntime();
+							rt.gc();
+						}
+					}	
+				}
+				else
+					readUnrecognizedCommand(file, t, name, block, commandName, s, blockComments, comment);
+			}
+			/*else { 
+				String st = "A block of trees has been read for which no corresponding block of taxa has been found, and no block of taxa could be created for it.";
+				st += "  If you had expected that the trees would have applied to an existing block of taxa, it is possible that the taxa no longer correspond because of changes in names or in which taxa are included.";
+
+				alert(st);
+				trees.dispose();
+				return null;
+			}*/
+		}
+		if (treeRead){
+			//assigning informative name if none or untitled
+			if (trees!=null && (StringUtil.blank(trees.getName())|| "UNTITLED".equalsIgnoreCase(trees.getName()))) {
+				trees.setName(treesVector.getUniqueName("Untitled Tree Block"));
+			}
+			if (trees != null && blockComments!=null && blockComments.length()>0)
+				trees.setAnnotation(blockComments.toString(), false);
+			if (getProject() != null)
+				getProject().refreshProjectWindow();
+			return t;
+		}
+		if (trees !=null)
+			trees.dispose();
+		discreetAlert( "No trees were read from the tree block.");
+		getProject().refreshProjectWindow();
+		return null;
+	}
+
+
+	public String getTreeBlock(TreeVector trees, NexusBlock tB){
+		if (trees == null || trees.size()==0)
+			return null;
+		String endLine = ";" + StringUtil.lineEnding();
+		StringBuffer block = new StringBuffer(5000);
+		Taxa taxa = trees.getTaxa();
+		block.append("BEGIN TREES");
+		if (trees.getAnnotation()!=null) 
+			block.append("[!" + StringUtil.tokenize(trees.getAnnotation()) + "]");
+		block.append(endLine);
+		if (!NexusBlock.suppressTITLE){
+			block.append("\tTitle " + StringUtil.tokenize(trees.getName()));
+			block.append(endLine);
+		}
+		if (taxa!=null && (getProject().getNumberTaxas()>1 || !NexusBlock.suppressLINK)) {
+			block.append("\tLINK Taxa = " + StringUtil.tokenize(taxa.getName()));
+			block.append(endLine);
+		}
+		block.append("\tTRANSLATE" + StringUtil.lineEnding());
+		String tt =trees.getTranslationTable();
+		int writeMode = Tree.BY_TABLE;
+		if (tt==null) {
+			tt = "";
+			if (taxa!=null)
+				for(int i=0; i<taxa.getNumTaxa(); i++) {
+					if (i>0)
+						tt += ","+ StringUtil.lineEnding();
+					tt += "\t\t" + Taxon.toExternal(i) + "\t" + StringUtil.tokenize(taxa.getTaxonName(i)) ;
+				}
+			writeMode = Tree.BY_NUMBERS;
+		}
+		block.append( tt);
+		block.append(endLine);
+
+		Enumeration e = trees.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			Tree t = (Tree)obj;
+
+			block.append("\tTREE ");
+			if (t instanceof MesquiteTree && !StringUtil.blank(((MesquiteTree)t).getAnnotation())) {
+				String s = ((MesquiteTree)t).getAnnotation();
+				s= StringUtil.replace(s, '\n', ' ');
+				s=StringUtil.replace(s, '\r', ' ');
+				block.append(" [!" + s + "] ");
+			}
+
+			Object weightObject = ((Attachable)t).getAttachment(WEIGHT);
+			if(trees.getWriteWeights()&& weightObject!=null && weightObject instanceof MesquiteString){
+				block.append(StringUtil.tokenize(t.getName()) + " = [&W " + ((MesquiteString)weightObject).getValue() + "] " + t.writeTree(writeMode) + StringUtil.lineEnding());
+			}
+			else {
+				String ttt = t.writeTree(Tree.BY_TABLE);
+				block.append(StringUtil.tokenize(t.getName() )+ " = " +  t.writeTree(writeMode) + StringUtil.lineEnding());
+			}
+
+		}
+		if (tB != null) block.append(tB.getUnrecognizedCommands() + StringUtil.lineEnding());
+		block.append("END");
+
+		block.append(";" + StringUtil.lineEnding()+ StringUtil.lineEnding());
+		return block.toString();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Manage TREES blocks"; //Name must be updated in Basic File Coord
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Tree Manager";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Manages tree blocks (including read/write TREES block in NEXUS file)." ;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+}
+/* ======================================================================== */
+abstract class FillerThread extends MesquiteThread {
+	ManageTrees ownerModule;
+	public FillerThread (ManageTrees ownerModule) {
+		super();
+		this.ownerModule = ownerModule;
+	}
+	public void threadGoodbye(){
+		ownerModule.fillerThreads.removeElement(this);
+		super.threadGoodbye();
+	}
+	public abstract void stopFilling();
+}
+
+/* ======================================================================== */
+class DirectTreeFileThread extends FillerThread {
+	TreeSource treeSourceTask;
+	Taxa taxa;
+	MesquiteFile file;
+	int howManyTrees;
+	boolean suppressAsk = false;
+
+	public DirectTreeFileThread (ManageTrees ownerModule, TreeSource treeSourceTask, Taxa taxa, int howManyTrees, MesquiteFile file) {
+		super(ownerModule);
+		this.treeSourceTask = treeSourceTask;
+		this.howManyTrees = howManyTrees;
+		this.taxa = taxa;
+		this.file = file;
+		setCurrent(1);
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		boolean sc;
+		if (cr == null)
+			sc = false;
+		else
+			sc = cr.recordIsScripting();
+		setCommandRecord(new CommandRecord(sc));
+	}
+
+	public String getCurrentCommandName(){
+		return "Making trees";
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	/*.............................................*/
+	public void run() {
+		long s = System.currentTimeMillis();
+		try {
+			ownerModule.saveDirectTreeFile(treeSourceTask, taxa, howManyTrees, file);
+		}
+		catch (Exception e){
+			MesquiteFile.throwableToLog(this, e);
+			ownerModule.alert("Sorry, there was a problem in making the tree block.  An Exception was thrown (class " + e.getClass() +"). For more details see Mesquite log file.");
+		}
+		catch (Error e){
+			MesquiteFile.throwableToLog(this, e);
+			ownerModule.alert("Sorry, there was a problem in making the tree block.  An Error was thrown (class " + e.getClass() +"). For more details see Mesquite log file.");
+			throw e;
+		}
+		threadGoodbye();
+	}
+	public void stopFilling(){
+
+	}
+	/*.............................................*/
+	public void dispose(){
+		ownerModule = null;
+		treeSourceTask=null;
+		taxa = null;
+		file = null;
+	}
+
+}
+/* ======================================================================== */
+class TreeBlockThread extends FillerThread {
+	TreeBlockFiller fillTask;
+	TreeVector trees;
+	MesquiteFile file;
+	int howManyTrees;
+	boolean suppressAsk = false;
+	CommandRecord comRec = null;
+	MesquiteBoolean autoSave = null;
+	boolean aborted = false;
+	public TreeBlockThread (ManageTrees ownerModule, TreeBlockFiller fillTask, TreeVector trees, int howManyTrees, MesquiteBoolean autoSave, MesquiteFile file) {
+		super(ownerModule);
+		this.fillTask = fillTask;
+		this.trees = trees;
+		this.howManyTrees = howManyTrees;
+		this.file = file;
+		this.autoSave = autoSave;
+		setCurrent(1);
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		boolean sc;
+		if (cr == null)
+			sc = false;
+		else
+			sc = cr.recordIsScripting();
+		comRec = new CommandRecord(sc);
+		setCommandRecord(comRec);
+
+	}
+
+	public String getCurrentCommandName(){
+		return "Making trees";
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	/*.............................................*/
+	public void run() {
+		long s = System.currentTimeMillis();
+		int before = trees.size();
+		try {
+			fillTask.fillTreeBlock(trees, howManyTrees);
+
+			boolean okToSave = false;
+			if (!ownerModule.isDoomed()){
+				if (!aborted){
+					if (trees.size()==before) {
+						ownerModule.alert("Sorry, no trees were returned by " + fillTask.getName());
+						ownerModule.fireTreeFiller();
+
+					}
+					else {
+						trees.addToFile(file, ownerModule.getProject(), ownerModule);
+						okToSave = true;
+					}
+					if (trees.size()!=before)
+						ownerModule.doneQuery(fillTask, trees.getTaxa(), trees, suppressAsk);
+				}
+				ownerModule.fireTreeFiller();
+				if (okToSave && autoSave != null && autoSave.getValue()){
+					FileCoordinator fCoord = ownerModule.getFileCoordinator();
+					fCoord.writeFile(file);
+				}
+			}
+			ownerModule.resetAllMenuBars();
+		}
+		catch (Exception e){
+			MesquiteFile.throwableToLog(this, e);
+			ownerModule.alert("Sorry, there was a problem in making the tree block.  An Exception was thrown (class " + e.getClass() +"). For more details see Mesquite log file.");
+		}
+		catch (Error e){
+			MesquiteFile.throwableToLog(this, e);
+			ownerModule.alert("Sorry, there was a problem in making the tree block.  An Error was thrown (class " + e.getClass() +"). For more details see Mesquite log file.");
+			throw e;
+		}
+		threadGoodbye();
+	}
+	public void stopFilling(){
+		if (fillTask != null)
+			fillTask.abortFilling();
+		aborted = true;
+	}
+	/*.............................................*/
+	public void dispose(){
+		ownerModule = null;
+		fillTask = null;
+		trees = null;
+		file = null;
+	}
+
+}
+/* ======================================================================== */
+class TreeBlockMonitorThread extends FillerThread {
+	TreeBlockFiller fillTask;
+	CommandRecord comRec = null;
+	boolean aborted = true;
+	String taxaIDString = null;
+
+	public TreeBlockMonitorThread (ManageTrees ownerModule, String taxaID, TreeBlockFiller fillTask) {
+		super(ownerModule);
+		this.fillTask = fillTask;
+		taxaIDString = taxaID;
+		setCurrent(1);
+		CommandRecord cr = MesquiteThread.getCurrentCommandRecord();
+		boolean sc;
+		if (cr == null)
+			sc = false;
+		else
+			sc = cr.recordIsScripting();
+		comRec = new CommandRecord(sc);
+		setCommandRecord(comRec);
+
+	}
+
+	public String getCurrentCommandName(){
+		return "Making trees";
+	}
+	public String getCurrentCommandExplanation(){
+		return null;
+	}
+	/*.............................................*/
+	public void run() {
+		Reconnectable reconnectable = fillTask.getReconnectable();
+		if (reconnectable != null){
+			reconnectable.reconnectToRequester(new MesquiteCommand("treesReady", taxaIDString, ownerModule));
+		}
+		threadGoodbye();
+
+	}
+	public void stopFilling(){
+		if (fillTask != null)
+			fillTask.abortFilling();
+		aborted = true;
+	}
+	/*.............................................*/
+	public void dispose(){
+		ownerModule = null;
+		fillTask = null;
+	}
+
+}/*===============================================*/
+class TreeBlock extends NexusBlock {
+	TreeVector trees = null;
+	public TreeBlock(MesquiteFile f, MesquiteModule mb){
+		super(f, mb);
+	}
+	public void written() {
+		trees.setDirty(false);
+	}
+	public boolean mustBeAfter(NexusBlock block){
+		if (block==null)
+			return false;
+		if (trees!=null && block instanceof TaxaBlock) {
+			return trees.getTaxa() == ((TaxaBlock)block).getTaxa();
+		}
+		return (block.getBlockName().equalsIgnoreCase("TAXA") || block.getBlockName().equalsIgnoreCase("CHARACTERS"));
+
+	}
+	public String getBlockName(){
+		return "TREES";
+	}
+	public boolean contains(FileElement e) {
+		return e!=null && trees == e;
+	}
+	public void setTreeBlock(TreeVector trees) {
+		this.trees = trees;
+	}
+	public TreeVector getTreeBlock() {
+		return trees;
+	}
+	public String getName(){
+		if (trees==null)
+			return "empty tree block";
+		else
+			return "Tree block: " + trees.getName();
+	}
+	public String getNEXUSBlock(){
+		if (trees==null)
+			return null;
+		else
+			return ((ManageTrees)getManager()).getTreeBlock(trees, this);
+	}
+}
+
+/* ======================================================================== */
+class TreeBlockTest extends NexusBlockTest  {
+	public TreeBlockTest () {
+	}
+	public  boolean readsWritesBlock(String blockName, FileBlock block){ //returns whether or not can deal with block
+		return blockName.equalsIgnoreCase("TREES");
+	}
+}
+
+
diff --git a/Source/mesquite/trees/ManyTreesFromFile/ManyTreesFromFile.java b/Source/mesquite/trees/ManyTreesFromFile/ManyTreesFromFile.java
new file mode 100644
index 0000000..3a96643
--- /dev/null
+++ b/Source/mesquite/trees/ManyTreesFromFile/ManyTreesFromFile.java
@@ -0,0 +1,49 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ManyTreesFromFile;
+/*~~  */
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.ManyTreesFromFileLib;
+
+
+public class ManyTreesFromFile extends ManyTreesFromFileLib {
+
+	
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Use Trees from Separate NEXUS File";
+	 }
+/*.................................................................................................................*/
+	 public String getNameForMenuItem() {
+	return "Use Trees from Separate NEXUS File...";
+	 }
+	 
+		/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies trees directly from a file, without bringing the contained tree block entirely into memory.  " + 
+		"This is a special purpose module designed to allow much larger blocks of trees to be used within constraints of memory, but will make some calculations slower.  " + 
+		"Except for this special use, we recommend you use Include or Link from the file menu to access external tree files.  " + 
+		"This module does NOT copy the trees into your main data file, and so if you save your main data file then move it or the tree file, the data file will no longer be able to find the trees.  " + 
+		"This module does not know how many trees are in the file, and hence may attempt to read files beyond the number in the file.";
+   	 }
+
+}
+
+
+
diff --git a/Source/mesquite/trees/MirrorTreeWindowMaker/MirrorTreeWindowMaker.java b/Source/mesquite/trees/MirrorTreeWindowMaker/MirrorTreeWindowMaker.java
new file mode 100644
index 0000000..99f6627
--- /dev/null
+++ b/Source/mesquite/trees/MirrorTreeWindowMaker/MirrorTreeWindowMaker.java
@@ -0,0 +1,557 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.MirrorTreeWindowMaker;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MirrorTreeWindowMaker extends TreeWindowAssistantN implements TreeDisplayActive {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DrawTreeCoordinator.class, getName() + "  needs a module to coordinate tree drawing.",
+		"This is arranged automatically");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeDisplayAssistantA.class, getName() + "  uses modules to add analyses and graphics to a tree graphic.",
+		"Supplementary analyses and graphics are available in the Left Side and Right Side submenus.");
+		
+	}
+	/*.................................................................................................................*/
+	public DrawTreeCoordinator treeDrawCoordTask;
+	MirrorTreeWindow mirrorTreeWindow;
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(DrawTreeCoordinator.class, null);
+		if (treeDrawCoordTask == null)
+			return sorry(getName() + " couldn't start because no tree draw coordinating module obtained.");
+ 		makeMenu("Mirror");
+ 		return true;
+  	 }
+  	 
+  	 public void employeeQuit(MesquiteModule m){
+  	 	if (m == treeDrawCoordTask)
+  	 		iQuit();
+  	 }
+	/*.................................................................................................................*/
+ 	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (source instanceof DrawTreeCoordinator){ //ignores since this should have directly called to update tree display
+			return;
+		}
+		if (mirrorTreeWindow != null)
+			mirrorTreeWindow.refresh();
+		super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	 public boolean isPrerelease(){
+	 	return false;
+	 }
+	 
+	/*.................................................................................................................*/
+	/** Query module as to whether conditions are such that it will have to quit soon -- e.g. if its taxa block has been doomed.  The tree window, data window, 
+	etc. override this to return true if their object is doomed. This is useful in case MesquiteListener disposing method is not called for an employer before one of its
+	employees discovers that it needs to quit.  If the employer is going to quit anyway,there is no use to use auto rehire for the quit employee.*/
+	public boolean quittingConditions(){
+		return (mirrorTreeWindow.taxa.isDoomed());
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (mirrorTreeWindow==null){
+	 		mirrorTreeWindow= new MirrorTreeWindow( this, treeDrawCoordTask, tree.getTaxa());
+	 		setModuleWindow(mirrorTreeWindow);
+	 		if (!MesquiteThread.isScripting())
+	 			mirrorTreeWindow.setVisible(true);
+	 		resetContainingMenuBar();
+	 		employer.resetContainingMenuBar();
+			resetAllWindowsMenus();
+	 		mirrorTreeWindow.sizeDisplays();
+		}
+		mirrorTreeWindow.setTree(tree);
+	}
+	/*.................................................................................................................*/
+ 	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+  	 	if (mirrorTreeWindow ==null)
+  	 		return null;
+  	 	Snapshot fromWindow = mirrorTreeWindow.getSnapshot(file);
+  	 	if (fromWindow == null || fromWindow.getNumLines() ==0)
+  	 		return null;
+   	 	Snapshot sn = new Snapshot();
+		sn.addLine("getWindow");
+		sn.addLine("tell It");
+		sn.incorporate(fromWindow, true);
+		sn.addLine("endTell");
+		sn.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
+    	 	sn.addLine("showWindow");
+		
+  	 	return sn;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Returns the tree draw coordinating module", null, commandName, "getTreeDrawCoordinator")) {
+    	 		return treeDrawCoordTask;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		}		   
+	/*.................................................................................................................*/
+   	 public boolean mouseDownInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+   		if (!treeDisplay.getTree().isLocked())
+   			return mirrorTreeWindow.ScanTouch(treeDisplay, g, x, y, modifiers);
+   		 return false;
+   	 }
+
+	/*.................................................................................................................*/
+   	 public boolean mouseUpInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+   		 return true;
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 public boolean mouseMoveInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+   		if (!treeDisplay.getTree().isLocked())
+   			mirrorTreeWindow.ScanFlash(treeDisplay, g, x, y, modifiers);
+   		 return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean mouseDragInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+   		 return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Mirror Tree Window";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Displays a single tree (the same as in a tree window) twice, in mirror image." ;
+   	 }
+   	 
+   	 
+}
+	
+/* ======================================================================== */
+class MirrorTreeWindow extends MesquiteWindow implements Commandable  {
+	public TreeDisplay[] treeDisplays;
+	public DrawTreeCoordinator treeDrawCoordTask;
+	int totalWidth;
+	int totalHeight;
+	int firstTree=0;
+	public MessagePanel messagePanel;
+	Taxa taxa;
+	MirrorExtra extra;
+	public int highlightedBranch=0;
+	String defaultExplanation;
+	
+	public MirrorTreeWindow ( MirrorTreeWindowMaker ownerModule, DrawTreeCoordinator treeDrawCoordTask, Taxa taxa){
+		super(ownerModule, true); //infobar
+  		this.treeDrawCoordTask = treeDrawCoordTask;
+      		setWindowSize(500,400);
+		setShowExplanation(true);
+		defaultExplanation = "This window shows the same tree as seen in ";
+		MesquiteWindow eW = ownerModule.getEmployer().getModuleWindow();
+		if (eW !=null)
+			defaultExplanation += eW.getTitle();
+		else
+			defaultExplanation += "a Tree Window";
+		setExplanation(defaultExplanation);
+		this.ownerModule = ownerModule;
+		//setLayout( null );
+		setBackground(Color.white);
+		messagePanel=new MessagePanel(getColorScheme());
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+		this.taxa = taxa; //taxa = ownerModule.getProject().getTaxa(0); //reset in setTree if not correct taxa block
+		ownerModule.addSubmenu(null, "Left Side", MesquiteModule.makeCommand("newAssistantLeft",  this), TreeDisplayAssistantA.class);
+		ownerModule.addSubmenu(null, "Right Side", MesquiteModule.makeCommand("newAssistantRight",  this), TreeDisplayAssistantA.class);
+		treeDisplays =treeDrawCoordTask.createTreeDisplays(2, taxa, this);
+		addToWindow(treeDisplays[0]);
+		treeDisplays[0].setOrientation(TreeDisplay.RIGHT);
+		treeDisplays[0].setAllowReorientation(false);
+		treeDisplays[0].setTipsMargin(40);
+		treeDisplays[0].setTaxonNameBuffer(8); ///8
+		treeDisplays[0].setTaxonNameDistance(14); ///absent
+		treeDisplays[1].setOrientation(TreeDisplay.LEFT);
+		treeDisplays[1].setAllowReorientation(false);
+		treeDisplays[1].suppressNames = true;
+		treeDisplays[1].setTipsMargin(18); //14
+		treeDisplays[1].setTaxonNameBuffer(20); //absent
+		treeDisplays[1].setTaxonNameDistance(14); ///absent
+		extra = new MirrorExtra(ownerModule, treeDisplays[0], this);
+		treeDisplays[0].addExtra(extra);
+		treeDisplays[0].centerNames = true;
+		//treeDisplays[1].setBackground(Color.cyan);
+		//treeDisplays[0].setBackground(Color.yellow);
+		addToWindow(treeDisplays[1]);
+		sizeDisplays();
+		addAssistantsDI(ownerModule);
+		resetTitle();
+	}
+	protected void addAssistantsDI(MesquiteModule ownerModule){
+		ownerModule.hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration e = ownerModule.getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistant tda = (TreeDisplayAssistant)obj;
+				treeDrawCoordTask.addAssistantTask(tda);
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplays[0]);
+				if (tce!=null) 
+					treeDisplays[0].addExtra(tce);
+				TreeDisplayExtra tce2 = tda.createTreeDisplayExtra(treeDisplays[1]);
+				if (tce2!=null) 
+					treeDisplays[1].addExtra(tce2);
+	 		}
+		}
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Mirror Tree"); 
+	}
+	/*.................................................................................................................*/
+  	 public int getNumSnapshotLines(MesquiteFile file) {
+  	 	int tot = 0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+			Object e=ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof TreeDisplayAssistantA) {
+				tot++;
+			}
+		}
+  	 	return tot;
+  	 }
+  	 public void setWindowSize(int w, int h){
+  		 super.setWindowSize(w, h);
+ 		//sizeDisplays();
+  	 }
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.incorporate(super.getSnapshot(file), false);
+		ListableVector extrasLeft = treeDisplays[0].getExtras();
+		if (extrasLeft!=null) {
+			Enumeration enumeration=extrasLeft.elements();
+			while (enumeration.hasMoreElements()){
+				TreeDisplayExtra tde = (TreeDisplayExtra)enumeration.nextElement();
+				MesquiteModule mb = tde.getOwnerModule();
+				if (mb instanceof TreeDisplayAssistantA) {
+					temp.addLine("newAssistantLeft", mb);
+				}
+			}
+		}
+		
+		ListableVector extrasRight = treeDisplays[1].getExtras();
+		if (extrasRight!=null) {
+			Enumeration enumeration=extrasRight.elements();
+			while (enumeration.hasMoreElements()){
+				TreeDisplayExtra tde = (TreeDisplayExtra)enumeration.nextElement();
+				MesquiteModule mb = tde.getOwnerModule();
+				if (mb instanceof TreeDisplayAssistantA) {
+					temp.addLine("newAssistantRight", mb);
+				}
+			}
+		}
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Hires a new tree display assistant (A) for the left-hand tree", "[name of module]", commandName, "newAssistantLeft")) {
+    	 		TreeDisplayAssistantA tda= (TreeDisplayAssistantA)ownerModule.hireNamedEmployee(TreeDisplayAssistantA.class, arguments);
+			if (tda!=null){
+				treeDrawCoordTask.addAssistantTask(tda);
+				
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplays[0]);
+				tce.setTree(treeDisplays[0].getTree());
+				treeDisplays[0].addExtra(tce);
+				treeDisplays[0].repaint();
+				return tda;
+			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Hires a new tree display assistant (A) for the right-hand tree", "[name of module]", commandName, "newAssistantRight")) {
+    	 		TreeDisplayAssistantA tda= (TreeDisplayAssistantA)ownerModule.hireNamedEmployee(TreeDisplayAssistantA.class, arguments);
+			if (tda!=null){
+				treeDrawCoordTask.addAssistantTask(tda);
+				
+				TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplays[1]);
+				tce.setTree(treeDisplays[1].getTree());
+				treeDisplays[1].addExtra(tce);
+				treeDisplays[1].repaint();
+				return tda;
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+    	 	return null;
+    	 }
+    	public void refresh(){
+		treeDisplays[0].pleaseUpdate(true);
+		treeDisplays[1].pleaseUpdate(true);
+    	}
+	/*.................................................................................................................*/
+	public void sizeDisplays(){
+		totalWidth = getWidth();
+		totalHeight = getHeight() - 16;
+		if (treeDisplays == null || treeDisplays.length ==0)
+			return;
+		int leftTreeEdge = totalWidth/2 + treeDisplays[0].getTipsMargin()/2 -  treeDisplays[1].getTipsMargin()/2;
+		treeDisplays[0].setLocation(0,0);
+		treeDisplays[0].setSize(leftTreeEdge,totalHeight);
+		treeDisplays[0].setFieldSize(leftTreeEdge,totalHeight);
+		treeDisplays[1].setLocation(leftTreeEdge, 0);
+		treeDisplays[1].setSize( totalWidth  - leftTreeEdge,totalHeight);
+		treeDisplays[1].setFieldSize(totalWidth  - leftTreeEdge,totalHeight);
+		resetDisplay(treeDisplays[0]);
+		resetDisplay(treeDisplays[1]);
+		messagePanel.setSize(totalWidth, 16);
+		messagePanel.setLocation(0, totalHeight);
+	}
+	void resetDisplay(TreeDisplay treeDisplay){
+		treeDisplay.setVisRect(new Rectangle(0, 0, treeDisplay.getWidth(), treeDisplay.getHeight()));
+		Component[] cc = treeDisplay.getComponents();
+		if (cc!=null && cc.length>0)
+			for (int i=0; i<cc.length; i++) {
+				if (cc[i] instanceof Legend){ //make sure legends are in bounds
+					//adjustLocation
+					Legend legend = (Legend)cc[i];
+				
+						legend.setConstrainingRectangle(treeDisplay.getBounds()); //treeDisplay.getBounds()
+				
+					legend.adjustLocation();
+				}
+			}
+	}
+	/*.................................................................................................................*/
+	public void setTree(Tree newTree){
+		if (treeDisplays[0].getTree()!=null)
+			treeDisplays[0].getTree().dispose();
+		if (treeDisplays[1].getTree()!=null)
+			treeDisplays[1].getTree().dispose();
+		Tree tree;
+		if (newTree!=null) {
+
+			/*if (newTree.getTaxa() != taxa) {
+				taxa = newTree.getTaxa();
+				treeDisplays[0].setTaxa(taxa);
+				treeDisplays[1].setTaxa(taxa);
+			}*/
+			tree = newTree.cloneTree();
+			treeDisplays[0].setTree(tree);
+			treeDisplays[1].setTree(tree);
+			treeDisplays[0].suppressDrawing(false);
+			treeDisplays[0].setVisible(true);
+			treeDisplays[0].repaint();
+			treeDisplays[0].setTreeAllExtras(tree);
+			treeDisplays[1].suppressDrawing(false);
+			treeDisplays[1].setVisible(true);
+			treeDisplays[1].repaint();
+			treeDisplays[1].setTreeAllExtras(tree);
+			MesquiteModule employer = ownerModule.getEmployer();
+			if (employer instanceof TreeWindowMaker && employer.getModuleWindow()!=null)
+				messagePanel.setMessage(tree.getName() + " in " + employer.getModuleWindow().getName());
+			else
+				messagePanel.setMessage(tree.getName());  
+		}
+		else messagePanel.setMessage("Error: source tree is null");  
+		messagePanel.repaint();
+	}
+	/*_________________________________________________*/
+	
+	public   void InvertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	   }
+	   
+	/*_________________________________________________*/
+	public   void RevertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	   }
+	/*_________________________________________________*/
+	
+	public   void HighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().highlightBranch(treeDisplay.getTree(), N, g);
+	   }
+	   
+	/*_________________________________________________*/
+	public   void UnhighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().unhighlightBranch(treeDisplay.getTree(), N, g);
+	   }
+	/*_________________________________________________*/
+	public   void ScanFlash(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot(); //TODO: remember drawnRoot!!!
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble fraction = new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, fraction);
+		if (highlightedBranch != 0) {
+			if (branchFound==0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+			else if (branchFound!=highlightedBranch)  {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch); 
+				notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+				HighlightBranch(treeDisplay, g, branchFound);
+			}
+		}
+		else if (branchFound!=0) {
+			notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+			HighlightBranch(treeDisplay, g, branchFound); 
+		}
+
+	}
+	/*_________________________________________________*/
+	public   boolean ScanTouch(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return false;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble fraction= new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, fraction);
+	        if (branchFound!=0) {
+			if (highlightedBranch != 0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+	   		notifyExtrasOfBranchTouch(treeDisplay, g, branchFound);
+	   		return true;
+       		}
+ 		return false;
+	   }
+	/*................................................................................................*/
+	private void notifyExtrasOfBranchTouch(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+		 			tce.cursorTouchBranch(treeDisplay.getTree(), N, g);
+		 		}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchEnter(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+		 			tce.cursorEnterBranch(treeDisplay.getTree(), N, g);
+		 		}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchExit(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+		 			tce.cursorExitBranch(treeDisplay.getTree(), N, g);
+		 		}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	 public void paintContents(Graphics g) {
+		if (treeDisplays==null){
+			MesquiteMessage.warnProgrammer("Oh no, tree displays are null");
+		}
+      		else {
+			sizeDisplays();
+		}
+		
+	}
+		/*.................................................................................................................*/
+		/**
+		* @author Peter Midford
+		*/
+		public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+			try{
+				// These windows don't currently support text mode, so no need to check infoBar (which doesn't seem to be around.
+			if (pdfFile != null) {
+				Graphics g = pdfFile.getPDFGraphicsForComponent(this.getOuterContentsArea(),null);
+				if (g == null || treeDisplays == null || treeDisplays[0] == null || treeDisplays[1]==null)
+					return;
+				sizeDisplays();
+				treeDisplays[0].print(g);
+				g.translate((int)treeDisplays[1].getLocation().getX(),(int)treeDisplays[1].getLocation().getY());
+				treeDisplays[1].print(g);
+				pdfFile.end();
+			}
+			}
+			catch (NullPointerException e){  //seems to be an issue...
+			}
+		}
+		/**
+		* @author Peter Midford
+		*/
+		public String getPrintToPDFMenuItemName() {
+			return "Save Mirror Tree Window as PDF...";
+		}
+	public void dispose(){
+		for (int itree=0; itree<2; itree++) {
+				if (treeDisplays[itree]!=null){
+					if (treeDisplays[itree].getTree()!=null)
+						treeDisplays[itree].getTree().dispose();
+					treeDisplays[itree].dispose();
+				}
+		}
+		super.dispose();
+	}
+}
+
+/* ======================================================================== */
+class MirrorExtra extends TreeDisplayExtra {
+	MirrorTreeWindow treeWindow;
+	public MirrorExtra (MesquiteModule ownerModule, TreeDisplay treeDisplay, MirrorTreeWindow treeWindow) {
+		super(ownerModule, treeDisplay);
+		this.treeWindow = treeWindow;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		treeWindow.sizeDisplays();
+	}
+	public   void setTree(Tree tree) {
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+	}
+}
+
+
diff --git a/Source/mesquite/trees/MultiTreeWindowMaker/MultiTreeWindowMaker.java b/Source/mesquite/trees/MultiTreeWindowMaker/MultiTreeWindowMaker.java
new file mode 100644
index 0000000..feaffc1
--- /dev/null
+++ b/Source/mesquite/trees/MultiTreeWindowMaker/MultiTreeWindowMaker.java
@@ -0,0 +1,630 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.MultiTreeWindowMaker;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class MultiTreeWindowMaker extends FileAssistantT {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(DrawTreeCoordinator.class, getName() + "  needs a module to coordinate tree drawing.",
+				"This is arranged automatically");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of trees.",
+				"The source of trees can be selected initially or in the Tree Source submenu");
+	}
+	/*.................................................................................................................*/
+	public DrawTreeCoordinator treeDrawCoordTask;
+	public TreeSourceDefinite treeSourceTask;
+	MultiTreeWindow multiTreeWindow;
+	MesquiteString treeSourceName;
+	Taxa taxa;
+	MesquiteBoolean namesVisible;
+	int numColumns = 3;
+	int numRows = 2;
+	MesquiteCommand tstC;
+	MesquiteBoolean legendBotRight = new MesquiteBoolean(false);
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		taxa = getProject().chooseTaxa(containerOfModule(), "For which block of taxa do you want to show a Multi-tree window?");
+		treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(DrawTreeCoordinator.class, null);
+		if (treeDrawCoordTask == null)
+			return sorry(getName() + " couldn't start because no tree draw coordinating module obtained.");
+		makeMenu("Multi-Tree");
+		int numberOfTrees;
+		treeSourceTask = (TreeSourceDefinite) hireEmployee(TreeSourceDefinite.class, "Source of Trees (Multi Tree Window)");
+		if (treeSourceTask == null) {
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		} else {
+			numberOfTrees = treeSourceTask.getNumberOfTrees(taxa);
+		}
+		addMenuItem( "Number of Columns...", makeCommand("setNumColumns",  this));
+		addMenuItem( "Number of Rows...", makeCommand("setNumRows",  this));
+		addCheckMenuItem( null,"Legend on Bottom Right", makeCommand("toggleLegendBotRight",  this), legendBotRight);
+
+		namesVisible = new MesquiteBoolean(true);
+		addCheckMenuItem(null, "Show Names", MesquiteModule.makeCommand("setNamesVisible",  this), namesVisible);
+		if (!MesquiteThread.isScripting()) {
+			if (taxa==null)
+				return sorry(getName() + " couldn't start because no block of taxa found.");
+			multiTreeWindow= new MultiTreeWindow( this, treeSourceTask, treeDrawCoordTask);
+			setModuleWindow(multiTreeWindow);
+			multiTreeWindow.setVisible(true);
+			resetContainingMenuBar();
+			resetAllWindowsMenus();
+		}
+		return true;
+	}
+
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == treeDrawCoordTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	/** passes which object is being disposed (from MesquiteListener interface)*/
+	public void disposing(Object obj){
+		if (obj instanceof Taxa && (Taxa)obj == taxa) {
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	/** Query module as to whether conditions are such that it will have to quit soon -- e.g. if its taxa block has been doomed.  The tree window, data window, 
+	etc. override this to return true if their object is doomed. This is useful in case MesquiteListener disposing method is not called for an employer before one of its
+	employees discovers that it needs to quit.  If the employer is going to quit anyway,there is no use to use auto rehire for the quit employee.*/
+	public boolean quittingConditions(){
+		return (taxa.isDoomed());
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee!=treeDrawCoordTask)
+			if ((multiTreeWindow!=null) ) 
+				multiTreeWindow.renew();
+			else if ((multiTreeWindow!=null)  && Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED) {
+				multiTreeWindow.contentsChanged();
+				multiTreeWindow.renew();
+			}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (multiTreeWindow ==null)
+			return null;
+		Snapshot fromWindow = multiTreeWindow.getSnapshot(file);
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(taxa));
+		temp.addLine("setNumColumns " + multiTreeWindow.getNumColumns());
+		temp.addLine("setNumRows " + multiTreeWindow.getNumRows());
+		temp.addLine("getTreeSource",treeSourceTask);
+		temp.addLine("makeWindow");
+		temp.addLine("toggleLegendBotRight " + legendBotRight.toOffOnString());
+		temp.addLine("setNamesVisible " + namesVisible.toOffOnString());
+		temp.addLine("getWindow");
+		temp.addLine("tell It");
+		temp.incorporate(fromWindow, true);
+		temp.addLine("endTell");
+		temp.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
+		temp.addLine("showWindow");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public boolean getLegendBotRight() {
+		return legendBotRight.getValue();
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the taxa block", "[block reference, number, or name]", commandName, "setTaxa")){
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				taxa = t;
+				return taxa;
+			}
+		} 
+
+		else if (checker.compare(this.getClass(), "Toggles whether the legends are shown on the bottom right or top left", null, commandName, "toggleLegendBotRight")) {
+			boolean current = legendBotRight.getValue();
+			pos.setValue(0);
+			legendBotRight.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (current != legendBotRight.getValue())
+				multiTreeWindow.setLegendPosition(legendBotRight.getValue());
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether the taxon names are visible", "[on or off]", commandName, "setNamesVisible")) {
+			namesVisible.toggleValue(parser.getFirstToken(arguments));
+			if (multiTreeWindow!=null)
+				multiTreeWindow.sizeDisplays(false);
+		}
+
+		else if (checker.compare(this.getClass(), "Sets the number of columns", "[number of columns]", commandName, "setNumColumns")) {
+			int newColumns = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newColumns))
+				newColumns= MesquiteInteger.queryInteger(containerOfModule(), "Set number of columns", "Columns:", numColumns);
+			if (newColumns>0 && newColumns<16) {
+				if (multiTreeWindow!=null)
+					if (newColumns!=multiTreeWindow.numColumns)
+						multiTreeWindow.setNumColumns(newColumns);
+
+				numColumns = newColumns;
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the number of rows", "[number of rows]", commandName, "setNumRows")) {
+			int newRows =MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newRows))
+				newRows= MesquiteInteger.queryInteger(containerOfModule(), "Set number of rows", "Rows:", numRows);
+			if (newRows>0 && newRows<16){
+				if (multiTreeWindow!=null)
+					if (newRows!=multiTreeWindow.numRows)
+						multiTreeWindow.setNumRows(newRows);
+				numRows = newRows;
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Makes but doesn't show the window", null, commandName, "makeWindow")) {
+			if (getModuleWindow()==null) {
+				multiTreeWindow= new MultiTreeWindow( this, treeSourceTask, treeDrawCoordTask);
+				setModuleWindow(multiTreeWindow);
+				resetContainingMenuBar();
+				resetAllWindowsMenus();
+			}
+			return multiTreeWindow;
+		}
+		else if (checker.compare(this.getClass(), "Shows the multi tree window", null, commandName, "showWindow")) {
+			if (multiTreeWindow!=null)
+				multiTreeWindow.setVisible(true);
+			return multiTreeWindow;
+		}
+		else if (checker.compare(this.getClass(), "To warn user that this command is no longer viable.", null, commandName, "setTreeSource")) {
+			MesquiteMessage.discreetNotifyUser("The file was saved with an older version of MultiTreeWindow.  For this reason, the tree source specified in the file could not be read.")  ;
+		}    	
+		else if (checker.compare(this.getClass(), "Returns treeSourceTask", null, commandName, "getTreeSource")) {
+			return treeSourceTask;
+		} else if (checker.compare(this.getClass(), "Returns the tree draw coordinating module", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Multi Tree Window";
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		whichWindow.dispose();
+		iQuit();
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Displays a special tree window with many trees simultaneously." ;
+	}
+}
+
+/* ======================================================================== */
+class MultiTreeWindow extends MesquiteWindow implements Commandable  {
+	public TreeDisplay[] treeDisplays;
+	public DrawTreeCoordinator treeDrawCoordTask;
+	TreeSourceDefinite treeSourceTask;
+	MultiTreeWindowMaker MTWmodule;
+	Taxa taxa;
+	MTWScroll treeScroll;
+	public int numColumns = 3;
+	public int numRows = 2;
+	int totalWidth;
+	int totalHeight;
+	int firstTree=0;
+	int maxDisplays = 36;
+	MessagePanel messagePanel;
+	MesquitePanel containingPanel;
+	MesquiteTimer timer;
+	TreeVector trees;
+
+
+	public MultiTreeWindow (MultiTreeWindowMaker ownerModule, TreeSourceDefinite treeSourceTask,   DrawTreeCoordinator treeDrawCoordTask){
+		super(ownerModule, true); //infobar
+		setWindowSize(500,400);
+		MTWmodule=ownerModule;
+		this.treeDrawCoordTask = treeDrawCoordTask;
+		taxa = ownerModule.taxa;
+		if (taxa==null) {
+			taxa = ownerModule.getProject().chooseTaxa(this, "For which block of taxa do you want to show a Multi-tree window?");
+		}
+		trees = new TreeVector(taxa);
+		numColumns = MTWmodule.numColumns;
+		numRows = MTWmodule.numRows;
+		setBackground(Color.white);
+
+		messagePanel=new MessagePanel(getColorScheme());
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+		MesquiteMenuSpec aux = ownerModule.addAuxiliaryMenu("Analysis:Trees");
+		ownerModule.addModuleMenuItems(aux, MesquiteModule.makeCommand("newAssistant",  this), TreeDisplayAssistantMA.class);
+		treeScroll = new MTWScroll(this, 0, 2, 0, treeSourceTask.getNumberOfTrees(taxa)/numColumns + 1); //-1
+		addToWindow(treeScroll);
+		treeDisplays =treeDrawCoordTask.createTreeDisplays(maxDisplays,taxa, this);
+		setTreeSource(treeSourceTask);
+
+
+		containingPanel = new MesquitePanel();
+		addToWindow(containingPanel);
+		for (int itree = 0; itree<maxDisplays; itree++) {
+			containingPanel.add(treeDisplays[itree]);
+		}
+
+		/*
+		for (int itree = 0; itree<maxDisplays; itree++) {
+			addToWindow(treeDisplays[itree]);
+		}
+		 */
+
+		treeScroll.setVisible(true);
+		sizeDisplays(false);
+		addAssistantsDI(ownerModule);
+		resetTitle();
+	}
+	protected void addAssistantsDI(MesquiteModule ownerModule){
+		ownerModule.hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration e = ownerModule.getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistant tda = (TreeDisplayAssistant)obj;
+				treeDrawCoordTask.addAssistantTask(tda);
+				for (int i=0; i<maxDisplays; i++){
+					TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplays[i]);
+					if (tce!=null) 
+						treeDisplays[i].addExtra(tce);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Trees"); 
+	}
+	/*.................................................................................................................*/
+	public void printWindow(MesquitePrintJob pjob) {
+		if (pjob != null) {
+			int mode;
+			if (infoBar==null)
+				mode =InfoBar.GRAPHICS;
+			else mode = infoBar.getMode();
+			if (mode==InfoBar.GRAPHICS) //graphical mode
+				pjob.printComponent(containingPanel, null, currentFont);
+			else 
+				super.printWindow(pjob);
+		}
+	}
+	/*.................................................................................................................*/
+	/**
+	 * @author Peter Midford
+	 */
+	public void windowToPDF(MesquitePDFFile pdfFile, int fitToPage) {
+		if (pdfFile != null) {
+			int mode;
+			if (infoBar==null)
+				mode =InfoBar.GRAPHICS;
+			else mode = infoBar.getMode();
+			if (mode==InfoBar.GRAPHICS) { //graphical mode
+				Graphics g = pdfFile.getPDFGraphicsForComponent(containingPanel,null);
+				for (int itree=0; itree<(numColumns*numRows); itree++) {
+					int xLoc = (int)treeDisplays[itree].getLocation().getX();
+					int yLoc = (int)treeDisplays[itree].getLocation().getY();
+					g.translate(xLoc,yLoc);
+					treeDisplays[itree].print(g);
+					g.translate(-xLoc,-yLoc);
+				}
+				pdfFile.end();
+			}			
+			else 
+				super.windowToPDF(pdfFile, fitToPage);
+		}
+	}
+	/**
+	 * @author Peter Midford
+	 */
+	public String getPrintToPDFMenuItemName() {
+		return "Save Multi Tree Window as PDF...";
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+			Object e=ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof TreeDisplayAssistantMA) {
+				temp.addLine("newAssistant " , ((MesquiteModule)e));
+			}
+		}
+		temp.incorporate(super.getSnapshot(file), false);
+		return temp;
+	}
+	public void setLegendPosition(boolean lowerRight){
+		if (treeDisplays==null)
+			return;
+		for (int p = 0; p<treeDisplays.length; p++) {
+			//cycle through all components getting those that are Legends 
+			Component[] cc = treeDisplays[p].getComponents();
+			if (cc!=null && cc.length>0)
+				for (int i=0; i<cc.length; i++) {
+					if (cc[i] instanceof Legend){
+						//use getOffsetX(); for current and 
+						//adjustLocation
+						Legend legend = (Legend)cc[i];
+						Rectangle rect  = legend.getBounds();
+						if (lowerRight) {
+							legend.setOffsetX(treeDisplays[p].getBounds().width - legend.getWidth()-4);
+							legend.setOffsetY(treeDisplays[p].getBounds().height - legend.getHeight() -8);
+						}
+						else {
+							legend.setOffsetX(4);
+							legend.setOffsetY(4);
+						}
+						legend.adjustLocation();
+					}
+				}
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires a tree display assistant (A)", "[name of module]", commandName, "newAssistant")) {
+			TreeDisplayAssistantMA tda= (TreeDisplayAssistantMA)ownerModule.hireNamedEmployee(TreeDisplayAssistantMA.class, arguments);
+			if (tda!=null){
+				treeDrawCoordTask.addAssistantTask(tda);
+
+				for (int itree=0; itree<(maxDisplays); itree++) {
+					TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplays[itree]);
+					tce.setTree(treeDisplays[itree].getTree());
+					treeDisplays[itree].addExtra(tce);
+					treeDisplays[itree].repaint();
+				}
+				contentsChanged();
+				renew();
+				return tda;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public void renew() {
+		if (treeScroll!=null && treeSourceTask!=null)
+			treeScroll.setMaximum(treeSourceTask.getNumberOfTrees(taxa)/numColumns + 1); //-1);
+		if (treeSourceTask!=null) {
+			if (ownerModule.getProject().getNumberTaxas()<=1)
+				messagePanel.setMessage("Trees from " + treeSourceTask.getNameAndParameters());
+			else
+				messagePanel.setMessage("Trees for taxa \"" + taxa.getName() + "\" from " + treeSourceTask.getNameAndParameters());
+		}
+		setFirstTree(0);
+		for (int itree=0; itree<(numColumns*numRows); itree++) {
+			treeDisplays[itree].repaint();
+		}
+	}
+	/*.................................................................................................................*/
+
+	public void setTreeSource(TreeSourceDefinite tsTask) {
+		treeSourceTask = tsTask;
+		tsTask.initialize(taxa);
+		treeScroll.setMaximum(treeSourceTask.getNumberOfTrees(taxa)/numColumns + 1); //-1);
+		if (treeSourceTask!=null) {
+			if (ownerModule.getProject().getNumberTaxas()<=1)
+				messagePanel.setMessage("Trees from " + treeSourceTask.getNameAndParameters());
+			else
+				messagePanel.setMessage("Trees for taxa \"" + taxa.getName() + "\" from " + treeSourceTask.getNameAndParameters());
+		}
+		setFirstTree(0);
+	}
+	public void setWindowSize(int width, int height){
+		super.setWindowSize(width,height);
+		sizeDisplays(false);
+	}
+	/*.................................................................................................................*/
+	public synchronized void sizeDisplays(boolean hide){
+		if (treeScroll == null || messagePanel == null || containingPanel == null)
+			return;
+		totalWidth = getWidth()-16;
+		totalHeight = getHeight() - 16;
+		treeScroll.setBounds(totalWidth, 0, 16, totalHeight);
+		containingPanel.setBounds(0,0,totalWidth, totalHeight);
+
+		for (int itree=0; itree<(numColumns*numRows); itree++) {
+			if (treeDisplays[itree] !=null){
+				treeDisplays[itree].setTipsMargin(0);
+				treeDisplays[itree].setTaxonNameBuffer(4);
+
+				treeDisplays[itree].setFrame(true);
+				treeDisplays[itree].suppressNames = !MTWmodule.namesVisible.getValue();
+				treeDisplays[itree].setFieldSize(totalWidth/numColumns,totalHeight/numRows);
+				treeDisplays[itree].setSize(totalWidth/numColumns,totalHeight/numRows);
+				treeDisplays[itree].setLocation(((itree) % numColumns)*totalWidth/numColumns, (itree / numColumns)*totalHeight/numRows);
+				if (hide) {
+					treeDisplays[itree].setVisible(false);
+				}
+				else
+					treeDisplays[itree].repaint();
+				if (treeDisplays[itree].getTreeDrawing()!=null)
+					treeDisplays[itree].getTreeDrawing().recalculatePositions(treeDisplays[itree].getTree()); //to force node locs recalc
+				resetDisplay(treeDisplays[itree]);
+				treeDisplays[itree].repaint(true);
+			}
+		}
+		messagePanel.setSize(totalWidth, 16);
+		messagePanel.setLocation(0, totalHeight);
+		messagePanel.repaint();
+	}
+	void resetDisplay(TreeDisplay treeDisplay){
+		treeDisplay.setVisRect(new Rectangle(0, 0, treeDisplay.getWidth(), treeDisplay.getHeight()));
+		Component[] cc = treeDisplay.getComponents();
+		if (cc!=null && cc.length>0)
+			for (int i=0; i<cc.length; i++) {
+				if (cc[i] instanceof Legend){ //make sure legends are in bounds
+					//adjustLocation
+					Legend legend = (Legend)cc[i];
+
+					legend.setConstrainingRectangle(treeDisplay.getBounds()); //treeDisplay.getBounds()
+
+					legend.adjustLocation();
+				}
+			}
+	}
+	/*.................................................................................................................*/
+	public void setFirstTree(int treeNum){
+		sizeDisplays(false);
+		firstTree = treeNum;
+		trees.removeAllElements(false);
+		for (int itree=0; itree<(maxDisplays); itree++) {
+			Tree sourceTree=null;
+			if (itree+treeNum <treeSourceTask.getNumberOfTrees(taxa))
+				sourceTree = treeSourceTask.getTree(taxa, itree+treeNum);
+			if (sourceTree!=null) {
+				if (treeDisplays[itree].getTree()!=null)
+					treeDisplays[itree].getTree().dispose();
+				Tree tree = sourceTree.cloneTree();
+				trees.addElement(tree, false); //for notification of taxa changes
+				treeDisplays[itree].setTree(tree);
+				treeDisplays[itree].setNotice(Integer.toString(itree+treeNum + 1)); // for debugging purposes???
+				treeDisplays[itree].suppressDrawing(false);
+				if (itree<numColumns*numRows) {
+					treeDisplays[itree].setVisible(true);
+					treeDisplays[itree].repaint();
+				}
+				treeDisplays[itree].setTreeAllExtras(tree);
+			}
+			else {
+				treeDisplays[itree].setVisible(false);
+			}
+		}
+
+		sizeDisplays(false);
+	}
+	/*.................................................................................................................*/
+	public void setNumColumns(int newNum){
+		if (newNum>0) {
+			// need to reset all of tree display extras!!!!!
+			for (int itree = 0; itree<numColumns*numRows; itree++) {
+				treeDisplays[itree].setVisible(false);
+			}
+			numColumns = newNum;
+			for (int itree = 0; itree<numColumns*numRows; itree++) {
+				treeDisplays[itree].setVisible(true);
+			}
+
+			if (treeScroll!=null && treeSourceTask!=null) {
+				treeScroll.setMaximum(treeSourceTask.getNumberOfTrees(taxa)/numColumns + 1); //-1);
+			}
+			setFirstTree(firstTree);
+			//sizeDisplays(false);
+			contentsChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public int getNumColumns(){
+		return numColumns;
+	}
+	/*.................................................................................................................*/
+	public void setNumRows(int newNum){
+		if (newNum>0) {
+			// need to reset all of tree display extras!!!!!
+			for (int itree = 0; itree<numColumns*numRows; itree++) {
+				treeDisplays[itree].setVisible(false);
+			}
+			numRows = newNum;
+			for (int itree = 0; itree<numColumns*numRows; itree++) {
+				treeDisplays[itree].setVisible(true);
+			}
+
+			setFirstTree(firstTree);
+			//sizeDisplays(false);
+			//for (int itree = 0; itree<numColumns*numRows; itree++)
+			//	addToWindow(treeDisplays[itree]);
+			contentsChanged();
+		}
+	}
+	/*.................................................................................................................*/
+	public int getNumRows(){
+		return numRows;
+	}
+	/*.................................................................................................................*/
+	public void windowResized() {
+		super.windowResized();
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		if (treeDisplays==null)
+			;//ownerModule.alert("Oh no, tree displays are null");
+		else  {
+			sizeDisplays(false);
+			setLegendPosition(MTWmodule.getLegendBotRight());
+		}
+
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void dispose(){
+		for (int itree=0; itree<treeDisplays.length; itree++) {
+			if (treeDisplays[itree]!=null){
+				if (treeDisplays[itree].getTree()!=null)
+					treeDisplays[itree].getTree().dispose();
+				treeDisplays[itree].dispose();
+			}
+		}
+		super.dispose();
+	}
+}
+
+/* ======================================================================== */
+class MTWScroll extends MesquiteScrollbar {
+	MultiTreeWindow w;
+	public MTWScroll (MultiTreeWindow w, int value, int visible, int min, int max){
+		super(Scrollbar.VERTICAL, value, visible, min, max);
+		this.w=w;
+	}
+
+	public void scrollTouched(){
+		int currentValue = getValue();
+		w.setFirstTree(currentValue*w.numColumns);
+	}
+	public boolean processDuringAdjustment() {
+		return false;
+	}
+	public void print(Graphics g){
+	}
+}
+
+
diff --git a/Source/mesquite/trees/NegativeToZeroBL/NegativeToZeroBL.java b/Source/mesquite/trees/NegativeToZeroBL/NegativeToZeroBL.java
new file mode 100644
index 0000000..1b8e6c6
--- /dev/null
+++ b/Source/mesquite/trees/NegativeToZeroBL/NegativeToZeroBL.java
@@ -0,0 +1,64 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.NegativeToZeroBL;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NegativeToZeroBL extends BranchLengthsAltererMult {
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+			zero(tree, tree.getRoot());
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+			return true;
+	}
+	/*.................................................................................................................*/
+   	 private void zero(AdjustableTree tree, int node){
+		if (tree.getBranchLength(node) < 0 && MesquiteDouble.isCombinable(tree.getBranchLength(node))) {
+			tree.setBranchLength(node, 0, false);
+		}
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			zero(tree, daughter);
+		}
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Convert Negative Branch Lengths to Zero";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adjusts a tree's branch lengths so that negative branch lengths are zero" ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/NodeLocsStandard/32expand.gif b/Source/mesquite/trees/NodeLocsStandard/32expand.gif
new file mode 100644
index 0000000..d1afceb
Binary files /dev/null and b/Source/mesquite/trees/NodeLocsStandard/32expand.gif differ
diff --git a/Source/mesquite/trees/NodeLocsStandard/64expand.gif b/Source/mesquite/trees/NodeLocsStandard/64expand.gif
new file mode 100644
index 0000000..cbb6186
Binary files /dev/null and b/Source/mesquite/trees/NodeLocsStandard/64expand.gif differ
diff --git a/Source/mesquite/trees/NodeLocsStandard/NodeLocsStandard.java b/Source/mesquite/trees/NodeLocsStandard/NodeLocsStandard.java
new file mode 100644
index 0000000..7c88a78
--- /dev/null
+++ b/Source/mesquite/trees/NodeLocsStandard/NodeLocsStandard.java
@@ -0,0 +1,1586 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NodeLocsStandard;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Calculates node locations for tree drawing in a standard vertical/horizontal position, as used by DiagonalDrawTree and SquareTree (for example).*/
+public class NodeLocsStandard extends NodeLocsVH {
+
+	int lastOrientation = 0;
+	Vector extras;
+	double fixedDepth = 1;
+	boolean leaveScaleAlone = true;
+	boolean fixedScale = false;
+	MesquiteBoolean inhibitStretch;
+	MesquiteBoolean showScale;
+	MesquiteBoolean broadScale;
+	MesquiteBoolean showBranchLengths;
+	boolean resetShowBranchLengths = false;
+	int fixedTaxonDistance = 0;
+
+	static final int totalHeight = 0;
+	static final int stretchfactor = 1;
+	static final int  scaling = 2;
+	
+
+//	double namesAngle = MesquiteDouble.unassigned;
+
+	int ROOTSIZE = 20;
+	MesquiteMenuItemSpec fixedScalingMenuItem, showScaleMenuItem, broadScaleMenuItem;
+	MesquiteMenuItemSpec offFixedScalingMenuItem, stretchMenuItem, evenMenuItem;
+	NameReference triangleNameRef;
+	MesquiteBoolean center;
+	boolean[] fixedSettings = null;
+	MesquiteBoolean even;
+	/*.................................................................................................................*/
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (condition instanceof boolean[]){
+			fixedSettings = (boolean[])condition;
+		}
+		extras = new Vector();
+		inhibitStretch = new MesquiteBoolean(false);
+		center = new MesquiteBoolean(false);
+		even = new MesquiteBoolean(false);
+		if (getEmployer()!=null && ("Square Tree".equalsIgnoreCase(getEmployer().getName()) || "Square Line Tree".equalsIgnoreCase(getEmployer().getName()))){ //a bit non-standard but a helpful service to use different defaults for square
+			even.setValue(true);
+			center.setValue(true);
+		}
+		triangleNameRef = NameReference.getNameReference("triangled");
+		showBranchLengths = new MesquiteBoolean(false);
+		showScale = new MesquiteBoolean(true);
+		broadScale = new MesquiteBoolean(false);
+
+		if (fixedSettings != null && fixedSettings.length>0 && fixedSettings[0]){
+			showBranchLengths.setValue(true);
+		}
+		else
+			addCheckMenuItem(null, "Branches Proportional to Lengths", makeCommand("branchLengthsToggle", this), showBranchLengths);
+
+		if (showBranchLengths.getValue()) {
+			fixedScalingMenuItem = addMenuItem( "Fixed Scaling...", makeCommand("setFixedScaling", this));
+			showScaleMenuItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+			broadScaleMenuItem = addCheckMenuItem(null, "Broad scale", makeCommand("toggleBroadScale", this), broadScale);
+			resetShowBranchLengths=true;
+		}
+		else {
+			stretchMenuItem = addCheckMenuItem(null, "Inhibit Stretch Tree to Fit", makeCommand("inhibitStretchToggle", this), inhibitStretch);
+			evenMenuItem = addCheckMenuItem(null, "Even root to tip spacing", makeCommand("toggleEven", this), even);
+		}
+		addMenuItem( "Fixed Distance Between Taxa...", makeCommand("setFixedTaxonDistance",  this));
+		addCheckMenuItem(null, "Centered Branches", makeCommand("toggleCenter", this), center);
+		if (employerAllowsReorientation())
+			addMenuItem("Set Current Orientation as Default", makeCommand("setDefaultOrientation",  this));
+
+		//	addMenuItem("Taxon Name Angle...", makeCommand("namesAngle", this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	private boolean employerAllowsReorientation(){
+		if (getEmployer()== null || !(getEmployer() instanceof DrawTree))
+			return true;
+		DrawTree dt = (DrawTree)getEmployer();
+		return dt.allowsReorientation();
+
+	}
+	public void endJob(){
+		storePreferences();
+		if (extras!=null) {
+			for (int i=0; i<extras.size(); i++){
+				TreeDisplayExtra extra = (TreeDisplayExtra)extras.elementAt(i);
+				if (extra!=null){
+					TreeDisplay td = extra.getTreeDisplay();
+					extra.turnOff();
+					if (td!=null)
+						td.removeExtra(extra);
+				}
+			}
+			extras.removeAllElements();
+		}
+		//treeDrawing = null;
+		//tree=null;
+		//treeDisplay=null;
+		if (showBranchLengths != null)
+			showBranchLengths.releaseMenuItem();
+		broadScale.releaseMenuItem();
+		showScale.releaseMenuItem();
+		inhibitStretch.releaseMenuItem();
+		center.releaseMenuItem();
+		even.releaseMenuItem();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			defaultOrientation = MesquiteInteger.fromString(prefs[0]);
+		}
+	}
+
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "defaultOrientation", defaultOrientation);   
+		return buffer.toString();
+	}
+
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("defaultOrientation".equalsIgnoreCase(tag))
+			defaultOrientation = MesquiteInteger.fromString(content);
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (stretchWasSet)
+			temp.addLine("inhibitStretchToggle " + inhibitStretch.toOffOnString());
+		temp.addLine("branchLengthsToggle " + showBranchLengths.toOffOnString());
+		temp.addLine("toggleScale " + showScale.toOffOnString());
+		temp.addLine("toggleBroadScale " + broadScale.toOffOnString());
+		temp.addLine("toggleCenter " + center.toOffOnString());
+		temp.addLine("toggleEven " + even.toOffOnString());
+		temp.addLine("setFixedTaxonDistance " + fixedTaxonDistance); 
+
+		if (fixedScale)
+			temp.addLine("setFixedScaling " + MesquiteDouble.toString(fixedDepth) );
+		return temp;
+	}
+
+	boolean stretchWasSet = false;
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "(For old scripts) Sets whether or not to stretch the tree to fit the drawing area", "[on = stretch; off]", commandName, "stretchToggle")) {
+			inhibitStretch.toggleValue(parser.getFirstToken(arguments));
+			inhibitStretch.toggleValue();  //since old sense is reverse
+			stretchWasSet = true;
+			parametersChanged();
+		}
+		else 	if (checker.compare(this.getClass(), "Sets a fixed distance between taxa for drawing the tree", "[distance in pixels]", commandName, "setFixedTaxonDistance")) {
+
+			int newDistance= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newDistance))
+				newDistance = MesquiteInteger.queryInteger(containerOfModule(), "Set taxon distance", "Distance between taxa:", "(Use a value of 0 to tell Mesquite to calculate the distance itself.)", "", fixedTaxonDistance, 0, 99, true);
+			if (newDistance>=0 && newDistance<100 && newDistance!=fixedTaxonDistance) {
+				fixedTaxonDistance=newDistance;
+/*				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+					treeDrawing.treeDisplay.setFixedTaxonSpacing(newDistance);
+				}
+				*/
+				
+				if ( !MesquiteThread.isScripting()) parametersChanged(new Notification(TREE_DRAWING_SIZING_CHANGED));
+			}
+
+		}
+	else if (checker.compare(this.getClass(), "Sets whether or not to inhibit automatic stretching the tree to fit the drawing area", "[on =inihibit stretch; off]", commandName, "inhibitStretchToggle")) {
+			inhibitStretch.toggleValue(parser.getFirstToken(arguments));
+			stretchWasSet = true;
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Here to avoid scripting error; user will need to reset taxon names", null, commandName, "namesAngle")) {
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to center the nodes between the immediate descendents, or the terminal in the clade", "[on = center over immediate; off]", commandName, "toggleCenter")) {
+			center.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to space the nodes evenly from root to tips", "[on = space evenly; off]", commandName, "toggleEven")) {
+			even.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets the current orientation to be the default", null, commandName, "setDefaultOrientation")) {
+			defaultOrientation = lastOrientation;
+			storePreferences();
+		}
+		else if (checker.compare(this.getClass(), "[no longer available; here to prevent warning given as old scripts are read]", "[]", commandName, "namesAngle")) {
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not the branches are to be shown proportional to their lengths", "[on = proportional; off]", commandName, "branchLengthsToggle")) {
+			if (fixedSettings != null && fixedSettings.length>0 && fixedSettings[0])
+				return null;
+			resetShowBranchLengths=true;
+			showBranchLengths.toggleValue(parser.getFirstToken(arguments));
+			if (!showBranchLengths.getValue()) {
+				deleteMenuItem(fixedScalingMenuItem);
+				deleteMenuItem(showScaleMenuItem);
+				deleteMenuItem(broadScaleMenuItem);
+				if (stretchMenuItem == null)
+					stretchMenuItem = addCheckMenuItem(null, "Inhibit Stretch tree to Fit", makeCommand("inhibitStretchToggle", this), inhibitStretch);
+				if (evenMenuItem == null)
+					evenMenuItem = addCheckMenuItem(null, "Even root to tip spacing", makeCommand("toggleEven", this), even);
+
+			}
+			else {
+				fixedScalingMenuItem = addMenuItem( "Fixed Scaling...", makeCommand("setFixedScaling", this));
+				showScaleMenuItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+				broadScaleMenuItem = addCheckMenuItem(null, "Broad scale", makeCommand("toggleBroadScale", this), broadScale);
+				deleteMenuItem(stretchMenuItem);
+				stretchMenuItem = null;
+				deleteMenuItem(evenMenuItem);
+				evenMenuItem = null;
+			}
+			resetContainingMenuBar();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets fixed scale length", "[length of branch lengths scale]", commandName, "setFixedScaling")) {
+			double newDepth;
+			if (StringUtil.blank(arguments))
+				newDepth= MesquiteDouble.queryDouble(containerOfModule(), "Set scaling depth", "Depth:", fixedDepth);
+			else 
+				newDepth= MesquiteDouble.fromString(arguments);
+			if (MesquiteDouble.isCombinable(newDepth) && newDepth>0) {
+				//TODO: remember these fixedScaling and depth to set in calcnodelocs below!!!!
+				fixedScale = true;
+				fixedDepth = newDepth;
+				leaveScaleAlone = false;
+				if (offFixedScalingMenuItem == null) {
+					offFixedScalingMenuItem = addMenuItem( "Off Fixed Scaling", makeCommand("offFixedScaling", this));
+					resetContainingMenuBar();
+				}
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to draw the scale for branch lengths", "[on or off]", commandName, "toggleScale")) {
+			showScale.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to draw the scale broadly, beneath the entire tree", "[on or off]", commandName, "toggleBroadScale")) {
+			broadScale.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Turns off fixed scaling", null, commandName, "offFixedScaling")) {
+			fixedScale = false;
+			leaveScaleAlone = false;
+			deleteMenuItem(offFixedScalingMenuItem);
+			offFixedScalingMenuItem = null;
+			resetContainingMenuBar();
+			parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public String getName() {
+		return "Node Locations (standard)";
+	}
+
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Calculates the node locations in a tree drawing, for use with vertical or horizontal tree drawers (e.g., the standard diagnonal or square trees)." ;
+	}
+	public boolean compatibleWithOrientation(int orientation) {
+		
+		return (orientation==TreeDisplay.UP || orientation==TreeDisplay.DOWN || orientation==TreeDisplay.RIGHT ||orientation==TreeDisplay.LEFT);
+	}
+	public void setDefaultOrientation(TreeDisplay treeDisplay) {
+		if (employerAllowsReorientation())
+			treeDisplay.setOrientation(defaultOrientation);
+	}
+	public int getDefaultOrientation() {
+		return defaultOrientation;
+	}
+	/*_________________________________________________*/
+
+	private double getNonZeroBranchLength(Tree tree, int N) {
+		if (tree.branchLengthUnassigned(N))
+			return 1;
+		else
+			return tree.getBranchLength(N);
+	}
+	/*_________________________________________________*/
+	private int lastleft;
+	/*_________________________________________________*/
+	private void UPCalcInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcInternalLocs(treeDrawing, tree, d);
+			int fD =tree.firstDaughterOfNode(N);
+			int lD =tree.lastDaughterOfNode(N);
+			if (lD==fD)   {//only one descendant
+				treeDrawing.y[N] = treeDrawing.y[fD];
+				treeDrawing.x[N] =treeDrawing.x[fD];
+			}
+			else {
+				int nFDx = treeDrawing.x[fD];
+				int nFDy = treeDrawing.y[fD];
+				int nLDx = treeDrawing.x[lD];
+				int nLDy = treeDrawing.y[lD];
+				treeDrawing.y[N] = (-nFDx + nLDx+nFDy + nLDy) / 2;
+				treeDrawing.x[N] =(nFDx + nLDx - nFDy + nLDy) / 2;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void UPDOWNCenterInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPDOWNCenterInternalLocs(treeDrawing, tree, d);
+			int fD =tree.firstDaughterOfNode(N);
+			int lD =tree.lastDaughterOfNode(N);
+			if (lD!=fD)   {//> one descendant
+				int nFDx = treeDrawing.x[fD];
+				int nLDx = treeDrawing.x[lD];
+				treeDrawing.x[N] =(nFDx + nLDx) / 2;
+			}
+		}
+	}
+
+	/*....................................................................................................*/
+	private void UPCalcTerminalLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, boolean inTriangle, int numInTriangle, int triangleBase) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+			if (inTriangle && tree.numberOfTerminalsInClade(triangleBase)>3 && treeDisplay.getSimpleTriangle()){
+				if (tree.leftmostTerminalOfNode(triangleBase)==N)
+					lastleft+= getSpacing(treeDisplay, tree, N, inTriangle); 
+				else {
+					//more than 2 in triangle; triangle as wide as 3.  Thus each 
+					if (tree.rightmostTerminalOfNode(triangleBase)==N)
+						lastleft= treeDrawing.x[tree.leftmostTerminalOfNode(triangleBase)] + 2*treeDisplay.getTaxonSpacing();
+					else 
+						lastleft+= (getSpacing(treeDisplay, tree, N, inTriangle)*2)/(numInTriangle-1);
+				}
+			}
+			else
+				lastleft+= getSpacing(treeDisplay, tree, N, inTriangle);
+			treeDrawing.y[N] = treeDisplay.getTipsMargin();
+			treeDrawing.x[N] = lastleft;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (inTriangle)
+					UPCalcTerminalLocs(treeDisplay, treeDrawing, tree, d,true, numInTriangle, triangleBase);
+				else
+					UPCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, tree.getAssociatedBit(triangleNameRef, d), tree.numberOfTerminalsInClade(d), d);
+			}
+		}
+	}
+	/*....................................................................................................*/
+	private void UPevenNodeLocs(TreeDrawing treeDrawing, Tree tree, int N, int evenVertSpacing) {
+		if (tree.nodeIsInternal(N)){
+			int deepest = 0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				UPevenNodeLocs(treeDrawing, tree, d, evenVertSpacing);
+				if (treeDrawing.y[d]>deepest)
+					deepest = treeDrawing.y[d];
+			}
+			treeDrawing.y[N] = deepest + evenVertSpacing;
+		}
+	}
+	/*....................................................................................................*/
+	private void UPstretchNodeLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			UPstretchNodeLocs(treeDisplay, treeDrawing, tree, d);
+		treeDrawing.y[N] = treeDisplay.getTipsMargin() + (int)((treeDrawing.y[N]-treeDisplay.getTipsMargin())*treeDisplay.nodeLocsParameters[stretchfactor]);
+	}
+
+	/*....................................................................................................*/
+	private void UPdoAdjustLengths (TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int bottom, int N, double ancH, int root) {
+		double nH;
+		if (N==root) {
+			nH=bottom;
+		}
+		else {
+			nH=ancH - (getNonZeroBranchLength(tree, N)*treeDisplay.nodeLocsParameters[scaling]);
+		}
+		treeDrawing.y[N]=(int)(nH);
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			UPdoAdjustLengths(treeDisplay, treeDrawing, tree, bottom, d, nH, root);
+
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcInternalLocs(treeDrawing, tree, d);
+			int nFD = tree.firstDaughterOfNode(N);
+			int nLD = tree.lastDaughterOfNode(N);
+			int nFDx = treeDrawing.x[nFD];
+			int nFDy = treeDrawing.y[nFD];
+			int nLDx = treeDrawing.x[nLD];
+			int nLDy = treeDrawing.y[nLD];
+			if (nLD==nFD)   {//only one descendant; put same as descendant, to be adjusted later
+				treeDrawing.y[N] = treeDrawing.y[nFD];
+				treeDrawing.x[N] =treeDrawing.x[nFD];
+			}
+			else {
+				treeDrawing.y[N] = (nFDx - nLDx + nFDy + nLDy) / 2;
+				treeDrawing.x[N] =(nFDx + nLDx + nFDy - nLDy) / 2;
+			}
+		}
+	}
+
+	/*....................................................................................................*/
+	private void DOWNCalcTerminalLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, int margin,  boolean inTriangle, int numInTriangle, int triangleBase) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+			if (inTriangle && tree.numberOfTerminalsInClade(triangleBase)>3 && treeDisplay.getSimpleTriangle()){
+				if (tree.leftmostTerminalOfNode(triangleBase)==N)
+					lastleft+= getSpacing(treeDisplay, tree, N, inTriangle); 
+				else {
+					//more than 2 in triangle; triangle as wide as 3.  Thus each 
+					if (tree.rightmostTerminalOfNode(triangleBase)==N)
+						lastleft= treeDrawing.x[tree.leftmostTerminalOfNode(triangleBase)] + 2*getSpacing(treeDisplay, tree, N, inTriangle);
+					else 
+						lastleft+= (getSpacing(treeDisplay, tree, N,inTriangle)*2)/(numInTriangle-1);
+				}
+			}
+			else
+				lastleft+= getSpacing(treeDisplay, tree, N, inTriangle);
+			treeDrawing.y[N] = margin;
+			treeDrawing.x[N] = lastleft;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (inTriangle)
+					DOWNCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, true, numInTriangle, triangleBase);
+				else
+					DOWNCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, tree.getAssociatedBit(triangleNameRef, d), tree.numberOfTerminalsInClade(d), d);
+		}
+	}
+	/*....................................................................................................*/
+	private void DOWNstretchNodeLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, int margin) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			DOWNstretchNodeLocs(treeDisplay, treeDrawing, tree, d, margin);
+		treeDrawing.y[N] = margin-(int)((margin-treeDrawing.y[N])*treeDisplay.nodeLocsParameters[stretchfactor]);
+	}
+	/*....................................................................................................*/
+	private void DOWNevenNodeLocs(TreeDrawing treeDrawing, Tree tree, int N, int evenVertSpacing) {
+		if (tree.nodeIsInternal(N)){
+			int deepest = 10000000;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				DOWNevenNodeLocs(treeDrawing, tree, d, evenVertSpacing);
+				if (treeDrawing.y[d]<deepest)
+					deepest = treeDrawing.y[d];
+			}
+			treeDrawing.y[N] = deepest - evenVertSpacing;
+		}
+	}
+
+	/*....................................................................................................*/
+	private void DOWNdoAdjustLengths (TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int bottom, int N, double ancH, int root) {
+		double nH;
+		if (N==root) 
+			nH=bottom;
+		else
+			nH=ancH + (getNonZeroBranchLength(tree, N)*treeDisplay.nodeLocsParameters[scaling]);
+
+		treeDrawing.y[N]=(int)(nH);
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			DOWNdoAdjustLengths(treeDisplay, treeDrawing, tree, bottom, d, nH, root);
+
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcInternalLocs(treeDrawing, tree,  d);
+			int fD = tree.firstDaughterOfNode(N);
+			int lD = tree.lastDaughterOfNode(N);
+			int nFDx = treeDrawing.x[fD];
+			int nFDy = treeDrawing.y[fD];
+			int nLDx = treeDrawing.x[lD];
+			int nLDy = treeDrawing.y[lD];
+			if (lD==fD)   {//only one descendant
+				treeDrawing.y[N] = treeDrawing.y[fD];
+				treeDrawing.x[N] =treeDrawing.x[fD];
+			}
+			else {
+				treeDrawing.x[N] =(nFDy - nLDy + nFDx + nLDx) / 2;
+				treeDrawing.y[N] =(nFDx - nLDx + nFDy + nLDy) / 2;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	private void RIGHTLEFTCenterInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTLEFTCenterInternalLocs(treeDrawing, tree, d);
+			int fD =tree.firstDaughterOfNode(N);
+			int lD =tree.lastDaughterOfNode(N);
+			if (lD!=fD)   {//> one descendant
+				int nFDy = treeDrawing.y[fD];
+				int nLDy = treeDrawing.y[lD];
+				treeDrawing.y[N] =(nFDy + nLDy) / 2;
+			}
+		}
+	}
+
+	/*....................................................................................................*/
+	private void RIGHTCalcTerminalLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, int margin,  boolean inTriangle, int numInTriangle, int triangleBase) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+			if (inTriangle && tree.numberOfTerminalsInClade(triangleBase)>3 && treeDisplay.getSimpleTriangle()){
+				if (tree.leftmostTerminalOfNode(triangleBase)==N)
+					lastleft+= getSpacing(treeDisplay, tree, N, inTriangle); 
+				else {
+					//more than 2 in triangle; triangle as wide as 3.  Thus each 
+					if (tree.rightmostTerminalOfNode(triangleBase)==N)
+						lastleft= treeDrawing.y[tree.leftmostTerminalOfNode(triangleBase)] + 2*getSpacing(treeDisplay, tree, N, inTriangle);
+					else 
+						lastleft+= (getSpacing(treeDisplay, tree, N, inTriangle)*2)/(numInTriangle-1);
+				}
+			}
+			else
+				lastleft+= getSpacing(treeDisplay, tree, N, inTriangle);
+			treeDrawing.x[N] = margin;
+			treeDrawing.y[N] = lastleft;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (inTriangle)
+					RIGHTCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, true, numInTriangle, triangleBase);
+				else
+					RIGHTCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, tree.getAssociatedBit(triangleNameRef, d), tree.numberOfTerminalsInClade(d),d);
+		}
+	}
+	/*....................................................................................................*/
+	private void RIGHTstretchNodeLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, int margin) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			RIGHTstretchNodeLocs(treeDisplay, treeDrawing, tree, d, margin);
+		treeDrawing.x[N] =  margin- (int)((margin - treeDrawing.x[N])*treeDisplay.nodeLocsParameters[stretchfactor]);
+	}
+
+	/*....................................................................................................*/
+	private void RIGHTevenNodeLocs(TreeDrawing treeDrawing, Tree tree, int N, int evenVertSpacing) {
+		if (tree.nodeIsInternal(N)){
+			int deepest = 1000000;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				RIGHTevenNodeLocs(treeDrawing, tree, d, evenVertSpacing);
+				if (treeDrawing.x[d]<deepest)
+					deepest = treeDrawing.x[d];
+			}
+			treeDrawing.x[N] = deepest - evenVertSpacing;
+		}
+	}
+	/*....................................................................................................*/
+	private void RIGHTdoAdjustLengths (TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int bottom, int N, double ancH, int root) {
+		double nH;
+
+		if (N==root) 
+			nH=bottom;
+		else 
+			nH=ancH + (getNonZeroBranchLength(tree, N)*treeDisplay.nodeLocsParameters[scaling]);
+		treeDrawing.x[N]=(int)(nH);
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			RIGHTdoAdjustLengths(treeDisplay, treeDrawing, tree, bottom, d, nH, root);
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcInternalLocs(TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcInternalLocs(treeDrawing, tree, d);
+			int fD = tree.firstDaughterOfNode(N);
+			int lD = tree.lastDaughterOfNode(N);
+			int nFDx = treeDrawing.x[fD];
+			int nFDy = treeDrawing.y[fD];
+			int nLDx = treeDrawing.x[lD];
+			int nLDy = treeDrawing.y[lD];
+			if (lD==fD)   {//only one descendant
+				treeDrawing.y[N] = treeDrawing.y[fD];
+				treeDrawing.x[N] =treeDrawing.x[fD];
+			}
+			else {
+				treeDrawing.x[N] =(nLDy - nFDy + nLDx + nFDx) / 2;
+				treeDrawing.y[N] =(nLDx - nFDx + nLDy + nFDy) / 2;
+			}
+		}
+	}
+
+	/*....................................................................................................*/
+	private void LEFTCalcTerminalLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N, int margin,  boolean inTriangle, int numInTriangle, int triangleBase) {
+		if  (tree.nodeIsTerminal(N)) {   //terminal
+			if (inTriangle && tree.numberOfTerminalsInClade(triangleBase)>3 && treeDisplay.getSimpleTriangle()){
+				if (tree.leftmostTerminalOfNode(triangleBase)==N)
+					lastleft+= getSpacing(treeDisplay, tree, N, inTriangle); 
+				else {
+					//more than 2 in triangle; triangle as wide as 3.  Thus each 
+					if (tree.rightmostTerminalOfNode(triangleBase)==N)
+						lastleft= treeDrawing.y[tree.leftmostTerminalOfNode(triangleBase)] + 2*getSpacing(treeDisplay, tree, N, inTriangle);
+					else 
+						lastleft+= (getSpacing(treeDisplay, tree, N, inTriangle)*2)/(numInTriangle-1);
+				}
+			}
+			else
+				lastleft+= getSpacing(treeDisplay, tree, N, inTriangle);
+			treeDrawing.x[N] = margin;
+			treeDrawing.y[N] = lastleft;
+		}
+		else {
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				if (inTriangle)
+					LEFTCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, true, numInTriangle, triangleBase);
+				else
+					LEFTCalcTerminalLocs(treeDisplay, treeDrawing, tree, d, margin, tree.getAssociatedBit(triangleNameRef, d),tree.numberOfTerminalsInClade(d),d);
+		}
+	}
+	/*....................................................................................................*/
+	private void LEFTstretchNodeLocs(TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int N) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			LEFTstretchNodeLocs(treeDisplay, treeDrawing, tree, d);
+		treeDrawing.x[N] = treeDisplay.getTipsMargin() + (int)((treeDrawing.x[N]-treeDisplay.getTipsMargin())*treeDisplay.nodeLocsParameters[stretchfactor]);
+	}
+
+	/*....................................................................................................*/
+	private void LEFTevenNodeLocs(TreeDrawing treeDrawing, Tree tree, int N, int evenVertSpacing) {
+		if (tree.nodeIsInternal(N)){
+			int deepest = 0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				LEFTevenNodeLocs(treeDrawing, tree, d, evenVertSpacing);
+				if (treeDrawing.x[d]>deepest)
+					deepest = treeDrawing.x[d];
+			}
+			treeDrawing.x[N] = deepest + evenVertSpacing;
+		}
+	}
+	/*....................................................................................................*/
+	private void LEFTdoAdjustLengths (TreeDisplay treeDisplay, TreeDrawing treeDrawing, Tree tree, int bottom, int N, double ancH, int root) {
+		double nH;
+		if (N==root) 
+			nH=bottom;
+		else 
+			nH=ancH - (getNonZeroBranchLength(tree, N)*treeDisplay.nodeLocsParameters[scaling]);
+
+		treeDrawing.x[N]=(int)(nH);
+
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			LEFTdoAdjustLengths(treeDisplay, treeDrawing, tree, bottom, d, nH, root);
+	}
+	/*....................................................................................................*/
+	private int edgeNode (TreeDrawing treeDrawing, Tree tree, int node, boolean x, boolean max) {
+		if (tree.nodeIsTerminal(node)) {
+			if (x)
+				return treeDrawing.x[node];
+			else
+				return treeDrawing.y[node];
+		}
+		int t;
+		if (max)
+			t = 0;
+		else
+			t = 1000000;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			int e = edgeNode( treeDrawing, tree, d, x, max);
+			if (max && e> t)
+				t = e;
+			else if (!max && e < t)
+				t = e;
+		}
+		return t;
+	}
+	/*_________________________________________________*/
+	private int propAverage(int xd, int xa, int i, int L){
+		return (int)(1.0*i*(xa-xd)/L + xd);
+	}
+
+	private void placeSingletons (TreeDrawing treeDrawing, Tree tree, int N) {
+		if (tree.numberOfDaughtersOfNode(N)==1)	{
+			int bD = tree.branchingDescendant(N);
+			int bA;
+			if (N==tree.getRoot()) {
+				bA = tree.getSubRoot();
+			}
+			else {
+				bA = tree.branchingAncestor(N);
+				if (bA == tree.getRoot() && tree.numberOfDaughtersOfNode(bA)==1)
+					bA = tree.getSubRoot();
+			}
+			int nA = tree.depthToAncestor(N, bA);
+			int nD = tree.depthToAncestor(bD, N);
+			treeDrawing.x[N]=propAverage(treeDrawing.x[bD], treeDrawing.x[bA], nD, nA+nD);
+			treeDrawing.y[N]=propAverage(treeDrawing.y[bD], treeDrawing.y[bA], nD, nA+nD);
+		}
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			placeSingletons(treeDrawing, tree, d);
+	}
+	/*....................................................................................................*/
+	private void AdjustForUnbranchedNodes(TreeDrawing treeDrawing, Tree tree, int N, int subRoot) {
+		if (tree.nodeIsInternal(N)) { //internal
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				AdjustForUnbranchedNodes(treeDrawing, tree, d, subRoot);
+			if (tree.lastDaughterOfNode(N) == tree.firstDaughterOfNode(N)) {  // has only one Daughter
+				if (tree.numberOfDaughtersOfNode(tree.motherOfNode(N)) != 1 || tree.motherOfNode(N)==subRoot) { //and is base of chain w 1
+					//count length of chain of nodes with only one Daughter
+					int count = 2;  // at least 2 in chain
+					int q = tree.firstDaughterOfNode(N);
+					while (tree.nodeIsInternal(q) && tree.firstDaughterOfNode(q) ==tree.lastDaughterOfNode(q)) {
+						count++;
+						q = tree.firstDaughterOfNode(q);
+					}
+					//adjust nodes in chain
+					int bottomX =treeDrawing.x[tree.motherOfNode(N)] ;
+					int bottomY =treeDrawing.y[tree.motherOfNode(N)] ;
+					int topX =treeDrawing.x[N] ;
+					int topY =treeDrawing.y[N] ;
+					treeDrawing.y[N] = (bottomY+topY)/count;
+					treeDrawing.x[N] = (bottomX+topX)/count;
+					int count2=1;
+					q = tree.firstDaughterOfNode(N);
+					while (tree.nodeIsInternal(q) && tree.firstDaughterOfNode(q) ==tree.lastDaughterOfNode(q)) {
+						count2++;
+						treeDrawing.y[q] = (bottomY+topY)*count2/count;
+						treeDrawing.x[q] = (bottomX+topX)*count2/count;
+						q = tree.firstDaughterOfNode(q);
+					}
+				}
+			}
+		}
+	}
+	/*....................................................................................................*/
+	FontMetrics fm;
+	private int findMaxNameLength(Tree tree, int N) {
+		if (tree.nodeIsTerminal(N)) {
+			String s = tree.getTaxa().getName(tree.taxonNumberOfNode(N));
+			if (s==null)
+				return 0;
+			else
+				return fm.stringWidth(s);
+		}
+		else {
+			int max = 0;
+			for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				int cur = findMaxNameLength(tree, d);
+				if (cur>max)
+					max = cur;
+			}
+			return max;
+		}
+	}
+	/*.................................................................................................................*/
+	public int effectiveNumberOfTerminals(Tree tree, int node){
+		if (tree.nodeIsTerminal(node))
+			return 1;
+		else if (tree.getAssociatedBit(triangleNameRef, node)) {
+			if (tree.numberOfTerminalsInClade(node)>2)
+				return 3;
+			else 
+				return 2;
+		}
+		int num=0;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			num += effectiveNumberOfTerminals(tree, d);
+		}
+		return num;
+	}
+	/*.................................................................................................................*/
+	int zoomNode = -1;
+	double zoomFactor = 1.0;
+	void setZoom(TreeDisplay treeDisplay, int node, double factor){
+		if (!treeDisplay.getTree().descendantOf(node, zoomNode)){ //in zoom
+			int inZoom = treeDisplay.getTree().numberOfTerminalsInClade(zoomNode);
+			int outZoom = treeDisplay.getTree().numberOfTerminalsInClade(treeDisplay.getTreeDrawing().getDrawnRoot()) - inZoom;
+			double currentFactor = (1 - (zoomFactor-1)*inZoom/outZoom);
+			factor *= currentFactor;
+		}
+		zoomNode = node;
+		zoomFactor = factor;
+		parametersChanged();
+	}
+	int getSpacing(TreeDisplay treeDisplay, Tree tree, int node, boolean inTriangle){
+		if (inTriangle && !treeDisplay.getSimpleTriangle()) {
+			int ancestralNode = tree.ancestorWithNameReference(triangleNameRef, node);
+			if (ancestralNode==0 ||  node != tree.leftmostTerminalOfNode(ancestralNode))
+				return 4;
+		}
+		int baseSpacing =treeDisplay.getTaxonSpacing();
+		if (zoomNode > 0){
+			int inZoom = tree.numberOfTerminalsInClade(zoomNode);
+			if (inZoom<2)
+				return baseSpacing;
+			int outZoom = tree.numberOfTerminalsInClade(treeDisplay.getTreeDrawing().getDrawnRoot()) - inZoom;
+
+			if (tree.descendantOf(node, zoomNode)){ //in zoom
+				//	x * baseSpacing*  inZoom + y *baseSpacing*  outZoom = (inZoom + outZoom)*baseSpacing;
+				return (int)(baseSpacing *zoomFactor);
+				//return baseSpacing * (inZoom + outZoom) / inZoom/2;
+			}
+			else {
+				return (int)(baseSpacing * (1 - (zoomFactor-1)*inZoom/outZoom));
+
+				// return baseSpacing * (inZoom + outZoom) / outZoom/2;
+			}
+		}
+		return baseSpacing;
+	}
+	
+	/*.................................................................................................................*/
+	public void calculateNodeLocs(TreeDisplay treeDisplay, Tree tree, int drawnRoot, Rectangle rect) { //Graphics g removed as parameter May 02
+		if (MesquiteTree.OK(tree)) {
+			int effectiveROOTSIZE = ROOTSIZE;
+			if (tree.numberOfTerminalsInClade(drawnRoot) == 1){
+				effectiveROOTSIZE += rect.height/2;
+			}
+			/*if (!stretchWasSet){
+				if (treeDisplay.inhibitStretchByDefault != inhibitStretch.getValue())
+					inhibitStretch.setValue(treeDisplay.inhibitStretchByDefault);
+			}*/
+			treeDisplay.setFixedTaxonSpacing(fixedTaxonDistance);  //NEW
+		//	int fixedTaxonDistance = treeDisplay.getFixedTaxonSpacing();  OLD code
+			lastOrientation = treeDisplay.getOrientation();
+			//this.treeDisplay = treeDisplay; 
+			if (!leaveScaleAlone) {
+				treeDisplay.fixedDepthScale = fixedDepth;
+				treeDisplay.fixedScalingOn = fixedScale;
+			}
+			TreeDrawing treeDrawing = treeDisplay.getTreeDrawing();
+			//		treeDrawing.namesAngle = namesAngle;
+			//this.tree = tree;
+			if (treeDisplay.getExtras() !=null) {
+				if (treeDisplay.getExtras().myElements(this)==null) {  //todo: need to do one for each treeDisplay!
+					NodeLocsExtra extra = new NodeLocsExtra(this, treeDisplay); 
+					treeDisplay.addExtra(extra); 
+					extras.addElement(extra);
+				}
+			}
+			int root = drawnRoot;
+			int subRoot = tree.motherOfNode(drawnRoot);
+			int buffer = 20;
+
+			Graphics g = treeDisplay.getGraphics();
+			if (g!=null) {
+				if (!treeDisplay.suppressNames) {
+					DrawNamesTreeDisplay dtn = treeDisplay.getDrawTaxonNames();
+					Font f = null;
+					if (dtn!=null)
+						f = dtn.getFont();
+
+					if (f==null)
+						f = g.getFont();
+					fm=g.getFontMetrics(f);
+					if (fm!=null)
+						treeDisplay.setTipsMargin(findMaxNameLength(tree, root) + treeDisplay.getTaxonNameBuffer() + treeDisplay.getTaxonNameDistance());
+				}
+				else 
+					treeDisplay.setTipsMargin(treeDisplay.getTaxonNameBuffer());
+				g.dispose();
+			}
+
+			int marginOffset=0;
+			if (resetShowBranchLengths)
+				treeDisplay.showBranchLengths=showBranchLengths.getValue();
+			else {
+				if (treeDisplay.showBranchLengths != showBranchLengths.getValue()) {
+					showBranchLengths.setValue(treeDisplay.showBranchLengths);
+					if (!showBranchLengths.getValue()) {
+						deleteMenuItem(fixedScalingMenuItem);
+						deleteMenuItem(showScaleMenuItem);
+						deleteMenuItem(broadScaleMenuItem);
+						if (stretchMenuItem == null)
+							stretchMenuItem = addCheckMenuItem(null, "Stretch tree to Fit", makeCommand("stretchToggle", this), inhibitStretch);
+						if (evenMenuItem == null)
+							evenMenuItem = addCheckMenuItem(null, "Even root to tip spacing", makeCommand("toggleEven", this), even);
+					}
+					else {
+						fixedScalingMenuItem = addMenuItem( "Fixed Scaling...", makeCommand("setFixedScaling", this));
+						showScaleMenuItem = addCheckMenuItem(null, "Show scale", makeCommand("toggleScale", this), showScale);
+						broadScaleMenuItem = addCheckMenuItem(null, "Broad scale", makeCommand("toggleBroadScale", this), broadScale);
+						deleteMenuItem(stretchMenuItem);
+						stretchMenuItem = null;
+						deleteMenuItem(evenMenuItem);
+						evenMenuItem = null;
+					}
+					resetContainingMenuBar();
+				}
+			}
+			if (!compatibleWithOrientation(treeDisplay.getOrientation()))
+				setDefaultOrientation(treeDisplay);
+			
+			if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+				int numTerms = effectiveNumberOfTerminals(tree, root);
+				if (numTerms == 0)
+					numTerms = 1;
+				if (fixedTaxonDistance!=0 && MesquiteInteger.isCombinable(fixedTaxonDistance))
+					treeDisplay.setTaxonSpacing(fixedTaxonDistance);
+				else
+					treeDisplay.setTaxonSpacing( (rect.width - 30) / numTerms);
+				if (numTerms*treeDisplay.getTaxonSpacing()>.95*rect.width && treeDisplay.getTaxonSpacing()/2*2 != treeDisplay.getTaxonSpacing())  //if odd
+					treeDisplay.setTaxonSpacing(treeDisplay.getTaxonSpacing()-1);
+				lastleft = -treeDisplay.getTaxonSpacing()/3*2; //TODO: this causes problems for shrunk, since first taxon doesn't move over enough
+				UPCalcTerminalLocs(treeDisplay, treeDrawing, tree, root, tree.getAssociatedBit(triangleNameRef, root), tree.numberOfTerminalsInClade(root), root);
+				UPCalcInternalLocs( treeDrawing, tree, root);
+				if (center.getValue())
+					UPDOWNCenterInternalLocs( treeDrawing, tree, root);
+				//AdjustForUnbranchedNodes(root, subRoot);
+				marginOffset = treeDisplay.getTipsMargin() + rect.y;
+				treeDrawing.y[subRoot] = (treeDrawing.y[root])+effectiveROOTSIZE;
+				treeDrawing.x[subRoot] = (treeDrawing.x[root])-effectiveROOTSIZE;
+				placeSingletons(treeDrawing, tree, root);
+				if (treeDisplay.showBranchLengths) {
+					treeDisplay.nodeLocsParameters[totalHeight]= tree.tallestPathAboveNode(root, 1.0);
+					if (!treeDisplay.fixedScalingOn) {
+						treeDisplay.fixedDepthScale = treeDisplay.nodeLocsParameters[totalHeight];
+						fixedDepth = treeDisplay.fixedDepthScale;
+						if (treeDisplay.nodeLocsParameters[totalHeight]==0){
+							treeDisplay.nodeLocsParameters[scaling]=1;
+						}
+						else
+							treeDisplay.nodeLocsParameters[scaling]=((double)(rect.height-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.nodeLocsParameters[totalHeight]); 
+						UPdoAdjustLengths( treeDisplay, treeDrawing, tree, rect.height-effectiveROOTSIZE-buffer, root, 0, root);
+						if (showScale.getValue()) {
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+						}
+					}
+					else {
+						if (treeDisplay.fixedDepthScale == 0)
+							treeDisplay.fixedDepthScale = 1;
+
+						treeDisplay.nodeLocsParameters[scaling]=((double)(rect.height-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.fixedDepthScale); 
+						UPdoAdjustLengths( treeDisplay, treeDrawing, tree, rect.height-effectiveROOTSIZE-(int)(treeDisplay.nodeLocsParameters[scaling]*(treeDisplay.fixedDepthScale-treeDisplay.nodeLocsParameters[totalHeight])+buffer), root, 0, root);
+						if (showScale.getValue()) {
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.fixedDepthScale, treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+						}
+					}
+
+					treeDrawing.y[subRoot] = (treeDrawing.y[root])+(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]); //effectiveROOTSIZE
+					treeDrawing.x[subRoot] = (treeDrawing.x[root])-(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+				}
+				else {
+					if (even.getValue()){
+						int evenVertSpacing =(int)((treeDrawing.y[subRoot] - edgeNode(treeDrawing, tree, root, false, false))/ (tree.mostStepsAboveNode(root) + 1));
+						if (evenVertSpacing > 0)
+							UPevenNodeLocs(treeDrawing, tree, root, evenVertSpacing);
+					}
+					if (!inhibitStretch.getValue() && (treeDisplay.autoStretchIfNeeded && treeDrawing.y[subRoot]>rect.height)) {
+						treeDisplay.nodeLocsParameters[stretchfactor]=((double)(rect.height-treeDisplay.getTipsMargin())) / (treeDrawing.y[subRoot] - (int)treeDisplay.getTipsMargin());
+						UPstretchNodeLocs(treeDisplay, treeDrawing, tree, root);
+						treeDrawing.y[subRoot]=rect.height-5;
+					}
+				}
+
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+				int numTerms = effectiveNumberOfTerminals(tree, root);
+				if (numTerms == 0)
+					numTerms = 1;
+				if (fixedTaxonDistance!=0 && MesquiteInteger.isCombinable(fixedTaxonDistance))
+					treeDisplay.setTaxonSpacing(fixedTaxonDistance);
+				else
+					treeDisplay.setTaxonSpacing( (rect.width - 30) / numTerms);
+				if (numTerms*treeDisplay.getTaxonSpacing()>.95*rect.width && treeDisplay.getTaxonSpacing()/2*2 != treeDisplay.getTaxonSpacing())  //if odd
+					treeDisplay.setTaxonSpacing(treeDisplay.getTaxonSpacing()-1);
+				lastleft = -treeDisplay.getTaxonSpacing()/3*2;
+				DOWNCalcTerminalLocs(treeDisplay, treeDrawing, tree, root, rect.height-treeDisplay.getTipsMargin(), tree.getAssociatedBit(triangleNameRef, root), tree.numberOfTerminalsInClade(root), root);
+				DOWNCalcInternalLocs(treeDrawing, tree, root);
+				if (center.getValue())
+					UPDOWNCenterInternalLocs(treeDrawing, tree, root);
+				//AdjustForUnbranchedNodes(root, subRoot);
+				marginOffset = 0;
+				treeDrawing.y[subRoot] = (treeDrawing.y[root])-effectiveROOTSIZE;
+				treeDrawing.x[subRoot] = (treeDrawing.x[root])-effectiveROOTSIZE;
+				placeSingletons(treeDrawing, tree, root);
+				if (treeDisplay.showBranchLengths) {
+					treeDisplay.nodeLocsParameters[totalHeight]=tree.tallestPathAboveNode(root, 1.0);
+					if (!treeDisplay.fixedScalingOn) {
+						treeDisplay.fixedDepthScale = treeDisplay.nodeLocsParameters[totalHeight];
+						fixedDepth = treeDisplay.fixedDepthScale;
+						if (treeDisplay.nodeLocsParameters[totalHeight]==0)
+							treeDisplay.nodeLocsParameters[scaling]=1;
+						else
+							treeDisplay.nodeLocsParameters[scaling]=((double)(rect.height-treeDisplay.getTipsMargin() -buffer - effectiveROOTSIZE))/(treeDisplay.nodeLocsParameters[totalHeight]); 
+						DOWNdoAdjustLengths(treeDisplay, treeDrawing, tree, effectiveROOTSIZE+ buffer, root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+					else {
+						if (treeDisplay.fixedDepthScale == 0)
+							treeDisplay.fixedDepthScale = 1;
+						treeDisplay.nodeLocsParameters[scaling]=((double)(rect.height-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.fixedDepthScale); 
+						DOWNdoAdjustLengths(treeDisplay, treeDrawing, tree, effectiveROOTSIZE+(int)(treeDisplay.nodeLocsParameters[scaling]*(treeDisplay.fixedDepthScale-treeDisplay.nodeLocsParameters[totalHeight]) + buffer), root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.fixedDepthScale, treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+
+					treeDrawing.y[subRoot] = (treeDrawing.y[root])-(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+					treeDrawing.x[subRoot] = (treeDrawing.x[root])-(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+				}
+				else {
+					if (even.getValue()){
+						int evenVertSpacing =(int)((- treeDrawing.y[subRoot] + edgeNode(treeDrawing, tree, root, false, true))/ (tree.mostStepsAboveNode(root) + 1));
+						if (evenVertSpacing > 0)
+							DOWNevenNodeLocs(treeDrawing, tree, root, evenVertSpacing);
+					}
+					if (!inhibitStretch.getValue() && (treeDisplay.autoStretchIfNeeded && treeDrawing.y[subRoot]<0)) {
+						treeDisplay.nodeLocsParameters[stretchfactor]=((double)(rect.height-treeDisplay.getTipsMargin())) / (rect.height - treeDrawing.y[subRoot] - treeDisplay.getTipsMargin());
+						DOWNstretchNodeLocs(treeDisplay, treeDrawing, tree, root, rect.height-treeDisplay.getTipsMargin());
+						treeDrawing.y[subRoot]=5;
+					}
+				}
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+				int numTerms = effectiveNumberOfTerminals(tree, root);
+				if (numTerms == 0)
+					numTerms = 1;
+				if (fixedTaxonDistance!=0 && MesquiteInteger.isCombinable(fixedTaxonDistance))
+					treeDisplay.setTaxonSpacing(fixedTaxonDistance);
+				else
+					treeDisplay.setTaxonSpacing( (rect.height - 30) / numTerms);
+				if (numTerms*treeDisplay.getTaxonSpacing()>.95*rect.height && treeDisplay.getTaxonSpacing()/2*2 != treeDisplay.getTaxonSpacing())  //if odd
+					treeDisplay.setTaxonSpacing(treeDisplay.getTaxonSpacing()-1);
+				lastleft = -treeDisplay.getTaxonSpacing()/3*2;
+				RIGHTCalcTerminalLocs(treeDisplay, treeDrawing, tree, root, rect.width-treeDisplay.getTipsMargin(), tree.getAssociatedBit(triangleNameRef, root), tree.numberOfTerminalsInClade(root), root);
+				RIGHTCalcInternalLocs(treeDrawing, tree, root);
+				if (center.getValue())
+					RIGHTLEFTCenterInternalLocs( treeDrawing, tree, root);
+				//AdjustForUnbranchedNodes(root, subRoot);
+				treeDrawing.y[subRoot] = (treeDrawing.y[root])-effectiveROOTSIZE;
+				treeDrawing.x[subRoot] = (treeDrawing.x[root])-effectiveROOTSIZE;
+				placeSingletons(treeDrawing, tree, root);
+				if (treeDisplay.showBranchLengths) {
+					treeDisplay.nodeLocsParameters[totalHeight]=tree.tallestPathAboveNode(root, 1.0);
+					if (!treeDisplay.fixedScalingOn) {
+						treeDisplay.fixedDepthScale = treeDisplay.nodeLocsParameters[totalHeight];
+						fixedDepth = treeDisplay.fixedDepthScale;
+						if (treeDisplay.nodeLocsParameters[totalHeight]==0)
+							treeDisplay.nodeLocsParameters[scaling]=1;
+						else
+							treeDisplay.nodeLocsParameters[scaling]=((double)(rect.width-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.nodeLocsParameters[totalHeight]); 
+						RIGHTdoAdjustLengths(treeDisplay, treeDrawing, tree, effectiveROOTSIZE + buffer, root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+					else {
+						if (treeDisplay.fixedDepthScale == 0)
+							treeDisplay.fixedDepthScale = 1;
+						treeDisplay.nodeLocsParameters[scaling]=((double)(rect.width-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.fixedDepthScale); 
+						RIGHTdoAdjustLengths(treeDisplay, treeDrawing, tree, effectiveROOTSIZE+(int)(treeDisplay.nodeLocsParameters[scaling]*(treeDisplay.fixedDepthScale-treeDisplay.nodeLocsParameters[totalHeight]) + buffer), root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.fixedDepthScale, treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+
+					treeDrawing.y[subRoot] = (treeDrawing.y[root])-(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+					treeDrawing.x[subRoot] = (treeDrawing.x[root])-(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+				}
+				else {
+					if (even.getValue()){
+						int evenVertSpacing =(int)((-treeDrawing.x[subRoot] +edgeNode(treeDrawing, tree, root, true, true))/ (tree.mostStepsAboveNode(root) + 1));
+						if (evenVertSpacing > 0)
+							RIGHTevenNodeLocs(treeDrawing, tree, root, evenVertSpacing);
+					}
+					if (!inhibitStretch.getValue() && (treeDisplay.autoStretchIfNeeded && treeDrawing.x[subRoot]<0)) {
+						treeDisplay.nodeLocsParameters[stretchfactor]=((double)(rect.width-treeDisplay.getTipsMargin())) / (rect.width - treeDrawing.x[subRoot] -treeDisplay.getTipsMargin());
+						RIGHTstretchNodeLocs(treeDisplay,treeDrawing, tree, root,rect.width-treeDisplay.getTipsMargin());
+						treeDrawing.x[subRoot]=5;
+					}
+				}
+			}
+			else if (treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+				int numTerms = effectiveNumberOfTerminals(tree, root);
+				if (numTerms == 0)
+					numTerms = 1;
+				if (fixedTaxonDistance!=0 && MesquiteInteger.isCombinable(fixedTaxonDistance))
+					treeDisplay.setTaxonSpacing(fixedTaxonDistance);
+				else
+					treeDisplay.setTaxonSpacing( (rect.height - 30) / numTerms);
+				if (numTerms*treeDisplay.getTaxonSpacing()>.95*rect.height && treeDisplay.getTaxonSpacing()/2*2 != treeDisplay.getTaxonSpacing())  //if odd
+					treeDisplay.setTaxonSpacing(treeDisplay.getTaxonSpacing()-1);
+				lastleft = -treeDisplay.getTaxonSpacing()/3*2;
+				LEFTCalcTerminalLocs(treeDisplay, treeDrawing, tree, root,treeDisplay.getTipsMargin(), tree.getAssociatedBit(triangleNameRef, root), tree.numberOfTerminalsInClade(root), root);
+				LEFTCalcInternalLocs(treeDrawing, tree, root);
+				if (center.getValue())
+					RIGHTLEFTCenterInternalLocs(treeDrawing, tree, root);
+				//AdjustForUnbranchedNodes(root, subRoot);
+				treeDrawing.y[subRoot] = (treeDrawing.y[root])+effectiveROOTSIZE;
+				treeDrawing.x[subRoot] = (treeDrawing.x[root])+effectiveROOTSIZE;
+				placeSingletons(treeDrawing, tree, root);
+				if (treeDisplay.showBranchLengths) {
+					treeDisplay.nodeLocsParameters[totalHeight]=tree.tallestPathAboveNode(root, 1.0);
+					if (!treeDisplay.fixedScalingOn) {
+						treeDisplay.fixedDepthScale = treeDisplay.nodeLocsParameters[totalHeight];
+						fixedDepth = treeDisplay.fixedDepthScale;
+						if (treeDisplay.nodeLocsParameters[totalHeight]==0)
+							treeDisplay.nodeLocsParameters[scaling]=1;
+						else
+							treeDisplay.nodeLocsParameters[scaling]=((double)(rect.width-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.nodeLocsParameters[totalHeight]); 
+						LEFTdoAdjustLengths(treeDisplay, treeDrawing, tree, rect.width - effectiveROOTSIZE -buffer, root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+					else {
+						if (treeDisplay.fixedDepthScale == 0)
+							treeDisplay.fixedDepthScale = 1;
+						treeDisplay.nodeLocsParameters[scaling]=((double)(rect.width-treeDisplay.getTipsMargin()-buffer - effectiveROOTSIZE))/(treeDisplay.fixedDepthScale); 
+						LEFTdoAdjustLengths(treeDisplay, treeDrawing, tree, rect.width - effectiveROOTSIZE-(int)(treeDisplay.nodeLocsParameters[scaling]*(treeDisplay.fixedDepthScale-treeDisplay.nodeLocsParameters[totalHeight])+buffer), root, 0, root);
+						if (showScale.getValue())
+							drawGrid(treeDisplay.nodeLocsParameters[totalHeight], treeDisplay.fixedDepthScale, treeDisplay.nodeLocsParameters[scaling], tree, drawnRoot, treeDisplay, g);
+					}
+
+					treeDrawing.y[subRoot] = (treeDrawing.y[root])+(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+					treeDrawing.x[subRoot] = (treeDrawing.x[root])+(int)(getNonZeroBranchLength(tree, root)*treeDisplay.nodeLocsParameters[scaling]);
+				}
+				else {
+					if (even.getValue()){
+						int evenVertSpacing =(int)((treeDrawing.x[subRoot] - edgeNode(treeDrawing, tree, root, true, false))/ (tree.mostStepsAboveNode(root) + 1));
+						if (evenVertSpacing > 0)
+							LEFTevenNodeLocs(treeDrawing, tree, root, evenVertSpacing);
+					}
+					if (!inhibitStretch.getValue() && (treeDisplay.autoStretchIfNeeded && treeDrawing.x[subRoot]>rect.width)) {
+						treeDisplay.nodeLocsParameters[stretchfactor]=((double)(rect.width-treeDisplay.getTipsMargin())) / (treeDrawing.x[subRoot] - (int)treeDisplay.getTipsMargin());
+						LEFTstretchNodeLocs(treeDisplay, treeDrawing, tree, root);
+						treeDrawing.x[subRoot]=rect.width-5;
+					}
+				}
+			}
+			treeDisplay.scaling=treeDisplay.nodeLocsParameters[scaling];
+		}
+
+	}
+	private void drawString(Graphics g, String s, int x, int y){
+		if (g == null || StringUtil.blank(s))
+			return;
+		try {
+			g.drawString(s, x, y);
+		}
+		catch (Exception e){
+		}
+	}
+	/*.................................................................................................................*/
+	public void drawGrid(double totalTreeHeight, double totalScaleHeight, double scaling, Tree tree, int drawnRoot, TreeDisplay treeDisplay, Graphics g) {
+		if (g == null)
+			return;
+		boolean narrowScaleOnly = !broadScale.getValue();
+		boolean rulerOnly = false;
+		int rulerWidth = 8;
+		Color c=g.getColor();
+		g.setColor(Color.cyan);
+		int scaleBuffer = 28;
+		TreeDrawing treeDrawing = treeDisplay.getTreeDrawing();
+		int buffer = 8;
+		double log10 = Math.log(10.0);
+		double hundredthHeight = Math.exp(log10* ((int) (Math.log(totalScaleHeight)/log10)-1));
+		if (totalScaleHeight/hundredthHeight <20.0)
+			hundredthHeight /= 10.0;
+		int countTenths = 0;
+		double thisHeight = totalScaleHeight + hundredthHeight;
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+			double base = (totalScaleHeight-totalTreeHeight)*scaling +treeDisplay.getTreeDrawing().y[drawnRoot];
+			int leftEdge = treeDisplay.getTreeDrawing().x[tree.leftmostTerminalOfNode(drawnRoot)];
+
+			int rightEdge = treeDisplay.getTreeDrawing().x[tree.rightmostTerminalOfNode(drawnRoot)]+ scaleBuffer;
+			if (narrowScaleOnly)
+				leftEdge = rightEdge - 10;
+			while ( thisHeight>=0) {
+				if (countTenths % 10 == 0)
+					g.setColor(Color.blue);
+				else
+					g.setColor(Color.cyan);
+				thisHeight -= hundredthHeight;
+				if (rulerOnly)
+					g.drawLine(rightEdge-rulerWidth, (int)(base- (thisHeight*scaling)), rightEdge,  (int)(base- (thisHeight*scaling)));
+				else
+					g.drawLine(leftEdge, (int)(base- (thisHeight*scaling)), rightEdge,  (int)(base- (thisHeight*scaling)));
+				if (countTenths % 10 == 0)
+					drawString(g, MesquiteDouble.toStringInRange(totalScaleHeight - thisHeight, totalScaleHeight), rightEdge + buffer, (int)(base- (thisHeight*scaling)));
+
+				countTenths ++;
+			}
+			if (rulerOnly)
+				g.drawLine(rightEdge, (int)(base), rightEdge,  (int)(base- (totalScaleHeight*scaling)));
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+			int leftEdge = treeDisplay.getTreeDrawing().x[tree.leftmostTerminalOfNode(drawnRoot)];
+			int rightEdge = treeDisplay.getTreeDrawing().x[tree.rightmostTerminalOfNode(drawnRoot)]+ scaleBuffer;
+			if (narrowScaleOnly)
+				leftEdge = rightEdge - 10;
+			double base = treeDrawing.y[drawnRoot];
+			if (fixedScale)
+				base += (totalTreeHeight - fixedDepth)*scaling;
+			while ( thisHeight>=0) {
+				if (countTenths % 10 == 0)
+					g.setColor(Color.blue);
+				else
+					g.setColor(Color.cyan);
+				thisHeight -= hundredthHeight;
+				if (rulerOnly)
+					g.drawLine(rightEdge-rulerWidth, (int)(base+ (thisHeight*scaling)), rightEdge,  (int)(base+ (thisHeight*scaling)));
+				else
+					g.drawLine(leftEdge, (int)(base+ (thisHeight*scaling)), rightEdge,  (int)(base+ (thisHeight*scaling)));
+				if (countTenths % 10 == 0)
+					drawString(g, MesquiteDouble.toStringInRange(totalScaleHeight - thisHeight, totalScaleHeight), rightEdge + buffer, (int)(base+ (thisHeight*scaling)));
+				countTenths ++;
+			}
+			if (rulerOnly)
+				g.drawLine(rightEdge, (int)(base), rightEdge,  (int)(base+ (totalScaleHeight*scaling)));
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+			fm=g.getFontMetrics(g.getFont());
+			int textHeight = fm.getHeight();
+			int leftEdge = treeDisplay.getTreeDrawing().y[tree.leftmostTerminalOfNode(drawnRoot)];
+			int rightEdge = treeDisplay.getTreeDrawing().y[tree.rightmostTerminalOfNode(drawnRoot)]+ scaleBuffer;
+			if (narrowScaleOnly)
+				leftEdge = rightEdge - 10;
+
+			//if fixed then base is centered on root!
+			double base = (totalScaleHeight-totalTreeHeight)*scaling +treeDisplay.getTreeDrawing().x[drawnRoot];
+			while ( thisHeight>=0) {
+				if (countTenths % 10 == 0)
+					g.setColor(Color.blue);
+				else
+					g.setColor(Color.cyan);
+				thisHeight -= hundredthHeight;
+				if (rulerOnly)
+					g.drawLine((int)(base- (thisHeight*scaling)), rightEdge,  (int)(base- (thisHeight*scaling)),  rightEdge-rulerWidth);
+				else
+					g.drawLine((int)(base- (thisHeight*scaling)), rightEdge,  (int)(base- (thisHeight*scaling)),  leftEdge);
+				if (countTenths % 10 == 0)
+					drawString(g, MesquiteDouble.toStringInRange(totalScaleHeight - thisHeight, totalScaleHeight), (int)(base- (thisHeight*scaling)), rightEdge + buffer + textHeight);
+				countTenths ++;
+			}
+			if (rulerOnly)
+				g.drawLine((int)(base), rightEdge, (int)(base- (totalScaleHeight*scaling)),rightEdge);
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			fm=g.getFontMetrics(g.getFont());
+			int textHeight = fm.getHeight();
+			int leftEdge = treeDisplay.getTreeDrawing().y[tree.leftmostTerminalOfNode(drawnRoot)];
+			int rightEdge = treeDisplay.getTreeDrawing().y[tree.rightmostTerminalOfNode(drawnRoot)] + scaleBuffer;
+			if (narrowScaleOnly) {
+				leftEdge = rightEdge - 10;
+			}
+			double base = treeDrawing.x[drawnRoot];
+			if (fixedScale)
+				base += (totalTreeHeight - fixedDepth)*scaling;
+			while ( thisHeight>=0) {
+				if (countTenths % 10 == 0)
+					g.setColor(Color.blue);
+				else
+					g.setColor(Color.cyan);
+				thisHeight -= hundredthHeight;
+				if (rulerOnly)
+					g.drawLine((int)(base+ (thisHeight*scaling)), rightEdge-rulerWidth,  (int)(base+ (thisHeight*scaling)),  rightEdge);
+				else
+					g.drawLine((int)(base+ (thisHeight*scaling)), leftEdge,  (int)(base+ (thisHeight*scaling)),  rightEdge);
+				if (countTenths % 10 == 0)
+					drawString(g, MesquiteDouble.toStringInRange(totalScaleHeight - thisHeight, totalScaleHeight), (int)(base+ (thisHeight*scaling)), rightEdge + buffer + textHeight);
+				countTenths ++;
+			}
+			if (rulerOnly)
+				g.drawLine((int)(base), rightEdge, (int)(base+ (totalScaleHeight*scaling)),rightEdge);
+		}
+		if (c !=null)
+			g.setColor(c);
+		g.setPaintMode();
+	}
+
+	public int getFixedTaxonDistance() {
+		return fixedTaxonDistance;
+	}
+
+	public void setFixedTaxonDistance(int fixedTaxonDistance) {
+		this.fixedTaxonDistance = fixedTaxonDistance;
+	}
+}
+
+
+class NodeLocsExtra extends TreeDisplayBkgdExtra implements Commandable {
+	NodeLocsStandard locsModule;
+	TreeTool stretchTool;
+	MesquiteWindow window = null;
+	public NodeLocsExtra (NodeLocsStandard ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		locsModule = ownerModule;
+		/*
+		stretchTool = new TreeTool(this,  "cladeexpander", locsModule.getPath() , "expand.gif", 8,0,"Stretch clade", "This tool stretches larger a clade.");
+		stretchTool.setTouchedCommand(MesquiteModule.makeCommand("touchedCladeStretch",  this));
+		stretchTool.setDroppedCommand(MesquiteModule.makeCommand("droppedCladeStretch",  this));
+		MesquiteCommand dragCommand = MesquiteModule.makeCommand("draggedCladeStretch",  this);
+		stretchTool.setDraggedCommand(dragCommand);
+		stretchTool.setTouchedFieldCommand(MesquiteModule.makeCommand("fieldCladeStretch",  this));
+		dragCommand.setDontDuplicate(true);
+		if (locsModule.containerOfModule() instanceof MesquiteWindow) {
+			window = ((MesquiteWindow)locsModule.containerOfModule());
+			window.addTool(stretchTool);
+		}
+		*/
+	}
+	/*.................................................................................................................*/
+	public   String writeOnTree(Tree tree, int drawnRoot) {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (locsModule.showScale.getValue() && locsModule.showBranchLengths.getValue())
+			locsModule.drawGrid(treeDisplay.nodeLocsParameters[locsModule.totalHeight], treeDisplay.fixedDepthScale, treeDisplay.nodeLocsParameters[locsModule.scaling], tree, drawnRoot, treeDisplay, g);
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorEnterBranch(Tree tree, int N, Graphics g){
+		if (window == null || window.getCurrentTool() != stretchTool)
+			return;
+		drawCladeBox(N);
+			lastBranch = N;
+			lineOnMove = true;
+	}
+	/**to inform TreeDisplayExtra that cursor has just entered branch N*/
+	public void cursorExitBranch(Tree tree, int N, Graphics g){
+		if (window == null || window.getCurrentTool() != stretchTool)
+			return;
+			if (lineOnMove)
+				drawCladeBox(N);
+			lastBranch = -1;
+			lineOnMove = false;
+	}
+	int findBranch(Tree tree, int x, int y){
+		TreeDrawing drawing = treeDisplay.getTreeDrawing(); 
+		int drawnRoot = drawing.getDrawnRoot();
+		for (int ky = y; ky>= 0; ky--){
+			int b = drawing.findBranch(tree, drawnRoot, x, ky, null);
+			if (b>0)
+				return b;
+		}
+		return -1;
+	}
+	int lastBranch = -1;
+	/**to inform TreeDisplayExtra that cursor has just moved OUTSIDE of taxa or branches*/
+	public void cursorMove(Tree tree, int x, int y, Graphics g){
+		if (window == null || window.getCurrentTool() != stretchTool)
+			return;
+		if (lineOnMove && lastBranch>0)
+			drawCladeBox(lastBranch);
+		lineOnMove = false;
+	}
+	int originalX, originalY, lastX, lastY;
+	boolean lineOnTouch = false;
+	boolean lineOnMove = false;
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		MesquiteTree t=null; //
+		if (treeDisplay!=null) {
+			Tree trt = treeDisplay.getTree();
+			if (trt instanceof MesquiteTree)
+				t = (MesquiteTree)trt;
+			else
+				t = null;
+		}
+		if (window == null || window.getCurrentTool() != stretchTool)
+			return null;
+		if (checker.compare(this.getClass(), "Touch on branch to stretch it", "[branch number] [x coordinate touched] [y coordinate touched] [modifiers]", commandName, "touchedCladeStretch")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+			stretchTouched(node, x, y, mod);
+
+		}
+		else if (checker.compare(this.getClass(),  "Drop branch being stretched.", "[branch number] [x coordinate dropped] [y coordinate dropped] ", commandName, "droppedCladeStretch")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOnTouch) {
+				stretchDropped(t, node, x, y);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Drag branch being stretched.", "[branch number] [current x coordinate] [current y coordinate] ", commandName, "draggedCladeStretch")) {
+			if (t==null)
+				return null;
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			if (lineOnTouch) {
+				stretchDragged(t, node, x, y);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Touched Field.", "[current x coordinate] [current y coordinate] ", commandName, "fieldCladeStretch")) {
+			if (t==null)
+				return null;
+			locsModule.setZoom(treeDisplay,-1, 1.0);
+		}
+		return null;
+	}
+	int cladeTop = -1;
+	int cladeBottom = -1;
+	int cladeLeft = -1;
+	int cladeRight = -1;
+	int tempHeight = -1;
+	int tempLeft = -1;
+	int tempWidth = -1;
+	int touchX = -1;
+	int touchY = -1;
+
+	void drawCladeBox(int node){
+		TreeDrawing drawing =  treeDisplay.getTreeDrawing();
+		Tree tree = treeDisplay.getTree();
+		cladeTop = tallestNode(tree, drawing.getDrawnRoot(), drawing.x, drawing.y);
+		cladeBottom = drawing.y[node];
+		cladeLeft = drawing.x[tree.leftmostTerminalOfNode(node)];
+		cladeRight = drawing.x[tree.rightmostTerminalOfNode(node)];
+		tempHeight = cladeBottom - cladeTop;
+		tempLeft = cladeLeft;
+		tempWidth = cladeRight - cladeLeft;
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+			g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+			g.dispose();
+		}
+	}
+	int tallestNode(Tree tree, int node, int[] x, int[] y){
+		if (tree.nodeIsTerminal(node))
+			return y[node];
+		int tallest = MesquiteInteger.unassigned;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)){
+			int height = tallestNode(tree, d, x, y);
+			if (tallest == MesquiteInteger.unassigned || height < tallest)
+				tallest = height;
+		}
+		return tallest;
+	}
+	void stretchTouched(int node, int x, int y, String mod) {
+		MesquiteTree tree=null; //
+		if (treeDisplay!=null) {
+			Tree trt = treeDisplay.getTree();
+			if (trt instanceof MesquiteTree)
+				tree = (MesquiteTree)trt;
+		}
+		if (tree == null)
+			return;
+		touchX = x;
+		touchY = y;
+		TreeDrawing drawing =  treeDisplay.getTreeDrawing();
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+			if (lineOnTouch)
+				g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+			cladeTop = tallestNode(tree, drawing.getDrawnRoot(), drawing.x, drawing.y);
+			cladeBottom = drawing.y[node];
+			cladeLeft = drawing.x[tree.leftmostTerminalOfNode(node)];
+			cladeRight = drawing.x[tree.rightmostTerminalOfNode(node)];
+			tempHeight = cladeBottom - cladeTop;
+			tempLeft = cladeLeft;
+			tempWidth = cladeRight - cladeLeft;
+			tempZoomFactor = -1;
+				
+			g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+			g.dispose();
+		}
+		lineOnTouch=true;
+	}
+
+
+	void stretchDragged(Tree t, int node, int x, int y){
+		if (y== touchY || !lineOnTouch)
+			return;
+		MesquiteTree tree=null; //
+		if (treeDisplay!=null) {
+			Tree trt = treeDisplay.getTree();
+			if (trt instanceof MesquiteTree)
+				tree = (MesquiteTree)trt;
+		}
+		if (tree == null)
+			return;
+
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+			int oldHeight =(cladeBottom - cladeTop);
+			double expansionFactor = (oldHeight + (y - touchY))*1.0/oldHeight;
+			if (setTempZoom(treeDisplay, tree, node, expansionFactor)){
+			//	locsModule.setZoom(treeDisplay, node, expansionFactor);
+				g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+				tempHeight = (int)(oldHeight * expansionFactor);
+				int newWidth = (int)((cladeRight-cladeLeft) * expansionFactor);
+				tempLeft = cladeLeft - (newWidth-(cladeRight-cladeLeft))/2;
+				tempWidth = newWidth;
+				g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+				lineOnTouch = true;
+			}
+			g.dispose();
+		}
+	}
+	void stretchDropped(MesquiteTree t, int node, int x, int y){
+		if (y== touchY || !lineOnTouch)
+			return;
+
+		MesquiteTree tree=null; //
+		if (treeDisplay!=null) {
+			Tree trt = treeDisplay.getTree();
+			if (trt instanceof MesquiteTree)
+				tree = (MesquiteTree)trt;
+		}
+		if (tree == null)
+			return;
+
+		if (GraphicsUtil.useXORMode(null, false)){
+			Graphics g = treeDisplay.getGraphics();
+			g.setXORMode(Color.white);
+			g.setColor(Color.red);
+			g.drawRect(tempLeft, cladeTop, tempWidth, tempHeight);
+			g.dispose();
+		}
+
+		if (tempZoomFactor>=0){
+			locsModule.setZoom(treeDisplay,node, tempZoomFactor);
+		}
+		lineOnTouch = false;
+	}
+
+	double tempZoomFactor = 1.0;
+	/*.................................................................................................................*/
+	boolean setTempZoom(TreeDisplay treeDisplay, Tree tree, int zoomNode, double proposedChange){
+		int baseSpacing =treeDisplay.getTaxonSpacing();
+		int inZoom = tree.numberOfTerminalsInClade(zoomNode);
+		int outZoom = tree.numberOfTerminalsInClade(treeDisplay.getTreeDrawing().getDrawnRoot()) - inZoom;
+		double totalFactor = proposedChange;
+		if (locsModule.zoomNode == zoomNode || tree.descendantOf(zoomNode, locsModule.zoomNode))
+			totalFactor= locsModule.zoomFactor * proposedChange;
+		if ( (int)(baseSpacing *totalFactor)>0 && (int)(baseSpacing * (1 - (totalFactor-1)*inZoom/outZoom))>0){
+			tempZoomFactor = totalFactor;
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*
+	boolean setTempZoom(TreeDisplay treeDisplay, Tree tree, int zoomNode, double proposedChange){
+		int baseSpacing =treeDisplay.getTaxonSpacing();
+		int inZoom = tree.numberOfTerminalsInClade(zoomNode);
+		int outZoom = tree.numberOfTerminalsInClade(treeDisplay.getTreeDrawing().getDrawnRoot()) - inZoom;
+		double totalFactor = proposedChange;
+		if (locsModule.zoomNode == zoomNode || tree.descendantOf(zoomNode, locsModule.zoomNode))
+			totalFactor= locsModule.zoomFactor * proposedChange;
+		if ( (int)(baseSpacing *totalFactor)>0 && (int)(baseSpacing * (1 - (totalFactor-1)*inZoom/outZoom))>0){
+			tempZoomFactor = totalFactor;
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void turnOff(){
+		super.turnOff();
+		if (window != null)
+			window.removeTool(stretchTool);
+	}
+}
+
+
+
diff --git a/Source/mesquite/trees/NodeLocsStandard/expand.gif b/Source/mesquite/trees/NodeLocsStandard/expand.gif
new file mode 100644
index 0000000..d0ab22d
Binary files /dev/null and b/Source/mesquite/trees/NodeLocsStandard/expand.gif differ
diff --git a/Source/mesquite/trees/NodeNamer/32nodeNamer.gif b/Source/mesquite/trees/NodeNamer/32nodeNamer.gif
new file mode 100644
index 0000000..9d67ddd
Binary files /dev/null and b/Source/mesquite/trees/NodeNamer/32nodeNamer.gif differ
diff --git a/Source/mesquite/trees/NodeNamer/64nodeNamer.gif b/Source/mesquite/trees/NodeNamer/64nodeNamer.gif
new file mode 100644
index 0000000..87e3ae6
Binary files /dev/null and b/Source/mesquite/trees/NodeNamer/64nodeNamer.gif differ
diff --git a/Source/mesquite/trees/NodeNamer/NodeNamer.java b/Source/mesquite/trees/NodeNamer/NodeNamer.java
new file mode 100644
index 0000000..98c56e8
--- /dev/null
+++ b/Source/mesquite/trees/NodeNamer/NodeNamer.java
@@ -0,0 +1,248 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NodeNamer;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NodeNamer extends TreeDisplayAssistantI {
+	public Vector extras;
+	public String getFunctionIconPath(){
+		return getPath() + "nodeNamer.gif";
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		NodeNamerExtra newPj = new NodeNamerExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	void sendTreeCommands(String command, String arguments){
+		Enumeration e = extras.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			NodeNamerExtra tCO = (NodeNamerExtra)obj;
+			tCO.doTreeCommand(command, arguments);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Node Namer";
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool to name the nodes of a tree";
+	}
+
+}
+
+/* ======================================================================== */
+class NodeNamerExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool adjustTool;
+	MesquiteMenuItemSpec hideMenuItem = null;
+	NodeNamer selectModule;
+	Tree tree;
+	int originalX, originalY, lastX, lastY;
+	boolean lineOn = true;
+	MiniStringEditor miniEditor;
+	double lastBL;	
+	boolean editorOn = false;
+	int editorNode = -1;
+	boolean dragMode = false; //default mode - if true,then drags branch to extend; needs modifier keys for editor; if false, opposite
+
+	public NodeNamerExtra (NodeNamer ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		selectModule = ownerModule;
+		adjustTool = new TreeTool(this,  "nodeNamer", ownerModule.getPath() , "nodeNamer.gif", 1,0,"Name nodes", "This tool can be used to give names to clades. When a branch is touched, a small text editing box appears in which a new name can be entered; touching the little blue button enters it." );
+		adjustTool.setTouchedCommand(MesquiteModule.makeCommand("touchedNamer",  this));
+		adjustTool.setTouchedTaxonCommand(MesquiteModule.makeCommand("touchedTaxonNamer",  this));
+		//adjustTool.setDroppedCommand(MesquiteModule.makeCommand("droppedNamer",  this));
+		//adjustTool.setDraggedCommand(MesquiteModule.makeCommand("draggedNamer",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(adjustTool);
+		}
+	}
+	public void doTreeCommand(String command, String arguments){
+		Tree tree = treeDisplay.getTree();
+		if (tree instanceof Commandable && tree!=null)
+			((Commandable)tree).doCommand(command, arguments, CommandChecker.defaultChecker);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		this.tree = tree;
+		if (editorOn) {
+			if (tree.nodeExists(editorNode))
+				miniEditor.setLocation(treeDisplay.getTreeDrawing().x[editorNode], treeDisplay.getTreeDrawing().y[editorNode]);
+			else hideMiniEditor();
+		}
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+	}
+
+	private void setMiniEditor(int node, int x,int y){
+		Tree t = treeDisplay.getTree();
+		if (t==null)
+			return;
+		editorNode = node;
+		if (miniEditor == null) {
+			miniEditor = new MiniStringEditor(ownerModule, ownerModule.makeCommand("acceptName", this));
+			treeDisplay.addPanelPlease(miniEditor);
+		}
+		miniEditor.setLocation(treeDisplay.getTreeDrawing().x[node], treeDisplay.getTreeDrawing().y[node]);
+		String lab = t.getNodeLabel(node);
+		if (lab == null)
+			lab = "";
+		miniEditor.setText(lab);
+		miniEditor.setVisible(true);
+		editorOn = true;
+	}
+	private void hideMiniEditor(){
+		miniEditor.setVisible(false);
+		editorOn = false;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		Tree trt = treeDisplay.getTree();
+		MesquiteTree t = null;
+		if (trt instanceof MesquiteTree)
+			t = (MesquiteTree)trt;
+
+		if (checker.compare(this.getClass(), "Assigns the given name to the current node", "[name of node]", commandName, "acceptName")){
+			if (t==null)
+				return null;
+			if (editorOn) {
+				if (t.nodeIsTerminal(editorNode)){
+					if (arguments!=null) {
+
+						int n = t.nodeOfLabel(arguments, true);
+						if (n<0) {
+							n = t.getTaxa().whichTaxonNumber(arguments, false);
+							n = t.nodeOfTaxonNumber(n);
+						}
+						if (n!=editorNode && t.nodeExists(n)) // node with that label already exists
+							if (!AlertDialog.query(ownerModule.containerOfModule(), "Name already exists", "That name already exists for some other node or terminal taxon.  Assigning the label to this terminal taxon may cause the tree to be misinterpreted if later re-read from a file.  Continue?"))
+								return null;
+
+						Taxa taxa = t.getTaxa();
+						int it = t.taxonNumberOfNode(editorNode);
+						if (it>=0) {
+							taxa.setTaxonName(it, arguments);
+							taxa.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+						}
+					}
+				}
+				else {
+					String lab = t.getNodeLabel(editorNode);
+					if (arguments == null	 && lab == null) { //both null
+						hideMiniEditor();
+						return null;
+					}
+					if (arguments != null && arguments.equals(lab)) { //same as before
+						hideMiniEditor();
+						return null;
+					}
+					if (!MesquiteTree.cosmeticInternalNames){
+						int n = t.nodeOfLabel(arguments, true);
+						if (n<0) {
+							n = t.getTaxa().whichTaxonNumber(arguments, false);
+							n = t.nodeOfTaxonNumber(n);
+						}
+						if (n!=editorNode && t.nodeExists(n)) // node with that label already exists
+							if (!AlertDialog.query(ownerModule.containerOfModule(), "Name already exists", "That name already exists for some other node or terminal taxon.  Assigning the label to this node may cause the tree to be interpreted as reticulate if later re-read from a file.  Continue?"))
+								return null;
+					}
+					t.setNodeLabel(arguments, editorNode);
+					if (arguments != null){
+						Clade c = t.getTaxa().getClades().findClade(arguments);
+						if (c==null)
+							t.getTaxa().getClades().addClade(arguments);
+					}
+					t.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED));
+					treeDisplay.pleaseUpdate(false);
+				}
+			}
+			hideMiniEditor();
+		}
+		else if (checker.compare(this.getClass(), "Indicates the node name tool touched on a branch", "[branch number] [x coordinate] [y coordinate] [modifiers]", commandName, "touchedNamer")) {
+			if (t==null)
+				return null;
+			if (miniEditor!=null)
+				miniEditor.setText("");
+			MesquiteInteger io = new MesquiteInteger(0);
+			int node= MesquiteInteger.fromString(arguments, io);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+
+			if (t.nodeExists(node)){
+				ownerModule.logln("Node " + node + " touched on to rename.");
+				setMiniEditor(node, x,y);
+			}
+			else 
+				ownerModule.logln("Node " + node + " touched on to rename, but node not in tree.");
+
+		}
+		else if (checker.compare(this.getClass(), "Indicates the node name tool touched on a terminal taxon name", "[taxon] [x coordinate] [y coordinate] [modifiers]", commandName, "touchedTaxonNamer")) {
+			if (t==null)
+				return null;
+			if (miniEditor!=null)
+				miniEditor.setText("");
+
+			MesquiteInteger io = new MesquiteInteger(0);
+			int taxon= MesquiteInteger.fromString(arguments, io);
+			int node = t.nodeOfTaxonNumber(taxon);
+			int x= MesquiteInteger.fromString(arguments, io);
+			int y= MesquiteInteger.fromString(arguments, io);
+			String mod= ParseUtil.getRemaining(arguments, io);
+
+			if (t.nodeExists(node)){
+				ownerModule.logln("Node " + node + " touched on to rename.");
+				setMiniEditor(node, x,y);
+			}
+			else 
+				ownerModule.logln("Node " + node + " touched on to rename, but node not in tree.");
+		}
+		return null;
+	}
+	public void turnOff() {
+
+		selectModule.extras.removeElement(this);
+		if (miniEditor != null)
+			treeDisplay.removePanelPlease(miniEditor);
+		super.turnOff();
+	}
+}
+
+
+
diff --git a/Source/mesquite/trees/NodeNamer/nodeNamer.gif b/Source/mesquite/trees/NodeNamer/nodeNamer.gif
new file mode 100644
index 0000000..842f935
Binary files /dev/null and b/Source/mesquite/trees/NodeNamer/nodeNamer.gif differ
diff --git a/Source/mesquite/trees/NumAttachedToTree/NumAttachedToTree.java b/Source/mesquite/trees/NumAttachedToTree/NumAttachedToTree.java
new file mode 100644
index 0000000..30af289
--- /dev/null
+++ b/Source/mesquite/trees/NumAttachedToTree/NumAttachedToTree.java
@@ -0,0 +1,167 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumAttachedToTree;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* 
+ * Walks a Mesquite tree and calculates the number of taxa in it.
+ */
+
+public class NumAttachedToTree extends NumberForTree {
+
+	String nameOfAttached = null;
+	ListableVector names = new ListableVector();
+	/* ................................................................................................................. */
+	/** Explains what the module does. */
+
+	public String getExplanation() {
+		return "Supplies a number attached to the tree";
+	}
+
+	/* ................................................................................................................. */
+	/** Name of module */
+	public String getName() {
+		if (nameOfAttached !=null)
+			return nameOfAttached;
+		return "Attached Value";
+	}
+	/* ................................................................................................................. */
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addMenuItem( "Value Attached to Trees...", makeCommand("setNameOfAttached",  this));
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNameOfAttached " + ParseUtil.tokenize(nameOfAttached)); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the name of the attached numbers to be used", "[name of attached]", commandName, "setNameOfAttached")) {
+			String name= parser.getFirstToken(arguments);
+			if (StringUtil.blank(name)){
+				Listable L = ListDialog.queryList(containerOfModule(), "Attached number", "Which attached number to show? (This list may change as other tree sources are used or trees are read.)", MesquiteString.helpString, names, 0);
+				if (L!=null)
+					name = L.getName();
+			}
+			if (!StringUtil.blank(name)) {
+				nameOfAttached = name;
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+
+	void reviewAttachmentsAvailable(Tree tree){
+		if (tree !=null && tree instanceof Attachable){
+			Vector at = ((Attachable)tree).getAttachments();
+			if (at !=null) {
+				for (int i =0; i < at.size(); i++){
+					Object obj = at.elementAt(i);
+					if (obj instanceof MesquiteDouble || obj instanceof MesquiteNumber  || obj instanceof MesquiteInteger   || obj instanceof MesquiteLong) {
+						String name = ((Listable)obj).getName();
+						if (names.indexOfByNameIgnoreCase(name)<0) {
+							MesquiteString ms = new MesquiteString(name);
+							ms.setName(name);
+							names.addElement(ms, false);
+						}
+					}
+				}
+			}
+		}
+
+	}
+	Object getFirstAttachment(Tree tree){
+		if (tree !=null && tree instanceof Attachable){
+			Vector at = ((Attachable)tree).getAttachments();
+			if (at !=null) {
+				for (int i =0; i < at.size(); i++){
+					Object obj = at.elementAt(i);
+					if (obj instanceof MesquiteDouble || obj instanceof MesquiteNumber  || obj instanceof MesquiteInteger  || obj instanceof MesquiteLong) {
+						nameOfAttached = ((Listable)obj).getName();
+						return obj;
+					}
+				}
+			}
+		}
+		return null;
+
+	}
+	/* ................................................................................................................. */
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		if (result == null || tree == null)
+			return;
+		clearResultAndLastResult(result);
+		reviewAttachmentsAvailable(tree);
+		if (tree instanceof Attachable){
+			Object obj = null;
+			if (nameOfAttached != null)
+				obj = ((Attachable)tree).getAttachment(nameOfAttached);
+			else
+				obj = getFirstAttachment(tree); //also sets nameOfAttached
+			if (obj == null){
+				if (resultString != null)
+					resultString.setValue("No attachment is associated with this tree.");
+				return;
+			}
+
+			if (obj instanceof MesquiteDouble)
+				result.setValue(((MesquiteDouble)obj).getValue());
+			else if (obj instanceof MesquiteNumber)
+				result.setValue((MesquiteNumber)obj);
+			else if (obj instanceof MesquiteInteger)
+				result.setValue(((MesquiteInteger)obj).getValue());
+			else if (obj instanceof MesquiteLong)
+				result.setValue(((MesquiteLong)obj).getValue());
+			/*else if (obj instanceof MesquiteString) {
+				String s = (((MesquiteString)obj).getValue());
+				int value = MesquiteInteger.fromString(s);
+				if (MesquiteInteger.isCombinable(value))
+					result.setValue(value);
+			}*/
+		}
+
+		if (resultString != null) {
+			resultString.setValue(nameOfAttached + " : " + result.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 272;  
+	}
+}
diff --git a/Source/mesquite/trees/NumFor2CharCurrentTree/NumFor2CharCurrentTree.java b/Source/mesquite/trees/NumFor2CharCurrentTree/NumFor2CharCurrentTree.java
new file mode 100644
index 0000000..f9ae112
--- /dev/null
+++ b/Source/mesquite/trees/NumFor2CharCurrentTree/NumFor2CharCurrentTree.java
@@ -0,0 +1,180 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumFor2CharCurrentTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumFor2CharCurrentTree extends NumberFor2Characters  {
+	public String getName() {
+		return "Value for 2 characters with current tree";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "2 Character value (current tree)";
+		else
+			return numberTask.getVeryShortName() + " (current tree)";
+	}
+	public String getNameForMenuItem() {
+		return "Value for 2 characters with current tree...";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for two characters based on a current tree." ;
+	}	
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2CharAndTree.class, getName() + "  needs a method to calculate the value for two characters using the tree.",
+		"The method to calculate values can be selected initially or in the Values submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source for a current tree.",
+		"The source for a current tree is arranged initially");
+	}
+	/*.................................................................................................................*/
+	NumberFor2CharAndTree numberTask;
+	OneTreeSource treeTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of current tree");
+		if (treeTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		numberTask = (NumberFor2CharAndTree)hireEmployee(NumberFor2CharAndTree.class, "Value to calculate for two characters on current tree");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberFor2CharAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberFor2CharAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+
+		return true;
+	}
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumberFor2CharAndTree temp =  (NumberFor2CharAndTree)replaceEmployee(NumberFor2CharAndTree.class, arguments, "Number for 2 characters and tree", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates1, CharacterDistribution charStates2){
+		if (charStates1 == null)
+			return;
+		CharacterData data = charStates1.getParentData();
+		if (data!=null) {
+			taxa = data.getTaxa();
+			treeTask.initialize(taxa);
+			numberTask.initialize(treeTask.getTree(taxa), charStates1, charStates2);
+		}
+
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates1, CharacterDistribution charStates2, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(charStates1, charStates2);
+		}
+		tree = treeTask.getTree(taxa);
+		rs.setValue("");
+		numberTask.calculateNumber(tree, charStates1, charStates2, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For current tree, ");
+			resultString.append(rs.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==treeTask || employee==numberTask) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (tree ==null)
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (tree ==null)
+			return numberTask.getName() + " with current tree"; //of which tree??
+		else
+			return numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+	/*.................................................................................................................*/
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForCharCurrentTree/NumForCharCurrentTree.java b/Source/mesquite/trees/NumForCharCurrentTree/NumForCharCurrentTree.java
new file mode 100644
index 0000000..938b7b5
--- /dev/null
+++ b/Source/mesquite/trees/NumForCharCurrentTree/NumForCharCurrentTree.java
@@ -0,0 +1,192 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForCharCurrentTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForCharCurrentTree extends NumberForCharacter implements NumForCharTreeDep {
+	public String getName() {
+		return "Character value with current tree";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Character value with current tree";
+		else
+			return numberTask.getVeryShortName() + " (current tree)";
+	}
+	public String getNameForMenuItem() {
+		return "Character value with current tree...";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a character based on a current tree." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharAndTree.class, getName() + "  needs a method to calculate the value for a character using the tree.",
+		"The method to calculate values can be selected initially or in the Values submenu");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source for a current tree.",
+		"The source for a current tree is arranged initially");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberForCharAndTree.class;
+	}
+	/*.................................................................................................................*/
+	NumberForCharAndTree numberTask;
+	OneTreeSource treeTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of current tree");
+		if (treeTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		if (arguments !=null) {
+			numberTask = (NumberForCharAndTree)hireNamedEmployee(NumberForCharAndTree.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+		numberTask = (NumberForCharAndTree)hireEmployee(NumberForCharAndTree.class, "Value to calculate for character");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberForCharAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values (for char. on tree)", ntC, NumberForCharAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+
+		return true;
+	}
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumberForCharAndTree temp =  (NumberForCharAndTree)replaceEmployee(NumberForCharAndTree.class, arguments, "Number for character and tree", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+		if (charStates == null)
+			return;
+		CharacterData data = charStates.getParentData();
+		if (data!=null) {
+			taxa = data.getTaxa();
+			treeTask.initialize(taxa);
+			numberTask.initialize(treeTask.getTree(taxa), charStates);
+		}
+
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(charStates);
+		}
+		tree = treeTask.getTree(taxa);
+		rs.setValue("");
+		numberTask.calculateNumber(tree, charStates, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For current tree, ");
+			resultString.append(rs.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==treeTask) {
+			parametersChanged(notification);
+		}
+		else if (employee==numberTask) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (tree ==null)
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (tree ==null)
+			return numberTask.getName() + " with current tree"; //of which tree??
+		else
+			return numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForCharOnTree/NumForCharOnTree.java b/Source/mesquite/trees/NumForCharOnTree/NumForCharOnTree.java
new file mode 100644
index 0000000..c331898
--- /dev/null
+++ b/Source/mesquite/trees/NumForCharOnTree/NumForCharOnTree.java
@@ -0,0 +1,226 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForCharOnTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForCharOnTree extends NumberForCharacter implements NumberForCharacterIncr, NumForCharTreeDep {
+	public String getName() {
+		return "Character value with tree";
+	}
+	public String getNameForMenuItem() {
+		return "Character value with tree...";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Character value with tree";
+		else
+			return numberTask.getVeryShortName() + " (with tree)";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a character based on a tree." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharAndTree.class, getName() + "  needs a method to calculate the value for a character using the trees.",
+		"The method to calculate values can be selected initially or in the Values submenu");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source for trees.",
+		"The source for trees can be requested initially or using the Tree Source submenu");
+		//e2.setDivertChainMessage("testing");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberForCharAndTree.class;
+	}
+	/*.................................................................................................................*/
+	NumberForCharAndTree numberTask;
+	TreeSource treeTask;
+	Taxa taxa;
+	Tree tree;
+	int currentTree = 0;
+	MesquiteString treeSourceName;
+	MesquiteCommand tsC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for Character Value)");
+		if (treeTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		treeSourceName = new MesquiteString(treeTask.getName());
+		tsC = makeCommand("setTreeSource",  this);
+		treeTask.setHiringCommand(tsC);
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tsC);
+			mss.setSelected(treeSourceName);
+			mss.setList(TreeSource.class);
+		}
+		if (arguments !=null) {
+			numberTask = (NumberForCharAndTree)hireNamedEmployee(NumberForCharAndTree.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumberForCharAndTree)hireEmployee(NumberForCharAndTree.class, "Value to calculate for character");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		if (getHiredAs() == NumberForCharacter.class){ //not hired as incrementable; offer menu item to change
+			addMenuItem( "Choose tree...", makeCommand("chooseTree",  this));
+		}
+		return true;
+	}
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee != treeTask || Notification.getCode(notification) != MesquiteListener.SELECTION_CHANGED)
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("setTreeSource " , treeTask);
+		if (getHiredAs() == NumberForCharacter.class){ //not hired as incrementable; offer menu item to change
+			temp.addLine("setTreeNumber " + currentTree);
+		}
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the source of trees", "[name of tree source module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees (for Character Value)", treeTask);
+			if (temp !=null){
+				treeTask = temp;
+				treeTask.setPreferredTaxa(taxa);
+				treeTask.setHiringCommand(tsC);
+				treeSourceName.setValue(treeTask.getName());
+				parametersChanged();
+				return treeTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Present a dialog box to choose a tree from the current tree source", null, commandName, "chooseTree")) {
+			int ic=treeTask.queryUserChoose(taxa, "for " + getName());
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentTree = ic;
+				parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets the tree to be the i'th one from the current tree source", "[number of tree to be used]", commandName, "setTreeNumber")) {
+			int ic = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentTree = ic;
+				parametersChanged();
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+		if (charStates == null)
+			return;
+		CharacterData data = charStates.getParentData();
+		if (data!=null) {
+			taxa = data.getTaxa();
+			treeTask.initialize(taxa);
+			numberTask.initialize(treeTask.getTree(taxa, 0), charStates);
+		}
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+
+	}
+	public void setCurrent(long i){
+		if (treeTask==null || taxa==null){
+			currentTree = (int)i;
+		}
+		else if ((i>=0) && (i<treeTask.getNumberOfTrees(taxa))) {
+			currentTree = (int)i;
+		}
+	}
+	public long getCurrent(){
+		return currentTree;
+	}
+	public long getMin(){
+		return 0;
+	}
+	public long getMax(){
+		if (taxa==null)
+			return 0;
+		else
+			return treeTask.getNumberOfTrees(taxa);
+	}
+	public String getItemTypeName(){
+		return "Tree";
+	}
+	public long toInternal(long i){
+		return MesquiteTree.toInternal((int)i);
+	}
+	public long toExternal(long i){
+		return MesquiteTree.toExternal((int)i);
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(charStates);
+		}
+		tree = treeTask.getTree(taxa, currentTree);
+		rs.setValue("");
+		numberTask.calculateNumber(tree, charStates, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For tree " + tree.getName() + ", ");
+			resultString.append(rs.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (tree ==null)
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForCharRespTree/NumForCharRespTree.java b/Source/mesquite/trees/NumForCharRespTree/NumForCharRespTree.java
new file mode 100644
index 0000000..9b32133
--- /dev/null
+++ b/Source/mesquite/trees/NumForCharRespTree/NumForCharRespTree.java
@@ -0,0 +1,174 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForCharRespTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForCharRespTree extends NumberForCharacter {
+	public String getName() {
+		return "Character Value with Respective Tree";
+	}
+	public String getNameForMenuItem() {
+		return "Character Value with Respective Tree...";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Char. value with respective tree";
+		else
+			return numberTask.getVeryShortName() + " (with tree)";
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 200;  
+	}
+
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a character based on a respective tree." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharAndTree.class, getName() + "  needs a method to calculate the value for a character using the trees.",
+		"The method to calculate values can be selected initially or in the Values submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source for trees.",
+		"The source for trees can be requested initially or using the Tree Source submenu");
+		//e2.setDivertChainMessage("testing");
+	}
+	/*.................................................................................................................*/
+	NumberForCharAndTree numberTask;
+	TreeSource treeTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString treeSourceName;
+	MesquiteCommand tsC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeTask = (TreeSource)hireEmployee(TreeSource.class, "Source of trees (for Character Value)");
+		if (treeTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained");
+		treeSourceName = new MesquiteString(treeTask.getName());
+		tsC = makeCommand("setTreeSource",  this);
+		treeTask.setHiringCommand(tsC);
+		if (numModulesAvailable(TreeSource.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Source", tsC);
+			mss.setSelected(treeSourceName);
+			mss.setList(TreeSource.class);
+		}
+		numberTask = (NumberForCharAndTree)hireEmployee(NumberForCharAndTree.class, "Value to calculate for character");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+
+		return true;
+	}
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		temp.addLine("setTreeSource " , treeTask);
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the source of trees", "[name of tree source module]", commandName, "setTreeSource")) {
+			TreeSource temp = (TreeSource)replaceEmployee(TreeSource.class, arguments, "Source of trees (for Character Value)", treeTask);
+			if (temp !=null){
+				treeTask = temp;
+				treeTask.setPreferredTaxa(taxa);
+				treeTask.setHiringCommand(tsC);
+				treeSourceName.setValue(treeTask.getName());
+				parametersChanged();
+				return treeTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(CharacterDistribution charStates){
+		if (charStates == null)
+			return;
+		CharacterData data = charStates.getParentData();
+		if (data!=null) {
+			taxa = data.getTaxa();
+			treeTask.initialize(taxa);
+			numberTask.initialize(treeTask.getTree(taxa, 0), charStates);
+		}
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(CharacterDistribution charStates, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(charStates);
+		}
+		int currentTree = charStates.getParentCharacter();
+		tree = treeTask.getTree(taxa, currentTree);
+		rs.setValue("");
+		if (tree != null){
+			numberTask.calculateNumber(tree, charStates, result, rs);
+			if (resultString!=null) {
+				resultString.setValue("For tree " + tree.getName() + ", ");
+				resultString.append(rs.toString());
+			}
+		}
+		else if (resultString != null){
+			resultString.setValue("No Tree");
+		}
+		
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (tree ==null)
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForMatCurrentTree/NumForMatCurrentTree.java b/Source/mesquite/trees/NumForMatCurrentTree/NumForMatCurrentTree.java
new file mode 100644
index 0000000..d104029
--- /dev/null
+++ b/Source/mesquite/trees/NumForMatCurrentTree/NumForMatCurrentTree.java
@@ -0,0 +1,187 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForMatCurrentTree;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForMatCurrentTree extends NumberForMatrix { // implements NumForCharTreeDep {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForMatrixAndTree.class, getName() + "  needs a method to calculate the value for a matrix using the current tree.",
+		"The method to calculate values can be selected initially or in the Values submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(TreeSource.class, getName() + "  needs a source of the current tree.",
+		"The source of a current tree is arranged initially");
+		//e2.setDivertChainMessage("testing");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberForMatrixAndTree.class;
+	}
+	/*.................................................................................................................*/
+	NumberForMatrixAndTree numberTask;
+	OneTreeSource treeTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		treeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of current tree");
+		if (treeTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		if (arguments !=null) {
+			numberTask = (NumberForMatrixAndTree)hireNamedEmployee(NumberForMatrixAndTree.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumberForMatrixAndTree)hireEmployee(NumberForMatrixAndTree.class, "Value to calculate for character matrix");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberForMatrixAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values with current tree", ntC, NumberForMatrixAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+
+		return true;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  //note: not snapshotting current tree task
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==treeTask) {
+			parametersChanged(notification);
+		}
+		else if (employee==numberTask) {
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for matrices with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumberForMatrixAndTree temp =  (NumberForMatrixAndTree)replaceEmployee(NumberForMatrixAndTree.class, arguments, "Number for matrix and tree", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(MCharactersDistribution data){
+		if (data!=null) {
+			taxa = data.getTaxa();
+			treeTask.initialize(taxa);
+			numberTask.initialize(treeTask.getTree(taxa), data);
+		}
+
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public  void calculateNumber(MCharactersDistribution data, MesquiteNumber result, MesquiteString resultString) {
+		if (result==null)
+			return;
+		clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(data);
+		}
+		tree = treeTask.getTree(taxa);
+		rs.setValue("");
+		numberTask.calculateNumber(tree, data, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For current tree, ");
+			resultString.append(rs.toString());
+		}
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (tree ==null)
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with tree \"" + tree.getName() + "\""; 
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Matrix value with current tree";
+	}
+	/*.................................................................................................................*/
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Matrix value with current tree";
+		else
+			return numberTask.getVeryShortName() + " (current tree)";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Matrix value with current tree...";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a character matrix based on a current tree." ;
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForNodesWithChar/NumForNodesWithChar.java b/Source/mesquite/trees/NumForNodesWithChar/NumForNodesWithChar.java
new file mode 100644
index 0000000..0e40eea
--- /dev/null
+++ b/Source/mesquite/trees/NumForNodesWithChar/NumForNodesWithChar.java
@@ -0,0 +1,198 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForNodesWithChar;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.*/
+
+public class NumForNodesWithChar extends NumbersForNodes {
+	public String getName() {
+		return "Number for Nodes using Character";
+	}
+	public String getExplanation() {
+		return "Supplies numbers, based on a character, for each node of a tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"");
+	}
+	/*.................................................................................................................*/
+	CharSourceCoordObed characterSourceTask;
+	private NumbersForNodesAndChar numAndCharTask;
+	Object dataCondition;
+	Taxa taxa;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+
+	int currentChar = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		numAndCharTask = (NumbersForNodesAndChar)hireCompatibleEmployee(NumbersForNodesAndChar.class, getCharacterClass(), "Calculator (for " + getName() + ")");
+		if (numAndCharTask == null)
+			return sorry(getName() + " couldn't start because no calculator (for " + getName() + ") was obtained");
+		//assume hired as NumbersForNodes; thus responsible for getting characters
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numAndCharTask.getCompatibilityTest(), "Source of characters (for " + numAndCharTask.getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		ntC =makeCommand("setNumberTask",  this);
+		numAndCharTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numAndCharTask.getName());
+		if (numModulesAvailable(NumberForCharAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values (for nodes with char.)", ntC, NumberForCharAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+		addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		addMenuItem( "-", null);
+
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Class getCharacterClass() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ", characterSourceTask); 
+		temp.addLine("setNumNodesSource ", numAndCharTask); 
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module supplying matrices", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying numbers", null, commandName, "setNumNodesSource")) {
+			NumbersForNodesAndChar temp =  (NumbersForNodesAndChar)replaceEmployee(NumbersForNodesAndChar.class, arguments, "Number for nodes", numAndCharTask);
+			if (temp!=null) {
+				numAndCharTask = temp;
+				numAndCharTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numAndCharTask.getName());
+				parametersChanged();
+				return numAndCharTask;
+			}
+			return numAndCharTask;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+			if (currentChar>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentChar--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentChar = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		CharacterDistribution observedStates = characterSourceTask.getCharacter(tree, currentChar);
+		numAndCharTask.calculateNumbers(tree, observedStates, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree == null)
+			return;
+		taxa = tree.getTaxa();
+		if (characterSourceTask!=null) {
+			characterSourceTask.initialize(tree.getTaxa());
+		}
+	}
+
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Calculator: " + numAndCharTask.getName() ; 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		return numAndCharTask.getName(); 
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == characterSourceTask || employee == numAndCharTask)  
+			iQuit();
+		super.employeeQuit(employee);
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
diff --git a/Source/mesquite/trees/NumForNodesWithCharHist/NumForNodesWithCharHist.java b/Source/mesquite/trees/NumForNodesWithCharHist/NumForNodesWithCharHist.java
new file mode 100644
index 0000000..ba18c57
--- /dev/null
+++ b/Source/mesquite/trees/NumForNodesWithCharHist/NumForNodesWithCharHist.java
@@ -0,0 +1,123 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForNodesWithCharHist;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**Suppliies numbers for each node of a tree.*/
+
+public class NumForNodesWithCharHist extends NumbersForNodesAndMatrix {
+	public String getName() {
+		return "Numbers for Nodes from Character Reconstructions";
+	}
+	public String getExplanation() {
+		return "Supplies numbers, based on a character reconstruction, for each node of a tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(CharsStatesForNodes.class, getName() + "  needs a source of character histories.",
+		"The source of character histories can be selected initially");
+		EmployeeNeed e2 = registerEmployeeNeed(NumbersForNodesAndHistory.class, getName() + "  needs a method to calculate values from the character histories.",
+		"The method to calculate values can be selected initially");
+	}
+	/*.................................................................................................................*/
+	CharsStatesForNodes allCharsTask;
+	NumbersForNodesAndHistory numAndHistoryTask;
+	MCharactersHistory ancestralStates;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		allCharsTask = (CharsStatesForNodes)hireEmployee(CharsStatesForNodes.class, "Reconstruction method");
+		if ( allCharsTask == null ) {
+			return sorry(getName() + " couldn't start because no character reconstructor was obtained.");
+		}
+		numAndHistoryTask = (NumbersForNodesAndHistory)hireCompatibleEmployee(NumbersForNodesAndHistory.class, getCharacterClass(), "Calculator (for " + getName() + ")");
+		if (numAndHistoryTask == null)
+			return sorry(getName() + " couldn't start because no calculator (for " + getName() + ") was obtained");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Class getCharacterClass() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("getReconstructor", allCharsTask);
+		temp.addLine("getNumNodesSource ", numAndHistoryTask); 
+		return temp;
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns reconstructor", null, commandName, "getReconstructor")) {
+			return allCharsTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns numbers for nodes and history task", null, commandName, "getNumNodesSource")) {
+			return numAndHistoryTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+
+	/*.................................................................................................................*/
+	public void calculateNumbers(Tree tree, MCharactersDistribution data, NumberArray result, MesquiteString resultString) {
+		if (tree==null || data==null)
+			return;
+		if (allCharsTask!=null) {
+		   	clearResultAndLastResult(result);
+			//note: following doesn't pass MesquiteString for results since does character by character and would only get message from last
+
+			ancestralStates = allCharsTask.calculateStates(tree, data, ancestralStates, null);
+
+			if (numAndHistoryTask!=null)
+				numAndHistoryTask.calculateNumbers(tree,ancestralStates,result,resultString);
+			saveLastResult(result);
+			saveLastResultString(resultString);
+		}
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree, MCharactersDistribution observedStates){
+		if (tree == null)
+			return;
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == allCharsTask || employee == numAndHistoryTask)  
+			iQuit();
+		super.employeeQuit(employee);
+	}
+
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+}
+
diff --git a/Source/mesquite/trees/NumForNodesWithMat/NumForNodesWithMat.java b/Source/mesquite/trees/NumForNodesWithMat/NumForNodesWithMat.java
new file mode 100644
index 0000000..c9efb86
--- /dev/null
+++ b/Source/mesquite/trees/NumForNodesWithMat/NumForNodesWithMat.java
@@ -0,0 +1,161 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForNodesWithMat;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+/**Supplies numbers for each node of a tree.*/
+
+public class NumForNodesWithMat extends NumbersForNodes {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"");
+		EmployeeNeed e2 = registerEmployeeNeed(NumbersForNodesAndMatrix.class, getName() + "  needs a method to calculate values for the nodes using matrices.",
+		"The method to calculate values can be chosen initially");
+	}
+	/*.................................................................................................................*/
+	private MatrixSourceCoord matrixSourceTask;
+	private NumbersForNodesAndMatrix numAndMatrixTask;
+	Taxa taxa;
+	protected MCharactersDistribution observedStates;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		if (NumForNodesWithMat.class.isAssignableFrom(getHiredAs()))
+			return true;
+		//assume hired as NumbersForNodes; thus responsible for getting matrices
+		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, getCharacterClass(), "Source of matrix (for " + getName() + ")");
+		if (matrixSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of matrix (for " + getName() + ") was obtained");
+
+
+		numAndMatrixTask = (NumbersForNodesAndMatrix)hireCompatibleEmployee(NumbersForNodesAndMatrix.class, getCharacterClass(), "Calculator (for " + getName() + ")");
+		if (numAndMatrixTask == null)
+			return sorry(getName() + " couldn't start because no calculator (for " + getName() + ") was obtained");
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Class getCharacterClass() {
+		return null;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getMatrixSource ", matrixSourceTask); 
+		temp.addLine("getNumNodesSource ", numAndMatrixTask); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets module supplying matrices", "[name of module]", commandName, "setMatrixSource")) {//temporary, for data files using old system without coordinators
+			if (matrixSourceTask!=null)
+				return matrixSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying matrices", null, commandName, "getMatrixSource")) {
+			return matrixSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying numbers", null, commandName, "getNumNodesSource")) {
+			return numAndMatrixTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee instanceof MatrixSourceCoord) {
+			observedStates = null;
+			parametersChanged(notification);
+		}
+
+	}
+	public Class getDutyClass() {
+		return NumForNodesWithMat.class;
+	}
+	public String getDutyName() {
+		return "Numbers for Nodes of Tree using a matrix";
+	}
+	public void calculateNumbers(Tree tree, NumberArray result, MesquiteString resultString){
+	   	clearResultAndLastResult(result);
+		if (tree!=null)
+			taxa = tree.getTaxa();
+		if (observedStates ==null)
+			observedStates = matrixSourceTask.getCurrentMatrix(tree);
+		numAndMatrixTask.calculateNumbers(tree, observedStates, result, resultString);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+
+
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == matrixSourceTask || employee == numAndMatrixTask)  // character source quit and none rehired automatically
+			iQuit();
+ 		super.employeeQuit(employee);
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+	 happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree == null)
+			return;
+		taxa = tree.getTaxa();
+		if (matrixSourceTask!=null) {
+			matrixSourceTask.initialize(tree.getTaxa());
+			if (observedStates ==null)
+				observedStates = matrixSourceTask.getCurrentMatrix(tree);
+		}
+		if (numAndMatrixTask!=null)
+			numAndMatrixTask.initialize(tree, observedStates);
+	}
+
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies numbers, based on a matrix, for each node of a tree.";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Number for Nodes using Matrix";
+	}
+	public String getNameAndParameters(){
+		if (numAndMatrixTask != null)
+			return numAndMatrixTask.getNameAndParameters();
+		return super.getNameAndParameters();
+	}
+
+}
+
+
diff --git a/Source/mesquite/trees/NumForTreeCladeValue/NumForTreeCladeValue.java b/Source/mesquite/trees/NumForTreeCladeValue/NumForTreeCladeValue.java
new file mode 100644
index 0000000..abaf2f9
--- /dev/null
+++ b/Source/mesquite/trees/NumForTreeCladeValue/NumForTreeCladeValue.java
@@ -0,0 +1,198 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForTreeCladeValue;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForTreeCladeValue extends NumberForTree {
+	public String getName() {
+		return "Value for Clade of Selected Taxa";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Value for Clade of Selected Taxa";
+		else
+			return numberTask.getVeryShortName();
+	}
+	public String getNameForMenuItem() {
+		return "Value for Clade of Selected Taxa....";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a value for the clade of selected terminal taxa.  If no terminal taxa are selected, the value at the root is given.  If the selected taxa do not make a clade, no answer is returned." ;
+	}	
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodes.class, getName() + "  needs a method to calculate values for nodes.",
+		"The method to calculate values can be selected initially or using the Values submenu");
+		e.setPriority(1);
+	}
+	/*.................................................................................................................*/
+	NumbersForNodes numberTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	MesquiteNumber lastValue;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumbersForNodes)hireNamedEmployee(NumbersForNodes.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumbersForNodes)hireEmployee(NumbersForNodes.class, "Value to calculate for selected clade");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		lastValue = new MesquiteNumber();
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumbersForNodes.class)>1 && numberTask.getCompatibilityTest()==null) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumbersForNodes.class);
+			mss.setSelected(numberTaskName);
+		}
+		return true;
+	}
+	
+	public boolean returnsMultipleValues(){
+		return false;
+}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumbersForNodes temp =  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Number for character and tree", numberTask);
+
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns most recent value calculated", null, commandName, "getMostRecentNumber")) {
+			return lastValue;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree == null)
+			return;
+		Taxa prevTaxa = taxa;
+		taxa = tree.getTaxa();
+		if (prevTaxa != null && prevTaxa != taxa){
+			prevTaxa.removeListener(this);
+			taxa.addListener(this);
+		}
+		else if (prevTaxa == null){
+			taxa.addListener(this);
+		}
+		numberTask.initialize(tree);
+	}
+	
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	/** passes which object changed, along with optional code number (type of change) and integers (e.g. which character)*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (obj == taxa && code == MesquiteListener.SELECTION_CHANGED){
+			parametersChanged();
+		}
+	}
+	MesquiteString rs = new MesquiteString();
+	NumberArray nr = new NumberArray();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		lastValue.setToUnassigned();
+		if (result==null || tree == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(tree);
+		}
+		boolean bt = tree.isClade(taxa.getSelectedBits());
+		if (!bt && taxa.anySelected()){
+			if (resultString != null)
+				resultString.setValue("Selected taxa do not form clade");
+			return;
+		}
+		nr.deassignArray();
+		nr.resetSize(tree.getNumNodeSpaces());
+		rs.setValue("");
+		numberTask.calculateNumbers(tree, nr, rs); ///Tree tree, NumberArray result, MesquiteString resultString
+		int node = tree.getRoot();
+		if (taxa.anySelected())
+			node = tree.mrca(taxa.getSelectedBits());
+		nr.placeValue(node, result);
+		if (resultString!=null) {
+			resultString.setValue(numberTask.getName());
+			if (node == tree.getRoot())
+				resultString.append(" (of root): ");
+			else
+				resultString.append(" (of selected clade): ");
+			resultString.append(result.toString());
+		}
+		lastValue.setValue(result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+			return "Calculator: " + numberTask.getName(); 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+			return numberTask.getName();
+	}
+	/*.................................................................................................................*/
+
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForTreeSelNodeValue/NumForTreeSelNodeValue.java b/Source/mesquite/trees/NumForTreeSelNodeValue/NumForTreeSelNodeValue.java
new file mode 100644
index 0000000..57bd86a
--- /dev/null
+++ b/Source/mesquite/trees/NumForTreeSelNodeValue/NumForTreeSelNodeValue.java
@@ -0,0 +1,217 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForTreeSelNodeValue;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForTreeSelNodeValue extends NumberForTree {
+	public String getName() {
+		return "Value for Node Selected In Current Tree";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Value for Node Selected In Current Tree";
+		else
+			return numberTask.getVeryShortName();
+	}
+	public String getNameForMenuItem() {
+		return "Value for Node Selected In Current Tree....";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a value for a node selected in a current tree.  If no node or more than one node is selected in current tree, no result is returned.  " + 
+		"If the assessed tree does not share the same clade of the selected node, no answer is returned." ;
+	}	
+	public int getVersionOfFirstRelease(){
+		return 260;  
+	}
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodes.class, getName() + "  needs a method to calculate values for nodes.",
+		"The method to calculate values can be selected initially or using the Values submenu");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(OneTreeSource.class, getName() + "  needs a source of a comparison tree.",
+		"The source of comparison tree is arranged initially");
+	}
+	/*.................................................................................................................*/
+	Tree otherTree = null;
+	OneTreeSource otherTreeTask;
+	NumbersForNodes numberTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	MesquiteNumber lastValue;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		otherTreeTask = (OneTreeSource)hireEmployee(OneTreeSource.class, "Source of tree for comparison");
+		if (otherTreeTask == null) {
+			return sorry(getName() + " couldn't start because no source of a current tree was obtained.");
+		}
+		if (arguments !=null) {
+			numberTask = (NumbersForNodes)hireNamedEmployee(NumbersForNodes.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumbersForNodes)hireEmployee(NumbersForNodes.class, "Value to calculate for selected clade");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		lastValue = new MesquiteNumber();
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumbersForNodes.class)>1 && numberTask.getCompatibilityTest()==null) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumbersForNodes.class);
+			mss.setSelected(numberTaskName);
+		}
+		return true;
+	}
+	
+	public boolean returnsMultipleValues(){
+		return false;
+}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		temp.addLine("setTreeSource ", otherTreeTask); 
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumbersForNodes temp =  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Number for character and tree", numberTask);
+
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the source of the comparison tree", "[name of module]", commandName, "setTreeSource")) {
+			OneTreeSource temp = (OneTreeSource)replaceEmployee(OneTreeSource.class, arguments, "Source of other tree", otherTreeTask);
+			if (temp !=null){
+				otherTreeTask = temp;
+				parametersChanged();
+				return otherTreeTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns most recent value calculated", null, commandName, "getMostRecentNumber")) {
+			return lastValue;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		if (tree == null)
+			return;
+		taxa = tree.getTaxa();
+			otherTreeTask.initialize(tree.getTaxa());
+		numberTask.initialize(tree);
+	}
+	
+	MesquiteString rs = new MesquiteString();
+	NumberArray nr = new NumberArray();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		lastValue.setToUnassigned();
+		if (result==null || tree == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(tree);
+		}
+		otherTree = otherTreeTask.getTree(tree.getTaxa());
+		if (otherTree == null || !(otherTree instanceof Associable)){
+			if (resultString != null)
+				resultString.setValue("No appropriate current tree is available from which to obtain selected node.");
+			return;
+		}
+		Associable oT = (Associable)otherTree;
+		if (oT.numberSelected() != 1){
+			if (resultString != null)
+				resultString.setValue("Current tree has no or more than one node selected.");
+			return;
+		}
+		int oN = oT.firstSelected();
+		Bits tS = otherTree.getTerminalTaxaAsBits(oN);
+		boolean bt = tree.isClade(tS);
+		
+		if (!bt){
+			if (resultString != null)
+				resultString.setValue("Node selected in current tree does not represent clade in this tree.");
+			return;
+		}
+		
+		nr.deassignArray();
+		nr.resetSize(tree.getNumNodeSpaces());
+		rs.setValue("");
+		numberTask.calculateNumbers(tree, nr, rs); ///Tree tree, NumberArray result, MesquiteString resultString
+		int node = tree.mrca(tS);
+		nr.placeValue(node, result);
+		if (resultString!=null) {
+			resultString.setValue(numberTask.getName());
+			if (node == tree.getRoot())
+				resultString.append(" (of root): ");
+			else
+				resultString.append(" (of selected node): ");
+			resultString.append(result.toString());
+		}
+		lastValue.setValue(result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+			String s= "Calculator: " + numberTask.getName(); 
+			if (otherTree !=null)
+				s += "; current tree with selected node " + otherTree;
+			return s;
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+			return numberTask.getName();
+	}
+	/*.................................................................................................................*/
+
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForTreeWith2Chars/NumForTreeWith2Chars.java b/Source/mesquite/trees/NumForTreeWith2Chars/NumForTreeWith2Chars.java
new file mode 100644
index 0000000..c19814b
--- /dev/null
+++ b/Source/mesquite/trees/NumForTreeWith2Chars/NumForTreeWith2Chars.java
@@ -0,0 +1,298 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForTreeWith2Chars;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForTreeWith2Chars extends NumberForTree {
+	public String getName() {
+		return "Tree value using 2 characters";
+	}
+
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Tree value using 2 characters";
+		else
+			return numberTask.getVeryShortName();
+	}
+
+	public String getNameForMenuItem() {
+		return "Tree value using 2 characters....";
+	}
+
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a tree based on 2 characters." ;
+	}
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberFor2CharAndTree.class, getName() + "  needs a method to calculate values for trees using characters.",
+		"The method to calculate values can be seslected initially or using the Values submenu");
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberFor2CharAndTree.class;
+	}
+	/*.................................................................................................................*/
+	NumberFor2CharAndTree numberTask;
+	CharSourceCoordObed characterSourceTask;
+	Taxa taxa;
+	MesquiteString numberTaskName;
+	MesquiteString charSourceName;
+	MesquiteCommand ntC;
+	MesquiteCommand cstC;
+	int currentCharX = 0;
+	int currentCharY = 1;
+	MesquiteNumber lastValue;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberFor2CharAndTree)hireNamedEmployee(NumberFor2CharAndTree.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumberFor2CharAndTree)hireEmployee(NumberFor2CharAndTree.class, "Value to calculate for tree with two characters");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(NumberFor2CharAndTree.class)>1) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, NumberFor2CharAndTree.class);
+			mss.setSelected(numberTaskName);
+		}
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numberTask.getCompatibilityTest(), "Source of Characters (for " + numberTask.getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		addMenuItem( "Next Character (X)", makeCommand("nextCharacterX",  this));
+		addMenuItem( "Previous Character (X)", makeCommand("previousCharacterX",  this));
+		addMenuItem( "Choose Character (X)...", makeCommand("chooseCharacterX",  this));
+
+		addMenuItem( "Next Character (Y)", makeCommand("nextCharacterY",  this));
+		addMenuItem( "Previous Character (Y)", makeCommand("previousCharacterY",  this));
+		addMenuItem( "Choose Character (Y)...", makeCommand("chooseCharacterY",  this));
+		lastValue = new MesquiteNumber();
+		return true;
+	}
+	/* ................................................................................................................. */
+	/** Returns the purpose for which the employee was hired (e.g., "to reconstruct ancestral states" or "for X axis"). */
+	public String purposeOfEmployee(MesquiteModule employee) {
+		if (employee == characterSourceTask)
+			return "for " + numberTask.getName(); // to be overridden
+		return "";
+	}		//mb.setExplanationByWhichHired
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNumberTask ", numberTask);  
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacterX " + CharacterStates.toExternal(currentCharX));
+		temp.addLine("setCharacterY " + CharacterStates.toExternal(currentCharY));
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumberFor2CharAndTree temp =  (NumberFor2CharAndTree)replaceEmployee(NumberFor2CharAndTree.class, arguments, "Number for character and tree", numberTask);
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (characterSourceTask != null)
+					characterSourceTask.setHiringCondition(numberTask.getCompatibilityTest());
+				resetContainingMenuBar();
+				parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Returns most recent value calculated", null, commandName, "getMostRecentNumber")) {
+			return lastValue;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character (X)", null, commandName, "nextCharacterX")) {
+			if (currentCharX>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentCharX=0;
+			else
+				currentCharX++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character (X)", null, commandName, "previousCharacterX")) {
+			if (currentCharX<=0)
+				currentCharX=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentCharX--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use (X)", null, commandName, "chooseCharacterX")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree (X, currently " + (currentCharX+1) + ")");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentCharX = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use (X)", "[character number]", commandName, "setCharacterX")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentCharX = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentCharX = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character (Y)", null, commandName, "nextCharacterY")) {
+			if (currentCharY>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentCharY=0;
+			else
+				currentCharY++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character (Y)", null, commandName, "previousCharacterY")) {
+			if (currentCharY<=0)
+				currentCharY=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentCharY--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use (Y)", null, commandName, "chooseCharacterY")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree (Y, currently " + (currentCharY+1) + ")");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentCharY = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacterY")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentCharY = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentCharY = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		taxa = tree.getTaxa();
+		CharacterDistribution charStatesX  = characterSourceTask.getCharacter(tree, currentCharX);
+		CharacterDistribution charStatesY  = characterSourceTask.getCharacter(tree, currentCharX);
+		numberTask.initialize(tree, charStatesX, charStatesY);
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+		lastValue.setToUnassigned();
+		if (result==null || tree == null)
+			return;
+		clearResultAndLastResult(result);
+
+		if (taxa==null){
+			initialize(tree);
+		}
+		CharacterDistribution charStatesX = characterSourceTask.getCharacter(tree, currentCharX);
+		CharacterDistribution charStatesY = characterSourceTask.getCharacter(tree, currentCharY);
+		rs.setValue("");
+		numberTask.calculateNumber(tree, charStatesX, charStatesY, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For characters " + (currentCharX+1) + " and " + (currentCharY+1) + ", ");
+			resultString.append(rs.toString());
+		}
+		lastValue.setValue(result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			currentCharX = 0;
+			currentCharY = 1;
+			parametersChanged(notification);
+		}
+		else
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		return "Calculator: " + numberTask.getName() + " with characters " + (currentCharX+1) + " and " + (currentCharY+1); 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		return numberTask.getName() + " with characters " + (currentCharX+1) + " and " + (currentCharY+1); 
+	}
+	/*.................................................................................................................*/
+
+
+}
+
diff --git a/Source/mesquite/trees/NumForTreeWithChar/NumForTreeWithChar.java b/Source/mesquite/trees/NumForTreeWithChar/NumForTreeWithChar.java
new file mode 100644
index 0000000..e9a7615
--- /dev/null
+++ b/Source/mesquite/trees/NumForTreeWithChar/NumForTreeWithChar.java
@@ -0,0 +1,297 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumForTreeWithChar;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumForTreeWithChar extends NumberForTreeM implements Incrementable{
+	public String getName() {
+		return "Tree value using character";
+	}
+	public String getVeryShortName() {
+		if (numberTask ==null)
+			return "Tree value using character";
+		else
+			return numberTask.getVeryShortName();
+	}
+	public String getNameForMenuItem() {
+		return "Tree value using character....";
+	}
+	public String getExplanation() {
+		return "Coordinates the calculation of a number for a tree based on a character." ;
+	}	
+	
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForCharAndTree.class, getName() + "  needs a method to calculate values for trees using characters.",
+		"The method to calculate values can be seslected initially or using the Values submenu");
+		e.setPriority(1);
+		EmployeeNeed e2 = registerEmployeeNeed(CharSourceCoordObed.class, getName() + "  needs a source of characters.",
+		"");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberForCharAndTree.class;
+	}
+	/*.................................................................................................................*/
+	NumberForCharAndTree numberTask;
+	CharSourceCoordObed characterSourceTask;
+	Taxa taxa;
+	Tree tree;
+	MesquiteString numberTaskName;
+	MesquiteCommand ntC;
+	int currentChar = -1;
+	Class taskClass = NumberForCharAndTree.class;
+	MesquiteNumber lastValue;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (getHiredAs() == NumberForTreeM.class)
+			taskClass = NumberForCharAndTreeM.class;
+		else
+			taskClass = NumberForCharAndTree.class;
+		if (arguments !=null) {
+			numberTask = (NumberForCharAndTree)hireNamedEmployee(taskClass, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+			numberTask = (NumberForCharAndTree)hireEmployee(taskClass, "Value to calculate for tree with character");
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because no calculator module obtained.");
+		}
+		lastValue = new MesquiteNumber();
+		ntC =makeCommand("setNumberTask",  this);
+		numberTask.setHiringCommand(ntC);
+		numberTaskName = new MesquiteString();
+		numberTaskName.setValue(numberTask.getName());
+		if (numModulesAvailable(taskClass)>1 && numberTask.getCompatibilityTest()==null) {
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Values", ntC, taskClass);
+			mss.setSelected(numberTaskName);
+		}
+		characterSourceTask = (CharSourceCoordObed)hireCompatibleEmployee(CharSourceCoordObed.class, numberTask.getCompatibilityTest(), "Source of characters (for " + numberTask.getName() + ")");
+		if (characterSourceTask == null)
+			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+		addMenuItem( "Next Character", makeCommand("nextCharacter",  this));
+		addMenuItem( "Previous Character", makeCommand("previousCharacter",  this));
+		addMenuItem( "Choose Character...", makeCommand("chooseCharacter",  this));
+		addMenuItem( "-", null);
+		return true;
+	}
+	
+	public boolean returnsMultipleValues(){
+		return numberTask.returnsMultipleValues();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	/*.................................................................................................................*/
+	public void setCurrent(long i){
+		if (characterSourceTask==null || taxa==null)
+			return;
+		if ((i>=0) && (i<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+			currentChar = (int)i;
+		}
+	}
+	public String getItemTypeName(){
+		return "Character";
+	}
+	/*.................................................................................................................*/
+	public long toInternal(long i){
+		return(CharacterStates.toInternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long toExternal(long i){
+		return(CharacterStates.toExternal((int)i));
+	}
+	/*.................................................................................................................*/
+	public long getCurrent(){
+		return currentChar;
+	}
+	/*.................................................................................................................*/
+	public long getMin(){
+		return 0;
+	}
+	/*.................................................................................................................*/
+	public long getMax(){
+		if (characterSourceTask==null || taxa==null)
+			return 0;
+		return characterSourceTask.getNumberOfCharacters(taxa)-1;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getCharacterSource ",characterSourceTask);
+		temp.addLine("setCharacter " + CharacterStates.toExternal(currentChar));
+		temp.addLine("setNumberTask ", numberTask);  
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module that calculates numbers for characters with the current tree", "[name of module]", commandName, "setNumberTask")) {
+			NumberForCharAndTree temp =  (NumberForCharAndTree)replaceEmployee(taskClass, arguments, "Number for character and tree", numberTask);
+
+			if (temp!=null) {
+				numberTask = temp;
+				numberTask.setHiringCommand(ntC);
+				numberTaskName.setValue(numberTask.getName());
+				if (!MesquiteThread.isScripting())
+					parametersChanged();
+				return numberTask;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets module supplying characters", "[name of module]", commandName, "setCharacterSource")) {//temporary, for data files using old system without coordinators
+			return characterSourceTask.doCommand(commandName, arguments, checker);
+		}
+		else if (checker.compare(this.getClass(), "Returns module supplying characters", null, commandName, "getCharacterSource")) {
+			return characterSourceTask;
+		}
+		else if (checker.compare(this.getClass(), "Goes to next character", null, commandName, "nextCharacter")) {
+			if (currentChar>=characterSourceTask.getNumberOfCharacters(taxa)-1)
+				currentChar=0;
+			else
+				currentChar++;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Goes to previous character", null, commandName, "previousCharacter")) {
+			if (currentChar<=0)
+				currentChar=characterSourceTask.getNumberOfCharacters(taxa)-1;
+			else
+				currentChar--;
+			//charStates = null;
+			parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Queries the user about what character to use", null, commandName, "chooseCharacter")) {
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the character to use", "[character number]", commandName, "setCharacter")) {
+			int icNum = MesquiteInteger.fromFirstToken(arguments, stringPos);
+			if (!MesquiteInteger.isCombinable(icNum))
+				return null;
+			int ic = CharacterStates.toInternal(icNum);
+			if ((ic>=0) && characterSourceTask.getNumberOfCharacters(taxa)==0) {
+				currentChar = ic;
+				//charStates = null;
+			}
+			else if ((ic>=0) && (ic<=characterSourceTask.getNumberOfCharacters(taxa)-1)) {
+				currentChar = ic;
+				//charStates = null;
+				parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Returns most recent value calculated", null, commandName, "getMostRecentNumber")) {
+			return lastValue;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Tree tree){
+		taxa = tree.getTaxa();
+		if (!MesquiteThread.isScripting() && currentChar<0){
+			int ic=characterSourceTask.queryUserChoose(taxa, " to calculate value for tree ");
+			if (MesquiteInteger.isCombinable(ic)) {
+				currentChar = ic;
+			}
+			else
+				currentChar = 0;
+		}
+		if (currentChar < 0 || !MesquiteInteger.isCombinable(currentChar)) 
+			currentChar = 0;
+		CharacterDistribution charStates  = characterSourceTask.getCharacter(tree, currentChar);
+		numberTask.initialize(tree, charStates);
+		if (taxa==null)
+			taxa = getProject().chooseTaxa(containerOfModule(), "Taxa"); 
+	}
+	public void endJob(){
+		if (taxa!=null)
+			taxa.removeListener(this);
+		super.endJob();
+	}
+	MesquiteString rs = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString, MesquiteTree modifiedTree) {
+		lastValue.setToUnassigned();
+		if (result==null || tree == null)
+			return;
+	   	clearResultAndLastResult(result);
+		if (taxa==null){
+			initialize(tree);
+		}
+		if (currentChar < 0 || !MesquiteInteger.isCombinable(currentChar)) 
+			currentChar = 0;
+		CharacterDistribution charStates = characterSourceTask.getCharacter(tree, currentChar);
+		rs.setValue("");
+		if (numberTask instanceof NumberForCharAndTreeM)
+			((NumberForCharAndTreeM)numberTask).calculateNumber(tree, charStates, result, rs, modifiedTree);
+		else
+			numberTask.calculateNumber(tree, charStates, result, rs);
+		if (resultString!=null) {
+			resultString.setValue("For character " + (currentChar + 1) + ", ");
+			resultString.append(rs.toString());
+		}
+		lastValue.setValue(result);
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee==characterSourceTask) {
+			currentChar = 0;
+			parametersChanged(notification);
+		}
+		else
+			super.employeeParametersChanged(employee, source, notification);
+	}
+	/*.................................................................................................................*/
+	public String getParameters(){
+		if (!MesquiteInteger.isCombinable(currentChar))
+			return "Calculator: " + numberTask.getName(); //of which tree??
+		else
+			return "Calculator: " + numberTask.getName() + " with character " + (currentChar+1); 
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters(){
+		if (!MesquiteInteger.isCombinable(currentChar))
+			return numberTask.getName();
+		else
+			return numberTask.getName() + " with character " +  (currentChar+1); 
+	}
+	/*.................................................................................................................*/
+
+
+
+}
+
diff --git a/Source/mesquite/trees/NumberOfTaxa/NumberOfTaxa.java b/Source/mesquite/trees/NumberOfTaxa/NumberOfTaxa.java
new file mode 100644
index 0000000..87399b7
--- /dev/null
+++ b/Source/mesquite/trees/NumberOfTaxa/NumberOfTaxa.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.NumberOfTaxa;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** this is a silly little module that can be used as a demonstration for NumberForTree modules */
+public class NumberOfTaxa extends NumberForTree {
+	MesquiteNumber nt;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		nt= new MesquiteNumber();
+ 		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 if (result==null || tree==null)
+    	 		return;
+    	clearResultAndLastResult(result);
+		nt.setValue(tree.numberOfTerminalsInClade(tree.getRoot()));
+		result.setValue(nt);
+		if (resultString!=null)
+			resultString.setValue("Taxa: "+ nt.toString());
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	/*.................................................................................................................*/
+	/**Returns true if the module is to appear in menus and other places in which users can choose, and if can be selected in any way other than by direct request*/
+	public boolean getUserChooseable(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Number of Taxa";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getVeryShortName() {
+		return "Taxa";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Counts the number of taxa in a tree." ;
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/trees/NumsForNodesBrLengths/NumsForNodesBrLengths.java b/Source/mesquite/trees/NumsForNodesBrLengths/NumsForNodesBrLengths.java
new file mode 100644
index 0000000..b0d0798
--- /dev/null
+++ b/Source/mesquite/trees/NumsForNodesBrLengths/NumsForNodesBrLengths.java
@@ -0,0 +1,103 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.NumsForNodesBrLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class NumsForNodesBrLengths extends BranchLengthsAltererMult {
+	public String getName() {
+		return "Obtain Branch Lengths from Numbers For Nodes";
+	}
+	public String getExplanation() {
+		return "Assigns a value of branch length for all of a tree's branches based upon the numbers calculated by a Numbers for Nodes." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodes.class, getName() + "  needs a method to calculate values for nodes by which to adjust branch lengths.",
+		"The method to calculate values can be chosen initially");
+	}
+	/*.................................................................................................................*/
+	NumbersForNodes numbersTask;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		numbersTask = (NumbersForNodes)hireEmployee(NumbersForNodes.class,  "Source of matrix (for " + getName() + ")");
+		if (numbersTask == null)
+			return sorry(getName() + " couldn't start because no NumbersForNodes (for " + getName() + ") was obtained");
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("getNumbersForNodes ", numbersTask); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module supplying numbers for nodes", null, commandName, "getNumbersForNodes")) {
+			return numbersTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
+	public void employeeQuit(MesquiteModule employee) {
+		if (employee == numbersTask)  
+			iQuit();
+		super.employeeQuit(employee);
+	}
+
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree instanceof MesquiteTree) {
+			int numNodes = tree.getNumNodeSpaces();
+			NumberArray result = new NumberArray(numNodes);
+			numbersTask.calculateNumbers(tree, result, null);
+
+			for (int i=0; i<numNodes; i++) 
+				((MesquiteTree)tree).setBranchLength(i,result.getDouble(i),false);
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+
+			return true;
+		}
+		return false;
+	}
+}
+
diff --git a/Source/mesquite/trees/ObedientTreeWindow/ObedientTreeWindow.java b/Source/mesquite/trees/ObedientTreeWindow/ObedientTreeWindow.java
new file mode 100644
index 0000000..9ca7747
--- /dev/null
+++ b/Source/mesquite/trees/ObedientTreeWindow/ObedientTreeWindow.java
@@ -0,0 +1,93 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ObedientTreeWindow;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+/* ======================================================================== */
+//see mesquite.lib.duties.TreeInferer for example of use
+public class ObedientTreeWindow extends SimpleTreeWindowMaker  {
+	OTreeWindow tw;
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	protected SimpleTreeWindow makeTreeWindow(SimpleTreeWindowMaker stwm, DrawTreeCoordinator dtwc){
+		tw= new OTreeWindow( this, treeDrawCoordTask);
+		return tw;
+	}
+	protected String getMenuName(){
+		return "Tree";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Simple Tree Window";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Displays a single tree." ;
+	}
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Ladderizes the clade", "[branch number]", commandName, "ladderize")) {
+			Parser parser = new Parser();
+			String s = parser.getFirstToken(arguments);
+			int branchFound= MesquiteInteger.fromString(s);
+			Tree tree = tw.getTree();
+			MesquiteTree mTree = null;
+			if (tree instanceof MesquiteTree) 
+				mTree = (MesquiteTree)tree;
+			else
+				return null;
+			if (s.equalsIgnoreCase("root"))
+				branchFound = mTree.getRoot();
+			else
+				branchFound= MesquiteInteger.fromString(s);
+			if (branchFound >0) {
+				boolean direction = true;
+				if (arguments.indexOf("option")>=0)
+					direction = false;
+				if (mTree.standardize(branchFound, direction, true)){
+						;
+				}
+			}
+		}		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+}
+
+/* ======================================================================== */
+class OTreeWindow extends SimpleTreeWindow  {
+	public OTreeWindow ( ObedientTreeWindow ownerModule, DrawTreeCoordinator treeDrawCoordTask){
+		super(ownerModule, treeDrawCoordTask); //infobar
+	}
+
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Tree"); //TODO: what tree?
+	}
+
+}
+
+
diff --git a/Source/mesquite/trees/OtherTreeBlocks/OtherTreeBlocks.java b/Source/mesquite/trees/OtherTreeBlocks/OtherTreeBlocks.java
new file mode 100644
index 0000000..c3d2c62
--- /dev/null
+++ b/Source/mesquite/trees/OtherTreeBlocks/OtherTreeBlocks.java
@@ -0,0 +1,176 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.OtherTreeBlocks;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.charMatrices.lib.RandomMatrixModifier;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies tree blocks from other sources.*/
+public class OtherTreeBlocks extends TreeBlockSource {
+	public String getName() {
+		return "Other Tree Blocks";
+	}
+	public String getExplanation() {
+		return "Supplies blocks of trees from various sources";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeBlockFiller.class, getName() + "  uses a secondary source of tree blocks.",
+		"The source of tree blocks can be chosen initially");
+		//e.setDivertChainMessage("testing");
+
+	}
+	/*.................................................................................................................*/
+	int currentTreeBlockIndex=MesquiteInteger.unassigned;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	TreeBlockFiller fillerTask = null;
+	Taxa preferredTaxa =null;
+
+	int numTrees = 100;
+	MesquiteMenuItemSpec ntreesItem = null;
+	boolean nTreesSet = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments ==null) {
+			if (MesquiteThread.isScripting())
+				fillerTask = (TreeBlockFiller)hireNamedEmployee(TreeBlockFiller.class, "#StoredTrees");
+			if (fillerTask == null)
+				fillerTask = (TreeBlockFiller)hireEmployee(TreeBlockFiller.class, "Source of trees for tree blocks");
+		}
+		else {
+			fillerTask = (TreeBlockFiller)hireNamedEmployee(TreeBlockFiller.class, arguments);
+			if (fillerTask == null)
+				fillerTask = (TreeBlockFiller)hireEmployee(TreeBlockFiller.class, "Source of trees for tree blocks");
+		}
+
+		if (fillerTask == null)
+			return sorry(getName() + " couldn't start because no source of trees obtained.");
+		ntreesItem = addMenuItem( "Number of Trees...", makeCommand("setNumberTrees",   this));
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Class getHireSubchoice(){
+		return TreeBlockFiller.class;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		preferredTaxa = taxa;
+	}
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		setPreferredTaxa(taxa);
+		fillerTask.initialize(taxa);
+		if (!fillerTask.hasLimitedTrees(taxa)){
+			if (!MesquiteThread.isScripting()  && !nTreesSet){
+				int n = MesquiteInteger.queryInteger(containerOfModule(), "Trees per block?", "How many trees to include per tree block?", numTrees);
+				if (MesquiteInteger.isCombinable(n) && n>0)
+					numTrees = n;
+				nTreesSet = true;
+			}
+		}
+		ntreesItem.setEnabled(!fillerTask.hasLimitedTrees(taxa));
+		MesquiteTrunk.resetMenuItemEnabling();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeFiller ", fillerTask);
+		temp.addLine("setNumberTrees " + numTrees);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the number of trees included in each tree block", "[number of trees]", commandName, "setNumberTrees")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees:", numTrees, 0, MesquiteInteger.infinite);
+			if (newNum>0  && newNum!=numTrees) {
+				numTrees = newNum;
+				parametersChanged();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the module supplying trees", "[name of module]", commandName, "setTreeFiller")) {
+			TreeBlockFiller temp=  (TreeBlockFiller)replaceEmployee(TreeBlockFiller.class, arguments, "Source of trees for tree blocks", fillerTask);
+			if (temp!=null) {
+				fillerTask = temp;
+				initialize(preferredTaxa);
+				parametersChanged(); //?
+			}
+			return temp;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public TreeVector getFirstBlock(Taxa taxa) {
+		currentTreeBlockIndex=0;
+		return getCurrentBlock(taxa);
+	}
+	/*.................................................................................................................*/
+	public TreeVector getBlock(Taxa taxa, int ic) {
+		currentTreeBlockIndex=ic;
+		return getCurrentBlock(taxa);
+	}
+	/*.................................................................................................................*/
+	public TreeVector getCurrentBlock(Taxa taxa) {
+		if (fillerTask instanceof Incrementable)
+			((Incrementable)fillerTask).setCurrent(currentTreeBlockIndex);
+		setPreferredTaxa(taxa);
+		TreeVector treeList = new TreeVector(taxa);	
+
+		fillerTask.fillTreeBlock(treeList, numTrees); 
+		return treeList;
+	}
+	/*.................................................................................................................*/
+	public TreeVector getNextBlock(Taxa taxa) {
+		currentTreeBlockIndex++;
+		return getCurrentBlock(taxa);
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTreeBlocks(Taxa taxa) {
+		if (fillerTask instanceof Incrementable)
+			return (int)( ((Incrementable)fillerTask).getMax() -  ((Incrementable)fillerTask).getMin() + 1);
+		return 1;
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeBlockNameString(Taxa taxa, int index) {
+		return fillerTask.getName() + "  " + currentTreeBlockIndex;//todo!  not right
+	}
+	/*.................................................................................................................*/
+	public String getCurrentTreeBlockNameString(Taxa taxa) {
+		return fillerTask.getName() + "  " + currentTreeBlockIndex; //todo!  not right
+	}
+}
+
diff --git a/Source/mesquite/trees/ResolvePolytomiesToZero/ResolvePolytomiesToZero.java b/Source/mesquite/trees/ResolvePolytomiesToZero/ResolvePolytomiesToZero.java
new file mode 100644
index 0000000..91c8a0f
--- /dev/null
+++ b/Source/mesquite/trees/ResolvePolytomiesToZero/ResolvePolytomiesToZero.java
@@ -0,0 +1,75 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ResolvePolytomiesToZero;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ResolvePolytomiesToZero extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+  	 
+  	void resolveNode(AdjustableTree tree, int node){
+  	 	if (tree.nodeIsInternal(node)) { 
+  	 		int numDaughters = 0;
+	  	 	for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+	  			resolveNode(tree, daughter);
+	  			numDaughters++;
+	   	 	}
+	   	 	if (tree.nodeIsPolytomous(node)){
+	  	 		for (int i=0; i<numDaughters-2; i++){
+	  	 			int first = tree.firstDaughterOfNode(node);
+	  	 			int moving = tree.indexedDaughterOfNode(node, 1);
+	  	 			double mLength = tree.getBranchLength(moving);
+	  	 			double fLength = tree.getBranchLength(first);
+	  	 			tree.moveBranch(moving, first, false);
+	  	 			tree.setBranchLength(first, fLength, false);
+	  	 			int newNode = tree.firstDaughterOfNode(node);
+	  	 			tree.setBranchLength(newNode, 0, false);
+	  	 			tree.setBranchLength(moving, mLength, false);
+	  	 		}
+	  	 	}
+ 		}
+  	}
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+			resolveNode(tree, tree.getRoot());
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Resolve Polytomies (to 0-length branches)";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Resolves polytomies arbitrarily and assigned the resulting new branches zero length." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SampleManyTreesFromFile/SampleManyTreesFromFile.java b/Source/mesquite/trees/SampleManyTreesFromFile/SampleManyTreesFromFile.java
new file mode 100644
index 0000000..c40e71a
--- /dev/null
+++ b/Source/mesquite/trees/SampleManyTreesFromFile/SampleManyTreesFromFile.java
@@ -0,0 +1,137 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SampleManyTreesFromFile;
+
+import mesquite.lib.*;
+import mesquite.trees.lib.*;
+
+public class SampleManyTreesFromFile extends ManyTreesFromFileLib {
+
+	/*.................................................................................................................*/
+	protected boolean additionStartJobItems(){
+		addMenuItem("File for Sample Trees From Separate...", makeCommand("setFilePath",  this));
+		addMenuItem("Number of Trees to Sample...", makeCommand("setNumTreesToSample",  this));
+		if (!MesquiteThread.isScripting()){
+			int nt = numTreesToSample;
+			if (!MesquiteInteger.isCombinable(nt))
+				nt=100;
+			if (numTreesInTreeBlock>0 && MesquiteInteger.isCombinable(numTreesInTreeBlock)) {
+				numTreesToSample =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Sample", "Number of Trees to Sample (out of " + numTreesInTreeBlock + " total trees) from file:", nt, 0, numTreesInTreeBlock, true);
+			}
+			else {
+				numTreesToSample =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Sample", "Number of trees to sample from file:",  nt, 0, MesquiteInteger.infinite, true);
+			}
+			if (!MesquiteInteger.isCombinable(numTreesToSample) || numTreesToSample==0)
+					return false;
+			else
+				setTreesToSample(numTreesToSample);
+		}
+		addMenuItem("Number of Trees to Ignore...", makeCommand("setStartTreesToIgnore",  this));
+		if (!MesquiteThread.isScripting()){
+			if (numTreesInTreeBlock>0 && MesquiteInteger.isCombinable(numTreesInTreeBlock)) {
+				numStartTreesToIgnore =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Ignore", "Number of trees to ignore (out of " + numTreesInTreeBlock + " total trees) from start of file:", numStartTreesToIgnore, 0, numTreesInTreeBlock, true);
+				}
+				else {
+					numStartTreesToIgnore =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Ignore", "Number of trees to ignore from start of  file:", numStartTreesToIgnore, 0, MesquiteInteger.infinite, true);
+				}
+			if (!MesquiteInteger.isCombinable(numStartTreesToIgnore))
+					return false;
+			else
+				setTreesToSample(numTreesToSample);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+ 	 public void additionalSnapshot(Snapshot snapshot) {
+   	 	snapshot.addLine("setNumTreesToSample " + numTreesToSample);  
+  	 	snapshot.addLine("setStartTreesToIgnore " + numStartTreesToIgnore);  
+ 	 }	
+ 	 MesquiteInteger pos = new MesquiteInteger(0);
+ 	 /*.................................................................................................................*/
+ 	 public boolean additionalDoCommands(String commandName, String arguments, CommandChecker checker) {
+		 if (checker.compare(this.getClass(), "Specifies the number of trees to sample", "[number of trees]", commandName, "setNumTreesToSample")) {
+ 			 pos.setValue(0);
+ 			 int num = MesquiteInteger.fromString(arguments, pos);
+ 			 if (!MesquiteInteger.isCombinable(num)&& !MesquiteThread.isScripting()){
+ 				int nt = numTreesToSample;
+				if (!MesquiteInteger.isCombinable(nt))
+					nt=100;
+				if (numTreesInTreeBlock>0 && MesquiteInteger.isCombinable(numTreesInTreeBlock)) {
+ 					num =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Sample", "Number of Trees to Sample (out of " + numTreesInTreeBlock + " total trees) from file:", nt, 0, numTreesInTreeBlock, true);
+ 				}
+ 				else {
+ 					num =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Sample", "Number of trees to sample from file:", nt, 0, MesquiteInteger.infinite, true);
+ 				}
+ 			 }
+ 			 if (MesquiteInteger.isCombinable(num)) {
+ 				 numTreesToSample = num;
+ 				 setTreesToSample(numTreesToSample);
+ 				 parametersChanged();
+ 			 }
+ 			 return true;
+ 		 }
+		 else  if (checker.compare(this.getClass(), "Specifies the number of trees to ignore from the start of the file", "[number of trees]", commandName, "setStartTreesToIgnore")) {
+ 			 pos.setValue(0);
+ 			 int num = MesquiteInteger.fromString(arguments, pos);
+ 			 if (!MesquiteInteger.isCombinable(num)&& !MesquiteThread.isScripting()){
+ 				if (numTreesInTreeBlock>0 && MesquiteInteger.isCombinable(numTreesInTreeBlock)) {
+ 					num =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Ignore", "Number of trees to ignore (out of " + numTreesInTreeBlock + " total trees) from start of file:", numStartTreesToIgnore, 0, numTreesInTreeBlock, true);
+				}
+ 				else {
+ 					num =MesquiteInteger.queryInteger(containerOfModule(), "Number of Trees to Ignore", "Number of trees to ignore from start of  file:", numStartTreesToIgnore, 0, MesquiteInteger.infinite, true);
+ 				}
+ 			 }
+ 			 if (MesquiteInteger.isCombinable(num)) {
+ 				numStartTreesToIgnore = num;
+ 				 setTreesToSample(numTreesToSample);
+ 				 parametersChanged();
+ 			 }
+ 			 return true;
+ 		 }
+ 		 return false;
+ 	 }
+ 	/*.................................................................................................................*/
+ 	protected boolean canIgnoreStartTrees(){
+ 		return true;
+ 	}
+ 	 /*.................................................................................................................*/
+ 	 protected boolean canDoLiveUpdate(){
+ 		 return false;
+ 	 }
+ 	 /*.................................................................................................................*/
+ 		 protected boolean getSampleTrees(){
+ 			 return true;
+	}
+	/*.................................................................................................................*/
+	 public String getName() {
+	return "Sample Trees from Separate NEXUS File";
+	 }
+		/*.................................................................................................................*/
+		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+		public int getVersionOfFirstRelease(){
+			return 200;  
+		}
+/*.................................................................................................................*/
+	 public String getNameForMenuItem() {
+	return "Sample Trees from Separate NEXUS File...";
+	 }
+	 
+/*.................................................................................................................*/
+	 public String getExplanation() {
+	return "Supplies a fixed number of randomly-sampled trees directly from a file, without bringing the contained tree block entirely into memory.  This allows much larger blocks of trees to be used within constraints of memory, but will make some calculations slower.  This module does not know how many trees are in the file, and hence may attempt to read files beyond the number in the file.";
+	 }
+
+}
diff --git a/Source/mesquite/trees/ScaleBranchLengths/ScaleBranchLengths.java b/Source/mesquite/trees/ScaleBranchLengths/ScaleBranchLengths.java
new file mode 100644
index 0000000..44efd00
--- /dev/null
+++ b/Source/mesquite/trees/ScaleBranchLengths/ScaleBranchLengths.java
@@ -0,0 +1,74 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ScaleBranchLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ScaleBranchLengths extends BranchLengthsAltererMult {
+	double resultNum;
+	double scale = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		scale = MesquiteDouble.queryDouble(containerOfModule(), "Scale branch lengths", "Multiply all branch lengths by", 1.0);
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+  	 		if (MesquiteDouble.isCombinable(scale) && tree instanceof MesquiteTree) {
+  	 			if (tree.hasBranchLengths()){
+   					((MesquiteTree)tree).scaleAllBranchLengths(scale, false);
+					if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+   				
+   					return true;
+   				}
+   				else {
+   					discreetAlert("Branch lengths of tree are all unassigned.  Cannot scale branch lengths.");
+   				}
+   			}
+   			return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Scale All Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Scale All Branch Lengths...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adjusts a tree's branch lengths by multiplying them by an amount." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/ScaleSelBranchLengths/ScaleSelBranchLengths.java b/Source/mesquite/trees/ScaleSelBranchLengths/ScaleSelBranchLengths.java
new file mode 100644
index 0000000..0047046
--- /dev/null
+++ b/Source/mesquite/trees/ScaleSelBranchLengths/ScaleSelBranchLengths.java
@@ -0,0 +1,71 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ScaleSelBranchLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ScaleSelBranchLengths extends BranchLengthsAlterer {
+	double resultNum;
+	double scale = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		scale = MesquiteDouble.queryDouble(containerOfModule(), "Scale lengths of selected branches", "Multiply all branch lengths by", 1.0);
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+  	 		if (MesquiteDouble.isCombinable(scale) && tree instanceof MesquiteTree) {
+  	 			if (tree.hasBranchLengths()){
+   					((MesquiteTree)tree).doCommand("scaleLengthSelectedBranches", MesquiteDouble.toString(scale), CommandChecker.defaultChecker);
+					if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+   					return true;
+   				}
+   				else discreetAlert( "Branch lengths of tree are all unassigned.  Cannot scale selected branch lengths.");
+   			}
+   			return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Scale Selected Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Scale Selected Branch Lengths...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adjusts lengths of a tree's selected branches by multiplying them by an amount." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SearchForBetterTree/SearchForBetterTree.java b/Source/mesquite/trees/SearchForBetterTree/SearchForBetterTree.java
new file mode 100644
index 0000000..091f680
--- /dev/null
+++ b/Source/mesquite/trees/SearchForBetterTree/SearchForBetterTree.java
@@ -0,0 +1,143 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SearchForBetterTree;
+
+import java.awt.Button;
+import mesquite.trees.lib.*;
+import java.awt.Checkbox;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+/*  TODO: ask option of showing live updates
+ * */
+
+public class SearchForBetterTree extends TreeAlterer {
+	int currentTree=0;
+	TreeSwapper swapTask;
+	NumberForTree numberTask;
+	boolean smallerIsBetter = true;
+	boolean liveUpdates = true;
+	RandomBetween rng = new RandomBetween(System.currentTimeMillis());
+	TreeOptimizer treeOptimizer;
+
+	public String getName() {
+		return "Search for Better Tree";
+	}
+	public String getExplanation() {
+		return "Finds better trees (by the chosen optimality criterion) by rearranging the current tree.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSwapper.class, getName() + "  needs a method to rearrange the tree.",
+		"The method to rearrange the tree can be selected initially or in the Branch Rearranger submenu");
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		swapTask = (TreeSwapper)hireEmployee(TreeSwapper.class, "Tree Rearranger");
+		if (swapTask==null)
+			return sorry(getName() + " couldn't start because no tree rearranging module was obtained");
+		numberTask = (NumberForTree)hireEmployee(NumberForTree.class, "Statistic to calculate for tree");
+		if (numberTask == null)
+			return sorry(getName() + " couldn't start because no calculator module obtained.");
+		if (!MesquiteThread.isScripting()){
+			if (!queryOptions())
+				return false;
+		}
+		treeOptimizer = new TreeOptimizer(this, numberTask, swapTask);
+		if (treeOptimizer== null)
+			return sorry(getName() + " couldn't start because the tree optimizer could not be created.");
+		return true;
+	}
+	/*.................................................................................................................*/
+
+	public boolean isPrerelease(){
+		return false;
+	}
+	public boolean requestPrimaryChoice(){
+		return true;
+	}
+	public CompatibilityTest getCompatibilityTest(){
+		if (numberTask !=null)
+			return numberTask.getCompatibilityTest();
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean queryOptions() {
+		MesquiteInteger buttonPressed = new MesquiteInteger(1);
+		String help = "If you select \"minimize objection function\", then Mesquite will search for trees that have smaller values of the number calculated for each tree; if you turn this option off, Mesquite will look for trees with larger values. ";
+		help+="For example, if Treelength were the value calculated for each tree, one typically would search for trees with smaller values; i.e., one would choose \"minimize objection function\".";
+		help+= " If \"live updates\" is chosen, then each time a better tree is found, the tree will be redrawn (if it is visible in a tree window) and any calculations based upon the tree,"; 
+		help+=" such as tracing of a character history, a tree legend, or a chart, will be redone, which may substantially increase the time taken for the search.";
+		ExtensibleDialog dialog = new ExtensibleDialog(containerOfModule(), "Options for Search for Better Tree",buttonPressed);  //MesquiteTrunk.mesquiteTrunk.containerOfModule()
+		dialog.appendToHelpString(help);
+		
+		dialog.addLabel("Options for Search for Better Tree");
+		
+		Checkbox smallerIsBetterBox = dialog.addCheckBox("minimize objection function", smallerIsBetter);
+		Checkbox liveUpdatesBox = dialog.addCheckBox("update display and calculations based upon tree as it is rearranged", liveUpdates);
+
+		dialog.completeAndShowDialog(true);
+		if (buttonPressed.getValue()==0)  {
+			smallerIsBetter = smallerIsBetterBox.getState();
+			liveUpdates = liveUpdatesBox.getState();
+			//storePreferences();
+		}
+		dialog.dispose();
+		return (buttonPressed.getValue()==0);
+	}
+	/*.................................................................................................................*
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = super.getSnapshot(file);
+		temp.addLine("setSwapper ", swapTask); 
+		return temp;
+	}
+	/*.................................................................................................................*
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the branch swapper", "[name of module]", commandName, "setSwapper")) {
+			TreeSwapper temp = (TreeSwapper)replaceEmployee(TreeSwapper.class, arguments, "Branch Rearranger", swapTask);
+			if (temp !=null){
+				swapTask = temp;
+				swapName.setValue(swapTask.getName());
+				swapTask.setHiringCommand(stC);
+				parametersChanged();
+				return swapTask;
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (treeOptimizer ==null)
+			return false;
+		treeOptimizer.setLiveUpdates(liveUpdates);
+		treeOptimizer.setBiggerIsBetter(!smallerIsBetter);
+		treeOptimizer.setNotify(notify);
+		return treeOptimizer.searchForBetterTree(tree,  tree.getRoot(),  rng,  resultString);
+		//return TreeSearchUtil.searchForBetterTree(this,  tree,  tree.getRoot(), swapTask,  numberTask,  rng,  resultString,  smallerIsBetter,  liveUpdates,  notify);
+	//	return TreeSearchUtil.searchForBetterTree(this,  tree,  tree.getRoot(),30000.0, false, false, swapTask,  numberTask,  rng,  resultString,  smallerIsBetter,  liveUpdates,  notify, true, false);
+	}
+	
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+	
+}
diff --git a/Source/mesquite/trees/SearchTreeToolAssistant/32searchTree.gif b/Source/mesquite/trees/SearchTreeToolAssistant/32searchTree.gif
new file mode 100644
index 0000000..e89dcc7
Binary files /dev/null and b/Source/mesquite/trees/SearchTreeToolAssistant/32searchTree.gif differ
diff --git a/Source/mesquite/trees/SearchTreeToolAssistant/64searchTree.gif b/Source/mesquite/trees/SearchTreeToolAssistant/64searchTree.gif
new file mode 100644
index 0000000..01788e9
Binary files /dev/null and b/Source/mesquite/trees/SearchTreeToolAssistant/64searchTree.gif differ
diff --git a/Source/mesquite/trees/SearchTreeToolAssistant/SearchTreeToolAssistant.java b/Source/mesquite/trees/SearchTreeToolAssistant/SearchTreeToolAssistant.java
new file mode 100644
index 0000000..271c72f
--- /dev/null
+++ b/Source/mesquite/trees/SearchTreeToolAssistant/SearchTreeToolAssistant.java
@@ -0,0 +1,243 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SearchTreeToolAssistant; 
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+
+	/* ======================================================================== */
+	public class SearchTreeToolAssistant extends TreeDisplayAssistantI {
+		TreeSwapper swapTask;
+		NumberForTree numberTask;
+		MesquiteString swapTaskName;
+		MesquiteCommand swapC;
+		MesquiteString numberTaskName;
+		MesquiteCommand numberC;
+		MesquiteBoolean smallerIsBetter = new MesquiteBoolean(true);
+		MesquiteBoolean liveUpdates = new MesquiteBoolean(true);
+		RandomBetween rng = new RandomBetween(System.currentTimeMillis());
+		MesquiteSubmenuSpec treeSwapperSubmenu;
+		MesquiteSubmenuSpec numberTaskSubmenu;
+
+		public Vector extras;
+		public String getFunctionIconPath(){
+			return getPath() + "searchTree.gif";
+		}
+		/*.................................................................................................................*/
+		public boolean startJob(String arguments, Object condition, boolean hiredByName){
+			setUseMenubar(false); //menu available by touching oning button
+			addCheckMenuItem(null, "Minimize Criterion", makeCommand("smallerIsBetter",  this), smallerIsBetter);
+			addCheckMenuItem(null, "Live Updates", makeCommand("liveUpdates",  this), liveUpdates);
+			swapTaskName = new MesquiteString();
+
+			
+			// TODO: have better protection here.
+			
+			MesquiteCommand command = makeCommand("saveLastNumberToFile",  this);		
+			swapC = makeCommand("setSwapTask",  this);
+			if (numModulesAvailable(TreeSwapper.class)>1) {
+				 treeSwapperSubmenu = addSubmenu(null, "Tree Swapper", swapC, TreeSwapper.class);
+			}
+			
+			numberC = makeCommand("setNumberTask",  this);
+			if (numModulesAvailable(NumberForTree.class)>1) {
+				numberTaskSubmenu = addSubmenu(null, "Criterion", numberC, NumberForTree.class);
+			}
+			
+			extras = new Vector();
+			return true;
+		} 
+		
+		/*.................................................................................................................*/
+		public boolean checkEmployeesAreHired(){
+			if (swapTask==null) {
+				swapTask = (TreeSwapper)hireEmployee(TreeSwapper.class, "Tree Rearranger");		
+				if (swapTask==null)
+					return sorry(getName() + " couldn't search because no tree rearranging module was obtained");
+				swapTaskName.setValue(swapTask.getName());
+				swapTask.setHiringCommand(swapC);
+				treeSwapperSubmenu.setSelected(swapTaskName);
+			}
+
+			if (numberTask==null){
+				numberTask = (NumberForTree)hireEmployee(NumberForTree.class, "Criterion used to judge trees");
+				if (numberTask == null)
+					return sorry(getName() + " couldn't search because no calculator module obtained.");
+				numberTaskName = new MesquiteString(numberTask.getName());
+				numberC = makeCommand("setNumberTask",  this);
+				numberTask.setHiringCommand(numberC);
+				numberTaskSubmenu.setSelected(numberTaskName);
+			}
+
+			return true;
+		}
+		/*.................................................................................................................*/
+		public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+			if (checker.compare(this.getClass(), "Sets the objection function that calculates a value for each tree.", "[name of module calculating value]", commandName, "setNumberTask")) {
+				NumberForTree temp = (NumberForTree)replaceEmployee(NumberForTree.class, arguments, "Statistic to calculate for tree", numberTask);
+				if (temp !=null){
+					numberTask = temp;
+					numberTask.setHiringCommand(numberC);
+					//numberTask.initialize(tree, charStates);
+					if (numberTaskName==null)
+						numberTaskName = new MesquiteString(numberTask.getName());
+					else
+						numberTaskName.setValue(numberTask.getName());
+					parametersChanged();
+					return numberTask;
+				}
+			} else if (checker.compare(this.getClass(), "Sets the method of rearrangement of a tree.", "[name of module rearranging tree]", commandName, "setSwapTask")) {
+				TreeSwapper temp = (TreeSwapper)replaceEmployee(TreeSwapper.class, arguments, "Rearranger of tree", swapTask);
+				if (temp !=null){
+					swapTask = temp;
+					swapTask.setHiringCommand(swapC);
+					//numberTask.initialize(tree, charStates);
+					swapTaskName.setValue(swapTask.getName());
+					parametersChanged();
+					return swapTask;
+				}
+			} else if (checker.compare(this.getClass(), "Sets whether the search considers tree with smaller values better", "[on off]", commandName, "smallerIsBetter")) {
+				boolean current = smallerIsBetter.getValue();
+				smallerIsBetter.toggleValue(parser.getFirstToken(arguments));
+			}
+			else if (checker.compare(this.getClass(), "Sets whether tree rearrangements are visible as they happen and whether or not other things that depend upon the tree (e.g., charts, legends) are recalculated as rearrangements happen.", "[on off]", commandName, "liveUpdates")) {
+				boolean current = liveUpdates.getValue();
+				liveUpdates.toggleValue(parser.getFirstToken(arguments));
+			}
+			else
+				return  super.doCommand(commandName, arguments, checker);
+			return null;
+		}
+		/*.................................................................................................................*/
+		public TreeSwapper getTreeSwapper() {
+			return swapTask;
+		}
+		/*.................................................................................................................*/
+		public NumberForTree getNumberTask() {
+				return numberTask;
+		}
+		/*.................................................................................................................*/
+		public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+			SearchTreeToolExtra newPj = new SearchTreeToolExtra(this, treeDisplay);
+			extras.addElement(newPj);
+			return newPj;
+		}
+		/*.................................................................................................................*/
+		public String getName() {
+			return "Search within clade";
+		}
+
+		/*.................................................................................................................*/
+		/** returns an explanation of what the module does.*/
+		public String getExplanation() {
+			return "Supplies a tool for tree windows that searches for a better branch arrangement within clade touched." ;
+		}
+		public boolean isSubstantive(){
+			return false;
+		}   	 
+		public boolean isPrerelease(){
+			return true;
+		}   	 
+		public boolean getSmallerIsBetter(){
+			return smallerIsBetter.getValue();
+		}
+		public boolean getLiveUpdates(){
+			return liveUpdates.getValue();
+		}
+		/*.................................................................................................................*/
+		/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+		 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+		 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+		public int getVersionOfFirstRelease(){
+			return 201;  
+		}
+
+	}
+
+	/* ======================================================================== */
+	class SearchTreeToolExtra extends TreeDisplayExtra implements Commandable  {
+		TreeTool searchTreeTool;
+		SearchTreeToolAssistant ownerModule;
+		MesquiteCommand searchTreeCommand;
+		AdjustableTree tree = null;
+		RandomBetween rng = new RandomBetween(System.currentTimeMillis());
+		TreeOptimizer treeOptimizer;
+
+		public SearchTreeToolExtra (SearchTreeToolAssistant ownerModule, TreeDisplay treeDisplay) {
+			super(ownerModule, treeDisplay);
+			this.ownerModule = ownerModule;
+			searchTreeCommand = MesquiteModule.makeCommand("searchTree",  this);
+			searchTreeTool = new TreeTool(this, "randomlyRotate", ownerModule.getPath(),"searchTree.gif", 4,14,"Search within clade", "This tool is used to search for a better branch arrangement within the clade touched.");
+			searchTreeTool.setTouchedCommand(searchTreeCommand);
+			if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+				((MesquiteWindow)ownerModule.containerOfModule()).addTool(searchTreeTool);
+				searchTreeTool.setPopUpOwner(ownerModule);
+			}
+			treeOptimizer =new TreeOptimizer(ownerModule,  ownerModule.getNumberTask(),ownerModule.getTreeSwapper());
+		}
+		/*.................................................................................................................*/
+		public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		}
+
+		/*.................................................................................................................*/
+		public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+			drawOnTree(tree, drawnRoot, g);
+		}
+		/*.................................................................................................................*/
+		public   void setTree(Tree tree) {
+			if (tree instanceof AdjustableTree)
+				this.tree = (AdjustableTree)tree;
+			else this.tree =null;
+		}
+		MesquiteInteger pos = new MesquiteInteger();
+		/*.................................................................................................................*/
+		public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+			if (checker.compare(this.getClass(), "Searches for rearrangements in the clade that yield a better tree as judged by the objective function values.", "[branch number]", commandName, "searchTree")) {
+				if (!ownerModule.checkEmployeesAreHired())
+					return null;
+				
+				pos.setValue(0);
+				
+				int branchFound= MesquiteInteger.fromString(arguments,pos);
+				MesquiteString resultString = new MesquiteString();
+				treeOptimizer.setSwapTask(ownerModule.getTreeSwapper());
+				treeOptimizer.setNumberTask(ownerModule.getNumberTask());
+				treeOptimizer.setBiggerIsBetter(!ownerModule.getSmallerIsBetter());
+				treeOptimizer.setLiveUpdates(ownerModule.getLiveUpdates());
+				treeOptimizer.setNotify(true);
+				treeOptimizer.searchForBetterTree(tree, branchFound, rng, resultString);
+
+				//	TreeSearchUtil.searchForBetterTree(ownerModule,  tree,  branchFound, ownerModule.getTreeSwapper(),  ownerModule.getNumberTask(),  rng,  resultString,  ownerModule.getSmallerIsBetter(),  ownerModule.getLiveUpdates(),  true);
+			//	TreeSearchUtil.searchForBetterTree(ownerModule,  tree,  branchFound, 30000,false,false,ownerModule.getTreeSwapper(),  ownerModule.getNumberTask(),  rng,  resultString,  ownerModule.getSmallerIsBetter(),  ownerModule.getLiveUpdates(),  true,true,false);
+
+			}
+			return null;
+		}
+		public void turnOff() {
+			ownerModule.extras.removeElement(this);
+			super.turnOff();
+		}
+		
+
+	}
+
+
diff --git a/Source/mesquite/trees/SearchTreeToolAssistant/searchTree.gif b/Source/mesquite/trees/SearchTreeToolAssistant/searchTree.gif
new file mode 100644
index 0000000..008cb27
Binary files /dev/null and b/Source/mesquite/trees/SearchTreeToolAssistant/searchTree.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/32select.gif b/Source/mesquite/trees/SelectBranches/32select.gif
new file mode 100644
index 0000000..5675688
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/32select.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/32selectClade.gif b/Source/mesquite/trees/SelectBranches/32selectClade.gif
new file mode 100644
index 0000000..7d10d0b
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/32selectClade.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/64select.gif b/Source/mesquite/trees/SelectBranches/64select.gif
new file mode 100644
index 0000000..e8834b9
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/64select.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/64selectClade.gif b/Source/mesquite/trees/SelectBranches/64selectClade.gif
new file mode 100644
index 0000000..52fd863
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/64selectClade.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/SelectBranches.java b/Source/mesquite/trees/SelectBranches/SelectBranches.java
new file mode 100644
index 0000000..844590a
--- /dev/null
+++ b/Source/mesquite/trees/SelectBranches/SelectBranches.java
@@ -0,0 +1,427 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SelectBranches;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectBranches extends TreeDisplayAssistantI {
+	public Vector extras;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Select Branches");
+		addItemToSubmenu(null, mss, "Select All Branches", makeCommand("selectAll",  this));
+		addItemToSubmenu(null, mss, "Invert Selection", makeCommand("invertSelection",  this));
+		addItemToSubmenu(null, mss, "Zero-length Branches", makeCommand("selectZero",  this));
+		addItemToSubmenu(null, mss, "Negative-length Branches", makeCommand("selectNeg",  this));
+		addItemToSubmenu(null, mss, "Branches of Unassigned Length", makeCommand("selectUnassignedLength",  this));
+		addItemToSubmenu(null, mss, "Internal Branches", makeCommand("selectInternal",  this));
+		addItemToSubmenu(null, mss, "Terminal Branches", makeCommand("selectTerminal",  this));
+		addItemToSubmenu(null, mss, "Polytomous Nodes", makeCommand("selectPolytomies",  this));
+		addItemToSubmenu(null, mss, "Unbranched Internals", makeCommand("selectUnbranched",  this));
+		addItemToSubmenu(null, mss, "Root", makeCommand("selectRoot",  this));
+		return true;
+	} 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	private void invertSelection(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			invertSelection(tree, daughter);
+		}
+		tree.setSelected(node, !tree.getSelected(node));
+	}
+	/*.................................................................................................................*/
+	private void selectZero(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectZero(tree, daughter);
+		}
+		if (tree.getBranchLength(node) == 0.0)
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectNeg(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectNeg(tree, daughter);
+		}
+		if (tree.getBranchLength(node) < 0.0)
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectUnassignedLength(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectUnassignedLength(tree, daughter);
+		}
+		if (tree.branchLengthUnassigned(node))
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectInternal(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectInternal(tree, daughter);
+		}
+		if (tree.nodeIsInternal(node))
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectTerminal(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectTerminal(tree, daughter);
+		}
+		if (tree.nodeIsTerminal(node))
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectPolytomies(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectPolytomies(tree, daughter);
+		}
+		if (tree.nodeIsPolytomous(node))
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	private void selectUnbranched(MesquiteTree tree, int node){
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectUnbranched(tree, daughter);
+		}
+		if (tree.nodeIsUnbranchedInternal(node))
+			tree.setSelected(node, true);
+		else
+			tree.setSelected(node, false);
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Inverts selection of branches", null, commandName, "invertSelection")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					invertSelection((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects all branches", null, commandName, "selectAll")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					((MesquiteTree)tree).deselectAll();
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects zero-length branches", null, commandName, "selectZero")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectZero((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects negative-length branches", null, commandName, "selectNeg")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectNeg((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects branches of unassigned length", null, commandName, "selectUnassignedLength")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectUnassignedLength((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects internal branches", null, commandName, "selectInternal")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectInternal((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects terminal branches", null, commandName, "selectTerminal")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectTerminal((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects polytomous nodes", null, commandName, "selectPolytomies")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectPolytomies((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects unbranched internal nodes", null, commandName, "selectUnbranched")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					selectUnbranched((MesquiteTree)tree, tree.getRoot());
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects root", null, commandName, "selectRoot")) {
+			for (int i =0; i<extras.size(); i++){
+				TreeDisplayExtra e = (TreeDisplayExtra)extras.elementAt(i);
+				Tree tree = e.getTreeDisplay().getTree();
+				if (tree instanceof MesquiteTree){
+					((MesquiteTree)tree).deselectAll();
+					((MesquiteTree)tree).setSelected(tree.getRoot(), true);
+					((MesquiteTree)tree).notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		SelectToolExtra newPj = new SelectToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Select Branches";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool and menu with which to select branches in a tree window.";
+	}
+	public void getSubfunctions(){
+		registerSubfunction(new FunctionExplanation("Select Branch", "(A tool of the Tree Window) Selects the touched branch", null, getPath() + "select.gif"));
+		registerSubfunction(new FunctionExplanation("Select Clade", "(A tool of the Tree Window) Selects the touched clade", null, getPath() + "selectClade.gif"));
+		super.getSubfunctions();
+	}
+}
+
+/* ======================================================================== */
+class SelectToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool selectCladeTool;//selectTool, 
+	MesquiteMenuItemSpec hideMenuItem = null;
+	SelectBranches selectModule;
+	MesquiteTree tree;
+
+	public SelectToolExtra (SelectBranches ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		selectModule = ownerModule;
+		/*selectTool = new TreeTool(this, "SelectBranches", ownerModule.getPath(), "select.gif", 5,3,"Select Branch", "This tool is used to select branches.  By holding down the Control key as you click, branch selection will accumulate.  By holding down the Shift key, the smallest clade containing the touched branch and already-selected branches will be selected.");
+		selectTool.setTouchedCommand(MesquiteModule.makeCommand("selectBranch",  this));
+		selectTool.setTouchedFieldCommand(MesquiteModule.makeCommand("deselectAllBranches",  this));*/
+		selectCladeTool = new TreeTool(this, "SelectClade", ownerModule.getPath(), "selectClade.gif", 9,7,"Select Clade", "This tool is used to select clades.  By holding down the Control key as you click, clade selection will accumulate.  By holding down the Shift key, the smallest clade containing the touched clade and already-selected clades will be selected.");
+		selectCladeTool.setTouchedCommand(MesquiteModule.makeCommand("selectClade",  this));
+		selectCladeTool.setTouchedFieldCommand(MesquiteModule.makeCommand("deselectAllBranches",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			//((MesquiteWindow)ownerModule.containerOfModule()).addTool(selectTool);
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(selectCladeTool);
+		}
+	}
+	/*.................................................................................................................*/
+	private void wrapSelections(MesquiteTree tree, int node, boolean selectedBelow){
+		if (selectedBelow)
+			tree.setSelected(node, true);
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			wrapSelections(tree, daughter, selectedBelow || tree.getSelected(node));
+		}
+	}
+	/*.................................................................................................................*/
+	private void selectedTwiceAbove(MesquiteTree tree, int node){
+		int numSelectedAbove = 0;
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			selectedTwiceAbove(tree, daughter);
+			if (tree.anySelectedInClade(daughter))
+				numSelectedAbove ++;
+		}
+		if (numSelectedAbove>1)
+			tree.setSelected(node, true);
+	}
+	/*.................................................................................................................*/
+	private void shrinkWrapSelections(MesquiteTree tree, int node){
+		selectedTwiceAbove(tree, node);
+		wrapSelections(tree, node, false);
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		//remember which selected
+		return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Sets the selection on the branch (if the control modifier is passed, then selection accumulates unless the branch touched is already selected; if the shift modifier is passed, then selection accumulates and the smallest clade containing all selected nodes is selected.", "[node number][x coordinate][y coordinate][modifiers]", commandName, "selectBranch")) {
+			if (tree == null)
+				return null;
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (arguments.indexOf("shift")>=0) {  //select smallest containing clade
+				tree.setSelected(branchFound, !tree.getSelected(branchFound));
+				shrinkWrapSelections(tree, tree.getRoot());
+				tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(true);
+			}
+			else if (arguments.indexOf("control")>=0) {  //single accumulate selection
+				tree.setSelected(branchFound, !tree.getSelected(branchFound));
+				tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(true);
+			}
+			else if (branchFound >0) {
+				/*if (tree.getSelected(branchFound)) {
+		   			tree.deselectAll();
+		   			tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+		   			treeDisplay.pleaseUpdate(true);
+	   				//treeDisplay.getTreeDrawing().setHighlightsOn(false);
+	   			}
+	   			else {*/
+				tree.deselectAll();
+				tree.setSelected(branchFound, true);
+				tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+				treeDisplay.pleaseUpdate(true);
+				//treeDisplay.getTreeDrawing().setHighlightsOn(true);
+				//}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deselects all branches",  null, commandName, "deselectAllBranches")) {
+			if (tree == null)
+				return null;
+			tree.deselectAll();
+			tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+			treeDisplay.pleaseUpdate(true);
+
+		}
+		else if (checker.compare(this.getClass(), "Sets selection to entire clade above node touched (selection accumlates if shift or control modifiers passed)",  "[node number][x coordinate][y coordinate][modifiers]", commandName, "selectClade")) {
+			if (tree == null)
+				return null;
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (arguments.indexOf("shift")>=0) {  //select smallest containing clade
+				selectClade(tree, branchFound, !tree.getSelected(branchFound));
+				shrinkWrapSelections(tree, tree.getRoot());
+				tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(true);
+			}
+			else if (arguments.indexOf("control")>=0) {  //single accumulate selection
+				selectClade(tree, branchFound, !tree.getSelected(branchFound));
+				tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(true);
+			}
+			else if (branchFound >0) {
+				if (tree.getSelected(branchFound)) { //deselect only if just this clade selected
+					selectClade(tree, branchFound, false);
+					if (tree.anySelected()) {
+						tree.deselectAll();
+						selectClade(tree, branchFound, true);
+					}
+					tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+					treeDisplay.pleaseUpdate(true);
+				}
+				else {
+					tree.deselectAll();
+					selectClade(tree, branchFound, true);
+					tree.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+					treeDisplay.pleaseUpdate(true);
+				}
+			}
+		}
+		return null;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether there are any selected nodes in the clade */
+	private void selectClade(MesquiteTree tree, int node, boolean select) {
+		tree.setSelected(node, select);
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			selectClade(tree, d, select);
+		}
+	}
+	public void turnOff() {
+		selectModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/trees/SelectBranches/select.gif b/Source/mesquite/trees/SelectBranches/select.gif
new file mode 100644
index 0000000..20d3b69
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/select.gif differ
diff --git a/Source/mesquite/trees/SelectBranches/selectClade.gif b/Source/mesquite/trees/SelectBranches/selectClade.gif
new file mode 100644
index 0000000..8edde0e
Binary files /dev/null and b/Source/mesquite/trees/SelectBranches/selectClade.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/32selectTaxa.gif b/Source/mesquite/trees/SelectTaxaInClade/32selectTaxa.gif
new file mode 100644
index 0000000..41782f1
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/32selectTaxa.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/32selectTaxaInClade.gif b/Source/mesquite/trees/SelectTaxaInClade/32selectTaxaInClade.gif
new file mode 100644
index 0000000..ee1ae62
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/32selectTaxaInClade.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/64selectTaxa.gif b/Source/mesquite/trees/SelectTaxaInClade/64selectTaxa.gif
new file mode 100644
index 0000000..02d2fef
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/64selectTaxa.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/64selectTaxaInClade.gif b/Source/mesquite/trees/SelectTaxaInClade/64selectTaxaInClade.gif
new file mode 100644
index 0000000..ecaaa66
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/64selectTaxaInClade.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/SelectTaxaInClade.java b/Source/mesquite/trees/SelectTaxaInClade/SelectTaxaInClade.java
new file mode 100644
index 0000000..f31e0d0
--- /dev/null
+++ b/Source/mesquite/trees/SelectTaxaInClade/SelectTaxaInClade.java
@@ -0,0 +1,263 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SelectTaxaInClade;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SelectTaxaInClade extends TreeDisplayAssistantI {
+	public Vector extras;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		extras = new Vector();
+		return true;
+	} 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		SelectTaxaToolExtra newPj = new SelectTaxaToolExtra(this, treeDisplay);
+		extras.addElement(newPj);
+		return newPj;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Select Taxa";
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Provides a tool with which to select taxa in a clade in a tree window.";
+	}
+	public void getSubfunctions(){
+		//registerSubfunction(new FunctionExplanation("Select Taxa", "(A tool of the Tree Window) Selects the touched terminal taxa", null, getPath() + "selectTaxa.gif"));
+		registerSubfunction(new FunctionExplanation("Select Taxa in Clade", "(A tool of the Tree Window) Selects all terminal taxa in the clade of the node touched", null, getPath() + "selectTaxaInClade.gif"));
+		super.getSubfunctions();
+	}
+}
+
+/* ======================================================================== */
+class SelectTaxaToolExtra extends TreeDisplayExtra implements Commandable  {
+	TreeTool selectCladeTool; //, selectTool;
+	SelectTaxaInClade selectModule;
+	MesquiteTree tree;
+
+	public SelectTaxaToolExtra (SelectTaxaInClade ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		selectModule = ownerModule;
+		/*selectTool = new TreeTool(this, "SelectTaxa", ownerModule.getPath(), "selectTaxa.gif", 8,6,"Select Taxa", "This tool is used to select terminal taxa.  By holding down the Control key as you click, selection will accumulate.  By holding down the Shift key, the taxa in the smallest clade containing the touched taxon and already-selected taxa will be selected.");
+		selectTool.setTouchedTaxonCommand(MesquiteModule.makeCommand("selectTaxa",  this));
+		selectTool.setTouchedFieldCommand(MesquiteModule.makeCommand("deselectAllTaxa",  this));
+		*
+		*/
+		selectCladeTool = new TreeTool(this, "SelectTaxaInClade", ownerModule.getPath(), "selectTaxaInClade.gif", 8,6,"Select Taxa In Clade", "This tool is used to select terminal taxa within clades.  By holding down the Control key as you click, selection will accumulate.  By holding down the Shift key, the taxa in the smallest clade containing the touched branch and already-selected taxa will be selected.");
+		selectCladeTool.setTouchedCommand(MesquiteModule.makeCommand("selectTaxaInClade",  this));
+		selectCladeTool.setTouchedFieldCommand(MesquiteModule.makeCommand("deselectAllTaxa",  this));
+		if (ownerModule.containerOfModule() instanceof MesquiteWindow) {
+			//((MesquiteWindow)ownerModule.containerOfModule()).addTool(selectTool);
+			((MesquiteWindow)ownerModule.containerOfModule()).addTool(selectCladeTool);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		if (tree instanceof MesquiteTree)
+			this.tree = (MesquiteTree)tree;
+		else
+			this.tree = null;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		//remember which selected
+		return null;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+
+		if (checker.compare(this.getClass(), "Sets selected taxa to those in clade above node touched (selection accumulates if control or shift modifiers passed)",  "[node number][x coordinate][y coordinate][modifiers]", commandName, "selectTaxaInClade")) {
+			if (tree == null)
+				return null;
+			Taxa taxa = tree.getTaxa();
+			int branchFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (arguments.indexOf("shift")>=0) {  //select smallest containing clade
+				selectClade(tree, branchFound, true);
+				shrinkWrapSelections(tree, tree.getRoot());
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (arguments.indexOf("control")>=0) {  //single accumulate selection
+				if (allSelected(tree, branchFound))
+					selectClade(tree, branchFound, false);
+				else
+					selectClade(tree, branchFound, true);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (branchFound >0) {
+				taxa.deselectAll();
+				selectClade(tree, branchFound, true);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+				treeDisplay.pleaseUpdate(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Selects taxa (selection accumulates if control or shift modifiers passed)",  "[taxon number][x coordinate][y coordinate][modifiers]", commandName, "selectTaxa")) {
+			if (tree == null)
+				return null;
+			Taxa taxa = tree.getTaxa();
+			int taxonFound= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(taxonFound))
+				return null;
+			if (arguments.indexOf("shift")>=0) {  //select smallest containing clade
+				selectTaxon(taxa, taxonFound, true);
+				shrinkWrapSelections(tree, tree.getRoot());
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (arguments.indexOf("control")>=0) {  //toggle selection of that taxon
+
+				selectTaxon(taxa, taxonFound, !taxa.getSelected(taxonFound));
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+				treeDisplay.pleaseUpdate(false);
+			}
+			else if (taxonFound >=0) {
+				taxa.deselectAll();
+				selectTaxon(taxa, taxonFound, true);
+				taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+				treeDisplay.pleaseUpdate(false);
+			}
+		}
+		else if (checker.compare(this.getClass(), "Deselects all taxa",  null, commandName, "deselectAllTaxa")) {
+			if (tree == null)
+				return null;
+			Taxa taxa = tree.getTaxa();
+			taxa.deselectAll();
+			taxa.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
+
+			treeDisplay.pleaseUpdate(false);
+
+		}
+		return null;
+	}
+	/*-----------------------------------------*/
+	/** Selects or deselects all nodes in the clade */
+	private void selectTaxon(Taxa taxa, int it, boolean select) {
+		taxa.setSelected(it, select);
+	}
+	/*-----------------------------------------*/
+	/** Selects or deselects all nodes in the clade */
+	private void selectClade(MesquiteTree tree, int node, boolean select) {
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			tree.getTaxa().setSelected(t, select);
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			selectClade(tree, d, select);
+		}
+	}
+	/*-----------------------------------------*/
+	/** Returns whether all nodes in clade selected */
+	private boolean allSelected(MesquiteTree tree, int node) {
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			return (tree.getTaxa().getSelected(t));
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (!allSelected(tree, d))
+				return false;
+		}
+		return true;
+	}
+	/*-----------------------------------------*/
+	/** Returns whether all nodes in clade selected */
+	private boolean anySelected(MesquiteTree tree, int node) {
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			return (tree.getTaxa().getSelected(t));
+		}
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+			if (anySelected(tree, d))
+				return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	private void wrapSelections(MesquiteTree tree, int node, boolean selectedBelow){
+		if (tree.nodeIsTerminal(node)){
+			if (selectedBelow){
+				int t = tree.taxonNumberOfNode(node);
+				tree.getTaxa().setSelected(t, true);
+			}
+			return;
+		}
+		boolean selectAbove = selectedBelow || selectedTwiceAbove(tree, node);
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			wrapSelections(tree, daughter, selectAbove);
+		}
+	}
+	/*.................................................................................................................*/
+	private boolean selectedTwiceAbove(MesquiteTree tree, int node){
+		if (tree.nodeIsTerminal(node)){
+			int t = tree.taxonNumberOfNode(node);
+			return (tree.getTaxa().getSelected(t));
+		}
+		int numSelectedAbove = 0;
+		for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) {
+			if (anySelected(tree, daughter))
+				numSelectedAbove ++;
+		}
+		return (numSelectedAbove>1);
+	}
+	/*.................................................................................................................*/
+	private void shrinkWrapSelections(MesquiteTree tree, int node){
+		wrapSelections(tree, node, false);
+	}
+	public void turnOff() {
+		selectModule.extras.removeElement(this);
+		super.turnOff();
+	}
+}
+
+
+
+
diff --git a/Source/mesquite/trees/SelectTaxaInClade/selectTaxa.gif b/Source/mesquite/trees/SelectTaxaInClade/selectTaxa.gif
new file mode 100644
index 0000000..be14aad
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/selectTaxa.gif differ
diff --git a/Source/mesquite/trees/SelectTaxaInClade/selectTaxaInClade.gif b/Source/mesquite/trees/SelectTaxaInClade/selectTaxaInClade.gif
new file mode 100644
index 0000000..bd80dc2
Binary files /dev/null and b/Source/mesquite/trees/SelectTaxaInClade/selectTaxaInClade.gif differ
diff --git a/Source/mesquite/trees/SetAssumptionDefault/SetAssumptionDefault.java b/Source/mesquite/trees/SetAssumptionDefault/SetAssumptionDefault.java
new file mode 100644
index 0000000..bdbeebb
--- /dev/null
+++ b/Source/mesquite/trees/SetAssumptionDefault/SetAssumptionDefault.java
@@ -0,0 +1,56 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetAssumptionDefault;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetAssumptionDefault extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null) {
+			tree.setPolytomiesAssumption(2, false);
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set Polytomy Assumption to Default";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets assumption that any polytomies in the tree are whatever is current default (which can be set in the submenu File>Defaults>Tree Defaults)." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetAssumptionHard/SetAssumptionHard.java b/Source/mesquite/trees/SetAssumptionHard/SetAssumptionHard.java
new file mode 100644
index 0000000..c175a29
--- /dev/null
+++ b/Source/mesquite/trees/SetAssumptionHard/SetAssumptionHard.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetAssumptionHard;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetAssumptionHard extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null) {
+			tree.setPolytomiesAssumption(0, false);
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set Polytomy Assumption to Hard";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets assumption that any polytomies in the tree are hard." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetAssumptionSoft/SetAssumptionSoft.java b/Source/mesquite/trees/SetAssumptionSoft/SetAssumptionSoft.java
new file mode 100644
index 0000000..6a1ecff
--- /dev/null
+++ b/Source/mesquite/trees/SetAssumptionSoft/SetAssumptionSoft.java
@@ -0,0 +1,56 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetAssumptionSoft;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetAssumptionSoft extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null) {
+			tree.setPolytomiesAssumption(1, false);
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set Polytomy Assumption to Soft";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets assumption that any polytomies in the tree are soft." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetBranchLengths/SetBranchLengths.java b/Source/mesquite/trees/SetBranchLengths/SetBranchLengths.java
new file mode 100644
index 0000000..cda2c3e
--- /dev/null
+++ b/Source/mesquite/trees/SetBranchLengths/SetBranchLengths.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetBranchLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetBranchLengths extends BranchLengthsAltererMult {
+	double resultNum;
+	double scale = 0;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		MesquiteDouble io = new MesquiteDouble(1.0);
+		boolean OK = QueryDialogs.queryDouble(containerOfModule(), "Set branch lengths", "Set all branch lengths to", io);
+		if (!OK)
+			return false;
+
+		scale = io.getValue();
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+	 		if ((MesquiteDouble.impossible != scale) && tree instanceof MesquiteTree) {
+   				((MesquiteTree)tree).setAllBranchLengths(scale, false);
+				if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+				return true;
+			}
+			return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Assign All Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Assign All Branch Lengths...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Assigns a value for branch length for all of a tree's branches." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetBranchLengthsFromNames/SetBranchLengthsFromNames.java b/Source/mesquite/trees/SetBranchLengthsFromNames/SetBranchLengthsFromNames.java
new file mode 100644
index 0000000..0c2cb16
--- /dev/null
+++ b/Source/mesquite/trees/SetBranchLengthsFromNames/SetBranchLengthsFromNames.java
@@ -0,0 +1,79 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetBranchLengthsFromNames;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetBranchLengthsFromNames extends BranchLengthsAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree instanceof MesquiteTree) {
+			int numNodes = tree.getNumNodeSpaces();
+
+			for (int i=0; i<numNodes; i++)  {
+				String s = tree.getNodeLabel(i);
+				double length = MesquiteDouble.fromString(s);
+				if (MesquiteDouble.isCombinable(length))
+						((MesquiteTree)tree).setBranchLength(i,length,false);
+				else
+					((MesquiteTree)tree).setBranchLength(i,MesquiteDouble.unassigned,false);
+
+			}
+			if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Assign Branch Lengths From Node Names";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Assigns a value for branch length for all of a tree's branches based upon node names that represent numbers." ;
+   	 }
+ 	/*.................................................................................................................*/
+ 	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+ 	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+ 	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+ 	public int getVersionOfFirstRelease(){
+		return 201;  
+ 	}
+}
+
diff --git a/Source/mesquite/trees/SetBranchLengthsIfLessThan/SetBranchLengthsIfLessThan.java b/Source/mesquite/trees/SetBranchLengthsIfLessThan/SetBranchLengthsIfLessThan.java
new file mode 100644
index 0000000..3e6897c
--- /dev/null
+++ b/Source/mesquite/trees/SetBranchLengthsIfLessThan/SetBranchLengthsIfLessThan.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+/*Oliver May '08*/
+
+package mesquite.trees.SetBranchLengthsIfLessThan;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+public class SetBranchLengthsIfLessThan extends BranchLengthsAltererMult {
+	MesquiteDouble assignLength;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		assignLength = new MesquiteDouble(0.0000001);
+		if(!MesquiteThread.isScripting()){
+			double tempL = MesquiteDouble.queryDouble(containerOfModule(), "Set Length", "Enter length to assign to branches with lengths less than or equal to zero:", assignLength.getValue());
+			if(MesquiteDouble.isCombinable(tempL))
+				assignLength.setValue(tempL);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+  	 	return true;
+  	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+ 	/*.................................................................................................................*/
+	public boolean requestPrimaryChoice(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		setLengths(tree, tree.getRoot());
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+			return true;
+	}
+	/*.................................................................................................................*/
+	private void setLengths(AdjustableTree tree, int node){
+		if(tree.getBranchLength(node) <= 0 && MesquiteDouble.isCombinable(tree.getBranchLength(node))){
+			tree.setBranchLength(node, assignLength.getValue(), false);
+		}
+		for(int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)){
+			setLengths(tree, daughter);
+		}
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Assign Branch Lengths Less than or Equal to Zero...";
+	}
+ 	/*.................................................................................................................*/
+	public String getExplanation(){
+		return "Assigns a user-provided value to all branches with lengths less than or equal to zero.";
+	}
+}
diff --git a/Source/mesquite/trees/SetSelBranchLengths/SetSelBranchLengths.java b/Source/mesquite/trees/SetSelBranchLengths/SetSelBranchLengths.java
new file mode 100644
index 0000000..6d5e304
--- /dev/null
+++ b/Source/mesquite/trees/SetSelBranchLengths/SetSelBranchLengths.java
@@ -0,0 +1,72 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetSelBranchLengths;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetSelBranchLengths extends BranchLengthsAlterer {
+	double scale = MesquiteDouble.impossible;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+			MesquiteDouble io = new MesquiteDouble(1.0);
+			boolean OK = QueryDialogs.queryDouble(containerOfModule(), "Set lengths of selected branches", "Set lengths of selected branches to", io);
+			if (!OK)
+				return false;
+
+ 		scale = io.getValue();
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+   
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+  	 		if ((MesquiteDouble.impossible != scale) && tree instanceof MesquiteTree) {
+   				((MesquiteTree)tree).doCommand("setLengthSelectedBranches", MesquiteDouble.toString(scale), CommandChecker.defaultChecker);
+				if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+				return true;
+			}
+			return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Assign Selected Branch Lengths";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameForMenuItem() {
+		return "Assign Selected Branch Lengths...";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Assigns a value for branch length for all of a tree's selected branches." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetToArbitrarySymmetrical/SetToArbitrarySymmetrical.java b/Source/mesquite/trees/SetToArbitrarySymmetrical/SetToArbitrarySymmetrical.java
new file mode 100644
index 0000000..06c33b1
--- /dev/null
+++ b/Source/mesquite/trees/SetToArbitrarySymmetrical/SetToArbitrarySymmetrical.java
@@ -0,0 +1,82 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SetToArbitrarySymmetrical;
+
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetToArbitrarySymmetrical extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return false;  
+	}
+  	 void formSymmetricalClade(AdjustableTree tree, int minTaxon, int maxTaxon){
+		int range = maxTaxon-minTaxon + 1;
+		if (range > 1) {
+			int newRight = minTaxon + range/2;
+			tree.splitTerminal(minTaxon, newRight, false);
+			formSymmetricalClade(tree, minTaxon, newRight -1);
+			formSymmetricalClade(tree, newRight, maxTaxon);
+		}
+  	 }
+	/*.................................................................................................................*/
+	public  boolean  transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree==null)
+			return false;
+		Taxa taxa = tree.getTaxa();
+		int numTaxa = taxa.getNumTaxa();
+		if (numTaxa == 1){
+			tree.setToDefaultBush(1, false);
+			return true;
+		}
+		tree.setToDefaultBush(2, false);
+		int secondHalf = numTaxa/2;
+		int rightNode = tree.nextSisterOfNode(tree.firstDaughterOfNode(tree.getRoot()));
+		tree.setTaxonNumber(rightNode, secondHalf, false);
+		formSymmetricalClade(tree, 0, secondHalf-1);
+		formSymmetricalClade(tree, secondHalf, tree.getTaxa().getNumTaxa()-1);
+		tree.setName("Default symmetrical");
+		return true;
+		
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 304;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Set to Arbitrary Symmetrical";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sets the tree to an arbitrary symmetrical tree." ;
+	}
+}
+
diff --git a/Source/mesquite/trees/SetToLadderized/SetToLadderized.java b/Source/mesquite/trees/SetToLadderized/SetToLadderized.java
new file mode 100644
index 0000000..062dd36
--- /dev/null
+++ b/Source/mesquite/trees/SetToLadderized/SetToLadderized.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+ 
+ Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+ The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+ Perhaps with your help we can be more than a few, and make Mesquite better.
+ 
+ Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+ Mesquite's web site is http://mesquiteproject.org
+ 
+ This source code and its compiled class files are free and modifiable under the terms of 
+ GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SetToLadderized;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetToLadderized extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public  boolean  transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null && (tree instanceof MesquiteTree)) {
+			((MesquiteTree)tree).standardize(tree.getRoot(), true, notify);
+			return true;
+		}
+		return false;
+		
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 110;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Right-Ladderize Tree";
+	}
+	/*.................................................................................................................*/
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Sets the tree to its ladderized (right) version." ;
+	}
+}
+
diff --git a/Source/mesquite/trees/SetToRooted/SetToRooted.java b/Source/mesquite/trees/SetToRooted/SetToRooted.java
new file mode 100644
index 0000000..ff9995d
--- /dev/null
+++ b/Source/mesquite/trees/SetToRooted/SetToRooted.java
@@ -0,0 +1,54 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetToRooted;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetToRooted extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null) {
+			tree.setRooted(true, false);
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Root tree";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets the tree to rooted." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetToUnrooted/SetToUnrooted.java b/Source/mesquite/trees/SetToUnrooted/SetToUnrooted.java
new file mode 100644
index 0000000..7953ca9
--- /dev/null
+++ b/Source/mesquite/trees/SetToUnrooted/SetToUnrooted.java
@@ -0,0 +1,55 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetToUnrooted;
+
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetToUnrooted extends TreeAltererMult {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean  transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		if (tree!=null) {
+			tree.setRooted(false, false);
+			if (tree instanceof Listened && notify) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			return true;
+		}
+		return false;
+		
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Unroot tree";
+   	 }
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Sets the tree to unrooted." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/SetTreeDefaults/SetTreeDefaults.java b/Source/mesquite/trees/SetTreeDefaults/SetTreeDefaults.java
new file mode 100644
index 0000000..e4cb739
--- /dev/null
+++ b/Source/mesquite/trees/SetTreeDefaults/SetTreeDefaults.java
@@ -0,0 +1,154 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SetTreeDefaults;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.CharacterData;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SetTreeDefaults extends DefaultsAssistant {
+	MesquiteBoolean polytomiesHard, convertInternalNames; //, warnReticulations;
+	static boolean changed = false;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		polytomiesHard = new MesquiteBoolean(true);
+		convertInternalNames  = new MesquiteBoolean(false);
+		//warnReticulations = new MesquiteBoolean(true);
+		loadPreferences();
+
+		MesquiteSubmenuSpec treeDefaultsSubmenu = addSubmenuToDefaults("Tree Defaults");
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.defaultsSubmenu, treeDefaultsSubmenu, "Polytomies Hard by Default", makeCommand("polytomiesHard",  this), polytomiesHard);
+		MesquiteTrunk.mesquiteTrunk.addCheckMenuItemToSubmenu(MesquiteTrunk.defaultsSubmenu,  treeDefaultsSubmenu, "Convert Internal Names to Notes", makeCommand("convertInternalNames",  this), convertInternalNames);
+		
+		//addCheckMenuItemToSubmenu(null,  mss, "Warn with Reticulations", makeCommand("warnReticulations",  this), warnReticulations);
+		return true;
+  	 }
+	public void processPreferencesFromFile (String[] prefs) {
+		if (prefs!=null && prefs.length>0) {
+			if (!changed) {
+				if (prefs[0].equals("soft") && polytomiesHard.getValue()) {
+					polytomiesHard.setValue(false);
+					MesquiteTree.polytomyDefaultHard = false;
+					MesquiteModule.mesquiteTrunk.classFieldChanged(Tree.class, "polytomyDefaultHard");
+				}
+				if (prefs.length>1){
+					MesquiteTree.convertInternalNames = prefs[1].equals("convertInternalNames");
+				}
+				/*
+    	 			if (prefs.length>2){
+					   MesquiteTree.warnReticulations = prefs[2].equals("warnReticulations");
+				 }
+				 */
+	
+			}
+		}
+	}
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("polytomiesHard".equalsIgnoreCase(tag)){
+			polytomiesHard.setValue(content);
+			MesquiteTree.polytomyDefaultHard = polytomiesHard.getValue();
+
+			MesquiteModule.mesquiteTrunk.classFieldChanged(Tree.class, "polytomyDefaultHard");
+		
+		}
+		else if ("convertInternalNames".equalsIgnoreCase(tag)){
+			convertInternalNames.setValue(content);
+			MesquiteTree.convertInternalNames = convertInternalNames.getValue();
+		}
+	}
+	
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer();
+		StringUtil.appendXMLTag(buffer, 2, "polytomiesHard", polytomiesHard);  
+		StringUtil.appendXMLTag(buffer, 2, "convertInternalNames", convertInternalNames);  
+		return buffer.toString();
+	}
+	/*.................................................................................................................*
+	public String[] preparePreferencesForFile () {
+		String pString, cString;
+		if (polytomiesHard.getValue())
+			pString = "hard";
+		else
+			pString = "soft";
+		if (convertInternalNames.getValue())
+			cString = "convertInternalNames";
+		else
+			cString = "noconvertInternalNames";
+		
+		return (new String[] {pString, cString}); //, wString
+	}
+	
+
+
+	*/
+	
+	
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets universal, Mesquite-wide setting whether polytomies are hard or soft by default", "[on = polytomies hard; off = soft]", commandName, "polytomiesHard")) {  
+    	 		boolean current = polytomiesHard.getValue();
+    	 		polytomiesHard.toggleValue(parser.getFirstToken(arguments));
+    	 		if (current!=polytomiesHard.getValue()) {
+    	 			MesquiteTree.polytomyDefaultHard = polytomiesHard.getValue();
+    	 			//tell all modules that default has changed  classFieldChanged(Class class, String fieldName)
+    	 			MesquiteModule.mesquiteTrunk.classFieldChanged(Tree.class, "polytomyDefaultHard");
+    	 			storePreferences();
+    	 			changed = true;
+    	 			
+    	 		}
+			return polytomiesHard;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets universal, Mesquite-wide setting whether node labels converted to string annotations", "[on = convert; off = not]", commandName, "convertInternalNames")) {  
+    	 		boolean current = convertInternalNames.getValue();
+    	 		convertInternalNames.toggleValue(parser.getFirstToken(arguments));
+    	 		if (current!=convertInternalNames.getValue()) {
+    	 			MesquiteTree.convertInternalNames = convertInternalNames.getValue();
+    	 			storePreferences();
+    	 			changed = true;
+    	 			
+    	 		}
+			return convertInternalNames;
+    	 	}
+    	 /*
+    	 	else if (checker.compare(this.getClass(), "Sets universal, Mesquite-wide setting whether to warn if reticulations found", "[on = warn; off = not]", commandName, "warnReticulations")) {  
+    	 		boolean current = warnReticulations.getValue();
+    	 		warnReticulations.toggleValue(parser.getFirstToken(arguments));
+    	 		if (current!=warnReticulations.getValue()) {
+    	 			MesquiteTree.warnReticulations = warnReticulations.getValue();
+    	 			storePreferences();
+    	 			changed = true;
+    	 			
+    	 		}
+			return warnReticulations;
+    	 	}
+    	*/
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+   	 }
+  	 
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Set Tree Defaults";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Sets the default state for polytomies & other aspects of tree handling.";
+   	 }
+}
+
+
diff --git a/Source/mesquite/trees/ShadeNumbersOnTree/ShadeNumbersOnTree.java b/Source/mesquite/trees/ShadeNumbersOnTree/ShadeNumbersOnTree.java
new file mode 100644
index 0000000..0cda48f
--- /dev/null
+++ b/Source/mesquite/trees/ShadeNumbersOnTree/ShadeNumbersOnTree.java
@@ -0,0 +1,299 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.ShadeNumbersOnTree;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+import mesquite.cont.lib.*;
+
+/* ======================================================================== */
+public class ShadeNumbersOnTree extends DisplayNumbersAtNodes {
+	TreeDisplay treeDisplay;
+	MesquiteBoolean backRect;
+	MesquiteBoolean useLogScale;
+	MesquiteColorTable colorTable = new ContColorTable();
+ 	Vector labellers;
+ 	int digits = 4;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		backRect = new MesquiteBoolean(false);
+		useLogScale = new MesquiteBoolean(false);
+		MesquiteSubmenuSpec mss = addSubmenu(null, "Display");
+		addCheckMenuItemToSubmenu(null, mss, "Label nodes", makeCommand("toggleLabels", this), showLabels);
+		addItemToSubmenu(null, mss, "Digits...", makeCommand("setDigits",  this));
+		addCheckMenuItemToSubmenu(null, mss, "Display as percentage", makeCommand("toggleDisplayPercentage", this), usePercentages);  
+		addCheckMenuItemToSubmenu(null, mss, "Include labels for terminals", makeCommand("toggleLabelTerminals", this), labelTerminals);  
+		addCheckMenuItemToSubmenu(null, mss, "Labels with background", makeCommand("toggleRectangle", this), backRect);
+		addItemToSubmenu(null, mss, "-", null);
+		addCheckMenuItemToSubmenu(null, mss, "Shade branches by value", makeCommand("toggleShade", this), shadeBranches);
+		addCheckMenuItemToSubmenu(null, mss, "Color shading", makeCommand("toggleColor", this), shadeInColor);
+		addCheckMenuItemToSubmenu(null, mss, "Log Shades When Grey", makeCommand("toggleLog", this), useLogScale);  
+ 		labellers = new Vector();
+ 		return true;
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("toggleLabels " + showLabels.toOffOnString());
+  	 	temp.addLine("toggleLabelTerminals " + labelTerminals.toOffOnString());
+  	 	temp.addLine("toggleColor " + shadeInColor.toOffOnString());
+  	 	temp.addLine("toggleShade " + shadeBranches.toOffOnString());
+  	 	temp.addLine("toggleRectangle " + backRect.toOffOnString());
+  	 	temp.addLine("toggleLog " + useLogScale.toOffOnString());
+  	 	temp.addLine("toggleDisplayPercentage " + usePercentages.toOffOnString());
+		temp.addLine("setDigits " + digits); 
+ 	 	return temp;
+  	 }
+ 	/*.................................................................................................................*/
+ 	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets whether or not nodes are labeled with text", "[on = labeled; off]", commandName, "toggleLabels")) {
+    	 		showLabels.toggleValue(parser.getFirstToken(arguments));
+    	 		parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether shadings are shown in color or grayscale", "[on = color; off]", commandName, "toggleColor")) {
+    	 		shadeInColor.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether labels are also shown for the terminals", "[on = color; off]", commandName, "toggleLabelTerminals")) {
+    	 		labelTerminals.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether numbers are shown as percentages", "[on = yes; off]", commandName, "toggleDisplayPercentage")) {
+    	 		usePercentages.toggleValue(parser.getFirstToken(arguments));
+    	 		parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether branches are shaded", "[on = color; off]", commandName, "toggleShade")) {
+    	 		shadeBranches.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether labels are given a background rectangle", "[on = rectangle; off]", commandName, "toggleRectangle")) {
+    	 		backRect.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets whether grayscale is shown with log or linear", "[on = color; off]", commandName, "toggleLog")) {
+    	 		useLogScale.toggleValue(parser.getFirstToken(arguments));
+			parametersChanged();
+    	 	}
+    		else if (checker.compare(this.getClass(), "Sets how many digits are shown", "[number of digits]", commandName, "setDigits")) {
+    			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+    			if (!MesquiteInteger.isCombinable(newWidth))
+    				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set number of digits", "Number of digits (after decimal point) to display for values on tree:", digits, 0, 24);
+    			if (newWidth>=0 && newWidth<24 && newWidth!=digits) {
+    				digits = newWidth;
+    				if (!MesquiteThread.isScripting()) parametersChanged();
+    			}
+    		}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	public   TreeDecorator createTreeDecorator(TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		ShadeNumbersDecorator newShadeler = new ShadeNumbersDecorator(this, treeDisplay, ownerExtra);
+		labellers.addElement(newShadeler);
+		return newShadeler;
+	}
+ 	
+	/*.................................................................................................................*/
+ 	public void endJob() {
+		Enumeration e = labellers.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ShadeNumbersDecorator) {
+				ShadeNumbersDecorator tCO = (ShadeNumbersDecorator)obj;
+	 			tCO.turnOff();
+	 		}
+		}
+ 		super.endJob();
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Shade numbers";
+   	 }
+   	 
+	/*.................................................................................................................*/
+   	 
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "A module that displays numbers at tree nodes using labels.  This is a display-only module,"
+ 		+ " and would be hired by another module that organizes assigning numbers to the nodes." ;
+   	 }
+	/*.................................................................................................................*/
+   	 
+}
+
+/* ======================================================================== */
+class ShadeNumbersDecorator extends TreeDecorator {
+ 	ShadeNumbersOnTree ownerModule;
+	ColorDistribution colors;
+	boolean shadeInternalNodes = true;
+	boolean shadeTerminalNodes = true;
+	
+	boolean labelHugsNode = true;
+
+	public ShadeNumbersDecorator (ShadeNumbersOnTree ownerModule, TreeDisplay treeDisplay, TreeDisplayExtra ownerExtra) {
+		super(treeDisplay, ownerExtra);
+		this.ownerModule=ownerModule;
+ 		colors = new ColorDistribution();
+	}
+	/*.................................................................................................................*/
+	private void writeAtNode(NumberArray numbers,Graphics g, FontMetrics fm, int N,  Tree tree) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			writeAtNode(numbers, g, fm, d, tree);
+		if ((tree.nodeIsInternal(N) || ownerModule.getLabelTerminals()) && !numbers.isUnassigned(N)) {
+			MesquiteNumber numberToDisplay = new MesquiteNumber(numbers.getMesquiteNumber(N));
+			if (ownerModule.getUsePercentages()) {
+				numberToDisplay.multiplyBy(100);
+			}
+			String s = numberToDisplay.toString(ownerModule.digits, false);
+			int stringWidth = fm.stringWidth(s);
+			int stringHeight = fm.getMaxAscent()+fm.getMaxDescent(); //numbers wouldn't actually reach max descent
+
+			int nodeX = treeDisplay.getTreeDrawing().x[N];
+			int nodeY = treeDisplay.getTreeDrawing().y[N];
+
+			if (treeDisplay.getOrientation() == treeDisplay.UP) {
+				nodeY+=fm.getMaxAscent()+2;
+				nodeX +=4;
+				//nodeX+=10;
+			}
+			else if (treeDisplay.getOrientation() == treeDisplay.DOWN) {
+				nodeY-=fm.getMaxDescent();
+				nodeX +=4;
+				//nodeX+=10;
+			}
+			else if (treeDisplay.getOrientation() == treeDisplay.RIGHT) {
+				//nodeY=20;
+				if (labelHugsNode) {
+					nodeX-=stringWidth+2;
+					nodeY+= fm.getMaxAscent()+2;
+				}
+				else
+					nodeX-=10;
+			}
+			else if (treeDisplay.getOrientation() == treeDisplay.LEFT) {
+				//nodeY+=20;
+				if (labelHugsNode) {
+					nodeX+=4;
+					nodeY+= fm.getMaxAscent()+2;
+				}
+				else
+					nodeX+=10;
+			}
+
+			if (ownerModule.backRect.getValue()){
+				Color c = g.getColor();
+				g.setColor(Color.white);
+				g.fillRect(nodeX, nodeY, stringWidth+4, stringHeight);
+				g.setColor(Color.blue);
+				g.drawRect(nodeX, nodeY, stringWidth+4, stringHeight);
+				g.drawString(s, nodeX +2, nodeY + fm.getMaxAscent()+1);
+				if (c!=null) g.setColor(c);
+			}
+			else
+				StringUtil.highlightString(g, s, nodeX, nodeY, Color.blue, Color.white);
+
+		}
+	}
+	/*.................................................................................................................*/
+	private void shadeNode(int N, Tree tree, NumberArray numbers, MesquiteNumber min, MesquiteNumber max, Graphics g) {
+		for (int d = tree.firstDaughterOfNode(N); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				shadeNode(d, tree, numbers, min, max, g);
+				
+		if ((tree.nodeIsInternal(N) && shadeInternalNodes) || (tree.nodeIsTerminal(N) && shadeTerminalNodes)) {
+			Color c;
+			if (ownerModule.getShadeInColor())
+				c = ownerModule.colorTable.getColor(numbers.getDouble(N), min.getDoubleValue(), max.getDoubleValue()); 
+			else 
+				c = MesquiteColorTable.getGrayScale(numbers.getDouble(N), min.getDoubleValue(), max.getDoubleValue(), ownerModule.useLogScale.getValue()); 
+			colors.initialize();
+			colors.setColor(0, c);
+			treeDisplay.getTreeDrawing().fillBranchWithColors(tree,  N, colors, g);
+			g.setColor(Color.black);
+		}
+
+	}
+	Color getColor(double d, MesquiteNumber min, MesquiteNumber max){
+		if (ownerModule.getShadeInColor())
+			return ownerModule.colorTable.getColor(d, min.getDoubleValue(), max.getDoubleValue()); 
+		else
+			return MesquiteColorTable.getGrayScale(d, min.getDoubleValue(), max.getDoubleValue(), ownerModule.useLogScale.getValue()); 
+	}
+	public ColorRecord[] getLegendColorRecords(){
+		if (!ownerModule.getShadeBranches()) 
+			return null;
+		if (min.isCombinable() && max.isCombinable()) {
+			ColorRecord[] records = new ColorRecord[10];
+			records[0] = new ColorRecord(getColor(min.getDoubleValue(), min, max), MesquiteDouble.toString(min.getDoubleValue())); 
+			for (int i=1; i<9; i++){
+				double d = (max.getDoubleValue() - min.getDoubleValue())/10.0*i + min.getDoubleValue();
+				records[i] = new ColorRecord(getColor(d, min, max), MesquiteDouble.toString(d)); 
+			}
+			records[9] = new ColorRecord(getColor(max.getDoubleValue(), min, max), MesquiteDouble.toString(max.getDoubleValue())); 
+			return records;
+		}
+		else 
+			return new ColorRecord[] {new ColorRecord(MesquiteColorTable.getGrayScale(MesquiteDouble.unassigned, min.getDoubleValue(), max.getDoubleValue(), false), "Unassigned")};
+	}
+	/*.................................................................................................................*/
+	MesquiteNumber min = new MesquiteNumber();
+	MesquiteNumber max = new MesquiteNumber();
+	public   void drawOnTree(Tree tree, int drawnRoot, Object obj, Object obj2, Object obj3, Graphics g) {
+		
+			if (obj instanceof NumberArray) {
+				if (treeDisplay!=null && tree!=null && obj!=null) {
+					NumberArray numbers = (NumberArray)obj;
+					numbers.placeMinimumValue(min);
+					numbers.placeMaximumValue(max);
+					if (treeDisplay!=null && tree!=null) {
+						if (ownerModule.getShadeBranches()) 
+							shadeNode(drawnRoot, tree, numbers, min, max, g);
+						if (ownerModule.getShowLabels()) {
+							writeAtNode(numbers, g, g.getFontMetrics(), drawnRoot,tree);
+						}
+					}
+					else
+						MesquiteMessage.warnProgrammer("Shade states -- null tree display, tree");
+				}
+				else
+					System.out.println("shade on tree  values//null");
+			}
+			else
+				System.out.println("Error: Shade Numbers needs number array");
+		
+	}
+	
+	/*.................................................................................................................*/
+	public void turnOff() {
+	}
+}
+
diff --git a/Source/mesquite/trees/ShowTreeInList/32showTree.gif b/Source/mesquite/trees/ShowTreeInList/32showTree.gif
new file mode 100644
index 0000000..fd8ab10
Binary files /dev/null and b/Source/mesquite/trees/ShowTreeInList/32showTree.gif differ
diff --git a/Source/mesquite/trees/ShowTreeInList/64showTree.gif b/Source/mesquite/trees/ShowTreeInList/64showTree.gif
new file mode 100644
index 0000000..233b62d
Binary files /dev/null and b/Source/mesquite/trees/ShowTreeInList/64showTree.gif differ
diff --git a/Source/mesquite/trees/ShowTreeInList/ShowTreeInList.java b/Source/mesquite/trees/ShowTreeInList/ShowTreeInList.java
new file mode 100644
index 0000000..f6db7bd
--- /dev/null
+++ b/Source/mesquite/trees/ShowTreeInList/ShowTreeInList.java
@@ -0,0 +1,114 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ShowTreeInList;
+/*~~  */
+
+import mesquite.lists.lib.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.lib.table.*;
+
+/* ======================================================================== */
+public class ShowTreeInList extends TreeListInit  {
+	TreeVector trees;
+	MesquiteTable table;
+	TableTool tool;
+	public String getName() {
+		return "Show Tree";
+	}
+	public String getExplanation() {
+		return "Provides tool in the List of Trees window to request that tree be shown in window.";
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 275;  
+	}
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		return temp;
+	}
+	TreeWindowMaker getTreeWindowModule(){
+	
+		mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord treeWindowCoord = (mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord)findNearestModuleWithDuty(mesquite.trees.BasicTreeWindowCoord.BasicTreeWindowCoord.class);
+		MesquiteModule[] treeWindowMakers = treeWindowCoord.getImmediateEmployeesWithDuty(mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker.class);
+		if (treeWindowMakers != null && treeWindowMakers.length>0){
+			for (int i = 0; i<treeWindowMakers.length; i++){
+				TreeWindowMaker mod = (TreeWindowMaker)treeWindowMakers[i];
+				MesquiteModule source = mod.getTreeSource();
+				if (source instanceof mesquite.trees.StoredTrees.StoredTrees){
+					mesquite.trees.StoredTrees.StoredTrees ts = (mesquite.trees.StoredTrees.StoredTrees)source;
+					if (ts.showing(trees)){
+						return mod;
+					}
+				}
+			}
+		}
+		
+		TreeWindowMaker mod = treeWindowCoord.makeWindowShowingTrees(trees.getTaxa(), trees);
+		return mod;
+		
+	}
+	/*.................................................................................................................*/
+	/** A request for the MesquiteModule to perform a command.  It is passed two strings, the name of the command and the arguments.
+	This should be overridden by any module that wants to respond to a command.*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) { 
+		if (checker.compare(MesquiteModule.class, null, null, commandName, "showTree")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int column= MesquiteInteger.fromString(arguments, io);
+			int row= MesquiteInteger.fromString(arguments, io);
+
+			mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker treeWindowModule = (mesquite.trees.BasicTreeWindowMaker.BasicTreeWindowMaker)getTreeWindowModule();
+			
+			treeWindowModule.goToTreeNumber(row);
+			treeWindowModule.showMe();
+			
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public void setTableAndTreeBlock(MesquiteTable table, TreeVector trees){
+		this.table = table;
+		this.trees = trees;
+		if (containerOfModule() instanceof ListWindow && tool == null){
+			String sortExplanation = "Shows tree in tree window. ";
+			tool = new TableTool(this, "showTree", getPath(),"showTree.gif", 0,0,"Show tree", sortExplanation, MesquiteModule.makeCommand("showTree",  this) , null, null);
+			tool.setWorksOnRowNames(true);
+			((ListWindow)containerOfModule()).addTool(tool);
+			//tool.setPopUpOwner(this);
+		}
+	}
+
+}
diff --git a/Source/mesquite/trees/ShowTreeInList/showTree.gif b/Source/mesquite/trees/ShowTreeInList/showTree.gif
new file mode 100644
index 0000000..393ddb5
Binary files /dev/null and b/Source/mesquite/trees/ShowTreeInList/showTree.gif differ
diff --git a/Source/mesquite/trees/SimulateTree/SimulateTree.java b/Source/mesquite/trees/SimulateTree/SimulateTree.java
new file mode 100644
index 0000000..ff5860d
--- /dev/null
+++ b/Source/mesquite/trees/SimulateTree/SimulateTree.java
@@ -0,0 +1,286 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SimulateTree;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.coalesce.lib.Coalescer;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies simulated trees.  This is a coordinator; the simulations themselves are done by modules hired.*/
+public class SimulateTree extends TreeSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSimulate.class, getName() + "  uses a specific simulator to generate trees.",
+		"The specific simulator can be chosen initially or in the Tree Simulator submenu");
+		e.setEmphasize(true);
+		e.setPriority(1);
+	}
+	int currentTree=0;
+
+	long originalSeed=System.currentTimeMillis(); //0L;
+	MesquiteTree tree;
+	TreeSimulate simulatorTask;
+	MesquiteLong seed;
+	Random rng;
+	MesquiteString simulatorName;
+	int notifyEvery = 0;
+	long count = 0;
+	long[][] symmetries;
+	Taxa currentTaxa = null;
+	MesquiteCommand stC;
+	MesquiteBoolean repeatableSequence = new MesquiteBoolean(true);
+
+	public Color getItemColor(Taxa taxa, int ic){  // 26 Aug 07:  Why was this red and green???????
+		/*  		if (ic % 2 == 0)
+   			return Color.red;
+   		else
+   			return Color.green;
+		 */
+		return null;
+	}
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (arguments ==null) {
+			if (MesquiteThread.isScripting())
+				simulatorTask= (TreeSimulate)hireNamedEmployee(TreeSimulate.class, StringUtil.tokenize("Equal rates Markov"));
+			if (simulatorTask == null && MesquiteThread.isScripting())
+				simulatorTask= (TreeSimulate)hireNamedEmployee(TreeSimulate.class, StringUtil.tokenize("Equiprobable Trees"));
+			if (simulatorTask == null)
+				simulatorTask= (TreeSimulate)hireEmployee(TreeSimulate.class, "Tree simulator");
+			if (simulatorTask == null) {
+				return sorry("Simulated Trees could not start because no simulator module was obtained");
+			}
+		}
+		else  {
+			simulatorTask= (TreeSimulate)hireNamedEmployee(TreeSimulate.class, arguments);
+			if (simulatorTask == null) {
+				return sorry("Simulated Trees could not start because the requested simulator module was not obtained");
+			}
+		}
+		stC = makeCommand("setTreeSimulator",  this);
+		simulatorTask.setHiringCommand(stC);
+		if (RandomBetween.askSeed && !MesquiteThread.isScripting()){
+			long response = MesquiteLong.queryLong(containerOfModule(), "Seed for Tree simulation", "Set Random Number seed for tree simulation:", originalSeed);
+			if (MesquiteLong.isCombinable(response))
+				originalSeed = response;
+		}
+		seed = new MesquiteLong(1);
+		seed.setValue(originalSeed);
+		rng = new Random(originalSeed);
+		simulatorName = new MesquiteString();
+		simulatorName.setValue(simulatorTask.getName());
+		if (numModulesAvailable(TreeSimulate.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Simulator", stC, TreeSimulate.class);
+			mss.setSelected(simulatorName);
+		}
+		addMenuItem("Set Seed (Tree simulation)...", makeCommand("setSeed",  this));
+		addCheckMenuItem(null, "Simulation Repeatable", makeCommand("toggleRepeatable",  this), repeatableSequence);
+
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return TreeSimulate.class;
+	}
+
+
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		storePreferences();
+		super.endJob();
+	}
+	int changes = 0;
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && !(code == MesquiteListener.SELECTION_CHANGED)) {
+
+			changes++;
+			parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("setTreeSimulator ", simulatorTask);
+		temp.addLine("setSeed " + originalSeed);
+		temp.addLine("toggleRepeatable " + repeatableSequence.toOffOnString());
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module simulating trees", "[name of module]", commandName, "setTreeSimulator")) {
+			TreeSimulate temp=  (TreeSimulate)replaceEmployee(TreeSimulate.class, arguments, "Tree simulator", simulatorTask);
+			if (temp!=null) {
+				simulatorTask = temp;
+				simulatorTask.setHiringCommand(stC);
+				simulatorName.setValue(simulatorTask.getName());
+				simulatorTask.initialize(currentTaxa);
+				seed.setValue(originalSeed);
+				if (tree!=null && tree instanceof MesquiteTree) {
+					((MesquiteTree)tree).removeAllSensitives();
+					((MesquiteTree)tree).deassignAssociated();
+					tree = null;
+				}
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //?
+			}
+			return temp;
+		}
+		else if (checker.compare(this.getClass(), "Toggles the sequence of trees is to be repeatable", null, commandName, "toggleRepeatable")) {
+			repeatableSequence.toggleValue(ParseUtil.getFirstToken(arguments, pos));
+			if (!MesquiteThread.isScripting())
+				parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Resets the random number seed to the current system time", null, commandName, "resetSeed")) {
+			originalSeed = System.currentTimeMillis();
+			if (!MesquiteThread.isScripting())
+				parametersChanged(); //?
+		}
+		else if (checker.compare(this.getClass(), "Sets the random number seed to that passed", "[long integer seed]", commandName, "setSeed")) {
+			long s = MesquiteLong.fromString(parser.getFirstToken(arguments));
+			if (!MesquiteLong.isCombinable(s)){
+				s = MesquiteLong.queryLong(containerOfModule(), "Random number seed", "Enter an integer value for the random number seed for tree simulation", originalSeed);
+			}
+			if (MesquiteLong.isCombinable(s)){
+				originalSeed = s;
+				if (!MesquiteThread.isScripting())
+					parametersChanged(); //?
+			}
+		}
+		else if (checker.compare(this.getClass(), "Notifies the user periodically how many trees have been simulated", "[how many trees between notifications]", commandName, "notifyEvery")) {
+			int notify = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(notify) && notify>0)
+				notifyEvery = notify;
+			else
+				notifyEvery = -1;
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	public void setPreferredTaxa(Taxa taxa){
+		if (taxa !=currentTaxa) {
+			if (currentTaxa!=null)
+				currentTaxa.removeListener(this);
+			currentTaxa = taxa;
+			currentTaxa.addListener(this);
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+	public void initialize(Taxa taxa){
+		setPreferredTaxa(taxa);
+		if (simulatorTask!=null)
+			simulatorTask.initialize(taxa);
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {  //TODO: should this reuse the same Tree object? forces user to use immediately or clone for storages
+		setPreferredTaxa(taxa);
+		currentTree=itree;
+		if (taxa==null) {
+			MesquiteMessage.warnProgrammer("taxa null in getTree of SimulateTree");
+			return null;
+		}
+		if (notifyEvery>0 && count++ % notifyEvery==0)
+			System.out.println("   tree " + currentTree);
+		tree = new MesquiteTree(taxa);
+		if (repeatableSequence.getValue()){
+			rng.setSeed(originalSeed);
+			long rnd = originalSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+			for (int it = 0; it<= currentTree; it++) 
+				rnd =  rng.nextInt();
+			rng.setSeed(rnd+1);
+			seed.setValue(rnd + 1); //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+		}
+		else
+			seed.setValue(rng.nextInt()); 
+
+		tree =  (MesquiteTree)simulatorTask.getSimulatedTree(taxa, tree, currentTree, null, seed);
+		if (tree ==null)
+			return null;
+		((MesquiteTree)tree).setName(getTreeNameString(taxa, currentTree));
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		if (simulatorTask!=null)
+			return simulatorTask.getNumberOfTrees(taxa);
+		return MesquiteInteger.infinite;
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		if (simulatorTask==null) return "";
+		return "Tree # " + MesquiteTree.toExternal(itree)  + " simulated by " + simulatorTask.getName();
+	}
+	/*.................................................................................................................*/
+	public String getCurrentTreeNameString() {
+		if (simulatorTask==null) return "";
+		return "Tree # " + MesquiteTree.toExternal(currentTree)  + " simulated by " + simulatorTask.getName();
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (simulatorTask==null) return "";
+		return "Tree simulator: " + simulatorTask.getName() + ". [seed: " + originalSeed + "]";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Simulated Trees";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies trees from simulations.";
+	}
+}
+
diff --git a/Source/mesquite/trees/SimulatedTreeBlocks/SimulatedTreeBlocks.java b/Source/mesquite/trees/SimulatedTreeBlocks/SimulatedTreeBlocks.java
new file mode 100644
index 0000000..0da8938
--- /dev/null
+++ b/Source/mesquite/trees/SimulatedTreeBlocks/SimulatedTreeBlocks.java
@@ -0,0 +1,247 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.SimulatedTreeBlocks;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class SimulatedTreeBlocks extends TreeBlockSource {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeSimulate.class, getName() + "  uses a specific simulator to generate trees.",
+		"The specific simulator can be chosen initially or in the Tree Simulator submenu");
+		e.setPriority(1);
+	}
+	/*.................................................................................................................*/
+	int currentTreeBlockIndex=0;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	TreeSimulate simulatorTask;
+	Taxa preferredTaxa =null;
+	Taxa currentTaxa = null;
+	MesquiteLong seed;
+	long originalSeed=System.currentTimeMillis(); //0L;
+	static int numTrees = 10;
+	Random rng;
+	MesquiteInteger pos = new MesquiteInteger(0);
+	MesquiteString simulatorName;
+	MesquiteCommand stC;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+	    	currentTreeBlockIndex = 0;
+		simulatorTask = (TreeSimulate)hireEmployee(TreeSimulate.class, "Tree simulator");
+		if (simulatorTask==null)
+			return sorry(getName() + " couldn't start because no tree simulator module was obtained.");
+    	 	stC = makeCommand("setTreeSimulator",  this);
+    	 	simulatorTask.setHiringCommand(stC);
+    	 	seed = new MesquiteLong(1);
+    	 	seed.setValue(originalSeed);
+    	 	rng = new Random(originalSeed);
+ 		simulatorName = new MesquiteString();
+		if (numModulesAvailable(TreeSimulate.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Tree Simulator", stC, TreeSimulate.class);
+ 			mss.setSelected(simulatorName);
+  		}
+		addMenuItem( "Number of Trees...", makeCommand("setNumberTrees",  this));
+		if (!MesquiteThread.isScripting()){
+			int n = MesquiteInteger.queryInteger(containerOfModule(), "Trees per block?", "How many trees to simulate per tree block?", numTrees);
+			if (!MesquiteInteger.isCombinable(n) || n<=0)
+				return false;
+			numTrees = n;
+		}
+		return true;
+  	 }
+	
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (currentTaxa!=null)
+			currentTaxa.removeListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		if (Notification.appearsCosmetic(notification))
+			return;
+		int code = Notification.getCode(notification);
+		if (obj == currentTaxa && !(code == MesquiteListener.SELECTION_CHANGED)) {
+				parametersChanged(notification);
+		}
+	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.addLine("setTreeSimulator ", simulatorTask);
+   	 	temp.addLine("setNumberTrees " + numTrees);
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the number of trees simulated in each tree block", "[number of trees]", commandName, "setNumberTrees")) {
+			int newNum= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newNum))
+				newNum = MesquiteInteger.queryInteger(containerOfModule(), "Set Number of Trees", "Number of Trees to simulate:", numTrees, 0, MesquiteInteger.infinite);
+    	 		if (newNum>0  && newNum!=numTrees) {
+    	 			numTrees = newNum;
+				parametersChanged();
+    	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the module simulating trees", "[name of module]", commandName, "setTreeSimulator")) {
+    	 		TreeSimulate temp=  (TreeSimulate)replaceEmployee(TreeSimulate.class, arguments, "Tree simulator", simulatorTask);
+	    	 	if (temp!=null) {
+	    	 		simulatorTask = temp;
+		    	 	simulatorTask.setHiringCommand(stC);
+	    	 		simulatorName.setValue(simulatorTask.getName());
+	    	 		simulatorTask.initialize(currentTaxa);
+	    	 		seed.setValue(originalSeed);
+ 				parametersChanged(); //?
+ 			}
+ 			return temp;
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void disposing(Object obj){
+		if (obj == currentTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+		}
+	}
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+   		if (taxa !=currentTaxa) {
+	 		if (currentTaxa!=null)
+	  			currentTaxa.removeListener(this);
+	  		currentTaxa = taxa;
+  			currentTaxa.addListener(this);
+  		}
+  		
+  	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		//TODO: should this respond to nothing???
+	}
+   	/*.................................................................................................................*/
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		setPreferredTaxa(taxa);
+ 	    	 if (simulatorTask!=null)
+ 	    	 	simulatorTask.initialize(taxa);
+   	}
+   	/*.................................................................................................................*/
+   	private Tree getTree(Taxa taxa, int whichTree, long baseSeed) {
+		rng.setSeed(baseSeed);
+		long rnd = baseSeed;  //v. 1. 12 this had been 0 and thus first would always use seed 1
+		for (int it = 0; it<=whichTree; it++)
+			rnd =  rng.nextInt();
+		rng.setSeed(rnd+1);
+		seed.setValue(rnd + 1);  //v. 1. 1, October 05: changed so as to avoid two adjacent trees differing merely by a frameshift of random numbers
+		Tree tree =  simulatorTask.getSimulatedTree(taxa, null, whichTree, null, seed); //TODO: this should be passed scripting
+		if (tree instanceof AdjustableTree)
+			((AdjustableTree)tree).setName("Simulated tree " + MesquiteTree.toExternal(whichTree));
+   		return tree;
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getFirstBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex=0;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getBlock(Taxa taxa, int ic) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex=ic;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getCurrentBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		if (taxa == null)
+   			return null;
+   		int min = taxa.getNumTaxa();
+   		TreeVector trees = new TreeVector(taxa);
+   		trees.setName("Simulated " + currentTreeBlockIndex);
+		for (int i = 0; i<numTrees; i++) {
+			trees.addElement(getTree(taxa, i, originalSeed + currentTreeBlockIndex), false);
+   		}
+   		return trees;
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getNextBlock(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		currentTreeBlockIndex++;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTreeBlocks(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+   		return MesquiteInteger.infinite;
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeBlockNameString(Taxa taxa, int index) {
+   		setPreferredTaxa(taxa);
+		return "Simulated tree block " + index;
+   	}
+	/*.................................................................................................................*/
+   	public String getCurrentTreeNameString(Taxa taxa) {
+   		setPreferredTaxa(taxa);
+		return "Simulated tree block " + currentTreeBlock;
+   	}
+
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Simulated Tree Blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Creates a tree block of simulated trees." ;
+   	 }
+	/*.................................................................................................................*/
+   	public String getParameters() {
+		if (currentTaxa!=null)
+			return "Simulated trees Lists (last set of taxa used: " + currentTaxa.getName() + ")";
+		else
+			return "Simulated trees Lists";
+   	}
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+}
+
diff --git a/Source/mesquite/trees/SquareLineTree/SquareLineTree.java b/Source/mesquite/trees/SquareLineTree/SquareLineTree.java
new file mode 100644
index 0000000..e3b2d21
--- /dev/null
+++ b/Source/mesquite/trees/SquareLineTree/SquareLineTree.java
@@ -0,0 +1,671 @@
+
+package mesquite.trees.SquareLineTree;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.*;
+
+import java.awt.geom.*;
+/* ======================================================================== */
+public class SquareLineTree extends DrawTree {
+	public String getName() {
+		return "Square Line Tree";
+	}
+	public String getExplanation() {
+		return "Draws trees with square branches made out of lines rather than polygons." ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsVH.class, getName() + "  needs the locations of nodes to be calculated.",
+		"The calculator for node locations is chosen automatically or initially");
+	}
+	/*.................................................................................................................*/
+
+	NodeLocsVH nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteString orientationName;
+	Vector drawings;
+	int oldEdgeWidth = 4;
+	int ornt;
+	MesquiteString nodeLocsName;
+	MesquiteBoolean showEdgeLines = new MesquiteBoolean(true);  //these needs to be set default true; otherwise Trace Character makes branches disappear in most common cases
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		nodeLocsTask= (NodeLocsVH)hireNamedEmployee(NodeLocsVH.class, "#NodeLocsStandard");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node locator module was obtained");
+
+		nodeLocsName = new MesquiteString(nodeLocsTask.getName());
+		if (numModulesAvailable(NodeLocsVH.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Locations Calculator", makeCommand("setNodeLocs", this), NodeLocsVH.class);
+			mss.setSelected(nodeLocsName);
+		}
+		drawings = new Vector();
+		ornt = NodeLocsVH.defaultOrientation;  //should take out of preferences
+
+		orientationName = new MesquiteString(orient(ornt));
+		MesquiteSubmenuSpec orientationSubmenu = addSubmenu(null, "Orientation");
+		orientationSubmenu.setSelected(orientationName);
+		addItemToSubmenu(null, orientationSubmenu, "Up", makeCommand("orientUp",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Right", makeCommand("orientRight",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Down", makeCommand("orientDown",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Left", makeCommand("orientLeft",  this));
+
+		
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		addCheckMenuItem(null,"Show Edge Lines", makeCommand("showEdgeLines",  this), showEdgeLines);
+		return true;
+
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		SquareLineTreeDrawing treeDrawing =  new SquareLineTreeDrawing (treeDisplay, numTaxa, this);
+		if (legalOrientation(treeDisplay.getOrientation())){
+			orientationName.setValue(orient(treeDisplay.getOrientation()));
+			ornt = treeDisplay.getOrientation();
+		}
+		else
+			treeDisplay.setOrientation(ornt);
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	public boolean legalOrientation (int orientation){
+		return (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN || orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT);
+	}
+
+	public String orient (int orientation){
+		if (orientation == TreeDisplay.UP)
+			return "Up";
+		else if (orientation == TreeDisplay.DOWN)
+			return "Down";
+		else if (orientation == TreeDisplay.RIGHT)
+			return "Right";
+		else if (orientation == TreeDisplay.LEFT)
+			return "Left";
+		else return "other";
+	}
+	/*.................................................................................................................*/
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNodeLocs", nodeLocsTask);
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		temp.addLine("showEdgeLines " + showEdgeLines.toOffOnString()); 
+
+		if (ornt== TreeDisplay.UP)
+			temp.addLine("orientUp"); 
+		else if (ornt== TreeDisplay.DOWN)
+			temp.addLine("orientDown"); 
+		else if (ornt== TreeDisplay.LEFT)
+			temp.addLine("orientLeft"); 
+		else if (ornt== TreeDisplay.RIGHT)
+			temp.addLine("orientRight"); 
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+
+		if (checker.compare(this.getClass(), "Sets the node locations calculator", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsVH temp = (NodeLocsVH)replaceEmployee(NodeLocsVH.class, arguments, "Node Locations Calculator", nodeLocsTask);
+			if (temp != null) {
+				nodeLocsTask = temp;
+				nodeLocsName.setValue(nodeLocsTask.getName());
+				parametersChanged();
+			}
+			return nodeLocsTask;
+		}
+		else 	if (checker.compare(this.getClass(), "Sets the width of lines for drawing the tree", "[width in pixels]", commandName, "setEdgeWidth")) {
+
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, 99);
+			if (newWidth>0 && newWidth<100 && newWidth!=oldEdgeWidth) {
+				oldEdgeWidth=newWidth;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+					treeDrawing.treeDisplay.setMinimumTaxonNameDistance(newWidth, 6); 
+				}
+				if ( !MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to show edge lines or not.", "", commandName, "showEdgeLines")) {
+ 			boolean current = showEdgeLines.getValue();
+ 			showEdgeLines.toggleValue(parser.getFirstToken(arguments));
+ 			if (current!=showEdgeLines.getValue()) {
+ 				parametersChanged();
+ 			}
+		}
+		else if (checker.compare(this.getClass(), "Returns the employee module that assigns node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are on top", null, commandName, "orientUp")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.UP);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at the bottom", null, commandName, "orientDown")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.DOWN);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at right", null, commandName, "orientRight")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.RIGHT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at left", null, commandName, "orientLeft")) {
+			Enumeration e = drawings.elements();
+			ornt = 0;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareLineTreeDrawing treeDrawing = (SquareLineTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.LEFT);
+				ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else {
+			return  super.doCommand(commandName, arguments, checker);
+		}
+		return null;
+	}
+	/*.................................................................................................................*/
+	public boolean getShowEdgeLines() {
+		return showEdgeLines.getValue();
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+}
+
+/* ======================================================================== */
+class SquareLineTreeDrawing extends TreeDrawing  {
+
+	private int lastleft;
+	private int taxspacing;
+	public int highlightedBranch, branchFrom;
+	public int xFrom, yFrom, xTo, yTo;
+	public SquareLineTree ownerModule;
+	public int edgewidth = 4;
+	public int preferredEdgeWidth = 4;
+	int oldNumTaxa = 0;
+	float inset=(float)1.0;
+	private boolean ready=false;
+	BasicStroke defaultStroke;
+
+	private int foundBranch;
+
+	public SquareLineTreeDrawing (TreeDisplay treeDisplay, int numTaxa, SquareLineTree ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		treeDisplay.setMinimumTaxonNameDistance(edgewidth, 4); //better if only did this if tracing on
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		oldNumTaxa = numTaxa;
+		try{
+			defaultStroke = new BasicStroke();
+		}
+		catch (Throwable t){
+		}
+		treeDisplay.setOrientation(ownerModule.nodeLocsTask.getDefaultOrientation());
+		ready = true;
+	}
+
+	/*_________________________________________________*/
+	private void calculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			calculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node] = y[tree.motherOfNode(node)];
+		lineBaseX[node] =  x[tree.motherOfNode(node)];
+	}
+
+	public int getBranchCenterX(int node){
+		int bX =lineBaseX[node];
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT)
+			return (bX-x[node])/3 + x[node];
+		else 
+			return x[node]; 
+	}
+	public int getBranchCenterY(int node){
+		int bY = lineBaseY[node];
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT)
+			return y[node];
+		else 
+			return (bY-y[node])/3 + y[node];
+	}
+
+	// TODO: Check new code (getMiddleOfBranch copied [then modified] from SquareTreeDrawing).  Oliver.July.31.2015
+	/**
+	 * Set values for x and y coordinates of middle of branch; sets {@code angle} value 
+	 * too, but unclear if this is ever used.
+	 * 
+	 *  @param	tree	the tree to extract coordinates from
+	 *  @param	N	the node corresponding to branch of interest
+	 *  @param	xValue	MesquiteNumber to store position on x-axis
+	 *  @param	yValue	MesquiteNumber to store position on y-axis
+	 *  @param	angle	MesquiteDouble...?
+	 */
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if(tree==null || xValue==null || yValue==null)
+			return;
+		if(!tree.nodeExists(N))
+			return;
+		int mother = tree.motherOfNode(N);
+		if(treeDisplay.getOrientation()==TreeDisplay.UP){
+			xValue.setValue(x[N] + getEdgeWidth()/2);
+			yValue.setValue(y[mother]+(y[N]-y[mother])/2 + getEdgeWidth()/2);
+			angle.setValue(-Math.PI/2.0);
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+			xValue.setValue(x[N] + getEdgeWidth()/2);
+			yValue.setValue(y[N]+(y[mother]-y[N])/2 - getEdgeWidth()/2);
+			angle.setValue(Math.PI/2.0);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			xValue.setValue(x[mother]+(x[N]-x[mother])/2 - getEdgeWidth()/2);
+			yValue.setValue(y[N] + getEdgeWidth()/2);
+			angle.setValue(0.0);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){
+			xValue.setValue(x[N]+(x[mother]-x[N])/2 + getEdgeWidth()/2);
+			yValue.setValue(y[N] + getEdgeWidth()/2);
+			angle.setValue(Math.PI);
+		}
+	}
+
+	/*_________________________________________________*/
+	public int getNodeValueTextBaseX(int node, int edgewidth, int stringwidth, int fontHeight, boolean horizontalText){
+		int bX =x[node];
+		if (horizontalText) {
+			if (treeDisplay.getOrientation()==treeDisplay.RIGHT) {
+				bX -=edgewidth+stringwidth;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.LEFT) {
+				bX +=edgewidth;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.DOWN) {
+				bX -=stringwidth/2;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.UP) {
+				bX -=stringwidth/2;
+			}
+		} else {
+			if (treeDisplay.getOrientation()==treeDisplay.RIGHT) {
+				bX -=fontHeight*2+edgewidth+2;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.LEFT) {
+				bX -=fontHeight;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.DOWN) {
+				bX -=fontHeight;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.UP) {
+				bX -=fontHeight;
+			}
+		}
+		return bX;
+	}
+	public int getNodeValueTextBaseY(int node, int edgewidth, int stringwidth, int fontHeight, boolean horizontalText){
+		int bY =y[node];
+		if (horizontalText) {
+			if (treeDisplay.getOrientation()==treeDisplay.RIGHT) {
+				bY -=fontHeight;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.LEFT) {
+				bY -=fontHeight;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.DOWN) {
+				bY -=edgewidth+fontHeight+2;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.UP) {
+				bY +=edgewidth;
+			}
+		} else {
+			if (treeDisplay.getOrientation()==treeDisplay.RIGHT) {
+				bY +=stringwidth/2;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.LEFT) {
+				bY +=stringwidth/2;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.DOWN) {
+				bY -=edgewidth;
+			}
+			else if (treeDisplay.getOrientation()==treeDisplay.UP) {
+				bY +=stringwidth+edgewidth;
+			}
+		}
+		return bY;
+	}
+	/*_________________________________________________*/
+	private void calcBranchStuff(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+
+//		treeDisplay.setTaxonSpacing(16);
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		calculateLines(tree, drawnRoot);
+		edgewidth = preferredEdgeWidth;
+		if (treeDisplay.getTaxonSpacing()<edgewidth+2) {
+			edgewidth= treeDisplay.getTaxonSpacing()-2;
+			if (edgewidth<2)
+				edgewidth=2;
+		}
+	}
+
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		Color tC = g.getColor();
+		if (flip)
+			g.setColor(Color.yellow);
+		else
+			g.setColor(Color.blue);
+
+		if (treeDisplay.getOrientation()==TreeDisplay.DOWN || treeDisplay.getOrientation()==TreeDisplay.UP){
+			g.fillOval(x[node]-4, y[node], 8, 8);
+		}
+		else {
+			g.fillOval(x[node], y[node]-4, 8,8);
+		}
+
+		g.setColor(tC);
+	}
+	/*_________________________________________________*/
+	private   void drawClade(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			g.setColor(treeDisplay.getBranchColor(node));
+			if (tree.getRooted() || tree.getRoot()!=node) {
+				DrawTreeUtil.drawOneSquareLineBranch(treeDisplay, x, y, getEdgeWidth(), tree, g, null, node, 0, edgewidth,0, emphasizeNodes(), nodePoly(node), defaultStroke);
+			}
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				drawClade( tree, g, thisSister);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			g.setColor(treeDisplay.branchColor);
+			drawClade(tree, g, drawnRoot);  
+		}
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			calcBranchStuff(tree, getDrawnRoot());
+		}
+	}
+
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		Rectangle box;
+		if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+			box = new Rectangle(x[node], y[node]-edgewidth/2-2, edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 0, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 180);
+			g.drawLine(box.x, box.y+ edgewidth/2, box.x+edgewidth,  box.y+ edgewidth/2);
+		}
+		else if (treeDisplay.getOrientation()==TreeDisplay.DOWN) {
+			box = new Rectangle(x[node], y[node] + 2, edgewidth, edgewidth);
+			g.fillArc(box.x, box.y -  box.height/2, box.width, box.height, 180, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y -  box.height/2, box.width, box.height, 180, 180);
+			g.drawLine(box.x, box.y , box.x+edgewidth,  box.y);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+			box = new Rectangle(x[node] + 2, y[node], edgewidth, edgewidth);
+			g.fillArc(box.x- box.width/2, box.y, box.width, box.height, 270, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x- box.width/2, box.y, box.width, box.height, 270, 180);
+			g.drawLine(box.x, box.y, box.x ,  box.y+edgewidth);
+		}
+		else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT) {
+			box = new Rectangle(x[node]-edgewidth/2-2, y[node], edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 90, 180);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 90, 180);
+			g.drawLine(box.x+edgewidth/2, box.y, box.x+edgewidth/2,  box.y+edgewidth);
+		}
+		else {
+			box = new Rectangle(x[node], y[node], edgewidth, edgewidth);
+			g.fillArc(box.x, box.y, box.width, box.height, 0, 360);
+			g.setColor(treeDisplay.getBranchColor(node));
+			g.drawArc(box.x, box.y, box.width, box.height, 0, 360);
+		}
+	}
+	/*_________________________________________________*/
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		int ew = edgewidth-1;
+		if (treeDisplay.getOrientation()==treeDisplay.UP) 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]-ew-3 && yPos < y[node]-3;
+		else if (treeDisplay.getOrientation()==treeDisplay.DOWN)
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]+1 && yPos < y[node]+ew+1;
+		else  if (treeDisplay.getOrientation()==treeDisplay.RIGHT) 
+			return xPos> x[node]+1 && xPos < x[node]+ew +1 && yPos > y[node] && yPos < y[node] + ew;
+		else  if (treeDisplay.getOrientation()==treeDisplay.LEFT)
+			return xPos> x[node]-ew-3 && xPos < x[node]-3 && yPos > y[node] && yPos < y[node] + ew;
+		else 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node] && yPos < y[node] + ew;
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		float localInset = 0;
+		if (ownerModule.getShowEdgeLines())
+			localInset=inset;
+		Rectangle2D box;
+		Rectangle2D colorBox;
+		Graphics2D g2 = (Graphics2D)g;
+		int numColors = colors.getNumColors();
+		float ew = edgewidth-1;
+		// the 0.5 values are the halfline width to deal with pen positioning
+		if (treeDisplay.getOrientation()==treeDisplay.UP) 
+			box = new Rectangle2D.Double(x[node]+0.5, y[node]-ew-2, ew, ew);
+		else if (treeDisplay.getOrientation()==treeDisplay.DOWN)
+			box = new Rectangle2D.Double(x[node]+0.5, y[node]+2, ew, ew);
+		else  if (treeDisplay.getOrientation()==treeDisplay.RIGHT) 
+			box = new Rectangle2D.Double(x[node]+2, y[node]+0.5, ew, ew);
+		else  if (treeDisplay.getOrientation()==treeDisplay.LEFT)
+			box = new Rectangle2D.Double(x[node]-ew-2, y[node]+0.5, ew, ew);
+		else 
+			box = new Rectangle2D.Double(x[node], y[node], ew, ew);
+		for (int i=0; i<numColors; i++) {
+			g2.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+			colorBox = new Rectangle2D.Double(box.getX() + (i*box.getWidth()/numColors), box.getY(), box.getWidth()-  (i*box.getWidth()/numColors), box.getHeight());
+			g2.fill(colorBox);
+		}
+		g2.setColor(treeDisplay.getBranchColor(node));
+		g2.draw(box);
+	}
+	/*_________________________________________________*
+	public void fillBranchWithMissingData(Tree tree, int node, Graphics g) {
+
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			Color c = g.getColor();
+			if (g instanceof Graphics2D){
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setPaint(GraphicsUtil.missingDataTexture);
+			}
+			else
+				g.setColor(Color.lightGray);
+			float localInset = 0;
+			if (ownerModule.getShowEdgeLines())
+				localInset=inset;
+			float fillWidth = edgewidth-2*localInset;
+			DrawTreeUtil.drawOneSquareLineBranch(treeDisplay,x,y,getEdgeWidth(), treeDisplay.getTree(), g, null, node, localInset,  fillWidth, 4,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			Color c = g.getColor();
+			float localInset = 0;
+			if (ownerModule.getShowEdgeLines())
+				localInset=inset;
+			float fillWidth = edgewidth-2*localInset;
+			int numColors = colors.getNumColors();
+			Color color;
+			if (numColors<=1) {
+				if ((color = colors.getColor(0, !tree.anySelected()|| tree.getSelected(node)))!=null)
+					g.setColor(color);
+				DrawTreeUtil.drawOneSquareLineBranch(treeDisplay,x,y,getEdgeWidth(), treeDisplay.getTree(), g, colors, node, localInset,  fillWidth, 4,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+			}
+			else
+				for (int i=0; i<numColors; i++) {
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					//			public static   void drawOneBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, Graphics g, int node, int start, int width, int adj, boolean emphasizeNodes, Polygon nodePoly, BasicStroke defaultStroke) {
+					float thickness = fillWidth/numColors;
+					float start = i*thickness+localInset;
+					DrawTreeUtil.fillOneSquareLineBranch(treeDisplay,x,y,getEdgeWidth(), treeDisplay.getTree(), g, colors, node, start,  thickness, localInset,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+				}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node)) {
+			//if (ownerModule.getShowEdgeLines())
+			DrawTreeUtil.drawOneSquareLineBranch(treeDisplay,x,y,getEdgeWidth(), tree, g, null, node, inset, edgewidth-inset*2, 4,emphasizeNodes(),nodePoly(node), defaultStroke) ;
+		}
+	}
+
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int doubleOffset = (getNodeWidth()-getEdgeWidth());
+		int startX = x[node] - offset;
+		int startY= y[node] - offset;
+		if (treeDisplay.getOrientation()==TreeDisplay.RIGHT){
+			startX -= getNodeWidth()-doubleOffset;
+		} else if (treeDisplay.getOrientation()==TreeDisplay.DOWN)
+			startY -= getNodeWidth()-doubleOffset;
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(startX,startY);
+		poly.addPoint(startX+getNodeWidth(),startY);
+		poly.addPoint(startX+getNodeWidth(),startY+getNodeWidth());
+		poly.addPoint(startX,startY+getNodeWidth());
+		poly.addPoint(startX,startY);
+		poly.npoints=5;
+		return poly;
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (DrawTreeUtil.inSquareLineBranch(treeDisplay, this.x, this.y, getEdgeWidth(), treeDisplay.getTaxonSpacing(), tree, node, x,y) || inNode(node,x,y)){
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							if (treeDisplay.getOrientation()==TreeDisplay.UP|| treeDisplay.getOrientation()==TreeDisplay.DOWN)  {
+								fraction.setValue( Math.abs(1.0*(y-this.y[motherNode])/(this.y[node]-this.y[motherNode])));
+							}
+							else if (treeDisplay.getOrientation()==TreeDisplay.LEFT || treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+								fraction.setValue( Math.abs(1.0*(x-this.x[motherNode])/(this.x[node]-this.x[motherNode])));
+							}
+						}
+					}
+			}
+
+			int thisSister = tree.firstDaughterOfNode(node);
+			while (tree.nodeExists(thisSister)) {
+				ScanBranches(tree, thisSister, x, y, fraction);
+				thisSister = tree.nextSisterOfNode(thisSister);
+			}
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, drawnRoot, x, y, fraction);
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+		preferredEdgeWidth = edw;
+	}
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+}
+
diff --git a/Source/mesquite/trees/SquareTree/SquareTree.java b/Source/mesquite/trees/SquareTree/SquareTree.java
new file mode 100644
index 0000000..dc92076
--- /dev/null
+++ b/Source/mesquite/trees/SquareTree/SquareTree.java
@@ -0,0 +1,1402 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.SquareTree;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.GeneralPath;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.stochchar.lib.MargLikeAncStForModel;
+import mesquite.stochchar.lib.MargLikelihoodForModel;
+import mesquite.trees.lib.*;
+
+/* ======================================================================== */
+public class SquareTree extends DrawTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NodeLocsVH.class, getName() + "  needs the locations of nodes to be calculated.",
+				"The calculator for node locations is chosen automatically or initially");
+	}
+	NodeLocsVH nodeLocsTask;
+	MesquiteCommand edgeWidthCommand;
+	MesquiteString orientationName;
+	Vector drawings;
+	int oldEdgeWidth = 6;
+	int ornt;
+	double shortcut = 0.0; //used of for eurogram 
+	double shortcutDegree = 0.4;
+	MesquiteString nodeLocsName;
+	StringArray cornerModes;
+	MesquiteString cornerModeName;
+	int cornerMode = 0;
+	int curvature = 50;
+	MesquiteBoolean simpleTriangle = new MesquiteBoolean(true);
+
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		drawings = new Vector();
+		nodeLocsTask= (NodeLocsVH)hireNamedEmployee(NodeLocsVH.class, "#NodeLocsStandard");
+		if (nodeLocsTask == null)
+			return sorry(getName() + " couldn't start because no node location module was obtained.");
+		nodeLocsName = new MesquiteString(nodeLocsTask.getName());
+		if (numModulesAvailable(NodeLocsVH.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Node Locations Calculator", makeCommand("setNodeLocs", this), NodeLocsVH.class);
+			mss.setSelected(nodeLocsName);
+		}
+		cornerModes = new StringArray(3);  
+		MesquiteSubmenuSpec cornersSubmenu = addSubmenu(null, "Corners", makeCommand("setCornerMode", this), cornerModes);
+		cornerModes.setValue(0, "Right Angle");  //the strings passed will be the menu item labels
+		cornerModes.setValue(1, "Diagonal");
+		cornerModes.setValue(2, "Curved");
+		cornerModeName = new MesquiteString(cornerModes.getValue(cornerMode));  //this helps the menu keep track of checkmenuitems
+		cornersSubmenu.setSelected(cornerModeName);
+
+
+		MesquiteSubmenuSpec orientationSubmenu = addSubmenu(null, "Orientation");
+		ornt = NodeLocsVH.defaultOrientation;  //should take out of preferences
+		orientationName = new MesquiteString(orient(ornt));
+		orientationSubmenu.setSelected(orientationName);
+		addItemToSubmenu(null, orientationSubmenu, "Up", makeCommand("orientUp",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Right", makeCommand("orientRight",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Down", makeCommand("orientDown",  this));
+		addItemToSubmenu(null, orientationSubmenu, "Left", makeCommand("orientLeft",  this));
+		addMenuItem( "Line Width...", makeCommand("setEdgeWidth",  this));
+		//	addCheckMenuItem(null, "Simple Triangle for Triangled Clades", makeCommand("toggleSimpleTriangle",  this), simpleTriangle);
+		return true;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		iQuit();
+	}
+	public   TreeDrawing createTreeDrawing(TreeDisplay treeDisplay, int numTaxa) {
+		SquareTreeDrawing treeDrawing =  new SquareTreeDrawing (treeDisplay, numTaxa, this);
+		if (legalOrientation(treeDisplay.getOrientation())){
+			orientationName.setValue(orient(treeDisplay.getOrientation()));
+			ornt = treeDisplay.getOrientation();
+		}
+		else
+			treeDisplay.setOrientation(ornt);
+		//treeDisplay.inhibitStretchByDefault = true;
+		drawings.addElement(treeDrawing);
+		return treeDrawing;
+	}
+	public boolean legalOrientation (int orientation){
+		return (orientation == TreeDisplay.UP || orientation == TreeDisplay.DOWN || orientation == TreeDisplay.RIGHT || orientation == TreeDisplay.LEFT);
+	}
+	/*.................................................................................................................*/
+	public String orient (int orientation){
+		if (orientation == TreeDisplay.UP)
+			return "Up";
+		else if (orientation == TreeDisplay.DOWN)
+			return "Down";
+		else if (orientation == TreeDisplay.RIGHT)
+			return "Right";
+		else if (orientation == TreeDisplay.LEFT)
+			return "Left";
+		else return "other";
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) { 
+		Snapshot temp = new Snapshot();
+		temp.addLine("setNodeLocs", nodeLocsTask);
+		temp.addLine("setEdgeWidth " + oldEdgeWidth); 
+		if (ornt== TreeDisplay.UP)
+			temp.addLine("orientUp"); 
+		else if (ornt== TreeDisplay.DOWN)
+			temp.addLine("orientDown"); 
+		else if (ornt== TreeDisplay.LEFT)
+			temp.addLine("orientLeft"); 
+		else if (ornt== TreeDisplay.RIGHT)
+			temp.addLine("orientRight"); 
+		//	temp.addLine("toggleCorners " + cutCorners.toOffOnString());
+		temp.addLine("setCornerMode " + ParseUtil.tokenize(cornerModes.getValue(cornerMode)) + "  " + curvature);
+		return temp;
+	}
+	MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the node locations calculator", "[name of module]", commandName, "setNodeLocs")) {
+			NodeLocsVH temp = (NodeLocsVH)replaceEmployee(NodeLocsVH.class, arguments, "Node Locations Calculator", nodeLocsTask);
+			if (temp != null) {
+				nodeLocsTask = temp;
+				nodeLocsName.setValue(nodeLocsTask.getName());
+				parametersChanged();
+			}
+			return nodeLocsTask;
+		}
+		else	if (checker.compare(this.getClass(), "Sets the thickness of drawn branches", "[width in pixels]", commandName, "setEdgeWidth")) {
+			int newWidth= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (!MesquiteInteger.isCombinable(newWidth))
+				newWidth = MesquiteInteger.queryInteger(containerOfModule(), "Set edge width", "Edge Width:", oldEdgeWidth, 1, 99);
+			if (newWidth>0 && newWidth<100 && newWidth!=oldEdgeWidth) {
+				oldEdgeWidth=newWidth;
+				if (drawings == null)
+					return null;
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+					treeDrawing.setEdgeWidth(newWidth);
+					if (treeDrawing.treeDisplay != null)
+						treeDrawing.treeDisplay.setMinimumTaxonNameDistance(treeDrawing.edgewidth, 5); //better if only did this if tracing on
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not corners are cut", "[on = cut; off]", commandName, "toggleCorners")) {  //defunct; for combatibility with old files
+			MesquiteBoolean cutCorners = new MesquiteBoolean(false);
+			cutCorners.toggleValue(parser.getFirstToken(arguments));
+			if (cutCorners.getValue()){
+				cornerMode = 1;
+				cornerModeName.setValue(cornerModes.getValue(cornerMode)); //so that menu item knows to become checked
+			}
+			Enumeration e = drawings.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+				treeDrawing.cornerMode = this.cornerMode;
+			}
+			if (!MesquiteThread.isScripting()) parametersChanged();
+		}
+		else if (checker.compare(getClass(), "Sets the corner mode", null, commandName, "setCornerMode")) {
+			String name = parser.getFirstToken(arguments); //get argument passed of option chosen
+			int newMode = cornerModes.indexOf(name); //see if the option is recognized by its name
+			if (newMode >=0 && newMode!=cornerMode){
+				cornerMode = newMode; //change mode
+				cornerModeName.setValue(cornerModes.getValue(cornerMode)); //so that menu item knows to become checked
+				if (cornerMode == 2){
+					String curveS = parser.getNextToken();
+					int curveD = MesquiteInteger.fromString(curveS);
+
+					if (MesquiteInteger.isCombinable(curveD))
+						curvature = curveD;
+					else if (!MesquiteThread.isScripting()){
+						curveD = MesquiteInteger.queryInteger(containerOfModule(), "Corner Curve", "Curvature (10 to 1000; suggested 50)", curvature, 10, 1000);
+						if (MesquiteInteger.isCombinable(curveD))
+							curvature = curveD;
+					}
+				}
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+					treeDrawing.cornerMode = this.cornerMode;
+				}
+				if (!MesquiteThread.isScripting()) parametersChanged();
+			}
+			else 	if (newMode == 2){
+				String curveS = parser.getNextToken();
+				int curveD = MesquiteInteger.fromString(curveS);
+
+				if (MesquiteInteger.isCombinable(curveD))
+					curvature = curveD;
+				else if (!MesquiteThread.isScripting()){
+					curveD = MesquiteInteger.queryInteger(containerOfModule(), "Corner Curve", "Curvature (10 to 1000; suggested 50)", curvature, 10, 1000);
+					if (MesquiteInteger.isCombinable(curveD))
+						curvature = curveD;
+					if (!MesquiteThread.isScripting()) parametersChanged();
+				}
+			}
+
+		}
+		else if (checker.compare(this.getClass(), "Returns the module calculating node locations", null, commandName, "getNodeLocsEmployee")) {
+			return nodeLocsTask;
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are on top", null, commandName, "orientUp")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.UP;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.UP);
+				if (treeDrawing.treeDisplay != null)
+					ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at the bottom", null, commandName, "orientDown")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.DOWN;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.DOWN);
+				if (treeDrawing.treeDisplay != null)
+					ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at right", null, commandName, "orientRight")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.RIGHT;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.RIGHT);
+				if (treeDrawing.treeDisplay != null)
+					ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Orients the tree drawing so that the terminal taxa are at left", null, commandName, "orientLeft")) {
+			Enumeration e = drawings.elements();
+			ornt = TreeDisplay.LEFT;
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+				treeDrawing.reorient(TreeDisplay.LEFT);
+				if (treeDrawing.treeDisplay != null)
+					ornt = treeDrawing.treeDisplay.getOrientation();
+			}
+			orientationName.setValue(orient(ornt));
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to draw triangled clades as simple triangles or not.", "", commandName, "toggleSimpleTriangle")) {
+			boolean current = simpleTriangle.getValue();
+			simpleTriangle.toggleValue(parser.getFirstToken(arguments));
+			if (current!=simpleTriangle.getValue()) {
+				Enumeration e = drawings.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					SquareTreeDrawing treeDrawing = (SquareTreeDrawing)obj;
+					treeDrawing.setSimpleTriangle(simpleTriangle.getValue());
+				}
+				parametersChanged();
+			}
+		}
+		else return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Classic Square tree";
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getVersion() {
+		return null;
+	}
+	/*.................................................................................................................*/
+
+	/** returns an explanation of what the module does.*/
+	public String getExplanation() {
+		return "Draws trees with standard square branches (\"phenogram\")" ;
+	}
+	/*.................................................................................................................*/
+
+}
+
+
+/* ======================================================================== */
+class SquareTreeDrawing extends TreeDrawing   {
+	public Polygon[] branchPoly;
+	public Polygon[] touchPoly;
+	public Polygon[] fillBranchPoly;
+
+	public SquareTree ownerModule;
+	public int edgewidth = 6;
+	public int preferredEdgeWidth = 6;
+	int oldNumTaxa = 0;
+	private int foundBranch;
+	private boolean ready=false;
+	private static final int  inset=1;
+	private Polygon utilityPolygon;
+	NameReference triangleNameRef;
+	int cornerMode;
+	BasicStroke defaultStroke;
+
+
+	public SquareTreeDrawing(TreeDisplay treeDisplay, int numTaxa, SquareTree ownerModule) {
+		super(treeDisplay, MesquiteTree.standardNumNodeSpaces(numTaxa));
+		treeDisplay.setMinimumTaxonNameDistance(edgewidth, 5); //better if only did this if tracing on
+		this.ownerModule = ownerModule;
+		this.treeDisplay = treeDisplay;
+		triangleNameRef = NameReference.getNameReference("triangled");
+		try{
+			defaultStroke = new BasicStroke();
+		}
+		catch (Throwable t){
+		}
+
+		cornerMode = ownerModule.cornerMode;
+
+		oldNumTaxa = numTaxa;
+		ready = true;
+		treeDisplay.setOrientation(ownerModule.nodeLocsTask.getDefaultOrientation());
+		utilityPolygon=new Polygon();
+		utilityPolygon.xpoints = new int[16];
+		utilityPolygon.ypoints = new int[16];
+		utilityPolygon.npoints=16;
+
+	}
+
+	public void resetNumNodes(int numNodes){
+		super.resetNumNodes(numNodes);
+		branchPoly= new Polygon[numNodes];
+		touchPoly= new Polygon[numNodes];
+		fillBranchPoly= new Polygon[numNodes];
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = new Polygon();
+			branchPoly[i].xpoints = new int[16];
+			branchPoly[i].ypoints = new int[16];
+			branchPoly[i].npoints=16;
+			touchPoly[i] = new Polygon();
+			touchPoly[i].xpoints = new int[16];
+			touchPoly[i].ypoints = new int[16];
+			touchPoly[i].npoints=16;
+			fillBranchPoly[i] = new Polygon();
+			fillBranchPoly[i].xpoints = new int[16];
+			fillBranchPoly[i].ypoints = new int[16];
+			fillBranchPoly[i].npoints=16;
+		}		
+	}
+	private boolean isUP(){
+		return treeDisplay.getOrientation()==TreeDisplay.UP;
+	}
+	private boolean isDOWN(){
+		return treeDisplay.getOrientation()==TreeDisplay.DOWN;
+	}
+	private boolean isLEFT(){
+		return treeDisplay.getOrientation()==TreeDisplay.LEFT;
+	}
+	private boolean isRIGHT(){
+		return treeDisplay.getOrientation()==TreeDisplay.RIGHT;
+	}
+	/*_________________________________________________*/
+	private int length(int node, int mother){
+		if (isUP())
+			return y[mother]-y[node];
+		else if (isDOWN())
+			return y[node]-y[mother];
+		else if (isLEFT())
+			return x[mother]-x[node];
+		else if (isRIGHT())
+			return x[node]-x[mother];
+		return 0;
+	}
+	private int getShortcutOfDaughters(Tree tree, int node){
+		if (cornerMode != 1)
+			return 0;
+		int s = MesquiteInteger.unassigned;
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			s = MesquiteInteger.minimum(s, length(d, node));  //find shortest descendant
+		return (int)(ownerModule.shortcutDegree*s);
+	}
+	private int getOffset(int width) {
+		return (width-getEdgeWidth())/2;
+	}
+	/*_________________________________________________*/
+	//makes polygon clockwise
+	private void UPdefineFillPoly(Polygon poly, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices, int nShortcut, boolean complete) {
+		int sliceWidth=edgewidth;
+		if (numSlices>1) {
+			Nx+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			sliceWidth=(edgewidth-inset)-( (sliceNumber-1)*(edgewidth-inset)/numSlices);
+		}
+		//rightedge needs to join to right edge of mother, not left edge of mother
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx+inset, Ny+inset); // root left
+			poly.addPoint(Nx+sliceWidth-inset, Ny+inset);	//root right 
+			poly.addPoint(Nx+sliceWidth-inset, mNy); //subroot right
+			poly.addPoint(Nx+inset, mNy); //subroot left
+			poly.addPoint(Nx+inset, Ny+inset); //return to root left
+			poly.npoints=5;
+		}
+		else if (Nx<mNx) //left leaning (*)
+		{
+			poly.npoints=0;
+			if (numSlices>1)
+				mNy+=inset;
+			//if (numSlices>1)
+			//	mNy-= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			poly.addPoint(Nx+inset, Ny+inset); // daugher left
+			poly.addPoint(Nx+sliceWidth-inset, Ny+inset);	//daughter right 
+			poly.addPoint(Nx+sliceWidth-inset, mNy+inset - nShortcut); //corner right
+			if (complete){
+				poly.addPoint(mNx+sliceWidth-inset, mNy+inset); //mother up (right edge)
+				poly.addPoint(mNx, mNy+sliceWidth-inset); //mother down (left edge)
+				poly.addPoint(Nx+inset, mNy+sliceWidth-inset -  nShortcut); //corner left
+			}
+			else
+				poly.addPoint(Nx+inset, mNy+inset -  nShortcut); //corner left
+			poly.addPoint(Nx+inset, Ny+inset); //return to daughter left 
+			//	poly.npoints=7;
+		}
+		else { //right leaning(*)
+			poly.npoints=0;
+			if (numSlices>1)
+				mNy+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			poly.addPoint(Nx+inset, Ny+inset); // daugher left
+			poly.addPoint(Nx+sliceWidth-inset, Ny+inset);//daughter right 
+			if (complete){
+				poly.addPoint(Nx+sliceWidth-inset, mNy+sliceWidth-inset -  nShortcut); //corner right
+				poly.addPoint(mNx+sliceWidth-inset, mNy+sliceWidth-inset); //mother down (right edge)
+				poly.addPoint(mNx, mNy+inset); //mother up (left edge)
+			}
+			else {
+				poly.addPoint(Nx+sliceWidth-inset, mNy + inset -  nShortcut); //corner right
+			}
+			poly.addPoint(Nx+inset, mNy+inset -  nShortcut); //corner left
+			poly.addPoint(Nx+inset, Ny+inset);  //return to daughter left
+			//	poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	private void UPCalcFillBranchPolys(Tree tree, int node, int nShortcut)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcFillBranchPolys(tree, d, dShortcut);
+		}
+		UPdefineFillPoly(fillBranchPoly[node], (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0, nShortcut, true);
+	}
+
+	/*_________________________________________________*/
+	private void UPCalcBranchPolys(Tree tree, int node, int nShortcut, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				UPCalcBranchPolys(tree, d, dShortcut, polys, width);
+		}
+		DrawTreeUtil.UPdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], nShortcut);
+	}
+	/*_________________________________________________*/
+	//makes polygon counterclockwise
+	private void DOWNdefineFillPoly(Polygon poly, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices, int nShortcut, boolean complete) {
+		int sliceWidth=edgewidth;
+		if (numSlices>1) {
+			Nx+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			sliceWidth=(edgewidth-inset)-((sliceNumber-1)*(edgewidth-inset)/numSlices);
+		}
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx+inset, Ny-inset); //root right
+			poly.addPoint(Nx+sliceWidth-inset, Ny-inset);	//root left
+			poly.addPoint(Nx+sliceWidth-inset, mNy);  //subroot left
+			poly.addPoint(Nx+inset, mNy); //subroot right
+			poly.addPoint(Nx+inset, Ny-inset); //return to root right
+			poly.npoints=4;
+		}
+		else if (Nx>mNx) //left leaning
+		{
+			poly.npoints=0;
+			if (numSlices>1)
+				mNy-= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			poly.addPoint(Nx+inset, Ny-inset);// daughter right
+			poly.addPoint(Nx+sliceWidth-inset, Ny-inset);//daughter left
+
+			if (complete){
+				poly.addPoint(Nx+sliceWidth-inset, mNy-sliceWidth+inset + nShortcut);//corner left
+				poly.addPoint(mNx+sliceWidth-inset, mNy-sliceWidth+inset); //mother down * on x
+				poly.addPoint(mNx, mNy-inset);//mother up 
+			}
+			else
+				poly.addPoint(Nx+sliceWidth-inset, mNy+inset + nShortcut);//corner left
+
+			poly.addPoint(Nx+inset, mNy-inset + nShortcut);//corner right
+
+			poly.addPoint(Nx+inset, Ny-inset); //return to daughter right
+		}
+		else {
+			poly.npoints=0;
+			if (numSlices>1)
+				mNy-=inset;
+			poly.addPoint(Nx+inset, Ny-inset); // daughter right
+			poly.addPoint(Nx+sliceWidth-inset, Ny-inset);	//daughter left
+			poly.addPoint(Nx+sliceWidth-inset, mNy-inset + nShortcut);//corner left
+			if (complete){
+				poly.addPoint(mNx+sliceWidth-inset, mNy-inset); //mother up * on x
+				poly.addPoint(mNx, mNy-sliceWidth+inset); //mother down 
+				poly.addPoint(Nx+inset, mNy-sliceWidth+inset + nShortcut); //corner right
+			}
+			else
+				poly.addPoint(Nx+inset, mNy+inset + nShortcut); //corner right
+
+			poly.addPoint(Nx+inset, Ny-inset); //return to daugher right
+		}
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcFillBranchPolys(Tree tree, int node, int nShortcut)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcFillBranchPolys(tree, d, dShortcut);
+		}
+		DOWNdefineFillPoly(fillBranchPoly[node], (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0, nShortcut, true);
+	}
+	/*_________________________________________________*/
+	private void DOWNCalcBranchPolys(Tree tree, int node, int nShortcut, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				DOWNCalcBranchPolys(tree, d, dShortcut, polys, width);
+		}
+		DrawTreeUtil.DOWNdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],  nShortcut);
+	}
+	/*_________________________________________________*/
+	//makes polygon clockwise
+	private void RIGHTdefineFillPoly(Polygon poly, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices,  int nShortcut, boolean complete) {
+		int sliceWidth=edgewidth;
+		if (numSlices>1) {
+			Ny+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			sliceWidth=(edgewidth-inset)-((sliceNumber-1)*(edgewidth-inset)/numSlices);
+		}
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx-inset, Ny+inset);// root left
+			poly.addPoint(Nx-inset, Ny+sliceWidth-inset);	//root right 
+			poly.addPoint(mNx, Ny+sliceWidth-inset); //subroot right
+			poly.addPoint(mNx, Ny+inset); //subroot left
+			poly.addPoint(Nx-inset, Ny+inset); //return to root left
+			poly.npoints=4;
+		}
+		else if (Ny<mNy) //leans left
+		{
+			poly.npoints=0;
+			//if (numSlices>1)
+			//	mNx+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			if (numSlices>1)
+				mNx-=inset;
+			poly.addPoint(Nx-inset, Ny+inset); // daughter left
+			poly.addPoint(Nx-inset, Ny+sliceWidth-inset);	//daughter right
+			poly.addPoint(mNx-inset + nShortcut, Ny+sliceWidth-inset);//corner right
+			if (complete){
+				poly.addPoint(mNx-inset, mNy +sliceWidth-inset); //mother up * on y
+				poly.addPoint(mNx-sliceWidth+inset, mNy); //mother down
+				poly.addPoint(mNx-sliceWidth+inset + nShortcut, Ny+inset); //corner left
+			}
+			else 
+
+				poly.addPoint(mNx+inset + nShortcut, Ny+inset); //corner left
+			poly.addPoint(Nx-inset, Ny+inset); //return to daughter left
+		}
+		else {
+			poly.npoints=0;
+			if (numSlices>1)
+				mNx-= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			poly.addPoint(Nx-inset, Ny+inset);// daughter left
+			poly.addPoint(Nx-inset, Ny+sliceWidth-inset);//daughter right
+			if (complete){
+				poly.addPoint(mNx-sliceWidth+inset + nShortcut, Ny+sliceWidth-inset);//corner right
+				poly.addPoint(mNx-sliceWidth+inset, mNy+sliceWidth-inset);//mother down * on y
+				poly.addPoint(mNx-inset, mNy);//mother up
+			}
+			else
+				poly.addPoint(mNx+inset + nShortcut, Ny+sliceWidth-inset);//corner right
+			poly.addPoint(mNx-inset + nShortcut, Ny+inset); //corner left
+
+			poly.addPoint(Nx-inset, Ny+inset); //return to daughter left
+		}
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcFillBranchPolys(Tree tree, int node, int nShortcut)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcFillBranchPolys(tree, d, dShortcut);
+		}
+		RIGHTdefineFillPoly(fillBranchPoly[node], (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0,  nShortcut, true);
+	}
+	/*_________________________________________________*/
+	private void RIGHTCalcBranchPolys(Tree tree, int node, int nShortcut, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()){
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				RIGHTCalcBranchPolys(tree, d, dShortcut, polys, width);
+		}
+		DrawTreeUtil.RIGHTdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],  nShortcut);
+	}
+	/*_________________________________________________*/
+	/* make polygon counterclockwise*/
+	private void LEFTdefineFillPoly(Polygon poly, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int sliceNumber, int numSlices, int nShortcut, boolean complete) {
+		int sliceWidth=edgewidth;
+		if (numSlices>1) {
+			Ny+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			sliceWidth=(edgewidth-inset)-((sliceNumber-1)*(edgewidth-inset)/numSlices);
+		}
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx+inset, Ny+inset); // root right
+			poly.addPoint(Nx+inset, Ny+sliceWidth-inset);	//root left
+			poly.addPoint(mNx, Ny+sliceWidth-inset);//subroot left
+			poly.addPoint(mNx, Ny+inset); //subroot right
+			poly.addPoint(Nx+inset, Ny+inset);  //return to root right
+			poly.npoints=5;
+		}
+		else if (Ny>mNy) //left leaning
+		{
+			poly.npoints=0;
+			if (numSlices>1)
+				mNx+=inset;
+			poly.addPoint(Nx+inset, Ny+inset);// daughter right 
+			poly.addPoint(Nx+inset, Ny+sliceWidth-inset);	//daughter left
+			if (complete){
+				poly.addPoint(mNx+sliceWidth -  nShortcut-inset, Ny+sliceWidth-inset);//corner left/
+				poly.addPoint(mNx+sliceWidth-inset, mNy +sliceWidth-inset); //mother down
+				poly.addPoint(mNx+inset, mNy); //mother up
+			}
+			else 
+				poly.addPoint(mNx -  nShortcut-inset, Ny+sliceWidth-inset);//corner left/
+			poly.addPoint(mNx+inset -  nShortcut, Ny+inset); //corner right
+			poly.addPoint(Nx+inset, Ny+inset); //return to daughter right
+		}
+		else {
+			poly.npoints=0;
+			if (numSlices>1)
+				mNx+= (sliceNumber-1)*(edgewidth-inset)/numSlices;
+			poly.addPoint(Nx+inset, Ny+inset);// daughter right
+			poly.addPoint(Nx+inset, Ny+sliceWidth-inset);//daughter left
+			poly.addPoint(mNx -  nShortcut+inset, Ny+sliceWidth-inset); // corner left
+			if (complete){
+				poly.addPoint(mNx+inset, mNy+sliceWidth-inset); //mother up
+				poly.addPoint(mNx+sliceWidth-inset, mNy);  //mother down 
+				poly.addPoint(mNx +sliceWidth-  nShortcut - inset, Ny+inset); //corner right
+			}
+			else
+				poly.addPoint(mNx -  nShortcut - inset, Ny+inset); //corner right
+
+			poly.addPoint(Nx+inset, Ny+inset); //return to daughter right
+		}
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcFillBranchPolys(Tree tree, int node, int nShortcut)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()) {
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcFillBranchPolys(tree, d, dShortcut);
+		}
+		LEFTdefineFillPoly(fillBranchPoly[node], (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 0, 0,  nShortcut, true);
+	}
+	/*_________________________________________________*/
+	private void LEFTCalcBranchPolys(Tree tree, int node, int nShortcut, Polygon[] polys, int width)
+	{
+		if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle()){
+			int dShortcut = getShortcutOfDaughters(tree, node);
+			for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+				LEFTCalcBranchPolys(tree, d, dShortcut, polys, width);
+		}
+		DrawTreeUtil.LEFTdefineSquarePoly(this,polys[node], width, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)],  nShortcut);
+	}
+	/*_________________________________________________*/
+	private void UPDOWNcalculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			UPDOWNcalculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[tree.motherOfNode(node)];
+		lineBaseX[node]=x[node];
+	}
+	/*_________________________________________________*/
+	private void LEFTRIGHTcalculateLines(Tree tree, int node) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			LEFTRIGHTcalculateLines( tree, d);
+		lineTipY[node]=y[node];
+		lineTipX[node]=x[node];
+		lineBaseY[node]=y[node];
+		lineBaseX[node]=x[tree.motherOfNode(node)];
+	}
+	int oops = 0;
+	/*_________________________________________________*/
+	private void calcBranches(Tree tree, int drawnRoot) {
+		if (ownerModule==null) {MesquiteTrunk.mesquiteTrunk.logln("ownerModule null"); return;}
+		if (ownerModule.nodeLocsTask==null) {ownerModule.logln("nodelocs task null"); return;}
+		if (treeDisplay==null) {ownerModule.logln("treeDisplay null"); return;}
+		if (tree==null) { ownerModule.logln("tree null"); return;}
+
+		ownerModule.nodeLocsTask.calculateNodeLocs(treeDisplay,  tree, drawnRoot,  treeDisplay.getField()); //Graphics g removed as parameter May 02
+		edgewidth = preferredEdgeWidth;
+		if (treeDisplay.getTaxonSpacing()<edgewidth+2) {
+			edgewidth= treeDisplay.getTaxonSpacing()-2;
+			if (edgewidth<2)
+				edgewidth=2;
+		}
+		treeDisplay.setMinimumTaxonNameDistance(edgewidth, 5);
+		if (isUP()) {
+			UPCalcBranchPolys(tree, drawnRoot, oops, branchPoly, getEdgeWidth());
+			UPCalcBranchPolys(tree, drawnRoot, oops, touchPoly, getNodeWidth());
+			UPCalcFillBranchPolys(tree, drawnRoot, oops);
+			UPDOWNcalculateLines(tree, drawnRoot);
+		}
+		else if (isDOWN()){
+			DOWNCalcBranchPolys(tree, drawnRoot, oops, branchPoly, getEdgeWidth());
+			DOWNCalcBranchPolys(tree, drawnRoot, oops, touchPoly, getNodeWidth());
+			DOWNCalcFillBranchPolys(tree, drawnRoot, oops);
+			UPDOWNcalculateLines(tree, drawnRoot);
+		}
+		else  if (isRIGHT()) {
+			RIGHTCalcBranchPolys(tree, drawnRoot, oops, branchPoly, getEdgeWidth());
+			RIGHTCalcBranchPolys(tree, drawnRoot, oops, touchPoly, getNodeWidth());
+			RIGHTCalcFillBranchPolys(tree, drawnRoot, oops);
+			LEFTRIGHTcalculateLines(tree, drawnRoot);
+		}
+		else  if (isLEFT()){
+			LEFTCalcBranchPolys(tree, drawnRoot, oops, branchPoly, getEdgeWidth());
+			LEFTCalcBranchPolys(tree, drawnRoot, oops, touchPoly, getNodeWidth());
+			LEFTCalcFillBranchPolys(tree, drawnRoot, oops);
+			LEFTRIGHTcalculateLines(tree, drawnRoot);
+		}
+	}
+
+	/*New version, accounting for width of drawn branches*/
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if(tree==null || xValue==null || yValue==null)
+			return;
+		if(!tree.nodeExists(N))
+			return;
+		int mother = tree.motherOfNode(N);
+		if(isUP()){
+			xValue.setValue(x[N] + getEdgeWidth()/2);
+			yValue.setValue(y[mother]+(y[N]-y[mother])/2 + getEdgeWidth()/2);
+			angle.setValue(-Math.PI/2.0);
+		}
+		else if (isDOWN()){
+			xValue.setValue(x[N] + getEdgeWidth()/2);
+			yValue.setValue(y[N]+(y[mother]-y[N])/2 - getEdgeWidth()/2);
+			angle.setValue(Math.PI/2.0);
+		}
+		else  if (isRIGHT()) {
+			xValue.setValue(x[mother]+(x[N]-x[mother])/2 - getEdgeWidth()/2);
+			yValue.setValue(y[N] + getEdgeWidth()/2);
+			angle.setValue(0.0);
+		}
+		else  if (isLEFT()){
+			xValue.setValue(x[N]+(x[mother]-x[N])/2 + getEdgeWidth()/2);
+			yValue.setValue(y[N] + getEdgeWidth()/2);
+			angle.setValue(Math.PI);
+		}
+	}
+	/*	
+	public void getMiddleOfBranch(Tree tree, int N, MesquiteNumber xValue, MesquiteNumber yValue, MesquiteDouble angle){
+		if (tree==null || xValue==null || yValue==null)
+			return;
+		if (!tree.nodeExists(N))
+			return;
+
+		int mother = tree.motherOfNode(N);
+		if (isUP()) {
+			xValue.setValue(x[N]);
+			yValue.setValue(y[mother]+(y[N]-y[mother])/2);
+			angle.setValue(-Math.PI/2.0);
+		}
+		else if (isDOWN()){
+			xValue.setValue(x[N]);
+			yValue.setValue(y[N]+(y[mother]-y[N])/2);
+			angle.setValue(Math.PI/2.0);
+		}
+		else  if (isRIGHT()) {
+			xValue.setValue(x[mother]+(x[N]-x[mother])/2);
+			yValue.setValue(y[N]);
+			angle.setValue(0.0);
+		}
+		else  if (isLEFT()){
+			xValue.setValue(x[N]+(x[mother]-x[N])/2);
+			yValue.setValue(y[N]);
+			angle.setValue(Math.PI);
+		}
+	}*/
+	/*_________________________________________________*
+	private   void drawLeftSideOfClade(Tree tree, Graphics g, int node) {
+		if (tree.nodeIsInternal(node)) {
+			int firstDaughter = tree.firstDaughterOfNode(node);
+			if (tree.nodeExists(firstDaughter)) {
+				g.drawLine(x[node],y[node], x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]);
+				g.drawLine(x[node]+1,y[node], x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]);
+				g.drawLine(x[node],y[node]+1, x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]+1);
+				g.drawLine(x[node]+1,y[node]+1, x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]+1);
+			}
+		}
+
+
+
+	}
+
+	/*_________________________________________________*/
+	private   void drawOneBranch(Tree tree, Graphics g, int node) {
+		if (tree.nodeExists(node)) {
+			//g.setColor(Color.black);//for testing
+			boolean draw = branchIsVisible(node);
+			if (draw){
+				g.setColor(treeDisplay.getBranchColor(node));
+				if ((tree.getRooted() || tree.getRoot()!=node) && branchPoly[node] != null){
+					if (SHOWTOUCHPOLYS && touchPoly!=null && touchPoly[node]!=null) {  //fordebugging
+						Color prev = g.getColor();
+						g.setColor(ColorDistribution.burlyWood);
+						g.fillPolygon(touchPoly[node]);
+						g.setColor(prev);
+					}
+					fillOneBranch(tree, g, branchPoly[node], node, true);
+				}
+				if (tree.numberOfParentsOfNode(node)>1) {
+					for (int i=1; i<=tree.numberOfParentsOfNode(node); i++) {
+						int anc =tree.parentOfNode(node, i);
+						if (anc!= tree.motherOfNode(node)) {
+							g.drawLine(x[node],y[node], x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node]+1,y[node], x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]);
+							g.drawLine(x[node],y[node]+1, x[tree.parentOfNode(node, i)],y[tree.parentOfNode(node, i)]+1);
+							g.drawLine(x[node]+1,y[node]+1, x[tree.parentOfNode(node, i)]+1,y[tree.parentOfNode(node, i)]+1);
+						}
+					}
+				}
+				if (tree.getAssociatedBit(triangleNameRef,node)) 
+					if (treeDisplay.getSimpleTriangle()) {
+						for (int j=0; j<2; j++)
+							for (int i=0; i<2; i++) {
+								g.drawLine(x[node]+i,y[node]+j, x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j);
+								g.drawLine(x[tree.leftmostTerminalOfNode(node)]+i,y[tree.leftmostTerminalOfNode(node)]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+								g.drawLine(x[node]+i,y[node]+j, x[tree.rightmostTerminalOfNode(node)]+i,y[tree.rightmostTerminalOfNode(node)]+j);
+							}
+					} else {
+						//	drawLeftSideOfClade(tree, g, node);
+					}
+			}
+			if (!tree.getAssociatedBit(triangleNameRef,node) || !treeDisplay.getSimpleTriangle())
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					drawOneBranch(tree, g, d);
+			//g.setColor(Color.green);//for testing
+			//g.fillPolygon(fillBranchPoly[node]); //for testing
+			//g.setColor(Color.black);//for testing
+			//	redCrosses(g, tree, node);
+
+			if (draw && emphasizeNodes()) {
+				Color prev = g.getColor();
+				g.setColor(Color.red);//for testing
+				fillOneBranch(tree, g, nodePoly(node), node, true);
+				g.setColor(prev);
+			}
+		}
+	}
+	//normal 0, edgewidth
+	// fill withcolours drawOneCurvedBranch( start, width inset + i*fillWidth/numColors,  (i+1)*fillWidth/numColors -i*fillWidth/numColors) ;
+	// fill drawOneCurvedBranch(inset, edgewidth-inset*2) ;
+	/*_________________________________________________*/
+	private void drawOneCurvedBranch(Tree tree, Graphics g, int node, int start, int width) {
+		if (tree.nodeExists(node)) {
+			if (width<0)
+				width = 0;
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];
+
+			if (treeDisplay.getOrientation()==TreeDisplay.UP || treeDisplay.getOrientation()==TreeDisplay.DOWN){
+				xN += width/2+start;
+				xnM += width/2;
+
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT || treeDisplay.getOrientation()==TreeDisplay.LEFT){ 
+				yN += width/2+start;
+				ynM += width/2;
+			}
+
+			GeneralPath arc = null;
+			double curveD = ownerModule.curvature;
+
+			if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+				arc = new GeneralPath(); // left
+				arc.moveTo(xN, yN);
+				if (ynM-yN>curveD)
+					arc.lineTo(xN, (float)(ynM-curveD));
+				arc.curveTo(xN, ynM, xN, ynM, xnM, ynM);
+				arc.lineTo(xnM, ynM);
+			}
+
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){//����
+				arc = new GeneralPath(); // left
+				arc.moveTo(xN, yN);
+				if (yN - ynM>curveD)
+					arc.lineTo(xN, (float)(ynM+curveD));
+				arc.curveTo(xN, ynM, xN, ynM, xnM, ynM);
+				arc.lineTo(xnM, ynM);
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+				arc = new GeneralPath(); // left
+				arc.moveTo(xN, yN);
+				if (xN - xnM>curveD)
+					arc.lineTo((float)(xnM+curveD), yN);
+				arc.curveTo(xnM, yN, xnM, yN, xnM, ynM);
+				arc.lineTo(xnM, ynM);
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){ //����
+				arc = new GeneralPath(); // left
+				arc.moveTo(xN, yN);
+				if (xnM - xN>curveD)
+					arc.lineTo((float)(xnM-curveD), yN);
+				arc.curveTo(xnM, yN, xnM, yN, xnM, ynM);
+				arc.lineTo(xnM, ynM);
+			}
+			if (arc!=null) {
+				BasicStroke wideStroke = new BasicStroke(width);
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setStroke(wideStroke);
+				g2.draw(arc);
+				g2.setStroke(defaultStroke);
+			}
+
+
+		}
+	}
+
+	void fillOneBranch(Tree tree, Graphics g, Polygon poly, int node, boolean total){
+		if (cornerMode == 2){
+			if (!total)
+				drawOneCurvedBranch(tree, g, node, inset, edgewidth-inset*2) ;
+			else
+				drawOneCurvedBranch(tree, g, node, 0, edgewidth) ;
+		}
+		else
+			g.fillPolygon(poly);
+		/*for (int i = 0 ; i < poly.npoints-1; i++){
+					g.drawLine(poly.xpoints[i], poly.ypoints[i], poly.xpoints[i+1] , poly.ypoints[i+1]);
+		}
+		 */
+	}
+	/*_________________________________________________*/
+	public   void drawTree(Tree tree, int drawnRoot, Graphics g) {
+		if (MesquiteTree.OK(tree)) {
+			if (treeDisplay == null)
+				return;
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			g.setColor(treeDisplay.branchColor);
+			/*if (oldNumTaxa!= tree.getNumTaxa())
+	        		adjustNumTaxa(tree.getNumTaxa()); */
+
+			drawOneBranch(tree, g, drawnRoot);  
+		}
+	}
+	/*_________________________________________________*/
+	public   void recalculatePositions(Tree tree) {
+		if (MesquiteTree.OK(tree)) {
+			if (tree.getNumNodeSpaces()!=numNodes)
+				resetNumNodes(tree.getNumNodeSpaces());
+			if (!tree.nodeExists(getDrawnRoot()))
+				setDrawnRoot(tree.getRoot());
+			calcBranches(tree, getDrawnRoot());
+		}
+	}
+	/*_________________________________________________*/
+	/** Draw highlight for branch node with current color of graphics context */
+	public void drawHighlight(Tree tree, int node, Graphics g, boolean flip){
+		Color tC = g.getColor();
+		if (flip)
+			g.setColor(Color.red);
+		else
+			g.setColor(Color.blue);
+		if (isDOWN() || isUP()){
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node]-2 - i, y[node], x[node]-2 - i, y[tree.motherOfNode(node)]);
+		}
+		else {
+			for (int i=0; i<4; i++)
+				g.drawLine(x[node], y[node]-2 - i, x[tree.motherOfNode(node)], y[node]-2 - i);
+		}
+		g.setColor(tC);
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBox(Tree tree, int node, Graphics g) {
+		Rectangle box;
+		int ew = edgewidth-1;
+		if (isUP()) 
+			box = new Rectangle(x[node], y[node]-ew-3, ew, ew);
+		else if (isDOWN())
+			box = new Rectangle(x[node], y[node]+1, ew, ew);
+		else  if (isRIGHT()) 
+			box = new Rectangle(x[node]+1, y[node], ew, ew);
+		else  if (isLEFT())
+			box = new Rectangle(x[node]-ew-3, y[node], ew, ew);
+		else 
+			box = new Rectangle(x[node], y[node], ew, ew);
+		g.fillRect(box.x, box.y, box.width, box.height);
+		g.setColor(treeDisplay.getBranchColor(node));
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+	/*_________________________________________________*/
+	public  void fillTerminalBoxWithColors(Tree tree, int node, ColorDistribution colors, Graphics g){
+		Rectangle box;
+		int numColors = colors.getNumColors();
+		int ew = edgewidth-1;
+		if (isUP()) 
+			box = new Rectangle(x[node], y[node]-ew-3, ew, ew);
+		else if (isDOWN())
+			box = new Rectangle(x[node], y[node]+1, ew, ew);
+		else  if (isRIGHT()) 
+			box = new Rectangle(x[node]+1, y[node], ew, ew);
+		else  if (isLEFT())
+			box = new Rectangle(x[node]-ew-3, y[node], ew, ew);
+		else 
+			box = new Rectangle(x[node], y[node], ew, ew);
+		for (int i=0; i<numColors; i++) {
+			g.setColor(colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)));
+			g.fillRect(box.x + (i*box.width/numColors), box.y, box.width-  (i*box.width/numColors), box.height);
+		}
+		g.setColor(treeDisplay.getBranchColor(node));
+		g.drawRect(box.x, box.y, box.width, box.height);
+	}
+	/*_________________________________________________*/
+	public  boolean isInTerminalBox(Tree tree, int node, int xPos, int yPos){
+		int ew = edgewidth-1;
+		if (isUP()){ 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]-ew-3 && yPos < y[node]-3;
+		}
+		else if (isDOWN())
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node]+1 && yPos < y[node]+ew+1;
+		else  if (isRIGHT()) 
+			return xPos> x[node]+1 && xPos < x[node]+ew +1 && yPos > y[node] && yPos < y[node] + ew;
+		else  if (isLEFT())
+			return xPos> x[node]-ew-3 && xPos < x[node]-3 && yPos > y[node] && yPos < y[node] + ew;
+		else 
+			return xPos> x[node] && xPos < x[node]+ew && yPos > y[node] && yPos < y[node] + ew;
+	}
+	/*_________________________________________________*
+	/*_________________________________________________*/
+	private boolean ancestorIsTriangled(Tree tree, int node) {
+		return tree.ancestorHasNameReference(triangleNameRef, node);
+	}
+	public boolean branchIsVisible(int node){
+		try {
+			if (node >=0 && node <  branchPoly.length)
+				return treeDisplay.getVisRect() == null || branchPoly[node].intersects(treeDisplay.getVisRect());
+		}
+		catch (Throwable t){
+		}
+		return false;
+	}
+	/*_________________________________________________*/
+	public   void fillBranch(Tree tree, int node, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && node<fillBranchPoly.length && branchIsVisible(node)){
+			fillOneBranch(tree, g, fillBranchPoly[node], node, false);  
+		}
+	}
+
+	/** Fill branch N with indicated set of colors as a sequence, e.g. for stochastic character mapping.  This is not abstract because many tree drawers would have difficulty implementing it */
+	public void fillBranchWithColorSequence(Tree tree, int node, ColorEventVector colors, Graphics g){
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			Color c = g.getColor();
+			int numEvents = colors.size();
+			int nShortcut = getShortcutOfDaughters(tree, tree.motherOfNode(node));
+			g.setColor(Color.lightGray);
+			fillBranch(tree, node, g);
+			if (isUP()) {
+				int desc = y[node];
+				int anc = y[tree.motherOfNode(node)];
+				if (cornerMode == 2){
+					anc = (int)(anc -ownerModule.curvature);
+				}
+				else if (cornerMode == 1){
+					anc = anc - nShortcut;
+					nShortcut = 0;
+				}
+				for (int i=numEvents-1; i>=0; i--) {
+					ColorEvent e = (ColorEvent)colors.elementAt(i);
+					double pos;
+					if (i == numEvents-1)
+						pos = 1.0;
+					else {
+						ColorEvent ec = (ColorEvent)colors.elementAt(i+1);
+						pos = ec.getPosition();
+					}
+					UPdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], anc- (int)(pos*(anc-desc)), x[tree.motherOfNode(node)], anc, 0, 1, nShortcut, cornerMode == 0);
+					//	if (cornerMode == 0 || i != 0){
+					g.setColor(e.getColor());
+					g.fillPolygon(utilityPolygon);
+					//	}
+
+				}
+			}
+			else if (isDOWN()) {
+				int desc = y[node];
+				int anc = y[tree.motherOfNode(node)];
+				if (cornerMode == 2){
+					anc = (int)(anc +ownerModule.curvature);
+				}
+				else if (cornerMode == 1){
+					anc = anc + nShortcut;
+					nShortcut = 0;
+				}
+				for (int i=numEvents-1; i>=0; i--) {
+					ColorEvent e = (ColorEvent)colors.elementAt(i);
+					double pos;
+					if (i == numEvents-1)
+						pos = 1.0;
+					else {
+						ColorEvent ec = (ColorEvent)colors.elementAt(i+1);
+						pos = ec.getPosition();
+					}
+					DOWNdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], anc + (int)(pos*(desc-anc)),  x[tree.motherOfNode(node)], anc, 0, 1, nShortcut, cornerMode == 0);
+					g.setColor(e.getColor());
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isRIGHT()) {
+				int desc = x[node];
+				int anc = x[tree.motherOfNode(node)];
+				if (cornerMode == 2){
+					anc = (int)(anc + ownerModule.curvature);
+				}
+				else if (cornerMode == 1){
+					anc = anc + nShortcut;
+					nShortcut = 0;
+				}
+				for (int i=numEvents-1; i>=0; i--) {
+					ColorEvent e = (ColorEvent)colors.elementAt(i);
+					double pos;
+					if (i == numEvents-1)
+						pos = 1.0;
+					else {
+						ColorEvent ec = (ColorEvent)colors.elementAt(i+1);
+						pos = ec.getPosition();
+					}
+					RIGHTdefineFillPoly(utilityPolygon, (node==tree.getRoot()),  anc- (int)(pos*(anc-desc)), y[node], anc, y[tree.motherOfNode(node)], 0, 1, nShortcut, cornerMode == 0);
+					g.setColor(e.getColor());
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isLEFT()){
+				int desc = x[node];
+				int anc = x[tree.motherOfNode(node)];
+				if (cornerMode == 2){
+					anc = (int)(anc - ownerModule.curvature);
+				}
+				else if (cornerMode == 1) {
+					anc = anc - nShortcut;
+					nShortcut = 0;
+				}
+
+				for (int i=numEvents-1; i>=0; i--) {
+					ColorEvent e = (ColorEvent)colors.elementAt(i);
+					double pos;
+					if (i == numEvents-1)
+						pos = 1.0;
+					else {
+						ColorEvent ec = (ColorEvent)colors.elementAt(i+1);
+						pos = ec.getPosition();
+					}
+					LEFTdefineFillPoly(utilityPolygon, (node==tree.getRoot()), anc + (int)(pos*(desc-anc)), y[node], anc, y[tree.motherOfNode(node)], 0, 1, nShortcut, cornerMode == 0);
+					g.setColor(e.getColor());
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*
+	public void fillBranchWithMissingData(Tree tree, int node, Graphics g) {
+
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			Color c = g.getColor();
+			if (g instanceof Graphics2D){
+				Graphics2D g2 = (Graphics2D)g;
+				g2.setPaint(GraphicsUtil.missingDataTexture);
+			}
+			else
+				g.setColor(Color.lightGray);
+			int nShortcut = getShortcutOfDaughters(tree, tree.motherOfNode(node));
+			if (cornerMode == 2){
+				int fillWidth = edgewidth-2*inset;
+				drawOneCurvedBranch(treeDisplay.getTree(), g, node, inset,  fillWidth) ;
+			}
+			else if (isUP())
+				UPdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1, nShortcut, true);
+			else if (isDOWN()) 
+				DOWNdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1, nShortcut, true);
+			else if (isRIGHT()) 
+				RIGHTdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1, nShortcut, true);
+			else if (isLEFT())
+				LEFTdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], 1, 1, nShortcut, true);
+
+			g.fillPolygon(utilityPolygon);
+			if (c!=null) g.setColor(c);
+		}	
+	}
+	/*_________________________________________________*/
+	public void fillBranchWithColors(Tree tree, int node, ColorDistribution colors, Graphics g) {
+		if (node>0 && (tree.getRooted() || tree.getRoot()!=node) && !ancestorIsTriangled(tree, node) && branchIsVisible(node)) {
+			Color c = g.getColor();
+			int numColors = colors.getNumColors();
+			int nShortcut = getShortcutOfDaughters(tree, tree.motherOfNode(node));
+			if (cornerMode == 2){
+				int fillWidth = edgewidth-2*inset;
+				for (int i=0; i<numColors; i++) {
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					drawOneCurvedBranch(treeDisplay.getTree(), g, node, inset + i*fillWidth/numColors,  (i+1)*fillWidth/numColors -i*fillWidth/numColors) ;
+				}
+			}
+			else if (isUP()) {
+				for (int i=0; i<numColors; i++) {
+					UPdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, numColors, nShortcut, true);
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isDOWN()) {
+				for (int i=0; i<numColors; i++) {
+					DOWNdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, numColors, nShortcut, true);
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isRIGHT()) {
+				for (int i=0; i<numColors; i++) {
+					RIGHTdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, numColors, nShortcut, true);
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			else if (isLEFT()){
+				for (int i=0; i<numColors; i++) {
+					LEFTdefineFillPoly(utilityPolygon, (node==tree.getRoot()), x[node], y[node], x[tree.motherOfNode(node)], y[tree.motherOfNode(node)], i+1, numColors, nShortcut, true);
+					Color color;
+					if ((color = colors.getColor(i, !tree.anySelected()|| tree.getSelected(node)))!=null)
+						g.setColor(color);
+					g.fillPolygon(utilityPolygon);
+				}
+			}
+			if (c!=null) g.setColor(c);
+		}
+	}
+	/*_________________________________________________*/
+	public Polygon nodePoly(int node) {
+		int offset = (getNodeWidth()-getEdgeWidth())/2;
+		int doubleOffset = (getNodeWidth()-getEdgeWidth());
+		int startX = x[node] - offset;
+		int startY= y[node] - offset;
+		if (isRIGHT()){
+			startX -= getNodeWidth()-doubleOffset;
+		} else if (isDOWN())
+			startY -= getNodeWidth()-doubleOffset;
+		Polygon poly = new Polygon();
+		poly.npoints=0;
+		poly.addPoint(startX,startY);
+		poly.addPoint(startX+getNodeWidth(),startY);
+		poly.addPoint(startX+getNodeWidth(),startY+getNodeWidth());
+		poly.addPoint(startX,startY+getNodeWidth());
+		poly.addPoint(startX,startY);
+		poly.npoints=5;
+		return poly;
+	}
+	/*_________________________________________________*/
+	public boolean inNode(int node, int x, int y){
+		Polygon nodeP = nodePoly(node);
+		if (nodeP!=null && nodeP.contains(x,y))
+			return true;
+		else
+			return false;
+	}
+	/*_________________________________________________*/
+	private void ScanBranches(Tree tree, Polygon[] polys, int node, int x, int y, MesquiteDouble fraction)
+	{
+		if (foundBranch==0) {
+			if (polys != null && polys[node] != null && polys[node].contains(x, y) || inNode(node,x,y)){
+				foundBranch = node;
+				if (fraction!=null)
+					if (inNode(node,x,y))
+						fraction.setValue(ATNODE);
+					else {
+						int motherNode = tree.motherOfNode(node);
+						fraction.setValue(EDGESTART);  //TODO: this is just temporary: need to calculate value along branch.
+						if (tree.nodeExists(motherNode)) {
+							if (isUP() || isDOWN())  {
+								fraction.setValue( Math.abs(1.0*(y-this.y[motherNode])/(this.y[node]-this.y[motherNode])));
+							}
+							else if (isRIGHT() || isLEFT()) {
+								fraction.setValue( Math.abs(1.0*(x-this.x[motherNode])/(this.x[node]-this.x[motherNode])));
+							}
+						}
+					}
+			}
+			if (!tree.getAssociatedBit(triangleNameRef, node) || !treeDisplay.getSimpleTriangle()) 
+				for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+					ScanBranches(tree, polys, d, x, y, fraction);
+
+		}
+	}
+	/*_________________________________________________*/
+	public   int findBranch(Tree tree, int drawnRoot, int x, int y, MesquiteDouble fraction) { 
+		if (MesquiteTree.OK(tree) && ready) {
+			foundBranch=0;
+			ScanBranches(tree, branchPoly, drawnRoot, x, y, fraction);
+			if (foundBranch==0 && getEdgeWidth()<ACCEPTABLETOUCHWIDTH)
+				ScanBranches(tree, touchPoly, drawnRoot, x, y, fraction);  //then scan through thicker versions
+			if (foundBranch == tree.getRoot() && !tree.getRooted())
+				return 0;
+			else
+				return foundBranch;
+		}
+		return 0;
+	}
+
+	/*_________________________________________________*/
+	public void reorient(int orientation) {
+		if (treeDisplay == null)
+			return;
+		treeDisplay.setOrientation(orientation);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setSimpleTriangle(boolean simpleTriangle) {
+		if (treeDisplay == null)
+			return;
+		treeDisplay.setSimpleTriangle(simpleTriangle);
+		treeDisplay.pleaseUpdate(true);
+	}
+	/*_________________________________________________*/
+	public void setEdgeWidth(int edw) {
+		edgewidth = edw;
+		preferredEdgeWidth = edw;
+	}
+	/*New code Feb.22.07 allows eavesdropping on edgewidth by the TreeDrawing oliver*/ //TODO: delete new code comments
+	/*_________________________________________________*/
+	public int getEdgeWidth() {
+		return edgewidth;
+	}
+	/*End new code Feb.22.07 oliver*/
+	/*_________________________________________________*/
+	public   void dispose() { 
+		for (int i=0; i<numNodes; i++) {
+			branchPoly[i] = null;
+			fillBranchPoly[i] = null;
+			touchPoly[i] = null;
+		}
+		super.dispose();
+	}
+}
+
+
diff --git a/Source/mesquite/trees/StoredTreeBlocks/StoredTreeBlocks.java b/Source/mesquite/trees/StoredTreeBlocks/StoredTreeBlocks.java
new file mode 100644
index 0000000..b7b97e1
--- /dev/null
+++ b/Source/mesquite/trees/StoredTreeBlocks/StoredTreeBlocks.java
@@ -0,0 +1,166 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.StoredTreeBlocks;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies tree blocks stored in the projects.*/
+public class StoredTreeBlocks extends TreeBlockSource implements MesquiteListener {
+	int currentTreeBlockIndex=MesquiteInteger.unassigned;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	TreesManager manager;
+	Taxa preferredTaxa =null;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		if (manager==null)
+			return sorry(getName() + " couldn't start because no tree manager module was found.");
+		if (manager.getNumberTreeBlocks()==0 && !MesquiteThread.isScripting())
+			return sorry("No stored blocks of trees are available.");
+		manager.addBlockListener(this);
+		return true;
+  	 }
+	public void endJob(){
+		if (manager != null)
+			manager.removeBlockListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (!doomed && code != MesquiteListener.SELECTION_CHANGED && code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED)
+			parametersChanged(notification);
+	}
+	
+	/*.................................................................................................................*/
+	/** passes which object disposed*/
+	public void disposing(Object obj){
+		if (obj == preferredTaxa) {
+			setHiringCommand(null); //since there is no rehiring
+			if (!MesquiteThread.isScripting())
+				iQuit();
+		}
+	}
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa) {
+  		if (preferredTaxa != taxa){
+	  		if (preferredTaxa != null)
+	  			preferredTaxa.removeListener(this);
+	  		taxa.addListener(this);
+  		}
+  		preferredTaxa = taxa;
+  	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getFirstBlock(Taxa taxa) {
+   		currentTreeBlockIndex=0;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getBlock(Taxa taxa, int ic) {
+   		currentTreeBlockIndex=ic;
+   		return getCurrentBlock(taxa);
+   	}
+   	private void checkBlock(Taxa taxa){
+   		if (manager == null)
+   			return;
+		int nt = manager.getNumberTreeBlocks(taxa);
+		setPreferredTaxa(taxa);
+		if ((!MesquiteInteger.isCombinable(currentTreeBlockIndex) || currentTreeBlockIndex>=nt || currentTreeBlockIndex<0)) {
+			if (MesquiteThread.isScripting())
+				currentTreeBlockIndex = 0;
+			else if (nt<=1)
+				currentTreeBlockIndex = 0;
+			else {
+				String[] list = new String[nt];
+				for (int i=0; i< nt; i++)
+					list[i]=manager.getTreeBlock(taxa, i).getName();
+				currentTreeBlockIndex = ListDialog.queryList(containerOfModule(), "Use which tree block?", "Use which tree block? \n(for " + employer.getName() + ")", MesquiteString.helpString,list, 0);
+				if (!MesquiteInteger.isCombinable(currentTreeBlockIndex))
+					currentTreeBlockIndex = 0;
+			}
+		}
+ 		currentTreeBlock = manager.getTreeBlock(taxa, currentTreeBlockIndex);
+   		if (currentTreeBlock!=lastUsedTreeBlock) {
+   			if (currentTreeBlock != null)
+   				currentTreeBlock.addListener(this);
+   			if (lastUsedTreeBlock!=null)
+   				lastUsedTreeBlock.removeListener(this);
+   			lastUsedTreeBlock = currentTreeBlock;
+   		}
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getCurrentBlock(Taxa taxa) {
+   		if (currentTreeBlockIndex>getNumberOfTreeBlocks(taxa) || currentTreeBlockIndex<0)
+   			return  null;
+ 		checkBlock(taxa);
+   		return currentTreeBlock;
+   	}
+	/*.................................................................................................................*/
+   	public TreeVector getNextBlock(Taxa taxa) {
+   		currentTreeBlockIndex++;
+   		return getCurrentBlock(taxa);
+   	}
+	/*.................................................................................................................*/
+   	public int getNumberOfTreeBlocks(Taxa taxa) {
+		return manager.getNumberTreeBlocks(taxa);
+   	}
+   
+	/*.................................................................................................................*/
+   	public String getTreeBlockNameString(Taxa taxa, int index) {
+		return manager.getTreeBlock(taxa, index).getName();
+   	}
+	/*.................................................................................................................*/
+   	public String getCurrentTreeBlockNameString(Taxa taxa) {
+ 		checkBlock(taxa);
+ 		return currentTreeBlock.getName();
+  	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Stored Tree Blocks";
+   	 }
+   	 
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies lists of trees stored, for instance in a file.";
+   	 }
+}
+
diff --git a/Source/mesquite/trees/StoredTrees/StoredTrees.java b/Source/mesquite/trees/StoredTrees/StoredTrees.java
new file mode 100644
index 0000000..90512d5
--- /dev/null
+++ b/Source/mesquite/trees/StoredTrees/StoredTrees.java
@@ -0,0 +1,751 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.StoredTrees;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies trees from tree blocks stored in the project.*/
+public class StoredTrees extends TreeSource implements MesquiteListener {
+	int currentTree=0;
+	TreeVector currentTreeBlock = null;
+	TreeVector lastUsedTreeBlock = null;
+	TreesManager manager;
+	Taxa preferredTaxa =null;
+
+	int currentListNumber = MesquiteInteger.unassigned;
+	MesquiteSubmenuSpec listSubmenu;
+	MesquiteBoolean weightsEnabled, useWeights;
+	MesquiteMenuItemSpec weightsItem;
+	MesquiteFile currentSourceFile = null;
+	MesquiteString blockName;
+	ListableVector managerVectorOfTreeBlocks = null;
+	long currentTreeBlockID = MesquiteLong.unassigned;
+	boolean laxMode = false; //mode where default tree given without complaint, empty trees block prepared automatically on store
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (condition !=null && condition instanceof Taxa){
+			preferredTaxa = (Taxa)condition;
+		}
+		weightsEnabled = new MesquiteBoolean(false);
+		useWeights = new MesquiteBoolean(false);
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		if (arguments != null && arguments.equalsIgnoreCase("laxMode"))
+			laxMode = true;
+		if (manager==null)
+			return sorry(getName() + " couldn't start because no tree manager module was found.");
+		if (!laxMode && manager.getNumberTreeBlocks(preferredTaxa)==0 && !MesquiteThread.isScripting()) {
+			return sorry("No stored trees are available.");
+		}
+		managerVectorOfTreeBlocks = manager.getTreeBlockVector();
+		managerVectorOfTreeBlocks.addListener(this);
+
+		//can leave a hint in terms of an id of a treeblock to use
+		String whichBlock = MesquiteThread.retrieveAndDeleteHint(this);
+		long wB = MesquiteLong.fromString(whichBlock);
+		if (MesquiteLong.isCombinable(wB)){
+			currentTreeBlockID = wB;
+		}
+		listSubmenu = addSubmenu(null, "Tree Block (" + whatIsMyPurpose() + ")", makeCommand("setTreeBlockInt",  this), manager.getTreeBlockVector());
+		blockName = new MesquiteString();
+		listSubmenu.setSelected(blockName);
+		return true;
+	}
+	public boolean permitSeparateThreadWhenFilling(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		if (laxMode)
+			temp.addLine("laxMode");
+		if (preferredTaxa!=null && getProject().getNumberTaxas()>1)
+			temp.addLine("setTaxa " + getProject().getTaxaReferenceExternal(preferredTaxa));
+		if (currentSourceFile!=null && currentSourceFile != file)
+			temp.addLine("setTreeBlockInt " + currentListNumber); 
+		else
+			temp.addLine("setTreeBlock " + TreeVector.toExternal(currentListNumber)); 
+		temp.addLine("toggleUseWeights " + useWeights.toOffOnString());
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets which block of trees to use (for internal use; 0 based)", "[block number]", commandName, "setTreeBlockInt")) { //need separate from setTreeBlock since this is used internally with 0-based menu response
+			int whichList = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				currentTreeBlock = manager.getTreeBlock(preferredTaxa, whichList); //checker.getFile(), 
+				if (currentTreeBlock ==null)
+					return null;
+				if (lastUsedTreeBlock !=null) 
+					lastUsedTreeBlock.removeListener(this);
+				blockName.setReferentID(Long.toString(currentTreeBlock.getID()));
+				blockName.setValue(currentTreeBlock.getName());
+				currentTreeBlock.addListener(this);
+				lastUsedTreeBlock = currentTreeBlock;
+				currentListNumber = whichList;
+				currentTreeBlockID = currentTreeBlock.getID();
+				currentSourceFile = currentTreeBlock.getFile();
+				MesquiteTrunk.resetChecks(listSubmenu);
+				parametersChanged();
+				MesquiteTrunk.checkForResetCheckMenuItems();
+				return currentTreeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Sets which block of trees to use", "[block number]", commandName, "setTreeBlock")) {
+			int whichList = TreeVector.toInternal(MesquiteInteger.fromString(arguments, new MesquiteInteger(0)));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				currentTreeBlock = manager.getTreeBlock(preferredTaxa, checker.getFile(), whichList);
+				if (currentTreeBlock ==null)
+					return null;
+				if (lastUsedTreeBlock !=null) 
+					lastUsedTreeBlock.removeListener(this);
+				blockName.setReferentID(Long.toString(currentTreeBlock.getID()));
+				blockName.setValue(currentTreeBlock.getName());
+				currentTreeBlock.addListener(this);
+				currentTreeBlockID = currentTreeBlock.getID();
+				currentSourceFile = currentTreeBlock.getFile();
+				lastUsedTreeBlock = currentTreeBlock;
+				currentListNumber = whichList;
+				MesquiteTrunk.resetChecks(listSubmenu);
+				parametersChanged();
+				return currentTreeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Sets which block of trees to use", "[runtime ID]", commandName, "setTreeBlockByID")) {
+			int whichList = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			if (MesquiteInteger.isCombinable(whichList)) {
+				TreeVector tr = manager.getTreeBlockByID(whichList);
+				if (tr == null || (preferredTaxa != null && tr.getTaxa() != preferredTaxa))
+					return null;
+				currentTreeBlock = tr;
+				if (lastUsedTreeBlock !=null) 
+					lastUsedTreeBlock.removeListener(this);
+				blockName.setReferentID(Long.toString(currentTreeBlock.getID()));
+				blockName.setValue(currentTreeBlock.getName());
+				currentTreeBlock.addListener(this);
+				currentTreeBlockID = currentTreeBlock.getID();
+				currentSourceFile = currentTreeBlock.getFile();
+				lastUsedTreeBlock = currentTreeBlock;
+				currentListNumber = whichList;
+				MesquiteTrunk.resetChecks(listSubmenu);
+				parametersChanged();
+				return currentTreeBlock;
+			}
+		}
+		else if (checker.compare(this.getClass(),  "Returns current tree block", null, commandName, "getTreeBlock")) {
+			if (currentTreeBlock == null)
+				checkTreeBlock(preferredTaxa, false);
+			return currentTreeBlock;
+		}
+		else if (checker.compare(this.getClass(),  "Sets to lax mode", null, commandName, "laxMode")) {
+			laxMode = true;
+		}
+		else if (checker.compare(this.getClass(),  "Turns off lax mode", null, commandName, "laxOff")) {
+			laxMode = false;
+		}
+		else if (checker.compare(this.getClass(), "Sets which block of taxa to use", "[block reference, number, or name]", commandName, "setTaxa")) { 
+			Taxa t = getProject().getTaxa(checker.getFile(), parser.getFirstToken(arguments));
+			if (t!=null){
+				setPreferredTaxa(t);
+				parametersChanged();
+				return t;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets whether to use any available weights for the trees", "[on or off]", commandName, "toggleUseWeights")) {
+			boolean current = useWeights.getValue();
+			useWeights.toggleValue(parser.getFirstToken(arguments));
+			if (current!=useWeights.getValue() && !MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void classFieldChanged (Class c, String fieldName) {
+		super.classFieldChanged(c, fieldName);
+		if (c== Tree.class)
+			parametersChanged();
+	}
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (currentTreeBlock !=null) {
+			currentTreeBlock.removeListener(this);
+		}
+		if (preferredTaxa != null){
+			preferredTaxa.removeListener(this);
+		}
+		if (managerVectorOfTreeBlocks!= null)
+			managerVectorOfTreeBlocks.removeListener(this);
+
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	long previous = -1;
+	/** passes which object changed*/
+	public void changed(Object caller, Object obj, Notification notification){
+		int code = Notification.getCode(notification);
+		if (notification != null && notification.getNotificationNumber() == previous)
+			return;
+		if (notification != null)
+			previous = notification.getNotificationNumber();
+		if (doomed)
+			return;
+
+		if (code != MesquiteListener.ANNOTATION_CHANGED && code != MesquiteListener.ANNOTATION_DELETED && code != MesquiteListener.ANNOTATION_ADDED && !(obj instanceof TreeVector && code == MesquiteListener.SELECTION_CHANGED)) {
+			if (obj == managerVectorOfTreeBlocks){
+				if (code == MesquiteListener.PARTS_MOVED){
+					if (MesquiteLong.isCombinable(currentTreeBlockID))
+						currentListNumber = indexOfTreeBlockWithID(preferredTaxa, currentTreeBlockID);
+				}
+				else if (code == MesquiteListener.PARTS_DELETED){
+					if (currentTreeBlock != null && managerVectorOfTreeBlocks.indexOf(currentTreeBlock)<0){
+						int index = indexOfTreeBlockWithID(preferredTaxa, currentTreeBlockID);
+						if (index>0)
+							currentListNumber = index;
+						else if (MesquiteLong.isCombinable(currentTreeBlockID)){
+							
+						//	discreetAlert( "The current tree block used by Stored Trees (for " + getEmployer().getName() + ") has apparently been deleted.  You might be asked to select another tree block, or this might force use of default trees, and also may yield error messages when rereading the file.");
+							if (currentTreeBlock != null)
+								currentTreeBlock.removeListener(this);
+							currentTreeBlock = null;
+							lastUsedTreeBlock = null;
+							currentListNumber = MesquiteInteger.unassigned;
+							currentTreeBlockID = MesquiteLong.unassigned;
+							MesquiteTrunk.resetChecks(listSubmenu);
+							checkTreeBlock(preferredTaxa, true);
+							parametersChanged(new Notification(MesquiteListener.BLOCK_DELETED));
+						}
+					}
+				}
+
+
+			}
+			else if (obj instanceof Taxa){
+				boolean respond = (code==MesquiteListener.ITEMS_ADDED || code==MesquiteListener.PARTS_CHANGED || code==MesquiteListener.PARTS_ADDED || code==MesquiteListener.PARTS_DELETED || code==MesquiteListener.PARTS_MOVED);
+				if (respond){
+					if (notification != null)
+						notification.setObjectClass(Taxa.class);
+					parametersChanged(notification);
+				}
+			}
+			else {
+				if (obj instanceof TreeVector && ((TreeVector)obj).size()==0 && obj == currentTreeBlock) {
+					discreetAlert( "The current tree block used by Stored Trees (for " + getEmployer().getName() + ") has no trees in it.  This might force use of default trees, and also may yield error messages when rereading the file.");
+					currentTreeBlock.removeListener(this);
+					currentTreeBlock = null;
+					lastUsedTreeBlock = null;
+					currentListNumber = MesquiteInteger.unassigned;
+					currentTreeBlockID = MesquiteLong.unassigned;
+					MesquiteTrunk.resetChecks(listSubmenu);
+				}
+				parametersChanged(notification);
+			}
+		}
+		else if ((obj instanceof TreeVector && code == MesquiteListener.SELECTION_CHANGED)) {
+			parametersChanged(notification);
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** passes which object was disposed*/
+	public void disposing(Object obj){
+		if (preferredTaxa == obj) {
+			preferredTaxa = null;
+			if (currentTreeBlock!= null)
+				currentTreeBlock.removeListener(this);
+			currentTreeBlock = null;
+			lastUsedTreeBlock = null;
+			currentListNumber = MesquiteInteger.unassigned;
+			setHiringCommand(null); //since there is no rehiring
+			iQuit();
+			//don't say parameters changed since employer asked for those taxa
+		}
+		else if (currentTreeBlock == obj) {
+			currentTreeBlock.removeListener(this);
+			currentTreeBlock = null;
+			lastUsedTreeBlock = null;
+			currentListNumber = MesquiteInteger.unassigned;
+			MesquiteTrunk.resetChecks(listSubmenu);
+			if (preferredTaxa != null && preferredTaxa.isDoomed()){
+				preferredTaxa = null; //don't say parameters changed since employer asked for those taxa
+			}
+			else{
+				checkTreeBlock(preferredTaxa, true);
+				parametersChanged(); 
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Asks whether it's ok to delete the object as far as the listener is concerned (e.g., is it in use?)*/
+	public boolean okToDispose(Object obj, int queryUser){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** queryies the user to choose a tree and returns an integer of the tree chosen*/
+	public int queryUserChoose(Taxa taxa, String forMessage){
+		int ic=MesquiteInteger.unassigned;
+		int numTrees = getNumberOfTrees(taxa);
+		if (currentTreeBlock == null)
+			return ic;
+		if (MesquiteInteger.isCombinable(numTrees)){
+			String[] s = new String[numTrees];
+			for (int i=0; i<numTrees; i++){
+				Tree tree= (Tree)currentTreeBlock.elementAt(i);
+				if (tree.getName()!=null && !tree.getName().equals(""))
+					s[i] = tree.getName();
+				else
+					s[i]= "Tree # " + Integer.toString(MesquiteTree.toExternal(i));
+			}
+			return ListDialog.queryList(containerOfModule(), "Choose tree", "Choose tree " + forMessage, MesquiteString.helpString,s, 0);
+		}
+		else 
+			return  MesquiteInteger.queryInteger(containerOfModule(), "Choose tree", "Number of tree " + forMessage, 1);
+
+	}
+
+	boolean firstInit = true;
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		checkTreeBlock(taxa, false);
+	}
+	/*.................................................................................................................*/
+	public void resetMenu(Taxa taxa){
+		boolean reset = false;
+		if (listSubmenu!=null){
+			if (!isInStartup()){
+				if (firstInit){
+					listSubmenu.setName("Tree Block (" + whatIsMyPurpose() + ")");
+					reset = true;
+				}
+				firstInit = false;
+			}
+			Object obj = listSubmenu.getCompatibilityCheck();
+			if (obj == null || obj!=taxa) {
+				listSubmenu.setCompatibilityCheck(taxa);
+				reset = true;
+			}
+		}
+		if (reset)
+			resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		if (taxa !=null && taxa.isDoomed())
+			return;
+		if (preferredTaxa!=taxa) {
+			if (preferredTaxa !=null)
+				preferredTaxa.removeListener(this);
+			preferredTaxa = taxa;
+			if (taxa == null)
+				return;
+			preferredTaxa.addListener(this);
+			resetMenu(taxa);
+		}
+	}
+	boolean first = true;
+
+	int indexOfTreeBlockWithID(Taxa taxa, long treeBlockID){
+		int nt = manager.getNumberTreeBlocks(taxa);
+		for (int i=0; i< nt; i++){
+			TreeVector tv =manager.getTreeBlock(taxa, i);
+			if (tv.getID() == treeBlockID)
+				return i;
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	private int checkTreeBlock(Taxa taxa, boolean becauseOfDeletion){
+		if (taxa == null) {
+			if (!MesquiteThread.isScripting())
+				logln("Taxa null in checkTreeBlock in Stored Trees");
+			return -1;
+		}
+		if (manager == null)
+			return -1;
+		resetMenu(taxa);
+		int nt = manager.getNumberTreeBlocks(taxa);
+		if (MesquiteLong.isCombinable(currentTreeBlockID))
+			currentListNumber = indexOfTreeBlockWithID(taxa, currentTreeBlockID);
+		if ((!MesquiteInteger.isCombinable(currentListNumber) || currentListNumber>=nt || currentListNumber<0)) {
+			if (MesquiteThread.isScripting())
+				currentListNumber = 0;
+			else if (nt<=1)
+				currentListNumber = 0;
+			else if (MesquiteLong.isCombinable(currentTreeBlockID)){
+				for (int i=0; i< nt; i++){
+					TreeVector tv =manager.getTreeBlock(taxa, i);
+					if (tv.getID() == currentTreeBlockID)
+						currentListNumber = i;
+				}
+			}
+			else {
+				if (becauseOfDeletion){
+					if (!dearEmployerShouldIHandleThis(new Notification(MesquiteListener.BLOCK_DELETED))){
+						currentListNumber = 0;
+						MesquiteTrunk.resetChecks(listSubmenu);
+						return -1;
+				}
+							
+				}
+				String[] list = new String[nt];
+				for (int i=0; i< nt; i++){
+					TreeVector tv =manager.getTreeBlock(taxa, i);
+					list[i]=tv.getName();
+				}
+				currentListNumber = ListDialog.queryList(containerOfModule(), "Use which tree block?", "Use which tree block? \n(" + whatIsMyPurpose() + ")",MesquiteString.helpString, list, 0);
+				if (!MesquiteInteger.isCombinable(currentListNumber))
+					currentListNumber = 0;
+			}
+			MesquiteTrunk.resetChecks(listSubmenu);
+		}
+		int code = 0;
+		if (lastUsedTreeBlock == null || lastUsedTreeBlock.getTaxa() == null || !lastUsedTreeBlock.getTaxa().equals(taxa)) {
+			currentTreeBlock =  manager.getTreeBlock(taxa, currentListNumber);
+			code = 1;
+		}
+		else
+			currentTreeBlock = lastUsedTreeBlock;
+
+		if (currentTreeBlock != null)
+			currentTreeBlockID = currentTreeBlock.getID();
+
+		if (blockName != null && currentTreeBlock != null){
+		blockName.setReferentID(Long.toString(currentTreeBlock.getID()));
+			blockName.setValue(currentTreeBlock.getName());
+		}
+		
+		if (lastUsedTreeBlock!=currentTreeBlock) {
+			if (lastUsedTreeBlock !=null) 
+				lastUsedTreeBlock.removeListener(this);
+			if (currentTreeBlock!=null)
+				currentTreeBlock.addListener(this);
+		}
+		lastUsedTreeBlock = currentTreeBlock;
+		if (currentTreeBlock == null) {
+			currentTreeBlock = manager.getTreeBlock(taxa, 0);
+			if (currentTreeBlock!=null)
+				currentTreeBlock.addListener(this);
+			lastUsedTreeBlock = currentTreeBlock;
+		}
+		if (currentTreeBlock == null) {
+			
+			
+			if (getProject() != null && getProject().getNumberTaxas()==1 && !MesquiteThread.isScripting() && !laxMode)
+				logln("No current tree block for taxa " + taxa.getName() + "(Module: Stored Trees)");
+			if (!MesquiteThread.isScripting())
+				iQuit();
+			return -1;
+		}
+		currentSourceFile = currentTreeBlock.getFile();
+		laxMode = false;
+		return code;
+	}
+	public boolean showing(TreeVector v){
+		return v == currentTreeBlock;
+	}
+	boolean warned = false;
+ 	public String getNotesAboutTrees(Taxa taxa){
+		int code = checkTreeBlock(taxa, false);
+		if (code <0 || currentTreeBlock == null) {
+			if (laxMode)
+				return "Tree being edited by hand.";
+			else
+				return null;
+		}
+		String s = "Tree block: " + currentTreeBlock.getName();
+		String an = currentTreeBlock.getAnnotation();
+		if (!StringUtil.blank(an))
+			s += "\n\nNotes:\n" + an;
+		return s;
+	}
+	/*.................................................................................................................*/
+	public Tree getCurrentTree(Taxa taxa) {
+		try {
+			int code = checkTreeBlock(taxa, false);
+			if (code <0) {
+				if (laxMode)
+					return getDefaultTree(taxa);
+				else
+					return null;
+			}
+			if (currentTreeBlock != null && currentTreeBlock.size()>0) {
+				if (currentTree<currentTreeBlock.size()) {
+					Tree t = (Tree)currentTreeBlock.elementAt(currentTree);
+					if (t == null)
+						return null;
+					t.setFileIndex(currentTree);
+
+					if (t instanceof MesquiteTree)
+						((MesquiteTree)t).setAssignedNumber(currentTree);
+					return t;
+				}
+				else {
+					MesquiteMessage.warnUser("Tree #" + (currentTree+1) + " requested beyond number available (" + currentTreeBlock.size() + ") in tree block \"" + currentTreeBlock.getName() + "\"."); //in 1.0 returned first tree in block
+					/*
+					currentTree = 0;
+	   				Tree t = (Tree)currentTreeBlock.elementAt(currentTree);
+	   				if (t instanceof MesquiteTree)
+	   					((MesquiteTree)t).setAssignedNumber(currentTree);
+					 */
+					return null;
+				}
+			}
+			else {
+				if (first) {
+					if (taxa != null) {
+						if (currentTreeBlock==null) {
+							if (!MesquiteThread.isScripting()) {
+								discreetAlert(warned, "No tree block available for taxa \"" + taxa.getName() + "\"; will use default tree");
+								warned = true;
+							}
+						}
+						else {
+							MesquiteMessage.warnUser("Tree #" + (currentTree+1) + " requested beyond number (" + currentTreeBlock.size() + ") in tree block \"" + currentTreeBlock.getName() + "\"."); //in 1.0 returned default tree
+						}
+					}
+					else
+						MesquiteMessage.warnUser("No tree block available! [code " + code + "]");
+					first = false;
+				}
+				//return taxa.getDefaultTree();
+				return null;
+			}
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	public Tree getDefaultTree(Taxa taxa) {
+		int numTaxa = taxa.getNumTaxa();
+		MesquiteTree tree = new MesquiteTree(taxa);
+		tree.setToDefaultSymmetricalTree(numTaxa, false);
+		tree.setName("DEFAULT ARBITRARY TREE");
+		return tree;
+	}
+	/*.................................................................................................................*/
+	public Selectionable getSelectionable(){
+		return currentTreeBlock;
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		currentTree=itree;
+		return getCurrentTree(taxa);
+	}
+	/*.................................................................................................................*/
+	public void setEnableWeights(boolean enable){
+		if (enable == weightsEnabled.getValue())
+			return;
+		weightsEnabled.setValue(enable);
+		if (enable && weightsItem == null) {
+			weightsItem = addCheckMenuItem(null, "Use Tree Weights", makeCommand("toggleUseWeights", this), useWeights);
+			resetContainingMenuBar();
+		}
+		else {
+			weightsItem.setEnabled(enable);
+			MesquiteTrunk.resetMenuItemEnabling();
+		}
+	}
+	/*.................................................................................................................*/
+	public boolean itemsHaveWeights(Taxa taxa){
+		if (!useWeights.getValue())
+			return false;
+		int code = checkTreeBlock(taxa, false);
+		if (currentTreeBlock != null) {
+			for (int itree =0; itree < currentTreeBlock.size(); itree++){
+				Tree tree = currentTreeBlock.getTree(itree);
+				if (tree !=null && tree instanceof Attachable){
+					Vector at = ((Attachable)tree).getAttachments();
+					if (at !=null) {
+						for (int i =0; i < at.size(); i++){
+							Object obj = at.elementAt(i);
+							if (obj instanceof MesquiteDouble) {
+								String name = ((Listable)obj).getName();
+								if ("weight".equalsIgnoreCase(name)) 
+									return true;
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+	/*.................................................................................................................*/
+	public double getItemWeight(Taxa taxa, int ic){
+		Tree tree = getTree(taxa, ic);
+		if (tree != null) {
+			if (tree instanceof Attachable){
+				Vector at = ((Attachable)tree).getAttachments();
+				if (at !=null) {
+					for (int i =0; i < at.size(); i++){
+						Object obj = at.elementAt(i);
+						if (obj instanceof MesquiteDouble) {
+							String name = ((Listable)obj).getName();
+							if ("weight".equalsIgnoreCase(name)) 
+								return ((MesquiteDouble)obj).getValue();
+						}
+					}
+				}
+			}
+		}
+		return MesquiteDouble.unassigned;
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		if (currentTreeBlock == null && laxMode)
+			return 0;
+		int code = checkTreeBlock(taxa, false);
+		if (currentTreeBlock != null)
+			return currentTreeBlock.size();
+		else
+			return 0; //just default tree
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		try {
+			Tree tree;
+			int code = checkTreeBlock(taxa, false);
+			if (currentTreeBlock == null || itree>=currentTreeBlock.size())
+				return "";
+			if (currentTree<currentTreeBlock.size())
+				tree= (Tree)currentTreeBlock.elementAt(itree);
+			else
+				tree = taxa.getDefaultTree();
+			if (tree.getName()!=null && !tree.getName().equals(""))
+				return "Tree \"" + tree.getName() + "\" from trees \"" + currentTreeBlock.getName() + "\" of file " + currentTreeBlock.getFileName() + "  [tree: " + tree + "]";
+			else
+				return "Tree # " + Integer.toString(MesquiteTree.toExternal(itree))  + " from trees \"" + currentTreeBlock.getName() + "\" of file " + currentTreeBlock.getFileName() + "  [tree: " + tree + "]";
+		}
+		catch (NullPointerException e) {
+			return null;
+		}
+	}
+	/*.................................................................................................................*/
+	public String getCurrentTreeNameString(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		Tree tree = getCurrentTree(taxa);
+		if (tree.getName()!=null && !tree.getName().equals(""))
+			return "Tree \"" + tree.getName() + "\" from file " + currentTreeBlock.getFileName();
+		else
+			return "Tree # " + Integer.toString(MesquiteTree.toExternal(currentTree))  + " from file " + currentTreeBlock.getFileName();
+	}
+ 	 /**Returns name to show in windows etc. for tree block or source of trees.*/
+ 	public String getTreesDescriptiveString(Taxa taxa){
+		setPreferredTaxa(taxa);
+		if (getNumberOfTrees(taxa)==0)
+			return "";
+		String description = "";
+		try {
+			Tree tree;
+			int code = checkTreeBlock(taxa, false);
+			if (currentTreeBlock != null)
+				return currentTreeBlock.getName();
+		}
+		catch (NullPointerException e) {
+		}
+		if (laxMode && currentTreeBlock == null)
+			return "";
+		return getNameForMenuItem();
+ 	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Stored Trees";
+	}
+	/*.................................................................................................................*/
+	public String getNameAndParameters() {
+		if (currentTreeBlock ==null)
+			return "Stored Trees";
+
+					
+		return "Trees stored in block \"" + currentTreeBlock.getName() + "\"";
+	}
+
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies trees stored, for instance in a file.";
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (currentTreeBlock==null) {
+			if (getProject()== null)
+				return "";
+			else
+				return "Trees stored in " + getProject().getName();
+		}
+		return "Trees \"" + currentTreeBlock.getName() + "\" from file " + currentTreeBlock.getFileName();
+	}
+	/*.................................................................................................................*/
+	public CompatibilityTest getCompatibilityTest() {
+		return new STCompatibilityTest();
+	}
+}
+
+class STCompatibilityTest extends CompatibilityTest{
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer){
+		return isCompatible(obj, project, prospectiveEmployer, null);
+	}
+	public  boolean isCompatible(Object obj, MesquiteProject project, EmployerEmployee prospectiveEmployer, MesquiteString report){
+		if (obj != null && !(obj instanceof Taxa))
+			return true;
+		else if (obj instanceof Taxa || obj == null) {
+			TreesManager manager = null;
+			if (prospectiveEmployer == null) {
+				if (project!=null){
+					MesquiteModule coord = project.getCoordinatorModule();
+					if (coord!=null){
+						manager = (TreesManager)coord.findElementManager(TreeVector.class);
+					}
+				}
+			}	
+			else
+				manager = (TreesManager)prospectiveEmployer.findElementManager(TreeVector.class);
+			if (manager==null) {
+				return true;
+			}
+			boolean treesExist =  (manager.getNumberTreeBlocks((Taxa)obj)>0);
+			if (!treesExist && report != null) {
+				report.setValue("there are no stored trees in the data file or project for the requested taxa block");
+			}
+			return treesExist;
+		}
+		return true;
+	}
+}
+
+
diff --git a/Source/mesquite/trees/TreeInfoValues/TreeInfoValues.java b/Source/mesquite/trees/TreeInfoValues/TreeInfoValues.java
new file mode 100644
index 0000000..89123fc
--- /dev/null
+++ b/Source/mesquite/trees/TreeInfoValues/TreeInfoValues.java
@@ -0,0 +1,388 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.trees.TreeInfoValues;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.trees.lib.TreeInfoExtraPanel;
+
+
+public class TreeInfoValues extends TreeInfoPanelAssistant  {
+	ValuesPanel panel;
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " needs methods to calculate values that pertain to the tree in the tree window, such as a parsimony score, an imbalance statistic, and so on.", 
+		"Values for the tree can be requested by touching the + button in the Tree Information Panel which is available by touching the blue i button in the Tree Window");
+		e.setPriority(3);
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public int getVersionOfFirstRelease(){
+		return 250;  
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*
+	public  Class getHireSubchoice(){
+		return NumberForTree.class;
+	}
+	*/
+
+	/*.................................................................................................................*/
+	public TreeInfoExtraPanel getPanel(ClosablePanelContainer container){
+		panel =  new ValuesPanel(container, this);
+		return panel;
+	}
+
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof NumberForTree) {
+				temp.addLine("newValue ", ((MesquiteModule)e));
+			}
+		}
+		temp.addLine("panelOpen " + panel.isOpen());
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+		//zap values panel line
+
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Turns off one of the modules employed to display a line in the tree legend", "[employee number]", commandName, "closeEmployee")) {
+			// argument is ID; fire it and zap values panel line
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to display a new line in the tree legend", "[name of module]", commandName, "newValue")) {
+			incrementMenuResetSuppression();
+			NumberForTree ntt= (NumberForTree)hireNamedEmployee(NumberForTree.class, arguments);
+			decrementMenuResetSuppression();
+			if (ntt!=null) {
+				ntt.setUseMenubar(false);  
+				panel.addEmployee(ntt);
+				resetContainingMenuBar();
+			}
+			return ntt;
+		}
+		else if (checker.compare(this.getClass(), "Sets the panel open", null, commandName, "panelOpen")) {
+			if (panel != null)
+				panel.setOpen(arguments == null || arguments.equalsIgnoreCase("true"));
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	public void hireNew(){
+		NumberForTree ntt= (NumberForTree)hireEmployee(NumberForTree.class, "Value to show for tree");
+		if (ntt!=null) {
+			ntt.setUseMenubar(false);  
+			panel.addEmployee(ntt);
+			resetContainingMenuBar();
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+		if (employee !=null) {
+			// make values panel line blank
+		}
+	}
+	/*.................................................................................................................*/
+	public int whichString(MesquiteModule employee) {
+		if (employee !=null) {
+			return getEmployeeVector().indexOf(employee) +1;
+		}
+		return -1;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee !=null) {
+			panel.recalculate(employee);
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Values (Tree information panel)...";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Makes the Values section of the Tree Information Panel to display values pertaining to the tree.";
+	}
+	
+	public String nameForWritableResults(){
+		if (panel == null)
+			return null;
+		String results = "(Values: ";
+		for (int i = 0; i<panel.employees.length; i++){
+			if (panel.employees[i] == null)
+				return results;
+			if (i != 0)
+				results += "; ";
+			results += panel.employees[i].getNameAndParameters();
+		}
+		return results + ")";
+	}
+	public boolean suppliesWritableResults(){
+		if (panel == null || panel.employees == null || panel.employees.length == 0)
+			return false;
+		for (int i = 0; i<panel.employees.length; i++){
+			if (panel.employees[i] != null)
+				return true;
+		}
+		return false;
+	}
+	public Object getWritableResults(){
+		if (panel == null)
+			return null;
+		String results = "";
+		for (int i = 0; i<panel.employees.length; i++){
+			if (panel.employees[i] == null)
+				return results;
+			if (i != 0)
+				results += "\t";
+			results += panel.employees[i].getNameAndParameters() + "\t" + panel.resultsNumbers[i];
+		}
+		return results;
+	}
+	public Object getResultsHeading(){
+		if (panel == null)
+			return null;
+		String results = "";
+		for (int i = 0; i<panel.employees.length; i++){
+			if (panel.employees[i] == null)
+				return results;
+			if (i != 0)
+				results += "\t";
+			results += panel.employees[i].getName();
+		}
+		return results;
+	}
+
+}
+/*===========================================*/
+class ValuesPanel extends TreeInfoExtraPanel {
+	StringInABox[] boxes;
+	String message = null;
+	int neededHeight = 20;
+	TreeInfoValues ownerModule;
+	int maxNumLines = 100;
+	int numLines = 0;
+	NumberForTree[] employees;
+	String[] results;
+	MesquiteNumber[] resultsNumbers;
+	int[] verts;
+	Image add, query, goaway;
+	public ValuesPanel(ClosablePanelContainer container, TreeInfoValues ownerModule){
+		super(container, "Values");
+		add = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "addGray.gif");
+		query = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "queryGray.gif");
+		goaway = MesquiteImage.getImage(MesquiteModule.getRootImageDirectoryPath() + "minimizeTransparent.gif");
+		boxes =  new StringInABox[maxNumLines];
+		for (int i= 0; i<maxNumLines; i++)
+			boxes[i] = new StringInABox("", null, 50);
+		verts = new int[maxNumLines];
+		employees = new NumberForTree[maxNumLines];
+		results = new String[maxNumLines];
+		resultsNumbers = new MesquiteNumber[maxNumLines];
+		for (int i=0; i<maxNumLines; i++)
+			resultsNumbers[i] = new MesquiteNumber();
+		this.ownerModule = ownerModule;
+	}
+	public void setTree(Tree tree){
+		super.setTree(tree);
+		recalculateAll();
+		container.requestHeightChange(this);
+		repaint();
+	}
+	public void recalculateAll(){
+		MesquiteString resultString = new MesquiteString();
+		MesquiteNumber result = new MesquiteNumber();
+		for (int i=0; i<numLines; i++){
+			employees[i].calculateNumber(tree, result, resultString);
+			resultsNumbers[i].setValue(result);
+			results[i] = resultString.getValue();
+		}
+	}
+	public void recalculate(MesquiteModule mb){
+		MesquiteString resultString = new MesquiteString();
+		MesquiteNumber result = new MesquiteNumber();
+		int i = findLine(mb);
+		if (i>=0){
+			employees[i].calculateNumber(tree, result, resultString);
+			resultsNumbers[i].setValue(result);
+			results[i] = resultString.getValue();
+			container.requestHeightChange(this);
+			repaint();
+		}
+	}
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseUp(int modifiers, int x, int y, MesquiteTool tool) {
+		if (y<MINHEIGHT){
+			if (x> getWidth()- 20)
+				ownerModule.alert("Values:  To change settings of one of the calculations, click on its text below until the popup menu appears.  To add a new calculations, click the + button beside Values");  //query button hit
+			else if (x> getWidth()- 40)
+				ownerModule.hireNew();  //add button hit
+			else
+				super.mouseUp(modifiers,  x,  y,  tool);
+		}
+		else {
+			int i = findGoAway(x, y);
+			if (i>=0 && prevGoAway == i){
+				ownerModule.fireEmployee(employees[i]);
+				for (int k = i+1; k<employees.length; k++){
+					employees[k-1] = employees[k];
+					resultsNumbers[k-1] = resultsNumbers[k];
+					results[k-1] = results[k];
+				}
+				numLines--;
+				container.requestHeightChange(this);
+				repaint();
+			}
+			else
+			super.mouseUp(modifiers,  x,  y,  tool);
+		}
+	}
+	int prevGoAway = -1;
+	/* to be used by subclasses to tell that panel touched */
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+
+		int i = findLine(x, y);
+		if (i>=0 && i<numLines)
+			employees[i].showPopUp(this, 0, verts[i]);
+		else {
+			prevGoAway= findGoAway(x, y);
+		}
+	}
+
+	public void addEmployee(NumberForTree mb){
+		employees[numLines] = mb;
+		if (tree != null){
+			MesquiteString resultString = new MesquiteString();
+			if (numLines == 0 && !isOpen())
+				setOpen(true);
+			MesquiteNumber result = new MesquiteNumber();
+			mb.calculateNumber(tree, result, resultString);
+			results[numLines] = resultString.getValue();
+			resultsNumbers[numLines].setValue(result);
+		}
+		else 
+			results[numLines] = "";
+		numLines++;
+		container.requestHeightChange(this);
+	}
+	public void removeEmployee(NumberForTree mb){
+		int which = findLine(mb);
+		if (which>=0){
+			for (int i=which; i<numLines; i++)
+				employees[i] = employees[i+1];
+			numLines--;
+		}
+	}
+	public int findLine(MesquiteModule id) {
+		for (int i=0; i<employees.length; i++){
+			if (id == employees[i])
+				return i;
+		}
+		return -1;
+	}
+	public int findLine(int x, int y) {
+		if (y < MINHEIGHT)
+			return -1;
+		int last = MINHEIGHT;
+		for (int i=0; i<numLines; i++){
+			if (y< verts[i] && (x>16 || y> last + 16))
+				return i;
+			last = verts[i];			
+		}
+		return -1;
+	}
+	public int findGoAway(int x, int y) {
+		if (y < MINHEIGHT)
+			return -1;
+		int last = MINHEIGHT;
+		for (int i=0; i<numLines; i++){
+			if (y< last + 16 && x< 16)
+				return i;
+			last = verts[i];
+		}
+		return -1;
+	}
+	public int getRequestedHeight(int width){
+		if (!isOpen())
+			return MINHEIGHT;
+		neededHeight= 0;
+		for (int i= 0; i<numLines; i++){
+			boxes[i].setFont(getFont());
+			boxes[i].setString(results[i]);
+			boxes[i].setWidth(width-21);
+			neededHeight += 4 + boxes[i].getHeight();
+			verts[i] = neededHeight + MINHEIGHT;
+		}
+		return neededHeight + MINHEIGHT;
+	}
+	
+	public void paint(Graphics g){
+		super.paint(g);
+		g.drawImage(query, getWidth()-20, 4, this);
+		g.drawImage(add, getWidth()-40, 4, this);
+		int vertical = MINHEIGHT;
+		int width = getWidth();
+		for (int i= 0; i<numLines; i++){
+			g.setColor(Color.black);
+			boxes[i].setFont(getFont());
+			boxes[i].setString(results[i]);
+			boxes[i].setWidth(width-21);
+			boxes[i].draw(g,21, vertical);
+			g.drawImage(goaway, 2, vertical+2, this);
+			vertical += 4 + boxes[i].getHeight();
+			
+			g.setColor(Color.gray);
+			g.drawLine(0,vertical, width, vertical);
+
+		}
+	}
+}
+
diff --git a/Source/mesquite/trees/TreeLegendMaker/TreeLegendMaker.java b/Source/mesquite/trees/TreeLegendMaker/TreeLegendMaker.java
new file mode 100644
index 0000000..33b3c46
--- /dev/null
+++ b/Source/mesquite/trees/TreeLegendMaker/TreeLegendMaker.java
@@ -0,0 +1,737 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+
+Modified 27 July 01: name reverted to "Tree Legend"; added getNameForMenuItem "Tree Legend..."
+ */
+package mesquite.trees.TreeLegendMaker;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+
+public class TreeLegendMaker extends TreeDisplayAssistantMA  {
+	private Vector legendOperators;
+	private ListableVector legends;
+
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumberForTree.class, getName() + " needs methods to calculate values that pertain to the tree in the tree window, such as a parsimony score, an imbalance statistic, and so on.", 
+		"The Values For Current Tree legend showing values for current tree can be started under the Analysis menu of the Tree Window.  You may add new values to display either when the legend starts, or later using the Legend menu");
+		e.setPriority(1);
+	}
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		makeMenu("Legend");
+		resetContainingMenuBar();
+		addSubmenu(null, "Show", makeCommand("newLegendItem",  this), NumberForTree.class);
+		addMenuItem( "-", null);
+		MesquiteSubmenuSpec mCloseAsst = addSubmenu(null, "Close");
+		mCloseAsst.setList(getEmployeeVector());
+		mCloseAsst.setCommand(makeCommand("closeEmployee",  this));
+
+		addMenuItem( "Close Values Legend", makeCommand("closeLegend",  this));
+
+		legendOperators = new Vector();
+		legends = new ListableVector();
+		boolean success = true;
+		if (arguments !=null) {
+			hireNamedEmployee(NumberForTree.class, arguments);
+		}
+		else if (!MesquiteThread.isScripting()) {
+			hireEmployee(NumberForTree.class, "Choose information to be displayed in Values for Current Tree legend.  If you hit Cancel now, the tree legend will appear with only the tree name.");
+			/*Listable[] list = MesquiteTrunk.mesquiteModulesInfoVector.getModulesOfDuty(NumberForTree.class, null, this);
+ 			if (list!=null && list.length>0) {
+ 				ListableVector possibleAssistants = new ListableVector();
+ 				for (int i = 0; i<list.length; i++)
+ 					possibleAssistants.addElement(list[i], false);
+				success = false;
+				Listable[] hires = ListDialog.queryListMultiple(containerOfModule(), "Tree legend", "Choose information to be displayed in tree legend.  If you hit Cancel now, the tree legend will appear with only the tree name.",MesquiteString.helpString, possibleAssistants, null);
+ 				if (hires!=null) {
+ 					for (int i = 0; i<hires.length; i++) {
+						MesquiteModule mb = hireEmployeeFromModuleInfo ((MesquiteModuleInfo)hires[i], NumberForTree.class);
+						if (mb != null)
+							success = true;
+					}
+				}
+ 			}*/
+		}
+
+		return success;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*
+	public  Class getHireSubchoice(){
+		return NumberForTree.class;
+	}
+	 */
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) { //todo: pass scripting
+		TreeLegendOperator newLegend =new TreeLegendOperator(this, treeDisplay);
+		legendOperators.addElement(newLegend);
+		legends.addElement(newLegend.treeLegend, false);
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof NumberForTree) {
+				NumberForTree startupNumber = (NumberForTree)e;
+				if (newLegend.treeLegend !=null){
+					MesquiteNumber cNum = new MesquiteNumber();
+					MesquiteString resultString = new MesquiteString();
+					if (newLegend.getTree()!=null){
+						startupNumber.calculateNumber(newLegend.getTree(), cNum, resultString);
+						newLegend.treeLegend.setString(resultString.toString(), startupNumber.needsMenu(), newLegend.treeLegend.getNumStrings(), startupNumber.getID()); //TODO: maybe pass MesquiteString also in calculateNumber?
+						newLegend.treeLegend.repaint();
+					}
+				}
+			}
+		}
+		resetContainingMenuBar();
+		return newLegend;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (legendOperators.size()<=0)
+			return null;
+		Snapshot temp = new Snapshot();
+		TreeLegendOperator tL = (TreeLegendOperator)legendOperators.elementAt(0);
+		temp.addLine("setOffsetsX " + tL.treeLegend.getOffsetX());
+		temp.addLine("setOffsetsY " + tL.treeLegend.getOffsetY());
+		temp.addLine("getLegendsVector");
+		temp.addLine("tell It");
+		//to set details of legends, send commands to vector which will pass on to all of contents;
+		temp.addLine("distributeCommands");
+		temp.incorporate(tL.treeLegend.getSnapshot(file), true);
+		temp.addLine("endDistributeCommands");
+		temp.addLine("endTell");
+		for (int i = 0; i<getNumberOfEmployees(); i++) {
+			Object e=getEmployeeVector().elementAt(i);
+			if (e instanceof NumberForTree) {
+				temp.addLine("newLegendItemNoCalc ", ((MesquiteModule)e));
+			}
+		}
+		temp.addLine("calculate");
+		return temp;
+	}
+
+	public void employeeQuit(MesquiteModule m){
+		if (m == null)
+			return;
+
+		for (int j=0; j<legends.size(); j++) {
+			Object obj = legends.elementAt(j);
+			if (obj instanceof TreeLegend) {
+				TreeLegend treeLegend = (TreeLegend)obj;
+				int line = treeLegend.findLine(m.getID());
+				if (line>=0)
+					treeLegend.zapLine(line);
+				treeLegend.repaint();
+			}
+		}
+	}
+	public String nameForWritableResults(){
+		EmployeeVector ev = getEmployeeVector();
+		if (ev.size() == 0)
+			return null;
+		String results = "";
+		for (int i = 0; i<ev.size(); i++){
+			if (i != 0)
+				results += "; ";
+			results += ((MesquiteModule)ev.elementAt(i)).getNameAndParameters();
+		}
+		return results;
+	}
+	
+	public boolean suppliesWritableResults(){
+		EmployeeVector ev = getEmployeeVector();
+		if (ev == null || ev.size() == 0)
+			return false;
+		
+		return true;
+	}
+	public Object getWritableResults(){
+		String results = "";
+		Enumeration e = legendOperators.elements();
+		boolean first = true;
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeLegendOperator) {
+				TreeLegendOperator tLO = (TreeLegendOperator)obj;
+				if (!first)
+					results += "\t";
+				first = false;
+				results += tLO.getWritableResults();
+			}
+		}
+		return results;
+	}
+	public Object getResultsHeading(){
+		EmployeeVector ev = getEmployeeVector();
+		if (ev.size() == 0)
+			return null;
+		String results = "";
+		for (int i = 0; i<ev.size(); i++){
+			if (i != 0)
+				results += "\t";
+			results += ((MesquiteModule)ev.elementAt(i)).getNameAndParameters();
+		}
+		return results;
+	}
+
+
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Turns off the Values for Current Tree legend", null, commandName, "closeLegend")) {
+			closeAllLegends();
+			iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Returns the Vector of legends", null, commandName, "getLegendsVector")) {
+			return legends;
+		}
+		else if (checker.compare(this.getClass(), "Turns off one of the modules employed to display a line in the tree legend", "[employee number]", commandName, "closeEmployee")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int ox = MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(ox)){
+				for (int i=0; i<legends.size(); i++) {
+					Object obj = legends.elementAt(i);
+					if (obj instanceof TreeLegend) {
+						TreeLegend treeLegend = (TreeLegend)obj;
+						treeLegend.zapLine(ox+1);
+						treeLegend.repaint();
+					}
+				}
+				EmployeeVector ev = getEmployeeVector();
+				if (ev==null)
+					return null;
+				for (int i=0; i< ev.size(); i++){
+					MesquiteModule mb = (MesquiteModule)ev.elementAt(i);
+					if (mb!=null) {
+						if (i== ox) {
+							fireEmployee(mb);
+							return null;
+						}
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial horizontal offset of the legend", "[offset]", commandName, "setOffsetsX")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int ox = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(ox)){
+				Enumeration e = legendOperators.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TreeLegendOperator) {
+						TreeLegendOperator tLO = (TreeLegendOperator)obj;
+						tLO.treeLegend.setOffsetX(ox);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets the initial vertical offset of the legend", "[offset]", commandName, "setOffsetsY")) {
+			MesquiteInteger pos = new MesquiteInteger(0);
+			int oy = MesquiteInteger.fromString(arguments, pos);
+			if (MesquiteInteger.isCombinable(oy)){
+				Enumeration e = legendOperators.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TreeLegendOperator) {
+						TreeLegendOperator tLO = (TreeLegendOperator)obj;
+						tLO.treeLegend.setOffsetY(oy);
+					}
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to display a new line in the tree legend", "[name of module]", commandName, "newLegendItem")) {
+			incrementMenuResetSuppression();
+			NumberForTree ntt= (NumberForTree)hireNamedEmployee(NumberForTree.class, arguments);
+			decrementMenuResetSuppression();
+			if (ntt!=null) {
+				ntt.setUseMenubar(true);  //June 07: changed to true, DRM
+				MesquiteNumber cNum = new MesquiteNumber();
+				MesquiteString resultString = new MesquiteString();
+
+				Enumeration e = legendOperators.elements();
+				while (e.hasMoreElements()) {
+					Object obj = e.nextElement();
+					if (obj instanceof TreeLegendOperator) {
+						cNum.setToUnassigned();
+						resultString.setValue("");
+						TreeLegendOperator tLO = (TreeLegendOperator)obj;
+						ntt.calculateNumber(tLO.getTree(), cNum, resultString);
+						tLO.treeLegend.setString(resultString.toString(), ntt.needsMenu(), whichString(ntt), ntt.getID()); //TODO: maybe pass MesquiteString also in calculateNumber?
+						tLO.treeLegend.repaint();
+					}
+				}
+				resetContainingMenuBar();
+			}
+			return ntt;
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to display a new line in the tree legend", "[name of module]", commandName, "newLegendItemNoCalc")) {
+			incrementMenuResetSuppression();
+			NumberForTree ntt= (NumberForTree)hireNamedEmployee(NumberForTree.class, arguments);
+			decrementMenuResetSuppression();
+			if (ntt!=null) {
+				ntt.setUseMenubar(true);  //June 07: changed to true, DRM
+				resetContainingMenuBar();
+			}
+			return ntt;
+		}
+		else if (checker.compare(this.getClass(), "Hires a module to display a new line in the tree legend", "[name of module]", commandName, "calculate")) {
+			MesquiteNumber cNum = new MesquiteNumber();
+			MesquiteString resultString = new MesquiteString();
+			ListableVector v = getEmployeeVector();
+			for (int i=0; i<v.size(); i++){
+				if (v.elementAt(i) instanceof NumberForTree){
+					NumberForTree ntt = (NumberForTree)v.elementAt(i);
+					Enumeration e = legendOperators.elements();
+					while (e.hasMoreElements()) {
+						Object obj = e.nextElement();
+						if (obj instanceof TreeLegendOperator) {
+							cNum.setToUnassigned();
+							resultString.setValue("");
+							TreeLegendOperator tLO = (TreeLegendOperator)obj;
+							if (tLO.getTree()!= null){
+								ntt.calculateNumber(tLO.getTree(), cNum, resultString);
+								tLO.treeLegend.setString(resultString.toString(), ntt.needsMenu(), whichString(ntt), ntt.getID()); //TODO: maybe pass MesquiteString also in calculateNumber?
+								tLO.treeLegend.repaint();
+							}
+						}
+					}
+				}
+			}
+		}
+		else 
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void closeAllLegends() {
+		Enumeration e = legendOperators.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeLegendOperator) {
+				TreeLegendOperator tCO = (TreeLegendOperator)obj;
+				tCO.turnOff();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void employeeOutputInvalid(MesquiteModule employee, MesquiteModule source) {
+		if (employee !=null) {
+			int sn = getEmployeeVector().indexOf(employee);
+			Enumeration e = legendOperators.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeLegendOperator) {
+					TreeLegendOperator tLO = (TreeLegendOperator)obj;
+					if (tLO.treeLegend!=null) {
+						tLO.treeLegend.blank(sn+1);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public int whichString(MesquiteModule employee) {
+		if (employee !=null) {
+			return getEmployeeVector().indexOf(employee) +1;
+		}
+		return -1;
+	}
+	boolean 	treeIsEdited(){
+		MesquiteModule mb = getEmployer();
+		if (mb instanceof TreeWindowMaker)
+			return ((TreeWindowMaker)mb).treeIsEdited();
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee !=null) {
+			int sn = getEmployeeVector().indexOf(employee);
+			Enumeration e = legendOperators.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeLegendOperator) {
+					TreeLegendOperator tLO = (TreeLegendOperator)obj;
+					if (tLO.treeLegend!=null) {
+						tLO.treeLegend.blank(sn+1);
+					}
+				}
+			}
+
+			MesquiteNumber cNum = new MesquiteNumber();
+			MesquiteString resultString = new MesquiteString();
+			e = legendOperators.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeLegendOperator) {
+					TreeLegendOperator tLO = (TreeLegendOperator)obj;
+					if (tLO.treeLegend==null)
+						System.out.println("Tree legend null");
+					else {
+						cNum.setToUnassigned();
+						resultString.setValue("");
+						((NumberForTree)employee).calculateNumber(tLO.getTree(), cNum, resultString);
+						tLO.treeLegend.setString(resultString.toString(), employee.needsMenu(), sn +1, employee.getID()); 
+						tLO.treeLegend.repaint();
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		closeAllLegends();
+		super.endJob();
+		resetContainingMenuBar();
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Values for Current Tree...";
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Values for Current Tree";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Makes the legend in a tree window to display the tree name and values pertaining to the tree.";
+	}
+}
+/* ======================================================================== */
+class TreeLegendOperator extends TreeDisplayDrawnExtra {
+	private Tree myTree;
+	private TreeLegendMaker legendModule;
+	public TreeLegend treeLegend;
+
+
+	public TreeLegendOperator (TreeLegendMaker ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		this.legendModule=ownerModule;
+		treeLegend = new TreeLegend(legendModule, this);
+		addPanelPlease(treeLegend);
+	}
+	/*.................................................................................................................*/
+	public   Tree getTree() {
+		return myTree;
+	}
+	/*.................................................................................................................*/
+	public void lineTouched(int which, int where){
+		int i=0;
+		if (legendModule.getEmployeeVector()!=null) {
+			Enumeration e = legendModule.getEmployeeVector().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof NumberForTree) {
+					i++;
+					if (i==which) {
+						((MesquiteModule)obj).showPopUp(treeLegend, 0, where + 12);
+						return;
+					}
+				}
+			}
+		}
+	}
+	String writableResults;
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		myTree = tree;
+		int i=0;
+		if (tree == null)
+			return;
+		if (legendModule.treeIsEdited())
+			treeLegend.setString("Tree: Modified from " + tree.getName(), false, i, -1);
+		else 	
+			treeLegend.setString("Tree: " + tree.getName(), false, i, -1);
+		MesquiteNumber cNum = new MesquiteNumber();
+		MesquiteString resultString = new MesquiteString();
+		writableResults = "";
+		if (legendModule.getEmployeeVector()!=null) {
+			Enumeration e = legendModule.getEmployeeVector().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof NumberForTree) {
+					NumberForTree dT = (NumberForTree)obj;
+					cNum.setToUnassigned();
+					resultString.setValue("");
+					dT.calculateNumber(tree, cNum, resultString);
+					writableResults += dT.getNameAndParameters() + "\t" + cNum.toString();
+					i++;
+					treeLegend.setString(resultString.toString(), dT.needsMenu(), i, dT.getID());
+				}
+			}
+		}
+		if (treeLegend!=null) {
+			treeLegend.invalidate();
+			treeLegend.repaint();
+		}
+	}
+	String getWritableResults(){
+		return writableResults;
+	}
+	/*.................................................................................................................*/
+	public   void placeLegend(Tree tree, int drawnRoot) {
+		if (!treeLegend.isVisible()) {
+			treeLegend.setVisible(true);
+		}
+
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+
+		placeLegend(tree, drawnRoot);
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		placeLegend(tree, drawnRoot);
+		//treeLegend.print(g);
+	}
+
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		return treeLegend.getTextVersion();
+	}
+	public void turnOff() {
+		if (treeLegend!=null && treeDisplay!=null)
+			removePanelPlease(treeLegend);
+		super.turnOff();
+	}
+}
+
+/* ======================================================================== */
+class TreeLegend extends Legend implements Listable {
+	TreeLegendMaker ownerModule;
+	TreeLegendOperator legendOperator;
+	int legendWidth=100;
+	int lineHeight=16;
+	int topEdge = 6;
+	int legendHeight=16;
+	int descent = 0;
+	int lineGap = 4;
+	boolean dragging = false;
+	boolean invalid;
+	String[] lines;
+	boolean[] dropDown;
+	long[] employeeID;
+	int numLines=0;
+	Polygon dropDownTriangle;
+	int maxNumLines = 32;
+	StringInABox box;
+	int[] lineBottom;
+	public TreeLegend(TreeLegendMaker ownerModule, TreeLegendOperator legendOperator) {
+		super(100, 16);
+		this.ownerModule = ownerModule;
+		this.legendOperator = legendOperator;
+		//setBackground(getParent().getBackground());
+		box = new StringInABox("", getFont(), 300);
+		setLayout(null);
+		setSize(legendWidth, legendHeight);
+		lines = new  String [maxNumLines];
+		lineBottom = new int[maxNumLines];
+		dropDown = new boolean[maxNumLines];
+		employeeID = new long[maxNumLines];
+		dropDownTriangle=MesquitePopup.getDropDownTriangle();
+	}
+
+	public String getName(){
+		return "Values for Current Tree Legend";
+	}
+	public void invalidate(){
+		invalid = true;
+	}
+	boolean usingStringBox = false;
+	private void setLegendDimensions() {
+		FontMetrics fm = getFontMetrics(getFont());
+		descent = fm.getMaxDescent();
+		lineHeight = fm.getMaxAscent()+ descent+ lineGap;
+
+		legendHeight = (numLines) * lineHeight+topEdge - 1;
+		legendWidth=0;
+		usingStringBox = false;
+		for (int i=0 ; i<numLines; i++) {
+
+			if (!StringUtil.blank(lines[i]) && fm.stringWidth(lines[i])> legendWidth)
+				legendWidth = fm.stringWidth(lines[i]) + 4;
+			lineBottom[i] = topEdge + (i+1)*lineHeight;
+		}
+		legendWidth+= 11;
+		if (legendWidth > 300){
+			legendHeight = 0;
+			legendWidth = 300;
+			usingStringBox = true;
+			for (int i=0 ; i<numLines; i++) {				
+				if (!StringUtil.blank(lines[i])){
+					box.setStringAndFontAndWidth(lines[i], getFont(), 300, getGraphics());
+					legendHeight += box.getHeight() + 4;
+					lineBottom[i] = legendHeight;
+				}
+			}
+		}
+		if (legendHeight <20)
+			legendHeight = 20;
+		setSize(legendWidth, legendHeight);
+	}
+	public int findLine(long id) {
+		for (int i=1; i<employeeID.length; i++){
+			if (id == employeeID[i])
+				return i;
+		}
+		return -1;
+	}
+	public void zapLine(int index) {
+		if (index<maxNumLines) {
+			if (index< numLines) {
+				numLines--;
+			}
+			lines[index]=null;
+			dropDown[index] = false;
+			employeeID[index] = -1;
+			for (int i=index; i<lines.length-1; i++){
+				lines[i]=lines[i+1];
+				dropDown[i] = dropDown[i+1];
+				employeeID[i] = employeeID[i+1];
+			}
+			setLegendDimensions();
+		}
+	}
+	public void setString(String s, boolean needsMenu, int index, long id) {
+		if (index >=0 && index<maxNumLines) {
+			if (index> numLines-1) {
+				numLines = index+1;
+			}
+			lines[index]=s;
+			dropDown[index] = needsMenu;
+			employeeID[index] = id;
+			setLegendDimensions();
+		}
+	}
+
+	public int getNumStrings() {
+		return numLines;
+	}
+
+	private int lineBottom(int index) {
+		return lineBottom[index];  //topEdge + (index+1)*lineHeight; //12 +topEdge + (index)*lineHeight + descent;
+	}
+	public void place(boolean p) {
+	}
+	public void blank(int whichLine) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		Graphics g = getGraphics();
+		if (g!=null){
+			g.setColor(getBackground());
+			g.fillRect(2, lineBottom(whichLine-1), legendWidth-1, lineHeight-1);
+			g.dispose();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		invalid = false;
+		int icount=-1;
+		g.setColor(Color.cyan);
+		legendWidth = getBounds().width;
+		legendHeight = getBounds().height;
+		g.drawRect(0, 0, legendWidth-1, legendHeight-1);
+		g.fillRect(0, 0, legendWidth-1, topEdge);
+		g.drawLine(0, topEdge, legendWidth-1,topEdge);
+		g.setColor(Color.black);
+		int prevBottom = 0;
+		for (int i=0; i<numLines; i++) {
+			g.setColor(Color.black);
+			icount++;
+			if (!usingStringBox)
+				g.drawString(lines[i], 4, lineBottom(icount)-descent-4);
+			else {
+				box.setString(lines[i]);
+				box.draw(g, 4, prevBottom);
+			}
+			prevBottom = lineBottom(icount);
+			g.setColor(Color.cyan);
+			g.drawLine(0, lineBottom(icount), legendWidth-1,lineBottom(icount));
+			if (dropDown[i]) {
+				dropDownTriangle.translate(legendWidth-7,lineBottom(icount-1)+1);
+				g.setColor(Color.white);
+				g.drawPolygon(dropDownTriangle);
+				g.setColor(Color.black);
+				g.fillPolygon(dropDownTriangle);
+				dropDownTriangle.translate(-(legendWidth-7),-(lineBottom(icount-1)+1));
+			}
+		}
+		if (invalid)
+			repaint();
+		MesquiteWindow.uncheckDoomed(this);
+	}
+	public String getTextVersion() {
+		String s="";
+		for (int i=0; i<numLines; i++) {
+			s+=lines[i]+"\n";
+		}
+		return s;
+	}
+	public void setFont (Font f){
+
+		super.setFont(f);
+		setLegendDimensions();
+	}
+	public void printAll(Graphics g) {
+		invalid = false;
+		int icount=-1;
+		g.setColor(Color.black);
+		for (int i=0; i<numLines; i++) 
+			g.drawString(lines[i], 4, 10 +topEdge + (++icount)*lineHeight);
+
+		if (invalid)
+			repaint();
+	}
+	private int whichLine(int y) {
+		for (int i=0; i<=numLines; i++) {
+			if (lineBottom(i)>y)
+				return i;
+		}
+		return -1;
+	}
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (y<=topEdge) {
+			super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+		else	 { 
+			int w = whichLine(y);
+			if (w>0)
+				legendOperator.lineTouched(w,y);
+			else
+				super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/trees/TreeNotesMaker/TreeNotesMaker.java b/Source/mesquite/trees/TreeNotesMaker/TreeNotesMaker.java
new file mode 100644
index 0000000..1890a31
--- /dev/null
+++ b/Source/mesquite/trees/TreeNotesMaker/TreeNotesMaker.java
@@ -0,0 +1,419 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.TreeNotesMaker;
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+
+public class TreeNotesMaker extends TreeDisplayAssistantD  {
+	Vector notes;
+	
+	
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+    	 	notes = new Vector();
+    	 	setUseMenubar(false);
+   		addMenuItem("Close Note", makeCommand("closeNote", this));
+		addSubmenu(null, "Font", makeCommand("setFont", this), MesquiteSubmenu.getFontList());
+		addSubmenu(null, "Font Size", makeCommand("setFontSize", this), MesquiteSubmenu.getFontSizeList());
+    	 	return true;
+ 	}
+ 	
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		TreeNotesOperator newNote = new TreeNotesOperator(this, treeDisplay);
+		notes.addElement(newNote);
+		return newNote;
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	public boolean isSubstantive(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	if (notes.size()>0){
+	  	 	TreeNotesOperator tno = (TreeNotesOperator)notes.elementAt(0);
+	  	 	TreeNote tn = tno.getNote();
+	  	 	temp.addLine("getNote");
+	  	 	temp.addLine("tell It");
+	  	 	temp.incorporate(tn.getSnapshot(file), true);
+	  	 	temp.addLine("endTell");
+			
+		}
+  	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Turns off this note", null, commandName, "closeNote")) {
+    	 		closeAllNotes();
+    	 		iQuit();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Returns the note object", null, commandName, "getNote")) {
+  	 		if (notes.size()>0){
+		  	 	TreeNotesOperator tno = (TreeNotesOperator)notes.elementAt(0);
+		  	 	return tno.getNote();
+  	 		}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the font", null, commandName, "setFont")) {
+			Enumeration e = notes.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeNotesOperator) {
+					TreeNotesOperator tCO = (TreeNotesOperator)obj;
+		 			tCO.treeNote.doCommand("setFont", arguments, checker);
+		 		}
+			}
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the font size", null, commandName, "setFontSize")) {
+			Enumeration e = notes.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeNotesOperator) {
+					TreeNotesOperator tCO = (TreeNotesOperator)obj;
+		 			tCO.treeNote.doCommand("setFontSize", arguments, checker);
+		 		}
+			}
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+   	
+	/*.................................................................................................................*/
+ 	public void closeAllNotes() {
+		Enumeration e = notes.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeNotesOperator) {
+				TreeNotesOperator tCO = (TreeNotesOperator)obj;
+	 			tCO.turnOff();
+	 		}
+		}
+	}
+	/*.................................................................................................................*/
+ 	public void endJob() {
+    	 	closeAllNotes();
+ 		super.endJob();
+		resetContainingMenuBar();
+ 	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Add Note On Tree";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Draws editable notes in a tree display.";
+   	 }
+   	 
+}
+/* ======================================================================== */
+class TreeNotesOperator extends TreeDisplayDrawnExtra {
+	Tree myTree;
+	TreeNotesMaker notesModule;
+	TreeNote treeNote;
+	
+	
+	public TreeNotesOperator (TreeNotesMaker ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		this.notesModule=ownerModule;
+		treeNote = new TreeNote(notesModule, this);
+		treeNote.setVisible(false);
+		addPanelPlease(treeNote);
+	}
+	public TreeNote getNote(){
+		return treeNote;
+	}
+	/*.................................................................................................................*/
+	public   void placeNote(Tree tree, int drawnRoot) {
+		int noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		int noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		
+		if (noteX>treeDisplay.getBounds().width) {
+			treeNote.setOffsetX(treeDisplay.getBounds().width-treeDisplay.getTreeDrawing().x[drawnRoot]-40);
+			noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		}
+		else if (noteX<0) {
+			treeNote.setOffsetX(-treeDisplay.getTreeDrawing().x[drawnRoot]+4);
+			noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		}
+			
+		if (noteY>treeDisplay.getBounds().height) {
+			treeNote.setOffsetY(treeDisplay.getBounds().height-treeDisplay.getTreeDrawing().y[drawnRoot]-40);
+			noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		}
+		else if (noteY<0) {
+			treeNote.setOffsetY(-treeDisplay.getTreeDrawing().y[drawnRoot]+4);
+			noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		}
+		if ((noteX!=treeNote.getBounds().x) || (noteY!=treeNote.getBounds().y))
+			treeNote.setLocation(noteX, noteY);
+			
+		if (!treeNote.isVisible()) {
+			treeNote.setVisible(true);
+		}
+	}
+	/*.................................................................................................................*
+	old, tree root based position
+	public   void placeNote(Tree tree, int drawnRoot) {
+		int noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		int noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		
+		if (noteX>treeDisplay.getBounds().width) {
+			treeNote.setOffsetX(treeDisplay.getBounds().width-treeDisplay.getTreeDrawing().x[drawnRoot]-40);
+			noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		}
+		else if (noteX<0) {
+			treeNote.setOffsetX(-treeDisplay.getTreeDrawing().x[drawnRoot]+4);
+			noteX = treeDisplay.getTreeDrawing().x[drawnRoot]+treeNote.getOffsetX();
+		}
+			
+		if (noteY>treeDisplay.getBounds().height) {
+			treeNote.setOffsetY(treeDisplay.getBounds().height-treeDisplay.getTreeDrawing().y[drawnRoot]-40);
+			noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		}
+		else if (noteY<0) {
+			treeNote.setOffsetY(-treeDisplay.getTreeDrawing().y[drawnRoot]+4);
+			noteY = treeDisplay.getTreeDrawing().y[drawnRoot]+treeNote.getOffsetY();
+		}
+		if ((noteX!=treeNote.getBounds().x) || (noteY!=treeNote.getBounds().y))
+			treeNote.setLocation(noteX, noteY);
+			
+		if (!treeNote.isVisible()) {
+			treeNote.setVisible(true);
+		}
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (!treeNote.isVisible()) {
+			treeNote.setVisible(true);
+		}
+		//placeNote(tree, drawnRoot);
+	}
+	/*.................................................................................................................*/
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		if (!treeNote.isVisible()) {
+			treeNote.setVisible(true);
+		}
+		//placeNote(tree, drawnRoot);
+		//treeNote.print(g);
+	}
+	
+	/*.................................................................................................................*/
+	public void turnOff() {
+		if (treeNote!=null && treeDisplay!=null)
+			removePanelPlease(treeNote);
+		super.turnOff();
+	}
+}
+
+/* ======================================================================== */
+class TreeNote extends ResizableLegend {
+	TreeNotesMaker ownerModule;
+	TreeNotesOperator notesOperator;
+	int noteWidth=100;
+	int lineHeight=16;
+	int noteHeight=20;
+	//boolean dragging = false;
+	//boolean sizing = false;
+	//int offsetX = 20;
+	//int offsetY=0;
+	int topEdge = 6;
+	int cornerEdge = 4;
+	//int origTouchX, origTouchY, dragOffsetX, dragOffsetY, sizeOffsetX, sizeOffsetY;
+	boolean invalid;
+	StringInABox textBox;
+	StringBuffer sb;
+	
+	boolean checkHeight = true;
+	static Image dropDownArrow=null;
+	Font font=null;
+	
+	static {
+		dropDownArrow = Toolkit.getDefaultToolkit().getImage(MesquiteModule.getRootPath() +"images/menuDropArrow.gif");
+	}
+
+	public TreeNote(TreeNotesMaker ownerModule, TreeNotesOperator notesOperator) {
+		super(100, 20);
+		this.ownerModule = ownerModule;
+		this.notesOperator = notesOperator;
+		//setBackground(getParent().getBackground());
+		setLayout(null);
+		sb = new StringBuffer("");
+		font = getFont();
+		textBox = new StringInABox(sb, getFont(), noteWidth);
+		checkHeight = true;
+		if (dropDownArrow==null)
+			dropDownArrow = Toolkit.getDefaultToolkit().getImage(MesquiteModule.getRootPath() +"images/menuDropArrow.gif");
+		setSize(noteWidth, noteHeight);
+	}
+	
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+  	 	temp.incorporate(super.getSnapshot(file), false);
+  	 	temp.addLine("setNote " + StringUtil.tokenize(textBox.getString()));
+  	 	temp.addLine("setOffsetX " + offsetX);
+  	 	temp.addLine("setOffsetY " + offsetY);
+  	 	return temp;
+  	 }
+  	 MesquiteInteger pos = new MesquiteInteger();
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the text of the note", "[text]", commandName, "setNote")) {
+    	 		setText(ParseUtil.getFirstToken(arguments, pos));
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the initial horizontal offset of the note from home position", "[offset in pixels]", commandName, "setOffsetX")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int ox = MesquiteInteger.fromString(arguments, pos);
+    	 		if (MesquiteInteger.isCombinable(ox))
+    	 			setOffsetX(ox);
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Sets the initial vertical offset of the note from home position", "[offset in pixels]", commandName, "setOffsetY")) {
+    	 		MesquiteInteger pos = new MesquiteInteger(0);
+    	 		int oy = MesquiteInteger.fromString(arguments, pos);
+    	 		if (MesquiteInteger.isCombinable(oy))
+    	 			setOffsetY(oy);
+    	 	}
+    	 	else 
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+	public void invalidate(){
+		invalid = true;
+	}
+	
+	
+	
+	public void setText(String s) {
+		sb.setLength(0);
+		sb.append(s);
+		textBox.setString(sb);
+		checkMinimumHeight();
+		repaint();
+	}
+	
+	
+	public void setBounds(int x, int y, int width, int height) {
+		noteWidth = width;
+		noteHeight = height;
+		textBox.setWidth(noteWidth);
+		int gH =textBox.getHeight();
+		if (height<gH) {
+			noteHeight = gH;
+		}
+		super.setBounds(x, y, noteWidth, noteHeight);
+	}
+	public void setSize(int width, int height) {
+		noteWidth = width;
+		noteHeight = height;
+		textBox.setWidth(noteWidth);
+		int gH =textBox.getHeight();
+		if (height<gH) {
+			noteHeight = gH;
+		}
+		super.setSize(noteWidth, noteHeight);
+	}
+	public void resetHeight(int height) {
+		noteHeight = height;
+		super.setSize(noteWidth, height);
+	}
+	void checkMinimumHeight() {
+		int gH =textBox.getHeight();
+		if (getBounds().height<gH)
+			resetHeight(gH);
+	}
+	public void setPanelFont(Font f) {
+		super.setPanelFont(f);
+		setFont(f);
+	}
+	
+	public void setFont(Font f) {
+		font = f;
+		textBox.setFont(f);
+		checkMinimumHeight();
+		super.setFont(f);
+	}
+	
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		invalid = false;
+		if (g instanceof PrintGraphics) {
+			textBox.draw(g,0,0);
+		}
+		else {
+			if (font==null) {
+				font = getFont();
+				textBox.setFont(font);
+			}
+			g.setColor(Color.cyan);
+			g.setClip(0,0,noteWidth, topEdge);
+			g.fillRoundRect(0, 0, noteWidth-1, noteHeight, 8, 8);
+			g.setColor(Color.blue);
+			g.drawRoundRect(0, 0, noteWidth-1, noteHeight, 8, 8);
+			g.setClip(0,0,noteWidth, noteHeight);
+			g.drawLine(0, topEdge, noteWidth-1, topEdge);
+			g.drawImage(dropDownArrow, noteWidth - 16, 0, this);
+			g.setColor(Color.cyan);
+			g.drawRect(0, topEdge, noteWidth-1, noteHeight-1-topEdge);
+			g.fillRect(noteWidth - 8, noteHeight - cornerEdge, 8, cornerEdge);
+			g.fillRect(noteWidth - cornerEdge, noteHeight - 8, cornerEdge, 8);
+			g.setColor(Color.black);
+			
+			textBox.draw(g,0,0);
+			
+			if (invalid)
+				repaint();
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		if (y<=topEdge) {
+			if (x>= noteWidth - 16) {
+				if (MesquiteEvent.controlKeyDown(modifiers))
+						panelTouched(modifiers, x,y, false);
+				else
+					ownerModule.showPopUp(this, x+8, y+8);
+			}
+			else {
+				super.mouseDown(modifiers, clickCount, when, x, y, tool);
+			}
+		}
+		else if (y> noteHeight-8 && x > noteWidth - 8) {
+				super.mouseDown(modifiers, clickCount, when, x, y, tool);
+		}
+		else {
+			String edited = MesquiteString.queryMultiLineString(ownerModule.containerOfModule(), "Note", "Note for tree:", sb.toString(), 8, false, false);
+			if (edited!=null)
+				setText(edited);
+		}
+	}
+}
+
+
diff --git a/Source/mesquite/trees/TreeOfContext/TreeOfContext.java b/Source/mesquite/trees/TreeOfContext/TreeOfContext.java
new file mode 100644
index 0000000..a5155e0
--- /dev/null
+++ b/Source/mesquite/trees/TreeOfContext/TreeOfContext.java
@@ -0,0 +1,354 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.TreeOfContext;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies a "current" tree.  It does this by looking for currently open tree contexts -- for instance, a Tree Window showing a tree.  If the tree is 
+for the appropriate block of taxa, this module can returns it.  It is used by simulators of character evolution and other calculations that depend upon a single "current tree".
+There is a search strategy, prefering tree contexts that are among the employers of this module, then looking later to more distantly connected contexts. */
+public class TreeOfContext extends OneTreeSource implements TreeContextListener {
+	TreeContext context=null;
+	TreeContext oldContext=null;
+	Taxa oldTaxa = null;
+	MesquiteTree rememberedDefaultTree = null;
+	Tree lastTree;
+	String contextID = null;
+	Object condition = null;
+	
+	//TODO: problem here with snapshotting.  This module may depend on a module in the employee tree, hired after it.  Must make sure
+	//context is hire before this module
+  	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+  		this.condition = condition;
+  		if (!MesquiteThread.isScripting()){
+	  		context = (TreeContext)findEmployerWithDuty(TreeContext.class);
+	  		if (context == null)
+	  			context = (TreeContext)findNearestColleagueWithDuty(TreeContext.class);
+	   		if (context == null){
+	   			return sorry("Sorry, " + whatIsMyPurpose()+ " you need to have an open Tree Window to serve as a source of a current tree; no appropriate Tree Window could be found.  You may request a Tree Window from the Trees menu.  The Multi Tree window is not appropriate, as it does not show a single current tree."); //TODO: should alert user
+	   		}
+	   		}
+   		context = null; // the check on context had been just to ensure that there was something
+		addMenuItem("Display Tree (used by " + getEmployer().getName() +")", makeCommand("showContext", this));
+  		return true;
+  	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+ 	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+ 	
+	/*.................................................................................................................*/
+  	 public Snapshot getSnapshot(MesquiteFile file) {
+   	 	Snapshot temp = new Snapshot();
+   	 	//tree context will create variable announcing its moduleID;
+   	 	//this module will request the name of the variable
+  	 	if (context instanceof MesquiteModule){
+   			String s =((MesquiteModule)context).getPermanentIDString();
+			temp.addLine("setContextID " + s);  //for tree context
+  	 	}	
+
+   	 	//temp.addLine(" " , treeSourceTask);
+
+ 	 	return temp;
+  	 }
+	/*.................................................................................................................*/
+    	 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+    	 	if (checker.compare(this.getClass(), "Sets the context identification code of this module (this is used internally in saving scripts to ensure users of the context reconnect to the correct tree context", "[code string]", commandName, "setContextID")) {
+   
+    	 		contextID = arguments;
+    	 		if (!MesquiteThread.isScripting())
+    	 			parametersChanged();
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Gets the current context", null, commandName, "getContext")) {
+   			return context;
+    	 	}
+    	 	else if (checker.compare(this.getClass(), "Shows the current context", null, commandName, "showContext")) {
+	  		if (context == null)
+	  			alert("Sorry, there is no record of a current tree context.");
+	  		else if (context instanceof Showable)
+	  			((Showable)context).showMe();
+	  		else
+	  			alert("Sorry, the current tree in use is not in a location that can be shown.");
+    	 	}
+    	 	else
+    	 		return  super.doCommand(commandName, arguments, checker);
+		return null;
+   	 }
+    	private boolean contextAppropriate(TreeContext context, Taxa taxa) {
+  		if (context ==null)
+  			return false;
+  		if (context.getTree()==null)
+  			return false;
+  		if (context.getTree().getTaxa() == null)
+  			return false;
+		if (taxa == null)
+  			return false;
+  		return context.getTree().getTaxa().equals(taxa);
+    	}
+	/*.................................................................................................................*/
+  	private TreeContext findContext(Taxa taxa){
+  		if (contextAppropriate(context, taxa))
+  			return context;
+  		ListableVector contexts = findModulesWithDuty(TreeContext.class);
+  		for (int i=0; i<contexts.size(); i++) {
+  			TreeContext c = (TreeContext)contexts.elementAt(i);
+  			if (contextAppropriate(c, taxa)) 
+  				return c;
+  		}
+  		return null;
+  	}
+	/*.................................................................................................................*/
+	/* rule: first, look for context among ancestor employees. If one found, use as default. If not, look for closest.  If more than one, allow
+	user to choose.  If one, use.  If more than one, allow for user to reattach to other context*/
+	/*.................................................................................................................*/
+  	private TreeContext queryFindContext(Taxa taxa){
+  		if (taxa==null)
+  			return null;
+  		
+  		//first, find out if current context is OK
+     		if (contextAppropriate(context, taxa)) {
+  			return context;
+  		}
+  			
+  		//First, gather info about all TreeContexts
+ 		ListableVector contexts = findModulesWithDuty(TreeContext.class);
+ 
+ 		if (contexts==null)
+ 			return null;
+		for (int i = contexts.size()-1; i>=0; i--){
+  			TreeContext c = (TreeContext)contexts.elementAt(i);
+  			if (!contextAppropriate(c, taxa)) 
+  				contexts.removeElement(c, false);
+		}
+
+
+ 		TreeContext employerContext = null;
+  		// otherwise, check among ancestors
+  		if (condition == null || !(condition instanceof MesquiteBoolean && !((MesquiteBoolean)condition).getValue())){
+  			MesquiteModule mb = getEmployer();
+  		while (mb !=null && !(mb instanceof TreeContext))
+  			mb = mb.getEmployer();
+  		if (mb!=null && mb instanceof TreeContext && contextAppropriate((TreeContext)mb, taxa)) {
+  			employerContext = (TreeContext)mb;
+  		}
+  		}
+  		/**/
+  			
+  		if (contexts.size()==1) { //just one context found
+  			TreeContext context = (TreeContext)contexts.elementAt(0);
+  			if (!contextAppropriate(context, taxa))
+  				return null;
+  			if (!MesquiteThread.isScripting()) {
+  				String s = "The current tree (for " + employer.getName() + ") will be obtained from ";
+  				if (context instanceof MesquiteModule)
+  					s+="the window " + ((MesquiteModule)context).containerOfModule().getName();
+  				else if (context instanceof Listable)
+  					s+= context.getName();
+				alert(s);
+  			}
+  			return context;
+  			
+  		}
+  		else if (contexts.size()==0) //no contexts found
+  			return null;
+  		else if (MesquiteThread.isScripting()){ //if scripting use employer context or first one found
+  			if (employerContext!=null)
+	  			context = employerContext;
+			else
+	  			context = (TreeContext)contexts.elementAt(0);
+  			return context;
+  		}
+  		else { //more than one found, not scripting
+			if (employerContext!=null)
+	  			context = employerContext;
+			else {
+	  			context = null;
+	  			int i = 0;
+	  			while (i<contexts.size() && context == null){
+	  				EmployerEmployee tc = (EmployerEmployee)contexts.elementAt(i);
+	  				if (!isEmployerOrHigher(tc)){
+	  					context = (TreeContext)tc;
+	  				}
+	  				i++;
+	  			}
+	  			if (context == null)
+		  			context = (TreeContext)contexts.elementAt(0);
+			}
+	  		if (context instanceof Showable)
+	  			((Showable)context).showMe();
+			String s = "The current tree (for " + employer.getName() + ") will be obtained from the window " + ((MesquiteModule)context).containerOfModule().getName();
+			s+= "\n\nIs this OK?";
+			if (AlertDialog.query(containerOfModule(), "Query", s, "Yes", "No"))
+	  			return context;
+			
+			context = null;
+
+
+			Context[] cx = new Context[contexts.size()];
+			for (int i=0; i<contexts.size(); i++){
+	  			cx[i] = (Context)contexts.elementAt(i);
+			}
+  			int chosen = ListDialog.queryList(containerOfModule(), "Choose tree context", "Choose the tree context from which to obtain the current tree (for " + employer.getName() + ")", MesquiteString.helpString,cx, 0, true);
+  			if (MesquiteInteger.isNonNegative(chosen)) {
+  				context =  (TreeContext)contexts.elementAt(chosen);
+  				return context;
+  			}
+  			else
+  				return null;
+  		}
+  		
+  		//CONTEXTNAME should be used here
+  	}
+	/*.................................................................................................................*/
+  	public void setPreferredTaxa(Taxa taxa){
+  	}
+  	
+  	public MesquiteModule getUltimateSource(){
+  		if (context == null)
+  			return null;
+  		return context.getTreeSource();
+  	}
+	/*.................................................................................................................*/
+	/** For TreeContextListener */
+	public void treeChanged(Tree tree) { 
+		parametersChanged(new Notification());
+	}
+	/*.................................................................................................................*/
+	/** For TreeContextListener */
+	public void disposing(TreeContext context) {
+		if (this.context == context) {
+			context.removeTreeContextListener(this);
+			rememberedDefaultTree = null;
+			lastTree = null;
+			this.context = null;
+			oldContext = null;
+			parametersChanged();
+		}
+	}
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Taxa taxa){
+   		if (taxa==null)
+   			return;
+   		context = queryFindContext(taxa);
+   	}
+	public void broadCastAssignedID(MesquiteModule module, String assignedID){
+  		if (contextID !=null && contextID.equals(assignedID))
+  			parametersChanged();
+	}
+   	boolean warned = false;
+	/*.................................................................................................................*/
+	/* rule: first, look for context among ancestor employees. If one found, use as default. If not, look for closest.  If more than one, allow
+	user to choose.  If one, use.  If more than one, allow for user to reattach to other context*/
+   	public Tree getTree(Taxa taxa) {
+   		if (taxa==null)
+   			return null;
+   		if (doomed)
+   			return null;
+   		//if context is supplying tree with other Taxa, need to look for other contexts!
+  		if (contextID !=null) {
+  			/*try to find id'd context (looking through modules for their assignedIDString.
+  			if found, set to context, and set contextID to null
+  			if not, return null; */
+  			MesquiteModule mb = getFileCoordinator().findEmployeeWithPermanentID(contextID);
+  			if (mb == null) {
+  				context= null;
+  				return null;
+  			}
+  			else if (mb instanceof TreeContext) {
+  				context = (TreeContext)mb;
+  				contextID = null;
+  			}
+  		}
+   		context = queryFindContext(taxa);
+ 		if (context == null) {
+			if (taxa != oldTaxa || rememberedDefaultTree == null)
+				rememberedDefaultTree = taxa.getDefaultDichotomousTree(rememberedDefaultTree);
+			oldTaxa = taxa;
+	   		if (context instanceof MesquiteModule)
+	   			deferBranchPriority((MesquiteModule)context);
+	   		if (!MesquiteThread.isScripting() && !warned){
+	   			alert("No suitable current tree was found (for " + employer.getName() + ").  A tree window needs to be open to supply a current tree.  There may be no tree window available for this set of taxa, or the tree in an available window may not be usable for this purpose.  This module may have to quit, and you may have to choose an alternative.");
+	   			warned = true;
+	   			iQuit();
+	   			return null;
+	   		}
+	   		lastTree =rememberedDefaultTree;
+			return rememberedDefaultTree;
+		}
+		else if (context != oldContext) {
+			if (oldContext !=null)
+				oldContext.removeTreeContextListener(this);
+	   		context.addTreeContextListener(this);
+	   		if (context instanceof MesquiteModule)
+	   			deferBranchPriority((MesquiteModule)context);
+	   	}
+		oldContext = context;
+   		Tree tree = context.getTree();
+   		oldTaxa = taxa;
+   		lastTree = tree;
+		if (taxa == null) 
+			return tree;
+		else if (tree != null && taxa.equals(tree.getTaxa(), false)) 
+			return tree;
+		else {
+   			lastTree = taxa.getDefaultTree();
+	   		if (!MesquiteThread.isScripting() && !warned){
+	   			alert("No suitable current tree was found (for " + employer.getName() + ").  A default tree will be used instead.");
+	   			warned = true;
+	   		}
+			return lastTree;
+		}
+   	}
+	/*.................................................................................................................*/
+	public void endJob() {
+		if (context!=null)
+			context.removeTreeContextListener(this);
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree of context";
+   	 }
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+  	 public String getParameters() {
+		String s = null;
+		if (context == null)
+			s = "No tree context found; default trees used.";
+		else
+			s = "Tree(s) used from " + context.getContextName() + ".";  
+		 if (lastTree!=null)
+		 	s+= " Last tree used: " + lastTree.getName() +  "  [tree: " + lastTree.writeTree() + "] ";
+		return s;
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Supplies a single tree from the nearest tree context (e.g., an available tree window).";
+   	 }
+   	 
+}
+
diff --git a/Source/mesquite/trees/TreeValueUsingMatrix/TreeValueUsingMatrix.java b/Source/mesquite/trees/TreeValueUsingMatrix/TreeValueUsingMatrix.java
new file mode 100644
index 0000000..69f68fb
--- /dev/null
+++ b/Source/mesquite/trees/TreeValueUsingMatrix/TreeValueUsingMatrix.java
@@ -0,0 +1,135 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.TreeValueUsingMatrix;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class TreeValueUsingMatrix extends NumberForTree {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(MatrixSourceCoord.class, getName() + "  needs a source of matrices.",
+		"");
+		EmployeeNeed e2 = registerEmployeeNeed(NumberForMatrixAndTree.class, getName() + "  needs a method to calculate values for the trees using a matrix.",
+		"The method to calculate values can be selected initially");
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumberForMatrixAndTree.class;
+	}
+	/*.................................................................................................................*/
+	MatrixSourceCoord characterSourceTask;
+	NumberForMatrixAndTree numberTask;
+	Taxa oldTaxa = null;
+    	 MCharactersDistribution matrix;
+
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numberTask = (NumberForMatrixAndTree)hireNamedEmployee(NumberForMatrixAndTree.class, arguments);
+			if (numberTask == null)
+				return sorry(getName() + " couldn't start because the requested calculator module wasn't successfully hired.");
+		}
+		else {
+		numberTask = (NumberForMatrixAndTree)hireEmployee(NumberForMatrixAndTree.class, "Value to calculate for trees");
+ 		if (numberTask == null)
+ 			return sorry(getName() + " couldn't start because no steps counting module was obtained.");
+		}
+		characterSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, numberTask.getCompatibilityTest(), "Source of characters (for " + numberTask.getName() + ")");
+ 		if (characterSourceTask == null)
+ 			return sorry(getName() + " couldn't start because no source of characters was obtained.");
+  		return true;
+  	 }
+  	 public void employeeQuit(MesquiteModule m){
+  	 		iQuit();
+  	 }
+ 	/*===== For NumberForItem interface ======*/
+  	public boolean returnsMultipleValues(){
+  		if (numberTask == null)
+  			return false;
+   		return numberTask.returnsMultipleValues();
+   	}
+  	 
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return true;  
+   	}
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return false;
+   	 }
+   	/** Called to provoke any necessary initialization.  This helps prevent the module's intialization queries to the user from
+   	happening at inopportune times (e.g., while a long chart calculation is in mid-progress)*/
+   	public void initialize(Tree tree){
+   		characterSourceTask.initialize(tree.getTaxa());
+   	}
+	MesquiteString cs = new MesquiteString();
+	/*.................................................................................................................*/
+	public void calculateNumber(Tree tree, MesquiteNumber result, MesquiteString resultString) {
+    	 	if (result==null || tree == null)
+    	 		return;
+    	clearResultAndLastResult(result);
+   	 	int count=0;
+    	Taxa taxa = tree.getTaxa();
+ 		matrix = characterSourceTask.getCurrentMatrix(tree);
+		
+		if (matrix == null) {
+			if (resultString!=null)
+				resultString.setValue("Value for tree not calculated; no matrix supplied");
+			return;
+		}
+		cs.setValue("");
+		numberTask.calculateNumber(tree, matrix, result, cs);
+		if (resultString!=null)
+			resultString.setValue(cs.getValue() + " (for matrix " + characterSourceTask.getCurrentMatrixName(tree.getTaxa()) + ")");
+		saveLastResult(result);
+		saveLastResultString(resultString);
+	}
+	public boolean biggerIsBetter() {
+		return false;
+	}
+	/*.................................................................................................................*/
+
+	/*.................................................................................................................*/
+   	 public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+   	 	if (employee==characterSourceTask) {
+			parametersChanged(notification);
+   	 	}
+   	 	else if (employee==numberTask) {
+			parametersChanged(notification);
+   	 	}
+   	 }
+	/*.................................................................................................................*/
+    	 public String getParameters() {
+		return "Value calculated: " + numberTask.getName() + "(Source of matrices: " + characterSourceTask.getNameAndParameters() + ")";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getNameAndParameters() {
+		return numberTask.getName() + "(Source of matrices: " + characterSourceTask.getNameAndParameters() + ")";
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Tree value using character matrix";
+   	 }
+	/*.................................................................................................................*/
+  	 public String getExplanation() {
+		return "Calculates a value for the tree using a character data matrix.";
+   	 }
+}
+
diff --git a/Source/mesquite/trees/Ultrametricize/Ultrametricize.java b/Source/mesquite/trees/Ultrametricize/Ultrametricize.java
new file mode 100644
index 0000000..636a83e
--- /dev/null
+++ b/Source/mesquite/trees/Ultrametricize/Ultrametricize.java
@@ -0,0 +1,94 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.Ultrametricize;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class Ultrametricize extends BranchLengthsAltererMult {
+	double resultNum;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		return true;
+  	 }
+  	 
+	/*.................................................................................................................*/
+   	 public boolean isSubstantive(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean isPrerelease(){
+   	 	return false;
+   	 }
+   
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+   	public boolean requestPrimaryChoice(){
+   		return false;  
+   	}
+	/*.................................................................................................................*/
+	public  boolean transformTree(AdjustableTree tree, MesquiteString resultString, boolean notify){
+		tree.arbitrarilyUltrametricize();
+		//allOnes(tree, tree.getRoot());
+		//ut(tree, tree.getRoot(), tree.tallestPathAboveNode(tree.getRoot(), 0));
+		if (notify && tree instanceof Listened) ((Listened)tree).notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+		return true;
+	}
+	/*.................................................................................................................*
+   	 private void allOnes(AdjustableTree tree, int node){
+		if (!MesquiteDouble.isCombinable(tree.getBranchLength(node))) {
+			tree.setBranchLength(node, 1, false);
+		}
+		for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+			allOnes(tree, daughter);
+		}
+   	 }
+   	 private void ut(AdjustableTree tree, int node, double targetHeight){
+		if (tree.nodeIsTerminal(node)) {
+			tree.setBranchLength(node, targetHeight, false);
+		}
+		else {
+	   	 	double heightAbove = tree.tallestPathAboveNode(node, 0);
+			double nodeLength;
+			if (heightAbove==0) 
+				nodeLength = targetHeight/2;
+			else
+				nodeLength = targetHeight-heightAbove;
+			if (tree.getRoot()!=node)
+				tree.setBranchLength(node, nodeLength, false);
+			for (int daughter=tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter) ) {
+				ut(tree, daughter, targetHeight - nodeLength);
+			}
+		}
+   	 	
+   	 }
+	/*.................................................................................................................*/
+   	 public boolean showCitation(){
+   	 	return true;
+   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Arbitrarily Ultrametricize";
+   	 }
+   	 
+	/*.................................................................................................................*/
+ 	/** returns an explanation of what the module does.*/
+ 	public String getExplanation() {
+ 		return "Adjusts a tree's branch lengths so that the distances among terminal taxa are ultrametric (i.e. like a molecular clock, all tips reaching to same level).  This is not done with any sophisticated smoothing algorithm; rather, branches are just stretched until they reach to same level." ;
+   	 }
+}
+
diff --git a/Source/mesquite/trees/UtilityCoordinator/UtilityCoordinator.java b/Source/mesquite/trees/UtilityCoordinator/UtilityCoordinator.java
new file mode 100644
index 0000000..56c1bca
--- /dev/null
+++ b/Source/mesquite/trees/UtilityCoordinator/UtilityCoordinator.java
@@ -0,0 +1,69 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.UtilityCoordinator;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+//new 1.04
+/* ======================================================================== */
+public class UtilityCoordinator extends TreeWindowAssistantI {
+	public String getName() {
+		return "Tree Utility Coordinator";
+	}
+
+	public String getExplanation() {
+		return "Coordinates use of tree utilities in tree window" ;
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(TreeUtility.class, "Various utilities to use trees may be available in the Tree Window.",
+		"Utilities to use trees may be available in the Utilities submenu of the Tree Window");
+	}
+	/*.................................................................................................................*/
+	Tree tree;
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		addSubmenu(null, "Utilities", makeCommand("doUtility",  this), TreeUtility.class);
+		return true;
+	}
+
+	public boolean isSubstantive(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		this.tree = tree;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Hires utility module to use the tree", "[name of module]", commandName, "doUtility")) {
+			if (tree!=null) {
+				TreeUtility tda= (TreeUtility)hireNamedEmployee(TreeUtility.class, arguments);
+				if (tda!=null) {
+					tda.useTree(tree);
+					//if (!tda.pleaseLeaveMeOn()) //if allowed to stay on, need to keep a list of active utilities and inform them when tree changes
+					fireEmployee(tda);
+				}
+			}
+			return null;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+
+}
+
diff --git a/Source/mesquite/trees/ValuesAtNodes/ValuesAtNodes.java b/Source/mesquite/trees/ValuesAtNodes/ValuesAtNodes.java
new file mode 100644
index 0000000..35b0c5b
--- /dev/null
+++ b/Source/mesquite/trees/ValuesAtNodes/ValuesAtNodes.java
@@ -0,0 +1,486 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.ValuesAtNodes;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ValuesAtNodes extends TreeDisplayAssistantMA implements LegendHolder {
+	public String getName() {
+		return "Values for Nodes";
+	}
+	public String getExplanation() {
+		return "Shows on a drawn tree various possible numbers at the nodes.";
+	}
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e = registerEmployeeNeed(NumbersForNodes.class, getName() + "  needs a method to calculate values at the nodes of the tree.",
+		"The method to calculate values at nodes can be selected initially or in the Values at Nodes submenu of the Node_Values menu");
+		EmployeeNeed e2 = registerEmployeeNeed(DisplayNumbersAtNodes.class, getName() + "  uses a module to display values at nodes.",
+		"The method to display values can be selected initially");
+	}
+	/*.................................................................................................................*/
+	public NumbersForNodes numForNodesTask;
+	public DisplayNumbersAtNodes displayTask;
+	Vector traces;
+	MesquiteString numberTaskName;
+	MesquiteCommand nfntC;
+	int initialOffsetX=MesquiteInteger.unassigned;
+	int initialOffsetY= MesquiteInteger.unassigned;
+	boolean suppress = false;
+
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		if (arguments !=null) {
+			numForNodesTask = (NumbersForNodes)hireNamedEmployee(NumbersForNodes.class, arguments);
+			if (numForNodesTask == null)
+				return sorry(getName() + " cannot start because the requested module to calculate values was not obtained.");
+		}
+		else {
+			numForNodesTask = (NumbersForNodes)hireEmployee(NumbersForNodes.class, "Values at nodes");
+			if (numForNodesTask == null) {
+				return sorry(getName() + " cannot start because no appropriate module to calculate values was obtained.");
+			}
+		}
+		nfntC = makeCommand("setNumForNodes",  this);
+		numForNodesTask.setHiringCommand(nfntC);
+		numberTaskName = new MesquiteString(numForNodesTask.getName());
+		displayTask = (DisplayNumbersAtNodes)hireNamedEmployee(DisplayNumbersAtNodes.class, "#ShadeNumbersOnTree");
+		if (displayTask == null) 
+			displayTask = (DisplayNumbersAtNodes)hireEmployee(DisplayNumbersAtNodes.class, "Choose display method for Values at Nodes");
+		if (displayTask == null) {
+			return sorry(getName() + " couldn't start because no display module was obtained");
+		}
+		setDefaultsFromNumbersForNodes();
+		traces = new Vector();
+		makeMenu("Node_Values");
+		resetContainingMenuBar();
+		if (numModulesAvailable(NumbersForNodes.class)>1){
+			MesquiteSubmenuSpec mss = addSubmenu(null, "Value at Nodes", nfntC, NumbersForNodes.class);
+			mss.setSelected(numberTaskName);
+		}
+		addMenuItem( "Transfer to Associated", makeCommand("transferToAssociated",  this));
+		addMenuItem( "Close Node Values", makeCommand("closeTrace",  this));
+		addMenuItem( "-", null);
+		return true;
+	}
+	/*.................................................................................................................*/
+	private void setDefaultsFromNumbersForNodes(){
+		if (displayTask!=null && numForNodesTask!=null) {
+			displayTask.setShadeBranches(numForNodesTask.getDefaultShadeBranches());
+			displayTask.setShadeInColor(numForNodesTask.getDefaultShadeInColor());
+			displayTask.setShowLabels(numForNodesTask.getDefaultShowLabels());
+			displayTask.setLabelTerminals(numForNodesTask.getDefaultLabelTerminals());
+		}
+	}
+	/*.................................................................................................................*/
+
+	public boolean suppliesWritableResults(){
+		return traces.size()<2;
+	}
+	public Object getWritableResults(){
+		if (traces.size() != 1)
+			return null;
+		ValuesAtNodesOperator trace = (ValuesAtNodesOperator)traces.elementAt(0);
+		String results = trace.vModule.getName();
+		for (int i = 0; i<trace.numArray.getSize(); i++){
+			results += "\t" + trace.numArray.toString(i);
+		}
+		return results;
+	}
+	public Object getResultsHeading(){
+		if (traces.size() != 1)
+			return null;
+		ValuesAtNodesOperator trace = (ValuesAtNodesOperator)traces.elementAt(0);
+		String results = trace.vModule.getName();
+		return results;
+	}
+
+	public boolean showLegend(){
+		return true;
+	}
+	public int getInitialOffsetX(){
+		return initialOffsetX;
+	}
+	public int getInitialOffsetY(){
+		return initialOffsetY;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if(m==displayTask)
+			iQuit();
+	}
+	/*.................................................................................................................*/
+	public  Class getHireSubchoice(){
+		return NumbersForNodes.class;
+	}
+	/*.................................................................................................................*/
+	public   TreeDisplayExtra createTreeDisplayExtra(TreeDisplay treeDisplay) {
+		ValuesAtNodesOperator newTrace = new ValuesAtNodesOperator(this, treeDisplay);
+		traces.addElement(newTrace);
+		return newTrace;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.addLine("suppress");
+		temp.addLine("setNumForNodes", numForNodesTask);
+		temp.addLine("setDisplay", displayTask);
+		ValuesAtNodesOperator tco = (ValuesAtNodesOperator)traces.elementAt(0);
+		if (tco!=null && tco.vLegend!=null) {
+			temp.addLine("setInitialOffsetX " + tco.vLegend.getOffsetX()); //Should go operator by operator!!!
+			temp.addLine("setInitialOffsetY " + tco.vLegend.getOffsetY());
+		}
+		temp.addLine("desuppress");
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Sets the module calculating the numbers for the nodes", "[name of module]", commandName, "setNumForNodes")) {
+			NumbersForNodes temp=  (NumbersForNodes)replaceEmployee(NumbersForNodes.class, arguments, "Value to calculate at nodes", numForNodesTask);
+			if (temp!=null) {
+				numForNodesTask= temp;
+				numForNodesTask.setHiringCommand(nfntC);
+				numberTaskName.setValue(numForNodesTask.getName());
+				resetAllTraceOperators();
+				recalculateAllTraceOperators();
+				if (!suppress)
+					parametersChanged();
+			}
+			return numForNodesTask;
+		}
+		else if (checker.compare(this.getClass(), "Sets the module displaying the numbers for the nodes", "[name of module]", commandName, "setDisplay")) {
+			DisplayNumbersAtNodes temp=  (DisplayNumbersAtNodes)replaceEmployee(DisplayNumbersAtNodes.class, arguments, "Displayer of numbers at nodes", displayTask);
+			if (temp!=null) {
+				displayTask= temp;
+				setDefaultsFromNumbersForNodes();
+				resetAllTraceOperators();
+				recalculateAllTraceOperators();
+				if (!suppress)
+					parametersChanged();
+			}
+			return displayTask;
+		}
+		else if (checker.compare(this.getClass(), "Suppresses calculations", null, commandName, "suppress")) {
+			suppress = true;
+		}
+		else if (checker.compare(this.getClass(), "Desuppresses calculations", null, commandName, "desuppress")) {
+			suppress = false;
+			recalculateAllTraceOperators();
+			parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Transfers node values to information associated with nodes of tree", null, commandName, "transferToAssociated")) {
+			String name = parser.getFirstToken(arguments);
+			if (StringUtil.blank(name) && !MesquiteThread.isScripting())
+				name = MesquiteString.queryString(containerOfModule(), "Transfer", "Name of variable to be associated with nodes of tree and to receive transfered node values (e.g., \"GCBias\")", "Untitled");
+			if (!StringUtil.blank(name))
+				transferAllTraceOperators(name);
+		}
+		else if (checker.compare(this.getClass(), "Sets initial horizontal offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetX")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetX = offset;
+
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets initial vertical offset of legend from home position", "[offset in pixels]", commandName, "setInitialOffsetY")) {
+			MesquiteInteger pos = new MesquiteInteger();
+			int offset= MesquiteInteger.fromFirstToken(arguments, pos);
+			if (MesquiteInteger.isCombinable(offset)) {
+				initialOffsetY = offset;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Turns off the values at nodes trace", null, commandName, "closeTrace")) {
+			iQuit();
+			resetContainingMenuBar();
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (employee == numForNodesTask)
+			recalculateAllTraceOperators();
+		resetAllTraceOperators();
+	}
+	/*.................................................................................................................*/
+	public void closeAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ValuesAtNodesOperator) {
+				ValuesAtNodesOperator tCO = (ValuesAtNodesOperator)obj;
+				tCO.turnOff();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void resetAllTraceOperators() {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ValuesAtNodesOperator) {
+				ValuesAtNodesOperator tCO = (ValuesAtNodesOperator)obj;
+				if (tCO.decorator!=null)
+					tCO.decorator.turnOff();
+				tCO.decorator = null;
+				if (tCO.treeDisplay!=null)
+					tCO.treeDisplay.pleaseUpdate(false);
+				//tCO.traceLegend.characterScroll.setMaximumValue(characterSourceTask.getNumberOfCharacters());
+				if (tCO.vLegend!=null)
+					tCO.vLegend.repaint();
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void recalculateAllTraceOperators() {
+		if (traces==null || suppress)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ValuesAtNodesOperator) {
+				ValuesAtNodesOperator tCO = (ValuesAtNodesOperator)obj;
+				tCO.doCalculations();
+				//tCO.traceLegend.characterScroll.setCurrentValue(currentChar);
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void transferAllTraceOperators(String name) {
+		if (traces==null)
+			return;
+		Enumeration e = traces.elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof ValuesAtNodesOperator) {
+				ValuesAtNodesOperator tCO = (ValuesAtNodesOperator)obj;
+				tCO.transferNumbersToAssociated(name);
+				//tCO.traceLegend.characterScroll.setCurrentValue(currentChar);
+			}
+		}
+	}
+
+	/*.................................................................................................................*/
+	public void endJob() {
+		closeAllTraceOperators();
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	/** returns current parameters, for logging etc..*/
+	public String getParameters() {
+		return "Values calculated for nodes: " + numForNodesTask.getName();
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+
+	/*.................................................................................................................*/
+	public boolean showCitation(){
+		return true;
+	}
+}
+
+/* ======================================================================== */
+class ValuesAtNodesOperator extends TreeDisplayDrawnExtra {
+	private Tree myTree;
+	ValuesAtNodes vModule;
+	public TDLegendWithColors vLegend;
+	public TreeDecorator decorator;
+	private boolean holding = false;
+	NumberArray numArray;
+	static Color lilac;
+	static {
+		lilac = new Color(210, 170, 255);
+	}
+	public ValuesAtNodesOperator (ValuesAtNodes ownerModule, TreeDisplay treeDisplay) {
+		super(ownerModule, treeDisplay);
+		vModule = ownerModule;
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree){
+		myTree = tree;
+		if ((vModule.numForNodesTask!=null) && (vModule.displayTask!=null)) {
+			doCalculations();
+		}
+	}
+	/*.................................................................................................................*/
+	public   Tree getTree(){
+		return myTree;
+	}
+	/*.................................................................................................................*/
+	public   Taxa getTaxa(){
+		if (myTree !=null)
+			return myTree.getTaxa();
+		else
+			return null;
+	}
+	public void transferNumbersToAssociated(String name){
+		if (myTree == null || numArray == null) 
+			return;
+		if (myTree instanceof MesquiteTree) {
+			MesquiteTree tree = (MesquiteTree)myTree;
+			NameReference nr = NameReference.getNameReference(name);
+			transfer(tree, tree.getRoot(), numArray, nr);
+			tree.notifyListeners(this, new Notification(MesquiteListener.UNKNOWN));
+		}
+	}
+	/*.................................................................................................................*/
+	public   void transfer(MesquiteTree tree, int node, NumberArray numArray, NameReference nr) {
+		for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d))
+			transfer(tree, d, numArray, nr);
+		if (numArray.getValueClass() == NumberArray.DOUBLE)
+			tree.setAssociatedDouble(nr, node, numArray.getDouble(node));
+		else 
+			tree.setAssociatedLong(nr, node, numArray.getLong(node));
+	}		
+	/*.................................................................................................................*/
+	public void doCalculations() {
+		holding = true;
+		if (myTree == null) {
+			System.out.println("tree null in Values at Nodes calculations");
+		}
+		else {
+
+			vModule.displayTask.onHold();
+			if (vLegend!=null) {
+				vLegend.onHold();
+				vLegend.setTitle(vModule.numForNodesTask.getName());
+			}
+
+			if (numArray == null || numArray.getSize() < myTree.getNumNodeSpaces()) 
+				numArray = new NumberArray(myTree.getNumNodeSpaces());
+			else
+				numArray.deassignArray();
+			vModule.numForNodesTask.calculateNumbers(myTree, numArray, resultString);
+			
+			int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+			if (!myTree.nodeExists(drawnRoot))
+				drawnRoot = myTree.getRoot();
+			if (decorator==null) {
+				decorator = vModule.displayTask.createTreeDecorator(treeDisplay, this);
+				decorator.setThemeColor(lilac);
+			}
+			decorator.calculateOnTree(myTree, drawnRoot, numArray);
+			vModule.displayTask.offHold();
+			holding = false;
+			treeDisplay.pleaseUpdate(false);
+			if (vLegend!=null) {
+				vLegend.offHold();
+				vLegend.repaint();
+			}
+		}
+	}
+	MesquiteString resultString = new MesquiteString();
+
+	String getResultString(){ //not used currently
+		if (StringUtil.blank(resultString.getValue()))
+			return "";
+		else
+			return " [" + resultString + "]";
+	}
+	public void cursorEnterBranch(Tree tree, int N, Graphics g) {
+		if (vLegend!=null)
+			vLegend.setMessage(textAtNode(tree, N));
+	}
+	public void cursorExitBranch(Tree tree, int N, Graphics g) {
+		if (vLegend!=null)
+			vLegend.setMessage("");
+	}
+	/**return a text version of information at node*/
+	public String textAtNode(Tree tree, int node){
+		if (numArray== null)
+			return "?";
+		else {
+			String s = numArray.toString(node);
+			if (StringUtil.blank(s))
+				return "?";
+			else
+				return s;
+		}
+	}
+	/**return a text version of any legends or other explanatory information*/
+	public String textForLegend(){
+		return "Values at nodes: "  + vModule.numForNodesTask.getNameAndParameters();
+	}
+	public String getNote(){
+		return vModule.numForNodesTask.getNameAndParameters();
+	}
+	/*.................................................................................................................*/
+	public   void drawOnTree(Tree tree, int drawnRoot, Graphics g) {
+		boolean toShow = false;
+		if (!holding) {
+			if (vLegend==null) {
+				vLegend = new TDLegendWithColors(vModule, treeDisplay, new ParamString(this), vModule.numForNodesTask.getName(), Color.black);
+				addPanelPlease(vLegend);
+				toShow = true;
+			}
+			//decorator or vLegend being set to null; MUST PROTECT
+			try {
+				if (vModule.numForNodesTask!=null) {
+					if (decorator==null) {
+						decorator = vModule.displayTask.createTreeDecorator(treeDisplay, this); 
+						decorator.setThemeColor(lilac);
+					}
+					decorator.drawOnTree(tree, drawnRoot, numArray, null, null, g);
+					//vLegend.setValues(numArray);
+					vLegend.adjustLocation();
+					vLegend.setColorRecords(decorator.getLegendColorRecords());
+					if (toShow || !vLegend.isVisible())
+						vLegend.setVisible(true);
+				}
+			}
+			catch (Exception e){
+			}
+		}
+	}
+	public   void printOnTree(Tree tree, int drawnRoot, Graphics g) {
+		drawOnTree(tree, drawnRoot, g);
+		//vLegend.print(g);
+	}
+	public void turnOff(){
+		if (vLegend!=null && treeDisplay!=null)
+			removePanelPlease(vLegend);
+		super.turnOff();
+	}
+}
+class ParamString extends MesquiteString {
+	ValuesAtNodesOperator vANO;
+	public ParamString (ValuesAtNodesOperator vANO){
+		super();
+		this.vANO = vANO;
+	}
+	public String getValue(){
+		return vANO.getNote();
+	}
+}
+
+
diff --git a/Source/mesquite/trees/aTreesIntro/aTreesIntro.java b/Source/mesquite/trees/aTreesIntro/aTreesIntro.java
new file mode 100644
index 0000000..4e5456d
--- /dev/null
+++ b/Source/mesquite/trees/aTreesIntro/aTreesIntro.java
@@ -0,0 +1,67 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.aTreesIntro;
+/*~~  */
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.characters.*;
+import mesquite.lib.duties.*;
+
+
+/* ======================================================================== */
+public class aTreesIntro extends PackageIntro {
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+ 		return true;
+  	 }
+  	 public Class getDutyClass(){
+  	 	return aTreesIntro.class;
+  	 }
+	/*.................................................................................................................*/
+    	 public String getExplanation() {
+		return "Basic management and utilities for phylogenetic trees.";
+   	 }
+   
+    	    /*.................................................................................................................*/
+    	    public boolean getHideable() {
+    			return false;
+    	   	 }
+	/*.................................................................................................................*/
+    	 public String getName() {
+		return "Trees Package Introduction";
+   	 }
+	/*.................................................................................................................*/
+	/** Returns the name of the package of modules (e.g., "Basic Mesquite Package", "Rhetenor")*/
+ 	public String getPackageName(){
+ 		return "Trees Package";
+ 	}
+	/*.................................................................................................................*/
+	/** Returns whether package is built-in (comes with default install of Mesquite)*/
+	public boolean isBuiltInPackage(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** Returns citation for a package of modules*
+ 	public String getPackageCitation()
+ 	
+ 	NOT overridden because part of the standard Mesquite packages; hence uses standard Mesquite citation
+	/*.................................................................................................................*/
+	/** Returns whether there is a splash banner*/
+	public boolean hasSplash(){
+ 		return false; 
+	}
+}
+
diff --git a/Source/mesquite/trees/explanation.txt b/Source/mesquite/trees/explanation.txt
new file mode 100644
index 0000000..89d994c
--- /dev/null
+++ b/Source/mesquite/trees/explanation.txt
@@ -0,0 +1,2 @@
+Basic Tree Modules for Mesquite
+One of the core Mesquite packages.  A diverse collection of modules that most calculations concerning trees will need.  Included are modules to manage tree and show the tree window.
diff --git a/Source/mesquite/trees/lib/DrawTreeUtil.java b/Source/mesquite/trees/lib/DrawTreeUtil.java
new file mode 100644
index 0000000..807b83d
--- /dev/null
+++ b/Source/mesquite/trees/lib/DrawTreeUtil.java
@@ -0,0 +1,883 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+
+package mesquite.trees.lib;
+import mesquite.lib.*;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+
+public class DrawTreeUtil {
+
+	private static int getOffset(int width, int edgeWidth) {
+		return (width-edgeWidth)/2;
+	}
+	/*_________________________________________________*/
+	public static void UPdefineDiagonalPoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Nx -= getOffset(width,treeDrawing.getEdgeWidth());
+			mNx -= getOffset(width,treeDrawing.getEdgeWidth());
+			if (internalNode)  {
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+width/2, Ny-width/2);//Ny+width/2 for down
+				poly.addPoint(Nx+width, Ny);
+				poly.addPoint(mNx+width, mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else {
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+width, Ny);
+				poly.addPoint(mNx+width, mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public static void DOWNdefineDiagonalPoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null){
+			Nx -= getOffset(width,treeDrawing.getEdgeWidth());
+			mNx -= getOffset(width,treeDrawing.getEdgeWidth());
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+width/2, Ny+width/2);
+				poly.addPoint(Nx+width, Ny);
+				poly.addPoint(mNx+width, mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+width, Ny);
+				poly.addPoint(mNx+width, mNy);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public static void RIGHTdefineDiagonalPoly(TreeDrawing treeDrawing, Polygon poly,int width, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Ny -= getOffset(width,treeDrawing.getEdgeWidth());
+			mNy -= getOffset(width,treeDrawing.getEdgeWidth());
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx+width/2, Ny+width/2);
+				poly.addPoint(Nx, Ny+width);
+				poly.addPoint(mNx, mNy+width);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx, Ny+width);
+				poly.addPoint(mNx, mNy+width);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public static void LEFTdefineDiagonalPoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean internalNode, int Nx, int Ny, int mNx, int mNy) {
+		if (poly!=null) {
+			Ny -= getOffset(width,treeDrawing.getEdgeWidth());
+			mNy -= getOffset(width,treeDrawing.getEdgeWidth());
+			if (internalNode) 
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx-width/2, Ny+width/2);
+				poly.addPoint(Nx, Ny+width);
+				poly.addPoint(mNx, mNy+width);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=6;
+			}
+			else
+			{
+				poly.npoints=0;
+				poly.addPoint(Nx, Ny);
+				poly.addPoint(Nx, Ny+width);
+				poly.addPoint(mNx, mNy+width);
+				poly.addPoint(mNx, mNy);
+				poly.addPoint(Nx, Ny);
+				poly.npoints=5;
+			}
+		}
+	}
+	/*_________________________________________________*/
+	public static void UPdefineSquarePoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int nShortcut) {
+		Nx -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNx -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNy -= getOffset(width, treeDrawing.getEdgeWidth());
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); //root left
+			poly.addPoint(Nx+width, Ny);	 //root right
+			poly.addPoint(Nx+width, mNy); //subroot right
+			poly.addPoint(Nx, mNy); //subroot let
+			poly.addPoint(Nx, Ny); //return to root left
+			poly.npoints=4;
+		}
+		else if (Nx<mNx) //left leaning (*)
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // daughter left
+			poly.addPoint(Nx+width, Ny);	//daughter right 
+			poly.addPoint(Nx+width, mNy -  nShortcut); //corner right
+			poly.addPoint(mNx+width, mNy); //mother up
+			poly.addPoint(mNx, mNy+width); //mother down
+			poly.addPoint(Nx, mNy+width -  nShortcut); //corner left
+			poly.addPoint(Nx, Ny); //return to daughter left
+			poly.npoints=7;
+		}
+		else //right leaning (*)
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny);// daughter left
+			poly.addPoint(Nx+width, Ny);// daughter right
+			poly.addPoint(Nx+width, mNy+width -  nShortcut);// corner right
+			poly.addPoint(mNx+width, mNy+width); //mother down
+			poly.addPoint(mNx, mNy); //mother up
+			poly.addPoint(Nx, mNy -  nShortcut); //corner left
+			poly.addPoint(Nx, Ny); //return to daughter left
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	//makes polygon counterclockwise
+	public static void DOWNdefineSquarePoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int nShortcut) {
+		Nx -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNx -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNy += getOffset(width, treeDrawing.getEdgeWidth());
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // root right
+			poly.addPoint(Nx+width, Ny);	//root left
+			poly.addPoint(Nx+width, mNy);//subroot left
+			poly.addPoint(Nx, mNy); //subroot right
+			poly.addPoint(Nx, Ny); //return to root right
+			poly.npoints=4;
+		}
+		else if (Nx>mNx) //left leaning
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); //daughter right
+			poly.addPoint(Nx+width, Ny);//daughter left
+			poly.addPoint(Nx+width, mNy-width + nShortcut);//corner left
+			poly.addPoint(mNx+width, mNy-width); //mother down * on x
+			poly.addPoint(mNx, mNy); //mother up 
+			poly.addPoint(Nx, mNy + nShortcut); //corner right
+			poly.addPoint(Nx, Ny); //return to daughter right
+			poly.npoints=7;
+		}
+		else //right leaning
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // daughter right
+			poly.addPoint(Nx+width, Ny);	//daughter left
+			poly.addPoint(Nx+width, mNy + nShortcut);//corner left
+			poly.addPoint(mNx+width, mNy); //mother up * on x
+			poly.addPoint(mNx, mNy-width); //mother down 
+			poly.addPoint(Nx, mNy-width + nShortcut); //corner right
+			poly.addPoint(Nx, Ny); //return to daughter right
+			poly.npoints=7;
+		}
+	}
+	/*_________________________________________________*/
+	//makes polygon clockwise
+	public static void RIGHTdefineSquarePoly(TreeDrawing treeDrawing, Polygon poly, int width, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int nShortcut) {
+		Ny -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNy -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNx += getOffset(width, treeDrawing.getEdgeWidth());
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // root left
+			poly.addPoint(Nx, Ny+width);	//root right
+			poly.addPoint(mNx, Ny+width);//subroot right
+			poly.addPoint(mNx, Ny); //subroot left
+			poly.addPoint(Nx, Ny); //return to root left
+			poly.npoints=4;
+		}
+		else if (Ny<mNy) //leans left
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // daughter left
+			poly.addPoint(Nx, Ny+width);	//daughter right
+			poly.addPoint(mNx + nShortcut, Ny+width);//corner right
+			poly.addPoint(mNx, mNy+width); //mother up * on y
+			poly.addPoint(mNx-width, mNy); //mother down
+			poly.addPoint(mNx-width + nShortcut, Ny); //corner left
+			poly.addPoint(Nx, Ny); //return to daughter left
+			poly.npoints=7;
+		}
+		else
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny);// daughter left
+			poly.addPoint(Nx, Ny+width);//daughter right
+			poly.addPoint(mNx-width + nShortcut, Ny+width);//corner right
+			poly.addPoint(mNx-width, mNy+width); //mother down * on y
+			poly.addPoint(mNx, mNy); //mother up 
+			poly.addPoint(mNx + nShortcut, Ny); //corner left
+			poly.addPoint(Nx, Ny); //return to daughter left
+			poly.npoints=7;
+		}
+
+	}
+	/*_________________________________________________*/
+	//makes polygon counterclockwise
+	public static void LEFTdefineSquarePoly(TreeDrawing treeDrawing,Polygon poly, int width, boolean isRoot, int Nx, int Ny, int mNx, int mNy, int nShortcut) {
+		Ny -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNy -= getOffset(width, treeDrawing.getEdgeWidth());
+		mNx -= getOffset(width, treeDrawing.getEdgeWidth());
+		if (isRoot) {
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // root right
+			poly.addPoint(Nx, Ny+width);	//root left
+			poly.addPoint(mNx, Ny+width);//subroot left
+			poly.addPoint(mNx, Ny); //subroot right
+			poly.addPoint(Nx, Ny); //return to root right
+			poly.npoints=5;
+		}
+		else if (Ny>mNy) //left leaning
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny); // daughter right
+			poly.addPoint(Nx, Ny+width);	//daughter left
+			poly.addPoint(mNx+width -  nShortcut, Ny+width);//corner left  
+			poly.addPoint(mNx+width, mNy+width); //mother down
+			poly.addPoint(mNx, mNy); //mother up
+			poly.addPoint(mNx -  nShortcut, Ny); //corner right
+			poly.addPoint(Nx, Ny); //return to daughter right
+			poly.npoints=7;
+		}
+		else
+		{
+			poly.npoints=0;
+			poly.addPoint(Nx, Ny);// daughter right
+			poly.addPoint(Nx, Ny+width); //daughter left
+			poly.addPoint(mNx -  nShortcut, Ny+width);//corner left
+			poly.addPoint(mNx, mNy+width); //mother up
+			poly.addPoint(mNx+width, mNy);//mother down
+			poly.addPoint(mNx+width -  nShortcut, Ny); //corner right
+			poly.addPoint(Nx, Ny); //return to daughter right
+			poly.npoints=7;
+		}
+	}
+
+	/*_________________________________________________*/
+	public static void drawOneCurvedBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, Graphics g, int node, int start, int width, int adj, boolean emphasizeNodes, Polygon nodePoly, BasicStroke defaultStroke) {
+		if (tree.nodeExists(node)) {
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];
+			boolean done = false;
+			try{
+				if ( g instanceof Graphics2D) {
+					if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+						if (xnM>xN){ //leans left
+							xN += width/2+start;
+							xnM += width/2;
+							ynM += edgewidth - width/2 -start;
+							yN += width/2;
+						}
+						else {
+							if (start>1)
+								start++;
+							xN += width/2+start;
+							xnM += width/2;
+							ynM += width/2 +start;
+							yN += width/2;
+						}
+
+					}
+					else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){ //����
+						if (xnM>xN){ //leans left
+							xN += width/2+start;
+							xnM += width/2;
+							ynM -= edgewidth - width/2 -start;
+							yN -= width/2;
+						}
+						else {
+							if (start>1)
+								start++;
+							xN += width/2+start;
+							xnM += width/2;
+							ynM -= width/2 +start;
+							yN -= width/2;
+						}
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+						if (ynM>yN){ //leans left
+							yN += width/2+start;
+							ynM += width/2;
+							xnM -= edgewidth - width/2 -start;
+							xN -= width/2;
+						}
+						else {
+							if (start>1)
+								start++;
+							yN += width/2+start;
+							ynM += width/2;
+							xnM -= width/2 +start;
+							xN -= width/2;
+						}
+
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){  //����
+						if (ynM>yN){ //leans right
+							yN += width/2+start;
+							ynM += width/2;
+							xnM += edgewidth - width/2 -start;
+							xN += width/2;
+						}
+						else {
+							if (start>1)
+								start++;
+							yN += width/2+start;
+							ynM += width/2;
+							xnM += width/2 +start;
+							xN += width/2;
+						}
+					}
+					Arc2D.Double arc = null;
+					if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+						if (xnM>xN) {  //leans left
+							//g.setColor(Color.blue);
+							arc = new Arc2D.Double(xN, yN-(ynM-yN), (xnM-xN)*2,  (ynM - yN)*2, 180, 90, Arc2D.OPEN); // left
+							//g.drawRect(xN, yN-(ynM-yN), (xnM-xN)*2,  (ynM - yN)*2);
+						}
+						else {
+							//g.setColor(Color.green);
+							arc = new Arc2D.Double(xnM-(xN-xnM), yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2, 0, -90, Arc2D.OPEN); //right
+							//g.drawRect(xnM-(xN-xnM), yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2);
+						}
+					}
+
+					else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){//����
+						if (xnM>xN) {  //leans right
+							//g.setColor(Color.blue);
+							arc = new Arc2D.Double(xN, ynM, (xnM-xN)*2,  -(ynM - yN)*2, 90, 90, Arc2D.OPEN); // left
+							//g.drawRect(xN, yN-(ynM-yN), (xnM-xN)*2,  (ynM - yN)*2);
+						}
+						else {
+							//g.setColor(Color.green);
+							arc = new Arc2D.Double(xnM-(xN-xnM), ynM, (xN-xnM)*2,  -(ynM - yN)*2, 0, 90, Arc2D.OPEN); //right
+							//g.drawRect(xnM-(xN-xnM), yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2);
+						}
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+						if (ynM>yN) { //leans left
+							//g.setColor(Color.blue);
+							arc = new Arc2D.Double(xnM, yN, (xN-xnM)*2,  (ynM - yN)*2, 90, 90, Arc2D.OPEN); // left
+							//g.drawRect(xN, yN-(ynM-yN), (xnM-xN)*2,  (ynM - yN)*2);
+						}
+						else {
+							//g.setColor(Color.green);
+							arc = new Arc2D.Double(xnM, ynM + (ynM - yN), (xN-xnM)*2,  -(ynM - yN)*2, 180,90, Arc2D.OPEN); //right
+							//g.drawRect(xnM-(xN-xnM), yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2);
+						}
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){ //����
+						if (ynM>yN) { //leans right
+							//g.setColor(Color.blue);
+							arc = new Arc2D.Double(xN - (xnM-xN), yN, -(xN-xnM)*2,  (ynM - yN)*2, 0, 90, Arc2D.OPEN); 
+							//g.drawRect(xN, yN-(ynM-yN), (xnM-xN)*2,  (ynM - yN)*2);
+						}
+						else {
+							//g.setColor(Color.green);
+							arc = new Arc2D.Double(xN - (xnM-xN), ynM + (ynM - yN), -(xN-xnM)*2, - (ynM - yN)*2, 0,-90, Arc2D.OPEN); 
+							//g.drawRect(xnM-(xN-xnM), yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2);
+						}
+					}
+					if (arc!=null) {
+						BasicStroke wideStroke = new BasicStroke(width);
+						Graphics2D g2 = (Graphics2D)g;
+						g2.setStroke(wideStroke);
+						g2.draw(arc);
+						done  = true;
+						g2.setStroke(defaultStroke);
+					}
+				}
+
+			}
+			catch (Throwable t){
+			}
+			if (!done){
+				if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+					if (xnM > xN)  ynM += edgewidth-1-start;
+					else ynM+=start;
+				}
+				else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){ //����
+					if (xnM > xN)  ynM -= edgewidth-1-start;
+					else ynM-=start;
+					xnM +=adj; //why this adj is needed, I don't know.  But it seems to work.
+					xN += adj;
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+					if (ynM > yN)  xnM -= edgewidth-1-start;
+					else xnM-=start;
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){  //����
+					if (ynM > yN) xnM += edgewidth-1-start;
+					else xnM+=start;
+					ynM +=adj;//why this adj is needed, I don't know.  But it seems to work.
+					yN += adj;
+				}
+				else
+					System.out.println("Error: wrong tree orientation in Arc Tree");
+				for (int i=0; i<width; i++) {
+					if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+						if (xnM>xN) {
+							g.drawArc(xN + start, yN - (ynM - yN), (xnM-xN)*2,  (ynM - yN)*2, 180, 90); // left
+							ynM--;
+						}
+						else {
+							g.drawArc(xnM-(xN-xnM) + start, yN - (ynM - yN), (xN-xnM)*2,  (ynM - yN)*2, 0, -90); //right
+							ynM++; //** start off -
+
+						}
+						xN++;
+					}
+
+					else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){//����
+						if (xnM>xN) {
+							g.drawArc(xN - start,ynM, (xnM-xN)*2,  (yN -ynM)*2, 90, 90); //right
+							ynM++;
+						}
+						else {
+							g.drawArc(xnM-(xN-xnM) - start,ynM, (xN-xnM)*2,   (yN -ynM)*2, 0, 90); //left 
+							ynM--;  //**start off + edgewidth
+						}
+						xN++;
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+						if (ynM>yN) {
+							g.drawArc(xnM, yN + start, (xN-xnM)*2,  (ynM - yN)*2, 90, 90);  //left
+							xnM++;
+						}
+						else {
+							g.drawArc(xnM,ynM - (yN -ynM) + start, (xN-xnM)*2,  (yN -ynM)*2, 180, 90);  //right 
+							xnM--;  //start off + edgewidth
+						}
+						yN++;
+					}
+					else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){ //����
+						if (ynM>yN) {
+							g.drawArc(xN - (xnM-xN), yN - start, (xnM-xN)*2,  (ynM - yN)*2, 0, 90);  //right
+							xnM--;
+						}
+						else {
+							g.drawArc(xN - (xnM-xN),ynM - (yN -ynM) - start, (xnM-xN)*2,  (yN -ynM)*2, 0, -90);  //left 
+							xnM++;  //start off - edgewidth
+						}
+						yN++;
+					}
+
+				}
+			}
+
+			if (emphasizeNodes && nodePoly!=null) {
+				Color prev = g.getColor();
+				g.setColor(Color.red);//for testing
+				g.fillPolygon(nodePoly);
+				g.setColor(prev);
+			}
+		}
+	}
+
+	/*_________________________________________________*/
+	public static void drawOneSquareLineBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, Graphics g, ColorDistribution colors, int node, float start, float width, int adj, boolean emphasizeNodes, Polygon nodePoly, BasicStroke defaultStroke) {
+		if (width< 0)
+			width = 0;
+		if (tree.nodeExists(node)) {
+			
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];  // y position of mother of node
+			float halfEdge = edgewidth/2;
+			if ( g instanceof Graphics2D) {
+				BasicStroke wideStroke = new BasicStroke(width);
+				Graphics2D g2 = (Graphics2D)g;
+				Stroke stroke = g2.getStroke();
+				g2.setStroke(wideStroke);
+				Shape line;
+				if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+					if (yN!=ynM){
+						line = new Line2D.Double(xN+halfEdge,yN+halfEdge,xN+halfEdge,ynM+halfEdge);
+						g2.draw(line);
+					}
+					line = new Line2D.Double(xN+halfEdge,ynM+halfEdge,xnM+halfEdge,ynM+halfEdge);
+					if (node!=tree.getRoot())
+						g2.draw(line);
+				}
+				else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){ 
+					if (yN!=ynM){
+						line = new Line2D.Double(xN+halfEdge,yN-halfEdge,xN+halfEdge,ynM-halfEdge);
+						g2.draw(line);
+					}
+					line = new Line2D.Double(xN+halfEdge,ynM-halfEdge,xnM+halfEdge,ynM-halfEdge);
+					if (node!=tree.getRoot())
+						g2.draw(line);
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+					if (xN!=xnM){
+						line = new Line2D.Double(xN-halfEdge,yN+halfEdge,xnM-halfEdge,yN+halfEdge);  // draws the horizontal lines
+						g2.draw(line);
+					}
+					line = new Line2D.Double(xnM-halfEdge,yN+halfEdge,xnM-halfEdge,ynM+halfEdge);  // draws the vertical lines
+					if (node!=tree.getRoot())
+						g2.draw(line);
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){  
+					if (xN!=xnM){
+						line = new Line2D.Double(xN+halfEdge,yN+halfEdge,xnM+halfEdge,yN+halfEdge);
+						g2.draw(line);
+					}
+					line = new Line2D.Double(xnM+halfEdge,yN+halfEdge,xnM+halfEdge,ynM+halfEdge);
+					if (node!=tree.getRoot())
+						g2.draw(line);
+				}
+				g2.setStroke(stroke);
+			}
+
+			if (emphasizeNodes && nodePoly!=null) {
+				Color prev = g.getColor();
+				g.setColor(Color.green);//for testing
+				//	g.fillPolygon(nodePoly);
+				g.fillRect(x[node]-1, y[node]-1,2,2);
+				g.setColor(prev);
+			}
+		}
+	}
+
+	/*_________________________________________________*/
+	public static void fillOneSquareLineBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, Graphics g, ColorDistribution colors, int node, float start, float lineWidth, float inset, boolean emphasizeNodes, Polygon nodePoly, BasicStroke defaultStroke) {
+		if (tree.nodeExists(node)) {
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];  // y position of mother of node
+			float xNHor, xnMHor, yNVert;
+			float ynMVert;
+			float halfLine = lineWidth/2;
+			Shape line;
+			if (g instanceof Graphics2D && lineWidth >=0) {
+				BasicStroke wideStroke = new BasicStroke(lineWidth);
+				Graphics2D g2 = (Graphics2D)g;
+				Stroke stroke = g2.getStroke();
+				g2.setStroke(wideStroke);
+				if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+					xNHor = xN+start+halfLine;
+					if (xN>xnM){ // branch going to right
+						ynMVert = ynM+start+halfLine;
+						if (yN!=ynM){
+							line = new Line2D.Double(xNHor,yN+halfLine+inset,xNHor,ynM-halfLine+start);  // draws the vertical lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xNHor,ynMVert,xnM+edgewidth,ynMVert);  // draws the horizontal lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+					else { // branch going to left
+						ynMVert = ynM+edgewidth-start-halfLine;
+						if (yN!=ynM){
+							line = new Line2D.Double(xNHor,yN+halfLine+inset,xNHor,ynMVert);  // draws the vertical lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xNHor,ynMVert,xnM+halfLine,ynMVert);  // draws the horizontal lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+				}
+				else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){ //����
+					xNHor = xN+start+halfLine;
+					if (xN>xnM){ // branch going to right
+						ynMVert = ynM-start-halfLine;
+						if (yN!=ynM){
+							line = new Line2D.Double(xNHor,yN-halfLine-inset,xNHor,ynMVert);  // draws the vertical lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xNHor,ynMVert,xnM+edgewidth,ynMVert);  // draws the horizontal lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+					else { // branch going to left
+						ynMVert = ynM-edgewidth+start+halfLine;
+						if (yN!=ynM){
+							line = new Line2D.Double(xNHor,yN-halfLine-inset,xNHor,ynMVert);  // draws the vertical lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xNHor,ynMVert,xnM+halfLine,ynMVert);  // draws the horizontal lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+					yNVert = yN+start+halfLine;
+					if (yN>ynM){ // branch going down
+						xnMHor = xnM-start-halfLine;
+						if (xN!=xnM){
+							line = new Line2D.Double(xN-halfLine-inset,yNVert,xnMHor,yNVert);  // draws the horizontal lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xnMHor,yNVert,xnMHor,ynM+edgewidth+halfLine-inset);  // draws the vertical lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+					else { // branch going up
+						xnMHor = xnM+start-edgewidth+halfLine;
+						if (xN!=xnM){
+							line = new Line2D.Double(xN-halfLine-inset,yNVert,xnMHor,yNVert);  // draws the horizontal lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xnMHor,yNVert,xnMHor,ynM-halfLine+inset);  // draws the vertical lines
+						if (node!=tree.getRoot())
+							g2.draw(line);
+					}
+				}
+				else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){  //����
+					yNVert = yN+start+halfLine;
+					if (yN>ynM){ // branch going down
+						xnMHor = xnM+start+halfLine;
+						if (xN!=xnM){
+							line = new Line2D.Double(xN+halfLine+1,yNVert,xnMHor,yNVert);  // draws the horizontal lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xnMHor,yNVert,xnMHor,ynM+edgewidth+halfLine-1);  // draws the vertical lines
+						g2.draw(line);
+					}
+					else { // branch going up
+						xnMHor = xnM+edgewidth-start-halfLine;
+						if (xN!=xnM){
+							line = new Line2D.Double(xN+halfLine+inset,yNVert,xnMHor,yNVert);  // draws the horizontal lines
+							g2.draw(line);
+						}
+						line = new Line2D.Double(xnMHor,yNVert,xnMHor,ynM-halfLine+inset);  // draws the vertical lines
+						g2.draw(line);
+					}
+				}
+				g2.setStroke(stroke);
+			}
+
+			if (emphasizeNodes && nodePoly!=null) {
+				Color prev = g.getColor();
+				g.setColor(Color.green);//for testing
+				//	g.fillPolygon(nodePoly);
+				g.fillRect(x[node]-1, y[node]-1,2,2);
+				g.setColor(prev);
+			}
+		}
+	}
+
+
+	/*_________________________________________________*/
+	public static boolean inSquareLineBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, int taxonSpacing, Tree tree, int node, int h, int v) {
+		if (tree.nodeExists(node)) {
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];
+			int halfEdgewidth = edgewidth/2;
+			int nearby = 4;
+			int halfTaxonSpacing = taxonSpacing/2 -4;
+			if (nearby> halfTaxonSpacing) nearby = halfTaxonSpacing;
+			if (nearby< 1) nearby = 1;
+
+			if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+				if ((h>=xN-nearby) && (h<=xN+edgewidth+nearby) && (v>=yN) && (v<=ynM))  //with vertical part of branch
+					return true;
+				if (xnM>xN) {  // mother is to the right of node
+					if ((h>=xN) && (h<=xnM) && (v>=ynM-halfEdgewidth-nearby) && (v<=ynM+halfEdgewidth+nearby))  //with horizontal part of branch
+						return true;
+				}
+				else {
+					if ((h>=xnM) && (h<=xN) && (v>=ynM-halfEdgewidth-nearby) && (v<=ynM+halfEdgewidth+nearby))  //with horizontal part of branch
+						return true;
+				}
+			}
+
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+				if ((h>=xN-nearby) && (h<=xN+edgewidth+nearby) && (v>=ynM) && (v<=yN))  //with vertical part of branch
+					return true;
+				if (xnM>xN) {  // mother is to the right of node
+					if ((h>=xN) && (h<=xnM) && (v>=ynM-halfEdgewidth-nearby) && (v<=ynM+halfEdgewidth+nearby))  //with horizontal part of branch
+						return true;
+				}
+				else {
+					if ((h>=xnM) && (h<=xN) && (v>=ynM-halfEdgewidth-nearby) && (v<=ynM+halfEdgewidth+nearby))  //with horizontal part of branch
+						return true;
+				}
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+				if ((v>=yN-nearby) && (v<=yN+edgewidth+nearby) && (h>=xnM) && (h<=xN))  //with horizontal part of branch
+					return true;
+				if (ynM>yN) {  // mother is below node
+					if ((v>=yN) && (v<=ynM) && (h>=xnM-halfEdgewidth-nearby) && (h<=xnM+halfEdgewidth+nearby))  //with vertical part of branch
+						return true;
+				}
+				else {
+					if ((v>=ynM) && (v<=yN) && (h>=xnM-halfEdgewidth-nearby) && (h<=xnM+halfEdgewidth+nearby))  //with vertical part of branch
+						return true;
+				}
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){ 
+				if ((v>=yN-nearby) && (v<=yN+edgewidth+nearby) && (h>=xN) && (h<=xnM))  //with horizontal part of branch
+					return true;
+				if (ynM>yN) { // mother is below node
+					if ((v>=yN) && (v<=ynM) && (h>=xnM-halfEdgewidth-nearby) && (h<=xnM+halfEdgewidth+nearby))  //with vertical part of branch
+						return true;
+				}
+				else {
+					if ((v>=ynM) && (v<=yN) && (h>=xnM-halfEdgewidth-nearby) && (h<=xnM+halfEdgewidth+nearby))  //with vertical part of branch
+						return true;
+				}
+			}
+
+		}
+		return false;
+	}
+
+
+
+
+	/*_________________________________________________*/
+	public static boolean inBranch(TreeDisplay treeDisplay, int[] x, int[] y, int edgewidth, Tree tree, int node, int h, int v) {
+		if (tree.nodeExists(node)) {
+			int nM = tree.motherOfNode(node);
+			int xN=x[node];
+			int xnM = x[nM];
+			int yN =y[node];
+			int ynM = y[nM];
+			double centerX, centerY,axisX, axisY;
+			centerX =  centerY =  axisX =   axisY =0;
+
+			if (treeDisplay.getOrientation()==TreeDisplay.UP) {
+				if (xnM>xN) {
+					if (h< xN || h>xnM)
+						return false;
+					centerX = xnM;
+					centerY = yN;
+					axisX =  xnM-xN;
+					axisY =ynM + edgewidth - yN;
+				}
+				else {
+					if (h< xnM || h>xN+ edgewidth)
+						return false;
+					centerX = xnM;
+					centerY = yN;
+					axisX =  xN-xnM+ edgewidth;
+					axisY =ynM + edgewidth - yN;
+				}
+				if (v < yN || v> ynM + edgewidth)
+					return false;
+			}
+
+			else if (treeDisplay.getOrientation()==TreeDisplay.DOWN){
+				if (xnM>xN) {
+					if (h< xN || h>xnM)
+						return false;
+					centerX = xnM;
+					centerY = yN;
+					axisX =  xnM-xN;
+					axisY =yN - ynM + edgewidth;
+				}
+				else {
+					if (h< xnM || h>xN+ edgewidth)
+						return false;
+					centerX = xnM;
+					centerY = yN;
+					axisX =  xN-xnM+ edgewidth;
+					axisY =yN - ynM + edgewidth;
+				}
+				if (v < ynM || v> yN)
+					return false;
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.RIGHT) {
+				if (ynM>yN) {
+					if (v< yN || v>ynM)
+						return false;
+					centerX = xN;
+					centerY = ynM;
+					axisX =  xN-xnM+ edgewidth;
+					axisY =ynM - yN;
+				}
+				else {
+					if (v< ynM || v>yN+ edgewidth)
+						return false;
+					centerX = xN;
+					centerY = ynM;
+					axisX =  xN-xnM+ edgewidth;
+					axisY =yN - ynM+ edgewidth;
+				}
+				if (h < xnM-edgewidth || h> xN)
+					return false;
+			}
+			else  if (treeDisplay.getOrientation()==TreeDisplay.LEFT){ 
+				if (ynM>yN) {
+					if (v< yN- edgewidth || v>ynM)
+						return false;
+					centerX = xN;
+					centerY = ynM;
+					axisX =  xnM-xN+ edgewidth;
+					axisY =ynM - yN+ edgewidth;
+				}
+				else {
+					if (v< ynM || v>yN)
+						return false;
+					centerX = xN;
+					centerY = ynM;
+					axisX =  xnM-xN+ edgewidth;
+					axisY =yN - ynM;
+				}
+				if (h < xN || h> xnM+ edgewidth)
+					return false;
+			}
+
+			if ((h-centerX)*(h-centerX)/(axisX*axisX) + (v-centerY)*(v-centerY)/(axisY*axisY) <= 1.0)  //inside outer edge
+				if ((h-centerX)*(h-centerX)/((axisX-edgewidth)*(axisX-edgewidth)) + (v-centerY)*(v-centerY)/((axisY-edgewidth)*(axisY-edgewidth)) > 1.0){ //outside inner edge
+					return true;
+				}
+		}
+		return false;
+	}
+
+
+
+}
diff --git a/Source/mesquite/trees/lib/ManyTreesFromFileLib.java b/Source/mesquite/trees/lib/ManyTreesFromFileLib.java
new file mode 100644
index 0000000..b3b570a
--- /dev/null
+++ b/Source/mesquite/trees/lib/ManyTreesFromFileLib.java
@@ -0,0 +1,1064 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.lib;
+/*~~  */
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+
+/** Supplies trees from tree blocks in a file.  Reads trees only when needed; hence suitable for files with too many trees to be held in memory at once, but slower than StoredTrees.*/
+public abstract class ManyTreesFromFileLib extends TreeSource implements MesquiteListener, PathHolder {
+	int currentTree=0;
+	Taxa preferredTaxa =null;
+	Taxa savedTaxa = null;
+	Taxa taxaInBlock = null;
+	TreesManager manager;
+	MesquiteFile file = null;
+	TreeVector trees = null;
+	Vector filePosVector;
+	int arraySize = 1000;
+	int highestTreeMarked = -1;
+	int lastTreeRead = -1;
+	String currentTreeName = null;
+	int numTrees = MesquiteInteger.finite;
+	int highestSuccessfulTree = -1;
+	FIleCheckThread fileCheckingThread = null;
+	protected MesquiteBoolean rereadWholeFileIfGrows = new MesquiteBoolean(true);
+	protected MesquiteBoolean live;
+	MesquiteCommand fileGrewCommand, fileChangedCommand;
+	boolean fileWasModified = false;
+	static MesquiteBoolean warningGiven = new MesquiteBoolean(false);
+	protected int numTreesInTreeBlock = 0;
+	protected Bits treesToSample = new Bits(0);
+	protected boolean sampleTrees = true;
+	protected int numTreesToSample = MesquiteInteger.unassigned;
+	protected int numStartTreesToIgnore = 0;
+	/*NOTE: 
+	 * -- to ask that it remains open even when finding the fail has failed, pass "remain" as the second token in arguments at hiring and in command setFilePath
+	 * -- to ask this to use not the  taxon names, but standardized taxon names (t0, t1, t2, ...) pass "useStandardizedTaxonNames" as the third token in arguments at hiring and in command setFilePath
+	 * -- to tell it what taxa block to use (because if may not be apparent if using the standardized taxon names) pass taxa block in initialize
+	 * */
+	/*.................................................................................................................*/
+	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
+		loadPreferences();
+		if (!MesquiteThread.isScripting()){
+			if (!warningGiven.getValue() && getHiredAs()==TreeSource.class){
+				alert("If you are using the function \"" + getName() + "\" as a Source of Trees for a tree window or a chart, you should be aware that it does not import the trees from the separate file into the current data file.  " + 
+						"It merely reads the trees temporarily for use by the tree window or chart.  If you want to import the trees into the data file, use Import File With Trees (from the Taxa & Trees menu) or Include File (from the File menu).");
+				warningGiven.setValue(true);
+				storePreferences();
+			}
+		}
+		filePosVector = new Vector();
+		fileGrewCommand = new MesquiteCommand("fileGrew", this);
+		fileChangedCommand = new MesquiteCommand("fileChanged", this);
+		fileCheckingThread = new FIleCheckThread(this);
+/*TODO hiring of TreesManager previously occurred after the succeeding conditional which called obtainFile() 
+ * and processFile() (it is commented out below in its original position).  The latter method called 
+ * processTreeBlock(), which requires a non-null manager. oliver*/
+		manager = (TreesManager)findElementManager(TreeVector.class);
+		if (manager == null)
+			return sorry("Tree manager not found.");
+		if (!MesquiteThread.isScripting()){
+			if (!obtainFile(arguments)){
+				return sorry("No tree file was obtained.");
+			}
+			if (!processFile())				
+				return sorry("The file could not be processed.");
+		}
+//		manager = (TreesManager)findElementManager(TreeVector.class);
+//		if (manager == null)
+//			return sorry("Tree manager not found.");
+		return additionStartJobItems();
+	}
+
+	/*.................................................................................................................*/
+	public void processSingleXMLPreference (String tag, String content) {
+		if ("warningGiven".equalsIgnoreCase(tag)) {
+			warningGiven.setValue(content);
+		}
+	}
+	/*.................................................................................................................*/
+	public String preparePreferencesForXML () {
+		StringBuffer buffer = new StringBuffer(200);
+		StringUtil.appendXMLTag(buffer, 2, "warningGiven", warningGiven);  
+		return buffer.toString();
+	}
+
+	/*.................................................................................................................*/
+	protected boolean additionStartJobItems(){
+		addMenuItem("File for \"Use Trees from Separate File\"...", makeCommand("setFilePath",  this));
+		live = new MesquiteBoolean(canDoLiveUpdate());
+		addCheckMenuItem( null, "Respond to Tree File Changes", makeCommand("toggleLive",  this), live);
+		addCheckMenuItem( null, "Reread Whole File If Enlarged", makeCommand("toggleReread",  this), rereadWholeFileIfGrows);
+		return true;
+	}
+	/*.................................................................................................................*/
+	protected boolean canIgnoreStartTrees(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	protected boolean getSampleTrees(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	protected boolean canDoLiveUpdate(){
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	protected void setTreesToSample(int numTreesToSample) {
+		int availableTrees = numTreesInTreeBlock - numStartTreesToIgnore;
+		if (!MesquiteInteger.isCombinable(numTreesToSample)|| numTreesToSample>= availableTrees) {
+			treesToSample.setAllBits();
+			for (int i = 0; i<numStartTreesToIgnore; i++) {  //unset all of the initial ones (e.g., burnin ones)
+				treesToSample.setBit(i, false);
+			}
+		}
+		else {
+			Random rng = new Random(System.currentTimeMillis());
+
+			if (numTreesToSample<=availableTrees/2) {   // we set less than half
+				treesToSample.clearAllBits();
+				for (int i = 0; i<numTreesToSample; i++) {
+					int candidate=-1;
+					while (candidate<0 || treesToSample.isBitOn(candidate+numStartTreesToIgnore))
+						candidate = (int)(rng.nextDouble()*availableTrees);
+					treesToSample.setBit(candidate+numStartTreesToIgnore);
+				}
+			}
+			else {  //we set more than half; therefore, set them all, then unset the need amount
+				treesToSample.setAllBits();
+				for (int i = 0; i<numStartTreesToIgnore; i++) {  //unset all of the initial ones (e.g., burnin ones)
+					treesToSample.setBit(i, false);
+				}
+				int numTreesToUnSet = availableTrees -  - numTreesToSample;
+				for (int i = 0; i<numTreesToUnSet; i++) {
+					int candidate=-1;
+					while (candidate<0 || !treesToSample.isBitOn(candidate+numStartTreesToIgnore))
+						candidate = (int)(rng.nextDouble()*availableTrees);
+					treesToSample.setBit(candidate+numStartTreesToIgnore, false);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	protected String reportTreesSampled(){
+		StringBuffer sb = new StringBuffer(100);
+		int availableTrees = numTreesInTreeBlock - numStartTreesToIgnore;
+		if (!getSampleTrees()){
+			if (MesquiteInteger.isCombinable(numTrees))
+				sb.append("" + numTrees + " trees.");
+		}
+		else if (!MesquiteInteger.isCombinable(numTreesToSample)|| numTreesToSample>= availableTrees) {
+			sb.append("All " + availableTrees + " trees sampled.");
+		}
+		else {
+			sb.append("Trees sampled: \n");
+			int count = 1;
+			for (int i = 0; i<numTreesInTreeBlock; i++) {
+				if (treesToSample.isBitOn(i)) {
+					sb.append("  " + (i+1));
+					if (count % 10 == 0)
+						sb.append("\n");
+					count++;
+				}
+			}
+			count--;
+			sb.append("\n(" + count + " trees total)");
+
+		}
+		return sb.toString();
+	}
+	/*.................................................................................................................*/
+	private int nextTreeToSample(int prevTree) {
+		if (getSampleTrees()) {
+			for (int i=prevTree+1; i<=numTreesInTreeBlock; i++) {
+				if (treesToSample.isBitOn(i))
+					return i;
+			}
+			return MesquiteInteger.unassigned;
+		}
+		return prevTree++;
+	}
+	/*.................................................................................................................*/
+	private int findTreeNumber(int treeNum) {
+		if (getSampleTrees()) {
+			int count=0;
+			for (int i=0; i<=numTreesInTreeBlock; i++) {
+				if (treesToSample.isBitOn(i)) {
+					if (count==treeNum) 
+						return i;
+					count++;
+				}
+			}
+			return MesquiteInteger.unassigned;
+		}
+		return treeNum;
+	}
+	boolean fileReady = false;
+	/*.................................................................................................................*/
+	private boolean obtainFile(String arguments){
+		fileReady = false;
+		if (ended){
+			discreetAlert("WARNING:  Attempt to use module that has ended");
+		}
+		FileCoordinator fCoord = getFileCoordinator();
+		if (fCoord == null)
+			return false;
+
+		for (int j = 0; j<filePosVector.size(); j++){
+			long[] filePosTrees = (long[])filePosVector.elementAt(j);
+
+			for (int i=0; i<arraySize; i++)
+				filePosTrees[i] = MesquiteLong.unassigned;
+		}
+		currentTree=0;
+		highestTreeMarked = -1;
+		lastTreeRead = -1;
+		taxaInBlock = null;
+		numTrees = MesquiteInteger.finite;
+		highestSuccessfulTree = -1;
+
+		MesquiteFile treeFile = fCoord.getNEXUSFileForReading(arguments, "Choose Tree File");
+		if (treeFile != null) {
+			if (file !=null) {
+				file.closeReading();
+				file.dispose();
+				if (trees !=null) {
+					trees.dispose();
+					trees = null;
+				}
+			}
+			file = treeFile;
+			String p = parser.getTokenNumber(arguments, 3);
+			file.useStandardizedTaxonNames = p!= null && p.equalsIgnoreCase("useStandardizedTaxonNames");
+			fileCheckingThread.setPath(file.getPath());
+		}
+		else
+			return false;
+		return true;
+	}
+	public String getFilePath(){
+		return file.getPath();
+	}
+	private boolean getFileFromPath(String pathName){
+		if (pathName.indexOf(MesquiteFile.fileSeparator)<0) {
+			file =MesquiteFile.open(getProject().getHomeDirectoryName(), pathName);
+		}
+		else {
+			String dirName = StringUtil.getAllButLastItem(pathName, MesquiteFile.fileSeparator, "/") + MesquiteFile.fileSeparator;
+			String fileName = StringUtil.getLastItem(pathName, MesquiteFile.fileSeparator, "/");
+			file =MesquiteFile.open(dirName, fileName);
+		}
+		return (file != null);
+	}
+	private boolean processFile(){
+		if (!goToTreeBlock(file))  	 		
+			return false;
+		if (!processTreeBlock())
+			return false;
+		fileReady = true;
+		return true;
+	}
+	boolean ended = false;
+	/*.................................................................................................................*/
+	public void endJob(){
+		if (file !=null){
+			file.closeReading();
+			file.dispose();
+		}
+		fileCheckingThread.abort = true;
+		fileCheckingThread.interrupt();
+		ended = true;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (this.file == null)
+			return null;
+		Snapshot temp = new Snapshot();
+		String arguments = StringUtil.tokenize(MesquiteFile.decomposePath(getProject().getHomeFile().getDirectoryName(), this.file.getPath())) + " remain ";
+		if (this.file.useStandardizedTaxonNames)
+			arguments += " useStandardizedTaxonNames";
+		temp.addLine("setFilePath " + arguments);  //quote //todo: should parse name relative to path to home file!!!!!
+		temp.addLine("toggleReread " + rereadWholeFileIfGrows.toOffOnString());
+		if (canDoLiveUpdate())
+			temp.addLine("toggleLive " + live.toOffOnString());
+		additionalSnapshot(temp);
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public void additionalSnapshot(Snapshot snapshot) {
+	}	
+	/*.................................................................................................................*/
+	MesquiteInteger pos = new MesquiteInteger(0);
+	/*.................................................................................................................*/
+	public boolean additionalDoCommands(String commandName, String arguments, CommandChecker checker) {
+		return false;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Specifies the tree file to use", "[path to file]", commandName, "setFilePath")) {
+			String path = parser.getFirstToken(arguments);
+			if (obtainFile(arguments)){
+				if (processFile()){
+					if (!MesquiteThread.isScripting())
+						parametersChanged();
+					return null;
+				}
+				else
+					discreetAlert( "File could not be processed for " + getName() + " (path " + path + ")");
+			}
+			else 
+				discreetAlert( "File was not obtained for " + getName() + " (path " + path + ")");
+			if (!("remain".equalsIgnoreCase(parser.getNextToken())))
+				iQuit();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to reread the whole file if the file enlarges", "[on or off]", commandName, "toggleReread")) {
+			boolean current = rereadWholeFileIfGrows.getValue();
+			rereadWholeFileIfGrows.toggleValue(parser.getFirstToken(arguments));
+			if (current!=rereadWholeFileIfGrows.getValue() && !MesquiteThread.isScripting())
+				parametersChanged();
+		}
+		else if (checker.compare(this.getClass(), "Sets whether or not to listen to changes in the file", "[on or off]", commandName, "toggleLive")) {
+			if (canDoLiveUpdate()) {
+				boolean current = live.getValue();
+				live.toggleValue(parser.getFirstToken(arguments));
+				if (current!=live.getValue()){
+					if (fileWasModified)
+						fileModified(-1);
+					else
+						parametersChanged();
+				}
+			}
+		}
+		else if (checker.compare(this.getClass(), "Uses quite mode (no proress indicator, few messages)", null, commandName, "quietOperation")) {
+			quietOperation = true;
+		}
+		else if (checker.compare(this.getClass(), "Receives message that file changed", null, commandName, "fileChanged")) {
+			numTrees = MesquiteInteger.finite;
+			parametersChanged();
+
+		}
+		else if (checker.compare(this.getClass(), "Receives message that file grew", null, commandName, "fileGrew")) {
+			int s = MesquiteInteger.fromString(arguments, new MesquiteInteger(0));
+			parametersChanged(new Notification(MesquiteListener.ITEMS_ADDED, new int[]{s, MesquiteInteger.finite }));
+
+		}
+		else if (additionalDoCommands(commandName, arguments, checker))
+			return  null;
+		else
+			super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	boolean quietOperation = false;
+	/*.................................................................................................................*/
+	/** finds the ith block of a given type and returns it raw.*/
+	private boolean goToTreeBlock(MesquiteFile mNF){
+		ProgressIndicator progIndicator = null;
+		if (!quietOperation){
+			progIndicator =  new ProgressIndicator(getProject(),"Processing File "+ mNF.getName() + " to find tree block", mNF.existingLength());
+			progIndicator.start();
+		}
+		boolean found = false;
+		if (mNF.openReading()) {
+			try {
+				//	long blockStart = 0;
+				if (!quietOperation)
+					logln("Processing File "+ mNF.getName() + " to find tree block");
+				String token= mNF.firstToken(null);
+				MesquiteLong startPos = new MesquiteLong();
+				if (token!=null) {
+					if (!token.equalsIgnoreCase("#NEXUS")) {
+						discreetAlert("Not a valid NEXUS file (first token is \"" + token + "\"");
+					}
+					else {
+						String name = null;
+						//blockStart = -1;
+						//blockStart = mNF.getFilePosition();
+						while (!found && (name = mNF.goToNextBlockStart(startPos ))!=null) {
+							if ("TREES".equalsIgnoreCase(name)){
+								found = true;
+
+								mNF.goToFilePosition(startPos.getValue()-1); //go back to start of trees block
+							}
+							else if ("TAXA".equalsIgnoreCase(name) || "DATA".equalsIgnoreCase(name)){
+								if (progIndicator!=null)
+									progIndicator.goAway();
+								if (!MesquiteThread.isScripting() && !AlertDialog.query(containerOfModule(), "Use File?",  "Tree file contains a TAXA or DATA block.  " + 
+										"If the TREES block has no translation table, and if the order of taxa is different in this file than in your current project in Mesquite, " +
+										"then the trees may be misread.  Do you want to open this file anyway?"))
+								return false;
+							}
+							//else
+							//	blockStart = mNF.getFilePosition()+1;
+						}
+						if (progIndicator!=null)
+							progIndicator.goAway();
+						if (found && !quietOperation)
+							logln("Tree block found");
+					}
+				}
+			}
+			catch (MesquiteException e){
+				if (progIndicator!=null)
+					progIndicator.goAway();
+				return false;
+			}
+		}
+		else {
+			if (progIndicator!=null)
+				progIndicator.goAway();
+			return false;
+		}
+		if (progIndicator!=null)
+			progIndicator.goAway();
+		return found;
+	}
+	/*.................................................................................................................*/
+	private boolean processTreeBlock(){
+
+		Parser commandParser = new Parser();
+
+		MesquiteInteger cPos = new MesquiteInteger(0);
+		MesquiteString comment = new MesquiteString();
+		String s;
+		int treeNum=0;
+		if (getProject().getNumberTaxas()==1)
+			taxaInBlock = getProject().getTaxa(0); //as default)
+		trees = new TreeVector(taxaInBlock);
+		trees.setTaxa(taxaInBlock);
+		trees.setName("Trees from \"" + file.getName() + "\"");
+		boolean nameSet = false;
+		MesquiteInteger status = new MesquiteInteger(0);
+		ProgressIndicator surveyTreesIndicator=null;
+
+		if (getSampleTrees()) {
+			surveyTreesIndicator =  new ProgressIndicator(getProject(),"Processing File "+ file.getName() + " to survey trees", file.existingLength());
+			surveyTreesIndicator.start();
+			//	surveyTreesIndicator.startTimer();
+		}
+		boolean treesEncountered=false;
+
+		file.goToFilePosition(file.getFilePosition()-1);  //needed because of where file pos last left
+		if (file.getFilePosition()<0)
+			return false;
+		recordFilePos(0, file.getFilePosition()); 
+		boolean translationTableRead = false;
+		// if sampling trees, we don't ask for the entire command if trees have already been found in the Trees block.  
+		// This is dangerous, as it means that this may not work if TREE commands are intermingled with other relevant commands!
+
+		while (!StringUtil.blank(s=file.getNextCommand(status, null, !(getSampleTrees()&&treesEncountered)))) {
+
+			if (status.getValue() == 2) { //end of block reached
+				numTreesInTreeBlock = treeNum;
+				if (getSampleTrees() && treesToSample!=null) {
+					treesToSample.resetSize(numTreesInTreeBlock);
+					if (MesquiteInteger.isCombinable(numTreesToSample))
+						setTreesToSample(numTreesToSample);
+				}
+				if (surveyTreesIndicator!=null)
+					surveyTreesIndicator.goAway();
+				return true;
+			}
+			String punc = ",";
+			String commandName = parser.getFirstToken(s);
+
+			if (commandName.equalsIgnoreCase("TREE") || commandName.equalsIgnoreCase("UTREE") || commandName.equalsIgnoreCase("RTREE"))  {
+				treesEncountered=true;
+				if (getSampleTrees()) {
+					if (surveyTreesIndicator != null) {
+						if (surveyTreesIndicator.isAborted()) {
+							int response = AlertDialog.query(containerOfModule(), "Continue with tree file processing?", "Continue with tree file processing?", "Continue", "Use Only Trees Processed", "Cancel", 1);
+							if (response==2) {
+								numTreesInTreeBlock = treeNum;
+								if (treesToSample!=null) {
+									treesToSample.resetSize(numTreesInTreeBlock);
+									if (MesquiteInteger.isCombinable(numTreesToSample))
+										setTreesToSample(numTreesToSample);
+								}
+								surveyTreesIndicator.goAway();
+								return true;
+							}
+							else if (response==3) {
+								surveyTreesIndicator.goAway();
+								return true;
+							}
+						}
+						if (treeNum % 50 == 0) {
+							surveyTreesIndicator.setText("Counting trees in file " + treeNum);
+							surveyTreesIndicator.setCurrentValue(file.getFilePosition());
+						}
+					}
+					recordFilePos(treeNum+1, file.getFilePosition());
+					treeNum++;
+				}
+				else {
+					recordFilePos(treeNum+1, file.getFilePosition());
+
+					return true;
+				}
+			}
+			else if (commandName.equalsIgnoreCase("BEGIN")) {
+				treesEncountered=false;
+				recordFilePos(0, file.getFilePosition() + 1); 
+			}
+			else if (commandName.equalsIgnoreCase("END")  || commandName.equalsIgnoreCase("ENDBLOCK")) {
+				//ignoring these
+			}
+			else if (commandName.equalsIgnoreCase("TRANSLATE")) {
+				if (treesEncountered && getSampleTrees())
+					MesquiteMessage.println("Warning: TRANSLATE command encountered after trees were found in TREES block; there may be a problem with processing this file");
+				Vector table = null;
+				translationTableRead = true;
+				if (taxaInBlock == null)
+					table = new Vector();
+				String label =  parser.getNextToken();
+				while (punc !=null && !punc.equalsIgnoreCase(";")) {
+					String taxonName = parser.getNextToken();
+					if (file.useStandardizedTaxonNames){
+						if (taxaInBlock == null)
+							taxaInBlock = savedTaxa;
+						String numS = null;
+						if (taxonName != null)
+							numS = taxonName.substring(1, taxonName.length());
+						int it = MesquiteInteger.fromString(numS);
+						if (MesquiteInteger.isCombinable(it))
+							taxonName = taxaInBlock.getTaxonName(it);
+					}
+					if (taxaInBlock==null) 
+						table.addElement(StringUtil.tokenize(taxonName) + " " + StringUtil.tokenize(label));
+					else
+						trees.setTranslationLabel(label, taxonName, false);
+					punc =  parser.getNextToken(); 
+					if (punc !=null && !punc.equals(";")) {
+						label =  parser.getNextToken();
+						if (";".equalsIgnoreCase(label))
+							punc = label;  //to pop out of loop
+					}
+				}
+
+				if (taxaInBlock==null) {
+					taxaInBlock = manager.findTaxaMatchingTable(trees, getProject(), file, table);
+					if (taxaInBlock!=null) {
+						trees.setTaxa(taxaInBlock);
+						trees.setTranslationTable(table);
+					}
+					else  {
+						String st = "FAILED.";
+						discreetAlert( st);
+					}
+
+				}
+				else {
+					if (table!=null)
+						trees.setTranslationTable(table);
+				}
+				trees.checkTranslationTable();
+				recordFilePos(0, file.getFilePosition()); 
+			}
+			else if (commandName.equalsIgnoreCase("TITLE")) {
+				if (treesEncountered && getSampleTrees())
+					MesquiteMessage.println("Warning: TITLE command encountered after trees were found in TREES block; there may be a problem with processing this file");
+				trees.setName(parser.getTokenNumber(2));
+				nameSet = true;
+				recordFilePos(0, file.getFilePosition()); 
+			}
+			else if (commandName.equalsIgnoreCase("LINK")) {
+				if (treesEncountered && getSampleTrees())
+					MesquiteMessage.println("Warning: LINK command encountered after trees were found in TREES block; there may be a problem with processing this file");
+				if ("taxa".equalsIgnoreCase(parser.getTokenNumber(2))) {
+					String taxaTitle = parser.getTokenNumber(4);
+					taxaInBlock = getProject().getTaxa(file, taxaTitle);
+					if (taxaInBlock == null)
+						taxaInBlock = getProject().getTaxaLastFirst(taxaTitle);
+					if (taxaInBlock == null) {
+						if (getProject().getNumberTaxas(file)==1) //if translation table should search for match
+							taxaInBlock = getProject().getTaxa(file, 0);
+						else if (getProject().getNumberTaxas(file)==0 && getProject().getNumberTaxas()==1) //if translation table should search for match
+							taxaInBlock = getProject().getTaxa(0);
+						else
+							discreetAlert( "Taxa block not found for tree block");
+					}
+					trees.setTaxa(taxaInBlock);
+					if (!nameSet)
+						trees.setName("Trees block from " + file.getName());
+				}
+				recordFilePos(0, file.getFilePosition()); 
+			}
+			else if (!treesEncountered)
+				recordFilePos(0, file.getFilePosition()); 
+		}
+		if (!translationTableRead && file.useStandardizedTaxonNames){
+			if (taxaInBlock == null)
+				taxaInBlock = savedTaxa;
+			for (int it = 0; it<taxaInBlock.getNumTaxa(); it++)
+				trees.setTranslationLabel(Integer.toString(it+1), "t" + it, false);
+			trees.checkTranslationTable();
+		}
+		numTreesInTreeBlock = treeNum;
+		if (getSampleTrees()) {
+			if (surveyTreesIndicator!=null)
+				surveyTreesIndicator.goAway();
+		}
+		if (getSampleTrees() && treesToSample!=null) {
+			treesToSample.resetSize(numTreesInTreeBlock);
+			setTreesToSample(numTreesToSample);
+		}
+		return true;
+	}
+	/*.................................................................................................................*/
+	/* Note: this returns a file position only if the tree index is within the range in the file AND the tree reading has already passed
+	that point.  It does not force a scan to find that tree if file reading has yet to proceed that far */
+	public long getFilePos(int iTree){
+		if (!MesquiteInteger.isCombinable(iTree))
+			return MesquiteLong.unassigned;
+		if (!posExists(iTree)) {
+			if (!quietOperation)
+				MesquiteMessage.warnProgrammer("NO POS RECORDED in " + getName() + " ( tree " + iTree + ")");
+			return MesquiteLong.unassigned;
+		}
+		int vec = iTree / arraySize;
+		int loc = iTree % arraySize;
+		long[] filePosTrees = (long[])filePosVector.elementAt(vec);
+		if (loc <0 || loc > filePosTrees.length)
+			return -1;
+		return filePosTrees[loc];
+	}
+	boolean posExists(int iTree){
+		return (iTree < arraySize*filePosVector.size()) ;
+	}
+	/*.................................................................................................................*/
+	void recordFilePos(int iTree, long pos){
+		if (pos<0 || pos > 100000000000L) {
+			if (!quietOperation)
+				MesquiteMessage.warnProgrammer("illegal file pos in " + getName());
+			return;
+		}
+		long[] filePosTrees;
+		while (!posExists(iTree)) {
+			filePosTrees = new long[arraySize];
+			for (int i=0; i<arraySize; i++)
+				filePosTrees[i] = MesquiteLong.unassigned;
+			filePosVector.addElement(filePosTrees);
+		}
+		int vec = iTree / arraySize;
+		int loc = iTree % arraySize;
+		filePosTrees = (long[])filePosVector.elementAt(vec);
+		filePosTrees[loc] = pos-1; //-1 to ensure not too far
+		if (iTree > highestTreeMarked)
+			highestTreeMarked = iTree;
+	}
+	/*.................................................................................................................*/
+	public boolean isSubstantive(){
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean isPrerelease(){
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public void setPreferredTaxa(Taxa taxa) {
+		if (taxa !=null && taxa.isDoomed())
+			return;
+		if (preferredTaxa!=taxa) {
+			preferredTaxa = taxa;
+		}
+	}
+	/*.................................................................................................................*/
+	public void initialize(Taxa taxa) {
+		savedTaxa = taxa;
+	}
+
+	/*.................................................................................................................*/
+	String getTreeDescription(int currentTree, StringBuffer comment){
+		String command  = null;
+		boolean fileDone = false;
+		boolean isTreeCommand = false;
+
+		if (!fileCheckingThread.going())
+			fileCheckingThread.start();
+		MesquiteInteger status = new MesquiteInteger(0);
+		if (file==null)
+			return null;
+		if (getSampleTrees()) {
+			int treeSelected = treesToSample.numBitsOn();
+			long fPos = getFilePos(findTreeNumber(currentTree));
+			if (!MesquiteLong.isCombinable(fPos))
+				return null;
+			file.goToFilePosition(fPos);
+			
+			while (!isTreeCommand && !fileDone){
+				command = file.getNextCommand(status, comment); 
+				if (StringUtil.blank(command))
+					fileDone = true;
+				else
+					isTreeCommand = ParseUtil.darkBeginsWithIgnoreCase(command, "TREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "UTREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "RTREE");
+				if (isTreeCommand && currentTree>highestSuccessfulTree){
+					highestSuccessfulTree = currentTree;
+					highestSuccessfulDescription = command;
+				}
+			}
+		}
+		else if (currentTree==0){  //first tree
+			CommandRecord.tick("\"Trees from Separate File\": Going to tree " + (currentTree+1));
+			file.goToFilePosition(getFilePos(0));
+			while (!isTreeCommand && !fileDone){
+				command = file.getNextCommand(status, comment); 
+				if (StringUtil.blank(command))
+					fileDone = true;
+				else
+					isTreeCommand = ParseUtil.darkBeginsWithIgnoreCase(command, "TREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "UTREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "RTREE");
+				if (isTreeCommand && currentTree>highestSuccessfulTree){
+					highestSuccessfulTree = currentTree;
+					highestSuccessfulDescription = command;
+				}
+			}
+			recordFilePos(1, file.getFilePosition()-1); 
+		}
+		else if (currentTree == lastTreeRead+1){ //last tree read was one less than requested; just continue to next without resetting file position
+			CommandRecord.tick("Going to tree " + (currentTree+1));
+			while (!isTreeCommand && !fileDone){
+				command = file.getNextCommand( status, comment); //this is highest tree read
+				if (StringUtil.blank(command))
+					fileDone = true;
+				else
+					isTreeCommand = ParseUtil.darkBeginsWithIgnoreCase(command, "TREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "UTREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "RTREE");
+				if (isTreeCommand && currentTree>highestSuccessfulTree){
+					highestSuccessfulTree = currentTree;
+					highestSuccessfulDescription = command;
+				}
+			}
+			if (currentTree % 1000 == 0 && !fileDone && ! file.atEOF()) {
+				MesquiteMessage.println("Tree " + (currentTree) + " found by \"Trees from Separate File\"");
+			}
+			recordFilePos(currentTree+1, file.getFilePosition()-1); 
+		}/**/
+		else if (currentTree>highestTreeMarked){  // a tree not yet read & not next in line
+			if (highestTreeMarked>=0)
+				file.goToFilePosition(getFilePos(highestTreeMarked));
+			int timeout = 0;
+			for (int i = highestTreeMarked; i<=currentTree && !fileDone; i++) {
+				CommandRecord.tick("Going to tree " + (i+1));
+				isTreeCommand = false;
+				timeout = 0;
+				while (!isTreeCommand && !fileDone && !file.atEOF() && timeout < 10000){
+					command = file.getNextCommand(status, comment); 
+					if (StringUtil.blank(command))
+						fileDone = true;
+					else
+						isTreeCommand = ParseUtil.darkBeginsWithIgnoreCase(command, "TREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "UTREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "RTREE");
+					if (!isTreeCommand)
+						timeout++;
+					if (isTreeCommand && i>highestSuccessfulTree){
+						highestSuccessfulTree = i;
+						highestSuccessfulDescription = command;
+					}
+
+				}
+				if (i % 1000 == 0 && !fileDone && ! file.atEOF()) {
+					MesquiteMessage.println("Tree " + (i) + " found by \"Trees from Separate File\"");
+				} 
+				if (timeout >= 10000)
+					alert("Error in reading tree file; 10000 commands found other than tree commands [last command (" + command + ")]");
+				recordFilePos(i+1, file.getFilePosition()-1); 
+			}
+		}
+		else { //a tree that is at or before the lastTreeRead, thus position should be known
+			CommandRecord.tick("Going to tree " + (currentTree+1));
+
+			file.goToFilePosition(getFilePos(currentTree));
+			while (!isTreeCommand && !fileDone){
+				command = file.getNextCommand( status, comment); //this is highest tree read
+				if (StringUtil.blank(command))
+					fileDone = true;
+				else
+					isTreeCommand = ParseUtil.darkBeginsWithIgnoreCase(command, "TREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "UTREE") || ParseUtil.darkBeginsWithIgnoreCase(command, "RTREE");
+				if (isTreeCommand && currentTree>highestSuccessfulTree){
+					highestSuccessfulTree = currentTree;
+					highestSuccessfulDescription = command;
+				}
+			}
+		}
+		lastTreeRead = currentTree;
+		//numTrees = highestSuccessfulTree+1;
+		//numTreesInTreeBlock = highestSuccessfulTree+1;
+		if (fileDone) {
+			numTrees = highestSuccessfulTree+1;
+		}
+		/*	if (StringUtil.blank(command) && fileDone) {
+			//discreetAlert("The last tree in the file " + file.getFileName() + " has been reached.");
+			currentTree = highestSuccessfulTree;
+			command = null;
+			//parametersChanged(new Notification(MesquiteListener.NUM_ITEMS_CHANGED));
+		}*/
+		return command;
+	}
+	String highestSuccessfulDescription = null;
+	/*.................................................................................................................*/
+	private Tree getCurrentTree(Taxa taxa, boolean processTree, MesquiteTree t) {
+		if (!fileReady)
+			return null;
+		String treeDescription = null;
+
+		MesquiteInteger cPos = new MesquiteInteger(0);
+		if (taxa != null && taxa != taxaInBlock) {
+			if (taxaInBlock !=null) {
+				discreetAlert( "Sorry, the trees found in file are for a different set of taxa than that requested");
+				return null;
+			}
+			else {
+				taxaInBlock = taxa;
+			}
+		}
+		if (taxa == null)
+			taxa = taxaInBlock;
+
+		MesquiteInteger status = new MesquiteInteger(0);
+		StringBuffer comment = new StringBuffer();
+		String treeCommand = getTreeDescription(currentTree, comment);
+		if (treeCommand == null)
+			return null;
+		if (treeCommand.length()<=2)
+			return null;
+		String commandName = parser.getFirstToken(treeCommand);
+		if (commandName == null)
+			return null;
+		int whichType = 1;
+		if (commandName.equalsIgnoreCase("UTREE")) 
+			whichType =2;
+		
+		currentTreeName=parser.getNextToken();
+		if (currentTreeName != null && currentTreeName.equals("*"))
+			currentTreeName=parser.getNextToken();
+		boolean treeDescriptionBad = (currentTreeName == null);
+		parser.getNextToken(); //eat up "equals"
+		if (processTree)
+			treeDescription=treeCommand.substring(parser.getPosition(), treeCommand.length());
+		if (treeDescription== null || treeDescription.length()<=2)
+			return null;
+		MesquiteTree thisTree =t; //t is supplied mostly for skipping trees
+		if (t == null)
+			thisTree = new MesquiteTree(taxa);
+		thisTree.setFileIndex(currentTree);
+		String commentString = comment.toString();
+
+		if (processTree && commentString!=null && commentString.length()>1){
+			if (commentString.charAt(0)=='!')
+				thisTree.setAnnotation(commentString.substring(1, commentString.length()), false);
+			else {
+				int wpos = commentString.indexOf("&W");
+				if (wpos <0)
+					wpos = commentString.indexOf("&w");
+				if (wpos>=0) {
+					cPos.setValue(wpos+2);
+					String num = ParseUtil.getToken(commentString, cPos);
+					String slash = ParseUtil.getToken(commentString, cPos);
+					String denom = ParseUtil.getToken(commentString, cPos, null, "$");
+					double w = 0;
+					if (slash !=null && "/".equals(slash))
+						w = 1.0*(MesquiteInteger.fromString(num))/(MesquiteInteger.fromString(denom));
+					else
+						w = MesquiteDouble.fromString(num);
+					if (MesquiteDouble.isCombinable(w)) {
+						MesquiteDouble d = new MesquiteDouble(w);
+						d.setName(TreesManager.WEIGHT);
+						thisTree.attachIfUniqueName(d);
+					}
+				}
+			}
+		}
+		if (processTree){
+			thisTree.setTreeVector(trees);
+			if (trees != null)
+				trees.setTaxa(taxa);
+
+			trees.addElement(thisTree, false);
+			boolean success = (!treeDescriptionBad) && thisTree.readTree(treeDescription);
+			//thisTree.warnRetIfNeeded();
+			thisTree.setName(currentTreeName);
+			if (whichType ==2) 
+				thisTree.setRooted(false, false);
+			trees.removeElement(thisTree, false);
+			if (!success)
+				return null;
+		}
+		return thisTree;
+	}
+	/*.................................................................................................................*/
+	public Tree getTree(Taxa taxa, int itree) {
+		setPreferredTaxa(taxa);
+		currentTree=itree;
+		return getCurrentTree(taxa, true, null);
+	}
+	public void findNumTrees(Taxa taxa){
+		if (taxa == null){
+			currentTree = 0;
+			numTrees = 0;
+			return;
+		}
+		int i = 0;
+		if (MesquiteInteger.isCombinable(numTrees))
+			i = numTrees;
+		int lastFound = -1;
+		MesquiteTree dummyTree = new MesquiteTree(taxa);
+		int oldCurrent = currentTree;
+		currentTree = i;
+		while((dummyTree = (MesquiteTree)getCurrentTree(taxa, false, dummyTree))!=null){
+			lastFound = i;
+			i++;
+			currentTree = i;
+		}
+		currentTree = oldCurrent;
+		if (lastFound >=0)
+			numTrees = lastFound;
+	}
+
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		if (getSampleTrees() && MesquiteInteger.isCombinable(numTreesToSample))
+			return numTreesToSample;
+		return numTrees; 
+	}
+	/*.................................................................................................................*/
+	public int getNumberOfTrees(Taxa taxa, boolean determineNumberIfFinite) {
+		if (!determineNumberIfFinite)
+			return getNumberOfTrees(taxa);
+		setPreferredTaxa(taxa);
+		if (!MesquiteInteger.isCombinable(numTrees)) { // fix oliver.Feb.12.'10.
+			if(getSampleTrees() && MesquiteInteger.isCombinable(numTreesToSample)){
+				return numTreesToSample;
+			}
+			findNumTrees(taxa);
+		} 
+		return numTrees; 
+	}
+
+	/*.................................................................................................................*/
+	public String getTreeNameString(Taxa taxa, int itree) {
+		if (itree == currentTree)
+			return getCurrentTreeNameString(taxa);
+		setPreferredTaxa(taxa);
+		return "Tree " + (itree +1);
+	}
+	/*.................................................................................................................*/
+	public String getCurrentTreeNameString(Taxa taxa) {
+		setPreferredTaxa(taxa);
+		if (currentTreeName == null)
+			return "Tree " + (currentTree +1);
+		return currentTreeName;
+	}
+
+	public void fileModified(long longer){
+		fileWasModified = true;
+		if (!live.getValue())
+			return;
+		fileWasModified = false;
+		int s = numTrees;
+		numTrees = MesquiteInteger.finite;
+		highestSuccessfulTree = -1;
+
+		if (longer>0 && !rereadWholeFileIfGrows.getValue())
+			fileGrewCommand.doItMainThread(Integer.toString(s), null, false, false);  
+		else
+			fileChangedCommand.doItMainThread(null, null, false, false);  
+
+	}
+	/*.................................................................................................................*/
+	/** returns whether this module is requesting to appear as a primary choice */
+	public boolean requestPrimaryChoice(){
+		return true;  
+	}
+	/*.................................................................................................................*/
+	public String getName() {
+		return "Use Trees from Separate NEXUS File";
+	}
+	/*.................................................................................................................*/
+	public String getNameForMenuItem() {
+		return "Use Trees from Separate NEXUS File...";
+	}
+
+	/*.................................................................................................................*/
+	public String getExplanation() {
+		return "Supplies trees directly from a file, without bringing the contained tree block entirely into memory.  " + 
+		"This is a special purpose module designed to allow much larger blocks of trees to be used within constraints of memory, but will make some calculations slower.  " + 
+		"Except for this special use, we recommend you use Include or Link from the file menu to access external tree files.  " + 
+		"This module does NOT copy the trees into your main data file, and so if you save your main data file then move it or the tree file, the data file will no longer be able to find the trees.  " + 
+		"This module does not know how many trees are in the file, and hence may attempt to read files beyond the number in the file.";
+	}
+	/*.................................................................................................................*/
+	public String getParameters() {
+		if (file == null)
+			return null;
+		String s = "Trees obtained from file " + file.getName();
+		s += "\n" + reportTreesSampled();
+		return s;
+	}
+}
+
+class FIleCheckThread extends Thread {
+	ManyTreesFromFileLib ownerModule;
+	boolean abort = false;
+	File treeFile;
+	String path;
+	long lastModified = 0;
+	long lastLength = 0;
+	boolean going = false;
+	public FIleCheckThread (ManyTreesFromFileLib ownerModule){
+		this.ownerModule = ownerModule;
+	}
+	public void setPath(String path){
+		this.path = path;
+		treeFile = new File(path);
+		lastModified = treeFile.lastModified();
+		lastLength = treeFile.length();
+	}
+	public void start(){
+		going = true;
+		super.start();
+	}
+	public boolean going(){
+		return going;
+	}
+	public void run() {
+
+		while (!abort){
+			try {
+				Thread.sleep(200);
+				if (treeFile != null){
+					long mod = treeFile.lastModified();
+					long length = treeFile.length();
+					if (mod > lastModified) {
+						ownerModule.fileModified(length - lastLength);
+						lastLength = length;
+						lastModified = mod;
+					}
+				}
+			}
+			catch (InterruptedException e){
+				Thread.currentThread().interrupt();
+			}
+		}
+
+	}
+
+
+}
+
diff --git a/Source/mesquite/trees/lib/SimpleTreeWindow.java b/Source/mesquite/trees/lib/SimpleTreeWindow.java
new file mode 100644
index 0000000..ae579ed
--- /dev/null
+++ b/Source/mesquite/trees/lib/SimpleTreeWindow.java
@@ -0,0 +1,477 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.lib;
+
+import java.util.*;
+import java.awt.*;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public class SimpleTreeWindow extends MesquiteWindow  {
+	public TreeDisplay treeDisplay;
+	public DrawTreeCoordinator treeDrawCoordTask;
+	int totalWidth;
+	int totalHeight;
+	int firstTree=0;
+	public MessagePanel messagePanel;
+	Taxa taxa;
+	public int highlightedBranch=0;
+	TreeTool arrowTool;
+	String defaultExplanation;
+	ScrollPane scrollPane;
+	protected Tree tree;
+	protected SimpleTreeWindowMaker ownerModule;
+	public SimpleTreeWindow ( SimpleTreeWindowMaker ownerModule, DrawTreeCoordinator treeDrawCoordTask){
+		super(ownerModule, true); //infobar
+		this.ownerModule = ownerModule;
+		this.treeDrawCoordTask = treeDrawCoordTask;
+		setShowExplanation(true);
+		defaultExplanation = ownerModule.getDefaultExplanation();
+		setExplanation(defaultExplanation);
+		setWindowSize(500,400);
+		this.ownerModule = ownerModule;
+		//setLayout( null );
+		arrowTool = new TreeTool(this, "arrow", MesquiteModule.getRootImageDirectoryPath(),"arrow.gif", 4,2,"Select", null);
+		arrowTool.setIsArrowTool(true);
+		arrowTool.setTouchedCommand(MesquiteModule.makeCommand("arrowTouch",  this));
+		addTool(arrowTool);
+		setCurrentTool(arrowTool);
+		if (arrowTool!=null)
+			arrowTool.setInUse(true);
+		setBackground(Color.white);
+		messagePanel=new MessagePanel(getColorScheme());
+		addToWindow(messagePanel);
+		messagePanel.setVisible(true);
+		taxa = ownerModule.getProject().getTaxa(0); //TODO: IN FUTURE ALLOW different
+		MesquiteSubmenuSpec mss = ownerModule.addSubmenu(null, "Analysis", MesquiteModule.makeCommand("newAssistant",  this), TreeDisplayAssistantA.class);
+		mss = ownerModule.addSubmenu(null, "Display", MesquiteModule.makeCommand("newAssistantD",  this), TreeDisplayAssistantD.class);
+		treeDisplay =treeDrawCoordTask.createOneTreeDisplay(taxa, this); //TODO: set tree display when tree is set for first time
+		scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+		scrollPane.add(treeDisplay);
+		sizeDisplays();
+		addToWindow(scrollPane);
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	public void addAssistant(TreeDisplayAssistant tda) {
+		tda.setEmployeesInStartup(true);  // normally used only within EmployerEmployee, this helps assistants know they are still in startup phase
+		treeDrawCoordTask.addAssistantTask(tda);
+		TreeDisplayExtra tce = tda.createTreeDisplayExtra(treeDisplay);
+		if (tce==null) 
+			return;
+		tce.setTree(tree);
+		treeDisplay.addExtra(tce);
+		treeDisplay.pleaseUpdate(false);
+		if (getMode()>0)
+			updateTextPage();
+		tda.setEmployeesInStartup(false);
+	}
+	/*.................................................................................................................*/
+	/** to be overridden by MesquiteWindows for a text version of their contents*/
+	public String getTextContents() {
+
+		String s = "";
+		if (ownerModule.isDoomed())
+			return"";
+		if (tree != null) {
+			s += "Tree: " + tree.writeTree() + "\n";
+			s += "  " + treeDisplay.getTextVersion();
+		}
+		return s;
+
+	}
+	String title = "Tree";
+	public void setWindowTitle(String t){
+		title = t;
+		resetTitle();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle(title); //TODO: what tree?
+	}
+	/*.................................................................................................................*/
+	public int getNumSnapshotLines(MesquiteFile file) {
+		int tot = 0;
+		for (int i = 0; i<ownerModule.getNumberOfEmployees(); i++) {
+			Object e=ownerModule.getEmployeeVector().elementAt(i);
+			if (e instanceof TreeDisplayAssistantA) {
+				tot++;
+			}
+		}
+		return tot;
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		Snapshot temp = new Snapshot();
+		temp.incorporate(super.getSnapshot(file), false);
+		ListableVector extras = treeDisplay.getExtras();
+		if (extras!=null) {
+			Enumeration enumeration=extras.elements();
+			while (enumeration.hasMoreElements()){
+				TreeDisplayExtra tde = (TreeDisplayExtra)enumeration.nextElement();
+				MesquiteModule mb = tde.getOwnerModule();
+				if (mb instanceof TreeDisplayAssistantA) {
+					temp.addLine("newAssistant", mb);
+				}
+				else if (mb instanceof TreeDisplayAssistantD) {
+					temp.addLine("newAssistantD", mb);
+				}
+			}
+		}
+
+		return temp;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module coordinating tree drawing", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else if (checker.compare(this.getClass(), "Hires new assistant module (TreeDisplayAssistantA)", "[name of module]", commandName, "newAssistant")) {
+			TreeDisplayAssistantA tda= (TreeDisplayAssistantA)ownerModule.hireNamedEmployee(TreeDisplayAssistantA.class, arguments);
+			if (tda!=null){
+				addAssistant(tda);
+				if (!MesquiteThread.isScripting())
+					ownerModule.resetContainingMenuBar();
+				return tda;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Hires new assistant module (TreeDisplayAssistantA)", "[name of module]", commandName, "newAssistantD")) {
+			TreeDisplayAssistantD tda= (TreeDisplayAssistantD)ownerModule.hireNamedEmployee(TreeDisplayAssistantD.class, arguments);
+			if (tda!=null){
+				addAssistant(tda);
+				if (!MesquiteThread.isScripting())
+					ownerModule.resetContainingMenuBar();
+				return tda;
+			}
+		}
+		else if (checker.compare(this.getClass(), "Sets size of window", "[width in pixels of window] [height in pixels of window]", commandName, "setSize")) {
+			MesquiteInteger io = new MesquiteInteger(0);
+			int width= MesquiteInteger.fromString(arguments, io);
+			int height= MesquiteInteger.fromString(arguments, io);
+			if (MesquiteInteger.isCombinable(width) && MesquiteInteger.isCombinable(height)) {
+				fromScriptCommand = true;//this is needed to counteract difficulties with popping in/out and size setting in window constructors
+				setWindowSize(width, height);
+				fromScriptCommand = false;
+				sizeDisplays();
+			}
+		}
+		else if (checker.compare(this.getClass(), "Ladderizes the clade", "[branch number]", commandName, "ladderize")) {
+			if (!(tree instanceof MesquiteTree))
+				return null;
+			Parser parser = new Parser();
+			String s = parser.getFirstToken(arguments);
+			int branchFound= MesquiteInteger.fromString(s);
+			if (s.equalsIgnoreCase("root"))
+				branchFound = tree.getRoot();
+			else
+				branchFound= MesquiteInteger.fromString(s);
+			if (branchFound >0) {
+				boolean direction = true;
+				if (arguments.indexOf("option")>=0)
+					direction = false;
+				 if (((MesquiteTree)tree).standardize(branchFound, direction, true)){
+					treeDisplay.recalculatePositions();
+					treeDisplay.repaint();
+					}
+			}
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+		return null;
+	}
+	
+	int minFieldWidth = -1;
+	int minFieldHeight = -1;
+	public void setMinimumFieldSize(int w, int h){  // if either parameter is negative, then use natural window size
+		minFieldWidth = w;
+		minFieldHeight = h;
+	}
+	
+	public int getOrientation(){
+		if (treeDisplay == null)
+			return -1;
+		return treeDisplay.getOrientation();
+	}
+	/*.................................................................................................................*/
+	public void sizeDisplays(){
+		if (treeDisplay == null || messagePanel == null)
+			return;
+		totalWidth = getWidth();
+		totalHeight = getHeight() - 16;
+		treeDisplay.setLocation(0,0);
+		scrollPane.setSize(totalWidth,totalHeight);
+		scrollPane.setLocation(0,0);
+		
+		int w = totalWidth;
+		int h = totalHeight;
+		if (w<minFieldWidth)
+			w = minFieldWidth;
+		if (h<minFieldHeight)
+			h = minFieldHeight;
+		
+		treeDisplay.setSize(w,h);
+		treeDisplay.setFieldSize(w, h);
+		messagePanel.setSize(totalWidth, 16);
+		messagePanel.setLocation(0, totalHeight);
+		resetDisplay(treeDisplay);
+	}
+	void resetDisplay(TreeDisplay treeDisplay){
+		treeDisplay.setVisRect(new Rectangle(0, 0, treeDisplay.getWidth(), treeDisplay.getHeight()));
+		Component[] cc = treeDisplay.getComponents();
+		if (cc!=null && cc.length>0)
+			for (int i=0; i<cc.length; i++) {
+				if (cc[i] instanceof Legend){ //make sure legends are in bounds
+					//adjustLocation
+					Legend legend = (Legend)cc[i];
+				
+						legend.setConstrainingRectangle(treeDisplay.getBounds()); //treeDisplay.getBounds()
+				
+					legend.adjustLocation();
+				}
+			}
+	}
+	/*.................................................................................................................*/
+	public TreeDisplay  getTreeDisplay(){
+		return treeDisplay;
+	}
+	/*.................................................................................................................*/
+	public void setTree(Tree newTree, boolean suppressDrawing){
+		if (ownerModule.isDoomed())
+				return;
+		if (treeDisplay.getTree()!=null)
+			treeDisplay.getTree().dispose();
+
+		if (newTree!=null) {
+			tree = newTree.cloneTree();//no need to establish listener to Taxa, as will be remade when needed?
+			treeDisplay.setTree(tree);
+			treeDisplay.suppressDrawing(suppressDrawing);
+			treeDisplay.setVisible(true);
+			treeDisplay.recalculatePositions();
+			treeDisplay.forceRepaint();
+			treeDisplay.setTreeAllExtras(tree);
+			MesquiteModule employer = ownerModule.getEmployer();
+			if (employer instanceof TreeWindowMaker && employer.getModuleWindow()!=null)
+				messagePanel.setMessage(tree.getName() + " in " + employer.getModuleWindow().getName());
+			else
+				messagePanel.setMessage(tree.getName());  
+		}
+		else messagePanel.setMessage("Error: source tree is null");  
+		messagePanel.repaint();
+		if (ownerModule.contextListeners !=null) {
+			Enumeration e = ownerModule.contextListeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeContextListener) {
+					TreeContextListener tce = (TreeContextListener)obj;
+					tce.treeChanged(tree);
+				}
+			}
+		}
+		contentsChanged();
+	}
+
+	/*.................................................................................................................*/
+	public Tree getTree(){
+		if (ownerModule.isDoomed())
+				return null;
+		return treeDisplay.getTree();
+	}
+	/*_________________________________________________*/
+	public   void InvertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (ownerModule.isDoomed())
+			return;
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void RevertBranchOld(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (ownerModule.isDoomed())
+			return;
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().fillBranchInverted(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void HighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (ownerModule.isDoomed())
+			return;
+		highlightedBranch=N;
+		treeDisplay.getTreeDrawing().highlightBranch(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void UnhighlightBranch(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (ownerModule.isDoomed())
+			return;
+		highlightedBranch=0;
+		treeDisplay.getTreeDrawing().unhighlightBranch(treeDisplay.getTree(), N, g);
+	}
+	/*_________________________________________________*/
+	public   void ScanFlash(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		if (ownerModule.isDoomed())
+				return;
+		setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot(); //TODO: remember drawnRoot!!!
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble d = new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, d);
+		if (highlightedBranch != 0) {
+			if (branchFound==0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+			else if (branchFound!=highlightedBranch)  {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch); 
+				notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+				HighlightBranch(treeDisplay, g, branchFound);
+			}
+		}
+		else if (branchFound!=0) {
+			notifyExtrasOfBranchEnter(treeDisplay, g, branchFound);
+			HighlightBranch(treeDisplay, g, branchFound); 
+		}
+
+	}
+	/*_________________________________________________*/
+	public   boolean ScanTouch(TreeDisplay treeDisplay, Graphics g, int x, int y, int modifiers) {
+		if (ownerModule.isDoomed())
+				return false;
+	setExplanation(defaultExplanation);
+		if (treeDisplay == null || treeDrawCoordTask == null || treeDrawCoordTask.getNamesTask() == null || treeDisplay.getTreeDrawing()==null)
+			return false;
+		Tree tree = treeDisplay.getTree();
+		int drawnRoot = treeDisplay.getTreeDrawing().getDrawnRoot();
+		if (!tree.nodeExists(drawnRoot))
+			drawnRoot = tree.getRoot();
+		MesquiteDouble d = new MesquiteDouble();
+		int branchFound =treeDisplay.getTreeDrawing().findBranch(tree,  drawnRoot, x, y, d);
+		if (branchFound!=0) {
+			if (highlightedBranch != 0) {
+				notifyExtrasOfBranchExit(treeDisplay, g, highlightedBranch);
+				UnhighlightBranch(treeDisplay, g, highlightedBranch);
+			}
+			notifyExtrasOfBranchTouch(treeDisplay, g, branchFound);
+			return true;
+		}
+		return false;
+	}
+	/*................................................................................................*/
+	private void notifyExtrasOfBranchTouch(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (ownerModule.isDoomed())
+				return;
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorTouchBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchEnter(TreeDisplay treeDisplay, Graphics g, int N) {
+		if (ownerModule.isDoomed())
+				return;
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorEnterBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	/*................................................................................................*/
+	public void notifyExtrasOfBranchExit(TreeDisplay treeDisplay,Graphics g, int N) {
+		if (ownerModule.isDoomed())
+				return;
+		if (treeDisplay.getExtras()!=null) {
+			Enumeration e = treeDisplay.getExtras().elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeDisplayExtra) {
+					TreeDisplayExtra tce = (TreeDisplayExtra)obj;
+					tce.cursorExitBranch(treeDisplay.getTree(), N, g);
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	public void paintContents(Graphics g) {
+		if (ownerModule.isDoomed())
+			return;
+		if (treeDisplay==null){
+			MesquiteMessage.warnProgrammer("Oh no, tree display is null");
+		}
+		else {
+			sizeDisplays();
+		}
+
+	}
+	/*.................................................................................................................*/
+	/** windows with manually resized components (i.e. null layoutmanagers) can override to respond to window resizing here */
+	public void windowResized(){
+		sizeDisplays();
+	}
+	public void dispose(){
+		try{
+		if (treeDisplay!=null){
+			if (treeDisplay.getTree()!=null)
+				treeDisplay.getTree().dispose();
+			treeDisplay.dispose();
+		}
+		}
+		catch (Throwable c){
+		}
+		super.dispose();
+	}
+}
+/* ======================================================================== */
+class SMessagePanel extends Panel {
+	String message;
+
+	public SMessagePanel(MesquiteWindow w) {  //in future pass general MesquiteWindow
+		super();
+		message="";
+		setBackground(ColorTheme.getInterfaceBackgroundPale());
+
+	}
+	public void paint(Graphics g) {
+		if (MesquiteWindow.checkDoomed(this))
+			return;
+		g.drawRect(0,0, getBounds().width, getBounds().height);
+		g.drawString(message,  4, 12);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+
+	public void setMessage(String s) {
+		message = s;
+		repaint();
+	}	
+}
+
+
diff --git a/Source/mesquite/trees/lib/SimpleTreeWindowMaker.java b/Source/mesquite/trees/lib/SimpleTreeWindowMaker.java
new file mode 100644
index 0000000..6331224
--- /dev/null
+++ b/Source/mesquite/trees/lib/SimpleTreeWindowMaker.java
@@ -0,0 +1,215 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.lib;
+
+import java.util.*;
+import java.awt.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import mesquite.assoc.lib.*;
+
+/* ======================================================================== */
+public abstract class SimpleTreeWindowMaker extends TWindowMaker implements TreeContext, TreeDisplayActive {
+	public void getEmployeeNeeds(){  //This gets called on startup to harvest information; override this and inside, call registerEmployeeNeed
+		EmployeeNeed e2 = registerEmployeeNeed(DrawTreeCoordinator.class,  getName() + " needs a module to draw trees.",
+		"The drawing coordinator is arranged automatically");
+	}
+	public DrawTreeCoordinator treeDrawCoordTask;
+	SimpleTreeWindow simpleTreeWindow;
+	public Vector contextListeners;
+
+	/*.................................................................................................................*/
+	public boolean superStartJob(String arguments, Object condition, boolean hiredByName) {
+		treeDrawCoordTask= (DrawTreeCoordinator)hireCompatibleEmployee(DrawTreeCoordinator.class, new MesquiteBoolean(false), null);
+		if (treeDrawCoordTask == null)
+			return sorry(getName() + " couldn't start because no tree draw coordinator module found");
+		makeMenu(getMenuName());
+		simpleTreeWindow= makeTreeWindow( this, treeDrawCoordTask);
+		contextListeners = new Vector();
+
+		setModuleWindow(simpleTreeWindow);
+		hireAllEmployees(TreeDisplayAssistantDI.class);
+		Enumeration e = getEmployeeVector().elements();
+		while (e.hasMoreElements()) {
+			Object obj = e.nextElement();
+			if (obj instanceof TreeDisplayAssistantI || obj instanceof TreeDisplayAssistantDI) {
+				TreeDisplayAssistant tca = (TreeDisplayAssistant)obj;
+				simpleTreeWindow.addAssistant(tca);
+			}
+		}
+		resetContainingMenuBar();
+		resetAllWindowsMenus();
+		simpleTreeWindow.sizeDisplays();
+		return true;
+	}
+	protected abstract SimpleTreeWindow makeTreeWindow(SimpleTreeWindowMaker stwm, DrawTreeCoordinator dtwc);
+	protected abstract String getMenuName();
+	protected String getDefaultExplanation(){
+		return null;
+	}
+	public void employeeQuit(MesquiteModule m){
+		if (m==treeDrawCoordTask)
+			iQuit();
+	}
+	public void endJob(){
+		if (contextListeners!=null){
+			Enumeration e = contextListeners.elements();
+			while (e.hasMoreElements()) {
+				Object obj = e.nextElement();
+				if (obj instanceof TreeContextListener) {
+					TreeContextListener tce = (TreeContextListener)obj;
+					tce.disposing(this);
+				}
+			}
+
+			contextListeners.removeAllElements();
+		}
+		treeDrawCoordTask=null;
+		simpleTreeWindow=null;
+		super.endJob();
+	}
+	/*.................................................................................................................*/
+	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
+		if (source instanceof DrawTreeCoordinator){ //ignores since this should have directly called to update tree display
+		}
+		else super.employeeParametersChanged(employee, source, notification);
+	}
+	public boolean isSubstantive(){
+		return false;
+	}
+	boolean first = true;
+	public  void setWindowVisible(boolean vis){
+		if (simpleTreeWindow == null)
+			return;
+		if (first){
+			simpleTreeWindow.setVisible(vis);
+			simpleTreeWindow.toFront();
+			first = false;
+		}
+		else if(!simpleTreeWindow.isVisible())
+			simpleTreeWindow.setVisible(vis);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree) {
+		simpleTreeWindow.setTree(tree, false);
+	}
+	/*.................................................................................................................*/
+	public   void setTree(Tree tree, boolean suppressDrawing) {
+		simpleTreeWindow.setTree(tree, suppressDrawing);
+	}
+	/*.................................................................................................................*/
+	public void  suppressDrawing(boolean suppress){
+		simpleTreeWindow.getTreeDisplay().suppressDrawing(suppress);
+		if (!suppress)
+			simpleTreeWindow.getTreeDisplay().repaint();
+	}
+
+	public Tree getTree (){
+		if (simpleTreeWindow == null)
+			return null;
+		return simpleTreeWindow.getTree();
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public String getContextName(){
+		if (simpleTreeWindow==null)
+			return "Tree Window";
+		return simpleTreeWindow.getTitle();
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public void addTreeContextListener (TreeContextListener listener){
+		if (listener!=null && contextListeners.indexOf(listener)<0)
+			contextListeners.addElement(listener);
+	}
+	/*.................................................................................................................*/
+	/** because TreeContext */
+	public void removeTreeContextListener (TreeContextListener listener){
+		contextListeners.removeElement(listener);
+	}
+	public MesquiteModule getTreeSource (){  //returns source of trees for context so that source can avoid using itself as context for modifications (e.g. SourceModifiedTree)
+		return this;
+	}
+	/*.................................................................................................................*/
+	public void windowGoAway(MesquiteWindow whichWindow) {
+		if (whichWindow == null)
+			return;
+		whichWindow.hide();
+		//whichWindow.dispose();
+		//iQuit();
+	}
+	/*.................................................................................................................*/
+	public Snapshot getSnapshot(MesquiteFile file) {
+		if (simpleTreeWindow ==null || !simpleTreeWindow.isVisible())
+			return null;
+
+		Snapshot fromWindow = simpleTreeWindow.getSnapshot(file);
+		if (fromWindow == null || fromWindow.getNumLines() ==0)
+			return null;
+		Snapshot sn = new Snapshot();
+		sn.addLine("getWindow");
+		sn.addLine("tell It");
+		sn.incorporate(fromWindow, true);
+		sn.addLine("endTell");
+		sn.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
+		sn.addLine("showWindow");
+
+		return sn;
+	}
+	/*.................................................................................................................*/
+	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
+		if (checker.compare(this.getClass(), "Returns module coordinating tree drawing", null, commandName, "getTreeDrawCoordinator")) {
+			return treeDrawCoordTask;
+		}
+		else
+			return  super.doCommand(commandName, arguments, checker);
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDownInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (isDoomed())
+				return false;
+		if (!treeDisplay.getTree().isLocked())
+			return simpleTreeWindow.ScanTouch(treeDisplay, g, x, y, modifiers);
+		return false;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseUpInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public boolean mouseMoveInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		if (isDoomed())
+				return false;
+		if (!treeDisplay.getTree().isLocked())
+			simpleTreeWindow.ScanFlash(treeDisplay, g, x, y, modifiers);
+		return true;
+	}
+	/*.................................................................................................................*/
+	public boolean mouseDragInTreeDisplay(int modifiers, int x, int y, TreeDisplay treeDisplay, Graphics g) {
+		return true;
+	}
+	/*.................................................................................................................*/
+	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
+	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
+	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
+	public int getVersionOfFirstRelease(){
+		return 201;  
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/trees/lib/TaxonPolygon.java b/Source/mesquite/trees/lib/TaxonPolygon.java
new file mode 100644
index 0000000..a5a7efe
--- /dev/null
+++ b/Source/mesquite/trees/lib/TaxonPolygon.java
@@ -0,0 +1,41 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.lib;
+
+import java.awt.Polygon;
+import java.awt.Rectangle;
+
+public class TaxonPolygon  extends Polygon {
+	Rectangle b;
+
+	public void setB(int x, int y, int w, int h){
+		if (b == null)
+			b = new Rectangle(x, y, w, h);
+		else {
+			b.x = x;
+			b.y = y;
+			b.width = w;
+			b.height = h;
+		}
+	}
+	
+	public boolean isHidden(){
+		if (b == null)
+			return true;
+		return b.width == 0 || b.height == 0;
+	}
+	public Rectangle getB(){
+		return b;
+	}
+}
\ No newline at end of file
diff --git a/Source/mesquite/trees/lib/TreeInfoExtraPanel.java b/Source/mesquite/trees/lib/TreeInfoExtraPanel.java
new file mode 100644
index 0000000..0be9ae7
--- /dev/null
+++ b/Source/mesquite/trees/lib/TreeInfoExtraPanel.java
@@ -0,0 +1,54 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trees.lib;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+
+import mesquite.lib.ClosablePanel;
+import mesquite.lib.ClosablePanelContainer;
+import mesquite.lib.Tree;
+
+
+public class TreeInfoExtraPanel extends ClosablePanel {
+	protected Tree tree;
+	protected int node = -1;
+	public TreeInfoExtraPanel(ClosablePanelContainer container, String title){
+		super(container, title);
+		setShowTriangle(true);
+	}
+	public void setTree(Tree tree){
+		this.tree = tree;
+	}
+	public void setNode(int node){
+		this.node = node;
+	}
+	public void taxonEnter(int it){
+	}
+	public void taxonExit(int it){
+	}
+	public void taxonTouch(int it){
+	}
+	public void branchEnter(int node){
+		setNode(node);
+	}
+	public void branchExit(int node){
+		setNode(-1);
+	}
+	public void branchTouch(int node){
+		setNode(node);
+	}
+}
+
diff --git a/Source/mesquite/trees/lib/TreeOptimizer.java b/Source/mesquite/trees/lib/TreeOptimizer.java
new file mode 100644
index 0000000..ac7b869
--- /dev/null
+++ b/Source/mesquite/trees/lib/TreeOptimizer.java
@@ -0,0 +1,467 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trees.lib;
+
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+import JSci.maths.statistics.*;
+
+public class TreeOptimizer {
+	protected MesquiteModule ownerModule;
+	protected MesquiteTimer timer;
+	protected double defaultBranchLengths=MesquiteDouble.unassigned;
+	protected double defaultBranchWidths = 1.0;
+	protected boolean searchBranchLengths=false;
+	protected boolean searchBranchWidths=false;
+	protected boolean writeToLog=true;
+	protected boolean showProgressIndicator = true;
+	protected boolean liveUpdates=false;
+	protected boolean biggerIsBetter=false;
+	protected boolean notify=false;
+	protected ProgressIndicator progIndicator=null;
+	MesquiteLong numRearrangementsTried = new MesquiteLong(0);
+	NumberForTree numberTask;
+	TreeSwapper swapTask;
+
+	
+	public TreeOptimizer (MesquiteModule ownerModule, NumberForTree numberTask, TreeSwapper swapTask) {
+		this.ownerModule = ownerModule;
+		this.numberTask = numberTask;
+		timer = new MesquiteTimer();
+		this.swapTask=swapTask;
+	}
+
+	/*.................................................................................................................*/
+	public MesquiteTree getStepwiseAdditionTree(Taxa taxa) {
+		MesquiteTree initialTree = new MesquiteTree(taxa);
+		initialTree.setToDefaultBush(2, false);
+
+		boolean minimize = !numberTask.biggerIsBetter();
+
+		MesquiteNumber bestValue = new MesquiteNumber(0);
+
+		MesquiteTree tempTree = initialTree.cloneTree();
+		CommandRecord rec = CommandRecord.getRecNSIfNull();
+
+		for (int taxon = 2; taxon < taxa.getNumTaxa() && (progIndicator==null || !progIndicator.isAborted()) && (rec==null || !rec.isCancelled()); taxon++) {
+			bestValue.setToUnassigned();
+			if (progIndicator!=null) {
+				progIndicator.setSecondaryMessage("Adding taxon " + (taxon +1));
+				progIndicator.toFront();
+		}
+			//dJCOs if a Combinable tree score is never encountered, will attempt to graft onto node 0. July.23.2012
+//			int whichNode = 0;
+			/*Assures grafting will take place on a node that exists in initialTree*/
+			int whichNode = initialTree.getRoot();
+			//dJCOe. July.23.2012
+			MesquiteNumber value = new MesquiteNumber();
+			int numNodes = initialTree.getNumNodeSpaces();
+			for (int node = 0; node<numNodes && (progIndicator==null || !progIndicator.isAborted()); node++) {   
+				if (initialTree.nodeInTree(node)) {
+					tempTree.setToClone(initialTree);
+					tempTree.graftTaxon(taxon, node, false);
+					if (MesquiteDouble.isCombinable(defaultBranchLengths))
+						tempTree.setAllBranchLengths(defaultBranchLengths,false);
+					value.setToUnassigned();
+					numberTask.calculateNumber(tempTree, value, null);
+					if ((minimize && value.isLessThan(bestValue)) || (!minimize && value.isMoreThan(bestValue))) {
+						bestValue.setValue(value);
+						whichNode = node;
+					}
+				}
+			}
+			initialTree.graftTaxon(taxon, whichNode, false);
+			if (ownerModule!=null && writeToLog)
+				ownerModule.logln("   Tree search: " + taxon + " added.");
+		}
+		return initialTree;
+	}
+
+	/*.................................................................................................................*/
+	public static double adjustBranch(MesquiteTree tree,int node, RandomBetween rng) {
+		double currentBranchLength = tree.getBranchLength(node);
+		double candidateLength = currentBranchLength + (rng.nextGaussian()*currentBranchLength/4);
+		if (candidateLength<=0) candidateLength=0.000001;
+		return candidateLength;
+	}
+	/*.................................................................................................................*/
+	public  boolean tryBranchAdjustment(MesquiteNumber currentScore, MesquiteTree swapTree,MesquiteTree tempTree, AdjustableTree tree, int node, MesquiteBoolean foundBetter, RandomBetween rng) {
+		if (numRearrangementsTried!=null)
+			numRearrangementsTried.increment();
+		MesquiteNumber tempScore = new MesquiteNumber();
+		if (progIndicator != null) {
+			if (progIndicator.isAborted()) {
+				progIndicator.goAway();
+				cleanUpSearch(currentScore, swapTree,tree,node);
+				return false;
+			}
+			progIndicator.spin();
+		}
+
+		MesquiteString rs =new MesquiteString("");
+		double oldLength= tempTree.getBranchLength(node);
+		double newLength = adjustBranch(tempTree,node, rng);//TODO: tempTree is not modified by adjustBranch, so is the new branch length even evaluated?
+		numberTask.calculateNumber(tempTree, tempScore, rs);
+
+
+		if (tempScore.isBetterThan(currentScore, biggerIsBetter)){
+			currentScore.setValue(tempScore);
+			swapTree.setBranchLength(node,newLength,notify);
+			foundBetter.setValue(true);
+			if (notify && tree instanceof Listened && liveUpdates) {
+				swapTree.standardize(node,true, false);
+				tree.setBranchLength(node,newLength,notify);
+				((Listened)tree).notifyListeners(ownerModule, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
+			}
+			return true;
+		} else
+			tempTree.setBranchLength(node,oldLength, false);			
+		return true;
+	}
+	/*.................................................................................................................*/
+	public  boolean tryRearrangement(long i, long total,MesquiteNumber currentScore, MesquiteTree swapTree, MesquiteTree tempTree, AdjustableTree tree, int node, MesquiteBoolean foundBetter) {
+		if (numRearrangementsTried!=null)
+			numRearrangementsTried.increment();
+		MesquiteNumber tempScore = new MesquiteNumber();
+		if (progIndicator != null && i % 20==0) {
+			if (progIndicator.isAborted()) {
+				progIndicator.goAway();
+				cleanUpSearch(currentScore, swapTree,tree,node);
+				return false;
+			}
+			progIndicator.spin();
+		}
+
+		MesquiteString rs =new MesquiteString("");
+		swapTask.rearrange(tempTree, node, i);  //do the rearrangement!
+
+		if (MesquiteDouble.isCombinable(defaultBranchLengths)) {
+			tempTree.setAllBranchLengths(defaultBranchLengths,false);
+		//	tempTree.arbitrarilyUltrametricize(); 
+		}
+
+		numberTask.calculateNumber(tempTree, tempScore, rs);
+
+		if (i%100==0) {
+			MesquiteMessage.print(".");
+		}
+		if (total%20==0) {
+			CommandRecord.tick(numberTask.getName()+ ": " + currentScore.toString() + "   ("+total+" rearrangements)");
+			if (progIndicator!=null)
+				progIndicator.setText(numberTask.getName()+ ": " + currentScore.toString() + "   ("+total+" rearrangements)");
+		}
+
+		if (tempScore.isBetterThan(currentScore, biggerIsBetter)){
+			currentScore.setValue(tempScore);
+			swapTree.setToClone(tempTree);
+			foundBetter.setValue(true);
+			if (notify && tree instanceof Listened && liveUpdates) {
+				swapTree.standardize(node,true, false);
+				tree.setToClone(swapTree);
+				((Listened)tree).notifyListeners(ownerModule, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+			}
+			return true;
+		} else
+			tempTree.setToClone(swapTree);			
+		return true;
+	}
+
+	/*.................................................................................................................*/
+	public   boolean searchForBetterTree(AdjustableTree tree, int node, RandomBetween rng, MesquiteString resultString){
+		if (numberTask==null)
+			return false;
+		numberTask.initialize(tree);
+		timer.start();
+
+		MesquiteString rs =new MesquiteString();
+		MesquiteNumber currentScore = new MesquiteNumber();
+		rs.setValue("");
+		MesquiteTree swapTree = new MesquiteTree(tree.getTaxa());
+		MesquiteTree tempTree = new MesquiteTree(tree.getTaxa());
+		swapTree = tree.cloneTree();
+		numberTask.calculateNumber(swapTree, currentScore, rs);
+		MesquiteBoolean foundBetter= new MesquiteBoolean(true);
+		MesquiteDialog.hideWizardForCalculation();
+
+		ProgressIndicator progIndicator=null;
+		if (ownerModule!=null && !MesquiteThread.isScripting() && showProgressIndicator)
+			progIndicator=new ProgressIndicator(ownerModule.getProject(),ownerModule.getName(), "Searching for a better tree", 0, true);
+		if (progIndicator!=null){
+			progIndicator.setButtonMode(ProgressIndicator.OFFER_CONTINUE);
+			progIndicator.setOfferContinueMessageString("Are you sure you want to stop the search?");
+			progIndicator.start();
+		}
+
+		numRearrangementsTried.setValue(0);
+		long total = 0;
+
+		CommandRecord rec = CommandRecord.getRecNSIfNull();
+
+		while(foundBetter.getValue() && !aborted(progIndicator, rec)) {  // loop for improving tree
+			tempTree.setToClone(swapTree);
+			if (MesquiteDouble.isCombinable(defaultBranchLengths)) {
+				tempTree.setAllBranchLengths(defaultBranchLengths,false);
+				//tempTree.arbitrarilyUltrametricize();
+			}
+
+			foundBetter.setValue(false);
+			long numRearrangements = swapTask.numberOfRearrangements(swapTree, node);
+			if (writeToLog) MesquiteMessage.print("\n  " + numberTask.getName()+ ": " + currentScore.toString()+ " ");
+
+			int motherNode = tree.motherOfNode(node); //store information so we can find our original node even if it has been renumbered.
+			int aTerminalOfNode=tree.leftmostTerminalOfNode(node);
+
+			/* Rather than going through the rearrangements in order (which will mean that one generally starts in the same part of the tree, and thus one will cover that
+			 * territory extremely well, to the detriment of other areas of the tree), we here pick a random rearrangement to serve as our starting point.  This is called "boundary".
+			 * We then either go down from there to rearrangement zero, followed by going up from boundary to numRearrangements, or we do the reverse, first going up from boundary.
+			 * This insures that we start in a random part of the tree each time.  This was a method suggested many years ago by DRM to DLS. The other method (going through rearrangements in order) 
+			 * is deterministic; this method with a random boundary, however, will give a different search path each time it is run.  
+			 * I did two comparisons of the two approaches, one with 27 taxa, the other with 53 taxa.
+			 * 27 taxa:  Standard order of rearrangement:  80.7, 80.6, and 80.5 seconds.
+			 *                with random starting point:   59.2, 27.4, 36.6, and 48.1 seconds.     
+			 * 53 taxa:  Standard order of rearrangement:  1505 seconds.
+			 *                with random starting point:   322 seconds.     
+			 * Ideally one might want to use a more
+			 * intelligent way to pick the boundary, but as that depends upon the nature of the objective function, and this code knows nothing but its value, that would be very hard.  */
+
+			/* if one used the standard order, this is what the next section would look like:
+
+			 for (long i=0; i<numRearrangements; i++) {
+				if (!tryRearrangement( i,  timer, currentScore, ownerModule,  swapTree,  tempTree,  tree,  node, swapTask,  numberTask,  progIndicator,  count,  foundBetter,  smallerIsBetter,  liveUpdates,  notify))
+					return false;
+				if (foundBetter.getValue()) break;
+			}
+			 */
+
+			CommandRecord.tick(numberTask.getName()+ ": " + currentScore.toString());
+			if (progIndicator!=null) {
+				progIndicator.setText(numberTask.getName()+ ": " + currentScore.toString());
+				progIndicator.toFront();
+			}
+			long boundary=rng.randomLongBetween(0, numRearrangements-1);
+			boolean downFirst  = rng.randomIntBetween(0, 1)>0;
+			double branchLengthAdjustmentFrequency =0.5;
+			if (!searchBranchLengths)
+				branchLengthAdjustmentFrequency=0;
+
+			if (downFirst) {
+				long i = boundary;
+				while (i<numRearrangements && !aborted(progIndicator, rec)) {
+					if (rng.nextDouble()>=branchLengthAdjustmentFrequency) {
+						total++;
+						if (!tryRearrangement( i,  total, currentScore,  swapTree,  tempTree,  tree,  node,  foundBetter))
+							return false;
+						if (foundBetter.getValue()) break;
+						i++;
+					} else{
+						if (!tryBranchAdjustment(currentScore,  swapTree,  tempTree,  tree, tempTree.randomNode(rng,false),  foundBetter, rng))
+							return false;
+						if (foundBetter.getValue()) break;
+
+					}
+				}
+				if (!foundBetter.getValue()){  // then let's try the other rearrangements
+					i = boundary-1; 
+					while (i>=0 && !aborted(progIndicator, rec)) {
+						if (rng.nextDouble()>=branchLengthAdjustmentFrequency) {
+							total++;
+							if (!tryRearrangement( i,  total, currentScore,  swapTree,  tempTree,  tree,  node,  foundBetter))
+								return false;
+							if (foundBetter.getValue()) break;
+							i--;
+						} else {
+							if (!tryBranchAdjustment(currentScore,  swapTree,  tempTree,  tree, tempTree.randomNode(rng,false),  foundBetter, rng))
+								return false;
+							if (foundBetter.getValue()) break;
+
+						}
+					}
+				}
+			}
+			else {
+				long i=boundary-1;
+				while (i>=0 && !aborted(progIndicator, rec)) {
+					if (rng.nextDouble()>=branchLengthAdjustmentFrequency) {
+						total++;
+						if (!tryRearrangement( i,  total, currentScore,  swapTree,  tempTree,  tree, node,  foundBetter))
+							return false;
+						if (foundBetter.getValue()) break;
+						i--;
+					} else {
+						if (!tryBranchAdjustment(currentScore,  swapTree,  tempTree,  tree, tempTree.randomNode(rng,false),  foundBetter, rng))
+							return false;
+						if (foundBetter.getValue()) break;
+					}
+				}
+				
+				if (!foundBetter.getValue()){  // then let's try the other rearrangements
+					total++;
+					i=boundary;
+					while (i<numRearrangements && !aborted(progIndicator, rec)) {
+						if (rng.nextDouble()>=branchLengthAdjustmentFrequency) {
+							if (!tryRearrangement( i,  total, currentScore,  swapTree,  tempTree,  tree,  node,  foundBetter))
+								return false;
+							if (foundBetter.getValue()) break;
+							i++;
+						} else {
+							if (!tryBranchAdjustment(currentScore,  swapTree,  tempTree,  tree, tempTree.randomNode(rng,false),  foundBetter, rng))
+								return false;
+							if (foundBetter.getValue()) break;
+						}
+
+					}
+				}
+			}
+
+
+			for (int d = tree.firstDaughterOfNode(motherNode); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) {
+				if (tree.descendantOf(aTerminalOfNode, d)) { // then this is our original node
+					node = d;
+					break;
+				}
+
+			}
+
+		}  // end while loop
+
+		cleanUpSearch(currentScore, swapTree,tree, node);
+
+		if (progIndicator!=null)
+			progIndicator.goAway();
+
+		return true;
+	}
+
+	boolean aborted(ProgressIndicator progIndicator, CommandRecord rec){
+		if (progIndicator != null && progIndicator.isAborted())
+			return true;
+		if (rec != null && rec.isCancelled())
+			return true;
+		return false;
+	}
+	/*.................................................................................................................*/
+	private  void cleanUpSearch(MesquiteNumber currentScore, MesquiteTree swapTree, AdjustableTree tree, int node) {
+		if (writeToLog) {
+			double seconds = timer.timeSinceLastInSeconds();
+			MesquiteMessage.println("\n\nSearch completed.");
+			MesquiteMessage.println("    Final score: " + currentScore.toString());
+			MesquiteMessage.println("    Total number of rearrangements: " + numRearrangementsTried.toString());
+			MesquiteMessage.println("    Time taken: " + seconds + " seconds");
+		}
+		swapTree.standardize(node,true, false);
+		tree.setToClone(swapTree);
+		swapTree.dispose();
+		if (notify && tree instanceof Listened && !liveUpdates) {
+			((Listened)tree).notifyListeners(ownerModule, new Notification(MesquiteListener.BRANCHES_REARRANGED));
+		}
+	}
+
+
+	public double getDefaultBranchLengths() {
+		return defaultBranchLengths;
+	}
+
+	public void setDefaultBranchLengths(double defaultBranchLengths) {
+		this.defaultBranchLengths = defaultBranchLengths;
+	}
+
+	public boolean isSearchBranchLengths() {
+		return searchBranchLengths;
+	}
+
+	public void setSearchBranchLengths(boolean searchBranchLengths) {
+		this.searchBranchLengths = searchBranchLengths;
+	}
+
+	public boolean isSearchBranchWidths() {
+		return searchBranchWidths;
+	}
+
+	public void setSearchBranchWidths(boolean searchBranchWidths) {
+		this.searchBranchWidths = searchBranchWidths;
+	}
+
+	public double getDefaultBranchWidths() {
+		return defaultBranchWidths;
+	}
+
+	public void setDefaultBranchWidths(double defaultBranchWidths) {
+		this.defaultBranchWidths = defaultBranchWidths;
+	}
+
+	public boolean isWriteToLog() {
+		return writeToLog;
+	}
+
+	public void setWriteToLog(boolean writeToLog) {
+		this.writeToLog = writeToLog;
+	}
+
+	public boolean isLiveUpdates() {
+		return liveUpdates;
+	}
+
+	public void setLiveUpdates(boolean liveUpdates) {
+		this.liveUpdates = liveUpdates;
+	}
+
+	public boolean isBiggerIsBetter() {
+		return biggerIsBetter;
+	}
+
+	public void setBiggerIsBetter(boolean biggerIsBetter) {
+		this.biggerIsBetter = biggerIsBetter;
+	}
+
+	public boolean isNotify() {
+		return notify;
+	}
+
+	public void setNotify(boolean notify) {
+		this.notify = notify;
+	}
+
+	public ProgressIndicator getProgIndicator() {
+		return progIndicator;
+	}
+
+	public void setProgIndicator(ProgressIndicator progIndicator) {
+		this.progIndicator = progIndicator;
+	}
+
+	public NumberForTree getNumberTask() {
+		return numberTask;
+	}
+
+	public void setNumberTask(NumberForTree numberTask) {
+		this.numberTask = numberTask;
+	}
+
+	public boolean isShowProgressIndicator() {
+		return showProgressIndicator;
+	}
+
+	public void setShowProgressIndicator(boolean showProgressIndicator) {
+		this.showProgressIndicator = showProgressIndicator;
+	}
+
+	public TreeSwapper getSwapTask() {
+		return swapTask;
+	}
+
+	public void setSwapTask(TreeSwapper swapTask) {
+		this.swapTask = swapTask;
+	}
+
+}
diff --git a/Source/mesquite/trunk/AboutPanel.java b/Source/mesquite/trunk/AboutPanel.java
new file mode 100644
index 0000000..8761701
--- /dev/null
+++ b/Source/mesquite/trunk/AboutPanel.java
@@ -0,0 +1,61 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.util.*;
+import mesquite.lib.*;
+
+/* ======================================================================== */
+/** The Panel containing the Mesquite logo on the startup window */
+public class AboutPanel extends Panel {
+	Image logo;
+	HPanel superimposed = null;
+	public AboutPanel (Image logo) {
+		this.logo = logo;
+		setBackground(Color.white);
+	}
+	void superimposePanel(HPanel p){
+		superimposed = p;
+		add(p);
+		p.setSize(getBounds().width, AboutWindow.aboutHeight - MesquiteModule.textEdgeCompensationHeight - 16);
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+	   	if (superimposed!=null || MesquiteWindow.checkDoomed(this))
+	   		return;
+		g.drawImage(logo,0,0,(ImageObserver)this);
+		
+		g.setColor(ColorDistribution.lightYellow);
+		g.drawString("Version " + MesquiteModule.getMesquiteVersion() + MesquiteModule.getBuildVersion() , 8,95); //was 15
+		if (MesquiteTrunk.mesquiteTrunk.isPrerelease())
+			g.drawString(MesquiteModule.getBuildDate() , 8,110); //was 15
+		if (StringUtil.notEmpty(MesquiteModule.getSpecialVersion()))
+			g.drawString( MesquiteModule.getSpecialVersion() , 8,125);
+		
+		if (MesquiteTrunk.substantivePrereleasesExist) {
+			g.drawString( "Some installed modules", 21,12);
+			g.drawString("are pre-release versions.", 21,27);
+			//StringUtil.highlightString(g, "Touch on red alert symbol in windows for information.", 25,45);
+			g.drawImage(InfoBar.prereleaseImage,3,3,(ImageObserver)this);
+		}
+		g.drawString("http://mesquiteproject.org", 5,210);
+		g.drawString("Copyright (c) 1997-2015 W. & D. Maddison.", 5,225);
+		
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
diff --git a/Source/mesquite/trunk/AboutWindow.java b/Source/mesquite/trunk/AboutWindow.java
new file mode 100644
index 0000000..decebb4
--- /dev/null
+++ b/Source/mesquite/trunk/AboutWindow.java
@@ -0,0 +1,273 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.util.*;
+import mesquite.lib.*;
+
+
+/* ======================================================================== */
+/** The About window (the window with the mesquite leaf that appears on startup)*/
+public class AboutWindow extends MesquiteWindow implements WindowListener {
+	public AboutPanel aboutPanel;
+	static AboutScrollPane scrollPane;
+	public SplashPanel splashPanel;
+	public ThermoPanel upperMessagePanel; //aboutMessagePanel, 
+//	public static int scrollWidth = 16;
+	public static int aboutHeight = 259;
+	public static int aboutWidth = 287; 
+	public static int splashWidth = 186;
+	public static int splashHeight = 400;
+	boolean quitIfGoAway=false;
+	public static int totalWidth = aboutWidth + splashWidth+4; 
+	private int splashColumns = 1;
+	private int splashColumnsUsed = 1;
+	private Vector splashes;
+	private int numSplashes = 0;
+	/** to be used only for accumulating commands*/
+	public AboutWindow () {
+	}
+	public AboutWindow (MesquiteModule ownerModule) {
+		super(ownerModule,  false);
+		getParentFrame().setSavedDimensions(totalWidth, aboutHeight);
+		setResizable(false);
+		setWindowSize(totalWidth, aboutHeight);
+		addWindowListener(this);
+		resetTitle();
+	//	ownerModule.setModuleWindow(this);
+		splashes = new Vector();
+	}
+	/*.................................................................................................................*/
+
+	public void setImage(Image logo){
+		addToWindow(aboutPanel = new AboutPanel(logo));
+		addToWindow(scrollPane = new AboutScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED)); 
+		//scrollPane.getHAdjustable().addAdjustmentListener(this);
+		//scrollPane.setWheelScrollingEnabled(true);
+		setBackground(ColorDistribution.mesquiteBrown);
+		aboutPanel.setSize(aboutWidth,aboutHeight);
+		aboutPanel.setVisible(true);
+		aboutPanel.repaint();
+		aboutPanel.setLayout(null);
+		aboutPanel.setBackground(ColorDistribution.mesquiteBrown);
+		scrollPane.setSize(splashWidth+4, aboutHeight);
+		scrollPane.setLocation(aboutWidth, 0);
+		splashPanel = new SplashPanel();
+		scrollPane.addSplashPanel(splashPanel);
+		splashPanel.setSize(splashWidth,splashHeight);
+		splashPanel.setLocation(0,0);
+		splashPanel.setVisible(true);
+		splashPanel.repaint();
+		splashPanel.setLayout(null);
+		scrollPane.setScrollPosition(0, 0);
+		scrollPane.setVisible(true);
+		Adjustable adj = scrollPane.getVAdjustable();
+		adj.setUnitIncrement(65);
+		scrollPane.doLayout();
+		//splashPanel.textArea.setLocation(3, 197);
+		//splashPanel.textArea.setSize(188, 60);
+		//splashPanel.textArea.setVisible(true);
+		int h = 26;
+		aboutPanel.add(upperMessagePanel = new ThermoPanel());
+		upperMessagePanel.setText("Mesquite modules loading");
+		upperMessagePanel.setSize(220,h);
+		upperMessagePanel.setForeground(ColorDistribution.lightYellow);
+		upperMessagePanel.setBackground(ColorDistribution.mesquiteBrown);
+		upperMessagePanel.setBarColor(ColorDistribution.darkMesquiteBrown);
+		upperMessagePanel.setBarBackColor(ColorDistribution.mesquiteBrown);
+		upperMessagePanel.setLocation(3,aboutHeight -h-2);
+		upperMessagePanel.setVisible(true);
+		upperMessagePanel.repaint();
+
+		//aboutPanel.add(aboutMessagePanel = new ThermoPanel());
+		
+		/*aboutMessagePanel.setText("");
+		//aboutMessagePanel.setEditable(false);
+		aboutMessagePanel.setSize(281,h);
+		aboutMessagePanel.setForeground(ColorDistribution.lightYellow);
+		aboutMessagePanel.setBackground(ColorDistribution.mesquiteBrown);
+		aboutMessagePanel.setBarColor(ColorDistribution.lightGreen);
+		aboutMessagePanel.setBarBackColor(ColorDistribution.mesquiteBrown);
+		aboutMessagePanel.setLocation(3,aboutHeight -h-2);
+		aboutMessagePanel.setVisible(true);
+		aboutMessagePanel.repaint();*/
+		setShowExplanation(false);
+	}
+	public boolean isCompactible(){
+		return false;
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		setTitle("Mesquite Startup Window");
+	}
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 1;
+	}
+	public void checkSize(){
+		int h = MesquiteModule.textEdgeCompensationHeight + 16;
+		/*if (aboutMessagePanel == null)
+			return;
+		if (aboutMessagePanel.getSize().height != h)
+			aboutMessagePanel.setSize(220,h);
+		if (aboutMessagePanel.getLocation().y != aboutHeight -h)
+			aboutMessagePanel.setLocation(3,aboutHeight -h-2);
+		*/
+		if (upperMessagePanel == null)
+			return;
+		if (upperMessagePanel.getSize().height != h)
+			upperMessagePanel.setSize(220,h);
+		if (upperMessagePanel.getLocation().y != aboutHeight -h-2)
+			upperMessagePanel.setLocation(3,aboutHeight  -h-2);
+	}
+	public Vector getSplashes(){
+		return splashes;
+	}
+	public void setQuitIfGoAway(boolean quitIfGoAway){
+		this.quitIfGoAway = quitIfGoAway;
+	}
+	public void superimposePanel(HPanel p){
+		if (aboutPanel!=null)
+			aboutPanel.superimposePanel(p);
+	}
+	public void addSplash(MesquiteModuleInfo mmi){
+		if (mmi !=null) {
+			splashes.addElement(mmi);
+			numSplashes++;
+			int y = splashPanel.addSplashImage(mmi);
+			
+			if (numSplashes <2)//
+				setWindowSize(totalWidth, aboutHeight);
+
+		}
+	}
+	/*.................................................................................................................*/
+	public void windowActivated(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowClosed(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowClosing(WindowEvent e) {
+		if (quitIfGoAway)
+			MesquiteTrunk.mesquiteTrunk.exit(false, 0);
+	}
+	/*.................................................................................................................*/
+	public void windowDeactivated(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowDeiconified(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowIconified(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+	public void windowOpened(WindowEvent e) {
+	}
+	/*.................................................................................................................*/
+}
+/* ======================================================================== */
+/** The Panel to the right of the About window (the startup window) that shows the logos of installed packages within the Mesquite system */
+class SplashPanel extends MesquitePanel {
+	//static final int numDown = 3;
+	//static final int numAcross = 3;
+	Vector splashImages;
+	Vector splashModules;
+	Color brightGreen;
+	//TextArea textArea;
+	//boolean starting = true;
+	public SplashPanel () {
+		splashImages = new Vector();
+		splashModules = new Vector();
+		setBackground(ColorDistribution.mesquiteBrown);
+	}
+	public int addSplashImage(MesquiteModuleInfo mmi){ //returns scroll setting
+		if (mmi !=null) {
+			Image im = MesquiteImage.getImage(mmi.getDirectoryPath() + "splash.gif", false);
+			if (im==null)
+				im = MesquiteImage.getImage(mmi.getDirectoryPath() + "splash.jpg", false);
+			if (im==null)
+				im = MesquiteImage.getImage(mmi.getDirectoryPath() + "splash.jpeg", false);
+			if (im!=null){
+				MediaTracker mt = new MediaTracker(this);
+				mt.addImage(im, 0);
+				try {
+					mt.waitForAll();
+				} catch (Exception e) {
+					MesquiteMessage.warnProgrammer("splash image exception------------");
+					e.printStackTrace();
+				}
+				splashImages.addElement(im);
+				splashModules.addElement(mmi);
+				if (splashImages.size()*65>AboutWindow.splashHeight) {
+					AboutWindow.splashHeight = splashImages.size()*2*65;
+					setSize(AboutWindow.splashWidth,AboutWindow.splashHeight);
+					AboutWindow.scrollPane.invalidate();
+					AboutWindow.scrollPane.validate();
+				}
+				int newSplashTop = (splashImages.size()-1)*65; //top of this new splash
+				int currentSplashAreaTop = AboutWindow.scrollPane.getScrollPosition().y; //what position is currently visible at top of splash
+				int currentSplashAreaBottom = currentSplashAreaTop + AboutWindow.aboutHeight;//what position is currently visible at bottom of splash
+				if (newSplashTop<currentSplashAreaTop || newSplashTop+65>currentSplashAreaBottom) {
+					int y = newSplashTop -AboutWindow.aboutHeight +65;
+					if (splashImages.size()>2)
+						y += 30;
+					AboutWindow.scrollPane.setScrollPosition(AboutWindow.scrollPane.getScrollPosition().x, y);
+					repaint();
+					return y;
+				}
+				repaint();
+			}
+		}
+		return -1;
+	}
+	/*.................................................................................................................*/
+	public void paint(Graphics g) {
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		for (int i=0; i<splashImages.size(); i++){
+			Image im = (Image)splashImages.elementAt(i);
+			g.drawImage(im,0, i*65, (ImageObserver)this);
+		}
+		if (StringUtil.defaultFontMetrics == null) 
+			StringUtil.defaultFontMetrics = g.getFontMetrics(ExtensibleDialog.defaultBigFont);
+		MesquiteWindow.uncheckDoomed(this);
+	}
+  	public void mouseDown (int modifiers, int clickCount, long when, int x, int y, MesquiteTool tool) {
+		for (int i=0; i<splashImages.size(); i++){
+			if (y< i*65 + 65) {
+				MesquiteModuleInfo mbi = ((MesquiteModuleInfo)splashModules.elementAt(i));
+				mbi.explainSplash();
+				return;
+			}	
+		}
+	}
+}
+
+/* ======================================================================== */
+class AboutScrollPane extends ScrollPane{
+	public AboutScrollPane (int scrollPolicy) {
+		super(scrollPolicy);
+	}
+	public void addSplashPanel(Component c){
+		addImpl(c, null, 0);
+	}
+}
+
diff --git a/Source/mesquite/trunk/ClassPathHacker.java b/Source/mesquite/trunk/ClassPathHacker.java
new file mode 100644
index 0000000..51094b5
--- /dev/null
+++ b/Source/mesquite/trunk/ClassPathHacker.java
@@ -0,0 +1,41 @@
+/* this class courtesy of Antony Miguel, http://forum.java.sun.com/thread.jsp?forum=32&thread=300557&message=1191210 */
+
+package mesquite.trunk;
+import java.lang.reflect.*;
+import java.io.*;
+import java.net.*;
+
+
+public class ClassPathHacker {
+
+	private static final Class[] parameters = new Class[]{URL.class};
+	
+	public static void addFile(String s) throws IOException {
+		File f = new File(s);
+		addFile(f);
+	}
+	
+	public static void addFile(File f) throws IOException {
+		addURL(f.toURL());
+	}
+	
+	
+	public static void addURL(URL u) throws IOException {
+			
+		URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
+		Class sysclass = URLClassLoader.class;
+	
+		try {
+			Method method = sysclass.getDeclaredMethod("addURL",parameters);
+			method.setAccessible(true);
+			method.invoke(sysloader,new Object[]{ u });
+		} 
+		catch (Throwable t) {
+			t.printStackTrace();
+			throw new IOException("Error, could not add URL to system classloader");
+		}
+					
+	}
+
+}
+
diff --git a/Source/mesquite/trunk/ClockWatcherThread.java b/Source/mesquite/trunk/ClockWatcherThread.java
new file mode 100644
index 0000000..32b63ef
--- /dev/null
+++ b/Source/mesquite/trunk/ClockWatcherThread.java
@@ -0,0 +1,151 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trunk;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.*;
+import mesquite.lib.duties.*;
+
+/* ======================================================================== */
+public class ClockWatcherThread extends Thread {
+	Mesquite mesquite;
+	static final int sleep = 1500;
+	static final int catnap = 50;
+	int sleepTime = sleep;
+	long lastTick = 0;
+	public ClockWatcherThread (Mesquite mesquite) {
+		this.mesquite = mesquite;
+		setPriority(Thread.MIN_PRIORITY);
+	}
+	public void run() {
+		long sleepCount = 0;
+		boolean reportThreads = false;
+		boolean sleptLong = false;
+		//MesquiteTrunk.mesquiteTrunk.helpSearchManager.loadManual();
+		while (!MesquiteTrunk.mesquiteTrunk.mesquiteExiting) { 
+			boolean previousSleptLong = sleptLong;
+			sleptLong = (sleepTime == sleep);
+			if (previousSleptLong && !sleptLong) //just starting naps
+				sleepCount = 0;
+			else
+				sleepCount++;
+			try {
+				Thread.sleep(sleepTime);  
+			}
+			catch (InterruptedException e){
+				Thread.currentThread().interrupt();
+			}
+			MesquiteTrunk.checkForResetCheckMenuItems();
+			if (sleptLong || sleepCount % (sleep/catnap) == 0) {
+				MesquiteThread.surveyDoomedIndicators();
+				//if (MesquiteTrunk.isMacOSXJaguar())
+				//	MesquiteThread.surveyNewWindows();
+			}
+			MesquiteThread[] mThreads = new MesquiteThread[MesquiteThread.threads.size()];
+			try {
+				for (int i=0; i<mThreads.length; i++)
+					mThreads[i] = (MesquiteThread)MesquiteThread.threads.elementAt(i);
+			}
+			catch (Exception e){
+			}
+
+
+			sleepTime = sleep;
+			sleepCount++;
+			for (int i=0; i<mThreads.length && mThreads[i]!=null; i++){  //go through current threads
+				MesquiteThread thread = mThreads[i];
+				thread.count++;
+				long currentCommandSequence = thread.getCurrent();
+				long previousCommandSequence = thread.getPrevious();
+				if (currentCommandSequence != previousCommandSequence || previousCommandSequence<=0){ // || MesquiteWindow.numDialogs>0){
+					thread.count = 0;
+					thread.setPrevious(currentCommandSequence);
+					ProgressIndicator pi = thread.getProgressIndicator();
+					if (pi !=null && pi.getIsFromWatcher()) {
+						pi.goAway();
+						thread.setProgressIndicator(null);
+					}
+					thread.checkOften = false;
+
+				}
+				else {
+					if ((thread.checkOften || sleptLong || sleepCount % (sleep/catnap) == 0) && (thread.count==thread.getPatience() || (thread.count> thread.getPatience() && thread.count % thread.getPatience() == 0))) {
+						if (!thread.dead() && (MesquiteWindow.numNonWizardDialogs>0 || MesquiteDialog.responsePending)){
+							thread.count =-1;
+						}
+						else if (!thread.dead() && MainThread.getShowWaitWindow()) {
+							sleepTime = catnap;
+							thread.checkOften = true;
+							try {
+								if (thread.getProgressIndicator() == null && thread.getSpontaneousIndicator()) {
+									ProgressIndicator pi;
+							
+									thread.setProgressIndicator(pi = new ProgressIndicator(null, "Command is executing", "A command is executing.", 0, "Emergency Cancel")); //"Cancel Command");
+									pi.setSecondaryMessage("Thread " + thread.getClass().getName() + " id " + thread.getID());
+									pi.setIsFromWatcher(true);
+									//pi.setSize(400, 220);
+									pi.setButtonMode(ProgressIndicator.OFFER_KILL_THREAD);
+									String commandNote = null;
+									CommandRecord cr = thread.getCommandRecord();
+									if (cr !=null)
+										commandNote = cr.getProgressNote();
+									if (!StringUtil.blank(commandNote))
+										commandNote += "\n";
+									else
+										commandNote = "";
+									pi.setSecondaryMessage(commandNote);
+									pi.setTertiaryMessage(StringUtil.blankIfNull(thread.getCurrentCommandName()) + "\n" + StringUtil.blankIfNull(thread.getCurrentCommandExplanation()));
+									pi.start();
+								}
+								if (thread.getProgressIndicator() !=null) {
+									String commandNote = null;
+									CommandRecord cr = thread.getCommandRecord();
+									if (cr !=null){
+										long tick = cr.getTicks();
+										if (tick!=lastTick) {
+											thread.getProgressIndicator().spin();
+										}
+										lastTick = tick;
+										commandNote = cr.getProgressNote();
+									}
+									if (!StringUtil.blank(commandNote))
+										commandNote += "\n";
+									else
+										commandNote = "";
+									thread.getProgressIndicator().setSecondaryMessage(commandNote);
+									thread.getProgressIndicator().setTertiaryMessage(StringUtil.blankIfNull(thread.getCurrentCommandName()) + "\n" + StringUtil.blankIfNull(thread.getCurrentCommandExplanation()));
+									//thread.getProgressIndicator().spin();
+									if (!thread.getProgressIndicator().isVisible()){
+										thread.getProgressIndicator().getProgressWindow().setVisible(true);
+									}
+								}
+							}
+							catch (NullPointerException e){
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	
+}
+
+
+
diff --git a/Source/mesquite/trunk/ConfigFileRecord.java b/Source/mesquite/trunk/ConfigFileRecord.java
new file mode 100644
index 0000000..61765e0
--- /dev/null
+++ b/Source/mesquite/trunk/ConfigFileRecord.java
@@ -0,0 +1,36 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import mesquite.lib.*;
+public class ConfigFileRecord implements Listable, Explainable {
+	public String[] cStored;
+	public boolean userDefined;
+	public ConfigFileRecord(boolean userDefined){
+		this.userDefined = userDefined;
+		cStored = new String[3];
+	}
+	public String getName(){
+		return cStored[1];
+	}
+	public String getExplanation(){
+		return cStored[2];
+	}
+	public String getPath(){
+		return cStored[0];
+	}
+	public boolean isUserDefined(){
+		return userDefined;
+	}
+}
diff --git a/Source/mesquite/trunk/DirectInit.java b/Source/mesquite/trunk/DirectInit.java
new file mode 100644
index 0000000..a3b9845
--- /dev/null
+++ b/Source/mesquite/trunk/DirectInit.java
@@ -0,0 +1,73 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+
+package mesquite.trunk;
+
+import mesquite.lib.*;
+
+import java.io.*;
+
+/* called by Mesquite trunk early (after directories found, before modules loaded) for any init activities other than by modules */
+public class DirectInit {
+	
+	public DirectInit(MesquiteTrunk mesquite){
+		/* This will be used to load jar files at runtime*/
+		loadJars(mesquite.getRootPath(), mesquite.jarFilesLoaded);
+		loadJarsInDirectories(mesquite.getRootPath() + MesquiteFile.fileSeparator + "mesquite", mesquite.jarFilesLoaded);
+	}
+	public static void loadJars(String directoryPath, StringBuffer buffer){
+		try {
+			String jarsPath = directoryPath;
+			if (!jarsPath.endsWith(MesquiteFile.fileSeparator) && !jarsPath.endsWith("/"))
+				jarsPath += MesquiteFile.fileSeparator;
+			jarsPath += "jars";
+			File f = new File(jarsPath);
+			if (f.exists() && f.isDirectory()){
+				String[] jars = f.list();
+				if (jars.length>0)
+					buffer.append("Incorporated from " + directoryPath +" ");
+				for (int i = 0; i< jars.length; i++) {
+					if (jars[i] != null && !jars[i].startsWith(".")){
+						String path = jarsPath + "/" + jars[i];
+						buffer.append(" " + jars[i]);
+					ClassPathHacker.addFile(path);
+					System.out.println("Jar file added to classpath: " + path);
+					}
+				}
+				buffer.append("\n\n");
+			}
+		}
+		catch (Throwable t){
+			System.out.println("DirectInit error " + t);
+		}
+	}
+	public static void loadJarsInDirectories(String path, StringBuffer buffer){ //path has no slash at the end of it
+		File f = new File(path);  //  
+		if (!f.exists())
+			return;
+		else if (f.isDirectory()){  // is a directory; hence look inside at each item
+			String[] fileList = f.list();
+			for (int i=0; i<fileList.length; i++)
+				if (fileList[i]!=null) {
+					if (fileList[i].equalsIgnoreCase("jars"))
+						loadJars(path, buffer);
+					else 
+						loadJarsInDirectories(path + MesquiteFile.fileSeparator + fileList[i], buffer);
+				}
+		}
+}
+
+
+}
+
diff --git a/Source/mesquite/trunk/EAWTHandler.java b/Source/mesquite/trunk/EAWTHandler.java
new file mode 100644
index 0000000..fc59e83
--- /dev/null
+++ b/Source/mesquite/trunk/EAWTHandler.java
@@ -0,0 +1,132 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.util.*;
+import java.io.*;
+import mesquite.lib.*;
+import mesquite.*;
+import com.apple.eawt.*;
+
+
+
+/* ======================================================================== */
+public class EAWTHandler implements FileOpener {
+	boolean waiting = false;
+	Vector fileList;
+	Mesquite mesquite;
+	static boolean quitting = false;
+	public static Vector openFileThreads = new Vector();
+	public EAWTHandler (Mesquite mesquite) {
+		this.mesquite = mesquite;
+		fileList = new Vector();
+	}
+	
+	public void register(){
+		Application app = new Application();
+	    	EAWTH eawtH = new EAWTH();
+		app.addApplicationListener(eawtH);
+	}
+	
+	public boolean isWaiting(){
+		return waiting;
+	}
+	
+	public void openFilesNow() {
+		if (mesquite == null)
+			return;
+		mesquite.openFilesNowUsed = true;
+		MesquiteModule.incrementMenuResetSuppression();
+		waiting = false;
+		while (fileList.size()>0) {
+			Object obj = fileList.elementAt(0);
+			fileList.removeElement(obj);
+			String path = null;
+			if (obj instanceof File){
+				File f = (File)obj;
+				path = f.getAbsolutePath();
+			}
+			else
+				path = (String)obj;
+			CommandRecord cr = new CommandRecord((CommandThread)null, false);
+		//	cr.suppressDebugWarning = true;
+			openFileThreads.addElement(Thread.currentThread());
+			CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+			MesquiteThread.setCurrentCommandRecord(cr);
+			MesquiteTrunk.mesquiteTrunk.openFile(path);
+			MesquiteThread.setCurrentCommandRecord(prevR);
+			openFileThreads.removeElement(Thread.currentThread());
+		}
+		MesquiteModule.decrementMenuResetSuppression();
+	}
+	class EAWTH implements ApplicationListener {
+		public void handleAbout (ApplicationEvent e){
+			if (((Mesquite)(MesquiteTrunk.mesquiteTrunk)).about!=null) {
+				((Mesquite)(MesquiteTrunk.mesquiteTrunk)).about.setVisible(true);
+				e.setHandled(true);
+			}
+		}
+		public void handleReOpenApplication (ApplicationEvent e){
+		}
+		public void handleOpenApplication (ApplicationEvent e){
+		}
+		public void handleOpenFile (ApplicationEvent e){
+			MesquiteModule.incrementMenuResetSuppression();
+			if (((Mesquite)MesquiteTrunk.mesquiteTrunk).ready) {
+				CommandRecord cr = new CommandRecord((CommandThread)null, false);
+				CommandRecord prevR = MesquiteThread.getCurrentCommandRecord();
+				MesquiteThread.setCurrentCommandRecord(cr);
+				openFileThreads.addElement(Thread.currentThread());
+			//	cr.suppressDebugWarning = true;
+				MesquiteTrunk.mesquiteTrunk.openFile(e.getFilename());
+				MesquiteThread.setCurrentCommandRecord(prevR);
+				openFileThreads.removeElement(Thread.currentThread());
+			}
+			else {
+				waiting = true;
+				fileList.addElement(e.getFilename());
+
+			}
+			MesquiteModule.decrementMenuResetSuppression();
+		}
+		public void handlePreferences (ApplicationEvent e){
+		}
+		public void handlePrintFile (ApplicationEvent e){
+		}
+		public void handleQuit (ApplicationEvent e){
+			if (quitting)
+				return;
+			if (MesquiteTrunk.attemptingToQuit)
+				return;
+			quitting = true;
+			QT q = new QT();
+			String MRJversion = System.getProperty("mrj.version");
+			double d= MesquiteDouble.fromString(MRJversion);
+			if (d>=3 && d<3.4)
+				q.start();
+			else
+				q.run();
+		}
+	}
+	class QT extends Thread {
+		public void run(){
+			if (mesquite == null)
+				return;
+			MesquiteTrunk.mesquiteTrunk.logln("About to Quit...");
+			mesquite.doCommand("quit", null, CommandChecker.defaultChecker);
+			quitting = false;
+		}
+	}
+}
+
diff --git a/Source/mesquite/trunk/FileOpener.java b/Source/mesquite/trunk/FileOpener.java
new file mode 100644
index 0000000..bc11852
--- /dev/null
+++ b/Source/mesquite/trunk/FileOpener.java
@@ -0,0 +1,24 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+
+
+
+/* ======================================================================== */
+public interface FileOpener {
+	public void openFilesNow();
+	public boolean isWaiting();
+}
+
diff --git a/Source/mesquite/trunk/ModuleLoader.java b/Source/mesquite/trunk/ModuleLoader.java
new file mode 100644
index 0000000..734e0aa
--- /dev/null
+++ b/Source/mesquite/trunk/ModuleLoader.java
@@ -0,0 +1,687 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.io.*;
+import java.util.*;
+import java.lang.reflect.*;
+import mesquite.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+/*======================================================================== */
+public class ModuleLoader {
+	Mesquite mesquite;
+	int directoryTotal = 0;
+	ListableVector configurations;
+	boolean[] packagesFound;
+	Parser parser;
+	String configurationString;
+	boolean verboseStartup = false;
+	public ModuleLoader(Mesquite mesquite){
+		this.mesquite = mesquite;
+		parser = new Parser();
+	}
+	
+MesquiteTimer loadTimer, fileTimer, listTimer,instantiateTime,compTime,mmiTime,otherTime, classTime;
+	/*.................................................................................................................*/
+	public void init(String configFile, ListableVector configurations, boolean useMinimal) {
+	this.configurations = configurations;
+		mesquite.mesquiteModulesInfoVector = new ModulesInfoVector();
+		MesquiteModuleInfo mBI = new MesquiteModuleInfo(Mesquite.class, mesquite, new CommandChecker(), mesquite.getPath());
+		mesquite.mesquiteModulesInfoVector.addElement(mBI, false);
+		mesquite.mesquiteModulesInfoVector.recordDuty(mesquite);
+		loadTimer= new MesquiteTimer();
+		fileTimer= new MesquiteTimer();
+		listTimer= new MesquiteTimer();
+		instantiateTime= new MesquiteTimer();
+		compTime= new MesquiteTimer();
+		mmiTime= new MesquiteTimer();
+		otherTime= new MesquiteTimer();
+		classTime = new MesquiteTimer();
+		verboseStartup = MesquiteFile.fileExists(MesquiteModule.getRootPath() + "verbose");
+		if (MesquiteTrunk.isApplet()) {
+			System.out.println("Error: attempt to use applet as application");
+		}
+		else {
+			StringArray targetDirectories;
+
+			
+			MesquiteTimer countTimer = new MesquiteTimer();
+			MesquiteTimer timer = new MesquiteTimer();
+			/*--------------------------------------*/
+			String[] configs = null;
+			if (useMinimal){
+				configs = new String[2];
+				configs[0] = "Minimal";
+				configs[1] = "mesquite.minimal";
+			}
+			else if (configFile != null && !("all".equalsIgnoreCase(configFile))){
+				String configPath =configFile; //MesquiteModule.getRootPath() + "mesquite" + MesquiteFile.fileSeparator + "configs" + MesquiteFile.fileSeparator + configFile;
+				if (MesquiteFile.fileExists(configPath)) {
+					configs = MesquiteFile.getFileContentsAsStrings(configPath);
+					mesquite.logln("Preferences request startup configuration file.  Mesquite will start with a selected set of modules.");
+				}
+			}
+			String path =MesquiteModule.getRootPath() + "mesquite" + MesquiteFile.fileSeparator + "minimal" + MesquiteFile.fileSeparator + "BasicFileCoordinator";
+			File f = new File(path+ MesquiteFile.fileSeparator + "BasicFileCoordinator.class");  //Modules/
+			numDirectoriesCurrent = 0;
+			if (!MesquiteInteger.isCombinable(mesquite.numDirectories))
+				mesquite.numDirectories = 0;
+			if (mesquite.numDirectories==0)
+				directoryTotal = 10000;
+			else
+				directoryTotal =  mesquite.numDirectories;
+			showMessage(true, "Looking for modules", directoryTotal, 0);
+			loadMesquiteModuleClassFiles(f, path, "mesquite.minimal.BasicFileCoordinator." , "BasicFileCoordinator.class");
+			mesquite.logln("Modules loading from directory " + MesquiteModule.getRootPath() + "mesquite/");
+			
+			StringBuffer report =  new StringBuffer(5000);
+			MesquiteModule.mesquiteTrunk.logln(report.toString());
+		//timer.start();
+			if (configs!=null){
+				targetDirectories = new StringArray(configs.length);
+				packagesFound = new boolean[configs.length];
+				for (int i=0; i<configs.length; i++) packagesFound[i]=false;
+				mesquite.setConfiguration(parser.getFirstToken(configs[0]));
+				mesquite.log("Using module set configuration file: Only modules in the module set \"" + mesquite.getConfiguration() + "\" are being loaded.  Packages loaded: ");
+				configurationString = "Configuration: " + mesquite.getConfiguration();
+				targetDirectories.setValue(0, "mesquite.minimal");
+				for (int i=1; i< configs.length; i++) { //first String is title & explanation
+					targetDirectories.setValue(i, configs[i]);
+				}
+				getModules("mesquite", MesquiteModule.getRootPath() + "mesquite", "", 0, targetDirectories, true, false);  //do the directories in config
+				int count = 0;
+				String notFound = "";
+				for (int i=0; i<configs.length; i++)
+					if (!packagesFound[i] && !("mesquite.minimal".equalsIgnoreCase(targetDirectories.getValue(i)))){
+						count++;
+						notFound += "   " + targetDirectories.getValue(i) + StringUtil.lineEnding();
+					}
+				if (count>0)
+					mesquite.alert("Some packages requested in the configuration file were not found.  These are:\n" + notFound);
+				
+				/* added by Paul Lewis */
+				String classPathsFileMF = null; 
+				if (MesquiteFile.fileExists(MesquiteModule.getRootPath() + "classpaths.xml")){
+					classPathsFileMF = MesquiteFile.getFileContentsAsString(MesquiteModule.getRootPath() + "classpaths.xml");
+					addModulesAtPaths(MesquiteModule.getRootPath(), classPathsFileMF);
+				}
+				
+			}
+			else {
+				int numStandard = MesquiteTrunk.standardPackages.length; 
+				int numStandardExtra = MesquiteTrunk.standardExtras.length; 
+				packagesFound = new boolean[numStandard + numStandardExtra +6];
+				targetDirectories = new StringArray(numStandard);
+				for (int i=0; i<numStandard; i++)
+					targetDirectories.setValue(i, "mesquite." + MesquiteTrunk.standardPackages[i]); //getting standard mesquite directories
+				getModules("mesquite", MesquiteModule.getRootPath() + "mesquite", "", 0, targetDirectories, true, true);  //first, only do the target directories
+				targetDirectories = new StringArray(numStandardExtra);
+				for (int i=0; i<numStandardExtra; i++)
+					targetDirectories.setValue(i, "mesquite." + MesquiteTrunk.standardExtras[i]); //getting standard mesquite directories
+				getModules("mesquite", MesquiteModule.getRootPath() + "mesquite", "", 0, targetDirectories, true, true);  //first, only do the target directories
+
+				targetDirectories = new StringArray(numStandard+ numStandardExtra+ 6);
+				for (int i=0; i<numStandard; i++)
+					targetDirectories.setValue(i, "mesquite." + MesquiteTrunk.standardPackages[i]); //getting standard mesquite directories
+				for (int i=0; i<numStandardExtra; i++)
+					targetDirectories.setValue(numStandard + i, "mesquite." + MesquiteTrunk.standardExtras[i]); //getting standard mesquite directories
+				targetDirectories.setValue(numStandard + numStandardExtra, "mesquite.lib.duties");//TODO: avoid duties in all contexts!
+				targetDirectories.setValue(numStandard + numStandardExtra+1, "mesquite.lib");//TODO: avoid lib in all contexts!
+				targetDirectories.setValue(numStandard + numStandardExtra+2, "mesquite.documentation");//TODO: avoid documentation in all contexts!
+				targetDirectories.setValue(numStandard + numStandardExtra+3, "mesquite.docs");//TODO: avoid docs in all contexts!
+				targetDirectories.setValue(numStandard + numStandardExtra+4, "mesquite.macros");//TODO: avoid macros in all contexts!
+				targetDirectories.setValue(numStandard + numStandardExtra+5, "mesquite.configs");  //TODO: avoid configs in all contexts!
+				getModules("mesquite", MesquiteModule.getRootPath() + "mesquite", "", 0, targetDirectories, false, true); //next, add to the target directories and do everything but them
+				try {
+					ClassPathHacker.addFile(System.getProperty("user.home") + MesquiteFile.fileSeparator  + "Mesquite_Support_Files" + MesquiteFile.fileSeparator  + "classes");
+					getModules("mesquite", System.getProperty("user.home") + MesquiteFile.fileSeparator  + "Mesquite_Support_Files" + MesquiteFile.fileSeparator  + "classes" + MesquiteFile.fileSeparator + "mesquite", "", 0, null, false, true);  //do the directories in config
+					ClassPathHacker.addFile(MesquiteModule.getRootPath() +  "additionalMesquiteModules" );
+					getModules("mesquite", MesquiteModule.getRootPath() +  "additionalMesquiteModules" + MesquiteFile.fileSeparator + "mesquite", "", 0, null, false, true);  //do the directories in config
+					
+					String classPathsFileMF = null; 
+					if (MesquiteFile.fileExists(MesquiteModule.getRootPath() + "classpaths.xml")){
+						classPathsFileMF = MesquiteFile.getFileContentsAsString(MesquiteModule.getRootPath() + "classpaths.xml");
+
+						addModulesAtPaths(MesquiteModule.getRootPath(), classPathsFileMF);
+					
+					}
+					if (MesquiteFile.fileExists(System.getProperty("user.home") + MesquiteFile.fileSeparator  + "Mesquite_Support_Files" + MesquiteFile.fileSeparator  + "classpaths.xml")){
+						classPathsFileMF = MesquiteFile.getFileContentsAsString(System.getProperty("user.home") + MesquiteFile.fileSeparator  + "Mesquite_Support_Files" + MesquiteFile.fileSeparator  + "classpaths.xml");
+						addModulesAtPaths(System.getProperty("user.home") + MesquiteFile.fileSeparator  + "Mesquite_Support_Files" + MesquiteFile.fileSeparator , classPathsFileMF);
+					}
+				}
+				catch(java.io.IOException e){ 
+					System.out.println("IOE in loading extra classes in Mesquite_Support_Files");
+				}
+				catch(Throwable e){  //to permit function under Java 1.1
+				}
+				}
+			mesquite.mesquiteModulesInfoVector.filterAllDutyDefaults();
+			mesquite.mesquiteModulesInfoVector.accumulateAllVersions();
+			//timer.end();
+			//CommandChecker checker = new CommandChecker();
+			//checker.composeDocumentation();
+			
+			// get special macros from user prefs directory
+			loadMacros(MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator +"macros", true);
+			loadConfigs(MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator +"configs", true);
+
+			hideMessage(true);
+			hideMessage(false);
+			mesquite.numDirectories = numDirectoriesCurrent;
+			mesquite.logln("");
+		}
+	}
+	
+						
+	void addModulesAtPaths(String relativeTo, String xmlPathsFileContents){
+		if (xmlPathsFileContents == null)return;
+
+		Parser parser = new Parser();
+		parser.setString(xmlPathsFileContents);
+		if (!parser.isXMLDocument(false))   // check if XML
+			return;
+		if (!parser.resetToMesquiteTagContents())   // check if has mesquite tag
+			return;
+
+		MesquiteString nextTag = new MesquiteString();
+		String tagContent = parser.getNextXMLTaggedContent(nextTag);
+		while (!StringUtil.blank(tagContent) || !StringUtil.blank(nextTag.getValue())) {
+				if (!StringUtil.blank(tagContent) && "classpath".equalsIgnoreCase(nextTag.getValue())) {
+					try{
+						String path = MesquiteFile.composePath(relativeTo, tagContent) ; //here you pass the ith thing in the list
+						DirectInit.loadJarsInDirectories(path, mesquite.jarFilesLoaded);
+						ClassPathHacker.addFile(path);	
+
+						mesquite.logln("\n\nAdditional modules loaded from " + path);
+						getModules("mesquite", path+ MesquiteFile.fileSeparator  + "mesquite", "", 0, null, false, true);  //do the directories in config
+					}
+					catch(IOException e){
+					}
+				}
+				tagContent = parser.getNextXMLTaggedContent(nextTag);
+			}
+
+			
+	}
+
+	
+	
+	
+	int directoryNumber = 0;
+	int modulesLoaded = 0;
+	int numDirectoriesCurrent = 0;
+	void checkIfModulesChanged(String path, String fileName, StringArray dontLook, StringBuffer report){ //path has no slash at the end of it
+			String filePathName;
+			if (StringUtil.blank(fileName))
+				filePathName = path;  //
+			else
+				filePathName = path+ MesquiteFile.fileSeparator + fileName;
+			if (fileName!=null && fileName.endsWith(".class")) {
+				report.append(filePathName + StringUtil.lineEnding());
+				return;
+			}
+			File f = new File(filePathName);  //
+			if (!f.exists())
+				return;
+			else if (f.isDirectory()){  // is a directory; hence look inside at each item
+				report.append(fileName + "===========" + StringUtil.lineEnding());
+				String[] modulesList = f.list();
+				mesquite.numDirectories++;
+				for (int i=0; i<modulesList.length; i++)
+					if (modulesList[i]!=null && !modulesList[i].endsWith(".class") && !avoidedDirectory(modulesList[i]) && (dontLook==null || dontLook.indexOf(modulesList[i])<0)) {
+						checkIfModulesChanged(filePathName, modulesList[i], null, report);
+					}
+			}
+			else {
+				report.append(filePathName + StringUtil.lineEnding());
+			}
+	}
+	boolean avoidedDirectory(String name){ //added 11 Mar 02
+		return ("macros".equalsIgnoreCase(name) || "documentation".equalsIgnoreCase(name) || "docs".equalsIgnoreCase(name)  || "lib".equalsIgnoreCase(name)  || "duties".equalsIgnoreCase(name)  || "configs".equalsIgnoreCase(name));
+	}
+	void countModules(String path, String fileName, StringArray dontLook){ //path has no slash at the end of it
+			String filePathName;
+			if (StringUtil.blank(fileName))
+				filePathName = path;  //
+			else
+				filePathName = path+ MesquiteFile.fileSeparator + fileName;
+			if (fileName!=null && fileName.endsWith(".class"))
+				return;
+			File f = new File(filePathName);  //
+			if (!f.exists())
+				return;
+			else if (f.isDirectory()){  // is a directory; hence look inside at each item
+				String[] modulesList = f.list();
+				mesquite.numDirectories++;
+				if (mesquite.numDirectories % 10 == 0)
+					showMessage(true, "Counting modules (approximate): " + mesquite.numDirectories, 0, 0);
+				for (int i=0; i<modulesList.length; i++)
+					if (modulesList[i]!=null && !modulesList[i].endsWith(".class") && !avoidedDirectory(modulesList[i]) && (dontLook==null || dontLook.indexOf(modulesList[i])<0)) {
+						countModules(filePathName, modulesList[i], null);
+					}
+			}
+	}
+	/*.................................................................................................................*/
+	/** Put a message in the lower left corner of the About window; integers are for thermometer use; send unassingned for no thermometer  */
+	public  void showMessage(boolean upper, String s){
+		if (mesquite.about!=null) {
+			ThermoPanel mp = null;
+			if (upper)
+				mp = mesquite.about.upperMessagePanel;
+			//else
+			//	mp = mesquite.about.aboutMessagePanel;
+			if (mp!=null){
+				if (!mp.isVisible())
+					mp.setVisible(true);
+				if (s!=null && !s.equals(mp.getText()))
+					mp.setText(s);
+			}
+			
+		}
+	}
+	/*.................................................................................................................*/
+	/** Put a message in the lower left corner of the About window; integers are for thermometer use; send unassingned for no thermometer  */
+	public  void showMessage(boolean upper, String s, int total, int current){
+		if (mesquite.about!=null) {
+			ThermoPanel mp = null;
+			if (upper)
+				mp = mesquite.about.upperMessagePanel;
+			//else
+			//	mp = mesquite.about.aboutMessagePanel;
+			if (mp!=null){
+				if (!mp.isVisible())
+					mp.setVisible(true);
+				if (s!=null && !s.equals(mp.getText()))
+					mp.setText(s);
+				mp.setTime(total, current);
+			}
+			
+		}
+	}
+	/*.................................................................................................................*/
+	/** Put a message in the lower left corner of the About window; integers are for thermometer use; send unassingned for no thermometer  */
+	public  void showMessage(boolean upper, int current){
+		if (mesquite.about!=null) {
+			ThermoPanel mp = null;
+			if (upper)
+				mp = mesquite.about.upperMessagePanel;
+			//else
+			//	mp = mesquite.about.aboutMessagePanel;
+			if (mp!=null){
+				mp.setTime(MesquiteLong.unassigned, current);
+			}
+			
+		}
+	}
+	/*.................................................................................................................*/
+	/** Remove message in the lower left corner of the About window  */
+	public  void hideMessage (boolean upper){
+		if (mesquite.about!=null) {
+			ThermoPanel mp = null;
+			if (upper)
+				mp = mesquite.about.upperMessagePanel;
+			//else
+			//	mp = mesquite.about.aboutMessagePanel;
+			if (mp!=null){
+				mp.setVisible(false);
+			}
+			
+		}
+	}
+	String extension(String name){
+		if (StringUtil.blank(name))
+			return "";
+		else {
+			int period = name.lastIndexOf('.');
+			if (period <0)
+				return "";
+			return name.substring(period, name.length());
+		}
+	}
+	String[] indent = {" ", "    ", "        ", "            ", "                ", "                   ", "                        "};
+	void getModules(String packageName, String path, String fileName, int level, StringArray targetDirectories, boolean targetOn, boolean loadingAll){ //path has no slash at the end of it
+			String filePathName;
+			if (StringUtil.blank(fileName))
+				filePathName = path;  //
+			else
+				filePathName = path+ MesquiteFile.fileSeparator + fileName;
+			level++;  //increment depth into directory structure
+			if (verboseStartup) MesquiteMessage.println(">level " + level + " " + filePathName);
+			if (fileName!=null && (".class").equalsIgnoreCase(extension(fileName))) {  //this is a class file, therefore try to load it
+				String cName = fileName.substring(0, fileName.lastIndexOf('.'));
+				if (path.indexOf(cName)<0) //for it to be a module, name of class must appear in directory structure (e.g., name of immediately containing folder)
+					return;
+				File f = new File(filePathName);  //
+				if (!f.exists())
+					return;
+				if (!"BasicFileCoordinator.class".equalsIgnoreCase(fileName)) { //is a single file; see if it's a class file; file coordinator has already been loaded
+					loadMesquiteModuleClassFiles(f, path, packageName, fileName);
+					if (verboseStartup){
+						if (targetOn)
+							MesquiteMessage.println("+loading " + fileName);
+						else 
+							MesquiteMessage.println("-loading " + fileName);
+					}
+				}
+			}
+			else {
+				File f = new File(filePathName);  //
+				if (verboseStartup) MesquiteMessage.println("    file  " + f + " exists? " + f.exists());
+				if (!f.exists())
+					return;
+				else if (f.isDirectory()){  // is a directory; hence look inside at each item
+					if (level ==2 ) {
+						loadPackageExplanation(filePathName, fileName, true);
+					}
+					numDirectoriesCurrent++;
+					String[] modulesList = f.list();
+				//	if (MesquiteTrunk.isJava2DAvailable()){
+						try{
+						Arrays.sort(modulesList);
+					}
+					catch (Throwable e){//to permit function under Java 1.1 (Arrays.sort is not defined)
+					}
+					int numItems = modulesList.length;
+					if (verboseStartup) MesquiteMessage.println("    into directory with  " + numItems + " items" );
+					if (level ==2) {
+						showMessage(true, "Loading from directory: " + fileName, directoryTotal, ++directoryNumber);
+						mesquite.log(" " + fileName);
+						if (MesquiteFile.fileOrDirectoryExists(filePathName + MesquiteFile.fileSeparator + "jars")){
+							StringBuffer buffer =new StringBuffer();
+							buffer.append("\n");
+							DirectInit.loadJars(filePathName + MesquiteFile.fileSeparator + "jars", buffer);
+							mesquite.logln(buffer.toString());
+						}
+					}
+					else
+						showMessage(true, ++directoryNumber);
+					boolean macrosFound = false;
+					for (int i=0; i<modulesList.length; i++) {
+						if (modulesList[i]==null )
+							;
+						else if (!avoidedDirectory(modulesList[i])){
+							String pathFM = packageName + fileName + "."+modulesList[i];
+							if (targetDirectories !=null){
+								int targetNumber = targetDirectories.indexOf(pathFM);
+								if (targetNumber>=0 && targetNumber<packagesFound.length)
+									packagesFound[targetNumber] = true;
+							}
+							if ((targetDirectories==null || (targetDirectories.indexOf(pathFM)<0 && !targetOn) || (targetDirectories.indexOf(pathFM)>=0 && targetOn))) {
+								getModules(packageName + fileName + ".", filePathName, modulesList[i], level, null, targetOn, loadingAll);
+							}
+							else if (level == 1) {
+								String notDonePath = filePathName+ MesquiteFile.fileSeparator + modulesList[i];
+								File notDoneFile = new File(notDonePath);
+								if (notDoneFile.exists() && notDoneFile.isDirectory() && !loadingAll) { //if loading all will catch later
+									loadConfigs(filePathName+ MesquiteFile.fileSeparator + modulesList[i]+ MesquiteFile.fileSeparator + "configs", false);
+									//loadMacros(filePathName+ MesquiteFile.fileSeparator + modulesList[i]+ MesquiteFile.fileSeparator + "macros");
+									loadPackageExplanation(notDonePath, modulesList[i], false);
+								}
+							}
+							else if (targetDirectories.indexOf(packageName + fileName + "."+modulesList[i])<0 && targetOn){
+								mesquite.logln("Not loading package \"" + pathFM + "\" because not included in current configuration list");
+							}
+						}
+						else if ("macros".equalsIgnoreCase(modulesList[i])){
+							macrosFound = true;
+						}
+						else if ("configs".equalsIgnoreCase(modulesList[i]) && (!loadingAll || targetOn)){
+							loadConfigs(filePathName+ MesquiteFile.fileSeparator + "configs", false);
+						}
+					}
+					if (macrosFound)
+						loadMacros(filePathName+ MesquiteFile.fileSeparator + "macros", false);
+				}
+			}
+	}
+	private void loadPackageExplanation(String path, String packageName, boolean loaded){
+			MesquitePackageRecord pRec = new MesquitePackageRecord();
+			pRec.setStored(0, packageName);
+			pRec.setLoaded(loaded);
+			mesquite.packages.addElement(pRec, false);
+			String ePath = path + MesquiteFile.fileSeparator + "explanation.txt";
+			if (MesquiteFile.fileExists(ePath)){
+				String[] contents = MesquiteFile.getFileContentsAsStrings(ePath);
+				if (contents!=null && contents.length>0){
+					pRec.setStored(1,contents[0]);
+					if (contents.length>1){
+						String s = "";
+						for (int i=1; i<contents.length; i++)
+							s += contents[i] + "\n";
+						pRec.setStored(2, s);
+					}
+				}
+			}
+							
+	}
+
+	private void loadConfigs(String path, boolean userDefined){
+		if (configurations == null)
+			return;
+		File configDir = new File(path);
+		if (configDir.exists() && configDir.isDirectory()) {
+					String[] configsList = configDir.list();
+					for (int i=0; i<configsList.length; i++) {
+						if (configsList[i]==null )
+							;
+						else {
+							String cPath = path + MesquiteFile.fileSeparator + configsList[i];
+							File cFile = new File(cPath);
+							if (cFile.exists() && !cFile.isDirectory() && configsList[i].endsWith("config")) {
+								String firstLine = MesquiteFile.getFileFirstContents(cPath);
+								ConfigFileRecord cfr = new ConfigFileRecord(userDefined);
+								cfr.cStored[0] = cPath;
+								cfr.cStored[1] = parser.getFirstToken(firstLine);
+								cfr.cStored[2]= parser.getNextToken();
+								configurations.addElement(cfr, false);
+							}
+						}
+					}
+		}
+	}
+	private void loadMacros(String path, boolean auto){  
+		MesquiteInteger io = new MesquiteInteger(0);
+		File macrosDirectory = new File(path);  
+		if (macrosDirectory.exists() && macrosDirectory.isDirectory()) {
+			String[] v = macrosDirectory.list();
+			for (int i=0; i<v.length; i++) {
+				String fullPath = path + MesquiteFile.fileSeparator + v[i];
+				File cFile = new File(fullPath);
+				if (cFile.exists() && !cFile.isDirectory()) {
+					String firstLine = MesquiteFile.getFileFirstContents(fullPath);
+					parser.getFirstToken(firstLine);  //"telling"
+					String target  = parser.getNextToken();
+					String name  = parser.getNextToken();
+					String explanation  = parser.getNextToken();
+					int preferredMenu  = MesquiteInteger.fromString(parser.getNextToken());
+					if (explanation== null || ";".equals(explanation))
+						explanation = "";
+					if (name == null || ";".equals(name))
+						name = v[i];
+					MesquiteModuleInfo mmi = mesquite.mesquiteModulesInfoVector.findModule(MesquiteModule.class, "#" + target);
+					if (mmi !=null) {
+						MesquiteMacro cfr = new MesquiteMacro(name, explanation, fullPath, mmi);
+						cfr.setAutoSave(auto);
+						if (MesquiteInteger.isCombinable(preferredMenu))
+								cfr.setPreferredMenu(preferredMenu);
+						mmi.addMacro(cfr);
+					}
+				}
+			}
+		}
+	}
+	/*.................................................................................................................*/
+	/** Returns whether module compatible with this version of Mesquite.*/
+   	 private String checkModuleForCompatibility(Class original){
+   	 	if (!MesquiteModule.checkMethodsAtStartup)
+   	 		return null;
+   	 	Class s = original;
+   	 	while (s!=MesquiteModule.class && s!=Object.class) {
+   	 		s = s.getSuperclass();
+   	 		try {
+   	 			String m = checkCompatibility(s, original);
+   	 			if (m!=null)
+   	 				return m;
+   	 		}
+   	 		catch (Exception e){
+   	 			return "Exception (" + e + ") checking class " + original.getName() + " against superclass " + s.getName();
+   	 		}
+   	 		catch (Error e){
+   	 			if (e instanceof ThreadDeath)
+   	 				throw e;
+   	 			else
+   	 				return "Error (" + e + ") checking class " + original.getName() + " against superclass " + s.getName();
+   	 		}
+   	 	}
+   	 	return null;
+   	 	
+   	 	//check all superclasses of this until arrive at MesquiteModule, for each checking that abstract methods of superclass are accurately represented in this
+   	 }
+   	 private String checkCompatibility(Class superClass, Class target){
+   	 	//check that abstract methods of superclass are accurately represented in target
+   	 	Method[] methods = superClass.getMethods();
+   	 	if (methods==null)
+   	 		return null;
+   	 	for (int i=0; i<methods.length; i++) {
+   	 		if (Modifier.isAbstract(methods[i].getModifiers())) {
+   	 			//check to find if method matching signature found in target
+   	 			try {
+   	 				Method inTarget = target.getMethod(methods[i].getName(), methods[i].getParameterTypes());
+   	 				if (inTarget==null){
+   	 					return "Method " + methods[i].getName() + " which should occur in class " + target.getName() + " is absent ";
+ 	 				}
+   	 				else if (Modifier.isAbstract(inTarget.getModifiers())){
+   	 					return "Method " + methods[i].getName() + " which should occur in class " + target.getName() + " is abstract ";
+ 	 				}
+   	 			}
+	   	 		catch (Exception e){
+   	 				return "Exception (" + e + ") checking method " + methods[i].getName() + " of superclass " + superClass.getName() + " against target class " + target.getName();
+	   	 		}
+	   	 		catch (Error e){
+   	 				if (e instanceof ThreadDeath)
+   	 					throw e;
+   	 				else
+   	 					return "Error (" + e + ") checking method " + methods[i].getName() + " of superclass " + superClass.getName() + " against target class " + target.getName();
+	   	 		}
+   	 			
+   	 		}
+   	 	}
+   	 	return null;
+   	 }
+   	 static boolean warnedError = false;
+   	 CommandChecker moduleChecker = new CommandChecker();
+	/*.................................................................................................................*/
+	public void loadMesquiteModuleClassFiles (File thisFile, String pathname, String packageName, String filename) {
+		String classname=StringUtil.getAllButLastItem(filename, ".");
+		String directoryName=StringUtil.getLastItem(pathname, MesquiteFile.fileSeparator);
+		if (classname==null || !classname.equalsIgnoreCase(directoryName)) //NOTE: module must be in directory of same name!!!
+			return;
+		String pathSlash = pathname + MesquiteFile.fileSeparator;
+		String lastTried = null;
+		if (thisFile.isFile()) {
+			try {
+				Class c = null;
+				//note: as of  21 april 2000 this simpler "Class.forName" was used instead of the more complex local ClassLoader
+				lastTried = packageName + classname;
+//classTime.start();
+				c= Class.forName(packageName + classname);
+//classTime.end();
+				if (lastTried.equals("mesquite.Mesquite")){
+				}
+				else if (c == null)  {
+					mesquite.logln("NULL returned by module class loader");
+				}
+				else {
+//instantiateTime.start();
+					MesquiteModule mb = mesquite.instantiateModule(c);
+					if (mb!=null && mb instanceof MesquiteModule) {
+						if (mb.isPrerelease() && mb.isSubstantive() && mb.loadModule()){
+							
+							MesquiteModule.mesquiteTrunk.substantivePrereleasesFound();
+						}
+						String message = checkModuleForCompatibility(c);
+						if (message == null && mb.compatibleWithSystem() && mb.loadModule()) {
+							MesquiteModuleInfo mBI = new MesquiteModuleInfo(c, mb, moduleChecker, pathSlash);
+							if (!mb.getName().equals("Mesquite") && mesquite.mesquiteModulesInfoVector.nameAlreadyInList(mb.getName()))
+								MesquiteTrunk.mesquiteTrunk.alert("Two modules have the same name (" + mb.getName() + ").  This may make one of the modules unavailable for use. (Module class: " + mb.getClass().getName() +
+										").\n\nThis problem can arise if a module has been moved, and you update your copy of Mesquite on a Windows machine by replacing folders without deleting the previous folder, or if you are programming and you haven't updated all projects.");
+							mesquite.mesquiteModulesInfoVector.addElement(mBI, false);
+								mesquite.mesquiteModulesInfoVector.recordDuty(mb);
+							mBI.setAsDefault(mesquite.mesquiteModulesInfoVector.isDefault(mb));
+							MesquiteTrunk.mesquiteTrunk.addSplash(mBI);
+							showMessage(false, configurationString);
+							if (mb.getExpectedPath() !=null){
+								File n = new File(mb.getExpectedPath());
+								if (!n.exists())
+									MesquiteMessage.warnProgrammer("...\n**************\nThe module " +mb.getName() + " (" + mb.getClass().getName() + ") expects a file or directory at " + mb.getExpectedPath() + " but it was not found. \n**************\n ...");
+							}
+							modulesLoaded++;
+							//mesquite.logln("Loading: " + mb.getName(), MesquiteLong.unassigned, MesquiteLong.unassigned);
+						}
+						else if (message !=null)
+							MesquiteTrunk.mesquiteTrunk.alert("Incompatible module found: " + mb.getName() + ". The module may be out of date and no longer compatible with the current version of the Mesquite system.   Error message: " + message);
+						//else 
+						//	MesquiteTrunk.mesquiteTrunk.alert("Incompatible module found: " + mb.getName() + ". The module may be out of date and no longer compatible with the current Java VM, the operating system. or the current version of the Mesquite system. ");
+						mb = null;
+					}
+					c = null;
+				}
+			}
+			catch (ClassNotFoundException e){
+				mesquite.logln("\n\nClassNotFoundException while loading: " + lastTried);
+				MesquiteFile.throwableToLog(this, e);
+				warnMissing(lastTried, e);
+			}
+			catch (NoClassDefFoundError e){
+				mesquite.logln("\n\nNoClassDefFoundError while loading: " + lastTried);
+				MesquiteFile.throwableToLog(this, e);
+				warnMissing(lastTried, e);
+			}
+			catch (NoSuchMethodError e){
+				mesquite.logln("\n\nNoSuchMethodError while loading: " + lastTried);
+				MesquiteFile.throwableToLog(this, e);
+				warnIncompatible(lastTried, e);
+			}
+			catch (AbstractMethodError e){
+				mesquite.logln("\n\nAbstractMethodError while loading: " + lastTried);
+				MesquiteFile.throwableToLog(this, e);
+				warnIncompatible(lastTried, e);
+			}
+			catch (Exception e){
+				mesquite.logln("\n\nException while loading: " + lastTried + "   exception: " + e.getClass());
+				MesquiteFile.throwableToLog(this, e);
+			}
+			catch (Error e){
+				mesquite.logln("\n\nError while loading: " + lastTried + "   error: " + e.getClass());
+				MesquiteFile.throwableToLog(this, e);
+   	 			throw e;
+			}
+		}
+	}
+	void warnIncompatible(String lastTried, Throwable e){
+		if (!warnedError)
+			mesquite.discreetAlert("Error while loading "  + lastTried + ".  This probably means that you have installed a package that is old or otherwise incompatible with this version of Mesquite.  Please ensure that any extra packages you have installed are up to date.  \n\nDetails: " +  e);
+		warnedError = true;
+	}
+	void warnMissing(String lastTried, Throwable e){
+		if (!warnedError)
+			mesquite.discreetAlert("Error while loading "  + lastTried + ".    It appears that a component of Mesquite or a required library is missing.  We recommend that you install Mesquite again. \n\nDetails: " +  e);
+		warnedError = true;
+	}
+}
+
+
+
diff --git a/Source/mesquite/trunk/PhoneHomeThread.java b/Source/mesquite/trunk/PhoneHomeThread.java
new file mode 100644
index 0000000..61838ec
--- /dev/null
+++ b/Source/mesquite/trunk/PhoneHomeThread.java
@@ -0,0 +1,118 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+ */
+package mesquite.trunk;
+
+import java.awt.*;
+import java.net.*;
+import java.util.*;
+import java.io.*;
+
+import mesquite.lib.*;
+import mesquite.*;
+import mesquite.lib.duties.*;
+import mesquite.tol.lib.BaseHttpRequestMaker;
+
+/* ======================================================================== */
+public class PhoneHomeThread extends Thread {
+
+	public PhoneHomeThread () {
+		setPriority(Thread.MIN_PRIORITY);
+	}
+	public void run() {
+		/*NOTICES =====Checking website to see if there are any notices or updates*/
+		//Put here on a separate thread so Mesquite doesn't hang if website is unavailable
+		checkForMessagesFromAllHomes();
+
+
+	}
+
+	/*.................................................................................................................*/
+	public void checkForMessagesFromAllHomes(){
+		//MesquiteTrunk.incrementMenuResetSuppression();
+		try {
+			if (!MesquiteTrunk.suppressVersionReporting){
+				StringBuffer response = new StringBuffer();
+				BaseHttpRequestMaker.contactServer(Integer.toString(MesquiteTrunk.getBuildNumber()), "http://mesquiteproject.org/pyMesquiteStartup", response);
+				String r = response.toString();
+			//if mq3rs is included in response, then this is real response
+				if (!StringUtil.blank(r) && r.indexOf("mq3rs")>=0){
+					if (r.indexOf("mq3rsshow")>=0){  //show dialog at startup!!!!
+						AlertDialog.noticeHTML(MesquiteTrunk.mesquiteTrunk.containerOfModule(),"Note", r, 600, 400, null);
+					}
+				}
+				else if (MesquiteTrunk.debugMode)
+					MesquiteMessage.warnProgrammer("no response or incorrect response from server on startup");
+			}
+		}
+		catch (Throwable t){
+		}
+		ListableVector phoneRecords = new ListableVector();
+		StringBuffer notices = new StringBuffer();
+		StringBuffer logBuffer = new StringBuffer();
+		String path  = MesquiteModule.prefsDirectory+ MesquiteFile.fileSeparator+ "phoneRecords.xml";
+		PhoneHomeUtil.readOldPhoneRecords(path, phoneRecords);
+
+		for (int i= 0; i<MesquiteTrunk.mesquiteModulesInfoVector.size(); i++){
+			MesquiteModuleInfo mmi = (MesquiteModuleInfo)MesquiteTrunk.mesquiteModulesInfoVector.elementAt(i);
+			if (!StringUtil.blank(mmi.getHomePhoneNumber())) {
+				try {
+					int rec = phoneRecords.indexOfByName("#" + mmi.getClassName()); 
+					PhoneHomeRecord phoneHomeRecord;
+					if (!MesquiteInteger.isCombinable(rec) || rec<0) {// this module is not the phone records 
+						phoneHomeRecord = new PhoneHomeRecord("#"+mmi.getClassName());
+						phoneRecords.addElement(phoneHomeRecord, false);
+					}
+					else
+						phoneHomeRecord = (PhoneHomeRecord)phoneRecords.elementAt(rec);
+					String notice = PhoneHomeUtil.retrieveMessagesFromHome(mmi, phoneHomeRecord, logBuffer);
+					phoneHomeRecord.setCurrentValues(mmi);
+					if (!StringUtil.blank(notice)) {
+						if (mmi.getModuleClass() == mesquite.Mesquite.class)
+							notices.append("<h3>From Mesquite</h3>");
+						else if (!StringUtil.blank(mmi.getPackageName()))
+							notices.append("<h3>From " + mmi.getPackageName() + "</h3>");
+						else
+							notices.append("<h3>From " + mmi.getName() + "</h3>");
+						notices.append(notice);
+						//notices.append("<hr>");
+					}
+				}
+				catch (Throwable t){
+				}
+			}
+		}
+		if (!StringUtil.blank(logBuffer.toString())){
+			MesquiteTrunk.mesquiteTrunk.logln("\n*************************" + logBuffer.toString() + "\n*************************\n");
+		}
+
+		if (!StringUtil.blank(notices)){
+			String note = ("<h2>Notices from the websites of Mesquite and installed packages</h2><hr>" + notices.toString() + "<br><h4>(You can ask Mesquite not to check for messages on its websites using the menu item in the Defaults submenu of the File menu)</h4>");
+			if (!MesquiteThread.isScripting()){
+				AlertDialog.noticeHTML(MesquiteTrunk.mesquiteTrunk.containerOfModule(),"Note", note, 600, 400, PhoneHomeUtil.getPhoneHomeDialogLinkCommand(), true);
+			}
+			else
+				System.out.println(note);
+		}
+		if (phoneRecords.size()>0)
+			PhoneHomeUtil.writePhoneRecords(path, phoneRecords);
+		MesquiteTrunk.mesquiteTrunk.storePreferences();
+		MesquiteTrunk.resetAllMenuBars();
+
+		//	MesquiteTrunk.decrementMenuResetSuppression();
+	}
+
+}
+
+
+
diff --git a/Source/mesquite/trunk/ProjectTreeWindow.java b/Source/mesquite/trunk/ProjectTreeWindow.java
new file mode 100644
index 0000000..5c58e78
--- /dev/null
+++ b/Source/mesquite/trunk/ProjectTreeWindow.java
@@ -0,0 +1,116 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.util.*;
+import mesquite.lib.*;
+import mesquite.lib.duties.*;
+/*======================================================================== */
+public class ProjectTreeWindow extends MesquiteWindow implements SystemWindow {
+	HPanel  browser;
+	MesquiteModule  ownerModule;
+	HelpSearchStrip searchStrip;
+	int searchHeight = 20;
+	public ProjectTreeWindow (MesquiteModule ownerModule, BrowseHierarchy drawTask) {
+		super(ownerModule, false);
+		setWindowSize(300,300);
+		setWindowLocation(4,4, false);
+		this.ownerModule = ownerModule;
+		setFont(new Font ("SanSerif", Font.PLAIN, 10));
+
+//		getGraphicsArea().setLayout(new BorderLayout());
+		//getGraphicsArea().setBackground(Color.cyan);
+		if (drawTask!=null){
+			browser = drawTask.makeHierarchyPanel();
+			browser.setTitle(null);
+			addToWindow(browser);
+			
+			browser.setSize(getWidth(), getHeight() - searchHeight);
+			browser.setLocation(0, 0);
+			browser.showTypes(true);
+			browser.setBackground(Color.white);
+			//browser.setBackground(ColorDistribution.projectLight[getColorScheme()]);
+			//checking for memory leaks 
+			browser.setRootNode(MesquiteTrunk.mesquiteTrunk.getProjectList());
+			searchStrip = new HelpSearchStrip(this, false);
+			addToWindow(searchStrip);
+			searchStrip.setBounds(4, getHeight()-searchHeight, getWidth()-4, searchHeight);
+			searchStrip.setVisible(true);
+			browser.setVisible(true);
+			setShowAnnotation(true);
+			incrementAnnotationArea();
+			setShowExplanation(true);
+			incrementExplanationArea();
+			setExplanation("Configuration of modules loaded: " + MesquiteTrunk.mesquiteTrunk.getConfiguration());
+		}
+		resetTitle();
+	}
+	public boolean showInfoTabs(){
+		return false;
+	}
+	public boolean permitViewMode(){
+		return false;
+	}
+	public void repaintSearchStrip(){
+		searchStrip.repaint();
+	}
+	/*.................................................................................................................*/
+	/** When called the window will determine its own title.  MesquiteWindows need
+	to be self-titling so that when things change (names of files, tree blocks, etc.)
+	they can reset their titles properly*/
+	public void resetTitle(){
+		if (compactWindows)
+			setTitle("Projects and Files"); 
+		else
+			setTitle("Mesquite Projects and Files"); 
+
+	}
+	/** Returns menu location for item to bring the window to the for (0 = custom or don't show; 1 = system area of Windows menu; 2 = after system area of Windows menu)*/
+	public int getShowMenuLocation(){
+		return 1;
+	}
+	public void contentsChanged() {
+		setExplanation("Configuration of modules loaded: " + MesquiteTrunk.mesquiteTrunk.getConfiguration());
+		super.contentsChanged();
+	}
+	public void disposeReferences() {
+		if (browser!=null)
+			browser.disposeReferences();
+	}
+	public void renew() {
+		if (browser!=null)
+			browser.renew();
+		setExplanation("Configuration of modules loaded: " + MesquiteTrunk.mesquiteTrunk.getConfiguration());
+	}
+	/*.................................................................................................................*/
+	public void windowResized() {
+		super.windowResized();
+	   	if (MesquiteWindow.checkDoomed(this))
+	   		return;
+		setExplanation("Configuration of modules loaded: " + MesquiteTrunk.mesquiteTrunk.getConfiguration());
+		if (browser!=null) {
+			browser.setSize(getWidth(), getHeight()-  searchHeight);
+			browser.setLocation(0, 0);
+		}
+		if (searchStrip != null) {
+			searchStrip.setLocation(4, getHeight()-searchHeight);
+			searchStrip.setSize(getWidth()-4, searchHeight);
+		}
+		MesquiteWindow.uncheckDoomed(this);
+	}
+}
+
+
diff --git a/Source/mesquite/trunk/WelcomeDialog.java b/Source/mesquite/trunk/WelcomeDialog.java
new file mode 100644
index 0000000..357e014
--- /dev/null
+++ b/Source/mesquite/trunk/WelcomeDialog.java
@@ -0,0 +1,68 @@
+/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 
+
+
+Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
+The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
+Perhaps with your help we can be more than a few, and make Mesquite better.
+
+Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
+Mesquite's web site is http://mesquiteproject.org
+
+This source code and its compiled class files are free and modifiable under the terms of 
+GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
+*/
+package mesquite.trunk;
+
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+import java.awt.event.*;
+import mesquite.lib.*;
+
+
+
+/*===============================================*/
+public class WelcomeDialog extends MesquiteDialog {
+	TextField t; 
+	public WelcomeDialog (MesquiteWindow parent,  String title, String label) {
+		super(parent, title);
+		
+		BorderLayout layout = new BorderLayout();
+		setLayout(layout);
+		setBackground(ColorTheme.getInterfaceBackground());
+		Font f = new Font ("Dialog", Font.PLAIN, 12);
+		Font fSmall = new Font ("Serif", Font.PLAIN, 6);
+		TextArea labstr1;
+		add("North", labstr1 = new TextArea (label, 10,10, TextArea.SCROLLBARS_VERTICAL_ONLY));
+		
+		Panel buttons = new Panel();
+		Button cancel;
+		Button ok;
+		buttons.add("West", t = new TextField(" "));
+		buttons.add("East", ok = new Button("OK"));
+		setDefaultButton("OK");
+		
+		ok.setFont(f);
+		labstr1.setFont(f);
+		
+		add("South", buttons);
+		setSize(350, 250);
+		labstr1.requestFocus();
+		MesquiteWindow.centerWindow(this);
+		setVisible(true);
+	}
+	
+
+	public void buttonHit(String buttonLabel, Button button) {
+		Dimension d = t.getSize();
+		Graphics g = getGraphics();
+		FontMetrics fm = g.getFontMetrics(g.getFont());
+		g.dispose();
+		int sw = fm.stringWidth(" ");
+		int ma = fm.getMaxAscent();
+		int md = fm.getMaxDescent();
+		MesquiteModule.textEdgeCompensationHeight = d.height-ma-md;
+		MesquiteModule.textEdgeCompensationWidth = d.width-sw;
+	}
+}
+
diff --git a/Source/org/apache/hivemind/util/ClassAdaptor.java b/Source/org/apache/hivemind/util/ClassAdaptor.java
new file mode 100644
index 0000000..35ac39a
--- /dev/null
+++ b/Source/org/apache/hivemind/util/ClassAdaptor.java
@@ -0,0 +1,215 @@
+package org.apache.hivemind.util;
+
+
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * Provides access to an object (of a particular class) as a set of individual property that may be
+ * read or updated.
+ * 
+ * @author Howard Lewis Ship
+ */
+class ClassAdaptor
+{
+    private final Map _propertyAdaptorMap = new HashMap();
+
+    ClassAdaptor(PropertyDescriptor[] properties)
+    {
+        for (int i = 0; i < properties.length; i++)
+        {
+            PropertyDescriptor d = properties[i];
+
+            String name = d.getName();
+
+            _propertyAdaptorMap.put(name, new PropertyAdaptor(name, d.getPropertyType(), d
+                    .getReadMethod(), d.getWriteMethod()));
+        }
+    }
+
+    /**
+     * Updates the property of the target object.
+     * 
+     * @param target
+     *            the object to update
+     * @param value
+     *            the value to be stored into the target object property
+     */
+    public void write(Object target, String propertyName, Object value)
+    {
+        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
+
+        a.write(target, value);
+    }
+
+    /**
+     * An improved version of {@link #write(Object, String, Object)} that can convert a string value
+     * to an appropriate property type value.
+     * 
+     * @since 1.1
+     */
+
+    public void smartWrite(Object target, String propertyName, String value)
+    {
+        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
+
+        a.smartWrite(target, value);
+    }
+
+    /**
+     * Reads the property of the target object.
+     * 
+     * @param target
+     *            the object to read
+     * @param propertyName
+     *            the name of the property to read
+     */
+    public Object read(Object target, String propertyName)
+    {
+        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
+
+        return a.read(target);
+    }
+
+    /**
+     * Returns the type of the named property.
+     * 
+     * @param target
+     *            the object to examine
+     * @param propertyName
+     *            the name of the property to check
+     */
+    public Class getPropertyType(Object target, String propertyName)
+    {
+        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
+
+        return a.getPropertyType();
+    }
+
+    /**
+     * Returns true if the named property exists and is readable.
+     */
+
+    public boolean isReadable(String propertyName)
+    {
+        PropertyAdaptor result = (PropertyAdaptor) _propertyAdaptorMap.get(propertyName);
+
+        return result != null && result.isReadable();
+    }
+
+    /**
+     * Returns true if the named property exists and is writable.
+     */
+
+    public boolean isWritable(String propertyName)
+    {
+        PropertyAdaptor result = (PropertyAdaptor) _propertyAdaptorMap.get(propertyName);
+
+        return result != null && result.isWritable();
+    }
+
+    PropertyAdaptor getPropertyAdaptor(Object target, String propertyName)
+    {
+        PropertyAdaptor result = (PropertyAdaptor) _propertyAdaptorMap.get(propertyName);
+
+        if (result == null)
+            throw new RuntimeException("");
+
+        return result;
+    }
+
+    /**
+     * Returns a List of the names of readable properties (properties with a non-null getter).
+     */
+    public List getReadableProperties()
+    {
+        List result = new ArrayList(_propertyAdaptorMap.size());
+
+        Iterator i = _propertyAdaptorMap.values().iterator();
+
+        while (i.hasNext())
+        {
+            PropertyAdaptor a = (PropertyAdaptor) i.next();
+
+            if (a.isReadable())
+                result.add(a.getPropertyName());
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns a List of the names of readable properties (properties with a non-null setter).
+     */
+    public List getWriteableProperties()
+    {
+        List result = new ArrayList(_propertyAdaptorMap.size());
+
+        Iterator i = _propertyAdaptorMap.values().iterator();
+
+        while (i.hasNext())
+        {
+            PropertyAdaptor a = (PropertyAdaptor) i.next();
+
+            if (a.isWritable())
+                result.add(a.getPropertyName());
+        }
+
+        return result;
+    }
+
+    /**
+     * Does the grunt work for
+     * {@link org.apache.hivemind.util.PropertyUtils#configureProperties(Object, String)}.
+     * 
+     * @since 1.1
+     */
+
+    public void configureProperties(Object target, String initializer)
+    {
+        StringTokenizer tokenizer = new StringTokenizer(initializer, ",");
+
+        while (tokenizer.hasMoreTokens())
+        {
+            configurePropertyFromToken(target, tokenizer.nextToken());
+        }
+    }
+
+    /**
+     * The token is either:
+     * <ul>
+     * <li>propertyName=value</li>
+     * <li>propertyName</li>
+     * <li>!propertyName</li>
+     * </ul>
+     * The later two are for boolean properties (true and false, respectively).
+     * 
+     * @since 1.1
+     */
+    private void configurePropertyFromToken(Object target, String token)
+    {
+        int equalsx = token.indexOf('=');
+
+        if (equalsx > 0)
+        {
+            String propertyName = token.substring(0, equalsx).trim();
+            String value = token.substring(equalsx + 1);
+
+            smartWrite(target, propertyName, value);
+            return;
+        }
+
+        boolean negate = token.startsWith("!");
+
+        String propertyName = negate ? token.substring(1) : token;
+
+        Boolean value = negate ? Boolean.FALSE : Boolean.TRUE;
+
+        write(target, propertyName, value);
+    }
+}
diff --git a/Source/org/apache/hivemind/util/PropertyAdaptor.java b/Source/org/apache/hivemind/util/PropertyAdaptor.java
new file mode 100644
index 0000000..f468db2
--- /dev/null
+++ b/Source/org/apache/hivemind/util/PropertyAdaptor.java
@@ -0,0 +1,184 @@
+package org.apache.hivemind.util;
+
+
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorManager;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+//import org.apache.hivemind.ApplicationRuntimeException;
+
+/**
+ * Used to manage dynamic access to a property of a specific class.
+ * 
+ * @author Howard Lewis Ship
+ */
+public class PropertyAdaptor
+{
+    private String _propertyName;
+
+    private Class _propertyType;
+
+    private Method _readMethod;
+
+    private Method _writeMethod;
+
+    PropertyAdaptor(String propertyName, Class propertyType, Method readMethod, Method writeMethod)
+    {
+        _propertyName = propertyName;
+        _propertyType = propertyType;
+        _readMethod = readMethod;
+        _writeMethod = writeMethod;
+    }
+
+    /**
+     * Returns the name of the method used to read the property, or null if the property is not
+     * readable.
+     */
+    public String getReadMethodName()
+    {
+        return _readMethod == null ? null : _readMethod.getName();
+    }
+
+    /**
+     * Returns the name of the method used to write the property, or null if the property is not
+     * writable.
+     */
+    public String getWriteMethodName()
+    {
+        return _writeMethod == null ? null : _writeMethod.getName();
+    }
+
+    public String getPropertyName()
+    {
+        return _propertyName;
+    }
+
+    public Class getPropertyType()
+    {
+        return _propertyType;
+    }
+
+    /**
+     * Updates the property of the target object.
+     * 
+     * @param target
+     *            the object to update
+     * @param value
+     *            the value to be stored into the target object property
+     */
+    public void write(Object target, Object value)
+    {
+        if (_writeMethod == null)
+            throw new RuntimeException("");
+
+        try
+        {
+            _writeMethod.invoke(target, new Object[]
+            { value });
+
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException("");
+        }
+    }
+
+    public void smartWrite(Object target, String value)
+    {
+        Object convertedValue = convertValueForAssignment(target, value);
+
+        write(target, convertedValue);
+    }
+
+    /** @since 1.1 */
+    private Object convertValueForAssignment(Object target, String value)
+    {
+        if (value == null || _propertyType.isInstance(value))
+            return value;
+
+        PropertyEditor e = PropertyEditorManager.findEditor(_propertyType);
+
+        if (e == null)
+        {
+            Object convertedValue = instantiateViaStringConstructor(target, value);
+
+            if (convertedValue != null)
+                return convertedValue;
+
+            throw new RuntimeException("");
+        }
+
+        try
+        {
+            e.setAsText(value);
+
+            return e.getValue();
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException("");
+        }
+    }
+
+    /**
+     * Checks to see if this adaptor's property type has a public constructor that takes a single
+     * String argument.
+     */
+
+    private Object instantiateViaStringConstructor(Object target, String value)
+    {
+        try
+        {
+            Constructor c = _propertyType.getConstructor(new Class[]
+            { String.class });
+
+            return c.newInstance(new Object[]
+            { value });
+        }
+        catch (Exception ex)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Returns true if there's a write method for the property.
+     */
+    public boolean isWritable()
+    {
+        return _writeMethod != null;
+    }
+
+    /**
+     * Reads the property of the target object.
+     * 
+     * @param target
+     *            the object to read a property from
+     */
+    public Object read(Object target)
+    {
+        if (_readMethod == null)
+            throw new RuntimeException("No read method found for: " + this);
+
+        try
+        {
+            return _readMethod.invoke(target, null);
+
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException("Problems invoking read method for: " + this);
+        }
+    }
+
+    /**
+     * Returns true if there's a read method for the property.
+     */
+
+    public boolean isReadable()
+    {
+        return _readMethod != null;
+    }
+
+}
diff --git a/Source/org/apache/hivemind/util/PropertyUtils.java b/Source/org/apache/hivemind/util/PropertyUtils.java
new file mode 100644
index 0000000..ad91b69
--- /dev/null
+++ b/Source/org/apache/hivemind/util/PropertyUtils.java
@@ -0,0 +1,206 @@
+package org.apache.hivemind.util;
+
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+//import org.apache.hivemind.ApplicationRuntimeException;
+//import org.apache.hivemind.HiveMind;
+
+/**
+ * A collection of static methods used to perform property-level access on arbitrary objects.
+ * 
+ * @author Howard Lewis Ship
+ */
+public class PropertyUtils
+{
+    private static final Map _classAdaptors = new HashMap();
+
+    // Prevent instantiation
+    private PropertyUtils()
+    {
+    }
+
+    /**
+     * Updates the property of the target object.
+     * 
+     * @param target
+     *            the object to update
+     * @param propertyName
+     *            the name of the property to be updated
+     * @param value
+     *            the value to be stored into the target object property
+     */
+    public static void write(Object target, String propertyName, Object value)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        a.write(target, propertyName, value);
+    }
+
+    /**
+     * An improved version of {@link #write(Object, String, Object)} where the value starts as a
+     * string and is converted to the correct property type before being assigned.
+     * 
+     * @since 1.1
+     */
+    public static void smartWrite(Object target, String propertyName, String value)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        a.smartWrite(target, propertyName, value);
+    }
+
+    /**
+     * Initializes the properties of an object from a string. The string is a comma-seperated
+     * sequence of property names and values. Property names are seperated from values be an equals
+     * sign. Spaces before and after the property names are trimmed.
+     * For boolean properties, the equals sign and value may be omitted (a value of true is
+     * assumed), or the property name may be prefixed with an exclamation point to indicated false
+     * value. Example: <code>validate,maxLength=10,displayName=User Id</code>.
+     * 
+     * @param target
+     *            the object to be configured
+     * @param initializer
+     *            the string encoding the properties and values to be configured in the target
+     *            object
+     * @since 1.1
+     */
+
+    public static void configureProperties(Object target, String initializer)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        a.configureProperties(target, initializer);
+    }
+
+    /**
+     * Returns true of the instance contains a writable property of the given type.
+     * 
+     * @param target
+     *            the object to inspect
+     * @param propertyName
+     *            the name of the property to check
+     */
+
+    public static boolean isWritable(Object target, String propertyName)
+    {
+        return getAdaptor(target).isWritable(propertyName);
+    }
+
+    public static boolean isReadable(Object target, String propertyName)
+    {
+        return getAdaptor(target).isReadable(propertyName);
+    }
+
+    /**
+     * Updates the property of the target object.
+     * 
+     * @param target
+     *            the object to update
+     * @param propertyName
+     *            the name of a property toread
+     */
+
+    public static Object read(Object target, String propertyName)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        return a.read(target, propertyName);
+    }
+
+    /**
+     * Returns the type of the named property.
+     * 
+     * @param target
+     *            the object to examine
+     * @param propertyName
+     *            the name of the property to check
+     */
+    public static Class getPropertyType(Object target, String propertyName)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        return a.getPropertyType(target, propertyName);
+    }
+
+    /**
+     * Returns the {@link PropertyAdaptor} for the given target object and property name.
+     * 
+     * @throws ApplicationRuntimeException
+     *             if the property does not exist.
+     */
+    public static PropertyAdaptor getPropertyAdaptor(Object target, String propertyName)
+    {
+        ClassAdaptor a = getAdaptor(target);
+
+        return a.getPropertyAdaptor(target, propertyName);
+    }
+
+    /**
+     * Returns an unordered List of the names of all readable properties of the target.
+     */
+    public static List getReadableProperties(Object target)
+    {
+        return getAdaptor(target).getReadableProperties();
+    }
+
+    /**
+     * Returns an unordered List of the names of all writable properties of the target.
+     */
+    public static List getWriteableProperties(Object target)
+    {
+        return getAdaptor(target).getWriteableProperties();
+    }
+
+    private static ClassAdaptor getAdaptor(Object target)
+    {
+        if (target == null)
+            throw new RuntimeException("");
+
+        Class targetClass = target.getClass();
+        Integer spinLock = new Integer(0);
+        synchronized (_classAdaptors)
+        {
+            ClassAdaptor result = (ClassAdaptor) _classAdaptors.get(targetClass);
+
+            if (result == null)
+            {
+                result = buildClassAdaptor(target, targetClass);
+                _classAdaptors.put(targetClass, result);
+            }
+
+            return result;
+        }
+    }
+
+    private static ClassAdaptor buildClassAdaptor(Object target, Class targetClass)
+    {
+        try
+        {
+            BeanInfo info = Introspector.getBeanInfo(targetClass);
+
+            return new ClassAdaptor(info.getPropertyDescriptors());
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException("");
+        }
+    }
+
+    /**
+     * Clears all cached information. Invokes {@link Introspector#flushCaches()}.
+     */
+    public static void clearCache()
+    {
+        synchronized (_classAdaptors)
+        {
+            _classAdaptors.clear();
+            Introspector.flushCaches();
+        }
+    }
+
+}
diff --git a/distributionBuildFiles/Windows XP.properties b/distributionBuildFiles/Windows XP.properties
new file mode 100644
index 0000000..2446841
--- /dev/null
+++ b/distributionBuildFiles/Windows XP.properties	
@@ -0,0 +1 @@
+windows=1
\ No newline at end of file
diff --git a/distributionBuildFiles/build.properties b/distributionBuildFiles/build.properties
new file mode 100644
index 0000000..0a11763
--- /dev/null
+++ b/distributionBuildFiles/build.properties
@@ -0,0 +1,2 @@
+openBracket=<
+closeBracket=>
\ No newline at end of file
diff --git a/distributionBuildFiles/build.xml b/distributionBuildFiles/build.xml
new file mode 100644
index 0000000..a20625a
--- /dev/null
+++ b/distributionBuildFiles/build.xml
@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="../" default="compile" name="Mesquite">
+	<target depends="packagedist,packagesrc" name="packagedistandsrc" description="packages source and binary distributions"/>
+	<target depends="compile" name="packagedist" description="Copies the appropriate files and creates distribution .tgz and .sit">
+		<copy todir="${mesquitefolder.dir}">
+			<fileset dir="${rsrcs.dir}">
+				<exclude name="${osxdirpath}" />
+				<exclude name="${osxdirpath500M}" />				
+				<exclude name="${osxdirpath1G}" />				
+				<exclude name="${osxdirpath2G}" />				
+				<exclude name="**/*.java"/>
+				<exclude name="**/*.html"/>
+			</fileset>
+			<fileset dir="${srcpath}">
+				<include name="**/*" />
+				<exclude name="**/*.java" />
+				<exclude name="**/Notes/" />
+				<exclude name="**/notes/" />				
+				<exclude name="**/a*Intro/*.html"/>
+			</fileset>
+		</copy>
+		<echo message="About to copy and replace html files"/>
+		<copy todir="${mesquitefolder.dir}">
+			<fileset dir="${rsrcs.dir}">
+				<include name="**/*.html"/>				
+			</fileset>
+			<fileset dir="${srcpath}">
+				<include name="**/a*Intro/*.html"/>
+			</fileset>
+			<filterset begintoken="${openBracket}" endtoken="${closeBracket}">
+				<filter token="protectedURL" value="${openBracket}"/>
+			</filterset>			
+			<filterset begintoken="${openBracket}/" endtoken="${closeBracket}">
+				<filter token="protectedURL" value="${closeBracket}"/>
+			</filterset>						
+		</copy>
+		<echo message="About to copy jars folder contents"/>
+		<copy todir="${mesquitefolder.dir}/jars">
+			<fileset dir="${jars.dir}">
+				<include name="**/*"/>	
+				<exclude name="AppleJavaExtensions.jar"/>
+				<exclude name="MRJToolkitStubs.zip"/>				
+			</fileset>
+		</copy>
+		
+		<copy todir="${mesquitefolder.dir}">
+			<fileset dir="${rsrcs.dir}">
+				<include name="${scriptfile}"/>
+			</fileset>
+		</copy>
+		<!-- package up the linux dist before we copy the mac stuff -->
+		<tar destfile="${linuxbin.tgz}" compression="gzip">	
+			<tarfileset dir="${release.dir}" mode="755"/>
+		</tar>
+		<!-- delete the script file before we package up the windows or mac distros -->
+		<delete>
+			<fileset dir="${mesquitefolder.dir}">
+				<include name="${scriptfile}"/>
+			</fileset>
+		</delete>
+		<delete>
+			<fileset dir="${mesquitefolder.dir}">
+				<include name="${macscriptfile}"/>
+			</fileset>
+		</delete>
+		
+		<antcall target="callwindowsinstaller"/>
+		
+		<copy todir="${mesquitefolder.dir}">
+			<fileset dir="${rsrcs.dir}">
+				<include name="${osxdirpath}"/>
+				<include name="${osxdirpath500M}"/>				
+				<include name="${osxdirpath1G}"/>				
+				<include name="${osxdirpath2G}"/>				
+			</fileset>
+		</copy>
+		
+		<exec os="Mac OS X,Linux" command="chmod 775 '${mesquitefolder.dir}/${osxdirname}/Contents/MacOS/Mesquite'"/>
+		<exec os="Mac OS X,Linux" command="chmod 775 '${mesquitefolder.dir}/${osxdir500Mname}/Contents/MacOS/Mesquite'"/>		
+		<exec os="Mac OS X,Linux" command="chmod 775 '${mesquitefolder.dir}/${osxdir1Gname}/Contents/MacOS/Mesquite'"/>		
+		<exec os="Mac OS X,Linux" command="chmod 775 '${mesquitefolder.dir}/${osxdir2Gname}/Contents/MacOS/Mesquite'"/>		
+		
+		<!-- create .dmg -->
+		<exec executable="hdiutil" failonerror="false" os="Mac OS X">
+			<arg value="create" />
+			<arg value="-srcfolder" />
+			<arg value="${release.dir}" />
+			<arg value="-fs" />
+			<arg value="HFS+" />
+			<arg value="${dmgbin}" />
+		</exec>
+		<!--
+		<exec executable="stuff" failifexecutionfails="false" failonerror="false" os="Mac OS X">
+			<arg line="-q -n='${sitbin}' -f=sit5 '${mesquitefolder.dir}'"/>
+		</exec>
+		-->
+	</target>
+	
+	<target depends="init" name="javadoc">
+		<javadoc destdir="${javadoc.dir}" doctitle="Mesquite Package Overview">
+			<packageset dir="${src.dir}">
+				<exclude name="**/corejava*"/>
+				<exclude name="**/edu*/**"/>				
+				<include name="**/mesquite/**/lib/**"/>
+				<include name="**/mesquite/lib/"/>				
+			</packageset>
+		</javadoc>
+	</target>	
+	<target depends="init" name="packagesrc">
+		<description>packages up the source distributions</description>
+
+		<mkdir dir="${dist.dir}"/>		
+		<mkdir dir="${workspacecontaining.dir}"/>
+		<mkdir dir="${workspacedist.dir}"/>
+		<mkdir dir="${workspaceproject.dir}"/>
+		<mkdir dir="${workspacejars.dir}"/>
+		<mkdir dir="${workspacesrc.dir}"/>
+		<mkdir dir="${workspacelibsrc.dir}"/>		
+		<copy todir="${workspaceproject.dir}">
+			<fileset dir=".">
+				<include name=".project"/>
+				<include name=".settings/"/>
+				<include name="${mesquitefoldername}"/>
+				<include name="${rsrcs}"/>
+			</fileset>
+		</copy>
+		<copy todir="${workspacejars.dir}">
+			<fileset dir="${jars.dir}">
+				<include name="*"/>
+			</fileset>
+		</copy>
+		<copy todir="${workspaceproject.dir}/${rsrcs}">
+			<fileset dir="${rsrcs}">
+				<include name="**/*"/>
+				<exclude name="**/*.java"/>
+			</fileset>
+		</copy>
+		<copy todir="${workspacesrc.dir}">
+			<fileset dir="${src.dir}">
+				<include name="**/*.java"/>
+				<include name="**/*.gif"/>
+			</fileset>
+			<filterset refid="mesquitetokens.filterset" />
+		</copy>
+		<copy todir="${workspacelibsrc.dir}">
+			<fileset dir="${librarysource.dir}">
+				<include name="**/*"/>
+			</fileset>
+		</copy>
+		<!-- ANDREW: EXCLUDED BECAUSE ABSENT copy file="${workspacedistclasspath}" tofile="${workspaceproject.dir}/.classpath"/ -->
+		<zip destfile="${windowssrc}">
+			<fileset dir="${workspacedist.dir}" />
+		</zip>
+		<tar destfile="${linuxsrc}" compression="gzip" basedir="${workspacedist.dir}" />
+	</target>	
+		
+	<target name="init"> 
+		<property environment="env" />
+		<property name="dist.dir" location="../dist" />
+		<property name="mesquite.version" value="2.75" />
+		<property name="release.dir" location="${dist.dir}/Mesquite ${mesquite.version}" />
+		<property name="mesquitefoldername" value="Mesquite_Folder"/>
+		<property name="mesquitefolder.dir" location="${release.dir}/${mesquitefoldername}" />
+		<property name="srcpath" value="Source" />
+		<property name="src.dir" location="${srcpath}" />
+		<property name="mesquitesrccontainingdir" location="${dist.dir}/Source" />
+		<property name="mesquitesrc" location="${mesquitesrccontainingdir}/mesquiteSource" />
+		<property name="rsrcs" value="Resources"/> 
+		<property name="rsrcs.dir" location="${rsrcs}" />
+		<property name="linuxbin.tgz" location="${dist.dir}/mesquite.tgz" />
+		<property name="dmgbin" location="${dist.dir}/mesquite.dmg" />
+		<property name="sitbin" location="${dist.dir}/mesquite.sit" />
+		<property name="linuxsrc" location="${dist.dir}/mesquiteSource.tgz" />
+		<property name="windowssrc" location="${dist.dir}/mesquiteSource.zip" />
+		<property name="macsrc" location="${dist.dir}/mesquiteSource.sit" />
+		
+		<property name="buildfiles.dir" location="distributionBuildFiles"/>
+
+		<property name="workspacecontaining.dir" location="${dist.dir}/mesquiteworkspacedist"/>
+		<property name="workspacedist.dir" location="${workspacecontaining.dir}/MesquiteWorkspace/" />
+		<property name="workspaceproject.dir" location="${workspacedist.dir}/MesquiteProject/" />
+		<property name="workspacejars.dir" location="${workspaceproject.dir}/jars"/>
+		<property name="workspacesrc.dir" location="${workspaceproject.dir}/Source"/>
+		<property name="workspacelibsrc.dir" location="${workspaceproject.dir}/LibrarySource"/>
+		<property name="workspacedistclasspath" location="${buildfiles.dir}/.classpath.dist"/>
+		
+		<property name="installer.dir" location="${basedir}/../mesquiteinstaller"/>     
+		<property name="librarysource.dir" location="LibrarySource"/>
+
+		<!-- assorted mac folders and files that need to be excluded for linux builds -->
+		<property name="osxdirname" value="Mesquite.app" />		
+		<property name="osxdirpath" value="**/${osxdirname}/" />
+		<property name="osxdir500Mname" value="Mesquite (500MB).app" />				
+		<property name="osxdirpath500M" value="**/${osxdir500Mname}/" />		
+		<property name="osxdir1Gname" value="Mesquite (1GB).app" />				
+		<property name="osxdirpath1G" value="**/${osxdir1Gname}/" />		
+		<property name="osxdir2Gname" value="Mesquite (2GB).app" />				
+		<property name="osxdirpath2G" value="**/${osxdir2Gname}/" />		
+
+		<!-- server destination locations -->
+		<property file="${buildfiles.dir}/serverinfo.properties" />
+		<property name="hostprefix" value="${username}:${password}@${host}:" />
+		<!-- The directory where the binary distributions are stored -->
+		<property name="bininstalldir" value="${hostprefix}/mesquite_install_folder/" />
+		<!-- The directory where the source distributions are stored -->
+		<property name="srcinstalldir" value="${hostprefix}/mesquite_source_folder/" />
+		<!-- The path to Mesquite_Folder on the server -->
+		<property name="mesquitefolderinstalldir" value="/Mesquite_Folder/" />
+
+
+		<property name="sftpjar" value="maverick-ant.jar"/>
+		<property name="jars.dir" location="jars"/>
+		
+		<property name="javadoc.dir" location="${dist.dir}/javadoc"/>
+		<property name="scriptfile" value="run_mesquite.sh"/>
+		<property name="macscriptfile" value="Run_Mesquite_OSX.command"/>
+		
+		<property file="${buildfiles.dir}/${os.name}.properties"/>
+		<property file="${buildfiles.dir}/build.properties"/>
+		
+		<path id="compile.classpath" >
+			<fileset dir="${jars.dir}">
+				<include name="*.jar"/>
+				<include name="*.zip"/>
+			</fileset>
+		</path>
+		<tstamp>
+			<format property="year" pattern="yyyy" />
+		</tstamp>
+		<filterset id="mesquitetokens.filterset">
+			<filter token="MESQUITE_RELEASE_VERSION" value="${mesquite.version}" />
+			<!-- is this needed, or is the release date always the year? -->
+			<filter token="MESQUITE_RELEASE_DATE" value="${TODAY}" />
+			<filter token="MESQUITE_RELEASE_YEAR" value="${year}" />
+		</filterset>
+	</target>
+
+	<target depends="init" name="clean">
+		<description>Gets rid of all generated build files</description>
+		<delete>
+			<fileset dir="${src.dir}">
+				<include name="**/*.class" />
+			</fileset>
+		</delete>
+		<delete dir="${dist.dir}" />
+		<delete dir="${workspacecontaining.dir}" />
+		<delete file="${linuxbin.tgz}" />
+		<delete file="${dmgbin}" />
+		<delete file="${sitbin}" />
+		<delete file="${linuxsrc}" />
+		<delete file="${windowssrc}" />
+		<delete file="${macsrc}" />
+	</target>
+	<target depends="init,clean" name="compile">
+		<description>Compiles the mesquite source and sends the output to the dist directory</description>
+		<mkdir dir="${dist.dir}" />
+		<mkdir dir="${mesquitefolder.dir}" />
+		<mkdir dir="${mesquitefolder.dir}/jars"/>
+		<javac debug="false" destdir="${mesquitefolder.dir}" srcdir="${srcpath}" target="1.4" source="1.4" nowarn="true" memorymaximumsize="500m" fork="true" memoryinitialsize="100m">
+			<classpath refid="compile.classpath" />
+		</javac>
+	</target>
+	<target name="callwindowsinstaller"  if="windows">
+		<description>
+			Calls the windows installer build script.  This only executes if the machine executing the build
+			is running windows.
+		</description>
+        <!-- <ant dir="${installer.dir}" target="makensis" inheritAll="true" /> -->
+		<!-- after consulting the documentation for Ant, I found that inheritAll is true by default -->
+		<ant dir="${installer.dir}" target="makensis" />
+	</target>
+	<!--
+	<target depends="packagedist,packagesrc" name="deployfiles">
+		<description>Sends all of the generated files up to the server</description>		
+		<scp file="${linuxbin.tgz}" todir="${bininstalldir}" trust="true" failonerror="false"/>
+		<scp file="${sitbin}" todir="${bininstalldir}" trust="true" failonerror="false"/>
+		<scp file="${dmgbin}" todir="${bininstalldir}" trust="true" failonerror="false"/>
+		<scp file="${macsrc}" todir="${srcinstalldir}" trust="true" failonerror="false"/>
+		<scp file="${windowssrc}" todir="${srcinstalldir}" trust="true" failonerror="false"/>
+		<scp file="${linuxsrc}" todir="${srcinstalldir}" trust="true" failonerror="false"/>
+		<taskdef name="ssh" classname="com.sshtools.ant.Ssh" classpath="${buildfiles.dir}/${sftpjar}" />
+		<ssh host="${host}" username="${username}" password="${password}">
+			<exec cmd="rm -rf ${mesquitefolderinstalldir}" />
+			<exec cmd="mkdir ${mesquitefolderinstalldir}" />
+			<sftp action="put" remotedir="${mesquitefolderinstalldir}">
+				<fileset dir="${mesquitefolder.dir}" />
+			</sftp>
+		</ssh>
+	</target>
+	-->
+</project>
\ No newline at end of file
diff --git a/distributionBuildFiles/buildInstructions.html b/distributionBuildFiles/buildInstructions.html
new file mode 100644
index 0000000..283b42d
--- /dev/null
+++ b/distributionBuildFiles/buildInstructions.html
@@ -0,0 +1,188 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Mesquite Build Instructions</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body>
+              <h2><font face="Trebuchet MS">Building a Mesquite Release with Ant and Eclipse</font></h2>
+              
+<p><font face="Trebuchet MS">This document discusses launching and editing <a href="http://ant.apache.org">ant</a> 
+  build files from within <a href="http://www.eclipse.org">Eclipse</a>. An <a href="http://help.eclipse.org/help30/index.jsp?topic=/org.eclipse.platform.doc.user/concepts/concepts-antsupport.htm">overview</a> 
+  of doing so can be found on the Eclipse website. </font></p>
+  <!--
+              <hr>
+              <h3><font face="Trebuchet MS">Edit the server deployment information (optional, only if using the automated file upload)</font></h3>
+              <p>The build script must be configured so it knows where to upload generated build files.  To
+                 configure server connection settings, follow these steps:
+                 <ol>
+                     <li>In the root of Mesquite Project, there is a directory called <em>buildfiles</em>.
+				 In this directory, there is a file called <em>serverinfo.properties.sample</em>.
+				 Copy this file and paste it back into the <em>buildfiles</em> directory, but call it 
+              	 <em>serverinfo.properties</em>.</li>
+                     <li>
+						Edit the newly created <em>serverinfo.properties</em>, replacing the lines:
+                        <pre>
+username=
+password=
+host=
+                        </pre> with the username, password, and hostname where the generated build files
+                        should be uploaded.
+					</li>
+                     <li>Edit the <em>build.xml</em> file and edit the following lines by replacing 
+                     	the current path locations with their desired locations on the server:
+                     <pre>
+		<!-- The directory where the binary distributions are stored -->
+		<property name="bininstalldir" value="${hostprefix}/mesquite_install_folder/" />
+		<!-- The directory where the source distributions are stored -->
+		<property name="srcinstalldir" value="${hostprefix}/mesquite_source_folder/" />
+		<!-- The path to Mesquite_Folder on the server (for documentation) -->
+		<property name="mesquitefolderinstalldir" value="/Mesquite_Folder/" />                         
+                     </pre>
+					 Be careful not to replace or edit the <em>${hostprefix}</em> part, as this
+                     is the server identification that ant needs to upload the files.
+                     For example, if you want the Mesquite install packages to go to a directory
+                     called <em>/home/user/mesquiteinstalls</em> you would have a line that looked like
+                     this:
+                     <pre>
+		<!-- The directory where the binary distributions are stored -->
+		<property name="bininstalldir" value="${hostprefix}/home/user/mesquiteinstalls/" />                         
+                     </pre>
+                 </ol>
+              </p>
+             -->
+             <h3>Targets Quick-Reference</h3>
+             <p>To execute the following commands, one needs only check the <em>packagedistandsrc</em>
+             	checkbox:
+<ol>
+             	<li><em>init, clean, compile, package source and dist</em></li>
+             	<li><em>init, clean, compile, build windowsinstaller</em> (needs to be run on a windows machine)</li>
+             	<li><em>init, clean, compile, package source and dist, build windowsinstaller</em> (needs to be run on a windows machine)</li>
+</ol>
+             </p>
+             <p>To build the javadocs, check the <em>javadoc</em> checkbox.</p>
+              <h3>Installing NSIS then checking out and building the Windows installer project (optional, only on Windows)</h3>
+              <p>In order to build the Windows installation file, the 
+                 <a href="http://nsis.sourceforge.net/Main_Page">Nullsoft Install System (NSIS)</a> must
+                 be installed on the machine prior to launching ant.  <em>makensis.exe</em> must also
+                 be located in a directory on the Windows PATH.  Instructions for downloading and installing
+                 NSIS can be found on the <a href="http://nsis.sourceforge.net/Download">NSIS website</a>.</p>
+              <p>Once NSIS is installed, you will want to check out the Windows installer project, which is
+              	located here: http://svn.mesquiteproject.org:8080/trunk/mesquiteinstaller/  The build script
+              	expects this to be in the same workspace as the "Mesquite Project" that is being built.</p>
+              <p>After NSIS is installed and the Mesquite Installer project is checked out, the Mesquite Installer
+              	can be built by running the <em>packagedist</em>  (or <em>packagedistandsrc</em>) target in the main Mesquite build file.  This will
+              	create a file in the <em>dist</em> directory called MesquiteInstaller.exe</p>
+			  <h3><font face="Trebuchet MS">Establishing an Ant Launch Configuration and Running the Script</font></h3>
+              <p>In the root of Mesquite Project, there is a directory called <em>buildfiles</em> which
+                contains a file called <em>build.xml</em>.  
+				  This is the ant build script that specifies how the Mesquite
+                release build will proceed. In order  to launch this script from
+                within Eclipse, you need to create one or more Eclipse launch
+                
+				  configurations.  Each Eclipse launch configuration will run
+                one or more ant targets.</p>
+				<p>For example, you might want to test the build process without uploading the files while you're still developing, 
+					and then later have the build script upload the files when you're confident they are ready for release.
+					In this scenario I might have a testing launch configuration called <em>Mesquite package distribution</em> that 
+					runs the <em>packagedistandsrc</em> target, and another called <em>Mesquite deploy files</em> that runs 
+					the <em>deployfiles</em> target when I'm ready to go live.</p>
+				<p>
+				  To establish an Eclipse launch configuration for the build file, follow these steps:
+				<ol>
+				  <li>In the Package Explorer view, right-click the <em>build.xml</em> file.</li>
+				  <li>From the file's pop-up menu, select <b>Run As > Ant Build...</b>. The launch configuration
+				  	dialog opens.</li>
+                  <li id="step3">Name the launch configuration something easy to remember, for instance 
+                      <em>Mesquite package distribution</em> or <em>Mesquite deploy files</em>.</li>
+				  <li>Select the desired targets you wish to execute from the <b>Targets</b> tab.
+				  	(<em>packagedistandsrc</em> creates the binary and source distributions; <em>packageddist</em> that
+				  	does the same but only for the binary distribution.
+				  	For information on the the other targets please see <a href="#targetreference">the
+				  	reference</a> at the bottom of this page.)</li>
+					  <!--
+				  <li><h4>(Optional -- only necessary if calling the <em>deployfiles</em> target in this configuration.)</h4> Click the <b>Classpath</b> tab.  
+					  Select <b>Additional Tasks & Support</b> and click 
+                  	  <b>Add JARs</b>.  Select a file called <em>jsch-0.1.28.jar</em> located under the <em>buildfiles</em>
+                        folder at the root of Mesquite Project.</li>
+                        -->
+                  <li>Make sure to save your configuration by clicking the <b>Apply</b> button in the 
+                  	bottom-right corner of the screen.</li>
+				  <li>You may now launch the build script by clicking <b>Run</b>.</li>
+				  <li>To launch this script in the future, follow these steps:
+				  	<ol>
+	                  <li>From the <b>Run</b> menu, select the <b>External Tools</b> menu, then select
+	              the <b>External Tools</b> item in that menu to bring up the External Tools dialog.</li>
+	                  <li>In the left-side panel, select the launch configuration you created earlier 
+	                      (it should be located under the <b>Ant Build</b> menu item).</li>
+	                  <li>Click <b>Run</b></li>						  
+				    </ol>
+				  </li>
+				  <li>To create another launch configuration, follow these steps:
+				  	<ol>
+						<li>From the <b>Run</b> menu, select the <b>External Tools</b> menu, then select
+	              		the <b>External Tools</b> item in that menu to bring up the External Tools dialog.</li>
+						<li>Select <b>Ant build</b> in the left-panel then click the <b>New</b> button
+							at the bottom of the screen.</li>
+						<li>Go to <a href="#step3">Step 3</a> in the previous launch configuration instructions to complete your
+							new launch configuration.</li>
+				    </ol>
+				  </li>
+				</ol>
+              </p>
+			  <h3>Generated Files</h3>
+              <p>There are number of files generated by the build script.  The generated files are located
+              in a directory called <em>dist</em> that is one-level above that of Mesquite Project.
+              A short explanation of
+              each follows:
+              <ul>
+                  <li><em>mesquite.dmg</em> -- A .dmg installation file for Max OS X (only produced if the script is run on Mac OS X)</li>
+                  <li><em>mesquite.tgz</em> -- A gzipped Mesquite binary suitable for linux or other unix distributions</li>                  
+                  <li><em>MesquiteInstaller.exe</em> -- The Windows setup file (only produced if the script is run on Windows)</li>
+                  <!--
+                  <li><em>mesquite.sit</em> -- (DANNY'S NOTE -- this currently is commented out because I don't have stuff installed, easy to re-establish if desired, though) A binary installation file for Mac OS X.
+                  -->
+                  <li><em>mesquiteSource.tgz</em> -- A gzipped copy of Mesquite's source that is suitable for importing within Eclipse</li>
+                  <li><em>mesquiteSource.zip</em> -- A zipped copy of Mesquite's source that is suitable for importing within Eclipse</li>                  
+                  <!--
+                  <li><em>mesquiteSource.sit</em> -- (DANNY'S NOTE -- same as above about the .sit) A StuffIt zipped copy of Mesquite's source that is suitable for importing within Eclipse</li>
+                  -->
+              </ul></p>
+              <h3>Token substitution</h3>
+              <p>During the build process, a number of documentation files are copied.  During this copying,
+              certain tokens are replaced in order to make sure that the documentation matches the current
+              Mesquite version number, release date, and copyright date.  These tokens are:
+              <ul>
+                  <li><em>@MESQUITE_RELEASE_VERSION@</em> -- replaced with the value of mesquite.version as defined in this 
+                      line of the build file:
+                  <pre>
+		<property name="mesquite.version" value="1.1" />                      
+                  </pre></li>
+                  <li><em>@MESQUITE_RELEASE_DATE@</em> -- replaced with the release date (the date the script is run) in the format <em>May 8, 2006</em> (MMMM dd yyy)</li>
+                  <li><em>@MESQUITE_RELEASE_YEAR@</em> -- replaced with the release year (of the date the script is run) in the format <em>2006</em> (yyyy)</li>
+              </ul>
+              In addition, any html files will have
+              the following token substitutions in order to make local 
+              links into or out of the Mesquite docs directory work:
+              <ul>
+                  <li><protectedURL> -- replaced with <</li>
+                  <li></protectedURL> -- replaced with ></li>
+              </ul>
+              </p>
+              <h3 id="targetreference">Build target reference</h3>
+              <p>Ant has its executable blocks set up in pieces called targets.  The following are the targets
+                  in the Mesquite build file:
+<ul>
+    <li><em>init</em> -- The initialization point for the build file.  It establishes build variables like directory locations, etc.</li>
+    <li><em>clean</em> -- Gets rid of any build-script related artifacts (i.e. class files, zip files, .dmg etc.)</li>
+    <li><em>compile</em> -- Invokes javac on all the source files.</li>
+    <li><em>packagedist</em> -- Packages the binary distribution files</li>
+    <li><em>callwindowsinstaller</em> -- Calls the Windows installer build script.  This only executes on Windows.</li>
+    <li><em>packagesrc</em> -- Builds a source distribution directory and includes a .classpath which Eclipse will read.
+    <li><em>packagedistandsrc</em> -- Calls <em>packagedist</em> and <em>packagesrc</em>.  This is good for testing purposes.</li>						 
+</ul>
+              </p>
+</body>
+</html>
+
diff --git a/distributionBuildFiles/serverinfo.properties.sample b/distributionBuildFiles/serverinfo.properties.sample
new file mode 100644
index 0000000..a703241
--- /dev/null
+++ b/distributionBuildFiles/serverinfo.properties.sample
@@ -0,0 +1,5 @@
+username=
+password=
+host=
+openBracket=<
+closeBracket=>
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/mesquite.git



More information about the debian-med-commit mailing list